summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitattributes1
-rw-r--r--.gitignore3
-rw-r--r--.travis.yml89
-rw-r--r--AUTHORS.md10
-rw-r--r--CONTRIBUTING.md2
-rw-r--r--DONORS.md87
-rw-r--r--LICENSE.txt2
-rw-r--r--README.md2
-rw-r--r--SConstruct44
-rw-r--r--compat.py4
-rw-r--r--core/array.cpp54
-rw-r--r--core/array.h8
-rw-r--r--core/bind/core_bind.cpp32
-rw-r--r--core/bind/core_bind.h7
-rw-r--r--core/class_db.cpp29
-rw-r--r--core/class_db.h9
-rw-r--r--core/command_queue_mt.h46
-rw-r--r--core/dictionary.cpp103
-rw-r--r--core/engine.cpp33
-rw-r--r--core/engine.h19
-rw-r--r--core/error_macros.cpp7
-rw-r--r--core/error_macros.h41
-rw-r--r--core/global_constants.cpp154
-rw-r--r--core/helper/math_fieldwise.cpp8
-rw-r--r--core/image.cpp25
-rw-r--r--core/image.h1
-rw-r--r--core/io/SCsub1
-rw-r--r--core/io/compression.cpp20
-rw-r--r--core/io/compression.h2
-rw-r--r--core/io/config_file.cpp20
-rw-r--r--core/io/config_file.h3
-rw-r--r--core/io/file_access_encrypted.cpp4
-rw-r--r--core/io/http_client.cpp147
-rw-r--r--core/io/http_client.h14
-rw-r--r--core/io/logger.cpp22
-rw-r--r--core/io/logger.h2
-rw-r--r--core/io/marshalls.cpp15
-rw-r--r--core/io/resource_format_binary.cpp30
-rw-r--r--core/make_binders.py2
-rw-r--r--core/map.h1
-rw-r--r--core/math/a_star.cpp73
-rw-r--r--core/math/a_star.h7
-rw-r--r--core/math/aabb.cpp (renamed from core/math/rect3.cpp)52
-rw-r--r--core/math/aabb.h (renamed from core/math/rect3.h)54
-rw-r--r--core/math/bsp_tree.cpp6
-rw-r--r--core/math/bsp_tree.h10
-rw-r--r--core/math/camera_matrix.cpp2
-rw-r--r--core/math/camera_matrix.h2
-rw-r--r--core/math/face3.cpp4
-rw-r--r--core/math/face3.h14
-rw-r--r--core/math/geometry.cpp4
-rw-r--r--core/math/math_funcs.cpp15
-rw-r--r--core/math/math_funcs.h21
-rw-r--r--core/math/matrix3.cpp38
-rw-r--r--core/math/matrix3.h15
-rw-r--r--core/math/octree.h38
-rw-r--r--core/math/quick_hull.cpp2
-rw-r--r--core/math/quick_hull.h2
-rw-r--r--core/math/transform.h14
-rw-r--r--core/math/triangle_mesh.cpp4
-rw-r--r--core/math/triangle_mesh.h4
-rw-r--r--core/method_ptrcall.h2
-rw-r--r--core/ordered_hash_map.h42
-rw-r--r--core/os/dir_access.cpp101
-rw-r--r--core/os/dir_access.h4
-rw-r--r--core/os/file_access.cpp2
-rw-r--r--core/os/input.cpp1
-rw-r--r--core/os/input_event.cpp92
-rw-r--r--core/os/input_event.h48
-rw-r--r--core/os/keyboard.cpp22
-rw-r--r--core/os/main_loop.cpp1
-rw-r--r--core/os/memory.cpp20
-rw-r--r--core/os/memory.h8
-rw-r--r--core/os/os.cpp102
-rw-r--r--core/os/os.h31
-rw-r--r--core/packed_data_container.cpp2
-rw-r--r--core/print_string.cpp20
-rw-r--r--core/print_string.h3
-rw-r--r--core/project_settings.cpp93
-rw-r--r--core/project_settings.h19
-rw-r--r--core/register_core_types.cpp45
-rw-r--r--core/script_debugger_remote.cpp174
-rw-r--r--core/script_debugger_remote.h2
-rw-r--r--core/script_language.cpp1
-rw-r--r--core/script_language.h10
-rw-r--r--core/set.h1
-rw-r--r--core/string_db.h3
-rw-r--r--core/translation.cpp149
-rw-r--r--core/translation.h7
-rw-r--r--core/type_info.h2
-rw-r--r--core/typedefs.h4
-rw-r--r--core/ustring.cpp77
-rw-r--r--core/ustring.h7
-rw-r--r--core/variant.cpp59
-rw-r--r--core/variant.h18
-rw-r--r--core/variant_call.cpp663
-rw-r--r--core/variant_op.cpp68
-rw-r--r--core/variant_parser.cpp10
-rw-r--r--core/version.h6
-rw-r--r--doc/Makefile2
-rw-r--r--doc/classes/@GDScript.xml89
-rw-r--r--doc/classes/@GlobalScope.xml (renamed from doc/classes/@Global Scope.xml)300
-rw-r--r--doc/classes/@NativeScript.xml2
-rw-r--r--doc/classes/@VisualScript.xml2
-rw-r--r--doc/classes/AABB.xml (renamed from doc/classes/Rect3.xml)65
-rw-r--r--doc/classes/ARVRAnchor.xml3
-rw-r--r--doc/classes/ARVRCamera.xml2
-rw-r--r--doc/classes/ARVRController.xml20
-rw-r--r--doc/classes/ARVRInterface.xml8
-rw-r--r--doc/classes/ARVROrigin.xml4
-rw-r--r--doc/classes/ARVRPositionalTracker.xml24
-rw-r--r--doc/classes/ARVRScriptInterface.xml118
-rw-r--r--doc/classes/ARVRServer.xml38
-rw-r--r--doc/classes/AStar.xml49
-rw-r--r--doc/classes/AcceptDialog.xml4
-rw-r--r--doc/classes/AnimatedSprite.xml2
-rw-r--r--doc/classes/AnimatedSprite3D.xml2
-rw-r--r--doc/classes/Animation.xml2
-rw-r--r--doc/classes/AnimationPlayer.xml8
-rw-r--r--doc/classes/AnimationTreePlayer.xml4
-rw-r--r--doc/classes/Area.xml6
-rw-r--r--doc/classes/Area2D.xml6
-rw-r--r--doc/classes/Array.xml43
-rw-r--r--doc/classes/ArrayMesh.xml20
-rw-r--r--doc/classes/AtlasTexture.xml18
-rw-r--r--doc/classes/AudioBusLayout.xml4
-rw-r--r--doc/classes/AudioEffect.xml2
-rw-r--r--doc/classes/AudioEffectAmplify.xml2
-rw-r--r--doc/classes/AudioEffectBandLimitFilter.xml4
-rw-r--r--doc/classes/AudioEffectBandPassFilter.xml4
-rw-r--r--doc/classes/AudioEffectChorus.xml2
-rw-r--r--doc/classes/AudioEffectCompressor.xml2
-rw-r--r--doc/classes/AudioEffectDelay.xml2
-rw-r--r--doc/classes/AudioEffectDistortion.xml4
-rw-r--r--doc/classes/AudioEffectEQ.xml2
-rw-r--r--doc/classes/AudioEffectEQ10.xml2
-rw-r--r--doc/classes/AudioEffectEQ21.xml2
-rw-r--r--doc/classes/AudioEffectEQ6.xml2
-rw-r--r--doc/classes/AudioEffectFilter.xml9
-rw-r--r--doc/classes/AudioEffectHighPassFilter.xml4
-rw-r--r--doc/classes/AudioEffectHighShelfFilter.xml2
-rw-r--r--doc/classes/AudioEffectLimiter.xml2
-rw-r--r--doc/classes/AudioEffectLowPassFilter.xml4
-rw-r--r--doc/classes/AudioEffectLowShelfFilter.xml2
-rw-r--r--doc/classes/AudioEffectNotchFilter.xml4
-rw-r--r--doc/classes/AudioEffectPanner.xml2
-rw-r--r--doc/classes/AudioEffectPhaser.xml2
-rw-r--r--doc/classes/AudioEffectPitchShift.xml2
-rw-r--r--doc/classes/AudioEffectReverb.xml4
-rw-r--r--doc/classes/AudioEffectStereoEnhance.xml2
-rw-r--r--doc/classes/AudioServer.xml39
-rw-r--r--doc/classes/AudioStream.xml2
-rw-r--r--doc/classes/AudioStreamPlayback.xml4
-rw-r--r--doc/classes/AudioStreamPlayer.xml12
-rw-r--r--doc/classes/AudioStreamPlayer2D.xml7
-rw-r--r--doc/classes/AudioStreamPlayer3D.xml15
-rw-r--r--doc/classes/AudioStreamRandomPitch.xml2
-rw-r--r--doc/classes/AudioStreamSample.xml2
-rw-r--r--doc/classes/BackBufferCopy.xml2
-rw-r--r--doc/classes/BaseButton.xml13
-rw-r--r--doc/classes/Basis.xml2
-rw-r--r--doc/classes/BitMap.xml5
-rw-r--r--doc/classes/BitmapFont.xml33
-rw-r--r--doc/classes/BoneAttachment.xml2
-rw-r--r--doc/classes/BoxContainer.xml2
-rw-r--r--doc/classes/BoxShape.xml2
-rw-r--r--doc/classes/Button.xml2
-rw-r--r--doc/classes/ButtonGroup.xml2
-rw-r--r--doc/classes/Camera.xml4
-rw-r--r--doc/classes/Camera2D.xml19
-rw-r--r--doc/classes/CanvasItem.xml12
-rw-r--r--doc/classes/CanvasItemMaterial.xml2
-rw-r--r--doc/classes/CanvasLayer.xml10
-rw-r--r--doc/classes/CanvasModulate.xml7
-rw-r--r--doc/classes/CapsuleMesh.xml2
-rw-r--r--doc/classes/CapsuleShape.xml2
-rw-r--r--doc/classes/CapsuleShape2D.xml10
-rw-r--r--doc/classes/CenterContainer.xml2
-rw-r--r--doc/classes/CheckBox.xml4
-rw-r--r--doc/classes/CheckButton.xml2
-rw-r--r--doc/classes/CircleShape2D.xml2
-rw-r--r--doc/classes/ClassDB.xml2
-rw-r--r--doc/classes/CollisionObject.xml4
-rw-r--r--doc/classes/CollisionObject2D.xml4
-rw-r--r--doc/classes/CollisionPolygon.xml2
-rw-r--r--doc/classes/CollisionPolygon2D.xml2
-rw-r--r--doc/classes/CollisionShape.xml2
-rw-r--r--doc/classes/CollisionShape2D.xml2
-rw-r--r--doc/classes/Color.xml2
-rw-r--r--doc/classes/ColorPicker.xml4
-rw-r--r--doc/classes/ColorPickerButton.xml4
-rw-r--r--doc/classes/ColorRect.xml6
-rw-r--r--doc/classes/ConcavePolygonShape.xml2
-rw-r--r--doc/classes/ConcavePolygonShape2D.xml4
-rw-r--r--doc/classes/ConeTwistJoint.xml27
-rw-r--r--doc/classes/ConfigFile.xml33
-rw-r--r--doc/classes/ConfirmationDialog.xml2
-rw-r--r--doc/classes/Container.xml4
-rw-r--r--doc/classes/Control.xml83
-rw-r--r--doc/classes/ConvexPolygonShape.xml7
-rw-r--r--doc/classes/ConvexPolygonShape2D.xml9
-rw-r--r--doc/classes/CubeMap.xml16
-rw-r--r--doc/classes/CubeMesh.xml2
-rw-r--r--doc/classes/Curve.xml4
-rw-r--r--doc/classes/Curve2D.xml5
-rw-r--r--doc/classes/Curve3D.xml2
-rw-r--r--doc/classes/CurveTexture.xml2
-rw-r--r--doc/classes/CylinderMesh.xml2
-rw-r--r--doc/classes/DampedSpringJoint2D.xml6
-rw-r--r--doc/classes/Dictionary.xml6
-rw-r--r--doc/classes/DirectionalLight.xml2
-rw-r--r--doc/classes/Directory.xml17
-rw-r--r--doc/classes/DynamicFont.xml30
-rw-r--r--doc/classes/DynamicFontData.xml7
-rw-r--r--doc/classes/EditorExportPlugin.xml2
-rw-r--r--doc/classes/EditorFileDialog.xml2
-rw-r--r--doc/classes/EditorFileSystem.xml2
-rw-r--r--doc/classes/EditorFileSystemDirectory.xml2
-rw-r--r--doc/classes/EditorImportPlugin.xml8
-rw-r--r--doc/classes/EditorInterface.xml24
-rw-r--r--doc/classes/EditorPlugin.xml4
-rw-r--r--doc/classes/EditorResourceConversionPlugin.xml2
-rw-r--r--doc/classes/EditorResourcePreview.xml4
-rw-r--r--doc/classes/EditorResourcePreviewGenerator.xml2
-rw-r--r--doc/classes/EditorScript.xml18
-rw-r--r--doc/classes/EditorSelection.xml4
-rw-r--r--doc/classes/EditorSettings.xml60
-rw-r--r--doc/classes/EditorSpatialGizmo.xml6
-rw-r--r--doc/classes/EncodedObjectAsID.xml2
-rw-r--r--doc/classes/Engine.xml41
-rw-r--r--doc/classes/Environment.xml72
-rw-r--r--doc/classes/File.xml100
-rw-r--r--doc/classes/FileDialog.xml8
-rw-r--r--doc/classes/Font.xml2
-rw-r--r--doc/classes/FuncRef.xml9
-rw-r--r--doc/classes/GDNativeLibrary.xml51
-rw-r--r--doc/classes/GIProbe.xml4
-rw-r--r--doc/classes/GIProbeData.xml8
-rw-r--r--doc/classes/Generic6DOFJoint.xml75
-rw-r--r--doc/classes/Geometry.xml41
-rw-r--r--doc/classes/GeometryInstance.xml2
-rw-r--r--doc/classes/Gradient.xml6
-rw-r--r--doc/classes/GradientTexture.xml2
-rw-r--r--doc/classes/GraphEdit.xml6
-rw-r--r--doc/classes/GraphNode.xml2
-rw-r--r--doc/classes/GridContainer.xml3
-rw-r--r--doc/classes/GrooveJoint2D.xml4
-rw-r--r--doc/classes/HBoxContainer.xml2
-rw-r--r--doc/classes/HScrollBar.xml2
-rw-r--r--doc/classes/HSeparator.xml2
-rw-r--r--doc/classes/HSlider.xml4
-rw-r--r--doc/classes/HSplitContainer.xml2
-rw-r--r--doc/classes/HTTPClient.xml26
-rw-r--r--doc/classes/HTTPRequest.xml4
-rw-r--r--doc/classes/HingeJoint.xml24
-rw-r--r--doc/classes/IP.xml2
-rw-r--r--doc/classes/IP_Unix.xml2
-rw-r--r--doc/classes/Image.xml69
-rw-r--r--doc/classes/ImageTexture.xml23
-rw-r--r--doc/classes/ImmediateGeometry.xml21
-rw-r--r--doc/classes/Input.xml32
-rw-r--r--doc/classes/InputDefault.xml2
-rw-r--r--doc/classes/InputEvent.xml22
-rw-r--r--doc/classes/InputEventAction.xml6
-rw-r--r--doc/classes/InputEventJoypadButton.xml12
-rw-r--r--doc/classes/InputEventJoypadMotion.xml10
-rw-r--r--doc/classes/InputEventKey.xml12
-rw-r--r--doc/classes/InputEventMouse.xml10
-rw-r--r--doc/classes/InputEventMouseButton.xml11
-rw-r--r--doc/classes/InputEventMouseMotion.xml8
-rw-r--r--doc/classes/InputEventScreenDrag.xml11
-rw-r--r--doc/classes/InputEventScreenTouch.xml11
-rw-r--r--doc/classes/InputEventWithModifiers.xml6
-rw-r--r--doc/classes/InputMap.xml26
-rw-r--r--doc/classes/InstancePlaceholder.xml2
-rw-r--r--doc/classes/InterpolatedCamera.xml2
-rw-r--r--doc/classes/ItemList.xml6
-rw-r--r--doc/classes/JSON.xml2
-rw-r--r--doc/classes/JSONParseResult.xml10
-rw-r--r--doc/classes/JavaScript.xml30
-rw-r--r--doc/classes/Joint.xml8
-rw-r--r--doc/classes/Joint2D.xml6
-rw-r--r--doc/classes/KinematicBody.xml8
-rw-r--r--doc/classes/KinematicBody2D.xml10
-rw-r--r--doc/classes/KinematicCollision.xml2
-rw-r--r--doc/classes/KinematicCollision2D.xml2
-rw-r--r--doc/classes/Label.xml25
-rw-r--r--doc/classes/LargeTexture.xml24
-rw-r--r--doc/classes/Light.xml4
-rw-r--r--doc/classes/Light2D.xml16
-rw-r--r--doc/classes/LightOccluder2D.xml2
-rw-r--r--doc/classes/Line2D.xml28
-rw-r--r--doc/classes/LineEdit.xml103
-rw-r--r--doc/classes/LineShape2D.xml2
-rw-r--r--doc/classes/LinkButton.xml4
-rw-r--r--doc/classes/Listener.xml2
-rw-r--r--doc/classes/MainLoop.xml6
-rw-r--r--doc/classes/MarginContainer.xml2
-rw-r--r--doc/classes/Marshalls.xml2
-rw-r--r--doc/classes/Material.xml2
-rw-r--r--doc/classes/MenuButton.xml2
-rw-r--r--doc/classes/Mesh.xml2
-rw-r--r--doc/classes/MeshDataTool.xml2
-rw-r--r--doc/classes/MeshInstance.xml2
-rw-r--r--doc/classes/MeshLibrary.xml2
-rw-r--r--doc/classes/MultiMesh.xml8
-rw-r--r--doc/classes/MultiMeshInstance.xml2
-rw-r--r--doc/classes/Mutex.xml8
-rw-r--r--doc/classes/Navigation.xml2
-rw-r--r--doc/classes/Navigation2D.xml2
-rw-r--r--doc/classes/NavigationMesh.xml2
-rw-r--r--doc/classes/NavigationMeshInstance.xml2
-rw-r--r--doc/classes/NavigationPolygon.xml2
-rw-r--r--doc/classes/NavigationPolygonInstance.xml2
-rw-r--r--doc/classes/NetworkedMultiplayerPeer.xml6
-rw-r--r--doc/classes/Nil.xml4
-rw-r--r--doc/classes/NinePatchRect.xml4
-rw-r--r--doc/classes/Node.xml125
-rw-r--r--doc/classes/Node2D.xml58
-rw-r--r--doc/classes/NodePath.xml6
-rw-r--r--doc/classes/OS.xml104
-rw-r--r--doc/classes/Object.xml59
-rw-r--r--doc/classes/OccluderPolygon2D.xml10
-rw-r--r--doc/classes/OmniLight.xml2
-rw-r--r--doc/classes/OptionButton.xml4
-rw-r--r--doc/classes/PCKPacker.xml2
-rw-r--r--doc/classes/PHashTranslation.xml2
-rw-r--r--doc/classes/PackedDataContainer.xml2
-rw-r--r--doc/classes/PackedDataContainerRef.xml2
-rw-r--r--doc/classes/PackedScene.xml2
-rw-r--r--doc/classes/PacketPeer.xml2
-rw-r--r--doc/classes/PacketPeerStream.xml2
-rw-r--r--doc/classes/PacketPeerUDP.xml10
-rw-r--r--doc/classes/Panel.xml2
-rw-r--r--doc/classes/PanelContainer.xml2
-rw-r--r--doc/classes/PanoramaSky.xml2
-rw-r--r--doc/classes/ParallaxBackground.xml10
-rw-r--r--doc/classes/ParallaxLayer.xml8
-rw-r--r--doc/classes/Particles.xml26
-rw-r--r--doc/classes/Particles2D.xml24
-rw-r--r--doc/classes/ParticlesMaterial.xml70
-rw-r--r--doc/classes/Path.xml2
-rw-r--r--doc/classes/Path2D.xml7
-rw-r--r--doc/classes/PathFollow.xml2
-rw-r--r--doc/classes/PathFollow2D.xml2
-rw-r--r--doc/classes/Performance.xml41
-rw-r--r--doc/classes/Physics2DDirectBodyState.xml2
-rw-r--r--doc/classes/Physics2DDirectBodyStateSW.xml2
-rw-r--r--doc/classes/Physics2DDirectSpaceState.xml12
-rw-r--r--doc/classes/Physics2DServer.xml237
-rw-r--r--doc/classes/Physics2DServerSW.xml4
-rw-r--r--doc/classes/Physics2DShapeQueryParameters.xml8
-rw-r--r--doc/classes/Physics2DShapeQueryResult.xml2
-rw-r--r--doc/classes/Physics2DTestMotionResult.xml2
-rw-r--r--doc/classes/PhysicsBody.xml2
-rw-r--r--doc/classes/PhysicsBody2D.xml2
-rw-r--r--doc/classes/PhysicsDirectBodyState.xml2
-rw-r--r--doc/classes/PhysicsDirectBodyStateSW.xml15
-rw-r--r--doc/classes/PhysicsDirectSpaceState.xml6
-rw-r--r--doc/classes/PhysicsServer.xml267
-rw-r--r--doc/classes/PhysicsShapeQueryParameters.xml2
-rw-r--r--doc/classes/PhysicsShapeQueryResult.xml2
-rw-r--r--doc/classes/PinJoint.xml14
-rw-r--r--doc/classes/PinJoint2D.xml3
-rw-r--r--doc/classes/Plane.xml2
-rw-r--r--doc/classes/PlaneMesh.xml2
-rw-r--r--doc/classes/PlaneShape.xml2
-rw-r--r--doc/classes/Polygon2D.xml18
-rw-r--r--doc/classes/PolygonPathFinder.xml2
-rw-r--r--doc/classes/PoolByteArray.xml10
-rw-r--r--doc/classes/PoolColorArray.xml4
-rw-r--r--doc/classes/PoolIntArray.xml4
-rw-r--r--doc/classes/PoolRealArray.xml2
-rw-r--r--doc/classes/PoolStringArray.xml2
-rw-r--r--doc/classes/PoolVector2Array.xml6
-rw-r--r--doc/classes/PoolVector3Array.xml4
-rw-r--r--doc/classes/Popup.xml2
-rw-r--r--doc/classes/PopupDialog.xml2
-rw-r--r--doc/classes/PopupMenu.xml2
-rw-r--r--doc/classes/PopupPanel.xml2
-rw-r--r--doc/classes/Position2D.xml2
-rw-r--r--doc/classes/Position3D.xml2
-rw-r--r--doc/classes/PrimitiveMesh.xml2
-rw-r--r--doc/classes/PrismMesh.xml2
-rw-r--r--doc/classes/ProceduralSky.xml2
-rw-r--r--doc/classes/ProgressBar.xml2
-rw-r--r--doc/classes/ProjectSettings.xml28
-rw-r--r--doc/classes/ProximityGroup.xml2
-rw-r--r--doc/classes/QuadMesh.xml20
-rw-r--r--doc/classes/Quat.xml17
-rw-r--r--doc/classes/RID.xml2
-rw-r--r--doc/classes/Range.xml2
-rw-r--r--doc/classes/RayCast.xml41
-rw-r--r--doc/classes/RayCast2D.xml38
-rw-r--r--doc/classes/RayShape.xml2
-rw-r--r--doc/classes/RayShape2D.xml2
-rw-r--r--doc/classes/Rect2.xml28
-rw-r--r--doc/classes/RectangleShape2D.xml2
-rw-r--r--doc/classes/Reference.xml2
-rw-r--r--doc/classes/ReferenceRect.xml2
-rw-r--r--doc/classes/ReflectionProbe.xml2
-rw-r--r--doc/classes/RegEx.xml114
-rw-r--r--doc/classes/RegExMatch.xml72
-rw-r--r--doc/classes/RemoteTransform.xml10
-rw-r--r--doc/classes/RemoteTransform2D.xml10
-rw-r--r--doc/classes/Resource.xml6
-rw-r--r--doc/classes/ResourceImporter.xml2
-rw-r--r--doc/classes/ResourceInteractiveLoader.xml2
-rw-r--r--doc/classes/ResourceLoader.xml4
-rw-r--r--doc/classes/ResourcePreloader.xml2
-rw-r--r--doc/classes/ResourceSaver.xml2
-rw-r--r--doc/classes/RichTextLabel.xml87
-rw-r--r--doc/classes/RigidBody.xml14
-rw-r--r--doc/classes/RigidBody2D.xml109
-rw-r--r--doc/classes/SceneState.xml2
-rw-r--r--doc/classes/SceneTree.xml20
-rw-r--r--doc/classes/SceneTreeTimer.xml2
-rw-r--r--doc/classes/Script.xml8
-rw-r--r--doc/classes/ScriptEditor.xml36
-rw-r--r--doc/classes/ScrollBar.xml2
-rw-r--r--doc/classes/ScrollContainer.xml2
-rw-r--r--doc/classes/SegmentShape2D.xml2
-rw-r--r--doc/classes/Semaphore.xml6
-rw-r--r--doc/classes/Separator.xml2
-rw-r--r--doc/classes/Shader.xml2
-rw-r--r--doc/classes/ShaderMaterial.xml2
-rw-r--r--doc/classes/Shape.xml2
-rw-r--r--doc/classes/Shape2D.xml2
-rw-r--r--doc/classes/ShortCut.xml2
-rw-r--r--doc/classes/Skeleton.xml2
-rw-r--r--doc/classes/Sky.xml2
-rw-r--r--doc/classes/Slider.xml2
-rw-r--r--doc/classes/SliderJoint.xml52
-rw-r--r--doc/classes/Spatial.xml22
-rw-r--r--doc/classes/SpatialGizmo.xml2
-rw-r--r--doc/classes/SpatialMaterial.xml46
-rw-r--r--doc/classes/SpatialVelocityTracker.xml6
-rw-r--r--doc/classes/SphereMesh.xml2
-rw-r--r--doc/classes/SphereShape.xml2
-rw-r--r--doc/classes/SpinBox.xml2
-rw-r--r--doc/classes/SplitContainer.xml2
-rw-r--r--doc/classes/SpotLight.xml2
-rw-r--r--doc/classes/Sprite.xml2
-rw-r--r--doc/classes/Sprite3D.xml2
-rw-r--r--doc/classes/SpriteBase3D.xml4
-rw-r--r--doc/classes/SpriteFrames.xml2
-rw-r--r--doc/classes/StaticBody.xml2
-rw-r--r--doc/classes/StaticBody2D.xml2
-rw-r--r--doc/classes/StreamPeer.xml8
-rw-r--r--doc/classes/StreamPeerBuffer.xml2
-rw-r--r--doc/classes/StreamPeerSSL.xml8
-rw-r--r--doc/classes/StreamPeerTCP.xml10
-rw-r--r--doc/classes/StreamTexture.xml2
-rw-r--r--doc/classes/String.xml153
-rw-r--r--doc/classes/StyleBox.xml2
-rw-r--r--doc/classes/StyleBoxEmpty.xml2
-rw-r--r--doc/classes/StyleBoxFlat.xml10
-rw-r--r--doc/classes/StyleBoxLine.xml79
-rw-r--r--doc/classes/StyleBoxTexture.xml2
-rw-r--r--doc/classes/SurfaceTool.xml6
-rw-r--r--doc/classes/TCP_Server.xml2
-rw-r--r--doc/classes/TabContainer.xml46
-rw-r--r--doc/classes/Tabs.xml6
-rw-r--r--doc/classes/TextEdit.xml65
-rw-r--r--doc/classes/Texture.xml8
-rw-r--r--doc/classes/TextureButton.xml2
-rw-r--r--doc/classes/TextureProgress.xml2
-rw-r--r--doc/classes/TextureRect.xml2
-rw-r--r--doc/classes/Theme.xml2
-rw-r--r--doc/classes/Thread.xml12
-rw-r--r--doc/classes/TileMap.xml18
-rw-r--r--doc/classes/TileSet.xml2
-rw-r--r--doc/classes/Timer.xml6
-rw-r--r--doc/classes/ToolButton.xml2
-rw-r--r--doc/classes/TouchScreenButton.xml33
-rw-r--r--doc/classes/Transform.xml6
-rw-r--r--doc/classes/Transform2D.xml10
-rw-r--r--doc/classes/Translation.xml2
-rw-r--r--doc/classes/TranslationServer.xml10
-rw-r--r--doc/classes/Tree.xml72
-rw-r--r--doc/classes/TreeItem.xml63
-rw-r--r--doc/classes/TriangleMesh.xml2
-rw-r--r--doc/classes/Tween.xml18
-rw-r--r--doc/classes/UndoRedo.xml2
-rw-r--r--doc/classes/VBoxContainer.xml2
-rw-r--r--doc/classes/VScrollBar.xml2
-rw-r--r--doc/classes/VSeparator.xml2
-rw-r--r--doc/classes/VSlider.xml4
-rw-r--r--doc/classes/VSplitContainer.xml2
-rw-r--r--doc/classes/Variant.xml2
-rw-r--r--doc/classes/Vector2.xml2
-rw-r--r--doc/classes/Vector3.xml25
-rw-r--r--doc/classes/VehicleBody.xml2
-rw-r--r--doc/classes/VehicleWheel.xml8
-rw-r--r--doc/classes/VideoPlayer.xml22
-rw-r--r--doc/classes/VideoStream.xml2
-rw-r--r--doc/classes/Viewport.xml8
-rw-r--r--doc/classes/ViewportContainer.xml18
-rw-r--r--doc/classes/ViewportTexture.xml2
-rw-r--r--doc/classes/VisibilityEnabler.xml8
-rw-r--r--doc/classes/VisibilityEnabler2D.xml20
-rw-r--r--doc/classes/VisibilityNotifier.xml8
-rw-r--r--doc/classes/VisibilityNotifier2D.xml2
-rw-r--r--doc/classes/VisualInstance.xml6
-rw-r--r--doc/classes/VisualScriptCondition.xml17
-rw-r--r--doc/classes/VisualScriptIterator.xml15
-rw-r--r--doc/classes/VisualServer.xml2032
-rw-r--r--doc/classes/WeakRef.xml4
-rw-r--r--doc/classes/WindowDialog.xml2
-rw-r--r--doc/classes/World.xml2
-rw-r--r--doc/classes/World2D.xml2
-rw-r--r--doc/classes/WorldEnvironment.xml4
-rw-r--r--doc/classes/XMLParser.xml2
-rw-r--r--doc/classes/YSort.xml2
-rw-r--r--doc/classes/bool.xml2
-rw-r--r--doc/classes/float.xml2
-rw-r--r--doc/classes/int.xml2
-rw-r--r--doc/tools/doc_status.py39
-rw-r--r--doc/tools/makerst.py60
-rw-r--r--drivers/SCsub5
-rw-r--r--drivers/gl_context/context_gl.cpp2
-rw-r--r--drivers/gl_context/context_gl.h2
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.cpp63
-rw-r--r--drivers/gles3/rasterizer_gles3.cpp50
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.cpp108
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.h13
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.cpp140
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.h48
-rw-r--r--drivers/gles3/shader_compiler_gles3.cpp9
-rw-r--r--drivers/gles3/shaders/canvas.glsl3
-rw-r--r--drivers/gles3/shaders/copy.glsl24
-rw-r--r--drivers/gles3/shaders/scene.glsl205
-rw-r--r--drivers/gles3/shaders/ssao.glsl24
-rw-r--r--drivers/gles3/shaders/ssao_blur.glsl20
-rw-r--r--drivers/gles3/shaders/subsurf_scattering.glsl25
-rw-r--r--drivers/gles3/shaders/tonemap.glsl7
-rw-r--r--drivers/unix/SCsub10
-rw-r--r--drivers/unix/os_unix.cpp50
-rw-r--r--drivers/unix/os_unix.h13
-rw-r--r--drivers/wasapi/audio_driver_wasapi.cpp53
-rw-r--r--drivers/wasapi/audio_driver_wasapi.h2
-rw-r--r--drivers/windows/dir_access_windows.cpp2
-rw-r--r--editor/SCsub76
-rw-r--r--editor/animation_editor.cpp63
-rw-r--r--editor/code_editor.cpp46
-rw-r--r--editor/code_editor.h3
-rw-r--r--editor/collada/collada.cpp30
-rw-r--r--editor/connections_dialog.cpp4
-rw-r--r--editor/create_dialog.cpp27
-rw-r--r--editor/create_dialog.h1
-rw-r--r--editor/dependency_editor.cpp209
-rw-r--r--editor/dependency_editor.h43
-rw-r--r--editor/dictionary_property_edit.cpp189
-rw-r--r--editor/dictionary_property_edit.h62
-rw-r--r--editor/doc/doc_data.cpp55
-rw-r--r--editor/doc/doc_dump.cpp4
-rw-r--r--editor/editor_about.cpp4
-rw-r--r--editor/editor_data.cpp2
-rw-r--r--editor/editor_export.cpp160
-rw-r--r--editor/editor_export.h65
-rw-r--r--editor/editor_file_dialog.cpp41
-rw-r--r--editor/editor_file_system.cpp72
-rw-r--r--editor/editor_fonts.cpp15
-rw-r--r--editor/editor_help.cpp159
-rw-r--r--editor/editor_node.cpp356
-rw-r--r--editor/editor_node.h24
-rw-r--r--editor/editor_path.cpp10
-rw-r--r--editor/editor_plugin.cpp25
-rw-r--r--editor/editor_plugin.h4
-rw-r--r--editor/editor_profiler.cpp2
-rw-r--r--editor/editor_resource_preview.cpp23
-rw-r--r--editor/editor_settings.cpp1092
-rw-r--r--editor/editor_settings.h104
-rw-r--r--editor/editor_themes.cpp45
-rw-r--r--editor/editor_themes.h2
-rw-r--r--editor/export_template_manager.cpp239
-rw-r--r--editor/export_template_manager.h20
-rw-r--r--editor/filesystem_dock.cpp1370
-rw-r--r--editor/filesystem_dock.h80
-rw-r--r--editor/icons/icon_GUI_ellipsis.svg5
-rw-r--r--editor/icons/icon_GUI_toggle_off.svg6
-rw-r--r--editor/icons/icon_GUI_toggle_on.svg6
-rw-r--r--editor/icons/icon_GUI_unchecked.svg4
-rw-r--r--editor/icons/icon_a_r_v_r_anchor.svg3
-rw-r--r--editor/icons/icon_a_r_v_r_camera.svg2
-rw-r--r--editor/icons/icon_a_r_v_r_controller.svg3
-rw-r--r--editor/icons/icon_a_r_v_r_origin.svg3
-rw-r--r--editor/icons/icon_animated_sprite.svg8
-rw-r--r--editor/icons/icon_animated_sprite_3d.svg8
-rw-r--r--editor/icons/icon_animation.svg4
-rw-r--r--editor/icons/icon_area.svg4
-rw-r--r--editor/icons/icon_area_2d.svg4
-rw-r--r--editor/icons/icon_array_mesh.svg4
-rw-r--r--editor/icons/icon_center_container.svg4
-rw-r--r--editor/icons/icon_color_pick.svg2
-rw-r--r--editor/icons/icon_color_picker.svg4
-rw-r--r--editor/icons/icon_color_picker_button.svg6
-rw-r--r--editor/icons/icon_connection_and_groups.svg5
-rw-r--r--editor/icons/icon_control_layout.svg3
-rw-r--r--editor/icons/icon_edit.svg2
-rw-r--r--editor/icons/icon_edit_key.svg5
-rw-r--r--editor/icons/icon_groups.svg4
-rw-r--r--editor/icons/icon_h_button_array.svg5
-rw-r--r--editor/icons/icon_key_position.svg (renamed from editor/icons/icon_key_move_enabled.svg)0
-rw-r--r--editor/icons/icon_key_rotation.svg (renamed from editor/icons/icon_key_rotate_enabled.svg)0
-rw-r--r--editor/icons/icon_key_scale.svg (renamed from editor/icons/icon_key_scale_enabled.svg)0
-rw-r--r--editor/icons/icon_kinematic_body.svg2
-rw-r--r--editor/icons/icon_kinematic_body_2d.svg4
-rw-r--r--editor/icons/icon_multi_edit.svg2
-rw-r--r--editor/icons/icon_onion.svg3
-rw-r--r--editor/icons/icon_shader.svg12
-rw-r--r--editor/icons/icon_signals.svg (renamed from editor/icons/icon_connect.svg)0
-rw-r--r--editor/icons/icon_signals_and_groups.svg5
-rw-r--r--editor/icons/icon_sprite.svg4
-rw-r--r--editor/icons/icon_sprite_3d.svg4
-rw-r--r--editor/icons/icon_sprite_frames.svg4
-rw-r--r--editor/icons/icon_texture_button.svg4
-rw-r--r--editor/icons/icon_texture_rect.svg3
-rw-r--r--editor/icons/icon_v_button_array.svg6
-rw-r--r--editor/icons/icon_viewport_speed.svg4
-rw-r--r--editor/icons/icon_viewport_sprite.svg7
-rw-r--r--editor/icons/icon_viewport_zoom.svg6
-rw-r--r--editor/import/editor_import_collada.cpp43
-rw-r--r--editor/import/editor_scene_importer_gltf.cpp6
-rw-r--r--editor/import/resource_importer_obj.cpp1
-rw-r--r--editor/import/resource_importer_scene.cpp112
-rw-r--r--editor/import/resource_importer_scene.h3
-rw-r--r--editor/import_dock.cpp79
-rw-r--r--editor/import_dock.h2
-rw-r--r--editor/node_dock.cpp4
-rw-r--r--editor/plugins/abstract_polygon_2d_editor.cpp796
-rw-r--r--editor/plugins/abstract_polygon_2d_editor.h167
-rw-r--r--editor/plugins/animation_player_editor_plugin.cpp2
-rw-r--r--editor/plugins/asset_library_editor_plugin.cpp61
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp881
-rw-r--r--editor/plugins/canvas_item_editor_plugin.h112
-rw-r--r--editor/plugins/collision_polygon_2d_editor_plugin.cpp396
-rw-r--r--editor/plugins/collision_polygon_2d_editor_plugin.h60
-rw-r--r--editor/plugins/collision_polygon_editor_plugin.cpp2
-rw-r--r--editor/plugins/collision_shape_2d_editor_plugin.cpp44
-rw-r--r--editor/plugins/collision_shape_2d_editor_plugin.h7
-rw-r--r--editor/plugins/editor_preview_plugins.cpp14
-rw-r--r--editor/plugins/gi_probe_editor_plugin.cpp26
-rw-r--r--editor/plugins/gi_probe_editor_plugin.h5
-rw-r--r--editor/plugins/light_occluder_2d_editor_plugin.cpp27
-rw-r--r--editor/plugins/light_occluder_2d_editor_plugin.h7
-rw-r--r--editor/plugins/line_2d_editor_plugin.cpp263
-rw-r--r--editor/plugins/line_2d_editor_plugin.h81
-rw-r--r--editor/plugins/material_editor_plugin.cpp85
-rw-r--r--editor/plugins/material_editor_plugin.h16
-rw-r--r--editor/plugins/mesh_editor_plugin.cpp2
-rw-r--r--editor/plugins/navigation_mesh_generator.cpp6
-rw-r--r--editor/plugins/navigation_polygon_editor_plugin.cpp500
-rw-r--r--editor/plugins/navigation_polygon_editor_plugin.h74
-rw-r--r--editor/plugins/particles_editor_plugin.cpp8
-rw-r--r--editor/plugins/path_2d_editor_plugin.cpp19
-rw-r--r--editor/plugins/path_2d_editor_plugin.h5
-rw-r--r--editor/plugins/polygon_2d_editor_plugin.cpp435
-rw-r--r--editor/plugins/polygon_2d_editor_plugin.h61
-rw-r--r--editor/plugins/resource_preloader_editor_plugin.cpp2
-rw-r--r--editor/plugins/script_editor_plugin.cpp392
-rw-r--r--editor/plugins/script_editor_plugin.h16
-rw-r--r--editor/plugins/script_text_editor.cpp199
-rw-r--r--editor/plugins/script_text_editor.h6
-rw-r--r--editor/plugins/shader_editor_plugin.cpp400
-rw-r--r--editor/plugins/shader_editor_plugin.h18
-rw-r--r--editor/plugins/spatial_editor_plugin.cpp964
-rw-r--r--editor/plugins/spatial_editor_plugin.h50
-rw-r--r--editor/plugins/sprite_frames_editor_plugin.cpp48
-rw-r--r--editor/plugins/sprite_frames_editor_plugin.h2
-rw-r--r--editor/plugins/texture_region_editor_plugin.cpp108
-rw-r--r--editor/plugins/texture_region_editor_plugin.h4
-rw-r--r--editor/plugins/theme_editor_plugin.cpp22
-rw-r--r--editor/plugins/theme_editor_plugin.h3
-rw-r--r--editor/plugins/tile_map_editor_plugin.cpp58
-rw-r--r--editor/plugins/tile_map_editor_plugin.h6
-rw-r--r--editor/project_export.cpp21
-rw-r--r--editor/project_export.h3
-rw-r--r--editor/project_manager.cpp96
-rw-r--r--editor/project_manager.h5
-rw-r--r--editor/project_settings_editor.cpp243
-rw-r--r--editor/project_settings_editor.h14
-rw-r--r--editor/property_editor.cpp99
-rw-r--r--editor/pvrtc_compress.cpp6
-rw-r--r--editor/scene_tree_dock.cpp160
-rw-r--r--editor/scene_tree_dock.h11
-rw-r--r--editor/scene_tree_editor.cpp16
-rw-r--r--editor/script_create_dialog.cpp41
-rw-r--r--editor/script_create_dialog.h1
-rw-r--r--editor/script_editor_debugger.cpp266
-rw-r--r--editor/script_editor_debugger.h21
-rw-r--r--editor/settings_config_dialog.cpp104
-rw-r--r--editor/settings_config_dialog.h5
-rw-r--r--editor/spatial_editor_gizmos.cpp34
-rw-r--r--editor/spatial_editor_gizmos.h4
-rw-r--r--editor/translations/ar.po2901
-rw-r--r--editor/translations/bg.po2235
-rw-r--r--editor/translations/bn.po2975
-rw-r--r--editor/translations/ca.po2568
-rw-r--r--editor/translations/cs.po2184
-rw-r--r--editor/translations/da.po2176
-rw-r--r--editor/translations/de.po3437
-rw-r--r--editor/translations/de_CH.po2222
-rw-r--r--editor/translations/editor.pot2081
-rw-r--r--editor/translations/el.po3418
-rw-r--r--editor/translations/es.po3377
-rw-r--r--editor/translations/es_AR.po3405
-rw-r--r--editor/translations/fa.po2203
-rw-r--r--editor/translations/fi.po2725
-rw-r--r--editor/translations/fr.po3893
-rw-r--r--editor/translations/hu.po2084
-rw-r--r--editor/translations/id.po2437
-rw-r--r--editor/translations/it.po3154
-rw-r--r--editor/translations/ja.po3275
-rw-r--r--editor/translations/ko.po3394
-rw-r--r--editor/translations/lt.po7371
-rw-r--r--editor/translations/nb.po2105
-rw-r--r--editor/translations/nl.po2559
-rw-r--r--editor/translations/pl.po2913
-rw-r--r--editor/translations/pr.po2109
-rw-r--r--editor/translations/pt_BR.po3874
-rw-r--r--editor/translations/pt_PT.po2173
-rw-r--r--editor/translations/ru.po3420
-rw-r--r--editor/translations/sk.po2122
-rw-r--r--editor/translations/sl.po2103
-rw-r--r--editor/translations/th.po3368
-rw-r--r--editor/translations/tr.po2989
-rw-r--r--editor/translations/ur_PK.po2103
-rw-r--r--editor/translations/zh_CN.po3501
-rw-r--r--editor/translations/zh_HK.po2179
-rw-r--r--editor/translations/zh_TW.po2165
-rw-r--r--main/SCsub2
-rw-r--r--main/input_default.cpp9
-rwxr-xr-x[-rw-r--r--]main/main.cpp150
-rw-r--r--main/performance.cpp40
-rw-r--r--main/performance.h8
-rw-r--r--main/splash.pngbin29867 -> 21504 bytes
-rw-r--r--main/tests/test_gdscript.cpp298
-rw-r--r--main/tests/test_physics.cpp2
-rw-r--r--main/tests/test_physics_2d.cpp20
-rw-r--r--main/tests/test_render.cpp4
-rw-r--r--methods.py53
-rw-r--r--misc/dist/docker/README.md80
-rw-r--r--misc/dist/html/default.html27
-rwxr-xr-xmisc/dist/ios_xcode/godot.iphone.debug.fat0
-rwxr-xr-xmisc/dist/ios_xcode/godot.iphone.release.arm0
-rwxr-xr-xmisc/dist/ios_xcode/godot.iphone.release.arm640
-rwxr-xr-xmisc/dist/ios_xcode/godot.iphone.release.fat0
-rw-r--r--misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj91
-rw-r--r--misc/dist/ios_xcode/godot_ios.xcodeproj/xcshareddata/xcschemes/godot_ios.xcscheme10
-rw-r--r--misc/dist/ios_xcode/godot_ios/dummy.cpp1
-rw-r--r--misc/dist/ios_xcode/godot_ios/dylibs/empty1
-rw-r--r--misc/dist/ios_xcode/godot_ios/export_options.plist (renamed from misc/dist/ios_xcode/export_options.plist)10
-rw-r--r--misc/dist/ios_xcode/godot_ios/godot_ios-Info.plist3
-rw-r--r--[-rwxr-xr-x]misc/dist/ios_xcode/libgodot.iphone.debug.fat.a (renamed from misc/dist/ios_xcode/godot.iphone.debug.arm)0
-rw-r--r--[-rwxr-xr-x]misc/dist/ios_xcode/libgodot.iphone.release.fat.a (renamed from misc/dist/ios_xcode/godot.iphone.debug.arm64)0
-rw-r--r--misc/dist/uwp_template/AppxManifest.xml62
-rwxr-xr-xmisc/travis/android-tools-linux.sh107
-rwxr-xr-xmisc/travis/android-tools-osx.sh107
-rwxr-xr-xmisc/travis/ccache-osx.sh43
-rwxr-xr-xmisc/travis/scons-local-osx.sh18
-rw-r--r--modules/SCsub1
-rw-r--r--modules/bullet/SCsub191
-rw-r--r--modules/bullet/SCsub_with_lib33
-rw-r--r--modules/bullet/area_bullet.cpp284
-rw-r--r--modules/bullet/area_bullet.h169
-rw-r--r--modules/bullet/btRayShape.cpp94
-rw-r--r--modules/bullet/btRayShape.h87
-rw-r--r--modules/bullet/bullet_physics_server.cpp1364
-rw-r--r--modules/bullet/bullet_physics_server.h362
-rw-r--r--modules/bullet/bullet_types_converter.cpp94
-rw-r--r--modules/bullet/bullet_types_converter.h57
-rw-r--r--modules/bullet/bullet_utilities.h44
-rw-r--r--modules/bullet/collision_object_bullet.cpp320
-rw-r--r--modules/bullet/collision_object_bullet.h234
-rw-r--r--modules/bullet/cone_twist_joint_bullet.cpp111
-rw-r--r--modules/bullet/cone_twist_joint_bullet.h58
-rw-r--r--modules/bullet/config.py14
-rw-r--r--modules/bullet/constraint_bullet.cpp50
-rw-r--r--modules/bullet/constraint_bullet.h64
-rw-r--r--modules/bullet/doc_classes/BulletPhysicsDirectBodyState.xml15
-rw-r--r--modules/bullet/doc_classes/BulletPhysicsServer.xml (renamed from doc/classes/PhysicsServerSW.xml)2
-rw-r--r--modules/bullet/generic_6dof_joint_bullet.cpp241
-rw-r--r--modules/bullet/generic_6dof_joint_bullet.h65
-rw-r--r--modules/bullet/godot_collision_configuration.cpp91
-rw-r--r--modules/bullet/godot_collision_configuration.h50
-rw-r--r--modules/bullet/godot_collision_dispatcher.cpp54
-rw-r--r--modules/bullet/godot_collision_dispatcher.h48
-rw-r--r--modules/bullet/godot_motion_state.h96
-rw-r--r--modules/bullet/godot_ray_world_algorithm.cpp104
-rw-r--r--modules/bullet/godot_ray_world_algorithm.h83
-rw-r--r--modules/bullet/godot_result_callbacks.cpp262
-rw-r--r--modules/bullet/godot_result_callbacks.h179
-rw-r--r--modules/bullet/hinge_joint_bullet.cpp163
-rw-r--r--modules/bullet/hinge_joint_bullet.h54
-rw-r--r--modules/bullet/joint_bullet.cpp38
-rw-r--r--modules/bullet/joint_bullet.h49
-rw-r--r--modules/bullet/pin_joint_bullet.cpp112
-rw-r--r--modules/bullet/pin_joint_bullet.h57
-rw-r--r--modules/bullet/register_types.cpp47
-rw-r--r--modules/bullet/register_types.h37
-rw-r--r--modules/bullet/rid_bullet.h50
-rw-r--r--modules/bullet/rigid_body_bullet.cpp999
-rw-r--r--modules/bullet/rigid_body_bullet.h302
-rw-r--r--modules/bullet/shape_bullet.cpp435
-rw-r--r--modules/bullet/shape_bullet.h225
-rw-r--r--modules/bullet/shape_owner_bullet.cpp32
-rw-r--r--modules/bullet/shape_owner_bullet.h52
-rw-r--r--modules/bullet/slider_joint_bullet.cpp385
-rw-r--r--modules/bullet/slider_joint_bullet.h118
-rw-r--r--modules/bullet/soft_body_bullet.cpp303
-rw-r--r--modules/bullet/soft_body_bullet.h136
-rw-r--r--modules/bullet/space_bullet.cpp1139
-rw-r--r--modules/bullet/space_bullet.h200
-rw-r--r--modules/dds/config.py2
-rw-r--r--modules/enet/config.py10
-rw-r--r--modules/enet/doc_classes/NetworkedMultiplayerENet.xml (renamed from doc/classes/NetworkedMultiplayerENet.xml)2
-rw-r--r--modules/enet/networked_multiplayer_enet.cpp2
-rw-r--r--modules/etc/config.py2
-rw-r--r--modules/etc/image_etc.cpp14
-rw-r--r--modules/freetype/config.py2
-rw-r--r--modules/gdnative/SCsub137
-rw-r--r--modules/gdnative/arvr/SCsub13
-rw-r--r--modules/gdnative/arvr/arvr_interface_gdnative.cpp398
-rw-r--r--modules/gdnative/arvr/arvr_interface_gdnative.h86
-rw-r--r--modules/gdnative/arvr/config.py5
-rw-r--r--modules/gdnative/arvr/register_types.cpp (renamed from misc/dist/ios_xcode/godot_ios/main.m)14
-rw-r--r--modules/gdnative/arvr/register_types.h32
-rw-r--r--modules/gdnative/config.py15
-rw-r--r--modules/gdnative/doc_classes/ARVRInterfaceGDNative.xml17
-rw-r--r--modules/gdnative/doc_classes/GDNative.xml (renamed from doc/classes/GDNative.xml)8
-rw-r--r--modules/gdnative/doc_classes/GDNativeLibrary.xml89
-rw-r--r--modules/gdnative/doc_classes/NativeScript.xml (renamed from doc/classes/NativeScript.xml)2
-rw-r--r--modules/gdnative/doc_classes/PluginScript.xml (renamed from doc/classes/VisualScriptSelf.xml)2
-rw-r--r--modules/gdnative/gd_native_library_editor.cpp2
-rw-r--r--modules/gdnative/gdnative.cpp403
-rw-r--r--modules/gdnative/gdnative.h121
-rw-r--r--modules/gdnative/gdnative/aabb.cpp217
-rw-r--r--modules/gdnative/gdnative/array.cpp19
-rw-r--r--modules/gdnative/gdnative/basis.cpp4
-rw-r--r--modules/gdnative/gdnative/color.cpp2
-rw-r--r--modules/gdnative/gdnative/dictionary.cpp8
-rw-r--r--modules/gdnative/gdnative/gdnative.cpp83
-rw-r--r--modules/gdnative/gdnative/node_path.cpp2
-rw-r--r--modules/gdnative/gdnative/plane.cpp2
-rw-r--r--modules/gdnative/gdnative/pool_arrays.cpp265
-rw-r--r--modules/gdnative/gdnative/quat.cpp2
-rw-r--r--modules/gdnative/gdnative/rect2.cpp2
-rw-r--r--modules/gdnative/gdnative/rect3.cpp219
-rw-r--r--modules/gdnative/gdnative/rid.cpp2
-rw-r--r--modules/gdnative/gdnative/string.cpp30
-rw-r--r--modules/gdnative/gdnative/string_name.cpp88
-rw-r--r--modules/gdnative/gdnative/transform.cpp18
-rw-r--r--modules/gdnative/gdnative/transform2d.cpp2
-rw-r--r--modules/gdnative/gdnative/variant.cpp14
-rw-r--r--modules/gdnative/gdnative/vector2.cpp2
-rw-r--r--modules/gdnative/gdnative/vector3.cpp2
-rw-r--r--modules/gdnative/gdnative_api.json10315
-rw-r--r--modules/gdnative/include/arvr/godot_arvr.h79
-rw-r--r--modules/gdnative/include/gdnative/aabb.h117
-rw-r--r--modules/gdnative/include/gdnative/array.h15
-rw-r--r--modules/gdnative/include/gdnative/basis.h11
-rw-r--r--modules/gdnative/include/gdnative/color.h9
-rw-r--r--modules/gdnative/include/gdnative/dictionary.h11
-rw-r--r--modules/gdnative/include/gdnative/gdnative.h34
-rw-r--r--modules/gdnative/include/gdnative/node_path.h9
-rw-r--r--modules/gdnative/include/gdnative/plane.h9
-rw-r--r--modules/gdnative/include/gdnative/pool_arrays.h133
-rw-r--r--modules/gdnative/include/gdnative/quat.h9
-rw-r--r--modules/gdnative/include/gdnative/rect2.h9
-rw-r--r--modules/gdnative/include/gdnative/rect3.h108
-rw-r--r--modules/gdnative/include/gdnative/rid.h9
-rw-r--r--modules/gdnative/include/gdnative/string.h12
-rw-r--r--modules/gdnative/include/gdnative/string_name.h77
-rw-r--r--modules/gdnative/include/gdnative/transform.h13
-rw-r--r--modules/gdnative/include/gdnative/transform2d.h9
-rw-r--r--modules/gdnative/include/gdnative/variant.h17
-rw-r--r--modules/gdnative/include/gdnative/vector2.h9
-rw-r--r--modules/gdnative/include/gdnative/vector3.h9
-rw-r--r--modules/gdnative/include/pluginscript/godot_pluginscript.h171
-rw-r--r--modules/gdnative/nativescript/SCsub1
-rw-r--r--modules/gdnative/nativescript/api_generator.cpp12
-rw-r--r--modules/gdnative/nativescript/api_generator.h2
-rw-r--r--modules/gdnative/nativescript/nativescript.cpp98
-rw-r--r--modules/gdnative/nativescript/nativescript.h17
-rw-r--r--modules/gdnative/nativescript/register_types.cpp50
-rw-r--r--modules/gdnative/pluginscript/SCsub9
-rw-r--r--modules/gdnative/pluginscript/pluginscript_instance.cpp181
-rw-r--r--modules/gdnative/pluginscript/pluginscript_instance.h90
-rw-r--r--modules/gdnative/pluginscript/pluginscript_language.cpp435
-rw-r--r--modules/gdnative/pluginscript/pluginscript_language.h132
-rw-r--r--modules/gdnative/pluginscript/pluginscript_loader.cpp113
-rw-r--r--modules/gdnative/pluginscript/pluginscript_loader.h62
-rw-r--r--modules/gdnative/pluginscript/pluginscript_script.cpp449
-rw-r--r--modules/gdnative/pluginscript/pluginscript_script.h127
-rw-r--r--modules/gdnative/pluginscript/register_types.cpp118
-rw-r--r--modules/gdnative/pluginscript/register_types.h31
-rw-r--r--modules/gdnative/register_types.cpp242
-rw-r--r--modules/gdscript/config.py13
-rw-r--r--modules/gdscript/doc_classes/GDScript.xml (renamed from doc/classes/GDScript.xml)2
-rw-r--r--modules/gdscript/doc_classes/GDScriptFunctionState.xml (renamed from doc/classes/GDFunctionState.xml)4
-rw-r--r--modules/gdscript/doc_classes/GDScriptNativeClass.xml (renamed from doc/classes/GDNativeClass.xml)2
-rw-r--r--modules/gdscript/gdscript.cpp (renamed from modules/gdscript/gd_script.cpp)164
-rw-r--r--modules/gdscript/gdscript.h (renamed from modules/gdscript/gd_script.h)73
-rw-r--r--modules/gdscript/gdscript_compiler.cpp (renamed from modules/gdscript/gd_compiler.cpp)582
-rw-r--r--modules/gdscript/gdscript_compiler.h (renamed from modules/gdscript/gd_compiler.h)46
-rw-r--r--modules/gdscript/gdscript_editor.cpp (renamed from modules/gdscript/gd_editor.cpp)584
-rw-r--r--modules/gdscript/gdscript_function.cpp (renamed from modules/gdscript/gd_function.cpp)208
-rw-r--r--modules/gdscript/gdscript_function.h (renamed from modules/gdscript/gd_function.h)40
-rw-r--r--modules/gdscript/gdscript_functions.cpp (renamed from modules/gdscript/gd_functions.cpp)73
-rw-r--r--modules/gdscript/gdscript_functions.h (renamed from modules/gdscript/gd_functions.h)14
-rw-r--r--modules/gdscript/gdscript_parser.cpp (renamed from modules/gdscript/gd_parser.cpp)810
-rw-r--r--modules/gdscript/gdscript_parser.h (renamed from modules/gdscript/gd_parser.h)22
-rw-r--r--modules/gdscript/gdscript_tokenizer.cpp (renamed from modules/gdscript/gd_tokenizer.cpp)208
-rw-r--r--modules/gdscript/gdscript_tokenizer.h (renamed from modules/gdscript/gd_tokenizer.h)31
-rw-r--r--modules/gdscript/register_types.cpp5
-rw-r--r--modules/gridmap/config.py9
-rw-r--r--modules/gridmap/doc_classes/GridMap.xml54
-rw-r--r--modules/gridmap/grid_map.cpp34
-rw-r--r--modules/gridmap/grid_map.h5
-rw-r--r--modules/gridmap/grid_map_editor_plugin.cpp193
-rw-r--r--modules/hdr/config.py2
-rw-r--r--modules/hdr/image_loader_hdr.cpp4
-rw-r--r--modules/jpg/config.py2
-rw-r--r--modules/mobile_vr/config.py12
-rw-r--r--modules/mobile_vr/doc_classes/MobileVRInterface.xml2
-rw-r--r--modules/mobile_vr/mobile_interface.cpp23
-rw-r--r--modules/mobile_vr/mobile_interface.h4
-rw-r--r--modules/mono/SCsub150
-rw-r--r--modules/mono/config.py95
-rw-r--r--modules/mono/csharp_script.cpp307
-rw-r--r--modules/mono/csharp_script.h17
-rw-r--r--modules/mono/doc_classes/@C#.xml2
-rw-r--r--modules/mono/doc_classes/CSharpScript.xml2
-rw-r--r--modules/mono/doc_classes/GodotSharp.xml2
-rw-r--r--modules/mono/editor/GodotSharpTools/Build/BuildSystem.cs66
-rw-r--r--modules/mono/editor/GodotSharpTools/GodotSharpTools.sln34
-rw-r--r--modules/mono/editor/bindings_generator.cpp1247
-rw-r--r--modules/mono/editor/bindings_generator.h7
-rw-r--r--modules/mono/editor/godotsharp_builds.cpp103
-rw-r--r--modules/mono/editor/godotsharp_builds.h9
-rw-r--r--modules/mono/editor/godotsharp_editor.cpp76
-rw-r--r--modules/mono/editor/godotsharp_editor.h24
-rw-r--r--modules/mono/editor/mono_bottom_panel.cpp37
-rw-r--r--modules/mono/editor/mono_bottom_panel.h4
-rw-r--r--modules/mono/glue/cs_files/AABB.cs (renamed from modules/mono/glue/cs_files/Rect3.cs)954
-rw-r--r--modules/mono/glue/cs_files/Basis.cs77
-rw-r--r--modules/mono/glue/cs_files/Color.cs1180
-rw-r--r--modules/mono/glue/cs_files/ExportAttribute.cs6
-rw-r--r--modules/mono/glue/cs_files/MarshalUtils.cs2
-rw-r--r--modules/mono/glue/cs_files/Mathf.cs10
-rw-r--r--modules/mono/glue/cs_files/Plane.cs418
-rw-r--r--modules/mono/glue/cs_files/Quat.cs4
-rw-r--r--modules/mono/glue/cs_files/ToolAttribute.cs2
-rw-r--r--modules/mono/glue/cs_files/Transform.cs8
-rw-r--r--modules/mono/glue/glue_header.h2
-rw-r--r--modules/mono/godotsharp_dirs.cpp28
-rw-r--r--modules/mono/mono_gc_handle.cpp4
-rw-r--r--modules/mono/mono_gd/gd_mono.cpp34
-rw-r--r--modules/mono/mono_gd/gd_mono_assembly.cpp13
-rw-r--r--modules/mono/mono_gd/gd_mono_class.cpp32
-rw-r--r--modules/mono/mono_gd/gd_mono_class.h6
-rw-r--r--modules/mono/mono_gd/gd_mono_field.cpp32
-rw-r--r--modules/mono/mono_gd/gd_mono_marshal.cpp109
-rw-r--r--modules/mono/mono_gd/gd_mono_marshal.h28
-rw-r--r--modules/mono/mono_gd/gd_mono_method.cpp41
-rw-r--r--modules/mono/mono_gd/gd_mono_utils.cpp14
-rw-r--r--modules/mono/mono_gd/gd_mono_utils.h16
-rw-r--r--modules/mono/mono_reg_utils.py94
-rw-r--r--modules/mono/register_types.cpp5
-rw-r--r--modules/mono/signal_awaiter_utils.cpp77
-rw-r--r--modules/mono/signal_awaiter_utils.h19
-rw-r--r--modules/mono/utils/path_utils.cpp6
-rw-r--r--modules/mono/utils/string_utils.cpp29
-rw-r--r--modules/mono/utils/string_utils.h6
-rw-r--r--modules/ogg/config.py5
-rw-r--r--modules/openssl/config.py2
-rw-r--r--modules/openssl/stream_peer_openssl.cpp6
-rw-r--r--modules/openssl/stream_peer_openssl.h2
-rw-r--r--modules/opus/SCsub11
-rw-r--r--modules/opus/audio_stream_opus.cpp6
-rw-r--r--modules/opus/audio_stream_opus.h2
-rw-r--r--modules/opus/config.py13
-rw-r--r--modules/opus/stub/register_types.cpp36
-rw-r--r--modules/opus/stub/register_types.h31
-rw-r--r--modules/pbm/config.py2
-rw-r--r--modules/pvr/config.py2
-rw-r--r--modules/recast/config.py2
-rw-r--r--modules/regex/SCsub2
-rw-r--r--modules/regex/config.py13
-rw-r--r--modules/regex/doc_classes/RegEx.xml134
-rw-r--r--modules/regex/doc_classes/RegExMatch.xml75
-rw-r--r--modules/regex/regex.cpp16
-rw-r--r--modules/regex/regex.h1
-rw-r--r--modules/squish/config.py2
-rw-r--r--modules/stb_vorbis/audio_stream_ogg_vorbis.cpp3
-rw-r--r--modules/stb_vorbis/config.py11
-rw-r--r--modules/stb_vorbis/doc_classes/AudioStreamOGGVorbis.xml (renamed from doc/classes/AudioStreamOGGVorbis.xml)2
-rw-r--r--modules/stb_vorbis/doc_classes/ResourceImporterOGGVorbis.xml (renamed from doc/classes/ResourceImporterOGGVorbis.xml)2
-rw-r--r--modules/svg/config.py2
-rw-r--r--modules/tga/config.py2
-rw-r--r--modules/theora/config.py14
-rw-r--r--modules/theora/doc_classes/ResourceImporterTheora.xml (renamed from doc/classes/VisualScriptWhile.xml)2
-rw-r--r--modules/theora/doc_classes/VideoStreamTheora.xml33
-rw-r--r--modules/theora/register_types.cpp13
-rw-r--r--modules/theora/resource_importer_theora.cpp89
-rw-r--r--modules/theora/resource_importer_theora.h57
-rw-r--r--modules/theora/video_stream_theora.cpp46
-rw-r--r--modules/theora/video_stream_theora.h16
-rw-r--r--modules/tinyexr/config.py2
-rw-r--r--modules/visual_script/config.py55
-rw-r--r--modules/visual_script/doc_classes/VisualScript.xml (renamed from doc/classes/VisualScript.xml)4
-rw-r--r--modules/visual_script/doc_classes/VisualScriptBasicTypeConstant.xml (renamed from doc/classes/VisualScriptBasicTypeConstant.xml)2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml (renamed from doc/classes/VisualScriptBuiltinFunc.xml)78
-rw-r--r--modules/visual_script/doc_classes/VisualScriptClassConstant.xml (renamed from doc/classes/VisualScriptClassConstant.xml)14
-rw-r--r--modules/visual_script/doc_classes/VisualScriptComment.xml (renamed from doc/classes/VisualScriptComment.xml)10
-rw-r--r--modules/visual_script/doc_classes/VisualScriptCondition.xml24
-rw-r--r--modules/visual_script/doc_classes/VisualScriptConstant.xml (renamed from doc/classes/VisualScriptConstant.xml)10
-rw-r--r--modules/visual_script/doc_classes/VisualScriptConstructor.xml (renamed from doc/classes/VisualScriptConstructor.xml)2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptCustomNode.xml (renamed from doc/classes/VisualScriptCustomNode.xml)2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptDeconstruct.xml (renamed from doc/classes/VisualScriptDeconstruct.xml)2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptEditor.xml46
-rw-r--r--modules/visual_script/doc_classes/VisualScriptEmitSignal.xml (renamed from doc/classes/VisualScriptEmitSignal.xml)10
-rw-r--r--modules/visual_script/doc_classes/VisualScriptEngineSingleton.xml (renamed from doc/classes/VisualScriptEngineSingleton.xml)2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptExpression.xml (renamed from doc/classes/VisualScriptExpression.xml)2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptFunction.xml (renamed from doc/classes/VisualScriptFunction.xml)2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptFunctionCall.xml (renamed from doc/classes/VisualScriptFunctionCall.xml)2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptFunctionState.xml (renamed from doc/classes/VisualScriptFunctionState.xml)2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptGlobalConstant.xml (renamed from doc/classes/VisualScriptGlobalConstant.xml)2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptIndexGet.xml (renamed from doc/classes/VisualScriptIndexGet.xml)2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptIndexSet.xml (renamed from doc/classes/VisualScriptIndexSet.xml)2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptInputAction.xml (renamed from doc/classes/VisualScriptInputAction.xml)2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptIterator.xml24
-rw-r--r--modules/visual_script/doc_classes/VisualScriptLocalVar.xml (renamed from doc/classes/VisualScriptLocalVar.xml)10
-rw-r--r--modules/visual_script/doc_classes/VisualScriptLocalVarSet.xml (renamed from doc/classes/VisualScriptLocalVarSet.xml)12
-rw-r--r--modules/visual_script/doc_classes/VisualScriptMathConstant.xml (renamed from doc/classes/VisualScriptMathConstant.xml)21
-rw-r--r--modules/visual_script/doc_classes/VisualScriptNode.xml (renamed from doc/classes/VisualScriptNode.xml)2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptOperator.xml (renamed from doc/classes/VisualScriptOperator.xml)7
-rw-r--r--modules/visual_script/doc_classes/VisualScriptPreload.xml (renamed from doc/classes/VisualScriptPreload.xml)9
-rw-r--r--modules/visual_script/doc_classes/VisualScriptPropertyGet.xml (renamed from doc/classes/VisualScriptPropertyGet.xml)2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptPropertySet.xml (renamed from doc/classes/VisualScriptPropertySet.xml)2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptResourcePath.xml (renamed from doc/classes/VisualScriptResourcePath.xml)2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptReturn.xml (renamed from doc/classes/VisualScriptReturn.xml)11
-rw-r--r--modules/visual_script/doc_classes/VisualScriptSceneNode.xml (renamed from doc/classes/VisualScriptSceneNode.xml)9
-rw-r--r--modules/visual_script/doc_classes/VisualScriptSceneTree.xml (renamed from doc/classes/VisualScriptSceneTree.xml)2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptSelect.xml (renamed from doc/classes/VisualScriptSelect.xml)11
-rw-r--r--modules/visual_script/doc_classes/VisualScriptSelf.xml21
-rw-r--r--modules/visual_script/doc_classes/VisualScriptSequence.xml (renamed from doc/classes/VisualScriptSequence.xml)11
-rw-r--r--modules/visual_script/doc_classes/VisualScriptSubCall.xml (renamed from doc/classes/VisualScriptSubCall.xml)2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptSwitch.xml26
-rw-r--r--modules/visual_script/doc_classes/VisualScriptTypeCast.xml (renamed from doc/classes/VisualScriptTypeCast.xml)2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptVariableGet.xml (renamed from doc/classes/VisualScriptVariableGet.xml)9
-rw-r--r--modules/visual_script/doc_classes/VisualScriptVariableSet.xml (renamed from doc/classes/VisualScriptVariableSet.xml)10
-rw-r--r--modules/visual_script/doc_classes/VisualScriptWhile.xml23
-rw-r--r--modules/visual_script/doc_classes/VisualScriptYield.xml (renamed from doc/classes/VisualScriptYield.xml)4
-rw-r--r--modules/visual_script/doc_classes/VisualScriptYieldSignal.xml (renamed from doc/classes/VisualScriptYieldSignal.xml)2
-rw-r--r--modules/visual_script/register_types.cpp11
-rw-r--r--modules/visual_script/visual_script.cpp14
-rw-r--r--modules/visual_script/visual_script.h4
-rw-r--r--modules/visual_script/visual_script_builtin_funcs.cpp137
-rw-r--r--modules/visual_script/visual_script_builtin_funcs.h7
-rw-r--r--modules/visual_script/visual_script_editor.cpp66
-rw-r--r--modules/visual_script/visual_script_editor.h23
-rw-r--r--modules/visual_script/visual_script_expression.cpp3
-rw-r--r--modules/visual_script/visual_script_func_nodes.cpp18
-rw-r--r--modules/visual_script/visual_script_nodes.cpp18
-rw-r--r--modules/visual_script/visual_script_nodes.h2
-rw-r--r--modules/visual_script/visual_script_yield_nodes.cpp4
-rw-r--r--modules/vorbis/SCsub10
-rw-r--r--modules/vorbis/audio_stream_ogg_vorbis.cpp12
-rw-r--r--modules/vorbis/audio_stream_ogg_vorbis.h4
-rw-r--r--modules/vorbis/config.py5
-rw-r--r--modules/vorbis/stub/register_types.cpp36
-rw-r--r--modules/vorbis/stub/register_types.h31
-rw-r--r--modules/webm/config.py14
-rw-r--r--modules/webm/doc_classes/ResourceImporterWebm.xml (renamed from doc/classes/VisualScriptSwitch.xml)2
-rw-r--r--modules/webm/doc_classes/VideoStreamWebm.xml33
-rw-r--r--modules/webm/libvpx/SCsub4
-rw-r--r--modules/webm/register_types.cpp13
-rw-r--r--modules/webm/resource_importer_webm.cpp95
-rw-r--r--modules/webm/resource_importer_webm.h55
-rw-r--r--modules/webm/video_stream_webm.cpp153
-rw-r--r--modules/webm/video_stream_webm.h23
-rw-r--r--modules/webp/config.py2
-rw-r--r--platform/SCsub30
-rw-r--r--platform/android/SCsub12
-rw-r--r--platform/android/build.gradle.template7
-rw-r--r--platform/android/detect.py49
-rw-r--r--platform/android/export/export.cpp16
-rw-r--r--platform/android/globals/global_defaults.cpp8
-rw-r--r--platform/android/godot_android.cpp28
-rw-r--r--platform/android/java/gradlew.bat180
-rw-r--r--platform/android/java/src/org/godotengine/godot/Godot.java23
-rw-r--r--platform/android/java/src/org/godotengine/godot/GodotLib.java1
-rw-r--r--platform/android/java/src/org/godotengine/godot/GodotView.java8
-rw-r--r--platform/android/java/src/org/godotengine/godot/input/GodotTextInputWrapper.java73
-rw-r--r--platform/android/java_glue.cpp79
-rw-r--r--platform/android/java_glue.h1
-rw-r--r--platform/android/os_android.cpp57
-rw-r--r--platform/android/os_android.h17
-rw-r--r--platform/android/platform_config.h1
-rw-r--r--platform/haiku/context_gl_haiku.cpp2
-rw-r--r--platform/haiku/context_gl_haiku.h2
-rw-r--r--platform/haiku/detect.py2
-rw-r--r--platform/haiku/os_haiku.cpp60
-rw-r--r--platform/haiku/os_haiku.h11
-rw-r--r--platform/iphone/SCsub12
-rw-r--r--platform/iphone/app_delegate.mm20
-rw-r--r--platform/iphone/detect.py50
-rw-r--r--platform/iphone/export/export.cpp473
-rw-r--r--platform/iphone/game_center.h9
-rw-r--r--platform/iphone/game_center.mm86
-rw-r--r--platform/iphone/globals/global_defaults.cpp7
-rw-r--r--platform/iphone/godot_iphone.cpp7
-rw-r--r--platform/iphone/in_app_store.mm3
-rw-r--r--platform/iphone/os_iphone.cpp120
-rw-r--r--platform/iphone/os_iphone.h19
-rw-r--r--platform/iphone/platform_config.h2
-rw-r--r--platform/javascript/SCsub34
-rw-r--r--platform/javascript/api/api.cpp73
-rw-r--r--platform/javascript/api/api.h31
-rw-r--r--platform/javascript/api/javascript_eval.h (renamed from platform/javascript/javascript_eval.h)3
-rw-r--r--platform/javascript/audio_driver_javascript.cpp79
-rw-r--r--platform/javascript/audio_driver_javascript.h15
-rw-r--r--platform/javascript/audio_server_javascript.cpp853
-rw-r--r--platform/javascript/audio_server_javascript.h229
-rw-r--r--platform/javascript/detect.py25
-rw-r--r--platform/javascript/engine.js219
-rw-r--r--platform/javascript/export/export.cpp134
-rw-r--r--platform/javascript/http_client.h.inc48
-rw-r--r--platform/javascript/http_client_javascript.cpp282
-rw-r--r--platform/javascript/http_request.h74
-rw-r--r--platform/javascript/http_request.js145
-rw-r--r--platform/javascript/javascript_eval.cpp99
-rw-r--r--platform/javascript/javascript_main.cpp1
-rw-r--r--platform/javascript/os_javascript.cpp69
-rw-r--r--platform/javascript/os_javascript.h21
-rw-r--r--platform/javascript/pre.js (renamed from platform/javascript/pre_wasm.js)1
-rw-r--r--platform/javascript/pre_asmjs.js3
-rw-r--r--platform/osx/crash_handler_osx.mm1
-rw-r--r--platform/osx/detect.py13
-rw-r--r--platform/osx/export/export.cpp459
-rw-r--r--platform/osx/os_osx.h29
-rw-r--r--platform/osx/os_osx.mm346
-rw-r--r--platform/register_platform_apis.h36
-rw-r--r--platform/server/detect.py3
-rw-r--r--platform/server/os_server.cpp18
-rw-r--r--platform/server/os_server.h6
-rw-r--r--platform/uwp/SCsub1
-rw-r--r--platform/uwp/app.h1
-rw-r--r--platform/uwp/detect.py4
-rw-r--r--platform/uwp/export/export.cpp6
-rw-r--r--platform/uwp/gl_context_egl.cpp39
-rw-r--r--platform/uwp/os_uwp.cpp38
-rw-r--r--platform/uwp/os_uwp.h11
-rw-r--r--platform/windows/context_gl_win.cpp19
-rw-r--r--platform/windows/context_gl_win.h13
-rw-r--r--platform/windows/crash_handler_win.cpp1
-rw-r--r--platform/windows/detect.py7
-rw-r--r--platform/windows/godot_res.rc8
-rw-r--r--platform/windows/key_mapping_win.cpp2
-rw-r--r--platform/windows/os_windows.cpp90
-rw-r--r--platform/windows/os_windows.h20
-rw-r--r--platform/x11/context_gl_x11.cpp2
-rw-r--r--platform/x11/context_gl_x11.h2
-rw-r--r--platform/x11/crash_handler_x11.cpp1
-rw-r--r--platform/x11/detect.py10
-rw-r--r--platform/x11/os_x11.cpp188
-rw-r--r--platform/x11/os_x11.h17
-rw-r--r--scene/2d/animated_sprite.cpp16
-rw-r--r--scene/2d/animated_sprite.h8
-rw-r--r--scene/2d/back_buffer_copy.cpp2
-rw-r--r--scene/2d/back_buffer_copy.h4
-rw-r--r--scene/2d/camera_2d.cpp8
-rw-r--r--scene/2d/canvas_item.cpp56
-rw-r--r--scene/2d/canvas_item.h37
-rw-r--r--scene/2d/collision_polygon_2d.cpp2
-rw-r--r--scene/2d/collision_polygon_2d.h2
-rw-r--r--scene/2d/collision_shape_2d.cpp2
-rw-r--r--scene/2d/collision_shape_2d.h3
-rw-r--r--scene/2d/joints_2d.cpp107
-rw-r--r--scene/2d/joints_2d.h13
-rw-r--r--scene/2d/light_2d.cpp8
-rw-r--r--scene/2d/light_2d.h9
-rw-r--r--scene/2d/navigation_polygon.cpp4
-rw-r--r--scene/2d/node_2d.cpp118
-rw-r--r--scene/2d/node_2d.h30
-rw-r--r--scene/2d/parallax_background.cpp10
-rw-r--r--scene/2d/parallax_background.h3
-rw-r--r--scene/2d/parallax_layer.cpp20
-rw-r--r--scene/2d/parallax_layer.h4
-rw-r--r--scene/2d/particles_2d.cpp6
-rw-r--r--scene/2d/path_2d.cpp46
-rw-r--r--scene/2d/path_2d.h5
-rw-r--r--scene/2d/physics_body_2d.cpp12
-rw-r--r--scene/2d/polygon_2d.cpp18
-rw-r--r--scene/2d/polygon_2d.h14
-rw-r--r--scene/2d/position_2d.cpp2
-rw-r--r--scene/2d/position_2d.h2
-rw-r--r--scene/2d/ray_cast_2d.cpp36
-rw-r--r--scene/2d/ray_cast_2d.h9
-rw-r--r--scene/2d/screen_button.cpp8
-rw-r--r--scene/2d/screen_button.h2
-rw-r--r--scene/2d/sprite.cpp231
-rw-r--r--scene/2d/sprite.h53
-rw-r--r--scene/2d/tile_map.cpp33
-rw-r--r--scene/2d/tile_map.h6
-rw-r--r--scene/2d/visibility_notifier_2d.cpp6
-rw-r--r--scene/2d/visibility_notifier_2d.h4
-rw-r--r--scene/3d/SCsub3
-rw-r--r--scene/3d/arvr_nodes.cpp33
-rw-r--r--scene/3d/arvr_nodes.h3
-rw-r--r--scene/3d/audio_stream_player_3d.cpp2
-rw-r--r--scene/3d/camera.cpp2
-rw-r--r--scene/3d/collision_polygon.cpp4
-rw-r--r--scene/3d/collision_polygon.h4
-rw-r--r--scene/3d/gi_probe.cpp87
-rw-r--r--scene/3d/gi_probe.h22
-rw-r--r--scene/3d/immediate_geometry.cpp2
-rw-r--r--scene/3d/immediate_geometry.h4
-rw-r--r--scene/3d/light.cpp29
-rw-r--r--scene/3d/light.h3
-rw-r--r--scene/3d/mesh_instance.cpp4
-rw-r--r--scene/3d/mesh_instance.h2
-rw-r--r--scene/3d/multimesh_instance.cpp4
-rw-r--r--scene/3d/multimesh_instance.h2
-rw-r--r--scene/3d/particles.cpp360
-rw-r--r--scene/3d/particles.h12
-rw-r--r--scene/3d/path.cpp52
-rw-r--r--scene/3d/path.h5
-rw-r--r--scene/3d/physics_body.cpp20
-rw-r--r--scene/3d/physics_joint.cpp31
-rw-r--r--scene/3d/portal.cpp2
-rw-r--r--scene/3d/portal.h4
-rw-r--r--scene/3d/ray_cast.cpp36
-rw-r--r--scene/3d/ray_cast.h9
-rw-r--r--scene/3d/reflection_probe.cpp4
-rw-r--r--scene/3d/reflection_probe.h2
-rw-r--r--scene/3d/room_instance.cpp6
-rw-r--r--scene/3d/room_instance.h2
-rw-r--r--scene/3d/spatial.cpp32
-rw-r--r--scene/3d/spatial.h8
-rw-r--r--scene/3d/sprite_3d.cpp6
-rw-r--r--scene/3d/sprite_3d.h6
-rw-r--r--scene/3d/visibility_notifier.cpp10
-rw-r--r--scene/3d/visibility_notifier.h6
-rw-r--r--scene/3d/visual_instance.cpp2
-rw-r--r--scene/3d/visual_instance.h4
-rw-r--r--scene/animation/animation_player.cpp36
-rw-r--r--scene/animation/animation_tree_player.cpp2
-rw-r--r--scene/animation/tween.cpp18
-rw-r--r--scene/audio/audio_player.cpp50
-rw-r--r--scene/audio/audio_player.h1
-rw-r--r--scene/gui/check_button.cpp23
-rw-r--r--scene/gui/check_button.h1
-rw-r--r--scene/gui/color_picker.cpp4
-rw-r--r--scene/gui/control.cpp202
-rw-r--r--scene/gui/control.h39
-rw-r--r--scene/gui/file_dialog.cpp38
-rw-r--r--scene/gui/graph_edit.cpp23
-rw-r--r--scene/gui/graph_edit.h1
-rw-r--r--scene/gui/item_list.cpp22
-rw-r--r--scene/gui/line_edit.cpp128
-rw-r--r--scene/gui/line_edit.h17
-rw-r--r--scene/gui/nine_patch_rect.cpp (renamed from scene/gui/patch_9_rect.cpp)4
-rw-r--r--scene/gui/nine_patch_rect.h (renamed from scene/gui/patch_9_rect.h)8
-rw-r--r--scene/gui/rich_text_label.cpp60
-rw-r--r--scene/gui/rich_text_label.h7
-rw-r--r--scene/gui/scroll_container.cpp16
-rw-r--r--scene/gui/separator.cpp6
-rw-r--r--scene/gui/slider.cpp6
-rw-r--r--scene/gui/tab_container.cpp16
-rw-r--r--scene/gui/tabs.cpp163
-rw-r--r--scene/gui/tabs.h7
-rw-r--r--scene/gui/text_edit.cpp972
-rw-r--r--scene/gui/text_edit.h62
-rw-r--r--scene/gui/tree.cpp77
-rw-r--r--scene/gui/tree.h1
-rw-r--r--scene/gui/video_player.cpp144
-rw-r--r--scene/gui/video_player.h22
-rw-r--r--scene/gui/viewport_container.cpp35
-rw-r--r--scene/gui/viewport_container.h4
-rw-r--r--scene/main/canvas_layer.cpp28
-rw-r--r--scene/main/canvas_layer.h8
-rw-r--r--scene/main/http_request.cpp1
-rwxr-xr-xscene/main/node.cpp66
-rw-r--r--scene/main/node.h10
-rw-r--r--scene/main/scene_tree.cpp9
-rw-r--r--scene/main/scene_tree.h6
-rwxr-xr-xscene/main/timer.cpp2
-rw-r--r--scene/main/viewport.cpp35
-rw-r--r--scene/register_scene_types.cpp19
-rw-r--r--scene/resources/animation.cpp29
-rw-r--r--scene/resources/audio_stream_sample.cpp35
-rw-r--r--scene/resources/box_shape.cpp2
-rw-r--r--scene/resources/capsule_shape_2d.cpp2
-rw-r--r--scene/resources/circle_shape_2d.cpp2
-rw-r--r--scene/resources/concave_polygon_shape_2d.cpp2
-rw-r--r--scene/resources/convex_polygon_shape_2d.cpp2
-rw-r--r--scene/resources/default_theme/default_theme.cpp37
-rw-r--r--scene/resources/dynamic_font.cpp2
-rw-r--r--scene/resources/dynamic_font_stb.cpp5
-rw-r--r--scene/resources/environment.cpp76
-rw-r--r--scene/resources/environment.h29
-rw-r--r--scene/resources/material.cpp38
-rw-r--r--scene/resources/material.h14
-rw-r--r--scene/resources/mesh.cpp46
-rw-r--r--scene/resources/mesh.h23
-rw-r--r--scene/resources/multimesh.cpp2
-rw-r--r--scene/resources/multimesh.h2
-rw-r--r--scene/resources/primitive_meshes.cpp42
-rw-r--r--scene/resources/primitive_meshes.h9
-rw-r--r--scene/resources/rectangle_shape_2d.cpp2
-rw-r--r--scene/resources/scene_format_text.cpp2
-rw-r--r--scene/resources/segment_shape_2d.cpp4
-rw-r--r--scene/resources/shader.cpp2
-rw-r--r--scene/resources/shape_line_2d.cpp2
-rw-r--r--scene/resources/style_box.cpp2
-rw-r--r--scene/resources/texture.cpp30
-rw-r--r--scene/resources/texture.h4
-rw-r--r--scene/resources/tile_set.cpp20
-rw-r--r--scene/resources/tile_set.h3
-rw-r--r--scene/resources/video_stream.h6
-rw-r--r--scene/resources/world.cpp10
-rw-r--r--scene/resources/world.h4
-rw-r--r--scene/scene_string_names.cpp2
-rw-r--r--servers/arvr/arvr_interface.cpp2
-rw-r--r--servers/arvr/arvr_interface.h2
-rw-r--r--servers/arvr/arvr_positional_tracker.cpp18
-rw-r--r--servers/arvr/arvr_positional_tracker.h3
-rw-r--r--servers/arvr/arvr_script_interface.cpp136
-rw-r--r--servers/arvr/arvr_script_interface.h52
-rw-r--r--servers/arvr_server.cpp25
-rw-r--r--servers/arvr_server.h1
-rw-r--r--servers/audio/audio_rb_resampler.cpp210
-rw-r--r--servers/audio/audio_rb_resampler.h49
-rw-r--r--servers/audio/audio_stream.cpp6
-rw-r--r--servers/audio/audio_stream.h6
-rw-r--r--servers/audio/effects/audio_effect_filter.cpp2
-rw-r--r--servers/audio_server.cpp4
-rw-r--r--servers/physics/body_pair_sw.cpp38
-rw-r--r--servers/physics/body_pair_sw.h1
-rw-r--r--servers/physics/body_sw.cpp10
-rw-r--r--servers/physics/body_sw.h14
-rw-r--r--servers/physics/broad_phase_basic.cpp10
-rw-r--r--servers/physics/broad_phase_basic.h6
-rw-r--r--servers/physics/broad_phase_octree.cpp6
-rw-r--r--servers/physics/broad_phase_octree.h4
-rw-r--r--servers/physics/broad_phase_sw.h6
-rw-r--r--servers/physics/collision_object_sw.cpp6
-rw-r--r--servers/physics/collision_object_sw.h4
-rw-r--r--servers/physics/collision_solver_sw.cpp10
-rw-r--r--servers/physics/collision_solver_sw.h2
-rw-r--r--servers/physics/joints/generic_6dof_joint_sw.cpp4
-rw-r--r--servers/physics/joints/pin_joint_sw.h4
-rw-r--r--servers/physics/physics_server_sw.cpp46
-rw-r--r--servers/physics/physics_server_sw.h8
-rw-r--r--servers/physics/shape_sw.cpp36
-rw-r--r--servers/physics/shape_sw.h18
-rw-r--r--servers/physics/space_sw.cpp48
-rw-r--r--servers/physics/space_sw.h14
-rw-r--r--servers/physics_2d/collision_object_2d_sw.h45
-rw-r--r--servers/physics_2d/physics_2d_server_sw.cpp76
-rw-r--r--servers/physics_2d/physics_2d_server_sw.h18
-rw-r--r--servers/physics_2d/physics_2d_server_wrap_mt.cpp27
-rw-r--r--servers/physics_2d/physics_2d_server_wrap_mt.h40
-rw-r--r--servers/physics_2d/space_2d_sw.cpp58
-rw-r--r--servers/physics_2d/space_2d_sw.h12
-rw-r--r--servers/physics_2d_server.cpp84
-rw-r--r--servers/physics_2d_server.h52
-rw-r--r--servers/physics_server.cpp77
-rw-r--r--servers/physics_server.h47
-rw-r--r--servers/register_server_types.cpp54
-rw-r--r--servers/register_server_types.h2
-rw-r--r--servers/server_wrap_mt_common.h9
-rw-r--r--servers/visual/rasterizer.h44
-rw-r--r--servers/visual/shader_language.cpp2
-rw-r--r--servers/visual/visual_server_canvas.h2
-rw-r--r--servers/visual/visual_server_raster.cpp12
-rw-r--r--servers/visual/visual_server_raster.h559
-rw-r--r--servers/visual/visual_server_scene.cpp63
-rw-r--r--servers/visual/visual_server_scene.h13
-rw-r--r--servers/visual/visual_server_viewport.cpp5
-rw-r--r--servers/visual/visual_server_viewport.h3
-rw-r--r--servers/visual/visual_server_wrap_mt.cpp26
-rw-r--r--servers/visual/visual_server_wrap_mt.h71
-rw-r--r--servers/visual_server.cpp429
-rw-r--r--servers/visual_server.h68
-rw-r--r--thirdparty/README.md6
-rw-r--r--thirdparty/bullet/src/Bullet3Collision/BroadPhaseCollision/b3BroadphaseCallback.h40
-rw-r--r--thirdparty/bullet/src/Bullet3Collision/BroadPhaseCollision/b3DynamicBvh.cpp1325
-rw-r--r--thirdparty/bullet/src/Bullet3Collision/BroadPhaseCollision/b3DynamicBvh.h1269
-rw-r--r--thirdparty/bullet/src/Bullet3Collision/BroadPhaseCollision/b3DynamicBvhBroadphase.cpp804
-rw-r--r--thirdparty/bullet/src/Bullet3Collision/BroadPhaseCollision/b3DynamicBvhBroadphase.h206
-rw-r--r--thirdparty/bullet/src/Bullet3Collision/BroadPhaseCollision/b3OverlappingPair.h72
-rw-r--r--thirdparty/bullet/src/Bullet3Collision/BroadPhaseCollision/b3OverlappingPairCache.cpp638
-rw-r--r--thirdparty/bullet/src/Bullet3Collision/BroadPhaseCollision/b3OverlappingPairCache.h474
-rw-r--r--thirdparty/bullet/src/Bullet3Collision/BroadPhaseCollision/shared/b3Aabb.h59
-rw-r--r--thirdparty/bullet/src/Bullet3Collision/CMakeLists.txt93
-rw-r--r--thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/b3Config.h41
-rw-r--r--thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/b3Contact4.h46
-rw-r--r--thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/b3ConvexUtility.cpp520
-rw-r--r--thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/b3ConvexUtility.h62
-rw-r--r--thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/b3CpuNarrowPhase.cpp323
-rw-r--r--thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/b3CpuNarrowPhase.h105
-rw-r--r--thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/b3RaycastInfo.h24
-rw-r--r--thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/b3RigidBodyCL.h30
-rw-r--r--thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3BvhSubtreeInfoData.h20
-rw-r--r--thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3BvhTraversal.h126
-rw-r--r--thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3ClipFaces.h188
-rw-r--r--thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h76
-rw-r--r--thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h40
-rw-r--r--thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3ContactConvexConvexSAT.h520
-rw-r--r--thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3ContactSphereSphere.h162
-rw-r--r--thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h40
-rw-r--r--thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3FindConcaveSatAxis.h832
-rw-r--r--thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3FindSeparatingAxis.h206
-rw-r--r--thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3MprPenetration.h920
-rw-r--r--thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3NewContactReduction.h196
-rw-r--r--thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3QuantizedBvhNodeData.h90
-rw-r--r--thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3ReduceContacts.h97
-rw-r--r--thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h34
-rw-r--r--thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3UpdateAabbs.h40
-rw-r--r--thirdparty/bullet/src/Bullet3Collision/premake4.lua13
-rw-r--r--thirdparty/bullet/src/Bullet3Common/CMakeLists.txt63
-rw-r--r--thirdparty/bullet/src/Bullet3Common/b3AlignedAllocator.cpp181
-rw-r--r--thirdparty/bullet/src/Bullet3Common/b3AlignedAllocator.h107
-rw-r--r--thirdparty/bullet/src/Bullet3Common/b3AlignedObjectArray.h533
-rw-r--r--thirdparty/bullet/src/Bullet3Common/b3CommandLineArgs.h101
-rw-r--r--thirdparty/bullet/src/Bullet3Common/b3FileUtils.h138
-rw-r--r--thirdparty/bullet/src/Bullet3Common/b3HashMap.h466
-rw-r--r--thirdparty/bullet/src/Bullet3Common/b3Logging.cpp160
-rw-r--r--thirdparty/bullet/src/Bullet3Common/b3Logging.h77
-rw-r--r--thirdparty/bullet/src/Bullet3Common/b3Matrix3x3.h1362
-rw-r--r--thirdparty/bullet/src/Bullet3Common/b3MinMax.h71
-rw-r--r--thirdparty/bullet/src/Bullet3Common/b3PoolAllocator.h121
-rw-r--r--thirdparty/bullet/src/Bullet3Common/b3QuadWord.h245
-rw-r--r--thirdparty/bullet/src/Bullet3Common/b3Quaternion.h918
-rw-r--r--thirdparty/bullet/src/Bullet3Common/b3Random.h50
-rw-r--r--thirdparty/bullet/src/Bullet3Common/b3ResizablePool.h182
-rw-r--r--thirdparty/bullet/src/Bullet3Common/b3Scalar.h663
-rw-r--r--thirdparty/bullet/src/Bullet3Common/b3StackAlloc.h116
-rw-r--r--thirdparty/bullet/src/Bullet3Common/b3Transform.h304
-rw-r--r--thirdparty/bullet/src/Bullet3Common/b3TransformUtil.h228
-rw-r--r--thirdparty/bullet/src/Bullet3Common/b3Vector3.cpp1631
-rw-r--r--thirdparty/bullet/src/Bullet3Common/b3Vector3.h1344
-rw-r--r--thirdparty/bullet/src/Bullet3Common/premake4.lua12
-rw-r--r--thirdparty/bullet/src/Bullet3Common/shared/b3Float4.h97
-rw-r--r--thirdparty/bullet/src/Bullet3Common/shared/b3Int2.h64
-rw-r--r--thirdparty/bullet/src/Bullet3Common/shared/b3Int4.h68
-rw-r--r--thirdparty/bullet/src/Bullet3Common/shared/b3Mat3x3.h179
-rw-r--r--thirdparty/bullet/src/Bullet3Common/shared/b3PlatformDefinitions.h41
-rw-r--r--thirdparty/bullet/src/Bullet3Common/shared/b3Quat.h103
-rw-r--r--thirdparty/bullet/src/Bullet3Dynamics/CMakeLists.txt61
-rw-r--r--thirdparty/bullet/src/Bullet3Dynamics/ConstraintSolver/b3ContactSolverInfo.h159
-rw-r--r--thirdparty/bullet/src/Bullet3Dynamics/ConstraintSolver/b3FixedConstraint.cpp108
-rw-r--r--thirdparty/bullet/src/Bullet3Dynamics/ConstraintSolver/b3FixedConstraint.h35
-rw-r--r--thirdparty/bullet/src/Bullet3Dynamics/ConstraintSolver/b3Generic6DofConstraint.cpp807
-rw-r--r--thirdparty/bullet/src/Bullet3Dynamics/ConstraintSolver/b3Generic6DofConstraint.h550
-rw-r--r--thirdparty/bullet/src/Bullet3Dynamics/ConstraintSolver/b3JacobianEntry.h155
-rw-r--r--thirdparty/bullet/src/Bullet3Dynamics/ConstraintSolver/b3PgsJacobiSolver.cpp1815
-rw-r--r--thirdparty/bullet/src/Bullet3Dynamics/ConstraintSolver/b3PgsJacobiSolver.h149
-rw-r--r--thirdparty/bullet/src/Bullet3Dynamics/ConstraintSolver/b3Point2PointConstraint.cpp209
-rw-r--r--thirdparty/bullet/src/Bullet3Dynamics/ConstraintSolver/b3Point2PointConstraint.h159
-rw-r--r--thirdparty/bullet/src/Bullet3Dynamics/ConstraintSolver/b3SolverBody.h302
-rw-r--r--thirdparty/bullet/src/Bullet3Dynamics/ConstraintSolver/b3SolverConstraint.h80
-rw-r--r--thirdparty/bullet/src/Bullet3Dynamics/ConstraintSolver/b3TypedConstraint.cpp161
-rw-r--r--thirdparty/bullet/src/Bullet3Dynamics/ConstraintSolver/b3TypedConstraint.h483
-rw-r--r--thirdparty/bullet/src/Bullet3Dynamics/b3CpuRigidBodyPipeline.cpp488
-rw-r--r--thirdparty/bullet/src/Bullet3Dynamics/b3CpuRigidBodyPipeline.h67
-rw-r--r--thirdparty/bullet/src/Bullet3Dynamics/premake4.lua15
-rw-r--r--thirdparty/bullet/src/Bullet3Dynamics/shared/b3ContactConstraint4.h34
-rw-r--r--thirdparty/bullet/src/Bullet3Dynamics/shared/b3ConvertConstraint4.h153
-rw-r--r--thirdparty/bullet/src/Bullet3Dynamics/shared/b3Inertia.h15
-rw-r--r--thirdparty/bullet/src/Bullet3Dynamics/shared/b3IntegrateTransforms.h113
-rw-r--r--thirdparty/bullet/src/Bullet3Geometry/CMakeLists.txt47
-rw-r--r--thirdparty/bullet/src/Bullet3Geometry/b3AabbUtil.h232
-rw-r--r--thirdparty/bullet/src/Bullet3Geometry/b3ConvexHullComputer.cpp2755
-rw-r--r--thirdparty/bullet/src/Bullet3Geometry/b3ConvexHullComputer.h103
-rw-r--r--thirdparty/bullet/src/Bullet3Geometry/b3GeometryUtil.cpp185
-rw-r--r--thirdparty/bullet/src/Bullet3Geometry/b3GeometryUtil.h42
-rw-r--r--thirdparty/bullet/src/Bullet3Geometry/b3GrahamScan2dConvexHull.h117
-rw-r--r--thirdparty/bullet/src/Bullet3Geometry/premake4.lua13
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/b3GpuBroadphaseInterface.h44
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/b3GpuGridBroadphase.cpp385
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/b3GpuGridBroadphase.h88
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvh.cpp577
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvh.h125
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvhBroadphase.cpp80
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvhBroadphase.h66
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/b3GpuSapBroadphase.cpp1366
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/b3GpuSapBroadphase.h151
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/b3SapAabb.h14
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/kernels/gridBroadphase.cl216
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/kernels/gridBroadphaseKernels.h199
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/kernels/parallelLinearBvh.cl767
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/kernels/parallelLinearBvhKernels.h729
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/kernels/sap.cl389
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/kernels/sapKernels.h342
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/CMakeLists.txt77
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/Initialize/b3OpenCLInclude.h48
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/Initialize/b3OpenCLUtils.cpp1011
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/Initialize/b3OpenCLUtils.h194
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3BvhInfo.h18
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3ContactCache.cpp258
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3ContactCache.h80
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3ConvexHullContact.cpp4733
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3ConvexHullContact.h118
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3ConvexPolyhedronCL.h9
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3GjkEpa.cpp1014
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3GjkEpa.h82
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3OptimizedBvh.cpp390
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3OptimizedBvh.h65
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3QuantizedBvh.cpp1301
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3QuantizedBvh.h556
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3StridingMeshInterface.cpp214
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3StridingMeshInterface.h167
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3SupportMappings.h38
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3TriangleCallback.cpp28
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3TriangleCallback.h42
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3TriangleIndexVertexArray.cpp95
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3TriangleIndexVertexArray.h133
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3VectorFloat4.h11
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3VoronoiSimplexSolver.cpp609
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3VoronoiSimplexSolver.h177
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/kernels/bvhTraversal.cl283
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/kernels/bvhTraversal.h258
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/kernels/mpr.cl311
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/kernels/mprKernels.h1446
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/kernels/primitiveContacts.cl1374
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/kernels/primitiveContacts.h1289
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/kernels/sat.cl2018
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/kernels/satClipHullContacts.cl1888
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/kernels/satClipHullContacts.h2099
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/kernels/satConcave.cl1220
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/kernels/satConcaveKernels.h1457
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/kernels/satKernels.h2104
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/b3BoundSearchCL.cpp213
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/b3BoundSearchCL.h67
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/b3BufferInfoCL.h19
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/b3FillCL.cpp126
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/b3FillCL.h63
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.cpp308
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.h135
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h306
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanCL.cpp126
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanCL.h37
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanFloat4CL.cpp126
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanFloat4CL.h38
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.cpp710
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.h95
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/kernels/BoundSearchKernels.cl106
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/kernels/BoundSearchKernelsCL.h87
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/kernels/CopyKernels.cl128
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/kernels/CopyKernelsCL.h132
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/kernels/FillKernels.cl107
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/kernels/FillKernelsCL.h91
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanFloat4Kernels.cl154
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanKernels.cl154
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanKernelsCL.h129
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanKernelsFloat4CL.h129
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/kernels/RadixSort32Kernels.cl1071
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/kernels/RadixSort32KernelsCL.h910
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/Raycast/b3GpuRaycast.cpp391
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/Raycast/b3GpuRaycast.h32
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/Raycast/kernels/rayCastKernels.cl439
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/Raycast/kernels/rayCastKernels.h381
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuConstraint4.h18
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuGenericConstraint.cpp137
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuGenericConstraint.h132
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuJacobiContactSolver.cpp1382
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuJacobiContactSolver.h62
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuNarrowPhase.cpp1107
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuNarrowPhase.h109
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuNarrowPhaseInternalData.h95
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuPgsConstraintSolver.cpp1158
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuPgsConstraintSolver.h78
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuPgsContactSolver.cpp1708
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuPgsContactSolver.h43
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuRigidBodyPipeline.cpp708
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuRigidBodyPipeline.h74
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuRigidBodyPipelineInternalData.h73
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuSolverBody.h228
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuSolverConstraint.h82
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3Solver.cpp1225
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3Solver.h126
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/batchingKernels.cl353
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/batchingKernels.h388
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/batchingKernelsNew.cl231
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/batchingKernelsNew.h291
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/integrateKernel.cl32
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/integrateKernel.h433
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/jointSolver.cl877
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/jointSolver.h721
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/solveContact.cl501
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/solveContact.h393
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/solveFriction.cl527
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/solveFriction.h421
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/solverSetup.cl277
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/solverSetup.h703
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/solverSetup2.cl613
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/solverSetup2.h601
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/solverUtils.cl968
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/solverUtils.h909
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/updateAabbsKernel.cl22
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/updateAabbsKernel.h483
-rw-r--r--thirdparty/bullet/src/Bullet3OpenCL/premake4.lua29
-rw-r--r--thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/CMakeLists.txt55
-rw-r--r--thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/autogenerated/bullet2.h1053
-rw-r--r--thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/b3BulletFile.cpp423
-rw-r--r--thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/b3BulletFile.h83
-rw-r--r--thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/b3Chunk.cpp75
-rw-r--r--thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/b3Chunk.h92
-rw-r--r--thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/b3Common.h39
-rw-r--r--thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/b3DNA.cpp629
-rw-r--r--thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/b3DNA.h110
-rw-r--r--thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/b3Defines.h136
-rw-r--r--thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/b3File.cpp1739
-rw-r--r--thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/b3File.h165
-rw-r--r--thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/b3Serializer.cpp908
-rw-r--r--thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/b3Serializer.h639
-rw-r--r--thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/premake4.lua12
-rw-r--r--thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp37
-rw-r--r--thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h52
-rw-r--r--thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btAxisSweep3Internal.h1022
-rw-r--r--thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h86
-rw-r--r--thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp18
-rw-r--r--thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h269
-rw-r--r--thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp23
-rw-r--r--thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h81
-rw-r--r--thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btDbvt.cpp1329
-rw-r--r--thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btDbvt.h1343
-rw-r--r--thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp822
-rw-r--r--thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h147
-rw-r--r--thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btDispatcher.cpp22
-rw-r--r--thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btDispatcher.h113
-rw-r--r--thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp632
-rw-r--r--thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h469
-rw-r--r--thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h43
-rw-r--r--thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp1397
-rw-r--r--thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h581
-rw-r--r--thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp349
-rw-r--r--thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h171
-rw-r--r--thirdparty/bullet/src/BulletCollision/CMakeLists.txt292
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp209
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h51
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp47
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h37
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp421
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h66
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp84
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h66
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp718
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.h44
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h49
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h45
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp324
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h175
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCollisionDispatcherMt.cpp164
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCollisionDispatcherMt.h39
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp131
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCollisionObject.h679
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h43
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp1666
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCollisionWorld.h528
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCollisionWorldImporter.cpp1147
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCollisionWorldImporter.h189
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp402
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h104
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.cpp456
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.h87
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp242
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h92
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp346
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h127
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp828
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h109
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp174
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h84
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp383
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h122
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp34
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h54
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionDispatch/btGhostObject.cpp171
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionDispatch/btGhostObject.h175
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionDispatch/btHashedSimplePairCache.cpp276
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionDispatch/btHashedSimplePairCache.h172
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp838
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h47
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp207
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionDispatch/btManifoldResult.h167
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp450
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h81
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp214
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h75
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp107
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h66
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp84
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h69
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionDispatch/btUnionFind.cpp82
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionDispatch/btUnionFind.h129
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btBox2dShape.cpp42
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btBox2dShape.h372
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btBoxShape.cpp51
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btBoxShape.h314
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp470
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h149
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp169
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btCapsuleShape.h190
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btCollisionMargin.h27
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btCollisionShape.cpp122
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btCollisionShape.h170
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btCompoundShape.cpp359
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btCompoundShape.h212
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btConcaveShape.cpp27
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btConcaveShape.h62
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btConeShape.cpp147
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btConeShape.h186
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btConvex2dShape.cpp92
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btConvex2dShape.h82
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btConvexHullShape.cpp262
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btConvexHullShape.h121
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp151
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btConvexInternalShape.h227
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp139
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btConvexPointCloudShape.h105
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp303
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btConvexPolyhedron.h65
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btConvexShape.cpp455
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btConvexShape.h85
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp315
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h77
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btCylinderShape.cpp282
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btCylinderShape.h219
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btEmptyShape.cpp50
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btEmptyShape.h72
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp409
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h167
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btMaterial.h35
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp77
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h62
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp185
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btMultiSphereShape.h101
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp45
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h119
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp391
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btOptimizedBvh.h65
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp500
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h118
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp121
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h95
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btShapeHull.cpp170
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btShapeHull.h61
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btSphereShape.cpp71
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btSphereShape.h76
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btStaticPlaneShape.cpp107
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btStaticPlaneShape.h111
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp388
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btStridingMeshInterface.h164
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btTetrahedronShape.cpp218
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btTetrahedronShape.h76
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btTriangleBuffer.cpp35
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btTriangleBuffer.h69
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btTriangleCallback.cpp28
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btTriangleCallback.h42
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp95
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h133
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp86
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h84
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btTriangleInfoMap.h248
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btTriangleMesh.cpp169
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btTriangleMesh.h72
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp207
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h90
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btTriangleShape.h184
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btUniformScalingShape.cpp160
-rw-r--r--thirdparty/bullet/src/BulletCollision/CollisionShapes/btUniformScalingShape.h89
-rw-r--r--thirdparty/bullet/src/BulletCollision/Gimpact/btBoxCollision.h645
-rw-r--r--thirdparty/bullet/src/BulletCollision/Gimpact/btClipPolygon.h182
-rw-r--r--thirdparty/bullet/src/BulletCollision/Gimpact/btCompoundFromGimpact.h109
-rw-r--r--thirdparty/bullet/src/BulletCollision/Gimpact/btContactProcessing.cpp181
-rw-r--r--thirdparty/bullet/src/BulletCollision/Gimpact/btContactProcessing.h65
-rw-r--r--thirdparty/bullet/src/BulletCollision/Gimpact/btContactProcessingStructs.h109
-rw-r--r--thirdparty/bullet/src/BulletCollision/Gimpact/btGImpactBvh.cpp498
-rw-r--r--thirdparty/bullet/src/BulletCollision/Gimpact/btGImpactBvh.h318
-rw-r--r--thirdparty/bullet/src/BulletCollision/Gimpact/btGImpactBvhStructs.h105
-rw-r--r--thirdparty/bullet/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp932
-rw-r--r--thirdparty/bullet/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h310
-rw-r--r--thirdparty/bullet/src/BulletCollision/Gimpact/btGImpactMassUtil.h60
-rw-r--r--thirdparty/bullet/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp528
-rw-r--r--thirdparty/bullet/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.h305
-rw-r--r--thirdparty/bullet/src/BulletCollision/Gimpact/btGImpactQuantizedBvhStructs.h91
-rw-r--r--thirdparty/bullet/src/BulletCollision/Gimpact/btGImpactShape.cpp291
-rw-r--r--thirdparty/bullet/src/BulletCollision/Gimpact/btGImpactShape.h1164
-rw-r--r--thirdparty/bullet/src/BulletCollision/Gimpact/btGenericPoolAllocator.cpp283
-rw-r--r--thirdparty/bullet/src/BulletCollision/Gimpact/btGenericPoolAllocator.h163
-rw-r--r--thirdparty/bullet/src/BulletCollision/Gimpact/btGeometryOperations.h212
-rw-r--r--thirdparty/bullet/src/BulletCollision/Gimpact/btQuantization.h88
-rw-r--r--thirdparty/bullet/src/BulletCollision/Gimpact/btTriangleShapeEx.cpp218
-rw-r--r--thirdparty/bullet/src/BulletCollision/Gimpact/btTriangleShapeEx.h180
-rw-r--r--thirdparty/bullet/src/BulletCollision/Gimpact/gim_array.h324
-rw-r--r--thirdparty/bullet/src/BulletCollision/Gimpact/gim_basic_geometry_operations.h546
-rw-r--r--thirdparty/bullet/src/BulletCollision/Gimpact/gim_bitset.h123
-rw-r--r--thirdparty/bullet/src/BulletCollision/Gimpact/gim_box_collision.h593
-rw-r--r--thirdparty/bullet/src/BulletCollision/Gimpact/gim_box_set.cpp182
-rw-r--r--thirdparty/bullet/src/BulletCollision/Gimpact/gim_box_set.h674
-rw-r--r--thirdparty/bullet/src/BulletCollision/Gimpact/gim_clip_polygon.h210
-rw-r--r--thirdparty/bullet/src/BulletCollision/Gimpact/gim_contact.cpp146
-rw-r--r--thirdparty/bullet/src/BulletCollision/Gimpact/gim_contact.h172
-rw-r--r--thirdparty/bullet/src/BulletCollision/Gimpact/gim_geom_types.h97
-rw-r--r--thirdparty/bullet/src/BulletCollision/Gimpact/gim_geometry.h42
-rw-r--r--thirdparty/bullet/src/BulletCollision/Gimpact/gim_hash_table.h902
-rw-r--r--thirdparty/bullet/src/BulletCollision/Gimpact/gim_linear_math.h1573
-rw-r--r--thirdparty/bullet/src/BulletCollision/Gimpact/gim_math.h157
-rw-r--r--thirdparty/bullet/src/BulletCollision/Gimpact/gim_memory.cpp135
-rw-r--r--thirdparty/bullet/src/BulletCollision/Gimpact/gim_memory.h190
-rw-r--r--thirdparty/bullet/src/BulletCollision/Gimpact/gim_radixsort.h406
-rw-r--r--thirdparty/bullet/src/BulletCollision/Gimpact/gim_tri_collision.cpp640
-rw-r--r--thirdparty/bullet/src/BulletCollision/Gimpact/gim_tri_collision.h380
-rw-r--r--thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btComputeGjkEpaPenetration.h369
-rw-r--r--thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp242
-rw-r--r--thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h59
-rw-r--r--thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btConvexCast.cpp20
-rw-r--r--thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btConvexCast.h73
-rw-r--r--thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h40
-rw-r--r--thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h90
-rw-r--r--thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btGjkCollisionDescription.h41
-rw-r--r--thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp176
-rw-r--r--thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h50
-rw-r--r--thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp1048
-rw-r--r--thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h75
-rw-r--r--thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btGjkEpa3.h1035
-rw-r--r--thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp66
-rw-r--r--thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h43
-rw-r--r--thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp467
-rw-r--r--thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h103
-rw-r--r--thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h180
-rw-r--r--thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp361
-rw-r--r--thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h40
-rw-r--r--thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btMprPenetration.h908
-rw-r--r--thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp308
-rw-r--r--thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h268
-rw-r--r--thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btPointCollector.h64
-rw-r--r--thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp570
-rw-r--r--thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h49
-rw-r--r--thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp178
-rw-r--r--thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h74
-rw-r--r--thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h63
-rw-r--r--thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp160
-rw-r--r--thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h50
-rw-r--r--thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp612
-rw-r--r--thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h185
-rw-r--r--thirdparty/bullet/src/BulletCollision/premake4.lua20
-rw-r--r--thirdparty/bullet/src/BulletDynamics/CMakeLists.txt170
-rw-r--r--thirdparty/bullet/src/BulletDynamics/Character/btCharacterControllerInterface.h47
-rw-r--r--thirdparty/bullet/src/BulletDynamics/Character/btKinematicCharacterController.cpp1000
-rw-r--r--thirdparty/bullet/src/BulletDynamics/Character/btKinematicCharacterController.h204
-rw-r--r--thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp1143
-rw-r--r--thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h435
-rw-r--r--thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btConstraintSolver.h65
-rw-r--r--thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp177
-rw-r--r--thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btContactConstraint.h73
-rw-r--r--thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h167
-rw-r--r--thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btFixedConstraint.cpp37
-rw-r--r--thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btFixedConstraint.h33
-rw-r--r--thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btGearConstraint.cpp54
-rw-r--r--thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btGearConstraint.h160
-rw-r--r--thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp1063
-rw-r--r--thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h647
-rw-r--r--thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.cpp1172
-rw-r--r--thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h679
-rw-r--r--thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp185
-rw-r--r--thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h141
-rw-r--r--thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btHinge2Constraint.cpp66
-rw-r--r--thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btHinge2Constraint.h60
-rw-r--r--thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp1120
-rw-r--r--thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h503
-rw-r--r--thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h155
-rw-r--r--thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btNNCGConstraintSolver.cpp374
-rw-r--r--thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btNNCGConstraintSolver.h64
-rw-r--r--thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp229
-rw-r--r--thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h180
-rw-r--r--thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp1973
-rw-r--r--thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h196
-rw-r--r--thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp855
-rw-r--r--thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h368
-rw-r--r--thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp255
-rw-r--r--thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h107
-rw-r--r--thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btSolverBody.h306
-rw-r--r--thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h80
-rw-r--r--thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp222
-rw-r--r--thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h541
-rw-r--r--thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp87
-rw-r--r--thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.h65
-rw-r--r--thirdparty/bullet/src/BulletDynamics/Dynamics/btActionInterface.h46
-rw-r--r--thirdparty/bullet/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp1538
-rw-r--r--thirdparty/bullet/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h239
-rw-r--r--thirdparty/bullet/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.cpp327
-rw-r--r--thirdparty/bullet/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.h134
-rw-r--r--thirdparty/bullet/src/BulletDynamics/Dynamics/btDynamicsWorld.h173
-rw-r--r--thirdparty/bullet/src/BulletDynamics/Dynamics/btRigidBody.cpp527
-rw-r--r--thirdparty/bullet/src/BulletDynamics/Dynamics/btRigidBody.h619
-rw-r--r--thirdparty/bullet/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp280
-rw-r--r--thirdparty/bullet/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h89
-rw-r--r--thirdparty/bullet/src/BulletDynamics/Dynamics/btSimulationIslandManagerMt.cpp678
-rw-r--r--thirdparty/bullet/src/BulletDynamics/Dynamics/btSimulationIslandManagerMt.h110
-rw-r--r--thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBody.cpp2043
-rw-r--r--thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBody.h814
-rw-r--r--thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyConstraint.cpp417
-rw-r--r--thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyConstraint.h195
-rw-r--r--thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp1429
-rw-r--r--thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h100
-rw-r--r--thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.cpp991
-rw-r--r--thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h114
-rw-r--r--thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyFixedConstraint.cpp211
-rw-r--r--thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyFixedConstraint.h94
-rw-r--r--thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyGearConstraint.cpp184
-rw-r--r--thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyGearConstraint.h117
-rw-r--r--thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyJointFeedback.h27
-rw-r--r--thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.cpp205
-rw-r--r--thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.h50
-rw-r--r--thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyJointMotor.cpp186
-rw-r--r--thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyJointMotor.h81
-rw-r--r--thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyLink.h244
-rw-r--r--thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyLinkCollider.h125
-rw-r--r--thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyPoint2Point.cpp221
-rw-r--r--thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyPoint2Point.h68
-rw-r--r--thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodySliderConstraint.cpp230
-rw-r--r--thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodySliderConstraint.h105
-rw-r--r--thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodySolverConstraint.h90
-rw-r--r--thirdparty/bullet/src/BulletDynamics/MLCPSolvers/btDantzigLCP.cpp2080
-rw-r--r--thirdparty/bullet/src/BulletDynamics/MLCPSolvers/btDantzigLCP.h77
-rw-r--r--thirdparty/bullet/src/BulletDynamics/MLCPSolvers/btDantzigSolver.h112
-rw-r--r--thirdparty/bullet/src/BulletDynamics/MLCPSolvers/btLemkeAlgorithm.cpp371
-rw-r--r--thirdparty/bullet/src/BulletDynamics/MLCPSolvers/btLemkeAlgorithm.h108
-rw-r--r--thirdparty/bullet/src/BulletDynamics/MLCPSolvers/btLemkeSolver.h350
-rw-r--r--thirdparty/bullet/src/BulletDynamics/MLCPSolvers/btMLCPSolver.cpp639
-rw-r--r--thirdparty/bullet/src/BulletDynamics/MLCPSolvers/btMLCPSolver.h94
-rw-r--r--thirdparty/bullet/src/BulletDynamics/MLCPSolvers/btMLCPSolverInterface.h33
-rw-r--r--thirdparty/bullet/src/BulletDynamics/MLCPSolvers/btPATHSolver.h151
-rw-r--r--thirdparty/bullet/src/BulletDynamics/MLCPSolvers/btSolveProjectedGaussSeidel.h110
-rw-r--r--thirdparty/bullet/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp772
-rw-r--r--thirdparty/bullet/src/BulletDynamics/Vehicle/btRaycastVehicle.h234
-rw-r--r--thirdparty/bullet/src/BulletDynamics/Vehicle/btVehicleRaycaster.h35
-rw-r--r--thirdparty/bullet/src/BulletDynamics/Vehicle/btWheelInfo.cpp56
-rw-r--r--thirdparty/bullet/src/BulletDynamics/Vehicle/btWheelInfo.h121
-rw-r--r--thirdparty/bullet/src/BulletDynamics/premake4.lua21
-rw-r--r--thirdparty/bullet/src/BulletInverseDynamics/CMakeLists.txt66
-rw-r--r--thirdparty/bullet/src/BulletInverseDynamics/IDConfig.hpp107
-rw-r--r--thirdparty/bullet/src/BulletInverseDynamics/IDConfigBuiltin.hpp37
-rw-r--r--thirdparty/bullet/src/BulletInverseDynamics/IDConfigEigen.hpp31
-rw-r--r--thirdparty/bullet/src/BulletInverseDynamics/IDErrorMessages.hpp29
-rw-r--r--thirdparty/bullet/src/BulletInverseDynamics/IDMath.cpp437
-rw-r--r--thirdparty/bullet/src/BulletInverseDynamics/IDMath.hpp99
-rw-r--r--thirdparty/bullet/src/BulletInverseDynamics/MultiBodyTree.cpp445
-rw-r--r--thirdparty/bullet/src/BulletInverseDynamics/MultiBodyTree.hpp363
-rw-r--r--thirdparty/bullet/src/BulletInverseDynamics/details/IDEigenInterface.hpp36
-rw-r--r--thirdparty/bullet/src/BulletInverseDynamics/details/IDLinearMathInterface.hpp172
-rw-r--r--thirdparty/bullet/src/BulletInverseDynamics/details/IDMatVec.hpp415
-rw-r--r--thirdparty/bullet/src/BulletInverseDynamics/details/MultiBodyTreeImpl.cpp1028
-rw-r--r--thirdparty/bullet/src/BulletInverseDynamics/details/MultiBodyTreeImpl.hpp283
-rw-r--r--thirdparty/bullet/src/BulletInverseDynamics/details/MultiBodyTreeInitCache.cpp113
-rw-r--r--thirdparty/bullet/src/BulletInverseDynamics/details/MultiBodyTreeInitCache.hpp109
-rw-r--r--thirdparty/bullet/src/BulletInverseDynamics/premake4.lua12
-rw-r--r--thirdparty/bullet/src/BulletSoftBody/CMakeLists.txt69
-rw-r--r--thirdparty/bullet/src/BulletSoftBody/btDefaultSoftBodySolver.cpp151
-rw-r--r--thirdparty/bullet/src/BulletSoftBody/btDefaultSoftBodySolver.h63
-rw-r--r--thirdparty/bullet/src/BulletSoftBody/btSoftBody.cpp3709
-rw-r--r--thirdparty/bullet/src/BulletSoftBody/btSoftBody.h1005
-rw-r--r--thirdparty/bullet/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp358
-rw-r--r--thirdparty/bullet/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h155
-rw-r--r--thirdparty/bullet/src/BulletSoftBody/btSoftBodyData.h217
-rw-r--r--thirdparty/bullet/src/BulletSoftBody/btSoftBodyHelpers.cpp1219
-rw-r--r--thirdparty/bullet/src/BulletSoftBody/btSoftBodyHelpers.h148
-rw-r--r--thirdparty/bullet/src/BulletSoftBody/btSoftBodyInternals.h911
-rw-r--r--thirdparty/bullet/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp134
-rw-r--r--thirdparty/bullet/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h48
-rw-r--r--thirdparty/bullet/src/BulletSoftBody/btSoftBodySolverVertexBuffer.h165
-rw-r--r--thirdparty/bullet/src/BulletSoftBody/btSoftBodySolvers.h154
-rw-r--r--thirdparty/bullet/src/BulletSoftBody/btSoftMultiBodyDynamicsWorld.cpp367
-rw-r--r--thirdparty/bullet/src/BulletSoftBody/btSoftMultiBodyDynamicsWorld.h110
-rw-r--r--thirdparty/bullet/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp86
-rw-r--r--thirdparty/bullet/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.h75
-rw-r--r--thirdparty/bullet/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp367
-rw-r--r--thirdparty/bullet/src/BulletSoftBody/btSoftRigidDynamicsWorld.h107
-rw-r--r--thirdparty/bullet/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp48
-rw-r--r--thirdparty/bullet/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h69
-rw-r--r--thirdparty/bullet/src/BulletSoftBody/btSparseSDF.h319
-rw-r--r--thirdparty/bullet/src/BulletSoftBody/premake4.lua11
-rw-r--r--thirdparty/bullet/src/CMakeLists.txt19
-rw-r--r--thirdparty/bullet/src/LinearMath/CMakeLists.txt75
-rw-r--r--thirdparty/bullet/src/LinearMath/btAabbUtil2.h232
-rw-r--r--thirdparty/bullet/src/LinearMath/btAlignedAllocator.cpp269
-rw-r--r--thirdparty/bullet/src/LinearMath/btAlignedAllocator.h113
-rw-r--r--thirdparty/bullet/src/LinearMath/btAlignedObjectArray.h530
-rw-r--r--thirdparty/bullet/src/LinearMath/btConvexHull.cpp1167
-rw-r--r--thirdparty/bullet/src/LinearMath/btConvexHull.h241
-rw-r--r--thirdparty/bullet/src/LinearMath/btConvexHullComputer.cpp2768
-rw-r--r--thirdparty/bullet/src/LinearMath/btConvexHullComputer.h103
-rw-r--r--thirdparty/bullet/src/LinearMath/btCpuFeatureUtility.h92
-rw-r--r--thirdparty/bullet/src/LinearMath/btDefaultMotionState.h42
-rw-r--r--thirdparty/bullet/src/LinearMath/btGeometryUtil.cpp185
-rw-r--r--thirdparty/bullet/src/LinearMath/btGeometryUtil.h42
-rw-r--r--thirdparty/bullet/src/LinearMath/btGrahamScan2dConvexHull.h130
-rw-r--r--thirdparty/bullet/src/LinearMath/btHashMap.h482
-rw-r--r--thirdparty/bullet/src/LinearMath/btIDebugDraw.h483
-rw-r--r--thirdparty/bullet/src/LinearMath/btList.h73
-rw-r--r--thirdparty/bullet/src/LinearMath/btMatrix3x3.h1348
-rw-r--r--thirdparty/bullet/src/LinearMath/btMatrixX.h554
-rw-r--r--thirdparty/bullet/src/LinearMath/btMinMax.h71
-rw-r--r--thirdparty/bullet/src/LinearMath/btMotionState.h40
-rw-r--r--thirdparty/bullet/src/LinearMath/btPolarDecomposition.cpp98
-rw-r--r--thirdparty/bullet/src/LinearMath/btPolarDecomposition.h72
-rw-r--r--thirdparty/bullet/src/LinearMath/btPoolAllocator.h130
-rw-r--r--thirdparty/bullet/src/LinearMath/btQuadWord.h244
-rw-r--r--thirdparty/bullet/src/LinearMath/btQuaternion.h1016
-rw-r--r--thirdparty/bullet/src/LinearMath/btQuickprof.cpp789
-rw-r--r--thirdparty/bullet/src/LinearMath/btQuickprof.h221
-rw-r--r--thirdparty/bullet/src/LinearMath/btRandom.h42
-rw-r--r--thirdparty/bullet/src/LinearMath/btScalar.h810
-rw-r--r--thirdparty/bullet/src/LinearMath/btSerializer.cpp599
-rw-r--r--thirdparty/bullet/src/LinearMath/btSerializer.h908
-rw-r--r--thirdparty/bullet/src/LinearMath/btSerializer64.cpp599
-rw-r--r--thirdparty/bullet/src/LinearMath/btSpatialAlgebra.h331
-rw-r--r--thirdparty/bullet/src/LinearMath/btStackAlloc.h116
-rw-r--r--thirdparty/bullet/src/LinearMath/btThreads.cpp722
-rw-r--r--thirdparty/bullet/src/LinearMath/btThreads.h155
-rw-r--r--thirdparty/bullet/src/LinearMath/btTransform.h305
-rw-r--r--thirdparty/bullet/src/LinearMath/btTransformUtil.h241
-rw-r--r--thirdparty/bullet/src/LinearMath/btVector3.cpp1670
-rw-r--r--thirdparty/bullet/src/LinearMath/btVector3.h1363
-rw-r--r--thirdparty/bullet/src/LinearMath/premake4.lua10
-rw-r--r--thirdparty/bullet/src/btBulletCollisionCommon.h67
-rw-r--r--thirdparty/bullet/src/btBulletDynamicsCommon.h51
-rw-r--r--thirdparty/bullet/src/clew/clew.c312
-rw-r--r--thirdparty/bullet/src/clew/clew.h2397
-rw-r--r--thirdparty/bullet/version.txt1
-rw-r--r--thirdparty/enet/enet/enet.h1
-rw-r--r--thirdparty/etc2comp/AUTHORS14
-rw-r--r--thirdparty/etc2comp/LICENSE404
-rw-r--r--thirdparty/etc2comp/README.md394
-rw-r--r--thirdparty/freetype/include/freetype/config/ftoption.h21
-rw-r--r--thirdparty/freetype/include/freetype/freetype.h37
-rw-r--r--thirdparty/freetype/include/freetype/ftautoh.h14
-rw-r--r--thirdparty/freetype/include/freetype/fterrdef.h2
-rw-r--r--thirdparty/freetype/include/freetype/fterrors.h6
-rw-r--r--thirdparty/freetype/include/freetype/ftglyph.h9
-rw-r--r--thirdparty/freetype/include/freetype/ftimage.h20
-rw-r--r--thirdparty/freetype/include/freetype/ftlcdfil.h19
-rw-r--r--thirdparty/freetype/include/freetype/ftmac.h9
-rw-r--r--thirdparty/freetype/include/freetype/ftmm.h64
-rw-r--r--thirdparty/freetype/include/freetype/ftoutln.h3
-rw-r--r--thirdparty/freetype/include/freetype/internal/ftcalc.h36
-rw-r--r--thirdparty/freetype/include/freetype/internal/ftobjs.h34
-rw-r--r--thirdparty/freetype/include/freetype/tttags.h6
-rw-r--r--thirdparty/freetype/src/autofit/afblue.c12
-rw-r--r--thirdparty/freetype/src/autofit/afblue.dat20
-rw-r--r--thirdparty/freetype/src/autofit/afblue.h10
-rw-r--r--thirdparty/freetype/src/autofit/afcjk.c12
-rw-r--r--thirdparty/freetype/src/autofit/afhints.c6
-rw-r--r--thirdparty/freetype/src/autofit/aflatin.c33
-rw-r--r--thirdparty/freetype/src/autofit/aflatin2.c12
-rw-r--r--thirdparty/freetype/src/autofit/afloader.c8
-rw-r--r--thirdparty/freetype/src/autofit/afscript.h24
-rw-r--r--thirdparty/freetype/src/autofit/afshaper.c1
-rw-r--r--thirdparty/freetype/src/autofit/afstyles.h28
-rw-r--r--thirdparty/freetype/src/base/ftbitmap.c5
-rw-r--r--thirdparty/freetype/src/base/ftcalc.c150
-rw-r--r--thirdparty/freetype/src/base/ftglyph.c16
-rw-r--r--thirdparty/freetype/src/base/ftlcdfil.c211
-rw-r--r--thirdparty/freetype/src/base/ftmac.c2
-rw-r--r--thirdparty/freetype/src/base/ftmm.c32
-rw-r--r--thirdparty/freetype/src/base/ftobjs.c38
-rw-r--r--thirdparty/freetype/src/base/ftoutln.c3
-rw-r--r--thirdparty/freetype/src/base/ftrfork.c10
-rw-r--r--thirdparty/freetype/src/base/ftsynth.c2
-rw-r--r--thirdparty/freetype/src/base/ftutil.c10
-rw-r--r--thirdparty/freetype/src/bdf/bdfdrivr.c144
-rw-r--r--thirdparty/freetype/src/bdf/bdflib.c40
-rw-r--r--thirdparty/freetype/src/cache/ftcbasic.c38
-rw-r--r--thirdparty/freetype/src/cff/cf2blues.c45
-rw-r--r--thirdparty/freetype/src/cff/cf2blues.h2
-rw-r--r--thirdparty/freetype/src/cff/cf2fixed.h4
-rw-r--r--thirdparty/freetype/src/cff/cf2font.c4
-rw-r--r--thirdparty/freetype/src/cff/cf2ft.c4
-rw-r--r--thirdparty/freetype/src/cff/cf2hints.c255
-rw-r--r--thirdparty/freetype/src/cff/cf2intrp.c179
-rw-r--r--thirdparty/freetype/src/cff/cffgload.c207
-rw-r--r--thirdparty/freetype/src/cff/cffload.c9
-rw-r--r--thirdparty/freetype/src/cff/cffparse.c27
-rw-r--r--thirdparty/freetype/src/gxvalid/README2
-rw-r--r--thirdparty/freetype/src/pcf/README4
-rw-r--r--thirdparty/freetype/src/pcf/pcfdrivr.c12
-rw-r--r--thirdparty/freetype/src/pcf/pcfread.c78
-rw-r--r--thirdparty/freetype/src/pfr/pfrobjs.c6
-rw-r--r--thirdparty/freetype/src/psaux/psconv.c8
-rw-r--r--thirdparty/freetype/src/psaux/t1decode.c92
-rw-r--r--thirdparty/freetype/src/psnames/psmodule.c13
-rw-r--r--thirdparty/freetype/src/psnames/pstables.h36
-rw-r--r--thirdparty/freetype/src/raster/ftrend1.c9
-rw-r--r--thirdparty/freetype/src/sfnt/pngshim.c72
-rw-r--r--thirdparty/freetype/src/sfnt/sfobjs.c51
-rw-r--r--thirdparty/freetype/src/sfnt/ttcmap.c112
-rw-r--r--thirdparty/freetype/src/sfnt/ttcmap.h2
-rw-r--r--thirdparty/freetype/src/sfnt/ttkern.c8
-rw-r--r--thirdparty/freetype/src/sfnt/ttpost.c7
-rw-r--r--thirdparty/freetype/src/sfnt/ttsbit.c20
-rw-r--r--thirdparty/freetype/src/smooth/ftgrays.c15
-rw-r--r--thirdparty/freetype/src/smooth/ftsmooth.c192
-rw-r--r--thirdparty/freetype/src/truetype/ttgload.c101
-rw-r--r--thirdparty/freetype/src/truetype/ttgxvar.c97
-rw-r--r--thirdparty/freetype/src/truetype/ttinterp.c303
-rw-r--r--thirdparty/freetype/src/truetype/ttinterp.h50
-rw-r--r--thirdparty/freetype/src/truetype/ttobjs.c16
-rw-r--r--thirdparty/freetype/src/truetype/ttpload.c8
-rw-r--r--thirdparty/freetype/src/type1/t1load.c4
-rw-r--r--thirdparty/freetype/src/type1/t1objs.c6
-rw-r--r--thirdparty/freetype/src/type42/t42objs.c6
-rw-r--r--thirdparty/freetype/src/winfonts/winfnt.c6
-rw-r--r--thirdparty/libpng/LICENSE9
-rw-r--r--thirdparty/libpng/png.c32
-rw-r--r--thirdparty/libpng/png.h28
-rw-r--r--thirdparty/libpng/pngconf.h2
-rw-r--r--thirdparty/libpng/pnglibconf.h4
-rw-r--r--thirdparty/libpng/pngread.c14
-rw-r--r--thirdparty/libpng/pngrtran.c22
-rw-r--r--thirdparty/libpng/pngrutil.c47
-rw-r--r--thirdparty/libpng/pngtrans.c6
-rw-r--r--thirdparty/libpng/pngwrite.c2
-rw-r--r--thirdparty/libsimplewebm/OpusVorbisDecoder.cpp37
-rw-r--r--thirdparty/libsimplewebm/OpusVorbisDecoder.hpp2
-rw-r--r--thirdparty/libtheora/x86_vc/mmxencfrag.c1938
-rw-r--r--thirdparty/libtheora/x86_vc/mmxfdct.c1340
-rw-r--r--thirdparty/nanosvg/LICENSE.txt36
-rw-r--r--thirdparty/openssl/uwp.cpp2
-rw-r--r--thirdparty/zstd/SCsub6
-rw-r--r--thirdparty/zstd/common/bitstream.h58
-rw-r--r--thirdparty/zstd/common/compiler.h1
-rw-r--r--thirdparty/zstd/common/error_private.c6
-rw-r--r--thirdparty/zstd/common/error_private.h8
-rw-r--r--thirdparty/zstd/common/fse.h2
-rw-r--r--thirdparty/zstd/common/huf.h2
-rw-r--r--thirdparty/zstd/common/mem.h1
-rw-r--r--thirdparty/zstd/common/pool.c107
-rw-r--r--thirdparty/zstd/common/pool.h4
-rw-r--r--thirdparty/zstd/common/threading.c26
-rw-r--r--thirdparty/zstd/common/threading.h84
-rw-r--r--thirdparty/zstd/common/zstd_common.c4
-rw-r--r--thirdparty/zstd/common/zstd_errors.h4
-rw-r--r--thirdparty/zstd/common/zstd_internal.h116
-rw-r--r--thirdparty/zstd/compress/fse_compress.c4
-rw-r--r--thirdparty/zstd/compress/huf_compress.c7
-rw-r--r--thirdparty/zstd/compress/zstd_compress.c2650
-rw-r--r--thirdparty/zstd/compress/zstd_compress.h307
-rw-r--r--thirdparty/zstd/compress/zstd_double_fast.c308
-rw-r--r--thirdparty/zstd/compress/zstd_double_fast.h28
-rw-r--r--thirdparty/zstd/compress/zstd_fast.c242
-rw-r--r--thirdparty/zstd/compress/zstd_fast.h30
-rw-r--r--thirdparty/zstd/compress/zstd_lazy.c749
-rw-r--r--thirdparty/zstd/compress/zstd_lazy.h38
-rw-r--r--thirdparty/zstd/compress/zstd_ldm.c707
-rw-r--r--thirdparty/zstd/compress/zstd_ldm.h67
-rw-r--r--thirdparty/zstd/compress/zstd_opt.c957
-rw-r--r--thirdparty/zstd/compress/zstd_opt.h936
-rw-r--r--thirdparty/zstd/compress/zstdmt_compress.c343
-rw-r--r--thirdparty/zstd/compress/zstdmt_compress.h23
-rw-r--r--thirdparty/zstd/decompress/zstd_decompress.c569
-rw-r--r--thirdparty/zstd/zstd.h484
-rw-r--r--version.py3
2169 files changed, 336334 insertions, 79167 deletions
diff --git a/.gitattributes b/.gitattributes
index f8959dd2d1..03c6f96f80 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -8,3 +8,4 @@ drivers/* linguist-vendored
*.h eol=lf
*.py eol=lf
*.hpp eol=lf
+*.xml eol=lf
diff --git a/.gitignore b/.gitignore
index b347b348a5..0de1e682a0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -88,6 +88,9 @@ bld/
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
+# Hints for improving IntelliSense, created together with VS project
+cpp.hint
+
#NUNIT
*.VisualState.xml
TestResult.xml
diff --git a/.travis.yml b/.travis.yml
index a2c3417412..974ef93d3f 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -6,45 +6,29 @@ sudo: false
cache: ccache
-compiler:
- - gcc
- - clang
-
-os:
- - linux
- - osx
-
-env:
- - GODOT_TARGET=iphone
- - GODOT_TARGET=osx
- - GODOT_TARGET=x11
- #- GODOT_TARGET=android
- #- GODOT_TARGET=windows
-
matrix:
include:
- env: STATIC_CHECKS=yes
- exclude:
- - os: linux
- env: GODOT_TARGET=iphone
- - os: linux
- env: GODOT_TARGET=osx
- - os: linux
- env: GODOT_TARGET=android
- - os: osx
- env: GODOT_TARGET=x11
- - os: osx
- env: GODOT_TARGET=windows
- - compiler: gcc
- env: GODOT_TARGET=iphone
- - compiler: gcc
- env: GODOT_TARGET=osx
- - compiler: clang
- env: GODOT_TARGET=android
- - compiler: clang
- env: GODOT_TARGET=windows
- - compiler: clang
- env: GODOT_TARGET=x11
+ os: linux
+ compiler: clang
+ - env: GODOT_TARGET=x11 TOOLS=yes
+ os: linux
+ compiler: gcc
+ - env: GODOT_TARGET=x11 TOOLS=no
+ os: linux
+ compiler: clang
+ #- env: GODOT_TARGET=windows TOOLS=yes
+ # os: linux
+ # compiler: gcc
+ - env: GODOT_TARGET=android TOOLS=no
+ os: linux
+ compiler: gcc
+ - env: GODOT_TARGET=osx TOOLS=yes
+ os: osx
+ compiler: clang
+ #- env: GODOT_TARGET=iphone TOOLS=no
+ # os: osx
+ # compiler: clang
addons:
apt:
@@ -77,20 +61,41 @@ addons:
# For style checks.
- clang-format-3.9
+install:
+ - if [ "$TRAVIS_OS_NAME" = "linux" ] && [ "$GODOT_TARGET" = "android" ]; then
+ misc/travis/android-tools-linux.sh;
+ fi
+ - if [ "$TRAVIS_OS_NAME" = "osx" ]; then
+ misc/travis/scons-local-osx.sh;
+ misc/travis/ccache-osx.sh;
+ fi
+ - if [ "$TRAVIS_OS_NAME" = "osx" ] && [ "$GODOT_TARGET" = "android" ]; then
+ misc/travis/android-tools-osx.sh;
+ fi
+
before_script:
+ - if [ "$TRAVIS_OS_NAME" = "linux" ]; then
+ export CCACHE="/usr/bin/ccache";
+ fi
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then
- brew update; brew install scons ccache;
+ export CCACHE="/usr/local/bin/ccache";
export PATH="/usr/local/opt/ccache/libexec:$PATH";
fi
- - if [ "$TRAVIS_OS_NAME" = "osx" ] && [ "$GODOT_TARGET" = "android" ]; then
- brew update; brew install -v android-sdk;
- brew install -v android-ndk | grep -v "inflating:" | grep -v "creating:";
- export ANDROID_HOME=/usr/local/opt/android-sdk; export ANDROID_NDK_ROOT=/usr/local/opt/android-ndk;
+ - if [ "$GODOT_TARGET" = "android" ]; then
+ export ANDROID_HOME=$TRAVIS_BUILD_DIR/godot-dev/build-tools/android-sdk;
+ export ANDROID_NDK_ROOT=$TRAVIS_BUILD_DIR/godot-dev/build-tools/android-ndk;
fi
script:
- if [ "$STATIC_CHECKS" = "yes" ]; then
sh ./misc/travis/clang-format.sh;
else
- scons -j 2 platform=$GODOT_TARGET progress=no verbose=yes CXX=$CXX;
+ scons -j2 CC=$CC CXX=$CXX platform=$GODOT_TARGET TOOLS=$TOOLS verbose=yes progress=no;
fi
+
+after_success:
+ - if [ "$STATIC_CHECKS" != "yes" ] && [ $(command -v ccache) ]; then
+ which ccache;
+ ccache --version | grep "ccache version";
+ ccache -s;
+ fi;
diff --git a/AUTHORS.md b/AUTHORS.md
index bf833d1435..588ce97322 100644
--- a/AUTHORS.md
+++ b/AUTHORS.md
@@ -30,16 +30,20 @@ name is available.
Alexander Holland (AlexHolly)
Alexey Velikiy (jonyrock)
Alket Rexhepi (alketii)
+ Andrea Catania (AndreaCatania)
Andreas Haas (Hinsbart)
Anton Yabchinskiy (a12n)
Aren Villanueva (kurikaesu)
Ariel Manzur (punto-)
Bastiaan Olij (BastiaanOlij)
+ Ben Brookshire (sheepandshepherd)
+ Bernard Liebl (poke1024)
Bojidar Marinov (bojidar-bg)
Błażej Szczygieł (zaps166)
Carl Olsson (not-surt)
Dana Olson (adolson)
Daniel J. Ramirez (djrm)
+ Дмитрий Сальников (DmitriySalnikov)
Emmanuel Leblond (touilleMan)
Fabio Alessandrelli (Faless)
Ferenc Arn (tagcup)
@@ -47,11 +51,14 @@ name is available.
Geequlim
Gen (dbsGen)
George Marques (vnen)
+ Gerrit Großkopf (Grosskopf)
Gilles Roudiere (groud)
Guilherme Felipe (guilhermefelipecgs)
Hein-Pieter van Braam (hpvb)
+ Hiroshi Ogawa (hi-ogawa)
Hubert Jarosz (Marqin)
Hugo Locurcio (Calinou)
+ Ian (ianb96)
Ignacio Etcheverry (neikeq)
Indah Sylvia (ISylvox)
J08nY
@@ -67,6 +74,8 @@ name is available.
Mariano Javier Suligoy (MarianoGnu)
Mario Schlack (hurikhan)
Masoud BH (masoudbh3)
+ Matthias Hölzl (hoelzl)
+ Max Hilbrunner (mhilbrunner)
Nathan Warden (NathanWarden)
Nuno Donato (nunodonato)
Ovnuniarchos
@@ -75,6 +84,7 @@ name is available.
Pawel Kowal (pkowal1982)
Pedro J. Estébanez (RandomShaper)
Poommetee Ketson (Noshyaar)
+ Przemysław Gołąb (n-pigeon)
Ralf Hölzemer (rollenrolm)
Ramesh Ravone (RameshRavone)
Ray Koopa (RayKoopa)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index a9ada58e64..6cb52cf5ff 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -87,7 +87,7 @@ rebase -i`` and relevant help about rebasing or ammending commits on the
Internet).
This git style guide has some good practices to have in mind:
-https://github.com/agis-/git-style-guide
+[Git Style Guide](https://github.com/agis-/git-style-guide)
#### Format your commit logs with readability in mind
diff --git a/DONORS.md b/DONORS.md
index 57902fb2fc..3891a708ce 100644
--- a/DONORS.md
+++ b/DONORS.md
@@ -17,31 +17,46 @@ None so far, but your company could be the first! :)
## Gold sponsors
Gamblify <https://www.gamblify.com>
+ GameDev.TV <https://www.gamedev.tv>
## Mini sponsors
- Arron Washington
- Chris Phyffer
+ Andreas
+ Andreas Hirschauer
Christian Uldall Pedersen
+ Christoph Woinke
+ E Hewert
Hein-Pieter van Braam
Matthieu Huvé
+ Nathan Warden
Neal Gompa (Conan Kudo)
Olimpiu Metiu
+ Pascal Julien
Ruslan Mustakov
+ Slobodan Milnovic
## Gold donors
+ 3Dexplorer
Alexander Otto
+ Andy Meier
+ Asdf
+ cheese65536
Jake Bo
Javier
- Nathan Warden
- Ranoller
+ Manuele Finocchiaro
+ Officine Pixel S.n.c.
Rémi Verschelde
Stephan Lanfermann
Andreas Schüle
+ Austen McRae
Bernhard Liebl
+ Gerald E Butler
+ Jahn Johansen
Jordan M Lucas
+ Kris Michael
+ Ranoller
BanjoNode2D
Chris Serino
@@ -56,54 +71,83 @@ None so far, but your company could be the first! :)
Przemysław Gołąb (n-pigeon)
Robert Willes
Robin Arys
+ ScottMakesGames
summerblind
Testus Maximus
Thomas Bjarnelöf
+ Xavier Tan
+ Zaq Poi
Amanda Haldy
Andreas Haas
+ Andres Cuevas
+ Arnaud Verstuyf
Bryanna M
+ Chris Brown
Cody Parker
D
Ezra Theunissen
flesk
François Cantin
+ Giovanni Solimeno
Hendrik Mans
Jeppe Zapp
- Johannes Wuensch
Justin Arnold
Justo Delgado Baudí
Leandro Voltolino
- Myles
- Robert Podgorski
- Scott Beacon
- x1212
+ Lucien Boudy
+ Noah
+ Ryan Estes
+ Trent McPheron
## Silver donors
+ 1D_Inc
+ Alessandro Senese
Alex Barsukov
+ Anthony Bongiovanni
Avencherus
Bastian Böhm
Ben Vercammen
+ Blair Allen
Bryan Stevenson
+ Christian Baune
+ Christian Winter
Collin Shooltz
+ Daniel Kaplan
+ David Cravens
+ David May
+ Diego Moreira Guimarães
+ Dominik Wetzel
+ Eric Martini
Fabian Becker
fengjiongmax
+ Frank C. Simmons
Geequlim
Gerrit Großkopf
Guldoman
+ Gustav Dahlström
+ HardRound
hatniX
HeartBeast
Heribert Hirth
Hunter Jones
- imekon
- Jacob McKenney
+ Jaime Ruiz-Borau Vizárraga
+ Jeff Hungerford
+ Jesse Liles
+ joe513
Jonathon
Josh 'Cheeseness' Bush
+ Juan Negrier
+ JuDelCo
Julian Murgia
Juraj Móza
+ KC Chan
Kevin Boyer
+ Kevin Kamper Meejach Petersen
Klavdij Voncina
+ Kobi Malul
+ Linus Lind Lundgren
Lisandro Lorea
magodev
Martin Novák
@@ -111,28 +155,39 @@ None so far, but your company could be the first! :)
Matthew Valancy
Matthias Hölzl
Max R.R. Collada
+ mhilbrunner
Michael Gringauz
+ Michael Tintiuc
Mikael Olsson
+ MoM
Moritz Laass
nee
- nvgrod
+ Neil Blakey-Milner
+ Nik Lee
+ Niko Leopold
+ Oleg Tyshchenko
Pablo Seibelt
Pan Ip
+ Pat LaBine
+ Patrick Nafarrete
Paul Mason
Paweł Kowal
+ Pete Goodwin
Pietro Vertechi
rayos
Richman Stewart
Roger Smith
+ Roman Tinkov
Sam Van Campenhout
- Sam Vila
Sasori Olkof
+ Scott D. Yelich
Sootstone
- Tavo Tell
+ TheHappieCat
+ Theo Cranmore
+ Thomas Norman
Tom Larrow
- Trent McPheron
- Troy Bonneau
UltyX
+ Wout Standaert
Xananax & karroffel
## Bronze donors
diff --git a/LICENSE.txt b/LICENSE.txt
index 0b5b0c341f..bcce1a3a33 100644
--- a/LICENSE.txt
+++ b/LICENSE.txt
@@ -18,5 +18,3 @@ 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.
-
--- Godot Engine <https://godotengine.org>
diff --git a/README.md b/README.md
index 675e666ce6..6bb07a8c44 100644
--- a/README.md
+++ b/README.md
@@ -26,6 +26,8 @@ Before being open sourced in February 2014, Godot had been developed by Juan
Linietsky and Ariel Manzur (both still maintaining the project) for several
years as an in-house engine, used to publish several work-for-hire titles.
+![Screenshot of a 3D scene in Godot Engine](http://download.tuxfamily.org/godotengine/media/screenshots/editor_3d_fracteed.jpg)
+
### Getting the engine
#### Binary downloads
diff --git a/SConstruct b/SConstruct
index 6045be54c7..856994ef15 100644
--- a/SConstruct
+++ b/SConstruct
@@ -1,4 +1,3 @@
-
#!/usr/bin/env python
EnsureSConsVersion(0, 98, 1)
@@ -11,7 +10,8 @@ import glob
import sys
import methods
-methods.update_version()
+# moved below to compensate with module version string
+# methods.update_version()
# scan possible build platforms
@@ -22,6 +22,7 @@ platform_flags = {} # flags for each platform
active_platforms = []
active_platform_ids = []
platform_exporters = []
+platform_apis = []
global_defaults = []
for x in glob.glob("platform/*"):
@@ -34,6 +35,8 @@ for x in glob.glob("platform/*"):
if (os.path.exists(x + "/export/export.cpp")):
platform_exporters.append(x[9:])
+ if (os.path.exists(x + "/api/api.cpp")):
+ platform_apis.append(x[9:])
if (os.path.exists(x + "/globals/global_defaults.cpp")):
global_defaults.append(x[9:])
if (detect.is_active()):
@@ -72,6 +75,7 @@ env_base.AppendENVPath('PATH', os.getenv('PATH'))
env_base.AppendENVPath('PKG_CONFIG_PATH', os.getenv('PKG_CONFIG_PATH'))
env_base.global_defaults = global_defaults
env_base.android_maven_repos = []
+env_base.android_flat_dirs = []
env_base.android_dependencies = []
env_base.android_gradle_plugins = []
env_base.android_gradle_classpath = []
@@ -86,6 +90,7 @@ env_base.android_appattributes_chunk = ""
env_base.disabled_modules = []
env_base.use_ptrcall = False
env_base.split_drivers = False
+env_base.module_version_string = ""
# To decide whether to rebuild a file, use the MD5 sum only if the timestamp has changed.
# http://scons.org/doc/production/HTML/scons-user/ch06.html#idm139837621851792
@@ -96,6 +101,7 @@ env_base.SetOption('implicit_cache', 1)
env_base.__class__.android_add_maven_repository = methods.android_add_maven_repository
+env_base.__class__.android_add_flat_dir = methods.android_add_flat_dir
env_base.__class__.android_add_dependency = methods.android_add_dependency
env_base.__class__.android_add_java_dir = methods.android_add_java_dir
env_base.__class__.android_add_res_dir = methods.android_add_res_dir
@@ -109,6 +115,8 @@ env_base.__class__.android_add_gradle_plugin = methods.android_add_gradle_plugin
env_base.__class__.android_add_gradle_classpath = methods.android_add_gradle_classpath
env_base.__class__.disable_module = methods.disable_module
+env_base.__class__.add_module_version_string = methods.add_module_version_string
+
env_base.__class__.add_source_files = methods.add_source_files
env_base.__class__.use_windows_spawn_fix = methods.use_windows_spawn_fix
env_base.__class__.split_lib = methods.split_lib
@@ -137,6 +145,7 @@ opts.Add('p', "Platform (alias for 'platform')", '')
opts.Add('platform', "Target platform (%s)" % ('|'.join(platform_list), ), '')
opts.Add(EnumVariable('target', "Compilation target", 'debug', ('debug', 'release_debug', 'release')))
opts.Add(BoolVariable('tools', "Build the tools a.k.a. the Godot editor", True))
+opts.Add(BoolVariable('use_lto', 'Use linking time optimization', False))
# Components
opts.Add(BoolVariable('deprecated', "Enable deprecated features", True))
@@ -209,6 +218,7 @@ env_base.Append(CPPPATH=['#core', '#core/math', '#editor', '#drivers', '#'])
# configure ENV for platform
env_base.platform_exporters = platform_exporters
+env_base.platform_apis = platform_apis
"""
sys.path.append("./platform/"+env_base["platform"])
@@ -264,9 +274,12 @@ if selected_platform in platform_list:
if len(pieces) > 0:
basename = pieces[0]
basename = basename.replace('\\\\', '/')
- env.vs_srcs = env.vs_srcs + [basename + ".cpp"]
- env.vs_incs = env.vs_incs + [basename + ".h"]
- # print basename
+ if os.path.isfile(basename + ".h"):
+ env.vs_incs = env.vs_incs + [basename + ".h"]
+ if os.path.isfile(basename + ".c"):
+ env.vs_srcs = env.vs_srcs + [basename + ".c"]
+ elif os.path.isfile(basename + ".cpp"):
+ env.vs_srcs = env.vs_srcs + [basename + ".cpp"]
env.AddToVSProject = AddToVSProject
env.extra_suffix = ""
@@ -356,16 +369,11 @@ if selected_platform in platform_list:
suffix += env.extra_suffix
- env["PROGSUFFIX"] = suffix + env["PROGSUFFIX"]
- env["OBJSUFFIX"] = suffix + env["OBJSUFFIX"]
- env["LIBSUFFIX"] = suffix + env["LIBSUFFIX"]
- env["SHLIBSUFFIX"] = suffix + env["SHLIBSUFFIX"]
-
sys.path.remove("./platform/" + selected_platform)
sys.modules.pop('detect')
env.module_list = []
- env.doc_class_path={}
+ env.doc_class_path = {}
for x in module_list:
if not env['module_' + x + '_enabled']:
@@ -381,14 +389,22 @@ if selected_platform in platform_list:
doc_classes = config.get_doc_classes()
doc_path = config.get_doc_path()
for c in doc_classes:
- env.doc_class_path[c]="modules/"+x+"/"+doc_path
+ env.doc_class_path[c] = "modules/" + x + "/" + doc_path
except:
pass
-
sys.path.remove(tmppath)
sys.modules.pop('config')
+ methods.update_version(env.module_version_string)
+
+ suffix += env.module_version_string
+
+ env["PROGSUFFIX"] = suffix + env["PROGSUFFIX"]
+ env["OBJSUFFIX"] = suffix + env["OBJSUFFIX"]
+ env["LIBSUFFIX"] = suffix + env["LIBSUFFIX"]
+ env["SHLIBSUFFIX"] = suffix + env["SHLIBSUFFIX"]
+
if (env.use_ptrcall):
env.Append(CPPFLAGS=['-DPTRCALL_ENABLED'])
@@ -426,6 +442,7 @@ if selected_platform in platform_list:
SConscript("editor/SCsub")
SConscript("drivers/SCsub")
+ SConscript("platform/SCsub")
SConscript("modules/SCsub")
SConscript("main/SCsub")
@@ -435,6 +452,7 @@ if selected_platform in platform_list:
if env['vsproj']:
env['CPPPATH'] = [Dir(path) for path in env['CPPPATH']]
methods.generate_vs_project(env, GetOption("num_jobs"))
+ methods.generate_cpp_hint_file("cpp.hint")
# Check for the existence of headers
conf = Configure(env)
diff --git a/compat.py b/compat.py
index e1bc0ed673..32c685f5b8 100644
--- a/compat.py
+++ b/compat.py
@@ -12,6 +12,8 @@ if sys.version_info < (3,):
return cStringIO.StringIO()
def encode_utf8(x):
return x
+ def decode_utf8(x):
+ return x
def iteritems(d):
return d.iteritems()
def escape_string(s):
@@ -38,6 +40,8 @@ else:
import codecs
def encode_utf8(x):
return codecs.utf_8_encode(x)[0]
+ def decode_utf8(x):
+ return codecs.utf_8_decode(x)[0]
def iteritems(d):
return iter(d.items())
def charcode_to_c_escapes(c):
diff --git a/core/array.cpp b/core/array.cpp
index 30184a002e..b7d4ae413a 100644
--- a/core/array.cpp
+++ b/core/array.cpp
@@ -233,9 +233,10 @@ struct _ArrayVariantSort {
}
};
-void Array::sort() {
+Array &Array::sort() {
_p->array.sort_custom<_ArrayVariantSort>();
+ return *this;
}
struct _ArrayVariantSortCustom {
@@ -253,19 +254,64 @@ struct _ArrayVariantSortCustom {
return res;
}
};
-void Array::sort_custom(Object *p_obj, const StringName &p_function) {
+Array &Array::sort_custom(Object *p_obj, const StringName &p_function) {
- ERR_FAIL_NULL(p_obj);
+ ERR_FAIL_NULL_V(p_obj, *this);
SortArray<Variant, _ArrayVariantSortCustom> avs;
avs.compare.obj = p_obj;
avs.compare.func = p_function;
avs.sort(_p->array.ptr(), _p->array.size());
+ return *this;
+}
+
+template <typename Less>
+_FORCE_INLINE_ int bisect(const Vector<Variant> &p_array, const Variant &p_value, bool p_before, const Less &p_less) {
+
+ int lo = 0;
+ int hi = p_array.size();
+ if (p_before) {
+ while (lo < hi) {
+ const int mid = (lo + hi) / 2;
+ if (p_less(p_array.get(mid), p_value)) {
+ lo = mid + 1;
+ } else {
+ hi = mid;
+ }
+ }
+ } else {
+ while (lo < hi) {
+ const int mid = (lo + hi) / 2;
+ if (p_less(p_value, p_array.get(mid))) {
+ hi = mid;
+ } else {
+ lo = mid + 1;
+ }
+ }
+ }
+ return lo;
+}
+
+int Array::bsearch(const Variant &p_value, bool p_before) {
+
+ return bisect(_p->array, p_value, p_before, _ArrayVariantSort());
+}
+
+int Array::bsearch_custom(const Variant &p_value, Object *p_obj, const StringName &p_function, bool p_before) {
+
+ ERR_FAIL_NULL_V(p_obj, 0);
+
+ _ArrayVariantSortCustom less;
+ less.obj = p_obj;
+ less.func = p_function;
+
+ return bisect(_p->array, p_value, p_before, less);
}
-void Array::invert() {
+Array &Array::invert() {
_p->array.invert();
+ return *this;
}
void Array::push_front(const Variant &p_value) {
diff --git a/core/array.h b/core/array.h
index 8a647dd13b..3d70a31d2f 100644
--- a/core/array.h
+++ b/core/array.h
@@ -68,9 +68,11 @@ public:
Variant front() const;
Variant back() const;
- void sort();
- void sort_custom(Object *p_obj, const StringName &p_function);
- void invert();
+ Array &sort();
+ Array &sort_custom(Object *p_obj, const StringName &p_function);
+ int bsearch(const Variant &p_value, bool p_before = true);
+ int bsearch_custom(const Variant &p_value, Object *p_obj, const StringName &p_function, bool p_before = true);
+ Array &invert();
int find(const Variant &p_value, int p_from = 0) const;
int rfind(const Variant &p_value, int p_from = -1) const;
diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp
index b47e611a51..999befaf67 100644
--- a/core/bind/core_bind.cpp
+++ b/core/bind/core_bind.cpp
@@ -413,6 +413,7 @@ String _OS::get_latin_keyboard_variant() const {
case OS::LATIN_KEYBOARD_QZERTY: return "QZERTY";
case OS::LATIN_KEYBOARD_DVORAK: return "DVORAK";
case OS::LATIN_KEYBOARD_NEO: return "NEO";
+ case OS::LATIN_KEYBOARD_COLEMAK: return "COLEMAK";
default: return "ERROR";
}
}
@@ -887,9 +888,9 @@ void _OS::dump_resources_to_file(const String &p_file) {
OS::get_singleton()->dump_resources_to_file(p_file.utf8().get_data());
}
-String _OS::get_data_dir() const {
+String _OS::get_user_data_dir() const {
- return OS::get_singleton()->get_data_dir();
+ return OS::get_singleton()->get_user_data_dir();
};
Error _OS::native_video_play(String p_path, float p_volume, String p_audio_track, String p_subtitle_track) {
@@ -1087,7 +1088,7 @@ void _OS::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_static_memory_peak_usage"), &_OS::get_static_memory_peak_usage);
ClassDB::bind_method(D_METHOD("get_dynamic_memory_usage"), &_OS::get_dynamic_memory_usage);
- ClassDB::bind_method(D_METHOD("get_data_dir"), &_OS::get_data_dir);
+ ClassDB::bind_method(D_METHOD("get_user_data_dir"), &_OS::get_user_data_dir);
ClassDB::bind_method(D_METHOD("get_system_dir", "dir"), &_OS::get_system_dir);
ClassDB::bind_method(D_METHOD("get_unique_id"), &_OS::get_unique_id);
@@ -1315,6 +1316,16 @@ Vector<int> _Geometry::triangulate_polygon(const Vector<Vector2> &p_polygon) {
return Geometry::triangulate_polygon(p_polygon);
}
+Vector<Point2> _Geometry::convex_hull_2d(const Vector<Point2> &p_points) {
+
+ return Geometry::convex_hull_2d(p_points);
+}
+
+Vector<Vector3> _Geometry::clip_polygon(const Vector<Vector3> &p_points, const Plane &p_plane) {
+
+ return Geometry::clip_polygon(p_points, p_plane);
+}
+
Dictionary _Geometry::make_atlas(const Vector<Size2> &p_rects) {
Dictionary ret;
@@ -1375,6 +1386,8 @@ void _Geometry::_bind_methods() {
ClassDB::bind_method(D_METHOD("point_is_inside_triangle", "point", "a", "b", "c"), &_Geometry::point_is_inside_triangle);
ClassDB::bind_method(D_METHOD("triangulate_polygon", "polygon"), &_Geometry::triangulate_polygon);
+ ClassDB::bind_method(D_METHOD("convex_hull_2d", "points"), &_Geometry::convex_hull_2d);
+ ClassDB::bind_method(D_METHOD("clip_polygon", "points", "plane"), &_Geometry::clip_polygon);
ClassDB::bind_method(D_METHOD("make_atlas", "sizes"), &_Geometry::make_atlas);
}
@@ -2579,6 +2592,16 @@ bool _Engine::is_in_physics_frame() const {
return Engine::get_singleton()->is_in_physics_frame();
}
+bool _Engine::has_singleton(const String &p_name) const {
+
+ return Engine::get_singleton()->has_singleton(p_name);
+}
+
+Object *_Engine::get_singleton_object(const String &p_name) const {
+
+ return Engine::get_singleton()->get_singleton_object(p_name);
+}
+
void _Engine::set_editor_hint(bool p_enabled) {
Engine::get_singleton()->set_editor_hint(p_enabled);
@@ -2608,6 +2631,9 @@ void _Engine::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_in_physics_frame"), &_Engine::is_in_physics_frame);
+ ClassDB::bind_method(D_METHOD("has_singleton", "name"), &_Engine::has_singleton);
+ ClassDB::bind_method(D_METHOD("get_singleton", "name"), &_Engine::get_singleton_object);
+
ClassDB::bind_method(D_METHOD("set_editor_hint", "enabled"), &_Engine::set_editor_hint);
ClassDB::bind_method(D_METHOD("is_editor_hint"), &_Engine::is_editor_hint);
}
diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h
index 7f8c734e36..8163b08d76 100644
--- a/core/bind/core_bind.h
+++ b/core/bind/core_bind.h
@@ -297,7 +297,7 @@ public:
String get_system_dir(SystemDir p_dir) const;
- String get_data_dir() const;
+ String get_user_data_dir() const;
void alert(const String &p_alert, const String &p_title = "ALERT!");
@@ -363,6 +363,8 @@ public:
int get_uv84_normal_bit(const Vector3 &p_vector);
Vector<int> triangulate_polygon(const Vector<Vector2> &p_polygon);
+ Vector<Point2> convex_hull_2d(const Vector<Point2> &p_points);
+ Vector<Vector3> clip_polygon(const Vector<Vector3> &p_points, const Plane &p_plane);
Dictionary make_atlas(const Vector<Size2> &p_rects);
@@ -668,6 +670,9 @@ public:
bool is_in_physics_frame() const;
+ bool has_singleton(const String &p_name) const;
+ Object *get_singleton_object(const String &p_name) const;
+
void set_editor_hint(bool p_enabled);
bool is_editor_hint() const;
diff --git a/core/class_db.cpp b/core/class_db.cpp
index f5ddd9c761..57e88044b5 100644
--- a/core/class_db.cpp
+++ b/core/class_db.cpp
@@ -187,6 +187,25 @@ MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_
return md;
}
+MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5, const char *p_arg6, const char *p_arg7, const char *p_arg8, const char *p_arg9, const char *p_arg10, const char *p_arg11) {
+
+ MethodDefinition md;
+ md.name = StaticCString::create(p_name);
+ md.args.resize(11);
+ md.args[0] = StaticCString::create(p_arg1);
+ md.args[1] = StaticCString::create(p_arg2);
+ md.args[2] = StaticCString::create(p_arg3);
+ md.args[3] = StaticCString::create(p_arg4);
+ md.args[4] = StaticCString::create(p_arg5);
+ md.args[5] = StaticCString::create(p_arg6);
+ md.args[6] = StaticCString::create(p_arg7);
+ md.args[7] = StaticCString::create(p_arg8);
+ md.args[8] = StaticCString::create(p_arg9);
+ md.args[9] = StaticCString::create(p_arg10);
+ md.args[10] = StaticCString::create(p_arg11);
+ return md;
+}
+
#endif
ClassDB::APIType ClassDB::current_api = API_CORE;
@@ -205,6 +224,7 @@ ClassDB::ClassInfo::ClassInfo() {
creation_func = NULL;
inherits_ptr = NULL;
disabled = false;
+ exposed = false;
}
ClassDB::ClassInfo::~ClassInfo() {
}
@@ -1284,6 +1304,15 @@ bool ClassDB::is_class_enabled(StringName p_class) {
return !ti->disabled;
}
+bool ClassDB::is_class_exposed(StringName p_class) {
+
+ OBJTYPE_RLOCK;
+
+ ClassInfo *ti = classes.getptr(p_class);
+ ERR_FAIL_COND_V(!ti, false);
+ return ti->exposed;
+}
+
StringName ClassDB::get_category(const StringName &p_node) {
ERR_FAIL_COND_V(!classes.has(p_node), StringName());
diff --git a/core/class_db.h b/core/class_db.h
index f6b97748b0..24db4c61bb 100644
--- a/core/class_db.h
+++ b/core/class_db.h
@@ -66,6 +66,7 @@ MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_
MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5, const char *p_arg6, const char *p_arg7, const char *p_arg8);
MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5, const char *p_arg6, const char *p_arg7, const char *p_arg8, const char *p_arg9);
MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5, const char *p_arg6, const char *p_arg7, const char *p_arg8, const char *p_arg9, const char *p_arg10);
+MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5, const char *p_arg6, const char *p_arg7, const char *p_arg8, const char *p_arg9, const char *p_arg10, const char *p_arg11);
#else
@@ -127,6 +128,7 @@ public:
StringName inherits;
StringName name;
bool disabled;
+ bool exposed;
Object *(*creation_func)();
ClassInfo();
~ClassInfo();
@@ -168,6 +170,7 @@ public:
ClassInfo *t = classes.getptr(T::get_class_static());
ERR_FAIL_COND(!t);
t->creation_func = &creator<T>;
+ t->exposed = true;
T::register_custom_data_to_otdb();
}
@@ -176,6 +179,9 @@ public:
GLOBAL_LOCK_FUNCTION;
T::initialize_class();
+ ClassInfo *t = classes.getptr(T::get_class_static());
+ ERR_FAIL_COND(!t);
+ t->exposed = true;
//nothing
}
@@ -193,6 +199,7 @@ public:
ClassInfo *t = classes.getptr(T::get_class_static());
ERR_FAIL_COND(!t);
t->creation_func = &_create_ptr_func<T>;
+ t->exposed = true;
T::register_custom_data_to_otdb();
}
@@ -347,6 +354,8 @@ public:
static void set_class_enabled(StringName p_class, bool p_enable);
static bool is_class_enabled(StringName p_class);
+ static bool is_class_exposed(StringName p_class);
+
static void add_resource_base_extension(const StringName &p_extension, const StringName &p_class);
static void get_resource_base_extensions(List<String> *p_extensions);
static void get_extensions_for_type(const StringName &p_class, List<String> *p_extensions);
diff --git a/core/command_queue_mt.h b/core/command_queue_mt.h
index f99e16da15..e37d593f9f 100644
--- a/core/command_queue_mt.h
+++ b/core/command_queue_mt.h
@@ -227,6 +227,27 @@ class CommandQueueMT {
virtual void call() { (instance->*method)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11); }
};
+ template <class T, class M, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9, class P10, class P11, class P12>
+ struct Command12 : public CommandBase {
+
+ T *instance;
+ M method;
+ typename GetSimpleTypeT<P1>::type_t p1;
+ typename GetSimpleTypeT<P2>::type_t p2;
+ typename GetSimpleTypeT<P3>::type_t p3;
+ typename GetSimpleTypeT<P4>::type_t p4;
+ typename GetSimpleTypeT<P5>::type_t p5;
+ typename GetSimpleTypeT<P6>::type_t p6;
+ typename GetSimpleTypeT<P7>::type_t p7;
+ typename GetSimpleTypeT<P8>::type_t p8;
+ typename GetSimpleTypeT<P9>::type_t p9;
+ typename GetSimpleTypeT<P10>::type_t p10;
+ typename GetSimpleTypeT<P11>::type_t p11;
+ typename GetSimpleTypeT<P12>::type_t p12;
+
+ virtual void call() { (instance->*method)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12); }
+ };
+
/* comands that return */
template <class T, class M, class R>
@@ -906,6 +927,31 @@ public:
if (sync) sync->post();
}
+ template <class T, class M, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9, class P10, class P11, class P12>
+ void push(T *p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, P9 p9, P10 p10, P11 p11, P12 p12) {
+
+ Command12<T, M, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12> *cmd = allocate_and_lock<Command12<T, M, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12> >();
+
+ cmd->instance = p_instance;
+ cmd->method = p_method;
+ cmd->p1 = p1;
+ cmd->p2 = p2;
+ cmd->p3 = p3;
+ cmd->p4 = p4;
+ cmd->p5 = p5;
+ cmd->p6 = p6;
+ cmd->p7 = p7;
+ cmd->p8 = p8;
+ cmd->p9 = p9;
+ cmd->p10 = p10;
+ cmd->p11 = p11;
+ cmd->p12 = p12;
+
+ unlock();
+
+ if (sync) sync->post();
+ }
+
/*** PUSH AND RET COMMANDS ***/
template <class T, class M, class R>
diff --git a/core/dictionary.cpp b/core/dictionary.cpp
index bb2e892951..48e65c734f 100644
--- a/core/dictionary.cpp
+++ b/core/dictionary.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "dictionary.h"
+#include "ordered_hash_map.h"
#include "safe_refcount.h"
#include "variant.h"
@@ -39,22 +40,8 @@ struct _DictionaryVariantHash {
struct DictionaryPrivate {
- struct Data {
- Variant variant;
- int order;
- };
-
SafeRefCount refcount;
- HashMap<Variant, Data, _DictionaryVariantHash> variant_map;
- int counter;
-};
-
-struct DictionaryPrivateSort {
-
- bool operator()(const HashMap<Variant, DictionaryPrivate::Data, _DictionaryVariantHash>::Pair *A, const HashMap<Variant, DictionaryPrivate::Data, _DictionaryVariantHash>::Pair *B) const {
-
- return A->data.order < B->data.order;
- }
+ OrderedHashMap<Variant, Variant, _DictionaryVariantHash> variant_map;
};
void Dictionary::get_key_list(List<Variant> *p_keys) const {
@@ -62,61 +49,45 @@ void Dictionary::get_key_list(List<Variant> *p_keys) const {
if (_p->variant_map.empty())
return;
- int count = _p->variant_map.size();
- const HashMap<Variant, DictionaryPrivate::Data, _DictionaryVariantHash>::Pair **pairs = (const HashMap<Variant, DictionaryPrivate::Data, _DictionaryVariantHash>::Pair **)alloca(count * sizeof(HashMap<Variant, DictionaryPrivate::Data, _DictionaryVariantHash>::Pair *));
- _p->variant_map.get_key_value_ptr_array(pairs);
-
- SortArray<const HashMap<Variant, DictionaryPrivate::Data, _DictionaryVariantHash>::Pair *, DictionaryPrivateSort> sort;
- sort.sort(pairs, count);
-
- for (int i = 0; i < count; i++) {
- p_keys->push_back(pairs[i]->key);
+ for (OrderedHashMap<Variant, Variant, _DictionaryVariantHash>::Element E = _p->variant_map.front(); E; E = E.next()) {
+ p_keys->push_back(E.key());
}
}
Variant &Dictionary::operator[](const Variant &p_key) {
- DictionaryPrivate::Data *v = _p->variant_map.getptr(p_key);
-
- if (!v) {
-
- DictionaryPrivate::Data d;
- d.order = _p->counter++;
- _p->variant_map[p_key] = d;
- v = _p->variant_map.getptr(p_key);
- }
- return v->variant;
+ return _p->variant_map[p_key];
}
const Variant &Dictionary::operator[](const Variant &p_key) const {
- return _p->variant_map[p_key].variant;
+ return _p->variant_map[p_key];
}
const Variant *Dictionary::getptr(const Variant &p_key) const {
- const DictionaryPrivate::Data *v = _p->variant_map.getptr(p_key);
- if (!v)
+ OrderedHashMap<Variant, Variant, _DictionaryVariantHash>::ConstElement E = ((const OrderedHashMap<Variant, Variant, _DictionaryVariantHash> *)&_p->variant_map)->find(p_key);
+
+ if (!E)
return NULL;
- else
- return &v->variant;
+ return &E.get();
}
Variant *Dictionary::getptr(const Variant &p_key) {
- DictionaryPrivate::Data *v = _p->variant_map.getptr(p_key);
- if (!v)
+ OrderedHashMap<Variant, Variant, _DictionaryVariantHash>::Element E = _p->variant_map.find(p_key);
+
+ if (!E)
return NULL;
- else
- return &v->variant;
+ return &E.get();
}
Variant Dictionary::get_valid(const Variant &p_key) const {
- DictionaryPrivate::Data *v = _p->variant_map.getptr(p_key);
- if (!v)
+ OrderedHashMap<Variant, Variant, _DictionaryVariantHash>::ConstElement E = ((const OrderedHashMap<Variant, Variant, _DictionaryVariantHash> *)&_p->variant_map)->find(p_key);
+
+ if (!E)
return Variant();
- else
- return v->variant;
+ return E.get();
}
int Dictionary::size() const {
@@ -171,7 +142,6 @@ void Dictionary::_ref(const Dictionary &p_from) const {
void Dictionary::clear() {
_p->variant_map.clear();
- _p->counter = 0;
}
void Dictionary::_unref() const {
@@ -205,15 +175,10 @@ Array Dictionary::keys() const {
if (_p->variant_map.empty())
return varr;
- int count = _p->variant_map.size();
- const HashMap<Variant, DictionaryPrivate::Data, _DictionaryVariantHash>::Pair **pairs = (const HashMap<Variant, DictionaryPrivate::Data, _DictionaryVariantHash>::Pair **)alloca(count * sizeof(HashMap<Variant, DictionaryPrivate::Data, _DictionaryVariantHash>::Pair *));
- _p->variant_map.get_key_value_ptr_array(pairs);
-
- SortArray<const HashMap<Variant, DictionaryPrivate::Data, _DictionaryVariantHash>::Pair *, DictionaryPrivateSort> sort;
- sort.sort(pairs, count);
-
- for (int i = 0; i < count; i++) {
- varr[i] = pairs[i]->key;
+ int i = 0;
+ for (OrderedHashMap<Variant, Variant, _DictionaryVariantHash>::Element E = _p->variant_map.front(); E; E = E.next()) {
+ varr[i] = E.key();
+ i++;
}
return varr;
@@ -226,15 +191,10 @@ Array Dictionary::values() const {
if (_p->variant_map.empty())
return varr;
- int count = _p->variant_map.size();
- const HashMap<Variant, DictionaryPrivate::Data, _DictionaryVariantHash>::Pair **pairs = (const HashMap<Variant, DictionaryPrivate::Data, _DictionaryVariantHash>::Pair **)alloca(count * sizeof(HashMap<Variant, DictionaryPrivate::Data, _DictionaryVariantHash>::Pair *));
- _p->variant_map.get_key_value_ptr_array(pairs);
-
- SortArray<const HashMap<Variant, DictionaryPrivate::Data, _DictionaryVariantHash>::Pair *, DictionaryPrivateSort> sort;
- sort.sort(pairs, count);
-
- for (int i = 0; i < count; i++) {
- varr[i] = pairs[i]->data.variant;
+ int i = 0;
+ for (OrderedHashMap<Variant, Variant, _DictionaryVariantHash>::Element E = _p->variant_map.front(); E; E = E.next()) {
+ varr[i] = E.get();
+ i++;
}
return varr;
@@ -242,7 +202,15 @@ Array Dictionary::values() const {
const Variant *Dictionary::next(const Variant *p_key) const {
- return _p->variant_map.next(p_key);
+ if (p_key == NULL) {
+ // caller wants to get the first element
+ return &_p->variant_map.front().key();
+ }
+ OrderedHashMap<Variant, Variant, _DictionaryVariantHash>::Element E = _p->variant_map.find(*p_key);
+
+ if (E && E.next())
+ return &E.next().key();
+ return NULL;
}
Dictionary Dictionary::copy() const {
@@ -273,7 +241,6 @@ Dictionary::Dictionary() {
_p = memnew(DictionaryPrivate);
_p->refcount.init();
- _p->counter = 0;
}
Dictionary::~Dictionary() {
diff --git a/core/engine.cpp b/core/engine.cpp
index c609ae9520..53c7a73b43 100644
--- a/core/engine.cpp
+++ b/core/engine.cpp
@@ -84,22 +84,47 @@ Dictionary Engine::get_version_info() const {
#else
dict["patch"] = 0;
#endif
- dict["status"] = _MKSTR(VERSION_STATUS);
- dict["revision"] = _MKSTR(VERSION_REVISION);
+ dict["status"] = VERSION_STATUS;
+ dict["build"] = VERSION_BUILD;
dict["year"] = VERSION_YEAR;
- String hash = String(VERSION_HASH);
+ String hash = VERSION_HASH;
dict["hash"] = hash.length() == 0 ? String("unknown") : hash;
String stringver = String(dict["major"]) + "." + String(dict["minor"]);
if ((int)dict["patch"] != 0)
stringver += "." + String(dict["patch"]);
- stringver += "-" + String(dict["status"]) + " (" + String(dict["revision"]) + ")";
+ stringver += "-" + String(dict["status"]) + " (" + String(dict["build"]) + ")";
dict["string"] = stringver;
return dict;
}
+void Engine::add_singleton(const Singleton &p_singleton) {
+
+ singletons.push_back(p_singleton);
+ singleton_ptrs[p_singleton.name] = p_singleton.ptr;
+}
+
+Object *Engine::get_singleton_object(const String &p_name) const {
+
+ const Map<StringName, Object *>::Element *E = singleton_ptrs.find(p_name);
+ ERR_EXPLAIN("Failed to retrieve non-existent singleton '" + p_name + "'");
+ ERR_FAIL_COND_V(!E, NULL);
+ return E->get();
+};
+
+bool Engine::has_singleton(const String &p_name) const {
+
+ return singleton_ptrs.has(p_name);
+};
+
+void Engine::get_singletons(List<Singleton> *p_singletons) {
+
+ for (List<Singleton>::Element *E = singletons.front(); E; E = E->next())
+ p_singletons->push_back(E->get());
+}
+
Engine *Engine::singleton = NULL;
Engine *Engine::get_singleton() {
diff --git a/core/engine.h b/core/engine.h
index 3b4979582f..4a573c1539 100644
--- a/core/engine.h
+++ b/core/engine.h
@@ -37,6 +37,17 @@
class Engine {
+public:
+ struct Singleton {
+ StringName name;
+ Object *ptr;
+ Singleton(const StringName &p_name = StringName(), Object *p_ptr = NULL)
+ : name(p_name),
+ ptr(p_ptr) {
+ }
+ };
+
+private:
friend class Main;
uint64_t frames_drawn;
@@ -54,6 +65,9 @@ class Engine {
uint64_t _idle_frames;
bool _in_physics;
+ List<Singleton> singletons;
+ Map<StringName, Object *> singleton_ptrs;
+
bool editor_hint;
static Engine *singleton;
@@ -83,6 +97,11 @@ public:
void set_frame_delay(uint32_t p_msec);
uint32_t get_frame_delay() const;
+ void add_singleton(const Singleton &p_singleton);
+ void get_singletons(List<Singleton> *p_singletons);
+ bool has_singleton(const String &p_name) const;
+ Object *get_singleton_object(const String &p_name) const;
+
_FORCE_INLINE_ bool get_use_pixel_snap() const { return _pixel_snap; }
#ifdef TOOLS_ENABLED
diff --git a/core/error_macros.cpp b/core/error_macros.cpp
index 170a22e8dd..7d85aa9001 100644
--- a/core/error_macros.cpp
+++ b/core/error_macros.cpp
@@ -97,3 +97,10 @@ void _err_print_error(const char *p_function, const char *p_file, int p_line, co
_err_error_exists = false;
}
}
+
+void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, bool fatal) {
+
+ String fstr(fatal ? "FATAL: " : "");
+ String err(fstr + "Index" + p_index_str + "=" + itos(p_index) + " out of size (" + p_size_str + "=" + itos(p_size) + ")");
+ _err_print_error(p_function, p_file, p_line, err.utf8().get_data());
+}
diff --git a/core/error_macros.h b/core/error_macros.h
index 1fa7f2c134..8d2f588706 100644
--- a/core/error_macros.h
+++ b/core/error_macros.h
@@ -76,6 +76,7 @@ void add_error_handler(ErrorHandlerList *p_handler);
void remove_error_handler(ErrorHandlerList *p_handler);
void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
+void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, bool fatal = false);
#ifndef _STR
#define _STR(m_x) #m_x
@@ -129,13 +130,13 @@ extern bool _err_error_exists;
// (*): See https://stackoverflow.com/questions/257418/do-while-0-what-is-it-good-for
-#define ERR_FAIL_INDEX(m_index, m_size) \
- do { \
- if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
- _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Index " _STR(m_index) " out of size (" _STR(m_size) ")."); \
- return; \
- } else \
- _err_error_exists = false; \
+#define ERR_FAIL_INDEX(m_index, m_size) \
+ do { \
+ if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
+ _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size)); \
+ return; \
+ } else \
+ _err_error_exists = false; \
} while (0); // (*)
/** An index has failed if m_index<0 or m_index >=m_size, the function exists.
@@ -143,24 +144,24 @@ extern bool _err_error_exists;
* appropriate error condition from error_macros.h
*/
-#define ERR_FAIL_INDEX_V(m_index, m_size, m_retval) \
- do { \
- if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
- _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Index " _STR(m_index) " out of size (" _STR(m_size) ")."); \
- return m_retval; \
- } else \
- _err_error_exists = false; \
+#define ERR_FAIL_INDEX_V(m_index, m_size, m_retval) \
+ do { \
+ if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
+ _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size)); \
+ return m_retval; \
+ } else \
+ _err_error_exists = false; \
} while (0); // (*)
/** Use this one if there is no sensible fallback, that is, the error is unrecoverable.
* We'll return a null reference and try to keep running.
*/
-#define CRASH_BAD_INDEX(m_index, m_size) \
- do { \
- if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
- _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Index " _STR(m_index) " out of size (" _STR(m_size) ")."); \
- GENERATE_TRAP \
- } \
+#define CRASH_BAD_INDEX(m_index, m_size) \
+ do { \
+ if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
+ _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), true); \
+ GENERATE_TRAP \
+ } \
} while (0); // (*)
/** An error condition happened (m_cond tested true) (WARNING this is the opposite as assert().
diff --git a/core/global_constants.cpp b/core/global_constants.cpp
index 6f58af2ccf..48101c8cf1 100644
--- a/core/global_constants.cpp
+++ b/core/global_constants.cpp
@@ -86,6 +86,8 @@ static Vector<_GlobalConstant> _global_constants;
VARIANT_ENUM_CAST(KeyList);
VARIANT_ENUM_CAST(KeyModifierMask);
+VARIANT_ENUM_CAST(ButtonList);
+VARIANT_ENUM_CAST(JoystickList);
void register_global_constants() {
@@ -367,82 +369,84 @@ void register_global_constants() {
BIND_GLOBAL_ENUM_CONSTANT(KEY_MASK_GROUP_SWITCH);
// mouse
- BIND_GLOBAL_CONSTANT(BUTTON_LEFT);
- BIND_GLOBAL_CONSTANT(BUTTON_RIGHT);
- BIND_GLOBAL_CONSTANT(BUTTON_MIDDLE);
- BIND_GLOBAL_CONSTANT(BUTTON_WHEEL_UP);
- BIND_GLOBAL_CONSTANT(BUTTON_WHEEL_DOWN);
- BIND_GLOBAL_CONSTANT(BUTTON_WHEEL_LEFT);
- BIND_GLOBAL_CONSTANT(BUTTON_WHEEL_RIGHT);
- BIND_GLOBAL_CONSTANT(BUTTON_MASK_LEFT);
- BIND_GLOBAL_CONSTANT(BUTTON_MASK_RIGHT);
- BIND_GLOBAL_CONSTANT(BUTTON_MASK_MIDDLE);
+ BIND_GLOBAL_ENUM_CONSTANT(BUTTON_LEFT);
+ BIND_GLOBAL_ENUM_CONSTANT(BUTTON_RIGHT);
+ BIND_GLOBAL_ENUM_CONSTANT(BUTTON_MIDDLE);
+ BIND_GLOBAL_ENUM_CONSTANT(BUTTON_WHEEL_UP);
+ BIND_GLOBAL_ENUM_CONSTANT(BUTTON_WHEEL_DOWN);
+ BIND_GLOBAL_ENUM_CONSTANT(BUTTON_WHEEL_LEFT);
+ BIND_GLOBAL_ENUM_CONSTANT(BUTTON_WHEEL_RIGHT);
+ BIND_GLOBAL_ENUM_CONSTANT(BUTTON_MASK_LEFT);
+ BIND_GLOBAL_ENUM_CONSTANT(BUTTON_MASK_RIGHT);
+ BIND_GLOBAL_ENUM_CONSTANT(BUTTON_MASK_MIDDLE);
//joypads
- BIND_GLOBAL_CONSTANT(JOY_BUTTON_0);
- BIND_GLOBAL_CONSTANT(JOY_BUTTON_1);
- BIND_GLOBAL_CONSTANT(JOY_BUTTON_2);
- BIND_GLOBAL_CONSTANT(JOY_BUTTON_3);
- BIND_GLOBAL_CONSTANT(JOY_BUTTON_4);
- BIND_GLOBAL_CONSTANT(JOY_BUTTON_5);
- BIND_GLOBAL_CONSTANT(JOY_BUTTON_6);
- BIND_GLOBAL_CONSTANT(JOY_BUTTON_7);
- BIND_GLOBAL_CONSTANT(JOY_BUTTON_8);
- BIND_GLOBAL_CONSTANT(JOY_BUTTON_9);
- BIND_GLOBAL_CONSTANT(JOY_BUTTON_10);
- BIND_GLOBAL_CONSTANT(JOY_BUTTON_11);
- BIND_GLOBAL_CONSTANT(JOY_BUTTON_12);
- BIND_GLOBAL_CONSTANT(JOY_BUTTON_13);
- BIND_GLOBAL_CONSTANT(JOY_BUTTON_14);
- BIND_GLOBAL_CONSTANT(JOY_BUTTON_15);
- BIND_GLOBAL_CONSTANT(JOY_BUTTON_MAX);
-
- BIND_GLOBAL_CONSTANT(JOY_SONY_CIRCLE);
- BIND_GLOBAL_CONSTANT(JOY_SONY_X);
- BIND_GLOBAL_CONSTANT(JOY_SONY_SQUARE);
- BIND_GLOBAL_CONSTANT(JOY_SONY_TRIANGLE);
-
- BIND_GLOBAL_CONSTANT(JOY_XBOX_B);
- BIND_GLOBAL_CONSTANT(JOY_XBOX_A);
- BIND_GLOBAL_CONSTANT(JOY_XBOX_X);
- BIND_GLOBAL_CONSTANT(JOY_XBOX_Y);
-
- BIND_GLOBAL_CONSTANT(JOY_DS_A);
- BIND_GLOBAL_CONSTANT(JOY_DS_B);
- BIND_GLOBAL_CONSTANT(JOY_DS_X);
- BIND_GLOBAL_CONSTANT(JOY_DS_Y);
-
- BIND_GLOBAL_CONSTANT(JOY_SELECT);
- BIND_GLOBAL_CONSTANT(JOY_START);
- BIND_GLOBAL_CONSTANT(JOY_DPAD_UP);
- BIND_GLOBAL_CONSTANT(JOY_DPAD_DOWN);
- BIND_GLOBAL_CONSTANT(JOY_DPAD_LEFT);
- BIND_GLOBAL_CONSTANT(JOY_DPAD_RIGHT);
- BIND_GLOBAL_CONSTANT(JOY_L);
- BIND_GLOBAL_CONSTANT(JOY_L2);
- BIND_GLOBAL_CONSTANT(JOY_L3);
- BIND_GLOBAL_CONSTANT(JOY_R);
- BIND_GLOBAL_CONSTANT(JOY_R2);
- BIND_GLOBAL_CONSTANT(JOY_R3);
-
- BIND_GLOBAL_CONSTANT(JOY_AXIS_0);
- BIND_GLOBAL_CONSTANT(JOY_AXIS_1);
- BIND_GLOBAL_CONSTANT(JOY_AXIS_2);
- BIND_GLOBAL_CONSTANT(JOY_AXIS_3);
- BIND_GLOBAL_CONSTANT(JOY_AXIS_4);
- BIND_GLOBAL_CONSTANT(JOY_AXIS_5);
- BIND_GLOBAL_CONSTANT(JOY_AXIS_6);
- BIND_GLOBAL_CONSTANT(JOY_AXIS_7);
- BIND_GLOBAL_CONSTANT(JOY_AXIS_MAX);
-
- BIND_GLOBAL_CONSTANT(JOY_ANALOG_LX);
- BIND_GLOBAL_CONSTANT(JOY_ANALOG_LY);
-
- BIND_GLOBAL_CONSTANT(JOY_ANALOG_RX);
- BIND_GLOBAL_CONSTANT(JOY_ANALOG_RY);
-
- BIND_GLOBAL_CONSTANT(JOY_ANALOG_L2);
- BIND_GLOBAL_CONSTANT(JOY_ANALOG_R2);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_0);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_1);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_2);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_3);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_4);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_5);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_6);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_7);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_8);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_9);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_10);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_11);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_12);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_13);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_14);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_15);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_MAX);
+
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_SONY_CIRCLE);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_SONY_X);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_SONY_SQUARE);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_SONY_TRIANGLE);
+
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_XBOX_B);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_XBOX_A);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_XBOX_X);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_XBOX_Y);
+
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_DS_A);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_DS_B);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_DS_X);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_DS_Y);
+
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_SELECT);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_START);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_DPAD_UP);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_DPAD_DOWN);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_DPAD_LEFT);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_DPAD_RIGHT);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_L);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_L2);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_L3);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_R);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_R2);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_R3);
+
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_0);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_1);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_2);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_3);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_4);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_5);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_6);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_7);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_8);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_9);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_MAX);
+
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_ANALOG_LX);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_ANALOG_LY);
+
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_ANALOG_RX);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_ANALOG_RY);
+
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_ANALOG_L2);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_ANALOG_R2);
// error list
@@ -553,7 +557,7 @@ void register_global_constants() {
BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_TRANSFORM2D", Variant::TRANSFORM2D);
BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_PLANE", Variant::PLANE);
BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_QUAT", Variant::QUAT); // 10
- BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_RECT3", Variant::RECT3);
+ BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_AABB", Variant::AABB);
BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_BASIS", Variant::BASIS);
BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_TRANSFORM", Variant::TRANSFORM);
BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_COLOR", Variant::COLOR);
diff --git a/core/helper/math_fieldwise.cpp b/core/helper/math_fieldwise.cpp
index 228611f8b3..2cd8a4f392 100644
--- a/core/helper/math_fieldwise.cpp
+++ b/core/helper/math_fieldwise.cpp
@@ -46,8 +46,8 @@ Variant fieldwise_assign(const Variant &p_target, const Variant &p_source, const
switch (p_source.get_type()) {
- /* clang-format makes a mess of this macro usage */
- /* clang-format off */
+ /* clang-format makes a mess of this macro usage */
+ /* clang-format off */
case Variant::VECTOR2: {
@@ -106,9 +106,9 @@ Variant fieldwise_assign(const Variant &p_target, const Variant &p_source, const
return target;
}
- case Variant::RECT3: {
+ case Variant::AABB: {
- SETUP_TYPE(Rect3)
+ SETUP_TYPE(AABB)
/**/ TRY_TRANSFER_FIELD("px", position.x)
else TRY_TRANSFER_FIELD("py", position.y)
diff --git a/core/image.cpp b/core/image.cpp
index c7f21d5599..422c0e407b 100644
--- a/core/image.cpp
+++ b/core/image.cpp
@@ -757,22 +757,24 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) {
_copy_internals_from(dst);
}
-void Image::crop(int p_width, int p_height) {
+void Image::crop_from_point(int p_x, int p_y, int p_width, int p_height) {
if (!_can_modify(format)) {
ERR_EXPLAIN("Cannot crop in indexed, compressed or custom image formats.");
ERR_FAIL();
}
+ ERR_FAIL_COND(p_x < 0);
+ ERR_FAIL_COND(p_y < 0);
ERR_FAIL_COND(p_width <= 0);
ERR_FAIL_COND(p_height <= 0);
- ERR_FAIL_COND(p_width > MAX_WIDTH);
- ERR_FAIL_COND(p_height > MAX_HEIGHT);
+ ERR_FAIL_COND(p_x + p_width > MAX_WIDTH);
+ ERR_FAIL_COND(p_y + p_height > MAX_HEIGHT);
/* to save memory, cropping should be done in-place, however, since this function
will most likely either not be used much, or in critical areas, for now it wont, because
it's a waste of time. */
- if (p_width == width && p_height == height)
+ if (p_width == width && p_height == height && p_x == 0 && p_y == 0)
return;
uint8_t pdata[16]; //largest is 16
@@ -784,9 +786,11 @@ void Image::crop(int p_width, int p_height) {
PoolVector<uint8_t>::Read r = data.read();
PoolVector<uint8_t>::Write w = dst.data.write();
- for (int y = 0; y < p_height; y++) {
+ int m_h = p_y + p_height;
+ int m_w = p_x + p_width;
+ for (int y = p_y; y < m_h; y++) {
- for (int x = 0; x < p_width; x++) {
+ for (int x = p_x; x < m_w; x++) {
if ((x >= width || y >= height)) {
for (uint32_t i = 0; i < pixel_size; i++)
@@ -795,7 +799,7 @@ void Image::crop(int p_width, int p_height) {
_get_pixelb(x, y, pixel_size, r.ptr(), pdata);
}
- dst._put_pixelb(x, y, pixel_size, w.ptr(), pdata);
+ dst._put_pixelb(x - p_x, y - p_y, pixel_size, w.ptr(), pdata);
}
}
}
@@ -805,6 +809,11 @@ void Image::crop(int p_width, int p_height) {
_copy_internals_from(dst);
}
+void Image::crop(int p_width, int p_height) {
+
+ crop_from_point(0, 0, p_width, p_height);
+}
+
void Image::flip_y() {
if (!_can_modify(format)) {
@@ -1061,7 +1070,6 @@ Error Image::generate_mipmaps() {
int size = _get_dst_image_size(width, height, format, mmcount);
data.resize(size);
- print_line("to gen mipmaps w " + itos(width) + " h " + itos(height) + " format " + get_format_name(format) + " mipmaps " + itos(mmcount) + " new size is: " + itos(size));
PoolVector<uint8_t>::Write wp = data.write();
@@ -2474,6 +2482,7 @@ void Image::fix_alpha_edges() {
if (rp[3] < alpha_threshold)
continue;
+ closest_dist = dist;
closest_color[0] = rp[0];
closest_color[1] = rp[1];
closest_color[2] = rp[2];
diff --git a/core/image.h b/core/image.h
index 27df65a898..24693aa706 100644
--- a/core/image.h
+++ b/core/image.h
@@ -207,6 +207,7 @@ public:
/**
* Crop the image to a specific size, if larger, then the image is filled by black
*/
+ void crop_from_point(int p_x, int p_y, int p_width, int p_height);
void crop(int p_width, int p_height);
void flip_x();
diff --git a/core/io/SCsub b/core/io/SCsub
index 4efc902717..79b56cb716 100644
--- a/core/io/SCsub
+++ b/core/io/SCsub
@@ -5,3 +5,4 @@ Import('env')
env.add_source_files(env.core_sources, "*.cpp")
Export('env')
+
diff --git a/core/io/compression.cpp b/core/io/compression.cpp
index fbe97e54c7..51d48901cf 100644
--- a/core/io/compression.cpp
+++ b/core/io/compression.cpp
@@ -78,9 +78,16 @@ int Compression::compress(uint8_t *p_dst, const uint8_t *p_src, int p_src_size,
} break;
case MODE_ZSTD: {
-
+ ZSTD_CCtx *cctx = ZSTD_createCCtx();
+ ZSTD_CCtx_setParameter(cctx, ZSTD_p_compressionLevel, zstd_level);
+ if (zstd_long_distance_matching) {
+ ZSTD_CCtx_setParameter(cctx, ZSTD_p_enableLongDistanceMatching, 1);
+ ZSTD_CCtx_setParameter(cctx, ZSTD_p_windowLog, zstd_window_log_size);
+ }
int max_dst_size = get_max_compressed_buffer_size(p_src_size, MODE_ZSTD);
- return ZSTD_compress(p_dst, max_dst_size, p_src, p_src_size, zstd_level);
+ int ret = ZSTD_compressCCtx(cctx, p_dst, max_dst_size, p_src, p_src_size, zstd_level);
+ ZSTD_freeCCtx(cctx);
+ return ret;
} break;
}
@@ -165,8 +172,11 @@ int Compression::decompress(uint8_t *p_dst, int p_dst_max_size, const uint8_t *p
return total;
} break;
case MODE_ZSTD: {
-
- return ZSTD_decompress(p_dst, p_dst_max_size, p_src, p_src_size);
+ ZSTD_DCtx *dctx = ZSTD_createDCtx();
+ if (zstd_long_distance_matching) ZSTD_DCtx_setMaxWindowSize(dctx, 1 << zstd_window_log_size);
+ int ret = ZSTD_decompressDCtx(dctx, p_dst, p_dst_max_size, p_src, p_src_size);
+ ZSTD_freeDCtx(dctx);
+ return ret;
} break;
}
@@ -176,3 +186,5 @@ int Compression::decompress(uint8_t *p_dst, int p_dst_max_size, const uint8_t *p
int Compression::zlib_level = Z_DEFAULT_COMPRESSION;
int Compression::gzip_level = Z_DEFAULT_COMPRESSION;
int Compression::zstd_level = 3;
+bool Compression::zstd_long_distance_matching = false;
+int Compression::zstd_window_log_size = 27;
diff --git a/core/io/compression.h b/core/io/compression.h
index 22d8109d4f..5a9aedec31 100644
--- a/core/io/compression.h
+++ b/core/io/compression.h
@@ -38,6 +38,8 @@ public:
static int zlib_level;
static int gzip_level;
static int zstd_level;
+ static bool zstd_long_distance_matching;
+ static int zstd_window_log_size;
enum Mode {
MODE_FASTLZ,
diff --git a/core/io/config_file.cpp b/core/io/config_file.cpp
index daa6b01d6e..2b60150832 100644
--- a/core/io/config_file.cpp
+++ b/core/io/config_file.cpp
@@ -75,7 +75,7 @@ void ConfigFile::set_value(const String &p_section, const String &p_key, const V
} else {
if (!values.has(p_section)) {
- values[p_section] = Map<String, Variant>();
+ values[p_section] = OrderedHashMap<String, Variant>();
}
values[p_section][p_key] = p_value;
@@ -106,16 +106,16 @@ bool ConfigFile::has_section_key(const String &p_section, const String &p_key) c
void ConfigFile::get_sections(List<String> *r_sections) const {
- for (const Map<String, Map<String, Variant> >::Element *E = values.front(); E; E = E->next()) {
- r_sections->push_back(E->key());
+ for (OrderedHashMap<String, OrderedHashMap<String, Variant> >::ConstElement E = values.front(); E; E = E.next()) {
+ r_sections->push_back(E.key());
}
}
void ConfigFile::get_section_keys(const String &p_section, List<String> *r_keys) const {
ERR_FAIL_COND(!values.has(p_section));
- for (const Map<String, Variant>::Element *E = values[p_section].front(); E; E = E->next()) {
- r_keys->push_back(E->key());
+ for (OrderedHashMap<String, Variant>::ConstElement E = values[p_section].front(); E; E = E.next()) {
+ r_keys->push_back(E.key());
}
}
@@ -135,17 +135,17 @@ Error ConfigFile::save(const String &p_path) {
return err;
}
- for (Map<String, Map<String, Variant> >::Element *E = values.front(); E; E = E->next()) {
+ for (OrderedHashMap<String, OrderedHashMap<String, Variant> >::Element E = values.front(); E; E = E.next()) {
if (E != values.front())
file->store_string("\n");
- file->store_string("[" + E->key() + "]\n\n");
+ file->store_string("[" + E.key() + "]\n\n");
- for (Map<String, Variant>::Element *F = E->get().front(); F; F = F->next()) {
+ for (OrderedHashMap<String, Variant>::Element F = E.get().front(); F; F = F.next()) {
String vstr;
- VariantWriter::write_to_string(F->get(), vstr);
- file->store_string(F->key() + "=" + vstr + "\n");
+ VariantWriter::write_to_string(F.get(), vstr);
+ file->store_string(F.key() + "=" + vstr + "\n");
}
}
diff --git a/core/io/config_file.h b/core/io/config_file.h
index 8ed8a069e4..29bd369a24 100644
--- a/core/io/config_file.h
+++ b/core/io/config_file.h
@@ -30,13 +30,14 @@
#ifndef CONFIG_FILE_H
#define CONFIG_FILE_H
+#include "core/ordered_hash_map.h"
#include "reference.h"
class ConfigFile : public Reference {
GDCLASS(ConfigFile, Reference);
- Map<String, Map<String, Variant> > values;
+ OrderedHashMap<String, OrderedHashMap<String, Variant> > values;
PoolStringArray _get_sections() const;
PoolStringArray _get_section_keys(const String &p_section) const;
diff --git a/core/io/file_access_encrypted.cpp b/core/io/file_access_encrypted.cpp
index c93e12f7da..e5da307153 100644
--- a/core/io/file_access_encrypted.cpp
+++ b/core/io/file_access_encrypted.cpp
@@ -62,12 +62,12 @@ Error FileAccessEncrypted::open_and_parse(FileAccess *p_base, const Vector<uint8
writing = false;
key = p_key;
uint32_t magic = p_base->get_32();
- print_line("MAGIC: " + itos(magic));
ERR_FAIL_COND_V(magic != COMP_MAGIC, ERR_FILE_UNRECOGNIZED);
+
mode = Mode(p_base->get_32());
ERR_FAIL_INDEX_V(mode, MODE_MAX, ERR_FILE_CORRUPT);
ERR_FAIL_COND_V(mode == 0, ERR_FILE_CORRUPT);
- print_line("MODE: " + itos(mode));
+
unsigned char md5d[16];
p_base->get_buffer(md5d, 16);
length = p_base->get_64();
diff --git a/core/io/http_client.cpp b/core/io/http_client.cpp
index b8c0a2b616..5097898314 100644
--- a/core/io/http_client.cpp
+++ b/core/io/http_client.cpp
@@ -30,6 +30,7 @@
#include "http_client.h"
#include "io/stream_peer_ssl.h"
+#ifndef JAVASCRIPT_ENABLED
Error HTTPClient::connect_to_host(const String &p_host, int p_port, bool p_ssl, bool p_verify_host) {
close();
@@ -189,16 +190,6 @@ Error HTTPClient::request(Method p_method, const String &p_url, const Vector<Str
return OK;
}
-Error HTTPClient::send_body_text(const String &p_body) {
-
- return OK;
-}
-
-Error HTTPClient::send_body_data(const PoolByteArray &p_body) {
-
- return OK;
-}
-
bool HTTPClient::has_response() const {
return response_headers.size() != 0;
@@ -415,38 +406,6 @@ Error HTTPClient::poll() {
return OK;
}
-Dictionary HTTPClient::_get_response_headers_as_dictionary() {
-
- List<String> rh;
- get_response_headers(&rh);
- Dictionary ret;
- for (const List<String>::Element *E = rh.front(); E; E = E->next()) {
- String s = E->get();
- int sp = s.find(":");
- if (sp == -1)
- continue;
- String key = s.substr(0, sp).strip_edges();
- String value = s.substr(sp + 1, s.length()).strip_edges();
- ret[key] = value;
- }
-
- return ret;
-}
-
-PoolStringArray HTTPClient::_get_response_headers() {
-
- List<String> rh;
- get_response_headers(&rh);
- PoolStringArray ret;
- ret.resize(rh.size());
- int idx = 0;
- for (const List<String>::Element *E = rh.front(); E; E = E->next()) {
- ret.set(idx++, E->get());
- }
-
- return ret;
-}
-
int HTTPClient::get_response_body_length() const {
return body_size;
@@ -622,6 +581,74 @@ Error HTTPClient::_get_http_data(uint8_t *p_buffer, int p_bytes, int &r_received
}
}
+void HTTPClient::set_read_chunk_size(int p_size) {
+ ERR_FAIL_COND(p_size < 256 || p_size > (1 << 24));
+ read_chunk_size = p_size;
+}
+
+HTTPClient::HTTPClient() {
+
+ tcp_connection = StreamPeerTCP::create_ref();
+ resolving = IP::RESOLVER_INVALID_ID;
+ status = STATUS_DISCONNECTED;
+ conn_port = 80;
+ body_size = 0;
+ chunked = false;
+ body_left = 0;
+ chunk_left = 0;
+ response_num = 0;
+ ssl = false;
+ blocking = false;
+ read_chunk_size = 4096;
+}
+
+HTTPClient::~HTTPClient() {
+}
+
+#endif // #ifndef JAVASCRIPT_ENABLED
+
+String HTTPClient::query_string_from_dict(const Dictionary &p_dict) {
+ String query = "";
+ Array keys = p_dict.keys();
+ for (int i = 0; i < keys.size(); ++i) {
+ query += "&" + String(keys[i]).http_escape() + "=" + String(p_dict[keys[i]]).http_escape();
+ }
+ query.erase(0, 1);
+ return query;
+}
+
+Dictionary HTTPClient::_get_response_headers_as_dictionary() {
+
+ List<String> rh;
+ get_response_headers(&rh);
+ Dictionary ret;
+ for (const List<String>::Element *E = rh.front(); E; E = E->next()) {
+ String s = E->get();
+ int sp = s.find(":");
+ if (sp == -1)
+ continue;
+ String key = s.substr(0, sp).strip_edges();
+ String value = s.substr(sp + 1, s.length()).strip_edges();
+ ret[key] = value;
+ }
+
+ return ret;
+}
+
+PoolStringArray HTTPClient::_get_response_headers() {
+
+ List<String> rh;
+ get_response_headers(&rh);
+ PoolStringArray ret;
+ ret.resize(rh.size());
+ int idx = 0;
+ for (const List<String>::Element *E = rh.front(); E; E = E->next()) {
+ ret.set(idx++, E->get());
+ }
+
+ return ret;
+}
+
void HTTPClient::_bind_methods() {
ClassDB::bind_method(D_METHOD("connect_to_host", "host", "port", "use_ssl", "verify_host"), &HTTPClient::connect_to_host, DEFVAL(false), DEFVAL(true));
@@ -629,8 +656,6 @@ void HTTPClient::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_connection"), &HTTPClient::get_connection);
ClassDB::bind_method(D_METHOD("request_raw", "method", "url", "headers", "body"), &HTTPClient::request_raw);
ClassDB::bind_method(D_METHOD("request", "method", "url", "headers", "body"), &HTTPClient::request, DEFVAL(String()));
- ClassDB::bind_method(D_METHOD("send_body_text", "body"), &HTTPClient::send_body_text);
- ClassDB::bind_method(D_METHOD("send_body_data", "body"), &HTTPClient::send_body_data);
ClassDB::bind_method(D_METHOD("close"), &HTTPClient::close);
ClassDB::bind_method(D_METHOD("has_response"), &HTTPClient::has_response);
@@ -729,37 +754,3 @@ void HTTPClient::_bind_methods() {
BIND_ENUM_CONSTANT(RESPONSE_INSUFFICIENT_STORAGE);
BIND_ENUM_CONSTANT(RESPONSE_NOT_EXTENDED);
}
-
-void HTTPClient::set_read_chunk_size(int p_size) {
- ERR_FAIL_COND(p_size < 256 || p_size > (1 << 24));
- read_chunk_size = p_size;
-}
-
-String HTTPClient::query_string_from_dict(const Dictionary &p_dict) {
- String query = "";
- Array keys = p_dict.keys();
- for (int i = 0; i < keys.size(); ++i) {
- query += "&" + String(keys[i]).http_escape() + "=" + String(p_dict[keys[i]]).http_escape();
- }
- query.erase(0, 1);
- return query;
-}
-
-HTTPClient::HTTPClient() {
-
- tcp_connection = StreamPeerTCP::create_ref();
- resolving = IP::RESOLVER_INVALID_ID;
- status = STATUS_DISCONNECTED;
- conn_port = 80;
- body_size = 0;
- chunked = false;
- body_left = 0;
- chunk_left = 0;
- response_num = 0;
- ssl = false;
- blocking = false;
- read_chunk_size = 4096;
-}
-
-HTTPClient::~HTTPClient() {
-}
diff --git a/core/io/http_client.h b/core/io/http_client.h
index 023370ae81..db5dd115bd 100644
--- a/core/io/http_client.h
+++ b/core/io/http_client.h
@@ -131,6 +131,7 @@ public:
};
private:
+#ifndef JAVASCRIPT_ENABLED
Status status;
IP::ResolverID resolving;
int conn_port;
@@ -152,13 +153,18 @@ private:
int response_num;
Vector<String> response_headers;
+ int read_chunk_size;
+
+ Error _get_http_data(uint8_t *p_buffer, int p_bytes, int &r_received);
+
+#else
+#include "platform/javascript/http_client.h.inc"
+#endif
- static void _bind_methods();
PoolStringArray _get_response_headers();
Dictionary _get_response_headers_as_dictionary();
- int read_chunk_size;
- Error _get_http_data(uint8_t *p_buffer, int p_bytes, int &r_received);
+ static void _bind_methods();
public:
//Error connect_and_get(const String& p_url,bool p_verify_host=true); //connects to a full url and perform request
@@ -169,8 +175,6 @@ public:
Error request_raw(Method p_method, const String &p_url, const Vector<String> &p_headers, const PoolVector<uint8_t> &p_body);
Error request(Method p_method, const String &p_url, const Vector<String> &p_headers, const String &p_body = String());
- Error send_body_text(const String &p_body);
- Error send_body_data(const PoolByteArray &p_body);
void close();
diff --git a/core/io/logger.cpp b/core/io/logger.cpp
index b94007d316..7177359c8a 100644
--- a/core/io/logger.cpp
+++ b/core/io/logger.cpp
@@ -29,10 +29,22 @@
/*************************************************************************/
#include "logger.h"
+
#include "os/dir_access.h"
#include "os/os.h"
#include "print_string.h"
+// va_copy was defined in the C99, but not in C++ standards before C++11.
+// When you compile C++ without --std=c++<XX> option, compilers still define
+// va_copy, otherwise you have to use the internal version (__va_copy).
+#if !defined(va_copy)
+#if defined(__GNUC__)
+#define va_copy(d, s) __va_copy(d, s)
+#else
+#define va_copy(d, s) ((d) = (s))
+#endif
+#endif
+
bool Logger::should_log(bool p_err) {
return (!p_err || _print_error_enabled) && (p_err || _print_line_enabled);
}
@@ -99,7 +111,7 @@ void RotatedFileLogger::close_file() {
void RotatedFileLogger::clear_old_backups() {
int max_backups = max_files - 1; // -1 for the current file
- String basename = base_path.get_basename();
+ String basename = base_path.get_file().get_basename();
String extension = "." + base_path.get_extension();
DirAccess *da = DirAccess::open(base_path.get_base_dir());
@@ -111,7 +123,7 @@ void RotatedFileLogger::clear_old_backups() {
String f = da->get_next();
Set<String> backups;
while (f != String()) {
- if (!da->current_is_dir() && f.begins_with(basename) && f.ends_with(extension) && f != base_path) {
+ if (!da->current_is_dir() && f.begins_with(basename) && f.ends_with(extension) && f != base_path.get_file()) {
backups.insert(f);
}
f = da->get_next();
@@ -138,7 +150,7 @@ void RotatedFileLogger::rotate_file() {
char timestamp[21];
OS::Date date = OS::get_singleton()->get_date();
OS::Time time = OS::get_singleton()->get_time();
- sprintf(timestamp, "-%04d-%02d-%02d-%02d-%02d-%02d", date.year, date.month, date.day + 1, time.hour, time.min, time.sec);
+ sprintf(timestamp, "-%04d-%02d-%02d-%02d-%02d-%02d", date.year, date.month, date.day, time.hour, time.min, time.sec);
String backup_name = base_path.get_basename() + timestamp + "." + base_path.get_extension();
@@ -248,6 +260,10 @@ void CompositeLogger::log_error(const char *p_function, const char *p_file, int
}
}
+void CompositeLogger::add_logger(Logger *p_logger) {
+ loggers.push_back(p_logger);
+}
+
CompositeLogger::~CompositeLogger() {
for (int i = 0; i < loggers.size(); ++i) {
memdelete(loggers[i]);
diff --git a/core/io/logger.h b/core/io/logger.h
index cf0cc7699f..f8a394193f 100644
--- a/core/io/logger.h
+++ b/core/io/logger.h
@@ -101,6 +101,8 @@ public:
virtual void logv(const char *p_format, va_list p_list, bool p_err);
virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type = ERR_ERROR);
+ void add_logger(Logger *p_logger);
+
virtual ~CompositeLogger();
};
diff --git a/core/io/marshalls.cpp b/core/io/marshalls.cpp
index 0834d6c321..1d9d2dd959 100644
--- a/core/io/marshalls.cpp
+++ b/core/io/marshalls.cpp
@@ -159,7 +159,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
r_variant = str;
} break;
- // math types
+ // math types
case Variant::VECTOR2: {
@@ -245,10 +245,10 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
(*r_len) += 4 * 4;
} break;
- case Variant::RECT3: {
+ case Variant::AABB: {
ERR_FAIL_COND_V(len < (int)4 * 6, ERR_INVALID_DATA);
- Rect3 val;
+ AABB val;
val.position.x = decode_float(&buf[0]);
val.position.y = decode_float(&buf[4]);
val.position.z = decode_float(&buf[8]);
@@ -967,7 +967,7 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
_encode_string(p_variant, buf, r_len);
} break;
- // math types
+ // math types
case Variant::VECTOR2: {
@@ -1045,10 +1045,10 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
r_len += 4 * 4;
} break;
- case Variant::RECT3: {
+ case Variant::AABB: {
if (buf) {
- Rect3 aabb = p_variant;
+ AABB aabb = p_variant;
encode_float(aabb.position.x, &buf[0]);
encode_float(aabb.position.y, &buf[4]);
encode_float(aabb.position.z, &buf[8]);
@@ -1140,8 +1140,9 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
if (buf) {
encode_uint32(0, buf);
buf += 4;
- r_len += 4;
}
+ r_len += 4;
+
} else {
_encode_string(obj->get_class(), buf, r_len);
diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp
index 900db7c2dc..8dc396c362 100644
--- a/core/io/resource_format_binary.cpp
+++ b/core/io/resource_format_binary.cpp
@@ -52,7 +52,7 @@ enum {
VARIANT_VECTOR3 = 12,
VARIANT_PLANE = 13,
VARIANT_QUAT = 14,
- VARIANT_RECT3 = 15,
+ VARIANT_AABB = 15,
VARIANT_MATRIX3 = 16,
VARIANT_TRANSFORM = 17,
VARIANT_MATRIX32 = 18,
@@ -196,9 +196,9 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) {
r_v = v;
} break;
- case VARIANT_RECT3: {
+ case VARIANT_AABB: {
- Rect3 v;
+ AABB v;
v.position.x = f->get_real();
v.position.y = f->get_real();
v.position.z = f->get_real();
@@ -282,7 +282,6 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) {
property = _get_string();
NodePath np = NodePath(names, subnames, absolute, property);
- //print_line("got path: "+String(np));
r_v = np;
@@ -640,7 +639,6 @@ Error ResourceInteractiveLoaderBinary::poll() {
String path = external_resources[s].path;
- print_line("load external res: " + path);
if (remaps.has(path)) {
path = remaps[path];
}
@@ -706,8 +704,6 @@ Error ResourceInteractiveLoaderBinary::poll() {
String t = get_unicode_string();
- // print_line("loading resource of type "+t+" path is "+path);
-
Object *obj = ClassDB::instance(t);
if (!obj) {
error = ERR_FILE_CORRUPT;
@@ -907,20 +903,6 @@ void ResourceInteractiveLoaderBinary::open(FileAccess *p_f) {
external_resources.push_back(er);
}
- //see if the exporter has different set of external resources for more efficient loading
- /*
- String preload_depts = "deps/"+res_path.md5_text();
- if (Globals::get_singleton()->has(preload_depts)) {
- external_resources.clear();
- //ignore external resources and use these
- NodePath depts=Globals::get_singleton()->get(preload_depts);
- external_resources.resize(depts.get_name_count());
- for(int i=0;i<depts.get_name_count();i++) {
- external_resources[i].path=depts.get_name(i);
- }
- print_line(res_path+" - EXTERNAL RESOURCES: "+itos(external_resources.size()));
- }*/
-
print_bl("ext resources: " + itos(ext_resources_size));
uint32_t int_resources_size = f->get_32();
@@ -1392,10 +1374,10 @@ void ResourceFormatSaverBinaryInstance::write_variant(const Variant &p_property,
f->store_real(val.w);
} break;
- case Variant::RECT3: {
+ case Variant::AABB: {
- f->store_32(VARIANT_RECT3);
- Rect3 val = p_property;
+ f->store_32(VARIANT_AABB);
+ AABB val = p_property;
f->store_real(val.position.x);
f->store_real(val.position.y);
f->store_real(val.position.z);
diff --git a/core/make_binders.py b/core/make_binders.py
index 6468c029f0..6f42c6e8eb 100644
--- a/core/make_binders.py
+++ b/core/make_binders.py
@@ -244,7 +244,7 @@ def make_version(template, nargs, argmax, const, ret):
def run(target, source, env):
- versions = 10
+ versions = 11
versions_ext = 6
text = ""
text_ext = ""
diff --git a/core/map.h b/core/map.h
index f01062ebed..fb24a5868c 100644
--- a/core/map.h
+++ b/core/map.h
@@ -438,7 +438,6 @@ private:
Element *rp = ((p_node->left == _data._nil) || (p_node->right == _data._nil)) ? p_node : p_node->_next;
Element *node = (rp->left == _data._nil) ? rp->right : rp->left;
- node->parent = rp->parent;
Element *sibling;
if (rp == rp->parent->left) {
diff --git a/core/math/a_star.cpp b/core/math/a_star.cpp
index 4f80fb2491..7e26761abf 100644
--- a/core/math/a_star.cpp
+++ b/core/math/a_star.cpp
@@ -42,8 +42,10 @@ int AStar::get_available_point_id() const {
}
void AStar::add_point(int p_id, const Vector3 &p_pos, real_t p_weight_scale) {
+
ERR_FAIL_COND(p_id < 0);
ERR_FAIL_COND(p_weight_scale < 1);
+
if (!points.has(p_id)) {
Point *pt = memnew(Point);
pt->id = p_id;
@@ -64,12 +66,29 @@ Vector3 AStar::get_point_position(int p_id) const {
return points[p_id]->pos;
}
+
+void AStar::set_point_position(int p_id, const Vector3 &p_pos) {
+
+ ERR_FAIL_COND(!points.has(p_id));
+
+ points[p_id]->pos = p_pos;
+}
+
real_t AStar::get_point_weight_scale(int p_id) const {
ERR_FAIL_COND_V(!points.has(p_id), 0);
return points[p_id]->weight_scale;
}
+
+void AStar::set_point_weight_scale(int p_id, real_t p_weight_scale) {
+
+ ERR_FAIL_COND(!points.has(p_id));
+ ERR_FAIL_COND(p_weight_scale < 1);
+
+ points[p_id]->weight_scale = p_weight_scale;
+}
+
void AStar::remove_point(int p_id) {
ERR_FAIL_COND(!points.has(p_id));
@@ -130,6 +149,7 @@ bool AStar::has_point(int p_id) const {
}
Array AStar::get_points() {
+
Array point_list;
for (const Map<int, Point *>::Element *E = points.front(); E; E = E->next()) {
@@ -139,6 +159,21 @@ Array AStar::get_points() {
return point_list;
}
+PoolVector<int> AStar::get_point_connections(int p_id) {
+
+ ERR_FAIL_COND_V(!points.has(p_id), PoolVector<int>());
+
+ PoolVector<int> point_list;
+
+ Point *p = points[p_id];
+
+ for (int i = 0; i < p->neighbours.size(); i++) {
+ point_list.push_back(p->neighbours[i]->id);
+ }
+
+ return point_list;
+}
+
bool AStar::are_points_connected(int p_id, int p_with_id) const {
Segment s(p_id, p_with_id);
@@ -171,6 +206,7 @@ int AStar::get_closest_point(const Vector3 &p_point) const {
return closest_id;
}
+
Vector3 AStar::get_closest_position_in_segment(const Vector3 &p_point) const {
real_t closest_dist = 1e20;
@@ -222,15 +258,15 @@ bool AStar::_solve(Point *begin_point, Point *end_point) {
while (!found_route) {
if (open_list.first() == NULL) {
- //could not find path sadly
+ // No path found
break;
}
- //check open list
+ // Check open list
SelfList<Point> *least_cost_point = NULL;
real_t least_cost = 1e30;
- //this could be faster (cache previous results)
+ // TODO: Cache previous results
for (SelfList<Point> *E = open_list.first(); E; E = E->next()) {
Point *p = E->self();
@@ -246,7 +282,7 @@ bool AStar::_solve(Point *begin_point, Point *end_point) {
}
Point *p = least_cost_point->self();
- //open the neighbours for search
+ // Open the neighbours for search
int es = p->neighbours.size();
for (int i = 0; i < es; i++) {
@@ -256,7 +292,7 @@ bool AStar::_solve(Point *begin_point, Point *end_point) {
real_t distance = _compute_cost(p->id, e->id) * e->weight_scale + p->distance;
if (e->last_pass == pass) {
- //oh this was visited already, can we win the cost?
+ // Already visited, is this cheaper?
if (e->distance > distance) {
@@ -264,15 +300,15 @@ bool AStar::_solve(Point *begin_point, Point *end_point) {
e->distance = distance;
}
} else {
- //add to open neighbours
+ // Add to open neighbours
e->prev_point = p;
e->distance = distance;
- e->last_pass = pass; //mark as used
+ e->last_pass = pass; // Mark as used
open_list.add(&e->list);
if (e == end_point) {
- //oh my reached end! stop algorithm
+ // End reached; stop algorithm
found_route = true;
break;
}
@@ -285,7 +321,7 @@ bool AStar::_solve(Point *begin_point, Point *end_point) {
open_list.remove(least_cost_point);
}
- //clear the openf list
+ // Clear the openf list
while (open_list.first()) {
open_list.remove(open_list.first());
}
@@ -294,6 +330,7 @@ bool AStar::_solve(Point *begin_point, Point *end_point) {
}
float AStar::_estimate_cost(int p_from_id, int p_to_id) {
+
if (get_script_instance() && get_script_instance()->has_method(SceneStringNames::get_singleton()->_estimate_cost))
return get_script_instance()->call(SceneStringNames::get_singleton()->_estimate_cost, p_from_id, p_to_id);
@@ -301,6 +338,7 @@ float AStar::_estimate_cost(int p_from_id, int p_to_id) {
}
float AStar::_compute_cost(int p_from_id, int p_to_id) {
+
if (get_script_instance() && get_script_instance()->has_method(SceneStringNames::get_singleton()->_compute_cost))
return get_script_instance()->call(SceneStringNames::get_singleton()->_compute_cost, p_from_id, p_to_id);
@@ -331,9 +369,9 @@ PoolVector<Vector3> AStar::get_point_path(int p_from_id, int p_to_id) {
if (!found_route)
return PoolVector<Vector3>();
- //midpoints
+ // Midpoints
Point *p = end_point;
- int pc = 1; //begin point
+ int pc = 1; // Begin point
while (p != begin_point) {
pc++;
p = p->prev_point;
@@ -352,7 +390,7 @@ PoolVector<Vector3> AStar::get_point_path(int p_from_id, int p_to_id) {
p = p->prev_point;
}
- w[0] = p->pos; //assign first
+ w[0] = p->pos; // Assign first
}
return path;
@@ -382,9 +420,9 @@ PoolVector<int> AStar::get_id_path(int p_from_id, int p_to_id) {
if (!found_route)
return PoolVector<int>();
- //midpoints
+ // Midpoints
Point *p = end_point;
- int pc = 1; //begin point
+ int pc = 1; // Begin point
while (p != begin_point) {
pc++;
p = p->prev_point;
@@ -403,7 +441,7 @@ PoolVector<int> AStar::get_id_path(int p_from_id, int p_to_id) {
p = p->prev_point;
}
- w[0] = p->id; //assign first
+ w[0] = p->id; // Assign first
}
return path;
@@ -414,11 +452,15 @@ void AStar::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_available_point_id"), &AStar::get_available_point_id);
ClassDB::bind_method(D_METHOD("add_point", "id", "position", "weight_scale"), &AStar::add_point, DEFVAL(1.0));
ClassDB::bind_method(D_METHOD("get_point_position", "id"), &AStar::get_point_position);
+ ClassDB::bind_method(D_METHOD("set_point_position", "id", "position"), &AStar::set_point_position);
ClassDB::bind_method(D_METHOD("get_point_weight_scale", "id"), &AStar::get_point_weight_scale);
+ ClassDB::bind_method(D_METHOD("set_point_weight_scale", "id", "weight_scale"), &AStar::set_point_weight_scale);
ClassDB::bind_method(D_METHOD("remove_point", "id"), &AStar::remove_point);
ClassDB::bind_method(D_METHOD("has_point", "id"), &AStar::has_point);
ClassDB::bind_method(D_METHOD("get_points"), &AStar::get_points);
+ ClassDB::bind_method(D_METHOD("get_point_connections"), &AStar::get_point_connections);
+
ClassDB::bind_method(D_METHOD("connect_points", "id", "to_id", "bidirectional"), &AStar::connect_points, DEFVAL(true));
ClassDB::bind_method(D_METHOD("disconnect_points", "id", "to_id"), &AStar::disconnect_points);
ClassDB::bind_method(D_METHOD("are_points_connected", "id", "to_id"), &AStar::are_points_connected);
@@ -443,4 +485,5 @@ AStar::AStar() {
AStar::~AStar() {
pass = 1;
+ clear();
}
diff --git a/core/math/a_star.h b/core/math/a_star.h
index 2c1e2e2cf7..b7b7e54125 100644
--- a/core/math/a_star.h
+++ b/core/math/a_star.h
@@ -33,6 +33,8 @@
#include "reference.h"
#include "self_list.h"
/**
+ A* pathfinding algorithm
+
@author Juan Linietsky <reduzio@gmail.com>
*/
@@ -53,7 +55,7 @@ class AStar : public Reference {
Vector<Point *> neighbours;
- //used for pathfinding
+ // Used for pathfinding
Point *prev_point;
real_t distance;
@@ -102,9 +104,12 @@ public:
void add_point(int p_id, const Vector3 &p_pos, real_t p_weight_scale = 1);
Vector3 get_point_position(int p_id) const;
+ void set_point_position(int p_id, const Vector3 &p_pos);
real_t get_point_weight_scale(int p_id) const;
+ void set_point_weight_scale(int p_id, real_t p_weight_scale);
void remove_point(int p_id);
bool has_point(int p_id) const;
+ PoolVector<int> get_point_connections(int p_id);
Array get_points();
void connect_points(int p_id, int p_with_id, bool bidirectional = true);
diff --git a/core/math/rect3.cpp b/core/math/aabb.cpp
index 6f01000f61..737a42b337 100644
--- a/core/math/rect3.cpp
+++ b/core/math/aabb.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* rect3.cpp */
+/* aabb.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -27,25 +27,25 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "rect3.h"
+#include "aabb.h"
#include "print_string.h"
-real_t Rect3::get_area() const {
+real_t AABB::get_area() const {
return size.x * size.y * size.z;
}
-bool Rect3::operator==(const Rect3 &p_rval) const {
+bool AABB::operator==(const AABB &p_rval) const {
return ((position == p_rval.position) && (size == p_rval.size));
}
-bool Rect3::operator!=(const Rect3 &p_rval) const {
+bool AABB::operator!=(const AABB &p_rval) const {
return ((position != p_rval.position) || (size != p_rval.size));
}
-void Rect3::merge_with(const Rect3 &p_aabb) {
+void AABB::merge_with(const AABB &p_aabb) {
Vector3 beg_1, beg_2;
Vector3 end_1, end_2;
@@ -68,7 +68,7 @@ void Rect3::merge_with(const Rect3 &p_aabb) {
size = max - min;
}
-Rect3 Rect3::intersection(const Rect3 &p_aabb) const {
+AABB AABB::intersection(const AABB &p_aabb) const {
Vector3 src_min = position;
Vector3 src_max = position + size;
@@ -78,7 +78,7 @@ Rect3 Rect3::intersection(const Rect3 &p_aabb) const {
Vector3 min, max;
if (src_min.x > dst_max.x || src_max.x < dst_min.x)
- return Rect3();
+ return AABB();
else {
min.x = (src_min.x > dst_min.x) ? src_min.x : dst_min.x;
@@ -86,7 +86,7 @@ Rect3 Rect3::intersection(const Rect3 &p_aabb) const {
}
if (src_min.y > dst_max.y || src_max.y < dst_min.y)
- return Rect3();
+ return AABB();
else {
min.y = (src_min.y > dst_min.y) ? src_min.y : dst_min.y;
@@ -94,17 +94,17 @@ Rect3 Rect3::intersection(const Rect3 &p_aabb) const {
}
if (src_min.z > dst_max.z || src_max.z < dst_min.z)
- return Rect3();
+ return AABB();
else {
min.z = (src_min.z > dst_min.z) ? src_min.z : dst_min.z;
max.z = (src_max.z < dst_max.z) ? src_max.z : dst_max.z;
}
- return Rect3(min, max - min);
+ return AABB(min, max - min);
}
-bool Rect3::intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *r_clip, Vector3 *r_normal) const {
+bool AABB::intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *r_clip, Vector3 *r_normal) const {
Vector3 c1, c2;
Vector3 end = position + size;
@@ -147,7 +147,7 @@ bool Rect3::intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, Vector3
return true;
}
-bool Rect3::intersects_segment(const Vector3 &p_from, const Vector3 &p_to, Vector3 *r_clip, Vector3 *r_normal) const {
+bool AABB::intersects_segment(const Vector3 &p_from, const Vector3 &p_to, Vector3 *r_clip, Vector3 *r_normal) const {
real_t min = 0, max = 1;
int axis = 0;
@@ -205,7 +205,7 @@ bool Rect3::intersects_segment(const Vector3 &p_from, const Vector3 &p_to, Vecto
return true;
}
-bool Rect3::intersects_plane(const Plane &p_plane) const {
+bool AABB::intersects_plane(const Plane &p_plane) const {
Vector3 points[8] = {
Vector3(position.x, position.y, position.z),
@@ -232,7 +232,7 @@ bool Rect3::intersects_plane(const Plane &p_plane) const {
return under && over;
}
-Vector3 Rect3::get_longest_axis() const {
+Vector3 AABB::get_longest_axis() const {
Vector3 axis(1, 0, 0);
real_t max_size = size.x;
@@ -249,7 +249,7 @@ Vector3 Rect3::get_longest_axis() const {
return axis;
}
-int Rect3::get_longest_axis_index() const {
+int AABB::get_longest_axis_index() const {
int axis = 0;
real_t max_size = size.x;
@@ -267,7 +267,7 @@ int Rect3::get_longest_axis_index() const {
return axis;
}
-Vector3 Rect3::get_shortest_axis() const {
+Vector3 AABB::get_shortest_axis() const {
Vector3 axis(1, 0, 0);
real_t max_size = size.x;
@@ -284,7 +284,7 @@ Vector3 Rect3::get_shortest_axis() const {
return axis;
}
-int Rect3::get_shortest_axis_index() const {
+int AABB::get_shortest_axis_index() const {
int axis = 0;
real_t max_size = size.x;
@@ -302,25 +302,25 @@ int Rect3::get_shortest_axis_index() const {
return axis;
}
-Rect3 Rect3::merge(const Rect3 &p_with) const {
+AABB AABB::merge(const AABB &p_with) const {
- Rect3 aabb = *this;
+ AABB aabb = *this;
aabb.merge_with(p_with);
return aabb;
}
-Rect3 Rect3::expand(const Vector3 &p_vector) const {
- Rect3 aabb = *this;
+AABB AABB::expand(const Vector3 &p_vector) const {
+ AABB aabb = *this;
aabb.expand_to(p_vector);
return aabb;
}
-Rect3 Rect3::grow(real_t p_by) const {
+AABB AABB::grow(real_t p_by) const {
- Rect3 aabb = *this;
+ AABB aabb = *this;
aabb.grow_by(p_by);
return aabb;
}
-void Rect3::get_edge(int p_edge, Vector3 &r_from, Vector3 &r_to) const {
+void AABB::get_edge(int p_edge, Vector3 &r_from, Vector3 &r_to) const {
ERR_FAIL_INDEX(p_edge, 12);
switch (p_edge) {
@@ -394,7 +394,7 @@ void Rect3::get_edge(int p_edge, Vector3 &r_from, Vector3 &r_to) const {
}
}
-Rect3::operator String() const {
+AABB::operator String() const {
return String() + position + " - " + size;
}
diff --git a/core/math/rect3.h b/core/math/aabb.h
index c3a2f5fbfb..c60213496a 100644
--- a/core/math/rect3.h
+++ b/core/math/aabb.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* rect3.h */
+/* aabb.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -39,7 +39,7 @@
* This is implemented by a point (position) and the box size
*/
-class Rect3 {
+class AABB {
public:
Vector3 position;
Vector3 size;
@@ -60,16 +60,16 @@ public:
const Vector3 &get_size() const { return size; }
void set_size(const Vector3 &p_size) { size = p_size; }
- bool operator==(const Rect3 &p_rval) const;
- bool operator!=(const Rect3 &p_rval) const;
+ bool operator==(const AABB &p_rval) const;
+ bool operator!=(const AABB &p_rval) const;
- _FORCE_INLINE_ bool intersects(const Rect3 &p_aabb) const; /// Both AABBs overlap
- _FORCE_INLINE_ bool intersects_inclusive(const Rect3 &p_aabb) const; /// Both AABBs (or their faces) overlap
- _FORCE_INLINE_ bool encloses(const Rect3 &p_aabb) const; /// p_aabb is completely inside this
+ _FORCE_INLINE_ bool intersects(const AABB &p_aabb) const; /// Both AABBs overlap
+ _FORCE_INLINE_ bool intersects_inclusive(const AABB &p_aabb) const; /// Both AABBs (or their faces) overlap
+ _FORCE_INLINE_ bool encloses(const AABB &p_aabb) const; /// p_aabb is completely inside this
- Rect3 merge(const Rect3 &p_with) const;
- void merge_with(const Rect3 &p_aabb); ///merge with another AABB
- Rect3 intersection(const Rect3 &p_aabb) const; ///get box where two intersect, empty if no intersection occurs
+ AABB merge(const AABB &p_with) const;
+ void merge_with(const AABB &p_aabb); ///merge with another AABB
+ AABB intersection(const AABB &p_aabb) const; ///get box where two intersect, empty if no intersection occurs
bool intersects_segment(const Vector3 &p_from, const Vector3 &p_to, Vector3 *r_clip = NULL, Vector3 *r_normal = NULL) const;
bool intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *r_clip = NULL, Vector3 *r_normal = NULL) const;
_FORCE_INLINE_ bool smits_intersect_ray(const Vector3 &p_from, const Vector3 &p_dir, real_t t0, real_t t1) const;
@@ -88,26 +88,26 @@ public:
int get_shortest_axis_index() const;
_FORCE_INLINE_ real_t get_shortest_axis_size() const;
- Rect3 grow(real_t p_by) const;
+ AABB grow(real_t p_by) const;
_FORCE_INLINE_ void grow_by(real_t p_amount);
void get_edge(int p_edge, Vector3 &r_from, Vector3 &r_to) const;
_FORCE_INLINE_ Vector3 get_endpoint(int p_point) const;
- Rect3 expand(const Vector3 &p_vector) const;
+ AABB expand(const Vector3 &p_vector) const;
_FORCE_INLINE_ void project_range_in_plane(const Plane &p_plane, real_t &r_min, real_t &r_max) const;
_FORCE_INLINE_ void expand_to(const Vector3 &p_vector); /** expand to contain a point if necessary */
operator String() const;
- _FORCE_INLINE_ Rect3() {}
- inline Rect3(const Vector3 &p_pos, const Vector3 &p_size)
+ _FORCE_INLINE_ AABB() {}
+ inline AABB(const Vector3 &p_pos, const Vector3 &p_size)
: position(p_pos),
size(p_size) {
}
};
-inline bool Rect3::intersects(const Rect3 &p_aabb) const {
+inline bool AABB::intersects(const AABB &p_aabb) const {
if (position.x >= (p_aabb.position.x + p_aabb.size.x))
return false;
@@ -125,7 +125,7 @@ inline bool Rect3::intersects(const Rect3 &p_aabb) const {
return true;
}
-inline bool Rect3::intersects_inclusive(const Rect3 &p_aabb) const {
+inline bool AABB::intersects_inclusive(const AABB &p_aabb) const {
if (position.x > (p_aabb.position.x + p_aabb.size.x))
return false;
@@ -143,7 +143,7 @@ inline bool Rect3::intersects_inclusive(const Rect3 &p_aabb) const {
return true;
}
-inline bool Rect3::encloses(const Rect3 &p_aabb) const {
+inline bool AABB::encloses(const AABB &p_aabb) const {
Vector3 src_min = position;
Vector3 src_max = position + size;
@@ -159,7 +159,7 @@ inline bool Rect3::encloses(const Rect3 &p_aabb) const {
(src_max.z > dst_max.z));
}
-Vector3 Rect3::get_support(const Vector3 &p_normal) const {
+Vector3 AABB::get_support(const Vector3 &p_normal) const {
Vector3 half_extents = size * 0.5;
Vector3 ofs = position + half_extents;
@@ -171,7 +171,7 @@ Vector3 Rect3::get_support(const Vector3 &p_normal) const {
ofs;
}
-Vector3 Rect3::get_endpoint(int p_point) const {
+Vector3 AABB::get_endpoint(int p_point) const {
switch (p_point) {
case 0: return Vector3(position.x, position.y, position.z);
@@ -187,7 +187,7 @@ Vector3 Rect3::get_endpoint(int p_point) const {
ERR_FAIL_V(Vector3());
}
-bool Rect3::intersects_convex_shape(const Plane *p_planes, int p_plane_count) const {
+bool AABB::intersects_convex_shape(const Plane *p_planes, int p_plane_count) const {
Vector3 half_extents = size * 0.5;
Vector3 ofs = position + half_extents;
@@ -206,7 +206,7 @@ bool Rect3::intersects_convex_shape(const Plane *p_planes, int p_plane_count) co
return true;
}
-bool Rect3::has_point(const Vector3 &p_point) const {
+bool AABB::has_point(const Vector3 &p_point) const {
if (p_point.x < position.x)
return false;
@@ -224,7 +224,7 @@ bool Rect3::has_point(const Vector3 &p_point) const {
return true;
}
-inline void Rect3::expand_to(const Vector3 &p_vector) {
+inline void AABB::expand_to(const Vector3 &p_vector) {
Vector3 begin = position;
Vector3 end = position + size;
@@ -247,7 +247,7 @@ inline void Rect3::expand_to(const Vector3 &p_vector) {
size = end - begin;
}
-void Rect3::project_range_in_plane(const Plane &p_plane, real_t &r_min, real_t &r_max) const {
+void AABB::project_range_in_plane(const Plane &p_plane, real_t &r_min, real_t &r_max) const {
Vector3 half_extents(size.x * 0.5, size.y * 0.5, size.z * 0.5);
Vector3 center(position.x + half_extents.x, position.y + half_extents.y, position.z + half_extents.z);
@@ -258,7 +258,7 @@ void Rect3::project_range_in_plane(const Plane &p_plane, real_t &r_min, real_t &
r_max = distance + length;
}
-inline real_t Rect3::get_longest_axis_size() const {
+inline real_t AABB::get_longest_axis_size() const {
real_t max_size = size.x;
@@ -273,7 +273,7 @@ inline real_t Rect3::get_longest_axis_size() const {
return max_size;
}
-inline real_t Rect3::get_shortest_axis_size() const {
+inline real_t AABB::get_shortest_axis_size() const {
real_t max_size = size.x;
@@ -288,7 +288,7 @@ inline real_t Rect3::get_shortest_axis_size() const {
return max_size;
}
-bool Rect3::smits_intersect_ray(const Vector3 &p_from, const Vector3 &p_dir, real_t t0, real_t t1) const {
+bool AABB::smits_intersect_ray(const Vector3 &p_from, const Vector3 &p_dir, real_t t0, real_t t1) const {
real_t divx = 1.0 / p_dir.x;
real_t divy = 1.0 / p_dir.y;
@@ -332,7 +332,7 @@ bool Rect3::smits_intersect_ray(const Vector3 &p_from, const Vector3 &p_dir, rea
return ((tmin < t1) && (tmax > t0));
}
-void Rect3::grow_by(real_t p_amount) {
+void AABB::grow_by(real_t p_amount) {
position.x -= p_amount;
position.y -= p_amount;
diff --git a/core/math/bsp_tree.cpp b/core/math/bsp_tree.cpp
index be950568cf..bdc040160f 100644
--- a/core/math/bsp_tree.cpp
+++ b/core/math/bsp_tree.cpp
@@ -31,7 +31,7 @@
#include "error_macros.h"
#include "print_string.h"
-void BSP_Tree::from_aabb(const Rect3 &p_aabb) {
+void BSP_Tree::from_aabb(const AABB &p_aabb) {
planes.clear();
@@ -67,7 +67,7 @@ Vector<Plane> BSP_Tree::get_planes() const {
return planes;
}
-Rect3 BSP_Tree::get_aabb() const {
+AABB BSP_Tree::get_aabb() const {
return aabb;
}
@@ -577,7 +577,7 @@ BSP_Tree::BSP_Tree(const PoolVector<Face3> &p_faces, real_t p_error_radius) {
error_radius = p_error_radius;
}
-BSP_Tree::BSP_Tree(const Vector<Node> &p_nodes, const Vector<Plane> &p_planes, const Rect3 &p_aabb, real_t p_error_radius)
+BSP_Tree::BSP_Tree(const Vector<Node> &p_nodes, const Vector<Plane> &p_planes, const AABB &p_aabb, real_t p_error_radius)
: nodes(p_nodes),
planes(p_planes),
aabb(p_aabb),
diff --git a/core/math/bsp_tree.h b/core/math/bsp_tree.h
index 2e762ba4de..f64a13ce39 100644
--- a/core/math/bsp_tree.h
+++ b/core/math/bsp_tree.h
@@ -30,11 +30,11 @@
#ifndef BSP_TREE_H
#define BSP_TREE_H
+#include "aabb.h"
#include "dvector.h"
#include "face3.h"
#include "method_ptrcall.h"
#include "plane.h"
-#include "rect3.h"
#include "variant.h"
#include "vector.h"
/**
@@ -64,7 +64,7 @@ private:
Vector<Node> nodes;
Vector<Plane> planes;
- Rect3 aabb;
+ AABB aabb;
real_t error_radius;
int _get_points_inside(int p_node, const Vector3 *p_points, int *p_indices, const Vector3 &p_center, const Vector3 &p_half_extents, int p_indices_count) const;
@@ -76,7 +76,7 @@ public:
bool is_empty() const { return nodes.size() == 0; }
Vector<Node> get_nodes() const;
Vector<Plane> get_planes() const;
- Rect3 get_aabb() const;
+ AABB get_aabb() const;
bool point_is_inside(const Vector3 &p_point) const;
int get_points_inside(const Vector3 *p_points, int p_point_count) const;
@@ -85,12 +85,12 @@ public:
operator Variant() const;
- void from_aabb(const Rect3 &p_aabb);
+ void from_aabb(const AABB &p_aabb);
BSP_Tree();
BSP_Tree(const Variant &p_variant);
BSP_Tree(const PoolVector<Face3> &p_faces, real_t p_error_radius = 0);
- BSP_Tree(const Vector<Node> &p_nodes, const Vector<Plane> &p_planes, const Rect3 &p_aabb, real_t p_error_radius = 0);
+ BSP_Tree(const Vector<Node> &p_nodes, const Vector<Plane> &p_planes, const AABB &p_aabb, real_t p_error_radius = 0);
~BSP_Tree();
};
diff --git a/core/math/camera_matrix.cpp b/core/math/camera_matrix.cpp
index 2c587762e8..c5f1d57441 100644
--- a/core/math/camera_matrix.cpp
+++ b/core/math/camera_matrix.cpp
@@ -596,7 +596,7 @@ void CameraMatrix::make_scale(const Vector3 &p_scale) {
matrix[2][2] = p_scale.z;
}
-void CameraMatrix::scale_translate_to_fit(const Rect3 &p_aabb) {
+void CameraMatrix::scale_translate_to_fit(const AABB &p_aabb) {
Vector3 min = p_aabb.position;
Vector3 max = p_aabb.position + p_aabb.size;
diff --git a/core/math/camera_matrix.h b/core/math/camera_matrix.h
index 3145d73356..15d6b8128e 100644
--- a/core/math/camera_matrix.h
+++ b/core/math/camera_matrix.h
@@ -86,7 +86,7 @@ struct CameraMatrix {
operator String() const;
- void scale_translate_to_fit(const Rect3 &p_aabb);
+ void scale_translate_to_fit(const AABB &p_aabb);
void make_scale(const Vector3 &p_scale);
int get_pixels_per_meter(int p_for_pixel_width) const;
operator Transform() const;
diff --git a/core/math/face3.cpp b/core/math/face3.cpp
index e1b172e491..070ce77db4 100644
--- a/core/math/face3.cpp
+++ b/core/math/face3.cpp
@@ -189,13 +189,13 @@ ClockDirection Face3::get_clock_dir() const {
return (normal.dot(vertex[0]) >= 0) ? CLOCKWISE : COUNTERCLOCKWISE;
}
-bool Face3::intersects_aabb(const Rect3 &p_aabb) const {
+bool Face3::intersects_aabb(const AABB &p_aabb) const {
/** TEST PLANE **/
if (!p_aabb.intersects_plane(get_plane()))
return false;
-/** TEST FACE AXIS */
+ /** TEST FACE AXIS */
#define TEST_AXIS(m_ax) \
{ \
diff --git a/core/math/face3.h b/core/math/face3.h
index 8e4a25fb7a..561fa31238 100644
--- a/core/math/face3.h
+++ b/core/math/face3.h
@@ -30,8 +30,8 @@
#ifndef FACE3_H
#define FACE3_H
+#include "aabb.h"
#include "plane.h"
-#include "rect3.h"
#include "transform.h"
#include "vector3.h"
@@ -76,16 +76,16 @@ public:
void get_support(const Vector3 &p_normal, const Transform &p_transform, Vector3 *p_vertices, int *p_count, int p_max) const;
void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const;
- Rect3 get_aabb() const {
+ AABB get_aabb() const {
- Rect3 aabb(vertex[0], Vector3());
+ AABB aabb(vertex[0], Vector3());
aabb.expand_to(vertex[1]);
aabb.expand_to(vertex[2]);
return aabb;
}
- bool intersects_aabb(const Rect3 &p_aabb) const;
- _FORCE_INLINE_ bool intersects_aabb2(const Rect3 &p_aabb) const;
+ bool intersects_aabb(const AABB &p_aabb) const;
+ _FORCE_INLINE_ bool intersects_aabb2(const AABB &p_aabb) const;
operator String() const;
inline Face3() {}
@@ -96,7 +96,7 @@ public:
}
};
-bool Face3::intersects_aabb2(const Rect3 &p_aabb) const {
+bool Face3::intersects_aabb2(const AABB &p_aabb) const {
Vector3 perp = (vertex[0] - vertex[2]).cross(vertex[0] - vertex[1]);
@@ -256,6 +256,6 @@ bool Face3::intersects_aabb2(const Rect3 &p_aabb) const {
return true;
}
-//this sucks...
+ //this sucks...
#endif // FACE3_H
diff --git a/core/math/geometry.cpp b/core/math/geometry.cpp
index 7c8fb6f17d..39bd34f03c 100644
--- a/core/math/geometry.cpp
+++ b/core/math/geometry.cpp
@@ -300,7 +300,7 @@ enum _CellFlags {
static inline void _plot_face(uint8_t ***p_cell_status, int x, int y, int z, int len_x, int len_y, int len_z, const Vector3 &voxelsize, const Face3 &p_face) {
- Rect3 aabb(Vector3(x, y, z), Vector3(len_x, len_y, len_z));
+ AABB aabb(Vector3(x, y, z), Vector3(len_x, len_y, len_z));
aabb.position = aabb.position * voxelsize;
aabb.size = aabb.size * voxelsize;
@@ -575,7 +575,7 @@ PoolVector<Face3> Geometry::wrap_geometry(PoolVector<Face3> p_array, real_t *p_e
PoolVector<Face3>::Read facesr = p_array.read();
const Face3 *faces = facesr.ptr();
- Rect3 global_aabb;
+ AABB global_aabb;
for (int i = 0; i < face_count; i++) {
diff --git a/core/math/math_funcs.cpp b/core/math/math_funcs.cpp
index 6fb688f16b..64e01e5841 100644
--- a/core/math/math_funcs.cpp
+++ b/core/math/math_funcs.cpp
@@ -176,3 +176,18 @@ float Math::random(float from, float to) {
float ret = (float)r / (float)RANDOM_MAX;
return (ret) * (to - from) + from;
}
+
+int Math::wrapi(int value, int min, int max) {
+ --max;
+ int rng = max - min + 1;
+ value = ((value - min) % rng);
+ if (value < 0)
+ return max + 1 + value;
+ else
+ return min + value;
+}
+
+float Math::wrapf(float value, float min, float max) {
+ float rng = max - min;
+ return min + (value - min) - (rng * floor((value - min) / rng));
+}
diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h
index d63da322a5..bc0b3717ed 100644
--- a/core/math/math_funcs.h
+++ b/core/math/math_funcs.h
@@ -39,6 +39,7 @@
#include <math.h>
#define Math_PI 3.14159265358979323846
+#define Math_TAU 6.28318530717958647692
#define Math_SQRT12 0.7071067811865475244008443621048490
#define Math_LN2 0.693147180559945309417
#define Math_INF INFINITY
@@ -207,6 +208,9 @@ public:
static _ALWAYS_INLINE_ double round(double p_val) { return (p_val >= 0) ? Math::floor(p_val + 0.5) : -Math::floor(-p_val + 0.5); }
static _ALWAYS_INLINE_ float round(float p_val) { return (p_val >= 0) ? Math::floor(p_val + 0.5) : -Math::floor(-p_val + 0.5); }
+ static int wrapi(int value, int min, int max);
+ static float wrapf(float value, float min, float max);
+
// double only, as these functions are mainly used by the editor and not performance-critical,
static double ease(double p_x, double p_c);
static int step_decimals(double p_step);
@@ -387,6 +391,23 @@ public:
return hf;
}
+
+ static _ALWAYS_INLINE_ float snap_scalar(float p_offset, float p_step, float p_target) {
+ return p_step != 0 ? Math::stepify(p_target - p_offset, p_step) + p_offset : p_target;
+ }
+
+ static _ALWAYS_INLINE_ float snap_scalar_seperation(float p_offset, float p_step, float p_target, float p_separation) {
+ if (p_step != 0) {
+ float a = Math::stepify(p_target - p_offset, p_step + p_separation) + p_offset;
+ float b = a;
+ if (p_target >= 0)
+ b -= p_separation;
+ else
+ b += p_step;
+ return (Math::abs(p_target - a) < Math::abs(p_target - b)) ? a : b;
+ }
+ return p_target;
+ }
};
#endif // MATH_FUNCS_H
diff --git a/core/math/matrix3.cpp b/core/math/matrix3.cpp
index 4051de7afb..ab3bca79ae 100644
--- a/core/math/matrix3.cpp
+++ b/core/math/matrix3.cpp
@@ -279,7 +279,7 @@ Vector3 Basis::get_signed_scale() const {
// Decomposes a Basis into a rotation-reflection matrix (an element of the group O(3)) and a positive scaling matrix as B = O.S.
// Returns the rotation-reflection matrix via reference argument, and scaling information is returned as a Vector3.
-// This (internal) function is too specıfıc and named too ugly to expose to users, and probably there's no need to do so.
+// This (internal) function is too specific and named too ugly to expose to users, and probably there's no need to do so.
Vector3 Basis::rotref_posscale_decomposition(Basis &rotref) const {
#ifdef MATH_CHECKS
ERR_FAIL_COND_V(determinant() == 0, Vector3());
@@ -371,31 +371,30 @@ Vector3 Basis::get_euler_xyz() const {
#ifdef MATH_CHECKS
ERR_FAIL_COND_V(is_rotation() == false, euler);
#endif
- euler.y = Math::asin(elements[0][2]);
- if (euler.y < Math_PI * 0.5) {
- if (euler.y > -Math_PI * 0.5) {
+ real_t sy = elements[0][2];
+ if (sy < 1.0) {
+ if (sy > -1.0) {
// is this a pure Y rotation?
if (elements[1][0] == 0.0 && elements[0][1] == 0.0 && elements[1][2] == 0 && elements[2][1] == 0 && elements[1][1] == 1) {
- // return the simplest form
+ // return the simplest form (human friendlier in editor and scripts)
euler.x = 0;
euler.y = atan2(elements[0][2], elements[0][0]);
euler.z = 0;
} else {
euler.x = Math::atan2(-elements[1][2], elements[2][2]);
+ euler.y = Math::asin(sy);
euler.z = Math::atan2(-elements[0][1], elements[0][0]);
}
-
} else {
- real_t r = Math::atan2(elements[1][0], elements[1][1]);
+ euler.x = -Math::atan2(elements[0][1], elements[1][1]);
+ euler.y = -Math_PI / 2.0;
euler.z = 0.0;
- euler.x = euler.z - r;
}
} else {
- real_t r = Math::atan2(elements[0][1], elements[1][1]);
- euler.z = 0;
- euler.x = r - euler.z;
+ euler.x = Math::atan2(elements[0][1], elements[1][1]);
+ euler.y = Math_PI / 2.0;
+ euler.z = 0.0;
}
-
return euler;
}
@@ -445,7 +444,7 @@ Vector3 Basis::get_euler_yxz() const {
if (m12 > -1) {
// is this a pure X rotation?
if (elements[1][0] == 0 && elements[0][1] == 0 && elements[0][2] == 0 && elements[2][0] == 0 && elements[0][0] == 1) {
- // return the simplest form
+ // return the simplest form (human friendlier in editor and scripts)
euler.x = atan2(-m12, elements[1][1]);
euler.y = 0;
euler.z = 0;
@@ -538,7 +537,7 @@ Basis::operator String() const {
return mtx;
}
-Basis::operator Quat() const {
+Quat Basis::get_quat() const {
//commenting this check because precision issues cause it to fail when it shouldn't
//#ifdef MATH_CHECKS
//ERR_FAIL_COND_V(is_rotation() == false, Quat());
@@ -710,12 +709,7 @@ void Basis::get_axis_angle(Vector3 &r_axis, real_t &r_angle) const {
r_angle = angle;
}
-Basis::Basis(const Vector3 &p_euler) {
-
- set_euler(p_euler);
-}
-
-Basis::Basis(const Quat &p_quat) {
+void Basis::set_quat(const Quat &p_quat) {
real_t d = p_quat.length_squared();
real_t s = 2.0 / d;
@@ -750,7 +744,3 @@ void Basis::set_axis_angle(const Vector3 &p_axis, real_t p_phi) {
elements[2][1] = p_axis.y * p_axis.z * (1.0 - cosine) + p_axis.x * sine;
elements[2][2] = axis_sq.z + cosine * (1.0 - axis_sq.z);
}
-
-Basis::Basis(const Vector3 &p_axis, real_t p_phi) {
- set_axis_angle(p_axis, p_phi);
-}
diff --git a/core/math/matrix3.h b/core/math/matrix3.h
index 23429888e0..9a33b8203d 100644
--- a/core/math/matrix3.h
+++ b/core/math/matrix3.h
@@ -88,8 +88,11 @@ public:
Vector3 get_euler_yxz() const;
void set_euler_yxz(const Vector3 &p_euler);
- Vector3 get_euler() const { return get_euler_yxz(); };
- void set_euler(const Vector3 &p_euler) { set_euler_yxz(p_euler); };
+ Quat get_quat() const;
+ void set_quat(const Quat &p_quat);
+
+ Vector3 get_euler() const { return get_euler_yxz(); }
+ void set_euler(const Vector3 &p_euler) { set_euler_yxz(p_euler); }
void get_axis_angle(Vector3 &r_axis, real_t &r_angle) const;
void set_axis_angle(const Vector3 &p_axis, real_t p_phi);
@@ -205,11 +208,11 @@ public:
bool is_symmetric() const;
Basis diagonalize();
- operator Quat() const;
+ operator Quat() const { return get_quat(); }
- Basis(const Quat &p_quat); // euler
- Basis(const Vector3 &p_euler); // euler
- Basis(const Vector3 &p_axis, real_t p_phi);
+ Basis(const Quat &p_quat) { set_quat(p_quat); };
+ Basis(const Vector3 &p_euler) { set_euler(p_euler); }
+ Basis(const Vector3 &p_axis, real_t p_phi) { set_axis_angle(p_axis, p_phi); }
_FORCE_INLINE_ Basis(const Vector3 &row0, const Vector3 &row1, const Vector3 &row2) {
elements[0] = row0;
diff --git a/core/math/octree.h b/core/math/octree.h
index 95a67943fd..6acd4c5f75 100644
--- a/core/math/octree.h
+++ b/core/math/octree.h
@@ -30,10 +30,10 @@
#ifndef OCTREE_H
#define OCTREE_H
+#include "aabb.h"
#include "list.h"
#include "map.h"
#include "print_string.h"
-#include "rect3.h"
#include "variant.h"
#include "vector3.h"
@@ -106,7 +106,7 @@ private:
struct Octant {
// cached for FAST plane check
- Rect3 aabb;
+ AABB aabb;
uint64_t last_pass;
Octant *parent;
@@ -152,8 +152,8 @@ private:
OctreeElementID _id;
Octant *common_parent;
- Rect3 aabb;
- Rect3 container_aabb;
+ AABB aabb;
+ AABB container_aabb;
List<PairData *, AL> pair_list;
@@ -334,7 +334,7 @@ private:
}
void _insert_element(Element *p_element, Octant *p_octant);
- void _ensure_valid_root(const Rect3 &p_aabb);
+ void _ensure_valid_root(const AABB &p_aabb);
bool _remove_element_from_octant(Element *p_element, Octant *p_octant, Octant *p_limit = NULL);
void _remove_element(Element *p_element);
void _pair_element(Element *p_element, Octant *p_octant);
@@ -351,7 +351,7 @@ private:
};
void _cull_convex(Octant *p_octant, _CullConvexData *p_cull);
- void _cull_aabb(Octant *p_octant, const Rect3 &p_aabb, T **p_result_array, int *p_result_idx, int p_result_max, int *p_subindex_array, uint32_t p_mask);
+ void _cull_aabb(Octant *p_octant, const AABB &p_aabb, T **p_result_array, int *p_result_idx, int p_result_max, int *p_subindex_array, uint32_t p_mask);
void _cull_segment(Octant *p_octant, const Vector3 &p_from, const Vector3 &p_to, T **p_result_array, int *p_result_idx, int p_result_max, int *p_subindex_array, uint32_t p_mask);
void _cull_point(Octant *p_octant, const Vector3 &p_point, T **p_result_array, int *p_result_idx, int p_result_max, int *p_subindex_array, uint32_t p_mask);
@@ -370,8 +370,8 @@ private:
}
public:
- OctreeElementID create(T *p_userdata, const Rect3 &p_aabb = Rect3(), int p_subindex = 0, bool p_pairable = false, uint32_t p_pairable_type = 0, uint32_t pairable_mask = 1);
- void move(OctreeElementID p_id, const Rect3 &p_aabb);
+ OctreeElementID create(T *p_userdata, const AABB &p_aabb = AABB(), int p_subindex = 0, bool p_pairable = false, uint32_t p_pairable_type = 0, uint32_t pairable_mask = 1);
+ void move(OctreeElementID p_id, const AABB &p_aabb);
void set_pairable(OctreeElementID p_id, bool p_pairable = false, uint32_t p_pairable_type = 0, uint32_t pairable_mask = 1);
void erase(OctreeElementID p_id);
@@ -380,7 +380,7 @@ public:
int get_subindex(OctreeElementID p_id) const;
int cull_convex(const Vector<Plane> &p_convex, T **p_result_array, int p_result_max, uint32_t p_mask = 0xFFFFFFFF);
- int cull_aabb(const Rect3 &p_aabb, T **p_result_array, int p_result_max, int *p_subindex_array = NULL, uint32_t p_mask = 0xFFFFFFFF);
+ int cull_aabb(const AABB &p_aabb, T **p_result_array, int p_result_max, int *p_subindex_array = NULL, uint32_t p_mask = 0xFFFFFFFF);
int cull_segment(const Vector3 &p_from, const Vector3 &p_to, T **p_result_array, int p_result_max, int *p_subindex_array = NULL, uint32_t p_mask = 0xFFFFFFFF);
int cull_point(const Vector3 &p_point, T **p_result_array, int p_result_max, int *p_subindex_array = NULL, uint32_t p_mask = 0xFFFFFFFF);
@@ -479,7 +479,7 @@ void Octree<T, use_pairs, AL>::_insert_element(Element *p_element, Octant *p_oct
} else {
/* check againt AABB where child should be */
- Rect3 aabb = p_octant->aabb;
+ AABB aabb = p_octant->aabb;
aabb.size *= 0.5;
if (i & 1)
@@ -535,12 +535,12 @@ void Octree<T, use_pairs, AL>::_insert_element(Element *p_element, Octant *p_oct
}
template <class T, bool use_pairs, class AL>
-void Octree<T, use_pairs, AL>::_ensure_valid_root(const Rect3 &p_aabb) {
+void Octree<T, use_pairs, AL>::_ensure_valid_root(const AABB &p_aabb) {
if (!root) {
// octre is empty
- Rect3 base(Vector3(), Vector3(1.0, 1.0, 1.0) * unit_size);
+ AABB base(Vector3(), Vector3(1.0, 1.0, 1.0) * unit_size);
while (!base.encloses(p_aabb)) {
@@ -563,7 +563,7 @@ void Octree<T, use_pairs, AL>::_ensure_valid_root(const Rect3 &p_aabb) {
} else {
- Rect3 base = root->aabb;
+ AABB base = root->aabb;
while (!base.encloses(p_aabb)) {
@@ -793,7 +793,7 @@ void Octree<T, use_pairs, AL>::_remove_element(Element *p_element) {
}
template <class T, bool use_pairs, class AL>
-OctreeElementID Octree<T, use_pairs, AL>::create(T *p_userdata, const Rect3 &p_aabb, int p_subindex, bool p_pairable, uint32_t p_pairable_type, uint32_t p_pairable_mask) {
+OctreeElementID Octree<T, use_pairs, AL>::create(T *p_userdata, const AABB &p_aabb, int p_subindex, bool p_pairable, uint32_t p_pairable_type, uint32_t p_pairable_mask) {
// check for AABB validity
#ifdef DEBUG_ENABLED
@@ -833,7 +833,7 @@ OctreeElementID Octree<T, use_pairs, AL>::create(T *p_userdata, const Rect3 &p_a
}
template <class T, bool use_pairs, class AL>
-void Octree<T, use_pairs, AL>::move(OctreeElementID p_id, const Rect3 &p_aabb) {
+void Octree<T, use_pairs, AL>::move(OctreeElementID p_id, const AABB &p_aabb) {
#ifdef DEBUG_ENABLED
// check for AABB validity
@@ -859,7 +859,7 @@ void Octree<T, use_pairs, AL>::move(OctreeElementID p_id, const Rect3 &p_aabb) {
if (old_has_surf) {
_remove_element(&e); // removing
e.common_parent = NULL;
- e.aabb = Rect3();
+ e.aabb = AABB();
_optimize();
} else {
_ensure_valid_root(p_aabb); // inserting
@@ -886,7 +886,7 @@ void Octree<T, use_pairs, AL>::move(OctreeElementID p_id, const Rect3 &p_aabb) {
return;
}
- Rect3 combined = e.aabb;
+ AABB combined = e.aabb;
combined.merge_with(p_aabb);
_ensure_valid_root(combined);
@@ -1072,7 +1072,7 @@ void Octree<T, use_pairs, AL>::_cull_convex(Octant *p_octant, _CullConvexData *p
}
template <class T, bool use_pairs, class AL>
-void Octree<T, use_pairs, AL>::_cull_aabb(Octant *p_octant, const Rect3 &p_aabb, T **p_result_array, int *p_result_idx, int p_result_max, int *p_subindex_array, uint32_t p_mask) {
+void Octree<T, use_pairs, AL>::_cull_aabb(Octant *p_octant, const AABB &p_aabb, T **p_result_array, int *p_result_idx, int p_result_max, int *p_subindex_array, uint32_t p_mask) {
if (*p_result_idx == p_result_max)
return; //pointless
@@ -1313,7 +1313,7 @@ int Octree<T, use_pairs, AL>::cull_convex(const Vector<Plane> &p_convex, T **p_r
}
template <class T, bool use_pairs, class AL>
-int Octree<T, use_pairs, AL>::cull_aabb(const Rect3 &p_aabb, T **p_result_array, int p_result_max, int *p_subindex_array, uint32_t p_mask) {
+int Octree<T, use_pairs, AL>::cull_aabb(const AABB &p_aabb, T **p_result_array, int p_result_max, int *p_subindex_array, uint32_t p_mask) {
if (!root)
return 0;
diff --git a/core/math/quick_hull.cpp b/core/math/quick_hull.cpp
index e0137b6921..946d9f6b79 100644
--- a/core/math/quick_hull.cpp
+++ b/core/math/quick_hull.cpp
@@ -38,7 +38,7 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry::MeshData &r_me
/* CREATE AABB VOLUME */
- Rect3 aabb;
+ AABB aabb;
for (int i = 0; i < p_points.size(); i++) {
if (i == 0) {
diff --git a/core/math/quick_hull.h b/core/math/quick_hull.h
index 47ed22615b..f014d0decc 100644
--- a/core/math/quick_hull.h
+++ b/core/math/quick_hull.h
@@ -30,9 +30,9 @@
#ifndef QUICK_HULL_H
#define QUICK_HULL_H
+#include "aabb.h"
#include "geometry.h"
#include "list.h"
-#include "rect3.h"
#include "set.h"
class QuickHull {
diff --git a/core/math/transform.h b/core/math/transform.h
index 566bf482a9..4d91869121 100644
--- a/core/math/transform.h
+++ b/core/math/transform.h
@@ -30,9 +30,9 @@
#ifndef TRANSFORM_H
#define TRANSFORM_H
+#include "aabb.h"
#include "matrix3.h"
#include "plane.h"
-#include "rect3.h"
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
@@ -80,8 +80,8 @@ public:
_FORCE_INLINE_ Plane xform(const Plane &p_plane) const;
_FORCE_INLINE_ Plane xform_inv(const Plane &p_plane) const;
- _FORCE_INLINE_ Rect3 xform(const Rect3 &p_aabb) const;
- _FORCE_INLINE_ Rect3 xform_inv(const Rect3 &p_aabb) const;
+ _FORCE_INLINE_ AABB xform(const AABB &p_aabb) const;
+ _FORCE_INLINE_ AABB xform_inv(const AABB &p_aabb) const;
void operator*=(const Transform &p_transform);
Transform operator*(const Transform &p_transform) const;
@@ -153,14 +153,14 @@ _FORCE_INLINE_ Plane Transform::xform_inv(const Plane &p_plane) const {
return Plane(normal, d);
}
-_FORCE_INLINE_ Rect3 Transform::xform(const Rect3 &p_aabb) const {
+_FORCE_INLINE_ AABB Transform::xform(const AABB &p_aabb) const {
/* define vertices */
Vector3 x = basis.get_axis(0) * p_aabb.size.x;
Vector3 y = basis.get_axis(1) * p_aabb.size.y;
Vector3 z = basis.get_axis(2) * p_aabb.size.z;
Vector3 pos = xform(p_aabb.position);
//could be even further optimized
- Rect3 new_aabb;
+ AABB new_aabb;
new_aabb.position = pos;
new_aabb.expand_to(pos + x);
new_aabb.expand_to(pos + y);
@@ -172,7 +172,7 @@ _FORCE_INLINE_ Rect3 Transform::xform(const Rect3 &p_aabb) const {
return new_aabb;
}
-_FORCE_INLINE_ Rect3 Transform::xform_inv(const Rect3 &p_aabb) const {
+_FORCE_INLINE_ AABB Transform::xform_inv(const AABB &p_aabb) const {
/* define vertices */
Vector3 vertices[8] = {
@@ -186,7 +186,7 @@ _FORCE_INLINE_ Rect3 Transform::xform_inv(const Rect3 &p_aabb) const {
Vector3(p_aabb.position.x, p_aabb.position.y, p_aabb.position.z)
};
- Rect3 ret;
+ AABB ret;
ret.position = xform_inv(vertices[0]);
diff --git a/core/math/triangle_mesh.cpp b/core/math/triangle_mesh.cpp
index 3b246cb183..5f57c7c26a 100644
--- a/core/math/triangle_mesh.cpp
+++ b/core/math/triangle_mesh.cpp
@@ -44,7 +44,7 @@ int TriangleMesh::_create_bvh(BVH *p_bvh, BVH **p_bb, int p_from, int p_size, in
return -1;
}
- Rect3 aabb;
+ AABB aabb;
aabb = p_bb[p_from]->aabb;
for (int i = 1; i < p_size; i++) {
@@ -166,7 +166,7 @@ void TriangleMesh::create(const PoolVector<Vector3> &p_faces) {
valid = true;
}
-Vector3 TriangleMesh::get_area_normal(const Rect3 &p_aabb) const {
+Vector3 TriangleMesh::get_area_normal(const AABB &p_aabb) const {
uint32_t *stack = (uint32_t *)alloca(sizeof(int) * max_depth);
diff --git a/core/math/triangle_mesh.h b/core/math/triangle_mesh.h
index 2bf67fffcb..4bd9fecf37 100644
--- a/core/math/triangle_mesh.h
+++ b/core/math/triangle_mesh.h
@@ -47,7 +47,7 @@ class TriangleMesh : public Reference {
struct BVH {
- Rect3 aabb;
+ AABB aabb;
Vector3 center; //used for sorting
int left;
int right;
@@ -88,7 +88,7 @@ public:
bool is_valid() const;
bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_point, Vector3 &r_normal) const;
bool intersect_ray(const Vector3 &p_begin, const Vector3 &p_dir, Vector3 &r_point, Vector3 &r_normal) const;
- Vector3 get_area_normal(const Rect3 &p_aabb) const;
+ Vector3 get_area_normal(const AABB &p_aabb) const;
PoolVector<Face3> get_faces() const;
void create(const PoolVector<Vector3> &p_faces);
diff --git a/core/method_ptrcall.h b/core/method_ptrcall.h
index 2875eb912f..d819dfbc27 100644
--- a/core/method_ptrcall.h
+++ b/core/method_ptrcall.h
@@ -119,7 +119,7 @@ MAKE_PTRARG_BY_REFERENCE(Vector3);
MAKE_PTRARG(Transform2D);
MAKE_PTRARG_BY_REFERENCE(Plane);
MAKE_PTRARG(Quat);
-MAKE_PTRARG_BY_REFERENCE(Rect3);
+MAKE_PTRARG_BY_REFERENCE(AABB);
MAKE_PTRARG_BY_REFERENCE(Basis);
MAKE_PTRARG_BY_REFERENCE(Transform);
MAKE_PTRARG_BY_REFERENCE(Color);
diff --git a/core/ordered_hash_map.h b/core/ordered_hash_map.h
index 9e95f963e1..1ed5a5d369 100644
--- a/core/ordered_hash_map.h
+++ b/core/ordered_hash_map.h
@@ -93,8 +93,12 @@ public:
return *this;
}
- friend bool operator==(const Element &, const Element &);
- friend bool operator!=(const Element &, const Element &);
+ _FORCE_INLINE_ bool operator==(const Element &p_other) const {
+ return this->list_element == p_other.list_element;
+ }
+ _FORCE_INLINE_ bool operator!=(const Element &p_other) const {
+ return this->list_element != p_other.list_element;
+ }
operator bool() const {
return (list_element != NULL);
@@ -157,8 +161,12 @@ public:
return ConstElement(list_element ? list_element->prev() : NULL);
}
- friend bool operator==(const ConstElement &, const ConstElement &);
- friend bool operator!=(const ConstElement &, const ConstElement &);
+ _FORCE_INLINE_ bool operator==(const ConstElement &p_other) const {
+ return this->list_element == p_other.list_element;
+ }
+ _FORCE_INLINE_ bool operator!=(const ConstElement &p_other) const {
+ return this->list_element != p_other.list_element;
+ }
operator bool() const {
return (list_element != NULL);
@@ -181,7 +189,7 @@ public:
};
ConstElement find(const K &p_key) const {
- typename InternalList::Element **list_element = map.getptr(p_key);
+ typename InternalList::Element *const *list_element = map.getptr(p_key);
if (list_element) {
return ConstElement(*list_element);
}
@@ -288,28 +296,4 @@ public:
}
};
-template <class K, class V, class Hasher, class Comparator, uint8_t MIN_HASH_TABLE_POWER, uint8_t RELATIONSHIP>
-bool operator==(const typename OrderedHashMap<K, V, Hasher, Comparator, MIN_HASH_TABLE_POWER, RELATIONSHIP>::Element &first,
- const typename OrderedHashMap<K, V, Hasher, Comparator, MIN_HASH_TABLE_POWER, RELATIONSHIP>::Element &second) {
- return (first.list_element == second.list_element);
-}
-
-template <class K, class V, class Hasher, class Comparator, uint8_t MIN_HASH_TABLE_POWER, uint8_t RELATIONSHIP>
-bool operator!=(const typename OrderedHashMap<K, V, Hasher, Comparator, MIN_HASH_TABLE_POWER, RELATIONSHIP>::Element &first,
- const typename OrderedHashMap<K, V, Hasher, Comparator, MIN_HASH_TABLE_POWER, RELATIONSHIP>::Element &second) {
- return (first.list_element != second.list_element);
-}
-
-template <class K, class V, class Hasher, class Comparator, uint8_t MIN_HASH_TABLE_POWER, uint8_t RELATIONSHIP>
-bool operator==(const typename OrderedHashMap<K, V, Hasher, Comparator, MIN_HASH_TABLE_POWER, RELATIONSHIP>::ConstElement &first,
- const typename OrderedHashMap<K, V, Hasher, Comparator, MIN_HASH_TABLE_POWER, RELATIONSHIP>::ConstElement &second) {
- return (first.list_element == second.list_element);
-}
-
-template <class K, class V, class Hasher, class Comparator, uint8_t MIN_HASH_TABLE_POWER, uint8_t RELATIONSHIP>
-bool operator!=(const typename OrderedHashMap<K, V, Hasher, Comparator, MIN_HASH_TABLE_POWER, RELATIONSHIP>::ConstElement &first,
- const typename OrderedHashMap<K, V, Hasher, Comparator, MIN_HASH_TABLE_POWER, RELATIONSHIP>::ConstElement &second) {
- return (first.list_element != second.list_element);
-}
-
#endif // ORDERED_HASH_MAP_H
diff --git a/core/os/dir_access.cpp b/core/os/dir_access.cpp
index 0875f78478..6d4b46f4da 100644
--- a/core/os/dir_access.cpp
+++ b/core/os/dir_access.cpp
@@ -38,7 +38,7 @@ String DirAccess::_get_root_path() const {
switch (_access_type) {
case ACCESS_RESOURCES: return ProjectSettings::get_singleton()->get_resource_path();
- case ACCESS_USERDATA: return OS::get_singleton()->get_data_dir();
+ case ACCESS_USERDATA: return OS::get_singleton()->get_user_data_dir();
default: return "";
}
@@ -98,6 +98,7 @@ static Error _erase_recursive(DirAccess *da) {
err = _erase_recursive(da);
if (err) {
print_line("err recurso " + E->get());
+ da->change_dir("..");
return err;
}
err = da->change_dir("..");
@@ -217,7 +218,7 @@ String DirAccess::fix_path(String p_path) const {
if (p_path.begins_with("user://")) {
- String data_dir = OS::get_singleton()->get_data_dir();
+ String data_dir = OS::get_singleton()->get_user_data_dir();
if (data_dir != "") {
return p_path.replace_first("user:/", data_dir);
@@ -340,6 +341,102 @@ Error DirAccess::copy(String p_from, String p_to, int chmod_flags) {
return err;
}
+// Changes dir for the current scope, returning back to the original dir
+// when scope exits
+class DirChanger {
+ DirAccess *da;
+ String original_dir;
+
+public:
+ DirChanger(DirAccess *p_da, String p_dir) {
+ da = p_da;
+ original_dir = p_da->get_current_dir();
+ p_da->change_dir(p_dir);
+ }
+
+ ~DirChanger() {
+ da->change_dir(original_dir);
+ }
+};
+
+Error DirAccess::_copy_dir(DirAccess *p_target_da, String p_to, int p_chmod_flags) {
+ List<String> dirs;
+
+ String curdir = get_current_dir();
+ list_dir_begin();
+ String n = get_next();
+ while (n != String()) {
+
+ if (n != "." && n != "..") {
+
+ if (current_is_dir())
+ dirs.push_back(n);
+ else {
+ String rel_path = n;
+ if (!n.is_rel_path()) {
+ list_dir_end();
+ return ERR_BUG;
+ }
+ Error err = copy(get_current_dir() + "/" + n, p_to + rel_path, p_chmod_flags);
+ if (err) {
+ list_dir_end();
+ return err;
+ }
+ }
+ }
+
+ n = get_next();
+ }
+
+ list_dir_end();
+
+ for (List<String>::Element *E = dirs.front(); E; E = E->next()) {
+ String rel_path = E->get();
+ String target_dir = p_to + rel_path;
+ if (!p_target_da->dir_exists(target_dir)) {
+ Error err = p_target_da->make_dir(target_dir);
+ ERR_FAIL_COND_V(err, err);
+ }
+
+ Error err = change_dir(E->get());
+ ERR_FAIL_COND_V(err, err);
+ err = _copy_dir(p_target_da, p_to + rel_path + "/", p_chmod_flags);
+ if (err) {
+ change_dir("..");
+ ERR_PRINT("Failed to copy recursively");
+ return err;
+ }
+ err = change_dir("..");
+ if (err) {
+ ERR_PRINT("Failed to go back");
+ return err;
+ }
+ }
+
+ return OK;
+}
+
+Error DirAccess::copy_dir(String p_from, String p_to, int p_chmod_flags) {
+ ERR_FAIL_COND_V(!dir_exists(p_from), ERR_FILE_NOT_FOUND);
+
+ DirAccess *target_da = DirAccess::create_for_path(p_to);
+ ERR_FAIL_COND_V(!target_da, ERR_CANT_CREATE);
+
+ if (!target_da->dir_exists(p_to)) {
+ Error err = target_da->make_dir_recursive(p_to);
+ if (err) {
+ memdelete(target_da);
+ }
+ ERR_FAIL_COND_V(err, err);
+ }
+
+ DirChanger dir_changer(this, p_from);
+ Error err = _copy_dir(target_da, p_to + "/", p_chmod_flags);
+ memdelete(target_da);
+
+ return err;
+}
+
bool DirAccess::exists(String p_dir) {
DirAccess *da = DirAccess::create_for_path(p_dir);
diff --git a/core/os/dir_access.h b/core/os/dir_access.h
index 7fa3ce5cf1..f3d1320041 100644
--- a/core/os/dir_access.h
+++ b/core/os/dir_access.h
@@ -52,6 +52,9 @@ public:
private:
AccessType _access_type;
static CreateFunc create_func[ACCESS_MAX]; ///< set this to instance a filesystem object
+
+ Error _copy_dir(DirAccess *p_target_da, String p_to, int p_chmod_flags);
+
protected:
String _get_root_path() const;
String _get_root_string() const;
@@ -89,6 +92,7 @@ public:
static bool exists(String p_dir);
virtual size_t get_space_left() = 0;
+ Error copy_dir(String p_from, String p_to, int chmod_flags = -1);
virtual Error copy(String p_from, String p_to, int chmod_flags = -1);
virtual Error rename(String p_from, String p_to) = 0;
virtual Error remove(String p_name) = 0;
diff --git a/core/os/file_access.cpp b/core/os/file_access.cpp
index fcb3b58fed..5fdd2b9135 100644
--- a/core/os/file_access.cpp
+++ b/core/os/file_access.cpp
@@ -152,7 +152,7 @@ String FileAccess::fix_path(const String &p_path) const {
if (r_path.begins_with("user://")) {
- String data_dir = OS::get_singleton()->get_data_dir();
+ String data_dir = OS::get_singleton()->get_user_data_dir();
if (data_dir != "") {
return r_path.replace("user:/", data_dir);
diff --git a/core/os/input.cpp b/core/os/input.cpp
index a4b82299a7..848b003d5e 100644
--- a/core/os/input.cpp
+++ b/core/os/input.cpp
@@ -58,6 +58,7 @@ void Input::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_action_just_released", "action"), &Input::is_action_just_released);
ClassDB::bind_method(D_METHOD("add_joy_mapping", "mapping", "update_existing"), &Input::add_joy_mapping, DEFVAL(false));
ClassDB::bind_method(D_METHOD("remove_joy_mapping", "guid"), &Input::remove_joy_mapping);
+ ClassDB::bind_method(D_METHOD("joy_connection_changed", "device", "connected", "name", "guid"), &Input::joy_connection_changed);
ClassDB::bind_method(D_METHOD("is_joy_known", "device"), &Input::is_joy_known);
ClassDB::bind_method(D_METHOD("get_joy_axis", "device", "axis"), &Input::get_joy_axis);
ClassDB::bind_method(D_METHOD("get_joy_name", "device"), &Input::get_joy_name);
diff --git a/core/os/input_event.cpp b/core/os/input_event.cpp
index b237a1113a..3cdd9ae0e0 100644
--- a/core/os/input_event.cpp
+++ b/core/os/input_event.cpp
@@ -177,6 +177,14 @@ bool InputEventWithModifiers::get_command() const {
return command;
}
+void InputEventWithModifiers::set_modifiers_from_event(const InputEventWithModifiers *event) {
+
+ set_alt(event->get_alt());
+ set_shift(event->get_shift());
+ set_control(event->get_control());
+ set_metakey(event->get_metakey());
+}
+
void InputEventWithModifiers::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_alt", "enable"), &InputEventWithModifiers::set_alt);
@@ -436,10 +444,7 @@ Ref<InputEvent> InputEventMouseButton::xformed_by(const Transform2D &p_xform, co
mb->set_id(get_id());
mb->set_device(get_device());
- mb->set_alt(get_alt());
- mb->set_shift(get_shift());
- mb->set_control(get_control());
- mb->set_metakey(get_metakey());
+ mb->set_modifiers_from_event(this);
mb->set_position(l);
mb->set_global_position(g);
@@ -555,10 +560,7 @@ Ref<InputEvent> InputEventMouseMotion::xformed_by(const Transform2D &p_xform, co
mm->set_id(get_id());
mm->set_device(get_device());
- mm->set_alt(get_alt());
- mm->set_shift(get_shift());
- mm->set_control(get_control());
- mm->set_metakey(get_metakey());
+ mm->set_modifiers_from_event(this);
mm->set_position(l);
mm->set_global_position(g);
@@ -637,7 +639,7 @@ bool InputEventJoypadMotion::action_match(const Ref<InputEvent> &p_event) const
if (jm.is_null())
return false;
- return (axis == jm->axis && (axis_value < 0) == (jm->axis_value < 0));
+ return (axis == jm->axis && ((axis_value < 0) == (jm->axis_value < 0) || jm->axis_value == 0));
}
String InputEventJoypadMotion::as_text() const {
@@ -930,3 +932,75 @@ void InputEventAction::_bind_methods() {
InputEventAction::InputEventAction() {
pressed = false;
}
+/////////////////////////////
+
+void InputEventGesture::set_position(const Vector2 &p_pos) {
+
+ pos = p_pos;
+}
+
+Vector2 InputEventGesture::get_position() const {
+
+ return pos;
+}
+/////////////////////////////
+
+void InputEventMagnifyGesture::set_factor(real_t p_factor) {
+
+ factor = p_factor;
+}
+
+real_t InputEventMagnifyGesture::get_factor() const {
+
+ return factor;
+}
+
+Ref<InputEvent> InputEventMagnifyGesture::xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs) const {
+
+ Ref<InputEventMagnifyGesture> ev;
+ ev.instance();
+
+ ev->set_id(get_id());
+ ev->set_device(get_device());
+ ev->set_modifiers_from_event(this);
+
+ ev->set_position(p_xform.xform(get_position() + p_local_ofs));
+ ev->set_factor(get_factor());
+
+ return ev;
+}
+
+InputEventMagnifyGesture::InputEventMagnifyGesture() {
+
+ factor = 1.0;
+}
+/////////////////////////////
+
+void InputEventPanGesture::set_delta(const Vector2 &p_delta) {
+
+ delta = p_delta;
+}
+
+Vector2 InputEventPanGesture::get_delta() const {
+ return delta;
+}
+
+Ref<InputEvent> InputEventPanGesture::xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs) const {
+
+ Ref<InputEventPanGesture> ev;
+ ev.instance();
+
+ ev->set_id(get_id());
+ ev->set_device(get_device());
+ ev->set_modifiers_from_event(this);
+
+ ev->set_position(p_xform.xform(get_position() + p_local_ofs));
+ ev->set_delta(get_delta());
+
+ return ev;
+}
+
+InputEventPanGesture::InputEventPanGesture() {
+
+ delta = Vector2(0, 0);
+}
diff --git a/core/os/input_event.h b/core/os/input_event.h
index 5dc0f91d5f..2cba60bede 100644
--- a/core/os/input_event.h
+++ b/core/os/input_event.h
@@ -44,7 +44,7 @@
* The events are pretty obvious.
*/
-enum {
+enum ButtonList {
BUTTON_LEFT = 1,
BUTTON_RIGHT = 2,
BUTTON_MIDDLE = 3,
@@ -58,7 +58,7 @@ enum {
};
-enum {
+enum JoystickList {
JOY_BUTTON_0 = 0,
JOY_BUTTON_1 = 1,
@@ -122,7 +122,9 @@ enum {
JOY_AXIS_5 = 5,
JOY_AXIS_6 = 6,
JOY_AXIS_7 = 7,
- JOY_AXIS_MAX = 8,
+ JOY_AXIS_8 = 8,
+ JOY_AXIS_9 = 9,
+ JOY_AXIS_MAX = 10,
JOY_ANALOG_LX = JOY_AXIS_0,
JOY_ANALOG_LY = JOY_AXIS_1,
@@ -211,6 +213,8 @@ public:
void set_command(bool p_enabled);
bool get_command() const;
+ void set_modifiers_from_event(const InputEventWithModifiers *event);
+
InputEventWithModifiers();
};
@@ -466,4 +470,42 @@ public:
InputEventAction();
};
+class InputEventGesture : public InputEventWithModifiers {
+
+ GDCLASS(InputEventGesture, InputEventWithModifiers)
+
+ Vector2 pos;
+
+public:
+ void set_position(const Vector2 &p_pos);
+ Vector2 get_position() const;
+};
+
+class InputEventMagnifyGesture : public InputEventGesture {
+
+ GDCLASS(InputEventMagnifyGesture, InputEventGesture)
+ real_t factor;
+
+public:
+ void set_factor(real_t p_factor);
+ real_t get_factor() const;
+
+ virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const;
+
+ InputEventMagnifyGesture();
+};
+
+class InputEventPanGesture : public InputEventGesture {
+
+ GDCLASS(InputEventPanGesture, InputEventGesture)
+ Vector2 delta;
+
+public:
+ void set_delta(const Vector2 &p_delta);
+ Vector2 get_delta() const;
+
+ virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const;
+
+ InputEventPanGesture();
+};
#endif
diff --git a/core/os/keyboard.cpp b/core/os/keyboard.cpp
index be1341054b..dead3b6ac0 100644
--- a/core/os/keyboard.cpp
+++ b/core/os/keyboard.cpp
@@ -532,6 +532,27 @@ static const _KeyCodeReplace _keycode_replace_neo[] = {
{ 0, 0 }
};
+static const _KeyCodeReplace _keycode_replace_colemak[] = {
+ { KEY_E, KEY_F },
+ { KEY_R, KEY_P },
+ { KEY_T, KEY_G },
+ { KEY_Y, KEY_J },
+ { KEY_U, KEY_L },
+ { KEY_I, KEY_U },
+ { KEY_O, KEY_Y },
+ { KEY_P, KEY_SEMICOLON },
+ { KEY_S, KEY_R },
+ { KEY_D, KEY_S },
+ { KEY_F, KEY_T },
+ { KEY_G, KEY_D },
+ { KEY_J, KEY_N },
+ { KEY_K, KEY_E },
+ { KEY_L, KEY_I },
+ { KEY_SEMICOLON, KEY_O },
+ { KEY_N, KEY_K },
+ { 0, 0 }
+};
+
int keycode_get_count() {
const _KeyCodeText *kct = &_keycodes[0];
@@ -564,6 +585,7 @@ int latin_keyboard_keycode_convert(int p_keycode) {
case OS::LATIN_KEYBOARD_QZERTY: kcr = _keycode_replace_qzerty; break;
case OS::LATIN_KEYBOARD_DVORAK: kcr = _keycode_replace_dvorak; break;
case OS::LATIN_KEYBOARD_NEO: kcr = _keycode_replace_neo; break;
+ case OS::LATIN_KEYBOARD_COLEMAK: kcr = _keycode_replace_colemak; break;
default: return p_keycode;
}
diff --git a/core/os/main_loop.cpp b/core/os/main_loop.cpp
index b146d370f1..8b4449586b 100644
--- a/core/os/main_loop.cpp
+++ b/core/os/main_loop.cpp
@@ -52,6 +52,7 @@ void MainLoop::_bind_methods() {
BIND_CONSTANT(NOTIFICATION_WM_FOCUS_IN);
BIND_CONSTANT(NOTIFICATION_WM_FOCUS_OUT);
BIND_CONSTANT(NOTIFICATION_WM_QUIT_REQUEST);
+ BIND_CONSTANT(NOTIFICATION_WM_GO_BACK_REQUEST);
BIND_CONSTANT(NOTIFICATION_WM_UNFOCUS_REQUEST);
BIND_CONSTANT(NOTIFICATION_OS_MEMORY_WARNING);
BIND_CONSTANT(NOTIFICATION_TRANSLATION_CHANGED);
diff --git a/core/os/memory.cpp b/core/os/memory.cpp
index 74d5cbbea1..439951f711 100644
--- a/core/os/memory.cpp
+++ b/core/os/memory.cpp
@@ -44,6 +44,26 @@ void *operator new(size_t p_size, void *(*p_allocfunc)(size_t p_size)) {
return p_allocfunc(p_size);
}
+#ifdef _MSC_VER
+void operator delete(void *p_mem, const char *p_description) {
+
+ ERR_EXPLAINC("Call to placement delete should not happen.");
+ CRASH_NOW();
+}
+
+void operator delete(void *p_mem, void *(*p_allocfunc)(size_t p_size)) {
+
+ ERR_EXPLAINC("Call to placement delete should not happen.");
+ CRASH_NOW();
+}
+
+void operator delete(void *p_mem, void *p_pointer, size_t check, const char *p_description) {
+
+ ERR_EXPLAINC("Call to placement delete should not happen.");
+ CRASH_NOW();
+}
+#endif
+
#ifdef DEBUG_ENABLED
uint64_t Memory::mem_usage = 0;
uint64_t Memory::max_usage = 0;
diff --git a/core/os/memory.h b/core/os/memory.h
index f8b3da579b..7801d56837 100644
--- a/core/os/memory.h
+++ b/core/os/memory.h
@@ -72,6 +72,14 @@ void *operator new(size_t p_size, void *(*p_allocfunc)(size_t p_size)); ///< ope
void *operator new(size_t p_size, void *p_pointer, size_t check, const char *p_description); ///< operator new that takes a description and uses a pointer to the preallocated memory
+#ifdef _MSC_VER
+// When compiling with VC++ 2017, the above declarations of placement new generate many irrelevant warnings (C4291).
+// The purpose of the following definitions is to muffle these warnings, not to provide a usable implementation of placement delete.
+void operator delete(void *p_mem, const char *p_description);
+void operator delete(void *p_mem, void *(*p_allocfunc)(size_t p_size));
+void operator delete(void *p_mem, void *p_pointer, size_t check, const char *p_description);
+#endif
+
#define memalloc(m_size) Memory::alloc_static(m_size)
#define memrealloc(m_mem, m_size) Memory::realloc_static(m_mem, m_size)
#define memfree(m_size) Memory::free_static(m_size)
diff --git a/core/os/os.cpp b/core/os/os.cpp
index eb5d5be33d..0e7e26df73 100644
--- a/core/os/os.cpp
+++ b/core/os/os.cpp
@@ -33,6 +33,7 @@
#include "input.h"
#include "os/file_access.h"
#include "project_settings.h"
+#include "version_generated.gen.h"
#include <stdarg.h>
@@ -62,15 +63,21 @@ void OS::debug_break(){
// something
};
-void OS::_set_logger(Logger *p_logger) {
+void OS::_set_logger(CompositeLogger *p_logger) {
if (_logger) {
memdelete(_logger);
}
_logger = p_logger;
}
-void OS::initialize_logger() {
- _set_logger(memnew(StdLogger));
+void OS::add_logger(Logger *p_logger) {
+ if (!_logger) {
+ Vector<Logger *> loggers;
+ loggers.push_back(p_logger);
+ _logger = memnew(CompositeLogger(loggers));
+ } else {
+ _logger->add_logger(p_logger);
+ }
}
void OS::print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, Logger::ErrorType p_type) {
@@ -262,16 +269,7 @@ String OS::get_locale() const {
return "en";
}
-String OS::get_resource_dir() const {
-
- return ProjectSettings::get_singleton()->get_resource_path();
-}
-
-String OS::get_system_dir(SystemDir p_dir) const {
-
- return ".";
-}
-
+// Helper function used by OS_Unix and OS_Windows
String OS::get_safe_application_name() const {
String an = ProjectSettings::get_singleton()->get("application/config/name");
Vector<String> invalid_char = String("\\ / : * ? \" < > |").split(" ");
@@ -281,11 +279,51 @@ String OS::get_safe_application_name() const {
return an;
}
-String OS::get_data_dir() const {
+// Path to data, config, cache, etc. OS-specific folders
+
+// Get properly capitalized engine name for system paths
+String OS::get_godot_dir_name() const {
+
+ // Default to lowercase, so only override when different case is needed
+ return String(VERSION_SHORT_NAME).to_lower();
+}
+
+// OS equivalent of XDG_DATA_HOME
+String OS::get_data_path() const {
+
+ return ".";
+}
+
+// OS equivalent of XDG_CONFIG_HOME
+String OS::get_config_path() const {
+
+ return ".";
+}
+
+// OS equivalent of XDG_CACHE_HOME
+String OS::get_cache_path() const {
+
+ return ".";
+}
+
+// OS specific path for user://
+String OS::get_user_data_dir() const {
return ".";
};
+// Absolute path to res://
+String OS::get_resource_dir() const {
+
+ return ProjectSettings::get_singleton()->get_resource_path();
+}
+
+// Access system-specific dirs like Documents, Downloads, etc.
+String OS::get_system_dir(SystemDir p_dir) const {
+
+ return ".";
+}
+
Error OS::shell_open(String p_uri) {
return ERR_UNAVAILABLE;
};
@@ -374,9 +412,9 @@ OS::ScreenOrientation OS::get_screen_orientation() const {
return (OS::ScreenOrientation)_orientation;
}
-void OS::_ensure_data_dir() {
+void OS::_ensure_user_data_dir() {
- String dd = get_data_dir();
+ String dd = get_user_data_dir();
DirAccess *da = DirAccess::open(dd);
if (da) {
memdelete(da);
@@ -516,6 +554,33 @@ bool OS::has_feature(const String &p_feature) {
if (sizeof(void *) == 4 && p_feature == "32") {
return true;
}
+#if defined(__x86_64) || defined(__x86_64__)
+ if (p_feature == "x86_64") {
+ return true;
+ }
+#elif (defined(__i386) || defined(__i386__))
+ if (p_feature == "x86") {
+ return true;
+ }
+#elif defined(__aarch64__)
+ if (p_feature == "arm64") {
+ return true;
+ }
+#elif defined(__arm__)
+#if defined(__ARM_ARCH_7A__)
+ if (p_feature == "armv7a" || p_feature == "armv7") {
+ return true;
+ }
+#endif
+#if defined(__ARM_ARCH_7S__)
+ if (p_feature == "armv7s" || p_feature == "armv7") {
+ return true;
+ }
+#endif
+ if (p_feature == "arm") {
+ return true;
+ }
+#endif
if (_check_internal_feature_support(p_feature))
return true;
@@ -545,7 +610,10 @@ OS::OS() {
_stack_bottom = (void *)(&stack_bottom);
_logger = NULL;
- _set_logger(memnew(StdLogger));
+
+ Vector<Logger *> loggers;
+ loggers.push_back(memnew(StdLogger));
+ _set_logger(memnew(CompositeLogger(loggers)));
}
OS::~OS() {
diff --git a/core/os/os.h b/core/os/os.h
index 6fcfd71332..fe4ffb2922 100644
--- a/core/os/os.h
+++ b/core/os/os.h
@@ -62,10 +62,10 @@ class OS {
void *_stack_bottom;
- Logger *_logger;
+ CompositeLogger *_logger;
protected:
- void _set_logger(Logger *p_logger);
+ void _set_logger(CompositeLogger *p_logger);
public:
typedef void (*ImeCallback)(void *p_inp, String p_text, Point2 p_selection);
@@ -90,13 +90,15 @@ public:
bool fullscreen;
bool resizable;
bool borderless_window;
+ bool maximized;
float get_aspect() const { return (float)width / (float)height; }
- VideoMode(int p_width = 1024, int p_height = 600, bool p_fullscreen = false, bool p_resizable = true, bool p_borderless_window = false) {
+ VideoMode(int p_width = 1024, int p_height = 600, bool p_fullscreen = false, bool p_resizable = true, bool p_borderless_window = false, bool p_maximized = false) {
width = p_width;
height = p_height;
fullscreen = p_fullscreen;
resizable = p_resizable;
borderless_window = p_borderless_window;
+ maximized = p_maximized;
}
};
@@ -109,12 +111,11 @@ protected:
virtual int get_video_driver_count() const = 0;
virtual const char *get_video_driver_name(int p_driver) const = 0;
- virtual VideoMode get_default_video_mode() const = 0;
-
virtual int get_audio_driver_count() const = 0;
virtual const char *get_audio_driver_name(int p_driver) const = 0;
- virtual void initialize_logger();
+ void add_logger(Logger *p_logger);
+
virtual void initialize_core() = 0;
virtual void initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) = 0;
@@ -126,7 +127,7 @@ protected:
virtual void set_cmdline(const char *p_execpath, const List<String> &p_args);
- void _ensure_data_dir();
+ void _ensure_user_data_dir();
virtual bool _check_internal_feature_support(const String &p_feature) = 0;
public:
@@ -202,9 +203,8 @@ public:
virtual void set_low_processor_usage_mode(bool p_enabled);
virtual bool is_in_low_processor_usage_mode() const;
- virtual String get_installed_templates_path() const { return ""; }
virtual String get_executable_path() const;
- virtual Error execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id = NULL, String *r_pipe = NULL, int *r_exitcode = NULL) = 0;
+ virtual Error execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id = NULL, String *r_pipe = NULL, int *r_exitcode = NULL, bool read_stderr = false) = 0;
virtual Error kill(const ProcessID &p_pid) = 0;
virtual int get_process_id() const;
@@ -336,10 +336,14 @@ public:
virtual String get_locale() const;
String get_safe_application_name() const;
- virtual String get_data_dir() const;
- virtual String get_resource_dir() const;
+ virtual String get_godot_dir_name() const;
- virtual Error move_to_trash(const String &p_path) { return FAILED; }
+ virtual String get_data_path() const;
+ virtual String get_config_path() const;
+ virtual String get_cache_path() const;
+
+ virtual String get_user_data_dir() const;
+ virtual String get_resource_dir() const;
enum SystemDir {
SYSTEM_DIR_DESKTOP,
@@ -354,6 +358,8 @@ public:
virtual String get_system_dir(SystemDir p_dir) const;
+ virtual Error move_to_trash(const String &p_path) { return FAILED; }
+
virtual void set_no_window_mode(bool p_enable);
virtual bool is_no_window_mode_enabled() const;
@@ -409,6 +415,7 @@ public:
LATIN_KEYBOARD_QZERTY,
LATIN_KEYBOARD_DVORAK,
LATIN_KEYBOARD_NEO,
+ LATIN_KEYBOARD_COLEMAK,
};
virtual LatinKeyboardVariant get_latin_keyboard_variant() const;
diff --git a/core/packed_data_container.cpp b/core/packed_data_container.cpp
index ad8438e416..3748df12f7 100644
--- a/core/packed_data_container.cpp
+++ b/core/packed_data_container.cpp
@@ -234,7 +234,7 @@ uint32_t PackedDataContainer::_pack(const Variant &p_data, Vector<uint8_t> &tmpd
case Variant::TRANSFORM2D:
case Variant::PLANE:
case Variant::QUAT:
- case Variant::RECT3:
+ case Variant::AABB:
case Variant::BASIS:
case Variant::TRANSFORM:
case Variant::POOL_BYTE_ARRAY:
diff --git a/core/print_string.cpp b/core/print_string.cpp
index 92a04cbf0b..520fb3daec 100644
--- a/core/print_string.cpp
+++ b/core/print_string.cpp
@@ -82,7 +82,25 @@ void print_line(String p_string) {
PrintHandlerList *l = print_handler_list;
while (l) {
- l->printfunc(l->userdata, p_string);
+ l->printfunc(l->userdata, p_string, false);
+ l = l->next;
+ }
+
+ _global_unlock();
+}
+
+void print_error(String p_string) {
+
+ if (!_print_error_enabled)
+ return;
+
+ OS::get_singleton()->printerr("%s\n", p_string.utf8().get_data());
+
+ _global_lock();
+ PrintHandlerList *l = print_handler_list;
+ while (l) {
+
+ l->printfunc(l->userdata, p_string, true);
l = l->next;
}
diff --git a/core/print_string.h b/core/print_string.h
index 9f8420c31a..6b68380b9d 100644
--- a/core/print_string.h
+++ b/core/print_string.h
@@ -34,7 +34,7 @@
extern void (*_print_func)(String);
-typedef void (*PrintHandlerFunc)(void *, const String &p_string);
+typedef void (*PrintHandlerFunc)(void *, const String &p_string, bool p_error);
struct PrintHandlerList {
@@ -56,5 +56,6 @@ void remove_print_handler(PrintHandlerList *p_handler);
extern bool _print_line_enabled;
extern bool _print_error_enabled;
extern void print_line(String p_string);
+extern void print_error(String p_string);
#endif
diff --git a/core/project_settings.cpp b/core/project_settings.cpp
index ff2be87b07..361464ee1f 100644
--- a/core/project_settings.cpp
+++ b/core/project_settings.cpp
@@ -116,7 +116,7 @@ String ProjectSettings::globalize_path(const String &p_path) const {
return p_path.replace("res://", "");
} else if (p_path.begins_with("user://")) {
- String data_dir = OS::get_singleton()->get_data_dir();
+ String data_dir = OS::get_singleton()->get_user_data_dir();
if (data_dir != "") {
return p_path.replace("user:/", data_dir);
@@ -261,7 +261,7 @@ bool ProjectSettings::_load_resource_pack(const String &p_pack) {
return true;
}
-Error ProjectSettings::setup(const String &p_path, const String &p_main_pack) {
+Error ProjectSettings::setup(const String &p_path, const String &p_main_pack, bool p_upwards) {
//If looking for files in network, just use network!
@@ -270,11 +270,6 @@ Error ProjectSettings::setup(const String &p_path, const String &p_main_pack) {
if (_load_settings("res://project.godot") == OK || _load_settings_binary("res://project.binary") == OK) {
_load_settings("res://override.cfg");
-#ifdef DEBUG_ENABLED
- } else {
- // when debug version of godot is used, provide some feedback to the developer
- print_line("Couldn't open project over network");
-#endif
}
return OK;
@@ -292,12 +287,6 @@ Error ProjectSettings::setup(const String &p_path, const String &p_main_pack) {
if (_load_settings("res://project.godot") == OK || _load_settings_binary("res://project.binary") == OK) {
//load override from location of the main pack
_load_settings(p_main_pack.get_base_dir().plus_file("override.cfg"));
-#ifdef DEBUG_ENABLED
- // when debug version of godot is used, provide some feedback to the developer
- print_line("Successfully loaded " + p_main_pack + "/project.godot or project.binary");
- } else {
- print_line("Couldn't load/find " + p_main_pack + "/project.godot or project.binary");
-#endif
}
return OK;
@@ -315,18 +304,9 @@ Error ProjectSettings::setup(const String &p_path, const String &p_main_pack) {
if (_load_resource_pack(datapack_name)) {
found = true;
} else {
-#ifdef DEBUG_ENABLED
- // when debug version of godot is used, provide some feedback to the developer
- print_line("Couldn't open " + datapack_name);
-#endif
datapack_name = filebase_name + ".pck";
if (_load_resource_pack(datapack_name)) {
found = true;
-#ifdef DEBUG_ENABLED
- } else {
- // when debug version of godot is used, provide some feedback to the developer
- print_line("Couldn't open " + datapack_name);
-#endif
}
}
@@ -335,13 +315,6 @@ Error ProjectSettings::setup(const String &p_path, const String &p_main_pack) {
if (_load_settings("res://project.godot") == OK || _load_settings_binary("res://project.binary") == OK) {
// load override from location of executable
_load_settings(exec_path.get_base_dir().plus_file("override.cfg"));
-
-#ifdef DEBUG_ENABLED
- // when debug version of godot is used, provide some feedback to the developer
- print_line("Successfully loaded " + datapack_name + "/project.godot or project.binary");
- } else {
- print_line("Couldn't load/find " + datapack_name + "/project.godot or project.binary");
-#endif
}
return OK;
@@ -362,12 +335,6 @@ Error ProjectSettings::setup(const String &p_path, const String &p_main_pack) {
if (_load_settings("res://project.godot") == OK || _load_settings_binary("res://project.binary") == OK) {
_load_settings("res://override.cfg");
-#ifdef DEBUG_ENABLED
- // when debug version of godot is used, provide some feedback to the developer
- print_line("Successfully loaded " + resource_path + "/project.godot or project.binary");
- } else {
- print_line("Couldn't load/find " + resource_path + "/project.godot or project.binary");
-#endif
}
return OK;
@@ -393,18 +360,16 @@ Error ProjectSettings::setup(const String &p_path, const String &p_main_pack) {
candidate = current_dir;
found = true;
break;
-#ifdef DEBUG_ENABLED
- // when debug version of godot is used, provide some feedback to the developer
- print_line("Successfully loaded " + current_dir + "/project.godot or project.binary");
- } else {
- print_line("Couldn't load/find " + current_dir + "/project.godot or project.binary");
-#endif
}
- d->change_dir("..");
- if (d->get_current_dir() == current_dir)
- break; //not doing anything useful
- current_dir = d->get_current_dir();
+ if (p_upwards) {
+ d->change_dir("..");
+ if (d->get_current_dir() == current_dir)
+ break; //not doing anything useful
+ current_dir = d->get_current_dir();
+ } else {
+ break;
+ }
}
resource_path = candidate;
@@ -667,8 +632,8 @@ Error ProjectSettings::_save_settings_text(const String &p_file, const Map<Strin
file->store_line("; Engine configuration file.");
file->store_line("; It's best edited using the editor UI and not directly,");
file->store_line("; since the parameters that go here are not all obvious.");
- file->store_line("; ");
- file->store_line("; Format: ");
+ file->store_line(";");
+ file->store_line("; Format:");
file->store_line("; [section] ; section goes between []");
file->store_line("; param=value ; assign values to parameters");
file->store_line("");
@@ -811,32 +776,6 @@ Variant _GLOBAL_DEF(const String &p_var, const Variant &p_default) {
return ret;
}
-void ProjectSettings::add_singleton(const Singleton &p_singleton) {
-
- singletons.push_back(p_singleton);
- singleton_ptrs[p_singleton.name] = p_singleton.ptr;
-}
-
-Object *ProjectSettings::get_singleton_object(const String &p_name) const {
-
- const Map<StringName, Object *>::Element *E = singleton_ptrs.find(p_name);
- if (!E)
- return NULL;
- else
- return E->get();
-};
-
-bool ProjectSettings::has_singleton(const String &p_name) const {
-
- return get_singleton_object(p_name) != NULL;
-};
-
-void ProjectSettings::get_singletons(List<Singleton> *p_singletons) {
-
- for (List<Singleton>::Element *E = singletons.front(); E; E = E->next())
- p_singletons->push_back(E->get());
-}
-
Vector<String> ProjectSettings::get_optimizer_presets() const {
List<PropertyInfo> pi;
@@ -928,8 +867,6 @@ void ProjectSettings::_bind_methods() {
ClassDB::bind_method(D_METHOD("localize_path", "path"), &ProjectSettings::localize_path);
ClassDB::bind_method(D_METHOD("globalize_path", "path"), &ProjectSettings::globalize_path);
ClassDB::bind_method(D_METHOD("save"), &ProjectSettings::save);
- ClassDB::bind_method(D_METHOD("has_singleton", "name"), &ProjectSettings::has_singleton);
- ClassDB::bind_method(D_METHOD("get_singleton", "name"), &ProjectSettings::get_singleton_object);
ClassDB::bind_method(D_METHOD("load_resource_pack", "pack"), &ProjectSettings::_load_resource_pack);
ClassDB::bind_method(D_METHOD("property_can_revert", "name"), &ProjectSettings::property_can_revert);
ClassDB::bind_method(D_METHOD("property_get_revert", "name"), &ProjectSettings::property_get_revert);
@@ -1071,10 +1008,16 @@ ProjectSettings::ProjectSettings() {
GLOBAL_DEF("debug/settings/profiler/max_functions", 16384);
//assigning here, because using GLOBAL_GET on every block for compressing can be slow
+ Compression::zstd_long_distance_matching = GLOBAL_DEF("compression/formats/zstd/long_distance_matching", false);
+ custom_prop_info["compression/formats/zstd/long_distance_matching"] = PropertyInfo(Variant::BOOL, "compression/formats/zstd/long_distance_matching");
Compression::zstd_level = GLOBAL_DEF("compression/formats/zstd/compression_level", 3);
custom_prop_info["compression/formats/zstd/compression_level"] = PropertyInfo(Variant::INT, "compression/formats/zstd/compression_level", PROPERTY_HINT_RANGE, "1,22,1");
+ Compression::zstd_window_log_size = GLOBAL_DEF("compression/formats/zstd/window_log_size", 27);
+ custom_prop_info["compression/formats/zstd/window_log_size"] = PropertyInfo(Variant::INT, "compression/formats/zstd/window_log_size", PROPERTY_HINT_RANGE, "10,30,1");
+
Compression::zlib_level = GLOBAL_DEF("compression/formats/zlib/compression_level", Z_DEFAULT_COMPRESSION);
custom_prop_info["compression/formats/zlib/compression_level"] = PropertyInfo(Variant::INT, "compression/formats/zlib/compression_level", PROPERTY_HINT_RANGE, "-1,9,1");
+
Compression::gzip_level = GLOBAL_DEF("compression/formats/gzip/compression_level", Z_DEFAULT_COMPRESSION);
custom_prop_info["compression/formats/gzip/compression_level"] = PropertyInfo(Variant::INT, "compression/formats/gzip/compression_level", PROPERTY_HINT_RANGE, "-1,9,1");
diff --git a/core/project_settings.h b/core/project_settings.h
index ea6034dc84..1c4078cebb 100644
--- a/core/project_settings.h
+++ b/core/project_settings.h
@@ -45,14 +45,6 @@ class ProjectSettings : public Object {
public:
typedef Map<String, Variant> CustomMap;
- struct Singleton {
- StringName name;
- Object *ptr;
- Singleton(const StringName &p_name = StringName(), Object *p_ptr = NULL)
- : name(p_name),
- ptr(p_ptr) {
- }
- };
enum {
//properties that are not for built in values begin from this value, so builtin ones are displayed first
NO_BUILTIN_ORDER_BASE = 1 << 16
@@ -106,9 +98,6 @@ protected:
Error _save_settings_text(const String &p_file, const Map<String, List<String> > &props, const CustomMap &p_custom = CustomMap(), const String &p_custom_features = String());
Error _save_settings_binary(const String &p_file, const Map<String, List<String> > &props, const CustomMap &p_custom = CustomMap(), const String &p_custom_features = String());
- List<Singleton> singletons;
- Map<StringName, Object *> singleton_ptrs;
-
Error _save_custom_bnd(const String &p_file);
bool _load_resource_pack(const String &p_pack);
@@ -139,23 +128,17 @@ public:
void set_order(const String &p_name, int p_order);
void set_builtin_order(const String &p_name);
- Error setup(const String &p_path, const String &p_main_pack);
+ Error setup(const String &p_path, const String &p_main_pack, bool p_upwards = false);
Error save_custom(const String &p_path = "", const CustomMap &p_custom = CustomMap(), const Vector<String> &p_custom_features = Vector<String>(), bool p_merge_with_current = true);
Error save();
void set_custom_property_info(const String &p_prop, const PropertyInfo &p_info);
- void add_singleton(const Singleton &p_singleton);
- void get_singletons(List<Singleton> *p_singletons);
-
- bool has_singleton(const String &p_name) const;
-
Vector<String> get_optimizer_presets() const;
List<String> get_input_presets() const { return input_presets; }
void set_disable_feature_overrides(bool p_disable);
- Object *get_singleton_object(const String &p_name) const;
void register_global_defaults();
diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp
index 0e34a3eea5..baaf738b42 100644
--- a/core/register_core_types.cpp
+++ b/core/register_core_types.cpp
@@ -34,12 +34,14 @@
#include "compressed_translation.h"
#include "core/io/xml_parser.h"
#include "core_string_names.h"
+#include "engine.h"
#include "func_ref.h"
#include "geometry.h"
#include "input_map.h"
#include "io/config_file.h"
#include "io/http_client.h"
#include "io/marshalls.h"
+#include "io/networked_multiplayer_peer.h"
#include "io/packet_peer.h"
#include "io/packet_peer_udp.h"
#include "io/pck_packer.h"
@@ -109,6 +111,8 @@ void register_core_types() {
ClassDB::register_class<Object>();
+ ClassDB::register_virtual_class<Script>();
+
ClassDB::register_class<Reference>();
ClassDB::register_class<WeakRef>();
ClassDB::register_class<Resource>();
@@ -136,6 +140,7 @@ void register_core_types() {
ClassDB::register_virtual_class<IP>();
ClassDB::register_virtual_class<PacketPeer>();
ClassDB::register_class<PacketPeerStream>();
+ ClassDB::register_virtual_class<NetworkedMultiplayerPeer>();
ClassDB::register_class<MainLoop>();
//ClassDB::register_type<OptimizedSaver>();
ClassDB::register_class<Translation>();
@@ -185,19 +190,33 @@ void register_core_settings() {
void register_core_singletons() {
- ProjectSettings::get_singleton()->add_singleton(ProjectSettings::Singleton("ProjectSettings", ProjectSettings::get_singleton()));
- ProjectSettings::get_singleton()->add_singleton(ProjectSettings::Singleton("IP", IP::get_singleton()));
- ProjectSettings::get_singleton()->add_singleton(ProjectSettings::Singleton("Geometry", _Geometry::get_singleton()));
- ProjectSettings::get_singleton()->add_singleton(ProjectSettings::Singleton("ResourceLoader", _ResourceLoader::get_singleton()));
- ProjectSettings::get_singleton()->add_singleton(ProjectSettings::Singleton("ResourceSaver", _ResourceSaver::get_singleton()));
- ProjectSettings::get_singleton()->add_singleton(ProjectSettings::Singleton("OS", _OS::get_singleton()));
- ProjectSettings::get_singleton()->add_singleton(ProjectSettings::Singleton("Engine", _Engine::get_singleton()));
- ProjectSettings::get_singleton()->add_singleton(ProjectSettings::Singleton("ClassDB", _classdb));
- ProjectSettings::get_singleton()->add_singleton(ProjectSettings::Singleton("Marshalls", _Marshalls::get_singleton()));
- ProjectSettings::get_singleton()->add_singleton(ProjectSettings::Singleton("TranslationServer", TranslationServer::get_singleton()));
- ProjectSettings::get_singleton()->add_singleton(ProjectSettings::Singleton("Input", Input::get_singleton()));
- ProjectSettings::get_singleton()->add_singleton(ProjectSettings::Singleton("InputMap", InputMap::get_singleton()));
- ProjectSettings::get_singleton()->add_singleton(ProjectSettings::Singleton("JSON", _JSON::get_singleton()));
+ ClassDB::register_class<ProjectSettings>();
+ ClassDB::register_virtual_class<IP>();
+ ClassDB::register_class<_Geometry>();
+ ClassDB::register_class<_ResourceLoader>();
+ ClassDB::register_class<_ResourceSaver>();
+ ClassDB::register_class<_OS>();
+ ClassDB::register_class<_Engine>();
+ ClassDB::register_class<_ClassDB>();
+ ClassDB::register_class<_Marshalls>();
+ ClassDB::register_class<TranslationServer>();
+ ClassDB::register_virtual_class<Input>();
+ ClassDB::register_class<InputMap>();
+ ClassDB::register_class<_JSON>();
+
+ Engine::get_singleton()->add_singleton(Engine::Singleton("ProjectSettings", ProjectSettings::get_singleton()));
+ Engine::get_singleton()->add_singleton(Engine::Singleton("IP", IP::get_singleton()));
+ Engine::get_singleton()->add_singleton(Engine::Singleton("Geometry", _Geometry::get_singleton()));
+ Engine::get_singleton()->add_singleton(Engine::Singleton("ResourceLoader", _ResourceLoader::get_singleton()));
+ Engine::get_singleton()->add_singleton(Engine::Singleton("ResourceSaver", _ResourceSaver::get_singleton()));
+ Engine::get_singleton()->add_singleton(Engine::Singleton("OS", _OS::get_singleton()));
+ Engine::get_singleton()->add_singleton(Engine::Singleton("Engine", _Engine::get_singleton()));
+ Engine::get_singleton()->add_singleton(Engine::Singleton("ClassDB", _classdb));
+ Engine::get_singleton()->add_singleton(Engine::Singleton("Marshalls", _Marshalls::get_singleton()));
+ Engine::get_singleton()->add_singleton(Engine::Singleton("TranslationServer", TranslationServer::get_singleton()));
+ Engine::get_singleton()->add_singleton(Engine::Singleton("Input", Input::get_singleton()));
+ Engine::get_singleton()->add_singleton(Engine::Singleton("InputMap", InputMap::get_singleton()));
+ Engine::get_singleton()->add_singleton(Engine::Singleton("JSON", _JSON::get_singleton()));
}
void unregister_core_types() {
diff --git a/core/script_debugger_remote.cpp b/core/script_debugger_remote.cpp
index 4653ade294..5e06339b9e 100644
--- a/core/script_debugger_remote.cpp
+++ b/core/script_debugger_remote.cpp
@@ -29,11 +29,14 @@
/*************************************************************************/
#include "script_debugger_remote.h"
+#include "engine.h"
#include "io/ip.h"
#include "io/marshalls.h"
#include "os/input.h"
#include "os/os.h"
#include "project_settings.h"
+#include "scene/main/node.h"
+
void ScriptDebuggerRemote::_send_video_memory() {
List<ResourceUsage> usage;
@@ -200,20 +203,39 @@ void ScriptDebuggerRemote::debug(ScriptLanguage *p_script, bool p_can_continue)
List<String> members;
List<Variant> member_vals;
-
+ if (ScriptInstance *inst = p_script->debug_get_stack_level_instance(lv)) {
+ members.push_back("self");
+ member_vals.push_back(inst->get_owner());
+ }
p_script->debug_get_stack_level_members(lv, &members, &member_vals);
-
ERR_CONTINUE(members.size() != member_vals.size());
List<String> locals;
List<Variant> local_vals;
-
p_script->debug_get_stack_level_locals(lv, &locals, &local_vals);
-
ERR_CONTINUE(locals.size() != local_vals.size());
+ List<String> globals;
+ List<Variant> globals_vals;
+ p_script->debug_get_globals(&globals, &globals_vals);
+ ERR_CONTINUE(globals.size() != globals_vals.size());
+
packet_peer_stream->put_var("stack_frame_vars");
- packet_peer_stream->put_var(2 + locals.size() * 2 + members.size() * 2);
+ packet_peer_stream->put_var(3 + (locals.size() + members.size() + globals.size()) * 2);
+
+ { //locals
+ packet_peer_stream->put_var(locals.size());
+
+ List<String>::Element *E = locals.front();
+ List<Variant>::Element *F = local_vals.front();
+
+ while (E) {
+ _put_variable(E->get(), F->get());
+
+ E = E->next();
+ F = F->next();
+ }
+ }
{ //members
packet_peer_stream->put_var(members.size());
@@ -230,11 +252,11 @@ void ScriptDebuggerRemote::debug(ScriptLanguage *p_script, bool p_can_continue)
}
}
- { //locals
- packet_peer_stream->put_var(locals.size());
+ { //globals
+ packet_peer_stream->put_var(globals.size());
- List<String>::Element *E = locals.front();
- List<Variant>::Element *F = local_vals.front();
+ List<String>::Element *E = globals.front();
+ List<Variant>::Element *F = globals_vals.front();
while (E) {
_put_variable(E->get(), F->get());
@@ -531,56 +553,88 @@ void ScriptDebuggerRemote::_send_object_id(ObjectID p_id) {
if (!obj)
return;
- List<PropertyInfo> pinfo;
- obj->get_property_list(&pinfo, true);
+ typedef Pair<PropertyInfo, Variant> PropertyDesc;
+ List<PropertyDesc> properties;
- int props_to_send = 0;
- for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) {
+ if (ScriptInstance *si = obj->get_script_instance()) {
+ if (!si->get_script().is_null()) {
- if (E->get().usage & (PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CATEGORY)) {
- props_to_send++;
- }
- }
+ Set<StringName> members;
+ si->get_script()->get_members(&members);
+ for (Set<StringName>::Element *E = members.front(); E; E = E->next()) {
- packet_peer_stream->put_var("message:inspect_object");
- packet_peer_stream->put_var(props_to_send * 5 + 4);
- packet_peer_stream->put_var(p_id);
- packet_peer_stream->put_var(obj->get_class());
- if (obj->is_class("Resource") || obj->is_class("Node"))
- packet_peer_stream->put_var(obj->call("get_path"));
- else
- packet_peer_stream->put_var("");
+ Variant m;
+ if (si->get(E->get(), m)) {
+ PropertyInfo pi(m.get_type(), String("Members/") + E->get());
+ properties.push_back(PropertyDesc(pi, m));
+ }
+ }
- packet_peer_stream->put_var(props_to_send);
+ Map<StringName, Variant> constants;
+ si->get_script()->get_constants(&constants);
+ for (Map<StringName, Variant>::Element *E = constants.front(); E; E = E->next()) {
+ PropertyInfo pi(E->value().get_type(), (String("Constants/") + E->key()));
+ properties.push_back(PropertyDesc(pi, E->value()));
+ }
+ }
+ }
+ if (Node *node = Object::cast_to<Node>(obj)) {
+ PropertyInfo pi(Variant::NODE_PATH, String("Node/path"));
+ properties.push_front(PropertyDesc(pi, node->get_path()));
+ } else if (Resource *res = Object::cast_to<Resource>(obj)) {
+ if (Script *s = Object::cast_to<Script>(res)) {
+ Map<StringName, Variant> constants;
+ s->get_constants(&constants);
+ for (Map<StringName, Variant>::Element *E = constants.front(); E; E = E->next()) {
+ PropertyInfo pi(E->value().get_type(), String("Constants/") + E->key());
+ properties.push_front(PropertyDesc(pi, E->value()));
+ }
+ }
+ }
+ List<PropertyInfo> pinfo;
+ obj->get_property_list(&pinfo, true);
for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) {
-
if (E->get().usage & (PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CATEGORY)) {
+ properties.push_back(PropertyDesc(E->get(), obj->get(E->get().name)));
+ }
+ }
- if (E->get().usage & PROPERTY_USAGE_CATEGORY) {
- packet_peer_stream->put_var("*" + E->get().name);
- } else {
- packet_peer_stream->put_var(E->get().name);
- }
-
- Variant var = obj->get(E->get().name);
- packet_peer_stream->put_var(E->get().type);
- //only send information that can be sent..
-
- int len = 0; //test how big is this to encode
- encode_variant(var, NULL, len);
-
- if (len > packet_peer_stream->get_output_buffer_max_size()) { //limit to max size
- packet_peer_stream->put_var(PROPERTY_HINT_OBJECT_TOO_BIG);
- packet_peer_stream->put_var("");
- packet_peer_stream->put_var(Variant());
- } else {
- packet_peer_stream->put_var(E->get().hint);
- packet_peer_stream->put_var(E->get().hint_string);
- packet_peer_stream->put_var(var);
- }
+ Array send_props;
+ for (int i = 0; i < properties.size(); i++) {
+ const PropertyInfo &pi = properties[i].first;
+ const Variant &var = properties[i].second;
+ RES res = var;
+
+ Array prop;
+ prop.push_back(pi.name);
+ prop.push_back(pi.type);
+
+ //only send information that can be sent..
+ int len = 0; //test how big is this to encode
+ encode_variant(var, NULL, len);
+ if (len > packet_peer_stream->get_output_buffer_max_size()) { //limit to max size
+ prop.push_back(PROPERTY_HINT_OBJECT_TOO_BIG);
+ prop.push_back("");
+ prop.push_back(pi.usage);
+ prop.push_back(Variant());
+ } else {
+ prop.push_back(pi.hint);
+ if (res.is_null())
+ prop.push_back(pi.hint_string);
+ else
+ prop.push_back(String("RES:") + res->get_path());
+ prop.push_back(pi.usage);
+ prop.push_back(var);
}
+ send_props.push_back(prop);
}
+
+ packet_peer_stream->put_var("message:inspect_object");
+ packet_peer_stream->put_var(3);
+ packet_peer_stream->put_var(p_id);
+ packet_peer_stream->put_var(obj->get_class());
+ packet_peer_stream->put_var(send_props);
}
void ScriptDebuggerRemote::_set_object_property(ObjectID p_id, const String &p_property, const Variant &p_value) {
@@ -589,7 +643,11 @@ void ScriptDebuggerRemote::_set_object_property(ObjectID p_id, const String &p_p
if (!obj)
return;
- obj->set(p_property, p_value);
+ String prop_name = p_property;
+ if (p_property.begins_with("Members/"))
+ prop_name = p_property.substr(8, p_property.length());
+
+ obj->set(prop_name, p_value);
}
void ScriptDebuggerRemote::_poll_events() {
@@ -831,7 +889,7 @@ void ScriptDebuggerRemote::send_message(const String &p_message, const Array &p_
mutex->unlock();
}
-void ScriptDebuggerRemote::_print_handler(void *p_this, const String &p_string) {
+void ScriptDebuggerRemote::_print_handler(void *p_this, const String &p_string, bool p_error) {
ScriptDebuggerRemote *sdr = (ScriptDebuggerRemote *)p_this;
@@ -855,15 +913,19 @@ void ScriptDebuggerRemote::_print_handler(void *p_this, const String &p_string)
}
sdr->char_count += allowed_chars;
-
- if (sdr->char_count >= sdr->max_cps) {
- s += "\n[output overflow, print less text!]\n";
- }
+ bool overflowed = sdr->char_count >= sdr->max_cps;
sdr->mutex->lock();
if (!sdr->locking && sdr->tcp_client->is_connected_to_host()) {
+ if (overflowed)
+ s += "[...]";
+
sdr->output_strings.push_back(s);
+
+ if (overflowed) {
+ sdr->output_strings.push_back("[output overflow, print less text!]");
+ }
}
sdr->mutex->unlock();
}
@@ -935,7 +997,7 @@ ScriptDebuggerRemote::ScriptDebuggerRemote()
tcp_client(StreamPeerTCP::create_ref()),
packet_peer_stream(Ref<PacketPeerStream>(memnew(PacketPeerStream))),
last_perf_time(0),
- performance(ProjectSettings::get_singleton()->get_singleton_object("Performance")),
+ performance(Engine::get_singleton()->get_singleton_object("Performance")),
requested_quit(false),
mutex(Mutex::create()),
max_cps(GLOBAL_GET("network/limits/debugger_stdout/max_chars_per_second")),
diff --git a/core/script_debugger_remote.h b/core/script_debugger_remote.h
index 22137d1350..90d2daf1f8 100644
--- a/core/script_debugger_remote.h
+++ b/core/script_debugger_remote.h
@@ -94,7 +94,7 @@ class ScriptDebuggerRemote : public ScriptDebugger {
uint64_t msec_count;
bool locking; //hack to avoid a deadloop
- static void _print_handler(void *p_this, const String &p_string);
+ static void _print_handler(void *p_this, const String &p_string, bool p_error);
PrintHandlerList phl;
diff --git a/core/script_language.cpp b/core/script_language.cpp
index 5ead91f26e..384e41e4bd 100644
--- a/core/script_language.cpp
+++ b/core/script_language.cpp
@@ -58,7 +58,6 @@ void Script::_bind_methods() {
ClassDB::bind_method(D_METHOD("has_script_signal", "signal_name"), &Script::has_script_signal);
ClassDB::bind_method(D_METHOD("is_tool"), &Script::is_tool);
- ClassDB::bind_method(D_METHOD("get_node_type"), &Script::get_node_type);
}
void ScriptServer::set_scripting_enabled(bool p_enabled) {
diff --git a/core/script_language.h b/core/script_language.h
index 25767a2f7a..3d01381f3b 100644
--- a/core/script_language.h
+++ b/core/script_language.h
@@ -107,8 +107,6 @@ public:
virtual bool is_tool() const = 0;
- virtual String get_node_type() const = 0;
-
virtual ScriptLanguage *get_language() const = 0;
virtual bool has_script_signal(const StringName &p_signal) const = 0;
@@ -122,6 +120,9 @@ public:
virtual int get_member_line(const StringName &p_member) const { return -1; }
+ virtual void get_constants(Map<StringName, Variant> *p_constants) {}
+ virtual void get_members(Set<StringName> *p_constants) {}
+
Script() {}
};
@@ -132,6 +133,7 @@ public:
virtual void get_property_list(List<PropertyInfo> *p_properties) const = 0;
virtual Variant::Type get_property_type(const StringName &p_name, bool *r_is_valid = NULL) const = 0;
+ virtual Object *get_owner() { return NULL; }
virtual void get_property_state(List<Pair<StringName, Variant> > &state);
virtual void get_method_list(List<MethodInfo> *p_list) const = 0;
@@ -202,6 +204,7 @@ public:
virtual bool validate(const String &p_script, int &r_line_error, int &r_col_error, String &r_test_error, const String &p_path = "", List<String> *r_functions = NULL) const = 0;
virtual Script *create_script() const = 0;
virtual bool has_named_classes() const = 0;
+ virtual bool supports_builtin_mode() const = 0;
virtual bool can_inherit_from_file() { return false; }
virtual int find_function(const String &p_function, const String &p_code) const = 0;
virtual String make_function(const String &p_class, const String &p_name, const PoolStringArray &p_args) const = 0;
@@ -245,7 +248,8 @@ public:
virtual String debug_get_stack_level_source(int p_level) const = 0;
virtual void debug_get_stack_level_locals(int p_level, List<String> *p_locals, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1) = 0;
virtual void debug_get_stack_level_members(int p_level, List<String> *p_members, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1) = 0;
- virtual void debug_get_globals(List<String> *p_locals, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1) = 0;
+ virtual ScriptInstance *debug_get_stack_level_instance(int p_level) { return NULL; }
+ virtual void debug_get_globals(List<String> *p_globals, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1) = 0;
virtual String debug_parse_stack_level_expression(int p_level, const String &p_expression, int p_max_subitems = -1, int p_max_depth = -1) = 0;
struct StackInfo {
diff --git a/core/set.h b/core/set.h
index 0f48e07520..331979d4e3 100644
--- a/core/set.h
+++ b/core/set.h
@@ -424,7 +424,6 @@ private:
Element *rp = ((p_node->left == _data._nil) || (p_node->right == _data._nil)) ? p_node : p_node->_next;
Element *node = (rp->left == _data._nil) ? rp->right : rp->left;
- node->parent = rp->parent;
Element *sibling;
if (rp == rp->parent->left) {
diff --git a/core/string_db.h b/core/string_db.h
index 2bef29fab8..de91e2abd8 100644
--- a/core/string_db.h
+++ b/core/string_db.h
@@ -113,6 +113,9 @@ public:
else
return 0;
}
+ _FORCE_INLINE_ const void *data_unique_pointer() const {
+ return (void *)_data;
+ }
bool operator!=(const StringName &p_name) const;
_FORCE_INLINE_ operator String() const {
diff --git a/core/translation.cpp b/core/translation.cpp
index 27e3b202d0..7e4d4feb89 100644
--- a/core/translation.cpp
+++ b/core/translation.cpp
@@ -753,65 +753,17 @@ static const char *locale_names[] = {
0
};
-bool TranslationServer::is_locale_valid(const String &p_locale) {
-
- const char **ptr = locale_list;
-
- while (*ptr) {
-
- if (*ptr == p_locale)
- return true;
- ptr++;
- }
-
- return false;
-}
-
-Vector<String> TranslationServer::get_all_locales() {
-
- Vector<String> locales;
-
- const char **ptr = locale_list;
-
- while (*ptr) {
- locales.push_back(*ptr);
- ptr++;
- }
-
- return locales;
-}
-
-Vector<String> TranslationServer::get_all_locale_names() {
-
- Vector<String> locales;
-
- const char **ptr = locale_names;
-
- while (*ptr) {
- locales.push_back(*ptr);
- ptr++;
- }
-
- return locales;
-}
+static const char *locale_renames[][2] = {
+ { "no", "nb" },
+ { NULL, NULL }
+};
static String get_trimmed_locale(const String &p_locale) {
return p_locale.substr(0, 2);
}
-static bool is_valid_locale(const String &p_locale) {
-
- const char **ptr = locale_list;
-
- while (*ptr) {
- if (p_locale == *ptr)
- return true;
- ptr++;
- }
-
- return false;
-}
+///////////////////////////////////////////////
PoolVector<String> Translation::_get_messages() const {
@@ -857,14 +809,13 @@ void Translation::_set_messages(const PoolVector<String> &p_messages) {
void Translation::set_locale(const String &p_locale) {
- // replaces '-' with '_' for macOS Sierra-style locales
- String univ_locale = p_locale.replace("-", "_");
+ String univ_locale = TranslationServer::standardize_locale(p_locale);
- if (!is_valid_locale(univ_locale)) {
+ if (!TranslationServer::is_locale_valid(univ_locale)) {
String trimmed_locale = get_trimmed_locale(univ_locale);
- ERR_EXPLAIN("Invalid Locale: " + trimmed_locale);
- ERR_FAIL_COND(!is_valid_locale(trimmed_locale));
+ ERR_EXPLAIN("Invalid locale: " + trimmed_locale);
+ ERR_FAIL_COND(!TranslationServer::is_locale_valid(trimmed_locale));
locale = trimmed_locale;
} else {
@@ -929,16 +880,47 @@ Translation::Translation()
///////////////////////////////////////////////
-void TranslationServer::set_locale(const String &p_locale) {
+bool TranslationServer::is_locale_valid(const String &p_locale) {
- // replaces '-' with '_' for macOS Sierra-style locales
+ const char **ptr = locale_list;
+
+ while (*ptr) {
+
+ if (*ptr == p_locale)
+ return true;
+ ptr++;
+ }
+
+ return false;
+}
+
+String TranslationServer::standardize_locale(const String &p_locale) {
+
+ // Replaces '-' with '_' for macOS Sierra-style locales
String univ_locale = p_locale.replace("-", "_");
- if (!is_valid_locale(univ_locale)) {
+ // Handles known non-ISO locale names used e.g. on Windows
+ int idx = 0;
+ while (locale_renames[idx][0] != NULL) {
+ if (locale_renames[idx][0] == univ_locale) {
+ univ_locale = locale_renames[idx][1];
+ break;
+ }
+ idx++;
+ }
+
+ return univ_locale;
+}
+
+void TranslationServer::set_locale(const String &p_locale) {
+
+ String univ_locale = standardize_locale(p_locale);
+
+ if (!is_locale_valid(univ_locale)) {
String trimmed_locale = get_trimmed_locale(univ_locale);
- ERR_EXPLAIN("Invalid Locale: " + trimmed_locale);
- ERR_FAIL_COND(!is_valid_locale(trimmed_locale));
+ ERR_EXPLAIN("Invalid locale: " + trimmed_locale);
+ ERR_FAIL_COND(!is_locale_valid(trimmed_locale));
locale = trimmed_locale;
} else {
@@ -957,6 +939,40 @@ String TranslationServer::get_locale() const {
return locale;
}
+String TranslationServer::get_locale_name(const String &p_locale) const {
+
+ if (!locale_name_map.has(p_locale)) return String();
+ return locale_name_map[p_locale];
+}
+
+Vector<String> TranslationServer::get_all_locales() {
+
+ Vector<String> locales;
+
+ const char **ptr = locale_list;
+
+ while (*ptr) {
+ locales.push_back(*ptr);
+ ptr++;
+ }
+
+ return locales;
+}
+
+Vector<String> TranslationServer::get_all_locale_names() {
+
+ Vector<String> locales;
+
+ const char **ptr = locale_names;
+
+ while (*ptr) {
+ locales.push_back(String::utf8(*ptr));
+ ptr++;
+ }
+
+ return locales;
+}
+
void TranslationServer::add_translation(const Ref<Translation> &p_translation) {
translations.insert(p_translation);
@@ -1122,6 +1138,8 @@ void TranslationServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_locale", "locale"), &TranslationServer::set_locale);
ClassDB::bind_method(D_METHOD("get_locale"), &TranslationServer::get_locale);
+ ClassDB::bind_method(D_METHOD("get_locale_name", "locale"), &TranslationServer::get_locale_name);
+
ClassDB::bind_method(D_METHOD("translate", "message"), &TranslationServer::translate);
ClassDB::bind_method(D_METHOD("add_translation", "translation"), &TranslationServer::add_translation);
@@ -1147,4 +1165,9 @@ TranslationServer::TranslationServer()
: locale("en"),
enabled(true) {
singleton = this;
+
+ for (int i = 0; locale_list[i]; ++i) {
+
+ locale_name_map.insert(locale_list[i], String::utf8(locale_names[i]));
+ }
}
diff --git a/core/translation.h b/core/translation.h
index cf59583ad6..0cdab3b0bc 100644
--- a/core/translation.h
+++ b/core/translation.h
@@ -73,6 +73,8 @@ class TranslationServer : public Object {
Set<Ref<Translation> > translations;
Ref<Translation> tool_translation;
+ Map<String, String> locale_name_map;
+
bool enabled;
static TranslationServer *singleton;
@@ -83,14 +85,14 @@ class TranslationServer : public Object {
public:
_FORCE_INLINE_ static TranslationServer *get_singleton() { return singleton; }
- //yes, portuguese is supported!
-
void set_enabled(bool p_enabled) { enabled = p_enabled; }
_FORCE_INLINE_ bool is_enabled() const { return enabled; }
void set_locale(const String &p_locale);
String get_locale() const;
+ String get_locale_name(const String &p_locale) const;
+
void add_translation(const Ref<Translation> &p_translation);
void remove_translation(const Ref<Translation> &p_translation);
@@ -99,6 +101,7 @@ public:
static Vector<String> get_all_locales();
static Vector<String> get_all_locale_names();
static bool is_locale_valid(const String &p_locale);
+ static String standardize_locale(const String &p_locale);
void set_tool_translation(const Ref<Translation> &p_translation);
StringName tool_translate(const StringName &p_message) const;
diff --git a/core/type_info.h b/core/type_info.h
index 9fb80af0eb..24d96c51e8 100644
--- a/core/type_info.h
+++ b/core/type_info.h
@@ -82,7 +82,7 @@ MAKE_TYPE_INFO(Vector3, Variant::VECTOR3)
MAKE_TYPE_INFO(Transform2D, Variant::TRANSFORM2D)
MAKE_TYPE_INFO(Plane, Variant::PLANE)
MAKE_TYPE_INFO(Quat, Variant::QUAT)
-MAKE_TYPE_INFO(Rect3, Variant::RECT3)
+MAKE_TYPE_INFO(AABB, Variant::AABB)
MAKE_TYPE_INFO(Basis, Variant::BASIS)
MAKE_TYPE_INFO(Transform, Variant::TRANSFORM)
MAKE_TYPE_INFO(Color, Variant::COLOR)
diff --git a/core/typedefs.h b/core/typedefs.h
index bf5c8b0f75..c509edf9fe 100644
--- a/core/typedefs.h
+++ b/core/typedefs.h
@@ -98,11 +98,11 @@ T *_nullptr() {
#undef OK
#endif
+#include "int_types.h"
+
#include "error_list.h"
#include "error_macros.h"
-#include "int_types.h"
-
/** Generic ABS function, for math uses please use Math::abs */
#ifndef ABS
diff --git a/core/ustring.cpp b/core/ustring.cpp
index b85996e3d1..8d40f56386 100644
--- a/core/ustring.cpp
+++ b/core/ustring.cpp
@@ -564,7 +564,7 @@ void String::erase(int p_pos, int p_chars) {
String String::capitalize() const {
- String aux = this->replace("_", " ").to_lower();
+ String aux = this->camelcase_to_underscore(true).replace("_", " ").strip_edges();
String cap;
for (int i = 0; i < aux.get_slice_count(" "); i++) {
@@ -862,6 +862,17 @@ Vector<int> String::split_ints_mk(const Vector<String> &p_splitters, bool p_allo
return ret;
}
+String String::join(Vector<String> parts) {
+ String ret;
+ for (int i = 0; i < parts.size(); ++i) {
+ if (i > 0) {
+ ret += *this;
+ }
+ ret += parts[i];
+ }
+ return ret;
+}
+
CharType String::char_uppercase(CharType p_char) {
return _find_upper(p_char);
@@ -2476,6 +2487,11 @@ bool String::begins_with(const char *p_string) const {
return *p_string == 0;
}
+bool String::is_enclosed_in(const String &p_string) const {
+
+ return begins_with(p_string) && ends_with(p_string);
+}
+
bool String::is_subsequence_of(const String &p_string) const {
return _base_is_subsequence_of(p_string, false);
@@ -2486,6 +2502,11 @@ bool String::is_subsequence_ofi(const String &p_string) const {
return _base_is_subsequence_of(p_string, true);
}
+bool String::is_quoted() const {
+
+ return is_enclosed_in("\"") || is_enclosed_in("'");
+}
+
bool String::_base_is_subsequence_of(const String &p_string, bool case_insensitive) const {
int len = length();
@@ -2747,6 +2768,48 @@ CharType String::ord_at(int p_idx) const {
return operator[](p_idx);
}
+String String::dedent() const {
+
+ String new_string;
+ String indent;
+ bool has_indent = false;
+ bool has_text = false;
+ int line_start = 0;
+ int indent_stop = -1;
+
+ for (int i = 0; i < length(); i++) {
+
+ CharType c = operator[](i);
+ if (c == '\n') {
+ if (has_text)
+ new_string += substr(indent_stop, i - indent_stop);
+ new_string += "\n";
+ has_text = false;
+ line_start = i + 1;
+ indent_stop = -1;
+ } else if (!has_text) {
+ if (c > 32) {
+ has_text = true;
+ if (!has_indent) {
+ has_indent = true;
+ indent = substr(line_start, i - line_start);
+ indent_stop = i;
+ }
+ }
+ if (has_indent && indent_stop < 0) {
+ int j = i - line_start;
+ if (j >= indent.length() || c != indent[j])
+ indent_stop = i;
+ }
+ }
+ }
+
+ if (has_text)
+ new_string += substr(indent_stop, length() - indent_stop);
+
+ return new_string;
+}
+
String String::strip_edges(bool left, bool right) const {
int len = length();
@@ -3906,6 +3969,18 @@ String String::sprintf(const Array &values, bool *error) const {
return formatted;
}
+String String::quote(String quotechar) const {
+ return quotechar + *this + quotechar;
+}
+
+String String::unquote() const {
+ if (!is_quoted()) {
+ return *this;
+ }
+
+ return substr(1, length() - 2);
+}
+
#include "translation.h"
#ifdef TOOLS_ENABLED
diff --git a/core/ustring.h b/core/ustring.h
index ab4e325f2c..9c24133b55 100644
--- a/core/ustring.h
+++ b/core/ustring.h
@@ -118,8 +118,10 @@ public:
bool begins_with(const String &p_string) const;
bool begins_with(const char *p_string) const;
bool ends_with(const String &p_string) const;
+ bool is_enclosed_in(const String &p_string) const;
bool is_subsequence_of(const String &p_string) const;
bool is_subsequence_ofi(const String &p_string) const;
+ bool is_quoted() const;
Vector<String> bigrams() const;
float similarity(const String &p_string) const;
String format(const Variant &values, String placeholder = "{_}") const;
@@ -132,6 +134,8 @@ public:
String lpad(int min_length, const String &character = " ") const;
String rpad(int min_length, const String &character = " ") const;
String sprintf(const Array &values, bool *error) const;
+ String quote(String quotechar = "\"") const;
+ String unquote() const;
static String num(double p_num, int p_decimals = -1);
static String num_scientific(double p_num);
static String num_real(double p_num);
@@ -165,6 +169,8 @@ public:
Vector<int> split_ints(const String &p_splitter, bool p_allow_empty = true) const;
Vector<int> split_ints_mk(const Vector<String> &p_splitters, bool p_allow_empty = true) const;
+ String join(Vector<String> parts);
+
static CharType char_uppercase(CharType p_char);
static CharType char_lowercase(CharType p_char);
String to_upper() const;
@@ -172,6 +178,7 @@ public:
String left(int p_pos) const;
String right(int p_pos) const;
+ String dedent() const;
String strip_edges(bool left = true, bool right = true) const;
String strip_escapes() const;
String get_extension() const;
diff --git a/core/variant.cpp b/core/variant.cpp
index f70e4a5218..d4143b8d84 100644
--- a/core/variant.cpp
+++ b/core/variant.cpp
@@ -66,7 +66,7 @@ String Variant::get_type_name(Variant::Type p_type) {
return "String";
} break;
- // math types
+ // math types
case VECTOR2: {
@@ -94,9 +94,9 @@ String Variant::get_type_name(Variant::Type p_type) {
} break;*/
- case RECT3: {
+ case AABB: {
- return "Rect3";
+ return "AABB";
} break;
case QUAT: {
@@ -267,6 +267,7 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) {
static const Type valid[] = {
QUAT,
+ VECTOR3,
NIL
};
@@ -722,7 +723,7 @@ bool Variant::is_zero() const {
} break;
- // math types
+ // math types
case VECTOR2: {
@@ -754,9 +755,9 @@ bool Variant::is_zero() const {
} break;*/
- case RECT3: {
+ case AABB: {
- return *_data._rect3 == Rect3();
+ return *_data._aabb == ::AABB();
} break;
case QUAT: {
@@ -931,7 +932,7 @@ void Variant::reference(const Variant &p_variant) {
memnew_placement(_data._mem, String(*reinterpret_cast<const String *>(p_variant._data._mem)));
} break;
- // math types
+ // math types
case VECTOR2: {
@@ -954,9 +955,9 @@ void Variant::reference(const Variant &p_variant) {
memnew_placement(_data._mem, Plane(*reinterpret_cast<const Plane *>(p_variant._data._mem)));
} break;
- case RECT3: {
+ case AABB: {
- _data._rect3 = memnew(Rect3(*p_variant._data._rect3));
+ _data._aabb = memnew(::AABB(*p_variant._data._aabb));
} break;
case QUAT: {
@@ -1079,9 +1080,9 @@ void Variant::clear() {
memdelete(_data._transform2d);
} break;
- case RECT3: {
+ case AABB: {
- memdelete(_data._rect3);
+ memdelete(_data._aabb);
} break;
case BASIS: {
@@ -1426,7 +1427,7 @@ Variant::operator String() const {
case PLANE:
return operator Plane();
//case QUAT:
- case RECT3: return operator Rect3();
+ case AABB: return operator ::AABB();
case QUAT: return "(" + operator Quat() + ")";
case BASIS: {
@@ -1617,12 +1618,12 @@ Variant::operator Plane() const {
else
return Plane();
}
-Variant::operator Rect3() const {
+Variant::operator ::AABB() const {
- if (type == RECT3)
- return *_data._rect3;
+ if (type == AABB)
+ return *_data._aabb;
else
- return Rect3();
+ return ::AABB();
}
Variant::operator Basis() const {
@@ -2188,10 +2189,10 @@ Variant::Variant(const Plane &p_plane) {
type = PLANE;
memnew_placement(_data._mem, Plane(p_plane));
}
-Variant::Variant(const Rect3 &p_aabb) {
+Variant::Variant(const ::AABB &p_aabb) {
- type = RECT3;
- _data._rect3 = memnew(Rect3(p_aabb));
+ type = AABB;
+ _data._aabb = memnew(::AABB(p_aabb));
}
Variant::Variant(const Basis &p_matrix) {
@@ -2501,7 +2502,7 @@ void Variant::operator=(const Variant &p_variant) {
*reinterpret_cast<String *>(_data._mem) = *reinterpret_cast<const String *>(p_variant._data._mem);
} break;
- // math types
+ // math types
case VECTOR2: {
@@ -2524,9 +2525,9 @@ void Variant::operator=(const Variant &p_variant) {
*reinterpret_cast<Plane *>(_data._mem) = *reinterpret_cast<const Plane *>(p_variant._data._mem);
} break;
- case RECT3: {
+ case AABB: {
- *_data._rect3 = *(p_variant._data._rect3);
+ *_data._aabb = *(p_variant._data._aabb);
} break;
case QUAT: {
@@ -2641,7 +2642,7 @@ uint32_t Variant::hash() const {
return reinterpret_cast<const String *>(_data._mem)->hash();
} break;
- // math types
+ // math types
case VECTOR2: {
@@ -2686,13 +2687,13 @@ uint32_t Variant::hash() const {
} break;*/
- case RECT3: {
+ case AABB: {
uint32_t hash = 5831;
for (int i = 0; i < 3; i++) {
- hash = hash_djb2_one_float(_data._rect3->position[i], hash);
- hash = hash_djb2_one_float(_data._rect3->size[i], hash);
+ hash = hash_djb2_one_float(_data._aabb->position[i], hash);
+ hash = hash_djb2_one_float(_data._aabb->size[i], hash);
}
return hash;
@@ -2952,9 +2953,9 @@ bool Variant::hash_compare(const Variant &p_variant) const {
(hash_compare_scalar(l->d, r->d));
} break;
- case RECT3: {
- const Rect3 *l = _data._rect3;
- const Rect3 *r = p_variant._data._rect3;
+ case AABB: {
+ const ::AABB *l = _data._aabb;
+ const ::AABB *r = p_variant._data._aabb;
return (hash_compare_vector3(l->position, r->position) &&
(hash_compare_vector3(l->size, r->size)));
diff --git a/core/variant.h b/core/variant.h
index e0d0bf05c8..8ba4d576cf 100644
--- a/core/variant.h
+++ b/core/variant.h
@@ -34,6 +34,7 @@
@author Juan Linietsky <reduzio@gmail.com>
*/
+#include "aabb.h"
#include "array.h"
#include "color.h"
#include "dictionary.h"
@@ -45,7 +46,6 @@
#include "node_path.h"
#include "plane.h"
#include "quat.h"
-#include "rect3.h"
#include "ref_ptr.h"
#include "rid.h"
#include "transform.h"
@@ -89,7 +89,7 @@ public:
TRANSFORM2D,
PLANE,
QUAT, // 10
- RECT3,
+ AABB,
BASIS,
TRANSFORM,
@@ -99,15 +99,15 @@ public:
_RID,
OBJECT,
DICTIONARY,
- ARRAY, // 20
+ ARRAY,
// arrays
- POOL_BYTE_ARRAY,
+ POOL_BYTE_ARRAY, // 20
POOL_INT_ARRAY,
POOL_REAL_ARRAY,
POOL_STRING_ARRAY,
- POOL_VECTOR2_ARRAY, // 25
- POOL_VECTOR3_ARRAY,
+ POOL_VECTOR2_ARRAY,
+ POOL_VECTOR3_ARRAY, // 25
POOL_COLOR_ARRAY,
VARIANT_MAX
@@ -136,7 +136,7 @@ private:
int64_t _int;
double _real;
Transform2D *_transform2d;
- Rect3 *_rect3;
+ ::AABB *_aabb;
Basis *_basis;
Transform *_transform;
RefPtr *_resource;
@@ -184,7 +184,7 @@ public:
operator Rect2() const;
operator Vector3() const;
operator Plane() const;
- operator Rect3() const;
+ operator ::AABB() const;
operator Quat() const;
operator Basis() const;
operator Transform() const;
@@ -253,7 +253,7 @@ public:
Variant(const Rect2 &p_rect2);
Variant(const Vector3 &p_vector3);
Variant(const Plane &p_plane);
- Variant(const Rect3 &p_aabb);
+ Variant(const ::AABB &p_aabb);
Variant(const Quat &p_quat);
Variant(const Basis &p_transform);
Variant(const Transform2D &p_transform);
diff --git a/core/variant_call.cpp b/core/variant_call.cpp
index d141621fbb..da6e602ccb 100644
--- a/core/variant_call.cpp
+++ b/core/variant_call.cpp
@@ -54,9 +54,8 @@ struct _VariantCall {
Variant::Type return_type;
bool _const;
-#ifdef DEBUG_ENABLED
bool returns;
-#endif
+
VariantFunc func;
_FORCE_INLINE_ bool verify_arguments(const Variant **p_args, Variant::CallError &r_error) {
@@ -146,7 +145,7 @@ struct _VariantCall {
#endif
}
- static void addfunc(bool p_const, Variant::Type p_type, Variant::Type p_return, const StringName &p_name, VariantFunc p_func, const Vector<Variant> &p_defaultarg, const Arg &p_argtype1 = Arg(), const Arg &p_argtype2 = Arg(), const Arg &p_argtype3 = Arg(), const Arg &p_argtype4 = Arg(), const Arg &p_argtype5 = Arg()) {
+ static void addfunc(bool p_const, Variant::Type p_type, Variant::Type p_return, bool p_has_return, const StringName &p_name, VariantFunc p_func, const Vector<Variant> &p_defaultarg, const Arg &p_argtype1 = Arg(), const Arg &p_argtype2 = Arg(), const Arg &p_argtype3 = Arg(), const Arg &p_argtype4 = Arg(), const Arg &p_argtype5 = Arg()) {
FuncData funcdata;
funcdata.func = p_func;
@@ -154,7 +153,7 @@ struct _VariantCall {
funcdata._const = p_const;
#ifdef DEBUG_ENABLED
funcdata.return_type = p_return;
- funcdata.returns = p_return != Variant::NIL;
+ funcdata.returns = p_has_return;
#endif
if (p_argtype1.name) {
@@ -261,6 +260,7 @@ struct _VariantCall {
VCALL_LOCALMEM0R(String, to_lower);
VCALL_LOCALMEM1R(String, left);
VCALL_LOCALMEM1R(String, right);
+ VCALL_LOCALMEM0R(String, dedent);
VCALL_LOCALMEM2R(String, strip_edges);
VCALL_LOCALMEM0R(String, get_extension);
VCALL_LOCALMEM0R(String, get_basename);
@@ -483,6 +483,8 @@ struct _VariantCall {
VCALL_LOCALMEM1(Array, erase);
VCALL_LOCALMEM0(Array, sort);
VCALL_LOCALMEM2(Array, sort_custom);
+ VCALL_LOCALMEM2R(Array, bsearch);
+ VCALL_LOCALMEM4R(Array, bsearch_custom);
VCALL_LOCALMEM0R(Array, duplicate);
VCALL_LOCALMEM0(Array, invert);
@@ -655,26 +657,26 @@ struct _VariantCall {
#define VCALL_PTR5R(m_type, m_method) \
static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { r_ret = reinterpret_cast<m_type *>(p_self._data._ptr)->m_method(*p_args[0], *p_args[1], *p_args[2], *p_args[3], *p_args[4]); }
- VCALL_PTR0R(Rect3, get_area);
- VCALL_PTR0R(Rect3, has_no_area);
- VCALL_PTR0R(Rect3, has_no_surface);
- VCALL_PTR1R(Rect3, intersects);
- VCALL_PTR1R(Rect3, encloses);
- VCALL_PTR1R(Rect3, merge);
- VCALL_PTR1R(Rect3, intersection);
- VCALL_PTR1R(Rect3, intersects_plane);
- VCALL_PTR2R(Rect3, intersects_segment);
- VCALL_PTR1R(Rect3, has_point);
- VCALL_PTR1R(Rect3, get_support);
- VCALL_PTR0R(Rect3, get_longest_axis);
- VCALL_PTR0R(Rect3, get_longest_axis_index);
- VCALL_PTR0R(Rect3, get_longest_axis_size);
- VCALL_PTR0R(Rect3, get_shortest_axis);
- VCALL_PTR0R(Rect3, get_shortest_axis_index);
- VCALL_PTR0R(Rect3, get_shortest_axis_size);
- VCALL_PTR1R(Rect3, expand);
- VCALL_PTR1R(Rect3, grow);
- VCALL_PTR1R(Rect3, get_endpoint);
+ VCALL_PTR0R(AABB, get_area);
+ VCALL_PTR0R(AABB, has_no_area);
+ VCALL_PTR0R(AABB, has_no_surface);
+ VCALL_PTR1R(AABB, intersects);
+ VCALL_PTR1R(AABB, encloses);
+ VCALL_PTR1R(AABB, merge);
+ VCALL_PTR1R(AABB, intersection);
+ VCALL_PTR1R(AABB, intersects_plane);
+ VCALL_PTR2R(AABB, intersects_segment);
+ VCALL_PTR1R(AABB, has_point);
+ VCALL_PTR1R(AABB, get_support);
+ VCALL_PTR0R(AABB, get_longest_axis);
+ VCALL_PTR0R(AABB, get_longest_axis_index);
+ VCALL_PTR0R(AABB, get_longest_axis_size);
+ VCALL_PTR0R(AABB, get_shortest_axis);
+ VCALL_PTR0R(AABB, get_shortest_axis_index);
+ VCALL_PTR0R(AABB, get_shortest_axis_size);
+ VCALL_PTR1R(AABB, expand);
+ VCALL_PTR1R(AABB, grow);
+ VCALL_PTR1R(AABB, get_endpoint);
VCALL_PTR0R(Transform2D, inverse);
VCALL_PTR0R(Transform2D, affine_inverse);
@@ -755,7 +757,7 @@ struct _VariantCall {
case Variant::VECTOR3: r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform(p_args[0]->operator Vector3()); return;
case Variant::PLANE: r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform(p_args[0]->operator Plane()); return;
- case Variant::RECT3: r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform(p_args[0]->operator Rect3()); return;
+ case Variant::AABB: r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform(p_args[0]->operator ::AABB()); return;
default: r_ret = Variant();
}
}
@@ -766,7 +768,7 @@ struct _VariantCall {
case Variant::VECTOR3: r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform_inv(p_args[0]->operator Vector3()); return;
case Variant::PLANE: r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform_inv(p_args[0]->operator Plane()); return;
- case Variant::RECT3: r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform_inv(p_args[0]->operator Rect3()); return;
+ case Variant::AABB: r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform_inv(p_args[0]->operator ::AABB()); return;
default: r_ret = Variant();
}
}
@@ -878,9 +880,9 @@ struct _VariantCall {
r_ret = Color::hex(*p_args[0]);
}
- static void Rect3_init1(Variant &r_ret, const Variant **p_args) {
+ static void AABB_init1(Variant &r_ret, const Variant **p_args) {
- r_ret = Rect3(*p_args[0], *p_args[1]);
+ r_ret = ::AABB(*p_args[0], *p_args[1]);
}
static void Basis_init1(Variant &r_ret, const Variant **p_args) {
@@ -1051,7 +1053,6 @@ Variant Variant::construct(const Variant::Type p_type, const Variant **p_args, i
return String();
// math types
-
case VECTOR2:
return Vector2(); // 5
case RECT2: return Rect2();
@@ -1059,8 +1060,8 @@ Variant Variant::construct(const Variant::Type p_type, const Variant **p_args, i
case TRANSFORM2D: return Transform2D();
case PLANE: return Plane();
case QUAT: return Quat();
- case RECT3:
- return Rect3(); // 10
+ case AABB:
+ return ::AABB(); // 10
case BASIS: return Basis();
case TRANSFORM:
return Transform();
@@ -1139,8 +1140,8 @@ Variant Variant::construct(const Variant::Type p_type, const Variant **p_args, i
case VECTOR3: return (Vector3(*p_args[0]));
case PLANE: return (Plane(*p_args[0]));
case QUAT: return (Quat(*p_args[0]));
- case RECT3:
- return (Rect3(*p_args[0])); // 10
+ case AABB:
+ return (::AABB(*p_args[0])); // 10
case BASIS: return (Basis(p_args[0]->operator Basis()));
case TRANSFORM:
return (Transform(p_args[0]->operator Transform()));
@@ -1234,7 +1235,7 @@ Variant::Type Variant::get_method_return_type(Variant::Type p_type, const String
return Variant::NIL;
if (r_has_return)
- *r_has_return = E->get().return_type;
+ *r_has_return = E->get().returns;
return E->get().return_type;
}
@@ -1376,215 +1377,238 @@ void register_variant_methods() {
_VariantCall::construct_funcs = memnew_arr(_VariantCall::ConstructFunc, Variant::VARIANT_MAX);
_VariantCall::constant_data = memnew_arr(_VariantCall::ConstantData, Variant::VARIANT_MAX);
+#define ADDFUNC0R(m_vtype, m_ret, m_class, m_method, m_defarg) \
+ _VariantCall::addfunc(true, Variant::m_vtype, Variant::m_ret, true, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg);
+#define ADDFUNC1R(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_defarg) \
+ _VariantCall::addfunc(true, Variant::m_vtype, Variant::m_ret, true, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)));
+#define ADDFUNC2R(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_arg2, m_argname2, m_defarg) \
+ _VariantCall::addfunc(true, Variant::m_vtype, Variant::m_ret, true, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2)));
+#define ADDFUNC3R(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_arg2, m_argname2, m_arg3, m_argname3, m_defarg) \
+ _VariantCall::addfunc(true, Variant::m_vtype, Variant::m_ret, true, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2)), _VariantCall::Arg(Variant::m_arg3, _scs_create(m_argname3)));
+#define ADDFUNC4R(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_arg2, m_argname2, m_arg3, m_argname3, m_arg4, m_argname4, m_defarg) \
+ _VariantCall::addfunc(true, Variant::m_vtype, Variant::m_ret, true, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2)), _VariantCall::Arg(Variant::m_arg3, _scs_create(m_argname3)), _VariantCall::Arg(Variant::m_arg4, _scs_create(m_argname4)));
+
+#define ADDFUNC0RNC(m_vtype, m_ret, m_class, m_method, m_defarg) \
+ _VariantCall::addfunc(false, Variant::m_vtype, Variant::m_ret, true, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg);
+#define ADDFUNC1RNC(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_defarg) \
+ _VariantCall::addfunc(false, Variant::m_vtype, Variant::m_ret, true, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)));
+#define ADDFUNC2RNC(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_arg2, m_argname2, m_defarg) \
+ _VariantCall::addfunc(false, Variant::m_vtype, Variant::m_ret, true, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2)));
+#define ADDFUNC3RNC(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_arg2, m_argname2, m_arg3, m_argname3, m_defarg) \
+ _VariantCall::addfunc(false, Variant::m_vtype, Variant::m_ret, true, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2)), _VariantCall::Arg(Variant::m_arg3, _scs_create(m_argname3)));
+#define ADDFUNC4RNC(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_arg2, m_argname2, m_arg3, m_argname3, m_arg4, m_argname4, m_defarg) \
+ _VariantCall::addfunc(false, Variant::m_vtype, Variant::m_ret, true, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2)), _VariantCall::Arg(Variant::m_arg3, _scs_create(m_argname3)), _VariantCall::Arg(Variant::m_arg4, _scs_create(m_argname4)));
+
#define ADDFUNC0(m_vtype, m_ret, m_class, m_method, m_defarg) \
- _VariantCall::addfunc(true, Variant::m_vtype, Variant::m_ret, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg);
+ _VariantCall::addfunc(true, Variant::m_vtype, Variant::m_ret, false, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg);
#define ADDFUNC1(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_defarg) \
- _VariantCall::addfunc(true, Variant::m_vtype, Variant::m_ret, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)));
+ _VariantCall::addfunc(true, Variant::m_vtype, Variant::m_ret, false, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)));
#define ADDFUNC2(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_arg2, m_argname2, m_defarg) \
- _VariantCall::addfunc(true, Variant::m_vtype, Variant::m_ret, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2)));
+ _VariantCall::addfunc(true, Variant::m_vtype, Variant::m_ret, false, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2)));
#define ADDFUNC3(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_arg2, m_argname2, m_arg3, m_argname3, m_defarg) \
- _VariantCall::addfunc(true, Variant::m_vtype, Variant::m_ret, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2)), _VariantCall::Arg(Variant::m_arg3, _scs_create(m_argname3)));
+ _VariantCall::addfunc(true, Variant::m_vtype, Variant::m_ret, false, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2)), _VariantCall::Arg(Variant::m_arg3, _scs_create(m_argname3)));
#define ADDFUNC4(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_arg2, m_argname2, m_arg3, m_argname3, m_arg4, m_argname4, m_defarg) \
- _VariantCall::addfunc(true, Variant::m_vtype, Variant::m_ret, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2)), _VariantCall::Arg(Variant::m_arg3, _scs_create(m_argname3)), _VariantCall::Arg(Variant::m_arg4, _scs_create(m_argname4)));
+ _VariantCall::addfunc(true, Variant::m_vtype, Variant::m_ret, false, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2)), _VariantCall::Arg(Variant::m_arg3, _scs_create(m_argname3)), _VariantCall::Arg(Variant::m_arg4, _scs_create(m_argname4)));
#define ADDFUNC0NC(m_vtype, m_ret, m_class, m_method, m_defarg) \
- _VariantCall::addfunc(false, Variant::m_vtype, Variant::m_ret, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg);
+ _VariantCall::addfunc(false, Variant::m_vtype, Variant::m_ret, false, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg);
#define ADDFUNC1NC(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_defarg) \
- _VariantCall::addfunc(false, Variant::m_vtype, Variant::m_ret, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)));
+ _VariantCall::addfunc(false, Variant::m_vtype, Variant::m_ret, false, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)));
#define ADDFUNC2NC(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_arg2, m_argname2, m_defarg) \
- _VariantCall::addfunc(false, Variant::m_vtype, Variant::m_ret, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2)));
+ _VariantCall::addfunc(false, Variant::m_vtype, Variant::m_ret, false, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2)));
#define ADDFUNC3NC(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_arg2, m_argname2, m_arg3, m_argname3, m_defarg) \
- _VariantCall::addfunc(false, Variant::m_vtype, Variant::m_ret, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2)), _VariantCall::Arg(Variant::m_arg3, _scs_create(m_argname3)));
+ _VariantCall::addfunc(false, Variant::m_vtype, Variant::m_ret, false, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2)), _VariantCall::Arg(Variant::m_arg3, _scs_create(m_argname3)));
#define ADDFUNC4NC(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_arg2, m_argname2, m_arg3, m_argname3, m_arg4, m_argname4, m_defarg) \
- _VariantCall::addfunc(false, Variant::m_vtype, Variant::m_ret, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2)), _VariantCall::Arg(Variant::m_arg3, _scs_create(m_argname3)), _VariantCall::Arg(Variant::m_arg4, _scs_create(m_argname4)));
+ _VariantCall::addfunc(false, Variant::m_vtype, Variant::m_ret, false, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2)), _VariantCall::Arg(Variant::m_arg3, _scs_create(m_argname3)), _VariantCall::Arg(Variant::m_arg4, _scs_create(m_argname4)));
/* STRING */
- ADDFUNC1(STRING, INT, String, casecmp_to, STRING, "to", varray());
- ADDFUNC1(STRING, INT, String, nocasecmp_to, STRING, "to", varray());
- ADDFUNC0(STRING, INT, String, length, varray());
- ADDFUNC2(STRING, STRING, String, substr, INT, "from", INT, "len", varray());
-
- ADDFUNC2(STRING, INT, String, find, STRING, "what", INT, "from", varray(0));
-
- ADDFUNC1(STRING, INT, String, find_last, STRING, "what", varray());
- ADDFUNC2(STRING, INT, String, findn, STRING, "what", INT, "from", varray(0));
- ADDFUNC2(STRING, INT, String, rfind, STRING, "what", INT, "from", varray(-1));
- ADDFUNC2(STRING, INT, String, rfindn, STRING, "what", INT, "from", varray(-1));
- ADDFUNC1(STRING, BOOL, String, match, STRING, "expr", varray());
- ADDFUNC1(STRING, BOOL, String, matchn, STRING, "expr", varray());
- ADDFUNC1(STRING, BOOL, String, begins_with, STRING, "text", varray());
- ADDFUNC1(STRING, BOOL, String, ends_with, STRING, "text", varray());
- ADDFUNC1(STRING, BOOL, String, is_subsequence_of, STRING, "text", varray());
- ADDFUNC1(STRING, BOOL, String, is_subsequence_ofi, STRING, "text", varray());
- ADDFUNC0(STRING, POOL_STRING_ARRAY, String, bigrams, varray());
- ADDFUNC1(STRING, REAL, String, similarity, STRING, "text", varray());
-
- ADDFUNC2(STRING, STRING, String, format, NIL, "values", STRING, "placeholder", varray("{_}"));
- ADDFUNC2(STRING, STRING, String, replace, STRING, "what", STRING, "forwhat", varray());
- ADDFUNC2(STRING, STRING, String, replacen, STRING, "what", STRING, "forwhat", varray());
- ADDFUNC2(STRING, STRING, String, insert, INT, "position", STRING, "what", varray());
- ADDFUNC0(STRING, STRING, String, capitalize, varray());
- ADDFUNC2(STRING, POOL_STRING_ARRAY, String, split, STRING, "divisor", BOOL, "allow_empty", varray(true));
- ADDFUNC2(STRING, POOL_REAL_ARRAY, String, split_floats, STRING, "divisor", BOOL, "allow_empty", varray(true));
-
- ADDFUNC0(STRING, STRING, String, to_upper, varray());
- ADDFUNC0(STRING, STRING, String, to_lower, varray());
-
- ADDFUNC1(STRING, STRING, String, left, INT, "position", varray());
- ADDFUNC1(STRING, STRING, String, right, INT, "position", varray());
- ADDFUNC2(STRING, STRING, String, strip_edges, BOOL, "left", BOOL, "right", varray(true, true));
- ADDFUNC0(STRING, STRING, String, get_extension, varray());
- ADDFUNC0(STRING, STRING, String, get_basename, varray());
- ADDFUNC1(STRING, STRING, String, plus_file, STRING, "file", varray());
- ADDFUNC1(STRING, INT, String, ord_at, INT, "at", varray());
+ ADDFUNC1R(STRING, INT, String, casecmp_to, STRING, "to", varray());
+ ADDFUNC1R(STRING, INT, String, nocasecmp_to, STRING, "to", varray());
+ ADDFUNC0R(STRING, INT, String, length, varray());
+ ADDFUNC2R(STRING, STRING, String, substr, INT, "from", INT, "len", varray());
+
+ ADDFUNC2R(STRING, INT, String, find, STRING, "what", INT, "from", varray(0));
+
+ ADDFUNC1R(STRING, INT, String, find_last, STRING, "what", varray());
+ ADDFUNC2R(STRING, INT, String, findn, STRING, "what", INT, "from", varray(0));
+ ADDFUNC2R(STRING, INT, String, rfind, STRING, "what", INT, "from", varray(-1));
+ ADDFUNC2R(STRING, INT, String, rfindn, STRING, "what", INT, "from", varray(-1));
+ ADDFUNC1R(STRING, BOOL, String, match, STRING, "expr", varray());
+ ADDFUNC1R(STRING, BOOL, String, matchn, STRING, "expr", varray());
+ ADDFUNC1R(STRING, BOOL, String, begins_with, STRING, "text", varray());
+ ADDFUNC1R(STRING, BOOL, String, ends_with, STRING, "text", varray());
+ ADDFUNC1R(STRING, BOOL, String, is_subsequence_of, STRING, "text", varray());
+ ADDFUNC1R(STRING, BOOL, String, is_subsequence_ofi, STRING, "text", varray());
+ ADDFUNC0R(STRING, POOL_STRING_ARRAY, String, bigrams, varray());
+ ADDFUNC1R(STRING, REAL, String, similarity, STRING, "text", varray());
+
+ ADDFUNC2R(STRING, STRING, String, format, NIL, "values", STRING, "placeholder", varray("{_}"));
+ ADDFUNC2R(STRING, STRING, String, replace, STRING, "what", STRING, "forwhat", varray());
+ ADDFUNC2R(STRING, STRING, String, replacen, STRING, "what", STRING, "forwhat", varray());
+ ADDFUNC2R(STRING, STRING, String, insert, INT, "position", STRING, "what", varray());
+ ADDFUNC0R(STRING, STRING, String, capitalize, varray());
+ ADDFUNC2R(STRING, POOL_STRING_ARRAY, String, split, STRING, "divisor", BOOL, "allow_empty", varray(true));
+ ADDFUNC2R(STRING, POOL_REAL_ARRAY, String, split_floats, STRING, "divisor", BOOL, "allow_empty", varray(true));
+
+ ADDFUNC0R(STRING, STRING, String, to_upper, varray());
+ ADDFUNC0R(STRING, STRING, String, to_lower, varray());
+
+ ADDFUNC1R(STRING, STRING, String, left, INT, "position", varray());
+ ADDFUNC1R(STRING, STRING, String, right, INT, "position", varray());
+ ADDFUNC2R(STRING, STRING, String, strip_edges, BOOL, "left", BOOL, "right", varray(true, true));
+ ADDFUNC0R(STRING, STRING, String, get_extension, varray());
+ ADDFUNC0R(STRING, STRING, String, get_basename, varray());
+ ADDFUNC1R(STRING, STRING, String, plus_file, STRING, "file", varray());
+ ADDFUNC1R(STRING, INT, String, ord_at, INT, "at", varray());
+ ADDFUNC0R(STRING, STRING, String, dedent, varray());
ADDFUNC2(STRING, NIL, String, erase, INT, "position", INT, "chars", varray());
- ADDFUNC0(STRING, INT, String, hash, varray());
- ADDFUNC0(STRING, STRING, String, md5_text, varray());
- ADDFUNC0(STRING, STRING, String, sha256_text, varray());
- ADDFUNC0(STRING, POOL_BYTE_ARRAY, String, md5_buffer, varray());
- ADDFUNC0(STRING, POOL_BYTE_ARRAY, String, sha256_buffer, varray());
- ADDFUNC0(STRING, BOOL, String, empty, varray());
- ADDFUNC0(STRING, BOOL, String, is_abs_path, varray());
- ADDFUNC0(STRING, BOOL, String, is_rel_path, varray());
- ADDFUNC0(STRING, STRING, String, get_base_dir, varray());
- ADDFUNC0(STRING, STRING, String, get_file, varray());
- ADDFUNC0(STRING, STRING, String, xml_escape, varray());
- ADDFUNC0(STRING, STRING, String, xml_unescape, varray());
- ADDFUNC0(STRING, STRING, String, c_escape, varray());
- ADDFUNC0(STRING, STRING, String, c_unescape, varray());
- ADDFUNC0(STRING, STRING, String, json_escape, varray());
- ADDFUNC0(STRING, STRING, String, percent_encode, varray());
- ADDFUNC0(STRING, STRING, String, percent_decode, varray());
- ADDFUNC0(STRING, BOOL, String, is_valid_identifier, varray());
- ADDFUNC0(STRING, BOOL, String, is_valid_integer, varray());
- ADDFUNC0(STRING, BOOL, String, is_valid_float, varray());
- ADDFUNC0(STRING, BOOL, String, is_valid_html_color, varray());
- ADDFUNC0(STRING, BOOL, String, is_valid_ip_address, varray());
- ADDFUNC0(STRING, INT, String, to_int, varray());
- ADDFUNC0(STRING, REAL, String, to_float, varray());
- ADDFUNC0(STRING, INT, String, hex_to_int, varray());
- ADDFUNC1(STRING, STRING, String, pad_decimals, INT, "digits", varray());
- ADDFUNC1(STRING, STRING, String, pad_zeros, INT, "digits", varray());
-
- ADDFUNC0(STRING, POOL_BYTE_ARRAY, String, to_ascii, varray());
- ADDFUNC0(STRING, POOL_BYTE_ARRAY, String, to_utf8, varray());
-
- ADDFUNC0(VECTOR2, VECTOR2, Vector2, normalized, varray());
- ADDFUNC0(VECTOR2, REAL, Vector2, length, varray());
- ADDFUNC0(VECTOR2, REAL, Vector2, angle, varray());
- ADDFUNC0(VECTOR2, REAL, Vector2, length_squared, varray());
- ADDFUNC0(VECTOR2, BOOL, Vector2, is_normalized, varray());
- ADDFUNC1(VECTOR2, REAL, Vector2, distance_to, VECTOR2, "to", varray());
- ADDFUNC1(VECTOR2, REAL, Vector2, distance_squared_to, VECTOR2, "to", varray());
- ADDFUNC1(VECTOR2, REAL, Vector2, angle_to, VECTOR2, "to", varray());
- ADDFUNC1(VECTOR2, REAL, Vector2, angle_to_point, VECTOR2, "to", varray());
- ADDFUNC2(VECTOR2, VECTOR2, Vector2, linear_interpolate, VECTOR2, "b", REAL, "t", varray());
- ADDFUNC4(VECTOR2, VECTOR2, Vector2, cubic_interpolate, VECTOR2, "b", VECTOR2, "pre_a", VECTOR2, "post_b", REAL, "t", varray());
- ADDFUNC1(VECTOR2, VECTOR2, Vector2, rotated, REAL, "phi", varray());
- ADDFUNC0(VECTOR2, VECTOR2, Vector2, tangent, varray());
- ADDFUNC0(VECTOR2, VECTOR2, Vector2, floor, varray());
- ADDFUNC1(VECTOR2, VECTOR2, Vector2, snapped, VECTOR2, "by", varray());
- ADDFUNC0(VECTOR2, REAL, Vector2, aspect, varray());
- ADDFUNC1(VECTOR2, REAL, Vector2, dot, VECTOR2, "with", varray());
- ADDFUNC1(VECTOR2, VECTOR2, Vector2, slide, VECTOR2, "n", varray());
- ADDFUNC1(VECTOR2, VECTOR2, Vector2, bounce, VECTOR2, "n", varray());
- ADDFUNC1(VECTOR2, VECTOR2, Vector2, reflect, VECTOR2, "n", varray());
- //ADDFUNC1(VECTOR2,REAL,Vector2,cross,VECTOR2,"with",varray());
- ADDFUNC0(VECTOR2, VECTOR2, Vector2, abs, varray());
- ADDFUNC1(VECTOR2, VECTOR2, Vector2, clamped, REAL, "length", varray());
-
- ADDFUNC0(RECT2, REAL, Rect2, get_area, varray());
- ADDFUNC1(RECT2, BOOL, Rect2, intersects, RECT2, "b", varray());
- ADDFUNC1(RECT2, BOOL, Rect2, encloses, RECT2, "b", varray());
- ADDFUNC0(RECT2, BOOL, Rect2, has_no_area, varray());
- ADDFUNC1(RECT2, RECT2, Rect2, clip, RECT2, "b", varray());
- ADDFUNC1(RECT2, RECT2, Rect2, merge, RECT2, "b", varray());
- ADDFUNC1(RECT2, BOOL, Rect2, has_point, VECTOR2, "point", varray());
- ADDFUNC1(RECT2, RECT2, Rect2, grow, REAL, "by", varray());
- ADDFUNC2(RECT2, RECT2, Rect2, grow_margin, INT, "margin", REAL, "by", varray());
- ADDFUNC4(RECT2, RECT2, Rect2, grow_individual, REAL, "left", REAL, "top", REAL, "right", REAL, " bottom", varray());
- ADDFUNC1(RECT2, RECT2, Rect2, expand, VECTOR2, "to", varray());
-
- ADDFUNC0(VECTOR3, INT, Vector3, min_axis, varray());
- ADDFUNC0(VECTOR3, INT, Vector3, max_axis, varray());
- ADDFUNC0(VECTOR3, REAL, Vector3, length, varray());
- ADDFUNC0(VECTOR3, REAL, Vector3, length_squared, varray());
- ADDFUNC0(VECTOR3, BOOL, Vector3, is_normalized, varray());
- ADDFUNC0(VECTOR3, VECTOR3, Vector3, normalized, varray());
- ADDFUNC0(VECTOR3, VECTOR3, Vector3, inverse, varray());
- ADDFUNC1(VECTOR3, VECTOR3, Vector3, snapped, REAL, "by", varray());
- ADDFUNC2(VECTOR3, VECTOR3, Vector3, rotated, VECTOR3, "axis", REAL, "phi", varray());
- ADDFUNC2(VECTOR3, VECTOR3, Vector3, linear_interpolate, VECTOR3, "b", REAL, "t", varray());
- ADDFUNC4(VECTOR3, VECTOR3, Vector3, cubic_interpolate, VECTOR3, "b", VECTOR3, "pre_a", VECTOR3, "post_b", REAL, "t", varray());
- ADDFUNC1(VECTOR3, REAL, Vector3, dot, VECTOR3, "b", varray());
- ADDFUNC1(VECTOR3, VECTOR3, Vector3, cross, VECTOR3, "b", varray());
- ADDFUNC1(VECTOR3, BASIS, Vector3, outer, VECTOR3, "b", varray());
- ADDFUNC0(VECTOR3, BASIS, Vector3, to_diagonal_matrix, varray());
- ADDFUNC0(VECTOR3, VECTOR3, Vector3, abs, varray());
- ADDFUNC0(VECTOR3, VECTOR3, Vector3, floor, varray());
- ADDFUNC0(VECTOR3, VECTOR3, Vector3, ceil, varray());
- ADDFUNC1(VECTOR3, REAL, Vector3, distance_to, VECTOR3, "b", varray());
- ADDFUNC1(VECTOR3, REAL, Vector3, distance_squared_to, VECTOR3, "b", varray());
- ADDFUNC1(VECTOR3, REAL, Vector3, angle_to, VECTOR3, "to", varray());
- ADDFUNC1(VECTOR3, VECTOR3, Vector3, slide, VECTOR3, "n", varray());
- ADDFUNC1(VECTOR3, VECTOR3, Vector3, bounce, VECTOR3, "n", varray());
- ADDFUNC1(VECTOR3, VECTOR3, Vector3, reflect, VECTOR3, "n", varray());
-
- ADDFUNC0(PLANE, PLANE, Plane, normalized, varray());
- ADDFUNC0(PLANE, VECTOR3, Plane, center, varray());
- ADDFUNC0(PLANE, VECTOR3, Plane, get_any_point, varray());
- ADDFUNC1(PLANE, BOOL, Plane, is_point_over, VECTOR3, "point", varray());
- ADDFUNC1(PLANE, REAL, Plane, distance_to, VECTOR3, "point", varray());
- ADDFUNC2(PLANE, BOOL, Plane, has_point, VECTOR3, "point", REAL, "epsilon", varray(CMP_EPSILON));
- ADDFUNC1(PLANE, VECTOR3, Plane, project, VECTOR3, "point", varray());
- ADDFUNC2(PLANE, VECTOR3, Plane, intersect_3, PLANE, "b", PLANE, "c", varray());
- ADDFUNC2(PLANE, VECTOR3, Plane, intersects_ray, VECTOR3, "from", VECTOR3, "dir", varray());
- ADDFUNC2(PLANE, VECTOR3, Plane, intersects_segment, VECTOR3, "begin", VECTOR3, "end", varray());
-
- ADDFUNC0(QUAT, REAL, Quat, length, varray());
- ADDFUNC0(QUAT, REAL, Quat, length_squared, varray());
- ADDFUNC0(QUAT, QUAT, Quat, normalized, varray());
- ADDFUNC0(QUAT, BOOL, Quat, is_normalized, varray());
- ADDFUNC0(QUAT, QUAT, Quat, inverse, varray());
- ADDFUNC1(QUAT, REAL, Quat, dot, QUAT, "b", varray());
- ADDFUNC1(QUAT, VECTOR3, Quat, xform, VECTOR3, "v", varray());
- ADDFUNC2(QUAT, QUAT, Quat, slerp, QUAT, "b", REAL, "t", varray());
- ADDFUNC2(QUAT, QUAT, Quat, slerpni, QUAT, "b", REAL, "t", varray());
- ADDFUNC4(QUAT, QUAT, Quat, cubic_slerp, QUAT, "b", QUAT, "pre_a", QUAT, "post_b", REAL, "t", varray());
-
- ADDFUNC0(COLOR, INT, Color, to_rgba32, varray());
- ADDFUNC0(COLOR, INT, Color, to_argb32, varray());
- ADDFUNC0(COLOR, REAL, Color, gray, varray());
- ADDFUNC0(COLOR, COLOR, Color, inverted, varray());
- ADDFUNC0(COLOR, COLOR, Color, contrasted, varray());
- ADDFUNC2(COLOR, COLOR, Color, linear_interpolate, COLOR, "b", REAL, "t", varray());
- ADDFUNC1(COLOR, COLOR, Color, blend, COLOR, "over", varray());
- ADDFUNC1(COLOR, STRING, Color, to_html, BOOL, "with_alpha", varray(true));
-
- ADDFUNC0(_RID, INT, RID, get_id, varray());
-
- ADDFUNC0(NODE_PATH, BOOL, NodePath, is_absolute, varray());
- ADDFUNC0(NODE_PATH, INT, NodePath, get_name_count, varray());
- ADDFUNC1(NODE_PATH, STRING, NodePath, get_name, INT, "idx", varray());
- ADDFUNC0(NODE_PATH, INT, NodePath, get_subname_count, varray());
- ADDFUNC1(NODE_PATH, STRING, NodePath, get_subname, INT, "idx", varray());
- ADDFUNC0(NODE_PATH, STRING, NodePath, get_property, varray());
- ADDFUNC0(NODE_PATH, BOOL, NodePath, is_empty, varray());
-
- ADDFUNC0(DICTIONARY, INT, Dictionary, size, varray());
- ADDFUNC0(DICTIONARY, BOOL, Dictionary, empty, varray());
+ ADDFUNC0R(STRING, INT, String, hash, varray());
+ ADDFUNC0R(STRING, STRING, String, md5_text, varray());
+ ADDFUNC0R(STRING, STRING, String, sha256_text, varray());
+ ADDFUNC0R(STRING, POOL_BYTE_ARRAY, String, md5_buffer, varray());
+ ADDFUNC0R(STRING, POOL_BYTE_ARRAY, String, sha256_buffer, varray());
+ ADDFUNC0R(STRING, BOOL, String, empty, varray());
+ ADDFUNC0R(STRING, BOOL, String, is_abs_path, varray());
+ ADDFUNC0R(STRING, BOOL, String, is_rel_path, varray());
+ ADDFUNC0R(STRING, STRING, String, get_base_dir, varray());
+ ADDFUNC0R(STRING, STRING, String, get_file, varray());
+ ADDFUNC0R(STRING, STRING, String, xml_escape, varray());
+ ADDFUNC0R(STRING, STRING, String, xml_unescape, varray());
+ ADDFUNC0R(STRING, STRING, String, c_escape, varray());
+ ADDFUNC0R(STRING, STRING, String, c_unescape, varray());
+ ADDFUNC0R(STRING, STRING, String, json_escape, varray());
+ ADDFUNC0R(STRING, STRING, String, percent_encode, varray());
+ ADDFUNC0R(STRING, STRING, String, percent_decode, varray());
+ ADDFUNC0R(STRING, BOOL, String, is_valid_identifier, varray());
+ ADDFUNC0R(STRING, BOOL, String, is_valid_integer, varray());
+ ADDFUNC0R(STRING, BOOL, String, is_valid_float, varray());
+ ADDFUNC0R(STRING, BOOL, String, is_valid_html_color, varray());
+ ADDFUNC0R(STRING, BOOL, String, is_valid_ip_address, varray());
+ ADDFUNC0R(STRING, INT, String, to_int, varray());
+ ADDFUNC0R(STRING, REAL, String, to_float, varray());
+ ADDFUNC0R(STRING, INT, String, hex_to_int, varray());
+ ADDFUNC1R(STRING, STRING, String, pad_decimals, INT, "digits", varray());
+ ADDFUNC1R(STRING, STRING, String, pad_zeros, INT, "digits", varray());
+
+ ADDFUNC0R(STRING, POOL_BYTE_ARRAY, String, to_ascii, varray());
+ ADDFUNC0R(STRING, POOL_BYTE_ARRAY, String, to_utf8, varray());
+
+ ADDFUNC0R(VECTOR2, VECTOR2, Vector2, normalized, varray());
+ ADDFUNC0R(VECTOR2, REAL, Vector2, length, varray());
+ ADDFUNC0R(VECTOR2, REAL, Vector2, angle, varray());
+ ADDFUNC0R(VECTOR2, REAL, Vector2, length_squared, varray());
+ ADDFUNC0R(VECTOR2, BOOL, Vector2, is_normalized, varray());
+ ADDFUNC1R(VECTOR2, REAL, Vector2, distance_to, VECTOR2, "to", varray());
+ ADDFUNC1R(VECTOR2, REAL, Vector2, distance_squared_to, VECTOR2, "to", varray());
+ ADDFUNC1R(VECTOR2, REAL, Vector2, angle_to, VECTOR2, "to", varray());
+ ADDFUNC1R(VECTOR2, REAL, Vector2, angle_to_point, VECTOR2, "to", varray());
+ ADDFUNC2R(VECTOR2, VECTOR2, Vector2, linear_interpolate, VECTOR2, "b", REAL, "t", varray());
+ ADDFUNC4R(VECTOR2, VECTOR2, Vector2, cubic_interpolate, VECTOR2, "b", VECTOR2, "pre_a", VECTOR2, "post_b", REAL, "t", varray());
+ ADDFUNC1R(VECTOR2, VECTOR2, Vector2, rotated, REAL, "phi", varray());
+ ADDFUNC0R(VECTOR2, VECTOR2, Vector2, tangent, varray());
+ ADDFUNC0R(VECTOR2, VECTOR2, Vector2, floor, varray());
+ ADDFUNC1R(VECTOR2, VECTOR2, Vector2, snapped, VECTOR2, "by", varray());
+ ADDFUNC0R(VECTOR2, REAL, Vector2, aspect, varray());
+ ADDFUNC1R(VECTOR2, REAL, Vector2, dot, VECTOR2, "with", varray());
+ ADDFUNC1R(VECTOR2, VECTOR2, Vector2, slide, VECTOR2, "n", varray());
+ ADDFUNC1R(VECTOR2, VECTOR2, Vector2, bounce, VECTOR2, "n", varray());
+ ADDFUNC1R(VECTOR2, VECTOR2, Vector2, reflect, VECTOR2, "n", varray());
+ //ADDFUNC1R(VECTOR2,REAL,Vector2,cross,VECTOR2,"with",varray());
+ ADDFUNC0R(VECTOR2, VECTOR2, Vector2, abs, varray());
+ ADDFUNC1R(VECTOR2, VECTOR2, Vector2, clamped, REAL, "length", varray());
+
+ ADDFUNC0R(RECT2, REAL, Rect2, get_area, varray());
+ ADDFUNC1R(RECT2, BOOL, Rect2, intersects, RECT2, "b", varray());
+ ADDFUNC1R(RECT2, BOOL, Rect2, encloses, RECT2, "b", varray());
+ ADDFUNC0R(RECT2, BOOL, Rect2, has_no_area, varray());
+ ADDFUNC1R(RECT2, RECT2, Rect2, clip, RECT2, "b", varray());
+ ADDFUNC1R(RECT2, RECT2, Rect2, merge, RECT2, "b", varray());
+ ADDFUNC1R(RECT2, BOOL, Rect2, has_point, VECTOR2, "point", varray());
+ ADDFUNC1R(RECT2, RECT2, Rect2, grow, REAL, "by", varray());
+ ADDFUNC2R(RECT2, RECT2, Rect2, grow_margin, INT, "margin", REAL, "by", varray());
+ ADDFUNC4R(RECT2, RECT2, Rect2, grow_individual, REAL, "left", REAL, "top", REAL, "right", REAL, " bottom", varray());
+ ADDFUNC1R(RECT2, RECT2, Rect2, expand, VECTOR2, "to", varray());
+
+ ADDFUNC0R(VECTOR3, INT, Vector3, min_axis, varray());
+ ADDFUNC0R(VECTOR3, INT, Vector3, max_axis, varray());
+ ADDFUNC0R(VECTOR3, REAL, Vector3, length, varray());
+ ADDFUNC0R(VECTOR3, REAL, Vector3, length_squared, varray());
+ ADDFUNC0R(VECTOR3, BOOL, Vector3, is_normalized, varray());
+ ADDFUNC0R(VECTOR3, VECTOR3, Vector3, normalized, varray());
+ ADDFUNC0R(VECTOR3, VECTOR3, Vector3, inverse, varray());
+ ADDFUNC1R(VECTOR3, VECTOR3, Vector3, snapped, REAL, "by", varray());
+ ADDFUNC2R(VECTOR3, VECTOR3, Vector3, rotated, VECTOR3, "axis", REAL, "phi", varray());
+ ADDFUNC2R(VECTOR3, VECTOR3, Vector3, linear_interpolate, VECTOR3, "b", REAL, "t", varray());
+ ADDFUNC4R(VECTOR3, VECTOR3, Vector3, cubic_interpolate, VECTOR3, "b", VECTOR3, "pre_a", VECTOR3, "post_b", REAL, "t", varray());
+ ADDFUNC1R(VECTOR3, REAL, Vector3, dot, VECTOR3, "b", varray());
+ ADDFUNC1R(VECTOR3, VECTOR3, Vector3, cross, VECTOR3, "b", varray());
+ ADDFUNC1R(VECTOR3, BASIS, Vector3, outer, VECTOR3, "b", varray());
+ ADDFUNC0R(VECTOR3, BASIS, Vector3, to_diagonal_matrix, varray());
+ ADDFUNC0R(VECTOR3, VECTOR3, Vector3, abs, varray());
+ ADDFUNC0R(VECTOR3, VECTOR3, Vector3, floor, varray());
+ ADDFUNC0R(VECTOR3, VECTOR3, Vector3, ceil, varray());
+ ADDFUNC1R(VECTOR3, REAL, Vector3, distance_to, VECTOR3, "b", varray());
+ ADDFUNC1R(VECTOR3, REAL, Vector3, distance_squared_to, VECTOR3, "b", varray());
+ ADDFUNC1R(VECTOR3, REAL, Vector3, angle_to, VECTOR3, "to", varray());
+ ADDFUNC1R(VECTOR3, VECTOR3, Vector3, slide, VECTOR3, "n", varray());
+ ADDFUNC1R(VECTOR3, VECTOR3, Vector3, bounce, VECTOR3, "n", varray());
+ ADDFUNC1R(VECTOR3, VECTOR3, Vector3, reflect, VECTOR3, "n", varray());
+
+ ADDFUNC0R(PLANE, PLANE, Plane, normalized, varray());
+ ADDFUNC0R(PLANE, VECTOR3, Plane, center, varray());
+ ADDFUNC0R(PLANE, VECTOR3, Plane, get_any_point, varray());
+ ADDFUNC1R(PLANE, BOOL, Plane, is_point_over, VECTOR3, "point", varray());
+ ADDFUNC1R(PLANE, REAL, Plane, distance_to, VECTOR3, "point", varray());
+ ADDFUNC2R(PLANE, BOOL, Plane, has_point, VECTOR3, "point", REAL, "epsilon", varray(CMP_EPSILON));
+ ADDFUNC1R(PLANE, VECTOR3, Plane, project, VECTOR3, "point", varray());
+ ADDFUNC2R(PLANE, VECTOR3, Plane, intersect_3, PLANE, "b", PLANE, "c", varray());
+ ADDFUNC2R(PLANE, VECTOR3, Plane, intersects_ray, VECTOR3, "from", VECTOR3, "dir", varray());
+ ADDFUNC2R(PLANE, VECTOR3, Plane, intersects_segment, VECTOR3, "begin", VECTOR3, "end", varray());
+
+ ADDFUNC0R(QUAT, REAL, Quat, length, varray());
+ ADDFUNC0R(QUAT, REAL, Quat, length_squared, varray());
+ ADDFUNC0R(QUAT, QUAT, Quat, normalized, varray());
+ ADDFUNC0R(QUAT, BOOL, Quat, is_normalized, varray());
+ ADDFUNC0R(QUAT, QUAT, Quat, inverse, varray());
+ ADDFUNC1R(QUAT, REAL, Quat, dot, QUAT, "b", varray());
+ ADDFUNC1R(QUAT, VECTOR3, Quat, xform, VECTOR3, "v", varray());
+ ADDFUNC2R(QUAT, QUAT, Quat, slerp, QUAT, "b", REAL, "t", varray());
+ ADDFUNC2R(QUAT, QUAT, Quat, slerpni, QUAT, "b", REAL, "t", varray());
+ ADDFUNC4R(QUAT, QUAT, Quat, cubic_slerp, QUAT, "b", QUAT, "pre_a", QUAT, "post_b", REAL, "t", varray());
+
+ ADDFUNC0R(COLOR, INT, Color, to_rgba32, varray());
+ ADDFUNC0R(COLOR, INT, Color, to_argb32, varray());
+ ADDFUNC0R(COLOR, REAL, Color, gray, varray());
+ ADDFUNC0R(COLOR, COLOR, Color, inverted, varray());
+ ADDFUNC0R(COLOR, COLOR, Color, contrasted, varray());
+ ADDFUNC2R(COLOR, COLOR, Color, linear_interpolate, COLOR, "b", REAL, "t", varray());
+ ADDFUNC1R(COLOR, COLOR, Color, blend, COLOR, "over", varray());
+ ADDFUNC1R(COLOR, STRING, Color, to_html, BOOL, "with_alpha", varray(true));
+
+ ADDFUNC0R(_RID, INT, RID, get_id, varray());
+
+ ADDFUNC0R(NODE_PATH, BOOL, NodePath, is_absolute, varray());
+ ADDFUNC0R(NODE_PATH, INT, NodePath, get_name_count, varray());
+ ADDFUNC1R(NODE_PATH, STRING, NodePath, get_name, INT, "idx", varray());
+ ADDFUNC0R(NODE_PATH, INT, NodePath, get_subname_count, varray());
+ ADDFUNC1R(NODE_PATH, STRING, NodePath, get_subname, INT, "idx", varray());
+ ADDFUNC0R(NODE_PATH, STRING, NodePath, get_property, varray());
+ ADDFUNC0R(NODE_PATH, BOOL, NodePath, is_empty, varray());
+
+ ADDFUNC0R(DICTIONARY, INT, Dictionary, size, varray());
+ ADDFUNC0R(DICTIONARY, BOOL, Dictionary, empty, varray());
ADDFUNC0NC(DICTIONARY, NIL, Dictionary, clear, varray());
- ADDFUNC1(DICTIONARY, BOOL, Dictionary, has, NIL, "key", varray());
- ADDFUNC1(DICTIONARY, BOOL, Dictionary, has_all, ARRAY, "keys", varray());
+ ADDFUNC1R(DICTIONARY, BOOL, Dictionary, has, NIL, "key", varray());
+ ADDFUNC1R(DICTIONARY, BOOL, Dictionary, has_all, ARRAY, "keys", varray());
ADDFUNC1(DICTIONARY, NIL, Dictionary, erase, NIL, "key", varray());
- ADDFUNC0(DICTIONARY, INT, Dictionary, hash, varray());
- ADDFUNC0(DICTIONARY, ARRAY, Dictionary, keys, varray());
- ADDFUNC0(DICTIONARY, ARRAY, Dictionary, values, varray());
+ ADDFUNC0R(DICTIONARY, INT, Dictionary, hash, varray());
+ ADDFUNC0R(DICTIONARY, ARRAY, Dictionary, keys, varray());
+ ADDFUNC0R(DICTIONARY, ARRAY, Dictionary, values, varray());
- ADDFUNC0(ARRAY, INT, Array, size, varray());
- ADDFUNC0(ARRAY, BOOL, Array, empty, varray());
+ ADDFUNC0R(ARRAY, INT, Array, size, varray());
+ ADDFUNC0R(ARRAY, BOOL, Array, empty, varray());
ADDFUNC0NC(ARRAY, NIL, Array, clear, varray());
- ADDFUNC0(ARRAY, INT, Array, hash, varray());
+ ADDFUNC0R(ARRAY, INT, Array, hash, varray());
ADDFUNC1NC(ARRAY, NIL, Array, push_back, NIL, "value", varray());
ADDFUNC1NC(ARRAY, NIL, Array, push_front, NIL, "value", varray());
ADDFUNC1NC(ARRAY, NIL, Array, append, NIL, "value", varray());
@@ -1592,165 +1616,162 @@ void register_variant_methods() {
ADDFUNC2NC(ARRAY, NIL, Array, insert, INT, "position", NIL, "value", varray());
ADDFUNC1NC(ARRAY, NIL, Array, remove, INT, "position", varray());
ADDFUNC1NC(ARRAY, NIL, Array, erase, NIL, "value", varray());
- ADDFUNC0(ARRAY, NIL, Array, front, varray());
- ADDFUNC0(ARRAY, NIL, Array, back, varray());
- ADDFUNC2(ARRAY, INT, Array, find, NIL, "what", INT, "from", varray(0));
- ADDFUNC2(ARRAY, INT, Array, rfind, NIL, "what", INT, "from", varray(-1));
- ADDFUNC1(ARRAY, INT, Array, find_last, NIL, "value", varray());
- ADDFUNC1(ARRAY, INT, Array, count, NIL, "value", varray());
- ADDFUNC1(ARRAY, BOOL, Array, has, NIL, "value", varray());
- ADDFUNC0NC(ARRAY, NIL, Array, pop_back, varray());
- ADDFUNC0NC(ARRAY, NIL, Array, pop_front, varray());
+ ADDFUNC0R(ARRAY, NIL, Array, front, varray());
+ ADDFUNC0R(ARRAY, NIL, Array, back, varray());
+ ADDFUNC2R(ARRAY, INT, Array, find, NIL, "what", INT, "from", varray(0));
+ ADDFUNC2R(ARRAY, INT, Array, rfind, NIL, "what", INT, "from", varray(-1));
+ ADDFUNC1R(ARRAY, INT, Array, find_last, NIL, "value", varray());
+ ADDFUNC1R(ARRAY, INT, Array, count, NIL, "value", varray());
+ ADDFUNC1R(ARRAY, BOOL, Array, has, NIL, "value", varray());
+ ADDFUNC0RNC(ARRAY, NIL, Array, pop_back, varray());
+ ADDFUNC0RNC(ARRAY, NIL, Array, pop_front, varray());
ADDFUNC0NC(ARRAY, NIL, Array, sort, varray());
ADDFUNC2NC(ARRAY, NIL, Array, sort_custom, OBJECT, "obj", STRING, "func", varray());
+ ADDFUNC2R(ARRAY, INT, Array, bsearch, NIL, "value", BOOL, "before", varray(true));
+ ADDFUNC4R(ARRAY, INT, Array, bsearch_custom, NIL, "value", OBJECT, "obj", STRING, "func", BOOL, "before", varray(true));
ADDFUNC0NC(ARRAY, NIL, Array, invert, varray());
- ADDFUNC0NC(ARRAY, ARRAY, Array, duplicate, varray());
+ ADDFUNC0RNC(ARRAY, ARRAY, Array, duplicate, varray());
- ADDFUNC0(POOL_BYTE_ARRAY, INT, PoolByteArray, size, varray());
+ ADDFUNC0R(POOL_BYTE_ARRAY, INT, PoolByteArray, size, varray());
ADDFUNC2(POOL_BYTE_ARRAY, NIL, PoolByteArray, set, INT, "idx", INT, "byte", varray());
ADDFUNC1(POOL_BYTE_ARRAY, NIL, PoolByteArray, push_back, INT, "byte", varray());
ADDFUNC1(POOL_BYTE_ARRAY, NIL, PoolByteArray, append, INT, "byte", varray());
ADDFUNC1(POOL_BYTE_ARRAY, NIL, PoolByteArray, append_array, POOL_BYTE_ARRAY, "array", varray());
ADDFUNC1(POOL_BYTE_ARRAY, NIL, PoolByteArray, remove, INT, "idx", varray());
- ADDFUNC2(POOL_BYTE_ARRAY, INT, PoolByteArray, insert, INT, "idx", INT, "byte", varray());
+ ADDFUNC2R(POOL_BYTE_ARRAY, INT, PoolByteArray, insert, INT, "idx", INT, "byte", varray());
ADDFUNC1(POOL_BYTE_ARRAY, NIL, PoolByteArray, resize, INT, "idx", varray());
ADDFUNC0(POOL_BYTE_ARRAY, NIL, PoolByteArray, invert, varray());
- ADDFUNC2(POOL_BYTE_ARRAY, POOL_BYTE_ARRAY, PoolByteArray, subarray, INT, "from", INT, "to", varray());
+ ADDFUNC2R(POOL_BYTE_ARRAY, POOL_BYTE_ARRAY, PoolByteArray, subarray, INT, "from", INT, "to", varray());
- ADDFUNC0(POOL_BYTE_ARRAY, STRING, PoolByteArray, get_string_from_ascii, varray());
- ADDFUNC0(POOL_BYTE_ARRAY, STRING, PoolByteArray, get_string_from_utf8, varray());
- ADDFUNC1(POOL_BYTE_ARRAY, POOL_BYTE_ARRAY, PoolByteArray, compress, INT, "compression_mode", varray(0));
- ADDFUNC2(POOL_BYTE_ARRAY, POOL_BYTE_ARRAY, PoolByteArray, decompress, INT, "buffer_size", INT, "compression_mode", varray(0));
+ ADDFUNC0R(POOL_BYTE_ARRAY, STRING, PoolByteArray, get_string_from_ascii, varray());
+ ADDFUNC0R(POOL_BYTE_ARRAY, STRING, PoolByteArray, get_string_from_utf8, varray());
+ ADDFUNC1R(POOL_BYTE_ARRAY, POOL_BYTE_ARRAY, PoolByteArray, compress, INT, "compression_mode", varray(0));
+ ADDFUNC2R(POOL_BYTE_ARRAY, POOL_BYTE_ARRAY, PoolByteArray, decompress, INT, "buffer_size", INT, "compression_mode", varray(0));
- ADDFUNC0(POOL_INT_ARRAY, INT, PoolIntArray, size, varray());
+ ADDFUNC0R(POOL_INT_ARRAY, INT, PoolIntArray, size, varray());
ADDFUNC2(POOL_INT_ARRAY, NIL, PoolIntArray, set, INT, "idx", INT, "integer", varray());
ADDFUNC1(POOL_INT_ARRAY, NIL, PoolIntArray, push_back, INT, "integer", varray());
ADDFUNC1(POOL_INT_ARRAY, NIL, PoolIntArray, append, INT, "integer", varray());
ADDFUNC1(POOL_INT_ARRAY, NIL, PoolIntArray, append_array, POOL_INT_ARRAY, "array", varray());
ADDFUNC1(POOL_INT_ARRAY, NIL, PoolIntArray, remove, INT, "idx", varray());
- ADDFUNC2(POOL_INT_ARRAY, INT, PoolIntArray, insert, INT, "idx", INT, "integer", varray());
+ ADDFUNC2R(POOL_INT_ARRAY, INT, PoolIntArray, insert, INT, "idx", INT, "integer", varray());
ADDFUNC1(POOL_INT_ARRAY, NIL, PoolIntArray, resize, INT, "idx", varray());
ADDFUNC0(POOL_INT_ARRAY, NIL, PoolIntArray, invert, varray());
- ADDFUNC0(POOL_REAL_ARRAY, INT, PoolRealArray, size, varray());
+ ADDFUNC0R(POOL_REAL_ARRAY, INT, PoolRealArray, size, varray());
ADDFUNC2(POOL_REAL_ARRAY, NIL, PoolRealArray, set, INT, "idx", REAL, "value", varray());
ADDFUNC1(POOL_REAL_ARRAY, NIL, PoolRealArray, push_back, REAL, "value", varray());
ADDFUNC1(POOL_REAL_ARRAY, NIL, PoolRealArray, append, REAL, "value", varray());
ADDFUNC1(POOL_REAL_ARRAY, NIL, PoolRealArray, append_array, POOL_REAL_ARRAY, "array", varray());
ADDFUNC1(POOL_REAL_ARRAY, NIL, PoolRealArray, remove, INT, "idx", varray());
- ADDFUNC2(POOL_REAL_ARRAY, INT, PoolRealArray, insert, INT, "idx", REAL, "value", varray());
+ ADDFUNC2R(POOL_REAL_ARRAY, INT, PoolRealArray, insert, INT, "idx", REAL, "value", varray());
ADDFUNC1(POOL_REAL_ARRAY, NIL, PoolRealArray, resize, INT, "idx", varray());
ADDFUNC0(POOL_REAL_ARRAY, NIL, PoolRealArray, invert, varray());
- ADDFUNC0(POOL_STRING_ARRAY, INT, PoolStringArray, size, varray());
+ ADDFUNC0R(POOL_STRING_ARRAY, INT, PoolStringArray, size, varray());
ADDFUNC2(POOL_STRING_ARRAY, NIL, PoolStringArray, set, INT, "idx", STRING, "string", varray());
ADDFUNC1(POOL_STRING_ARRAY, NIL, PoolStringArray, push_back, STRING, "string", varray());
ADDFUNC1(POOL_STRING_ARRAY, NIL, PoolStringArray, append, STRING, "string", varray());
ADDFUNC1(POOL_STRING_ARRAY, NIL, PoolStringArray, append_array, POOL_STRING_ARRAY, "array", varray());
ADDFUNC1(POOL_STRING_ARRAY, NIL, PoolStringArray, remove, INT, "idx", varray());
- ADDFUNC2(POOL_STRING_ARRAY, INT, PoolStringArray, insert, INT, "idx", STRING, "string", varray());
+ ADDFUNC2R(POOL_STRING_ARRAY, INT, PoolStringArray, insert, INT, "idx", STRING, "string", varray());
ADDFUNC1(POOL_STRING_ARRAY, NIL, PoolStringArray, resize, INT, "idx", varray());
ADDFUNC0(POOL_STRING_ARRAY, NIL, PoolStringArray, invert, varray());
ADDFUNC1(POOL_STRING_ARRAY, STRING, PoolStringArray, join, STRING, "delimiter", varray());
- ADDFUNC0(POOL_VECTOR2_ARRAY, INT, PoolVector2Array, size, varray());
+ ADDFUNC0R(POOL_VECTOR2_ARRAY, INT, PoolVector2Array, size, varray());
ADDFUNC2(POOL_VECTOR2_ARRAY, NIL, PoolVector2Array, set, INT, "idx", VECTOR2, "vector2", varray());
ADDFUNC1(POOL_VECTOR2_ARRAY, NIL, PoolVector2Array, push_back, VECTOR2, "vector2", varray());
ADDFUNC1(POOL_VECTOR2_ARRAY, NIL, PoolVector2Array, append, VECTOR2, "vector2", varray());
ADDFUNC1(POOL_VECTOR2_ARRAY, NIL, PoolVector2Array, append_array, POOL_VECTOR2_ARRAY, "array", varray());
ADDFUNC1(POOL_VECTOR2_ARRAY, NIL, PoolVector2Array, remove, INT, "idx", varray());
- ADDFUNC2(POOL_VECTOR2_ARRAY, INT, PoolVector2Array, insert, INT, "idx", VECTOR2, "vector2", varray());
+ ADDFUNC2R(POOL_VECTOR2_ARRAY, INT, PoolVector2Array, insert, INT, "idx", VECTOR2, "vector2", varray());
ADDFUNC1(POOL_VECTOR2_ARRAY, NIL, PoolVector2Array, resize, INT, "idx", varray());
ADDFUNC0(POOL_VECTOR2_ARRAY, NIL, PoolVector2Array, invert, varray());
- ADDFUNC0(POOL_VECTOR3_ARRAY, INT, PoolVector3Array, size, varray());
+ ADDFUNC0R(POOL_VECTOR3_ARRAY, INT, PoolVector3Array, size, varray());
ADDFUNC2(POOL_VECTOR3_ARRAY, NIL, PoolVector3Array, set, INT, "idx", VECTOR3, "vector3", varray());
ADDFUNC1(POOL_VECTOR3_ARRAY, NIL, PoolVector3Array, push_back, VECTOR3, "vector3", varray());
ADDFUNC1(POOL_VECTOR3_ARRAY, NIL, PoolVector3Array, append, VECTOR3, "vector3", varray());
ADDFUNC1(POOL_VECTOR3_ARRAY, NIL, PoolVector3Array, append_array, POOL_VECTOR3_ARRAY, "array", varray());
ADDFUNC1(POOL_VECTOR3_ARRAY, NIL, PoolVector3Array, remove, INT, "idx", varray());
- ADDFUNC2(POOL_VECTOR3_ARRAY, INT, PoolVector3Array, insert, INT, "idx", VECTOR3, "vector3", varray());
+ ADDFUNC2R(POOL_VECTOR3_ARRAY, INT, PoolVector3Array, insert, INT, "idx", VECTOR3, "vector3", varray());
ADDFUNC1(POOL_VECTOR3_ARRAY, NIL, PoolVector3Array, resize, INT, "idx", varray());
ADDFUNC0(POOL_VECTOR3_ARRAY, NIL, PoolVector3Array, invert, varray());
- ADDFUNC0(POOL_COLOR_ARRAY, INT, PoolColorArray, size, varray());
+ ADDFUNC0R(POOL_COLOR_ARRAY, INT, PoolColorArray, size, varray());
ADDFUNC2(POOL_COLOR_ARRAY, NIL, PoolColorArray, set, INT, "idx", COLOR, "color", varray());
ADDFUNC1(POOL_COLOR_ARRAY, NIL, PoolColorArray, push_back, COLOR, "color", varray());
ADDFUNC1(POOL_COLOR_ARRAY, NIL, PoolColorArray, append, COLOR, "color", varray());
ADDFUNC1(POOL_COLOR_ARRAY, NIL, PoolColorArray, append_array, POOL_COLOR_ARRAY, "array", varray());
ADDFUNC1(POOL_COLOR_ARRAY, NIL, PoolColorArray, remove, INT, "idx", varray());
- ADDFUNC2(POOL_COLOR_ARRAY, INT, PoolColorArray, insert, INT, "idx", COLOR, "color", varray());
+ ADDFUNC2R(POOL_COLOR_ARRAY, INT, PoolColorArray, insert, INT, "idx", COLOR, "color", varray());
ADDFUNC1(POOL_COLOR_ARRAY, NIL, PoolColorArray, resize, INT, "idx", varray());
ADDFUNC0(POOL_COLOR_ARRAY, NIL, PoolColorArray, invert, varray());
//pointerbased
- ADDFUNC0(RECT3, REAL, Rect3, get_area, varray());
- ADDFUNC0(RECT3, BOOL, Rect3, has_no_area, varray());
- ADDFUNC0(RECT3, BOOL, Rect3, has_no_surface, varray());
- ADDFUNC1(RECT3, BOOL, Rect3, intersects, RECT3, "with", varray());
- ADDFUNC1(RECT3, BOOL, Rect3, encloses, RECT3, "with", varray());
- ADDFUNC1(RECT3, RECT3, Rect3, merge, RECT3, "with", varray());
- ADDFUNC1(RECT3, RECT3, Rect3, intersection, RECT3, "with", varray());
- ADDFUNC1(RECT3, BOOL, Rect3, intersects_plane, PLANE, "plane", varray());
- ADDFUNC2(RECT3, BOOL, Rect3, intersects_segment, VECTOR3, "from", VECTOR3, "to", varray());
- ADDFUNC1(RECT3, BOOL, Rect3, has_point, VECTOR3, "point", varray());
- ADDFUNC1(RECT3, VECTOR3, Rect3, get_support, VECTOR3, "dir", varray());
- ADDFUNC0(RECT3, VECTOR3, Rect3, get_longest_axis, varray());
- ADDFUNC0(RECT3, INT, Rect3, get_longest_axis_index, varray());
- ADDFUNC0(RECT3, REAL, Rect3, get_longest_axis_size, varray());
- ADDFUNC0(RECT3, VECTOR3, Rect3, get_shortest_axis, varray());
- ADDFUNC0(RECT3, INT, Rect3, get_shortest_axis_index, varray());
- ADDFUNC0(RECT3, REAL, Rect3, get_shortest_axis_size, varray());
- ADDFUNC1(RECT3, RECT3, Rect3, expand, VECTOR3, "to_point", varray());
- ADDFUNC1(RECT3, RECT3, Rect3, grow, REAL, "by", varray());
- ADDFUNC1(RECT3, VECTOR3, Rect3, get_endpoint, INT, "idx", varray());
-
- ADDFUNC0(TRANSFORM2D, TRANSFORM2D, Transform2D, inverse, varray());
- ADDFUNC0(TRANSFORM2D, TRANSFORM2D, Transform2D, affine_inverse, varray());
- ADDFUNC0(TRANSFORM2D, REAL, Transform2D, get_rotation, varray());
- ADDFUNC0(TRANSFORM2D, VECTOR2, Transform2D, get_origin, varray());
- ADDFUNC0(TRANSFORM2D, VECTOR2, Transform2D, get_scale, varray());
- ADDFUNC0(TRANSFORM2D, TRANSFORM2D, Transform2D, orthonormalized, varray());
- ADDFUNC1(TRANSFORM2D, TRANSFORM2D, Transform2D, rotated, REAL, "phi", varray());
- ADDFUNC1(TRANSFORM2D, TRANSFORM2D, Transform2D, scaled, VECTOR2, "scale", varray());
- ADDFUNC1(TRANSFORM2D, TRANSFORM2D, Transform2D, translated, VECTOR2, "offset", varray());
- ADDFUNC1(TRANSFORM2D, TRANSFORM2D, Transform2D, xform, NIL, "v", varray());
- ADDFUNC1(TRANSFORM2D, TRANSFORM2D, Transform2D, xform_inv, NIL, "v", varray());
- ADDFUNC1(TRANSFORM2D, TRANSFORM2D, Transform2D, basis_xform, NIL, "v", varray());
- ADDFUNC1(TRANSFORM2D, TRANSFORM2D, Transform2D, basis_xform_inv, NIL, "v", varray());
- ADDFUNC2(TRANSFORM2D, TRANSFORM2D, Transform2D, interpolate_with, TRANSFORM2D, "transform", REAL, "weight", varray());
-
- ADDFUNC0(BASIS, BASIS, Basis, inverse, varray());
- ADDFUNC0(BASIS, BASIS, Basis, transposed, varray());
- ADDFUNC0(BASIS, BASIS, Basis, orthonormalized, varray());
- ADDFUNC0(BASIS, REAL, Basis, determinant, varray());
- ADDFUNC2(BASIS, BASIS, Basis, rotated, VECTOR3, "axis", REAL, "phi", varray());
- ADDFUNC1(BASIS, BASIS, Basis, scaled, VECTOR3, "scale", varray());
- ADDFUNC0(BASIS, VECTOR3, Basis, get_scale, varray());
- ADDFUNC0(BASIS, VECTOR3, Basis, get_euler, varray());
- ADDFUNC1(BASIS, REAL, Basis, tdotx, VECTOR3, "with", varray());
- ADDFUNC1(BASIS, REAL, Basis, tdoty, VECTOR3, "with", varray());
- ADDFUNC1(BASIS, REAL, Basis, tdotz, VECTOR3, "with", varray());
- ADDFUNC1(BASIS, VECTOR3, Basis, xform, VECTOR3, "v", varray());
- ADDFUNC1(BASIS, VECTOR3, Basis, xform_inv, VECTOR3, "v", varray());
- ADDFUNC0(BASIS, INT, Basis, get_orthogonal_index, varray());
-
- ADDFUNC0(TRANSFORM, TRANSFORM, Transform, inverse, varray());
- ADDFUNC0(TRANSFORM, TRANSFORM, Transform, affine_inverse, varray());
- ADDFUNC0(TRANSFORM, TRANSFORM, Transform, orthonormalized, varray());
- ADDFUNC2(TRANSFORM, TRANSFORM, Transform, rotated, VECTOR3, "axis", REAL, "phi", varray());
- ADDFUNC1(TRANSFORM, TRANSFORM, Transform, scaled, VECTOR3, "scale", varray());
- ADDFUNC1(TRANSFORM, TRANSFORM, Transform, translated, VECTOR3, "ofs", varray());
- ADDFUNC2(TRANSFORM, TRANSFORM, Transform, looking_at, VECTOR3, "target", VECTOR3, "up", varray());
- ADDFUNC2(TRANSFORM, TRANSFORM, Transform, interpolate_with, TRANSFORM, "transform", REAL, "weight", varray());
- ADDFUNC1(TRANSFORM, NIL, Transform, xform, NIL, "v", varray());
- ADDFUNC1(TRANSFORM, NIL, Transform, xform_inv, NIL, "v", varray());
-
-#ifdef DEBUG_ENABLED
- _VariantCall::type_funcs[Variant::TRANSFORM].functions["xform"].returns = true;
- _VariantCall::type_funcs[Variant::TRANSFORM].functions["xform_inv"].returns = true;
-#endif
+ ADDFUNC0R(AABB, REAL, AABB, get_area, varray());
+ ADDFUNC0R(AABB, BOOL, AABB, has_no_area, varray());
+ ADDFUNC0R(AABB, BOOL, AABB, has_no_surface, varray());
+ ADDFUNC1R(AABB, BOOL, AABB, intersects, AABB, "with", varray());
+ ADDFUNC1R(AABB, BOOL, AABB, encloses, AABB, "with", varray());
+ ADDFUNC1R(AABB, AABB, AABB, merge, AABB, "with", varray());
+ ADDFUNC1R(AABB, AABB, AABB, intersection, AABB, "with", varray());
+ ADDFUNC1R(AABB, BOOL, AABB, intersects_plane, PLANE, "plane", varray());
+ ADDFUNC2R(AABB, BOOL, AABB, intersects_segment, VECTOR3, "from", VECTOR3, "to", varray());
+ ADDFUNC1R(AABB, BOOL, AABB, has_point, VECTOR3, "point", varray());
+ ADDFUNC1R(AABB, VECTOR3, AABB, get_support, VECTOR3, "dir", varray());
+ ADDFUNC0R(AABB, VECTOR3, AABB, get_longest_axis, varray());
+ ADDFUNC0R(AABB, INT, AABB, get_longest_axis_index, varray());
+ ADDFUNC0R(AABB, REAL, AABB, get_longest_axis_size, varray());
+ ADDFUNC0R(AABB, VECTOR3, AABB, get_shortest_axis, varray());
+ ADDFUNC0R(AABB, INT, AABB, get_shortest_axis_index, varray());
+ ADDFUNC0R(AABB, REAL, AABB, get_shortest_axis_size, varray());
+ ADDFUNC1R(AABB, AABB, AABB, expand, VECTOR3, "to_point", varray());
+ ADDFUNC1R(AABB, AABB, AABB, grow, REAL, "by", varray());
+ ADDFUNC1R(AABB, VECTOR3, AABB, get_endpoint, INT, "idx", varray());
+
+ ADDFUNC0R(TRANSFORM2D, TRANSFORM2D, Transform2D, inverse, varray());
+ ADDFUNC0R(TRANSFORM2D, TRANSFORM2D, Transform2D, affine_inverse, varray());
+ ADDFUNC0R(TRANSFORM2D, REAL, Transform2D, get_rotation, varray());
+ ADDFUNC0R(TRANSFORM2D, VECTOR2, Transform2D, get_origin, varray());
+ ADDFUNC0R(TRANSFORM2D, VECTOR2, Transform2D, get_scale, varray());
+ ADDFUNC0R(TRANSFORM2D, TRANSFORM2D, Transform2D, orthonormalized, varray());
+ ADDFUNC1R(TRANSFORM2D, TRANSFORM2D, Transform2D, rotated, REAL, "phi", varray());
+ ADDFUNC1R(TRANSFORM2D, TRANSFORM2D, Transform2D, scaled, VECTOR2, "scale", varray());
+ ADDFUNC1R(TRANSFORM2D, TRANSFORM2D, Transform2D, translated, VECTOR2, "offset", varray());
+ ADDFUNC1R(TRANSFORM2D, TRANSFORM2D, Transform2D, xform, NIL, "v", varray());
+ ADDFUNC1R(TRANSFORM2D, TRANSFORM2D, Transform2D, xform_inv, NIL, "v", varray());
+ ADDFUNC1R(TRANSFORM2D, TRANSFORM2D, Transform2D, basis_xform, NIL, "v", varray());
+ ADDFUNC1R(TRANSFORM2D, TRANSFORM2D, Transform2D, basis_xform_inv, NIL, "v", varray());
+ ADDFUNC2R(TRANSFORM2D, TRANSFORM2D, Transform2D, interpolate_with, TRANSFORM2D, "transform", REAL, "weight", varray());
+
+ ADDFUNC0R(BASIS, BASIS, Basis, inverse, varray());
+ ADDFUNC0R(BASIS, BASIS, Basis, transposed, varray());
+ ADDFUNC0R(BASIS, BASIS, Basis, orthonormalized, varray());
+ ADDFUNC0R(BASIS, REAL, Basis, determinant, varray());
+ ADDFUNC2R(BASIS, BASIS, Basis, rotated, VECTOR3, "axis", REAL, "phi", varray());
+ ADDFUNC1R(BASIS, BASIS, Basis, scaled, VECTOR3, "scale", varray());
+ ADDFUNC0R(BASIS, VECTOR3, Basis, get_scale, varray());
+ ADDFUNC0R(BASIS, VECTOR3, Basis, get_euler, varray());
+ ADDFUNC1R(BASIS, REAL, Basis, tdotx, VECTOR3, "with", varray());
+ ADDFUNC1R(BASIS, REAL, Basis, tdoty, VECTOR3, "with", varray());
+ ADDFUNC1R(BASIS, REAL, Basis, tdotz, VECTOR3, "with", varray());
+ ADDFUNC1R(BASIS, VECTOR3, Basis, xform, VECTOR3, "v", varray());
+ ADDFUNC1R(BASIS, VECTOR3, Basis, xform_inv, VECTOR3, "v", varray());
+ ADDFUNC0R(BASIS, INT, Basis, get_orthogonal_index, varray());
+
+ ADDFUNC0R(TRANSFORM, TRANSFORM, Transform, inverse, varray());
+ ADDFUNC0R(TRANSFORM, TRANSFORM, Transform, affine_inverse, varray());
+ ADDFUNC0R(TRANSFORM, TRANSFORM, Transform, orthonormalized, varray());
+ ADDFUNC2R(TRANSFORM, TRANSFORM, Transform, rotated, VECTOR3, "axis", REAL, "phi", varray());
+ ADDFUNC1R(TRANSFORM, TRANSFORM, Transform, scaled, VECTOR3, "scale", varray());
+ ADDFUNC1R(TRANSFORM, TRANSFORM, Transform, translated, VECTOR3, "ofs", varray());
+ ADDFUNC2R(TRANSFORM, TRANSFORM, Transform, looking_at, VECTOR3, "target", VECTOR3, "up", varray());
+ ADDFUNC2R(TRANSFORM, TRANSFORM, Transform, interpolate_with, TRANSFORM, "transform", REAL, "weight", varray());
+ ADDFUNC1R(TRANSFORM, NIL, Transform, xform, NIL, "v", varray());
+ ADDFUNC1R(TRANSFORM, NIL, Transform, xform_inv, NIL, "v", varray());
/* REGISTER CONSTRUCTORS */
@@ -1774,7 +1795,7 @@ void register_variant_methods() {
_VariantCall::add_constructor(_VariantCall::Color_init1, Variant::COLOR, "r", Variant::REAL, "g", Variant::REAL, "b", Variant::REAL, "a", Variant::REAL);
_VariantCall::add_constructor(_VariantCall::Color_init2, Variant::COLOR, "r", Variant::REAL, "g", Variant::REAL, "b", Variant::REAL);
- _VariantCall::add_constructor(_VariantCall::Rect3_init1, Variant::RECT3, "position", Variant::VECTOR3, "size", Variant::VECTOR3);
+ _VariantCall::add_constructor(_VariantCall::AABB_init1, Variant::AABB, "position", Variant::VECTOR3, "size", Variant::VECTOR3);
_VariantCall::add_constructor(_VariantCall::Basis_init1, Variant::BASIS, "x_axis", Variant::VECTOR3, "y_axis", Variant::VECTOR3, "z_axis", Variant::VECTOR3);
_VariantCall::add_constructor(_VariantCall::Basis_init2, Variant::BASIS, "axis", Variant::VECTOR3, "phi", Variant::REAL);
diff --git a/core/variant_op.cpp b/core/variant_op.cpp
index 03ec336291..c793d70ed8 100644
--- a/core/variant_op.cpp
+++ b/core/variant_op.cpp
@@ -48,7 +48,7 @@
CASE_TYPE(PREFIX, OP, TRANSFORM2D) \
CASE_TYPE(PREFIX, OP, PLANE) \
CASE_TYPE(PREFIX, OP, QUAT) \
- CASE_TYPE(PREFIX, OP, RECT3) \
+ CASE_TYPE(PREFIX, OP, AABB) \
CASE_TYPE(PREFIX, OP, BASIS) \
CASE_TYPE(PREFIX, OP, TRANSFORM) \
CASE_TYPE(PREFIX, OP, COLOR) \
@@ -81,7 +81,7 @@
TYPE(PREFIX, OP, TRANSFORM2D), \
TYPE(PREFIX, OP, PLANE), \
TYPE(PREFIX, OP, QUAT), \
- TYPE(PREFIX, OP, RECT3), \
+ TYPE(PREFIX, OP, AABB), \
TYPE(PREFIX, OP, BASIS), \
TYPE(PREFIX, OP, TRANSFORM), \
TYPE(PREFIX, OP, COLOR), \
@@ -465,7 +465,7 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
DEFAULT_OP_LOCALMEM_NULL(math, OP_EQUAL, VECTOR3, ==, Vector3);
DEFAULT_OP_LOCALMEM_NULL(math, OP_EQUAL, PLANE, ==, Plane);
DEFAULT_OP_LOCALMEM_NULL(math, OP_EQUAL, QUAT, ==, Quat);
- DEFAULT_OP_PTRREF_NULL(math, OP_EQUAL, RECT3, ==, _rect3);
+ DEFAULT_OP_PTRREF_NULL(math, OP_EQUAL, AABB, ==, _aabb);
DEFAULT_OP_PTRREF_NULL(math, OP_EQUAL, BASIS, ==, _basis);
DEFAULT_OP_PTRREF_NULL(math, OP_EQUAL, TRANSFORM, ==, _transform);
DEFAULT_OP_LOCALMEM_NULL(math, OP_EQUAL, COLOR, ==, Color);
@@ -555,7 +555,7 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
DEFAULT_OP_LOCALMEM_NULL(math, OP_NOT_EQUAL, VECTOR3, !=, Vector3);
DEFAULT_OP_LOCALMEM_NULL(math, OP_NOT_EQUAL, PLANE, !=, Plane);
DEFAULT_OP_LOCALMEM_NULL(math, OP_NOT_EQUAL, QUAT, !=, Quat);
- DEFAULT_OP_PTRREF_NULL(math, OP_NOT_EQUAL, RECT3, !=, _rect3);
+ DEFAULT_OP_PTRREF_NULL(math, OP_NOT_EQUAL, AABB, !=, _aabb);
DEFAULT_OP_PTRREF_NULL(math, OP_NOT_EQUAL, BASIS, !=, _basis);
DEFAULT_OP_PTRREF_NULL(math, OP_NOT_EQUAL, TRANSFORM, !=, _transform);
DEFAULT_OP_LOCALMEM_NULL(math, OP_NOT_EQUAL, COLOR, !=, Color);
@@ -629,7 +629,7 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
CASE_TYPE(math, OP_LESS, TRANSFORM2D)
CASE_TYPE(math, OP_LESS, PLANE)
CASE_TYPE(math, OP_LESS, QUAT)
- CASE_TYPE(math, OP_LESS, RECT3)
+ CASE_TYPE(math, OP_LESS, AABB)
CASE_TYPE(math, OP_LESS, BASIS)
CASE_TYPE(math, OP_LESS, TRANSFORM)
CASE_TYPE(math, OP_LESS, COLOR)
@@ -658,7 +658,7 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
CASE_TYPE(math, OP_LESS_EQUAL, TRANSFORM2D)
CASE_TYPE(math, OP_LESS_EQUAL, PLANE)
CASE_TYPE(math, OP_LESS_EQUAL, QUAT)
- CASE_TYPE(math, OP_LESS_EQUAL, RECT3)
+ CASE_TYPE(math, OP_LESS_EQUAL, AABB)
CASE_TYPE(math, OP_LESS_EQUAL, BASIS)
CASE_TYPE(math, OP_LESS_EQUAL, TRANSFORM)
CASE_TYPE(math, OP_LESS_EQUAL, COLOR)
@@ -733,7 +733,7 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
CASE_TYPE(math, OP_GREATER, TRANSFORM2D)
CASE_TYPE(math, OP_GREATER, PLANE)
CASE_TYPE(math, OP_GREATER, QUAT)
- CASE_TYPE(math, OP_GREATER, RECT3)
+ CASE_TYPE(math, OP_GREATER, AABB)
CASE_TYPE(math, OP_GREATER, BASIS)
CASE_TYPE(math, OP_GREATER, TRANSFORM)
CASE_TYPE(math, OP_GREATER, COLOR)
@@ -762,7 +762,7 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
CASE_TYPE(math, OP_GREATER_EQUAL, TRANSFORM2D)
CASE_TYPE(math, OP_GREATER_EQUAL, PLANE)
CASE_TYPE(math, OP_GREATER_EQUAL, QUAT)
- CASE_TYPE(math, OP_GREATER_EQUAL, RECT3)
+ CASE_TYPE(math, OP_GREATER_EQUAL, AABB)
CASE_TYPE(math, OP_GREATER_EQUAL, BASIS)
CASE_TYPE(math, OP_GREATER_EQUAL, TRANSFORM)
CASE_TYPE(math, OP_GREATER_EQUAL, COLOR)
@@ -818,7 +818,7 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
CASE_TYPE(math, OP_ADD, RECT2)
CASE_TYPE(math, OP_ADD, TRANSFORM2D)
CASE_TYPE(math, OP_ADD, PLANE)
- CASE_TYPE(math, OP_ADD, RECT3)
+ CASE_TYPE(math, OP_ADD, AABB)
CASE_TYPE(math, OP_ADD, BASIS)
CASE_TYPE(math, OP_ADD, TRANSFORM)
CASE_TYPE(math, OP_ADD, NODE_PATH)
@@ -842,7 +842,7 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
CASE_TYPE(math, OP_SUBTRACT, RECT2)
CASE_TYPE(math, OP_SUBTRACT, TRANSFORM2D)
CASE_TYPE(math, OP_SUBTRACT, PLANE)
- CASE_TYPE(math, OP_SUBTRACT, RECT3)
+ CASE_TYPE(math, OP_SUBTRACT, AABB)
CASE_TYPE(math, OP_SUBTRACT, BASIS)
CASE_TYPE(math, OP_SUBTRACT, TRANSFORM)
CASE_TYPE(math, OP_SUBTRACT, NODE_PATH)
@@ -923,7 +923,7 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
CASE_TYPE(math, OP_MULTIPLY, STRING)
CASE_TYPE(math, OP_MULTIPLY, RECT2)
CASE_TYPE(math, OP_MULTIPLY, PLANE)
- CASE_TYPE(math, OP_MULTIPLY, RECT3)
+ CASE_TYPE(math, OP_MULTIPLY, AABB)
CASE_TYPE(math, OP_MULTIPLY, NODE_PATH)
CASE_TYPE(math, OP_MULTIPLY, _RID)
CASE_TYPE(math, OP_MULTIPLY, OBJECT)
@@ -964,7 +964,7 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
CASE_TYPE(math, OP_DIVIDE, RECT2)
CASE_TYPE(math, OP_DIVIDE, TRANSFORM2D)
CASE_TYPE(math, OP_DIVIDE, PLANE)
- CASE_TYPE(math, OP_DIVIDE, RECT3)
+ CASE_TYPE(math, OP_DIVIDE, AABB)
CASE_TYPE(math, OP_DIVIDE, BASIS)
CASE_TYPE(math, OP_DIVIDE, TRANSFORM)
CASE_TYPE(math, OP_DIVIDE, NODE_PATH)
@@ -995,7 +995,7 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
CASE_TYPE(math, OP_POSITIVE, STRING)
CASE_TYPE(math, OP_POSITIVE, RECT2)
CASE_TYPE(math, OP_POSITIVE, TRANSFORM2D)
- CASE_TYPE(math, OP_POSITIVE, RECT3)
+ CASE_TYPE(math, OP_POSITIVE, AABB)
CASE_TYPE(math, OP_POSITIVE, BASIS)
CASE_TYPE(math, OP_POSITIVE, TRANSFORM)
CASE_TYPE(math, OP_POSITIVE, COLOR)
@@ -1029,7 +1029,7 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
CASE_TYPE(math, OP_NEGATE, STRING)
CASE_TYPE(math, OP_NEGATE, RECT2)
CASE_TYPE(math, OP_NEGATE, TRANSFORM2D)
- CASE_TYPE(math, OP_NEGATE, RECT3)
+ CASE_TYPE(math, OP_NEGATE, AABB)
CASE_TYPE(math, OP_NEGATE, BASIS)
CASE_TYPE(math, OP_NEGATE, TRANSFORM)
CASE_TYPE(math, OP_NEGATE, NODE_PATH)
@@ -1088,7 +1088,7 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
CASE_TYPE(math, OP_MODULE, TRANSFORM2D)
CASE_TYPE(math, OP_MODULE, PLANE)
CASE_TYPE(math, OP_MODULE, QUAT)
- CASE_TYPE(math, OP_MODULE, RECT3)
+ CASE_TYPE(math, OP_MODULE, AABB)
CASE_TYPE(math, OP_MODULE, BASIS)
CASE_TYPE(math, OP_MODULE, TRANSFORM)
CASE_TYPE(math, OP_MODULE, COLOR)
@@ -1384,10 +1384,10 @@ void Variant::set_named(const StringName &p_index, const Variant &p_value, bool
}
} break; // 10
- case RECT3: {
+ case AABB: {
if (p_value.type == Variant::VECTOR3) {
- Rect3 *v = _data._rect3;
+ ::AABB *v = _data._aabb;
//scalar name
if (p_index == CoreStringNames::singleton->position) {
v->position = *reinterpret_cast<const Vector3 *>(p_value._data._mem);
@@ -1609,9 +1609,9 @@ Variant Variant::get_named(const StringName &p_index, bool *r_valid) const {
}
} break; // 10
- case RECT3: {
+ case AABB: {
- const Rect3 *v = _data._rect3;
+ const ::AABB *v = _data._aabb;
//scalar name
if (p_index == CoreStringNames::singleton->position) {
return v->position;
@@ -1655,13 +1655,13 @@ Variant Variant::get_named(const StringName &p_index, bool *r_valid) const {
} else if (p_index == CoreStringNames::singleton->a) {
return v->a;
} else if (p_index == CoreStringNames::singleton->r8) {
- return v->r * 255.0;
+ return int(v->r * 255.0);
} else if (p_index == CoreStringNames::singleton->g8) {
- return v->g * 255.0;
+ return int(v->g * 255.0);
} else if (p_index == CoreStringNames::singleton->b8) {
- return v->b * 255.0;
+ return int(v->b * 255.0);
} else if (p_index == CoreStringNames::singleton->a8) {
- return v->a * 255.0;
+ return int(v->a * 255.0);
} else if (p_index == CoreStringNames::singleton->h) {
return v->get_h();
} else if (p_index == CoreStringNames::singleton->s) {
@@ -1982,7 +1982,7 @@ void Variant::set(const Variant &p_index, const Variant &p_value, bool *r_valid)
}
} break; // 10
- case RECT3: {
+ case AABB: {
if (p_value.type != Variant::VECTOR3)
return;
@@ -1991,7 +1991,7 @@ void Variant::set(const Variant &p_index, const Variant &p_value, bool *r_valid)
//scalar name
const String *str = reinterpret_cast<const String *>(p_index._data._mem);
- Rect3 *v = _data._rect3;
+ ::AABB *v = _data._aabb;
if (*str == "position") {
valid = true;
v->position = p_value;
@@ -2400,13 +2400,13 @@ Variant Variant::get(const Variant &p_index, bool *r_valid) const {
}
} break; // 10
- case RECT3: {
+ case AABB: {
if (p_index.get_type() == Variant::STRING) {
//scalar name
const String *str = reinterpret_cast<const String *>(p_index._data._mem);
- const Rect3 *v = _data._rect3;
+ const ::AABB *v = _data._aabb;
if (*str == "position") {
valid = true;
return v->position;
@@ -2835,7 +2835,7 @@ void Variant::get_property_list(List<PropertyInfo> *p_list) const {
p_list->push_back(PropertyInfo(Variant::REAL, "w"));
} break; // 10
- case RECT3: {
+ case AABB: {
p_list->push_back(PropertyInfo(Variant::VECTOR3, "position"));
p_list->push_back(PropertyInfo(Variant::VECTOR3, "size"));
p_list->push_back(PropertyInfo(Variant::VECTOR3, "end"));
@@ -3457,10 +3457,10 @@ void Variant::blend(const Variant &a, const Variant &b, float c, Variant &r_dst)
r_dst = *reinterpret_cast<const Vector3 *>(a._data._mem) + *reinterpret_cast<const Vector3 *>(b._data._mem) * c;
}
return;
- case RECT3: {
- const Rect3 *ra = reinterpret_cast<const Rect3 *>(a._data._mem);
- const Rect3 *rb = reinterpret_cast<const Rect3 *>(b._data._mem);
- r_dst = Rect3(ra->position + rb->position * c, ra->size + rb->size * c);
+ case AABB: {
+ const ::AABB *ra = reinterpret_cast<const ::AABB *>(a._data._mem);
+ const ::AABB *rb = reinterpret_cast<const ::AABB *>(b._data._mem);
+ r_dst = ::AABB(ra->position + rb->position * c, ra->size + rb->size * c);
}
return;
case QUAT: {
@@ -3591,8 +3591,8 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant &
r_dst = reinterpret_cast<const Quat *>(a._data._mem)->slerp(*reinterpret_cast<const Quat *>(b._data._mem), c);
}
return;
- case RECT3: {
- r_dst = Rect3(a._data._rect3->position.linear_interpolate(b._data._rect3->position, c), a._data._rect3->size.linear_interpolate(b._data._rect3->size, c));
+ case AABB: {
+ r_dst = ::AABB(a._data._aabb->position.linear_interpolate(b._data._aabb->position, c), a._data._aabb->size.linear_interpolate(b._data._aabb->size, c));
}
return;
case BASIS: {
diff --git a/core/variant_parser.cpp b/core/variant_parser.cpp
index d60d10cd3a..1c02c627b5 100644
--- a/core/variant_parser.cpp
+++ b/core/variant_parser.cpp
@@ -595,7 +595,7 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
value = Quat(args[0], args[1], args[2], args[3]);
return OK;
- } else if (id == "Rect3" || id == "AABB") {
+ } else if (id == "AABB" || id == "Rect3") {
Vector<float> args;
Error err = _parse_construct<float>(p_stream, args, line, r_err_str);
@@ -606,7 +606,7 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
r_err_str = "Expected 6 arguments for constructor";
}
- value = Rect3(Vector3(args[0], args[1], args[2]), Vector3(args[3], args[4], args[5]));
+ value = AABB(Vector3(args[0], args[1], args[2]), Vector3(args[3], args[4], args[5]));
return OK;
} else if (id == "Basis" || id == "Matrix3") { //compatibility
@@ -1634,10 +1634,10 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
p_store_string_func(p_store_string_ud, "Plane( " + rtosfix(p.normal.x) + ", " + rtosfix(p.normal.y) + ", " + rtosfix(p.normal.z) + ", " + rtosfix(p.d) + " )");
} break;
- case Variant::RECT3: {
+ case Variant::AABB: {
- Rect3 aabb = p_variant;
- p_store_string_func(p_store_string_ud, "Rect3( " + rtosfix(aabb.position.x) + ", " + rtosfix(aabb.position.y) + ", " + rtosfix(aabb.position.z) + ", " + rtosfix(aabb.size.x) + ", " + rtosfix(aabb.size.y) + ", " + rtosfix(aabb.size.z) + " )");
+ AABB aabb = p_variant;
+ p_store_string_func(p_store_string_ud, "AABB( " + rtosfix(aabb.position.x) + ", " + rtosfix(aabb.position.y) + ", " + rtosfix(aabb.position.z) + ", " + rtosfix(aabb.size.x) + ", " + rtosfix(aabb.size.y) + ", " + rtosfix(aabb.size.z) + " )");
} break;
case Variant::QUAT: {
diff --git a/core/version.h b/core/version.h
index 436f30ef01..b217d82c5d 100644
--- a/core/version.h
+++ b/core/version.h
@@ -30,8 +30,8 @@
#include "version_generated.gen.h"
#ifdef VERSION_PATCH
-#define VERSION_MKSTRING "" _MKSTR(VERSION_MAJOR) "." _MKSTR(VERSION_MINOR) "." _MKSTR(VERSION_PATCH) "." _MKSTR(VERSION_STATUS) "." _MKSTR(VERSION_REVISION)
+#define VERSION_MKSTRING "" _MKSTR(VERSION_MAJOR) "." _MKSTR(VERSION_MINOR) "." _MKSTR(VERSION_PATCH) "." VERSION_STATUS "." VERSION_BUILD VERSION_MODULE_CONFIG
#else
-#define VERSION_MKSTRING "" _MKSTR(VERSION_MAJOR) "." _MKSTR(VERSION_MINOR) "." _MKSTR(VERSION_STATUS) "." _MKSTR(VERSION_REVISION)
+#define VERSION_MKSTRING "" _MKSTR(VERSION_MAJOR) "." _MKSTR(VERSION_MINOR) "." VERSION_STATUS "." VERSION_BUILD VERSION_MODULE_CONFIG
#endif // VERSION_PATCH
-#define VERSION_FULL_NAME "" _MKSTR(VERSION_NAME) " v" VERSION_MKSTRING
+#define VERSION_FULL_NAME "" VERSION_NAME " v" VERSION_MKSTRING
diff --git a/doc/Makefile b/doc/Makefile
index d68c66f8eb..2f9fefe794 100644
--- a/doc/Makefile
+++ b/doc/Makefile
@@ -24,5 +24,5 @@ rst:
rm -rf $(OUTPUTDIR)/rst
mkdir -p $(OUTPUTDIR)/rst
pushd $(OUTPUTDIR)/rst
- python2 $(TOOLSDIR)/makerst.py $(CLASSES)
+ python $(TOOLSDIR)/makerst.py $(CLASSES)
popd
diff --git a/doc/classes/@GDScript.xml b/doc/classes/@GDScript.xml
index b61cf93ef7..15ada7fdfa 100644
--- a/doc/classes/@GDScript.xml
+++ b/doc/classes/@GDScript.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="@GDScript" category="Core" version="3.0.alpha.custom_build">
+<class name="@GDScript" category="Core" version="3.0-alpha">
<brief_description>
Built-in GDScript functions.
</brief_description>
@@ -138,6 +138,17 @@
Decodes a byte array back to a value.
</description>
</method>
+ <method name="cartesian2polar">
+ <return type="Vector2">
+ </return>
+ <argument index="0" name="x" type="float">
+ </argument>
+ <argument index="1" name="y" type="float">
+ </argument>
+ <description>
+ Converts a 2D point expressed in the cartesian coordinate system (x and y axis) to the polar coordinate system (a distance from the origin and an angle).
+ </description>
+ </method>
<method name="ceil">
<return type="float">
</return>
@@ -196,7 +207,7 @@
<argument index="1" name="type" type="int">
</argument>
<description>
- Converts from a type to another in the best way possible. The [code]type[/code] parameter uses the enum TYPE_* in [@Global Scope].
+ Converts from a type to another in the best way possible. The [code]type[/code] parameter uses the enum TYPE_* in [@GlobalScope].
[codeblock]
a = Vector2(1, 0)
# prints 1
@@ -604,6 +615,17 @@
[/codeblock]
</description>
</method>
+ <method name="polar2cartesian">
+ <return type="Vector2">
+ </return>
+ <argument index="0" name="r" type="float">
+ </argument>
+ <argument index="1" name="th" type="float">
+ </argument>
+ <description>
+ Converts a 2D point expressed in the polar coordinate system (a distance from the origin [code]r[/code] and an angle [code]th[/code]) to the cartesian coordinate system (x and y axis).
+ </description>
+ </method>
<method name="pow">
<return type="float">
</return>
@@ -984,7 +1006,7 @@
<argument index="0" name="what" type="Variant">
</argument>
<description>
- Returns the internal type of the given Variant object, using the TYPE_* enum in [@Global Scope].
+ Returns the internal type of the given Variant object, using the TYPE_* enum in [@GlobalScope].
[codeblock]
p = parse_json('["a", "b", "c"]')
if typeof(p) == TYPE_ARRAY:
@@ -1050,22 +1072,77 @@
A weak reference to an object is not enough to keep the object alive: when the only remaining references to a referent are weak references, garbage collection is free to destroy the referent and reuse its memory for something else. However, until the object is actually destroyed the weak reference may return the object even if there are no strong references to it.
</description>
</method>
+ <method name="wrapf">
+ <return type="float">
+ </return>
+ <argument index="0" name="value" type="float">
+ </argument>
+ <argument index="1" name="min" type="float">
+ </argument>
+ <argument index="2" name="max" type="float">
+ </argument>
+ <description>
+ Wraps float [code]value[/code] between [code]min[/code] and [code]max[/code].
+ Usable for creating loop-alike behavior or infinite surfaces.
+ [codeblock]
+ # a is 0.5
+ a = wrapf(10.5, 0.0, 10.0)
+ [/codeblock]
+ [codeblock]
+ # a is 9.5
+ a = wrapf(-0.5, 0.0, 10.0)
+ [/codeblock]
+ [codeblock]
+ # infinite loop between 0.0 and 0.99
+ f = wrapf(f + 0.1, 0.0, 1.0)
+ [/codeblock]
+ </description>
+ </method>
+ <method name="wrapi">
+ <return type="int">
+ </return>
+ <argument index="0" name="value" type="int">
+ </argument>
+ <argument index="1" name="min" type="int">
+ </argument>
+ <argument index="2" name="max" type="int">
+ </argument>
+ <description>
+ Wraps integer [code]value[/code] between [code]min[/code] and [code]max[/code].
+ Usable for creating loop-alike behavior or infinite surfaces.
+ [codeblock]
+ # a is 0
+ a = wrapi(10, 0, 10)
+ [/codeblock]
+ [codeblock]
+ # a is 9
+ a = wrapi(-1, 0, 10)
+ [/codeblock]
+ [codeblock]
+ # infinite loop between 0 and 9
+ frame = wrapi(frame + 1, 0, 10)
+ [/codeblock]
+ </description>
+ </method>
<method name="yield">
- <return type="GDFunctionState">
+ <return type="GDScriptFunctionState">
</return>
<argument index="0" name="object" type="Object">
</argument>
<argument index="1" name="signal" type="String">
</argument>
<description>
- Stops the function execution and returns the current state. Call [method GDFunctionState.resume] on the state to resume execution. This invalidates the state.
+ Stops the function execution and returns the current state. Call [method GDScriptFunctionState.resume] on the state to resume execution. This invalidates the state.
Returns anything that was passed to the resume function call. If passed an object and a signal, the execution is resumed when the object's signal is emitted.
</description>
</method>
</methods>
<constants>
<constant name="PI" value="3.141593" enum="">
- Constant that represents how many times the diameter of a circumference fits around its perimeter.
+ Constant that represents how many times the diameter of a circle fits around its perimeter.
+ </constant>
+ <constant name="TAU" value="6.283185" enum="">
+ The circle constant, the circumference of the unit circle.
</constant>
<constant name="INF" value="inf" enum="">
A positive infinity. (For negative infinity, use -INF).
diff --git a/doc/classes/@Global Scope.xml b/doc/classes/@GlobalScope.xml
index d8c9a57a88..d9bdf0e3cf 100644
--- a/doc/classes/@Global Scope.xml
+++ b/doc/classes/@GlobalScope.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="@Global Scope" category="Core" version="3.0.alpha.custom_build">
+<class name="@GlobalScope" category="Core" version="3.0-alpha">
<brief_description>
Global scope constants and variables.
</brief_description>
@@ -29,6 +29,9 @@
<member name="Geometry" type="Geometry" setter="" getter="">
[Geometry] singleton
</member>
+ <member name="GodotSharp" type="GodotSharp" setter="" getter="">
+ [GodotSharp] singleton
+ </member>
<member name="IP" type="IP" setter="" getter="">
[IP] singleton
</member>
@@ -39,6 +42,9 @@
[InputMap] singleton
</member>
<member name="JSON" type="JSON" setter="" getter="">
+ [JSON] singleton
+ </member>
+ <member name="JavaScript" type="JavaScript" setter="" getter="">
</member>
<member name="Marshalls" type="Reference" setter="" getter="">
[Marshalls] singleton
@@ -142,8 +148,10 @@
Printscreen Key
</constant>
<constant name="KEY_SYSREQ" value="16777227">
+ System Request Key
</constant>
<constant name="KEY_CLEAR" value="16777228">
+ Clear Key
</constant>
<constant name="KEY_HOME" value="16777229">
Home Key
@@ -176,6 +184,7 @@
Control Key
</constant>
<constant name="KEY_META" value="16777239">
+ Meta Key
</constant>
<constant name="KEY_ALT" value="16777240">
Alt Key
@@ -283,24 +292,28 @@
Number 9 on Numpad
</constant>
<constant name="KEY_SUPER_L" value="16777260">
- Super Left key (windows key)
+ Left Super Key (Windows Key)
</constant>
<constant name="KEY_SUPER_R" value="16777261">
- Super Left key (windows key)
+ Right Super Key (Windows Key)
</constant>
<constant name="KEY_MENU" value="16777262">
Context menu key
</constant>
<constant name="KEY_HYPER_L" value="16777263">
+ Left Hyper Key
</constant>
<constant name="KEY_HYPER_R" value="16777264">
+ Right Hyper Key
</constant>
<constant name="KEY_HELP" value="16777265">
Help key
</constant>
<constant name="KEY_DIRECTION_L" value="16777266">
+ Left Direction Key
</constant>
<constant name="KEY_DIRECTION_R" value="16777267">
+ Right Direction Key
</constant>
<constant name="KEY_BACK" value="16777280">
Back key
@@ -324,14 +337,19 @@
Volume up key
</constant>
<constant name="KEY_BASSBOOST" value="16777287">
+ Bass Boost Key
</constant>
<constant name="KEY_BASSUP" value="16777288">
+ Bass Up Key
</constant>
<constant name="KEY_BASSDOWN" value="16777289">
+ Bass Down Key
</constant>
<constant name="KEY_TREBLEUP" value="16777290">
+ Treble Up Key
</constant>
<constant name="KEY_TREBLEDOWN" value="16777291">
+ Treble Down Key
</constant>
<constant name="KEY_MEDIAPLAY" value="16777292">
Media play key
@@ -358,46 +376,67 @@
Search key
</constant>
<constant name="KEY_STANDBY" value="16777300">
+ Standby Key
</constant>
<constant name="KEY_OPENURL" value="16777301">
+ Open URL / Launch Browser Key
</constant>
<constant name="KEY_LAUNCHMAIL" value="16777302">
+ Launch Mail Key
</constant>
<constant name="KEY_LAUNCHMEDIA" value="16777303">
+ Launch Media Key
</constant>
<constant name="KEY_LAUNCH0" value="16777304">
+ Launch Shortcut 0 Key
</constant>
<constant name="KEY_LAUNCH1" value="16777305">
+ Launch Shortcut 1 Key
</constant>
<constant name="KEY_LAUNCH2" value="16777306">
+ Launch Shortcut 2 Key
</constant>
<constant name="KEY_LAUNCH3" value="16777307">
+ Launch Shortcut 3 Key
</constant>
<constant name="KEY_LAUNCH4" value="16777308">
+ Launch Shortcut 4 Key
</constant>
<constant name="KEY_LAUNCH5" value="16777309">
+ Launch Shortcut 5 Key
</constant>
<constant name="KEY_LAUNCH6" value="16777310">
+ Launch Shortcut 6 Key
</constant>
<constant name="KEY_LAUNCH7" value="16777311">
+ Launch Shortcut 7 Key
</constant>
<constant name="KEY_LAUNCH8" value="16777312">
+ Launch Shortcut 8 Key
</constant>
<constant name="KEY_LAUNCH9" value="16777313">
+ Launch Shortcut 9 Key
</constant>
<constant name="KEY_LAUNCHA" value="16777314">
+ Launch Shortcut A Key
</constant>
<constant name="KEY_LAUNCHB" value="16777315">
+ Launch Shortcut B Key
</constant>
<constant name="KEY_LAUNCHC" value="16777316">
+ Launch Shortcut C Key
</constant>
<constant name="KEY_LAUNCHD" value="16777317">
+ Launch Shortcut D Key
</constant>
<constant name="KEY_LAUNCHE" value="16777318">
+ Launch Shortcut E Key
</constant>
<constant name="KEY_LAUNCHF" value="16777319">
+ Launch Shortcut F Key
</constant>
<constant name="KEY_UNKNOWN" value="33554431">
+ Unknown Key
</constant>
<constant name="KEY_SPACE" value="32">
Space Key
@@ -592,6 +631,7 @@
_ key
</constant>
<constant name="KEY_QUOTELEFT" value="96">
+ Left Quote Key
</constant>
<constant name="KEY_BRACELEFT" value="123">
{ key
@@ -617,6 +657,7 @@
<constant name="KEY_CURRENCY" value="164">
</constant>
<constant name="KEY_YEN" value="165">
+ Yen Key
</constant>
<constant name="KEY_BROKENBAR" value="166">
¦ key
@@ -645,6 +686,7 @@
® key
</constant>
<constant name="KEY_MACRON" value="175">
+ Macron Key
</constant>
<constant name="KEY_DEGREE" value="176">
° key
@@ -665,6 +707,7 @@
µ key
</constant>
<constant name="KEY_PARAGRAPH" value="182">
+ Paragraph Key
</constant>
<constant name="KEY_PERIODCENTERED" value="183">
· key
@@ -673,377 +716,479 @@
¬ key
</constant>
<constant name="KEY_ONESUPERIOR" value="185">
+ ¹ key
</constant>
<constant name="KEY_MASCULINE" value="186">
+ ♂ key
</constant>
<constant name="KEY_GUILLEMOTRIGHT" value="187">
+ » key
</constant>
<constant name="KEY_ONEQUARTER" value="188">
+ ¼ key
</constant>
<constant name="KEY_ONEHALF" value="189">
½ key
</constant>
<constant name="KEY_THREEQUARTERS" value="190">
+ ¾ key
</constant>
<constant name="KEY_QUESTIONDOWN" value="191">
+ ¿ key
</constant>
<constant name="KEY_AGRAVE" value="192">
+ à key
</constant>
<constant name="KEY_AACUTE" value="193">
+ á key
</constant>
<constant name="KEY_ACIRCUMFLEX" value="194">
+ â key
</constant>
<constant name="KEY_ATILDE" value="195">
+ ã key
</constant>
<constant name="KEY_ADIAERESIS" value="196">
+ ä key
</constant>
<constant name="KEY_ARING" value="197">
+ å key
</constant>
<constant name="KEY_AE" value="198">
+ æ key
</constant>
<constant name="KEY_CCEDILLA" value="199">
+ ç key
</constant>
<constant name="KEY_EGRAVE" value="200">
+ è key
</constant>
<constant name="KEY_EACUTE" value="201">
+ é key
</constant>
<constant name="KEY_ECIRCUMFLEX" value="202">
+ ê key
</constant>
<constant name="KEY_EDIAERESIS" value="203">
+ ë key
</constant>
<constant name="KEY_IGRAVE" value="204">
+ ì key
</constant>
<constant name="KEY_IACUTE" value="205">
+ í key
</constant>
<constant name="KEY_ICIRCUMFLEX" value="206">
+ î key
</constant>
<constant name="KEY_IDIAERESIS" value="207">
+ ë key
</constant>
<constant name="KEY_ETH" value="208">
+ ð key
</constant>
<constant name="KEY_NTILDE" value="209">
+ ñ key
</constant>
<constant name="KEY_OGRAVE" value="210">
+ ò key
</constant>
<constant name="KEY_OACUTE" value="211">
+ ó key
</constant>
<constant name="KEY_OCIRCUMFLEX" value="212">
+ ô key
</constant>
<constant name="KEY_OTILDE" value="213">
+ õ key
</constant>
<constant name="KEY_ODIAERESIS" value="214">
+ ö key
</constant>
<constant name="KEY_MULTIPLY" value="215">
+ × key
</constant>
<constant name="KEY_OOBLIQUE" value="216">
+ ø key
</constant>
<constant name="KEY_UGRAVE" value="217">
+ ù key
</constant>
<constant name="KEY_UACUTE" value="218">
+ ú key
</constant>
<constant name="KEY_UCIRCUMFLEX" value="219">
+ û key
</constant>
<constant name="KEY_UDIAERESIS" value="220">
+ ü key
</constant>
<constant name="KEY_YACUTE" value="221">
+ ý key
</constant>
<constant name="KEY_THORN" value="222">
+ þ key
</constant>
<constant name="KEY_SSHARP" value="223">
+ ß key
</constant>
<constant name="KEY_DIVISION" value="247">
+ ÷ key
</constant>
<constant name="KEY_YDIAERESIS" value="255">
+ ÿ key
</constant>
<constant name="KEY_CODE_MASK" value="33554431">
+ Key Code Mask
</constant>
<constant name="KEY_MODIFIER_MASK" value="-16777216">
+ Modifier Key Mask
</constant>
<constant name="KEY_MASK_SHIFT" value="33554432">
+ Shift Key Mask
</constant>
<constant name="KEY_MASK_ALT" value="67108864">
+ Alt Key Mask
</constant>
<constant name="KEY_MASK_META" value="134217728">
+ Meta Key Mask
</constant>
<constant name="KEY_MASK_CTRL" value="268435456">
+ CTRL Key Mask
</constant>
<constant name="KEY_MASK_CMD" value="268435456">
+ CMD Key Mask
</constant>
<constant name="KEY_MASK_KPAD" value="536870912">
+ Keypad Key Mask
</constant>
<constant name="KEY_MASK_GROUP_SWITCH" value="1073741824">
+ Group Switch Key Mask
</constant>
- <constant name="BUTTON_LEFT" value="1" enum="">
+ <constant name="BUTTON_LEFT" value="1">
Left Mouse Button
</constant>
- <constant name="BUTTON_RIGHT" value="2" enum="">
+ <constant name="BUTTON_RIGHT" value="2">
Right Mouse Button
</constant>
- <constant name="BUTTON_MIDDLE" value="3" enum="">
+ <constant name="BUTTON_MIDDLE" value="3">
Middle Mouse Button
</constant>
- <constant name="BUTTON_WHEEL_UP" value="4" enum="">
+ <constant name="BUTTON_WHEEL_UP" value="4">
Mouse wheel up
</constant>
- <constant name="BUTTON_WHEEL_DOWN" value="5" enum="">
+ <constant name="BUTTON_WHEEL_DOWN" value="5">
Mouse wheel down
</constant>
- <constant name="BUTTON_WHEEL_LEFT" value="6" enum="">
+ <constant name="BUTTON_WHEEL_LEFT" value="6">
Mouse wheel left button
</constant>
- <constant name="BUTTON_WHEEL_RIGHT" value="7" enum="">
+ <constant name="BUTTON_WHEEL_RIGHT" value="7">
Mouse wheel right button
</constant>
- <constant name="BUTTON_MASK_LEFT" value="1" enum="">
+ <constant name="BUTTON_MASK_LEFT" value="1">
+ Left Mouse Button Mask
</constant>
- <constant name="BUTTON_MASK_RIGHT" value="2" enum="">
+ <constant name="BUTTON_MASK_RIGHT" value="2">
+ Right Mouse Button Mask
</constant>
- <constant name="BUTTON_MASK_MIDDLE" value="4" enum="">
+ <constant name="BUTTON_MASK_MIDDLE" value="4">
+ Middle Mouse Button Mask
</constant>
- <constant name="JOY_BUTTON_0" value="0" enum="">
+ <constant name="JOY_BUTTON_0" value="0">
Joypad Button 0
</constant>
- <constant name="JOY_BUTTON_1" value="1" enum="">
+ <constant name="JOY_BUTTON_1" value="1">
Joypad Button 1
</constant>
- <constant name="JOY_BUTTON_2" value="2" enum="">
+ <constant name="JOY_BUTTON_2" value="2">
Joypad Button 2
</constant>
- <constant name="JOY_BUTTON_3" value="3" enum="">
+ <constant name="JOY_BUTTON_3" value="3">
Joypad Button 3
</constant>
- <constant name="JOY_BUTTON_4" value="4" enum="">
+ <constant name="JOY_BUTTON_4" value="4">
Joypad Button 4
</constant>
- <constant name="JOY_BUTTON_5" value="5" enum="">
+ <constant name="JOY_BUTTON_5" value="5">
Joypad Button 5
</constant>
- <constant name="JOY_BUTTON_6" value="6" enum="">
+ <constant name="JOY_BUTTON_6" value="6">
Joypad Button 6
</constant>
- <constant name="JOY_BUTTON_7" value="7" enum="">
+ <constant name="JOY_BUTTON_7" value="7">
Joypad Button 7
</constant>
- <constant name="JOY_BUTTON_8" value="8" enum="">
+ <constant name="JOY_BUTTON_8" value="8">
Joypad Button 8
</constant>
- <constant name="JOY_BUTTON_9" value="9" enum="">
+ <constant name="JOY_BUTTON_9" value="9">
Joypad Button 9
</constant>
- <constant name="JOY_BUTTON_10" value="10" enum="">
+ <constant name="JOY_BUTTON_10" value="10">
Joypad Button 10
</constant>
- <constant name="JOY_BUTTON_11" value="11" enum="">
+ <constant name="JOY_BUTTON_11" value="11">
Joypad Button 11
</constant>
- <constant name="JOY_BUTTON_12" value="12" enum="">
+ <constant name="JOY_BUTTON_12" value="12">
Joypad Button 12
</constant>
- <constant name="JOY_BUTTON_13" value="13" enum="">
+ <constant name="JOY_BUTTON_13" value="13">
Joypad Button 13
</constant>
- <constant name="JOY_BUTTON_14" value="14" enum="">
+ <constant name="JOY_BUTTON_14" value="14">
Joypad Button 14
</constant>
- <constant name="JOY_BUTTON_15" value="15" enum="">
+ <constant name="JOY_BUTTON_15" value="15">
Joypad Button 15
</constant>
- <constant name="JOY_BUTTON_MAX" value="16" enum="">
+ <constant name="JOY_BUTTON_MAX" value="16">
Joypad Button 16
</constant>
- <constant name="JOY_SONY_CIRCLE" value="1" enum="">
+ <constant name="JOY_SONY_CIRCLE" value="1">
DUALSHOCK circle button
</constant>
- <constant name="JOY_SONY_X" value="0" enum="">
+ <constant name="JOY_SONY_X" value="0">
DUALSHOCK X button
</constant>
- <constant name="JOY_SONY_SQUARE" value="2" enum="">
+ <constant name="JOY_SONY_SQUARE" value="2">
DUALSHOCK square button
</constant>
- <constant name="JOY_SONY_TRIANGLE" value="3" enum="">
+ <constant name="JOY_SONY_TRIANGLE" value="3">
DUALSHOCK triangle button
</constant>
- <constant name="JOY_XBOX_B" value="1" enum="">
+ <constant name="JOY_XBOX_B" value="1">
XBOX controller B button
</constant>
- <constant name="JOY_XBOX_A" value="0" enum="">
+ <constant name="JOY_XBOX_A" value="0">
XBOX controller A button
</constant>
- <constant name="JOY_XBOX_X" value="2" enum="">
+ <constant name="JOY_XBOX_X" value="2">
XBOX controller X button
</constant>
- <constant name="JOY_XBOX_Y" value="3" enum="">
+ <constant name="JOY_XBOX_Y" value="3">
XBOX controller Y button
</constant>
- <constant name="JOY_DS_A" value="1" enum="">
+ <constant name="JOY_DS_A" value="1">
+ DualShock controller A button
</constant>
- <constant name="JOY_DS_B" value="0" enum="">
+ <constant name="JOY_DS_B" value="0">
+ DualShock controller B button
</constant>
- <constant name="JOY_DS_X" value="3" enum="">
+ <constant name="JOY_DS_X" value="3">
+ DualShock controller X button
</constant>
- <constant name="JOY_DS_Y" value="2" enum="">
+ <constant name="JOY_DS_Y" value="2">
+ DualShock controller Y button
</constant>
- <constant name="JOY_SELECT" value="10" enum="">
+ <constant name="JOY_SELECT" value="10">
Joypad Button Select
</constant>
- <constant name="JOY_START" value="11" enum="">
+ <constant name="JOY_START" value="11">
Joypad Button Start
</constant>
- <constant name="JOY_DPAD_UP" value="12" enum="">
+ <constant name="JOY_DPAD_UP" value="12">
Joypad DPad Up
</constant>
- <constant name="JOY_DPAD_DOWN" value="13" enum="">
+ <constant name="JOY_DPAD_DOWN" value="13">
Joypad DPad Down
</constant>
- <constant name="JOY_DPAD_LEFT" value="14" enum="">
+ <constant name="JOY_DPAD_LEFT" value="14">
Joypad DPad Left
</constant>
- <constant name="JOY_DPAD_RIGHT" value="15" enum="">
+ <constant name="JOY_DPAD_RIGHT" value="15">
Joypad DPad Right
</constant>
- <constant name="JOY_L" value="4" enum="">
+ <constant name="JOY_L" value="4">
Joypad Left Shoulder Button
</constant>
- <constant name="JOY_L2" value="6" enum="">
+ <constant name="JOY_L2" value="6">
Joypad Left Trigger
</constant>
- <constant name="JOY_L3" value="8" enum="">
+ <constant name="JOY_L3" value="8">
Joypad Left Stick Click
</constant>
- <constant name="JOY_R" value="5" enum="">
+ <constant name="JOY_R" value="5">
Joypad Right Shoulder Button
</constant>
- <constant name="JOY_R2" value="7" enum="">
+ <constant name="JOY_R2" value="7">
Joypad Right Trigger
</constant>
- <constant name="JOY_R3" value="9" enum="">
+ <constant name="JOY_R3" value="9">
Joypad Right Stick Click
</constant>
- <constant name="JOY_AXIS_0" value="0" enum="">
+ <constant name="JOY_AXIS_0" value="0">
Joypad Left Stick Horizontal Axis
</constant>
- <constant name="JOY_AXIS_1" value="1" enum="">
+ <constant name="JOY_AXIS_1" value="1">
Joypad Left Stick Vertical Axis
</constant>
- <constant name="JOY_AXIS_2" value="2" enum="">
+ <constant name="JOY_AXIS_2" value="2">
Joypad Right Stick Horizontal Axis
</constant>
- <constant name="JOY_AXIS_3" value="3" enum="">
+ <constant name="JOY_AXIS_3" value="3">
Joypad Right Stick Vertical Axis
</constant>
- <constant name="JOY_AXIS_4" value="4" enum="">
+ <constant name="JOY_AXIS_4" value="4">
</constant>
- <constant name="JOY_AXIS_5" value="5" enum="">
+ <constant name="JOY_AXIS_5" value="5">
</constant>
- <constant name="JOY_AXIS_6" value="6" enum="">
+ <constant name="JOY_AXIS_6" value="6">
Joypad Left Trigger Analog Axis
</constant>
- <constant name="JOY_AXIS_7" value="7" enum="">
+ <constant name="JOY_AXIS_7" value="7">
Joypad Right Trigger Analog Axis
</constant>
- <constant name="JOY_AXIS_MAX" value="8" enum="">
+ <constant name="JOY_AXIS_8" value="8">
+ </constant>
+ <constant name="JOY_AXIS_9" value="9">
+ </constant>
+ <constant name="JOY_AXIS_MAX" value="10">
</constant>
- <constant name="JOY_ANALOG_LX" value="0" enum="">
+ <constant name="JOY_ANALOG_LX" value="0">
Joypad Left Stick Horizontal Axis
</constant>
- <constant name="JOY_ANALOG_LY" value="1" enum="">
+ <constant name="JOY_ANALOG_LY" value="1">
Joypad Left Stick Vertical Axis
</constant>
- <constant name="JOY_ANALOG_RX" value="2" enum="">
+ <constant name="JOY_ANALOG_RX" value="2">
Joypad Right Stick Horizontal Axis
</constant>
- <constant name="JOY_ANALOG_RY" value="3" enum="">
+ <constant name="JOY_ANALOG_RY" value="3">
Joypad Right Stick Vertical Axis
</constant>
- <constant name="JOY_ANALOG_L2" value="6" enum="">
+ <constant name="JOY_ANALOG_L2" value="6">
+ Joypad Left Analog Trigger
</constant>
- <constant name="JOY_ANALOG_R2" value="7" enum="">
+ <constant name="JOY_ANALOG_R2" value="7">
+ Joypad Right Analog Trigger
</constant>
<constant name="OK" value="0">
- Functions that return Error return OK when everything went ok. Most functions don't return error anyway and/or just print errors to stdout.
+ Functions that return Error return OK when no error occured. Most functions don't return errors and/or just print errors to STDOUT.
</constant>
<constant name="FAILED" value="1">
- Generic fail return error.
+ Generic error.
</constant>
<constant name="ERR_UNAVAILABLE" value="2">
+ Unavailable error
</constant>
<constant name="ERR_UNCONFIGURED" value="3">
+ Unconfigured error
</constant>
<constant name="ERR_UNAUTHORIZED" value="4">
+ Unauthorized error
</constant>
<constant name="ERR_PARAMETER_RANGE_ERROR" value="5">
+ Parameter range error
</constant>
<constant name="ERR_OUT_OF_MEMORY" value="6">
+ Out of memory (OOM) error
</constant>
<constant name="ERR_FILE_NOT_FOUND" value="7">
+ File: Not found error
</constant>
<constant name="ERR_FILE_BAD_DRIVE" value="8">
+ File: Bad drive error
</constant>
<constant name="ERR_FILE_BAD_PATH" value="9">
+ File: Bad path error
</constant>
<constant name="ERR_FILE_NO_PERMISSION" value="10">
+ File: No permission error
</constant>
<constant name="ERR_FILE_ALREADY_IN_USE" value="11">
+ File: Already in use error
</constant>
<constant name="ERR_FILE_CANT_OPEN" value="12">
+ File: Can't open error
</constant>
<constant name="ERR_FILE_CANT_WRITE" value="13">
+ File: Can't write error
</constant>
<constant name="ERR_FILE_CANT_READ" value="14">
+ File: Can't read error
</constant>
<constant name="ERR_FILE_UNRECOGNIZED" value="15">
+ File: Unrecognized error
</constant>
<constant name="ERR_FILE_CORRUPT" value="16">
+ File: Corrupt error
</constant>
<constant name="ERR_FILE_MISSING_DEPENDENCIES" value="17">
+ File: Missing dependencies error
</constant>
<constant name="ERR_FILE_EOF" value="18">
+ File: End of file (EOF) error
</constant>
<constant name="ERR_CANT_OPEN" value="19">
+ Can't open error
</constant>
<constant name="ERR_CANT_CREATE" value="20">
+ Can't create error
</constant>
<constant name="ERR_PARSE_ERROR" value="43">
+ Parse error
</constant>
<constant name="ERR_QUERY_FAILED" value="21">
+ Query failed error
</constant>
<constant name="ERR_ALREADY_IN_USE" value="22">
+ Already in use error
</constant>
<constant name="ERR_LOCKED" value="23">
+ Locked error
</constant>
<constant name="ERR_TIMEOUT" value="24">
+ Timeout error
</constant>
<constant name="ERR_CANT_ACQUIRE_RESOURCE" value="28">
+ Can't acquire resource error
</constant>
<constant name="ERR_INVALID_DATA" value="30">
+ Invalid data error
</constant>
<constant name="ERR_INVALID_PARAMETER" value="31">
+ Invalid parameter error
</constant>
<constant name="ERR_ALREADY_EXISTS" value="32">
+ Already exists error
</constant>
<constant name="ERR_DOES_NOT_EXIST" value="33">
+ Does not exist error
</constant>
<constant name="ERR_DATABASE_CANT_READ" value="34">
+ Database: Read error
</constant>
<constant name="ERR_DATABASE_CANT_WRITE" value="35">
+ Database: Write error
</constant>
<constant name="ERR_COMPILATION_FAILED" value="36">
+ Compilation failed error
</constant>
<constant name="ERR_METHOD_NOT_FOUND" value="37">
+ Method not found error
</constant>
<constant name="ERR_LINK_FAILED" value="38">
+ Linking failed error
</constant>
<constant name="ERR_SCRIPT_FAILED" value="39">
+ Script failed error
</constant>
<constant name="ERR_CYCLIC_LINK" value="40">
+ Cycling link (import cycle) error
</constant>
<constant name="ERR_BUSY" value="44">
+ Busy error
</constant>
<constant name="ERR_HELP" value="46">
+ Help error
</constant>
<constant name="ERR_BUG" value="47">
+ Bug error
</constant>
<constant name="ERR_WTF" value="49">
+ WTF error (something probably went really wrong)
</constant>
<constant name="PROPERTY_HINT_NONE" value="0">
No hint for edited property.
@@ -1092,8 +1237,10 @@
<constant name="PROPERTY_HINT_COLOR_NO_ALPHA" value="19">
</constant>
<constant name="PROPERTY_HINT_IMAGE_COMPRESS_LOSSY" value="20">
+ Hints that the image is compressed using lossy compression.
</constant>
<constant name="PROPERTY_HINT_IMAGE_COMPRESS_LOSSLESS" value="21">
+ Hints that the image is compressed using lossless compression.
</constant>
<constant name="PROPERTY_USAGE_STORAGE" value="1">
Property will be used as storage (default).
@@ -1133,20 +1280,26 @@
<constant name="PROPERTY_USAGE_NOEDITOR" value="5">
</constant>
<constant name="METHOD_FLAG_NORMAL" value="1">
+ Flag for normal method
</constant>
<constant name="METHOD_FLAG_EDITOR" value="2">
+ Flag for editor method
</constant>
<constant name="METHOD_FLAG_NOSCRIPT" value="4">
</constant>
<constant name="METHOD_FLAG_CONST" value="8">
+ Flag for constant method
</constant>
<constant name="METHOD_FLAG_REVERSE" value="16">
</constant>
<constant name="METHOD_FLAG_VIRTUAL" value="32">
+ Flag for virtual method
</constant>
<constant name="METHOD_FLAG_FROM_SCRIPT" value="64">
+ Flag for method from script
</constant>
<constant name="METHOD_FLAGS_DEFAULT" value="1">
+ Default method flags
</constant>
<constant name="TYPE_NIL" value="0">
Variable is of type nil (only applied for null).
@@ -1181,8 +1334,8 @@
<constant name="TYPE_QUAT" value="10">
Variable is of type [Quat].
</constant>
- <constant name="TYPE_RECT3" value="11">
- Variable is of type [Rect3].
+ <constant name="TYPE_AABB" value="11">
+ Variable is of type [AABB].
</constant>
<constant name="TYPE_BASIS" value="12">
Variable is of type [Basis].
@@ -1230,6 +1383,7 @@
Variable is of type [PoolColorArray].
</constant>
<constant name="TYPE_MAX" value="27">
+ Marker for end of type constants.
</constant>
</constants>
</class>
diff --git a/doc/classes/@NativeScript.xml b/doc/classes/@NativeScript.xml
index 03e6416b19..a9dfc4538a 100644
--- a/doc/classes/@NativeScript.xml
+++ b/doc/classes/@NativeScript.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="@NativeScript" category="Core" version="3.0.alpha.custom_build">
+<class name="@NativeScript" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/@VisualScript.xml b/doc/classes/@VisualScript.xml
index fe40bc45e9..0e6205c040 100644
--- a/doc/classes/@VisualScript.xml
+++ b/doc/classes/@VisualScript.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="@VisualScript" category="Core" version="3.0.alpha.custom_build">
+<class name="@VisualScript" category="Core" version="3.0-alpha">
<brief_description>
Built-in visual script functions.
</brief_description>
diff --git a/doc/classes/Rect3.xml b/doc/classes/AABB.xml
index f41665db34..494dcb8fce 100644
--- a/doc/classes/Rect3.xml
+++ b/doc/classes/AABB.xml
@@ -1,18 +1,18 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Rect3" category="Built-In Types" version="3.0.alpha.custom_build">
+<class name="AABB" category="Built-In Types" version="3.0-alpha">
<brief_description>
Axis-Aligned Bounding Box.
</brief_description>
<description>
- Rect3 provides an 3D Axis-Aligned Bounding Box. It consists of a position, a size, and several utility functions. It is typically used for simple (fast) overlap tests.
+ AABB consists of a position, a size, and several utility functions. It is typically used for fast overlap tests.
</description>
<tutorials>
</tutorials>
<demos>
</demos>
<methods>
- <method name="Rect3">
- <return type="Rect3">
+ <method name="AABB">
+ <return type="AABB">
</return>
<argument index="0" name="position" type="Vector3">
</argument>
@@ -25,26 +25,26 @@
<method name="encloses">
<return type="bool">
</return>
- <argument index="0" name="with" type="Rect3">
+ <argument index="0" name="with" type="AABB">
</argument>
<description>
- Return true if this [Rect3] completely encloses another one.
+ Returns [code]true[/code] if this [code]AABB[/code] completely encloses another one.
</description>
</method>
<method name="expand">
- <return type="Rect3">
+ <return type="AABB">
</return>
<argument index="0" name="to_point" type="Vector3">
</argument>
<description>
- Return this [Rect3] expanded to include a given point.
+ Returns this [code]AABB[/code] expanded to include a given point.
</description>
</method>
<method name="get_area">
<return type="float">
</return>
<description>
- Get the area of the [Rect3].
+ Gets the area of the [code]AABB[/code].
</description>
</method>
<method name="get_endpoint">
@@ -53,49 +53,49 @@
<argument index="0" name="idx" type="int">
</argument>
<description>
- Get the position of the 8 endpoints of the [Rect3] in space.
+ Gets the position of the 8 endpoints of the [code]AABB[/code] in space.
</description>
</method>
<method name="get_longest_axis">
<return type="Vector3">
</return>
<description>
- Return the normalized longest axis of the [Rect3].
+ Returns the normalized longest axis of the [code]AABB[/code].
</description>
</method>
<method name="get_longest_axis_index">
<return type="int">
</return>
<description>
- Return the index of the longest axis of the [Rect3] (according to [Vector3]::AXIS* enum).
+ Returns the index of the longest axis of the [code]AABB[/code] (according to [Vector3]::AXIS* enum).
</description>
</method>
<method name="get_longest_axis_size">
<return type="float">
</return>
<description>
- Return the scalar length of the longest axis of the [Rect3].
+ Returns the scalar length of the longest axis of the [code]AABB[/code].
</description>
</method>
<method name="get_shortest_axis">
<return type="Vector3">
</return>
<description>
- Return the normalized shortest axis of the [Rect3].
+ Returns the normalized shortest axis of the [code]AABB[/code].
</description>
</method>
<method name="get_shortest_axis_index">
<return type="int">
</return>
<description>
- Return the index of the shortest axis of the [Rect3] (according to [Vector3]::AXIS* enum).
+ Returns the index of the shortest axis of the [code]AABB[/code] (according to [Vector3]::AXIS* enum).
</description>
</method>
<method name="get_shortest_axis_size">
<return type="float">
</return>
<description>
- Return the scalar length of the shortest axis of the [Rect3].
+ Returns the scalar length of the shortest axis of the [code]AABB[/code].
</description>
</method>
<method name="get_support">
@@ -104,30 +104,30 @@
<argument index="0" name="dir" type="Vector3">
</argument>
<description>
- Return the support point in a given direction. This is useful for collision detection algorithms.
+ Returns the support point in a given direction. This is useful for collision detection algorithms.
</description>
</method>
<method name="grow">
- <return type="Rect3">
+ <return type="AABB">
</return>
<argument index="0" name="by" type="float">
</argument>
<description>
- Return a copy of the [Rect3] grown a given amount of units towards all the sides.
+ Returns a copy of the [code]AABB[/code] grown a given amount of units towards all the sides.
</description>
</method>
<method name="has_no_area">
<return type="bool">
</return>
<description>
- Return true if the [Rect3] is flat or empty.
+ Returns [code]true[/code] if the [code]AABB[/code] is flat or empty.
</description>
</method>
<method name="has_no_surface">
<return type="bool">
</return>
<description>
- Return true if the [Rect3] is empty.
+ Returns [code]true[/code] if the [code]AABB[/code] is empty.
</description>
</method>
<method name="has_point">
@@ -136,25 +136,25 @@
<argument index="0" name="point" type="Vector3">
</argument>
<description>
- Return true if the [Rect3] contains a point.
+ Returns [code]true[/code] if the [code]AABB[/code] contains a point.
</description>
</method>
<method name="intersection">
- <return type="Rect3">
+ <return type="AABB">
</return>
- <argument index="0" name="with" type="Rect3">
+ <argument index="0" name="with" type="AABB">
</argument>
<description>
- Return the intersection between two [Rect3]. An empty Rect3 (size 0,0,0) is returned on failure.
+ Returns the intersection between two [code]AABB[/code]. An empty AABB (size 0,0,0) is returned on failure.
</description>
</method>
<method name="intersects">
<return type="bool">
</return>
- <argument index="0" name="with" type="Rect3">
+ <argument index="0" name="with" type="AABB">
</argument>
<description>
- Return true if the [Rect3] overlaps with another.
+ Returns [code]true[/code] if the [code]AABB[/code] overlaps with another.
</description>
</method>
<method name="intersects_plane">
@@ -163,7 +163,7 @@
<argument index="0" name="plane" type="Plane">
</argument>
<description>
- Return true if the [Rect3] is at both sides of a plane.
+ Returns [code]true[/code] if the [code]AABB[/code] is on both sides of a plane.
</description>
</method>
<method name="intersects_segment">
@@ -174,16 +174,16 @@
<argument index="1" name="to" type="Vector3">
</argument>
<description>
- Return true if the [Rect3] intersects the line segment between from and to
+ Returns [code]true[/code] if the [code]AABB[/code] intersects the line segment between [code]from[/code] and [code]to[/code].
</description>
</method>
<method name="merge">
- <return type="Rect3">
+ <return type="AABB">
</return>
- <argument index="0" name="with" type="Rect3">
+ <argument index="0" name="with" type="AABB">
</argument>
<description>
- Combine this [Rect3] with another, a larger one is returned that contains both.
+ Returns a larger AABB that contains this AABB and [code]with[/code].
</description>
</method>
</methods>
@@ -192,6 +192,7 @@
Ending corner.
</member>
<member name="position" type="Vector3" setter="" getter="">
+ Beginning corner.
</member>
<member name="size" type="Vector3" setter="" getter="">
Size from position to end.
diff --git a/doc/classes/ARVRAnchor.xml b/doc/classes/ARVRAnchor.xml
index 6e11034073..8bb12609b0 100644
--- a/doc/classes/ARVRAnchor.xml
+++ b/doc/classes/ARVRAnchor.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ARVRAnchor" inherits="Spatial" category="Core" version="3.0.alpha.custom_build">
+<class name="ARVRAnchor" inherits="Spatial" category="Core" version="3.0-alpha">
<brief_description>
Anchor point in AR Space
</brief_description>
@@ -60,6 +60,7 @@
</methods>
<members>
<member name="anchor_id" type="int" setter="set_anchor_id" getter="get_anchor_id">
+ The anchor's id. You can set this before the anchor itself exists. The first anchor gets an id of [code]1[/code], the second an id of [code]2[/code], etc. When anchors get removed, the engine can then assign the corresponding id to new anchors. The most common situation where anchors 'disappear' is when the AR server identifies that two anchors represent different parts of the same plane and merges them.
</member>
</members>
<constants>
diff --git a/doc/classes/ARVRCamera.xml b/doc/classes/ARVRCamera.xml
index e6817d3417..0d9886618d 100644
--- a/doc/classes/ARVRCamera.xml
+++ b/doc/classes/ARVRCamera.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ARVRCamera" inherits="Camera" category="Core" version="3.0.alpha.custom_build">
+<class name="ARVRCamera" inherits="Camera" category="Core" version="3.0-alpha">
<brief_description>
A camera node with a few overrules for AR/VR applied such as location tracking.
</brief_description>
diff --git a/doc/classes/ARVRController.xml b/doc/classes/ARVRController.xml
index 557f915c1d..8af483132b 100644
--- a/doc/classes/ARVRController.xml
+++ b/doc/classes/ARVRController.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ARVRController" inherits="Spatial" category="Core" version="3.0.alpha.custom_build">
+<class name="ARVRController" inherits="Spatial" category="Core" version="3.0-alpha">
<brief_description>
A spatial node representing a spatially tracked controller.
</brief_description>
@@ -31,6 +31,7 @@
<return type="int" enum="ARVRPositionalTracker.TrackerHand">
</return>
<description>
+ Returns the hand holding this controller, if known. See TRACKER_* constants in [ARVRPositionalTracker].
</description>
</method>
<method name="get_is_active" qualifiers="const">
@@ -56,6 +57,12 @@
Returns the ID of the joystick object bound to this. Every controller tracked by the ARVR Server that has buttons and axis will also be registered as a joystick within Godot. This means that all the normal joystick tracking and input mapping will work for buttons and axis found on the AR/VR controllers. This ID is purely offered as information so you can link up the controller with its joystick entry.
</description>
</method>
+ <method name="get_rumble" qualifiers="const">
+ <return type="float">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="is_button_pressed" qualifiers="const">
<return type="int">
</return>
@@ -74,9 +81,20 @@
Changes the id that identifies the controller bound to this node. The first controller that the ARVR Server detects will have id 1, the second id 2, the third id 3, etc. When a controller is turned off that slot is freed ensuring that controllers will keep the same id while it is turned on even when controllers with lower ids are turned off.
</description>
</method>
+ <method name="set_rumble">
+ <return type="void">
+ </return>
+ <argument index="0" name="rumble" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
</methods>
<members>
<member name="controller_id" type="int" setter="set_controller_id" getter="get_controller_id">
+ The controller's id. The first controller that the [ARVRServer] detects will have id 1, the second id 2, the third id 3, etc. When a controller is turned off, it's slot is freed. This ensures controllers will keep the same id even when controllers with lower ids are turned off.
+ </member>
+ <member name="rumble" type="float" setter="set_rumble" getter="get_rumble">
</member>
</members>
<signals>
diff --git a/doc/classes/ARVRInterface.xml b/doc/classes/ARVRInterface.xml
index 1c2e761b57..e9f8857ec8 100644
--- a/doc/classes/ARVRInterface.xml
+++ b/doc/classes/ARVRInterface.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ARVRInterface" inherits="Reference" category="Core" version="3.0.alpha.custom_build">
+<class name="ARVRInterface" inherits="Reference" category="Core" version="3.0-alpha">
<brief_description>
Base class for ARVR interface implementation.
</brief_description>
@@ -33,7 +33,7 @@
Returns the name of this interface (OpenVR, OpenHMD, ARKit, etc).
</description>
</method>
- <method name="get_recommended_render_targetsize">
+ <method name="get_render_targetsize">
<return type="Vector2">
</return>
<description>
@@ -94,7 +94,7 @@
<argument index="0" name="initialized" type="bool">
</argument>
<description>
- Initialise/uninitilise this interface (same effect as calling intialize/uninitialize).
+ Initialize/uninitialize this interface (same effect as calling initialize/uninitialize).
</description>
</method>
<method name="set_is_primary">
@@ -139,7 +139,7 @@
This interface support AR (video background and real world tracking).
</constant>
<constant name="ARVR_EXTERNAL" value="8">
- This interface outputs to an external device, if the main viewport is used the on screen output is an unmodified buffer of either the left or right eye (stretched if the viewport size is not changed to the same aspect ratio of get_recommended_render_targetsize. Using a seperate viewport node frees up the main viewport for other purposes.
+ This interface outputs to an external device, if the main viewport is used the on screen output is an unmodified buffer of either the left or right eye (stretched if the viewport size is not changed to the same aspect ratio of get_render_targetsize. Using a seperate viewport node frees up the main viewport for other purposes.
</constant>
<constant name="EYE_MONO" value="0">
Mono output, this is mostly used internally when retrieving positioning information for our camera node or when stereo scopic rendering is not supported.
diff --git a/doc/classes/ARVROrigin.xml b/doc/classes/ARVROrigin.xml
index 28864bb3ae..8ad3793c80 100644
--- a/doc/classes/ARVROrigin.xml
+++ b/doc/classes/ARVROrigin.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ARVROrigin" inherits="Spatial" category="Core" version="3.0.alpha.custom_build">
+<class name="ARVROrigin" inherits="Spatial" category="Core" version="3.0-alpha">
<brief_description>
Our origin point in AR/VR.
</brief_description>
@@ -35,6 +35,8 @@
</methods>
<members>
<member name="world_scale" type="float" setter="set_world_scale" getter="get_world_scale">
+ Allows you to adjust the scale to your game's units. Most AR/VR platforms assume a scale of 1 game world unit = 1 meter in the real world.
+ Note that this method is a passthrough to the [ARVRServer] itself.
</member>
</members>
<constants>
diff --git a/doc/classes/ARVRPositionalTracker.xml b/doc/classes/ARVRPositionalTracker.xml
index 1379677344..2a2c6aa843 100644
--- a/doc/classes/ARVRPositionalTracker.xml
+++ b/doc/classes/ARVRPositionalTracker.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ARVRPositionalTracker" inherits="Object" category="Core" version="3.0.alpha.custom_build">
+<class name="ARVRPositionalTracker" inherits="Object" category="Core" version="3.0-alpha">
<brief_description>
A tracked object
</brief_description>
@@ -17,6 +17,7 @@
<return type="int" enum="ARVRPositionalTracker.TrackerHand">
</return>
<description>
+ Returns the hand holding this tracker, if known. See TRACKER_* constants.
</description>
</method>
<method name="get_joy_id" qualifiers="const">
@@ -47,6 +48,12 @@
Returns the position of the controller adjusted by world scale.
</description>
</method>
+ <method name="get_rumble" qualifiers="const">
+ <return type="float">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="get_tracks_orientation" qualifiers="const">
<return type="bool">
</return>
@@ -77,13 +84,28 @@
Type of tracker.
</description>
</method>
+ <method name="set_rumble">
+ <return type="void">
+ </return>
+ <argument index="0" name="rumble" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
</methods>
+ <members>
+ <member name="rumble" type="float" setter="set_rumble" getter="get_rumble">
+ </member>
+ </members>
<constants>
<constant name="TRACKER_HAND_UNKNOWN" value="0">
+ The hand this tracker is held in is unknown or not applicable.
</constant>
<constant name="TRACKER_LEFT_HAND" value="1">
+ This tracker is the left hand controller.
</constant>
<constant name="TRACKER_RIGHT_HAND" value="2">
+ This tracker is the right hand controller.
</constant>
</constants>
</class>
diff --git a/doc/classes/ARVRScriptInterface.xml b/doc/classes/ARVRScriptInterface.xml
deleted file mode 100644
index 182147a015..0000000000
--- a/doc/classes/ARVRScriptInterface.xml
+++ /dev/null
@@ -1,118 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ARVRScriptInterface" inherits="ARVRInterface" category="Core" version="3.0.alpha.custom_build">
- <brief_description>
- Base class for GDNative based ARVR interfaces.
- </brief_description>
- <description>
- This class is used as a base class/interface class for implementing GDNative based ARVR interfaces and as a result exposes more of the internals of the ARVR server.
- </description>
- <tutorials>
- </tutorials>
- <demos>
- </demos>
- <methods>
- <method name="_get_projection_for_eye" qualifiers="virtual">
- <return type="void">
- </return>
- <description>
- Should return the projection 4x4 matrix for the requested eye.
- </description>
- </method>
- <method name="commit_for_eye" qualifiers="virtual">
- <return type="void">
- </return>
- <argument index="0" name="eye" type="int">
- </argument>
- <argument index="1" name="render_target" type="RID">
- </argument>
- <description>
- Outputs a finished render buffer to the AR/VR device for the given eye.
- </description>
- </method>
- <method name="get_anchor_detection_is_enabled" qualifiers="virtual">
- <return type="bool">
- </return>
- <description>
- Returns true if achor detection is enabled (AR only).
- </description>
- </method>
- <method name="get_capabilities" qualifiers="virtual">
- <return type="int">
- </return>
- <description>
- Returns a combination of flags providing information about the capabilities of this interface.
- </description>
- </method>
- <method name="get_recommended_render_targetsize" qualifiers="virtual">
- <return type="Vector2">
- </return>
- <description>
- Returns the size at which we should render our scene to get optimal quality on the output device.
- </description>
- </method>
- <method name="get_tracking_status" qualifiers="virtual">
- <return type="int">
- </return>
- <description>
- If supported, returns the status of our tracking. This will allow you to provide feedback to the user whether there are issues with positional tracking.
- </description>
- </method>
- <method name="get_transform_for_eye" qualifiers="virtual">
- <return type="Transform">
- </return>
- <argument index="0" name="eye" type="int">
- </argument>
- <argument index="1" name="cam_transform" type="Transform">
- </argument>
- <description>
- Get the location and orientation transform used when rendering a specific eye.
- </description>
- </method>
- <method name="initialize" qualifiers="virtual">
- <return type="bool">
- </return>
- <description>
- Initialize this interface.
- </description>
- </method>
- <method name="is_initialized" qualifiers="virtual">
- <return type="bool">
- </return>
- <description>
- Returns true if this interface has been initialized and is active.
- </description>
- </method>
- <method name="is_stereo" qualifiers="virtual">
- <return type="bool">
- </return>
- <description>
- Returns true if we require stereoscopic rendering for this interface.
- </description>
- </method>
- <method name="process" qualifiers="virtual">
- <return type="void">
- </return>
- <description>
- Gets called before rendering each frame so tracking data gets updated in time.
- </description>
- </method>
- <method name="set_anchor_detection_is_enabled" qualifiers="virtual">
- <return type="void">
- </return>
- <argument index="0" name="enabled" type="bool">
- </argument>
- <description>
- Enables anchor detection, this is used on AR interfaces and enables the extra logic that will detect planes, features, objects, etc. and adds/modifies anchor points.
- </description>
- </method>
- <method name="uninitialize" qualifiers="virtual">
- <return type="void">
- </return>
- <description>
- Turn this interface off.
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
diff --git a/doc/classes/ARVRServer.xml b/doc/classes/ARVRServer.xml
index 6a7262bd14..bee95ea072 100644
--- a/doc/classes/ARVRServer.xml
+++ b/doc/classes/ARVRServer.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ARVRServer" inherits="Object" category="Core" version="3.0.alpha.custom_build">
+<class name="ARVRServer" inherits="Object" category="Core" version="3.0-alpha">
<brief_description>
This is our AR/VR Server.
</brief_description>
@@ -11,15 +11,6 @@
<demos>
</demos>
<methods>
- <method name="add_interface">
- <return type="void">
- </return>
- <argument index="0" name="arg0" type="ARVRInterface">
- </argument>
- <description>
- Mostly exposed for GDNative based interfaces, this is called to register an available interface with the AR/VR server.
- </description>
- </method>
<method name="center_on_hmd">
<return type="void">
</return>
@@ -61,6 +52,13 @@
Get the number of interfaces currently registered with the AR/VR server. If you're game supports multiple AR/VR platforms you can look throught the available interface and either present the user with a selection or simply try an initialize each interface and use the first one that returns true.
</description>
</method>
+ <method name="get_interfaces" qualifiers="const">
+ <return type="Array">
+ </return>
+ <description>
+ Returns a list of available interfaces with both id and name of the interface.
+ </description>
+ </method>
<method name="get_reference_frame" qualifiers="const">
<return type="Transform">
</return>
@@ -91,19 +89,10 @@
Returns our world scale (see ARVROrigin for more information).
</description>
</method>
- <method name="remove_interface">
- <return type="void">
- </return>
- <argument index="0" name="arg0" type="ARVRInterface">
- </argument>
- <description>
- Removes a registered interface, again exposed mostly for GDNative based interfaces.
- </description>
- </method>
<method name="set_primary_interface">
<return type="void">
</return>
- <argument index="0" name="arg0" type="ARVRInterface">
+ <argument index="0" name="interface" type="ARVRInterface">
</argument>
<description>
Changes the primary interface to the specified interface. Again mostly exposed for GDNative interfaces.
@@ -121,6 +110,7 @@
</methods>
<members>
<member name="world_scale" type="float" setter="set_world_scale" getter="get_world_scale">
+ Allows you to adjust the scale to your game's units. Most AR/VR platforms assume a scale of 1 game world unit = 1 meter in the real world.
</member>
</members>
<signals>
@@ -171,14 +161,14 @@
<constant name="TRACKER_ANCHOR" value="4">
Our tracker tracks the location and size of an AR anchor.
</constant>
- <constant name="TRACKER_UNKNOWN" value="128">
- Used internally if we haven't set the tracker type yet.
- </constant>
<constant name="TRACKER_ANY_KNOWN" value="127">
Used internally to filter trackers of any known type.
</constant>
+ <constant name="TRACKER_UNKNOWN" value="128">
+ Used internally if we haven't set the tracker type yet.
+ </constant>
<constant name="TRACKER_ANY" value="255">
- Used interally to select all trackers.
+ Used internally to select all trackers.
</constant>
</constants>
</class>
diff --git a/doc/classes/AStar.xml b/doc/classes/AStar.xml
index 9b15afbbd4..ceb3c907a6 100644
--- a/doc/classes/AStar.xml
+++ b/doc/classes/AStar.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AStar" inherits="Reference" category="Core" version="3.0.alpha.custom_build">
+<class name="AStar" inherits="Reference" category="Core" version="3.0-alpha">
<brief_description>
AStar class representation that uses vectors as edges.
</brief_description>
@@ -50,6 +50,7 @@
as.add_point(1, Vector3(1,0,0), 4) # Adds the point (1,0,0) with weight_scale=4 and id=1
[/codeblock]
+ If there already exists a point for the given id, its position and weight scale are updated to the given values.
</description>
</method>
<method name="are_points_connected" qualifiers="const">
@@ -107,7 +108,7 @@
<return type="int">
</return>
<description>
- Returns an id with no point associated to it.
+ Returns the next available point id with no point associated to it.
</description>
</method>
<method name="get_closest_point" qualifiers="const">
@@ -167,6 +168,28 @@
If you change the 2nd point's weight to 3, then the result will be [code][1, 4, 3][/code] instead, because now even though the distance is longer, it's "easier" to get through point 4 than through point 2.
</description>
</method>
+ <method name="get_point_connections">
+ <return type="PoolIntArray">
+ </return>
+ <argument index="0" name="arg0" type="int">
+ </argument>
+ <description>
+ Returns an array with the ids of the points that form the connect with the given point.
+ [codeblock]
+ var as = AStar.new()
+
+ as.add_point(1, Vector3(0,0,0))
+ as.add_point(2, Vector3(0,1,0))
+ as.add_point(3, Vector3(1,1,0))
+ as.add_point(4, Vector3(2,0,0))
+
+ as.connect_points(1, 2, true)
+ as.connect_points(1, 3, true)
+
+ var neighbors = as.get_point_connections(1) # returns [2, 3]
+ [/codeblock]
+ </description>
+ </method>
<method name="get_point_path">
<return type="PoolVector3Array">
</return>
@@ -220,6 +243,28 @@
Removes the point associated with the given id from the points pool.
</description>
</method>
+ <method name="set_point_position">
+ <return type="void">
+ </return>
+ <argument index="0" name="id" type="int">
+ </argument>
+ <argument index="1" name="position" type="Vector3">
+ </argument>
+ <description>
+ Sets the position for the point with the given id.
+ </description>
+ </method>
+ <method name="set_point_weight_scale">
+ <return type="void">
+ </return>
+ <argument index="0" name="id" type="int">
+ </argument>
+ <argument index="1" name="weight_scale" type="float">
+ </argument>
+ <description>
+ Sets the [code]weight_scale[/code] for the point with the given id.
+ </description>
+ </method>
</methods>
<constants>
</constants>
diff --git a/doc/classes/AcceptDialog.xml b/doc/classes/AcceptDialog.xml
index 4244e66a35..2292d54756 100644
--- a/doc/classes/AcceptDialog.xml
+++ b/doc/classes/AcceptDialog.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AcceptDialog" inherits="WindowDialog" category="Core" version="3.0.alpha.custom_build">
+<class name="AcceptDialog" inherits="WindowDialog" category="Core" version="3.0-alpha">
<brief_description>
Base dialog for user notification.
</brief_description>
@@ -92,8 +92,10 @@
</methods>
<members>
<member name="dialog_hide_on_ok" type="bool" setter="set_hide_on_ok" getter="get_hide_on_ok">
+ If [code]true[/code] the dialog is hidden when accepted. Default value: [code]true[/code].
</member>
<member name="dialog_text" type="String" setter="set_text" getter="get_text">
+ The text displayed by this dialog.
</member>
</members>
<signals>
diff --git a/doc/classes/AnimatedSprite.xml b/doc/classes/AnimatedSprite.xml
index dce7bf283a..984eb47f12 100644
--- a/doc/classes/AnimatedSprite.xml
+++ b/doc/classes/AnimatedSprite.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AnimatedSprite" inherits="Node2D" category="Core" version="3.0.alpha.custom_build">
+<class name="AnimatedSprite" inherits="Node2D" category="Core" version="3.0-alpha">
<brief_description>
Sprite node that can use multiple textures for animation.
</brief_description>
diff --git a/doc/classes/AnimatedSprite3D.xml b/doc/classes/AnimatedSprite3D.xml
index b0bb7bb6ab..0d8e2fc433 100644
--- a/doc/classes/AnimatedSprite3D.xml
+++ b/doc/classes/AnimatedSprite3D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AnimatedSprite3D" inherits="SpriteBase3D" category="Core" version="3.0.alpha.custom_build">
+<class name="AnimatedSprite3D" inherits="SpriteBase3D" category="Core" version="3.0-alpha">
<brief_description>
2D sprite node in 3D world, that can use multiple 2D textures for animation.
</brief_description>
diff --git a/doc/classes/Animation.xml b/doc/classes/Animation.xml
index d853345268..677976f1d3 100644
--- a/doc/classes/Animation.xml
+++ b/doc/classes/Animation.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Animation" inherits="Resource" category="Core" version="3.0.alpha.custom_build">
+<class name="Animation" inherits="Resource" category="Core" version="3.0-alpha">
<brief_description>
Contains data used to animate everything in the engine.
</brief_description>
diff --git a/doc/classes/AnimationPlayer.xml b/doc/classes/AnimationPlayer.xml
index 74a7f6c8a4..f0a1f7f634 100644
--- a/doc/classes/AnimationPlayer.xml
+++ b/doc/classes/AnimationPlayer.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AnimationPlayer" inherits="Node" category="Core" version="3.0.alpha.custom_build">
+<class name="AnimationPlayer" inherits="Node" category="Core" version="3.0-alpha">
<brief_description>
Container and player of [Animation] resources.
</brief_description>
@@ -380,11 +380,11 @@
</signal>
</signals>
<constants>
- <constant name="ANIMATION_PROCESS_FIXED" value="0">
- Process animation on fixed process. This is specially useful when animating kinematic bodies.
+ <constant name="ANIMATION_PROCESS_PHYSICS" value="0">
+ Process animation during the physics process. This is especially useful when animating physics bodies.
</constant>
<constant name="ANIMATION_PROCESS_IDLE" value="1">
- Process animation on idle process.
+ Process animation during the idle process.
</constant>
</constants>
</class>
diff --git a/doc/classes/AnimationTreePlayer.xml b/doc/classes/AnimationTreePlayer.xml
index f088d21e41..413606dbaa 100644
--- a/doc/classes/AnimationTreePlayer.xml
+++ b/doc/classes/AnimationTreePlayer.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AnimationTreePlayer" inherits="Node" category="Core" version="3.0.alpha.custom_build">
+<class name="AnimationTreePlayer" inherits="Node" category="Core" version="3.0-alpha">
<brief_description>
Animation Player that uses a node graph for the blending.
</brief_description>
@@ -659,7 +659,7 @@
<constant name="NODE_TRANSITION" value="9">
Transition node.
</constant>
- <constant name="ANIMATION_PROCESS_FIXED" value="0">
+ <constant name="ANIMATION_PROCESS_PHYSICS" value="0">
</constant>
<constant name="ANIMATION_PROCESS_IDLE" value="1">
</constant>
diff --git a/doc/classes/Area.xml b/doc/classes/Area.xml
index 8797575038..85afa24214 100644
--- a/doc/classes/Area.xml
+++ b/doc/classes/Area.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Area" inherits="CollisionObject" category="Core" version="3.0.alpha.custom_build">
+<class name="Area" inherits="CollisionObject" category="Core" version="3.0-alpha">
<brief_description>
General purpose area node for detection and 3D physics influence.
</brief_description>
@@ -88,14 +88,14 @@
<return type="Array">
</return>
<description>
- Returns a list of intersecting [Area]\ s.
+ Returns a list of intersecting [code]Area[/code]s.
</description>
</method>
<method name="get_overlapping_bodies" qualifiers="const">
<return type="Array">
</return>
<description>
- Returns a list of intersecting [PhysicsBody]\ s.
+ Returns a list of intersecting [PhysicsBody]s.
</description>
</method>
<method name="get_priority" qualifiers="const">
diff --git a/doc/classes/Area2D.xml b/doc/classes/Area2D.xml
index 0cbc079962..5869e2238e 100644
--- a/doc/classes/Area2D.xml
+++ b/doc/classes/Area2D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Area2D" inherits="CollisionObject2D" category="Core" version="3.0.alpha.custom_build">
+<class name="Area2D" inherits="CollisionObject2D" category="Core" version="3.0-alpha">
<brief_description>
2D area for detection and 2D physics influence.
</brief_description>
@@ -88,14 +88,14 @@
<return type="Array">
</return>
<description>
- Returns a list of intersecting [Area2D]\ s.
+ Returns a list of intersecting [code]Area2D[/code]s.
</description>
</method>
<method name="get_overlapping_bodies" qualifiers="const">
<return type="Array">
</return>
<description>
- Returns a list of intersecting [PhysicsBody2D]\ s.
+ Returns a list of intersecting [PhysicsBody2D]s.
</description>
</method>
<method name="get_priority" qualifiers="const">
diff --git a/doc/classes/Array.xml b/doc/classes/Array.xml
index 9542c83eaf..3bb40755a6 100644
--- a/doc/classes/Array.xml
+++ b/doc/classes/Array.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Array" category="Built-In Types" version="3.0.alpha.custom_build">
+<class name="Array" category="Built-In Types" version="3.0-alpha">
<brief_description>
Generic array datatype.
</brief_description>
@@ -82,6 +82,8 @@
</description>
</method>
<method name="back">
+ <return type="var">
+ </return>
<description>
Returns the last element of the array if the array is not empty (size&gt;0).
</description>
@@ -104,6 +106,7 @@
<return type="Array">
</return>
<description>
+ Returns a copy of this [code]Array[/code].
</description>
</method>
<method name="empty">
@@ -141,6 +144,8 @@
</description>
</method>
<method name="front">
+ <return type="var">
+ </return>
<description>
Returns the first element of the array if the array is not empty (size&gt;0).
</description>
@@ -178,15 +183,19 @@
</method>
<method name="invert">
<description>
- Reverse the order of the elements in the array (so first element will now be the last).
+ Reverse the order of the elements in the array (so first element will now be the last) and return reference to the array.
</description>
</method>
<method name="pop_back">
+ <return type="var">
+ </return>
<description>
Remove the last element of the array.
</description>
</method>
<method name="pop_front">
+ <return type="var">
+ </return>
<description>
Remove the first element of the array.
</description>
@@ -239,7 +248,7 @@
</method>
<method name="sort">
<description>
- Sort the array using natural order.
+ Sort the array using natural order and return reference to the array.
</description>
</method>
<method name="sort_custom">
@@ -248,7 +257,33 @@
<argument index="1" name="func" type="String">
</argument>
<description>
- Sort 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 true if the first argument is less than the second, and return false otherwise. Note: you cannot randomize the return value as the heapsort algorithm expects a deterministic result. Doing so will result in unexpected behavior.
+ Sort the array using a custom method and return reference to the array. 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 true if the first argument is less than the second, and return false otherwise. Note: you cannot randomize the return value as the heapsort algorithm expects a deterministic result. Doing so will result in unexpected behavior.
+ </description>
+ </method>
+ <method name="bsearch">
+ <return type="int">
+ </return>
+ <argument index="0" name="value" type="var">
+ </argument>
+ <argument index="1" name="before" type="bool" default="true">
+ </argument>
+ <description>
+ Finds the index of an existing value (or the insertion index that maintains sorting order, if the value is not yet present in the array) using binary search. Optionally, a before specifier can be passed. If false, the returned index comes after all existing entries of the value in the array. Note that calling bsearch on an unsorted array results in unexpected behavior.
+ </description>
+ </method>
+ <method name="bsearch_custom">
+ <return type="int">
+ </return>
+ <argument index="0" name="value" type="var">
+ </argument>
+ <argument index="1" name="obj" type="Object">
+ </argument>
+ <argument index="2" name="func" type="String">
+ </argument>
+ <argument index="3" name="before" type="bool" default="true">
+ </argument>
+ <description>
+ Finds the index of an existing value (or the insertion index that maintains sorting order, if the value is not yet present in the array) using binary search and a custom comparison method. Optionally, a before specifier can be passed. If false, the returned index comes after all existing entries of the value in the array. The custom method receives two arguments (an element from the array and the value searched for) and must return true if the first argument is less than the second, and return false otherwise. Note that calling bsearch on an unsorted array results in unexpected behavior.
</description>
</method>
</methods>
diff --git a/doc/classes/ArrayMesh.xml b/doc/classes/ArrayMesh.xml
index 36f8494c44..6c9b191371 100644
--- a/doc/classes/ArrayMesh.xml
+++ b/doc/classes/ArrayMesh.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ArrayMesh" inherits="Mesh" category="Core" version="3.0.alpha.custom_build">
+<class name="ArrayMesh" inherits="Mesh" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
@@ -66,7 +66,7 @@
</description>
</method>
<method name="get_custom_aabb" qualifiers="const">
- <return type="Rect3">
+ <return type="AABB">
</return>
<description>
</description>
@@ -75,7 +75,7 @@
<return type="int">
</return>
<description>
- Return the amount of surfaces that the [ArrayMesh] holds.
+ Return the amount of surfaces that the [code]ArrayMesh[/code] holds.
</description>
</method>
<method name="regen_normalmaps">
@@ -95,7 +95,7 @@
<method name="set_custom_aabb">
<return type="void">
</return>
- <argument index="0" name="aabb" type="Rect3">
+ <argument index="0" name="aabb" type="AABB">
</argument>
<description>
</description>
@@ -199,6 +199,18 @@
Set a [Material] for a given surface. Surface will be rendered using this material.
</description>
</method>
+ <method name="surface_update_region">
+ <return type="void">
+ </return>
+ <argument index="0" name="surf_idx" type="int">
+ </argument>
+ <argument index="1" name="offset" type="int">
+ </argument>
+ <argument index="2" name="data" type="PoolByteArray">
+ </argument>
+ <description>
+ </description>
+ </method>
</methods>
<constants>
<constant name="NO_INDEX_ARRAY" value="-1" enum="">
diff --git a/doc/classes/AtlasTexture.xml b/doc/classes/AtlasTexture.xml
index 179f78f16f..7cb934889e 100644
--- a/doc/classes/AtlasTexture.xml
+++ b/doc/classes/AtlasTexture.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AtlasTexture" inherits="Texture" category="Core" version="3.0.alpha.custom_build">
+<class name="AtlasTexture" inherits="Texture" category="Core" version="3.0-alpha">
<brief_description>
Packs multiple small textures in a single, bigger one. Helps to optimize video memory costs and render calls.
</brief_description>
@@ -30,6 +30,12 @@
<description>
</description>
</method>
+ <method name="has_filter_clip" qualifiers="const">
+ <return type="bool">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="set_atlas">
<return type="void">
</return>
@@ -38,6 +44,14 @@
<description>
</description>
</method>
+ <method name="set_filter_clip">
+ <return type="void">
+ </return>
+ <argument index="0" name="enable" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="set_margin">
<return type="void">
</return>
@@ -59,6 +73,8 @@
<member name="atlas" type="Texture" setter="set_atlas" getter="get_atlas">
The texture that contains the atlas. Can be any [Texture] subtype.
</member>
+ <member name="filter_clip" type="bool" setter="set_filter_clip" getter="has_filter_clip">
+ </member>
<member name="margin" type="Rect2" setter="set_margin" getter="get_margin">
The margin around the region. The [Rect2]'s 'size' parameter ('w' and 'h' in the editor) resizes the texture so it fits within the margin.
</member>
diff --git a/doc/classes/AudioBusLayout.xml b/doc/classes/AudioBusLayout.xml
index e5b17b8dfb..c539c7500b 100644
--- a/doc/classes/AudioBusLayout.xml
+++ b/doc/classes/AudioBusLayout.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AudioBusLayout" inherits="Resource" category="Core" version="3.0.alpha.custom_build">
+<class name="AudioBusLayout" inherits="Resource" category="Core" version="3.0-alpha">
<brief_description>
+ Stores information about the audiobusses.
</brief_description>
<description>
+ Stores position, muting, solo, bypass, effects, effect position, volume, and the connections between busses. See [AudioServer] for usage.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/AudioEffect.xml b/doc/classes/AudioEffect.xml
index 627d243f25..804cba82fe 100644
--- a/doc/classes/AudioEffect.xml
+++ b/doc/classes/AudioEffect.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AudioEffect" inherits="Resource" category="Core" version="3.0.alpha.custom_build">
+<class name="AudioEffect" inherits="Resource" category="Core" version="3.0-alpha">
<brief_description>
Audio Effect For Audio.
</brief_description>
diff --git a/doc/classes/AudioEffectAmplify.xml b/doc/classes/AudioEffectAmplify.xml
index 35d7991833..0149e03de4 100644
--- a/doc/classes/AudioEffectAmplify.xml
+++ b/doc/classes/AudioEffectAmplify.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AudioEffectAmplify" inherits="AudioEffect" category="Core" version="3.0.alpha.custom_build">
+<class name="AudioEffectAmplify" inherits="AudioEffect" category="Core" version="3.0-alpha">
<brief_description>
Adds a Amplify audio effect to an Audio bus.
Increases or decreases the volume of the selected audio bus.
diff --git a/doc/classes/AudioEffectBandLimitFilter.xml b/doc/classes/AudioEffectBandLimitFilter.xml
index 96f95fbffd..f83cf8ba72 100644
--- a/doc/classes/AudioEffectBandLimitFilter.xml
+++ b/doc/classes/AudioEffectBandLimitFilter.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AudioEffectBandLimitFilter" inherits="AudioEffectFilter" category="Core" version="3.0.alpha.custom_build">
+<class name="AudioEffectBandLimitFilter" inherits="AudioEffectFilter" category="Core" version="3.0-alpha">
<brief_description>
+ Adds a band limit filter to the Audio Bus.
</brief_description>
<description>
+ Limits the frequencies in a range around the [member cutoff_hz] and allows frequencies outside of this range to pass.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/AudioEffectBandPassFilter.xml b/doc/classes/AudioEffectBandPassFilter.xml
index 4437961cc6..e922d3e821 100644
--- a/doc/classes/AudioEffectBandPassFilter.xml
+++ b/doc/classes/AudioEffectBandPassFilter.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AudioEffectBandPassFilter" inherits="AudioEffectFilter" category="Core" version="3.0.alpha.custom_build">
+<class name="AudioEffectBandPassFilter" inherits="AudioEffectFilter" category="Core" version="3.0-alpha">
<brief_description>
+ Adds a band pass filter to the Audio Bus.
</brief_description>
<description>
+ Attenuates the frequencies inside of a range around the [member cutoff_hz] and cuts frequencies outside of this band.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/AudioEffectChorus.xml b/doc/classes/AudioEffectChorus.xml
index b9f27678ec..40bac419d6 100644
--- a/doc/classes/AudioEffectChorus.xml
+++ b/doc/classes/AudioEffectChorus.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AudioEffectChorus" inherits="AudioEffect" category="Core" version="3.0.alpha.custom_build">
+<class name="AudioEffectChorus" inherits="AudioEffect" category="Core" version="3.0-alpha">
<brief_description>
Adds a chorus audio effect.
</brief_description>
diff --git a/doc/classes/AudioEffectCompressor.xml b/doc/classes/AudioEffectCompressor.xml
index 9d7e25dbf2..ae877f145a 100644
--- a/doc/classes/AudioEffectCompressor.xml
+++ b/doc/classes/AudioEffectCompressor.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AudioEffectCompressor" inherits="AudioEffect" category="Core" version="3.0.alpha.custom_build">
+<class name="AudioEffectCompressor" inherits="AudioEffect" category="Core" version="3.0-alpha">
<brief_description>
Adds a Compressor audio effect to an Audio bus.
Reduces sounds that exceed a certain threshold level, smooths out the dynamics and increases the overall volume.
diff --git a/doc/classes/AudioEffectDelay.xml b/doc/classes/AudioEffectDelay.xml
index 9dc61883ab..a9251b6cf0 100644
--- a/doc/classes/AudioEffectDelay.xml
+++ b/doc/classes/AudioEffectDelay.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AudioEffectDelay" inherits="AudioEffect" category="Core" version="3.0.alpha.custom_build">
+<class name="AudioEffectDelay" inherits="AudioEffect" category="Core" version="3.0-alpha">
<brief_description>
Adds a Delay audio effect to an Audio bus. Plays input signal back after a period of time.
Two tap delay and feedback options.
diff --git a/doc/classes/AudioEffectDistortion.xml b/doc/classes/AudioEffectDistortion.xml
index 1a6aa1d2b6..25df71d5f5 100644
--- a/doc/classes/AudioEffectDistortion.xml
+++ b/doc/classes/AudioEffectDistortion.xml
@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AudioEffectDistortion" inherits="AudioEffect" category="Core" version="3.0.alpha.custom_build">
+<class name="AudioEffectDistortion" inherits="AudioEffect" category="Core" version="3.0-alpha">
<brief_description>
Adds a Distortion audio effect to an Audio bus.
Modify the sound to make it dirty.
</brief_description>
<description>
- Modify the sound and make it dirty. Differents types available : clip, tan, lofi (bit crushing), overdrive, or waveshape.
+ Modify the sound and make it dirty. Different types are available : clip, tan, lofi (bit crushing), overdrive, or waveshape.
By distorting the waveform the frequency content change, which will often make the sound "crunchy" or "abrasive". For games, it can simulate sound coming from some saturated device or speaker very efficiently.
</description>
<tutorials>
diff --git a/doc/classes/AudioEffectEQ.xml b/doc/classes/AudioEffectEQ.xml
index 246f6b882e..f8b4d426f4 100644
--- a/doc/classes/AudioEffectEQ.xml
+++ b/doc/classes/AudioEffectEQ.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AudioEffectEQ" inherits="AudioEffect" category="Core" version="3.0.alpha.custom_build">
+<class name="AudioEffectEQ" inherits="AudioEffect" category="Core" version="3.0-alpha">
<brief_description>
Base class for audio equalizers. Gives you control over frequencies.
Use it to create a custom equalizer if [AudioEffectEQ6], [AudioEffectEQ10] or [AudioEffectEQ21] don't fit your needs.
diff --git a/doc/classes/AudioEffectEQ10.xml b/doc/classes/AudioEffectEQ10.xml
index 7a29f4cc0b..95801ef40c 100644
--- a/doc/classes/AudioEffectEQ10.xml
+++ b/doc/classes/AudioEffectEQ10.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AudioEffectEQ10" inherits="AudioEffectEQ" category="Core" version="3.0.alpha.custom_build">
+<class name="AudioEffectEQ10" inherits="AudioEffectEQ" category="Core" version="3.0-alpha">
<brief_description>
Adds a 10-band equalizer audio effect to an Audio bus. Gives you control over frequencies from 31 Hz to 16000 Hz.
Each frequency can be modulated between -60/+24 dB.
diff --git a/doc/classes/AudioEffectEQ21.xml b/doc/classes/AudioEffectEQ21.xml
index 327f5a291a..b62e0458f7 100644
--- a/doc/classes/AudioEffectEQ21.xml
+++ b/doc/classes/AudioEffectEQ21.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AudioEffectEQ21" inherits="AudioEffectEQ" category="Core" version="3.0.alpha.custom_build">
+<class name="AudioEffectEQ21" inherits="AudioEffectEQ" category="Core" version="3.0-alpha">
<brief_description>
Adds a 21-band equalizer audio effect to an Audio bus. Gives you control over frequencies from 22 Hz to 22000 Hz.
Each frequency can be modulated between -60/+24 dB.
diff --git a/doc/classes/AudioEffectEQ6.xml b/doc/classes/AudioEffectEQ6.xml
index bc05535041..f679ccede4 100644
--- a/doc/classes/AudioEffectEQ6.xml
+++ b/doc/classes/AudioEffectEQ6.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AudioEffectEQ6" inherits="AudioEffectEQ" category="Core" version="3.0.alpha.custom_build">
+<class name="AudioEffectEQ6" inherits="AudioEffectEQ" category="Core" version="3.0-alpha">
<brief_description>
Adds a 6-band equalizer audio effect to an Audio bus. Gives you control over frequencies from 32 Hz to 10000 Hz.
Each frequency can be modulated between -60/+24 dB.
diff --git a/doc/classes/AudioEffectFilter.xml b/doc/classes/AudioEffectFilter.xml
index 17aa01d60a..244c07a6da 100644
--- a/doc/classes/AudioEffectFilter.xml
+++ b/doc/classes/AudioEffectFilter.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AudioEffectFilter" inherits="AudioEffect" category="Core" version="3.0.alpha.custom_build">
+<class name="AudioEffectFilter" inherits="AudioEffect" category="Core" version="3.0-alpha">
<brief_description>
+ Adds a filter to the Audio Bus.
</brief_description>
<description>
+ Allows frequencies other than the [member cutoff_hz] to pass.
</description>
<tutorials>
</tutorials>
@@ -68,12 +70,15 @@
</methods>
<members>
<member name="cutoff_hz" type="float" setter="set_cutoff" getter="get_cutoff">
+ Threshold frequency for the filter.
</member>
- <member name="dB" type="int" setter="set_db" getter="get_db" enum="AudioEffectFilter.FilterDB">
+ <member name="db" type="int" setter="set_db" getter="get_db" enum="AudioEffectFilter.FilterDB">
</member>
<member name="gain" type="float" setter="set_gain" getter="get_gain">
+ Gain amount of the frequencies after the filter.
</member>
<member name="resonance" type="float" setter="set_resonance" getter="get_resonance">
+ Amount of boost in the overtones near the cutoff frequency.
</member>
</members>
<constants>
diff --git a/doc/classes/AudioEffectHighPassFilter.xml b/doc/classes/AudioEffectHighPassFilter.xml
index 641f7cfee2..4718d4d4a5 100644
--- a/doc/classes/AudioEffectHighPassFilter.xml
+++ b/doc/classes/AudioEffectHighPassFilter.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AudioEffectHighPassFilter" inherits="AudioEffectFilter" category="Core" version="3.0.alpha.custom_build">
+<class name="AudioEffectHighPassFilter" inherits="AudioEffectFilter" category="Core" version="3.0-alpha">
<brief_description>
+ Adds a high pass filter to the Audio Bus.
</brief_description>
<description>
+ Cuts frequencies lower than the [member cutoff_hz] and allows higher frequencies to pass.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/AudioEffectHighShelfFilter.xml b/doc/classes/AudioEffectHighShelfFilter.xml
index a2504d6808..62ff3d9366 100644
--- a/doc/classes/AudioEffectHighShelfFilter.xml
+++ b/doc/classes/AudioEffectHighShelfFilter.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AudioEffectHighShelfFilter" inherits="AudioEffectFilter" category="Core" version="3.0.alpha.custom_build">
+<class name="AudioEffectHighShelfFilter" inherits="AudioEffectFilter" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/AudioEffectLimiter.xml b/doc/classes/AudioEffectLimiter.xml
index 5209f290b1..ebed589829 100644
--- a/doc/classes/AudioEffectLimiter.xml
+++ b/doc/classes/AudioEffectLimiter.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AudioEffectLimiter" inherits="AudioEffect" category="Core" version="3.0.alpha.custom_build">
+<class name="AudioEffectLimiter" inherits="AudioEffect" category="Core" version="3.0-alpha">
<brief_description>
Adds a soft clip Limiter audio effect to an Audio bus.
</brief_description>
diff --git a/doc/classes/AudioEffectLowPassFilter.xml b/doc/classes/AudioEffectLowPassFilter.xml
index fcaf32d761..9f9ecc98b1 100644
--- a/doc/classes/AudioEffectLowPassFilter.xml
+++ b/doc/classes/AudioEffectLowPassFilter.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AudioEffectLowPassFilter" inherits="AudioEffectFilter" category="Core" version="3.0.alpha.custom_build">
+<class name="AudioEffectLowPassFilter" inherits="AudioEffectFilter" category="Core" version="3.0-alpha">
<brief_description>
+ Adds a low pass filter to the Audio Bus.
</brief_description>
<description>
+ Cuts frequencies higher than the [member cutoff_hz] and allows lower frequencies to pass.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/AudioEffectLowShelfFilter.xml b/doc/classes/AudioEffectLowShelfFilter.xml
index 8cf1a63c81..c74d1bc479 100644
--- a/doc/classes/AudioEffectLowShelfFilter.xml
+++ b/doc/classes/AudioEffectLowShelfFilter.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AudioEffectLowShelfFilter" inherits="AudioEffectFilter" category="Core" version="3.0.alpha.custom_build">
+<class name="AudioEffectLowShelfFilter" inherits="AudioEffectFilter" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/AudioEffectNotchFilter.xml b/doc/classes/AudioEffectNotchFilter.xml
index f90577fa5a..6407fc8431 100644
--- a/doc/classes/AudioEffectNotchFilter.xml
+++ b/doc/classes/AudioEffectNotchFilter.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AudioEffectNotchFilter" inherits="AudioEffectFilter" category="Core" version="3.0.alpha.custom_build">
+<class name="AudioEffectNotchFilter" inherits="AudioEffectFilter" category="Core" version="3.0-alpha">
<brief_description>
+ Adds a notch filter to the Audio Bus.
</brief_description>
<description>
+ Attenuates frequencies in a narrow band around the [member cutoff_hz] and cuts frequencies outside of this range.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/AudioEffectPanner.xml b/doc/classes/AudioEffectPanner.xml
index 56b39a36c6..46be7c1696 100644
--- a/doc/classes/AudioEffectPanner.xml
+++ b/doc/classes/AudioEffectPanner.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AudioEffectPanner" inherits="AudioEffect" category="Core" version="3.0.alpha.custom_build">
+<class name="AudioEffectPanner" inherits="AudioEffect" category="Core" version="3.0-alpha">
<brief_description>
Adds a Panner audio effect to an Audio bus. Pans sound left or right.
</brief_description>
diff --git a/doc/classes/AudioEffectPhaser.xml b/doc/classes/AudioEffectPhaser.xml
index bd9067471b..f413366fc7 100644
--- a/doc/classes/AudioEffectPhaser.xml
+++ b/doc/classes/AudioEffectPhaser.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AudioEffectPhaser" inherits="AudioEffect" category="Core" version="3.0.alpha.custom_build">
+<class name="AudioEffectPhaser" inherits="AudioEffect" category="Core" version="3.0-alpha">
<brief_description>
Adds a Phaser audio effect to an Audio bus.
Combines the original signal with a copy that is slightly out of phase with the original.
diff --git a/doc/classes/AudioEffectPitchShift.xml b/doc/classes/AudioEffectPitchShift.xml
index edcb54e09e..490aacbc8e 100644
--- a/doc/classes/AudioEffectPitchShift.xml
+++ b/doc/classes/AudioEffectPitchShift.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AudioEffectPitchShift" inherits="AudioEffect" category="Core" version="3.0.alpha.custom_build">
+<class name="AudioEffectPitchShift" inherits="AudioEffect" category="Core" version="3.0-alpha">
<brief_description>
Adds a Pitch shift audio effect to an Audio bus.
Raises or lowers the pitch of original sound.
diff --git a/doc/classes/AudioEffectReverb.xml b/doc/classes/AudioEffectReverb.xml
index 4cda24530b..e0567a48c7 100644
--- a/doc/classes/AudioEffectReverb.xml
+++ b/doc/classes/AudioEffectReverb.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AudioEffectReverb" inherits="AudioEffect" category="Core" version="3.0.alpha.custom_build">
+<class name="AudioEffectReverb" inherits="AudioEffect" category="Core" version="3.0-alpha">
<brief_description>
Adds a Reverb audio effect to an Audio bus.
Simulates the sound of acoustic environments such as rooms, concert halls, caverns, or an open spaces.
@@ -136,7 +136,7 @@
High-pass filter passes signals with a frequency higher than a certain cutoff frequency and attenuates signals with frequencies lower than the cutoff frequency. Value can range from 0 to 1. Default value: [code]0[/code].
</member>
<member name="predelay_feedback" type="float" setter="set_predelay_msec" getter="get_predelay_msec">
- Output percent of predelay. Value can range from 0 to 1. Default value: [code]1[/code].
+ Output percent of predelay. Value can range from 0 to 1. Default value: [code]1[/code].
</member>
<member name="predelay_msec" type="float" setter="set_predelay_msec" getter="get_predelay_msec">
Time between the original signal and the early reflections of the reverb signal. Default value: [code]150ms[/code].
diff --git a/doc/classes/AudioEffectStereoEnhance.xml b/doc/classes/AudioEffectStereoEnhance.xml
index 345d019d85..eb17056813 100644
--- a/doc/classes/AudioEffectStereoEnhance.xml
+++ b/doc/classes/AudioEffectStereoEnhance.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AudioEffectStereoEnhance" inherits="AudioEffect" category="Core" version="3.0.alpha.custom_build">
+<class name="AudioEffectStereoEnhance" inherits="AudioEffect" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/AudioServer.xml b/doc/classes/AudioServer.xml
index 768987fd0b..83a06bcd4d 100644
--- a/doc/classes/AudioServer.xml
+++ b/doc/classes/AudioServer.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AudioServer" inherits="Object" category="Core" version="3.0.alpha.custom_build">
+<class name="AudioServer" inherits="Object" category="Core" version="3.0-alpha">
<brief_description>
Server interface for low level audio access.
</brief_description>
@@ -17,6 +17,7 @@
<argument index="0" name="at_position" type="int" default="-1">
</argument>
<description>
+ Adds a bus at [code]at_position[/code].
</description>
</method>
<method name="add_bus_effect">
@@ -29,18 +30,21 @@
<argument index="2" name="at_position" type="int" default="-1">
</argument>
<description>
+ Adds an [AudioEffect] effect to the bus [code]bus_idx[/code] at [code]at_position[/code].
</description>
</method>
<method name="generate_bus_layout" qualifiers="const">
<return type="AudioBusLayout">
</return>
<description>
+ Generates an [AudioBusLayout] using the available busses and effects.
</description>
</method>
<method name="get_bus_count" qualifiers="const">
<return type="int">
</return>
<description>
+ Returns the number of available busses.
</description>
</method>
<method name="get_bus_effect">
@@ -51,6 +55,7 @@
<argument index="1" name="effect_idx" type="int">
</argument>
<description>
+ Returns the [AudioEffect] at position [code]effect_idx[/code] in bus [code]bus_idx[/code].
</description>
</method>
<method name="get_bus_effect_count">
@@ -59,6 +64,7 @@
<argument index="0" name="bus_idx" type="int">
</argument>
<description>
+ Returns the number of effects on the bus at [code]bus_idx[/code].
</description>
</method>
<method name="get_bus_index" qualifiers="const">
@@ -67,6 +73,7 @@
<argument index="0" name="bus_name" type="String">
</argument>
<description>
+ Returns the index of the bus with the name [code]bus_name[/code].
</description>
</method>
<method name="get_bus_name" qualifiers="const">
@@ -75,6 +82,7 @@
<argument index="0" name="bus_idx" type="int">
</argument>
<description>
+ Returns the name of the bus with the index [code]bus_idx[/code].
</description>
</method>
<method name="get_bus_peak_volume_left_db" qualifiers="const">
@@ -85,6 +93,7 @@
<argument index="1" name="channel" type="int">
</argument>
<description>
+ Returns the peak volume of the left speaker at bus index [code]bus_idx[/code] and channel index [code]channel[/code].
</description>
</method>
<method name="get_bus_peak_volume_right_db" qualifiers="const">
@@ -95,6 +104,7 @@
<argument index="1" name="channel" type="int">
</argument>
<description>
+ Returns the peak volume of the right speaker at bus index [code]bus_idx[/code] and channel index [code]channel[/code].
</description>
</method>
<method name="get_bus_send" qualifiers="const">
@@ -103,6 +113,7 @@
<argument index="0" name="bus_idx" type="int">
</argument>
<description>
+ Returns the name of the bus that the bus at index [code]bus_idx[/code] sends to.
</description>
</method>
<method name="get_bus_volume_db" qualifiers="const">
@@ -111,18 +122,21 @@
<argument index="0" name="bus_idx" type="int">
</argument>
<description>
+ Returns the volume of the bus at index [code]bus_idx[/code] in dB.
</description>
</method>
<method name="get_mix_rate" qualifiers="const">
<return type="float">
</return>
<description>
+ Returns the sample rate at the output of the audioserver.
</description>
</method>
<method name="get_speaker_mode" qualifiers="const">
<return type="int" enum="AudioServer.SpeakerMode">
</return>
<description>
+ Returns the speaker configuration.
</description>
</method>
<method name="is_bus_bypassing_effects" qualifiers="const">
@@ -131,6 +145,7 @@
<argument index="0" name="bus_idx" type="int">
</argument>
<description>
+ If [code]true[/code] the bus at index [code]bus_idx[/code] is bypassing effects.
</description>
</method>
<method name="is_bus_effect_enabled" qualifiers="const">
@@ -141,6 +156,7 @@
<argument index="1" name="effect_idx" type="int">
</argument>
<description>
+ If [code]true[/code] the effect at index [code]effect_idx[/code] on the bus at index [code]bus_idx[/code] is enabled.
</description>
</method>
<method name="is_bus_mute" qualifiers="const">
@@ -149,6 +165,7 @@
<argument index="0" name="bus_idx" type="int">
</argument>
<description>
+ If [code]true[/code] the bus at index [code]bus_idx[/code] is muted.
</description>
</method>
<method name="is_bus_solo" qualifiers="const">
@@ -157,12 +174,14 @@
<argument index="0" name="bus_idx" type="int">
</argument>
<description>
+ If [code]true[/code] the bus at index [code]bus_idx[/code] is in solo mode.
</description>
</method>
<method name="lock">
<return type="void">
</return>
<description>
+ Locks the audio drivers mainloop. Remember to unlock it afterwards.
</description>
</method>
<method name="move_bus">
@@ -173,6 +192,7 @@
<argument index="1" name="to_index" type="int">
</argument>
<description>
+ Moves the bus from index [code]index[/code] to index [code]to_index[/code].
</description>
</method>
<method name="remove_bus">
@@ -181,6 +201,7 @@
<argument index="0" name="index" type="int">
</argument>
<description>
+ Removes the bus at index [code]index[/code].
</description>
</method>
<method name="remove_bus_effect">
@@ -191,6 +212,7 @@
<argument index="1" name="effect_idx" type="int">
</argument>
<description>
+ Removes the effect at index [code]effect_idx[/code] from the bus at index [code]bus_idx[/code].
</description>
</method>
<method name="set_bus_bypass_effects">
@@ -201,6 +223,7 @@
<argument index="1" name="enable" type="bool">
</argument>
<description>
+ If [code]true[/code] the bus at index [code]bus_idx[/code] is bypassing effects.
</description>
</method>
<method name="set_bus_count">
@@ -209,6 +232,7 @@
<argument index="0" name="amount" type="int">
</argument>
<description>
+ Adds and removes busses to make the number of busses match [code]amount[/code].
</description>
</method>
<method name="set_bus_effect_enabled">
@@ -221,6 +245,7 @@
<argument index="2" name="enabled" type="bool">
</argument>
<description>
+ If [code]true[/code] the effect at index [code]effect_idx[/code] on the bus at index [code]bus_idx[/code] is enabled.
</description>
</method>
<method name="set_bus_layout">
@@ -229,6 +254,7 @@
<argument index="0" name="bus_layout" type="AudioBusLayout">
</argument>
<description>
+ Overwrites the currently used [AudioBusLayout].
</description>
</method>
<method name="set_bus_mute">
@@ -239,6 +265,7 @@
<argument index="1" name="enable" type="bool">
</argument>
<description>
+ If [code]true[/code] the bus at index [code]bus_idx[/code] is muted.
</description>
</method>
<method name="set_bus_name">
@@ -249,6 +276,7 @@
<argument index="1" name="name" type="String">
</argument>
<description>
+ Sets the name of the bus at index [code]bus_idx[/code] to [code]name[/code].
</description>
</method>
<method name="set_bus_send">
@@ -259,6 +287,7 @@
<argument index="1" name="send" type="String">
</argument>
<description>
+ Connects the output of the bus at [code]bus_idx[/code] to the bus named [code]send[/code].
</description>
</method>
<method name="set_bus_solo">
@@ -269,6 +298,7 @@
<argument index="1" name="enable" type="bool">
</argument>
<description>
+ If [code]true[/code] the bus at index [code]bus_idx[/code] is in solo mode.
</description>
</method>
<method name="set_bus_volume_db">
@@ -279,6 +309,7 @@
<argument index="1" name="volume_db" type="float">
</argument>
<description>
+ Sets the volume of the bus at index [code]bus_idx[/code] to [code]volume_db[/code].
</description>
</method>
<method name="swap_bus_effects">
@@ -291,27 +322,33 @@
<argument index="2" name="by_effect_idx" type="int">
</argument>
<description>
+ Swaps the position of two effects in bus [code]bus_idx[/code].
</description>
</method>
<method name="unlock">
<return type="void">
</return>
<description>
+ Unlocks the audiodriver's main loop. After locking it always unlock it.
</description>
</method>
</methods>
<signals>
<signal name="bus_layout_changed">
<description>
+ Emitted when the [AudioBusLayout] changes.
</description>
</signal>
</signals>
<constants>
<constant name="SPEAKER_MODE_STEREO" value="0">
+ Two or fewer speakers are detected.
</constant>
<constant name="SPEAKER_SURROUND_51" value="2">
+ A 5.1 channel surround setup detected.
</constant>
<constant name="SPEAKER_SURROUND_71" value="3">
+ A 7.1 channel surround setup detected.
</constant>
</constants>
</class>
diff --git a/doc/classes/AudioStream.xml b/doc/classes/AudioStream.xml
index b4a98b2d8c..67323c59c5 100644
--- a/doc/classes/AudioStream.xml
+++ b/doc/classes/AudioStream.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AudioStream" inherits="Resource" category="Core" version="3.0.alpha.custom_build">
+<class name="AudioStream" inherits="Resource" category="Core" version="3.0-alpha">
<brief_description>
Base class for audio streams.
</brief_description>
diff --git a/doc/classes/AudioStreamPlayback.xml b/doc/classes/AudioStreamPlayback.xml
index 30a9a8f070..61393fbe29 100644
--- a/doc/classes/AudioStreamPlayback.xml
+++ b/doc/classes/AudioStreamPlayback.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AudioStreamPlayback" inherits="Reference" category="Core" version="3.0.alpha.custom_build">
+<class name="AudioStreamPlayback" inherits="Reference" category="Core" version="3.0-alpha">
<brief_description>
+ Meta class for playing back audio.
</brief_description>
<description>
+ Can play, loop, pause a scroll through Audio. See [AudioStream] and [AudioStreamOGGVorbis] for usage.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/AudioStreamPlayer.xml b/doc/classes/AudioStreamPlayer.xml
index 9b104fe757..55edbfb438 100644
--- a/doc/classes/AudioStreamPlayer.xml
+++ b/doc/classes/AudioStreamPlayer.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AudioStreamPlayer" inherits="Node" category="Core" version="3.0.alpha.custom_build">
+<class name="AudioStreamPlayer" inherits="Node" category="Core" version="3.0-alpha">
<brief_description>
Plays back audio.
</brief_description>
@@ -7,6 +7,7 @@
Plays background audio.
</description>
<tutorials>
+ http://docs.godotengine.org/en/latest/learning/features/audio/index.html
</tutorials>
<demos>
</demos>
@@ -27,6 +28,7 @@
<return type="float">
</return>
<description>
+ Returns the position in the [AudioStream].
</description>
</method>
<method name="get_stream" qualifiers="const">
@@ -121,15 +123,16 @@
</methods>
<members>
<member name="autoplay" type="bool" setter="set_autoplay" getter="is_autoplay_enabled">
- If [code]true[/code], audio plays when added to scene tree. Default value: [code]false[/code].
+ If [code]true[/code] audio plays when added to scene tree. Default value: [code]false[/code].
</member>
<member name="bus" type="String" setter="set_bus" getter="get_bus">
Bus on which this audio is playing.
</member>
<member name="mix_target" type="int" setter="set_mix_target" getter="get_mix_target" enum="AudioStreamPlayer.MixTarget">
+ If the audio configuration has more than two speakers, this sets the target channels. See [code]MIX_TARGET_*[/code] constants.
</member>
<member name="playing" type="bool" setter="_set_playing" getter="is_playing">
- If [code]true[/code], audio is playing.
+ If [code]true[/code] audio is playing.
</member>
<member name="stream" type="AudioStream" setter="set_stream" getter="get_stream">
The [AudioStream] object to be played.
@@ -147,10 +150,13 @@
</signals>
<constants>
<constant name="MIX_TARGET_STEREO" value="0">
+ The audio will be played only on the first channel.
</constant>
<constant name="MIX_TARGET_SURROUND" value="1">
+ The audio will be played on all surround channels.
</constant>
<constant name="MIX_TARGET_CENTER" value="2">
+ The audio will be played on the second channel, which is usually the center.
</constant>
</constants>
</class>
diff --git a/doc/classes/AudioStreamPlayer2D.xml b/doc/classes/AudioStreamPlayer2D.xml
index 600e0858dd..98ebeacc5f 100644
--- a/doc/classes/AudioStreamPlayer2D.xml
+++ b/doc/classes/AudioStreamPlayer2D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AudioStreamPlayer2D" inherits="Node2D" category="Core" version="3.0.alpha.custom_build">
+<class name="AudioStreamPlayer2D" inherits="Node2D" category="Core" version="3.0-alpha">
<brief_description>
Plays audio in 2D.
</brief_description>
@@ -40,6 +40,7 @@
<return type="float">
</return>
<description>
+ Returns the position in the [AudioStream].
</description>
</method>
<method name="get_stream" qualifiers="const">
@@ -156,7 +157,7 @@
Dampens audio over distance with this as an exponent.
</member>
<member name="autoplay" type="bool" setter="set_autoplay" getter="is_autoplay_enabled">
- If [code]true[/code], audio plays when added to scene tree. Default value: [code]false[/code].
+ If [code]true[/code] audio plays when added to scene tree. Default value: [code]false[/code].
</member>
<member name="bus" type="String" setter="set_bus" getter="get_bus">
Bus on which this audio is playing.
@@ -165,7 +166,7 @@
Maximum distance from which audio is still hearable.
</member>
<member name="playing" type="bool" setter="_set_playing" getter="is_playing">
- If [code]true[/code], audio is playing.
+ If [code]true[/code] audio is playing.
</member>
<member name="stream" type="AudioStream" setter="set_stream" getter="get_stream">
The [AudioStream] object to be played.
diff --git a/doc/classes/AudioStreamPlayer3D.xml b/doc/classes/AudioStreamPlayer3D.xml
index 886b2b975a..9c016a0173 100644
--- a/doc/classes/AudioStreamPlayer3D.xml
+++ b/doc/classes/AudioStreamPlayer3D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AudioStreamPlayer3D" inherits="Spatial" category="Core" version="3.0.alpha.custom_build">
+<class name="AudioStreamPlayer3D" inherits="Spatial" category="Core" version="3.0-alpha">
<brief_description>
Plays 3D sound in 3D space
</brief_description>
@@ -82,6 +82,7 @@
<return type="float">
</return>
<description>
+ Returns the position in the [AudioStream].
</description>
</method>
<method name="get_stream" qualifiers="const">
@@ -288,7 +289,7 @@
Decides if audio should get quieter with distance linearly, quadratically or logarithmically.
</member>
<member name="autoplay" type="bool" setter="set_autoplay" getter="is_autoplay_enabled">
- If [code]true[/code], audio plays audio plays when added to scene tree. Default value: [code]false[/code].
+ If [code]true[/code] audio plays when added to scene tree. Default value: [code]false[/code].
</member>
<member name="bus" type="String" setter="set_bus" getter="get_bus">
Bus on which this audio is playing.
@@ -300,7 +301,7 @@
The angle in which the audio reaches cameras undampened.
</member>
<member name="emission_angle_enabled" type="bool" setter="set_emission_angle_enabled" getter="is_emission_angle_enabled">
- If [code]true[/code], the audio should be dampened according to the direction of the sound.
+ If [code]true[/code] the audio should be dampened according to the direction of the sound.
</member>
<member name="emission_angle_filter_attenuation_db" type="float" setter="set_emission_angle_filter_attenuation_db" getter="get_emission_angle_filter_attenuation_db">
dampens audio if camera is outside of 'emission_angle_degrees' and 'emission_angle_enabled' is set by this factor, in dB.
@@ -309,7 +310,7 @@
Sets the absolute maximum of the soundlevel, in dB.
</member>
<member name="max_distance" type="float" setter="set_max_distance" getter="get_max_distance">
- Sets the distance from wich the 'out_of_range_mode' takes effect. Has no effect if set to 0.
+ Sets the distance from which the 'out_of_range_mode' takes effect. Has no effect if set to 0.
</member>
<member name="out_of_range_mode" type="int" setter="set_out_of_range_mode" getter="get_out_of_range_mode" enum="AudioStreamPlayer3D.OutOfRangeMode">
Decides if audio should pause when source is outside of 'max_distance' range.
@@ -354,10 +355,10 @@
Disables doppler tracking.
</constant>
<constant name="DOPPLER_TRACKING_IDLE_STEP" value="1">
- Executes doppler trackin in idle step.
+ Executes doppler tracking in idle step.
</constant>
- <constant name="DOPPLER_TRACKING_FIXED_STEP" value="2">
- Executes doppler tracking in fixed step.
+ <constant name="DOPPLER_TRACKING_PHYSICS_STEP" value="2">
+ Executes doppler tracking in physics step.
</constant>
</constants>
</class>
diff --git a/doc/classes/AudioStreamRandomPitch.xml b/doc/classes/AudioStreamRandomPitch.xml
index 1573a78d1f..56c7ee1998 100644
--- a/doc/classes/AudioStreamRandomPitch.xml
+++ b/doc/classes/AudioStreamRandomPitch.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AudioStreamRandomPitch" inherits="AudioStream" category="Core" version="3.0.alpha.custom_build">
+<class name="AudioStreamRandomPitch" inherits="AudioStream" category="Core" version="3.0-alpha">
<brief_description>
Plays audio with random pitch tweaking.
</brief_description>
diff --git a/doc/classes/AudioStreamSample.xml b/doc/classes/AudioStreamSample.xml
index 7f7414e4d3..3a0a171480 100644
--- a/doc/classes/AudioStreamSample.xml
+++ b/doc/classes/AudioStreamSample.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AudioStreamSample" inherits="AudioStream" category="Core" version="3.0.alpha.custom_build">
+<class name="AudioStreamSample" inherits="AudioStream" category="Core" version="3.0-alpha">
<brief_description>
Plays audio.
</brief_description>
diff --git a/doc/classes/BackBufferCopy.xml b/doc/classes/BackBufferCopy.xml
index 6c44430949..2b5a9aac20 100644
--- a/doc/classes/BackBufferCopy.xml
+++ b/doc/classes/BackBufferCopy.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="BackBufferCopy" inherits="Node2D" category="Core" version="3.0.alpha.custom_build">
+<class name="BackBufferCopy" inherits="Node2D" category="Core" version="3.0-alpha">
<brief_description>
Copies a region of the screen (or the whole screen) to a buffer so it can be accessed with the texscreen() shader instruction.
</brief_description>
diff --git a/doc/classes/BaseButton.xml b/doc/classes/BaseButton.xml
index 2ad46579b2..26939143b6 100644
--- a/doc/classes/BaseButton.xml
+++ b/doc/classes/BaseButton.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="BaseButton" inherits="Control" category="Core" version="3.0.alpha.custom_build">
+<class name="BaseButton" inherits="Control" category="Core" version="3.0-alpha">
<brief_description>
- Provides a base class for different kinds of buttons.
+ Base class for different kinds of buttons.
</brief_description>
<description>
- BaseButton is the abstract base class for buttons, so it shouldn't be used directly (It doesn't display anything). Other types of buttons inherit from it.
+ BaseButton is the abstract base class for buttons, so it shouldn't be used directly (it doesn't display anything). Other types of buttons inherit from it.
</description>
<tutorials>
</tutorials>
@@ -152,18 +152,25 @@
</methods>
<members>
<member name="action_mode" type="int" setter="set_action_mode" getter="get_action_mode" enum="BaseButton.ActionMode">
+ Determines when the button is considered clicked, one of the ACTION_MODE_* constants.
</member>
<member name="disabled" type="bool" setter="set_disabled" getter="is_disabled">
+ If [code]true[/code] the button is in disabled state and can't be clicked or toggled.
</member>
<member name="enabled_focus_mode" type="int" setter="set_enabled_focus_mode" getter="get_enabled_focus_mode" enum="Control.FocusMode">
+ Focus access mode to use when switching between enabled/disabled (see [method Control.set_focus_mode] and [member disabled]).
</member>
<member name="group" type="ButtonGroup" setter="set_button_group" getter="get_button_group">
+ [ButtonGroup] associated to the button.
</member>
<member name="pressed" type="bool" setter="set_pressed" getter="is_pressed">
+ If [code]true[/code] the button's state is pressed. Means the button is pressed down or toggled (if toggle_mode is active).
</member>
<member name="shortcut" type="ShortCut" setter="set_shortcut" getter="get_shortcut">
+ [Shortcut] associated to the button.
</member>
<member name="toggle_mode" type="bool" setter="set_toggle_mode" getter="is_toggle_mode">
+ If [code]true[/code] the button is in toggle mode. Makes the button flip state between pressed and unpressed each time its area is clicked.
</member>
</members>
<signals>
diff --git a/doc/classes/Basis.xml b/doc/classes/Basis.xml
index 7731647648..c8a28621ea 100644
--- a/doc/classes/Basis.xml
+++ b/doc/classes/Basis.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Basis" category="Built-In Types" version="3.0.alpha.custom_build">
+<class name="Basis" category="Built-In Types" version="3.0-alpha">
<brief_description>
3x3 matrix datatype.
</brief_description>
diff --git a/doc/classes/BitMap.xml b/doc/classes/BitMap.xml
index d872d0892d..4de059d908 100644
--- a/doc/classes/BitMap.xml
+++ b/doc/classes/BitMap.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="BitMap" inherits="Resource" category="Core" version="3.0.alpha.custom_build">
+<class name="BitMap" inherits="Resource" category="Core" version="3.0-alpha">
<brief_description>
Boolean matrix.
</brief_description>
@@ -77,6 +77,9 @@
</methods>
<members>
<member name="data" type="Dictionary" setter="_set_data" getter="_get_data">
+ Returns a [Dictionary] with two keys :
+ [code]data[/code] : [PoolByteArray] with [code]true[/code]/[code]false[/code] [code]BitMap[/code] data.
+ [code]size[/code] : The [code]Bitmap[/code]'s size.
</member>
</members>
<constants>
diff --git a/doc/classes/BitmapFont.xml b/doc/classes/BitmapFont.xml
index e983c59782..c013a474b2 100644
--- a/doc/classes/BitmapFont.xml
+++ b/doc/classes/BitmapFont.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="BitmapFont" inherits="Font" category="Core" version="3.0.alpha.custom_build">
+<class name="BitmapFont" inherits="Font" category="Core" version="3.0-alpha">
<brief_description>
+ Renders text using [code]*.fnt[/code] fonts.
</brief_description>
<description>
+ Renders text using [code]*.fnt[/code] fonts containing texture atlases. Supports distance fields. For using vector font files like TTF directly, see [DynamicFont].
</description>
<tutorials>
</tutorials>
@@ -23,7 +25,7 @@
<argument index="4" name="advance" type="float" default="-1">
</argument>
<description>
- Add a character to the font, where [i]character[/i] is the unicode value, [i]texture[/i] is the texture index, [i]rect[/i] is the region in the texture (in pixels!), [i]align[/i] is the (optional) alignment for the character and [i]advance[/i] is the (optional) advance.
+ Adds a character to the font, where [code]character[/code] is the unicode value, [code]texture[/code] is the texture index, [code]rect[/code] is the region in the texture (in pixels!), [code]align[/code] is the (optional) alignment for the character and [code]advance[/code] is the (optional) advance.
</description>
</method>
<method name="add_kerning_pair">
@@ -36,7 +38,7 @@
<argument index="2" name="kerning" type="int">
</argument>
<description>
- Add a kerning pair to the [BitmapFont] as a difference. Kerning pairs are special cases where a typeface advance is determined by the next character.
+ Adds a kerning pair to the [code]BitmapFont[/code] as a difference. Kerning pairs are special cases where a typeface advance is determined by the next character.
</description>
</method>
<method name="add_texture">
@@ -45,14 +47,14 @@
<argument index="0" name="texture" type="Texture">
</argument>
<description>
- Add a texture to the [BitmapFont].
+ Adds a texture to the [code]BitmapFont[/code].
</description>
</method>
<method name="clear">
<return type="void">
</return>
<description>
- Clear all the font data.
+ Clears all the font data and settings.
</description>
</method>
<method name="create_from_fnt">
@@ -61,6 +63,7 @@
<argument index="0" name="path" type="String">
</argument>
<description>
+ Creates a BitmapFont from the [code]*.fnt[/code] file at [code]path[/code].
</description>
</method>
<method name="get_char_size" qualifiers="const">
@@ -71,13 +74,14 @@
<argument index="1" name="next" type="int" default="0">
</argument>
<description>
- Return the size of a character, optionally taking kerning into account if the next character is provided.
+ Returns the size of a character, optionally taking kerning into account if the next character is provided.
</description>
</method>
<method name="get_fallback" qualifiers="const">
<return type="BitmapFont">
</return>
<description>
+ Returns the fallback BitmapFont.
</description>
</method>
<method name="get_kerning_pair" qualifiers="const">
@@ -88,7 +92,7 @@
<argument index="1" name="char_b" type="int">
</argument>
<description>
- Return a kerning pair as a difference.
+ Returns a kerning pair as a difference.
</description>
</method>
<method name="get_texture" qualifiers="const">
@@ -97,12 +101,14 @@
<argument index="0" name="idx" type="int">
</argument>
<description>
+ Returns the font atlas texture at index [code]idx[/code].
</description>
</method>
<method name="get_texture_count" qualifiers="const">
<return type="int">
</return>
<description>
+ Returns the number of textures in the BitmapFont atlas.
</description>
</method>
<method name="set_ascent">
@@ -111,7 +117,7 @@
<argument index="0" name="px" type="float">
</argument>
<description>
- Set the font ascent (number of pixels above the baseline).
+ Sets the font ascent (number of pixels above the baseline).
</description>
</method>
<method name="set_distance_field_hint">
@@ -120,6 +126,7 @@
<argument index="0" name="enable" type="bool">
</argument>
<description>
+ If [code]true[/code] distance field hint is enabled.
</description>
</method>
<method name="set_fallback">
@@ -128,6 +135,7 @@
<argument index="0" name="fallback" type="BitmapFont">
</argument>
<description>
+ Sets the fallback BitmapFont.
</description>
</method>
<method name="set_height">
@@ -136,24 +144,31 @@
<argument index="0" name="px" type="float">
</argument>
<description>
- Set the total font height (ascent plus descent) in pixels.
+ Sets the total font height (ascent plus descent) in pixels.
</description>
</method>
</methods>
<members>
<member name="ascent" type="float" setter="set_ascent" getter="get_ascent">
+ Ascent (number of pixels above the baseline).
</member>
<member name="chars" type="PoolIntArray" setter="_set_chars" getter="_get_chars">
+ The characters in the BitmapFont.
</member>
<member name="distance_field" type="bool" setter="set_distance_field_hint" getter="is_distance_field_hint">
+ If [code]true[/code] distance field hint is enabled.
</member>
<member name="fallback" type="BitmapFont" setter="set_fallback" getter="get_fallback">
+ The fallback font.
</member>
<member name="height" type="float" setter="set_height" getter="get_height">
+ Total font height (ascent plus descent) in pixels.
</member>
<member name="kernings" type="PoolIntArray" setter="_set_kernings" getter="_get_kernings">
+ The font's kernings as [PoolIntArray].
</member>
<member name="textures" type="Array" setter="_set_textures" getter="_get_textures">
+ The font's [Texture]s.
</member>
</members>
<constants>
diff --git a/doc/classes/BoneAttachment.xml b/doc/classes/BoneAttachment.xml
index 9297c0e1b1..8f33d7a73c 100644
--- a/doc/classes/BoneAttachment.xml
+++ b/doc/classes/BoneAttachment.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="BoneAttachment" inherits="Spatial" category="Core" version="3.0.alpha.custom_build">
+<class name="BoneAttachment" inherits="Spatial" category="Core" version="3.0-alpha">
<brief_description>
A node that will attach to a bone.
</brief_description>
diff --git a/doc/classes/BoxContainer.xml b/doc/classes/BoxContainer.xml
index 0c70d919f3..a7465a959a 100644
--- a/doc/classes/BoxContainer.xml
+++ b/doc/classes/BoxContainer.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="BoxContainer" inherits="Container" category="Core" version="3.0.alpha.custom_build">
+<class name="BoxContainer" inherits="Container" category="Core" version="3.0-alpha">
<brief_description>
Base class for box containers.
</brief_description>
diff --git a/doc/classes/BoxShape.xml b/doc/classes/BoxShape.xml
index 4e8eb0ba6f..0f46442550 100644
--- a/doc/classes/BoxShape.xml
+++ b/doc/classes/BoxShape.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="BoxShape" inherits="Shape" category="Core" version="3.0.alpha.custom_build">
+<class name="BoxShape" inherits="Shape" category="Core" version="3.0-alpha">
<brief_description>
Box shape resource.
</brief_description>
diff --git a/doc/classes/Button.xml b/doc/classes/Button.xml
index bb02e4266b..2964cc9efc 100644
--- a/doc/classes/Button.xml
+++ b/doc/classes/Button.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Button" inherits="BaseButton" category="Core" version="3.0.alpha.custom_build">
+<class name="Button" inherits="BaseButton" category="Core" version="3.0-alpha">
<brief_description>
Standard themed Button.
</brief_description>
diff --git a/doc/classes/ButtonGroup.xml b/doc/classes/ButtonGroup.xml
index c2c999f9d8..ccc457f9e6 100644
--- a/doc/classes/ButtonGroup.xml
+++ b/doc/classes/ButtonGroup.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ButtonGroup" inherits="Resource" category="Core" version="3.0.alpha.custom_build">
+<class name="ButtonGroup" inherits="Resource" category="Core" version="3.0-alpha">
<brief_description>
Group of Buttons.
</brief_description>
diff --git a/doc/classes/Camera.xml b/doc/classes/Camera.xml
index 068b91204c..c840da9266 100644
--- a/doc/classes/Camera.xml
+++ b/doc/classes/Camera.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Camera" inherits="Spatial" category="Core" version="3.0.alpha.custom_build">
+<class name="Camera" inherits="Spatial" category="Core" version="3.0-alpha">
<brief_description>
Camera node, displays from a point of view.
</brief_description>
@@ -267,7 +267,7 @@
<constant name="DOPPLER_TRACKING_IDLE_STEP" value="1">
Simulate Doppler effect by tracking positions of objects that are changed in [code]_process[/code]. Changes in the relative velocity of this Camera compared to those objects affect how Audio is perceived (changing the Audio's [code]pitch shift[/code]).
</constant>
- <constant name="DOPPLER_TRACKING_FIXED_STEP" value="2">
+ <constant name="DOPPLER_TRACKING_PHYSICS_STEP" value="2">
Simulate Doppler effect by tracking positions of objects that are changed in [code]_physics_process[/code]. Changes in the relative velocity of this Camera compared to those objects affect how Audio is perceived (changing the Audio's [code]pitch shift[/code]).
</constant>
</constants>
diff --git a/doc/classes/Camera2D.xml b/doc/classes/Camera2D.xml
index 228b6ebf91..8704624b2d 100644
--- a/doc/classes/Camera2D.xml
+++ b/doc/classes/Camera2D.xml
@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Camera2D" inherits="Node2D" category="Core" version="3.0.alpha.custom_build">
+<class name="Camera2D" inherits="Node2D" category="Core" version="3.0-alpha">
<brief_description>
Camera node for 2D scenes.
</brief_description>
<description>
Camera node for 2D scenes. It forces the screen (current layer) to scroll following this node. This makes it easier (and faster) to program scrollable scenes than manually changing the position of [CanvasItem] based nodes.
- This node is intended to be a simple helper get get things going quickly and it may happen often that more functionality is desired to change how the camera works. To make your own custom camera node, simply inherit from [Node2D] and change the transform of the canvas by calling get_viewport().set_canvas_transform(m) in [Viewport].
+ This node is intended to be a simple helper to get things going quickly and it may happen often that more functionality is desired to change how the camera works. To make your own custom camera node, simply inherit from [Node2D] and change the transform of the canvas by calling get_viewport().set_canvas_transform(m) in [Viewport].
</description>
<tutorials>
</tutorials>
@@ -327,12 +327,13 @@
The Camera2D's anchor point. See [code]ANCHOR_MODE_*[/code] constants.
</member>
<member name="current" type="bool" setter="_set_current" getter="is_current">
- If [code]true[/code] this camera is the active camera for the current scene. Only one camera can be current, so setting a different camera [code]current[/code] will disable this one.
+ If [code]true[/code] the camera is the active camera for the current scene. Only one camera can be current, so setting a different camera [code]current[/code] will disable this one.
</member>
<member name="drag_margin_bottom" type="float" setter="set_drag_margin" getter="get_drag_margin">
Bottom margin needed to drag the camera. A value of [code]1[/code] makes the camera move only when reaching the edge of the screen.
</member>
<member name="drag_margin_h_enabled" type="bool" setter="set_h_drag_enabled" getter="is_h_drag_enabled">
+ If [code]true[/code] the camera only moves when reaching the horizontal drag margins. If [code]false[/code] the camera moves horizontally regardless of margins. Default value: [code]true[/code].
</member>
<member name="drag_margin_left" type="float" setter="set_drag_margin" getter="get_drag_margin">
Left margin needed to drag the camera. A value of [code]1[/code] makes the camera move only when reaching the edge of the screen.
@@ -344,12 +345,16 @@
Top margin needed to drag the camera. A value of [code]1[/code] makes the camera move only when reaching the edge of the screen.
</member>
<member name="drag_margin_v_enabled" type="bool" setter="set_v_drag_enabled" getter="is_v_drag_enabled">
+ If [code]true[/code] the camera only moves when reaching the vertical drag margins. If [code]false[/code] the camera moves vertically regardless of margins. Default value: [code]true[/code].
</member>
<member name="editor_draw_drag_margin" type="bool" setter="set_margin_drawing_enabled" getter="is_margin_drawing_enabled">
+ If [code]true[/code] draws the camera's drag margin rectangle in the editor. Default value: [code]false[/code]
</member>
<member name="editor_draw_limits" type="bool" setter="set_limit_drawing_enabled" getter="is_limit_drawing_enabled">
+ If [code]true[/code] draws the camera's limits rectangle in the editor. Default value: [code]true[/code]
</member>
<member name="editor_draw_screen" type="bool" setter="set_screen_drawing_enabled" getter="is_screen_drawing_enabled">
+ If [code]true[/code] draws the camera's screen rectangle in the editor. Default value: [code]false[/code]
</member>
<member name="limit_bottom" type="int" setter="set_limit" getter="get_limit">
Bottom scroll limit in pixels. The camera stops moving when reaching this value.
@@ -361,6 +366,7 @@
Right scroll limit in pixels. The camera stops moving when reaching this value.
</member>
<member name="limit_smoothed" type="bool" setter="set_limit_smoothing_enabled" getter="is_limit_smoothing_enabled">
+ If [code]true[/code] the camera smoothly stops when reaches its limits. Default value: [code]false[/code]
</member>
<member name="limit_top" type="int" setter="set_limit" getter="get_limit">
Top scroll limit in pixels. The camera stops moving when reaching this value.
@@ -369,19 +375,22 @@
The camera's offset, useful for looking around or camera shake animations.
</member>
<member name="rotating" type="bool" setter="set_rotating" getter="is_rotating">
+ If [code]true[/code] the camera rotates with the target. Default value: [code]false[/code]
</member>
<member name="smoothing_enabled" type="bool" setter="set_enable_follow_smoothing" getter="is_follow_smoothing_enabled">
+ If [code]true[/code] the camera smoothly moves towards the target at [member smoothing_speed]. Default value: [code]false[/code]
</member>
<member name="smoothing_speed" type="float" setter="set_follow_smoothing" getter="get_follow_smoothing">
+ Speed in pixels per second of the camera's smoothing effect when [member smoothing_enabled] is [code]true[/code]
</member>
<member name="zoom" type="Vector2" setter="set_zoom" getter="get_zoom">
The camera's zoom relative to the viewport. Values larger than [code]Vector2(1, 1)[/code] zoom out and smaller values zoom in. For an example, use [code]Vector2(0.5, 0.5)[/code] for a 2x zoom in, and [code]Vector2(4, 4)[/code] for a 4x zoom out.
</member>
</members>
<constants>
- <constant name="ANCHOR_MODE_DRAG_CENTER" value="1">
- </constant>
<constant name="ANCHOR_MODE_FIXED_TOP_LEFT" value="0">
</constant>
+ <constant name="ANCHOR_MODE_DRAG_CENTER" value="1">
+ </constant>
</constants>
</class>
diff --git a/doc/classes/CanvasItem.xml b/doc/classes/CanvasItem.xml
index 4a9890ea18..bb3a9b3845 100644
--- a/doc/classes/CanvasItem.xml
+++ b/doc/classes/CanvasItem.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="CanvasItem" inherits="Node" category="Core" version="3.0.alpha.custom_build">
+<class name="CanvasItem" inherits="Node" category="Core" version="3.0-alpha">
<brief_description>
Base class of anything 2D.
</brief_description>
@@ -346,14 +346,14 @@
Get the global transform matrix of this item in relation to the canvas.
</description>
</method>
- <method name="get_item_and_children_rect" qualifiers="const">
+ <method name="edit_get_item_and_children_rect" qualifiers="const">
<return type="Rect2">
</return>
<description>
Get a [Rect2] with the boundaries of this item and its children.
</description>
</method>
- <method name="get_item_rect" qualifiers="const">
+ <method name="edit_get_rect" qualifiers="const">
<return type="Rect2">
</return>
<description>
@@ -652,6 +652,9 @@
<constant name="BLEND_MODE_PREMULT_ALPHA" value="4">
Mix blending mode. Colors are assumed to be premultiplied by the alpha (opacity) value.
</constant>
+ <constant name="NOTIFICATION_TRANSFORM_CHANGED" value="29" enum="">
+ Canvas item transform has changed. Only received if requested.
+ </constant>
<constant name="NOTIFICATION_DRAW" value="30" enum="">
CanvasItem is requested to draw.
</constant>
@@ -664,8 +667,5 @@
<constant name="NOTIFICATION_EXIT_CANVAS" value="33" enum="">
Canvas item has exited the canvas.
</constant>
- <constant name="NOTIFICATION_TRANSFORM_CHANGED" value="29" enum="">
- Canvas item transform has changed. Only received if requested.
- </constant>
</constants>
</class>
diff --git a/doc/classes/CanvasItemMaterial.xml b/doc/classes/CanvasItemMaterial.xml
index 2a6553bb6a..b9d2653a2f 100644
--- a/doc/classes/CanvasItemMaterial.xml
+++ b/doc/classes/CanvasItemMaterial.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="CanvasItemMaterial" inherits="Material" category="Core" version="3.0.alpha.custom_build">
+<class name="CanvasItemMaterial" inherits="Material" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/CanvasLayer.xml b/doc/classes/CanvasLayer.xml
index 3ee1f10536..139624bb1d 100644
--- a/doc/classes/CanvasLayer.xml
+++ b/doc/classes/CanvasLayer.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="CanvasLayer" inherits="Node" category="Core" version="3.0.alpha.custom_build">
+<class name="CanvasLayer" inherits="Node" category="Core" version="3.0-alpha">
<brief_description>
Canvas drawing layer.
</brief_description>
<description>
- Canvas drawing layer. [CanvasItem] nodes that are direct or indirect children of a [CanvasLayer] will be drawn in that layer. The layer is a numeric index that defines the draw order. The default 2D scene renders with index 0, so a [CanvasLayer] with index -1 will be drawn below, and one with index 1 will be drawn above. This is very useful for HUDs (in layer 1+ or above), or backgrounds (in layer -1 or below).
+ Canvas drawing layer. [CanvasItem] nodes that are direct or indirect children of a [code]CanvasLayer[/code] will be drawn in that layer. The layer is a numeric index that defines the draw order. The default 2D scene renders with index 0, so a [code]CanvasLayer[/code] with index -1 will be drawn below, and one with index 1 will be drawn above. This is very useful for HUDs (in layer 1+ or above), or backgrounds (in layer -1 or below).
</description>
<tutorials>
</tutorials>
@@ -38,7 +38,7 @@
Return the base rotation for this layer in radians (helper).
</description>
</method>
- <method name="get_rotationd" qualifiers="const">
+ <method name="get_rotation_degrees" qualifiers="const">
<return type="float">
</return>
<description>
@@ -101,7 +101,7 @@
Set the base rotation for this layer in radians (helper).
</description>
</method>
- <method name="set_rotationd">
+ <method name="set_rotation_degrees">
<return type="void">
</return>
<argument index="0" name="degrees" type="float">
@@ -136,7 +136,7 @@
<member name="offset" type="Vector2" setter="set_offset" getter="get_offset">
The layer's base offset.
</member>
- <member name="rotation" type="float" setter="set_rotationd" getter="get_rotationd">
+ <member name="rotation" type="float" setter="set_rotation_degrees" getter="get_rotation_degrees">
The layer's rotation in degrees.
</member>
<member name="scale" type="Vector2" setter="set_scale" getter="get_scale">
diff --git a/doc/classes/CanvasModulate.xml b/doc/classes/CanvasModulate.xml
index f0e3132da5..3872d80236 100644
--- a/doc/classes/CanvasModulate.xml
+++ b/doc/classes/CanvasModulate.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="CanvasModulate" inherits="Node2D" category="Core" version="3.0.alpha.custom_build">
+<class name="CanvasModulate" inherits="Node2D" category="Core" version="3.0-alpha">
<brief_description>
- Tint the entire canvas
+ Tint the entire canvas.
</brief_description>
<description>
- CanvasModulate tints the canvas elements using its assigned color
+ [code]CanvasModulate[/code] tints the canvas elements using its assigned [code]color[/code].
</description>
<tutorials>
</tutorials>
@@ -30,6 +30,7 @@
</methods>
<members>
<member name="color" type="Color" setter="set_color" getter="get_color">
+ The tint color to apply.
</member>
</members>
<constants>
diff --git a/doc/classes/CapsuleMesh.xml b/doc/classes/CapsuleMesh.xml
index 13cdfa057d..497e795253 100644
--- a/doc/classes/CapsuleMesh.xml
+++ b/doc/classes/CapsuleMesh.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="CapsuleMesh" inherits="PrimitiveMesh" category="Core" version="3.0.alpha.custom_build">
+<class name="CapsuleMesh" inherits="PrimitiveMesh" category="Core" version="3.0-alpha">
<brief_description>
Class representing a capsule-shaped [PrimitiveMesh].
</brief_description>
diff --git a/doc/classes/CapsuleShape.xml b/doc/classes/CapsuleShape.xml
index db075a504c..f2d3528e4f 100644
--- a/doc/classes/CapsuleShape.xml
+++ b/doc/classes/CapsuleShape.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="CapsuleShape" inherits="Shape" category="Core" version="3.0.alpha.custom_build">
+<class name="CapsuleShape" inherits="Shape" category="Core" version="3.0-alpha">
<brief_description>
Capsule shape for collisions.
</brief_description>
diff --git a/doc/classes/CapsuleShape2D.xml b/doc/classes/CapsuleShape2D.xml
index df833e0582..b700388303 100644
--- a/doc/classes/CapsuleShape2D.xml
+++ b/doc/classes/CapsuleShape2D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="CapsuleShape2D" inherits="Shape2D" category="Core" version="3.0.alpha.custom_build">
+<class name="CapsuleShape2D" inherits="Shape2D" category="Core" version="3.0-alpha">
<brief_description>
Capsule shape for 2D collisions.
</brief_description>
@@ -15,14 +15,14 @@
<return type="float">
</return>
<description>
- Return the height of the [CapsuleShape2D].
+ Return the height of the [code]CapsuleShape2D[/code].
</description>
</method>
<method name="get_radius" qualifiers="const">
<return type="float">
</return>
<description>
- Return the radius of the [CapsuleShape2D].
+ Return the radius of the [code]CapsuleShape2D[/code].
</description>
</method>
<method name="set_height">
@@ -31,7 +31,7 @@
<argument index="0" name="height" type="float">
</argument>
<description>
- Set the height of the [CapsuleShape2D].
+ Set the height of the [code]CapsuleShape2D[/code].
</description>
</method>
<method name="set_radius">
@@ -40,7 +40,7 @@
<argument index="0" name="radius" type="float">
</argument>
<description>
- Set the radius of the [CapsuleShape2D].
+ Set the radius of the [code]CapsuleShape2D[/code].
</description>
</method>
</methods>
diff --git a/doc/classes/CenterContainer.xml b/doc/classes/CenterContainer.xml
index 2f81e7739f..9e88448e32 100644
--- a/doc/classes/CenterContainer.xml
+++ b/doc/classes/CenterContainer.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="CenterContainer" inherits="Container" category="Core" version="3.0.alpha.custom_build">
+<class name="CenterContainer" inherits="Container" category="Core" version="3.0-alpha">
<brief_description>
Keeps children controls centered.
</brief_description>
diff --git a/doc/classes/CheckBox.xml b/doc/classes/CheckBox.xml
index 6258eb503f..fb9a67323b 100644
--- a/doc/classes/CheckBox.xml
+++ b/doc/classes/CheckBox.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="CheckBox" inherits="Button" category="Core" version="3.0.alpha.custom_build">
+<class name="CheckBox" inherits="Button" category="Core" version="3.0-alpha">
<brief_description>
Binary choice user interface widget
</brief_description>
<description>
- A checkbox allows the user to make a binary choice (choosing only one of two posible options), for example Answer 'yes' or 'no'.
+ A checkbox allows the user to make a binary choice (choosing only one of two possible options), for example Answer 'yes' or 'no'.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/CheckButton.xml b/doc/classes/CheckButton.xml
index bb4e6fc0cb..996b4238a1 100644
--- a/doc/classes/CheckButton.xml
+++ b/doc/classes/CheckButton.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="CheckButton" inherits="Button" category="Core" version="3.0.alpha.custom_build">
+<class name="CheckButton" inherits="Button" category="Core" version="3.0-alpha">
<brief_description>
Checkable button.
</brief_description>
diff --git a/doc/classes/CircleShape2D.xml b/doc/classes/CircleShape2D.xml
index 1ed54f0705..e5158755fe 100644
--- a/doc/classes/CircleShape2D.xml
+++ b/doc/classes/CircleShape2D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="CircleShape2D" inherits="Shape2D" category="Core" version="3.0.alpha.custom_build">
+<class name="CircleShape2D" inherits="Shape2D" category="Core" version="3.0-alpha">
<brief_description>
Circular shape for 2D collisions.
</brief_description>
diff --git a/doc/classes/ClassDB.xml b/doc/classes/ClassDB.xml
index 35cf819959..2fed2f8676 100644
--- a/doc/classes/ClassDB.xml
+++ b/doc/classes/ClassDB.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ClassDB" inherits="Object" category="Core" version="3.0.alpha.custom_build">
+<class name="ClassDB" inherits="Object" category="Core" version="3.0-alpha">
<brief_description>
Class information repository.
</brief_description>
diff --git a/doc/classes/CollisionObject.xml b/doc/classes/CollisionObject.xml
index 64e9e07925..be047ad699 100644
--- a/doc/classes/CollisionObject.xml
+++ b/doc/classes/CollisionObject.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="CollisionObject" inherits="Spatial" category="Core" version="3.0.alpha.custom_build">
+<class name="CollisionObject" inherits="Spatial" category="Core" version="3.0-alpha">
<brief_description>
Base node for collision objects.
</brief_description>
<description>
- CollisionObject is the base class for physics objects. It can hold any number of collision [Shape]\ s. Each shape must be assigned to a [i]shape owner[/i]. The CollisionObject can have any number of shape owners. Shape owners are not nodes and do not appear in the editor, but are accessible through code using the [code]shape_owner_*[/code] methods.
+ CollisionObject is the base class for physics objects. It can hold any number of collision [Shape]s. Each shape must be assigned to a [i]shape owner[/i]. The CollisionObject can have any number of shape owners. Shape owners are not nodes and do not appear in the editor, but are accessible through code using the [code]shape_owner_*[/code] methods.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/CollisionObject2D.xml b/doc/classes/CollisionObject2D.xml
index 52743bd37d..d10368229c 100644
--- a/doc/classes/CollisionObject2D.xml
+++ b/doc/classes/CollisionObject2D.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="CollisionObject2D" inherits="Node2D" category="Core" version="3.0.alpha.custom_build">
+<class name="CollisionObject2D" inherits="Node2D" category="Core" version="3.0-alpha">
<brief_description>
Base node for 2D collision objects.
</brief_description>
<description>
- CollisionObject2D is the base class for 2D physics objects. It can hold any number of 2D collision [Shape2D]\ s. Each shape must be assigned to a [i]shape owner[/i]. The CollisionObject2D can have any number of shape owners. Shape owners are not nodes and do not appear in the editor, but are accessible through code using the [code]shape_owner_*[/code] methods.
+ CollisionObject2D is the base class for 2D physics objects. It can hold any number of 2D collision [Shape2D]s. Each shape must be assigned to a [i]shape owner[/i]. The CollisionObject2D can have any number of shape owners. Shape owners are not nodes and do not appear in the editor, but are accessible through code using the [code]shape_owner_*[/code] methods.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/CollisionPolygon.xml b/doc/classes/CollisionPolygon.xml
index c2496424d6..13a993e9f4 100644
--- a/doc/classes/CollisionPolygon.xml
+++ b/doc/classes/CollisionPolygon.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="CollisionPolygon" inherits="Spatial" category="Core" version="3.0.alpha.custom_build">
+<class name="CollisionPolygon" inherits="Spatial" category="Core" version="3.0-alpha">
<brief_description>
Editor-only class for defining a collision polygon in 3D space.
</brief_description>
diff --git a/doc/classes/CollisionPolygon2D.xml b/doc/classes/CollisionPolygon2D.xml
index 7f30e8e83e..bc4d2a5b16 100644
--- a/doc/classes/CollisionPolygon2D.xml
+++ b/doc/classes/CollisionPolygon2D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="CollisionPolygon2D" inherits="Node2D" category="Core" version="3.0.alpha.custom_build">
+<class name="CollisionPolygon2D" inherits="Node2D" category="Core" version="3.0-alpha">
<brief_description>
Defines a 2D collision polygon.
</brief_description>
diff --git a/doc/classes/CollisionShape.xml b/doc/classes/CollisionShape.xml
index 6e98d2f979..3c9e252788 100644
--- a/doc/classes/CollisionShape.xml
+++ b/doc/classes/CollisionShape.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="CollisionShape" inherits="Spatial" category="Core" version="3.0.alpha.custom_build">
+<class name="CollisionShape" inherits="Spatial" category="Core" version="3.0-alpha">
<brief_description>
Node that represents collision shape data in 3D space.
</brief_description>
diff --git a/doc/classes/CollisionShape2D.xml b/doc/classes/CollisionShape2D.xml
index cefa0c1c81..caf3f8d8be 100644
--- a/doc/classes/CollisionShape2D.xml
+++ b/doc/classes/CollisionShape2D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="CollisionShape2D" inherits="Node2D" category="Core" version="3.0.alpha.custom_build">
+<class name="CollisionShape2D" inherits="Node2D" category="Core" version="3.0-alpha">
<brief_description>
Node that represents collision shape data in 2D space.
</brief_description>
diff --git a/doc/classes/Color.xml b/doc/classes/Color.xml
index 4547771b63..479eb719d4 100644
--- a/doc/classes/Color.xml
+++ b/doc/classes/Color.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Color" category="Built-In Types" version="3.0.alpha.custom_build">
+<class name="Color" category="Built-In Types" version="3.0-alpha">
<brief_description>
Color in RGBA format with some support for ARGB format.
</brief_description>
diff --git a/doc/classes/ColorPicker.xml b/doc/classes/ColorPicker.xml
index 87414eb03a..b6aeb8d0e3 100644
--- a/doc/classes/ColorPicker.xml
+++ b/doc/classes/ColorPicker.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ColorPicker" inherits="BoxContainer" category="Core" version="3.0.alpha.custom_build">
+<class name="ColorPicker" inherits="BoxContainer" category="Core" version="3.0-alpha">
<brief_description>
Color picker control.
</brief_description>
@@ -93,6 +93,8 @@
</theme_item>
<theme_item name="margin" type="int">
</theme_item>
+ <theme_item name="preset_bg" type="Texture">
+ </theme_item>
<theme_item name="screen_picker" type="Texture">
</theme_item>
<theme_item name="sv_height" type="int">
diff --git a/doc/classes/ColorPickerButton.xml b/doc/classes/ColorPickerButton.xml
index 59b74edd77..24b37580d6 100644
--- a/doc/classes/ColorPickerButton.xml
+++ b/doc/classes/ColorPickerButton.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ColorPickerButton" inherits="Button" category="Core" version="3.0.alpha.custom_build">
+<class name="ColorPickerButton" inherits="Button" category="Core" version="3.0-alpha">
<brief_description>
Button that pops out a [ColorPicker]
</brief_description>
@@ -72,6 +72,8 @@
<constants>
</constants>
<theme_items>
+ <theme_item name="bg" type="Texture">
+ </theme_item>
<theme_item name="disabled" type="StyleBox">
</theme_item>
<theme_item name="focus" type="StyleBox">
diff --git a/doc/classes/ColorRect.xml b/doc/classes/ColorRect.xml
index 90e88603b0..4dbc4f010c 100644
--- a/doc/classes/ColorRect.xml
+++ b/doc/classes/ColorRect.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ColorRect" inherits="Control" category="Core" version="3.0.alpha.custom_build">
+<class name="ColorRect" inherits="Control" category="Core" version="3.0-alpha">
<brief_description>
Colored rect for canvas.
</brief_description>
@@ -38,6 +38,10 @@
</methods>
<members>
<member name="color" type="Color" setter="set_frame_color" getter="get_frame_color">
+ The color to fill the [code]ColorRect[/code].
+ [codeblock]
+ $ColorRect.color = Color(1, 0, 0, 1) # Set ColorRect node's color to red
+ [/codeblock]
</member>
</members>
<constants>
diff --git a/doc/classes/ConcavePolygonShape.xml b/doc/classes/ConcavePolygonShape.xml
index 0b1cbf9c21..e586eb11c5 100644
--- a/doc/classes/ConcavePolygonShape.xml
+++ b/doc/classes/ConcavePolygonShape.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ConcavePolygonShape" inherits="Shape" category="Core" version="3.0.alpha.custom_build">
+<class name="ConcavePolygonShape" inherits="Shape" category="Core" version="3.0-alpha">
<brief_description>
Concave polygon shape.
</brief_description>
diff --git a/doc/classes/ConcavePolygonShape2D.xml b/doc/classes/ConcavePolygonShape2D.xml
index 018d64b643..5d2dbb4596 100644
--- a/doc/classes/ConcavePolygonShape2D.xml
+++ b/doc/classes/ConcavePolygonShape2D.xml
@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ConcavePolygonShape2D" inherits="Shape2D" category="Core" version="3.0.alpha.custom_build">
+<class name="ConcavePolygonShape2D" inherits="Shape2D" category="Core" version="3.0-alpha">
<brief_description>
Concave polygon 2D shape resource for physics.
</brief_description>
<description>
Concave polygon 2D shape resource for physics. It is made out of segments and is very optimal for complex polygonal concave collisions. It is really not advised to use for [RigidBody2D] nodes. A CollisionPolygon2D in convex decomposition mode (solids) or several convex objects are advised for that instead. Otherwise, a concave polygon 2D shape is better for static collisions.
- The main difference between a [ConvexPolygonShape2D] and a [ConcavePolygonShape2D] is that a concave polygon assumes it is concave and uses a more complex method of collision detection, and a convex one forces itself to be convex in order to speed up collision detection.
+ The main difference between a [ConvexPolygonShape2D] and a [code]ConcavePolygonShape2D[/code] is that a concave polygon assumes it is concave and uses a more complex method of collision detection, and a convex one forces itself to be convex in order to speed up collision detection.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/ConeTwistJoint.xml b/doc/classes/ConeTwistJoint.xml
index 67c7cc4cfe..2f72b451f3 100644
--- a/doc/classes/ConeTwistJoint.xml
+++ b/doc/classes/ConeTwistJoint.xml
@@ -1,8 +1,12 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ConeTwistJoint" inherits="Joint" category="Core" version="3.0.alpha.custom_build">
+<class name="ConeTwistJoint" inherits="Joint" category="Core" version="3.0-alpha">
<brief_description>
+ A twist joint between two 3D bodies
</brief_description>
<description>
+ The joint can rotate the bodies across an axis defined by the local x-axes of the [Joint].
+ The twist axis is initiated as the x-axis of the [Joint].
+ Once the Bodies swing, the twist axis is calculated as the middle of the x-axes of the Joint in the local space of the two Bodies.
</description>
<tutorials>
</tutorials>
@@ -30,28 +34,49 @@
</methods>
<members>
<member name="bias" type="float" setter="set_param" getter="get_param">
+ The speed with which the swing or twist will take place.
+ The higher, the faster.
</member>
<member name="relaxation" type="float" setter="set_param" getter="get_param">
+ Defines, how fast the swing- and twist-speed-difference on both sides gets synced.
</member>
<member name="softness" type="float" setter="set_param" getter="get_param">
+ The ease with which the joint starts to twist. If it's too low, it takes more force to start twisting the joint.
</member>
<member name="swing_span" type="float" setter="_set_swing_span" getter="_get_swing_span">
+ Swing is rotation from side to side, around the axis perpendicular to the twist axis.
+ The swing span defines, how much rotation will not get corrected allong the swing axis.
+ Could be defined as looseness in the [code]ConeTwistJoint[/code].
+ If below 0.05, this behaviour is locked. Default value: [code]PI/4[/code].
</member>
<member name="twist_span" type="float" setter="_set_twist_span" getter="_get_twist_span">
+ Twist is the rotation around the twist axis, this value defined how far the joint can twist.
+ Twist is locked if below 0.05.
</member>
</members>
<constants>
<constant name="PARAM_SWING_SPAN" value="0">
+ Swing is rotation from side to side, around the axis perpendicular to the twist axis.
+ The swing span defines, how much rotation will not get corrected allong the swing axis.
+ Could be defined as looseness in the [code]ConeTwistJoint[/code].
+ If below 0.05, this behaviour is locked. Default value: [code]PI/4[/code].
</constant>
<constant name="PARAM_TWIST_SPAN" value="1">
+ Twist is the rotation around the twist axis, this value defined how far the joint can twist.
+ Twist is locked if below 0.05.
</constant>
<constant name="PARAM_BIAS" value="2">
+ The speed with which the swing or twist will take place.
+ The higher, the faster.
</constant>
<constant name="PARAM_SOFTNESS" value="3">
+ The ease with which the joint starts to twist. If it's too low, it takes more force to start twisting the joint.
</constant>
<constant name="PARAM_RELAXATION" value="4">
+ Defines, how fast the swing- and twist-speed-difference on both sides gets synced.
</constant>
<constant name="PARAM_MAX" value="5">
+ End flag of PARAM_* constants, used internally.
</constant>
</constants>
</class>
diff --git a/doc/classes/ConfigFile.xml b/doc/classes/ConfigFile.xml
index c2d1ec1355..ef668ca994 100644
--- a/doc/classes/ConfigFile.xml
+++ b/doc/classes/ConfigFile.xml
@@ -1,18 +1,25 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ConfigFile" inherits="Reference" category="Core" version="3.0.alpha.custom_build">
+<class name="ConfigFile" inherits="Reference" category="Core" version="3.0-alpha">
<brief_description>
Helper class to handle INI-style files.
</brief_description>
<description>
- This helper class can be used to store [Variant] values on the filesystem using an INI-style formatting. The stored values as referenced by a section and a key. The stored data can be saved to or parsed from a file, though ConfigFile objects can also be used directly with accessing the filesystem.
- The following example shows how to parse a INI-style file from the system, read its contents and store new values in it:
+ This helper class can be used to store [Variant] values on the filesystem using INI-style formatting. The stored values are indentified by a section and a key:
+ [codeblock]
+ [section]
+ some_key=42
+ string_example="Hello World!"
+ a_vector=Vector3( 1, 0, 2 )
+ [/codeblock]
+ The stored data can be saved to or parsed from a file, though ConfigFile objects can also be used directly without accessing the filesystem.
+ The following example shows how to parse an INI-style file from the system, read its contents and store new values in it:
[codeblock]
var config = ConfigFile.new()
var err = config.load("user://settings.cfg")
if err == OK: # if not, something went wrong with the file loading
# Look for the display/width pair, and default to 1024 if missing
var screen_width = get_value("display", "width", 1024)
- # Store a variable if and only it hasn't been defined yet
+ # Store a variable if and only if it hasn't been defined yet
if not config.has_section_key("audio", "mute"):
config.set_value("audio", "mute", false)
# Save the changes by overwriting the previous file
@@ -30,6 +37,7 @@
<argument index="0" name="section" type="String">
</argument>
<description>
+ Deletes the specified section along with all the key-value pairs inside.
</description>
</method>
<method name="get_section_keys" qualifiers="const">
@@ -38,14 +46,14 @@
<argument index="0" name="section" type="String">
</argument>
<description>
- Return an array of all defined key identifiers in the specified section.
+ Returns an array of all defined key identifiers in the specified section.
</description>
</method>
<method name="get_sections" qualifiers="const">
<return type="PoolStringArray">
</return>
<description>
- Return an array of all defined section identifiers.
+ Returns an array of all defined section identifiers.
</description>
</method>
<method name="get_value" qualifiers="const">
@@ -58,7 +66,7 @@
<argument index="2" name="default" type="Variant" default="null">
</argument>
<description>
- Return the current value for the specified section and key. If the section and/or the key do not exist, the method returns the value of the optional [i]default[/i] argument (and thus [code]NULL[/code] if not specified).
+ Returns the current value for the specified section and key. If the section and/or the key do not exist, the method returns the value of the optional [code]default[/code] argument, or [code]null[/code] if it is omitted.
</description>
</method>
<method name="has_section" qualifiers="const">
@@ -67,7 +75,7 @@
<argument index="0" name="section" type="String">
</argument>
<description>
- Check if the specified section exists.
+ Returns [code]true[/code] if the specified section exists.
</description>
</method>
<method name="has_section_key" qualifiers="const">
@@ -78,7 +86,7 @@
<argument index="1" name="key" type="String">
</argument>
<description>
- Check if the specified section-key pair exists.
+ Returns [code]true[/code] if the specified section-key pair exists.
</description>
</method>
<method name="load">
@@ -87,7 +95,7 @@
<argument index="0" name="path" type="String">
</argument>
<description>
- Load the config file specified as a parameter. The file's contents are parsed and loaded in the ConfigFile object from which the method was called. The return value is one of the OK, FAILED or ERR_* constants listed in [@Global Scope] (if the load was successful, it returns OK).
+ Loads the config file specified as a parameter. The file's contents are parsed and loaded in the ConfigFile object which the method was called on. Returns one of the [code]OK[/code], [code]FAILED[/code] or [code]ERR_*[/code] constants listed in [@GlobalScope]. If the load was successful, the return value is [code]OK[/code].
</description>
</method>
<method name="save">
@@ -96,8 +104,7 @@
<argument index="0" name="path" type="String">
</argument>
<description>
- Save the contents of the ConfigFile object to the file specified as a parameter. The output file uses an INI-style structure.
- The return value is one of the OK, FAILED or ERR_* constants listed in [@Global Scope] (if the save was successful, it returns OK).
+ Saves the contents of the ConfigFile object to the file specified as a parameter. The output file uses an INI-style structure. Returns one of the [code]OK[/code], [code]FAILED[/code] or [code]ERR_*[/code] constants listed in [@GlobalScope]. If the load was successful, the return value is [code]OK[/code].
</description>
</method>
<method name="set_value">
@@ -110,7 +117,7 @@
<argument index="2" name="value" type="Variant">
</argument>
<description>
- Assign a value to the specified key of the the specified section. If the section and/or the key do not exist, they are created. Passing a [code]NULL[/code] value deletes the specified key if it exists (and deletes the section if it ends up empty once the key has been removed).
+ Assigns a value to the specified key of the the specified section. If the section and/or the key do not exist, they are created. Passing a [code]null[/code] value deletes the specified key if it exists, and deletes the section if it ends up empty once the key has been removed.
</description>
</method>
</methods>
diff --git a/doc/classes/ConfirmationDialog.xml b/doc/classes/ConfirmationDialog.xml
index 84de287519..1bbb338c07 100644
--- a/doc/classes/ConfirmationDialog.xml
+++ b/doc/classes/ConfirmationDialog.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ConfirmationDialog" inherits="AcceptDialog" category="Core" version="3.0.alpha.custom_build">
+<class name="ConfirmationDialog" inherits="AcceptDialog" category="Core" version="3.0-alpha">
<brief_description>
Dialog for confirmation of actions.
</brief_description>
diff --git a/doc/classes/Container.xml b/doc/classes/Container.xml
index 844c17a1d9..5490c84bae 100644
--- a/doc/classes/Container.xml
+++ b/doc/classes/Container.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Container" inherits="Control" category="Core" version="3.0.alpha.custom_build">
+<class name="Container" inherits="Control" category="Core" version="3.0-alpha">
<brief_description>
Base node for containers.
</brief_description>
<description>
- Base node for containers. A [Container] contains other controls and automatically arranges them in a certain way.
+ Base node for containers. A [code]Container[/code] contains other controls and automatically arranges them in a certain way.
A Control can inherit this to create custom container classes.
</description>
<tutorials>
diff --git a/doc/classes/Control.xml b/doc/classes/Control.xml
index b3bdd1d6c2..57966fb74e 100644
--- a/doc/classes/Control.xml
+++ b/doc/classes/Control.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Control" inherits="CanvasItem" category="Core" version="3.0.alpha.custom_build">
+<class name="Control" inherits="CanvasItem" category="Core" version="3.0-alpha">
<brief_description>
All User Interface nodes inherit from Control. Features anchors and margins to adapt its position and size to its parent.
</brief_description>
@@ -60,7 +60,7 @@
<argument index="1" name="constant" type="int">
</argument>
<description>
- Overrides an integer constant in the [theme] resource the node uses. If the [code]constant[code] is invalid, Godot clears the override. See [member Theme.INVALID_CONSTANT] for more information.
+ Overrides an integer constant in the [Theme] resource the node uses. If the [code]constant[/code] is invalid, Godot clears the override. See [member Theme.INVALID_CONSTANT] for more information.
</description>
</method>
<method name="add_font_override">
@@ -228,7 +228,14 @@
<argument index="0" name="margin" type="int" enum="Margin">
</argument>
<description>
- Return the forced neighbour for moving the input focus to. When pressing TAB or directional/joypad directions focus is moved to the next control in that direction. However, the neighbour to move to can be forced with this function.
+ Return the forced neighbour for moving the input focus to. When pressing directional/joypad directions, focus is moved to the next control in that direction. However, the neighbour to move to can be forced with this function.
+ </description>
+ </method>
+ <method name="get_focus_next" qualifiers="const">
+ <return type="NodePath">
+ </return>
+ <description>
+ Return the 'focus_next' for moving input focus to. When pressing TAB, focus is moved to the next control in the tree. However, the control to move to can be forced with this function.
</description>
</method>
<method name="get_focus_owner" qualifiers="const">
@@ -238,6 +245,13 @@
Return which control is owning the keyboard focus, or null if no one.
</description>
</method>
+ <method name="get_focus_previous" qualifiers="const">
+ <return type="NodePath">
+ </return>
+ <description>
+ Return the 'focus_previous' for moving input focus to. When pressing Shift+TAB focus is moved to the previous control in the tree. However, the control to move to can be forced with this function.
+ </description>
+ </method>
<method name="get_font" qualifiers="const">
<return type="Font">
</return>
@@ -347,7 +361,7 @@
Return the rotation (in radians)
</description>
</method>
- <method name="get_rotation_deg" qualifiers="const">
+ <method name="get_rotation_degrees" qualifiers="const">
<return type="float">
</return>
<description>
@@ -578,23 +592,26 @@
<description>
</description>
</method>
- <method name="set_anchors_preset">
+ <method name="set_anchors_and_margins_preset">
<return type="void">
</return>
<argument index="0" name="preset" type="int" enum="Control.LayoutPreset">
</argument>
- <argument index="1" name="keep_margin" type="bool" default="false">
+ <argument index="1" name="resize_mode" type="int" enum="Control.LayoutPresetMode" default="0">
+ </argument>
+ <argument index="2" name="margin" type="int" default="0">
</argument>
<description>
</description>
</method>
- <method name="set_area_as_parent_rect">
+ <method name="set_anchors_preset">
<return type="void">
</return>
- <argument index="0" name="margin" type="int" default="0">
+ <argument index="0" name="preset" type="int" enum="Control.LayoutPreset">
+ </argument>
+ <argument index="1" name="keep_margin" type="bool" default="false">
</argument>
<description>
- Change all margins and anchors, so this Control always takes up the same area as the parent Control. This is a helper (see [method set_anchor], [method set_margin]).
</description>
</method>
<method name="set_begin">
@@ -673,7 +690,25 @@
<argument index="1" name="neighbour" type="NodePath">
</argument>
<description>
- Force a neighbour for moving the input focus to. When pressing TAB or directional/joypad directions focus is moved to the next control in that direction. However, the neighbour to move to can be forced with this function.
+ Force a neighbour for moving the input focus to. When pressing directional/joypad directions, focus is moved to the next control in that direction. However, the neighbour to move to can be forced with this function.
+ </description>
+ </method>
+ <method name="set_focus_next">
+ <return type="void">
+ </return>
+ <argument index="0" name="next" type="NodePath">
+ </argument>
+ <description>
+ Force the 'focus_next' for moving input focus to. When pressing TAB, focus is moved to the next control in the tree. However, the control to move to can be forced with this function.
+ </description>
+ </method>
+ <method name="set_focus_previous">
+ <return type="void">
+ </return>
+ <argument index="0" name="previous" type="NodePath">
+ </argument>
+ <description>
+ Force the 'focus_previous' for moving input focus to. When pressing Shift+TAB, focus is moved to the previous control in the tree. However, the control to move to can be forced with this function.
</description>
</method>
<method name="set_global_position">
@@ -713,6 +748,18 @@
Set a margin offset. Margin can be one of (MARGIN_LEFT, MARGIN_TOP, MARGIN_RIGHT, MARGIN_BOTTOM). Offset value being set depends on the anchor mode.
</description>
</method>
+ <method name="set_margins_preset">
+ <return type="void">
+ </return>
+ <argument index="0" name="preset" type="int" enum="Control.LayoutPreset">
+ </argument>
+ <argument index="1" name="resize_mode" type="int" enum="Control.LayoutPresetMode" default="0">
+ </argument>
+ <argument index="2" name="margin" type="int" default="0">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="set_mouse_filter">
<return type="void">
</return>
@@ -748,7 +795,7 @@
Set the rotation (in radians).
</description>
</method>
- <method name="set_rotation_deg">
+ <method name="set_rotation_degrees">
<return type="void">
</return>
<argument index="0" name="degrees" type="float">
@@ -895,7 +942,7 @@
<member name="rect_position" type="Vector2" setter="set_position" getter="get_position">
The node's position, relative to its parent. It corresponds to the rectangle's top-left corner. The property is not affected by [member rect_pivot_offset].
</member>
- <member name="rect_rotation" type="float" setter="set_rotation_deg" getter="get_rotation_deg">
+ <member name="rect_rotation" type="float" setter="set_rotation_degrees" getter="get_rotation_degrees">
The node's rotation around its pivot, in degrees. See [member rect_pivot_offset] to change the pivot's position.
</member>
<member name="rect_scale" type="Vector2" setter="set_scale" getter="get_scale">
@@ -1096,12 +1143,20 @@
<constant name="PRESET_WIDE" value="15">
Snap all 4 anchors to the respective corners of the parent container. Set all 4 margins to 0 after you applied this preset and the [code]Control[/code] will fit its parent container. Use with [method set_anchors_preset].
</constant>
- <constant name="SIZE_EXPAND" value="2">
- Tells the parent [Container] to let this node take all the available space on the axis you flag. If multiple neighboring nodes are set to expand, they'll share the space based on their stretch ratio. See [member size_flags_stretch_ratio]. Use with [member size_flags_horizontal] and [member size_flags_vertical].
+ <constant name="PRESET_MODE_MINSIZE" value="0">
+ </constant>
+ <constant name="PRESET_MODE_KEEP_WIDTH" value="1">
+ </constant>
+ <constant name="PRESET_MODE_KEEP_HEIGHT" value="2">
+ </constant>
+ <constant name="PRESET_MODE_KEEP_SIZE" value="3">
</constant>
<constant name="SIZE_FILL" value="1">
Tells the parent [Container] to expand the bounds of this node to fill all the available space without pushing any other node. Use with [member size_flags_horizontal] and [member size_flags_vertical].
</constant>
+ <constant name="SIZE_EXPAND" value="2">
+ Tells the parent [Container] to let this node take all the available space on the axis you flag. If multiple neighboring nodes are set to expand, they'll share the space based on their stretch ratio. See [member size_flags_stretch_ratio]. Use with [member size_flags_horizontal] and [member size_flags_vertical].
+ </constant>
<constant name="SIZE_EXPAND_FILL" value="3">
Sets the node's size flags to both fill and expand. See the 2 constants above for more information.
</constant>
diff --git a/doc/classes/ConvexPolygonShape.xml b/doc/classes/ConvexPolygonShape.xml
index 9a7cb0d475..0ea140148c 100644
--- a/doc/classes/ConvexPolygonShape.xml
+++ b/doc/classes/ConvexPolygonShape.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ConvexPolygonShape" inherits="Shape" category="Core" version="3.0.alpha.custom_build">
+<class name="ConvexPolygonShape" inherits="Shape" category="Core" version="3.0-alpha">
<brief_description>
- Convex Polygon Shape.
+ Convex polygon shape for 3D physics.
</brief_description>
<description>
- Convex polygon shape resource, which can be set into a [PhysicsBody] or area.
+ Convex polygon shape resource, which can be added to a [PhysicsBody] or area.
</description>
<tutorials>
</tutorials>
@@ -28,6 +28,7 @@
</methods>
<members>
<member name="points" type="PoolVector3Array" setter="set_points" getter="get_points">
+ The list of 3D points forming the convex polygon shape.
</member>
</members>
<constants>
diff --git a/doc/classes/ConvexPolygonShape2D.xml b/doc/classes/ConvexPolygonShape2D.xml
index c5b6d90041..40507c6a6b 100644
--- a/doc/classes/ConvexPolygonShape2D.xml
+++ b/doc/classes/ConvexPolygonShape2D.xml
@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ConvexPolygonShape2D" inherits="Shape2D" category="Core" version="3.0.alpha.custom_build">
+<class name="ConvexPolygonShape2D" inherits="Shape2D" category="Core" version="3.0-alpha">
<brief_description>
Convex Polygon Shape for 2D physics.
</brief_description>
<description>
Convex Polygon Shape for 2D physics. A convex polygon, whatever its shape, is internally decomposed into as many convex polygons as needed to ensure all collision checks against it are always done on convex polygons (which are faster to check).
- The main difference between a [ConvexPolygonShape2D] and a [ConcavePolygonShape2D] is that a concave polygon assumes it is concave and uses a more complex method of collision detection, and a convex one forces itself to be convex in order to speed up collision detection.
+ The main difference between a [code]ConvexPolygonShape2D[/code] and a [ConcavePolygonShape2D] is that a concave polygon assumes it is concave and uses a more complex method of collision detection, and a convex one forces itself to be convex in order to speed up collision detection.
</description>
<tutorials>
</tutorials>
@@ -16,7 +16,7 @@
<return type="PoolVector2Array">
</return>
<description>
- Return a list of points in either clockwise or counter clockwise order, forming a convex polygon.
+ Returns a list of points in either clockwise or counter clockwise order, forming a convex polygon.
</description>
</method>
<method name="set_point_cloud">
@@ -34,12 +34,13 @@
<argument index="0" name="points" type="PoolVector2Array">
</argument>
<description>
- Set a list of points in either clockwise or counter clockwise order, forming a convex polygon.
+ Sets a list of points in either clockwise or counter clockwise order, forming a convex polygon.
</description>
</method>
</methods>
<members>
<member name="points" type="PoolVector2Array" setter="set_points" getter="get_points">
+ The polygon's list of vertices. Can be in either clockwise or counterclockwise order.
</member>
</members>
<constants>
diff --git a/doc/classes/CubeMap.xml b/doc/classes/CubeMap.xml
index ac2ff3fc57..9b0837306e 100644
--- a/doc/classes/CubeMap.xml
+++ b/doc/classes/CubeMap.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="CubeMap" inherits="Resource" category="Core" version="3.0.alpha.custom_build">
+<class name="CubeMap" inherits="Resource" category="Core" version="3.0-alpha">
<brief_description>
+ A CubeMap is a 6 sided 3D texture.
</brief_description>
<description>
+ A CubeMap is a 6 sided 3D texture typically used for faking reflections. It can be used to make an object look as if it's reflecting its surroundings. This usually delivers much better performance than other reflection methods.
</description>
<tutorials>
</tutorials>
@@ -19,6 +21,7 @@
<return type="int">
</return>
<description>
+ Returns the CubeMap's height.
</description>
</method>
<method name="get_lossy_storage_quality" qualifiers="const">
@@ -33,6 +36,7 @@
<argument index="0" name="side" type="int" enum="CubeMap.Side">
</argument>
<description>
+ Returns an [Image] for a side of the CubeMap using one of the [code]SIDE_*[/code] constants or an integer 0-5.
</description>
</method>
<method name="get_storage" qualifiers="const">
@@ -45,6 +49,7 @@
<return type="int">
</return>
<description>
+ Returns the CubeMap's width.
</description>
</method>
<method name="set_flags">
@@ -71,6 +76,7 @@
<argument index="1" name="image" type="Image">
</argument>
<description>
+ Sets an [Image] for a side of the CubeMap using one of the [code]SIDE_*[/code] constants or an integer 0-5.
</description>
</method>
<method name="set_storage">
@@ -82,6 +88,14 @@
</description>
</method>
</methods>
+ <members>
+ <member name="lossy_storage_quality" type="float" setter="set_lossy_storage_quality" getter="get_lossy_storage_quality">
+ The lossy storage quality of the CubeMap if the storage mode is set to STORAGE_COMPRESS_LOSSY.
+ </member>
+ <member name="storage_mode" type="int" setter="set_storage" getter="get_storage" enum="CubeMap.Storage">
+ The CubeMap's storage mode. See [code]STORAGE_*[/code] constants.
+ </member>
+ </members>
<constants>
<constant name="STORAGE_RAW" value="0">
</constant>
diff --git a/doc/classes/CubeMesh.xml b/doc/classes/CubeMesh.xml
index 642f37c393..4a8ad104b7 100644
--- a/doc/classes/CubeMesh.xml
+++ b/doc/classes/CubeMesh.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="CubeMesh" inherits="PrimitiveMesh" category="Core" version="3.0.alpha.custom_build">
+<class name="CubeMesh" inherits="PrimitiveMesh" category="Core" version="3.0-alpha">
<brief_description>
Generate an axis-aligned cuboid [PrimitiveMesh].
</brief_description>
diff --git a/doc/classes/Curve.xml b/doc/classes/Curve.xml
index ef43d9024c..3741f51fad 100644
--- a/doc/classes/Curve.xml
+++ b/doc/classes/Curve.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Curve" inherits="Resource" category="Core" version="3.0.alpha.custom_build">
+<class name="Curve" inherits="Resource" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
@@ -170,7 +170,7 @@
</description>
</method>
<method name="set_point_offset">
- <return type="void">
+ <return type="int">
</return>
<argument index="0" name="index" type="int">
</argument>
diff --git a/doc/classes/Curve2D.xml b/doc/classes/Curve2D.xml
index 4362887be3..0d9dfad643 100644
--- a/doc/classes/Curve2D.xml
+++ b/doc/classes/Curve2D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Curve2D" inherits="Resource" category="Core" version="3.0.alpha.custom_build">
+<class name="Curve2D" inherits="Resource" category="Core" version="3.0-alpha">
<brief_description>
Describes a Bezier curve in 2D space.
</brief_description>
@@ -32,6 +32,7 @@
<return type="void">
</return>
<description>
+ Removes all points from the curve.
</description>
</method>
<method name="get_bake_interval" qualifiers="const">
@@ -191,8 +192,10 @@
</methods>
<members>
<member name="_data" type="Dictionary" setter="_set_data" getter="_get_data">
+ The points describing the curve. Value is a [Dictionary] with the keys [code]in[/code], [code]out[/code], and [code]pos[/code]. The key pos is the position of a vertex of the curve, the key in is the vector from that position to the control point before this vertex, the key out is the vector from that position to the controlpoint after this vertex.
</member>
<member name="bake_interval" type="float" setter="set_bake_interval" getter="get_bake_interval">
+ The distance in pixels between two adjacent cached points. Changing it forces the cache to be recomputed the next time the [method get_baked_points] or [method get_baked_length] function is called. The smaller the distance, the more points in the cache and the more memory it will consume, so use with care.
</member>
</members>
<constants>
diff --git a/doc/classes/Curve3D.xml b/doc/classes/Curve3D.xml
index 02299753cf..35f8db0177 100644
--- a/doc/classes/Curve3D.xml
+++ b/doc/classes/Curve3D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Curve3D" inherits="Resource" category="Core" version="3.0.alpha.custom_build">
+<class name="Curve3D" inherits="Resource" category="Core" version="3.0-alpha">
<brief_description>
Describes a Bezier curve in 3D space.
</brief_description>
diff --git a/doc/classes/CurveTexture.xml b/doc/classes/CurveTexture.xml
index 8f8f60968a..61a6a2486f 100644
--- a/doc/classes/CurveTexture.xml
+++ b/doc/classes/CurveTexture.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="CurveTexture" inherits="Texture" category="Core" version="3.0.alpha.custom_build">
+<class name="CurveTexture" inherits="Texture" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/CylinderMesh.xml b/doc/classes/CylinderMesh.xml
index 8399312dac..8398b52ee0 100644
--- a/doc/classes/CylinderMesh.xml
+++ b/doc/classes/CylinderMesh.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="CylinderMesh" inherits="PrimitiveMesh" category="Core" version="3.0.alpha.custom_build">
+<class name="CylinderMesh" inherits="PrimitiveMesh" category="Core" version="3.0-alpha">
<brief_description>
Class representing a cylindrical [PrimitiveMesh].
</brief_description>
diff --git a/doc/classes/DampedSpringJoint2D.xml b/doc/classes/DampedSpringJoint2D.xml
index 18554820fa..da7147933d 100644
--- a/doc/classes/DampedSpringJoint2D.xml
+++ b/doc/classes/DampedSpringJoint2D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="DampedSpringJoint2D" inherits="Joint2D" category="Core" version="3.0.alpha.custom_build">
+<class name="DampedSpringJoint2D" inherits="Joint2D" category="Core" version="3.0-alpha">
<brief_description>
Damped spring constraint for 2D physics.
</brief_description>
@@ -78,12 +78,16 @@
</methods>
<members>
<member name="damping" type="float" setter="set_damping" getter="get_damping">
+ The spring joint's damping ratio. A value between [code]0[/code] and [code]1[/code]. When the two bodies move into different directions the system tries to align them to the spring axis again. A high [code]damping[/code] value forces the attached bodies to align faster. Default value: [code]1[/code]
</member>
<member name="length" type="float" setter="set_length" getter="get_length">
+ The spring joint's maximum length. The two attached bodies cannot stretch it past this value. Default value: [code]50[/code]
</member>
<member name="rest_length" type="float" setter="set_rest_length" getter="get_rest_length">
+ When the bodies attached to the spring joint move they stretch or squash it. The joint always tries to resize towards this length. Default value: [code]0[/code]
</member>
<member name="stiffness" type="float" setter="set_stiffness" getter="get_stiffness">
+ The higher the value, the less the bodies attached to the joint will deform it. The joint applies an opposing force to the bodies, the product of the stiffness multiplied by the size difference from its resting length. Default value: [code]20[/code]
</member>
</members>
<constants>
diff --git a/doc/classes/Dictionary.xml b/doc/classes/Dictionary.xml
index 447c0d7ed3..5664b2079b 100644
--- a/doc/classes/Dictionary.xml
+++ b/doc/classes/Dictionary.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Dictionary" category="Built-In Types" version="3.0.alpha.custom_build">
+<class name="Dictionary" category="Built-In Types" version="3.0-alpha">
<brief_description>
Dictionary type.
</brief_description>
@@ -59,7 +59,7 @@
<return type="Array">
</return>
<description>
- Return the list of keys in the [Dictionary].
+ Return the list of keys in the [code]Dictionary[/code].
</description>
</method>
<method name="size">
@@ -73,7 +73,7 @@
<return type="Array">
</return>
<description>
- Return the list of values in the [Dictionary].
+ Return the list of values in the [code]Dictionary[/code].
</description>
</method>
</methods>
diff --git a/doc/classes/DirectionalLight.xml b/doc/classes/DirectionalLight.xml
index 7de1791519..f0cc007339 100644
--- a/doc/classes/DirectionalLight.xml
+++ b/doc/classes/DirectionalLight.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="DirectionalLight" inherits="Light" category="Core" version="3.0.alpha.custom_build">
+<class name="DirectionalLight" inherits="Light" category="Core" version="3.0-alpha">
<brief_description>
Directional Light, such as the Sun or the Moon.
</brief_description>
diff --git a/doc/classes/Directory.xml b/doc/classes/Directory.xml
index ee0b873084..b11e0629cd 100644
--- a/doc/classes/Directory.xml
+++ b/doc/classes/Directory.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Directory" inherits="Reference" category="Core" version="3.0.alpha.custom_build">
+<class name="Directory" inherits="Reference" category="Core" version="3.0-alpha">
<brief_description>
Type used to handle the filesystem.
</brief_description>
@@ -34,7 +34,7 @@
</argument>
<description>
Change the currently opened directory to the one passed as an argument. The argument can be relative to the current directory (e.g. [code]newdir[/code] or [code]../newdir[/code]), or an absolute path (e.g. [code]/tmp/newdir[/code] or [code]res://somedir/newdir[/code]).
- The method returns one of the error code constants defined in [@Global Scope] (OK or ERR_*).
+ The method returns one of the error code constants defined in [@GlobalScope] (OK or ERR_*).
</description>
</method>
<method name="copy">
@@ -46,7 +46,7 @@
</argument>
<description>
Copy the [i]from[/i] file to the [i]to[/i] destination. Both arguments should be paths to files, either relative or absolute. If the destination file exists and is not access-protected, it will be overwritten.
- Returns one of the error code constants defined in [@Global Scope] (OK, FAILED or ERR_*).
+ Returns one of the error code constants defined in [@GlobalScope] (OK, FAILED or ERR_*).
</description>
</method>
<method name="current_is_dir" qualifiers="const">
@@ -85,6 +85,7 @@
<return type="int">
</return>
<description>
+ Returns the currently opened directory's drive index. See [method get_drive] to convert returned index to the name of the drive.
</description>
</method>
<method name="get_drive">
@@ -145,7 +146,7 @@
</argument>
<description>
Create a directory. The argument can be relative to the current directory, or an absolute path. The target directory should be placed in an already existing directory (to create the full path recursively, see [method make_dir_recursive]).
- The method returns one of the error code constants defined in [@Global Scope] (OK, FAILED or ERR_*).
+ The method returns one of the error code constants defined in [@GlobalScope] (OK, FAILED or ERR_*).
</description>
</method>
<method name="make_dir_recursive">
@@ -155,7 +156,7 @@
</argument>
<description>
Create a target directory and all necessary intermediate directories in its path, by calling [method make_dir] recursively. The argument can be relative to the current directory, or an absolute path.
- Return one of the error code constants defined in [@Global Scope] (OK, FAILED or ERR_*).
+ Return one of the error code constants defined in [@GlobalScope] (OK, FAILED or ERR_*).
</description>
</method>
<method name="open">
@@ -165,7 +166,7 @@
</argument>
<description>
Open an existing directory of the filesystem. The [i]path[/i] argument can be within the project tree ([code]res://folder[/code]), the user directory ([code]user://folder[/code]) or an absolute path of the user filesystem (e.g. [code]/tmp/folder[/code] or [code]C:\tmp\folder[/code]).
- The method returns one of the error code constants defined in [@Global Scope] (OK or ERR_*).
+ The method returns one of the error code constants defined in [@GlobalScope] (OK or ERR_*).
</description>
</method>
<method name="remove">
@@ -175,7 +176,7 @@
</argument>
<description>
Delete the target file or an empty directory. The argument can be relative to the current directory, or an absolute path. If the target directory is not empty, the operation will fail.
- Return one of the error code constants defined in [@Global Scope] (OK or FAILED).
+ Return one of the error code constants defined in [@GlobalScope] (OK or FAILED).
</description>
</method>
<method name="rename">
@@ -187,7 +188,7 @@
</argument>
<description>
Rename (move) the [i]from[/i] file to the [i]to[/i] destination. Both arguments should be paths to files, either relative or absolute. If the destination file exists and is not access-protected, it will be overwritten.
- Return one of the error code constants defined in [@Global Scope] (OK or FAILED).
+ Return one of the error code constants defined in [@GlobalScope] (OK or FAILED).
</description>
</method>
</methods>
diff --git a/doc/classes/DynamicFont.xml b/doc/classes/DynamicFont.xml
index e4ce2ff3f0..9149e14a62 100644
--- a/doc/classes/DynamicFont.xml
+++ b/doc/classes/DynamicFont.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="DynamicFont" inherits="Font" category="Core" version="3.0.alpha.custom_build">
+<class name="DynamicFont" inherits="Font" category="Core" version="3.0-alpha">
<brief_description>
+ DynamicFont renders vector font files at runtime.
</brief_description>
<description>
+ DynamicFont renders vector font files (such as TTF or OTF) dynamically at runtime instead of using a prerendered texture atlas like [BitmapFont]. This trades the faster loading time of [BitmapFont]s for the ability to change font parameters like size and spacing during runtime. [DynamicFontData] is used for referencing the font file paths.
</description>
<tutorials>
</tutorials>
@@ -15,6 +17,7 @@
<argument index="0" name="data" type="DynamicFontData">
</argument>
<description>
+ Adds a fallback font.
</description>
</method>
<method name="get_fallback" qualifiers="const">
@@ -23,12 +26,14 @@
<argument index="0" name="idx" type="int">
</argument>
<description>
+ Returns the fallback font at index [code]idx[/code].
</description>
</method>
<method name="get_fallback_count" qualifiers="const">
<return type="int">
</return>
<description>
+ Returns the number of fallback fonts.
</description>
</method>
<method name="get_font_data" qualifiers="const">
@@ -41,6 +46,7 @@
<return type="int">
</return>
<description>
+ Returns the font size in pixels.
</description>
</method>
<method name="get_spacing" qualifiers="const">
@@ -49,18 +55,21 @@
<argument index="0" name="type" type="int">
</argument>
<description>
+ Returns the given type of spacing in pixels. See [code]SPACING_*[/code] constants.
</description>
</method>
<method name="get_use_filter" qualifiers="const">
<return type="bool">
</return>
<description>
+ Returns [code]true[/code] if filtering is used.
</description>
</method>
<method name="get_use_mipmaps" qualifiers="const">
<return type="bool">
</return>
<description>
+ Returns [code]true[/code] if mipmapping is used.
</description>
</method>
<method name="remove_fallback">
@@ -69,6 +78,7 @@
<argument index="0" name="idx" type="int">
</argument>
<description>
+ Removes the fallback font at index [code]idx[/code].
</description>
</method>
<method name="set_fallback">
@@ -79,6 +89,7 @@
<argument index="1" name="data" type="DynamicFontData">
</argument>
<description>
+ Sets the fallback font at index [code]idx[/code].
</description>
</method>
<method name="set_font_data">
@@ -87,6 +98,7 @@
<argument index="0" name="data" type="DynamicFontData">
</argument>
<description>
+ Sets the [DynamicFontData].
</description>
</method>
<method name="set_size">
@@ -95,6 +107,7 @@
<argument index="0" name="data" type="int">
</argument>
<description>
+ Sets the font size.
</description>
</method>
<method name="set_spacing">
@@ -105,6 +118,7 @@
<argument index="1" name="value" type="int">
</argument>
<description>
+ Sets the spacing of the given type. See [code]SPACING_*[/code] constants.
</description>
</method>
<method name="set_use_filter">
@@ -113,6 +127,7 @@
<argument index="0" name="enable" type="bool">
</argument>
<description>
+ Set to [code]true[/code] to use filtering.
</description>
</method>
<method name="set_use_mipmaps">
@@ -121,35 +136,48 @@
<argument index="0" name="enable" type="bool">
</argument>
<description>
+ Set to [code]true[/code] to use mipmapping.
</description>
</method>
</methods>
<members>
<member name="extra_spacing_bottom" type="int" setter="set_spacing" getter="get_spacing">
+ Extra spacing at the bottom in pixels.
</member>
<member name="extra_spacing_char" type="int" setter="set_spacing" getter="get_spacing">
+ Extra character spacing in pixels.
</member>
<member name="extra_spacing_space" type="int" setter="set_spacing" getter="get_spacing">
+ Extra space spacing in pixels.
</member>
<member name="extra_spacing_top" type="int" setter="set_spacing" getter="get_spacing">
+ Extra spacing at the top in pixels.
</member>
<member name="font_data" type="DynamicFontData" setter="set_font_data" getter="get_font_data">
+ The font data.
</member>
<member name="size" type="int" setter="set_size" getter="get_size">
+ The font size.
</member>
<member name="use_filter" type="bool" setter="set_use_filter" getter="get_use_filter">
+ If [code]true[/code] filtering is used.
</member>
<member name="use_mipmaps" type="bool" setter="set_use_mipmaps" getter="get_use_mipmaps">
+ If [code]true[/code] mipmapping is used.
</member>
</members>
<constants>
<constant name="SPACING_TOP" value="0">
+ Spacing at the top.
</constant>
<constant name="SPACING_BOTTOM" value="1">
+ Spacing at the bottom.
</constant>
<constant name="SPACING_CHAR" value="2">
+ Character spacing.
</constant>
<constant name="SPACING_SPACE" value="3">
+ Space spacing.
</constant>
</constants>
</class>
diff --git a/doc/classes/DynamicFontData.xml b/doc/classes/DynamicFontData.xml
index 51e4e0d231..26529006cb 100644
--- a/doc/classes/DynamicFontData.xml
+++ b/doc/classes/DynamicFontData.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="DynamicFontData" inherits="Resource" category="Core" version="3.0.alpha.custom_build">
+<class name="DynamicFontData" inherits="Resource" category="Core" version="3.0-alpha">
<brief_description>
+ Used with [DynamicFont] to describe the location of a font file.
</brief_description>
<description>
+ Used with [DynamicFont] to describe the location of a vector font file for dynamic rendering at runtime.
</description>
<tutorials>
</tutorials>
@@ -13,6 +15,7 @@
<return type="String">
</return>
<description>
+ Returns the font path.
</description>
</method>
<method name="set_font_path">
@@ -21,11 +24,13 @@
<argument index="0" name="path" type="String">
</argument>
<description>
+ Sets the font path.
</description>
</method>
</methods>
<members>
<member name="font_path" type="String" setter="set_font_path" getter="get_font_path">
+ The path to the vector font file.
</member>
</members>
<constants>
diff --git a/doc/classes/EditorExportPlugin.xml b/doc/classes/EditorExportPlugin.xml
index b0ed24b767..a3bab32476 100644
--- a/doc/classes/EditorExportPlugin.xml
+++ b/doc/classes/EditorExportPlugin.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="EditorExportPlugin" inherits="Reference" category="Core" version="3.0.alpha.custom_build">
+<class name="EditorExportPlugin" inherits="Reference" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/EditorFileDialog.xml b/doc/classes/EditorFileDialog.xml
index 6ae893f189..f29d9fd4dd 100644
--- a/doc/classes/EditorFileDialog.xml
+++ b/doc/classes/EditorFileDialog.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="EditorFileDialog" inherits="ConfirmationDialog" category="Core" version="3.0.alpha.custom_build">
+<class name="EditorFileDialog" inherits="ConfirmationDialog" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/EditorFileSystem.xml b/doc/classes/EditorFileSystem.xml
index 6a2f811425..afec85184c 100644
--- a/doc/classes/EditorFileSystem.xml
+++ b/doc/classes/EditorFileSystem.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="EditorFileSystem" inherits="Node" category="Core" version="3.0.alpha.custom_build">
+<class name="EditorFileSystem" inherits="Node" category="Core" version="3.0-alpha">
<brief_description>
Resource filesystem, as the editor sees it.
</brief_description>
diff --git a/doc/classes/EditorFileSystemDirectory.xml b/doc/classes/EditorFileSystemDirectory.xml
index 7d284f864e..99bca09eb6 100644
--- a/doc/classes/EditorFileSystemDirectory.xml
+++ b/doc/classes/EditorFileSystemDirectory.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="EditorFileSystemDirectory" inherits="Object" category="Core" version="3.0.alpha.custom_build">
+<class name="EditorFileSystemDirectory" inherits="Object" category="Core" version="3.0-alpha">
<brief_description>
A diretory for the resource filesystem.
</brief_description>
diff --git a/doc/classes/EditorImportPlugin.xml b/doc/classes/EditorImportPlugin.xml
index 05319e926c..9836fb2527 100644
--- a/doc/classes/EditorImportPlugin.xml
+++ b/doc/classes/EditorImportPlugin.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="EditorImportPlugin" inherits="Reference" category="Core" version="3.0.alpha.custom_build">
+<class name="EditorImportPlugin" inherits="Reference" category="Core" version="3.0-alpha">
<brief_description>
Registers a custom resource importer in the editor. Use the class to parse any file and import it as a new resource type.
</brief_description>
@@ -35,12 +35,12 @@
func get_preset_name(i):
return "Default"
- func get_import_optons(i):
+ func get_import_options(i):
return [{"name": "my_option", "default_value": false}]
func load(src, dst, opts, r_platform_variants, r_gen_files):
- var f = File.new()
- if f.open(src, File.READ) != OK:
+ var file = File.new()
+ if file.open(src, File.READ) != OK:
return FAILED
var mesh = Mesh.new()
diff --git a/doc/classes/EditorInterface.xml b/doc/classes/EditorInterface.xml
index 0422e9a64e..0059804c00 100644
--- a/doc/classes/EditorInterface.xml
+++ b/doc/classes/EditorInterface.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="EditorInterface" inherits="Node" category="Core" version="3.0.alpha.custom_build">
+<class name="EditorInterface" inherits="Node" category="Core" version="3.0-alpha">
<brief_description>
+ Editor interface and main components.
</brief_description>
<description>
+ Editor interface. Allows saving and (re-)loading scenes, rendering mesh previews, inspecting and editing resources and objects and provides access to [EditorSettings], [EditorFileSystem], [EditorResourcePreview]\ er, [ScriptEditor], the editor viewport, as well as information about scenes. Also see [EditorPlugin] and [EditorScript].
</description>
<tutorials>
</tutorials>
@@ -15,60 +17,70 @@
<argument index="0" name="resource" type="Resource">
</argument>
<description>
+ Edits the given [Resource].
</description>
</method>
<method name="get_base_control">
<return type="Control">
</return>
<description>
+ Returns the base [Control].
</description>
</method>
<method name="get_edited_scene_root">
<return type="Node">
</return>
<description>
+ Returns the edited scene's root [Node].
</description>
</method>
<method name="get_editor_settings">
<return type="EditorSettings">
</return>
<description>
+ Returns the [EditorSettings].
</description>
</method>
<method name="get_editor_viewport">
<return type="Control">
</return>
<description>
+ Returns the editor [Viewport].
</description>
</method>
<method name="get_open_scenes" qualifiers="const">
<return type="Array">
</return>
<description>
+ Returns an [Array] of the currently opened scenes.
</description>
</method>
<method name="get_resource_filesystem">
<return type="EditorFileSystem">
</return>
<description>
+ Returns the [EditorFileSystem].
</description>
</method>
<method name="get_resource_previewer">
<return type="EditorResourcePreview">
</return>
<description>
+ Returns the [EditorResourcePreview]\ er.
</description>
</method>
<method name="get_script_editor">
<return type="ScriptEditor">
</return>
<description>
+ Returns the [ScriptEditor].
</description>
</method>
<method name="get_selection">
<return type="EditorSelection">
</return>
<description>
+ Returns the [EditorSelection].
</description>
</method>
<method name="inspect_object">
@@ -79,16 +91,18 @@
<argument index="1" name="for_property" type="String" default="&quot;&quot;">
</argument>
<description>
+ Shows the given property on the given [code]object[/code] in the Editor's Inspector dock.
</description>
</method>
<method name="make_mesh_previews">
<return type="Array">
</return>
- <argument index="0" name="arg0" type="Array">
+ <argument index="0" name="meshes" type="Array">
</argument>
- <argument index="1" name="arg1" type="int">
+ <argument index="1" name="preview_size" type="int">
</argument>
<description>
+ Returns mesh previews rendered at the given size as an [Array] of [Texture]s.
</description>
</method>
<method name="open_scene_from_path">
@@ -97,6 +111,7 @@
<argument index="0" name="scene_filepath" type="String">
</argument>
<description>
+ Opens the scene at the given path.
</description>
</method>
<method name="reload_scene_from_path">
@@ -105,12 +120,14 @@
<argument index="0" name="scene_filepath" type="String">
</argument>
<description>
+ Reloads the scene at the given path.
</description>
</method>
<method name="save_scene">
<return type="int" enum="Error">
</return>
<description>
+ Saves the scene. Returns either OK or ERR_CANT_CREATE. See [@GlobalScope] constants.
</description>
</method>
<method name="save_scene_as">
@@ -121,6 +138,7 @@
<argument index="1" name="with_preview" type="bool" default="true">
</argument>
<description>
+ Saves the scene as a file at [code]path[/code].
</description>
</method>
</methods>
diff --git a/doc/classes/EditorPlugin.xml b/doc/classes/EditorPlugin.xml
index 2831555d41..f9bdf1dcd5 100644
--- a/doc/classes/EditorPlugin.xml
+++ b/doc/classes/EditorPlugin.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="EditorPlugin" inherits="Node" category="Core" version="3.0.alpha.custom_build">
+<class name="EditorPlugin" inherits="Node" category="Core" version="3.0-alpha">
<brief_description>
Used by the editor to extend its functionality.
</brief_description>
@@ -366,6 +366,8 @@
</constant>
<constant name="CONTAINER_CANVAS_EDITOR_SIDE" value="5">
</constant>
+ <constant name="CONTAINER_CANVAS_EDITOR_BOTTOM" value="6">
+ </constant>
<constant name="CONTAINER_PROPERTY_EDITOR_BOTTOM" value="7">
</constant>
<constant name="DOCK_SLOT_LEFT_UL" value="0">
diff --git a/doc/classes/EditorResourceConversionPlugin.xml b/doc/classes/EditorResourceConversionPlugin.xml
index e165ae376b..6fbb60ddf6 100644
--- a/doc/classes/EditorResourceConversionPlugin.xml
+++ b/doc/classes/EditorResourceConversionPlugin.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="EditorResourceConversionPlugin" inherits="Reference" category="Core" version="3.0.alpha.custom_build">
+<class name="EditorResourceConversionPlugin" inherits="Reference" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/EditorResourcePreview.xml b/doc/classes/EditorResourcePreview.xml
index acf36b6a08..44f60d4d2c 100644
--- a/doc/classes/EditorResourcePreview.xml
+++ b/doc/classes/EditorResourcePreview.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="EditorResourcePreview" inherits="Node" category="Core" version="3.0.alpha.custom_build">
+<class name="EditorResourcePreview" inherits="Node" category="Core" version="3.0-alpha">
<brief_description>
- Helper to generate previews of reources or files.
+ Helper to generate previews of resources or files.
</brief_description>
<description>
This object is used to generate previews for resources of files.
diff --git a/doc/classes/EditorResourcePreviewGenerator.xml b/doc/classes/EditorResourcePreviewGenerator.xml
index 231198516e..3de0dbc708 100644
--- a/doc/classes/EditorResourcePreviewGenerator.xml
+++ b/doc/classes/EditorResourcePreviewGenerator.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="EditorResourcePreviewGenerator" inherits="Reference" category="Core" version="3.0.alpha.custom_build">
+<class name="EditorResourcePreviewGenerator" inherits="Reference" category="Core" version="3.0-alpha">
<brief_description>
Custom generator of previews.
</brief_description>
diff --git a/doc/classes/EditorScript.xml b/doc/classes/EditorScript.xml
index 48cf3e9843..1e46164fc6 100644
--- a/doc/classes/EditorScript.xml
+++ b/doc/classes/EditorScript.xml
@@ -1,10 +1,19 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="EditorScript" inherits="Reference" category="Core" version="3.0.alpha.custom_build">
+<class name="EditorScript" inherits="Reference" category="Core" version="3.0-alpha">
<brief_description>
- Simple script to perform changes in the currently edited scene.
+ Base script that can be used to add extension functions to the editor.
</brief_description>
<description>
- This script can be run from the Scene -&gt; Run Script menu option.
+ Scripts extending this class and implementing its [code]_run()[/code] method can be executed from the Script Editor's [code]File -&gt; Run[/code] menu option (or by pressing [code]CTRL+Shift+X[/code]) while the editor is running. This is useful for adding custom in-editor functionality to Godot. For more complex additions, consider using [EditorPlugin]s instead. Note that extending scripts need to have [code]tool mode[/code] enabled.
+ Example script:
+ [codeblock]
+ tool
+ extends EditorScript
+
+ func _run():
+ print("Hello from the Godot Editor!")
+ [/codeblock]
+ Note that the script is run in the Editor context, which means the output is visible in the console window started with the Editor (STDOUT) instead of the usual Godot [i]Output[/i] dock.
</description>
<tutorials>
</tutorials>
@@ -15,6 +24,7 @@
<return type="void">
</return>
<description>
+ This method is executed by the Editor when [code]File -&gt; Run[/code] is used.
</description>
</method>
<method name="add_root_node">
@@ -29,12 +39,14 @@
<return type="EditorInterface">
</return>
<description>
+ Returns the [EditorInterface] singleton instance.
</description>
</method>
<method name="get_scene">
<return type="Node">
</return>
<description>
+ Returns the Editor's currently active scene.
</description>
</method>
</methods>
diff --git a/doc/classes/EditorSelection.xml b/doc/classes/EditorSelection.xml
index 8d9bdd2c05..999cb5e505 100644
--- a/doc/classes/EditorSelection.xml
+++ b/doc/classes/EditorSelection.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="EditorSelection" inherits="Object" category="Core" version="3.0.alpha.custom_build">
+<class name="EditorSelection" inherits="Object" category="Core" version="3.0-alpha">
<brief_description>
Manages the SceneTree selection in the editor.
</brief_description>
@@ -31,7 +31,7 @@
<return type="Array">
</return>
<description>
- Get the list of selectes nodes.
+ Get the list of selected nodes.
</description>
</method>
<method name="get_transformable_selected_nodes">
diff --git a/doc/classes/EditorSettings.xml b/doc/classes/EditorSettings.xml
index 37c7a47a51..e58516d461 100644
--- a/doc/classes/EditorSettings.xml
+++ b/doc/classes/EditorSettings.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="EditorSettings" inherits="Resource" category="Core" version="3.0.alpha.custom_build">
+<class name="EditorSettings" inherits="Resource" category="Core" version="3.0-alpha">
<brief_description>
Object that holds the project-independent editor settings.
</brief_description>
@@ -23,7 +23,7 @@
<argument index="0" name="info" type="Dictionary">
</argument>
<description>
- Add a custom property info to a property. The dictionary must contain: name:[String](the name of the property) and type:[int](see TYPE_* in [@Global Scope]), and optionally hint:[int](see PROPERTY_HINT_* in [@Global Scope]), hint_string:[String].
+ Add a custom property info to a property. The dictionary must contain: name:[String](the name of the property) and type:[int](see TYPE_* in [@GlobalScope]), and optionally hint:[int](see PROPERTY_HINT_* in [@GlobalScope]), hint_string:[String].
Example:
[codeblock]
editor_settings.set("category/property_name", 0)
@@ -55,7 +55,7 @@
Get the list of favorite directories for this project.
</description>
</method>
- <method name="get_project_settings_path" qualifiers="const">
+ <method name="get_project_settings_dir" qualifiers="const">
<return type="String">
</return>
<description>
@@ -69,7 +69,15 @@
Get the list of recently visited folders in the file dialog for this project.
</description>
</method>
- <method name="get_settings_path" qualifiers="const">
+ <method name="get_setting" qualifiers="const">
+ <return type="Variant">
+ </return>
+ <argument index="0" name="name" type="String">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="get_settings_dir" qualifiers="const">
<return type="String">
</return>
<description>
@@ -78,6 +86,30 @@
settings/templates - where export templates are located
</description>
</method>
+ <method name="has_setting" qualifiers="const">
+ <return type="bool">
+ </return>
+ <argument index="0" name="name" type="String">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="property_can_revert">
+ <return type="bool">
+ </return>
+ <argument index="0" name="name" type="String">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="property_get_revert">
+ <return type="Variant">
+ </return>
+ <argument index="0" name="name" type="String">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="set_favorite_dirs">
<return type="void">
</return>
@@ -87,6 +119,16 @@
Set the list of favorite directories for this project.
</description>
</method>
+ <method name="set_initial_value">
+ <return type="void">
+ </return>
+ <argument index="0" name="name" type="String">
+ </argument>
+ <argument index="1" name="value" type="Variant">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="set_recent_dirs">
<return type="void">
</return>
@@ -96,6 +138,16 @@
Set the list of recently visited folders in the file dialog for this project.
</description>
</method>
+ <method name="set_setting">
+ <return type="void">
+ </return>
+ <argument index="0" name="name" type="String">
+ </argument>
+ <argument index="1" name="value" type="Variant">
+ </argument>
+ <description>
+ </description>
+ </method>
</methods>
<signals>
<signal name="settings_changed">
diff --git a/doc/classes/EditorSpatialGizmo.xml b/doc/classes/EditorSpatialGizmo.xml
index baab995fab..758024c99b 100644
--- a/doc/classes/EditorSpatialGizmo.xml
+++ b/doc/classes/EditorSpatialGizmo.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="EditorSpatialGizmo" inherits="SpatialGizmo" category="Core" version="3.0.alpha.custom_build">
+<class name="EditorSpatialGizmo" inherits="SpatialGizmo" category="Core" version="3.0-alpha">
<brief_description>
Custom gizmo for editing Spatial objects.
</brief_description>
@@ -24,7 +24,7 @@
</return>
<argument index="0" name="triangles" type="TriangleMesh">
</argument>
- <argument index="1" name="bounds" type="Rect3">
+ <argument index="1" name="bounds" type="AABB">
</argument>
<description>
Add collision triangles to the gizmo for picking. A [TriangleMesh] can be generated from a regular [Mesh] too. Call this function during [method redraw].
@@ -96,7 +96,7 @@
<argument index="2" name="cancel" type="bool" default="false">
</argument>
<description>
- Commit a handle being edited (handles must have been prevously added by [method add_handles]).
+ Commit a handle being edited (handles must have been previously added by [method add_handles]).
If the cancel parameter is true, an option to restore the edited value to the original is provided.
</description>
</method>
diff --git a/doc/classes/EncodedObjectAsID.xml b/doc/classes/EncodedObjectAsID.xml
index 412e60bf99..41839e3d01 100644
--- a/doc/classes/EncodedObjectAsID.xml
+++ b/doc/classes/EncodedObjectAsID.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="EncodedObjectAsID" inherits="Reference" category="Core" version="3.0.alpha.custom_build">
+<class name="EncodedObjectAsID" inherits="Reference" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/Engine.xml b/doc/classes/Engine.xml
index 2372c619f5..090e0d7910 100644
--- a/doc/classes/Engine.xml
+++ b/doc/classes/Engine.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Engine" inherits="Object" category="Core" version="3.0.alpha.custom_build">
+<class name="Engine" inherits="Object" category="Core" version="3.0-alpha">
<brief_description>
+ Access to basic engine properties.
</brief_description>
<description>
+ The [code]Engine[/code] class allows you to query and modify the game's run-time parameters, such as frames per second, time scale, and others.
</description>
<tutorials>
</tutorials>
@@ -13,7 +15,7 @@
<return type="int">
</return>
<description>
- Return the total amount of frames drawn.
+ Returns the total number of frames drawn.
</description>
</method>
<method name="get_frames_per_second" qualifiers="const">
@@ -27,26 +29,36 @@
<return type="int">
</return>
<description>
- Return the amount of fixed iterations per second (for fixed process and physics).
+ Returns the number of fixed iterations per second (for fixed process and physics).
</description>
</method>
<method name="get_main_loop" qualifiers="const">
<return type="MainLoop">
</return>
<description>
- Return the main loop object (see [MainLoop] and [SceneTree]).
+ Returns the main loop object (see [MainLoop] and [SceneTree]).
+ </description>
+ </method>
+ <method name="get_singleton" qualifiers="const">
+ <return type="Object">
+ </return>
+ <argument index="0" name="name" type="String">
+ </argument>
+ <description>
</description>
</method>
<method name="get_target_fps" qualifiers="const">
<return type="float">
</return>
<description>
+ Returns the desired frames per second. If the hardware cannot keep up, this setting may not be respected. It defaults to 0, which indicates no limit.
</description>
</method>
<method name="get_time_scale">
<return type="float">
</return>
<description>
+ Returns how fast or slow the in-game clock ticks versus the real life one. It defaults to 1.0. A value of 2.0 means the game moves twice as fast as real life, whilst a value of 0.5 means the game moves at half the regular speed.
</description>
</method>
<method name="get_version_info" qualifiers="const">
@@ -59,20 +71,30 @@
"minor" - Holds the minor version number as a String
"patch" - Holds the patch version number as a String
"status" - Holds the status (e.g. "beta", "rc1", "rc2", ... "stable") as a String
- "revision" - Holds the revision (e.g. "custom-build") as a String
- "string" - major + minor + patch + status + revision in a single String
+ "build" - Holds the build name (e.g. "custom-build") as a String
+ "string" - major + minor + patch + status + build in a single String
+ </description>
+ </method>
+ <method name="has_singleton" qualifiers="const">
+ <return type="bool">
+ </return>
+ <argument index="0" name="name" type="String">
+ </argument>
+ <description>
</description>
</method>
<method name="is_editor_hint" qualifiers="const">
<return type="bool">
</return>
<description>
+ Returns [code]true[/code] if the editor is running.
</description>
</method>
- <method name="is_in_fixed_frame" qualifiers="const">
+ <method name="is_in_physics_frame" qualifiers="const">
<return type="bool">
</return>
<description>
+ Returns [code]true[/code] if the game is inside the fixed process and physics phase of the game loop.
</description>
</method>
<method name="set_editor_hint">
@@ -81,6 +103,7 @@
<argument index="0" name="enabled" type="bool">
</argument>
<description>
+ Sets the running inside the editor hint if [code]enabled[/code] is [code]true[/code].
</description>
</method>
<method name="set_iterations_per_second">
@@ -89,7 +112,7 @@
<argument index="0" name="iterations_per_second" type="int">
</argument>
<description>
- Set the amount of fixed iterations per second (for fixed process and physics).
+ Sets the number of fixed iterations per second (for fixed process and physics).
</description>
</method>
<method name="set_target_fps">
@@ -98,6 +121,7 @@
<argument index="0" name="target_fps" type="int">
</argument>
<description>
+ Sets the target frames per second.
</description>
</method>
<method name="set_time_scale">
@@ -106,6 +130,7 @@
<argument index="0" name="time_scale" type="float">
</argument>
<description>
+ Sets the time scale.
</description>
</method>
</methods>
diff --git a/doc/classes/Environment.xml b/doc/classes/Environment.xml
index 3880c45a86..285caa8d0a 100644
--- a/doc/classes/Environment.xml
+++ b/doc/classes/Environment.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Environment" inherits="Resource" category="Core" version="3.0">
+<class name="Environment" inherits="Resource" category="Core" version="3.0-alpha">
<brief_description>
Resource for environment nodes (like [WorldEnvironment]) that define multiple rendering options.
</brief_description>
@@ -226,7 +226,7 @@
<description>
</description>
</method>
- <method name="get_sky_scale" qualifiers="const">
+ <method name="get_sky_custom_fov" qualifiers="const">
<return type="float">
</return>
<description>
@@ -238,6 +238,12 @@
<description>
</description>
</method>
+ <method name="get_ssao_blur" qualifiers="const">
+ <return type="int" enum="Environment.SSAOBlur">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="get_ssao_color" qualifiers="const">
<return type="Color">
</return>
@@ -250,6 +256,12 @@
<description>
</description>
</method>
+ <method name="get_ssao_edge_sharpness" qualifiers="const">
+ <return type="float">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="get_ssao_intensity" qualifiers="const">
<return type="float">
</return>
@@ -262,6 +274,12 @@
<description>
</description>
</method>
+ <method name="get_ssao_quality" qualifiers="const">
+ <return type="int" enum="Environment.SSAOQuality">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="get_ssao_radius" qualifiers="const">
<return type="float">
</return>
@@ -408,12 +426,6 @@
<description>
</description>
</method>
- <method name="is_ssao_blur_enabled" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
<method name="is_ssao_enabled" qualifiers="const">
<return type="bool">
</return>
@@ -794,7 +806,7 @@
<description>
</description>
</method>
- <method name="set_sky_scale">
+ <method name="set_sky_custom_fov">
<return type="void">
</return>
<argument index="0" name="scale" type="float">
@@ -813,7 +825,7 @@
<method name="set_ssao_blur">
<return type="void">
</return>
- <argument index="0" name="enabled" type="bool">
+ <argument index="0" name="mode" type="int" enum="Environment.SSAOBlur">
</argument>
<description>
</description>
@@ -834,6 +846,14 @@
<description>
</description>
</method>
+ <method name="set_ssao_edge_sharpness">
+ <return type="void">
+ </return>
+ <argument index="0" name="edge_sharpness" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="set_ssao_enabled">
<return type="void">
</return>
@@ -858,6 +878,14 @@
<description>
</description>
</method>
+ <method name="set_ssao_quality">
+ <return type="void">
+ </return>
+ <argument index="0" name="quality" type="int" enum="Environment.SSAOQuality">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="set_ssao_radius">
<return type="void">
</return>
@@ -1042,8 +1070,8 @@
<member name="background_sky" type="Sky" setter="set_sky" getter="get_sky">
[Sky] resource defined as background.
</member>
- <member name="background_sky_scale" type="float" setter="set_sky_scale" getter="get_sky_scale">
- [Sky] resource's scale.
+ <member name="background_sky_custom_fov" type="float" setter="set_sky_custom_fov" getter="get_sky_custom_fov">
+ [Sky] resource's custom field of view.
</member>
<member name="dof_blur_far_amount" type="float" setter="set_dof_blur_far_amount" getter="get_dof_blur_far_amount">
Amount of far blur.
@@ -1172,10 +1200,12 @@
</member>
<member name="ssao_bias" type="float" setter="set_ssao_bias" getter="get_ssao_bias">
</member>
- <member name="ssao_blur" type="bool" setter="set_ssao_blur" getter="is_ssao_blur_enabled">
+ <member name="ssao_blur" type="int" setter="set_ssao_blur" getter="is_ssao_blur_enabled" enum="Environment.SSAOBlur">
</member>
<member name="ssao_color" type="Color" setter="set_ssao_color" getter="get_ssao_color">
</member>
+ <member name="ssao_edge_sharpness" type="float" setter="set_ssao_edge_sharpness" getter="get_ssao_edge_sharpness">
+ </member>
<member name="ssao_enabled" type="bool" setter="set_ssao_enabled" getter="is_ssao_enabled">
</member>
<member name="ssao_intensity" type="float" setter="set_ssao_intensity" getter="get_ssao_intensity">
@@ -1184,6 +1214,8 @@
</member>
<member name="ssao_light_affect" type="float" setter="set_ssao_direct_light_affect" getter="get_ssao_direct_light_affect">
</member>
+ <member name="ssao_quality" type="int" setter="set_ssao_quality" getter="get_ssao_quality" enum="Environment.SSAOQuality">
+ </member>
<member name="ssao_radius" type="float" setter="set_ssao_radius" getter="get_ssao_radius">
</member>
<member name="ssao_radius2" type="float" setter="set_ssao_radius2" getter="get_ssao_radius2">
@@ -1253,5 +1285,19 @@
<constant name="DOF_BLUR_QUALITY_HIGH" value="2">
High depth-of-field blur quality.
</constant>
+ <constant name="SSAO_BLUR_DISABLED" value="0">
+ </constant>
+ <constant name="SSAO_BLUR_1x1" value="1">
+ </constant>
+ <constant name="SSAO_BLUR_2x2" value="2">
+ </constant>
+ <constant name="SSAO_BLUR_3x3" value="3">
+ </constant>
+ <constant name="SSAO_QUALITY_LOW" value="0">
+ </constant>
+ <constant name="SSAO_QUALITY_MEDIUM" value="1">
+ </constant>
+ <constant name="SSAO_QUALITY_HIGH" value="2">
+ </constant>
</constants>
</class>
diff --git a/doc/classes/File.xml b/doc/classes/File.xml
index e1a024270e..8ec56e9c48 100644
--- a/doc/classes/File.xml
+++ b/doc/classes/File.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="File" inherits="Reference" category="Core" version="3.0.alpha.custom_build">
+<class name="File" inherits="Reference" category="Core" version="3.0-alpha">
<brief_description>
Type to handle file reading and writing operations.
</brief_description>
@@ -30,14 +30,14 @@
<return type="void">
</return>
<description>
- Close the currently opened file.
+ Closes the currently opened file.
</description>
</method>
<method name="eof_reached" qualifiers="const">
<return type="bool">
</return>
<description>
- Return whether the file cursor reached the end of the file.
+ Returns [code]true[/code] if the file cursor has reached the end of the file.
</description>
</method>
<method name="file_exists" qualifiers="const">
@@ -46,42 +46,42 @@
<argument index="0" name="path" type="String">
</argument>
<description>
- Get whether or not the file in the specified path exists.
+ Returns [code]true[/code] if the file exists in the given path.
</description>
</method>
<method name="get_16" qualifiers="const">
<return type="int">
</return>
<description>
- Get the next 16 bits from the file as an integer.
+ Returns the next 16 bits from the file as an integer.
</description>
</method>
<method name="get_32" qualifiers="const">
<return type="int">
</return>
<description>
- Get the next 32 bits from the file as an integer.
+ Returns the next 32 bits from the file as an integer.
</description>
</method>
<method name="get_64" qualifiers="const">
<return type="int">
</return>
<description>
- Get the next 64 bits from the file as an integer.
+ Returns the next 64 bits from the file as an integer.
</description>
</method>
<method name="get_8" qualifiers="const">
<return type="int">
</return>
<description>
- Get the next 8 bits from the file as an integer.
+ Returns the next 8 bits from the file as an integer.
</description>
</method>
<method name="get_as_text" qualifiers="const">
<return type="String">
</return>
<description>
- Get the whole file as a [String].
+ Returns the whole file as a [String].
</description>
</method>
<method name="get_buffer" qualifiers="const">
@@ -90,7 +90,7 @@
<argument index="0" name="len" type="int">
</argument>
<description>
- Get next len bytes of the file as a [PoolByteArray].
+ Returns next [code]len[/code] bytes of the file as a [PoolByteArray].
</description>
</method>
<method name="get_csv_line" qualifiers="const">
@@ -99,49 +99,49 @@
<argument index="0" name="delim" type="String" default="&quot;,&quot;">
</argument>
<description>
- Get the next value of the file in CSV (Comma Separated Values) format. You can pass a different delimiter to use other than the default "," (comma).
+ Returns the next value of the file in CSV (Comma Separated Values) format. You can pass a different delimiter to use other than the default "," (comma).
</description>
</method>
<method name="get_double" qualifiers="const">
<return type="float">
</return>
<description>
- Get the next 64 bits from the file as a floating point number.
+ Returns the next 64 bits from the file as a floating point number.
</description>
</method>
<method name="get_endian_swap">
<return type="bool">
</return>
<description>
- Get whether endian swap is enabled for this file.
+ Returns [code]true[/code] if endian swap is enabled for this file.
</description>
</method>
<method name="get_error" qualifiers="const">
<return type="int" enum="Error">
</return>
<description>
- Get the last error that happened when trying to perform operations. Compare with the [code]ERR_FILE_*[/code] constants from [@Global Scope].
+ Returns the last error that happened when trying to perform operations. Compare with the [code]ERR_FILE_*[/code] constants from [@GlobalScope].
</description>
</method>
<method name="get_float" qualifiers="const">
<return type="float">
</return>
<description>
- Get the next 32 bits from the file as a floating point number.
+ Returns the next 32 bits from the file as a floating point number.
</description>
</method>
<method name="get_len" qualifiers="const">
<return type="int">
</return>
<description>
- Return the size of the file in bytes.
+ Returns the size of the file in bytes.
</description>
</method>
<method name="get_line" qualifiers="const">
<return type="String">
</return>
<description>
- Get the next line of the file as a [String].
+ Returns the next line of the file as a [String].
</description>
</method>
<method name="get_md5" qualifiers="const">
@@ -150,7 +150,7 @@
<argument index="0" name="path" type="String">
</argument>
<description>
- Return a md5 String representing the file at the given path or an empty [String] on failure.
+ Returns an MD5 String representing the file at the given path or an empty [String] on failure.
</description>
</method>
<method name="get_modified_time" qualifiers="const">
@@ -159,27 +159,28 @@
<argument index="0" name="file" type="String">
</argument>
<description>
+ Returns the last time the [code]file[/code] was modified in unix timestamp format or returns a [String] "ERROR IN [code]file[/code]". This unix timestamp can be converted to datetime by using [method OS.get_datetime_from_unix_time].
</description>
</method>
<method name="get_pascal_string">
<return type="String">
</return>
<description>
- Get a [String] saved in Pascal format from the file.
+ Returns a [String] saved in Pascal format from the file.
</description>
</method>
<method name="get_position" qualifiers="const">
<return type="int">
</return>
<description>
- Return the file cursor position.
+ Returns the file cursor's position.
</description>
</method>
<method name="get_real" qualifiers="const">
<return type="float">
</return>
<description>
- Get the next bits from the file as a floating point number.
+ Returns the next bits from the file as a floating point number.
</description>
</method>
<method name="get_sha256" qualifiers="const">
@@ -188,21 +189,21 @@
<argument index="0" name="path" type="String">
</argument>
<description>
- Return a sha256 String representing the file at the given path or an empty [String] on failure.
+ Returns a SHA-256 [String] representing the file at the given path or an empty [String] on failure.
</description>
</method>
<method name="get_var" qualifiers="const">
<return type="Variant">
</return>
<description>
- Get the next Variant value from the file.
+ Returns the next [Variant] value from the file.
</description>
</method>
<method name="is_open" qualifiers="const">
<return type="bool">
</return>
<description>
- Return whether the file is currently opened.
+ Returns [code]true[/code] if the file is currently opened.
</description>
</method>
<method name="open">
@@ -213,7 +214,7 @@
<argument index="1" name="flags" type="int">
</argument>
<description>
- Open the file for writing or reading, depending on the flags.
+ Opens the file for writing or reading, depending on the flags.
</description>
</method>
<method name="open_compressed">
@@ -226,7 +227,7 @@
<argument index="2" name="compression_mode" type="int" default="0">
</argument>
<description>
- Open a compressed file for reading or writing. The compression_mode can be set as one of the COMPRESSION_* constants.
+ Opens a compressed file for reading or writing. Use COMPRESSION_* constants to set [code]compression_mode[/code].
</description>
</method>
<method name="open_encrypted">
@@ -239,7 +240,7 @@
<argument index="2" name="key" type="PoolByteArray">
</argument>
<description>
- Open an encrypted file in write or read mode. You need to pass a binary key to encrypt/decrypt it.
+ Opens an encrypted file in write or read mode. You need to pass a binary key to encrypt/decrypt it.
</description>
</method>
<method name="open_encrypted_with_pass">
@@ -252,7 +253,7 @@
<argument index="2" name="pass" type="String">
</argument>
<description>
- Open an encrypted file in write or read mode. You need to pass a password to encrypt/decrypt it.
+ Opens an encrypted file in write or read mode. You need to pass a password to encrypt/decrypt it.
</description>
</method>
<method name="seek">
@@ -270,7 +271,7 @@
<argument index="0" name="position" type="int" default="0">
</argument>
<description>
- Change the file reading/writing cursor to the specified position (in bytes from the end of the file). Note that this is an offset, so you should use negative numbers or the cursor will be at the end of the file.
+ Changes the file reading/writing cursor to the specified position (in bytes from the end of the file). Note that this is an offset, so you should use negative numbers or the cursor will be at the end of the file.
</description>
</method>
<method name="set_endian_swap">
@@ -279,7 +280,7 @@
<argument index="0" name="enable" type="bool">
</argument>
<description>
- Set whether to swap the endianness of the file. Enable this if you're dealing with files written in big endian machines.
+ If [code]true[/code] the file's endianness is swapped. Use this if you're dealing with files written in big endian machines.
Note that this is about the file format, not CPU type. This is always reseted to [code]false[/code] whenever you open the file.
</description>
</method>
@@ -289,7 +290,7 @@
<argument index="0" name="value" type="int">
</argument>
<description>
- Store an integer as 16 bits in the file.
+ Stores an integer as 16 bits in the file.
</description>
</method>
<method name="store_32">
@@ -298,7 +299,7 @@
<argument index="0" name="value" type="int">
</argument>
<description>
- Store an integer as 32 bits in the file.
+ Stores an integer as 32 bits in the file.
</description>
</method>
<method name="store_64">
@@ -307,7 +308,7 @@
<argument index="0" name="value" type="int">
</argument>
<description>
- Store an integer as 64 bits in the file.
+ Stores an integer as 64 bits in the file.
</description>
</method>
<method name="store_8">
@@ -316,7 +317,7 @@
<argument index="0" name="value" type="int">
</argument>
<description>
- Store an integer as 8 bits in the file.
+ Stores an integer as 8 bits in the file.
</description>
</method>
<method name="store_buffer">
@@ -325,7 +326,7 @@
<argument index="0" name="buffer" type="PoolByteArray">
</argument>
<description>
- Store the given array of bytes in the file.
+ Stores the given array of bytes in the file.
</description>
</method>
<method name="store_double">
@@ -334,7 +335,7 @@
<argument index="0" name="value" type="float">
</argument>
<description>
- Store a floating point number as 64 bits in the file.
+ Stores a floating point number as 64 bits in the file.
</description>
</method>
<method name="store_float">
@@ -343,7 +344,7 @@
<argument index="0" name="value" type="float">
</argument>
<description>
- Store a floating point number as 32 bits in the file.
+ Stores a floating point number as 32 bits in the file.
</description>
</method>
<method name="store_line">
@@ -352,7 +353,7 @@
<argument index="0" name="line" type="String">
</argument>
<description>
- Store the given [String] as a line in the file.
+ Stores the given [String] as a line in the file.
</description>
</method>
<method name="store_pascal_string">
@@ -361,7 +362,7 @@
<argument index="0" name="string" type="String">
</argument>
<description>
- Store the given [String] as a line in the file in Pascal format (i.e. also store the length of the string).
+ Stores the given [String] as a line in the file in Pascal format (i.e. also store the length of the string).
</description>
</method>
<method name="store_real">
@@ -370,7 +371,7 @@
<argument index="0" name="value" type="float">
</argument>
<description>
- Store a floating point number in the file.
+ Stores a floating point number in the file.
</description>
</method>
<method name="store_string">
@@ -379,7 +380,7 @@
<argument index="0" name="string" type="String">
</argument>
<description>
- Store the given [String] in the file.
+ Stores the given [String] in the file.
</description>
</method>
<method name="store_var">
@@ -388,33 +389,34 @@
<argument index="0" name="value" type="Variant">
</argument>
<description>
- Store any Variant value in the file.
+ Stores any Variant value in the file.
</description>
</method>
</methods>
<constants>
<constant name="READ" value="1">
- Open the file for reading.
+ Opens the file for read operations.
</constant>
<constant name="WRITE" value="2">
- Open the file for writing. Create it if the file not exists and truncate if it exists.
+ Opens the file for write operations. Create it if the file does not exist and truncate if it exists.
</constant>
<constant name="READ_WRITE" value="3">
- Open the file for reading and writing, without truncating the file.
+ Opens the file for read and write operations. Does not truncate the file.
</constant>
<constant name="WRITE_READ" value="7">
- Open the file for reading and writing. Create it if the file not exists and truncate if it exists.
+ Opens the file for read and write operations. Create it if the file does not exist and truncate if it exists.
</constant>
<constant name="COMPRESSION_FASTLZ" value="0">
- Use the FastLZ compression method.
+ Uses the FastLZ compression method.
</constant>
<constant name="COMPRESSION_DEFLATE" value="1">
- Use the Deflate compression method.
+ Uses the Deflate compression method.
</constant>
<constant name="COMPRESSION_ZSTD" value="2">
- Use the Zstd compression method.
+ Uses the Zstd compression method.
</constant>
<constant name="COMPRESSION_GZIP" value="3">
+ Uses the gzip compression method.
</constant>
</constants>
</class>
diff --git a/doc/classes/FileDialog.xml b/doc/classes/FileDialog.xml
index d7a08368a5..7dda486ac9 100644
--- a/doc/classes/FileDialog.xml
+++ b/doc/classes/FileDialog.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="FileDialog" inherits="ConfirmationDialog" category="Core" version="3.0.alpha.custom_build">
+<class name="FileDialog" inherits="ConfirmationDialog" category="Core" version="3.0-alpha">
<brief_description>
Dialog for selecting files or directories in the filesystem.
</brief_description>
@@ -86,7 +86,7 @@
<return type="bool">
</return>
<description>
- Return true if the diaog allows show hidden files.
+ Return true if the dialog allows show hidden files.
</description>
</method>
<method name="set_access">
@@ -205,10 +205,10 @@
The dialog allows the selection of file and directory.
</constant>
<constant name="ACCESS_USERDATA" value="1">
- The dialog allows ascess files under [Resource] path(res://) .
+ The dialog allows access files under [Resource] path(res://) .
</constant>
<constant name="ACCESS_FILESYSTEM" value="2">
- The dialog allows ascess files in whole file system.
+ The dialog allows access files in whole file system.
</constant>
</constants>
<theme_items>
diff --git a/doc/classes/Font.xml b/doc/classes/Font.xml
index 2e2124cbd6..b83d66830f 100644
--- a/doc/classes/Font.xml
+++ b/doc/classes/Font.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Font" inherits="Resource" category="Core" version="3.0.alpha.custom_build">
+<class name="Font" inherits="Resource" category="Core" version="3.0-alpha">
<brief_description>
Internationalized font and text drawing support.
</brief_description>
diff --git a/doc/classes/FuncRef.xml b/doc/classes/FuncRef.xml
index a7593dc2a1..65da5dd98f 100644
--- a/doc/classes/FuncRef.xml
+++ b/doc/classes/FuncRef.xml
@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="FuncRef" inherits="Reference" category="Core" version="3.0.alpha.custom_build">
+<class name="FuncRef" inherits="Reference" category="Core" version="3.0-alpha">
<brief_description>
Reference to a function in an object.
</brief_description>
<description>
In GDScript, functions are not [i]first-class objects[/i]. This means it is impossible to store them directly as variables, return them from another function, or pass them as arguments.
- However, by creating a [FuncRef] using the [method @GDScript.funcref] function, a reference to a function in a given object can be created, passed around and called.
+ However, by creating a [code]FuncRef[/code] using the [method @GDScript.funcref] function, a reference to a function in a given object can be created, passed around and called.
</description>
<tutorials>
</tutorials>
@@ -16,6 +16,7 @@
<return type="Variant">
</return>
<description>
+ Calls the referenced function previously set by [method set_function] or [method @GDScript.funcref].
</description>
</method>
<method name="set_function">
@@ -24,7 +25,7 @@
<argument index="0" name="name" type="String">
</argument>
<description>
- Set the name of the function to call on the object, without parentheses or any parameters.
+ The name of the referenced function to call on the object, without parentheses or any parameters.
</description>
</method>
<method name="set_instance">
@@ -33,7 +34,7 @@
<argument index="0" name="instance" type="Object">
</argument>
<description>
- Set the object on which to call the referenced function. This object must be of a type actually inheriting from [Object], not a built-in type such as [int], [Vector2] or [Dictionary].
+ The object containing the referenced function. This object must be of a type actually inheriting from [Object], not a built-in type such as [int], [Vector2] or [Dictionary].
</description>
</method>
</methods>
diff --git a/doc/classes/GDNativeLibrary.xml b/doc/classes/GDNativeLibrary.xml
deleted file mode 100644
index c3561856cc..0000000000
--- a/doc/classes/GDNativeLibrary.xml
+++ /dev/null
@@ -1,51 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<class name="GDNativeLibrary" inherits="Resource" category="Core" version="3.0.alpha.custom_build">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <tutorials>
- </tutorials>
- <demos>
- </demos>
- <methods>
- <method name="get_library_path" qualifiers="const">
- <return type="String">
- </return>
- <argument index="0" name="platform" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="is_singleton_gdnative" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
- <method name="set_library_path">
- <return type="void">
- </return>
- <argument index="0" name="platform" type="String">
- </argument>
- <argument index="1" name="path" type="String">
- </argument>
- <description>
- </description>
- </method>
- <method name="set_singleton_gdnative">
- <return type="void">
- </return>
- <argument index="0" name="singleton" type="bool">
- </argument>
- <description>
- </description>
- </method>
- </methods>
- <members>
- <member name="singleton_gdnative" type="bool" setter="set_singleton_gdnative" getter="is_singleton_gdnative">
- </member>
- </members>
- <constants>
- </constants>
-</class>
diff --git a/doc/classes/GIProbe.xml b/doc/classes/GIProbe.xml
index 9df0b80b35..e445d94835 100644
--- a/doc/classes/GIProbe.xml
+++ b/doc/classes/GIProbe.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="GIProbe" inherits="VisualInstance" category="Core" version="3.0.alpha.custom_build">
+<class name="GIProbe" inherits="VisualInstance" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
@@ -195,6 +195,8 @@
</constant>
<constant name="SUBDIV_256" value="2">
</constant>
+ <constant name="SUBDIV_512" value="3">
+ </constant>
<constant name="SUBDIV_MAX" value="4">
</constant>
</constants>
diff --git a/doc/classes/GIProbeData.xml b/doc/classes/GIProbeData.xml
index 6d47daf985..5d118be776 100644
--- a/doc/classes/GIProbeData.xml
+++ b/doc/classes/GIProbeData.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="GIProbeData" inherits="Resource" category="Core" version="3.0.alpha.custom_build">
+<class name="GIProbeData" inherits="Resource" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
@@ -16,7 +16,7 @@
</description>
</method>
<method name="get_bounds" qualifiers="const">
- <return type="Rect3">
+ <return type="AABB">
</return>
<description>
</description>
@@ -86,7 +86,7 @@
<method name="set_bounds">
<return type="void">
</return>
- <argument index="0" name="bounds" type="Rect3">
+ <argument index="0" name="bounds" type="AABB">
</argument>
<description>
</description>
@@ -167,7 +167,7 @@
<members>
<member name="bias" type="float" setter="set_bias" getter="get_bias">
</member>
- <member name="bounds" type="Rect3" setter="set_bounds" getter="get_bounds">
+ <member name="bounds" type="AABB" setter="set_bounds" getter="get_bounds">
</member>
<member name="cell_size" type="float" setter="set_cell_size" getter="get_cell_size">
</member>
diff --git a/doc/classes/Generic6DOFJoint.xml b/doc/classes/Generic6DOFJoint.xml
index 4b782e994a..202e461652 100644
--- a/doc/classes/Generic6DOFJoint.xml
+++ b/doc/classes/Generic6DOFJoint.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Generic6DOFJoint" inherits="Joint" category="Core" version="3.0.alpha.custom_build">
+<class name="Generic6DOFJoint" inherits="Joint" category="Core" version="3.0-alpha">
<brief_description>
+ The generic 6 degrees of freedom joint can implement a variety of joint-types by locking certain axes' rotation or translation.
</brief_description>
<description>
+ The first 3 dof axes are linear axes, which represent translation of Bodies, and the latter 3 dof axes represent the angular motion. Each axis can be either locked, or limited.
</description>
<tutorials>
</tutorials>
@@ -120,146 +122,217 @@
</methods>
<members>
<member name="angular_limit_x/damping" type="float" setter="set_param_x" getter="get_param_x">
+ The amount of rotational damping across the x-axis.
+ The lower, the longer an impulse from one side takes to travel to the other side.
</member>
<member name="angular_limit_x/enabled" type="bool" setter="set_flag_x" getter="get_flag_x">
+ If [code]true[/code] rotation across the x-axis is enabled.
</member>
<member name="angular_limit_x/erp" type="float" setter="set_param_x" getter="get_param_x">
+ When rotating across x-axis, this error tolerance factor defines how much the correction gets slowed down. The lower, the slower.
</member>
<member name="angular_limit_x/force_limit" type="float" setter="set_param_x" getter="get_param_x">
+ The maximum amount of force that can occur, when rotating arround x-axis.
</member>
<member name="angular_limit_x/lower_angle" type="float" setter="_set_angular_lo_limit_x" getter="_get_angular_lo_limit_x">
+ The minimum rotation in negative direction to break loose and rotate arround the x-axis.
</member>
<member name="angular_limit_x/restitution" type="float" setter="set_param_x" getter="get_param_x">
+ The amount of rotational restitution across the x-axis. The lower, the more restitution occurs.
</member>
<member name="angular_limit_x/softness" type="float" setter="set_param_x" getter="get_param_x">
+ The speed of all rotations across the x-axis.
</member>
<member name="angular_limit_x/upper_angle" type="float" setter="_set_angular_hi_limit_x" getter="_get_angular_hi_limit_x">
+ The minimum rotation in positive direction to break loose and rotate arround the x-axis.
</member>
<member name="angular_limit_y/damping" type="float" setter="set_param_y" getter="get_param_y">
+ The amount of rotational damping across the y-axis. The lower, the more dampening occurs.
</member>
<member name="angular_limit_y/enabled" type="bool" setter="set_flag_y" getter="get_flag_y">
+ If [code]true[/code] rotation across the y-axis is enabled.
</member>
<member name="angular_limit_y/erp" type="float" setter="set_param_y" getter="get_param_y">
+ When rotating across y-axis, this error tolerance factor defines how much the correction gets slowed down. The lower, the slower.
</member>
<member name="angular_limit_y/force_limit" type="float" setter="set_param_y" getter="get_param_y">
+ The maximum amount of force that can occur, when rotating arround y-axis.
</member>
<member name="angular_limit_y/lower_angle" type="float" setter="_set_angular_lo_limit_y" getter="_get_angular_lo_limit_y">
+ The minimum rotation in negative direction to break loose and rotate arround the y-axis.
</member>
<member name="angular_limit_y/restitution" type="float" setter="set_param_y" getter="get_param_y">
+ The amount of rotational restitution across the y-axis. The lower, the more restitution occurs.
</member>
<member name="angular_limit_y/softness" type="float" setter="set_param_y" getter="get_param_y">
+ The speed of all rotations across the y-axis.
</member>
<member name="angular_limit_y/upper_angle" type="float" setter="_set_angular_hi_limit_y" getter="_get_angular_hi_limit_y">
+ The minimum rotation in positive direction to break loose and rotate arround the y-axis.
</member>
<member name="angular_limit_z/damping" type="float" setter="set_param_z" getter="get_param_z">
+ The amount of rotational damping across the z-axis. The lower, the more dampening occurs.
</member>
<member name="angular_limit_z/enabled" type="bool" setter="set_flag_z" getter="get_flag_z">
+ If [code]true[/code] rotation across the z-axis is enabled.
</member>
<member name="angular_limit_z/erp" type="float" setter="set_param_z" getter="get_param_z">
+ When rotating across z-axis, this error tolerance factor defines how much the correction gets slowed down. The lower, the slower.
</member>
<member name="angular_limit_z/force_limit" type="float" setter="set_param_z" getter="get_param_z">
+ The maximum amount of force that can occur, when rotating arround z-axis.
</member>
<member name="angular_limit_z/lower_angle" type="float" setter="_set_angular_lo_limit_z" getter="_get_angular_lo_limit_z">
+ The minimum rotation in negative direction to break loose and rotate arround the z-axis.
</member>
<member name="angular_limit_z/restitution" type="float" setter="set_param_z" getter="get_param_z">
+ The amount of rotational restitution across the z-axis. The lower, the more restitution occurs.
</member>
<member name="angular_limit_z/softness" type="float" setter="set_param_z" getter="get_param_z">
+ The speed of all rotations across the z-axis.
</member>
<member name="angular_limit_z/upper_angle" type="float" setter="_set_angular_hi_limit_z" getter="_get_angular_hi_limit_z">
+ The minimum rotation in positive direction to break loose and rotate arround the z-axis.
</member>
<member name="angular_motor_x/enabled" type="bool" setter="set_flag_x" getter="get_flag_x">
+ If [code]true[/code] a rotating motor at the x-axis is enabled.
</member>
<member name="angular_motor_x/force_limit" type="float" setter="set_param_x" getter="get_param_x">
+ Maximum acceleration for the motor at the x-axis.
</member>
<member name="angular_motor_x/target_velocity" type="float" setter="set_param_x" getter="get_param_x">
+ Target speed for the motor at the x-axis.
</member>
<member name="angular_motor_y/enabled" type="bool" setter="set_flag_y" getter="get_flag_y">
+ If [code]true[/code] a rotating motor at the y-axis is enabled.
</member>
<member name="angular_motor_y/force_limit" type="float" setter="set_param_y" getter="get_param_y">
+ Maximum acceleration for the motor at the y-axis.
</member>
<member name="angular_motor_y/target_velocity" type="float" setter="set_param_y" getter="get_param_y">
+ Target speed for the motor at the y-axis.
</member>
<member name="angular_motor_z/enabled" type="bool" setter="set_flag_z" getter="get_flag_z">
+ If [code]true[/code] a rotating motor at the z-axis is enabled.
</member>
<member name="angular_motor_z/force_limit" type="float" setter="set_param_z" getter="get_param_z">
+ Maximum acceleration for the motor at the z-axis.
</member>
<member name="angular_motor_z/target_velocity" type="float" setter="set_param_z" getter="get_param_z">
+ Target speed for the motor at the z-axis.
</member>
<member name="linear_limit_x/damping" type="float" setter="set_param_x" getter="get_param_x">
+ The amount of damping that happens at the x-motion.
</member>
<member name="linear_limit_x/enabled" type="bool" setter="set_flag_x" getter="get_flag_x">
+ If [code]true[/code] the linear motion across the x-axis is enabled.
</member>
<member name="linear_limit_x/lower_distance" type="float" setter="set_param_x" getter="get_param_x">
+ The minimum difference between the pivot points' x-axis.
</member>
<member name="linear_limit_x/restitution" type="float" setter="set_param_x" getter="get_param_x">
+ The amount of restitution on the x-axis movement The lower, the more momentum gets lost.
</member>
<member name="linear_limit_x/softness" type="float" setter="set_param_x" getter="get_param_x">
+ A factor applied to the movement across the x-axis The lower, the slower the movement.
</member>
<member name="linear_limit_x/upper_distance" type="float" setter="set_param_x" getter="get_param_x">
+ The maximum difference between the pivot points' x-axis.
</member>
<member name="linear_limit_y/damping" type="float" setter="set_param_y" getter="get_param_y">
+ The amount of damping that happens at the y-motion.
</member>
<member name="linear_limit_y/enabled" type="bool" setter="set_flag_y" getter="get_flag_y">
+ If [code]true[/code] the linear motion across the y-axis is enabled.
</member>
<member name="linear_limit_y/lower_distance" type="float" setter="set_param_y" getter="get_param_y">
+ The minimum difference between the pivot points' y-axis.
</member>
<member name="linear_limit_y/restitution" type="float" setter="set_param_y" getter="get_param_y">
+ The amount of restitution on the y-axis movement The lower, the more momentum gets lost.
</member>
<member name="linear_limit_y/softness" type="float" setter="set_param_y" getter="get_param_y">
+ A factor applied to the movement across the y-axis The lower, the slower the movement.
</member>
<member name="linear_limit_y/upper_distance" type="float" setter="set_param_y" getter="get_param_y">
+ The maximum difference between the pivot points' y-axis.
</member>
<member name="linear_limit_z/damping" type="float" setter="set_param_z" getter="get_param_z">
+ The amount of damping that happens at the z-motion.
</member>
<member name="linear_limit_z/enabled" type="bool" setter="set_flag_z" getter="get_flag_z">
+ If [code]true[/code] the linear motion across the z-axis is enabled.
</member>
<member name="linear_limit_z/lower_distance" type="float" setter="set_param_z" getter="get_param_z">
+ The minimum difference between the pivot points' z-axis.
</member>
<member name="linear_limit_z/restitution" type="float" setter="set_param_z" getter="get_param_z">
+ The amount of restitution on the z-axis movement The lower, the more momentum gets lost.
</member>
<member name="linear_limit_z/softness" type="float" setter="set_param_z" getter="get_param_z">
+ A factor applied to the movement across the z-axis The lower, the slower the movement.
</member>
<member name="linear_limit_z/upper_distance" type="float" setter="set_param_z" getter="get_param_z">
+ The maximum difference between the pivot points' z-axis.
</member>
</members>
<constants>
<constant name="PARAM_LINEAR_LOWER_LIMIT" value="0">
+ The minimum difference between the pivot points' axes.
</constant>
<constant name="PARAM_LINEAR_UPPER_LIMIT" value="1">
+ The maximum difference between the pivot points' axes.
</constant>
<constant name="PARAM_LINEAR_LIMIT_SOFTNESS" value="2">
+ A factor applied to the movement across the axes The lower, the slower the movement.
</constant>
<constant name="PARAM_LINEAR_RESTITUTION" value="3">
+ The amount of restitution on the axes movement The lower, the more momentum gets lost.
</constant>
<constant name="PARAM_LINEAR_DAMPING" value="4">
+ The amount of damping that happens at the linear motion across the axes.
</constant>
<constant name="PARAM_ANGULAR_LOWER_LIMIT" value="5">
+ The minimum rotation in negative direction to break loose and rotate arround the axes.
</constant>
<constant name="PARAM_ANGULAR_UPPER_LIMIT" value="6">
+ The minimum rotation in positive direction to break loose and rotate arround the axes.
</constant>
<constant name="PARAM_ANGULAR_LIMIT_SOFTNESS" value="7">
+ The speed of all rotations across the axes.
</constant>
<constant name="PARAM_ANGULAR_DAMPING" value="8">
+ The amount of rotational damping across the axes. The lower, the more dampening occurs.
</constant>
<constant name="PARAM_ANGULAR_RESTITUTION" value="9">
+ The amount of rotational restitution across the axes. The lower, the more restitution occurs.
</constant>
<constant name="PARAM_ANGULAR_FORCE_LIMIT" value="10">
+ The maximum amount of force that can occur, when rotating arround the axes.
</constant>
<constant name="PARAM_ANGULAR_ERP" value="11">
+ When rotating across the axes, this error tolerance factor defines how much the correction gets slowed down. The lower, the slower.
</constant>
<constant name="PARAM_ANGULAR_MOTOR_TARGET_VELOCITY" value="12">
+ Target speed for the motor at the axes.
</constant>
<constant name="PARAM_ANGULAR_MOTOR_FORCE_LIMIT" value="13">
+ Maximum acceleration for the motor at the axes.
</constant>
<constant name="PARAM_MAX" value="14">
+ End flag of PARAM_* constants, used internally.
</constant>
<constant name="FLAG_ENABLE_LINEAR_LIMIT" value="0">
+ If [code]set[/code] there is linear motion possible within the given limits.
</constant>
<constant name="FLAG_ENABLE_ANGULAR_LIMIT" value="1">
+ If [code]set[/code] there is rotational motion possible.
</constant>
<constant name="FLAG_ENABLE_MOTOR" value="2">
+ If [code]set[/code] there is a rotational motor across these axes.
</constant>
<constant name="FLAG_MAX" value="3">
+ End flag of FLAG_* constants, used internally.
</constant>
</constants>
</class>
diff --git a/doc/classes/Geometry.xml b/doc/classes/Geometry.xml
index 49f32bc68f..5da3ca0059 100644
--- a/doc/classes/Geometry.xml
+++ b/doc/classes/Geometry.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Geometry" inherits="Object" category="Core" version="3.0.alpha.custom_build">
+<class name="Geometry" inherits="Object" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
@@ -15,6 +15,7 @@
<argument index="0" name="extents" type="Vector3">
</argument>
<description>
+ Returns an array with 6 [Plane]s that describe the sides of a box centered at the origin. The box size is defined by [code]extents[/code], which represents one (positive) corner of the box (i.e. half its actual size).
</description>
</method>
<method name="build_capsule_planes">
@@ -31,6 +32,7 @@
<argument index="4" name="axis" type="int" enum="Vector3.Axis" default="2">
</argument>
<description>
+ Returns an array of [Plane]s closely bounding a faceted capsule centered at the origin with radius [code]radius[/code] and height [code]height[/code]. The parameter [code]sides[/code] defines how many planes will be generated for the side part of the capsule, whereas [code]lats[/code] gives the number of latitudinal steps at the bottom and top of the capsule. The parameter [code]axis[/code] describes the axis along which the capsule is oriented (0 for X, 1 for Y, 2 for Z).
</description>
</method>
<method name="build_cylinder_planes">
@@ -45,6 +47,27 @@
<argument index="3" name="axis" type="int" enum="Vector3.Axis" default="2">
</argument>
<description>
+ Returns an array of [Plane]s closely bounding a faceted cylinder centered at the origin with radius [code]radius[/code] and height [code]height[/code]. The parameter [code]sides[/code] defines how many planes will be generated for the round part of the cylinder. The parameter [code]axis[/code] describes the axis along which the cylinder is oriented (0 for X, 1 for Y, 2 for Z).
+ </description>
+ </method>
+ <method name="clip_polygon">
+ <return type="PoolVector3Array">
+ </return>
+ <argument index="0" name="points" type="PoolVector3Array">
+ </argument>
+ <argument index="1" name="plane" type="Plane">
+ </argument>
+ <description>
+ Clips the polygon defined by the points in [code]points[/code] against the [code]plane[/code] and returns the points of the clipped polygon.
+ </description>
+ </method>
+ <method name="convex_hull_2d">
+ <return type="PoolVector2Array">
+ </return>
+ <argument index="0" name="points" type="PoolVector2Array">
+ </argument>
+ <description>
+ Given an array of [Vector2]s, returns the convex hull as a list of points in counter-clockwise order. The last point is the same as the first one.
</description>
</method>
<method name="get_closest_point_to_segment">
@@ -57,6 +80,7 @@
<argument index="2" name="s2" type="Vector3">
</argument>
<description>
+ Returns the 3d point on the 3d segment ([code]s1[/code], [code]s2[/code]) that is closest to [code]point[/code]. The returned point will always be inside the specified segment.
</description>
</method>
<method name="get_closest_point_to_segment_2d">
@@ -69,6 +93,7 @@
<argument index="2" name="s2" type="Vector2">
</argument>
<description>
+ Returns the 2d point on the 2d segment ([code]s1[/code], [code]s2[/code]) that is closest to [code]point[/code]. The returned point will always be inside the specified segment.
</description>
</method>
<method name="get_closest_point_to_segment_uncapped">
@@ -81,6 +106,7 @@
<argument index="2" name="s2" type="Vector3">
</argument>
<description>
+ Returns the 3d point on the 3d line defined by ([code]s1[/code], [code]s2[/code]) that is closest to [code]point[/code]. The returned point can be inside the segment ([code]s1[/code], [code]s2[/code]) or outside of it, i.e. somewhere on the line extending from the segment.
</description>
</method>
<method name="get_closest_point_to_segment_uncapped_2d">
@@ -93,6 +119,7 @@
<argument index="2" name="s2" type="Vector2">
</argument>
<description>
+ Returns the 2d point on the 2d line defined by ([code]s1[/code], [code]s2[/code]) that is closest to [code]point[/code]. The returned point can be inside the segment ([code]s1[/code], [code]s2[/code]) or outside of it, i.e. somewhere on the line extending from the segment.
</description>
</method>
<method name="get_closest_points_between_segments">
@@ -107,6 +134,7 @@
<argument index="3" name="q2" type="Vector3">
</argument>
<description>
+ Given the two 3d segments ([code]p1[/code], [code]p2[/code]) and ([code]q1[/code], [code]q2[/code]), finds those two points on the two segments that are closest to each other. Returns a [PoolVector3Array] that contains this point on ([code]p1[/code], [code]p2[/code]) as well the accompanying point on ([code]q1[/code], [code]q2[/code]).
</description>
</method>
<method name="get_closest_points_between_segments_2d">
@@ -121,6 +149,7 @@
<argument index="3" name="q2" type="Vector2">
</argument>
<description>
+ Given the two 2d segments ([code]p1[/code], [code]p2[/code]) and ([code]q1[/code], [code]q2[/code]), finds those two points on the two segments that are closest to each other. Returns a [PoolVector2Array] that contains this point on ([code]p1[/code], [code]p2[/code]) as well the accompanying point on ([code]q1[/code], [code]q2[/code]).
</description>
</method>
<method name="get_uv84_normal_bit">
@@ -137,6 +166,7 @@
<argument index="0" name="sizes" type="PoolVector2Array">
</argument>
<description>
+ Given an array of [Vector2]s representing tiles, builds an atlas. The returned dictionary has two keys: [code]points[/code] is a vector of [Vector2] that specifies the positions of each tile, [code]size[/code] contains the overall size of the whole atlas as [Vector2].
</description>
</method>
<method name="point_is_inside_triangle" qualifiers="const">
@@ -151,6 +181,7 @@
<argument index="3" name="c" type="Vector2">
</argument>
<description>
+ Returns if [code]point[/code] is inside the triangle specified by [code]a[/code], [code]b[/code] and [code]c[/code].
</description>
</method>
<method name="ray_intersects_triangle">
@@ -167,6 +198,7 @@
<argument index="4" name="c" type="Vector3">
</argument>
<description>
+ Tests if the 3d ray starting at [code]from[/code] with the direction of [code]dir[/code] intersects the triangle specified by [code]a[/code], [code]b[/code] and [code]c[/code]. If yes, returns the point of intersection as [Vector3]. If no intersection takes place, an empty [Variant] is returned.
</description>
</method>
<method name="segment_intersects_circle">
@@ -181,6 +213,7 @@
<argument index="3" name="circle_radius" type="float">
</argument>
<description>
+ Given the 2d segment ([code]segment_from[/code], [code]segment_to[/code]), returns the position on the segment (as a number between 0 and 1) at which the segment hits the circle that is located at position [code]circle_position[/code] and has radius [code]circle_radius[/code]. If the segment does not intersect the circle, -1 is returned (this is also the case if the line extending the segment would intersect the circle, but the segment does not).
</description>
</method>
<method name="segment_intersects_convex">
@@ -193,6 +226,7 @@
<argument index="2" name="planes" type="Array">
</argument>
<description>
+ Given a convex hull defined though the [Plane]s in the array [code]planes[/code], tests if the segment ([code]from[/code], [code]to[/code]) intersects with that hull. If an intersection is found, returns a [PoolVector3Array] containing the point the intersection and the hull's normal. If no intersecion is found, an the returned array is empty.
</description>
</method>
<method name="segment_intersects_cylinder">
@@ -207,6 +241,7 @@
<argument index="3" name="radius" type="float">
</argument>
<description>
+ Checks if the segment ([code]from[/code], [code]to[/code]) intersects the cylinder with height [code]height[/code] that is centered at the origin and has radius [code]radius[/code]. If no, returns an empty [PoolVector3Array]. If an intersection takes place, the returned array contains the point of intersection and the cylinder's normal at the point of intersection.
</description>
</method>
<method name="segment_intersects_segment_2d">
@@ -221,6 +256,7 @@
<argument index="3" name="to_b" type="Vector2">
</argument>
<description>
+ Checks if the two segments ([code]from_a[/code], [code]to_a[/code]) and ([code]from_b[/code], [code]to_b[/code]) intersect. If yes, return the point of intersection as [Vector2]. If no intersection takes place, returns an empty [Variant].
</description>
</method>
<method name="segment_intersects_sphere">
@@ -235,6 +271,7 @@
<argument index="3" name="sphere_radius" type="float">
</argument>
<description>
+ Checks if the segment ([code]from[/code], [code]to[/code]) intersects the sphere that is located at [code]sphere_position[/code] and has radius [code]sphere_radius[/code]. If no, returns an empty [PoolVector3Array]. If yes, returns a [PoolVector3Array] containing the point of intersection and the sphere's normal at the point of intersection.
</description>
</method>
<method name="segment_intersects_triangle">
@@ -251,6 +288,7 @@
<argument index="4" name="c" type="Vector3">
</argument>
<description>
+ Tests if the segment ([code]from[/code], [code]to[/code]) intersects the triangle [code]a[/code], [code]b[/code], [code]c[/code]. If yes, returns the point of intersection as [Vector3]. If no intersection takes place, an empty [Variant] is returned.
</description>
</method>
<method name="triangulate_polygon">
@@ -259,6 +297,7 @@
<argument index="0" name="polygon" type="PoolVector2Array">
</argument>
<description>
+ Triangulates the polygon specified by the points in [code]polygon[/code]. Returns a [PoolIntArray] where each triangle consists of three consecutive point indices into [code]polygon[/code] (i.e. the returned array will have [code]n * 3[/code] elements, with [code]n[/code] being the number of found triangles). If the triangulation did not succeed, an empty [PoolIntArray] is returned.
</description>
</method>
</methods>
diff --git a/doc/classes/GeometryInstance.xml b/doc/classes/GeometryInstance.xml
index 57aec8be41..f21dbecd04 100644
--- a/doc/classes/GeometryInstance.xml
+++ b/doc/classes/GeometryInstance.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="GeometryInstance" inherits="VisualInstance" category="Core" version="3.0.alpha.custom_build">
+<class name="GeometryInstance" inherits="VisualInstance" category="Core" version="3.0-alpha">
<brief_description>
Base node for geometry based visual instances.
</brief_description>
diff --git a/doc/classes/Gradient.xml b/doc/classes/Gradient.xml
index f97908b0a2..d557ec11c5 100644
--- a/doc/classes/Gradient.xml
+++ b/doc/classes/Gradient.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Gradient" inherits="Resource" category="Core" version="3.0.alpha.custom_build">
+<class name="Gradient" inherits="Resource" category="Core" version="3.0-alpha">
<brief_description>
- Color interpolator node
+ Color interpolator node.
</brief_description>
<description>
Given a set of colors, this node will interpolate them in order, meaning, that if you have color 1, color 2 and color3, the ramp will interpolate (generate the colors between two colors) from color 1 to color 2 and from color 2 to color 3. Initially the ramp will have 2 colors (black and white), one (black) at ramp lower offset offset 0 and the other (white) at the ramp higher offset 1.
@@ -122,8 +122,10 @@
</methods>
<members>
<member name="colors" type="PoolColorArray" setter="set_colors" getter="get_colors">
+ Gradient's colors returned as a [PoolColorArray].
</member>
<member name="offsets" type="PoolRealArray" setter="set_offsets" getter="get_offsets">
+ Gradient's offsets returned as a [PoolRealArray].
</member>
</members>
<constants>
diff --git a/doc/classes/GradientTexture.xml b/doc/classes/GradientTexture.xml
index eab8ea77af..88a776cb6a 100644
--- a/doc/classes/GradientTexture.xml
+++ b/doc/classes/GradientTexture.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="GradientTexture" inherits="Texture" category="Core" version="3.0.alpha.custom_build">
+<class name="GradientTexture" inherits="Texture" category="Core" version="3.0-alpha">
<brief_description>
Gradient filled texture.
</brief_description>
diff --git a/doc/classes/GraphEdit.xml b/doc/classes/GraphEdit.xml
index f064029a01..a07809ce95 100644
--- a/doc/classes/GraphEdit.xml
+++ b/doc/classes/GraphEdit.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="GraphEdit" inherits="Control" category="Core" version="3.0.alpha.custom_build">
+<class name="GraphEdit" inherits="Control" category="Core" version="3.0-alpha">
<brief_description>
GraphEdit is an area capable of showing various GraphNodes. It manages connection events between them.
</brief_description>
@@ -228,8 +228,6 @@
<constants>
</constants>
<theme_items>
- <theme_item name="SnapGrid" type="Texture">
- </theme_item>
<theme_item name="bezier_len_neg" type="int">
</theme_item>
<theme_item name="bezier_len_pos" type="int">
@@ -246,5 +244,7 @@
</theme_item>
<theme_item name="reset" type="Texture">
</theme_item>
+ <theme_item name="snap" type="Texture">
+ </theme_item>
</theme_items>
</class>
diff --git a/doc/classes/GraphNode.xml b/doc/classes/GraphNode.xml
index e230390882..2ad0cc1182 100644
--- a/doc/classes/GraphNode.xml
+++ b/doc/classes/GraphNode.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="GraphNode" inherits="Container" category="Core" version="3.0.alpha.custom_build">
+<class name="GraphNode" inherits="Container" category="Core" version="3.0-alpha">
<brief_description>
A GraphNode is a container with several input and output slots allowing connections between GraphNodes. Slots can have different, incompatible types.
</brief_description>
diff --git a/doc/classes/GridContainer.xml b/doc/classes/GridContainer.xml
index ca7b868cd8..01bbed6ea7 100644
--- a/doc/classes/GridContainer.xml
+++ b/doc/classes/GridContainer.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="GridContainer" inherits="Container" category="Core" version="3.0.alpha.custom_build">
+<class name="GridContainer" inherits="Container" category="Core" version="3.0-alpha">
<brief_description>
Grid container used to arrange elements in a grid like layout
</brief_description>
@@ -30,6 +30,7 @@
</methods>
<members>
<member name="columns" type="int" setter="set_columns" getter="get_columns">
+ The number of columns in the [code]GridContainer[/code]. If modified, [code]GridContainer[/code] reorders its children to accommodate the new layout.
</member>
</members>
<constants>
diff --git a/doc/classes/GrooveJoint2D.xml b/doc/classes/GrooveJoint2D.xml
index 3db2d9aee9..182bf5e8f1 100644
--- a/doc/classes/GrooveJoint2D.xml
+++ b/doc/classes/GrooveJoint2D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="GrooveJoint2D" inherits="Joint2D" category="Core" version="3.0.alpha.custom_build">
+<class name="GrooveJoint2D" inherits="Joint2D" category="Core" version="3.0-alpha">
<brief_description>
Groove constraint for 2D physics.
</brief_description>
@@ -46,8 +46,10 @@
</methods>
<members>
<member name="initial_offset" type="float" setter="set_initial_offset" getter="get_initial_offset">
+ The body B's initial anchor position defined by the joint's origin and a local offset [member initial_offset] along the joint's y axis (along the groove). Default value: [code]25[/code]
</member>
<member name="length" type="float" setter="set_length" getter="get_length">
+ The groove's length. The groove is from the joint's origin towards [member length] along the joint's local y axis. Default value: [code]50[/code]
</member>
</members>
<constants>
diff --git a/doc/classes/HBoxContainer.xml b/doc/classes/HBoxContainer.xml
index 2ffc2a8c57..6ee9a2c1f4 100644
--- a/doc/classes/HBoxContainer.xml
+++ b/doc/classes/HBoxContainer.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="HBoxContainer" inherits="BoxContainer" category="Core" version="3.0.alpha.custom_build">
+<class name="HBoxContainer" inherits="BoxContainer" category="Core" version="3.0-alpha">
<brief_description>
Horizontal box container.
</brief_description>
diff --git a/doc/classes/HScrollBar.xml b/doc/classes/HScrollBar.xml
index 188995527c..7fe26ec863 100644
--- a/doc/classes/HScrollBar.xml
+++ b/doc/classes/HScrollBar.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="HScrollBar" inherits="ScrollBar" category="Core" version="3.0.alpha.custom_build">
+<class name="HScrollBar" inherits="ScrollBar" category="Core" version="3.0-alpha">
<brief_description>
Horizontal scroll bar.
</brief_description>
diff --git a/doc/classes/HSeparator.xml b/doc/classes/HSeparator.xml
index 351eee7ee6..487f83ec1d 100644
--- a/doc/classes/HSeparator.xml
+++ b/doc/classes/HSeparator.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="HSeparator" inherits="Separator" category="Core" version="3.0.alpha.custom_build">
+<class name="HSeparator" inherits="Separator" category="Core" version="3.0-alpha">
<brief_description>
Horizontal separator.
</brief_description>
diff --git a/doc/classes/HSlider.xml b/doc/classes/HSlider.xml
index 91f95d1548..b4a97425f3 100644
--- a/doc/classes/HSlider.xml
+++ b/doc/classes/HSlider.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="HSlider" inherits="Slider" category="Core" version="3.0.alpha.custom_build">
+<class name="HSlider" inherits="Slider" category="Core" version="3.0-alpha">
<brief_description>
Horizontal slider.
</brief_description>
@@ -19,6 +19,8 @@
</theme_item>
<theme_item name="grabber" type="Texture">
</theme_item>
+ <theme_item name="grabber_area" type="StyleBox">
+ </theme_item>
<theme_item name="grabber_disabled" type="Texture">
</theme_item>
<theme_item name="grabber_disabled" type="StyleBox">
diff --git a/doc/classes/HSplitContainer.xml b/doc/classes/HSplitContainer.xml
index d7dc79a783..a107d30be7 100644
--- a/doc/classes/HSplitContainer.xml
+++ b/doc/classes/HSplitContainer.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="HSplitContainer" inherits="SplitContainer" category="Core" version="3.0.alpha.custom_build">
+<class name="HSplitContainer" inherits="SplitContainer" category="Core" version="3.0-alpha">
<brief_description>
Horizontal split container.
</brief_description>
diff --git a/doc/classes/HTTPClient.xml b/doc/classes/HTTPClient.xml
index cf48ec84f6..569c76ae0c 100644
--- a/doc/classes/HTTPClient.xml
+++ b/doc/classes/HTTPClient.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="HTTPClient" inherits="Reference" category="Core" version="3.0.alpha.custom_build">
+<class name="HTTPClient" inherits="Reference" category="Core" version="3.0-alpha">
<brief_description>
Hyper-text transfer protocol client.
</brief_description>
@@ -16,7 +16,7 @@
<return type="void">
</return>
<description>
- Cloces the current connection, allows for reusal of [HTTPClient].
+ Cloces the current connection, allows for reusal of [code]HTTPClient[/code].
</description>
</method>
<method name="connect_to_host">
@@ -84,7 +84,7 @@
<return type="bool">
</return>
<description>
- Return whether this [HTTPClient] has a response available.
+ Return whether this [code]HTTPClient[/code] has a response available.
</description>
</method>
<method name="is_blocking_mode_enabled" qualifiers="const">
@@ -98,7 +98,7 @@
<return type="bool">
</return>
<description>
- Return whether this [HTTPClient] has a response that is chunked.
+ Return whether this [code]HTTPClient[/code] has a response that is chunked.
</description>
</method>
<method name="poll">
@@ -169,24 +169,6 @@
Sends body raw, as a byte array, does not encode it in any way.
</description>
</method>
- <method name="send_body_data">
- <return type="int" enum="Error">
- </return>
- <argument index="0" name="body" type="PoolByteArray">
- </argument>
- <description>
- Stub function
- </description>
- </method>
- <method name="send_body_text">
- <return type="int" enum="Error">
- </return>
- <argument index="0" name="body" type="String">
- </argument>
- <description>
- Stub function
- </description>
- </method>
<method name="set_blocking_mode">
<return type="void">
</return>
diff --git a/doc/classes/HTTPRequest.xml b/doc/classes/HTTPRequest.xml
index c2839890cf..a1a84d2211 100644
--- a/doc/classes/HTTPRequest.xml
+++ b/doc/classes/HTTPRequest.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="HTTPRequest" inherits="Node" category="Core" version="3.0.alpha.custom_build">
+<class name="HTTPRequest" inherits="Node" category="Core" version="3.0-alpha">
<brief_description>
A Node with the ability to send HTTP requests.
</brief_description>
@@ -166,7 +166,7 @@
Request does not have a response(yet).
</constant>
<constant name="RESULT_BODY_SIZE_LIMIT_EXCEEDED" value="7">
- Request exceded its maximum size limit, see [method set_body_size_limit].
+ Request exceeded its maximum size limit, see [method set_body_size_limit].
</constant>
<constant name="RESULT_REQUEST_FAILED" value="8">
Request failed. (unused)
diff --git a/doc/classes/HingeJoint.xml b/doc/classes/HingeJoint.xml
index ae3693c3a4..2d91549a66 100644
--- a/doc/classes/HingeJoint.xml
+++ b/doc/classes/HingeJoint.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="HingeJoint" inherits="Joint" category="Core" version="3.0.alpha.custom_build">
+<class name="HingeJoint" inherits="Joint" category="Core" version="3.0-alpha">
<brief_description>
+ A hinge between two 3D bodies.
</brief_description>
<description>
+ Normaly uses the z-axis of body A as the hinge axis, another axis can be specified when adding it manually though.
</description>
<tutorials>
</tutorials>
@@ -48,50 +50,70 @@
</methods>
<members>
<member name="angular_limit/bias" type="float" setter="set_param" getter="get_param">
+ The speed with which the rotation across the axis perpendicular to the hinge gets corrected.
</member>
<member name="angular_limit/enable" type="bool" setter="set_flag" getter="get_flag">
+ If [code]true[/code] the hinges maximum and minimum rotation, defined by [member angular_limit/lower] and [member angular_limit/upper] has effects.
</member>
<member name="angular_limit/lower" type="float" setter="_set_lower_limit" getter="_get_lower_limit">
+ The minimum rotation. only active if [member angular_limit/enable] is [code]true[/code].
</member>
<member name="angular_limit/relaxation" type="float" setter="set_param" getter="get_param">
+ The lower this value, the more the rotation gets slowed down.
</member>
<member name="angular_limit/softness" type="float" setter="set_param" getter="get_param">
</member>
<member name="angular_limit/upper" type="float" setter="_set_upper_limit" getter="_get_upper_limit">
+ The maximum rotation. only active if [member angular_limit/enable] is [code]true[/code].
</member>
<member name="motor/enable" type="bool" setter="set_flag" getter="get_flag">
+ When activated, a motor turns the hinge.
</member>
<member name="motor/max_impulse" type="float" setter="set_param" getter="get_param">
+ Maximum acceleration for the motor.
</member>
<member name="motor/target_velocity" type="float" setter="set_param" getter="get_param">
+ Target speed for the motor.
</member>
<member name="params/bias" type="float" setter="set_param" getter="get_param">
+ The speed with wich the two bodies get pulled together when they move in different directions.
</member>
</members>
<constants>
<constant name="PARAM_BIAS" value="0">
+ The speed with wich the two bodies get pulled together when they move in different directions.
</constant>
<constant name="PARAM_LIMIT_UPPER" value="1">
+ The maximum rotation. only active if [member angular_limit/enable] is [code]true[/code].
</constant>
<constant name="PARAM_LIMIT_LOWER" value="2">
+ The minimum rotation. only active if [member angular_limit/enable] is [code]true[/code].
</constant>
<constant name="PARAM_LIMIT_BIAS" value="3">
+ The speed with which the rotation across the axis perpendicular to the hinge gets corrected.
</constant>
<constant name="PARAM_LIMIT_SOFTNESS" value="4">
</constant>
<constant name="PARAM_LIMIT_RELAXATION" value="5">
+ The lower this value, the more the rotation gets slowed down.
</constant>
<constant name="PARAM_MOTOR_TARGET_VELOCITY" value="6">
+ Target speed for the motor.
</constant>
<constant name="PARAM_MOTOR_MAX_IMPULSE" value="7">
+ Maximum acceleration for the motor.
</constant>
<constant name="PARAM_MAX" value="8">
+ End flag of PARAM_* constants, used internally.
</constant>
<constant name="FLAG_USE_LIMIT" value="0">
+ If [code]true[/code] the hinges maximum and minimum rotation, defined by [member angular_limit/lower] and [member angular_limit/upper] has effects.
</constant>
<constant name="FLAG_ENABLE_MOTOR" value="1">
+ When activated, a motor turns the hinge.
</constant>
<constant name="FLAG_MAX" value="2">
+ End flag of FLAG_* constants, used internally.
</constant>
</constants>
</class>
diff --git a/doc/classes/IP.xml b/doc/classes/IP.xml
index fed7000df6..721cf07441 100644
--- a/doc/classes/IP.xml
+++ b/doc/classes/IP.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="IP" inherits="Object" category="Core" version="3.0.alpha.custom_build">
+<class name="IP" inherits="Object" category="Core" version="3.0-alpha">
<brief_description>
IP Protocol support functions.
</brief_description>
diff --git a/doc/classes/IP_Unix.xml b/doc/classes/IP_Unix.xml
index d30ad795a8..bac7e374bb 100644
--- a/doc/classes/IP_Unix.xml
+++ b/doc/classes/IP_Unix.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="IP_Unix" inherits="IP" category="Core" version="3.0.alpha.custom_build">
+<class name="IP_Unix" inherits="IP" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/Image.xml b/doc/classes/Image.xml
index f4ea9d00ce..b6eb26ce8c 100644
--- a/doc/classes/Image.xml
+++ b/doc/classes/Image.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Image" inherits="Resource" category="Core" version="3.0.alpha.custom_build">
+<class name="Image" inherits="Resource" category="Core" version="3.0-alpha">
<brief_description>
Image datatype.
</brief_description>
<description>
- Native image datatype. Contains image data, which can be converted to a texture, and several functions to interact with it.
+ Native image datatype. Contains image data, which can be converted to a [Texture], and several functions to interact with it. The maximum width and height for an [code]Image[/code] is 16384 pixels.
</description>
<tutorials>
</tutorials>
@@ -21,7 +21,7 @@
<argument index="2" name="dst" type="Vector2">
</argument>
<description>
- Alpha-blends a "src_rect" [Rect2] from "src" [Image] to this [Image] on coordinates "dest".
+ Alpha-blends [code]src_rect[/code] from [code]src[/code] image to this image at coordinates [code]dest[/code].
</description>
</method>
<method name="blend_rect_mask">
@@ -36,7 +36,7 @@
<argument index="3" name="dst" type="Vector2">
</argument>
<description>
- Alpha-blends a "src_rect" [Rect2] from "src" [Image] to this [Image] using a "mask" [Image] on coordinates "dest". Alpha channels are required for both "src" and "mask", dest pixels and src pixels will blend if the corresponding mask pixel's alpha value is not 0. "src" [Image] and "mask" [Image] *must* have the same size (width and height) but they can have different formats
+ Alpha-blends [code]src_rect[/code] from [code]src[/code] image to this image using [code]mask[/code] image at coordinates [code]dst[/code]. Alpha channels are required for both [code]src[/code] and [code]mask[/code]. [code]dst[/code] pixels and [code]src[/code] pixels will blend if the corresponding mask pixel's alpha value is not 0. [code]src[/code] image and [code]mask[/code] image [b]must[/b] have the same size (width and height) but they can have different formats.
</description>
</method>
<method name="blit_rect">
@@ -49,7 +49,7 @@
<argument index="2" name="dst" type="Vector2">
</argument>
<description>
- Copy a "src_rect" [Rect2] from "src" [Image] to this [Image] on coordinates "dest".
+ Copies [code]src_rect[/code] from [code]src[/code] image to this image at coordinates [code]dst[/code].
</description>
</method>
<method name="blit_rect_mask">
@@ -64,13 +64,14 @@
<argument index="3" name="dst" type="Vector2">
</argument>
<description>
- Blits a "src_rect" [Rect2] from "src" [Image] to this [Image] using a "mask" [Image] on coordinates "dest". Alpha channel is required for "mask", will copy src pixel onto dest if the corresponding mask pixel's alpha value is not 0. "src" [Image] and "mask" [Image] *must* have the same size (width and height) but they can have different formats
+ Blits [code]src_rect[/code] area from [code]src[/code] image to this image at the coordinates given by [code]dst[/code]. [code]src[/code] pixel is copied onto [code]dst[/code] if the corresponding [code]mask[/code] pixel's alpha value is not 0. [code]src[/code] image and [code]mask[/code] image [b]must[/b] have the same size (width and height) but they can have different formats.
</description>
</method>
<method name="clear_mipmaps">
<return type="void">
</return>
<description>
+ Removes the image's mipmaps.
</description>
</method>
<method name="compress">
@@ -83,6 +84,7 @@
<argument index="2" name="lossy_quality" type="float">
</argument>
<description>
+ Compresses the image to use less memory. Can not directly access pixel data while the image is compressed. Returns error if the chosen compression mode is not available. See [code]COMPRESS_*[/code] constants.
</description>
</method>
<method name="convert">
@@ -91,6 +93,7 @@
<argument index="0" name="format" type="int" enum="Image.Format">
</argument>
<description>
+ Converts the image's format. See [code]FORMAT_*[/code] constants.
</description>
</method>
<method name="copy_from">
@@ -99,6 +102,7 @@
<argument index="0" name="src" type="Image">
</argument>
<description>
+ Copies [code]src[/code] image to this image.
</description>
</method>
<method name="create">
@@ -113,7 +117,7 @@
<argument index="3" name="format" type="int" enum="Image.Format">
</argument>
<description>
- Create an empty image of a specific size and format.
+ Creates an empty image of given size and format. See [code]FORMAT_*[/code] constants. If [code]use_mipmaps[/code] is true then generate mipmaps for this image. See the [code]generate_mipmaps[/code] method.
</description>
</method>
<method name="create_from_data">
@@ -130,6 +134,7 @@
<argument index="4" name="data" type="PoolByteArray">
</argument>
<description>
+ Creates a new image of given size and format. See [code]FORMAT_*[/code] constants. Fills the image with the given raw data. If [code]use_mipmaps[/code] is true then generate mipmaps for this image. See the [code]generate_mipmaps[/code] method.
</description>
</method>
<method name="crop">
@@ -140,24 +145,28 @@
<argument index="1" name="height" type="int">
</argument>
<description>
+ Crops the image to the given [code]width[/code] and [code]height[/code]. If the specified size is larger than the current size, the extra area is filled with black pixels.
</description>
</method>
<method name="decompress">
<return type="int" enum="Error">
</return>
<description>
+ Decompresses the image if it is compressed. Returns an error if decompress function is not available.
</description>
</method>
<method name="detect_alpha" qualifiers="const">
<return type="int" enum="Image.AlphaMode">
</return>
<description>
+ Returns ALPHA_BLEND if the image has data for alpha values. Returns ALPHA_BIT if all the alpha values are below a certain threshold or the maximum value. Returns ALPHA_NONE if no data for alpha values is found.
</description>
</method>
<method name="expand_x2_hq2x">
<return type="void">
</return>
<description>
+ Stretches the image and enlarges it by a factor of 2. No interpolation is done.
</description>
</method>
<method name="fill">
@@ -166,52 +175,56 @@
<argument index="0" name="color" type="Color">
</argument>
<description>
- Fills an [Image] with a specified [Color]
+ Fills the image with a given [Color].
</description>
</method>
<method name="fix_alpha_edges">
<return type="void">
</return>
<description>
+ Blends low-alpha pixels with nearby pixels.
</description>
</method>
<method name="flip_x">
<return type="void">
</return>
<description>
+ Flips the image horizontally.
</description>
</method>
<method name="flip_y">
<return type="void">
</return>
<description>
+ Flips the image vertically.
</description>
</method>
<method name="generate_mipmaps">
<return type="int" enum="Error">
</return>
<description>
+ Generates mipmaps for the image. Mipmaps are pre-calculated and lower resolution copies of the image. Mipmaps are automatically used if the image needs to be scaled down when rendered. This improves image quality and the performance of the rendering. Returns an error if the image is compressed, in a custom format or if the image's width/height is 0.
</description>
</method>
<method name="get_data" qualifiers="const">
<return type="PoolByteArray">
</return>
<description>
- Return the raw data of the [Image].
+ Returns the image's raw data.
</description>
</method>
<method name="get_format" qualifiers="const">
<return type="int" enum="Image.Format">
</return>
<description>
- Return the format of the [Image], one of [Image].FORMAT_*.
+ Returns the image's raw data.
</description>
</method>
<method name="get_height" qualifiers="const">
<return type="int">
</return>
<description>
- Return the height of the [Image].
+ Returns the image's height.
</description>
</method>
<method name="get_mipmap_offset" qualifiers="const">
@@ -220,6 +233,7 @@
<argument index="0" name="mipmap" type="int">
</argument>
<description>
+ Returns the offset where the image's mipmap with index [code]mipmap[/code] is stored in the [code]data[/code] dictionary.
</description>
</method>
<method name="get_pixel" qualifiers="const">
@@ -230,6 +244,7 @@
<argument index="1" name="y" type="int">
</argument>
<description>
+ Returns the color of the pixel at [code](x, y)[/code] if the image is locked. If the image is unlocked it always returns a [Color] with the value [code](0, 0, 0, 1.0)[/code].
</description>
</method>
<method name="get_rect" qualifiers="const">
@@ -238,51 +253,56 @@
<argument index="0" name="rect" type="Rect2">
</argument>
<description>
- Return a new [Image] that is a copy of "area" in this [Image].
+ Returns a new image that is a copy of the image's area specified with [code]rect[/code].
</description>
</method>
<method name="get_size" qualifiers="const">
<return type="Vector2">
</return>
<description>
+ Returns the image's size (width and height).
</description>
</method>
<method name="get_used_rect" qualifiers="const">
<return type="Rect2">
</return>
<description>
- Return the area of this [Image] that is used/visibly colored/opaque.
+ Returns a [Rect2] enclosing the visible portion of the image.
</description>
</method>
<method name="get_width" qualifiers="const">
<return type="int">
</return>
<description>
- Return the width of the [Image].
+ Returns the image's width.
</description>
</method>
<method name="has_mipmaps" qualifiers="const">
<return type="bool">
</return>
<description>
+ Returns [code]true[/code] if the image has generated mipmaps.
</description>
</method>
<method name="is_compressed" qualifiers="const">
<return type="bool">
</return>
<description>
+ Returns [code]true[/code] if the image is compressed.
</description>
</method>
<method name="is_empty" qualifiers="const">
<return type="bool">
</return>
<description>
+ Returns [code]true[/code] if the image has no data.
</description>
</method>
<method name="is_invisible" qualifiers="const">
<return type="bool">
</return>
<description>
+ Returns [code]true[/code] if all the image's pixels have an alpha value of 0. Returns [code]false[/code] if any pixel has an alpha value higher than 0.
</description>
</method>
<method name="load">
@@ -291,25 +311,28 @@
<argument index="0" name="path" type="String">
</argument>
<description>
- Load an [Image].
+ Loads an image from file [code]path[/code].
</description>
</method>
<method name="lock">
<return type="void">
</return>
<description>
+ Locks the data and prevents changes.
</description>
</method>
<method name="normalmap_to_xy">
<return type="void">
</return>
<description>
+ Converts the image's data to represent coordinates on a 3D plane. This is used when the image represents a normalmap. A normalmap can add lots of detail to a 3D surface without increasing the polygon count.
</description>
</method>
<method name="premultiply_alpha">
<return type="void">
</return>
<description>
+ Multiplies color values with alpha values. Resulting color values for a pixel are [code](color * alpha)/256[/code].
</description>
</method>
<method name="resize">
@@ -322,6 +345,7 @@
<argument index="2" name="interpolation" type="int" enum="Image.Interpolation" default="1">
</argument>
<description>
+ Resizes the image to the given [code]width[/code] and [code]height[/code]. New pixels are calculated using [code]interpolation[/code]. See [code]interpolation[/code] constants.
</description>
</method>
<method name="resize_to_po2">
@@ -330,6 +354,7 @@
<argument index="0" name="square" type="bool" default="false">
</argument>
<description>
+ Resizes the image to the nearest power of 2 for the width and height. If [code]square[/code] is [code]true[/code] then set width and height to be the same.
</description>
</method>
<method name="save_png" qualifiers="const">
@@ -338,7 +363,7 @@
<argument index="0" name="path" type="String">
</argument>
<description>
- Save this [Image] as a png.
+ Saves the image as a PNG file to [code]path[/code].
</description>
</method>
<method name="set_pixel">
@@ -351,29 +376,41 @@
<argument index="2" name="color" type="Color">
</argument>
<description>
+ Sets the [Color] of the pixel at [code](x, y)[/code] if the image is unlocked. Example:
+ [codeblock]
+ var img = Image.new()
+ img.lock()
+ img.set_pixel(x, y, color) # Does not have an effect
+ img.unlock()
+ img.set_pixel(x, y, color) # Works
+ [/codeblock]
</description>
</method>
<method name="shrink_x2">
<return type="void">
</return>
<description>
+ Shrinks the image by a factor of 2.
</description>
</method>
<method name="srgb_to_linear">
<return type="void">
</return>
<description>
+ Converts the raw data from the sRGB colorspace to a linear scale.
</description>
</method>
<method name="unlock">
<return type="void">
</return>
<description>
+ Unlocks the data for writing access.
</description>
</method>
</methods>
<members>
<member name="data" type="Dictionary" setter="_set_data" getter="_get_data">
+ Holds all of the image's color data in a given format. See [code]FORMAT_*[/code] constants.
</member>
</members>
<constants>
diff --git a/doc/classes/ImageTexture.xml b/doc/classes/ImageTexture.xml
index 4fcdf684c0..d179794c1f 100644
--- a/doc/classes/ImageTexture.xml
+++ b/doc/classes/ImageTexture.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ImageTexture" inherits="Texture" category="Core" version="3.0.alpha.custom_build">
+<class name="ImageTexture" inherits="Texture" category="Core" version="3.0-alpha">
<brief_description>
A [Texture] based on an [Image].
</brief_description>
<description>
- A [Texture] based on an [Image]. Can be created from an [Image].
+ A [Texture] based on an [Image]. Can be created from an [Image] with [method create_from_image].
</description>
<tutorials>
</tutorials>
@@ -23,7 +23,7 @@
<argument index="3" name="flags" type="int" default="7">
</argument>
<description>
- Create a new [ImageTexture] with "width" and "height".
+ Create a new [code]ImageTexture[/code] with "width" and "height".
"format" one of [Image].FORMAT_*.
"flags" one or more of [Texture].FLAG_*.
</description>
@@ -36,28 +36,28 @@
<argument index="1" name="flags" type="int" default="7">
</argument>
<description>
- Create a new [ImageTexture] from an [Image] with "flags" from [Texture].FLAG_*.
+ Create a new [code]ImageTexture[/code] from an [Image] with "flags" from [Texture].FLAG_*.
</description>
</method>
<method name="get_format" qualifiers="const">
<return type="int" enum="Image.Format">
</return>
<description>
- Return the format of the [ImageTexture], one of [Image].FORMAT_*.
+ Return the format of the [code]ImageTexture[/code], one of [Image].FORMAT_*.
</description>
</method>
<method name="get_lossy_storage_quality" qualifiers="const">
<return type="float">
</return>
<description>
- Return the storage quality for [ImageTexture].STORAGE_COMPRESS_LOSSY.
+ Return the storage quality for [code]ImageTexture[/code].STORAGE_COMPRESS_LOSSY.
</description>
</method>
<method name="get_storage" qualifiers="const">
<return type="int" enum="ImageTexture.Storage">
</return>
<description>
- Return the storage type. One of [ImageTexture].STORAGE_*.
+ Return the storage type. One of [code]ImageTexture[/code].STORAGE_*.
</description>
</method>
<method name="load">
@@ -66,7 +66,7 @@
<argument index="0" name="path" type="String">
</argument>
<description>
- Load an [ImageTexture].
+ Load an [code]ImageTexture[/code].
</description>
</method>
<method name="set_data">
@@ -75,7 +75,7 @@
<argument index="0" name="image" type="Image">
</argument>
<description>
- Set the [Image] of this [ImageTexture].
+ Set the [Image] of this [code]ImageTexture[/code].
</description>
</method>
<method name="set_lossy_storage_quality">
@@ -84,7 +84,7 @@
<argument index="0" name="quality" type="float">
</argument>
<description>
- Set the storage quality in case of [ImageTexture].STORAGE_COMPRESS_LOSSY.
+ Set the storage quality in case of [code]ImageTexture[/code].STORAGE_COMPRESS_LOSSY.
</description>
</method>
<method name="set_size_override">
@@ -93,6 +93,7 @@
<argument index="0" name="size" type="Vector2">
</argument>
<description>
+ Resizes the [code]ImageTexture[/code] to the specified dimensions.
</description>
</method>
<method name="set_storage">
@@ -101,7 +102,7 @@
<argument index="0" name="mode" type="int" enum="ImageTexture.Storage">
</argument>
<description>
- Set the storage type. One of [ImageTexture].STORAGE_*.
+ Set the storage type. One of [code]ImageTexture[/code].STORAGE_*.
</description>
</method>
</methods>
diff --git a/doc/classes/ImmediateGeometry.xml b/doc/classes/ImmediateGeometry.xml
index b12f9c99a9..7ad09c3fe9 100644
--- a/doc/classes/ImmediateGeometry.xml
+++ b/doc/classes/ImmediateGeometry.xml
@@ -1,9 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ImmediateGeometry" inherits="GeometryInstance" category="Core" version="3.0.alpha.custom_build">
+<class name="ImmediateGeometry" inherits="GeometryInstance" category="Core" version="3.0-alpha">
<brief_description>
- Node to draw simple geometry from code, ala OpenGL 1.x
+ Draws simple geometry from code.
</brief_description>
<description>
+ Draws simple geometry from code. Uses a drawing mode similar to OpenGL 1.x.
</description>
<tutorials>
</tutorials>
@@ -31,7 +32,7 @@
<argument index="0" name="position" type="Vector3">
</argument>
<description>
- Add a vertex with the currently set color/uv/etc.
+ Adds a vertex with the currently set color/uv/etc.
</description>
</method>
<method name="begin">
@@ -50,14 +51,14 @@
<return type="void">
</return>
<description>
- Clear everything that was drawn using begin/end.
+ Clears everything that was drawn using begin/end.
</description>
</method>
<method name="end">
<return type="void">
</return>
<description>
- Call this when done adding a batch of geometry, otherwise it can't be displayed.
+ Ends a drawing context and displays the results.
</description>
</method>
<method name="set_color">
@@ -66,7 +67,7 @@
<argument index="0" name="color" type="Color">
</argument>
<description>
- Set the color that the next vertex will use to be drawn.
+ The current drawing color.
</description>
</method>
<method name="set_normal">
@@ -75,7 +76,7 @@
<argument index="0" name="normal" type="Vector3">
</argument>
<description>
- Set the normal that the next vertex will use to be drawn.
+ The next vertex's normal.
</description>
</method>
<method name="set_tangent">
@@ -84,7 +85,7 @@
<argument index="0" name="tangent" type="Plane">
</argument>
<description>
- Set the tangent (and binormal facing) that the next vertex will use to be drawn.
+ The next vertex's tangent (and binormal facing).
</description>
</method>
<method name="set_uv">
@@ -93,7 +94,7 @@
<argument index="0" name="uv" type="Vector2">
</argument>
<description>
- Set the UV that the next vertex will use to be drawn.
+ The next vertex's UV.
</description>
</method>
<method name="set_uv2">
@@ -102,7 +103,7 @@
<argument index="0" name="uv" type="Vector2">
</argument>
<description>
- Set the second layer of UV that the next vertex will use to be drawn.
+ The next vertex's second layer UV.
</description>
</method>
</methods>
diff --git a/doc/classes/Input.xml b/doc/classes/Input.xml
index 3d8b4154f8..114c8d2c59 100644
--- a/doc/classes/Input.xml
+++ b/doc/classes/Input.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Input" inherits="Object" category="Core" version="3.0.alpha.custom_build">
+<class name="Input" inherits="Object" category="Core" version="3.0-alpha">
<brief_description>
A Singleton that deals with inputs.
</brief_description>
<description>
- A Singleton that deals with inputs. This includes key presses, mouse buttons and movement, joypads, and input actions.
+ A Singleton that deals with inputs. This includes key presses, mouse buttons and movement, joypads, and input actions. Actions and their events can be set in the Project Settings / Input Map tab. Or be set with [InputMap].
</description>
<tutorials>
</tutorials>
@@ -75,7 +75,7 @@
<argument index="1" name="axis" type="int">
</argument>
<description>
- Returns the current value of the joypad axis at given index (see JOY_* constants in [@Global Scope])
+ Returns the current value of the joypad axis at given index (see [code]JOY_*[/code] constants in [@GlobalScope])
</description>
</method>
<method name="get_joy_axis_index_from_string">
@@ -180,6 +180,7 @@
<argument index="0" name="action" type="String">
</argument>
<description>
+ Returns [code]true[/code] when you start pressing the action event.
</description>
</method>
<method name="is_action_just_released" qualifiers="const">
@@ -188,6 +189,7 @@
<argument index="0" name="action" type="String">
</argument>
<description>
+ Returns [code]true[/code] when you stop pressing the action event.
</description>
</method>
<method name="is_action_pressed" qualifiers="const">
@@ -196,7 +198,7 @@
<argument index="0" name="action" type="String">
</argument>
<description>
- Returns true or false depending on whether the action event is pressed. Actions and their events can be set in the Project Settings / Input Map tab. Or be set with [InputMap].
+ Returns [code]true[/code] if you are pressing the action event.
</description>
</method>
<method name="is_joy_button_pressed" qualifiers="const">
@@ -207,7 +209,7 @@
<argument index="1" name="button" type="int">
</argument>
<description>
- Returns if the joypad button at the given index is currently pressed. (see JOY_* constants in [@Global Scope])
+ Returns [code]true[/code] if you are pressing the joypad button. (see [code]JOY_*[/code] constants in [@GlobalScope])
</description>
</method>
<method name="is_joy_known">
@@ -216,7 +218,7 @@
<argument index="0" name="device" type="int">
</argument>
<description>
- Returns if the specified device is known by the system. This means that it sets all button and axis indices exactly as defined in the JOY_* constants (see [@Global Scope]). Unknown joypads are not expected to match these constants, but you can still retrieve events from them.
+ Returns [code]true[/code] if the system knows the specified device. This means that it sets all button and axis indices exactly as defined in the [code]JOY_*[/code] constants (see [@GlobalScope]). Unknown joypads are not expected to match these constants, but you can still retrieve events from them.
</description>
</method>
<method name="is_key_pressed" qualifiers="const">
@@ -225,7 +227,7 @@
<argument index="0" name="scancode" type="int">
</argument>
<description>
- Returns true or false depending on whether the key is pressed or not. You can pass KEY_*, which are pre-defined constants listed in [@Global Scope].
+ Returns [code]true[/code] if you are pressing the key. You can pass [code]KEY_*[/code], which are pre-defined constants listed in [@GlobalScope].
</description>
</method>
<method name="is_mouse_button_pressed" qualifiers="const">
@@ -234,7 +236,21 @@
<argument index="0" name="button" type="int">
</argument>
<description>
- Returns true or false depending on whether mouse button is pressed or not. You can pass BUTTON_*, which are pre-defined constants listed in [@Global Scope].
+ Returns [code]true[/code] if you are pressing the mouse button. You can pass [code]BUTTON_*[/code], which are pre-defined constants listed in [@GlobalScope].
+ </description>
+ </method>
+ <method name="joy_connection_changed">
+ <return type="void">
+ </return>
+ <argument index="0" name="device" type="int">
+ </argument>
+ <argument index="1" name="connected" type="bool">
+ </argument>
+ <argument index="2" name="name" type="String">
+ </argument>
+ <argument index="3" name="guid" type="String">
+ </argument>
+ <description>
</description>
</method>
<method name="parse_input_event">
diff --git a/doc/classes/InputDefault.xml b/doc/classes/InputDefault.xml
index cb8ad6b823..9cbc993af1 100644
--- a/doc/classes/InputDefault.xml
+++ b/doc/classes/InputDefault.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="InputDefault" inherits="Input" category="Core" version="3.0.alpha.custom_build">
+<class name="InputDefault" inherits="Input" category="Core" version="3.0-alpha">
<brief_description>
Default implementation of the [Input] class.
</brief_description>
diff --git a/doc/classes/InputEvent.xml b/doc/classes/InputEvent.xml
index 392ee25ad6..e4404fc258 100644
--- a/doc/classes/InputEvent.xml
+++ b/doc/classes/InputEvent.xml
@@ -1,11 +1,13 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="InputEvent" inherits="Resource" category="Core" version="3.0.alpha.custom_build">
+<class name="InputEvent" inherits="Resource" category="Core" version="3.0-alpha">
<brief_description>
Generic input event
</brief_description>
<description>
+ Base class of all sort of input event. See [method Node._input].
</description>
<tutorials>
+ http://docs.godotengine.org/en/stable/learning/features/inputs/inputevent.html
</tutorials>
<demos>
</demos>
@@ -16,7 +18,7 @@
<argument index="0" name="event" type="InputEvent">
</argument>
<description>
- Returns true if this input event matches the event passed.
+ Returns [code]true[/code] if this event matches [code]event[/code].
</description>
</method>
<method name="as_text" qualifiers="const">
@@ -30,14 +32,14 @@
<return type="int">
</return>
<description>
- Returns the id of the device that generated the event.
+ Returns the device's id that generated the event.
</description>
</method>
<method name="get_id" qualifiers="const">
<return type="int">
</return>
<description>
- Returns the id of the event.
+ Returns the event's ID.
</description>
</method>
<method name="is_action" qualifiers="const">
@@ -46,7 +48,7 @@
<argument index="0" name="action" type="String">
</argument>
<description>
- Returns true if this input event matches a pre-defined action, no matter the type.
+ Returns [code]true[/code] if this input event matches a pre-defined action of any type.
</description>
</method>
<method name="is_action_pressed" qualifiers="const">
@@ -55,7 +57,7 @@
<argument index="0" name="action" type="String">
</argument>
<description>
- Returns true if the given action is being pressed (and is not an echo event for KEY events). Not relevant for the event types MOUSE_MOTION, SCREEN_DRAG and NONE.
+ Returns [code]true[/code] if the given action is being pressed (and is not an echo event for KEY events). Not relevant for the event types [code]MOUSE_MOTION[/code], [code]SCREEN_DRAG[/code] or [code]NONE[/code].
</description>
</method>
<method name="is_action_released" qualifiers="const">
@@ -64,27 +66,28 @@
<argument index="0" name="action" type="String">
</argument>
<description>
- Returns true if the given action is released (i.e. not pressed). Not relevant for the event types MOUSE_MOTION, SCREEN_DRAG and NONE.
+ Returns [code]true[/code] if the given action is released (i.e. not pressed). Not relevant for the event types [code]MOUSE_MOTION[/code], [code]SCREEN_DRAG[/code] or [code]NONE[/code].
</description>
</method>
<method name="is_action_type" qualifiers="const">
<return type="bool">
</return>
<description>
+ Returns [code]true[/code] if this input event's type is one of the [code]InputEvent[/code] constants.
</description>
</method>
<method name="is_echo" qualifiers="const">
<return type="bool">
</return>
<description>
- Returns true if this input event is an echo event (only for events of type KEY, it will return false for other types).
+ Returns [code]true[/code] if this input event is an echo event (only for events of type KEY).
</description>
</method>
<method name="is_pressed" qualifiers="const">
<return type="bool">
</return>
<description>
- Returns true if this input event is pressed. Not relevant for the event types MOUSE_MOTION, SCREEN_DRAG and NONE.
+ Returns [code]true[/code] if this input event is pressed. Not relevant for the event types [code]MOUSE_MOTION[/code], [code]SCREEN_DRAG[/code] or [code]NONE[/code].
</description>
</method>
<method name="set_device">
@@ -124,6 +127,7 @@
</methods>
<members>
<member name="device" type="int" setter="set_device" getter="get_device">
+ The event's device ID.
</member>
</members>
<constants>
diff --git a/doc/classes/InputEventAction.xml b/doc/classes/InputEventAction.xml
index 2617ea4dfa..383f8360fb 100644
--- a/doc/classes/InputEventAction.xml
+++ b/doc/classes/InputEventAction.xml
@@ -1,11 +1,13 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="InputEventAction" inherits="InputEvent" category="Core" version="3.0.alpha.custom_build">
+<class name="InputEventAction" inherits="InputEvent" category="Core" version="3.0-alpha">
<brief_description>
Input event type for actions.
</brief_description>
<description>
+ Contains a generic action which can be targeted from several type of inputs. Actions can be created from the project settings menu [code]Project &gt; Project Settings &gt; Input Map[/code]. See [method Node._input].
</description>
<tutorials>
+ http://docs.godotengine.org/en/stable/learning/features/inputs/inputevent.html#actions
</tutorials>
<demos>
</demos>
@@ -35,8 +37,10 @@
</methods>
<members>
<member name="action" type="String" setter="set_action" getter="get_action">
+ The action's name. Actions are accessed via this [String].
</member>
<member name="pressed" type="bool" setter="set_pressed" getter="is_pressed">
+ If [code]true[/code] the action's state is pressed. If [code]false[/code] the action's state is released.
</member>
</members>
<constants>
diff --git a/doc/classes/InputEventJoypadButton.xml b/doc/classes/InputEventJoypadButton.xml
index 2784b06442..fecd65e6a2 100644
--- a/doc/classes/InputEventJoypadButton.xml
+++ b/doc/classes/InputEventJoypadButton.xml
@@ -1,11 +1,13 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="InputEventJoypadButton" inherits="InputEvent" category="Core" version="3.0.alpha.custom_build">
+<class name="InputEventJoypadButton" inherits="InputEvent" category="Core" version="3.0-alpha">
<brief_description>
- Input event type for joypad button events.
+ Input event for gamepad buttons.
</brief_description>
<description>
+ Input event type for gamepad buttons. For joysticks see [InputEventJoypadMotion].
</description>
<tutorials>
+ http://docs.godotengine.org/en/stable/learning/features/inputs/inputevent.html
</tutorials>
<demos>
</demos>
@@ -49,13 +51,13 @@
</methods>
<members>
<member name="button_index" type="int" setter="set_button_index" getter="get_button_index">
- Joypad button identifier, one of the JOY_BUTTON_* constants in [@Global Scope].
+ Button identifier. One of the [code]JOY_BUTTON_*[/code] constants from [@global Scope].
</member>
<member name="pressed" type="bool" setter="set_pressed" getter="is_pressed">
- Pressed state of the joypad button.
+ If [code]true[/code] the button's state is pressed. If [code]false[/code] the button's state is released.
</member>
<member name="pressure" type="float" setter="set_pressure" getter="get_pressure">
- Intensity of the button pressure, ranges from 0 to 1.0.
+ Represents the pressure the user puts on the button with his finger, if the controller supports it. Ranges from [code]0[/code] to [code]1[/code].
</member>
</members>
<constants>
diff --git a/doc/classes/InputEventJoypadMotion.xml b/doc/classes/InputEventJoypadMotion.xml
index 8a26007fc1..a89c91fbe6 100644
--- a/doc/classes/InputEventJoypadMotion.xml
+++ b/doc/classes/InputEventJoypadMotion.xml
@@ -1,11 +1,13 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="InputEventJoypadMotion" inherits="InputEvent" category="Core" version="3.0.alpha.custom_build">
+<class name="InputEventJoypadMotion" inherits="InputEvent" category="Core" version="3.0-alpha">
<brief_description>
- Input event type for joypad motion/axis events.
+ Input event type for gamepad joysticks and other motions. For buttons see [code]InputEventJoypadMotion[/code].
</brief_description>
<description>
+ Stores information about joystick motions. One [code]InputEventJoypadMotion[/code] represents one axis at a time.
</description>
<tutorials>
+ http://docs.godotengine.org/en/stable/learning/features/inputs/inputevent.html
</tutorials>
<demos>
</demos>
@@ -41,10 +43,10 @@
</methods>
<members>
<member name="axis" type="int" setter="set_axis" getter="get_axis">
- Joypad axis identifier, one of the JOY_AXIS_* constants in [@Global Scope].
+ Axis identifier. Use one of the [code]JOY_AXIS_*[/code] constants in [@global Scope].
</member>
<member name="axis_value" type="float" setter="set_axis_value" getter="get_axis_value">
- Position of the axis, ranging from -1.0 to 1.0. A value of 0 means that the axis is in its neutral position.
+ Current position of the joystick on the given axis. The value ranges from [code]-1.0[/code] to [code]1.0[/code]. A value of [code]0[/code] means the axis is in its resting position.
</member>
</members>
<constants>
diff --git a/doc/classes/InputEventKey.xml b/doc/classes/InputEventKey.xml
index 151e19d25d..440e1347f8 100644
--- a/doc/classes/InputEventKey.xml
+++ b/doc/classes/InputEventKey.xml
@@ -1,11 +1,13 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="InputEventKey" inherits="InputEventWithModifiers" category="Core" version="3.0.alpha.custom_build">
+<class name="InputEventKey" inherits="InputEventWithModifiers" category="Core" version="3.0-alpha">
<brief_description>
Input event type for keyboard events.
</brief_description>
<description>
+ Stores key presses on the keyboard. Supports key presses, key releases and [member echo] events.
</description>
<tutorials>
+ http://docs.godotengine.org/en/stable/learning/features/inputs/inputevent.html
</tutorials>
<demos>
</demos>
@@ -63,16 +65,16 @@
</methods>
<members>
<member name="echo" type="bool" setter="set_echo" getter="is_echo">
- Echo state of the key, i.e. whether it's a repeat event or not.
+ If [code]true[/code] the key was already pressed before this event. It means the user is holding the key down.
</member>
<member name="pressed" type="bool" setter="set_pressed" getter="is_pressed">
- Pressed state of the key.
+ If [code]true[/code] the key's state is pressed. If [code]false[/code] the key's state is released.
</member>
<member name="scancode" type="int" setter="set_scancode" getter="get_scancode">
- Scancode of the key, one of the KEY_* constants in [@Global Scope].
+ Key scancode, one of the [code]KEY_*[/code] constants in [@global Scope].
</member>
<member name="unicode" type="int" setter="set_unicode" getter="get_unicode">
- Unicode identifier of the key (when relevant).
+ Key unicode identifier when relevant.
</member>
</members>
<constants>
diff --git a/doc/classes/InputEventMouse.xml b/doc/classes/InputEventMouse.xml
index 57f0acbf30..24a771cef3 100644
--- a/doc/classes/InputEventMouse.xml
+++ b/doc/classes/InputEventMouse.xml
@@ -1,11 +1,13 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="InputEventMouse" inherits="InputEventWithModifiers" category="Core" version="3.0.alpha.custom_build">
+<class name="InputEventMouse" inherits="InputEventWithModifiers" category="Core" version="3.0-alpha">
<brief_description>
Base input event type for mouse events.
</brief_description>
<description>
+ Stores general mouse events informations.
</description>
<tutorials>
+ http://docs.godotengine.org/en/stable/learning/features/inputs/inputevent.html
</tutorials>
<demos>
</demos>
@@ -55,13 +57,13 @@
</methods>
<members>
<member name="button_mask" type="int" setter="set_button_mask" getter="get_button_mask">
- Mouse button mask identifier, one of or a bitwise combination of the BUTTON_MASK_* constants in [@Global Scope].
+ Mouse button mask identifier, one of or a bitwise combination of the BUTTON_MASK_* constants in [@GlobalScope].
</member>
<member name="global_position" type="Vector2" setter="set_global_position" getter="get_global_position">
- Global position of the mouse click.
+ Mouse position relative to the current [Viewport] when used in [method Control._gui_input], otherwise is at 0,0.
</member>
<member name="position" type="Vector2" setter="set_position" getter="get_position">
- Local position of the mouse click.
+ Mouse local position relative to the [Viewport]. If used in [method Control._gui_input] the position is relative to the current [Control] wich is under the mouse.
</member>
</members>
<constants>
diff --git a/doc/classes/InputEventMouseButton.xml b/doc/classes/InputEventMouseButton.xml
index 63e31eb61c..ff7c1da34e 100644
--- a/doc/classes/InputEventMouseButton.xml
+++ b/doc/classes/InputEventMouseButton.xml
@@ -1,11 +1,13 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="InputEventMouseButton" inherits="InputEventMouse" category="Core" version="3.0.alpha.custom_build">
+<class name="InputEventMouseButton" inherits="InputEventMouse" category="Core" version="3.0-alpha">
<brief_description>
Input event type for mouse button events.
</brief_description>
<description>
+ Contains mouse click informations. See [method Node._input].
</description>
<tutorials>
+ http://docs.godotengine.org/en/stable/learning/features/inputs/inputevent.html
</tutorials>
<demos>
</demos>
@@ -63,15 +65,16 @@
</methods>
<members>
<member name="button_index" type="int" setter="set_button_index" getter="get_button_index">
- Mouse button identifier, one of the BUTTON_* or BUTTON_WHEEL_* constants in [@Global Scope].
+ Mouse button identifier, one of the BUTTON_* or BUTTON_WHEEL_* constants in [@GlobalScope].
</member>
<member name="doubleclick" type="bool" setter="set_doubleclick" getter="is_doubleclick">
- Whether the event is a double-click.
+ If [code]true[/code] the mouse button's state is a double-click. If [code]false[/code] the mouse button's state is released.
</member>
<member name="factor" type="float" setter="set_factor" getter="get_factor">
+ TO TALK in PR, reduz said : i think it's used for apple touch but i don't remember what it does
</member>
<member name="pressed" type="bool" setter="set_pressed" getter="is_pressed">
- Pressed state of the mouse button.
+ If [code]true[/code] the mouse button's state is pressed. If [code]false[/code] the mouse button's state is released.
</member>
</members>
<constants>
diff --git a/doc/classes/InputEventMouseMotion.xml b/doc/classes/InputEventMouseMotion.xml
index 59fe8d2e58..6c9165fea8 100644
--- a/doc/classes/InputEventMouseMotion.xml
+++ b/doc/classes/InputEventMouseMotion.xml
@@ -1,11 +1,13 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="InputEventMouseMotion" inherits="InputEventMouse" category="Core" version="3.0.alpha.custom_build">
+<class name="InputEventMouseMotion" inherits="InputEventMouse" category="Core" version="3.0-alpha">
<brief_description>
Input event type for mouse motion events.
</brief_description>
<description>
+ Contains mouse motion informations. Supports relative, absolute positions and speed. See [method Node._input].
</description>
<tutorials>
+ http://docs.godotengine.org/en/stable/learning/features/inputs/inputevent.html
</tutorials>
<demos>
</demos>
@@ -41,10 +43,10 @@
</methods>
<members>
<member name="relative" type="Vector2" setter="set_relative" getter="get_relative">
- Position of the mouse pointer relative to the previous mouse position.
+ Mouse position relative to the previous position (position at the last frame).
</member>
<member name="speed" type="Vector2" setter="set_speed" getter="get_speed">
- Speed of the mouse pointer.
+ Mouse speed.
</member>
</members>
<constants>
diff --git a/doc/classes/InputEventScreenDrag.xml b/doc/classes/InputEventScreenDrag.xml
index 0b0ecc17bc..a68f444a7c 100644
--- a/doc/classes/InputEventScreenDrag.xml
+++ b/doc/classes/InputEventScreenDrag.xml
@@ -1,11 +1,14 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="InputEventScreenDrag" inherits="InputEvent" category="Core" version="3.0.alpha.custom_build">
+<class name="InputEventScreenDrag" inherits="InputEvent" category="Core" version="3.0-alpha">
<brief_description>
Input event type for screen drag events.
+ (only available on mobile devices)
</brief_description>
<description>
+ Contains screen drag informations. See [method Node._input].
</description>
<tutorials>
+ http://docs.godotengine.org/en/stable/learning/features/inputs/inputevent.html
</tutorials>
<demos>
</demos>
@@ -72,13 +75,13 @@
Drag event index in the case of a multi-drag event.
</member>
<member name="position" type="Vector2" setter="set_position" getter="get_position">
- Position of the drag event.
+ Drag position.
</member>
<member name="relative" type="Vector2" setter="set_relative" getter="get_relative">
- Position of the drag event relative to its start position.
+ Drag position relative to its start position.
</member>
<member name="speed" type="Vector2" setter="set_speed" getter="get_speed">
- Speed of the drag event.
+ Drag speed.
</member>
</members>
<constants>
diff --git a/doc/classes/InputEventScreenTouch.xml b/doc/classes/InputEventScreenTouch.xml
index 48c5626f14..d0c7181e84 100644
--- a/doc/classes/InputEventScreenTouch.xml
+++ b/doc/classes/InputEventScreenTouch.xml
@@ -1,11 +1,14 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="InputEventScreenTouch" inherits="InputEvent" category="Core" version="3.0.alpha.custom_build">
+<class name="InputEventScreenTouch" inherits="InputEvent" category="Core" version="3.0-alpha">
<brief_description>
Input event type for screen touch events.
+ (only available on mobile devices)
</brief_description>
<description>
+ Stores multi-touch press/release information. Supports touch press, touch release and [member index] for multi-touch count and order.
</description>
<tutorials>
+ http://docs.godotengine.org/en/stable/learning/features/inputs/inputevent.html
</tutorials>
<demos>
</demos>
@@ -49,13 +52,13 @@
</methods>
<members>
<member name="index" type="int" setter="set_index" getter="get_index">
- Touch event index in the case of a multi-touch event.
+ Touch index in the case of a multi-touch event. One index = one finger.
</member>
<member name="position" type="Vector2" setter="set_position" getter="get_position">
- Position of the touch event.
+ Touch position.
</member>
<member name="pressed" type="bool" setter="set_pressed" getter="is_pressed">
- Pressed state of the touch event.
+ If [code]true[/code] the touch's state is pressed. If [code]false[/code] the touch's state is released.
</member>
</members>
<constants>
diff --git a/doc/classes/InputEventWithModifiers.xml b/doc/classes/InputEventWithModifiers.xml
index 7bbdf0a441..8e5ffed149 100644
--- a/doc/classes/InputEventWithModifiers.xml
+++ b/doc/classes/InputEventWithModifiers.xml
@@ -1,11 +1,13 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="InputEventWithModifiers" inherits="InputEvent" category="Core" version="3.0.alpha.custom_build">
+<class name="InputEventWithModifiers" inherits="InputEvent" category="Core" version="3.0-alpha">
<brief_description>
- Base class for input events with modifiers.
+ Base class for keys events with modifiers.
</brief_description>
<description>
+ Contains keys events informations with modifiers support like [code]SHIFT[/code] or [code]ALT[/code]. See [method Node._input].
</description>
<tutorials>
+ http://docs.godotengine.org/en/stable/learning/features/inputs/inputevent.html
</tutorials>
<demos>
</demos>
diff --git a/doc/classes/InputMap.xml b/doc/classes/InputMap.xml
index bf72ba05e7..d5a1d85def 100644
--- a/doc/classes/InputMap.xml
+++ b/doc/classes/InputMap.xml
@@ -1,11 +1,13 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="InputMap" inherits="Object" category="Core" version="3.0.alpha.custom_build">
+<class name="InputMap" inherits="Object" category="Core" version="3.0-alpha">
<brief_description>
- Singleton that manages actions.
+ Singleton that manages [InputEventAction].
</brief_description>
<description>
+ Manages all [InputEventAction] which can be created/modified from the project settings menu [code]Project &gt; Project Settings &gt; Input Map[/code] or in code with [method add_action] and [method action_add_event]. See [method Node._input].
</description>
<tutorials>
+ http://docs.godotengine.org/en/stable/learning/features/inputs/inputevent.html#inputmap
</tutorials>
<demos>
</demos>
@@ -18,7 +20,7 @@
<argument index="1" name="event" type="InputEvent">
</argument>
<description>
- Add an [InputEvent] to an action. This [InputEvent] will trigger the action.
+ Adds an [InputEvent] to an action. This [InputEvent] will trigger the action.
</description>
</method>
<method name="action_erase_event">
@@ -29,7 +31,7 @@
<argument index="1" name="event" type="InputEvent">
</argument>
<description>
- Remove an [InputEvent] from an action.
+ Removes an [InputEvent] from an action.
</description>
</method>
<method name="action_has_event">
@@ -40,7 +42,7 @@
<argument index="1" name="event" type="InputEvent">
</argument>
<description>
- Whether an action has an [InputEvent] associated with it.
+ Returns [true] if an action has an [InputEvent] associated with it.
</description>
</method>
<method name="add_action">
@@ -49,7 +51,7 @@
<argument index="0" name="action" type="String">
</argument>
<description>
- Add an (empty) action to the [InputMap]. An [InputEvent] can then be added to this action with [method action_add_event].
+ Adds an (empty) action to the [code]InputMap[/code]. An [InputEvent] can then be added to this action with [method action_add_event].
</description>
</method>
<method name="erase_action">
@@ -58,7 +60,7 @@
<argument index="0" name="action" type="String">
</argument>
<description>
- Remove an action from the [InputMap].
+ Removes an action from the [code]InputMap[/code].
</description>
</method>
<method name="event_is_action" qualifiers="const">
@@ -69,7 +71,7 @@
<argument index="1" name="action" type="String">
</argument>
<description>
- Return whether the given event is part of an existing action. This method ignores keyboard modifiers if the given [InputEvent] is not pressed (for proper release detection). See [method action_has_event] if you don't want this behavior.
+ Returns [true] if the given event is part of an existing action. This method ignores keyboard modifiers if the given [InputEvent] is not pressed (for proper release detection). See [method action_has_event] if you don't want this behavior.
</description>
</method>
<method name="get_action_list">
@@ -78,14 +80,14 @@
<argument index="0" name="action" type="String">
</argument>
<description>
- Return an array of InputEvents associated with a given action.
+ Returns an array of [InputEvent]s associated with a given action.
</description>
</method>
<method name="get_actions">
<return type="Array">
</return>
<description>
- Return an array of all actions in the [InputMap].
+ Returns an array of all actions in the [code]InputMap[/code].
</description>
</method>
<method name="has_action" qualifiers="const">
@@ -94,14 +96,14 @@
<argument index="0" name="action" type="String">
</argument>
<description>
- Whether this InputMap has a registered action with the given name.
+ Returns [code]true[/code] if the [code]InputMap[/code] has a registered action with the given name.
</description>
</method>
<method name="load_from_globals">
<return type="void">
</return>
<description>
- Clear the [InputMap] and load it anew from [ProjectSettings].
+ Clears all [InputEventAction] in the [code]InputMap[/code] and load it anew from [ProjectSettings].
</description>
</method>
</methods>
diff --git a/doc/classes/InstancePlaceholder.xml b/doc/classes/InstancePlaceholder.xml
index e962192f81..4105065cb6 100644
--- a/doc/classes/InstancePlaceholder.xml
+++ b/doc/classes/InstancePlaceholder.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="InstancePlaceholder" inherits="Node" category="Core" version="3.0.alpha.custom_build">
+<class name="InstancePlaceholder" inherits="Node" category="Core" version="3.0-alpha">
<brief_description>
Placeholder for the root [Node] of a [PackedScene].
</brief_description>
diff --git a/doc/classes/InterpolatedCamera.xml b/doc/classes/InterpolatedCamera.xml
index 5e5ce59a8b..bd532bec85 100644
--- a/doc/classes/InterpolatedCamera.xml
+++ b/doc/classes/InterpolatedCamera.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="InterpolatedCamera" inherits="Camera" category="Core" version="3.0.alpha.custom_build">
+<class name="InterpolatedCamera" inherits="Camera" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/ItemList.xml b/doc/classes/ItemList.xml
index a8d879888f..950b43417b 100644
--- a/doc/classes/ItemList.xml
+++ b/doc/classes/ItemList.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ItemList" inherits="Control" category="Core" version="3.0.alpha.custom_build">
+<class name="ItemList" inherits="Control" category="Core" version="3.0-alpha">
<brief_description>
Control that provides a list of selectable items (and/or icons) in a single column, or optionally in multiple columns.
</brief_description>
@@ -217,7 +217,7 @@
<argument index="0" name="idx" type="int">
</argument>
<description>
- Returns whether the tooptip is enabled for specified item index.
+ Returns whether the tooltip is enabled for specified item index.
</description>
</method>
<method name="is_same_column_width" qualifiers="const">
@@ -511,7 +511,7 @@
<argument index="1" name="selected" type="bool">
</argument>
<description>
- Fired when a multiple selection is altered on a list allowing mutliple selection.
+ Fired when a multiple selection is altered on a list allowing multiple selection.
</description>
</signal>
</signals>
diff --git a/doc/classes/JSON.xml b/doc/classes/JSON.xml
index 8bff140bb4..e945a580db 100644
--- a/doc/classes/JSON.xml
+++ b/doc/classes/JSON.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="JSON" inherits="Object" category="Core" version="3.0.alpha.custom_build">
+<class name="JSON" inherits="Object" category="Core" version="3.0-alpha">
<brief_description>
Helper class for parsing JSON data.
</brief_description>
diff --git a/doc/classes/JSONParseResult.xml b/doc/classes/JSONParseResult.xml
index 86edaaf1e6..5bf9298f7a 100644
--- a/doc/classes/JSONParseResult.xml
+++ b/doc/classes/JSONParseResult.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="JSONParseResult" inherits="Reference" category="Core" version="3.0.alpha.custom_build">
+<class name="JSONParseResult" inherits="Reference" category="Core" version="3.0-alpha">
<brief_description>
Data class wrapper for decoded JSON.
</brief_description>
<description>
- Returned by [method JSON.parse], [JSONParseResult] contains decoded JSON or error information if JSON source not successfully parsed. You can check if JSON source was successfully parsed with [code]if json_result.error == 0[/code].
+ Returned by [method JSON.parse], [code]JSONParseResult[/code] contains decoded JSON or error information if JSON source not successfully parsed. You can check if JSON source was successfully parsed with [code]if json_result.error == 0[/code].
</description>
<tutorials>
</tutorials>
@@ -70,16 +70,16 @@
</methods>
<members>
<member name="error" type="int" setter="set_error" getter="get_error" enum="Error">
- The error type if JSON source was not successfully parsed. See [@Global Scope]ERR_* constants.
+ The error type if JSON source was not successfully parsed. See [@GlobalScope]ERR_* constants.
</member>
<member name="error_line" type="int" setter="set_error_line" getter="get_error_line">
The line number where the error occurred if JSON source was not successfully parsed.
</member>
<member name="error_string" type="String" setter="set_error_string" getter="get_error_string">
- The error message if JSON source was not successfully parsed. See [@Global Scope]ERR_* constants.
+ The error message if JSON source was not successfully parsed. See [@GlobalScope]ERR_* constants.
</member>
<member name="result" type="Variant" setter="set_result" getter="get_result">
- A [Variant] containing the parsed JSON. Use typeof() to check if it is what you expect. For exemple, if JSON source starts with braces [code]{}[/code] a [Dictionary] will be returned, if JSON source starts with array braces [code][][/code] an [Array] will be returned.
+ A [Variant] containing the parsed JSON. Use typeof() to check if it is what you expect. For example, if JSON source starts with braces [code]{}[/code] a [Dictionary] will be returned, if JSON source starts with array braces [code][][/code] an [Array] will be returned.
[i]Be aware that the JSON specification does not define integer or float types, but only a number type. Therefore, parsing a JSON text will convert all numerical values to float types.[/i]
[codeblock]
p = JSON.parse('["hello", "world", "!"]')
diff --git a/doc/classes/JavaScript.xml b/doc/classes/JavaScript.xml
new file mode 100644
index 0000000000..9dd386f08e
--- /dev/null
+++ b/doc/classes/JavaScript.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="JavaScript" inherits="Object" category="Core" version="3.0-alpha">
+ <brief_description>
+ Singleton that connects the engine with the browser's JavaScript context in HTML5 export.
+ </brief_description>
+ <description>
+ The JavaScript singleton is implemented only in HTML5 export. It's used to access the browser's JavaScript context. This allows interaction with embedding pages or calling third-party JavaScript APIs.
+ </description>
+ <tutorials>
+ http://docs.godotengine.org/en/stable/learning/workflow/export/exporting_for_web.html#calling-javascript-from-script
+ </tutorials>
+ <demos>
+ </demos>
+ <methods>
+ <method name="eval">
+ <return type="Variant">
+ </return>
+ <argument index="0" name="code" type="String">
+ </argument>
+ <argument index="1" name="use_global_execution_context" type="bool" default="false">
+ </argument>
+ <description>
+ Execute the string [code]code[/code] as JavaScript code within the browser window. This is a call to the actual global JavaScript function [code]eval()[/code].
+ If [code]use_global_execution_context[/code] is [code]true[/code], the code will be evaluated in the global execution context. Otherwise, it is evaluated in the execution context of a function within the engine's runtime environment.
+ </description>
+ </method>
+ </methods>
+ <constants>
+ </constants>
+</class>
diff --git a/doc/classes/Joint.xml b/doc/classes/Joint.xml
index 2e7d24aac1..30ece8df1f 100644
--- a/doc/classes/Joint.xml
+++ b/doc/classes/Joint.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Joint" inherits="Spatial" category="Core" version="3.0.alpha.custom_build">
+<class name="Joint" inherits="Spatial" category="Core" version="3.0-alpha">
<brief_description>
+ Base class for all 3D joints
</brief_description>
<description>
+ All 3D joints link two nodes, has a priority, and can decide if the two bodies of the nodes should be able to collide with each other
</description>
<tutorials>
</tutorials>
@@ -68,12 +70,16 @@
</methods>
<members>
<member name="collision/exclude_nodes" type="bool" setter="set_exclude_nodes_from_collision" getter="get_exclude_nodes_from_collision">
+ If [code]true[/code] the two bodies of the nodes are not able to collide with each other.
</member>
<member name="nodes/node_a" type="NodePath" setter="set_node_a" getter="get_node_a">
+ The [Node], the first side of the Joint attaches to.
</member>
<member name="nodes/node_b" type="NodePath" setter="set_node_b" getter="get_node_b">
+ The [Node], the second side of the Joint attaches to.
</member>
<member name="solver/priority" type="int" setter="set_solver_priority" getter="get_solver_priority">
+ The order in wich the solver is executed compared to the other [Joints], the lower, the earlier.
</member>
</members>
<constants>
diff --git a/doc/classes/Joint2D.xml b/doc/classes/Joint2D.xml
index e6c2f6d157..df70a04f10 100644
--- a/doc/classes/Joint2D.xml
+++ b/doc/classes/Joint2D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Joint2D" inherits="Node2D" category="Core" version="3.0.alpha.custom_build">
+<class name="Joint2D" inherits="Node2D" category="Core" version="3.0-alpha">
<brief_description>
Base node for all joint constraints in 2D physics.
</brief_description>
@@ -74,12 +74,16 @@
</methods>
<members>
<member name="bias" type="float" setter="set_bias" getter="get_bias">
+ When [member node_a] and [member node_b] move in different directions the [code]bias[/code] controls how fast the joint pulls them back to their original position. The lower the [code]bias[/code] the more the two bodies can pull on the joint. Default value: [code]0[/code]
</member>
<member name="disable_collision" type="bool" setter="set_exclude_nodes_from_collision" getter="get_exclude_nodes_from_collision">
+ If [code]true[/code] [member node_a] and [member node_b] can collide. Default value: [code]false[/code].
</member>
<member name="node_a" type="NodePath" setter="set_node_a" getter="get_node_a">
+ The first body attached to the joint. Must derive from [PhysicsBody2D].
</member>
<member name="node_b" type="NodePath" setter="set_node_b" getter="get_node_b">
+ The second body attached to the joint. Must derive from [PhysicsBody2D].
</member>
</members>
<constants>
diff --git a/doc/classes/KinematicBody.xml b/doc/classes/KinematicBody.xml
index fb7edd65ad..a423974753 100644
--- a/doc/classes/KinematicBody.xml
+++ b/doc/classes/KinematicBody.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="KinematicBody" inherits="PhysicsBody" category="Core" version="3.0.alpha.custom_build">
+<class name="KinematicBody" inherits="PhysicsBody" category="Core" version="3.0-alpha">
<brief_description>
Kinematic body 3D node.
</brief_description>
@@ -32,7 +32,7 @@
<argument index="0" name="slide_idx" type="int">
</argument>
<description>
- Returns a [KinematicCollision], which contains information about a collision that occured during the last [method move_and_slide] call. Since the body can collide several times in a single call to [method move_and_slide], you must specify the index of the collision in the range 0 to ([method get_slide_count]()-1).
+ Returns a [KinematicCollision], which contains information about a collision that occured during the last [method move_and_slide] call. Since the body can collide several times in a single call to [method move_and_slide], you must specify the index of the collision in the range 0 to ([method get_slide_count] - 1).
</description>
</method>
<method name="get_slide_count" qualifiers="const">
@@ -86,8 +86,8 @@
<argument index="4" name="floor_max_angle" type="float" default="0.785398">
</argument>
<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 a value in pixels per second. Unlike in for example [method move_and_collide], you should [i]not[/i] multiply it with [code]delta[/delta] — this is done by the method.
+ 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 [code]KinematicBody[/code] 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 a value in pixels per second. Unlike in for example [method move_and_collide], you should [i]not[/i] multiply it with [code]delta[/code] — this is done by the method.
[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.
If the body is standing on a slope and the horizontal speed (relative to the floor's speed) goes below [code]slope_stop_min_velocity[/code], the body will stop completely. This prevents the body from sliding down slopes when you include gravity in [code]linear_velocity[/code]. When set to lower values, the body will not be able to stand still on steep slopes.
If the body collides, it will change direction a maximum of [code]max_bounces[/code] times before it stops.
diff --git a/doc/classes/KinematicBody2D.xml b/doc/classes/KinematicBody2D.xml
index d9e669f493..7285c780e5 100644
--- a/doc/classes/KinematicBody2D.xml
+++ b/doc/classes/KinematicBody2D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="KinematicBody2D" inherits="PhysicsBody2D" category="Core" version="3.0.alpha.custom_build">
+<class name="KinematicBody2D" inherits="PhysicsBody2D" category="Core" version="3.0-alpha">
<brief_description>
Kinematic body 2D node.
</brief_description>
@@ -32,7 +32,7 @@
<argument index="0" name="slide_idx" type="int">
</argument>
<description>
- Returns a [KinematicCollision2D], which contains information about a collision that occured during the last [method move_and_slide] call. Since the body can collide several times in a single call to [method move_and_slide], you must specify the index of the collision in the range 0 to ([method get_slide_count]()-1).
+ Returns a [KinematicCollision2D], which contains information about a collision that occured during the last [method move_and_slide] call. Since the body can collide several times in a single call to [method move_and_slide], you must specify the index of the collision in the range 0 to ([method get_slide_count] - 1).
</description>
</method>
<method name="get_slide_count" qualifiers="const">
@@ -86,8 +86,8 @@
<argument index="4" name="floor_max_angle" type="float" default="0.785398">
</argument>
<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 a value in pixels per second. Unlike in for example [method move_and_collide], you should [i]not[/i] multiply it with [code]delta[/delta] — this is done by the method.
+ 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 [code]KinematicBody2D[/code] 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 a value in pixels per second. Unlike in for example [method move_and_collide], you should [i]not[/i] multiply it with [code]delta[/code] — this is done by the method.
[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.
If the body is standing on a slope and the horizontal speed (relative to the floor's speed) goes below [code]slope_stop_min_velocity[/code], the body will stop completely. This prevents the body from sliding down slopes when you include gravity in [code]linear_velocity[/code]. When set to lower values, the body will not be able to stand still on steep slopes.
If the body collides, it will change direction a maximum of [code]max_bounces[/code] times before it stops.
@@ -122,4 +122,4 @@
</members>
<constants>
</constants>
-</class> \ No newline at end of file
+</class>
diff --git a/doc/classes/KinematicCollision.xml b/doc/classes/KinematicCollision.xml
index b7269a646e..ce82004839 100644
--- a/doc/classes/KinematicCollision.xml
+++ b/doc/classes/KinematicCollision.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="KinematicCollision" inherits="Reference" category="Core" version="3.0.alpha.custom_build">
+<class name="KinematicCollision" inherits="Reference" category="Core" version="3.0-alpha">
<brief_description>
Collision data for KinematicBody2D collisions.
</brief_description>
diff --git a/doc/classes/KinematicCollision2D.xml b/doc/classes/KinematicCollision2D.xml
index 7a40a39292..e498dea7a5 100644
--- a/doc/classes/KinematicCollision2D.xml
+++ b/doc/classes/KinematicCollision2D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="KinematicCollision2D" inherits="Reference" category="Core" version="3.0.alpha.custom_build">
+<class name="KinematicCollision2D" inherits="Reference" category="Core" version="3.0-alpha">
<brief_description>
Collision data for KinematicBody2D collisions.
</brief_description>
diff --git a/doc/classes/Label.xml b/doc/classes/Label.xml
index 8c5e69b407..93d7b20491 100644
--- a/doc/classes/Label.xml
+++ b/doc/classes/Label.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Label" inherits="Control" category="Core" version="3.0.alpha.custom_build">
+<class name="Label" inherits="Control" category="Core" version="3.0-alpha">
<brief_description>
Displays plain text in a line or wrapped inside a rectangle. For formatted text, use [RichTextLabel].
</brief_description>
@@ -15,7 +15,7 @@
<return type="int" enum="Label.Align">
</return>
<description>
- Return the alignment mode (any of the ALIGN_* enumeration values).
+ Returns the alignment mode (any of the ALIGN_* enumeration values).
</description>
</method>
<method name="get_line_count" qualifiers="const">
@@ -36,76 +36,77 @@
<return type="int">
</return>
<description>
- Return the the number of lines to skipped before displaying.
+ Returns the the number of lines to skip before displaying.
</description>
</method>
<method name="get_max_lines_visible" qualifiers="const">
<return type="int">
</return>
<description>
- Return the restricted number of lines to display. Returns -1 if unrestricted.
+ Returns the maximum number of lines to display. Returns -1 if unrestricted.
</description>
</method>
<method name="get_percent_visible" qualifiers="const">
<return type="float">
</return>
<description>
- Return the restricted number of characters to display (as a percentage of the total text).
+ Returns the maximum number of characters to display as a percentage of the total text.
</description>
</method>
<method name="get_text" qualifiers="const">
<return type="String">
</return>
<description>
- Return the label text. Text can contain newlines.
+ Returns the label text. Text can contain newlines.
</description>
</method>
<method name="get_total_character_count" qualifiers="const">
<return type="int">
</return>
<description>
- Return the total length of the text.
+ Returns the total length of the text.
</description>
</method>
<method name="get_valign" qualifiers="const">
<return type="int" enum="Label.VAlign">
</return>
<description>
- Return the vertical alignment mode (any of the VALIGN_* enumeration values).
+ Returns the vertical alignment mode (any of the VALIGN_* enumeration values).
</description>
</method>
<method name="get_visible_characters" qualifiers="const">
<return type="int">
</return>
<description>
- Return the restricted number of characters to display. Returns -1 if unrestricted.
+ Returns the restricted number of characters to display. Returns -1 if unrestricted.
</description>
</method>
<method name="get_visible_line_count" qualifiers="const">
<return type="int">
</return>
<description>
+ Returns the number of lines shown. Useful if the [code]Label[/code] 's height cannot currently display all lines.
</description>
</method>
<method name="has_autowrap" qualifiers="const">
<return type="bool">
</return>
<description>
- Return the state of the [i]autowrap[/i] mode (see [method set_autowrap]).
+ Returns [code]true[/code] if [i]autowrap[/i] mode (see [method set_autowrap]).
</description>
</method>
<method name="is_clipping_text" qualifiers="const">
<return type="bool">
</return>
<description>
- Return [code]true[/code] if text would be cut off if it is too wide.
+ Returns [code]true[/code] if text would be cut off if it is too wide.
</description>
</method>
<method name="is_uppercase" qualifiers="const">
<return type="bool">
</return>
<description>
- Return [code]true[/code] if text is displayed in all capitals.
+ Returns [code]true[/code] if text is displayed in all capitals.
</description>
</method>
<method name="set_align">
diff --git a/doc/classes/LargeTexture.xml b/doc/classes/LargeTexture.xml
index e4cabdc556..6ec3c80bca 100644
--- a/doc/classes/LargeTexture.xml
+++ b/doc/classes/LargeTexture.xml
@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="LargeTexture" inherits="Texture" category="Core" version="3.0.alpha.custom_build">
+<class name="LargeTexture" inherits="Texture" category="Core" version="3.0-alpha">
<brief_description>
A Texture capable of storing many smaller Textures with offsets.
</brief_description>
<description>
A Texture capable of storing many smaller Textures with offsets.
- You can dynamically add pieces(Textures) to this fLargeTexture] using different offsets.
+ You can dynamically add pieces([Texture]) to this [code]LargeTexture[/code] using different offsets.
</description>
<tutorials>
</tutorials>
@@ -20,21 +20,21 @@
<argument index="1" name="texture" type="Texture">
</argument>
<description>
- Add another [Texture] to this [LargeTexture], starting on offset "ofs".
+ Add another [Texture] to this [code]LargeTexture[/code], starting on offset "ofs".
</description>
</method>
<method name="clear">
<return type="void">
</return>
<description>
- Clear the [LargeTexture].
+ Clears the [code]LargeTexture[/code].
</description>
</method>
<method name="get_piece_count" qualifiers="const">
<return type="int">
</return>
<description>
- Return the number of pieces currently in this [LargeTexture].
+ Returns the number of pieces currently in this [code]LargeTexture[/code].
</description>
</method>
<method name="get_piece_offset" qualifiers="const">
@@ -43,7 +43,7 @@
<argument index="0" name="idx" type="int">
</argument>
<description>
- Return the offset of the piece with index "idx".
+ Returns the offset of the piece with index "idx".
</description>
</method>
<method name="get_piece_texture" qualifiers="const">
@@ -52,7 +52,7 @@
<argument index="0" name="idx" type="int">
</argument>
<description>
- Return the [Texture] of the piece with index "idx".
+ Returns the [Texture] of the piece with index "idx".
</description>
</method>
<method name="set_piece_offset">
@@ -63,7 +63,7 @@
<argument index="1" name="ofs" type="Vector2">
</argument>
<description>
- Set the offset of the piece with index "idx" to "ofs".
+ Sets the offset of the piece with index "idx" to "ofs".
</description>
</method>
<method name="set_piece_texture">
@@ -74,7 +74,7 @@
<argument index="1" name="texture" type="Texture">
</argument>
<description>
- Set the [Texture] of the piece with index "idx" to "ofs".
+ Sets the [Texture] of the piece with index "idx" to "ofs".
</description>
</method>
<method name="set_size">
@@ -83,12 +83,16 @@
<argument index="0" name="size" type="Vector2">
</argument>
<description>
- Set the size of this [LargeTexture].
+ Sets the size of this [code]LargeTexture[/code].
</description>
</method>
</methods>
<members>
<member name="_data" type="Array" setter="_set_data" getter="_get_data">
+ Returns an [Array] with offsets and textures data of each added piece. Schema is [offsets1, texture1, offsets2, texture2, large_texture_size].
+ [code]offsets[/code] : [Vector2] offsets of the texture piece.
+ [code]second[/code] : [StreamTexture] data of the texture piece.
+ [code]last entry[/code] : [Vector2] size of the entire large texture.
</member>
</members>
<constants>
diff --git a/doc/classes/Light.xml b/doc/classes/Light.xml
index 11eee135cb..1c625d59e1 100644
--- a/doc/classes/Light.xml
+++ b/doc/classes/Light.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Light" inherits="VisualInstance" category="Core" version="3.0.alpha.custom_build">
+<class name="Light" inherits="VisualInstance" category="Core" version="3.0-alpha">
<brief_description>
Provides a base class for different kinds of light nodes.
</brief_description>
@@ -179,6 +179,8 @@
</constant>
<constant name="PARAM_SHADOW_BIAS" value="12">
</constant>
+ <constant name="PARAM_SHADOW_BIAS_SPLIT_SCALE" value="13">
+ </constant>
<constant name="PARAM_MAX" value="14">
</constant>
</constants>
diff --git a/doc/classes/Light2D.xml b/doc/classes/Light2D.xml
index 7ce7cef7c1..285d302ba7 100644
--- a/doc/classes/Light2D.xml
+++ b/doc/classes/Light2D.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Light2D" inherits="Node2D" category="Core" version="3.0.alpha.custom_build">
+<class name="Light2D" inherits="Node2D" category="Core" version="3.0-alpha">
<brief_description>
- Node that casts light in a 2D environment.
+ Casts light in a 2D environment.
</brief_description>
<description>
- Node that casts light in a 2D environment. Light is defined by a (usually grayscale) texture, a color, an energy value, a mode (see constants), and various other parameters (range and shadows-related). Note that Light2D can be used as a mask.
+ Casts light in a 2D environment. Light is defined by a (usually grayscale) texture, a color, an energy value, a mode (see constants), and various other parameters (range and shadows-related). Note that Light2D can be used as a mask.
</description>
<tutorials>
</tutorials>
@@ -385,7 +385,7 @@
If [code]true[/code] the Light2D will cast shadows. Default value: [code]false[/code].
</member>
<member name="shadow_filter" type="int" setter="set_shadow_filter" getter="get_shadow_filter" enum="Light2D.ShadowFilter">
- Shadow filter type. May be one of [code][None, PCF5, PCF9, PCF13][/code]. Default value: [code]None[/code].
+ Shadow filter type. Use SHADOW_FILTER_* constants to set [code]shadow_filter[/code]. Default value: [code]None[/code].
</member>
<member name="shadow_filter_smooth" type="float" setter="set_shadow_smooth" getter="get_shadow_smooth">
Smoothing value for shadows.
@@ -408,7 +408,7 @@
Adds the value of pixels corresponding to the Light2D to the values of pixels under it. This is the common behaviour of a light.
</constant>
<constant name="MODE_SUB" value="1">
- Subtract the value of pixels corresponding to the Light2D to the values of pixels under it, resulting in inversed light effect.
+ Subtracts the value of pixels corresponding to the Light2D to the values of pixels under it, resulting in inversed light effect.
</constant>
<constant name="MODE_MIX" value="2">
Mix the value of pixels corresponding to the Light2D to the values of pixels under it by linear interpolation.
@@ -417,16 +417,22 @@
The light texture of the Light2D is used as a mask, hiding or revealing parts of the screen underneath depending on the value of each pixel of the light (mask) texture.
</constant>
<constant name="SHADOW_FILTER_NONE" value="0">
+ No filter applies to the shadow map. See [method shadow_filter].
</constant>
<constant name="SHADOW_FILTER_PCF3" value="1">
+ Percentage closer filtering (3 samples) applies to the shadow map. See [method shadow_filter].
</constant>
<constant name="SHADOW_FILTER_PCF5" value="2">
+ Percentage closer filtering (5 samples) applies to the shadow map. See [method shadow_filter].
</constant>
<constant name="SHADOW_FILTER_PCF7" value="3">
+ Percentage closer filtering (7 samples) applies to the shadow map. See [method shadow_filter].
</constant>
<constant name="SHADOW_FILTER_PCF9" value="4">
+ Percentage closer filtering (9 samples) applies to the shadow map. See [method shadow_filter].
</constant>
<constant name="SHADOW_FILTER_PCF13" value="5">
+ Percentage closer filtering (13 samples) applies to the shadow map. See [method shadow_filter].
</constant>
</constants>
</class>
diff --git a/doc/classes/LightOccluder2D.xml b/doc/classes/LightOccluder2D.xml
index babcf31c08..9a1b84158b 100644
--- a/doc/classes/LightOccluder2D.xml
+++ b/doc/classes/LightOccluder2D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="LightOccluder2D" inherits="Node2D" category="Core" version="3.0.alpha.custom_build">
+<class name="LightOccluder2D" inherits="Node2D" category="Core" version="3.0-alpha">
<brief_description>
Occludes light cast by a Light2D, casting shadows.
</brief_description>
diff --git a/doc/classes/Line2D.xml b/doc/classes/Line2D.xml
index e6e615ccf1..7b76d94c95 100644
--- a/doc/classes/Line2D.xml
+++ b/doc/classes/Line2D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Line2D" inherits="Node2D" category="Core" version="3.0.alpha.custom_build">
+<class name="Line2D" inherits="Node2D" category="Core" version="3.0-alpha">
<brief_description>
A 2D line.
</brief_description>
@@ -17,7 +17,7 @@
<argument index="0" name="position" type="Vector2">
</argument>
<description>
- Add a point at the x/y position in the supplied [Vector2]
+ Add a point at the [code]position[/code]. Appends the point at the end of the line.
</description>
</method>
<method name="get_begin_cap_mode" qualifiers="const">
@@ -54,6 +54,7 @@
<return type="int">
</return>
<description>
+ Returns the Line2D's amount of points.
</description>
</method>
<method name="get_point_position" qualifiers="const">
@@ -62,6 +63,7 @@
<argument index="0" name="i" type="int">
</argument>
<description>
+ Returns point [code]i[/code]'s position.
</description>
</method>
<method name="get_points" qualifiers="const">
@@ -106,7 +108,7 @@
<argument index="0" name="i" type="int">
</argument>
<description>
- Remove the point at index 'i' from the line.
+ Remove the point at index [code]i[/code] from the line.
</description>
</method>
<method name="set_begin_cap_mode">
@@ -157,6 +159,7 @@
<argument index="1" name="position" type="Vector2">
</argument>
<description>
+ Overwites the position in point [code]i[/code] with the supplied [code]position[/code].
</description>
</method>
<method name="set_points">
@@ -210,44 +213,63 @@
</methods>
<members>
<member name="begin_cap_mode" type="int" setter="set_begin_cap_mode" getter="get_begin_cap_mode" enum="Line2D.LineCapMode">
+ Controls the style of the line's first point. Use [code]LINE_CAP_*[/code] constants. Default value: [code]LINE_CAP_NONE[/code].
</member>
<member name="default_color" type="Color" setter="set_default_color" getter="get_default_color">
+ The line's color. Will not be used if a gradient is set.
</member>
<member name="end_cap_mode" type="int" setter="set_end_cap_mode" getter="get_end_cap_mode" enum="Line2D.LineCapMode">
+ Controls the style of the line's last point. Use [code]LINE_CAP_*[/code] constants. Default value: [code]LINE_CAP_NONE[/code].
</member>
<member name="gradient" type="Gradient" setter="set_gradient" getter="get_gradient">
+ The gradient is drawn through the whole line from start to finish. The default color will not be used if a gradient is set.
</member>
<member name="joint_mode" type="int" setter="set_joint_mode" getter="get_joint_mode" enum="Line2D.LineJointMode">
+ The style for the points inbetween the start and the end.
</member>
<member name="points" type="PoolVector2Array" setter="set_points" getter="get_points">
+ The points that form the lines. The line is drawn between every point set in this array.
</member>
<member name="round_precision" type="int" setter="set_round_precision" getter="get_round_precision">
+ The smoothness of the rounded joints and caps. This is only used if a cap or joint is set as round.
</member>
<member name="sharp_limit" type="float" setter="set_sharp_limit" getter="get_sharp_limit">
+ The direction difference in radians between vector points. This value is only used if [code]joint mode[/code] is set to [code]LINE_JOINT_SHARP[/code].
</member>
<member name="texture" type="Texture" setter="set_texture" getter="get_texture">
+ The texture used for the line's texture. Uses [code]texture_mode[/code] for drawing style.
</member>
<member name="texture_mode" type="int" setter="set_texture_mode" getter="get_texture_mode" enum="Line2D.LineTextureMode">
+ The style to render the [code]texture[/code] on the line. Use [code]LINE_TEXTURE_*[/code] constants. Default value: [code]LINE_TEXTURE_NONE[/code].
</member>
<member name="width" type="float" setter="set_width" getter="get_width">
+ The line's width.
</member>
</members>
<constants>
<constant name="LINE_JOINT_SHARP" value="0">
+ The line's joints will be pointy. If [code]sharp_limit[/code] is greater than the rotation of a joint, it becomes a bevel joint instead.
</constant>
<constant name="LINE_JOINT_BEVEL" value="1">
+ The line's joints will be bevelled/chamfered.
</constant>
<constant name="LINE_JOINT_ROUND" value="2">
+ The line's joints will be rounded.
</constant>
<constant name="LINE_CAP_NONE" value="0">
+ Don't have a line cap.
</constant>
<constant name="LINE_CAP_BOX" value="1">
+ Draws the line cap as a box.
</constant>
<constant name="LINE_CAP_ROUND" value="2">
+ Draws the line cap as a circle.
</constant>
<constant name="LINE_TEXTURE_NONE" value="0">
+ Takes the left pixels of the texture and renders it over the whole line.
</constant>
<constant name="LINE_TEXTURE_TILE" value="1">
+ Tiles the texture over the line. The texture need to be imported with Repeat Enabled for it to work properly.
</constant>
</constants>
</class>
diff --git a/doc/classes/LineEdit.xml b/doc/classes/LineEdit.xml
index e6c26e3248..432f583566 100644
--- a/doc/classes/LineEdit.xml
+++ b/doc/classes/LineEdit.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="LineEdit" inherits="Control" category="Core" version="3.0.alpha.custom_build">
+<class name="LineEdit" inherits="Control" category="Core" version="3.0-alpha">
<brief_description>
Control that provides single line string editing.
</brief_description>
@@ -17,14 +17,14 @@
<argument index="0" name="text" type="String">
</argument>
<description>
- Append text at cursor, scrolling the [LineEdit] when needed.
+ Adds [code]text[/code] after the cursor. If the resulting value is longer than [member max_length], nothing happens.
</description>
</method>
<method name="clear">
<return type="void">
</return>
<description>
- Clear the [LineEdit] text.
+ Erases the [LineEdit] text.
</description>
</method>
<method name="cursor_get_blink_enabled" qualifiers="const">
@@ -63,14 +63,14 @@
<return type="int" enum="LineEdit.Align">
</return>
<description>
- Return the align mode of the [LineEdit].
+ Return the align mode of the [code]LineEdit[/code].
</description>
</method>
<method name="get_cursor_position" qualifiers="const">
<return type="int">
</return>
<description>
- Return the cursor position inside the [LineEdit].
+ Returns the cursor position inside the [code]LineEdit[/code].
</description>
</method>
<method name="get_expand_to_text_length" qualifiers="const">
@@ -83,14 +83,14 @@
<return type="int">
</return>
<description>
- Return the maximum amount of characters the [LineEdit] can edit. If 0 is returned, no limit exists.
+ Return the maximum amount of characters the [code]LineEdit[/code] can edit. If 0 is returned, no limit exists.
</description>
</method>
<method name="get_menu" qualifiers="const">
<return type="PopupMenu">
</return>
<description>
- Return the [PopupMenu] of this [LineEdit].
+ Returns the [PopupMenu] of this [code]LineEdit[/code]. By default, this menu is displayed when right-clicking on the [LineEdit].
</description>
</method>
<method name="get_placeholder" qualifiers="const">
@@ -111,21 +111,28 @@
<return type="String">
</return>
<description>
- Return the text in the [LineEdit].
+ Return the text in the [code]LineEdit[/code].
+ </description>
+ </method>
+ <method name="is_context_menu_enabled">
+ <return type="bool">
+ </return>
+ <description>
+ Returns true if the context menu is enabled.
</description>
</method>
<method name="is_editable" qualifiers="const">
<return type="bool">
</return>
<description>
- Return the [i]editable[/i] status of the [LineEdit] (see [method set_editable]).
+ Return the [i]editable[/i] status of the [code]LineEdit[/code] (see [method set_editable]).
</description>
</method>
<method name="is_secret" qualifiers="const">
<return type="bool">
</return>
<description>
- Return the [i]secret[/i] status of the [LineEdit] (see [method set_secret]).
+ Return the [i]secret[/i] status of the [code]LineEdit[/code] (see [method set_secret]).
</description>
</method>
<method name="menu_option">
@@ -134,7 +141,7 @@
<argument index="0" name="option" type="int">
</argument>
<description>
- Execute a given action as defined in the MENU_* enum.
+ Executes a given action as defined in the MENU_* enum.
</description>
</method>
<method name="select">
@@ -145,11 +152,12 @@
<argument index="1" name="to" type="int" default="-1">
</argument>
<description>
- Select the text inside [LineEdit] by the given character positions. [code]from[/code] is default to the beginning. [code]to[/code] is default to the end.
+ Selects characters inside [LineEdit] between [code]from[/code] and [code]to[/code]. By default [code]from[/code] is at the beginning and [code]to[/code] at the end.
[codeblock]
- select() # select all
- select(5) # select from the fifth character to the end.
- select(2, 5) # select from the second to the fifth character.
+ text = "Welcome"
+ select() # Welcome
+ select(4) # ome
+ select(2, 5) # lco
[/codeblock]
</description>
</method>
@@ -157,7 +165,7 @@
<return type="void">
</return>
<description>
- Select the whole string.
+ Selects the whole [String].
</description>
</method>
<method name="set_align">
@@ -166,7 +174,16 @@
<argument index="0" name="align" type="int" enum="LineEdit.Align">
</argument>
<description>
- Set text alignment of the [LineEdit].
+ Set text alignment of the [code]LineEdit[/code].
+ </description>
+ </method>
+ <method name="set_context_menu_enabled">
+ <return type="void">
+ </return>
+ <argument index="0" name="enable" type="bool">
+ </argument>
+ <description>
+ Set the status of the context menu. When enabled, the context menu will appear when the [code]LineEdit[/code] is right clicked.
</description>
</method>
<method name="set_cursor_position">
@@ -175,7 +192,7 @@
<argument index="0" name="position" type="int">
</argument>
<description>
- Set the cursor position inside the [LineEdit], causing it to scroll if needed.
+ Sets the cursor position inside the [code]LineEdit[/code]. The text may scroll if needed.
</description>
</method>
<method name="set_editable">
@@ -184,7 +201,7 @@
<argument index="0" name="enabled" type="bool">
</argument>
<description>
- Set the [i]editable[/i] status of the [LineEdit]. When disabled, existing text can't be modified and new text can't be added.
+ Set the [i]editable[/i] status of the [code]LineEdit[/code]. When disabled, existing text can't be modified and new text can't be added.
</description>
</method>
<method name="set_expand_to_text_length">
@@ -201,7 +218,7 @@
<argument index="0" name="chars" type="int">
</argument>
<description>
- Set the maximum amount of characters the [LineEdit] can edit, and cropping existing text in case it exceeds that limit. Setting 0 removes the limit.
+ Set the maximum amount of characters the [code]LineEdit[/code] can edit, and cropping existing text in case it exceeds that limit. Setting 0 removes the limit.
</description>
</method>
<method name="set_placeholder">
@@ -228,7 +245,7 @@
<argument index="0" name="enabled" type="bool">
</argument>
<description>
- Set the [i]secret[/i] status of the [LineEdit]. When enabled, every character is displayed as "*".
+ Set the [i]secret[/i] status of the [code]LineEdit[/code]. When enabled, every character is displayed as "*".
</description>
</method>
<method name="set_text">
@@ -237,32 +254,46 @@
<argument index="0" name="text" type="String">
</argument>
<description>
- Set the text in the [LineEdit], clearing the existing one and the selection.
+ Set the text in the [code]LineEdit[/code], clearing the existing one and the selection.
</description>
</method>
</methods>
<members>
<member name="align" type="int" setter="set_align" getter="get_align" enum="LineEdit.Align">
+ Text alignment as defined in the ALIGN_* enum.
</member>
<member name="caret_blink" type="bool" setter="cursor_set_blink_enabled" getter="cursor_get_blink_enabled">
+ If [code]true[/code] the caret (visual cursor) blinks.
</member>
<member name="caret_blink_speed" type="float" setter="cursor_set_blink_speed" getter="cursor_get_blink_speed">
+ Duration (in seconds) of a caret's blinking cycle.
+ </member>
+ <member name="context_menu_enabled" type="bool" setter="set_context_menu_enabled" getter="is_context_menu_enabled">
+ If [code]true[/code] the context menu will appear when right clicked.
</member>
<member name="editable" type="bool" setter="set_editable" getter="is_editable">
+ If [code]false[/code] existing text cannot be modified and new text cannot be added.
</member>
<member name="expand_to_len" type="bool" setter="set_expand_to_text_length" getter="get_expand_to_text_length">
+ If [code]true[/code] the [LineEdit] width will increase to stay longer than the [member text]. It will [b]not[/b] compress if the [member text] is shortened.
</member>
<member name="focus_mode" type="int" setter="set_focus_mode" getter="get_focus_mode" enum="Control.FocusMode">
+ Defines how the [LineEdit] can grab focus (Keyboard and mouse, only keyboard, or none). See [code]enum FocusMode[/code] in [Control] for details.
</member>
<member name="max_length" type="int" setter="set_max_length" getter="get_max_length">
+ Maximum amount of characters that can be entered inside the [LineEdit]. If [code]0[/code], there is no limit.
</member>
<member name="placeholder_alpha" type="float" setter="set_placeholder_alpha" getter="get_placeholder_alpha">
+ Opacity of the [member placeholder_text]. From [code]0[/code] to [code]1[/code].
</member>
<member name="placeholder_text" type="String" setter="set_placeholder" getter="get_placeholder">
+ Text shown when the [LineEdit] is empty. It is [b]not[/b] the [LineEdit]'s default value (see [member text]).
</member>
<member name="secret" type="bool" setter="set_secret" getter="is_secret">
+ If [code]true[/code] every character is shown as "*".
</member>
<member name="text" type="String" setter="set_text" getter="get_text">
+ String value of the [LineEdit].
</member>
</members>
<signals>
@@ -270,49 +301,51 @@
<argument index="0" name="text" type="String">
</argument>
<description>
- When the text changes, this signal is emitted.
+ Emitted when the text changes.
</description>
</signal>
<signal name="text_entered">
<argument index="0" name="text" type="String">
</argument>
<description>
- This signal is emitted when the user presses KEY_ENTER on the [LineEdit]. This signal is often used as an alternate confirmation mechanism in dialogs.
+ Emitted when the user presses KEY_ENTER on the [code]LineEdit[/code].
</description>
</signal>
</signals>
<constants>
<constant name="ALIGN_LEFT" value="0">
- Align left.
+ Aligns the text on the left hand side of the [LineEdit].
</constant>
<constant name="ALIGN_CENTER" value="1">
- Align center.
+ Centers the text in the middle of the [LineEdit].
</constant>
<constant name="ALIGN_RIGHT" value="2">
- Align right.
+ Aligns the text on the right hand side of the [LineEdit].
</constant>
<constant name="ALIGN_FILL" value="3">
- Align fill.
+ Stretches whitespaces to fit the [LineEdit]'s width.
</constant>
<constant name="MENU_CUT" value="0">
- Cut (Copy and clear).
+ Cuts (Copies and clears) the selected text.
</constant>
<constant name="MENU_COPY" value="1">
- Copy the selected text.
+ Copies the selected text.
</constant>
<constant name="MENU_PASTE" value="2">
- Paste the clipboard text over the selected text.
+ Pastes the clipboard text over the selected text (or at the cursor's position).
</constant>
<constant name="MENU_CLEAR" value="3">
- Clear the text.
+ Erases the whole [Linedit] text.
</constant>
<constant name="MENU_SELECT_ALL" value="4">
- Select all text.
+ Selects the whole [Linedit] text.
</constant>
<constant name="MENU_UNDO" value="5">
- Undo an action.
+ Undoes the previous action.
+ </constant>
+ <constant name="MENU_REDO" value="6">
</constant>
- <constant name="MENU_MAX" value="6">
+ <constant name="MENU_MAX" value="7">
</constant>
</constants>
<theme_items>
diff --git a/doc/classes/LineShape2D.xml b/doc/classes/LineShape2D.xml
index 5596c48162..6ae6fad6f4 100644
--- a/doc/classes/LineShape2D.xml
+++ b/doc/classes/LineShape2D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="LineShape2D" inherits="Shape2D" category="Core" version="3.0.alpha.custom_build">
+<class name="LineShape2D" inherits="Shape2D" category="Core" version="3.0-alpha">
<brief_description>
Line shape for 2D collisions.
</brief_description>
diff --git a/doc/classes/LinkButton.xml b/doc/classes/LinkButton.xml
index d9598daf16..d13a0d7be6 100644
--- a/doc/classes/LinkButton.xml
+++ b/doc/classes/LinkButton.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="LinkButton" inherits="BaseButton" category="Core" version="3.0.alpha.custom_build">
+<class name="LinkButton" inherits="BaseButton" category="Core" version="3.0-alpha">
<brief_description>
Simple button used to represent a link to some resource
</brief_description>
@@ -40,7 +40,7 @@
<argument index="0" name="underline_mode" type="int" enum="LinkButton.UnderlineMode">
</argument>
<description>
- Sets the underline mode for this button, the argument must be one of the [LinkButton] constants (see constants section).
+ Sets the underline mode for this button, the argument must be one of the [code]LinkButton[/code] constants (see constants section).
</description>
</method>
</methods>
diff --git a/doc/classes/Listener.xml b/doc/classes/Listener.xml
index 176369cccb..742198acd0 100644
--- a/doc/classes/Listener.xml
+++ b/doc/classes/Listener.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Listener" inherits="Spatial" category="Core" version="3.0.alpha.custom_build">
+<class name="Listener" inherits="Spatial" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/MainLoop.xml b/doc/classes/MainLoop.xml
index e6f9e40dfe..048b13a7ca 100644
--- a/doc/classes/MainLoop.xml
+++ b/doc/classes/MainLoop.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="MainLoop" inherits="Object" category="Core" version="3.0.alpha.custom_build">
+<class name="MainLoop" inherits="Object" category="Core" version="3.0-alpha">
<brief_description>
Main loop is the abstract main loop base class.
</brief_description>
<description>
- Main loop is the abstract main loop base class. All other main loop classes are derived from it. Upon application start, a [MainLoop] has to be provided to OS, else the application will exit. This happens automatically (and a [SceneTree] is created), unless a main [Script] is supplied, which may or not create and return a [MainLoop].
+ Main loop is the abstract main loop base class. All other main loop classes are derived from it. Upon application start, a [code]MainLoop[/code] has to be provided to OS, else the application will exit. This happens automatically (and a [SceneTree] is created), unless a main [Script] is supplied, which may or not create and return a [code]MainLoop[/code].
</description>
<tutorials>
</tutorials>
@@ -124,6 +124,8 @@
</constant>
<constant name="NOTIFICATION_WM_QUIT_REQUEST" value="6" enum="">
</constant>
+ <constant name="NOTIFICATION_WM_GO_BACK_REQUEST" value="7" enum="">
+ </constant>
<constant name="NOTIFICATION_WM_UNFOCUS_REQUEST" value="8" enum="">
</constant>
<constant name="NOTIFICATION_OS_MEMORY_WARNING" value="9" enum="">
diff --git a/doc/classes/MarginContainer.xml b/doc/classes/MarginContainer.xml
index d4b9b01f63..1c748de229 100644
--- a/doc/classes/MarginContainer.xml
+++ b/doc/classes/MarginContainer.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="MarginContainer" inherits="Container" category="Core" version="3.0.alpha.custom_build">
+<class name="MarginContainer" inherits="Container" category="Core" version="3.0-alpha">
<brief_description>
Simple margin container.
</brief_description>
diff --git a/doc/classes/Marshalls.xml b/doc/classes/Marshalls.xml
index b443d03108..0e561ab374 100644
--- a/doc/classes/Marshalls.xml
+++ b/doc/classes/Marshalls.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Marshalls" inherits="Reference" category="Core" version="3.0.alpha.custom_build">
+<class name="Marshalls" inherits="Reference" category="Core" version="3.0-alpha">
<brief_description>
Data transformation (marshalling) and encoding helpers.
</brief_description>
diff --git a/doc/classes/Material.xml b/doc/classes/Material.xml
index 88b35ac6b5..87c2e51003 100644
--- a/doc/classes/Material.xml
+++ b/doc/classes/Material.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Material" inherits="Resource" category="Core" version="3.0.alpha.custom_build">
+<class name="Material" inherits="Resource" category="Core" version="3.0-alpha">
<brief_description>
Abstract base [Resource] for coloring and shading geometry.
</brief_description>
diff --git a/doc/classes/MenuButton.xml b/doc/classes/MenuButton.xml
index f1ab74d00e..54be44d3d8 100644
--- a/doc/classes/MenuButton.xml
+++ b/doc/classes/MenuButton.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="MenuButton" inherits="Button" category="Core" version="3.0.alpha.custom_build">
+<class name="MenuButton" inherits="Button" category="Core" version="3.0-alpha">
<brief_description>
Special button that brings up a [PopupMenu] when clicked.
</brief_description>
diff --git a/doc/classes/Mesh.xml b/doc/classes/Mesh.xml
index 658265d242..733f76728c 100644
--- a/doc/classes/Mesh.xml
+++ b/doc/classes/Mesh.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Mesh" inherits="Resource" category="Core" version="3.0.alpha.custom_build">
+<class name="Mesh" inherits="Resource" category="Core" version="3.0-alpha">
<brief_description>
A [Resource] that contains vertex-array based geometry.
</brief_description>
diff --git a/doc/classes/MeshDataTool.xml b/doc/classes/MeshDataTool.xml
index 6088d30013..f433d7a753 100644
--- a/doc/classes/MeshDataTool.xml
+++ b/doc/classes/MeshDataTool.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="MeshDataTool" inherits="Reference" category="Core" version="3.0.alpha.custom_build">
+<class name="MeshDataTool" inherits="Reference" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/MeshInstance.xml b/doc/classes/MeshInstance.xml
index 56b446cac1..5bd6bedf7e 100644
--- a/doc/classes/MeshInstance.xml
+++ b/doc/classes/MeshInstance.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="MeshInstance" inherits="GeometryInstance" category="Core" version="3.0.alpha.custom_build">
+<class name="MeshInstance" inherits="GeometryInstance" category="Core" version="3.0-alpha">
<brief_description>
Node that instances meshes into a scenario.
</brief_description>
diff --git a/doc/classes/MeshLibrary.xml b/doc/classes/MeshLibrary.xml
index 5636db23b5..54a8228d02 100644
--- a/doc/classes/MeshLibrary.xml
+++ b/doc/classes/MeshLibrary.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="MeshLibrary" inherits="Resource" category="Core" version="3.0.alpha.custom_build">
+<class name="MeshLibrary" inherits="Resource" category="Core" version="3.0-alpha">
<brief_description>
Library of meshes.
</brief_description>
diff --git a/doc/classes/MultiMesh.xml b/doc/classes/MultiMesh.xml
index 6df9689ada..b6a89d09f4 100644
--- a/doc/classes/MultiMesh.xml
+++ b/doc/classes/MultiMesh.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="MultiMesh" inherits="Resource" category="Core" version="3.0.alpha.custom_build">
+<class name="MultiMesh" inherits="Resource" category="Core" version="3.0-alpha">
<brief_description>
Provides high performance mesh instancing.
</brief_description>
@@ -7,7 +7,7 @@
MultiMesh provides low level mesh instancing. If the amount of [Mesh] instances needed goes from hundreds to thousands (and most need to be visible at close proximity) creating such a large amount of [MeshInstance] nodes may affect performance by using too much CPU or video memory.
For this case a MultiMesh becomes very useful, as it can draw thousands of instances with little API overhead.
As a drawback, if the instances are too far away of each other, performance may be reduced as every single instance will always rendered (they are spatially indexed as one, for the whole object).
- Since instances may have any behavior, the Rect3 used for visibility must be provided by the user.
+ Since instances may have any behavior, the AABB used for visibility must be provided by the user.
</description>
<tutorials>
</tutorials>
@@ -15,10 +15,10 @@
</demos>
<methods>
<method name="get_aabb" qualifiers="const">
- <return type="Rect3">
+ <return type="AABB">
</return>
<description>
- Return the visibility Rect3.
+ Return the visibility AABB.
</description>
</method>
<method name="get_color_format" qualifiers="const">
diff --git a/doc/classes/MultiMeshInstance.xml b/doc/classes/MultiMeshInstance.xml
index 06454e3cdc..11e22c2581 100644
--- a/doc/classes/MultiMeshInstance.xml
+++ b/doc/classes/MultiMeshInstance.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="MultiMeshInstance" inherits="GeometryInstance" category="Core" version="3.0.alpha.custom_build">
+<class name="MultiMeshInstance" inherits="GeometryInstance" category="Core" version="3.0-alpha">
<brief_description>
Node that instances a [MultiMesh].
</brief_description>
diff --git a/doc/classes/Mutex.xml b/doc/classes/Mutex.xml
index ef3aeb9e07..d36dbb64c1 100644
--- a/doc/classes/Mutex.xml
+++ b/doc/classes/Mutex.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Mutex" inherits="Reference" category="Core" version="3.0.alpha.custom_build">
+<class name="Mutex" inherits="Reference" category="Core" version="3.0-alpha">
<brief_description>
A synchronization Mutex.
</brief_description>
@@ -15,21 +15,21 @@
<return type="void">
</return>
<description>
- Lock this [Mutex], blocks until it is unlocked by the current owner.
+ Lock this [code]Mutex[/code], blocks until it is unlocked by the current owner.
</description>
</method>
<method name="try_lock">
<return type="int" enum="Error">
</return>
<description>
- Try locking this [Mutex], does not block. Returns [OK] on success else [ERR_BUSY].
+ Try locking this [code]Mutex[/code], does not block. Returns [OK] on success else [ERR_BUSY].
</description>
</method>
<method name="unlock">
<return type="void">
</return>
<description>
- Unlock this [Mutex], leaving it to others threads.
+ Unlock this [code]Mutex[/code], leaving it to others threads.
</description>
</method>
</methods>
diff --git a/doc/classes/Navigation.xml b/doc/classes/Navigation.xml
index 3e063f6a82..c83e81b197 100644
--- a/doc/classes/Navigation.xml
+++ b/doc/classes/Navigation.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Navigation" inherits="Spatial" category="Core" version="3.0.alpha.custom_build">
+<class name="Navigation" inherits="Spatial" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/Navigation2D.xml b/doc/classes/Navigation2D.xml
index ab10463a5d..ac2e0d88d8 100644
--- a/doc/classes/Navigation2D.xml
+++ b/doc/classes/Navigation2D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Navigation2D" inherits="Node2D" category="Core" version="3.0.alpha.custom_build">
+<class name="Navigation2D" inherits="Node2D" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/NavigationMesh.xml b/doc/classes/NavigationMesh.xml
index 788fadfd77..dd49b0a593 100644
--- a/doc/classes/NavigationMesh.xml
+++ b/doc/classes/NavigationMesh.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="NavigationMesh" inherits="Resource" category="Core" version="3.0.alpha.custom_build">
+<class name="NavigationMesh" inherits="Resource" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/NavigationMeshInstance.xml b/doc/classes/NavigationMeshInstance.xml
index 6d3a81a939..1e8998009e 100644
--- a/doc/classes/NavigationMeshInstance.xml
+++ b/doc/classes/NavigationMeshInstance.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="NavigationMeshInstance" inherits="Spatial" category="Core" version="3.0.alpha.custom_build">
+<class name="NavigationMeshInstance" inherits="Spatial" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/NavigationPolygon.xml b/doc/classes/NavigationPolygon.xml
index 07eb4afb8d..fd7238114e 100644
--- a/doc/classes/NavigationPolygon.xml
+++ b/doc/classes/NavigationPolygon.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="NavigationPolygon" inherits="Resource" category="Core" version="3.0.alpha.custom_build">
+<class name="NavigationPolygon" inherits="Resource" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/NavigationPolygonInstance.xml b/doc/classes/NavigationPolygonInstance.xml
index a6d70d5b4b..ac56b03002 100644
--- a/doc/classes/NavigationPolygonInstance.xml
+++ b/doc/classes/NavigationPolygonInstance.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="NavigationPolygonInstance" inherits="Node2D" category="Core" version="3.0.alpha.custom_build">
+<class name="NavigationPolygonInstance" inherits="Node2D" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/NetworkedMultiplayerPeer.xml b/doc/classes/NetworkedMultiplayerPeer.xml
index c1d8c5ad91..4333c3d28a 100644
--- a/doc/classes/NetworkedMultiplayerPeer.xml
+++ b/doc/classes/NetworkedMultiplayerPeer.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="NetworkedMultiplayerPeer" inherits="PacketPeer" category="Core" version="3.0.alpha.custom_build">
+<class name="NetworkedMultiplayerPeer" inherits="PacketPeer" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
@@ -31,7 +31,7 @@
<return type="bool">
</return>
<description>
- Return whether this [NetworkedMultiplayerPeer] is refusing new connections.
+ Return whether this [code]NetworkedMultiplayerPeer[/code] is refusing new connections.
</description>
</method>
<method name="poll">
@@ -46,7 +46,7 @@
<argument index="0" name="enable" type="bool">
</argument>
<description>
- If [code]endable[/code] is true, this [NetworkedMultiplayerPeer] will refuse new connections.
+ If [code]endable[/code] is true, this [code]NetworkedMultiplayerPeer[/code] will refuse new connections.
</description>
</method>
<method name="set_target_peer">
diff --git a/doc/classes/Nil.xml b/doc/classes/Nil.xml
index de12ad1261..a4bd60d53e 100644
--- a/doc/classes/Nil.xml
+++ b/doc/classes/Nil.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Nil" category="Built-In Types" version="3.0.alpha.custom_build">
+<class name="Nil" category="Built-In Types" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
@@ -100,7 +100,7 @@
</description>
</method>
<method name="Nil">
- <argument index="0" name="from" type="Rect3">
+ <argument index="0" name="from" type="AABB">
</argument>
<description>
</description>
diff --git a/doc/classes/NinePatchRect.xml b/doc/classes/NinePatchRect.xml
index 6829b36e14..2c8bce52a0 100644
--- a/doc/classes/NinePatchRect.xml
+++ b/doc/classes/NinePatchRect.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="NinePatchRect" inherits="Control" category="Core" version="3.0.alpha.custom_build">
+<class name="NinePatchRect" inherits="Control" category="Core" version="3.0-alpha">
<brief_description>
Scalable texture-based frame that tiles the texture's centers and sides, but keeps the corners' original size. Perfect for panels and dialog boxes.
</brief_description>
@@ -111,7 +111,7 @@
If [code]true[/code], draw the panel's center. Else, only draw the 9-slice's borders. Default value: [code]true[/code]
</member>
<member name="patch_margin_bottom" type="int" setter="set_patch_margin" getter="get_patch_margin">
- The height of the 9-slice's bottom row. A margin of 16 means the 9-slice's bottom corners and side will have a height of 16 pixels. You can set all 4 margin values indivually to create panels with non-uniform borders.
+ The height of the 9-slice's bottom row. A margin of 16 means the 9-slice's bottom corners and side will have a height of 16 pixels. You can set all 4 margin values individually to create panels with non-uniform borders.
</member>
<member name="patch_margin_left" type="int" setter="set_patch_margin" getter="get_patch_margin">
The height of the 9-slice's left column.
diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml
index e35f64a9c0..a103d0eba0 100644
--- a/doc/classes/Node.xml
+++ b/doc/classes/Node.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Node" inherits="Object" category="Core" version="3.0.alpha.custom_build">
+<class name="Node" inherits="Object" category="Core" version="3.0-alpha">
<brief_description>
Base class for all the [i]scene[/i] elements.
</brief_description>
@@ -9,11 +9,11 @@
[b]Scene tree:[/b] The [SceneTree] contains the active tree of nodes. When a node is added to the scene tree, it receives the NOTIFICATION_ENTER_TREE notification and its [method _enter_tree] callback is triggered. Children nodes are always added [i]after[/i] their parent node, i.e. the [method _enter_tree] callback of a parent node will be triggered before its child's.
Once all nodes have been added in the scene tree, they receive the NOTIFICATION_READY notification and their respective [method _ready] callbacks are triggered. For groups of nodes, the [method _ready] callback is called in reverse order, from the children up to the parent nodes.
It means that when adding a scene to the scene tree, the following order will be used for the callbacks: [method _enter_tree] of the parent, [method _enter_tree] of the children, [method _ready] of the children and finally [method _ready] of the parent (and that recursively for the whole scene).
- [b]Processing:[/b] Nodes can be set to the "process" state, so that they receive a callback on each frame requesting them to process (do something). Normal processing (callback [method _process], toggled with [method set_process]) happens as fast as possible and is dependent on the frame rate, so the processing time [i]delta[/i] is variable. Fixed processing (callback [method _fixed_process], toggled with [method set_fixed_process]) happens a fixed amount of times per second (by default 60) and is useful to link itself to the physics.
+ [b]Processing:[/b] Nodes can be set to the "process" state, so that they receive a callback on each frame requesting them to process (do something). Normal processing (callback [method _process], toggled with [method set_process]) happens as fast as possible and is dependent on the frame rate, so the processing time [i]delta[/i] is variable. Physics processing (callback [method _physics_process], toggled with [method set_physics_process]) happens a fixed amount of times per second (by default 60) and is useful to link itself to the physics.
Nodes can also process input events. When set, the [method _input] function will be called for each input that the program receives. In many cases, this can be overkill (unless used for simple projects), and the [method _unhandled_input] function might be preferred; it is called when the input event was not handled by anyone else (typically, GUI [Control] nodes), ensuring that the node only receives the events that were meant for it.
To keep track of the scene hierarchy (especially when instancing scenes into other scenes), an "owner" can be set for the node with [method set_owner]. This keeps track of who instanced what. This is mostly useful when writing editors and tools, though.
Finally, when a node is freed with [method free] or [method queue_free], it will also free all its children.
- [b]Networking with nodes:[/b] After connecting to a server (or making one, see [NetworkedMultiplayerENet]) it is possible to use the built-in RPC (remote procedure call) system to easily communicate over the network. By calling [method rpc] with a method name, it will be called locally, and in all connected peers (peers = clients and the server that accepts connections), with behaviour varying depending on the network mode ([method set_network_mode]) on the receiving peer. To identify which [Node] receives the RPC call Godot will use its [NodePath] (make sure node names are the same on all peers).
+ [b]Networking with nodes:[/b] After connecting to a server (or making one, see [NetworkedMultiplayerENet]) it is possible to use the built-in RPC (remote procedure call) system to easily communicate over the network. By calling [method rpc] with a method name, it will be called locally, and in all connected peers (peers = clients and the server that accepts connections), with behaviour varying depending on the network mode ([method set_network_mode]) on the receiving peer. To identify which [code]Node[/code] receives the RPC call Godot will use its [NodePath] (make sure node names are the same on all peers).
</description>
<tutorials>
</tutorials>
@@ -36,24 +36,24 @@
Corresponds to the NOTIFICATION_EXIT_TREE notification in [method Object._notification].
</description>
</method>
- <method name="_fixed_process" qualifiers="virtual">
+ <method name="_input" qualifiers="virtual">
<return type="void">
</return>
- <argument index="0" name="delta" type="float">
+ <argument index="0" name="event" type="InputEvent">
</argument>
<description>
- Called during the fixed processing step of the main loop. Fixed processing means that the frame rate is synced to the physics, i.e. the [code]delta[/code] variable should be constant.
- It is only called if fixed processing has been enabled with [method set_fixed_process].
- Corresponds to the NOTIFICATION_FIXED_PROCESS notification in [method Object._notification].
+ Called when there is a change to input devices. Propagated through the node tree until a Node consumes it.
</description>
</method>
- <method name="_input" qualifiers="virtual">
+ <method name="_physics_process" qualifiers="virtual">
<return type="void">
</return>
- <argument index="0" name="event" type="InputEvent">
+ <argument index="0" name="delta" type="float">
</argument>
<description>
- Called when there is a change to input devices. Propagated through the node tree until a Node consumes it.
+ Called during the physics processing step of the main loop. Physics processing means that the frame rate is synced to the physics, i.e. the [code]delta[/code] variable should be constant.
+ It is only called if physics processing has been enabled with [method set_physics_process].
+ Corresponds to the NOTIFICATION_PHYSICS_PROCESS notification in [method Object._notification].
</description>
</method>
<method name="_process" qualifiers="virtual">
@@ -100,7 +100,7 @@
<argument index="1" name="legible_unique_name" type="bool" default="false">
</argument>
<description>
- Add a child [Node]. Nodes can have as many children as they want, but every child must have a unique name. Children nodes are automatically deleted when the parent node is deleted, so deleting a whole scene is performed by deleting its topmost node.
+ Add a child [code]Node[/code]. Nodes can have as many children as they want, but every child must have a unique name. Children nodes are automatically deleted when the parent node is deleted, so deleting a whole scene is performed by deleting its topmost node.
The optional boolean argument enforces creating child nodes with human-readable names, based on the name of the node being instanced instead of its type only.
</description>
</method>
@@ -124,7 +124,7 @@
<argument index="1" name="persistent" type="bool" default="false">
</argument>
<description>
- Add a node to a group. Groups are helpers to name and organize a subset of nodes, like for example "enemies" or "collectables". A [Node] can be in any number of groups. Nodes can be assigned a group at any time, but will not be added to it until they are inside the scene tree (see [method is_inside_tree]).
+ Add a node to a group. Groups are helpers to name and organize a subset of nodes, like for example "enemies" or "collectables". A [code]Node[/code] can be in any number of groups. Nodes can be assigned a group at any time, but will not be added to it until they are inside the scene tree (see [method is_inside_tree]).
</description>
</method>
<method name="can_process" qualifiers="const">
@@ -140,7 +140,7 @@
<argument index="0" name="flags" type="int" default="15">
</argument>
<description>
- Duplicate the node, returning a new [Node].
+ Duplicate the node, returning a new [code]Node[/code].
You can fine-tune the behavior using the [code]flags[/code], which are based on the DUPLICATE_* constants.
</description>
</method>
@@ -177,7 +177,7 @@
<return type="Array">
</return>
<description>
- Return an array of references ([Node]) to the child nodes.
+ Return an array of references ([code]Node[/code]) to the child nodes.
</description>
</method>
<method name="get_filename" qualifiers="const">
@@ -187,13 +187,6 @@
Return a filename that may be contained by the node. When a scene is instanced from a file, it topmost node contains the filename from where it was loaded (see [method set_filename]).
</description>
</method>
- <method name="get_fixed_process_delta_time" qualifiers="const">
- <return type="float">
- </return>
- <description>
- Return the time elapsed since the last fixed frame (see [method _fixed_process]). This is always the same in fixed processing unless the frames per second is changed in [OS].
- </description>
- </method>
<method name="get_groups" qualifiers="const">
<return type="Array">
</return>
@@ -268,7 +261,7 @@
<return type="Node">
</return>
<description>
- Return the parent node of the current node, or an empty [Node] if the node lacks a parent.
+ Return the parent node of the current node, or an empty [code]Node[/code] if the node lacks a parent.
</description>
</method>
<method name="get_path" qualifiers="const">
@@ -294,6 +287,13 @@
Return the pause mode (PAUSE_MODE_*) of this Node.
</description>
</method>
+ <method name="get_physics_process_delta_time" qualifiers="const">
+ <return type="float">
+ </return>
+ <description>
+ Return the time elapsed since the last physics-bound frame (see [method _physics_process]). This is always a constant value in physics processing unless the frames per second is changed in [OS].
+ </description>
+ </method>
<method name="get_position_in_parent" qualifiers="const">
<return type="int">
</return>
@@ -359,19 +359,6 @@
<description>
</description>
</method>
- <method name="is_fixed_processing" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- Return true if fixed processing is enabled (see [method set_fixed_process]).
- </description>
- </method>
- <method name="is_fixed_processing_internal" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- </description>
- </method>
<method name="is_greater_than" qualifiers="const">
<return type="bool">
</return>
@@ -403,6 +390,19 @@
<description>
</description>
</method>
+ <method name="is_physics_processing" qualifiers="const">
+ <return type="bool">
+ </return>
+ <description>
+ Return true if physics processing is enabled (see [method set_physics_process]).
+ </description>
+ </method>
+ <method name="is_physics_processing_internal" qualifiers="const">
+ <return type="bool">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="is_processing" qualifiers="const">
<return type="bool">
</return>
@@ -470,7 +470,7 @@
<argument index="2" name="parent_first" type="bool" default="false">
</argument>
<description>
- Calls the method (if present) with the arguments given in "args" on this Node and recursively on all children. If the parent_first argument is true then the method will be called on the current [Node] first, then on all children. If it is false then the children will get called first.
+ Calls the method (if present) with the arguments given in "args" on this Node and recursively on all children. If the parent_first argument is true then the method will be called on the current [code]Node[/code] first, then on all children. If it is false then the children will get called first.
</description>
</method>
<method name="propagate_notification">
@@ -509,7 +509,7 @@
<argument index="0" name="node" type="Node">
</argument>
<description>
- Remove a child [Node]. Node is NOT deleted and will have to be deleted manually.
+ Remove a child [code]Node[/code]. Node is NOT deleted and will have to be deleted manually.
</description>
</method>
<method name="remove_from_group">
@@ -666,30 +666,13 @@
A node can contain a filename. This filename should not be changed by the user, unless writing editors and tools. When a scene is instanced from a file, it topmost node contains the filename from where it was loaded.
</description>
</method>
- <method name="set_fixed_process">
- <return type="void">
- </return>
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- Enables or disables node fixed framerate processing. When a node is being processed, it will receive a NOTIFICATION_PROCESS at a fixed (usually 60 fps, check [OS] to change that) interval (and the [method _fixed_process] callback will be called if exists). It is common to check how much time was elapsed since the previous frame by calling [method get_fixed_process_delta_time].
- </description>
- </method>
- <method name="set_fixed_process_internal">
- <return type="void">
- </return>
- <argument index="0" name="enable" type="bool">
- </argument>
- <description>
- </description>
- </method>
<method name="set_name">
<return type="void">
</return>
<argument index="0" name="name" type="String">
</argument>
<description>
- Set the name of the [Node]. Name must be unique within parent, and setting an already existing name will cause for the node to be automatically renamed.
+ Set the name of the [code]Node[/code]. Name must be unique within parent, and setting an already existing name will cause for the node to be automatically renamed.
</description>
</method>
<method name="set_network_master">
@@ -720,6 +703,23 @@
Set pause mode (PAUSE_MODE_*) of this Node.
</description>
</method>
+ <method name="set_physics_process">
+ <return type="void">
+ </return>
+ <argument index="0" name="enable" type="bool">
+ </argument>
+ <description>
+ Enables or disables the node's physics (alias fixed framerate) processing. When a node is being processed, it will receive a NOTIFICATION_PHYSICS_PROCESS at a fixed (usually 60 fps, check [OS] to change that) interval (and the [method _physics_process] callback will be called if exists). It is common to check how much time was elapsed since the previous frame by calling [method get_physics_process_delta_time].
+ </description>
+ </method>
+ <method name="set_physics_process_internal">
+ <return type="void">
+ </return>
+ <argument index="0" name="enable" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="set_process">
<return type="void">
</return>
@@ -806,7 +806,12 @@
</constant>
<constant name="NOTIFICATION_READY" value="13" enum="">
</constant>
- <constant name="NOTIFICATION_FIXED_PROCESS" value="16" enum="">
+ <constant name="NOTIFICATION_PAUSED" value="14" enum="">
+ </constant>
+ <constant name="NOTIFICATION_UNPAUSED" value="15" enum="">
+ </constant>
+ <constant name="NOTIFICATION_PHYSICS_PROCESS" value="16" enum="">
+ Notification received every frame when the physics process flag is set (see [method set_physics_process]).
</constant>
<constant name="NOTIFICATION_PROCESS" value="17" enum="">
Notification received every frame when the process flag is set (see [method set_process]).
@@ -817,10 +822,6 @@
<constant name="NOTIFICATION_UNPARENTED" value="19" enum="">
Notification received when a node is unparented (parent removed it from the list of children).
</constant>
- <constant name="NOTIFICATION_PAUSED" value="14" enum="">
- </constant>
- <constant name="NOTIFICATION_UNPAUSED" value="15" enum="">
- </constant>
<constant name="NOTIFICATION_INSTANCED" value="20" enum="">
</constant>
<constant name="NOTIFICATION_DRAG_BEGIN" value="21" enum="">
@@ -833,7 +834,7 @@
</constant>
<constant name="NOTIFICATION_INTERNAL_PROCESS" value="25" enum="">
</constant>
- <constant name="NOTIFICATION_INTERNAL_FIXED_PROCESS" value="26" enum="">
+ <constant name="NOTIFICATION_INTERNAL_PHYSICS_PROCESS" value="26" enum="">
</constant>
<constant name="RPC_MODE_DISABLED" value="0">
</constant>
diff --git a/doc/classes/Node2D.xml b/doc/classes/Node2D.xml
index 084bee92df..195dd9265f 100644
--- a/doc/classes/Node2D.xml
+++ b/doc/classes/Node2D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Node2D" inherits="CanvasItem" category="Core" version="3.0.alpha.custom_build">
+<class name="Node2D" inherits="CanvasItem" category="Core" version="3.0-alpha">
<brief_description>
A 2D game object, parent of all 2D related nodes. Has a position, rotation, scale and Z-index.
</brief_description>
@@ -26,7 +26,7 @@
<argument index="0" name="pivot" type="Vector2">
</argument>
<description>
- Set the pivot position of the 2D node to 'pivot' value. Only some Node2Ds implement this method.
+ Sets the node's pivot position.
</description>
</method>
<method name="get_angle_to" qualifiers="const">
@@ -52,7 +52,7 @@
Returns the node's global rotation in radians.
</description>
</method>
- <method name="get_global_rotation_in_degrees" qualifiers="const">
+ <method name="get_global_rotation_degrees" qualifiers="const">
<return type="float">
</return>
<description>
@@ -89,7 +89,7 @@
Returns the node's rotation in radians.
</description>
</method>
- <method name="get_rotation_in_degrees" qualifiers="const">
+ <method name="get_rotation_degrees" qualifiers="const">
<return type="float">
</return>
<description>
@@ -143,7 +143,7 @@
<argument index="1" name="scaled" type="bool" default="false">
</argument>
<description>
- Apply a local translation on the node's X axis based on the process's 'delta'. If 'scaled' is false, normalizes the movement.
+ Applies a local translation on the node's X axis based on the [method Node._process]'s [code]delta[/code]. If [code]scaled[/code] is false, normalizes the movement.
</description>
</method>
<method name="move_local_y">
@@ -154,7 +154,7 @@
<argument index="1" name="scaled" type="bool" default="false">
</argument>
<description>
- Apply a local translation on the node's Y axis based on the process's 'delta'. If 'scaled' is false, normalizes the movement.
+ Applies a local translation on the node's Y axis based on the [method Node._process]'s [code]delta[/code]. If [code]scaled[/code] is false, normalizes the movement.
</description>
</method>
<method name="rotate">
@@ -163,7 +163,7 @@
<argument index="0" name="radians" type="float">
</argument>
<description>
- Apply a rotation to the node, in radians, starting from its current rotation.
+ Applies a rotation to the node, in radians, starting from its current rotation.
</description>
</method>
<method name="set_global_position">
@@ -172,7 +172,7 @@
<argument index="0" name="position" type="Vector2">
</argument>
<description>
- Set the node's global position.
+ Sets the node's global position.
</description>
</method>
<method name="set_global_rotation">
@@ -181,16 +181,16 @@
<argument index="0" name="radians" type="float">
</argument>
<description>
- Set the node's global rotation in radians.
+ Sets the node's global rotation in radians.
</description>
</method>
- <method name="set_global_rotation_in_degrees">
+ <method name="set_global_rotation_degrees">
<return type="void">
</return>
<argument index="0" name="degrees" type="float">
</argument>
<description>
- Set the node's global rotation in degrees.
+ Sets the node's global rotation in degrees.
</description>
</method>
<method name="set_global_scale">
@@ -199,7 +199,7 @@
<argument index="0" name="scale" type="Vector2">
</argument>
<description>
- Set the node's global scale.
+ Sets the node's global scale.
</description>
</method>
<method name="set_global_transform">
@@ -208,7 +208,7 @@
<argument index="0" name="xform" type="Transform2D">
</argument>
<description>
- Set the node's global [Transform2D].
+ Sets the node's global [Transform2D].
</description>
</method>
<method name="set_position">
@@ -217,7 +217,7 @@
<argument index="0" name="position" type="Vector2">
</argument>
<description>
- Set the node's position.
+ Sets the node's position.
</description>
</method>
<method name="set_rotation">
@@ -226,16 +226,16 @@
<argument index="0" name="radians" type="float">
</argument>
<description>
- Set the node's rotation in radians.
+ Sets the node's rotation in radians.
</description>
</method>
- <method name="set_rotation_in_degrees">
+ <method name="set_rotation_degrees">
<return type="void">
</return>
<argument index="0" name="degrees" type="float">
</argument>
<description>
- Set the node's rotation in degrees.
+ Sets the node's rotation in degrees.
</description>
</method>
<method name="set_scale">
@@ -244,7 +244,7 @@
<argument index="0" name="scale" type="Vector2">
</argument>
<description>
- Set the node's scale.
+ Sets the node's scale.
</description>
</method>
<method name="set_transform">
@@ -253,7 +253,7 @@
<argument index="0" name="xform" type="Transform2D">
</argument>
<description>
- Set the node's local [Transform2D].
+ Sets the node's local [Transform2D].
</description>
</method>
<method name="set_z">
@@ -262,7 +262,7 @@
<argument index="0" name="z" type="int">
</argument>
<description>
- Set the node's Z-index.
+ Sets the node's Z-index.
</description>
</method>
<method name="set_z_as_relative">
@@ -271,7 +271,7 @@
<argument index="0" name="enable" type="bool">
</argument>
<description>
- Make the node's Z-index relative to its parent's Z-index. If this node's Z-index is 2 and its parent's effective Z-index is 3, then this node's effective Z-index will be 2 + 3 = 5.
+ Makes the node's Z-index relative to its parent's Z-index. If this node's Z-index is 2 and its parent's effective Z-index is 3, then this node's effective Z-index will be 2 + 3 = 5.
</description>
</method>
<method name="to_global" qualifiers="const">
@@ -280,6 +280,7 @@
<argument index="0" name="local_point" type="Vector2">
</argument>
<description>
+ Converts a local point's coordinates to global coordinates.
</description>
</method>
<method name="to_local" qualifiers="const">
@@ -288,6 +289,7 @@
<argument index="0" name="global_point" type="Vector2">
</argument>
<description>
+ Converts a global point's coordinates to local coordinates.
</description>
</method>
<method name="translate">
@@ -296,7 +298,7 @@
<argument index="0" name="offset" type="Vector2">
</argument>
<description>
- Translate the node locally by the 'offset' vector, starting from its current local position.
+ Translates the node by the given [code]offset[/code] in local coordinates.
</description>
</method>
</methods>
@@ -307,7 +309,7 @@
<member name="global_rotation" type="float" setter="set_global_rotation" getter="get_global_rotation">
Global rotation in radians.
</member>
- <member name="global_rotation_deg" type="float" setter="set_global_rotation_in_degrees" getter="get_global_rotation_in_degrees">
+ <member name="global_rotation_degrees" type="float" setter="set_global_rotation_degrees" getter="get_global_rotation_degrees">
Global rotation in degrees.
</member>
<member name="global_scale" type="Vector2" setter="set_global_scale" getter="get_global_scale">
@@ -320,13 +322,13 @@
Position, relative to the node's parent.
</member>
<member name="rotation" type="float" setter="set_rotation" getter="get_rotation">
- Rotation in radians.
+ Rotation in radians, relative to the node's parent.
</member>
- <member name="rotation_deg" type="float" setter="set_rotation_in_degrees" getter="get_rotation_in_degrees">
- Rotation in degrees.
+ <member name="rotation_degrees" type="float" setter="set_rotation_degrees" getter="get_rotation_degrees">
+ Rotation in degrees, relative to the node's parent.
</member>
<member name="scale" type="Vector2" setter="set_scale" getter="get_scale">
- Rotation in degrees.
+ The node's scale. Unscaled value: [code](1, 1)[/code]
</member>
<member name="transform" type="Transform2D" setter="set_transform" getter="get_transform">
Local [Transform2D].
@@ -335,7 +337,7 @@
Z-index. Controls the order in which the nodes render. A node with a higher Z-index will display in front of others.
</member>
<member name="z_as_relative" type="bool" setter="set_z_as_relative" getter="is_z_relative">
- Make the node's Z-index relative to its parent's Z-index. If this node's Z-index is 2 and its parent's effective Z-index is 3, then this node's effective Z-index will be 2 + 3 = 5.
+ If [code]true[/code] the node's Z-index is relative to its parent's Z-index. If this node's Z-index is 2 and its parent's effective Z-index is 3, then this node's effective Z-index will be 2 + 3 = 5.
</member>
</members>
<constants>
diff --git a/doc/classes/NodePath.xml b/doc/classes/NodePath.xml
index 9aa9572b80..c706864379 100644
--- a/doc/classes/NodePath.xml
+++ b/doc/classes/NodePath.xml
@@ -1,12 +1,12 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="NodePath" category="Built-In Types" version="3.0.alpha.custom_build">
+<class name="NodePath" category="Built-In Types" version="3.0-alpha">
<brief_description>
Pre-parsed scene tree path.
</brief_description>
<description>
A pre-parsed relative or absolute path in a scene tree, for use with [method Node.get_node] and similar functions. It can reference a node, a resource within a node, or a property of a node or resource. For instance, [code]"Path2D/PathFollow2D/Sprite:texture:size"[/code] would refer to the size property of the texture resource on the node named "Sprite" which is a child of the other named nodes in the path. Note that if you want to get a resource, you must end the path with a colon, otherwise the last element will be used as a property name.
- You will usually just pass a string to [method Node.get_node] and it will be automatically converted, but you may occasionally want to parse a path ahead of time with [NodePath] or the literal syntax [code]@"path"[/code]. Exporting a [NodePath] variable will give you a node selection widget in the properties panel of the editor, which can often be useful.
- A [NodePath] is made up of a list of node names, a list of "subnode" (resource) names, and the name of a property in the final node or resource.
+ You will usually just pass a string to [method Node.get_node] and it will be automatically converted, but you may occasionally want to parse a path ahead of time with [code]NodePath[/code] or the literal syntax [code]@"path"[/code]. Exporting a [code]NodePath[/code] variable will give you a node selection widget in the properties panel of the editor, which can often be useful.
+ A [code]NodePath[/code] is made up of a list of node names, a list of "subnode" (resource) names, and the name of a property in the final node or resource.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml
index d411d07979..8f82040eca 100644
--- a/doc/classes/OS.xml
+++ b/doc/classes/OS.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="OS" inherits="Object" category="Core" version="3.0.alpha.custom_build">
+<class name="OS" inherits="Object" category="Core" version="3.0-alpha">
<brief_description>
Operating System functions.
</brief_description>
@@ -26,14 +26,14 @@
<return type="bool">
</return>
<description>
- Return true if the host OS allows drawing.
+ Returns [code]true[/code] if the host OS allows drawing.
</description>
</method>
<method name="can_use_threads" qualifiers="const">
<return type="bool">
</return>
<description>
- Returns if the current host platform is using multiple threads.
+ Returns [code]true[/code] if the current host platform is using multiple threads.
</description>
</method>
<method name="delay_msec" qualifiers="const">
@@ -117,7 +117,7 @@
<return type="PoolStringArray">
</return>
<description>
- Return the commandline passed to the engine.
+ Returns the command line arguments passed to the engine.
</description>
</method>
<method name="get_current_screen" qualifiers="const">
@@ -127,11 +127,11 @@
Returns the current screen index (0 padded).
</description>
</method>
- <method name="get_data_dir" qualifiers="const">
+ <method name="get_user_data_dir" qualifiers="const">
<return type="String">
</return>
<description>
- Return the absolute directory path of user data path([user://]).
+ Returns the absolute directory path where user data is written ([code]user://[/code]).
</description>
</method>
<method name="get_date" qualifiers="const">
@@ -166,7 +166,7 @@
<return type="int">
</return>
<description>
- Return the total amount of dynamic memory used (only works in debug).
+ Returns the total amount of dynamic memory used (only works in debug).
</description>
</method>
<method name="get_environment" qualifiers="const">
@@ -175,14 +175,14 @@
<argument index="0" name="environment" type="String">
</argument>
<description>
- Return an environment variable.
+ Returns an environment variable.
</description>
</method>
<method name="get_executable_path" qualifiers="const">
<return type="String">
</return>
<description>
- Return the path to the current engine executable.
+ Returns the path to the current engine executable.
</description>
</method>
<method name="get_exit_code" qualifiers="const">
@@ -196,14 +196,14 @@
</return>
<description>
Returns the current latin keyboard variant as a String.
- Possible return values are: "QWERTY", "AZERTY", "QZERTY", "DVORAK", "NEO" or "ERROR"
+ Possible return values are: "QWERTY", "AZERTY", "QZERTY", "DVORAK", "NEO", "COLEMAK" or "ERROR".
</description>
</method>
<method name="get_locale" qualifiers="const">
<return type="String">
</return>
<description>
- Return the host OS locale.
+ Returns the host OS locale.
</description>
</method>
<method name="get_model_name" qualifiers="const">
@@ -217,25 +217,28 @@
<return type="String">
</return>
<description>
- Return the name of the host OS. Possible values are: "Android", "Haiku", "iOS", "HTML5", "OSX", "Server", "Windows", "UWP", "X11".
+ Returns the name of the host OS. Possible values are: "Android", "Haiku", "iOS", "HTML5", "OSX", "Server", "Windows", "UWP", "X11".
</description>
</method>
<method name="get_power_percent_left">
<return type="int">
</return>
<description>
+ Returns the amount of battery left in the device as a percentage.
</description>
</method>
<method name="get_power_seconds_left">
<return type="int">
</return>
<description>
+ Returns the time in seconds before the device runs out of battery.
</description>
</method>
<method name="get_power_state">
<return type="int" enum="OS.PowerState">
</return>
<description>
+ Returns the current state of the device regarding battery and power. See [code]POWERSTATE_*[/code] constants.
</description>
</method>
<method name="get_process_id" qualifiers="const">
@@ -265,7 +268,7 @@
<return type="int">
</return>
<description>
- Returns the number of displays attached to the host machine
+ Returns the number of displays attached to the host machine.
</description>
</method>
<method name="get_screen_dpi" qualifiers="const">
@@ -298,6 +301,7 @@
<argument index="0" name="screen" type="int" default="-1">
</argument>
<description>
+ Returns the position of the specified screen by index. If no screen index is provided, the current screen will be used.
</description>
</method>
<method name="get_screen_size" qualifiers="const">
@@ -319,7 +323,7 @@
<return type="int">
</return>
<description>
- Return the max amount of static memory used (only works in debug).
+ Returns the max amount of static memory used (only works in debug).
</description>
</method>
<method name="get_static_memory_usage" qualifiers="const">
@@ -335,6 +339,7 @@
<argument index="0" name="dir" type="int" enum="OS.SystemDir">
</argument>
<description>
+ Returns the actual path to commonly used folders across different platforms. Available locations are specified in [OS.SystemDir].
</description>
</method>
<method name="get_system_time_secs" qualifiers="const">
@@ -348,7 +353,7 @@
<return type="int">
</return>
<description>
- Return the amount of time passed in milliseconds since the engine started.
+ Returns the amount of time passed in milliseconds since the engine started.
</description>
</method>
<method name="get_time" qualifiers="const">
@@ -357,19 +362,21 @@
<argument index="0" name="utc" type="bool" default="false">
</argument>
<description>
- Returns current time as a dictionary of keys: hour, minute, second
+ Returns current time as a dictionary of keys: hour, minute, second.
</description>
</method>
<method name="get_time_zone_info" qualifiers="const">
<return type="Dictionary">
</return>
<description>
+ Returns the current time zone as a dictionary with the keys: bias and name.
</description>
</method>
<method name="get_unique_id" qualifiers="const">
<return type="String">
</return>
<description>
+ Returns a string that is unique to the device. Currently only works on Android and iOS. Returns empty string on other platforms.
</description>
</method>
<method name="get_unix_time" qualifiers="const">
@@ -390,6 +397,12 @@
You can pass the output from [method get_datetime_from_unix_time] directly into this function. Daylight savings time (dst), if present, is ignored.
</description>
</method>
+ <method name="get_virtual_keyboard_height">
+ <return type="int">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="get_window_position" qualifiers="const">
<return type="Vector2">
</return>
@@ -410,20 +423,29 @@
<argument index="0" name="environment" type="String">
</argument>
<description>
- Return true if an environment variable exists.
+ Returns [code]true[/code] if an environment variable exists.
+ </description>
+ </method>
+ <method name="has_feature" qualifiers="const">
+ <return type="bool">
+ </return>
+ <argument index="0" name="tag_name" type="String">
+ </argument>
+ <description>
</description>
</method>
<method name="has_touchscreen_ui_hint" qualifiers="const">
<return type="bool">
</return>
<description>
+ Returns [code]true[/code] if the device has a touchscreen or emulates one.
</description>
</method>
<method name="has_virtual_keyboard" qualifiers="const">
<return type="bool">
</return>
<description>
- Returns true if the platform has a virtual keyboard, false otherwise.
+ Returns [code]true[/code] if the platform has a virtual keyboard, [code]false[/code] otherwise.
</description>
</method>
<method name="hide_virtual_keyboard">
@@ -446,20 +468,21 @@
<return type="bool">
</return>
<description>
- Return true if low cpu usage mode is enabled.
+ Returns [code]true[/code] if low cpu usage mode is enabled.
</description>
</method>
<method name="is_keep_screen_on" qualifiers="const">
<return type="bool">
</return>
<description>
- Returns whether the screen is being kept on or not.
+ Returns [code]true[/code] if the screen is being kept on.
</description>
</method>
<method name="is_ok_left_and_cancel_right" qualifiers="const">
<return type="bool">
</return>
<description>
+ Returns [code]true[/code] if the "Okay" button should appear on the left and "Cancel" on the right.
</description>
</method>
<method name="is_scancode_unicode" qualifiers="const">
@@ -468,13 +491,14 @@
<argument index="0" name="code" type="int">
</argument>
<description>
+ Returns [code]true[/code] if the input code has a unicode character.
</description>
</method>
<method name="is_stdout_verbose" qualifiers="const">
<return type="bool">
</return>
<description>
- Return true if the engine was executed with -v (verbose stdout).
+ Returns [code]true[/code] if the engine was executed with -v (verbose stdout).
</description>
</method>
<method name="is_userfs_persistent" qualifiers="const">
@@ -495,28 +519,28 @@
<return type="bool">
</return>
<description>
- Returns whether the window is in fullscreen mode or not.
+ Returns [code]true[/code] if the window is in fullscreen mode.
</description>
</method>
<method name="is_window_maximized" qualifiers="const">
<return type="bool">
</return>
<description>
- Return true if the window is maximized.
+ Returns [code]true[/code] if the window is maximized.
</description>
</method>
<method name="is_window_minimized" qualifiers="const">
<return type="bool">
</return>
<description>
- Return true if the window is minimized.
+ Returns [code]true[/code] if the window is minimized.
</description>
</method>
<method name="is_window_resizable" qualifiers="const">
<return type="bool">
</return>
<description>
- Returns whether the window is resizable or not.
+ Returns [code]true[/code] if the window is resizable.
</description>
</method>
<method name="kill">
@@ -532,12 +556,14 @@
<return type="bool">
</return>
<description>
+ Returns [code]true[/code] if native video is playing.
</description>
</method>
<method name="native_video_pause">
<return type="void">
</return>
<description>
+ Pauses native video playback.
</description>
</method>
<method name="native_video_play">
@@ -552,18 +578,21 @@
<argument index="3" name="subtitle_track" type="String">
</argument>
<description>
+ Plays native video from the specified path, at the given volume and with audio and subtitle tracks.
</description>
</method>
<method name="native_video_stop">
<return type="void">
</return>
<description>
+ Stops native video playback.
</description>
</method>
<method name="native_video_unpause">
<return type="void">
</return>
<description>
+ Resumes native video playback.
</description>
</method>
<method name="print_all_resources">
@@ -572,12 +601,14 @@
<argument index="0" name="tofile" type="String" default="&quot;&quot;">
</argument>
<description>
+ Shows all resources in the game. Optionally the list can be written to a file.
</description>
</method>
<method name="print_all_textures_by_size">
<return type="void">
</return>
<description>
+ Shows the list of loaded textures sorted by size in memory.
</description>
</method>
<method name="print_resources_by_type">
@@ -586,6 +617,7 @@
<argument index="0" name="types" type="PoolStringArray">
</argument>
<description>
+ Shows the number of resources loaded by the game of the given types.
</description>
</method>
<method name="print_resources_in_use">
@@ -594,6 +626,7 @@
<argument index="0" name="short" type="bool" default="false">
</argument>
<description>
+ Shows all resources currently used by the game.
</description>
</method>
<method name="request_attention">
@@ -609,6 +642,7 @@
<argument index="0" name="borderless" type="bool">
</argument>
<description>
+ Removes the window frame.
</description>
</method>
<method name="set_clipboard">
@@ -617,7 +651,7 @@
<argument index="0" name="clipboard" type="String">
</argument>
<description>
- Set clipboard to the OS.
+ Sets clipboard to the OS.
</description>
</method>
<method name="set_current_screen">
@@ -626,6 +660,7 @@
<argument index="0" name="screen" type="int">
</argument>
<description>
+ Sets the current screen by index.
</description>
</method>
<method name="set_exit_code">
@@ -634,6 +669,7 @@
<argument index="0" name="code" type="int">
</argument>
<description>
+ Sets the exit code that will be returned by the game.
</description>
</method>
<method name="set_icon">
@@ -642,6 +678,7 @@
<argument index="0" name="icon" type="Image">
</argument>
<description>
+ Sets the game's icon.
</description>
</method>
<method name="set_ime_position">
@@ -658,7 +695,7 @@
<argument index="0" name="enabled" type="bool">
</argument>
<description>
- Set keep screen on if true, or goes to sleep by device setting if false. (for Android/iOS)
+ Sets keep screen on if true, or goes to sleep by device setting if false. (for Android/iOS)
</description>
</method>
<method name="set_low_processor_usage_mode">
@@ -667,7 +704,7 @@
<argument index="0" name="enable" type="bool">
</argument>
<description>
- Set to true to enable the low cpu usage mode. In this mode, the screen only redraws when there are changes, and a considerable sleep time is inserted between frames. This way, editors using the engine UI only use very little cpu.
+ Set to [code]true[/code] to enable the low cpu usage mode. In this mode, the screen only redraws when there are changes, and a considerable sleep time is inserted between frames. Use this in tool mode to reduce CPU usage.
</description>
</method>
<method name="set_screen_orientation">
@@ -685,6 +722,7 @@
<argument index="0" name="name" type="String">
</argument>
<description>
+ Sets the name of the current thread.
</description>
</method>
<method name="set_use_file_access_save_and_swap">
@@ -693,6 +731,7 @@
<argument index="0" name="enabled" type="bool">
</argument>
<description>
+ Enables backup saves if [code]enabled[/code] is [code]true[/code].
</description>
</method>
<method name="set_use_vsync">
@@ -719,7 +758,7 @@
<argument index="0" name="enabled" type="bool">
</argument>
<description>
- Set the window size to maximized.
+ Set [code]true[/code] to maximize the window.
</description>
</method>
<method name="set_window_minimized">
@@ -728,7 +767,7 @@
<argument index="0" name="enabled" type="bool">
</argument>
<description>
- Set whether the window is minimized.
+ Set [code]true[/code] to minimize the window.
</description>
</method>
<method name="set_window_position">
@@ -746,7 +785,7 @@
<argument index="0" name="enabled" type="bool">
</argument>
<description>
- Set the window resizable state, if the window is not resizable it will preserve the dimensions specified in the project settings.
+ Sets the window resizable state, if the window is not resizable it will preserve the dimensions specified in the project settings.
</description>
</method>
<method name="set_window_size">
@@ -773,6 +812,9 @@
<argument index="0" name="uri" type="String">
</argument>
<description>
+ Requests the OS to open a resource with the most appropriate program. For example.
+ [code]OS.shell_open("C:\\Users\name\Downloads")[/code] on Windows opens the file explorer at the downloads folders of the user.
+ [code]OS.shell_open("http://godotengine.org")[/code] opens the default web browser on the official Godot website.
</description>
</method>
<method name="show_virtual_keyboard">
diff --git a/doc/classes/Object.xml b/doc/classes/Object.xml
index 67421487f1..bea4c14a3c 100644
--- a/doc/classes/Object.xml
+++ b/doc/classes/Object.xml
@@ -1,12 +1,12 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Object" category="Core" version="3.0.alpha.custom_build">
+<class name="Object" category="Core" version="3.0-alpha">
<brief_description>
Base class for all non built-in types.
</brief_description>
<description>
Base class for all non built-in types. Everything not a built-in type starts the inheritance chain from this class.
Objects do not manage memory, if inheriting from one the object will most likely have to be deleted manually (call the [method free] function from the script or delete from C++).
- Some derivates add memory management, such as [Reference] (which keeps a reference count and deletes itself automatically when no longer referenced) and [Node], which deletes the children tree when deleted.
+ Some derivatives add memory management, such as [Reference] (which keeps a reference count and deletes itself automatically when no longer referenced) and [Node], which deletes the children tree when deleted.
Objects export properties, which are mainly useful for storage and editing, but not really so much in programming. Properties are exported in [method _get_property_list] and handled in [method _get] and [method _set]. However, scripting languages and C++ have simpler means to export them.
Objects also receive notifications ([method _notification]). Notifications are a simple way to notify the object about simple events, so they can all be handled together.
</description>
@@ -21,20 +21,21 @@
<argument index="0" name="property" type="String">
</argument>
<description>
- Return a property, return null if the property does not exist.
+ Returns the given property. Returns [code]null[/code] if the [code]property[/code] does not exist.
</description>
</method>
<method name="_get_property_list" qualifiers="virtual">
<return type="Array">
</return>
<description>
- Return the property list, array of dictionaries, dictionaries must contain: name:String, type:int (see TYPE_* enum in [@Global Scope]) and optionally: hint:int (see PROPERTY_HINT_* in [@Global Scope]), hint_string:String, usage:int (see PROPERTY_USAGE_* in [@Global Scope]).
+ Returns the object's property list as an [Array] of dictionaries. Dictionaries must contain: name:String, type:int (see TYPE_* enum in [@GlobalScope]) and optionally: hint:int (see PROPERTY_HINT_* in [@GlobalScope]), hint_string:String, usage:int (see PROPERTY_USAGE_* in [@GlobalScope]).
</description>
</method>
<method name="_init" qualifiers="virtual">
<return type="void">
</return>
<description>
+ The virtual method called upon initialization.
</description>
</method>
<method name="_notification" qualifiers="virtual">
@@ -43,7 +44,7 @@
<argument index="0" name="what" type="int">
</argument>
<description>
- Notification request, the notification id is received.
+ Notify the object internally using an ID.
</description>
</method>
<method name="_set" qualifiers="virtual">
@@ -54,7 +55,7 @@
<argument index="1" name="value" type="Variant">
</argument>
<description>
- Set a property. Return true if the property was found.
+ Sets a property. Returns [code]true[/code] if the [code]property[/code] exists.
</description>
</method>
<method name="add_user_signal">
@@ -65,7 +66,7 @@
<argument index="1" name="arguments" type="Array" default="[ ]">
</argument>
<description>
- Add a user signal (can be added anytime). Arguments are optional, but can be added as an array of dictionaries, each containing "name" and "type" (from [@Global Scope] TYPE_*).
+ Adds a user-defined [code]signal[/code]. Arguments are optional, but can be added as an [Array] of dictionaries, each containing "name" and "type" (from [@GlobalScope] TYPE_*).
</description>
</method>
<method name="call" qualifiers="vararg">
@@ -74,6 +75,7 @@
<argument index="0" name="method" type="String">
</argument>
<description>
+ Calls the [code]method[/code] on the object and returns a result. Pass parameters as a comma separated list.
</description>
</method>
<method name="call_deferred" qualifiers="vararg">
@@ -82,6 +84,7 @@
<argument index="0" name="method" type="String">
</argument>
<description>
+ Calls the [code]method[/code] on the object during idle time and returns a result. Pass parameters as a comma separated list.
</description>
</method>
<method name="callv">
@@ -92,13 +95,14 @@
<argument index="1" name="arg_array" type="Array">
</argument>
<description>
+ Calls the [code]method[/code] on the object and returns a result. Pass parameters as an [Array].
</description>
</method>
<method name="can_translate_messages" qualifiers="const">
<return type="bool">
</return>
<description>
- Return true if this object can translate strings.
+ Returns [code]true[/code] if the object can translate strings.
</description>
</method>
<method name="connect">
@@ -115,7 +119,7 @@
<argument index="4" name="flags" type="int" default="0">
</argument>
<description>
- Connect a signal to a method at a target (member function). Binds are optional and are passed as extra arguments to the call. Flags specify optional deferred or one shot connections, see enum CONNECT_*. A signal can only be connected once to a method, and it will throw an error if already connected. If you want to avoid this, use [method is_connected] to check.
+ Connects a [code]signal[/code] to a [code]method[/code] on a [code]target[/code] object. Pass optional [code]binds[/code] to the call. Use [code]flags[/code] to set deferred or one shot connections. See [code]CONNECT_*[/code] constants. A [code]signal[/code] can only be connected once to a [code]method[/code]. It will throw an error if already connected. To avoid this, first use [method is_connected] to check for existing connections.
</description>
</method>
<method name="disconnect">
@@ -128,7 +132,7 @@
<argument index="2" name="method" type="String">
</argument>
<description>
- Disconnect a signal from a method.
+ Disconnects a [code]signal[/code] from a [code]method[/code] on the given [code]target[/code].
</description>
</method>
<method name="emit_signal" qualifiers="vararg">
@@ -137,12 +141,14 @@
<argument index="0" name="signal" type="String">
</argument>
<description>
+ Emits the given [code]signal[/code].
</description>
</method>
<method name="free">
<return type="void">
</return>
<description>
+ Deletes the object from memory.
</description>
</method>
<method name="get" qualifiers="const">
@@ -151,21 +157,21 @@
<argument index="0" name="property" type="String">
</argument>
<description>
- Get a property from the object.
+ Returns a [Variant] for a [code]property[/code].
</description>
</method>
<method name="get_class" qualifiers="const">
<return type="String">
</return>
<description>
- Return the class of the object as a string.
+ Returns the object's class as a [String].
</description>
</method>
<method name="get_incoming_connections" qualifiers="const">
<return type="Array">
</return>
<description>
- Returns an [Array] of dictionaries with informations about signals that are connected to this object.
+ Returns an [Array] of dictionaries with information about signals that are connected to the object.
Inside each [Dictionary] there are 3 fields:
- "source" is a reference to signal emitter.
- "signal_name" is name of connected signal.
@@ -176,7 +182,7 @@
<return type="int">
</return>
<description>
- Return the instance ID. All objects have a unique instance ID.
+ Returns the object's unique instance ID.
</description>
</method>
<method name="get_meta" qualifiers="const">
@@ -185,34 +191,35 @@
<argument index="0" name="name" type="String">
</argument>
<description>
- Return a metadata from the object.
+ Returns the object's metadata for the given [code]name[/code].
</description>
</method>
<method name="get_meta_list" qualifiers="const">
<return type="PoolStringArray">
</return>
<description>
- Return the list of metadata in the object.
+ Returns the object's metadata as a [PoolStringArray].
</description>
</method>
<method name="get_method_list" qualifiers="const">
<return type="Array">
</return>
<description>
+ Returns the object's methods and their signatures as an [Array].
</description>
</method>
<method name="get_property_list" qualifiers="const">
<return type="Array">
</return>
<description>
- Return the list of properties as an array of dictionaries, dictionaries contain: name:String, type:int (see TYPE_* enum in [@Global Scope]) and optionally: hint:int (see PROPERTY_HINT_* in [@Global Scope]), hint_string:String, usage:int (see PROPERTY_USAGE_* in [@Global Scope]).
+ Returns the list of properties as an [Array] of dictionaries. Dictionaries contain: name:String, type:int (see TYPE_* enum in [@GlobalScope]) and optionally: hint:int (see PROPERTY_HINT_* in [@GlobalScope]), hint_string:String, usage:int (see PROPERTY_USAGE_* in [@GlobalScope]).
</description>
</method>
<method name="get_script" qualifiers="const">
<return type="Reference">
</return>
<description>
- Return the object script (or null if it doesn't have one).
+ Returns the object's [Script] or [code]null[/code] if one doesn't exist.
</description>
</method>
<method name="get_signal_connection_list" qualifiers="const">
@@ -221,13 +228,14 @@
<argument index="0" name="signal" type="String">
</argument>
<description>
+ Returns an [Array] of connections for the given [code]signal[/code].
</description>
</method>
<method name="get_signal_list" qualifiers="const">
<return type="Array">
</return>
<description>
- Return the list of signals as an array of dictionaries.
+ Returns the list of signals as an [Array] of dictionaries.
</description>
</method>
<method name="has_meta" qualifiers="const">
@@ -236,7 +244,7 @@
<argument index="0" name="name" type="String">
</argument>
<description>
- Return true if a metadata is found with the requested name.
+ Returns [code]true[/code] if a metadata is found with the given [code]name[/code].
</description>
</method>
<method name="has_method" qualifiers="const">
@@ -245,6 +253,7 @@
<argument index="0" name="method" type="String">
</argument>
<description>
+ Returns [code]true[/code] if the object contains the given [code]method[/code].
</description>
</method>
<method name="has_user_signal" qualifiers="const">
@@ -253,13 +262,14 @@
<argument index="0" name="signal" type="String">
</argument>
<description>
+ Returns [code]true[/code] if the given user-defined [code]signal[/code] exists.
</description>
</method>
<method name="is_blocking_signals" qualifiers="const">
<return type="bool">
</return>
<description>
- Return true if signal emission blocking is enabled.
+ Returns [code]true[/code] if signal emission blocking is enabled.
</description>
</method>
<method name="is_class" qualifiers="const">
@@ -268,7 +278,7 @@
<argument index="0" name="type" type="String">
</argument>
<description>
- Check the class of the object against a string (including inheritance).
+ Returns [code]true[/code] if the object inherits from the given [code]type[/code].
</description>
</method>
<method name="is_connected" qualifiers="const">
@@ -281,13 +291,14 @@
<argument index="2" name="method" type="String">
</argument>
<description>
- Return true if a connection exists for a given signal and target/method.
+ Returns [code]true[/code] if a connection exists for a given [code]signal[/code], [code]target[/code], and [code]method[/code].
</description>
</method>
<method name="is_queued_for_deletion" qualifiers="const">
<return type="bool">
</return>
<description>
+ Returns [code]true[/code] if the [code]queue_free[/code] method was called for the object.
</description>
</method>
<method name="notification">
@@ -333,7 +344,7 @@
<argument index="0" name="enable" type="bool">
</argument>
<description>
- Define whether this object can translate strings (with calls to [method tr]). Default is true.
+ Define whether the object can translate strings (with calls to [method tr]). Default is true.
</description>
</method>
<method name="set_meta">
diff --git a/doc/classes/OccluderPolygon2D.xml b/doc/classes/OccluderPolygon2D.xml
index 99c1536ddf..e86aa999ad 100644
--- a/doc/classes/OccluderPolygon2D.xml
+++ b/doc/classes/OccluderPolygon2D.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="OccluderPolygon2D" inherits="Resource" category="Core" version="3.0.alpha.custom_build">
+<class name="OccluderPolygon2D" inherits="Resource" category="Core" version="3.0-alpha">
<brief_description>
+ Defines a 2D polygon for LightOccluder2D.
</brief_description>
<description>
+ Editor facility that helps you draw a 2D polygon used as resource for [LightOccluder2D].
</description>
<tutorials>
</tutorials>
@@ -54,18 +56,24 @@
</methods>
<members>
<member name="closed" type="bool" setter="set_closed" getter="is_closed">
+ If [code]true[/code] closes the polygon. A closed OccluderPolygon2D occludes the light coming from any direction. An opened OccluderPolygon2D occludes the light only at its outline's direction. Default value [code]true[/code].
</member>
<member name="cull_mode" type="int" setter="set_cull_mode" getter="get_cull_mode" enum="OccluderPolygon2D.CullMode">
+ Set the direction of the occlusion culling when not [code]CULL_DISABLED[/code]. Default value [code]DISABLED[/code].
</member>
<member name="polygon" type="PoolVector2Array" setter="set_polygon" getter="get_polygon">
+ A [Vector2] array with the index for polygon's vertices positions.
</member>
</members>
<constants>
<constant name="CULL_DISABLED" value="0">
+ Culling mode for the occlusion. Disabled means no culling. See [member cull_mode].
</constant>
<constant name="CULL_CLOCKWISE" value="1">
+ Culling mode for the occlusion. Sets the culling to be in clockwise direction. See [member cull_mode].
</constant>
<constant name="CULL_COUNTER_CLOCKWISE" value="2">
+ Culling mode for the occlusion. Sets the culling to be in counter clockwise direction. See [member cull_mode].
</constant>
</constants>
</class>
diff --git a/doc/classes/OmniLight.xml b/doc/classes/OmniLight.xml
index cb8e756a4c..7c8b1d4756 100644
--- a/doc/classes/OmniLight.xml
+++ b/doc/classes/OmniLight.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="OmniLight" inherits="Light" category="Core" version="3.0.alpha.custom_build">
+<class name="OmniLight" inherits="Light" category="Core" version="3.0-alpha">
<brief_description>
OmniDirectional Light, such as a light bulb or a candle.
</brief_description>
diff --git a/doc/classes/OptionButton.xml b/doc/classes/OptionButton.xml
index abb0dc4f2d..e08b5cac16 100644
--- a/doc/classes/OptionButton.xml
+++ b/doc/classes/OptionButton.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="OptionButton" inherits="Button" category="Core" version="3.0.alpha.custom_build">
+<class name="OptionButton" inherits="Button" category="Core" version="3.0-alpha">
<brief_description>
Button control that provides selectable options when pressed.
</brief_description>
@@ -46,7 +46,7 @@
<return type="void">
</return>
<description>
- Clear all the items in the [OptionButton].
+ Clear all the items in the [code]OptionButton[/code].
</description>
</method>
<method name="get_item_count" qualifiers="const">
diff --git a/doc/classes/PCKPacker.xml b/doc/classes/PCKPacker.xml
index cf8efdf6be..4677c15b7b 100644
--- a/doc/classes/PCKPacker.xml
+++ b/doc/classes/PCKPacker.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="PCKPacker" inherits="Reference" category="Core" version="3.0.alpha.custom_build">
+<class name="PCKPacker" inherits="Reference" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/PHashTranslation.xml b/doc/classes/PHashTranslation.xml
index b25ddcbf22..c74cc8793f 100644
--- a/doc/classes/PHashTranslation.xml
+++ b/doc/classes/PHashTranslation.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="PHashTranslation" inherits="Translation" category="Core" version="3.0.alpha.custom_build">
+<class name="PHashTranslation" inherits="Translation" category="Core" version="3.0-alpha">
<brief_description>
Optimized translation.
</brief_description>
diff --git a/doc/classes/PackedDataContainer.xml b/doc/classes/PackedDataContainer.xml
index 660a39f210..6e660b983a 100644
--- a/doc/classes/PackedDataContainer.xml
+++ b/doc/classes/PackedDataContainer.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="PackedDataContainer" inherits="Resource" category="Core" version="3.0.alpha.custom_build">
+<class name="PackedDataContainer" inherits="Resource" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/PackedDataContainerRef.xml b/doc/classes/PackedDataContainerRef.xml
index 413cd4468b..9d44307afe 100644
--- a/doc/classes/PackedDataContainerRef.xml
+++ b/doc/classes/PackedDataContainerRef.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="PackedDataContainerRef" inherits="Reference" category="Core" version="3.0.alpha.custom_build">
+<class name="PackedDataContainerRef" inherits="Reference" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/PackedScene.xml b/doc/classes/PackedScene.xml
index b40207229c..a226a2bc28 100644
--- a/doc/classes/PackedScene.xml
+++ b/doc/classes/PackedScene.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="PackedScene" inherits="Resource" category="Core" version="3.0.alpha.custom_build">
+<class name="PackedScene" inherits="Resource" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/PacketPeer.xml b/doc/classes/PacketPeer.xml
index bc15e5fc0c..b99d5dc5e9 100644
--- a/doc/classes/PacketPeer.xml
+++ b/doc/classes/PacketPeer.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="PacketPeer" inherits="Reference" category="Core" version="3.0.alpha.custom_build">
+<class name="PacketPeer" inherits="Reference" category="Core" version="3.0-alpha">
<brief_description>
Abstraction and base class for packet-based protocols.
</brief_description>
diff --git a/doc/classes/PacketPeerStream.xml b/doc/classes/PacketPeerStream.xml
index 531046a4ba..38e2d9c1a1 100644
--- a/doc/classes/PacketPeerStream.xml
+++ b/doc/classes/PacketPeerStream.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="PacketPeerStream" inherits="PacketPeer" category="Core" version="3.0.alpha.custom_build">
+<class name="PacketPeerStream" inherits="PacketPeer" category="Core" version="3.0-alpha">
<brief_description>
Wrapper to use a PacketPeer over a StreamPeer.
</brief_description>
diff --git a/doc/classes/PacketPeerUDP.xml b/doc/classes/PacketPeerUDP.xml
index 9bff0c9b5e..758ad35365 100644
--- a/doc/classes/PacketPeerUDP.xml
+++ b/doc/classes/PacketPeerUDP.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="PacketPeerUDP" inherits="PacketPeer" category="Core" version="3.0.alpha.custom_build">
+<class name="PacketPeerUDP" inherits="PacketPeer" category="Core" version="3.0-alpha">
<brief_description>
UDP packet peer.
</brief_description>
<description>
- UDP packet peer. Can be used to send raw UDP packets as well as [Variant]\ s.
+ UDP packet peer. Can be used to send raw UDP packets as well as [Variant]s.
</description>
<tutorials>
</tutorials>
@@ -15,7 +15,7 @@
<return type="void">
</return>
<description>
- Close the UDP socket the [PacketPeerUDP] is currently listening on.
+ Close the UDP socket the [code]PacketPeerUDP[/code] is currently listening on.
</description>
</method>
<method name="get_packet_ip" qualifiers="const">
@@ -36,7 +36,7 @@
<return type="bool">
</return>
<description>
- Return whether this [PacketPeerUDP] is listening.
+ Return whether this [code]PacketPeerUDP[/code] is listening.
</description>
</method>
<method name="listen">
@@ -49,7 +49,7 @@
<argument index="2" name="recv_buf_size" type="int" default="65536">
</argument>
<description>
- Make this [PacketPeerUDP] listen on the "port" binding to "bind_address" with a buffer size "recv_buf_size".
+ Make this [code]PacketPeerUDP[/code] listen on the "port" binding to "bind_address" with a buffer size "recv_buf_size".
If "bind_address" is set as "*" (default), the peer will listen on all available addresses (both IPv4 and IPv6).
If "bind_address" is set as "0.0.0.0" (for IPv4) or "::" (for IPv6), the peer will listen on all available addresses matching that IP type.
If "bind_address" is set to any valid address (e.g. "192.168.1.101", "::1", etc), the peer will only listen on the interface with that addresses (or fail if no interface with the given address exists).
diff --git a/doc/classes/Panel.xml b/doc/classes/Panel.xml
index 8a57659c0c..28a1e304aa 100644
--- a/doc/classes/Panel.xml
+++ b/doc/classes/Panel.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Panel" inherits="Control" category="Core" version="3.0.alpha.custom_build">
+<class name="Panel" inherits="Control" category="Core" version="3.0-alpha">
<brief_description>
Provides an opaque background for [Control] children.
</brief_description>
diff --git a/doc/classes/PanelContainer.xml b/doc/classes/PanelContainer.xml
index 29d5169b9e..415d71c8e7 100644
--- a/doc/classes/PanelContainer.xml
+++ b/doc/classes/PanelContainer.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="PanelContainer" inherits="Container" category="Core" version="3.0.alpha.custom_build">
+<class name="PanelContainer" inherits="Container" category="Core" version="3.0-alpha">
<brief_description>
Panel container type.
</brief_description>
diff --git a/doc/classes/PanoramaSky.xml b/doc/classes/PanoramaSky.xml
index 81f358461e..7f24bb294b 100644
--- a/doc/classes/PanoramaSky.xml
+++ b/doc/classes/PanoramaSky.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="PanoramaSky" inherits="Sky" category="Core" version="3.0.alpha.custom_build">
+<class name="PanoramaSky" inherits="Sky" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/ParallaxBackground.xml b/doc/classes/ParallaxBackground.xml
index a7d616129a..3186f6b972 100644
--- a/doc/classes/ParallaxBackground.xml
+++ b/doc/classes/ParallaxBackground.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ParallaxBackground" inherits="CanvasLayer" category="Core" version="3.0.alpha.custom_build">
+<class name="ParallaxBackground" inherits="CanvasLayer" category="Core" version="3.0-alpha">
<brief_description>
A node used to create a parallax scrolling background.
</brief_description>
<description>
- A ParallaxBackground will use one or more [ParallaxLayer] nodes to create a parallax scrolling background. Each [ParallaxLayer] can be set to move at different speeds relative to the camera movement, this can be used to create an illusion of depth in a 2D game.
+ A ParallaxBackground uses one or more [ParallaxLayer] child nodes to create a parallax effect. Each [ParallaxLayer] can move at a different speed using [member ParallaxLayer.motion_offset]. This creates an illusion of depth in a 2D game. If not used with a [Camera2D], you must manually calculate the [member scroll_offset].
</description>
<tutorials>
</tutorials>
@@ -108,16 +108,22 @@
</methods>
<members>
<member name="scroll_base_offset" type="Vector2" setter="set_scroll_base_offset" getter="get_scroll_base_offset">
+ Base position offset of all [ParallaxLayer] children.
</member>
<member name="scroll_base_scale" type="Vector2" setter="set_scroll_base_scale" getter="get_scroll_base_scale">
+ Base motion scale of all [ParallaxLayer] children.
</member>
<member name="scroll_ignore_camera_zoom" type="bool" setter="set_ignore_camera_zoom" getter="is_ignore_camera_zoom">
+ If [code]true[/code] elements in [ParallaxLayer] child aren't affected by the zoom level of the camera.
</member>
<member name="scroll_limit_begin" type="Vector2" setter="set_limit_begin" getter="get_limit_begin">
+ Top left limits for scrolling to begin. If the camera is outside of this limit the background will stop scrolling. Must be lower than [member scroll_limit_end] to work.
</member>
<member name="scroll_limit_end" type="Vector2" setter="set_limit_end" getter="get_limit_end">
+ Right bottom limits for scrolling to end. If the camera is outside of this limit the background will stop scrolling. Must be higher than [member scroll_limit_begin] to work.
</member>
<member name="scroll_offset" type="Vector2" setter="set_scroll_offset" getter="get_scroll_offset">
+ The ParallaxBackground's scroll value. Calculated automatically when using a [Camera2D], but can be used to manually manage scrolling when no camera is present.
</member>
</members>
<constants>
diff --git a/doc/classes/ParallaxLayer.xml b/doc/classes/ParallaxLayer.xml
index 6cf5549c8f..784395b1ec 100644
--- a/doc/classes/ParallaxLayer.xml
+++ b/doc/classes/ParallaxLayer.xml
@@ -1,10 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ParallaxLayer" inherits="Node2D" category="Core" version="3.0.alpha.custom_build">
+<class name="ParallaxLayer" inherits="Node2D" category="Core" version="3.0-alpha">
<brief_description>
A parallax scrolling layer to be used with [ParallaxBackground].
</brief_description>
<description>
- A ParallaxLayer must be the child of a [ParallaxBackground] node. All child nodes will be affected by the parallax scrolling of this layer.
+ A ParallaxLayer must be the child of a [ParallaxBackground] node. Each ParallaxLayer can be set to move at different speeds relative to the camera movement or the [member ParallaxBackground.scroll_offset] value.
+ This node's children will be affected by its scroll offset.
</description>
<tutorials>
</tutorials>
@@ -60,10 +61,13 @@
</methods>
<members>
<member name="motion_mirroring" type="Vector2" setter="set_mirroring" getter="get_mirroring">
+ The ParallaxLayer's [Texture] mirroring. Useful for creating an infinite scrolling background. If an axis is set to [code]0[/code] the [Texture] will not be mirrored. Default value: [code](0, 0)[/code].
</member>
<member name="motion_offset" type="Vector2" setter="set_motion_offset" getter="get_motion_offset">
+ The ParallaxLayer's offset relative to the parent ParallaxBackground's [member ParallaxBackground.scroll_offset].
</member>
<member name="motion_scale" type="Vector2" setter="set_motion_scale" getter="get_motion_scale">
+ Multiplies the ParallaxLayer's motion. If an axis is set to [code]0[/code] it will not scroll.
</member>
</members>
<constants>
diff --git a/doc/classes/Particles.xml b/doc/classes/Particles.xml
index e17e60f2bc..9a9279b0a7 100644
--- a/doc/classes/Particles.xml
+++ b/doc/classes/Particles.xml
@@ -1,8 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Particles" inherits="GeometryInstance" category="Core" version="3.0.alpha.custom_build">
+<class name="Particles" inherits="GeometryInstance" category="Core" version="3.0-alpha">
<brief_description>
+ 3D particle emitter.
</brief_description>
<description>
+ 3D particle node used to create a variety of particle systems and effects. [code]Particles[/code] features an emitter that generates some number of particles at a given rate.
+ Use the [code]process_material[/code] property to add a [ParticlesMaterial] to configure particle appearance and behavior. Alternatively, you can add a [ShaderMaterial] which will be applied to all particles.
</description>
<tutorials>
</tutorials>
@@ -10,7 +13,7 @@
</demos>
<methods>
<method name="capture_aabb" qualifiers="const">
- <return type="Rect3">
+ <return type="AABB">
</return>
<description>
</description>
@@ -102,7 +105,7 @@
</description>
</method>
<method name="get_visibility_aabb" qualifiers="const">
- <return type="Rect3">
+ <return type="AABB">
</return>
<description>
</description>
@@ -244,7 +247,7 @@
<method name="set_visibility_aabb">
<return type="void">
</return>
- <argument index="0" name="aabb" type="Rect3">
+ <argument index="0" name="aabb" type="AABB">
</argument>
<description>
</description>
@@ -252,8 +255,10 @@
</methods>
<members>
<member name="amount" type="int" setter="set_amount" getter="get_amount">
+ Number of particles to emit.
</member>
<member name="draw_order" type="int" setter="set_draw_order" getter="get_draw_order" enum="Particles.DrawOrder">
+ Particle draw order. Uses [code]DRAW_ORDER_*[/code] values. Default value: [code]DRAW_ORDER_INDEX[/code].
</member>
<member name="draw_pass_1" type="Mesh" setter="set_draw_pass_mesh" getter="get_draw_pass_mesh">
</member>
@@ -266,36 +271,47 @@
<member name="draw_passes" type="int" setter="set_draw_passes" getter="get_draw_passes">
</member>
<member name="emitting" type="bool" setter="set_emitting" getter="is_emitting">
+ If [code]true[/code] particles are being emitted. Default value: [code]true[/code].
</member>
<member name="explosiveness" type="float" setter="set_explosiveness_ratio" getter="get_explosiveness_ratio">
+ Time ratio between each emission. If [code]0[/code] particles are emitted continuously. If [code]1[/code] all particles are emitted simultaneously. Default value: [code]0[/code].
</member>
<member name="fixed_fps" type="int" setter="set_fixed_fps" getter="get_fixed_fps">
</member>
<member name="fract_delta" type="bool" setter="set_fractional_delta" getter="get_fractional_delta">
</member>
<member name="lifetime" type="float" setter="set_lifetime" getter="get_lifetime">
+ Amount of time each particle will exist. Default value: [code]1[/code].
</member>
<member name="local_coords" type="bool" setter="set_use_local_coordinates" getter="get_use_local_coordinates">
+ If [code]true[/code] particles use the parent node's coordinate space. If [code]false[/code] they use global coordinates. Default value: [code]true[/code].
</member>
<member name="one_shot" type="bool" setter="set_one_shot" getter="get_one_shot">
+ If [code]true[/code] only [code]amount[/code] particles will be emitted. Default value: [code]false[/code].
</member>
<member name="preprocess" type="float" setter="set_pre_process_time" getter="get_pre_process_time">
</member>
<member name="process_material" type="Material" setter="set_process_material" getter="get_process_material">
+ [Material] for processing particles. Can be a [ParticlesMaterial] or a [ShaderMaterial].
</member>
<member name="randomness" type="float" setter="set_randomness_ratio" getter="get_randomness_ratio">
+ Emission randomness ratio. Default value: [code]0[/code].
</member>
<member name="speed_scale" type="float" setter="set_speed_scale" getter="get_speed_scale">
+ Speed scaling ratio. Default value: [code]1[/code].
</member>
- <member name="visibility_aabb" type="Rect3" setter="set_visibility_aabb" getter="get_visibility_aabb">
+ <member name="visibility_aabb" type="AABB" setter="set_visibility_aabb" getter="get_visibility_aabb">
</member>
</members>
<constants>
<constant name="DRAW_ORDER_INDEX" value="0">
+ Particles are drawn in the order emitted.
</constant>
<constant name="DRAW_ORDER_LIFETIME" value="1">
+ Particles are drawn in order of remaining lifetime.
</constant>
<constant name="DRAW_ORDER_VIEW_DEPTH" value="2">
+ Particles are drawn in order of depth.
</constant>
<constant name="MAX_DRAW_PASSES" value="4" enum="">
</constant>
diff --git a/doc/classes/Particles2D.xml b/doc/classes/Particles2D.xml
index d837d6eb62..be69e03d56 100644
--- a/doc/classes/Particles2D.xml
+++ b/doc/classes/Particles2D.xml
@@ -1,10 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Particles2D" inherits="Node2D" category="Core" version="3.0.alpha.custom_build">
+<class name="Particles2D" inherits="Node2D" category="Core" version="3.0-alpha">
<brief_description>
- 2D Particle emitter
+ 2D particle emitter.
</brief_description>
<description>
- Particles2D is a particle system 2D [Node] that is used to simulate several types of particle effects, such as explosions, rain, snow, fireflies, or other magical-like shinny sparkles. Particles are drawn using impostors, and given their dynamic behavior, the user must provide a visibility bounding box (although helpers to create one automatically exist).
+ 2D particle node used to create a variety of particle systems and effects. [code]Particles2D[/code] features an emitter that generates some number of particles at a given rate.
+ Use the [code]process_material[/code] property to add a [ParticlesMaterial] to configure particle appearance and behavior. Alternatively, you can add a [ShaderMaterial] which will be applied to all particles.
</description>
<tutorials>
</tutorials>
@@ -285,46 +286,63 @@
</methods>
<members>
<member name="amount" type="int" setter="set_amount" getter="get_amount">
+ Number of particles emitted in one emission cycle.
</member>
<member name="draw_order" type="int" setter="set_draw_order" getter="get_draw_order" enum="Particles2D.DrawOrder">
+ Particle draw order. Uses [code]DRAW_ORDER_*[/code] values. Default value: [code]DRAW_ORDER_INDEX[/code].
</member>
<member name="emitting" type="bool" setter="set_emitting" getter="is_emitting">
+ If [code]true[/code] particles are being emitted. Default value: [code]true[/code].
</member>
<member name="explosiveness" type="float" setter="set_explosiveness_ratio" getter="get_explosiveness_ratio">
+ How rapidly particles in an emission cycle are emitted. If greater than [code]0[/code], there will be a gap in emissions before the next cycle begins. Default value: [code]0[/code].
</member>
<member name="fixed_fps" type="int" setter="set_fixed_fps" getter="get_fixed_fps">
</member>
<member name="fract_delta" type="bool" setter="set_fractional_delta" getter="get_fractional_delta">
</member>
<member name="h_frames" type="int" setter="set_h_frames" getter="get_h_frames">
+ Number of horizontal frames in [code]texture[/code].
</member>
<member name="lifetime" type="float" setter="set_lifetime" getter="get_lifetime">
+ Amount of time each particle will exist. Default value: [code]1[/code].
</member>
<member name="local_coords" type="bool" setter="set_use_local_coordinates" getter="get_use_local_coordinates">
+ If [code]true[/code] particles use the parent node's coordinate space. If [code]false[/code] they use global coordinates. Default value: [code]true[/code].
</member>
<member name="normal_map" type="Texture" setter="set_normal_map" getter="get_normal_map">
</member>
<member name="one_shot" type="bool" setter="set_one_shot" getter="get_one_shot">
+ If [code]true[/code] only one emission cycle occurs. If set [code]true[/code] during a cycle, emission will stop at the cycle's end. Default value: [code]false[/code].
</member>
<member name="preprocess" type="float" setter="set_pre_process_time" getter="get_pre_process_time">
+ Particle system starts as if it had already run for this many seconds.
</member>
<member name="process_material" type="Material" setter="set_process_material" getter="get_process_material">
+ [Material] for processing particles. Can be a [ParticlesMaterial] or a [ShaderMaterial].
</member>
<member name="randomness" type="float" setter="set_randomness_ratio" getter="get_randomness_ratio">
+ Emission lifetime randomness ratio. Default value: [code]0[/code].
</member>
<member name="speed_scale" type="float" setter="set_speed_scale" getter="get_speed_scale">
+ Particle system's running speed scaling ratio. Default value: [code]1[/code].
</member>
<member name="texture" type="Texture" setter="set_texture" getter="get_texture">
+ Particle texture. If [code]null[/code] particles will be squares.
</member>
<member name="v_frames" type="int" setter="set_v_frames" getter="get_v_frames">
+ Number of vertical frames in [code]texture[/code].
</member>
<member name="visibility_rect" type="Rect2" setter="set_visibility_rect" getter="get_visibility_rect">
+ Editor visibility helper.
</member>
</members>
<constants>
<constant name="DRAW_ORDER_INDEX" value="0">
+ Particles are drawn in the order emitted.
</constant>
<constant name="DRAW_ORDER_LIFETIME" value="1">
+ Particles are drawn in order of remaining lifetime.
</constant>
</constants>
</class>
diff --git a/doc/classes/ParticlesMaterial.xml b/doc/classes/ParticlesMaterial.xml
index 1767a19a9f..2428d1880d 100644
--- a/doc/classes/ParticlesMaterial.xml
+++ b/doc/classes/ParticlesMaterial.xml
@@ -1,8 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ParticlesMaterial" inherits="Material" category="Core" version="3.0.alpha.custom_build">
+<class name="ParticlesMaterial" inherits="Material" category="Core" version="3.0-alpha">
<brief_description>
+ Particle properties for [Particles] and [Particles2D] nodes.
</brief_description>
<description>
+ ParticlesMaterial defines particle properties and behavior. It is used in the [code]process_material[/code] of [Particles] and [Particles2D] emitter nodes.
+ Some of this material's properties are applied to each particle when emitted, while others can have a [CurveTexture] applied to vary values over the lifetime of the particle.
</description>
<tutorials>
</tutorials>
@@ -294,152 +297,217 @@
</methods>
<members>
<member name="angle" type="float" setter="set_param" getter="get_param">
+ Initial rotation applied to each particle.
</member>
<member name="angle_curve" type="Texture" setter="set_param_texture" getter="get_param_texture">
+ Each particle's rotation will be animated along this [CurveTexture].
</member>
<member name="angle_random" type="float" setter="set_param_randomness" getter="get_param_randomness">
+ Rotation randomness ratio. Default value: [code]0[/code].
</member>
<member name="angular_velocity" type="float" setter="set_param" getter="get_param">
+ Initial angular velocity applied to each particle.
</member>
<member name="angular_velocity_curve" type="Texture" setter="set_param_texture" getter="get_param_texture">
+ Each particle's angular velocity will vary along this [CurveTexture].
</member>
<member name="angular_velocity_random" type="float" setter="set_param_randomness" getter="get_param_randomness">
+ Angular velocity randomness ratio. Default value: [code]0[/code].
</member>
<member name="anim_loop" type="bool" setter="set_flag" getter="get_flag">
+ If [code]true[/code] animation will loop. Default value: [code]false[/code].
</member>
<member name="anim_offset" type="float" setter="set_param" getter="get_param">
+ Particle animation offset.
</member>
<member name="anim_offset_curve" type="Texture" setter="set_param_texture" getter="get_param_texture">
+ Each particle's animation offset will vary along this [CurveTexture].
</member>
<member name="anim_offset_random" type="float" setter="set_param_randomness" getter="get_param_randomness">
+ Animation offset randomness ratio. Default value: [code]0[/code].
</member>
<member name="anim_speed" type="float" setter="set_param" getter="get_param">
+ Particle animation speed.
</member>
<member name="anim_speed_curve" type="Texture" setter="set_param_texture" getter="get_param_texture">
+ Each particle's animation speed will vary along this [CurveTexture].
</member>
<member name="anim_speed_random" type="float" setter="set_param_randomness" getter="get_param_randomness">
+ Animation speed randomness ratio. Default value: [code]0[/code].
</member>
<member name="color" type="Color" setter="set_color" getter="get_color">
+ Each particle's initial color. If the [Particle2D]'s [code]texture[/code] is defined, it will be multiplied by this color.
</member>
<member name="color_ramp" type="Texture" setter="set_color_ramp" getter="get_color_ramp">
+ Each particle's color will vary along this [GradientTexture].
</member>
<member name="damping" type="float" setter="set_param" getter="get_param">
+ The rate at which particles lose velocity.
</member>
<member name="damping_curve" type="Texture" setter="set_param_texture" getter="get_param_texture">
+ Damping will vary along this [CurveTexture].
</member>
<member name="damping_random" type="float" setter="set_param_randomness" getter="get_param_randomness">
+ Damping randomness ratio. Default value: [code]0[/code].
</member>
<member name="emission_box_extents" type="Vector3" setter="set_emission_box_extents" getter="get_emission_box_extents">
+ The box's extents if [code]emission_shape[/code] is set to [code]EMISSION_SHAPE_BOX[/code].
</member>
<member name="emission_color_texture" type="Texture" setter="set_emission_color_texture" getter="get_emission_color_texture">
</member>
<member name="emission_normal_texture" type="Texture" setter="set_emission_normal_texture" getter="get_emission_normal_texture">
</member>
<member name="emission_point_count" type="int" setter="set_emission_point_count" getter="get_emission_point_count">
+ The number of emission points if [code]emission_shape[/code] is set to [code]EMISSION_SHAPE_POINTS[/code] or [code]EMISSION_SHAPE_DIRECTED_POINTS[/code].
</member>
<member name="emission_point_texture" type="Texture" setter="set_emission_point_texture" getter="get_emission_point_texture">
</member>
<member name="emission_shape" type="int" setter="set_emission_shape" getter="get_emission_shape" enum="ParticlesMaterial.EmissionShape">
+ Particles will be emitted inside this region. Use [code]EMISSION_SHAPE_*[/code] constants for values. Default value: [code]EMISSION_SHAPE_POINT[/code].
</member>
<member name="emission_sphere_radius" type="float" setter="set_emission_sphere_radius" getter="get_emission_sphere_radius">
+ The sphere's radius if [code]emission_shape[/code] is set to [code]EMISSION_SHAPE_SPHERE[/code].
</member>
<member name="flag_align_y" type="bool" setter="set_flag" getter="get_flag">
</member>
<member name="flag_disable_z" type="bool" setter="set_flag" getter="get_flag">
+ If [code]true[/code] particles will not move on the z axis. Default value: [code]true[/code] for [Particles2D], [code]false[/code] for [Particles].
</member>
<member name="flag_rotate_y" type="bool" setter="set_flag" getter="get_flag">
</member>
<member name="flatness" type="float" setter="set_flatness" getter="get_flatness">
</member>
<member name="gravity" type="Vector3" setter="set_gravity" getter="get_gravity">
+ Gravity applied to every particle. Default value: [code](0, 98, 0)[/code].
</member>
<member name="hue_variation" type="float" setter="set_param" getter="get_param">
+ Initial hue variation applied to each particle.
</member>
<member name="hue_variation_curve" type="Texture" setter="set_param_texture" getter="get_param_texture">
+ Each particle's hue will vary along this [CurveTexture].
</member>
<member name="hue_variation_random" type="float" setter="set_param_randomness" getter="get_param_randomness">
+ Hue variation randomness ratio. Default value: [code]0[/code].
</member>
<member name="initial_velocity" type="float" setter="set_param" getter="get_param">
+ Initial velocity for each particle.
</member>
<member name="initial_velocity_random" type="float" setter="set_param_randomness" getter="get_param_randomness">
+ Initial velocity randomness ratio. Default value: [code]0[/code].
</member>
<member name="linear_accel" type="float" setter="set_param" getter="get_param">
+ Linear acceleration applied to each particle.
</member>
<member name="linear_accel_curve" type="Texture" setter="set_param_texture" getter="get_param_texture">
+ Each particle's linear acceleration will vary along this [CurveTexture].
</member>
<member name="linear_accel_random" type="float" setter="set_param_randomness" getter="get_param_randomness">
+ Linear acceleration randomness ratio. Default value: [code]0[/code].
</member>
<member name="orbit_velocity" type="float" setter="set_param" getter="get_param">
+ Orbital velocity applied to each particle.
</member>
<member name="orbit_velocity_curve" type="Texture" setter="set_param_texture" getter="get_param_texture">
+ Each particle's orbital velocity will vary along this [CurveTexture].
</member>
<member name="orbit_velocity_random" type="float" setter="set_param_randomness" getter="get_param_randomness">
+ Orbital velocity randomness ratio. Default value: [code]0[/code].
</member>
<member name="radial_accel" type="float" setter="set_param" getter="get_param">
+ Linear acceleration applied to each particle.
</member>
<member name="radial_accel_curve" type="Texture" setter="set_param_texture" getter="get_param_texture">
+ Each particle's radial acceleration will vary along this [CurveTexture].
</member>
<member name="radial_accel_random" type="float" setter="set_param_randomness" getter="get_param_randomness">
+ Radial acceleration randomness ratio. Default value: [code]0[/code].
</member>
<member name="scale" type="float" setter="set_param" getter="get_param">
+ Initial scale applied to each particle.
</member>
<member name="scale_curve" type="Texture" setter="set_param_texture" getter="get_param_texture">
+ Each particle's scale will vary along this [CurveTexture].
</member>
<member name="scale_random" type="float" setter="set_param_randomness" getter="get_param_randomness">
+ Scale randomness ratio. Default value: [code]0[/code].
</member>
<member name="spread" type="float" setter="set_spread" getter="get_spread">
+ Each particle's initial direction range from [code]+spread[/code] to [code]-spread[/code] degrees. Default value: [code]45[/code].
</member>
<member name="tangential_accel" type="float" setter="set_param" getter="get_param">
+ Tangential acceleration applied to each particle. Tangential acceleration is perpendicular to the particle's velocity.
</member>
<member name="tangential_accel_curve" type="Texture" setter="set_param_texture" getter="get_param_texture">
+ Each particle's tangential acceleration will vary along this [CurveTexture].
</member>
<member name="tangential_accel_random" type="float" setter="set_param_randomness" getter="get_param_randomness">
+ Tangential acceleration randomness ratio. Default value: [code]0[/code].
</member>
<member name="trail_color_modifier" type="GradientTexture" setter="set_trail_color_modifier" getter="get_trail_color_modifier">
+ Trail particles' color will vary along this [GradientTexture].
</member>
<member name="trail_divisor" type="int" setter="set_trail_divisor" getter="get_trail_divisor">
+ Emitter will emit [code]amount[/code] divided by [code]trail_divisor[/code] particles. The remaining particles will be used as trail(s).
</member>
<member name="trail_size_modifier" type="CurveTexture" setter="set_trail_size_modifier" getter="get_trail_size_modifier">
+ Trail particles' size will vary along this [CurveTexture].
</member>
</members>
<constants>
<constant name="PARAM_INITIAL_LINEAR_VELOCITY" value="0">
+ Use with [method set_param], [method set_param_randomness], and [method set_param_texture] to set initial velocity properties.
</constant>
<constant name="PARAM_ANGULAR_VELOCITY" value="1">
+ Use with [method set_param], [method set_param_randomness], and [method set_param_texture] to set angular velocity properties.
</constant>
<constant name="PARAM_ORBIT_VELOCITY" value="2">
+ Use with [method set_param], [method set_param_randomness], and [method set_param_texture] to set orbital_velocity properties.
</constant>
<constant name="PARAM_LINEAR_ACCEL" value="3">
+ Use with [method set_param], [method set_param_randomness], and [method set_param_texture] to set linear acceleration properties.
</constant>
<constant name="PARAM_RADIAL_ACCEL" value="4">
+ Use with [method set_param], [method set_param_randomness], and [method set_param_texture] to set radial acceleration properties.
</constant>
<constant name="PARAM_TANGENTIAL_ACCEL" value="5">
+ Use with [method set_param], [method set_param_randomness], and [method set_param_texture] to set tangential acceleration properties.
</constant>
<constant name="PARAM_DAMPING" value="6">
+ Use with [method set_param], [method set_param_randomness], and [method set_param_texture] to set damping properties.
</constant>
<constant name="PARAM_ANGLE" value="7">
+ Use with [method set_param], [method set_param_randomness], and [method set_param_texture] to set angle properties.
</constant>
<constant name="PARAM_SCALE" value="8">
+ Use with [method set_param], [method set_param_randomness], and [method set_param_texture] to set scale properties.
</constant>
<constant name="PARAM_HUE_VARIATION" value="9">
+ Use with [method set_param], [method set_param_randomness], and [method set_param_texture] to set hue_variation properties.
</constant>
<constant name="PARAM_ANIM_SPEED" value="10">
+ Use with [method set_param], [method set_param_randomness], and [method set_param_texture] to set animation speed properties.
</constant>
<constant name="PARAM_ANIM_OFFSET" value="11">
+ Use with [method set_param], [method set_param_randomness], and [method set_param_texture] to set animation offset properties.
</constant>
<constant name="PARAM_MAX" value="12">
</constant>
<constant name="FLAG_ALIGN_Y_TO_VELOCITY" value="0">
+ Use with [method set_flag] to set [member flag_align_y].
</constant>
<constant name="FLAG_ROTATE_Y" value="1">
+ Use with [method set_flag] to set [member flag_rotate_y]
</constant>
<constant name="FLAG_MAX" value="4">
</constant>
<constant name="EMISSION_SHAPE_POINT" value="0">
+ All particles will be emitted from a single point.
</constant>
<constant name="EMISSION_SHAPE_SPHERE" value="1">
+ Particles will be emitted in the volume of a sphere.
</constant>
<constant name="EMISSION_SHAPE_BOX" value="2">
+ Particles will be emitted in the volume of a box.
</constant>
<constant name="EMISSION_SHAPE_POINTS" value="3">
</constant>
diff --git a/doc/classes/Path.xml b/doc/classes/Path.xml
index 97543418b9..8138a92dcc 100644
--- a/doc/classes/Path.xml
+++ b/doc/classes/Path.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Path" inherits="Spatial" category="Core" version="3.0.alpha.custom_build">
+<class name="Path" inherits="Spatial" category="Core" version="3.0-alpha">
<brief_description>
Container for a [Curve3D].
</brief_description>
diff --git a/doc/classes/Path2D.xml b/doc/classes/Path2D.xml
index 839e617375..8172fc2c4b 100644
--- a/doc/classes/Path2D.xml
+++ b/doc/classes/Path2D.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Path2D" inherits="Node2D" category="Core" version="3.0.alpha.custom_build">
+<class name="Path2D" inherits="Node2D" category="Core" version="3.0-alpha">
<brief_description>
- Container for a [Curve2D].
+ Contains a [Curve2D] path for [PathFollow2D] nodes to follow.
</brief_description>
<description>
- This class is a container/Node-ification of a [Curve2D], so it can have [Node2D] properties and [Node] info.
+ Can have [PathFollow2D] child-nodes moving along the [Curve2D]. See [PathFollow2D] for more information on this usage.
</description>
<tutorials>
</tutorials>
@@ -30,6 +30,7 @@
</methods>
<members>
<member name="curve" type="Curve2D" setter="set_curve" getter="get_curve">
+ A [Curve2D] describing the path.
</member>
</members>
<constants>
diff --git a/doc/classes/PathFollow.xml b/doc/classes/PathFollow.xml
index 86f55a2aaf..bdf2a082e0 100644
--- a/doc/classes/PathFollow.xml
+++ b/doc/classes/PathFollow.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="PathFollow" inherits="Spatial" category="Core" version="3.0.alpha.custom_build">
+<class name="PathFollow" inherits="Spatial" category="Core" version="3.0-alpha">
<brief_description>
Point sampler for a [Path].
</brief_description>
diff --git a/doc/classes/PathFollow2D.xml b/doc/classes/PathFollow2D.xml
index 850b81c046..01137d01d0 100644
--- a/doc/classes/PathFollow2D.xml
+++ b/doc/classes/PathFollow2D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="PathFollow2D" inherits="Node2D" category="Core" version="3.0.alpha.custom_build">
+<class name="PathFollow2D" inherits="Node2D" category="Core" version="3.0-alpha">
<brief_description>
Point sampler for a [Path2D].
</brief_description>
diff --git a/doc/classes/Performance.xml b/doc/classes/Performance.xml
index 71987ace9e..daf1bd62ed 100644
--- a/doc/classes/Performance.xml
+++ b/doc/classes/Performance.xml
@@ -1,8 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Performance" inherits="Object" category="Core" version="3.0.alpha.custom_build">
+<class name="Performance" inherits="Object" category="Core" version="3.0-alpha">
<brief_description>
+ Exposes performance related data.
</brief_description>
<description>
+ This class provides access to a number of different monitors related to performance, such as memory usage, draw calls, and FPS. These are the same as the values displayed in the [i]Monitor[/i] tab in the editor's [i]Debugger[/i] panel. By using the [method get_monitor] method of this class, you can access this data from your code. Note that a few of these monitors are only available in debug mode and will always return 0 when used in a release build.
+ Many of these monitors are not updated in real-time, so there may be a short delay between changes.
</description>
<tutorials>
</tutorials>
@@ -15,63 +18,93 @@
<argument index="0" name="monitor" type="int" enum="Performance.Monitor">
</argument>
<description>
+ Returns the value of one of the available monitors. You should provide one of this class's constants as the argument, like this:
+ [codeblock]
+ print(Performance.get_monitor(Performance.TIME_FPS)) # Prints the FPS to the console
+ [/codeblock]
</description>
</method>
</methods>
<constants>
<constant name="TIME_FPS" value="0">
+ Frames per second.
</constant>
<constant name="TIME_PROCESS" value="1">
+ Time it took to complete one frame.
</constant>
- <constant name="TIME_FIXED_PROCESS" value="2">
+ <constant name="TIME_PHYSICS_PROCESS" value="2">
+ Time it took to complete one physics frame.
</constant>
<constant name="MEMORY_STATIC" value="3">
+ Static memory currently used, in bytes. Not available in release builds.
</constant>
<constant name="MEMORY_DYNAMIC" value="4">
+ Dynamic memory currently used, in bytes. Not available in release builds.
</constant>
<constant name="MEMORY_STATIC_MAX" value="5">
+ Available static memory. Not available in release builds.
</constant>
<constant name="MEMORY_DYNAMIC_MAX" value="6">
+ Available dynamic memory. Not available in release builds.
</constant>
<constant name="MEMORY_MESSAGE_BUFFER_MAX" value="7">
+ Largest amount of memory the message queue buffer has used, in bytes. The message queue is used for deferred functions calls and notifications.
</constant>
<constant name="OBJECT_COUNT" value="8">
+ Number of objects currently instanced (including nodes).
</constant>
<constant name="OBJECT_RESOURCE_COUNT" value="9">
+ Number of resources currently used.
</constant>
<constant name="OBJECT_NODE_COUNT" value="10">
+ Number of nodes currently instanced. This also includes the root node, as well as any nodes not in the scene tree.
</constant>
<constant name="RENDER_OBJECTS_IN_FRAME" value="11">
+ 3D objects drawn per frame.
</constant>
<constant name="RENDER_VERTICES_IN_FRAME" value="12">
+ Vertices drawn per frame. 3D only.
</constant>
<constant name="RENDER_MATERIAL_CHANGES_IN_FRAME" value="13">
+ Material changes per frame. 3D only
</constant>
<constant name="RENDER_SHADER_CHANGES_IN_FRAME" value="14">
+ Shader changes per frame. 3D only.
</constant>
<constant name="RENDER_SURFACE_CHANGES_IN_FRAME" value="15">
+ Render surface changes per frame. 3D only.
</constant>
<constant name="RENDER_DRAW_CALLS_IN_FRAME" value="16">
- </constant>
- <constant name="RENDER_USAGE_VIDEO_MEM_TOTAL" value="20">
+ Draw calls per frame. 3D only.
</constant>
<constant name="RENDER_VIDEO_MEM_USED" value="17">
+ Video memory used. Includes both texture and vertex memory.
</constant>
<constant name="RENDER_TEXTURE_MEM_USED" value="18">
+ Texture memory used.
</constant>
<constant name="RENDER_VERTEX_MEM_USED" value="19">
+ Vertex memory used.
+ </constant>
+ <constant name="RENDER_USAGE_VIDEO_MEM_TOTAL" value="20">
</constant>
<constant name="PHYSICS_2D_ACTIVE_OBJECTS" value="21">
+ Number of active [RigidBody2D] nodes in the game.
</constant>
<constant name="PHYSICS_2D_COLLISION_PAIRS" value="22">
+ Number of collision pairs in the 2D physics engine.
</constant>
<constant name="PHYSICS_2D_ISLAND_COUNT" value="23">
+ Number of islands in the 2D physics engine.
</constant>
<constant name="PHYSICS_3D_ACTIVE_OBJECTS" value="24">
+ Number of active [RigidBody] and [VehicleBody] nodes in the game.
</constant>
<constant name="PHYSICS_3D_COLLISION_PAIRS" value="25">
+ Number of collision pairs in the 3D physics engine.
</constant>
<constant name="PHYSICS_3D_ISLAND_COUNT" value="26">
+ Number of islands in the 3D physics engine.
</constant>
<constant name="MONITOR_MAX" value="27">
</constant>
diff --git a/doc/classes/Physics2DDirectBodyState.xml b/doc/classes/Physics2DDirectBodyState.xml
index cc68aaab1f..40666d8330 100644
--- a/doc/classes/Physics2DDirectBodyState.xml
+++ b/doc/classes/Physics2DDirectBodyState.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Physics2DDirectBodyState" inherits="Object" category="Core" version="3.0.alpha.custom_build">
+<class name="Physics2DDirectBodyState" inherits="Object" category="Core" version="3.0-alpha">
<brief_description>
Direct access object to a physics body in the [Physics2DServer].
</brief_description>
diff --git a/doc/classes/Physics2DDirectBodyStateSW.xml b/doc/classes/Physics2DDirectBodyStateSW.xml
index c2444d4795..865fb6a347 100644
--- a/doc/classes/Physics2DDirectBodyStateSW.xml
+++ b/doc/classes/Physics2DDirectBodyStateSW.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Physics2DDirectBodyStateSW" inherits="Physics2DDirectBodyState" category="Core" version="3.0.alpha.custom_build">
+<class name="Physics2DDirectBodyStateSW" inherits="Physics2DDirectBodyState" category="Core" version="3.0-alpha">
<brief_description>
Software implementation of [Physics2DDirectBodyState].
</brief_description>
diff --git a/doc/classes/Physics2DDirectSpaceState.xml b/doc/classes/Physics2DDirectSpaceState.xml
index 9399227d27..ca7dbab8b8 100644
--- a/doc/classes/Physics2DDirectSpaceState.xml
+++ b/doc/classes/Physics2DDirectSpaceState.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Physics2DDirectSpaceState" inherits="Object" category="Core" version="3.0.alpha.custom_build">
+<class name="Physics2DDirectSpaceState" inherits="Object" category="Core" version="3.0-alpha">
<brief_description>
Direct access object to a space in the [Physics2DServer].
</brief_description>
@@ -70,7 +70,7 @@
collider_id: Id of the object the point is in.
collider: Object the point is inside of.
rid: [RID] of the object the point is in.
- Additionally, the method can take an array of objects or [RID]\ s that are to be excluded from collisions, a bitmask representing the physics layers to check in, and another bitmask for the types of objects to check (see TYPE_MASK_* constants).
+ Additionally, the method can take an array of objects or [RID]s that are to be excluded from collisions, a bitmask representing the physics layers to check in, and another bitmask for the types of objects to check (see TYPE_MASK_* constants).
</description>
</method>
<method name="intersect_ray">
@@ -96,7 +96,7 @@
collider: Object against which the ray was stopped.
rid: [RID] of the object against which the ray was stopped.
If the ray did not intersect anything, then an empty dictionary (dir.empty()==true) is returned instead.
- Additionally, the method can take an array of objects or [RID]\ s that are to be excluded from collisions, a bitmask representing the physics layers to check in, and another bitmask for the types of objects to check (see TYPE_MASK_* constants).
+ Additionally, the method can take an array of objects or [RID]s that are to be excluded from collisions, a bitmask representing the physics layers to check in, and another bitmask for the types of objects to check (see TYPE_MASK_* constants).
</description>
</method>
<method name="intersect_shape">
@@ -130,11 +130,11 @@
<constant name="TYPE_MASK_CHARACTER_BODY" value="8">
Check for collisions with rigid bodies in character mode.
</constant>
- <constant name="TYPE_MASK_AREA" value="16">
- Check for collisions with areas.
- </constant>
<constant name="TYPE_MASK_COLLISION" value="15">
Check for collisions with any kind of bodies (but not areas).
</constant>
+ <constant name="TYPE_MASK_AREA" value="16">
+ Check for collisions with areas.
+ </constant>
</constants>
</class>
diff --git a/doc/classes/Physics2DServer.xml b/doc/classes/Physics2DServer.xml
index fd093edc84..f3115144fa 100644
--- a/doc/classes/Physics2DServer.xml
+++ b/doc/classes/Physics2DServer.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Physics2DServer" inherits="Object" category="Core" version="3.0.alpha.custom_build">
+<class name="Physics2DServer" inherits="Object" category="Core" version="3.0-alpha">
<brief_description>
Physics 2D Server.
</brief_description>
@@ -21,7 +21,7 @@
<argument index="2" name="transform" type="Transform2D" default="Transform2D( 1, 0, 0, 1, 0, 0 )">
</argument>
<description>
- Add a shape to the area, along with a transform matrix. Shapes are usually referenced by their index, so you should track which shape has a given index.
+ Adds a shape to the area, along with a transform matrix. Shapes are usually referenced by their index, so you should track which shape has a given index.
</description>
</method>
<method name="area_attach_object_instance_id">
@@ -32,7 +32,7 @@
<argument index="1" name="id" type="int">
</argument>
<description>
- Assign the area to a descendant of [Object], so it can exist in the node tree.
+ Assigns the area to a descendant of [Object], so it can exist in the node tree.
</description>
</method>
<method name="area_clear_shapes">
@@ -41,14 +41,14 @@
<argument index="0" name="area" type="RID">
</argument>
<description>
- Remove all shapes from an area. It does not delete the shapes, so they can be reassigned later.
+ Removes all shapes from an area. It does not delete the shapes, so they can be reassigned later.
</description>
</method>
<method name="area_create">
<return type="RID">
</return>
<description>
- Create an [Area2D].
+ Creates an [Area2D].
</description>
</method>
<method name="area_get_object_instance_id" qualifiers="const">
@@ -57,7 +57,7 @@
<argument index="0" name="area" type="RID">
</argument>
<description>
- Get the instance ID of the object the area is assigned to.
+ Gets the instance ID of the object the area is assigned to.
</description>
</method>
<method name="area_get_param" qualifiers="const">
@@ -68,7 +68,7 @@
<argument index="1" name="param" type="int" enum="Physics2DServer.AreaParameter">
</argument>
<description>
- Return an area parameter value.
+ Returns an area parameter value. A list of available parameters is on the AREA_PARAM_* constants.
</description>
</method>
<method name="area_get_shape" qualifiers="const">
@@ -79,7 +79,7 @@
<argument index="1" name="shape_idx" type="int">
</argument>
<description>
- Return the [RID] of the nth shape of an area.
+ Returns the [RID] of the nth shape of an area.
</description>
</method>
<method name="area_get_shape_count" qualifiers="const">
@@ -88,7 +88,7 @@
<argument index="0" name="area" type="RID">
</argument>
<description>
- Return the number of shapes assigned to an area.
+ Returns the number of shapes assigned to an area.
</description>
</method>
<method name="area_get_shape_transform" qualifiers="const">
@@ -99,7 +99,7 @@
<argument index="1" name="shape_idx" type="int">
</argument>
<description>
- Return the transform matrix of a shape within an area.
+ Returns the transform matrix of a shape within an area.
</description>
</method>
<method name="area_get_space" qualifiers="const">
@@ -108,7 +108,7 @@
<argument index="0" name="area" type="RID">
</argument>
<description>
- Return the space assigned to the area.
+ Returns the space assigned to the area.
</description>
</method>
<method name="area_get_space_override_mode" qualifiers="const">
@@ -117,7 +117,7 @@
<argument index="0" name="area" type="RID">
</argument>
<description>
- Return the space override mode for the area.
+ Returns the space override mode for the area.
</description>
</method>
<method name="area_get_transform" qualifiers="const">
@@ -126,7 +126,7 @@
<argument index="0" name="area" type="RID">
</argument>
<description>
- Return the transform matrix for an area.
+ Returns the transform matrix for an area.
</description>
</method>
<method name="area_remove_shape">
@@ -137,7 +137,7 @@
<argument index="1" name="shape_idx" type="int">
</argument>
<description>
- Remove a shape from an area. It does not delete the shape, so it can be reassigned later.
+ Removes a shape from an area. It does not delete the shape, so it can be reassigned later.
</description>
</method>
<method name="area_set_collision_layer">
@@ -148,7 +148,7 @@
<argument index="1" name="layer" type="int">
</argument>
<description>
- Assign the area to one or many physics layers.
+ Assigns the area to one or many physics layers.
</description>
</method>
<method name="area_set_collision_mask">
@@ -159,7 +159,7 @@
<argument index="1" name="mask" type="int">
</argument>
<description>
- Set which physics layers the area will monitor.
+ Sets which physics layers the area will monitor.
</description>
</method>
<method name="area_set_monitor_callback">
@@ -172,7 +172,7 @@
<argument index="2" name="method" type="String">
</argument>
<description>
- Set the function to call when any body/area enters or exits the area. This callback will be called for any object interacting with the area, and takes five parameters:
+ Sets the function to call when any body/area enters or exits the area. This callback will be called for any object interacting with the area, and takes five parameters:
1: AREA_BODY_ADDED or AREA_BODY_REMOVED, depending on whether the object entered or exited the area.
2: [RID] of the object that entered/exited the area.
3: Instance ID of the object that entered/exited the area.
@@ -190,7 +190,7 @@
<argument index="2" name="value" type="Variant">
</argument>
<description>
- Set the value for an area parameter. A list of available parameters is on the AREA_PARAM_* constants.
+ Sets the value for an area parameter. A list of available parameters is on the AREA_PARAM_* constants.
</description>
</method>
<method name="area_set_shape">
@@ -203,7 +203,7 @@
<argument index="2" name="shape" type="RID">
</argument>
<description>
- Substitute a given area shape by another. The old shape is selected by its index, the new one by its [RID].
+ Substitutes a given area shape by another. The old shape is selected by its index, the new one by its [RID].
</description>
</method>
<method name="area_set_shape_disabled">
@@ -216,6 +216,7 @@
<argument index="2" name="disable" type="bool">
</argument>
<description>
+ Disables a given shape in this area if [code]disable is true[/code]
</description>
</method>
<method name="area_set_shape_transform">
@@ -228,7 +229,7 @@
<argument index="2" name="transform" type="Transform2D">
</argument>
<description>
- Set the transform matrix for an area shape.
+ Sets the transform matrix for an area shape.
</description>
</method>
<method name="area_set_space">
@@ -239,7 +240,7 @@
<argument index="1" name="space" type="RID">
</argument>
<description>
- Assign a space to the area.
+ Assigns a space to the area.
</description>
</method>
<method name="area_set_space_override_mode">
@@ -250,7 +251,7 @@
<argument index="1" name="mode" type="int" enum="Physics2DServer.AreaSpaceOverrideMode">
</argument>
<description>
- Set the space override mode for the area. The modes are described in the constants AREA_SPACE_OVERRIDE_*.
+ Sets the space override mode for the area. The modes are described in the constants AREA_SPACE_OVERRIDE_*.
</description>
</method>
<method name="area_set_transform">
@@ -261,7 +262,7 @@
<argument index="1" name="transform" type="Transform2D">
</argument>
<description>
- Set the transform matrix for an area.
+ Sets the transform matrix for an area.
</description>
</method>
<method name="body_add_collision_exception">
@@ -272,7 +273,7 @@
<argument index="1" name="excepted_body" type="RID">
</argument>
<description>
- Add a body to the list of bodies exempt from collisions.
+ Adds a body to the list of bodies exempt from collisions.
</description>
</method>
<method name="body_add_force">
@@ -285,7 +286,7 @@
<argument index="2" name="force" type="Vector2">
</argument>
<description>
- Add a positioned force to the applied force and torque. As with [method body_apply_impulse], both the force and the offset from the body origin are in global coordinates. A force differs from an impulse in that, while the two are forces, the impulse clears itself after being applied.
+ Adds a positioned force to the applied force and torque. As with [method body_apply_impulse], both the force and the offset from the body origin are in global coordinates. A force differs from an impulse in that, while the two are forces, the impulse clears itself after being applied.
</description>
</method>
<method name="body_add_shape">
@@ -298,7 +299,7 @@
<argument index="2" name="transform" type="Transform2D" default="Transform2D( 1, 0, 0, 1, 0, 0 )">
</argument>
<description>
- Add a shape to the body, along with a transform matrix. Shapes are usually referenced by their index, so you should track which shape has a given index.
+ Adds a shape to the body, along with a transform matrix. Shapes are usually referenced by their index, so you should track which shape has a given index.
</description>
</method>
<method name="body_apply_impulse">
@@ -311,7 +312,7 @@
<argument index="2" name="impulse" type="Vector2">
</argument>
<description>
- Add a positioned impulse to the applied force and torque. Both the force and the offset from the body origin are in global coordinates.
+ Adds a positioned impulse to the applied force and torque. Both the force and the offset from the body origin are in global coordinates.
</description>
</method>
<method name="body_attach_object_instance_id">
@@ -322,7 +323,7 @@
<argument index="1" name="id" type="int">
</argument>
<description>
- Assign the area to a descendant of [Object], so it can exist in the node tree.
+ Assigns the area to a descendant of [Object], so it can exist in the node tree.
</description>
</method>
<method name="body_clear_shapes">
@@ -331,18 +332,14 @@
<argument index="0" name="body" type="RID">
</argument>
<description>
- Remove all shapes from a body.
+ Removes all shapes from a body.
</description>
</method>
<method name="body_create">
<return type="RID">
</return>
- <argument index="0" name="mode" type="int" enum="Physics2DServer.BodyMode" default="2">
- </argument>
- <argument index="1" name="init_sleeping" type="bool" default="false">
- </argument>
<description>
- Create a physics body. The first parameter can be any value from constants BODY_MODE*, for the type of body created. Additionally, the body can be created in sleeping state to save processing time.
+ Creates a physics body. The first parameter can be any value from constants BODY_MODE*, for the type of body created. Additionally, the body can be created in sleeping state to save processing time.
</description>
</method>
<method name="body_get_collision_layer" qualifiers="const">
@@ -351,7 +348,7 @@
<argument index="0" name="body" type="RID">
</argument>
<description>
- Return the physics layer or layers a body belongs to.
+ Returns the physics layer or layers a body belongs to.
</description>
</method>
<method name="body_get_collision_mask" qualifiers="const">
@@ -360,7 +357,7 @@
<argument index="0" name="body" type="RID">
</argument>
<description>
- Return the physics layer or layers a body can collide with.
+ Returns the physics layer or layers a body can collide with.
</description>
</method>
<method name="body_get_continuous_collision_detection_mode" qualifiers="const">
@@ -369,7 +366,16 @@
<argument index="0" name="body" type="RID">
</argument>
<description>
- Return the continuous collision detection mode.
+ Returns the continuous collision detection mode.
+ </description>
+ </method>
+ <method name="body_get_direct_state">
+ <return type="Physics2DDirectBodyState">
+ </return>
+ <argument index="0" name="body" type="RID">
+ </argument>
+ <description>
+ Returns the [Physics2DDirectBodyState] of the body.
</description>
</method>
<method name="body_get_max_contacts_reported" qualifiers="const">
@@ -378,7 +384,7 @@
<argument index="0" name="body" type="RID">
</argument>
<description>
- Return the maximum contacts that can be reported. See [method body_set_max_contacts_reported].
+ Returns the maximum contacts that can be reported. See [method body_set_max_contacts_reported].
</description>
</method>
<method name="body_get_mode" qualifiers="const">
@@ -387,7 +393,7 @@
<argument index="0" name="body" type="RID">
</argument>
<description>
- Return the body mode.
+ Returns the body mode.
</description>
</method>
<method name="body_get_object_instance_id" qualifiers="const">
@@ -396,7 +402,7 @@
<argument index="0" name="body" type="RID">
</argument>
<description>
- Get the instance ID of the object the area is assigned to.
+ Gets the instance ID of the object the area is assigned to.
</description>
</method>
<method name="body_get_param" qualifiers="const">
@@ -407,7 +413,7 @@
<argument index="1" name="param" type="int" enum="Physics2DServer.BodyParameter">
</argument>
<description>
- Return the value of a body parameter.
+ Returns the value of a body parameter. A list of available parameters is on the BODY_PARAM_* constants.
</description>
</method>
<method name="body_get_shape" qualifiers="const">
@@ -418,7 +424,7 @@
<argument index="1" name="shape_idx" type="int">
</argument>
<description>
- Return the [RID] of the nth shape of a body.
+ Returns the [RID] of the nth shape of a body.
</description>
</method>
<method name="body_get_shape_count" qualifiers="const">
@@ -427,7 +433,7 @@
<argument index="0" name="body" type="RID">
</argument>
<description>
- Return the number of shapes assigned to a body.
+ Returns the number of shapes assigned to a body.
</description>
</method>
<method name="body_get_shape_metadata" qualifiers="const">
@@ -438,7 +444,7 @@
<argument index="1" name="shape_idx" type="int">
</argument>
<description>
- Return the metadata of a shape of a body.
+ Returns the metadata of a shape of a body.
</description>
</method>
<method name="body_get_shape_transform" qualifiers="const">
@@ -449,7 +455,7 @@
<argument index="1" name="shape_idx" type="int">
</argument>
<description>
- Return the transform matrix of a body shape.
+ Returns the transform matrix of a body shape.
</description>
</method>
<method name="body_get_space" qualifiers="const">
@@ -458,7 +464,7 @@
<argument index="0" name="body" type="RID">
</argument>
<description>
- Return the [RID] of the space assigned to a body.
+ Returns the [RID] of the space assigned to a body.
</description>
</method>
<method name="body_get_state" qualifiers="const">
@@ -469,7 +475,7 @@
<argument index="1" name="state" type="int" enum="Physics2DServer.BodyState">
</argument>
<description>
- Return a body state.
+ Returns a body state.
</description>
</method>
<method name="body_is_omitting_force_integration" qualifiers="const">
@@ -478,7 +484,7 @@
<argument index="0" name="body" type="RID">
</argument>
<description>
- Return whether a body uses a callback function to calculate its own physics (see [method body_set_force_integration_callback]).
+ Returns whether a body uses a callback function to calculate its own physics (see [method body_set_force_integration_callback]).
</description>
</method>
<method name="body_remove_collision_exception">
@@ -489,7 +495,7 @@
<argument index="1" name="excepted_body" type="RID">
</argument>
<description>
- Remove a body from the list of bodies exempt from collisions.
+ Removes a body from the list of bodies exempt from collisions.
</description>
</method>
<method name="body_remove_shape">
@@ -500,7 +506,7 @@
<argument index="1" name="shape_idx" type="int">
</argument>
<description>
- Remove a shape from a body. The shape is not deleted, so it can be reused afterwards.
+ Removes a shape from a body. The shape is not deleted, so it can be reused afterwards.
</description>
</method>
<method name="body_set_axis_velocity">
@@ -511,7 +517,7 @@
<argument index="1" name="axis_velocity" type="Vector2">
</argument>
<description>
- Set an axis velocity. The velocity in the given vector axis will be set as the given vector length. This is useful for jumping behavior.
+ Sets an axis velocity. The velocity in the given vector axis will be set as the given vector length. This is useful for jumping behavior.
</description>
</method>
<method name="body_set_collision_layer">
@@ -522,7 +528,7 @@
<argument index="1" name="layer" type="int">
</argument>
<description>
- Set the physics layer or layers a body belongs to.
+ Sets the physics layer or layers a body belongs to.
</description>
</method>
<method name="body_set_collision_mask">
@@ -533,7 +539,7 @@
<argument index="1" name="mask" type="int">
</argument>
<description>
- Set the physics layer or layers a body can collide with.
+ Sets the physics layer or layers a body can collide with.
</description>
</method>
<method name="body_set_continuous_collision_detection_mode">
@@ -544,7 +550,7 @@
<argument index="1" name="mode" type="int" enum="Physics2DServer.CCDMode">
</argument>
<description>
- Set the continuous collision detection mode from any of the CCD_MODE_* constants.
+ Sets the continuous collision detection mode from any of the CCD_MODE_* constants.
Continuous collision detection tries to predict where a moving body will collide, instead of moving it and correcting its movement if it collided.
</description>
</method>
@@ -560,7 +566,7 @@
<argument index="3" name="userdata" type="Variant" default="null">
</argument>
<description>
- Set the function used to calculate physics for an object, if that object allows it (see [method body_set_omit_force integration]).
+ Sets the function used to calculate physics for an object, if that object allows it (see [method body_set_omit_force integration]).
</description>
</method>
<method name="body_set_max_contacts_reported">
@@ -571,7 +577,7 @@
<argument index="1" name="amount" type="int">
</argument>
<description>
- Set the maximum contacts to report. Bodies can keep a log of the contacts with other bodies, this is enabled by setting the maximum amount of contacts reported to a number greater than 0.
+ Sets the maximum contacts to report. Bodies can keep a log of the contacts with other bodies, this is enabled by setting the maximum amount of contacts reported to a number greater than 0.
</description>
</method>
<method name="body_set_mode">
@@ -582,7 +588,7 @@
<argument index="1" name="mode" type="int" enum="Physics2DServer.BodyMode">
</argument>
<description>
- Set the body mode, from one of the constants BODY_MODE*.
+ Sets the body mode, from one of the constants BODY_MODE*.
</description>
</method>
<method name="body_set_omit_force_integration">
@@ -593,7 +599,7 @@
<argument index="1" name="enable" type="bool">
</argument>
<description>
- Set whether a body uses a callback function to calculate its own physics (see [method body_set_force_integration_callback]).
+ Sets whether a body uses a callback function to calculate its own physics (see [method body_set_force_integration_callback]).
</description>
</method>
<method name="body_set_param">
@@ -606,7 +612,7 @@
<argument index="2" name="value" type="float">
</argument>
<description>
- Set a body parameter (see BODY_PARAM* constants).
+ Sets a body parameter. A list of available parameters is on the BODY_PARAM_* constants.
</description>
</method>
<method name="body_set_shape">
@@ -619,7 +625,7 @@
<argument index="2" name="shape" type="RID">
</argument>
<description>
- Substitute a given body shape by another. The old shape is selected by its index, the new one by its [RID].
+ Substitutes a given body shape by another. The old shape is selected by its index, the new one by its [RID].
</description>
</method>
<method name="body_set_shape_as_one_way_collision">
@@ -632,6 +638,7 @@
<argument index="2" name="enable" type="bool">
</argument>
<description>
+ Enables one way collision on body if [code]enable is true[/code].
</description>
</method>
<method name="body_set_shape_disabled">
@@ -644,6 +651,7 @@
<argument index="2" name="disable" type="bool">
</argument>
<description>
+ Disables shape in body if [code]disable is true[/code].
</description>
</method>
<method name="body_set_shape_metadata">
@@ -656,7 +664,7 @@
<argument index="2" name="metadata" type="Variant">
</argument>
<description>
- Set metadata of a shape within a body. This metadata is different from [method Object.set_meta], and can be retrieved on shape queries.
+ Sets metadata of a shape within a body. This metadata is different from [method Object.set_meta], and can be retrieved on shape queries.
</description>
</method>
<method name="body_set_shape_transform">
@@ -669,7 +677,7 @@
<argument index="2" name="transform" type="Transform2D">
</argument>
<description>
- Set the transform matrix for a body shape.
+ Sets the transform matrix for a body shape.
</description>
</method>
<method name="body_set_space">
@@ -680,7 +688,7 @@
<argument index="1" name="space" type="RID">
</argument>
<description>
- Assign a space to the body (see [method create_space]).
+ Assigns a space to the body (see [method create_space]).
</description>
</method>
<method name="body_set_state">
@@ -693,7 +701,7 @@
<argument index="2" name="value" type="Variant">
</argument>
<description>
- Set a body state (see BODY_STATE* constants).
+ Sets a body state (see BODY_STATE* constants).
</description>
</method>
<method name="body_test_motion">
@@ -710,7 +718,31 @@
<argument index="4" name="result" type="Physics2DTestMotionResult" default="null">
</argument>
<description>
- Return whether a body can move from a given point in a given direction. Apart from the boolean return value, a [Physics2DTestMotionResult] can be passed to return additional information in.
+ Returns whether a body can move from a given point in a given direction. Apart from the boolean return value, a [Physics2DTestMotionResult] can be passed to return additional information in.
+ </description>
+ </method>
+ <method name="capsule_shape_create">
+ <return type="RID">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="circle_shape_create">
+ <return type="RID">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="concave_polygon_shape_create">
+ <return type="RID">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="convex_polygon_shape_create">
+ <return type="RID">
+ </return>
+ <description>
</description>
</method>
<method name="damped_spring_joint_create">
@@ -725,7 +757,7 @@
<argument index="3" name="body_b" type="RID">
</argument>
<description>
- Create a damped spring joint between two bodies. If not specified, the second body is assumed to be the joint itself.
+ Creates a damped spring joint between two bodies. If not specified, the second body is assumed to be the joint itself.
</description>
</method>
<method name="damped_string_joint_get_param" qualifiers="const">
@@ -736,7 +768,7 @@
<argument index="1" name="param" type="int" enum="Physics2DServer.DampedStringParam">
</argument>
<description>
- Return the value of a damped spring joint parameter.
+ Returns the value of a damped spring joint parameter.
</description>
</method>
<method name="damped_string_joint_set_param">
@@ -749,7 +781,7 @@
<argument index="2" name="value" type="float">
</argument>
<description>
- Set a damped spring joint parameter. Parameters are explained in the DAMPED_STRING* constants.
+ Sets a damped spring joint parameter. Parameters are explained in the DAMPED_STRING* constants.
</description>
</method>
<method name="free_rid">
@@ -758,7 +790,7 @@
<argument index="0" name="rid" type="RID">
</argument>
<description>
- Destroy any of the objects created by Physics2DServer. If the [RID] passed is not one of the objects that can be created by Physics2DServer, an error will be sent to the console.
+ Destroys any of the objects created by Physics2DServer. If the [RID] passed is not one of the objects that can be created by Physics2DServer, an error will be sent to the console.
</description>
</method>
<method name="get_process_info">
@@ -767,7 +799,7 @@
<argument index="0" name="process_info" type="int" enum="Physics2DServer.ProcessInfo">
</argument>
<description>
- Return information about the current state of the 2D physics engine. The states are listed under the INFO_* constants.
+ Returns information about the current state of the 2D physics engine. The states are listed under the INFO_* constants.
</description>
</method>
<method name="groove_joint_create">
@@ -784,7 +816,7 @@
<argument index="4" name="body_b" type="RID">
</argument>
<description>
- Create a groove joint between two bodies. If not specified, the bodyies are assumed to be the joint itself.
+ Creates a groove joint between two bodies. If not specified, the bodyies are assumed to be the joint itself.
</description>
</method>
<method name="joint_get_param" qualifiers="const">
@@ -795,7 +827,7 @@
<argument index="1" name="param" type="int" enum="Physics2DServer.JointParam">
</argument>
<description>
- Return the value of a joint parameter.
+ Returns the value of a joint parameter.
</description>
</method>
<method name="joint_get_type" qualifiers="const">
@@ -804,7 +836,7 @@
<argument index="0" name="joint" type="RID">
</argument>
<description>
- Return the type of a joint (see JOINT_* constants).
+ Returns the type of a joint (see JOINT_* constants).
</description>
</method>
<method name="joint_set_param">
@@ -817,7 +849,13 @@
<argument index="2" name="value" type="float">
</argument>
<description>
- Set a joint parameter. Parameters are explained in the JOINT_PARAM* constants.
+ Sets a joint parameter. Parameters are explained in the JOINT_PARAM* constants.
+ </description>
+ </method>
+ <method name="line_shape_create">
+ <return type="RID">
+ </return>
+ <description>
</description>
</method>
<method name="pin_joint_create">
@@ -830,25 +868,34 @@
<argument index="2" name="body_b" type="RID">
</argument>
<description>
- Create a pin joint between two bodies. If not specified, the second body is assumed to be the joint itself.
+ Creates a pin joint between two bodies. If not specified, the second body is assumed to be the joint itself.
</description>
</method>
- <method name="set_active">
- <return type="void">
+ <method name="ray_shape_create">
+ <return type="RID">
</return>
- <argument index="0" name="active" type="bool">
- </argument>
<description>
- Activate or deactivate the 2D physics engine.
</description>
</method>
- <method name="shape_create">
+ <method name="rectangle_shape_create">
<return type="RID">
</return>
- <argument index="0" name="type" type="int" enum="Physics2DServer.ShapeType">
+ <description>
+ </description>
+ </method>
+ <method name="segment_shape_create">
+ <return type="RID">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="set_active">
+ <return type="void">
+ </return>
+ <argument index="0" name="active" type="bool">
</argument>
<description>
- Create a shape of type SHAPE_*. Does not assign it to a body or an area. To do so, you must use [method area_set_shape] or [method body_set_shape].
+ Activates or deactivates the 2D physics engine.
</description>
</method>
<method name="shape_get_data" qualifiers="const">
@@ -857,7 +904,7 @@
<argument index="0" name="shape" type="RID">
</argument>
<description>
- Return the shape data.
+ Returns the shape data.
</description>
</method>
<method name="shape_get_type" qualifiers="const">
@@ -866,7 +913,7 @@
<argument index="0" name="shape" type="RID">
</argument>
<description>
- Return the type of shape (see SHAPE_* constants).
+ Returns the type of shape (see SHAPE_* constants).
</description>
</method>
<method name="shape_set_data">
@@ -877,14 +924,14 @@
<argument index="1" name="data" type="Variant">
</argument>
<description>
- Set the shape data that defines its shape and size. The data to be passed depends on the kind of shape created [method shape_get_type].
+ Sets the shape data that defines its shape and size. The data to be passed depends on the kind of shape created [method shape_get_type].
</description>
</method>
<method name="space_create">
<return type="RID">
</return>
<description>
- Create a space. A space is a collection of parameters for the physics engine that can be assigned to an area or a body. It can be assigned to an area with [method area_set_space], or to a body with [method body_set_space].
+ Creates a space. A space is a collection of parameters for the physics engine that can be assigned to an area or a body. It can be assigned to an area with [method area_set_space], or to a body with [method body_set_space].
</description>
</method>
<method name="space_get_direct_state">
@@ -893,7 +940,7 @@
<argument index="0" name="space" type="RID">
</argument>
<description>
- Return the state of a space, a [Physics2DDirectSpaceState]. This object can be used to make collision/intersection queries.
+ Returns the state of a space, a [Physics2DDirectSpaceState]. This object can be used to make collision/intersection queries.
</description>
</method>
<method name="space_get_param" qualifiers="const">
@@ -904,7 +951,7 @@
<argument index="1" name="param" type="int" enum="Physics2DServer.SpaceParameter">
</argument>
<description>
- Return the value of a space parameter.
+ Returns the value of a space parameter.
</description>
</method>
<method name="space_is_active" qualifiers="const">
@@ -913,7 +960,7 @@
<argument index="0" name="space" type="RID">
</argument>
<description>
- Return whether the space is active.
+ Returns whether the space is active.
</description>
</method>
<method name="space_set_active">
@@ -924,7 +971,7 @@
<argument index="1" name="active" type="bool">
</argument>
<description>
- Mark a space as active. It will not have an effect, unless it is assigned to an area or body.
+ Marks a space as active. It will not have an effect, unless it is assigned to an area or body.
</description>
</method>
<method name="space_set_param">
@@ -937,7 +984,7 @@
<argument index="2" name="value" type="float">
</argument>
<description>
- Set the value for a space parameter. A list of available parameters is on the SPACE_PARAM_* constants.
+ Sets the value for a space parameter. A list of available parameters is on the SPACE_PARAM_* constants.
</description>
</method>
</methods>
@@ -952,8 +999,10 @@
Constant to set/get the maximum distance a shape can penetrate another shape before it is considered a collision.
</constant>
<constant name="SPACE_PARAM_BODY_LINEAR_VELOCITY_SLEEP_THRESHOLD" value="3">
+ Constant to set/get the threshold linear velocity of activity. A body marked as potentially inactive for both linear and angular velocity will be put to sleep after the time given.
</constant>
<constant name="SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_THRESHOLD" value="4">
+ Constant to set/get the threshold angular velocity of activity. A body marked as potentially inactive for both linear and angular velocity will be put to sleep after the time given.
</constant>
<constant name="SPACE_PARAM_BODY_TIME_TO_SLEEP" value="5">
Constant to set/get the maximum time of activity. A body marked as potentially inactive for both linear and angular velocity will be put to sleep after this time.
@@ -964,6 +1013,8 @@
<constant name="SHAPE_LINE" value="0">
This is the constant for creating line shapes. A line shape is an infinite line with an origin point, and a normal. Thus, it can be used for front/behind checks.
</constant>
+ <constant name="SHAPE_RAY" value="1">
+ </constant>
<constant name="SHAPE_SEGMENT" value="2">
This is the constant for creating segment shapes. A segment shape is a line from a point A to a point B. It can be checked for intersections.
</constant>
@@ -977,7 +1028,7 @@
This is the constant for creating capsule shapes. A capsule shape is defined by a radius and a length. It can be used for intersections and inside/outside checks.
</constant>
<constant name="SHAPE_CONVEX_POLYGON" value="6">
- This is the constant for creating convex polygon shapes. A polygon is defined by a list of points. It can be used for intersections and inside/outside checks. Unlike the method [method CollisionPolygon2D.set_polygon], polygons modified with [method shape_set_data] do not verify that the points supplied form, in fact, a convex polygon.
+ This is the constant for creating convex polygon shapes. A polygon is defined by a list of points. It can be used for intersections and inside/outside checks. Unlike the method [method CollisionPolygon2D.set_polygon], polygons modified with [method shape_set_data] do not verify that the points supplied form is a convex polygon.
</constant>
<constant name="SHAPE_CONCAVE_POLYGON" value="7">
This is the constant for creating concave polygon shapes. A polygon is defined by a list of points. It can be used for intersections checks, but not for inside/outside checks.
diff --git a/doc/classes/Physics2DServerSW.xml b/doc/classes/Physics2DServerSW.xml
index a8645c0b96..6764f1a4f6 100644
--- a/doc/classes/Physics2DServerSW.xml
+++ b/doc/classes/Physics2DServerSW.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Physics2DServerSW" inherits="Physics2DServer" category="Core" version="3.0.alpha.custom_build">
+<class name="Physics2DServerSW" inherits="Physics2DServer" category="Core" version="3.0-alpha">
<brief_description>
Software implementation of [Physics2DServer].
</brief_description>
<description>
- Software implementation of [Physics2DServer]. This class exposes no new methods or properties and should not be used, as [Physics2DServer] automatically selects the best implementation available.
+ This class exposes no new methods or properties and should not be used, as [Physics2DServer] automatically selects the best implementation available.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/Physics2DShapeQueryParameters.xml b/doc/classes/Physics2DShapeQueryParameters.xml
index 78d12e0b73..829aec7a25 100644
--- a/doc/classes/Physics2DShapeQueryParameters.xml
+++ b/doc/classes/Physics2DShapeQueryParameters.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Physics2DShapeQueryParameters" inherits="Reference" category="Core" version="3.0.alpha.custom_build">
+<class name="Physics2DShapeQueryParameters" inherits="Reference" category="Core" version="3.0-alpha">
<brief_description>
Parameters to be sent to a 2D shape physics query.
</brief_description>
@@ -22,7 +22,7 @@
<return type="Array">
</return>
<description>
- Return the list of objects, or object [RID]\ s, that will be excluded from collisions.
+ Return the list of objects, or object [RID]s, that will be excluded from collisions.
</description>
</method>
<method name="get_margin" qualifiers="const">
@@ -75,7 +75,7 @@
<argument index="0" name="exclude" type="Array">
</argument>
<description>
- Set the list of objects, or object [RID]\ s, that will be excluded from collisions.
+ Set the list of objects, or object [RID]s, that will be excluded from collisions.
</description>
</method>
<method name="set_margin">
@@ -129,7 +129,7 @@
<argument index="0" name="transform" type="Transform2D">
</argument>
<description>
- Set the transormation matrix of the shape. This is necessary to set its position/rotation/scale.
+ Set the transformation matrix of the shape. This is necessary to set its position/rotation/scale.
</description>
</method>
</methods>
diff --git a/doc/classes/Physics2DShapeQueryResult.xml b/doc/classes/Physics2DShapeQueryResult.xml
index 9786a6aa75..d5a29e79fa 100644
--- a/doc/classes/Physics2DShapeQueryResult.xml
+++ b/doc/classes/Physics2DShapeQueryResult.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Physics2DShapeQueryResult" inherits="Reference" category="Core" version="3.0.alpha.custom_build">
+<class name="Physics2DShapeQueryResult" inherits="Reference" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/Physics2DTestMotionResult.xml b/doc/classes/Physics2DTestMotionResult.xml
index a71d58faa7..6bc4849184 100644
--- a/doc/classes/Physics2DTestMotionResult.xml
+++ b/doc/classes/Physics2DTestMotionResult.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Physics2DTestMotionResult" inherits="Reference" category="Core" version="3.0.alpha.custom_build">
+<class name="Physics2DTestMotionResult" inherits="Reference" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/PhysicsBody.xml b/doc/classes/PhysicsBody.xml
index e75fbb8e2d..579a074731 100644
--- a/doc/classes/PhysicsBody.xml
+++ b/doc/classes/PhysicsBody.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="PhysicsBody" inherits="CollisionObject" category="Core" version="3.0.alpha.custom_build">
+<class name="PhysicsBody" inherits="CollisionObject" category="Core" version="3.0-alpha">
<brief_description>
Base class for all objects affected by physics in 3D space.
</brief_description>
diff --git a/doc/classes/PhysicsBody2D.xml b/doc/classes/PhysicsBody2D.xml
index 748506baa9..bf341692bf 100644
--- a/doc/classes/PhysicsBody2D.xml
+++ b/doc/classes/PhysicsBody2D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="PhysicsBody2D" inherits="CollisionObject2D" category="Core" version="3.0.alpha.custom_build">
+<class name="PhysicsBody2D" inherits="CollisionObject2D" category="Core" version="3.0-alpha">
<brief_description>
Base class for all objects affected by physics in 2D space.
</brief_description>
diff --git a/doc/classes/PhysicsDirectBodyState.xml b/doc/classes/PhysicsDirectBodyState.xml
index 349b7e7c3f..33dafa29f6 100644
--- a/doc/classes/PhysicsDirectBodyState.xml
+++ b/doc/classes/PhysicsDirectBodyState.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="PhysicsDirectBodyState" inherits="Object" category="Core" version="3.0.alpha.custom_build">
+<class name="PhysicsDirectBodyState" inherits="Object" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/PhysicsDirectBodyStateSW.xml b/doc/classes/PhysicsDirectBodyStateSW.xml
deleted file mode 100644
index 6d283f307e..0000000000
--- a/doc/classes/PhysicsDirectBodyStateSW.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<class name="PhysicsDirectBodyStateSW" inherits="PhysicsDirectBodyState" category="Core" version="3.0.alpha.custom_build">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <tutorials>
- </tutorials>
- <demos>
- </demos>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
diff --git a/doc/classes/PhysicsDirectSpaceState.xml b/doc/classes/PhysicsDirectSpaceState.xml
index 1e4354fa7e..b5765b6421 100644
--- a/doc/classes/PhysicsDirectSpaceState.xml
+++ b/doc/classes/PhysicsDirectSpaceState.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="PhysicsDirectSpaceState" inherits="Object" category="Core" version="3.0.alpha.custom_build">
+<class name="PhysicsDirectSpaceState" inherits="Object" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
@@ -73,9 +73,9 @@
</constant>
<constant name="TYPE_MASK_CHARACTER_BODY" value="8">
</constant>
- <constant name="TYPE_MASK_AREA" value="16">
- </constant>
<constant name="TYPE_MASK_COLLISION" value="15">
</constant>
+ <constant name="TYPE_MASK_AREA" value="16">
+ </constant>
</constants>
</class>
diff --git a/doc/classes/PhysicsServer.xml b/doc/classes/PhysicsServer.xml
index 145f5a0163..76dabd12ba 100644
--- a/doc/classes/PhysicsServer.xml
+++ b/doc/classes/PhysicsServer.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="PhysicsServer" inherits="Object" category="Core" version="3.0.alpha.custom_build">
+<class name="PhysicsServer" inherits="Object" category="Core" version="3.0-alpha">
<brief_description>
+ Server interface for low level physics access.
</brief_description>
<description>
+ Everything related to physics in 3D.
</description>
<tutorials>
</tutorials>
@@ -19,6 +21,7 @@
<argument index="2" name="transform" type="Transform" default="Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 )">
</argument>
<description>
+ Adds a shape to the area, along with a transform matrix. Shapes are usually referenced by their index, so you should track which shape has a given index.
</description>
</method>
<method name="area_attach_object_instance_id">
@@ -29,6 +32,7 @@
<argument index="1" name="id" type="int">
</argument>
<description>
+ Assigns the area to a descendant of [Object], so it can exist in the node tree.
</description>
</method>
<method name="area_clear_shapes">
@@ -37,12 +41,14 @@
<argument index="0" name="area" type="RID">
</argument>
<description>
+ Removes all shapes from an area. It does not delete the shapes, so they can be reassigned later.
</description>
</method>
<method name="area_create">
<return type="RID">
</return>
<description>
+ Creates an [Area].
</description>
</method>
<method name="area_get_object_instance_id" qualifiers="const">
@@ -51,6 +57,7 @@
<argument index="0" name="area" type="RID">
</argument>
<description>
+ Gets the instance ID of the object the area is assigned to.
</description>
</method>
<method name="area_get_param" qualifiers="const">
@@ -61,6 +68,7 @@
<argument index="1" name="param" type="int" enum="PhysicsServer.AreaParameter">
</argument>
<description>
+ Returns an area parameter value. A list of available parameters is on the AREA_PARAM_* constants.
</description>
</method>
<method name="area_get_shape" qualifiers="const">
@@ -71,6 +79,7 @@
<argument index="1" name="shape_idx" type="int">
</argument>
<description>
+ Returns the [RID] of the nth shape of an area.
</description>
</method>
<method name="area_get_shape_count" qualifiers="const">
@@ -79,6 +88,7 @@
<argument index="0" name="area" type="RID">
</argument>
<description>
+ Returns the number of shapes assigned to an area.
</description>
</method>
<method name="area_get_shape_transform" qualifiers="const">
@@ -89,6 +99,7 @@
<argument index="1" name="shape_idx" type="int">
</argument>
<description>
+ Returns the transform matrix of a shape within an area.
</description>
</method>
<method name="area_get_space" qualifiers="const">
@@ -97,6 +108,7 @@
<argument index="0" name="area" type="RID">
</argument>
<description>
+ Returns the space assigned to the area.
</description>
</method>
<method name="area_get_space_override_mode" qualifiers="const">
@@ -105,6 +117,7 @@
<argument index="0" name="area" type="RID">
</argument>
<description>
+ Returns the space override mode for the area.
</description>
</method>
<method name="area_get_transform" qualifiers="const">
@@ -113,6 +126,7 @@
<argument index="0" name="area" type="RID">
</argument>
<description>
+ Returns the transform matrix for an area.
</description>
</method>
<method name="area_is_ray_pickable" qualifiers="const">
@@ -121,6 +135,7 @@
<argument index="0" name="area" type="RID">
</argument>
<description>
+ If [code]true[/code] area collides with rays.
</description>
</method>
<method name="area_remove_shape">
@@ -131,6 +146,7 @@
<argument index="1" name="shape_idx" type="int">
</argument>
<description>
+ Removes a shape from an area. It does not delete the shape, so it can be reassigned later.
</description>
</method>
<method name="area_set_collision_layer">
@@ -141,6 +157,7 @@
<argument index="1" name="layer" type="int">
</argument>
<description>
+ Assigns the area to one or many physics layers.
</description>
</method>
<method name="area_set_collision_mask">
@@ -151,6 +168,7 @@
<argument index="1" name="mask" type="int">
</argument>
<description>
+ Sets which physics layers the area will monitor.
</description>
</method>
<method name="area_set_monitor_callback">
@@ -163,6 +181,12 @@
<argument index="2" name="method" type="String">
</argument>
<description>
+ Sets the function to call when any body/area enters or exits the area. This callback will be called for any object interacting with the area, and takes five parameters:
+ 1: AREA_BODY_ADDED or AREA_BODY_REMOVED, depending on whether the object entered or exited the area.
+ 2: [RID] of the object that entered/exited the area.
+ 3: Instance ID of the object that entered/exited the area.
+ 4: The shape index of the object that entered/exited the area.
+ 5: The shape index of the area where the object entered/exited.
</description>
</method>
<method name="area_set_param">
@@ -175,6 +199,7 @@
<argument index="2" name="value" type="Variant">
</argument>
<description>
+ Sets the value for an area parameter. A list of available parameters is on the AREA_PARAM_* constants.
</description>
</method>
<method name="area_set_ray_pickable">
@@ -185,6 +210,7 @@
<argument index="1" name="enable" type="bool">
</argument>
<description>
+ Sets object pickable with rays.
</description>
</method>
<method name="area_set_shape">
@@ -197,6 +223,7 @@
<argument index="2" name="shape" type="RID">
</argument>
<description>
+ Substitutes a given area shape by another. The old shape is selected by its index, the new one by its [RID].
</description>
</method>
<method name="area_set_shape_transform">
@@ -209,6 +236,7 @@
<argument index="2" name="transform" type="Transform">
</argument>
<description>
+ Sets the transform matrix for an area shape.
</description>
</method>
<method name="area_set_space">
@@ -219,6 +247,7 @@
<argument index="1" name="space" type="RID">
</argument>
<description>
+ Assigns a space to the area.
</description>
</method>
<method name="area_set_space_override_mode">
@@ -229,6 +258,7 @@
<argument index="1" name="mode" type="int" enum="PhysicsServer.AreaSpaceOverrideMode">
</argument>
<description>
+ Sets the space override mode for the area. The modes are described in the constants AREA_SPACE_OVERRIDE_*.
</description>
</method>
<method name="area_set_transform">
@@ -239,6 +269,7 @@
<argument index="1" name="transform" type="Transform">
</argument>
<description>
+ Sets the transform matrix for an area.
</description>
</method>
<method name="body_add_collision_exception">
@@ -249,6 +280,7 @@
<argument index="1" name="excepted_body" type="RID">
</argument>
<description>
+ Adds a body to the list of bodies exempt from collisions.
</description>
</method>
<method name="body_add_shape">
@@ -261,6 +293,7 @@
<argument index="2" name="transform" type="Transform" default="Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 )">
</argument>
<description>
+ Adds a shape to the body, along with a transform matrix. Shapes are usually referenced by their index, so you should track which shape has a given index.
</description>
</method>
<method name="body_apply_impulse">
@@ -273,6 +306,7 @@
<argument index="2" name="impulse" type="Vector3">
</argument>
<description>
+ Gives the body a push at a [code]position[/code] in the direction of the [code]impulse[/code].
</description>
</method>
<method name="body_apply_torque_impulse">
@@ -283,6 +317,7 @@
<argument index="1" name="impulse" type="Vector3">
</argument>
<description>
+ Gives the body a push to rotate it.
</description>
</method>
<method name="body_attach_object_instance_id">
@@ -293,6 +328,7 @@
<argument index="1" name="id" type="int">
</argument>
<description>
+ Assigns the area to a descendant of [Object], so it can exist in the node tree.
</description>
</method>
<method name="body_clear_shapes">
@@ -301,6 +337,7 @@
<argument index="0" name="body" type="RID">
</argument>
<description>
+ Removes all shapes from a body.
</description>
</method>
<method name="body_create">
@@ -311,6 +348,7 @@
<argument index="1" name="init_sleeping" type="bool" default="false">
</argument>
<description>
+ Creates a physics body. The first parameter can be any value from constants BODY_MODE*, for the type of body created. Additionally, the body can be created in sleeping state to save processing time.
</description>
</method>
<method name="body_get_axis_lock" qualifiers="const">
@@ -319,6 +357,7 @@
<argument index="0" name="body" type="RID">
</argument>
<description>
+ Gets the information, which Axis is locked if any. The can be any calue from the constants BODY_AXIS_LOCK*
</description>
</method>
<method name="body_get_collision_layer" qualifiers="const">
@@ -327,6 +366,7 @@
<argument index="0" name="body" type="RID">
</argument>
<description>
+ Returns the physics layer or layers a body belongs to.
</description>
</method>
<method name="body_get_collision_mask" qualifiers="const">
@@ -335,6 +375,25 @@
<argument index="0" name="body" type="RID">
</argument>
<description>
+ Returns the physics layer or layers a body can collide with.
+-
+ </description>
+ </method>
+ <method name="body_get_direct_state">
+ <return type="PhysicsDirectBodyState">
+ </return>
+ <argument index="0" name="body" type="RID">
+ </argument>
+ <description>
+ Returns the [PhysicsDirectBodyState] of the body.
+ </description>
+ </method>
+ <method name="body_get_kinematic_safe_margin" qualifiers="const">
+ <return type="float">
+ </return>
+ <argument index="0" name="body" type="RID">
+ </argument>
+ <description>
</description>
</method>
<method name="body_get_max_contacts_reported" qualifiers="const">
@@ -343,6 +402,7 @@
<argument index="0" name="body" type="RID">
</argument>
<description>
+ Returns the maximum contacts that can be reported. See [method body_set_max_contacts_reported].
</description>
</method>
<method name="body_get_mode" qualifiers="const">
@@ -351,6 +411,7 @@
<argument index="0" name="body" type="RID">
</argument>
<description>
+ Returns the body mode.
</description>
</method>
<method name="body_get_object_instance_id" qualifiers="const">
@@ -359,6 +420,7 @@
<argument index="0" name="body" type="RID">
</argument>
<description>
+ Gets the instance ID of the object the area is assigned to.
</description>
</method>
<method name="body_get_param" qualifiers="const">
@@ -369,6 +431,7 @@
<argument index="1" name="param" type="int" enum="PhysicsServer.BodyParameter">
</argument>
<description>
+ Returns the value of a body parameter. A list of available parameters is on the BODY_PARAM_* constants.
</description>
</method>
<method name="body_get_shape" qualifiers="const">
@@ -379,6 +442,7 @@
<argument index="1" name="shape_idx" type="int">
</argument>
<description>
+ Returns the [RID] of the nth shape of a body.
</description>
</method>
<method name="body_get_shape_count" qualifiers="const">
@@ -387,6 +451,7 @@
<argument index="0" name="body" type="RID">
</argument>
<description>
+ Returns the number of shapes assigned to a body.
</description>
</method>
<method name="body_get_shape_transform" qualifiers="const">
@@ -397,6 +462,7 @@
<argument index="1" name="shape_idx" type="int">
</argument>
<description>
+ Returns the transform matrix of a body shape.
</description>
</method>
<method name="body_get_space" qualifiers="const">
@@ -405,6 +471,7 @@
<argument index="0" name="body" type="RID">
</argument>
<description>
+ Returns the [RID] of the space assigned to a body.
</description>
</method>
<method name="body_get_state" qualifiers="const">
@@ -415,6 +482,7 @@
<argument index="1" name="state" type="int" enum="PhysicsServer.BodyState">
</argument>
<description>
+ Returns a body state.
</description>
</method>
<method name="body_is_continuous_collision_detection_enabled" qualifiers="const">
@@ -423,6 +491,7 @@
<argument index="0" name="body" type="RID">
</argument>
<description>
+ If [code]true[/code] the continuous collision detection mode is enabled.
</description>
</method>
<method name="body_is_omitting_force_integration" qualifiers="const">
@@ -431,6 +500,7 @@
<argument index="0" name="body" type="RID">
</argument>
<description>
+ Returns whether a body uses a callback function to calculate its own physics (see [method body_set_force_integration_callback]).
</description>
</method>
<method name="body_is_ray_pickable" qualifiers="const">
@@ -439,6 +509,7 @@
<argument index="0" name="body" type="RID">
</argument>
<description>
+ If [code]true[/code] the body can be detected by rays
</description>
</method>
<method name="body_remove_collision_exception">
@@ -449,6 +520,8 @@
<argument index="1" name="excepted_body" type="RID">
</argument>
<description>
+ Removes a body from the list of bodies exempt from collisions.
+ Continuous collision detection tries to predict where a moving body will collide, instead of moving it and correcting its movement if it collided.
</description>
</method>
<method name="body_remove_shape">
@@ -459,6 +532,7 @@
<argument index="1" name="shape_idx" type="int">
</argument>
<description>
+ Removes a shape from a body. The shape is not deleted, so it can be reused afterwards.
</description>
</method>
<method name="body_set_axis_lock">
@@ -469,6 +543,7 @@
<argument index="1" name="axis" type="int" enum="PhysicsServer.BodyAxisLock">
</argument>
<description>
+ Locks velocity along one axis to 0 and only allows rotation along this axis, can also be set to disabled which disables this functionality.
</description>
</method>
<method name="body_set_axis_velocity">
@@ -479,6 +554,7 @@
<argument index="1" name="axis_velocity" type="Vector3">
</argument>
<description>
+ Sets an axis velocity. The velocity in the given vector axis will be set as the given vector length. This is useful for jumping behavior.
</description>
</method>
<method name="body_set_collision_layer">
@@ -489,6 +565,7 @@
<argument index="1" name="layer" type="int">
</argument>
<description>
+ Sets the physics layer or layers a body belongs to.
</description>
</method>
<method name="body_set_collision_mask">
@@ -499,6 +576,7 @@
<argument index="1" name="mask" type="int">
</argument>
<description>
+ Sets the physics layer or layers a body can collide with.
</description>
</method>
<method name="body_set_enable_continuous_collision_detection">
@@ -509,6 +587,8 @@
<argument index="1" name="enable" type="bool">
</argument>
<description>
+ If [code]true[/code] the continuous collision detection mode is enabled.
+ Continuous collision detection tries to predict where a moving body will collide, instead of moving it and correcting its movement if it collided.
</description>
</method>
<method name="body_set_force_integration_callback">
@@ -523,6 +603,17 @@
<argument index="3" name="userdata" type="Variant" default="null">
</argument>
<description>
+ Sets the function used to calculate physics for an object, if that object allows it (see [method body_set_omit_force integration]).
+ </description>
+ </method>
+ <method name="body_set_kinematic_safe_margin">
+ <return type="void">
+ </return>
+ <argument index="0" name="body" type="RID">
+ </argument>
+ <argument index="1" name="margin" type="float">
+ </argument>
+ <description>
</description>
</method>
<method name="body_set_max_contacts_reported">
@@ -533,6 +624,7 @@
<argument index="1" name="amount" type="int">
</argument>
<description>
+ Sets the maximum contacts to report. Bodies can keep a log of the contacts with other bodies, this is enabled by setting the maximum amount of contacts reported to a number greater than 0.
</description>
</method>
<method name="body_set_mode">
@@ -543,6 +635,7 @@
<argument index="1" name="mode" type="int" enum="PhysicsServer.BodyMode">
</argument>
<description>
+ Sets the body mode, from one of the constants BODY_MODE*.
</description>
</method>
<method name="body_set_omit_force_integration">
@@ -553,6 +646,7 @@
<argument index="1" name="enable" type="bool">
</argument>
<description>
+ Sets whether a body uses a callback function to calculate its own physics (see [method body_set_force_integration_callback]).
</description>
</method>
<method name="body_set_param">
@@ -565,6 +659,7 @@
<argument index="2" name="value" type="float">
</argument>
<description>
+ Sets a body parameter. A list of available parameters is on the BODY_PARAM_* constants.
</description>
</method>
<method name="body_set_ray_pickable">
@@ -575,6 +670,7 @@
<argument index="1" name="enable" type="bool">
</argument>
<description>
+ Sets the body pickable with rays if [code]enabled[/code] is set.
</description>
</method>
<method name="body_set_shape">
@@ -587,6 +683,7 @@
<argument index="2" name="shape" type="RID">
</argument>
<description>
+ Substitutes a given body shape by another. The old shape is selected by its index, the new one by its [RID].
</description>
</method>
<method name="body_set_shape_transform">
@@ -599,6 +696,7 @@
<argument index="2" name="transform" type="Transform">
</argument>
<description>
+ Sets the transform matrix for a body shape.
</description>
</method>
<method name="body_set_space">
@@ -609,6 +707,7 @@
<argument index="1" name="space" type="RID">
</argument>
<description>
+ Assigns a space to the body (see [method create_space]).
</description>
</method>
<method name="body_set_state">
@@ -621,6 +720,7 @@
<argument index="2" name="value" type="Variant">
</argument>
<description>
+ Sets a body state (see BODY_STATE* constants).
</description>
</method>
<method name="cone_twist_joint_get_param" qualifiers="const">
@@ -631,6 +731,7 @@
<argument index="1" name="param" type="int" enum="PhysicsServer.ConeTwistJointParam">
</argument>
<description>
+ Gets a cone_twist_joint parameter (see CONE_TWIST_JOINT* constants).
</description>
</method>
<method name="cone_twist_joint_set_param">
@@ -643,6 +744,7 @@
<argument index="2" name="value" type="float">
</argument>
<description>
+ Sets a cone_twist_joint parameter (see CONE_TWIST_JOINT* constants).
</description>
</method>
<method name="free_rid">
@@ -651,6 +753,7 @@
<argument index="0" name="rid" type="RID">
</argument>
<description>
+ Destroys any of the objects created by PhysicsServer. If the [RID] passed is not one of the objects that can be created by PhysicsServer, an error will be sent to the console.
</description>
</method>
<method name="generic_6dof_joint_get_flag">
@@ -663,6 +766,7 @@
<argument index="2" name="flag" type="int" enum="PhysicsServer.G6DOFJointAxisFlag">
</argument>
<description>
+ Gets a generic_6_DOF_joint flag (see G6DOF_JOINT_FLAG* constants).
</description>
</method>
<method name="generic_6dof_joint_get_param">
@@ -675,6 +779,7 @@
<argument index="2" name="param" type="int" enum="PhysicsServer.G6DOFJointAxisParam">
</argument>
<description>
+ Gets a generic_6_DOF_joint parameter (see G6DOF_JOINT* constants without the G6DOF_JOINT_FLAG*).
</description>
</method>
<method name="generic_6dof_joint_set_flag">
@@ -689,6 +794,7 @@
<argument index="3" name="enable" type="bool">
</argument>
<description>
+ Sets a generic_6_DOF_joint flag (see G6DOF_JOINT_FLAG* constants).
</description>
</method>
<method name="generic_6dof_joint_set_param">
@@ -703,6 +809,7 @@
<argument index="3" name="value" type="float">
</argument>
<description>
+ Sets a generic_6_DOF_joint parameter (see G6DOF_JOINT* constants without the G6DOF_JOINT_FLAG*).
</description>
</method>
<method name="get_process_info">
@@ -711,6 +818,7 @@
<argument index="0" name="process_info" type="int" enum="PhysicsServer.ProcessInfo">
</argument>
<description>
+ Returns an Info defined by the [ProcessInfo] input given.
</description>
</method>
<method name="hinge_joint_get_flag" qualifiers="const">
@@ -721,6 +829,7 @@
<argument index="1" name="flag" type="int" enum="PhysicsServer.HingeJointFlag">
</argument>
<description>
+ Gets a hinge_joint flag (see HINGE_JOINT_FLAG* constants).
</description>
</method>
<method name="hinge_joint_get_param" qualifiers="const">
@@ -731,6 +840,7 @@
<argument index="1" name="param" type="int" enum="PhysicsServer.HingeJointParam">
</argument>
<description>
+ Gets a hinge_joint parameter (see HINGE_JOINT* constants without the HINGE_JOINT_FLAG*).
</description>
</method>
<method name="hinge_joint_set_flag">
@@ -743,6 +853,7 @@
<argument index="2" name="enabled" type="bool">
</argument>
<description>
+ Sets a hinge_joint flag (see HINGE_JOINT_FLAG* constants).
</description>
</method>
<method name="hinge_joint_set_param">
@@ -755,6 +866,7 @@
<argument index="2" name="value" type="float">
</argument>
<description>
+ Sets a hinge_joint parameter (see HINGE_JOINT* constants without the HINGE_JOINT_FLAG*).
</description>
</method>
<method name="joint_create_cone_twist">
@@ -769,6 +881,7 @@
<argument index="3" name="local_ref_B" type="Transform">
</argument>
<description>
+ Creates a [ConeTwistJoint].
</description>
</method>
<method name="joint_create_generic_6dof">
@@ -783,6 +896,7 @@
<argument index="3" name="local_ref_B" type="Transform">
</argument>
<description>
+ Creates a [Generic6DOFJoint].
</description>
</method>
<method name="joint_create_hinge">
@@ -797,6 +911,7 @@
<argument index="3" name="hinge_B" type="Transform">
</argument>
<description>
+ Creates a [HingeJoint].
</description>
</method>
<method name="joint_create_pin">
@@ -811,6 +926,7 @@
<argument index="3" name="local_B" type="Vector3">
</argument>
<description>
+ Creates a [PinJoint].
</description>
</method>
<method name="joint_create_slider">
@@ -825,6 +941,7 @@
<argument index="3" name="local_ref_B" type="Transform">
</argument>
<description>
+ Creates a [SliderJoint].
</description>
</method>
<method name="joint_get_solver_priority" qualifiers="const">
@@ -833,6 +950,7 @@
<argument index="0" name="joint" type="RID">
</argument>
<description>
+ Gets the priority value of the Joint.
</description>
</method>
<method name="joint_get_type" qualifiers="const">
@@ -841,6 +959,7 @@
<argument index="0" name="joint" type="RID">
</argument>
<description>
+ Returns the type of the Joint.
</description>
</method>
<method name="joint_set_solver_priority">
@@ -851,6 +970,7 @@
<argument index="1" name="priority" type="int">
</argument>
<description>
+ Sets the priority value of the Joint.
</description>
</method>
<method name="pin_joint_get_local_a" qualifiers="const">
@@ -859,6 +979,7 @@
<argument index="0" name="joint" type="RID">
</argument>
<description>
+ Returns position of the joint in the local space of body a of the joint.
</description>
</method>
<method name="pin_joint_get_local_b" qualifiers="const">
@@ -867,6 +988,7 @@
<argument index="0" name="joint" type="RID">
</argument>
<description>
+ Returns position of the joint in the local space of body b of the joint.
</description>
</method>
<method name="pin_joint_get_param" qualifiers="const">
@@ -877,6 +999,7 @@
<argument index="1" name="param" type="int" enum="PhysicsServer.PinJointParam">
</argument>
<description>
+ Gets a pin_joint parameter (see PIN_JOINT* constants).
</description>
</method>
<method name="pin_joint_set_local_a">
@@ -887,6 +1010,7 @@
<argument index="1" name="local_A" type="Vector3">
</argument>
<description>
+ Sets position of the joint in the local space of body a of the joint.
</description>
</method>
<method name="pin_joint_set_local_b">
@@ -897,6 +1021,7 @@
<argument index="1" name="local_B" type="Vector3">
</argument>
<description>
+ Sets position of the joint in the local space of body b of the joint.
</description>
</method>
<method name="pin_joint_set_param">
@@ -909,6 +1034,7 @@
<argument index="2" name="value" type="float">
</argument>
<description>
+ Sets a pin_joint parameter (see PIN_JOINT* constants).
</description>
</method>
<method name="set_active">
@@ -917,6 +1043,7 @@
<argument index="0" name="active" type="bool">
</argument>
<description>
+ Activates or deactivates the 3D physics engine.
</description>
</method>
<method name="shape_create">
@@ -925,6 +1052,7 @@
<argument index="0" name="type" type="int" enum="PhysicsServer.ShapeType">
</argument>
<description>
+ Creates a shape of type SHAPE_*. Does not assign it to a body or an area. To do so, you must use [method area_set_shape] or [method body_set_shape].
</description>
</method>
<method name="shape_get_data" qualifiers="const">
@@ -933,6 +1061,7 @@
<argument index="0" name="shape" type="RID">
</argument>
<description>
+ Returns the shape data.
</description>
</method>
<method name="shape_get_type" qualifiers="const">
@@ -941,6 +1070,7 @@
<argument index="0" name="shape" type="RID">
</argument>
<description>
+ Returns the type of shape (see SHAPE_* constants).
</description>
</method>
<method name="shape_set_data">
@@ -951,6 +1081,7 @@
<argument index="1" name="data" type="Variant">
</argument>
<description>
+ Sets the shape data that defines its shape and size. The data to be passed depends on the kind of shape created [method shape_get_type].
</description>
</method>
<method name="slider_joint_get_param" qualifiers="const">
@@ -961,6 +1092,7 @@
<argument index="1" name="param" type="int" enum="PhysicsServer.SliderJointParam">
</argument>
<description>
+ Gets a slider_joint parameter (see SLIDER_JOINT* constants).
</description>
</method>
<method name="slider_joint_set_param">
@@ -973,12 +1105,14 @@
<argument index="2" name="value" type="float">
</argument>
<description>
+ Gets a slider_joint parameter (see SLIDER_JOINT* constants).
</description>
</method>
<method name="space_create">
<return type="RID">
</return>
<description>
+ Creates a space. A space is a collection of parameters for the physics engine that can be assigned to an area or a body. It can be assigned to an area with [method area_set_space], or to a body with [method body_set_space].
</description>
</method>
<method name="space_get_direct_state">
@@ -987,6 +1121,7 @@
<argument index="0" name="space" type="RID">
</argument>
<description>
+ Returns the state of a space, a [PhysicsDirectSpaceState]. This object can be used to make collision/intersection queries.
</description>
</method>
<method name="space_get_param" qualifiers="const">
@@ -997,6 +1132,7 @@
<argument index="1" name="param" type="int" enum="PhysicsServer.SpaceParameter">
</argument>
<description>
+ Returns the value of a space parameter.
</description>
</method>
<method name="space_is_active" qualifiers="const">
@@ -1005,6 +1141,7 @@
<argument index="0" name="space" type="RID">
</argument>
<description>
+ Returns whether the space is active.
</description>
</method>
<method name="space_set_active">
@@ -1015,6 +1152,7 @@
<argument index="1" name="active" type="bool">
</argument>
<description>
+ Marks a space as active. It will not have an effect, unless it is assigned to an area or body.
</description>
</method>
<method name="space_set_param">
@@ -1027,169 +1165,256 @@
<argument index="2" name="value" type="float">
</argument>
<description>
+ Sets the value for a space parameter. A list of available parameters is on the SPACE_PARAM_* constants.
</description>
</method>
</methods>
<constants>
<constant name="JOINT_PIN" value="0">
+ The [Joint] is a [PinJoint].
</constant>
<constant name="JOINT_HINGE" value="1">
+ The [Joint] is a [HingeJoint].
</constant>
<constant name="JOINT_SLIDER" value="2">
+ The [Joint] is a [SliderJoint].
</constant>
<constant name="JOINT_CONE_TWIST" value="3">
+ The [Joint] is a [ConeTwistJoint].
</constant>
<constant name="JOINT_6DOF" value="4">
+ The [Joint] is a [Generic6DOFJoint].
</constant>
<constant name="PIN_JOINT_BIAS" value="0">
+ The strength with which the pinned objects try to stay in positional relation to each other.
+ The higher, the stronger.
</constant>
<constant name="PIN_JOINT_DAMPING" value="1">
+ The strength with which the pinned objects try to stay in velocity relation to each other.
+ The higher, the stronger.
</constant>
<constant name="PIN_JOINT_IMPULSE_CLAMP" value="2">
+ If above 0, this value is the maximum value for an impulse that this Joint puts on it's ends.
</constant>
<constant name="HINGE_JOINT_BIAS" value="0">
+ The speed with wich the two bodies get pulled together when they move in different directions.
</constant>
<constant name="HINGE_JOINT_LIMIT_UPPER" value="1">
+ The maximum rotation across the Hinge.
</constant>
<constant name="HINGE_JOINT_LIMIT_LOWER" value="2">
+ The minimum rotation across the Hinge.
</constant>
<constant name="HINGE_JOINT_LIMIT_BIAS" value="3">
+ The speed with which the rotation across the axis perpendicular to the hinge gets corrected.
</constant>
<constant name="HINGE_JOINT_LIMIT_SOFTNESS" value="4">
</constant>
<constant name="HINGE_JOINT_LIMIT_RELAXATION" value="5">
+ The lower this value, the more the rotation gets slowed down.
</constant>
<constant name="HINGE_JOINT_MOTOR_TARGET_VELOCITY" value="6">
+ Target speed for the motor.
</constant>
<constant name="HINGE_JOINT_MOTOR_MAX_IMPULSE" value="7">
+ Maximum acceleration for the motor.
</constant>
<constant name="HINGE_JOINT_FLAG_USE_LIMIT" value="0">
+ If [code]true[/code] the Hinge has a maximum and a minimum rotation.
</constant>
<constant name="HINGE_JOINT_FLAG_ENABLE_MOTOR" value="1">
+ If [code]true[/code] a motor turns the Hinge
</constant>
<constant name="SLIDER_JOINT_LINEAR_LIMIT_UPPER" value="0">
+ The maximum difference between the pivot points on their x-axis before damping happens.
</constant>
<constant name="SLIDER_JOINT_LINEAR_LIMIT_LOWER" value="1">
+ The minimum difference between the pivot points on their x-axis before damping happens.
</constant>
<constant name="SLIDER_JOINT_LINEAR_LIMIT_SOFTNESS" value="2">
+ A factor applied to the movement accross the slider axis once the limits get surpassed. The lower, the slower the movement.
</constant>
<constant name="SLIDER_JOINT_LINEAR_LIMIT_RESTITUTION" value="3">
+ The amount of restitution once the limits are surpassed. The lower, the more velocityenergy gets lost.
</constant>
<constant name="SLIDER_JOINT_LINEAR_LIMIT_DAMPING" value="4">
+ The amount of damping once the slider limits are surpassed.
</constant>
<constant name="SLIDER_JOINT_LINEAR_MOTION_SOFTNESS" value="5">
+ A factor applied to the movement accross the slider axis as long as the slider is in the limits. The lower, the slower the movement.
</constant>
<constant name="SLIDER_JOINT_LINEAR_MOTION_RESTITUTION" value="6">
+ The amount of restitution inside the slider limits.
</constant>
<constant name="SLIDER_JOINT_LINEAR_MOTION_DAMPING" value="7">
+ The amount of damping inside the slider limits.
</constant>
<constant name="SLIDER_JOINT_LINEAR_ORTHOGONAL_SOFTNESS" value="8">
+ A factor applied to the movement accross axes orthogonal to the slider.
</constant>
<constant name="SLIDER_JOINT_LINEAR_ORTHOGONAL_RESTITUTION" value="9">
+ The amount of restitution when movement is accross axes orthogonal to the slider.
</constant>
<constant name="SLIDER_JOINT_LINEAR_ORTHOGONAL_DAMPING" value="10">
+ The amount of damping when movement is accross axes orthogonal to the slider.
</constant>
<constant name="SLIDER_JOINT_ANGULAR_LIMIT_UPPER" value="11">
+ The upper limit of rotation in the slider.
</constant>
<constant name="SLIDER_JOINT_ANGULAR_LIMIT_LOWER" value="12">
+ The lower limit of rotation in the slider.
</constant>
<constant name="SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS" value="13">
+ A factor applied to the all rotation once the limit is surpassed.
</constant>
<constant name="SLIDER_JOINT_ANGULAR_LIMIT_RESTITUTION" value="14">
+ The amount of restitution of the rotation when the limit is surpassed.
</constant>
<constant name="SLIDER_JOINT_ANGULAR_LIMIT_DAMPING" value="15">
+ The amount of damping of the rotation when the limit is surpassed.
</constant>
<constant name="SLIDER_JOINT_ANGULAR_MOTION_SOFTNESS" value="16">
+ A factor that gets applied to the all rotation in the limits.
</constant>
<constant name="SLIDER_JOINT_ANGULAR_MOTION_RESTITUTION" value="17">
+ The amount of restitution of the rotation in the limits.
</constant>
<constant name="SLIDER_JOINT_ANGULAR_MOTION_DAMPING" value="18">
+ The amount of damping of the rotation in the limits.
</constant>
<constant name="SLIDER_JOINT_ANGULAR_ORTHOGONAL_SOFTNESS" value="19">
+ A factor that gets applied to the all rotation across axes orthogonal to the slider.
</constant>
<constant name="SLIDER_JOINT_ANGULAR_ORTHOGONAL_RESTITUTION" value="20">
+ The amount of restitution of the rotation across axes orthogonal to the slider.
</constant>
<constant name="SLIDER_JOINT_ANGULAR_ORTHOGONAL_DAMPING" value="21">
+ The amount of damping of the rotation across axes orthogonal to the slider.
</constant>
<constant name="SLIDER_JOINT_MAX" value="22">
+ End flag of SLIDER_JOINT_* constants, used internally.
</constant>
<constant name="CONE_TWIST_JOINT_SWING_SPAN" value="0">
+ Swing is rotation from side to side, around the axis perpendicular to the twist axis.
+ The swing span defines, how much rotation will not get corrected allong the swing axis.
+ Could be defined as looseness in the [ConeTwistJoint].
+ If below 0.05, this behaviour is locked. Default value: [code]PI/4[/code].
</constant>
<constant name="CONE_TWIST_JOINT_TWIST_SPAN" value="1">
+ Twist is the rotation around the twist axis, this value defined how far the joint can twist.
+ Twist is locked if below 0.05.
</constant>
<constant name="CONE_TWIST_JOINT_BIAS" value="2">
+ The speed with which the swing or twist will take place.
+ The higher, the faster.
</constant>
<constant name="CONE_TWIST_JOINT_SOFTNESS" value="3">
+ The ease with which the Joint twists, if it's too low, it takes more force to twist the joint.
</constant>
<constant name="CONE_TWIST_JOINT_RELAXATION" value="4">
+ Defines, how fast the swing- and twist-speed-difference on both sides gets synced.
</constant>
<constant name="G6DOF_JOINT_LINEAR_LOWER_LIMIT" value="0">
+ The minimum difference between the pivot points' axes.
</constant>
<constant name="G6DOF_JOINT_LINEAR_UPPER_LIMIT" value="1">
+ The maximum difference between the pivot points' axes.
</constant>
<constant name="G6DOF_JOINT_LINEAR_LIMIT_SOFTNESS" value="2">
+ A factor that gets applied to the movement accross the axes. The lower, the slower the movement.
</constant>
<constant name="G6DOF_JOINT_LINEAR_RESTITUTION" value="3">
+ The amount of restitution on the axes movement. The lower, the more velocity-energy gets lost.
</constant>
<constant name="G6DOF_JOINT_LINEAR_DAMPING" value="4">
+ The amount of damping that happens at the linear motion across the axes.
</constant>
<constant name="G6DOF_JOINT_ANGULAR_LOWER_LIMIT" value="5">
+ The minimum rotation in negative direction to break loose and rotate arround the axes.
</constant>
<constant name="G6DOF_JOINT_ANGULAR_UPPER_LIMIT" value="6">
+ The minimum rotation in positive direction to break loose and rotate arround the axes.
</constant>
<constant name="G6DOF_JOINT_ANGULAR_LIMIT_SOFTNESS" value="7">
+ A factor that gets multiplied onto all rotations accross the axes.
</constant>
<constant name="G6DOF_JOINT_ANGULAR_DAMPING" value="8">
+ The amount of rotational damping accross the axes. The lower, the more dampening occurs.
</constant>
<constant name="G6DOF_JOINT_ANGULAR_RESTITUTION" value="9">
+ The amount of rotational restitution accross the axes. The lower, the more restitution occurs.
</constant>
<constant name="G6DOF_JOINT_ANGULAR_FORCE_LIMIT" value="10">
+ The maximum amount of force that can occur, when rotating arround the axes.
</constant>
<constant name="G6DOF_JOINT_ANGULAR_ERP" value="11">
+ When correcting the crossing of limits in rotation accross the axes, this error tolerance factor defines how much the correction gets slowed down. The lower, the slower.
</constant>
<constant name="G6DOF_JOINT_ANGULAR_MOTOR_TARGET_VELOCITY" value="12">
+ Target speed for the motor at the axes.
</constant>
<constant name="G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT" value="13">
+ Maximum acceleration for the motor at the axes.
</constant>
<constant name="G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT" value="0">
+ If [code]set[/code] there is linear motion possible within the given limits.
</constant>
<constant name="G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT" value="1">
+ If [code]set[/code] there is rotational motion possible.
</constant>
<constant name="G6DOF_JOINT_FLAG_ENABLE_MOTOR" value="2">
+ If [code]set[/code] there is a rotational motor across these axes.
</constant>
<constant name="SHAPE_PLANE" value="0">
+ The [Shape] is a [PlaneShape].
</constant>
<constant name="SHAPE_RAY" value="1">
+ The [Shape] is a [RayShape].
</constant>
<constant name="SHAPE_SPHERE" value="2">
+ The [Shape] is a [SphereShape].
</constant>
<constant name="SHAPE_BOX" value="3">
+ The [Shape] is a [BoxShape].
</constant>
<constant name="SHAPE_CAPSULE" value="4">
+ The [Shape] is a [CapsuleShape].
</constant>
<constant name="SHAPE_CONVEX_POLYGON" value="5">
+ The [Shape] is a [ConvexPolygonShape].
</constant>
<constant name="SHAPE_CONCAVE_POLYGON" value="6">
+ The [Shape] is a [ConcavePolygonShape].
</constant>
<constant name="SHAPE_HEIGHTMAP" value="7">
+ The [Shape] is a [HeightMapShape].
</constant>
<constant name="SHAPE_CUSTOM" value="8">
+ This constant is used internally by the engine. Any attempt to create this kind of shape results in an error.
</constant>
<constant name="AREA_PARAM_GRAVITY" value="0">
+ Constant to set/get gravity strength in an area.
</constant>
<constant name="AREA_PARAM_GRAVITY_VECTOR" value="1">
+ Constant to set/get gravity vector/center in an area.
</constant>
<constant name="AREA_PARAM_GRAVITY_IS_POINT" value="2">
+ Constant to set/get whether the gravity vector of an area is a direction, or a center point.
</constant>
<constant name="AREA_PARAM_GRAVITY_DISTANCE_SCALE" value="3">
+ Constant to set/get the falloff factor for point gravity of an area. The greater this value is, the faster the strength of gravity decreases with the square of distance.
</constant>
<constant name="AREA_PARAM_GRAVITY_POINT_ATTENUATION" value="4">
+ This constant was used to set/get the falloff factor for point gravity. It has been superseded by AREA_PARAM_GRAVITY_DISTANCE_SCALE.
</constant>
<constant name="AREA_PARAM_LINEAR_DAMP" value="5">
+ Constant to set/get the linear dampening factor of an area.
</constant>
<constant name="AREA_PARAM_ANGULAR_DAMP" value="6">
+ Constant to set/get the angular dampening factor of an area.
</constant>
<constant name="AREA_PARAM_PRIORITY" value="7">
+ Constant to set/get the priority (order of processing) of an area.
</constant>
<constant name="AREA_SPACE_OVERRIDE_DISABLED" value="0">
This area does not affect gravity/damp. These are generally areas that exist only to detect collisions, and objects entering or exiting them.
@@ -1207,70 +1432,104 @@
This area replaces any gravity/damp calculated so far, but keeps calculating the rest of the areas, down to the default one.
</constant>
<constant name="BODY_MODE_STATIC" value="0">
+ Constant for static bodies.
</constant>
<constant name="BODY_MODE_KINEMATIC" value="1">
+ Constant for kinematic bodies.
</constant>
<constant name="BODY_MODE_RIGID" value="2">
+ Constant for rigid bodies.
+ </constant>
+ <constant name="BODY_MODE_SOFT" value="3">
</constant>
- <constant name="BODY_MODE_CHARACTER" value="3">
+ <constant name="BODY_MODE_CHARACTER" value="4">
+ Constant for rigid bodies in character mode. In this mode, a body can not rotate, and only its linear velocity is affected by physics.
</constant>
<constant name="BODY_PARAM_BOUNCE" value="0">
+ Constant to set/get a body's bounce factor.
</constant>
<constant name="BODY_PARAM_FRICTION" value="1">
+ Constant to set/get a body's friction.
</constant>
<constant name="BODY_PARAM_MASS" value="2">
+ Constant to set/get a body's mass.
</constant>
<constant name="BODY_PARAM_GRAVITY_SCALE" value="3">
- </constant>
- <constant name="BODY_PARAM_ANGULAR_DAMP" value="5">
+ Constant to set/get a body's gravity multiplier.
</constant>
<constant name="BODY_PARAM_LINEAR_DAMP" value="4">
+ Constant to set/get a body's linear dampening factor.
+ </constant>
+ <constant name="BODY_PARAM_ANGULAR_DAMP" value="5">
+ Constant to set/get a body's angular dampening factor.
</constant>
<constant name="BODY_PARAM_MAX" value="6">
+ This is the last ID for body parameters. Any attempt to set this property is ignored. Any attempt to get it returns 0.
</constant>
<constant name="BODY_STATE_TRANSFORM" value="0">
+ Constant to set/get the current transform matrix of the body.
</constant>
<constant name="BODY_STATE_LINEAR_VELOCITY" value="1">
+ Constant to set/get the current linear velocity of the body.
</constant>
<constant name="BODY_STATE_ANGULAR_VELOCITY" value="2">
+ Constant to set/get the current angular velocity of the body.
</constant>
<constant name="BODY_STATE_SLEEPING" value="3">
+ Constant to sleep/wake up a body, or to get whether it is sleeping.
</constant>
<constant name="BODY_STATE_CAN_SLEEP" value="4">
+ Constant to set/get whether the body can sleep.
</constant>
<constant name="AREA_BODY_ADDED" value="0">
+ The value of the first parameter and area callback function receives, when an object enters one of its shapes.
</constant>
<constant name="AREA_BODY_REMOVED" value="1">
+ The value of the first parameter and area callback function receives, when an object exits one of its shapes.
</constant>
<constant name="INFO_ACTIVE_OBJECTS" value="0">
+ Constant to get the number of objects that are not sleeping.
</constant>
<constant name="INFO_COLLISION_PAIRS" value="1">
+ Constant to get the number of possible collisions.
</constant>
<constant name="INFO_ISLAND_COUNT" value="2">
+ Constant to get the number of space regions where a collision could occur.
</constant>
<constant name="SPACE_PARAM_CONTACT_RECYCLE_RADIUS" value="0">
+ Constant to set/get the maximum distance a pair of bodies has to move before their collision status has to be recalculated.
</constant>
<constant name="SPACE_PARAM_CONTACT_MAX_SEPARATION" value="1">
+ Constant to set/get the maximum distance a shape can be from another before they are considered separated.
</constant>
<constant name="SPACE_PARAM_BODY_MAX_ALLOWED_PENETRATION" value="2">
+ Constant to set/get the maximum distance a shape can penetrate another shape before it is considered a collision.
</constant>
<constant name="SPACE_PARAM_BODY_LINEAR_VELOCITY_SLEEP_THRESHOLD" value="3">
+ Constant to set/get the threshold linear velocity of activity. A body marked as potentially inactive for both linear and angular velocity will be put to sleep after the time given.
</constant>
<constant name="SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_THRESHOLD" value="4">
+ Constant to set/get the threshold angular velocity of activity. A body marked as potentially inactive for both linear and angular velocity will be put to sleep after the time given.
</constant>
<constant name="SPACE_PARAM_BODY_TIME_TO_SLEEP" value="5">
+ Constant to set/get the maximum time of activity. A body marked as potentially inactive for both linear and angular velocity will be put to sleep after this time.
</constant>
<constant name="SPACE_PARAM_BODY_ANGULAR_VELOCITY_DAMP_RATIO" value="6">
</constant>
<constant name="SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS" value="7">
+ Constant to set/get the default solver bias for all physics constraints. A solver bias is a factor controlling how much two objects "rebound", after violating a constraint, to avoid leaving them in that state because of numerical imprecision.
</constant>
<constant name="BODY_AXIS_LOCK_DISABLED" value="0">
+ The [Body] can rotate and move freely.
</constant>
<constant name="BODY_AXIS_LOCK_X" value="1">
+ The [Body] cannot move across x axis can only rotate across x axis.
</constant>
<constant name="BODY_AXIS_LOCK_Y" value="2">
+ The [Body] cannot move across y axis can only rotate across y axis.
</constant>
<constant name="BODY_AXIS_LOCK_Z" value="3">
+ The [Body] cannot move across z axis can only rotate across z axis.
</constant>
</constants>
</class>
diff --git a/doc/classes/PhysicsShapeQueryParameters.xml b/doc/classes/PhysicsShapeQueryParameters.xml
index f2e8b1986a..b9023194d7 100644
--- a/doc/classes/PhysicsShapeQueryParameters.xml
+++ b/doc/classes/PhysicsShapeQueryParameters.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="PhysicsShapeQueryParameters" inherits="Reference" category="Core" version="3.0.alpha.custom_build">
+<class name="PhysicsShapeQueryParameters" inherits="Reference" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/PhysicsShapeQueryResult.xml b/doc/classes/PhysicsShapeQueryResult.xml
index 4c4a283688..2e723e96df 100644
--- a/doc/classes/PhysicsShapeQueryResult.xml
+++ b/doc/classes/PhysicsShapeQueryResult.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="PhysicsShapeQueryResult" inherits="Reference" category="Core" version="3.0.alpha.custom_build">
+<class name="PhysicsShapeQueryResult" inherits="Reference" category="Core" version="3.0-alpha">
<brief_description>
Result of a shape query in Physics2DServer.
</brief_description>
diff --git a/doc/classes/PinJoint.xml b/doc/classes/PinJoint.xml
index 22aa35a0a4..bcf69df816 100644
--- a/doc/classes/PinJoint.xml
+++ b/doc/classes/PinJoint.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="PinJoint" inherits="Joint" category="Core" version="3.0.alpha.custom_build">
+<class name="PinJoint" inherits="Joint" category="Core" version="3.0-alpha">
<brief_description>
+ Pin Joint for 3D Shapes.
</brief_description>
<description>
+ Pin Joint for 3D Rigid Bodies. It pins 2 bodies (rigid or static) together.
</description>
<tutorials>
</tutorials>
@@ -30,18 +32,28 @@
</methods>
<members>
<member name="params/bias" type="float" setter="set_param" getter="get_param">
+ The force with wich the pinned objects stay in positional relation to each other.
+ The higher, the stronger.
</member>
<member name="params/damping" type="float" setter="set_param" getter="get_param">
+ The force with wich the pinned objects stay in velocity relation to each other.
+ The higher, the stronger.
</member>
<member name="params/impulse_clamp" type="float" setter="set_param" getter="get_param">
+ If above 0, this value is the maximum value for an impulse that this Joint produces.
</member>
</members>
<constants>
<constant name="PARAM_BIAS" value="0">
+ The force with wich the pinned objects stay in positional relation to each other.
+ The higher, the stronger.
</constant>
<constant name="PARAM_DAMPING" value="1">
+ The force with wich the pinned objects stay in velocity relation to each other.
+ The higher, the stronger.
</constant>
<constant name="PARAM_IMPULSE_CLAMP" value="2">
+ If above 0, this value is the maximum value for an impulse that this Joint produces.
</constant>
</constants>
</class>
diff --git a/doc/classes/PinJoint2D.xml b/doc/classes/PinJoint2D.xml
index 826a1684a4..7f92567ae4 100644
--- a/doc/classes/PinJoint2D.xml
+++ b/doc/classes/PinJoint2D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="PinJoint2D" inherits="Joint2D" category="Core" version="3.0.alpha.custom_build">
+<class name="PinJoint2D" inherits="Joint2D" category="Core" version="3.0-alpha">
<brief_description>
Pin Joint for 2D Shapes.
</brief_description>
@@ -28,6 +28,7 @@
</methods>
<members>
<member name="softness" type="float" setter="set_softness" getter="get_softness">
+ The higher this value, the more the bond to the pinned partner can flex.
</member>
</members>
<constants>
diff --git a/doc/classes/Plane.xml b/doc/classes/Plane.xml
index 5c4eb984db..2fd02a56c6 100644
--- a/doc/classes/Plane.xml
+++ b/doc/classes/Plane.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Plane" category="Built-In Types" version="3.0.alpha.custom_build">
+<class name="Plane" category="Built-In Types" version="3.0-alpha">
<brief_description>
Plane in hessian form.
</brief_description>
diff --git a/doc/classes/PlaneMesh.xml b/doc/classes/PlaneMesh.xml
index 034bc391a6..93bc191e45 100644
--- a/doc/classes/PlaneMesh.xml
+++ b/doc/classes/PlaneMesh.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="PlaneMesh" inherits="PrimitiveMesh" category="Core" version="3.0.alpha.custom_build">
+<class name="PlaneMesh" inherits="PrimitiveMesh" category="Core" version="3.0-alpha">
<brief_description>
Class representing a planar [PrimitiveMesh].
</brief_description>
diff --git a/doc/classes/PlaneShape.xml b/doc/classes/PlaneShape.xml
index 7e7bde4db3..d394f781e3 100644
--- a/doc/classes/PlaneShape.xml
+++ b/doc/classes/PlaneShape.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="PlaneShape" inherits="Shape" category="Core" version="3.0.alpha.custom_build">
+<class name="PlaneShape" inherits="Shape" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/Polygon2D.xml b/doc/classes/Polygon2D.xml
index 23cb9bd91b..ccf60e4d49 100644
--- a/doc/classes/Polygon2D.xml
+++ b/doc/classes/Polygon2D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Polygon2D" inherits="Node2D" category="Core" version="3.0.alpha.custom_build">
+<class name="Polygon2D" inherits="Node2D" category="Core" version="3.0-alpha">
<brief_description>
A 2D polygon.
</brief_description>
@@ -73,6 +73,12 @@
Return the rotation in radians of the texture polygon.
</description>
</method>
+ <method name="get_texture_rotation_degrees" qualifiers="const">
+ <return type="float">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="get_texture_scale" qualifiers="const">
<return type="Vector2">
</return>
@@ -173,6 +179,14 @@
Set the amount of rotation of the polygon texture, [code]texture_rotation[/code] is specified in radians and clockwise rotation.
</description>
</method>
+ <method name="set_texture_rotation_degrees">
+ <return type="void">
+ </return>
+ <argument index="0" name="texture_rotation" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="set_texture_scale">
<return type="void">
</return>
@@ -227,7 +241,7 @@
<member name="texture_offset" type="Vector2" setter="set_texture_offset" getter="get_texture_offset">
Amount to offset the polygon's [code]texture[/code]. If [code](0, 0)[/code] the texture's origin (its top-left corner) will be placed at the polygon's [code]position[/code].
</member>
- <member name="texture_rotation" type="float" setter="_set_texture_rotationd" getter="_get_texture_rotationd">
+ <member name="texture_rotation" type="float" setter="set_texture_rotation_degrees" getter="get_texture_rotation_degrees">
The texture's rotation in degrees.
</member>
<member name="texture_scale" type="Vector2" setter="set_texture_scale" getter="get_texture_scale">
diff --git a/doc/classes/PolygonPathFinder.xml b/doc/classes/PolygonPathFinder.xml
index a0d1284a85..213d7c0981 100644
--- a/doc/classes/PolygonPathFinder.xml
+++ b/doc/classes/PolygonPathFinder.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="PolygonPathFinder" inherits="Resource" category="Core" version="3.0.alpha.custom_build">
+<class name="PolygonPathFinder" inherits="Resource" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/PoolByteArray.xml b/doc/classes/PoolByteArray.xml
index 2640b5118f..54efc24725 100644
--- a/doc/classes/PoolByteArray.xml
+++ b/doc/classes/PoolByteArray.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="PoolByteArray" category="Built-In Types" version="3.0.alpha.custom_build">
+<class name="PoolByteArray" category="Built-In Types" version="3.0-alpha">
<brief_description>
Raw byte array.
</brief_description>
@@ -31,7 +31,7 @@
<argument index="0" name="array" type="PoolByteArray">
</argument>
<description>
- Append a [PoolByteArray] at the end of this array.
+ Append a [code]PoolByteArray[/code] at the end of this array.
</description>
</method>
<method name="compress">
@@ -40,7 +40,7 @@
<argument index="0" name="compression_mode" type="int" default="0">
</argument>
<description>
- Returns a new [PoolByteArray] with the data compressed. Set the compression mode using one of [File]'s COMPRESS_* constants.
+ Returns a new [code]PoolByteArray[/code] with the data compressed. Set the compression mode using one of [File]'s COMPRESS_* constants.
</description>
</method>
<method name="decompress">
@@ -51,7 +51,7 @@
<argument index="1" name="compression_mode" type="int" default="0">
</argument>
<description>
- Returns a new [PoolByteArray] with the data decompressed. Set buffer_size to the size of the uncompressed data. Set the compression mode using one of [File]'s COMPRESS_* constants.
+ Returns a new [code]PoolByteArray[/code] with the data decompressed. Set buffer_size to the size of the uncompressed data. Set the compression mode using one of [File]'s COMPRESS_* constants.
</description>
</method>
<method name="get_string_from_ascii">
@@ -129,7 +129,7 @@
<argument index="1" name="to" type="int">
</argument>
<description>
- Returns the slice of the [PoolByteArray] between indices (inclusive) as a new [PoolByteArray]. Any negative index is considered to be from the end of the array.
+ Returns the slice of the [code]PoolByteArray[/code] between indices (inclusive) as a new [code]PoolByteArray[/code]. Any negative index is considered to be from the end of the array.
</description>
</method>
</methods>
diff --git a/doc/classes/PoolColorArray.xml b/doc/classes/PoolColorArray.xml
index 644256e765..f7cf389577 100644
--- a/doc/classes/PoolColorArray.xml
+++ b/doc/classes/PoolColorArray.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="PoolColorArray" category="Built-In Types" version="3.0.alpha.custom_build">
+<class name="PoolColorArray" category="Built-In Types" version="3.0-alpha">
<brief_description>
Array of Colors
</brief_description>
@@ -31,7 +31,7 @@
<argument index="0" name="array" type="PoolColorArray">
</argument>
<description>
- Append a [PoolColorArray] at the end of this array.
+ Append a [code]PoolColorArray[/code] at the end of this array.
</description>
</method>
<method name="insert">
diff --git a/doc/classes/PoolIntArray.xml b/doc/classes/PoolIntArray.xml
index 17772b6e2a..53b2258c58 100644
--- a/doc/classes/PoolIntArray.xml
+++ b/doc/classes/PoolIntArray.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="PoolIntArray" category="Built-In Types" version="3.0.alpha.custom_build">
+<class name="PoolIntArray" category="Built-In Types" version="3.0-alpha">
<brief_description>
Integer Array.
</brief_description>
@@ -31,7 +31,7 @@
<argument index="0" name="array" type="PoolIntArray">
</argument>
<description>
- Append an [PoolIntArray] at the end of this array.
+ Append an [code]PoolIntArray[/code] at the end of this array.
</description>
</method>
<method name="insert">
diff --git a/doc/classes/PoolRealArray.xml b/doc/classes/PoolRealArray.xml
index ee2740e92a..cc22c256e7 100644
--- a/doc/classes/PoolRealArray.xml
+++ b/doc/classes/PoolRealArray.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="PoolRealArray" category="Built-In Types" version="3.0.alpha.custom_build">
+<class name="PoolRealArray" category="Built-In Types" version="3.0-alpha">
<brief_description>
Real Array.
</brief_description>
diff --git a/doc/classes/PoolStringArray.xml b/doc/classes/PoolStringArray.xml
index ace4f732da..47928281cf 100644
--- a/doc/classes/PoolStringArray.xml
+++ b/doc/classes/PoolStringArray.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="PoolStringArray" category="Built-In Types" version="3.0.alpha.custom_build">
+<class name="PoolStringArray" category="Built-In Types" version="3.0-alpha">
<brief_description>
String Array.
</brief_description>
diff --git a/doc/classes/PoolVector2Array.xml b/doc/classes/PoolVector2Array.xml
index e5df38483a..2ece5a6486 100644
--- a/doc/classes/PoolVector2Array.xml
+++ b/doc/classes/PoolVector2Array.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="PoolVector2Array" category="Built-In Types" version="3.0.alpha.custom_build">
+<class name="PoolVector2Array" category="Built-In Types" version="3.0-alpha">
<brief_description>
An Array of Vector2.
</brief_description>
@@ -17,7 +17,7 @@
<argument index="0" name="from" type="Array">
</argument>
<description>
- Construct a new [PoolVector2Array]. Optionally, you can pass in an Array that will be converted.
+ Construct a new [code]PoolVector2Array[/code]. Optionally, you can pass in an Array that will be converted.
</description>
</method>
<method name="append">
@@ -31,7 +31,7 @@
<argument index="0" name="array" type="PoolVector2Array">
</argument>
<description>
- Append an [PoolVector2Array] at the end of this array.
+ Append an [code]PoolVector2Array[/code] at the end of this array.
</description>
</method>
<method name="insert">
diff --git a/doc/classes/PoolVector3Array.xml b/doc/classes/PoolVector3Array.xml
index 13a8290531..59f1c36a9e 100644
--- a/doc/classes/PoolVector3Array.xml
+++ b/doc/classes/PoolVector3Array.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="PoolVector3Array" category="Built-In Types" version="3.0.alpha.custom_build">
+<class name="PoolVector3Array" category="Built-In Types" version="3.0-alpha">
<brief_description>
An Array of Vector3.
</brief_description>
@@ -31,7 +31,7 @@
<argument index="0" name="array" type="PoolVector3Array">
</argument>
<description>
- Append an [PoolVector3Array] at the end of this array.
+ Append an [code]PoolVector3Array[/code] at the end of this array.
</description>
</method>
<method name="insert">
diff --git a/doc/classes/Popup.xml b/doc/classes/Popup.xml
index 7e87c9fcc0..7a93c32ea8 100644
--- a/doc/classes/Popup.xml
+++ b/doc/classes/Popup.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Popup" inherits="Control" category="Core" version="3.0.alpha.custom_build">
+<class name="Popup" inherits="Control" category="Core" version="3.0-alpha">
<brief_description>
Base container control for popups and dialogs.
</brief_description>
diff --git a/doc/classes/PopupDialog.xml b/doc/classes/PopupDialog.xml
index c51c5b6d21..82439e9d74 100644
--- a/doc/classes/PopupDialog.xml
+++ b/doc/classes/PopupDialog.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="PopupDialog" inherits="Popup" category="Core" version="3.0.alpha.custom_build">
+<class name="PopupDialog" inherits="Popup" category="Core" version="3.0-alpha">
<brief_description>
Base class for Popup Dialogs.
</brief_description>
diff --git a/doc/classes/PopupMenu.xml b/doc/classes/PopupMenu.xml
index 086eb8e34d..f3cd7df796 100644
--- a/doc/classes/PopupMenu.xml
+++ b/doc/classes/PopupMenu.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="PopupMenu" inherits="Popup" category="Core" version="3.0.alpha.custom_build">
+<class name="PopupMenu" inherits="Popup" category="Core" version="3.0-alpha">
<brief_description>
PopupMenu displays a list of options.
</brief_description>
diff --git a/doc/classes/PopupPanel.xml b/doc/classes/PopupPanel.xml
index f8060ab4f6..3878e345c9 100644
--- a/doc/classes/PopupPanel.xml
+++ b/doc/classes/PopupPanel.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="PopupPanel" inherits="Popup" category="Core" version="3.0.alpha.custom_build">
+<class name="PopupPanel" inherits="Popup" category="Core" version="3.0-alpha">
<brief_description>
Class for displaying popups with a panel background.
</brief_description>
diff --git a/doc/classes/Position2D.xml b/doc/classes/Position2D.xml
index ffb1c62d0f..6d282370d4 100644
--- a/doc/classes/Position2D.xml
+++ b/doc/classes/Position2D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Position2D" inherits="Node2D" category="Core" version="3.0.alpha.custom_build">
+<class name="Position2D" inherits="Node2D" category="Core" version="3.0-alpha">
<brief_description>
Generic 2D Position hint for editing.
</brief_description>
diff --git a/doc/classes/Position3D.xml b/doc/classes/Position3D.xml
index a544e59ddc..cd4c1293ca 100644
--- a/doc/classes/Position3D.xml
+++ b/doc/classes/Position3D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Position3D" inherits="Spatial" category="Core" version="3.0.alpha.custom_build">
+<class name="Position3D" inherits="Spatial" category="Core" version="3.0-alpha">
<brief_description>
Generic 3D Position hint for editing
</brief_description>
diff --git a/doc/classes/PrimitiveMesh.xml b/doc/classes/PrimitiveMesh.xml
index 34141edbe7..5c8d467927 100644
--- a/doc/classes/PrimitiveMesh.xml
+++ b/doc/classes/PrimitiveMesh.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="PrimitiveMesh" inherits="Mesh" category="Core" version="3.0.alpha.custom_build">
+<class name="PrimitiveMesh" inherits="Mesh" category="Core" version="3.0-alpha">
<brief_description>
Base class for all primitive meshes. Handles applying a [Material] to a primitive mesh.
</brief_description>
diff --git a/doc/classes/PrismMesh.xml b/doc/classes/PrismMesh.xml
index 21fa67bc82..fa53717111 100644
--- a/doc/classes/PrismMesh.xml
+++ b/doc/classes/PrismMesh.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="PrismMesh" inherits="PrimitiveMesh" category="Core" version="3.0.alpha.custom_build">
+<class name="PrismMesh" inherits="PrimitiveMesh" category="Core" version="3.0-alpha">
<brief_description>
Class representing a prism-shaped [PrimitiveMesh].
</brief_description>
diff --git a/doc/classes/ProceduralSky.xml b/doc/classes/ProceduralSky.xml
index 032ce9def2..70e9388058 100644
--- a/doc/classes/ProceduralSky.xml
+++ b/doc/classes/ProceduralSky.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ProceduralSky" inherits="Sky" category="Core" version="3.0.alpha.custom_build">
+<class name="ProceduralSky" inherits="Sky" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/ProgressBar.xml b/doc/classes/ProgressBar.xml
index f6be04cc19..d72b28efc5 100644
--- a/doc/classes/ProgressBar.xml
+++ b/doc/classes/ProgressBar.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ProgressBar" inherits="Range" category="Core" version="3.0.alpha.custom_build">
+<class name="ProgressBar" inherits="Range" category="Core" version="3.0-alpha">
<brief_description>
General purpose progress bar.
</brief_description>
diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml
index 1a3ea5c5c7..6f670ded64 100644
--- a/doc/classes/ProjectSettings.xml
+++ b/doc/classes/ProjectSettings.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ProjectSettings" inherits="Object" category="Core" version="3.0.alpha.custom_build">
+<class name="ProjectSettings" inherits="Object" category="Core" version="3.0-alpha">
<brief_description>
Contains global variables accessible from everywhere.
</brief_description>
@@ -17,7 +17,7 @@
<argument index="0" name="hint" type="Dictionary">
</argument>
<description>
- Add a custom property info to a property. The dictionary must contain: name:[String](the name of the property) and type:[int](see TYPE_* in [@Global Scope]), and optionally hint:[int](see PROPERTY_HINT_* in [@Global Scope]), hint_string:[String].
+ Add a custom property info to a property. The dictionary must contain: name:[String](the name of the property) and type:[int](see TYPE_* in [@GlobalScope]), and optionally hint:[int](see PROPERTY_HINT_* in [@GlobalScope]), hint_string:[String].
Example:
[codeblock]
ProjectSettings.set("category/property_name", 0)
@@ -51,8 +51,8 @@
Return the order of a configuration value (influences when saved to the config file).
</description>
</method>
- <method name="get_singleton" qualifiers="const">
- <return type="Object">
+ <method name="get_setting" qualifiers="const">
+ <return type="Variant">
</return>
<argument index="0" name="name" type="String">
</argument>
@@ -68,7 +68,7 @@
Convert a localized path (res://) to a full native OS path.
</description>
</method>
- <method name="has" qualifiers="const">
+ <method name="has_setting" qualifiers="const">
<return type="bool">
</return>
<argument index="0" name="name" type="String">
@@ -77,14 +77,6 @@
Return true if a configuration value is present.
</description>
</method>
- <method name="has_singleton" qualifiers="const">
- <return type="bool">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <description>
- </description>
- </method>
<method name="load_resource_pack">
<return type="bool">
</return>
@@ -153,6 +145,16 @@
Set the order of a configuration value (influences when saved to the config file).
</description>
</method>
+ <method name="set_setting">
+ <return type="void">
+ </return>
+ <argument index="0" name="name" type="String">
+ </argument>
+ <argument index="1" name="value" type="Variant">
+ </argument>
+ <description>
+ </description>
+ </method>
</methods>
<constants>
</constants>
diff --git a/doc/classes/ProximityGroup.xml b/doc/classes/ProximityGroup.xml
index 9b4b564900..b05d5b95dd 100644
--- a/doc/classes/ProximityGroup.xml
+++ b/doc/classes/ProximityGroup.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ProximityGroup" inherits="Spatial" category="Core" version="3.0.alpha.custom_build">
+<class name="ProximityGroup" inherits="Spatial" category="Core" version="3.0-alpha">
<brief_description>
General purpose proximity-detection node.
</brief_description>
diff --git a/doc/classes/QuadMesh.xml b/doc/classes/QuadMesh.xml
index b7c66b04de..807141a284 100644
--- a/doc/classes/QuadMesh.xml
+++ b/doc/classes/QuadMesh.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="QuadMesh" inherits="PrimitiveMesh" category="Core" version="3.0.alpha.custom_build">
+<class name="QuadMesh" inherits="PrimitiveMesh" category="Core" version="3.0-alpha">
<brief_description>
Class representing a square mesh.
</brief_description>
@@ -11,7 +11,25 @@
<demos>
</demos>
<methods>
+ <method name="get_size" qualifiers="const">
+ <return type="Vector2">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="set_size">
+ <return type="void">
+ </return>
+ <argument index="0" name="size" type="Vector2">
+ </argument>
+ <description>
+ </description>
+ </method>
</methods>
+ <members>
+ <member name="size" type="Vector2" setter="set_size" getter="get_size">
+ </member>
+ </members>
<constants>
</constants>
</class>
diff --git a/doc/classes/Quat.xml b/doc/classes/Quat.xml
index f07e143aa0..1aa30075e4 100644
--- a/doc/classes/Quat.xml
+++ b/doc/classes/Quat.xml
@@ -1,10 +1,13 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Quat" category="Built-In Types" version="3.0.alpha.custom_build">
+<class name="Quat" category="Built-In Types" version="3.0-alpha">
<brief_description>
Quaternion.
</brief_description>
<description>
- Quaternion is a 4 dimensional vector that is used to represent a rotation. It mainly exists to perform SLERP (spherical-linear interpolation) between two rotations. Multiplying quaternions also cheaply reproduces rotation sequences. However quaternions need to be often renormalized, or else they suffer from precision issues.
+ A 4-dimensional vector representing a rotation.
+ The vector represents a 4 dimensional complex number where multiplication of the basis elements is not commutative (multiplying i with j gives a different result than multiplying j with i).
+ Multiplying quaternions reproduces rotation sequences. However quaternions need to be often renormalized, or else they suffer from precision issues.
+ It can be used to perform SLERP (spherical-linear interpolation) between two rotations.
</description>
<tutorials>
</tutorials>
@@ -23,6 +26,7 @@
<argument index="3" name="w" type="float">
</argument>
<description>
+ Returns a quaternion defined by these values.
</description>
</method>
<method name="Quat">
@@ -57,6 +61,7 @@
<argument index="3" name="t" type="float">
</argument>
<description>
+ Performs a cubic spherical-linear interpolation with another quaternion.
</description>
</method>
<method name="dot">
@@ -111,7 +116,7 @@
<argument index="1" name="t" type="float">
</argument>
<description>
- Perform a spherical-linear interpolation with another quaternion.
+ Performs a spherical-linear interpolation with another quaternion.
</description>
</method>
<method name="slerpni">
@@ -122,6 +127,7 @@
<argument index="1" name="t" type="float">
</argument>
<description>
+ Performs a spherical-linear interpolation with another quaterion without checking if the rotation path is not bigger than 90°.
</description>
</method>
<method name="xform">
@@ -130,17 +136,22 @@
<argument index="0" name="v" type="Vector3">
</argument>
<description>
+ Transforms the vector [code]v[/code] by this quaternion.
</description>
</method>
</methods>
<members>
<member name="w" type="float" setter="" getter="">
+ W component of the quaternion. Default value: [code]1[/code]
</member>
<member name="x" type="float" setter="" getter="">
+ X component of the quaternion. Default value: [code]0[/code]
</member>
<member name="y" type="float" setter="" getter="">
+ Y component of the quaternion. Default value: [code]0[/code]
</member>
<member name="z" type="float" setter="" getter="">
+ Z component of the quaternion. Default value: [code]0[/code]
</member>
</members>
<constants>
diff --git a/doc/classes/RID.xml b/doc/classes/RID.xml
index 89005b0d3b..831a4665c4 100644
--- a/doc/classes/RID.xml
+++ b/doc/classes/RID.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="RID" category="Built-In Types" version="3.0.alpha.custom_build">
+<class name="RID" category="Built-In Types" version="3.0-alpha">
<brief_description>
Handle for a [Resource]'s unique ID.
</brief_description>
diff --git a/doc/classes/Range.xml b/doc/classes/Range.xml
index cd75c2b658..d2ea59cbeb 100644
--- a/doc/classes/Range.xml
+++ b/doc/classes/Range.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Range" inherits="Control" category="Core" version="3.0.alpha.custom_build">
+<class name="Range" inherits="Control" category="Core" version="3.0-alpha">
<brief_description>
Abstract base class for range-based controls.
</brief_description>
diff --git a/doc/classes/RayCast.xml b/doc/classes/RayCast.xml
index 2e6efff769..d5f57c43c8 100644
--- a/doc/classes/RayCast.xml
+++ b/doc/classes/RayCast.xml
@@ -1,16 +1,13 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="RayCast" inherits="Spatial" category="Core" version="3.0.alpha.custom_build">
+<class name="RayCast" inherits="Spatial" category="Core" version="3.0-alpha">
<brief_description>
Query the closest object intersecting a ray.
</brief_description>
<description>
A RayCast represents a line from its origin to its destination position, [code]cast_to[/code]. It is used to query the 3D space in order to find the closest object along the path of the ray.
-
RayCast can ignore some objects by adding them to the exception list via [code]add_exception[/code], by setting proper filtering with collision layers, or by filtering object types with type masks.
-
Only enabled raycasts will be able to query the space and report collisions.
-
- RayCast calculates intersection every fixed frame (see [Node]), and the result is cached so it can be used later until the next frame. If multiple queries are required between fixed frames (or during the same frame) use [method force_raycast_update] after adjusting the raycast.
+ RayCast calculates intersection every physics frame (see [Node]), and the result is cached so it can be used later until the next frame. If multiple queries are required between physics frames (or during the same frame) use [method force_raycast_update] after adjusting the raycast.
</description>
<tutorials>
</tutorials>
@@ -47,7 +44,7 @@
</return>
<description>
Updates the collision information for the ray.
- Use this method to update the collision information immediately instead of waiting for the next [code]_fixed_process[/code] call, for example if the ray or its parent has changed state. Note: [code]enabled == true[/code] is not required for this to work.
+ Use this method to update the collision information immediately instead of waiting for the next [code]_physics_process[/code] call, for example if the ray or its parent has changed state. Note: [code]enabled == true[/code] is not required for this to work.
</description>
</method>
<method name="get_cast_to" qualifiers="const">
@@ -81,11 +78,19 @@
[/codeblock]
</description>
</method>
- <method name="get_collision_layer" qualifiers="const">
+ <method name="get_collision_mask" qualifiers="const">
<return type="int">
</return>
<description>
- Returns the collision layer for this ray.
+ Returns the collision mask for this ray.
+ </description>
+ </method>
+ <method name="get_collision_mask_bit" qualifiers="const">
+ <return type="bool">
+ </return>
+ <argument index="0" name="bit" type="int">
+ </argument>
+ <description>
</description>
</method>
<method name="get_collision_normal" qualifiers="const">
@@ -150,13 +155,23 @@
Sets the ray destination point, so that the ray will test from the ray's origin to [code]local_point[/code].
</description>
</method>
- <method name="set_collision_layer">
+ <method name="set_collision_mask">
+ <return type="void">
+ </return>
+ <argument index="0" name="mask" type="int">
+ </argument>
+ <description>
+ Set the mask to filter objects. Only objects in at least one collision layer enabled in the mask will be detected.
+ </description>
+ </method>
+ <method name="set_collision_mask_bit">
<return type="void">
</return>
- <argument index="0" name="layer" type="int">
+ <argument index="0" name="bit" type="int">
+ </argument>
+ <argument index="1" name="value" type="bool">
</argument>
<description>
- Set the mask to filter objects. Only objects with at least the same mask element set will be detected.
</description>
</method>
<method name="set_enabled">
@@ -182,8 +197,8 @@
<member name="cast_to" type="Vector3" setter="set_cast_to" getter="get_cast_to">
The ray's destination point, relative to the RayCast's [code]position[/code].
</member>
- <member name="collision_layer" type="int" setter="set_collision_layer" getter="get_collision_layer">
- The RayCast's collison layer(s). Only bodies in the same collision layer(s) will be detected.
+ <member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask">
+ The ray's collision mask. Only objects in at least one collision layer enabled in the mask will be detected.
</member>
<member name="enabled" type="bool" setter="set_enabled" getter="is_enabled">
If [code]true[/code], collisions will be reported. Default value: [code]false[/code].
diff --git a/doc/classes/RayCast2D.xml b/doc/classes/RayCast2D.xml
index 5520abe050..f5828da796 100644
--- a/doc/classes/RayCast2D.xml
+++ b/doc/classes/RayCast2D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="RayCast2D" inherits="Node2D" category="Core" version="3.0.alpha.custom_build">
+<class name="RayCast2D" inherits="Node2D" category="Core" version="3.0-alpha">
<brief_description>
Query the closest object intersecting a ray.
</brief_description>
@@ -7,7 +7,7 @@
A RayCast represents a line from its origin to its destination position, [code]cast_to[/code]. It is used to query the 2D space in order to find the closest object along the path of the ray.
RayCast2D can ignore some objects by adding them to the exception list via [code]add_exception[/code], by setting proper filtering with collision layers, or by filtering object types with type masks.
Only enabled raycasts will be able to query the space and report collisions.
- RayCast2D calculates intersection every fixed frame (see [Node]), and the result is cached so it can be used later until the next frame. If multiple queries are required between fixed frames (or during the same frame) use [method force_raycast_update] after adjusting the raycast.
+ RayCast2D calculates intersection every physics frame (see [Node]), and the result is cached so it can be used later until the next frame. If multiple queries are required between physics frames (or during the same frame) use [method force_raycast_update] after adjusting the raycast.
</description>
<tutorials>
</tutorials>
@@ -43,7 +43,7 @@
<return type="void">
</return>
<description>
- Updates the collision information for the ray. Use this method to update the collision information immediately instead of waiting for the next [code]_fixed_process[/code] call, for example if the ray or its parent has changed state. Note: [code]enabled == true[/code] is not required for this to work.
+ Updates the collision information for the ray. Use this method to update the collision information immediately instead of waiting for the next [code]_physics_process[/code] call, for example if the ray or its parent has changed state. Note: [code]enabled == true[/code] is not required for this to work.
</description>
</method>
<method name="get_cast_to" qualifiers="const">
@@ -77,11 +77,19 @@
[/codeblock]
</description>
</method>
- <method name="get_collision_layer" qualifiers="const">
+ <method name="get_collision_mask" qualifiers="const">
<return type="int">
</return>
<description>
- Returns the collision layer for this ray.
+ Returns the collision mask for this ray.
+ </description>
+ </method>
+ <method name="get_collision_mask_bit" qualifiers="const">
+ <return type="bool">
+ </return>
+ <argument index="0" name="bit" type="int">
+ </argument>
+ <description>
</description>
</method>
<method name="get_collision_normal" qualifiers="const">
@@ -153,13 +161,23 @@
Sets the ray destination point, so that the ray will test from the ray's origin to [code]local_point[/code]
</description>
</method>
- <method name="set_collision_layer">
+ <method name="set_collision_mask">
+ <return type="void">
+ </return>
+ <argument index="0" name="mask" type="int">
+ </argument>
+ <description>
+ Set the mask to filter objects. Only objects in at least one collision layer enabled in the mask will be detected.
+ </description>
+ </method>
+ <method name="set_collision_mask_bit">
<return type="void">
</return>
- <argument index="0" name="layer" type="int">
+ <argument index="0" name="bit" type="int">
+ </argument>
+ <argument index="1" name="value" type="bool">
</argument>
<description>
- Set the mask to filter objects. Only objects with at least the same mask element set will be detected.
</description>
</method>
<method name="set_enabled">
@@ -194,8 +212,8 @@
<member name="cast_to" type="Vector2" setter="set_cast_to" getter="get_cast_to">
The ray's destination point, relative to the RayCast's [code]position[/code].
</member>
- <member name="collision_layer" type="int" setter="set_collision_layer" getter="get_collision_layer">
- The RayCast2D's collison layer(s). Only bodies in the same collision layer(s) will be detected.
+ <member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask">
+ The ray's collision mask. Only objects in at least one collision layer enabled in the mask will be detected.
</member>
<member name="enabled" type="bool" setter="set_enabled" getter="is_enabled">
If [code]true[/code], collisions will be reported. Default value: [code]false[/code].
diff --git a/doc/classes/RayShape.xml b/doc/classes/RayShape.xml
index d5d367a335..d4826141e8 100644
--- a/doc/classes/RayShape.xml
+++ b/doc/classes/RayShape.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="RayShape" inherits="Shape" category="Core" version="3.0.alpha.custom_build">
+<class name="RayShape" inherits="Shape" category="Core" version="3.0-alpha">
<brief_description>
Ray shape for 3D collisions.
</brief_description>
diff --git a/doc/classes/RayShape2D.xml b/doc/classes/RayShape2D.xml
index 4f6313a1d2..c9779a4307 100644
--- a/doc/classes/RayShape2D.xml
+++ b/doc/classes/RayShape2D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="RayShape2D" inherits="Shape2D" category="Core" version="3.0.alpha.custom_build">
+<class name="RayShape2D" inherits="Shape2D" category="Core" version="3.0-alpha">
<brief_description>
Ray shape for 2D collisions.
</brief_description>
diff --git a/doc/classes/Rect2.xml b/doc/classes/Rect2.xml
index 80f7830a16..e0b8b6ec75 100644
--- a/doc/classes/Rect2.xml
+++ b/doc/classes/Rect2.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Rect2" category="Built-In Types" version="3.0.alpha.custom_build">
+<class name="Rect2" category="Built-In Types" version="3.0-alpha">
<brief_description>
2D Axis-aligned bounding box.
</brief_description>
<description>
- Rect2 provides an 2D Axis-Aligned Bounding Box. It consists of a position, a size, and several utility functions. It is typically used for fast overlap tests.
+ Rect2 consists of a position, a size, and several utility functions. It is typically used for fast overlap tests.
</description>
<tutorials>
</tutorials>
@@ -19,7 +19,7 @@
<argument index="1" name="size" type="Vector2">
</argument>
<description>
- Construct a [Rect2] by position and size.
+ Constructs a [code]Rect2[/code] by position and size.
</description>
</method>
<method name="Rect2">
@@ -34,7 +34,7 @@
<argument index="3" name="height" type="float">
</argument>
<description>
- Construct a [Rect2] by x, y, width and height.
+ Constructs a [code]Rect2[/code] by x, y, width, and height.
</description>
</method>
<method name="clip">
@@ -43,7 +43,7 @@
<argument index="0" name="b" type="Rect2">
</argument>
<description>
- Returns the intersection of this [Rect2] and b.
+ Returns the intersection of this [code]Rect2[/code] and b.
</description>
</method>
<method name="encloses">
@@ -52,7 +52,7 @@
<argument index="0" name="b" type="Rect2">
</argument>
<description>
- Returns true if this [Rect2] completely encloses another one.
+ Returns [code]true[/code] if this [code]Rect2[/code] completely encloses another one.
</description>
</method>
<method name="expand">
@@ -61,14 +61,14 @@
<argument index="0" name="to" type="Vector2">
</argument>
<description>
- Return this [Rect2] expanded to include a given point.
+ Returns this [code]Rect2[/code] expanded to include a given point.
</description>
</method>
<method name="get_area">
<return type="float">
</return>
<description>
- Get the area of the [Rect2].
+ Returns the area of the [code]Rect2[/code].
</description>
</method>
<method name="grow">
@@ -77,7 +77,7 @@
<argument index="0" name="by" type="float">
</argument>
<description>
- Return a copy of the [Rect2] grown a given amount of units towards all the sides.
+ Returns a copy of the [code]Rect2[/code] grown a given amount of units towards all the sides.
</description>
</method>
<method name="grow_individual">
@@ -92,6 +92,7 @@
<argument index="3" name=" bottom" type="float">
</argument>
<description>
+ Returns a copy of the [code]Rect2[/code] grown a given amount of units towards each direction individually.
</description>
</method>
<method name="grow_margin">
@@ -102,13 +103,14 @@
<argument index="1" name="by" type="float">
</argument>
<description>
+ Returns a copy of the [code]Rect2[/code] grown a given amount of units towards the [Margin] direction.
</description>
</method>
<method name="has_no_area">
<return type="bool">
</return>
<description>
- Return true if the [Rect2] is flat or empty.
+ Returns [code]true[/code] if the [code]Rect2[/code] is flat or empty.
</description>
</method>
<method name="has_point">
@@ -117,7 +119,7 @@
<argument index="0" name="point" type="Vector2">
</argument>
<description>
- Return true if the [Rect2] contains a point.
+ Returns [code]true[/code] if the [code]Rect2[/code] contains a point.
</description>
</method>
<method name="intersects">
@@ -126,7 +128,7 @@
<argument index="0" name="b" type="Rect2">
</argument>
<description>
- Return true if the [Rect2] overlaps with another.
+ Returns [code]true[/code] if the [code]Rect2[/code] overlaps with another.
</description>
</method>
<method name="merge">
@@ -135,7 +137,7 @@
<argument index="0" name="b" type="Rect2">
</argument>
<description>
- Combine this [Rect2] with another, a larger one is returned that contains both.
+ Returns a larger Rect2 that contains this Rect2 and [code]with[/code].
</description>
</method>
</methods>
diff --git a/doc/classes/RectangleShape2D.xml b/doc/classes/RectangleShape2D.xml
index 7a1aec2021..b61344d86f 100644
--- a/doc/classes/RectangleShape2D.xml
+++ b/doc/classes/RectangleShape2D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="RectangleShape2D" inherits="Shape2D" category="Core" version="3.0.alpha.custom_build">
+<class name="RectangleShape2D" inherits="Shape2D" category="Core" version="3.0-alpha">
<brief_description>
Rectangle shape for 2D collisions.
</brief_description>
diff --git a/doc/classes/Reference.xml b/doc/classes/Reference.xml
index 2531ea88ad..18bd51f675 100644
--- a/doc/classes/Reference.xml
+++ b/doc/classes/Reference.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Reference" inherits="Object" category="Core" version="3.0.alpha.custom_build">
+<class name="Reference" inherits="Object" category="Core" version="3.0-alpha">
<brief_description>
Base class for anything that keeps a reference count.
</brief_description>
diff --git a/doc/classes/ReferenceRect.xml b/doc/classes/ReferenceRect.xml
index e8de910cc8..75b513a147 100644
--- a/doc/classes/ReferenceRect.xml
+++ b/doc/classes/ReferenceRect.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ReferenceRect" inherits="Control" category="Core" version="3.0.alpha.custom_build">
+<class name="ReferenceRect" inherits="Control" category="Core" version="3.0-alpha">
<brief_description>
Reference frame for GUI.
</brief_description>
diff --git a/doc/classes/ReflectionProbe.xml b/doc/classes/ReflectionProbe.xml
index c3d95e5a62..1508323207 100644
--- a/doc/classes/ReflectionProbe.xml
+++ b/doc/classes/ReflectionProbe.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ReflectionProbe" inherits="VisualInstance" category="Core" version="3.0.alpha.custom_build">
+<class name="ReflectionProbe" inherits="VisualInstance" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/RegEx.xml b/doc/classes/RegEx.xml
deleted file mode 100644
index 4577672c72..0000000000
--- a/doc/classes/RegEx.xml
+++ /dev/null
@@ -1,114 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<class name="RegEx" inherits="Reference" category="Core" version="3.0.alpha.custom_build">
- <brief_description>
- Simple regular expression matcher.
- </brief_description>
- <description>
- Class for finding text patterns in a string using regular expressions. It can not perform replacements. Regular expressions are a way to define patterns of text to be searched. Details on writing patterns are too long to explain here but the Internet is full of tutorials and detailed explanations.
- Once created, the RegEx object needs to be compiled with the search pattern before it can be used. The search pattern must be escaped first for gdscript before it is escaped for the expression. For example:
- [code]var exp = RegEx.new()[/code]
- [code]exp.compile("\\d+")[/code]
- would be read by RegEx as [code]\d+[/code]
- Similarly:
- [code]exp.compile("\"(?:\\\\.|[^\"])*\"")[/code]
- would be read as [code]"(?:\\.|[^"])*"[/code]
- Currently supported features:
- * Capturing [code]()[/code] and non-capturing [code](?:)[/code] groups
- * Named capturing groups [code](?P&lt;name&gt;)[/code]
- * Any character [code].[/code]
- * Shorthand character classes [code]\w \W \s \S \d \D[/code]
- * User-defined character classes such as [code][A-Za-z][/code]
- * Simple quantifiers [code]?[/code], [code]*[/code] and [code]+[/code]
- * Range quantifiers [code]{x,y}[/code]
- * Lazy (non-greedy) quantifiers [code]*?[/code]
- * Beginning [code]^[/code] and end [code]$[/code] anchors
- * Alternation [code]|[/code]
- * Backreferences [code]\1[/code], [code]\g{1}[/code], and [code]\g&lt;name&gt;[/code]
- * POSIX character classes [code][[:alnum:]][/code]
- * Lookahead [code](?=)[/code], [code](?!)[/code] and lookbehind [code](?&lt;=)[/code], [code](?&lt;!)[/code]
- * ASCII [code]\xFF[/code] and Unicode [code]\uFFFF[/code] code points (in a style similar to Python)
- * Word boundaries [code]\b[/code], [code]\B[/code]
- </description>
- <tutorials>
- </tutorials>
- <demos>
- </demos>
- <methods>
- <method name="clear">
- <return type="void">
- </return>
- <description>
- This method resets the state of the object, as it was freshly created. Namely, it unassigns the regular expression of this object.
- </description>
- </method>
- <method name="compile">
- <return type="int" enum="Error">
- </return>
- <argument index="0" name="pattern" type="String">
- </argument>
- <description>
- Compiles and assign the search pattern to use.
- </description>
- </method>
- <method name="get_group_count" qualifiers="const">
- <return type="int">
- </return>
- <description>
- Returns the number of numeric capturing groups.
- </description>
- </method>
- <method name="get_names" qualifiers="const">
- <return type="Array">
- </return>
- <description>
- Returns an array of names of named capturing groups.
- </description>
- </method>
- <method name="get_pattern" qualifiers="const">
- <return type="String">
- </return>
- <description>
- Returns the search pattern used to compile the code.
- </description>
- </method>
- <method name="is_valid" qualifiers="const">
- <return type="bool">
- </return>
- <description>
- Returns whether this object has a valid search pattern assigned.
- </description>
- </method>
- <method name="search" qualifiers="const">
- <return type="RegExMatch">
- </return>
- <argument index="0" name="subject" type="String">
- </argument>
- <argument index="1" name="offset" type="int" default="0">
- </argument>
- <argument index="2" name="end" type="int" default="-1">
- </argument>
- <description>
- Searches the text for the compiled pattern. Returns a [RegExMatch] container of the first matching result if found, otherwise null. The region to search within can be specified without modifying where the start and end anchor would be.
- </description>
- </method>
- <method name="sub" qualifiers="const">
- <return type="String">
- </return>
- <argument index="0" name="subject" type="String">
- </argument>
- <argument index="1" name="replacement" type="String">
- </argument>
- <argument index="2" name="all" type="bool" default="false">
- </argument>
- <argument index="3" name="offset" type="int" default="0">
- </argument>
- <argument index="4" name="end" type="int" default="-1">
- </argument>
- <description>
- Searches the text for the compiled pattern and replaces it with the specified string. Escapes and backreferences such as [code]\1[/code] and [code]\g&lt;name&gt;[/code] expanded and resolved. By default only the first instance is replaced but it can be changed for all instances (global replacement). The region to search within can be specified without modifying where the start and end anchor would be.
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
diff --git a/doc/classes/RegExMatch.xml b/doc/classes/RegExMatch.xml
deleted file mode 100644
index abf2e383d5..0000000000
--- a/doc/classes/RegExMatch.xml
+++ /dev/null
@@ -1,72 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<class name="RegExMatch" inherits="Reference" category="Core" version="3.0.alpha.custom_build">
- <brief_description>
- Contains the results of a regex search.
- </brief_description>
- <description>
- Contains the results of a regex search. [method RegEx.search] returns an instance of [code]RegExMatch[/code] if it finds the search pattern in the [source] string.
- </description>
- <tutorials>
- </tutorials>
- <demos>
- </demos>
- <methods>
- <method name="get_end" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="name" type="Variant" default="0">
- </argument>
- <description>
- Returns the end position of the match in the [source] string. An integer can be specified for numeric groups or a string for named groups. Returns -1 if that group wasn't found or doesn't exist. Defaults to 0 (whole pattern).
- </description>
- </method>
- <method name="get_group_count" qualifiers="const">
- <return type="int">
- </return>
- <description>
- Returns the number of numeric capturing groups.
- </description>
- </method>
- <method name="get_names" qualifiers="const">
- <return type="Dictionary">
- </return>
- <description>
- Returns an array of names of named capturing groups.
- </description>
- </method>
- <method name="get_start" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="name" type="Variant" default="0">
- </argument>
- <description>
- Returns the starting position of the match in the [source] string. An integer can be specified for numeric groups or a string for named groups. Returns -1 if that group wasn't found or doesn't exist. Defaults to 0 (whole pattern).
- </description>
- </method>
- <method name="get_string" qualifiers="const">
- <return type="String">
- </return>
- <argument index="0" name="name" type="Variant" default="0">
- </argument>
- <description>
- Returns the result of the match in the [source] string. An integer can be specified for numeric groups or a string for named groups. Returns -1 if that group wasn't found or doesn't exist. Defaults to 0 (whole pattern).
- </description>
- </method>
- <method name="get_strings" qualifiers="const">
- <return type="Array">
- </return>
- <description>
- Returns an [Array] of the matches in the [source] string.
- </description>
- </method>
- <method name="get_subject" qualifiers="const">
- <return type="String">
- </return>
- <description>
- Returns the [source] string used with the search pattern to find this matching result.
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
diff --git a/doc/classes/RemoteTransform.xml b/doc/classes/RemoteTransform.xml
index ecc136055e..76caea1a94 100644
--- a/doc/classes/RemoteTransform.xml
+++ b/doc/classes/RemoteTransform.xml
@@ -1,8 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="RemoteTransform" inherits="Spatial" category="Core" version="3.0.alpha.custom_build">
+<class name="RemoteTransform" inherits="Spatial" category="Core" version="3.0-alpha">
<brief_description>
+ RemoteTransform mirrors the [Transform] of another [Spatial] derived Node in the scene.
</brief_description>
<description>
+ RemoteTransform mirrors the [Transform] of another [Spatial] derived Node (called the remote node) in the scene.
+ It can be set to track another Node's position, rotation and/or scale and update its own accordingly, using either global or local coordinates.
</description>
<tutorials>
</tutorials>
@@ -82,14 +85,19 @@
</methods>
<members>
<member name="remote_path" type="NodePath" setter="set_remote_node" getter="get_remote_node">
+ The remote node's [NodePath].
</member>
<member name="update_position" type="bool" setter="set_update_position" getter="get_update_position">
+ If [code]true[/code] the remote node's position is mirrored.
</member>
<member name="update_rotation" type="bool" setter="set_update_rotation" getter="get_update_rotation">
+ If [code]true[/code] the remote node's rotation is mirrored.
</member>
<member name="update_scale" type="bool" setter="set_update_scale" getter="get_update_scale">
+ If [code]true[/code] the remote node's scale is mirrored.
</member>
<member name="use_global_coordinates" type="bool" setter="set_use_global_coordinates" getter="get_use_global_coordinates">
+ If [code]true[/code] global coordinates are used. If [code]false[/code] local coordinates are used. Default value: [code]true[/code].
</member>
</members>
<constants>
diff --git a/doc/classes/RemoteTransform2D.xml b/doc/classes/RemoteTransform2D.xml
index 346b8de621..d6dcde5742 100644
--- a/doc/classes/RemoteTransform2D.xml
+++ b/doc/classes/RemoteTransform2D.xml
@@ -1,8 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="RemoteTransform2D" inherits="Node2D" category="Core" version="3.0.alpha.custom_build">
+<class name="RemoteTransform2D" inherits="Node2D" category="Core" version="3.0-alpha">
<brief_description>
+ RemoteTransform2D mirrors the [Transform2D] of another [CanvasItem] derived Node in the scene.
</brief_description>
<description>
+ RemoteTransform2D mirrors the [Transform2D] of another [CanvasItem] derived Node (called the remote node) in the scene.
+ It can be set to track another Node's position, rotation and/or and update its own accordingly, using either global or local coordinates.
</description>
<tutorials>
</tutorials>
@@ -82,14 +85,19 @@
</methods>
<members>
<member name="remote_path" type="NodePath" setter="set_remote_node" getter="get_remote_node">
+ The remote node's [NodePath].
</member>
<member name="update_position" type="bool" setter="set_update_position" getter="get_update_position">
+ If [code]true[/code] the remote node's position is mirrored.
</member>
<member name="update_rotation" type="bool" setter="set_update_rotation" getter="get_update_rotation">
+ If [code]true[/code] the remote node's rotation is mirrored.
</member>
<member name="update_scale" type="bool" setter="set_update_scale" getter="get_update_scale">
+ If [code]true[/code] the remote node's scale is mirrored.
</member>
<member name="use_global_coordinates" type="bool" setter="set_use_global_coordinates" getter="get_use_global_coordinates">
+ If [code]true[/code] global coordinates are used. If [code]false[/code] local coordinates are used. Default value: [code]true[/code].
</member>
</members>
<constants>
diff --git a/doc/classes/Resource.xml b/doc/classes/Resource.xml
index 57497f5d78..0044756003 100644
--- a/doc/classes/Resource.xml
+++ b/doc/classes/Resource.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Resource" inherits="Reference" category="Core" version="3.0.alpha.custom_build">
+<class name="Resource" inherits="Reference" category="Core" version="3.0-alpha">
<brief_description>
Base class for all resources.
</brief_description>
@@ -81,7 +81,7 @@
<argument index="0" name="path" type="String">
</argument>
<description>
- Set the path of the resource. This is useful mainly for editors when saving/loading, and shouldn't be changed by anything else. Fails if another [Resource] already has path "path".
+ Set the path of the resource. This is useful mainly for editors when saving/loading, and shouldn't be changed by anything else. Fails if another [code]Resource[/code] already has path "path".
</description>
</method>
<method name="setup_local_to_scene">
@@ -96,7 +96,7 @@
<argument index="0" name="path" type="String">
</argument>
<description>
- Set the path of the resource. Differs from set_path(), if another [Resource] exists with "path" it over-takes it, instead of failing.
+ Set the path of the resource. Differs from set_path(), if another [code]Resource[/code] exists with "path" it over-takes it, instead of failing.
</description>
</method>
</methods>
diff --git a/doc/classes/ResourceImporter.xml b/doc/classes/ResourceImporter.xml
index 419c4a84fb..b627438c89 100644
--- a/doc/classes/ResourceImporter.xml
+++ b/doc/classes/ResourceImporter.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ResourceImporter" inherits="Reference" category="Core" version="3.0.alpha.custom_build">
+<class name="ResourceImporter" inherits="Reference" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/ResourceInteractiveLoader.xml b/doc/classes/ResourceInteractiveLoader.xml
index d508b0a532..866347c0bb 100644
--- a/doc/classes/ResourceInteractiveLoader.xml
+++ b/doc/classes/ResourceInteractiveLoader.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ResourceInteractiveLoader" inherits="Reference" category="Core" version="3.0.alpha.custom_build">
+<class name="ResourceInteractiveLoader" inherits="Reference" category="Core" version="3.0-alpha">
<brief_description>
Interactive Resource Loader.
</brief_description>
diff --git a/doc/classes/ResourceLoader.xml b/doc/classes/ResourceLoader.xml
index 6558a388c8..5940031a76 100644
--- a/doc/classes/ResourceLoader.xml
+++ b/doc/classes/ResourceLoader.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ResourceLoader" inherits="Object" category="Core" version="3.0.alpha.custom_build">
+<class name="ResourceLoader" inherits="Object" category="Core" version="3.0-alpha">
<brief_description>
Resource Loader.
</brief_description>
<description>
- Resource Loader. This is a static object accessible as [ResourceLoader]. GDScript has a simplified load() function, though.
+ Resource Loader. This is a static object accessible as [code]ResourceLoader[/code]. GDScript has a simplified load() function, though.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/ResourcePreloader.xml b/doc/classes/ResourcePreloader.xml
index 35ebeb1760..f4c3334107 100644
--- a/doc/classes/ResourcePreloader.xml
+++ b/doc/classes/ResourcePreloader.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ResourcePreloader" inherits="Node" category="Core" version="3.0.alpha.custom_build">
+<class name="ResourcePreloader" inherits="Node" category="Core" version="3.0-alpha">
<brief_description>
Resource Preloader Node.
</brief_description>
diff --git a/doc/classes/ResourceSaver.xml b/doc/classes/ResourceSaver.xml
index de296776ad..af9c592ded 100644
--- a/doc/classes/ResourceSaver.xml
+++ b/doc/classes/ResourceSaver.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ResourceSaver" inherits="Object" category="Core" version="3.0.alpha.custom_build">
+<class name="ResourceSaver" inherits="Object" category="Core" version="3.0-alpha">
<brief_description>
Resource Saving Interface.
</brief_description>
diff --git a/doc/classes/RichTextLabel.xml b/doc/classes/RichTextLabel.xml
index 9f8cdcce6d..18e77ff5e3 100644
--- a/doc/classes/RichTextLabel.xml
+++ b/doc/classes/RichTextLabel.xml
@@ -1,10 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="RichTextLabel" inherits="Control" category="Core" version="3.0.alpha.custom_build">
+<class name="RichTextLabel" inherits="Control" category="Core" version="3.0-alpha">
<brief_description>
Label that displays rich text.
</brief_description>
<description>
- Label that displays rich text. Rich text can contain custom text, fonts, images and some basic formatting. It also adapts itself to given width/heights.
+ Rich text can contain custom text, fonts, images and some basic formatting. The label manages these as an internal tag stack. It also adapts itself to given width/heights.
+ Note that assignments to [member bbcode_text] clear the tag stack and reconstruct it from the property's contents. Any edits made to [member bbcode_text] will erase previous edits made from other manual sources such as [method append_bbcode] and the [code]push_*[/code] / [method pop] methods.
</description>
<tutorials>
</tutorials>
@@ -17,6 +18,7 @@
<argument index="0" name="image" type="Texture">
</argument>
<description>
+ Adds an image's opening and closing tags to the tag stack.
</description>
</method>
<method name="add_text">
@@ -25,6 +27,7 @@
<argument index="0" name="text" type="String">
</argument>
<description>
+ Adds raw non-bbcode-parsed text to the tag stack.
</description>
</method>
<method name="append_bbcode">
@@ -33,55 +36,63 @@
<argument index="0" name="bbcode" type="String">
</argument>
<description>
+ Parses [code]bbcode[/code] and adds tags to the tag stack as needed. Returns the result of the parsing, [code]OK[/code] if successful.
</description>
</method>
<method name="clear">
<return type="void">
</return>
<description>
+ Clears the tag stack and sets [member bbcode_text] to an empty string.
</description>
</method>
<method name="get_bbcode" qualifiers="const">
<return type="String">
</return>
<description>
+ Returns the bbcode-parsed [member bbcode_text].
</description>
</method>
<method name="get_line_count" qualifiers="const">
<return type="int">
</return>
<description>
+ Returns the total number of newlines in the tag stack's text tags. Considers wrapped text as one line.
</description>
</method>
<method name="get_percent_visible" qualifiers="const">
<return type="float">
</return>
<description>
+ Returns the text's visibility as a floating point value between 0.0 and 1.0.
</description>
</method>
<method name="get_tab_size" qualifiers="const">
<return type="int">
</return>
<description>
+ Returns the number of spaces associated with a single tab length. Does not affect "\t" in text tags, only indent tags.
</description>
</method>
<method name="get_text">
<return type="String">
</return>
<description>
- Returns the raw text, stripping out the formatting information.
+ Returns the raw content of [member bbcode_text].
</description>
</method>
<method name="get_total_character_count" qualifiers="const">
<return type="int">
</return>
<description>
+ Returns the total number of characters from text tags. Does not include bbcodes.
</description>
</method>
<method name="get_v_scroll">
<return type="VScrollBar">
</return>
<description>
+ Returns the vertical scrollbar.
</description>
</method>
<method name="get_visible_characters" qualifiers="const">
@@ -94,31 +105,41 @@
<return type="int">
</return>
<description>
+ Returns the number of visible lines.
</description>
</method>
<method name="is_meta_underlined" qualifiers="const">
<return type="bool">
</return>
<description>
+ Returns [code]true[/code] if the label underlines meta tags such as [url]{text}[/url].
+ </description>
+ </method>
+ <method name="is_overriding_selected_font_color" qualifiers="const">
+ <return type="bool">
+ </return>
+ <description>
</description>
</method>
<method name="is_scroll_active" qualifiers="const">
<return type="bool">
</return>
<description>
+ Returns [code]true[/code] if the scrollbar is visible. Does not block scrolling completely. See [method scroll_to_line].
</description>
</method>
<method name="is_scroll_following" qualifiers="const">
<return type="bool">
</return>
<description>
+ Returns [code]true[/code] if the window scrolls down to display new content automatically.
</description>
</method>
<method name="is_selection_enabled" qualifiers="const">
<return type="bool">
</return>
<description>
- Return true if selecting the text inside this richtext is allowed.
+ Returns [code]true[/code] if the label allows text selection.
</description>
</method>
<method name="is_using_bbcode" qualifiers="const">
@@ -131,6 +152,7 @@
<return type="void">
</return>
<description>
+ Adds a newline tag to the tag stack.
</description>
</method>
<method name="parse_bbcode">
@@ -139,12 +161,14 @@
<argument index="0" name="bbcode" type="String">
</argument>
<description>
+ The assignment version of [method append_bbcode]. Clears the tag stack and inserts the new content. Returns [code]OK[/code] if parses [code]bbcode[/code] successfully.
</description>
</method>
<method name="pop">
<return type="void">
</return>
<description>
+ Terminates the current tag. Use after [code]push_*[/code] methods to close bbcodes manually. Does not need to follow [code]add_*[/code] methods.
</description>
</method>
<method name="push_align">
@@ -153,12 +177,14 @@
<argument index="0" name="align" type="int" enum="RichTextLabel.Align">
</argument>
<description>
+ Adds a [code][right][/code] tag to the tag stack.
</description>
</method>
<method name="push_cell">
<return type="void">
</return>
<description>
+ Adds a [code][cell][/code] tag to the tag stack. Must be inside a [table] tag. See [method push_table] for details.
</description>
</method>
<method name="push_color">
@@ -167,6 +193,7 @@
<argument index="0" name="color" type="Color">
</argument>
<description>
+ Adds a [code][color][/code] tag to the tag stack.
</description>
</method>
<method name="push_font">
@@ -175,6 +202,7 @@
<argument index="0" name="font" type="Font">
</argument>
<description>
+ Adds a [code][font][/code] tag to the tag stack. Overrides default fonts for its duration.
</description>
</method>
<method name="push_indent">
@@ -183,6 +211,7 @@
<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.
</description>
</method>
<method name="push_list">
@@ -191,6 +220,7 @@
<argument index="0" name="type" type="int" enum="RichTextLabel.ListType">
</argument>
<description>
+ Adds a list tag to the tag stack. Similar to the bbcodes [code][ol][/code] or [code][ul][/code], but supports more list types. Not fully implemented!
</description>
</method>
<method name="push_meta">
@@ -199,6 +229,7 @@
<argument index="0" name="data" type="Variant">
</argument>
<description>
+ Adds a meta tag to the tag stack. Similar to the bbcode [code][url=something]{text}[/url][/code], but supports non-[String] metadata types.
</description>
</method>
<method name="push_table">
@@ -207,12 +238,14 @@
<argument index="0" name="columns" type="int">
</argument>
<description>
+ Adds a [code][table=columns][/code] tag to the tag stack.
</description>
</method>
<method name="push_underline">
<return type="void">
</return>
<description>
+ Adds a [code][u][/code] tag to the tag stack.
</description>
</method>
<method name="remove_line">
@@ -221,6 +254,7 @@
<argument index="0" name="line" type="int">
</argument>
<description>
+ Removes a line of content from the label. Returns [code]true[/code] if the line exists.
</description>
</method>
<method name="scroll_to_line">
@@ -229,6 +263,7 @@
<argument index="0" name="line" type="int">
</argument>
<description>
+ Scrolls the window's top line to match [code]line[/code].
</description>
</method>
<method name="set_bbcode">
@@ -237,6 +272,7 @@
<argument index="0" name="text" type="String">
</argument>
<description>
+ Sets the BBCode text to the label.
</description>
</method>
<method name="set_meta_underline">
@@ -245,6 +281,15 @@
<argument index="0" name="enable" type="bool">
</argument>
<description>
+ If [code]true[/code] will underline meta tags such as the [url] bbcode. Default value: [code]true[/code].
+ </description>
+ </method>
+ <method name="set_override_selected_font_color">
+ <return type="void">
+ </return>
+ <argument index="0" name="override" type="bool">
+ </argument>
+ <description>
</description>
</method>
<method name="set_percent_visible">
@@ -253,6 +298,7 @@
<argument index="0" name="percent_visible" type="float">
</argument>
<description>
+ Sets the text's visibility. Takes a floating point value between 0.0 and 1.0.
</description>
</method>
<method name="set_scroll_active">
@@ -261,6 +307,7 @@
<argument index="0" name="active" type="bool">
</argument>
<description>
+ If [code]false[/code] the vertical scrollbar is hidden. Default value: [code]true[/code].
</description>
</method>
<method name="set_scroll_follow">
@@ -269,6 +316,7 @@
<argument index="0" name="follow" type="bool">
</argument>
<description>
+ If [code]true[/code] the window scrolls to reveal new content. Default value: [code]false[/code].
</description>
</method>
<method name="set_selection_enabled">
@@ -277,7 +325,7 @@
<argument index="0" name="enabled" type="bool">
</argument>
<description>
- Set to true if selecting the text inside this richtext is allowed.
+ If [code]true[/code] text can be selected.
</description>
</method>
<method name="set_tab_size">
@@ -286,6 +334,7 @@
<argument index="0" name="spaces" type="int">
</argument>
<description>
+ Sets the current tab length in spaces. Use with [method push_indent] to redefine indent length.
</description>
</method>
<method name="set_table_column_expand">
@@ -298,6 +347,9 @@
<argument index="2" name="ratio" type="int">
</argument>
<description>
+ Edits the selected columns expansion options. If [code]expand[/code] is [code]true[/code], the column expands in proportion to its expansion ratio versus the other columns' ratios.
+ For example, 2 columns with ratios 3 and 4 plus 70 pixels in available width would expand 30 and 40 pixels, respectively.
+ Columns with a [code]false[/code] expand will not contribute to the total ratio.
</description>
</method>
<method name="set_text">
@@ -306,6 +358,7 @@
<argument index="0" name="text" type="String">
</argument>
<description>
+ Clears the tag stack and adds a raw text tag to the top of it. Does not parse bbcodes. Does not modify [member bbcode_text].
</description>
</method>
<method name="set_use_bbcode">
@@ -327,12 +380,19 @@
</methods>
<members>
<member name="bbcode_enabled" type="bool" setter="set_use_bbcode" getter="is_using_bbcode">
+ If [code]true[/code] the label uses BBCode formatting. Default value: [code]false[/code].
</member>
<member name="bbcode_text" type="String" setter="set_bbcode" getter="get_bbcode">
+ The label's text in BBCode format. Is not representative of manual modifications to the internal tag stack. Erases changes made by other methods when edited.
+ </member>
+ <member name="override_selected_font_color" type="bool" setter="set_override_selected_font_color" getter="is_overriding_selected_font_color">
+ If [code]true[/code] the label uses the custom font color. Default value: [code]false[/code].
</member>
<member name="percent_visible" type="float" setter="set_percent_visible" getter="get_percent_visible">
+ The text's visibility, as a [float] between 0.0 and 1.0.
</member>
<member name="visible_characters" type="int" setter="set_visible_characters" getter="get_visible_characters">
+ The restricted number of characters to display in the label.
</member>
</members>
<signals>
@@ -340,6 +400,21 @@
<argument index="0" name="meta" type="Nil">
</argument>
<description>
+ Triggered when the user clicks on content between [url] 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_started">
+ <argument index="0" name="meta" type="Nil">
+ </argument>
+ <description>
+ Triggers when the mouse enters a meta tag.
+ </description>
+ </signal>
+ <signal name="meta_hover_ended">
+ <argument index="0" name="meta" type="Nil">
+ </argument>
+ <description>
+ Triggers when the mouse exits a meta tag.
</description>
</signal>
</signals>
@@ -378,6 +453,8 @@
</constant>
<constant name="ITEM_LIST" value="9">
</constant>
+ <constant name="ITEM_TABLE" value="10">
+ </constant>
<constant name="ITEM_META" value="11">
</constant>
</constants>
diff --git a/doc/classes/RigidBody.xml b/doc/classes/RigidBody.xml
index 76a93248fb..d40f7b4429 100644
--- a/doc/classes/RigidBody.xml
+++ b/doc/classes/RigidBody.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="RigidBody" inherits="PhysicsBody" category="Core" version="3.0.alpha.custom_build">
+<class name="RigidBody" inherits="PhysicsBody" category="Core" version="3.0-alpha">
<brief_description>
Physics Body whose position is determined through physics simulation in 3D space.
</brief_description>
@@ -430,18 +430,18 @@
</signal>
</signals>
<constants>
- <constant name="MODE_STATIC" value="1">
- Static mode. The body behaves like a [StaticBody], and can only move by user code.
- </constant>
- <constant name="MODE_KINEMATIC" value="3">
- Kinematic body. The body behaves like a [KinematicBody], and can only move by user code.
- </constant>
<constant name="MODE_RIGID" value="0">
Rigid body. This is the "natural" state of a rigid body. It is affected by forces, and can move, rotate, and be affected by user code.
</constant>
+ <constant name="MODE_STATIC" value="1">
+ Static mode. The body behaves like a [StaticBody], and can only move by user code.
+ </constant>
<constant name="MODE_CHARACTER" value="2">
Character body. This behaves like a rigid body, but can not rotate.
</constant>
+ <constant name="MODE_KINEMATIC" value="3">
+ Kinematic body. The body behaves like a [KinematicBody], and can only move by user code.
+ </constant>
<constant name="AXIS_LOCK_DISABLED" value="0">
</constant>
<constant name="AXIS_LOCK_X" value="1">
diff --git a/doc/classes/RigidBody2D.xml b/doc/classes/RigidBody2D.xml
index a4faa697de..af8e59c83b 100644
--- a/doc/classes/RigidBody2D.xml
+++ b/doc/classes/RigidBody2D.xml
@@ -1,14 +1,17 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="RigidBody2D" inherits="PhysicsBody2D" category="Core" version="3.0.alpha.custom_build">
+<class name="RigidBody2D" inherits="PhysicsBody2D" category="Core" version="3.0-alpha">
<brief_description>
- Physics Body whose position is determined through physics simulation in 2D space.
+ A body that is controlled by the 2D physics engine.
</brief_description>
<description>
- This is the node that implements full 2D physics. This means that you do not control a RigidBody2D directly. Instead you can apply forces to it (gravity, impulses, etc.), and the physics simulation will calculate the resulting movement, collision, bouncing, rotating, etc.
- This node can use custom force integration, for writing complex physics motion behavior per node.
- This node can shift state between regular Rigid body, Kinematic, Character or Static.
- Character mode forbids this node from being rotated.
- As a warning, don't change RigidBody2D's position every frame or very often. Sporadic changes work fine, but physics runs at a different granularity (fixed hz) than usual rendering (process callback) and maybe even in a separate thread, so changing this from a process loop will yield strange behavior.
+ This node implements simulated 2D physics. You do not control a RigidBody2D directly. Instead you apply forces to it (gravity, impulses, etc.) and the physics simulation calculates the resulting movement based on its mass, friction, and other physical properties.
+ A RigidBody2D has 4 behavior modes (see [member mode]):
+ - [b]Rigid[/b]: The body behaves as a physical object. It collides with other bodies and responds to forces applied to it. This is the default mode.
+ - [b]Static[/b]: The body behaves like a [StaticBody2D] and does not move.
+ - [b]Character[/b]: Similar to [code]Rigid[/code] mode, but the body can not rotate.
+ - [b]Kinematic[/b]: The body behaves like a [KinematicBody2D], and must be moved by code.
+ [b]Note:[/b] You should not change a RigidBody2D's [code]position[/code] or [code]linear_velocity[/code] every frame or even very often. If you need to directly affect the body's state, use [method _integrate_forces], which allows you to directly access the physics state.
+ If you need to override the default physics behavior, you can write a custom force integration. See [member custom_integrator].
</description>
<tutorials>
</tutorials>
@@ -21,7 +24,7 @@
<argument index="0" name="state" type="Physics2DDirectBodyState">
</argument>
<description>
- Called during physics processing, allowing you to read and safely modify the simulation state for the object. By default it works in addition to the usual physics behavior, but [method set_use_custom_integrator] allows you to disable the default behavior and do fully custom force integration for a body.
+ Allows you to read and safely modify the simulation state for the object. Use this instead of [Node._physics_process] if you need to directly change the body's [code]position[/code] or other physics properties. By default it works in addition to the usual physics behavior, but [member custom_integrator] allows you to disable the default behavior and write custom force integration for a body.
</description>
</method>
<method name="add_force">
@@ -32,7 +35,7 @@
<argument index="1" name="force" type="Vector2">
</argument>
<description>
- Add a positioned force to the applied force and torque. As with [method apply_impulse], both the force and the offset from the body origin are in global coordinates.
+ Adds a positioned force to the body. Both the force and the offset from the body origin are in global coordinates.
</description>
</method>
<method name="apply_impulse">
@@ -43,7 +46,7 @@
<argument index="1" name="impulse" type="Vector2">
</argument>
<description>
- Apply a positioned impulse (which will be affected by the body mass and shape). This is the equivalent of hitting a billiard ball with a cue: a force that is applied once, and only once. Both the impulse and the offset from the body origin are in global coordinates.
+ Applies a positioned impulse to the body (which will be affected by the body mass and shape). This is the equivalent of hitting a billiard ball with a cue: a force that is applied instantaneously. Both the impulse and the offset from the body origin are in global coordinates.
</description>
</method>
<method name="get_angular_damp" qualifiers="const">
@@ -64,14 +67,14 @@
<return type="Vector2">
</return>
<description>
- Return the applied force vector.
+ Returns the body's total applied force.
</description>
</method>
<method name="get_applied_torque" qualifiers="const">
<return type="float">
</return>
<description>
- Return the torque which is being applied to this body.
+ Returns the body's total applied torque.
</description>
</method>
<method name="get_bounce" qualifiers="const">
@@ -85,7 +88,7 @@
<return type="Array">
</return>
<description>
- Return a list of the bodies colliding with this one. By default, number of max contacts reported is at 0 , see [method set_max_contacts_reported] to increase it. You must also enable contact monitor, see [method set_contact_monitor]
+ Returns a list of the bodies colliding with this one. Use [member contacts_reported] to set the maximum number reported. You must also set [member contact_monitor] to [code]true[/code].
</description>
</method>
<method name="get_continuous_collision_detection_mode" qualifiers="const">
@@ -113,7 +116,7 @@
<return type="float">
</return>
<description>
- Return the body's moment of inertia. This is usually automatically computed from the mass and the shapes. Note that this doesn't seem to work in a [code]_ready[/code] function: it apparently has not been auto-computed yet.
+ Returns the body's moment of inertia, which is computed automatically from the body's mass and assigned [Shape2D]s during the physics frame. Note that it will not yet have a value in the [code]_ready()[/code] function.
</description>
</method>
<method name="get_linear_damp" qualifiers="const">
@@ -127,7 +130,7 @@
<return type="Vector2">
</return>
<description>
- Return the body linear velocity. This changes by physics granularity. See [method set_linear_velocity].
+ Returns the body's linear velocity. This changes when a physics frame has passed, not during a normal update. See [method set_linear_velocity].
</description>
</method>
<method name="get_mass" qualifiers="const">
@@ -210,7 +213,7 @@
<argument index="0" name="force" type="Vector2">
</argument>
<description>
- Set the applied force vector. This is the equivalent of pushing a box over the ground: the force applied is applied constantly.
+ Sets the applied force vector. This is the equivalent of firing a rocket: the force is applied constantly.
</description>
</method>
<method name="set_applied_torque">
@@ -219,7 +222,7 @@
<argument index="0" name="torque" type="float">
</argument>
<description>
- Set a constant torque which will be applied to this body.
+ Sets the applied torque.
</description>
</method>
<method name="set_axis_velocity">
@@ -228,7 +231,7 @@
<argument index="0" name="axis_velocity" type="Vector2">
</argument>
<description>
- Set an axis velocity. The velocity in the given vector axis will be set as the given vector length. This is useful for jumping behavior.
+ Sets the body's velocity on the given axis. The velocity in the given vector axis will be set as the given vector length. This is useful for jumping behavior.
</description>
</method>
<method name="set_bounce">
@@ -378,59 +381,59 @@
<argument index="2" name="result" type="Physics2DTestMotionResult" default="null">
</argument>
<description>
- Return whether the body would collide, if it tried to move in the given vector. This method allows two extra parameters: A margin, which increases slightly the size of the shapes involved in the collision detection, and an object of type [Physics2DTestMotionResult], which will store additional information about the collision (should there be one).
+ Returns [code]true[/code] if a collision would result from moving in the given vector. [code]margin[/code] increases the size of the shapes involved in the collision detection, and [code]result[/code] is an object of type [Physics2DTestMotionResult], which contains additional information about the collision (should there be one).
</description>
</method>
</methods>
<members>
<member name="angular_damp" type="float" setter="set_angular_damp" getter="get_angular_damp">
- Damps RigidBody2D's rotational forces.
+ Damps the body's [member angular_velocity]. If [code]-1[/code] the body will use the "Default Angular Damp" in "Project &gt; Project Settings &gt; Physics &gt; 2d". Default value: [code]-1[/code].
</member>
<member name="angular_velocity" type="float" setter="set_angular_velocity" getter="get_angular_velocity">
- RigidBody2D's rotational velocity.
+ The body's rotational velocity.
</member>
<member name="bounce" type="float" setter="set_bounce" getter="get_bounce">
- RigidBody2D's bounciness.
+ The body's bounciness. Default value: [code]0[/code].
</member>
<member name="can_sleep" type="bool" setter="set_can_sleep" getter="is_able_to_sleep">
- If [code]true[/code] RigidBody2D will not calculate forces and will act as a static body while there is no movement. It will wake up when other forces are applied through other collisions or when the [code]apply_impulse[/code] method is used. Default value: [code]true[/code]
+ If [code]true[/code] the body will not calculate forces and will act as a static body if there is no movement. The body will wake up when other forces are applied via collisions or by using [method apply_impulse] or [method add_force]. Default value: [code]true[/code].
</member>
<member name="contact_monitor" type="bool" setter="set_contact_monitor" getter="is_contact_monitor_enabled">
- If [code]true[/code] RigidBody2D will emit signals when it collides with another RigidBody2D.
+ If [code]true[/code] the body will emit signals when it collides with another RigidBody2D. See also [member contacts_reported]. Default value: [code]false[/code].
</member>
<member name="contacts_reported" type="int" setter="set_max_contacts_reported" getter="get_max_contacts_reported">
- The maximum contacts to report. Bodies can keep a log of the contacts with other bodies, this is enabled by setting the maximum amount of contacts reported to a number greater than 0.
+ The maximum number of contacts to report. Default value: [code]0[/code].
</member>
<member name="continuous_cd" type="int" setter="set_continuous_collision_detection_mode" getter="get_continuous_collision_detection_mode" enum="RigidBody2D.CCDMode">
- If [code]true[/code] continuous collision detection is used. Default value: [code]false[/code]
- Continuous collision detection tries to predict where a moving body will collide, instead of moving it and correcting its movement if it collided. Continuous collision detection is more precise, and misses less impacts by small, fast-moving objects. Not using continuous collision detection is faster to compute, but can miss small, fast-moving objects.
+ Continuous collision detection mode. Default value: [code]CCD_MODE_DISABLED[/code].
+ Continuous collision detection tries to predict where a moving body will collide instead of moving it and correcting its movement after collision. Continuous collision detection is slower, but more precise and misses fewer collisions with small, fast-moving objects. Raycasting and shapecasting methods are available. See [code]CCD_MODE_[/code] constants for details.
</member>
<member name="custom_integrator" type="bool" setter="set_use_custom_integrator" getter="is_using_custom_integrator">
- If [code]true[/code] internal force integration will be disabled (like gravity or air friction) for this body. Other than collision response, the body will only move as determined by the [method _integrate_forces] function, if defined.
+ If [code]true[/code] internal force integration is disabled for this body. Aside from collision response, the body will only move as determined by the [method _integrate_forces] function.
</member>
<member name="friction" type="float" setter="set_friction" getter="get_friction">
- The body friction, from 0 (frictionless) to 1 (max friction).
+ The body's friction. Values range from [code]0[/code] (frictionless) to [code]1[/code] (maximum friction). Default value: [code]1[/code].
</member>
<member name="gravity_scale" type="float" setter="set_gravity_scale" getter="get_gravity_scale">
- This is multiplied by the global 2D gravity setting found in "Project &gt; Project Settings &gt; Physics &gt; 2d" to produce RigidBody2D's gravity. E.g. a value of 1 will be normal gravity, 2 will apply double gravity, and 0.5 will apply half gravity to this object.
+ Multiplies the gravity applied to the body. The body's gravity is calculated from the "Default Gravity" value in "Project &gt; Project Settings &gt; Physics &gt; 2d" and/or any additional gravity vector applied by [Area2D]s. Default value: [code]1[/code].
</member>
<member name="linear_damp" type="float" setter="set_linear_damp" getter="get_linear_damp">
- RigidBody2D's linear damp. Default of -1, cannot be less than -1. If this value is different from -1, any linear damp derived from the world or areas will be overridden.
+ Damps the body's [member linear_velocity]. If [code]-1[/code] the body will use the "Default Linear Damp" in "Project &gt; Project Settings &gt; Physics &gt; 2d". Default value: [code]-1[/code].
</member>
<member name="linear_velocity" type="Vector2" setter="set_linear_velocity" getter="get_linear_velocity">
- RigidBody2D's linear velocity. Can be used sporadically, but [b]DON'T SET THIS IN EVERY FRAME[/b], because physics may run in another thread and runs at a different granularity. Use [method _integrate_forces] as your process loop for precise control of the body state.
+ The body's linear velocity.
</member>
<member name="mass" type="float" setter="set_mass" getter="get_mass">
- RigidBody2D's mass.
+ The body's mass. Default value: [code]1[/code].
</member>
<member name="mode" type="int" setter="set_mode" getter="get_mode" enum="RigidBody2D.Mode">
- The body mode from the MODE_* enum. Modes include: MODE_STATIC, MODE_KINEMATIC, MODE_RIGID, and MODE_CHARACTER.
+ The body's mode. See [code]MODE_*[/code] constants. Default value: [code]MODE_RIGID[/code].
</member>
<member name="sleeping" type="bool" setter="set_sleeping" getter="is_sleeping">
- If [code]true[/code] RigidBody2D is sleeping and will not calculate forces until woken up by a collision or the [code]apply_impulse[/code] method.
+ If [code]true[/code] the body is sleeping and will not calculate forces until woken up by a collision or by using [method apply_impulse] or [method add_force].
</member>
<member name="weight" type="float" setter="set_weight" getter="get_weight">
- RigidBody2D's weight based on its mass and the global 2D gravity. Global values are set in "Project &gt; Project Settings &gt; Physics &gt; 2d".
+ The body's weight based on its mass and the "Default Gravity" value in "Project &gt; Project Settings &gt; Physics &gt; 2d".
</member>
</members>
<signals>
@@ -438,14 +441,14 @@
<argument index="0" name="body" type="Object">
</argument>
<description>
- Emitted when a body enters into contact with this one. Contact monitor and contacts reported must be enabled for this to work.
+ Emitted when a body enters into contact with this one. [member contact_monitor] must be [code]true[/code] and [member contacts_reported] greater than [code]0[/code].
</description>
</signal>
<signal name="body_exited">
<argument index="0" name="body" type="Object">
</argument>
<description>
- Emitted when a body exits contact with this one. Contact monitor and contacts reported must be enabled for this to work.
+ Emitted when a body exits contact with this one. [member contact_monitor] must be [code]true[/code] and [member contacts_reported] greater than [code]0[/code].
</description>
</signal>
<signal name="body_shape_entered">
@@ -458,8 +461,7 @@
<argument index="3" name="local_shape" type="int">
</argument>
<description>
- Emitted when a body enters into contact with this one. Contact monitor and contacts reported must be enabled for this to work.
- This signal not only receives the body that collided with this one, but also its [RID] (body_id), the shape index from the colliding body (body_shape), and the shape index from this body (local_shape) the other body collided with.
+ Emitted when a body enters into contact with this one. Reports colliding shape information. See [CollisionObject2D] for shape index information. [member contact_monitor] must be [code]true[/code] and [member contacts_reported] greater than [code]0[/code].
</description>
</signal>
<signal name="body_shape_exited">
@@ -472,37 +474,36 @@
<argument index="3" name="local_shape" type="int">
</argument>
<description>
- Emitted when a body shape exits contact with this one. Contact monitor and contacts reported must be enabled for this to work.
- This signal not only receives the body that stopped colliding with this one, but also its [RID] (body_id), the shape index from the colliding body (body_shape), and the shape index from this body (local_shape) the other body stopped colliding with.
+ Emitted when a body shape exits contact with this one. Reports colliding shape information. See [CollisionObject2D] for shape index information. [member contact_monitor] must be [code]true[/code] and [member contacts_reported] greater than [code]0[/code].
</description>
</signal>
<signal name="sleeping_state_changed">
<description>
- Emitted when the body changes its sleeping state. Either by sleeping or waking up.
+ Emitted when [member sleeping] changes.
</description>
</signal>
</signals>
<constants>
- <constant name="MODE_STATIC" value="1">
- Static mode. The body behaves like a [StaticBody2D], and can only move by user code.
- </constant>
- <constant name="MODE_KINEMATIC" value="3">
- Kinematic body. The body behaves like a [KinematicBody2D], and can only move by user code.
- </constant>
<constant name="MODE_RIGID" value="0">
- Rigid body. This is the "natural" state of a rigid body. It is affected by forces, and can move, rotate, and be affected by user code.
+ Rigid mode. The body behaves as a physical object. It collides with other bodies and responds to forces applied to it. This is the default mode.
+ </constant>
+ <constant name="MODE_STATIC" value="1">
+ Static mode. The body behaves like a [StaticBody2D] and does not move.
</constant>
<constant name="MODE_CHARACTER" value="2">
- Character body. This behaves like a rigid body, but can not rotate.
+ Character mode. Similar to [code]MODE_RIGID[/code], but the body can not rotate.
+ </constant>
+ <constant name="MODE_KINEMATIC" value="3">
+ Kinematic mode. The body behaves like a [KinematicBody2D], and must be moved by code.
</constant>
<constant name="CCD_MODE_DISABLED" value="0">
- Disables continuous collision detection. This is the fastest way to detect body collisions, but can miss small, fast-moving objects.
+ Continuous collision detection disabled. This is the fastest way to detect body collisions, but can miss small, fast-moving objects.
</constant>
<constant name="CCD_MODE_CAST_RAY" value="1">
- Enables continuous collision detection by raycasting. It is faster than shapecasting, but less precise.
+ Continuous collision detection enabled using raycasting. This is faster than shapecasting but less precise.
</constant>
<constant name="CCD_MODE_CAST_SHAPE" value="2">
- Enables continuous collision detection by shapecasting. It is the slowest CCD method, and the most precise.
+ Continuous collision detection enabled using shapecasting. This is the slowest CCD method and the most precise.
</constant>
</constants>
</class>
diff --git a/doc/classes/SceneState.xml b/doc/classes/SceneState.xml
index 967c3fbad6..61e08336db 100644
--- a/doc/classes/SceneState.xml
+++ b/doc/classes/SceneState.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="SceneState" inherits="Reference" category="Core" version="3.0.alpha.custom_build">
+<class name="SceneState" inherits="Reference" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/SceneTree.xml b/doc/classes/SceneTree.xml
index c40d9339d1..7cfacc737d 100644
--- a/doc/classes/SceneTree.xml
+++ b/doc/classes/SceneTree.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="SceneTree" inherits="MainLoop" category="Core" version="3.0.alpha.custom_build">
+<class name="SceneTree" inherits="MainLoop" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
@@ -313,7 +313,7 @@
</argument>
<argument index="2" name="minsize" type="Vector2">
</argument>
- <argument index="3" name="shrink" type="int" default="1">
+ <argument index="3" name="shrink" type="float" default="1">
</argument>
<description>
</description>
@@ -336,10 +336,6 @@
<description>
</description>
</signal>
- <signal name="fixed_frame">
- <description>
- </description>
- </signal>
<signal name="idle_frame">
<description>
</description>
@@ -356,6 +352,12 @@
<description>
</description>
</signal>
+ <signal name="node_added">
+ <argument index="0" name="node" type="Object">
+ </argument>
+ <description>
+ </description>
+ </signal>
<signal name="node_configuration_warning_changed">
<argument index="0" name="node" type="Object">
</argument>
@@ -368,6 +370,10 @@
<description>
</description>
</signal>
+ <signal name="physics_frame">
+ <description>
+ </description>
+ </signal>
<signal name="screen_resized">
<description>
</description>
@@ -404,5 +410,7 @@
</constant>
<constant name="STRETCH_ASPECT_KEEP_HEIGHT" value="3">
</constant>
+ <constant name="STRETCH_ASPECT_EXPAND" value="4">
+ </constant>
</constants>
</class>
diff --git a/doc/classes/SceneTreeTimer.xml b/doc/classes/SceneTreeTimer.xml
index 276c6857ae..6c540396e5 100644
--- a/doc/classes/SceneTreeTimer.xml
+++ b/doc/classes/SceneTreeTimer.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="SceneTreeTimer" inherits="Reference" category="Core" version="3.0.alpha.custom_build">
+<class name="SceneTreeTimer" inherits="Reference" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/Script.xml b/doc/classes/Script.xml
index 307afba8a7..83e33c4764 100644
--- a/doc/classes/Script.xml
+++ b/doc/classes/Script.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Script" inherits="Resource" category="Core" version="3.0.alpha.custom_build">
+<class name="Script" inherits="Resource" category="Core" version="3.0-alpha">
<brief_description>
A class stored as a resource.
</brief_description>
@@ -19,12 +19,6 @@
Returns true if the script can be instanced.
</description>
</method>
- <method name="get_node_type" qualifiers="const">
- <return type="String">
- </return>
- <description>
- </description>
- </method>
<method name="get_source_code" qualifiers="const">
<return type="String">
</return>
diff --git a/doc/classes/ScriptEditor.xml b/doc/classes/ScriptEditor.xml
index e93a0eda0c..7a95f1276e 100644
--- a/doc/classes/ScriptEditor.xml
+++ b/doc/classes/ScriptEditor.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ScriptEditor" inherits="PanelContainer" category="Core" version="3.0.alpha.custom_build">
+<class name="ScriptEditor" inherits="PanelContainer" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
@@ -9,6 +9,30 @@
<demos>
</demos>
<methods>
+ <method name="can_drop_data_fw" qualifiers="const">
+ <return type="bool">
+ </return>
+ <argument index="0" name="arg0" type="Vector2">
+ </argument>
+ <argument index="1" name="arg1" type="Variant">
+ </argument>
+ <argument index="2" name="arg2" type="Control">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="drop_data_fw">
+ <return type="void">
+ </return>
+ <argument index="0" name="arg0" type="Vector2">
+ </argument>
+ <argument index="1" name="arg1" type="Variant">
+ </argument>
+ <argument index="2" name="arg2" type="Control">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="get_current_script">
<return type="Script">
</return>
@@ -16,6 +40,16 @@
Returns a [Script] that is currently active in editor.
</description>
</method>
+ <method name="get_drag_data_fw">
+ <return type="Variant">
+ </return>
+ <argument index="0" name="arg0" type="Vector2">
+ </argument>
+ <argument index="1" name="arg1" type="Control">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="get_open_scripts" qualifiers="const">
<return type="Array">
</return>
diff --git a/doc/classes/ScrollBar.xml b/doc/classes/ScrollBar.xml
index 7a10d3679e..312baf3bb6 100644
--- a/doc/classes/ScrollBar.xml
+++ b/doc/classes/ScrollBar.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ScrollBar" inherits="Range" category="Core" version="3.0.alpha.custom_build">
+<class name="ScrollBar" inherits="Range" category="Core" version="3.0-alpha">
<brief_description>
Base class for scroll bars.
</brief_description>
diff --git a/doc/classes/ScrollContainer.xml b/doc/classes/ScrollContainer.xml
index 1ae06bde70..51bd950cd9 100644
--- a/doc/classes/ScrollContainer.xml
+++ b/doc/classes/ScrollContainer.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ScrollContainer" inherits="Container" category="Core" version="3.0.alpha.custom_build">
+<class name="ScrollContainer" inherits="Container" category="Core" version="3.0-alpha">
<brief_description>
A helper node for displaying scrollable elements (e.g. lists).
</brief_description>
diff --git a/doc/classes/SegmentShape2D.xml b/doc/classes/SegmentShape2D.xml
index 3b7a747bcb..c59370018d 100644
--- a/doc/classes/SegmentShape2D.xml
+++ b/doc/classes/SegmentShape2D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="SegmentShape2D" inherits="Shape2D" category="Core" version="3.0.alpha.custom_build">
+<class name="SegmentShape2D" inherits="Shape2D" category="Core" version="3.0-alpha">
<brief_description>
Segment shape for 2D collisions.
</brief_description>
diff --git a/doc/classes/Semaphore.xml b/doc/classes/Semaphore.xml
index 0aeb6472af..0f70ec1bd2 100644
--- a/doc/classes/Semaphore.xml
+++ b/doc/classes/Semaphore.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Semaphore" inherits="Reference" category="Core" version="3.0.alpha.custom_build">
+<class name="Semaphore" inherits="Reference" category="Core" version="3.0-alpha">
<brief_description>
A synchronization Semaphore.
</brief_description>
@@ -15,14 +15,14 @@
<return type="int" enum="Error">
</return>
<description>
- Lowers the [Semaphore], allowing one more thread in.
+ Lowers the [code]Semaphore[/code], allowing one more thread in.
</description>
</method>
<method name="wait">
<return type="int" enum="Error">
</return>
<description>
- Tries to wait for the [Semaphore], if its value is zero, blocks until non-zero.
+ Tries to wait for the [code]Semaphore[/code], if its value is zero, blocks until non-zero.
</description>
</method>
</methods>
diff --git a/doc/classes/Separator.xml b/doc/classes/Separator.xml
index 4bbabe58aa..8754eb566d 100644
--- a/doc/classes/Separator.xml
+++ b/doc/classes/Separator.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Separator" inherits="Control" category="Core" version="3.0.alpha.custom_build">
+<class name="Separator" inherits="Control" category="Core" version="3.0-alpha">
<brief_description>
Base class for separators.
</brief_description>
diff --git a/doc/classes/Shader.xml b/doc/classes/Shader.xml
index 75644c31ab..53b67c9d38 100644
--- a/doc/classes/Shader.xml
+++ b/doc/classes/Shader.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Shader" inherits="Resource" category="Core" version="3.0.alpha.custom_build">
+<class name="Shader" inherits="Resource" category="Core" version="3.0-alpha">
<brief_description>
To be changed, ignore.
</brief_description>
diff --git a/doc/classes/ShaderMaterial.xml b/doc/classes/ShaderMaterial.xml
index 8bd9f1039e..81dec0cc14 100644
--- a/doc/classes/ShaderMaterial.xml
+++ b/doc/classes/ShaderMaterial.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ShaderMaterial" inherits="Material" category="Core" version="3.0.alpha.custom_build">
+<class name="ShaderMaterial" inherits="Material" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/Shape.xml b/doc/classes/Shape.xml
index 4d822a1705..df39988a35 100644
--- a/doc/classes/Shape.xml
+++ b/doc/classes/Shape.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Shape" inherits="Resource" category="Core" version="3.0.alpha.custom_build">
+<class name="Shape" inherits="Resource" category="Core" version="3.0-alpha">
<brief_description>
Base class for all 3D shape resources.
</brief_description>
diff --git a/doc/classes/Shape2D.xml b/doc/classes/Shape2D.xml
index d5e2984ba0..fcc1ded4f7 100644
--- a/doc/classes/Shape2D.xml
+++ b/doc/classes/Shape2D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Shape2D" inherits="Resource" category="Core" version="3.0.alpha.custom_build">
+<class name="Shape2D" inherits="Resource" category="Core" version="3.0-alpha">
<brief_description>
Base class for all 2D Shapes.
</brief_description>
diff --git a/doc/classes/ShortCut.xml b/doc/classes/ShortCut.xml
index e8b3b962d3..b89c3a65bd 100644
--- a/doc/classes/ShortCut.xml
+++ b/doc/classes/ShortCut.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ShortCut" inherits="Resource" category="Core" version="3.0.alpha.custom_build">
+<class name="ShortCut" inherits="Resource" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/Skeleton.xml b/doc/classes/Skeleton.xml
index b5be340b77..b32f8bf7f0 100644
--- a/doc/classes/Skeleton.xml
+++ b/doc/classes/Skeleton.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Skeleton" inherits="Spatial" category="Core" version="3.0.alpha.custom_build">
+<class name="Skeleton" inherits="Spatial" category="Core" version="3.0-alpha">
<brief_description>
Skeleton for characters and animated objects.
</brief_description>
diff --git a/doc/classes/Sky.xml b/doc/classes/Sky.xml
index 3045167346..a2259df42a 100644
--- a/doc/classes/Sky.xml
+++ b/doc/classes/Sky.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Sky" inherits="Resource" category="Core" version="3.0.alpha.custom_build">
+<class name="Sky" inherits="Resource" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/Slider.xml b/doc/classes/Slider.xml
index b9b2b98549..649752a8a2 100644
--- a/doc/classes/Slider.xml
+++ b/doc/classes/Slider.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Slider" inherits="Range" category="Core" version="3.0.alpha.custom_build">
+<class name="Slider" inherits="Range" category="Core" version="3.0-alpha">
<brief_description>
Base class for GUI Sliders.
</brief_description>
diff --git a/doc/classes/SliderJoint.xml b/doc/classes/SliderJoint.xml
index 617390b6a4..69cdf79c53 100644
--- a/doc/classes/SliderJoint.xml
+++ b/doc/classes/SliderJoint.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="SliderJoint" inherits="Joint" category="Core" version="3.0.alpha.custom_build">
+<class name="SliderJoint" inherits="Joint" category="Core" version="3.0-alpha">
<brief_description>
+ Piston kind of slider between two bodies in 3D.
</brief_description>
<description>
+ Slides across the x-axis of the [Pivot] object.
</description>
<tutorials>
</tutorials>
@@ -30,96 +32,144 @@
</methods>
<members>
<member name="angular_limit/damping" type="float" setter="set_param" getter="get_param">
+ The amount of damping of the rotation when the limit is surpassed.
+ A lower damping value allows a rotation initiated by body A to travel to body B slower.
</member>
<member name="angular_limit/lower_angle" type="float" setter="_set_lower_limit_angular" getter="_get_lower_limit_angular">
+ The lower limit of rotation in the slider.
</member>
<member name="angular_limit/restitution" type="float" setter="set_param" getter="get_param">
+ The amount of restitution of the rotation when the limit is surpassed.
+ Does not affect damping.
</member>
<member name="angular_limit/softness" type="float" setter="set_param" getter="get_param">
+ A factor applied to the all rotation once the limit is surpassed.
+ Makes all rotation slower when between 0 and 1.
</member>
<member name="angular_limit/upper_angle" type="float" setter="_set_upper_limit_angular" getter="_get_upper_limit_angular">
+ The upper limit of rotation in the slider.
</member>
<member name="angular_motion/damping" type="float" setter="set_param" getter="get_param">
+ The amount of damping of the rotation in the limits.
</member>
<member name="angular_motion/restitution" type="float" setter="set_param" getter="get_param">
+ The amount of restitution of the rotation in the limits.
</member>
<member name="angular_motion/softness" type="float" setter="set_param" getter="get_param">
+ A factor applied to the all rotation in the limits.
</member>
<member name="angular_ortho/damping" type="float" setter="set_param" getter="get_param">
+ The amount of damping of the rotation across axes orthogonal to the slider.
</member>
<member name="angular_ortho/restitution" type="float" setter="set_param" getter="get_param">
+ The amount of restitution of the rotation across axes orthogonal to the slider.
</member>
<member name="angular_ortho/softness" type="float" setter="set_param" getter="get_param">
+ A factor applied to the all rotation across axes orthogonal to the slider.
</member>
<member name="linear_limit/damping" type="float" setter="set_param" getter="get_param">
+ The amount of damping that happens once the limit defined by [member linear_limit/lower_distance] and [member linear_limit/upper_distance] is surpassed.
</member>
<member name="linear_limit/lower_distance" type="float" setter="set_param" getter="get_param">
+ The minimum difference between the pivot points on their x-axis before damping happens.
</member>
<member name="linear_limit/restitution" type="float" setter="set_param" getter="get_param">
+ The amount of restitution once the limits are surpassed. The lower, the more velocity-energy gets lost.
</member>
<member name="linear_limit/softness" type="float" setter="set_param" getter="get_param">
+ A factor applied to the movement accross the slider axis once the limits get surpassed. The lower, the slower the movement.
</member>
<member name="linear_limit/upper_distance" type="float" setter="set_param" getter="get_param">
+ The maximum difference between the pivot points on their x-axis before damping happens.
</member>
<member name="linear_motion/damping" type="float" setter="set_param" getter="get_param">
+ The amount of damping inside the slider limits.
</member>
<member name="linear_motion/restitution" type="float" setter="set_param" getter="get_param">
+ The amount of restitution inside the slider limits.
</member>
<member name="linear_motion/softness" type="float" setter="set_param" getter="get_param">
+ A factor applied to the movement accross the slider axis as long as the slider is in the limits. The lower, the slower the movement.
</member>
<member name="linear_ortho/damping" type="float" setter="set_param" getter="get_param">
+ The amount of damping when movement is accross axes orthogonal to the slider.
</member>
<member name="linear_ortho/restitution" type="float" setter="set_param" getter="get_param">
+ The amount of restitution when movement is accross axes orthogonal to the slider.
</member>
<member name="linear_ortho/softness" type="float" setter="set_param" getter="get_param">
+ A factor applied to the movement accross axes orthogonal to the slider.
</member>
</members>
<constants>
<constant name="PARAM_LINEAR_LIMIT_UPPER" value="0">
+ The maximum difference between the pivot points on their x-axis before damping happens.
</constant>
<constant name="PARAM_LINEAR_LIMIT_LOWER" value="1">
+ The minimum difference between the pivot points on their x-axis before damping happens.
</constant>
<constant name="PARAM_LINEAR_LIMIT_SOFTNESS" value="2">
+ A factor applied to the movement accross the slider axis once the limits get surpassed. The lower, the slower the movement.
</constant>
<constant name="PARAM_LINEAR_LIMIT_RESTITUTION" value="3">
+ The amount of restitution once the limits are surpassed. The lower, the more velocityenergy gets lost.
</constant>
<constant name="PARAM_LINEAR_LIMIT_DAMPING" value="4">
+ The amount of damping once the slider limits are surpassed.
</constant>
<constant name="PARAM_LINEAR_MOTION_SOFTNESS" value="5">
+ A factor applied to the movement accross the slider axis as long as the slider is in the limits. The lower, the slower the movement.
</constant>
<constant name="PARAM_LINEAR_MOTION_RESTITUTION" value="6">
+ The amount of restitution inside the slider limits.
</constant>
<constant name="PARAM_LINEAR_MOTION_DAMPING" value="7">
+ The amount of damping inside the slider limits.
</constant>
<constant name="PARAM_LINEAR_ORTHOGONAL_SOFTNESS" value="8">
+ A factor applied to the movement accross axes orthogonal to the slider.
</constant>
<constant name="PARAM_LINEAR_ORTHOGONAL_RESTITUTION" value="9">
+ The amount of restitution when movement is accross axes orthogonal to the slider.
</constant>
<constant name="PARAM_LINEAR_ORTHOGONAL_DAMPING" value="10">
+ The amount of damping when movement is accross axes orthogonal to the slider.
</constant>
<constant name="PARAM_ANGULAR_LIMIT_UPPER" value="11">
+ The upper limit of rotation in the slider.
</constant>
<constant name="PARAM_ANGULAR_LIMIT_LOWER" value="12">
+ The lower limit of rotation in the slider.
</constant>
<constant name="PARAM_ANGULAR_LIMIT_SOFTNESS" value="13">
+ A factor applied to the all rotation once the limit is surpassed.
</constant>
<constant name="PARAM_ANGULAR_LIMIT_RESTITUTION" value="14">
+ The amount of restitution of the rotation when the limit is surpassed.
</constant>
<constant name="PARAM_ANGULAR_LIMIT_DAMPING" value="15">
+ The amount of damping of the rotation when the limit is surpassed.
</constant>
<constant name="PARAM_ANGULAR_MOTION_SOFTNESS" value="16">
+ A factor applied to the all rotation in the limits.
</constant>
<constant name="PARAM_ANGULAR_MOTION_RESTITUTION" value="17">
+ The amount of restitution of the rotation in the limits.
</constant>
<constant name="PARAM_ANGULAR_MOTION_DAMPING" value="18">
+ The amount of damping of the rotation in the limits.
</constant>
<constant name="PARAM_ANGULAR_ORTHOGONAL_SOFTNESS" value="19">
+ A factor applied to the all rotation across axes orthogonal to the slider.
</constant>
<constant name="PARAM_ANGULAR_ORTHOGONAL_RESTITUTION" value="20">
+ The amount of restitution of the rotation across axes orthogonal to the slider.
</constant>
<constant name="PARAM_ANGULAR_ORTHOGONAL_DAMPING" value="21">
+ The amount of damping of the rotation across axes orthogonal to the slider.
</constant>
<constant name="PARAM_MAX" value="22">
+ End flag of PARAM_* constants, used internally.
</constant>
</constants>
</class>
diff --git a/doc/classes/Spatial.xml b/doc/classes/Spatial.xml
index 54eb82fbff..726654f91f 100644
--- a/doc/classes/Spatial.xml
+++ b/doc/classes/Spatial.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Spatial" inherits="Node" category="Core" version="3.0.alpha.custom_build">
+<class name="Spatial" inherits="Node" category="Core" version="3.0-alpha">
<brief_description>
Most basic 3D game object, parent of all 3D related nodes.
</brief_description>
@@ -29,7 +29,7 @@
<return type="Spatial">
</return>
<description>
- Returns the parent [Spatial], or an empty [Object] if no parent exists or parent is not of type [Spatial].
+ Returns the parent [code]Spatial[/code], or an empty [Object] if no parent exists or parent is not of type [code]Spatial[/code].
</description>
</method>
<method name="get_rotation" qualifiers="const">
@@ -39,7 +39,7 @@
Returns the rotation (in radians).
</description>
</method>
- <method name="get_rotation_deg" qualifiers="const">
+ <method name="get_rotation_degrees" qualifiers="const">
<return type="Vector3">
</return>
<description>
@@ -209,7 +209,7 @@
<argument index="0" name="enable" type="bool">
</argument>
<description>
- Makes the node ignore its parents tranformations. Node tranformations are only in global space.
+ Makes the node ignore its parents transformations. Node transformations are only in global space.
</description>
</method>
<method name="set_gizmo">
@@ -234,7 +234,7 @@
<return type="void">
</return>
<description>
- Reset all tranformations for this node. Set its [Transform3D] to identity matrix.
+ Reset all transformations for this node. Set its [Transform3D] to identity matrix.
</description>
</method>
<method name="set_ignore_transform_notification">
@@ -267,16 +267,16 @@
<method name="set_rotation">
<return type="void">
</return>
- <argument index="0" name="rotation_rad" type="Vector3">
+ <argument index="0" name="radians" type="Vector3">
</argument>
<description>
Set the rotation (in radians).
</description>
</method>
- <method name="set_rotation_deg">
+ <method name="set_rotation_degrees">
<return type="void">
</return>
- <argument index="0" name="rotation_deg" type="Vector3">
+ <argument index="0" name="degrees" type="Vector3">
</argument>
<description>
Set the rotation (in degrees).
@@ -329,7 +329,7 @@
<argument index="0" name="local_point" type="Vector3">
</argument>
<description>
- Tranforms [Vector3] "local_point" from this node's local space to world space.
+ Transforms [Vector3] "local_point" from this node's local space to world space.
</description>
</method>
<method name="to_local" qualifiers="const">
@@ -338,7 +338,7 @@
<argument index="0" name="global_point" type="Vector3">
</argument>
<description>
- Tranforms [Vector3] "global_point" from world space to this node's local space.
+ Transforms [Vector3] "global_point" from world space to this node's local space.
</description>
</method>
<method name="translate">
@@ -365,7 +365,7 @@
<member name="rotation" type="Vector3" setter="set_rotation" getter="get_rotation">
Local euler rotation in radians of this node.
</member>
- <member name="rotation_deg" type="Vector3" setter="set_rotation_deg" getter="get_rotation_deg">
+ <member name="rotation_degrees" type="Vector3" setter="set_rotation_degrees" getter="get_rotation_degrees">
Local euler rotation in degrees of this node.
</member>
<member name="scale" type="Vector3" setter="set_scale" getter="get_scale">
diff --git a/doc/classes/SpatialGizmo.xml b/doc/classes/SpatialGizmo.xml
index 1612e80500..eaac74fe10 100644
--- a/doc/classes/SpatialGizmo.xml
+++ b/doc/classes/SpatialGizmo.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="SpatialGizmo" inherits="Reference" category="Core" version="3.0.alpha.custom_build">
+<class name="SpatialGizmo" inherits="Reference" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/SpatialMaterial.xml b/doc/classes/SpatialMaterial.xml
index 344a42b7c0..9f8b563373 100644
--- a/doc/classes/SpatialMaterial.xml
+++ b/doc/classes/SpatialMaterial.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="SpatialMaterial" inherits="Material" category="Core" version="3.0.alpha.custom_build">
+<class name="SpatialMaterial" inherits="Material" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
@@ -27,6 +27,12 @@
<description>
</description>
</method>
+ <method name="get_ao_light_affect" qualifiers="const">
+ <return type="float">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="get_ao_texture_channel" qualifiers="const">
<return type="int" enum="SpatialMaterial.TextureChannel">
</return>
@@ -129,6 +135,12 @@
<description>
</description>
</method>
+ <method name="get_emission_operator" qualifiers="const">
+ <return type="int" enum="SpatialMaterial.EmissionOperator">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="get_feature" qualifiers="const">
<return type="bool">
</return>
@@ -357,6 +369,14 @@
<description>
</description>
</method>
+ <method name="set_ao_light_affect">
+ <return type="void">
+ </return>
+ <argument index="0" name="amount" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="set_ao_texture_channel">
<return type="void">
</return>
@@ -509,6 +529,14 @@
<description>
</description>
</method>
+ <method name="set_emission_operator">
+ <return type="void">
+ </return>
+ <argument index="0" name="operator" type="int" enum="SpatialMaterial.EmissionOperator">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="set_feature">
<return type="void">
</return>
@@ -777,6 +805,8 @@
</member>
<member name="ao_enabled" type="bool" setter="set_feature" getter="get_feature">
</member>
+ <member name="ao_light_affect" type="float" setter="set_ao_light_affect" getter="get_ao_light_affect">
+ </member>
<member name="ao_on_uv2" type="bool" setter="set_flag" getter="get_flag">
</member>
<member name="ao_texture" type="Texture" setter="set_texture" getter="get_texture">
@@ -827,6 +857,8 @@
</member>
<member name="emission_energy" type="float" setter="set_emission_energy" getter="get_emission_energy">
</member>
+ <member name="emission_operator" type="int" setter="set_emission_operator" getter="get_emission_operator" enum="SpatialMaterial.EmissionOperator">
+ </member>
<member name="emission_texture" type="Texture" setter="set_texture" getter="get_texture">
</member>
<member name="flags_fixed_size" type="bool" setter="set_flag" getter="get_flag">
@@ -1059,13 +1091,13 @@
</constant>
<constant name="FLAG_MAX" value="12">
</constant>
- <constant name="DIFFUSE_LAMBERT" value="0">
+ <constant name="DIFFUSE_BURLEY" value="0">
</constant>
- <constant name="DIFFUSE_LAMBERT_WRAP" value="1">
+ <constant name="DIFFUSE_LAMBERT" value="1">
</constant>
- <constant name="DIFFUSE_OREN_NAYAR" value="2">
+ <constant name="DIFFUSE_LAMBERT_WRAP" value="2">
</constant>
- <constant name="DIFFUSE_BURLEY" value="3">
+ <constant name="DIFFUSE_OREN_NAYAR" value="3">
</constant>
<constant name="DIFFUSE_TOON" value="4">
</constant>
@@ -1097,5 +1129,9 @@
</constant>
<constant name="TEXTURE_CHANNEL_GRAYSCALE" value="4">
</constant>
+ <constant name="EMISSION_OP_ADD" value="0">
+ </constant>
+ <constant name="EMISSION_OP_MULTIPLY" value="1">
+ </constant>
</constants>
</class>
diff --git a/doc/classes/SpatialVelocityTracker.xml b/doc/classes/SpatialVelocityTracker.xml
index 2cbc2b9739..62d3f02c89 100644
--- a/doc/classes/SpatialVelocityTracker.xml
+++ b/doc/classes/SpatialVelocityTracker.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="SpatialVelocityTracker" inherits="Reference" category="Core" version="3.0.alpha.custom_build">
+<class name="SpatialVelocityTracker" inherits="Reference" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
@@ -15,7 +15,7 @@
<description>
</description>
</method>
- <method name="is_tracking_fixed_step" qualifiers="const">
+ <method name="is_tracking_physics_step" qualifiers="const">
<return type="bool">
</return>
<description>
@@ -29,7 +29,7 @@
<description>
</description>
</method>
- <method name="set_track_fixed_step">
+ <method name="set_track_physics_step">
<return type="void">
</return>
<argument index="0" name="enable" type="bool">
diff --git a/doc/classes/SphereMesh.xml b/doc/classes/SphereMesh.xml
index 0ae48cb7d7..42af9cd6b8 100644
--- a/doc/classes/SphereMesh.xml
+++ b/doc/classes/SphereMesh.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="SphereMesh" inherits="PrimitiveMesh" category="Core" version="3.0.alpha.custom_build">
+<class name="SphereMesh" inherits="PrimitiveMesh" category="Core" version="3.0-alpha">
<brief_description>
Class representing a spherical [PrimitiveMesh].
</brief_description>
diff --git a/doc/classes/SphereShape.xml b/doc/classes/SphereShape.xml
index 7c6174f4e4..28f96b0028 100644
--- a/doc/classes/SphereShape.xml
+++ b/doc/classes/SphereShape.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="SphereShape" inherits="Shape" category="Core" version="3.0.alpha.custom_build">
+<class name="SphereShape" inherits="Shape" category="Core" version="3.0-alpha">
<brief_description>
Sphere shape for 3D collisions.
</brief_description>
diff --git a/doc/classes/SpinBox.xml b/doc/classes/SpinBox.xml
index 31ef1865e9..e0c0a88148 100644
--- a/doc/classes/SpinBox.xml
+++ b/doc/classes/SpinBox.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="SpinBox" inherits="Range" category="Core" version="3.0.alpha.custom_build">
+<class name="SpinBox" inherits="Range" category="Core" version="3.0-alpha">
<brief_description>
Numerical input text field.
</brief_description>
diff --git a/doc/classes/SplitContainer.xml b/doc/classes/SplitContainer.xml
index 861a483f6d..50ed6a5f64 100644
--- a/doc/classes/SplitContainer.xml
+++ b/doc/classes/SplitContainer.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="SplitContainer" inherits="Container" category="Core" version="3.0.alpha.custom_build">
+<class name="SplitContainer" inherits="Container" category="Core" version="3.0-alpha">
<brief_description>
Container for splitting and adjusting.
</brief_description>
diff --git a/doc/classes/SpotLight.xml b/doc/classes/SpotLight.xml
index 430e7c4a26..ce58791171 100644
--- a/doc/classes/SpotLight.xml
+++ b/doc/classes/SpotLight.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="SpotLight" inherits="Light" category="Core" version="3.0.alpha.custom_build">
+<class name="SpotLight" inherits="Light" category="Core" version="3.0-alpha">
<brief_description>
Spotlight [Light], such as a reflector spotlight or a lantern.
</brief_description>
diff --git a/doc/classes/Sprite.xml b/doc/classes/Sprite.xml
index 0cdc8f7099..7996adab51 100644
--- a/doc/classes/Sprite.xml
+++ b/doc/classes/Sprite.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Sprite" inherits="Node2D" category="Core" version="3.0.alpha.custom_build">
+<class name="Sprite" inherits="Node2D" category="Core" version="3.0-alpha">
<brief_description>
General purpose Sprite node.
</brief_description>
diff --git a/doc/classes/Sprite3D.xml b/doc/classes/Sprite3D.xml
index e51616a071..5354d8c819 100644
--- a/doc/classes/Sprite3D.xml
+++ b/doc/classes/Sprite3D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Sprite3D" inherits="SpriteBase3D" category="Core" version="3.0.alpha.custom_build">
+<class name="Sprite3D" inherits="SpriteBase3D" category="Core" version="3.0-alpha">
<brief_description>
2D Sprite node in 3D world.
</brief_description>
diff --git a/doc/classes/SpriteBase3D.xml b/doc/classes/SpriteBase3D.xml
index 7ed681ea12..69537cd884 100644
--- a/doc/classes/SpriteBase3D.xml
+++ b/doc/classes/SpriteBase3D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="SpriteBase3D" inherits="GeometryInstance" category="Core" version="3.0.alpha.custom_build">
+<class name="SpriteBase3D" inherits="GeometryInstance" category="Core" version="3.0-alpha">
<brief_description>
2D Sprite node in 3D environment.
</brief_description>
@@ -210,7 +210,7 @@
If set, texture can be seen from the back as well, if not, it is invisible when looking at it from behind.
</constant>
<constant name="FLAG_MAX" value="3">
- Used internally to mark the end of the Flags section.
+ Used internally to mark the end of the Flags section.
</constant>
<constant name="ALPHA_CUT_DISABLED" value="0">
</constant>
diff --git a/doc/classes/SpriteFrames.xml b/doc/classes/SpriteFrames.xml
index e46fdc80e0..336b155689 100644
--- a/doc/classes/SpriteFrames.xml
+++ b/doc/classes/SpriteFrames.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="SpriteFrames" inherits="Resource" category="Core" version="3.0.alpha.custom_build">
+<class name="SpriteFrames" inherits="Resource" category="Core" version="3.0-alpha">
<brief_description>
Sprite frame library for AnimatedSprite.
</brief_description>
diff --git a/doc/classes/StaticBody.xml b/doc/classes/StaticBody.xml
index 6b5b007310..a008f0b99c 100644
--- a/doc/classes/StaticBody.xml
+++ b/doc/classes/StaticBody.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="StaticBody" inherits="PhysicsBody" category="Core" version="3.0.alpha.custom_build">
+<class name="StaticBody" inherits="PhysicsBody" category="Core" version="3.0-alpha">
<brief_description>
Static body for 3D Physics.
</brief_description>
diff --git a/doc/classes/StaticBody2D.xml b/doc/classes/StaticBody2D.xml
index cff41074b8..9f1f79ad59 100644
--- a/doc/classes/StaticBody2D.xml
+++ b/doc/classes/StaticBody2D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="StaticBody2D" inherits="PhysicsBody2D" category="Core" version="3.0.alpha.custom_build">
+<class name="StaticBody2D" inherits="PhysicsBody2D" category="Core" version="3.0-alpha">
<brief_description>
Static body for 2D Physics.
</brief_description>
diff --git a/doc/classes/StreamPeer.xml b/doc/classes/StreamPeer.xml
index 2fdd4b07d5..4f92a524b1 100644
--- a/doc/classes/StreamPeer.xml
+++ b/doc/classes/StreamPeer.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="StreamPeer" inherits="Reference" category="Core" version="3.0.alpha.custom_build">
+<class name="StreamPeer" inherits="Reference" category="Core" version="3.0-alpha">
<brief_description>
Abstraction and base class for stream-based protocols.
</brief_description>
@@ -43,7 +43,7 @@
<return type="int">
</return>
<description>
- Return the amount of bytes this [StreamPeer] has available.
+ Return the amount of bytes this [code]StreamPeer[/code] has available.
</description>
</method>
<method name="get_data">
@@ -135,7 +135,7 @@
<return type="bool">
</return>
<description>
- Return whether this [StreamPeer] is using big-endian format.
+ Return whether this [code]StreamPeer[/code] is using big-endian format.
</description>
</method>
<method name="put_16">
@@ -270,7 +270,7 @@
<argument index="0" name="enable" type="bool">
</argument>
<description>
- Set this [StreamPeer] to use big-endian format. Default is false.
+ Set this [code]StreamPeer[/code] to use big-endian format. Default is false.
</description>
</method>
</methods>
diff --git a/doc/classes/StreamPeerBuffer.xml b/doc/classes/StreamPeerBuffer.xml
index 141d46564c..5c67598285 100644
--- a/doc/classes/StreamPeerBuffer.xml
+++ b/doc/classes/StreamPeerBuffer.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="StreamPeerBuffer" inherits="StreamPeer" category="Core" version="3.0.alpha.custom_build">
+<class name="StreamPeerBuffer" inherits="StreamPeer" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/StreamPeerSSL.xml b/doc/classes/StreamPeerSSL.xml
index 7a2843ff47..59d0e492e4 100644
--- a/doc/classes/StreamPeerSSL.xml
+++ b/doc/classes/StreamPeerSSL.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="StreamPeerSSL" inherits="StreamPeer" category="Core" version="3.0.alpha.custom_build">
+<class name="StreamPeerSSL" inherits="StreamPeer" category="Core" version="3.0-alpha">
<brief_description>
SSL Stream peer.
</brief_description>
@@ -29,7 +29,7 @@
<argument index="2" name="for_hostname" type="String" default="&quot;&quot;">
</argument>
<description>
- Connect to a peer using an underlying [StreamPeer] "stream", when "validate_certs" is true, [StreamPeerSSL] will validate that the certificate presented by the peer matches the "for_hostname".
+ Connect to a peer using an underlying [StreamPeer] "stream", when "validate_certs" is true, [code]StreamPeerSSL[/code] will validate that the certificate presented by the peer matches the "for_hostname".
</description>
</method>
<method name="disconnect_from_stream">
@@ -49,10 +49,10 @@
</methods>
<constants>
<constant name="STATUS_DISCONNECTED" value="0">
- A status representing a [StreamPeerSSL] that is disconnected.
+ A status representing a [code]StreamPeerSSL[/code] that is disconnected.
</constant>
<constant name="STATUS_CONNECTED" value="1">
- A status representing a [StreamPeerSSL] that is connected to a host.
+ A status representing a [code]StreamPeerSSL[/code] that is connected to a host.
</constant>
<constant name="STATUS_ERROR_NO_CERTIFICATE" value="2">
An errot status that shows the peer did not present a SSL certificate and validation was requested.
diff --git a/doc/classes/StreamPeerTCP.xml b/doc/classes/StreamPeerTCP.xml
index 3b2af330b3..3df68d0926 100644
--- a/doc/classes/StreamPeerTCP.xml
+++ b/doc/classes/StreamPeerTCP.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="StreamPeerTCP" inherits="StreamPeer" category="Core" version="3.0.alpha.custom_build">
+<class name="StreamPeerTCP" inherits="StreamPeer" category="Core" version="3.0-alpha">
<brief_description>
TCP Stream peer.
</brief_description>
@@ -59,16 +59,16 @@
</methods>
<constants>
<constant name="STATUS_NONE" value="0">
- The initial status of the [StreamPeerTCP], also the status after a disconnect.
+ The initial status of the [code]StreamPeerTCP[/code], also the status after a disconnect.
</constant>
<constant name="STATUS_CONNECTING" value="1">
- A status representing a [StreamPeerTCP] that is connecting to a host.
+ A status representing a [code]StreamPeerTCP[/code] that is connecting to a host.
</constant>
<constant name="STATUS_CONNECTED" value="2">
- A status representing a [StreamPeerTCP] that is connected to a host.
+ A status representing a [code]StreamPeerTCP[/code] that is connected to a host.
</constant>
<constant name="STATUS_ERROR" value="3">
- A staus representing a [StreamPeerTCP] in error state.
+ A staus representing a [code]StreamPeerTCP[/code] in error state.
</constant>
</constants>
</class>
diff --git a/doc/classes/StreamTexture.xml b/doc/classes/StreamTexture.xml
index 6e6f2e8056..2a5ad36b25 100644
--- a/doc/classes/StreamTexture.xml
+++ b/doc/classes/StreamTexture.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="StreamTexture" inherits="Texture" category="Core" version="3.0.alpha.custom_build">
+<class name="StreamTexture" inherits="Texture" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/String.xml b/doc/classes/String.xml
index c7c19997b9..60c5e75dec 100644
--- a/doc/classes/String.xml
+++ b/doc/classes/String.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="String" category="Built-In Types" version="3.0.alpha.custom_build">
+<class name="String" category="Built-In Types" version="3.0-alpha">
<brief_description>
Built-in string class.
</brief_description>
@@ -17,6 +17,7 @@
<argument index="0" name="from" type="bool">
</argument>
<description>
+ Constructs a new String from the given [bool].
</description>
</method>
<method name="String">
@@ -25,6 +26,7 @@
<argument index="0" name="from" type="int">
</argument>
<description>
+ Constructs a new String from the given [int].
</description>
</method>
<method name="String">
@@ -33,6 +35,7 @@
<argument index="0" name="from" type="float">
</argument>
<description>
+ Constructs a new String from the given [float].
</description>
</method>
<method name="String">
@@ -41,6 +44,7 @@
<argument index="0" name="from" type="Vector2">
</argument>
<description>
+ Constructs a new String from the given [Vector2].
</description>
</method>
<method name="String">
@@ -49,6 +53,7 @@
<argument index="0" name="from" type="Rect2">
</argument>
<description>
+ Constructs a new String from the given [Rect2].
</description>
</method>
<method name="String">
@@ -57,6 +62,7 @@
<argument index="0" name="from" type="Vector3">
</argument>
<description>
+ Constructs a new String from the given [Vector3].
</description>
</method>
<method name="String">
@@ -65,6 +71,7 @@
<argument index="0" name="from" type="Transform2D">
</argument>
<description>
+ Constructs a new String from the given [Transform2D].
</description>
</method>
<method name="String">
@@ -73,6 +80,7 @@
<argument index="0" name="from" type="Plane">
</argument>
<description>
+ Constructs a new String from the given [Plane].
</description>
</method>
<method name="String">
@@ -81,14 +89,16 @@
<argument index="0" name="from" type="Quat">
</argument>
<description>
+ Constructs a new String from the given [Quat].
</description>
</method>
<method name="String">
<return type="String">
</return>
- <argument index="0" name="from" type="Rect3">
+ <argument index="0" name="from" type="AABB">
</argument>
<description>
+ Constructs a new String from the given [AABB].
</description>
</method>
<method name="String">
@@ -97,6 +107,7 @@
<argument index="0" name="from" type="Basis">
</argument>
<description>
+ Constructs a new String from the given [Basis].
</description>
</method>
<method name="String">
@@ -105,6 +116,7 @@
<argument index="0" name="from" type="Transform">
</argument>
<description>
+ Constructs a new String from the given [Transform].
</description>
</method>
<method name="String">
@@ -113,6 +125,7 @@
<argument index="0" name="from" type="Color">
</argument>
<description>
+ Constructs a new String from the given [Color].
</description>
</method>
<method name="String">
@@ -121,6 +134,7 @@
<argument index="0" name="from" type="NodePath">
</argument>
<description>
+ Constructs a new String from the given [NodePath].
</description>
</method>
<method name="String">
@@ -129,6 +143,7 @@
<argument index="0" name="from" type="RID">
</argument>
<description>
+ Constructs a new String from the given [RID].
</description>
</method>
<method name="String">
@@ -137,6 +152,7 @@
<argument index="0" name="from" type="Dictionary">
</argument>
<description>
+ Constructs a new String from the given [Dictionary].
</description>
</method>
<method name="String">
@@ -145,6 +161,7 @@
<argument index="0" name="from" type="Array">
</argument>
<description>
+ Constructs a new String from the given [Array].
</description>
</method>
<method name="String">
@@ -153,6 +170,7 @@
<argument index="0" name="from" type="PoolByteArray">
</argument>
<description>
+ Constructs a new String from the given [PoolByteArray].
</description>
</method>
<method name="String">
@@ -161,6 +179,7 @@
<argument index="0" name="from" type="PoolIntArray">
</argument>
<description>
+ Constructs a new String from the given [PoolIntArray].
</description>
</method>
<method name="String">
@@ -169,6 +188,7 @@
<argument index="0" name="from" type="PoolRealArray">
</argument>
<description>
+ Constructs a new String from the given [PoolRealArray].
</description>
</method>
<method name="String">
@@ -177,6 +197,7 @@
<argument index="0" name="from" type="PoolStringArray">
</argument>
<description>
+ Constructs a new String from the given [PoolStringArray].
</description>
</method>
<method name="String">
@@ -185,6 +206,7 @@
<argument index="0" name="from" type="PoolVector2Array">
</argument>
<description>
+ Constructs a new String from the given [PoolVector2Array].
</description>
</method>
<method name="String">
@@ -193,6 +215,7 @@
<argument index="0" name="from" type="PoolVector3Array">
</argument>
<description>
+ Constructs a new String from the given [PoolVector3Array].
</description>
</method>
<method name="String">
@@ -201,6 +224,7 @@
<argument index="0" name="from" type="PoolColorArray">
</argument>
<description>
+ Constructs a new String from the given [PoolColorArray].
</description>
</method>
<method name="begins_with">
@@ -209,35 +233,35 @@
<argument index="0" name="text" type="String">
</argument>
<description>
- Return true if the strings begins with the given string.
+ Returns [code]true[/code] if the string begins with the given string.
</description>
</method>
<method name="bigrams">
<return type="PoolStringArray">
</return>
<description>
- Return the bigrams (pairs of consecutive letters) of this string.
+ Returns the bigrams (pairs of consecutive letters) of this string.
</description>
</method>
<method name="c_escape">
<return type="String">
</return>
<description>
- Return a copy of the string with special characters escaped using the C language standard.
+ Returns a copy of the string with special characters escaped using the C language standard.
</description>
</method>
<method name="c_unescape">
<return type="String">
</return>
<description>
- Return a copy of the string with escaped characters replaced by their meanings according to the C language standard.
+ Returns a copy of the string with escaped characters replaced by their meanings according to the C language standard.
</description>
</method>
<method name="capitalize">
<return type="String">
</return>
<description>
- Change the case of some letters. Replace underscores with spaces, convert all letters to lowercase then capitalize first and every letter following the space character. For [code]capitalize camelCase mixed_with_underscores[/code] it will return [code]Capitalize Camelcase Mixed With Underscores[/code].
+ Changes the case of some letters. Replaces underscores with spaces, converts all letters to lowercase, then capitalizes first and every letter following the space character. For [code]capitalize camelCase mixed_with_underscores[/code] it will return [code]Capitalize Camelcase Mixed With Underscores[/code].
</description>
</method>
<method name="casecmp_to">
@@ -246,14 +270,20 @@
<argument index="0" name="to" type="String">
</argument>
<description>
- Perform a case-sensitive comparison to another string, return -1 if less, 0 if equal and +1 if greater.
+ Performs a case-sensitive comparison to another string. Returns [code]-1[/code] if less than, [code]+1[/code] if greater than, or [code]0[/code] if equal.
+ </description>
+ </method>
+ <method name="dedent">
+ <return type="String">
+ </return>
+ <description>
</description>
</method>
<method name="empty">
<return type="bool">
</return>
<description>
- Return true if the string is empty.
+ Returns [code]true[/code] if the string is empty.
</description>
</method>
<method name="ends_with">
@@ -262,7 +292,7 @@
<argument index="0" name="text" type="String">
</argument>
<description>
- Return true if the strings ends with the given string.
+ Returns [code]true[/code] if the string ends with the given string.
</description>
</method>
<method name="erase">
@@ -271,7 +301,7 @@
<argument index="1" name="chars" type="int">
</argument>
<description>
- Erase [code]chars[/code] characters from the string starting from [code]position[/code].
+ Erases [code]chars[/code] characters from the string starting from [code]position[/code].
</description>
</method>
<method name="find">
@@ -282,7 +312,7 @@
<argument index="1" name="from" type="int" default="0">
</argument>
<description>
- Find the first occurrence of a substring, return the starting position of the substring or -1 if not found. Optionally, the initial search index can be passed.
+ Finds the first occurrence of a substring. Returns the starting position of the substring or -1 if not found. Optionally, the initial search index can be passed.
</description>
</method>
<method name="find_last">
@@ -291,7 +321,7 @@
<argument index="0" name="what" type="String">
</argument>
<description>
- Find the last occurrence of a substring, return the starting position of the substring or -1 if not found. Optionally, the initial search index can be passed.
+ Finds the last occurrence of a substring. Returns the starting position of the substring or -1 if not found. Optionally, the initial search index can be passed.
</description>
</method>
<method name="findn">
@@ -302,7 +332,7 @@
<argument index="1" name="from" type="int" default="0">
</argument>
<description>
- Find the first occurrence of a substring but search as case-insensitive, return the starting position of the substring or -1 if not found. Optionally, the initial search index can be passed.
+ Finds the first occurrence of a substring, ignoring case. Returns the starting position of the substring or -1 if not found. Optionally, the initial search index can be passed.
</description>
</method>
<method name="format">
@@ -313,48 +343,49 @@
<argument index="1" name="placeholder" type="String" default="{_}">
</argument>
<description>
+ Formats the string by replacing all occurences of [code]placeholder[/code] with [code]values[/code].
</description>
</method>
<method name="get_base_dir">
<return type="String">
</return>
<description>
- If the string is a path to a file, return the base directory.
+ If the string is a valid file path, returns the base directory name.
</description>
</method>
<method name="get_basename">
<return type="String">
</return>
<description>
- If the string is a path to a file, return the path to the file without the extension.
+ If the string is a valid file path, returns the full file path without the extension.
</description>
</method>
<method name="get_extension">
<return type="String">
</return>
<description>
- If the string is a path to a file, return the extension.
+ If the string is a valid file path, returns the extension.
</description>
</method>
<method name="get_file">
<return type="String">
</return>
<description>
- If the string is a path to a file, return the file and ignore the base directory.
+ If the string is a valid file path, returns the filename.
</description>
</method>
<method name="hash">
<return type="int">
</return>
<description>
- Hash the string and return a 32 bits integer.
+ Hashes the string and returns a 32-bit integer.
</description>
</method>
<method name="hex_to_int">
<return type="int">
</return>
<description>
- Convert a string containing a hexadecimal number into an int.
+ Converts a string containing a hexadecimal number into an integer.
</description>
</method>
<method name="insert">
@@ -365,21 +396,21 @@
<argument index="1" name="what" type="String">
</argument>
<description>
- Insert a substring at a given position.
+ Inserts a substring at a given position.
</description>
</method>
<method name="is_abs_path">
<return type="bool">
</return>
<description>
- If the string is a path to a file or directory, return true if the path is absolute.
+ If the string is a path to a file or directory, returns [code]true[/code] if the path is absolute.
</description>
</method>
<method name="is_rel_path">
<return type="bool">
</return>
<description>
- If the string is a path to a file or directory, return true if the path is relative.
+ If the string is a path to a file or directory, returns [code]true[/code] if the path is relative.
</description>
</method>
<method name="is_subsequence_of">
@@ -388,7 +419,7 @@
<argument index="0" name="text" type="String">
</argument>
<description>
- Check whether this string is a subsequence of the given string.
+ Returns [code]true[/code] if this string is a subsequence of the given string.
</description>
</method>
<method name="is_subsequence_ofi">
@@ -397,49 +428,49 @@
<argument index="0" name="text" type="String">
</argument>
<description>
- Check whether this string is a subsequence of the given string, without considering case.
+ Returns [code]true[/code] if this string is a subsequence of the given string, without considering case.
</description>
</method>
<method name="is_valid_float">
<return type="bool">
</return>
<description>
- Check whether the string contains a valid float.
+ Returns [code]true[/code] if this string contains a valid float.
</description>
</method>
<method name="is_valid_html_color">
<return type="bool">
</return>
<description>
- Check whether the string contains a valid color in HTML notation.
+ Returns [code]true[/code] if this string contains a valid color in HTML notation.
</description>
</method>
<method name="is_valid_identifier">
<return type="bool">
</return>
<description>
- Check whether the string is a valid identifier. As is common in programming languages, a valid identifier may contain only letters, digits and underscores (_) and the first character may not be a digit.
+ Returns [code]true[/code] if this string is a valid identifier. A valid identifier may contain only letters, digits and underscores (_) and the first character may not be a digit.
</description>
</method>
<method name="is_valid_integer">
<return type="bool">
</return>
<description>
- Check whether the string contains a valid integer.
+ Returns [code]true[/code] if this string contains a valid integer.
</description>
</method>
<method name="is_valid_ip_address">
<return type="bool">
</return>
<description>
- Check whether the string contains a valid IP address.
+ Returns [code]true[/code] if this string contains a valid IP address.
</description>
</method>
<method name="json_escape">
<return type="String">
</return>
<description>
- Return a copy of the string with special characters escaped using the JSON standard.
+ Returns a copy of the string with special characters escaped using the JSON standard.
</description>
</method>
<method name="left">
@@ -448,14 +479,14 @@
<argument index="0" name="position" type="int">
</argument>
<description>
- Return an amount of characters from the left of the string.
+ Returns a number of characters from the left of the string.
</description>
</method>
<method name="length">
<return type="int">
</return>
<description>
- Return the length of the string in characters.
+ Returns the string's amount of characters.
</description>
</method>
<method name="match">
@@ -464,7 +495,7 @@
<argument index="0" name="expr" type="String">
</argument>
<description>
- Do a simple expression match, where '*' matches zero or more arbitrary characters and '?' matches any single character except '.'.
+ Does a simple expression match, where '*' matches zero or more arbitrary characters and '?' matches any single character except '.'.
</description>
</method>
<method name="matchn">
@@ -473,21 +504,21 @@
<argument index="0" name="expr" type="String">
</argument>
<description>
- Do a simple case insensitive expression match, using ? and * wildcards (see [method match]).
+ Does a simple case insensitive expression match, using ? and * wildcards (see [method match]).
</description>
</method>
<method name="md5_buffer">
<return type="PoolByteArray">
</return>
<description>
- Return the MD5 hash of the string as an array of bytes.
+ Returns the MD5 hash of the string as an array of bytes.
</description>
</method>
<method name="md5_text">
<return type="String">
</return>
<description>
- Return the MD5 hash of the string as a string.
+ Returns the MD5 hash of the string as a string.
</description>
</method>
<method name="nocasecmp_to">
@@ -496,7 +527,7 @@
<argument index="0" name="to" type="String">
</argument>
<description>
- Perform a case-insensitive comparison to another string, return -1 if less, 0 if equal and +1 if greater.
+ Performs a case-insensitive comparison to another string. Returns [code]-1[/code] if less than, [code]+1[/code] if greater than, or [code]0[/code] if equal.
</description>
</method>
<method name="ord_at">
@@ -505,7 +536,7 @@
<argument index="0" name="at" type="int">
</argument>
<description>
- Return the character code at position [code]at[/code].
+ Returns the character code at position [code]at[/code].
</description>
</method>
<method name="pad_decimals">
@@ -514,7 +545,7 @@
<argument index="0" name="digits" type="int">
</argument>
<description>
- Format a number to have an exact number of [code]digits[/code] after the decimal point.
+ Formats a number to have an exact number of [code]digits[/code] after the decimal point.
</description>
</method>
<method name="pad_zeros">
@@ -523,7 +554,7 @@
<argument index="0" name="digits" type="int">
</argument>
<description>
- Format a number to have an exact number of [code]digits[/code] before the decimal point.
+ Formats a number to have an exact number of [code]digits[/code] before the decimal point.
</description>
</method>
<method name="percent_decode">
@@ -537,7 +568,7 @@
<return type="String">
</return>
<description>
- Percent-encode a string. This is meant to encode parameters in a URL when sending a HTTP GET request and bodies of form-urlencoded POST request.
+ Percent-encodes a string. Encodes parameters in a URL when sending a HTTP GET request (and bodies of form-urlencoded POST requests).
</description>
</method>
<method name="plus_file">
@@ -557,7 +588,7 @@
<argument index="1" name="forwhat" type="String">
</argument>
<description>
- Replace occurrences of a substring for different ones inside the string.
+ Replaces occurrences of a substring with the given one inside the string.
</description>
</method>
<method name="replacen">
@@ -568,7 +599,7 @@
<argument index="1" name="forwhat" type="String">
</argument>
<description>
- Replace occurrences of a substring for different ones inside the string, but search case-insensitive.
+ Replaces occurrences of a substring with the given one inside the string. Ignores case.
</description>
</method>
<method name="rfind">
@@ -579,7 +610,7 @@
<argument index="1" name="from" type="int" default="-1">
</argument>
<description>
- Perform a search for a substring, but start from the end of the string instead of the beginning.
+ Performs a search for a substring, but starts from the end of the string instead of the beginning.
</description>
</method>
<method name="rfindn">
@@ -590,7 +621,7 @@
<argument index="1" name="from" type="int" default="-1">
</argument>
<description>
- Perform a search for a substring, but start from the end of the string instead of the beginning. Also search case-insensitive.
+ Performs a search for a substring, but starts from the end of the string instead of the beginning. Ignores case.
</description>
</method>
<method name="right">
@@ -599,7 +630,7 @@
<argument index="0" name="position" type="int">
</argument>
<description>
- Return the right side of the string from a given position.
+ Returns the right side of the string from a given position.
</description>
</method>
<method name="sha256_buffer">
@@ -612,7 +643,7 @@
<return type="String">
</return>
<description>
- Return the SHA-256 hash of the string as a string.
+ Returns the SHA-256 hash of the string as a string.
</description>
</method>
<method name="similarity">
@@ -621,7 +652,7 @@
<argument index="0" name="text" type="String">
</argument>
<description>
- Return the similarity index of the text compared to this string. 1 means totally similar and 0 means totally dissimilar.
+ Returns the similarity index of the text compared to this string. 1 means totally similar and 0 means totally dissimilar.
</description>
</method>
<method name="split">
@@ -632,7 +663,7 @@
<argument index="1" name="allow_empty" type="bool" default="True">
</argument>
<description>
- Split the string by a divisor string, return an array of the substrings. Example "One,Two,Three" will return ["One","Two","Three"] if split by ",".
+ Splits the string by a divisor string and returns an array of the substrings. Example "One,Two,Three" will return ["One","Two","Three"] if split by ",".
</description>
</method>
<method name="split_floats">
@@ -643,7 +674,7 @@
<argument index="1" name="allow_empty" type="bool" default="True">
</argument>
<description>
- Split the string in floats by using a divisor string, return an array of the substrings. Example "1,2.5,3" will return [1,2.5,3] if split by ",".
+ Splits the string in floats by using a divisor string and returns an array of the substrings. Example "1,2.5,3" will return [1,2.5,3] if split by ",".
</description>
</method>
<method name="strip_edges">
@@ -654,7 +685,7 @@
<argument index="1" name="right" type="bool" default="True">
</argument>
<description>
- Return a copy of the string stripped of any non-printable character at the beginning and the end. The optional arguments are used to toggle stripping on the left and right edges respectively.
+ Returns a copy of the string stripped of any non-printable character at the beginning and the end. The optional arguments are used to toggle stripping on the left and right edges respectively.
</description>
</method>
<method name="substr">
@@ -665,63 +696,63 @@
<argument index="1" name="len" type="int">
</argument>
<description>
- Return part of the string from the position [code]from[/code], with length [code]len[/code].
+ Returns part of the string from the position [code]from[/code] with length [code]len[/code].
</description>
</method>
<method name="to_ascii">
<return type="PoolByteArray">
</return>
<description>
- Convert the String (which is a character array) to PoolByteArray (which is an array of bytes). The conversion is speeded up in comparison to to_utf8() with the assumption that all the characters the String contains are only ASCII characters.
+ Converts the String (which is a character array) to [PoolByteArray] (which is an array of bytes). The conversion is sped up in comparison to to_utf8() with the assumption that all the characters the String contains are only ASCII characters.
</description>
</method>
<method name="to_float">
<return type="float">
</return>
<description>
- Convert a string, containing a decimal number, into a [code]float[/code].
+ Converts a string containing a decimal number into a [code]float[/code].
</description>
</method>
<method name="to_int">
<return type="int">
</return>
<description>
- Convert a string, containing an integer number, into an [code]int[/code].
+ Converts a string containing an integer number into an [code]int[/code].
</description>
</method>
<method name="to_lower">
<return type="String">
</return>
<description>
- Return the string converted to lowercase.
+ Returns the string converted to lowercase.
</description>
</method>
<method name="to_upper">
<return type="String">
</return>
<description>
- Return the string converted to uppercase.
+ Returns the string converted to uppercase.
</description>
</method>
<method name="to_utf8">
<return type="PoolByteArray">
</return>
<description>
- Convert the String (which is an array of characters) to PoolByteArray (which is an array of bytes). The conversion is a bit slower than to_ascii(), but supports all UTF-8 characters. Therefore, you should prefer this function over to_ascii().
+ Converts the String (which is an array of characters) to [PoolByteArray] (which is an array of bytes). The conversion is a bit slower than to_ascii(), but supports all UTF-8 characters. Therefore, you should prefer this function over to_ascii().
</description>
</method>
<method name="xml_escape">
<return type="String">
</return>
<description>
- Return a copy of the string with special characters escaped using the XML standard.
+ Returns a copy of the string with special characters escaped using the XML standard.
</description>
</method>
<method name="xml_unescape">
<return type="String">
</return>
<description>
- Return a copy of the string with escaped characters replaced by their meanings according to the XML standard.
+ Returns a copy of the string with escaped characters replaced by their meanings according to the XML standard.
</description>
</method>
</methods>
diff --git a/doc/classes/StyleBox.xml b/doc/classes/StyleBox.xml
index ab1ec1f997..c904522c7f 100644
--- a/doc/classes/StyleBox.xml
+++ b/doc/classes/StyleBox.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="StyleBox" inherits="Resource" category="Core" version="3.0.alpha.custom_build">
+<class name="StyleBox" inherits="Resource" category="Core" version="3.0-alpha">
<brief_description>
Base class for drawing stylized boxes for the UI.
</brief_description>
diff --git a/doc/classes/StyleBoxEmpty.xml b/doc/classes/StyleBoxEmpty.xml
index f11959c41d..fd0e256e36 100644
--- a/doc/classes/StyleBoxEmpty.xml
+++ b/doc/classes/StyleBoxEmpty.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="StyleBoxEmpty" inherits="StyleBox" category="Core" version="3.0.alpha.custom_build">
+<class name="StyleBoxEmpty" inherits="StyleBox" category="Core" version="3.0-alpha">
<brief_description>
Empty stylebox (does not display anything).
</brief_description>
diff --git a/doc/classes/StyleBoxFlat.xml b/doc/classes/StyleBoxFlat.xml
index b09b9f0679..ab1f733c5c 100644
--- a/doc/classes/StyleBoxFlat.xml
+++ b/doc/classes/StyleBoxFlat.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="StyleBoxFlat" inherits="StyleBox" category="Core" version="3.0.alpha.custom_build">
+<class name="StyleBoxFlat" inherits="StyleBox" category="Core" version="3.0-alpha">
<brief_description>
Customizable Stylebox with a given set of parameters. (no texture required)
</brief_description>
@@ -14,12 +14,12 @@
[codeblock]
height = 30
corner_radius_top_left = 50
- corner_raidus_bottom_left = 100
+ corner_radius_bottom_left = 100
[/codeblock]
The relative system now would take the 1:2 ratio of the two left corners to calculate the actual corner width. Both corners added will [b]never[/b] be more than the height. Result:
[codeblock]
corner_radius_top_left: 10
- corner_raidus_bottom_left: 20
+ corner_radius_bottom_left: 20
[/codeblock]
</description>
<tutorials>
@@ -202,7 +202,7 @@
</argument>
<argument index="1" name="radius_top_right" type="int">
</argument>
- <argument index="2" name="radius_botton_right" type="int">
+ <argument index="2" name="radius_bottom_right" type="int">
</argument>
<argument index="3" name="radius_bottom_left" type="int">
</argument>
@@ -268,7 +268,7 @@
</methods>
<members>
<member name="anti_aliasing" type="bool" setter="set_anti_aliased" getter="is_anti_aliased">
- Anti Aliasing draws a small ring around edges. This ring fades to transparent. As a result edges look much smoother. This is only noticable when using rounded corners.
+ Anti Aliasing draws a small ring around edges. This ring fades to transparent. As a result edges look much smoother. This is only noticeable when using rounded corners.
</member>
<member name="anti_aliasing_size" type="int" setter="set_aa_size" getter="get_aa_size">
This changes the size of the faded ring. Higher values can be used to achieve a "blurry" effect.
diff --git a/doc/classes/StyleBoxLine.xml b/doc/classes/StyleBoxLine.xml
new file mode 100644
index 0000000000..669d74416f
--- /dev/null
+++ b/doc/classes/StyleBoxLine.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="StyleBoxLine" inherits="StyleBox" category="Core" version="3.0-alpha">
+ <brief_description>
+ </brief_description>
+ <description>
+ </description>
+ <tutorials>
+ </tutorials>
+ <demos>
+ </demos>
+ <methods>
+ <method name="get_color" qualifiers="const">
+ <return type="Color">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_grow" qualifiers="const">
+ <return type="float">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_thickness" qualifiers="const">
+ <return type="int">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="is_vertical" qualifiers="const">
+ <return type="bool">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="set_color">
+ <return type="void">
+ </return>
+ <argument index="0" name="color" type="Color">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="set_grow">
+ <return type="void">
+ </return>
+ <argument index="0" name="grow" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="set_thickness">
+ <return type="void">
+ </return>
+ <argument index="0" name="thickness" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="set_vertical">
+ <return type="void">
+ </return>
+ <argument index="0" name="vertical" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
+ </methods>
+ <members>
+ <member name="color" type="Color" setter="set_color" getter="get_color">
+ </member>
+ <member name="thickness" type="int" setter="set_thickness" getter="get_thickness">
+ </member>
+ <member name="vertical" type="bool" setter="set_vertical" getter="is_vertical">
+ </member>
+ </members>
+ <constants>
+ </constants>
+</class>
diff --git a/doc/classes/StyleBoxTexture.xml b/doc/classes/StyleBoxTexture.xml
index 458fdad99e..2b64b5d6bf 100644
--- a/doc/classes/StyleBoxTexture.xml
+++ b/doc/classes/StyleBoxTexture.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="StyleBoxTexture" inherits="StyleBox" category="Core" version="3.0.alpha.custom_build">
+<class name="StyleBoxTexture" inherits="StyleBox" category="Core" version="3.0-alpha">
<brief_description>
Texture Based 3x3 scale style.
</brief_description>
diff --git a/doc/classes/SurfaceTool.xml b/doc/classes/SurfaceTool.xml
index 1e91ee402b..93090d9d2e 100644
--- a/doc/classes/SurfaceTool.xml
+++ b/doc/classes/SurfaceTool.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="SurfaceTool" inherits="Reference" category="Core" version="3.0.alpha.custom_build">
+<class name="SurfaceTool" inherits="Reference" category="Core" version="3.0-alpha">
<brief_description>
Helper tool to create geometry.
</brief_description>
<description>
- The [SurfaceTool] is used to construct a [Mesh] by specifying vertex attributes individually. It can be used to construct a [Mesh] from script. All properties except index need to be added before a call to [method add_vertex]. For example adding vertex colors and UVs looks like
+ The [code]SurfaceTool[/code] is used to construct a [Mesh] by specifying vertex attributes individually. It can be used to construct a [Mesh] from script. All properties except index need to be added before a call to [method add_vertex]. For example adding vertex colors and UVs looks like
[codeblock]
var st = SurfaceTool.new()
st.begin(Mesh.PRIMITIVE_TRIANGLES)
@@ -12,7 +12,7 @@
st.add_uv(Vector2(0, 0))
st.add_vertex(Vector3(0, 0, 0))
[/codeblock]
- The [SurfaceTool] now contains one vertex of a triangle which has a UV coordinate and a specified [Color]. If another vertex were added without calls to [method add_uv] or [method add_color] then the last values would be used.
+ The [code]SurfaceTool[/code] now contains one vertex of a triangle which has a UV coordinate and a specified [Color]. If another vertex were added without calls to [method add_uv] or [method add_color] then the last values would be used.
It is very important that vertex attributes are passed [b]before[/b] the call to [method add_vertex], failure to do this will result in an error when committing the vertex information to a mesh.
</description>
<tutorials>
diff --git a/doc/classes/TCP_Server.xml b/doc/classes/TCP_Server.xml
index 97115619ad..20cdbe4231 100644
--- a/doc/classes/TCP_Server.xml
+++ b/doc/classes/TCP_Server.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="TCP_Server" inherits="Reference" category="Core" version="3.0.alpha.custom_build">
+<class name="TCP_Server" inherits="Reference" category="Core" version="3.0-alpha">
<brief_description>
TCP Server.
</brief_description>
diff --git a/doc/classes/TabContainer.xml b/doc/classes/TabContainer.xml
index ffe99eb82b..4921690074 100644
--- a/doc/classes/TabContainer.xml
+++ b/doc/classes/TabContainer.xml
@@ -1,11 +1,13 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="TabContainer" inherits="Control" category="Core" version="3.0.alpha.custom_build">
+<class name="TabContainer" inherits="Control" category="Core" version="3.0-alpha">
<brief_description>
Tabbed Container.
</brief_description>
<description>
- Tabbed Container. Contains several children controls, but shows only one at the same time. Clicking on the top tabs allows to change the currently visible one.
- Children controls of this one automatically.
+ Sets the active tab's [code]visible[/code] property to the value [code]true[/code]. Sets all other children's to [code]false[/code].
+ Ignores non-[Control] children.
+ Individual tabs are always visible unless you use [method set_tab_disabled] and [method set_tab_title] to hide it.
+ To hide only a tab's content, nest the content inside a child [Control], so it receives the [code]TabContainer[/code]'s visibility setting instead.
</description>
<tutorials>
</tutorials>
@@ -16,40 +18,42 @@
<return type="bool">
</return>
<description>
- Return whether the tabs should be visible or hidden.
+ Returns [code]true[/code] if the tabs are visible.
</description>
</method>
<method name="get_current_tab" qualifiers="const">
<return type="int">
</return>
<description>
- Return the current tab index that is being shown.
+ Returns the currently visible tab's index.
</description>
</method>
<method name="get_current_tab_control" qualifiers="const">
<return type="Control">
</return>
<description>
+ Returns the child [Control] node located at the active tab index.
</description>
</method>
<method name="get_popup" qualifiers="const">
<return type="Popup">
</return>
<description>
+ Returns the [Popup] node instance if one has been set already with [method set_popup].
</description>
</method>
<method name="get_previous_tab" qualifiers="const">
<return type="int">
</return>
<description>
- Return the previous tab index that was being shown.
+ Returns the previously active tab index.
</description>
</method>
<method name="get_tab_align" qualifiers="const">
<return type="int" enum="TabContainer.TabAlign">
</return>
<description>
- Return tab alignment, from the ALIGN_* enum.
+ Returns the tab alignment. See the [code]ALIGN_*[/code] constants.
</description>
</method>
<method name="get_tab_control" qualifiers="const">
@@ -58,14 +62,14 @@
<argument index="0" name="idx" type="int">
</argument>
<description>
- Return the current tab control that is being shown.
+ Returns the currently visible tab's [Control] node.
</description>
</method>
<method name="get_tab_count" qualifiers="const">
<return type="int">
</return>
<description>
- Return the amount of tabs.
+ Returns the number of tabs.
</description>
</method>
<method name="get_tab_disabled" qualifiers="const">
@@ -74,6 +78,7 @@
<argument index="0" name="tab_idx" type="int">
</argument>
<description>
+ Returns [code]true[/code] if the tab at index [code]tab_idx[/code] is disabled.
</description>
</method>
<method name="get_tab_icon" qualifiers="const">
@@ -82,6 +87,7 @@
<argument index="0" name="tab_idx" type="int">
</argument>
<description>
+ Returns the [Texture] for the tab at index [code]tab_idx[/code] or null if the tab has no [Texture].
</description>
</method>
<method name="get_tab_title" qualifiers="const">
@@ -90,7 +96,7 @@
<argument index="0" name="tab_idx" type="int">
</argument>
<description>
- Return the title for the tab. Tab titles are by default the children node name, but this can be overridden.
+ Returns the title of the tab at index [code]tab_idx[/code]. Tab titles default to the name of the indexed child node, but this can be overridden with [method set_tab_title].
</description>
</method>
<method name="set_current_tab">
@@ -99,7 +105,7 @@
<argument index="0" name="tab_idx" type="int">
</argument>
<description>
- Bring a tab (and the Control it represents) to the front, and hide the rest.
+ Sets to [code]false[/code] the [code]visible[/code] property for all [Control] children except for the tab at [code]tab_idx[/code].
</description>
</method>
<method name="set_popup">
@@ -108,6 +114,7 @@
<argument index="0" name="popup" type="Node">
</argument>
<description>
+ If set on a [Popup] node instance, a popup menu icon appears in the top-right corner of the [code]TabContainer[/code]. Clicking it will expand the [Popup] node.
</description>
</method>
<method name="set_tab_align">
@@ -116,7 +123,7 @@
<argument index="0" name="align" type="int" enum="TabContainer.TabAlign">
</argument>
<description>
- Set tab alignment, from the ALIGN_* enum. Moves tabs to the left, right or center.
+ Sets tab alignment, from the [code]ALIGN_*[/code] constants. Moves tabs to the left, right, or center.
</description>
</method>
<method name="set_tab_disabled">
@@ -127,6 +134,7 @@
<argument index="1" name="disabled" type="bool">
</argument>
<description>
+ If [code]disabled[/code] is false, hides the tab at index [code]tab_idx[/code]. Note that its title text will remain, unless also removed with [method set_tab_title].
</description>
</method>
<method name="set_tab_icon">
@@ -137,7 +145,7 @@
<argument index="1" name="icon" type="Texture">
</argument>
<description>
- Set an icon for a tab.
+ Sets an icon for the tab at index [code]tab_idx[/code].
</description>
</method>
<method name="set_tab_title">
@@ -148,7 +156,7 @@
<argument index="1" name="title" type="String">
</argument>
<description>
- Set a title for the tab. Tab titles are by default the children node name, but this can be overridden.
+ Sets a title for the tab at index [code]tab_idx[/code]. Tab titles default to the name of the indexed child node, but this can be overridden with [method set_tab_title].
</description>
</method>
<method name="set_tabs_visible">
@@ -157,35 +165,39 @@
<argument index="0" name="visible" type="bool">
</argument>
<description>
- Set whether the tabs should be visible or hidden.
+ If [code]true[/code] tabs are visible. If [code]false[/code] tabs' content and titles are hidden. Default value: [code]true[/code].
</description>
</method>
</methods>
<members>
<member name="current_tab" type="int" setter="set_current_tab" getter="get_current_tab">
+ The current tab index. When set, this index's [Control] node's [code]visible[/code] property is set to [code]true[/code] and all others are set to [code]false[/code].
</member>
<member name="tab_align" type="int" setter="set_tab_align" getter="get_tab_align" enum="TabContainer.TabAlign">
+ The alignment of all tabs in the tab container. See the [code]ALIGN_*[/code] constants for details.
</member>
<member name="tabs_visible" type="bool" setter="set_tabs_visible" getter="are_tabs_visible">
+ If [code]true[/code] tabs are visible. If [code]false[/code] tabs' content and titles are hidden. Default value: [code]true[/code].
</member>
</members>
<signals>
<signal name="pre_popup_pressed">
<description>
+ Emitted when the [code]TabContainer[/code]'s [Popup] button is clicked. See [method set_popup] for details.
</description>
</signal>
<signal name="tab_changed">
<argument index="0" name="tab" type="int">
</argument>
<description>
- Emitted only when the current tab changes.
+ Emitted when switching to another tab.
</description>
</signal>
<signal name="tab_selected">
<argument index="0" name="tab" type="int">
</argument>
<description>
- Emitted when a tab is being selected, even if it is the same tab.
+ Emitted when a tab is selected, even if it is the current tab.
</description>
</signal>
</signals>
diff --git a/doc/classes/Tabs.xml b/doc/classes/Tabs.xml
index 78821a244c..e007decf47 100644
--- a/doc/classes/Tabs.xml
+++ b/doc/classes/Tabs.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Tabs" inherits="Control" category="Core" version="3.0.alpha.custom_build">
+<class name="Tabs" inherits="Control" category="Core" version="3.0-alpha">
<brief_description>
Tabs Control.
</brief_description>
@@ -213,12 +213,12 @@
</constant>
<constant name="ALIGN_MAX" value="3">
</constant>
+ <constant name="CLOSE_BUTTON_SHOW_NEVER" value="0">
+ </constant>
<constant name="CLOSE_BUTTON_SHOW_ACTIVE_ONLY" value="1">
</constant>
<constant name="CLOSE_BUTTON_SHOW_ALWAYS" value="2">
</constant>
- <constant name="CLOSE_BUTTON_SHOW_NEVER" value="0">
- </constant>
<constant name="CLOSE_BUTTON_MAX" value="3">
</constant>
</constants>
diff --git a/doc/classes/TextEdit.xml b/doc/classes/TextEdit.xml
index d77cb69eef..0e862a7903 100644
--- a/doc/classes/TextEdit.xml
+++ b/doc/classes/TextEdit.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="TextEdit" inherits="Control" category="Core" version="3.0.alpha.custom_build">
+<class name="TextEdit" inherits="Control" category="Core" version="3.0-alpha">
<brief_description>
Multiline text editing control.
</brief_description>
@@ -232,6 +232,13 @@
Insert a given text at the cursor position.
</description>
</method>
+ <method name="is_context_menu_enabled">
+ <return type="bool">
+ </return>
+ <description>
+ Returns true if the context menu is enabled.
+ </description>
+ </method>
<method name="is_highlight_all_occurrences_enabled" qualifiers="const">
<return type="bool">
</return>
@@ -239,6 +246,25 @@
Returns true if highlight all occurrences is enabled.
</description>
</method>
+ <method name="is_highlight_current_line_enabled" qualifiers="const">
+ <return type="bool">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="is_overriding_selected_font_color" qualifiers="const">
+ <return type="bool">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="is_readonly" qualifiers="const">
+ <return type="bool">
+ </return>
+ <description>
+ Return true if the text editor is in read-only mode (see [method set_readonly]).
+ </description>
+ </method>
<method name="is_selection_active" qualifiers="const">
<return type="bool">
</return>
@@ -325,6 +351,15 @@
Select all the text.
</description>
</method>
+ <method name="set_context_menu_enabled">
+ <return type="void">
+ </return>
+ <argument index="0" name="enable" type="bool">
+ </argument>
+ <description>
+ Set the status of the context menu. When enabled, the context menu will appear when the [code]TextEdit[/code] is right clicked.
+ </description>
+ </method>
<method name="set_highlight_all_occurrences">
<return type="void">
</return>
@@ -334,6 +369,14 @@
Set to enable highlighting all occurrences of the current selection.
</description>
</method>
+ <method name="set_highlight_current_line">
+ <return type="void">
+ </return>
+ <argument index="0" name="enabled" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="set_max_chars">
<return type="void">
</return>
@@ -343,6 +386,14 @@
Set the maximum amount of characters editable.
</description>
</method>
+ <method name="set_override_selected_font_color">
+ <return type="void">
+ </return>
+ <argument index="0" name="override" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="set_readonly">
<return type="void">
</return>
@@ -419,14 +470,26 @@
</member>
<member name="caret_block_mode" type="bool" setter="cursor_set_block_mode" getter="cursor_is_block_mode">
</member>
+ <member name="context_menu_enabled" type="bool" setter="set_context_menu_enabled" getter="is_context_menu_enabled">
+ </member>
<member name="highlight_all_occurrences" type="bool" setter="set_highlight_all_occurrences" getter="is_highlight_all_occurrences_enabled">
</member>
+ <member name="highlight_current_line" type="bool" setter="set_highlight_current_line" getter="is_highlight_current_line_enabled">
+ </member>
+ <member name="override_selected_font_color" type="bool" setter="set_override_selected_font_color" getter="is_overriding_selected_font_color">
+ </member>
+ <member name="readonly" type="bool" setter="set_readonly" getter="is_readonly">
+ If [code]true[/code] read-only mode is enabled. Existing text cannot be modified and new text cannot be added.
+ </member>
<member name="show_line_numbers" type="bool" setter="set_show_line_numbers" getter="is_show_line_numbers_enabled">
</member>
<member name="smooth_scrolling" type="bool" setter="set_smooth_scroll_enable" getter="is_smooth_scroll_enabled">
</member>
<member name="syntax_highlighting" type="bool" setter="set_syntax_coloring" getter="is_syntax_coloring_enabled">
</member>
+ <member name="text" type="String" setter="set_text" getter="get_text">
+ String value of the [TextEdit].
+ </member>
<member name="v_scroll_speed" type="float" setter="set_v_scroll_speed" getter="get_v_scroll_speed">
</member>
</members>
diff --git a/doc/classes/Texture.xml b/doc/classes/Texture.xml
index cbf72eb991..a856eb64ad 100644
--- a/doc/classes/Texture.xml
+++ b/doc/classes/Texture.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Texture" inherits="Resource" category="Core" version="3.0.alpha.custom_build">
+<class name="Texture" inherits="Resource" category="Core" version="3.0-alpha">
<brief_description>
Texture for 2D and 3D.
</brief_description>
@@ -125,9 +125,6 @@
<constant name="FLAG_FILTER" value="4">
Turn on magnifying filter, to enable smooth zooming in of the texture.
</constant>
- <constant name="FLAG_VIDEO_SURFACE" value="4096">
- Texture is a video surface.
- </constant>
<constant name="FLAGS_DEFAULT" value="7">
Default flags. Generate mipmaps, repeat, and filter are enabled.
</constant>
@@ -137,5 +134,8 @@
</constant>
<constant name="FLAG_MIRRORED_REPEAT" value="32">
</constant>
+ <constant name="FLAG_VIDEO_SURFACE" value="4096">
+ Texture is a video surface.
+ </constant>
</constants>
</class>
diff --git a/doc/classes/TextureButton.xml b/doc/classes/TextureButton.xml
index 8e51548c10..a6d935376a 100644
--- a/doc/classes/TextureButton.xml
+++ b/doc/classes/TextureButton.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="TextureButton" inherits="BaseButton" category="Core" version="3.0.alpha.custom_build">
+<class name="TextureButton" inherits="BaseButton" category="Core" version="3.0-alpha">
<brief_description>
Texture-based button. Supports Pressed, Hover, Disabled and Focused states.
</brief_description>
diff --git a/doc/classes/TextureProgress.xml b/doc/classes/TextureProgress.xml
index f8165753c6..550c38920a 100644
--- a/doc/classes/TextureProgress.xml
+++ b/doc/classes/TextureProgress.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="TextureProgress" inherits="Range" category="Core" version="3.0.alpha.custom_build">
+<class name="TextureProgress" inherits="Range" category="Core" version="3.0-alpha">
<brief_description>
Texture-based progress bar. Useful for loading screens and life or stamina bars.
</brief_description>
diff --git a/doc/classes/TextureRect.xml b/doc/classes/TextureRect.xml
index af5626ae84..cef102e8ae 100644
--- a/doc/classes/TextureRect.xml
+++ b/doc/classes/TextureRect.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="TextureRect" inherits="Control" category="Core" version="3.0.alpha.custom_build">
+<class name="TextureRect" inherits="Control" category="Core" version="3.0-alpha">
<brief_description>
Draws a sprite or a texture inside a User Interface. The texture can tile or not.
</brief_description>
diff --git a/doc/classes/Theme.xml b/doc/classes/Theme.xml
index 4dd45ac821..0a95a52e4f 100644
--- a/doc/classes/Theme.xml
+++ b/doc/classes/Theme.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Theme" inherits="Resource" category="Core" version="3.0.alpha.custom_build">
+<class name="Theme" inherits="Resource" category="Core" version="3.0-alpha">
<brief_description>
Theme for controls.
</brief_description>
diff --git a/doc/classes/Thread.xml b/doc/classes/Thread.xml
index 2156d04614..24bc4bb985 100644
--- a/doc/classes/Thread.xml
+++ b/doc/classes/Thread.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Thread" inherits="Reference" category="Core" version="3.0.alpha.custom_build">
+<class name="Thread" inherits="Reference" category="Core" version="3.0-alpha">
<brief_description>
A unit of execution in a process.
</brief_description>
<description>
- A unit of execution in a process. Can run methods on [Object]\ s simultaneously. The use of synchronization via [Mutex], [Semaphore] is advised if working with shared objects.
+ A unit of execution in a process. Can run methods on [Object]s simultaneously. The use of synchronization via [Mutex], [Semaphore] is advised if working with shared objects.
</description>
<tutorials>
</tutorials>
@@ -15,14 +15,14 @@
<return type="String">
</return>
<description>
- Returns the current [Thread]\ s id, uniquely identifying it among all threads.
+ Returns the current [code]Thread[/code]s id, uniquely identifying it among all threads.
</description>
</method>
<method name="is_active" qualifiers="const">
<return type="bool">
</return>
<description>
- Returns true if this [Thread] is currently active. An active [Thread] cannot start work on a new method but can be joined with [method wait_to_finish].
+ Returns true if this [code]Thread[/code] is currently active. An active [code]Thread[/code] cannot start work on a new method but can be joined with [method wait_to_finish].
</description>
</method>
<method name="start">
@@ -37,7 +37,7 @@
<argument index="3" name="priority" type="int" default="1">
</argument>
<description>
- Starts a new [Thread] that runs "method" on object "instance" with "userdata" passed as an argument. The "priority" of the [Thread] can be changed by passing a PRIORITY_* enum.
+ Starts a new [code]Thread[/code] that runs "method" on object "instance" with "userdata" passed as an argument. The "priority" of the [code]Thread[/code] can be changed by passing a PRIORITY_* enum.
Returns OK on success, or ERR_CANT_CREATE on failure.
</description>
</method>
@@ -45,7 +45,7 @@
<return type="Variant">
</return>
<description>
- Joins the [Thread] and waits for it to finish. Returns what the method called returned.
+ Joins the [code]Thread[/code] and waits for it to finish. Returns what the method called returned.
</description>
</method>
</methods>
diff --git a/doc/classes/TileMap.xml b/doc/classes/TileMap.xml
index c44fa500cd..c48f58f123 100644
--- a/doc/classes/TileMap.xml
+++ b/doc/classes/TileMap.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="TileMap" inherits="Node2D" category="Core" version="3.0.alpha.custom_build">
+<class name="TileMap" inherits="Node2D" category="Core" version="3.0-alpha">
<brief_description>
Node for 2D tile-based maps.
</brief_description>
@@ -59,6 +59,12 @@
Return true if tiles are to be centered in y coordinate (by default this is false and they are drawn from upper left cell corner).
</description>
</method>
+ <method name="get_clip_uv" qualifiers="const">
+ <return type="bool">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="get_collision_bounce" qualifiers="const">
<return type="float">
</return>
@@ -298,6 +304,14 @@
Set tiles to be centered in y coordinate. (by default this is false and they are drawn from upper left cell corner).
</description>
</method>
+ <method name="set_clip_uv">
+ <return type="void">
+ </return>
+ <argument index="0" name="enable" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="set_collision_bounce">
<return type="void">
</return>
@@ -450,6 +464,8 @@
</method>
</methods>
<members>
+ <member name="cell_clip_uv" type="bool" setter="set_clip_uv" getter="get_clip_uv">
+ </member>
<member name="cell_custom_transform" type="Transform2D" setter="set_custom_transform" getter="get_custom_transform">
The custom [Transform2D] to be applied to the TileMap's cells.
</member>
diff --git a/doc/classes/TileSet.xml b/doc/classes/TileSet.xml
index a858138144..a1063567f8 100644
--- a/doc/classes/TileSet.xml
+++ b/doc/classes/TileSet.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="TileSet" inherits="Resource" category="Core" version="3.0.alpha.custom_build">
+<class name="TileSet" inherits="Resource" category="Core" version="3.0-alpha">
<brief_description>
Tile library for tilemaps.
</brief_description>
diff --git a/doc/classes/Timer.xml b/doc/classes/Timer.xml
index 35979bb1fc..8d834537a7 100644
--- a/doc/classes/Timer.xml
+++ b/doc/classes/Timer.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Timer" inherits="Node" category="Core" version="3.0.alpha.custom_build">
+<class name="Timer" inherits="Node" category="Core" version="3.0-alpha">
<brief_description>
A countdown timer.
</brief_description>
@@ -141,8 +141,8 @@
</signal>
</signals>
<constants>
- <constant name="TIMER_PROCESS_FIXED" value="0">
- Update the Timer at fixed intervals (framerate processing).
+ <constant name="TIMER_PROCESS_PHYSICS" value="0">
+ Update the Timer during the physics step at each frame (fixed framerate processing).
</constant>
<constant name="TIMER_PROCESS_IDLE" value="1">
Update the Timer during the idle time at each frame.
diff --git a/doc/classes/ToolButton.xml b/doc/classes/ToolButton.xml
index 7723dadb83..b541d00d2f 100644
--- a/doc/classes/ToolButton.xml
+++ b/doc/classes/ToolButton.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ToolButton" inherits="Button" category="Core" version="3.0.alpha.custom_build">
+<class name="ToolButton" inherits="Button" category="Core" version="3.0-alpha">
<brief_description>
Flat button helper class.
</brief_description>
diff --git a/doc/classes/TouchScreenButton.xml b/doc/classes/TouchScreenButton.xml
index 8a96fa1454..283ead1b1b 100644
--- a/doc/classes/TouchScreenButton.xml
+++ b/doc/classes/TouchScreenButton.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="TouchScreenButton" inherits="Node2D" category="Core" version="3.0.alpha.custom_build">
+<class name="TouchScreenButton" inherits="Node2D" category="Core" version="3.0-alpha">
<brief_description>
+ Button for touch screen devices.
</brief_description>
<description>
+ Button for touch screen devices. You can set it to be visible on all screens, or only on touch devices.
</description>
<tutorials>
</tutorials>
@@ -13,36 +15,42 @@
<return type="String">
</return>
<description>
+ Returns the button's action.
</description>
</method>
<method name="get_bitmask" qualifiers="const">
<return type="BitMap">
</return>
<description>
+ Returns the button's bitmask.
</description>
</method>
<method name="get_shape" qualifiers="const">
<return type="Shape2D">
</return>
<description>
+ Returns the button's shape.
</description>
</method>
<method name="get_texture" qualifiers="const">
<return type="Texture">
</return>
<description>
+ Returns the button's texture for the normal state.
</description>
</method>
<method name="get_texture_pressed" qualifiers="const">
<return type="Texture">
</return>
<description>
+ Returns the button's texture for the pressed state.
</description>
</method>
<method name="get_visibility_mode" qualifiers="const">
<return type="int" enum="TouchScreenButton.VisibilityMode">
</return>
<description>
+ Sets the button's visibility mode. See [code]VISIBILITY_*[/code] constants.
</description>
</method>
<method name="is_passby_press_enabled" qualifiers="const">
@@ -55,6 +63,7 @@
<return type="bool">
</return>
<description>
+ Returns [code]true[/code] if this button is currently pressed.
</description>
</method>
<method name="is_shape_centered" qualifiers="const">
@@ -75,6 +84,7 @@
<argument index="0" name="action" type="String">
</argument>
<description>
+ Sets the button's action.
</description>
</method>
<method name="set_bitmask">
@@ -83,6 +93,7 @@
<argument index="0" name="bitmask" type="BitMap">
</argument>
<description>
+ Sets the button's [BitMap] bitmask.
</description>
</method>
<method name="set_passby_press">
@@ -91,6 +102,7 @@
<argument index="0" name="enabled" type="bool">
</argument>
<description>
+ If [code]true[/code] passby presses are enabled for this button.
</description>
</method>
<method name="set_shape">
@@ -99,6 +111,7 @@
<argument index="0" name="shape" type="Shape2D">
</argument>
<description>
+ Sets the button's shape.
</description>
</method>
<method name="set_shape_centered">
@@ -107,6 +120,7 @@
<argument index="0" name="bool" type="bool">
</argument>
<description>
+ If [code]true[/code] the button's shape is centered.
</description>
</method>
<method name="set_shape_visible">
@@ -115,6 +129,7 @@
<argument index="0" name="bool" type="bool">
</argument>
<description>
+ If [code]true[/code] the button's shape is visible.
</description>
</method>
<method name="set_texture">
@@ -123,6 +138,7 @@
<argument index="0" name="texture" type="Texture">
</argument>
<description>
+ Sets the button's [Texture] for the normal state.
</description>
</method>
<method name="set_texture_pressed">
@@ -131,6 +147,7 @@
<argument index="0" name="texture_pressed" type="Texture">
</argument>
<description>
+ Sets the button's [Texture] for the pressed state.
</description>
</method>
<method name="set_visibility_mode">
@@ -139,43 +156,57 @@
<argument index="0" name="mode" type="int" enum="TouchScreenButton.VisibilityMode">
</argument>
<description>
+ Sets the button's visibility mode. See the [code]VISIBILITY_*[/code] constants.
</description>
</method>
</methods>
<members>
<member name="action" type="String" setter="set_action" getter="get_action">
+ The button's action. Actions can be handled with [InputEventAction].
</member>
<member name="bitmask" type="BitMap" setter="set_bitmask" getter="get_bitmask">
+ The button's bitmask.
</member>
<member name="normal" type="Texture" setter="set_texture" getter="get_texture">
+ The button's texture for the normal state.
</member>
<member name="passby_press" type="bool" setter="set_passby_press" getter="is_passby_press_enabled">
+ If [code]true[/code] passby presses are enabled.
</member>
<member name="pressed" type="Texture" setter="set_texture_pressed" getter="get_texture_pressed">
+ The button's texture for the pressed state.
</member>
<member name="shape" type="Shape2D" setter="set_shape" getter="get_shape">
+ The button's shape.
</member>
<member name="shape_centered" type="bool" setter="set_shape_centered" getter="is_shape_centered">
+ If [code]true[/code] the button's shape is centered.
</member>
<member name="shape_visible" type="bool" setter="set_shape_visible" getter="is_shape_visible">
+ If [code]true[/code] the button's shape is visible.
</member>
<member name="visibility_mode" type="int" setter="set_visibility_mode" getter="get_visibility_mode" enum="TouchScreenButton.VisibilityMode">
+ The button's visibility mode. See [code]VISIBILITY_*[/code] constants.
</member>
</members>
<signals>
<signal name="pressed">
<description>
+ Emitted when the button is pressed (down).
</description>
</signal>
<signal name="released">
<description>
+ Emitted when the button is released (up).
</description>
</signal>
</signals>
<constants>
<constant name="VISIBILITY_ALWAYS" value="0">
+ Always visible.
</constant>
<constant name="VISIBILITY_TOUCHSCREEN_ONLY" value="1">
+ Visible on touch screens only.
</constant>
</constants>
</class>
diff --git a/doc/classes/Transform.xml b/doc/classes/Transform.xml
index 6780de1943..9e1672e6f5 100644
--- a/doc/classes/Transform.xml
+++ b/doc/classes/Transform.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Transform" category="Built-In Types" version="3.0.alpha.custom_build">
+<class name="Transform" category="Built-In Types" version="3.0-alpha">
<brief_description>
3D Transformation. 3x4 matrix.
</brief_description>
@@ -68,7 +68,7 @@
<return type="Transform">
</return>
<description>
- Returns the inverse of the transfrom, under the assumption that the transformation is composed of rotation, scaling and translation.
+ Returns the inverse of the transform, under the assumption that the transformation is composed of rotation, scaling and translation.
</description>
</method>
<method name="interpolate_with">
@@ -104,7 +104,7 @@
<return type="Transform">
</return>
<description>
- Returns the transfrom with the basis orthogonal (90 degrees), and normalized axis vectors.
+ Returns the transform with the basis orthogonal (90 degrees), and normalized axis vectors.
</description>
</method>
<method name="rotated">
diff --git a/doc/classes/Transform2D.xml b/doc/classes/Transform2D.xml
index 0e39505ac3..d17063b550 100644
--- a/doc/classes/Transform2D.xml
+++ b/doc/classes/Transform2D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Transform2D" category="Built-In Types" version="3.0.alpha.custom_build">
+<class name="Transform2D" category="Built-In Types" version="3.0-alpha">
<brief_description>
2D Transformation. 3x2 matrix.
</brief_description>
@@ -17,7 +17,7 @@
<argument index="0" name="from" type="Transform">
</argument>
<description>
- Constructs the [Transform2D] from a 3D [Transform].
+ Constructs the [code]Transform2D[/code] from a 3D [Transform].
</description>
</method>
<method name="Transform2D">
@@ -30,7 +30,7 @@
<argument index="2" name="origin" type="Vector2">
</argument>
<description>
- Constructs the [Transform2D] from 3 [Vector2] consisting of rows x, y and origin.
+ Constructs the [code]Transform2D[/code] from 3 [Vector2] consisting of rows x, y and origin.
</description>
</method>
<method name="Transform2D">
@@ -41,7 +41,7 @@
<argument index="1" name="position" type="Vector2">
</argument>
<description>
- Constructs the [Transform2D] from rotation angle in radians and position [Vector2].
+ Constructs the [code]Transform2D[/code] from rotation angle in radians and position [Vector2].
</description>
</method>
<method name="affine_inverse">
@@ -112,7 +112,7 @@
<return type="Transform2D">
</return>
<description>
- Returns the transfrom with the basis orthogonal (90 degrees), and normalized axis vectors.
+ Returns the transform with the basis orthogonal (90 degrees), and normalized axis vectors.
</description>
</method>
<method name="rotated">
diff --git a/doc/classes/Translation.xml b/doc/classes/Translation.xml
index c0707d26b8..dc2609b3e1 100644
--- a/doc/classes/Translation.xml
+++ b/doc/classes/Translation.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Translation" inherits="Resource" category="Core" version="3.0.alpha.custom_build">
+<class name="Translation" inherits="Resource" category="Core" version="3.0-alpha">
<brief_description>
Language Translation.
</brief_description>
diff --git a/doc/classes/TranslationServer.xml b/doc/classes/TranslationServer.xml
index 974b0e283f..8b50bf027b 100644
--- a/doc/classes/TranslationServer.xml
+++ b/doc/classes/TranslationServer.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="TranslationServer" inherits="Object" category="Core" version="3.0.alpha.custom_build">
+<class name="TranslationServer" inherits="Object" category="Core" version="3.0-alpha">
<brief_description>
Server that manages all translations. Translations can be set to it and removed from it.
</brief_description>
@@ -30,6 +30,14 @@
<description>
</description>
</method>
+ <method name="get_locale_name" qualifiers="const">
+ <return type="String">
+ </return>
+ <argument index="0" name="locale" type="String">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="remove_translation">
<return type="void">
</return>
diff --git a/doc/classes/Tree.xml b/doc/classes/Tree.xml
index 82e85126cc..508a0ec194 100644
--- a/doc/classes/Tree.xml
+++ b/doc/classes/Tree.xml
@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Tree" inherits="Control" category="Core" version="3.0.alpha.custom_build">
+<class name="Tree" inherits="Control" category="Core" version="3.0-alpha">
<brief_description>
Control to show a tree of items.
</brief_description>
<description>
- This shows a tree of items that can be selected, expanded and collapsed. The tree can have multiple columns with custom controls like text editing, buttons and popups. It can be useful for structural displaying and interactions.
- Trees are built via code, using [TreeItem] objects to create the structure. They have a single root but multiple root can be simulated if a dummy hidden root is added.
+ This shows a tree of items that can be selected, expanded and collapsed. The tree can have multiple columns with custom controls like text editing, buttons and popups. It can be useful for structured displays and interactions.
+ Trees are built via code, using [TreeItem] objects to create the structure. They have a single root but multiple roots can be simulated if a dummy hidden root is added.
[codeblock]
func _ready():
var tree = Tree.new()
@@ -26,14 +26,14 @@
<return type="bool">
</return>
<description>
- Get whether the column titles are being shown.
+ Returns [code]true[/code] if the column titles are being shown.
</description>
</method>
<method name="clear">
<return type="void">
</return>
<description>
- Clear the tree. This erases all of the items.
+ Clears the tree. This removes all items.
</description>
</method>
<method name="create_item">
@@ -42,27 +42,28 @@
<argument index="0" name="parent" type="Object" default="null">
</argument>
<description>
- Create an item in the tree and add it as the last child of [code]parent[/code]. If parent is not given, it will be added as the last child of the root, or it'll the be the root itself if the tree is empty.
+ Create an item in the tree and add it as the last child of [code]parent[/code]. If parent is not given, it will be added as the root's last child, or it'll the be the root itself if the tree is empty.
</description>
</method>
<method name="ensure_cursor_is_visible">
<return type="void">
</return>
<description>
- Make the current selected item visible. This will scroll the tree to make sure the selected item is in sight.
+ Makes the currently selected item visible. This will scroll the tree to make sure the selected item is visible.
</description>
</method>
<method name="get_allow_reselect" qualifiers="const">
<return type="bool">
</return>
<description>
+ Returns [code]true[/code] if a cell that is currently already selected may be selected again.
</description>
</method>
<method name="get_allow_rmb_select" qualifiers="const">
<return type="bool">
</return>
<description>
- Get whether a right click can select items.
+ Returns [code]true[/code] if a right click can select items.
</description>
</method>
<method name="get_column_at_position" qualifiers="const">
@@ -71,7 +72,7 @@
<argument index="0" name="position" type="Vector2">
</argument>
<description>
- Get the column index under the given point.
+ Returns the column index under the given point.
</description>
</method>
<method name="get_column_title" qualifiers="const">
@@ -80,7 +81,7 @@
<argument index="0" name="column" type="int">
</argument>
<description>
- Get the title of the given column.
+ Returns the column's title.
</description>
</method>
<method name="get_column_width" qualifiers="const">
@@ -89,28 +90,28 @@
<argument index="0" name="column" type="int">
</argument>
<description>
- Get the width of the given column in pixels.
+ Returns the column's width in pixels.
</description>
</method>
<method name="get_columns" qualifiers="const">
<return type="int">
</return>
<description>
- Get the amount of columns.
+ Returns the amount of columns.
</description>
</method>
<method name="get_custom_popup_rect" qualifiers="const">
<return type="Rect2">
</return>
<description>
- Get the rectangle for custom popups. Helper to create custom cell controls that display a popup. See [method TreeItem.set_cell_mode].
+ Returns the rectangle for custom popups. Helper to create custom cell controls that display a popup. See [method TreeItem.set_cell_mode].
</description>
</method>
<method name="get_drop_mode_flags" qualifiers="const">
<return type="int">
</return>
<description>
- Get the flags of the current drop mode.
+ Returns the current drop mode's flags.
</description>
</method>
<method name="get_drop_section_at_position" qualifiers="const">
@@ -125,14 +126,14 @@
<return type="TreeItem">
</return>
<description>
- Get the current edited item. This is only available for custom cell mode.
+ Returns the currently edited item. This is only available for custom cell mode.
</description>
</method>
<method name="get_edited_column" qualifiers="const">
<return type="int">
</return>
<description>
- Get the column of the cell for the current edited icon. This is only available for custom cell mode.
+ Returns the column for the currently edited item. This is only available for custom cell mode.
</description>
</method>
<method name="get_item_area_rect" qualifiers="const">
@@ -143,7 +144,7 @@
<argument index="1" name="column" type="int" default="-1">
</argument>
<description>
- Get the rectangle area of the 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 column 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">
@@ -152,7 +153,7 @@
<argument index="0" name="position" type="Vector2">
</argument>
<description>
- Get the tree item at the specified position (relative to the tree origin position).
+ Returns the tree item at the specified position (relative to the tree origin position).
</description>
</method>
<method name="get_next_selected">
@@ -161,49 +162,49 @@
<argument index="0" name="from" type="Object">
</argument>
<description>
- Get the next selected item after the given one.
+ Returns the next selected item after the given one.
</description>
</method>
<method name="get_pressed_button" qualifiers="const">
<return type="int">
</return>
<description>
- Get the index of the last pressed button.
+ Returns the last pressed button's index.
</description>
</method>
<method name="get_root">
<return type="TreeItem">
</return>
<description>
- Get the root item of the tree.
+ Returns the tree's root item.
</description>
</method>
<method name="get_scroll" qualifiers="const">
<return type="Vector2">
</return>
<description>
- Get the current scrolling position.
+ Returns the current scrolling position.
</description>
</method>
<method name="get_selected" qualifiers="const">
<return type="TreeItem">
</return>
<description>
- Get the currently selected item.
+ Returns the currently selected item.
</description>
</method>
<method name="get_selected_column" qualifiers="const">
<return type="int">
</return>
<description>
- Get the column number of the current selection.
+ Returns the current selection's column.
</description>
</method>
<method name="is_folding_hidden" qualifiers="const">
<return type="bool">
</return>
<description>
- Get whether the folding arrow is hidden.
+ Returns [code]true[/code] if the folding arrow is hidden.
</description>
</method>
<method name="set_allow_reselect">
@@ -212,6 +213,7 @@
<argument index="0" name="allow" type="bool">
</argument>
<description>
+ If [code]true[/code] the currently selected cell may be selected again.
</description>
</method>
<method name="set_allow_rmb_select">
@@ -220,7 +222,7 @@
<argument index="0" name="allow" type="bool">
</argument>
<description>
- Set whether or not a right mouse button click can select items.
+ If [code]true[/code] a right mouse button click can select items.
</description>
</method>
<method name="set_column_expand">
@@ -231,7 +233,7 @@
<argument index="1" name="expand" type="bool">
</argument>
<description>
- Set whether a column will have the "Expand" flag of [Control].
+ If [code]true[/code] the column will have the "Expand" flag of [Control].
</description>
</method>
<method name="set_column_min_width">
@@ -262,7 +264,7 @@
<argument index="0" name="visible" type="bool">
</argument>
<description>
- Set whether the column titles visibility.
+ If [code]true[/code] column titles are visible.
</description>
</method>
<method name="set_columns">
@@ -289,7 +291,7 @@
<argument index="0" name="hide" type="bool">
</argument>
<description>
- Set whether the folding arrow should be hidden.
+ If [code]true[/code] the folding arrow is hidden.
</description>
</method>
<method name="set_hide_root">
@@ -298,7 +300,7 @@
<argument index="0" name="enable" type="bool">
</argument>
<description>
- Set whether the root of the tree should be hidden.
+ If [code]true[/code] the tree's root is hidden.
</description>
</method>
<method name="set_select_mode">
@@ -307,7 +309,7 @@
<argument index="0" name="mode" type="int" enum="Tree.SelectMode">
</argument>
<description>
- Set the selection mode. Use one of the [code]SELECT_*[/code] constants.
+ Allow single or multiple selection. See the [code]SELECT_*[/code] constants.
</description>
</method>
</methods>
@@ -332,6 +334,7 @@
<argument index="0" name="column" type="int">
</argument>
<description>
+ Emitted when a column's title is pressed.
</description>
</signal>
<signal name="custom_popup_edited">
@@ -366,15 +369,17 @@
</signal>
<signal name="item_double_clicked">
<description>
+ Emitted when an item is double clicked.
</description>
</signal>
<signal name="item_edited">
<description>
- Emitted when an item is editted.
+ Emitted when an item is edited.
</description>
</signal>
<signal name="item_rmb_edited">
<description>
+ Emitted when an item is edited using the right mouse button.
</description>
</signal>
<signal name="item_rmb_selected">
@@ -397,15 +402,18 @@
<argument index="2" name="selected" type="bool">
</argument>
<description>
+ Emitted instead of [code]item_selected[/code] when [code]select_mode[/code] is [code]SELECT_MULTI[/code].
</description>
</signal>
</signals>
<constants>
<constant name="SELECT_SINGLE" value="0">
+ Allow selection of a single item at a time.
</constant>
<constant name="SELECT_ROW" value="1">
</constant>
<constant name="SELECT_MULTI" value="2">
+ Allow selection of multiple items at the same time.
</constant>
<constant name="DROP_MODE_DISABLED" value="0">
</constant>
diff --git a/doc/classes/TreeItem.xml b/doc/classes/TreeItem.xml
index d1e45bd10f..b463ef7bbb 100644
--- a/doc/classes/TreeItem.xml
+++ b/doc/classes/TreeItem.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="TreeItem" inherits="Object" category="Core" version="3.0.alpha.custom_build">
+<class name="TreeItem" inherits="Object" category="Core" version="3.0-alpha">
<brief_description>
+ Control for a single item inside a [Tree].
</brief_description>
<description>
+ Control for a single item inside a [Tree]. May have child [code]TreeItem[/code]s and be styled as well as contain buttons.
</description>
<tutorials>
</tutorials>
@@ -23,6 +25,7 @@
<argument index="4" name="tooltip" type="String" default="&quot;&quot;">
</argument>
<description>
+ Adds a button with [Texture] [code]button[/code] at column [code]column[/code]. The [code]button_idx[/code] index is used to identify the button when calling other methods. If not specified, the next available index is used, which may be retrieved by calling [code]get_buton_count()[/code] immediately after this method. Optionally, the button can be [code]disabled[/code] and have a [code]tooltip[/code].
</description>
</method>
<method name="clear_custom_bg_color">
@@ -31,6 +34,7 @@
<argument index="0" name="column" type="int">
</argument>
<description>
+ Resets the background color for the given column to default.
</description>
</method>
<method name="clear_custom_color">
@@ -39,6 +43,7 @@
<argument index="0" name="column" type="int">
</argument>
<description>
+ Resets the color for the given column to default.
</description>
</method>
<method name="deselect">
@@ -47,6 +52,7 @@
<argument index="0" name="column" type="int">
</argument>
<description>
+ Deselects the given column.
</description>
</method>
<method name="erase_button">
@@ -57,6 +63,7 @@
<argument index="1" name="button_idx" type="int">
</argument>
<description>
+ Removes the button at index [code]button_idx[/code] in column [code]column[/code].
</description>
</method>
<method name="get_button" qualifiers="const">
@@ -67,6 +74,7 @@
<argument index="1" name="button_idx" type="int">
</argument>
<description>
+ Returns the [Texture] of the button at index [code]button_idx[/code] in column [code]column[/code].
</description>
</method>
<method name="get_button_count" qualifiers="const">
@@ -75,6 +83,7 @@
<argument index="0" name="column" type="int">
</argument>
<description>
+ Returns the number of buttons in column [code]column[/code]. May be used to get the most recently added button's index, if no index was specified.
</description>
</method>
<method name="get_cell_mode" qualifiers="const">
@@ -83,12 +92,14 @@
<argument index="0" name="column" type="int">
</argument>
<description>
+ Returns the column's cell mode. See [code]CELL_MODE_*[/code] constants.
</description>
</method>
<method name="get_children">
<return type="TreeItem">
</return>
<description>
+ Returns the TreeItem's child items.
</description>
</method>
<method name="get_custom_bg_color" qualifiers="const">
@@ -97,12 +108,14 @@
<argument index="0" name="column" type="int">
</argument>
<description>
+ Returns the custom background color of column [code]column[/code].
</description>
</method>
<method name="get_custom_minimum_height" qualifiers="const">
<return type="int">
</return>
<description>
+ Returns the custom minimum height.
</description>
</method>
<method name="get_expand_right" qualifiers="const">
@@ -111,6 +124,7 @@
<argument index="0" name="column" type="int">
</argument>
<description>
+ Returns [code]true[/code] if [code]expand_right[/code] is set.
</description>
</method>
<method name="get_icon" qualifiers="const">
@@ -119,6 +133,7 @@
<argument index="0" name="column" type="int">
</argument>
<description>
+ Returns the given column's icon [Texture]. Error if no icon is set.
</description>
</method>
<method name="get_icon_max_width" qualifiers="const">
@@ -127,6 +142,7 @@
<argument index="0" name="column" type="int">
</argument>
<description>
+ Returns the column's icon's maximum width.
</description>
</method>
<method name="get_icon_region" qualifiers="const">
@@ -135,6 +151,7 @@
<argument index="0" name="column" type="int">
</argument>
<description>
+ Returns the icon [Texture] region as [Rect2].
</description>
</method>
<method name="get_metadata" qualifiers="const">
@@ -149,30 +166,35 @@
<return type="TreeItem">
</return>
<description>
+ Returns the next TreeItem in the tree.
</description>
</method>
<method name="get_next_visible">
<return type="TreeItem">
</return>
<description>
+ Returns the next visible TreeItem in the tree.
</description>
</method>
<method name="get_parent">
<return type="TreeItem">
</return>
<description>
+ Returns the parent TreeItem.
</description>
</method>
<method name="get_prev">
<return type="TreeItem">
</return>
<description>
+ Returns the previous TreeItem in the tree.
</description>
</method>
<method name="get_prev_visible">
<return type="TreeItem">
</return>
<description>
+ Returns the previous visible TreeItem in the tree.
</description>
</method>
<method name="get_range" qualifiers="const">
@@ -197,6 +219,7 @@
<argument index="0" name="column" type="int">
</argument>
<description>
+ Returns the given column's text.
</description>
</method>
<method name="get_text_align" qualifiers="const">
@@ -205,6 +228,7 @@
<argument index="0" name="column" type="int">
</argument>
<description>
+ Returns the given column's text alignment.
</description>
</method>
<method name="get_tooltip" qualifiers="const">
@@ -213,6 +237,7 @@
<argument index="0" name="column" type="int">
</argument>
<description>
+ Returns the given column's tooltip.
</description>
</method>
<method name="is_button_disabled" qualifiers="const">
@@ -223,6 +248,7 @@
<argument index="1" name="button_idx" type="int">
</argument>
<description>
+ Returns [code]true[/code] if the button at index [code]button_idx[/code] for the given column is disabled.
</description>
</method>
<method name="is_checked" qualifiers="const">
@@ -231,12 +257,14 @@
<argument index="0" name="column" type="int">
</argument>
<description>
+ Returns [code]true[/code] if the given column is checked.
</description>
</method>
<method name="is_collapsed">
<return type="bool">
</return>
<description>
+ Returns [code]true[/code] if this TreeItem is collapsed.
</description>
</method>
<method name="is_custom_set_as_button" qualifiers="const">
@@ -253,12 +281,14 @@
<argument index="0" name="column" type="int">
</argument>
<description>
+ Returns [code]true[/code] if column [code]column[/code] is editable.
</description>
</method>
<method name="is_folding_disabled" qualifiers="const">
<return type="bool">
</return>
<description>
+ Returns [code]true[/code] if folding is disabled for this TreeItem.
</description>
</method>
<method name="is_selectable" qualifiers="const">
@@ -267,6 +297,7 @@
<argument index="0" name="column" type="int">
</argument>
<description>
+ Returns [code]true[/code] if column [code]column[/code] is selectable.
</description>
</method>
<method name="is_selected">
@@ -275,18 +306,21 @@
<argument index="0" name="column" type="int">
</argument>
<description>
+ Returns [code]true[/code] if column [code]column[/code] is selected.
</description>
</method>
<method name="move_to_bottom">
<return type="void">
</return>
<description>
+ Moves this TreeItem to the bottom in the [Tree] hierarchy.
</description>
</method>
<method name="move_to_top">
<return type="void">
</return>
<description>
+ Moves this TreeItem to the top in the [Tree] hierarchy.
</description>
</method>
<method name="remove_child">
@@ -295,6 +329,7 @@
<argument index="0" name="child" type="Object">
</argument>
<description>
+ Removes the child TreeItem at index [code]index[/code].
</description>
</method>
<method name="select">
@@ -303,6 +338,7 @@
<argument index="0" name="column" type="int">
</argument>
<description>
+ Selects the column [code]column[/code].
</description>
</method>
<method name="set_button">
@@ -315,6 +351,7 @@
<argument index="2" name="button" type="Texture">
</argument>
<description>
+ Sets the given column's button [Texture] at index [code]button_idx[/code] to [code]button[/code].
</description>
</method>
<method name="set_cell_mode">
@@ -325,6 +362,7 @@
<argument index="1" name="mode" type="int" enum="TreeItem.TreeCellMode">
</argument>
<description>
+ Sets the given column's cell mode to [code]mode[/code]. See [code]CELL_MODE_*[/code] constants.
</description>
</method>
<method name="set_checked">
@@ -335,6 +373,7 @@
<argument index="1" name="checked" type="bool">
</argument>
<description>
+ If [code]true[/code] the column [code]column[/code] is checked.
</description>
</method>
<method name="set_collapsed">
@@ -343,6 +382,7 @@
<argument index="0" name="enable" type="bool">
</argument>
<description>
+ If [code]true[/code] the TreeItem is collapsed.
</description>
</method>
<method name="set_custom_as_button">
@@ -365,6 +405,7 @@
<argument index="2" name="just_outline" type="bool" default="false">
</argument>
<description>
+ Sets the given column's custom background color and whether to just use it as an outline.
</description>
</method>
<method name="set_custom_color">
@@ -375,6 +416,7 @@
<argument index="1" name="color" type="Color">
</argument>
<description>
+ Sets the given column's custom color.
</description>
</method>
<method name="set_custom_draw">
@@ -387,6 +429,7 @@
<argument index="2" name="callback" type="String">
</argument>
<description>
+ Sets the given column's custom draw callback to [code]callback[/code] method on [code]object[/code].
</description>
</method>
<method name="set_custom_minimum_height">
@@ -395,6 +438,7 @@
<argument index="0" name="height" type="int">
</argument>
<description>
+ Sets the custom minimum height of this TreeItem.
</description>
</method>
<method name="set_disable_folding">
@@ -403,6 +447,7 @@
<argument index="0" name="disable" type="bool">
</argument>
<description>
+ If [code]true[/code] folding is disabled for this TreeItem.
</description>
</method>
<method name="set_editable">
@@ -413,6 +458,7 @@
<argument index="1" name="enabled" type="bool">
</argument>
<description>
+ If [code]true[/code] column [code]column[/code] is editable.
</description>
</method>
<method name="set_expand_right">
@@ -423,6 +469,7 @@
<argument index="1" name="enable" type="bool">
</argument>
<description>
+ If [code]true[/code] column [code]column[/code] is expanded to the right.
</description>
</method>
<method name="set_icon">
@@ -433,6 +480,7 @@
<argument index="1" name="texture" type="Texture">
</argument>
<description>
+ Sets the given column's icon [Texture].
</description>
</method>
<method name="set_icon_max_width">
@@ -443,6 +491,7 @@
<argument index="1" name="width" type="int">
</argument>
<description>
+ Sets the given column's icon's maximum width.
</description>
</method>
<method name="set_icon_region">
@@ -453,6 +502,7 @@
<argument index="1" name="region" type="Rect2">
</argument>
<description>
+ Sets the given column's icon's texture region.
</description>
</method>
<method name="set_metadata">
@@ -499,6 +549,7 @@
<argument index="1" name="selectable" type="bool">
</argument>
<description>
+ If [code]true[/code] the given column is selectable.
</description>
</method>
<method name="set_text">
@@ -519,6 +570,7 @@
<argument index="1" name="text_align" type="int" enum="TreeItem.TextAlign">
</argument>
<description>
+ Sets the given column's text alignment. See [code]ALIGN_*[/code] constants.
</description>
</method>
<method name="set_tooltip">
@@ -529,27 +581,36 @@
<argument index="1" name="tooltip" type="String">
</argument>
<description>
+ Sets the given column's tooltip text.
</description>
</method>
</methods>
<constants>
<constant name="CELL_MODE_STRING" value="0">
+ Cell contains a string.
</constant>
<constant name="CELL_MODE_CHECK" value="1">
+ Cell can be checked.
</constant>
<constant name="CELL_MODE_RANGE" value="2">
+ Cell contains a range.
</constant>
<constant name="CELL_MODE_RANGE_EXPRESSION" value="3">
+ Cell contains a range expression.
</constant>
<constant name="CELL_MODE_ICON" value="4">
+ Cell contains an icon.
</constant>
<constant name="CELL_MODE_CUSTOM" value="5">
</constant>
<constant name="ALIGN_LEFT" value="0">
+ Align text to the left. See [code]set_text_align()[/code].
</constant>
<constant name="ALIGN_CENTER" value="1">
+ Center text. See [code]set_text_align()[/code].
</constant>
<constant name="ALIGN_RIGHT" value="2">
+ Align text to the right. See [code]set_text_align()[/code].
</constant>
</constants>
</class>
diff --git a/doc/classes/TriangleMesh.xml b/doc/classes/TriangleMesh.xml
index 21b85c1d05..21a37913c8 100644
--- a/doc/classes/TriangleMesh.xml
+++ b/doc/classes/TriangleMesh.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="TriangleMesh" inherits="Reference" category="Core" version="3.0.alpha.custom_build">
+<class name="TriangleMesh" inherits="Reference" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/Tween.xml b/doc/classes/Tween.xml
index d291f44de3..822eee5838 100644
--- a/doc/classes/Tween.xml
+++ b/doc/classes/Tween.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Tween" inherits="Node" category="Core" version="3.0.alpha.custom_build">
+<class name="Tween" inherits="Node" category="Core" version="3.0-alpha">
<brief_description>
Node useful for animations with unknown start and end points.
</brief_description>
@@ -12,7 +12,7 @@
tween.start()
[/codeblock]
Some of the methods of this class require a property name. You can get the property name by hovering over the property in the inspector of the editor.
- Many of the methods accept [code]trans_type[/code] and [code]ease_type[/code]. The first accepts an TRANS_* constant, and refers to the way the timing of the animation is handled (you might want to see [code]http://easings.net/[/code] for some examples). The second accepts an EASE_* constant, and controls the where [code]trans_type[/code] is applied to the interpolation (in the beginning, the end, or both). If you don't know which transision and easing to pick, you can try different TRANS_* constants with EASE_IN_OUT, and use the one that looks best.
+ Many of the methods accept [code]trans_type[/code] and [code]ease_type[/code]. The first accepts an TRANS_* constant, and refers to the way the timing of the animation is handled (you might want to see [code]http://easings.net/[/code] for some examples). The second accepts an EASE_* constant, and controls the where [code]trans_type[/code] is applied to the interpolation (in the beginning, the end, or both). If you don't know which transition and easing to pick, you can try different TRANS_* constants with EASE_IN_OUT, and use the one that looks best.
</description>
<tutorials>
</tutorials>
@@ -135,7 +135,7 @@
<argument index="7" name="arg5" type="Variant" default="null">
</argument>
<description>
- Call [code]callback[/code] of [code]object[/code] after [code]duration[/code] on the main thread (similar to [methog Object.call_deferred). [code]arg1[/code]-[code]arg5[/code] are arguments to be passed to the callback.
+ Call [code]callback[/code] of [code]object[/code] after [code]duration[/code] on the main thread (similar to [method Object.call_deferred]). [code]arg1[/code]-[code]arg5[/code] are arguments to be passed to the callback.
</description>
</method>
<method name="interpolate_method">
@@ -158,7 +158,7 @@
<argument index="7" name="delay" type="float" default="0">
</argument>
<description>
- Animate [code]method[/code] of [code]object[/code] from [code]initial_val[/code] to [code]final_val[/code] for [code]duration[/code] seconds, [code]delay[/code] seconds later. Methods are animated by calling them with consecuitive values.
+ Animate [code]method[/code] of [code]object[/code] from [code]initial_val[/code] to [code]final_val[/code] for [code]duration[/code] seconds, [code]delay[/code] seconds later. Methods are animated by calling them with consecutive values.
[code]trans_type[/code] accepts TRANS_* constants, and is the way the animation is interpolated, while [code]ease_type[/code] accepts EASE_* constants, and controls the place of the interpolation (the beginning, the end, or both). You can read more about them in the class description.
</description>
</method>
@@ -296,7 +296,7 @@
<argument index="0" name="mode" type="int" enum="Tween.TweenProcessMode">
</argument>
<description>
- Set whether the Tween uses [code]_process[/code] or [code]_fixed_process[/code] (accepts TWEEN_PROCESS_IDLE and TWEEN_PROCESS_FIXED constants, respectively).
+ Set whether the Tween uses [code]_process[/code] or [code]_physics_process[/code] (accepts TWEEN_PROCESS_IDLE and TWEEN_PROCESS_PHYSICS constants, respectively).
</description>
</method>
<method name="start">
@@ -346,7 +346,7 @@
<argument index="8" name="delay" type="float" default="0">
</argument>
<description>
- Animate [code]method[/code] of [code]object[/code] from the value returned by [code]initial.initial_method[/code] to [code]final_val[/code] for [code]duration[/code] seconds, [code]delay[/code] seconds later. Methods are animated by calling them with consecuitive values.
+ Animate [code]method[/code] of [code]object[/code] from the value returned by [code]initial.initial_method[/code] to [code]final_val[/code] for [code]duration[/code] seconds, [code]delay[/code] seconds later. Methods are animated by calling them with consecutive values.
[code]trans_type[/code] accepts TRANS_* constants, and is the way the animation is interpolated, while [code]ease_type[/code] accepts EASE_* constants, and controls the place of the interpolation (the beginning, the end, or both). You can read more about them in the class description.
</description>
</method>
@@ -422,11 +422,11 @@
</signal>
</signals>
<constants>
- <constant name="TWEEN_PROCESS_FIXED" value="0">
- The [Tween] should use [code]_fixed_process[/code] for timekeeping when this is enabled.
+ <constant name="TWEEN_PROCESS_PHYSICS" value="0">
+ The [code]Tween[/code] should use [code]_physics_process[/code] for timekeeping when this is enabled.
</constant>
<constant name="TWEEN_PROCESS_IDLE" value="1">
- The [Tween] should use [code]_process[/code] for timekeeping when this is enabled (default).
+ The [code]Tween[/code] should use [code]_process[/code] for timekeeping when this is enabled (default).
</constant>
<constant name="TRANS_LINEAR" value="0">
Means that the animation is interpolated linearly.
diff --git a/doc/classes/UndoRedo.xml b/doc/classes/UndoRedo.xml
index d450a8812e..718522aa57 100644
--- a/doc/classes/UndoRedo.xml
+++ b/doc/classes/UndoRedo.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="UndoRedo" inherits="Object" category="Core" version="3.0.alpha.custom_build">
+<class name="UndoRedo" inherits="Object" category="Core" version="3.0-alpha">
<brief_description>
Helper to manage UndoRedo in the editor or custom tools.
</brief_description>
diff --git a/doc/classes/VBoxContainer.xml b/doc/classes/VBoxContainer.xml
index de544ed031..b64b04437a 100644
--- a/doc/classes/VBoxContainer.xml
+++ b/doc/classes/VBoxContainer.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VBoxContainer" inherits="BoxContainer" category="Core" version="3.0.alpha.custom_build">
+<class name="VBoxContainer" inherits="BoxContainer" category="Core" version="3.0-alpha">
<brief_description>
Vertical box container.
</brief_description>
diff --git a/doc/classes/VScrollBar.xml b/doc/classes/VScrollBar.xml
index 4510ac1e2e..5e5ed6f211 100644
--- a/doc/classes/VScrollBar.xml
+++ b/doc/classes/VScrollBar.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VScrollBar" inherits="ScrollBar" category="Core" version="3.0.alpha.custom_build">
+<class name="VScrollBar" inherits="ScrollBar" category="Core" version="3.0-alpha">
<brief_description>
Vertical version of [ScrollBar], which goes from left (min) to right (max).
</brief_description>
diff --git a/doc/classes/VSeparator.xml b/doc/classes/VSeparator.xml
index f98473a148..88c043f9ca 100644
--- a/doc/classes/VSeparator.xml
+++ b/doc/classes/VSeparator.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VSeparator" inherits="Separator" category="Core" version="3.0.alpha.custom_build">
+<class name="VSeparator" inherits="Separator" category="Core" version="3.0-alpha">
<brief_description>
Vertical version of [Separator].
</brief_description>
diff --git a/doc/classes/VSlider.xml b/doc/classes/VSlider.xml
index e4ba4a19c5..bc0a3a25b6 100644
--- a/doc/classes/VSlider.xml
+++ b/doc/classes/VSlider.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VSlider" inherits="Slider" category="Core" version="3.0.alpha.custom_build">
+<class name="VSlider" inherits="Slider" category="Core" version="3.0-alpha">
<brief_description>
Vertical slider.
</brief_description>
@@ -19,6 +19,8 @@
</theme_item>
<theme_item name="grabber" type="Texture">
</theme_item>
+ <theme_item name="grabber_area" type="StyleBox">
+ </theme_item>
<theme_item name="grabber_disabled" type="Texture">
</theme_item>
<theme_item name="grabber_disabled" type="StyleBox">
diff --git a/doc/classes/VSplitContainer.xml b/doc/classes/VSplitContainer.xml
index aac10841c3..e5a8981aaf 100644
--- a/doc/classes/VSplitContainer.xml
+++ b/doc/classes/VSplitContainer.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VSplitContainer" inherits="SplitContainer" category="Core" version="3.0.alpha.custom_build">
+<class name="VSplitContainer" inherits="SplitContainer" category="Core" version="3.0-alpha">
<brief_description>
Vertical split container.
</brief_description>
diff --git a/doc/classes/Variant.xml b/doc/classes/Variant.xml
index 914ef10036..14df6f050f 100644
--- a/doc/classes/Variant.xml
+++ b/doc/classes/Variant.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Variant" category="Core" version="3.0.alpha.custom_build">
+<class name="Variant" category="Core" version="3.0-alpha">
<brief_description>
The most important data type in Godot.
</brief_description>
diff --git a/doc/classes/Vector2.xml b/doc/classes/Vector2.xml
index 510559327f..3afad1d6fa 100644
--- a/doc/classes/Vector2.xml
+++ b/doc/classes/Vector2.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Vector2" category="Built-In Types" version="3.0.alpha.custom_build">
+<class name="Vector2" category="Built-In Types" version="3.0-alpha">
<brief_description>
Vector used for 2D Math.
</brief_description>
diff --git a/doc/classes/Vector3.xml b/doc/classes/Vector3.xml
index fdbdabafd3..cec5970f06 100644
--- a/doc/classes/Vector3.xml
+++ b/doc/classes/Vector3.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Vector3" category="Built-In Types" version="3.0.alpha.custom_build">
+<class name="Vector3" category="Built-In Types" version="3.0-alpha">
<brief_description>
Vector class, which performs basic 3D vector math operations.
</brief_description>
@@ -37,6 +37,7 @@
<argument index="0" name="to" type="Vector3">
</argument>
<description>
+ Returns the vector's minimum angle to the vector [code]to[/code].
</description>
</method>
<method name="bounce">
@@ -61,7 +62,7 @@
<argument index="0" name="b" type="Vector3">
</argument>
<description>
- Return the cross product with b.
+ Returns the cross product with [code]b[/code].
</description>
</method>
<method name="cubic_interpolate">
@@ -76,7 +77,7 @@
<argument index="3" name="t" type="float">
</argument>
<description>
- Perform a cubic interpolation between vectors pre_a, a, b, post_b (a is current), by the given amount (t).
+ Performs a cubic interpolation between vectors [code]pre_a[/code], [code]a[/code], [code]b[/code], [code]post_b[/code] ([code]a[/code] is current), by the given amount (t).
</description>
</method>
<method name="distance_squared_to">
@@ -85,7 +86,7 @@
<argument index="0" name="b" type="Vector3">
</argument>
<description>
- Return the squared distance (distance minus the last square root) to b. Prefer this function over distance_to if you need to sort vectors or need the squared distance for some formula.
+ Returns the squared distance to [code]b[/code]. Prefer this function over distance_to if you need to sort vectors or need the squared distance for some formula.
</description>
</method>
<method name="distance_to">
@@ -94,7 +95,7 @@
<argument index="0" name="b" type="Vector3">
</argument>
<description>
- Return the distance to b.
+ Returns the distance to b.
</description>
</method>
<method name="dot">
@@ -103,7 +104,7 @@
<argument index="0" name="b" type="Vector3">
</argument>
<description>
- Return the dot product with b.
+ Returns the dot product with b.
</description>
</method>
<method name="floor">
@@ -131,14 +132,14 @@
<return type="float">
</return>
<description>
- Return the length of the vector.
+ Returns the length of the vector.
</description>
</method>
<method name="length_squared">
<return type="float">
</return>
<description>
- Return the length of the vector, squared. Prefer this function over "length" if you need to sort vectors or need the squared length for some formula.
+ Returns the length of the vector, squared. Prefer this function over "length" if you need to sort vectors or need the squared length for some formula.
</description>
</method>
<method name="linear_interpolate">
@@ -170,7 +171,7 @@
<return type="Vector3">
</return>
<description>
- Return a copy of the normalized vector to unit length. This is the same as v / v.length().
+ Returns a copy of the normalized vector to unit length. This is the same as v / v.length().
</description>
</method>
<method name="outer">
@@ -179,7 +180,7 @@
<argument index="0" name="b" type="Vector3">
</argument>
<description>
- Return the outer product with b.
+ Returns the outer product with b.
</description>
</method>
<method name="reflect">
@@ -217,14 +218,14 @@
<argument index="0" name="by" type="float">
</argument>
<description>
- Return a copy of the vector, snapped to the lowest neared multiple.
+ Returns a copy of the vector, snapped to the lowest neared multiple.
</description>
</method>
<method name="to_diagonal_matrix">
<return type="Basis">
</return>
<description>
- Return a diagonal matrix with the vector as main diagonal.
+ Returns a diagonal matrix with the vector as main diagonal.
</description>
</method>
</methods>
diff --git a/doc/classes/VehicleBody.xml b/doc/classes/VehicleBody.xml
index 48202665fb..f9f3590385 100644
--- a/doc/classes/VehicleBody.xml
+++ b/doc/classes/VehicleBody.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VehicleBody" inherits="PhysicsBody" category="Core" version="3.0.alpha.custom_build">
+<class name="VehicleBody" inherits="PhysicsBody" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/VehicleWheel.xml b/doc/classes/VehicleWheel.xml
index 82e93e0f01..f04c33cc5a 100644
--- a/doc/classes/VehicleWheel.xml
+++ b/doc/classes/VehicleWheel.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VehicleWheel" inherits="Spatial" category="Core" version="3.0.alpha.custom_build">
+<class name="VehicleWheel" inherits="Spatial" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
@@ -39,6 +39,12 @@
<description>
</description>
</method>
+ <method name="get_skidinfo" qualifiers="const">
+ <return type="float">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="get_suspension_max_force" qualifiers="const">
<return type="float">
</return>
diff --git a/doc/classes/VideoPlayer.xml b/doc/classes/VideoPlayer.xml
index bac7d1e3b0..340b162727 100644
--- a/doc/classes/VideoPlayer.xml
+++ b/doc/classes/VideoPlayer.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VideoPlayer" inherits="Control" category="Core" version="3.0.alpha.custom_build">
+<class name="VideoPlayer" inherits="Control" category="Core" version="3.0-alpha">
<brief_description>
Control to play video files.
</brief_description>
@@ -22,7 +22,13 @@
<return type="int">
</return>
<description>
- Get the amount of miliseconds to store in buffer while playing.
+ Get the amount of milliseconds to store in buffer while playing.
+ </description>
+ </method>
+ <method name="get_bus" qualifiers="const">
+ <return type="String">
+ </return>
+ <description>
</description>
</method>
<method name="get_stream" qualifiers="const">
@@ -126,7 +132,15 @@
<argument index="0" name="msec" type="int">
</argument>
<description>
- Set the amount of miliseconds to buffer during playback.
+ Set the amount of milliseconds to buffer during playback.
+ </description>
+ </method>
+ <method name="set_bus">
+ <return type="void">
+ </return>
+ <argument index="0" name="bus" type="String">
+ </argument>
+ <description>
</description>
</method>
<method name="set_expand">
@@ -196,6 +210,8 @@
</member>
<member name="autoplay" type="bool" setter="set_autoplay" getter="has_autoplay">
</member>
+ <member name="bus" type="String" setter="set_bus" getter="get_bus">
+ </member>
<member name="expand" type="bool" setter="set_expand" getter="has_expand">
</member>
<member name="paused" type="bool" setter="set_paused" getter="is_paused">
diff --git a/doc/classes/VideoStream.xml b/doc/classes/VideoStream.xml
index c282cdfbd0..00607b0f0a 100644
--- a/doc/classes/VideoStream.xml
+++ b/doc/classes/VideoStream.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VideoStream" inherits="Resource" category="Core" version="3.0.alpha.custom_build">
+<class name="VideoStream" inherits="Resource" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/Viewport.xml b/doc/classes/Viewport.xml
index 2cf36ba69b..9bd229ef26 100644
--- a/doc/classes/Viewport.xml
+++ b/doc/classes/Viewport.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Viewport" inherits="Node" category="Core" version="3.0.alpha.custom_build">
+<class name="Viewport" inherits="Node" category="Core" version="3.0-alpha">
<brief_description>
Creates a sub-view into the screen.
</brief_description>
@@ -192,14 +192,14 @@
<return type="Variant">
</return>
<description>
- Returs the drag data from the GUI, that was previously returned by [method Control.get_drag_data].
+ Returns the drag data from the GUI, that was previously returned by [method Control.get_drag_data].
</description>
</method>
<method name="gui_has_modal_stack" qualifiers="const">
<return type="bool">
</return>
<description>
- Returs whether there are shown modals on-screen.
+ Returns whether there are shown modals on-screen.
</description>
</method>
<method name="has_transparent_background" qualifiers="const">
@@ -303,7 +303,7 @@
<argument index="0" name="xform" type="Transform2D">
</argument>
<description>
- Set the canvas transform of the viewport, useful for changing the on-screen positions of all child [CanvasItem]\ s. This is relative to the global canvas transform of the viewport.
+ Set the canvas transform of the viewport, useful for changing the on-screen positions of all child [CanvasItem]s. This is relative to the global canvas transform of the viewport.
</description>
</method>
<method name="set_clear_mode">
diff --git a/doc/classes/ViewportContainer.xml b/doc/classes/ViewportContainer.xml
index d4d42ad4fb..5a4c3af1f6 100644
--- a/doc/classes/ViewportContainer.xml
+++ b/doc/classes/ViewportContainer.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ViewportContainer" inherits="Container" category="Core" version="3.0.alpha.custom_build">
+<class name="ViewportContainer" inherits="Container" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
@@ -9,6 +9,12 @@
<demos>
</demos>
<methods>
+ <method name="get_stretch_shrink" qualifiers="const">
+ <return type="int">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="is_stretch_enabled" qualifiers="const">
<return type="bool">
</return>
@@ -23,10 +29,20 @@
<description>
</description>
</method>
+ <method name="set_stretch_shrink">
+ <return type="void">
+ </return>
+ <argument index="0" name="amount" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
</methods>
<members>
<member name="stretch" type="bool" setter="set_stretch" getter="is_stretch_enabled">
</member>
+ <member name="stretch_shrink" type="int" setter="set_stretch_shrink" getter="get_stretch_shrink">
+ </member>
</members>
<constants>
</constants>
diff --git a/doc/classes/ViewportTexture.xml b/doc/classes/ViewportTexture.xml
index f2515cbcc7..1eace840a8 100644
--- a/doc/classes/ViewportTexture.xml
+++ b/doc/classes/ViewportTexture.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ViewportTexture" inherits="Texture" category="Core" version="3.0.alpha.custom_build">
+<class name="ViewportTexture" inherits="Texture" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/VisibilityEnabler.xml b/doc/classes/VisibilityEnabler.xml
index ebe646679a..95bcbd6816 100644
--- a/doc/classes/VisibilityEnabler.xml
+++ b/doc/classes/VisibilityEnabler.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisibilityEnabler" inherits="VisibilityNotifier" category="Core" version="3.0.alpha.custom_build">
+<class name="VisibilityEnabler" inherits="VisibilityNotifier" category="Core" version="3.0-alpha">
<brief_description>
Enable certain nodes only when visible.
</brief_description>
@@ -39,12 +39,12 @@
</member>
</members>
<constants>
- <constant name="ENABLER_FREEZE_BODIES" value="1">
- This enabler will freeze [RigidBody] nodes.
- </constant>
<constant name="ENABLER_PAUSE_ANIMATIONS" value="0">
This enabler will pause [AnimationPlayer] nodes.
</constant>
+ <constant name="ENABLER_FREEZE_BODIES" value="1">
+ This enabler will freeze [RigidBody] nodes.
+ </constant>
<constant name="ENABLER_MAX" value="2">
</constant>
</constants>
diff --git a/doc/classes/VisibilityEnabler2D.xml b/doc/classes/VisibilityEnabler2D.xml
index b8ef1f8d22..f23d54a544 100644
--- a/doc/classes/VisibilityEnabler2D.xml
+++ b/doc/classes/VisibilityEnabler2D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisibilityEnabler2D" inherits="VisibilityNotifier2D" category="Core" version="3.0.alpha.custom_build">
+<class name="VisibilityEnabler2D" inherits="VisibilityNotifier2D" category="Core" version="3.0-alpha">
<brief_description>
Enable certain nodes only when visible.
</brief_description>
@@ -33,8 +33,6 @@
</method>
</methods>
<members>
- <member name="fixed_process_parent" type="bool" setter="set_enabler" getter="is_enabler_enabled">
- </member>
<member name="freeze_bodies" type="bool" setter="set_enabler" getter="is_enabler_enabled">
</member>
<member name="pause_animated_sprites" type="bool" setter="set_enabler" getter="is_enabler_enabled">
@@ -43,26 +41,28 @@
</member>
<member name="pause_particles" type="bool" setter="set_enabler" getter="is_enabler_enabled">
</member>
+ <member name="physics_process_parent" type="bool" setter="set_enabler" getter="is_enabler_enabled">
+ </member>
<member name="process_parent" type="bool" setter="set_enabler" getter="is_enabler_enabled">
</member>
</members>
<constants>
- <constant name="ENABLER_FREEZE_BODIES" value="1">
- This enabler will freeze [RigidBody2D] nodes.
- </constant>
<constant name="ENABLER_PAUSE_ANIMATIONS" value="0">
This enabler will pause [AnimationPlayer] nodes.
</constant>
+ <constant name="ENABLER_FREEZE_BODIES" value="1">
+ This enabler will freeze [RigidBody2D] nodes.
+ </constant>
<constant name="ENABLER_PAUSE_PARTICLES" value="2">
This enabler will stop [Particles2D] nodes.
</constant>
- <constant name="ENABLER_PAUSE_ANIMATED_SPRITES" value="5">
- </constant>
<constant name="ENABLER_PARENT_PROCESS" value="3">
This enabler will stop the parent's _process function.
</constant>
- <constant name="ENABLER_PARENT_FIXED_PROCESS" value="4">
- This enabler will stop the parent's _fixed_process function.
+ <constant name="ENABLER_PARENT_PHYSICS_PROCESS" value="4">
+ This enabler will stop the parent's _physics_process function.
+ </constant>
+ <constant name="ENABLER_PAUSE_ANIMATED_SPRITES" value="5">
</constant>
<constant name="ENABLER_MAX" value="6">
</constant>
diff --git a/doc/classes/VisibilityNotifier.xml b/doc/classes/VisibilityNotifier.xml
index 816523fc27..90f1974697 100644
--- a/doc/classes/VisibilityNotifier.xml
+++ b/doc/classes/VisibilityNotifier.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisibilityNotifier" inherits="Spatial" category="Core" version="3.0.alpha.custom_build">
+<class name="VisibilityNotifier" inherits="Spatial" category="Core" version="3.0-alpha">
<brief_description>
Detects when the node is visible on screen.
</brief_description>
@@ -12,7 +12,7 @@
</demos>
<methods>
<method name="get_aabb" qualifiers="const">
- <return type="Rect3">
+ <return type="AABB">
</return>
<description>
Returns the bounding box of the VisibilityNotifier.
@@ -28,7 +28,7 @@
<method name="set_aabb">
<return type="void">
</return>
- <argument index="0" name="rect" type="Rect3">
+ <argument index="0" name="rect" type="AABB">
</argument>
<description>
Set the visibility bounding box of the VisibilityNotifier.
@@ -36,7 +36,7 @@
</method>
</methods>
<members>
- <member name="aabb" type="Rect3" setter="set_aabb" getter="get_aabb">
+ <member name="aabb" type="AABB" setter="set_aabb" getter="get_aabb">
The VisibilityNotifier's bounding box.
</member>
</members>
diff --git a/doc/classes/VisibilityNotifier2D.xml b/doc/classes/VisibilityNotifier2D.xml
index 86227a0277..b8db14e583 100644
--- a/doc/classes/VisibilityNotifier2D.xml
+++ b/doc/classes/VisibilityNotifier2D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisibilityNotifier2D" inherits="Node2D" category="Core" version="3.0.alpha.custom_build">
+<class name="VisibilityNotifier2D" inherits="Node2D" category="Core" version="3.0-alpha">
<brief_description>
Detects when the node is visible on screen.
</brief_description>
diff --git a/doc/classes/VisualInstance.xml b/doc/classes/VisualInstance.xml
index ed317882a8..7108eb13c5 100644
--- a/doc/classes/VisualInstance.xml
+++ b/doc/classes/VisualInstance.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualInstance" inherits="Spatial" category="Core" version="3.0.alpha.custom_build">
+<class name="VisualInstance" inherits="Spatial" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
@@ -10,7 +10,7 @@
</demos>
<methods>
<method name="get_aabb" qualifiers="const">
- <return type="Rect3">
+ <return type="AABB">
</return>
<description>
</description>
@@ -22,7 +22,7 @@
</description>
</method>
<method name="get_transformed_aabb" qualifiers="const">
- <return type="Rect3">
+ <return type="AABB">
</return>
<description>
</description>
diff --git a/doc/classes/VisualScriptCondition.xml b/doc/classes/VisualScriptCondition.xml
deleted file mode 100644
index de814a6b17..0000000000
--- a/doc/classes/VisualScriptCondition.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptCondition" inherits="VisualScriptNode" category="Core" version="3.0.alpha.custom_build">
- <brief_description>
- A Visual Script node which branches the flow.
- </brief_description>
- <description>
- A Visual Script node which switches the flow based on a boolean. It acts similar to if/else in typical programming languages.
- </description>
- <tutorials>
- </tutorials>
- <demos>
- </demos>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
diff --git a/doc/classes/VisualScriptIterator.xml b/doc/classes/VisualScriptIterator.xml
deleted file mode 100644
index 74309fcf00..0000000000
--- a/doc/classes/VisualScriptIterator.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptIterator" inherits="VisualScriptNode" category="Core" version="3.0.alpha.custom_build">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <tutorials>
- </tutorials>
- <demos>
- </demos>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
diff --git a/doc/classes/VisualServer.xml b/doc/classes/VisualServer.xml
index 242fc18ab9..d716d99e5d 100644
--- a/doc/classes/VisualServer.xml
+++ b/doc/classes/VisualServer.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualServer" inherits="Object" category="Core" version="3.0.alpha.custom_build">
+<class name="VisualServer" inherits="Object" category="Core" version="3.0-alpha">
<brief_description>
Server for anything visible.
</brief_description>
@@ -12,12 +12,1342 @@
<demos>
</demos>
<methods>
+ <method name="black_bars_set_images">
+ <return type="void">
+ </return>
+ <argument index="0" name="left" type="RID">
+ </argument>
+ <argument index="1" name="top" type="RID">
+ </argument>
+ <argument index="2" name="right" type="RID">
+ </argument>
+ <argument index="3" name="bottom" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="black_bars_set_margins">
+ <return type="void">
+ </return>
+ <argument index="0" name="left" type="int">
+ </argument>
+ <argument index="1" name="top" type="int">
+ </argument>
+ <argument index="2" name="right" type="int">
+ </argument>
+ <argument index="3" name="bottom" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_create">
+ <return type="RID">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_add_circle">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="pos" type="Vector2">
+ </argument>
+ <argument index="2" name="radius" type="float">
+ </argument>
+ <argument index="3" name="color" type="Color">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_add_clip_ignore">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="ignore" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_add_line">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="from" type="Vector2">
+ </argument>
+ <argument index="2" name="to" type="Vector2">
+ </argument>
+ <argument index="3" name="color" type="Color">
+ </argument>
+ <argument index="4" name="width" type="float" default="1.0">
+ </argument>
+ <argument index="5" name="antialiased" type="bool" default="false">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_add_mesh">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="mesh" type="RID">
+ </argument>
+ <argument index="2" name="skeleton" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_add_multimesh">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="mesh" type="RID">
+ </argument>
+ <argument index="2" name="skeleton" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_add_nine_patch">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="rect" type="Rect2">
+ </argument>
+ <argument index="2" name="source" type="Rect2">
+ </argument>
+ <argument index="3" name="texture" type="RID">
+ </argument>
+ <argument index="4" name="topleft" type="Vector2">
+ </argument>
+ <argument index="5" name="bottomright" type="Vector2">
+ </argument>
+ <argument index="6" name="x_axis_mode" type="int" enum="VisualServer.NinePatchAxisMode" default="0">
+ </argument>
+ <argument index="7" name="y_axis_mode" type="int" enum="VisualServer.NinePatchAxisMode" default="0">
+ </argument>
+ <argument index="8" name="draw_center" type="bool" default="true">
+ </argument>
+ <argument index="9" name="modulate" type="Color" default="Color( 1, 1, 1, 1 )">
+ </argument>
+ <argument index="10" name="normal_map" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_add_particles">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="particles" type="RID">
+ </argument>
+ <argument index="2" name="texture" type="RID">
+ </argument>
+ <argument index="3" name="normal_map" type="RID">
+ </argument>
+ <argument index="4" name="h_frames" type="int">
+ </argument>
+ <argument index="5" name="v_frames" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_add_polygon">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="points" type="PoolVector2Array">
+ </argument>
+ <argument index="2" name="colors" type="PoolColorArray">
+ </argument>
+ <argument index="3" name="uvs" type="PoolVector2Array" default="PoolVector2Array( )">
+ </argument>
+ <argument index="4" name="texture" type="RID">
+ </argument>
+ <argument index="5" name="normal_map" type="RID">
+ </argument>
+ <argument index="6" name="antialiased" type="bool" default="false">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_add_polyline">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="points" type="PoolVector2Array">
+ </argument>
+ <argument index="2" name="colors" type="PoolColorArray">
+ </argument>
+ <argument index="3" name="width" type="float" default="1.0">
+ </argument>
+ <argument index="4" name="antialiased" type="bool" default="false">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_add_primitive">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="points" type="PoolVector2Array">
+ </argument>
+ <argument index="2" name="colors" type="PoolColorArray">
+ </argument>
+ <argument index="3" name="uvs" type="PoolVector2Array">
+ </argument>
+ <argument index="4" name="texture" type="RID">
+ </argument>
+ <argument index="5" name="width" type="float" default="1.0">
+ </argument>
+ <argument index="6" name="normal_map" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_add_rect">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="rect" type="Rect2">
+ </argument>
+ <argument index="2" name="color" type="Color">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_add_set_transform">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="transform" type="Transform2D">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_add_texture_rect">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="rect" type="Rect2">
+ </argument>
+ <argument index="2" name="texture" type="RID">
+ </argument>
+ <argument index="3" name="tile" type="bool" default="false">
+ </argument>
+ <argument index="4" name="modulate" type="Color" default="Color( 1, 1, 1, 1 )">
+ </argument>
+ <argument index="5" name="transpose" type="bool" default="false">
+ </argument>
+ <argument index="6" name="normal_map" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_add_texture_rect_region">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="rect" type="Rect2">
+ </argument>
+ <argument index="2" name="texture" type="RID">
+ </argument>
+ <argument index="3" name="src_rect" type="Rect2">
+ </argument>
+ <argument index="4" name="modulate" type="Color" default="Color( 1, 1, 1, 1 )">
+ </argument>
+ <argument index="5" name="transpose" type="bool" default="false">
+ </argument>
+ <argument index="6" name="normal_map" type="RID">
+ </argument>
+ <argument index="7" name="clip_uv" type="bool" default="true">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_add_triangle_array">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="indices" type="PoolIntArray">
+ </argument>
+ <argument index="2" name="points" type="PoolVector2Array">
+ </argument>
+ <argument index="3" name="colors" type="PoolColorArray">
+ </argument>
+ <argument index="4" name="uvs" type="PoolVector2Array" default="PoolVector2Array( )">
+ </argument>
+ <argument index="5" name="texture" type="RID">
+ </argument>
+ <argument index="6" name="count" type="int" default="-1">
+ </argument>
+ <argument index="7" name="normal_map" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_clear">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_create">
+ <return type="RID">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_set_clip">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="clip" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_set_copy_to_backbuffer">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="enabled" type="bool">
+ </argument>
+ <argument index="2" name="rect" type="Rect2">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_set_custom_rect">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="use_custom_rect" type="bool">
+ </argument>
+ <argument index="2" name="rect" type="Rect2" default="Rect2( 0, 0, 0, 0 )">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_set_distance_field_mode">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="enabled" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_set_draw_behind_parent">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="enabled" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_set_draw_index">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="index" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_set_light_mask">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="mask" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_set_material">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="material" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_set_modulate">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="color" type="Color">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_set_parent">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="parent" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_set_self_modulate">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="color" type="Color">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_set_sort_children_by_y">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="enabled" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_set_transform">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="transform" type="Transform2D">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_set_use_parent_material">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="enabled" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_set_visible">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="visible" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_set_z">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="z" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_item_set_z_as_relative_to_parent">
+ <return type="void">
+ </return>
+ <argument index="0" name="item" type="RID">
+ </argument>
+ <argument index="1" name="enabled" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_light_attach_to_canvas">
+ <return type="void">
+ </return>
+ <argument index="0" name="light" type="RID">
+ </argument>
+ <argument index="1" name="canvas" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_light_create">
+ <return type="RID">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_light_occluder_attach_to_canvas">
+ <return type="void">
+ </return>
+ <argument index="0" name="occluder" type="RID">
+ </argument>
+ <argument index="1" name="canvas" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_light_occluder_create">
+ <return type="RID">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_light_occluder_set_enabled">
+ <return type="void">
+ </return>
+ <argument index="0" name="occluder" type="RID">
+ </argument>
+ <argument index="1" name="enabled" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_light_occluder_set_light_mask">
+ <return type="void">
+ </return>
+ <argument index="0" name="occluder" type="RID">
+ </argument>
+ <argument index="1" name="mask" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_light_occluder_set_polygon">
+ <return type="void">
+ </return>
+ <argument index="0" name="occluder" type="RID">
+ </argument>
+ <argument index="1" name="polygon" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_light_occluder_set_transform">
+ <return type="void">
+ </return>
+ <argument index="0" name="occluder" type="RID">
+ </argument>
+ <argument index="1" name="transform" type="Transform2D">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_light_set_color">
+ <return type="void">
+ </return>
+ <argument index="0" name="light" type="RID">
+ </argument>
+ <argument index="1" name="color" type="Color">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_light_set_enabled">
+ <return type="void">
+ </return>
+ <argument index="0" name="light" type="RID">
+ </argument>
+ <argument index="1" name="enabled" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_light_set_energy">
+ <return type="void">
+ </return>
+ <argument index="0" name="light" type="RID">
+ </argument>
+ <argument index="1" name="energy" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_light_set_height">
+ <return type="void">
+ </return>
+ <argument index="0" name="light" type="RID">
+ </argument>
+ <argument index="1" name="height" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_light_set_item_cull_mask">
+ <return type="void">
+ </return>
+ <argument index="0" name="light" type="RID">
+ </argument>
+ <argument index="1" name="mask" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_light_set_item_shadow_cull_mask">
+ <return type="void">
+ </return>
+ <argument index="0" name="light" type="RID">
+ </argument>
+ <argument index="1" name="mask" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_light_set_layer_range">
+ <return type="void">
+ </return>
+ <argument index="0" name="light" type="RID">
+ </argument>
+ <argument index="1" name="min_layer" type="int">
+ </argument>
+ <argument index="2" name="max_layer" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_light_set_mode">
+ <return type="void">
+ </return>
+ <argument index="0" name="light" type="RID">
+ </argument>
+ <argument index="1" name="mode" type="int" enum="VisualServer.CanvasLightMode">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_light_set_scale">
+ <return type="void">
+ </return>
+ <argument index="0" name="light" type="RID">
+ </argument>
+ <argument index="1" name="scale" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_light_set_shadow_buffer_size">
+ <return type="void">
+ </return>
+ <argument index="0" name="light" type="RID">
+ </argument>
+ <argument index="1" name="size" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_light_set_shadow_color">
+ <return type="void">
+ </return>
+ <argument index="0" name="light" type="RID">
+ </argument>
+ <argument index="1" name="color" type="Color">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_light_set_shadow_enabled">
+ <return type="void">
+ </return>
+ <argument index="0" name="light" type="RID">
+ </argument>
+ <argument index="1" name="enabled" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_light_set_shadow_filter">
+ <return type="void">
+ </return>
+ <argument index="0" name="light" type="RID">
+ </argument>
+ <argument index="1" name="filter" type="int" enum="VisualServer.CanvasLightShadowFilter">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_light_set_shadow_gradient_length">
+ <return type="void">
+ </return>
+ <argument index="0" name="light" type="RID">
+ </argument>
+ <argument index="1" name="length" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_light_set_shadow_smooth">
+ <return type="void">
+ </return>
+ <argument index="0" name="light" type="RID">
+ </argument>
+ <argument index="1" name="smooth" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_light_set_texture">
+ <return type="void">
+ </return>
+ <argument index="0" name="light" type="RID">
+ </argument>
+ <argument index="1" name="texture" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_light_set_texture_offset">
+ <return type="void">
+ </return>
+ <argument index="0" name="light" type="RID">
+ </argument>
+ <argument index="1" name="offset" type="Vector2">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_light_set_transform">
+ <return type="void">
+ </return>
+ <argument index="0" name="light" type="RID">
+ </argument>
+ <argument index="1" name="transform" type="Transform2D">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_light_set_z_range">
+ <return type="void">
+ </return>
+ <argument index="0" name="light" type="RID">
+ </argument>
+ <argument index="1" name="min_z" type="int">
+ </argument>
+ <argument index="2" name="max_z" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_occluder_polygon_create">
+ <return type="RID">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_occluder_polygon_set_cull_mode">
+ <return type="void">
+ </return>
+ <argument index="0" name="occluder_polygon" type="RID">
+ </argument>
+ <argument index="1" name="mode" type="int" enum="VisualServer.CanvasOccluderPolygonCullMode">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_occluder_polygon_set_shape">
+ <return type="void">
+ </return>
+ <argument index="0" name="occluder_polygon" type="RID">
+ </argument>
+ <argument index="1" name="shape" type="PoolVector2Array">
+ </argument>
+ <argument index="2" name="closed" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_occluder_polygon_set_shape_as_lines">
+ <return type="void">
+ </return>
+ <argument index="0" name="occluder_polygon" type="RID">
+ </argument>
+ <argument index="1" name="shape" type="PoolVector2Array">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_set_item_mirroring">
+ <return type="void">
+ </return>
+ <argument index="0" name="canvas" type="RID">
+ </argument>
+ <argument index="1" name="item" type="RID">
+ </argument>
+ <argument index="2" name="mirroring" type="Vector2">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="canvas_set_modulate">
+ <return type="void">
+ </return>
+ <argument index="0" name="canvas" type="RID">
+ </argument>
+ <argument index="1" name="color" type="Color">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="draw">
+ <return type="void">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="finish">
+ <return type="void">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="force_draw">
<return type="void">
</return>
<description>
</description>
</method>
+ <method name="force_sync">
+ <return type="void">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="free">
+ <return type="void">
+ </return>
+ <argument index="0" name="rid" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="get_render_info">
+ <return type="int">
+ </return>
+ <argument index="0" name="info" type="int" enum="VisualServer.RenderInfo">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="get_test_cube">
+ <return type="RID">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_test_texture">
+ <return type="RID">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_white_texture">
+ <return type="RID">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="has_changed" qualifiers="const">
+ <return type="bool">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="has_feature" qualifiers="const">
+ <return type="bool">
+ </return>
+ <argument index="0" name="feature" type="int" enum="VisualServer.Features">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="has_os_feature" qualifiers="const">
+ <return type="bool">
+ </return>
+ <argument index="0" name="feature" type="String">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="init">
+ <return type="void">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="make_sphere_mesh">
+ <return type="RID">
+ </return>
+ <argument index="0" name="latitudes" type="int">
+ </argument>
+ <argument index="1" name="longitudes" type="int">
+ </argument>
+ <argument index="2" name="radius" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="material_create">
+ <return type="RID">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="material_get_param" qualifiers="const">
+ <return type="Variant">
+ </return>
+ <argument index="0" name="material" type="RID">
+ </argument>
+ <argument index="1" name="parameter" type="String">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="material_get_shader" qualifiers="const">
+ <return type="RID">
+ </return>
+ <argument index="0" name="shader_material" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="material_set_line_width">
+ <return type="void">
+ </return>
+ <argument index="0" name="material" type="RID">
+ </argument>
+ <argument index="1" name="width" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="material_set_next_pass">
+ <return type="void">
+ </return>
+ <argument index="0" name="material" type="RID">
+ </argument>
+ <argument index="1" name="next_material" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="material_set_param">
+ <return type="void">
+ </return>
+ <argument index="0" name="material" type="RID">
+ </argument>
+ <argument index="1" name="parameter" type="String">
+ </argument>
+ <argument index="2" name="value" type="Variant">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="material_set_render_priority">
+ <return type="void">
+ </return>
+ <argument index="0" name="material" type="RID">
+ </argument>
+ <argument index="1" name="priority" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="material_set_shader">
+ <return type="void">
+ </return>
+ <argument index="0" name="shader_material" type="RID">
+ </argument>
+ <argument index="1" name="shader" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="mesh_add_surface_from_arrays">
+ <return type="void">
+ </return>
+ <argument index="0" name="mesh" type="RID">
+ </argument>
+ <argument index="1" name="primtive" type="int" enum="VisualServer.PrimitiveType">
+ </argument>
+ <argument index="2" name="arrays" type="Array">
+ </argument>
+ <argument index="3" name="blend_shapes" type="Array" default="[ ]">
+ </argument>
+ <argument index="4" name="compress_format" type="int" default="97792">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="mesh_clear">
+ <return type="void">
+ </return>
+ <argument index="0" name="mesh" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="mesh_create">
+ <return type="RID">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="mesh_get_blend_shape_count" qualifiers="const">
+ <return type="int">
+ </return>
+ <argument index="0" name="mesh" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="mesh_get_blend_shape_mode" qualifiers="const">
+ <return type="int" enum="VisualServer.BlendShapeMode">
+ </return>
+ <argument index="0" name="mesh" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="mesh_get_custom_aabb" qualifiers="const">
+ <return type="AABB">
+ </return>
+ <argument index="0" name="mesh" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="mesh_get_surface_count" qualifiers="const">
+ <return type="int">
+ </return>
+ <argument index="0" name="mesh" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="mesh_remove_surface">
+ <return type="void">
+ </return>
+ <argument index="0" name="mesh" type="RID">
+ </argument>
+ <argument index="1" name="index" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="mesh_set_blend_shape_count">
+ <return type="void">
+ </return>
+ <argument index="0" name="mesh" type="RID">
+ </argument>
+ <argument index="1" name="amount" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="mesh_set_blend_shape_mode">
+ <return type="void">
+ </return>
+ <argument index="0" name="mesh" type="RID">
+ </argument>
+ <argument index="1" name="mode" type="int" enum="VisualServer.BlendShapeMode">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="mesh_set_custom_aabb">
+ <return type="void">
+ </return>
+ <argument index="0" name="mesh" type="RID">
+ </argument>
+ <argument index="1" name="aabb" type="AABB">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="mesh_surface_get_aabb" qualifiers="const">
+ <return type="AABB">
+ </return>
+ <argument index="0" name="mesh" type="RID">
+ </argument>
+ <argument index="1" name="surface" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="mesh_surface_get_array" qualifiers="const">
+ <return type="PoolByteArray">
+ </return>
+ <argument index="0" name="mesh" type="RID">
+ </argument>
+ <argument index="1" name="surface" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="mesh_surface_get_array_index_len" qualifiers="const">
+ <return type="int">
+ </return>
+ <argument index="0" name="mesh" type="RID">
+ </argument>
+ <argument index="1" name="surface" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="mesh_surface_get_array_len" qualifiers="const">
+ <return type="int">
+ </return>
+ <argument index="0" name="mesh" type="RID">
+ </argument>
+ <argument index="1" name="surface" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="mesh_surface_get_arrays" qualifiers="const">
+ <return type="Array">
+ </return>
+ <argument index="0" name="mesh" type="RID">
+ </argument>
+ <argument index="1" name="surface" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="mesh_surface_get_blend_shape_arrays" qualifiers="const">
+ <return type="Array">
+ </return>
+ <argument index="0" name="mesh" type="RID">
+ </argument>
+ <argument index="1" name="surface" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="mesh_surface_get_format" qualifiers="const">
+ <return type="int">
+ </return>
+ <argument index="0" name="mesh" type="RID">
+ </argument>
+ <argument index="1" name="surface" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="mesh_surface_get_index_array" qualifiers="const">
+ <return type="PoolByteArray">
+ </return>
+ <argument index="0" name="mesh" type="RID">
+ </argument>
+ <argument index="1" name="surface" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="mesh_surface_get_material" qualifiers="const">
+ <return type="RID">
+ </return>
+ <argument index="0" name="mesh" type="RID">
+ </argument>
+ <argument index="1" name="surface" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="mesh_surface_get_primitive_type" qualifiers="const">
+ <return type="int" enum="VisualServer.PrimitiveType">
+ </return>
+ <argument index="0" name="mesh" type="RID">
+ </argument>
+ <argument index="1" name="surface" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="mesh_surface_get_skeleton_aabb" qualifiers="const">
+ <return type="Array">
+ </return>
+ <argument index="0" name="mesh" type="RID">
+ </argument>
+ <argument index="1" name="surface" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="mesh_surface_set_material">
+ <return type="void">
+ </return>
+ <argument index="0" name="mesh" type="RID">
+ </argument>
+ <argument index="1" name="surface" type="int">
+ </argument>
+ <argument index="2" name="material" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="request_frame_drawn_callback">
+ <return type="void">
+ </return>
+ <argument index="0" name="where" type="Object">
+ </argument>
+ <argument index="1" name="method" type="String">
+ </argument>
+ <argument index="2" name="userdata" type="Variant">
+ </argument>
+ <description>
+ Schedules a callback to the corresponding named 'method' on 'where' after a frame has been drawn.
+ The callback method must use only 1 argument which will be called with 'userdata'.
+ </description>
+ </method>
+ <method name="set_boot_image">
+ <return type="void">
+ </return>
+ <argument index="0" name="image" type="Image">
+ </argument>
+ <argument index="1" name="color" type="Color">
+ </argument>
+ <argument index="2" name="scale" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="set_debug_generate_wireframes">
+ <return type="void">
+ </return>
+ <argument index="0" name="generate" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="set_default_clear_color">
+ <return type="void">
+ </return>
+ <argument index="0" name="color" type="Color">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="shader_create">
+ <return type="RID">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="shader_get_code" qualifiers="const">
+ <return type="String">
+ </return>
+ <argument index="0" name="shader" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="shader_get_default_texture_param" qualifiers="const">
+ <return type="RID">
+ </return>
+ <argument index="0" name="shader" type="RID">
+ </argument>
+ <argument index="1" name="name" type="String">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="shader_get_param_list" qualifiers="const">
+ <return type="Array">
+ </return>
+ <argument index="0" name="shader" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="shader_set_code">
+ <return type="void">
+ </return>
+ <argument index="0" name="shader" type="RID">
+ </argument>
+ <argument index="1" name="code" type="String">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="shader_set_default_texture_param">
+ <return type="void">
+ </return>
+ <argument index="0" name="shader" type="RID">
+ </argument>
+ <argument index="1" name="name" type="String">
+ </argument>
+ <argument index="2" name="texture" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="sky_create">
+ <return type="RID">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="sky_set_texture">
+ <return type="void">
+ </return>
+ <argument index="0" name="sky" type="RID">
+ </argument>
+ <argument index="1" name="cube_map" type="RID">
+ </argument>
+ <argument index="2" name="radiance_size" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="sync">
+ <return type="void">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="texture_allocate">
+ <return type="void">
+ </return>
+ <argument index="0" name="texture" type="RID">
+ </argument>
+ <argument index="1" name="width" type="int">
+ </argument>
+ <argument index="2" name="height" type="int">
+ </argument>
+ <argument index="3" name="format" type="int" enum="Image.Format">
+ </argument>
+ <argument index="4" name="flags" type="int" default="7">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="texture_create">
<return type="RID">
</return>
@@ -34,6 +1364,22 @@
<description>
</description>
</method>
+ <method name="texture_debug_usage">
+ <return type="Array">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="texture_get_data" qualifiers="const">
+ <return type="Image">
+ </return>
+ <argument index="0" name="texture" type="RID">
+ </argument>
+ <argument index="1" name="cube_side" type="int" enum="VisualServer.CubeMapSide" default="0">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="texture_get_flags" qualifiers="const">
<return type="int">
</return>
@@ -42,6 +1388,14 @@
<description>
</description>
</method>
+ <method name="texture_get_format" qualifiers="const">
+ <return type="int" enum="Image.Format">
+ </return>
+ <argument index="0" name="texture" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="texture_get_height" qualifiers="const">
<return type="int">
</return>
@@ -50,6 +1404,22 @@
<description>
</description>
</method>
+ <method name="texture_get_path" qualifiers="const">
+ <return type="String">
+ </return>
+ <argument index="0" name="texture" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="texture_get_texid" qualifiers="const">
+ <return type="int">
+ </return>
+ <argument index="0" name="texture" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="texture_get_width" qualifiers="const">
<return type="int">
</return>
@@ -58,6 +1428,18 @@
<description>
</description>
</method>
+ <method name="texture_set_data">
+ <return type="void">
+ </return>
+ <argument index="0" name="texture" type="RID">
+ </argument>
+ <argument index="1" name="image" type="Image">
+ </argument>
+ <argument index="2" name="cube_side" type="int" enum="VisualServer.CubeMapSide" default="0">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="texture_set_flags">
<return type="void">
</return>
@@ -68,6 +1450,16 @@
<description>
</description>
</method>
+ <method name="texture_set_path">
+ <return type="void">
+ </return>
+ <argument index="0" name="texture" type="RID">
+ </argument>
+ <argument index="1" name="path" type="String">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="texture_set_shrink_all_x2_on_set_data">
<return type="void">
</return>
@@ -76,7 +1468,645 @@
<description>
</description>
</method>
+ <method name="texture_set_size_override">
+ <return type="void">
+ </return>
+ <argument index="0" name="texture" type="RID">
+ </argument>
+ <argument index="1" name="width" type="int">
+ </argument>
+ <argument index="2" name="height" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="textures_keep_original">
+ <return type="void">
+ </return>
+ <argument index="0" name="enable" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="viewport_attach_camera">
+ <return type="void">
+ </return>
+ <argument index="0" name="viewport" type="RID">
+ </argument>
+ <argument index="1" name="camera" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="viewport_attach_canvas">
+ <return type="void">
+ </return>
+ <argument index="0" name="viewport" type="RID">
+ </argument>
+ <argument index="1" name="canvas" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="viewport_attach_to_screen">
+ <return type="void">
+ </return>
+ <argument index="0" name="viewport" type="RID">
+ </argument>
+ <argument index="1" name="rect" type="Rect2" default="Rect2( 0, 0, 0, 0 )">
+ </argument>
+ <argument index="2" name="screen" type="int" default="0">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="viewport_create">
+ <return type="RID">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="viewport_detach">
+ <return type="void">
+ </return>
+ <argument index="0" name="viewport" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="viewport_get_render_info">
+ <return type="int">
+ </return>
+ <argument index="0" name="viewport" type="RID">
+ </argument>
+ <argument index="1" name="info" type="int" enum="VisualServer.ViewportRenderInfo">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="viewport_get_texture" qualifiers="const">
+ <return type="RID">
+ </return>
+ <argument index="0" name="viewport" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="viewport_remove_canvas">
+ <return type="void">
+ </return>
+ <argument index="0" name="viewport" type="RID">
+ </argument>
+ <argument index="1" name="canvas" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="viewport_set_active">
+ <return type="void">
+ </return>
+ <argument index="0" name="viewport" type="RID">
+ </argument>
+ <argument index="1" name="active" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="viewport_set_canvas_layer">
+ <return type="void">
+ </return>
+ <argument index="0" name="viewport" type="RID">
+ </argument>
+ <argument index="1" name="canvas" type="RID">
+ </argument>
+ <argument index="2" name="layer" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="viewport_set_canvas_transform">
+ <return type="void">
+ </return>
+ <argument index="0" name="viewport" type="RID">
+ </argument>
+ <argument index="1" name="canvas" type="RID">
+ </argument>
+ <argument index="2" name="offset" type="Transform2D">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="viewport_set_clear_mode">
+ <return type="void">
+ </return>
+ <argument index="0" name="viewport" type="RID">
+ </argument>
+ <argument index="1" name="clear_mode" type="int" enum="VisualServer.ViewportClearMode">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="viewport_set_debug_draw">
+ <return type="void">
+ </return>
+ <argument index="0" name="viewport" type="RID">
+ </argument>
+ <argument index="1" name="draw" type="int" enum="VisualServer.ViewportDebugDraw">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="viewport_set_disable_3d">
+ <return type="void">
+ </return>
+ <argument index="0" name="viewport" type="RID">
+ </argument>
+ <argument index="1" name="disabled" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="viewport_set_disable_environment">
+ <return type="void">
+ </return>
+ <argument index="0" name="viewport" type="RID">
+ </argument>
+ <argument index="1" name="disabled" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="viewport_set_global_canvas_transform">
+ <return type="void">
+ </return>
+ <argument index="0" name="viewport" type="RID">
+ </argument>
+ <argument index="1" name="transform" type="Transform2D">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="viewport_set_hdr">
+ <return type="void">
+ </return>
+ <argument index="0" name="viewport" type="RID">
+ </argument>
+ <argument index="1" name="enabled" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="viewport_set_hide_canvas">
+ <return type="void">
+ </return>
+ <argument index="0" name="viewport" type="RID">
+ </argument>
+ <argument index="1" name="hidden" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="viewport_set_hide_scenario">
+ <return type="void">
+ </return>
+ <argument index="0" name="viewport" type="RID">
+ </argument>
+ <argument index="1" name="hidden" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="viewport_set_msaa">
+ <return type="void">
+ </return>
+ <argument index="0" name="viewport" type="RID">
+ </argument>
+ <argument index="1" name="msaa" type="int" enum="VisualServer.ViewportMSAA">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="viewport_set_parent_viewport">
+ <return type="void">
+ </return>
+ <argument index="0" name="viewport" type="RID">
+ </argument>
+ <argument index="1" name="parent_viewport" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="viewport_set_scenario">
+ <return type="void">
+ </return>
+ <argument index="0" name="viewport" type="RID">
+ </argument>
+ <argument index="1" name="scenario" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="viewport_set_shadow_atlas_quadrant_subdivision">
+ <return type="void">
+ </return>
+ <argument index="0" name="viewport" type="RID">
+ </argument>
+ <argument index="1" name="quadrant" type="int">
+ </argument>
+ <argument index="2" name="subdivision" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="viewport_set_shadow_atlas_size">
+ <return type="void">
+ </return>
+ <argument index="0" name="viewport" type="RID">
+ </argument>
+ <argument index="1" name="size" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="viewport_set_size">
+ <return type="void">
+ </return>
+ <argument index="0" name="viewport" type="RID">
+ </argument>
+ <argument index="1" name="width" type="int">
+ </argument>
+ <argument index="2" name="height" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="viewport_set_transparent_background">
+ <return type="void">
+ </return>
+ <argument index="0" name="viewport" type="RID">
+ </argument>
+ <argument index="1" name="enabled" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="viewport_set_update_mode">
+ <return type="void">
+ </return>
+ <argument index="0" name="viewport" type="RID">
+ </argument>
+ <argument index="1" name="update_mode" type="int" enum="VisualServer.ViewportUpdateMode">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="viewport_set_usage">
+ <return type="void">
+ </return>
+ <argument index="0" name="viewport" type="RID">
+ </argument>
+ <argument index="1" name="usage" type="int" enum="VisualServer.ViewportUsage">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="viewport_set_use_arvr">
+ <return type="void">
+ </return>
+ <argument index="0" name="viewport" type="RID">
+ </argument>
+ <argument index="1" name="use_arvr" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="viewport_set_vflip">
+ <return type="void">
+ </return>
+ <argument index="0" name="viewport" type="RID">
+ </argument>
+ <argument index="1" name="enabled" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
</methods>
+ <signals>
+ <signal name="frame_drawn_in_thread">
+ <description>
+ </description>
+ </signal>
+ </signals>
<constants>
+ <constant name="NO_INDEX_ARRAY" value="-1" enum="">
+ </constant>
+ <constant name="ARRAY_WEIGHTS_SIZE" value="4" enum="">
+ </constant>
+ <constant name="CANVAS_ITEM_Z_MIN" value="-4096" enum="">
+ </constant>
+ <constant name="CANVAS_ITEM_Z_MAX" value="4096" enum="">
+ </constant>
+ <constant name="MAX_GLOW_LEVELS" value="7" enum="">
+ </constant>
+ <constant name="MAX_CURSORS" value="8" enum="">
+ </constant>
+ <constant name="MATERIAL_RENDER_PRIORITY_MIN" value="-128" enum="">
+ </constant>
+ <constant name="MATERIAL_RENDER_PRIORITY_MAX" value="127" enum="">
+ </constant>
+ <constant name="CUBEMAP_LEFT" value="0">
+ </constant>
+ <constant name="CUBEMAP_RIGHT" value="1">
+ </constant>
+ <constant name="CUBEMAP_BOTTOM" value="2">
+ </constant>
+ <constant name="CUBEMAP_TOP" value="3">
+ </constant>
+ <constant name="CUBEMAP_FRONT" value="4">
+ </constant>
+ <constant name="CUBEMAP_BACK" value="5">
+ </constant>
+ <constant name="TEXTURE_FLAG_MIPMAPS" value="1">
+ </constant>
+ <constant name="TEXTURE_FLAG_REPEAT" value="2">
+ </constant>
+ <constant name="TEXTURE_FLAG_FILTER" value="4">
+ </constant>
+ <constant name="TEXTURE_FLAG_ANISOTROPIC_FILTER" value="8">
+ </constant>
+ <constant name="TEXTURE_FLAG_CONVERT_TO_LINEAR" value="16">
+ </constant>
+ <constant name="TEXTURE_FLAG_MIRRORED_REPEAT" value="32">
+ </constant>
+ <constant name="TEXTURE_FLAG_CUBEMAP" value="2048">
+ </constant>
+ <constant name="TEXTURE_FLAG_USED_FOR_STREAMING" value="4096">
+ </constant>
+ <constant name="TEXTURE_FLAGS_DEFAULT" value="7">
+ </constant>
+ <constant name="SHADER_SPATIAL" value="0">
+ </constant>
+ <constant name="SHADER_CANVAS_ITEM" value="1">
+ </constant>
+ <constant name="SHADER_PARTICLES" value="2">
+ </constant>
+ <constant name="SHADER_MAX" value="3">
+ </constant>
+ <constant name="ARRAY_VERTEX" value="0">
+ </constant>
+ <constant name="ARRAY_NORMAL" value="1">
+ </constant>
+ <constant name="ARRAY_TANGENT" value="2">
+ </constant>
+ <constant name="ARRAY_COLOR" value="3">
+ </constant>
+ <constant name="ARRAY_TEX_UV" value="4">
+ </constant>
+ <constant name="ARRAY_TEX_UV2" value="5">
+ </constant>
+ <constant name="ARRAY_BONES" value="6">
+ </constant>
+ <constant name="ARRAY_WEIGHTS" value="7">
+ </constant>
+ <constant name="ARRAY_INDEX" value="8">
+ </constant>
+ <constant name="ARRAY_MAX" value="9">
+ </constant>
+ <constant name="ARRAY_FORMAT_VERTEX" value="1">
+ </constant>
+ <constant name="ARRAY_FORMAT_NORMAL" value="2">
+ </constant>
+ <constant name="ARRAY_FORMAT_TANGENT" value="4">
+ </constant>
+ <constant name="ARRAY_FORMAT_COLOR" value="8">
+ </constant>
+ <constant name="ARRAY_FORMAT_TEX_UV" value="16">
+ </constant>
+ <constant name="ARRAY_FORMAT_TEX_UV2" value="32">
+ </constant>
+ <constant name="ARRAY_FORMAT_BONES" value="64">
+ </constant>
+ <constant name="ARRAY_FORMAT_WEIGHTS" value="128">
+ </constant>
+ <constant name="ARRAY_FORMAT_INDEX" value="256">
+ </constant>
+ <constant name="ARRAY_COMPRESS_VERTEX" value="512">
+ </constant>
+ <constant name="ARRAY_COMPRESS_NORMAL" value="1024">
+ </constant>
+ <constant name="ARRAY_COMPRESS_TANGENT" value="2048">
+ </constant>
+ <constant name="ARRAY_COMPRESS_COLOR" value="4096">
+ </constant>
+ <constant name="ARRAY_COMPRESS_TEX_UV" value="8192">
+ </constant>
+ <constant name="ARRAY_COMPRESS_TEX_UV2" value="16384">
+ </constant>
+ <constant name="ARRAY_COMPRESS_BONES" value="32768">
+ </constant>
+ <constant name="ARRAY_COMPRESS_WEIGHTS" value="65536">
+ </constant>
+ <constant name="ARRAY_COMPRESS_INDEX" value="131072">
+ </constant>
+ <constant name="ARRAY_FLAG_USE_2D_VERTICES" value="262144">
+ </constant>
+ <constant name="ARRAY_FLAG_USE_16_BIT_BONES" value="524288">
+ </constant>
+ <constant name="ARRAY_COMPRESS_DEFAULT" value="97792">
+ </constant>
+ <constant name="PRIMITIVE_POINTS" value="0">
+ </constant>
+ <constant name="PRIMITIVE_LINES" value="1">
+ </constant>
+ <constant name="PRIMITIVE_LINE_STRIP" value="2">
+ </constant>
+ <constant name="PRIMITIVE_LINE_LOOP" value="3">
+ </constant>
+ <constant name="PRIMITIVE_TRIANGLES" value="4">
+ </constant>
+ <constant name="PRIMITIVE_TRIANGLE_STRIP" value="5">
+ </constant>
+ <constant name="PRIMITIVE_TRIANGLE_FAN" value="6">
+ </constant>
+ <constant name="PRIMITIVE_MAX" value="7">
+ </constant>
+ <constant name="BLEND_SHAPE_MODE_NORMALIZED" value="0">
+ </constant>
+ <constant name="BLEND_SHAPE_MODE_RELATIVE" value="1">
+ </constant>
+ <constant name="LIGHT_DIRECTIONAL" value="0">
+ </constant>
+ <constant name="LIGHT_OMNI" value="1">
+ </constant>
+ <constant name="LIGHT_SPOT" value="2">
+ </constant>
+ <constant name="LIGHT_PARAM_ENERGY" value="0">
+ </constant>
+ <constant name="LIGHT_PARAM_SPECULAR" value="1">
+ </constant>
+ <constant name="LIGHT_PARAM_RANGE" value="2">
+ </constant>
+ <constant name="LIGHT_PARAM_ATTENUATION" value="3">
+ </constant>
+ <constant name="LIGHT_PARAM_SPOT_ANGLE" value="4">
+ </constant>
+ <constant name="LIGHT_PARAM_SPOT_ATTENUATION" value="5">
+ </constant>
+ <constant name="LIGHT_PARAM_CONTACT_SHADOW_SIZE" value="6">
+ </constant>
+ <constant name="LIGHT_PARAM_SHADOW_MAX_DISTANCE" value="7">
+ </constant>
+ <constant name="LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET" value="8">
+ </constant>
+ <constant name="LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET" value="9">
+ </constant>
+ <constant name="LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET" value="10">
+ </constant>
+ <constant name="LIGHT_PARAM_SHADOW_NORMAL_BIAS" value="11">
+ </constant>
+ <constant name="LIGHT_PARAM_SHADOW_BIAS" value="12">
+ </constant>
+ <constant name="LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE" value="13">
+ </constant>
+ <constant name="LIGHT_PARAM_MAX" value="14">
+ </constant>
+ <constant name="VIEWPORT_UPDATE_DISABLED" value="0">
+ </constant>
+ <constant name="VIEWPORT_UPDATE_ONCE" value="1">
+ </constant>
+ <constant name="VIEWPORT_UPDATE_WHEN_VISIBLE" value="2">
+ </constant>
+ <constant name="VIEWPORT_UPDATE_ALWAYS" value="3">
+ </constant>
+ <constant name="VIEWPORT_CLEAR_ALWAYS" value="0">
+ </constant>
+ <constant name="VIEWPORT_CLEAR_NEVER" value="1">
+ </constant>
+ <constant name="VIEWPORT_CLEAR_ONLY_NEXT_FRAME" value="2">
+ </constant>
+ <constant name="VIEWPORT_MSAA_DISABLED" value="0">
+ </constant>
+ <constant name="VIEWPORT_MSAA_2X" value="1">
+ </constant>
+ <constant name="VIEWPORT_MSAA_4X" value="2">
+ </constant>
+ <constant name="VIEWPORT_MSAA_8X" value="3">
+ </constant>
+ <constant name="VIEWPORT_MSAA_16X" value="4">
+ </constant>
+ <constant name="VIEWPORT_USAGE_2D" value="0">
+ </constant>
+ <constant name="VIEWPORT_USAGE_2D_NO_SAMPLING" value="1">
+ </constant>
+ <constant name="VIEWPORT_USAGE_3D" value="2">
+ </constant>
+ <constant name="VIEWPORT_USAGE_3D_NO_EFFECTS" value="3">
+ </constant>
+ <constant name="VIEWPORT_RENDER_INFO_OBJECTS_IN_FRAME" value="0">
+ </constant>
+ <constant name="VIEWPORT_RENDER_INFO_VERTICES_IN_FRAME" value="1">
+ </constant>
+ <constant name="VIEWPORT_RENDER_INFO_MATERIAL_CHANGES_IN_FRAME" value="2">
+ </constant>
+ <constant name="VIEWPORT_RENDER_INFO_SHADER_CHANGES_IN_FRAME" value="3">
+ </constant>
+ <constant name="VIEWPORT_RENDER_INFO_SURFACE_CHANGES_IN_FRAME" value="4">
+ </constant>
+ <constant name="VIEWPORT_RENDER_INFO_DRAW_CALLS_IN_FRAME" value="5">
+ </constant>
+ <constant name="VIEWPORT_RENDER_INFO_MAX" value="6">
+ </constant>
+ <constant name="VIEWPORT_DEBUG_DRAW_DISABLED" value="0">
+ </constant>
+ <constant name="VIEWPORT_DEBUG_DRAW_UNSHADED" value="1">
+ </constant>
+ <constant name="VIEWPORT_DEBUG_DRAW_OVERDRAW" value="2">
+ </constant>
+ <constant name="VIEWPORT_DEBUG_DRAW_WIREFRAME" value="3">
+ </constant>
+ <constant name="SCENARIO_DEBUG_DISABLED" value="0">
+ </constant>
+ <constant name="SCENARIO_DEBUG_WIREFRAME" value="1">
+ </constant>
+ <constant name="SCENARIO_DEBUG_OVERDRAW" value="2">
+ </constant>
+ <constant name="SCENARIO_DEBUG_SHADELESS" value="3">
+ </constant>
+ <constant name="INSTANCE_NONE" value="0">
+ </constant>
+ <constant name="INSTANCE_MESH" value="1">
+ </constant>
+ <constant name="INSTANCE_MULTIMESH" value="2">
+ </constant>
+ <constant name="INSTANCE_IMMEDIATE" value="3">
+ </constant>
+ <constant name="INSTANCE_PARTICLES" value="4">
+ </constant>
+ <constant name="INSTANCE_LIGHT" value="5">
+ </constant>
+ <constant name="INSTANCE_REFLECTION_PROBE" value="6">
+ </constant>
+ <constant name="INSTANCE_GI_PROBE" value="7">
+ </constant>
+ <constant name="INSTANCE_MAX" value="8">
+ </constant>
+ <constant name="INSTANCE_GEOMETRY_MASK" value="30">
+ </constant>
+ <constant name="NINE_PATCH_STRETCH" value="0">
+ </constant>
+ <constant name="NINE_PATCH_TILE" value="1">
+ </constant>
+ <constant name="NINE_PATCH_TILE_FIT" value="2">
+ </constant>
+ <constant name="CANVAS_LIGHT_MODE_ADD" value="0">
+ </constant>
+ <constant name="CANVAS_LIGHT_MODE_SUB" value="1">
+ </constant>
+ <constant name="CANVAS_LIGHT_MODE_MIX" value="2">
+ </constant>
+ <constant name="CANVAS_LIGHT_MODE_MASK" value="3">
+ </constant>
+ <constant name="CANVAS_LIGHT_FILTER_NONE" value="0">
+ </constant>
+ <constant name="CANVAS_LIGHT_FILTER_PCF3" value="1">
+ </constant>
+ <constant name="CANVAS_LIGHT_FILTER_PCF5" value="2">
+ </constant>
+ <constant name="CANVAS_LIGHT_FILTER_PCF7" value="3">
+ </constant>
+ <constant name="CANVAS_LIGHT_FILTER_PCF9" value="4">
+ </constant>
+ <constant name="CANVAS_LIGHT_FILTER_PCF13" value="5">
+ </constant>
+ <constant name="CANVAS_OCCLUDER_POLYGON_CULL_DISABLED" value="0">
+ </constant>
+ <constant name="CANVAS_OCCLUDER_POLYGON_CULL_CLOCKWISE" value="1">
+ </constant>
+ <constant name="CANVAS_OCCLUDER_POLYGON_CULL_COUNTER_CLOCKWISE" value="2">
+ </constant>
+ <constant name="INFO_OBJECTS_IN_FRAME" value="0">
+ </constant>
+ <constant name="INFO_VERTICES_IN_FRAME" value="1">
+ </constant>
+ <constant name="INFO_MATERIAL_CHANGES_IN_FRAME" value="2">
+ </constant>
+ <constant name="INFO_SHADER_CHANGES_IN_FRAME" value="3">
+ </constant>
+ <constant name="INFO_SURFACE_CHANGES_IN_FRAME" value="4">
+ </constant>
+ <constant name="INFO_DRAW_CALLS_IN_FRAME" value="5">
+ </constant>
+ <constant name="INFO_USAGE_VIDEO_MEM_TOTAL" value="6">
+ </constant>
+ <constant name="INFO_VIDEO_MEM_USED" value="7">
+ </constant>
+ <constant name="INFO_TEXTURE_MEM_USED" value="8">
+ </constant>
+ <constant name="INFO_VERTEX_MEM_USED" value="9">
+ </constant>
+ <constant name="FEATURE_SHADERS" value="0">
+ </constant>
+ <constant name="FEATURE_MULTITHREADED" value="1">
+ </constant>
</constants>
</class>
diff --git a/doc/classes/WeakRef.xml b/doc/classes/WeakRef.xml
index 1071a40c3b..00e5bdfd2c 100644
--- a/doc/classes/WeakRef.xml
+++ b/doc/classes/WeakRef.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="WeakRef" inherits="Reference" category="Core" version="3.0.alpha.custom_build">
+<class name="WeakRef" inherits="Reference" category="Core" version="3.0-alpha">
<brief_description>
Holds an [Object], but does not contribute to the reference count if the object is a reference.
</brief_description>
<description>
- A weakref can hold a [Reference], without contributing to the reference counter. A weakref can be created from an [Object] using [method @GDScript.weakref]. If this object is not a reference, weakref still works, however, it does not have any effect on the object. Weakrefs are useful in cases where multiple classes have variables that refer to eachother. Without weakrefs, using these classes could lead to memory leaks, since both references keep eachother from being released. Making part of the variables a weakref can prevent this cyclic dependency, and allows the references to be released.
+ A weakref can hold a [Reference], without contributing to the reference counter. A weakref can be created from an [Object] using [method @GDScript.weakref]. If this object is not a reference, weakref still works, however, it does not have any effect on the object. Weakrefs are useful in cases where multiple classes have variables that refer to each other. Without weakrefs, using these classes could lead to memory leaks, since both references keep each other from being released. Making part of the variables a weakref can prevent this cyclic dependency, and allows the references to be released.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/WindowDialog.xml b/doc/classes/WindowDialog.xml
index e57983c367..a6ebd45a76 100644
--- a/doc/classes/WindowDialog.xml
+++ b/doc/classes/WindowDialog.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="WindowDialog" inherits="Popup" category="Core" version="3.0.alpha.custom_build">
+<class name="WindowDialog" inherits="Popup" category="Core" version="3.0-alpha">
<brief_description>
Base class for window dialogs.
</brief_description>
diff --git a/doc/classes/World.xml b/doc/classes/World.xml
index f4f5f5b756..6d243f26a5 100644
--- a/doc/classes/World.xml
+++ b/doc/classes/World.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="World" inherits="Resource" category="Core" version="3.0.alpha.custom_build">
+<class name="World" inherits="Resource" category="Core" version="3.0-alpha">
<brief_description>
Class that has everything pertaining to a world.
</brief_description>
diff --git a/doc/classes/World2D.xml b/doc/classes/World2D.xml
index d57117fef0..bf3cc9f24b 100644
--- a/doc/classes/World2D.xml
+++ b/doc/classes/World2D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="World2D" inherits="Resource" category="Core" version="3.0.alpha.custom_build">
+<class name="World2D" inherits="Resource" category="Core" version="3.0-alpha">
<brief_description>
Class that has everything pertaining to a 2D world.
</brief_description>
diff --git a/doc/classes/WorldEnvironment.xml b/doc/classes/WorldEnvironment.xml
index a9450c1743..13922b4987 100644
--- a/doc/classes/WorldEnvironment.xml
+++ b/doc/classes/WorldEnvironment.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="WorldEnvironment" inherits="Node" category="Core" version="3.0.alpha.custom_build">
+<class name="WorldEnvironment" inherits="Node" category="Core" version="3.0-alpha">
<brief_description>
Sets environment properties for the entire scene
</brief_description>
<description>
- The [WorldEnvironment] node can be added to a scene in order to set default [Environment] variables for the scene. The [WorldEnvironment] can be overridden by an [Environment] node set on the current [Camera]. Additionally, only one [WorldEnvironment] may be instanced in a given scene at a time. The [WorldEnvironment] allows the user to specify default lighting parameters (e.g. ambient lighting), various post-processing effects (e.g. SSAO, DOF, Tonemapping), and how to draw the background (e.g. solid color, skybox).
+ The [code]WorldEnvironment[/code] node can be added to a scene in order to set default [Environment] variables for the scene. The [code]WorldEnvironment[/code] can be overridden by an [Environment] node set on the current [Camera]. Additionally, only one [code]WorldEnvironment[/code] may be instanced in a given scene at a time. The [code]WorldEnvironment[/code] allows the user to specify default lighting parameters (e.g. ambient lighting), various post-processing effects (e.g. SSAO, DOF, Tonemapping), and how to draw the background (e.g. solid color, skybox).
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/XMLParser.xml b/doc/classes/XMLParser.xml
index bb9599e273..5e7ba3b4bf 100644
--- a/doc/classes/XMLParser.xml
+++ b/doc/classes/XMLParser.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="XMLParser" inherits="Reference" category="Core" version="3.0.alpha.custom_build">
+<class name="XMLParser" inherits="Reference" category="Core" version="3.0-alpha">
<brief_description>
Low-level class for creating parsers for XML files.
</brief_description>
diff --git a/doc/classes/YSort.xml b/doc/classes/YSort.xml
index 3c0c8b3d06..de4c8be11a 100644
--- a/doc/classes/YSort.xml
+++ b/doc/classes/YSort.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="YSort" inherits="Node2D" category="Core" version="3.0.alpha.custom_build">
+<class name="YSort" inherits="Node2D" category="Core" version="3.0-alpha">
<brief_description>
Sort all child nodes based on their Y positions.
</brief_description>
diff --git a/doc/classes/bool.xml b/doc/classes/bool.xml
index 1d662ba946..f596180bcf 100644
--- a/doc/classes/bool.xml
+++ b/doc/classes/bool.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="bool" category="Built-In Types" version="3.0.alpha.custom_build">
+<class name="bool" category="Built-In Types" version="3.0-alpha">
<brief_description>
Boolean built-in type
</brief_description>
diff --git a/doc/classes/float.xml b/doc/classes/float.xml
index 942aa4d55a..703ca55be8 100644
--- a/doc/classes/float.xml
+++ b/doc/classes/float.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="float" category="Built-In Types" version="3.0.alpha.custom_build">
+<class name="float" category="Built-In Types" version="3.0-alpha">
<brief_description>
Float built-in type
</brief_description>
diff --git a/doc/classes/int.xml b/doc/classes/int.xml
index 7c2267ac9a..79a198b198 100644
--- a/doc/classes/int.xml
+++ b/doc/classes/int.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="int" category="Built-In Types" version="3.0.alpha.custom_build">
+<class name="int" category="Built-In Types" version="3.0-alpha">
<brief_description>
Integer built-in type.
</brief_description>
diff --git a/doc/tools/doc_status.py b/doc/tools/doc_status.py
index 6b936899d8..170ded9f50 100644
--- a/doc/tools/doc_status.py
+++ b/doc/tools/doc_status.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python3
+#!/usr/bin/env python
import fnmatch
import os
@@ -250,15 +250,16 @@ class ClassStatus:
for tag in list(c):
if tag.tag in ['methods']:
for sub_tag in list(tag):
- methods.append(sub_tag.find('name'))
+ methods.append(sub_tag.attrib['name'])
if tag.tag in ['members']:
for sub_tag in list(tag):
try:
- methods.remove(sub_tag.find('setter'))
- methods.remove(sub_tag.find('getter'))
+ if(sub_tag.attrib['setter'].startswith('_') == False):
+ methods.remove(sub_tag.attrib['setter'])
+ if(sub_tag.attrib['getter'].startswith('_') == False):
+ methods.remove(sub_tag.attrib['getter'])
except:
pass
-
for tag in list(c):
if tag.tag == 'brief_description':
@@ -269,7 +270,7 @@ class ClassStatus:
elif tag.tag in ['methods', 'signals']:
for sub_tag in list(tag):
- if sub_tag.find('name') in methods or tag.tag == 'signals':
+ if sub_tag.attrib['name'] in methods or tag.tag == 'signals':
descr = sub_tag.find('description')
status.progresses[tag.tag].increment(len(descr.text.strip()) > 0)
elif tag.tag in ['constants', 'members']:
@@ -297,17 +298,21 @@ input_class_list = []
merged_file = ""
for arg in sys.argv[1:]:
- if arg.startswith('--'):
- flags[long_flags[arg[2:]]] = not flags[long_flags[arg[2:]]]
- elif arg.startswith('-'):
- for f in arg[1:]:
- flags[f] = not flags[f]
- elif os.path.isdir(arg):
- for f in os.listdir(arg):
- if f.endswith('.xml'):
- input_file_list.append(os.path.join(arg, f));
- else:
- input_class_list.append(arg)
+ try:
+ if arg.startswith('--'):
+ flags[long_flags[arg[2:]]] = not flags[long_flags[arg[2:]]]
+ elif arg.startswith('-'):
+ for f in arg[1:]:
+ flags[f] = not flags[f]
+ elif os.path.isdir(arg):
+ for f in os.listdir(arg):
+ if f.endswith('.xml'):
+ input_file_list.append(os.path.join(arg, f));
+ else:
+ input_class_list.append(arg)
+ except KeyError:
+ print("Unknown command line flag: " + arg)
+ sys.exit(1)
if flags['i']:
for r in ['methods', 'constants', 'members', 'signals']:
diff --git a/doc/tools/makerst.py b/doc/tools/makerst.py
index c4dff588b0..cd0108019b 100644
--- a/doc/tools/makerst.py
+++ b/doc/tools/makerst.py
@@ -7,6 +7,7 @@ import os
import xml.etree.ElementTree as ET
input_list = []
+cur_file = ""
for arg in sys.argv[1:]:
if arg.endswith(os.sep):
@@ -14,14 +15,14 @@ for arg in sys.argv[1:]:
input_list.append(arg)
if len(input_list) < 1:
- print 'usage: makerst.py <path to folders> and/or <path to .xml files> (order of arguments irrelevant)'
- print 'example: makerst.py "../../modules/" "../classes" path_to/some_class.xml'
+ print('usage: makerst.py <path to folders> and/or <path to .xml files> (order of arguments irrelevant)')
+ print('example: makerst.py "../../modules/" "../classes" path_to/some_class.xml')
sys.exit(0)
def validate_tag(elem, tag):
if elem.tag != tag:
- print "Tag mismatch, expected '" + tag + "', got " + elem.tag
+ print("Tag mismatch, expected '" + tag + "', got " + elem.tag)
sys.exit(255)
@@ -41,7 +42,7 @@ def make_class_list(class_list, columns):
f = codecs.open('class_list.rst', 'wb', 'utf-8')
prev = 0
col_max = len(class_list) / columns + 1
- print ('col max is ', col_max)
+ print(('col max is ', col_max))
col_count = 0
row_count = 0
last_initial = ''
@@ -189,8 +190,11 @@ def rstize_text(text, cclass):
post_text = text[endq_pos + 1:]
tag_text = text[pos + 1:endq_pos]
+ escape_post = False
+
if tag_text in class_names:
tag_text = make_type(tag_text)
+ escape_post = True
else: # command
cmd = tag_text
space_pos = tag_text.find(' ')
@@ -203,27 +207,33 @@ def rstize_text(text, cclass):
elif cmd == '/code':
tag_text = '``'
inside_code = False
+ escape_post = True
elif inside_code:
tag_text = '[' + tag_text + ']'
elif cmd.find('html') == 0:
cmd = tag_text[:space_pos]
param = tag_text[space_pos + 1:]
tag_text = param
- elif cmd.find('method') == 0:
+ elif cmd.find('method') == 0 or cmd.find('member') == 0 or cmd.find('signal') == 0:
cmd = tag_text[:space_pos]
param = tag_text[space_pos + 1:]
if param.find('.') != -1:
- (class_param, method_param) = param.split('.')
+ ss = param.split('.')
+ if len(ss) > 2:
+ sys.exit("Bad reference: '" + param + "' in file: " + cur_file)
+ (class_param, method_param) = ss
tag_text = ':ref:`' + class_param + '.' + method_param + '<class_' + class_param + '_' + method_param + '>`'
else:
tag_text = ':ref:`' + param + '<class_' + cclass + "_" + param + '>`'
+ escape_post = True
elif cmd.find('image=') == 0:
tag_text = "" # '![](' + cmd[6:] + ')'
elif cmd.find('url=') == 0:
tag_text = ':ref:`' + cmd[4:] + '<' + cmd[4:] + ">`"
elif cmd == '/url':
- tag_text = ')'
+ tag_text = ''
+ escape_post = True
elif cmd == 'center':
tag_text = ''
elif cmd == '/center':
@@ -248,6 +258,11 @@ def rstize_text(text, cclass):
inside_code = True
else:
tag_text = make_type(tag_text)
+ escape_post = True
+
+ # Properly escape things like `[Node]s`
+ if escape_post and post_text and post_text[0].isalnum(): # not punctuation, escape
+ post_text = '\ ' + post_text
text = pre_text + tag_text + post_text
pos = len(pre_text) + len(tag_text)
@@ -300,16 +315,11 @@ def make_method(
if declare or pp == None:
- # span.attrib["class"]="funcdecl"
- # a=ET.SubElement(span,"a")
- # a.attrib["name"]=name+"_"+m.attrib["name"]
- # a.text=name+"::"+m.attrib["name"]
-
- s = ' **' + m.attrib['name'] + '** '
+ s = '**' + m.attrib['name'] + '** '
else:
s = ':ref:`' + m.attrib['name'] + '<class_' + cname + "_" + m.attrib['name'] + '>` '
- s += ' **(**'
+ s += '**(**'
argfound = False
for a in mdata['argidx']:
arg = mdata[a]
@@ -329,10 +339,6 @@ def make_method(
if 'default' in arg.attrib:
s += '=' + arg.attrib['default']
- argfound = True
-
- if argfound:
- s += ' '
s += ' **)**'
if 'qualifiers' in m.attrib:
@@ -445,7 +451,9 @@ def make_rst_class(node):
if events != None and len(list(events)) > 0:
f.write(make_heading('Signals', '-'))
for m in list(events):
+ f.write(".. _class_" + name + "_" + m.attrib['name'] + ":\n\n")
make_method(f, node.attrib['name'], m, True, name, True)
+ f.write('\n')
d = m.find('description')
if d == None or d.text.strip() == '':
continue
@@ -459,12 +467,14 @@ def make_rst_class(node):
f.write(make_heading('Member Variables', '-'))
for c in list(members):
+ # Leading two spaces necessary to prevent breaking the <ul>
+ f.write(" .. _class_" + name + "_" + c.attrib['name'] + ":\n\n")
s = '- '
s += make_type(c.attrib['type']) + ' '
s += '**' + c.attrib['name'] + '**'
if c.text.strip() != '':
- s += ' - ' + c.text.strip()
- f.write(s + '\n')
+ s += ' - ' + rstize_text(c.text.strip(), name)
+ f.write(s + '\n\n')
f.write('\n')
constants = node.find('constants')
@@ -507,19 +517,19 @@ for path in input_list:
for subdir, dirs, _ in os.walk(path):
if 'doc_classes' in dirs:
doc_dir = os.path.join(subdir, 'doc_classes')
- class_file_name = [f for f in os.listdir(doc_dir) if f.endswith('.xml')][0]
- file_list.append(os.path.join(doc_dir, class_file_name))
+ class_file_names = [f for f in os.listdir(doc_dir) if f.endswith('.xml')]
+ file_list += [os.path.join(doc_dir, f) for f in class_file_names]
elif not os.path.isfile(path):
file_list += [os.path.join(path, f) for f in os.listdir(path) if f.endswith('.xml')]
elif os.path.isfile(path) and path.endswith('.xml'):
file_list.append(path)
-for file in file_list:
- tree = ET.parse(file)
+for cur_file in file_list:
+ tree = ET.parse(cur_file)
doc = tree.getroot()
if 'version' not in doc.attrib:
- print "Version missing from 'doc'"
+ print("Version missing from 'doc'")
sys.exit(255)
version = doc.attrib['version']
diff --git a/drivers/SCsub b/drivers/SCsub
index 34d6254578..938927f3a9 100644
--- a/drivers/SCsub
+++ b/drivers/SCsub
@@ -34,7 +34,12 @@ if env['tools']:
SConscript("convex_decomp/SCsub")
if env['vsproj']:
+ import os
+ path = os.getcwd()
+ # Change directory so the path resolves correctly in the function call.
+ os.chdir("..")
env.AddToVSProject(env.drivers_sources)
+ os.chdir(path)
if env.split_drivers:
env.split_lib("drivers")
diff --git a/drivers/gl_context/context_gl.cpp b/drivers/gl_context/context_gl.cpp
index a453eef227..1581512369 100644
--- a/drivers/gl_context/context_gl.cpp
+++ b/drivers/gl_context/context_gl.cpp
@@ -29,7 +29,7 @@
/*************************************************************************/
#include "context_gl.h"
-#if defined(OPENGL_ENABLED) || defined(GLES2_ENABLED)
+#if defined(OPENGL_ENABLED) || defined(GLES_ENABLED)
ContextGL *ContextGL::singleton = NULL;
diff --git a/drivers/gl_context/context_gl.h b/drivers/gl_context/context_gl.h
index 399657eb52..3496f2948c 100644
--- a/drivers/gl_context/context_gl.h
+++ b/drivers/gl_context/context_gl.h
@@ -30,7 +30,7 @@
#ifndef CONTEXT_GL_H
#define CONTEXT_GL_H
-#if defined(OPENGL_ENABLED) || defined(GLES2_ENABLED)
+#if defined(OPENGL_ENABLED) || defined(GLES_ENABLED)
#include "typedefs.h"
diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp
index 5d62d2f5a0..308a18aa9d 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.cpp
+++ b/drivers/gles3/rasterizer_canvas_gles3.cpp
@@ -149,13 +149,6 @@ void RasterizerCanvasGLES3::canvas_begin() {
storage->frame.clear_request = false;
}
- /*canvas_shader.unbind();
- canvas_shader.set_custom_shader(0);
- canvas_shader.set_conditional(CanvasShaderGLES2::USE_MODULATE,false);
- canvas_shader.bind();
- canvas_shader.set_uniform(CanvasShaderGLES2::TEXTURE, 0);
- canvas_use_modulate=false;*/
-
reset_canvas();
state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_TEXTURE_RECT, true);
@@ -911,61 +904,6 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur
}
}
-#if 0
-void RasterizerGLES2::_canvas_item_setup_shader_params(ShaderMaterial *material,Shader* shader) {
-
- if (canvas_shader.bind())
- rebind_texpixel_size=true;
-
- if (material->shader_version!=shader->version) {
- //todo optimize uniforms
- material->shader_version=shader->version;
- }
-
- if (shader->has_texscreen && framebuffer.active) {
-
- int x = viewport.x;
- int y = window_size.height-(viewport.height+viewport.y);
-
- canvas_shader.set_uniform(CanvasShaderGLES2::TEXSCREEN_SCREEN_MULT,Vector2(float(viewport.width)/framebuffer.width,float(viewport.height)/framebuffer.height));
- canvas_shader.set_uniform(CanvasShaderGLES2::TEXSCREEN_SCREEN_CLAMP,Color(float(x)/framebuffer.width,float(y)/framebuffer.height,float(x+viewport.width)/framebuffer.width,float(y+viewport.height)/framebuffer.height));
- canvas_shader.set_uniform(CanvasShaderGLES2::TEXSCREEN_TEX,max_texture_units-1);
- glActiveTexture(GL_TEXTURE0+max_texture_units-1);
- glBindTexture(GL_TEXTURE_2D,framebuffer.sample_color);
- if (framebuffer.scale==1 && !canvas_texscreen_used) {
-#ifdef GLEW_ENABLED
- if (current_rt) {
- glReadBuffer(GL_COLOR_ATTACHMENT0);
- } else {
- glReadBuffer(GL_BACK);
- }
-#endif
- if (current_rt) {
- glCopyTexSubImage2D(GL_TEXTURE_2D,0,viewport.x,viewport.y,viewport.x,viewport.y,viewport.width,viewport.height);
- canvas_shader.set_uniform(CanvasShaderGLES2::TEXSCREEN_SCREEN_CLAMP,Color(float(x)/framebuffer.width,float(viewport.y)/framebuffer.height,float(x+viewport.width)/framebuffer.width,float(y+viewport.height)/framebuffer.height));
- //window_size.height-(viewport.height+viewport.y)
- } else {
- glCopyTexSubImage2D(GL_TEXTURE_2D,0,x,y,x,y,viewport.width,viewport.height);
- }
-
- canvas_texscreen_used=true;
- }
-
- glActiveTexture(GL_TEXTURE0);
-
- }
-
- if (shader->has_screen_uv) {
- canvas_shader.set_uniform(CanvasShaderGLES2::SCREEN_UV_MULT,Vector2(1.0/viewport.width,1.0/viewport.height));
- }
-
-
- uses_texpixel_size=shader->uses_texpixel_size;
-
-}
-
-#endif
-
void RasterizerCanvasGLES3::_copy_texscreen(const Rect2 &p_rect) {
glDisable(GL_BLEND);
@@ -1570,6 +1508,7 @@ void RasterizerCanvasGLES3::reset_canvas() {
glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
glDisable(GL_SCISSOR_TEST);
+ glDisable(GL_DITHER);
glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD);
if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) {
diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp
index d1c8ccfe21..ee61481a86 100644
--- a/drivers/gles3/rasterizer_gles3.cpp
+++ b/drivers/gles3/rasterizer_gles3.cpp
@@ -83,6 +83,9 @@ static void GLAPIENTRY _gl_debug_print(GLenum source, GLenum type, GLuint id, GL
if (type == _EXT_DEBUG_TYPE_OTHER_ARB)
return;
+ if (type == _EXT_DEBUG_TYPE_PERFORMANCE_ARB)
+ return; //these are ultimately annoying, so removing for now
+
char debSource[256], debType[256], debSev[256];
if (source == _EXT_DEBUG_SOURCE_API_ARB)
strcpy(debSource, "OpenGL");
@@ -138,53 +141,48 @@ void RasterizerGLES3::initialize() {
print_line("Using GLES3 video driver");
}
-#ifdef GLEW_ENABLED
- GLuint res = glewInit();
- ERR_FAIL_COND(res != GLEW_OK);
- if (OS::get_singleton()->is_stdout_verbose()) {
- print_line(String("GLES2: Using GLEW ") + (const char *)glewGetString(GLEW_VERSION));
+#ifdef GLAD_ENABLED
+ if (!gladLoadGL()) {
+ ERR_PRINT("Error initializing GLAD");
}
- // Check for GL 2.1 compatibility, if not bail out
- if (!glewIsSupported("GL_VERSION_3_0")) {
- ERR_PRINT("Your system's graphic drivers seem not to support OpenGL 3.0+ / GLES 3.0, sorry :(\n"
+// GLVersion seems to be used for both GL and GL ES, so we need different version checks for them
+#ifdef OPENGL_ENABLED // OpenGL 3.3 Core Profile required
+ if (GLVersion.major < 3 && GLVersion.minor < 3) {
+#else // OpenGL ES 3.0
+ if (GLVersion.major < 3) {
+#endif
+ ERR_PRINT("Your system's graphic drivers seem not to support OpenGL 3.3 / OpenGL ES 3.0, sorry :(\n"
"Try a drivers update, buy a new GPU or try software rendering on Linux; Godot will now crash with a segmentation fault.");
- OS::get_singleton()->alert("Your system's graphic drivers seem not to support OpenGL 3.0+ / GLES 3.0, sorry :(\n"
+ OS::get_singleton()->alert("Your system's graphic drivers seem not to support OpenGL 3.3 / OpenGL ES 3.0, sorry :(\n"
"Godot Engine will self-destruct as soon as you acknowledge this error message.",
- "Fatal error: Insufficient OpenGL / GLES drivers");
- // TODO: If it's even possible, we should stop the execution without segfault and memory leaks :)
- }
-#endif
-
-#ifdef GLAD_ENABLED
-
- if (!gladLoadGL()) {
- ERR_PRINT("Error initializing GLAD");
+ "Fatal error: Insufficient OpenGL / GLES driver support");
}
#ifdef __APPLE__
// FIXME glDebugMessageCallbackARB does not seem to work on Mac OS X and opengl 3, this may be an issue with our opengl canvas..
#else
- glEnable(_EXT_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
- glDebugMessageCallbackARB(_gl_debug_print, NULL);
- glEnable(_EXT_DEBUG_OUTPUT);
+ if (OS::get_singleton()->is_stdout_verbose()) {
+ glEnable(_EXT_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
+ glDebugMessageCallbackARB(_gl_debug_print, NULL);
+ glEnable(_EXT_DEBUG_OUTPUT);
+ }
#endif
-#endif
+#endif // GLAD_ENABLED
- /* glDebugMessageControlARB(GL_DEBUG_SOURCE_API_ARB,GL_DEBUG_TYPE_ERROR_ARB,GL_DEBUG_SEVERITY_HIGH_ARB,0,NULL,GL_TRUE);
+ /* // For debugging
+ glDebugMessageControlARB(GL_DEBUG_SOURCE_API_ARB,GL_DEBUG_TYPE_ERROR_ARB,GL_DEBUG_SEVERITY_HIGH_ARB,0,NULL,GL_TRUE);
glDebugMessageControlARB(GL_DEBUG_SOURCE_API_ARB,GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB,GL_DEBUG_SEVERITY_HIGH_ARB,0,NULL,GL_TRUE);
glDebugMessageControlARB(GL_DEBUG_SOURCE_API_ARB,GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB,GL_DEBUG_SEVERITY_HIGH_ARB,0,NULL,GL_TRUE);
glDebugMessageControlARB(GL_DEBUG_SOURCE_API_ARB,GL_DEBUG_TYPE_PORTABILITY_ARB,GL_DEBUG_SEVERITY_HIGH_ARB,0,NULL,GL_TRUE);
glDebugMessageControlARB(GL_DEBUG_SOURCE_API_ARB,GL_DEBUG_TYPE_PERFORMANCE_ARB,GL_DEBUG_SEVERITY_HIGH_ARB,0,NULL,GL_TRUE);
glDebugMessageControlARB(GL_DEBUG_SOURCE_API_ARB,GL_DEBUG_TYPE_OTHER_ARB,GL_DEBUG_SEVERITY_HIGH_ARB,0,NULL,GL_TRUE);
glDebugMessageInsertARB(
-
GL_DEBUG_SOURCE_API_ARB,
GL_DEBUG_TYPE_OTHER_ARB, 1,
GL_DEBUG_SEVERITY_HIGH_ARB,5, "hello");
-
-*/
+ */
const GLubyte *renderer = glGetString(GL_RENDERER);
print_line("OpenGL ES 3.0 Renderer: " + String((const char *)renderer));
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp
index eaf0b06664..0c57e4e9cf 100644
--- a/drivers/gles3/rasterizer_scene_gles3.cpp
+++ b/drivers/gles3/rasterizer_scene_gles3.cpp
@@ -379,6 +379,7 @@ bool RasterizerSceneGLES3::shadow_atlas_update_light(RID p_atlas, RID p_light_in
sh->owner = p_light_intance;
sh->alloc_tick = tick;
sh->version = p_light_version;
+ li->shadow_atlases.insert(p_atlas);
//make new key
key = new_quadrant << ShadowAtlas::QUADRANT_SHIFT;
@@ -414,6 +415,7 @@ bool RasterizerSceneGLES3::shadow_atlas_update_light(RID p_atlas, RID p_light_in
sh->owner = p_light_intance;
sh->alloc_tick = tick;
sh->version = p_light_version;
+ li->shadow_atlases.insert(p_atlas);
//make new key
uint32_t key = new_quadrant << ShadowAtlas::QUADRANT_SHIFT;
@@ -893,7 +895,7 @@ void RasterizerSceneGLES3::environment_set_ssr(RID p_env, bool p_enable, int p_m
env->ssr_roughness = p_roughness;
}
-void RasterizerSceneGLES3::environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_radius2, float p_intensity2, float p_bias, float p_light_affect, const Color &p_color, bool p_blur) {
+void RasterizerSceneGLES3::environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_radius2, float p_intensity2, float p_bias, float p_light_affect, const Color &p_color, VS::EnvironmentSSAOQuality p_quality, VisualServer::EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness) {
Environment *env = environment_owner.getornull(p_env);
ERR_FAIL_COND(!env);
@@ -907,6 +909,8 @@ void RasterizerSceneGLES3::environment_set_ssao(RID p_env, bool p_enable, float
env->ssao_light_affect = p_light_affect;
env->ssao_color = p_color;
env->ssao_filter = p_blur;
+ env->ssao_quality = p_quality;
+ env->ssao_bilateral_sharpness = p_bilateral_sharpness;
}
void RasterizerSceneGLES3::environment_set_tonemap(RID p_env, VS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) {
@@ -2140,7 +2144,6 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_
first = false;
}
- glFrontFace(GL_CW);
glBindVertexArray(0);
state.scene_shader.set_conditional(SceneShaderGLES3::USE_INSTANCING, false);
@@ -2349,22 +2352,7 @@ void RasterizerSceneGLES3::_draw_sky(RasterizerStorageGLES3::Sky *p_sky, const C
glDepthFunc(GL_LEQUAL);
glColorMask(1, 1, 1, 1);
- float flip_sign = p_vflip ? -1 : 1;
-
- Vector3 vertices[8] = {
- Vector3(-1, -1 * flip_sign, 1),
- Vector3(0, 1, 0),
- Vector3(1, -1 * flip_sign, 1),
- Vector3(1, 1, 0),
- Vector3(1, 1 * flip_sign, 1),
- Vector3(1, 0, 0),
- Vector3(-1, 1 * flip_sign, 1),
- Vector3(0, 0, 0)
-
- };
-
- //sky uv vectors
- float vw, vh, zn;
+ // Camera
CameraMatrix camera;
if (p_custom_fov) {
@@ -2379,17 +2367,39 @@ void RasterizerSceneGLES3::_draw_sky(RasterizerStorageGLES3::Sky *p_sky, const C
camera = p_projection;
}
- camera.get_viewport_size(vw, vh);
- zn = p_projection.get_z_near();
+ float flip_sign = p_vflip ? -1 : 1;
- for (int i = 0; i < 4; i++) {
+ /*
+ If matrix[2][0] or matrix[2][1] we're dealing with an asymmetrical projection matrix. This is the case for stereoscopic rendering (i.e. VR).
+ To ensure the image rendered is perspective correct we need to move some logic into the shader. For this the USE_ASYM_PANO option is introduced.
+ It also means the uv coordinates are ignored in this mode and we don't need our loop.
+ */
+ bool asymmetrical = ((camera.matrix[2][0] != 0.0) || (camera.matrix[2][1] != 0.0));
+
+ Vector3 vertices[8] = {
+ Vector3(-1, -1 * flip_sign, 1),
+ Vector3(0, 1, 0),
+ Vector3(1, -1 * flip_sign, 1),
+ Vector3(1, 1, 0),
+ Vector3(1, 1 * flip_sign, 1),
+ Vector3(1, 0, 0),
+ Vector3(-1, 1 * flip_sign, 1),
+ Vector3(0, 0, 0)
+ };
- Vector3 uv = vertices[i * 2 + 1];
- uv.x = (uv.x * 2.0 - 1.0) * vw;
- uv.y = -(uv.y * 2.0 - 1.0) * vh;
- uv.z = -zn;
- vertices[i * 2 + 1] = p_transform.basis.xform(uv).normalized();
- vertices[i * 2 + 1].z = -vertices[i * 2 + 1].z;
+ if (!asymmetrical) {
+ float vw, vh, zn;
+ camera.get_viewport_size(vw, vh);
+ zn = p_projection.get_z_near();
+
+ for (int i = 0; i < 4; i++) {
+ Vector3 uv = vertices[i * 2 + 1];
+ uv.x = (uv.x * 2.0 - 1.0) * vw;
+ uv.y = -(uv.y * 2.0 - 1.0) * vh;
+ uv.z = -zn;
+ vertices[i * 2 + 1] = p_transform.basis.xform(uv).normalized();
+ vertices[i * 2 + 1].z = -vertices[i * 2 + 1].z;
+ }
}
glBindBuffer(GL_ARRAY_BUFFER, state.sky_verts);
@@ -2398,16 +2408,24 @@ void RasterizerSceneGLES3::_draw_sky(RasterizerStorageGLES3::Sky *p_sky, const C
glBindVertexArray(state.sky_array);
- storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_PANORAMA, true);
+ storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_ASYM_PANO, asymmetrical);
+ storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_PANORAMA, !asymmetrical);
storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_MULTIPLIER, true);
storage->shaders.copy.bind();
storage->shaders.copy.set_uniform(CopyShaderGLES3::MULTIPLIER, p_energy);
+ if (asymmetrical) {
+ // pack the bits we need from our projection matrix
+ storage->shaders.copy.set_uniform(CopyShaderGLES3::ASYM_PROJ, camera.matrix[2][0], camera.matrix[0][0], camera.matrix[2][1], camera.matrix[1][1]);
+ ///@TODO I couldn't get mat3 + p_transform.basis to work, that would be better here.
+ storage->shaders.copy.set_uniform(CopyShaderGLES3::PANO_TRANSFORM, p_transform);
+ }
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
glBindVertexArray(0);
glColorMask(1, 1, 1, 1);
+ storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_ASYM_PANO, false);
storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_MULTIPLIER, false);
storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_PANORAMA, false);
}
@@ -2553,8 +2571,8 @@ void RasterizerSceneGLES3::_setup_directional_light(int p_index, const Transform
ubo_data.light_direction_attenuation[3] = 1.0;
ubo_data.light_params[0] = 0;
- ubo_data.light_params[1] = li->light_ptr->param[VS::LIGHT_PARAM_SPECULAR];
- ubo_data.light_params[2] = 0;
+ ubo_data.light_params[1] = 0;
+ ubo_data.light_params[2] = li->light_ptr->param[VS::LIGHT_PARAM_SPECULAR];
ubo_data.light_params[3] = 0;
Color shadow_color = li->light_ptr->shadow_color.to_linear();
@@ -3170,6 +3188,15 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env, const CameraMatrix &p_
glDisable(GL_CULL_FACE);
glDisable(GL_BLEND);
+ if (env->ssao_enabled || env->ssr_enabled) {
+
+ //copy normal and roughness to effect buffer
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo);
+ glReadBuffer(GL_COLOR_ATTACHMENT2);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, storage->frame.current_rt->buffers.effect_fbo);
+ glBlitFramebuffer(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, 0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
+ }
+
if (env->ssao_enabled) {
//copy diffuse to front buffer
glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo);
@@ -3219,6 +3246,8 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env, const CameraMatrix &p_
// do SSAO!
state.ssao_shader.set_conditional(SsaoShaderGLES3::ENABLE_RADIUS2, env->ssao_radius2 > 0.001);
state.ssao_shader.set_conditional(SsaoShaderGLES3::USE_ORTHOGONAL_PROJECTION, p_cam_projection.is_orthogonal());
+ state.ssao_shader.set_conditional(SsaoShaderGLES3::SSAO_QUALITY_LOW, env->ssao_quality == VS::ENV_SSAO_QUALITY_LOW);
+ state.ssao_shader.set_conditional(SsaoShaderGLES3::SSAO_QUALITY_HIGH, env->ssao_quality == VS::ENV_SSAO_QUALITY_HIGH);
state.ssao_shader.bind();
state.ssao_shader.set_uniform(SsaoShaderGLES3::CAMERA_Z_FAR, p_cam_projection.get_z_far());
state.ssao_shader.set_uniform(SsaoShaderGLES3::CAMERA_Z_NEAR, p_cam_projection.get_z_near());
@@ -3271,6 +3300,9 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env, const CameraMatrix &p_
state.ssao_blur_shader.set_uniform(SsaoBlurShaderGLES3::CAMERA_Z_FAR, p_cam_projection.get_z_far());
state.ssao_blur_shader.set_uniform(SsaoBlurShaderGLES3::CAMERA_Z_NEAR, p_cam_projection.get_z_near());
+ state.ssao_blur_shader.set_uniform(SsaoBlurShaderGLES3::EDGE_SHARPNESS, env->ssao_bilateral_sharpness);
+ state.ssao_blur_shader.set_uniform(SsaoBlurShaderGLES3::FILTER_SCALE, int(env->ssao_filter));
+
GLint axis[2] = { i, 1 - i };
glUniform2iv(state.ssao_blur_shader.get_uniform(SsaoBlurShaderGLES3::AXIS), 1, axis);
glUniform2iv(state.ssao_blur_shader.get_uniform(SsaoBlurShaderGLES3::SCREEN_SIZE), 1, ss);
@@ -3279,6 +3311,8 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env, const CameraMatrix &p_
glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.ssao.blur_red[i]);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->depth);
+ glActiveTexture(GL_TEXTURE2);
+ glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->buffers.effect);
glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.ssao.blur_fbo[1 - i]);
if (i == 0) {
glClearBufferfv(GL_COLOR, 0, white.components); // specular
@@ -3370,12 +3404,6 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env, const CameraMatrix &p_
if (env->ssr_enabled) {
- //copy normal and roughness to effect buffer
- glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo);
- glReadBuffer(GL_COLOR_ATTACHMENT2);
- glBindFramebuffer(GL_DRAW_FRAMEBUFFER, storage->frame.current_rt->buffers.effect_fbo);
- glBlitFramebuffer(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, 0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
-
//blur diffuse into effect mipmaps using separatable convolution
//storage->shaders.copy.set_conditional(CopyShaderGLES3::GAUSSIAN_HORIZONTAL,true);
_blur_effect_buffer();
@@ -3995,6 +4023,8 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const
state.ubo_data.shadow_dual_paraboloid_render_side = 0;
state.ubo_data.shadow_dual_paraboloid_render_zfar = 0;
+ p_cam_projection.get_viewport_size(state.ubo_data.viewport_size[0], state.ubo_data.viewport_size[1]);
+
if (storage->frame.current_rt) {
state.ubo_data.screen_pixel_size[0] = 1.0 / storage->frame.current_rt->width;
state.ubo_data.screen_pixel_size[1] = 1.0 / storage->frame.current_rt->height;
@@ -4252,7 +4282,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const
if (i > 0) {
glEnable(GL_BLEND);
}
- _setup_directional_light(i, p_cam_transform.affine_inverse(), shadow_atlas != NULL);
+ _setup_directional_light(i, p_cam_transform.affine_inverse(), shadow_atlas != NULL && shadow_atlas->size > 0);
_render_list(render_list.elements, render_list.element_count, p_cam_transform, p_cam_projection, env_radiance_tex, false, false, false, i > 0, shadow_atlas != NULL);
}
}
@@ -4315,7 +4345,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const
} else {
for (int i = 0; i < state.directional_light_count; i++) {
directional_light = directional_lights[i];
- _setup_directional_light(i, p_cam_transform.affine_inverse(), shadow_atlas != NULL);
+ _setup_directional_light(i, p_cam_transform.affine_inverse(), shadow_atlas != NULL && shadow_atlas->size > 0);
_render_list(&render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, p_cam_transform, p_cam_projection, env_radiance_tex, false, true, false, i > 0, shadow_atlas != NULL);
}
}
@@ -5024,6 +5054,8 @@ void RasterizerSceneGLES3::initialize() {
}
state.debug_draw = VS::VIEWPORT_DEBUG_DRAW_DISABLED;
+
+ glFrontFace(GL_CW);
}
void RasterizerSceneGLES3::iteration() {
diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h
index 28a5cef0ee..69b43c7813 100644
--- a/drivers/gles3/rasterizer_scene_gles3.h
+++ b/drivers/gles3/rasterizer_scene_gles3.h
@@ -124,6 +124,7 @@ public:
float z_slope_scale;
float shadow_dual_paraboloid_render_zfar;
float shadow_dual_paraboloid_render_side;
+ float viewport_size[2];
float screen_pixel_size[2];
float shadow_atlas_pixel_size[2];
float shadow_directional_pixel_size[2];
@@ -143,7 +144,7 @@ public:
float fog_height_min;
float fog_height_max;
float fog_height_curve;
- uint8_t padding[8];
+ // make sure this struct is padded to be a multiple of 16 bytes for webgl
} ubo_data;
@@ -379,7 +380,9 @@ public:
float ssao_bias;
float ssao_light_affect;
Color ssao_color;
- bool ssao_filter;
+ VS::EnvironmentSSAOQuality ssao_quality;
+ float ssao_bilateral_sharpness;
+ VS::EnvironmentSSAOBlur ssao_filter;
bool glow_enabled;
int glow_levels;
@@ -456,7 +459,9 @@ public:
ssao_radius2 = 0.0;
ssao_bias = 0.01;
ssao_light_affect = 0;
- ssao_filter = true;
+ ssao_filter = VS::ENV_SSAO_BLUR_3x3;
+ ssao_quality = VS::ENV_SSAO_QUALITY_LOW;
+ ssao_bilateral_sharpness = 4;
tone_mapper = VS::ENV_TONE_MAPPER_LINEAR;
tone_mapper_exposure = 1.0;
@@ -532,7 +537,7 @@ public:
virtual void environment_set_fog(RID p_env, bool p_enable, float p_begin, float p_end, RID p_gradient_texture);
virtual void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_in, float p_fade_out, float p_depth_tolerance, bool p_roughness);
- virtual void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_radius2, float p_intensity2, float p_bias, float p_light_affect, const Color &p_color, bool p_blur);
+ virtual void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_radius2, float p_intensity2, float p_bias, float p_light_affect, const Color &p_color, VS::EnvironmentSSAOQuality p_quality, VS::EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness);
virtual void environment_set_tonemap(RID p_env, VS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale);
diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp
index 44a9909bd7..a41d84a2aa 100644
--- a/drivers/gles3/rasterizer_storage_gles3.cpp
+++ b/drivers/gles3/rasterizer_storage_gles3.cpp
@@ -2430,7 +2430,8 @@ void RasterizerStorageGLES3::_update_material(Material *material) {
if (material->shader && material->shader->mode == VS::SHADER_SPATIAL) {
- if (!material->shader->spatial.uses_alpha && material->shader->spatial.blend_mode == Shader::Spatial::BLEND_MODE_MIX) {
+ if (material->shader->spatial.blend_mode == Shader::Spatial::BLEND_MODE_MIX &&
+ (!material->shader->spatial.uses_alpha || (material->shader->spatial.uses_alpha && material->shader->spatial.depth_draw_mode == Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS))) {
can_cast_shadow = true;
}
@@ -2599,7 +2600,7 @@ RID RasterizerStorageGLES3::mesh_create() {
return mesh_owner.make_rid(mesh);
}
-void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh, uint32_t p_format, VS::PrimitiveType p_primitive, const PoolVector<uint8_t> &p_array, int p_vertex_count, const PoolVector<uint8_t> &p_index_array, int p_index_count, const Rect3 &p_aabb, const Vector<PoolVector<uint8_t> > &p_blend_shapes, const Vector<Rect3> &p_bone_aabbs) {
+void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh, uint32_t p_format, VS::PrimitiveType p_primitive, const PoolVector<uint8_t> &p_array, int p_vertex_count, const PoolVector<uint8_t> &p_index_array, int p_index_count, const AABB &p_aabb, const Vector<PoolVector<uint8_t> > &p_blend_shapes, const Vector<AABB> &p_bone_aabbs) {
PoolVector<uint8_t> array = p_array;
@@ -2865,7 +2866,7 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh, uint32_t p_format, VS:
glGenBuffers(1, &surface->vertex_id);
glBindBuffer(GL_ARRAY_BUFFER, surface->vertex_id);
- glBufferData(GL_ARRAY_BUFFER, array_size, vr.ptr(), GL_STATIC_DRAW);
+ glBufferData(GL_ARRAY_BUFFER, array_size, vr.ptr(), p_format & VS::ARRAY_FLAG_USE_DYNAMIC_UPDATE ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind
if (p_format & VS::ARRAY_FORMAT_INDEX) {
@@ -3103,6 +3104,22 @@ VS::BlendShapeMode RasterizerStorageGLES3::mesh_get_blend_shape_mode(RID p_mesh)
return mesh->blend_shape_mode;
}
+void RasterizerStorageGLES3::mesh_surface_update_region(RID p_mesh, int p_surface, int p_offset, const PoolVector<uint8_t> &p_data) {
+
+ Mesh *mesh = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND(!mesh);
+ ERR_FAIL_INDEX(p_surface, mesh->surfaces.size());
+
+ int total_size = p_data.size();
+ ERR_FAIL_COND(p_offset + total_size > mesh->surfaces[p_surface]->array_byte_size);
+
+ PoolVector<uint8_t>::Read r = p_data.read();
+
+ glBindBuffer(GL_ARRAY_BUFFER, mesh->surfaces[p_surface]->array_id);
+ glBufferSubData(GL_ARRAY_BUFFER, p_offset, total_size, r.ptr());
+ glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind
+}
+
void RasterizerStorageGLES3::mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) {
Mesh *mesh = mesh_owner.getornull(p_mesh);
@@ -3223,11 +3240,11 @@ VS::PrimitiveType RasterizerStorageGLES3::mesh_surface_get_primitive_type(RID p_
return mesh->surfaces[p_surface]->primitive;
}
-Rect3 RasterizerStorageGLES3::mesh_surface_get_aabb(RID p_mesh, int p_surface) const {
+AABB RasterizerStorageGLES3::mesh_surface_get_aabb(RID p_mesh, int p_surface) const {
const Mesh *mesh = mesh_owner.getornull(p_mesh);
- ERR_FAIL_COND_V(!mesh, Rect3());
- ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), Rect3());
+ ERR_FAIL_COND_V(!mesh, AABB());
+ ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), AABB());
return mesh->surfaces[p_surface]->aabb;
}
@@ -3262,11 +3279,11 @@ Vector<PoolVector<uint8_t> > RasterizerStorageGLES3::mesh_surface_get_blend_shap
return bsarr;
}
-Vector<Rect3> RasterizerStorageGLES3::mesh_surface_get_skeleton_aabb(RID p_mesh, int p_surface) const {
+Vector<AABB> RasterizerStorageGLES3::mesh_surface_get_skeleton_aabb(RID p_mesh, int p_surface) const {
const Mesh *mesh = mesh_owner.getornull(p_mesh);
- ERR_FAIL_COND_V(!mesh, Vector<Rect3>());
- ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), Vector<Rect3>());
+ ERR_FAIL_COND_V(!mesh, Vector<AABB>());
+ ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), Vector<AABB>());
return mesh->surfaces[p_surface]->skeleton_bone_aabb;
}
@@ -3320,7 +3337,7 @@ int RasterizerStorageGLES3::mesh_get_surface_count(RID p_mesh) const {
return mesh->surfaces.size();
}
-void RasterizerStorageGLES3::mesh_set_custom_aabb(RID p_mesh, const Rect3 &p_aabb) {
+void RasterizerStorageGLES3::mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) {
Mesh *mesh = mesh_owner.getornull(p_mesh);
ERR_FAIL_COND(!mesh);
@@ -3328,37 +3345,37 @@ void RasterizerStorageGLES3::mesh_set_custom_aabb(RID p_mesh, const Rect3 &p_aab
mesh->custom_aabb = p_aabb;
}
-Rect3 RasterizerStorageGLES3::mesh_get_custom_aabb(RID p_mesh) const {
+AABB RasterizerStorageGLES3::mesh_get_custom_aabb(RID p_mesh) const {
const Mesh *mesh = mesh_owner.getornull(p_mesh);
- ERR_FAIL_COND_V(!mesh, Rect3());
+ ERR_FAIL_COND_V(!mesh, AABB());
return mesh->custom_aabb;
}
-Rect3 RasterizerStorageGLES3::mesh_get_aabb(RID p_mesh, RID p_skeleton) const {
+AABB RasterizerStorageGLES3::mesh_get_aabb(RID p_mesh, RID p_skeleton) const {
Mesh *mesh = mesh_owner.get(p_mesh);
- ERR_FAIL_COND_V(!mesh, Rect3());
+ ERR_FAIL_COND_V(!mesh, AABB());
- if (mesh->custom_aabb != Rect3())
+ if (mesh->custom_aabb != AABB())
return mesh->custom_aabb;
Skeleton *sk = NULL;
if (p_skeleton.is_valid())
sk = skeleton_owner.get(p_skeleton);
- Rect3 aabb;
+ AABB aabb;
if (sk && sk->size != 0) {
for (int i = 0; i < mesh->surfaces.size(); i++) {
- Rect3 laabb;
+ AABB laabb;
if ((mesh->surfaces[i]->format & VS::ARRAY_FORMAT_BONES) && mesh->surfaces[i]->skeleton_bone_aabb.size()) {
int bs = mesh->surfaces[i]->skeleton_bone_aabb.size();
- const Rect3 *skbones = mesh->surfaces[i]->skeleton_bone_aabb.ptr();
+ const AABB *skbones = mesh->surfaces[i]->skeleton_bone_aabb.ptr();
const bool *skused = mesh->surfaces[i]->skeleton_bone_used.ptr();
int sbs = sk->size;
@@ -3384,7 +3401,7 @@ Rect3 RasterizerStorageGLES3::mesh_get_aabb(RID p_mesh, RID p_skeleton) const {
mtx.basis[1].y = texture[base_ofs + 1];
mtx.origin.y = texture[base_ofs + 3];
- Rect3 baabb = mtx.xform(skbones[j]);
+ AABB baabb = mtx.xform(skbones[j]);
if (first) {
laabb = baabb;
first = false;
@@ -3417,7 +3434,7 @@ Rect3 RasterizerStorageGLES3::mesh_get_aabb(RID p_mesh, RID p_skeleton) const {
mtx.basis[2].z = texture[base_ofs + 2];
mtx.origin.z = texture[base_ofs + 3];
- Rect3 baabb = mtx.xform(skbones[j]);
+ AABB baabb = mtx.xform(skbones[j]);
if (first) {
laabb = baabb;
first = false;
@@ -4011,10 +4028,10 @@ int RasterizerStorageGLES3::multimesh_get_visible_instances(RID p_multimesh) con
return multimesh->visible_instances;
}
-Rect3 RasterizerStorageGLES3::multimesh_get_aabb(RID p_multimesh) const {
+AABB RasterizerStorageGLES3::multimesh_get_aabb(RID p_multimesh) const {
MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
- ERR_FAIL_COND_V(!multimesh, Rect3());
+ ERR_FAIL_COND_V(!multimesh, AABB());
const_cast<RasterizerStorageGLES3 *>(this)->update_dirty_multimeshes(); //update pending AABBs
@@ -4036,7 +4053,7 @@ void RasterizerStorageGLES3::update_dirty_multimeshes() {
if (multimesh->size && multimesh->dirty_aabb) {
- Rect3 mesh_aabb;
+ AABB mesh_aabb;
if (multimesh->mesh.is_valid()) {
mesh_aabb = mesh_get_aabb(multimesh->mesh, RID());
@@ -4048,7 +4065,7 @@ void RasterizerStorageGLES3::update_dirty_multimeshes() {
int count = multimesh->data.size();
float *data = multimesh->data.ptr();
- Rect3 aabb;
+ AABB aabb;
if (multimesh->transform_format == VS::MULTIMESH_TRANSFORM_2D) {
@@ -4063,7 +4080,7 @@ void RasterizerStorageGLES3::update_dirty_multimeshes() {
xform.basis[1][1] = dataptr[5];
xform.origin[1] = dataptr[7];
- Rect3 laabb = xform.xform(mesh_aabb);
+ AABB laabb = xform.xform(mesh_aabb);
if (i == 0)
aabb = laabb;
else
@@ -4089,7 +4106,7 @@ void RasterizerStorageGLES3::update_dirty_multimeshes() {
xform.basis.elements[2][2] = dataptr[10];
xform.origin.z = dataptr[11];
- Rect3 laabb = xform.xform(mesh_aabb);
+ AABB laabb = xform.xform(mesh_aabb);
if (i == 0)
aabb = laabb;
else
@@ -4225,10 +4242,10 @@ void RasterizerStorageGLES3::immediate_clear(RID p_immediate) {
im->instance_change_notify();
}
-Rect3 RasterizerStorageGLES3::immediate_get_aabb(RID p_immediate) const {
+AABB RasterizerStorageGLES3::immediate_get_aabb(RID p_immediate) const {
Immediate *im = immediate_owner.get(p_immediate);
- ERR_FAIL_COND_V(!im, Rect3());
+ ERR_FAIL_COND_V(!im, AABB());
return im->aabb;
}
@@ -4449,6 +4466,7 @@ RID RasterizerStorageGLES3::light_create(VS::LightType p_type) {
light->type = p_type;
light->param[VS::LIGHT_PARAM_ENERGY] = 1.0;
+ light->param[VS::LIGHT_PARAM_INDIRECT_ENERGY] = 1.0;
light->param[VS::LIGHT_PARAM_SPECULAR] = 0.5;
light->param[VS::LIGHT_PARAM_RANGE] = 1.0;
light->param[VS::LIGHT_PARAM_SPOT_ANGLE] = 45;
@@ -4677,10 +4695,10 @@ uint64_t RasterizerStorageGLES3::light_get_version(RID p_light) const {
return light->version;
}
-Rect3 RasterizerStorageGLES3::light_get_aabb(RID p_light) const {
+AABB RasterizerStorageGLES3::light_get_aabb(RID p_light) const {
const Light *light = light_owner.getornull(p_light);
- ERR_FAIL_COND_V(!light, Rect3());
+ ERR_FAIL_COND_V(!light, AABB());
switch (light->type) {
@@ -4688,22 +4706,22 @@ Rect3 RasterizerStorageGLES3::light_get_aabb(RID p_light) const {
float len = light->param[VS::LIGHT_PARAM_RANGE];
float size = Math::tan(Math::deg2rad(light->param[VS::LIGHT_PARAM_SPOT_ANGLE])) * len;
- return Rect3(Vector3(-size, -size, -len), Vector3(size * 2, size * 2, len));
+ return AABB(Vector3(-size, -size, -len), Vector3(size * 2, size * 2, len));
} break;
case VS::LIGHT_OMNI: {
float r = light->param[VS::LIGHT_PARAM_RANGE];
- return Rect3(-Vector3(r, r, r), Vector3(r, r, r) * 2);
+ return AABB(-Vector3(r, r, r), Vector3(r, r, r) * 2);
} break;
case VS::LIGHT_DIRECTIONAL: {
- return Rect3();
+ return AABB();
} break;
default: {}
}
- ERR_FAIL_V(Rect3());
- return Rect3();
+ ERR_FAIL_V(AABB());
+ return AABB();
}
/* PROBE API */
@@ -4825,11 +4843,11 @@ void RasterizerStorageGLES3::reflection_probe_set_cull_mask(RID p_probe, uint32_
reflection_probe->instance_change_notify();
}
-Rect3 RasterizerStorageGLES3::reflection_probe_get_aabb(RID p_probe) const {
+AABB RasterizerStorageGLES3::reflection_probe_get_aabb(RID p_probe) const {
const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
- ERR_FAIL_COND_V(!reflection_probe, Rect3());
+ ERR_FAIL_COND_V(!reflection_probe, AABB());
- Rect3 aabb;
+ AABB aabb;
aabb.position = -reflection_probe->extents;
aabb.size = reflection_probe->extents * 2.0;
@@ -4886,7 +4904,7 @@ RID RasterizerStorageGLES3::gi_probe_create() {
GIProbe *gip = memnew(GIProbe);
- gip->bounds = Rect3(Vector3(), Vector3(1, 1, 1));
+ gip->bounds = AABB(Vector3(), Vector3(1, 1, 1));
gip->dynamic_range = 1.0;
gip->energy = 1.0;
gip->propagation = 1.0;
@@ -4900,7 +4918,7 @@ RID RasterizerStorageGLES3::gi_probe_create() {
return gi_probe_owner.make_rid(gip);
}
-void RasterizerStorageGLES3::gi_probe_set_bounds(RID p_probe, const Rect3 &p_bounds) {
+void RasterizerStorageGLES3::gi_probe_set_bounds(RID p_probe, const AABB &p_bounds) {
GIProbe *gip = gi_probe_owner.getornull(p_probe);
ERR_FAIL_COND(!gip);
@@ -4909,10 +4927,10 @@ void RasterizerStorageGLES3::gi_probe_set_bounds(RID p_probe, const Rect3 &p_bou
gip->version++;
gip->instance_change_notify();
}
-Rect3 RasterizerStorageGLES3::gi_probe_get_bounds(RID p_probe) const {
+AABB RasterizerStorageGLES3::gi_probe_get_bounds(RID p_probe) const {
const GIProbe *gip = gi_probe_owner.getornull(p_probe);
- ERR_FAIL_COND_V(!gip, Rect3());
+ ERR_FAIL_COND_V(!gip, AABB());
return gip->bounds;
}
@@ -5321,7 +5339,7 @@ void RasterizerStorageGLES3::_particles_update_histories(Particles *particles) {
particles->clear = true;
}
-void RasterizerStorageGLES3::particles_set_custom_aabb(RID p_particles, const Rect3 &p_aabb) {
+void RasterizerStorageGLES3::particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) {
Particles *particles = particles_owner.getornull(p_particles);
ERR_FAIL_COND(!particles);
@@ -5412,15 +5430,15 @@ void RasterizerStorageGLES3::particles_request_process(RID p_particles) {
}
}
-Rect3 RasterizerStorageGLES3::particles_get_current_aabb(RID p_particles) {
+AABB RasterizerStorageGLES3::particles_get_current_aabb(RID p_particles) {
const Particles *particles = particles_owner.getornull(p_particles);
- ERR_FAIL_COND_V(!particles, Rect3());
+ ERR_FAIL_COND_V(!particles, AABB());
glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffers[0]);
float *data = (float *)glMapBufferRange(GL_ARRAY_BUFFER, 0, particles->amount * 16 * 6, GL_MAP_READ_BIT);
- Rect3 aabb;
+ AABB aabb;
Transform inv = particles->emission_transform.affine_inverse();
@@ -5442,7 +5460,7 @@ Rect3 RasterizerStorageGLES3::particles_get_current_aabb(RID p_particles) {
float longest_axis = 0;
for (int i = 0; i < particles->draw_passes.size(); i++) {
if (particles->draw_passes[i].is_valid()) {
- Rect3 maabb = mesh_get_aabb(particles->draw_passes[i], RID());
+ AABB maabb = mesh_get_aabb(particles->draw_passes[i], RID());
longest_axis = MAX(maabb.get_longest_axis_size(), longest_axis);
}
}
@@ -5452,10 +5470,10 @@ Rect3 RasterizerStorageGLES3::particles_get_current_aabb(RID p_particles) {
return aabb;
}
-Rect3 RasterizerStorageGLES3::particles_get_aabb(RID p_particles) const {
+AABB RasterizerStorageGLES3::particles_get_aabb(RID p_particles) const {
const Particles *particles = particles_owner.getornull(p_particles);
- ERR_FAIL_COND_V(!particles, Rect3());
+ ERR_FAIL_COND_V(!particles, AABB());
return particles->custom_aabb;
}
@@ -7010,14 +7028,22 @@ void RasterizerStorageGLES3::initialize() {
glBindBuffer(GL_ARRAY_BUFFER, resources.quadie);
{
const float qv[16] = {
- -1, -1,
- 0, 0,
- -1, 1,
- 0, 1,
- 1, 1,
- 1, 1,
- 1, -1,
- 1, 0,
+ -1,
+ -1,
+ 0,
+ 0,
+ -1,
+ 1,
+ 0,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ -1,
+ 1,
+ 0,
};
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 16, qv, GL_STATIC_DRAW);
diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h
index 6abc22b643..8aa8235b42 100644
--- a/drivers/gles3/rasterizer_storage_gles3.h
+++ b/drivers/gles3/rasterizer_storage_gles3.h
@@ -592,7 +592,7 @@ public:
GLuint instancing_array_wireframe_id;
int index_wireframe_len;
- Vector<Rect3> skeleton_bone_aabb;
+ Vector<AABB> skeleton_bone_aabb;
Vector<bool> skeleton_bone_used;
//bool packed;
@@ -604,7 +604,7 @@ public:
Vector<BlendShape> blend_shapes;
- Rect3 aabb;
+ AABB aabb;
int array_len;
int index_array_len;
@@ -659,7 +659,7 @@ public:
Vector<Surface *> surfaces;
int blend_shape_count;
VS::BlendShapeMode blend_shape_mode;
- Rect3 custom_aabb;
+ AABB custom_aabb;
mutable uint64_t last_pass;
SelfList<MultiMesh>::List multimeshes;
@@ -684,7 +684,7 @@ public:
virtual RID mesh_create();
- virtual void mesh_add_surface(RID p_mesh, uint32_t p_format, VS::PrimitiveType p_primitive, const PoolVector<uint8_t> &p_array, int p_vertex_count, const PoolVector<uint8_t> &p_index_array, int p_index_count, const Rect3 &p_aabb, const Vector<PoolVector<uint8_t> > &p_blend_shapes = Vector<PoolVector<uint8_t> >(), const Vector<Rect3> &p_bone_aabbs = Vector<Rect3>());
+ virtual void mesh_add_surface(RID p_mesh, uint32_t p_format, VS::PrimitiveType p_primitive, const PoolVector<uint8_t> &p_array, int p_vertex_count, const PoolVector<uint8_t> &p_index_array, int p_index_count, const AABB &p_aabb, const Vector<PoolVector<uint8_t> > &p_blend_shapes = Vector<PoolVector<uint8_t> >(), const Vector<AABB> &p_bone_aabbs = Vector<AABB>());
virtual void mesh_set_blend_shape_count(RID p_mesh, int p_amount);
virtual int mesh_get_blend_shape_count(RID p_mesh) const;
@@ -692,6 +692,8 @@ public:
virtual void mesh_set_blend_shape_mode(RID p_mesh, VS::BlendShapeMode p_mode);
virtual VS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const;
+ virtual void mesh_surface_update_region(RID p_mesh, int p_surface, int p_offset, const PoolVector<uint8_t> &p_data);
+
virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material);
virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const;
@@ -704,17 +706,17 @@ public:
virtual uint32_t mesh_surface_get_format(RID p_mesh, int p_surface) const;
virtual VS::PrimitiveType mesh_surface_get_primitive_type(RID p_mesh, int p_surface) const;
- virtual Rect3 mesh_surface_get_aabb(RID p_mesh, int p_surface) const;
+ virtual AABB mesh_surface_get_aabb(RID p_mesh, int p_surface) const;
virtual Vector<PoolVector<uint8_t> > mesh_surface_get_blend_shapes(RID p_mesh, int p_surface) const;
- virtual Vector<Rect3> mesh_surface_get_skeleton_aabb(RID p_mesh, int p_surface) const;
+ virtual Vector<AABB> mesh_surface_get_skeleton_aabb(RID p_mesh, int p_surface) const;
virtual void mesh_remove_surface(RID p_mesh, int p_surface);
virtual int mesh_get_surface_count(RID p_mesh) const;
- virtual void mesh_set_custom_aabb(RID p_mesh, const Rect3 &p_aabb);
- virtual Rect3 mesh_get_custom_aabb(RID p_mesh) const;
+ virtual void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb);
+ virtual AABB mesh_get_custom_aabb(RID p_mesh) const;
- virtual Rect3 mesh_get_aabb(RID p_mesh, RID p_skeleton) const;
+ virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton) const;
virtual void mesh_clear(RID p_mesh);
void mesh_render_blend_shapes(Surface *s, float *p_weights);
@@ -727,7 +729,7 @@ public:
VS::MultimeshTransformFormat transform_format;
VS::MultimeshColorFormat color_format;
Vector<float> data;
- Rect3 aabb;
+ AABB aabb;
SelfList<MultiMesh> update_list;
SelfList<MultiMesh> mesh_list;
GLuint buffer;
@@ -778,7 +780,7 @@ public:
virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible);
virtual int multimesh_get_visible_instances(RID p_multimesh) const;
- virtual Rect3 multimesh_get_aabb(RID p_multimesh) const;
+ virtual AABB multimesh_get_aabb(RID p_multimesh) const;
/* IMMEDIATE API */
@@ -799,7 +801,7 @@ public:
List<Chunk> chunks;
bool building;
int mask;
- Rect3 aabb;
+ AABB aabb;
Immediate() {
type = GEOMETRY_IMMEDIATE;
@@ -828,7 +830,7 @@ public:
virtual void immediate_clear(RID p_immediate);
virtual void immediate_set_material(RID p_immediate, RID p_material);
virtual RID immediate_get_material(RID p_immediate) const;
- virtual Rect3 immediate_get_aabb(RID p_immediate) const;
+ virtual AABB immediate_get_aabb(RID p_immediate) const;
/* SKELETON API */
@@ -916,7 +918,7 @@ public:
virtual float light_get_param(RID p_light, VS::LightParam p_param);
virtual Color light_get_color(RID p_light);
- virtual Rect3 light_get_aabb(RID p_light) const;
+ virtual AABB light_get_aabb(RID p_light) const;
virtual uint64_t light_get_version(RID p_light) const;
/* PROBE API */
@@ -954,7 +956,7 @@ public:
virtual void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable);
virtual void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers);
- virtual Rect3 reflection_probe_get_aabb(RID p_probe) const;
+ virtual AABB reflection_probe_get_aabb(RID p_probe) const;
virtual VS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const;
virtual uint32_t reflection_probe_get_cull_mask(RID p_probe) const;
@@ -967,7 +969,7 @@ public:
struct GIProbe : public Instantiable {
- Rect3 bounds;
+ AABB bounds;
Transform to_cell;
float cell_size;
@@ -988,8 +990,8 @@ public:
virtual RID gi_probe_create();
- virtual void gi_probe_set_bounds(RID p_probe, const Rect3 &p_bounds);
- virtual Rect3 gi_probe_get_bounds(RID p_probe) const;
+ virtual void gi_probe_set_bounds(RID p_probe, const AABB &p_bounds);
+ virtual AABB gi_probe_get_bounds(RID p_probe) const;
virtual void gi_probe_set_cell_size(RID p_probe, float p_size);
virtual float gi_probe_get_cell_size(RID p_probe) const;
@@ -1056,7 +1058,7 @@ public:
float explosiveness;
float randomness;
bool restart_request;
- Rect3 custom_aabb;
+ AABB custom_aabb;
bool use_local_coords;
RID process_material;
@@ -1111,7 +1113,7 @@ public:
restart_request = false;
- custom_aabb = Rect3(Vector3(-4, -4, -4), Vector3(8, 8, 8));
+ custom_aabb = AABB(Vector3(-4, -4, -4), Vector3(8, 8, 8));
draw_order = VS::PARTICLES_DRAW_ORDER_INDEX;
particle_buffers[0] = 0;
@@ -1153,7 +1155,7 @@ public:
virtual void particles_set_pre_process_time(RID p_particles, float p_time);
virtual void particles_set_explosiveness_ratio(RID p_particles, float p_ratio);
virtual void particles_set_randomness_ratio(RID p_particles, float p_ratio);
- virtual void particles_set_custom_aabb(RID p_particles, const Rect3 &p_aabb);
+ virtual void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb);
virtual void particles_set_speed_scale(RID p_particles, float p_scale);
virtual void particles_set_use_local_coordinates(RID p_particles, bool p_enable);
virtual void particles_set_process_material(RID p_particles, RID p_material);
@@ -1167,8 +1169,8 @@ public:
virtual void particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh);
virtual void particles_request_process(RID p_particles);
- virtual Rect3 particles_get_current_aabb(RID p_particles);
- virtual Rect3 particles_get_aabb(RID p_particles) const;
+ virtual AABB particles_get_current_aabb(RID p_particles);
+ virtual AABB particles_get_aabb(RID p_particles) const;
virtual void _particles_update_histories(Particles *particles);
diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp
index 91159e3381..325df8e4f1 100644
--- a/drivers/gles3/shader_compiler_gles3.cpp
+++ b/drivers/gles3/shader_compiler_gles3.cpp
@@ -741,6 +741,7 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() {
actions[VS::SHADER_CANVAS_ITEM].usage_defines["NORMAL"] = "#define NORMAL_USED\n";
actions[VS::SHADER_CANVAS_ITEM].usage_defines["NORMALMAP"] = "#define NORMALMAP_USED\n";
actions[VS::SHADER_CANVAS_ITEM].usage_defines["SHADOW_COLOR"] = "#define SHADOW_COLOR_USED\n";
+ actions[VS::SHADER_CANVAS_ITEM].usage_defines["LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n";
actions[VS::SHADER_CANVAS_ITEM].render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n";
@@ -766,10 +767,10 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() {
//builtins
actions[VS::SHADER_SPATIAL].renames["TIME"] = "time";
- //actions[VS::SHADER_SPATIAL].renames["VIEWPORT_SIZE"]=ShaderLanguage::TYPE_VEC2;
+ actions[VS::SHADER_SPATIAL].renames["VIEWPORT_SIZE"] = "viewport_size";
actions[VS::SHADER_SPATIAL].renames["FRAGCOORD"] = "gl_FragCoord";
- actions[VS::SHADER_SPATIAL].renames["FRONT_FACING"] = "gl_FrotFacing";
+ actions[VS::SHADER_SPATIAL].renames["FRONT_FACING"] = "gl_FrontFacing";
actions[VS::SHADER_SPATIAL].renames["NORMALMAP"] = "normalmap";
actions[VS::SHADER_SPATIAL].renames["NORMALMAP_DEPTH"] = "normaldepth";
actions[VS::SHADER_SPATIAL].renames["ALBEDO"] = "albedo";
@@ -828,6 +829,9 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() {
actions[VS::SHADER_SPATIAL].usage_defines["SCREEN_TEXTURE"] = "#define SCREEN_TEXTURE_USED\n";
actions[VS::SHADER_SPATIAL].usage_defines["SCREEN_UV"] = "#define SCREEN_UV_USED\n";
+ actions[VS::SHADER_SPATIAL].usage_defines["DIFFUSE_LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n";
+ actions[VS::SHADER_SPATIAL].usage_defines["SPECULAR_LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n";
+
actions[VS::SHADER_SPATIAL].renames["SSS_STRENGTH"] = "sss_strength";
actions[VS::SHADER_SPATIAL].render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n";
@@ -838,6 +842,7 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() {
actions[VS::SHADER_SPATIAL].render_mode_defines["diffuse_lambert_wrap"] = "#define DIFFUSE_LAMBERT_WRAP\n";
actions[VS::SHADER_SPATIAL].render_mode_defines["diffuse_toon"] = "#define DIFFUSE_TOON\n";
+ actions[VS::SHADER_SPATIAL].render_mode_defines["specular_schlick_ggx"] = "#define SPECULAR_SCHLICK_GGX\n";
actions[VS::SHADER_SPATIAL].render_mode_defines["specular_blinn"] = "#define SPECULAR_BLINN\n";
actions[VS::SHADER_SPATIAL].render_mode_defines["specular_phong"] = "#define SPECULAR_PHONG\n";
actions[VS::SHADER_SPATIAL].render_mode_defines["specular_toon"] = "#define SPECULAR_TOON\n";
diff --git a/drivers/gles3/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl
index 731d6968ce..4bbb18ce42 100644
--- a/drivers/gles3/shaders/canvas.glsl
+++ b/drivers/gles3/shaders/canvas.glsl
@@ -381,8 +381,7 @@ void main() {
if (clip_rect_uv) {
- vec2 half_texpixel = color_texpixel_size * 0.5;
- uv = clamp(uv,src_rect.xy+half_texpixel,src_rect.xy+abs(src_rect.zw)-color_texpixel_size);
+ uv = clamp(uv,src_rect.xy,src_rect.xy+abs(src_rect.zw));
}
#endif
diff --git a/drivers/gles3/shaders/copy.glsl b/drivers/gles3/shaders/copy.glsl
index d33193ee50..743fe122d1 100644
--- a/drivers/gles3/shaders/copy.glsl
+++ b/drivers/gles3/shaders/copy.glsl
@@ -27,6 +27,8 @@ void main() {
#if defined(USE_CUBEMAP) || defined(USE_PANORAMA)
cube_interp = cube_in;
+#elif defined(USE_ASYM_PANO)
+ uv_interp = vertex_attrib.xy;
#else
uv_interp = uv_in;
#ifdef V_FLIP
@@ -59,6 +61,11 @@ in vec3 cube_interp;
in vec2 uv_interp;
#endif
+#ifdef USE_ASYM_PANO
+uniform highp mat4 pano_transform;
+uniform highp vec4 asym_proj;
+#endif
+
#ifdef USE_CUBEMAP
uniform samplerCube source_cube; //texunit:0
#else
@@ -70,7 +77,7 @@ uniform sampler2D source; //texunit:0
uniform float multiplier;
#endif
-#ifdef USE_PANORAMA
+#if defined(USE_PANORAMA) || defined(USE_ASYM_PANO)
vec4 texturePanorama(vec3 normal,sampler2D pano ) {
@@ -122,6 +129,21 @@ void main() {
vec4 color = texturePanorama( normalize(cube_interp), source );
+#elif defined(USE_ASYM_PANO)
+
+ // When an assymetrical projection matrix is used (applicable for stereoscopic rendering i.e. VR) we need to do this calculation per fragment to get a perspective correct result.
+ // Note that we're ignoring the x-offset for IPD, with Z sufficiently in the distance it becomes neglectible, as a result we could probably just set cube_normal.z to -1.
+ // The Matrix[2][0] (= asym_proj.x) and Matrix[2][1] (= asym_proj.z) values are what provide the right shift in the image.
+
+ vec3 cube_normal;
+ cube_normal.z = -1000000.0;
+ cube_normal.x = (cube_normal.z * (-uv_interp.x - asym_proj.x)) / asym_proj.y;
+ cube_normal.y = (cube_normal.z * (-uv_interp.y - asym_proj.z)) / asym_proj.a;
+ cube_normal = mat3(pano_transform) * cube_normal;
+ cube_normal.z = -cube_normal.z;
+
+ vec4 color = texturePanorama( normalize(cube_normal.xyz), source );
+
#elif defined(USE_CUBEMAP)
vec4 color = texture( source_cube, normalize(cube_interp) );
diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl
index 341a5bf2c7..9880663143 100644
--- a/drivers/gles3/shaders/scene.glsl
+++ b/drivers/gles3/shaders/scene.glsl
@@ -80,6 +80,7 @@ layout(std140) uniform SceneData { //ubo:0
highp float shadow_dual_paraboloid_render_zfar;
highp float shadow_dual_paraboloid_render_side;
+ highp vec2 viewport_size;
highp vec2 screen_pixel_size;
highp vec2 shadow_atlas_pixel_size;
highp vec2 directional_shadow_pixel_size;
@@ -566,6 +567,7 @@ in vec3 normal_interp;
uniform bool no_ambient_light;
+
#ifdef USE_RADIANCE_MAP
@@ -663,6 +665,7 @@ layout(std140) uniform SceneData {
highp float shadow_dual_paraboloid_render_zfar;
highp float shadow_dual_paraboloid_render_side;
+ highp vec2 viewport_size;
highp vec2 screen_pixel_size;
highp vec2 shadow_atlas_pixel_size;
highp vec2 directional_shadow_pixel_size;
@@ -865,11 +868,57 @@ float contact_shadow_compute(vec3 pos, vec3 dir, float max_distance) {
#endif
-// GGX Specular
-// Source: http://www.filmicworlds.com/images/ggx-opt/optimized-ggx.hlsl
-float G1V(float dotNV, float k)
-{
- return 1.0 / (dotNV * (1.0 - k) + k);
+
+// This returns the G_GGX function divided by 2 cos_theta_m, where in practice cos_theta_m is either N.L or N.V.
+// We're dividing this factor off because the overall term we'll end up looks like
+// (see, for example, the first unnumbered equation in B. Burley, "Physically Based Shading at Disney", SIGGRAPH 2012):
+//
+// F(L.V) D(N.H) G(N.L) G(N.V) / (4 N.L N.V)
+//
+// We're basically regouping this as
+//
+// F(L.V) D(N.H) [G(N.L)/(2 N.L)] [G(N.V) / (2 N.V)]
+//
+// and thus, this function implements the [G(N.m)/(2 N.m)] part with m = L or V.
+//
+// The contents of the D and G (G1) functions (GGX) are taken from
+// E. Heitz, "Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs", J. Comp. Graph. Tech. 3 (2) (2014).
+// Eqns 71-72 and 85-86 (see also Eqns 43 and 80).
+
+float G_GGX_2cos(float cos_theta_m, float alpha) {
+ // Schlick's approximation
+ // C. Schlick, "An Inexpensive BRDF Model for Physically-based Rendering", Computer Graphics Forum. 13 (3): 233 (1994)
+ // Eq. (19), although see Heitz (2014) the about the problems with his derivation.
+ // It nevertheless approximates GGX well with k = alpha/2.
+ float k = 0.5*alpha;
+ return 0.5 / (cos_theta_m * (1.0 - k) + k);
+
+ // float cos2 = cos_theta_m*cos_theta_m;
+ // float sin2 = (1.0-cos2);
+ // return 1.0 /( cos_theta_m + sqrt(cos2 + alpha*alpha*sin2) );
+}
+
+float D_GGX(float cos_theta_m, float alpha) {
+ float alpha2 = alpha*alpha;
+ float d = 1.0 + (alpha2-1.0)*cos_theta_m*cos_theta_m;
+ return alpha2/(M_PI * d * d);
+}
+
+float G_GGX_anisotropic_2cos(float cos_theta_m, float alpha_x, float alpha_y, float cos_phi, float sin_phi) {
+ float cos2 = cos_theta_m * cos_theta_m;
+ float sin2 = (1.0-cos2);
+ float s_x = alpha_x * cos_phi;
+ float s_y = alpha_y * sin_phi;
+ return 1.0 / (cos_theta_m + sqrt(cos2 + (s_x*s_x + s_y*s_y)*sin2 ));
+}
+
+float D_GGX_anisotropic(float cos_theta_m, float alpha_x, float alpha_y, float cos_phi, float sin_phi) {
+ float cos2 = cos_theta_m * cos_theta_m;
+ float sin2 = (1.0-cos2);
+ float r_x = cos_phi/alpha_x;
+ float r_y = sin_phi/alpha_y;
+ float d = cos2 + sin2*(r_x * r_x + r_y * r_y);
+ return 1.0 / (M_PI * alpha_x * alpha_y * d * d );
}
@@ -894,7 +943,7 @@ vec3 metallic_to_specular_color(float metallic, float specular, vec3 albedo) {
return mix(vec3(dielectric), albedo, metallic); // TODO: reference?
}
-void light_compute(vec3 N, vec3 L, vec3 V, vec3 B, vec3 T, vec3 light_color, vec3 attenuation, vec3 diffuse_color, vec3 transmission, float specular_blob_intensity, float roughness, float rim, float rim_tint, float clearcoat, float clearcoat_gloss, float anisotropy, inout vec3 diffuse_light, inout vec3 specular_light) {
+void light_compute(vec3 N, vec3 L, vec3 V, vec3 B, vec3 T, vec3 light_color, vec3 attenuation, vec3 diffuse_color, vec3 transmission, float specular_blob_intensity, float roughness, float metallic, float rim, float rim_tint, float clearcoat, float clearcoat_gloss, float anisotropy, inout vec3 diffuse_light, inout vec3 specular_light) {
#if defined(USE_LIGHT_SHADER_CODE)
//light is written by the light shader
@@ -913,80 +962,82 @@ LIGHT_SHADER_CODE
float NdotV = dot(N, V);
float cNdotV = max(NdotV, 0.0);
+ if (metallic < 1.0) {
#if defined(DIFFUSE_OREN_NAYAR)
- vec3 diffuse_brdf_NL;
+ vec3 diffuse_brdf_NL;
#else
- float diffuse_brdf_NL; // BRDF times N.L for calculating diffuse radiance
+ float diffuse_brdf_NL; // BRDF times N.L for calculating diffuse radiance
#endif
#if defined(DIFFUSE_LAMBERT_WRAP)
- //energy conserving lambert wrap shader
- diffuse_brdf_NL = max(0.0,(NdotL + roughness) / ((1.0 + roughness) * (1.0 + roughness)));
+ //energy conserving lambert wrap shader
+ diffuse_brdf_NL = max(0.0,(NdotL + roughness) / ((1.0 + roughness) * (1.0 + roughness)));
#elif defined(DIFFUSE_OREN_NAYAR)
- {
- // see http://mimosa-pudica.net/improved-oren-nayar.html
- float LdotV = dot(L, V);
+ {
+ // see http://mimosa-pudica.net/improved-oren-nayar.html
+ float LdotV = dot(L, V);
- float s = LdotV - NdotL * NdotV;
- float t = mix(1.0, max(NdotL, NdotV), step(0.0, s));
+ float s = LdotV - NdotL * NdotV;
+ float t = mix(1.0, max(NdotL, NdotV), step(0.0, s));
- float sigma2 = roughness * roughness; // TODO: this needs checking
- vec3 A = 1.0 + sigma2 * (- 0.5 / (sigma2 + 0.33) + 0.17*diffuse_color / (sigma2 + 0.13) );
- float B = 0.45 * sigma2 / (sigma2 + 0.09);
+ float sigma2 = roughness * roughness; // TODO: this needs checking
+ vec3 A = 1.0 + sigma2 * (- 0.5 / (sigma2 + 0.33) + 0.17*diffuse_color / (sigma2 + 0.13) );
+ float B = 0.45 * sigma2 / (sigma2 + 0.09);
- diffuse_brdf_NL = cNdotL * (A + vec3(B) * s / t) * (1.0 / M_PI);
- }
+ diffuse_brdf_NL = cNdotL * (A + vec3(B) * s / t) * (1.0 / M_PI);
+ }
#elif defined(DIFFUSE_TOON)
- diffuse_brdf_NL = smoothstep(-roughness,max(roughness,0.01),NdotL);
+ diffuse_brdf_NL = smoothstep(-roughness,max(roughness,0.01),NdotL);
#elif defined(DIFFUSE_BURLEY)
- {
+ {
- vec3 H = normalize(V + L);
- float cLdotH = max(0.0,dot(L, H));
+ vec3 H = normalize(V + L);
+ float cLdotH = max(0.0,dot(L, H));
- float FD90 = 0.5 + 2.0 * cLdotH * cLdotH * roughness;
- float FdV = 1.0 + (FD90 - 1.0) * SchlickFresnel(cNdotV);
- float FdL = 1.0 + (FD90 - 1.0) * SchlickFresnel(cNdotL);
- diffuse_brdf_NL = (1.0 / M_PI) * FdV * FdL * cNdotL;
-/*
- float energyBias = mix(roughness, 0.0, 0.5);
- float energyFactor = mix(roughness, 1.0, 1.0 / 1.51);
- float fd90 = energyBias + 2.0 * VoH * VoH * roughness;
- float f0 = 1.0;
- float lightScatter = f0 + (fd90 - f0) * pow(1.0 - cNdotL, 5.0);
- float viewScatter = f0 + (fd90 - f0) * pow(1.0 - cNdotV, 5.0);
-
- diffuse_brdf_NL = lightScatter * viewScatter * energyFactor;*/
- }
+ float FD90 = 0.5 + 2.0 * cLdotH * cLdotH * roughness;
+ float FdV = 1.0 + (FD90 - 1.0) * SchlickFresnel(cNdotV);
+ float FdL = 1.0 + (FD90 - 1.0) * SchlickFresnel(cNdotL);
+ diffuse_brdf_NL = (1.0 / M_PI) * FdV * FdL * cNdotL;
+ /*
+ float energyBias = mix(roughness, 0.0, 0.5);
+ float energyFactor = mix(roughness, 1.0, 1.0 / 1.51);
+ float fd90 = energyBias + 2.0 * VoH * VoH * roughness;
+ float f0 = 1.0;
+ float lightScatter = f0 + (fd90 - f0) * pow(1.0 - cNdotL, 5.0);
+ float viewScatter = f0 + (fd90 - f0) * pow(1.0 - cNdotV, 5.0);
+
+ diffuse_brdf_NL = lightScatter * viewScatter * energyFactor;*/
+ }
#else
- //lambert
- diffuse_brdf_NL = cNdotL * (1.0 / M_PI);
+ //lambert
+ diffuse_brdf_NL = cNdotL * (1.0 / M_PI);
#endif
#if defined(TRANSMISSION_USED)
- diffuse_light += light_color * diffuse_color * mix(vec3(diffuse_brdf_NL), vec3(M_PI), transmission) * attenuation;
+ diffuse_light += light_color * diffuse_color * mix(vec3(diffuse_brdf_NL), vec3(M_PI), transmission) * attenuation;
#else
- diffuse_light += light_color * diffuse_color * diffuse_brdf_NL * attenuation;
+ diffuse_light += light_color * diffuse_color * diffuse_brdf_NL * attenuation;
#endif
#if defined(LIGHT_USE_RIM)
- float rim_light = pow(1.0-cNdotV, (1.0-roughness)*16.0);
- diffuse_light += rim_light * rim * mix(vec3(1.0),diffuse_color,rim_tint) * light_color;
+ float rim_light = pow(1.0-cNdotV, (1.0-roughness)*16.0);
+ diffuse_light += rim_light * rim * mix(vec3(1.0),diffuse_color,rim_tint) * light_color;
#endif
+ }
- if (roughness > 0.0) {
+ if (roughness > 0.0) { // FIXME: roughness == 0 should not disable specular light entirely
// D
@@ -1019,14 +1070,13 @@ LIGHT_SHADER_CODE
#elif defined(SPECULAR_SCHLICK_GGX)
// shlick+ggx as default
- float alpha = roughness * roughness;
vec3 H = normalize(V + L);
float cNdotH = max(dot(N,H), 0.0);
float cLdotH = max(dot(L,H), 0.0);
-#if defined(LIGHT_USE_ANISOTROPY)
+# if defined(LIGHT_USE_ANISOTROPY)
float aspect = sqrt(1.0-anisotropy*0.9);
float rx = roughness/aspect;
@@ -1035,44 +1085,43 @@ LIGHT_SHADER_CODE
float ay = ry*ry;
float XdotH = dot( T, H );
float YdotH = dot( B, H );
- float denom = XdotH*XdotH / (ax*ax) + YdotH*YdotH / (ay*ay) + cNdotH*cNdotH;
- float D = 1.0 / ( M_PI * ax*ay * denom*denom );
+ float D = D_GGX_anisotropic(cNdotH, ax, ay, XdotH, YdotH);
+ float G = G_GGX_anisotropic_2cos(cNdotL, ax, ay, XdotH, YdotH) * G_GGX_anisotropic_2cos(cNdotV, ax, ay, XdotH, YdotH);
-#else
- float alphaSqr = alpha * alpha;
- float denom = cNdotH * cNdotH * (alphaSqr - 1.0) + 1.0;
- float D = alphaSqr / (M_PI * denom * denom);
-#endif
+# else
+ float alpha = roughness * roughness;
+ float D = D_GGX(cNdotH, alpha);
+ float G = G_GGX_2cos(cNdotL, alpha) * G_GGX_2cos(cNdotV, alpha);
+# endif
// F
float F0 = 1.0; // FIXME
float cLdotH5 = SchlickFresnel(cLdotH);
float F = mix(cLdotH5, 1.0, F0);
- // V
- float k = alpha / 2.0f;
- float vis = G1V(cNdotL, k) * G1V(cNdotV, k);
+ float specular_brdf_NL = cNdotL * D * F * G;
- float speci = cNdotL * D * F * vis;
-
- specular_light += speci * light_color * specular_blob_intensity * attenuation;
+ specular_light += specular_brdf_NL * light_color * specular_blob_intensity * attenuation;
#endif
#if defined(LIGHT_USE_CLEARCOAT)
-
+ if (clearcoat_gloss > 0.0) {
# if !defined(SPECULAR_SCHLICK_GGX) && !defined(SPECULAR_BLINN)
- vec3 H = normalize(V + L);
+ vec3 H = normalize(V + L);
# endif
# if !defined(SPECULAR_SCHLICK_GGX)
- float cNdotH = max(dot(N,H), 0.0);
- float cLdotH = max(dot(L,H), 0.0);
- float cLdotH5 = SchlickFresnel(cLdotH);
+ float cNdotH = max(dot(N,H), 0.0);
+ float cLdotH = max(dot(L,H), 0.0);
+ float cLdotH5 = SchlickFresnel(cLdotH);
#endif
- float Dr = GTR1(cNdotH, mix(.1, .001, clearcoat_gloss));
- float Fr = mix(.04, 1.0, cLdotH5);
- float Gr = G1V(cNdotL, .25) * G1V(cNdotV, .25);
+ float Dr = GTR1(cNdotH, mix(.1, .001, clearcoat_gloss));
+ float Fr = mix(.04, 1.0, cLdotH5);
+ float Gr = G_GGX_2cos(cNdotL, .25) * G_GGX_2cos(cNdotV, .25);
- specular_light += .25*clearcoat*Gr*Fr*Dr;
+ float specular_brdf_NL = 0.25 * clearcoat * Gr * Fr * Dr * cNdotL;
+
+ specular_light += specular_brdf_NL * light_color * specular_blob_intensity * attenuation;
+ }
#endif
}
@@ -1154,7 +1203,7 @@ vec3 light_transmittance(float translucency,vec3 light_vec, vec3 normal, vec3 po
}
#endif
-void light_process_omni(int idx, vec3 vertex, vec3 eye_vec,vec3 normal,vec3 binormal, vec3 tangent, vec3 albedo, vec3 transmission, float roughness, float rim, float rim_tint, float clearcoat, float clearcoat_gloss, float anisotropy, float p_blob_intensity, inout vec3 diffuse_light, inout vec3 specular_light) {
+void light_process_omni(int idx, vec3 vertex, vec3 eye_vec,vec3 normal,vec3 binormal, vec3 tangent, vec3 albedo, vec3 transmission, float roughness, float metallic, float rim, float rim_tint, float clearcoat, float clearcoat_gloss, float anisotropy, float p_blob_intensity, inout vec3 diffuse_light, inout vec3 specular_light) {
vec3 light_rel_vec = omni_lights[idx].light_pos_inv_radius.xyz-vertex;
float light_length = length( light_rel_vec );
@@ -1208,11 +1257,11 @@ void light_process_omni(int idx, vec3 vertex, vec3 eye_vec,vec3 normal,vec3 bino
light_attenuation*=mix(omni_lights[idx].shadow_color_contact.rgb,vec3(1.0),shadow);
}
- light_compute(normal,normalize(light_rel_vec),eye_vec,binormal,tangent,omni_lights[idx].light_color_energy.rgb,light_attenuation,albedo,transmission,omni_lights[idx].light_params.z*p_blob_intensity,roughness,rim,rim_tint,clearcoat,clearcoat_gloss,anisotropy,diffuse_light,specular_light);
+ light_compute(normal,normalize(light_rel_vec),eye_vec,binormal,tangent,omni_lights[idx].light_color_energy.rgb,light_attenuation,albedo,transmission,omni_lights[idx].light_params.z*p_blob_intensity,roughness,metallic,rim,rim_tint,clearcoat,clearcoat_gloss,anisotropy,diffuse_light,specular_light);
}
-void light_process_spot(int idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 binormal, vec3 tangent,vec3 albedo, vec3 transmission,float roughness, float rim,float rim_tint, float clearcoat, float clearcoat_gloss,float anisotropy,float p_blob_intensity, inout vec3 diffuse_light, inout vec3 specular_light) {
+void light_process_spot(int idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 binormal, vec3 tangent,vec3 albedo, vec3 transmission,float roughness, float metallic, float rim, float rim_tint, float clearcoat, float clearcoat_gloss,float anisotropy,float p_blob_intensity, inout vec3 diffuse_light, inout vec3 specular_light) {
vec3 light_rel_vec = spot_lights[idx].light_pos_inv_radius.xyz-vertex;
float light_length = length( light_rel_vec );
@@ -1242,7 +1291,7 @@ void light_process_spot(int idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 bi
light_attenuation*=mix(spot_lights[idx].shadow_color_contact.rgb,vec3(1.0),shadow);
}
- light_compute(normal,normalize(light_rel_vec),eye_vec,binormal,tangent,spot_lights[idx].light_color_energy.rgb,light_attenuation,albedo,transmission,spot_lights[idx].light_params.z*p_blob_intensity,roughness,rim,rim_tint,clearcoat,clearcoat_gloss,anisotropy,diffuse_light,specular_light);
+ light_compute(normal,normalize(light_rel_vec),eye_vec,binormal,tangent,spot_lights[idx].light_color_energy.rgb,light_attenuation,albedo,transmission,spot_lights[idx].light_params.z*p_blob_intensity,roughness,metallic,rim,rim_tint,clearcoat,clearcoat_gloss,anisotropy,diffuse_light,specular_light);
}
@@ -1875,7 +1924,7 @@ FRAGMENT_SHADER_CODE
specular_light*=mix(vec3(1.0),light_attenuation,specular_light_interp.a);
#else
- light_compute(normal,-light_direction_attenuation.xyz,eye_vec,binormal,tangent,light_color_energy.rgb,light_attenuation,albedo,transmission,light_params.z*specular_blob_intensity,roughness,rim,rim_tint,clearcoat,clearcoat_gloss,anisotropy,diffuse_light,specular_light);
+ light_compute(normal,-light_direction_attenuation.xyz,eye_vec,binormal,tangent,light_color_energy.rgb,light_attenuation,albedo,transmission,light_params.z*specular_blob_intensity,roughness,metallic,rim,rim_tint,clearcoat,clearcoat_gloss,anisotropy,diffuse_light,specular_light);
#endif
@@ -1913,11 +1962,11 @@ FRAGMENT_SHADER_CODE
#else
for(int i=0;i<omni_light_count;i++) {
- light_process_omni(omni_light_indices[i],vertex,eye_vec,normal,binormal,tangent,albedo,transmission,roughness,rim,rim_tint,clearcoat,clearcoat_gloss,anisotropy,specular_blob_intensity,diffuse_light,specular_light);
+ light_process_omni(omni_light_indices[i],vertex,eye_vec,normal,binormal,tangent,albedo,transmission,roughness,metallic,rim,rim_tint,clearcoat,clearcoat_gloss,anisotropy,specular_blob_intensity,diffuse_light,specular_light);
}
for(int i=0;i<spot_light_count;i++) {
- light_process_spot(spot_light_indices[i],vertex,eye_vec,normal,binormal,tangent,albedo,transmission,roughness,rim,rim_tint,clearcoat,clearcoat_gloss,anisotropy,specular_blob_intensity,diffuse_light,specular_light);
+ light_process_spot(spot_light_indices[i],vertex,eye_vec,normal,binormal,tangent,albedo,transmission,roughness,metallic,rim,rim_tint,clearcoat,clearcoat_gloss,anisotropy,specular_blob_intensity,diffuse_light,specular_light);
}
#endif //USE_VERTEX_LIGHTING
@@ -1944,7 +1993,7 @@ FRAGMENT_SHADER_CODE
//energy conservation
- diffuse_light *= 1.0-metallic; // TODO: avoid diffuse and ambient light calculations when metallic == 1
+ diffuse_light *= 1.0-metallic; // TODO: avoid all diffuse and ambient light calculations when metallic == 1 up to this point
ambient_light *= 1.0-metallic;
@@ -2063,5 +2112,3 @@ FRAGMENT_SHADER_CODE
}
-
-
diff --git a/drivers/gles3/shaders/ssao.glsl b/drivers/gles3/shaders/ssao.glsl
index c668e63745..219f0957e0 100644
--- a/drivers/gles3/shaders/ssao.glsl
+++ b/drivers/gles3/shaders/ssao.glsl
@@ -13,8 +13,24 @@ void main() {
#define TWO_PI 6.283185307179586476925286766559
+#ifdef SSAO_QUALITY_HIGH
+
+#define NUM_SAMPLES (80)
+
+#endif
+
+#ifdef SSAO_QUALITY_LOW
+
#define NUM_SAMPLES (15)
+#endif
+
+#if !defined(SSAO_QUALITY_LOW) && !defined(SSAO_QUALITY_HIGH)
+
+#define NUM_SAMPLES (40)
+
+#endif
+
// If using depth mip levels, the log of the maximum pixel offset before we need to switch to a lower
// miplevel to maintain reasonable spatial locality in the cache
// If this number is too small (< 3), too many taps will land in the same pixel, and we'll get bad variance that manifests as flashing.
@@ -212,12 +228,12 @@ void main() {
//visibility=-C.z/camera_z_far;
//return;
-
- //vec3 n_C = texelFetch(source_normal,ssC,0).rgb * 2.0 - 1.0;
-
+#if 0
+ vec3 n_C = texelFetch(source_normal,ssC,0).rgb * 2.0 - 1.0;
+#else
vec3 n_C = reconstructCSFaceNormal(C);
n_C = -n_C;
-
+#endif
// Hash function used in the HPG12 AlchemyAO paper
float randomPatternRotationAngle = mod(float((3 * ssC.x ^ ssC.y + ssC.x * ssC.y) * 10), TWO_PI);
diff --git a/drivers/gles3/shaders/ssao_blur.glsl b/drivers/gles3/shaders/ssao_blur.glsl
index c7c978dc37..472dc21acf 100644
--- a/drivers/gles3/shaders/ssao_blur.glsl
+++ b/drivers/gles3/shaders/ssao_blur.glsl
@@ -15,6 +15,7 @@ void main() {
uniform sampler2D source_ssao; //texunit:0
uniform sampler2D source_depth; //texunit:1
+uniform sampler2D source_normal; //texunit:3
layout(location = 0) out float visibility;
@@ -24,7 +25,7 @@ layout(location = 0) out float visibility;
// Tunable Parameters:
/** Increase to make depth edges crisper. Decrease to reduce flicker. */
-#define EDGE_SHARPNESS (4.0)
+uniform float edge_sharpness;
/** Step in 2-pixel intervals since we already blurred against neighbors in the
first AO pass. This constant can be increased while R decreases to improve
@@ -34,7 +35,8 @@ layout(location = 0) out float visibility;
unobjectionable after shading was applied but eliminated most temporal incoherence
from using small numbers of sample taps.
*/
-#define SCALE (3)
+
+uniform int filter_scale;
/** Filter radius in pixels. This will be multiplied by SCALE. */
#define R (4)
@@ -63,13 +65,14 @@ void main() {
ivec2 ssC = ivec2(gl_FragCoord.xy);
float depth = texelFetch(source_depth, ssC, 0).r;
+ //vec3 normal = texelFetch(source_normal,ssC,0).rgb * 2.0 - 1.0;
depth = depth * 2.0 - 1.0;
depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - depth * (camera_z_far - camera_z_near));
float depth_divide = 1.0 / camera_z_far;
- depth*=depth_divide;
+// depth*=depth_divide;
/*
if (depth > camera_z_far*0.999) {
@@ -92,20 +95,23 @@ void main() {
// so the IF statement has no runtime cost
if (r != 0) {
- ivec2 ppos = ssC + axis * (r * SCALE);
+ ivec2 ppos = ssC + axis * (r * filter_scale);
float value = texelFetch(source_ssao, clamp(ppos,ivec2(0),clamp_limit), 0).r;
- float temp_depth = texelFetch(source_depth, clamp(ssC,ivec2(0),clamp_limit), 0).r;
+ ivec2 rpos = clamp(ppos,ivec2(0),clamp_limit);
+ float temp_depth = texelFetch(source_depth, rpos, 0).r;
+ //vec3 temp_normal = texelFetch(source_normal, rpos, 0).rgb * 2.0 - 1.0;
temp_depth = temp_depth * 2.0 - 1.0;
temp_depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - temp_depth * (camera_z_far - camera_z_near));
- temp_depth *= depth_divide;
+// temp_depth *= depth_divide;
// spatial domain: offset gaussian tap
float weight = 0.3 + gaussian[abs(r)];
+ //weight *= max(0.0,dot(temp_normal,normal));
// range domain (the "bilateral" weight). As depth difference increases, decrease weight.
weight *= max(0.0, 1.0
- - (EDGE_SHARPNESS * 2000.0) * abs(temp_depth - depth)
+ - edge_sharpness * abs(temp_depth - depth)
);
sum += value * weight;
diff --git a/drivers/gles3/shaders/subsurf_scattering.glsl b/drivers/gles3/shaders/subsurf_scattering.glsl
index 20c3b7473f..fc66d66198 100644
--- a/drivers/gles3/shaders/subsurf_scattering.glsl
+++ b/drivers/gles3/shaders/subsurf_scattering.glsl
@@ -82,18 +82,18 @@ QUALIFIER vec2 kernel[17] = vec2[](
const int kernel_size=11;
-QUALIFIER vec4 kernel[11] = vec4[](
- vec4(0.560479, 0.0),
- vec4(0.00471691, -2.0),
- vec4(0.0192831, -1.28),
- vec4(0.03639, -0.72),
- vec4(0.0821904, -0.32),
- vec4(0.0771802, -0.08),
- vec4(0.0771802, 0.08),
- vec4(0.0821904, 0.32),
- vec4(0.03639, 0.72),
- vec4(0.0192831, 1.28),
- vec4(0.00471691,2.0)
+QUALIFIER vec2 kernel[11] = vec2[](
+ vec2(0.560479, 0.0),
+ vec2(0.00471691, -2.0),
+ vec2(0.0192831, -1.28),
+ vec2(0.03639, -0.72),
+ vec2(0.0821904, -0.32),
+ vec2(0.0771802, -0.08),
+ vec2(0.0771802, 0.08),
+ vec2(0.0821904, 0.32),
+ vec2(0.03639, 0.72),
+ vec2(0.0192831, 1.28),
+ vec2(0.00471691,2.0)
);
#endif //USE_11_SAMPLES
@@ -190,4 +190,3 @@ void main() {
frag_color = base_color;
}
}
-
diff --git a/drivers/gles3/shaders/tonemap.glsl b/drivers/gles3/shaders/tonemap.glsl
index 73dec4f90c..2f671158b2 100644
--- a/drivers/gles3/shaders/tonemap.glsl
+++ b/drivers/gles3/shaders/tonemap.glsl
@@ -175,12 +175,9 @@ vec3 tonemap_reindhart(vec3 color,float white) {
return ( color * ( 1.0 + ( color / ( white) ) ) ) / ( 1.0 + color );
}
-
void main() {
- ivec2 coord = ivec2(gl_FragCoord.xy);
- vec3 color = texelFetch(source,coord,0).rgb;
-
+ vec4 color = textureLod(source, uv_interp, 0.0);
#ifdef USE_AUTO_EXPOSURE
@@ -324,5 +321,3 @@ void main() {
frag_color=vec4(color.rgb,1.0);
}
-
-
diff --git a/drivers/unix/SCsub b/drivers/unix/SCsub
index c560e1289f..ada8255580 100644
--- a/drivers/unix/SCsub
+++ b/drivers/unix/SCsub
@@ -2,16 +2,6 @@
Import('env')
-g_set_p = '#ifdef UNIX_ENABLED\n'
-g_set_p += '#include "os_unix.h"\n'
-g_set_p += 'String OS_Unix::get_global_settings_path() const {\n'
-g_set_p += '\treturn "' + env["unix_global_settings_path"] + '";\n'
-g_set_p += '}\n'
-g_set_p += '#endif'
-f = open("os_unix_global_settings_path.gen.cpp", "w")
-f.write(g_set_p)
-f.close()
-
env.add_source_files(env.drivers_sources, "*.cpp")
env["check_c_headers"] = [ [ "mntent.h", "HAVE_MNTENT" ] ]
diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp
index 29fe73f170..0d102902e8 100644
--- a/drivers/unix/os_unix.cpp
+++ b/drivers/unix/os_unix.cpp
@@ -133,13 +133,6 @@ void OS_Unix::initialize_core() {
}
}
-void OS_Unix::initialize_logger() {
- Vector<Logger *> loggers;
- loggers.push_back(memnew(UnixTerminalLogger));
- loggers.push_back(memnew(RotatedFileLogger("user://logs/log.txt")));
- _set_logger(memnew(CompositeLogger(loggers)));
-}
-
void OS_Unix::finalize_core() {
}
@@ -285,7 +278,7 @@ uint64_t OS_Unix::get_ticks_usec() const {
return longtime;
}
-Error OS_Unix::execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, String *r_pipe, int *r_exitcode) {
+Error OS_Unix::execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, String *r_pipe, int *r_exitcode, bool read_stderr) {
if (p_blocking && r_pipe) {
@@ -297,7 +290,11 @@ Error OS_Unix::execute(const String &p_path, const List<String> &p_arguments, bo
argss += String(" \"") + p_arguments[i] + "\"";
}
- argss += " 2>/dev/null"; //silence stderr
+ if (read_stderr) {
+ argss += " 2>&1"; // Read stderr too
+ } else {
+ argss += " 2>/dev/null"; //silence stderr
+ }
FILE *f = popen(argss.utf8().get_data(), "r");
ERR_FAIL_COND_V(!f, ERR_CANT_OPEN);
@@ -339,7 +336,7 @@ Error OS_Unix::execute(const String &p_path, const List<String> &p_arguments, bo
execvp(getprogname(), &args[0]);
}
#else
- execv(p_path.utf8().get_data(), &args[0]);
+ execvp(p_path.utf8().get_data(), &args[0]);
#endif
// still alive? something failed..
fprintf(stderr, "**ERROR** OS_Unix::execute - Could not create child process while executing: %s\n", p_path.utf8().get_data());
@@ -448,32 +445,21 @@ int OS_Unix::get_processor_count() const {
return sysconf(_SC_NPROCESSORS_CONF);
}
-String OS_Unix::get_data_dir() const {
-
- String an = get_safe_application_name();
- if (an != "") {
-
- if (has_environment("HOME")) {
+String OS_Unix::get_user_data_dir() const {
- bool use_godot = ProjectSettings::get_singleton()->get("application/config/use_shared_user_dir");
- if (use_godot)
- return get_environment("HOME") + "/.godot/app_userdata/" + an;
- else
- return get_environment("HOME") + "/." + an;
+ String appname = get_safe_application_name();
+ if (appname != "") {
+ bool use_godot_dir = ProjectSettings::get_singleton()->get("application/config/use_shared_user_dir");
+ if (use_godot_dir) {
+ return get_data_path().plus_file(get_godot_dir_name()).plus_file("app_userdata").plus_file(appname);
+ } else {
+ return get_data_path().plus_file(appname);
}
}
return ProjectSettings::get_singleton()->get_resource_path();
}
-String OS_Unix::get_installed_templates_path() const {
- String p = get_global_settings_path();
- if (p != "")
- return p + "/templates/";
- else
- return "";
-}
-
String OS_Unix::get_executable_path() const {
#ifdef __linux__
@@ -548,4 +534,10 @@ void UnixTerminalLogger::log_error(const char *p_function, const char *p_file, i
UnixTerminalLogger::~UnixTerminalLogger() {}
+OS_Unix::OS_Unix() {
+ Vector<Logger *> loggers;
+ loggers.push_back(memnew(UnixTerminalLogger));
+ _set_logger(memnew(CompositeLogger(loggers)));
+}
+
#endif
diff --git a/drivers/unix/os_unix.h b/drivers/unix/os_unix.h
index 1cc44c0ffd..5b3fb824f0 100644
--- a/drivers/unix/os_unix.h
+++ b/drivers/unix/os_unix.h
@@ -49,12 +49,10 @@ protected:
//virtual int get_video_driver_count() const;
//virtual const char * get_video_driver_name(int p_driver) const;
- //virtual VideoMode get_default_video_mode() const;
virtual int get_audio_driver_count() const;
virtual const char *get_audio_driver_name(int p_driver) const;
- virtual void initialize_logger();
virtual void initialize_core();
virtual int unix_initialize_audio(int p_audio_driver);
//virtual void initialize(int p_video_driver,int p_audio_driver);
@@ -63,9 +61,9 @@ protected:
String stdin_buf;
- String get_global_settings_path() const;
-
public:
+ OS_Unix();
+
virtual void alert(const String &p_alert, const String &p_title = "ALERT!");
virtual String get_stdin_string(bool p_block);
@@ -97,7 +95,7 @@ public:
virtual void delay_usec(uint32_t p_usec) const;
virtual uint64_t get_ticks_usec() const;
- virtual Error execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id = NULL, String *r_pipe = NULL, int *r_exitcode = NULL);
+ virtual Error execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id = NULL, String *r_pipe = NULL, int *r_exitcode = NULL, bool read_stderr = false);
virtual Error kill(const ProcessID &p_pid);
virtual int get_process_id() const;
@@ -109,11 +107,8 @@ public:
virtual void debug_break();
- virtual String get_installed_templates_path() const;
virtual String get_executable_path() const;
- virtual String get_data_dir() const;
-
- //virtual void run( MainLoop * p_main_loop );
+ virtual String get_user_data_dir() const;
};
class UnixTerminalLogger : public StdLogger {
diff --git a/drivers/wasapi/audio_driver_wasapi.cpp b/drivers/wasapi/audio_driver_wasapi.cpp
index eb86491dec..0671ee408e 100644
--- a/drivers/wasapi/audio_driver_wasapi.cpp
+++ b/drivers/wasapi/audio_driver_wasapi.cpp
@@ -39,7 +39,7 @@ const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator);
const IID IID_IAudioClient = __uuidof(IAudioClient);
const IID IID_IAudioRenderClient = __uuidof(IAudioRenderClient);
-Error AudioDriverWASAPI::init_device() {
+Error AudioDriverWASAPI::init_device(bool reinit) {
WAVEFORMATEX *pwfex;
IMMDeviceEnumerator *enumerator = NULL;
@@ -51,10 +51,24 @@ Error AudioDriverWASAPI::init_device() {
ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN);
hr = enumerator->GetDefaultAudioEndpoint(eRender, eConsole, &device);
- ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN);
+ if (reinit) {
+ // In case we're trying to re-initialize the device prevent throwing this error on the console,
+ // otherwise if there is currently no devie available this will spam the console.
+ if (hr != S_OK) {
+ return ERR_CANT_OPEN;
+ }
+ } else {
+ ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN);
+ }
hr = device->Activate(IID_IAudioClient, CLSCTX_ALL, NULL, (void **)&audio_client);
- ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN);
+ if (reinit) {
+ if (hr != S_OK) {
+ return ERR_CANT_OPEN;
+ }
+ } else {
+ ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN);
+ }
hr = audio_client->GetMixFormat(&pwfex);
ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN);
@@ -152,7 +166,9 @@ Error AudioDriverWASAPI::finish_device() {
Error AudioDriverWASAPI::init() {
Error err = init_device();
- ERR_FAIL_COND_V(err != OK, err);
+ if (err != OK) {
+ ERR_PRINT("WASAPI: init_device error");
+ }
active = false;
exit_thread = false;
@@ -209,7 +225,7 @@ void AudioDriverWASAPI::thread_func(void *p_udata) {
unsigned int left_frames = ad->buffer_frames;
unsigned int buffer_idx = 0;
- while (left_frames > 0) {
+ while (left_frames > 0 && ad->audio_client) {
WaitForSingleObject(ad->event, 1000);
UINT32 cur_frames;
@@ -271,9 +287,9 @@ void AudioDriverWASAPI::thread_func(void *p_udata) {
} else if (hr == AUDCLNT_E_DEVICE_INVALIDATED) {
// Device is not valid anymore, reopen it
- Error err = ad->reopen();
+ Error err = ad->finish_device();
if (err != OK) {
- ad->exit_thread = true;
+ ERR_PRINT("WASAPI: finish_device error");
} else {
// We reopened the device and samples_in may have resized, so invalidate the current left_frames
left_frames = 0;
@@ -285,9 +301,9 @@ void AudioDriverWASAPI::thread_func(void *p_udata) {
} else if (hr == AUDCLNT_E_DEVICE_INVALIDATED) {
// Device is not valid anymore, reopen it
- Error err = ad->reopen();
+ Error err = ad->finish_device();
if (err != OK) {
- ad->exit_thread = true;
+ ERR_PRINT("WASAPI: finish_device error");
} else {
// We reopened the device and samples_in may have resized, so invalidate the current left_frames
left_frames = 0;
@@ -296,6 +312,13 @@ void AudioDriverWASAPI::thread_func(void *p_udata) {
ERR_PRINT("WASAPI: GetCurrentPadding error");
}
}
+
+ if (!ad->audio_client) {
+ Error err = ad->init_device(true);
+ if (err == OK) {
+ ad->start();
+ }
+ }
}
ad->thread_exited = true;
@@ -303,11 +326,13 @@ void AudioDriverWASAPI::thread_func(void *p_udata) {
void AudioDriverWASAPI::start() {
- HRESULT hr = audio_client->Start();
- if (hr != S_OK) {
- ERR_PRINT("WASAPI: Start failed");
- } else {
- active = true;
+ if (audio_client) {
+ HRESULT hr = audio_client->Start();
+ if (hr != S_OK) {
+ ERR_PRINT("WASAPI: Start failed");
+ } else {
+ active = true;
+ }
}
}
diff --git a/drivers/wasapi/audio_driver_wasapi.h b/drivers/wasapi/audio_driver_wasapi.h
index fab8ab3250..87a2db724c 100644
--- a/drivers/wasapi/audio_driver_wasapi.h
+++ b/drivers/wasapi/audio_driver_wasapi.h
@@ -64,7 +64,7 @@ class AudioDriverWASAPI : public AudioDriver {
static void thread_func(void *p_udata);
- Error init_device();
+ Error init_device(bool reinit = false);
Error finish_device();
Error reopen();
diff --git a/drivers/windows/dir_access_windows.cpp b/drivers/windows/dir_access_windows.cpp
index 8d6e78dbee..0bc4201ba3 100644
--- a/drivers/windows/dir_access_windows.cpp
+++ b/drivers/windows/dir_access_windows.cpp
@@ -164,7 +164,7 @@ Error DirAccessWindows::make_dir(String p_dir) {
p_dir = fix_path(p_dir);
if (p_dir.is_rel_path())
- p_dir = get_current_dir().plus_file(p_dir);
+ p_dir = current_dir.plus_file(p_dir);
p_dir = p_dir.replace("/", "\\");
diff --git a/editor/SCsub b/editor/SCsub
index e44b4e4bb2..75ec422bd5 100644
--- a/editor/SCsub
+++ b/editor/SCsub
@@ -21,11 +21,11 @@ def make_certs_header(target, source, env):
g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n")
g.write("#ifndef _CERTS_RAW_H\n")
g.write("#define _CERTS_RAW_H\n")
- g.write("static const int _certs_compressed_size=" + str(len(buf)) + ";\n")
- g.write("static const int _certs_uncompressed_size=" + str(decomp_size) + ";\n")
- g.write("static const unsigned char _certs_compressed[]={\n")
+ g.write("static const int _certs_compressed_size = " + str(len(buf)) + ";\n")
+ g.write("static const int _certs_uncompressed_size = " + str(decomp_size) + ";\n")
+ g.write("static const unsigned char _certs_compressed[] = {\n")
for i in range(len(buf)):
- g.write(byte_to_str(buf[i]) + ",\n")
+ g.write("\t" + byte_to_str(buf[i]) + ",\n")
g.write("};\n")
g.write("#endif")
@@ -39,9 +39,11 @@ def make_doc_header(target, source, env):
docend = ""
for s in source:
src = s.srcnode().abspath
+ if not src.endswith(".xml"):
+ continue
f = open_utf8(src, "r")
content = f.read()
- buf+=content
+ buf += content
buf = encode_utf8(docbegin + buf + docend)
decomp_size = len(buf)
@@ -51,11 +53,11 @@ def make_doc_header(target, source, env):
g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n")
g.write("#ifndef _DOC_DATA_RAW_H\n")
g.write("#define _DOC_DATA_RAW_H\n")
- g.write("static const int _doc_data_compressed_size=" + str(len(buf)) + ";\n")
- g.write("static const int _doc_data_uncompressed_size=" + str(decomp_size) + ";\n")
- g.write("static const unsigned char _doc_data_compressed[]={\n")
+ g.write("static const int _doc_data_compressed_size = " + str(len(buf)) + ";\n")
+ g.write("static const int _doc_data_uncompressed_size = " + str(decomp_size) + ";\n")
+ g.write("static const unsigned char _doc_data_compressed[] = {\n")
for i in range(len(buf)):
- g.write(byte_to_str(buf[i]) + ",\n")
+ g.write("\t" + byte_to_str(buf[i]) + ",\n")
g.write("};\n")
g.write("#endif")
@@ -80,10 +82,10 @@ def make_fonts_header(target, source, env):
name = os.path.splitext(os.path.basename(source[i].srcnode().abspath))[0]
- g.write("static const int _font_" + name + "_size=" + str(len(buf)) + ";\n")
- g.write("static const unsigned char _font_" + name + "[]={\n")
+ g.write("static const int _font_" + name + "_size = " + str(len(buf)) + ";\n")
+ g.write("static const unsigned char _font_" + name + "[] = {\n")
for i in range(len(buf)):
- g.write(byte_to_str(buf[i]) + ",\n")
+ g.write("\t" + byte_to_str(buf[i]) + ",\n")
g.write("};\n")
@@ -114,11 +116,9 @@ def make_translations_header(target, source, env):
buf = zlib.compress(buf)
name = os.path.splitext(os.path.basename(sorted_paths[i]))[0]
- #g.write("static const int _translation_"+name+"_compressed_size="+str(len(buf))+";\n")
- #g.write("static const int _translation_"+name+"_uncompressed_size="+str(decomp_size)+";\n")
- g.write("static const unsigned char _translation_" + name + "_compressed[]={\n")
+ g.write("static const unsigned char _translation_" + name + "_compressed[] = {\n")
for i in range(len(buf)):
- g.write(byte_to_str(buf[i]) + ",\n")
+ g.write("\t" + byte_to_str(buf[i]) + ",\n")
g.write("};\n")
@@ -130,10 +130,10 @@ def make_translations_header(target, source, env):
g.write("\tint uncomp_size;\n")
g.write("\tconst unsigned char* data;\n")
g.write("};\n\n")
- g.write("static EditorTranslationList _editor_translations[]={\n")
+ g.write("static EditorTranslationList _editor_translations[] = {\n")
for x in xl_names:
- g.write("\t{ \"" + x[0] + "\", " + str(x[1]) + ", " + str(x[2]) + ",_translation_" + x[0] + "_compressed},\n")
- g.write("\t{NULL,0,0,NULL}\n")
+ g.write("\t{ \"" + x[0] + "\", " + str(x[1]) + ", " + str(x[2]) + ", _translation_" + x[0] + "_compressed},\n")
+ g.write("\t{NULL, 0, 0, NULL}\n")
g.write("};\n")
g.write("#endif")
@@ -237,7 +237,7 @@ def make_license_header(target, source, env):
g.write("static const char *about_license =")
for line in f:
- escaped_string = escape_string(line.strip().replace("\"", "\\\""))
+ escaped_string = escape_string(line.strip())
g.write("\n\t\"" + escaped_string + "\\n\"")
g.write(";\n")
@@ -323,12 +323,12 @@ def make_license_header(target, source, env):
for k in j[0].split("\n"):
if file_body != "":
file_body += "\\n\"\n"
- escaped_string = escape_string(k.strip().replace("\"", "\\\""))
+ escaped_string = escape_string(k.strip())
file_body += "\t\"" + escaped_string
for k in j[1].split("\n"):
if copyright_body != "":
copyright_body += "\\n\"\n"
- escaped_string = escape_string(k.strip().replace("\"", "\\\""))
+ escaped_string = escape_string(k.strip())
copyright_body += "\t\"" + escaped_string
about_tp_file += "\t" + file_body + "\",\n"
@@ -343,7 +343,7 @@ def make_license_header(target, source, env):
for j in i[1].split("\n"):
if body != "":
body += "\\n\"\n"
- escaped_string = escape_string(j.strip().replace("\"", "\\\""))
+ escaped_string = escape_string(j.strip())
body += "\t\"" + escaped_string
about_license_name += "\t\"" + i[0] + "\",\n"
@@ -390,13 +390,13 @@ def make_license_header(target, source, env):
def _make_doc_data_class_path(to_path):
g = open_utf8(os.path.join(to_path,"doc_data_class_path.gen.h"), "w")
- g.write("static const int _doc_data_class_path_count="+str(len(env.doc_class_path))+";\n")
+ g.write("static const int _doc_data_class_path_count = " + str(len(env.doc_class_path)) + ";\n")
g.write("struct _DocDataClassPath { const char* name; const char* path; };\n")
- g.write("static const _DocDataClassPath _doc_data_class_paths["+str(len(env.doc_class_path)+1)+"]={\n");
- for c in env.doc_class_path:
- g.write("{\""+c+"\",\""+env.doc_class_path[c]+"\"},\n")
- g.write("{NULL,NULL}\n")
+ g.write("static const _DocDataClassPath _doc_data_class_paths[" + str(len(env.doc_class_path) + 1) + "] = {\n");
+ for c in sorted(env.doc_class_path):
+ g.write("\t{\"" + c + "\", \"" + env.doc_class_path[c] + "\"},\n")
+ g.write("\t{NULL, NULL}\n")
g.write("};\n")
@@ -415,13 +415,23 @@ if env['tools']:
f.close()
# API documentation
- docs=[]
- print("cdir is: "+env.Dir('#').abspath)
- for f in os.listdir(os.path.join(env.Dir('#').abspath,"doc/classes")):
- docs.append("#doc/classes/"+f)
+ docs = []
+ doc_dirs = ["doc/classes"]
+
+ for p in env.doc_class_path.values():
+ if p not in doc_dirs:
+ doc_dirs.append(p)
+
+ for d in doc_dirs:
+ try:
+ for f in os.listdir(os.path.join(env.Dir('#').abspath, d)):
+ docs.append("#" + os.path.join(d, f))
+ except OSError:
+ pass
- _make_doc_data_class_path(os.path.join(env.Dir('#').abspath,"editor/doc"))
+ _make_doc_data_class_path(os.path.join(env.Dir('#').abspath, "editor/doc"))
+ docs = sorted(docs)
env.Depends("#editor/doc_data_compressed.gen.h", docs)
env.Command("#editor/doc_data_compressed.gen.h", docs, make_doc_header)
# Certificates
diff --git a/editor/animation_editor.cpp b/editor/animation_editor.cpp
index b832b993bb..ae304ed0bc 100644
--- a/editor/animation_editor.cpp
+++ b/editor/animation_editor.cpp
@@ -64,6 +64,8 @@ private:
float transition;
Mode mode;
+ LineEdit *value_edit;
+
void _notification(int p_what) {
if (p_what == NOTIFICATION_DRAW) {
@@ -144,14 +146,11 @@ private:
}
}
- String txt = String::num(exp, 2);
if (mode == MODE_DISABLED) {
- txt = TTR("Disabled");
+ f->draw(ci, Point2(5, 5 + f->get_ascent()), TTR("Disabled"), color);
} else if (mode == MODE_MULTIPLE) {
- txt += " - " + TTR("All Selection");
+ f->draw(ci, Point2(5, 5 + f->get_ascent() + value_edit->get_size().height), TTR("All Selection"), color);
}
-
- f->draw(ci, Point2(10, 10 + f->get_ascent()), txt, color);
}
}
@@ -163,6 +162,8 @@ private:
if (mode == MODE_DISABLED)
return;
+ value_edit->release_focus();
+
float rel = mm->get_relative().x;
if (rel == 0)
return;
@@ -187,24 +188,28 @@ private:
if (sg)
val = -val;
- transition = val;
- update();
- //emit_signal("variant_changed");
- emit_signal("transition_changed", transition);
+ force_transition(val);
}
}
+ void _edit_value_changed(const String &p_value_str) {
+
+ force_transition(p_value_str.to_float());
+ }
+
public:
static void _bind_methods() {
//ClassDB::bind_method("_update_obj",&AnimationKeyEdit::_update_obj);
ClassDB::bind_method("_gui_input", &AnimationCurveEdit::_gui_input);
+ ClassDB::bind_method("_edit_value_changed", &AnimationCurveEdit::_edit_value_changed);
ADD_SIGNAL(MethodInfo("transition_changed"));
}
void set_mode(Mode p_mode) {
mode = p_mode;
+ value_edit->set_visible(mode != MODE_DISABLED);
update();
}
@@ -218,7 +223,8 @@ public:
}
void set_transition(float p_transition) {
- transition = p_transition;
+ transition = Math::stepify(p_transition, 0.01);
+ value_edit->set_text(String::num(transition));
update();
}
@@ -229,9 +235,8 @@ public:
void force_transition(float p_value) {
if (mode == MODE_DISABLED)
return;
- transition = p_value;
+ set_transition(p_value);
emit_signal("transition_changed", p_value);
- update();
}
AnimationCurveEdit() {
@@ -239,6 +244,11 @@ public:
transition = 1.0;
set_default_cursor_shape(CURSOR_HSPLIT);
mode = MODE_DISABLED;
+
+ value_edit = memnew(LineEdit);
+ value_edit->hide();
+ value_edit->connect("text_entered", this, "_edit_value_changed");
+ add_child(value_edit);
}
};
@@ -1101,7 +1111,7 @@ void AnimationKeyEditor::_track_editor_draw() {
Color select_color = color;
select_color.a = 0.1;
Color invalid_path_color = get_color("error_color", "Editor");
- Color track_select_color = get_color("accent", "Editor");
+ Color track_select_color = get_color("highlighted_font_color", "Editor");
Ref<Texture> remove_icon = get_icon("Remove", "EditorIcons");
Ref<Texture> move_up_icon = get_icon("MoveUp", "EditorIcons");
@@ -1358,7 +1368,7 @@ void AnimationKeyEditor::_track_editor_draw() {
icon_ofs.x-=hsep;
*/
- track_ofs[0] = size.width - icon_ofs.x;
+ track_ofs[0] = size.width - icon_ofs.x + ofs.x;
icon_ofs.x -= down_icon->get_width();
te->draw_texture(down_icon, icon_ofs - Size2(0, 4 * EDSCALE));
@@ -1370,7 +1380,7 @@ void AnimationKeyEditor::_track_editor_draw() {
icon_ofs.x -= hsep;
te->draw_line(Point2(icon_ofs.x, ofs.y + y), Point2(icon_ofs.x, ofs.y + y + h), sepcolor);
- track_ofs[1] = size.width - icon_ofs.x;
+ track_ofs[1] = size.width - icon_ofs.x + ofs.x;
icon_ofs.x -= down_icon->get_width();
te->draw_texture(down_icon, icon_ofs - Size2(0, 4 * EDSCALE));
@@ -1384,7 +1394,7 @@ void AnimationKeyEditor::_track_editor_draw() {
icon_ofs.x -= hsep;
te->draw_line(Point2(icon_ofs.x, ofs.y + y), Point2(icon_ofs.x, ofs.y + y + h), sepcolor);
- track_ofs[2] = size.width - icon_ofs.x;
+ track_ofs[2] = size.width - icon_ofs.x + ofs.x;
if (animation->track_get_type(idx) == Animation::TYPE_VALUE) {
@@ -1405,13 +1415,12 @@ void AnimationKeyEditor::_track_editor_draw() {
icon_ofs.x -= hsep;
te->draw_line(Point2(icon_ofs.x, ofs.y + y), Point2(icon_ofs.x, ofs.y + y + h), sepcolor);
- track_ofs[3] = size.width - icon_ofs.x;
+ track_ofs[3] = size.width - icon_ofs.x + ofs.x;
icon_ofs.x -= hsep;
icon_ofs.x -= add_key_icon->get_width();
te->draw_texture((mouse_over.over == MouseOver::OVER_ADD_KEY && mouse_over.track == idx) ? add_key_icon_hl : add_key_icon, icon_ofs);
-
- track_ofs[4] = size.width - icon_ofs.x;
+ track_ofs[4] = size.width - icon_ofs.x + ofs.x;
//draw the keys;
int tt = animation->track_get_type(idx);
@@ -2070,7 +2079,7 @@ void AnimationKeyEditor::_track_editor_gui_input(const Ref<InputEvent> &p_input)
return;
}
- if (mpos.x < name_limit) {
+ if (mpos.x < name_limit - (type_icon[0]->get_width() / 2.0)) {
//name column
// area
@@ -2880,6 +2889,18 @@ void AnimationKeyEditor::_track_editor_gui_input(const Ref<InputEvent> &p_input)
}
}
}
+
+ Ref<InputEventMagnifyGesture> magnify_gesture = p_input;
+ if (magnify_gesture.is_valid()) {
+ zoom->set_value(zoom->get_value() * magnify_gesture->get_factor());
+ }
+
+ Ref<InputEventPanGesture> pan_gesture = p_input;
+ if (pan_gesture.is_valid()) {
+
+ h_scroll->set_value(h_scroll->get_value() - h_scroll->get_page() * pan_gesture->get_delta().x / 8);
+ v_scroll->set_value(v_scroll->get_value() - v_scroll->get_page() * pan_gesture->get_delta().y / 8);
+ }
}
void AnimationKeyEditor::_notification(int p_what) {
@@ -3320,7 +3341,7 @@ int AnimationKeyEditor::_confirm_insert(InsertData p_id, int p_last_track) {
h.type == Variant::VECTOR2 ||
h.type == Variant::RECT2 ||
h.type == Variant::VECTOR3 ||
- h.type == Variant::RECT3 ||
+ h.type == Variant::AABB ||
h.type == Variant::QUAT ||
h.type == Variant::COLOR ||
h.type == Variant::TRANSFORM) {
diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp
index ee1faf5a55..216f2027fb 100644
--- a/editor/code_editor.cpp
+++ b/editor/code_editor.cpp
@@ -56,6 +56,7 @@ void GotoLineDialog::ok_pressed() {
if (get_line() < 1 || get_line() > text_editor->get_line_count())
return;
+ text_editor->unfold_line(get_line() - 1);
text_editor->cursor_set_line(get_line() - 1);
hide();
}
@@ -139,6 +140,7 @@ bool FindReplaceBar::_search(uint32_t p_flags, int p_from_line, int p_from_col)
if (found) {
if (!preserve_cursor) {
+ text_edit->unfold_line(line);
text_edit->cursor_set_line(line, false);
text_edit->cursor_set_column(col + text.length(), false);
text_edit->center_viewport_to_cursor();
@@ -167,6 +169,7 @@ void FindReplaceBar::_replace() {
if (result_line != -1 && result_col != -1) {
text_edit->begin_complex_operation();
+ text_edit->unfold_line(result_line);
text_edit->select(result_line, result_col, result_line, result_col + get_search_text().length());
text_edit->insert_text_at_cursor(get_replace_text());
@@ -214,6 +217,7 @@ void FindReplaceBar::_replace_all() {
prev_match = Point2i(result_line, result_col + replace_text.length());
+ text_edit->unfold_line(result_line);
text_edit->select(result_line, result_col, result_line, match_to.y);
if (selection_enabled && is_selection_only()) {
@@ -751,6 +755,7 @@ bool FindReplaceDialog::_search() {
if (found) {
// print_line("found");
+ text_edit->unfold_line(line);
text_edit->cursor_set_line(line);
if (is_backwards())
text_edit->cursor_set_column(col);
@@ -974,6 +979,23 @@ void CodeTextEditor::_text_editor_gui_input(const Ref<InputEvent> &p_event) {
}
}
+ Ref<InputEventMagnifyGesture> magnify_gesture = p_event;
+ if (magnify_gesture.is_valid()) {
+
+ Ref<DynamicFont> font = text_editor->get_font("font");
+
+ if (font.is_valid()) {
+ if (font->get_size() != (int)font_size) {
+ font_size = font->get_size();
+ }
+
+ font_size *= powf(magnify_gesture->get_factor(), 0.25);
+
+ _add_font_size((int)font_size - font->get_size());
+ }
+ return;
+ }
+
Ref<InputEventKey> k = p_event;
if (k.is_valid()) {
@@ -994,14 +1016,15 @@ void CodeTextEditor::_text_editor_gui_input(const Ref<InputEvent> &p_event) {
void CodeTextEditor::_zoom_in() {
font_resize_val += EDSCALE;
-
- if (font_resize_timer->get_time_left() == 0)
- font_resize_timer->start();
+ _zoom_changed();
}
void CodeTextEditor::_zoom_out() {
font_resize_val -= EDSCALE;
+ _zoom_changed();
+}
+void CodeTextEditor::_zoom_changed() {
if (font_resize_timer->get_time_left() == 0)
font_resize_timer->start();
}
@@ -1062,16 +1085,25 @@ void CodeTextEditor::_complete_request() {
void CodeTextEditor::_font_resize_timeout() {
+ if (_add_font_size(font_resize_val)) {
+ font_resize_val = 0;
+ }
+}
+
+bool CodeTextEditor::_add_font_size(int p_delta) {
+
Ref<DynamicFont> font = text_editor->get_font("font");
if (font.is_valid()) {
- int new_size = CLAMP(font->get_size() + font_resize_val, 8 * EDSCALE, 96 * EDSCALE);
+ int new_size = CLAMP(font->get_size() + p_delta, 8 * EDSCALE, 96 * EDSCALE);
if (new_size != font->get_size()) {
EditorSettings::get_singleton()->set("interface/editor/source_font_size", new_size / EDSCALE);
font->set_size(new_size);
}
- font_resize_val = 0;
+ return true;
+ } else {
+ return false;
}
}
@@ -1089,9 +1121,12 @@ void CodeTextEditor::update_editor_settings() {
text_editor->set_line_length_guideline_column(EditorSettings::get_singleton()->get("text_editor/line_numbers/line_length_guideline_column"));
text_editor->set_syntax_coloring(EditorSettings::get_singleton()->get("text_editor/highlighting/syntax_highlighting"));
text_editor->set_highlight_all_occurrences(EditorSettings::get_singleton()->get("text_editor/highlighting/highlight_all_occurrences"));
+ text_editor->set_highlight_current_line(EditorSettings::get_singleton()->get("text_editor/highlighting/highlight_current_line"));
text_editor->cursor_set_blink_enabled(EditorSettings::get_singleton()->get("text_editor/cursor/caret_blink"));
text_editor->cursor_set_blink_speed(EditorSettings::get_singleton()->get("text_editor/cursor/caret_blink_speed"));
text_editor->set_draw_breakpoint_gutter(EditorSettings::get_singleton()->get("text_editor/line_numbers/show_breakpoint_gutter"));
+ text_editor->set_hiding_enabled(EditorSettings::get_singleton()->get("text_editor/line_numbers/code_folding"));
+ text_editor->set_draw_fold_gutter(EditorSettings::get_singleton()->get("text_editor/line_numbers/code_folding"));
text_editor->cursor_set_block_mode(EditorSettings::get_singleton()->get("text_editor/cursor/block_caret"));
text_editor->set_smooth_scroll_enabled(EditorSettings::get_singleton()->get("text_editor/open_scripts/smooth_scrolling"));
text_editor->set_v_scroll_speed(EditorSettings::get_singleton()->get("text_editor/open_scripts/v_scroll_speed"));
@@ -1277,6 +1312,7 @@ CodeTextEditor::CodeTextEditor() {
code_complete_timer->connect("timeout", this, "_code_complete_timer_timeout");
font_resize_val = 0;
+ font_size = -1;
font_resize_timer = memnew(Timer);
add_child(font_resize_timer);
font_resize_timer->set_one_shot(true);
diff --git a/editor/code_editor.h b/editor/code_editor.h
index 410dd99878..656ea4b47b 100644
--- a/editor/code_editor.h
+++ b/editor/code_editor.h
@@ -204,6 +204,7 @@ class CodeTextEditor : public VBoxContainer {
Timer *font_resize_timer;
int font_resize_val;
+ real_t font_size;
Label *error;
@@ -212,10 +213,12 @@ class CodeTextEditor : public VBoxContainer {
void _update_font();
void _complete_request();
void _font_resize_timeout();
+ bool _add_font_size(int p_delta);
void _text_editor_gui_input(const Ref<InputEvent> &p_event);
void _zoom_in();
void _zoom_out();
+ void _zoom_changed();
void _reset_zoom();
CodeTextEditorCodeCompleteFunc code_complete_func;
diff --git a/editor/collada/collada.cpp b/editor/collada/collada.cpp
index 2d49840683..6dbfd84c86 100644
--- a/editor/collada/collada.cpp
+++ b/editor/collada/collada.cpp
@@ -422,11 +422,6 @@ Vector<String> Collada::_read_string_array(XMLParser &parser) {
// parse String data
String str = parser.get_node_data();
array = str.split_spaces();
- /*
- for(int i=0;i<array.size();i++) {
- print_line(itos(i)+": "+array[i]);
- }
- */
} else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END)
break; // end parsing text
}
@@ -1320,11 +1315,8 @@ void Collada::_parse_morph_controller(XMLParser &parser, String p_id) {
state.morph_controller_data_map[p_id] = MorphControllerData();
MorphControllerData &morphdata = state.morph_controller_data_map[p_id];
- print_line("morph source: " + parser.get_attribute_value("source") + " id: " + p_id);
morphdata.mesh = _uri_to_id(parser.get_attribute_value("source"));
- print_line("morph source2: " + morphdata.mesh);
morphdata.mode = parser.get_attribute_value("method");
- printf("JJmorph: %p\n", &morphdata);
String current_source;
while (parser.read() == OK) {
@@ -1690,7 +1682,6 @@ Collada::Node *Collada::_parse_visual_scene_node(XMLParser &parser) {
} else if (section != "node") {
//usually what defines the type of node
- //print_line(" don't know what to do with "+section);
if (section.begins_with("instance_")) {
if (!node) {
@@ -1863,9 +1854,6 @@ void Collada::_parse_animation(XMLParser &parser) {
String source = _uri_to_id(channel_sources[i]);
String target = channel_targets[i];
- if (!samplers.has(source)) {
- print_line("channel lacks source: " + source);
- }
ERR_CONTINUE(!samplers.has(source));
Map<String, String> &sampler = samplers[source];
@@ -1970,8 +1958,6 @@ void Collada::_parse_animation(XMLParser &parser) {
track.target = target;
}
- print_line("TARGET: " + track.target);
-
state.animation_tracks.push_back(track);
if (!state.referenced_tracks.has(target))
@@ -2027,8 +2013,8 @@ void Collada::_parse_animation_clip(XMLParser &parser) {
}
state.animation_clips.push_back(clip);
- print_line("found anim clip: " + clip.name);
}
+
void Collada::_parse_scene(XMLParser &parser) {
if (parser.is_empty()) {
@@ -2044,7 +2030,6 @@ void Collada::_parse_scene(XMLParser &parser) {
if (name == "instance_visual_scene") {
state.root_visual_scene = _uri_to_id(parser.get_attribute_value("url"));
- print_line("***ROOT VISUAL SCENE: " + state.root_visual_scene);
} else if (name == "instance_physics_scene") {
state.root_physics_scene = _uri_to_id(parser.get_attribute_value("url"));
@@ -2213,9 +2198,6 @@ void Collada::_merge_skeletons(VisualScene *p_vscene, Node *p_node) {
NodeJoint *nj = SAFE_CAST<NodeJoint *>(state.scene_map[nodeid]);
ERR_CONTINUE(!nj); //broken collada
- if (!nj->owner) {
- print_line("no owner for: " + String(nodeid));
- }
ERR_CONTINUE(!nj->owner); //weird, node should have a skeleton owner
skeletons.insert(nj->owner);
@@ -2268,10 +2250,6 @@ void Collada::_merge_skeletons2(VisualScene *p_vscene) {
name = state.sid_to_node_map[F->key()];
- if (!state.scene_map.has(name)) {
- print_line("no foundie node for: " + name);
- }
-
ERR_CONTINUE(!state.scene_map.has(name));
Node *node = state.scene_map[name];
@@ -2299,9 +2277,6 @@ void Collada::_merge_skeletons2(VisualScene *p_vscene) {
if (skeleton != sk) {
//whoa.. wtf, merge.
- print_line("MERGED BONES!!");
-
- //NodeSkeleton *merged = E->get();
_remove_node(p_vscene, sk);
for (int i = 0; i < sk->children.size(); i++) {
@@ -2399,9 +2374,6 @@ bool Collada::_move_geometry_to_skeletons(VisualScene *p_vscene, Node *p_node, L
ERR_FAIL_COND_V(!state.scene_map.has(nodeid), false); //weird, it should have it...
NodeJoint *nj = SAFE_CAST<NodeJoint *>(state.scene_map[nodeid]);
ERR_FAIL_COND_V(!nj, false);
- if (!nj->owner) {
- print_line("Has no owner: " + nj->name);
- }
ERR_FAIL_COND_V(!nj->owner, false); //weird, node should have a skeleton owner
NodeSkeleton *sk = nj->owner;
diff --git a/editor/connections_dialog.cpp b/editor/connections_dialog.cpp
index b4c2ac95cc..cd60455f4f 100644
--- a/editor/connections_dialog.cpp
+++ b/editor/connections_dialog.cpp
@@ -209,7 +209,7 @@ void ConnectDialog::_add_bind() {
case Variant::VECTOR3: value = Vector3(); break;
case Variant::PLANE: value = Plane(); break;
case Variant::QUAT: value = Quat(); break;
- case Variant::RECT3: value = Rect3(); break;
+ case Variant::AABB: value = AABB(); break;
case Variant::BASIS: value = Basis(); break;
case Variant::TRANSFORM: value = Transform(); break;
case Variant::COLOR: value = Color(); break;
@@ -295,7 +295,7 @@ ConnectDialog::ConnectDialog() {
type_list->add_item("Vector3", Variant::VECTOR3);
type_list->add_item("Plane", Variant::PLANE);
type_list->add_item("Quat", Variant::QUAT);
- type_list->add_item("Rect3", Variant::RECT3);
+ type_list->add_item("AABB", Variant::AABB);
type_list->add_item("Basis", Variant::BASIS);
type_list->add_item("Transform", Variant::TRANSFORM);
//type_list->add_separator();
diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp
index 520bf480fd..c058d290bf 100644
--- a/editor/create_dialog.cpp
+++ b/editor/create_dialog.cpp
@@ -41,7 +41,7 @@ void CreateDialog::popup_create(bool p_dontclear) {
recent->clear();
- FileAccess *f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_path().plus_file("create_recent." + base_type), FileAccess::READ);
+ FileAccess *f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("create_recent." + base_type), FileAccess::READ);
if (f) {
@@ -63,7 +63,7 @@ void CreateDialog::popup_create(bool p_dontclear) {
favorites->clear();
- f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_path().plus_file("favorites." + base_type), FileAccess::READ);
+ f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("favorites." + base_type), FileAccess::READ);
favorite_list.clear();
@@ -97,6 +97,15 @@ void CreateDialog::popup_create(bool p_dontclear) {
search_box->grab_focus();
_update_search();
+
+ bool enable_rl = EditorSettings::get_singleton()->get("docks/scene_tree/draw_relationship_lines");
+ Color rl_color = EditorSettings::get_singleton()->get("docks/scene_tree/relationship_line_color");
+
+ if (enable_rl) {
+ search_options->add_constant_override("draw_relationship_lines", 1);
+ search_options->add_color_override("relationship_line_color", rl_color);
+ } else
+ search_options->add_constant_override("draw_relationship_lines", 0);
}
void CreateDialog::_text_changed(const String &p_newtext) {
@@ -171,6 +180,9 @@ void CreateDialog::add_type(const String &p_type, HashMap<String, TreeItem *> &p
bool is_search_subsequence = search_box->get_text().is_subsequence_ofi(p_type);
String to_select_type = *to_select ? (*to_select)->get_text(0) : "";
bool current_item_is_preffered = ClassDB::is_parent_class(p_type, preferred_search_result_type) && !ClassDB::is_parent_class(to_select_type, preferred_search_result_type);
+ if (*to_select && p_type.length() < (*to_select)->get_text(0).length()) {
+ current_item_is_preffered = true;
+ }
if (((!*to_select || current_item_is_preffered) && is_search_subsequence) || search_box->get_text() == p_type) {
*to_select = item;
@@ -211,9 +223,6 @@ void CreateDialog::_update_search() {
_parse_fs(EditorFileSystem::get_singleton()->get_filesystem());
*/
- List<StringName> type_list;
- ClassDB::get_class_list(&type_list);
-
HashMap<String, TreeItem *> types;
TreeItem *root = search_options->create_item();
@@ -293,6 +302,7 @@ void CreateDialog::_update_search() {
if (to_select) {
to_select->select(0);
+ search_options->scroll_to_item(to_select);
favorite->set_disabled(false);
favorite->set_pressed(favorite_list.find(to_select->get_text(0)) != -1);
}
@@ -306,7 +316,7 @@ void CreateDialog::_confirmed() {
if (!ti)
return;
- FileAccess *f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_path().plus_file("create_recent." + base_type), FileAccess::WRITE);
+ FileAccess *f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("create_recent." + base_type), FileAccess::WRITE);
if (f) {
f->store_line(get_selected_type());
@@ -466,7 +476,7 @@ void CreateDialog::_favorite_toggled() {
void CreateDialog::_save_favorite_list() {
- FileAccess *f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_path().plus_file("favorites." + base_type), FileAccess::WRITE);
+ FileAccess *f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("favorites." + base_type), FileAccess::WRITE);
if (f) {
@@ -615,6 +625,9 @@ void CreateDialog::_bind_methods() {
CreateDialog::CreateDialog() {
+ ClassDB::get_class_list(&type_list);
+ type_list.sort_custom<StringName::AlphCompare>();
+
set_resizable(true);
HSplitContainer *hbc = memnew(HSplitContainer);
diff --git a/editor/create_dialog.h b/editor/create_dialog.h
index 2e4ce9b277..157c126c66 100644
--- a/editor/create_dialog.h
+++ b/editor/create_dialog.h
@@ -55,6 +55,7 @@ class CreateDialog : public ConfirmationDialog {
String base_type;
String preferred_search_result_type;
EditorHelpBit *help_bit;
+ List<StringName> type_list;
void _item_selected();
diff --git a/editor/dependency_editor.cpp b/editor/dependency_editor.cpp
index 5305c4f256..ec0ca3add5 100644
--- a/editor/dependency_editor.cpp
+++ b/editor/dependency_editor.cpp
@@ -281,6 +281,47 @@ DependencyEditor::DependencyEditor() {
}
/////////////////////////////////////
+void DependencyEditorOwners::_list_rmb_select(int p_item, const Vector2 &p_pos) {
+
+ file_options->clear();
+ file_options->set_size(Size2(1, 1));
+ if (p_item >= 0) {
+ file_options->add_item(TTR("Open"), FILE_OPEN);
+ }
+
+ file_options->set_position(owners->get_global_position() + p_pos);
+ file_options->popup();
+}
+
+void DependencyEditorOwners::_select_file(int p_idx) {
+
+ String fpath = owners->get_item_text(p_idx);
+
+ if (ResourceLoader::get_resource_type(fpath) == "PackedScene") {
+ editor->open_request(fpath);
+ hide();
+ emit_signal("confirmed");
+ }
+}
+
+void DependencyEditorOwners::_file_option(int p_option) {
+
+ switch (p_option) {
+ case FILE_OPEN: {
+ int idx = owners->get_current();
+ if (idx < 0 || idx >= owners->get_item_count())
+ break;
+ _select_file(idx);
+ } break;
+ }
+}
+
+void DependencyEditorOwners::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("_list_rmb_select"), &DependencyEditorOwners::_list_rmb_select);
+ ClassDB::bind_method(D_METHOD("_file_option"), &DependencyEditorOwners::_file_option);
+ ClassDB::bind_method(D_METHOD("_select_file"), &DependencyEditorOwners::_select_file);
+}
void DependencyEditorOwners::_fill_owners(EditorFileSystemDirectory *efsd) {
@@ -329,100 +370,160 @@ void DependencyEditorOwners::show(const String &p_path) {
set_title(TTR("Owners Of:") + " " + p_path.get_file());
}
-DependencyEditorOwners::DependencyEditorOwners() {
+DependencyEditorOwners::DependencyEditorOwners(EditorNode *p_editor) {
+
+ editor = p_editor;
+
+ file_options = memnew(PopupMenu);
+ add_child(file_options);
+ file_options->connect("id_pressed", this, "_file_option");
owners = memnew(ItemList);
+ owners->set_select_mode(ItemList::SELECT_SINGLE);
+ owners->connect("item_rmb_selected", this, "_list_rmb_select");
+ owners->connect("item_activated", this, "_select_file");
+ owners->set_allow_rmb_select(true);
add_child(owners);
}
///////////////////////
-void DependencyRemoveDialog::_fill_owners(EditorFileSystemDirectory *efsd) {
+void DependencyRemoveDialog::_find_files_in_removed_folder(EditorFileSystemDirectory *efsd, const String &p_folder) {
+ if (!efsd)
+ return;
+
+ for (int i = 0; i < efsd->get_subdir_count(); ++i) {
+ _find_files_in_removed_folder(efsd->get_subdir(i), p_folder);
+ }
+ for (int i = 0; i < efsd->get_file_count(); i++) {
+ String file = efsd->get_file_path(i);
+ ERR_FAIL_COND(all_remove_files.has(file)); //We are deleting a directory which is contained in a directory we are deleting...
+ all_remove_files[file] = p_folder; //Point the file to the ancestor directory we are deleting so we know what to parent it under in the tree.
+ }
+}
+void DependencyRemoveDialog::_find_all_removed_dependencies(EditorFileSystemDirectory *efsd, Vector<RemovedDependency> &p_removed) {
if (!efsd)
return;
for (int i = 0; i < efsd->get_subdir_count(); i++) {
- _fill_owners(efsd->get_subdir(i));
+ _find_all_removed_dependencies(efsd->get_subdir(i), p_removed);
}
for (int i = 0; i < efsd->get_file_count(); i++) {
+ const String path = efsd->get_file_path(i);
- Vector<String> deps = efsd->get_file_deps(i);
- //print_line(":::"+efsd->get_file_path(i));
- Set<String> met;
- for (int j = 0; j < deps.size(); j++) {
- if (files.has(deps[j])) {
- met.insert(deps[j]);
- }
- }
- if (!met.size())
+ //It doesn't matter if a file we are about to delete will have some of its dependencies removed too
+ if (all_remove_files.has(path))
continue;
- exist = true;
-
- Ref<Texture> icon;
- String type = efsd->get_file_type(i);
- if (!has_icon(type, "EditorIcons")) {
- icon = get_icon("Object", "EditorIcons");
- } else {
- icon = get_icon(type, "EditorIcons");
+ Vector<String> all_deps = efsd->get_file_deps(i);
+ for (int j = 0; j < all_deps.size(); ++j) {
+ if (all_remove_files.has(all_deps[j])) {
+ RemovedDependency dep;
+ dep.file = path;
+ dep.file_type = efsd->get_file_type(i);
+ dep.dependency = all_deps[j];
+ dep.dependency_folder = all_remove_files[all_deps[j]];
+ p_removed.push_back(dep);
+ }
}
+ }
+}
- for (Set<String>::Element *E = met.front(); E; E = E->next()) {
+void DependencyRemoveDialog::_build_removed_dependency_tree(const Vector<RemovedDependency> &p_removed) {
+ owners->clear();
+ owners->create_item(); // root
- String which = E->get();
- if (!files[which]) {
- TreeItem *ti = owners->create_item(owners->get_root());
- ti->set_text(0, which.get_file());
- files[which] = ti;
+ Map<String, TreeItem *> tree_items;
+ for (int i = 0; i < p_removed.size(); i++) {
+ RemovedDependency rd = p_removed[i];
+
+ //Ensure that the dependency is already in the tree
+ if (!tree_items.has(rd.dependency)) {
+ if (rd.dependency_folder.length() > 0) {
+ //Ensure the ancestor folder is already in the tree
+ if (!tree_items.has(rd.dependency_folder)) {
+ TreeItem *folder_item = owners->create_item(owners->get_root());
+ folder_item->set_text(0, rd.dependency_folder);
+ folder_item->set_icon(0, get_icon("Folder", "EditorIcons"));
+ tree_items[rd.dependency_folder] = folder_item;
+ }
+ TreeItem *dependency_item = owners->create_item(tree_items[rd.dependency_folder]);
+ dependency_item->set_text(0, rd.dependency);
+ dependency_item->set_icon(0, get_icon("Warning", "EditorIcons"));
+ tree_items[rd.dependency] = dependency_item;
+ } else {
+ TreeItem *dependency_item = owners->create_item(owners->get_root());
+ dependency_item->set_text(0, rd.dependency);
+ dependency_item->set_icon(0, get_icon("Warning", "EditorIcons"));
+ tree_items[rd.dependency] = dependency_item;
}
- TreeItem *ti = owners->create_item(files[which]);
- ti->set_text(0, efsd->get_file_path(i));
- ti->set_icon(0, icon);
}
+
+ //List this file under this dependency
+ Ref<Texture> icon = has_icon(rd.file_type, "EditorIcons") ? get_icon(rd.file_type, "EditorIcons") : get_icon("Object", "EditorIcons");
+ TreeItem *file_item = owners->create_item(tree_items[rd.dependency]);
+ file_item->set_text(0, rd.file);
+ file_item->set_icon(0, icon);
}
}
-void DependencyRemoveDialog::show(const Vector<String> &to_erase) {
-
- exist = false;
+void DependencyRemoveDialog::show(const Vector<String> &p_folders, const Vector<String> &p_files) {
+ all_remove_files.clear();
+ to_delete.clear();
owners->clear();
- files.clear();
- owners->create_item(); // root
- for (int i = 0; i < to_erase.size(); i++) {
- files[to_erase[i]] = NULL;
+
+ for (int i = 0; i < p_folders.size(); ++i) {
+ String folder = p_folders[i].ends_with("/") ? p_folders[i] : (p_folders[i] + "/");
+ _find_files_in_removed_folder(EditorFileSystem::get_singleton()->get_filesystem_path(folder), folder);
+ to_delete.push_back(folder);
+ }
+ for (int i = 0; i < p_files.size(); ++i) {
+ all_remove_files[p_files[i]] = String();
+ to_delete.push_back(p_files[i]);
}
- _fill_owners(EditorFileSystem::get_singleton()->get_filesystem());
+ Vector<RemovedDependency> removed_deps;
+ _find_all_removed_dependencies(EditorFileSystem::get_singleton()->get_filesystem(), removed_deps);
+ removed_deps.sort();
- if (exist) {
- owners->show();
- text->set_text(TTR("The files being removed are required by other resources in order for them to work.\nRemove them anyway? (no undo)"));
- popup_centered_minsize(Size2(500, 220));
- } else {
+ if (removed_deps.empty()) {
owners->hide();
text->set_text(TTR("Remove selected files from the project? (no undo)"));
popup_centered_minsize(Size2(400, 100));
+ } else {
+ _build_removed_dependency_tree(removed_deps);
+ owners->show();
+ text->set_text(TTR("The files being removed are required by other resources in order for them to work.\nRemove them anyway? (no undo)"));
+ popup_centered_minsize(Size2(500, 350));
}
}
void DependencyRemoveDialog::ok_pressed() {
-
- bool changed = false;
-
- for (Map<String, TreeItem *>::Element *E = files.front(); E; E = E->next()) {
-
- if (ResourceCache::has(E->key())) {
- Resource *res = ResourceCache::get(E->key());
+ bool files_only = true;
+ for (int i = 0; i < to_delete.size(); ++i) {
+ if (to_delete[i].ends_with("/")) {
+ files_only = false;
+ } else if (ResourceCache::has(to_delete[i])) {
+ Resource *res = ResourceCache::get(to_delete[i]);
res->set_path(""); //clear reference to path
}
- String fpath = OS::get_singleton()->get_resource_dir() + E->key().replace_first("res://", "/");
- OS::get_singleton()->move_to_trash(fpath);
- changed = true;
+
+ String path = OS::get_singleton()->get_resource_dir() + to_delete[i].replace_first("res://", "/");
+ print_line("Moving to trash: " + path);
+ Error err = OS::get_singleton()->move_to_trash(path);
+ if (err != OK) {
+ EditorNode::get_singleton()->add_io_error(TTR("Cannot remove:\n") + to_delete[i] + "\n");
+ }
}
- if (changed) {
+ if (files_only) {
+ //If we only deleted files we should only need to tell the file system about the files we touched.
+ for (int i = 0; i < to_delete.size(); ++i) {
+ EditorFileSystem::get_singleton()->update_file(to_delete[i]);
+ }
+ } else {
EditorFileSystem::get_singleton()->scan_changes();
}
}
@@ -494,7 +595,7 @@ DependencyErrorDialog::DependencyErrorDialog() {
vb->add_margin_child(TTR("Scene failed to load due to missing dependencies:"), files, true);
files->set_v_size_flags(SIZE_EXPAND_FILL);
get_ok()->set_text(TTR("Open Anyway"));
- get_cancel()->set_text(TTR("Done"));
+ get_cancel()->set_text(TTR("Close"));
text = memnew(Label);
vb->add_child(text);
diff --git a/editor/dependency_editor.h b/editor/dependency_editor.h
index 4dfb9de268..9b0aca67d5 100644
--- a/editor/dependency_editor.h
+++ b/editor/dependency_editor.h
@@ -36,6 +36,7 @@
#include "scene/gui/tree.h"
class EditorFileSystemDirectory;
+class EditorNode;
class DependencyEditor : public AcceptDialog {
GDCLASS(DependencyEditor, AcceptDialog);
@@ -71,12 +72,25 @@ class DependencyEditorOwners : public AcceptDialog {
GDCLASS(DependencyEditorOwners, AcceptDialog);
ItemList *owners;
+ PopupMenu *file_options;
+ EditorNode *editor;
String editing;
+
void _fill_owners(EditorFileSystemDirectory *efsd);
+ static void _bind_methods();
+ void _list_rmb_select(int p_item, const Vector2 &p_pos);
+ void _select_file(int p_idx);
+ void _file_option(int p_option);
+
+private:
+ enum FileMenu {
+ FILE_OPEN
+ };
+
public:
void show(const String &p_path);
- DependencyEditorOwners();
+ DependencyEditorOwners(EditorNode *p_editor);
};
class DependencyRemoveDialog : public ConfirmationDialog {
@@ -84,14 +98,33 @@ class DependencyRemoveDialog : public ConfirmationDialog {
Label *text;
Tree *owners;
- bool exist;
- Map<String, TreeItem *> files;
- void _fill_owners(EditorFileSystemDirectory *efsd);
+
+ Map<String, String> all_remove_files;
+ Vector<String> to_delete;
+
+ struct RemovedDependency {
+ String file;
+ String file_type;
+ String dependency;
+ String dependency_folder;
+
+ bool operator<(const RemovedDependency &p_other) const {
+ if (dependency_folder.empty() != p_other.dependency_folder.empty()) {
+ return p_other.dependency_folder.empty();
+ } else {
+ return dependency < p_other.dependency;
+ }
+ }
+ };
+
+ void _find_files_in_removed_folder(EditorFileSystemDirectory *efsd, const String &p_folder);
+ void _find_all_removed_dependencies(EditorFileSystemDirectory *efsd, Vector<RemovedDependency> &p_removed);
+ void _build_removed_dependency_tree(const Vector<RemovedDependency> &p_removed);
void ok_pressed();
public:
- void show(const Vector<String> &to_erase);
+ void show(const Vector<String> &p_folders, const Vector<String> &p_files);
DependencyRemoveDialog();
};
diff --git a/editor/dictionary_property_edit.cpp b/editor/dictionary_property_edit.cpp
new file mode 100644
index 0000000000..5b5a7ec9b0
--- /dev/null
+++ b/editor/dictionary_property_edit.cpp
@@ -0,0 +1,189 @@
+/*************************************************************************/
+/* dictionary_property_edit.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#include "dictionary_property_edit.h"
+#include "editor_node.h"
+
+void DictionaryPropertyEdit::_notif_change() {
+ _change_notify();
+}
+
+void DictionaryPropertyEdit::_notif_changev(const String &p_v) {
+ _change_notify(p_v.utf8().get_data());
+}
+
+void DictionaryPropertyEdit::_set_key(const Variant &p_old_key, const Variant &p_new_key) {
+
+ // TODO: Set key of a dictionary is not allowd yet
+ return;
+}
+
+void DictionaryPropertyEdit::_set_value(const Variant &p_key, const Variant &p_value) {
+
+ Dictionary dict = get_dictionary();
+ dict[p_key] = p_value;
+ Object *o = ObjectDB::get_instance(obj);
+ if (!o)
+ return;
+
+ o->set(property, dict);
+}
+
+Variant DictionaryPropertyEdit::get_dictionary() const {
+
+ Object *o = ObjectDB::get_instance(obj);
+ if (!o)
+ return Dictionary();
+ Variant dict = o->get(property);
+ if (dict.get_type() != Variant::DICTIONARY)
+ return Dictionary();
+ return dict;
+}
+
+void DictionaryPropertyEdit::_get_property_list(List<PropertyInfo> *p_list) const {
+
+ Dictionary dict = get_dictionary();
+
+ Array keys = dict.keys();
+ keys.sort();
+
+ for (int i = 0; i < keys.size(); i++) {
+ String index = itos(i);
+
+ const Variant &key = keys[i];
+ PropertyInfo pi(key.get_type(), index + ": key");
+ p_list->push_back(pi);
+
+ const Variant &value = dict[key];
+ pi = PropertyInfo(value.get_type(), index + ": value");
+ p_list->push_back(pi);
+ }
+}
+
+void DictionaryPropertyEdit::edit(Object *p_obj, const StringName &p_prop) {
+
+ property = p_prop;
+ obj = p_obj->get_instance_id();
+}
+
+Node *DictionaryPropertyEdit::get_node() {
+
+ Object *o = ObjectDB::get_instance(obj);
+ if (!o)
+ return NULL;
+
+ return cast_to<Node>(o);
+}
+
+void DictionaryPropertyEdit::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("_set_key"), &DictionaryPropertyEdit::_set_key);
+ ClassDB::bind_method(D_METHOD("_set_value"), &DictionaryPropertyEdit::_set_value);
+ ClassDB::bind_method(D_METHOD("_notif_change"), &DictionaryPropertyEdit::_notif_change);
+ ClassDB::bind_method(D_METHOD("_notif_changev"), &DictionaryPropertyEdit::_notif_changev);
+}
+
+bool DictionaryPropertyEdit::_set(const StringName &p_name, const Variant &p_value) {
+
+ Dictionary dict = get_dictionary();
+ Array keys = dict.keys();
+ keys.sort();
+
+ String pn = p_name;
+ int slash = pn.find(": ");
+ if (slash != -1 && pn.length() > slash) {
+ String type = pn.substr(slash + 2, pn.length());
+ int index = pn.substr(0, slash).to_int();
+ if (type == "key" && index < keys.size()) {
+
+ const Variant &key = keys[index];
+ UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+
+ ur->create_action(TTR("Change Dictionary Key"));
+ ur->add_do_method(this, "_set_key", key, p_value);
+ ur->add_undo_method(this, "_set_key", p_value, key);
+ ur->add_do_method(this, "_notif_changev", p_name);
+ ur->add_undo_method(this, "_notif_changev", p_name);
+ ur->commit_action();
+
+ return true;
+ } else if (type == "value" && index < keys.size()) {
+ const Variant &key = keys[index];
+ if (dict.has(key)) {
+
+ Variant value = dict[key];
+ UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+
+ ur->create_action(TTR("Change Dictionary Value"));
+ ur->add_do_method(this, "_set_value", key, p_value);
+ ur->add_undo_method(this, "_set_value", key, value);
+ ur->add_do_method(this, "_notif_changev", p_name);
+ ur->add_undo_method(this, "_notif_changev", p_name);
+ ur->commit_action();
+
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+bool DictionaryPropertyEdit::_get(const StringName &p_name, Variant &r_ret) const {
+
+ Dictionary dict = get_dictionary();
+ Array keys = dict.keys();
+ keys.sort();
+
+ String pn = p_name;
+ int slash = pn.find(": ");
+
+ if (slash != -1 && pn.length() > slash) {
+
+ String type = pn.substr(slash + 2, pn.length());
+ int index = pn.substr(0, slash).to_int();
+
+ if (type == "key" && index < keys.size()) {
+ r_ret = keys[index];
+ return true;
+ } else if (type == "value" && index < keys.size()) {
+ const Variant &key = keys[index];
+ if (dict.has(key)) {
+ r_ret = dict[key];
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+DictionaryPropertyEdit::DictionaryPropertyEdit() {
+ obj = 0;
+}
diff --git a/editor/dictionary_property_edit.h b/editor/dictionary_property_edit.h
new file mode 100644
index 0000000000..7a86727fb2
--- /dev/null
+++ b/editor/dictionary_property_edit.h
@@ -0,0 +1,62 @@
+/*************************************************************************/
+/* dictionary_property_edit.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#ifndef DICTIONARY_PROPERTY_EDIT_H
+#define DICTIONARY_PROPERTY_EDIT_H
+
+#include "scene/main/node.h"
+
+class DictionaryPropertyEdit : public Reference {
+ GDCLASS(DictionaryPropertyEdit, Reference);
+
+ ObjectID obj;
+ StringName property;
+
+ void _notif_change();
+ void _notif_changev(const String &p_v);
+ void _set_key(const Variant &p_old_key, const Variant &p_new_key);
+ void _set_value(const Variant &p_key, const Variant &p_value);
+
+ Variant get_dictionary() const;
+
+protected:
+ static void _bind_methods();
+ bool _set(const StringName &p_name, const Variant &p_value);
+ bool _get(const StringName &p_name, Variant &r_ret) const;
+ void _get_property_list(List<PropertyInfo> *p_list) const;
+
+public:
+ void edit(Object *p_obj, const StringName &p_prop);
+
+ Node *get_node();
+
+ DictionaryPropertyEdit();
+};
+
+#endif // DICTIONARY_PROPERTY_EDIT_H
diff --git a/editor/doc/doc_data.cpp b/editor/doc/doc_data.cpp
index d35dc53ae1..1f9884aa70 100644
--- a/editor/doc/doc_data.cpp
+++ b/editor/doc/doc_data.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "doc_data.h"
+#include "engine.h"
#include "global_constants.h"
#include "io/compression.h"
#include "io/marshalls.h"
@@ -529,7 +530,7 @@ void DocData::generate(bool p_basic_types) {
{
- String cname = "@Global Scope";
+ String cname = "@GlobalScope";
class_list[cname] = ClassDoc();
ClassDoc &c = class_list[cname];
c.name = cname;
@@ -543,14 +544,14 @@ void DocData::generate(bool p_basic_types) {
c.constants.push_back(cd);
}
- List<ProjectSettings::Singleton> singletons;
- ProjectSettings::get_singleton()->get_singletons(&singletons);
+ List<Engine::Singleton> singletons;
+ Engine::get_singleton()->get_singletons(&singletons);
//servers (this is kind of hackish)
- for (List<ProjectSettings::Singleton>::Element *E = singletons.front(); E; E = E->next()) {
+ for (List<Engine::Singleton>::Element *E = singletons.front(); E; E = E->next()) {
PropertyDoc pd;
- ProjectSettings::Singleton &s = E->get();
+ Engine::Singleton &s = E->get();
pd.name = s.name;
pd.type = s.ptr->get_class();
while (String(ClassDB::get_parent_class(pd.type)) != "Object")
@@ -661,7 +662,7 @@ static Error _parse_methods(Ref<XMLParser> &parser, Vector<DocData::MethodDoc> &
parser->read();
if (parser->get_node_type() == XMLParser::NODE_TEXT)
- method.description = parser->get_node_data().strip_edges();
+ method.description = parser->get_node_data();
}
} else if (parser->get_node_type() == XMLParser::NODE_ELEMENT_END && parser->get_node_name() == element)
@@ -776,20 +777,20 @@ Error DocData::_load(Ref<XMLParser> parser) {
parser->read();
if (parser->get_node_type() == XMLParser::NODE_TEXT)
- c.brief_description = parser->get_node_data().strip_edges();
+ c.brief_description = parser->get_node_data();
} else if (name == "description") {
parser->read();
if (parser->get_node_type() == XMLParser::NODE_TEXT)
- c.description = parser->get_node_data().strip_edges();
+ c.description = parser->get_node_data();
} else if (name == "tutorials") {
parser->read();
if (parser->get_node_type() == XMLParser::NODE_TEXT)
- c.tutorials = parser->get_node_data().strip_edges();
+ c.tutorials = parser->get_node_data();
} else if (name == "demos") {
parser->read();
if (parser->get_node_type() == XMLParser::NODE_TEXT)
- c.demos = parser->get_node_data().strip_edges();
+ c.demos = parser->get_node_data();
} else if (name == "methods") {
Error err = _parse_methods(parser, c.methods);
@@ -823,7 +824,7 @@ Error DocData::_load(Ref<XMLParser> parser) {
prop.enumeration = parser->get_attribute_value("enum");
parser->read();
if (parser->get_node_type() == XMLParser::NODE_TEXT)
- prop.description = parser->get_node_data().strip_edges();
+ prop.description = parser->get_node_data();
c.properties.push_back(prop);
} else {
ERR_EXPLAIN("Invalid tag in doc file: " + name);
@@ -852,7 +853,7 @@ Error DocData::_load(Ref<XMLParser> parser) {
prop.type = parser->get_attribute_value("type");
parser->read();
if (parser->get_node_type() == XMLParser::NODE_TEXT)
- prop.description = parser->get_node_data().strip_edges();
+ prop.description = parser->get_node_data();
c.theme_properties.push_back(prop);
} else {
ERR_EXPLAIN("Invalid tag in doc file: " + name);
@@ -883,7 +884,7 @@ Error DocData::_load(Ref<XMLParser> parser) {
}
parser->read();
if (parser->get_node_type() == XMLParser::NODE_TEXT)
- constant.description = parser->get_node_data().strip_edges();
+ constant.description = parser->get_node_data();
c.constants.push_back(constant);
} else {
ERR_EXPLAIN("Invalid tag in doc file: " + name);
@@ -910,6 +911,8 @@ Error DocData::_load(Ref<XMLParser> parser) {
static void _write_string(FileAccess *f, int p_tablevel, const String &p_string) {
+ if (p_string == "")
+ return;
String tab;
for (int i = 0; i < p_tablevel; i++)
tab += "\t";
@@ -948,24 +951,20 @@ Error DocData::save_classes(const String &p_default_path, const Map<String, Stri
if (c.category == "")
category = "Core";
header += " category=\"" + category + "\"";
- header += " version=\"" + String(VERSION_MKSTRING) + "\"";
+ header += String(" version=\"") + itos(VERSION_MAJOR) + "." + itos(VERSION_MINOR) + "-" + VERSION_STATUS + "\"";
header += ">";
_write_string(f, 0, header);
_write_string(f, 1, "<brief_description>");
- if (c.brief_description != "")
- _write_string(f, 2, c.brief_description.xml_escape());
+ _write_string(f, 2, c.brief_description.strip_edges().xml_escape());
_write_string(f, 1, "</brief_description>");
_write_string(f, 1, "<description>");
- if (c.description != "")
- _write_string(f, 2, c.description.xml_escape());
+ _write_string(f, 2, c.description.strip_edges().xml_escape());
_write_string(f, 1, "</description>");
_write_string(f, 1, "<tutorials>");
- if (c.tutorials != "")
- _write_string(f, 2, c.tutorials.xml_escape());
+ _write_string(f, 2, c.tutorials.strip_edges().xml_escape());
_write_string(f, 1, "</tutorials>");
_write_string(f, 1, "<demos>");
- if (c.demos != "")
- _write_string(f, 2, c.demos.xml_escape());
+ _write_string(f, 2, c.demos.strip_edges().xml_escape());
_write_string(f, 1, "</demos>");
_write_string(f, 1, "<methods>");
@@ -1009,8 +1008,7 @@ Error DocData::save_classes(const String &p_default_path, const Map<String, Stri
}
_write_string(f, 3, "<description>");
- if (m.description != "")
- _write_string(f, 4, m.description.xml_escape());
+ _write_string(f, 4, m.description.strip_edges().xml_escape());
_write_string(f, 3, "</description>");
_write_string(f, 2, "</method>");
@@ -1031,8 +1029,7 @@ Error DocData::save_classes(const String &p_default_path, const Map<String, Stri
}
PropertyDoc &p = c.properties[i];
_write_string(f, 2, "<member name=\"" + p.name + "\" type=\"" + p.type + "\" setter=\"" + p.setter + "\" getter=\"" + p.getter + "\"" + enum_text + ">");
- if (p.description != "")
- _write_string(f, 3, p.description.xml_escape());
+ _write_string(f, 3, p.description.strip_edges().xml_escape());
_write_string(f, 2, "</member>");
}
_write_string(f, 1, "</members>");
@@ -1055,8 +1052,7 @@ Error DocData::save_classes(const String &p_default_path, const Map<String, Stri
}
_write_string(f, 3, "<description>");
- if (m.description != "")
- _write_string(f, 4, m.description.xml_escape());
+ _write_string(f, 4, m.description.strip_edges().xml_escape());
_write_string(f, 3, "</description>");
_write_string(f, 2, "</signal>");
@@ -1075,8 +1071,7 @@ Error DocData::save_classes(const String &p_default_path, const Map<String, Stri
} else {
_write_string(f, 2, "<constant name=\"" + k.name + "\" value=\"" + k.value + "\" enum=\"" + k.enumeration + "\">");
}
- if (k.description != "")
- _write_string(f, 3, k.description.xml_escape());
+ _write_string(f, 3, k.description.strip_edges().xml_escape());
_write_string(f, 2, "</constant>");
}
diff --git a/editor/doc/doc_dump.cpp b/editor/doc/doc_dump.cpp
index 2ba7e3c779..9dd05d9d0f 100644
--- a/editor/doc/doc_dump.cpp
+++ b/editor/doc/doc_dump.cpp
@@ -82,8 +82,8 @@ void DocDump::dump(const String &p_file) {
FileAccess *f = FileAccess::open(p_file, FileAccess::WRITE);
_write_string(f, 0, "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>");
+ _write_string(f, 0, String("<doc version=\"") + itos(VERSION_MAJOR) + "." + itos(VERSION_MINOR) + "-" + VERSION_STATUS + "\" name=\"Engine Types\">");
- _write_string(f, 0, "<doc version=\"" + String(VERSION_MKSTRING) + "\" name=\"Engine Types\">");
while (class_list.size()) {
String name = class_list.front()->get();
@@ -182,7 +182,7 @@ void DocDump::dump(const String &p_file) {
case Variant::VECTOR3:
case Variant::PLANE:
case Variant::QUAT:
- case Variant::RECT3:
+ case Variant::AABB:
case Variant::BASIS:
case Variant::COLOR:
case Variant::POOL_BYTE_ARRAY:
diff --git a/editor/editor_about.cpp b/editor/editor_about.cpp
index a48e6c9057..290cb1be42 100644
--- a/editor/editor_about.cpp
+++ b/editor/editor_about.cpp
@@ -117,7 +117,7 @@ EditorAbout::EditorAbout() {
Label *about_text = memnew(Label);
about_text->set_v_size_flags(Control::SIZE_SHRINK_CENTER);
- about_text->set_text(VERSION_FULL_NAME + hash + String::utf8("\n\u00A9 2007-2017 Juan Linietsky, Ariel Manzur.\n\u00A9 2014-2017 ") +
+ about_text->set_text(VERSION_FULL_NAME + hash + String::utf8("\n\xc2\xa9 2007-2017 Juan Linietsky, Ariel Manzur.\n\xc2\xa9 2014-2017 ") +
TTR("Godot Engine contributors") + "\n");
hbc->add_child(about_text);
@@ -201,7 +201,7 @@ EditorAbout::EditorAbout() {
for (int j = 0; j < about_tp_copyright_count[i]; j++) {
text += "\n Files:\n " + String(about_tp_file[read_idx]).replace("\n", "\n ") + "\n";
- String copyright = String::utf8(" \u00A9 ") + String::utf8(about_tp_copyright[read_idx]).replace("\n", String::utf8("\n \u00A9 "));
+ String copyright = String::utf8(" \xc2\xa9 ") + String::utf8(about_tp_copyright[read_idx]).replace("\n", String::utf8("\n \xc2\xa9 "));
text += copyright;
long_text += copyright;
String license = "\n License: " + String(about_tp_license[read_idx]) + "\n";
diff --git a/editor/editor_data.cpp b/editor/editor_data.cpp
index 2cb5340b8b..443004f820 100644
--- a/editor/editor_data.cpp
+++ b/editor/editor_data.cpp
@@ -913,8 +913,8 @@ void EditorSelection::update() {
if (!changed)
return;
- emit_signal("selection_changed");
changed = false;
+ emit_signal("selection_changed");
}
List<Node *> &EditorSelection::get_selected_node_list() {
diff --git a/editor/editor_export.cpp b/editor/editor_export.cpp
index bc20a99809..8c8d9c4c79 100644
--- a/editor/editor_export.cpp
+++ b/editor/editor_export.cpp
@@ -336,35 +336,18 @@ Error EditorExportPlatform::_save_zip_file(void *p_userdata, const String &p_pat
String EditorExportPlatform::find_export_template(String template_file_name, String *err) const {
- String base_name = itos(VERSION_MAJOR) + "." + itos(VERSION_MINOR) + "-" + _MKSTR(VERSION_STATUS) + "/" + template_file_name;
- String user_file = EditorSettings::get_singleton()->get_settings_path() + "/templates/" + base_name;
- String system_file = OS::get_singleton()->get_installed_templates_path();
- bool has_system_path = (system_file != "");
- system_file = system_file.plus_file(base_name);
-
- print_line("test user file: " + user_file);
- // Prefer user file
- if (FileAccess::exists(user_file)) {
- return user_file;
- }
- print_line("test system file: " + system_file);
+ String current_version = itos(VERSION_MAJOR) + "." + itos(VERSION_MINOR) + "-" + VERSION_STATUS + VERSION_MODULE_CONFIG;
+ String template_path = EditorSettings::get_singleton()->get_templates_dir().plus_file(current_version).plus_file(template_file_name);
- // Now check system file
- if (has_system_path) {
- if (FileAccess::exists(system_file)) {
- return system_file;
- }
+ if (FileAccess::exists(template_path)) {
+ return template_path;
}
// Not found
if (err) {
- *err += "No export template found at \"" + user_file + "\"";
- if (has_system_path)
- *err += "\n or \"" + system_file + "\".";
- else
- *err += ".";
+ *err += "No export template found at \"" + template_path + "\".";
}
- return String(); // not found
+ return String();
}
bool EditorExportPlatform::exists_export_template(String template_file_name, String *err) const {
@@ -487,9 +470,52 @@ void EditorExportPlugin::add_file(const String &p_path, const Vector<uint8_t> &p
extra_files.push_back(ef);
}
-void EditorExportPlugin::add_shared_object(const String &p_path) {
+void EditorExportPlugin::add_shared_object(const String &p_path, const Vector<String> &tags) {
+
+ shared_objects.push_back(SharedObject(p_path, tags));
+}
+
+void EditorExportPlugin::add_ios_framework(const String &p_path) {
+ ios_frameworks.push_back(p_path);
+}
+
+Vector<String> EditorExportPlugin::get_ios_frameworks() const {
+ return ios_frameworks;
+}
+
+void EditorExportPlugin::add_ios_plist_content(const String &p_plist_content) {
+ ios_plist_content += p_plist_content + "\n";
+}
+
+String EditorExportPlugin::get_ios_plist_content() const {
+ return ios_plist_content;
+}
+
+void EditorExportPlugin::add_ios_linker_flags(const String &p_flags) {
+ if (ios_linker_flags.length() > 0) {
+ ios_linker_flags += ' ';
+ }
+ ios_linker_flags += p_flags;
+}
+
+String EditorExportPlugin::get_ios_linker_flags() const {
+ return ios_linker_flags;
+}
- shared_objects.push_back(p_path);
+void EditorExportPlugin::add_ios_bundle_file(const String &p_path) {
+ ios_bundle_files.push_back(p_path);
+}
+
+Vector<String> EditorExportPlugin::get_ios_bundle_files() const {
+ return ios_bundle_files;
+}
+
+void EditorExportPlugin::add_ios_cpp_code(const String &p_code) {
+ ios_cpp_code += p_code;
+}
+
+String EditorExportPlugin::get_ios_cpp_code() const {
+ return ios_cpp_code;
}
void EditorExportPlugin::_export_file_script(const String &p_path, const String &p_type, const PoolVector<String> &p_features) {
@@ -499,17 +525,17 @@ void EditorExportPlugin::_export_file_script(const String &p_path, const String
}
}
-void EditorExportPlugin::_export_begin_script(const PoolVector<String> &p_features) {
+void EditorExportPlugin::_export_begin_script(const PoolVector<String> &p_features, bool p_debug, const String &p_path, int p_flags) {
if (get_script_instance()) {
- get_script_instance()->call("_export_begin", p_features);
+ get_script_instance()->call("_export_begin", p_features, p_debug, p_path, p_flags);
}
}
void EditorExportPlugin::_export_file(const String &p_path, const String &p_type, const Set<String> &p_features) {
}
-void EditorExportPlugin::_export_begin(const Set<String> &p_features) {
+void EditorExportPlugin::_export_begin(const Set<String> &p_features, bool p_debug, const String &p_path, int p_flags) {
}
void EditorExportPlugin::skip() {
@@ -519,33 +545,58 @@ void EditorExportPlugin::skip() {
void EditorExportPlugin::_bind_methods() {
- ClassDB::bind_method(D_METHOD("add_shared_object", "path"), &EditorExportPlugin::add_shared_object);
+ ClassDB::bind_method(D_METHOD("add_shared_object", "path", "tags"), &EditorExportPlugin::add_shared_object);
ClassDB::bind_method(D_METHOD("add_file", "path", "file", "remap"), &EditorExportPlugin::add_file);
+ ClassDB::bind_method(D_METHOD("add_ios_framework", "path"), &EditorExportPlugin::add_ios_framework);
+ ClassDB::bind_method(D_METHOD("add_ios_plist_content", "plist_content"), &EditorExportPlugin::add_ios_plist_content);
+ ClassDB::bind_method(D_METHOD("add_ios_linker_flags", "flags"), &EditorExportPlugin::add_ios_linker_flags);
+ ClassDB::bind_method(D_METHOD("add_ios_bundle_file", "path"), &EditorExportPlugin::add_ios_bundle_file);
+ ClassDB::bind_method(D_METHOD("add_ios_cpp_code", "code"), &EditorExportPlugin::add_ios_cpp_code);
ClassDB::bind_method(D_METHOD("skip"), &EditorExportPlugin::skip);
BIND_VMETHOD(MethodInfo("_export_file", PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::STRING, "type"), PropertyInfo(Variant::POOL_STRING_ARRAY, "features")));
- BIND_VMETHOD(MethodInfo("_export_begin", PropertyInfo(Variant::POOL_STRING_ARRAY, "features")));
+ BIND_VMETHOD(MethodInfo("_export_begin", PropertyInfo(Variant::POOL_STRING_ARRAY, "features"), PropertyInfo(Variant::BOOL, "is_debug"), PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::INT, "flags")));
}
EditorExportPlugin::EditorExportPlugin() {
skipped = false;
}
-Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &p_preset, EditorExportSaveFunction p_func, void *p_udata, EditorExportSaveSharedObject p_so_func) {
-
+EditorExportPlatform::FeatureContainers EditorExportPlatform::get_feature_containers(const Ref<EditorExportPreset> &p_preset) {
Ref<EditorExportPlatform> platform = p_preset->get_platform();
List<String> feature_list;
+ platform->get_platform_features(&feature_list);
platform->get_preset_features(p_preset, &feature_list);
- //figure out features
- Set<String> features;
- PoolVector<String> features_pv;
+
+ FeatureContainers result;
for (List<String>::Element *E = feature_list.front(); E; E = E->next()) {
- features.insert(E->get());
- features_pv.push_back(E->get());
+ result.features.insert(E->get());
+ result.features_pv.push_back(E->get());
}
+ return result;
+}
+EditorExportPlatform::ExportNotifier::ExportNotifier(EditorExportPlatform &p_platform, const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
+ FeatureContainers features = p_platform.get_feature_containers(p_preset);
Vector<Ref<EditorExportPlugin> > export_plugins = EditorExport::get_singleton()->get_export_plugins();
+ //initial export plugin callback
+ for (int i = 0; i < export_plugins.size(); i++) {
+ if (export_plugins[i]->get_script_instance()) { //script based
+ export_plugins[i]->_export_begin_script(features.features_pv, p_debug, p_path, p_flags);
+ } else {
+ export_plugins[i]->_export_begin(features.features, p_debug, p_path, p_flags);
+ }
+ }
+}
+
+EditorExportPlatform::ExportNotifier::~ExportNotifier() {
+ Vector<Ref<EditorExportPlugin> > export_plugins = EditorExport::get_singleton()->get_export_plugins();
+ for (int i = 0; i < export_plugins.size(); i++) {
+ export_plugins[i]->_export_end();
+ }
+}
+Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &p_preset, EditorExportSaveFunction p_func, void *p_udata, EditorExportSaveSharedObject p_so_func) {
//figure out paths of files that will be exported
Set<String> paths;
Vector<String> path_remaps;
@@ -568,13 +619,8 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &
_edit_filter_list(paths, p_preset->get_include_filter(), false);
_edit_filter_list(paths, p_preset->get_exclude_filter(), true);
- //initial export plugin callback
+ Vector<Ref<EditorExportPlugin> > export_plugins = EditorExport::get_singleton()->get_export_plugins();
for (int i = 0; i < export_plugins.size(); i++) {
- if (export_plugins[i]->get_script_instance()) { //script based
- export_plugins[i]->_export_begin_script(features_pv);
- } else {
- export_plugins[i]->_export_begin(features);
- }
if (p_so_func) {
for (int j = 0; j < export_plugins[i]->shared_objects.size(); j++) {
p_so_func(p_udata, export_plugins[i]->shared_objects[j]);
@@ -587,6 +633,10 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &
export_plugins[i]->_clear();
}
+ FeatureContainers feature_containers = get_feature_containers(p_preset);
+ Set<String> &features = feature_containers.features;
+ PoolVector<String> &features_pv = feature_containers.features_pv;
+
//store everything in the export medium
int idx = 0;
int total = paths.size();
@@ -694,7 +744,7 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &
}
String config_file = "project.binary";
- String engine_cfb = EditorSettings::get_singleton()->get_settings_path() + "/tmp/tmp" + config_file;
+ String engine_cfb = EditorSettings::get_singleton()->get_cache_dir().plus_file("tmp" + config_file);
ProjectSettings::get_singleton()->save_custom(engine_cfb, custom_map, custom_list);
Vector<uint8_t> data = FileAccess::get_file_as_array(engine_cfb);
@@ -703,19 +753,29 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &
return OK;
}
-Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, const String &p_path) {
+Error EditorExportPlatform::_add_shared_object(void *p_userdata, const SharedObject &p_so) {
+ PackData *pack_data = (PackData *)p_userdata;
+ if (pack_data->so_files) {
+ pack_data->so_files->push_back(p_so);
+ }
+
+ return OK;
+}
+
+Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, const String &p_path, Vector<SharedObject> *p_so_files) {
EditorProgress ep("savepack", TTR("Packing"), 102);
- String tmppath = EditorSettings::get_singleton()->get_settings_path() + "/tmp/packtmp";
+ String tmppath = EditorSettings::get_singleton()->get_cache_dir().plus_file("packtmp");
FileAccess *ftmp = FileAccess::open(tmppath, FileAccess::WRITE);
ERR_FAIL_COND_V(!ftmp, ERR_CANT_CREATE)
PackData pd;
pd.ep = &ep;
pd.f = ftmp;
+ pd.so_files = p_so_files;
- Error err = export_project_files(p_preset, _save_pack_file, &pd);
+ Error err = export_project_files(p_preset, _save_pack_file, &pd, _add_shared_object);
memdelete(ftmp); //close tmp file
@@ -927,13 +987,10 @@ void EditorExport::_save() {
}
config->save("res://export_presets.cfg");
-
- print_line("saved ok");
}
void EditorExport::save_presets() {
- print_line("save presets");
if (block_save)
return;
save_timer->start();
@@ -987,7 +1044,7 @@ void EditorExport::remove_export_preset(int p_idx) {
void EditorExport::add_export_plugin(const Ref<EditorExportPlugin> &p_plugin) {
- if (export_plugins.find(p_plugin) == 1) {
+ if (export_plugins.find(p_plugin) == -1) {
export_plugins.push_back(p_plugin);
}
}
@@ -1223,6 +1280,7 @@ String EditorExportPlatformPC::get_binary_extension() const {
}
Error EditorExportPlatformPC::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
+ ExportNotifier notifier(*this, p_preset, p_debug, p_path, p_flags);
String custom_debug = p_preset->get("custom_template/debug");
String custom_release = p_preset->get("custom_template/release");
diff --git a/editor/editor_export.h b/editor/editor_export.h
index 50379b9683..346c3b58e1 100644
--- a/editor/editor_export.h
+++ b/editor/editor_export.h
@@ -118,13 +118,24 @@ public:
EditorExportPreset();
};
+struct SharedObject {
+ String path;
+ Vector<String> tags;
+
+ SharedObject(const String &p_path, const Vector<String> &p_tags)
+ : path(p_path), tags(p_tags) {
+ }
+
+ SharedObject() {}
+};
+
class EditorExportPlatform : public Reference {
GDCLASS(EditorExportPlatform, Reference)
public:
typedef Error (*EditorExportSaveFunction)(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total);
- typedef Error (*EditorExportSaveSharedObject)(void *p_userdata, const String &p_path);
+ typedef Error (*EditorExportSaveSharedObject)(void *p_userdata, const SharedObject &p_so);
private:
struct SavedData {
@@ -144,6 +155,7 @@ private:
FileAccess *f;
Vector<SavedData> file_ofs;
EditorProgress *ep;
+ Vector<SharedObject> *so_files;
};
struct ZipData {
@@ -152,6 +164,11 @@ private:
EditorProgress *ep;
};
+ struct FeatureContainers {
+ Set<String> features;
+ PoolVector<String> features_pv;
+ };
+
void _export_find_resources(EditorFileSystemDirectory *p_dir, Set<String> &p_paths);
void _export_find_dependencies(const String &p_path, Set<String> &p_paths);
@@ -162,7 +179,16 @@ private:
void _edit_files_with_filter(DirAccess *da, const Vector<String> &p_filters, Set<String> &r_list, bool exclude);
void _edit_filter_list(Set<String> &r_list, const String &p_filter, bool exclude);
+ static Error _add_shared_object(void *p_userdata, const SharedObject &p_so);
+
protected:
+ struct ExportNotifier {
+ ExportNotifier(EditorExportPlatform &p_platform, const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags);
+ ~ExportNotifier();
+ };
+
+ FeatureContainers get_feature_containers(const Ref<EditorExportPreset> &p_preset);
+
bool exists_export_template(String template_file_name, String *err) const;
String find_export_template(String template_file_name, String *err = NULL) const;
void gen_export_flags(Vector<String> &r_flags, int p_flags);
@@ -192,7 +218,7 @@ public:
Error export_project_files(const Ref<EditorExportPreset> &p_preset, EditorExportSaveFunction p_func, void *p_udata, EditorExportSaveSharedObject p_so_func = NULL);
- Error save_pack(const Ref<EditorExportPreset> &p_preset, const String &p_path);
+ Error save_pack(const Ref<EditorExportPreset> &p_preset, const String &p_path, Vector<SharedObject> *p_so_files = NULL);
Error save_zip(const Ref<EditorExportPreset> &p_preset, const String &p_path);
virtual bool poll_devices() { return false; }
@@ -225,7 +251,7 @@ class EditorExportPlugin : public Reference {
friend class EditorExportPlatform;
- Vector<String> shared_objects;
+ Vector<SharedObject> shared_objects;
struct ExtraFile {
String path;
Vector<uint8_t> data;
@@ -234,26 +260,53 @@ class EditorExportPlugin : public Reference {
Vector<ExtraFile> extra_files;
bool skipped;
+ Vector<String> ios_frameworks;
+ String ios_plist_content;
+ String ios_linker_flags;
+ Vector<String> ios_bundle_files;
+ String ios_cpp_code;
+
_FORCE_INLINE_ void _clear() {
shared_objects.clear();
extra_files.clear();
skipped = false;
}
+ _FORCE_INLINE_ void _export_end() {
+ ios_frameworks.clear();
+ ios_bundle_files.clear();
+ ios_plist_content = "";
+ ios_linker_flags = "";
+ ios_cpp_code = "";
+ }
+
void _export_file_script(const String &p_path, const String &p_type, const PoolVector<String> &p_features);
- void _export_begin_script(const PoolVector<String> &p_features);
+ void _export_begin_script(const PoolVector<String> &p_features, bool p_debug, const String &p_path, int p_flags);
protected:
void add_file(const String &p_path, const Vector<uint8_t> &p_file, bool p_remap);
- void add_shared_object(const String &p_path);
+ void add_shared_object(const String &p_path, const Vector<String> &tags);
+
+ void add_ios_framework(const String &p_path);
+ void add_ios_plist_content(const String &p_plist_content);
+ void add_ios_linker_flags(const String &p_flags);
+ void add_ios_bundle_file(const String &p_path);
+ void add_ios_cpp_code(const String &p_code);
+
void skip();
virtual void _export_file(const String &p_path, const String &p_type, const Set<String> &p_features);
- virtual void _export_begin(const Set<String> &p_features);
+ virtual void _export_begin(const Set<String> &p_features, bool p_debug, const String &p_path, int p_flags);
static void _bind_methods();
public:
+ Vector<String> get_ios_frameworks() const;
+ String get_ios_plist_content() const;
+ String get_ios_linker_flags() const;
+ Vector<String> get_ios_bundle_files() const;
+ String get_ios_cpp_code() const;
+
EditorExportPlugin();
};
diff --git a/editor/editor_file_dialog.cpp b/editor/editor_file_dialog.cpp
index b980c4f0ec..f8b9425a4e 100644
--- a/editor/editor_file_dialog.cpp
+++ b/editor/editor_file_dialog.cpp
@@ -541,6 +541,9 @@ void EditorFileDialog::update_file_list() {
while ((item = dir_access->get_next(&isdir)) != "") {
+ if (item == ".")
+ continue;
+
ishidden = dir_access->current_is_hidden();
if (show_hidden || !ishidden) {
@@ -562,7 +565,7 @@ void EditorFileDialog::update_file_list() {
while (!dirs.empty()) {
const String &dir_name = dirs.front()->get();
- item_list->add_item(dir_name + "/");
+ item_list->add_item(dir_name);
if (display_mode == DISPLAY_THUMBNAILS) {
@@ -1368,35 +1371,41 @@ EditorFileDialog::EditorFileDialog() {
VBoxContainer *item_vb = memnew(VBoxContainer);
list_hb->add_child(item_vb);
- item_vb->set_h_size_flags(SIZE_EXPAND_FILL);
- item_list = memnew(ItemList);
- item_list->set_v_size_flags(SIZE_EXPAND_FILL);
- item_vb->add_margin_child(TTR("Directories & Files:"), item_list, true);
+ HBoxContainer *preview_hb = memnew(HBoxContainer);
+ preview_hb->set_v_size_flags(SIZE_EXPAND_FILL);
+ item_vb->add_child(preview_hb);
- HBoxContainer *filter_hb = memnew(HBoxContainer);
- item_vb->add_child(filter_hb);
+ VBoxContainer *list_vb = memnew(VBoxContainer);
+ list_vb->set_h_size_flags(SIZE_EXPAND_FILL);
+ list_vb->add_child(memnew(Label(TTR("Directories & Files:"))));
+ preview_hb->add_child(list_vb);
- VBoxContainer *filter_vb = memnew(VBoxContainer);
- filter_hb->add_child(filter_vb);
- filter_vb->set_h_size_flags(SIZE_EXPAND_FILL);
+ item_list = memnew(ItemList);
+ item_list->set_v_size_flags(SIZE_EXPAND_FILL);
+ list_vb->add_child(item_list);
preview_vb = memnew(VBoxContainer);
- filter_hb->add_child(preview_vb);
+ preview_hb->add_child(preview_vb);
CenterContainer *prev_cc = memnew(CenterContainer);
preview_vb->add_margin_child(TTR("Preview:"), prev_cc);
preview = memnew(TextureRect);
prev_cc->add_child(preview);
preview_vb->hide();
+ HBoxContainer *filename_hbc = memnew(HBoxContainer);
+ filename_hbc->add_child(memnew(Label(TTR("File:"))));
file = memnew(LineEdit);
- //add_child(file);
- filter_vb->add_margin_child(TTR("File:"), file);
-
+ file->set_stretch_ratio(4);
+ file->set_h_size_flags(SIZE_EXPAND_FILL);
+ filename_hbc->add_child(file);
filter = memnew(OptionButton);
- //add_child(filter);
- filter_vb->add_margin_child(TTR("Filter:"), filter);
+ filter->set_stretch_ratio(3);
+ filter->set_h_size_flags(SIZE_EXPAND_FILL);
filter->set_clip_text(true); //too many extensions overflow it
+ filename_hbc->add_child(filter);
+ filename_hbc->set_h_size_flags(SIZE_EXPAND_FILL);
+ item_vb->add_child(filename_hbc);
dir_access = DirAccess::create(DirAccess::ACCESS_RESOURCES);
access = ACCESS_RESOURCES;
diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp
index 4ae786391b..8d5bad3346 100644
--- a/editor/editor_file_system.cpp
+++ b/editor/editor_file_system.cpp
@@ -188,7 +188,7 @@ void EditorFileSystem::_scan_filesystem() {
String project = ProjectSettings::get_singleton()->get_resource_path();
- String fscache = EditorSettings::get_singleton()->get_project_settings_path().plus_file("filesystem_cache3");
+ String fscache = EditorSettings::get_singleton()->get_project_settings_dir().plus_file("filesystem_cache3");
FileAccess *f = FileAccess::open(fscache, FileAccess::READ);
if (f) {
@@ -238,19 +238,14 @@ void EditorFileSystem::_scan_filesystem() {
memdelete(f);
}
- String update_cache = EditorSettings::get_singleton()->get_project_settings_path().plus_file("filesystem_update3");
+ String update_cache = EditorSettings::get_singleton()->get_project_settings_dir().plus_file("filesystem_update3");
- print_line("try to see fs update2");
if (FileAccess::exists(update_cache)) {
-
- print_line("it exists");
-
{
FileAccessRef f = FileAccess::open(update_cache, FileAccess::READ);
String l = f->get_line().strip_edges();
while (l != String()) {
- print_line("erased cache for: " + l + " " + itos(file_cache.has(l)));
file_cache.erase(l); //erase cache for this, so it gets updated
l = f->get_line().strip_edges();
}
@@ -278,9 +273,6 @@ void EditorFileSystem::_scan_filesystem() {
memdelete(d);
- //save back the findings
- //String fscache = EditorSettings::get_singleton()->get_project_settings_path().plus_file("file_cache");
-
f = FileAccess::open(fscache, FileAccess::WRITE);
_save_filesystem_cache(new_filesystem, f);
f->close();
@@ -290,7 +282,7 @@ void EditorFileSystem::_scan_filesystem() {
}
void EditorFileSystem::_save_filesystem_cache() {
- String fscache = EditorSettings::get_singleton()->get_project_settings_path().plus_file("filesystem_cache3");
+ String fscache = EditorSettings::get_singleton()->get_project_settings_dir().plus_file("filesystem_cache3");
FileAccess *f = FileAccess::open(fscache, FileAccess::WRITE);
_save_filesystem_cache(filesystem, f);
@@ -322,7 +314,6 @@ bool EditorFileSystem::_update_scan_actions() {
} break;
case ItemAction::ACTION_DIR_ADD: {
- //print_line("*ACTION ADD DIR: "+ia.new_dir->get_name());
int idx = 0;
for (int i = 0; i < ia.dir->subdirs.size(); i++) {
@@ -341,7 +332,6 @@ bool EditorFileSystem::_update_scan_actions() {
case ItemAction::ACTION_DIR_REMOVE: {
ERR_CONTINUE(!ia.dir->parent);
- //print_line("*ACTION REMOVE DIR: "+ia.dir->get_name());
ia.dir->parent->subdirs.erase(ia.dir);
memdelete(ia.dir);
fs_changed = true;
@@ -362,7 +352,6 @@ bool EditorFileSystem::_update_scan_actions() {
}
fs_changed = true;
- //print_line("*ACTION ADD FILE: "+ia.new_file->file);
} break;
case ItemAction::ACTION_FILE_REMOVE: {
@@ -374,7 +363,6 @@ bool EditorFileSystem::_update_scan_actions() {
ia.dir->files.remove(idx);
fs_changed = true;
- //print_line("*ACTION REMOVE FILE: "+ia.file);
} break;
case ItemAction::ACTION_FILE_REIMPORT: {
@@ -512,7 +500,6 @@ bool EditorFileSystem::_check_missing_imported_files(const String &p_path) {
for (List<String>::Element *E = to_check.front(); E; E = E->next()) {
if (!FileAccess::exists(E->get())) {
- print_line("missing " + E->get() + ", reimport");
return false;
}
}
@@ -639,22 +626,7 @@ void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir, DirAccess
} else {
- if (!fc) {
- print_line("REIMPORT BECAUSE: not previously found");
- } else if (fc->modification_time != mt) {
- print_line("REIMPORT BECAUSE: modified resource time " + itos(fc->modification_time) + " vs " + itos(mt));
-
- } else if (fc->import_modification_time != import_mt) {
- print_line("REIMPORT BECAUSE: modified .import time" + itos(fc->import_modification_time) + " vs " + itos(import_mt));
-
- } else {
-
- print_line("REIMPORT BECAUSE: missing imported files");
- }
-
fi->type = ResourceFormatImporter::get_singleton()->get_resource_type(path);
- //fi->deps = ResourceLoader::get_dependencies(path); pointless because it will be reimported, but..
- print_line("import extension tried resource type for " + path + " and its " + fi->type);
fi->modified_time = 0;
fi->import_modified_time = 0;
fi->import_valid = ResourceLoader::is_import_valid(path);
@@ -678,7 +650,6 @@ void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir, DirAccess
//new or modified time
fi->type = ResourceLoader::get_resource_type(path);
fi->deps = _get_dependencies(path);
- print_line("regular import tried resource type for " + path + " and its " + fi->type);
fi->modified_time = mt;
fi->import_modified_time = 0;
fi->import_valid = true;
@@ -697,8 +668,6 @@ void EditorFileSystem::_scan_fs_changes(EditorFileSystemDirectory *p_dir, const
bool updated_dir = false;
String cd = p_dir->get_path();
- //print_line("dir: "+p_dir->get_path()+" MODTIME: "+itos(p_dir->modified_time)+" CTIME: "+itos(current_mtime));
-
if (current_mtime != p_dir->modified_time) {
updated_dir = true;
@@ -791,11 +760,6 @@ void EditorFileSystem::_scan_fs_changes(EditorFileSystemDirectory *p_dir, const
if (import_extensions.has(ext)) {
//if it can be imported, and it was added, it needs to be reimported
- print_line("REIMPORT: file was not found before, reimport");
- print_line("at dir: " + p_dir->get_path() + " file: " + f);
- for (int i = 0; i < p_dir->files.size(); i++) {
- print_line(itos(i) + ": " + p_dir->files[i]->file);
- }
ItemAction ia;
ia.action = ItemAction::ACTION_FILE_REIMPORT;
ia.dir = p_dir;
@@ -835,20 +799,15 @@ void EditorFileSystem::_scan_fs_changes(EditorFileSystemDirectory *p_dir, const
bool reimport = false;
if (mt != p_dir->files[i]->modified_time) {
- print_line("REIMPORT: modified time changed, reimport");
reimport = true; //it was modified, must be reimported.
} else if (!FileAccess::exists(path + ".import")) {
- print_line("REIMPORT: no .import exists, reimport");
reimport = true; //no .import file, obviously reimport
} else {
uint64_t import_mt = FileAccess::get_modified_time(path + ".import");
- //print_line(itos(import_mt) + " vs " + itos(p_dir->files[i]->import_modified_time));
if (import_mt != p_dir->files[i]->import_modified_time) {
- print_line("REIMPORT: import modified changed, reimport");
reimport = true;
} else if (!_check_missing_imported_files(path)) {
- print_line("REIMPORT: imported files removed");
reimport = true;
}
}
@@ -862,8 +821,6 @@ void EditorFileSystem::_scan_fs_changes(EditorFileSystemDirectory *p_dir, const
scan_actions.push_back(ia);
}
}
-
- EditorResourcePreview::get_singleton()->check_for_invalidation(p_dir->get_file_path(i));
}
for (int i = 0; i < p_dir->subdirs.size(); i++) {
@@ -947,9 +904,6 @@ void EditorFileSystem::scan_changes() {
Thread::Settings s;
s.priority = Thread::PRIORITY_LOW;
thread_sources = Thread::create(_thread_func_sources, this, s);
- //tree->hide();
- //print_line("SCAN BEGIN!");
- //progress->show();
}
}
@@ -959,7 +913,8 @@ void EditorFileSystem::_notification(int p_what) {
case NOTIFICATION_ENTER_TREE: {
- scan();
+ call_deferred("scan"); //this should happen after every editor node entered the tree
+
} break;
case NOTIFICATION_EXIT_TREE: {
if (use_threads && thread) {
@@ -1000,7 +955,6 @@ void EditorFileSystem::_notification(int p_what) {
thread_sources = NULL;
if (_update_scan_actions())
emit_signal("filesystem_changed");
- //print_line("sources changed: "+itos(sources_changed.size()));
emit_signal("sources_changed", sources_changed.size() > 0);
}
} else if (!scanning) {
@@ -1017,10 +971,6 @@ void EditorFileSystem::_notification(int p_what) {
_update_scan_actions();
emit_signal("filesystem_changed");
emit_signal("sources_changed", sources_changed.size() > 0);
- //print_line("initial sources changed: "+itos(sources_changed.size()));
-
- } else {
- //progress->set_text("Scanning...\n"+itos(total*100)+"%");
}
}
} break;
@@ -1230,7 +1180,7 @@ EditorFileSystemDirectory *EditorFileSystem::get_filesystem_path(const String &p
void EditorFileSystem::_save_late_updated_files() {
//files that already existed, and were modified, need re-scanning for dependencies upon project restart. This is done via saving this special file
- String fscache = EditorSettings::get_singleton()->get_project_settings_path().plus_file("filesystem_update3");
+ String fscache = EditorSettings::get_singleton()->get_project_settings_dir().plus_file("filesystem_update3");
FileAccessRef f = FileAccess::open(fscache, FileAccess::WRITE);
for (Set<String>::Element *E = late_update_files.front(); E; E = E->next()) {
f->store_line(E->get());
@@ -1239,7 +1189,6 @@ void EditorFileSystem::_save_late_updated_files() {
void EditorFileSystem::_resource_saved(const String &p_path) {
- //print_line("resource saved: "+p_path);
EditorFileSystem::get_singleton()->update_file(p_path);
}
@@ -1311,23 +1260,16 @@ void EditorFileSystem::update_file(const String &p_file) {
_save_late_updated_files(); //files need to be updated in the re-scan
}
- //print_line("UPDATING: "+p_file);
fs->files[cpos]->type = type;
fs->files[cpos]->modified_time = FileAccess::get_modified_time(p_file);
fs->files[cpos]->deps = _get_dependencies(p_file);
fs->files[cpos]->import_valid = ResourceLoader::is_import_valid(p_file);
- //if (FileAccess::exists(p_file+".import")) {
- // fs->files[cpos]->import_modified_time=FileAccess::get_modified_time(p_file+".import");
- //}
- EditorResourcePreview::get_singleton()->call_deferred("check_for_invalidation", p_file);
call_deferred("emit_signal", "filesystem_changed"); //update later
}
void EditorFileSystem::_reimport_file(const String &p_file) {
- print_line("REIMPORTING: " + p_file);
-
EditorFileSystemDirectory *fs = NULL;
int cpos = -1;
bool found = _find_file(p_file, &fs, cpos);
@@ -1492,6 +1434,8 @@ void EditorFileSystem::_reimport_file(const String &p_file) {
r->set_import_last_modified_time(0);
}
}
+
+ EditorResourcePreview::get_singleton()->check_for_invalidation(p_file);
}
void EditorFileSystem::reimport_files(const Vector<String> &p_files) {
diff --git a/editor/editor_fonts.cpp b/editor/editor_fonts.cpp
index 05f9da03e1..7e20077fd6 100644
--- a/editor/editor_fonts.cpp
+++ b/editor/editor_fonts.cpp
@@ -122,20 +122,24 @@ void editor_register_fonts(Ref<Theme> p_theme) {
dfmono->set_font_ptr(_font_Hack_Regular, _font_Hack_Regular_size);
//dfd->set_force_autohinter(true); //just looks better..i think?
- MAKE_DEFAULT_FONT(df, int(EditorSettings::get_singleton()->get("interface/editor/font_size")) * EDSCALE);
+ int default_font_size = int(EditorSettings::get_singleton()->get("interface/editor/font_size")) * EDSCALE;
+ MAKE_DEFAULT_FONT(df, default_font_size);
p_theme->set_default_theme_font(df);
+ MAKE_DEFAULT_FONT(df_title, default_font_size + 2 * EDSCALE);
+ p_theme->set_font("title", "EditorFonts", df_title);
+
//Ref<BitmapFont> doc_font = make_font(_bi_font_doc_font_height,_bi_font_doc_font_ascent,0,_bi_font_doc_font_charcount,_bi_font_doc_font_characters,p_theme->get_icon("DocFont","EditorIcons"));
//Ref<BitmapFont> doc_title_font = make_font(_bi_font_doc_title_font_height,_bi_font_doc_title_font_ascent,0,_bi_font_doc_title_font_charcount,_bi_font_doc_title_font_characters,p_theme->get_icon("DocTitleFont","EditorIcons"));
//Ref<BitmapFont> doc_code_font = make_font(_bi_font_doc_code_font_height,_bi_font_doc_code_font_ascent,0,_bi_font_doc_code_font_charcount,_bi_font_doc_code_font_characters,p_theme->get_icon("DocCodeFont","EditorIcons"));
- MAKE_DEFAULT_FONT(df_title, int(EDITOR_DEF("text_editor/help/help_title_font_size", 16)) * EDSCALE);
+ MAKE_DEFAULT_FONT(df_doc_title, int(EDITOR_DEF("text_editor/help/help_title_font_size", 16)) * EDSCALE);
MAKE_DEFAULT_FONT(df_doc, int(EDITOR_DEF("text_editor/help/help_font_size", 14)) * EDSCALE);
p_theme->set_font("doc", "EditorFonts", df_doc);
- p_theme->set_font("doc_title", "EditorFonts", df_title);
+ p_theme->set_font("doc_title", "EditorFonts", df_doc_title);
MAKE_DEFAULT_FONT(df_rulers, int(EDITOR_DEF("canvas_item_editor/rulers", 8)) * EDSCALE);
p_theme->set_font("rulers", "EditorFonts", df_rulers);
@@ -176,9 +180,4 @@ void editor_register_fonts(Ref<Theme> p_theme) {
df_output_code->set_font_data(dfmono);
MAKE_FALLBACKS(df_output_code);
p_theme->set_font("status_source", "EditorFonts", df_output_code);
-
- //replace default theme
- Ref<Texture> di;
- Ref<StyleBox> ds;
- fill_default_theme(p_theme, df, df_doc, di, ds, EDSCALE);
}
diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp
index cb94ea72d1..4b372e7afd 100644
--- a/editor/editor_help.cpp
+++ b/editor/editor_help.cpp
@@ -555,7 +555,7 @@ void EditorHelp::_class_desc_select(const String &p_select) {
if (select.find(".") != -1) {
class_name = select.get_slice(".", 0);
} else {
- class_name = "@Global Scope";
+ class_name = "@GlobalScope";
}
emit_signal("go_to_help", "class_enum:" + class_name + ":" + select);
return;
@@ -564,18 +564,37 @@ void EditorHelp::_class_desc_select(const String &p_select) {
emit_signal("go_to_help", "class_name:" + p_select.substr(1, p_select.length()));
return;
} else if (p_select.begins_with("@")) {
+ String tag = p_select.substr(1, 6);
+ String link = p_select.substr(7, p_select.length());
+
+ String topic;
+ Map<String, int> *table = NULL;
+
+ if (tag == "method") {
+ topic = "class_method";
+ table = &this->method_line;
+ } else if (tag == "member") {
+ topic = "class_property";
+ table = &this->property_line;
+ } else if (tag == "enum ") {
+ topic = "class_enum";
+ table = &this->enum_line;
+ } else if (tag == "signal") {
+ topic = "class_signal";
+ table = &this->signal_line;
+ } else {
+ return;
+ }
- String m = p_select.substr(1, p_select.length());
-
- if (m.find(".") != -1) {
+ if (link.find(".") != -1) {
//must go somewhere else
- emit_signal("go_to_help", "class_method:" + m.get_slice(".", 0) + ":" + m.get_slice(".", 0));
+ emit_signal("go_to_help", topic + ":" + link.get_slice(".", 0) + ":" + link.get_slice(".", 1));
} else {
- if (!method_line.has(m))
+ if (!table->has(link))
return;
- class_desc->scroll_to_line(method_line[m]);
+ class_desc->scroll_to_line((*table)[link]);
}
} else if (p_select.begins_with("http")) {
OS::get_singleton()->shell_open(p_select);
@@ -694,7 +713,7 @@ Error EditorHelp::_goto_desc(const String &p_class, int p_vscr) {
inherits = doc->class_list[inherits].inherits;
if (inherits != "") {
- class_desc->add_text(" , ");
+ class_desc->add_text(" < ");
}
}
@@ -808,7 +827,7 @@ Error EditorHelp::_goto_desc(const String &p_class, int p_vscr) {
}
class_desc->push_cell();
if (describe) {
- class_desc->push_meta("@" + cd.properties[i].name);
+ class_desc->push_meta("@member" + cd.properties[i].name);
}
class_desc->push_font(doc_code_font);
@@ -881,7 +900,7 @@ Error EditorHelp::_goto_desc(const String &p_class, int p_vscr) {
if (methods[i].description != "") {
method_descr = true;
- class_desc->push_meta("@" + methods[i].name);
+ class_desc->push_meta("@method" + methods[i].name);
}
class_desc->push_color(headline_color);
_add_text(methods[i].name);
@@ -1045,12 +1064,17 @@ Error EditorHelp::_goto_desc(const String &p_class, int p_vscr) {
class_desc->pop(); // end monofont
if (cd.signals[i].description != "") {
+ class_desc->push_font(doc_font);
class_desc->push_color(comment_color);
- class_desc->add_text(" ");
+ class_desc->push_indent(1);
+ // class_desc->add_text(" ");
_add_text(cd.signals[i].description);
+ class_desc->pop(); // indent
class_desc->pop();
+ class_desc->pop(); // font
}
class_desc->add_newline();
+ class_desc->add_newline();
}
class_desc->pop();
@@ -1129,11 +1153,14 @@ Error EditorHelp::_goto_desc(const String &p_class, int p_vscr) {
class_desc->pop();
if (enum_list[i].description != "") {
class_desc->push_font(doc_font);
- class_desc->add_text(" ");
+ //class_desc->add_text(" ");
+ class_desc->push_indent(1);
class_desc->push_color(comment_color);
_add_text(enum_list[i].description);
class_desc->pop();
class_desc->pop();
+ class_desc->pop(); // indent
+ class_desc->add_newline();
}
class_desc->add_newline();
@@ -1177,11 +1204,14 @@ Error EditorHelp::_goto_desc(const String &p_class, int p_vscr) {
class_desc->pop();
if (constants[i].description != "") {
class_desc->push_font(doc_font);
- class_desc->add_text(" ");
+ class_desc->push_indent(1);
+ //class_desc->add_text(" ");
class_desc->push_color(comment_color);
_add_text(constants[i].description);
class_desc->pop();
class_desc->pop();
+ class_desc->pop(); // indent
+ class_desc->add_newline();
}
class_desc->add_newline();
@@ -1229,56 +1259,64 @@ Error EditorHelp::_goto_desc(const String &p_class, int p_vscr) {
for (int i = 0; i < cd.properties.size(); i++) {
- method_line[cd.properties[i].name] = class_desc->get_line_count() - 2;
+ property_line[cd.properties[i].name] = class_desc->get_line_count() - 2;
+ class_desc->push_table(2);
+ class_desc->set_table_column_expand(1, 1);
+
+ class_desc->push_cell();
class_desc->push_font(doc_code_font);
_add_type(cd.properties[i].type, cd.properties[i].enumeration);
-
class_desc->add_text(" ");
+ class_desc->pop(); // font
+ class_desc->pop(); // cell
+
+ class_desc->push_cell();
+ class_desc->push_font(doc_code_font);
class_desc->push_color(headline_color);
_add_text(cd.properties[i].name);
- class_desc->pop(); //color
-
- class_desc->add_text(" ");
+ class_desc->pop(); // color
+ class_desc->pop(); // font
+ class_desc->pop(); // cell
- class_desc->pop(); //font
+ //class_desc->add_text(" ");
if (cd.properties[i].setter != "") {
- class_desc->push_font(doc_font);
-
- class_desc->push_indent(2);
- class_desc->push_color(comment_color);
- class_desc->add_text("Setter: ");
- class_desc->pop();
+ class_desc->push_cell();
+ class_desc->pop(); // cell
+ class_desc->push_cell();
+ class_desc->push_font(doc_code_font);
class_desc->push_color(text_color);
class_desc->add_text(cd.properties[i].setter + "(value)");
- class_desc->pop(); //color
-
- class_desc->pop(); //indent
-
- class_desc->pop(); //font
+ class_desc->pop(); // color
+ class_desc->push_color(comment_color);
+ class_desc->add_text(" setter");
+ class_desc->pop(); // color
+ class_desc->pop(); // font
+ class_desc->pop(); // cell
}
if (cd.properties[i].getter != "") {
- class_desc->push_font(doc_font);
-
- class_desc->push_indent(2);
- class_desc->push_color(comment_color);
- class_desc->add_text("Getter: ");
- class_desc->pop();
+ class_desc->push_cell();
+ class_desc->pop(); // cell
+ class_desc->push_cell();
+ class_desc->push_font(doc_code_font);
class_desc->push_color(text_color);
class_desc->add_text(cd.properties[i].getter + "()");
class_desc->pop(); //color
-
- class_desc->pop(); //indent
-
+ class_desc->push_color(comment_color);
+ class_desc->add_text(" getter");
+ class_desc->pop(); //color
class_desc->pop(); //font
+ class_desc->pop(); //cell
}
+ class_desc->pop(); // table
+
class_desc->add_newline();
class_desc->push_color(text_color);
@@ -1433,7 +1471,6 @@ void EditorHelp::_help_callback(const String &p_topic) {
line = property_line[name];
} else if (what == "class_enum") {
- print_line("go to enum:");
if (enum_line.has(name))
line = enum_line[name];
} else if (what == "class_theme_item") {
@@ -1459,9 +1496,10 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt) {
Color font_color_hl = p_rt->get_color("headline_color", "EditorHelp");
Color link_color = p_rt->get_color("accent_color", "Editor").linear_interpolate(font_color_hl, 0.8);
- String bbcode = p_bbcode.replace("\t", " ").replace("\r", " ").strip_edges();
+ String bbcode = p_bbcode.dedent().replace("\t", "").replace("\r", "").strip_edges();
List<String> tag_stack;
+ bool code_tag = false;
int pos = 0;
while (pos < bbcode.length()) {
@@ -1472,7 +1510,10 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt) {
brk_pos = bbcode.length();
if (brk_pos > pos) {
- p_rt->add_text(bbcode.substr(pos, brk_pos - pos));
+ String text = bbcode.substr(pos, brk_pos - pos);
+ if (!code_tag)
+ text = text.replace("\n", "\n\n");
+ p_rt->add_text(text);
}
if (brk_pos == bbcode.length())
@@ -1481,7 +1522,11 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt) {
int brk_end = bbcode.find("]", brk_pos + 1);
if (brk_end == -1) {
- p_rt->add_text(bbcode.substr(brk_pos, bbcode.length() - brk_pos));
+
+ String text = bbcode.substr(brk_pos, bbcode.length() - brk_pos);
+ if (!code_tag)
+ text = text.replace("\n", "\n\n");
+ p_rt->add_text(text);
break;
}
@@ -1490,27 +1535,31 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt) {
if (tag.begins_with("/")) {
bool tag_ok = tag_stack.size() && tag_stack.front()->get() == tag.substr(1, tag.length());
- if (tag_stack.size()) {
- }
if (!tag_ok) {
p_rt->add_text("[");
- pos++;
+ pos = brk_pos + 1;
continue;
}
tag_stack.pop_front();
pos = brk_end + 1;
+ code_tag = false;
if (tag != "/img")
p_rt->pop();
+ } else if (code_tag) {
+
+ p_rt->add_text("[");
+ pos = brk_pos + 1;
- } else if (tag.begins_with("method ")) {
+ } else if (tag.begins_with("method ") || tag.begins_with("member ") || tag.begins_with("signal ") || tag.begins_with("enum ")) {
- String m = tag.substr(7, tag.length());
+ String link_target = tag.substr(tag.find(" ") + 1, tag.length());
+ String link_tag = tag.substr(0, tag.find(" ")).rpad(6);
p_rt->push_color(link_color);
- p_rt->push_meta("@" + m);
- p_rt->add_text(m + "()");
+ p_rt->push_meta("@" + link_tag + link_target);
+ p_rt->add_text(link_target + (tag.begins_with("method ") ? "()" : ""));
p_rt->pop();
p_rt->pop();
pos = brk_end + 1;
@@ -1540,6 +1589,7 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt) {
//use monospace font
p_rt->push_font(doc_code_font);
+ code_tag = true;
pos = brk_end + 1;
tag_stack.push_front(tag);
} else if (tag == "center") {
@@ -1699,7 +1749,7 @@ void EditorHelp::_notification(int p_what) {
case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
- class_desc->add_color_override("selection_color", EDITOR_DEF("text_editor/highlighting/selection_color", Color(0.2, 0.2, 1)));
+ class_desc->add_color_override("selection_color", get_color("text_editor/theme/selection_color", "Editor"));
} break;
@@ -1788,7 +1838,7 @@ EditorHelp::EditorHelp() {
class_desc = memnew(RichTextLabel);
vbc->add_child(class_desc);
class_desc->set_v_size_flags(SIZE_EXPAND_FILL);
- class_desc->add_color_override("selection_color", EDITOR_DEF("text_editor/highlighting/selection_color", Color(0.2, 0.2, 1)));
+ class_desc->add_color_override("selection_color", get_color("text_editor/theme/selection_color", "Editor"));
class_desc->connect("meta_clicked", this, "_class_desc_select");
class_desc->connect("gui_input", this, "_class_desc_input");
}
@@ -1879,7 +1929,7 @@ void EditorHelpBit::_notification(int p_what) {
switch (p_what) {
case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
- rich_text->add_color_override("selection_color", EDITOR_DEF("text_editor/highlighting/selection_color", Color(0.2, 0.2, 1)));
+ rich_text->add_color_override("selection_color", get_color("text_editor/theme/selection_color", "Editor"));
} break;
default: break;
@@ -1898,6 +1948,7 @@ EditorHelpBit::EditorHelpBit() {
add_child(rich_text);
rich_text->set_anchors_and_margins_preset(Control::PRESET_WIDE);
rich_text->connect("meta_clicked", this, "_meta_clicked");
- rich_text->add_color_override("selection_color", EDITOR_DEF("text_editor/highlighting/selection_color", Color(0.2, 0.2, 1)));
+ rich_text->add_color_override("selection_color", get_color("text_editor/theme/selection_color", "Editor"));
+ rich_text->set_override_selected_font_color(false);
set_custom_minimum_size(Size2(0, 70 * EDSCALE));
}
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 4e0ad38320..a32ade3b71 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -141,13 +141,33 @@ void EditorNode::_update_scene_tabs() {
}
scene_tabs->set_current_tab(editor_data.get_edited_scene());
- scene_tabs->ensure_tab_visible(editor_data.get_edited_scene());
+
+ int current = editor_data.get_edited_scene();
+ if (scene_tabs->get_offset_buttons_visible()) {
+ // move add button to fixed position on the tabbar
+ if (scene_tab_add->get_parent() == scene_tabs) {
+ scene_tab_add->set_position(Point2(0, 0));
+ scene_tabs->remove_child(scene_tab_add);
+ tabbar_container->add_child(scene_tab_add);
+ tabbar_container->move_child(scene_tab_add, 1);
+ }
+ } else {
+ // move add button to after last tab
+ if (scene_tab_add->get_parent() == tabbar_container) {
+ tabbar_container->remove_child(scene_tab_add);
+ scene_tabs->add_child(scene_tab_add);
+ }
+ Rect2 last_tab = Rect2();
+ if (scene_tabs->get_tab_count() != 0)
+ last_tab = scene_tabs->get_tab_rect(scene_tabs->get_tab_count() - 1);
+ scene_tab_add->set_position(Point2(last_tab.get_position().x + last_tab.get_size().x + 3, last_tab.get_position().y));
+ }
}
void EditorNode::_update_title() {
String appname = ProjectSettings::get_singleton()->get("application/config/name");
- String title = appname.empty() ? String(VERSION_FULL_NAME) : String(_MKSTR(VERSION_NAME) + String(" - ") + appname);
+ String title = appname.empty() ? String(VERSION_FULL_NAME) : String(VERSION_NAME + String(" - ") + appname);
String edited = editor_data.get_edited_scene_root() ? editor_data.get_edited_scene_root()->get_filename() : String();
if (!edited.empty())
title += " - " + String(edited.get_file());
@@ -283,10 +303,10 @@ void EditorNode::_notification(int p_what) {
if (p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) {
scene_tabs->set_tab_close_display_policy((bool(EDITOR_DEF("interface/editor/always_show_close_button_in_scene_tabs", false)) ? Tabs::CLOSE_BUTTON_SHOW_ALWAYS : Tabs::CLOSE_BUTTON_SHOW_ACTIVE_ONLY));
- property_editor->set_enable_capitalize_paths(bool(EDITOR_DEF("interface/editor/capitalize_properties", true)));
Ref<Theme> theme = create_editor_theme(theme_base->get_theme());
theme_base->set_theme(theme);
+ gui_base->set_theme(theme);
gui_base->add_style_override("panel", gui_base->get_stylebox("Background", "EditorStyles"));
play_button_panel->add_style_override("panel", gui_base->get_stylebox("PlayButtonPanel", "EditorStyles"));
@@ -308,6 +328,8 @@ void EditorNode::_notification(int p_what) {
}
_update_scene_tabs();
+ recent_scenes->set_as_minsize();
+
// debugger area
if (ScriptEditor::get_singleton()->get_debugger()->is_visible())
bottom_panel->add_style_override("panel", gui_base->get_stylebox("BottomPanelDebuggerOverride", "EditorStyles"));
@@ -324,6 +346,7 @@ void EditorNode::_notification(int p_what) {
prev_scene->set_icon(gui_base->get_icon("PrevScene", "EditorIcons"));
distraction_free->set_icon(gui_base->get_icon("DistractionFree", "EditorIcons"));
+ scene_tab_add->set_icon(gui_base->get_icon("Add", "EditorIcons"));
resource_new_button->set_icon(gui_base->get_icon("New", "EditorIcons"));
resource_load_button->set_icon(gui_base->get_icon("Load", "EditorIcons"));
@@ -341,6 +364,10 @@ void EditorNode::_notification(int p_what) {
dock_tab_move_right->set_icon(theme->get_icon("Forward", "EditorIcons"));
update_menu->set_icon(gui_base->get_icon("Progress1", "EditorIcons"));
}
+
+ if (p_what == Control::NOTIFICATION_RESIZED) {
+ _update_scene_tabs();
+ }
}
void EditorNode::_fs_changed() {
@@ -373,7 +400,18 @@ void EditorNode::_fs_changed() {
String err = "Preset \"" + export_defer.preset + "\" doesn't have a platform.";
ERR_PRINT(err.utf8().get_data());
} else {
- platform->export_project(preset, export_defer.debug, export_defer.path, /*p_flags*/ 0);
+ // ensures export_project does not loop infinitely, because notifications may
+ // come during the export
+ export_defer.preset = "";
+ if (!preset->is_runnable() && (export_defer.path.ends_with(".pck") || export_defer.path.ends_with(".zip"))) {
+ if (export_defer.path.ends_with(".zip")) {
+ platform->save_zip(preset, export_defer.path);
+ } else if (export_defer.path.ends_with(".pck")) {
+ platform->save_pack(preset, export_defer.path);
+ }
+ } else {
+ platform->export_project(preset, export_defer.debug, export_defer.path, /*p_flags*/ 0);
+ }
}
}
@@ -403,7 +441,6 @@ void EditorNode::_fs_changed() {
uint64_t mt = FileAccess::get_modified_time(E->get()->get_import_path());
if (mt != E->get()->get_import_last_modified_time()) {
- print_line("success");
changed.push_back(E->get());
}
#endif
@@ -428,7 +465,7 @@ void EditorNode::_fs_changed() {
}
void EditorNode::_resources_reimported(const Vector<String> &p_resources) {
- print_line("reimporting");
+
List<String> scenes; //will load later
for (int i = 0; i < p_resources.size(); i++) {
@@ -460,7 +497,6 @@ void EditorNode::_sources_changed(bool p_exist) {
if (defer_load_scene != "") {
- print_line("loading scene DEFERRED");
load_scene(defer_load_scene);
defer_load_scene = "";
}
@@ -701,7 +737,7 @@ void EditorNode::_get_scene_metadata(const String &p_file) {
if (!scene)
return;
- String path = EditorSettings::get_singleton()->get_project_settings_path().plus_file(p_file.get_file() + "-editstate-" + p_file.md5_text() + ".cfg");
+ String path = EditorSettings::get_singleton()->get_project_settings_dir().plus_file(p_file.get_file() + "-editstate-" + p_file.md5_text() + ".cfg");
Ref<ConfigFile> cf;
cf.instance();
@@ -735,7 +771,7 @@ void EditorNode::_set_scene_metadata(const String &p_file, int p_idx) {
scene->set_meta("__editor_run_settings__", Variant()); //clear it (no point in keeping it)
scene->set_meta("__editor_plugin_states__", Variant());
- String path = EditorSettings::get_singleton()->get_project_settings_path().plus_file(p_file.get_file() + "-editstate-" + p_file.md5_text() + ".cfg");
+ String path = EditorSettings::get_singleton()->get_project_settings_dir().plus_file(p_file.get_file() + "-editstate-" + p_file.md5_text() + ".cfg");
Ref<ConfigFile> cf;
cf.instance();
@@ -778,7 +814,6 @@ bool EditorNode::_find_and_save_resource(RES p_res, Map<RES, bool> &processed, i
if (p_res->get_path().is_resource_file()) {
if (changed || subchanged) {
//save
- print_line("Also saving modified external resource: " + p_res->get_path());
ResourceSaver::save(p_res->get_path(), p_res, flags);
}
processed[p_res] = false; //because it's a file
@@ -869,7 +904,7 @@ void EditorNode::_find_node_types(Node *p_node, int &count_2d, int &count_3d) {
_find_node_types(p_node->get_child(i), count_2d, count_3d);
}
-void EditorNode::_save_scene_with_preview(String p_file) {
+void EditorNode::_save_scene_with_preview(String p_file, int p_idx) {
EditorProgress save("save", TTR("Saving Scene"), 4);
save.step(TTR("Analyzing"), 0);
@@ -903,27 +938,33 @@ void EditorNode::_save_scene_with_preview(String p_file) {
int preview_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size");
preview_size *= EDSCALE;
- int width, height;
- if (img->get_width() > preview_size && img->get_width() >= img->get_height()) {
- width = preview_size;
- height = img->get_height() * preview_size / img->get_width();
- } else if (img->get_height() > preview_size && img->get_height() >= img->get_width()) {
+ // consider a square region
+ int vp_size = MIN(img->get_width(), img->get_height());
+ int x = (img->get_width() - vp_size) / 2;
+ int y = (img->get_height() - vp_size) / 2;
+
+ img->convert(Image::FORMAT_RGB8);
- height = preview_size;
- width = img->get_width() * preview_size / img->get_height();
+ if (vp_size < preview_size) {
+ // just square it.
+ img->crop_from_point(x, y, vp_size, vp_size);
} else {
+ int ratio = vp_size / preview_size;
+ int size = preview_size * (ratio / 2);
- width = img->get_width();
- height = img->get_height();
+ x = (img->get_width() - size) / 2;
+ y = (img->get_height() - size) / 2;
+
+ img->crop_from_point(x, y, size, size);
+ // We could get better pictures with better filters
+ img->resize(preview_size, preview_size, Image::INTERPOLATE_CUBIC);
}
- img->convert(Image::FORMAT_RGB8);
- img->resize(width, height);
img->flip_y();
//save thumbnail directly, as thumbnailer may not update due to actual scene not changing md5
- String temp_path = EditorSettings::get_singleton()->get_settings_path().plus_file("tmp");
+ String temp_path = EditorSettings::get_singleton()->get_cache_dir();
String cache_base = ProjectSettings::get_singleton()->globalize_path(p_file).md5_text();
cache_base = temp_path.plus_file("resthumb-" + cache_base);
@@ -935,7 +976,7 @@ void EditorNode::_save_scene_with_preview(String p_file) {
}
save.step(TTR("Saving Scene"), 4);
- _save_scene(p_file);
+ _save_scene(p_file, p_idx);
EditorResourcePreview::get_singleton()->check_for_invalidation(p_file);
}
@@ -1093,10 +1134,7 @@ void EditorNode::_dialog_action(String p_file) {
if (file->get_mode() == EditorFileDialog::MODE_SAVE_FILE) {
_save_default_environment();
- if (scene_idx != editor_data.get_edited_scene())
- _save_scene(p_file, scene_idx);
- else
- _save_scene_with_preview(p_file);
+ _save_scene_with_preview(p_file, scene_idx);
if (scene_idx != -1)
_discard_changes();
@@ -1109,7 +1147,7 @@ void EditorNode::_dialog_action(String p_file) {
_save_default_environment();
_save_scene_with_preview(p_file);
- _run(true);
+ _run(false, p_file);
}
} break;
@@ -1198,7 +1236,7 @@ void EditorNode::_dialog_action(String p_file) {
Ref<ConfigFile> config;
config.instance();
- Error err = config->load(EditorSettings::get_singleton()->get_settings_path().plus_file("editor_layouts-3.cfg"));
+ Error err = config->load(EditorSettings::get_singleton()->get_editor_layouts_config());
if (err == ERR_CANT_OPEN) {
config.instance(); // new config
@@ -1209,7 +1247,7 @@ void EditorNode::_dialog_action(String p_file) {
_save_docks_to_config(config, p_file);
- config->save(EditorSettings::get_singleton()->get_settings_path().plus_file("editor_layouts-3.cfg"));
+ config->save(EditorSettings::get_singleton()->get_editor_layouts_config());
layout_dialog->hide();
_update_layouts_menu();
@@ -1226,7 +1264,7 @@ void EditorNode::_dialog_action(String p_file) {
Ref<ConfigFile> config;
config.instance();
- Error err = config->load(EditorSettings::get_singleton()->get_settings_path().plus_file("editor_layouts-3.cfg"));
+ Error err = config->load(EditorSettings::get_singleton()->get_editor_layouts_config());
if (err != OK || !config->has_section(p_file)) {
show_warning(TTR("Layout name not found!"));
@@ -1240,7 +1278,7 @@ void EditorNode::_dialog_action(String p_file) {
config->set_value(p_file, E->get(), Variant());
}
- config->save(EditorSettings::get_singleton()->get_settings_path().plus_file("editor_layouts-3.cfg"));
+ config->save(EditorSettings::get_singleton()->get_editor_layouts_config());
layout_dialog->hide();
_update_layouts_menu();
@@ -1330,6 +1368,8 @@ void EditorNode::_prepare_history() {
}
} else if (Object::cast_to<Node>(obj)) {
text = Object::cast_to<Node>(obj)->get_name();
+ } else if (obj->is_class("ScriptEditorDebuggerInspectedObject")) {
+ text = obj->call("get_title");
} else {
text = obj->get_class();
}
@@ -1425,6 +1465,7 @@ void EditorNode::_edit_current() {
object_menu->set_disabled(true);
+ bool capitalize = bool(EDITOR_DEF("interface/editor/capitalize_properties", true));
bool is_resource = current_obj->is_class("Resource");
bool is_node = current_obj->is_class("Node");
resource_save_button->set_disabled(!is_resource);
@@ -1451,7 +1492,7 @@ void EditorNode::_edit_current() {
}
} else if (current_res->get_path().is_resource_file()) {
if (FileAccess::exists(current_res->get_path() + ".import")) {
- editable_warning = TTR("This resource was imported, so it's not editable. Change it's settings in the import panel and re-import.");
+ editable_warning = TTR("This resource was imported, so it's not editable. Change its settings in the import panel and then re-import.");
}
}
} else if (is_node) {
@@ -1478,6 +1519,11 @@ void EditorNode::_edit_current() {
} else {
+ if (current_obj->is_class("ScriptEditorDebuggerInspectedObject")) {
+ editable_warning = TTR("This is a remote object so changes to it will not be kept.\nPlease read the documentation relevant to debugging to better understand this workflow.");
+ capitalize = false;
+ }
+
property_editor->edit(current_obj);
node_dock->set_node(NULL);
}
@@ -1487,6 +1533,10 @@ void EditorNode::_edit_current() {
property_editable_warning_dialog->set_text(editable_warning);
}
+ if (property_editor->is_capitalize_paths_enabled() != capitalize) {
+ property_editor->set_enable_capitalize_paths(capitalize);
+ }
+
/* Take care of PLUGIN EDITOR */
EditorPlugin *main_plugin = editor_data.get_editor(current_obj);
@@ -1759,6 +1809,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
int idx = editor_data.add_edited_scene(-1);
_scene_tab_changed(idx);
editor_data.clear_editor_states();
+ _update_scene_tabs();
} break;
case FILE_NEW_INHERITED_SCENE:
@@ -1823,7 +1874,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
if (scene && scene->get_filename() != "") {
if (scene_idx != editor_data.get_edited_scene())
- _save_scene(scene->get_filename(), scene_idx);
+ _save_scene_with_preview(scene->get_filename(), scene_idx);
else
_save_scene_with_preview(scene->get_filename());
@@ -1931,6 +1982,15 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
} break;
case FILE_EXPORT_TILESET: {
+ //Make sure that the scene has a root before trying to convert to tileset
+ if (!editor_data.get_edited_scene_root()) {
+ current_option = -1;
+ accept->get_ok()->set_text(TTR("I see.."));
+ accept->set_text(TTR("This operation can't be done without a root node."));
+ accept->popup_centered_minsize();
+ break;
+ }
+
List<String> extensions;
Ref<TileSet> ml(memnew(TileSet));
ResourceSaver::get_recognized_extensions(ml, &extensions);
@@ -1988,7 +2048,6 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
case EDIT_UNDO: {
if (Input::get_singleton()->get_mouse_button_mask() & 0x7) {
- print_line("no because state");
break; // can't undo while mouse buttons are pressed
}
@@ -2669,12 +2728,12 @@ void EditorNode::set_addon_plugin_enabled(const String &p_addon, bool p_enabled)
String addon_path = "res://addons/" + p_addon + "/plugin.cfg";
Error err = cf->load(addon_path);
if (err != OK) {
- show_warning(TTR("Unable to enable addon plugin at: '") + addon_path + TTR("' parsing of config failed."));
+ show_warning(vformat(TTR("Unable to enable addon plugin at: '%s' parsing of config failed."), addon_path));
return;
}
if (!cf->has_section_key("plugin", "script")) {
- show_warning(TTR("Unable to find script field for addon plugin at: 'res://addons/") + p_addon + "''.");
+ show_warning(vformat(TTR("Unable to find script field for addon plugin at: 'res://addons/%s'."), p_addon));
return;
}
@@ -2684,18 +2743,18 @@ void EditorNode::set_addon_plugin_enabled(const String &p_addon, bool p_enabled)
Ref<Script> script = ResourceLoader::load(path);
if (script.is_null()) {
- show_warning(TTR("Unable to load addon script from path: '") + path + "'.");
+ show_warning(vformat(TTR("Unable to load addon script from path: '%s'."), path));
return;
}
//could check inheritance..
if (String(script->get_instance_base_type()) != "EditorPlugin") {
- show_warning(TTR("Unable to load addon script from path: '") + path + "' Base type is not EditorPlugin.");
+ show_warning(vformat(TTR("Unable to load addon script from path: '%s' Base type is not EditorPlugin."), path));
return;
}
if (!script->is_tool()) {
- show_warning(TTR("Unable to load addon script from path: '") + path + "' Script is not in tool mode.");
+ show_warning(vformat(TTR("Unable to load addon script from path: '%s' Script is not in tool mode."), path));
return;
}
@@ -2957,7 +3016,6 @@ Error EditorNode::load_scene(const String &p_scene, bool p_ignore_broken_deps, b
dependency_errors.clear();
- print_line("actually loading it");
Error err;
Ref<PackedScene> sdata = ResourceLoader::load(lpath, "", true, &err);
if (!sdata.is_valid()) {
@@ -3153,12 +3211,19 @@ void EditorNode::_add_to_recent_scenes(const String &p_scene) {
void EditorNode::_open_recent_scene(int p_idx) {
String base = "_" + ProjectSettings::get_singleton()->get_resource_path().replace("\\", "::").replace("/", "::");
- Vector<String> rc = EDITOR_DEF(base + "/_recent_scenes", Array());
- ERR_FAIL_INDEX(p_idx, rc.size());
+ if (p_idx == recent_scenes->get_item_count() - 1) {
+
+ EditorSettings::get_singleton()->erase(base + "/_recent_scenes");
+ call_deferred("_update_recent_scenes");
+ } else {
+
+ Vector<String> rc = EDITOR_DEF(base + "/_recent_scenes", Array());
+ ERR_FAIL_INDEX(p_idx, rc.size());
- String path = "res://" + rc[p_idx];
- load_scene(path);
+ String path = "res://" + rc[p_idx];
+ load_scene(path);
+ }
}
void EditorNode::_update_recent_scenes() {
@@ -3166,10 +3231,15 @@ void EditorNode::_update_recent_scenes() {
String base = "_" + ProjectSettings::get_singleton()->get_resource_path().replace("\\", "::").replace("/", "::");
Vector<String> rc = EDITOR_DEF(base + "/_recent_scenes", Array());
recent_scenes->clear();
+
for (int i = 0; i < rc.size(); i++) {
recent_scenes->add_item(rc[i], i);
}
+
+ recent_scenes->add_separator();
+ recent_scenes->add_shortcut(ED_SHORTCUT("editor/clear_recent", TTR("Clear Recent Scenes")));
+ recent_scenes->set_as_minsize();
}
void EditorNode::_quick_opened() {
@@ -3242,11 +3312,11 @@ void EditorNode::register_editor_types() {
ClassDB::register_class<EditorScript>();
ClassDB::register_class<EditorSelection>();
ClassDB::register_class<EditorFileDialog>();
- ClassDB::register_class<EditorSettings>();
+ ClassDB::register_virtual_class<EditorSettings>();
ClassDB::register_class<EditorSpatialGizmo>();
- ClassDB::register_class<EditorResourcePreview>();
+ ClassDB::register_virtual_class<EditorResourcePreview>();
ClassDB::register_class<EditorResourcePreviewGenerator>();
- ClassDB::register_class<EditorFileSystem>();
+ ClassDB::register_virtual_class<EditorFileSystem>();
ClassDB::register_class<EditorFileSystemDirectory>();
ClassDB::register_virtual_class<ScriptEditor>();
ClassDB::register_virtual_class<EditorInterface>();
@@ -3254,7 +3324,7 @@ void EditorNode::register_editor_types() {
ClassDB::register_class<EditorResourceConversionPlugin>();
// FIXME: Is this stuff obsolete, or should it be ported to new APIs?
- //ClassDB::register_class<EditorScenePostImport>();
+ ClassDB::register_class<EditorScenePostImport>();
//ClassDB::register_type<EditorImportExport>();
}
@@ -3562,7 +3632,7 @@ void EditorNode::_save_docks() {
_save_docks_to_config(config, "docks");
editor_data.get_plugin_window_layout(config);
- config->save(EditorSettings::get_singleton()->get_project_settings_path().plus_file("editor_layout.cfg"));
+ config->save(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("editor_layout.cfg"));
}
void EditorNode::_save_docks_to_config(Ref<ConfigFile> p_layout, const String &p_section) {
@@ -3624,7 +3694,7 @@ void EditorNode::_load_docks() {
Ref<ConfigFile> config;
config.instance();
- Error err = config->load(EditorSettings::get_singleton()->get_project_settings_path().plus_file("editor_layout.cfg"));
+ Error err = config->load(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("editor_layout.cfg"));
if (err != OK) {
//no config
if (overridden_default_layout >= 0) {
@@ -3793,7 +3863,7 @@ void EditorNode::_update_layouts_menu() {
Ref<ConfigFile> config;
config.instance();
- Error err = config->load(EditorSettings::get_singleton()->get_settings_path().plus_file("editor_layouts-3.cfg"));
+ Error err = config->load(EditorSettings::get_singleton()->get_editor_layouts_config());
if (err != OK) {
return; //no config
}
@@ -3841,7 +3911,7 @@ void EditorNode::_layout_menu_option(int p_id) {
Ref<ConfigFile> config;
config.instance();
- Error err = config->load(EditorSettings::get_singleton()->get_settings_path().plus_file("editor_layouts-3.cfg"));
+ Error err = config->load(EditorSettings::get_singleton()->get_editor_layouts_config());
if (err != OK) {
return; //no config
}
@@ -3878,6 +3948,7 @@ void EditorNode::_scene_tab_closed(int p_tab) {
} else {
_discard_changes();
}
+ _update_scene_tabs();
}
void EditorNode::_scene_tab_hover(int p_tab) {
@@ -4205,72 +4276,71 @@ Variant EditorNode::drag_resource(const Ref<Resource> &p_res, Control *p_from) {
return drag_data;
}
-Variant EditorNode::drag_files(const Vector<String> &p_files, Control *p_from) {
-
- VBoxContainer *files = memnew(VBoxContainer);
-
- int max_files = 6;
-
- for (int i = 0; i < MIN(max_files, p_files.size()); i++) {
-
- Label *label = memnew(Label);
- label->set_text(p_files[i].get_file());
- files->add_child(label);
+Variant EditorNode::drag_files_and_dirs(const Vector<String> &p_paths, Control *p_from) {
+ bool has_folder = false;
+ bool has_file = false;
+ for (int i = 0; i < p_paths.size(); i++) {
+ bool is_folder = p_paths[i].ends_with("/");
+ has_folder |= is_folder;
+ has_file |= !is_folder;
}
- if (p_files.size() > max_files) {
-
+ int max_rows = 6;
+ int num_rows = p_paths.size() > max_rows ? max_rows - 1 : p_paths.size(); //Don't waste a row to say "1 more file" - list it instead.
+ VBoxContainer *vbox = memnew(VBoxContainer);
+ for (int i = 0; i < num_rows; i++) {
+ HBoxContainer *hbox = memnew(HBoxContainer);
+ TextureRect *icon = memnew(TextureRect);
Label *label = memnew(Label);
- label->set_text(vformat(TTR("%d more file(s)"), p_files.size() - max_files));
- files->add_child(label);
- }
- Dictionary drag_data;
- drag_data["type"] = "files";
- drag_data["files"] = p_files;
- drag_data["from"] = p_from;
-
- p_from->set_drag_preview(files); //wait until it enters scene
-
- return drag_data;
-}
-
-Variant EditorNode::drag_files_and_dirs(const Vector<String> &p_files, Control *p_from) {
-
- VBoxContainer *files = memnew(VBoxContainer);
-
- int max_files = 6;
- for (int i = 0; i < MIN(max_files, p_files.size()); i++) {
-
- Label *label = memnew(Label);
- label->set_text(p_files[i].get_file());
- files->add_child(label);
+ if (p_paths[i].ends_with("/")) {
+ label->set_text(p_paths[i].substr(0, p_paths[i].length() - 1).get_file());
+ icon->set_texture(gui_base->get_icon("Folder", "EditorIcons"));
+ } else {
+ label->set_text(p_paths[i].get_file());
+ icon->set_texture(gui_base->get_icon("File", "EditorIcons"));
+ }
+ icon->set_size(Size2(16, 16));
+ hbox->add_child(icon);
+ hbox->add_child(label);
+ vbox->add_child(hbox);
}
- if (p_files.size() > max_files) {
-
+ if (p_paths.size() > num_rows) {
Label *label = memnew(Label);
- label->set_text(vformat(TTR("%d more file(s) or folder(s)"), p_files.size() - max_files));
- files->add_child(label);
+ if (has_file && has_folder) {
+ label->set_text(vformat(TTR("%d more files or folders"), p_paths.size() - num_rows));
+ } else if (has_folder) {
+ label->set_text(vformat(TTR("%d more folders"), p_paths.size() - num_rows));
+ } else {
+ label->set_text(vformat(TTR("%d more files"), p_paths.size() - num_rows));
+ }
+ vbox->add_child(label);
}
+ p_from->set_drag_preview(vbox); //wait until it enters scene
+
Dictionary drag_data;
- drag_data["type"] = "files_and_dirs";
- drag_data["files"] = p_files;
+ drag_data["type"] = has_folder ? "files_and_dirs" : "files";
+ drag_data["files"] = p_paths;
drag_data["from"] = p_from;
-
- p_from->set_drag_preview(files); //wait until it enters scene
-
return drag_data;
}
void EditorNode::_dropped_files(const Vector<String> &p_files, int p_screen) {
- /*
- String cur_path = filesystem_dock->get_current_path();
- for(int i=0;i<EditorImportExport::get_singleton()->get_import_plugin_count();i++) {
- EditorImportExport::get_singleton()->get_import_plugin(i)->import_from_drop(p_files,cur_path);
+ String to_path = ProjectSettings::get_singleton()->globalize_path(get_filesystem_dock()->get_current_path());
+ DirAccessRef dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+
+ for (int i = 0; i < p_files.size(); i++) {
+
+ String from = p_files[i];
+ if (!ResourceFormatImporter::get_singleton()->can_be_imported(from)) {
+ continue;
+ }
+ String to = to_path.plus_file(from.get_file());
+ dir->copy(from, to);
}
- */
+ EditorFileSystem::get_singleton()->scan_changes();
}
void EditorNode::_file_access_close_error_notify(const String &p_str) {
@@ -4282,15 +4352,11 @@ void EditorNode::reload_scene(const String &p_path) {
//first of all, reload internal textures, materials, meshes, etc. as they might have changed on disk
- print_line("reloading: " + p_path);
List<Ref<Resource> > cached;
ResourceCache::get_cached_resources(&cached);
List<Ref<Resource> > to_clear; //clear internal resources from previous scene from being used
for (List<Ref<Resource> >::Element *E = cached.front(); E; E = E->next()) {
- if (E->get()->get_path().find("::") != -1) {
- print_line(E->get()->get_path());
- }
if (E->get()->get_path().begins_with(p_path + "::")) { //subresources of existing scene
to_clear.push_back(E->get());
}
@@ -4298,7 +4364,6 @@ void EditorNode::reload_scene(const String &p_path) {
//so reload reloads everything, clear subresources of previous scene
while (to_clear.front()) {
- print_line("bye bye: " + to_clear.front()->get()->get_path());
to_clear.front()->get()->set_path("");
to_clear.pop_front();
}
@@ -4510,6 +4575,7 @@ void EditorNode::_bind_methods() {
ClassDB::bind_method("_set_main_scene_state", &EditorNode::_set_main_scene_state);
ClassDB::bind_method("_update_scene_tabs", &EditorNode::_update_scene_tabs);
ClassDB::bind_method("_discard_changes", &EditorNode::_discard_changes);
+ ClassDB::bind_method("_update_recent_scenes", &EditorNode::_update_recent_scenes);
ClassDB::bind_method("_prepare_history", &EditorNode::_prepare_history);
ClassDB::bind_method("_select_history", &EditorNode::_select_history);
@@ -4545,6 +4611,11 @@ static Node *_resource_get_edited_scene() {
return EditorNode::get_singleton()->get_edited_scene();
}
+void EditorNode::_print_handler(void *p_this, const String &p_string, bool p_error) {
+ EditorNode *en = (EditorNode *)p_this;
+ en->log->add_message(p_string, p_error);
+}
+
EditorNode::EditorNode() {
Resource::_get_local_scene_func = _resource_get_edited_scene;
@@ -4588,7 +4659,8 @@ EditorNode::EditorNode() {
{
int dpi_mode = EditorSettings::get_singleton()->get("interface/editor/hidpi_mode");
if (dpi_mode == 0) {
- editor_set_scale(OS::get_singleton()->get_screen_dpi(0) >= 192 && OS::get_singleton()->get_screen_size(OS::get_singleton()->get_current_screen()).x > 2000 ? 2.0 : 1.0);
+ const int screen = OS::get_singleton()->get_current_screen();
+ editor_set_scale(OS::get_singleton()->get_screen_dpi(screen) >= 192 && OS::get_singleton()->get_screen_size(screen).x > 2000 ? 2.0 : 1.0);
} else if (dpi_mode == 1) {
editor_set_scale(0.75);
} else if (dpi_mode == 2) {
@@ -4681,9 +4753,9 @@ EditorNode::EditorNode() {
theme_base->add_child(gui_base);
gui_base->set_anchors_and_margins_preset(Control::PRESET_WIDE);
- Ref<Theme> theme = create_editor_theme();
+ Ref<Theme> theme = create_custom_theme();
theme_base->set_theme(theme);
- gui_base->set_theme(create_custom_theme());
+ gui_base->set_theme(theme);
gui_base->add_style_override("panel", gui_base->get_stylebox("Background", "EditorStyles"));
resource_preview = memnew(EditorResourcePreview);
@@ -4780,7 +4852,12 @@ EditorNode::EditorNode() {
dock_tab_move_left->set_focus_mode(Control::FOCUS_NONE);
dock_tab_move_left->connect("pressed", this, "_dock_move_left");
dock_hb->add_child(dock_tab_move_left);
- dock_hb->add_spacer();
+
+ Label *dock_label = memnew(Label);
+ dock_label->set_text(TTR("Dock Position"));
+ dock_label->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ dock_hb->add_child(dock_label);
+
dock_tab_move_right = memnew(ToolButton);
dock_tab_move_right->set_icon(theme->get_icon("Forward", "EditorIcons"));
dock_tab_move_right->set_focus_mode(Control::FOCUS_NONE);
@@ -4850,20 +4927,28 @@ EditorNode::EditorNode() {
scene_tabs->connect("mouse_exited", this, "_scene_tab_exit");
scene_tabs->connect("gui_input", this, "_scene_tab_input");
scene_tabs->connect("reposition_active_tab_request", this, "_reposition_active_tab");
+ scene_tabs->connect("resized", this, "_update_scene_tabs");
- HBoxContainer *tabbar_container = memnew(HBoxContainer);
+ tabbar_container = memnew(HBoxContainer);
scene_tabs->set_h_size_flags(Control::SIZE_EXPAND_FILL);
srt->add_child(tabbar_container);
tabbar_container->add_child(scene_tabs);
distraction_free = memnew(ToolButton);
- tabbar_container->add_child(distraction_free);
distraction_free->set_shortcut(ED_SHORTCUT("editor/distraction_free_mode", TTR("Distraction Free Mode"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_F11));
distraction_free->set_tooltip(TTR("Toggle distraction-free mode."));
distraction_free->connect("pressed", this, "_toggle_distraction_free_mode");
distraction_free->set_icon(gui_base->get_icon("DistractionFree", "EditorIcons"));
distraction_free->set_toggle_mode(true);
+ scene_tab_add = memnew(ToolButton);
+ tabbar_container->add_child(scene_tab_add);
+ tabbar_container->add_child(distraction_free);
+ scene_tab_add->set_tooltip(TTR("Add a new scene."));
+ scene_tab_add->set_icon(gui_base->get_icon("Add", "EditorIcons"));
+ scene_tab_add->add_color_override("icon_color_normal", Color(0.6f, 0.6f, 0.6f, 0.8f));
+ scene_tab_add->connect("pressed", this, "_menu_option", make_binds(FILE_NEW_SCENE));
+
scene_root_parent = memnew(PanelContainer);
scene_root_parent->set_custom_minimum_size(Size2(0, 80) * EDSCALE);
scene_root_parent->add_style_override("panel", gui_base->get_stylebox("Content", "EditorStyles"));
@@ -5378,12 +5463,12 @@ EditorNode::EditorNode() {
save_confirmation->connect("confirmed", this, "_menu_confirm_current");
save_confirmation->connect("custom_action", this, "_discard_changes");
- file_templates = memnew(FileDialog);
+ file_templates = memnew(EditorFileDialog);
file_templates->set_title(TTR("Import Templates From ZIP File"));
gui_base->add_child(file_templates);
- file_templates->set_mode(FileDialog::MODE_OPEN_FILE);
- file_templates->set_access(FileDialog::ACCESS_FILESYSTEM);
+ file_templates->set_mode(EditorFileDialog::MODE_OPEN_FILE);
+ file_templates->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
file_templates->clear_filters();
file_templates->add_filter("*.tpz ; Template Package");
@@ -5391,15 +5476,15 @@ EditorNode::EditorNode() {
gui_base->add_child(file);
file->set_current_dir("res://");
- file_export = memnew(FileDialog);
- file_export->set_access(FileDialog::ACCESS_FILESYSTEM);
+ 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(FileDialog);
+ file_export_lib = memnew(EditorFileDialog);
file_export_lib->set_title(TTR("Export Library"));
- file_export_lib->set_mode(FileDialog::MODE_SAVE_FILE);
+ file_export_lib->set_mode(EditorFileDialog::MODE_SAVE_FILE);
file_export_lib->connect("file_selected", this, "_dialog_action");
file_export_lib_merge = memnew(CheckButton);
file_export_lib_merge->set_text(TTR("Merge With Existing"));
@@ -5412,10 +5497,10 @@ EditorNode::EditorNode() {
file_export_password->set_editable(false);
file_export->get_vbox()->add_margin_child(TTR("Password:"), file_export_password);
- file_script = memnew(FileDialog);
+ file_script = memnew(EditorFileDialog);
file_script->set_title(TTR("Open & Run a Script"));
- file_script->set_access(FileDialog::ACCESS_FILESYSTEM);
- file_script->set_mode(FileDialog::MODE_OPEN_FILE);
+ file_script->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
+ file_script->set_mode(EditorFileDialog::MODE_OPEN_FILE);
List<String> sexts;
ResourceLoader::get_recognized_extensions_for_type("Script", &sexts);
for (List<String>::Element *E = sexts.front(); E; E = E->next()) {
@@ -5524,6 +5609,14 @@ EditorNode::EditorNode() {
Ref<SpatialMaterialConversionPlugin> spatial_mat_convert;
spatial_mat_convert.instance();
resource_conversion_plugins.push_back(spatial_mat_convert);
+
+ Ref<CanvasItemMaterialConversionPlugin> canvas_item_mat_convert;
+ canvas_item_mat_convert.instance();
+ resource_conversion_plugins.push_back(canvas_item_mat_convert);
+
+ Ref<ParticlesMaterialConversionPlugin> particles_mat_convert;
+ particles_mat_convert.instance();
+ resource_conversion_plugins.push_back(particles_mat_convert);
}
circle_step_msec = OS::get_singleton()->get_ticks_msec();
circle_step_frame = Engine::get_singleton()->get_frames_drawn();
@@ -5636,6 +5729,10 @@ EditorNode::EditorNode() {
_dim_timer->connect("timeout", this, "_dim_timeout");
add_child(_dim_timer);
+ print_handler.printfunc = _print_handler;
+ print_handler.userdata = this;
+ add_print_handler(&print_handler);
+
ED_SHORTCUT("editor/editor_2d", TTR("Open 2D Editor"), KEY_F1);
ED_SHORTCUT("editor/editor_3d", TTR("Open 3D Editor"), KEY_F2);
ED_SHORTCUT("editor/editor_script", TTR("Open Script Editor"), KEY_F3); //hack neded for script editor F3 search to work :) Assign like this or don't use F3
@@ -5647,6 +5744,7 @@ EditorNode::EditorNode() {
EditorNode::~EditorNode() {
+ remove_print_handler(&print_handler);
memdelete(EditorHelp::get_doc_data());
memdelete(editor_selection);
memdelete(editor_plugins_over);
@@ -5674,12 +5772,12 @@ void EditorPluginList::edit(Object *p_object) {
}
}
-bool EditorPluginList::forward_gui_input(const Transform2D &p_canvas_xform, const Ref<InputEvent> &p_event) {
+bool EditorPluginList::forward_gui_input(const Ref<InputEvent> &p_event) {
bool discard = false;
for (int i = 0; i < plugins_list.size(); i++) {
- if (plugins_list[i]->forward_canvas_gui_input(p_canvas_xform, p_event)) {
+ if (plugins_list[i]->forward_canvas_gui_input(p_event)) {
discard = true;
}
}
@@ -5703,10 +5801,10 @@ bool EditorPluginList::forward_spatial_gui_input(Camera *p_camera, const Ref<Inp
return discard;
}
-void EditorPluginList::forward_draw_over_canvas(const Transform2D &p_canvas_xform, Control *p_canvas) {
+void EditorPluginList::forward_draw_over_canvas(Control *p_canvas) {
for (int i = 0; i < plugins_list.size(); i++) {
- plugins_list[i]->forward_draw_over_canvas(p_canvas_xform, p_canvas);
+ plugins_list[i]->forward_draw_over_canvas(p_canvas);
}
}
diff --git a/editor/editor_node.h b/editor/editor_node.h
index 0d1c6787cd..a2b4a0a049 100644
--- a/editor/editor_node.h
+++ b/editor/editor_node.h
@@ -30,6 +30,7 @@
#ifndef EDITOR_NODE_H
#define EDITOR_NODE_H
+#include "core/print_string.h"
#include "editor/connections_dialog.h"
#include "editor/create_dialog.h"
#include "editor/editor_about.h"
@@ -294,10 +295,10 @@ private:
ProjectSettingsEditor *project_settings;
EditorFileDialog *file;
ExportTemplateManager *export_template_manager;
- FileDialog *file_templates;
- FileDialog *file_export;
- FileDialog *file_export_lib;
- FileDialog *file_script;
+ EditorFileDialog *file_templates;
+ EditorFileDialog *file_export;
+ EditorFileDialog *file_export_lib;
+ EditorFileDialog *file_script;
CheckButton *file_export_lib_merge;
LineEdit *file_export_password;
String current_path;
@@ -343,7 +344,10 @@ private:
int dock_popup_selected;
Timer *dock_drag_timer;
bool docks_visible;
+
+ HBoxContainer *tabbar_container;
ToolButton *distraction_free;
+ ToolButton *scene_tab_add;
bool scene_distraction;
bool script_distraction;
@@ -503,7 +507,7 @@ private:
void _mark_unsaved_scenes();
void _find_node_types(Node *p_node, int &count_2d, int &count_3d);
- void _save_scene_with_preview(String p_file);
+ void _save_scene_with_preview(String p_file, int p_idx = -1);
Map<String, Set<String> > dependency_errors;
@@ -610,6 +614,9 @@ private:
Vector<Ref<EditorResourceConversionPlugin> > resource_conversion_plugins;
+ PrintHandlerList print_handler;
+ static void _print_handler(void *p_this, const String &p_string, bool p_error);
+
protected:
void _notification(int p_what);
static void _bind_methods();
@@ -765,8 +772,7 @@ public:
void remove_bottom_panel_item(Control *p_item);
Variant drag_resource(const Ref<Resource> &p_res, Control *p_from);
- Variant drag_files(const Vector<String> &p_files, Control *p_from);
- Variant drag_files_and_dirs(const Vector<String> &p_files, Control *p_from);
+ Variant drag_files_and_dirs(const Vector<String> &p_paths, Control *p_from);
void add_tool_menu_item(const String &p_name, Object *p_handler, const String &p_callback, const Variant &p_ud = Variant());
void add_tool_submenu_item(const String &p_name, PopupMenu *p_submenu);
@@ -812,9 +818,9 @@ public:
void make_visible(bool p_visible);
void edit(Object *p_object);
- bool forward_gui_input(const Transform2D &p_canvas_xform, const Ref<InputEvent> &p_event);
+ bool forward_gui_input(const Ref<InputEvent> &p_event);
bool forward_spatial_gui_input(Camera *p_camera, const Ref<InputEvent> &p_event, bool serve_when_force_input_enabled);
- void forward_draw_over_canvas(const Transform2D &p_canvas_xform, Control *p_canvas);
+ void forward_draw_over_canvas(Control *p_canvas);
void add_plugin(EditorPlugin *p_plugin);
void clear();
bool empty();
diff --git a/editor/editor_path.cpp b/editor/editor_path.cpp
index 0587939a1a..f0d3c29c11 100644
--- a/editor/editor_path.cpp
+++ b/editor/editor_path.cpp
@@ -149,14 +149,14 @@ void EditorPath::_notification(int p_what) {
if (name == "")
name = r->get_class();
- } else if (Object::cast_to<Node>(obj)) {
-
+ } else if (obj->is_class("ScriptEditorDebuggerInspectedObject"))
+ name = obj->call("get_title");
+ else if (Object::cast_to<Node>(obj))
name = Object::cast_to<Node>(obj)->get_name();
- } else if (Object::cast_to<Resource>(obj) && Object::cast_to<Resource>(obj)->get_name() != "") {
+ else if (Object::cast_to<Resource>(obj) && Object::cast_to<Resource>(obj)->get_name() != "")
name = Object::cast_to<Resource>(obj)->get_name();
- } else {
+ else
name = obj->get_class();
- }
set_tooltip(obj->get_class());
diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp
index b4460c5619..38e8b301b7 100644
--- a/editor/editor_plugin.cpp
+++ b/editor/editor_plugin.cpp
@@ -76,11 +76,11 @@ Vector<Ref<Texture> > EditorInterface::make_mesh_previews(const Vector<Ref<Mesh>
//VS::get_singleton()->camera_set_perspective(camera,45,0.1,10);
VS::get_singleton()->camera_set_orthogonal(camera, 1.0, 0.01, 1000.0);
- RID light = VS::get_singleton()->light_create(VS::LIGHT_DIRECTIONAL);
+ RID light = VS::get_singleton()->directional_light_create();
RID light_instance = VS::get_singleton()->instance_create2(light, scenario);
VS::get_singleton()->instance_set_transform(light_instance, Transform().looking_at(Vector3(-1, -1, -1), Vector3(0, 1, 0)));
- RID light2 = VS::get_singleton()->light_create(VS::LIGHT_DIRECTIONAL);
+ RID light2 = VS::get_singleton()->directional_light_create();
VS::get_singleton()->light_set_color(light2, Color(0.7, 0.7, 0.7));
//VS::get_singleton()->light_set_color(light2, VS::LIGHT_COLOR_SPECULAR, Color(0.0, 0.0, 0.0));
RID light_instance2 = VS::get_singleton()->instance_create2(light2, scenario);
@@ -102,14 +102,14 @@ Vector<Ref<Texture> > EditorInterface::make_mesh_previews(const Vector<Ref<Mesh>
textures.push_back(Ref<Texture>());
continue;
}
- Rect3 aabb = mesh->get_aabb();
+ AABB aabb = mesh->get_aabb();
print_line("aabb: " + aabb);
Vector3 ofs = aabb.position + aabb.size * 0.5;
aabb.position -= ofs;
Transform xform;
xform.basis = Basis().rotated(Vector3(0, 1, 0), -Math_PI * 0.25);
xform.basis = Basis().rotated(Vector3(1, 0, 0), Math_PI * 0.25) * xform.basis;
- Rect3 rot_aabb = xform.xform(aabb);
+ AABB rot_aabb = xform.xform(aabb);
print_line("rot_aabb: " + rot_aabb);
float m = MAX(rot_aabb.size.x, rot_aabb.size.y) * 0.5;
if (m == 0) {
@@ -258,7 +258,7 @@ void EditorInterface::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_resource_previewer"), &EditorInterface::get_resource_previewer);
ClassDB::bind_method(D_METHOD("get_resource_filesystem"), &EditorInterface::get_resource_file_system);
ClassDB::bind_method(D_METHOD("get_editor_viewport"), &EditorInterface::get_editor_viewport);
- ClassDB::bind_method(D_METHOD("make_mesh_previews"), &EditorInterface::_make_mesh_previews);
+ ClassDB::bind_method(D_METHOD("make_mesh_previews", "meshes", "preview_size"), &EditorInterface::_make_mesh_previews);
ClassDB::bind_method(D_METHOD("save_scene"), &EditorInterface::save_scene);
ClassDB::bind_method(D_METHOD("save_scene_as", "path", "with_preview"), &EditorInterface::save_scene_as, DEFVAL(true));
@@ -402,18 +402,18 @@ Ref<SpatialEditorGizmo> EditorPlugin::create_spatial_gizmo(Spatial *p_spatial) {
return Ref<SpatialEditorGizmo>();
}
-bool EditorPlugin::forward_canvas_gui_input(const Transform2D &p_canvas_xform, const Ref<InputEvent> &p_event) {
+bool EditorPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p_event) {
if (get_script_instance() && get_script_instance()->has_method("forward_canvas_gui_input")) {
- return get_script_instance()->call("forward_canvas_gui_input", p_canvas_xform, p_event);
+ return get_script_instance()->call("forward_canvas_gui_input", p_event);
}
return false;
}
-void EditorPlugin::forward_draw_over_canvas(const Transform2D &p_canvas_xform, Control *p_canvas) {
+void EditorPlugin::forward_draw_over_canvas(Control *p_canvas) {
if (get_script_instance() && get_script_instance()->has_method("forward_draw_over_canvas")) {
- get_script_instance()->call("forward_draw_over_canvas", p_canvas_xform, p_canvas);
+ get_script_instance()->call("forward_draw_over_canvas", p_canvas);
}
}
@@ -455,7 +455,11 @@ void EditorPlugin::make_visible(bool p_visible) {
void EditorPlugin::edit(Object *p_object) {
if (get_script_instance() && get_script_instance()->has_method("edit")) {
- get_script_instance()->call("edit", p_object);
+ if (p_object->is_class("Resource")) {
+ get_script_instance()->call("edit", Ref<Resource>(Object::cast_to<Resource>(p_object)));
+ } else {
+ get_script_instance()->call("edit", p_object);
+ }
}
}
@@ -632,6 +636,7 @@ void EditorPlugin::_bind_methods() {
BIND_ENUM_CONSTANT(CONTAINER_SPATIAL_EDITOR_BOTTOM);
BIND_ENUM_CONSTANT(CONTAINER_CANVAS_EDITOR_MENU);
BIND_ENUM_CONSTANT(CONTAINER_CANVAS_EDITOR_SIDE);
+ BIND_ENUM_CONSTANT(CONTAINER_CANVAS_EDITOR_BOTTOM);
BIND_ENUM_CONSTANT(CONTAINER_PROPERTY_EDITOR_BOTTOM);
BIND_ENUM_CONSTANT(DOCK_SLOT_LEFT_UL);
diff --git a/editor/editor_plugin.h b/editor/editor_plugin.h
index 18530e9ce4..1d68eee117 100644
--- a/editor/editor_plugin.h
+++ b/editor/editor_plugin.h
@@ -156,8 +156,8 @@ public:
void notify_scene_closed(const String &scene_filepath);
virtual Ref<SpatialEditorGizmo> create_spatial_gizmo(Spatial *p_spatial);
- virtual bool forward_canvas_gui_input(const Transform2D &p_canvas_xform, const Ref<InputEvent> &p_event);
- virtual void forward_draw_over_canvas(const Transform2D &p_canvas_xform, Control *p_canvas);
+ virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event);
+ virtual void forward_draw_over_canvas(Control *p_canvas);
virtual bool forward_spatial_gui_input(Camera *p_camera, const Ref<InputEvent> &p_event);
virtual String get_name() const;
virtual bool has_main_screen() const;
diff --git a/editor/editor_profiler.cpp b/editor/editor_profiler.cpp
index 968d8b831e..faf49ffd41 100644
--- a/editor/editor_profiler.cpp
+++ b/editor/editor_profiler.cpp
@@ -634,7 +634,7 @@ EditorProfiler::EditorProfiler() {
display_mode->add_item(TTR("Frame Time (sec)"));
display_mode->add_item(TTR("Average Time (sec)"));
display_mode->add_item(TTR("Frame %"));
- display_mode->add_item(TTR("Fixed Frame %"));
+ display_mode->add_item(TTR("Physics Frame %"));
display_mode->connect("item_selected", this, "_combo_changed");
hb->add_child(display_mode);
diff --git a/editor/editor_resource_preview.cpp b/editor/editor_resource_preview.cpp
index 437ad5ac3f..467451cd2b 100644
--- a/editor/editor_resource_preview.cpp
+++ b/editor/editor_resource_preview.cpp
@@ -86,7 +86,6 @@ void EditorResourcePreview::_thread_func(void *ud) {
void EditorResourcePreview::_preview_ready(const String &p_str, const Ref<Texture> &p_texture, ObjectID id, const StringName &p_func, const Variant &p_ud) {
- //print_line("preview is ready");
preview_mutex->lock();
String path = p_str;
@@ -121,7 +120,6 @@ Ref<Texture> EditorResourcePreview::_generate_preview(const QueueItem &p_item, c
type = p_item.resource->get_class();
else
type = ResourceLoader::get_resource_type(p_item.path);
- //print_line("resource type is: "+type);
if (type == "")
return Ref<Texture>(); //could not guess type
@@ -144,7 +142,6 @@ Ref<Texture> EditorResourcePreview::_generate_preview(const QueueItem &p_item, c
if (!p_item.resource.is_valid()) {
// cache the preview in case it's a resource on disk
if (generated.is_valid()) {
- //print_line("was generated");
int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size");
thumbnail_size *= EDSCALE;
//wow it generated a preview... save cache
@@ -164,15 +161,11 @@ Ref<Texture> EditorResourcePreview::_generate_preview(const QueueItem &p_item, c
void EditorResourcePreview::_thread() {
- //print_line("begin thread");
while (!exit) {
- //print_line("wait for semaphore");
preview_sem->wait();
preview_mutex->lock();
- //print_line("blue team go");
-
if (queue.size()) {
QueueItem item = queue.front()->get();
@@ -185,45 +178,36 @@ void EditorResourcePreview::_thread() {
path += ":" + itos(cache[item.path].last_hash); //keep last hash (see description of what this is in condition below)
}
- print_line("cached: " + item.path);
_preview_ready(path, cache[item.path].preview, item.id, item.function, item.userdata);
preview_mutex->unlock();
} else {
+
preview_mutex->unlock();
Ref<ImageTexture> texture;
- //print_line("pop from queue "+item.path);
-
int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size");
thumbnail_size *= EDSCALE;
if (item.resource.is_valid()) {
- print_line("generated: " + item.path);
-
texture = _generate_preview(item, String());
//adding hash to the end of path (should be ID:<objid>:<hash>) because of 5 argument limit to call_deferred
_preview_ready(item.path + ":" + itos(item.resource->hash_edited_version()), texture, item.id, item.function, item.userdata);
} else {
- print_line("from file: " + item.path);
-
- String temp_path = EditorSettings::get_singleton()->get_settings_path().plus_file("tmp");
+ String temp_path = EditorSettings::get_singleton()->get_cache_dir();
String cache_base = ProjectSettings::get_singleton()->globalize_path(item.path).md5_text();
cache_base = temp_path.plus_file("resthumb-" + cache_base);
//does not have it, try to load a cached thumbnail
String file = cache_base + ".txt";
- //print_line("cachetxt at "+file);
FileAccess *f = FileAccess::open(file, FileAccess::READ);
if (!f) {
- //print_line("generate because not cached");
-
//generate
texture = _generate_preview(item, cache_base);
} else {
@@ -283,7 +267,6 @@ void EditorResourcePreview::_thread() {
}
}
- //print_line("notify of preview ready");
_preview_ready(item.path, texture, item.id, item.function, item.userdata);
}
}
@@ -313,7 +296,6 @@ void EditorResourcePreview::queue_edited_resource_preview(const Ref<Resource> &p
cache.erase(path_id); //erase if exists, since it will be regen
- //print_line("send to thread "+p_path);
QueueItem item;
item.function = p_receiver_func;
item.id = p_receiver->get_instance_id();
@@ -337,7 +319,6 @@ void EditorResourcePreview::queue_resource_preview(const String &p_path, Object
return;
}
- //print_line("send to thread "+p_path);
QueueItem item;
item.function = p_receiver_func;
item.id = p_receiver->get_instance_id();
diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp
index b532bb793a..582bb977b8 100644
--- a/editor/editor_settings.cpp
+++ b/editor/editor_settings.cpp
@@ -47,12 +47,11 @@
#include "scene/main/scene_tree.h"
#include "scene/main/viewport.h"
+// PRIVATE METHODS
+
Ref<EditorSettings> EditorSettings::singleton = NULL;
-EditorSettings *EditorSettings::get_singleton() {
-
- return singleton.ptr();
-}
+// Properties
bool EditorSettings::_set(const StringName &p_name, const Variant &p_value, bool p_emit_signal) {
@@ -136,6 +135,7 @@ bool EditorSettings::_get(const StringName &p_name, Variant &r_ret) const {
void EditorSettings::_initial_set(const StringName &p_name, const Variant &p_value) {
set(p_name, p_value);
props[p_name].initial = p_value;
+ props[p_name].has_default_value = true;
}
struct _EVCSort {
@@ -195,346 +195,33 @@ void EditorSettings::_get_property_list(List<PropertyInfo> *p_list) const {
p_list->push_back(PropertyInfo(Variant::ARRAY, "shortcuts", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); //do not edit
}
-void EditorSettings::set_setting(const String &p_setting, const Variant &p_value) {
- _THREAD_SAFE_METHOD_
- set(p_setting, p_value);
-}
+void EditorSettings::_add_property_info_bind(const Dictionary &p_info) {
-Variant EditorSettings::get_setting(const String &p_setting) const {
- _THREAD_SAFE_METHOD_
- return get(p_setting);
-}
+ ERR_FAIL_COND(!p_info.has("name"));
+ ERR_FAIL_COND(!p_info.has("type"));
-bool EditorSettings::has_setting(String p_var) const {
+ PropertyInfo pinfo;
+ pinfo.name = p_info["name"];
+ ERR_FAIL_COND(!props.has(pinfo.name));
+ pinfo.type = Variant::Type(p_info["type"].operator int());
+ ERR_FAIL_INDEX(pinfo.type, Variant::VARIANT_MAX);
- _THREAD_SAFE_METHOD_
+ if (p_info.has("hint"))
+ pinfo.hint = PropertyHint(p_info["hint"].operator int());
+ if (p_info.has("hint_string"))
+ pinfo.hint_string = p_info["hint_string"];
- return props.has(p_var);
+ add_property_hint(pinfo);
}
-void EditorSettings::erase(String p_var) {
+// Default configs
+bool EditorSettings::has_default_value(const String &p_setting) const {
_THREAD_SAFE_METHOD_
- props.erase(p_var);
-}
-
-void EditorSettings::raise_order(const String &p_name) {
- _THREAD_SAFE_METHOD_
-
- ERR_FAIL_COND(!props.has(p_name));
- props[p_name].order = ++last_order;
-}
-
-Variant _EDITOR_DEF(const String &p_var, const Variant &p_default) {
-
- if (EditorSettings::get_singleton()->has_setting(p_var))
- return EditorSettings::get_singleton()->get(p_var);
- EditorSettings::get_singleton()->set(p_var, p_default);
- EditorSettings::get_singleton()->set_initial_value(p_var, p_default);
-
- return p_default;
-}
-
-Variant _EDITOR_GET(const String &p_var) {
-
- ERR_FAIL_COND_V(!EditorSettings::get_singleton()->has_setting(p_var), Variant())
- return EditorSettings::get_singleton()->get(p_var);
-}
-
-static Dictionary _get_builtin_script_templates() {
- Dictionary templates;
-
- //No Comments
- templates["no_comments.gd"] =
- "extends %BASE%\n"
- "\n"
- "func _ready():\n"
- "%TS%pass\n";
-
- //Empty
- templates["empty.gd"] =
- "extends %BASE%"
- "\n"
- "\n";
-
- return templates;
-}
-
-static void _create_script_templates(const String &p_path) {
-
- Dictionary templates = _get_builtin_script_templates();
- List<Variant> keys;
- templates.get_key_list(&keys);
- FileAccess *file = FileAccess::create(FileAccess::ACCESS_FILESYSTEM);
-
- DirAccess *dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- dir->change_dir(p_path);
- for (int i = 0; i < keys.size(); i++) {
- if (!dir->file_exists(keys[i])) {
- Error err = file->reopen(p_path.plus_file((String)keys[i]), FileAccess::WRITE);
- ERR_FAIL_COND(err != OK);
- file->store_string(templates[keys[i]]);
- file->close();
- }
- }
-
- memdelete(dir);
- memdelete(file);
-}
-
-void EditorSettings::create() {
-
- if (singleton.ptr())
- return; //pointless
-
- DirAccess *dir = NULL;
- Variant meta;
-
- String config_path;
- String config_dir;
- Ref<ConfigFile> extra_config = memnew(ConfigFile);
-
- String exe_path = OS::get_singleton()->get_executable_path().get_base_dir();
- DirAccess *d = DirAccess::create_for_path(exe_path);
- bool self_contained = false;
-
- if (d->file_exists(exe_path + "/._sc_")) {
- self_contained = true;
- extra_config->load(exe_path + "/._sc_");
- } else if (d->file_exists(exe_path + "/_sc_")) {
- self_contained = true;
- extra_config->load(exe_path + "/_sc_");
- }
- memdelete(d);
-
- if (self_contained) {
- // editor is self contained
- config_path = exe_path;
- config_dir = "editor_data";
- } else {
-
- if (OS::get_singleton()->has_environment("APPDATA")) {
- // Most likely under windows, save here
- config_path = OS::get_singleton()->get_environment("APPDATA");
- config_dir = String(_MKSTR(VERSION_SHORT_NAME)).capitalize();
- } else if (OS::get_singleton()->has_environment("HOME")) {
-
- config_path = OS::get_singleton()->get_environment("HOME");
- config_dir = "." + String(_MKSTR(VERSION_SHORT_NAME)).to_lower();
- }
- };
-
- ClassDB::register_class<EditorSettings>(); //otherwise it can't be unserialized
- String config_file_path;
-
- if (config_path != "") {
-
- dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- if (dir->change_dir(config_path) != OK) {
- ERR_PRINT("Cannot find path for config directory!");
- memdelete(dir);
- goto fail;
- }
-
- if (dir->change_dir(config_dir) != OK) {
- dir->make_dir(config_dir);
- if (dir->change_dir(config_dir) != OK) {
- ERR_PRINT("Cannot create config directory!");
- memdelete(dir);
- goto fail;
- }
- }
-
- if (dir->change_dir("templates") != OK) {
- dir->make_dir("templates");
- } else {
-
- dir->change_dir("..");
- }
-
- if (dir->change_dir("text_editor_themes") != OK) {
- dir->make_dir("text_editor_themes");
- } else {
- dir->change_dir("..");
- }
-
- if (dir->change_dir("script_templates") != OK) {
- dir->make_dir("script_templates");
- } else {
- dir->change_dir("..");
- }
- _create_script_templates(dir->get_current_dir() + "/script_templates");
-
- if (dir->change_dir("tmp") != OK) {
- dir->make_dir("tmp");
- } else {
-
- dir->change_dir("..");
- }
-
- if (dir->change_dir("config") != OK) {
- dir->make_dir("config");
- } else {
-
- dir->change_dir("..");
- }
-
- dir->change_dir("config");
-
- String pcp = ProjectSettings::get_singleton()->get_resource_path();
- if (pcp.ends_with("/"))
- pcp = config_path.substr(0, pcp.size() - 1);
- pcp = pcp.get_file() + "-" + pcp.md5_text();
-
- if (dir->change_dir(pcp)) {
- dir->make_dir(pcp);
- } else {
- dir->change_dir("..");
- }
-
- dir->change_dir("..");
-
- // path at least is validated, so validate config file
-
- String config_file_name = "editor_settings-" + String(_MKSTR(VERSION_MAJOR)) + ".tres";
- config_file_path = config_path + "/" + config_dir + "/" + config_file_name;
-
- String open_path = config_file_path;
-
- if (!dir->file_exists(config_file_name)) {
-
- goto fail;
- }
-
- memdelete(dir);
-
- singleton = ResourceLoader::load(open_path, "EditorSettings");
-
- if (singleton.is_null()) {
- WARN_PRINT("Could not open config file.");
- goto fail;
- }
-
- singleton->save_changed_setting = true;
- singleton->config_file_path = config_file_path;
- singleton->project_config_path = pcp;
- singleton->settings_path = config_path + "/" + config_dir;
-
- if (OS::get_singleton()->is_stdout_verbose()) {
-
- print_line("EditorSettings: Load OK!");
- }
-
- singleton->setup_language();
- singleton->setup_network();
- singleton->load_favorites();
- singleton->list_text_editor_themes();
-
- return;
- }
-
-fail:
-
- // patch init projects
- if (extra_config->has_section("init_projects")) {
- Vector<String> list = extra_config->get_value("init_projects", "list");
- for (int i = 0; i < list.size(); i++) {
-
- list[i] = exe_path + "/" + list[i];
- };
- extra_config->set_value("init_projects", "list", list);
- };
-
- singleton = Ref<EditorSettings>(memnew(EditorSettings));
- singleton->save_changed_setting = true;
- singleton->config_file_path = config_file_path;
- singleton->settings_path = config_path + "/" + config_dir;
- singleton->_load_defaults(extra_config);
- singleton->setup_language();
- singleton->setup_network();
- singleton->list_text_editor_themes();
-}
-
-String EditorSettings::get_settings_path() const {
-
- return settings_path;
-}
-
-void EditorSettings::setup_language() {
-
- String lang = get("interface/editor/editor_language");
- if (lang == "en")
- return; //none to do
-
- for (int i = 0; i < translations.size(); i++) {
- if (translations[i]->get_locale() == lang) {
- TranslationServer::get_singleton()->set_tool_translation(translations[i]);
- break;
- }
- }
-}
-
-void EditorSettings::setup_network() {
-
- List<IP_Address> local_ip;
- IP::get_singleton()->get_local_addresses(&local_ip);
- String lip = "127.0.0.1";
- String hint;
- String current = has_setting("network/debug/remote_host") ? get("network/debug/remote_host") : "";
- int port = has_setting("network/debug/remote_port") ? (int)get("network/debug/remote_port") : 6007;
-
- for (List<IP_Address>::Element *E = local_ip.front(); E; E = E->next()) {
-
- String ip = E->get();
-
- // link-local IPv6 addresses don't work, skipping them
- if (ip.begins_with("fe80:0:0:0:")) // fe80::/64
- continue;
- if (ip == current)
- lip = current; //so it saves
- if (hint != "")
- hint += ",";
- hint += ip;
- }
-
- set("network/debug/remote_host", lip);
- add_property_hint(PropertyInfo(Variant::STRING, "network/debug/remote_host", PROPERTY_HINT_ENUM, hint));
-
- set("network/debug/remote_port", port);
- add_property_hint(PropertyInfo(Variant::INT, "network/debug/remote_port", PROPERTY_HINT_RANGE, "1,65535,1"));
-}
-
-void EditorSettings::save() {
-
- //_THREAD_SAFE_METHOD_
-
- if (!singleton.ptr())
- return;
-
- if (singleton->config_file_path == "") {
- ERR_PRINT("Cannot save EditorSettings config, no valid path");
- return;
- }
-
- Error err = ResourceSaver::save(singleton->config_file_path, singleton);
-
- if (err != OK) {
- ERR_PRINT("Can't Save!");
- return;
- }
-
- if (OS::get_singleton()->is_stdout_verbose()) {
- print_line("EditorSettings Save OK!");
- }
-}
-
-void EditorSettings::destroy() {
-
- if (!singleton.ptr())
- return;
- save();
- singleton = Ref<EditorSettings>();
+ if (!props.has(p_setting))
+ return false;
+ return props[p_setting].has_default_value;
}
void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
@@ -544,6 +231,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
{
String lang_hint = "en";
String host_lang = OS::get_singleton()->get_locale();
+ host_lang = TranslationServer::standardize_locale(host_lang);
String best;
@@ -619,7 +307,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
_initial_set("filesystem/directories/default_project_path", OS::get_singleton()->has_environment("HOME") ? OS::get_singleton()->get_environment("HOME") : OS::get_singleton()->get_system_dir(OS::SYSTEM_DIR_DOCUMENTS));
hints["filesystem/directories/default_project_path"] = PropertyInfo(Variant::STRING, "filesystem/directories/default_project_path", PROPERTY_HINT_GLOBAL_DIR);
_initial_set("filesystem/directories/default_project_export_path", "");
- hints["global/default_project_export_path"] = PropertyInfo(Variant::STRING, "global/default_project_export_path", PROPERTY_HINT_GLOBAL_DIR);
+ hints["filesystem/directories/default_project_export_path"] = PropertyInfo(Variant::STRING, "filesystem/directories/default_project_export_path", PROPERTY_HINT_GLOBAL_DIR);
_initial_set("interface/editor/show_script_in_scene_tabs", false);
_initial_set("text_editor/theme/color_theme", "Adaptive");
@@ -632,6 +320,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
_initial_set("text_editor/highlighting/syntax_highlighting", true);
_initial_set("text_editor/highlighting/highlight_all_occurrences", true);
+ _initial_set("text_editor/highlighting/highlight_current_line", true);
_initial_set("text_editor/cursor/scroll_past_end_of_file", false);
_initial_set("text_editor/indent/type", 0);
@@ -645,6 +334,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
_initial_set("text_editor/line_numbers/show_line_numbers", true);
_initial_set("text_editor/line_numbers/line_numbers_zero_padded", false);
_initial_set("text_editor/line_numbers/show_breakpoint_gutter", true);
+ _initial_set("text_editor/line_numbers/code_folding", true);
_initial_set("text_editor/line_numbers/show_line_length_guideline", false);
_initial_set("text_editor/line_numbers/line_length_guideline_column", 80);
hints["text_editor/line_numbers/line_length_guideline_column"] = PropertyInfo(Variant::INT, "text_editor/line_numbers/line_length_guideline_column", PROPERTY_HINT_RANGE, "20, 160, 10");
@@ -705,7 +395,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
_initial_set("editors/3d/navigation_feel/orbit_sensitivity", 0.4);
hints["editors/3d/navigation_feel/orbit_sensitivity"] = PropertyInfo(Variant::REAL, "editors/3d/navigation_feel/orbit_sensitivity", PROPERTY_HINT_RANGE, "0.0, 2, 0.01");
- _initial_set("editors/3d/navigation_feel/orbit_inertia", 0.15);
+ _initial_set("editors/3d/navigation_feel/orbit_inertia", 0.05);
hints["editors/3d/navigation_feel/orbit_inertia"] = PropertyInfo(Variant::REAL, "editors/3d/navigation_feel/orbit_inertia", PROPERTY_HINT_RANGE, "0.0, 1, 0.01");
_initial_set("editors/3d/navigation_feel/translation_inertia", 0.15);
hints["editors/3d/navigation_feel/translation_inertia"] = PropertyInfo(Variant::REAL, "editors/3d/navigation_feel/translation_inertia", PROPERTY_HINT_RANGE, "0.0, 1, 0.01");
@@ -719,12 +409,13 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
// freelook
_initial_set("editors/3d/freelook/freelook_inertia", 0.1);
hints["editors/3d/freelook/freelook_inertia"] = PropertyInfo(Variant::REAL, "editors/3d/freelook/freelook_inertia", PROPERTY_HINT_RANGE, "0.0, 1, 0.01");
- _initial_set("editors/3d/freelook/freelook_base_speed", 0.1);
+ _initial_set("editors/3d/freelook/freelook_base_speed", 5.0);
hints["editors/3d/freelook/freelook_base_speed"] = PropertyInfo(Variant::REAL, "editors/3d/freelook/freelook_base_speed", PROPERTY_HINT_RANGE, "0.0, 10, 0.01");
_initial_set("editors/3d/freelook/freelook_activation_modifier", 0);
hints["editors/3d/freelook/freelook_activation_modifier"] = PropertyInfo(Variant::INT, "editors/3d/freelook/freelook_activation_modifier", PROPERTY_HINT_ENUM, "None,Shift,Alt,Meta,Ctrl");
_initial_set("editors/3d/freelook/freelook_modifier_speed_factor", 3.0);
hints["editors/3d/freelook/freelook_modifier_speed_factor"] = PropertyInfo(Variant::REAL, "editors/3d/freelook/freelook_modifier_speed_factor", PROPERTY_HINT_RANGE, "0.0, 10.0, 0.1");
+ _initial_set("editors/3d/freelook/freelook_speed_zoom_link", false);
_initial_set("editors/2d/bone_width", 5);
_initial_set("editors/2d/bone_color1", Color(1.0, 1.0, 1.0, 0.9));
@@ -733,6 +424,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
_initial_set("editors/2d/bone_ik_color", Color(0.9, 0.9, 0.45, 0.9));
_initial_set("editors/2d/keep_margins_when_changing_anchors", false);
_initial_set("editors/2d/warped_mouse_panning", true);
+ _initial_set("editors/2d/simple_spacebar_panning", false);
_initial_set("editors/2d/scroll_to_pan", false);
_initial_set("editors/2d/pan_speed", 20);
@@ -854,41 +546,464 @@ void EditorSettings::_load_default_text_editor_theme() {
_initial_set("text_editor/highlighting/search_result_border_color", Color(0.1, 0.45, 0.1, 1));
}
-void EditorSettings::notify_changes() {
+bool EditorSettings::_save_text_editor_theme(String p_file) {
+ String theme_section = "color_theme";
+ Ref<ConfigFile> cf = memnew(ConfigFile); // hex is better?
+ cf->set_value(theme_section, "background_color", ((Color)get("text_editor/highlighting/background_color")).to_html());
+ cf->set_value(theme_section, "completion_background_color", ((Color)get("text_editor/highlighting/completion_background_color")).to_html());
+ cf->set_value(theme_section, "completion_selected_color", ((Color)get("text_editor/highlighting/completion_selected_color")).to_html());
+ cf->set_value(theme_section, "completion_existing_color", ((Color)get("text_editor/highlighting/completion_existing_color")).to_html());
+ cf->set_value(theme_section, "completion_scroll_color", ((Color)get("text_editor/highlighting/completion_scroll_color")).to_html());
+ cf->set_value(theme_section, "completion_font_color", ((Color)get("text_editor/highlighting/completion_font_color")).to_html());
+ cf->set_value(theme_section, "caret_color", ((Color)get("text_editor/highlighting/caret_color")).to_html());
+ cf->set_value(theme_section, "caret_background_color", ((Color)get("text_editor/highlighting/caret_background_color")).to_html());
+ cf->set_value(theme_section, "line_number_color", ((Color)get("text_editor/highlighting/line_number_color")).to_html());
+ cf->set_value(theme_section, "text_color", ((Color)get("text_editor/highlighting/text_color")).to_html());
+ cf->set_value(theme_section, "text_selected_color", ((Color)get("text_editor/highlighting/text_selected_color")).to_html());
+ cf->set_value(theme_section, "keyword_color", ((Color)get("text_editor/highlighting/keyword_color")).to_html());
+ cf->set_value(theme_section, "base_type_color", ((Color)get("text_editor/highlighting/base_type_color")).to_html());
+ cf->set_value(theme_section, "engine_type_color", ((Color)get("text_editor/highlighting/engine_type_color")).to_html());
+ cf->set_value(theme_section, "function_color", ((Color)get("text_editor/highlighting/function_color")).to_html());
+ cf->set_value(theme_section, "member_variable_color", ((Color)get("text_editor/highlighting/member_variable_color")).to_html());
+ cf->set_value(theme_section, "comment_color", ((Color)get("text_editor/highlighting/comment_color")).to_html());
+ cf->set_value(theme_section, "string_color", ((Color)get("text_editor/highlighting/string_color")).to_html());
+ cf->set_value(theme_section, "number_color", ((Color)get("text_editor/highlighting/number_color")).to_html());
+ cf->set_value(theme_section, "symbol_color", ((Color)get("text_editor/highlighting/symbol_color")).to_html());
+ cf->set_value(theme_section, "selection_color", ((Color)get("text_editor/highlighting/selection_color")).to_html());
+ cf->set_value(theme_section, "brace_mismatch_color", ((Color)get("text_editor/highlighting/brace_mismatch_color")).to_html());
+ cf->set_value(theme_section, "current_line_color", ((Color)get("text_editor/highlighting/current_line_color")).to_html());
+ cf->set_value(theme_section, "line_length_guideline_color", ((Color)get("text_editor/highlighting/line_length_guideline_color")).to_html());
+ cf->set_value(theme_section, "mark_color", ((Color)get("text_editor/highlighting/mark_color")).to_html());
+ cf->set_value(theme_section, "breakpoint_color", ((Color)get("text_editor/highlighting/breakpoint_color")).to_html());
+ cf->set_value(theme_section, "word_highlighted_color", ((Color)get("text_editor/highlighting/word_highlighted_color")).to_html());
+ cf->set_value(theme_section, "search_result_color", ((Color)get("text_editor/highlighting/search_result_color")).to_html());
+ cf->set_value(theme_section, "search_result_border_color", ((Color)get("text_editor/highlighting/search_result_border_color")).to_html());
- _THREAD_SAFE_METHOD_
+ Error err = cf->save(p_file);
- SceneTree *sml = Object::cast_to<SceneTree>(OS::get_singleton()->get_main_loop());
+ if (err == OK) {
+ return true;
+ }
+ return false;
+}
+
+static Dictionary _get_builtin_script_templates() {
+ Dictionary templates;
+
+ //No Comments
+ templates["no_comments.gd"] =
+ "extends %BASE%\n"
+ "\n"
+ "func _ready():\n"
+ "%TS%pass\n";
+
+ //Empty
+ templates["empty.gd"] =
+ "extends %BASE%"
+ "\n"
+ "\n";
+
+ return templates;
+}
+
+static void _create_script_templates(const String &p_path) {
+
+ Dictionary templates = _get_builtin_script_templates();
+ List<Variant> keys;
+ templates.get_key_list(&keys);
+ FileAccess *file = FileAccess::create(FileAccess::ACCESS_FILESYSTEM);
+
+ DirAccess *dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ dir->change_dir(p_path);
+ for (int i = 0; i < keys.size(); i++) {
+ if (!dir->file_exists(keys[i])) {
+ Error err = file->reopen(p_path.plus_file((String)keys[i]), FileAccess::WRITE);
+ ERR_FAIL_COND(err != OK);
+ file->store_string(templates[keys[i]]);
+ file->close();
+ }
+ }
+
+ memdelete(dir);
+ memdelete(file);
+}
+
+// PUBLIC METHODS
+
+EditorSettings *EditorSettings::get_singleton() {
+
+ return singleton.ptr();
+}
+
+void EditorSettings::create() {
+
+ if (singleton.ptr())
+ return; //pointless
+
+ DirAccess *dir = NULL;
+
+ String data_path;
+ String data_dir;
+ String config_path;
+ String config_dir;
+ String cache_path;
+ String cache_dir;
+
+ Ref<ConfigFile> extra_config = memnew(ConfigFile);
+
+ String exe_path = OS::get_singleton()->get_executable_path().get_base_dir();
+ DirAccess *d = DirAccess::create_for_path(exe_path);
+ bool self_contained = false;
+
+ if (d->file_exists(exe_path + "/._sc_")) {
+ self_contained = true;
+ extra_config->load(exe_path + "/._sc_");
+ } else if (d->file_exists(exe_path + "/_sc_")) {
+ self_contained = true;
+ extra_config->load(exe_path + "/_sc_");
+ }
+ memdelete(d);
+
+ if (self_contained) {
+
+ // editor is self contained, all in same folder
+ data_path = exe_path;
+ data_dir = data_path.plus_file("editor_data");
+ config_path = exe_path;
+ config_dir = data_dir;
+ cache_path = exe_path;
+ cache_dir = data_dir.plus_file("cache");
+ } else {
+
+ // Typically XDG_DATA_HOME or %APPDATA%
+ data_path = OS::get_singleton()->get_data_path();
+ data_dir = data_path.plus_file(OS::get_singleton()->get_godot_dir_name());
+ // Can be different from data_path e.g. on Linux or macOS
+ config_path = OS::get_singleton()->get_config_path();
+ config_dir = config_path.plus_file(OS::get_singleton()->get_godot_dir_name());
+ // Can be different from above paths, otherwise a subfolder of data_dir
+ cache_path = OS::get_singleton()->get_cache_path();
+ if (cache_path == data_path) {
+ cache_dir = data_dir.plus_file("cache");
+ } else {
+ cache_dir = cache_path.plus_file(OS::get_singleton()->get_godot_dir_name());
+ }
+ }
+
+ ClassDB::register_class<EditorSettings>(); //otherwise it can't be unserialized
+
+ String config_file_path;
+
+ if (data_path != "" && config_path != "" && cache_path != "") {
+
+ // Validate/create data dir and subdirectories
+
+ dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ if (dir->change_dir(data_path) != OK) {
+ ERR_PRINT("Cannot find path for data directory!");
+ memdelete(dir);
+ goto fail;
+ }
+
+ if (dir->change_dir(data_dir) != OK) {
+ dir->make_dir(data_dir);
+ if (dir->change_dir(data_dir) != OK) {
+ ERR_PRINT("Cannot create data directory!");
+ memdelete(dir);
+ goto fail;
+ }
+ }
+
+ if (dir->change_dir("templates") != OK) {
+ dir->make_dir("templates");
+ } else {
+ dir->change_dir("..");
+ }
+
+ // Validate/create cache dir
+
+ if (dir->change_dir(cache_path) != OK) {
+ ERR_PRINT("Cannot find path for cache directory!");
+ memdelete(dir);
+ goto fail;
+ }
+
+ if (dir->change_dir(cache_dir) != OK) {
+ dir->make_dir(cache_dir);
+ if (dir->change_dir(cache_dir) != OK) {
+ ERR_PRINT("Cannot create cache directory!");
+ memdelete(dir);
+ goto fail;
+ }
+ }
+
+ // Validate/create config dir and subdirectories
+
+ if (dir->change_dir(config_path) != OK) {
+ ERR_PRINT("Cannot find path for config directory!");
+ memdelete(dir);
+ goto fail;
+ }
+
+ if (dir->change_dir(config_dir) != OK) {
+ dir->make_dir(config_dir);
+ if (dir->change_dir(config_dir) != OK) {
+ ERR_PRINT("Cannot create config directory!");
+ memdelete(dir);
+ goto fail;
+ }
+ }
+
+ if (dir->change_dir("text_editor_themes") != OK) {
+ dir->make_dir("text_editor_themes");
+ } else {
+ dir->change_dir("..");
+ }
+
+ if (dir->change_dir("script_templates") != OK) {
+ dir->make_dir("script_templates");
+ } else {
+ dir->change_dir("..");
+ }
+ _create_script_templates(dir->get_current_dir().plus_file("script_templates"));
+
+ if (dir->change_dir("projects") != OK) {
+ dir->make_dir("projects");
+ } else {
+ dir->change_dir("..");
+ }
+
+ // Validate/create project-specific config dir
+
+ dir->change_dir("projects");
+ String project_config_dir = ProjectSettings::get_singleton()->get_resource_path();
+ if (project_config_dir.ends_with("/"))
+ project_config_dir = config_path.substr(0, project_config_dir.size() - 1);
+ project_config_dir = project_config_dir.get_file() + "-" + project_config_dir.md5_text();
+
+ if (dir->change_dir(project_config_dir) != OK) {
+ dir->make_dir(project_config_dir);
+ } else {
+ dir->change_dir("..");
+ }
+ dir->change_dir("..");
+
+ // Validate editor config file
+
+ String config_file_name = "editor_settings-" + itos(VERSION_MAJOR) + ".tres";
+ config_file_path = config_dir.plus_file(config_file_name);
+ if (!dir->file_exists(config_file_name)) {
+ goto fail;
+ }
+
+ memdelete(dir);
+
+ singleton = ResourceLoader::load(config_file_path, "EditorSettings");
+
+ if (singleton.is_null()) {
+ WARN_PRINT("Could not open config file.");
+ goto fail;
+ }
+
+ singleton->save_changed_setting = true;
+ singleton->config_file_path = config_file_path;
+ singleton->project_config_dir = project_config_dir;
+ singleton->settings_dir = config_dir;
+ singleton->data_dir = data_dir;
+ singleton->cache_dir = cache_dir;
+
+ if (OS::get_singleton()->is_stdout_verbose()) {
+
+ print_line("EditorSettings: Load OK!");
+ }
+
+ singleton->setup_language();
+ singleton->setup_network();
+ singleton->load_favorites();
+ singleton->list_text_editor_themes();
- if (!sml) {
return;
}
- Node *root = sml->get_root()->get_child(0);
+fail:
- if (!root) {
+ // patch init projects
+ if (extra_config->has_section("init_projects")) {
+ Vector<String> list = extra_config->get_value("init_projects", "list");
+ for (int i = 0; i < list.size(); i++) {
+
+ list[i] = exe_path + "/" + list[i];
+ };
+ extra_config->set_value("init_projects", "list", list);
+ };
+
+ singleton = Ref<EditorSettings>(memnew(EditorSettings));
+ singleton->save_changed_setting = true;
+ singleton->config_file_path = config_file_path;
+ singleton->settings_dir = config_dir;
+ singleton->data_dir = data_dir;
+ singleton->cache_dir = cache_dir;
+ singleton->_load_defaults(extra_config);
+ singleton->setup_language();
+ singleton->setup_network();
+ singleton->list_text_editor_themes();
+}
+
+void EditorSettings::setup_language() {
+
+ String lang = get("interface/editor/editor_language");
+ if (lang == "en")
+ return; //none to do
+
+ for (int i = 0; i < translations.size(); i++) {
+ if (translations[i]->get_locale() == lang) {
+ TranslationServer::get_singleton()->set_tool_translation(translations[i]);
+ break;
+ }
+ }
+}
+
+void EditorSettings::setup_network() {
+
+ List<IP_Address> local_ip;
+ IP::get_singleton()->get_local_addresses(&local_ip);
+ String lip = "127.0.0.1";
+ String hint;
+ String current = has_setting("network/debug/remote_host") ? get("network/debug/remote_host") : "";
+ int port = has_setting("network/debug/remote_port") ? (int)get("network/debug/remote_port") : 6007;
+
+ for (List<IP_Address>::Element *E = local_ip.front(); E; E = E->next()) {
+
+ String ip = E->get();
+
+ // link-local IPv6 addresses don't work, skipping them
+ if (ip.begins_with("fe80:0:0:0:")) // fe80::/64
+ continue;
+ if (ip == current)
+ lip = current; //so it saves
+ if (hint != "")
+ hint += ",";
+ hint += ip;
+ }
+
+ _initial_set("network/debug/remote_host", lip);
+ add_property_hint(PropertyInfo(Variant::STRING, "network/debug/remote_host", PROPERTY_HINT_ENUM, hint));
+
+ _initial_set("network/debug/remote_port", port);
+ add_property_hint(PropertyInfo(Variant::INT, "network/debug/remote_port", PROPERTY_HINT_RANGE, "1,65535,1"));
+}
+
+void EditorSettings::save() {
+
+ //_THREAD_SAFE_METHOD_
+
+ if (!singleton.ptr())
+ return;
+
+ if (singleton->config_file_path == "") {
+ ERR_PRINT("Cannot save EditorSettings config, no valid path");
return;
}
- root->propagate_notification(NOTIFICATION_EDITOR_SETTINGS_CHANGED);
+
+ Error err = ResourceSaver::save(singleton->config_file_path, singleton);
+
+ if (err != OK) {
+ ERR_PRINT("Can't Save!");
+ return;
+ }
+
+ if (OS::get_singleton()->is_stdout_verbose()) {
+ print_line("EditorSettings Save OK!");
+ }
}
-void EditorSettings::_add_property_info_bind(const Dictionary &p_info) {
+void EditorSettings::destroy() {
- ERR_FAIL_COND(!p_info.has("name"));
- ERR_FAIL_COND(!p_info.has("type"));
+ if (!singleton.ptr())
+ return;
+ save();
+ singleton = Ref<EditorSettings>();
+}
- PropertyInfo pinfo;
- pinfo.name = p_info["name"];
- ERR_FAIL_COND(!props.has(pinfo.name));
- pinfo.type = Variant::Type(p_info["type"].operator int());
- ERR_FAIL_INDEX(pinfo.type, Variant::VARIANT_MAX);
+void EditorSettings::set_optimize_save(bool p_optimize) {
- if (p_info.has("hint"))
- pinfo.hint = PropertyHint(p_info["hint"].operator int());
- if (p_info.has("hint_string"))
- pinfo.hint_string = p_info["hint_string"];
+ optimize_save = p_optimize;
+}
- add_property_hint(pinfo);
+// Properties
+
+void EditorSettings::set_setting(const String &p_setting, const Variant &p_value) {
+ _THREAD_SAFE_METHOD_
+ set(p_setting, p_value);
+}
+
+Variant EditorSettings::get_setting(const String &p_setting) const {
+ _THREAD_SAFE_METHOD_
+ return get(p_setting);
+}
+
+bool EditorSettings::has_setting(const String &p_setting) const {
+
+ _THREAD_SAFE_METHOD_
+
+ return props.has(p_setting);
+}
+
+void EditorSettings::erase(const String &p_setting) {
+
+ _THREAD_SAFE_METHOD_
+
+ props.erase(p_setting);
+}
+
+void EditorSettings::raise_order(const String &p_setting) {
+ _THREAD_SAFE_METHOD_
+
+ ERR_FAIL_COND(!props.has(p_setting));
+ props[p_setting].order = ++last_order;
+}
+
+void EditorSettings::set_initial_value(const StringName &p_setting, const Variant &p_value) {
+
+ if (!props.has(p_setting))
+ return;
+ props[p_setting].initial = p_value;
+ props[p_setting].has_default_value = true;
+}
+
+Variant _EDITOR_DEF(const String &p_setting, const Variant &p_default) {
+
+ Variant ret = p_default;
+ if (EditorSettings::get_singleton()->has_setting(p_setting))
+ ret = EditorSettings::get_singleton()->get(p_setting);
+ else
+ EditorSettings::get_singleton()->set(p_setting, p_default);
+ if (!EditorSettings::get_singleton()->has_default_value(p_setting))
+ EditorSettings::get_singleton()->set_initial_value(p_setting, p_default);
+
+ return ret;
+}
+
+Variant _EDITOR_GET(const String &p_setting) {
+
+ ERR_FAIL_COND_V(!EditorSettings::get_singleton()->has_setting(p_setting), Variant())
+ return EditorSettings::get_singleton()->get(p_setting);
+}
+
+bool EditorSettings::property_can_revert(const String &p_setting) {
+
+ if (!props.has(p_setting))
+ return false;
+
+ return props[p_setting].initial != props[p_setting].variant;
+}
+
+Variant EditorSettings::property_get_revert(const String &p_setting) {
+
+ if (!props.has(p_setting))
+ return Variant();
+
+ return props[p_setting].initial;
}
void EditorSettings::add_property_hint(const PropertyInfo &p_hint) {
@@ -898,10 +1013,71 @@ void EditorSettings::add_property_hint(const PropertyInfo &p_hint) {
hints[p_hint.name] = p_hint;
}
+// Data directories
+
+String EditorSettings::get_data_dir() const {
+
+ return data_dir;
+}
+
+String EditorSettings::get_templates_dir() const {
+
+ return get_data_dir().plus_file("templates");
+}
+
+// Config directories
+
+String EditorSettings::get_settings_dir() const {
+
+ return settings_dir;
+}
+
+String EditorSettings::get_project_settings_dir() const {
+
+ return get_settings_dir().plus_file("projects").plus_file(project_config_dir);
+}
+
+String EditorSettings::get_text_editor_themes_dir() const {
+
+ return get_settings_dir().plus_file("text_editor_themes");
+}
+
+String EditorSettings::get_script_templates_dir() const {
+
+ return get_settings_dir().plus_file("script_templates");
+}
+
+// Cache directory
+
+String EditorSettings::get_cache_dir() const {
+
+ return cache_dir;
+}
+
+// Metadata
+
+void EditorSettings::set_project_metadata(const String &p_section, const String &p_key, Variant p_data) {
+ Ref<ConfigFile> cf = memnew(ConfigFile);
+ String path = get_project_settings_dir().plus_file("project_metadata.cfg");
+ cf->load(path);
+ cf->set_value(p_section, p_key, p_data);
+ cf->save(path);
+}
+
+Variant EditorSettings::get_project_metadata(const String &p_section, const String &p_key, Variant p_default) {
+ Ref<ConfigFile> cf = memnew(ConfigFile);
+ String path = get_project_settings_dir().plus_file("project_metadata.cfg");
+ Error err = cf->load(path);
+ if (err != OK) {
+ return p_default;
+ }
+ return cf->get_value(p_section, p_key, p_default);
+}
+
void EditorSettings::set_favorite_dirs(const Vector<String> &p_favorites_dirs) {
favorite_dirs = p_favorites_dirs;
- FileAccess *f = FileAccess::open(get_project_settings_path().plus_file("favorite_dirs"), FileAccess::WRITE);
+ FileAccess *f = FileAccess::open(get_project_settings_dir().plus_file("favorite_dirs"), FileAccess::WRITE);
if (f) {
for (int i = 0; i < favorite_dirs.size(); i++)
f->store_line(favorite_dirs[i]);
@@ -917,7 +1093,7 @@ Vector<String> EditorSettings::get_favorite_dirs() const {
void EditorSettings::set_recent_dirs(const Vector<String> &p_recent_dirs) {
recent_dirs = p_recent_dirs;
- FileAccess *f = FileAccess::open(get_project_settings_path().plus_file("recent_dirs"), FileAccess::WRITE);
+ FileAccess *f = FileAccess::open(get_project_settings_dir().plus_file("recent_dirs"), FileAccess::WRITE);
if (f) {
for (int i = 0; i < recent_dirs.size(); i++)
f->store_line(recent_dirs[i]);
@@ -930,14 +1106,9 @@ Vector<String> EditorSettings::get_recent_dirs() const {
return recent_dirs;
}
-String EditorSettings::get_project_settings_path() const {
-
- return get_settings_path().plus_file("config").plus_file(project_config_path);
-}
-
void EditorSettings::load_favorites() {
- FileAccess *f = FileAccess::open(get_project_settings_path().plus_file("favorite_dirs"), FileAccess::READ);
+ FileAccess *f = FileAccess::open(get_project_settings_dir().plus_file("favorite_dirs"), FileAccess::READ);
if (f) {
String line = f->get_line().strip_edges();
while (line != "") {
@@ -947,7 +1118,7 @@ void EditorSettings::load_favorites() {
memdelete(f);
}
- f = FileAccess::open(get_project_settings_path().plus_file("recent_dirs"), FileAccess::READ);
+ f = FileAccess::open(get_project_settings_dir().plus_file("recent_dirs"), FileAccess::READ);
if (f) {
String line = f->get_line().strip_edges();
while (line != "") {
@@ -960,7 +1131,7 @@ void EditorSettings::load_favorites() {
void EditorSettings::list_text_editor_themes() {
String themes = "Adaptive,Default";
- DirAccess *d = DirAccess::open(settings_path + "/text_editor_themes");
+ DirAccess *d = DirAccess::open(get_text_editor_themes_dir());
if (d) {
d->list_dir_begin();
String file = d->get_next();
@@ -982,7 +1153,7 @@ void EditorSettings::load_text_editor_theme() {
return;
}
- String theme_path = get_settings_path() + "/text_editor_themes/" + get("text_editor/theme/color_theme") + ".tet";
+ String theme_path = get_text_editor_themes_dir().plus_file((String)get("text_editor/theme/color_theme") + ".tet");
Ref<ConfigFile> cf = memnew(ConfigFile);
Error err = cf->load(theme_path);
@@ -1020,9 +1191,9 @@ bool EditorSettings::import_text_editor_theme(String p_file) {
return false;
}
- DirAccess *d = DirAccess::open(settings_path + "/text_editor_themes");
+ DirAccess *d = DirAccess::open(get_text_editor_themes_dir());
if (d) {
- d->copy(p_file, settings_path + "/text_editor_themes/" + p_file.get_file());
+ d->copy(p_file, get_text_editor_themes_dir().plus_file(p_file.get_file()));
memdelete(d);
return true;
}
@@ -1037,7 +1208,7 @@ bool EditorSettings::save_text_editor_theme() {
if (p_file.get_file().to_lower() == "default" || p_file.get_file().to_lower() == "adaptive") {
return false;
}
- String theme_path = get_settings_path() + "/text_editor_themes/" + p_file + ".tet";
+ String theme_path = get_text_editor_themes_dir().plus_file(p_file + ".tet");
return _save_text_editor_theme(theme_path);
}
@@ -1055,7 +1226,7 @@ bool EditorSettings::save_text_editor_theme_as(String p_file) {
list_text_editor_themes();
String theme_name = p_file.substr(0, p_file.length() - 4).get_file();
- if (p_file.get_base_dir() == get_settings_path() + "/text_editor_themes") {
+ if (p_file.get_base_dir() == get_text_editor_themes_dir()) {
_initial_set("text_editor/theme/color_theme", theme_name);
load_text_editor_theme();
}
@@ -1067,7 +1238,7 @@ bool EditorSettings::save_text_editor_theme_as(String p_file) {
Vector<String> EditorSettings::get_script_templates(const String &p_extension) {
Vector<String> templates;
- DirAccess *d = DirAccess::open(settings_path + "/script_templates");
+ DirAccess *d = DirAccess::open(get_script_templates_dir());
if (d) {
d->list_dir_begin();
String file = d->get_next();
@@ -1083,47 +1254,13 @@ Vector<String> EditorSettings::get_script_templates(const String &p_extension) {
return templates;
}
-bool EditorSettings::_save_text_editor_theme(String p_file) {
- String theme_section = "color_theme";
- Ref<ConfigFile> cf = memnew(ConfigFile); // hex is better?
- cf->set_value(theme_section, "background_color", ((Color)get("text_editor/highlighting/background_color")).to_html());
- cf->set_value(theme_section, "completion_background_color", ((Color)get("text_editor/highlighting/completion_background_color")).to_html());
- cf->set_value(theme_section, "completion_selected_color", ((Color)get("text_editor/highlighting/completion_selected_color")).to_html());
- cf->set_value(theme_section, "completion_existing_color", ((Color)get("text_editor/highlighting/completion_existing_color")).to_html());
- cf->set_value(theme_section, "completion_scroll_color", ((Color)get("text_editor/highlighting/completion_scroll_color")).to_html());
- cf->set_value(theme_section, "completion_font_color", ((Color)get("text_editor/highlighting/completion_font_color")).to_html());
- cf->set_value(theme_section, "caret_color", ((Color)get("text_editor/highlighting/caret_color")).to_html());
- cf->set_value(theme_section, "caret_background_color", ((Color)get("text_editor/highlighting/caret_background_color")).to_html());
- cf->set_value(theme_section, "line_number_color", ((Color)get("text_editor/highlighting/line_number_color")).to_html());
- cf->set_value(theme_section, "text_color", ((Color)get("text_editor/highlighting/text_color")).to_html());
- cf->set_value(theme_section, "text_selected_color", ((Color)get("text_editor/highlighting/text_selected_color")).to_html());
- cf->set_value(theme_section, "keyword_color", ((Color)get("text_editor/highlighting/keyword_color")).to_html());
- cf->set_value(theme_section, "base_type_color", ((Color)get("text_editor/highlighting/base_type_color")).to_html());
- cf->set_value(theme_section, "engine_type_color", ((Color)get("text_editor/highlighting/engine_type_color")).to_html());
- cf->set_value(theme_section, "function_color", ((Color)get("text_editor/highlighting/function_color")).to_html());
- cf->set_value(theme_section, "member_variable_color", ((Color)get("text_editor/highlighting/member_variable_color")).to_html());
- cf->set_value(theme_section, "comment_color", ((Color)get("text_editor/highlighting/comment_color")).to_html());
- cf->set_value(theme_section, "string_color", ((Color)get("text_editor/highlighting/string_color")).to_html());
- cf->set_value(theme_section, "number_color", ((Color)get("text_editor/highlighting/number_color")).to_html());
- cf->set_value(theme_section, "symbol_color", ((Color)get("text_editor/highlighting/symbol_color")).to_html());
- cf->set_value(theme_section, "selection_color", ((Color)get("text_editor/highlighting/selection_color")).to_html());
- cf->set_value(theme_section, "brace_mismatch_color", ((Color)get("text_editor/highlighting/brace_mismatch_color")).to_html());
- cf->set_value(theme_section, "current_line_color", ((Color)get("text_editor/highlighting/current_line_color")).to_html());
- cf->set_value(theme_section, "line_length_guideline_color", ((Color)get("text_editor/highlighting/line_length_guideline_color")).to_html());
- cf->set_value(theme_section, "mark_color", ((Color)get("text_editor/highlighting/mark_color")).to_html());
- cf->set_value(theme_section, "breakpoint_color", ((Color)get("text_editor/highlighting/breakpoint_color")).to_html());
- cf->set_value(theme_section, "word_highlighted_color", ((Color)get("text_editor/highlighting/word_highlighted_color")).to_html());
- cf->set_value(theme_section, "search_result_color", ((Color)get("text_editor/highlighting/search_result_color")).to_html());
- cf->set_value(theme_section, "search_result_border_color", ((Color)get("text_editor/highlighting/search_result_border_color")).to_html());
-
- Error err = cf->save(p_file);
+String EditorSettings::get_editor_layouts_config() const {
- if (err == OK) {
- return true;
- }
- return false;
+ return get_settings_dir().plus_file("editor_layouts.cfg");
}
+// Shortcuts
+
void EditorSettings::add_shortcut(const String &p_name, Ref<ShortCut> &p_shortcut) {
shortcuts[p_name] = p_shortcut;
@@ -1157,49 +1294,64 @@ void EditorSettings::get_shortcut_list(List<String> *r_shortcuts) {
}
}
-void EditorSettings::set_optimize_save(bool p_optimize) {
+Ref<ShortCut> ED_GET_SHORTCUT(const String &p_path) {
- optimize_save = p_optimize;
+ Ref<ShortCut> sc = EditorSettings::get_singleton()->get_shortcut(p_path);
+ if (!sc.is_valid()) {
+ ERR_EXPLAIN("Used ED_GET_SHORTCUT with invalid shortcut: " + p_path);
+ ERR_FAIL_COND_V(!sc.is_valid(), sc);
+ }
+
+ return sc;
}
-Variant EditorSettings::get_project_metadata(const String &p_section, const String &p_key, Variant p_default) {
- Ref<ConfigFile> cf = memnew(ConfigFile);
- String path = get_project_settings_path().plus_file("project_metadata.cfg");
- Error err = cf->load(path);
- if (err != OK) {
- return p_default;
+Ref<ShortCut> ED_SHORTCUT(const String &p_path, const String &p_name, uint32_t p_keycode) {
+
+ Ref<InputEventKey> ie;
+ if (p_keycode) {
+ ie.instance();
+
+ ie->set_unicode(p_keycode & KEY_CODE_MASK);
+ ie->set_scancode(p_keycode & KEY_CODE_MASK);
+ ie->set_shift(bool(p_keycode & KEY_MASK_SHIFT));
+ ie->set_alt(bool(p_keycode & KEY_MASK_ALT));
+ ie->set_control(bool(p_keycode & KEY_MASK_CTRL));
+ ie->set_metakey(bool(p_keycode & KEY_MASK_META));
}
- return cf->get_value(p_section, p_key, p_default);
-}
-void EditorSettings::set_project_metadata(const String &p_section, const String &p_key, Variant p_data) {
- Ref<ConfigFile> cf = memnew(ConfigFile);
- String path = get_project_settings_path().plus_file("project_metadata.cfg");
- cf->load(path);
- cf->set_value(p_section, p_key, p_data);
- cf->save(path);
-}
+ Ref<ShortCut> sc = EditorSettings::get_singleton()->get_shortcut(p_path);
+ if (sc.is_valid()) {
-bool EditorSettings::property_can_revert(const String &p_name) {
+ sc->set_name(p_name); //keep name (the ones that come from disk have no name)
+ sc->set_meta("original", ie); //to compare against changes
+ return sc;
+ }
- if (!props.has(p_name))
- return false;
+ sc.instance();
+ sc->set_name(p_name);
+ sc->set_shortcut(ie);
+ sc->set_meta("original", ie); //to compare against changes
+ EditorSettings::get_singleton()->add_shortcut(p_path, sc);
- return props[p_name].initial != props[p_name].variant;
+ return sc;
}
-Variant EditorSettings::property_get_revert(const String &p_name) {
+void EditorSettings::notify_changes() {
- if (!props.has(p_name))
- return Variant();
+ _THREAD_SAFE_METHOD_
- return props[p_name].initial;
-}
+ SceneTree *sml = Object::cast_to<SceneTree>(OS::get_singleton()->get_main_loop());
-void EditorSettings::set_initial_value(const StringName &p_name, const Variant &p_value) {
+ if (!sml) {
+ return;
+ }
- ERR_FAIL_COND(!props.has(p_name));
- props[p_name].initial = p_value;
+ Node *root = sml->get_root()->get_child(0);
+
+ if (!root) {
+ return;
+ }
+ root->propagate_notification(NOTIFICATION_EDITOR_SETTINGS_CHANGED);
}
void EditorSettings::_bind_methods() {
@@ -1207,24 +1359,20 @@ void EditorSettings::_bind_methods() {
ClassDB::bind_method(D_METHOD("has_setting", "name"), &EditorSettings::has_setting);
ClassDB::bind_method(D_METHOD("set_setting", "name", "value"), &EditorSettings::set_setting);
ClassDB::bind_method(D_METHOD("get_setting", "name"), &EditorSettings::get_setting);
-
ClassDB::bind_method(D_METHOD("erase", "property"), &EditorSettings::erase);
- ClassDB::bind_method(D_METHOD("get_settings_path"), &EditorSettings::get_settings_path);
- ClassDB::bind_method(D_METHOD("get_project_settings_path"), &EditorSettings::get_project_settings_path);
-
+ ClassDB::bind_method(D_METHOD("set_initial_value", "name", "value"), &EditorSettings::set_initial_value);
+ ClassDB::bind_method(D_METHOD("property_can_revert", "name"), &EditorSettings::property_can_revert);
+ ClassDB::bind_method(D_METHOD("property_get_revert", "name"), &EditorSettings::property_get_revert);
ClassDB::bind_method(D_METHOD("add_property_info", "info"), &EditorSettings::_add_property_info_bind);
+ ClassDB::bind_method(D_METHOD("get_settings_dir"), &EditorSettings::get_settings_dir);
+ ClassDB::bind_method(D_METHOD("get_project_settings_dir"), &EditorSettings::get_project_settings_dir);
+
ClassDB::bind_method(D_METHOD("set_favorite_dirs", "dirs"), &EditorSettings::set_favorite_dirs);
ClassDB::bind_method(D_METHOD("get_favorite_dirs"), &EditorSettings::get_favorite_dirs);
-
ClassDB::bind_method(D_METHOD("set_recent_dirs", "dirs"), &EditorSettings::set_recent_dirs);
ClassDB::bind_method(D_METHOD("get_recent_dirs"), &EditorSettings::get_recent_dirs);
- ClassDB::bind_method(D_METHOD("property_can_revert", "name"), &EditorSettings::property_can_revert);
- ClassDB::bind_method(D_METHOD("property_get_revert", "name"), &EditorSettings::property_get_revert);
-
- ClassDB::bind_method(D_METHOD("set_initial_value", "name", "value"), &EditorSettings::set_initial_value);
-
ADD_SIGNAL(MethodInfo("settings_changed"));
}
@@ -1260,45 +1408,3 @@ EditorSettings::EditorSettings() {
EditorSettings::~EditorSettings() {
}
-
-Ref<ShortCut> ED_GET_SHORTCUT(const String &p_path) {
-
- Ref<ShortCut> sc = EditorSettings::get_singleton()->get_shortcut(p_path);
- if (!sc.is_valid()) {
- ERR_EXPLAIN("Used ED_GET_SHORTCUT with invalid shortcut: " + p_path);
- ERR_FAIL_COND_V(!sc.is_valid(), sc);
- }
-
- return sc;
-}
-
-Ref<ShortCut> ED_SHORTCUT(const String &p_path, const String &p_name, uint32_t p_keycode) {
-
- Ref<InputEventKey> ie;
- if (p_keycode) {
- ie.instance();
-
- ie->set_unicode(p_keycode & KEY_CODE_MASK);
- ie->set_scancode(p_keycode & KEY_CODE_MASK);
- ie->set_shift(bool(p_keycode & KEY_MASK_SHIFT));
- ie->set_alt(bool(p_keycode & KEY_MASK_ALT));
- ie->set_control(bool(p_keycode & KEY_MASK_CTRL));
- ie->set_metakey(bool(p_keycode & KEY_MASK_META));
- }
-
- Ref<ShortCut> sc = EditorSettings::get_singleton()->get_shortcut(p_path);
- if (sc.is_valid()) {
-
- sc->set_name(p_name); //keep name (the ones that come from disk have no name)
- sc->set_meta("original", ie); //to compare against changes
- return sc;
- }
-
- sc.instance();
- sc->set_name(p_name);
- sc->set_shortcut(ie);
- sc->set_meta("original", ie); //to compare against changes
- EditorSettings::get_singleton()->add_shortcut(p_path, sc);
-
- return sc;
-}
diff --git a/editor/editor_settings.h b/editor/editor_settings.h
index c5d2670650..a8c991a6d9 100644
--- a/editor/editor_settings.h
+++ b/editor/editor_settings.h
@@ -66,11 +66,13 @@ private:
int order;
Variant variant;
Variant initial;
+ bool has_default_value;
bool hide_from_editor;
bool save;
VariantContainer() {
order = 0;
hide_from_editor = false;
+ has_default_value = false;
save = false;
}
VariantContainer(const Variant &p_variant, int p_order) {
@@ -80,44 +82,39 @@ private:
}
};
+ static Ref<EditorSettings> singleton;
+
HashMap<String, PropertyInfo> hints;
- int last_order;
HashMap<String, VariantContainer> props;
- String resource_path;
-
- bool _set(const StringName &p_name, const Variant &p_value, bool p_emit_signal = true);
- bool _get(const StringName &p_name, Variant &r_ret) const;
- void _get_property_list(List<PropertyInfo> *p_list) const;
-
- void _initial_set(const StringName &p_name, const Variant &p_value);
+ int last_order;
- static Ref<EditorSettings> singleton;
+ Ref<Resource> clipboard;
+ Vector<Ref<Translation> > translations;
+ Map<String, Ref<ShortCut> > shortcuts;
+ String resource_path;
+ String settings_dir;
+ String data_dir;
+ String cache_dir;
String config_file_path;
- String settings_path;
+ String project_config_dir;
- Ref<Resource> clipboard;
+ Vector<String> favorite_dirs;
+ Vector<String> recent_dirs;
bool save_changed_setting;
-
bool optimize_save; //do not save stuff that came from config but was not set from engine
+ bool _set(const StringName &p_name, const Variant &p_value, bool p_emit_signal = true);
+ bool _get(const StringName &p_name, Variant &r_ret) const;
+ void _initial_set(const StringName &p_name, const Variant &p_value);
+ void _get_property_list(List<PropertyInfo> *p_list) const;
+ void _add_property_info_bind(const Dictionary &p_info);
+
void _load_defaults(Ref<ConfigFile> p_extra_config = NULL);
void _load_default_text_editor_theme();
-
bool _save_text_editor_theme(String p_file);
- String project_config_path;
-
- Vector<String> favorite_dirs;
- Vector<String> recent_dirs;
-
- Vector<Ref<Translation> > translations;
-
- Map<String, Ref<ShortCut> > shortcuts;
-
- void _add_property_info_bind(const Dictionary &p_info);
-
protected:
static void _bind_methods();
@@ -126,41 +123,47 @@ public:
NOTIFICATION_EDITOR_SETTINGS_CHANGED = 10000
};
- void set_manually(const StringName &p_name, const Variant &p_value, bool p_emit_signal = false) {
- _set(p_name, p_value, p_emit_signal);
- }
-
- void set_setting(const String &p_setting, const Variant &p_value);
- Variant get_setting(const String &p_setting) const;
-
- bool has_setting(String p_var) const;
static EditorSettings *get_singleton();
- void erase(String p_var);
- String get_settings_path() const;
- //String get_global_settings_path() const;
- String get_project_settings_path() const;
+ static void create();
void setup_language();
void setup_network();
-
- void raise_order(const String &p_name);
- static void create();
static void save();
static void destroy();
+ void set_optimize_save(bool p_optimize);
- void notify_changes();
+ bool has_default_value(const String &p_setting) const;
+ void set_setting(const String &p_setting, const Variant &p_value);
+ Variant get_setting(const String &p_setting) const;
+ bool has_setting(const String &p_setting) const;
+ void erase(const String &p_setting);
+ void raise_order(const String &p_setting);
+ void set_initial_value(const StringName &p_setting, const Variant &p_value);
+ void set_manually(const StringName &p_setting, const Variant &p_value, bool p_emit_signal = false) {
+ _set(p_setting, p_value, p_emit_signal);
+ }
+ bool property_can_revert(const String &p_setting);
+ Variant property_get_revert(const String &p_setting);
+ void add_property_hint(const PropertyInfo &p_hint);
void set_resource_clipboard(const Ref<Resource> &p_resource) { clipboard = p_resource; }
Ref<Resource> get_resource_clipboard() const { return clipboard; }
- void add_property_hint(const PropertyInfo &p_hint);
+ String get_data_dir() const;
+ String get_templates_dir() const;
+ String get_settings_dir() const;
+ String get_project_settings_dir() const;
+ String get_text_editor_themes_dir() const;
+ String get_script_templates_dir() const;
+ String get_cache_dir() const;
+
+ void set_project_metadata(const String &p_section, const String &p_key, Variant p_data);
+ Variant get_project_metadata(const String &p_section, const String &p_key, Variant p_default);
void set_favorite_dirs(const Vector<String> &p_favorites_dirs);
Vector<String> get_favorite_dirs() const;
-
void set_recent_dirs(const Vector<String> &p_recent_dirs);
Vector<String> get_recent_dirs() const;
-
void load_favorites();
void list_text_editor_themes();
@@ -170,21 +173,14 @@ public:
bool save_text_editor_theme_as(String p_file);
Vector<String> get_script_templates(const String &p_extension);
+ String get_editor_layouts_config() const;
void add_shortcut(const String &p_name, Ref<ShortCut> &p_shortcut);
bool is_shortcut(const String &p_name, const Ref<InputEvent> &p_event) const;
Ref<ShortCut> get_shortcut(const String &p_name) const;
void get_shortcut_list(List<String> *r_shortcuts);
- void set_optimize_save(bool p_optimize);
-
- Variant get_project_metadata(const String &p_section, const String &p_key, Variant p_default);
- void set_project_metadata(const String &p_section, const String &p_key, Variant p_data);
-
- bool property_can_revert(const String &p_name);
- Variant property_get_revert(const String &p_name);
-
- void set_initial_value(const StringName &p_name, const Variant &p_value);
+ void notify_changes();
EditorSettings();
~EditorSettings();
@@ -193,10 +189,10 @@ public:
//not a macro any longer
#define EDITOR_DEF(m_var, m_val) _EDITOR_DEF(m_var, Variant(m_val))
-Variant _EDITOR_DEF(const String &p_var, const Variant &p_default);
+Variant _EDITOR_DEF(const String &p_setting, const Variant &p_default);
#define EDITOR_GET(m_var) _EDITOR_GET(m_var)
-Variant _EDITOR_GET(const String &p_var);
+Variant _EDITOR_GET(const String &p_setting);
#define ED_IS_SHORTCUT(p_name, p_ev) (EditorSettings::get_singleton()->is_shortcut(p_name, p_ev))
Ref<ShortCut> ED_SHORTCUT(const String &p_path, const String &p_name, uint32_t p_keycode = 0);
diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp
index 0436ac78df..ae29b7420e 100644
--- a/editor/editor_themes.cpp
+++ b/editor/editor_themes.cpp
@@ -233,7 +233,6 @@ void editor_register_and_generate_icons(Ref<Theme> p_theme, bool p_dark_theme =
clock_t end_time = clock();
double time_d = (double)(end_time - begin_time) / CLOCKS_PER_SEC;
- print_line("SVG_GENERATION TIME: " + rtos(time_d));
#else
print_line("Sorry no icons for you");
#endif
@@ -350,6 +349,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_color("contrast_color_2", "Editor", contrast_color_2);
theme->set_color("font_color", "Editor", font_color);
+ theme->set_color("highlighted_font_color", "Editor", font_color_hl);
theme->set_color("disabled_font_color", "Editor", font_color_disabled);
theme->set_color("mono_color", "Editor", mono_color);
@@ -391,7 +391,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
editor_register_and_generate_icons(theme, dark_theme, thumb_size);
}
// thumbnail size has changed, so we regenerate the medium sizes
- if (p_theme != NULL && fabs(p_theme->get_constant("thumb_size", "Editor") - thumb_size) > 0.00001) {
+ if (p_theme != NULL && fabs((double)p_theme->get_constant("thumb_size", "Editor") - thumb_size) > 0.00001) {
editor_register_and_generate_icons(p_theme, dark_theme, thumb_size, true);
}
@@ -568,6 +568,11 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_constant("modulate_arrow", "OptionButton", true);
// CheckButton
+ theme->set_stylebox("normal", "CheckButton", style_menu);
+ theme->set_stylebox("pressed", "CheckButton", style_menu);
+ theme->set_stylebox("disabled", "CheckButton", style_menu);
+ theme->set_stylebox("hover", "CheckButton", style_menu);
+
theme->set_icon("on", "CheckButton", theme->get_icon("GuiToggleOn", "EditorIcons"));
theme->set_icon("off", "CheckButton", theme->get_icon("GuiToggleOff", "EditorIcons"));
@@ -577,7 +582,22 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_color("font_color_disabled", "CheckButton", font_color_disabled);
theme->set_color("icon_color_hover", "CheckButton", font_color_hl);
+ theme->set_constant("hseparation", "CheckButton", 4 * EDSCALE);
+ theme->set_constant("check_vadjust", "CheckButton", 0 * EDSCALE);
+
// Checkbox
+ Ref<StyleBoxFlat> sb_checkbox = style_menu->duplicate();
+ // HACK, in reality, the checkbox draws the text over the icon by default, so the margin compensates that.
+ const int cb_w = theme->get_icon("GuiChecked", "EditorIcons")->get_width() + default_margin_size;
+ sb_checkbox->set_default_margin(MARGIN_LEFT, cb_w * EDSCALE);
+ sb_checkbox->set_default_margin(MARGIN_RIGHT, default_margin_size * EDSCALE);
+ sb_checkbox->set_default_margin(MARGIN_TOP, default_margin_size * EDSCALE);
+ sb_checkbox->set_default_margin(MARGIN_BOTTOM, default_margin_size * EDSCALE);
+
+ theme->set_stylebox("normal", "CheckBox", sb_checkbox);
+ theme->set_stylebox("pressed", "CheckBox", sb_checkbox);
+ theme->set_stylebox("disabled", "CheckBox", sb_checkbox);
+ theme->set_stylebox("hover", "CheckBox", sb_checkbox);
theme->set_icon("checked", "CheckBox", theme->get_icon("GuiChecked", "EditorIcons"));
theme->set_icon("unchecked", "CheckBox", theme->get_icon("GuiUnchecked", "EditorIcons"));
theme->set_icon("radio_checked", "CheckBox", theme->get_icon("GuiRadioChecked", "EditorIcons"));
@@ -589,6 +609,9 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_color("font_color_disabled", "CheckBox", font_color_disabled);
theme->set_color("icon_color_hover", "CheckBox", font_color_hl);
+ theme->set_constant("hseparation", "CheckBox", 4 * EDSCALE);
+ theme->set_constant("check_vadjust", "CheckBox", 0 * EDSCALE);
+
// PopupMenu
Ref<StyleBoxFlat> style_popup_menu = style_popup;
theme->set_stylebox("panel", "PopupMenu", style_popup_menu);
@@ -715,6 +738,13 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_stylebox("button", "Tabs", style_menu);
theme->set_icon("increment", "TabContainer", theme->get_icon("GuiScrollArrowRight", "EditorIcons"));
theme->set_icon("decrement", "TabContainer", theme->get_icon("GuiScrollArrowLeft", "EditorIcons"));
+ theme->set_icon("increment", "Tabs", theme->get_icon("GuiScrollArrowRight", "EditorIcons"));
+ theme->set_icon("decrement", "Tabs", theme->get_icon("GuiScrollArrowLeft", "EditorIcons"));
+ theme->set_icon("increment_highlight", "Tabs", theme->get_icon("GuiScrollArrowRight", "EditorIcons"));
+ theme->set_icon("decrement_highlight", "Tabs", theme->get_icon("GuiScrollArrowLeft", "EditorIcons"));
+ theme->set_icon("increment_highlight", "TabContainer", theme->get_icon("GuiScrollArrowRight", "EditorIcons"));
+ theme->set_icon("decrement_highlight", "TabContainer", theme->get_icon("GuiScrollArrowLeft", "EditorIcons"));
+ theme->set_constant("hseparation", "Tabs", 4 * EDSCALE);
// Content of each tab
Ref<StyleBoxFlat> style_content_panel = style_default->duplicate();
@@ -801,6 +831,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_constant("close_h_ofs", "WindowDialog", 22 * EDSCALE);
theme->set_constant("close_v_ofs", "WindowDialog", 20 * EDSCALE);
theme->set_constant("title_height", "WindowDialog", 24 * EDSCALE);
+ theme->set_font("title_font", "WindowDialog", theme->get_font("title", "EditorFonts"));
// complex window, for now only Editor settings and Project settings
Ref<StyleBoxFlat> style_complex_window = style_window->duplicate();
@@ -971,8 +1002,8 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
const Color dim_color = Color(font_color.r, font_color.g, font_color.b, 0.5);
const float mono_value = mono_color.r;
- const Color alpha1 = Color(mono_value, mono_value, mono_value, 0.1);
- const Color alpha2 = Color(mono_value, mono_value, mono_value, 0.3);
+ const Color alpha1 = Color(mono_value, mono_value, mono_value, 0.07);
+ const Color alpha2 = Color(mono_value, mono_value, mono_value, 0.14);
const Color alpha3 = Color(mono_value, mono_value, mono_value, 0.5);
const Color alpha4 = Color(mono_value, mono_value, mono_value, 0.7);
@@ -997,7 +1028,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
const Color caret_color = mono_color;
const Color caret_background_color = mono_color.inverted();
const Color text_selected_color = dark_color_3;
- const Color selection_color = alpha3;
+ const Color selection_color = alpha2;
const Color brace_mismatch_color = error_color;
const Color current_line_color = alpha1;
const Color line_length_guideline_color = warning_color;
@@ -1043,12 +1074,14 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
return theme;
}
-Ref<Theme> create_custom_theme() {
+Ref<Theme> create_custom_theme(const Ref<Theme> p_theme) {
Ref<Theme> theme;
String custom_theme = EditorSettings::get_singleton()->get("interface/theme/custom_theme");
if (custom_theme != "") {
theme = ResourceLoader::load(custom_theme);
+ } else {
+ theme = create_editor_theme(p_theme);
}
String global_font = EditorSettings::get_singleton()->get("interface/editor/custom_font");
diff --git a/editor/editor_themes.h b/editor/editor_themes.h
index a644c5936f..6f3b83e0b0 100644
--- a/editor/editor_themes.h
+++ b/editor/editor_themes.h
@@ -34,6 +34,6 @@
Ref<Theme> create_editor_theme(Ref<Theme> p_theme = NULL);
-Ref<Theme> create_custom_theme();
+Ref<Theme> create_custom_theme(Ref<Theme> p_theme = NULL);
#endif
diff --git a/editor/export_template_manager.cpp b/editor/export_template_manager.cpp
index d867404f3d..d208bbe662 100644
--- a/editor/export_template_manager.cpp
+++ b/editor/export_template_manager.cpp
@@ -31,6 +31,7 @@
#include "editor_node.h"
#include "editor_scale.h"
+#include "io/json.h"
#include "io/zip_io.h"
#include "os/dir_access.h"
#include "version.h"
@@ -46,7 +47,7 @@ void ExportTemplateManager::_update_template_list() {
}
DirAccess *d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- Error err = d->change_dir(EditorSettings::get_singleton()->get_settings_path().plus_file("templates"));
+ Error err = d->change_dir(EditorSettings::get_singleton()->get_templates_dir());
d->list_dir_begin();
Set<String> templates;
@@ -66,7 +67,7 @@ void ExportTemplateManager::_update_template_list() {
memdelete(d);
- String current_version = itos(VERSION_MAJOR) + "." + itos(VERSION_MINOR) + "-" + _MKSTR(VERSION_STATUS);
+ String current_version = itos(VERSION_MAJOR) + "." + itos(VERSION_MINOR) + "-" + VERSION_STATUS + VERSION_MODULE_CONFIG;
Label *current = memnew(Label);
current->set_h_size_flags(SIZE_EXPAND_FILL);
@@ -120,6 +121,16 @@ void ExportTemplateManager::_update_template_list() {
void ExportTemplateManager::_download_template(const String &p_version) {
print_line("download " + p_version);
+ while (template_list->get_child_count()) {
+ memdelete(template_list->get_child(0));
+ }
+ template_downloader->popup_centered_minsize();
+ template_list_state->set_text(TTR("Retrieving mirrors, please wait.."));
+ template_download_progress->set_max(100);
+ template_download_progress->set_value(0);
+ request_mirror->request("https://godotengine.org/mirrorlist/" + p_version + ".json");
+ template_list_state->show();
+ template_download_progress->show();
}
void ExportTemplateManager::_uninstall_template(const String &p_version) {
@@ -132,7 +143,7 @@ void ExportTemplateManager::_uninstall_template(const String &p_version) {
void ExportTemplateManager::_uninstall_template_confirm() {
DirAccess *d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- Error err = d->change_dir(EditorSettings::get_singleton()->get_settings_path().plus_file("templates"));
+ Error err = d->change_dir(EditorSettings::get_singleton()->get_templates_dir());
ERR_FAIL_COND(err != OK);
@@ -234,7 +245,7 @@ void ExportTemplateManager::_install_from_file(const String &p_file) {
return;
}
- String template_path = EditorSettings::get_singleton()->get_settings_path().plus_file("templates").plus_file(version);
+ String template_path = EditorSettings::get_singleton()->get_templates_dir().plus_file(version);
DirAccess *d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
Error err = d->make_dir_recursive(template_path);
@@ -307,12 +318,203 @@ void ExportTemplateManager::ok_pressed() {
template_open->popup_centered_ratio();
}
+void ExportTemplateManager::_http_download_mirror_completed(int p_status, int p_code, const PoolStringArray &headers, const PoolByteArray &p_data) {
+
+ if (p_status != HTTPRequest::RESULT_SUCCESS || p_code != 200) {
+ EditorNode::get_singleton()->show_warning("Error getting the list of mirrors.");
+ return;
+ }
+
+ String mirror_str;
+ {
+ PoolByteArray::Read r = p_data.read();
+ mirror_str.parse_utf8((const char *)r.ptr(), p_data.size());
+ }
+
+ template_list_state->hide();
+ template_download_progress->hide();
+
+ Variant r;
+ String errs;
+ int errline;
+ Error err = JSON::parse(mirror_str, r, errs, errline);
+ if (err != OK) {
+ EditorNode::get_singleton()->show_warning("Error parsing JSON of mirror list. Please report this issue!");
+ return;
+ }
+
+ bool mirrors_found = false;
+
+ Dictionary d = r;
+ print_line(r);
+ if (d.has("mirrors")) {
+ Array mirrors = d["mirrors"];
+ for (int i = 0; i < mirrors.size(); i++) {
+ Dictionary m = mirrors[i];
+ ERR_CONTINUE(!m.has("url") || !m.has("name"));
+ LinkButton *lb = memnew(LinkButton);
+ lb->set_text(m["name"]);
+ lb->connect("pressed", this, "_begin_template_download", varray(m["url"]));
+ template_list->add_child(lb);
+ mirrors_found = true;
+ }
+ }
+
+ if (!mirrors_found) {
+ EditorNode::get_singleton()->show_warning(TTR("No download links found for this version. Direct download is only available for official releases."));
+ return;
+ }
+}
+void ExportTemplateManager::_http_download_templates_completed(int p_status, int p_code, const PoolStringArray &headers, const PoolByteArray &p_data) {
+
+ switch (p_status) {
+
+ case HTTPRequest::RESULT_CANT_RESOLVE: {
+ template_list_state->set_text(TTR("Can't resolve."));
+ } break;
+ case HTTPRequest::RESULT_BODY_SIZE_LIMIT_EXCEEDED:
+ case HTTPRequest::RESULT_CONNECTION_ERROR:
+ case HTTPRequest::RESULT_CHUNKED_BODY_SIZE_MISMATCH: {
+ template_list_state->set_text(TTR("Can't connect."));
+ } break;
+ case HTTPRequest::RESULT_SSL_HANDSHAKE_ERROR:
+ case HTTPRequest::RESULT_CANT_CONNECT: {
+ template_list_state->set_text(TTR("Can't connect."));
+ } break;
+ case HTTPRequest::RESULT_NO_RESPONSE: {
+ template_list_state->set_text(TTR("No response."));
+ } break;
+ case HTTPRequest::RESULT_REQUEST_FAILED: {
+ template_list_state->set_text(TTR("Req. Failed."));
+ } break;
+ case HTTPRequest::RESULT_REDIRECT_LIMIT_REACHED: {
+ template_list_state->set_text(TTR("Redirect Loop."));
+ } break;
+ default: {
+ if (p_code != 200) {
+ template_list_state->set_text(TTR("Failed:") + " " + itos(p_code));
+ } else {
+ String path = EditorSettings::get_singleton()->get_cache_dir().plus_file("tmp_templates.tpz");
+ FileAccess *f = FileAccess::open(path, FileAccess::WRITE);
+ if (!f) {
+ template_list_state->set_text(TTR("Can't write file."));
+ } else {
+ int size = p_data.size();
+ PoolVector<uint8_t>::Read r = p_data.read();
+ f->store_buffer(r.ptr(), size);
+ memdelete(f);
+ template_list_state->set_text(TTR("Download Complete."));
+ template_downloader->hide();
+ _install_from_file(path);
+ }
+ }
+ } break;
+ }
+
+ set_process(false);
+}
+
+void ExportTemplateManager::_begin_template_download(const String &p_url) {
+
+ for (int i = 0; i < template_list->get_child_count(); i++) {
+ BaseButton *b = Object::cast_to<BaseButton>(template_list->get_child(0));
+ if (b) {
+ b->set_disabled(true);
+ }
+ }
+
+ download_data.clear();
+
+ Error err = download_templates->request(p_url);
+ if (err != OK) {
+ EditorNode::get_singleton()->show_warning(TTR("Error requesting url: ") + p_url);
+ return;
+ }
+
+ set_process(true);
+
+ template_list_state->show();
+ template_download_progress->set_max(100);
+ template_download_progress->set_value(0);
+ template_download_progress->show();
+ template_list_state->set_text(TTR("Connecting to Mirror.."));
+}
+
+void ExportTemplateManager::_notification(int p_what) {
+
+ if (p_what == NOTIFICATION_PROCESS) {
+
+ update_countdown -= get_process_delta_time();
+
+ if (update_countdown > 0) {
+ return;
+ }
+ update_countdown = 0.5;
+ String status;
+ bool errored = false;
+
+ switch (download_templates->get_http_client_status()) {
+ case HTTPClient::STATUS_DISCONNECTED:
+ status = TTR("Disconnected");
+ errored = true;
+ break;
+ case HTTPClient::STATUS_RESOLVING: status = TTR("Resolving"); break;
+ case HTTPClient::STATUS_CANT_RESOLVE:
+ status = TTR("Can't Resolve");
+ errored = true;
+ break;
+ case HTTPClient::STATUS_CONNECTING: status = TTR("Connecting.."); break;
+ case HTTPClient::STATUS_CANT_CONNECT:
+ status = TTR("Can't Conect");
+ errored = true;
+ break;
+ case HTTPClient::STATUS_CONNECTED: status = TTR("Connected"); break;
+ case HTTPClient::STATUS_REQUESTING: status = TTR("Requesting.."); break;
+ case HTTPClient::STATUS_BODY:
+ status = TTR("Downloading");
+ if (download_templates->get_body_size() > 0) {
+ status += " " + String::humanize_size(download_templates->get_downloaded_bytes()) + "/" + String::humanize_size(download_templates->get_body_size());
+ template_download_progress->set_max(download_templates->get_body_size());
+ template_download_progress->set_value(download_templates->get_downloaded_bytes());
+ } else {
+ status += " " + String::humanize_size(download_templates->get_downloaded_bytes());
+ }
+ break;
+ case HTTPClient::STATUS_CONNECTION_ERROR:
+ status = TTR("Connection Error");
+ errored = true;
+ break;
+ case HTTPClient::STATUS_SSL_HANDSHAKE_ERROR:
+ status = TTR("SSL Handshake Error");
+ errored = true;
+ break;
+ }
+
+ template_list_state->set_text(status);
+ if (errored) {
+ set_process(false);
+ ;
+ }
+ }
+
+ if (p_what == NOTIFICATION_VISIBILITY_CHANGED) {
+ if (!is_visible_in_tree()) {
+ print_line("closed");
+ download_templates->cancel_request();
+ set_process(false);
+ }
+ }
+}
+
void ExportTemplateManager::_bind_methods() {
ClassDB::bind_method("_download_template", &ExportTemplateManager::_download_template);
ClassDB::bind_method("_uninstall_template", &ExportTemplateManager::_uninstall_template);
ClassDB::bind_method("_uninstall_template_confirm", &ExportTemplateManager::_uninstall_template_confirm);
ClassDB::bind_method("_install_from_file", &ExportTemplateManager::_install_from_file);
+ ClassDB::bind_method("_http_download_mirror_completed", &ExportTemplateManager::_http_download_mirror_completed);
+ ClassDB::bind_method("_http_download_templates_completed", &ExportTemplateManager::_http_download_templates_completed);
+ ClassDB::bind_method("_begin_template_download", &ExportTemplateManager::_begin_template_download);
}
ExportTemplateManager::ExportTemplateManager() {
@@ -350,4 +552,33 @@ ExportTemplateManager::ExportTemplateManager() {
set_title(TTR("Export Template Manager"));
set_hide_on_ok(false);
+
+ request_mirror = memnew(HTTPRequest);
+ add_child(request_mirror);
+ request_mirror->connect("request_completed", this, "_http_download_mirror_completed");
+
+ download_templates = memnew(HTTPRequest);
+ add_child(download_templates);
+ download_templates->connect("request_completed", this, "_http_download_templates_completed");
+
+ template_downloader = memnew(AcceptDialog);
+ template_downloader->set_title(TTR("Download Templates"));
+ template_downloader->get_ok()->set_text(TTR("Close"));
+ add_child(template_downloader);
+
+ VBoxContainer *vbc = memnew(VBoxContainer);
+ template_downloader->add_child(vbc);
+ ScrollContainer *sc = memnew(ScrollContainer);
+ sc->set_custom_minimum_size(Size2(400, 200) * EDSCALE);
+ vbc->add_margin_child(TTR("Select mirror from list: "), sc);
+ template_list = memnew(VBoxContainer);
+ sc->add_child(template_list);
+ sc->set_enable_v_scroll(true);
+ sc->set_enable_h_scroll(false);
+ template_list_state = memnew(Label);
+ vbc->add_child(template_list_state);
+ template_download_progress = memnew(ProgressBar);
+ vbc->add_child(template_download_progress);
+
+ update_countdown = 0;
}
diff --git a/editor/export_template_manager.h b/editor/export_template_manager.h
index c77f85688f..644c6b466b 100644
--- a/editor/export_template_manager.h
+++ b/editor/export_template_manager.h
@@ -33,13 +33,20 @@
#include "editor/editor_settings.h"
#include "scene/gui/dialogs.h"
#include "scene/gui/file_dialog.h"
+#include "scene/gui/progress_bar.h"
#include "scene/gui/scroll_container.h"
+#include "scene/main/http_request.h"
class ExportTemplateVersion;
class ExportTemplateManager : public ConfirmationDialog {
GDCLASS(ExportTemplateManager, ConfirmationDialog)
+ AcceptDialog *template_downloader;
+ VBoxContainer *template_list;
+ Label *template_list_state;
+ ProgressBar *template_download_progress;
+
ScrollContainer *installed_scroll;
VBoxContainer *installed_vb;
HBoxContainer *current_hb;
@@ -48,6 +55,13 @@ class ExportTemplateManager : public ConfirmationDialog {
ConfirmationDialog *remove_confirm;
String to_remove;
+ HTTPRequest *request_mirror;
+ HTTPRequest *download_templates;
+
+ Vector<uint8_t> download_data;
+
+ float update_countdown;
+
void _update_template_list();
void _download_template(const String &p_version);
@@ -57,7 +71,13 @@ class ExportTemplateManager : public ConfirmationDialog {
virtual void ok_pressed();
void _install_from_file(const String &p_file);
+ void _http_download_mirror_completed(int p_status, int p_code, const PoolStringArray &headers, const PoolByteArray &p_data);
+ void _http_download_templates_completed(int p_status, int p_code, const PoolStringArray &headers, const PoolByteArray &p_data);
+
+ void _begin_template_download(const String &p_url);
+
protected:
+ void _notification(int p_what);
static void _bind_methods();
public:
diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp
index a9d72607b4..2ddfea00e3 100644
--- a/editor/filesystem_dock.cpp
+++ b/editor/filesystem_dock.cpp
@@ -38,16 +38,12 @@
#include "project_settings.h"
#include "scene/main/viewport.h"
-bool FileSystemDock::_create_tree(TreeItem *p_parent, EditorFileSystemDirectory *p_dir) {
+bool FileSystemDock::_create_tree(TreeItem *p_parent, EditorFileSystemDirectory *p_dir, Vector<String> &uncollapsed_paths) {
TreeItem *item = tree->create_item(p_parent);
String dname = p_dir->get_name();
if (dname == "")
dname = "res://";
- else {
- // collapse every tree item but the root folder
- item->set_collapsed(true);
- }
item->set_text(0, dname);
item->set_icon(0, get_icon("Folder", "EditorIcons"));
@@ -61,38 +57,78 @@ bool FileSystemDock::_create_tree(TreeItem *p_parent, EditorFileSystemDirectory
item->select(0);
}
+ if ((path.begins_with(lpath) && path != lpath)) {
+ item->set_collapsed(false);
+ } else {
+ bool is_collapsed = true;
+ for (int i = 0; i < uncollapsed_paths.size(); i++) {
+ if (lpath == uncollapsed_paths[i]) {
+ is_collapsed = false;
+ break;
+ }
+ }
+ item->set_collapsed(is_collapsed);
+ }
+
for (int i = 0; i < p_dir->get_subdir_count(); i++)
- _create_tree(item, p_dir->get_subdir(i));
+ _create_tree(item, p_dir->get_subdir(i), uncollapsed_paths);
return true;
}
-void FileSystemDock::_update_tree() {
+void FileSystemDock::_update_tree(bool keep_collapse_state) {
+
+ Vector<String> uncollapsed_paths;
+ if (keep_collapse_state) {
+ TreeItem *root = tree->get_root();
+ if (root) {
+ TreeItem *resTree = root->get_children()->get_next();
+
+ Vector<TreeItem *> needs_check;
+ needs_check.push_back(resTree);
+
+ while (needs_check.size()) {
+ if (!needs_check[0]->is_collapsed()) {
+ uncollapsed_paths.push_back(needs_check[0]->get_metadata(0));
+ TreeItem *child = needs_check[0]->get_children();
+ while (child) {
+ needs_check.push_back(child);
+ child = child->get_next();
+ }
+ }
+ needs_check.remove(0);
+ }
+ }
+ }
tree->clear();
updating_tree = true;
+
TreeItem *root = tree->create_item();
TreeItem *favorites = tree->create_item(root);
favorites->set_icon(0, get_icon("Favorites", "EditorIcons"));
favorites->set_text(0, TTR("Favorites:"));
favorites->set_selectable(0, false);
- Vector<String> faves = EditorSettings::get_singleton()->get_favorite_dirs();
- for (int i = 0; i < faves.size(); i++) {
- if (!faves[i].begins_with("res://"))
+
+ Vector<String> favorite_paths = EditorSettings::get_singleton()->get_favorite_dirs();
+ String res_path = "res://";
+ Ref<Texture> folder_icon = get_icon("Folder", "EditorIcons");
+ for (int i = 0; i < favorite_paths.size(); i++) {
+ String fave = favorite_paths[i];
+ if (!fave.begins_with(res_path))
continue;
TreeItem *ti = tree->create_item(favorites);
- String fv = faves[i];
- if (fv == "res://")
+ if (fave == res_path)
ti->set_text(0, "/");
else
- ti->set_text(0, faves[i].get_file());
- ti->set_icon(0, get_icon("Folder", "EditorIcons"));
+ ti->set_text(0, fave.get_file());
+ ti->set_icon(0, folder_icon);
ti->set_selectable(0, true);
- ti->set_metadata(0, faves[i]);
+ ti->set_metadata(0, fave);
}
- _create_tree(root, EditorFileSystem::get_singleton()->get_filesystem());
+ _create_tree(root, EditorFileSystem::get_singleton()->get_filesystem(), uncollapsed_paths);
updating_tree = false;
}
@@ -104,26 +140,28 @@ void FileSystemDock::_notification(int p_what) {
bool new_mode = get_size().height < get_viewport_rect().size.height / 2;
- if (new_mode != split_mode) {
+ if (new_mode != low_height_mode) {
- split_mode = new_mode;
+ low_height_mode = new_mode;
- //print_line("SPLIT MODE? "+itos(split_mode));
- if (split_mode) {
+ if (low_height_mode) {
file_list_vb->hide();
- tree->set_custom_minimum_size(Size2(0, 0));
tree->set_v_size_flags(SIZE_EXPAND_FILL);
- button_back->show();
+ button_tree->show();
} else {
- tree->show();
- file_list_vb->show();
- tree->set_custom_minimum_size(Size2(0, 200) * EDSCALE);
tree->set_v_size_flags(SIZE_FILL);
- button_back->hide();
- if (!EditorFileSystem::get_singleton()->is_scanning()) {
- _fs_changed();
+ if (!tree->is_visible()) {
+ tree->show();
+ button_favorite->show();
+ _update_tree(true);
+ }
+
+ if (!file_list_vb->is_visible()) {
+ file_list_vb->show();
+ button_tree->hide();
+ _update_files(true);
}
}
}
@@ -138,30 +176,32 @@ void FileSystemDock::_notification(int p_what) {
EditorFileSystem::get_singleton()->connect("filesystem_changed", this, "_fs_changed");
EditorResourcePreview::get_singleton()->connect("preview_invalidated", this, "_preview_invalidated");
- button_reload->set_icon(get_icon("Reload", "EditorIcons"));
- button_favorite->set_icon(get_icon("Favorites", "EditorIcons"));
- //button_instance->set_icon( get_icon("Add","EditorIcons"));
- //button_open->set_icon( get_icon("Folder","EditorIcons"));
- button_back->set_icon(get_icon("Filesystem", "EditorIcons"));
+ String ei = "EditorIcons";
+ button_reload->set_icon(get_icon("Reload", ei));
+ button_favorite->set_icon(get_icon("Favorites", ei));
+ //button_instance->set_icon(get_icon("Add", ei));
+ //button_open->set_icon(get_icon("Folder", ei));
+ button_tree->set_icon(get_icon("Filesystem", ei));
_update_file_display_toggle_button();
button_display_mode->connect("pressed", this, "_change_file_display");
- //file_options->set_icon( get_icon("Tools","EditorIcons"));
+ //file_options->set_icon( get_icon("Tools","ei"));
files->connect("item_activated", this, "_select_file");
button_hist_next->connect("pressed", this, "_fw_history");
button_hist_prev->connect("pressed", this, "_bw_history");
- search_box->add_icon_override("right_icon", get_icon("Search", "EditorIcons"));
+ search_box->add_icon_override("right_icon", get_icon("Search", ei));
- button_hist_next->set_icon(get_icon("Forward", "EditorIcons"));
- button_hist_prev->set_icon(get_icon("Back", "EditorIcons"));
+ button_hist_next->set_icon(get_icon("Forward", ei));
+ button_hist_prev->set_icon(get_icon("Back", ei));
file_options->connect("id_pressed", this, "_file_option");
folder_options->connect("id_pressed", this, "_folder_option");
- button_back->connect("pressed", this, "_go_to_tree", varray(), CONNECT_DEFERRED);
- current_path->connect("text_entered", this, "_go_to_dir");
- _update_tree(); //maybe it finished already
+ button_tree->connect("pressed", this, "_go_to_tree", varray(), CONNECT_DEFERRED);
+ current_path->connect("text_entered", this, "navigate_to_path");
if (EditorFileSystem::get_singleton()->is_scanning()) {
_set_scanning_mode();
+ } else {
+ _update_tree(false);
}
} break;
@@ -179,8 +219,7 @@ void FileSystemDock::_notification(int p_what) {
if (tree->is_visible_in_tree() && dd.has("type")) {
if ((String(dd["type"]) == "files") || (String(dd["type"]) == "files_and_dirs") || (String(dd["type"]) == "resource")) {
tree->set_drop_mode_flags(Tree::DROP_MODE_ON_ITEM);
- }
- if ((String(dd["type"]) == "favorite")) {
+ } else if ((String(dd["type"]) == "favorite")) {
tree->set_drop_mode_flags(Tree::DROP_MODE_INBETWEEN);
}
}
@@ -193,52 +232,54 @@ void FileSystemDock::_notification(int p_what) {
} break;
case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
+ String ei = "EditorIcons";
int new_mode = int(EditorSettings::get_singleton()->get("docks/filesystem/display_mode"));
//_update_icons
- button_reload->set_icon(get_icon("Reload", "EditorIcons"));
- button_favorite->set_icon(get_icon("Favorites", "EditorIcons"));
- button_back->set_icon(get_icon("Filesystem", "EditorIcons"));
- _update_file_display_toggle_button();
-
- search_box->add_icon_override("right_icon", get_icon("Search", "EditorIcons"));
+ button_reload->set_icon(get_icon("Reload", ei));
+ button_favorite->set_icon(get_icon("Favorites", ei));
+ button_tree->set_icon(get_icon("Filesystem", ei));
+ button_hist_next->set_icon(get_icon("Forward", ei));
+ button_hist_prev->set_icon(get_icon("Back", ei));
- button_hist_next->set_icon(get_icon("Forward", "EditorIcons"));
- button_hist_prev->set_icon(get_icon("Back", "EditorIcons"));
+ search_box->add_icon_override("right_icon", get_icon("Search", ei));
if (new_mode != display_mode) {
set_display_mode(new_mode);
} else {
+ _update_file_display_toggle_button();
_update_files(true);
}
- _update_tree();
-
+ _update_tree(true);
} break;
}
}
void FileSystemDock::_dir_selected() {
- TreeItem *ti = tree->get_selected();
- if (!ti)
+ TreeItem *sel = tree->get_selected();
+ if (!sel)
return;
- String dir = ti->get_metadata(0);
+ path = sel->get_metadata(0);
+
bool found = false;
Vector<String> favorites = EditorSettings::get_singleton()->get_favorite_dirs();
for (int i = 0; i < favorites.size(); i++) {
- if (favorites[i] == dir) {
+ if (favorites[i] == path) {
found = true;
break;
}
}
button_favorite->set_pressed(found);
+ current_path->set_text(path);
+ _push_to_history();
- if (!split_mode) {
- _open_pressed(); //go directly to dir
+ if (!low_height_mode) {
+ _update_files(false);
}
}
@@ -247,27 +288,25 @@ void FileSystemDock::_favorites_pressed() {
TreeItem *sel = tree->get_selected();
if (!sel)
return;
- String dir = sel->get_metadata(0);
+ path = sel->get_metadata(0);
int idx = -1;
Vector<String> favorites = EditorSettings::get_singleton()->get_favorite_dirs();
for (int i = 0; i < favorites.size(); i++) {
- if (favorites[i] == dir) {
+ if (favorites[i] == path) {
idx = i;
break;
}
}
- if (button_favorite->is_pressed() && idx == -1) {
- favorites.push_back(dir);
- EditorSettings::get_singleton()->set_favorite_dirs(favorites);
- _update_tree();
- } else if (!button_favorite->is_pressed() && idx != -1) {
+ if (idx == -1) {
+ favorites.push_back(path);
+ } else {
favorites.remove(idx);
- EditorSettings::get_singleton()->set_favorite_dirs(favorites);
- _update_tree();
}
+ EditorSettings::get_singleton()->set_favorite_dirs(favorites);
+ _update_tree(true);
}
String FileSystemDock::get_selected_path() const {
@@ -275,8 +314,8 @@ String FileSystemDock::get_selected_path() const {
TreeItem *sel = tree->get_selected();
if (!sel)
return "";
- String path = sel->get_metadata(0);
- return "res://" + path;
+
+ return sel->get_metadata(0);
}
String FileSystemDock::get_current_path() const {
@@ -286,27 +325,33 @@ String FileSystemDock::get_current_path() const {
void FileSystemDock::navigate_to_path(const String &p_path) {
// If the path is a file, do not only go to the directory in the tree, also select the file in the file list.
- String dir_path = "";
String file_name = "";
DirAccess *dirAccess = DirAccess::open("res://");
if (dirAccess->file_exists(p_path)) {
- dir_path = p_path.get_base_dir();
+ path = p_path.get_base_dir();
file_name = p_path.get_file();
} else if (dirAccess->dir_exists(p_path)) {
- dir_path = p_path;
+ path = p_path;
} else {
- ERR_EXPLAIN(TTR("Cannot navigate to '" + p_path + "' as it has not been found in the file system!"));
+ ERR_EXPLAIN(vformat(TTR("Cannot navigate to '%s' as it has not been found in the file system!"), p_path));
ERR_FAIL();
}
- path = dir_path;
- _update_tree();
- tree->ensure_cursor_is_visible();
+ current_path->set_text(path);
+ _push_to_history();
- if (!file_name.empty()) {
- _open_pressed(); // Seems to be the only way to get into the file view. This also pushes to history.
+ if (!low_height_mode) {
+ _update_tree(true);
+ _update_files(false);
+ } else {
+ if (file_name.empty()) {
+ _go_to_tree();
+ } else {
+ _go_to_file_list();
+ }
+ }
- // Focus the given file.
+ if (!file_name.empty()) {
for (int i = 0; i < files->get_item_count(); i++) {
if (files->get_item_text(i) == file_name) {
files->select(i, true);
@@ -319,27 +364,13 @@ void FileSystemDock::navigate_to_path(const String &p_path) {
void FileSystemDock::_thumbnail_done(const String &p_path, const Ref<Texture> &p_preview, const Variant &p_udata) {
- bool valid = false;
-
- if (search_box->is_visible()) {
- valid = true;
- } else {
- valid = (path == p_path.get_base_dir());
- }
-
- if (p_preview.is_valid() && valid) {
+ if ((file_list_vb->is_visible_in_tree() || path == p_path.get_base_dir()) && p_preview.is_valid()) {
Array uarr = p_udata;
int idx = uarr[0];
String file = uarr[1];
- if (idx >= files->get_item_count())
- return;
- if (files->get_item_text(idx) != file)
- return;
- String fpath = files->get_item_metadata(idx);
- if (fpath != p_path)
- return;
- files->set_item_icon(idx, p_preview);
+ if (idx < files->get_item_count() && files->get_item_text(idx) == file && files->get_item_metadata(idx) == p_path)
+ files->set_item_icon(idx, p_preview);
}
}
@@ -416,6 +447,7 @@ void FileSystemDock::_update_files(bool p_keep_selection) {
if (!efd)
return;
+ String ei = "EditorIcons";
int thumbnail_size = EditorSettings::get_singleton()->get("docks/filesystem/thumbnail_size");
thumbnail_size *= EDSCALE;
Ref<Texture> folder_thumbnail;
@@ -425,9 +457,9 @@ void FileSystemDock::_update_files(bool p_keep_selection) {
bool always_show_folders = EditorSettings::get_singleton()->get("docks/filesystem/always_show_folders");
bool use_thumbnails = (display_mode == DISPLAY_THUMBNAILS);
- bool use_folders = search_box->get_text().length() == 0 && (split_mode || always_show_folders);
+ bool use_folders = search_box->get_text().length() == 0 && (low_height_mode || always_show_folders);
- if (use_thumbnails) { //thumbnails
+ if (use_thumbnails) {
files->set_max_columns(0);
files->set_icon_mode(ItemList::ICON_MODE_TOP);
@@ -436,13 +468,13 @@ void FileSystemDock::_update_files(bool p_keep_selection) {
files->set_fixed_icon_size(Size2(thumbnail_size, thumbnail_size));
if (thumbnail_size < 64) {
- folder_thumbnail = get_icon("FolderMediumThumb", "EditorIcons");
- file_thumbnail = get_icon("FileMediumThumb", "EditorIcons");
- file_thumbnail_broken = get_icon("FileDeadMediumThumb", "EditorIcons");
+ folder_thumbnail = get_icon("FolderMediumThumb", ei);
+ file_thumbnail = get_icon("FileMediumThumb", ei);
+ file_thumbnail_broken = get_icon("FileDeadMediumThumb", ei);
} else {
- folder_thumbnail = get_icon("FolderBigThumb", "EditorIcons");
- file_thumbnail = get_icon("FileBigThumb", "EditorIcons");
- file_thumbnail_broken = get_icon("FileDeadBigThumb", "EditorIcons");
+ folder_thumbnail = get_icon("FolderBigThumb", ei);
+ file_thumbnail = get_icon("FileBigThumb", ei);
+ file_thumbnail_broken = get_icon("FileDeadBigThumb", ei);
}
} else {
@@ -454,14 +486,10 @@ void FileSystemDock::_update_files(bool p_keep_selection) {
}
if (use_folders) {
+ Ref<Texture> folderIcon = (use_thumbnails) ? folder_thumbnail : get_icon("folder", "FileDialog");
if (path != "res://") {
-
- if (use_thumbnails) {
- files->add_item("..", folder_thumbnail, true);
- } else {
- files->add_item("..", get_icon("folder", "FileDialog"), true);
- }
+ files->add_item("..", folderIcon, false);
String bd = path.get_base_dir();
if (bd != "res://" && !bd.ends_with("/"))
@@ -474,12 +502,7 @@ void FileSystemDock::_update_files(bool p_keep_selection) {
String dname = efd->get_subdir(i)->get_name();
- if (use_thumbnails) {
- files->add_item(dname, folder_thumbnail, true);
- } else {
- files->add_item(dname, get_icon("folder", "FileDialog"), true);
- }
-
+ files->add_item(dname, folderIcon, true);
files->set_item_metadata(files->get_item_count() - 1, path.plus_file(dname) + "/");
if (cselection.has(dname))
@@ -489,12 +512,9 @@ void FileSystemDock::_update_files(bool p_keep_selection) {
List<FileInfo> filelist;
- if (search_box->get_text().length()) {
-
- if (search_box->get_text().length() > 1) {
- _search(EditorFileSystem::get_singleton()->get_filesystem(), &filelist, 128);
- }
+ if (search_box->get_text().length() > 0) {
+ _search(EditorFileSystem::get_singleton()->get_filesystem(), &filelist, 128);
filelist.sort();
} else {
@@ -511,90 +531,93 @@ void FileSystemDock::_update_files(bool p_keep_selection) {
}
}
- StringName ei = "EditorIcons"; //make it faster..
- StringName oi = "Object";
+ String oi = "Object";
for (List<FileInfo>::Element *E = filelist.front(); E; E = E->next()) {
- String fname = E->get().name;
- String fp = E->get().path;
- StringName type = E->get().type;
+ FileInfo *finfo = &(E->get());
+ String fname = finfo->name;
+ String fpath = finfo->path;
+ String ftype = finfo->type;
Ref<Texture> type_icon;
- Ref<Texture> big_icon = file_thumbnail;
+ Ref<Texture> big_icon;
String tooltip = fname;
- if (!E->get().import_broken) {
-
- if (has_icon(type, ei)) {
- type_icon = get_icon(type, ei);
- } else {
- type_icon = get_icon(oi, ei);
- }
+ if (!finfo->import_broken) {
+ type_icon = (has_icon(ftype, ei)) ? get_icon(ftype, ei) : get_icon(oi, ei);
+ big_icon = file_thumbnail;
} else {
- type_icon = get_icon("ImportFail", "EditorIcons");
+ type_icon = get_icon("ImportFail", ei);
big_icon = file_thumbnail_broken;
tooltip += TTR("\nStatus: Import of file failed. Please fix file and reimport manually.");
}
- if (E->get().sources.size()) {
- for (int i = 0; i < E->get().sources.size(); i++) {
- tooltip += TTR("\nSource: ") + E->get().sources[i];
- }
- }
-
+ int item_index;
if (use_thumbnails) {
files->add_item(fname, big_icon, true);
- files->set_item_metadata(files->get_item_count() - 1, fp);
- files->set_item_tag_icon(files->get_item_count() - 1, type_icon);
- Array udata;
- udata.resize(2);
- udata[0] = files->get_item_count() - 1;
- udata[1] = fname;
- if (!E->get().import_broken) {
- EditorResourcePreview::get_singleton()->queue_resource_preview(fp, this, "_thumbnail_done", udata);
+ item_index = files->get_item_count() - 1;
+ files->set_item_metadata(item_index, fpath);
+ files->set_item_tag_icon(item_index, type_icon);
+ if (!finfo->import_broken) {
+ Array udata;
+ udata.resize(2);
+ udata[0] = item_index;
+ udata[1] = fname;
+ EditorResourcePreview::get_singleton()->queue_resource_preview(fpath, this, "_thumbnail_done", udata);
}
} else {
files->add_item(fname, type_icon, true);
- files->set_item_metadata(files->get_item_count() - 1, fp);
+ item_index = files->get_item_count() - 1;
+ files->set_item_metadata(item_index, fpath);
}
if (cselection.has(fname))
- files->select(files->get_item_count() - 1, false);
+ files->select(item_index, false);
- files->set_item_tooltip(files->get_item_count() - 1, tooltip);
+ if (finfo->sources.size()) {
+ for (int j = 0; j < finfo->sources.size(); j++) {
+ tooltip += "\nSource: " + finfo->sources[j];
+ }
+ }
+ files->set_item_tooltip(item_index, tooltip);
}
}
void FileSystemDock::_select_file(int p_idx) {
-
- files->select(p_idx, true);
- _file_option(FILE_OPEN);
+ String fpath = files->get_item_metadata(p_idx);
+ if (fpath.ends_with("/")) {
+ if (fpath != "res://") {
+ fpath = fpath.substr(0, fpath.length() - 1);
+ }
+ path = fpath;
+ _update_files(false);
+ current_path->set_text(path);
+ _push_to_history();
+ } else {
+ if (ResourceLoader::get_resource_type(fpath) == "PackedScene") {
+ editor->open_request(fpath);
+ } else {
+ editor->load_resource(fpath);
+ }
+ }
}
void FileSystemDock::_go_to_tree() {
- tree->show();
- file_list_vb->hide();
- _update_tree();
+ if (low_height_mode) {
+ tree->show();
+ button_favorite->show();
+ file_list_vb->hide();
+ }
+
+ _update_tree(true);
tree->grab_focus();
tree->ensure_cursor_is_visible();
- button_favorite->show();
//button_open->hide();
//file_options->hide();
}
-void FileSystemDock::_go_to_dir(const String &p_dir) {
-
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
- if (da->change_dir(p_dir) == OK) {
- path = da->get_current_dir();
- _update_files(false);
- }
- current_path->set_text(path);
- memdelete(da);
-}
-
void FileSystemDock::_preview_invalidated(const String &p_path) {
if (display_mode == DISPLAY_THUMBNAILS && p_path.get_base_dir() == path && search_box->get_text() == String() && file_list_vb->is_visible_in_tree()) {
@@ -617,17 +640,15 @@ void FileSystemDock::_preview_invalidated(const String &p_path) {
void FileSystemDock::_fs_changed() {
button_hist_prev->set_disabled(history_pos == 0);
- button_hist_next->set_disabled(history_pos + 1 == history.size());
+ button_hist_next->set_disabled(history_pos == history.size() - 1);
scanning_vb->hide();
split_box->show();
if (tree->is_visible()) {
- button_favorite->show();
- _update_tree();
+ _update_tree(true);
}
if (file_list_vb->is_visible()) {
-
_update_files(true);
}
@@ -636,9 +657,9 @@ void FileSystemDock::_fs_changed() {
void FileSystemDock::_set_scanning_mode() {
- split_box->hide();
button_hist_prev->set_disabled(true);
button_hist_next->set_disabled(true);
+ split_box->hide();
scanning_vb->show();
set_process(true);
if (EditorFileSystem::get_singleton()->is_scanning()) {
@@ -653,69 +674,63 @@ void FileSystemDock::_fw_history() {
if (history_pos < history.size() - 1)
history_pos++;
- path = history[history_pos];
-
- if (tree->is_visible()) {
- _update_tree();
- tree->grab_focus();
- tree->ensure_cursor_is_visible();
- }
-
- if (file_list_vb->is_visible()) {
- _update_files(false);
- current_path->set_text(path);
- }
-
- button_hist_prev->set_disabled(history_pos == 0);
- button_hist_next->set_disabled(history_pos + 1 == history.size());
+ _update_history();
}
void FileSystemDock::_bw_history() {
-
if (history_pos > 0)
history_pos--;
+ _update_history();
+}
+
+void FileSystemDock::_update_history() {
path = history[history_pos];
+ current_path->set_text(path);
if (tree->is_visible()) {
- _update_tree();
+ _update_tree(true);
tree->grab_focus();
tree->ensure_cursor_is_visible();
}
if (file_list_vb->is_visible()) {
_update_files(false);
- current_path->set_text(path);
}
button_hist_prev->set_disabled(history_pos == 0);
- button_hist_next->set_disabled(history_pos + 1 == history.size());
+ button_hist_next->set_disabled(history_pos == history.size() - 1);
}
void FileSystemDock::_push_to_history() {
-
- history.resize(history_pos + 1);
if (history[history_pos] != path) {
+ history.resize(history_pos + 1);
history.push_back(path);
history_pos++;
+
+ if (history.size() > history_max_size) {
+ history.remove(0);
+ history_pos = history_max_size - 1;
+ }
}
button_hist_prev->set_disabled(history_pos == 0);
- button_hist_next->set_disabled(history_pos + 1 == history.size());
+ button_hist_next->set_disabled(history_pos == history.size() - 1);
}
-void FileSystemDock::_find_inside_move_files(EditorFileSystemDirectory *efsd, Vector<String> &files) {
+void FileSystemDock::_get_all_files_in_dir(EditorFileSystemDirectory *efsd, Vector<String> &files) const {
+ if (efsd == NULL)
+ return;
for (int i = 0; i < efsd->get_subdir_count(); i++) {
- _find_inside_move_files(efsd->get_subdir(i), files);
+ _get_all_files_in_dir(efsd->get_subdir(i), files);
}
for (int i = 0; i < efsd->get_file_count(); i++) {
files.push_back(efsd->get_file_path(i));
}
}
-void FileSystemDock::_find_remaps(EditorFileSystemDirectory *efsd, Map<String, String> &renames, List<String> &to_remaps) {
-
+void FileSystemDock::_find_remaps(EditorFileSystemDirectory *efsd, const Map<String, String> &renames, Vector<String> &to_remaps) const {
for (int i = 0; i < efsd->get_subdir_count(); i++) {
_find_remaps(efsd->get_subdir(i), renames, to_remaps);
}
@@ -730,199 +745,157 @@ void FileSystemDock::_find_remaps(EditorFileSystemDirectory *efsd, Map<String, S
}
}
-void FileSystemDock::_rename_operation(const String &p_to_path) {
+void FileSystemDock::_try_move_item(const FileOrFolder &p_item, const String &p_new_path, Map<String, String> &p_renames) const {
+ //Ensure folder paths end with "/"
+ String old_path = (p_item.is_file || p_item.path.ends_with("/")) ? p_item.path : (p_item.path + "/");
+ String new_path = (p_item.is_file || p_new_path.ends_with("/")) ? p_new_path : (p_new_path + "/");
- if (move_files[0] == p_to_path) {
- EditorNode::get_singleton()->show_warning(TTR("Same source and destination files, doing nothing."));
+ if (new_path == old_path) {
return;
- }
- if (FileAccess::exists(p_to_path)) {
- EditorNode::get_singleton()->show_warning(TTR("Target file exists, can't overwrite. Delete first."));
+ } else if (old_path == "res://") {
+ EditorNode::get_singleton()->add_io_error(TTR("Cannot move/rename resources root."));
+ return;
+ } else if (!p_item.is_file && new_path.begins_with(old_path)) {
+ //This check doesn't erroneously catch renaming to a longer name as folder paths always end with "/"
+ EditorNode::get_singleton()->add_io_error(TTR("Cannot move a folder into itself.\n") + old_path + "\n");
return;
}
- Map<String, String> renames;
- renames[move_files[0]] = p_to_path;
-
- List<String> remap;
-
- _find_remaps(EditorFileSystem::get_singleton()->get_filesystem(), renames, remap);
- print_line("found files to remap: " + itos(remap.size()));
-
- //perform remaps
- for (List<String>::Element *E = remap.front(); E; E = E->next()) {
-
- Error err = ResourceLoader::rename_dependencies(E->get(), renames);
- print_line("remapping: " + E->get());
-
- if (err != OK) {
- EditorNode::get_singleton()->add_io_error("Can't rename deps for:\n" + E->get() + "\n");
- }
+ //Build a list of files which will have new paths as a result of this operation
+ Vector<String> changed_paths;
+ if (p_item.is_file) {
+ changed_paths.push_back(old_path);
+ } else {
+ _get_all_files_in_dir(EditorFileSystem::get_singleton()->get_filesystem_path(old_path), changed_paths);
}
- //finally, perform moves
-
DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ print_line("Moving " + old_path + " -> " + new_path);
+ Error err = da->rename(old_path, new_path);
+ if (err == OK) {
+ //Move/Rename any corresponding import settings too
+ if (p_item.is_file && FileAccess::exists(old_path + ".import")) {
+ err = da->rename(old_path + ".import", new_path + ".import");
+ if (err != OK) {
+ EditorNode::get_singleton()->add_io_error(TTR("Error moving:\n") + old_path + ".import\n");
+ }
+ }
- Error err = da->rename(move_files[0], p_to_path);
- print_line("moving file " + move_files[0] + " to " + p_to_path);
- if (err != OK) {
- EditorNode::get_singleton()->add_io_error("Error moving file:\n" + move_files[0] + "\n");
+ //Only treat as a changed dependency if it was successfully moved
+ for (int i = 0; i < changed_paths.size(); ++i) {
+ p_renames[changed_paths[i]] = changed_paths[i].replace_first(old_path, new_path);
+ print_line(" Remap: " + changed_paths[i] + " -> " + p_renames[changed_paths[i]]);
+ }
+ } else {
+ EditorNode::get_singleton()->add_io_error(TTR("Error moving:\n") + old_path + "\n");
}
-
- //rescan everything
memdelete(da);
- print_line("call rescan!");
- _rescan();
}
-void FileSystemDock::_move_operation(const String &p_to_path) {
-
- if (p_to_path == path) {
- EditorNode::get_singleton()->show_warning(TTR("Same source and destination paths, doing nothing."));
- return;
+void FileSystemDock::_update_dependencies_after_move(const Map<String, String> &p_renames) const {
+ //The following code assumes that the following holds:
+ // 1) EditorFileSystem contains the old paths/folder structure from before the rename/move.
+ // 2) ResourceLoader can use the new paths without needing to call rescan.
+ Vector<String> remaps;
+ _find_remaps(EditorFileSystem::get_singleton()->get_filesystem(), p_renames, remaps);
+ for (int i = 0; i < remaps.size(); ++i) {
+ //Because we haven't called a rescan yet the found remap might still be an old path itself.
+ String file = p_renames.has(remaps[i]) ? p_renames[remaps[i]] : remaps[i];
+ print_line("Remapping dependencies for: " + file);
+ Error err = ResourceLoader::rename_dependencies(file, p_renames);
+ if (err != OK) {
+ EditorNode::get_singleton()->add_io_error(TTR("Unable to update dependencies:\n") + remaps[i] + "\n");
+ }
}
+}
- //find files inside dirs to be moved
-
- Vector<String> inside_files;
-
- for (int i = 0; i < move_dirs.size(); i++) {
- if (p_to_path.begins_with(move_dirs[i])) {
- EditorNode::get_singleton()->show_warning(TTR("Can't move directories to within themselves."));
- return;
- }
+void FileSystemDock::_make_dir_confirm() {
+ String dir_name = make_dir_dialog_text->get_text().strip_edges();
- EditorFileSystemDirectory *efsd = EditorFileSystem::get_singleton()->get_filesystem_path(move_dirs[i]);
- if (!efsd)
- continue;
- _find_inside_move_files(efsd, inside_files);
+ if (dir_name.length() == 0) {
+ EditorNode::get_singleton()->show_warning(TTR("No name provided"));
+ return;
+ } else if (dir_name.find("/") != -1 || dir_name.find("\\") != -1 || dir_name.find(":") != -1) {
+ EditorNode::get_singleton()->show_warning(TTR("Provided name contains invalid characters"));
+ return;
}
- //make list of remaps
- Map<String, String> renames;
- String repfrom = path == "res://" ? path : String(path + "/");
- String repto = p_to_path;
- if (!repto.ends_with("/")) {
- repto += "/";
+ print_line("Making folder " + dir_name + " in " + path);
+ DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ Error err = da->change_dir(path);
+ if (err == OK) {
+ err = da->make_dir(dir_name);
}
+ memdelete(da);
- print_line("reprfrom: " + repfrom + " repto " + repto);
-
- for (int i = 0; i < move_files.size(); i++) {
- renames[move_files[i]] = move_files[i].replace_first(repfrom, repto);
- print_line("move file " + move_files[i] + " -> " + renames[move_files[i]]);
- }
- for (int i = 0; i < inside_files.size(); i++) {
- renames[inside_files[i]] = inside_files[i].replace_first(repfrom, repto);
- print_line("inside file " + inside_files[i] + " -> " + renames[inside_files[i]]);
+ if (err == OK) {
+ print_line("call rescan!");
+ _rescan();
+ } else {
+ EditorNode::get_singleton()->show_warning(TTR("Could not create folder."));
}
+}
- //make list of files that will be run the remapping
- List<String> remap;
-
- _find_remaps(EditorFileSystem::get_singleton()->get_filesystem(), renames, remap);
- print_line("found files to remap: " + itos(remap.size()));
-
- //perform remaps
- for (List<String>::Element *E = remap.front(); E; E = E->next()) {
-
- Error err = ResourceLoader::rename_dependencies(E->get(), renames);
- print_line("remapping: " + E->get());
+void FileSystemDock::_rename_operation_confirm() {
- if (err != OK) {
- EditorNode::get_singleton()->add_io_error(TTR("Can't rename deps for:\n") + E->get() + "\n");
- }
+ String new_name = rename_dialog_text->get_text().strip_edges();
+ if (new_name.length() == 0) {
+ EditorNode::get_singleton()->show_warning(TTR("No name provided."));
+ return;
+ } else if (new_name.find("/") != -1 || new_name.find("\\") != -1 || new_name.find(":") != -1) {
+ EditorNode::get_singleton()->show_warning(TTR("Name contains invalid characters."));
+ return;
}
- //finally, perform moves
+ String old_path = to_rename.path.ends_with("/") ? to_rename.path.substr(0, to_rename.path.length() - 1) : to_rename.path;
+ String new_path = old_path.get_base_dir().plus_file(new_name);
+ if (old_path == new_path) {
+ return;
+ }
+ //Present a more user friendly warning for name conflict
DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
-
- for (int i = 0; i < move_files.size(); i++) {
-
- String to = move_files[i].replace_first(repfrom, repto);
- Error err = da->rename(move_files[i], to);
- print_line("moving file " + move_files[i] + " to " + to);
- if (err != OK) {
- EditorNode::get_singleton()->add_io_error(TTR("Error moving file:\n") + move_files[i] + "\n");
- }
- if (FileAccess::exists(move_files[i] + ".import")) { //move imported files too
- //@todo should remove the files in .import folder
- err = da->rename(move_files[i] + ".import", to + ".import");
- if (err != OK) {
- EditorNode::get_singleton()->add_io_error(TTR("Error moving file:\n") + move_files[i] + ".import\n");
- }
- }
+ if (da->file_exists(new_path) || da->dir_exists(new_path)) {
+ EditorNode::get_singleton()->show_warning(TTR("A file or folder with this name already exists."));
+ memdelete(da);
+ return;
}
+ memdelete(da);
- for (int i = 0; i < move_dirs.size(); i++) {
+ Map<String, String> renames;
+ _try_move_item(to_rename, new_path, renames);
+ _update_dependencies_after_move(renames);
- String mdir = move_dirs[i];
- if (mdir == "res://")
- continue;
+ //Rescan everything
+ print_line("call rescan!");
+ _rescan();
+}
- if (mdir.ends_with("/")) {
- mdir = mdir.substr(0, mdir.length() - 1);
- }
+void FileSystemDock::_move_operation_confirm(const String &p_to_path) {
- String to = p_to_path.plus_file(mdir.get_file());
- Error err = da->rename(mdir, to);
- print_line("moving dir " + mdir + " to " + to);
- if (err != OK) {
- EditorNode::get_singleton()->add_io_error(TTR("Error moving dir:\n") + move_dirs[i] + "\n");
- }
+ Map<String, String> renames;
+ for (int i = 0; i < to_move.size(); i++) {
+ String old_path = to_move[i].path.ends_with("/") ? to_move[i].path.substr(0, to_move[i].path.length() - 1) : to_move[i].path;
+ String new_path = p_to_path.plus_file(old_path.get_file());
+ _try_move_item(to_move[i], new_path, renames);
}
- memdelete(da);
- //rescan everything
+ _update_dependencies_after_move(renames);
print_line("call rescan!");
_rescan();
}
void FileSystemDock::_file_option(int p_option) {
-
switch (p_option) {
-
- case FILE_SHOW_IN_EXPLORER:
+ case FILE_SHOW_IN_EXPLORER: {
+ String dir = ProjectSettings::get_singleton()->globalize_path(this->path);
+ OS::get_singleton()->shell_open(String("file://") + dir);
+ } break;
case FILE_OPEN: {
- int idx = -1;
- for (int i = 0; i < files->get_item_count(); i++) {
- if (files->is_selected(i)) {
- idx = i;
- break;
- }
- }
-
- if (idx < 0)
- return;
-
- String path = files->get_item_metadata(idx);
- if (p_option == FILE_SHOW_IN_EXPLORER) {
- String dir = ProjectSettings::get_singleton()->globalize_path(path);
- dir = dir.substr(0, dir.find_last("/"));
- OS::get_singleton()->shell_open(String("file://") + dir);
- return;
- }
-
- if (path.ends_with("/")) {
- if (path != "res://") {
- path = path.substr(0, path.length() - 1);
- }
- this->path = path;
- _update_files(false);
- current_path->set_text(path);
- _push_to_history();
- } else {
-
- if (ResourceLoader::get_resource_type(path) == "PackedScene") {
-
- editor->open_request(path);
- } else {
-
- editor->load_resource(path);
- }
- }
+ int idx = files->get_current();
+ if (idx < 0 || idx >= files->get_item_count())
+ break;
+ _select_file(idx);
} break;
case FILE_INSTANCE: {
@@ -931,9 +904,9 @@ void FileSystemDock::_file_option(int p_option) {
for (int i = 0; i < files->get_item_count(); i++) {
if (!files->is_selected(i))
continue;
- String path = files->get_item_metadata(i);
- if (EditorFileSystem::get_singleton()->get_file_type(path) == "PackedScene") {
- paths.push_back(path);
+ String fpath = files->get_item_metadata(i);
+ if (EditorFileSystem::get_singleton()->get_file_type(fpath) == "PackedScene") {
+ paths.push_back(fpath);
}
}
@@ -946,76 +919,71 @@ void FileSystemDock::_file_option(int p_option) {
int idx = files->get_current();
if (idx < 0 || idx >= files->get_item_count())
break;
- String path = files->get_item_metadata(idx);
- deps_editor->edit(path);
+ String fpath = files->get_item_metadata(idx);
+ deps_editor->edit(fpath);
} break;
case FILE_OWNERS: {
int idx = files->get_current();
if (idx < 0 || idx >= files->get_item_count())
break;
- String path = files->get_item_metadata(idx);
- owners_editor->show(path);
+ String fpath = files->get_item_metadata(idx);
+ owners_editor->show(fpath);
} break;
case FILE_MOVE: {
-
- move_dirs.clear();
- move_files.clear();
-
+ to_move.clear();
for (int i = 0; i < files->get_item_count(); i++) {
-
- String path = files->get_item_metadata(i);
if (!files->is_selected(i))
continue;
- if (files->get_item_text(i) == "..") {
- EditorNode::get_singleton()->show_warning(TTR("Can't operate on '..'"));
- return;
- }
-
- if (path.ends_with("/")) {
- move_dirs.push_back(path.substr(0, path.length() - 1));
- } else {
- move_files.push_back(path);
- }
+ String fpath = files->get_item_metadata(i);
+ to_move.push_back(FileOrFolder(fpath, !fpath.ends_with("/")));
}
-
- if (move_dirs.empty() && move_files.size() == 1) {
-
- rename_dialog->clear_filters();
- rename_dialog->add_filter("*." + move_files[0].get_extension());
- rename_dialog->set_mode(EditorFileDialog::MODE_SAVE_FILE);
- rename_dialog->set_current_path(move_files[0]);
- rename_dialog->popup_centered_ratio();
- rename_dialog->set_title(TTR("Pick New Name and Location For:") + " " + move_files[0].get_file());
-
- } else {
- //just move
+ if (to_move.size() > 0) {
move_dialog->popup_centered_ratio();
}
+ } break;
+ case FILE_RENAME: {
+ int idx = files->get_current();
+ if (idx < 0 || idx >= files->get_item_count())
+ break;
+ to_rename.path = files->get_item_metadata(idx);
+ to_rename.is_file = !to_rename.path.ends_with("/");
+ if (to_rename.is_file) {
+ String name = to_rename.path.get_file();
+ rename_dialog->set_title(TTR("Renaming file:") + " " + name);
+ rename_dialog_text->set_text(name);
+ rename_dialog_text->select(0, name.find_last("."));
+ } else {
+ String name = to_rename.path.substr(0, to_rename.path.length() - 1).get_file();
+ rename_dialog->set_title(TTR("Renaming folder:") + " " + name);
+ rename_dialog_text->set_text(name);
+ rename_dialog_text->select(0, name.length());
+ }
+ rename_dialog->popup_centered_minsize(Size2(250, 80) * EDSCALE);
+ rename_dialog_text->grab_focus();
} break;
case FILE_REMOVE: {
-
- Vector<String> torem;
+ Vector<String> remove_files;
+ Vector<String> remove_folders;
for (int i = 0; i < files->get_item_count(); i++) {
-
- String path = files->get_item_metadata(i);
- if (!files->is_selected(i))
- continue;
- torem.push_back(path);
+ String fpath = files->get_item_metadata(i);
+ if (files->is_selected(i) && fpath != "res://") {
+ if (fpath.ends_with("/")) {
+ remove_folders.push_back(fpath);
+ } else {
+ remove_files.push_back(fpath);
+ }
+ }
}
- if (torem.empty()) {
- EditorNode::get_singleton()->show_warning(TTR("No files selected!"));
- break;
+ if (remove_files.size() + remove_folders.size() > 0) {
+ remove_dialog->show(remove_folders, remove_files);
+ //1) find if used
+ //2) warn
}
-
- remove_dialog->show(torem);
- //1) find if used
- //2) warn
-
} break;
case FILE_INFO: {
@@ -1028,8 +996,8 @@ void FileSystemDock::_file_option(int p_option) {
if (!files->is_selected(i))
continue;
- String path = files->get_item_metadata(i);
- reimport.push_back(path);
+ String fpath = files->get_item_metadata(i);
+ reimport.push_back(fpath);
}
ERR_FAIL_COND(reimport.size() == 0);
@@ -1052,61 +1020,97 @@ void FileSystemDock::_file_option(int p_option) {
}
*/
-
} break;
- case FILE_COPY_PATH:
-
+ case FILE_NEW_FOLDER: {
+ make_dir_dialog_text->set_text("new folder");
+ make_dir_dialog_text->select_all();
+ make_dir_dialog->popup_centered_minsize(Size2(250, 80) * EDSCALE);
+ make_dir_dialog_text->grab_focus();
+ } break;
+ case FILE_COPY_PATH: {
int idx = files->get_current();
if (idx < 0 || idx >= files->get_item_count())
break;
- String path = files->get_item_metadata(idx);
- OS::get_singleton()->set_clipboard(path);
+ String fpath = files->get_item_metadata(idx);
+ OS::get_singleton()->set_clipboard(fpath);
+ } break;
}
}
void FileSystemDock::_folder_option(int p_option) {
- TreeItem *item = tree->get_selected();
- TreeItem *child = item->get_children();
+ TreeItem *selected = tree->get_selected();
switch (p_option) {
-
case FOLDER_EXPAND_ALL:
- item->set_collapsed(false);
- while (child) {
- child->set_collapsed(false);
- child = child->get_next();
- }
- break;
+ case FOLDER_COLLAPSE_ALL: {
+ bool is_collapsed = (p_option == FOLDER_COLLAPSE_ALL);
+ Vector<TreeItem *> needs_check;
+ needs_check.push_back(selected);
+
+ while (needs_check.size()) {
+ needs_check[0]->set_collapsed(is_collapsed);
+
+ TreeItem *child = needs_check[0]->get_children();
+ while (child) {
+ needs_check.push_back(child);
+ child = child->get_next();
+ }
- case FOLDER_COLLAPSE_ALL:
- while (child) {
- child->set_collapsed(true);
- child = child->get_next();
+ needs_check.remove(0);
}
- break;
- case FOLDER_SHOW_IN_EXPLORER:
- String path = item->get_metadata(tree->get_selected_column());
- String dir = ProjectSettings::get_singleton()->globalize_path(path);
+ } break;
+ case FOLDER_MOVE: {
+ to_move.clear();
+ String fpath = selected->get_metadata(tree->get_selected_column());
+ if (fpath != "res://") {
+ fpath = fpath.ends_with("/") ? fpath.substr(0, fpath.length() - 1) : fpath;
+ to_move.push_back(FileOrFolder(fpath, false));
+ move_dialog->popup_centered_ratio();
+ }
+ } break;
+ case FOLDER_RENAME: {
+ to_rename.path = selected->get_metadata(tree->get_selected_column());
+ to_rename.is_file = false;
+ if (to_rename.path != "res://") {
+ String name = to_rename.path.ends_with("/") ? to_rename.path.substr(0, to_rename.path.length() - 1).get_file() : to_rename.path.get_file();
+ rename_dialog->set_title(TTR("Renaming folder:") + " " + name);
+ rename_dialog_text->set_text(name);
+ rename_dialog_text->select(0, name.length());
+ rename_dialog->popup_centered_minsize(Size2(250, 80) * EDSCALE);
+ rename_dialog_text->grab_focus();
+ }
+ } break;
+ case FOLDER_REMOVE: {
+ Vector<String> remove_folders;
+ Vector<String> remove_files;
+ String fpath = selected->get_metadata(tree->get_selected_column());
+ if (fpath != "res://") {
+ remove_folders.push_back(fpath);
+ remove_dialog->show(remove_folders, remove_files);
+ }
+ } break;
+ case FOLDER_NEW_FOLDER: {
+ make_dir_dialog_text->set_text("new folder");
+ make_dir_dialog_text->select_all();
+ make_dir_dialog->popup_centered_minsize(Size2(250, 80) * EDSCALE);
+ make_dir_dialog_text->grab_focus();
+ } break;
+ case FOLDER_COPY_PATH: {
+ String fpath = selected->get_metadata(tree->get_selected_column());
+ OS::get_singleton()->set_clipboard(fpath);
+ } break;
+ case FOLDER_SHOW_IN_EXPLORER: {
+ String fpath = selected->get_metadata(tree->get_selected_column());
+ String dir = ProjectSettings::get_singleton()->globalize_path(fpath);
OS::get_singleton()->shell_open(String("file://") + dir);
- return;
+ } break;
}
}
-void FileSystemDock::_open_pressed() {
-
- TreeItem *sel = tree->get_selected();
- if (!sel) {
- return;
- }
- path = sel->get_metadata(0);
- /*if (path!="res://" && path.ends_with("/")) {
- path=path.substr(0,path.length()-1);
- }*/
-
- //tree_mode=false;
+void FileSystemDock::_go_to_file_list() {
- if (split_mode) {
+ if (low_height_mode) {
tree->hide();
file_list_vb->show();
button_favorite->hide();
@@ -1115,8 +1119,6 @@ void FileSystemDock::_open_pressed() {
//file_options->show();
_update_files(false);
- current_path->set_text(path);
- _push_to_history();
//emit_signal("open",path);
}
@@ -1128,19 +1130,28 @@ void FileSystemDock::_dir_rmb_pressed(const Vector2 &p_pos) {
folder_options->add_item(TTR("Expand all"), FOLDER_EXPAND_ALL);
folder_options->add_item(TTR("Collapse all"), FOLDER_COLLAPSE_ALL);
- folder_options->add_separator();
- folder_options->add_item(TTR("Show In File Manager"), FOLDER_SHOW_IN_EXPLORER);
-
+ TreeItem *item = tree->get_selected();
+ if (item) {
+ String fpath = item->get_metadata(tree->get_selected_column());
+ folder_options->add_separator();
+ folder_options->add_item(TTR("Copy Path"), FOLDER_COPY_PATH);
+ if (fpath != "res://") {
+ folder_options->add_item(TTR("Rename.."), FOLDER_RENAME);
+ folder_options->add_item(TTR("Move To.."), FOLDER_MOVE);
+ folder_options->add_item(TTR("Delete"), FOLDER_REMOVE);
+ }
+ folder_options->add_separator();
+ folder_options->add_item(TTR("New Folder.."), FOLDER_NEW_FOLDER);
+ folder_options->add_item(TTR("Show In File Manager"), FOLDER_SHOW_IN_EXPLORER);
+ }
folder_options->set_position(tree->get_global_position() + p_pos);
folder_options->popup();
}
void FileSystemDock::_search_changed(const String &p_text) {
- if (!search_box->is_visible_in_tree())
- return; //wtf
-
- _update_files(false);
+ if (file_list_vb->is_visible())
+ _update_files(false);
}
void FileSystemDock::_rescan() {
@@ -1155,7 +1166,7 @@ void FileSystemDock::fix_dependencies(const String &p_for_file) {
void FileSystemDock::focus_on_filter() {
- if (!search_box->is_visible_in_tree()) {
+ if (low_height_mode && tree->is_visible()) {
// Tree mode, switch to files list with search box
tree->hide();
file_list_vb->show();
@@ -1175,80 +1186,36 @@ void FileSystemDock::set_display_mode(int p_mode) {
}
Variant FileSystemDock::get_drag_data_fw(const Point2 &p_point, Control *p_from) {
+ bool is_favorite = false;
+ Vector<String> paths;
if (p_from == tree) {
-
TreeItem *selected = tree->get_selected();
if (!selected)
return Variant();
- String path = selected->get_metadata(0);
- if (path == String())
+ String folder = selected->get_metadata(0);
+ if (folder == String())
return Variant();
- if (!path.ends_with("/"))
- path = path + "/";
- Vector<String> paths;
- paths.push_back(path);
- Dictionary d = EditorNode::get_singleton()->drag_files(paths, p_from);
-
- if (selected->get_parent() && tree->get_root()->get_children() == selected->get_parent()) {
- //a favorite.. treat as such
- d["type"] = "favorite";
- }
-
- return d;
- }
-
- if (p_from == files) {
-
- List<int> seldirs;
- List<int> selfiles;
+ paths.push_back(folder.ends_with("/") ? folder : (folder + "/"));
+ is_favorite = selected->get_parent() != NULL && tree->get_root()->get_children() == selected->get_parent();
+ } else if (p_from == files) {
for (int i = 0; i < files->get_item_count(); i++) {
if (files->is_selected(i)) {
- String path = files->get_item_metadata(i);
- if (path.ends_with("/"))
- seldirs.push_back(i);
- else
- selfiles.push_back(i);
+ paths.push_back(files->get_item_metadata(i));
}
}
+ }
- if (seldirs.empty() && selfiles.empty())
- return Variant();
- /*
- if (seldirs.size() && selfiles.size())
- return Variant(); //can't really mix files and dirs (i think?) - yes you can, commenting
- */
-
- /*if (selfiles.size()==1) {
- Ref<Resource> resource = ResourceLoader::load(files->get_item_metadata(selfiles.front()->get()));
- if (resource.is_valid()) {
- return EditorNode::get_singleton()->drag_resource(resource,p_from);
- }
- }*/
-
- if (selfiles.size() > 0 && seldirs.size() == 0) {
- Vector<String> fnames;
- for (List<int>::Element *E = selfiles.front(); E; E = E->next()) {
- fnames.push_back(files->get_item_metadata(E->get()));
- }
- return EditorNode::get_singleton()->drag_files(fnames, p_from);
- }
+ if (paths.empty())
+ return Variant();
- if (selfiles.size() > 0 || seldirs.size() > 0) {
- Vector<String> fnames;
- for (List<int>::Element *E = selfiles.front(); E; E = E->next()) {
- fnames.push_back(files->get_item_metadata(E->get()));
- }
- for (List<int>::Element *E = seldirs.front(); E; E = E->next()) {
- fnames.push_back(files->get_item_metadata(E->get()));
- }
- return EditorNode::get_singleton()->drag_files_and_dirs(fnames, p_from);
- }
+ Dictionary drag_data = EditorNode::get_singleton()->drag_files_and_dirs(paths, p_from);
+ if (is_favorite) {
+ drag_data["type"] = "favorite";
}
-
- return Variant();
+ return drag_data;
}
bool FileSystemDock::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const {
@@ -1279,36 +1246,25 @@ bool FileSystemDock::can_drop_data_fw(const Point2 &p_point, const Variant &p_da
}
if (drag_data.has("type") && String(drag_data["type"]) == "resource") {
- return true;
+ String to_dir = _get_drag_target_folder(p_point, p_from);
+ return !to_dir.empty();
}
if (drag_data.has("type") && (String(drag_data["type"]) == "files" || String(drag_data["type"]) == "files_and_dirs")) {
+ String to_dir = _get_drag_target_folder(p_point, p_from);
+ if (to_dir.empty())
+ return false;
+ //Attempting to move a folder into itself will fail later
+ //Rather than bring up a message don't try to do it in the first place
+ to_dir = to_dir.ends_with("/") ? to_dir : (to_dir + "/");
Vector<String> fnames = drag_data["files"];
-
- if (p_from == files) {
-
- int at_pos = files->get_item_at_position(p_point);
- if (at_pos != -1) {
-
- String dir = files->get_item_metadata(at_pos);
- if (dir.ends_with("/"))
- return true;
- }
- }
-
- if (p_from == tree) {
-
- TreeItem *ti = tree->get_item_at_position(p_point);
- if (!ti)
- return false;
- String path = ti->get_metadata(0);
-
- if (path == String())
+ for (int i = 0; i < fnames.size(); ++i) {
+ if (fnames[i].ends_with("/") && to_dir.begins_with(fnames[i]))
return false;
-
- return true;
}
+
+ return true;
}
return false;
@@ -1378,207 +1334,151 @@ void FileSystemDock::drop_data_fw(const Point2 &p_point, const Variant &p_data,
}
EditorSettings::get_singleton()->set_favorite_dirs(dirs);
- _update_tree();
+ _update_tree(true);
return;
}
if (drag_data.has("type") && String(drag_data["type"]) == "resource") {
Ref<Resource> res = drag_data["resource"];
-
- if (!res.is_valid()) {
- return;
- }
-
- if (p_from == tree) {
-
- TreeItem *ti = tree->get_item_at_position(p_point);
- if (!ti)
- return;
- String path = ti->get_metadata(0);
-
- if (path == String())
- return;
-
- EditorNode::get_singleton()->save_resource_as(res, path);
- return;
- }
-
- if (p_from == files) {
- String save_path = path;
-
- int at_pos = files->get_item_at_position(p_point);
- if (at_pos != -1) {
- String to_dir = files->get_item_metadata(at_pos);
- if (to_dir.ends_with("/")) {
- save_path = to_dir;
- if (save_path != "res://")
- save_path = save_path.substr(0, save_path.length() - 1);
- }
- }
-
- EditorNode::get_singleton()->save_resource_as(res, save_path);
- return;
+ String to_dir = _get_drag_target_folder(p_point, p_from);
+ if (res.is_valid() && !to_dir.empty()) {
+ EditorNode::get_singleton()->push_item(res.ptr());
+ EditorNode::get_singleton()->save_resource_as(res, to_dir);
}
}
if (drag_data.has("type") && (String(drag_data["type"]) == "files" || String(drag_data["type"]) == "files_and_dirs")) {
-
- if (p_from == files || p_from == tree) {
-
- String to_dir;
-
- if (p_from == files) {
-
- int at_pos = files->get_item_at_position(p_point);
- ERR_FAIL_COND(at_pos == -1);
- to_dir = files->get_item_metadata(at_pos);
- } else {
- TreeItem *ti = tree->get_item_at_position(p_point);
- if (!ti)
- return;
- to_dir = ti->get_metadata(0);
- ERR_FAIL_COND(to_dir == String());
- }
-
- if (to_dir != "res://" && to_dir.ends_with("/")) {
- to_dir = to_dir.substr(0, to_dir.length() - 1);
- }
-
+ String to_dir = _get_drag_target_folder(p_point, p_from);
+ if (!to_dir.empty()) {
Vector<String> fnames = drag_data["files"];
- move_files.clear();
- move_dirs.clear();
-
+ to_move.clear();
for (int i = 0; i < fnames.size(); i++) {
- if (fnames[i].ends_with("/"))
- move_dirs.push_back(fnames[i]);
- else
- move_files.push_back(fnames[i]);
+ to_move.push_back(FileOrFolder(fnames[i], !fnames[i].ends_with("/")));
}
-
- _move_operation(to_dir);
+ _move_operation_confirm(to_dir);
}
}
}
-void FileSystemDock::_files_list_rmb_select(int p_item, const Vector2 &p_pos) {
-
- Vector<String> filenames;
-
- bool all_scenes = true;
- bool all_can_reimport = true;
- bool is_dir = false;
- Set<String> types;
+String FileSystemDock::_get_drag_target_folder(const Point2 &p_point, Control *p_from) const {
+ if (p_from == files) {
+ int pos = files->get_item_at_position(p_point, true);
+ if (pos == -1)
+ return path;
- for (int i = 0; i < files->get_item_count(); i++) {
+ String target = files->get_item_metadata(pos);
+ return target.ends_with("/") ? target : path;
+ }
- if (!files->is_selected(i))
- continue;
+ if (p_from == tree) {
+ TreeItem *ti = tree->get_item_at_position(p_point);
+ if (ti && ti != tree->get_root()->get_children())
+ return ti->get_metadata(0);
+ }
- String path = files->get_item_metadata(i);
+ return String();
+}
- if (files->get_item_text(i) == "..") {
- // no operate on ..
- return;
- }
+void FileSystemDock::_files_list_rmb_select(int p_item, const Vector2 &p_pos) {
- if (path.ends_with("/")) {
- is_dir = true;
+ //Right clicking ".." should clear current selection
+ if (files->get_item_text(p_item) == "..") {
+ for (int i = 0; i < files->get_item_count(); i++) {
+ files->unselect(i);
}
+ }
- int pos;
-
- EditorFileSystemDirectory *efsd = EditorFileSystem::get_singleton()->find_file(path, &pos);
+ Vector<String> filenames;
+ Vector<String> foldernames;
- if (efsd) {
+ bool all_files = true;
+ bool all_files_scenes = true;
+ bool all_folders = true;
+ for (int i = 0; i < files->get_item_count(); i++) {
+ if (!files->is_selected(i)) {
+ continue;
+ }
+ String fpath = files->get_item_metadata(i);
+ if (fpath.ends_with("/")) {
+ foldernames.push_back(fpath);
+ all_files = false;
} else {
- all_can_reimport = false;
+ filenames.push_back(fpath);
+ all_folders = false;
+ all_files_scenes &= (EditorFileSystem::get_singleton()->get_file_type(fpath) == "PackedScene");
}
-
- filenames.push_back(path);
- if (EditorFileSystem::get_singleton()->get_file_type(path) != "PackedScene")
- all_scenes = false;
}
- if (filenames.size() == 0)
- return;
-
file_options->clear();
file_options->set_size(Size2(1, 1));
+ if (all_files && filenames.size() > 0) {
+ file_options->add_item(TTR("Open"), FILE_OPEN);
+ if (all_files_scenes) {
+ file_options->add_item(TTR("Instance"), FILE_INSTANCE);
+ }
+ file_options->add_separator();
- file_options->add_item(TTR("Open"), FILE_OPEN);
- if (all_scenes) {
- file_options->add_item(TTR("Instance"), FILE_INSTANCE);
- }
-
- file_options->add_separator();
-
- if (filenames.size() == 1 && !is_dir) {
- file_options->add_item(TTR("Edit Dependencies.."), FILE_DEPENDENCIES);
- file_options->add_item(TTR("View Owners.."), FILE_OWNERS);
+ if (filenames.size() == 1) {
+ file_options->add_item(TTR("Edit Dependencies.."), FILE_DEPENDENCIES);
+ file_options->add_item(TTR("View Owners.."), FILE_OWNERS);
+ file_options->add_separator();
+ }
+ } else if (all_folders && foldernames.size() > 0) {
+ file_options->add_item(TTR("Open"), FILE_OPEN);
file_options->add_separator();
}
- if (!is_dir) {
- if (filenames.size() == 1) {
+ int num_items = filenames.size() + foldernames.size();
+ if (num_items >= 1) {
+ if (num_items == 1) {
file_options->add_item(TTR("Copy Path"), FILE_COPY_PATH);
- file_options->add_item(TTR("Rename or Move.."), FILE_MOVE);
- } else {
- file_options->add_item(TTR("Move To.."), FILE_MOVE);
+ file_options->add_item(TTR("Rename.."), FILE_RENAME);
}
+ file_options->add_item(TTR("Move To.."), FILE_MOVE);
+ file_options->add_item(TTR("Delete"), FILE_REMOVE);
+ file_options->add_separator();
}
- file_options->add_item(TTR("Delete"), FILE_REMOVE);
-
- //file_options->add_item(TTR("Info"),FILE_INFO);
-
- file_options->add_separator();
+ file_options->add_item(TTR("New Folder.."), FILE_NEW_FOLDER);
file_options->add_item(TTR("Show In File Manager"), FILE_SHOW_IN_EXPLORER);
- if (all_can_reimport && types.size() == 1) { //all can reimport and are of the same type
-
- /*
- bool valid=true;
- Ref<EditorImportPlugin> rimp = EditorImportExport::get_singleton()->get_import_plugin_by_name(types.front()->get());
- if (rimp.is_valid()) {
-
- if (filenames.size()>1 && !rimp->can_reimport_multiple_files()) {
- valid=false;
- }
- } else {
- valid=false;
- }
+ file_options->set_position(files->get_global_position() + p_pos);
+ file_options->popup();
+}
- if (valid) {
- file_options->add_separator();
- file_options->add_item(TTR("Re-Import.."),FILE_REIMPORT);
- }
- */
- }
+void FileSystemDock::_rmb_pressed(const Vector2 &p_pos) {
+ file_options->clear();
+ file_options->set_size(Size2(1, 1));
+ file_options->add_item(TTR("New Folder.."), FILE_NEW_FOLDER);
+ file_options->add_item(TTR("Show In File Manager"), FILE_SHOW_IN_EXPLORER);
file_options->set_position(files->get_global_position() + p_pos);
file_options->popup();
}
void FileSystemDock::select_file(const String &p_file) {
- _go_to_dir(p_file.get_base_dir());
- for (int i = 0; i < files->get_item_count(); i++) {
- if (files->get_item_metadata(i) == p_file) {
- files->select(i);
- files->ensure_current_is_visible();
- break;
- }
- }
+ navigate_to_path(p_file);
}
void FileSystemDock::_file_multi_selected(int p_index, bool p_selected) {
- _file_selected();
+ import_dock_needs_update = true;
+ call_deferred("_update_import_dock");
}
void FileSystemDock::_file_selected() {
+ import_dock_needs_update = true;
+ _update_import_dock();
+}
+
+void FileSystemDock::_update_import_dock() {
+
+ if (!import_dock_needs_update)
+ return;
+
//check import
Vector<String> imports;
String import_type;
@@ -1587,14 +1487,14 @@ void FileSystemDock::_file_selected() {
if (!files->is_selected(i))
continue;
- String p = files->get_item_metadata(i);
- if (!FileAccess::exists(p + ".import")) {
+ String fpath = files->get_item_metadata(i);
+ if (!FileAccess::exists(fpath + ".import")) {
imports.clear();
break;
}
Ref<ConfigFile> cf;
cf.instance();
- Error err = cf->load(p + ".import");
+ Error err = cf->load(fpath + ".import");
if (err != OK) {
imports.clear();
break;
@@ -1608,7 +1508,7 @@ void FileSystemDock::_file_selected() {
imports.clear();
break;
}
- imports.push_back(p);
+ imports.push_back(fpath);
}
if (imports.size() == 0) {
@@ -1618,6 +1518,8 @@ void FileSystemDock::_file_selected() {
} else {
EditorNode::get_singleton()->get_import_dock()->set_edit_multiple_paths(imports);
}
+
+ import_dock_needs_update = false;
}
void FileSystemDock::_bind_methods() {
@@ -1626,13 +1528,13 @@ void FileSystemDock::_bind_methods() {
ClassDB::bind_method(D_METHOD("_rescan"), &FileSystemDock::_rescan);
ClassDB::bind_method(D_METHOD("_favorites_pressed"), &FileSystemDock::_favorites_pressed);
//ClassDB::bind_method(D_METHOD("_instance_pressed"),&ScenesDock::_instance_pressed);
- ClassDB::bind_method(D_METHOD("_open_pressed"), &FileSystemDock::_open_pressed);
+ ClassDB::bind_method(D_METHOD("_go_to_file_list"), &FileSystemDock::_go_to_file_list);
ClassDB::bind_method(D_METHOD("_dir_rmb_pressed"), &FileSystemDock::_dir_rmb_pressed);
ClassDB::bind_method(D_METHOD("_thumbnail_done"), &FileSystemDock::_thumbnail_done);
ClassDB::bind_method(D_METHOD("_select_file"), &FileSystemDock::_select_file);
ClassDB::bind_method(D_METHOD("_go_to_tree"), &FileSystemDock::_go_to_tree);
- ClassDB::bind_method(D_METHOD("_go_to_dir"), &FileSystemDock::_go_to_dir);
+ ClassDB::bind_method(D_METHOD("navigate_to_path"), &FileSystemDock::navigate_to_path);
ClassDB::bind_method(D_METHOD("_change_file_display"), &FileSystemDock::_change_file_display);
ClassDB::bind_method(D_METHOD("_fw_history"), &FileSystemDock::_fw_history);
ClassDB::bind_method(D_METHOD("_bw_history"), &FileSystemDock::_bw_history);
@@ -1640,8 +1542,9 @@ void FileSystemDock::_bind_methods() {
ClassDB::bind_method(D_METHOD("_dir_selected"), &FileSystemDock::_dir_selected);
ClassDB::bind_method(D_METHOD("_file_option"), &FileSystemDock::_file_option);
ClassDB::bind_method(D_METHOD("_folder_option"), &FileSystemDock::_folder_option);
- ClassDB::bind_method(D_METHOD("_move_operation"), &FileSystemDock::_move_operation);
- ClassDB::bind_method(D_METHOD("_rename_operation"), &FileSystemDock::_rename_operation);
+ ClassDB::bind_method(D_METHOD("_make_dir_confirm"), &FileSystemDock::_make_dir_confirm);
+ ClassDB::bind_method(D_METHOD("_move_operation_confirm"), &FileSystemDock::_move_operation_confirm);
+ ClassDB::bind_method(D_METHOD("_rename_operation_confirm"), &FileSystemDock::_rename_operation_confirm);
ClassDB::bind_method(D_METHOD("_search_changed"), &FileSystemDock::_search_changed);
@@ -1653,6 +1556,8 @@ void FileSystemDock::_bind_methods() {
ClassDB::bind_method(D_METHOD("_preview_invalidated"), &FileSystemDock::_preview_invalidated);
ClassDB::bind_method(D_METHOD("_file_selected"), &FileSystemDock::_file_selected);
ClassDB::bind_method(D_METHOD("_file_multi_selected"), &FileSystemDock::_file_multi_selected);
+ ClassDB::bind_method(D_METHOD("_update_import_dock"), &FileSystemDock::_update_import_dock);
+ ClassDB::bind_method(D_METHOD("_rmb_pressed"), &FileSystemDock::_rmb_pressed);
ADD_SIGNAL(MethodInfo("instance", PropertyInfo(Variant::POOL_STRING_ARRAY, "files")));
ADD_SIGNAL(MethodInfo("open"));
@@ -1661,21 +1566,22 @@ void FileSystemDock::_bind_methods() {
FileSystemDock::FileSystemDock(EditorNode *p_editor) {
editor = p_editor;
+ path = "res://";
HBoxContainer *toolbar_hbc = memnew(HBoxContainer);
add_child(toolbar_hbc);
button_hist_prev = memnew(ToolButton);
- toolbar_hbc->add_child(button_hist_prev);
button_hist_prev->set_disabled(true);
+ button_hist_prev->set_focus_mode(FOCUS_NONE);
button_hist_prev->set_tooltip(TTR("Previous Directory"));
+ toolbar_hbc->add_child(button_hist_prev);
button_hist_next = memnew(ToolButton);
- toolbar_hbc->add_child(button_hist_next);
button_hist_next->set_disabled(true);
- button_hist_prev->set_focus_mode(FOCUS_NONE);
button_hist_next->set_focus_mode(FOCUS_NONE);
button_hist_next->set_tooltip(TTR("Next Directory"));
+ toolbar_hbc->add_child(button_hist_next);
current_path = memnew(LineEdit);
current_path->set_h_size_flags(SIZE_EXPAND_FILL);
@@ -1684,10 +1590,10 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) {
button_reload = memnew(Button);
button_reload->set_flat(true);
button_reload->connect("pressed", this, "_rescan");
- toolbar_hbc->add_child(button_reload);
button_reload->set_focus_mode(FOCUS_NONE);
button_reload->set_tooltip(TTR("Re-Scan Filesystem"));
button_reload->hide();
+ toolbar_hbc->add_child(button_reload);
//toolbar_hbc->add_spacer();
@@ -1695,17 +1601,16 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) {
button_favorite->set_flat(true);
button_favorite->set_toggle_mode(true);
button_favorite->connect("pressed", this, "_favorites_pressed");
- toolbar_hbc->add_child(button_favorite);
button_favorite->set_tooltip(TTR("Toggle folder status as Favorite"));
-
button_favorite->set_focus_mode(FOCUS_NONE);
+ toolbar_hbc->add_child(button_favorite);
//Control *spacer = memnew( Control);
/*
button_open = memnew( Button );
button_open->set_flat(true);
- button_open->connect("pressed",this,"_open_pressed");
+ button_open->connect("pressed",this,"_go_to_file_list");
toolbar_hbc->add_child(button_open);
button_open->hide();
button_open->set_focus_mode(FOCUS_NONE);
@@ -1728,92 +1633,111 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) {
add_child(folder_options);
split_box = memnew(VSplitContainer);
- add_child(split_box);
split_box->set_v_size_flags(SIZE_EXPAND_FILL);
+ add_child(split_box);
tree = memnew(Tree);
tree->set_hide_root(true);
- split_box->add_child(tree);
tree->set_drag_forwarding(this);
tree->set_allow_rmb_select(true);
+ tree->set_custom_minimum_size(Size2(0, 200 * EDSCALE));
+ split_box->add_child(tree);
- //tree->set_v_size_flags(SIZE_EXPAND_FILL);
tree->connect("item_edited", this, "_favorite_toggled");
- tree->connect("item_activated", this, "_open_pressed");
+ tree->connect("item_activated", this, "_go_to_file_list");
tree->connect("cell_selected", this, "_dir_selected");
tree->connect("item_rmb_selected", this, "_dir_rmb_pressed");
- files = memnew(ItemList);
- files->set_v_size_flags(SIZE_EXPAND_FILL);
- files->set_select_mode(ItemList::SELECT_MULTI);
- files->set_drag_forwarding(this);
- files->connect("item_rmb_selected", this, "_files_list_rmb_select");
- files->connect("item_selected", this, "_file_selected");
- files->connect("multi_selected", this, "_file_multi_selected");
- files->set_allow_rmb_select(true);
-
file_list_vb = memnew(VBoxContainer);
- split_box->add_child(file_list_vb);
file_list_vb->set_v_size_flags(SIZE_EXPAND_FILL);
+ split_box->add_child(file_list_vb);
path_hb = memnew(HBoxContainer);
file_list_vb->add_child(path_hb);
- button_back = memnew(ToolButton);
- path_hb->add_child(button_back);
- button_back->hide();
+ button_tree = memnew(ToolButton);
+ button_tree->hide();
+ path_hb->add_child(button_tree);
search_box = memnew(LineEdit);
search_box->set_h_size_flags(SIZE_EXPAND_FILL);
- path_hb->add_child(search_box);
search_box->connect("text_changed", this, "_search_changed");
+ path_hb->add_child(search_box);
button_display_mode = memnew(ToolButton);
- path_hb->add_child(button_display_mode);
button_display_mode->set_toggle_mode(true);
+ path_hb->add_child(button_display_mode);
+ files = memnew(ItemList);
+ files->set_v_size_flags(SIZE_EXPAND_FILL);
+ files->set_select_mode(ItemList::SELECT_MULTI);
+ files->set_drag_forwarding(this);
+ files->connect("item_rmb_selected", this, "_files_list_rmb_select");
+ files->connect("item_selected", this, "_file_selected");
+ files->connect("multi_selected", this, "_file_multi_selected");
+ files->connect("rmb_clicked", this, "_rmb_pressed");
+ files->set_allow_rmb_select(true);
file_list_vb->add_child(files);
scanning_vb = memnew(VBoxContainer);
+ scanning_vb->hide();
+ add_child(scanning_vb);
+
Label *slabel = memnew(Label);
slabel->set_text(TTR("Scanning Files,\nPlease Wait.."));
slabel->set_align(Label::ALIGN_CENTER);
scanning_vb->add_child(slabel);
+
scanning_progress = memnew(ProgressBar);
scanning_vb->add_child(scanning_progress);
- add_child(scanning_vb);
- scanning_vb->hide();
deps_editor = memnew(DependencyEditor);
add_child(deps_editor);
- owners_editor = memnew(DependencyEditorOwners);
+ owners_editor = memnew(DependencyEditorOwners(editor));
add_child(owners_editor);
remove_dialog = memnew(DependencyRemoveDialog);
add_child(remove_dialog);
move_dialog = memnew(EditorDirDialog);
- add_child(move_dialog);
- move_dialog->connect("dir_selected", this, "_move_operation");
move_dialog->get_ok()->set_text(TTR("Move"));
+ add_child(move_dialog);
+ move_dialog->connect("dir_selected", this, "_move_operation_confirm");
+
+ rename_dialog = memnew(ConfirmationDialog);
+ VBoxContainer *rename_dialog_vb = memnew(VBoxContainer);
+ rename_dialog->add_child(rename_dialog_vb);
- rename_dialog = memnew(EditorFileDialog);
- rename_dialog->set_mode(EditorFileDialog::MODE_SAVE_FILE);
- rename_dialog->connect("file_selected", this, "_rename_operation");
+ rename_dialog_text = memnew(LineEdit);
+ rename_dialog_vb->add_margin_child(TTR("Name:"), rename_dialog_text);
+ rename_dialog->get_ok()->set_text(TTR("Rename"));
add_child(rename_dialog);
+ rename_dialog->register_text_enter(rename_dialog_text);
+ rename_dialog->connect("confirmed", this, "_rename_operation_confirm");
+
+ make_dir_dialog = memnew(ConfirmationDialog);
+ make_dir_dialog->set_title(TTR("Create Folder"));
+ VBoxContainer *make_folder_dialog_vb = memnew(VBoxContainer);
+ make_dir_dialog->add_child(make_folder_dialog_vb);
+
+ make_dir_dialog_text = memnew(LineEdit);
+ make_folder_dialog_vb->add_margin_child(TTR("Name:"), make_dir_dialog_text);
+ add_child(make_dir_dialog);
+ make_dir_dialog->register_text_enter(make_dir_dialog_text);
+ make_dir_dialog->connect("confirmed", this, "_make_dir_confirm");
updating_tree = false;
initialized = false;
+ import_dock_needs_update = false;
- history.push_back("res://");
history_pos = 0;
+ history_max_size = 20;
+ history.push_back("res://");
- split_mode = false;
+ low_height_mode = false;
display_mode = DISPLAY_THUMBNAILS;
-
- path = "res://";
}
FileSystemDock::~FileSystemDock() {
diff --git a/editor/filesystem_dock.h b/editor/filesystem_dock.h
index aec049ba43..f1fd342052 100644
--- a/editor/filesystem_dock.h
+++ b/editor/filesystem_dock.h
@@ -32,6 +32,7 @@
#include "scene/gui/box_container.h"
#include "scene/gui/control.h"
+#include "scene/gui/dialogs.h"
#include "scene/gui/item_list.h"
#include "scene/gui/label.h"
#include "scene/gui/menu_button.h"
@@ -67,9 +68,11 @@ private:
FILE_DEPENDENCIES,
FILE_OWNERS,
FILE_MOVE,
+ FILE_RENAME,
FILE_REMOVE,
FILE_REIMPORT,
FILE_INFO,
+ FILE_NEW_FOLDER,
FILE_SHOW_IN_EXPLORER,
FILE_COPY_PATH
};
@@ -77,7 +80,12 @@ private:
enum FolderMenu {
FOLDER_EXPAND_ALL,
FOLDER_COLLAPSE_ALL,
- FOLDER_SHOW_IN_EXPLORER
+ FOLDER_MOVE,
+ FOLDER_RENAME,
+ FOLDER_REMOVE,
+ FOLDER_NEW_FOLDER,
+ FOLDER_SHOW_IN_EXPLORER,
+ FOLDER_COPY_PATH
};
VBoxContainer *scanning_vb;
@@ -90,7 +98,7 @@ private:
Button *button_reload;
Button *button_favorite;
- Button *button_back;
+ Button *button_tree;
Button *button_display_mode;
Button *button_hist_next;
Button *button_hist_prev;
@@ -99,7 +107,7 @@ private:
TextureRect *search_icon;
HBoxContainer *path_hb;
- bool split_mode;
+ bool low_height_mode;
DisplayMode display_mode;
PopupMenu *file_options;
@@ -110,13 +118,27 @@ private:
DependencyRemoveDialog *remove_dialog;
EditorDirDialog *move_dialog;
- EditorFileDialog *rename_dialog;
+ ConfirmationDialog *rename_dialog;
+ LineEdit *rename_dialog_text;
+ ConfirmationDialog *make_dir_dialog;
+ LineEdit *make_dir_dialog_text;
- Vector<String> move_dirs;
- Vector<String> move_files;
+ class FileOrFolder {
+ public:
+ String path;
+ bool is_file;
+
+ FileOrFolder()
+ : path(""), is_file(false) {}
+ FileOrFolder(const String &p_path, bool p_is_file)
+ : path(p_path), is_file(p_is_file) {}
+ };
+ FileOrFolder to_rename;
+ Vector<FileOrFolder> to_move;
Vector<String> history;
int history_pos;
+ int history_max_size;
String path;
@@ -125,44 +147,52 @@ private:
bool updating_tree;
Tree *tree; //directories
ItemList *files;
+ bool import_dock_needs_update;
- void _file_multi_selected(int p_index, bool p_selected);
- void _file_selected();
+ bool _create_tree(TreeItem *p_parent, EditorFileSystemDirectory *p_dir, Vector<String> &uncollapsed_paths);
+ void _update_tree(bool keep_collapse_state);
+
+ void _update_files(bool p_keep_selection);
+ void _update_file_display_toggle_button();
+ void _change_file_display();
+ void _fs_changed();
void _go_to_tree();
- void _go_to_dir(const String &p_dir);
+ void _go_to_file_list();
+
void _select_file(int p_idx);
+ void _file_multi_selected(int p_index, bool p_selected);
+ void _update_import_dock();
- bool _create_tree(TreeItem *p_parent, EditorFileSystemDirectory *p_dir);
- void _thumbnail_done(const String &p_path, const Ref<Texture> &p_preview, const Variant &p_udata);
- void _find_inside_move_files(EditorFileSystemDirectory *efsd, Vector<String> &files);
- void _find_remaps(EditorFileSystemDirectory *efsd, Map<String, String> &renames, List<String> &to_remaps);
+ void _file_selected();
+ void _dir_selected();
- void _rename_operation(const String &p_to_path);
- void _move_operation(const String &p_to_path);
+ void _get_all_files_in_dir(EditorFileSystemDirectory *efsd, Vector<String> &files) const;
+ void _find_remaps(EditorFileSystemDirectory *efsd, const Map<String, String> &renames, Vector<String> &to_remaps) const;
+ void _try_move_item(const FileOrFolder &p_item, const String &p_new_path, Map<String, String> &p_renames) const;
+ void _update_dependencies_after_move(const Map<String, String> &p_renames) const;
+
+ void _make_dir_confirm();
+ void _rename_operation_confirm();
+ void _move_operation_confirm(const String &p_to_path);
void _file_option(int p_option);
void _folder_option(int p_option);
- void _update_files(bool p_keep_selection);
- void _update_file_display_toggle_button();
- void _change_file_display();
- void _fs_changed();
void _fw_history();
void _bw_history();
+ void _update_history();
void _push_to_history();
- void _dir_selected();
- void _update_tree();
- void _rescan();
void _set_scanning_mode();
+ void _rescan();
void _favorites_pressed();
- void _open_pressed();
- void _dir_rmb_pressed(const Vector2 &p_pos);
void _search_changed(const String &p_text);
+ void _dir_rmb_pressed(const Vector2 &p_pos);
void _files_list_rmb_select(int p_item, const Vector2 &p_pos);
+ void _rmb_pressed(const Vector2 &p_pos);
struct FileInfo {
String name;
@@ -182,8 +212,10 @@ private:
Variant get_drag_data_fw(const Point2 &p_point, Control *p_from);
bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const;
void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from);
+ String _get_drag_target_folder(const Point2 &p_point, Control *p_from) const;
void _preview_invalidated(const String &p_path);
+ void _thumbnail_done(const String &p_path, const Ref<Texture> &p_preview, const Variant &p_udata);
protected:
void _notification(int p_what);
diff --git a/editor/icons/icon_GUI_ellipsis.svg b/editor/icons/icon_GUI_ellipsis.svg
new file mode 100644
index 0000000000..5565fd2947
--- /dev/null
+++ b/editor/icons/icon_GUI_ellipsis.svg
@@ -0,0 +1,5 @@
+<svg width="14" height="8" version="1.1" viewBox="0 0 14 8" xmlns="http://www.w3.org/2000/svg">
+<g transform="translate(0 -1044.4)">
+<path transform="translate(0 1040.4)" d="m3.8594 4c-2.1381 0-3.8594 1.7213-3.8594 3.8594v0.28125c0 2.1381 1.7213 3.8594 3.8594 3.8594h6.2812c2.1381 0 3.8594-1.7213 3.8594-3.8594v-0.28125c0-2.1381-1.7213-3.8594-3.8594-3.8594zm-0.85938 3a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1zm4 0a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1zm4 0a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1z" fill="#fff" fill-opacity=".39216"/>
+</g>
+</svg>
diff --git a/editor/icons/icon_GUI_toggle_off.svg b/editor/icons/icon_GUI_toggle_off.svg
index 0d43b158b5..aea0f85f96 100644
--- a/editor/icons/icon_GUI_toggle_off.svg
+++ b/editor/icons/icon_GUI_toggle_off.svg
@@ -1,5 +1,5 @@
-<svg width="64" height="32" version="1.1" viewBox="0 0 64 31.999998" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1020.4)">
-<path transform="translate(0 1020.4)" d="m24 4.002c-6.6307 0-12 5.3654-12 11.996v0.003906c0 6.6307 5.3693 12 12 12h16c6.6307 0 12-5.3693 12-12v-0.003906c0-6.6307-5.3693-11.996-12-11.996h-16zm0 2h16c5.5573 0 10 4.4388 10 9.9961v0.003906c0 5.5573-4.4427 10-10 10h-16c-5.5573 0-10-4.4427-10-10v-0.003906c0-5.5573 4.4427-9.9961 10-9.9961zm7 4.9961a1.0001 1.0001 0 0 0 -1 1v8a1 1 0 0 0 1 1 1 1 0 0 0 1 -1v-3h2a1 1 0 0 0 1 -1 1 1 0 0 0 -1 -1h-2v-2h4a1 1 0 0 0 1 -1 1 1 0 0 0 -1 -1h-5zm9 0a1.0001 1.0001 0 0 0 -1 1v4 4a1 1 0 0 0 1 1 1 1 0 0 0 1 -1v-3h2a1 1 0 0 0 1 -1 1 1 0 0 0 -1 -1h-2v-2h4a1 1 0 0 0 1 -1 1 1 0 0 0 -1 -1h-5zm-17 0.003906c-2.7496 0-5 2.2504-5 5s2.2504 5 5 5 5-2.2504 5-5-2.2504-5-5-5zm0 2c1.6687 0 3 1.3313 3 3s-1.3313 3-3 3-3-1.3313-3-3 1.3313-3 3-3z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#e0e0e0" fill-opacity=".78431" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="filter-blend-mode:normal;filter-gaussianBlur-deviation:0;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
+<svg width="42" height="26" version="1.1" viewBox="0 0 42 25.999998" xmlns="http://www.w3.org/2000/svg">
+<g transform="translate(0 -1026.4)">
+<path d="m13 1027.4c-6.6307 0-12 5.3663-12 11.998 0 6.6318 5.3693 12.002 12 12.002h16c6.6307 0 12-5.3702 12-12.002 0-6.6317-5.3693-11.998-12-11.998zm0 2.0003h16c5.5573 0 10 4.4395 10 9.9977 0 5.5583-4.4427 10.002-10 10.002h-16c-5.5573 0-10-4.4434-10-10.002 0-5.5582 4.4427-9.9977 10-9.9977zm7 4.9969a1.0001 1.0003 0 0 0 -1 1.0002v8.0013a1 1.0002 0 0 0 1 1.0002 1 1.0002 0 0 0 1 -1.0002v-3.0005h2a1 1.0002 0 0 0 1 -1.0002 1 1.0002 0 0 0 -1 -1.0001h-2v-2.0003h4a1 1.0002 0 0 0 1 -1.0002 1 1.0002 0 0 0 -1 -1.0002zm9 0a1.0001 1.0003 0 0 0 -1 1.0002v8.0013a1 1.0002 0 0 0 1 1.0002 1 1.0002 0 0 0 1 -1.0002v-3.0005h2a1 1.0002 0 0 0 1 -1.0002 1 1.0002 0 0 0 -1 -1.0001h-2v-2.0003h4a1 1.0002 0 0 0 1 -1.0002 1 1.0002 0 0 0 -1 -1.0002zm-17 0c-2.7496 0-5 2.2508-5 5.0008 0 2.7501 2.2504 5.0009 5 5.0009s5-2.2508 5-5.0009c0-2.75-2.2504-5.0008-5-5.0008zm0 2.0004c1.6687 0 3 1.3315 3 3.0004 0 1.669-1.3313 3.0005-3 3.0005s-3-1.3315-3-3.0005c0-1.6689 1.3313-3.0004 3-3.0004z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#e0e0e0" fill-opacity=".78431" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
</g>
</svg>
diff --git a/editor/icons/icon_GUI_toggle_on.svg b/editor/icons/icon_GUI_toggle_on.svg
index fd2b915fc3..c0a11810d4 100644
--- a/editor/icons/icon_GUI_toggle_on.svg
+++ b/editor/icons/icon_GUI_toggle_on.svg
@@ -1,5 +1,5 @@
-<svg width="64" height="32" version="1.1" viewBox="0 0 64 31.999998" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1020.4)">
-<path transform="translate(0 1020.4)" d="m24 4.002c-6.6307 0-12 5.3654-12 11.996 0 6.6307 5.3693 12 12 12h16c6.6307 0 12-5.3693 12-12 0-6.6307-5.3693-11.996-12-11.996h-16zm17 6.9961a1 1 0 0 1 1 1v8a1.0001 1.0001 0 0 1 -1.752 0.66211l-5.248-6v5.3379a1 1 0 0 1 -1 1 1 1 0 0 1 -1 -1v-8a1.0001 1.0001 0 0 1 1.752 -0.6582l5.248 6v-5.3418a1 1 0 0 1 1 -1zm-15 0.003906c2.7496 0 5 2.2504 5 5s-2.2504 5-5 5-5-2.2504-5-5 2.2504-5 5-5zm0 2c-1.6687 0-3 1.3313-3 3s1.3313 3 3 3 3-1.3313 3-3-1.3313-3-3-3z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#e0e0e0" fill-opacity=".78431" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
+<svg width="42" height="26" version="1.1" viewBox="0 0 42 25.999998" xmlns="http://www.w3.org/2000/svg">
+<g transform="translate(0 -1026.4)">
+<path d="m13 1027.4c-6.6307 0-12 5.3662-12 11.998s5.3693 12.002 12 12.002h16c6.6307 0 12-5.3702 12-12.002s-5.3693-11.998-12-11.998zm17 6.9972a1 1.0002 0 0 1 1 1.0001v8.0014a1.0001 1.0003 0 0 1 -1.752 0.6623l-5.248-6.001v5.3387a1 1.0002 0 0 1 -1 1.0001 1 1.0002 0 0 1 -1 -1.0001v-8.0014a1.0001 1.0003 0 0 1 1.752 -0.6583l5.248 6.001v-5.3427a1 1.0002 0 0 1 1 -1.0001zm-15 0c2.7496 0 5 2.2507 5 5.0008s-2.2504 5.0008-5 5.0008-5-2.2507-5-5.0008 2.2504-5.0008 5-5.0008zm0 2.0003c-1.6687 0-3 1.3315-3 3.0005s1.3313 3.0005 3 3.0005 3-1.3315 3-3.0005-1.3313-3.0005-3-3.0005z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#e0e0e0" fill-opacity=".78431" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
</g>
</svg>
diff --git a/editor/icons/icon_GUI_unchecked.svg b/editor/icons/icon_GUI_unchecked.svg
index 4adf3dd61e..59df40954f 100644
--- a/editor/icons/icon_GUI_unchecked.svg
+++ b/editor/icons/icon_GUI_unchecked.svg
@@ -1,5 +1,3 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 15.999999" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m4 2a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h8a2 2 0 0 0 2 -2v-8a2 2 0 0 0 -2 -2h-8zm0.80078 2h6.3984a0.8 0.8 0 0 1 0.80078 0.80078v6.3984a0.8 0.8 0 0 1 -0.80078 0.80078h-6.3984a0.8 0.8 0 0 1 -0.80078 -0.80078v-6.3984a0.8 0.8 0 0 1 0.80078 -0.80078z" fill="#e0e0e0" fill-opacity=".78431"/>
-</g>
+<path d="m4 2a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h8a2 2 0 0 0 2 -2v-8a2 2 0 0 0 -2 -2h-8zm0.80078 2h6.3984a0.8 0.8 0 0 1 0.80078 0.80078v6.3984a0.8 0.8 0 0 1 -0.80078 0.80078h-6.3984a0.8 0.8 0 0 1 -0.80078 -0.80078v-6.3984a0.8 0.8 0 0 1 0.80078 -0.80078z" fill="#e0e0e0" fill-opacity=".78431"/>
</svg>
diff --git a/editor/icons/icon_a_r_v_r_anchor.svg b/editor/icons/icon_a_r_v_r_anchor.svg
new file mode 100644
index 0000000000..1a8398a1be
--- /dev/null
+++ b/editor/icons/icon_a_r_v_r_anchor.svg
@@ -0,0 +1,3 @@
+<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
+<path d="m7 1v2h-2v2h2v3.2656l-2.5527-1.2773c-0.15005-0.075253-0.31662-0.11152-0.48438-0.10547-0.36536 0.013648-0.69415 0.2256-0.85742 0.55273-0.24709 0.49403-0.046823 1.0948 0.44727 1.3418l4.4473 2.2227 4.4473-2.2227c0.49409-0.24697 0.69435-0.84777 0.44726-1.3418-0.24697-0.49409-0.84777-0.69435-1.3418-0.44727l-2.5527 1.2773v-3.2656h2v-2h-2v-2zm-3 11v1c0 0.55228 0.44772 1 1 1-0.55228 0-1 0.44772-1 1v1h1v-1h1v1h1v-1c0-0.55228-0.44772-1-1-1 0.55228 0 1-0.44772 1-1v-1h-1v1h-1v-1zm5 0v4h1v-1h1v1h1v-1c-8.34e-4 -0.17579-0.047991-0.34825-0.13672-0.5 0.088728-0.15175 0.13588-0.32421 0.13672-0.5v-1c0-0.55228-0.44772-1-1-1h-1zm1 1h1v1h-1z" fill="#fc9c9c"/>
+</svg>
diff --git a/editor/icons/icon_a_r_v_r_camera.svg b/editor/icons/icon_a_r_v_r_camera.svg
index a02b4d983c..5bf815bcef 100644
--- a/editor/icons/icon_a_r_v_r_camera.svg
+++ b/editor/icons/icon_a_r_v_r_camera.svg
@@ -1,3 +1,3 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<path d="m2 1c-0.55401 0-1 0.446-1 1v7c0 0.554 0.44599 1 1 1h4l1-2c0.24699-0.494 0.44772-1 1-1s0.75301 0.506 1 1l1 2h4c0.55401 0 1-0.446 1-1v-7c0-0.554-0.44599-1-1-1h-12zm2 3a2 2 0 0 1 2 2 2 2 0 0 1 -2 2 2 2 0 0 1 -2 -2 2 2 0 0 1 2 -2zm8 0a2 2 0 0 1 2 2 2 2 0 0 1 -2 2 2 2 0 0 1 -2 -2 2 2 0 0 1 2 -2zm-8 7v4h2c0.502 4e-4 0.9265-0.37144 0.99219-0.86914 0.0059-0.047 0.0085325-0.094025 0.0078125-0.14062v-2.9902h-1v3h-1v-3h-1zm5 0v4h1v-1h1v1h1v-1c-7.73e-4 -0.1811-0.05073-0.35867-0.14453-0.51367 0.08369-0.1462 0.14453-0.30573 0.14453-0.48633v-1c0-0.5523-0.4485-1.0293-1-1h-2zm1 1h1v1h-1v-1z" fill="#fc9c9c"/>
+<path d="m9.5 0a3 3 0 0 0 -2.9883 2.7773 3 3 0 0 0 -2.0117 -0.77734 3 3 0 0 0 -3 3 3 3 0 0 0 2 2.8242v2.1758c0 0.554 0.44599 1 1 1h6c0.55401 0 1-0.446 1-1v-1l3 2v-6l-3 2v-1.7695a3 3 0 0 0 1 -2.2305 3 3 0 0 0 -3 -3zm-5.5 12v1c0 0.55228 0.44772 1 1 1-0.55228 0-1 0.44772-1 1v1h1v-1h1v1h1v-1c0-0.55228-0.44772-1-1-1 0.55228 0 1-0.44772 1-1v-1h-1v1h-1v-1h-1zm5 0v1 3h1v-1h1v1h1v-1c-8.34e-4 -0.17579-0.047991-0.34825-0.13672-0.5 0.088728-0.15175 0.13588-0.32421 0.13672-0.5v-1c0-0.55228-0.44772-1-1-1h-1-1zm1 1h1v1h-1v-1z" fill="#fc9c9c"/>
</svg>
diff --git a/editor/icons/icon_a_r_v_r_controller.svg b/editor/icons/icon_a_r_v_r_controller.svg
new file mode 100644
index 0000000000..a61f99ffdf
--- /dev/null
+++ b/editor/icons/icon_a_r_v_r_controller.svg
@@ -0,0 +1,3 @@
+<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
+<path d="m2 1c-0.554 0-1 0.446-1 1v6c0 0.554 0.446 1 1 1h12c0.554 0 1-0.446 1-1v-6c0-0.554-0.446-1-1-1h-12zm2 1h2v2h2v2h-2v2h-2v-2h-2v-2h2v-2zm9 1c0.55228 0 1 0.44772 1 1s-0.44772 1-1 1-1-0.44772-1-1 0.44772-1 1-1zm-2 2c0.55228 0 1 0.44772 1 1s-0.44772 1-1 1-1-0.44772-1-1 0.44772-1 1-1zm-7 7v1c0 0.55228 0.44772 1 1 1-0.55228 0-1 0.44772-1 1v1h1v-1h1v1h1v-1c0-0.55228-0.44772-1-1-1 0.55228 0 1-0.44772 1-1v-1h-1v1h-1v-1h-1zm5 0v1 3h1v-1h1v1h1v-1c-8.34e-4 -0.17579-0.047991-0.34825-0.13672-0.5 0.088728-0.15175 0.13588-0.32421 0.13672-0.5v-1c0-0.55228-0.44772-1-1-1h-1-1zm1 1h1v1h-1v-1z" fill="#fc9c9c"/>
+</svg>
diff --git a/editor/icons/icon_a_r_v_r_origin.svg b/editor/icons/icon_a_r_v_r_origin.svg
new file mode 100644
index 0000000000..53a149cec6
--- /dev/null
+++ b/editor/icons/icon_a_r_v_r_origin.svg
@@ -0,0 +1,3 @@
+<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
+<path d="m7 1v3h2v-3h-2zm-4 4v2h3v-2h-3zm5 0c-0.55228 0-1 0.44772-1 1s0.44772 1 1 1 1-0.44772 1-1-0.44772-1-1-1zm2 0v2h3v-2h-3zm-3 3v3h2v-3h-2zm-3 4v1c0 0.55228 0.44772 1 1 1-0.55228 0-1 0.44772-1 1v1h1v-1h1v1h1v-1c0-0.55228-0.44772-1-1-1 0.55228 0 1-0.44772 1-1v-1h-1v1h-1v-1h-1zm5 0v1 3h1v-1h1v1h1v-1c-8.34e-4 -0.17579-0.047991-0.34825-0.13672-0.5 0.088728-0.15175 0.13588-0.32421 0.13672-0.5v-1c0-0.55228-0.44772-1-1-1h-1-1zm1 1h1v1h-1v-1z" fill="#fc9c9c"/>
+</svg>
diff --git a/editor/icons/icon_animated_sprite.svg b/editor/icons/icon_animated_sprite.svg
index fe7fde5a39..6fdf8a7a40 100644
--- a/editor/icons/icon_animated_sprite.svg
+++ b/editor/icons/icon_animated_sprite.svg
@@ -1,7 +1,7 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#a5b7f3">
-<path transform="translate(0 1036.4)" d="m10.5 0a5.5 5.5 0 0 0 -5.3301 4.1699 5.5 5.5 0 0 1 1.3301 -0.16992 5.5 5.5 0 0 1 5.5 5.5 5.5 5.5 0 0 1 -0.16992 1.3301 5.5 5.5 0 0 0 4.1699 -5.3301 5.5 5.5 0 0 0 -5.5 -5.5z" fill-opacity=".39216"/>
-<path transform="translate(0 1036.4)" d="m8.5 2a5.5 5.5 0 0 0 -4.7559 2.748 5.5 5.5 0 0 1 2.7559 -0.74805 5.5 5.5 0 0 1 5.5 5.5 5.5 5.5 0 0 1 -0.74414 2.752 5.5 5.5 0 0 0 2.7441 -4.752 5.5 5.5 0 0 0 -5.5 -5.5z" fill-opacity=".58824"/>
-<path transform="translate(0 1036.4)" d="m6.5 4a5.5 5.5 0 0 0 -5.5 5.5 5.5 5.5 0 0 0 5.5 5.5 5.5 5.5 0 0 0 5.5 -5.5 5.5 5.5 0 0 0 -5.5 -5.5zm-2.5 4a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1zm5 0a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1zm-5 3h5a2.5 2 0 0 1 -1.25 1.7324 2.5 2 0 0 1 -2.5 0 2.5 2 0 0 1 -1.25 -1.7324z"/>
+<g fill="#a5b7f3">
+<path d="m7 0c-1.108 0-2 0.89199-2 2h7c1.108 0 2 0.89199 2 2v6c1.108 0 2-0.89199 2-2v-6c0-1.108-0.89199-2-2-2z" fill-opacity=".39216"/>
+<path d="m5 2c-1.108 0-2 0.89199-2 2h7c1.108 0 2 0.89199 2 2v7c1.108 0 2-0.89199 2-2v-7c0-1.108-0.89199-2-2-2h-7z" fill-opacity=".58824"/>
+<path d="m3 4c-1.108 0-2 0.89199-2 2v7c0 1.108 0.89199 2 2 2h7c1.108 0 2-0.89199 2-2v-7c0-1.108-0.89199-2-2-2h-7zm0 4c0.554 0 1 0.446 1 1v1c0 0.554-0.446 1-1 1s-1-0.446-1-1v-1c0-0.554 0.446-1 1-1zm7 0c0.554 0 1 0.446 1 1v1c0 0.554-0.446 1-1 1s-1-0.446-1-1v-1c0-0.554 0.446-1 1-1zm-6 4h5a2.5 2 0 0 1 -1.25 1.7324 2.5 2 0 0 1 -2.5 0 2.5 2 0 0 1 -1.25 -1.7324z"/>
</g>
</svg>
diff --git a/editor/icons/icon_animated_sprite_3d.svg b/editor/icons/icon_animated_sprite_3d.svg
index 658ba3e5c2..ccc836832c 100644
--- a/editor/icons/icon_animated_sprite_3d.svg
+++ b/editor/icons/icon_animated_sprite_3d.svg
@@ -1,7 +1,7 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#fc9c9c">
-<path transform="translate(0 1036.4)" d="m10.5 0a5.5 5.5 0 0 0 -5.3301 4.1699 5.5 5.5 0 0 1 1.3301 -0.16992 5.5 5.5 0 0 1 5.5 5.5 5.5 5.5 0 0 1 -0.16992 1.3301 5.5 5.5 0 0 0 4.1699 -5.3301 5.5 5.5 0 0 0 -5.5 -5.5z" fill-opacity=".39216"/>
-<path transform="translate(0 1036.4)" d="m8.5 2a5.5 5.5 0 0 0 -4.7559 2.748 5.5 5.5 0 0 1 2.7559 -0.74805 5.5 5.5 0 0 1 5.5 5.5 5.5 5.5 0 0 1 -0.74414 2.752 5.5 5.5 0 0 0 2.7441 -4.752 5.5 5.5 0 0 0 -5.5 -5.5z" fill-opacity=".58824"/>
-<path transform="translate(0 1036.4)" d="m6.5 4a5.5 5.5 0 0 0 -5.5 5.5 5.5 5.5 0 0 0 5.5 5.5 5.5 5.5 0 0 0 5.5 -5.5 5.5 5.5 0 0 0 -5.5 -5.5zm-2.5 4a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1zm5 0a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1zm-5 3h5a2.5 2 0 0 1 -1.25 1.7324 2.5 2 0 0 1 -2.5 0 2.5 2 0 0 1 -1.25 -1.7324z"/>
+<g fill="#fc9c9c">
+<path d="m7 0c-1.108 0-2 0.89199-2 2h7c1.108 0 2 0.89199 2 2v6c1.108 0 2-0.89199 2-2v-6c0-1.108-0.89199-2-2-2z" fill-opacity=".39216"/>
+<path d="m5 2c-1.108 0-2 0.89199-2 2h7c1.108 0 2 0.89199 2 2v7c1.108 0 2-0.89199 2-2v-7c0-1.108-0.89199-2-2-2h-7z" fill-opacity=".58824"/>
+<path d="m3 4c-1.108 0-2 0.89199-2 2v7c0 1.108 0.89199 2 2 2h7c1.108 0 2-0.89199 2-2v-7c0-1.108-0.89199-2-2-2h-7zm0 4c0.554 0 1 0.446 1 1v1c0 0.554-0.446 1-1 1s-1-0.446-1-1v-1c0-0.554 0.446-1 1-1zm7 0c0.554 0 1 0.446 1 1v1c0 0.554-0.446 1-1 1s-1-0.446-1-1v-1c0-0.554 0.446-1 1-1zm-6 4h5a2.5 2 0 0 1 -1.25 1.7324 2.5 2 0 0 1 -2.5 0 2.5 2 0 0 1 -1.25 -1.7324z"/>
</g>
</svg>
diff --git a/editor/icons/icon_animation.svg b/editor/icons/icon_animation.svg
index 146403ece5..600faeeddb 100644
--- a/editor/icons/icon_animation.svg
+++ b/editor/icons/icon_animation.svg
@@ -1,5 +1,3 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m8 2a6 6 0 0 0 -6 6 6 6 0 0 0 6 6 6 6 0 0 0 4 -1.5352v1.5352h0.001953a2 2 0 0 0 0.26562 1 2 2 0 0 0 1.7324 1h1v-1-1h-0.5a0.5 0.49999 0 0 1 -0.5 -0.5v-0.5-5a6 6 0 0 0 -6 -6zm0 1a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1zm3.4414 2a1 1 0 0 1 0.88867 0.5 1 1 0 0 1 -0.36523 1.3652 1 1 0 0 1 -1.3672 -0.36523 1 1 0 0 1 0.36719 -1.3652 1 1 0 0 1 0.47656 -0.13477zm-6.9531 0.0019531a1 1 0 0 1 0.54688 0.13281 1 1 0 0 1 0.36719 1.3652 1 1 0 0 1 -1.3672 0.36523 1 1 0 0 1 -0.36523 -1.3652 1 1 0 0 1 0.81836 -0.49805zm0.023438 3.998a1 1 0 0 1 0.89062 0.5 1 1 0 0 1 -0.36719 1.3652 1 1 0 0 1 -1.3652 -0.36523 1 1 0 0 1 0.36523 -1.3652 1 1 0 0 1 0.47656 -0.13477zm6.9043 0.0019531a1 1 0 0 1 0.54883 0.13281 1 1 0 0 1 0.36523 1.3652 1 1 0 0 1 -1.3652 0.36523 1 1 0 0 1 -0.36719 -1.3652 1 1 0 0 1 0.81836 -0.49805zm-3.416 1.998a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1z" fill="#e0e0e0"/>
-</g>
+<path d="m8 2a6 6 0 0 0 -6 6 6 6 0 0 0 6 6 6 6 0 0 0 4 -1.5352v1.5352h0.001953a2 2 0 0 0 0.26562 1 2 2 0 0 0 1.7324 1h1v-1-1h-0.5a0.5 0.49999 0 0 1 -0.5 -0.5v-0.5-5a6 6 0 0 0 -6 -6zm0 1a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1zm3.4414 2a1 1 0 0 1 0.88867 0.5 1 1 0 0 1 -0.36523 1.3652 1 1 0 0 1 -1.3672 -0.36523 1 1 0 0 1 0.36719 -1.3652 1 1 0 0 1 0.47656 -0.13477zm-6.9531 0.0019531a1 1 0 0 1 0.54688 0.13281 1 1 0 0 1 0.36719 1.3652 1 1 0 0 1 -1.3672 0.36523 1 1 0 0 1 -0.36523 -1.3652 1 1 0 0 1 0.81836 -0.49805zm0.023438 3.998a1 1 0 0 1 0.89062 0.5 1 1 0 0 1 -0.36719 1.3652 1 1 0 0 1 -1.3652 -0.36523 1 1 0 0 1 0.36523 -1.3652 1 1 0 0 1 0.47656 -0.13477zm6.9043 0.0019531a1 1 0 0 1 0.54883 0.13281 1 1 0 0 1 0.36523 1.3652 1 1 0 0 1 -1.3652 0.36523 1 1 0 0 1 -0.36719 -1.3652 1 1 0 0 1 0.81836 -0.49805zm-3.416 1.998a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1z" fill="#e0e0e0"/>
</svg>
diff --git a/editor/icons/icon_area.svg b/editor/icons/icon_area.svg
index ac673d10fc..5e1a385f58 100644
--- a/editor/icons/icon_area.svg
+++ b/editor/icons/icon_area.svg
@@ -1,5 +1,3 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m1 1v2 2h2v-2h2v-2h-4zm10 0v2h2v2h2v-4h-4zm-7 3v2 4 2h8v-2-6h-8zm2 2h4v4h-4v-4zm-5 5v2 2h2 2v-2h-2v-2h-2zm12 0v2h-2v2h4v-2-2h-2z" fill="#fc9c9c"/>
-</g>
+<path d="m1 1v2 2h2v-2h2v-2h-4zm10 0v2h2v2h2v-4h-4zm-7 3v2 4 2h8v-2-6h-8zm2 2h4v4h-4v-4zm-5 5v2 2h2 2v-2h-2v-2h-2zm12 0v2h-2v2h4v-2-2h-2z" fill="#fc9c9c"/>
</svg>
diff --git a/editor/icons/icon_area_2d.svg b/editor/icons/icon_area_2d.svg
index d6ecb6abe5..28fc4d7804 100644
--- a/editor/icons/icon_area_2d.svg
+++ b/editor/icons/icon_area_2d.svg
@@ -1,5 +1,3 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m1 1v2 2h2v-2h2v-2h-4zm10 0v2h2v2h2v-4h-4zm-7 3v2 4 2h8v-2-6h-8zm2 2h4v4h-4v-4zm-5 5v2 2h2 2v-2h-2v-2h-2zm12 0v2h-2v2h4v-2-2h-2z" fill="#a5b7f3"/>
-</g>
+<path d="m1 1v2 2h2v-2h2v-2h-4zm10 0v2h2v2h2v-4h-4zm-7 3v2 4 2h8v-2-6h-8zm2 2h4v4h-4v-4zm-5 5v2 2h2 2v-2h-2v-2h-2zm12 0v2h-2v2h4v-2-2h-2z" fill="#a5b7f3"/>
</svg>
diff --git a/editor/icons/icon_array_mesh.svg b/editor/icons/icon_array_mesh.svg
index 68890c4366..867fc95b0c 100644
--- a/editor/icons/icon_array_mesh.svg
+++ b/editor/icons/icon_array_mesh.svg
@@ -1,5 +1,3 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m3 1a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2 -2 2 2 0 0 0 -2 -2zm10 0a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2 -2 2 2 0 0 0 -2 -2zm-2 7v3h-3v2h3v3h2v-3h3v-2h-3v-3h-2zm-8 3a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2 -2 2 2 0 0 0 -2 -2z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#ffd684" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
-</g>
+<path d="m3 1a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2 -2 2 2 0 0 0 -2 -2zm10 0a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2 -2 2 2 0 0 0 -2 -2zm-2 7v3h-3v2h3v3h2v-3h3v-2h-3v-3h-2zm-8 3a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2 -2 2 2 0 0 0 -2 -2z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#ffd684" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
</svg>
diff --git a/editor/icons/icon_center_container.svg b/editor/icons/icon_center_container.svg
index 446e9e0f9c..fc0abc5c28 100644
--- a/editor/icons/icon_center_container.svg
+++ b/editor/icons/icon_center_container.svg
@@ -1,5 +1,3 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m3 1c-1.1046 0-2 0.89543-2 2v10c0 1.1046 0.89543 2 2 2h10c1.1046 0 2-0.89543 2-2v-10c0-1.1046-0.89543-2-2-2h-10zm0 2h10v10h-10v-10zm3 1l2 2 2-2h-4zm-2 2v4l2-2-2-2zm8 0l-2 2 2 2v-4zm-4 4l-2 2h4l-2-2z" fill="#a5efac"/>
-</g>
+<path d="m3 1c-1.1046 0-2 0.89543-2 2v10c0 1.1046 0.89543 2 2 2h10c1.1046 0 2-0.89543 2-2v-10c0-1.1046-0.89543-2-2-2h-10zm0 2h10v10h-10v-10zm3 1l2 2 2-2h-4zm-2 2v4l2-2-2-2zm8 0l-2 2 2 2v-4zm-4 4l-2 2h4l-2-2z" fill="#a5efac"/>
</svg>
diff --git a/editor/icons/icon_color_pick.svg b/editor/icons/icon_color_pick.svg
index 893afb4eb4..5c21eeba8b 100644
--- a/editor/icons/icon_color_pick.svg
+++ b/editor/icons/icon_color_pick.svg
@@ -1,5 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m13.051 0.97852a2 2 0 0 0 -1.4434 0.58594l-1.4141 1.4141-1.416-1.4141-1.4141 1.4141 1.4141 1.4141-7.0703 7.0723-0.35352 1.7676-0.35352 1.7676 1.7676-0.35352 1.7676-0.35352 7.0723-7.0703 1.4141 1.4141 1.4141-1.4141-1.4141-1.416 1.4141-1.4141a2 2 0 0 0 0 -2.8281 2 2 0 0 0 -1.3848 -0.58594zm-3.5664 4.1211l1.416 1.416-7.0723 7.0703-0.70703-0.70703-0.70703-0.70703 7.0703-7.0723z" fill="#e0e0e0" fill-opacity=".99608"/>
+<path transform="translate(0 1036.4)" d="m8 1c-1.108 0-2 0.892-2 2v2h-1v2h1v5a2 2 0 0 0 1 1.7285v1.2715h2v-1.2695a2 2 0 0 0 1 -1.7305v-5h1v-2h-1v-2c0-1.108-0.892-2-2-2zm-1 6h2v5a1 1 0 0 1 -1 1 1 1 0 0 1 -1 -1v-5z" fill="#e0e0e0"/>
</g>
</svg>
diff --git a/editor/icons/icon_color_picker.svg b/editor/icons/icon_color_picker.svg
index 272dfeca48..55c55fe205 100644
--- a/editor/icons/icon_color_picker.svg
+++ b/editor/icons/icon_color_picker.svg
@@ -1,5 +1,3 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m13.051 0.97852a2 2 0 0 0 -1.4434 0.58594l-1.4141 1.4141-1.416-1.4141-1.4141 1.4141 1.4141 1.4141-7.0703 7.0723-0.35352 1.7676-0.35352 1.7676 1.7676-0.35352 1.7676-0.35352 7.0723-7.0703 1.4141 1.4141 1.4141-1.4141-1.4141-1.416 1.4141-1.4141a2 2 0 0 0 0 -2.8281 2 2 0 0 0 -1.3848 -0.58594zm-3.5664 4.1211l1.416 1.416-7.0723 7.0703-0.70703-0.70703-0.70703-0.70703 7.0703-7.0723z" fill="#a5efac"/>
-</g>
+<path d="m8 1c-1.108 0-2 0.892-2 2v2h-1v2h1v5a2 2 0 0 0 1 1.7285v1.2715h2v-1.2695a2 2 0 0 0 1 -1.7305v-5h1v-2h-1v-2c0-1.108-0.892-2-2-2zm-1 6h2v5a1 1 0 0 1 -1 1 1 1 0 0 1 -1 -1v-5z" fill="#a5efac"/>
</svg>
diff --git a/editor/icons/icon_color_picker_button.svg b/editor/icons/icon_color_picker_button.svg
index 5d734a5b20..d8de02b298 100644
--- a/editor/icons/icon_color_picker_button.svg
+++ b/editor/icons/icon_color_picker_button.svg
@@ -1,7 +1,3 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m13.051 0.97852a2 2 0 0 0 -1.4434 0.58594l-1.4141 1.4141-1.416-1.4141-1.4141 1.4141 1.4141 1.4141-7.0703 7.0723-0.35352 1.7676-0.35352 1.7676 1.7676-0.35352 1.7676-0.35352 7.0723-7.0703 1.4141 1.4141 1.4141-1.4141-1.4141-1.416 1.4141-1.4141a2 2 0 0 0 0 -2.8281 2 2 0 0 0 -1.3848 -0.58594zm-3.5664 4.1211 1.416 1.416-7.0723 7.0703-0.70703-0.70703-0.70703-0.70703 7.0703-7.0723z" fill="#a5efac"/>
-<path transform="translate(0 1036.4)" d="m1 3v6.3438l4.9492-4.9512-1.3926-1.3926h-3.5566zm14 6.4863l-1.5137 1.5137h-0.92969l-0.94922-0.94922-2.9492 2.9492h6.3418v-3.5137z" fill="#a5efac"/>
-<path transform="translate(0 1036.4)" d="m10.658 11l-2 2h6.3418v-2h-1.5137-0.92969-1.8984z" fill-opacity=".078431"/>
-</g>
+<path d="m13 1c-1.108 0-2 0.892-2 2v2h-1v2h1v5a2 2 0 0 0 1 1.7285v1.2715h2v-1.2695a2 2 0 0 0 1 -1.7305v-5h1v-2h-1v-2c0-1.108-0.892-2-2-2zm-9 1v3.1328l-1.4453-0.96484-1.1094 1.6641 3 2c0.3359 0.2239 0.77347 0.2239 1.1094 0l3-2-1.1094-1.6641-1.4453 0.96484v-3.1328h-2zm8 5h2v5a1 1 0 0 1 -1 1 1 1 0 0 1 -1 -1v-5zm-8.5 3c-0.831 0-1.5 0.669-1.5 1.5v0.5 1h-1v2h8v-2h-1v-1-0.5c0-0.831-0.669-1.5-1.5-1.5h-3z" fill="#a5efac"/>
</svg>
diff --git a/editor/icons/icon_connection_and_groups.svg b/editor/icons/icon_connection_and_groups.svg
deleted file mode 100644
index 67a73f02b3..0000000000
--- a/editor/icons/icon_connection_and_groups.svg
+++ /dev/null
@@ -1,5 +0,0 @@
-<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m2 0v1 5 1h12v-1-6h-11-1zm1 1h10v5h-10v-5zm2.5 1a1.5 1.5 0 0 0 -1.5 1.5 1.5 1.5 0 0 0 1.5 1.5 1.5 1.5 0 0 0 1.5 -1.5 1.5 1.5 0 0 0 -1.5 -1.5zm5 0a1.5 1.5 0 0 0 -1.5 1.5 1.5 1.5 0 0 0 1.5 1.5 1.5 1.5 0 0 0 1.5 -1.5 1.5 1.5 0 0 0 -1.5 -1.5zm-0.5 7a2 2 0 0 0 -2 2v1h-6v1h6v1a2 2 0 0 0 2 2h2v-1h2v-1h-2v-3h2v-1h-2v-1h-2z" fill="#e0e0e0"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_control_layout.svg b/editor/icons/icon_control_layout.svg
new file mode 100644
index 0000000000..4bf60cf751
--- /dev/null
+++ b/editor/icons/icon_control_layout.svg
@@ -0,0 +1,3 @@
+<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
+<path d="m1 1v14h14v-14zm2 2h3v3h-3zm5 0h5v3h-5zm-5 5h3v5h-3zm5 0h5v5h-5z" fill="#a5efac"/>
+</svg>
diff --git a/editor/icons/icon_edit.svg b/editor/icons/icon_edit.svg
index b1bce158c4..1805aab54f 100644
--- a/editor/icons/icon_edit.svg
+++ b/editor/icons/icon_edit.svg
@@ -1,5 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
-<path d="m1.7071 1047.8-0.70711 3.5356l3.5355-0.7071 7.7782-7.7782-2.8284-2.8284zm9.1924-9.1924 2.8284 2.8285 1.4142-1.4142-2.8284-2.8285z" fill="#e0e0e0"/>
+<path transform="translate(0 1036.4)" d="m7 1c-0.554 0-1 0.446-1 1v2h4v-2c0-0.554-0.446-1-1-1h-2zm-1 4v7l2 3 2-3v-7h-4zm1 1h1v5h-1v-5z" fill="#e0e0e0"/>
</g>
</svg>
diff --git a/editor/icons/icon_edit_key.svg b/editor/icons/icon_edit_key.svg
index 2959900d04..443a9a0455 100644
--- a/editor/icons/icon_edit_key.svg
+++ b/editor/icons/icon_edit_key.svg
@@ -1,6 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#e0e0e0">
-<path d="m1.7071 1047.8-0.70711 3.5356l3.5355-0.7071 7.7782-7.7782-2.8284-2.8284zm9.1924-9.1924 2.8284 2.8285 1.4142-1.4142-2.8284-2.8285z"/>
-<ellipse cx="3.5" cy="1039.9" rx="2.5" ry="2.5"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m12 1c-0.554 0-1 0.446-1 1v2h4v-2c0-0.554-0.446-1-1-1h-2zm-7 3c-0.195 0-0.38964 0.07519-0.53906 0.22461l-3.2363 3.2363c-0.29884 0.29884-0.29884 0.77929 0 1.0781l3.2363 3.2363c0.29884 0.29884 0.77929 0.29884 1.0781 0l3.2363-3.2363c0.29884-0.29884 0.29884-0.77929 0-1.0781l-3.2363-3.2363c-0.14942-0.14942-0.34406-0.22461-0.53906-0.22461zm6 1v7l2 3 2-3v-7h-4zm1 1h1v5h-1v-5z" fill="#e0e0e0"/>
</g>
</svg>
diff --git a/editor/icons/icon_groups.svg b/editor/icons/icon_groups.svg
index 37e40749b8..55cf3c48eb 100644
--- a/editor/icons/icon_groups.svg
+++ b/editor/icons/icon_groups.svg
@@ -1,7 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
-<rect x="1" y="1040.4" width="14" height="8" fill="none" stroke="#e0e0e0" stroke-linejoin="round" stroke-width="2"/>
-<ellipse cx="5" cy="1044.4" rx="2" ry="2" fill="#e0e0e0"/>
-<ellipse cx="11" cy="1044.4" rx="2" ry="2" fill="#e0e0e0"/>
+<path transform="translate(0 1036.4)" d="m2 1a1.0001 1.0001 0 0 0 -1 1v12a1.0001 1.0001 0 0 0 1 1h12a1.0001 1.0001 0 0 0 1 -1v-12a1.0001 1.0001 0 0 0 -1 -1h-12zm1 2h10v10h-10v-10zm5 2a3 3 0 0 0 -3 3 3 3 0 0 0 3 3 3 3 0 0 0 3 -3 3 3 0 0 0 -3 -3z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#e0e0e0" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
</g>
</svg>
diff --git a/editor/icons/icon_h_button_array.svg b/editor/icons/icon_h_button_array.svg
deleted file mode 100644
index 3f95dbbde1..0000000000
--- a/editor/icons/icon_h_button_array.svg
+++ /dev/null
@@ -1,5 +0,0 @@
-<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m4 1v3.1328l-1.4453-0.96484-1.1094 1.6641 3 2c0.3359 0.2239 0.77347 0.2239 1.1094 0l3-2-1.1094-1.6641-1.4453 0.96484v-3.1328h-2zm8 4v2h-2v2h2v2h2v-2h2v-2h-2v-2h-2zm-8.5 4c-0.831 0-1.5 0.669-1.5 1.5v0.5 1h-1v2h8v-2h-1v-1-0.5c0-0.831-0.669-1.5-1.5-1.5h-3z" fill="#a5efac"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_key_move_enabled.svg b/editor/icons/icon_key_position.svg
index 203b697ad2..203b697ad2 100644
--- a/editor/icons/icon_key_move_enabled.svg
+++ b/editor/icons/icon_key_position.svg
diff --git a/editor/icons/icon_key_rotate_enabled.svg b/editor/icons/icon_key_rotation.svg
index 0f975631b2..0f975631b2 100644
--- a/editor/icons/icon_key_rotate_enabled.svg
+++ b/editor/icons/icon_key_rotation.svg
diff --git a/editor/icons/icon_key_scale_enabled.svg b/editor/icons/icon_key_scale.svg
index eaa12fdf0e..eaa12fdf0e 100644
--- a/editor/icons/icon_key_scale_enabled.svg
+++ b/editor/icons/icon_key_scale.svg
diff --git a/editor/icons/icon_kinematic_body.svg b/editor/icons/icon_kinematic_body.svg
index 393e21a529..6f8d69fa53 100644
--- a/editor/icons/icon_kinematic_body.svg
+++ b/editor/icons/icon_kinematic_body.svg
@@ -1,5 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m4 4v1h1v-1h-1zm1 1v1h-1v1h-1v1h-1v1 2h1v-2h1v1 1h1v-1h5v1h1v-2h1v2h1v-2-1h-1v-1h-1v-1h-1v-1h-1v1h-3v-1h-1zm5 0h1v-1h-1v1zm0 6h-2v1h2v-1zm-5 0v1h2v-1h-2zm0-4h1v1h-1v-1zm4 0h1v1h-1v-1z" fill="#fc9c9c" fill-opacity=".99608"/>
+<path transform="translate(0 1036.4)" d="m6 1c-0.55401 0-1 0.44599-1 1v3c0 0.55401 0.44599 1 1 1h1v0.99023a1.0001 1.0001 0 0 0 -0.31641 0.0625l-2.0508 0.68359-0.68359-2.0508a1.0001 1.0001 0 0 0 -0.99023 -0.69727 1.0001 1.0001 0 0 0 -0.9082 1.3281l1 3a1.0001 1.0001 0 0 0 1.2656 0.63281l1.6836-0.56055v0.61133c0 0.040884 0.018715 0.075662 0.023438 0.11523l-4.5781 3.0527a1.0001 1.0001 0 1 0 1.1094 1.6641l5.0566-3.3711 1.4941 2.9863a1.0001 1.0001 0 0 0 1.2109 0.50195l3-1a1.0001 1.0001 0 1 0 -0.63281 -1.8965l-2.1777 0.72461-0.97461-1.9512c0.2759-0.17764 0.46875-0.47227 0.46875-0.82617v-1h1.3828l0.72266 1.4473a1.0001 1.0001 0 1 0 1.7891 -0.89453l-1-2a1.0001 1.0001 0 0 0 -0.89453 -0.55273h-3v-1h1c0.55401 0 1-0.44599 1-1v-3c0-0.55401-0.44599-1-1-1h-4zm0 2h1v2h-1v-2z" fill="#fc9c9c" fill-opacity=".99608"/>
</g>
</svg>
diff --git a/editor/icons/icon_kinematic_body_2d.svg b/editor/icons/icon_kinematic_body_2d.svg
index e269efd12a..51026e5f28 100644
--- a/editor/icons/icon_kinematic_body_2d.svg
+++ b/editor/icons/icon_kinematic_body_2d.svg
@@ -1,5 +1,7 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m4 4v1h1v-1h-1zm1 1v1h-1v1h-1v1h-1v1 2h1v-2h1v1 1h1v-1h5v1h1v-2h1v2h1v-2-1h-1v-1h-1v-1h-1v-1h-1v1h-3v-1h-1zm5 0h1v-1h-1v1zm0 6h-2v1h2v-1zm-5 0v1h2v-1h-2zm0-4h1v1h-1v-1zm4 0h1v1h-1v-1z" fill="#a5b7f3" fill-opacity=".98824"/>
+<g transform="translate(.49212 -.0044019)" fill="#a5b7f5" fill-opacity=".98824">
+<path transform="translate(0 1036.4)" d="m6 1c-0.55401 0-1 0.44599-1 1v3c0 0.55401 0.44599 1 1 1h1v0.99023a1.0001 1.0001 0 0 0 -0.31641 0.0625l-2.0508 0.68359-0.68359-2.0508a1.0001 1.0001 0 0 0 -0.99023 -0.69727 1.0001 1.0001 0 0 0 -0.9082 1.3281l1 3a1.0001 1.0001 0 0 0 1.2656 0.63281l1.6836-0.56055v0.61133c0 0.04088 0.018715 0.07566 0.023437 0.11523l-4.5781 3.0527a1.0001 1.0001 0 1 0 1.1094 1.6641l5.0566-3.3711 1.4941 2.9863a1.0001 1.0001 0 0 0 1.2109 0.50195l3-1a1.0001 1.0001 0 1 0 -0.63281 -1.8965l-2.1777 0.72461-0.97461-1.9512c0.2759-0.17764 0.46875-0.47227 0.46875-0.82617v-1h1.3828l0.72266 1.4473a1.0001 1.0001 0 1 0 1.7891 -0.89453l-1-2a1.0001 1.0001 0 0 0 -0.89453 -0.55273h-3v-1h1c0.55401 0 1-0.44599 1-1v-3c0-0.55401-0.44599-1-1-1zm0 2h1v2h-1z" fill="#a5b7f5" fill-opacity=".98824"/>
+</g>
</g>
</svg>
diff --git a/editor/icons/icon_multi_edit.svg b/editor/icons/icon_multi_edit.svg
index 36f62006e0..9a1cfe8e16 100644
--- a/editor/icons/icon_multi_edit.svg
+++ b/editor/icons/icon_multi_edit.svg
@@ -1,5 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m12.314 0.85742l-1.4141 1.4141 2.8281 2.8281 1.4141-1.4141-2.8281-2.8281zm-11.314 0.14258v2h2v-2h-2zm4 0v2h2v-2h-2zm4.4844 2.6855l-7.7773 7.7793-0.70703 3.5352 3.5352-0.70703 7.7793-7.7773-2.8301-2.8301zm-8.4844 1.3145v2h2v-2h-2z" fill="#e0e0e0"/>
+<path transform="translate(0 1036.4)" d="m2 1c-0.554 0-1 0.446-1 1v2h4v-2c0-0.554-0.446-1-1-1h-2zm-1 4v7l2 3 2-3v-7h-4zm1 1h1v5h-1v-5zm8 1v3h-3v2h3v3h2v-3h3v-2h-3v-3h-2z" fill="#e0e0e0"/>
</g>
</svg>
diff --git a/editor/icons/icon_onion.svg b/editor/icons/icon_onion.svg
new file mode 100644
index 0000000000..5bb2a99423
--- /dev/null
+++ b/editor/icons/icon_onion.svg
@@ -0,0 +1,3 @@
+<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
+<path d="m8 1c-2 2-7 4-7 8s3 6 7 6c-7-3-6.5995-7.703 0-13-2.2981 3.9516-5.4951 8.9197 0 13 4.8692-4.2391 2.7733-8.1815 1-12 5.5855 4.704 5.3995 8.6488-1 12 4 0 7-2 7-6s-5-6-7-8z" fill="#e0e0e0"/>
+</svg>
diff --git a/editor/icons/icon_shader.svg b/editor/icons/icon_shader.svg
new file mode 100644
index 0000000000..659d81519a
--- /dev/null
+++ b/editor/icons/icon_shader.svg
@@ -0,0 +1,12 @@
+<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
+<g>
+<path d="m2 1c-0.55226 1e-4 -0.99994 0.4477-1 1v12c5.52e-5 0.5523 0.44774 0.9999 1 1h12c0.55226-1e-4 0.99994-0.4477 1-1v-8l-5-5zm1 2h6v3c0 0.554 0.44599 1 1 1h3v6h-10z" fill="#e0e0e0"/>
+<path d="m10 11h2v1h-2z" fill="#9f70ff"/>
+<path d="m4 6h2v1h-2z" fill="#ffeb70"/>
+<path d="m8 8h4v1h-4z" fill="#9dff70"/>
+<path d="m7 6h1v1h-1z" fill="#70deff"/>
+<path d="m4 11h5v1h-5z" fill="#ff70ac"/>
+<path d="m4 4h3v1h-3z" fill="#ff7070"/>
+<path d="m4 8h3v1h-3z" fill="#70ffb9"/>
+</g>
+</svg>
diff --git a/editor/icons/icon_connect.svg b/editor/icons/icon_signals.svg
index 97859370b7..97859370b7 100644
--- a/editor/icons/icon_connect.svg
+++ b/editor/icons/icon_signals.svg
diff --git a/editor/icons/icon_signals_and_groups.svg b/editor/icons/icon_signals_and_groups.svg
new file mode 100644
index 0000000000..5dedbaa433
--- /dev/null
+++ b/editor/icons/icon_signals_and_groups.svg
@@ -0,0 +1,5 @@
+<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m6 0c-0.55228 0-1 0.4477-1 1s0.44772 1 1 1c4.4301 0 8 3.5699 8 8 0 0.5523 0.44772 1 1 1s1-0.4477 1-1c0-5.511-4.489-10-10-10zm0 4c-0.55228 0-1 0.4477-1 1s0.44772 1 1 1c2.221 0 4 1.779 4 4 0 0.5523 0.44772 1 1 1s1-0.4477 1-1c0-3.3018-2.6981-6-6-6zm-5 4a1.0001 1.0001 0 0 0 -1 1v6a1.0001 1.0001 0 0 0 1 1h6a1.0001 1.0001 0 0 0 1 -1v-6a1.0001 1.0001 0 0 0 -1 -1h-6zm1 2h4v4h-4v-4z" fill="#e0e0e0"/>
+</g>
+</svg>
diff --git a/editor/icons/icon_sprite.svg b/editor/icons/icon_sprite.svg
index 4feea4d265..09fc2f0979 100644
--- a/editor/icons/icon_sprite.svg
+++ b/editor/icons/icon_sprite.svg
@@ -1,5 +1,3 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m8 1a7 7 0 0 0 -7 7 7 7 0 0 0 7 7 7 7 0 0 0 7 -7 7 7 0 0 0 -7 -7zm-4 5a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1zm8 0a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1zm-7 3h6a3 3 0 0 1 -1.5 2.5977 3 3 0 0 1 -3 0 3 3 0 0 1 -1.5 -2.5977z" fill="#a5b7f3"/>
-</g>
+<path d="m5 1c-2.216 0-4 1.784-4 4v6c0 2.216 1.784 4 4 4h6c2.216 0 4-1.784 4-4v-6c0-2.216-1.784-4-4-4h-6zm-1 5c0.554 0 1 0.446 1 1v2c0 0.554-0.446 1-1 1s-1-0.446-1-1v-2c0-0.554 0.446-1 1-1zm8 0c0.554 0 1 0.446 1 1v2c0 0.554-0.446 1-1 1s-1-0.446-1-1v-2c0-0.554 0.446-1 1-1zm-1.8887 5.1074a1.0001 1.0001 0 0 1 0.7168 1.7207c-0.74987 0.74987-1.7676 1.1719-2.8281 1.1719s-2.0783-0.422-2.8281-1.1719a1.0001 1.0001 0 0 1 0.69727 -1.7168 1.0001 1.0001 0 0 1 0.7168 0.30273c0.37534 0.37535 0.88325 0.58594 1.4141 0.58594s1.0387-0.21059 1.4141-0.58594a1.0001 1.0001 0 0 1 0.69727 -0.30664z" fill="#a5b7f6" fill-opacity=".98824"/>
</svg>
diff --git a/editor/icons/icon_sprite_3d.svg b/editor/icons/icon_sprite_3d.svg
index 0d5caae501..eb163e3f43 100644
--- a/editor/icons/icon_sprite_3d.svg
+++ b/editor/icons/icon_sprite_3d.svg
@@ -1,5 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m8 1a7 7 0 0 0 -7 7 7 7 0 0 0 7 7 7 7 0 0 0 7 -7 7 7 0 0 0 -7 -7zm-4 5a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1zm8 0a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1zm-7 3h6a3 3 0 0 1 -1.5 2.5977 3 3 0 0 1 -3 0 3 3 0 0 1 -1.5 -2.5977z" fill="#fc9c9c" fill-opacity=".99608"/>
+<g fill="#fc9c9c">
+<path d="m5 1c-2.216 0-4 1.784-4 4v6c0 2.216 1.784 4 4 4h6c2.216 0 4-1.784 4-4v-6c0-2.216-1.784-4-4-4zm-1 5c0.554 0 1 0.446 1 1v2c0 0.554-0.446 1-1 1s-1-0.446-1-1v-2c0-0.554 0.446-1 1-1zm8 0c0.554 0 1 0.446 1 1v2c0 0.554-0.446 1-1 1s-1-0.446-1-1v-2c0-0.554 0.446-1 1-1zm-1.8887 5.1074a1.0001 1.0001 0 0 1 0.7168 1.7207c-0.74987 0.74987-1.7676 1.1719-2.8281 1.1719s-2.0783-0.422-2.8281-1.1719a1.0001 1.0001 0 0 1 0.69727 -1.7168 1.0001 1.0001 0 0 1 0.7168 0.30273c0.37534 0.37535 0.88325 0.58594 1.4141 0.58594s1.0387-0.21059 1.4141-0.58594a1.0001 1.0001 0 0 1 0.69727 -0.30664z" fill="#fc9c9c"/>
</g>
</svg>
diff --git a/editor/icons/icon_sprite_frames.svg b/editor/icons/icon_sprite_frames.svg
index e797819892..8123cbd6b4 100644
--- a/editor/icons/icon_sprite_frames.svg
+++ b/editor/icons/icon_sprite_frames.svg
@@ -1,5 +1,3 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m6 1a5 5 0 0 0 -5 5 5 5 0 0 0 5 5 5 5 0 0 0 5 -5 5 5 0 0 0 -5 -5zm-3 4a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1zm6 0a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1zm4 2v2h2v-2h-2zm-5.0039 0.49219a0.50005 0.50005 0 0 1 0.35742 0.86133c-0.61785 0.6179-1.4924 0.89648-2.3535 0.89648s-1.7357-0.27858-2.3535-0.89648a0.50005 0.50005 0 0 1 0.34766 -0.85742 0.50005 0.50005 0 0 1 0.35938 0.15039c0.38215 0.3822 1.0076 0.60352 1.6465 0.60352s1.2643-0.22132 1.6465-0.60352a0.50005 0.50005 0 0 1 0.34961 -0.1543zm2.0039 2.5078v2h2v-2h-2zm3 0v2h2v-2h-2zm-6 3v2h2v-2h-2zm3 0v2h2v-2h-2zm3 0v2h2v-2h-2z" fill="#e0e0e0"/>
-</g>
+<path d="m3 1c-1.108 0-2 0.89199-2 2v6c0 1.108 0.89199 2 2 2h6c1.108 0 2-0.89199 2-2v-6c0-1.108-0.89199-2-2-2h-6zm10 0v2h2v-2h-2zm-10 4c0.554 0 1 0.446 1 1v1c0 0.554-0.446 1-1 1s-1-0.446-1-1v-1c0-0.554 0.446-1 1-1zm6 0c0.554 0 1 0.446 1 1v1c0 0.554-0.446 1-1 1s-1-0.446-1-1v-1c0-0.554 0.446-1 1-1zm4 0v2h2v-2h-2zm-9 4h2 2a2 1 0 0 1 -1 0.86523 2 1 0 0 1 -2 0 2 1 0 0 1 -1 -0.86523zm9 0v2h2v-2h-2zm-12 4v2h2v-2h-2zm4 0v2h2v-2h-2zm4 0v2h2v-2h-2zm4 0v2h2v-2h-2z" fill="#e0e0e0"/>
</svg>
diff --git a/editor/icons/icon_texture_button.svg b/editor/icons/icon_texture_button.svg
index 17f87ab861..19f5e8d5c9 100644
--- a/editor/icons/icon_texture_button.svg
+++ b/editor/icons/icon_texture_button.svg
@@ -1,7 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m1 3v8h14v-8h-1-12-1zm8 2h1v1h1v2h1v2h-2-2-2-2v-1h1v-1h1v-1h2v-1h1v-1z" fill="#a5efac"/>
-<rect transform="scale(1,-1)" x="1" y="-1049.4" width="14" height="2.0001" fill="#a5efac"/>
-<rect transform="scale(1,-1)" x="1" y="-1049.4" width="14" height="2.0001" fill-opacity=".078431"/>
+<path transform="translate(0 1036.4)" d="m8 1v2h6v10h-4v2h6v-14h-8zm-5 1v3.1328l-1.4453-0.96484-1.1094 1.6641 3 2c0.3359 0.2239 0.77347 0.2239 1.1094 0l3-2-1.1094-1.6641-1.4453 0.96484v-3.1328h-2zm7 4v1h-1v1h-1v1h1v2h2 2v-2h-1v-2h-1v-1h-1zm-7.5 4c-0.831 0-1.5 0.669-1.5 1.5v0.5 1h-1v2h8v-2h-1v-1-0.5c0-0.831-0.669-1.5-1.5-1.5h-3z" fill="#a5efac"/>
</g>
</svg>
diff --git a/editor/icons/icon_texture_rect.svg b/editor/icons/icon_texture_rect.svg
index 86d24ac223..2dbbe7f247 100644
--- a/editor/icons/icon_texture_rect.svg
+++ b/editor/icons/icon_texture_rect.svg
@@ -1,6 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
-<rect x="2" y="1038.4" width="12" height="12" fill="none" stroke="#a5efac" stroke-linecap="round" stroke-width="2"/>
-<path d="m9 1042.4v1h-1v1h-2v1h-1v1h-1v1h2 2 2 2v-2h-1v-2h-1v-1h-1z" fill="#a5efac"/>
+<path transform="translate(0 1036.4)" d="m1 1v14h14v-14h-14zm2 2h10v10h-10v-10zm6 3v1h-1v1h-2v1h-1v1h-1v1h2 2 2 2v-2h-1v-2h-1v-1h-1z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#a5efac" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
</g>
</svg>
diff --git a/editor/icons/icon_v_button_array.svg b/editor/icons/icon_v_button_array.svg
deleted file mode 100644
index ac7ce6064c..0000000000
--- a/editor/icons/icon_v_button_array.svg
+++ /dev/null
@@ -1,6 +0,0 @@
-<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#a5efac">
-<path transform="translate(0 1036.4)" d="m7 1v2.1328l-1.4453-0.96484-1.1094 1.6641 3 2c0.3359 0.2239 0.77347 0.2239 1.1094 0l3-2-1.1094-1.6641-1.4453 0.96484v-2.1328h-2zm-0.5 6c-0.831 0-1.5 0.669-1.5 1.5v0.5h-1v2h2v-2h4v2h2v-2h-1v-0.5c0-0.831-0.669-1.5-1.5-1.5h-3z"/>
-<path d="m7 1046.4v2h-2v2h2v2h2v-2h2v-2h-2v-2z"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_viewport_speed.svg b/editor/icons/icon_viewport_speed.svg
new file mode 100644
index 0000000000..e64b5a8059
--- /dev/null
+++ b/editor/icons/icon_viewport_speed.svg
@@ -0,0 +1,4 @@
+<svg width="16" height="16" version="1.1" viewBox="0 0 4.2333333 4.2333333" xmlns="http://www.w3.org/2000/svg">
+<path d="m1.5875 0c-0.28858 0-0.52917 0.24059-0.52917 0.52917v0.61132c-0.085589-0.051-0.18113-0.0891-0.28525-0.0853-0.34849 0.0127-0.5952 0.37346-0.48059 0.70278l0.26355 0.79066c0.048664 0.14623 0.15979 0.24805 0.29249 0.30644l-0.60927 0.40669c-0.13121 0.0845-0.22102 0.22389-0.24133 0.3633-0.020312 0.13941 0.017471 0.26985 0.087333 0.37465s0.17614 0.19045 0.31264 0.22532c0.13634 0.0348 0.29946 6e-3 0.42788-0.0827h5.159e-4l1.0852-0.72348 0.26097 0.52192c0.11682 0.23391 0.39274 0.34829 0.64079 0.26561l0.79375-0.26458-0.00775 3e-3c0.15105-0.0454 0.27732-0.15615 0.33486-0.2863 0.057538-0.13015 0.055144-0.26773 0.014986-0.38809-0.03156-0.0946-0.10972-0.1687-0.19275-0.23617 0.069099-0.0546 0.1445-0.10364 0.18035-0.19325 0.051761-0.12941 0.045257-0.29292-0.02377-0.43098l-0.26459-0.52946c-0.089407-0.17933-0.27348-0.29308-0.47335-0.29305h-0.1111c0.052029-0.0817 0.1111-0.16214 0.1111-0.26458v-0.79375c0-0.28858-0.24059-0.52917-0.52917-0.52917z" color="#000000" color-rendering="auto" dominant-baseline="auto" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
+<path d="m1.5875 0.26458c-0.14658 0-0.26458 0.118-0.26458 0.26459v0.79375c0 0.14658 0.118 0.26458 0.26458 0.26458h0.26458v0.262a0.26461 0.26461 0 0 0 -0.083716 0.0165l-0.5426 0.18086-0.18087-0.5426a0.26461 0.26461 0 0 0 -0.262 -0.18448 0.26461 0.26461 0 0 0 -0.2403 0.3514l0.26458 0.79375a0.26461 0.26461 0 0 0 0.33486 0.16743l0.44545-0.14831v0.16174c0 0.0108 0.00495 0.02 0.0062 0.0305l-1.2113 0.80771a0.26461 0.26461 0 1 0 0.29352 0.44028l1.3379-0.89194 0.39532 0.79014a0.26461 0.26461 0 0 0 0.32039 0.1328l0.79375-0.26458a0.26461 0.26461 0 1 0 -0.16743 -0.50175l-0.57619 0.19172-0.25787-0.51625c0.072998-0.047 0.12402-0.12495 0.12402-0.21859v-0.26458h0.36587l0.1912 0.38292a0.26461 0.26461 0 1 0 0.47336 -0.23668l-0.26458-0.52916a0.26461 0.26461 0 0 0 -0.23668 -0.14625h-0.79375v-0.26458h0.26458c0.14658 0 0.26458-0.118 0.26458-0.26458v-0.79375c0-0.14659-0.118-0.26459-0.26458-0.26459zm0 0.52917h0.26458v0.52917h-0.26458z" fill="#fff" fill-opacity=".99608"/>
+</svg>
diff --git a/editor/icons/icon_viewport_sprite.svg b/editor/icons/icon_viewport_sprite.svg
deleted file mode 100644
index 4b8bbeaeba..0000000000
--- a/editor/icons/icon_viewport_sprite.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)">
-<rect x="20" y="1042.4" width="1" height="1" fill="#fefeff"/>
-<rect x="29" y="1042.4" width="1" height="1" fill="#fefeff"/>
-<path transform="translate(0 1036.4)" d="m3 2c-0.5304 8.01e-5 -1.0391 0.21085-1.4141 0.58594-0.37509 0.37501-0.58586 0.88366-0.58594 1.4141v8c8.03e-5 0.5304 0.21085 1.0391 0.58594 1.4141 0.37501 0.37509 0.88366 0.58586 1.4141 0.58594h10c1.1046 0 2-0.89543 2-2v-8c0-1.1046-0.89543-2-2-2h-10zm0 1h10c0.55228 9.6e-6 0.99999 0.44772 1 1v8c-1e-5 0.55228-0.44772 0.99999-1 1h-10c-0.55228-1e-5 -0.99999-0.44772-1-1v-8c9.6e-6 -0.55228 0.44772-0.99999 1-1zm1 3v2h2v-2h-2zm6 0v2h2v-2h-2zm-6 3v1h8v-1h-8z" fill="#a5b7f3" fill-opacity=".98824"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_viewport_zoom.svg b/editor/icons/icon_viewport_zoom.svg
new file mode 100644
index 0000000000..18d4ec32ce
--- /dev/null
+++ b/editor/icons/icon_viewport_zoom.svg
@@ -0,0 +1,6 @@
+<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
+<g>
+<path d="m6 0c-3.3019 0-6 2.6981-6 6s2.6981 6 6 6h0.00195c0.88828 0 1.737-0.2588 2.5332-0.6367l3.8281 3.8281c0.39053 0.3904 1.0235 0.3904 1.4141 0l1.4141-1.4141c0.39033-0.3905 0.39033-1.0235 0-1.414l-3.791-3.791c0.02779-0.058 0.06588-0.1109 0.0918-0.17 0.05554-0.1268 0.08414-0.2638 0.08398-0.4023h1.4238c0.55226-1e-4 0.99994-0.4477 1-1v-1h1c0.55226-1e-4 0.99994-0.4477 1-1v-2c-5.5e-5 -0.5523-0.44774-0.9999-1-1h-1v-1c-5.5e-5 -0.5523-0.44774-0.9999-1-1h-2c-0.55226 1e-4 -0.99994 0.4477-1 1v1h-0.00977c1.44e-4 -0.3151-0.14822-0.6118-0.40039-0.8008-1.0353-0.7764-2.2938-1.1967-3.5879-1.1992h-0.00195z" color="#000000" color-rendering="auto" dominant-baseline="auto" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
+<path d="m6 1a5 5 0 0 0 -5 5 5 5 0 0 0 5 5 5 5 0 0 0 2.752 -0.83398l4.3184 4.3184 1.4141-1.4141-4.3184-4.3184a5 5 0 0 0 0.41016 -0.75195h-0.57617v-2h-1a3 3 0 0 1 -3 3 3 3 0 0 1 -3 -3 3 3 0 0 1 3 -3 3 3 0 0 1 2 0.76758v-1.7676h0.99023a5 5 0 0 0 -2.9902 -1zm5 0v2h-2v2h2v2h2v-2h2v-2h-2v-2z" fill="#fff"/>
+</g>
+</svg>
diff --git a/editor/import/editor_import_collada.cpp b/editor/import/editor_import_collada.cpp
index 6ef1758363..3c73411dee 100644
--- a/editor/import/editor_import_collada.cpp
+++ b/editor/import/editor_import_collada.cpp
@@ -88,10 +88,10 @@ struct ColladaImport {
Error _populate_skeleton(Skeleton *p_skeleton, Collada::Node *p_node, int &r_bone, int p_parent);
Error _create_scene_skeletons(Collada::Node *p_node);
Error _create_scene(Collada::Node *p_node, Spatial *p_parent);
- Error _create_resources(Collada::Node *p_node);
+ Error _create_resources(Collada::Node *p_node, bool p_use_compression);
Error _create_material(const String &p_target);
- Error _create_mesh_surfaces(bool p_optimize, Ref<ArrayMesh> &p_mesh, const Map<String, Collada::NodeGeometry::Material> &p_material_map, const Collada::MeshData &meshdata, const Transform &p_local_xform, const Vector<int> &bone_remap, const Collada::SkinControllerData *p_skin_controller, const Collada::MorphControllerData *p_morph_data, Vector<Ref<ArrayMesh> > p_morph_meshes = Vector<Ref<ArrayMesh> >(), bool p_for_morph = false, bool p_use_mesh_material = false);
- Error load(const String &p_path, int p_flags, bool p_force_make_tangents = false);
+ Error _create_mesh_surfaces(bool p_optimize, Ref<ArrayMesh> &p_mesh, const Map<String, Collada::NodeGeometry::Material> &p_material_map, const Collada::MeshData &meshdata, const Transform &p_local_xform, const Vector<int> &bone_remap, const Collada::SkinControllerData *p_skin_controller, const Collada::MorphControllerData *p_morph_data, Vector<Ref<ArrayMesh> > p_morph_meshes = Vector<Ref<ArrayMesh> >(), bool p_use_compression = false, bool p_use_mesh_material = false);
+ Error load(const String &p_path, int p_flags, bool p_force_make_tangents = false, bool p_use_compression = false);
void _fix_param_animation_tracks();
void create_animation(int p_clip, bool p_make_tracks_in_all_bones, bool p_import_value_tracks);
void create_animations(bool p_make_tracks_in_all_bones, bool p_import_value_tracks);
@@ -608,7 +608,7 @@ static void _generate_tangents_and_binormals(const PoolVector<int> &p_indices, c
}
}
-Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<ArrayMesh> &p_mesh, const Map<String, Collada::NodeGeometry::Material> &p_material_map, const Collada::MeshData &meshdata, const Transform &p_local_xform, const Vector<int> &bone_remap, const Collada::SkinControllerData *p_skin_controller, const Collada::MorphControllerData *p_morph_data, Vector<Ref<ArrayMesh> > p_morph_meshes, bool p_for_morph, bool p_use_mesh_material) {
+Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<ArrayMesh> &p_mesh, const Map<String, Collada::NodeGeometry::Material> &p_material_map, const Collada::MeshData &meshdata, const Transform &p_local_xform, const Vector<int> &bone_remap, const Collada::SkinControllerData *p_skin_controller, const Collada::MorphControllerData *p_morph_data, Vector<Ref<ArrayMesh> > p_morph_meshes, bool p_use_compression, bool p_use_mesh_material) {
bool local_xform_mirror = p_local_xform.basis.determinant() < 0;
@@ -1106,7 +1106,6 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<ArrayMesh> &p_me
for (int mi = 0; mi < p_morph_meshes.size(); mi++) {
- //print_line("want surface "+itos(mi)+" has "+itos(p_morph_meshes[mi]->get_surface_count()));
Array a = p_morph_meshes[mi]->surface_get_arrays(surface);
//add valid weight and bone arrays if they exist, TODO check if they are unique to shape (generally not)
@@ -1120,7 +1119,7 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<ArrayMesh> &p_me
mr.push_back(a);
}
- p_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, d, mr, p_for_morph ? 0 : Mesh::ARRAY_COMPRESS_DEFAULT);
+ p_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, d, mr, p_use_compression ? Mesh::ARRAY_COMPRESS_DEFAULT : 0);
if (material.is_valid()) {
if (p_use_mesh_material) {
@@ -1140,7 +1139,7 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<ArrayMesh> &p_me
return OK;
}
-Error ColladaImport::_create_resources(Collada::Node *p_node) {
+Error ColladaImport::_create_resources(Collada::Node *p_node, bool p_use_compression) {
if (p_node->type == Collada::Node::TYPE_GEOMETRY && node_map.has(p_node->id)) {
@@ -1187,9 +1186,6 @@ Error ColladaImport::_create_resources(Collada::Node *p_node) {
if (cd.control_vertices.has("TILT") && cd.sources.has(cd.control_vertices["TILT"]))
tilts = &cd.sources[cd.control_vertices["TILT"]];
- if (tilts) {
- print_line("FOUND TILTS!!!");
- }
int pc = vertices.array.size() / 3;
for (int i = 0; i < pc; i++) {
@@ -1237,12 +1233,8 @@ Error ColladaImport::_create_resources(Collada::Node *p_node) {
Vector<int> bone_remap;
Vector<Ref<ArrayMesh> > morphs;
- print_line("mesh: " + String(mi->get_name()));
-
if (ng->controller) {
- print_line("has controller");
-
String ngsource = ng->source;
if (collada.state.skin_controller_data_map.has(ngsource)) {
@@ -1255,9 +1247,6 @@ Error ColladaImport::_create_resources(Collada::Node *p_node) {
ERR_FAIL_COND_V(skeletons.empty(), ERR_INVALID_DATA);
String skname = skeletons[0];
- if (!node_map.has(skname)) {
- print_line("no node for skeleton " + skname);
- }
ERR_FAIL_COND_V(!node_map.has(skname), ERR_INVALID_DATA);
NodeMap nmsk = node_map[skname];
Skeleton *sk = Object::cast_to<Skeleton>(nmsk.node);
@@ -1295,22 +1284,16 @@ Error ColladaImport::_create_resources(Collada::Node *p_node) {
for (int i = 0; i < bone_remap.size(); i++) {
String str = joint_src->sarray[i];
- if (!bone_remap_map.has(str)) {
- print_line("bone not found for remap: " + str);
- print_line("in skeleton: " + skname);
- }
ERR_FAIL_COND_V(!bone_remap_map.has(str), ERR_INVALID_DATA);
bone_remap[i] = bone_remap_map[str];
}
}
if (collada.state.morph_controller_data_map.has(ngsource)) {
- print_line("is morph " + ngsource);
+
//it's a morph!!
morph = &collada.state.morph_controller_data_map[ngsource];
meshid = morph->mesh;
- printf("KKmorph: %p\n", morph);
- print_line("morph mshid: " + meshid);
Vector<String> targets;
@@ -1326,7 +1309,7 @@ Error ColladaImport::_create_resources(Collada::Node *p_node) {
if (collada.state.mesh_data_map.has(meshid)) {
Ref<ArrayMesh> mesh = Ref<ArrayMesh>(memnew(ArrayMesh));
const Collada::MeshData &meshdata = collada.state.mesh_data_map[meshid];
- Error err = _create_mesh_surfaces(false, mesh, ng->material_map, meshdata, apply_xform, bone_remap, skin, NULL, Vector<Ref<ArrayMesh> >(), true);
+ Error err = _create_mesh_surfaces(false, mesh, ng->material_map, meshdata, apply_xform, bone_remap, skin, NULL, Vector<Ref<ArrayMesh> >(), false);
ERR_FAIL_COND_V(err, err);
morphs.push_back(mesh);
@@ -1362,7 +1345,7 @@ Error ColladaImport::_create_resources(Collada::Node *p_node) {
mesh = Ref<ArrayMesh>(memnew(ArrayMesh));
const Collada::MeshData &meshdata = collada.state.mesh_data_map[meshid];
mesh->set_name(meshdata.name);
- Error err = _create_mesh_surfaces(morphs.size() == 0, mesh, ng->material_map, meshdata, apply_xform, bone_remap, skin, morph, morphs, false, use_mesh_builtin_materials);
+ Error err = _create_mesh_surfaces(morphs.size() == 0, mesh, ng->material_map, meshdata, apply_xform, bone_remap, skin, morph, morphs, p_use_compression, use_mesh_builtin_materials);
ERR_FAIL_COND_V(err, err);
mesh_cache[meshid] = mesh;
@@ -1405,14 +1388,14 @@ Error ColladaImport::_create_resources(Collada::Node *p_node) {
for (int i = 0; i < p_node->children.size(); i++) {
- Error err = _create_resources(p_node->children[i]);
+ Error err = _create_resources(p_node->children[i], p_use_compression);
if (err)
return err;
}
return OK;
}
-Error ColladaImport::load(const String &p_path, int p_flags, bool p_force_make_tangents) {
+Error ColladaImport::load(const String &p_path, int p_flags, bool p_force_make_tangents, bool p_use_compression) {
Error err = collada.load(p_path, p_flags);
ERR_FAIL_COND_V(err, err);
@@ -1447,7 +1430,7 @@ Error ColladaImport::load(const String &p_path, int p_flags, bool p_force_make_t
ERR_FAIL_COND_V(err, err);
}
- Error err2 = _create_resources(vs.root_nodes[i]);
+ Error err2 = _create_resources(vs.root_nodes[i], p_use_compression);
if (err2 != OK) {
memdelete(scene);
ERR_FAIL_COND_V(err2, err2);
@@ -1950,7 +1933,7 @@ Node *EditorSceneImporterCollada::import_scene(const String &p_path, uint32_t p_
state.use_mesh_builtin_materials = !(p_flags & IMPORT_MATERIALS_IN_INSTANCES);
state.bake_fps = p_bake_fps;
- Error err = state.load(p_path, flags, p_flags & EditorSceneImporter::IMPORT_GENERATE_TANGENT_ARRAYS);
+ Error err = state.load(p_path, flags, p_flags & EditorSceneImporter::IMPORT_GENERATE_TANGENT_ARRAYS, p_flags & EditorSceneImporter::IMPORT_USE_COMPRESSION);
ERR_FAIL_COND_V(err != OK, NULL);
diff --git a/editor/import/editor_scene_importer_gltf.cpp b/editor/import/editor_scene_importer_gltf.cpp
index 831eb74b66..397bb6ad68 100644
--- a/editor/import/editor_scene_importer_gltf.cpp
+++ b/editor/import/editor_scene_importer_gltf.cpp
@@ -1,5 +1,6 @@
#include "editor_scene_importer_gltf.h"
#include "io/json.h"
+#include "math_defs.h"
#include "os/file_access.h"
#include "os/os.h"
#include "scene/3d/camera.h"
@@ -1378,8 +1379,8 @@ Error EditorSceneImporterGLTF::_parse_skins(GLTFState &state) {
state.nodes[skin_node]->skeleton_children.push_back(i);
}
- state.skins.push_back(skin);
}
+ state.skins.push_back(skin);
}
print_line("total skins: " + itos(state.skins.size()));
@@ -1419,7 +1420,8 @@ Error EditorSceneImporterGLTF::_parse_cameras(GLTFState &state) {
camera.perspective = true;
if (d.has("perspective")) {
Dictionary ppt = d["perspective"];
- camera.fov_size = ppt["yfov"];
+ // GLTF spec is in radians, Godot's camera is in degrees.
+ camera.fov_size = (double)ppt["yfov"] * 180.0 / Math_PI;
camera.zfar = ppt["zfar"];
camera.znear = ppt["znear"];
} else {
diff --git a/editor/import/resource_importer_obj.cpp b/editor/import/resource_importer_obj.cpp
index 4541c77085..bd24aac99b 100644
--- a/editor/import/resource_importer_obj.cpp
+++ b/editor/import/resource_importer_obj.cpp
@@ -413,6 +413,7 @@ Node *EditorOBJImporter::import_scene(const String &p_path, uint32_t p_flags, in
for (List<Ref<Mesh> >::Element *E = meshes.front(); E; E = E->next()) {
MeshInstance *mi = memnew(MeshInstance);
+ mi->set_mesh(E->get());
mi->set_name(E->get()->get_name());
scene->add_child(mi);
mi->set_owner(scene);
diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp
index 6d5ff822ef..63d4039295 100644
--- a/editor/import/resource_importer_scene.cpp
+++ b/editor/import/resource_importer_scene.cpp
@@ -232,16 +232,26 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Array
}
}
- if (_teststr(name, "colonly")) {
+ if (_teststr(name, "colonly") || _teststr(name, "convcolonly")) {
if (isroot)
return p_node;
MeshInstance *mi = Object::cast_to<MeshInstance>(p_node);
if (mi) {
- Node *col = mi->create_trimesh_collision_node();
- ERR_FAIL_COND_V(!col, NULL);
+ Node *col;
+
+ if (_teststr(name, "colonly")) {
+ col = mi->create_trimesh_collision_node();
+ ERR_FAIL_COND_V(!col, NULL);
+
+ col->set_name(_fixstr(name, "colonly"));
+ } else {
+ col = mi->create_convex_collision_node();
+ ERR_FAIL_COND_V(!col, NULL);
+
+ col->set_name(_fixstr(name, "convcolonly"));
+ }
- col->set_name(_fixstr(name, "colonly"));
Object::cast_to<Spatial>(col)->set_transform(mi->get_transform());
p_node->replace_by(col);
memdelete(p_node);
@@ -292,7 +302,7 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Array
// get mesh instance and bounding box
MeshInstance *mi = Object::cast_to<MeshInstance>(p_node);
- Rect3 aabb = mi->get_aabb();
+ AABB aabb = mi->get_aabb();
// create a new rigid body collision node
RigidBody *rigid_body = memnew(RigidBody);
@@ -328,15 +338,25 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Array
rb->add_child(colshape);
colshape->set_owner(p_node->get_owner());
- } else if (_teststr(name, "col") && Object::cast_to<MeshInstance>(p_node)) {
+ } else if ((_teststr(name, "col") || (_teststr(name, "convcol"))) && Object::cast_to<MeshInstance>(p_node)) {
MeshInstance *mi = Object::cast_to<MeshInstance>(p_node);
+ Node *col;
- mi->set_name(_fixstr(name, "col"));
- Node *col = mi->create_trimesh_collision_node();
- ERR_FAIL_COND_V(!col, NULL);
+ if (_teststr(name, "col")) {
+ mi->set_name(_fixstr(name, "col"));
+ col = mi->create_trimesh_collision_node();
+ ERR_FAIL_COND_V(!col, NULL);
+
+ col->set_name("col");
+ } else {
+ mi->set_name(_fixstr(name, "convcol"));
+ col = mi->create_convex_collision_node();
+ ERR_FAIL_COND_V(!col, NULL);
+
+ col->set_name("convcol");
+ }
- col->set_name("col");
p_node->add_child(col);
StaticBody *sb = Object::cast_to<StaticBody>(col);
@@ -527,26 +547,55 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Array
#endif
} else if (Object::cast_to<MeshInstance>(p_node)) {
- //last attempt, maybe collision insde the mesh data
+ //last attempt, maybe collision inside the mesh data
MeshInstance *mi = Object::cast_to<MeshInstance>(p_node);
Ref<ArrayMesh> mesh = mi->get_mesh();
if (!mesh.is_null()) {
- if (_teststr(mesh->get_name(), "col")) {
-
- mesh->set_name(_fixstr(mesh->get_name(), "col"));
+ if (_teststr(mesh->get_name(), "col") || _teststr(mesh->get_name(), "convcol")) {
Ref<Shape> shape;
+ if (_teststr(mesh->get_name(), "col")) {
+ mesh->set_name(_fixstr(mesh->get_name(), "col"));
- if (collision_map.has(mesh)) {
- shape = collision_map[mesh];
+ if (collision_map.has(mesh)) {
+ shape = collision_map[mesh];
- } else {
+ } else {
+
+ shape = mesh->create_trimesh_shape();
+ if (!shape.is_null())
+ collision_map[mesh] = shape;
+ }
+ } else if (_teststr(mesh->get_name(), "convcol")) {
+ mesh->set_name(_fixstr(mesh->get_name(), "convcol"));
+
+ if (collision_map.has(mesh)) {
+ shape = collision_map[mesh];
+
+ } else {
+
+ shape = mesh->create_convex_shape();
+ if (!shape.is_null())
+ collision_map[mesh] = shape;
+ }
+ }
+
+ if (!shape.is_null()) {
+ StaticBody *col = memnew(StaticBody);
+ CollisionShape *cshape = memnew(CollisionShape);
+ cshape->set_shape(shape);
+ col->add_child(cshape);
+
+ col->set_transform(mi->get_transform());
+ col->set_name(mi->get_name());
+ p_node->replace_by(col);
+ memdelete(p_node);
+ p_node = col;
- shape = mesh->create_trimesh_shape();
- if (!shape.is_null())
- collision_map[mesh] = shape;
+ cshape->set_name("shape");
+ cshape->set_owner(p_node->get_owner());
}
}
}
@@ -858,12 +907,11 @@ void ResourceImporterScene::_make_external_resources(Node *p_node, const String
String ext_name = p_base_path.plus_file(_make_extname(mat->get_name()) + ".material");
if (p_keep_materials && FileAccess::exists(ext_name)) {
//if exists, use it
- Ref<Material> existing = ResourceLoader::load(ext_name);
- p_materials[mat] = existing;
+ p_materials[mat] = ResourceLoader::load(ext_name);
} else {
ResourceSaver::save(ext_name, mat, ResourceSaver::FLAG_CHANGE_PATH);
- p_materials[mat] = mat;
+ p_materials[mat] = ResourceLoader::load(ext_name);
}
}
@@ -887,7 +935,8 @@ void ResourceImporterScene::_make_external_resources(Node *p_node, const String
String ext_name = p_base_path.plus_file(_make_extname(mesh->get_name()) + ".mesh");
ResourceSaver::save(ext_name, mesh, ResourceSaver::FLAG_CHANGE_PATH);
- p_meshes[mesh] = mesh;
+ p_meshes[mesh] = ResourceLoader::load(ext_name);
+ p_node->set(E->get().name, p_meshes[mesh]);
mesh_just_added = true;
}
}
@@ -907,18 +956,24 @@ void ResourceImporterScene::_make_external_resources(Node *p_node, const String
;
if (FileAccess::exists(ext_name)) {
//if exists, use it
- Ref<Material> existing = ResourceLoader::load(ext_name);
- p_materials[mat] = existing;
+ p_materials[mat] = ResourceLoader::load(ext_name);
} else {
ResourceSaver::save(ext_name, mat, ResourceSaver::FLAG_CHANGE_PATH);
- p_materials[mat] = mat;
+ p_materials[mat] = ResourceLoader::load(ext_name);
}
}
if (p_materials[mat] != mat) {
mesh->surface_set_material(i, p_materials[mat]);
+
+ //re-save the mesh since a material is now assigned
+ if (p_make_meshes) {
+ String ext_name = p_base_path.plus_file(_make_extname(mesh->get_name()) + ".mesh");
+ ResourceSaver::save(ext_name, mesh, ResourceSaver::FLAG_CHANGE_PATH);
+ p_meshes[mesh] = ResourceLoader::load(ext_name);
+ }
}
}
@@ -1037,6 +1092,9 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p
if (bool(p_options["animation/import"]))
import_flags |= EditorSceneImporter::IMPORT_ANIMATION;
+ if (int(p_options["meshes/compress"]))
+ import_flags |= EditorSceneImporter::IMPORT_USE_COMPRESSION;
+
if (bool(p_options["meshes/ensure_tangents"]))
import_flags |= EditorSceneImporter::IMPORT_GENERATE_TANGENT_ARRAYS;
diff --git a/editor/import/resource_importer_scene.h b/editor/import/resource_importer_scene.h
index 9c7e791719..5bf3145148 100644
--- a/editor/import/resource_importer_scene.h
+++ b/editor/import/resource_importer_scene.h
@@ -51,7 +51,8 @@ public:
IMPORT_ANIMATION_KEEP_VALUE_TRACKS = 32,
IMPORT_GENERATE_TANGENT_ARRAYS = 256,
IMPORT_FAIL_ON_MISSING_DEPENDENCIES = 512,
- IMPORT_MATERIALS_IN_INSTANCES = 1024
+ IMPORT_MATERIALS_IN_INSTANCES = 1024,
+ IMPORT_USE_COMPRESSION = 2048
};
diff --git a/editor/import_dock.cpp b/editor/import_dock.cpp
index 77fd6d883a..84d55b4d14 100644
--- a/editor/import_dock.cpp
+++ b/editor/import_dock.cpp
@@ -87,23 +87,7 @@ void ImportDock::set_edit_path(const String &p_path) {
return;
}
- List<ResourceImporter::ImportOption> options;
- params->importer->get_import_options(&options);
-
- params->properties.clear();
- params->values.clear();
-
- for (List<ResourceImporter::ImportOption>::Element *E = options.front(); E; E = E->next()) {
-
- params->properties.push_back(E->get().option);
- if (config->has_section_key("params", E->get().option.name)) {
- params->values[E->get().option.name] = config->get_value("params", E->get().option.name);
- } else {
- params->values[E->get().option.name] = E->get().default_value;
- }
- }
-
- params->update();
+ _update_options(config);
List<Ref<ResourceImporter> > importers;
ResourceFormatImporter::get_singleton()->get_importers_for_extension(p_path.get_extension(), &importers);
@@ -125,6 +109,34 @@ void ImportDock::set_edit_path(const String &p_path) {
}
}
+ params->paths.clear();
+ params->paths.push_back(p_path);
+ import->set_disabled(false);
+ import_as->set_disabled(false);
+
+ imported->set_text(p_path.get_file());
+}
+
+void ImportDock::_update_options(const Ref<ConfigFile> &p_config) {
+
+ List<ResourceImporter::ImportOption> options;
+ params->importer->get_import_options(&options);
+
+ params->properties.clear();
+ params->values.clear();
+
+ for (List<ResourceImporter::ImportOption>::Element *E = options.front(); E; E = E->next()) {
+
+ params->properties.push_back(E->get().option);
+ if (p_config.is_valid() && p_config->has_section_key("params", E->get().option.name)) {
+ params->values[E->get().option.name] = p_config->get_value("params", E->get().option.name);
+ } else {
+ params->values[E->get().option.name] = E->get().default_value;
+ }
+ }
+
+ params->update();
+
preset->get_popup()->clear();
if (params->importer->get_preset_count() == 0) {
@@ -142,13 +154,6 @@ void ImportDock::set_edit_path(const String &p_path) {
preset->get_popup()->add_separator();
preset->get_popup()->add_item(vformat(TTR("Clear Default for '%s'"), params->importer->get_visible_name()), ITEM_CLEAR_DEFAULT);
}
-
- params->paths.clear();
- params->paths.push_back(p_path);
- import->set_disabled(false);
- import_as->set_disabled(false);
-
- imported->set_text(p_path.get_file());
}
void ImportDock::set_edit_multiple_paths(const Vector<String> &p_paths) {
@@ -263,6 +268,24 @@ void ImportDock::set_edit_multiple_paths(const Vector<String> &p_paths) {
imported->set_text(itos(p_paths.size()) + TTR(" Files"));
}
+void ImportDock::_importer_selected(int i_idx) {
+ String name = import_as->get_selected_metadata();
+ Ref<ResourceImporter> importer = ResourceFormatImporter::get_singleton()->get_importer_by_name(name);
+ ERR_FAIL_COND(importer.is_null());
+
+ params->importer = importer;
+
+ Ref<ConfigFile> config;
+ if (params->paths.size()) {
+ config.instance();
+ Error err = config->load(params->paths[0] + ".import");
+ if (err != OK) {
+ config.unref();
+ }
+ }
+ _update_options(config);
+}
+
void ImportDock::_preset_selected(int p_idx) {
int item_id = preset->get_popup()->get_item_id(p_idx);
@@ -336,6 +359,7 @@ void ImportDock::_reimport() {
Error err = config->load(params->paths[i] + ".import");
ERR_CONTINUE(err != OK);
+ config->set_value("remap", "importer", params->importer->get_importer_name());
config->erase_section("params");
for (List<PropertyInfo>::Element *E = params->properties.front(); E; E = E->next()) {
@@ -356,12 +380,18 @@ void ImportDock::_notification(int p_what) {
imported->add_style_override("normal", get_stylebox("normal", "LineEdit"));
} break;
+
+ case NOTIFICATION_ENTER_TREE: {
+
+ import_opts->edit(params);
+ } break;
}
}
void ImportDock::_bind_methods() {
ClassDB::bind_method(D_METHOD("_reimport"), &ImportDock::_reimport);
ClassDB::bind_method(D_METHOD("_preset_selected"), &ImportDock::_preset_selected);
+ ClassDB::bind_method(D_METHOD("_importer_selected"), &ImportDock::_importer_selected);
}
void ImportDock::initialize_import_options() const {
@@ -379,6 +409,7 @@ ImportDock::ImportDock() {
HBoxContainer *hb = memnew(HBoxContainer);
add_margin_child(TTR("Import As:"), hb);
import_as = memnew(OptionButton);
+ import_as->connect("item_selected", this, "_importer_selected");
hb->add_child(import_as);
import_as->set_h_size_flags(SIZE_EXPAND_FILL);
preset = memnew(MenuButton);
diff --git a/editor/import_dock.h b/editor/import_dock.h
index 029c458320..28c29e4b20 100644
--- a/editor/import_dock.h
+++ b/editor/import_dock.h
@@ -54,6 +54,8 @@ class ImportDock : public VBoxContainer {
ImportDockParameters *params;
void _preset_selected(int p_idx);
+ void _importer_selected(int i_idx);
+ void _update_options(const Ref<ConfigFile> &p_config = Ref<ConfigFile>());
void _reimport();
diff --git a/editor/node_dock.cpp b/editor/node_dock.cpp
index 7edaf0e5af..20392a67a7 100644
--- a/editor/node_dock.cpp
+++ b/editor/node_dock.cpp
@@ -56,10 +56,10 @@ void NodeDock::_bind_methods() {
void NodeDock::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE) {
- connections_button->set_icon(get_icon("Connect", "EditorIcons"));
+ connections_button->set_icon(get_icon("Signals", "EditorIcons"));
groups_button->set_icon(get_icon("Groups", "EditorIcons"));
} else if (p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) {
- connections_button->set_icon(get_icon("Connect", "EditorIcons"));
+ connections_button->set_icon(get_icon("Signals", "EditorIcons"));
groups_button->set_icon(get_icon("Groups", "EditorIcons"));
}
}
diff --git a/editor/plugins/abstract_polygon_2d_editor.cpp b/editor/plugins/abstract_polygon_2d_editor.cpp
new file mode 100644
index 0000000000..736e176ab8
--- /dev/null
+++ b/editor/plugins/abstract_polygon_2d_editor.cpp
@@ -0,0 +1,796 @@
+/*************************************************************************/
+/* abstract_polygon_2d_editor.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#include "abstract_polygon_2d_editor.h"
+
+#include "canvas_item_editor_plugin.h"
+#include "core/os/keyboard.h"
+
+AbstractPolygon2DEditor::Vertex::Vertex()
+ : polygon(-1), vertex(-1) {
+ // invalid vertex
+}
+
+AbstractPolygon2DEditor::Vertex::Vertex(int p_vertex)
+ : polygon(-1), vertex(p_vertex) {
+ // vertex p_vertex of current wip polygon
+}
+
+AbstractPolygon2DEditor::Vertex::Vertex(int p_polygon, int p_vertex)
+ : polygon(p_polygon), vertex(p_vertex) {
+ // vertex p_vertex of polygon p_polygon
+}
+
+bool AbstractPolygon2DEditor::Vertex::operator==(const AbstractPolygon2DEditor::Vertex &p_vertex) const {
+
+ return polygon == p_vertex.polygon && vertex == p_vertex.vertex;
+}
+
+bool AbstractPolygon2DEditor::Vertex::operator!=(const AbstractPolygon2DEditor::Vertex &p_vertex) const {
+
+ return !(*this == p_vertex);
+}
+
+bool AbstractPolygon2DEditor::Vertex::valid() const {
+
+ return vertex >= 0;
+}
+
+AbstractPolygon2DEditor::PosVertex::PosVertex() {
+ // invalid vertex
+}
+
+AbstractPolygon2DEditor::PosVertex::PosVertex(const Vertex &p_vertex, const Vector2 &p_pos)
+ : Vertex(p_vertex.polygon, p_vertex.vertex), pos(p_pos) {
+}
+
+AbstractPolygon2DEditor::PosVertex::PosVertex(int p_polygon, int p_vertex, const Vector2 &p_pos)
+ : Vertex(p_polygon, p_vertex), pos(p_pos) {
+}
+
+bool AbstractPolygon2DEditor::_is_empty() const {
+
+ if (!_get_node())
+ return true;
+
+ const int n = _get_polygon_count();
+
+ for (int i = 0; i < n; i++) {
+
+ Vector<Vector2> vertices = _get_polygon(i);
+
+ if (vertices.size() != 0)
+ return false;
+ }
+
+ return true;
+}
+
+bool AbstractPolygon2DEditor::_is_line() const {
+
+ return false;
+}
+
+int AbstractPolygon2DEditor::_get_polygon_count() const {
+
+ return 1;
+}
+
+Variant AbstractPolygon2DEditor::_get_polygon(int p_idx) const {
+
+ return _get_node()->get("polygon");
+}
+
+void AbstractPolygon2DEditor::_set_polygon(int p_idx, const Variant &p_polygon) const {
+
+ _get_node()->set("polygon", p_polygon);
+}
+
+void AbstractPolygon2DEditor::_action_set_polygon(int p_idx, const Variant &p_previous, const Variant &p_polygon) {
+
+ Node2D *node = _get_node();
+ undo_redo->add_do_method(node, "set_polygon", p_polygon);
+ undo_redo->add_undo_method(node, "set_polygon", p_previous);
+}
+
+Vector2 AbstractPolygon2DEditor::_get_offset(int p_idx) const {
+
+ return Vector2(0, 0);
+}
+
+void AbstractPolygon2DEditor::_commit_action() {
+
+ undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
+ undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
+ undo_redo->commit_action();
+}
+
+void AbstractPolygon2DEditor::_action_add_polygon(const Variant &p_polygon) {
+
+ _action_set_polygon(0, p_polygon);
+}
+
+void AbstractPolygon2DEditor::_action_remove_polygon(int p_idx) {
+
+ _action_set_polygon(p_idx, _get_polygon(p_idx), PoolVector<Vector2>());
+}
+
+void AbstractPolygon2DEditor::_action_set_polygon(int p_idx, const Variant &p_polygon) {
+
+ _action_set_polygon(p_idx, _get_polygon(p_idx), p_polygon);
+}
+
+bool AbstractPolygon2DEditor::_has_resource() const {
+
+ return true;
+}
+
+void AbstractPolygon2DEditor::_create_resource() {
+}
+
+void AbstractPolygon2DEditor::_menu_option(int p_option) {
+
+ switch (p_option) {
+
+ case MODE_CREATE: {
+
+ mode = MODE_CREATE;
+ button_create->set_pressed(true);
+ button_edit->set_pressed(false);
+ button_delete->set_pressed(false);
+ } break;
+ case MODE_EDIT: {
+
+ wip_active = false;
+ mode = MODE_EDIT;
+ button_create->set_pressed(false);
+ button_edit->set_pressed(true);
+ button_delete->set_pressed(false);
+ } break;
+ case MODE_DELETE: {
+
+ wip_active = false;
+ mode = MODE_DELETE;
+ button_create->set_pressed(false);
+ button_edit->set_pressed(false);
+ button_delete->set_pressed(true);
+ } break;
+ }
+}
+
+void AbstractPolygon2DEditor::_notification(int p_what) {
+
+ switch (p_what) {
+
+ case NOTIFICATION_READY: {
+
+ button_create->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("CurveCreate", "EditorIcons"));
+ button_edit->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("CurveEdit", "EditorIcons"));
+ button_delete->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("CurveDelete", "EditorIcons"));
+ button_edit->set_pressed(true);
+
+ get_tree()->connect("node_removed", this, "_node_removed");
+
+ create_resource->connect("confirmed", this, "_create_resource");
+
+ } break;
+ case NOTIFICATION_PHYSICS_PROCESS: {
+
+ } break;
+ }
+}
+
+void AbstractPolygon2DEditor::_node_removed(Node *p_node) {
+
+ if (p_node == _get_node()) {
+ edit(NULL);
+ hide();
+
+ canvas_item_editor->get_viewport_control()->update();
+ }
+}
+
+void AbstractPolygon2DEditor::_wip_changed() {
+
+ if (wip_active && _is_line()) {
+ _set_polygon(0, wip);
+ }
+}
+
+void AbstractPolygon2DEditor::_wip_close() {
+ if (_is_line()) {
+
+ _set_polygon(0, wip);
+ } else if (wip.size() >= 3) {
+
+ undo_redo->create_action(TTR("Create Poly"));
+ _action_add_polygon(wip);
+ _commit_action();
+ } else {
+
+ return;
+ }
+
+ mode = MODE_EDIT;
+ button_edit->set_pressed(true);
+ button_create->set_pressed(false);
+ button_delete->set_pressed(false);
+
+ wip.clear();
+ wip_active = false;
+
+ edited_point = PosVertex();
+ hover_point = Vertex();
+ selected_point = Vertex();
+}
+
+bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
+
+ if (!_get_node())
+ return false;
+
+ Ref<InputEventMouseButton> mb = p_event;
+
+ if (!_has_resource()) {
+
+ if (mb.is_valid() && mb->get_button_index() == 1 && mb->is_pressed()) {
+ create_resource->set_text(String("No polygon resource on this node.\nCreate and assign one?"));
+ create_resource->popup_centered_minsize();
+ }
+ return (mb.is_valid() && mb->get_button_index() == 1);
+ }
+
+ if (mb.is_valid()) {
+
+ Transform2D xform = canvas_item_editor->get_canvas_transform() * _get_node()->get_global_transform();
+
+ Vector2 gpoint = mb->get_position();
+ Vector2 cpoint = _get_node()->get_global_transform().affine_inverse().xform(canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(mb->get_position())));
+
+ if (mode == MODE_CREATE) {
+
+ if (mb->get_button_index() == BUTTON_LEFT && mb->is_pressed()) {
+
+ if (!wip_active) {
+
+ wip.clear();
+ wip.push_back(cpoint);
+ wip_active = true;
+ _wip_changed();
+ edited_point = PosVertex(-1, 1, cpoint);
+ canvas_item_editor->get_viewport_control()->update();
+ hover_point = Vertex();
+ selected_point = Vertex(0);
+ edge_point = PosVertex();
+ return true;
+ } else {
+
+ const real_t grab_threshold = EDITOR_DEF("editors/poly_editor/point_grab_radius", 8);
+
+ if (!_is_line() && wip.size() > 1 && xform.xform(wip[0]).distance_to(gpoint) < grab_threshold) {
+ //wip closed
+ _wip_close();
+
+ return true;
+ } else {
+
+ //add wip point
+ wip.push_back(cpoint);
+ _wip_changed();
+ edited_point = PosVertex(-1, wip.size(), cpoint);
+ selected_point = Vertex(wip.size() - 1);
+ canvas_item_editor->get_viewport_control()->update();
+ return true;
+ }
+ }
+ } else if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed() && wip_active) {
+ _wip_close();
+ }
+ } else if (mode == MODE_EDIT) {
+
+ if (mb->get_button_index() == BUTTON_LEFT) {
+
+ if (mb->is_pressed()) {
+
+ const PosVertex insert = closest_edge_point(gpoint);
+
+ if (insert.valid()) {
+
+ Vector<Vector2> vertices = _get_polygon(insert.polygon);
+
+ if (vertices.size() < 3) {
+
+ vertices.push_back(cpoint);
+ undo_redo->create_action(TTR("Edit Poly"));
+ selected_point = Vertex(insert.polygon, vertices.size());
+ _action_set_polygon(insert.polygon, vertices);
+ _commit_action();
+ return true;
+ } else {
+
+ Vector<Vector2> vertices = _get_polygon(insert.polygon);
+ pre_move_edit = vertices;
+ edited_point = PosVertex(insert.polygon, insert.vertex + 1, xform.affine_inverse().xform(insert.pos));
+ vertices.insert(edited_point.vertex, edited_point.pos);
+ selected_point = edited_point;
+ edge_point = PosVertex();
+
+ undo_redo->create_action(TTR("Insert Point"));
+ _action_set_polygon(insert.polygon, vertices);
+ _commit_action();
+
+ return true;
+ }
+ } else {
+
+ //look for points to move
+ const PosVertex closest = closest_point(gpoint);
+
+ if (closest.valid()) {
+
+ pre_move_edit = _get_polygon(closest.polygon);
+ edited_point = PosVertex(closest, xform.affine_inverse().xform(closest.pos));
+ selected_point = closest;
+ edge_point = PosVertex();
+ canvas_item_editor->get_viewport_control()->update();
+ return true;
+ } else {
+
+ selected_point = Vertex();
+ }
+ }
+ } else {
+
+ if (edited_point.valid()) {
+
+ //apply
+
+ Vector<Vector2> vertices = _get_polygon(edited_point.polygon);
+ ERR_FAIL_INDEX_V(edited_point.vertex, vertices.size(), false);
+ vertices[edited_point.vertex] = edited_point.pos - _get_offset(edited_point.polygon);
+
+ undo_redo->create_action(TTR("Edit Poly"));
+ _action_set_polygon(edited_point.polygon, pre_move_edit, vertices);
+ _commit_action();
+
+ edited_point = PosVertex();
+ return true;
+ }
+ }
+ } else if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed() && !edited_point.valid()) {
+
+ const PosVertex closest = closest_point(gpoint);
+
+ if (closest.valid()) {
+
+ remove_point(closest);
+ return true;
+ }
+ }
+ } else if (mode == MODE_DELETE) {
+
+ if (mb->get_button_index() == BUTTON_LEFT && mb->is_pressed()) {
+
+ const PosVertex closest = closest_point(gpoint);
+
+ if (closest.valid()) {
+
+ remove_point(closest);
+ return true;
+ }
+ }
+ }
+ }
+
+ Ref<InputEventMouseMotion> mm = p_event;
+
+ if (mm.is_valid()) {
+
+ Vector2 gpoint = mm->get_position();
+
+ if (edited_point.valid() && (wip_active || (mm->get_button_mask() & BUTTON_MASK_LEFT))) {
+
+ Vector2 cpoint = _get_node()->get_global_transform().affine_inverse().xform(canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint)));
+ edited_point = PosVertex(edited_point, cpoint);
+
+ if (!wip_active) {
+
+ Vector<Vector2> vertices = _get_polygon(edited_point.polygon);
+ ERR_FAIL_INDEX_V(edited_point.vertex, vertices.size(), false);
+ vertices[edited_point.vertex] = cpoint - _get_offset(edited_point.polygon);
+ _set_polygon(edited_point.polygon, vertices);
+ }
+
+ canvas_item_editor->get_viewport_control()->update();
+ } else if (mode == MODE_EDIT) {
+
+ const PosVertex onEdgeVertex = closest_edge_point(gpoint);
+
+ if (onEdgeVertex.valid()) {
+
+ hover_point = Vertex();
+ edge_point = onEdgeVertex;
+ canvas_item_editor->get_viewport_control()->update();
+ } else {
+
+ if (edge_point.valid()) {
+
+ edge_point = PosVertex();
+ canvas_item_editor->get_viewport_control()->update();
+ }
+
+ const PosVertex new_hover_point = closest_point(gpoint);
+ if (hover_point != new_hover_point) {
+
+ hover_point = new_hover_point;
+ canvas_item_editor->get_viewport_control()->update();
+ }
+ }
+ }
+ }
+
+ Ref<InputEventKey> k = p_event;
+
+ if (k.is_valid() && k->is_pressed()) {
+
+ if (k->get_scancode() == KEY_DELETE || k->get_scancode() == KEY_BACKSPACE) {
+
+ if (wip_active && selected_point.polygon == -1) {
+
+ if (wip.size() > selected_point.vertex) {
+
+ wip.remove(selected_point.vertex);
+ _wip_changed();
+ selected_point = wip.size() - 1;
+ canvas_item_editor->get_viewport_control()->update();
+ return true;
+ }
+ } else {
+
+ const Vertex active_point = get_active_point();
+
+ if (active_point.valid()) {
+
+ remove_point(active_point);
+ return true;
+ }
+ }
+ } else if (wip_active && k->get_scancode() == KEY_ENTER) {
+
+ _wip_close();
+ }
+ }
+
+ return false;
+}
+
+void AbstractPolygon2DEditor::forward_draw_over_canvas(Control *p_canvas) {
+ if (!_get_node())
+ return;
+
+ Control *vpc = canvas_item_editor->get_viewport_control();
+
+ Transform2D xform = canvas_item_editor->get_canvas_transform() * _get_node()->get_global_transform();
+ Ref<Texture> default_handle = get_icon("EditorHandle", "EditorIcons");
+ Ref<Texture> selected_handle = get_icon("EditorHandleSelected", "EditorIcons");
+
+ const Vertex active_point = get_active_point();
+ const int n_polygons = _get_polygon_count();
+ const bool is_closed = !_is_line();
+
+ for (int j = -1; j < n_polygons; j++) {
+
+ if (wip_active && wip_destructive && j != -1)
+ continue;
+
+ PoolVector<Vector2> points;
+ Vector2 offset;
+
+ if (wip_active && j == edited_point.polygon) {
+
+ points = Variant(wip);
+ offset = Vector2(0, 0);
+ } else {
+
+ if (j == -1)
+ continue;
+ points = _get_polygon(j);
+ offset = _get_offset(j);
+ }
+
+ if (!wip_active && j == edited_point.polygon && EDITOR_DEF("editors/poly_editor/show_previous_outline", true)) {
+
+ const Color col = Color(0.5, 0.5, 0.5); // FIXME polygon->get_outline_color();
+ const int n = pre_move_edit.size();
+ for (int i = 0; i < n - is_closed ? 0 : 1; i++) {
+
+ Vector2 p, p2;
+ p = pre_move_edit[i] + offset;
+ p2 = pre_move_edit[(i + 1) % n] + offset;
+
+ Vector2 point = xform.xform(p);
+ Vector2 next_point = xform.xform(p2);
+
+ vpc->draw_line(point, next_point, col, 2);
+ }
+ }
+
+ const int n_points = points.size();
+ const Color col = Color(1, 0.3, 0.1, 0.8);
+
+ for (int i = 0; i < n_points; i++) {
+
+ const Vertex vertex(j, i);
+
+ const Vector2 p = (vertex == edited_point) ? edited_point.pos : (points[i] + offset);
+ const Vector2 point = xform.xform(p);
+
+ if (is_closed || i < n_points - 1) {
+
+ Vector2 p2;
+ if (j == edited_point.polygon &&
+ ((wip_active && i == n_points - 1) || (((i + 1) % n_points) == edited_point.vertex)))
+ p2 = edited_point.pos;
+ else
+ p2 = points[(i + 1) % n_points] + offset;
+
+ const Vector2 next_point = xform.xform(p2);
+ vpc->draw_line(point, next_point, col, 2);
+ }
+ }
+
+ for (int i = 0; i < n_points; i++) {
+
+ const Vertex vertex(j, i);
+
+ const Vector2 p = (vertex == edited_point) ? edited_point.pos : (points[i] + offset);
+ const Vector2 point = xform.xform(p);
+
+ Ref<Texture> handle = vertex == active_point ? selected_handle : default_handle;
+ vpc->draw_texture(handle, point - handle->get_size() * 0.5);
+ }
+ }
+
+ if (edge_point.valid()) {
+
+ Ref<Texture> add_handle = get_icon("EditorHandleAdd", "EditorIcons");
+ vpc->draw_texture(add_handle, edge_point.pos - add_handle->get_size() * 0.5);
+ }
+}
+
+void AbstractPolygon2DEditor::edit(Node *p_polygon) {
+
+ if (!canvas_item_editor) {
+ canvas_item_editor = CanvasItemEditor::get_singleton();
+ }
+
+ if (p_polygon) {
+
+ _set_node(p_polygon);
+
+ //Enable the pencil tool if the polygon is empty
+ if (_is_empty())
+ _menu_option(MODE_CREATE);
+
+ wip.clear();
+ wip_active = false;
+ edited_point = PosVertex();
+ hover_point = Vertex();
+ selected_point = Vertex();
+
+ canvas_item_editor->get_viewport_control()->update();
+
+ } else {
+
+ _set_node(NULL);
+ }
+}
+
+void AbstractPolygon2DEditor::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("_node_removed"), &AbstractPolygon2DEditor::_node_removed);
+ ClassDB::bind_method(D_METHOD("_menu_option"), &AbstractPolygon2DEditor::_menu_option);
+ ClassDB::bind_method(D_METHOD("_create_resource"), &AbstractPolygon2DEditor::_create_resource);
+}
+
+void AbstractPolygon2DEditor::remove_point(const Vertex &p_vertex) {
+
+ PoolVector<Vector2> vertices = _get_polygon(p_vertex.polygon);
+
+ if (vertices.size() > 3) {
+
+ vertices.remove(p_vertex.vertex);
+
+ undo_redo->create_action(TTR("Edit Poly (Remove Point)"));
+ _action_set_polygon(p_vertex.polygon, vertices);
+ _commit_action();
+ } else {
+
+ undo_redo->create_action(TTR("Remove Poly And Point"));
+ _action_remove_polygon(p_vertex.polygon);
+ _commit_action();
+ }
+
+ if (_is_empty())
+ _menu_option(MODE_CREATE);
+
+ hover_point = Vertex();
+ if (selected_point == p_vertex)
+ selected_point = Vertex();
+}
+
+AbstractPolygon2DEditor::Vertex AbstractPolygon2DEditor::get_active_point() const {
+
+ return hover_point.valid() ? hover_point : selected_point;
+}
+
+AbstractPolygon2DEditor::PosVertex AbstractPolygon2DEditor::closest_point(const Vector2 &p_pos) const {
+
+ const real_t grab_threshold = EDITOR_DEF("editors/poly_editor/point_grab_radius", 8);
+
+ const int n_polygons = _get_polygon_count();
+ const Transform2D xform = canvas_item_editor->get_canvas_transform() * _get_node()->get_global_transform();
+
+ PosVertex closest;
+ real_t closest_dist = 1e10;
+
+ for (int j = 0; j < n_polygons; j++) {
+
+ PoolVector<Vector2> points = _get_polygon(j);
+ const Vector2 offset = _get_offset(j);
+ const int n_points = points.size();
+
+ for (int i = 0; i < n_points; i++) {
+
+ Vector2 cp = xform.xform(points[i] + offset);
+
+ real_t d = cp.distance_to(p_pos);
+ if (d < closest_dist && d < grab_threshold) {
+ closest_dist = d;
+ closest = PosVertex(j, i, cp);
+ }
+ }
+ }
+
+ return closest;
+}
+
+AbstractPolygon2DEditor::PosVertex AbstractPolygon2DEditor::closest_edge_point(const Vector2 &p_pos) const {
+
+ const real_t grab_threshold = EDITOR_DEF("editors/poly_editor/point_grab_radius", 8);
+ const real_t eps = grab_threshold * 2;
+ const real_t eps2 = eps * eps;
+
+ const int n_polygons = _get_polygon_count();
+ const Transform2D xform = canvas_item_editor->get_canvas_transform() * _get_node()->get_global_transform();
+
+ PosVertex closest;
+ real_t closest_dist = 1e10;
+
+ for (int j = 0; j < n_polygons; j++) {
+
+ PoolVector<Vector2> points = _get_polygon(j);
+ const Vector2 offset = _get_offset(j);
+ const int n_points = points.size();
+
+ for (int i = 0; i < n_points; i++) {
+
+ Vector2 segment[2] = { xform.xform(points[i] + offset),
+ xform.xform(points[(i + 1) % n_points] + offset) };
+
+ Vector2 cp = Geometry::get_closest_point_to_segment_2d(p_pos, segment);
+
+ if (cp.distance_squared_to(segment[0]) < eps2 || cp.distance_squared_to(segment[1]) < eps2)
+ continue; //not valid to reuse point
+
+ real_t d = cp.distance_to(p_pos);
+ if (d < closest_dist && d < grab_threshold) {
+ closest_dist = d;
+ closest = PosVertex(j, i, cp);
+ }
+ }
+ }
+
+ return closest;
+}
+
+AbstractPolygon2DEditor::AbstractPolygon2DEditor(EditorNode *p_editor, bool p_wip_destructive) {
+
+ canvas_item_editor = NULL;
+ editor = p_editor;
+ undo_redo = editor->get_undo_redo();
+
+ wip_active = false;
+ edited_point = PosVertex();
+ wip_destructive = p_wip_destructive;
+
+ hover_point = Vertex();
+ selected_point = Vertex();
+ edge_point = PosVertex();
+
+ add_child(memnew(VSeparator));
+ button_create = memnew(ToolButton);
+ add_child(button_create);
+ button_create->connect("pressed", this, "_menu_option", varray(MODE_CREATE));
+ button_create->set_toggle_mode(true);
+ button_create->set_tooltip(TTR("Create a new polygon from scratch"));
+
+ button_edit = memnew(ToolButton);
+ add_child(button_edit);
+ button_edit->connect("pressed", this, "_menu_option", varray(MODE_EDIT));
+ button_edit->set_toggle_mode(true);
+ button_edit->set_tooltip(TTR("Edit existing polygon:\nLMB: Move Point.\nCtrl+LMB: Split Segment.\nRMB: Erase Point."));
+
+ button_delete = memnew(ToolButton);
+ add_child(button_delete);
+ button_delete->connect("pressed", this, "_menu_option", varray(MODE_DELETE));
+ button_delete->set_toggle_mode(true);
+ button_delete->set_tooltip(TTR("Delete points"));
+
+ create_resource = memnew(ConfirmationDialog);
+ add_child(create_resource);
+ create_resource->get_ok()->set_text(TTR("Create"));
+
+ mode = MODE_EDIT;
+}
+
+void AbstractPolygon2DEditorPlugin::edit(Object *p_object) {
+
+ polygon_editor->edit(Object::cast_to<Node>(p_object));
+}
+
+bool AbstractPolygon2DEditorPlugin::handles(Object *p_object) const {
+
+ return p_object->is_class(klass);
+}
+
+void AbstractPolygon2DEditorPlugin::make_visible(bool p_visible) {
+
+ if (p_visible) {
+
+ polygon_editor->show();
+ } else {
+
+ polygon_editor->hide();
+ polygon_editor->edit(NULL);
+ }
+}
+
+AbstractPolygon2DEditorPlugin::AbstractPolygon2DEditorPlugin(EditorNode *p_node, AbstractPolygon2DEditor *p_polygon_editor, String p_class) {
+
+ editor = p_node;
+ polygon_editor = p_polygon_editor;
+ klass = p_class;
+ CanvasItemEditor::get_singleton()->add_control_to_menu_panel(polygon_editor);
+
+ polygon_editor->hide();
+}
+
+AbstractPolygon2DEditorPlugin::~AbstractPolygon2DEditorPlugin() {
+}
diff --git a/editor/plugins/abstract_polygon_2d_editor.h b/editor/plugins/abstract_polygon_2d_editor.h
new file mode 100644
index 0000000000..915fe0803e
--- /dev/null
+++ b/editor/plugins/abstract_polygon_2d_editor.h
@@ -0,0 +1,167 @@
+/*************************************************************************/
+/* abstract_polygon_2d_editor.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#ifndef ABSTRACT_POLYGON_2D_EDITOR_H
+#define ABSTRACT_POLYGON_2D_EDITOR_H
+
+#include "editor/editor_node.h"
+#include "editor/editor_plugin.h"
+#include "scene/2d/polygon_2d.h"
+#include "scene/gui/tool_button.h"
+
+/**
+ @author Juan Linietsky <reduzio@gmail.com>
+*/
+class CanvasItemEditor;
+
+class AbstractPolygon2DEditor : public HBoxContainer {
+
+ GDCLASS(AbstractPolygon2DEditor, HBoxContainer);
+
+ ToolButton *button_create;
+ ToolButton *button_edit;
+ ToolButton *button_delete;
+
+ struct Vertex {
+ Vertex();
+ Vertex(int p_vertex);
+ Vertex(int p_polygon, int p_vertex);
+
+ bool operator==(const Vertex &p_vertex) const;
+ bool operator!=(const Vertex &p_vertex) const;
+
+ bool valid() const;
+
+ int polygon;
+ int vertex;
+ };
+
+ struct PosVertex : public Vertex {
+ PosVertex();
+ PosVertex(const Vertex &p_vertex, const Vector2 &p_pos);
+ PosVertex(int p_polygon, int p_vertex, const Vector2 &p_pos);
+
+ Vector2 pos;
+ };
+
+ PosVertex edited_point;
+ Vertex hover_point; // point under mouse cursor
+ Vertex selected_point; // currently selected
+ PosVertex edge_point; // adding an edge point?
+
+ Vector<Vector2> pre_move_edit;
+ Vector<Vector2> wip;
+ bool wip_active;
+ bool wip_destructive;
+
+ CanvasItemEditor *canvas_item_editor;
+ EditorNode *editor;
+ Panel *panel;
+ ConfirmationDialog *create_resource;
+
+protected:
+ enum {
+
+ MODE_CREATE,
+ MODE_EDIT,
+ MODE_DELETE,
+ MODE_CONT,
+
+ };
+
+ int mode;
+
+ UndoRedo *undo_redo;
+
+ virtual void _menu_option(int p_option);
+ void _wip_changed();
+ void _wip_close();
+ bool _delete_point(const Vector2 &p_gpoint);
+
+ void _notification(int p_what);
+ void _node_removed(Node *p_node);
+ static void _bind_methods();
+
+ void remove_point(const Vertex &p_vertex);
+ Vertex get_active_point() const;
+ PosVertex closest_point(const Vector2 &p_pos) const;
+ PosVertex closest_edge_point(const Vector2 &p_pos) const;
+
+ bool _is_empty() const;
+ void _commit_action();
+
+protected:
+ virtual Node2D *_get_node() const = 0;
+ virtual void _set_node(Node *p_polygon) = 0;
+
+ virtual bool _is_line() const;
+ virtual int _get_polygon_count() const;
+ virtual Vector2 _get_offset(int p_idx) const;
+ virtual Variant _get_polygon(int p_idx) const;
+ virtual void _set_polygon(int p_idx, const Variant &p_polygon) const;
+
+ virtual void _action_add_polygon(const Variant &p_polygon);
+ virtual void _action_remove_polygon(int p_idx);
+ virtual void _action_set_polygon(int p_idx, const Variant &p_polygon);
+ virtual void _action_set_polygon(int p_idx, const Variant &p_previous, const Variant &p_polygon);
+
+ virtual bool _has_resource() const;
+ virtual void _create_resource();
+
+public:
+ bool forward_gui_input(const Ref<InputEvent> &p_event);
+ void forward_draw_over_canvas(Control *p_canvas);
+
+ void edit(Node *p_polygon);
+ AbstractPolygon2DEditor(EditorNode *p_editor, bool p_wip_destructive = true);
+};
+
+class AbstractPolygon2DEditorPlugin : public EditorPlugin {
+
+ GDCLASS(AbstractPolygon2DEditorPlugin, EditorPlugin);
+
+ AbstractPolygon2DEditor *polygon_editor;
+ EditorNode *editor;
+ String klass;
+
+public:
+ virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event) { return polygon_editor->forward_gui_input(p_event); }
+ virtual void forward_draw_over_canvas(Control *p_canvas) { polygon_editor->forward_draw_over_canvas(p_canvas); }
+
+ bool has_main_screen() const { return false; }
+ virtual String get_name() const { return klass; }
+ virtual void edit(Object *p_object);
+ virtual bool handles(Object *p_object) const;
+ virtual void make_visible(bool p_visible);
+
+ AbstractPolygon2DEditorPlugin(EditorNode *p_node, AbstractPolygon2DEditor *p_polygon_editor, String p_class);
+ ~AbstractPolygon2DEditorPlugin();
+};
+
+#endif // ABSTRACT_POLYGON_2D_EDITOR_H
diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp
index bdfe380211..2b9c625aa4 100644
--- a/editor/plugins/animation_player_editor_plugin.cpp
+++ b/editor/plugins/animation_player_editor_plugin.cpp
@@ -557,7 +557,7 @@ void AnimationPlayerEditor::_animation_blend() {
String current = animation->get_item_text(animation->get_selected());
- blend_editor.dialog->popup_centered(Size2(400, 400));
+ blend_editor.dialog->popup_centered(Size2(400, 400) * EDSCALE);
blend_editor.tree->set_hide_root(true);
blend_editor.tree->set_column_min_width(0, 10);
diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp
index cd53264437..b63352389e 100644
--- a/editor/plugins/asset_library_editor_plugin.cpp
+++ b/editor/plugins/asset_library_editor_plugin.cpp
@@ -33,6 +33,8 @@
#include "editor_settings.h"
#include "io/json.h"
+#include "version_generated.gen.h"
+
void EditorAssetLibraryItem::configure(const String &p_title, int p_asset_id, const String &p_category, int p_category_id, const String &p_author, int p_author_id, int p_rating, const String &p_cost) {
title->set_text(p_title);
@@ -45,9 +47,9 @@ void EditorAssetLibraryItem::configure(const String &p_title, int p_asset_id, co
for (int i = 0; i < 5; i++) {
if (i < p_rating)
- stars[i]->set_texture(get_icon("RatingStar", "EditorIcons"));
+ stars[i]->set_texture(get_icon("Favorites", "EditorIcons"));
else
- stars[i]->set_texture(get_icon("RatingNoStar", "EditorIcons"));
+ stars[i]->set_texture(get_icon("NonFavorite", "EditorIcons"));
}
}
@@ -271,15 +273,15 @@ EditorAssetLibraryItemDescription::EditorAssetLibraryItemDescription() {
HBoxContainer *hbox = memnew(HBoxContainer);
vbox->add_child(hbox);
- vbox->add_constant_override("separation", 15);
+ vbox->add_constant_override("separation", 15 * EDSCALE);
VBoxContainer *desc_vbox = memnew(VBoxContainer);
hbox->add_child(desc_vbox);
- hbox->add_constant_override("separation", 15);
+ hbox->add_constant_override("separation", 15 * EDSCALE);
item = memnew(EditorAssetLibraryItem);
desc_vbox->add_child(item);
- desc_vbox->set_custom_minimum_size(Size2(300, 0));
+ desc_vbox->set_custom_minimum_size(Size2(300 * EDSCALE, 0));
desc_bg = memnew(PanelContainer);
desc_vbox->add_child(desc_bg);
@@ -290,12 +292,12 @@ EditorAssetLibraryItemDescription::EditorAssetLibraryItemDescription() {
desc_bg->add_child(description);
preview = memnew(TextureRect);
- preview->set_custom_minimum_size(Size2(640, 345));
+ preview->set_custom_minimum_size(Size2(640 * EDSCALE, 345 * EDSCALE));
hbox->add_child(preview);
previews_bg = memnew(PanelContainer);
vbox->add_child(previews_bg);
- previews_bg->set_custom_minimum_size(Size2(0, 85));
+ previews_bg->set_custom_minimum_size(Size2(0, 101 * EDSCALE));
previews = memnew(ScrollContainer);
previews_bg->add_child(previews);
@@ -443,7 +445,7 @@ void EditorAssetLibraryItemDownload::_install() {
void EditorAssetLibraryItemDownload::_make_request() {
download->cancel_request();
- download->set_download_file(EditorSettings::get_singleton()->get_settings_path().plus_file("tmp").plus_file("tmp_asset_" + itos(asset_id)) + ".zip");
+ download->set_download_file(EditorSettings::get_singleton()->get_cache_dir().plus_file("tmp_asset_" + itos(asset_id)) + ".zip");
Error err = download->request(host);
if (err != OK) {
@@ -678,7 +680,7 @@ void EditorAssetLibrary::_image_update(bool use_cache, bool final, const PoolByt
PoolByteArray image_data = p_data;
if (use_cache) {
- String cache_filename_base = EditorSettings::get_singleton()->get_settings_path().plus_file("tmp").plus_file("assetimage_" + image_queue[p_queue_id].image_url.md5_text());
+ String cache_filename_base = EditorSettings::get_singleton()->get_cache_dir().plus_file("assetimage_" + image_queue[p_queue_id].image_url.md5_text());
FileAccess *file = FileAccess::open(cache_filename_base + ".data", FileAccess::READ);
@@ -700,15 +702,28 @@ void EditorAssetLibrary::_image_update(bool use_cache, bool final, const PoolByt
Ref<Image> image = Ref<Image>(memnew(Image(r.ptr(), len)));
if (!image->empty()) {
- float max_height = 10000;
switch (image_queue[p_queue_id].image_type) {
- case IMAGE_QUEUE_ICON: max_height = 80; break;
- case IMAGE_QUEUE_THUMBNAIL: max_height = 80; break;
- case IMAGE_QUEUE_SCREENSHOT: max_height = 345; break;
- }
- float scale_ratio = max_height / image->get_height();
- if (scale_ratio < 1) {
- image->resize(image->get_width() * scale_ratio, image->get_height() * scale_ratio, Image::INTERPOLATE_CUBIC);
+ case IMAGE_QUEUE_ICON:
+
+ image->resize(80 * EDSCALE, 80 * EDSCALE, Image::INTERPOLATE_CUBIC);
+
+ break;
+ case IMAGE_QUEUE_THUMBNAIL: {
+ float max_height = 85 * EDSCALE;
+
+ float scale_ratio = max_height / (image->get_height() * EDSCALE);
+ if (scale_ratio < 1) {
+ image->resize(image->get_width() * EDSCALE * scale_ratio, image->get_height() * EDSCALE * scale_ratio, Image::INTERPOLATE_CUBIC);
+ }
+ } break;
+ case IMAGE_QUEUE_SCREENSHOT: {
+ float max_height = 397 * EDSCALE;
+
+ float scale_ratio = max_height / (image->get_height() * EDSCALE);
+ if (scale_ratio < 1) {
+ image->resize(image->get_width() * EDSCALE * scale_ratio, image->get_height() * EDSCALE * scale_ratio, Image::INTERPOLATE_CUBIC);
+ }
+ } break;
}
Ref<ImageTexture> tex;
@@ -736,7 +751,7 @@ void EditorAssetLibrary::_image_request_completed(int p_status, int p_code, cons
if (p_code != HTTPClient::RESPONSE_NOT_MODIFIED) {
for (int i = 0; i < headers.size(); i++) {
if (headers[i].findn("ETag:") == 0) { // Save etag
- String cache_filename_base = EditorSettings::get_singleton()->get_settings_path().plus_file("tmp").plus_file("assetimage_" + image_queue[p_queue_id].image_url.md5_text());
+ String cache_filename_base = EditorSettings::get_singleton()->get_cache_dir().plus_file("assetimage_" + image_queue[p_queue_id].image_url.md5_text());
String new_etag = headers[i].substr(headers[i].find(":") + 1, headers[i].length()).strip_edges();
FileAccess *file;
@@ -784,7 +799,7 @@ void EditorAssetLibrary::_update_image_queue() {
for (Map<int, ImageQueue>::Element *E = image_queue.front(); E; E = E->next()) {
if (!E->get().active && current_images < max_images) {
- String cache_filename_base = EditorSettings::get_singleton()->get_settings_path().plus_file("tmp").plus_file("assetimage_" + E->get().image_url.md5_text());
+ String cache_filename_base = EditorSettings::get_singleton()->get_cache_dir().plus_file("assetimage_" + E->get().image_url.md5_text());
Vector<String> headers;
if (FileAccess::exists(cache_filename_base + ".etag") && FileAccess::exists(cache_filename_base + ".data")) {
@@ -867,6 +882,8 @@ void EditorAssetLibrary::_search(int p_page) {
}
args += String() + "sort=" + sort_key[sort->get_selected()];
+ args += "&godot_version=" + itos(VERSION_MAJOR) + "." + itos(VERSION_MINOR);
+
String support_list;
for (int i = 0; i < SUPPORT_MAX; i++) {
if (support->get_popup()->is_item_checked(i)) {
@@ -1348,13 +1365,11 @@ EditorAssetLibrary::EditorAssetLibrary(bool p_templates_only) {
search_hb2->add_child(memnew(Label(TTR("Site:") + " ")));
repository = memnew(OptionButton);
- // FIXME: Reenable me once GH-7147 is fixed.
- /*
repository->add_item("godotengine.org");
repository->set_item_metadata(0, "https://godotengine.org/asset-library/api");
- */
repository->add_item("localhost");
- repository->set_item_metadata(/*1*/ 0, "http://127.0.0.1/asset-library/api");
+ repository->set_item_metadata(1, "http://127.0.0.1/asset-library/api");
+
repository->connect("item_selected", this, "_repository_changed");
search_hb2->add_child(repository);
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index 4f6c8f89ee..3940dd9044 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -45,7 +45,7 @@
#include "scene/2d/screen_button.h"
#include "scene/2d/sprite.h"
#include "scene/gui/grid_container.h"
-#include "scene/gui/patch_9_rect.h"
+#include "scene/gui/nine_patch_rect.h"
#include "scene/main/canvas_layer.h"
#include "scene/main/viewport.h"
#include "scene/resources/packed_scene.h"
@@ -176,9 +176,9 @@ void CanvasItemEditor::_edit_set_pivot(const Vector2 &mouse_pos) {
for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
Node2D *n2d = Object::cast_to<Node2D>(E->get());
- if (n2d && n2d->edit_has_pivot()) {
+ if (n2d && n2d->_edit_use_pivot()) {
- Vector2 offset = n2d->edit_get_pivot();
+ Vector2 offset = n2d->_edit_get_pivot();
Vector2 gpos = n2d->get_global_position();
Vector2 local_mouse_pos = n2d->get_canvas_transform().affine_inverse().xform(mouse_pos);
@@ -186,9 +186,9 @@ void CanvasItemEditor::_edit_set_pivot(const Vector2 &mouse_pos) {
Vector2 motion_ofs = gpos - local_mouse_pos;
undo_redo->add_do_method(n2d, "set_global_position", local_mouse_pos);
- undo_redo->add_do_method(n2d, "edit_set_pivot", offset + n2d->get_global_transform().affine_inverse().basis_xform(motion_ofs));
+ undo_redo->add_do_method(n2d, "_edit_set_pivot", offset + n2d->get_global_transform().affine_inverse().basis_xform(motion_ofs));
undo_redo->add_undo_method(n2d, "set_global_position", gpos);
- undo_redo->add_undo_method(n2d, "edit_set_pivot", offset);
+ undo_redo->add_undo_method(n2d, "_edit_set_pivot", offset);
for (int i = 0; i < n2d->get_child_count(); i++) {
Node2D *n2dc = Object::cast_to<Node2D>(n2d->get_child(i));
if (!n2dc)
@@ -222,41 +222,38 @@ void CanvasItemEditor::_edit_set_pivot(const Vector2 &mouse_pos) {
undo_redo->commit_action();
}
-void CanvasItemEditor::_snap_if_closer(Point2 p_value, Point2 p_target_snap, Point2 &r_current_snap, bool (&r_snapped)[2], real_t rotation, float p_radius) {
+void CanvasItemEditor::_snap_if_closer_float(float p_value, float p_target_snap, float &r_current_snap, bool &r_snapped, float p_radius) {
float radius = p_radius / zoom;
- float dist;
+ float dist = Math::abs(p_value - p_target_snap);
+ if (p_radius < 0 || dist < radius && (!r_snapped || dist < Math::abs(r_current_snap - p_value))) {
+ r_current_snap = p_target_snap;
+ r_snapped = true;
+ }
+}
+void CanvasItemEditor::_snap_if_closer_point(Point2 p_value, Point2 p_target_snap, Point2 &r_current_snap, bool (&r_snapped)[2], real_t rotation, float p_radius) {
Transform2D rot_trans = Transform2D(rotation, Point2());
p_value = rot_trans.inverse().xform(p_value);
p_target_snap = rot_trans.inverse().xform(p_target_snap);
r_current_snap = rot_trans.inverse().xform(r_current_snap);
- dist = Math::abs(p_value.x - p_target_snap.x);
- if (p_radius < 0 || dist < radius && (!r_snapped[0] || dist < Math::abs(r_current_snap.x - p_value.x))) {
- r_current_snap.x = p_target_snap.x;
- r_snapped[0] = true;
- }
-
- dist = Math::abs(p_value.y - p_target_snap.y);
- if (p_radius < 0 || dist < radius && (!r_snapped[1] || dist < Math::abs(r_current_snap.y - p_value.y))) {
- r_current_snap.y = p_target_snap.y;
- r_snapped[1] = true;
- }
+ _snap_if_closer_float(p_value.x, p_target_snap.x, r_current_snap.x, r_snapped[0], p_radius);
+ _snap_if_closer_float(p_value.y, p_target_snap.y, r_current_snap.y, r_snapped[1], p_radius);
r_current_snap = rot_trans.xform(r_current_snap);
}
void CanvasItemEditor::_snap_other_nodes(Point2 p_value, Point2 &r_current_snap, bool (&r_snapped)[2], const Node *p_current, const CanvasItem *p_to_snap) {
const CanvasItem *canvas_item = Object::cast_to<CanvasItem>(p_current);
- if (canvas_item && p_current != p_to_snap) {
+ if (canvas_item && (!p_to_snap || p_current != p_to_snap)) {
Transform2D ci_transform = canvas_item->get_global_transform_with_canvas();
- Transform2D to_snap_transform = p_to_snap->get_global_transform_with_canvas();
- if (ci_transform.get_rotation() == to_snap_transform.get_rotation()) {
- Point2 begin = ci_transform.xform(canvas_item->get_item_rect().get_position());
- Point2 end = ci_transform.xform(canvas_item->get_item_rect().get_position() + canvas_item->get_item_rect().get_size());
+ Transform2D to_snap_transform = p_to_snap ? p_to_snap->get_global_transform_with_canvas() : Transform2D();
+ if (fmod(ci_transform.get_rotation() - to_snap_transform.get_rotation(), (real_t)360.0) == 0.0) {
+ Point2 begin = ci_transform.xform(canvas_item->_edit_get_rect().get_position());
+ Point2 end = ci_transform.xform(canvas_item->_edit_get_rect().get_position() + canvas_item->_edit_get_rect().get_size());
- _snap_if_closer(p_value, begin, r_current_snap, r_snapped, ci_transform.get_rotation());
- _snap_if_closer(p_value, end, r_current_snap, r_snapped, ci_transform.get_rotation());
+ _snap_if_closer_point(p_value, begin, r_current_snap, r_snapped, ci_transform.get_rotation());
+ _snap_if_closer_point(p_value, end, r_current_snap, r_snapped, ci_transform.get_rotation());
}
}
for (int i = 0; i < p_current->get_child_count(); i++) {
@@ -285,15 +282,15 @@ Point2 CanvasItemEditor::snap_point(Point2 p_target, unsigned int p_modes, const
end = p_canvas_item->get_global_transform_with_canvas().xform(_anchor_to_position(c, Point2(1, 1)));
can_snap = true;
} else if (const CanvasItem *parent_ci = Object::cast_to<CanvasItem>(p_canvas_item->get_parent())) {
- begin = p_canvas_item->get_transform().affine_inverse().xform(parent_ci->get_item_rect().get_position());
- end = p_canvas_item->get_transform().affine_inverse().xform(parent_ci->get_item_rect().get_position() + parent_ci->get_item_rect().get_size());
+ begin = p_canvas_item->get_transform().affine_inverse().xform(parent_ci->_edit_get_rect().get_position());
+ end = p_canvas_item->get_transform().affine_inverse().xform(parent_ci->_edit_get_rect().get_position() + parent_ci->_edit_get_rect().get_size());
can_snap = true;
}
if (can_snap) {
- _snap_if_closer(p_target, begin, output, snapped, rotation);
- _snap_if_closer(p_target, (begin + end) / 2.0, output, snapped, rotation);
- _snap_if_closer(p_target, end, output, snapped, rotation);
+ _snap_if_closer_point(p_target, begin, output, snapped, rotation);
+ _snap_if_closer_point(p_target, (begin + end) / 2.0, output, snapped, rotation);
+ _snap_if_closer_point(p_target, end, output, snapped, rotation);
}
}
@@ -302,26 +299,43 @@ Point2 CanvasItemEditor::snap_point(Point2 p_target, unsigned int p_modes, const
if (const Control *c = Object::cast_to<Control>(p_canvas_item)) {
begin = p_canvas_item->get_global_transform_with_canvas().xform(_anchor_to_position(c, Point2(c->get_anchor(MARGIN_LEFT), c->get_anchor(MARGIN_TOP))));
end = p_canvas_item->get_global_transform_with_canvas().xform(_anchor_to_position(c, Point2(c->get_anchor(MARGIN_RIGHT), c->get_anchor(MARGIN_BOTTOM))));
- _snap_if_closer(p_target, begin, output, snapped, rotation);
- _snap_if_closer(p_target, end, output, snapped, rotation);
+ _snap_if_closer_point(p_target, begin, output, snapped, rotation);
+ _snap_if_closer_point(p_target, end, output, snapped, rotation);
}
}
// Self sides (for anchors)
if ((snap_active && snap_node_sides && (p_modes & SNAP_NODE_SIDES)) || (p_forced_modes & SNAP_NODE_SIDES)) {
- begin = p_canvas_item->get_global_transform_with_canvas().xform(p_canvas_item->get_item_rect().get_position());
- end = p_canvas_item->get_global_transform_with_canvas().xform(p_canvas_item->get_item_rect().get_position() + p_canvas_item->get_item_rect().get_size());
- _snap_if_closer(p_target, begin, output, snapped, rotation);
- _snap_if_closer(p_target, end, output, snapped, rotation);
+ begin = p_canvas_item->get_global_transform_with_canvas().xform(p_canvas_item->_edit_get_rect().get_position());
+ end = p_canvas_item->get_global_transform_with_canvas().xform(p_canvas_item->_edit_get_rect().get_position() + p_canvas_item->_edit_get_rect().get_size());
+ _snap_if_closer_point(p_target, begin, output, snapped, rotation);
+ _snap_if_closer_point(p_target, end, output, snapped, rotation);
+ }
+ }
+
+ // Other nodes sides
+ if ((snap_active && snap_other_nodes && (p_modes & SNAP_OTHER_NODES)) || (p_forced_modes & SNAP_OTHER_NODES)) {
+ _snap_other_nodes(p_target, output, snapped, get_tree()->get_edited_scene_root(), p_canvas_item);
+ }
+
+ if (((snap_active && snap_guides && (p_modes & SNAP_GUIDES)) || (p_forced_modes & SNAP_GUIDES)) && fmod(rotation, (real_t)360.0) == 0.0) {
+ // Guides
+ if (EditorNode::get_singleton()->get_edited_scene() && EditorNode::get_singleton()->get_edited_scene()->has_meta("_edit_vertical_guides_")) {
+ Array vguides = EditorNode::get_singleton()->get_edited_scene()->get_meta("_edit_vertical_guides_");
+ for (int i = 0; i < vguides.size(); i++) {
+ _snap_if_closer_float(p_target.x, vguides[i], output.x, snapped[0]);
+ }
}
- // Other nodes sides
- if ((snap_active && snap_other_nodes && (p_modes & SNAP_OTHER_NODES)) || (p_forced_modes & SNAP_OTHER_NODES)) {
- _snap_other_nodes(p_target, output, snapped, get_tree()->get_edited_scene_root(), p_canvas_item);
+ if (EditorNode::get_singleton()->get_edited_scene() && EditorNode::get_singleton()->get_edited_scene()->has_meta("_edit_horizontal_guides_")) {
+ Array hguides = EditorNode::get_singleton()->get_edited_scene()->get_meta("_edit_horizontal_guides_");
+ for (int i = 0; i < hguides.size(); i++) {
+ _snap_if_closer_float(p_target.y, hguides[i], output.y, snapped[1]);
+ }
}
}
- if (((snap_active && snap_grid && (p_modes & SNAP_GRID)) || (p_forced_modes & SNAP_GRID)) && rotation == 0.0) {
+ if (((snap_active && snap_grid && (p_modes & SNAP_GRID)) || (p_forced_modes & SNAP_GRID)) && fmod(rotation, (real_t)360.0) == 0.0) {
// Grid
Point2 offset = grid_offset;
if (snap_relative) {
@@ -335,7 +349,7 @@ Point2 CanvasItemEditor::snap_point(Point2 p_target, unsigned int p_modes, const
Point2 grid_output;
grid_output.x = Math::stepify(p_target.x - offset.x, grid_step.x * Math::pow(2.0, grid_step_multiplier)) + offset.x;
grid_output.y = Math::stepify(p_target.y - offset.y, grid_step.y * Math::pow(2.0, grid_step_multiplier)) + offset.y;
- _snap_if_closer(p_target, grid_output, output, snapped, 0.0, -1.0);
+ _snap_if_closer_point(p_target, grid_output, output, snapped, 0.0, -1.0);
}
if (((snap_pixel && (p_modes & SNAP_PIXEL)) || (p_forced_modes & SNAP_PIXEL)) && rotation == 0.0) {
@@ -429,8 +443,10 @@ Dictionary CanvasItemEditor::get_state() const {
state["snap_node_sides"] = snap_node_sides;
state["snap_other_nodes"] = snap_other_nodes;
state["snap_grid"] = snap_grid;
+ state["snap_guides"] = snap_guides;
state["show_grid"] = show_grid;
state["show_rulers"] = show_rulers;
+ state["show_guides"] = show_guides;
state["show_helpers"] = show_helpers;
state["snap_rotation"] = snap_rotation;
state["snap_relative"] = snap_relative;
@@ -497,6 +513,12 @@ void CanvasItemEditor::set_state(const Dictionary &p_state) {
smartsnap_config_popup->set_item_checked(idx, snap_other_nodes);
}
+ if (state.has("snap_guides")) {
+ snap_guides = state["snap_guides"];
+ int idx = smartsnap_config_popup->get_item_index(SNAP_USE_GUIDES);
+ smartsnap_config_popup->set_item_checked(idx, snap_guides);
+ }
+
if (state.has("snap_grid")) {
snap_grid = state["snap_grid"];
int idx = snap_config_menu->get_popup()->get_item_index(SNAP_USE_GRID);
@@ -515,6 +537,12 @@ void CanvasItemEditor::set_state(const Dictionary &p_state) {
view_menu->get_popup()->set_item_checked(idx, show_rulers);
}
+ if (state.has("show_guides")) {
+ show_guides = state["show_guides"];
+ int idx = view_menu->get_popup()->get_item_index(SHOW_GUIDES);
+ view_menu->get_popup()->set_item_checked(idx, show_guides);
+ }
+
if (state.has("show_helpers")) {
show_helpers = state["show_helpers"];
int idx = view_menu->get_popup()->get_item_index(SHOW_HELPERS);
@@ -601,7 +629,7 @@ void CanvasItemEditor::_find_canvas_items_at_pos(const Point2 &p_pos, Node *p_no
if (c && c->is_visible_in_tree() && !c->has_meta("_edit_lock_") && !Object::cast_to<CanvasLayer>(c)) {
- Rect2 rect = c->get_item_rect();
+ Rect2 rect = c->_edit_get_rect();
Point2 local_pos = (p_parent_xform * p_canvas_xform * c->get_transform()).affine_inverse().xform(p_pos);
if (rect.has_point(local_pos)) {
@@ -647,7 +675,7 @@ void CanvasItemEditor::_find_canvas_items_at_rect(const Rect2 &p_rect, Node *p_n
if (c && c->is_visible_in_tree() && !c->has_meta("_edit_lock_") && !Object::cast_to<CanvasLayer>(c)) {
- Rect2 rect = c->get_item_rect();
+ Rect2 rect = c->_edit_get_rect();
Transform2D xform = p_parent_xform * p_canvas_xform * c->get_transform();
if (p_rect.has_point(xform.xform(rect.position)) &&
@@ -739,15 +767,15 @@ void CanvasItemEditor::_key_move(const Vector2 &p_dir, bool p_snap, KeyMoveMODE
if (p_snap)
drag *= grid_step * Math::pow(2.0, grid_step_multiplier);
- undo_redo->add_undo_method(canvas_item, "edit_set_state", canvas_item->edit_get_state());
+ undo_redo->add_undo_method(canvas_item, "_edit_set_state", canvas_item->_edit_get_state());
if (p_move_mode == MOVE_VIEW_BASE) {
// drag = transform.affine_inverse().basis_xform(p_dir); // zoom sensitive
drag = canvas_item->get_global_transform_with_canvas().affine_inverse().basis_xform(drag);
- Rect2 local_rect = canvas_item->get_item_rect();
+ Rect2 local_rect = canvas_item->_edit_get_rect();
local_rect.position += drag;
- undo_redo->add_do_method(canvas_item, "edit_set_rect", local_rect);
+ undo_redo->add_do_method(canvas_item, "_edit_set_rect", local_rect);
} else { // p_move_mode==MOVE_LOCAL_BASE || p_move_mode==MOVE_LOCAL_WITH_ROT
@@ -788,7 +816,7 @@ Point2 CanvasItemEditor::_find_topleftmost_point() {
if (canvas_item->get_viewport() != EditorNode::get_singleton()->get_scene_root())
continue;
- Rect2 rect = canvas_item->get_item_rect();
+ Rect2 rect = canvas_item->_edit_get_rect();
Transform2D xform = canvas_item->get_global_transform_with_canvas();
r2.expand_to(xform.xform(rect.position));
@@ -849,7 +877,7 @@ CanvasItemEditor::DragType CanvasItemEditor::_get_resize_handle_drag_type(const
ERR_FAIL_COND_V(!canvas_item, DRAG_NONE);
- Rect2 rect = canvas_item->get_item_rect();
+ Rect2 rect = canvas_item->_edit_get_rect();
Transform2D xforml = canvas_item->get_global_transform_with_canvas();
Transform2D xform = transform * xforml;
@@ -983,17 +1011,17 @@ void CanvasItemEditor::_prepare_drag(const Point2 &p_click_pos) {
if (!se)
continue;
- se->undo_state = canvas_item->edit_get_state();
+ se->undo_state = canvas_item->_edit_get_state();
if (Object::cast_to<Node2D>(canvas_item))
- se->undo_pivot = Object::cast_to<Node2D>(canvas_item)->edit_get_pivot();
+ se->undo_pivot = Object::cast_to<Node2D>(canvas_item)->_edit_get_pivot();
if (Object::cast_to<Control>(canvas_item))
se->undo_pivot = Object::cast_to<Control>(canvas_item)->get_pivot_offset();
se->pre_drag_xform = canvas_item->get_global_transform_with_canvas();
- se->pre_drag_rect = canvas_item->get_item_rect();
+ se->pre_drag_rect = canvas_item->_edit_get_rect();
}
- if (selection.size() == 1 && Object::cast_to<Node2D>(selection[0])) {
+ if (selection.size() == 1 && Object::cast_to<Node2D>(selection[0]) && bone_ik_list.size() == 0) {
drag = DRAG_NODE_2D;
drag_point_from = Object::cast_to<Node2D>(selection[0])->get_global_position();
} else {
@@ -1198,14 +1226,215 @@ void CanvasItemEditor::_update_cursor() {
viewport->set_default_cursor_shape(c);
}
-void CanvasItemEditor::_viewport_base_gui_input(const Ref<InputEvent> &p_event) {
+void CanvasItemEditor::_gui_input_viewport_base(const Ref<InputEvent> &p_event) {
+
+ Ref<InputEventMouseButton> b = p_event;
+ if (b.is_valid()) {
+ if (b->get_button_index() == BUTTON_LEFT && b->is_pressed()) {
+ if (show_guides && show_rulers && EditorNode::get_singleton()->get_edited_scene()) {
+ Transform2D xform = viewport_scrollable->get_transform() * transform;
+ // Retreive the guide lists
+ Array vguides;
+ if (EditorNode::get_singleton()->get_edited_scene()->has_meta("_edit_vertical_guides_")) {
+ vguides = EditorNode::get_singleton()->get_edited_scene()->get_meta("_edit_vertical_guides_");
+ }
+ Array hguides;
+ if (EditorNode::get_singleton()->get_edited_scene()->has_meta("_edit_horizontal_guides_")) {
+ hguides = EditorNode::get_singleton()->get_edited_scene()->get_meta("_edit_horizontal_guides_");
+ }
+
+ // Press button
+ if (b->get_position().x < RULER_WIDTH && b->get_position().y < RULER_WIDTH) {
+ // Drag a new double guide
+ drag = DRAG_DOUBLE_GUIDE;
+ edited_guide_index = -1;
+ } else if (b->get_position().x < RULER_WIDTH) {
+ // Check if we drag an existing horizontal guide
+ float minimum = 1e20;
+ edited_guide_index = -1;
+ for (int i = 0; i < hguides.size(); i++) {
+ if (ABS(xform.xform(Point2(0, hguides[i])).y - b->get_position().y) < MIN(minimum, 8)) {
+ edited_guide_index = i;
+ }
+ }
+
+ if (edited_guide_index >= 0) {
+ // Drag an existing horizontal guide
+ drag = DRAG_H_GUIDE;
+ } else {
+ // Drag a new vertical guide
+ drag = DRAG_V_GUIDE;
+ }
+ } else if (b->get_position().y < RULER_WIDTH) {
+ // Check if we drag an existing vertical guide
+ float minimum = 1e20;
+ edited_guide_index = -1;
+ for (int i = 0; i < vguides.size(); i++) {
+ if (ABS(xform.xform(Point2(vguides[i], 0)).x - b->get_position().x) < MIN(minimum, 8)) {
+ edited_guide_index = i;
+ }
+ }
+
+ if (edited_guide_index >= 0) {
+ // Drag an existing vertical guide
+ drag = DRAG_V_GUIDE;
+ } else {
+ // Drag a new vertical guide
+ drag = DRAG_H_GUIDE;
+ }
+ }
+ }
+ }
+
+ if (b->get_button_index() == BUTTON_LEFT && !b->is_pressed()) {
+ // Release button
+ if (show_guides && EditorNode::get_singleton()->get_edited_scene()) {
+ Transform2D xform = viewport_scrollable->get_transform() * transform;
+
+ // Retreive the guide lists
+ Array vguides;
+ if (EditorNode::get_singleton()->get_edited_scene()->has_meta("_edit_vertical_guides_")) {
+ vguides = EditorNode::get_singleton()->get_edited_scene()->get_meta("_edit_vertical_guides_");
+ }
+ Array hguides;
+ if (EditorNode::get_singleton()->get_edited_scene()->has_meta("_edit_horizontal_guides_")) {
+ hguides = EditorNode::get_singleton()->get_edited_scene()->get_meta("_edit_horizontal_guides_");
+ }
+
+ Point2 edited = snap_point(xform.affine_inverse().xform(b->get_position()), SNAP_GRID | SNAP_PIXEL | SNAP_OTHER_NODES);
+ if (drag == DRAG_V_GUIDE) {
+ Array prev_vguides = vguides.duplicate();
+ if (b->get_position().x > RULER_WIDTH) {
+ // Adds a new vertical guide
+ if (edited_guide_index >= 0) {
+ vguides[edited_guide_index] = edited.x;
+ undo_redo->create_action(TTR("Move vertical guide"));
+ undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_vertical_guides_", vguides);
+ undo_redo->add_undo_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_vertical_guides_", prev_vguides);
+ undo_redo->add_undo_method(viewport_base, "update");
+ undo_redo->commit_action();
+ } else {
+ vguides.push_back(edited.x);
+ undo_redo->create_action(TTR("Create new vertical guide"));
+ undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_vertical_guides_", vguides);
+ undo_redo->add_undo_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_vertical_guides_", prev_vguides);
+ undo_redo->add_undo_method(viewport_base, "update");
+ undo_redo->commit_action();
+ }
+ } else {
+ if (edited_guide_index >= 0) {
+ vguides.remove(edited_guide_index);
+ undo_redo->create_action(TTR("Remove vertical guide"));
+ undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_vertical_guides_", vguides);
+ undo_redo->add_undo_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_vertical_guides_", prev_vguides);
+ undo_redo->add_undo_method(viewport_base, "update");
+ undo_redo->commit_action();
+ }
+ }
+ } else if (drag == DRAG_H_GUIDE) {
+ Array prev_hguides = hguides.duplicate();
+ if (b->get_position().y > RULER_WIDTH) {
+ // Adds a new horizontal guide
+ if (edited_guide_index >= 0) {
+ hguides[edited_guide_index] = edited.y;
+ undo_redo->create_action(TTR("Move horizontal guide"));
+ undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_horizontal_guides_", hguides);
+ undo_redo->add_undo_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_horizontal_guides_", prev_hguides);
+ undo_redo->add_undo_method(viewport_base, "update");
+ undo_redo->commit_action();
+ } else {
+ hguides.push_back(edited.y);
+ undo_redo->create_action(TTR("Create new horizontal guide"));
+ undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_horizontal_guides_", hguides);
+ undo_redo->add_undo_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_horizontal_guides_", prev_hguides);
+ undo_redo->add_undo_method(viewport_base, "update");
+ undo_redo->commit_action();
+ }
+ } else {
+ if (edited_guide_index >= 0) {
+ hguides.remove(edited_guide_index);
+ undo_redo->create_action(TTR("Remove horizontal guide"));
+ undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_horizontal_guides_", hguides);
+ undo_redo->add_undo_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_horizontal_guides_", prev_hguides);
+ undo_redo->add_undo_method(viewport_base, "update");
+ undo_redo->commit_action();
+ }
+ }
+ } else if (drag == DRAG_DOUBLE_GUIDE) {
+ Array prev_hguides = hguides.duplicate();
+ Array prev_vguides = vguides.duplicate();
+ if (b->get_position().x > RULER_WIDTH && b->get_position().y > RULER_WIDTH) {
+ // Adds a new horizontal guide a new vertical guide
+ vguides.push_back(edited.x);
+ hguides.push_back(edited.y);
+ undo_redo->create_action(TTR("Create new horizontal and vertical guides"));
+ undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_vertical_guides_", vguides);
+ undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_horizontal_guides_", hguides);
+ undo_redo->add_undo_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_vertical_guides_", prev_vguides);
+ undo_redo->add_undo_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_horizontal_guides_", prev_hguides);
+ undo_redo->add_undo_method(viewport_base, "update");
+ undo_redo->commit_action();
+ }
+ }
+ }
+ if (drag == DRAG_DOUBLE_GUIDE || drag == DRAG_V_GUIDE || drag == DRAG_H_GUIDE) {
+ drag = DRAG_NONE;
+ viewport_base->update();
+ }
+ }
+ }
+
+ Ref<InputEventMouseMotion> m = p_event;
+ if (m.is_valid()) {
+ if (!viewport_base->has_focus() && (!get_focus_owner() || !get_focus_owner()->is_text_field())) {
+ viewport_base->call_deferred("grab_focus");
+ }
+ if (drag == DRAG_DOUBLE_GUIDE || drag == DRAG_H_GUIDE || drag == DRAG_V_GUIDE) {
+ Transform2D xform = viewport_scrollable->get_transform() * transform;
+ Point2 mouse_pos = m->get_position();
+ mouse_pos = xform.affine_inverse().xform(mouse_pos);
+ mouse_pos = xform.xform(snap_point(mouse_pos, SNAP_GRID | SNAP_PIXEL | SNAP_OTHER_NODES));
+
+ edited_guide_pos = mouse_pos;
+ viewport_base->update();
+ }
+ }
+
+ Ref<InputEventKey> k = p_event;
+ if (k.is_valid()) {
+ if (k->is_pressed() && drag == DRAG_NONE) {
+ // Move the object with the arrow keys
+ KeyMoveMODE move_mode = MOVE_VIEW_BASE;
+ if (k->get_alt()) move_mode = MOVE_LOCAL_BASE;
+ if (k->get_control() || k->get_metakey()) move_mode = MOVE_LOCAL_WITH_ROT;
+
+ if (k->get_scancode() == KEY_UP)
+ _key_move(Vector2(0, -1), k->get_shift(), move_mode);
+ else if (k->get_scancode() == KEY_DOWN)
+ _key_move(Vector2(0, 1), k->get_shift(), move_mode);
+ else if (k->get_scancode() == KEY_LEFT)
+ _key_move(Vector2(-1, 0), k->get_shift(), move_mode);
+ else if (k->get_scancode() == KEY_RIGHT)
+ _key_move(Vector2(1, 0), k->get_shift(), move_mode);
+ else if (k->get_scancode() == KEY_ESCAPE) {
+ editor_selection->clear();
+ viewport->update();
+ } else
+ return;
+
+ accept_event();
+ }
+ }
+}
+
+void CanvasItemEditor::_gui_input_viewport(const Ref<InputEvent> &p_event) {
{
EditorNode *en = editor;
EditorPluginList *over_plugin_list = en->get_editor_plugins_over();
if (!over_plugin_list->empty()) {
- bool discard = over_plugin_list->forward_gui_input(transform, p_event);
+ bool discard = over_plugin_list->forward_gui_input(p_event);
if (discard) {
accept_event();
return;
@@ -1213,6 +1442,22 @@ void CanvasItemEditor::_viewport_base_gui_input(const Ref<InputEvent> &p_event)
}
}
+ Ref<InputEventMagnifyGesture> magnify_gesture = p_event;
+ if (magnify_gesture.is_valid()) {
+
+ _zoom_on_position(zoom * magnify_gesture->get_factor(), magnify_gesture->get_position());
+ return;
+ }
+
+ Ref<InputEventPanGesture> pan_gesture = p_event;
+ if (pan_gesture.is_valid()) {
+
+ const Vector2 delta = (int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom) * pan_gesture->get_delta();
+ h_scroll->set_value(h_scroll->get_value() + delta.x);
+ v_scroll->set_value(v_scroll->get_value() + delta.y);
+ return;
+ }
+
Ref<InputEventMouseButton> b = p_event;
if (b.is_valid()) {
// Button event
@@ -1224,7 +1469,7 @@ void CanvasItemEditor::_viewport_base_gui_input(const Ref<InputEvent> &p_event)
_update_scroll(0);
viewport->update();
} else {
- _zoom_on_position(zoom * (1 - (0.05 * b->get_factor())), viewport_scrollable->get_transform().affine_inverse().xform(b->get_position()));
+ _zoom_on_position(zoom * (1 - (0.05 * b->get_factor())), b->get_position());
}
return;
@@ -1237,7 +1482,7 @@ void CanvasItemEditor::_viewport_base_gui_input(const Ref<InputEvent> &p_event)
_update_scroll(0);
viewport->update();
} else {
- _zoom_on_position(zoom * ((0.95 + (0.05 * b->get_factor())) / 0.95), viewport_scrollable->get_transform().affine_inverse().xform(b->get_position()));
+ _zoom_on_position(zoom * ((0.95 + (0.05 * b->get_factor())) / 0.95), b->get_position());
}
return;
@@ -1271,7 +1516,7 @@ void CanvasItemEditor::_viewport_base_gui_input(const Ref<InputEvent> &p_event)
// Cancel a drag
if (bone_ik_list.size()) {
for (List<BoneIK>::Element *E = bone_ik_list.back(); E; E = E->prev()) {
- E->get().node->edit_set_state(E->get().orig_state);
+ E->get().node->_edit_set_state(E->get().orig_state);
}
bone_ik_list.clear();
@@ -1290,9 +1535,9 @@ void CanvasItemEditor::_viewport_base_gui_input(const Ref<InputEvent> &p_event)
if (!se)
continue;
- canvas_item->edit_set_state(se->undo_state);
+ canvas_item->_edit_set_state(se->undo_state);
if (Object::cast_to<Node2D>(canvas_item))
- Object::cast_to<Node2D>(canvas_item)->edit_set_pivot(se->undo_pivot);
+ Object::cast_to<Node2D>(canvas_item)->_edit_set_pivot(se->undo_pivot);
if (Object::cast_to<Control>(canvas_item))
Object::cast_to<Control>(canvas_item)->set_pivot_offset(se->undo_pivot);
}
@@ -1320,7 +1565,7 @@ void CanvasItemEditor::_viewport_base_gui_input(const Ref<InputEvent> &p_event)
if (b->get_button_index() == BUTTON_LEFT && tool == TOOL_EDIT_PIVOT) {
if (b->is_pressed()) {
// Set the pivot point
- Point2 mouse_pos = viewport_scrollable->get_transform().affine_inverse().xform(b->get_position());
+ Point2 mouse_pos = b->get_position();
mouse_pos = transform.affine_inverse().xform(mouse_pos);
mouse_pos = snap_point(mouse_pos, SNAP_DEFAULT, _get_single_item());
_edit_set_pivot(mouse_pos);
@@ -1345,8 +1590,8 @@ void CanvasItemEditor::_viewport_base_gui_input(const Ref<InputEvent> &p_event)
for (List<BoneIK>::Element *E = bone_ik_list.back(); E; E = E->prev()) {
- undo_redo->add_do_method(E->get().node, "edit_set_state", E->get().node->edit_get_state());
- undo_redo->add_undo_method(E->get().node, "edit_set_state", E->get().orig_state);
+ undo_redo->add_do_method(E->get().node, "_edit_set_state", E->get().node->_edit_get_state());
+ undo_redo->add_undo_method(E->get().node, "_edit_set_state", E->get().orig_state);
}
undo_redo->add_do_method(viewport, "update");
@@ -1372,14 +1617,14 @@ void CanvasItemEditor::_viewport_base_gui_input(const Ref<InputEvent> &p_event)
if (!se)
continue;
- Variant state = canvas_item->edit_get_state();
- undo_redo->add_do_method(canvas_item, "edit_set_state", state);
- undo_redo->add_undo_method(canvas_item, "edit_set_state", se->undo_state);
+ Variant state = canvas_item->_edit_get_state();
+ undo_redo->add_do_method(canvas_item, "_edit_set_state", state);
+ undo_redo->add_undo_method(canvas_item, "_edit_set_state", se->undo_state);
{
Node2D *pvt = Object::cast_to<Node2D>(canvas_item);
- if (pvt && pvt->edit_has_pivot()) {
- undo_redo->add_do_method(canvas_item, "edit_set_pivot", pvt->edit_get_pivot());
- undo_redo->add_undo_method(canvas_item, "edit_set_pivot", se->undo_pivot);
+ if (pvt && pvt->_edit_use_pivot()) {
+ undo_redo->add_do_method(canvas_item, "_edit_set_pivot", pvt->_edit_get_pivot());
+ undo_redo->add_undo_method(canvas_item, "_edit_set_pivot", se->undo_pivot);
}
Control *cnt = Object::cast_to<Control>(canvas_item);
@@ -1443,8 +1688,8 @@ void CanvasItemEditor::_viewport_base_gui_input(const Ref<InputEvent> &p_event)
E->get().to
};
- Vector2 p = Geometry::get_closest_point_to_segment_2d(viewport_scrollable->get_transform().affine_inverse().xform(b->get_position()), s);
- float d = p.distance_to(viewport_scrollable->get_transform().affine_inverse().xform(b->get_position()));
+ Vector2 p = Geometry::get_closest_point_to_segment_2d(b->get_position(), s);
+ float d = p.distance_to(b->get_position());
if (d < bone_width && d < closest_dist) {
Cbone = E;
closest_dist = d;
@@ -1480,7 +1725,7 @@ void CanvasItemEditor::_viewport_base_gui_input(const Ref<InputEvent> &p_event)
BoneIK bik;
bik.node = b;
bik.len = len;
- bik.orig_state = b->edit_get_state();
+ bik.orig_state = b->_edit_get_state();
bone_ik_list.push_back(bik);
@@ -1506,19 +1751,19 @@ void CanvasItemEditor::_viewport_base_gui_input(const Ref<InputEvent> &p_event)
CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
ERR_FAIL_COND(!se);
- Point2 click = viewport_scrollable->get_transform().affine_inverse().xform(b->get_position());
+ Point2 click = b->get_position();
// Rotation
if ((b->get_control() && tool == TOOL_SELECT) || tool == TOOL_ROTATE) {
drag = DRAG_ROTATE;
drag_from = transform.affine_inverse().xform(click);
- se->undo_state = canvas_item->edit_get_state();
+ se->undo_state = canvas_item->_edit_get_state();
if (Object::cast_to<Node2D>(canvas_item))
- se->undo_pivot = Object::cast_to<Node2D>(canvas_item)->edit_get_pivot();
+ se->undo_pivot = Object::cast_to<Node2D>(canvas_item)->_edit_get_pivot();
if (Object::cast_to<Control>(canvas_item))
se->undo_pivot = Object::cast_to<Control>(canvas_item)->get_pivot_offset();
se->pre_drag_xform = canvas_item->get_global_transform_with_canvas();
- se->pre_drag_rect = canvas_item->get_item_rect();
+ se->pre_drag_rect = canvas_item->_edit_get_rect();
return;
}
@@ -1535,13 +1780,13 @@ void CanvasItemEditor::_viewport_base_gui_input(const Ref<InputEvent> &p_event)
drag = _get_resize_handle_drag_type(click, drag_point_from);
if (drag != DRAG_NONE) {
drag_from = transform.affine_inverse().xform(click);
- se->undo_state = canvas_item->edit_get_state();
+ se->undo_state = canvas_item->_edit_get_state();
if (Object::cast_to<Node2D>(canvas_item))
- se->undo_pivot = Object::cast_to<Node2D>(canvas_item)->edit_get_pivot();
+ se->undo_pivot = Object::cast_to<Node2D>(canvas_item)->_edit_get_pivot();
if (Object::cast_to<Control>(canvas_item))
se->undo_pivot = Object::cast_to<Control>(canvas_item)->get_pivot_offset();
se->pre_drag_xform = canvas_item->get_global_transform_with_canvas();
- se->pre_drag_rect = canvas_item->get_item_rect();
+ se->pre_drag_rect = canvas_item->_edit_get_rect();
return;
}
@@ -1551,9 +1796,9 @@ void CanvasItemEditor::_viewport_base_gui_input(const Ref<InputEvent> &p_event)
drag = _get_anchor_handle_drag_type(click, drag_point_from);
if (drag != DRAG_NONE) {
drag_from = transform.affine_inverse().xform(click);
- se->undo_state = canvas_item->edit_get_state();
+ se->undo_state = canvas_item->_edit_get_state();
se->pre_drag_xform = canvas_item->get_global_transform_with_canvas();
- se->pre_drag_rect = canvas_item->get_item_rect();
+ se->pre_drag_rect = canvas_item->_edit_get_rect();
return;
}
}
@@ -1561,7 +1806,7 @@ void CanvasItemEditor::_viewport_base_gui_input(const Ref<InputEvent> &p_event)
}
// Multiple selected items
- Point2 click = viewport_scrollable->get_transform().affine_inverse().xform(b->get_position());
+ Point2 click = b->get_position();
if ((b->get_alt() || tool == TOOL_MOVE) && get_item_count()) {
// Drag the nodes
@@ -1621,18 +1866,25 @@ void CanvasItemEditor::_viewport_base_gui_input(const Ref<InputEvent> &p_event)
// Mouse motion event
_update_cursor();
- if (!viewport_base->has_focus() && (!get_focus_owner() || !get_focus_owner()->is_text_field()))
- viewport_base->call_deferred("grab_focus");
-
if (box_selecting) {
// Update box selection
- box_selecting_to = transform.affine_inverse().xform(viewport_scrollable->get_transform().affine_inverse().xform(m->get_position()));
+ box_selecting_to = transform.affine_inverse().xform(m->get_position());
viewport->update();
return;
}
if (drag == DRAG_NONE) {
- if (((m->get_button_mask() & BUTTON_MASK_LEFT) && tool == TOOL_PAN) || (m->get_button_mask() & BUTTON_MASK_MIDDLE) || ((m->get_button_mask() & BUTTON_MASK_LEFT) && Input::get_singleton()->is_key_pressed(KEY_SPACE))) {
+ bool space_pressed = Input::get_singleton()->is_key_pressed(KEY_SPACE);
+ bool simple_panning = EditorSettings::get_singleton()->get("editors/2d/simple_spacebar_panning");
+ int button = m->get_button_mask();
+
+ // Check if any of the panning triggers are activated
+ bool panning_tool = (button & BUTTON_MASK_LEFT) && tool == TOOL_PAN;
+ bool panning_middle_button = button & BUTTON_MASK_MIDDLE;
+ bool panning_spacebar = (button & BUTTON_MASK_LEFT) && space_pressed;
+ bool panning_spacebar_simple = space_pressed && simple_panning;
+
+ if (panning_tool || panning_middle_button || panning_spacebar || panning_spacebar_simple) {
// Pan the viewport
Point2i relative;
if (bool(EditorSettings::get_singleton()->get("editors/2d/warped_mouse_panning"))) {
@@ -1664,15 +1916,15 @@ void CanvasItemEditor::_viewport_base_gui_input(const Ref<InputEvent> &p_event)
bool dragging_bone = drag == DRAG_ALL && selection.size() == 1 && bone_ik_list.size();
if (!dragging_bone) {
- canvas_item->edit_set_state(se->undo_state); //reset state and reapply
+ canvas_item->_edit_set_state(se->undo_state); //reset state and reapply
if (Object::cast_to<Node2D>(canvas_item))
- Object::cast_to<Node2D>(canvas_item)->edit_set_pivot(se->undo_pivot);
+ Object::cast_to<Node2D>(canvas_item)->_edit_set_pivot(se->undo_pivot);
if (Object::cast_to<Control>(canvas_item))
Object::cast_to<Control>(canvas_item)->set_pivot_offset(se->undo_pivot);
}
Vector2 dfrom = drag_from;
- Vector2 dto = transform.affine_inverse().xform(viewport_scrollable->get_transform().affine_inverse().xform(m->get_position()));
+ Vector2 dto = transform.affine_inverse().xform(m->get_position());
if (canvas_item->has_meta("_edit_lock_"))
continue;
@@ -1735,7 +1987,7 @@ void CanvasItemEditor::_viewport_base_gui_input(const Ref<InputEvent> &p_event)
Vector2 anchor = c_trans_rev.xform(dto - drag_from + drag_point_from);
anchor = _position_to_anchor(control, anchor);
- Vector2 anchor_snapped = c_trans_rev.xform(snap_point(dto - drag_from + drag_point_from, SNAP_GRID | SNAP_OTHER_NODES, _get_single_item(), SNAP_NODE_PARENT | SNAP_NODE_SIDES));
+ Vector2 anchor_snapped = c_trans_rev.xform(snap_point(dto - drag_from + drag_point_from, SNAP_GRID | SNAP_GUIDES | SNAP_OTHER_NODES, _get_single_item(), SNAP_NODE_PARENT | SNAP_NODE_SIDES));
anchor_snapped = _position_to_anchor(control, anchor_snapped).snapped(Vector2(0.00001, 0.00001));
bool use_y = Math::abs(drag_vector.y) > Math::abs(drag_vector.x);
@@ -1771,16 +2023,16 @@ void CanvasItemEditor::_viewport_base_gui_input(const Ref<InputEvent> &p_event)
}
dfrom = drag_point_from;
- dto = snap_point(dto, SNAP_NODE_ANCHORS | SNAP_NODE_PARENT | SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL, _get_single_item());
+ dto = snap_point(dto, SNAP_NODE_ANCHORS | SNAP_NODE_PARENT | SNAP_OTHER_NODES | SNAP_GRID | SNAP_GUIDES | SNAP_PIXEL, _get_single_item());
drag_vector =
canvas_item->get_global_transform_with_canvas().affine_inverse().xform(dto) -
canvas_item->get_global_transform_with_canvas().affine_inverse().xform(dfrom);
- Rect2 local_rect = canvas_item->get_item_rect();
+ Rect2 local_rect = canvas_item->_edit_get_rect();
Vector2 begin = local_rect.position;
Vector2 end = local_rect.position + local_rect.size;
- Vector2 minsize = canvas_item->edit_get_minimum_size();
+ Vector2 minsize = canvas_item->_edit_get_minimum_size();
if (uniform) {
// Keep the height/width ratio of the item
@@ -1858,7 +2110,7 @@ void CanvasItemEditor::_viewport_base_gui_input(const Ref<InputEvent> &p_event)
if (Object::cast_to<Node2D>(canvas_item)) {
Node2D *n2d = Object::cast_to<Node2D>(canvas_item);
- n2d->edit_set_pivot(se->undo_pivot + drag_vector);
+ n2d->_edit_set_pivot(se->undo_pivot + drag_vector);
}
if (Object::cast_to<Control>(canvas_item)) {
Object::cast_to<Control>(canvas_item)->set_pivot_offset(se->undo_pivot + drag_vector);
@@ -1877,7 +2129,7 @@ void CanvasItemEditor::_viewport_base_gui_input(const Ref<InputEvent> &p_event)
local_rect.position = begin;
local_rect.size = end - begin;
- canvas_item->edit_set_rect(local_rect);
+ canvas_item->_edit_set_rect(local_rect);
} else {
//ok, all that had to be done was done, now solve IK
@@ -1995,32 +2247,6 @@ void CanvasItemEditor::_viewport_base_gui_input(const Ref<InputEvent> &p_event)
}
}
}
-
- Ref<InputEventKey> k = p_event;
- if (k.is_valid()) {
- if (k->is_pressed() && drag == DRAG_NONE) {
- // Move the object with the arrow keys
- KeyMoveMODE move_mode = MOVE_VIEW_BASE;
- if (k->get_alt()) move_mode = MOVE_LOCAL_BASE;
- if (k->get_control() || k->get_metakey()) move_mode = MOVE_LOCAL_WITH_ROT;
-
- if (k->get_scancode() == KEY_UP)
- _key_move(Vector2(0, -1), k->get_shift(), move_mode);
- else if (k->get_scancode() == KEY_DOWN)
- _key_move(Vector2(0, 1), k->get_shift(), move_mode);
- else if (k->get_scancode() == KEY_LEFT)
- _key_move(Vector2(-1, 0), k->get_shift(), move_mode);
- else if (k->get_scancode() == KEY_RIGHT)
- _key_move(Vector2(1, 0), k->get_shift(), move_mode);
- else if (k->get_scancode() == KEY_ESCAPE) {
- editor_selection->clear();
- viewport->update();
- } else
- return;
-
- accept_event();
- }
- }
}
void CanvasItemEditor::_draw_text_at_position(Point2 p_position, String p_string, Margin p_side) {
@@ -2059,6 +2285,58 @@ void CanvasItemEditor::_draw_percentage_at_position(float p_value, Point2 p_posi
}
}
+void CanvasItemEditor::_draw_focus() {
+ // Draw the focus around the base viewport
+ if (viewport_base->has_focus()) {
+ get_stylebox("Focus", "EditorStyles")->draw(viewport_base->get_canvas_item(), Rect2(Point2(), viewport_base->get_size()));
+ }
+}
+
+void CanvasItemEditor::_draw_guides() {
+
+ Color guide_color = Color(0.6, 0.0, 0.8);
+ Transform2D xform = viewport_scrollable->get_transform() * transform;
+
+ // Guides already there
+ if (EditorNode::get_singleton()->get_edited_scene() && EditorNode::get_singleton()->get_edited_scene()->has_meta("_edit_vertical_guides_")) {
+ Array vguides = EditorNode::get_singleton()->get_edited_scene()->get_meta("_edit_vertical_guides_");
+ for (int i = 0; i < vguides.size(); i++) {
+ if (drag == DRAG_V_GUIDE && i == edited_guide_index)
+ continue;
+ float x = xform.xform(Point2(vguides[i], 0)).x;
+ viewport_base->draw_line(Point2(x, 0), Point2(x, viewport_base->get_size().y), guide_color);
+ }
+ }
+
+ if (EditorNode::get_singleton()->get_edited_scene() && EditorNode::get_singleton()->get_edited_scene()->has_meta("_edit_horizontal_guides_")) {
+ Array hguides = EditorNode::get_singleton()->get_edited_scene()->get_meta("_edit_horizontal_guides_");
+ for (int i = 0; i < hguides.size(); i++) {
+ if (drag == DRAG_H_GUIDE && i == edited_guide_index)
+ continue;
+ float y = xform.xform(Point2(0, hguides[i])).y;
+ viewport_base->draw_line(Point2(0, y), Point2(viewport_base->get_size().x, y), guide_color);
+ }
+ }
+
+ // Dragged guide
+ Color text_color = get_color("font_color", "Editor");
+ text_color.a = 0.5;
+ if (drag == DRAG_DOUBLE_GUIDE || drag == DRAG_V_GUIDE) {
+ String str = vformat("%d px", xform.affine_inverse().xform(edited_guide_pos).x);
+ Ref<Font> font = get_font("font", "Label");
+ Size2 text_size = font->get_string_size(str);
+ viewport_base->draw_string(font, Point2(edited_guide_pos.x + 10, RULER_WIDTH + text_size.y / 2 + 10), str, text_color);
+ viewport_base->draw_line(Point2(edited_guide_pos.x, 0), Point2(edited_guide_pos.x, viewport_base->get_size().y), guide_color);
+ }
+ if (drag == DRAG_DOUBLE_GUIDE || drag == DRAG_H_GUIDE) {
+ String str = vformat("%d px", xform.affine_inverse().xform(edited_guide_pos).y);
+ Ref<Font> font = get_font("font", "Label");
+ Size2 text_size = font->get_string_size(str);
+ viewport_base->draw_string(font, Point2(RULER_WIDTH + 10, edited_guide_pos.y + text_size.y / 2 + 10), str, text_color);
+ viewport_base->draw_line(Point2(0, edited_guide_pos.y), Point2(viewport_base->get_size().x, edited_guide_pos.y), guide_color);
+ }
+}
+
void CanvasItemEditor::_draw_rulers() {
Color graduation_color = get_color("font_color", "Editor");
graduation_color.a = 0.5;
@@ -2143,12 +2421,6 @@ void CanvasItemEditor::_draw_rulers() {
viewport_base->draw_rect(Rect2(Point2(), Size2(RULER_WIDTH, RULER_WIDTH)), graduation_color);
}
-void CanvasItemEditor::_draw_focus() {
- if (viewport_base->has_focus()) {
- get_stylebox("Focus", "EditorStyles")->draw(viewport_base->get_canvas_item(), Rect2(Point2(), viewport_base->get_size()));
- }
-}
-
void CanvasItemEditor::_draw_grid() {
if (show_grid) {
//Draw the grid
@@ -2159,8 +2431,8 @@ void CanvasItemEditor::_draw_grid() {
Vector2 real_grid_offset;
if (snap_relative && get_item_count() > 0) {
Vector2 topleft = _find_topleftmost_point();
- real_grid_offset.x = fmod(topleft.x, grid_step.x * Math::pow(2.0, grid_step_multiplier));
- real_grid_offset.y = fmod(topleft.y, grid_step.y * Math::pow(2.0, grid_step_multiplier));
+ real_grid_offset.x = fmod(topleft.x, grid_step.x * (real_t)Math::pow(2.0, grid_step_multiplier));
+ real_grid_offset.y = fmod(topleft.y, grid_step.y * (real_t)Math::pow(2.0, grid_step_multiplier));
} else {
real_grid_offset = grid_offset;
}
@@ -2208,7 +2480,7 @@ void CanvasItemEditor::_draw_selection() {
if (!se)
continue;
- Rect2 rect = canvas_item->get_item_rect();
+ Rect2 rect = canvas_item->_edit_get_rect();
if (show_helpers && drag != DRAG_NONE && drag != DRAG_PIVOT) {
const Transform2D pre_drag_xform = transform * se->pre_drag_xform;
@@ -2250,7 +2522,7 @@ void CanvasItemEditor::_draw_selection() {
Node2D *node2d = Object::cast_to<Node2D>(canvas_item);
if (node2d) {
- if (node2d->edit_has_pivot()) {
+ if (node2d->_edit_use_pivot()) {
viewport->draw_texture(pivot_icon, xform.get_origin() + (-pivot_icon->get_size() / 2).floor());
can_move_pivot = true;
pivot_found = true;
@@ -2622,7 +2894,7 @@ void CanvasItemEditor::_get_encompassing_rect(Node *p_node, Rect2 &r_rect, const
CanvasItem *c = Object::cast_to<CanvasItem>(p_node);
if (c && c->is_visible_in_tree()) {
- Rect2 rect = c->get_item_rect();
+ Rect2 rect = c->_edit_get_rect();
Transform2D xform = p_xform * c->get_transform();
r_rect.expand_to(xform.xform(rect.position));
r_rect.expand_to(xform.xform(rect.position + Point2(rect.size.x, 0)));
@@ -2634,6 +2906,8 @@ void CanvasItemEditor::_get_encompassing_rect(Node *p_node, Rect2 &r_rect, const
void CanvasItemEditor::_draw_viewport_base() {
if (show_rulers)
_draw_rulers();
+ if (show_guides)
+ _draw_guides();
_draw_focus();
}
@@ -2681,9 +2955,8 @@ void CanvasItemEditor::_draw_viewport() {
EditorPluginList *over_plugin_list = editor->get_editor_plugins_over();
if (!over_plugin_list->empty()) {
- over_plugin_list->forward_draw_over_canvas(transform, viewport);
+ over_plugin_list->forward_draw_over_canvas(viewport);
}
- _draw_focus();
_draw_bones();
}
@@ -2716,7 +2989,7 @@ void CanvasItemEditor::_notification(int p_what) {
if (!se)
continue;
- Rect2 r = canvas_item->get_item_rect();
+ Rect2 r = canvas_item->_edit_get_rect();
Transform2D xform = canvas_item->get_transform();
if (r != se->prev_rect || xform != se->prev_xform) {
@@ -2748,9 +3021,9 @@ void CanvasItemEditor::_notification(int p_what) {
}
if (all_control && has_control)
- anchor_menu->show();
+ presets_menu->show();
else
- anchor_menu->hide();
+ presets_menu->hide();
for (Map<ObjectID, BoneList>::Element *E = bone_list.front(); E; E = E->next()) {
@@ -2782,57 +3055,15 @@ void CanvasItemEditor::_notification(int p_what) {
select_sb->set_default_margin(Margin(i), 4);
}
- select_button->set_icon(get_icon("ToolSelect", "EditorIcons"));
- list_select_button->set_icon(get_icon("ListSelect", "EditorIcons"));
- move_button->set_icon(get_icon("ToolMove", "EditorIcons"));
- rotate_button->set_icon(get_icon("ToolRotate", "EditorIcons"));
- snap_button->set_icon(get_icon("Snap", "EditorIcons"));
- snap_config_menu->set_icon(get_icon("GuiMiniTabMenu", "EditorIcons"));
- skeleton_menu->set_icon(get_icon("Bone", "EditorIcons"));
- pan_button->set_icon(get_icon("ToolPan", "EditorIcons"));
- pivot_button->set_icon(get_icon("EditPivot", "EditorIcons"));
- select_handle = get_icon("EditorHandle", "EditorIcons");
- anchor_handle = get_icon("EditorControlAnchor", "EditorIcons");
- lock_button->set_icon(get_icon("Lock", "EditorIcons"));
- unlock_button->set_icon(get_icon("Unlock", "EditorIcons"));
- group_button->set_icon(get_icon("Group", "EditorIcons"));
- ungroup_button->set_icon(get_icon("Ungroup", "EditorIcons"));
- key_insert_button->set_icon(get_icon("Key", "EditorIcons"));
-
- zoom_minus->set_icon(get_icon("ZoomLess", "EditorIcons"));
- zoom_reset->set_icon(get_icon("ZoomReset", "EditorIcons"));
- zoom_plus->set_icon(get_icon("ZoomMore", "EditorIcons"));
-
- anchor_menu->set_icon(get_icon("Anchor", "EditorIcons"));
- PopupMenu *p = anchor_menu->get_popup();
-
- p->add_icon_item(get_icon("ControlAlignTopLeft", "EditorIcons"), "Top Left", ANCHOR_ALIGN_TOP_LEFT);
- p->add_icon_item(get_icon("ControlAlignTopRight", "EditorIcons"), "Top Right", ANCHOR_ALIGN_TOP_RIGHT);
- p->add_icon_item(get_icon("ControlAlignBottomRight", "EditorIcons"), "Bottom Right", ANCHOR_ALIGN_BOTTOM_RIGHT);
- p->add_icon_item(get_icon("ControlAlignBottomLeft", "EditorIcons"), "Bottom Left", ANCHOR_ALIGN_BOTTOM_LEFT);
- p->add_separator();
- p->add_icon_item(get_icon("ControlAlignLeftCenter", "EditorIcons"), "Center Left", ANCHOR_ALIGN_CENTER_LEFT);
- p->add_icon_item(get_icon("ControlAlignTopCenter", "EditorIcons"), "Center Top", ANCHOR_ALIGN_CENTER_TOP);
- p->add_icon_item(get_icon("ControlAlignRightCenter", "EditorIcons"), "Center Right", ANCHOR_ALIGN_CENTER_RIGHT);
- p->add_icon_item(get_icon("ControlAlignBottomCenter", "EditorIcons"), "Center Bottom", ANCHOR_ALIGN_CENTER_BOTTOM);
- p->add_icon_item(get_icon("ControlAlignCenter", "EditorIcons"), "Center", ANCHOR_ALIGN_CENTER);
- p->add_separator();
- p->add_icon_item(get_icon("ControlAlignLeftWide", "EditorIcons"), "Left Wide", ANCHOR_ALIGN_LEFT_WIDE);
- p->add_icon_item(get_icon("ControlAlignTopWide", "EditorIcons"), "Top Wide", ANCHOR_ALIGN_TOP_WIDE);
- p->add_icon_item(get_icon("ControlAlignRightWide", "EditorIcons"), "Right Wide", ANCHOR_ALIGN_RIGHT_WIDE);
- p->add_icon_item(get_icon("ControlAlignBottomWide", "EditorIcons"), "Bottom Wide", ANCHOR_ALIGN_BOTTOM_WIDE);
- p->add_icon_item(get_icon("ControlVcenterWide", "EditorIcons"), "VCenter Wide ", ANCHOR_ALIGN_VCENTER_WIDE);
- p->add_icon_item(get_icon("ControlHcenterWide", "EditorIcons"), "HCenter Wide ", ANCHOR_ALIGN_HCENTER_WIDE);
- p->add_separator();
- p->add_icon_item(get_icon("ControlAlignWide", "EditorIcons"), "Full Rect", ANCHOR_ALIGN_WIDE);
- p->add_icon_item(get_icon("ControlAlignWide", "EditorIcons"), "Full Rect and Fit Parent", ANCHOR_ALIGN_WIDE_FIT);
-
AnimationPlayerEditor::singleton->get_key_editor()->connect("visibility_changed", this, "_keying_changed");
_keying_changed();
+
} else if (p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) {
select_sb->set_texture(get_icon("EditorRect2D", "EditorIcons"));
+ }
+ if (p_what == NOTIFICATION_ENTER_TREE || p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) {
select_button->set_icon(get_icon("ToolSelect", "EditorIcons"));
list_select_button->set_icon(get_icon("ListSelect", "EditorIcons"));
move_button->set_icon(get_icon("ToolMove", "EditorIcons"));
@@ -2848,32 +3079,62 @@ void CanvasItemEditor::_notification(int p_what) {
unlock_button->set_icon(get_icon("Unlock", "EditorIcons"));
group_button->set_icon(get_icon("Group", "EditorIcons"));
ungroup_button->set_icon(get_icon("Ungroup", "EditorIcons"));
+ key_loc_button->set_icon(get_icon("KeyPosition", "EditorIcons"));
+ key_rot_button->set_icon(get_icon("KeyRotation", "EditorIcons"));
+ key_scale_button->set_icon(get_icon("KeyScale", "EditorIcons"));
key_insert_button->set_icon(get_icon("Key", "EditorIcons"));
- anchor_menu->set_icon(get_icon("Anchor", "EditorIcons"));
- PopupMenu *p = anchor_menu->get_popup();
- p->clear();
+ zoom_minus->set_icon(get_icon("ZoomLess", "EditorIcons"));
+ zoom_reset->set_icon(get_icon("ZoomReset", "EditorIcons"));
+ zoom_plus->set_icon(get_icon("ZoomMore", "EditorIcons"));
- p->add_icon_item(get_icon("ControlAlignTopLeft", "EditorIcons"), "Top Left", ANCHOR_ALIGN_TOP_LEFT);
- p->add_icon_item(get_icon("ControlAlignTopRight", "EditorIcons"), "Top Right", ANCHOR_ALIGN_TOP_RIGHT);
- p->add_icon_item(get_icon("ControlAlignBottomRight", "EditorIcons"), "Bottom Right", ANCHOR_ALIGN_BOTTOM_RIGHT);
- p->add_icon_item(get_icon("ControlAlignBottomLeft", "EditorIcons"), "Bottom Left", ANCHOR_ALIGN_BOTTOM_LEFT);
+ presets_menu->set_icon(get_icon("ControlLayout", "EditorIcons"));
+ PopupMenu *p = presets_menu->get_popup();
+
+ p->clear();
+ p->add_icon_item(get_icon("ControlAlignTopLeft", "EditorIcons"), "Top Left", ANCHORS_AND_MARGINS_PRESET_TOP_LEFT);
+ p->add_icon_item(get_icon("ControlAlignTopRight", "EditorIcons"), "Top Right", ANCHORS_AND_MARGINS_PRESET_TOP_RIGHT);
+ p->add_icon_item(get_icon("ControlAlignBottomRight", "EditorIcons"), "Bottom Right", ANCHORS_AND_MARGINS_PRESET_BOTTOM_RIGHT);
+ p->add_icon_item(get_icon("ControlAlignBottomLeft", "EditorIcons"), "Bottom Left", ANCHORS_AND_MARGINS_PRESET_BOTTOM_LEFT);
p->add_separator();
- p->add_icon_item(get_icon("ControlAlignLeftCenter", "EditorIcons"), "Center Left", ANCHOR_ALIGN_CENTER_LEFT);
- p->add_icon_item(get_icon("ControlAlignTopCenter", "EditorIcons"), "Center Top", ANCHOR_ALIGN_CENTER_TOP);
- p->add_icon_item(get_icon("ControlAlignRightCenter", "EditorIcons"), "Center Right", ANCHOR_ALIGN_CENTER_RIGHT);
- p->add_icon_item(get_icon("ControlAlignBottomCenter", "EditorIcons"), "Center Bottom", ANCHOR_ALIGN_CENTER_BOTTOM);
- p->add_icon_item(get_icon("ControlAlignCenter", "EditorIcons"), "Center", ANCHOR_ALIGN_CENTER);
+ p->add_icon_item(get_icon("ControlAlignLeftCenter", "EditorIcons"), "Center Left", ANCHORS_AND_MARGINS_PRESET_CENTER_LEFT);
+ p->add_icon_item(get_icon("ControlAlignTopCenter", "EditorIcons"), "Center Top", ANCHORS_AND_MARGINS_PRESET_CENTER_TOP);
+ p->add_icon_item(get_icon("ControlAlignRightCenter", "EditorIcons"), "Center Right", ANCHORS_AND_MARGINS_PRESET_CENTER_RIGHT);
+ p->add_icon_item(get_icon("ControlAlignBottomCenter", "EditorIcons"), "Center Bottom", ANCHORS_AND_MARGINS_PRESET_CENTER_BOTTOM);
+ p->add_icon_item(get_icon("ControlAlignCenter", "EditorIcons"), "Center", ANCHORS_AND_MARGINS_PRESET_CENTER);
p->add_separator();
- p->add_icon_item(get_icon("ControlAlignLeftWide", "EditorIcons"), "Left Wide", ANCHOR_ALIGN_LEFT_WIDE);
- p->add_icon_item(get_icon("ControlAlignTopWide", "EditorIcons"), "Top Wide", ANCHOR_ALIGN_TOP_WIDE);
- p->add_icon_item(get_icon("ControlAlignRightWide", "EditorIcons"), "Right Wide", ANCHOR_ALIGN_RIGHT_WIDE);
- p->add_icon_item(get_icon("ControlAlignBottomWide", "EditorIcons"), "Bottom Wide", ANCHOR_ALIGN_BOTTOM_WIDE);
- p->add_icon_item(get_icon("ControlVcenterWide", "EditorIcons"), "VCenter Wide ", ANCHOR_ALIGN_VCENTER_WIDE);
- p->add_icon_item(get_icon("ControlHcenterWide", "EditorIcons"), "HCenter Wide ", ANCHOR_ALIGN_HCENTER_WIDE);
+ p->add_icon_item(get_icon("ControlAlignLeftWide", "EditorIcons"), "Left Wide", ANCHORS_AND_MARGINS_PRESET_LEFT_WIDE);
+ p->add_icon_item(get_icon("ControlAlignTopWide", "EditorIcons"), "Top Wide", ANCHORS_AND_MARGINS_PRESET_TOP_WIDE);
+ p->add_icon_item(get_icon("ControlAlignRightWide", "EditorIcons"), "Right Wide", ANCHORS_AND_MARGINS_PRESET_RIGHT_WIDE);
+ p->add_icon_item(get_icon("ControlAlignBottomWide", "EditorIcons"), "Bottom Wide", ANCHORS_AND_MARGINS_PRESET_BOTTOM_WIDE);
+ p->add_icon_item(get_icon("ControlVcenterWide", "EditorIcons"), "VCenter Wide ", ANCHORS_AND_MARGINS_PRESET_VCENTER_WIDE);
+ p->add_icon_item(get_icon("ControlHcenterWide", "EditorIcons"), "HCenter Wide ", ANCHORS_AND_MARGINS_PRESET_HCENTER_WIDE);
p->add_separator();
- p->add_icon_item(get_icon("ControlAlignWide", "EditorIcons"), "Full Rect", ANCHOR_ALIGN_WIDE);
- p->add_icon_item(get_icon("ControlAlignWide", "EditorIcons"), "Full Rect and Fit Parent", ANCHOR_ALIGN_WIDE_FIT);
+ p->add_icon_item(get_icon("ControlAlignWide", "EditorIcons"), "Full Rect", ANCHORS_AND_MARGINS_PRESET_WIDE);
+ p->add_separator();
+ p->add_submenu_item(TTR("Anchors only"), "Anchors");
+ p->set_item_icon(20, get_icon("Anchor", "EditorIcons"));
+
+ anchors_popup->clear();
+ anchors_popup->add_icon_item(get_icon("ControlAlignTopLeft", "EditorIcons"), "Top Left", ANCHORS_PRESET_TOP_LEFT);
+ anchors_popup->add_icon_item(get_icon("ControlAlignTopRight", "EditorIcons"), "Top Right", ANCHORS_PRESET_TOP_RIGHT);
+ anchors_popup->add_icon_item(get_icon("ControlAlignBottomRight", "EditorIcons"), "Bottom Right", ANCHORS_PRESET_BOTTOM_RIGHT);
+ anchors_popup->add_icon_item(get_icon("ControlAlignBottomLeft", "EditorIcons"), "Bottom Left", ANCHORS_PRESET_BOTTOM_LEFT);
+ anchors_popup->add_separator();
+ anchors_popup->add_icon_item(get_icon("ControlAlignLeftCenter", "EditorIcons"), "Center Left", ANCHORS_PRESET_CENTER_LEFT);
+ anchors_popup->add_icon_item(get_icon("ControlAlignTopCenter", "EditorIcons"), "Center Top", ANCHORS_PRESET_CENTER_TOP);
+ anchors_popup->add_icon_item(get_icon("ControlAlignRightCenter", "EditorIcons"), "Center Right", ANCHORS_PRESET_CENTER_RIGHT);
+ anchors_popup->add_icon_item(get_icon("ControlAlignBottomCenter", "EditorIcons"), "Center Bottom", ANCHORS_PRESET_CENTER_BOTTOM);
+ anchors_popup->add_icon_item(get_icon("ControlAlignCenter", "EditorIcons"), "Center", ANCHORS_PRESET_CENTER);
+ anchors_popup->add_separator();
+ anchors_popup->add_icon_item(get_icon("ControlAlignLeftWide", "EditorIcons"), "Left Wide", ANCHORS_PRESET_LEFT_WIDE);
+ anchors_popup->add_icon_item(get_icon("ControlAlignTopWide", "EditorIcons"), "Top Wide", ANCHORS_PRESET_TOP_WIDE);
+ anchors_popup->add_icon_item(get_icon("ControlAlignRightWide", "EditorIcons"), "Right Wide", ANCHORS_PRESET_RIGHT_WIDE);
+ anchors_popup->add_icon_item(get_icon("ControlAlignBottomWide", "EditorIcons"), "Bottom Wide", ANCHORS_PRESET_BOTTOM_WIDE);
+ anchors_popup->add_icon_item(get_icon("ControlVcenterWide", "EditorIcons"), "VCenter Wide ", ANCHORS_PRESET_VCENTER_WIDE);
+ anchors_popup->add_icon_item(get_icon("ControlHcenterWide", "EditorIcons"), "HCenter Wide ", ANCHORS_PRESET_HCENTER_WIDE);
+ anchors_popup->add_separator();
+ anchors_popup->add_icon_item(get_icon("ControlAlignWide", "EditorIcons"), "Full Rect", ANCHORS_PRESET_WIDE);
}
}
@@ -3005,25 +3266,51 @@ void CanvasItemEditor::_update_scroll(float) {
viewport_base->update();
}
-void CanvasItemEditor::_set_anchors_preset(Control::LayoutPreset p_preset) {
+void CanvasItemEditor::_set_anchors_and_margins_preset(Control::LayoutPreset p_preset) {
List<Node *> &selection = editor_selection->get_selected_node_list();
- undo_redo->create_action(TTR("Change Anchors"));
+ undo_redo->create_action(TTR("Change Anchors and Margins"));
for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
Control *c = Object::cast_to<Control>(E->get());
undo_redo->add_do_method(c, "set_anchors_preset", p_preset);
+ switch (p_preset) {
+ case PRESET_TOP_LEFT:
+ case PRESET_TOP_RIGHT:
+ case PRESET_BOTTOM_LEFT:
+ case PRESET_BOTTOM_RIGHT:
+ case PRESET_CENTER_LEFT:
+ case PRESET_CENTER_TOP:
+ case PRESET_CENTER_RIGHT:
+ case PRESET_CENTER_BOTTOM:
+ case PRESET_CENTER:
+ undo_redo->add_do_method(c, "set_margins_preset", p_preset, Control::PRESET_MODE_KEEP_SIZE);
+ break;
+ case PRESET_LEFT_WIDE:
+ case PRESET_TOP_WIDE:
+ case PRESET_RIGHT_WIDE:
+ case PRESET_BOTTOM_WIDE:
+ case PRESET_VCENTER_WIDE:
+ case PRESET_HCENTER_WIDE:
+ case PRESET_WIDE:
+ undo_redo->add_do_method(c, "set_margins_preset", p_preset, Control::PRESET_MODE_MINSIZE);
+ break;
+ }
undo_redo->add_undo_method(c, "set_anchor", MARGIN_LEFT, c->get_anchor(MARGIN_LEFT));
undo_redo->add_undo_method(c, "set_anchor", MARGIN_TOP, c->get_anchor(MARGIN_TOP));
undo_redo->add_undo_method(c, "set_anchor", MARGIN_RIGHT, c->get_anchor(MARGIN_RIGHT));
undo_redo->add_undo_method(c, "set_anchor", MARGIN_BOTTOM, c->get_anchor(MARGIN_BOTTOM));
+ undo_redo->add_undo_method(c, "set_margin", MARGIN_LEFT, c->get_margin(MARGIN_LEFT));
+ undo_redo->add_undo_method(c, "set_margin", MARGIN_TOP, c->get_margin(MARGIN_TOP));
+ undo_redo->add_undo_method(c, "set_margin", MARGIN_RIGHT, c->get_margin(MARGIN_RIGHT));
+ undo_redo->add_undo_method(c, "set_margin", MARGIN_BOTTOM, c->get_margin(MARGIN_BOTTOM));
}
undo_redo->commit_action();
}
-void CanvasItemEditor::_set_full_rect() {
+void CanvasItemEditor::_set_anchors_preset(Control::LayoutPreset p_preset) {
List<Node *> &selection = editor_selection->get_selected_node_list();
undo_redo->create_action(TTR("Change Anchors"));
@@ -3031,19 +3318,11 @@ void CanvasItemEditor::_set_full_rect() {
Control *c = Object::cast_to<Control>(E->get());
- undo_redo->add_do_method(c, "set_anchors_preset", Control::PRESET_WIDE);
- undo_redo->add_do_method(c, "set_margin", MARGIN_LEFT, 0);
- undo_redo->add_do_method(c, "set_margin", MARGIN_TOP, 0);
- undo_redo->add_do_method(c, "set_margin", MARGIN_RIGHT, 0);
- undo_redo->add_do_method(c, "set_margin", MARGIN_BOTTOM, 0);
+ undo_redo->add_do_method(c, "set_anchors_preset", p_preset);
undo_redo->add_undo_method(c, "set_anchor", MARGIN_LEFT, c->get_anchor(MARGIN_LEFT));
undo_redo->add_undo_method(c, "set_anchor", MARGIN_TOP, c->get_anchor(MARGIN_TOP));
undo_redo->add_undo_method(c, "set_anchor", MARGIN_RIGHT, c->get_anchor(MARGIN_RIGHT));
undo_redo->add_undo_method(c, "set_anchor", MARGIN_BOTTOM, c->get_anchor(MARGIN_BOTTOM));
- undo_redo->add_undo_method(c, "set_margin", MARGIN_LEFT, c->get_margin(MARGIN_LEFT));
- undo_redo->add_undo_method(c, "set_margin", MARGIN_TOP, c->get_margin(MARGIN_TOP));
- undo_redo->add_undo_method(c, "set_margin", MARGIN_RIGHT, c->get_margin(MARGIN_RIGHT));
- undo_redo->add_undo_method(c, "set_margin", MARGIN_BOTTOM, c->get_margin(MARGIN_BOTTOM));
}
undo_redo->commit_action();
@@ -3115,6 +3394,11 @@ void CanvasItemEditor::_popup_callback(int p_op) {
int idx = smartsnap_config_popup->get_item_index(SNAP_USE_OTHER_NODES);
smartsnap_config_popup->set_item_checked(idx, snap_other_nodes);
} break;
+ case SNAP_USE_GUIDES: {
+ snap_guides = !snap_guides;
+ int idx = smartsnap_config_popup->get_item_index(SNAP_USE_GUIDES);
+ smartsnap_config_popup->set_item_checked(idx, snap_guides);
+ } break;
case SNAP_USE_GRID: {
snap_grid = !snap_grid;
int idx = snap_config_menu->get_popup()->get_item_index(SNAP_USE_GRID);
@@ -3160,6 +3444,13 @@ void CanvasItemEditor::_popup_callback(int p_op) {
viewport->update();
viewport_base->update();
} break;
+ case SHOW_GUIDES: {
+ show_guides = !show_guides;
+ int idx = view_menu->get_popup()->get_item_index(SHOW_GUIDES);
+ view_menu->get_popup()->set_item_checked(idx, show_guides);
+ viewport->update();
+ viewport_base->update();
+ } break;
case LOCK_SELECTED: {
@@ -3237,57 +3528,104 @@ void CanvasItemEditor::_popup_callback(int p_op) {
viewport->update();
} break;
- case ANCHOR_ALIGN_TOP_LEFT: {
+
+ case ANCHORS_AND_MARGINS_PRESET_TOP_LEFT: {
+ _set_anchors_and_margins_preset(PRESET_TOP_LEFT);
+ } break;
+ case ANCHORS_AND_MARGINS_PRESET_TOP_RIGHT: {
+ _set_anchors_and_margins_preset(PRESET_TOP_RIGHT);
+ } break;
+ case ANCHORS_AND_MARGINS_PRESET_BOTTOM_LEFT: {
+ _set_anchors_and_margins_preset(PRESET_BOTTOM_LEFT);
+ } break;
+ case ANCHORS_AND_MARGINS_PRESET_BOTTOM_RIGHT: {
+ _set_anchors_and_margins_preset(PRESET_BOTTOM_RIGHT);
+ } break;
+ case ANCHORS_AND_MARGINS_PRESET_CENTER_LEFT: {
+ _set_anchors_and_margins_preset(PRESET_CENTER_LEFT);
+ } break;
+ case ANCHORS_AND_MARGINS_PRESET_CENTER_RIGHT: {
+ _set_anchors_and_margins_preset(PRESET_CENTER_RIGHT);
+ } break;
+ case ANCHORS_AND_MARGINS_PRESET_CENTER_TOP: {
+ _set_anchors_and_margins_preset(PRESET_CENTER_TOP);
+ } break;
+ case ANCHORS_AND_MARGINS_PRESET_CENTER_BOTTOM: {
+ _set_anchors_and_margins_preset(PRESET_CENTER_BOTTOM);
+ } break;
+ case ANCHORS_AND_MARGINS_PRESET_CENTER: {
+ _set_anchors_and_margins_preset(PRESET_CENTER);
+ } break;
+ case ANCHORS_AND_MARGINS_PRESET_TOP_WIDE: {
+ _set_anchors_and_margins_preset(PRESET_TOP_WIDE);
+ } break;
+ case ANCHORS_AND_MARGINS_PRESET_LEFT_WIDE: {
+ _set_anchors_and_margins_preset(PRESET_LEFT_WIDE);
+ } break;
+ case ANCHORS_AND_MARGINS_PRESET_RIGHT_WIDE: {
+ _set_anchors_and_margins_preset(PRESET_RIGHT_WIDE);
+ } break;
+ case ANCHORS_AND_MARGINS_PRESET_BOTTOM_WIDE: {
+ _set_anchors_and_margins_preset(PRESET_BOTTOM_WIDE);
+ } break;
+ case ANCHORS_AND_MARGINS_PRESET_VCENTER_WIDE: {
+ _set_anchors_and_margins_preset(PRESET_VCENTER_WIDE);
+ } break;
+ case ANCHORS_AND_MARGINS_PRESET_HCENTER_WIDE: {
+ _set_anchors_and_margins_preset(PRESET_HCENTER_WIDE);
+ } break;
+ case ANCHORS_AND_MARGINS_PRESET_WIDE: {
+ _set_anchors_and_margins_preset(Control::PRESET_WIDE);
+ } break;
+
+ case ANCHORS_PRESET_TOP_LEFT: {
_set_anchors_preset(PRESET_TOP_LEFT);
} break;
- case ANCHOR_ALIGN_TOP_RIGHT: {
+ case ANCHORS_PRESET_TOP_RIGHT: {
_set_anchors_preset(PRESET_TOP_RIGHT);
} break;
- case ANCHOR_ALIGN_BOTTOM_LEFT: {
+ case ANCHORS_PRESET_BOTTOM_LEFT: {
_set_anchors_preset(PRESET_BOTTOM_LEFT);
} break;
- case ANCHOR_ALIGN_BOTTOM_RIGHT: {
+ case ANCHORS_PRESET_BOTTOM_RIGHT: {
_set_anchors_preset(PRESET_BOTTOM_RIGHT);
} break;
- case ANCHOR_ALIGN_CENTER_LEFT: {
+ case ANCHORS_PRESET_CENTER_LEFT: {
_set_anchors_preset(PRESET_CENTER_LEFT);
} break;
- case ANCHOR_ALIGN_CENTER_RIGHT: {
+ case ANCHORS_PRESET_CENTER_RIGHT: {
_set_anchors_preset(PRESET_CENTER_RIGHT);
} break;
- case ANCHOR_ALIGN_CENTER_TOP: {
+ case ANCHORS_PRESET_CENTER_TOP: {
_set_anchors_preset(PRESET_CENTER_TOP);
} break;
- case ANCHOR_ALIGN_CENTER_BOTTOM: {
+ case ANCHORS_PRESET_CENTER_BOTTOM: {
_set_anchors_preset(PRESET_CENTER_BOTTOM);
} break;
- case ANCHOR_ALIGN_CENTER: {
+ case ANCHORS_PRESET_CENTER: {
_set_anchors_preset(PRESET_CENTER);
} break;
- case ANCHOR_ALIGN_TOP_WIDE: {
+ case ANCHORS_PRESET_TOP_WIDE: {
_set_anchors_preset(PRESET_TOP_WIDE);
} break;
- case ANCHOR_ALIGN_LEFT_WIDE: {
+ case ANCHORS_PRESET_LEFT_WIDE: {
_set_anchors_preset(PRESET_LEFT_WIDE);
} break;
- case ANCHOR_ALIGN_RIGHT_WIDE: {
+ case ANCHORS_PRESET_RIGHT_WIDE: {
_set_anchors_preset(PRESET_RIGHT_WIDE);
} break;
- case ANCHOR_ALIGN_BOTTOM_WIDE: {
+ case ANCHORS_PRESET_BOTTOM_WIDE: {
_set_anchors_preset(PRESET_BOTTOM_WIDE);
} break;
- case ANCHOR_ALIGN_VCENTER_WIDE: {
+ case ANCHORS_PRESET_VCENTER_WIDE: {
_set_anchors_preset(PRESET_VCENTER_WIDE);
} break;
- case ANCHOR_ALIGN_HCENTER_WIDE: {
+ case ANCHORS_PRESET_HCENTER_WIDE: {
_set_anchors_preset(PRESET_HCENTER_WIDE);
} break;
- case ANCHOR_ALIGN_WIDE: {
+ case ANCHORS_PRESET_WIDE: {
_set_anchors_preset(Control::PRESET_WIDE);
} break;
- case ANCHOR_ALIGN_WIDE_FIT: {
- _set_full_rect();
- } break;
case ANIM_INSERT_KEY:
case ANIM_INSERT_KEY_EXISTING: {
@@ -3311,7 +3649,7 @@ void CanvasItemEditor::_popup_callback(int p_op) {
if (key_pos)
AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(n2d, "position", n2d->get_position(), existing);
if (key_rot)
- AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(n2d, "rotation_deg", Math::rad2deg(n2d->get_rotation()), existing);
+ AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(n2d, "rotation_degrees", Math::rad2deg(n2d->get_rotation()), existing);
if (key_scale)
AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(n2d, "scale", n2d->get_scale(), existing);
@@ -3342,7 +3680,7 @@ void CanvasItemEditor::_popup_callback(int p_op) {
if (key_pos)
AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(F->get(), "position", F->get()->get_position(), existing);
if (key_rot)
- AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(F->get(), "rotation_deg", Math::rad2deg(F->get()->get_rotation()), existing);
+ AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(F->get(), "rotation_degrees", Math::rad2deg(F->get()->get_rotation()), existing);
if (key_scale)
AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(F->get(), "scale", F->get()->get_scale(), existing);
}
@@ -3356,7 +3694,7 @@ void CanvasItemEditor::_popup_callback(int p_op) {
if (key_pos)
AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(ctrl, "rect_position", ctrl->get_position(), existing);
if (key_rot)
- AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(ctrl, "rect_rotation", ctrl->get_rotation_deg(), existing);
+ AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(ctrl, "rect_rotation", ctrl->get_rotation_degrees(), existing);
if (key_scale)
AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(ctrl, "rect_size", ctrl->get_size(), existing);
}
@@ -3380,7 +3718,6 @@ void CanvasItemEditor::_popup_callback(int p_op) {
case ANIM_INSERT_POS_SCALE:
case ANIM_INSERT_ROT_SCALE:
case ANIM_INSERT_POS_ROT_SCALE: {
-
static const bool key_toggles[7][3]={
{true,false,false},
{false,true,false},
@@ -3393,12 +3730,10 @@ void CanvasItemEditor::_popup_callback(int p_op) {
key_pos=key_toggles[p_op-ANIM_INSERT_POS][0];
key_rot=key_toggles[p_op-ANIM_INSERT_POS][1];
key_scale=key_toggles[p_op-ANIM_INSERT_POS][2];
-
for(int i=ANIM_INSERT_POS;i<=ANIM_INSERT_POS_ROT_SCALE;i++) {
int idx = animation_menu->get_popup()->get_item_index(i);
animation_menu->get_popup()->set_item_checked(idx,i==p_op);
}
-
} break;*/
case ANIM_COPY_POSE: {
@@ -3590,7 +3925,7 @@ void CanvasItemEditor::_focus_selection(int p_op) {
//if (!canvas_item->is_visible_in_tree()) continue;
++count;
- Rect2 item_rect = canvas_item->get_item_rect();
+ Rect2 item_rect = canvas_item->_edit_get_rect();
Vector2 pos = canvas_item->get_global_transform().get_origin();
Vector2 scale = canvas_item->get_global_transform().get_scale();
@@ -3641,7 +3976,8 @@ void CanvasItemEditor::_bind_methods() {
ClassDB::bind_method("_unhandled_key_input", &CanvasItemEditor::_unhandled_key_input);
ClassDB::bind_method("_draw_viewport", &CanvasItemEditor::_draw_viewport);
ClassDB::bind_method("_draw_viewport_base", &CanvasItemEditor::_draw_viewport_base);
- ClassDB::bind_method("_viewport_base_gui_input", &CanvasItemEditor::_viewport_base_gui_input);
+ ClassDB::bind_method("_gui_input_viewport", &CanvasItemEditor::_gui_input_viewport);
+ ClassDB::bind_method("_gui_input_viewport_base", &CanvasItemEditor::_gui_input_viewport_base);
ClassDB::bind_method("_snap_changed", &CanvasItemEditor::_snap_changed);
ClassDB::bind_method(D_METHOD("_selection_result_pressed"), &CanvasItemEditor::_selection_result_pressed);
ClassDB::bind_method(D_METHOD("_selection_menu_hide"), &CanvasItemEditor::_selection_menu_hide);
@@ -3694,7 +4030,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
palette_split->add_child(viewport_base);
viewport_base->set_clip_contents(true);
viewport_base->connect("draw", this, "_draw_viewport_base");
- viewport_base->connect("gui_input", this, "_viewport_base_gui_input");
+ viewport_base->connect("gui_input", this, "_gui_input_viewport_base");
viewport_base->set_focus_mode(FOCUS_ALL);
viewport_base->set_v_size_flags(SIZE_EXPAND_FILL);
viewport_base->set_h_size_flags(SIZE_EXPAND_FILL);
@@ -3718,6 +4054,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
viewport->set_anchors_and_margins_preset(Control::PRESET_WIDE);
viewport->set_clip_contents(true);
viewport->connect("draw", this, "_draw_viewport");
+ viewport->connect("gui_input", this, "_gui_input_viewport");
h_scroll = memnew(HScrollBar);
viewport->add_child(h_scroll);
@@ -3827,6 +4164,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
smartsnap_config_popup->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_node_anchors", TTR("Snap to node anchor")), SNAP_USE_NODE_ANCHORS);
smartsnap_config_popup->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_node_sides", TTR("Snap to node sides")), SNAP_USE_NODE_SIDES);
smartsnap_config_popup->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_other_nodes", TTR("Snap to other nodes")), SNAP_USE_OTHER_NODES);
+ smartsnap_config_popup->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_guides", TTR("Snap to guides")), SNAP_USE_GUIDES);
hb->add_child(memnew(VSeparator));
@@ -3865,7 +4203,6 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
p->add_separator();
p->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_set_ik_chain", TTR("Make IK Chain")), SKELETON_SET_IK_CHAIN);
p->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_clear_ik_chain", TTR("Clear IK Chain")), SKELETON_CLEAR_IK_CHAIN);
- p->set_hide_on_checkable_item_selection(false);
p->connect("id_pressed", this, "_popup_callback");
hb->add_child(memnew(VSeparator));
@@ -3879,47 +4216,47 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_grid", TTR("Show Grid"), KEY_G), SHOW_GRID);
p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_helpers", TTR("Show helpers"), KEY_H), SHOW_HELPERS);
p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_rulers", TTR("Show rulers"), KEY_R), SHOW_RULERS);
+ p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_guides", TTR("Show guides"), KEY_Y), SHOW_GUIDES);
p->add_separator();
p->add_shortcut(ED_SHORTCUT("canvas_item_editor/center_selection", TTR("Center Selection"), KEY_F), VIEW_CENTER_TO_SELECTION);
p->add_shortcut(ED_SHORTCUT("canvas_item_editor/frame_selection", TTR("Frame Selection"), KEY_MASK_SHIFT | KEY_F), VIEW_FRAME_TO_SELECTION);
- anchor_menu = memnew(MenuButton);
- anchor_menu->set_text(TTR("Anchor"));
- hb->add_child(anchor_menu);
- anchor_menu->get_popup()->connect("id_pressed", this, "_popup_callback");
- anchor_menu->hide();
+ presets_menu = memnew(MenuButton);
+ presets_menu->set_text(TTR("Layout"));
+ hb->add_child(presets_menu);
+ presets_menu->hide();
- //p = anchor_menu->get_popup();
+ p = presets_menu->get_popup();
+ p->connect("id_pressed", this, "_popup_callback");
+
+ anchors_popup = memnew(PopupMenu);
+ p->add_child(anchors_popup);
+ anchors_popup->set_name("Anchors");
+ anchors_popup->connect("id_pressed", this, "_popup_callback");
animation_hb = memnew(HBoxContainer);
hb->add_child(animation_hb);
animation_hb->add_child(memnew(VSeparator));
animation_hb->hide();
- key_loc_button = memnew(Button("loc"));
+ key_loc_button = memnew(Button);
key_loc_button->set_toggle_mode(true);
key_loc_button->set_flat(true);
key_loc_button->set_pressed(true);
key_loc_button->set_focus_mode(FOCUS_NONE);
- key_loc_button->add_color_override("font_color", Color(1, 0.6, 0.6));
- key_loc_button->add_color_override("font_color_pressed", Color(0.6, 1, 0.6));
key_loc_button->connect("pressed", this, "_popup_callback", varray(ANIM_INSERT_POS));
animation_hb->add_child(key_loc_button);
- key_rot_button = memnew(Button("rot"));
+ key_rot_button = memnew(Button);
key_rot_button->set_toggle_mode(true);
key_rot_button->set_flat(true);
key_rot_button->set_pressed(true);
key_rot_button->set_focus_mode(FOCUS_NONE);
- key_rot_button->add_color_override("font_color", Color(1, 0.6, 0.6));
- key_rot_button->add_color_override("font_color_pressed", Color(0.6, 1, 0.6));
key_rot_button->connect("pressed", this, "_popup_callback", varray(ANIM_INSERT_ROT));
animation_hb->add_child(key_rot_button);
- key_scale_button = memnew(Button("scl"));
+ key_scale_button = memnew(Button);
key_scale_button->set_toggle_mode(true);
key_scale_button->set_flat(true);
key_scale_button->set_focus_mode(FOCUS_NONE);
- key_scale_button->add_color_override("font_color", Color(1, 0.6, 0.6));
- key_scale_button->add_color_override("font_color_pressed", Color(0.6, 1, 0.6));
key_scale_button->connect("pressed", this, "_popup_callback", varray(ANIM_INSERT_SCALE));
animation_hb->add_child(key_scale_button);
key_insert_button = memnew(Button);
@@ -3967,9 +4304,13 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
key_rot = true;
key_scale = false;
+ edited_guide_pos = Point2();
+ edited_guide_index = -1;
+
show_grid = false;
show_helpers = false;
show_rulers = false;
+ show_guides = true;
zoom = 1;
grid_offset = Point2();
grid_step = Point2(10, 10);
@@ -3982,6 +4323,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
snap_node_sides = true;
snap_other_nodes = true;
snap_grid = true;
+ snap_guides = true;
snap_rotation = false;
snap_pixel = false;
skeleton_show_bones = true;
@@ -4057,11 +4399,11 @@ void CanvasItemEditorViewport::_on_mouse_exit() {
void CanvasItemEditorViewport::_on_select_type(Object *selected) {
CheckBox *check = Object::cast_to<CheckBox>(selected);
String type = check->get_text();
- selector_label->set_text(vformat(TTR("Add %s"), type));
+ selector->set_title(vformat(TTR("Add %s"), type));
label->set_text(vformat(TTR("Adding %s..."), type));
}
-void CanvasItemEditorViewport::_on_change_type() {
+void CanvasItemEditorViewport::_on_change_type_confirmed() {
if (!button_group->get_pressed_button())
return;
@@ -4071,6 +4413,11 @@ void CanvasItemEditorViewport::_on_change_type() {
selector->hide();
}
+void CanvasItemEditorViewport::_on_change_type_closed() {
+
+ _remove_preview();
+}
+
void CanvasItemEditorViewport::_create_preview(const Vector<String> &files) const {
label->set_position(get_global_position() + Point2(14, 14) * EDSCALE);
label_desc->set_position(label->get_position() + Point2(0, label->get_size().height));
@@ -4382,7 +4729,7 @@ void CanvasItemEditorViewport::drop_data(const Point2 &p_point, const Variant &p
CheckBox *check = Object::cast_to<CheckBox>(btn_list[i]);
check->set_pressed(check->get_text() == default_type);
}
- selector_label->set_text(vformat(TTR("Add %s"), default_type));
+ selector->set_title(vformat(TTR("Add %s"), default_type));
selector->popup_centered_minsize();
} else {
_perform_drop_data();
@@ -4405,7 +4752,8 @@ void CanvasItemEditorViewport::_notification(int p_what) {
void CanvasItemEditorViewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("_on_select_type"), &CanvasItemEditorViewport::_on_select_type);
- ClassDB::bind_method(D_METHOD("_on_change_type"), &CanvasItemEditorViewport::_on_change_type);
+ ClassDB::bind_method(D_METHOD("_on_change_type_confirmed"), &CanvasItemEditorViewport::_on_change_type_confirmed);
+ ClassDB::bind_method(D_METHOD("_on_change_type_closed"), &CanvasItemEditorViewport::_on_change_type_closed);
ClassDB::bind_method(D_METHOD("_on_mouse_exit"), &CanvasItemEditorViewport::_on_mouse_exit);
}
@@ -4433,7 +4781,8 @@ CanvasItemEditorViewport::CanvasItemEditorViewport(EditorNode *p_node, CanvasIte
selector = memnew(AcceptDialog);
editor->get_gui_base()->add_child(selector);
selector->set_title(TTR("Change default type"));
- selector->connect("confirmed", this, "_on_change_type");
+ selector->connect("confirmed", this, "_on_change_type_confirmed");
+ selector->connect("popup_hide", this, "_on_change_type_closed");
VBoxContainer *vbc = memnew(VBoxContainer);
selector->add_child(vbc);
@@ -4441,12 +4790,6 @@ CanvasItemEditorViewport::CanvasItemEditorViewport(EditorNode *p_node, CanvasIte
vbc->set_v_size_flags(SIZE_EXPAND_FILL);
vbc->set_custom_minimum_size(Size2(200, 260) * EDSCALE);
- selector_label = memnew(Label);
- vbc->add_child(selector_label);
- selector_label->set_align(Label::ALIGN_CENTER);
- selector_label->set_valign(Label::VALIGN_BOTTOM);
- selector_label->set_custom_minimum_size(Size2(0, 30) * EDSCALE);
-
btn_group = memnew(VBoxContainer);
vbc->add_child(btn_group);
btn_group->set_h_size_flags(0);
diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h
index f87bfef8ad..457833e1a7 100644
--- a/editor/plugins/canvas_item_editor_plugin.h
+++ b/editor/plugins/canvas_item_editor_plugin.h
@@ -87,6 +87,7 @@ class CanvasItemEditor : public VBoxContainer {
SNAP_USE_NODE_SIDES,
SNAP_USE_OTHER_NODES,
SNAP_USE_GRID,
+ SNAP_USE_GUIDES,
SNAP_USE_ROTATION,
SNAP_RELATIVE,
SNAP_CONFIGURE,
@@ -94,27 +95,59 @@ class CanvasItemEditor : public VBoxContainer {
SHOW_GRID,
SHOW_HELPERS,
SHOW_RULERS,
+ SHOW_GUIDES,
LOCK_SELECTED,
UNLOCK_SELECTED,
GROUP_SELECTED,
UNGROUP_SELECTED,
- ANCHOR_ALIGN_TOP_LEFT,
- ANCHOR_ALIGN_TOP_RIGHT,
- ANCHOR_ALIGN_BOTTOM_LEFT,
- ANCHOR_ALIGN_BOTTOM_RIGHT,
- ANCHOR_ALIGN_CENTER_LEFT,
- ANCHOR_ALIGN_CENTER_RIGHT,
- ANCHOR_ALIGN_CENTER_TOP,
- ANCHOR_ALIGN_CENTER_BOTTOM,
- ANCHOR_ALIGN_CENTER,
- ANCHOR_ALIGN_TOP_WIDE,
- ANCHOR_ALIGN_LEFT_WIDE,
- ANCHOR_ALIGN_RIGHT_WIDE,
- ANCHOR_ALIGN_BOTTOM_WIDE,
- ANCHOR_ALIGN_VCENTER_WIDE,
- ANCHOR_ALIGN_HCENTER_WIDE,
- ANCHOR_ALIGN_WIDE,
- ANCHOR_ALIGN_WIDE_FIT,
+ ANCHORS_AND_MARGINS_PRESET_TOP_LEFT,
+ ANCHORS_AND_MARGINS_PRESET_TOP_RIGHT,
+ ANCHORS_AND_MARGINS_PRESET_BOTTOM_LEFT,
+ ANCHORS_AND_MARGINS_PRESET_BOTTOM_RIGHT,
+ ANCHORS_AND_MARGINS_PRESET_CENTER_LEFT,
+ ANCHORS_AND_MARGINS_PRESET_CENTER_RIGHT,
+ ANCHORS_AND_MARGINS_PRESET_CENTER_TOP,
+ ANCHORS_AND_MARGINS_PRESET_CENTER_BOTTOM,
+ ANCHORS_AND_MARGINS_PRESET_CENTER,
+ ANCHORS_AND_MARGINS_PRESET_TOP_WIDE,
+ ANCHORS_AND_MARGINS_PRESET_LEFT_WIDE,
+ ANCHORS_AND_MARGINS_PRESET_RIGHT_WIDE,
+ ANCHORS_AND_MARGINS_PRESET_BOTTOM_WIDE,
+ ANCHORS_AND_MARGINS_PRESET_VCENTER_WIDE,
+ ANCHORS_AND_MARGINS_PRESET_HCENTER_WIDE,
+ ANCHORS_AND_MARGINS_PRESET_WIDE,
+ ANCHORS_PRESET_TOP_LEFT,
+ ANCHORS_PRESET_TOP_RIGHT,
+ ANCHORS_PRESET_BOTTOM_LEFT,
+ ANCHORS_PRESET_BOTTOM_RIGHT,
+ ANCHORS_PRESET_CENTER_LEFT,
+ ANCHORS_PRESET_CENTER_RIGHT,
+ ANCHORS_PRESET_CENTER_TOP,
+ ANCHORS_PRESET_CENTER_BOTTOM,
+ ANCHORS_PRESET_CENTER,
+ ANCHORS_PRESET_TOP_WIDE,
+ ANCHORS_PRESET_LEFT_WIDE,
+ ANCHORS_PRESET_RIGHT_WIDE,
+ ANCHORS_PRESET_BOTTOM_WIDE,
+ ANCHORS_PRESET_VCENTER_WIDE,
+ ANCHORS_PRESET_HCENTER_WIDE,
+ ANCHORS_PRESET_WIDE,
+ MARGINS_PRESET_TOP_LEFT,
+ MARGINS_PRESET_TOP_RIGHT,
+ MARGINS_PRESET_BOTTOM_LEFT,
+ MARGINS_PRESET_BOTTOM_RIGHT,
+ MARGINS_PRESET_CENTER_LEFT,
+ MARGINS_PRESET_CENTER_RIGHT,
+ MARGINS_PRESET_CENTER_TOP,
+ MARGINS_PRESET_CENTER_BOTTOM,
+ MARGINS_PRESET_CENTER,
+ MARGINS_PRESET_TOP_WIDE,
+ MARGINS_PRESET_LEFT_WIDE,
+ MARGINS_PRESET_RIGHT_WIDE,
+ MARGINS_PRESET_BOTTOM_WIDE,
+ MARGINS_PRESET_VCENTER_WIDE,
+ MARGINS_PRESET_HCENTER_WIDE,
+ MARGINS_PRESET_WIDE,
ANIM_INSERT_KEY,
ANIM_INSERT_KEY_EXISTING,
ANIM_INSERT_POS,
@@ -152,6 +185,9 @@ class CanvasItemEditor : public VBoxContainer {
DRAG_ROTATE,
DRAG_PIVOT,
DRAG_NODE_2D,
+ DRAG_V_GUIDE,
+ DRAG_H_GUIDE,
+ DRAG_DOUBLE_GUIDE,
};
enum KeyMoveMODE {
@@ -182,6 +218,7 @@ class CanvasItemEditor : public VBoxContainer {
Transform2D transform;
bool show_grid;
bool show_rulers;
+ bool show_guides;
bool show_helpers;
float zoom;
@@ -197,6 +234,7 @@ class CanvasItemEditor : public VBoxContainer {
bool snap_node_sides;
bool snap_other_nodes;
bool snap_grid;
+ bool snap_guides;
bool snap_rotation;
bool snap_relative;
bool snap_pixel;
@@ -279,7 +317,10 @@ class CanvasItemEditor : public VBoxContainer {
MenuButton *view_menu;
HBoxContainer *animation_hb;
MenuButton *animation_menu;
- MenuButton *anchor_menu;
+
+ MenuButton *presets_menu;
+ PopupMenu *anchors_and_margins_popup;
+ PopupMenu *anchors_popup;
Button *key_loc_button;
Button *key_rot_button;
@@ -299,6 +340,9 @@ class CanvasItemEditor : public VBoxContainer {
Point2 display_rotate_from;
Point2 display_rotate_to;
+ int edited_guide_index;
+ Point2 edited_guide_pos;
+
Ref<StyleBoxTexture> select_sb;
Ref<Texture> select_handle;
Ref<Texture> anchor_handle;
@@ -368,6 +412,7 @@ class CanvasItemEditor : public VBoxContainer {
void _draw_percentage_at_position(float p_value, Point2 p_position, Margin p_side);
void _draw_rulers();
+ void _draw_guides();
void _draw_focus();
void _draw_grid();
void _draw_selection();
@@ -376,17 +421,20 @@ class CanvasItemEditor : public VBoxContainer {
void _draw_locks_and_groups(Node *p_node, const Transform2D &p_xform);
void _draw_viewport();
-
- void _viewport_base_gui_input(const Ref<InputEvent> &p_event);
void _draw_viewport_base();
+ void _gui_input_viewport(const Ref<InputEvent> &p_event);
+ void _gui_input_viewport_base(const Ref<InputEvent> &p_event);
+
void _focus_selection(int p_op);
- void _snap_if_closer(Point2 p_value, Point2 p_target_snap, Point2 &r_current_snap, bool (&r_snapped)[2], real_t rotation = 0.0, float p_radius = 10.0);
- void _snap_other_nodes(Point2 p_value, Point2 &r_current_snap, bool (&r_snapped)[2], const Node *p_current, const CanvasItem *p_to_snap);
+ void _snap_if_closer_float(float p_value, float p_target_snap, float &r_current_snap, bool &r_snapped, float p_radius = 10.0);
+ void _snap_if_closer_point(Point2 p_value, Point2 p_target_snap, Point2 &r_current_snap, bool (&r_snapped)[2], real_t rotation = 0.0, float p_radius = 10.0);
+ void _snap_other_nodes(Point2 p_value, Point2 &r_current_snap, bool (&r_snapped)[2], const Node *p_current, const CanvasItem *p_to_snap = NULL);
void _set_anchors_preset(Control::LayoutPreset p_preset);
- void _set_full_rect();
+ void _set_margins_preset(Control::LayoutPreset p_preset);
+ void _set_anchors_and_margins_preset(Control::LayoutPreset p_preset);
void _zoom_on_position(float p_zoom, Point2 p_position = Point2());
void _zoom_minus();
@@ -440,13 +488,14 @@ protected:
public:
enum SnapMode {
SNAP_GRID = 1 << 0,
- SNAP_PIXEL = 1 << 1,
- SNAP_NODE_PARENT = 1 << 2,
- SNAP_NODE_ANCHORS = 1 << 3,
- SNAP_NODE_SIDES = 1 << 4,
- SNAP_OTHER_NODES = 1 << 5,
-
- SNAP_DEFAULT = 0x03,
+ SNAP_GUIDES = 1 << 1,
+ SNAP_PIXEL = 1 << 2,
+ SNAP_NODE_PARENT = 1 << 3,
+ SNAP_NODE_ANCHORS = 1 << 4,
+ SNAP_NODE_SIDES = 1 << 5,
+ SNAP_OTHER_NODES = 1 << 6,
+
+ SNAP_DEFAULT = 0x07,
};
Point2 snap_point(Point2 p_target, unsigned int p_modes = SNAP_DEFAULT, const CanvasItem *p_canvas_item = NULL, unsigned int p_forced_modes = 0);
@@ -519,7 +568,8 @@ class CanvasItemEditorViewport : public Control {
void _on_mouse_exit();
void _on_select_type(Object *selected);
- void _on_change_type();
+ void _on_change_type_confirmed();
+ void _on_change_type_closed();
void _create_preview(const Vector<String> &files) const;
void _remove_preview();
diff --git a/editor/plugins/collision_polygon_2d_editor_plugin.cpp b/editor/plugins/collision_polygon_2d_editor_plugin.cpp
index 4501136e19..00e6d617a1 100644
--- a/editor/plugins/collision_polygon_2d_editor_plugin.cpp
+++ b/editor/plugins/collision_polygon_2d_editor_plugin.cpp
@@ -29,400 +29,20 @@
/*************************************************************************/
#include "collision_polygon_2d_editor_plugin.h"
-#include "canvas_item_editor_plugin.h"
-#include "editor/editor_settings.h"
-#include "os/file_access.h"
+Node2D *CollisionPolygon2DEditor::_get_node() const {
-void CollisionPolygon2DEditor::_notification(int p_what) {
-
- switch (p_what) {
-
- case NOTIFICATION_READY: {
-
- button_create->set_icon(get_icon("Edit", "EditorIcons"));
- button_edit->set_icon(get_icon("MovePoint", "EditorIcons"));
- button_edit->set_pressed(true);
- get_tree()->connect("node_removed", this, "_node_removed");
-
- } break;
- case NOTIFICATION_PHYSICS_PROCESS: {
-
- } break;
- }
-}
-void CollisionPolygon2DEditor::_node_removed(Node *p_node) {
-
- if (p_node == node) {
- node = NULL;
- hide();
- canvas_item_editor->get_viewport_control()->update();
- }
-}
-
-void CollisionPolygon2DEditor::_menu_option(int p_option) {
-
- switch (p_option) {
-
- case MODE_CREATE: {
-
- mode = MODE_CREATE;
- button_create->set_pressed(true);
- button_edit->set_pressed(false);
- } break;
- case MODE_EDIT: {
-
- mode = MODE_EDIT;
- button_create->set_pressed(false);
- button_edit->set_pressed(true);
- } break;
- }
-}
-
-void CollisionPolygon2DEditor::_wip_close() {
-
- undo_redo->create_action(TTR("Create Poly"));
- undo_redo->add_undo_method(node, "set_polygon", node->get_polygon());
- undo_redo->add_do_method(node, "set_polygon", wip);
- undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
- undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
- undo_redo->commit_action();
- wip.clear();
- wip_active = false;
- mode = MODE_EDIT;
- button_edit->set_pressed(true);
- button_create->set_pressed(false);
- edited_point = -1;
-}
-
-bool CollisionPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
-
- if (!node)
- return false;
-
- Ref<InputEventMouseButton> mb = p_event;
-
- if (mb.is_valid()) {
- Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
-
- Vector2 gpoint = mb->get_position();
- Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
- cpoint = canvas_item_editor->snap_point(cpoint);
- cpoint = node->get_global_transform().affine_inverse().xform(cpoint);
-
- Vector<Vector2> poly = node->get_polygon();
-
- //first check if a point is to be added (segment split)
- real_t grab_threshold = EDITOR_DEF("editors/poly_editor/point_grab_radius", 8);
-
- switch (mode) {
-
- case MODE_CREATE: {
-
- if (mb->get_button_index() == BUTTON_LEFT && mb->is_pressed()) {
-
- if (!wip_active) {
-
- wip.clear();
- wip.push_back(cpoint);
- wip_active = true;
- edited_point_pos = cpoint;
- canvas_item_editor->get_viewport_control()->update();
- edited_point = 1;
- return true;
- } else {
-
- if (wip.size() > 1 && xform.xform(wip[0]).distance_to(gpoint) < grab_threshold) {
- //wip closed
- _wip_close();
-
- return true;
- } else {
-
- wip.push_back(cpoint);
- edited_point = wip.size();
- canvas_item_editor->get_viewport_control()->update();
- return true;
-
- //add wip point
- }
- }
- } else if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed() && wip_active) {
- _wip_close();
- }
-
- } break;
-
- case MODE_EDIT: {
-
- if (mb->get_button_index() == BUTTON_LEFT) {
- if (mb->is_pressed()) {
-
- if (mb->get_control()) {
-
- if (poly.size() < 3) {
-
- undo_redo->create_action(TTR("Edit Poly"));
- undo_redo->add_undo_method(node, "set_polygon", poly);
- poly.push_back(cpoint);
- undo_redo->add_do_method(node, "set_polygon", poly);
- undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
- undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
- undo_redo->commit_action();
- return true;
- }
-
- //search edges
- int closest_idx = -1;
- Vector2 closest_pos;
- real_t closest_dist = 1e10;
- for (int i = 0; i < poly.size(); i++) {
-
- Vector2 points[2] = { xform.xform(poly[i]),
- xform.xform(poly[(i + 1) % poly.size()]) };
-
- Vector2 cp = Geometry::get_closest_point_to_segment_2d(gpoint, points);
- if (cp.distance_squared_to(points[0]) < CMP_EPSILON2 || cp.distance_squared_to(points[1]) < CMP_EPSILON2)
- continue; //not valid to reuse point
-
- real_t d = cp.distance_to(gpoint);
- if (d < closest_dist && d < grab_threshold) {
- closest_dist = d;
- closest_pos = cp;
- closest_idx = i;
- }
- }
-
- if (closest_idx >= 0) {
-
- pre_move_edit = poly;
- poly.insert(closest_idx + 1, xform.affine_inverse().xform(closest_pos));
- edited_point = closest_idx + 1;
- edited_point_pos = xform.affine_inverse().xform(closest_pos);
- node->set_polygon(poly);
- canvas_item_editor->get_viewport_control()->update();
- return true;
- }
- } else {
-
- //look for points to move
-
- int closest_idx = -1;
- Vector2 closest_pos;
- real_t closest_dist = 1e10;
- for (int i = 0; i < poly.size(); i++) {
-
- Vector2 cp = xform.xform(poly[i]);
-
- real_t d = cp.distance_to(gpoint);
- if (d < closest_dist && d < grab_threshold) {
- closest_dist = d;
- closest_pos = cp;
- closest_idx = i;
- }
- }
-
- if (closest_idx >= 0) {
-
- pre_move_edit = poly;
- edited_point = closest_idx;
- edited_point_pos = xform.affine_inverse().xform(closest_pos);
- canvas_item_editor->get_viewport_control()->update();
- return true;
- }
- }
- } else {
-
- if (edited_point != -1) {
-
- //apply
-
- ERR_FAIL_INDEX_V(edited_point, poly.size(), false);
- poly[edited_point] = edited_point_pos;
- undo_redo->create_action(TTR("Edit Poly"));
- undo_redo->add_do_method(node, "set_polygon", poly);
- undo_redo->add_undo_method(node, "set_polygon", pre_move_edit);
- undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
- undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
- undo_redo->commit_action();
-
- edited_point = -1;
- return true;
- }
- }
- } else if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed() && edited_point == -1) {
-
- int closest_idx = -1;
- Vector2 closest_pos;
- real_t closest_dist = 1e10;
- for (int i = 0; i < poly.size(); i++) {
-
- Vector2 cp = xform.xform(poly[i]);
-
- real_t d = cp.distance_to(gpoint);
- if (d < closest_dist && d < grab_threshold) {
- closest_dist = d;
- closest_pos = cp;
- closest_idx = i;
- }
- }
-
- if (closest_idx >= 0) {
-
- undo_redo->create_action(TTR("Edit Poly (Remove Point)"));
- undo_redo->add_undo_method(node, "set_polygon", poly);
- poly.remove(closest_idx);
- undo_redo->add_do_method(node, "set_polygon", poly);
- undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
- undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
- undo_redo->commit_action();
- return true;
- }
- }
-
- } break;
- }
- }
-
- Ref<InputEventMouseMotion> mm = p_event;
-
- if (mm.is_valid()) {
-
- if (edited_point != -1 && (wip_active || mm->get_button_mask() & BUTTON_MASK_LEFT)) {
-
- Vector2 gpoint = mm->get_position();
- Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
- cpoint = canvas_item_editor->snap_point(cpoint);
- edited_point_pos = node->get_global_transform().affine_inverse().xform(cpoint);
-
- canvas_item_editor->get_viewport_control()->update();
- }
- }
-
- return false;
+ return node;
}
-void CollisionPolygon2DEditor::_canvas_draw() {
-
- if (!node)
- return;
-
- Control *vpc = canvas_item_editor->get_viewport_control();
-
- Vector<Vector2> poly;
-
- if (wip_active)
- poly = wip;
- else
- poly = node->get_polygon();
- Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
- Ref<Texture> handle = get_icon("EditorHandle", "EditorIcons");
+void CollisionPolygon2DEditor::_set_node(Node *p_polygon) {
- for (int i = 0; i < poly.size(); i++) {
-
- Vector2 p, p2;
- p = i == edited_point ? edited_point_pos : poly[i];
- if ((wip_active && i == poly.size() - 1) || (((i + 1) % poly.size()) == edited_point))
- p2 = edited_point_pos;
- else
- p2 = poly[(i + 1) % poly.size()];
-
- Vector2 point = xform.xform(p);
- Vector2 next_point = xform.xform(p2);
-
- Color col = Color(1, 0.3, 0.1, 0.8);
- vpc->draw_line(point, next_point, col, 2);
- vpc->draw_texture(handle, point - handle->get_size() * 0.5);
- }
+ node = Object::cast_to<CollisionPolygon2D>(p_polygon);
}
-void CollisionPolygon2DEditor::edit(Node *p_collision_polygon) {
-
- if (!canvas_item_editor) {
- canvas_item_editor = CanvasItemEditor::get_singleton();
- }
-
- if (p_collision_polygon) {
-
- node = Object::cast_to<CollisionPolygon2D>(p_collision_polygon);
- //Enable the pencil tool if the polygon is empty
- if (node->get_polygon().size() == 0) {
- _menu_option(MODE_CREATE);
- }
- if (!canvas_item_editor->get_viewport_control()->is_connected("draw", this, "_canvas_draw"))
- canvas_item_editor->get_viewport_control()->connect("draw", this, "_canvas_draw");
- wip.clear();
- wip_active = false;
- edited_point = -1;
- canvas_item_editor->get_viewport_control()->update();
-
- } else {
- node = NULL;
-
- if (canvas_item_editor->get_viewport_control()->is_connected("draw", this, "_canvas_draw"))
- canvas_item_editor->get_viewport_control()->disconnect("draw", this, "_canvas_draw");
- }
-}
-
-void CollisionPolygon2DEditor::_bind_methods() {
-
- ClassDB::bind_method(D_METHOD("_menu_option"), &CollisionPolygon2DEditor::_menu_option);
- ClassDB::bind_method(D_METHOD("_canvas_draw"), &CollisionPolygon2DEditor::_canvas_draw);
- ClassDB::bind_method(D_METHOD("_node_removed"), &CollisionPolygon2DEditor::_node_removed);
-}
-
-CollisionPolygon2DEditor::CollisionPolygon2DEditor(EditorNode *p_editor) {
-
- node = NULL;
- canvas_item_editor = NULL;
- editor = p_editor;
- undo_redo = editor->get_undo_redo();
-
- add_child(memnew(VSeparator));
- button_create = memnew(ToolButton);
- add_child(button_create);
- button_create->connect("pressed", this, "_menu_option", varray(MODE_CREATE));
- button_create->set_toggle_mode(true);
- button_create->set_tooltip(TTR("Create a new polygon from scratch."));
-
- button_edit = memnew(ToolButton);
- add_child(button_edit);
- button_edit->connect("pressed", this, "_menu_option", varray(MODE_EDIT));
- button_edit->set_toggle_mode(true);
- button_edit->set_tooltip(TTR("Edit existing polygon:\nLMB: Move Point.\nCtrl+LMB: Split Segment.\nRMB: Erase Point."));
-
- mode = MODE_EDIT;
- wip_active = false;
-}
-
-void CollisionPolygon2DEditorPlugin::edit(Object *p_object) {
-
- collision_polygon_editor->edit(Object::cast_to<Node>(p_object));
-}
-
-bool CollisionPolygon2DEditorPlugin::handles(Object *p_object) const {
-
- return p_object->is_class("CollisionPolygon2D");
-}
-
-void CollisionPolygon2DEditorPlugin::make_visible(bool p_visible) {
-
- if (p_visible) {
- collision_polygon_editor->show();
- } else {
-
- collision_polygon_editor->hide();
- collision_polygon_editor->edit(NULL);
- }
-}
-
-CollisionPolygon2DEditorPlugin::CollisionPolygon2DEditorPlugin(EditorNode *p_node) {
-
- editor = p_node;
- collision_polygon_editor = memnew(CollisionPolygon2DEditor(p_node));
- CanvasItemEditor::get_singleton()->add_control_to_menu_panel(collision_polygon_editor);
-
- collision_polygon_editor->hide();
+CollisionPolygon2DEditor::CollisionPolygon2DEditor(EditorNode *p_editor)
+ : AbstractPolygon2DEditor(p_editor) {
}
-CollisionPolygon2DEditorPlugin::~CollisionPolygon2DEditorPlugin() {
+CollisionPolygon2DEditorPlugin::CollisionPolygon2DEditorPlugin(EditorNode *p_node)
+ : AbstractPolygon2DEditorPlugin(p_node, memnew(CollisionPolygon2DEditor(p_node)), "CollisionPolygon2D") {
}
diff --git a/editor/plugins/collision_polygon_2d_editor_plugin.h b/editor/plugins/collision_polygon_2d_editor_plugin.h
index 4715abd2e6..edf3bbcc08 100644
--- a/editor/plugins/collision_polygon_2d_editor_plugin.h
+++ b/editor/plugins/collision_polygon_2d_editor_plugin.h
@@ -30,78 +30,32 @@
#ifndef COLLISION_POLYGON_2D_EDITOR_PLUGIN_H
#define COLLISION_POLYGON_2D_EDITOR_PLUGIN_H
-#include "editor/editor_node.h"
-#include "editor/editor_plugin.h"
+#include "editor/plugins/abstract_polygon_2d_editor.h"
#include "scene/2d/collision_polygon_2d.h"
-#include "scene/gui/tool_button.h"
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
-class CanvasItemEditor;
+class CollisionPolygon2DEditor : public AbstractPolygon2DEditor {
-class CollisionPolygon2DEditor : public HBoxContainer {
+ GDCLASS(CollisionPolygon2DEditor, AbstractPolygon2DEditor);
- GDCLASS(CollisionPolygon2DEditor, HBoxContainer);
-
- UndoRedo *undo_redo;
- enum Mode {
-
- MODE_CREATE,
- MODE_EDIT,
-
- };
-
- Mode mode;
-
- ToolButton *button_create;
- ToolButton *button_edit;
-
- CanvasItemEditor *canvas_item_editor;
- EditorNode *editor;
- Panel *panel;
CollisionPolygon2D *node;
- MenuButton *options;
-
- int edited_point;
- Vector2 edited_point_pos;
- Vector<Vector2> pre_move_edit;
- Vector<Vector2> wip;
- bool wip_active;
-
- void _wip_close();
- void _canvas_draw();
- void _menu_option(int p_option);
protected:
- void _notification(int p_what);
- void _node_removed(Node *p_node);
- static void _bind_methods();
+ virtual Node2D *_get_node() const;
+ virtual void _set_node(Node *p_polygon);
public:
- bool forward_gui_input(const Ref<InputEvent> &p_event);
- void edit(Node *p_collision_polygon);
CollisionPolygon2DEditor(EditorNode *p_editor);
};
-class CollisionPolygon2DEditorPlugin : public EditorPlugin {
-
- GDCLASS(CollisionPolygon2DEditorPlugin, EditorPlugin);
+class CollisionPolygon2DEditorPlugin : public AbstractPolygon2DEditorPlugin {
- CollisionPolygon2DEditor *collision_polygon_editor;
- EditorNode *editor;
+ GDCLASS(CollisionPolygon2DEditorPlugin, AbstractPolygon2DEditorPlugin);
public:
- virtual bool forward_canvas_gui_input(const Transform2D &p_canvas_xform, const Ref<InputEvent> &p_event) { return collision_polygon_editor->forward_gui_input(p_event); }
-
- virtual String get_name() const { return "CollisionPolygon2D"; }
- bool has_main_screen() const { return false; }
- virtual void edit(Object *p_object);
- virtual bool handles(Object *p_object) const;
- virtual void make_visible(bool p_visible);
-
CollisionPolygon2DEditorPlugin(EditorNode *p_node);
- ~CollisionPolygon2DEditorPlugin();
};
#endif // COLLISION_POLYGON_2D_EDITOR_PLUGIN_H
diff --git a/editor/plugins/collision_polygon_editor_plugin.cpp b/editor/plugins/collision_polygon_editor_plugin.cpp
index 24c4813771..0818c8975e 100644
--- a/editor/plugins/collision_polygon_editor_plugin.cpp
+++ b/editor/plugins/collision_polygon_editor_plugin.cpp
@@ -389,7 +389,7 @@ void CollisionPolygonEditor::_polygon_draw() {
rect = rect.grow(1);
- Rect3 r;
+ AABB r;
r.position.x = rect.position.x;
r.position.y = rect.position.y;
r.position.z = depth;
diff --git a/editor/plugins/collision_shape_2d_editor_plugin.cpp b/editor/plugins/collision_shape_2d_editor_plugin.cpp
index 3e6165e552..005de096cd 100644
--- a/editor/plugins/collision_shape_2d_editor_plugin.cpp
+++ b/editor/plugins/collision_shape_2d_editor_plugin.cpp
@@ -302,7 +302,7 @@ void CollisionShape2DEditor::commit_handle(int idx, Variant &p_org) {
undo_redo->commit_action();
}
-bool CollisionShape2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
+bool CollisionShape2DEditor::forward_canvas_gui_input(const Ref<InputEvent> &p_event) {
if (!node) {
return false;
@@ -317,17 +317,17 @@ bool CollisionShape2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
}
Ref<InputEventMouseButton> mb = p_event;
+ Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
if (mb.is_valid()) {
- Transform2D gt = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
-
- Point2 gpoint(mb->get_position().x, mb->get_position().y);
+ Vector2 gpoint = mb->get_position();
+ Vector2 cpoint = node->get_global_transform().affine_inverse().xform(canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(mb->get_position())));
if (mb->get_button_index() == BUTTON_LEFT) {
if (mb->is_pressed()) {
for (int i = 0; i < handles.size(); i++) {
- if (gt.xform(handles[i]).distance_to(gpoint) < 8) {
+ if (xform.xform(handles[i]).distance_to(gpoint) < 8) {
edit_handle = i;
break;
@@ -368,9 +368,7 @@ bool CollisionShape2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
return false;
}
- Point2 gpoint = mm->get_position();
- Point2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
- cpoint = canvas_item_editor->snap_point(cpoint);
+ Vector2 cpoint = canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(mm->get_position()));
cpoint = node->get_global_transform().affine_inverse().xform(cpoint);
set_handle(edit_handle, cpoint);
@@ -416,7 +414,7 @@ void CollisionShape2DEditor::_get_current_shape_type() {
canvas_item_editor->get_viewport_control()->update();
}
-void CollisionShape2DEditor::_canvas_draw() {
+void CollisionShape2DEditor::forward_draw_over_canvas(Control *p_canvas) {
if (!node) {
return;
@@ -432,7 +430,6 @@ void CollisionShape2DEditor::_canvas_draw() {
return;
}
- Control *c = canvas_item_editor->get_viewport_control();
Transform2D gt = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
Ref<Texture> h = get_icon("EditorHandle", "EditorIcons");
@@ -451,8 +448,8 @@ void CollisionShape2DEditor::_canvas_draw() {
handles[0] = Point2(radius, -height);
handles[1] = Point2(0, -(height + radius));
- c->draw_texture(h, gt.xform(handles[0]) - size);
- c->draw_texture(h, gt.xform(handles[1]) - size);
+ p_canvas->draw_texture(h, gt.xform(handles[0]) - size);
+ p_canvas->draw_texture(h, gt.xform(handles[1]) - size);
} break;
@@ -462,7 +459,7 @@ void CollisionShape2DEditor::_canvas_draw() {
handles.resize(1);
handles[0] = Point2(shape->get_radius(), 0);
- c->draw_texture(h, gt.xform(handles[0]) - size);
+ p_canvas->draw_texture(h, gt.xform(handles[0]) - size);
} break;
@@ -481,8 +478,8 @@ void CollisionShape2DEditor::_canvas_draw() {
handles[0] = shape->get_normal() * shape->get_d();
handles[1] = shape->get_normal() * (shape->get_d() + 30.0);
- c->draw_texture(h, gt.xform(handles[0]) - size);
- c->draw_texture(h, gt.xform(handles[1]) - size);
+ p_canvas->draw_texture(h, gt.xform(handles[0]) - size);
+ p_canvas->draw_texture(h, gt.xform(handles[1]) - size);
} break;
@@ -492,7 +489,7 @@ void CollisionShape2DEditor::_canvas_draw() {
handles.resize(1);
handles[0] = Point2(0, shape->get_length());
- c->draw_texture(h, gt.xform(handles[0]) - size);
+ p_canvas->draw_texture(h, gt.xform(handles[0]) - size);
} break;
@@ -504,8 +501,8 @@ void CollisionShape2DEditor::_canvas_draw() {
handles[0] = Point2(ext.x, 0);
handles[1] = Point2(0, -ext.y);
- c->draw_texture(h, gt.xform(handles[0]) - size);
- c->draw_texture(h, gt.xform(handles[1]) - size);
+ p_canvas->draw_texture(h, gt.xform(handles[0]) - size);
+ p_canvas->draw_texture(h, gt.xform(handles[1]) - size);
} break;
@@ -516,8 +513,8 @@ void CollisionShape2DEditor::_canvas_draw() {
handles[0] = shape->get_a();
handles[1] = shape->get_b();
- c->draw_texture(h, gt.xform(handles[0]) - size);
- c->draw_texture(h, gt.xform(handles[1]) - size);
+ p_canvas->draw_texture(h, gt.xform(handles[0]) - size);
+ p_canvas->draw_texture(h, gt.xform(handles[1]) - size);
} break;
}
@@ -532,18 +529,12 @@ void CollisionShape2DEditor::edit(Node *p_node) {
if (p_node) {
node = Object::cast_to<CollisionShape2D>(p_node);
- if (!canvas_item_editor->get_viewport_control()->is_connected("draw", this, "_canvas_draw"))
- canvas_item_editor->get_viewport_control()->connect("draw", this, "_canvas_draw");
-
_get_current_shape_type();
} else {
edit_handle = -1;
shape_type = -1;
- if (canvas_item_editor->get_viewport_control()->is_connected("draw", this, "_canvas_draw"))
- canvas_item_editor->get_viewport_control()->disconnect("draw", this, "_canvas_draw");
-
node = NULL;
}
@@ -552,7 +543,6 @@ void CollisionShape2DEditor::edit(Node *p_node) {
void CollisionShape2DEditor::_bind_methods() {
- ClassDB::bind_method("_canvas_draw", &CollisionShape2DEditor::_canvas_draw);
ClassDB::bind_method("_get_current_shape_type", &CollisionShape2DEditor::_get_current_shape_type);
}
diff --git a/editor/plugins/collision_shape_2d_editor_plugin.h b/editor/plugins/collision_shape_2d_editor_plugin.h
index ffa91952e0..d4fbe87fb3 100644
--- a/editor/plugins/collision_shape_2d_editor_plugin.h
+++ b/editor/plugins/collision_shape_2d_editor_plugin.h
@@ -68,13 +68,13 @@ class CollisionShape2DEditor : public Control {
void commit_handle(int idx, Variant &p_org);
void _get_current_shape_type();
- void _canvas_draw();
protected:
static void _bind_methods();
public:
- bool forward_gui_input(const Ref<InputEvent> &p_event);
+ bool forward_canvas_gui_input(const Ref<InputEvent> &p_event);
+ void forward_draw_over_canvas(Control *p_canvas);
void edit(Node *p_node);
CollisionShape2DEditor(EditorNode *p_editor);
@@ -87,7 +87,8 @@ class CollisionShape2DEditorPlugin : public EditorPlugin {
EditorNode *editor;
public:
- virtual bool forward_canvas_gui_input(const Transform2D &p_canvas_xform, const Ref<InputEvent> &p_event) { return collision_shape_2d_editor->forward_gui_input(p_event); }
+ virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event) { return collision_shape_2d_editor->forward_canvas_gui_input(p_event); }
+ virtual void forward_draw_over_canvas(Control *p_canvas) { return collision_shape_2d_editor->forward_draw_over_canvas(p_canvas); }
virtual String get_name() const { return "CollisionShape2D"; }
bool has_main_screen() const { return false; }
diff --git a/editor/plugins/editor_preview_plugins.cpp b/editor/plugins/editor_preview_plugins.cpp
index c48a241e4d..ed04c90cc5 100644
--- a/editor/plugins/editor_preview_plugins.cpp
+++ b/editor/plugins/editor_preview_plugins.cpp
@@ -184,7 +184,7 @@ Ref<Texture> EditorPackedScenePreviewPlugin::generate(const RES &p_from) {
Ref<Texture> EditorPackedScenePreviewPlugin::generate_from_path(const String &p_path) {
- String temp_path = EditorSettings::get_singleton()->get_settings_path().plus_file("tmp");
+ String temp_path = EditorSettings::get_singleton()->get_cache_dir();
String cache_base = ProjectSettings::get_singleton()->globalize_path(p_path).md5_text();
cache_base = temp_path.plus_file("resthumb-" + cache_base);
@@ -278,11 +278,11 @@ EditorMaterialPreviewPlugin::EditorMaterialPreviewPlugin() {
VS::get_singleton()->camera_set_transform(camera, Transform(Basis(), Vector3(0, 0, 3)));
VS::get_singleton()->camera_set_perspective(camera, 45, 0.1, 10);
- light = VS::get_singleton()->light_create(VS::LIGHT_DIRECTIONAL);
+ light = VS::get_singleton()->directional_light_create();
light_instance = VS::get_singleton()->instance_create2(light, scenario);
VS::get_singleton()->instance_set_transform(light_instance, Transform().looking_at(Vector3(-1, -1, -1), Vector3(0, 1, 0)));
- light2 = VS::get_singleton()->light_create(VS::LIGHT_DIRECTIONAL);
+ light2 = VS::get_singleton()->directional_light_create();
VS::get_singleton()->light_set_color(light2, Color(0.7, 0.7, 0.7));
//VS::get_singleton()->light_set_color(light2, Color(0.7, 0.7, 0.7));
@@ -790,13 +790,13 @@ Ref<Texture> EditorMeshPreviewPlugin::generate(const RES &p_from) {
VS::get_singleton()->instance_set_base(mesh_instance, mesh->get_rid());
- Rect3 aabb = mesh->get_aabb();
+ AABB aabb = mesh->get_aabb();
Vector3 ofs = aabb.position + aabb.size * 0.5;
aabb.position -= ofs;
Transform xform;
xform.basis = Basis().rotated(Vector3(0, 1, 0), -Math_PI * 0.125);
xform.basis = Basis().rotated(Vector3(1, 0, 0), Math_PI * 0.125) * xform.basis;
- Rect3 rot_aabb = xform.xform(aabb);
+ AABB rot_aabb = xform.xform(aabb);
float m = MAX(rot_aabb.size.x, rot_aabb.size.y) * 0.5;
if (m == 0)
return Ref<Texture>();
@@ -850,11 +850,11 @@ EditorMeshPreviewPlugin::EditorMeshPreviewPlugin() {
//VS::get_singleton()->camera_set_perspective(camera,45,0.1,10);
VS::get_singleton()->camera_set_orthogonal(camera, 1.0, 0.01, 1000.0);
- light = VS::get_singleton()->light_create(VS::LIGHT_DIRECTIONAL);
+ light = VS::get_singleton()->directional_light_create();
light_instance = VS::get_singleton()->instance_create2(light, scenario);
VS::get_singleton()->instance_set_transform(light_instance, Transform().looking_at(Vector3(-1, -1, -1), Vector3(0, 1, 0)));
- light2 = VS::get_singleton()->light_create(VS::LIGHT_DIRECTIONAL);
+ light2 = VS::get_singleton()->directional_light_create();
VS::get_singleton()->light_set_color(light2, Color(0.7, 0.7, 0.7));
//VS::get_singleton()->light_set_color(light2, VS::LIGHT_COLOR_SPECULAR, Color(0.0, 0.0, 0.0));
light_instance2 = VS::get_singleton()->instance_create2(light2, scenario);
diff --git a/editor/plugins/gi_probe_editor_plugin.cpp b/editor/plugins/gi_probe_editor_plugin.cpp
index fcbf282758..443cd2e41f 100644
--- a/editor/plugins/gi_probe_editor_plugin.cpp
+++ b/editor/plugins/gi_probe_editor_plugin.cpp
@@ -60,6 +60,27 @@ void GIProbeEditorPlugin::make_visible(bool p_visible) {
}
}
+EditorProgress *GIProbeEditorPlugin::tmp_progress = NULL;
+
+void GIProbeEditorPlugin::bake_func_begin(int p_steps) {
+
+ ERR_FAIL_COND(tmp_progress != NULL);
+
+ tmp_progress = memnew(EditorProgress("bake_gi", TTR("Bake GI Probe"), p_steps));
+}
+
+void GIProbeEditorPlugin::bake_func_step(int p_step, const String &p_description) {
+
+ ERR_FAIL_COND(tmp_progress == NULL);
+ tmp_progress->step(p_description, p_step);
+}
+
+void GIProbeEditorPlugin::bake_func_end() {
+ ERR_FAIL_COND(tmp_progress == NULL);
+ memdelete(tmp_progress);
+ tmp_progress = NULL;
+}
+
void GIProbeEditorPlugin::_bind_methods() {
ClassDB::bind_method("_bake", &GIProbeEditorPlugin::_bake);
@@ -70,10 +91,15 @@ GIProbeEditorPlugin::GIProbeEditorPlugin(EditorNode *p_node) {
editor = p_node;
bake = memnew(Button);
bake->set_icon(editor->get_gui_base()->get_icon("BakedLight", "EditorIcons"));
+ bake->set_text(TTR("Bake GI Probe"));
bake->hide();
bake->connect("pressed", this, "_bake");
add_control_to_container(CONTAINER_SPATIAL_EDITOR_MENU, bake);
gi_probe = NULL;
+
+ GIProbe::bake_begin_function = bake_func_begin;
+ GIProbe::bake_step_function = bake_func_step;
+ GIProbe::bake_end_function = bake_func_end;
}
GIProbeEditorPlugin::~GIProbeEditorPlugin() {
diff --git a/editor/plugins/gi_probe_editor_plugin.h b/editor/plugins/gi_probe_editor_plugin.h
index a1fecd2911..527f420510 100644
--- a/editor/plugins/gi_probe_editor_plugin.h
+++ b/editor/plugins/gi_probe_editor_plugin.h
@@ -44,6 +44,11 @@ class GIProbeEditorPlugin : public EditorPlugin {
Button *bake;
EditorNode *editor;
+ static EditorProgress *tmp_progress;
+ static void bake_func_begin(int p_steps);
+ static void bake_func_step(int p_step, const String &p_description);
+ static void bake_func_end();
+
void _bake();
protected:
diff --git a/editor/plugins/light_occluder_2d_editor_plugin.cpp b/editor/plugins/light_occluder_2d_editor_plugin.cpp
index ed0bc60d2f..485657d2c9 100644
--- a/editor/plugins/light_occluder_2d_editor_plugin.cpp
+++ b/editor/plugins/light_occluder_2d_editor_plugin.cpp
@@ -119,9 +119,7 @@ bool LightOccluder2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
Vector2 gpoint = mb->get_position();
- Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
- cpoint = canvas_item_editor->snap_point(cpoint);
- cpoint = node->get_global_transform().affine_inverse().xform(cpoint);
+ Vector2 cpoint = node->get_global_transform().affine_inverse().xform(canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(mb->get_position())));
Vector<Vector2> poly = Variant(node->get_occluder_polygon()->get_polygon());
@@ -319,7 +317,8 @@ bool LightOccluder2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
return false;
}
-void LightOccluder2DEditor::_canvas_draw() {
+
+void LightOccluder2DEditor::forward_draw_over_canvas(Control *p_canvas) {
if (!node || !node->get_occluder_polygon().is_valid())
return;
@@ -368,17 +367,12 @@ void LightOccluder2DEditor::edit(Node *p_collision_polygon) {
if (p_collision_polygon) {
node = Object::cast_to<LightOccluder2D>(p_collision_polygon);
- if (!canvas_item_editor->get_viewport_control()->is_connected("draw", this, "_canvas_draw"))
- canvas_item_editor->get_viewport_control()->connect("draw", this, "_canvas_draw");
wip.clear();
wip_active = false;
edited_point = -1;
canvas_item_editor->get_viewport_control()->update();
} else {
node = NULL;
-
- if (canvas_item_editor->get_viewport_control()->is_connected("draw", this, "_canvas_draw"))
- canvas_item_editor->get_viewport_control()->disconnect("draw", this, "_canvas_draw");
}
}
@@ -395,7 +389,6 @@ void LightOccluder2DEditor::_create_poly() {
void LightOccluder2DEditor::_bind_methods() {
ClassDB::bind_method(D_METHOD("_menu_option"), &LightOccluder2DEditor::_menu_option);
- ClassDB::bind_method(D_METHOD("_canvas_draw"), &LightOccluder2DEditor::_canvas_draw);
ClassDB::bind_method(D_METHOD("_node_removed"), &LightOccluder2DEditor::_node_removed);
ClassDB::bind_method(D_METHOD("_create_poly"), &LightOccluder2DEditor::_create_poly);
}
@@ -430,7 +423,7 @@ LightOccluder2DEditor::LightOccluder2DEditor(EditorNode *p_editor) {
void LightOccluder2DEditorPlugin::edit(Object *p_object) {
- collision_polygon_editor->edit(Object::cast_to<Node>(p_object));
+ light_occluder_editor->edit(Object::cast_to<Node>(p_object));
}
bool LightOccluder2DEditorPlugin::handles(Object *p_object) const {
@@ -441,21 +434,21 @@ bool LightOccluder2DEditorPlugin::handles(Object *p_object) const {
void LightOccluder2DEditorPlugin::make_visible(bool p_visible) {
if (p_visible) {
- collision_polygon_editor->show();
+ light_occluder_editor->show();
} else {
- collision_polygon_editor->hide();
- collision_polygon_editor->edit(NULL);
+ light_occluder_editor->hide();
+ light_occluder_editor->edit(NULL);
}
}
LightOccluder2DEditorPlugin::LightOccluder2DEditorPlugin(EditorNode *p_node) {
editor = p_node;
- collision_polygon_editor = memnew(LightOccluder2DEditor(p_node));
- CanvasItemEditor::get_singleton()->add_control_to_menu_panel(collision_polygon_editor);
+ light_occluder_editor = memnew(LightOccluder2DEditor(p_node));
+ CanvasItemEditor::get_singleton()->add_control_to_menu_panel(light_occluder_editor);
- collision_polygon_editor->hide();
+ light_occluder_editor->hide();
}
LightOccluder2DEditorPlugin::~LightOccluder2DEditorPlugin() {
diff --git a/editor/plugins/light_occluder_2d_editor_plugin.h b/editor/plugins/light_occluder_2d_editor_plugin.h
index b270dcb6e5..068832d8ed 100644
--- a/editor/plugins/light_occluder_2d_editor_plugin.h
+++ b/editor/plugins/light_occluder_2d_editor_plugin.h
@@ -72,7 +72,6 @@ class LightOccluder2DEditor : public HBoxContainer {
ConfirmationDialog *create_poly;
void _wip_close(bool p_closed);
- void _canvas_draw();
void _menu_option(int p_option);
void _create_poly();
@@ -83,6 +82,7 @@ protected:
public:
Vector2 snap_point(const Vector2 &p_point) const;
+ void forward_draw_over_canvas(Control *p_canvas);
bool forward_gui_input(const Ref<InputEvent> &p_event);
void edit(Node *p_collision_polygon);
LightOccluder2DEditor(EditorNode *p_editor);
@@ -92,11 +92,12 @@ class LightOccluder2DEditorPlugin : public EditorPlugin {
GDCLASS(LightOccluder2DEditorPlugin, EditorPlugin);
- LightOccluder2DEditor *collision_polygon_editor;
+ LightOccluder2DEditor *light_occluder_editor;
EditorNode *editor;
public:
- virtual bool forward_canvas_gui_input(const Transform2D &p_canvas_xform, const Ref<InputEvent> &p_event) { return collision_polygon_editor->forward_gui_input(p_event); }
+ virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event) { return light_occluder_editor->forward_gui_input(p_event); }
+ virtual void forward_draw_over_canvas(Control *p_canvas) { return light_occluder_editor->forward_draw_over_canvas(p_canvas); }
virtual String get_name() const { return "LightOccluder2D"; }
bool has_main_screen() const { return false; }
diff --git a/editor/plugins/line_2d_editor_plugin.cpp b/editor/plugins/line_2d_editor_plugin.cpp
index ef3ee6a78f..51fa488b43 100644
--- a/editor/plugins/line_2d_editor_plugin.cpp
+++ b/editor/plugins/line_2d_editor_plugin.cpp
@@ -29,269 +29,42 @@
/*************************************************************************/
#include "line_2d_editor_plugin.h"
-#include "canvas_item_editor_plugin.h"
-#include "editor/editor_settings.h"
-#include "os/file_access.h"
-#include "os/keyboard.h"
+Node2D *Line2DEditor::_get_node() const {
-//----------------------------------------------------------------------------
-// Line2DEditor
-//----------------------------------------------------------------------------
-
-void Line2DEditor::_node_removed(Node *p_node) {
- if (p_node == node) {
- node = NULL;
- hide();
- }
-}
-
-void Line2DEditor::_notification(int p_what) {
- switch (p_what) {
- case NOTIFICATION_VISIBILITY_CHANGED:
- // This widget is not a child but should have the same visibility state
- base_hb->set_visible(is_visible());
- break;
- }
-}
-
-Vector2 Line2DEditor::mouse_to_local_pos(Vector2 gpos, bool alt) {
- Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
- return !alt ? canvas_item_editor->snap_point(xform.affine_inverse().xform(gpos)) : node->get_global_transform().affine_inverse().xform(canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpos)));
-}
-
-int Line2DEditor::get_point_index_at(Vector2 gpos) {
- ERR_FAIL_COND_V(node == 0, -1);
-
- real_t grab_threshold = EDITOR_DEF("editors/poly_editor/point_grab_radius", 8);
- Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
-
- for (int i = 0; i < node->get_point_count(); ++i) {
- Point2 p = xform.xform(node->get_point_position(i));
- if (gpos.distance_to(p) < grab_threshold) {
- return i;
- }
- }
-
- return -1;
-}
-
-bool Line2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
-
- if (!node)
- return false;
-
- if (!node->is_visible())
- return false;
-
- Ref<InputEventMouseButton> mb = p_event;
-
- if (mb.is_valid()) {
-
- Vector2 gpoint = mb->get_position();
- Vector2 cpoint = mouse_to_local_pos(gpoint, mb->get_alt());
-
- if (mb->is_pressed() && _dragging == false) {
- int i = get_point_index_at(gpoint);
- if (i != -1) {
- if (mb->get_button_index() == BUTTON_LEFT && !mb->get_shift() && mode == MODE_EDIT) {
- _dragging = true;
- action_point = i;
- moving_from = node->get_point_position(i);
- moving_screen_from = gpoint;
- } else if ((mb->get_button_index() == BUTTON_RIGHT && mode == MODE_EDIT) || (mb->get_button_index() == BUTTON_LEFT && mode == MODE_DELETE)) {
- undo_redo->create_action(TTR("Remove Point from Line2D"));
- undo_redo->add_do_method(node, "remove_point", i);
- undo_redo->add_undo_method(node, "add_point", node->get_point_position(i), i);
- undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
- undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
- undo_redo->commit_action();
- }
- return true;
- }
- }
-
- if (mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT && ((mb->get_command() && mode == MODE_EDIT) || mode == MODE_CREATE)) {
-
- undo_redo->create_action(TTR("Add Point to Line2D"));
- undo_redo->add_do_method(node, "add_point", cpoint);
- undo_redo->add_undo_method(node, "remove_point", node->get_point_count());
- undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
- undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
- undo_redo->commit_action();
-
- _dragging = true;
- action_point = node->get_point_count() - 1;
- moving_from = node->get_point_position(action_point);
- moving_screen_from = gpoint;
-
- canvas_item_editor->get_viewport_control()->update();
-
- return true;
- }
-
- if (!mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT && _dragging) {
- undo_redo->create_action(TTR("Move Point in Line2D"));
- undo_redo->add_do_method(node, "set_point_position", action_point, cpoint);
- undo_redo->add_undo_method(node, "set_point_position", action_point, moving_from);
- undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
- undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
- undo_redo->commit_action();
- _dragging = false;
- return true;
- }
- }
-
- Ref<InputEventMouseMotion> mm = p_event;
-
- if (mm.is_valid()) {
-
- if (_dragging) {
- Vector2 cpoint = mouse_to_local_pos(mm->get_position(), mm->get_alt());
- node->set_point_position(action_point, cpoint);
- canvas_item_editor->get_viewport_control()->update();
- return true;
- }
- }
-
- return false;
+ return node;
}
-void Line2DEditor::_canvas_draw() {
-
- if (!node)
- return;
+void Line2DEditor::_set_node(Node *p_line) {
- if (!node->is_visible())
- return;
-
- Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
- Ref<Texture> handle = get_icon("EditorHandle", "EditorIcons");
- Size2 handle_size = handle->get_size();
-
- int len = node->get_point_count();
- Control *vpc = canvas_item_editor->get_viewport_control();
-
- for (int i = 0; i < len; ++i) {
- Vector2 point = xform.xform(node->get_point_position(i));
- vpc->draw_texture_rect(handle, Rect2(point - handle_size * 0.5, handle_size), false);
- }
+ node = Object::cast_to<Line2D>(p_line);
}
-void Line2DEditor::_node_visibility_changed() {
- if (!node)
- return;
- canvas_item_editor->get_viewport_control()->update();
-}
-
-void Line2DEditor::edit(Node *p_line2d) {
-
- if (!canvas_item_editor)
- canvas_item_editor = CanvasItemEditor::get_singleton();
+bool Line2DEditor::_is_line() const {
- if (p_line2d) {
- node = Object::cast_to<Line2D>(p_line2d);
- if (!canvas_item_editor->get_viewport_control()->is_connected("draw", this, "_canvas_draw"))
- canvas_item_editor->get_viewport_control()->connect("draw", this, "_canvas_draw");
- if (!node->is_connected("visibility_changed", this, "_node_visibility_changed"))
- node->connect("visibility_changed", this, "_node_visibility_changed");
- } else {
- if (canvas_item_editor->get_viewport_control()->is_connected("draw", this, "_canvas_draw"))
- canvas_item_editor->get_viewport_control()->disconnect("draw", this, "_canvas_draw");
- // node may have been deleted at this point
- if (node && node->is_connected("visibility_changed", this, "_node_visibility_changed"))
- node->disconnect("visibility_changed", this, "_node_visibility_changed");
- node = NULL;
- }
+ return true;
}
-void Line2DEditor::_bind_methods() {
- ClassDB::bind_method(D_METHOD("_canvas_draw"), &Line2DEditor::_canvas_draw);
- ClassDB::bind_method(D_METHOD("_node_visibility_changed"), &Line2DEditor::_node_visibility_changed);
- ClassDB::bind_method(D_METHOD("_mode_selected"), &Line2DEditor::_mode_selected);
-}
+Variant Line2DEditor::_get_polygon(int p_idx) const {
-void Line2DEditor::_mode_selected(int p_mode) {
- for (int i = 0; i < _MODE_COUNT; ++i) {
- toolbar_buttons[i]->set_pressed(i == p_mode);
- }
- mode = Mode(p_mode);
+ return _get_node()->get("points");
}
-Line2DEditor::Line2DEditor(EditorNode *p_editor) {
-
- canvas_item_editor = NULL;
- editor = p_editor;
- undo_redo = editor->get_undo_redo();
-
- _dragging = false;
-
- base_hb = memnew(HBoxContainer);
- CanvasItemEditor::get_singleton()->add_control_to_menu_panel(base_hb);
-
- sep = memnew(VSeparator);
- base_hb->add_child(sep);
-
- {
- ToolButton *b = memnew(ToolButton);
- b->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("CurveEdit", "EditorIcons"));
- b->set_toggle_mode(true);
- b->set_focus_mode(Control::FOCUS_NONE);
- b->set_tooltip(
- TTR("Select Points") + "\n" + TTR("Shift+Drag: Select Control Points") + "\n" + keycode_get_string(KEY_MASK_CMD) + TTR("Click: Add Point") + "\n" + TTR("Right Click: Delete Point"));
- b->connect("pressed", this, "_mode_selected", varray(MODE_EDIT));
- toolbar_buttons[MODE_EDIT] = b;
- base_hb->add_child(b);
- }
+void Line2DEditor::_set_polygon(int p_idx, const Variant &p_polygon) const {
- {
- ToolButton *b = memnew(ToolButton);
- b->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("CurveCreate", "EditorIcons"));
- b->set_toggle_mode(true);
- b->set_focus_mode(Control::FOCUS_NONE);
- b->set_tooltip(TTR("Add Point (in empty space)") + "\n" + TTR("Split Segment (in line)"));
- b->connect("pressed", this, "_mode_selected", varray(MODE_CREATE));
- toolbar_buttons[MODE_CREATE] = b;
- base_hb->add_child(b);
- }
-
- {
- ToolButton *b = memnew(ToolButton);
- b->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("CurveDelete", "EditorIcons"));
- b->set_toggle_mode(true);
- b->set_focus_mode(Control::FOCUS_NONE);
- b->set_tooltip(TTR("Delete Point"));
- b->connect("pressed", this, "_mode_selected", varray(MODE_DELETE));
- toolbar_buttons[MODE_DELETE] = b;
- base_hb->add_child(b);
- }
-
- base_hb->hide();
- hide();
-
- _mode_selected(MODE_CREATE);
+ _get_node()->set("points", p_polygon);
}
-//----------------------------------------------------------------------------
-// Line2DEditorPlugin
-//----------------------------------------------------------------------------
-
-void Line2DEditorPlugin::edit(Object *p_object) {
- line2d_editor->edit(Object::cast_to<Node>(p_object));
-}
+void Line2DEditor::_action_set_polygon(int p_idx, const Variant &p_previous, const Variant &p_polygon) {
-bool Line2DEditorPlugin::handles(Object *p_object) const {
- return p_object->is_class("Line2D");
+ Node2D *node = _get_node();
+ undo_redo->add_do_method(node, "set_points", p_polygon);
+ undo_redo->add_undo_method(node, "set_points", p_previous);
}
-void Line2DEditorPlugin::make_visible(bool p_visible) {
- line2d_editor->set_visible(p_visible);
- if (p_visible == false)
- line2d_editor->edit(NULL);
+Line2DEditor::Line2DEditor(EditorNode *p_editor)
+ : AbstractPolygon2DEditor(p_editor) {
}
-Line2DEditorPlugin::Line2DEditorPlugin(EditorNode *p_node) {
- editor = p_node;
- line2d_editor = memnew(Line2DEditor(p_node));
- CanvasItemEditor::get_singleton()->add_control_to_menu_panel(line2d_editor);
- line2d_editor->hide();
+Line2DEditorPlugin::Line2DEditorPlugin(EditorNode *p_node)
+ : AbstractPolygon2DEditorPlugin(p_node, memnew(Line2DEditor(p_node)), "Line2D") {
}
diff --git a/editor/plugins/line_2d_editor_plugin.h b/editor/plugins/line_2d_editor_plugin.h
index dea0433084..24c19c420d 100644
--- a/editor/plugins/line_2d_editor_plugin.h
+++ b/editor/plugins/line_2d_editor_plugin.h
@@ -30,85 +30,34 @@
#ifndef LINE_2D_EDITOR_PLUGIN_H
#define LINE_2D_EDITOR_PLUGIN_H
-#include "editor/editor_node.h"
-#include "editor/editor_plugin.h"
+#include "editor/plugins/abstract_polygon_2d_editor.h"
#include "scene/2d/line_2d.h"
-#include "scene/2d/path_2d.h"
-#include "scene/gui/tool_button.h"
-class CanvasItemEditor;
+class Line2DEditor : public AbstractPolygon2DEditor {
-class Line2DEditor : public HBoxContainer {
- GDCLASS(Line2DEditor, HBoxContainer)
+ GDCLASS(Line2DEditor, AbstractPolygon2DEditor);
-public:
- bool forward_gui_input(const Ref<InputEvent> &p_event);
- void edit(Node *p_line2d);
- Line2DEditor(EditorNode *p_editor);
-
-protected:
- void _node_removed(Node *p_node);
- void _notification(int p_what);
-
- Vector2 mouse_to_local_pos(Vector2 mpos);
-
- static void _bind_methods();
-
-private:
- void _mode_selected(int p_mode);
- void _canvas_draw();
- void _node_visibility_changed();
-
- int get_point_index_at(Vector2 gpos);
- Vector2 mouse_to_local_pos(Vector2 gpos, bool alt);
-
- UndoRedo *undo_redo;
-
- CanvasItemEditor *canvas_item_editor;
- EditorNode *editor;
- Panel *panel;
Line2D *node;
- HBoxContainer *base_hb;
- Separator *sep;
-
- enum Mode {
- MODE_CREATE = 0,
- MODE_EDIT,
- MODE_DELETE,
- _MODE_COUNT
- };
+protected:
+ virtual Node2D *_get_node() const;
+ virtual void _set_node(Node *p_line);
- Mode mode;
- ToolButton *toolbar_buttons[_MODE_COUNT];
+ virtual bool _is_line() const;
+ virtual Variant _get_polygon(int p_idx) const;
+ virtual void _set_polygon(int p_idx, const Variant &p_polygon) const;
+ virtual void _action_set_polygon(int p_idx, const Variant &p_previous, const Variant &p_polygon);
- bool _dragging;
- int action_point;
- Point2 moving_from;
- Point2 moving_screen_from;
+public:
+ Line2DEditor(EditorNode *p_editor);
};
-class Line2DEditorPlugin : public EditorPlugin {
- GDCLASS(Line2DEditorPlugin, EditorPlugin)
+class Line2DEditorPlugin : public AbstractPolygon2DEditorPlugin {
-public:
- virtual bool forward_canvas_gui_input(
- const Transform2D &p_canvas_xform,
- const Ref<InputEvent> &p_event) {
- return line2d_editor->forward_gui_input(p_event);
- }
-
- virtual String get_name() const { return "Line2D"; }
- bool has_main_screen() const { return false; }
- virtual void edit(Object *p_object);
- virtual bool handles(Object *p_object) const;
- virtual void make_visible(bool p_visible);
+ GDCLASS(Line2DEditorPlugin, AbstractPolygon2DEditorPlugin);
+public:
Line2DEditorPlugin(EditorNode *p_node);
-
-private:
- Line2DEditor *line2d_editor;
- EditorNode *editor;
};
#endif // LINE_2D_EDITOR_PLUGIN_H
diff --git a/editor/plugins/material_editor_plugin.cpp b/editor/plugins/material_editor_plugin.cpp
index 6b613c1bcc..1fc112896d 100644
--- a/editor/plugins/material_editor_plugin.cpp
+++ b/editor/plugins/material_editor_plugin.cpp
@@ -32,6 +32,7 @@
// Waiting for PropertyEditor rewrite (planned for 3.1) to be refactored.
#include "material_editor_plugin.h"
+#include "scene/3d/particles.h"
#if 0
@@ -449,6 +450,90 @@ Ref<Resource> SpatialMaterialConversionPlugin::convert(const Ref<Resource> &p_re
VS::get_singleton()->shader_get_param_list(mat->get_shader_rid(), &params);
for (List<PropertyInfo>::Element *E = params.front(); E; E = E->next()) {
+
+ // Texture parameter has to be treated specially since SpatialMaterial saved it
+ // as RID but ShaderMaterial needs Texture itself
+ Ref<Texture> texture = mat->get_texture_by_name(E->get().name);
+ if (texture.is_valid()) {
+ smat->set_shader_param(E->get().name, texture);
+ } else {
+ Variant value = VS::get_singleton()->material_get_param(mat->get_rid(), E->get().name);
+ smat->set_shader_param(E->get().name, value);
+ }
+ }
+
+ smat->set_render_priority(mat->get_render_priority());
+ return smat;
+}
+
+String ParticlesMaterialConversionPlugin::converts_to() const {
+
+ return "ShaderMaterial";
+}
+bool ParticlesMaterialConversionPlugin::handles(const Ref<Resource> &p_resource) const {
+
+ Ref<ParticlesMaterial> mat = p_resource;
+ return mat.is_valid();
+}
+Ref<Resource> ParticlesMaterialConversionPlugin::convert(const Ref<Resource> &p_resource) {
+
+ Ref<ParticlesMaterial> mat = p_resource;
+ ERR_FAIL_COND_V(!mat.is_valid(), Ref<Resource>());
+
+ Ref<ShaderMaterial> smat;
+ smat.instance();
+
+ Ref<Shader> shader;
+ shader.instance();
+
+ String code = VS::get_singleton()->shader_get_code(mat->get_shader_rid());
+
+ shader->set_code(code);
+
+ smat->set_shader(shader);
+
+ List<PropertyInfo> params;
+ VS::get_singleton()->shader_get_param_list(mat->get_shader_rid(), &params);
+
+ for (List<PropertyInfo>::Element *E = params.front(); E; E = E->next()) {
+ Variant value = VS::get_singleton()->material_get_param(mat->get_rid(), E->get().name);
+ smat->set_shader_param(E->get().name, value);
+ }
+
+ smat->set_render_priority(mat->get_render_priority());
+ return smat;
+}
+
+String CanvasItemMaterialConversionPlugin::converts_to() const {
+
+ return "ShaderMaterial";
+}
+bool CanvasItemMaterialConversionPlugin::handles(const Ref<Resource> &p_resource) const {
+
+ Ref<CanvasItemMaterial> mat = p_resource;
+ return mat.is_valid();
+}
+Ref<Resource> CanvasItemMaterialConversionPlugin::convert(const Ref<Resource> &p_resource) {
+
+ Ref<CanvasItemMaterial> mat = p_resource;
+ ERR_FAIL_COND_V(!mat.is_valid(), Ref<Resource>());
+
+ Ref<ShaderMaterial> smat;
+ smat.instance();
+
+ Ref<Shader> shader;
+ shader.instance();
+
+ String code = VS::get_singleton()->shader_get_code(mat->get_shader_rid());
+
+ shader->set_code(code);
+
+ smat->set_shader(shader);
+
+ List<PropertyInfo> params;
+ VS::get_singleton()->shader_get_param_list(mat->get_shader_rid(), &params);
+
+ for (List<PropertyInfo>::Element *E = params.front(); E; E = E->next()) {
Variant value = VS::get_singleton()->material_get_param(mat->get_rid(), E->get().name);
smat->set_shader_param(E->get().name, value);
}
diff --git a/editor/plugins/material_editor_plugin.h b/editor/plugins/material_editor_plugin.h
index af9602f944..2cc24be33a 100644
--- a/editor/plugins/material_editor_plugin.h
+++ b/editor/plugins/material_editor_plugin.h
@@ -111,4 +111,20 @@ public:
virtual Ref<Resource> convert(const Ref<Resource> &p_resource);
};
+class ParticlesMaterialConversionPlugin : public EditorResourceConversionPlugin {
+ GDCLASS(ParticlesMaterialConversionPlugin, EditorResourceConversionPlugin)
+public:
+ virtual String converts_to() const;
+ virtual bool handles(const Ref<Resource> &p_resource) const;
+ virtual Ref<Resource> convert(const Ref<Resource> &p_resource);
+};
+
+class CanvasItemMaterialConversionPlugin : public EditorResourceConversionPlugin {
+ GDCLASS(CanvasItemMaterialConversionPlugin, EditorResourceConversionPlugin)
+public:
+ virtual String converts_to() const;
+ virtual bool handles(const Ref<Resource> &p_resource) const;
+ virtual Ref<Resource> convert(const Ref<Resource> &p_resource);
+};
+
#endif // MATERIAL_EDITOR_PLUGIN_H
diff --git a/editor/plugins/mesh_editor_plugin.cpp b/editor/plugins/mesh_editor_plugin.cpp
index 74618aecc2..60e8858b2d 100644
--- a/editor/plugins/mesh_editor_plugin.cpp
+++ b/editor/plugins/mesh_editor_plugin.cpp
@@ -95,7 +95,7 @@ void MeshEditor::edit(Ref<Mesh> p_mesh) {
rot_y = 0;
_update_rotation();
- Rect3 aabb = mesh->get_aabb();
+ AABB aabb = mesh->get_aabb();
print_line("aabb: " + aabb);
Vector3 ofs = aabb.position + aabb.size * 0.5;
float m = aabb.get_longest_axis_size();
diff --git a/editor/plugins/navigation_mesh_generator.cpp b/editor/plugins/navigation_mesh_generator.cpp
index 526db3a582..5d50e9c855 100644
--- a/editor/plugins/navigation_mesh_generator.cpp
+++ b/editor/plugins/navigation_mesh_generator.cpp
@@ -38,9 +38,11 @@ void NavigationMeshGenerator::_add_vertex(const Vector3 &p_vec3, Vector<float> &
}
void NavigationMeshGenerator::_add_mesh(const Ref<Mesh> &p_mesh, const Transform &p_xform, Vector<float> &p_verticies, Vector<int> &p_indices) {
- int current_vertex_count = p_verticies.size() / 3;
+ int current_vertex_count = 0;
for (int i = 0; i < p_mesh->get_surface_count(); i++) {
+ current_vertex_count = p_verticies.size() / 3;
+
if (p_mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES)
continue;
@@ -213,7 +215,7 @@ void NavigationMeshGenerator::_build_recast_navigation_mesh(Ref<NavigationMesh>
ep->step(TTR("Eroding walkable area..."), 6);
ERR_FAIL_COND(!rcErodeWalkableArea(&ctx, cfg.walkableRadius, *chf));
- ep->step(TTR("Partioning..."), 7);
+ ep->step(TTR("Partitioning..."), 7);
if (p_nav_mesh->get_sample_partition_type() == NavigationMesh::SAMPLE_PARTITION_WATERSHED) {
ERR_FAIL_COND(!rcBuildDistanceField(&ctx, *chf));
ERR_FAIL_COND(!rcBuildRegions(&ctx, *chf, 0, cfg.minRegionArea, cfg.mergeRegionArea));
diff --git a/editor/plugins/navigation_polygon_editor_plugin.cpp b/editor/plugins/navigation_polygon_editor_plugin.cpp
index 69e553eefb..6560a8dac7 100644
--- a/editor/plugins/navigation_polygon_editor_plugin.cpp
+++ b/editor/plugins/navigation_polygon_editor_plugin.cpp
@@ -29,485 +29,101 @@
/*************************************************************************/
#include "navigation_polygon_editor_plugin.h"
-#include "canvas_item_editor_plugin.h"
-#include "editor/editor_settings.h"
-#include "os/file_access.h"
+Ref<NavigationPolygon> NavigationPolygonEditor::_ensure_navpoly() const {
-void NavigationPolygonEditor::_notification(int p_what) {
+ Ref<NavigationPolygon> navpoly = node->get_navigation_polygon();
+ if (!navpoly.is_valid()) {
- switch (p_what) {
-
- case NOTIFICATION_READY: {
-
- button_create->set_icon(get_icon("Edit", "EditorIcons"));
- button_edit->set_icon(get_icon("MovePoint", "EditorIcons"));
- button_edit->set_pressed(true);
- get_tree()->connect("node_removed", this, "_node_removed");
- create_nav->connect("confirmed", this, "_create_nav");
-
- } break;
- case NOTIFICATION_PHYSICS_PROCESS: {
-
- } break;
+ navpoly = Ref<NavigationPolygon>(memnew(NavigationPolygon));
+ node->set_navigation_polygon(navpoly);
}
+ return navpoly;
}
-void NavigationPolygonEditor::_node_removed(Node *p_node) {
- if (p_node == node) {
- node = NULL;
- hide();
- canvas_item_editor->get_viewport_control()->update();
- }
-}
+Node2D *NavigationPolygonEditor::_get_node() const {
-void NavigationPolygonEditor::_create_nav() {
-
- if (!node)
- return;
-
- undo_redo->create_action(TTR("Create Navigation Polygon"));
- undo_redo->add_do_method(node, "set_navigation_polygon", Ref<NavigationPolygon>(memnew(NavigationPolygon)));
- undo_redo->add_undo_method(node, "set_navigation_polygon", Variant(REF()));
- undo_redo->commit_action();
- _menu_option(MODE_CREATE);
+ return node;
}
-void NavigationPolygonEditor::_menu_option(int p_option) {
+void NavigationPolygonEditor::_set_node(Node *p_polygon) {
- switch (p_option) {
-
- case MODE_CREATE: {
-
- mode = MODE_CREATE;
- button_create->set_pressed(true);
- button_edit->set_pressed(false);
- } break;
- case MODE_EDIT: {
-
- mode = MODE_EDIT;
- button_create->set_pressed(false);
- button_edit->set_pressed(true);
- } break;
- }
+ node = Object::cast_to<NavigationPolygonInstance>(p_polygon);
}
-void NavigationPolygonEditor::_wip_close() {
+int NavigationPolygonEditor::_get_polygon_count() const {
- if (wip.size() >= 3) {
-
- undo_redo->create_action(TTR("Create Poly"));
- undo_redo->add_undo_method(node->get_navigation_polygon().ptr(), "remove_outline", node->get_navigation_polygon()->get_outline_count());
- undo_redo->add_do_method(node->get_navigation_polygon().ptr(), "add_outline", wip);
- undo_redo->add_do_method(node->get_navigation_polygon().ptr(), "make_polygons_from_outlines");
- undo_redo->add_undo_method(node->get_navigation_polygon().ptr(), "make_polygons_from_outlines");
- undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
- undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
- undo_redo->commit_action();
- mode = MODE_EDIT;
- button_edit->set_pressed(true);
- button_create->set_pressed(false);
- }
-
- wip.clear();
- wip_active = false;
- edited_point = -1;
+ Ref<NavigationPolygon> navpoly = node->get_navigation_polygon();
+ if (navpoly.is_valid())
+ return navpoly->get_outline_count();
+ else
+ return 0;
}
-bool NavigationPolygonEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
-
- if (!node)
- return false;
-
- if (node->get_navigation_polygon().is_null()) {
-
- Ref<InputEventMouseButton> mb = p_event;
-
- if (mb.is_valid() && mb->get_button_index() == 1 && mb->is_pressed()) {
- create_nav->set_text("No NavigationPolygon resource on this node.\nCreate and assign one?");
- create_nav->popup_centered_minsize();
- }
- return (mb.is_valid() && mb->get_button_index() == 1);
- }
-
- Ref<InputEventMouseButton> mb = p_event;
-
- if (mb.is_valid()) {
-
- Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
-
- Vector2 gpoint = mb->get_position();
- Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
- cpoint = canvas_item_editor->snap_point(cpoint);
- cpoint = node->get_global_transform().affine_inverse().xform(cpoint);
-
- //first check if a point is to be added (segment split)
- real_t grab_threshold = EDITOR_DEF("editors/poly_editor/point_grab_radius", 8);
-
- switch (mode) {
-
- case MODE_CREATE: {
-
- if (mb->get_button_index() == BUTTON_LEFT && mb->is_pressed()) {
-
- if (!wip_active) {
-
- wip.clear();
- wip.push_back(cpoint);
- wip_active = true;
- edited_point_pos = cpoint;
- edited_outline = -1;
- canvas_item_editor->get_viewport_control()->update();
- edited_point = 1;
- return true;
- } else {
-
- if (wip.size() > 1 && xform.xform(wip[0]).distance_to(gpoint) < grab_threshold) {
- //wip closed
- _wip_close();
-
- return true;
- } else {
-
- wip.push_back(cpoint);
- edited_point = wip.size();
- canvas_item_editor->get_viewport_control()->update();
- return true;
-
- //add wip point
- }
- }
- } else if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed() && wip_active) {
- _wip_close();
- }
-
- } break;
-
- case MODE_EDIT: {
-
- if (mb->get_button_index() == BUTTON_LEFT) {
- if (mb->is_pressed()) {
-
- if (mb->get_control()) {
-
- //search edges
- int closest_outline = -1;
- int closest_idx = -1;
- Vector2 closest_pos;
- real_t closest_dist = 1e10;
-
- for (int j = 0; j < node->get_navigation_polygon()->get_outline_count(); j++) {
-
- PoolVector<Vector2> points = node->get_navigation_polygon()->get_outline(j);
-
- int pc = points.size();
- PoolVector<Vector2>::Read poly = points.read();
-
- for (int i = 0; i < pc; i++) {
-
- Vector2 points[2] = { xform.xform(poly[i]),
- xform.xform(poly[(i + 1) % pc]) };
-
- Vector2 cp = Geometry::get_closest_point_to_segment_2d(gpoint, points);
- if (cp.distance_squared_to(points[0]) < CMP_EPSILON2 || cp.distance_squared_to(points[1]) < CMP_EPSILON2)
- continue; //not valid to reuse point
-
- real_t d = cp.distance_to(gpoint);
- if (d < closest_dist && d < grab_threshold) {
- closest_dist = d;
- closest_outline = j;
- closest_pos = cp;
- closest_idx = i;
- }
- }
- }
-
- if (closest_idx >= 0) {
-
- pre_move_edit = node->get_navigation_polygon()->get_outline(closest_outline);
- PoolVector<Point2> poly = pre_move_edit;
- poly.insert(closest_idx + 1, xform.affine_inverse().xform(closest_pos));
- edited_point = closest_idx + 1;
- edited_outline = closest_outline;
- edited_point_pos = xform.affine_inverse().xform(closest_pos);
- node->get_navigation_polygon()->set_outline(closest_outline, poly);
- canvas_item_editor->get_viewport_control()->update();
- return true;
- }
- } else {
-
- //look for points to move
- int closest_outline = -1;
- int closest_idx = -1;
- Vector2 closest_pos;
- real_t closest_dist = 1e10;
-
- for (int j = 0; j < node->get_navigation_polygon()->get_outline_count(); j++) {
-
- PoolVector<Vector2> points = node->get_navigation_polygon()->get_outline(j);
-
- int pc = points.size();
- PoolVector<Vector2>::Read poly = points.read();
+Variant NavigationPolygonEditor::_get_polygon(int p_idx) const {
- for (int i = 0; i < pc; i++) {
-
- Vector2 cp = xform.xform(poly[i]);
-
- real_t d = cp.distance_to(gpoint);
- if (d < closest_dist && d < grab_threshold) {
- closest_dist = d;
- closest_pos = cp;
- closest_outline = j;
- closest_idx = i;
- }
- }
- }
-
- if (closest_idx >= 0) {
-
- pre_move_edit = node->get_navigation_polygon()->get_outline(closest_outline);
- edited_point = closest_idx;
- edited_outline = closest_outline;
- edited_point_pos = xform.affine_inverse().xform(closest_pos);
- canvas_item_editor->get_viewport_control()->update();
- return true;
- }
- }
- } else {
-
- if (edited_point != -1) {
-
- //apply
-
- PoolVector<Vector2> poly = node->get_navigation_polygon()->get_outline(edited_outline);
- ERR_FAIL_INDEX_V(edited_point, poly.size(), false);
- poly.set(edited_point, edited_point_pos);
- undo_redo->create_action(TTR("Edit Poly"));
- undo_redo->add_do_method(node->get_navigation_polygon().ptr(), "set_outline", edited_outline, poly);
- undo_redo->add_undo_method(node->get_navigation_polygon().ptr(), "set_outline", edited_outline, pre_move_edit);
- undo_redo->add_do_method(node->get_navigation_polygon().ptr(), "make_polygons_from_outlines");
- undo_redo->add_undo_method(node->get_navigation_polygon().ptr(), "make_polygons_from_outlines");
- undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
- undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
- undo_redo->commit_action();
-
- edited_point = -1;
- return true;
- }
- }
- } else if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed() && edited_point == -1) {
-
- int closest_outline = -1;
- int closest_idx = -1;
- Vector2 closest_pos;
- real_t closest_dist = 1e10;
-
- for (int j = 0; j < node->get_navigation_polygon()->get_outline_count(); j++) {
-
- PoolVector<Vector2> points = node->get_navigation_polygon()->get_outline(j);
-
- int pc = points.size();
- PoolVector<Vector2>::Read poly = points.read();
-
- for (int i = 0; i < pc; i++) {
-
- Vector2 cp = xform.xform(poly[i]);
-
- real_t d = cp.distance_to(gpoint);
- if (d < closest_dist && d < grab_threshold) {
- closest_dist = d;
- closest_pos = cp;
- closest_outline = j;
- closest_idx = i;
- }
- }
- }
-
- if (closest_idx >= 0) {
-
- PoolVector<Vector2> poly = node->get_navigation_polygon()->get_outline(closest_outline);
-
- if (poly.size() > 3) {
- undo_redo->create_action(TTR("Edit Poly (Remove Point)"));
- undo_redo->add_undo_method(node->get_navigation_polygon().ptr(), "set_outline", closest_outline, poly);
- poly.remove(closest_idx);
- undo_redo->add_do_method(node->get_navigation_polygon().ptr(), "set_outline", closest_outline, poly);
- undo_redo->add_do_method(node->get_navigation_polygon().ptr(), "make_polygons_from_outlines");
- undo_redo->add_undo_method(node->get_navigation_polygon().ptr(), "make_polygons_from_outlines");
- undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
- undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
- undo_redo->commit_action();
- } else {
-
- undo_redo->create_action(TTR("Remove Poly And Point"));
- undo_redo->add_undo_method(node->get_navigation_polygon().ptr(), "add_outline_at_index", poly, closest_outline);
- poly.remove(closest_idx);
- undo_redo->add_do_method(node->get_navigation_polygon().ptr(), "remove_outline", closest_outline);
- undo_redo->add_do_method(node->get_navigation_polygon().ptr(), "make_polygons_from_outlines");
- undo_redo->add_undo_method(node->get_navigation_polygon().ptr(), "make_polygons_from_outlines");
- undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
- undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
- undo_redo->commit_action();
- }
- return true;
- }
- }
-
- } break;
- }
- }
-
- Ref<InputEventMouseMotion> mm = p_event;
-
- if (mm.is_valid()) {
-
- if (edited_point != -1 && (wip_active || mm->get_button_mask() & BUTTON_MASK_LEFT)) {
-
- Vector2 gpoint = mm->get_position();
- Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
- cpoint = canvas_item_editor->snap_point(cpoint);
- edited_point_pos = node->get_global_transform().affine_inverse().xform(cpoint);
-
- canvas_item_editor->get_viewport_control()->update();
- }
- }
-
- return false;
+ Ref<NavigationPolygon> navpoly = node->get_navigation_polygon();
+ if (navpoly.is_valid())
+ return navpoly->get_outline(p_idx);
+ else
+ return Variant(Vector<Vector2>());
}
-void NavigationPolygonEditor::_canvas_draw() {
- if (!node)
- return;
+void NavigationPolygonEditor::_set_polygon(int p_idx, const Variant &p_polygon) const {
- Control *vpc = canvas_item_editor->get_viewport_control();
- if (node->get_navigation_polygon().is_null())
- return;
-
- Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
- Ref<Texture> handle = get_icon("EditorHandle", "EditorIcons");
-
- for (int j = -1; j < node->get_navigation_polygon()->get_outline_count(); j++) {
- Vector<Vector2> poly;
-
- if (wip_active && j == edited_outline) {
- poly = wip;
- } else {
- if (j == -1)
- continue;
- poly = Variant(node->get_navigation_polygon()->get_outline(j));
- }
-
- for (int i = 0; i < poly.size(); i++) {
-
- Vector2 p, p2;
- p = (j == edited_outline && i == edited_point) ? edited_point_pos : poly[i];
- if (j == edited_outline && ((wip_active && i == poly.size() - 1) || (((i + 1) % poly.size()) == edited_point)))
- p2 = edited_point_pos;
- else
- p2 = poly[(i + 1) % poly.size()];
-
- Vector2 point = xform.xform(p);
- Vector2 next_point = xform.xform(p2);
-
- Color col = Color(1, 0.3, 0.1, 0.8);
- vpc->draw_line(point, next_point, col, 2);
- vpc->draw_texture(handle, point - handle->get_size() * 0.5);
- }
- }
+ Ref<NavigationPolygon> navpoly = _ensure_navpoly();
+ navpoly->set_outline(p_idx, p_polygon);
+ navpoly->make_polygons_from_outlines();
}
-void NavigationPolygonEditor::edit(Node *p_collision_polygon) {
-
- if (!canvas_item_editor) {
- canvas_item_editor = CanvasItemEditor::get_singleton();
- }
-
- if (p_collision_polygon) {
+void NavigationPolygonEditor::_action_add_polygon(const Variant &p_polygon) {
- node = Object::cast_to<NavigationPolygonInstance>(p_collision_polygon);
- //Enable the pencil tool if the polygon is empty
- if (!node->get_navigation_polygon().is_null()) {
- if (node->get_navigation_polygon()->get_polygon_count() == 0)
- _menu_option(MODE_CREATE);
- }
- if (!canvas_item_editor->get_viewport_control()->is_connected("draw", this, "_canvas_draw"))
- canvas_item_editor->get_viewport_control()->connect("draw", this, "_canvas_draw");
- wip.clear();
- wip_active = false;
- edited_point = -1;
- canvas_item_editor->get_viewport_control()->update();
-
- } else {
- node = NULL;
-
- if (canvas_item_editor->get_viewport_control()->is_connected("draw", this, "_canvas_draw"))
- canvas_item_editor->get_viewport_control()->disconnect("draw", this, "_canvas_draw");
- }
+ Ref<NavigationPolygon> navpoly = _ensure_navpoly();
+ undo_redo->add_do_method(navpoly.ptr(), "add_outline", p_polygon);
+ undo_redo->add_undo_method(navpoly.ptr(), "remove_outline", navpoly->get_outline_count());
+ undo_redo->add_do_method(navpoly.ptr(), "make_polygons_from_outlines");
+ undo_redo->add_undo_method(navpoly.ptr(), "make_polygons_from_outlines");
}
-void NavigationPolygonEditor::_bind_methods() {
+void NavigationPolygonEditor::_action_remove_polygon(int p_idx) {
- ClassDB::bind_method(D_METHOD("_menu_option"), &NavigationPolygonEditor::_menu_option);
- ClassDB::bind_method(D_METHOD("_canvas_draw"), &NavigationPolygonEditor::_canvas_draw);
- ClassDB::bind_method(D_METHOD("_node_removed"), &NavigationPolygonEditor::_node_removed);
- ClassDB::bind_method(D_METHOD("_create_nav"), &NavigationPolygonEditor::_create_nav);
+ Ref<NavigationPolygon> navpoly = _ensure_navpoly();
+ undo_redo->add_do_method(navpoly.ptr(), "remove_outline", p_idx);
+ undo_redo->add_undo_method(navpoly.ptr(), "add_outline_at_index", navpoly->get_outline(p_idx), p_idx);
+ undo_redo->add_do_method(navpoly.ptr(), "make_polygons_from_outlines");
+ undo_redo->add_undo_method(navpoly.ptr(), "make_polygons_from_outlines");
}
-NavigationPolygonEditor::NavigationPolygonEditor(EditorNode *p_editor) {
- node = NULL;
- canvas_item_editor = NULL;
- editor = p_editor;
- undo_redo = editor->get_undo_redo();
+void NavigationPolygonEditor::_action_set_polygon(int p_idx, const Variant &p_previous, const Variant &p_polygon) {
- add_child(memnew(VSeparator));
- button_create = memnew(ToolButton);
- add_child(button_create);
- button_create->connect("pressed", this, "_menu_option", varray(MODE_CREATE));
- button_create->set_toggle_mode(true);
- button_create->set_tooltip(TTR("Create a new polygon from scratch."));
-
- button_edit = memnew(ToolButton);
- add_child(button_edit);
- button_edit->connect("pressed", this, "_menu_option", varray(MODE_EDIT));
- button_edit->set_toggle_mode(true);
- button_edit->set_tooltip(TTR("Edit existing polygon:") + "\n" + TTR("LMB: Move Point.") + "\n" + TTR("Ctrl+LMB: Split Segment.") + "\n" + TTR("RMB: Erase Point."));
- create_nav = memnew(ConfirmationDialog);
- add_child(create_nav);
- create_nav->get_ok()->set_text(TTR("Create"));
-
- mode = MODE_EDIT;
- wip_active = false;
- edited_outline = -1;
+ Ref<NavigationPolygon> navpoly = _ensure_navpoly();
+ undo_redo->add_do_method(navpoly.ptr(), "set_outline", p_idx, p_polygon);
+ undo_redo->add_undo_method(navpoly.ptr(), "set_outline", p_idx, p_previous);
+ undo_redo->add_do_method(navpoly.ptr(), "make_polygons_from_outlines");
+ undo_redo->add_undo_method(navpoly.ptr(), "make_polygons_from_outlines");
}
-void NavigationPolygonEditorPlugin::edit(Object *p_object) {
+bool NavigationPolygonEditor::_has_resource() const {
- collision_polygon_editor->edit(Object::cast_to<Node>(p_object));
+ return node && node->get_navigation_polygon().is_valid();
}
-bool NavigationPolygonEditorPlugin::handles(Object *p_object) const {
-
- return p_object->is_class("NavigationPolygonInstance");
-}
+void NavigationPolygonEditor::_create_resource() {
-void NavigationPolygonEditorPlugin::make_visible(bool p_visible) {
+ if (!node)
+ return;
- if (p_visible) {
- collision_polygon_editor->show();
- } else {
+ undo_redo->create_action(TTR("Create Navigation Polygon"));
+ undo_redo->add_do_method(node, "set_navigation_polygon", Ref<NavigationPolygon>(memnew(NavigationPolygon)));
+ undo_redo->add_undo_method(node, "set_navigation_polygon", Variant(REF()));
+ undo_redo->commit_action();
- collision_polygon_editor->hide();
- collision_polygon_editor->edit(NULL);
- }
+ _menu_option(MODE_CREATE);
}
-NavigationPolygonEditorPlugin::NavigationPolygonEditorPlugin(EditorNode *p_node) {
-
- editor = p_node;
- collision_polygon_editor = memnew(NavigationPolygonEditor(p_node));
- CanvasItemEditor::get_singleton()->add_control_to_menu_panel(collision_polygon_editor);
-
- collision_polygon_editor->hide();
+NavigationPolygonEditor::NavigationPolygonEditor(EditorNode *p_editor)
+ : AbstractPolygon2DEditor(p_editor) {
}
-NavigationPolygonEditorPlugin::~NavigationPolygonEditorPlugin() {
+NavigationPolygonEditorPlugin::NavigationPolygonEditorPlugin(EditorNode *p_node)
+ : AbstractPolygon2DEditorPlugin(p_node, memnew(NavigationPolygonEditor(p_node)), "NavigationPolygonInstance") {
}
diff --git a/editor/plugins/navigation_polygon_editor_plugin.h b/editor/plugins/navigation_polygon_editor_plugin.h
index 7dd555e9c9..54cc347a8c 100644
--- a/editor/plugins/navigation_polygon_editor_plugin.h
+++ b/editor/plugins/navigation_polygon_editor_plugin.h
@@ -30,83 +30,45 @@
#ifndef NAVIGATIONPOLYGONEDITORPLUGIN_H
#define NAVIGATIONPOLYGONEDITORPLUGIN_H
-#include "editor/editor_node.h"
-#include "editor/editor_plugin.h"
+#include "editor/plugins/abstract_polygon_2d_editor.h"
#include "scene/2d/navigation_polygon.h"
-#include "scene/gui/tool_button.h"
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
-class CanvasItemEditor;
+class NavigationPolygonEditor : public AbstractPolygon2DEditor {
-class NavigationPolygonEditor : public HBoxContainer {
+ GDCLASS(NavigationPolygonEditor, AbstractPolygon2DEditor);
- GDCLASS(NavigationPolygonEditor, HBoxContainer);
-
- UndoRedo *undo_redo;
- enum Mode {
-
- MODE_CREATE,
- MODE_EDIT,
-
- };
-
- Mode mode;
-
- ToolButton *button_create;
- ToolButton *button_edit;
-
- ConfirmationDialog *create_nav;
-
- CanvasItemEditor *canvas_item_editor;
- EditorNode *editor;
- Panel *panel;
NavigationPolygonInstance *node;
- MenuButton *options;
- int edited_outline;
- int edited_point;
- Vector2 edited_point_pos;
- PoolVector<Vector2> pre_move_edit;
- Vector<Vector2> wip;
- bool wip_active;
+ Ref<NavigationPolygon> _ensure_navpoly() const;
- void _wip_close();
- void _canvas_draw();
- void _create_nav();
+protected:
+ virtual Node2D *_get_node() const;
+ virtual void _set_node(Node *p_polygon);
- void _menu_option(int p_option);
+ virtual int _get_polygon_count() const;
+ virtual Variant _get_polygon(int p_idx) const;
+ virtual void _set_polygon(int p_idx, const Variant &p_polygon) const;
-protected:
- void _notification(int p_what);
- void _node_removed(Node *p_node);
- static void _bind_methods();
+ virtual void _action_add_polygon(const Variant &p_polygon);
+ virtual void _action_remove_polygon(int p_idx);
+ virtual void _action_set_polygon(int p_idx, const Variant &p_previous, const Variant &p_polygon);
+
+ virtual bool _has_resource() const;
+ virtual void _create_resource();
public:
- bool forward_gui_input(const Ref<InputEvent> &p_event);
- void edit(Node *p_collision_polygon);
NavigationPolygonEditor(EditorNode *p_editor);
};
-class NavigationPolygonEditorPlugin : public EditorPlugin {
+class NavigationPolygonEditorPlugin : public AbstractPolygon2DEditorPlugin {
- GDCLASS(NavigationPolygonEditorPlugin, EditorPlugin);
-
- NavigationPolygonEditor *collision_polygon_editor;
- EditorNode *editor;
+ GDCLASS(NavigationPolygonEditorPlugin, AbstractPolygon2DEditorPlugin);
public:
- virtual bool forward_canvas_gui_input(const Transform2D &p_canvas_xform, const Ref<InputEvent> &p_event) { return collision_polygon_editor->forward_gui_input(p_event); }
-
- virtual String get_name() const { return "NavigationPolygonInstance"; }
- bool has_main_screen() const { return false; }
- virtual void edit(Object *p_object);
- virtual bool handles(Object *p_object) const;
- virtual void make_visible(bool p_visible);
-
NavigationPolygonEditorPlugin(EditorNode *p_node);
- ~NavigationPolygonEditorPlugin();
};
#endif // NAVIGATIONPOLYGONEDITORPLUGIN_H
diff --git a/editor/plugins/particles_editor_plugin.cpp b/editor/plugins/particles_editor_plugin.cpp
index 10834b74ff..f4a9960087 100644
--- a/editor/plugins/particles_editor_plugin.cpp
+++ b/editor/plugins/particles_editor_plugin.cpp
@@ -153,15 +153,15 @@ void ParticlesEditor::_generate_aabb() {
EditorProgress ep("gen_aabb", TTR("Generating AABB"), int(time));
- Rect3 rect;
+ AABB rect;
while (running < time) {
uint64_t ticks = OS::get_singleton()->get_ticks_usec();
ep.step("Generating..", int(running), true);
OS::get_singleton()->delay_usec(1000);
- Rect3 capture = node->capture_aabb();
- if (rect == Rect3())
+ AABB capture = node->capture_aabb();
+ if (rect == AABB())
rect = capture;
else
rect.merge_with(capture);
@@ -247,7 +247,7 @@ void ParticlesEditor::_generate_emission_points() {
PoolVector<Face3>::Read r = geometry.read();
- Rect3 aabb;
+ AABB aabb;
for (int i = 0; i < gcount; i++) {
diff --git a/editor/plugins/path_2d_editor_plugin.cpp b/editor/plugins/path_2d_editor_plugin.cpp
index df10ac8929..2174f08e23 100644
--- a/editor/plugins/path_2d_editor_plugin.cpp
+++ b/editor/plugins/path_2d_editor_plugin.cpp
@@ -76,10 +76,7 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
Vector2 gpoint = mb->get_position();
- Vector2 cpoint =
- !mb->get_alt() ?
- canvas_item_editor->snap_point(xform.affine_inverse().xform(gpoint)) :
- node->get_global_transform().affine_inverse().xform(canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint)));
+ Vector2 cpoint = node->get_global_transform().affine_inverse().xform(canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(mb->get_position())));
real_t grab_threshold = EDITOR_DEF("editors/poly_editor/point_grab_radius", 8);
@@ -239,10 +236,7 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
// Handle point/control movement.
Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
Vector2 gpoint = mm->get_position();
- Vector2 cpoint =
- !mm->get_alt() ?
- canvas_item_editor->snap_point(xform.affine_inverse().xform(gpoint)) :
- node->get_global_transform().affine_inverse().xform(canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint)));
+ Vector2 cpoint = node->get_global_transform().affine_inverse().xform(canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(mm->get_position())));
Ref<Curve2D> curve = node->get_curve();
@@ -274,7 +268,8 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
return false;
}
-void Path2DEditor::_canvas_draw() {
+
+void Path2DEditor::forward_draw_over_canvas(Control *p_canvas) {
if (!node)
return;
@@ -329,16 +324,11 @@ void Path2DEditor::edit(Node *p_path2d) {
if (p_path2d) {
node = Object::cast_to<Path2D>(p_path2d);
- if (!canvas_item_editor->get_viewport_control()->is_connected("draw", this, "_canvas_draw"))
- canvas_item_editor->get_viewport_control()->connect("draw", this, "_canvas_draw");
if (!node->is_connected("visibility_changed", this, "_node_visibility_changed"))
node->connect("visibility_changed", this, "_node_visibility_changed");
} else {
- if (canvas_item_editor->get_viewport_control()->is_connected("draw", this, "_canvas_draw"))
- canvas_item_editor->get_viewport_control()->disconnect("draw", this, "_canvas_draw");
-
// node may have been deleted at this point
if (node && node->is_connected("visibility_changed", this, "_node_visibility_changed"))
node->disconnect("visibility_changed", this, "_node_visibility_changed");
@@ -349,7 +339,6 @@ void Path2DEditor::edit(Node *p_path2d) {
void Path2DEditor::_bind_methods() {
//ClassDB::bind_method(D_METHOD("_menu_option"),&Path2DEditor::_menu_option);
- ClassDB::bind_method(D_METHOD("_canvas_draw"), &Path2DEditor::_canvas_draw);
ClassDB::bind_method(D_METHOD("_node_visibility_changed"), &Path2DEditor::_node_visibility_changed);
ClassDB::bind_method(D_METHOD("_mode_selected"), &Path2DEditor::_mode_selected);
}
diff --git a/editor/plugins/path_2d_editor_plugin.h b/editor/plugins/path_2d_editor_plugin.h
index f0f5d4d637..516e48c471 100644
--- a/editor/plugins/path_2d_editor_plugin.h
+++ b/editor/plugins/path_2d_editor_plugin.h
@@ -84,7 +84,6 @@ class Path2DEditor : public HBoxContainer {
void _mode_selected(int p_mode);
- void _canvas_draw();
void _node_visibility_changed();
friend class Path2DEditorPlugin;
@@ -95,6 +94,7 @@ protected:
public:
bool forward_gui_input(const Ref<InputEvent> &p_event);
+ void forward_draw_over_canvas(Control *p_canvas);
void edit(Node *p_path2d);
Path2DEditor(EditorNode *p_editor);
};
@@ -107,7 +107,8 @@ class Path2DEditorPlugin : public EditorPlugin {
EditorNode *editor;
public:
- virtual bool forward_canvas_gui_input(const Transform2D &p_canvas_xform, const Ref<InputEvent> &p_event) { return path2d_editor->forward_gui_input(p_event); }
+ virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event) { return path2d_editor->forward_gui_input(p_event); }
+ virtual void forward_draw_over_canvas(Control *p_canvas) { return path2d_editor->forward_draw_over_canvas(p_canvas); }
virtual String get_name() const { return "Path2D"; }
bool has_main_screen() const { return false; }
diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp
index af2349983d..ebb5f57e99 100644
--- a/editor/plugins/polygon_2d_editor_plugin.cpp
+++ b/editor/plugins/polygon_2d_editor_plugin.cpp
@@ -35,15 +35,27 @@
#include "os/input.h"
#include "os/keyboard.h"
+Node2D *Polygon2DEditor::_get_node() const {
+
+ return node;
+}
+
+void Polygon2DEditor::_set_node(Node *p_polygon) {
+
+ node = Object::cast_to<Polygon2D>(p_polygon);
+}
+
+Vector2 Polygon2DEditor::_get_offset(int p_idx) const {
+
+ return node->get_offset();
+}
+
void Polygon2DEditor::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_READY: {
- button_create->set_icon(get_icon("Edit", "EditorIcons"));
- button_edit->set_icon(get_icon("MovePoint", "EditorIcons"));
- button_edit->set_pressed(true);
button_uv->set_icon(get_icon("Uv", "EditorIcons"));
uv_button[UV_MODE_EDIT_POINT]->set_icon(get_icon("ToolSelect", "EditorIcons"));
@@ -55,40 +67,17 @@ void Polygon2DEditor::_notification(int p_what) {
b_snap_enable->set_icon(get_icon("SnapGrid", "EditorIcons"));
uv_icon_zoom->set_texture(get_icon("Zoom", "EditorIcons"));
- get_tree()->connect("node_removed", this, "_node_removed");
-
} break;
case NOTIFICATION_PHYSICS_PROCESS: {
} break;
}
}
-void Polygon2DEditor::_node_removed(Node *p_node) {
-
- if (p_node == node) {
- edit(NULL);
- hide();
-
- canvas_item_editor->get_viewport_control()->update();
- }
-}
void Polygon2DEditor::_menu_option(int p_option) {
switch (p_option) {
- case MODE_CREATE: {
-
- mode = MODE_CREATE;
- button_create->set_pressed(true);
- button_edit->set_pressed(false);
- } break;
- case MODE_EDIT: {
-
- mode = MODE_EDIT;
- button_create->set_pressed(false);
- button_edit->set_pressed(true);
- } break;
case MODE_EDIT_UV: {
if (node->get_texture().is_null()) {
@@ -153,6 +142,9 @@ void Polygon2DEditor::_menu_option(int p_option) {
undo_redo->commit_action();
} break;
+ default: {
+ AbstractPolygon2DEditor::_menu_option(p_option);
+ } break;
}
}
@@ -185,289 +177,6 @@ void Polygon2DEditor::_set_snap_step_y(float p_val) {
uv_edit_draw->update();
}
-void Polygon2DEditor::_wip_close() {
-
- undo_redo->create_action(TTR("Create Poly"));
- undo_redo->add_undo_method(node, "set_polygon", node->get_polygon());
- undo_redo->add_do_method(node, "set_polygon", wip);
- undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
- undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
- undo_redo->commit_action();
- wip.clear();
- wip_active = false;
- mode = MODE_EDIT;
- button_edit->set_pressed(true);
- button_create->set_pressed(false);
- edited_point = -1;
-}
-
-bool Polygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
-
- if (node == NULL)
- return false;
-
- Ref<InputEventMouseButton> mb = p_event;
-
- if (mb.is_valid()) {
-
- Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
-
- Vector2 gpoint = mb->get_position();
- Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
- cpoint = canvas_item_editor->snap_point(cpoint);
- cpoint = node->get_global_transform().affine_inverse().xform(cpoint);
-
- Vector<Vector2> poly = Variant(node->get_polygon());
-
- //first check if a point is to be added (segment split)
- real_t grab_threshold = EDITOR_DEF("editors/poly_editor/point_grab_radius", 8);
-
- switch (mode) {
-
- case MODE_CREATE: {
-
- if (mb->get_button_index() == BUTTON_LEFT && mb->is_pressed()) {
-
- if (!wip_active) {
-
- wip.clear();
- wip.push_back(cpoint - node->get_offset());
- wip_active = true;
- edited_point_pos = cpoint;
- canvas_item_editor->get_viewport_control()->update();
- edited_point = 1;
- return true;
- } else {
-
- if (wip.size() > 1 && xform.xform(wip[0] + node->get_offset()).distance_to(gpoint) < grab_threshold) {
- //wip closed
- _wip_close();
-
- return true;
- } else {
-
- wip.push_back(cpoint - node->get_offset());
- edited_point = wip.size();
- canvas_item_editor->get_viewport_control()->update();
- return true;
-
- //add wip point
- }
- }
- } else if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed() && wip_active) {
- _wip_close();
- }
-
- } break;
-
- case MODE_EDIT: {
-
- if (mb->get_button_index() == BUTTON_LEFT) {
- if (mb->is_pressed()) {
-
- if (mb->get_control()) {
-
- if (poly.size() < 3) {
-
- undo_redo->create_action(TTR("Edit Poly"));
- undo_redo->add_undo_method(node, "set_polygon", poly);
- poly.push_back(cpoint);
- undo_redo->add_do_method(node, "set_polygon", poly);
- undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
- undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
- undo_redo->commit_action();
- return true;
- }
-
- //search edges
- int closest_idx = -1;
- Vector2 closest_pos;
- real_t closest_dist = 1e10;
- for (int i = 0; i < poly.size(); i++) {
-
- Vector2 points[2] = { xform.xform(poly[i] + node->get_offset()),
- xform.xform(poly[(i + 1) % poly.size()] + node->get_offset()) };
-
- Vector2 cp = Geometry::get_closest_point_to_segment_2d(gpoint, points);
- if (cp.distance_squared_to(points[0]) < CMP_EPSILON2 || cp.distance_squared_to(points[1]) < CMP_EPSILON2)
- continue; //not valid to reuse point
-
- real_t d = cp.distance_to(gpoint);
- if (d < closest_dist && d < grab_threshold) {
- closest_dist = d;
- closest_pos = cp;
- closest_idx = i;
- }
- }
-
- if (closest_idx >= 0) {
-
- pre_move_edit = poly;
- poly.insert(closest_idx + 1, xform.affine_inverse().xform(closest_pos) - node->get_offset());
- edited_point = closest_idx + 1;
- edited_point_pos = xform.affine_inverse().xform(closest_pos);
- node->set_polygon(Variant(poly));
- canvas_item_editor->get_viewport_control()->update();
- return true;
- }
- } else {
-
- //look for points to move
-
- int closest_idx = -1;
- Vector2 closest_pos;
- real_t closest_dist = 1e10;
- for (int i = 0; i < poly.size(); i++) {
-
- Vector2 cp = xform.xform(poly[i] + node->get_offset());
-
- real_t d = cp.distance_to(gpoint);
- if (d < closest_dist && d < grab_threshold) {
- closest_dist = d;
- closest_pos = cp;
- closest_idx = i;
- }
- }
-
- if (closest_idx >= 0) {
-
- pre_move_edit = poly;
- edited_point = closest_idx;
- edited_point_pos = xform.affine_inverse().xform(closest_pos);
- canvas_item_editor->get_viewport_control()->update();
- return true;
- }
- }
- } else {
-
- if (edited_point != -1) {
-
- //apply
-
- ERR_FAIL_INDEX_V(edited_point, poly.size(), false);
- poly[edited_point] = edited_point_pos - node->get_offset();
- undo_redo->create_action(TTR("Edit Poly"));
- undo_redo->add_do_method(node, "set_polygon", poly);
- undo_redo->add_undo_method(node, "set_polygon", pre_move_edit);
- undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
- undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
- undo_redo->commit_action();
-
- edited_point = -1;
- return true;
- }
- }
- } else if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed() && edited_point == -1) {
-
- int closest_idx = -1;
- Vector2 closest_pos;
- real_t closest_dist = 1e10;
- for (int i = 0; i < poly.size(); i++) {
-
- Vector2 cp = xform.xform(poly[i] + node->get_offset());
-
- real_t d = cp.distance_to(gpoint);
- if (d < closest_dist && d < grab_threshold) {
- closest_dist = d;
- closest_pos = cp;
- closest_idx = i;
- }
- }
-
- if (closest_idx >= 0) {
-
- undo_redo->create_action(TTR("Edit Poly (Remove Point)"));
- undo_redo->add_undo_method(node, "set_polygon", poly);
- poly.remove(closest_idx);
- undo_redo->add_do_method(node, "set_polygon", poly);
- undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
- undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
- undo_redo->commit_action();
- return true;
- }
- }
-
- } break;
- }
- }
-
- Ref<InputEventMouseMotion> mm = p_event;
-
- if (mm.is_valid()) {
-
- if (edited_point != -1 && (wip_active || (mm->get_button_mask() & BUTTON_MASK_LEFT))) {
-
- Vector2 gpoint = mm->get_position();
- Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
- cpoint = canvas_item_editor->snap_point(cpoint);
- edited_point_pos = node->get_global_transform().affine_inverse().xform(cpoint);
-
- if (!wip_active) {
-
- Vector<Vector2> poly = Variant(node->get_polygon());
- ERR_FAIL_INDEX_V(edited_point, poly.size(), false);
- poly[edited_point] = edited_point_pos - node->get_offset();
- node->set_polygon(Variant(poly));
- }
-
- canvas_item_editor->get_viewport_control()->update();
- }
- }
-
- return false;
-}
-void Polygon2DEditor::_canvas_draw() {
-
- if (!node)
- return;
-
- Control *vpc = canvas_item_editor->get_viewport_control();
-
- Vector<Vector2> poly;
-
- if (wip_active)
- poly = wip;
- else
- poly = Variant(node->get_polygon());
-
- Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
- Ref<Texture> handle = get_icon("EditorHandle", "EditorIcons");
-
- if (!wip_active && edited_point >= 0 && EDITOR_DEF("editors/poly_editor/show_previous_outline", true)) {
-
- const Color col = node->get_color().contrasted();
- const int n = pre_move_edit.size();
- for (int i = 0; i < n; i++) {
-
- Vector2 p, p2;
- p = pre_move_edit[i] + node->get_offset();
- p2 = pre_move_edit[(i + 1) % n] + node->get_offset();
-
- Vector2 point = xform.xform(p);
- Vector2 next_point = xform.xform(p2);
-
- vpc->draw_line(point, next_point, col, 2);
- }
- }
-
- for (int i = 0; i < poly.size(); i++) {
-
- Vector2 p, p2;
- p = i == edited_point ? edited_point_pos : (poly[i] + node->get_offset());
- if ((wip_active && i == poly.size() - 1) || (((i + 1) % poly.size()) == edited_point))
- p2 = edited_point_pos;
- else
- p2 = poly[(i + 1) % poly.size()] + node->get_offset();
-
- Vector2 point = xform.xform(p);
- Vector2 next_point = xform.xform(p2);
-
- Color col = Color(1, 0.3, 0.1, 0.8);
- vpc->draw_line(point, next_point, col, 2);
- vpc->draw_texture(handle, point - handle->get_size() * 0.5);
- }
-}
-
void Polygon2DEditor::_uv_mode(int p_mode) {
uv_mode = UVMode(p_mode);
@@ -630,6 +339,19 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) {
uv_edit_draw->update();
}
}
+
+ Ref<InputEventMagnifyGesture> magnify_gesture = p_input;
+ if (magnify_gesture.is_valid()) {
+
+ uv_zoom->set_value(uv_zoom->get_value() * magnify_gesture->get_factor());
+ }
+
+ Ref<InputEventPanGesture> pan_gesture = p_input;
+ if (pan_gesture.is_valid()) {
+
+ uv_hscroll->set_value(uv_hscroll->get_value() + uv_hscroll->get_page() * pan_gesture->get_delta().x / 8);
+ uv_vscroll->set_value(uv_vscroll->get_value() + uv_vscroll->get_page() * pan_gesture->get_delta().y / 8);
+ }
}
void Polygon2DEditor::_uv_scroll_changed(float) {
@@ -714,44 +436,12 @@ void Polygon2DEditor::_uv_draw() {
updating_uv_scroll = false;
}
-void Polygon2DEditor::edit(Node *p_collision_polygon) {
-
- if (!canvas_item_editor) {
- canvas_item_editor = CanvasItemEditor::get_singleton();
- }
-
- if (p_collision_polygon) {
-
- node = Object::cast_to<Polygon2D>(p_collision_polygon);
- //Enable the pencil tool if the polygon is empty
- if (node->get_polygon().size() == 0) {
- _menu_option(MODE_CREATE);
- }
- if (!canvas_item_editor->get_viewport_control()->is_connected("draw", this, "_canvas_draw"))
- canvas_item_editor->get_viewport_control()->connect("draw", this, "_canvas_draw");
-
- wip.clear();
- wip_active = false;
- edited_point = -1;
-
- } else {
-
- node = NULL;
-
- if (canvas_item_editor->get_viewport_control()->is_connected("draw", this, "_canvas_draw"))
- canvas_item_editor->get_viewport_control()->disconnect("draw", this, "_canvas_draw");
- }
-}
-
void Polygon2DEditor::_bind_methods() {
- ClassDB::bind_method(D_METHOD("_menu_option"), &Polygon2DEditor::_menu_option);
- ClassDB::bind_method(D_METHOD("_canvas_draw"), &Polygon2DEditor::_canvas_draw);
ClassDB::bind_method(D_METHOD("_uv_mode"), &Polygon2DEditor::_uv_mode);
ClassDB::bind_method(D_METHOD("_uv_draw"), &Polygon2DEditor::_uv_draw);
ClassDB::bind_method(D_METHOD("_uv_input"), &Polygon2DEditor::_uv_input);
ClassDB::bind_method(D_METHOD("_uv_scroll_changed"), &Polygon2DEditor::_uv_scroll_changed);
- ClassDB::bind_method(D_METHOD("_node_removed"), &Polygon2DEditor::_node_removed);
ClassDB::bind_method(D_METHOD("_set_use_snap"), &Polygon2DEditor::_set_use_snap);
ClassDB::bind_method(D_METHOD("_set_show_grid"), &Polygon2DEditor::_set_show_grid);
ClassDB::bind_method(D_METHOD("_set_snap_off_x"), &Polygon2DEditor::_set_snap_off_x);
@@ -760,48 +450,26 @@ void Polygon2DEditor::_bind_methods() {
ClassDB::bind_method(D_METHOD("_set_snap_step_y"), &Polygon2DEditor::_set_snap_step_y);
}
-inline float _snap_scalar(float p_offset, float p_step, float p_target) {
- return p_step != 0 ? Math::stepify(p_target - p_offset, p_step) + p_offset : p_target;
-}
-
Vector2 Polygon2DEditor::snap_point(Vector2 p_target) const {
if (use_snap) {
- p_target.x = _snap_scalar(snap_offset.x * uv_draw_zoom - uv_draw_ofs.x, snap_step.x * uv_draw_zoom, p_target.x);
- p_target.y = _snap_scalar(snap_offset.y * uv_draw_zoom - uv_draw_ofs.y, snap_step.y * uv_draw_zoom, p_target.y);
+ p_target.x = Math::snap_scalar(snap_offset.x * uv_draw_zoom - uv_draw_ofs.x, snap_step.x * uv_draw_zoom, p_target.x);
+ p_target.y = Math::snap_scalar(snap_offset.y * uv_draw_zoom - uv_draw_ofs.y, snap_step.y * uv_draw_zoom, p_target.y);
}
return p_target;
}
-Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) {
-
- node = NULL;
- canvas_item_editor = NULL;
- editor = p_editor;
- undo_redo = editor->get_undo_redo();
+Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor)
+ : AbstractPolygon2DEditor(p_editor) {
snap_step = Vector2(10, 10);
use_snap = false;
snap_show_grid = false;
- add_child(memnew(VSeparator));
- button_create = memnew(ToolButton);
- add_child(button_create);
- button_create->connect("pressed", this, "_menu_option", varray(MODE_CREATE));
- button_create->set_toggle_mode(true);
-
- button_edit = memnew(ToolButton);
- add_child(button_edit);
- button_edit->connect("pressed", this, "_menu_option", varray(MODE_EDIT));
- button_edit->set_toggle_mode(true);
-
button_uv = memnew(ToolButton);
add_child(button_uv);
button_uv->connect("pressed", this, "_menu_option", varray(MODE_EDIT_UV));
- mode = MODE_EDIT;
- wip_active = false;
-
uv_mode = UV_MODE_EDIT_POINT;
uv_edit = memnew(AcceptDialog);
add_child(uv_edit);
@@ -941,35 +609,6 @@ Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) {
uv_edit_draw->set_clip_contents(true);
}
-void Polygon2DEditorPlugin::edit(Object *p_object) {
-
- collision_polygon_editor->edit(Object::cast_to<Node>(p_object));
-}
-
-bool Polygon2DEditorPlugin::handles(Object *p_object) const {
-
- return p_object->is_class("Polygon2D");
-}
-
-void Polygon2DEditorPlugin::make_visible(bool p_visible) {
-
- if (p_visible) {
- collision_polygon_editor->show();
- } else {
-
- collision_polygon_editor->hide();
- collision_polygon_editor->edit(NULL);
- }
-}
-
-Polygon2DEditorPlugin::Polygon2DEditorPlugin(EditorNode *p_node) {
-
- editor = p_node;
- collision_polygon_editor = memnew(Polygon2DEditor(p_node));
- CanvasItemEditor::get_singleton()->add_control_to_menu_panel(collision_polygon_editor);
-
- collision_polygon_editor->hide();
-}
-
-Polygon2DEditorPlugin::~Polygon2DEditorPlugin() {
+Polygon2DEditorPlugin::Polygon2DEditorPlugin(EditorNode *p_node)
+ : AbstractPolygon2DEditorPlugin(p_node, memnew(Polygon2DEditor(p_node)), "Polygon2D") {
}
diff --git a/editor/plugins/polygon_2d_editor_plugin.h b/editor/plugins/polygon_2d_editor_plugin.h
index f9d6a6b4b6..90da3e61c1 100644
--- a/editor/plugins/polygon_2d_editor_plugin.h
+++ b/editor/plugins/polygon_2d_editor_plugin.h
@@ -30,26 +30,18 @@
#ifndef POLYGON_2D_EDITOR_PLUGIN_H
#define POLYGON_2D_EDITOR_PLUGIN_H
-#include "editor/editor_node.h"
-#include "editor/editor_plugin.h"
-#include "scene/2d/polygon_2d.h"
-#include "scene/gui/tool_button.h"
+#include "editor/plugins/abstract_polygon_2d_editor.h"
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
-class CanvasItemEditor;
+class Polygon2DEditor : public AbstractPolygon2DEditor {
-class Polygon2DEditor : public HBoxContainer {
+ GDCLASS(Polygon2DEditor, AbstractPolygon2DEditor);
- GDCLASS(Polygon2DEditor, HBoxContainer);
-
- UndoRedo *undo_redo;
enum Mode {
- MODE_CREATE,
- MODE_EDIT,
- MODE_EDIT_UV,
+ MODE_EDIT_UV = MODE_CONT,
UVEDIT_POLYGON_TO_UV,
UVEDIT_UV_TO_POLYGON,
UVEDIT_UV_CLEAR
@@ -64,7 +56,7 @@ class Polygon2DEditor : public HBoxContainer {
UV_MODE_MAX
};
- Mode mode;
+ Polygon2D *node;
UVMode uv_mode;
AcceptDialog *uv_edit;
@@ -90,34 +82,19 @@ class Polygon2DEditor : public HBoxContainer {
AcceptDialog *error;
- ToolButton *button_create;
- ToolButton *button_edit;
ToolButton *button_uv;
- CanvasItemEditor *canvas_item_editor;
- EditorNode *editor;
- Panel *panel;
- Polygon2D *node;
- MenuButton *options;
-
- int edited_point;
- Vector2 edited_point_pos;
- Vector<Vector2> pre_move_edit;
- Vector<Vector2> wip;
- bool wip_active;
-
bool use_snap;
bool snap_show_grid;
Vector2 snap_offset;
Vector2 snap_step;
+ virtual void _menu_option(int p_option);
+
void _uv_scroll_changed(float);
void _uv_input(const Ref<InputEvent> &p_input);
void _uv_draw();
void _uv_mode(int p_mode);
- void _wip_close();
- void _canvas_draw();
- void _menu_option(int p_option);
void _set_use_snap(bool p_use);
void _set_show_grid(bool p_show);
@@ -127,36 +104,26 @@ class Polygon2DEditor : public HBoxContainer {
void _set_snap_step_y(float p_val);
protected:
+ virtual Node2D *_get_node() const;
+ virtual void _set_node(Node *p_polygon);
+
+ virtual Vector2 _get_offset(int p_idx) const;
+
void _notification(int p_what);
- void _node_removed(Node *p_node);
static void _bind_methods();
Vector2 snap_point(Vector2 p_target) const;
public:
- bool forward_gui_input(const Ref<InputEvent> &p_event);
- void edit(Node *p_collision_polygon);
Polygon2DEditor(EditorNode *p_editor);
};
-class Polygon2DEditorPlugin : public EditorPlugin {
-
- GDCLASS(Polygon2DEditorPlugin, EditorPlugin);
+class Polygon2DEditorPlugin : public AbstractPolygon2DEditorPlugin {
- Polygon2DEditor *collision_polygon_editor;
- EditorNode *editor;
+ GDCLASS(Polygon2DEditorPlugin, AbstractPolygon2DEditorPlugin);
public:
- virtual bool forward_canvas_gui_input(const Transform2D &p_canvas_xform, const Ref<InputEvent> &p_event) { return collision_polygon_editor->forward_gui_input(p_event); }
-
- virtual String get_name() const { return "Polygon2D"; }
- bool has_main_screen() const { return false; }
- virtual void edit(Object *p_object);
- virtual bool handles(Object *p_object) const;
- virtual void make_visible(bool p_visible);
-
Polygon2DEditorPlugin(EditorNode *p_node);
- ~Polygon2DEditorPlugin();
};
#endif // POLYGON_2D_EDITOR_PLUGIN_H
diff --git a/editor/plugins/resource_preloader_editor_plugin.cpp b/editor/plugins/resource_preloader_editor_plugin.cpp
index d421b3798b..3210af1433 100644
--- a/editor/plugins/resource_preloader_editor_plugin.cpp
+++ b/editor/plugins/resource_preloader_editor_plugin.cpp
@@ -43,7 +43,7 @@ void ResourcePreloaderEditor::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE) {
load->set_icon(get_icon("Folder", "EditorIcons"));
- _delete->set_icon(get_icon("Del", "EditorIcons"));
+ _delete->set_icon(get_icon("Remove", "EditorIcons"));
}
if (p_what == NOTIFICATION_READY) {
diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp
index 5e66488afb..3c2d52c128 100644
--- a/editor/plugins/script_editor_plugin.cpp
+++ b/editor/plugins/script_editor_plugin.cpp
@@ -467,6 +467,8 @@ void ScriptEditor::_update_recent_scripts() {
recent_scripts->add_separator();
recent_scripts->add_shortcut(ED_SHORTCUT("script_editor/clear_recent", TTR("Clear Recent Files")));
+
+ recent_scripts->set_as_minsize();
}
void ScriptEditor::_open_recent_script(int p_idx) {
@@ -474,7 +476,7 @@ void ScriptEditor::_open_recent_script(int p_idx) {
// clear button
if (p_idx == recent_scripts->get_item_count() - 1) {
previous_scripts.clear();
- _update_recent_scripts();
+ call_deferred("_update_recent_scripts");
return;
}
@@ -584,6 +586,32 @@ void ScriptEditor::_close_docs_tab() {
}
}
+void ScriptEditor::_close_other_tabs() {
+
+ int child_count = tab_container->get_child_count();
+ int current_idx = tab_container->get_current_tab();
+ for (int i = child_count - 1; i >= 0; i--) {
+
+ if (i == current_idx) {
+ continue;
+ }
+
+ tab_container->set_current_tab(i);
+ ScriptEditorBase *se = Object::cast_to<ScriptEditorBase>(tab_container->get_child(i));
+
+ if (se) {
+
+ // Maybe there are unsaved changes
+ if (se->is_unsaved()) {
+ _ask_close_current_unsaved_tab(se);
+ continue;
+ }
+ }
+
+ _close_current_tab();
+ }
+}
+
void ScriptEditor::_close_all_tabs() {
int child_count = tab_container->get_child_count();
@@ -853,7 +881,7 @@ void ScriptEditor::_menu_option(int p_option) {
file_dialog_option = FILE_SAVE_THEME_AS;
file_dialog->clear_filters();
file_dialog->add_filter("*.tet");
- file_dialog->set_current_path(EditorSettings::get_singleton()->get_settings_path() + "/text_editor_themes/" + EditorSettings::get_singleton()->get("text_editor/theme/color_theme"));
+ file_dialog->set_current_path(EditorSettings::get_singleton()->get_text_editor_themes_dir().plus_file(EditorSettings::get_singleton()->get("text_editor/theme/color_theme")));
file_dialog->popup_centered_ratio();
file_dialog->set_title(TTR("Save Theme As.."));
} break;
@@ -863,20 +891,7 @@ void ScriptEditor::_menu_option(int p_option) {
} break;
case SEARCH_CLASSES: {
- String current;
-
- if (tab_container->get_tab_count() > 0) {
- EditorHelp *eh = Object::cast_to<EditorHelp>(tab_container->get_child(tab_container->get_current_tab()));
- if (eh) {
- current = eh->get_class();
- }
- }
-
help_index->popup();
-
- if (current != "") {
- help_index->call_deferred("select_class", current);
- }
} break;
case SEARCH_WEBSITE: {
@@ -888,8 +903,13 @@ void ScriptEditor::_menu_option(int p_option) {
_history_forward();
} break;
case WINDOW_PREV: {
+
_history_back();
} break;
+ case WINDOW_SORT: {
+ _sort_list_on_update = true;
+ _update_script_names();
+ } break;
case DEBUG_SHOW: {
if (debugger) {
bool visible = debug_menu->get_popup()->is_item_checked(debug_menu->get_popup()->get_item_index(DEBUG_SHOW));
@@ -924,10 +944,6 @@ void ScriptEditor::_menu_option(int p_option) {
if (current) {
switch (p_option) {
- case FILE_NEW: {
- script_create_dialog->config("Node", ".gd");
- script_create_dialog->popup_centered(Size2(300, 300) * EDSCALE);
- } break;
case FILE_SAVE: {
if (_test_script_times_on_disk())
@@ -1013,6 +1029,9 @@ void ScriptEditor::_menu_option(int p_option) {
case CLOSE_DOCS: {
_close_docs_tab();
} break;
+ case CLOSE_OTHER_TABS: {
+ _close_other_tabs();
+ } break;
case CLOSE_ALL: {
_close_all_tabs();
} break;
@@ -1039,26 +1058,22 @@ void ScriptEditor::_menu_option(int p_option) {
debugger->debug_continue();
} break;
- case WINDOW_MOVE_LEFT: {
+ case WINDOW_MOVE_UP: {
if (tab_container->get_current_tab() > 0) {
- tab_container->call_deferred("set_current_tab", tab_container->get_current_tab() - 1);
- script_list->call_deferred("select", tab_container->get_current_tab() - 1);
tab_container->move_child(current, tab_container->get_current_tab() - 1);
+ tab_container->set_current_tab(tab_container->get_current_tab() - 1);
_update_script_names();
}
} break;
- case WINDOW_MOVE_RIGHT: {
+ case WINDOW_MOVE_DOWN: {
if (tab_container->get_current_tab() < tab_container->get_child_count() - 1) {
- tab_container->call_deferred("set_current_tab", tab_container->get_current_tab() + 1);
- script_list->call_deferred("select", tab_container->get_current_tab() + 1);
tab_container->move_child(current, tab_container->get_current_tab() + 1);
+ tab_container->set_current_tab(tab_container->get_current_tab() + 1);
_update_script_names();
}
-
} break;
-
default: {
if (p_option >= WINDOW_SELECT_BASE) {
@@ -1075,6 +1090,11 @@ void ScriptEditor::_menu_option(int p_option) {
switch (p_option) {
+ case SEARCH_CLASSES: {
+
+ help_index->popup();
+ help_index->call_deferred("select_class", help->get_class());
+ } break;
case HELP_SEARCH_FIND: {
help->popup_search();
} break;
@@ -1087,9 +1107,28 @@ void ScriptEditor::_menu_option(int p_option) {
case CLOSE_DOCS: {
_close_docs_tab();
} break;
+ case CLOSE_OTHER_TABS: {
+ _close_other_tabs();
+ } break;
case CLOSE_ALL: {
_close_all_tabs();
} break;
+ case WINDOW_MOVE_UP: {
+
+ if (tab_container->get_current_tab() > 0) {
+ tab_container->move_child(help, tab_container->get_current_tab() - 1);
+ tab_container->set_current_tab(tab_container->get_current_tab() - 1);
+ _update_script_names();
+ }
+ } break;
+ case WINDOW_MOVE_DOWN: {
+
+ if (tab_container->get_current_tab() < tab_container->get_child_count() - 1) {
+ tab_container->move_child(help, tab_container->get_current_tab() + 1);
+ tab_container->set_current_tab(tab_container->get_current_tab() + 1);
+ _update_script_names();
+ }
+ } break;
}
}
}
@@ -1112,6 +1151,7 @@ void ScriptEditor::_notification(int p_what) {
editor->connect("script_add_function_request", this, "_add_callback");
editor->connect("resource_saved", this, "_res_saved_callback");
script_list->connect("item_selected", this, "_script_selected");
+
members_overview->connect("item_selected", this, "_members_overview_selected");
help_overview->connect("item_selected", this, "_help_overview_selected");
script_split->connect("dragged", this, "_script_split_dragged");
@@ -1167,6 +1207,8 @@ void ScriptEditor::_notification(int p_what) {
script_forward->set_icon(get_icon("Forward", "EditorIcons"));
script_back->set_icon(get_icon("Back", "EditorIcons"));
+
+ recent_scripts->set_as_minsize();
} break;
default:
@@ -1278,7 +1320,11 @@ void ScriptEditor::_members_overview_selected(int p_idx) {
if (!se) {
return;
}
- se->goto_line(members_overview->get_item_metadata(p_idx));
+ Dictionary state;
+ state["scroll_position"] = members_overview->get_item_metadata(p_idx);
+ state["column"] = 0;
+ state["row"] = members_overview->get_item_metadata(p_idx);
+ se->set_edit_state(state);
se->ensure_focus();
}
@@ -1353,6 +1399,7 @@ struct _ScriptEditorItemData {
String tooltip;
bool used;
int category;
+ Node *ref;
bool operator<(const _ScriptEditorItemData &id) const {
@@ -1403,8 +1450,10 @@ void ScriptEditor::_update_members_overview() {
void ScriptEditor::_update_help_overview_visibility() {
int selected = tab_container->get_current_tab();
- if (selected < 0 || selected >= tab_container->get_child_count())
+ if (selected < 0 || selected >= tab_container->get_child_count()) {
+ help_overview->set_visible(false);
return;
+ }
Node *current = tab_container->get_child(tab_container->get_current_tab());
EditorHelp *se = Object::cast_to<EditorHelp>(current);
@@ -1421,6 +1470,7 @@ void ScriptEditor::_update_help_overview_visibility() {
}
void ScriptEditor::_update_help_overview() {
+ help_overview->clear();
int selected = tab_container->get_current_tab();
if (selected < 0 || selected >= tab_container->get_child_count())
@@ -1432,8 +1482,6 @@ void ScriptEditor::_update_help_overview() {
return;
}
- help_overview->clear();
-
Vector<Pair<String, int> > sections = se->get_sections();
for (int i = 0; i < sections.size(); i++) {
help_overview->add_item(sections[i].first);
@@ -1441,9 +1489,6 @@ void ScriptEditor::_update_help_overview() {
}
}
-void _help_overview_selected(int p_idx) {
-}
-
void ScriptEditor::_update_script_colors() {
bool script_temperature_enabled = EditorSettings::get_singleton()->get("text_editor/open_scripts/script_temperature_enabled");
@@ -1520,6 +1565,7 @@ void ScriptEditor::_update_script_names() {
sd.index = i;
sd.used = used.has(se->get_edited_script());
sd.category = 0;
+ sd.ref = se;
switch (sort_by) {
case SORT_BY_NAME: {
@@ -1559,16 +1605,38 @@ void ScriptEditor::_update_script_names() {
_ScriptEditorItemData sd;
sd.icon = icon;
sd.name = name;
- sd.sort_key = name;
+ sd.sort_key = name.to_lower();
sd.tooltip = tooltip;
sd.index = i;
sd.used = false;
sd.category = split_script_help ? 1 : 0;
+ sd.ref = eh;
+
sedata.push_back(sd);
}
}
- sedata.sort();
+ if (_sort_list_on_update && !sedata.empty()) {
+ sedata.sort();
+
+ // change actual order of tab_container so that the order can be rearranged by user
+ int cur_tab = tab_container->get_current_tab();
+ int prev_tab = tab_container->get_previous_tab();
+ int new_cur_tab = -1;
+ int new_prev_tab = -1;
+ for (int i = 0; i < sedata.size(); i++) {
+ tab_container->move_child(sedata[i].ref, i);
+ if (new_prev_tab == -1 && sedata[i].index == prev_tab) {
+ new_prev_tab = i;
+ }
+ if (new_cur_tab == -1 && sedata[i].index == cur_tab) {
+ new_cur_tab = i;
+ }
+ }
+ tab_container->call_deferred("set_current_tab", new_prev_tab);
+ tab_container->call_deferred("set_current_tab", new_cur_tab);
+ _sort_list_on_update = false;
+ }
for (int i = 0; i < sedata.size(); i++) {
@@ -1589,6 +1657,8 @@ void ScriptEditor::_update_script_names() {
_update_members_overview();
_update_help_overview();
+ _update_members_overview_visibility();
+ _update_help_overview_visibility();
_update_script_colors();
}
@@ -1895,8 +1965,171 @@ void ScriptEditor::_script_split_dragged(float) {
_save_layout();
}
+Variant ScriptEditor::get_drag_data_fw(const Point2 &p_point, Control *p_from) {
+
+ // return Variant(); // return this if drag disabled
+
+ Node *cur_node = tab_container->get_child(tab_container->get_current_tab());
+
+ HBoxContainer *drag_preview = memnew(HBoxContainer);
+ String preview_name = "";
+ Ref<Texture> preview_icon;
+
+ ScriptEditorBase *se = Object::cast_to<ScriptEditorBase>(cur_node);
+ if (se) {
+ preview_name = se->get_name();
+ preview_icon = se->get_icon();
+ }
+ EditorHelp *eh = Object::cast_to<EditorHelp>(cur_node);
+ if (eh) {
+ preview_name = eh->get_class();
+ preview_icon = get_icon("Help", "EditorIcons");
+ }
+
+ if (!preview_icon.is_null()) {
+ TextureRect *tf = memnew(TextureRect);
+ tf->set_texture(preview_icon);
+ drag_preview->add_child(tf);
+ }
+ Label *label = memnew(Label(preview_name));
+ drag_preview->add_child(label);
+ set_drag_preview(drag_preview);
+
+ Dictionary drag_data;
+ drag_data["type"] = "script_list_element"; // using a custom type because node caused problems when dragging to scene tree
+ drag_data["script_list_element"] = cur_node;
+
+ return drag_data;
+}
+
+bool ScriptEditor::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const {
+
+ Dictionary d = p_data;
+ if (!d.has("type"))
+ return false;
+
+ if (String(d["type"]) == "script_list_element") {
+
+ Node *node = d["script_list_element"];
+
+ ScriptEditorBase *se = Object::cast_to<ScriptEditorBase>(node);
+ if (se) {
+ return true;
+ }
+ EditorHelp *eh = Object::cast_to<EditorHelp>(node);
+ if (eh) {
+ return true;
+ }
+ }
+
+ if (String(d["type"]) == "nodes") {
+
+ Array nodes = d["nodes"];
+ if (nodes.size() == 0)
+ return false;
+ Node *node = get_node((nodes[0]));
+
+ ScriptEditorBase *se = Object::cast_to<ScriptEditorBase>(node);
+ if (se) {
+ return true;
+ }
+ EditorHelp *eh = Object::cast_to<EditorHelp>(node);
+ if (eh) {
+ return true;
+ }
+ }
+
+ if (String(d["type"]) == "files") {
+
+ Vector<String> files = d["files"];
+
+ if (files.size() == 0)
+ return false; //weird
+
+ for (int i = 0; i < files.size(); i++) {
+ String file = files[i];
+ if (file == "" || !FileAccess::exists(file))
+ continue;
+ Ref<Script> scr = ResourceLoader::load(file);
+ if (scr.is_valid()) {
+ return true;
+ }
+ }
+ return true;
+ }
+
+ return false;
+}
+
+void ScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) {
+
+ if (!can_drop_data_fw(p_point, p_data, p_from))
+ return;
+
+ Dictionary d = p_data;
+ if (!d.has("type"))
+ return;
+
+ if (String(d["type"]) == "script_list_element") {
+
+ Node *node = d["script_list_element"];
+
+ ScriptEditorBase *se = Object::cast_to<ScriptEditorBase>(node);
+ EditorHelp *eh = Object::cast_to<EditorHelp>(node);
+ if (se || eh) {
+ int new_index = script_list->get_item_at_position(p_point);
+ tab_container->move_child(node, new_index);
+ tab_container->set_current_tab(new_index);
+ _update_script_names();
+ }
+ }
+
+ if (String(d["type"]) == "nodes") {
+
+ Array nodes = d["nodes"];
+ if (nodes.size() == 0)
+ return;
+ Node *node = get_node(nodes[0]);
+
+ ScriptEditorBase *se = Object::cast_to<ScriptEditorBase>(node);
+ EditorHelp *eh = Object::cast_to<EditorHelp>(node);
+ if (se || eh) {
+ int new_index = script_list->get_item_at_position(p_point);
+ tab_container->move_child(node, new_index);
+ tab_container->set_current_tab(new_index);
+ _update_script_names();
+ }
+ }
+
+ if (String(d["type"]) == "files") {
+
+ Vector<String> files = d["files"];
+
+ int new_index = script_list->get_item_at_position(p_point);
+ int num_tabs_before = tab_container->get_child_count();
+ for (int i = 0; i < files.size(); i++) {
+ String file = files[i];
+ if (file == "" || !FileAccess::exists(file))
+ continue;
+ Ref<Script> scr = ResourceLoader::load(file);
+ if (scr.is_valid()) {
+ edit(scr);
+ if (tab_container->get_child_count() > num_tabs_before) {
+ tab_container->move_child(tab_container->get_child(tab_container->get_child_count() - 1), new_index);
+ num_tabs_before = tab_container->get_child_count();
+ } else {
+ tab_container->move_child(tab_container->get_child(tab_container->get_current_tab()), new_index);
+ }
+ }
+ }
+ tab_container->set_current_tab(new_index);
+ _update_script_names();
+ }
+}
+
void ScriptEditor::_unhandled_input(const Ref<InputEvent> &p_event) {
- if (p_event->is_pressed() || !is_visible_in_tree()) return;
+ if (!is_visible_in_tree() || !p_event->is_pressed() || p_event->is_echo())
+ return;
if (ED_IS_SHORTCUT("script_editor/next_script", p_event)) {
int next_tab = script_list->get_current() + 1;
next_tab %= script_list->get_item_count();
@@ -1909,6 +2142,64 @@ void ScriptEditor::_unhandled_input(const Ref<InputEvent> &p_event) {
_go_to_tab(script_list->get_item_metadata(next_tab));
_update_script_names();
}
+ if (ED_IS_SHORTCUT("script_editor/window_move_up", p_event)) {
+ _menu_option(WINDOW_MOVE_UP);
+ }
+ if (ED_IS_SHORTCUT("script_editor/window_move_down", p_event)) {
+ _menu_option(WINDOW_MOVE_DOWN);
+ }
+}
+
+void ScriptEditor::_script_list_gui_input(const Ref<InputEvent> &ev) {
+
+ Ref<InputEventMouseButton> mb = ev;
+ if (mb.is_valid() && mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed()) {
+
+ _make_script_list_context_menu();
+ }
+}
+
+void ScriptEditor::_make_script_list_context_menu() {
+
+ context_menu->clear();
+
+ int selected = tab_container->get_current_tab();
+ if (selected < 0 || selected >= tab_container->get_child_count())
+ return;
+
+ ScriptEditorBase *se = Object::cast_to<ScriptEditorBase>(tab_container->get_child(selected));
+ if (se) {
+ context_menu->add_shortcut(ED_GET_SHORTCUT("script_editor/save"), FILE_SAVE);
+ context_menu->add_shortcut(ED_GET_SHORTCUT("script_editor/save_as"), FILE_SAVE_AS);
+ context_menu->add_shortcut(ED_GET_SHORTCUT("script_editor/close_file"), FILE_CLOSE);
+ context_menu->add_shortcut(ED_GET_SHORTCUT("script_editor/close_all"), CLOSE_ALL);
+ context_menu->add_shortcut(ED_GET_SHORTCUT("script_editor/close_other_tabs"), CLOSE_OTHER_TABS);
+ context_menu->add_separator();
+ context_menu->add_shortcut(ED_GET_SHORTCUT("script_editor/reload_script_soft"), FILE_TOOL_RELOAD_SOFT);
+
+ Ref<Script> scr = se->get_edited_script();
+ if (!scr.is_null() && scr->is_tool()) {
+ context_menu->add_separator();
+ context_menu->add_shortcut(ED_GET_SHORTCUT("script_editor/run_file"), FILE_RUN);
+ }
+ } else {
+ context_menu->add_shortcut(ED_GET_SHORTCUT("script_editor/close_file"), FILE_CLOSE);
+ }
+
+ EditorHelp *eh = Object::cast_to<EditorHelp>(tab_container->get_child(selected));
+ if (eh) {
+ // nothing
+ }
+
+ context_menu->add_separator();
+ context_menu->add_shortcut(ED_GET_SHORTCUT("script_editor/window_move_up"), WINDOW_MOVE_UP);
+ context_menu->add_shortcut(ED_GET_SHORTCUT("script_editor/window_move_down"), WINDOW_MOVE_DOWN);
+ context_menu->add_shortcut(ED_GET_SHORTCUT("script_editor/window_sort"), WINDOW_SORT);
+ context_menu->add_shortcut(ED_GET_SHORTCUT("script_editor/toggle_scripts_panel"), TOGGLE_SCRIPTS_PANEL);
+
+ context_menu->set_position(get_global_transform().xform(get_local_mouse_position()));
+ context_menu->set_size(Vector2(1, 1));
+ context_menu->popup();
}
void ScriptEditor::set_window_layout(Ref<ConfigFile> p_layout) {
@@ -2202,6 +2493,7 @@ void ScriptEditor::_bind_methods() {
ClassDB::bind_method("_close_discard_current_tab", &ScriptEditor::_close_discard_current_tab);
ClassDB::bind_method("_close_docs_tab", &ScriptEditor::_close_docs_tab);
ClassDB::bind_method("_close_all_tabs", &ScriptEditor::_close_all_tabs);
+ ClassDB::bind_method("_close_other_tabs", &ScriptEditor::_close_other_tabs);
ClassDB::bind_method("_open_recent_script", &ScriptEditor::_open_recent_script);
ClassDB::bind_method("_editor_play", &ScriptEditor::_editor_play);
ClassDB::bind_method("_editor_pause", &ScriptEditor::_editor_pause);
@@ -2235,7 +2527,13 @@ void ScriptEditor::_bind_methods() {
ClassDB::bind_method("_history_back", &ScriptEditor::_history_back);
ClassDB::bind_method("_live_auto_reload_running_scripts", &ScriptEditor::_live_auto_reload_running_scripts);
ClassDB::bind_method("_unhandled_input", &ScriptEditor::_unhandled_input);
+ ClassDB::bind_method("_script_list_gui_input", &ScriptEditor::_script_list_gui_input);
ClassDB::bind_method("_script_changed", &ScriptEditor::_script_changed);
+ ClassDB::bind_method("_update_recent_scripts", &ScriptEditor::_update_recent_scripts);
+
+ ClassDB::bind_method(D_METHOD("get_drag_data_fw"), &ScriptEditor::get_drag_data_fw);
+ ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &ScriptEditor::can_drop_data_fw);
+ ClassDB::bind_method(D_METHOD("drop_data_fw"), &ScriptEditor::drop_data_fw);
ClassDB::bind_method(D_METHOD("get_current_script"), &ScriptEditor::_get_current_script);
ClassDB::bind_method(D_METHOD("get_open_scripts"), &ScriptEditor::_get_open_scripts);
@@ -2277,6 +2575,14 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) {
script_list->set_v_size_flags(SIZE_EXPAND_FILL);
script_split->set_split_offset(140);
//list_split->set_split_offset(500);
+ _sort_list_on_update = true;
+ script_list->connect("gui_input", this, "_script_list_gui_input");
+ script_list->set_allow_rmb_select(true);
+ script_list->set_drag_forwarding(this);
+
+ context_menu = memnew(PopupMenu);
+ add_child(context_menu);
+ context_menu->connect("id_pressed", this, "_menu_option");
members_overview = memnew(ItemList);
list_split->add_child(members_overview);
@@ -2294,8 +2600,11 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) {
tab_container->set_h_size_flags(SIZE_EXPAND_FILL);
- ED_SHORTCUT("script_editor/next_script", TTR("Next script"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_GREATER);
- ED_SHORTCUT("script_editor/prev_script", TTR("Previous script"), KEY_MASK_CMD | KEY_LESS);
+ ED_SHORTCUT("script_editor/window_sort", TTR("Sort"));
+ ED_SHORTCUT("script_editor/window_move_up", TTR("Move Up"), KEY_MASK_SHIFT | KEY_MASK_ALT | KEY_UP);
+ ED_SHORTCUT("script_editor/window_move_down", TTR("Move Down"), KEY_MASK_SHIFT | KEY_MASK_ALT | KEY_DOWN);
+ ED_SHORTCUT("script_editor/next_script", TTR("Next script"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_PERIOD); // these should be KEY_GREATER and KEY_LESS but those don't work
+ ED_SHORTCUT("script_editor/prev_script", TTR("Previous script"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_COLON);
set_process_unhandled_input(true);
file_menu = memnew(MenuButton);
@@ -2330,6 +2639,7 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) {
file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/close_docs", TTR("Close Docs")), CLOSE_DOCS);
file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/close_file", TTR("Close"), KEY_MASK_CMD | KEY_W), FILE_CLOSE);
file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/close_all", TTR("Close All")), CLOSE_ALL);
+ file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/close_other_tabs", TTR("Close Other Tabs")), CLOSE_OTHER_TABS);
file_menu->get_popup()->add_separator();
file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/run_file", TTR("Run"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_X), FILE_RUN);
file_menu->get_popup()->add_separator();
@@ -2351,7 +2661,7 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) {
debug_menu->get_popup()->add_shortcut(ED_SHORTCUT("debugger/step_into", TTR("Step Into"), KEY_F11), DEBUG_STEP);
debug_menu->get_popup()->add_separator();
debug_menu->get_popup()->add_shortcut(ED_SHORTCUT("debugger/break", TTR("Break")), DEBUG_BREAK);
- debug_menu->get_popup()->add_shortcut(ED_SHORTCUT("debugger/continue", TTR("Continue")), DEBUG_CONTINUE);
+ debug_menu->get_popup()->add_shortcut(ED_SHORTCUT("debugger/continue", TTR("Continue"), KEY_F12), DEBUG_CONTINUE);
debug_menu->get_popup()->add_separator();
//debug_menu->get_popup()->add_check_item("Show Debugger",DEBUG_SHOW);
debug_menu->get_popup()->add_check_shortcut(ED_SHORTCUT("debugger/keep_debugger_open", TTR("Keep Debugger Open")), DEBUG_SHOW_KEEP_OPEN);
@@ -2587,7 +2897,7 @@ ScriptEditorPlugin::ScriptEditorPlugin(EditorNode *p_node) {
EDITOR_DEF("text_editor/open_scripts/script_temperature_enabled", true);
EDITOR_DEF("text_editor/open_scripts/highlight_current_script", true);
EDITOR_DEF("text_editor/open_scripts/script_temperature_history_size", 15);
- EDITOR_DEF("text_editor/open_scripts/current_script_background_color", Color(1, 1, 1, 0.5));
+ EDITOR_DEF("text_editor/open_scripts/current_script_background_color", Color(1, 1, 1, 0.3));
EDITOR_DEF("text_editor/open_scripts/group_help_pages", true);
EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::INT, "text_editor/open_scripts/sort_scripts_by", PROPERTY_HINT_ENUM, "Name,Path"));
EDITOR_DEF("text_editor/open_scripts/sort_scripts_by", 0);
diff --git a/editor/plugins/script_editor_plugin.h b/editor/plugins/script_editor_plugin.h
index 03fc4da7ce..77ca4bc9d9 100644
--- a/editor/plugins/script_editor_plugin.h
+++ b/editor/plugins/script_editor_plugin.h
@@ -135,6 +135,7 @@ class ScriptEditor : public PanelContainer {
FILE_CLOSE,
CLOSE_DOCS,
CLOSE_ALL,
+ CLOSE_OTHER_TABS,
TOGGLE_SCRIPTS_PANEL,
FILE_TOOL_RELOAD,
FILE_TOOL_RELOAD_SOFT,
@@ -150,10 +151,11 @@ class ScriptEditor : public PanelContainer {
SEARCH_WEBSITE,
HELP_SEARCH_FIND,
HELP_SEARCH_FIND_NEXT,
- WINDOW_MOVE_LEFT,
- WINDOW_MOVE_RIGHT,
+ WINDOW_MOVE_UP,
+ WINDOW_MOVE_DOWN,
WINDOW_NEXT,
WINDOW_PREV,
+ WINDOW_SORT,
WINDOW_SELECT_BASE = 100
};
@@ -173,6 +175,7 @@ class ScriptEditor : public PanelContainer {
MenuButton *edit_menu;
MenuButton *script_search_menu;
MenuButton *debug_menu;
+ PopupMenu *context_menu;
Timer *autosave_timer;
uint64_t idle;
@@ -249,6 +252,7 @@ class ScriptEditor : public PanelContainer {
void _close_current_tab();
void _close_discard_current_tab(const String &p_str);
void _close_docs_tab();
+ void _close_other_tabs();
void _close_all_tabs();
void _ask_close_current_unsaved_tab(ScriptEditorBase *current);
@@ -292,6 +296,7 @@ class ScriptEditor : public PanelContainer {
void _update_members_overview_visibility();
void _update_members_overview();
void _update_script_names();
+ bool _sort_list_on_update;
void _members_overview_selected(int p_idx);
void _script_selected(int p_idx);
@@ -306,8 +311,15 @@ class ScriptEditor : public PanelContainer {
void _script_split_dragged(float);
+ Variant get_drag_data_fw(const Point2 &p_point, Control *p_from);
+ bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const;
+ void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from);
+
void _unhandled_input(const Ref<InputEvent> &p_event);
+ void _script_list_gui_input(const Ref<InputEvent> &ev);
+ void _make_script_list_context_menu();
+
void _help_search(String p_text);
void _help_index(String p_text);
diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp
index a24856dad7..214f24b386 100644
--- a/editor/plugins/script_text_editor.cpp
+++ b/editor/plugins/script_text_editor.cpp
@@ -201,7 +201,7 @@ void ScriptTextEditor::_set_theme_for_script() {
text_edit->add_keyword_color("Rect2", basetype_color);
text_edit->add_keyword_color("Transform2D", basetype_color);
text_edit->add_keyword_color("Vector3", basetype_color);
- text_edit->add_keyword_color("Rect3", basetype_color);
+ text_edit->add_keyword_color("AABB", basetype_color);
text_edit->add_keyword_color("Basis", basetype_color);
text_edit->add_keyword_color("Plane", basetype_color);
text_edit->add_keyword_color("Transform", basetype_color);
@@ -518,7 +518,9 @@ void ScriptTextEditor::tag_saved_version() {
}
void ScriptTextEditor::goto_line(int p_line, bool p_with_error) {
- code_editor->get_text_edit()->call_deferred("cursor_set_line", p_line);
+ TextEdit *tx = code_editor->get_text_edit();
+ tx->unfold_line(p_line);
+ tx->call_deferred("cursor_set_line", p_line);
}
void ScriptTextEditor::ensure_focus() {
@@ -529,9 +531,9 @@ void ScriptTextEditor::ensure_focus() {
void ScriptTextEditor::set_edit_state(const Variant &p_state) {
Dictionary state = p_state;
- code_editor->get_text_edit()->set_v_scroll(state["scroll_position"]);
code_editor->get_text_edit()->cursor_set_column(state["column"]);
code_editor->get_text_edit()->cursor_set_line(state["row"]);
+ code_editor->get_text_edit()->set_v_scroll(state["scroll_position"]);
code_editor->get_text_edit()->grab_focus();
//int scroll_pos;
@@ -712,15 +714,6 @@ void ScriptTextEditor::_breakpoint_toggled(int p_row) {
ScriptEditor::get_singleton()->get_debugger()->set_breakpoint(script->get_path(), p_row + 1, code_editor->get_text_edit()->is_line_set_as_breakpoint(p_row));
}
-static void swap_lines(TextEdit *tx, int line1, int line2) {
- String tmp = tx->get_line(line1);
- String tmp2 = tx->get_line(line2);
- tx->set_line(line2, tmp);
- tx->set_line(line1, tmp2);
-
- tx->cursor_set_line(line2);
-}
-
void ScriptTextEditor::_lookup_symbol(const String &p_symbol, int p_row, int p_column) {
Node *base = get_tree()->get_edited_scene_root();
@@ -799,39 +792,41 @@ void ScriptTextEditor::_lookup_symbol(const String &p_symbol, int p_row, int p_c
void ScriptTextEditor::_edit_option(int p_op) {
+ TextEdit *tx = code_editor->get_text_edit();
+
switch (p_op) {
case EDIT_UNDO: {
- code_editor->get_text_edit()->undo();
- code_editor->get_text_edit()->call_deferred("grab_focus");
+
+ tx->undo();
+ tx->call_deferred("grab_focus");
} break;
case EDIT_REDO: {
- code_editor->get_text_edit()->redo();
- code_editor->get_text_edit()->call_deferred("grab_focus");
+
+ tx->redo();
+ tx->call_deferred("grab_focus");
} break;
case EDIT_CUT: {
- code_editor->get_text_edit()->cut();
- code_editor->get_text_edit()->call_deferred("grab_focus");
+ tx->cut();
+ tx->call_deferred("grab_focus");
} break;
case EDIT_COPY: {
- code_editor->get_text_edit()->copy();
- code_editor->get_text_edit()->call_deferred("grab_focus");
+ tx->copy();
+ tx->call_deferred("grab_focus");
} break;
case EDIT_PASTE: {
- code_editor->get_text_edit()->paste();
- code_editor->get_text_edit()->call_deferred("grab_focus");
+ tx->paste();
+ tx->call_deferred("grab_focus");
} break;
case EDIT_SELECT_ALL: {
- code_editor->get_text_edit()->select_all();
- code_editor->get_text_edit()->call_deferred("grab_focus");
-
+ tx->select_all();
+ tx->call_deferred("grab_focus");
} break;
case EDIT_MOVE_LINE_UP: {
- TextEdit *tx = code_editor->get_text_edit();
Ref<Script> scr = script;
if (scr.is_null())
return;
@@ -850,7 +845,11 @@ void ScriptTextEditor::_edit_option(int p_op) {
if (line_id == 0 || next_id < 0)
return;
- swap_lines(tx, line_id, next_id);
+ tx->unfold_line(line_id);
+ tx->unfold_line(next_id);
+
+ tx->swap_lines(line_id, next_id);
+ tx->cursor_set_line(next_id);
}
int from_line_up = from_line > 0 ? from_line - 1 : from_line;
int to_line_up = to_line > 0 ? to_line - 1 : to_line;
@@ -862,15 +861,17 @@ void ScriptTextEditor::_edit_option(int p_op) {
if (line_id == 0 || next_id < 0)
return;
- swap_lines(tx, line_id, next_id);
+ tx->unfold_line(line_id);
+ tx->unfold_line(next_id);
+
+ tx->swap_lines(line_id, next_id);
+ tx->cursor_set_line(next_id);
}
tx->end_complex_operation();
tx->update();
-
} break;
case EDIT_MOVE_LINE_DOWN: {
- TextEdit *tx = code_editor->get_text_edit();
Ref<Script> scr = get_edited_script();
if (scr.is_null())
return;
@@ -889,7 +890,11 @@ void ScriptTextEditor::_edit_option(int p_op) {
if (line_id == tx->get_line_count() - 1 || next_id > tx->get_line_count())
return;
- swap_lines(tx, line_id, next_id);
+ tx->unfold_line(line_id);
+ tx->unfold_line(next_id);
+
+ tx->swap_lines(line_id, next_id);
+ tx->cursor_set_line(next_id);
}
int from_line_down = from_line < tx->get_line_count() ? from_line + 1 : from_line;
int to_line_down = to_line < tx->get_line_count() ? to_line + 1 : to_line;
@@ -901,7 +906,11 @@ void ScriptTextEditor::_edit_option(int p_op) {
if (line_id == tx->get_line_count() - 1 || next_id > tx->get_line_count())
return;
- swap_lines(tx, line_id, next_id);
+ tx->unfold_line(line_id);
+ tx->unfold_line(next_id);
+
+ tx->swap_lines(line_id, next_id);
+ tx->cursor_set_line(next_id);
}
tx->end_complex_operation();
tx->update();
@@ -909,7 +918,6 @@ void ScriptTextEditor::_edit_option(int p_op) {
} break;
case EDIT_INDENT_LEFT: {
- TextEdit *tx = code_editor->get_text_edit();
Ref<Script> scr = get_edited_script();
if (scr.is_null())
return;
@@ -934,11 +942,9 @@ void ScriptTextEditor::_edit_option(int p_op) {
tx->end_complex_operation();
tx->update();
//tx->deselect();
-
} break;
case EDIT_INDENT_RIGHT: {
- TextEdit *tx = code_editor->get_text_edit();
Ref<Script> scr = get_edited_script();
if (scr.is_null())
return;
@@ -955,11 +961,9 @@ void ScriptTextEditor::_edit_option(int p_op) {
tx->end_complex_operation();
tx->update();
//tx->deselect();
-
} break;
case EDIT_DELETE_LINE: {
- TextEdit *tx = code_editor->get_text_edit();
Ref<Script> scr = get_edited_script();
if (scr.is_null())
return;
@@ -968,13 +972,12 @@ void ScriptTextEditor::_edit_option(int p_op) {
int line = tx->cursor_get_line();
tx->set_line(tx->cursor_get_line(), "");
tx->backspace_at_cursor();
+ tx->unfold_line(line);
tx->cursor_set_line(line);
tx->end_complex_operation();
-
} break;
case EDIT_CLONE_DOWN: {
- TextEdit *tx = code_editor->get_text_edit();
Ref<Script> scr = get_edited_script();
if (scr.is_null())
return;
@@ -993,6 +996,7 @@ void ScriptTextEditor::_edit_option(int p_op) {
tx->begin_complex_operation();
for (int i = from_line; i <= to_line; i++) {
+ tx->unfold_line(i);
if (i >= tx->get_line_count() - 1) {
tx->set_line(i, tx->get_line(i) + "\n");
}
@@ -1008,11 +1012,29 @@ void ScriptTextEditor::_edit_option(int p_op) {
tx->end_complex_operation();
tx->update();
+ } break;
+ case EDIT_FOLD_LINE: {
+
+ tx->fold_line(tx->cursor_get_line());
+ tx->update();
+ } break;
+ case EDIT_UNFOLD_LINE: {
+
+ tx->unfold_line(tx->cursor_get_line());
+ tx->update();
+ } break;
+ case EDIT_FOLD_ALL_LINES: {
+
+ tx->fold_all_lines();
+ tx->update();
+ } break;
+ case EDIT_UNFOLD_ALL_LINES: {
+ tx->unhide_all_lines();
+ tx->update();
} break;
case EDIT_TOGGLE_COMMENT: {
- TextEdit *tx = code_editor->get_text_edit();
Ref<Script> scr = get_edited_script();
if (scr.is_null())
return;
@@ -1061,62 +1083,65 @@ void ScriptTextEditor::_edit_option(int p_op) {
tx->end_complex_operation();
tx->update();
//tx->deselect();
-
} break;
case EDIT_COMPLETE: {
- code_editor->get_text_edit()->query_code_comple();
-
+ tx->query_code_comple();
} break;
case EDIT_AUTO_INDENT: {
- TextEdit *te = code_editor->get_text_edit();
- String text = te->get_text();
+ String text = tx->get_text();
Ref<Script> scr = get_edited_script();
if (scr.is_null())
return;
- te->begin_complex_operation();
+ tx->begin_complex_operation();
int begin, end;
- if (te->is_selection_active()) {
- begin = te->get_selection_from_line();
- end = te->get_selection_to_line();
+ if (tx->is_selection_active()) {
+ begin = tx->get_selection_from_line();
+ end = tx->get_selection_to_line();
// ignore if the cursor is not past the first column
- if (te->get_selection_to_column() == 0) {
+ if (tx->get_selection_to_column() == 0) {
end--;
}
} else {
begin = 0;
- end = te->get_line_count() - 1;
+ end = tx->get_line_count() - 1;
}
scr->get_language()->auto_indent_code(text, begin, end);
Vector<String> lines = text.split("\n");
for (int i = begin; i <= end; ++i) {
- te->set_line(i, lines[i]);
+ tx->set_line(i, lines[i]);
}
- te->end_complex_operation();
-
+ tx->end_complex_operation();
} break;
case EDIT_TRIM_TRAILING_WHITESAPCE: {
+
trim_trailing_whitespace();
} break;
case EDIT_CONVERT_INDENT_TO_SPACES: {
+
convert_indent_to_spaces();
} break;
case EDIT_CONVERT_INDENT_TO_TABS: {
+
convert_indent_to_tabs();
} break;
case EDIT_PICK_COLOR: {
+
color_panel->popup();
} break;
case EDIT_TO_UPPERCASE: {
+
_convert_case(UPPER);
} break;
case EDIT_TO_LOWERCASE: {
+
_convert_case(LOWER);
} break;
case EDIT_CAPITALIZE: {
+
_convert_case(CAPITALIZE);
} break;
case SEARCH_FIND: {
@@ -1141,41 +1166,47 @@ void ScriptTextEditor::_edit_option(int p_op) {
} break;
case SEARCH_GOTO_LINE: {
- goto_line_dialog->popup_find_line(code_editor->get_text_edit());
+ goto_line_dialog->popup_find_line(tx);
} break;
case DEBUG_TOGGLE_BREAKPOINT: {
- int line = code_editor->get_text_edit()->cursor_get_line();
- bool dobreak = !code_editor->get_text_edit()->is_line_set_as_breakpoint(line);
- code_editor->get_text_edit()->set_line_as_breakpoint(line, dobreak);
+
+ int line = tx->cursor_get_line();
+ bool dobreak = !tx->is_line_set_as_breakpoint(line);
+ tx->set_line_as_breakpoint(line, dobreak);
ScriptEditor::get_singleton()->get_debugger()->set_breakpoint(get_edited_script()->get_path(), line + 1, dobreak);
} break;
case DEBUG_REMOVE_ALL_BREAKPOINTS: {
+
List<int> bpoints;
- code_editor->get_text_edit()->get_breakpoints(&bpoints);
+ tx->get_breakpoints(&bpoints);
for (List<int>::Element *E = bpoints.front(); E; E = E->next()) {
int line = E->get();
- bool dobreak = !code_editor->get_text_edit()->is_line_set_as_breakpoint(line);
- code_editor->get_text_edit()->set_line_as_breakpoint(line, dobreak);
+ bool dobreak = !tx->is_line_set_as_breakpoint(line);
+ tx->set_line_as_breakpoint(line, dobreak);
ScriptEditor::get_singleton()->get_debugger()->set_breakpoint(get_edited_script()->get_path(), line + 1, dobreak);
}
}
case DEBUG_GOTO_NEXT_BREAKPOINT: {
+
List<int> bpoints;
- code_editor->get_text_edit()->get_breakpoints(&bpoints);
+ tx->get_breakpoints(&bpoints);
if (bpoints.size() <= 0) {
return;
}
- int line = code_editor->get_text_edit()->cursor_get_line();
+ int line = tx->cursor_get_line();
+
// wrap around
if (line >= bpoints[bpoints.size() - 1]) {
- code_editor->get_text_edit()->cursor_set_line(bpoints[0]);
+ tx->unfold_line(bpoints[0]);
+ tx->cursor_set_line(bpoints[0]);
} else {
for (List<int>::Element *E = bpoints.front(); E; E = E->next()) {
int bline = E->get();
if (bline > line) {
- code_editor->get_text_edit()->cursor_set_line(bline);
+ tx->unfold_line(bline);
+ tx->cursor_set_line(bline);
return;
}
}
@@ -1183,21 +1214,24 @@ void ScriptTextEditor::_edit_option(int p_op) {
} break;
case DEBUG_GOTO_PREV_BREAKPOINT: {
+
List<int> bpoints;
- code_editor->get_text_edit()->get_breakpoints(&bpoints);
+ tx->get_breakpoints(&bpoints);
if (bpoints.size() <= 0) {
return;
}
- int line = code_editor->get_text_edit()->cursor_get_line();
+ int line = tx->cursor_get_line();
// wrap around
if (line <= bpoints[0]) {
- code_editor->get_text_edit()->cursor_set_line(bpoints[bpoints.size() - 1]);
+ tx->unfold_line(bpoints[bpoints.size() - 1]);
+ tx->cursor_set_line(bpoints[bpoints.size() - 1]);
} else {
for (List<int>::Element *E = bpoints.back(); E; E = E->prev()) {
int bline = E->get();
if (bline < line) {
- code_editor->get_text_edit()->cursor_set_line(bline);
+ tx->unfold_line(bline);
+ tx->cursor_set_line(bline);
return;
}
}
@@ -1206,9 +1240,10 @@ void ScriptTextEditor::_edit_option(int p_op) {
} break;
case HELP_CONTEXTUAL: {
- String text = code_editor->get_text_edit()->get_selection_text();
+
+ String text = tx->get_selection_text();
if (text == "")
- text = code_editor->get_text_edit()->get_word_under_cursor();
+ text = tx->get_word_under_cursor();
if (text != "") {
emit_signal("request_help_search", text);
}
@@ -1394,6 +1429,9 @@ void ScriptTextEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) {
Vector2 mpos = mb->get_global_position() - tx->get_global_position();
bool have_selection = (tx->get_selection_text().length() > 0);
bool have_color = (tx->get_word_at_pos(mpos) == "Color");
+ int fold_state = 0;
+ bool can_fold = tx->can_fold(row);
+ bool is_folded = tx->is_folded(row);
if (have_color) {
String line = tx->get_line(row);
@@ -1424,7 +1462,7 @@ void ScriptTextEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) {
have_color = false;
}
}
- _make_context_menu(have_selection, have_color);
+ _make_context_menu(have_selection, have_color, can_fold, is_folded);
}
}
}
@@ -1443,7 +1481,7 @@ void ScriptTextEditor::_color_changed(const Color &p_color) {
code_editor->get_text_edit()->set_line(color_line, new_line);
}
-void ScriptTextEditor::_make_context_menu(bool p_selection, bool p_color) {
+void ScriptTextEditor::_make_context_menu(bool p_selection, bool p_color, bool p_can_fold, bool p_is_folded) {
context_menu->clear();
if (p_selection) {
@@ -1463,6 +1501,13 @@ void ScriptTextEditor::_make_context_menu(bool p_selection, bool p_color) {
context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/indent_right"), EDIT_INDENT_RIGHT);
context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/toggle_comment"), EDIT_TOGGLE_COMMENT);
}
+ if (p_can_fold) {
+ // can fold
+ context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/fold_line"), EDIT_FOLD_LINE);
+ } else if (p_is_folded) {
+ // can unfold
+ context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/unfold_line"), EDIT_UNFOLD_LINE);
+ }
if (p_color) {
context_menu->add_separator();
context_menu->add_item(TTR("Pick Color"), EDIT_PICK_COLOR);
@@ -1526,6 +1571,10 @@ ScriptTextEditor::ScriptTextEditor() {
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/delete_line"), EDIT_DELETE_LINE);
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/toggle_comment"), EDIT_TOGGLE_COMMENT);
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/clone_down"), EDIT_CLONE_DOWN);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/fold_line"), EDIT_FOLD_LINE);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/fold_all_lines"), EDIT_FOLD_ALL_LINES);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/unfold_line"), EDIT_UNFOLD_LINE);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/unfold_all_lines"), EDIT_UNFOLD_ALL_LINES);
edit_menu->get_popup()->add_separator();
#ifdef OSX_ENABLED
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/complete_symbol"), EDIT_COMPLETE);
@@ -1603,6 +1652,10 @@ void ScriptTextEditor::register_editor() {
ED_SHORTCUT("script_text_editor/indent_right", TTR("Indent Right"), 0);
ED_SHORTCUT("script_text_editor/toggle_comment", TTR("Toggle Comment"), KEY_MASK_CMD | KEY_K);
ED_SHORTCUT("script_text_editor/clone_down", TTR("Clone Down"), KEY_MASK_CMD | KEY_B);
+ ED_SHORTCUT("script_text_editor/fold_line", TTR("Fold Line"), KEY_MASK_ALT | KEY_LEFT);
+ ED_SHORTCUT("script_text_editor/unfold_line", TTR("Unfold Line"), KEY_MASK_ALT | KEY_RIGHT);
+ ED_SHORTCUT("script_text_editor/fold_all_lines", TTR("Fold All Lines"), 0);
+ ED_SHORTCUT("script_text_editor/unfold_all_lines", TTR("Unfold All Lines"), 0);
#ifdef OSX_ENABLED
ED_SHORTCUT("script_text_editor/complete_symbol", TTR("Complete Symbol"), KEY_MASK_CTRL | KEY_SPACE);
#else
diff --git a/editor/plugins/script_text_editor.h b/editor/plugins/script_text_editor.h
index 83f3ea57c0..722015ef3e 100644
--- a/editor/plugins/script_text_editor.h
+++ b/editor/plugins/script_text_editor.h
@@ -91,6 +91,10 @@ class ScriptTextEditor : public ScriptEditorBase {
EDIT_TO_UPPERCASE,
EDIT_TO_LOWERCASE,
EDIT_CAPITALIZE,
+ EDIT_FOLD_LINE,
+ EDIT_UNFOLD_LINE,
+ EDIT_FOLD_ALL_LINES,
+ EDIT_UNFOLD_ALL_LINES,
SEARCH_FIND,
SEARCH_FIND_NEXT,
SEARCH_FIND_PREV,
@@ -118,7 +122,7 @@ protected:
static void _bind_methods();
void _edit_option(int p_op);
- void _make_context_menu(bool p_selection, bool p_color);
+ void _make_context_menu(bool p_selection, bool p_color, bool p_can_fold, bool p_is_folded);
void _text_edit_gui_input(const Ref<InputEvent> &ev);
void _color_changed(const Color &p_color);
diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp
index b0ee1a32ca..49e4642049 100644
--- a/editor/plugins/shader_editor_plugin.cpp
+++ b/editor/plugins/shader_editor_plugin.cpp
@@ -248,6 +248,8 @@ void ShaderTextEditor::_validate_script() {
if (err != OK) {
String error_text = "error(" + itos(sl.get_error_line()) + "): " + sl.get_error_text();
set_error(error_text);
+ for (int i = 0; i < get_text_edit()->get_line_count(); i++)
+ get_text_edit()->set_line_as_marked(i, false);
get_text_edit()->set_line_as_marked(sl.get_error_line() - 1, true);
} else {
@@ -269,55 +271,284 @@ ShaderTextEditor::ShaderTextEditor() {
void ShaderEditor::_menu_option(int p_option) {
- ShaderTextEditor *current = shader_editor;
-
switch (p_option) {
case EDIT_UNDO: {
-
- current->get_text_edit()->undo();
+ shader_editor->get_text_edit()->undo();
} break;
case EDIT_REDO: {
- current->get_text_edit()->redo();
-
+ shader_editor->get_text_edit()->redo();
} break;
case EDIT_CUT: {
-
- current->get_text_edit()->cut();
+ shader_editor->get_text_edit()->cut();
} break;
case EDIT_COPY: {
- current->get_text_edit()->copy();
-
+ shader_editor->get_text_edit()->copy();
} break;
case EDIT_PASTE: {
- current->get_text_edit()->paste();
-
+ shader_editor->get_text_edit()->paste();
} break;
case EDIT_SELECT_ALL: {
+ shader_editor->get_text_edit()->select_all();
+ } break;
+ case EDIT_MOVE_LINE_UP: {
+
+ TextEdit *tx = shader_editor->get_text_edit();
+ if (shader.is_null())
+ return;
+
+ tx->begin_complex_operation();
+ if (tx->is_selection_active()) {
+ int from_line = tx->get_selection_from_line();
+ int from_col = tx->get_selection_from_column();
+ int to_line = tx->get_selection_to_line();
+ int to_column = tx->get_selection_to_column();
+
+ for (int i = from_line; i <= to_line; i++) {
+ int line_id = i;
+ int next_id = i - 1;
+
+ if (line_id == 0 || next_id < 0)
+ return;
+
+ tx->swap_lines(line_id, next_id);
+ tx->cursor_set_line(next_id);
+ }
+ int from_line_up = from_line > 0 ? from_line - 1 : from_line;
+ int to_line_up = to_line > 0 ? to_line - 1 : to_line;
+ tx->select(from_line_up, from_col, to_line_up, to_column);
+ } else {
+ int line_id = tx->cursor_get_line();
+ int next_id = line_id - 1;
+
+ if (line_id == 0 || next_id < 0)
+ return;
+
+ tx->swap_lines(line_id, next_id);
+ tx->cursor_set_line(next_id);
+ }
+ tx->end_complex_operation();
+ tx->update();
+
+ } break;
+ case EDIT_MOVE_LINE_DOWN: {
+
+ TextEdit *tx = shader_editor->get_text_edit();
+ if (shader.is_null())
+ return;
+
+ tx->begin_complex_operation();
+ if (tx->is_selection_active()) {
+ int from_line = tx->get_selection_from_line();
+ int from_col = tx->get_selection_from_column();
+ int to_line = tx->get_selection_to_line();
+ int to_column = tx->get_selection_to_column();
+
+ for (int i = to_line; i >= from_line; i--) {
+ int line_id = i;
+ int next_id = i + 1;
+
+ if (line_id == tx->get_line_count() - 1 || next_id > tx->get_line_count())
+ return;
+
+ tx->swap_lines(line_id, next_id);
+ tx->cursor_set_line(next_id);
+ }
+ int from_line_down = from_line < tx->get_line_count() ? from_line + 1 : from_line;
+ int to_line_down = to_line < tx->get_line_count() ? to_line + 1 : to_line;
+ tx->select(from_line_down, from_col, to_line_down, to_column);
+ } else {
+ int line_id = tx->cursor_get_line();
+ int next_id = line_id + 1;
+
+ if (line_id == tx->get_line_count() - 1 || next_id > tx->get_line_count())
+ return;
+
+ tx->swap_lines(line_id, next_id);
+ tx->cursor_set_line(next_id);
+ }
+ tx->end_complex_operation();
+ tx->update();
+
+ } break;
+ case EDIT_INDENT_LEFT: {
+
+ TextEdit *tx = shader_editor->get_text_edit();
+ if (shader.is_null())
+ return;
+
+ tx->begin_complex_operation();
+ if (tx->is_selection_active()) {
+ tx->indent_selection_left();
+ } else {
+ int begin = tx->cursor_get_line();
+ String line_text = tx->get_line(begin);
+ // begins with tab
+ if (line_text.begins_with("\t")) {
+ line_text = line_text.substr(1, line_text.length());
+ tx->set_line(begin, line_text);
+ }
+ // begins with 4 spaces
+ else if (line_text.begins_with(" ")) {
+ line_text = line_text.substr(4, line_text.length());
+ tx->set_line(begin, line_text);
+ }
+ }
+ tx->end_complex_operation();
+ tx->update();
+ //tx->deselect();
+
+ } break;
+ case EDIT_INDENT_RIGHT: {
+
+ TextEdit *tx = shader_editor->get_text_edit();
+ if (shader.is_null())
+ return;
+
+ tx->begin_complex_operation();
+ if (tx->is_selection_active()) {
+ tx->indent_selection_right();
+ } else {
+ int begin = tx->cursor_get_line();
+ String line_text = tx->get_line(begin);
+ line_text = '\t' + line_text;
+ tx->set_line(begin, line_text);
+ }
+ tx->end_complex_operation();
+ tx->update();
+ //tx->deselect();
+
+ } break;
+ case EDIT_DELETE_LINE: {
- current->get_text_edit()->select_all();
+ TextEdit *tx = shader_editor->get_text_edit();
+ if (shader.is_null())
+ return;
+
+ tx->begin_complex_operation();
+ int line = tx->cursor_get_line();
+ tx->set_line(tx->cursor_get_line(), "");
+ tx->backspace_at_cursor();
+ tx->cursor_set_line(line);
+ tx->end_complex_operation();
} break;
+ case EDIT_CLONE_DOWN: {
+
+ TextEdit *tx = shader_editor->get_text_edit();
+ if (shader.is_null())
+ return;
+
+ int from_line = tx->cursor_get_line();
+ int to_line = tx->cursor_get_line();
+ int column = tx->cursor_get_column();
+
+ if (tx->is_selection_active()) {
+ from_line = tx->get_selection_from_line();
+ to_line = tx->get_selection_to_line();
+ column = tx->cursor_get_column();
+ }
+ int next_line = to_line + 1;
+
+ tx->begin_complex_operation();
+ for (int i = from_line; i <= to_line; i++) {
+
+ if (i >= tx->get_line_count() - 1) {
+ tx->set_line(i, tx->get_line(i) + "\n");
+ }
+ String line_clone = tx->get_line(i);
+ tx->insert_at(line_clone, next_line);
+ next_line++;
+ }
+
+ tx->cursor_set_column(column);
+ if (tx->is_selection_active()) {
+ tx->select(to_line + 1, tx->get_selection_from_column(), next_line - 1, tx->get_selection_to_column());
+ }
+
+ tx->end_complex_operation();
+ tx->update();
+
+ } break;
+ case EDIT_TOGGLE_COMMENT: {
+
+ TextEdit *tx = shader_editor->get_text_edit();
+ if (shader.is_null())
+ return;
+
+ tx->begin_complex_operation();
+ if (tx->is_selection_active()) {
+ int begin = tx->get_selection_from_line();
+ int end = tx->get_selection_to_line();
+
+ // End of selection ends on the first column of the last line, ignore it.
+ if (tx->get_selection_to_column() == 0)
+ end -= 1;
+
+ // Check if all lines in the selected block are commented
+ bool is_commented = true;
+ for (int i = begin; i <= end; i++) {
+ if (!tx->get_line(i).begins_with("//")) {
+ is_commented = false;
+ break;
+ }
+ }
+ for (int i = begin; i <= end; i++) {
+ String line_text = tx->get_line(i);
+
+ if (line_text.strip_edges().empty()) {
+ line_text = "//";
+ } else {
+ if (is_commented) {
+ line_text = line_text.substr(2, line_text.length());
+ } else {
+ line_text = "//" + line_text;
+ }
+ }
+ tx->set_line(i, line_text);
+ }
+ } else {
+ int begin = tx->cursor_get_line();
+ String line_text = tx->get_line(begin);
+
+ if (line_text.begins_with("//"))
+ line_text = line_text.substr(2, line_text.length());
+ else
+ line_text = "//" + line_text;
+ tx->set_line(begin, line_text);
+ }
+ tx->end_complex_operation();
+ tx->update();
+ //tx->deselect();
+
+ } break;
+ case EDIT_COMPLETE: {
+
+ shader_editor->get_text_edit()->query_code_comple();
+ } break;
case SEARCH_FIND: {
- current->get_find_replace_bar()->popup_search();
+ shader_editor->get_find_replace_bar()->popup_search();
} break;
case SEARCH_FIND_NEXT: {
- current->get_find_replace_bar()->search_next();
+ shader_editor->get_find_replace_bar()->search_next();
} break;
case SEARCH_FIND_PREV: {
- current->get_find_replace_bar()->search_prev();
+ shader_editor->get_find_replace_bar()->search_prev();
} break;
case SEARCH_REPLACE: {
- current->get_find_replace_bar()->popup_replace();
+ shader_editor->get_find_replace_bar()->popup_replace();
} break;
case SEARCH_GOTO_LINE: {
- goto_line_dialog->popup_find_line(current->get_text_edit());
+ goto_line_dialog->popup_find_line(shader_editor->get_text_edit());
} break;
}
+ if (p_option != SEARCH_FIND && p_option != SEARCH_REPLACE && p_option != SEARCH_GOTO_LINE) {
+ shader_editor->get_text_edit()->call_deferred("grab_focus");
+ }
}
void ShaderEditor::_notification(int p_what) {
@@ -325,10 +556,6 @@ void ShaderEditor::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE) {
}
if (p_what == NOTIFICATION_DRAW) {
-
- RID ci = get_canvas_item();
- Ref<StyleBox> style = get_stylebox("panel", "Panel");
- style->draw(ci, Rect2(Point2(), get_size()));
}
}
@@ -348,6 +575,7 @@ void ShaderEditor::_editor_settings_changed() {
shader_editor->get_text_edit()->set_show_line_numbers(EditorSettings::get_singleton()->get("text_editor/line_numbers/show_line_numbers"));
shader_editor->get_text_edit()->set_syntax_coloring(EditorSettings::get_singleton()->get("text_editor/highlighting/syntax_highlighting"));
shader_editor->get_text_edit()->set_highlight_all_occurrences(EditorSettings::get_singleton()->get("text_editor/highlighting/highlight_all_occurrences"));
+ shader_editor->get_text_edit()->set_highlight_current_line(EditorSettings::get_singleton()->get("text_editor/highlighting/highlight_current_line"));
shader_editor->get_text_edit()->cursor_set_blink_enabled(EditorSettings::get_singleton()->get("text_editor/cursor/caret_blink"));
shader_editor->get_text_edit()->cursor_set_blink_speed(EditorSettings::get_singleton()->get("text_editor/cursor/caret_blink_speed"));
shader_editor->get_text_edit()->add_constant_override("line_spacing", EditorSettings::get_singleton()->get("text_editor/theme/line_spacing"));
@@ -359,6 +587,7 @@ void ShaderEditor::_editor_settings_changed() {
void ShaderEditor::_bind_methods() {
ClassDB::bind_method("_editor_settings_changed", &ShaderEditor::_editor_settings_changed);
+ ClassDB::bind_method("_text_edit_gui_input", &ShaderEditor::_text_edit_gui_input);
ClassDB::bind_method("_menu_option", &ShaderEditor::_menu_option);
ClassDB::bind_method("_params_changed", &ShaderEditor::_params_changed);
@@ -412,49 +641,122 @@ void ShaderEditor::apply_shaders() {
}
}
-ShaderEditor::ShaderEditor() {
+void ShaderEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) {
- HBoxContainer *hbc = memnew(HBoxContainer);
+ Ref<InputEventMouseButton> mb = ev;
- add_child(hbc);
+ if (mb.is_valid()) {
+
+ if (mb->get_button_index() == BUTTON_RIGHT && !mb->is_pressed()) {
+
+ int col, row;
+ TextEdit *tx = shader_editor->get_text_edit();
+ tx->_get_mouse_pos(mb->get_global_position() - tx->get_global_position(), row, col);
+ Vector2 mpos = mb->get_global_position() - tx->get_global_position();
+ bool have_selection = (tx->get_selection_text().length() > 0);
+ _make_context_menu(have_selection);
+ }
+ }
+}
+
+void ShaderEditor::_make_context_menu(bool p_selection) {
+
+ context_menu->clear();
+ if (p_selection) {
+ context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/cut"), EDIT_CUT);
+ context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/copy"), EDIT_COPY);
+ }
+
+ context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/paste"), EDIT_PASTE);
+ context_menu->add_separator();
+ context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/select_all"), EDIT_SELECT_ALL);
+ context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/undo"), EDIT_UNDO);
+ context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/redo"), EDIT_REDO);
+
+ context_menu->add_separator();
+ context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/indent_left"), EDIT_INDENT_LEFT);
+ context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/indent_right"), EDIT_INDENT_RIGHT);
+ context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/toggle_comment"), EDIT_TOGGLE_COMMENT);
+
+ context_menu->set_position(get_global_transform().xform(get_local_mouse_position()));
+ context_menu->set_size(Vector2(1, 1));
+ context_menu->popup();
+}
+
+ShaderEditor::ShaderEditor(EditorNode *p_node) {
+
+ shader_editor = memnew(ShaderTextEditor);
+ shader_editor->set_v_size_flags(SIZE_EXPAND_FILL);
+ shader_editor->add_constant_override("separation", 0);
+ shader_editor->set_anchors_and_margins_preset(Control::PRESET_WIDE);
+
+ shader_editor->connect("script_changed", this, "apply_shaders");
+ EditorSettings::get_singleton()->connect("settings_changed", this, "_editor_settings_changed");
+
+ shader_editor->get_text_edit()->set_callhint_settings(
+ EditorSettings::get_singleton()->get("text_editor/completion/put_callhint_tooltip_below_current_line"),
+ EditorSettings::get_singleton()->get("text_editor/completion/callhint_tooltip_offset"));
+
+ shader_editor->get_text_edit()->set_select_identifiers_on_hover(true);
+ shader_editor->get_text_edit()->set_context_menu_enabled(false);
+ shader_editor->get_text_edit()->connect("gui_input", this, "_text_edit_gui_input");
+
+ shader_editor->update_editor_settings();
+
+ context_menu = memnew(PopupMenu);
+ add_child(context_menu);
+ context_menu->connect("id_pressed", this, "_menu_option");
+
+ VBoxContainer *main_container = memnew(VBoxContainer);
+ HBoxContainer *hbc = memnew(HBoxContainer);
edit_menu = memnew(MenuButton);
- hbc->add_child(edit_menu);
- edit_menu->set_position(Point2(5, -1));
+ //edit_menu->set_position(Point2(5, -1));
edit_menu->set_text(TTR("Edit"));
- edit_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/undo", TTR("Undo"), KEY_MASK_CMD | KEY_Z), EDIT_UNDO);
- edit_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/redo", TTR("Redo"), KEY_MASK_CMD | KEY_Y), EDIT_REDO);
+
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/undo"), EDIT_UNDO);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/redo"), EDIT_REDO);
+ edit_menu->get_popup()->add_separator();
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/cut"), EDIT_CUT);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/copy"), EDIT_COPY);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/paste"), EDIT_PASTE);
+ edit_menu->get_popup()->add_separator();
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/select_all"), EDIT_SELECT_ALL);
edit_menu->get_popup()->add_separator();
- edit_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/cut", TTR("Cut"), KEY_MASK_CMD | KEY_X), EDIT_CUT);
- edit_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/copy", TTR("Copy"), KEY_MASK_CMD | KEY_C), EDIT_COPY);
- edit_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/paste", TTR("Paste"), KEY_MASK_CMD | KEY_V), EDIT_PASTE);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/move_up"), EDIT_MOVE_LINE_UP);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/move_down"), EDIT_MOVE_LINE_DOWN);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/indent_left"), EDIT_INDENT_LEFT);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/indent_right"), EDIT_INDENT_RIGHT);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/delete_line"), EDIT_DELETE_LINE);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/toggle_comment"), EDIT_TOGGLE_COMMENT);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/clone_down"), EDIT_CLONE_DOWN);
edit_menu->get_popup()->add_separator();
- edit_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/select_all", TTR("Select All"), KEY_MASK_CMD | KEY_A), EDIT_SELECT_ALL);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/complete_symbol"), EDIT_COMPLETE);
+
edit_menu->get_popup()->connect("id_pressed", this, "_menu_option");
search_menu = memnew(MenuButton);
- hbc->add_child(search_menu);
- search_menu->set_position(Point2(38, -1));
+ //search_menu->set_position(Point2(38, -1));
search_menu->set_text(TTR("Search"));
- search_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/find", TTR("Find.."), KEY_MASK_CMD | KEY_F), SEARCH_FIND);
- search_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/find_next", TTR("Find Next"), KEY_F3), SEARCH_FIND_NEXT);
- search_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/find_previous", TTR("Find Previous"), KEY_MASK_SHIFT | KEY_F3), SEARCH_FIND_PREV);
- search_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/replace", TTR("Replace.."), KEY_MASK_CMD | KEY_R), SEARCH_REPLACE);
+
+ search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/find"), SEARCH_FIND);
+ search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/find_next"), SEARCH_FIND_NEXT);
+ search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/find_previous"), SEARCH_FIND_PREV);
+ search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/replace"), SEARCH_REPLACE);
search_menu->get_popup()->add_separator();
- //search_menu->get_popup()->add_item("Locate Symbol..",SEARCH_LOCATE_SYMBOL,KEY_MASK_CMD|KEY_K);
- search_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/goto_line", TTR("Goto Line.."), KEY_MASK_CMD | KEY_L), SEARCH_GOTO_LINE);
+ search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_line"), SEARCH_GOTO_LINE);
search_menu->get_popup()->connect("id_pressed", this, "_menu_option");
+ add_child(main_container);
+ main_container->add_child(hbc);
+ hbc->add_child(search_menu);
+ hbc->add_child(edit_menu);
+ hbc->add_style_override("panel", p_node->get_gui_base()->get_stylebox("ScriptEditorPanel", "EditorStyles"));
+ main_container->add_child(shader_editor);
+
goto_line_dialog = memnew(GotoLineDialog);
add_child(goto_line_dialog);
- shader_editor = memnew(ShaderTextEditor);
- add_child(shader_editor);
- shader_editor->set_v_size_flags(SIZE_EXPAND_FILL);
-
- shader_editor->connect("script_changed", this, "apply_shaders");
- EditorSettings::get_singleton()->connect("settings_changed", this, "_editor_settings_changed");
-
_editor_settings_changed();
}
@@ -503,7 +805,7 @@ void ShaderEditorPlugin::apply_changes() {
ShaderEditorPlugin::ShaderEditorPlugin(EditorNode *p_node) {
editor = p_node;
- shader_editor = memnew(ShaderEditor);
+ shader_editor = memnew(ShaderEditor(p_node));
shader_editor->set_custom_minimum_size(Size2(0, 300));
button = editor->add_bottom_panel_item(TTR("Shader"), shader_editor);
diff --git a/editor/plugins/shader_editor_plugin.h b/editor/plugins/shader_editor_plugin.h
index ab18784d9f..b191f5700f 100644
--- a/editor/plugins/shader_editor_plugin.h
+++ b/editor/plugins/shader_editor_plugin.h
@@ -33,6 +33,7 @@
#include "editor/code_editor.h"
#include "editor/editor_plugin.h"
#include "scene/gui/menu_button.h"
+#include "scene/gui/panel_container.h"
#include "scene/gui/tab_container.h"
#include "scene/gui/text_edit.h"
#include "scene/main/timer.h"
@@ -61,9 +62,9 @@ public:
ShaderTextEditor();
};
-class ShaderEditor : public VBoxContainer {
+class ShaderEditor : public PanelContainer {
- GDCLASS(ShaderEditor, VBoxContainer);
+ GDCLASS(ShaderEditor, PanelContainer);
enum {
@@ -73,6 +74,14 @@ class ShaderEditor : public VBoxContainer {
EDIT_COPY,
EDIT_PASTE,
EDIT_SELECT_ALL,
+ EDIT_MOVE_LINE_UP,
+ EDIT_MOVE_LINE_DOWN,
+ EDIT_INDENT_LEFT,
+ EDIT_INDENT_RIGHT,
+ EDIT_DELETE_LINE,
+ EDIT_CLONE_DOWN,
+ EDIT_TOGGLE_COMMENT,
+ EDIT_COMPLETE,
SEARCH_FIND,
SEARCH_FIND_NEXT,
SEARCH_FIND_PREV,
@@ -84,6 +93,7 @@ class ShaderEditor : public VBoxContainer {
MenuButton *edit_menu;
MenuButton *search_menu;
MenuButton *settings_menu;
+ PopupMenu *context_menu;
uint64_t idle;
GotoLineDialog *goto_line_dialog;
@@ -100,6 +110,8 @@ class ShaderEditor : public VBoxContainer {
protected:
void _notification(int p_what);
static void _bind_methods();
+ void _make_context_menu(bool p_selection);
+ void _text_edit_gui_input(const Ref<InputEvent> &ev);
public:
void apply_shaders();
@@ -110,7 +122,7 @@ public:
virtual Size2 get_minimum_size() const { return Size2(0, 200); }
void save_external_data();
- ShaderEditor();
+ ShaderEditor(EditorNode *p_node);
};
class ShaderEditorPlugin : public EditorPlugin {
diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp
index 425390723c..921ba529a2 100644
--- a/editor/plugins/spatial_editor_plugin.cpp
+++ b/editor/plugins/spatial_editor_plugin.cpp
@@ -63,7 +63,8 @@
#define ZOOM_MULTIPLIER 1.08
#define ZOOM_INDICATOR_DELAY_S 1.5
-#define FREELOOK_MIN_SPEED 0.1
+#define FREELOOK_MIN_SPEED 0.01
+#define FREELOOK_SPEED_MULTIPLIER 1.08
#define MIN_Z 0.01
#define MAX_Z 10000
@@ -75,34 +76,66 @@ void SpatialEditorViewport::_update_camera(float p_interp_delta) {
bool is_orthogonal = camera->get_projection() == Camera::PROJECTION_ORTHOGONAL;
- //when not being manipulated, move softly
- float free_orbit_inertia = EDITOR_GET("editors/3d/navigation_feel/orbit_inertia");
- float free_translation_inertia = EDITOR_GET("editors/3d/navigation_feel/translation_inertia");
- //when being manipulated, move more quickly
- float manip_orbit_inertia = EDITOR_GET("editors/3d/navigation_feel/manipulation_orbit_inertia");
- float manip_translation_inertia = EDITOR_GET("editors/3d/navigation_feel/manipulation_translation_inertia");
+ Cursor old_camera_cursor = camera_cursor;
+ camera_cursor = cursor;
- float zoom_inertia = EDITOR_GET("editors/3d/navigation_feel/zoom_inertia");
+ if (p_interp_delta > 0) {
- //determine if being manipulated
- bool manipulated = (Input::get_singleton()->get_mouse_button_mask() & (2 | 4)) || Input::get_singleton()->is_key_pressed(KEY_SHIFT) || Input::get_singleton()->is_key_pressed(KEY_ALT) || Input::get_singleton()->is_key_pressed(KEY_CONTROL);
+ //-------
+ // Perform smoothing
- float orbit_inertia = MAX(0.00001, manipulated ? manip_orbit_inertia : free_orbit_inertia);
- float translation_inertia = MAX(0.0001, manipulated ? manip_translation_inertia : free_translation_inertia);
+ if (is_freelook_active()) {
- Cursor old_camera_cursor = camera_cursor;
- camera_cursor = cursor;
+ // Higher inertia should increase "lag" (lerp with factor between 0 and 1)
+ // Inertia of zero should produce instant movement (lerp with factor of 1) in this case it returns a really high value and gets clamped to 1.
+ real_t inertia = EDITOR_GET("editors/3d/freelook/freelook_inertia");
+ inertia = MAX(0.001, inertia);
+ real_t factor = (1.0 / inertia) * p_interp_delta;
+
+ // We interpolate a different point here, because in freelook mode the focus point (cursor.pos) orbits around eye_pos
+ camera_cursor.eye_pos = old_camera_cursor.eye_pos.linear_interpolate(cursor.eye_pos, CLAMP(factor, 0, 1));
+ //camera_cursor.pos = camera_cursor.eye_pos + (cursor.pos - cursor.eye_pos);
+
+ float orbit_inertia = EDITOR_GET("editors/3d/navigation_feel/orbit_inertia");
+ orbit_inertia = MAX(0.0001, orbit_inertia);
+ camera_cursor.x_rot = Math::lerp(old_camera_cursor.x_rot, cursor.x_rot, MIN(1.f, p_interp_delta * (1 / orbit_inertia)));
+ camera_cursor.y_rot = Math::lerp(old_camera_cursor.y_rot, cursor.y_rot, MIN(1.f, p_interp_delta * (1 / orbit_inertia)));
+
+ Vector3 forward = to_camera_transform(camera_cursor).basis.xform(Vector3(0, 0, -1));
+ camera_cursor.pos = camera_cursor.eye_pos + forward * camera_cursor.distance;
+
+ } else {
+
+ //when not being manipulated, move softly
+ float free_orbit_inertia = EDITOR_GET("editors/3d/navigation_feel/orbit_inertia");
+ float free_translation_inertia = EDITOR_GET("editors/3d/navigation_feel/translation_inertia");
+ //when being manipulated, move more quickly
+ float manip_orbit_inertia = EDITOR_GET("editors/3d/navigation_feel/manipulation_orbit_inertia");
+ float manip_translation_inertia = EDITOR_GET("editors/3d/navigation_feel/manipulation_translation_inertia");
+
+ float zoom_inertia = EDITOR_GET("editors/3d/navigation_feel/zoom_inertia");
+
+ //determine if being manipulated
+ bool manipulated = Input::get_singleton()->get_mouse_button_mask() & (2 | 4);
+ manipulated |= Input::get_singleton()->is_key_pressed(KEY_SHIFT);
+ manipulated |= Input::get_singleton()->is_key_pressed(KEY_ALT);
+ manipulated |= Input::get_singleton()->is_key_pressed(KEY_CONTROL);
- camera_cursor.x_rot = Math::lerp(old_camera_cursor.x_rot, cursor.x_rot, MIN(1.f, p_interp_delta * (1 / orbit_inertia)));
- camera_cursor.y_rot = Math::lerp(old_camera_cursor.y_rot, cursor.y_rot, MIN(1.f, p_interp_delta * (1 / orbit_inertia)));
+ float orbit_inertia = MAX(0.00001, manipulated ? manip_orbit_inertia : free_orbit_inertia);
+ float translation_inertia = MAX(0.0001, manipulated ? manip_translation_inertia : free_translation_inertia);
+ zoom_inertia = MAX(0.0001, zoom_inertia);
- camera_cursor.pos = old_camera_cursor.pos.linear_interpolate(cursor.pos, MIN(1.f, p_interp_delta * (1 / translation_inertia)));
- camera_cursor.distance = Math::lerp(old_camera_cursor.distance, cursor.distance, MIN(1.f, p_interp_delta * (1 / zoom_inertia)));
+ camera_cursor.x_rot = Math::lerp(old_camera_cursor.x_rot, cursor.x_rot, MIN(1.f, p_interp_delta * (1 / orbit_inertia)));
+ camera_cursor.y_rot = Math::lerp(old_camera_cursor.y_rot, cursor.y_rot, MIN(1.f, p_interp_delta * (1 / orbit_inertia)));
- if (p_interp_delta == 0 || is_freelook_active()) {
- camera_cursor = cursor;
+ camera_cursor.pos = old_camera_cursor.pos.linear_interpolate(cursor.pos, MIN(1.f, p_interp_delta * (1 / translation_inertia)));
+ camera_cursor.distance = Math::lerp(old_camera_cursor.distance, cursor.distance, MIN(1.f, p_interp_delta * (1 / zoom_inertia)));
+ }
}
+ //-------
+ // Apply camera transform
+
float tolerance = 0.001;
bool equal = true;
if (Math::abs(old_camera_cursor.x_rot - camera_cursor.x_rot) > tolerance || Math::abs(old_camera_cursor.y_rot - camera_cursor.y_rot) > tolerance) {
@@ -234,12 +267,12 @@ Vector3 SpatialEditorViewport::_get_camera_position() const {
Point2 SpatialEditorViewport::_point_to_screen(const Vector3 &p_point) {
- return camera->unproject_position(p_point);
+ return camera->unproject_position(p_point) * viewport_container->get_stretch_shrink();
}
Vector3 SpatialEditorViewport::_get_ray_pos(const Vector2 &p_pos) const {
- return camera->project_ray_origin(p_pos);
+ return camera->project_ray_origin(p_pos / viewport_container->get_stretch_shrink());
}
Vector3 SpatialEditorViewport::_get_camera_normal() const {
@@ -249,7 +282,7 @@ Vector3 SpatialEditorViewport::_get_camera_normal() const {
Vector3 SpatialEditorViewport::_get_ray(const Vector2 &p_pos) const {
- return camera->project_ray_normal(p_pos);
+ return camera->project_ray_normal(p_pos / viewport_container->get_stretch_shrink());
}
/*
void SpatialEditorViewport::_clear_id(Spatial *p_node) {
@@ -725,17 +758,49 @@ bool SpatialEditorViewport::_gizmo_select(const Vector2 &p_screenpos, bool p_hig
}
}
+ bool is_plane_scale = false;
+ // plane select
+ if (col_axis == -1) {
+ col_d = 1e20;
+
+ for (int i = 0; i < 3; i++) {
+
+ Vector3 ivec2 = gt.basis.get_axis((i + 1) % 3).normalized();
+ Vector3 ivec3 = gt.basis.get_axis((i + 2) % 3).normalized();
+
+ Vector3 grabber_pos = gt.origin + (ivec2 + ivec3) * gs * (GIZMO_PLANE_SIZE + GIZMO_PLANE_DST);
+
+ Vector3 r;
+ Plane plane(gt.origin, gt.basis.get_axis(i).normalized());
+
+ if (plane.intersects_ray(ray_pos, ray, &r)) {
+
+ float dist = r.distance_to(grabber_pos);
+ if (dist < (gs * GIZMO_PLANE_SIZE)) {
+
+ float d = ray_pos.distance_to(r);
+ if (d < col_d) {
+ col_d = d;
+ col_axis = i;
+
+ is_plane_scale = true;
+ }
+ }
+ }
+ }
+ }
+
if (col_axis != -1) {
if (p_highlight_only) {
- spatial_editor->select_gizmo_highlight_axis(col_axis + 9);
+ spatial_editor->select_gizmo_highlight_axis(col_axis + (is_plane_scale ? 12 : 9));
} else {
//handle scale
_edit.mode = TRANSFORM_SCALE;
_compute_edit(Point2(p_screenpos.x, p_screenpos.y));
- _edit.plane = TransformPlane(TRANSFORM_X_AXIS + col_axis);
+ _edit.plane = TransformPlane(TRANSFORM_X_AXIS + col_axis + (is_plane_scale ? 3 : 0));
}
return true;
}
@@ -814,6 +879,7 @@ void SpatialEditorViewport::_list_select(Ref<InputEventMouseButton> b) {
selection_menu->set_invalidate_click_until_motion();
}
}
+
void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
if (previewing)
@@ -845,11 +911,17 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
switch (b->get_button_index()) {
case BUTTON_WHEEL_UP: {
- scale_cursor_distance(is_freelook_active() ? zoom_factor : 1.0 / zoom_factor);
+ if (is_freelook_active())
+ scale_freelook_speed(zoom_factor);
+ else
+ scale_cursor_distance(1.0 / zoom_factor);
} break;
case BUTTON_WHEEL_DOWN: {
- scale_cursor_distance(is_freelook_active() ? 1.0 / zoom_factor : zoom_factor);
+ if (is_freelook_active())
+ scale_freelook_speed(1.0 / zoom_factor);
+ else
+ scale_cursor_distance(zoom_factor);
} break;
case BUTTON_RIGHT: {
@@ -901,10 +973,10 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
if (b->is_pressed()) {
int mod = _get_key_modifier(b);
if (mod == _get_key_modifier_setting("editors/3d/freelook/freelook_activation_modifier")) {
- freelook_active = true;
+ set_freelook_active(true);
}
} else {
- freelook_active = false;
+ set_freelook_active(false);
}
if (freelook_active && !surface->has_focus()) {
@@ -1025,7 +1097,7 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
if (get_selected_count() == 0)
break; //bye
- //handle rotate
+ //handle scale
_edit.mode = TRANSFORM_SCALE;
_compute_edit(b->get_position());
break;
@@ -1215,7 +1287,7 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
Vector3 motion_mask;
Plane plane;
- bool plane_mv;
+ bool plane_mv = false;
switch (_edit.plane) {
case TRANSFORM_VIEW:
@@ -1234,6 +1306,21 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
motion_mask = spatial_editor->get_gizmo_transform().basis.get_axis(2);
plane = Plane(_edit.center, motion_mask.cross(motion_mask.cross(_get_camera_normal())).normalized());
break;
+ case TRANSFORM_YZ:
+ motion_mask = spatial_editor->get_gizmo_transform().basis.get_axis(2) + spatial_editor->get_gizmo_transform().basis.get_axis(1);
+ plane = Plane(_edit.center, spatial_editor->get_gizmo_transform().basis.get_axis(0));
+ plane_mv = true;
+ break;
+ case TRANSFORM_XZ:
+ motion_mask = spatial_editor->get_gizmo_transform().basis.get_axis(2) + spatial_editor->get_gizmo_transform().basis.get_axis(0);
+ plane = Plane(_edit.center, spatial_editor->get_gizmo_transform().basis.get_axis(1));
+ plane_mv = true;
+ break;
+ case TRANSFORM_XY:
+ motion_mask = spatial_editor->get_gizmo_transform().basis.get_axis(0) + spatial_editor->get_gizmo_transform().basis.get_axis(1);
+ plane = Plane(_edit.center, spatial_editor->get_gizmo_transform().basis.get_axis(2));
+ plane_mv = true;
+ break;
}
Vector3 intersection;
@@ -1245,12 +1332,21 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
break;
Vector3 motion = intersection - click;
- print_line(String(intersection) + " --- " + String(click));
- if (motion_mask != Vector3()) {
+ if (_edit.plane != TRANSFORM_VIEW) {
- motion = motion_mask.dot(motion) * motion_mask;
- } else {
+ if (!plane_mv) {
+
+ motion = motion_mask.dot(motion) * motion_mask;
+
+ } else {
+
+ // Alternative planar scaling mode
+ if (_get_key_modifier(m) != KEY_SHIFT) {
+ motion = motion_mask.dot(motion) * motion_mask;
+ }
+ }
+ } else {
float center_click_dist = click.distance_to(_edit.center);
float center_inters_dist = intersection.distance_to(_edit.center);
if (center_click_dist == 0)
@@ -1262,12 +1358,19 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
List<Node *> &selection = editor_selection->get_selected_node_list();
- bool local_coords = (spatial_editor->are_local_coords_enabled() && motion_mask != Vector3()); // Disable local transformation for TRANSFORM_VIEW
+ bool local_coords = (spatial_editor->are_local_coords_enabled() && _edit.plane != TRANSFORM_VIEW); // Disable local transformation for TRANSFORM_VIEW
float snap = 0;
if (_edit.snap || spatial_editor->is_snap_enabled()) {
snap = spatial_editor->get_scale_snap() / 100;
+
+ Vector3 motion_snapped = motion;
+ motion_snapped.snap(Vector3(snap, snap, snap));
+ set_message(TTR("Scaling: ") + motion_snapped);
+
+ } else {
+ set_message(TTR("Scaling: ") + motion);
}
for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
@@ -1282,6 +1385,10 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
continue;
}
+ if (sp->has_meta("_edit_lock_")) {
+ continue;
+ }
+
Transform original = se->original;
Transform original_local = se->original_local;
Transform base = Transform(Basis(), _edit.center);
@@ -1299,6 +1406,15 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
local_scale = original_local.basis.get_scale() * (local_motion + Vector3(1, 1, 1));
+ // Prevent scaling to 0 it would break the gizmo
+ Basis check = original_local.basis;
+ check.scale(local_scale);
+ if (check.determinant() != 0) {
+
+ // Apply scale
+ sp->set_scale(local_scale);
+ }
+
} else {
if (_edit.snap || spatial_editor->is_snap_enabled()) {
@@ -1308,12 +1424,8 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
Transform r;
r.basis.scale(motion + Vector3(1, 1, 1));
t = base * (r * (base.inverse() * original));
- }
- // Apply scale
- if (local_coords) {
- sp->set_scale(local_scale);
- } else {
+ // Apply scale
sp->set_global_transform(t);
}
}
@@ -1326,11 +1438,10 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
Vector3 motion_mask;
Plane plane;
- bool plane_mv;
+ bool plane_mv = false;
switch (_edit.plane) {
case TRANSFORM_VIEW:
- motion_mask = Vector3(0, 0, 0);
plane = Plane(_edit.center, _get_camera_normal());
break;
case TRANSFORM_X_AXIS:
@@ -1346,17 +1457,14 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
plane = Plane(_edit.center, motion_mask.cross(motion_mask.cross(_get_camera_normal())).normalized());
break;
case TRANSFORM_YZ:
- motion_mask = spatial_editor->get_gizmo_transform().basis.get_axis(2) + spatial_editor->get_gizmo_transform().basis.get_axis(1);
plane = Plane(_edit.center, spatial_editor->get_gizmo_transform().basis.get_axis(0));
plane_mv = true;
break;
case TRANSFORM_XZ:
- motion_mask = spatial_editor->get_gizmo_transform().basis.get_axis(2) + spatial_editor->get_gizmo_transform().basis.get_axis(0);
plane = Plane(_edit.center, spatial_editor->get_gizmo_transform().basis.get_axis(1));
plane_mv = true;
break;
case TRANSFORM_XY:
- motion_mask = spatial_editor->get_gizmo_transform().basis.get_axis(0) + spatial_editor->get_gizmo_transform().basis.get_axis(1);
plane = Plane(_edit.center, spatial_editor->get_gizmo_transform().basis.get_axis(2));
plane_mv = true;
break;
@@ -1370,55 +1478,27 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
if (!plane.intersects_ray(_edit.click_ray_pos, _edit.click_ray, &click))
break;
- //_validate_selection();
Vector3 motion = intersection - click;
- if (motion_mask != Vector3()) {
- if (plane_mv)
- motion *= motion_mask;
- else
+ if (_edit.plane != TRANSFORM_VIEW) {
+ if (!plane_mv) {
motion = motion_mask.dot(motion) * motion_mask;
+ }
}
- //set_message("Translating: "+motion);
-
List<Node *> &selection = editor_selection->get_selected_node_list();
- float snap = 0;
+ bool local_coords = (spatial_editor->are_local_coords_enabled() && _edit.plane != TRANSFORM_VIEW); // Disable local transformation for TRANSFORM_VIEW
+ float snap = 0;
if (_edit.snap || spatial_editor->is_snap_enabled()) {
snap = spatial_editor->get_translate_snap();
- bool local_coords = spatial_editor->are_local_coords_enabled();
- if (local_coords) {
- bool multiple = false;
- Spatial *node = NULL;
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
-
- Spatial *sp = Object::cast_to<Spatial>(E->get());
- if (!sp) {
- continue;
- }
- if (node) {
- multiple = true;
- break;
- } else {
- node = sp;
- }
- }
-
- if (multiple) {
- motion.snap(Vector3(snap, snap, snap));
- } else {
- Basis b = node->get_global_transform().basis.orthonormalized();
- Vector3 local_motion = b.inverse().xform(motion);
- local_motion.snap(Vector3(snap, snap, snap));
- motion = b.xform(local_motion);
- }
-
- } else {
- motion.snap(Vector3(snap, snap, snap));
- }
+ Vector3 motion_snapped = motion;
+ motion_snapped.snap(Vector3(snap, snap, snap));
+ set_message(TTR("Translating: ") + motion_snapped);
+ } else {
+ set_message(TTR("Translating: ") + motion);
}
for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
@@ -1433,15 +1513,44 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
continue;
}
- Transform t = se->original;
+ if (sp->has_meta("_edit_lock_")) {
+ continue;
+ }
+
+ Transform original = se->original;
+ Transform t;
+
+ if (local_coords) {
+
+ if (_edit.snap || spatial_editor->is_snap_enabled()) {
+ Basis g = original.basis.orthonormalized();
+ Vector3 local_motion = g.inverse().xform(motion);
+ local_motion.snap(Vector3(snap, snap, snap));
+
+ motion = g.xform(local_motion);
+ }
+
+ } else {
+
+ if (_edit.snap || spatial_editor->is_snap_enabled()) {
+ motion.snap(Vector3(snap, snap, snap));
+ }
+ }
+
+ // Apply translation
+ t = original;
t.origin += motion;
sp->set_global_transform(t);
}
+
+ surface->update();
+
} break;
case TRANSFORM_ROTATE: {
Plane plane;
+ Vector3 axis;
switch (_edit.plane) {
case TRANSFORM_VIEW:
@@ -1449,12 +1558,15 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
break;
case TRANSFORM_X_AXIS:
plane = Plane(_edit.center, spatial_editor->get_gizmo_transform().basis.get_axis(0));
+ axis = Vector3(1, 0, 0);
break;
case TRANSFORM_Y_AXIS:
plane = Plane(_edit.center, spatial_editor->get_gizmo_transform().basis.get_axis(1));
+ axis = Vector3(0, 1, 0);
break;
case TRANSFORM_Z_AXIS:
plane = Plane(_edit.center, spatial_editor->get_gizmo_transform().basis.get_axis(2));
+ axis = Vector3(0, 0, 1);
break;
}
@@ -1470,6 +1582,7 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
Vector3 x_axis = plane.normal.cross(y_axis).normalized();
float angle = Math::atan2(x_axis.dot(intersection - _edit.center), y_axis.dot(intersection - _edit.center));
+
if (_edit.snap || spatial_editor->is_snap_enabled()) {
float snap = spatial_editor->get_rotate_snap();
@@ -1486,11 +1599,10 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
set_message(vformat(TTR("Rotating %s degrees."), rtos(Math::rad2deg(angle))));
}
- Transform r;
- r.basis.rotate(plane.normal, angle);
-
List<Node *> &selection = editor_selection->get_selected_node_list();
+ bool local_coords = (spatial_editor->are_local_coords_enabled() && _edit.plane != TRANSFORM_VIEW); // Disable local transformation for TRANSFORM_VIEW
+
for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
Spatial *sp = Object::cast_to<Spatial>(E->get());
@@ -1501,33 +1613,46 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
if (!se)
continue;
- Transform original = se->original;
+ if (sp->has_meta("_edit_lock_")) {
+ continue;
+ }
- Transform base = Transform(Basis(), _edit.center);
- Transform t = base * r * base.inverse() * original;
+ Transform t;
- sp->set_global_transform(t);
+ if (local_coords) {
+
+ Transform original_local = se->original_local;
+ Basis rot = Basis(axis, angle);
+
+ t.basis = original_local.get_basis().orthonormalized() * rot;
+ t.origin = original_local.origin;
+
+ // Apply rotation
+ sp->set_transform(t);
+ sp->set_scale(original_local.basis.get_scale()); // re-apply original scale
+
+ } else {
+
+ Transform original = se->original;
+ Transform r;
+ Transform base = Transform(Basis(), _edit.center);
+
+ r.basis.rotate(plane.normal, angle);
+ t = base * r * base.inverse() * original;
+
+ // Apply rotation
+ sp->set_global_transform(t);
+ }
}
surface->update();
- /*
- VisualServer::get_singleton()->poly_clear(indicators);
-
- Vector<Vector3> points;
- Vector<Vector3> empty;
- Vector<Color> colors;
- points.push_back(intersection);
- points.push_back(_edit.original.origin);
- colors.push_back( Color(255,155,100) );
- colors.push_back( Color(255,155,100) );
- VisualServer::get_singleton()->poly_add_primitive(indicators,points,empty,colors,empty);
- */
+
} break;
default: {}
}
}
- } else if (m->get_button_mask() & BUTTON_MASK_RIGHT) {
+ } else if ((m->get_button_mask() & BUTTON_MASK_RIGHT) || freelook_active) {
if (nav_scheme == NAVIGATION_MAYA && m->get_alt()) {
nav_mode = NAVIGATION_ZOOM;
@@ -1569,89 +1694,78 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
switch (nav_mode) {
case NAVIGATION_PAN: {
+ _nav_pan(m, _get_warped_mouse_motion(m));
+
+ } break;
+
+ case NAVIGATION_ZOOM: {
+ _nav_zoom(m, m->get_relative());
+
+ } break;
+
+ case NAVIGATION_ORBIT: {
+ _nav_orbit(m, _get_warped_mouse_motion(m));
+
+ } break;
+
+ case NAVIGATION_LOOK: {
+ _nav_look(m, _get_warped_mouse_motion(m));
+
+ } break;
- real_t pan_speed = 1 / 150.0;
- int pan_speed_modifier = 10;
- if (nav_scheme == NAVIGATION_MAYA && m->get_shift())
- pan_speed *= pan_speed_modifier;
+ default: {}
+ }
+ }
+
+ Ref<InputEventMagnifyGesture> magnify_gesture = p_event;
+ if (magnify_gesture.is_valid()) {
+
+ if (is_freelook_active())
+ scale_freelook_speed(magnify_gesture->get_factor());
+ else
+ scale_cursor_distance(1.0 / magnify_gesture->get_factor());
+ }
- Point2i relative = _get_warped_mouse_motion(m);
+ Ref<InputEventPanGesture> pan_gesture = p_event;
+ if (pan_gesture.is_valid()) {
- Transform camera_transform;
+ NavigationScheme nav_scheme = (NavigationScheme)EditorSettings::get_singleton()->get("editors/3d/navigation/navigation_scheme").operator int();
+ NavigationMode nav_mode = NAVIGATION_NONE;
+
+ if (nav_scheme == NAVIGATION_GODOT) {
- camera_transform.translate(cursor.pos);
- camera_transform.basis.rotate(Vector3(1, 0, 0), -cursor.x_rot);
- camera_transform.basis.rotate(Vector3(0, 1, 0), -cursor.y_rot);
- Vector3 translation(-relative.x * pan_speed, relative.y * pan_speed, 0);
- translation *= cursor.distance / DISTANCE_DEFAULT;
- camera_transform.translate(translation);
- cursor.pos = camera_transform.origin;
+ int mod = _get_key_modifier(pan_gesture);
+
+ if (mod == _get_key_modifier_setting("editors/3d/navigation/pan_modifier"))
+ nav_mode = NAVIGATION_PAN;
+ else if (mod == _get_key_modifier_setting("editors/3d/navigation/zoom_modifier"))
+ nav_mode = NAVIGATION_ZOOM;
+ else if (mod == _get_key_modifier_setting("editors/3d/navigation/orbit_modifier"))
+ nav_mode = NAVIGATION_ORBIT;
+
+ } else if (nav_scheme == NAVIGATION_MAYA) {
+ if (pan_gesture->get_alt())
+ nav_mode = NAVIGATION_PAN;
+ }
+
+ switch (nav_mode) {
+ case NAVIGATION_PAN: {
+ _nav_pan(m, pan_gesture->get_delta());
} break;
case NAVIGATION_ZOOM: {
- real_t zoom_speed = 1 / 80.0;
- int zoom_speed_modifier = 10;
- if (nav_scheme == NAVIGATION_MAYA && m->get_shift())
- zoom_speed *= zoom_speed_modifier;
-
- NavigationZoomStyle zoom_style = (NavigationZoomStyle)EditorSettings::get_singleton()->get("editors/3d/navigation/zoom_style").operator int();
- if (zoom_style == NAVIGATION_ZOOM_HORIZONTAL) {
- if (m->get_relative().x > 0)
- scale_cursor_distance(1 - m->get_relative().x * zoom_speed);
- else if (m->get_relative().x < 0)
- scale_cursor_distance(1.0 / (1 + m->get_relative().x * zoom_speed));
- } else {
- if (m->get_relative().y > 0)
- scale_cursor_distance(1 + m->get_relative().y * zoom_speed);
- else if (m->get_relative().y < 0)
- scale_cursor_distance(1.0 / (1 - m->get_relative().y * zoom_speed));
- }
+ _nav_zoom(m, pan_gesture->get_delta());
} break;
case NAVIGATION_ORBIT: {
- Point2i relative = _get_warped_mouse_motion(m);
-
- real_t degrees_per_pixel = EditorSettings::get_singleton()->get("editors/3d/navigation_feel/orbit_sensitivity");
- real_t radians_per_pixel = Math::deg2rad(degrees_per_pixel);
-
- cursor.x_rot += relative.y * radians_per_pixel;
- cursor.y_rot += relative.x * radians_per_pixel;
- if (cursor.x_rot > Math_PI / 2.0)
- cursor.x_rot = Math_PI / 2.0;
- if (cursor.x_rot < -Math_PI / 2.0)
- cursor.x_rot = -Math_PI / 2.0;
- name = "";
- _update_name();
+ _nav_orbit(m, pan_gesture->get_delta());
+
} break;
case NAVIGATION_LOOK: {
- // Freelook only works properly in perspective.
- // It technically works too in ortho, but it's awful for a user due to fov being near zero
- if (!orthogonal) {
- Point2i relative = _get_warped_mouse_motion(m);
-
- real_t degrees_per_pixel = EditorSettings::get_singleton()->get("editors/3d/navigation_feel/orbit_sensitivity");
- real_t radians_per_pixel = Math::deg2rad(degrees_per_pixel);
-
- cursor.x_rot += relative.y * radians_per_pixel;
- cursor.y_rot += relative.x * radians_per_pixel;
- if (cursor.x_rot > Math_PI / 2.0)
- cursor.x_rot = Math_PI / 2.0;
- if (cursor.x_rot < -Math_PI / 2.0)
- cursor.x_rot = -Math_PI / 2.0;
-
- // Look is like Orbit, except the cursor translates, not the camera
- Transform camera_transform = to_camera_transform(cursor);
- Vector3 pos = camera_transform.xform(Vector3(0, 0, 0));
- Vector3 diff = camera->get_translation() - pos;
- cursor.pos += diff;
- freelook_target_position += diff;
-
- name = "";
- _update_name();
- }
+ _nav_look(m, pan_gesture->get_delta());
} break;
@@ -1739,10 +1853,142 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
set_message(TTR("Animation Key Inserted."));
}
+ if (ED_IS_SHORTCUT("spatial_editor/freelook_toggle", p_event)) {
+ set_freelook_active(!is_freelook_active());
+
+ } else if (k->get_scancode() == KEY_ESCAPE) {
+ set_freelook_active(false);
+ }
+
if (k->get_scancode() == KEY_SPACE) {
if (!k->is_pressed()) emit_signal("toggle_maximize_view", this);
}
}
+
+ // freelook uses most of the useful shortcuts, like save, so its ok
+ // to consider freelook active as end of the line for future events.
+ if (freelook_active)
+ accept_event();
+}
+
+void SpatialEditorViewport::_nav_pan(Ref<InputEventWithModifiers> p_event, const Vector2 &p_relative) {
+
+ const NavigationScheme nav_scheme = (NavigationScheme)EditorSettings::get_singleton()->get("editors/3d/navigation/navigation_scheme").operator int();
+
+ real_t pan_speed = 1 / 150.0;
+ int pan_speed_modifier = 10;
+ if (nav_scheme == NAVIGATION_MAYA && p_event->get_shift())
+ pan_speed *= pan_speed_modifier;
+
+ Transform camera_transform;
+
+ camera_transform.translate(cursor.pos);
+ camera_transform.basis.rotate(Vector3(1, 0, 0), -cursor.x_rot);
+ camera_transform.basis.rotate(Vector3(0, 1, 0), -cursor.y_rot);
+ Vector3 translation(-p_relative.x * pan_speed, p_relative.y * pan_speed, 0);
+ translation *= cursor.distance / DISTANCE_DEFAULT;
+ camera_transform.translate(translation);
+ cursor.pos = camera_transform.origin;
+}
+
+void SpatialEditorViewport::_nav_zoom(Ref<InputEventWithModifiers> p_event, const Vector2 &p_relative) {
+
+ const NavigationScheme nav_scheme = (NavigationScheme)EditorSettings::get_singleton()->get("editors/3d/navigation/navigation_scheme").operator int();
+
+ real_t zoom_speed = 1 / 80.0;
+ int zoom_speed_modifier = 10;
+ if (nav_scheme == NAVIGATION_MAYA && p_event->get_shift())
+ zoom_speed *= zoom_speed_modifier;
+
+ NavigationZoomStyle zoom_style = (NavigationZoomStyle)EditorSettings::get_singleton()->get("editors/3d/navigation/zoom_style").operator int();
+ if (zoom_style == NAVIGATION_ZOOM_HORIZONTAL) {
+ if (p_relative.x > 0)
+ scale_cursor_distance(1 - p_relative.x * zoom_speed);
+ else if (p_relative.x < 0)
+ scale_cursor_distance(1.0 / (1 + p_relative.x * zoom_speed));
+ } else {
+ if (p_relative.y > 0)
+ scale_cursor_distance(1 + p_relative.y * zoom_speed);
+ else if (p_relative.y < 0)
+ scale_cursor_distance(1.0 / (1 - p_relative.y * zoom_speed));
+ }
+}
+
+void SpatialEditorViewport::_nav_orbit(Ref<InputEventWithModifiers> p_event, const Vector2 &p_relative) {
+
+ real_t degrees_per_pixel = EditorSettings::get_singleton()->get("editors/3d/navigation_feel/orbit_sensitivity");
+ real_t radians_per_pixel = Math::deg2rad(degrees_per_pixel);
+
+ cursor.x_rot += p_relative.y * radians_per_pixel;
+ cursor.y_rot += p_relative.x * radians_per_pixel;
+ if (cursor.x_rot > Math_PI / 2.0)
+ cursor.x_rot = Math_PI / 2.0;
+ if (cursor.x_rot < -Math_PI / 2.0)
+ cursor.x_rot = -Math_PI / 2.0;
+ name = "";
+ _update_name();
+}
+
+void SpatialEditorViewport::_nav_look(Ref<InputEventWithModifiers> p_event, const Vector2 &p_relative) {
+
+ // Freelook only works properly in perspective.
+ // It technically works too in ortho, but it's awful for a user due to fov being near zero
+ if (!orthogonal) {
+ real_t degrees_per_pixel = EditorSettings::get_singleton()->get("editors/3d/navigation_feel/orbit_sensitivity");
+ real_t radians_per_pixel = Math::deg2rad(degrees_per_pixel);
+
+ // Note: do NOT assume the camera has the "current" transform, because it is interpolated and may have "lag".
+ Transform prev_camera_transform = to_camera_transform(cursor);
+
+ cursor.x_rot += p_relative.y * radians_per_pixel;
+ cursor.y_rot += p_relative.x * radians_per_pixel;
+ if (cursor.x_rot > Math_PI / 2.0)
+ cursor.x_rot = Math_PI / 2.0;
+ if (cursor.x_rot < -Math_PI / 2.0)
+ cursor.x_rot = -Math_PI / 2.0;
+
+ // Look is like the opposite of Orbit: the focus point rotates around the camera
+ Transform camera_transform = to_camera_transform(cursor);
+ Vector3 pos = camera_transform.xform(Vector3(0, 0, 0));
+ Vector3 prev_pos = prev_camera_transform.xform(Vector3(0, 0, 0));
+ Vector3 diff = prev_pos - pos;
+ cursor.pos += diff;
+
+ name = "";
+ _update_name();
+ }
+}
+
+void SpatialEditorViewport::set_freelook_active(bool active_now) {
+
+ if (!freelook_active && active_now) {
+ // Sync camera cursor to cursor to "cut" interpolation jumps due to changing referential
+ cursor = camera_cursor;
+
+ // Make sure eye_pos is synced, because freelook referential is eye pos rather than orbit pos
+ Vector3 forward = to_camera_transform(cursor).basis.xform(Vector3(0, 0, -1));
+ cursor.eye_pos = cursor.pos - cursor.distance * forward;
+ // Also sync the camera cursor, otherwise switching to freelook will be trippy if inertia is active
+ camera_cursor.eye_pos = cursor.eye_pos;
+
+ if (EditorSettings::get_singleton()->get("editors/3d/freelook/freelook_speed_zoom_link")) {
+ // Re-adjust freelook speed from the current zoom level
+ real_t base_speed = EditorSettings::get_singleton()->get("editors/3d/freelook/freelook_base_speed");
+ freelook_speed = base_speed * cursor.distance;
+ }
+
+ // Hide mouse like in an FPS (warping doesn't work)
+ OS::get_singleton()->set_mouse_mode(OS::MOUSE_MODE_CAPTURED);
+
+ } else if (freelook_active && !active_now) {
+ // Sync camera cursor to cursor to "cut" interpolation jumps due to changing referential
+ cursor = camera_cursor;
+
+ // Restore mouse
+ OS::get_singleton()->set_mouse_mode(OS::MOUSE_MODE_VISIBLE);
+ }
+
+ freelook_active = active_now;
}
void SpatialEditorViewport::scale_cursor_distance(real_t scale) {
@@ -1751,17 +1997,25 @@ void SpatialEditorViewport::scale_cursor_distance(real_t scale) {
if (cursor.distance < ZOOM_MIN_DISTANCE)
cursor.distance = ZOOM_MIN_DISTANCE;
- real_t prev_distance = cursor.distance;
cursor.distance *= scale;
if (cursor.distance < ZOOM_MIN_DISTANCE)
cursor.distance = ZOOM_MIN_DISTANCE;
- if (is_freelook_active()) {
- // In freelook mode, cursor reference is reversed so it needs to be adjusted
- Vector3 forward = camera->get_transform().basis.xform(Vector3(0, 0, -1));
- cursor.pos += (cursor.distance - prev_distance) * forward;
- }
+ zoom_indicator_delay = ZOOM_INDICATOR_DELAY_S;
+ surface->update();
+}
+
+void SpatialEditorViewport::scale_freelook_speed(real_t scale) {
+
+ // Prevents zero distance which would short-circuit any scaling
+ if (freelook_speed < FREELOOK_MIN_SPEED)
+ freelook_speed = FREELOOK_MIN_SPEED;
+
+ freelook_speed *= scale;
+
+ if (freelook_speed < FREELOOK_MIN_SPEED)
+ freelook_speed = FREELOOK_MIN_SPEED;
zoom_indicator_delay = ZOOM_INDICATOR_DELAY_S;
surface->update();
@@ -1780,7 +2034,6 @@ Point2i SpatialEditorViewport::_get_warped_mouse_motion(const Ref<InputEventMous
void SpatialEditorViewport::_update_freelook(real_t delta) {
if (!is_freelook_active()) {
- freelook_target_position = cursor.pos;
return;
}
@@ -1823,21 +2076,15 @@ void SpatialEditorViewport::_update_freelook(real_t delta) {
speed_modifier = true;
}
- real_t inertia = EDITOR_DEF("editors/3d/freelook/freelook_inertia", 0.1);
- inertia = MAX(0, inertia);
- const real_t base_speed = EDITOR_DEF("editors/3d/freelook/freelook_base_speed", 0.5);
- const real_t modifier_speed_factor = EDITOR_DEF("editors/3d/freelook/freelook_modifier_speed_factor", 3);
-
- real_t speed = base_speed * cursor.distance;
- if (speed_modifier)
+ real_t speed = freelook_speed;
+ if (speed_modifier) {
+ real_t modifier_speed_factor = EditorSettings::get_singleton()->get("editors/3d/freelook/freelook_modifier_speed_factor");
speed *= modifier_speed_factor;
+ }
- // Higher inertia should increase "lag" (lerp with factor between 0 and 1)
- // Inertia of zero should produce instant movement (lerp with factor of 1) in this case it returns a really high value and gets clamped to 1.
-
- freelook_target_position += direction * speed;
- real_t factor = (1.0 / (inertia + 0.001)) * delta;
- cursor.pos = cursor.pos.linear_interpolate(freelook_target_position, CLAMP(factor, 0, 1));
+ Vector3 motion = direction * speed * delta;
+ cursor.pos += motion;
+ cursor.eye_pos += motion;
}
void SpatialEditorViewport::set_message(String p_message, float p_time) {
@@ -1876,7 +2123,7 @@ void SpatialEditorViewport::_notification(int p_what) {
}
*/
- real_t delta = get_tree()->get_idle_process_time();
+ real_t delta = get_process_delta_time();
if (zoom_indicator_delay > 0) {
zoom_indicator_delay -= delta;
@@ -1887,7 +2134,7 @@ void SpatialEditorViewport::_notification(int p_what) {
_update_freelook(delta);
- _update_camera(get_process_delta_time());
+ _update_camera(delta);
Map<Node *, Object *> &selection = editor_selection->get_selection();
@@ -1908,7 +2155,7 @@ void SpatialEditorViewport::_notification(int p_what) {
if (se->aabb.has_no_surface()) {
- se->aabb = vi ? vi->get_aabb() : Rect3(Vector3(-0.2, -0.2, -0.2), Vector3(0.4, 0.4, 0.4));
+ se->aabb = vi ? vi->get_aabb() : AABB(Vector3(-0.2, -0.2, -0.2), Vector3(0.4, 0.4, 0.4));
}
Transform t = sp->get_global_transform();
@@ -1957,6 +2204,12 @@ void SpatialEditorViewport::_notification(int p_what) {
viewport->set_shadow_atlas_quadrant_subdiv(2, Viewport::ShadowAtlasQuadrantSubdiv(atlas_q2));
viewport->set_shadow_atlas_quadrant_subdiv(3, Viewport::ShadowAtlasQuadrantSubdiv(atlas_q3));
+ bool shrink = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(VIEW_HALF_RESOLUTION));
+
+ if (shrink != viewport_container->get_stretch_shrink() > 1) {
+ viewport_container->set_stretch_shrink(shrink ? 2 : 1);
+ }
+
//update msaa if changed
int msaa_mode = ProjectSettings::get_singleton()->get("rendering/quality/filters/msaa");
@@ -1990,6 +2243,29 @@ void SpatialEditorViewport::_notification(int p_what) {
}
}
+ // FPS Counter.
+ bool show_fps = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(VIEW_FPS));
+ if (show_fps != fps->is_visible()) {
+ if (show_fps)
+ fps->show();
+ else
+ fps->hide();
+ }
+
+ if (show_fps) {
+ String text;
+ const float temp_fps = Engine::get_singleton()->get_frames_per_second();
+ text += TTR("FPS") + ": " + itos(temp_fps) + " (" + String::num(1000.0f / temp_fps, 2) + " ms)";
+
+ if (fps_label->get_text() != text || surface->get_size() != prev_size) {
+ fps_label->set_text(text);
+ Size2 ms = fps->get_size();
+ Size2 size = surface->get_size();
+ size.y = ms.y + 20;
+ fps->set_position(size - ms - Vector2(20, 0) * EDSCALE);
+ }
+ }
+
prev_size = surface->get_size();
}
@@ -2000,6 +2276,7 @@ void SpatialEditorViewport::_notification(int p_what) {
surface->connect("mouse_entered", this, "_smouseenter");
surface->connect("mouse_exited", this, "_smouseexit");
info->add_style_override("panel", get_stylebox("panel", "Panel"));
+ fps->add_style_override("panel", get_stylebox("panel", "Panel"));
preview_camera->set_icon(get_icon("Camera", "EditorIcons"));
_init_gizmo_instance(index);
}
@@ -2016,7 +2293,7 @@ void SpatialEditorViewport::_notification(int p_what) {
}
// TODO That should be part of the drawing API...
-static void stroke_rect(CanvasItem *ci, Rect2 rect, Color color, real_t width = 1.0) {
+static void stroke_rect(CanvasItem &ci, Rect2 rect, Color color, real_t width = 1.0) {
// a---b
// | |
@@ -2026,10 +2303,31 @@ static void stroke_rect(CanvasItem *ci, Rect2 rect, Color color, real_t width =
Vector2 c(rect.position.x, rect.position.y + rect.size.y);
Vector2 d(rect.position + rect.size);
- ci->draw_line(a, b, color, width);
- ci->draw_line(b, d, color, width);
- ci->draw_line(d, c, color, width);
- ci->draw_line(c, a, color, width);
+ ci.draw_line(a, b, color, width);
+ ci.draw_line(b, d, color, width);
+ ci.draw_line(d, c, color, width);
+ ci.draw_line(c, a, color, width);
+}
+
+static void draw_indicator_bar(Control &surface, real_t fill, Ref<Texture> icon) {
+
+ // Adjust bar size from control height
+ Vector2 surface_size = surface.get_size();
+ real_t h = surface_size.y / 2.0;
+ real_t y = (surface_size.y - h) / 2.0;
+
+ Rect2 r(10, y, 6, h);
+ real_t sy = r.size.y * fill;
+
+ // Note: because this bar appears over the viewport, it has to stay readable for any background color
+ // Draw both neutral dark and bright colors to account this
+ surface.draw_rect(r, Color(1, 1, 1, 0.2));
+ surface.draw_rect(Rect2(r.position.x, r.position.y + r.size.y - sy, r.size.x, sy), Color(1, 1, 1, 0.6));
+ stroke_rect(surface, r.grow(1), Color(0, 0, 0, 0.7));
+
+ Vector2 icon_size = icon->get_size();
+ Vector2 icon_pos = Vector2(r.position.x - (icon_size.x - r.size.x) / 2, r.position.y + r.size.y + 2);
+ surface.draw_texture(icon, icon_pos);
}
void SpatialEditorViewport::_draw() {
@@ -2088,35 +2386,47 @@ void SpatialEditorViewport::_draw() {
draw_rect = Rect2(Vector2(), s).clip(draw_rect);
- stroke_rect(surface, draw_rect, Color(0.6, 0.6, 0.1, 0.5), 2.0);
+ stroke_rect(*surface, draw_rect, Color(0.6, 0.6, 0.1, 0.5), 2.0);
} else {
if (zoom_indicator_delay > 0.0) {
- // Show indicative zoom factor
- real_t min_distance = ZOOM_MIN_DISTANCE; // TODO Why not pick znear to limit zoom?
- real_t max_distance = camera->get_zfar();
- real_t scale_length = (max_distance - min_distance);
+ if (is_freelook_active()) {
+ // Show speed
- if (Math::abs(scale_length) > CMP_EPSILON) {
- real_t logscale_t = 1.0 - Math::log(1 + cursor.distance - min_distance) / Math::log(1 + scale_length);
+ real_t min_speed = FREELOOK_MIN_SPEED;
+ real_t max_speed = camera->get_zfar();
+ real_t scale_length = (max_speed - min_speed);
+
+ if (Math::abs(scale_length) > CMP_EPSILON) {
+ real_t logscale_t = 1.0 - Math::log(1 + freelook_speed - min_speed) / Math::log(1 + scale_length);
+
+ // There is no real maximum speed so that factor can become negative,
+ // Let's make it look asymptotic instead (will decrease slower and slower).
+ if (logscale_t < 0.25)
+ logscale_t = 0.25 * Math::exp(4.0 * logscale_t - 1.0);
+
+ draw_indicator_bar(*surface, 1.0 - logscale_t, get_icon("ViewportSpeed", "EditorIcons"));
+ }
+
+ } else {
+ // Show zoom
- // There is no real maximum distance so that factor can become negative,
- // Let's make it look asymptotic instead (will decrease slower and slower).
- if (logscale_t < 0.25)
- logscale_t = 0.25 * Math::exp(4.0 * logscale_t - 1.0);
+ real_t min_distance = ZOOM_MIN_DISTANCE; // TODO Why not pick znear to limit zoom?
+ real_t max_distance = camera->get_zfar();
+ real_t scale_length = (max_distance - min_distance);
- Vector2 surface_size = surface->get_size();
- real_t h = surface_size.y / 2.0;
- real_t y = (surface_size.y - h) / 2.0;
+ if (Math::abs(scale_length) > CMP_EPSILON) {
+ real_t logscale_t = 1.0 - Math::log(1 + cursor.distance - min_distance) / Math::log(1 + scale_length);
- Rect2 r(10, y, 6, h);
- real_t sy = r.size.y * logscale_t;
+ // There is no real maximum distance so that factor can become negative,
+ // Let's make it look asymptotic instead (will decrease slower and slower).
+ if (logscale_t < 0.25)
+ logscale_t = 0.25 * Math::exp(4.0 * logscale_t - 1.0);
- surface->draw_rect(r, Color(1, 1, 1, 0.2));
- surface->draw_rect(Rect2(r.position.x, r.position.y + r.size.y - sy, r.size.x, sy), Color(1, 1, 1, 0.6));
- stroke_rect(surface, r.grow(1), Color(0, 0, 0, 0.7));
+ draw_indicator_bar(*surface, logscale_t, get_icon("ViewportZoom", "EditorIcons"));
+ }
}
}
}
@@ -2275,6 +2585,13 @@ void SpatialEditorViewport::_menu_option(int p_option) {
view_menu->get_popup()->set_item_checked(idx, current);
} break;
+ case VIEW_HALF_RESOLUTION: {
+
+ int idx = view_menu->get_popup()->get_item_index(VIEW_HALF_RESOLUTION);
+ bool current = view_menu->get_popup()->is_item_checked(idx);
+ current = !current;
+ view_menu->get_popup()->set_item_checked(idx, current);
+ } break;
case VIEW_INFORMATION: {
int idx = view_menu->get_popup()->get_item_index(VIEW_INFORMATION);
@@ -2282,6 +2599,13 @@ void SpatialEditorViewport::_menu_option(int p_option) {
view_menu->get_popup()->set_item_checked(idx, !current);
} break;
+ case VIEW_FPS: {
+
+ int idx = view_menu->get_popup()->get_item_index(VIEW_FPS);
+ bool current = view_menu->get_popup()->is_item_checked(idx);
+ view_menu->get_popup()->set_item_checked(idx, !current);
+
+ } break;
case VIEW_DISPLAY_NORMAL: {
viewport->set_debug_draw(Viewport::DEBUG_DRAW_DISABLED);
@@ -2367,6 +2691,14 @@ void SpatialEditorViewport::_init_gizmo_instance(int p_idx) {
//VS::get_singleton()->instance_geometry_set_flag(scale_gizmo_instance[i],VS::INSTANCE_FLAG_DEPH_SCALE,true);
VS::get_singleton()->instance_geometry_set_cast_shadows_setting(scale_gizmo_instance[i], VS::SHADOW_CASTING_SETTING_OFF);
VS::get_singleton()->instance_set_layer_mask(scale_gizmo_instance[i], layer);
+
+ scale_plane_gizmo_instance[i] = VS::get_singleton()->instance_create();
+ VS::get_singleton()->instance_set_base(scale_plane_gizmo_instance[i], spatial_editor->get_scale_plane_gizmo(i)->get_rid());
+ VS::get_singleton()->instance_set_scenario(scale_plane_gizmo_instance[i], get_tree()->get_root()->get_world()->get_scenario());
+ VS::get_singleton()->instance_set_visible(scale_plane_gizmo_instance[i], false);
+ //VS::get_singleton()->instance_geometry_set_flag(scale_plane_gizmo_instance[i],VS::INSTANCE_FLAG_DEPH_SCALE,true);
+ VS::get_singleton()->instance_geometry_set_cast_shadows_setting(scale_plane_gizmo_instance[i], VS::SHADOW_CASTING_SETTING_OFF);
+ VS::get_singleton()->instance_set_layer_mask(scale_plane_gizmo_instance[i], layer);
}
}
@@ -2377,6 +2709,7 @@ void SpatialEditorViewport::_finish_gizmo_instances() {
VS::get_singleton()->free(move_plane_gizmo_instance[i]);
VS::get_singleton()->free(rotate_gizmo_instance[i]);
VS::get_singleton()->free(scale_gizmo_instance[i]);
+ VS::get_singleton()->free(scale_plane_gizmo_instance[i]);
}
}
void SpatialEditorViewport::_toggle_camera_preview(bool p_activate) {
@@ -2473,6 +2806,8 @@ void SpatialEditorViewport::update_transform_gizmo_view() {
VisualServer::get_singleton()->instance_set_visible(rotate_gizmo_instance[i], spatial_editor->is_gizmo_visible() && (spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_SELECT || spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_ROTATE));
VisualServer::get_singleton()->instance_set_transform(scale_gizmo_instance[i], xform);
VisualServer::get_singleton()->instance_set_visible(scale_gizmo_instance[i], spatial_editor->is_gizmo_visible() && (spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_SCALE));
+ VisualServer::get_singleton()->instance_set_transform(scale_plane_gizmo_instance[i], xform);
+ VisualServer::get_singleton()->instance_set_visible(scale_plane_gizmo_instance[i], spatial_editor->is_gizmo_visible() && (spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_SCALE));
}
}
@@ -2504,6 +2839,12 @@ void SpatialEditorViewport::set_state(const Dictionary &p_state) {
camera->set_doppler_tracking(doppler ? Camera::DOPPLER_TRACKING_IDLE_STEP : Camera::DOPPLER_TRACKING_DISABLED);
view_menu->get_popup()->set_item_checked(idx, doppler);
}
+ if (p_state.has("half_res")) {
+ bool half_res = p_state["half_res"];
+
+ int idx = view_menu->get_popup()->get_item_index(VIEW_HALF_RESOLUTION);
+ view_menu->get_popup()->set_item_checked(idx, half_res);
+ }
if (p_state.has("previewing")) {
Node *pv = EditorNode::get_singleton()->get_edited_scene()->get_node(p_state["previewing"]);
@@ -2529,6 +2870,7 @@ Dictionary SpatialEditorViewport::get_state() const {
d["use_environment"] = camera->get_environment().is_valid();
d["use_orthogonal"] = camera->get_projection() == Camera::PROJECTION_ORTHOGONAL;
d["listener"] = viewport->is_audio_listener();
+ d["half_res"] = viewport_container->get_stretch_shrink() > 1;
if (previewing) {
d["previewing"] = EditorNode::get_singleton()->get_edited_scene()->get_path_to(previewing);
}
@@ -2566,6 +2908,7 @@ void SpatialEditorViewport::reset() {
cursor.y_rot = 0.5;
cursor.distance = 4;
cursor.region_select = false;
+ cursor.pos = Vector3();
_update_name();
}
@@ -2599,7 +2942,7 @@ void SpatialEditorViewport::focus_selection() {
cursor.pos = center;
}
-void SpatialEditorViewport::assign_pending_data_pointers(Spatial *p_preview_node, Rect3 *p_preview_bounds, AcceptDialog *p_accept) {
+void SpatialEditorViewport::assign_pending_data_pointers(Spatial *p_preview_node, AABB *p_preview_bounds, AcceptDialog *p_accept) {
preview_node = p_preview_node;
preview_bounds = p_preview_bounds;
accept = p_accept;
@@ -2652,18 +2995,24 @@ Vector3 SpatialEditorViewport::_get_instance_position(const Point2 &p_pos) const
normal = hit_normal;
}
}
- Vector3 center = preview_bounds->get_size() * 0.5;
- return point + (center * normal);
+ Vector3 offset = Vector3();
+ for (int i = 0; i < 3; i++) {
+ if (normal[i] > 0.0)
+ offset[i] = (preview_bounds->get_size()[i] - (preview_bounds->get_size()[i] + preview_bounds->get_position()[i]));
+ else if (normal[i] < 0.0)
+ offset[i] = -(preview_bounds->get_size()[i] + preview_bounds->get_position()[i]);
+ }
+ return point + offset;
}
-Rect3 SpatialEditorViewport::_calculate_spatial_bounds(const Spatial *p_parent, const Rect3 p_bounds) {
- Rect3 bounds = p_bounds;
+AABB SpatialEditorViewport::_calculate_spatial_bounds(const Spatial *p_parent, const AABB p_bounds) {
+ AABB bounds = p_bounds;
for (int i = 0; i < p_parent->get_child_count(); i++) {
Spatial *child = Object::cast_to<Spatial>(p_parent->get_child(i));
if (child) {
MeshInstance *mesh_instance = Object::cast_to<MeshInstance>(child);
if (mesh_instance) {
- Rect3 mesh_instance_bounds = mesh_instance->get_aabb();
+ AABB mesh_instance_bounds = mesh_instance->get_aabb();
mesh_instance_bounds.position += mesh_instance->get_global_transform().origin - p_parent->get_global_transform().origin;
bounds.merge_with(mesh_instance_bounds);
}
@@ -2695,7 +3044,7 @@ void SpatialEditorViewport::_create_preview(const Vector<String> &files) const {
editor->get_scene_root()->add_child(preview_node);
}
}
- *preview_bounds = _calculate_spatial_bounds(preview_node, Rect3());
+ *preview_bounds = _calculate_spatial_bounds(preview_node, AABB());
}
void SpatialEditorViewport::_remove_preview() {
@@ -2758,7 +3107,9 @@ bool SpatialEditorViewport::_create_instance(Node *parent, String &path, const P
}
}
- instanced_scene->set_filename(ProjectSettings::get_singleton()->localize_path(path));
+ if (scene != NULL) {
+ instanced_scene->set_filename(ProjectSettings::get_singleton()->localize_path(path));
+ }
editor_data->get_undo_redo().add_do_method(parent, "add_child", instanced_scene);
editor_data->get_undo_redo().add_do_method(instanced_scene, "set_owner", editor->get_edited_scene());
@@ -2775,7 +3126,7 @@ bool SpatialEditorViewport::_create_instance(Node *parent, String &path, const P
if (parent_spatial)
global_transform = parent_spatial->get_global_transform();
- global_transform.origin = _get_instance_position(p_point);
+ global_transform.origin = spatial_editor->snap_point(_get_instance_position(p_point));
editor_data->get_undo_redo().add_do_method(instanced_scene, "set_global_transform", global_transform);
@@ -2939,6 +3290,7 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed
spatial_editor = p_spatial_editor;
ViewportContainer *c = memnew(ViewportContainer);
+ viewport_container = c;
c->set_stretch(true);
add_child(c);
c->set_anchors_and_margins_preset(Control::PRESET_WIDE);
@@ -2983,8 +3335,11 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed
view_menu->get_popup()->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_environment", TTR("View Environment")), VIEW_ENVIRONMENT);
view_menu->get_popup()->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_gizmos", TTR("View Gizmos")), VIEW_GIZMOS);
view_menu->get_popup()->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_information", TTR("View Information")), VIEW_INFORMATION);
+ view_menu->get_popup()->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_fps", TTR("View FPS")), VIEW_FPS);
view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_ENVIRONMENT), true);
view_menu->get_popup()->add_separator();
+ view_menu->get_popup()->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_half_resolution", TTR("Half Resolution")), VIEW_HALF_RESOLUTION);
+ view_menu->get_popup()->add_separator();
view_menu->get_popup()->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_audio_listener", TTR("Audio Listener")), VIEW_AUDIO_LISTENER);
view_menu->get_popup()->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_audio_doppler", TTR("Doppler Enable")), VIEW_AUDIO_DOPPLER);
view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_GIZMOS), true);
@@ -3023,9 +3378,18 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed
info->add_child(info_label);
info->hide();
+ // FPS Counter.
+ fps = memnew(PanelContainer);
+ fps->set_self_modulate(Color(1, 1, 1, 0.4));
+ surface->add_child(fps);
+ fps_label = memnew(Label);
+ fps->add_child(fps_label);
+ fps->hide();
+
accept = NULL;
freelook_active = false;
+ freelook_speed = EditorSettings::get_singleton()->get("editors/3d/freelook/freelook_base_speed");
selection_menu = memnew(PopupMenu);
add_child(selection_menu);
@@ -3359,13 +3723,14 @@ void SpatialEditor::select_gizmo_highlight_axis(int p_axis) {
move_plane_gizmo[i]->surface_set_material(0, (i + 6) == p_axis ? gizmo_hl : plane_gizmo_color[i]);
rotate_gizmo[i]->surface_set_material(0, (i + 3) == p_axis ? gizmo_hl : gizmo_color[i]);
scale_gizmo[i]->surface_set_material(0, (i + 9) == p_axis ? gizmo_hl : gizmo_color[i]);
+ scale_plane_gizmo[i]->surface_set_material(0, (i + 12) == p_axis ? gizmo_hl : plane_gizmo_color[i]);
}
}
void SpatialEditor::update_transform_gizmo() {
List<Node *> &selection = editor_selection->get_selected_node_list();
- Rect3 center;
+ AABB center;
bool first = true;
Basis gizmo_basis;
@@ -3426,7 +3791,7 @@ Object *SpatialEditor::_get_editor_data(Object *p_what) {
void SpatialEditor::_generate_selection_box() {
- Rect3 aabb(Vector3(), Vector3(1, 1, 1));
+ AABB aabb(Vector3(), Vector3(1, 1, 1));
aabb.grow_by(aabb.get_longest_axis_size() / 20.0);
Ref<SurfaceTool> st = memnew(SurfaceTool);
@@ -3815,6 +4180,44 @@ void SpatialEditor::_menu_item_pressed(int p_option) {
settings_dialog->popup_centered(settings_vbc->get_combined_minimum_size() + Size2(50, 50));
} break;
+ case MENU_LOCK_SELECTED: {
+
+ List<Node *> &selection = editor_selection->get_selected_node_list();
+
+ for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
+
+ Spatial *spatial = Object::cast_to<Spatial>(E->get());
+ if (!spatial || !spatial->is_visible_in_tree())
+ continue;
+
+ if (spatial->get_viewport() != EditorNode::get_singleton()->get_scene_root())
+ continue;
+
+ spatial->set_meta("_edit_lock_", true);
+ emit_signal("item_lock_status_changed");
+ }
+
+ _refresh_menu_icons();
+ } break;
+ case MENU_UNLOCK_SELECTED: {
+
+ List<Node *> &selection = editor_selection->get_selected_node_list();
+
+ for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
+
+ Spatial *spatial = Object::cast_to<Spatial>(E->get());
+ if (!spatial || !spatial->is_visible_in_tree())
+ continue;
+
+ if (spatial->get_viewport() != EditorNode::get_singleton()->get_scene_root())
+ continue;
+
+ spatial->set_meta("_edit_lock_", Variant());
+ emit_signal("item_lock_status_changed");
+ }
+
+ _refresh_menu_icons();
+ } break;
}
}
@@ -3932,6 +4335,7 @@ void SpatialEditor::_init_indicators() {
move_plane_gizmo[i] = Ref<ArrayMesh>(memnew(ArrayMesh));
rotate_gizmo[i] = Ref<ArrayMesh>(memnew(ArrayMesh));
scale_gizmo[i] = Ref<ArrayMesh>(memnew(ArrayMesh));
+ scale_plane_gizmo[i] = Ref<ArrayMesh>(memnew(ArrayMesh));
Ref<SpatialMaterial> mat = memnew(SpatialMaterial);
mat->set_flag(SpatialMaterial::FLAG_UNSHADED, true);
@@ -4127,6 +4531,49 @@ void SpatialEditor::_init_indicators() {
surftool->set_material(mat);
surftool->commit(scale_gizmo[i]);
}
+
+ // Plane Scale
+ {
+ Ref<SurfaceTool> surftool = memnew(SurfaceTool);
+ surftool->begin(Mesh::PRIMITIVE_TRIANGLES);
+
+ Vector3 vec = ivec2 - ivec3;
+ Vector3 plane[4] = {
+ vec * GIZMO_PLANE_DST,
+ vec * GIZMO_PLANE_DST + ivec2 * GIZMO_PLANE_SIZE,
+ vec * (GIZMO_PLANE_DST + GIZMO_PLANE_SIZE),
+ vec * GIZMO_PLANE_DST - ivec3 * GIZMO_PLANE_SIZE
+ };
+
+ Basis ma(ivec, Math_PI / 2);
+
+ Vector3 points[4] = {
+ ma.xform(plane[0]),
+ ma.xform(plane[1]),
+ ma.xform(plane[2]),
+ ma.xform(plane[3]),
+ };
+ surftool->add_vertex(points[0]);
+ surftool->add_vertex(points[1]);
+ surftool->add_vertex(points[2]);
+
+ surftool->add_vertex(points[0]);
+ surftool->add_vertex(points[2]);
+ surftool->add_vertex(points[3]);
+
+ Ref<SpatialMaterial> plane_mat = memnew(SpatialMaterial);
+ plane_mat->set_flag(SpatialMaterial::FLAG_UNSHADED, true);
+ plane_mat->set_on_top_of_alpha();
+ plane_mat->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true);
+ plane_mat->set_cull_mode(SpatialMaterial::CULL_DISABLED);
+ Color col;
+ col[i] = 1.0;
+ col.a = gizmo_alph;
+ plane_mat->set_albedo(col);
+ plane_gizmo_color[i] = plane_mat; // needed, so we can draw planes from both sides
+ surftool->set_material(plane_mat);
+ surftool->commit(scale_plane_gizmo[i]);
+ }
}
}
@@ -4154,6 +4601,28 @@ bool SpatialEditor::is_any_freelook_active() const {
return false;
}
+void SpatialEditor::_refresh_menu_icons() {
+
+ bool all_locked = true;
+
+ List<Node *> &selection = editor_selection->get_selected_node_list();
+
+ if (selection.empty()) {
+ all_locked = false;
+ } else {
+ for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
+ if (Object::cast_to<Spatial>(E->get()) && !Object::cast_to<Spatial>(E->get())->has_meta("_edit_lock_")) {
+ all_locked = false;
+ break;
+ }
+ }
+ }
+
+ tool_button[TOOL_LOCK_SELECTED]->set_visible(!all_locked);
+ tool_button[TOOL_LOCK_SELECTED]->set_disabled(selection.empty());
+ tool_button[TOOL_UNLOCK_SELECTED]->set_visible(all_locked);
+}
+
void SpatialEditor::_unhandled_key_input(Ref<InputEvent> p_event) {
if (!is_visible_in_tree() || get_viewport()->gui_has_modal_stack())
@@ -4192,6 +4661,8 @@ void SpatialEditor::_notification(int p_what) {
tool_button[SpatialEditor::TOOL_MODE_ROTATE]->set_icon(get_icon("ToolRotate", "EditorIcons"));
tool_button[SpatialEditor::TOOL_MODE_SCALE]->set_icon(get_icon("ToolScale", "EditorIcons"));
tool_button[SpatialEditor::TOOL_MODE_LIST_SELECT]->set_icon(get_icon("ListSelect", "EditorIcons"));
+ tool_button[SpatialEditor::TOOL_LOCK_SELECTED]->set_icon(get_icon("Lock", "EditorIcons"));
+ tool_button[SpatialEditor::TOOL_UNLOCK_SELECTED]->set_icon(get_icon("Unlock", "EditorIcons"));
view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT), get_icon("Panels1", "EditorIcons"));
view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), get_icon("Panels2", "EditorIcons"));
@@ -4202,7 +4673,11 @@ void SpatialEditor::_notification(int p_what) {
_menu_item_pressed(MENU_VIEW_USE_1_VIEWPORT);
+ _refresh_menu_icons();
+
get_tree()->connect("node_removed", this, "_node_removed");
+ EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor()->connect("node_changed", this, "_refresh_menu_icons");
+ editor_selection->connect("selection_changed", this, "_refresh_menu_icons");
}
if (p_what == NOTIFICATION_ENTER_TREE) {
@@ -4345,8 +4820,10 @@ void SpatialEditor::_bind_methods() {
ClassDB::bind_method("_get_editor_data", &SpatialEditor::_get_editor_data);
ClassDB::bind_method("_request_gizmo", &SpatialEditor::_request_gizmo);
ClassDB::bind_method("_toggle_maximize_view", &SpatialEditor::_toggle_maximize_view);
+ ClassDB::bind_method("_refresh_menu_icons", &SpatialEditor::_refresh_menu_icons);
ADD_SIGNAL(MethodInfo("transform_key_request"));
+ ADD_SIGNAL(MethodInfo("item_lock_status_changed"));
}
void SpatialEditor::clear() {
@@ -4448,12 +4925,24 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) {
tool_button[TOOL_MODE_LIST_SELECT]->connect("pressed", this, "_menu_item_pressed", button_binds);
tool_button[TOOL_MODE_LIST_SELECT]->set_tooltip(TTR("Show a list of all objects at the position clicked\n(same as Alt+RMB in select mode)."));
+ tool_button[TOOL_LOCK_SELECTED] = memnew(ToolButton);
+ hbc_menu->add_child(tool_button[TOOL_LOCK_SELECTED]);
+ button_binds[0] = MENU_LOCK_SELECTED;
+ tool_button[TOOL_LOCK_SELECTED]->connect("pressed", this, "_menu_item_pressed", button_binds);
+ tool_button[TOOL_LOCK_SELECTED]->set_tooltip(TTR("Lock the selected object in place (can't be moved)."));
+
+ tool_button[TOOL_UNLOCK_SELECTED] = memnew(ToolButton);
+ hbc_menu->add_child(tool_button[TOOL_UNLOCK_SELECTED]);
+ button_binds[0] = MENU_UNLOCK_SELECTED;
+ tool_button[TOOL_UNLOCK_SELECTED]->connect("pressed", this, "_menu_item_pressed", button_binds);
+ tool_button[TOOL_UNLOCK_SELECTED]->set_tooltip(TTR("Unlock the selected object (can be moved)."));
+
vs = memnew(VSeparator);
hbc_menu->add_child(vs);
// Drag and drop support;
preview_node = memnew(Spatial);
- preview_bounds = Rect3();
+ preview_bounds = AABB();
ED_SHORTCUT("spatial_editor/bottom_view", TTR("Bottom View"), KEY_MASK_ALT + KEY_KP_7);
ED_SHORTCUT("spatial_editor/top_view", TTR("Top View"), KEY_KP_7);
@@ -4475,6 +4964,8 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) {
ED_SHORTCUT("spatial_editor/display_wireframe", TTR("Display Wireframe"), KEY_Z);
+ ED_SHORTCUT("spatial_editor/freelook_toggle", TTR("Toggle Freelook"), KEY_MASK_SHIFT + KEY_F);
+
PopupMenu *p;
transform_menu = memnew(MenuButton);
@@ -4714,6 +5205,15 @@ void SpatialEditor::snap_cursor_to_plane(const Plane &p_plane) {
//cursor.pos=p_plane.project(cursor.pos);
}
+Vector3 SpatialEditor::snap_point(Vector3 p_target, Vector3 p_start) const {
+ if (is_snap_enabled()) {
+ p_target.x = Math::snap_scalar(0.0, get_translate_snap(), p_target.x);
+ p_target.y = Math::snap_scalar(0.0, get_translate_snap(), p_target.y);
+ p_target.z = Math::snap_scalar(0.0, get_translate_snap(), p_target.z);
+ }
+ return p_target;
+}
+
void SpatialEditorPlugin::_bind_methods() {
ClassDB::bind_method("snap_cursor_to_plane", &SpatialEditorPlugin::snap_cursor_to_plane);
diff --git a/editor/plugins/spatial_editor_plugin.h b/editor/plugins/spatial_editor_plugin.h
index 4f4c540048..14558fc878 100644
--- a/editor/plugins/spatial_editor_plugin.h
+++ b/editor/plugins/spatial_editor_plugin.h
@@ -83,10 +83,12 @@ class SpatialEditorViewport : public Control {
VIEW_PERSPECTIVE,
VIEW_ENVIRONMENT,
VIEW_ORTHOGONAL,
+ VIEW_HALF_RESOLUTION,
VIEW_AUDIO_LISTENER,
VIEW_AUDIO_DOPPLER,
VIEW_GIZMOS,
VIEW_INFORMATION,
+ VIEW_FPS,
VIEW_DISPLAY_NORMAL,
VIEW_DISPLAY_WIREFRAME,
VIEW_DISPLAY_OVERDRAW,
@@ -107,7 +109,7 @@ private:
Size2 prev_size;
Spatial *preview_node;
- Rect3 *preview_bounds;
+ AABB *preview_bounds;
Vector<String> selected_files;
AcceptDialog *accept;
@@ -120,6 +122,7 @@ private:
UndoRedo *undo_redo;
Button *preview_camera;
+ ViewportContainer *viewport_container;
MenuButton *view_menu;
@@ -131,11 +134,14 @@ private:
float gizmo_scale;
bool freelook_active;
- Vector3 freelook_target_position;
+ real_t freelook_speed;
PanelContainer *info;
Label *info_label;
+ PanelContainer *fps;
+ Label *fps_label;
+
struct _RayResult {
Spatial *item;
@@ -164,6 +170,11 @@ private:
void _select_region();
bool _gizmo_select(const Vector2 &p_screenpos, bool p_highlight_only = false);
+ void _nav_pan(Ref<InputEventWithModifiers> p_event, const Vector2 &p_relative);
+ void _nav_zoom(Ref<InputEventWithModifiers> p_event, const Vector2 &p_relative);
+ void _nav_orbit(Ref<InputEventWithModifiers> p_event, const Vector2 &p_relative);
+ void _nav_look(Ref<InputEventWithModifiers> p_event, const Vector2 &p_relative);
+
float get_znear() const;
float get_zfar() const;
float get_fov() const;
@@ -231,6 +242,7 @@ private:
Vector3 pos;
float x_rot, y_rot, distance;
+ Vector3 eye_pos; // Used in freelook mode
bool region_select;
Point2 region_begin, region_end;
@@ -239,13 +251,20 @@ private:
distance = 4;
region_select = false;
}
- } cursor, camera_cursor;
+ };
+ // Viewport camera supports movement smoothing,
+ // so one cursor is the real cursor, while the other can be an interpolated version.
+ Cursor cursor; // Immediate cursor
+ Cursor camera_cursor; // That one may be interpolated (don't modify this one except for smoothing purposes)
void scale_cursor_distance(real_t scale);
+ void set_freelook_active(bool active_now);
+ void scale_freelook_speed(real_t scale);
+
real_t zoom_indicator_delay;
- RID move_gizmo_instance[3], move_plane_gizmo_instance[3], rotate_gizmo_instance[3], scale_gizmo_instance[3];
+ RID move_gizmo_instance[3], move_plane_gizmo_instance[3], rotate_gizmo_instance[3], scale_gizmo_instance[3], scale_plane_gizmo_instance[3];
String last_message;
String message;
@@ -277,7 +296,7 @@ private:
Point2i _get_warped_mouse_motion(const Ref<InputEventMouseMotion> &p_ev_mouse_motion) const;
Vector3 _get_instance_position(const Point2 &p_pos) const;
- static Rect3 _calculate_spatial_bounds(const Spatial *p_parent, const Rect3 p_bounds);
+ static AABB _calculate_spatial_bounds(const Spatial *p_parent, const AABB p_bounds);
void _create_preview(const Vector<String> &files) const;
void _remove_preview();
bool _cyclical_dependency_exists(const String &p_target_scene_path, Node *p_desired_node);
@@ -304,7 +323,7 @@ public:
void assign_pending_data_pointers(
Spatial *p_preview_node,
- Rect3 *p_preview_bounds,
+ AABB *p_preview_bounds,
AcceptDialog *p_accept);
Viewport *get_viewport_node() { return viewport; }
@@ -317,7 +336,7 @@ class SpatialEditorSelectedItem : public Object {
GDCLASS(SpatialEditorSelectedItem, Object);
public:
- Rect3 aabb;
+ AABB aabb;
Transform original; // original location when moving
Transform original_local;
Transform last_xform; // last transform
@@ -377,6 +396,8 @@ public:
TOOL_MODE_ROTATE,
TOOL_MODE_SCALE,
TOOL_MODE_LIST_SELECT,
+ TOOL_LOCK_SELECTED,
+ TOOL_UNLOCK_SELECTED,
TOOL_MAX
};
@@ -408,7 +429,7 @@ private:
bool grid_enable[3]; //should be always visible if true
bool grid_enabled;
- Ref<ArrayMesh> move_gizmo[3], move_plane_gizmo[3], rotate_gizmo[3], scale_gizmo[3];
+ Ref<ArrayMesh> move_gizmo[3], move_plane_gizmo[3], rotate_gizmo[3], scale_gizmo[3], scale_plane_gizmo[3];
Ref<SpatialMaterial> gizmo_color[3];
Ref<SpatialMaterial> plane_gizmo_color[3];
Ref<SpatialMaterial> gizmo_hl;
@@ -425,7 +446,7 @@ private:
// Scene drag and drop support
Spatial *preview_node;
- Rect3 preview_bounds;
+ AABB preview_bounds;
/*
struct Selected {
@@ -465,7 +486,8 @@ private:
MENU_VIEW_ORIGIN,
MENU_VIEW_GRID,
MENU_VIEW_CAMERA_SETTINGS,
-
+ MENU_LOCK_SELECTED,
+ MENU_UNLOCK_SELECTED
};
Button *tool_button[TOOL_MAX];
@@ -473,6 +495,9 @@ private:
MenuButton *transform_menu;
MenuButton *view_menu;
+ ToolButton *lock_button;
+ ToolButton *unlock_button;
+
AcceptDialog *accept;
ConfirmationDialog *snap_dialog;
@@ -529,6 +554,8 @@ private:
bool is_any_freelook_active() const;
+ void _refresh_menu_icons();
+
protected:
void _notification(int p_what);
//void _gui_input(InputEvent p_event);
@@ -540,6 +567,8 @@ public:
static SpatialEditor *get_singleton() { return singleton; }
void snap_cursor_to_plane(const Plane &p_plane);
+ Vector3 snap_point(Vector3 p_target, Vector3 p_start = Vector3(0, 0, 0)) const;
+
float get_znear() const { return settings_znear->get_value(); }
float get_zfar() const { return settings_zfar->get_value(); }
float get_fov() const { return settings_fov->get_value(); }
@@ -559,6 +588,7 @@ public:
Ref<ArrayMesh> get_move_plane_gizmo(int idx) const { return move_plane_gizmo[idx]; }
Ref<ArrayMesh> get_rotate_gizmo(int idx) const { return rotate_gizmo[idx]; }
Ref<ArrayMesh> get_scale_gizmo(int idx) const { return scale_gizmo[idx]; }
+ Ref<ArrayMesh> get_scale_plane_gizmo(int idx) const { return scale_plane_gizmo[idx]; }
void update_transform_gizmo();
diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp
index 3b6eeb61d6..b3bb103577 100644
--- a/editor/plugins/sprite_frames_editor_plugin.cpp
+++ b/editor/plugins/sprite_frames_editor_plugin.cpp
@@ -43,10 +43,10 @@ void SpriteFramesEditor::_notification(int p_what) {
}
if (p_what == NOTIFICATION_ENTER_TREE) {
- load->set_icon(get_icon("Folder", "EditorIcons"));
- _delete->set_icon(get_icon("Del", "EditorIcons"));
+ load->set_icon(get_icon("Load", "EditorIcons"));
+ _delete->set_icon(get_icon("Remove", "EditorIcons"));
new_anim->set_icon(get_icon("New", "EditorIcons"));
- remove_anim->set_icon(get_icon("Del", "EditorIcons"));
+ remove_anim->set_icon(get_icon("Remove", "EditorIcons"));
}
if (p_what == NOTIFICATION_READY) {
@@ -142,6 +142,19 @@ void SpriteFramesEditor::_paste_pressed() {
undo_redo->commit_action();
}
+void SpriteFramesEditor::_copy_pressed() {
+ ERR_FAIL_COND(!frames->has_animation(edited_anim));
+
+ if (tree->get_current() < 0)
+ return;
+ Ref<Texture> r = frames->get_frame(edited_anim, tree->get_current());
+ if (!r.is_valid()) {
+ return;
+ }
+
+ EditorSettings::get_singleton()->set_resource_clipboard(r);
+}
+
void SpriteFramesEditor::_empty_pressed() {
ERR_FAIL_COND(!frames->has_animation(edited_anim));
@@ -352,13 +365,11 @@ void SpriteFramesEditor::_animation_name_edited() {
}
void SpriteFramesEditor::_animation_add() {
- String new_name = "New Anim";
-
- String name = new_name;
+ String name = "New Anim";
int counter = 0;
while (frames->has_animation(name)) {
counter++;
- name = new_name + " " + itos(counter);
+ name = "New Anim " + itos(counter);
}
List<Node *> nodes;
@@ -380,7 +391,7 @@ void SpriteFramesEditor::_animation_add() {
undo_redo->add_undo_method(E->get(), "set_animation", current);
}
- edited_anim = new_name;
+ edited_anim = name;
undo_redo->commit_action();
}
@@ -642,6 +653,7 @@ void SpriteFramesEditor::_bind_methods() {
ClassDB::bind_method(D_METHOD("_empty_pressed"), &SpriteFramesEditor::_empty_pressed);
ClassDB::bind_method(D_METHOD("_empty2_pressed"), &SpriteFramesEditor::_empty2_pressed);
ClassDB::bind_method(D_METHOD("_delete_pressed"), &SpriteFramesEditor::_delete_pressed);
+ ClassDB::bind_method(D_METHOD("_copy_pressed"), &SpriteFramesEditor::_copy_pressed);
ClassDB::bind_method(D_METHOD("_paste_pressed"), &SpriteFramesEditor::_paste_pressed);
ClassDB::bind_method(D_METHOD("_file_load_request", "files", "at_position"), &SpriteFramesEditor::_file_load_request, DEFVAL(-1));
ClassDB::bind_method(D_METHOD("_update_library", "skipsel"), &SpriteFramesEditor::_update_library, DEFVAL(false));
@@ -667,7 +679,7 @@ SpriteFramesEditor::SpriteFramesEditor() {
VBoxContainer *vbc_animlist = memnew(VBoxContainer);
split->add_child(vbc_animlist);
- vbc_animlist->set_custom_minimum_size(Size2(150, 0));
+ vbc_animlist->set_custom_minimum_size(Size2(150, 0) * EDSCALE);
//vbc_animlist->set_v_size_flags(SIZE_EXPAND_FILL);
VBoxContainer *sub_vb = memnew(VBoxContainer);
@@ -678,12 +690,13 @@ SpriteFramesEditor::SpriteFramesEditor() {
sub_vb->add_child(hbc_animlist);
new_anim = memnew(Button);
+ new_anim->set_flat(true);
hbc_animlist->add_child(new_anim);
+ new_anim->set_h_size_flags(SIZE_EXPAND_FILL);
new_anim->connect("pressed", this, "_animation_add");
- hbc_animlist->add_spacer();
-
remove_anim = memnew(Button);
+ remove_anim->set_flat(true);
hbc_animlist->add_child(remove_anim);
remove_anim->connect("pressed", this, "_animation_remove");
@@ -720,9 +733,14 @@ SpriteFramesEditor::SpriteFramesEditor() {
//animations = memnew( ItemList );
load = memnew(Button);
+ load->set_flat(true);
load->set_tooltip(TTR("Load Resource"));
hbc->add_child(load);
+ copy = memnew(Button);
+ copy->set_text(TTR("Copy"));
+ hbc->add_child(copy);
+
paste = memnew(Button);
paste->set_text(TTR("Paste"));
hbc->add_child(paste);
@@ -736,14 +754,15 @@ SpriteFramesEditor::SpriteFramesEditor() {
hbc->add_child(empty2);
move_up = memnew(Button);
- move_up->set_text(TTR("Up"));
+ move_up->set_text(TTR("Move (Before)"));
hbc->add_child(move_up);
move_down = memnew(Button);
- move_down->set_text(TTR("Down"));
+ move_down->set_text(TTR("Move (After)"));
hbc->add_child(move_down);
_delete = memnew(Button);
+ _delete->set_flat(true);
hbc->add_child(_delete);
file = memnew(EditorFileDialog);
@@ -769,6 +788,7 @@ SpriteFramesEditor::SpriteFramesEditor() {
load->connect("pressed", this, "_load_pressed");
_delete->connect("pressed", this, "_delete_pressed");
+ copy->connect("pressed", this, "_copy_pressed");
paste->connect("pressed", this, "_paste_pressed");
empty->connect("pressed", this, "_empty_pressed");
empty2->connect("pressed", this, "_empty2_pressed");
@@ -818,7 +838,7 @@ SpriteFramesEditorPlugin::SpriteFramesEditorPlugin(EditorNode *p_node) {
editor = p_node;
frames_editor = memnew(SpriteFramesEditor);
- frames_editor->set_custom_minimum_size(Size2(0, 300));
+ frames_editor->set_custom_minimum_size(Size2(0, 300) * EDSCALE);
button = editor->add_bottom_panel_item("SpriteFrames", frames_editor);
button->hide();
}
diff --git a/editor/plugins/sprite_frames_editor_plugin.h b/editor/plugins/sprite_frames_editor_plugin.h
index 0d1ab9fd8c..9fdab37f0e 100644
--- a/editor/plugins/sprite_frames_editor_plugin.h
+++ b/editor/plugins/sprite_frames_editor_plugin.h
@@ -44,6 +44,7 @@ class SpriteFramesEditor : public PanelContainer {
Button *load;
Button *_delete;
+ Button *copy;
Button *paste;
Button *empty;
Button *empty2;
@@ -72,6 +73,7 @@ class SpriteFramesEditor : public PanelContainer {
void _load_pressed();
void _load_scene_pressed();
void _file_load_request(const PoolVector<String> &p_path, int p_at_pos = -1);
+ void _copy_pressed();
void _paste_pressed();
void _empty_pressed();
void _empty2_pressed();
diff --git a/editor/plugins/texture_region_editor_plugin.cpp b/editor/plugins/texture_region_editor_plugin.cpp
index 0a7f3ff8f9..48aed0cf6c 100644
--- a/editor/plugins/texture_region_editor_plugin.cpp
+++ b/editor/plugins/texture_region_editor_plugin.cpp
@@ -48,8 +48,8 @@ void TextureRegionEditor::_region_draw() {
Ref<Texture> base_tex = NULL;
if (node_sprite)
base_tex = node_sprite->get_texture();
- else if (node_patch9)
- base_tex = node_patch9->get_texture();
+ else if (node_ninepatch)
+ base_tex = node_ninepatch->get_texture();
else if (obj_styleBox.is_valid())
base_tex = obj_styleBox->get_texture();
else if (atlas_tex.is_valid())
@@ -177,12 +177,12 @@ void TextureRegionEditor::_region_draw() {
updating_scroll = false;
float margins[4];
- if (node_patch9 || obj_styleBox.is_valid()) {
- if (node_patch9) {
- margins[0] = node_patch9->get_patch_margin(MARGIN_TOP);
- margins[1] = node_patch9->get_patch_margin(MARGIN_BOTTOM);
- margins[2] = node_patch9->get_patch_margin(MARGIN_LEFT);
- margins[3] = node_patch9->get_patch_margin(MARGIN_RIGHT);
+ if (node_ninepatch || obj_styleBox.is_valid()) {
+ if (node_ninepatch) {
+ margins[0] = node_ninepatch->get_patch_margin(MARGIN_TOP);
+ margins[1] = node_ninepatch->get_patch_margin(MARGIN_BOTTOM);
+ margins[2] = node_ninepatch->get_patch_margin(MARGIN_LEFT);
+ margins[3] = node_ninepatch->get_patch_margin(MARGIN_RIGHT);
} else if (obj_styleBox.is_valid()) {
margins[0] = obj_styleBox->get_margin_size(MARGIN_TOP);
margins[1] = obj_styleBox->get_margin_size(MARGIN_BOTTOM);
@@ -225,14 +225,14 @@ void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) {
if (mb->get_button_index() == BUTTON_LEFT) {
if (mb->is_pressed()) {
- if (node_patch9 || obj_styleBox.is_valid()) {
+ if (node_ninepatch || obj_styleBox.is_valid()) {
edited_margin = -1;
float margins[4];
- if (node_patch9) {
- margins[0] = node_patch9->get_patch_margin(MARGIN_TOP);
- margins[1] = node_patch9->get_patch_margin(MARGIN_BOTTOM);
- margins[2] = node_patch9->get_patch_margin(MARGIN_LEFT);
- margins[3] = node_patch9->get_patch_margin(MARGIN_RIGHT);
+ if (node_ninepatch) {
+ margins[0] = node_ninepatch->get_patch_margin(MARGIN_TOP);
+ margins[1] = node_ninepatch->get_patch_margin(MARGIN_BOTTOM);
+ margins[2] = node_ninepatch->get_patch_margin(MARGIN_LEFT);
+ margins[3] = node_ninepatch->get_patch_margin(MARGIN_RIGHT);
} else if (obj_styleBox.is_valid()) {
margins[0] = obj_styleBox->get_margin_size(MARGIN_TOP);
margins[1] = obj_styleBox->get_margin_size(MARGIN_BOTTOM);
@@ -272,8 +272,8 @@ void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) {
Rect2 r;
if (node_sprite)
r = node_sprite->get_region_rect();
- else if (node_patch9)
- r = node_patch9->get_region_rect();
+ else if (node_ninepatch)
+ r = node_ninepatch->get_region_rect();
else if (obj_styleBox.is_valid())
r = obj_styleBox->get_region_rect();
else if (atlas_tex.is_valid())
@@ -285,9 +285,9 @@ void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) {
if (node_sprite) {
undo_redo->add_do_method(node_sprite, "set_region_rect", rect);
undo_redo->add_undo_method(node_sprite, "set_region_rect", node_sprite->get_region_rect());
- } else if (node_patch9) {
- undo_redo->add_do_method(node_patch9, "set_region_rect", rect);
- undo_redo->add_undo_method(node_patch9, "set_region_rect", node_patch9->get_region_rect());
+ } else if (node_ninepatch) {
+ undo_redo->add_do_method(node_ninepatch, "set_region_rect", rect);
+ undo_redo->add_undo_method(node_ninepatch, "set_region_rect", node_ninepatch->get_region_rect());
} else if (obj_styleBox.is_valid()) {
undo_redo->add_do_method(obj_styleBox.ptr(), "set_region_rect", rect);
undo_redo->add_undo_method(obj_styleBox.ptr(), "set_region_rect", obj_styleBox->get_region_rect());
@@ -310,8 +310,8 @@ void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) {
drag = true;
if (node_sprite)
rect_prev = node_sprite->get_region_rect();
- else if (node_patch9)
- rect_prev = node_patch9->get_region_rect();
+ else if (node_ninepatch)
+ rect_prev = node_ninepatch->get_region_rect();
else if (obj_styleBox.is_valid())
rect_prev = obj_styleBox->get_region_rect();
else if (atlas_tex.is_valid())
@@ -334,9 +334,9 @@ void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) {
if (edited_margin >= 0) {
undo_redo->create_action("Set Margin");
static Margin m[4] = { MARGIN_TOP, MARGIN_BOTTOM, MARGIN_LEFT, MARGIN_RIGHT };
- if (node_patch9) {
- undo_redo->add_do_method(node_patch9, "set_patch_margin", m[edited_margin], node_patch9->get_patch_margin(m[edited_margin]));
- undo_redo->add_undo_method(node_patch9, "set_patch_margin", m[edited_margin], prev_margin);
+ if (node_ninepatch) {
+ undo_redo->add_do_method(node_ninepatch, "set_patch_margin", m[edited_margin], node_ninepatch->get_patch_margin(m[edited_margin]));
+ undo_redo->add_undo_method(node_ninepatch, "set_patch_margin", m[edited_margin], prev_margin);
} else if (obj_styleBox.is_valid()) {
undo_redo->add_do_method(obj_styleBox.ptr(), "set_margin_size", m[edited_margin], obj_styleBox->get_margin_size(m[edited_margin]));
undo_redo->add_undo_method(obj_styleBox.ptr(), "set_margin_size", m[edited_margin], prev_margin);
@@ -351,11 +351,11 @@ void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) {
} else if (atlas_tex.is_valid()) {
undo_redo->add_do_method(atlas_tex.ptr(), "set_region", atlas_tex->get_region());
undo_redo->add_undo_method(atlas_tex.ptr(), "set_region", rect_prev);
- } else if (node_patch9) {
+ } else if (node_ninepatch) {
// FIXME: Is this intentional?
- } else if (node_patch9) {
- undo_redo->add_do_method(node_patch9, "set_region_rect", node_patch9->get_region_rect());
- undo_redo->add_undo_method(node_patch9, "set_region_rect", rect_prev);
+ } else if (node_ninepatch) {
+ undo_redo->add_do_method(node_ninepatch, "set_region_rect", node_ninepatch->get_region_rect());
+ undo_redo->add_undo_method(node_ninepatch, "set_region_rect", rect_prev);
} else if (obj_styleBox.is_valid()) {
undo_redo->add_do_method(obj_styleBox.ptr(), "set_region_rect", obj_styleBox->get_region_rect());
undo_redo->add_undo_method(obj_styleBox.ptr(), "set_region_rect", rect_prev);
@@ -375,8 +375,8 @@ void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) {
drag = false;
if (edited_margin >= 0) {
static Margin m[4] = { MARGIN_TOP, MARGIN_BOTTOM, MARGIN_LEFT, MARGIN_RIGHT };
- if (node_patch9)
- node_patch9->set_patch_margin(m[edited_margin], prev_margin);
+ if (node_ninepatch)
+ node_ninepatch->set_patch_margin(m[edited_margin], prev_margin);
if (obj_styleBox.is_valid())
obj_styleBox->set_margin_size(m[edited_margin], prev_margin);
edited_margin = -1;
@@ -422,8 +422,8 @@ void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) {
if (new_margin < 0)
new_margin = 0;
static Margin m[4] = { MARGIN_TOP, MARGIN_BOTTOM, MARGIN_LEFT, MARGIN_RIGHT };
- if (node_patch9)
- node_patch9->set_patch_margin(m[edited_margin], new_margin);
+ if (node_ninepatch)
+ node_ninepatch->set_patch_margin(m[edited_margin], new_margin);
if (obj_styleBox.is_valid())
obj_styleBox->set_margin_size(m[edited_margin], new_margin);
} else {
@@ -573,8 +573,8 @@ void TextureRegionEditor::_zoom_out() {
void TextureRegionEditor::apply_rect(const Rect2 &rect) {
if (node_sprite)
node_sprite->set_region_rect(rect);
- else if (node_patch9)
- node_patch9->set_region_rect(rect);
+ else if (node_ninepatch)
+ node_ninepatch->set_region_rect(rect);
else if (obj_styleBox.is_valid())
obj_styleBox->set_region_rect(rect);
else if (atlas_tex.is_valid())
@@ -593,8 +593,8 @@ void TextureRegionEditor::_notification(int p_what) {
}
void TextureRegionEditor::_node_removed(Object *p_obj) {
- if (p_obj == node_sprite || p_obj == node_patch9 || p_obj == obj_styleBox.ptr() || p_obj == atlas_tex.ptr()) {
- node_patch9 = NULL;
+ if (p_obj == node_sprite || p_obj == node_ninepatch || p_obj == obj_styleBox.ptr() || p_obj == atlas_tex.ptr()) {
+ node_ninepatch = NULL;
node_sprite = NULL;
obj_styleBox = Ref<StyleBox>(NULL);
atlas_tex = Ref<AtlasTexture>(NULL);
@@ -623,15 +623,15 @@ void TextureRegionEditor::_bind_methods() {
void TextureRegionEditor::edit(Object *p_obj) {
if (node_sprite)
node_sprite->remove_change_receptor(this);
- if (node_patch9)
- node_patch9->remove_change_receptor(this);
+ if (node_ninepatch)
+ node_ninepatch->remove_change_receptor(this);
if (obj_styleBox.is_valid())
obj_styleBox->remove_change_receptor(this);
if (atlas_tex.is_valid())
atlas_tex->remove_change_receptor(this);
if (p_obj) {
node_sprite = Object::cast_to<Sprite>(p_obj);
- node_patch9 = Object::cast_to<NinePatchRect>(p_obj);
+ node_ninepatch = Object::cast_to<NinePatchRect>(p_obj);
if (Object::cast_to<StyleBoxTexture>(p_obj))
obj_styleBox = Ref<StyleBoxTexture>(Object::cast_to<StyleBoxTexture>(p_obj));
if (Object::cast_to<AtlasTexture>(p_obj))
@@ -640,7 +640,7 @@ void TextureRegionEditor::edit(Object *p_obj) {
_edit_region();
} else {
node_sprite = NULL;
- node_patch9 = NULL;
+ node_ninepatch = NULL;
obj_styleBox = Ref<StyleBoxTexture>(NULL);
atlas_tex = Ref<AtlasTexture>(NULL);
}
@@ -659,8 +659,8 @@ void TextureRegionEditor::_edit_region() {
Ref<Texture> texture = NULL;
if (node_sprite)
texture = node_sprite->get_texture();
- else if (node_patch9)
- texture = node_patch9->get_texture();
+ else if (node_ninepatch)
+ texture = node_ninepatch->get_texture();
else if (obj_styleBox.is_valid())
texture = obj_styleBox->get_texture();
else if (atlas_tex.is_valid())
@@ -726,8 +726,8 @@ void TextureRegionEditor::_edit_region() {
if (node_sprite)
rect = node_sprite->get_region_rect();
- else if (node_patch9)
- rect = node_patch9->get_region_rect();
+ else if (node_ninepatch)
+ rect = node_ninepatch->get_region_rect();
else if (obj_styleBox.is_valid())
rect = obj_styleBox->get_region_rect();
else if (atlas_tex.is_valid())
@@ -736,23 +736,10 @@ void TextureRegionEditor::_edit_region() {
edit_draw->update();
}
-inline float _snap_scalar(float p_offset, float p_step, float separation, float p_target) {
- if (p_step != 0) {
- float a = Math::stepify(p_target - p_offset, p_step + separation) + p_offset;
- float b = a;
- if (p_target >= 0)
- b -= separation;
- else
- b += p_step;
- return (Math::abs(p_target - a) < Math::abs(p_target - b)) ? a : b;
- }
- return p_target;
-}
-
Vector2 TextureRegionEditor::snap_point(Vector2 p_target) const {
if (snap_mode == SNAP_GRID) {
- p_target.x = _snap_scalar(snap_offset.x, snap_step.x, snap_separation.x, p_target.x);
- p_target.y = _snap_scalar(snap_offset.y, snap_step.y, snap_separation.y, p_target.y);
+ p_target.x = Math::snap_scalar_seperation(snap_offset.x, snap_step.x, p_target.x, snap_separation.x);
+ p_target.y = Math::snap_scalar_seperation(snap_offset.y, snap_step.y, p_target.y, snap_separation.y);
}
return p_target;
@@ -760,7 +747,7 @@ Vector2 TextureRegionEditor::snap_point(Vector2 p_target) const {
TextureRegionEditor::TextureRegionEditor(EditorNode *p_editor) {
node_sprite = NULL;
- node_patch9 = NULL;
+ node_ninepatch = NULL;
obj_styleBox = Ref<StyleBoxTexture>(NULL);
atlas_tex = Ref<AtlasTexture>(NULL);
editor = p_editor;
@@ -873,6 +860,7 @@ TextureRegionEditor::TextureRegionEditor(EditorNode *p_editor) {
hb_tools->add_child(separator);
icon_zoom = memnew(TextureRect);
+ icon_zoom->set_stretch_mode(TextureRect::STRETCH_KEEP_ASPECT_CENTERED);
hb_tools->add_child(icon_zoom);
zoom_out = memnew(ToolButton);
diff --git a/editor/plugins/texture_region_editor_plugin.h b/editor/plugins/texture_region_editor_plugin.h
index 0789dde1c1..2058dad791 100644
--- a/editor/plugins/texture_region_editor_plugin.h
+++ b/editor/plugins/texture_region_editor_plugin.h
@@ -37,7 +37,7 @@
#include "editor/editor_node.h"
#include "editor/editor_plugin.h"
#include "scene/2d/sprite.h"
-#include "scene/gui/patch_9_rect.h"
+#include "scene/gui/nine_patch_rect.h"
#include "scene/resources/style_box.h"
#include "scene/resources/texture.h"
@@ -82,7 +82,7 @@ class TextureRegionEditor : public Control {
Vector2 snap_step;
Vector2 snap_separation;
- NinePatchRect *node_patch9;
+ NinePatchRect *node_ninepatch;
Sprite *node_sprite;
Ref<StyleBoxTexture> obj_styleBox;
Ref<AtlasTexture> atlas_tex;
diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp
index e500dec0ef..7f956b01ff 100644
--- a/editor/plugins/theme_editor_plugin.cpp
+++ b/editor/plugins/theme_editor_plugin.cpp
@@ -427,7 +427,9 @@ void ThemeEditor::_dialog_cbk() {
void ThemeEditor::_theme_menu_cbk(int p_option) {
- if (p_option == POPUP_CREATE_EMPTY || p_option == POPUP_CREATE_EDITOR_EMPTY) {
+ if (p_option == POPUP_CREATE_EMPTY || p_option == POPUP_CREATE_EDITOR_EMPTY || p_option == POPUP_IMPORT_EDITOR_THEME) {
+
+ bool import = (p_option == POPUP_IMPORT_EDITOR_THEME);
Ref<Theme> base_theme;
@@ -449,21 +451,21 @@ void ThemeEditor::_theme_menu_cbk(int p_option) {
base_theme->get_icon_list(type, &icons);
for (List<StringName>::Element *E = icons.front(); E; E = E->next()) {
- theme->set_icon(E->get(), type, Ref<Texture>());
+ theme->set_icon(E->get(), type, import ? base_theme->get_icon(E->get(), type) : Ref<Texture>());
}
List<StringName> shaders;
base_theme->get_shader_list(type, &shaders);
for (List<StringName>::Element *E = shaders.front(); E; E = E->next()) {
- theme->set_shader(E->get(), type, Ref<Shader>());
+ theme->set_shader(E->get(), type, import ? base_theme->get_shader(E->get(), type) : Ref<Shader>());
}
List<StringName> styleboxs;
base_theme->get_stylebox_list(type, &styleboxs);
for (List<StringName>::Element *E = styleboxs.front(); E; E = E->next()) {
- theme->set_stylebox(E->get(), type, Ref<StyleBox>());
+ theme->set_stylebox(E->get(), type, import ? base_theme->get_stylebox(E->get(), type) : Ref<StyleBox>());
}
List<StringName> fonts;
@@ -477,14 +479,14 @@ void ThemeEditor::_theme_menu_cbk(int p_option) {
base_theme->get_color_list(type, &colors);
for (List<StringName>::Element *E = colors.front(); E; E = E->next()) {
- theme->set_color(E->get(), type, Color());
+ theme->set_color(E->get(), type, import ? base_theme->get_color(E->get(), type) : Color());
}
List<StringName> constants;
base_theme->get_constant_list(type, &constants);
for (List<StringName>::Element *E = constants.front(); E; E = E->next()) {
- theme->set_constant(E->get(), type, base_theme->get_constant(type, E->get()));
+ theme->set_constant(E->get(), type, base_theme->get_constant(E->get(), type));
}
}
}
@@ -588,6 +590,8 @@ void ThemeEditor::_notification(int p_what) {
time_left = 1.5;
_refresh_interval();
}
+ } else if (p_what == NOTIFICATION_THEME_CHANGED) {
+ theme_menu->set_icon(get_icon("Theme", "EditorIcons"));
}
}
@@ -627,7 +631,9 @@ ThemeEditor::ThemeEditor() {
main_vb->add_child(hb_menu);
theme_menu = memnew(MenuButton);
- theme_menu->set_text(TTR("Theme"));
+ theme_menu->set_text(TTR("Edit theme.."));
+ theme_menu->set_flat(false);
+ theme_menu->set_tooltip(TTR("Theme editing menu."));
theme_menu->get_popup()->add_item(TTR("Add Item"), POPUP_ADD);
theme_menu->get_popup()->add_item(TTR("Add Class Items"), POPUP_CLASS_ADD);
theme_menu->get_popup()->add_item(TTR("Remove Item"), POPUP_REMOVE);
@@ -635,7 +641,7 @@ ThemeEditor::ThemeEditor() {
theme_menu->get_popup()->add_separator();
theme_menu->get_popup()->add_item(TTR("Create Empty Template"), POPUP_CREATE_EMPTY);
theme_menu->get_popup()->add_item(TTR("Create Empty Editor Template"), POPUP_CREATE_EDITOR_EMPTY);
-
+ theme_menu->get_popup()->add_item(TTR("Create From Current Editor Theme"), POPUP_IMPORT_EDITOR_THEME);
add_child(theme_menu);
theme_menu->set_position(Vector2(3, 3) * EDSCALE);
theme_menu->get_popup()->connect("id_pressed", this, "_theme_menu_cbk");
diff --git a/editor/plugins/theme_editor_plugin.h b/editor/plugins/theme_editor_plugin.h
index 16b2da94d1..4d46282ba1 100644
--- a/editor/plugins/theme_editor_plugin.h
+++ b/editor/plugins/theme_editor_plugin.h
@@ -69,7 +69,8 @@ class ThemeEditor : public Control {
POPUP_REMOVE,
POPUP_CLASS_REMOVE,
POPUP_CREATE_EMPTY,
- POPUP_CREATE_EDITOR_EMPTY
+ POPUP_CREATE_EDITOR_EMPTY,
+ POPUP_IMPORT_EDITOR_THEME
};
int popup_mode;
diff --git a/editor/plugins/tile_map_editor_plugin.cpp b/editor/plugins/tile_map_editor_plugin.cpp
index 2f2ed7bdf0..ffddd8a3a9 100644
--- a/editor/plugins/tile_map_editor_plugin.cpp
+++ b/editor/plugins/tile_map_editor_plugin.cpp
@@ -229,7 +229,7 @@ struct _PaletteEntry {
return name < p_rhs.name;
}
};
-}
+} // namespace
void TileMapEditor::_update_palette() {
@@ -363,7 +363,7 @@ PoolVector<Vector2> TileMapEditor::_bucket_fill(const Point2i &p_start, bool era
return PoolVector<Vector2>();
}
- Rect2i r = node->get_item_rect();
+ Rect2i r = node->_edit_get_rect();
r.position = r.position / node->get_cell_size();
r.size = r.size / node->get_cell_size();
@@ -945,6 +945,7 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
if (mm.is_valid()) {
Point2i new_over_tile = node->world_to_map(xform_inv.xform(mm->get_position()));
+ Point2i old_over_tile = over_tile;
if (new_over_tile != over_tile) {
@@ -963,17 +964,43 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
if (tool == TOOL_PAINTING) {
+ // Paint using bresenham line to prevent holes in painting if the user moves fast
+
+ Vector<Point2i> points = line(old_over_tile.x, over_tile.x, old_over_tile.y, over_tile.y);
int id = get_selected_tile();
- if (id != TileMap::INVALID_CELL) {
- if (!paint_undo.has(over_tile)) {
- paint_undo[over_tile] = _get_op_from_cell(over_tile);
+ for (int i = 0; i < points.size(); ++i) {
+
+ Point2i pos = points[i];
+
+ if (!paint_undo.has(pos)) {
+ paint_undo[pos] = _get_op_from_cell(pos);
}
- _set_cell(over_tile, id, flip_h, flip_v, transpose);
+ _set_cell(pos, id, flip_h, flip_v, transpose);
+ }
- return true;
+ return true;
+ }
+
+ if (tool == TOOL_ERASING) {
+
+ // erase using bresenham line to prevent holes in painting if the user moves fast
+
+ Vector<Point2i> points = line(old_over_tile.x, over_tile.x, old_over_tile.y, over_tile.y);
+
+ for (int i = 0; i < points.size(); ++i) {
+
+ Point2i pos = points[i];
+
+ if (!paint_undo.has(pos)) {
+ paint_undo[pos] = _get_op_from_cell(pos);
+ }
+
+ _set_cell(pos, TileMap::INVALID_CELL);
}
+
+ return true;
}
if (tool == TOOL_SELECTING) {
@@ -1044,16 +1071,6 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
return true;
}
- if (tool == TOOL_ERASING) {
-
- if (!paint_undo.has(over_tile)) {
- paint_undo[over_tile] = _get_op_from_cell(over_tile);
- }
-
- _set_cell(over_tile, TileMap::INVALID_CELL);
-
- return true;
- }
if (tool == TOOL_PICKING && Input::get_singleton()->is_mouse_button_pressed(BUTTON_LEFT)) {
_pick_tile(over_tile);
@@ -1152,7 +1169,7 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
return false;
}
-void TileMapEditor::_canvas_draw() {
+void TileMapEditor::forward_draw_over_canvas(Control *p_canvas) {
if (!node)
return;
@@ -1379,8 +1396,6 @@ void TileMapEditor::edit(Node *p_tile_map) {
if (p_tile_map) {
node = Object::cast_to<TileMap>(p_tile_map);
- if (!canvas_item_editor->is_connected("draw", this, "_canvas_draw"))
- canvas_item_editor->connect("draw", this, "_canvas_draw");
if (!canvas_item_editor->is_connected("mouse_entered", this, "_canvas_mouse_enter"))
canvas_item_editor->connect("mouse_entered", this, "_canvas_mouse_enter");
if (!canvas_item_editor->is_connected("mouse_exited", this, "_canvas_mouse_exit"))
@@ -1391,8 +1406,6 @@ void TileMapEditor::edit(Node *p_tile_map) {
} else {
node = NULL;
- if (canvas_item_editor->is_connected("draw", this, "_canvas_draw"))
- canvas_item_editor->disconnect("draw", this, "_canvas_draw");
if (canvas_item_editor->is_connected("mouse_entered", this, "_canvas_mouse_enter"))
canvas_item_editor->disconnect("mouse_entered", this, "_canvas_mouse_enter");
if (canvas_item_editor->is_connected("mouse_exited", this, "_canvas_mouse_exit"))
@@ -1428,7 +1441,6 @@ void TileMapEditor::_bind_methods() {
ClassDB::bind_method(D_METHOD("_text_changed"), &TileMapEditor::_text_changed);
ClassDB::bind_method(D_METHOD("_sbox_input"), &TileMapEditor::_sbox_input);
ClassDB::bind_method(D_METHOD("_menu_option"), &TileMapEditor::_menu_option);
- ClassDB::bind_method(D_METHOD("_canvas_draw"), &TileMapEditor::_canvas_draw);
ClassDB::bind_method(D_METHOD("_canvas_mouse_enter"), &TileMapEditor::_canvas_mouse_enter);
ClassDB::bind_method(D_METHOD("_canvas_mouse_exit"), &TileMapEditor::_canvas_mouse_exit);
ClassDB::bind_method(D_METHOD("_tileset_settings_changed"), &TileMapEditor::_tileset_settings_changed);
diff --git a/editor/plugins/tile_map_editor_plugin.h b/editor/plugins/tile_map_editor_plugin.h
index c8f29dfb7b..73474a3f3d 100644
--- a/editor/plugins/tile_map_editor_plugin.h
+++ b/editor/plugins/tile_map_editor_plugin.h
@@ -163,7 +163,6 @@ class TileMapEditor : public VBoxContainer {
void _text_changed(const String &p_text);
void _sbox_input(const Ref<InputEvent> &p_ie);
void _update_palette();
- void _canvas_draw();
void _menu_option(int p_option);
void _set_cell(const Point2i &p_pos, int p_value, bool p_flip_h = false, bool p_flip_v = false, bool p_transpose = false, bool p_with_undo = false);
@@ -183,6 +182,8 @@ public:
HBoxContainer *get_toolbar() const { return toolbar; }
bool forward_gui_input(const Ref<InputEvent> &p_event);
+ void forward_draw_over_canvas(Control *p_canvas);
+
void edit(Node *p_tile_map);
TileMapEditor(EditorNode *p_editor);
@@ -196,7 +197,8 @@ class TileMapEditorPlugin : public EditorPlugin {
TileMapEditor *tile_map_editor;
public:
- virtual bool forward_canvas_gui_input(const Transform2D &p_canvas_xform, const Ref<InputEvent> &p_event) { return tile_map_editor->forward_gui_input(p_event); }
+ virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event) { return tile_map_editor->forward_gui_input(p_event); }
+ virtual void forward_draw_over_canvas(Control *p_canvas) { tile_map_editor->forward_draw_over_canvas(p_canvas); }
virtual String get_name() const { return "TileMap"; }
bool has_main_screen() const { return false; }
diff --git a/editor/project_export.cpp b/editor/project_export.cpp
index e5b6f8e406..6500b10a3a 100644
--- a/editor/project_export.cpp
+++ b/editor/project_export.cpp
@@ -308,7 +308,7 @@ void ProjectExportDialog::_patch_button_pressed(Object *p_item, int p_column, in
if (p_id == 0) {
Vector<String> patches = current->get_patches();
ERR_FAIL_INDEX(patch_index, patches.size());
- patch_erase->set_text(vformat(TTR("Delete patch '" + patches[patch_index].get_file() + "' from list?")));
+ patch_erase->set_text(vformat(TTR("Delete patch '%s' from list?"), patches[patch_index].get_file()));
patch_erase->popup_centered_minsize();
} else {
patch_dialog->popup_centered_ratio();
@@ -717,6 +717,7 @@ void ProjectExportDialog::_export_project() {
export_project->set_access(FileDialog::ACCESS_FILESYSTEM);
export_project->clear_filters();
+ export_project->set_current_file(default_filename);
String extension = platform->get_binary_extension();
if (extension != String()) {
export_project->add_filter("*." + extension + " ; " + platform->get_name() + " Export");
@@ -726,6 +727,9 @@ void ProjectExportDialog::_export_project() {
}
void ProjectExportDialog::_export_project_to_path(const String &p_path) {
+ // Save this name for use in future exports (but drop the file extension)
+ default_filename = p_path.get_basename().get_file();
+ EditorSettings::get_singleton()->set_project_metadata("export_options", "default_filename", default_filename);
Ref<EditorExportPreset> current = EditorExport::get_singleton()->get_export_preset(presets->get_current());
ERR_FAIL_COND(current.is_null());
@@ -733,8 +737,12 @@ void ProjectExportDialog::_export_project_to_path(const String &p_path) {
ERR_FAIL_COND(platform.is_null());
Error err = platform->export_project(current, export_debug->is_pressed(), p_path, 0);
- if (err != OK)
+ if (err != OK) {
+ error_dialog->set_text(TTR("Export templates for this platform are missing/corrupted: ") + platform->get_name());
+ error_dialog->show();
+ error_dialog->popup_centered_minsize(Size2(300, 80));
ERR_PRINT("Failed to export project");
+ }
}
void ProjectExportDialog::_bind_methods() {
@@ -915,6 +923,7 @@ ProjectExportDialog::ProjectExportDialog() {
updating = false;
+ get_cancel()->set_text(TTR("Close"));
get_ok()->set_text(TTR("Export PCK/Zip"));
export_button = add_button(TTR("Export Project"), !OS::get_singleton()->get_swap_ok_cancel(), "export");
@@ -940,6 +949,12 @@ ProjectExportDialog::ProjectExportDialog() {
export_error2->add_color_override("font_color", get_color("error_color", "Editor"));
export_error2->set_text(" - " + TTR("Export templates for this platform are missing:") + " ");
+ error_dialog = memnew(AcceptDialog);
+ error_dialog->set_title("Error");
+ error_dialog->set_text(TTR("Export templates for this platform are missing/corrupted:") + " ");
+ main_vb->add_child(error_dialog);
+ error_dialog->hide();
+
LinkButton *download_templates = memnew(LinkButton);
download_templates->set_text(TTR("Manage Export Templates"));
export_templates_error->add_child(download_templates);
@@ -959,6 +974,8 @@ ProjectExportDialog::ProjectExportDialog() {
set_hide_on_ok(false);
editor_icons = "EditorIcons";
+
+ default_filename = EditorSettings::get_singleton()->get_project_metadata("export_options", "default_filename", String());
}
ProjectExportDialog::~ProjectExportDialog() {
diff --git a/editor/project_export.h b/editor/project_export.h
index 61de0f739a..b258112fa8 100644
--- a/editor/project_export.h
+++ b/editor/project_export.h
@@ -72,6 +72,7 @@ private:
Button *button_export;
bool updating;
+ AcceptDialog *error_dialog;
ConfirmationDialog *delete_confirm;
OptionButton *export_filter;
@@ -98,6 +99,8 @@ private:
Label *export_error;
HBoxContainer *export_templates_error;
+ String default_filename;
+
void _patch_selected(const String &p_path);
void _patch_deleted();
diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp
index 1fb3fb2ed1..16b85121ef 100644
--- a/editor/project_manager.cpp
+++ b/editor/project_manager.cpp
@@ -48,6 +48,7 @@
#include "scene/gui/separator.h"
#include "scene/gui/texture_rect.h"
#include "scene/gui/tool_button.h"
+#include "translation.h"
#include "version.h"
#include "version_hash.gen.h"
@@ -124,7 +125,7 @@ private:
}
if (valid_path == "") {
- set_message(TTR("The path does not exists."), MESSAGE_ERROR);
+ set_message(TTR("The path does not exist."), MESSAGE_ERROR);
memdelete(d);
return "";
}
@@ -232,7 +233,7 @@ private:
fdialog->set_mode(FileDialog::MODE_OPEN_FILE);
fdialog->clear_filters();
- fdialog->add_filter("project.godot ; " _MKSTR(VERSION_NAME) " Project");
+ fdialog->add_filter("project.godot ; " VERSION_NAME " Project");
} else {
fdialog->set_mode(FileDialog::MODE_OPEN_DIR);
}
@@ -283,7 +284,6 @@ private:
}
ProjectSettings *current = memnew(ProjectSettings);
- current->add_singleton(ProjectSettings::Singleton("Current"));
if (current->setup(dir, "")) {
set_message(TTR("Couldn't get project.godot in project path."), MESSAGE_ERROR);
@@ -502,7 +502,6 @@ public:
name_container->show();
ProjectSettings *current = memnew(ProjectSettings);
- current->add_singleton(ProjectSettings::Singleton("Current"));
if (current->setup(project_path->get_text(), "")) {
set_message(TTR("Couldn't get project.godot in the project path."), MESSAGE_ERROR);
@@ -750,6 +749,9 @@ void ProjectManager::_unhandled_input(const Ref<InputEvent> &p_ev) {
if (!k->is_pressed())
return;
+ if (tabs->get_current_tab() != 0)
+ return;
+
bool scancode_handled = true;
switch (k->get_scancode()) {
@@ -1049,7 +1051,7 @@ void ProjectManager::_load_recent_projects() {
ec->set_custom_minimum_size(Size2(0, 1));
vb->add_child(ec);
Label *title = memnew(Label(project_name));
- title->add_font_override("font", gui_base->get_font("large", "Fonts"));
+ title->add_font_override("font", gui_base->get_font("title", "EditorFonts"));
title->add_color_override("font_color", font_color);
title->set_clip_text(true);
vb->add_child(title);
@@ -1322,6 +1324,28 @@ void ProjectManager::_erase_project() {
erase_ask->popup_centered_minsize();
}
+void ProjectManager::_language_selected(int p_id) {
+
+ String lang = language_btn->get_item_metadata(p_id);
+ EditorSettings::get_singleton()->set("interface/editor/editor_language", lang);
+ language_btn->set_text(lang);
+ language_btn->set_icon(get_icon("Environment", "EditorIcons"));
+
+ language_restart_ask->set_text(TTR("Language changed.\nThe UI will update next time the editor or project manager starts."));
+ language_restart_ask->popup_centered();
+}
+
+void ProjectManager::_restart_confirm() {
+
+ List<String> args = OS::get_singleton()->get_cmdline_args();
+ String exec = OS::get_singleton()->get_executable_path();
+ OS::ProcessID pid = 0;
+ Error err = OS::get_singleton()->execute(exec, args, false, &pid);
+ ERR_FAIL_COND(err);
+
+ get_tree()->quit();
+}
+
void ProjectManager::_exit_dialog() {
get_tree()->quit();
@@ -1395,6 +1419,8 @@ void ProjectManager::_bind_methods() {
ClassDB::bind_method("_rename_project", &ProjectManager::_rename_project);
ClassDB::bind_method("_erase_project", &ProjectManager::_erase_project);
ClassDB::bind_method("_erase_project_confirm", &ProjectManager::_erase_project_confirm);
+ ClassDB::bind_method("_language_selected", &ProjectManager::_language_selected);
+ ClassDB::bind_method("_restart_confirm", &ProjectManager::_restart_confirm);
ClassDB::bind_method("_exit_dialog", &ProjectManager::_exit_dialog);
ClassDB::bind_method("_load_recent_projects", &ProjectManager::_load_recent_projects);
ClassDB::bind_method("_on_project_renamed", &ProjectManager::_on_project_renamed);
@@ -1420,7 +1446,8 @@ ProjectManager::ProjectManager() {
{
int dpi_mode = EditorSettings::get_singleton()->get("interface/editor/hidpi_mode");
if (dpi_mode == 0) {
- editor_set_scale(OS::get_singleton()->get_screen_dpi(0) >= 192 && OS::get_singleton()->get_screen_size(OS::get_singleton()->get_current_screen()).x > 2000 ? 2.0 : 1.0);
+ const int screen = OS::get_singleton()->get_current_screen();
+ editor_set_scale(OS::get_singleton()->get_screen_dpi(screen) >= 192 && OS::get_singleton()->get_screen_size(screen).x > 2000 ? 2.0 : 1.0);
} else if (dpi_mode == 1) {
editor_set_scale(0.75);
} else if (dpi_mode == 2) {
@@ -1456,14 +1483,13 @@ ProjectManager::ProjectManager() {
String cp;
cp.push_back(0xA9);
cp.push_back(0);
- OS::get_singleton()->set_window_title(_MKSTR(VERSION_NAME) + String(" - ") + TTR("Project Manager") + " - " + cp + " 2008-2017 Juan Linietsky, Ariel Manzur & Godot Contributors");
+ OS::get_singleton()->set_window_title(VERSION_NAME + String(" - ") + TTR("Project Manager") + " - " + cp + " 2008-2017 Juan Linietsky, Ariel Manzur & Godot Contributors");
HBoxContainer *top_hb = memnew(HBoxContainer);
vb->add_child(top_hb);
CenterContainer *ccl = memnew(CenterContainer);
Label *l = memnew(Label);
- l->set_text(_MKSTR(VERSION_NAME) + String(" - ") + TTR("Project Manager"));
- l->add_font_override("font", gui_base->get_font("doc", "EditorFonts"));
+ l->set_text(VERSION_NAME + String(" - ") + TTR("Project Manager"));
ccl->add_child(l);
top_hb->add_child(ccl);
top_hb->add_spacer();
@@ -1472,15 +1498,16 @@ ProjectManager::ProjectManager() {
if (hash.length() != 0)
hash = "." + hash.left(7);
l->set_text("v" VERSION_MKSTRING "" + hash);
- //l->add_font_override("font",get_font("bold","Fonts"));
l->set_align(Label::ALIGN_CENTER);
top_hb->add_child(l);
- //vb->add_child(memnew(HSeparator));
- //vb->add_margin_child("\n",memnew(Control));
+
+ Control *center_box = memnew(Control);
+ center_box->set_v_size_flags(SIZE_EXPAND_FILL);
+ vb->add_child(center_box);
tabs = memnew(TabContainer);
- vb->add_child(tabs);
- tabs->set_v_size_flags(SIZE_EXPAND_FILL);
+ center_box->add_child(tabs);
+ tabs->set_anchors_and_margins_preset(Control::PRESET_WIDE);
HBoxContainer *tree_hb = memnew(HBoxContainer);
projects_hb = tree_hb;
@@ -1581,6 +1608,40 @@ ProjectManager::ProjectManager() {
WARN_PRINT("Asset Library not available, as it requires SSL to work.");
}
+ HBoxContainer *settings_hb = memnew(HBoxContainer);
+ settings_hb->set_alignment(BoxContainer::ALIGN_END);
+ settings_hb->set_h_grow_direction(Control::GROW_DIRECTION_BEGIN);
+
+ language_btn = memnew(OptionButton);
+
+ Vector<String> editor_languages;
+ List<PropertyInfo> editor_settings_properties;
+ EditorSettings::get_singleton()->get_property_list(&editor_settings_properties);
+ for (List<PropertyInfo>::Element *E = editor_settings_properties.front(); E; E = E->next()) {
+ PropertyInfo &pi = E->get();
+ if (pi.name == "interface/editor/editor_language") {
+ editor_languages = pi.hint_string.split(",");
+ }
+ }
+ String current_lang = EditorSettings::get_singleton()->get("interface/editor/editor_language");
+ for (int i = 0; i < editor_languages.size(); i++) {
+ String lang = editor_languages[i];
+ String lang_name = TranslationServer::get_singleton()->get_locale_name(lang);
+ language_btn->add_item(lang_name + " [" + lang + "]", i);
+ language_btn->set_item_metadata(i, lang);
+ if (current_lang == lang) {
+ language_btn->select(i);
+ language_btn->set_text(lang);
+ }
+ }
+ language_btn->set_icon(get_icon("Environment", "EditorIcons"));
+
+ settings_hb->add_child(language_btn);
+ language_btn->connect("item_selected", this, "_language_selected");
+
+ center_box->add_child(settings_hb);
+ settings_hb->set_anchors_and_margins_preset(Control::PRESET_TOP_RIGHT);
+
CenterContainer *cc = memnew(CenterContainer);
Button *cancel = memnew(Button);
cancel->set_text(TTR("Exit"));
@@ -1591,6 +1652,13 @@ ProjectManager::ProjectManager() {
//
+ language_restart_ask = memnew(ConfirmationDialog);
+ language_restart_ask->get_ok()->set_text(TTR("Restart Now"));
+ language_restart_ask->get_ok()->connect("pressed", this, "_restart_confirm");
+ language_restart_ask->get_cancel()->set_text(TTR("Continue"));
+
+ gui_base->add_child(language_restart_ask);
+
erase_ask = memnew(ConfirmationDialog);
erase_ask->get_ok()->set_text(TTR("Remove"));
erase_ask->get_ok()->connect("pressed", this, "_erase_project_confirm");
diff --git a/editor/project_manager.h b/editor/project_manager.h
index bfae0b2297..656bd2d19c 100644
--- a/editor/project_manager.h
+++ b/editor/project_manager.h
@@ -54,6 +54,7 @@ class ProjectManager : public Control {
ProjectListFilter *project_filter;
+ ConfirmationDialog *language_restart_ask;
ConfirmationDialog *erase_ask;
ConfirmationDialog *multi_open_ask;
ConfirmationDialog *multi_run_ask;
@@ -71,6 +72,8 @@ class ProjectManager : public Control {
TabContainer *tabs;
+ OptionButton *language_btn;
+
Control *gui_base;
void _scan_projects();
@@ -84,6 +87,8 @@ class ProjectManager : public Control {
void _erase_project();
void _erase_project_confirm();
void _update_project_buttons();
+ void _language_selected(int p_id);
+ void _restart_confirm();
void _exit_dialog();
void _scan_begin(const String &p_base);
diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp
index 0cc368b21f..900f7625bc 100644
--- a/editor/project_settings_editor.cpp
+++ b/editor/project_settings_editor.cpp
@@ -81,6 +81,8 @@ void ProjectSettingsEditor::_notification(int p_what) {
search_button->set_icon(get_icon("Search", "EditorIcons"));
clear_button->set_icon(get_icon("Close", "EditorIcons"));
+ action_add_error->add_color_override("font_color", get_color("error_color", "Editor"));
+
translation_list->connect("button_pressed", this, "_translation_delete");
_update_actions();
popup_add->add_icon_item(get_icon("Keyboard", "EditorIcons"), TTR("Key "), INPUT_KEY); //"Key " - because the word 'key' has already been used as a key animation
@@ -783,12 +785,12 @@ void ProjectSettingsEditor::_item_del() {
String property = globals_editor->get_current_section().plus_file(path);
if (!ProjectSettings::get_singleton()->has_setting(property)) {
- EditorNode::get_singleton()->show_warning(TTR("No property '" + property + "' exists."));
+ EditorNode::get_singleton()->show_warning(vformat(TTR("No property '%s' exists."), property));
return;
}
if (ProjectSettings::get_singleton()->get_order(property) < ProjectSettings::NO_BUILTIN_ORDER_BASE) {
- EditorNode::get_singleton()->show_warning(TTR("Setting '" + property + "' is internal, and it can't be deleted."));
+ EditorNode::get_singleton()->show_warning(vformat(TTR("Setting '%s' is internal, and it can't be deleted."), property));
return;
}
@@ -819,12 +821,16 @@ void ProjectSettingsEditor::_action_check(String p_action) {
} else {
if (p_action.find("/") != -1 || p_action.find(":") != -1) {
- action_add->set_text(TTR("Can't contain '/' or ':'"));
+
+ action_add_error->set_text(TTR("Can't contain '/' or ':'"));
+ action_add_error->show();
action_add->set_disabled(true);
return;
}
if (ProjectSettings::get_singleton()->has_setting("input/" + p_action)) {
- action_add->set_text(TTR("Already existing"));
+
+ action_add_error->set_text(TTR("Already existing"));
+ action_add_error->show();
action_add->set_disabled(true);
return;
}
@@ -832,7 +838,7 @@ void ProjectSettingsEditor::_action_check(String p_action) {
action_add->set_disabled(false);
}
- action_add->set_text(TTR("Add"));
+ action_add_error->hide();
}
void ProjectSettingsEditor::_action_adds(String) {
@@ -869,7 +875,8 @@ void ProjectSettingsEditor::_action_add() {
return;
r->select(0);
input_editor->ensure_cursor_is_visible();
- action_add->set_text(TTR("Add"));
+ action_add_error->hide();
+ action_name->clear();
}
void ProjectSettingsEditor::_item_checked(const String &p_item, bool p_check) {
@@ -1127,7 +1134,11 @@ void ProjectSettingsEditor::_translation_res_option_changed() {
ERR_FAIL_COND(!remaps.has(key));
PoolStringArray r = remaps[key];
ERR_FAIL_INDEX(idx, r.size());
- r.set(idx, path + ":" + langs[which]);
+ if (translation_locales_idxs_remap.size() > 0) {
+ r.set(idx, path + ":" + langs[translation_locales_idxs_remap[which]]);
+ } else {
+ r.set(idx, path + ":" + langs[which]);
+ }
remaps[key] = r;
updating_translations = true;
@@ -1189,7 +1200,7 @@ void ProjectSettingsEditor::_translation_res_option_delete(Object *p_item, int p
ERR_FAIL_COND(!remaps.has(key));
PoolStringArray r = remaps[key];
- ERR_FAIL_INDEX(idx, remaps.size());
+ ERR_FAIL_INDEX(idx, r.size());
r.remove(idx);
remaps[key] = r;
@@ -1203,6 +1214,88 @@ void ProjectSettingsEditor::_translation_res_option_delete(Object *p_item, int p
undo_redo->commit_action();
}
+void ProjectSettingsEditor::_translation_filter_option_changed() {
+
+ int sel_id = translation_locale_filter_mode->get_selected_id();
+ TreeItem *t = translation_filter->get_selected();
+ String locale = t->get_tooltip(0);
+ bool checked = t->is_checked(0);
+
+ Variant prev;
+ Array f_locales_all;
+
+ if (ProjectSettings::get_singleton()->has_setting("locale/locale_filter")) {
+ f_locales_all = ProjectSettings::get_singleton()->get("locale/locale_filter");
+ prev = f_locales_all;
+
+ if (f_locales_all.size() != 2) {
+ f_locales_all.clear();
+ f_locales_all.append(sel_id);
+ f_locales_all.append(Array());
+ }
+ } else {
+ f_locales_all.append(sel_id);
+ f_locales_all.append(Array());
+ }
+
+ Array f_locales = f_locales_all[1];
+ int l_idx = f_locales.find(locale);
+
+ if (checked) {
+ if (l_idx == -1) {
+ f_locales.append(locale);
+ }
+ } else {
+ if (l_idx != -1) {
+ f_locales.remove(l_idx);
+ }
+ }
+
+ f_locales = f_locales.sort();
+
+ undo_redo->create_action(TTR("Changed Locale Filter"));
+ undo_redo->add_do_property(ProjectSettings::get_singleton(), "locale/locale_filter", f_locales_all);
+ undo_redo->add_undo_property(ProjectSettings::get_singleton(), "locale/locale_filter", prev);
+ undo_redo->add_do_method(this, "_update_translations");
+ undo_redo->add_undo_method(this, "_update_translations");
+ undo_redo->add_do_method(this, "_settings_changed");
+ undo_redo->add_undo_method(this, "_settings_changed");
+ undo_redo->commit_action();
+}
+
+void ProjectSettingsEditor::_translation_filter_mode_changed(int p_mode) {
+
+ int sel_id = translation_locale_filter_mode->get_selected_id();
+
+ Variant prev;
+ Array f_locales_all;
+
+ if (ProjectSettings::get_singleton()->has_setting("locale/locale_filter")) {
+ f_locales_all = ProjectSettings::get_singleton()->get("locale/locale_filter");
+ prev = f_locales_all;
+
+ if (f_locales_all.size() != 2) {
+ f_locales_all.clear();
+ f_locales_all.append(sel_id);
+ f_locales_all.append(Array());
+ } else {
+ f_locales_all[0] = sel_id;
+ }
+ } else {
+ f_locales_all.append(sel_id);
+ f_locales_all.append(Array());
+ }
+
+ undo_redo->create_action(TTR("Changed Locale Filter Mode"));
+ undo_redo->add_do_property(ProjectSettings::get_singleton(), "locale/locale_filter", f_locales_all);
+ undo_redo->add_undo_property(ProjectSettings::get_singleton(), "locale/locale_filter", prev);
+ undo_redo->add_do_method(this, "_update_translations");
+ undo_redo->add_undo_method(this, "_update_translations");
+ undo_redo->add_do_method(this, "_settings_changed");
+ undo_redo->add_undo_method(this, "_settings_changed");
+ undo_redo->commit_action();
+}
+
void ProjectSettingsEditor::_update_translations() {
//update translations
@@ -1225,7 +1318,62 @@ void ProjectSettingsEditor::_update_translations() {
t->set_text(0, translations[i].replace_first("res://", ""));
t->set_tooltip(0, translations[i]);
t->set_metadata(0, i);
- t->add_button(0, get_icon("Del", "EditorIcons"), 0, false, TTR("Remove"));
+ t->add_button(0, get_icon("Remove", "EditorIcons"), 0, false, TTR("Remove"));
+ }
+ }
+
+ Vector<String> langs = TranslationServer::get_all_locales();
+ Vector<String> names = TranslationServer::get_all_locale_names();
+
+ //update filter tab
+ Array l_filter_all;
+
+ bool is_arr_empty = true;
+ if (ProjectSettings::get_singleton()->has_setting("locale/locale_filter")) {
+
+ l_filter_all = ProjectSettings::get_singleton()->get("locale/locale_filter");
+
+ if (l_filter_all.size() == 2) {
+
+ translation_locale_filter_mode->select(l_filter_all[0]);
+ is_arr_empty = false;
+ }
+ }
+ if (is_arr_empty) {
+
+ l_filter_all.append(0);
+ l_filter_all.append(Array());
+ translation_locale_filter_mode->select(0);
+ }
+
+ int filter_mode = l_filter_all[0];
+ Array l_filter = l_filter_all[1];
+
+ int s = names.size();
+ if (!translation_locales_list_created) {
+
+ translation_locales_list_created = true;
+ translation_filter->clear();
+ root = translation_filter->create_item(NULL);
+ translation_filter->set_hide_root(true);
+ translation_filter_treeitems.resize(s);
+
+ for (int i = 0; i < s; i++) {
+ String n = names[i];
+ String l = langs[i];
+ TreeItem *t = translation_filter->create_item(root);
+ t->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
+ t->set_text(0, n);
+ t->set_editable(0, true);
+ t->set_tooltip(0, l);
+ t->set_checked(0, l_filter.has(l));
+ translation_filter_treeitems[i] = t;
+ }
+ } else {
+ for (int i = 0; i < s; i++) {
+
+ TreeItem *t = translation_filter_treeitems[i];
+ t->set_checked(0, l_filter.has(t->get_tooltip(0)));
}
}
@@ -1244,13 +1392,30 @@ void ProjectSettingsEditor::_update_translations() {
translation_remap_options->set_hide_root(true);
translation_res_option_add_button->set_disabled(true);
- Vector<String> langs = TranslationServer::get_all_locales();
- Vector<String> names = TranslationServer::get_all_locale_names();
- String langnames;
+ translation_locales_idxs_remap.clear();
+ translation_locales_idxs_remap.resize(l_filter.size());
+ int fl_idx_count = translation_locales_idxs_remap.size();
+
+ String langnames = "";
+ int l_idx = 0;
for (int i = 0; i < names.size(); i++) {
- if (i > 0)
- langnames += ",";
- langnames += names[i];
+
+ if (filter_mode == SHOW_ONLY_SELECTED_LOCALES && fl_idx_count != 0) {
+ if (l_filter.size() > 0) {
+
+ if (l_filter.find(langs[i]) != -1) {
+ if (langnames.length() > 0)
+ langnames += ",";
+ langnames += names[i];
+ translation_locales_idxs_remap[l_idx] = i;
+ l_idx++;
+ }
+ }
+ } else {
+ if (i > 0)
+ langnames += ",";
+ langnames += names[i];
+ }
}
if (ProjectSettings::get_singleton()->has_setting("locale/translation_remaps")) {
@@ -1271,7 +1436,7 @@ void ProjectSettingsEditor::_update_translations() {
t->set_text(0, keys[i].replace_first("res://", ""));
t->set_tooltip(0, keys[i]);
t->set_metadata(0, keys[i]);
- t->add_button(0, get_icon("Del", "EditorIcons"), 0, false, TTR("Remove"));
+ t->add_button(0, get_icon("Remove", "EditorIcons"), 0, false, TTR("Remove"));
if (keys[i] == remap_selected) {
t->select(0);
translation_res_option_add_button->set_disabled(false);
@@ -1289,17 +1454,24 @@ void ProjectSettingsEditor::_update_translations() {
t2->set_text(0, path.replace_first("res://", ""));
t2->set_tooltip(0, path);
t2->set_metadata(0, j);
- t2->add_button(0, get_icon("Del", "EditorIcons"), 0, false, TTR("Remove"));
+ t2->add_button(0, get_icon("Remove", "EditorIcons"), 0, false, TTR("Remove"));
t2->set_cell_mode(1, TreeItem::CELL_MODE_RANGE);
t2->set_text(1, langnames);
t2->set_editable(1, true);
t2->set_metadata(1, path);
int idx = langs.find(locale);
- print_line("find " + locale + " at " + itos(idx));
+ //print_line("find " + locale + " at " + itos(idx));
if (idx < 0)
idx = 0;
- t2->set_range(1, idx);
+ int f_idx = translation_locales_idxs_remap.find(idx);
+ if (f_idx != -1 && fl_idx_count > 0 && filter_mode == SHOW_ONLY_SELECTED_LOCALES) {
+
+ t2->set_range(1, f_idx);
+ } else {
+
+ t2->set_range(1, idx);
+ }
}
}
}
@@ -1381,6 +1553,9 @@ void ProjectSettingsEditor::_bind_methods() {
ClassDB::bind_method(D_METHOD("_translation_res_delete"), &ProjectSettingsEditor::_translation_res_delete);
ClassDB::bind_method(D_METHOD("_translation_res_option_delete"), &ProjectSettingsEditor::_translation_res_option_delete);
+ ClassDB::bind_method(D_METHOD("_translation_filter_option_changed"), &ProjectSettingsEditor::_translation_filter_option_changed);
+ ClassDB::bind_method(D_METHOD("_translation_filter_mode_changed"), &ProjectSettingsEditor::_translation_filter_mode_changed);
+
ClassDB::bind_method(D_METHOD("_clear_search_box"), &ProjectSettingsEditor::_clear_search_box);
ClassDB::bind_method(D_METHOD("_toggle_search_bar"), &ProjectSettingsEditor::_toggle_search_bar);
@@ -1528,6 +1703,10 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) {
action_name->connect("text_entered", this, "_action_adds");
action_name->connect("text_changed", this, "_action_check");
+ action_add_error = memnew(Label);
+ hbc->add_child(action_add_error);
+ action_add_error->hide();
+
add = memnew(Button);
hbc->add_child(add);
add->set_custom_minimum_size(Size2(150, 0) * EDSCALE);
@@ -1601,6 +1780,9 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) {
translations->set_tab_align(TabContainer::ALIGN_LEFT);
translations->set_name(TTR("Localization"));
tab_container->add_child(translations);
+ //remap for properly select language in popup
+ translation_locales_idxs_remap = Vector<int>();
+ translation_locales_list_created = false;
{
@@ -1684,6 +1866,29 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) {
}
{
+ VBoxContainer *tvb = memnew(VBoxContainer);
+ translations->add_child(tvb);
+ tvb->set_name(TTR("Locales Filter"));
+ VBoxContainer *tmc = memnew(VBoxContainer);
+ tmc->set_v_size_flags(SIZE_EXPAND_FILL);
+ tvb->add_child(tmc);
+
+ translation_locale_filter_mode = memnew(OptionButton);
+ translation_locale_filter_mode->add_item(TTR("Show all locales"), SHOW_ALL_LOCALES);
+ translation_locale_filter_mode->add_item(TTR("Show only selected locales"), SHOW_ONLY_SELECTED_LOCALES);
+ translation_locale_filter_mode->select(0);
+ tmc->add_margin_child(TTR("Filter mode:"), translation_locale_filter_mode);
+ translation_locale_filter_mode->connect("item_selected", this, "_translation_filter_mode_changed");
+
+ translation_filter = memnew(Tree);
+ translation_filter->set_v_size_flags(SIZE_EXPAND_FILL);
+ translation_filter->set_columns(1);
+ tmc->add_child(memnew(Label(TTR("Locales:"))));
+ tmc->add_child(translation_filter);
+ translation_filter->connect("item_edited", this, "_translation_filter_option_changed");
+ }
+
+ {
autoload_settings = memnew(EditorAutoloadSettings);
autoload_settings->set_name(TTR("AutoLoad"));
tab_container->add_child(autoload_settings);
diff --git a/editor/project_settings_editor.h b/editor/project_settings_editor.h
index 7f9b18a968..dbca158133 100644
--- a/editor/project_settings_editor.h
+++ b/editor/project_settings_editor.h
@@ -49,6 +49,11 @@ class ProjectSettingsEditor : public AcceptDialog {
INPUT_MOUSE_BUTTON
};
+ enum LocaleFilter {
+ SHOW_ALL_LOCALES,
+ SHOW_ONLY_SELECTED_LOCALES,
+ };
+
TabContainer *tab_container;
Timer *timer;
@@ -81,6 +86,7 @@ class ProjectSettingsEditor : public AcceptDialog {
LineEdit *action_name;
Button *action_add;
+ Label *action_add_error;
Tree *input_editor;
bool setting;
bool updating_translations;
@@ -95,6 +101,11 @@ class ProjectSettingsEditor : public AcceptDialog {
EditorFileDialog *translation_res_option_file_open;
Tree *translation_remap;
Tree *translation_remap_options;
+ Tree *translation_filter;
+ bool translation_locales_list_created;
+ OptionButton *translation_locale_filter_mode;
+ Vector<TreeItem *> translation_filter_treeitems;
+ Vector<int> translation_locales_idxs_remap;
EditorAutoloadSettings *autoload_settings;
@@ -142,6 +153,9 @@ class ProjectSettingsEditor : public AcceptDialog {
void _translation_res_option_changed();
void _translation_res_option_delete(Object *p_item, int p_column, int p_button);
+ void _translation_filter_option_changed();
+ void _translation_filter_mode_changed(int p_mode);
+
void _toggle_search_bar(bool p_pressed);
void _clear_search_box();
diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp
index 47ebf49c43..bc7d8f4b14 100644
--- a/editor/property_editor.cpp
+++ b/editor/property_editor.cpp
@@ -40,6 +40,7 @@
#include "core/project_settings.h"
#include "editor/array_property_edit.h"
#include "editor/create_dialog.h"
+#include "editor/dictionary_property_edit.h"
#include "editor/editor_export.h"
#include "editor/editor_file_system.h"
#include "editor/editor_help.h"
@@ -376,7 +377,7 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant::
if (hint == PROPERTY_HINT_RANGE) {
int c = hint_text.get_slice_count(",");
- float min = 0, max = 100, step = 1;
+ float min = 0, max = 100, step = type == Variant::REAL ? .01 : 1;
if (c >= 1) {
if (!hint_text.get_slice(",", 0).empty())
@@ -415,7 +416,11 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant::
menu->clear();
Vector<String> options = hint_text.split(",");
for (int i = 0; i < options.size(); i++) {
- menu->add_item(options[i], i);
+ if (options[i].find(":") != -1) {
+ menu->add_item(options[i].get_slicec(':', 0), options[i].get_slicec(':', 1).to_int());
+ } else {
+ menu->add_item(options[i], i);
+ }
}
menu->set_position(get_position());
menu->popup();
@@ -755,7 +760,7 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant::
value_editor[3]->set_text(String::num(q.w));
} break;
- case Variant::RECT3: {
+ case Variant::AABB: {
field_names.push_back("px");
field_names.push_back("py");
@@ -765,7 +770,7 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant::
field_names.push_back("sz");
config_value_editors(6, 3, 16, field_names);
- Rect3 aabb = v;
+ AABB aabb = v;
value_editor[0]->set_text(String::num(aabb.position.x));
value_editor[1]->set_text(String::num(aabb.position.y));
value_editor[2]->set_text(String::num(aabb.position.z));
@@ -861,7 +866,7 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant::
names.push_back(TTR("Assign"));
names.push_back(TTR("Clear"));
- if (owner->is_class("Node") && (v.get_type() == Variant::NODE_PATH) && Object::cast_to<Node>(owner)->has_node(v))
+ if (owner && owner->is_class("Node") && (v.get_type() == Variant::NODE_PATH) && Object::cast_to<Node>(owner)->has_node(v))
names.push_back(TTR("Select Node"));
config_action_buttons(names);
@@ -1153,7 +1158,8 @@ void CustomPropertyEditor::_node_path_selected(NodePath p_path) {
node = Object::cast_to<Node>(owner);
else if (owner->is_class("ArrayPropertyEdit"))
node = Object::cast_to<ArrayPropertyEdit>(owner)->get_node();
-
+ else if (owner->is_class("DictionaryPropertyEdit"))
+ node = Object::cast_to<DictionaryPropertyEdit>(owner)->get_node();
if (!node) {
v = p_path;
emit_signal("variant_changed");
@@ -1585,7 +1591,7 @@ void CustomPropertyEditor::_modified(String p_string) {
_emit_changed_whole_or_field();
} break;
- case Variant::RECT3: {
+ case Variant::AABB: {
Vector3 pos;
Vector3 size;
@@ -1605,7 +1611,7 @@ void CustomPropertyEditor::_modified(String p_string) {
size.y = value_editor[4]->get_text().to_double();
size.z = value_editor[5]->get_text().to_double();
}
- v = Rect3(pos, size);
+ v = AABB(pos, size);
_emit_changed_whole_or_field();
} break;
@@ -1727,7 +1733,7 @@ void CustomPropertyEditor::_focus_enter() {
case Variant::VECTOR3:
case Variant::PLANE:
case Variant::QUAT:
- case Variant::RECT3:
+ case Variant::AABB:
case Variant::TRANSFORM2D:
case Variant::BASIS:
case Variant::TRANSFORM: {
@@ -1752,7 +1758,7 @@ void CustomPropertyEditor::_focus_exit() {
case Variant::VECTOR3:
case Variant::PLANE:
case Variant::QUAT:
- case Variant::RECT3:
+ case Variant::AABB:
case Variant::TRANSFORM2D:
case Variant::BASIS:
case Variant::TRANSFORM: {
@@ -1766,19 +1772,19 @@ void CustomPropertyEditor::_focus_exit() {
void CustomPropertyEditor::config_action_buttons(const List<String> &p_strings) {
- int w = 100;
- int h = 18;
- int m = 5;
+ int cell_width = 60;
+ int cell_height = 25;
+ int cell_margin = 5;
- set_size(Size2(w, m * 2 + (h + m) * p_strings.size()));
+ set_size(Size2(cell_margin + (cell_width + cell_margin) * p_strings.size(), (cell_margin * 2) + cell_height) * EDSCALE);
for (int i = 0; i < MAX_ACTION_BUTTONS; i++) {
if (i < p_strings.size()) {
action_buttons[i]->show();
action_buttons[i]->set_text(p_strings[i]);
- action_buttons[i]->set_position(Point2(m, m + i * (h + m)));
- action_buttons[i]->set_size(Size2(w - m * 2, h));
+ action_buttons[i]->set_position(Point2(cell_margin + (cell_width + cell_margin) * i, cell_margin) * EDSCALE);
+ action_buttons[i]->set_size(Size2(cell_width, cell_height - cell_margin * 2) * EDSCALE);
action_buttons[i]->set_flat(true);
} else {
action_buttons[i]->hide();
@@ -1788,13 +1794,14 @@ void CustomPropertyEditor::config_action_buttons(const List<String> &p_strings)
void CustomPropertyEditor::config_value_editors(int p_amount, int p_columns, int p_label_w, const List<String> &p_strings) {
- int w = 80;
- int h = 20;
- int m = 10;
+ int cell_width = 95;
+ int cell_height = 25;
+ int cell_margin = 5;
+ int hor_spacing = 5; // Spacing between labels and their values
int rows = ((p_amount - 1) / p_columns) + 1;
- set_size(Size2(m * (1 + p_columns) + (w + p_label_w) * p_columns, m * (1 + rows) + h * rows));
+ set_size(Size2(cell_margin + p_label_w + (cell_width + cell_margin + p_label_w) * p_columns, cell_margin + (cell_height + cell_margin) * rows) * EDSCALE);
for (int i = 0; i < MAX_VALUE_EDITORS; i++) {
@@ -1805,9 +1812,9 @@ void CustomPropertyEditor::config_value_editors(int p_amount, int p_columns, int
value_editor[i]->show();
value_label[i]->show();
value_label[i]->set_text(i < p_strings.size() ? p_strings[i] : String(""));
- value_editor[i]->set_position(Point2(m + p_label_w + c * (w + m + p_label_w), m + r * (h + m)));
- value_editor[i]->set_size(Size2(w, h));
- value_label[i]->set_position(Point2(m + c * (w + m + p_label_w), m + r * (h + m)));
+ value_editor[i]->set_position(Point2(cell_margin + p_label_w + hor_spacing + (cell_width + cell_margin + p_label_w + hor_spacing) * c, cell_margin + (cell_height + cell_margin) * r) * EDSCALE);
+ value_editor[i]->set_size(Size2(cell_width, cell_height));
+ value_label[i]->set_position(Point2(cell_margin + (cell_width + cell_margin + p_label_w + hor_spacing) * c, cell_margin + (cell_height + cell_margin) * r) * EDSCALE);
value_editor[i]->set_editable(!read_only);
} else {
value_editor[i]->hide();
@@ -2237,7 +2244,7 @@ void PropertyEditor::set_item_text(TreeItem *p_item, int p_type, const String &p
case Variant::VECTOR3:
case Variant::QUAT:
case Variant::VECTOR2:
- case Variant::RECT3:
+ case Variant::AABB:
case Variant::RECT2:
case Variant::TRANSFORM2D:
case Variant::BASIS:
@@ -3032,7 +3039,7 @@ void PropertyEditor::update_tree() {
if (p.hint == PROPERTY_HINT_SPRITE_FRAME || p.hint == PROPERTY_HINT_RANGE || p.hint == PROPERTY_HINT_EXP_RANGE) {
int c = p.hint_string.get_slice_count(",");
- float min = 0, max = 100, step = 1;
+ float min = 0, max = 100, step = p.type == Variant::REAL ? .01 : 1;
if (c >= 1) {
min = p.hint_string.get_slice(",", 0).to_double();
@@ -3210,9 +3217,14 @@ void PropertyEditor::update_tree() {
} break;
case Variant::DICTIONARY: {
+ Variant v = obj->get(p.name);
+
item->set_cell_mode(1, TreeItem::CELL_MODE_STRING);
- item->set_editable(1, false);
- item->set_text(1, obj->get(p.name).operator String());
+ item->set_text(1, String("Dictionary{") + itos(v.call("size")) + "}");
+ item->add_button(1, get_icon("EditResource", "EditorIcons"));
+
+ if (show_type_icons)
+ item->set_icon(0, get_icon("DictionaryData", "EditorIcons"));
} break;
@@ -3366,13 +3378,13 @@ void PropertyEditor::update_tree() {
item->set_icon(0, get_icon("Plane", "EditorIcons"));
} break;
- case Variant::RECT3: {
+ case Variant::AABB: {
item->set_cell_mode(1, TreeItem::CELL_MODE_CUSTOM);
item->set_editable(1, true);
- item->set_text(1, "Rect3");
+ item->set_text(1, "AABB");
if (show_type_icons)
- item->set_icon(0, get_icon("Rect3", "EditorIcons"));
+ item->set_icon(0, get_icon("AABB", "EditorIcons"));
} break;
case Variant::QUAT: {
@@ -3411,7 +3423,9 @@ void PropertyEditor::update_tree() {
type = p.hint_string;
RES res = obj->get(p.name).operator RefPtr();
-
+ if (type.begins_with("RES:") && type != "RES:") { // Remote resources
+ res = ResourceLoader::load(type.substr(4, type.length()));
+ }
Ref<EncodedObjectAsID> encoded = obj->get(p.name); //for debugger and remote tools
if (encoded.is_valid()) {
@@ -3422,6 +3436,7 @@ void PropertyEditor::update_tree() {
item->set_editable(1, true);
} else if (obj->get(p.name).get_type() == Variant::NIL || res.is_null()) {
+
item->set_text(1, "<null>");
item->set_icon(1, Ref<Texture>());
item->set_custom_as_button(1, false);
@@ -3580,7 +3595,7 @@ void PropertyEditor::_edit_set(const String &p_name, const Variant &p_value, boo
}
}
- if (!undo_redo || Object::cast_to<ArrayPropertyEdit>(obj)) { //kind of hacky
+ if (!undo_redo || Object::cast_to<ArrayPropertyEdit>(obj) || Object::cast_to<DictionaryPropertyEdit>(obj)) { //kind of hacky
obj->set(p_name, p_value);
if (p_refresh_all)
@@ -3713,7 +3728,7 @@ void PropertyEditor::_item_edited() {
_edit_set(name, item->get_text(1), refresh_all);
}
} break;
- // math types
+ // math types
case Variant::VECTOR3: {
@@ -3724,7 +3739,7 @@ void PropertyEditor::_item_edited() {
case Variant::QUAT: {
} break;
- case Variant::RECT3: {
+ case Variant::AABB: {
} break;
case Variant::BASIS: {
@@ -3978,8 +3993,20 @@ void PropertyEditor::_edit_button(Object *p_item, int p_column, int p_button) {
Ref<ArrayPropertyEdit> ape = memnew(ArrayPropertyEdit);
ape->edit(obj, n, ht, Variant::Type(t));
-
EditorNode::get_singleton()->push_item(ape.ptr());
+
+ } else if (t == Variant::DICTIONARY) {
+
+ Variant v = obj->get(n);
+
+ if (v.get_type() != t) {
+ Variant::CallError ce;
+ v = Variant::construct(Variant::Type(t), NULL, 0, ce);
+ }
+
+ Ref<DictionaryPropertyEdit> dpe = memnew(DictionaryPropertyEdit);
+ dpe->edit(obj, n);
+ EditorNode::get_singleton()->push_item(dpe.ptr());
}
}
}
@@ -4257,7 +4284,7 @@ PropertyEditor::PropertyEditor() {
use_filter = false;
subsection_selectable = false;
property_selectable = false;
- show_type_icons = EDITOR_DEF("interface/editor/show_type_icons", false);
+ show_type_icons = false; // maybe one day will return.
}
PropertyEditor::~PropertyEditor() {
diff --git a/editor/pvrtc_compress.cpp b/editor/pvrtc_compress.cpp
index 13d74a6593..575ff40287 100644
--- a/editor/pvrtc_compress.cpp
+++ b/editor/pvrtc_compress.cpp
@@ -62,12 +62,12 @@ static void _compress_image(Image::CompressMode p_mode, Image *p_image) {
}
return;
}
- String spath = EditorSettings::get_singleton()->get_settings_path();
+ String tmppath = EditorSettings::get_singleton()->get_cache_dir();
List<String> args;
- String src_img = spath + "/" + "_tmp_src_img.png";
- String dst_img = spath + "/" + "_tmp_dst_img.pvr";
+ String src_img = tmppath.plus_file("_tmp_src_img.png");
+ String dst_img = tmppath.plus_file("_tmp_dst_img.pvr");
args.push_back("-i");
args.push_back(src_img);
diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp
index f3e59932c4..1d2647badc 100644
--- a/editor/scene_tree_dock.cpp
+++ b/editor/scene_tree_dock.cpp
@@ -319,6 +319,14 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
editor->push_item(existing.ptr());
else {
String path = selected->get_filename();
+ if (path == "") {
+ String root_path = editor_data->get_edited_scene_root()->get_filename();
+ if (root_path == "") {
+ path = "res://" + selected->get_name();
+ } else {
+ path = root_path.get_base_dir() + "/" + selected->get_name();
+ }
+ }
script_create_dialog->config(selected->get_class(), path);
script_create_dialog->popup_centered();
}
@@ -435,8 +443,8 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
List<Node *> owned;
node->get_owned_by(node->get_owner(), &owned);
- Map<Node *, Node *> duplimap;
- Node *dup = _duplicate(node, duplimap);
+ Map<const Node *, Node *> duplimap;
+ Node *dup = node->duplicate_from_editor(duplimap);
ERR_CONTINUE(!dup);
@@ -525,10 +533,6 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
if (p_confirm_override) {
_delete_confirm();
- // hack, force 2d editor viewport to refresh after deletion
- if (CanvasItemEditor *editor = CanvasItemEditor::get_singleton())
- editor->get_viewport_control()->update();
-
} else {
delete_dialog->set_text(TTR("Delete Node(s)?"));
delete_dialog->popup_centered_minsize();
@@ -741,6 +745,10 @@ void SceneTreeDock::_notification(int p_what) {
canvas_item_plugin->get_canvas_item_editor()->connect("item_group_status_changed", scene_tree, "_update_tree");
scene_tree->connect("node_changed", canvas_item_plugin->get_canvas_item_editor()->get_viewport_control(), "update");
}
+
+ SpatialEditorPlugin *spatial_editor_plugin = Object::cast_to<SpatialEditorPlugin>(editor_data->get_editor("3D"));
+ spatial_editor_plugin->get_spatial_editor()->connect("item_lock_status_changed", scene_tree, "_update_tree");
+
button_add->set_icon(get_icon("Add", "EditorIcons"));
button_instance->set_icon(get_icon("Instance", "EditorIcons"));
button_create_script->set_icon(get_icon("ScriptCreate", "EditorIcons"));
@@ -817,74 +825,6 @@ void SceneTreeDock::_node_renamed() {
_node_selected();
}
-Node *SceneTreeDock::_duplicate(Node *p_node, Map<Node *, Node *> &duplimap) {
-
- Node *node = NULL;
-
- if (p_node->get_filename() != "") { //an instance
-
- Ref<PackedScene> sd = ResourceLoader::load(p_node->get_filename());
- ERR_FAIL_COND_V(!sd.is_valid(), NULL);
- node = sd->instance(PackedScene::GEN_EDIT_STATE_INSTANCE);
- ERR_FAIL_COND_V(!node, NULL);
- node->set_scene_instance_load_placeholder(p_node->get_scene_instance_load_placeholder());
- } else {
- Object *obj = ClassDB::instance(p_node->get_class());
- ERR_FAIL_COND_V(!obj, NULL);
- node = Object::cast_to<Node>(obj);
- if (!node)
- memdelete(obj);
- ERR_FAIL_COND_V(!node, NULL);
- }
-
- List<PropertyInfo> plist;
-
- p_node->get_property_list(&plist);
-
- for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) {
-
- if (!(E->get().usage & PROPERTY_USAGE_STORAGE))
- continue;
- String name = E->get().name;
- Variant value = p_node->get(name);
- // Duplicate dictionaries and arrays, mainly needed for __meta__
- if (value.get_type() == Variant::DICTIONARY) {
- value = Dictionary(value).copy();
- } else if (value.get_type() == Variant::ARRAY) {
- value = Array(value).duplicate();
- }
- node->set(name, value);
- }
-
- List<Node::GroupInfo> group_info;
- p_node->get_groups(&group_info);
- for (List<Node::GroupInfo>::Element *E = group_info.front(); E; E = E->next()) {
-
- if (E->get().persistent)
- node->add_to_group(E->get().name, true);
- }
-
- node->set_name(p_node->get_name());
- duplimap[p_node] = node;
-
- for (int i = 0; i < p_node->get_child_count(); i++) {
-
- Node *child = p_node->get_child(i);
- if (p_node->get_owner() != child->get_owner())
- continue; //don't bother with not in-scene nodes.
-
- Node *dup = _duplicate(child, duplimap);
- if (!dup) {
- memdelete(node);
- return NULL;
- }
-
- node->add_child(dup);
- }
-
- return node;
-}
-
void SceneTreeDock::_set_owners(Node *p_owner, const Array &p_nodes) {
for (int i = 0; i < p_nodes.size(); i++) {
@@ -1292,6 +1232,7 @@ void SceneTreeDock::_delete_confirm() {
editor_data->get_undo_redo().add_do_method(editor, "set_edited_scene", (Object *)NULL);
editor_data->get_undo_redo().add_undo_method(editor, "set_edited_scene", edited_scene);
editor_data->get_undo_redo().add_undo_method(edited_scene, "set_owner", edited_scene->get_owner());
+ editor_data->get_undo_redo().add_undo_method(scene_tree, "update_tree");
editor_data->get_undo_redo().add_undo_reference(edited_scene);
} else {
@@ -1337,6 +1278,12 @@ void SceneTreeDock::_delete_confirm() {
}
}
editor_data->get_undo_redo().commit_action();
+
+ // hack, force 2d editor viewport to refresh after deletion
+ if (CanvasItemEditor *editor = CanvasItemEditor::get_singleton())
+ editor->get_viewport_control()->update();
+
+ editor->push_item(NULL);
}
void SceneTreeDock::_selection_changed() {
@@ -1404,6 +1351,7 @@ void SceneTreeDock::_create() {
} else {
editor_data->get_undo_redo().add_do_method(editor, "set_edited_scene", child);
+ editor_data->get_undo_redo().add_do_method(scene_tree, "update_tree");
editor_data->get_undo_redo().add_do_reference(child);
editor_data->get_undo_redo().add_undo_method(editor, "set_edited_scene", (Object *)NULL);
}
@@ -1439,6 +1387,8 @@ void SceneTreeDock::_create() {
for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) {
if (!(E->get().usage & PROPERTY_USAGE_STORAGE))
continue;
+ if (E->get().name == "__meta__")
+ continue;
newnode->set(E->get().name, n->get(E->get().name));
}
@@ -1868,6 +1818,45 @@ void SceneTreeDock::open_script_dialog(Node *p_for_node) {
_tool_selected(TOOL_ATTACH_SCRIPT);
}
+void SceneTreeDock::add_remote_tree_editor(Control *p_remote) {
+ ERR_FAIL_COND(remote_tree != NULL);
+ add_child(p_remote);
+ remote_tree = p_remote;
+ remote_tree->hide();
+}
+
+void SceneTreeDock::show_remote_tree() {
+
+ button_hb->show();
+ _remote_tree_selected();
+}
+
+void SceneTreeDock::hide_remote_tree() {
+
+ button_hb->hide();
+ _local_tree_selected();
+}
+
+void SceneTreeDock::_remote_tree_selected() {
+
+ scene_tree->hide();
+ if (remote_tree)
+ remote_tree->show();
+ edit_remote->set_pressed(true);
+ edit_local->set_pressed(false);
+}
+
+void SceneTreeDock::_local_tree_selected() {
+
+ scene_tree->show();
+ if (remote_tree)
+ remote_tree->hide();
+ edit_remote->set_pressed(false);
+ edit_local->set_pressed(true);
+
+ _node_selected();
+}
+
void SceneTreeDock::_bind_methods() {
ClassDB::bind_method(D_METHOD("_tool_selected"), &SceneTreeDock::_tool_selected, DEFVAL(false));
@@ -1893,6 +1882,8 @@ void SceneTreeDock::_bind_methods() {
ClassDB::bind_method(D_METHOD("_tree_rmb"), &SceneTreeDock::_tree_rmb);
ClassDB::bind_method(D_METHOD("_filter_changed"), &SceneTreeDock::_filter_changed);
ClassDB::bind_method(D_METHOD("_focus_node"), &SceneTreeDock::_focus_node);
+ ClassDB::bind_method(D_METHOD("_remote_tree_selected"), &SceneTreeDock::_remote_tree_selected);
+ ClassDB::bind_method(D_METHOD("_local_tree_selected"), &SceneTreeDock::_local_tree_selected);
ClassDB::bind_method(D_METHOD("instance"), &SceneTreeDock::instance);
}
@@ -1963,7 +1954,28 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor, Node *p_scene_root, EditorSel
button_clear_script = tb;
tb->hide();
+ button_hb = memnew(HBoxContainer);
+ vbc->add_child(button_hb);
+
+ edit_remote = memnew(ToolButton);
+ button_hb->add_child(edit_remote);
+ edit_remote->set_h_size_flags(SIZE_EXPAND_FILL);
+ edit_remote->set_text(TTR("Remote"));
+ edit_remote->set_toggle_mode(true);
+ edit_remote->connect("pressed", this, "_remote_tree_selected");
+
+ edit_local = memnew(ToolButton);
+ button_hb->add_child(edit_local);
+ edit_local->set_h_size_flags(SIZE_EXPAND_FILL);
+ edit_local->set_text(TTR("Local"));
+ edit_local->set_toggle_mode(true);
+ edit_local->connect("pressed", this, "_local_tree_selected");
+
+ remote_tree = NULL;
+ button_hb->hide();
+
scene_tree = memnew(SceneTreeEditor(false, true, true));
+
vbc->add_child(scene_tree);
scene_tree->set_v_size_flags(SIZE_EXPAND | SIZE_FILL);
scene_tree->connect("rmb_pressed", this, "_tree_rmb");
diff --git a/editor/scene_tree_dock.h b/editor/scene_tree_dock.h
index f61c67bb13..7848052241 100644
--- a/editor/scene_tree_dock.h
+++ b/editor/scene_tree_dock.h
@@ -95,7 +95,10 @@ class SceneTreeDock : public VBoxContainer {
ToolButton *button_create_script;
ToolButton *button_clear_script;
+ HBoxContainer *button_hb;
+ ToolButton *edit_local, *edit_remote;
SceneTreeEditor *scene_tree;
+ Control *remote_tree;
HBoxContainer *tool_hbc;
void _tool_selected(int p_tool, bool p_confirm_override = false);
@@ -127,7 +130,6 @@ class SceneTreeDock : public VBoxContainer {
void _add_children_to_popup(Object *p_obj, int p_depth);
- Node *_duplicate(Node *p_node, Map<Node *, Node *> &duplimap);
void _node_reparent(NodePath p_path, bool p_keep_global_xform);
void _do_reparent(Node *p_new_parent, int p_position_in_parent, Vector<Node *> p_nodes, bool p_keep_global_xform);
@@ -174,6 +176,9 @@ class SceneTreeDock : public VBoxContainer {
void _file_selected(String p_file);
+ void _remote_tree_selected();
+ void _local_tree_selected();
+
protected:
void _notification(int p_what);
static void _bind_methods();
@@ -194,6 +199,10 @@ public:
SceneTreeEditor *get_tree_editor() { return scene_tree; }
EditorData *get_editor_data() { return editor_data; }
+ void add_remote_tree_editor(Control *p_remote);
+ void show_remote_tree();
+ void hide_remote_tree();
+
void open_script_dialog(Node *p_for_node);
SceneTreeDock(EditorNode *p_editor, Node *p_scene_root, EditorSelection *p_editor_selection, EditorData &p_editor_data);
};
diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp
index 6dcd5e54ec..dfda8a780d 100644
--- a/editor/scene_tree_editor.cpp
+++ b/editor/scene_tree_editor.cpp
@@ -88,7 +88,7 @@ void SceneTreeEditor::_cell_button_pressed(Object *p_item, int p_column, int p_i
} else if (p_id == BUTTON_LOCK) {
- if (n->is_class("CanvasItem")) {
+ if (n->is_class("CanvasItem") || n->is_class("Spatial")) {
n->set_meta("_edit_lock_", Variant());
_update_tree();
emit_signal("node_changed");
@@ -215,9 +215,9 @@ bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) {
bool has_groups = p_node->has_persistent_groups();
if (has_connections && has_groups) {
- item->add_button(0, get_icon("ConnectionAndGroups", "EditorIcons"), BUTTON_SIGNALS, false, TTR("Node has connection(s) and group(s)\nClick to show signals dock."));
+ item->add_button(0, get_icon("SignalsAndGroups", "EditorIcons"), BUTTON_SIGNALS, false, TTR("Node has connection(s) and group(s)\nClick to show signals dock."));
} else if (has_connections) {
- item->add_button(0, get_icon("Connect", "EditorIcons"), BUTTON_SIGNALS, false, TTR("Node has connections.\nClick to show signals dock."));
+ item->add_button(0, get_icon("Signals", "EditorIcons"), BUTTON_SIGNALS, false, TTR("Node has connections.\nClick to show signals dock."));
} else if (has_groups) {
item->add_button(0, get_icon("Groups", "EditorIcons"), BUTTON_GROUPS, false, TTR("Node is in group(s).\nClick to show groups dock."));
}
@@ -266,6 +266,10 @@ bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) {
_update_visibility_color(p_node, item);
} else if (p_node->is_class("Spatial")) {
+ bool is_locked = p_node->has_meta("_edit_lock_");
+ if (is_locked)
+ item->add_button(0, get_icon("Lock", "EditorIcons"), BUTTON_LOCK, false, TTR("Node is locked.\nClick to unlock"));
+
bool v = p_node->call("is_visible");
if (v)
item->add_button(0, get_icon("Visible", "EditorIcons"), BUTTON_VISIBILITY, false, TTR("Toggle Visibility"));
@@ -354,7 +358,11 @@ void SceneTreeEditor::_update_visibility_color(Node *p_node, TreeItem *p_item) {
void SceneTreeEditor::_node_script_changed(Node *p_node) {
- _update_tree();
+ if (tree_dirty)
+ return;
+
+ MessageQueue::get_singleton()->push_call(this, "_update_tree");
+ tree_dirty = true;
/*
changes the order :|
TreeItem* item=p_node?_find(tree->get_root(),p_node->get_path()):NULL;
diff --git a/editor/script_create_dialog.cpp b/editor/script_create_dialog.cpp
index 089c054b59..3cab14b0c4 100644
--- a/editor/script_create_dialog.cpp
+++ b/editor/script_create_dialog.cpp
@@ -88,7 +88,7 @@ bool ScriptCreateDialog::_validate(const String &p_string) {
continue;
}
- bool valid_char = (p_string[i] >= '0' && p_string[i] <= '9') || (p_string[i] >= 'a' && p_string[i] <= 'z') || (p_string[i] >= 'A' && p_string[i] <= 'Z') || p_string[i] == '_' || (is_val_path && (p_string[i] == '/' || p_string[i] == '.'));
+ bool valid_char = (p_string[i] >= '0' && p_string[i] <= '9') || (p_string[i] >= 'a' && p_string[i] <= 'z') || (p_string[i] >= 'A' && p_string[i] <= 'Z') || p_string[i] == '_' || p_string[i] == '-' || (is_val_path && (p_string[i] == '/' || p_string[i] == '.'));
if (!valid_char)
return false;
@@ -128,7 +128,7 @@ void ScriptCreateDialog::_template_changed(int p_template) {
}
String ext = ScriptServer::get_language(language_menu->get_selected())->get_extension();
String name = template_list[p_template - 1] + "." + ext;
- script_template = EditorSettings::get_singleton()->get_settings_path() + "/script_templates/" + name;
+ script_template = EditorSettings::get_singleton()->get_script_templates_dir().plus_file(name);
}
void ScriptCreateDialog::ok_pressed() {
@@ -145,9 +145,13 @@ void ScriptCreateDialog::ok_pressed() {
void ScriptCreateDialog::_create_new() {
- String cname;
- if (has_named_classes)
- cname = class_name->get_text();
+ String cname_param;
+
+ if (has_named_classes) {
+ cname_param = class_name->get_text();
+ } else {
+ cname_param = ProjectSettings::get_singleton()->localize_path(file_path->get_text()).get_file().get_basename();
+ }
Ref<Script> scr;
if (script_template != "") {
@@ -159,13 +163,16 @@ void ScriptCreateDialog::_create_new() {
return;
}
scr = scr->duplicate();
- ScriptServer::get_language(language_menu->get_selected())->make_template(cname, parent_name->get_text(), scr);
+ ScriptServer::get_language(language_menu->get_selected())->make_template(cname_param, parent_name->get_text(), scr);
} else {
- scr = ScriptServer::get_language(language_menu->get_selected())->get_template(cname, parent_name->get_text());
+ scr = ScriptServer::get_language(language_menu->get_selected())->get_template(cname_param, parent_name->get_text());
}
- if (cname != "")
- scr->set_name(cname);
+ if (has_named_classes) {
+ String cname = class_name->get_text();
+ if (cname.length())
+ scr->set_name(cname);
+ }
if (!is_built_in) {
String lpath = ProjectSettings::get_singleton()->localize_path(file_path->get_text());
@@ -201,12 +208,20 @@ void ScriptCreateDialog::_lang_changed(int l) {
l = language_menu->get_selected();
ScriptLanguage *language = ScriptServer::get_language(l);
+
if (language->has_named_classes()) {
has_named_classes = true;
} else {
has_named_classes = false;
}
+ if (language->supports_builtin_mode()) {
+ supports_built_in = true;
+ } else {
+ supports_built_in = false;
+ is_built_in = false;
+ }
+
if (ScriptServer::get_language(l)->can_inherit_from_file()) {
can_inherit_from_file = true;
} else {
@@ -496,6 +511,9 @@ void ScriptCreateDialog::_update_dialog() {
}
}
+ if (!supports_built_in)
+ internal->set_pressed(false);
+
/* Is Script created or loaded from existing file */
if (is_new_script_created) {
@@ -503,7 +521,7 @@ void ScriptCreateDialog::_update_dialog() {
get_ok()->set_text(TTR("Create"));
parent_name->set_editable(true);
parent_browse_button->set_disabled(false);
- internal->set_disabled(false);
+ internal->set_disabled(!supports_built_in);
if (is_built_in) {
_msg_path_valid(true, TTR("Built-in script (into scene file)"));
} else {
@@ -685,9 +703,7 @@ ScriptCreateDialog::ScriptCreateDialog() {
internal = memnew(CheckButton);
internal->connect("pressed", this, "_built_in_pressed");
hb = memnew(HBoxContainer);
- Control *empty = memnew(Control);
hb->add_child(internal);
- hb->add_child(empty);
l = memnew(Label);
l->set_text(TTR("Built-in Script"));
l->set_align(Label::ALIGN_RIGHT);
@@ -734,6 +750,7 @@ ScriptCreateDialog::ScriptCreateDialog() {
is_path_valid = false;
has_named_classes = false;
+ supports_built_in = false;
can_inherit_from_file = false;
is_built_in = false;
diff --git a/editor/script_create_dialog.h b/editor/script_create_dialog.h
index d16c523f0a..c7bbc82d47 100644
--- a/editor/script_create_dialog.h
+++ b/editor/script_create_dialog.h
@@ -62,6 +62,7 @@ class ScriptCreateDialog : public ConfirmationDialog {
bool is_new_script_created;
bool is_path_valid;
bool has_named_classes;
+ bool supports_built_in;
bool can_inherit_from_file;
bool is_parent_name_valid;
bool is_class_name_valid;
diff --git a/editor/script_editor_debugger.cpp b/editor/script_editor_debugger.cpp
index 5ad4674f7f..2a3e47b2a6 100644
--- a/editor/script_editor_debugger.cpp
+++ b/editor/script_editor_debugger.cpp
@@ -116,7 +116,7 @@ class ScriptEditorDebuggerInspectedObject : public Object {
protected:
bool _set(const StringName &p_name, const Variant &p_value) {
- if (!prop_values.has(p_name))
+ if (!prop_values.has(p_name) || String(p_name).begins_with("Constants/"))
return false;
emit_signal("value_edited", p_name, p_value);
@@ -132,6 +132,7 @@ protected:
r_ret = prop_values[p_name];
return true;
}
+
void _get_property_list(List<PropertyInfo> *p_list) const {
p_list->clear(); //sorry, no want category
@@ -142,23 +143,52 @@ protected:
static void _bind_methods() {
+ ClassDB::bind_method(D_METHOD("get_title"), &ScriptEditorDebuggerInspectedObject::get_title);
+ ClassDB::bind_method(D_METHOD("get_variant"), &ScriptEditorDebuggerInspectedObject::get_variant);
+ ClassDB::bind_method(D_METHOD("clear"), &ScriptEditorDebuggerInspectedObject::clear);
+ ClassDB::bind_method(D_METHOD("get_remote_object_id"), &ScriptEditorDebuggerInspectedObject::get_remote_object_id);
+
ADD_SIGNAL(MethodInfo("value_edited"));
}
public:
- ObjectID last_edited_id;
+ String type_name;
+ ObjectID remote_object_id;
List<PropertyInfo> prop_list;
Map<StringName, Variant> prop_values;
+ ObjectID get_remote_object_id() {
+ return remote_object_id;
+ }
+
+ String get_title() {
+ if (remote_object_id)
+ return TTR("Remote ") + String(type_name) + ": " + itos(remote_object_id);
+ else
+ return "<null>";
+ }
+ Variant get_variant(const StringName &p_name) {
+
+ Variant var;
+ _get(p_name, var);
+ return var;
+ }
+
+ void clear() {
+
+ prop_list.clear();
+ prop_values.clear();
+ }
void update() {
_change_notify();
}
-
void update_single(const char *p_prop) {
_change_notify(p_prop);
}
- ScriptEditorDebuggerInspectedObject() { last_edited_id = 0; }
+ ScriptEditorDebuggerInspectedObject() {
+ remote_object_id = 0;
+ }
};
void ScriptEditorDebugger::debug_next() {
@@ -297,7 +327,6 @@ Size2 ScriptEditorDebugger::get_minimum_size() const {
void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_data) {
if (p_msg == "debug_enter") {
-
Array msg;
msg.push_back("get_stack_dump");
ppeer->put_var(msg);
@@ -315,12 +344,10 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da
if (error != "") {
tabs->set_current_tab(0);
}
-
profiler->set_enabled(false);
-
EditorNode::get_singleton()->get_pause_button()->set_pressed(true);
-
EditorNode::get_singleton()->make_bottom_panel_item_visible(this);
+ _clear_remote_objects();
} else if (p_msg == "debug_exit") {
@@ -337,9 +364,8 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da
//tabs->set_current_tab(0);
profiler->set_enabled(true);
profiler->disable_seeking();
-
+ inspector->edit(NULL);
EditorNode::get_singleton()->get_pause_button()->set_pressed(false);
-
} else if (p_msg == "message:click_ctrl") {
clicked_ctrl->set_text(p_data[0]);
@@ -399,55 +425,57 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da
le_set->set_disabled(false);
} else if (p_msg == "message:inspect_object") {
+ ScriptEditorDebuggerInspectedObject *debugObj = NULL;
+
ObjectID id = p_data[0];
String type = p_data[1];
- Variant path = p_data[2]; //what to do yet, i don't know
- int prop_count = p_data[3];
-
- int idx = 4;
+ Array properties = p_data[2];
- if (inspected_object->last_edited_id != id) {
- inspected_object->prop_list.clear();
- inspected_object->prop_values.clear();
+ bool is_new_object = false;
+ if (remote_objects.has(id)) {
+ debugObj = remote_objects[id];
+ } else {
+ debugObj = memnew(ScriptEditorDebuggerInspectedObject);
+ debugObj->remote_object_id = id;
+ debugObj->type_name = type;
+ remote_objects[id] = debugObj;
+ is_new_object = true;
+ debugObj->connect("value_edited", this, "_scene_tree_property_value_edited");
}
- for (int i = 0; i < prop_count; i++) {
+ for (int i = 0; i < properties.size(); i++) {
+
+ Array prop = properties[i];
+ if (prop.size() != 6)
+ continue;
PropertyInfo pinfo;
- pinfo.name = p_data[idx++];
- pinfo.type = Variant::Type(int(p_data[idx++]));
- pinfo.hint = PropertyHint(int(p_data[idx++]));
- pinfo.hint_string = p_data[idx++];
- if (pinfo.name.begins_with("*")) {
- pinfo.name = pinfo.name.substr(1, pinfo.name.length());
- pinfo.usage = PROPERTY_USAGE_CATEGORY;
- } else {
- pinfo.usage = PROPERTY_USAGE_EDITOR;
+ pinfo.name = prop[0];
+ pinfo.type = Variant::Type(int(prop[1]));
+ pinfo.hint = PropertyHint(int(prop[2]));
+ pinfo.hint_string = prop[3];
+ pinfo.usage = PropertyUsageFlags(int(prop[4]));
+ Variant var = prop[5];
+
+ String hint_string = pinfo.hint_string;
+ if (hint_string.begins_with("RES:") && hint_string != "RES:") {
+ String path = hint_string.substr(4, hint_string.length());
+ var = ResourceLoader::load(path);
}
- if (inspected_object->last_edited_id != id) {
+ if (is_new_object) {
//don't update.. it's the same, instead refresh
- inspected_object->prop_list.push_back(pinfo);
+ debugObj->prop_list.push_back(pinfo);
}
- inspected_object->prop_values[pinfo.name] = p_data[idx++];
-
- if (inspected_object->last_edited_id == id) {
- //same, just update value, don't rebuild
- inspected_object->update_single(pinfo.name.ascii().get_data());
- }
+ debugObj->prop_values[pinfo.name] = var;
}
- if (inspected_object->last_edited_id != id) {
- //only if different
- inspected_object->update();
+ if (editor->get_editor_history()->get_current() != debugObj->get_instance_id()) {
+ editor->push_item(debugObj, "");
+ } else {
+ debugObj->update();
}
-
- inspected_object->last_edited_id = id;
-
- tabs->set_current_tab(inspect_info->get_index());
- inspect_properties->edit(inspected_object);
-
} else if (p_msg == "message:video_mem") {
vmem_tree->clear();
@@ -502,7 +530,6 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da
int ofs = 0;
int mcount = p_data[ofs];
-
ofs++;
for (int i = 0; i < mcount; i++) {
@@ -521,12 +548,34 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da
v = s.get_slice(":", 1).to_int();
}
- variables->add_property("members/" + n, v, h, hs);
+ variables->add_property("Locals/" + n, v, h, hs);
}
- ofs += mcount * 2;
+ ofs += mcount * 2;
mcount = p_data[ofs];
+ ofs++;
+ for (int i = 0; i < mcount; i++) {
+
+ String n = p_data[ofs + i * 2 + 0];
+ Variant v = p_data[ofs + i * 2 + 1];
+ PropertyHint h = PROPERTY_HINT_NONE;
+ String hs = String();
+
+ if (n.begins_with("*")) {
+
+ n = n.substr(1, n.length());
+ h = PROPERTY_HINT_OBJECT_ID;
+ String s = v;
+ s = s.replace("[", "");
+ hs = s.get_slice(":", 0);
+ v = s.get_slice(":", 1).to_int();
+ }
+
+ variables->add_property("Members/" + n, v, h, hs);
+ }
+ ofs += mcount * 2;
+ mcount = p_data[ofs];
ofs++;
for (int i = 0; i < mcount; i++) {
@@ -545,7 +594,7 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da
v = s.get_slice(":", 1).to_int();
}
- variables->add_property("locals/" + n, v, h, hs);
+ variables->add_property("Globals/" + n, v, h, hs);
}
variables->update();
@@ -574,7 +623,38 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da
for (int i = 0; i < arr.size(); i++) {
p[i] = arr[i];
if (i < perf_items.size()) {
- perf_items[i]->set_text(1, rtos(p[i]));
+
+ float v = p[i];
+ String vs = rtos(v);
+ String tt = vs;
+ switch (Performance::MonitorType((int)perf_items[i]->get_metadata(1))) {
+ case Performance::MONITOR_TYPE_MEMORY: {
+ // for the time being, going above GBs is a bad sign.
+ String unit = "B";
+ if ((int)v > 1073741824) {
+ unit = "GB";
+ v /= 1073741824.0;
+ } else if ((int)v > 1048576) {
+ unit = "MB";
+ v /= 1048576.0;
+ } else if ((int)v > 1024) {
+ unit = "KB";
+ v /= 1024.0;
+ }
+ tt += " bytes";
+ vs = rtos(v) + " " + unit;
+ } break;
+ case Performance::MONITOR_TYPE_TIME: {
+ tt += " seconds";
+ vs += " s";
+ } break;
+ default: {
+ tt += " " + perf_items[i]->get_text(0);
+ } break;
+ }
+
+ perf_items[i]->set_text(1, vs);
+ perf_items[i]->set_tooltip(1, tt);
if (p[i] > perf_max[i])
perf_max[i] = p[i];
}
@@ -663,7 +743,7 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da
EditorProfiler::Metric::Category::Item item;
item.calls = 1;
item.line = 0;
- item.name = "Fixed Time";
+ item.name = "Physics Time";
item.total = metric.physics_time;
item.self = item.total;
item.signature = "physics_time";
@@ -677,7 +757,7 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da
frame_time.items.push_back(item);
- item.name = "Fixed Frame Time";
+ item.name = "Physics Frame Time";
item.total = metric.physics_frame_time;
item.self = item.total;
item.signature = "physics_frame_time";
@@ -775,7 +855,7 @@ void ScriptEditorDebugger::_set_reason_text(const String &p_reason, MessageType
reason->set_tooltip(p_reason);
}
-void ScriptEditorDebugger::_performance_select(Object *, int, bool) {
+void ScriptEditorDebugger::_performance_select() {
perf_draw->update();
}
@@ -785,7 +865,7 @@ void ScriptEditorDebugger::_performance_draw() {
Vector<int> which;
for (int i = 0; i < perf_items.size(); i++) {
- if (perf_items[i]->is_selected(0))
+ if (perf_items[i]->is_checked(0))
which.push_back(i);
}
@@ -816,14 +896,14 @@ void ScriptEditorDebugger::_performance_draw() {
r.position += graph_sb->get_offset();
r.size -= graph_sb->get_minimum_size();
int pi = which[i];
- Color c = get_color("success_color", "Editor");
- c.set_hsv(Math::fmod(c.get_h() + pi * 0.7654, 1), c.get_s(), c.get_v());
- //c = c.linear_interpolate(get_color("base_color", "Editor"), 0.9);
+ Color c = get_color("accent_color", "Editor");
+ float h = (float)which[i] / (float)(perf_items.size());
+ c.set_hsv(Math::fmod(h + 0.4, 0.9), c.get_s() * 0.9, c.get_v() * 1.4);
- c.a = 0.8;
- perf_draw->draw_string(graph_font, r.position + Point2(0, graph_font->get_ascent()), perf_items[pi]->get_text(0), c, r.size.x);
c.a = 0.6;
- perf_draw->draw_string(graph_font, r.position + Point2(graph_font->get_char_size('X').width, graph_font->get_ascent() + graph_font->get_height()), perf_items[pi]->get_text(1), c, r.size.y);
+ perf_draw->draw_string(graph_font, r.position + Point2(0, graph_font->get_ascent()), perf_items[pi]->get_text(0), c, r.size.x);
+ c.a = 0.9;
+ perf_draw->draw_string(graph_font, r.position + Point2(0, graph_font->get_ascent() + graph_font->get_height()), perf_items[pi]->get_text(1), c, r.size.y);
float spacing = point_sep / float(cols);
float from = r.size.width;
@@ -1070,6 +1150,8 @@ void ScriptEditorDebugger::start() {
EditorNode::get_log()->add_message(String("Error listening on port ") + itos(remote_port), true);
return;
}
+
+ EditorNode::get_singleton()->get_scene_tree_dock()->show_remote_tree();
set_process(true);
}
@@ -1102,11 +1184,11 @@ void ScriptEditorDebugger::stop() {
le_set->set_disabled(true);
profiler->set_enabled(true);
- inspect_properties->edit(NULL);
inspect_scene_tree->clear();
EditorNode::get_singleton()->get_pause_button()->set_pressed(false);
EditorNode::get_singleton()->get_pause_button()->set_disabled(true);
+ EditorNode::get_singleton()->get_scene_tree_dock()->hide_remote_tree();
if (hide_on_stop) {
if (is_visible_in_tree())
@@ -1573,6 +1655,24 @@ void ScriptEditorDebugger::_paused() {
}
}
+void ScriptEditorDebugger::_set_remote_object(ObjectID p_id, ScriptEditorDebuggerInspectedObject *p_obj) {
+
+ if (remote_objects.has(p_id))
+ memdelete(remote_objects[p_id]);
+ remote_objects[p_id] = p_obj;
+}
+
+void ScriptEditorDebugger::_clear_remote_objects() {
+
+ for (Map<ObjectID, ScriptEditorDebuggerInspectedObject *>::Element *E = remote_objects.front(); E; E = E->next()) {
+ if (editor->get_editor_history()->get_current() == E->value()->get_instance_id()) {
+ editor->push_item(NULL);
+ }
+ memdelete(E->value());
+ }
+ remote_objects.clear();
+}
+
void ScriptEditorDebugger::_bind_methods() {
ClassDB::bind_method(D_METHOD("_stack_dump_frame_selected"), &ScriptEditorDebugger::_stack_dump_frame_selected);
@@ -1618,6 +1718,7 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor) {
ppeer = Ref<PacketPeerStream>(memnew(PacketPeerStream));
ppeer->set_input_buffer_max_size(1024 * 1024 * 8); //8mb should be enough
editor = p_editor;
+ editor->get_property_editor()->connect("object_id_selected", this, "_scene_tree_property_select_object");
tabs = memnew(TabContainer);
tabs->set_tab_align(TabContainer::ALIGN_LEFT);
@@ -1730,41 +1831,18 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor) {
tabs->add_child(error_split);
}
- { // inquire
-
- inspect_info = memnew(HSplitContainer);
- inspect_info->set_name(TTR("Remote Inspector"));
- tabs->add_child(inspect_info);
-
- VBoxContainer *info_left = memnew(VBoxContainer);
- info_left->set_h_size_flags(SIZE_EXPAND_FILL);
- inspect_info->add_child(info_left);
+ { // remote scene tree
inspect_scene_tree = memnew(Tree);
- info_left->add_margin_child(TTR("Live Scene Tree:"), inspect_scene_tree, true);
+ EditorNode::get_singleton()->get_scene_tree_dock()->add_remote_tree_editor(inspect_scene_tree);
+ inspect_scene_tree->set_v_size_flags(SIZE_EXPAND_FILL);
inspect_scene_tree->connect("cell_selected", this, "_scene_tree_selected");
inspect_scene_tree->connect("item_collapsed", this, "_scene_tree_folded");
- //
-
- VBoxContainer *info_right = memnew(VBoxContainer);
- info_right->set_h_size_flags(SIZE_EXPAND_FILL);
- inspect_info->add_child(info_right);
-
- inspect_properties = memnew(PropertyEditor);
- inspect_properties->hide_top_label();
- inspect_properties->set_show_categories(true);
- inspect_properties->connect("object_id_selected", this, "_scene_tree_property_select_object");
-
- info_right->add_margin_child(TTR("Remote Object Properties: "), inspect_properties, true);
-
inspect_scene_tree_timeout = EDITOR_DEF("debugger/scene_tree_refresh_interval", 1.0);
inspect_edited_object_timeout = EDITOR_DEF("debugger/remote_inspect_refresh_interval", 0.2);
inspected_object_id = 0;
updating_scene_tree = false;
-
- inspected_object = memnew(ScriptEditorDebuggerInspectedObject);
- inspected_object->connect("value_edited", this, "_scene_tree_property_value_edited");
}
{ //profiler
@@ -1785,13 +1863,12 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor) {
perf_monitors->set_column_title(1, TTR("Value"));
perf_monitors->set_column_titles_visible(true);
hsp->add_child(perf_monitors);
- perf_monitors->set_select_mode(Tree::SELECT_MULTI);
- perf_monitors->connect("multi_selected", this, "_performance_select");
+ perf_monitors->connect("item_edited", this, "_performance_select");
perf_draw = memnew(Control);
perf_draw->connect("draw", this, "_performance_draw");
hsp->add_child(perf_draw);
hsp->set_name(TTR("Monitors"));
- hsp->set_split_offset(300);
+ hsp->set_split_offset(340 * EDSCALE);
tabs->add_child(hsp);
perf_max.resize(Performance::MONITOR_MAX);
@@ -1801,6 +1878,7 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor) {
for (int i = 0; i < Performance::MONITOR_MAX; i++) {
String n = Performance::get_singleton()->get_monitor_name(Performance::Monitor(i));
+ Performance::MonitorType mtype = Performance::get_singleton()->get_monitor_type(Performance::Monitor(i));
String base = n.get_slice("/", 0);
String name = n.get_slice("/", 1);
if (!bases.has(base)) {
@@ -1808,12 +1886,16 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor) {
b->set_text(0, base.capitalize());
b->set_editable(0, false);
b->set_selectable(0, false);
+ b->set_expand_right(0, true);
bases[base] = b;
}
TreeItem *it = perf_monitors->create_item(bases[base]);
- it->set_editable(0, false);
- it->set_selectable(0, true);
+ it->set_metadata(1, mtype);
+ it->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
+ it->set_editable(0, true);
+ it->set_selectable(0, false);
+ it->set_selectable(1, false);
it->set_text(0, name.capitalize());
perf_items.push_back(it);
perf_max[i] = 0;
@@ -1917,5 +1999,5 @@ ScriptEditorDebugger::~ScriptEditorDebugger() {
ppeer->set_stream_peer(Ref<StreamPeer>());
server->stop();
- memdelete(inspected_object);
+ _clear_remote_objects();
}
diff --git a/editor/script_editor_debugger.h b/editor/script_editor_debugger.h
index 64ac2535a9..dc851dd575 100644
--- a/editor/script_editor_debugger.h
+++ b/editor/script_editor_debugger.h
@@ -72,19 +72,18 @@ class ScriptEditorDebugger : public Control {
Button *le_set;
Button *le_clear;
- Tree *inspect_scene_tree;
- HSplitContainer *inspect_info;
- PropertyEditor *inspect_properties;
+ bool updating_scene_tree;
float inspect_scene_tree_timeout;
float inspect_edited_object_timeout;
ObjectID inspected_object_id;
- ScriptEditorDebuggerInspectedObject *inspected_object;
- bool updating_scene_tree;
+ ScriptEditorDebuggerVariables *variables;
+ Map<ObjectID, ScriptEditorDebuggerInspectedObject *> remote_objects;
Set<ObjectID> unfold_cache;
HSplitContainer *error_split;
ItemList *error_list;
ItemList *error_stack;
+ Tree *inspect_scene_tree;
int error_count;
int last_error_count;
@@ -96,7 +95,6 @@ class ScriptEditorDebugger : public Control {
TabContainer *tabs;
Label *reason;
- ScriptEditorDebuggerVariables *variables;
Button *step;
Button *next;
@@ -142,7 +140,7 @@ class ScriptEditorDebugger : public Control {
bool live_debug;
void _performance_draw();
- void _performance_select(Object *, int, bool);
+ void _performance_select();
void _stack_dump_frame_selected();
void _output_clear();
@@ -166,9 +164,6 @@ class ScriptEditorDebugger : public Control {
void _method_changed(Object *p_base, const StringName &p_name, VARIANT_ARG_DECLARE);
void _property_changed(Object *p_base, const StringName &p_property, const Variant &p_value);
- static void _method_changeds(void *p_ud, Object *p_base, const StringName &p_name, VARIANT_ARG_DECLARE);
- static void _property_changeds(void *p_ud, Object *p_base, const StringName &p_property, const Variant &p_value);
-
void _error_selected(int p_idx);
void _error_stack_selected(int p_idx);
@@ -177,6 +172,9 @@ class ScriptEditorDebugger : public Control {
void _paused();
+ void _set_remote_object(ObjectID p_id, ScriptEditorDebuggerInspectedObject *p_obj);
+ void _clear_remote_objects();
+
protected:
void _notification(int p_what);
static void _bind_methods();
@@ -196,6 +194,9 @@ public:
void set_live_debugging(bool p_enable);
+ static void _method_changeds(void *p_ud, Object *p_base, const StringName &p_name, VARIANT_ARG_DECLARE);
+ static void _property_changeds(void *p_ud, Object *p_base, const StringName &p_property, const Variant &p_value);
+
void live_debug_create_node(const NodePath &p_parent, const String &p_type, const String &p_name);
void live_debug_instance_node(const NodePath &p_parent, const String &p_path, const String &p_name);
void live_debug_remove_node(const NodePath &p_at);
diff --git a/editor/settings_config_dialog.cpp b/editor/settings_config_dialog.cpp
index 2f3da487d2..853761f689 100644
--- a/editor/settings_config_dialog.cpp
+++ b/editor/settings_config_dialog.cpp
@@ -35,6 +35,7 @@
#include "os/keyboard.h"
#include "project_settings.h"
#include "scene/gui/margin_container.h"
+#include "script_editor_debugger.h"
void EditorSettingsDialog::ok_pressed() {
@@ -91,6 +92,7 @@ void EditorSettingsDialog::popup_edit_settings() {
search_box->grab_focus();
_update_shortcuts();
+ set_process_unhandled_input(true);
// Restore valid window bounds or pop up at default size.
if (EditorSettings::get_singleton()->has_setting("interface/dialogs/editor_settings_bounds")) {
@@ -121,19 +123,62 @@ void EditorSettingsDialog::_filter_shortcuts(const String &p_filter) {
_update_shortcuts();
}
+void EditorSettingsDialog::_undo_redo_callback(void *p_self, const String &p_name) {
+ EditorNode::get_log()->add_message(p_name);
+}
+
void EditorSettingsDialog::_notification(int p_what) {
switch (p_what) {
+ case NOTIFICATION_READY: {
+ ScriptEditorDebugger *sed = ScriptEditor::get_singleton()->get_debugger();
+ undo_redo->set_method_notify_callback(sed->_method_changeds, sed);
+ undo_redo->set_property_notify_callback(sed->_property_changeds, sed);
+ undo_redo->set_commit_notify_callback(_undo_redo_callback, this);
+ } break;
case NOTIFICATION_ENTER_TREE: {
clear_button->set_icon(get_icon("Close", "EditorIcons"));
shortcut_clear_button->set_icon(get_icon("Close", "EditorIcons"));
} break;
case NOTIFICATION_POPUP_HIDE: {
EditorSettings::get_singleton()->set("interface/dialogs/editor_settings_bounds", get_rect());
+ set_process_unhandled_input(false);
} break;
}
}
+void EditorSettingsDialog::_unhandled_input(const Ref<InputEvent> &p_event) {
+
+ Ref<InputEventKey> k = p_event;
+
+ if (k.is_valid() && is_window_modal_on_top()) {
+
+ if (k->is_pressed()) {
+
+ bool handled = false;
+
+ if (ED_IS_SHORTCUT("editor/undo", p_event)) {
+ String action = undo_redo->get_current_action_name();
+ if (action != "")
+ EditorNode::get_log()->add_message("UNDO: " + action);
+ undo_redo->undo();
+ handled = true;
+ }
+ if (ED_IS_SHORTCUT("editor/redo", p_event)) {
+ undo_redo->redo();
+ String action = undo_redo->get_current_action_name();
+ if (action != "")
+ EditorNode::get_log()->add_message("REDO: " + action);
+ handled = true;
+ }
+
+ if (handled) {
+ accept_event();
+ }
+ }
+ }
+}
+
void EditorSettingsDialog::_update_shortcuts() {
shortcuts->clear();
@@ -212,30 +257,28 @@ void EditorSettingsDialog::_shortcut_button_pressed(Object *p_item, int p_column
if (!sc.is_valid())
return; //pointless, there is nothing
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
- ur->create_action("Erase Shortcut");
- ur->add_do_method(sc.ptr(), "set_shortcut", Ref<InputEvent>());
- ur->add_undo_method(sc.ptr(), "set_shortcut", sc->get_shortcut());
- ur->add_do_method(this, "_update_shortcuts");
- ur->add_undo_method(this, "_update_shortcuts");
- ur->add_do_method(this, "_settings_changed");
- ur->add_undo_method(this, "_settings_changed");
- ur->commit_action();
+ undo_redo->create_action("Erase Shortcut");
+ undo_redo->add_do_method(sc.ptr(), "set_shortcut", Ref<InputEvent>());
+ undo_redo->add_undo_method(sc.ptr(), "set_shortcut", sc->get_shortcut());
+ undo_redo->add_do_method(this, "_update_shortcuts");
+ undo_redo->add_undo_method(this, "_update_shortcuts");
+ undo_redo->add_do_method(this, "_settings_changed");
+ undo_redo->add_undo_method(this, "_settings_changed");
+ undo_redo->commit_action();
} else if (p_idx == 2) { //revert to original
if (!sc.is_valid())
return; //pointless, there is nothing
Ref<InputEvent> original = sc->get_meta("original");
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
- ur->create_action("Restore Shortcut");
- ur->add_do_method(sc.ptr(), "set_shortcut", original);
- ur->add_undo_method(sc.ptr(), "set_shortcut", sc->get_shortcut());
- ur->add_do_method(this, "_update_shortcuts");
- ur->add_undo_method(this, "_update_shortcuts");
- ur->add_do_method(this, "_settings_changed");
- ur->add_undo_method(this, "_settings_changed");
- ur->commit_action();
+ undo_redo->create_action("Restore Shortcut");
+ undo_redo->add_do_method(sc.ptr(), "set_shortcut", original);
+ undo_redo->add_undo_method(sc.ptr(), "set_shortcut", sc->get_shortcut());
+ undo_redo->add_do_method(this, "_update_shortcuts");
+ undo_redo->add_undo_method(this, "_update_shortcuts");
+ undo_redo->add_do_method(this, "_settings_changed");
+ undo_redo->add_undo_method(this, "_settings_changed");
+ undo_redo->commit_action();
}
}
@@ -276,19 +319,19 @@ void EditorSettingsDialog::_press_a_key_confirm() {
Ref<ShortCut> sc = EditorSettings::get_singleton()->get_shortcut(shortcut_configured);
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
- ur->create_action("Change Shortcut '" + shortcut_configured + "'");
- ur->add_do_method(sc.ptr(), "set_shortcut", ie);
- ur->add_undo_method(sc.ptr(), "set_shortcut", sc->get_shortcut());
- ur->add_do_method(this, "_update_shortcuts");
- ur->add_undo_method(this, "_update_shortcuts");
- ur->add_do_method(this, "_settings_changed");
- ur->add_undo_method(this, "_settings_changed");
- ur->commit_action();
+ undo_redo->create_action("Change Shortcut '" + shortcut_configured + "'");
+ undo_redo->add_do_method(sc.ptr(), "set_shortcut", ie);
+ undo_redo->add_undo_method(sc.ptr(), "set_shortcut", sc->get_shortcut());
+ undo_redo->add_do_method(this, "_update_shortcuts");
+ undo_redo->add_undo_method(this, "_update_shortcuts");
+ undo_redo->add_do_method(this, "_settings_changed");
+ undo_redo->add_undo_method(this, "_settings_changed");
+ undo_redo->commit_action();
}
void EditorSettingsDialog::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("_unhandled_input"), &EditorSettingsDialog::_unhandled_input);
ClassDB::bind_method(D_METHOD("_settings_save"), &EditorSettingsDialog::_settings_save);
ClassDB::bind_method(D_METHOD("_settings_changed"), &EditorSettingsDialog::_settings_changed);
ClassDB::bind_method(D_METHOD("_settings_property_edited"), &EditorSettingsDialog::_settings_property_edited);
@@ -305,6 +348,7 @@ EditorSettingsDialog::EditorSettingsDialog() {
set_title(TTR("Editor Settings"));
set_resizable(true);
+ undo_redo = memnew(UndoRedo);
tabs = memnew(TabContainer);
tabs->set_tab_align(TabContainer::ALIGN_LEFT);
@@ -336,7 +380,7 @@ EditorSettingsDialog::EditorSettingsDialog() {
property_editor->get_property_editor()->set_use_filter(true);
property_editor->register_search_box(search_box);
property_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL);
- property_editor->get_property_editor()->set_undo_redo(EditorNode::get_singleton()->get_undo_redo());
+ property_editor->get_property_editor()->set_undo_redo(undo_redo);
vbc->add_child(property_editor);
property_editor->get_property_editor()->connect("property_edited", this, "_settings_property_edited");
@@ -400,3 +444,7 @@ EditorSettingsDialog::EditorSettingsDialog() {
updating = false;
}
+
+EditorSettingsDialog::~EditorSettingsDialog() {
+ memdelete(undo_redo);
+}
diff --git a/editor/settings_config_dialog.h b/editor/settings_config_dialog.h
index 8a66d5098c..a03b15c06d 100644
--- a/editor/settings_config_dialog.h
+++ b/editor/settings_config_dialog.h
@@ -50,6 +50,7 @@ class EditorSettingsDialog : public AcceptDialog {
Timer *timer;
+ UndoRedo *undo_redo;
Tree *shortcuts;
ConfirmationDialog *press_a_key;
@@ -65,6 +66,7 @@ class EditorSettingsDialog : public AcceptDialog {
void _settings_property_edited(const String &p_name);
void _settings_save();
+ void _unhandled_input(const Ref<InputEvent> &p_event);
void _notification(int p_what);
void _press_a_key_confirm();
@@ -78,6 +80,8 @@ class EditorSettingsDialog : public AcceptDialog {
void _update_shortcuts();
void _shortcut_button_pressed(Object *p_item, int p_column, int p_idx);
+ static void _undo_redo_callback(void *p_self, const String &p_name);
+
protected:
static void _bind_methods();
@@ -85,6 +89,7 @@ public:
void popup_edit_settings();
EditorSettingsDialog();
+ ~EditorSettingsDialog();
};
#endif // SETTINGS_CONFIG_DIALOG_H
diff --git a/editor/spatial_editor_gizmos.cpp b/editor/spatial_editor_gizmos.cpp
index 3c1889e829..3ffc61cb45 100644
--- a/editor/spatial_editor_gizmos.cpp
+++ b/editor/spatial_editor_gizmos.cpp
@@ -149,7 +149,7 @@ void EditorSpatialGizmo::add_lines(const Vector<Vector3> &p_lines, const Ref<Mat
md = MAX(0, p_lines[i].length());
}
if (md) {
- mesh->set_custom_aabb(Rect3(Vector3(-md, -md, -md), Vector3(md, md, md) * 2.0));
+ mesh->set_custom_aabb(AABB(Vector3(-md, -md, -md), Vector3(md, md, md) * 2.0));
}
}
@@ -196,7 +196,7 @@ void EditorSpatialGizmo::add_unscaled_billboard(const Ref<Material> &p_material,
md = MAX(0, vs[i].length());
}
if (md) {
- mesh->set_custom_aabb(Rect3(Vector3(-md, -md, -md), Vector3(md, md, md) * 2.0));
+ mesh->set_custom_aabb(AABB(Vector3(-md, -md, -md), Vector3(md, md, md) * 2.0));
}
}
@@ -211,7 +211,7 @@ void EditorSpatialGizmo::add_unscaled_billboard(const Ref<Material> &p_material,
instances.push_back(ins);
}
-void EditorSpatialGizmo::add_collision_triangles(const Ref<TriangleMesh> &p_tmesh, const Rect3 &p_bounds) {
+void EditorSpatialGizmo::add_collision_triangles(const Ref<TriangleMesh> &p_tmesh, const AABB &p_bounds) {
collision_mesh = p_tmesh;
collision_mesh_bounds = p_bounds;
@@ -270,7 +270,7 @@ void EditorSpatialGizmo::add_handles(const Vector<Vector3> &p_handles, bool p_bi
md = MAX(0, p_handles[i].length());
}
if (md) {
- mesh->set_custom_aabb(Rect3(Vector3(-md, -md, -md), Vector3(md, md, md) * 2.0));
+ mesh->set_custom_aabb(AABB(Vector3(-md, -md, -md), Vector3(md, md, md) * 2.0));
}
}
@@ -298,11 +298,11 @@ void EditorSpatialGizmo::add_handles(const Vector<Vector3> &p_handles, bool p_bi
}
}
-void EditorSpatialGizmo::add_solid_box(Ref<Material> &p_material, Vector3 size) {
+void EditorSpatialGizmo::add_solid_box(Ref<Material> &p_material, Vector3 p_size) {
ERR_FAIL_COND(!spatial_node);
CubeMesh cubem;
- cubem.set_size(size);
+ cubem.set_size(p_size);
Ref<ArrayMesh> m = memnew(ArrayMesh);
m->add_surface_from_arrays(cubem.surface_get_primitive_type(0), cubem.surface_get_arrays(0));
m->surface_set_material(0, p_material);
@@ -1274,7 +1274,7 @@ void MeshInstanceSpatialGizmo::redraw() {
Ref<TriangleMesh> tm = m->generate_triangle_mesh();
if (tm.is_valid()) {
- Rect3 aabb;
+ AABB aabb;
add_collision_triangles(tm, aabb);
}
}
@@ -1336,7 +1336,7 @@ void SkeletonSpatialGizmo::redraw() {
weights[0] = 1;
- Rect3 aabb;
+ AABB aabb;
Color bonecolor = Color(1.0, 0.4, 0.4, 0.3);
Color rootcolor = Color(0.4, 1.0, 0.4, 0.1);
@@ -1961,7 +1961,7 @@ void CollisionShapeSpatialGizmo::redraw() {
Ref<BoxShape> bs = s;
Vector<Vector3> lines;
- Rect3 aabb;
+ AABB aabb;
aabb.position = -bs->get_extents();
aabb.size = aabb.position * -2;
@@ -2191,7 +2191,7 @@ void VisibilityNotifierGizmo::set_handle(int p_idx, Camera *p_camera, const Poin
//gt.orthonormalize();
Transform gi = gt.affine_inverse();
- Rect3 aabb = notifier->get_aabb();
+ AABB aabb = notifier->get_aabb();
Vector3 ray_from = p_camera->project_ray_origin(p_point);
Vector3 ray_dir = p_camera->project_ray_normal(p_point);
@@ -2234,7 +2234,7 @@ void VisibilityNotifierGizmo::redraw() {
clear();
Vector<Vector3> lines;
- Rect3 aabb = notifier->get_aabb();
+ AABB aabb = notifier->get_aabb();
for (int i = 0; i < 12; i++) {
Vector3 a, b;
@@ -2293,7 +2293,7 @@ void ParticlesGizmo::set_handle(int p_idx, Camera *p_camera, const Point2 &p_poi
bool move = p_idx >= 3;
p_idx = p_idx % 3;
- Rect3 aabb = particles->get_visibility_aabb();
+ AABB aabb = particles->get_visibility_aabb();
Vector3 ray_from = p_camera->project_ray_origin(p_point);
Vector3 ray_dir = p_camera->project_ray_normal(p_point);
@@ -2347,7 +2347,7 @@ void ParticlesGizmo::redraw() {
clear();
Vector<Vector3> lines;
- Rect3 aabb = particles->get_visibility_aabb();
+ AABB aabb = particles->get_visibility_aabb();
for (int i = 0; i < 12; i++) {
Vector3 a, b;
@@ -2420,7 +2420,7 @@ String ReflectionProbeGizmo::get_handle_name(int p_idx) const {
}
Variant ReflectionProbeGizmo::get_handle_value(int p_idx) const {
- return Rect3(probe->get_extents(), probe->get_origin_offset());
+ return AABB(probe->get_extents(), probe->get_origin_offset());
}
void ReflectionProbeGizmo::set_handle(int p_idx, Camera *p_camera, const Point2 &p_point) {
@@ -2474,7 +2474,7 @@ void ReflectionProbeGizmo::set_handle(int p_idx, Camera *p_camera, const Point2
void ReflectionProbeGizmo::commit_handle(int p_idx, const Variant &p_restore, bool p_cancel) {
- Rect3 restore = p_restore;
+ AABB restore = p_restore;
if (p_cancel) {
probe->set_extents(restore.position);
@@ -2499,7 +2499,7 @@ void ReflectionProbeGizmo::redraw() {
Vector<Vector3> internal_lines;
Vector3 extents = probe->get_extents();
- Rect3 aabb;
+ AABB aabb;
aabb.position = -extents;
aabb.size = extents * 2;
@@ -2641,7 +2641,7 @@ void GIProbeGizmo::redraw() {
static const int subdivs[GIProbe::SUBDIV_MAX] = { 64, 128, 256, 512 };
- Rect3 aabb = Rect3(-extents, extents * 2);
+ AABB aabb = AABB(-extents, extents * 2);
int subdiv = subdivs[probe->get_subdiv()];
float cell_size = aabb.get_longest_axis_size() / subdiv;
diff --git a/editor/spatial_editor_gizmos.h b/editor/spatial_editor_gizmos.h
index afe64c723c..751bad2b13 100644
--- a/editor/spatial_editor_gizmos.h
+++ b/editor/spatial_editor_gizmos.h
@@ -78,7 +78,7 @@ class EditorSpatialGizmo : public SpatialEditorGizmo {
Vector<Vector3> collision_segments;
Ref<TriangleMesh> collision_mesh;
- Rect3 collision_mesh_bounds;
+ AABB collision_mesh_bounds;
struct Handle {
Vector3 pos;
@@ -100,7 +100,7 @@ protected:
void add_lines(const Vector<Vector3> &p_lines, const Ref<Material> &p_material, bool p_billboard = false);
void add_mesh(const Ref<ArrayMesh> &p_mesh, bool p_billboard = false, const RID &p_skeleton = RID());
void add_collision_segments(const Vector<Vector3> &p_lines);
- void add_collision_triangles(const Ref<TriangleMesh> &p_tmesh, const Rect3 &p_bounds = Rect3());
+ void add_collision_triangles(const Ref<TriangleMesh> &p_tmesh, const AABB &p_bounds = AABB());
void add_unscaled_billboard(const Ref<Material> &p_material, float p_scale = 1);
void add_handles(const Vector<Vector3> &p_handles, bool p_billboard = false, bool p_secondary = false);
void add_solid_box(Ref<Material> &p_material, Vector3 size);
diff --git a/editor/translations/ar.po b/editor/translations/ar.po
index f98fa91e30..0309680da9 100644
--- a/editor/translations/ar.po
+++ b/editor/translations/ar.po
@@ -1,16 +1,20 @@
# Arabic translation of the Godot Engine editor
-# Copyright (C) 2016-2017 Juan Linietsky, Ariel Manzur and the Godot community
+# Copyright (C) 2007-2017 Juan Linietsky, Ariel Manzur
+# Copyright (C) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)
# This file is distributed under the same license as the Godot source code.
#
# athomield <athomield@hotmail.com>, 2017.
+# Basil Al-Khateeb <basil.y.alkhateeb@gmail.com>, 2017.
# Mohammmad Khashashneh <mohammad.rasmi@gmail.com>, 2016.
+# omar anwar aglan <omar.aglan91@yahoo.com>, 2017.
# OWs Tetra <owstetra@gmail.com>, 2017.
+# Wajdi Feki <wajdi.feki@gmail.com>, 2017.
#
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
-"PO-Revision-Date: 2017-03-29 16:30+0000\n"
-"Last-Translator: OWs Tetra <owstetra@gmail.com>\n"
+"PO-Revision-Date: 2017-10-25 20:58+0000\n"
+"Last-Translator: Wajdi Feki <wajdi.feki@gmail.com>\n"
"Language-Team: Arabic <https://hosted.weblate.org/projects/godot-engine/"
"godot/ar/>\n"
"Language: ar\n"
@@ -18,752 +22,520 @@ msgstr ""
"Content-Transfer-Encoding: 8-bit\n"
"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 "
"&& n%100<=10 ? 3 : n%100>=11 ? 4 : 5;\n"
-"X-Generator: Weblate 2.13-dev\n"
+"X-Generator: Weblate 2.17\n"
#: editor/animation_editor.cpp
msgid "Disabled"
-msgstr ""
+msgstr "معطّل"
#: editor/animation_editor.cpp
msgid "All Selection"
-msgstr ""
+msgstr "ÙƒÙÙ„ الإختيار"
#: editor/animation_editor.cpp
msgid "Move Add Key"
-msgstr ""
+msgstr "Ù…Ùتاح إضاÙØ© الحركة"
#: editor/animation_editor.cpp
msgid "Anim Change Transition"
-msgstr ""
+msgstr "إنتقالية تغيير التحريك"
#: editor/animation_editor.cpp
msgid "Anim Change Transform"
-msgstr ""
+msgstr "تحويل تغيير التحريك"
#: editor/animation_editor.cpp
msgid "Anim Change Value"
-msgstr ""
+msgstr "قيمة تغيير التحريك"
#: editor/animation_editor.cpp
msgid "Anim Change Call"
-msgstr ""
+msgstr "نداء تغيير التحريك"
#: editor/animation_editor.cpp
msgid "Anim Add Track"
-msgstr ""
+msgstr "مسار إضاÙØ© التحريك"
#: editor/animation_editor.cpp
msgid "Anim Duplicate Keys"
-msgstr ""
+msgstr "Ù…Ùاتيح نسخ التحريك"
#: editor/animation_editor.cpp
msgid "Move Anim Track Up"
-msgstr ""
+msgstr "رÙع مسار التحريك"
#: editor/animation_editor.cpp
msgid "Move Anim Track Down"
-msgstr ""
+msgstr "إنزال مسار التحريك"
#: editor/animation_editor.cpp
msgid "Remove Anim Track"
-msgstr ""
+msgstr "حذ٠مسار التحريك"
#: editor/animation_editor.cpp
msgid "Set Transitions to:"
-msgstr ""
+msgstr "تحديد التحولات ل:"
#: editor/animation_editor.cpp
msgid "Anim Track Rename"
-msgstr ""
+msgstr "تغيير إسم مسار التحريك"
#: editor/animation_editor.cpp
msgid "Anim Track Change Interpolation"
-msgstr ""
+msgstr "تغيير إقحام مسار التحريك"
#: editor/animation_editor.cpp
msgid "Anim Track Change Value Mode"
-msgstr ""
+msgstr "تغيير صيغة القيمة لمسار التحريك"
#: editor/animation_editor.cpp
msgid "Anim Track Change Wrap Mode"
-msgstr ""
+msgstr "تغيير صيغة الغلا٠لمسار التحريك"
#: editor/animation_editor.cpp
msgid "Edit Node Curve"
-msgstr ""
+msgstr "تحرير منحى العقدة"
#: editor/animation_editor.cpp
msgid "Edit Selection Curve"
-msgstr ""
+msgstr "تحرير منحى الإختيار"
#: editor/animation_editor.cpp
msgid "Anim Delete Keys"
-msgstr "حذ٠الأطر الرئيسة"
+msgstr "Ù…Ùاتيح حذ٠التحريك"
#: editor/animation_editor.cpp editor/plugins/tile_map_editor_plugin.cpp
msgid "Duplicate Selection"
-msgstr ""
+msgstr "إختيار النسخ"
#: editor/animation_editor.cpp
msgid "Duplicate Transposed"
-msgstr ""
+msgstr "نسخ محمّل"
#: editor/animation_editor.cpp
msgid "Remove Selection"
-msgstr ""
+msgstr "حذ٠الإختيار"
#: editor/animation_editor.cpp
msgid "Continuous"
-msgstr ""
+msgstr "متواصل"
#: editor/animation_editor.cpp
msgid "Discrete"
-msgstr ""
+msgstr "متقطع"
#: editor/animation_editor.cpp
msgid "Trigger"
-msgstr ""
+msgstr "Ù…Ùطلق"
#: editor/animation_editor.cpp
msgid "Anim Add Key"
-msgstr ""
+msgstr "Ù…Ùتاح إضاÙØ© تحريك"
#: editor/animation_editor.cpp
msgid "Anim Move Keys"
-msgstr ""
+msgstr "Ù…Ùتاح حركة التحريك"
#: editor/animation_editor.cpp
msgid "Scale Selection"
-msgstr ""
+msgstr "تكبير المحدد"
#: editor/animation_editor.cpp
msgid "Scale From Cursor"
-msgstr ""
+msgstr "تكبير من المؤشر"
#: editor/animation_editor.cpp
msgid "Goto Next Step"
-msgstr ""
+msgstr "إذهب إلي الخطوة التالية"
#: editor/animation_editor.cpp
msgid "Goto Prev Step"
-msgstr ""
+msgstr "إذهب إلي الخطوة السابقة"
#: editor/animation_editor.cpp editor/plugins/curve_editor_plugin.cpp
#: editor/property_editor.cpp
msgid "Linear"
-msgstr ""
+msgstr "خطي"
#: editor/animation_editor.cpp editor/plugins/theme_editor_plugin.cpp
msgid "Constant"
-msgstr ""
+msgstr "ثابت"
#: editor/animation_editor.cpp
msgid "In"
-msgstr ""
+msgstr "داخل"
#: editor/animation_editor.cpp
msgid "Out"
-msgstr ""
+msgstr "خارج"
#: editor/animation_editor.cpp
msgid "In-Out"
-msgstr ""
+msgstr "داخل-خارج"
#: editor/animation_editor.cpp
msgid "Out-In"
-msgstr ""
+msgstr "خارج-داخل"
#: editor/animation_editor.cpp
msgid "Transitions"
-msgstr ""
+msgstr "تحولات"
#: editor/animation_editor.cpp
msgid "Optimize Animation"
-msgstr ""
+msgstr "تحسين الحركة"
#: editor/animation_editor.cpp
msgid "Clean-Up Animation"
-msgstr ""
+msgstr "تنظي٠الحركة"
#: editor/animation_editor.cpp
msgid "Create NEW track for %s and insert key?"
-msgstr ""
+msgstr "أنشئ مسار جديد لـ %s Ùˆ أدخل Ù…Ùتاح؟"
#: editor/animation_editor.cpp
msgid "Create %d NEW tracks and insert keys?"
-msgstr ""
+msgstr "أنشئ %d مسارات جديدة Ùˆ أدخل Ù…Ùاتيح؟"
#: editor/animation_editor.cpp editor/create_dialog.cpp
-#: editor/editor_audio_buses.cpp
+#: editor/editor_audio_buses.cpp editor/plugins/abstract_polygon_2d_editor.cpp
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
#: editor/plugins/mesh_instance_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp editor/project_manager.cpp
#: editor/script_create_dialog.cpp
msgid "Create"
-msgstr ""
+msgstr "أنشئ"
#: editor/animation_editor.cpp
msgid "Anim Create & Insert"
-msgstr ""
+msgstr "أنشي حركة وأدخلها"
#: editor/animation_editor.cpp
msgid "Anim Insert Track & Key"
-msgstr ""
+msgstr "أنشي مسار حركة Ùˆ Ù…Ùتاح"
#: editor/animation_editor.cpp
msgid "Anim Insert Key"
-msgstr ""
+msgstr "أض٠مÙتاح حركة"
#: editor/animation_editor.cpp
msgid "Change Anim Len"
-msgstr ""
+msgstr "تغيير خط الحركة"
#: editor/animation_editor.cpp
msgid "Change Anim Loop"
-msgstr ""
+msgstr "تغيير تكرير الحركة"
#: editor/animation_editor.cpp
msgid "Anim Create Typed Value Key"
-msgstr ""
+msgstr "أنشي Ù…Ùتاح حركة ذا قيمة مكتوبة"
#: editor/animation_editor.cpp
msgid "Anim Insert"
-msgstr ""
+msgstr "إدخال حركة"
#: editor/animation_editor.cpp
msgid "Anim Scale Keys"
-msgstr ""
+msgstr "Ù…Ùتاح تكبير حركة"
#: editor/animation_editor.cpp
msgid "Anim Add Call Track"
-msgstr ""
+msgstr "أض٠خانة مسار حركة"
#: editor/animation_editor.cpp
msgid "Animation zoom."
-msgstr ""
+msgstr "تكبير الحركة."
#: editor/animation_editor.cpp
msgid "Length (s):"
-msgstr ""
+msgstr "الطول (ثانية):"
#: editor/animation_editor.cpp
msgid "Animation length (in seconds)."
-msgstr ""
+msgstr "طول الأنميشين (بالثواني)."
#: editor/animation_editor.cpp
msgid "Step (s):"
-msgstr ""
+msgstr "خطوة (ثانية):"
#: editor/animation_editor.cpp
msgid "Cursor step snap (in seconds)."
-msgstr ""
+msgstr "المؤشر خطوة خطوة (بالثواني)."
#: editor/animation_editor.cpp
msgid "Enable/Disable looping in animation."
-msgstr ""
+msgstr "تمكين/تعطيل التكرار ÙÙŠ الحركة."
#: editor/animation_editor.cpp
msgid "Add new tracks."
-msgstr ""
+msgstr "أض٠مسارات جديدة."
#: editor/animation_editor.cpp
msgid "Move current track up."
-msgstr ""
+msgstr "تحريك المسار الحالي للأعلى."
#: editor/animation_editor.cpp
msgid "Move current track down."
-msgstr ""
+msgstr "تحريك المسار الحالي للاسÙÙ„."
#: editor/animation_editor.cpp
msgid "Remove selected track."
-msgstr ""
+msgstr "ازالة المسار المحدد."
#: editor/animation_editor.cpp
msgid "Track tools"
-msgstr ""
+msgstr "أدوات المسار"
#: editor/animation_editor.cpp
msgid "Enable editing of individual keys by clicking them."
-msgstr ""
+msgstr "السماح بتعديل ازرار منÙصلة بالضغط عليها."
#: editor/animation_editor.cpp
msgid "Anim. Optimizer"
-msgstr ""
+msgstr "Ù…Ùحسن الحركة"
#: editor/animation_editor.cpp
msgid "Max. Linear Error:"
-msgstr ""
+msgstr "أقصي أخطاء خطية:"
#: editor/animation_editor.cpp
msgid "Max. Angular Error:"
-msgstr ""
+msgstr "أقصي أخطاء زواية:"
#: editor/animation_editor.cpp
msgid "Max Optimizable Angle:"
-msgstr ""
+msgstr "أقصي زواية تحسين:"
#: editor/animation_editor.cpp
msgid "Optimize"
-msgstr ""
+msgstr "تحسين"
#: editor/animation_editor.cpp
msgid "Select an AnimationPlayer from the Scene Tree to edit animations."
-msgstr ""
+msgstr "خدد مشغل حركة من شجرة المشهد لكي تعدل الحركة."
#: editor/animation_editor.cpp
msgid "Key"
-msgstr ""
+msgstr "Ù…Ùتاح"
#: editor/animation_editor.cpp
msgid "Transition"
-msgstr ""
+msgstr "تحول"
#: editor/animation_editor.cpp
msgid "Scale Ratio:"
-msgstr ""
+msgstr "نسبة التكبير:"
#: editor/animation_editor.cpp
msgid "Call Functions in Which Node?"
-msgstr ""
+msgstr "إستدعاء وظائ٠ÙÙŠ أي عقدة؟"
#: editor/animation_editor.cpp
msgid "Remove invalid keys"
-msgstr ""
+msgstr "إمسح المÙاتيح الÙاسدة"
#: editor/animation_editor.cpp
msgid "Remove unresolved and empty tracks"
-msgstr ""
+msgstr "إمسح المسارات الÙارغة أو الغير محلولة"
#: editor/animation_editor.cpp
msgid "Clean-up all animations"
-msgstr ""
+msgstr "تنظي٠جميع الحركات"
#: editor/animation_editor.cpp
msgid "Clean-Up Animation(s) (NO UNDO!)"
-msgstr ""
+msgstr "تنظي٠الحركة(ات) (بلا عودة)"
#: editor/animation_editor.cpp
msgid "Clean-Up"
-msgstr ""
+msgstr "تنظيÙ"
#: editor/array_property_edit.cpp
msgid "Resize Array"
-msgstr ""
+msgstr "تغيير حجم المصÙÙˆÙØ©"
#: editor/array_property_edit.cpp
msgid "Change Array Value Type"
-msgstr ""
+msgstr "تغيير نوع القيم ÙÙŠ المصÙÙˆÙØ©"
#: editor/array_property_edit.cpp
msgid "Change Array Value"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Free"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_plugin_settings.cpp
-msgid "Version:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Contents:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "View Files"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_help.cpp editor/property_selector.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Description:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-#: editor/project_manager.cpp
-msgid "Install"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/call_dialog.cpp
-#: editor/connections_dialog.cpp editor/export_template_manager.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-#: editor/project_settings_editor.cpp editor/property_editor.cpp
-#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Close"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve hostname:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Connection error, please try again."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't connect."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't connect to host:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response from host:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Request failed, return code:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Req. Failed."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Request failed, too many redirects"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Redirect Loop."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Bad download hash, assuming file has been tampered with."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Expected:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Got:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Asset Download Error:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-msgid "Success!"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Fetching:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Resolving.."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Connecting.."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Requesting.."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Error making request"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Idle"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Retry"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Download Error"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Download for this asset is already in progress!"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "first"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "prev"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "next"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "last"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "All"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
-#: editor/settings_config_dialog.cpp
-msgid "Search:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/code_editor.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Search"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/project_manager.cpp
-msgid "Import"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Plugins"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Sort:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Reverse"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Category:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Site:"
-msgstr "الموقع:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Support.."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Official"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-msgid "Community"
-msgstr "مجتمع"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Testing"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Assets ZIP File"
-msgstr "مل٠اصول مضغوطة"
-
-#: editor/call_dialog.cpp
-msgid "Method List For '%s':"
-msgstr ""
-
-#: editor/call_dialog.cpp modules/visual_script/visual_script_editor.cpp
-msgid "Call"
-msgstr "نداء"
-
-#: editor/call_dialog.cpp
-msgid "Method List:"
-msgstr ""
-
-#: editor/call_dialog.cpp
-msgid "Arguments:"
-msgstr ""
-
-#: editor/call_dialog.cpp
-msgid "Return:"
-msgstr ""
+msgstr "تغيير قيمة ÙÙŠ المصÙÙˆÙØ©"
#: editor/code_editor.cpp
msgid "Go to Line"
-msgstr ""
+msgstr "إذهب إلي الخط"
#: editor/code_editor.cpp
msgid "Line Number:"
-msgstr ""
+msgstr "رقم الخط:"
#: editor/code_editor.cpp
msgid "No Matches"
-msgstr ""
+msgstr "لا مطابقة"
#: editor/code_editor.cpp
msgid "Replaced %d occurrence(s)."
-msgstr ""
+msgstr "إستبÙدل %d حادثة(حوادث)."
#: editor/code_editor.cpp
msgid "Replace"
-msgstr ""
+msgstr "إستبدال"
#: editor/code_editor.cpp
msgid "Replace All"
-msgstr ""
+msgstr "إستبدال الكل"
#: editor/code_editor.cpp
msgid "Match Case"
-msgstr ""
+msgstr "قضية تشابه"
#: editor/code_editor.cpp
msgid "Whole Words"
-msgstr ""
+msgstr "كل الكلمات"
#: editor/code_editor.cpp
msgid "Selection Only"
-msgstr ""
+msgstr "المحدد Ùقط"
+
+#: editor/code_editor.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
+msgid "Search"
+msgstr "بحث"
#: editor/code_editor.cpp editor/editor_help.cpp
msgid "Find"
-msgstr ""
+msgstr "جد"
#: editor/code_editor.cpp
msgid "Next"
-msgstr ""
+msgstr "التالي"
#: editor/code_editor.cpp
msgid "Not found!"
-msgstr ""
+msgstr "لم يوجد!"
#: editor/code_editor.cpp
msgid "Replace By"
-msgstr ""
+msgstr "إستبدلت بـ"
#: editor/code_editor.cpp
msgid "Case Sensitive"
-msgstr ""
+msgstr "حساسة لحالة الأحرÙ"
#: editor/code_editor.cpp
msgid "Backwards"
-msgstr ""
+msgstr "إلي الخلÙ"
#: editor/code_editor.cpp
msgid "Prompt On Replace"
-msgstr ""
+msgstr "تأكيد عند الإستبدال"
#: editor/code_editor.cpp
msgid "Skip"
-msgstr ""
+msgstr "تخطي"
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom In"
-msgstr ""
+msgstr "تقريب"
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom Out"
-msgstr ""
+msgstr "إبعاد"
#: editor/code_editor.cpp
msgid "Reset Zoom"
-msgstr ""
+msgstr "إرجاع التكبير"
#: editor/code_editor.cpp editor/script_editor_debugger.cpp
msgid "Line:"
-msgstr ""
+msgstr "الخط:"
#: editor/code_editor.cpp
msgid "Col:"
-msgstr ""
+msgstr "العمود:"
#: editor/connections_dialog.cpp
msgid "Method in target Node must be specified!"
-msgstr ""
+msgstr "الطريقة ÙÙŠ العقدة المستهدÙØ© يجب أن تكون محدّدة!"
#: editor/connections_dialog.cpp
msgid ""
"Target method not found! Specify a valid method or attach a script to target "
"Node."
msgstr ""
+"لم يتم العثور على الطريقة المستهدÙØ©! حدّد طريقة سليمة أو أرÙÙ‚ سيكربت لاستهدا٠"
+"العقدة."
#: editor/connections_dialog.cpp
msgid "Connect To Node:"
-msgstr ""
+msgstr "صلها بالعقدة:"
#: editor/connections_dialog.cpp editor/editor_autoload_settings.cpp
#: editor/groups_editor.cpp editor/plugins/item_list_editor_plugin.cpp
#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp
msgid "Add"
-msgstr ""
+msgstr "أضÙ"
#: editor/connections_dialog.cpp editor/dependency_editor.cpp
#: editor/plugins/animation_tree_editor_plugin.cpp
#: editor/plugins/theme_editor_plugin.cpp editor/project_manager.cpp
#: editor/project_settings_editor.cpp
msgid "Remove"
-msgstr ""
+msgstr "إمسح"
#: editor/connections_dialog.cpp
msgid "Add Extra Call Argument:"
-msgstr ""
+msgstr "إضاÙØ© وسيطة إستدعاء إضاÙية"
#: editor/connections_dialog.cpp
msgid "Extra Call Arguments:"
-msgstr ""
+msgstr "وسائط إستدعاء إضاÙية :"
#: editor/connections_dialog.cpp
msgid "Path to Node:"
-msgstr ""
+msgstr "مسار العقدة:"
#: editor/connections_dialog.cpp
msgid "Make Function"
-msgstr ""
+msgstr "إصنع دالة"
#: editor/connections_dialog.cpp
msgid "Deferred"
-msgstr ""
+msgstr "مؤجل"
#: editor/connections_dialog.cpp
msgid "Oneshot"
-msgstr ""
+msgstr "لقطة واحدة"
+
+#: editor/connections_dialog.cpp editor/dependency_editor.cpp
+#: editor/export_template_manager.cpp
+#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Close"
+msgstr "اغلاق"
#: editor/connections_dialog.cpp
msgid "Connect"
-msgstr ""
+msgstr "وصل"
#: editor/connections_dialog.cpp
msgid "Connect '%s' to '%s'"
-msgstr ""
+msgstr "وصل '%s' إلي '%s'"
#: editor/connections_dialog.cpp
msgid "Connecting Signal:"
-msgstr ""
+msgstr "يوصل الإشارة:"
#: editor/connections_dialog.cpp
msgid "Create Subscription"
@@ -771,89 +543,110 @@ msgstr "عمل اشتراك"
#: editor/connections_dialog.cpp
msgid "Connect.."
-msgstr ""
+msgstr "يتصل..."
#: editor/connections_dialog.cpp
#: editor/plugins/animation_tree_editor_plugin.cpp
msgid "Disconnect"
-msgstr ""
+msgstr "قطع الاتصال"
-#: editor/connections_dialog.cpp editor/node_dock.cpp
+#: editor/connections_dialog.cpp editor/editor_help.cpp editor/node_dock.cpp
msgid "Signals"
-msgstr ""
+msgstr "الإشارات"
#: editor/create_dialog.cpp
msgid "Create New"
-msgstr ""
+msgstr "إصنع جديد"
#: editor/create_dialog.cpp editor/editor_file_dialog.cpp
#: editor/filesystem_dock.cpp
msgid "Favorites:"
-msgstr ""
+msgstr "المÙضلة:"
#: editor/create_dialog.cpp editor/editor_file_dialog.cpp
msgid "Recent:"
-msgstr ""
+msgstr "الحالي:"
+
+#: editor/create_dialog.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/quick_open.cpp editor/settings_config_dialog.cpp
+msgid "Search:"
+msgstr "بحث:"
#: editor/create_dialog.cpp editor/editor_help.cpp
#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/quick_open.cpp
msgid "Matches:"
-msgstr ""
+msgstr "يطابق:"
+
+#: editor/create_dialog.cpp editor/editor_help.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/property_selector.cpp
+#: editor/script_editor_debugger.cpp
+msgid "Description:"
+msgstr "الوصÙ:"
#: editor/dependency_editor.cpp
msgid "Search Replacement For:"
-msgstr ""
+msgstr "البحث عن بديل لـ:"
#: editor/dependency_editor.cpp
msgid "Dependencies For:"
-msgstr ""
+msgstr "تابعة لـ:"
#: editor/dependency_editor.cpp
msgid ""
"Scene '%s' is currently being edited.\n"
"Changes will not take effect unless reloaded."
msgstr ""
+"المشهد '%s' هو حالياً جاري تعديله.\n"
+"التغييرات لن تحصل حتي يتم إعادة التشغيل."
#: editor/dependency_editor.cpp
msgid ""
"Resource '%s' is in use.\n"
"Changes will take effect when reloaded."
msgstr ""
+"المورد '%s' قيد الإستخدام.\n"
+"التغييرات ستظهر بعد إعادة التشغيل."
#: editor/dependency_editor.cpp
msgid "Dependencies"
-msgstr ""
+msgstr "التبعيات"
#: editor/dependency_editor.cpp
msgid "Resource"
-msgstr ""
+msgstr "مورد"
#: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp
#: editor/project_manager.cpp editor/project_settings_editor.cpp
#: editor/script_create_dialog.cpp
msgid "Path"
-msgstr ""
+msgstr "مسار"
#: editor/dependency_editor.cpp
msgid "Dependencies:"
-msgstr ""
+msgstr "التبعيات:"
#: editor/dependency_editor.cpp
msgid "Fix Broken"
-msgstr ""
+msgstr "أصلح المعطوب"
#: editor/dependency_editor.cpp
msgid "Dependency Editor"
-msgstr ""
+msgstr "محرر التبعيات"
#: editor/dependency_editor.cpp
msgid "Search Replacement Resource:"
-msgstr ""
+msgstr "البحث عن مورد بديل:"
#: editor/dependency_editor.cpp
msgid "Owners Of:"
-msgstr ""
+msgstr "ملاك:"
+
+#: editor/dependency_editor.cpp
+msgid "Remove selected files from the project? (no undo)"
+msgstr "إمسح الملÙات المحددة من المشروع؟ (لا رجعة)"
#: editor/dependency_editor.cpp
msgid ""
@@ -861,101 +654,132 @@ msgid ""
"work.\n"
"Remove them anyway? (no undo)"
msgstr ""
+"المل٠الذي يمسح مطلوب من موارد أخري لكل تعمل جيداً.\n"
+"إمسح علي أية حال؟ (لا رجعة)"
#: editor/dependency_editor.cpp
-msgid "Remove selected files from the project? (no undo)"
-msgstr ""
+#, fuzzy
+msgid "Cannot remove:\n"
+msgstr "لا يمكن الحل."
#: editor/dependency_editor.cpp
msgid "Error loading:"
-msgstr ""
+msgstr "خطآ ÙÙŠ التحميل:"
#: editor/dependency_editor.cpp
msgid "Scene failed to load due to missing dependencies:"
-msgstr ""
+msgstr "Ùشل ÙÙŠ تحميل المشهد بسبب وجود ملÙات Ù…Ùقودة يعتمد المشهد عليها:"
#: editor/dependency_editor.cpp editor/editor_node.cpp
msgid "Open Anyway"
-msgstr ""
+msgstr "Ø¥Ùتح علي أية حال"
#: editor/dependency_editor.cpp
msgid "Which action should be taken?"
-msgstr ""
+msgstr "ماذا يجب أن ÙŠÙÙعل؟"
#: editor/dependency_editor.cpp
msgid "Fix Dependencies"
-msgstr ""
+msgstr "أصلح التبعيات"
#: editor/dependency_editor.cpp
msgid "Errors loading!"
-msgstr ""
+msgstr "اخطاء ÙÙŠ التحميل!"
#: editor/dependency_editor.cpp
msgid "Permanently delete %d item(s)? (No undo!)"
-msgstr ""
+msgstr "إمسح نهائيا %d عنصر(عناصر)؟ (بلا رجعة!)"
#: editor/dependency_editor.cpp
msgid "Owns"
-msgstr ""
+msgstr "يملك"
#: editor/dependency_editor.cpp
msgid "Resources Without Explicit Ownership:"
-msgstr ""
+msgstr "موارد من غير مالك صريح:"
#: editor/dependency_editor.cpp editor/editor_node.cpp
msgid "Orphan Resource Explorer"
-msgstr ""
+msgstr "متصÙØ­ الموارد أورÙان"
#: editor/dependency_editor.cpp
msgid "Delete selected files?"
-msgstr ""
+msgstr "إمسح الملÙات المحددة؟"
#: editor/dependency_editor.cpp editor/editor_audio_buses.cpp
#: editor/editor_node.cpp editor/filesystem_dock.cpp
#: editor/plugins/item_list_editor_plugin.cpp editor/project_export.cpp
#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp
msgid "Delete"
-msgstr ""
+msgstr "مسح"
#: editor/editor_about.cpp
msgid "Thanks from the Godot community!"
-msgstr ""
+msgstr "شكراً من مجتمع Godot!"
#: editor/editor_about.cpp
msgid "Thanks!"
-msgstr ""
+msgstr "شكراً!"
#: editor/editor_about.cpp
msgid "Godot Engine contributors"
-msgstr ""
-
-#: editor/editor_about.cpp
-msgid "Authors"
-msgstr ""
+msgstr "المسهامين ÙÙŠ محرك Godot"
#: editor/editor_about.cpp
msgid "Project Founders"
-msgstr ""
+msgstr "مؤسسون المشروع"
#: editor/editor_about.cpp
msgid "Lead Developer"
-msgstr ""
+msgstr "قائد المطوريين"
#: editor/editor_about.cpp editor/project_manager.cpp
msgid "Project Manager"
-msgstr ""
+msgstr "مدير المشروع"
#: editor/editor_about.cpp
msgid "Developers"
-msgstr ""
+msgstr "المطورون"
+
+#: editor/editor_about.cpp
+msgid "Authors"
+msgstr "المالكون"
+
+#: editor/editor_about.cpp
+msgid "Platinum Sponsors"
+msgstr "الرعاة البلاتينيين"
+
+#: editor/editor_about.cpp
+msgid "Gold Sponsors"
+msgstr "الرعاة الذهبيين"
+
+#: editor/editor_about.cpp
+msgid "Mini Sponsors"
+msgstr "الرعاة الصغار"
+
+#: editor/editor_about.cpp
+msgid "Gold Donors"
+msgstr "المانحين الذهبيين"
+
+#: editor/editor_about.cpp
+msgid "Silver Donors"
+msgstr "المانحين الÙضيين"
+
+#: editor/editor_about.cpp
+msgid "Bronze Donors"
+msgstr "المانحين البرنزيين"
+
+#: editor/editor_about.cpp
+msgid "Donors"
+msgstr "مانحين"
#: editor/editor_about.cpp
msgid "License"
-msgstr ""
+msgstr "الترخيص"
#: editor/editor_about.cpp
msgid "Thirdparty License"
-msgstr ""
+msgstr "ترخيص الطر٠الثالث"
#: editor/editor_about.cpp
msgid ""
@@ -964,344 +788,343 @@ msgid ""
"is an exhaustive list of all such thirdparty components with their "
"respective copyright statements and license terms."
msgstr ""
+"محرك \"Godot\" يعتمد على عدد من المكتبات و المكونات البرمجية لملاك اخرين و "
+"لكنها مجانية Ùˆ Ù…Ùتوحة المصدر، Ùˆ كلها متÙقة مع شروط الاستخدام لرخصة \"MIT\". "
+"ÙÙŠ ما يلي قائمة تحوي جميع هذه المكونات اضاÙØ© الى حقوق النشر Ùˆ شروط الاستخدام "
+"الخاصة بها."
#: editor/editor_about.cpp
msgid "All Components"
-msgstr ""
+msgstr "كل المكونات"
#: editor/editor_about.cpp
msgid "Components"
-msgstr ""
+msgstr "مكونات"
#: editor/editor_about.cpp
msgid "Licenses"
-msgstr ""
+msgstr "تراخيص"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Error opening package file, not in zip format."
-msgstr ""
+msgstr "خطأ عندÙتح مل٠الحزمة بسبب أن المل٠ليس ÙÙŠ صيغة \"ZIP\"."
#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
-msgstr ""
+msgstr "ÙŠÙكك الضغط عن الأصول"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package Installed Successfully!"
-msgstr ""
+msgstr "الحزمة تم تثبيتها بنجاح!"
+
+#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Success!"
+msgstr "تم بنجاح!"
+
+#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/project_manager.cpp
+msgid "Install"
+msgstr "تثبيت"
#: editor/editor_asset_installer.cpp
msgid "Package Installer"
-msgstr ""
+msgstr "مثبت الحزم"
#: editor/editor_audio_buses.cpp
msgid "Speakers"
-msgstr ""
+msgstr "مكبرات الصوت"
#: editor/editor_audio_buses.cpp
msgid "Add Effect"
-msgstr ""
+msgstr "أض٠تأثير"
#: editor/editor_audio_buses.cpp
msgid "Rename Audio Bus"
-msgstr ""
+msgstr "إعادة تسمية بيوس الصوت"
#: editor/editor_audio_buses.cpp
msgid "Toggle Audio Bus Solo"
-msgstr ""
+msgstr "تبديل بيوس الصوت إلي Ùردي"
#: editor/editor_audio_buses.cpp
msgid "Toggle Audio Bus Mute"
-msgstr ""
+msgstr "تبديل بيوس الصوت إلي صامت"
#: editor/editor_audio_buses.cpp
msgid "Toggle Audio Bus Bypass Effects"
-msgstr ""
+msgstr "تبديل بيوس الصوت إلي موثرات التبديل"
#: editor/editor_audio_buses.cpp
msgid "Select Audio Bus Send"
-msgstr ""
+msgstr "حدد بيوس الصوت للإرسال"
#: editor/editor_audio_buses.cpp
msgid "Add Audio Bus Effect"
-msgstr ""
+msgstr "أض٠موثرات إلي بيوس الصوت"
#: editor/editor_audio_buses.cpp
msgid "Move Bus Effect"
-msgstr ""
+msgstr "حرك مؤثر البيوس"
#: editor/editor_audio_buses.cpp
msgid "Delete Bus Effect"
-msgstr ""
+msgstr "مسح تأثير البيوس"
#: editor/editor_audio_buses.cpp
msgid "Audio Bus, Drag and Drop to rearrange."
-msgstr ""
-
-#: editor/editor_audio_buses.cpp
-msgid "Bus options"
-msgstr ""
+msgstr "بيوس الصوت، سحب وإسقاط لإعادة الترتيب."
#: editor/editor_audio_buses.cpp
msgid "Solo"
-msgstr ""
+msgstr "Ùردي"
#: editor/editor_audio_buses.cpp
msgid "Mute"
-msgstr ""
+msgstr "صامت"
#: editor/editor_audio_buses.cpp
msgid "Bypass"
-msgstr ""
+msgstr "تخطي"
+
+#: editor/editor_audio_buses.cpp
+msgid "Bus options"
+msgstr "إعدادات البيوس"
#: editor/editor_audio_buses.cpp editor/plugins/tile_map_editor_plugin.cpp
#: editor/scene_tree_dock.cpp
msgid "Duplicate"
-msgstr ""
+msgstr "تكرير"
+
+#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Reset Volume"
+msgstr "إرجاع التكبير"
#: editor/editor_audio_buses.cpp
msgid "Delete Effect"
-msgstr ""
+msgstr "إمسح التأثير"
#: editor/editor_audio_buses.cpp
msgid "Add Audio Bus"
-msgstr ""
+msgstr "أض٠بيوس الصوت"
#: editor/editor_audio_buses.cpp
msgid "Master bus can't be deleted!"
-msgstr ""
+msgstr "البيوس الأساسي لا يمكن مسحة!"
#: editor/editor_audio_buses.cpp
msgid "Delete Audio Bus"
-msgstr ""
+msgstr "إمسح بيوس الصوت"
#: editor/editor_audio_buses.cpp
msgid "Duplicate Audio Bus"
-msgstr ""
+msgstr "تكرير بيوس الصوت"
#: editor/editor_audio_buses.cpp
#, fuzzy
+msgid "Reset Bus Volume"
+msgstr "إرجاع التكبير"
+
+#: editor/editor_audio_buses.cpp
msgid "Move Audio Bus"
-msgstr "عملية تحريك"
+msgstr "تحريك بيوس الصوت"
#: editor/editor_audio_buses.cpp
msgid "Save Audio Bus Layout As.."
-msgstr ""
+msgstr "إحÙظ نسق بيوس الصوت كـ..."
#: editor/editor_audio_buses.cpp
msgid "Location for New Layout.."
-msgstr ""
+msgstr "المكان للنسق الجديد..."
#: editor/editor_audio_buses.cpp
msgid "Open Audio Bus Layout"
-msgstr ""
+msgstr "Ø¥Ùتح نسق بيوس الصوت"
#: editor/editor_audio_buses.cpp
msgid "There is no 'res://default_bus_layout.tres' file."
-msgstr ""
+msgstr "ليس هناك مل٠'res://default_bus_layout.tres'."
#: editor/editor_audio_buses.cpp
msgid "Invalid file, not an audio bus layout."
-msgstr ""
+msgstr "مل٠خطأ، ليس مل٠نسق بيوس الصوت."
#: editor/editor_audio_buses.cpp
msgid "Add Bus"
-msgstr ""
+msgstr "أض٠بيوس"
#: editor/editor_audio_buses.cpp
msgid "Create a new Bus Layout."
-msgstr ""
+msgstr "إصنع نسق بيوس جديد."
-#: editor/editor_audio_buses.cpp editor/script_create_dialog.cpp
+#: editor/editor_audio_buses.cpp editor/property_editor.cpp
+#: editor/script_create_dialog.cpp
msgid "Load"
-msgstr ""
+msgstr "تحميل"
#: editor/editor_audio_buses.cpp
msgid "Load an existing Bus Layout."
-msgstr ""
+msgstr "تحميل نسق بيوس موجود مسبقاً."
#: editor/editor_audio_buses.cpp
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Save As"
-msgstr ""
+msgstr "Ø­Ùظ بأسم"
#: editor/editor_audio_buses.cpp
msgid "Save this Bus Layout to a file."
-msgstr ""
+msgstr "إحÙظ نسق البيوس هذا إلي ملÙ."
#: editor/editor_audio_buses.cpp editor/import_dock.cpp
msgid "Load Default"
-msgstr ""
+msgstr "تحميل الإÙتراضي"
#: editor/editor_audio_buses.cpp
msgid "Load the default Bus Layout."
-msgstr ""
+msgstr "تحميل نسق البيوس الإÙتراضي."
#: editor/editor_autoload_settings.cpp
msgid "Invalid name."
-msgstr ""
+msgstr "اسم غير صالح."
#: editor/editor_autoload_settings.cpp
msgid "Valid characters:"
-msgstr ""
+msgstr "الأحر٠الصالحة:"
#: editor/editor_autoload_settings.cpp
msgid "Invalid name. Must not collide with an existing engine class name."
-msgstr ""
+msgstr "إسم غير صالح، يجب أن لا يتصادم مع أسم Ùصل خاص بالمحرك."
#: editor/editor_autoload_settings.cpp
msgid "Invalid name. Must not collide with an existing buit-in type name."
-msgstr ""
+msgstr "إسم غير صالح، يجب أن لا يتصادم مع الأسماء المبنية تلقائياً الموجودة."
#: editor/editor_autoload_settings.cpp
msgid "Invalid name. Must not collide with an existing global constant name."
-msgstr ""
+msgstr "إسم غير صالح، ييجب ألاّ يتصادم مع إسم موجود لثابت عمومي."
#: editor/editor_autoload_settings.cpp
msgid "Invalid Path."
-msgstr ""
+msgstr "مسار غير صالح."
#: editor/editor_autoload_settings.cpp
msgid "File does not exist."
-msgstr ""
+msgstr "المل٠غير موجود."
#: editor/editor_autoload_settings.cpp
msgid "Not in resource path."
-msgstr ""
+msgstr "ليس ÙÙŠ مسار الموارد."
#: editor/editor_autoload_settings.cpp
msgid "Add AutoLoad"
-msgstr ""
+msgstr "إضاÙØ© للتحميل التلقائي"
#: editor/editor_autoload_settings.cpp
msgid "Autoload '%s' already exists!"
-msgstr ""
+msgstr "التحميل التلقائي '%s' موجود اصلا!"
#: editor/editor_autoload_settings.cpp
msgid "Rename Autoload"
-msgstr ""
+msgstr "اعادة تسمية التحميل التلقائي"
#: editor/editor_autoload_settings.cpp
msgid "Toggle AutoLoad Globals"
-msgstr ""
+msgstr "تبديل التحميل التلقائي العام"
#: editor/editor_autoload_settings.cpp
msgid "Move Autoload"
-msgstr ""
+msgstr "نقل التحميل التلقائي"
#: editor/editor_autoload_settings.cpp
msgid "Remove Autoload"
-msgstr ""
+msgstr "ازالة التحميل التلقائي"
#: editor/editor_autoload_settings.cpp
msgid "Enable"
-msgstr ""
+msgstr "تمكين"
#: editor/editor_autoload_settings.cpp
msgid "Rearrange Autoloads"
-msgstr ""
+msgstr "اعادة ترتيب التحميلات التلقائية"
#: editor/editor_autoload_settings.cpp editor/editor_file_dialog.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp scene/gui/file_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/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp editor/project_manager.cpp
+#: editor/editor_autoload_settings.cpp editor/project_manager.cpp
msgid "Name"
-msgstr ""
+msgstr "الأسم"
#: editor/editor_autoload_settings.cpp
msgid "Singleton"
-msgstr ""
+msgstr "الÙردية"
#: editor/editor_autoload_settings.cpp
msgid "List:"
-msgstr ""
+msgstr "القائمة:"
#: editor/editor_data.cpp
msgid "Updating Scene"
-msgstr ""
+msgstr "ÙŠÙحدث المشهد"
#: editor/editor_data.cpp
msgid "Storing local changes.."
-msgstr ""
+msgstr "جاري تخزين التعديلات المحلية.."
#: editor/editor_data.cpp
msgid "Updating scene.."
-msgstr ""
+msgstr "ÙŠÙحدث المشهد..."
#: editor/editor_dir_dialog.cpp
msgid "Please select a base directory first"
-msgstr ""
+msgstr "من Ùضلك حدد الوجهة الأساسية أولاً"
#: editor/editor_dir_dialog.cpp
msgid "Choose a Directory"
-msgstr ""
+msgstr "حدد الوجهة"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Create Folder"
-msgstr ""
+msgstr "أنشئ مجلد"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: editor/editor_plugin_settings.cpp editor/plugins/theme_editor_plugin.cpp
-#: editor/project_export.cpp scene/gui/file_dialog.cpp
+#: editor/editor_plugin_settings.cpp editor/filesystem_dock.cpp
+#: editor/plugins/theme_editor_plugin.cpp editor/project_export.cpp
+#: scene/gui/file_dialog.cpp
msgid "Name:"
-msgstr ""
+msgstr "الأسم:"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Could not create folder."
-msgstr ""
+msgstr "لا يمكن إنشاء المجلد."
#: editor/editor_dir_dialog.cpp
msgid "Choose"
-msgstr ""
+msgstr "إختر"
#: editor/editor_export.cpp
msgid "Storing File:"
-msgstr ""
+msgstr "تخزين الملÙ:"
#: editor/editor_export.cpp
msgid "Packing"
-msgstr ""
+msgstr "يَحزم\"ينتج المل٠المضغوط\""
#: editor/editor_export.cpp platform/javascript/export/export.cpp
msgid "Template file not found:\n"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Added:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Removed:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Error saving atlas:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Could not save atlas subtexture:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Exporting for %s"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Setting Up.."
-msgstr ""
+msgstr "مل٠النموذج غير موجود:\n"
#: 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 "All Recognized"
@@ -1309,305 +1132,411 @@ msgstr "جميع الأنواع المعتمدة"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "All Files (*)"
-msgstr ""
+msgstr "كل الملÙات (*)"
#: editor/editor_file_dialog.cpp editor/editor_help.cpp editor/editor_node.cpp
#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
#: editor/property_selector.cpp editor/quick_open.cpp scene/gui/file_dialog.cpp
msgid "Open"
-msgstr ""
+msgstr "Ø¥Ùتح"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Open a File"
-msgstr ""
+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"
-msgstr ""
+msgstr "Ø¥Ùتح وجهة"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Open a File or Directory"
-msgstr ""
+msgstr "Ø¥Ùتح مل٠أو وجهة"
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
-msgstr ""
+msgstr "Ø­Ùظ"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Save a File"
-msgstr ""
+msgstr "Ø­Ùظ ملÙ"
#: editor/editor_file_dialog.cpp
msgid "Go Back"
-msgstr ""
+msgstr "إرجع للخلÙ"
#: editor/editor_file_dialog.cpp
msgid "Go Forward"
-msgstr ""
+msgstr "إذهب للأمام"
#: editor/editor_file_dialog.cpp
msgid "Go Up"
-msgstr ""
+msgstr "إذهب للأعلي"
#: editor/editor_file_dialog.cpp
msgid "Refresh"
-msgstr ""
+msgstr "تحديث"
#: editor/editor_file_dialog.cpp
msgid "Toggle Hidden Files"
-msgstr ""
+msgstr "أظهر الملÙات المخÙية"
#: editor/editor_file_dialog.cpp
msgid "Toggle Favorite"
-msgstr ""
+msgstr "أظهر المÙÙضلة"
#: editor/editor_file_dialog.cpp
msgid "Toggle Mode"
-msgstr ""
+msgstr "أظهر المود"
#: editor/editor_file_dialog.cpp
msgid "Focus Path"
-msgstr ""
+msgstr "مسار التركيز"
#: editor/editor_file_dialog.cpp
msgid "Move Favorite Up"
-msgstr ""
+msgstr "حرك المÙÙضلة للأعلي"
#: editor/editor_file_dialog.cpp
msgid "Move Favorite Down"
-msgstr ""
+msgstr "حرك المÙÙضلة للأسÙÙ„"
+
+#: editor/editor_file_dialog.cpp
+#, fuzzy
+msgid "Go to parent folder"
+msgstr "لا يمكن إنشاء المجلد."
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Directories & Files:"
-msgstr ""
+msgstr "الوجهات والملÙات:"
#: editor/editor_file_dialog.cpp
msgid "Preview:"
-msgstr ""
+msgstr "إستعراض:"
#: editor/editor_file_dialog.cpp editor/script_editor_debugger.cpp
#: scene/gui/file_dialog.cpp
msgid "File:"
-msgstr ""
-
-#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
-msgid "Filter:"
-msgstr ""
+msgstr "الملÙ:"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Must use a valid extension."
-msgstr ""
+msgstr "يجب أن يستخدم صيغة صحيحة."
#: editor/editor_file_system.cpp
msgid "ScanSources"
-msgstr ""
+msgstr "Ùحص المصادر"
#: editor/editor_file_system.cpp
msgid "(Re)Importing Assets"
-msgstr ""
+msgstr "إعادة إستيراد الأصول"
#: editor/editor_help.cpp editor/editor_node.cpp
#: editor/plugins/script_editor_plugin.cpp
msgid "Search Help"
-msgstr ""
+msgstr "إبحث ÙÙŠ المساعدة"
#: editor/editor_help.cpp
msgid "Class List:"
-msgstr ""
+msgstr "قائمة الأصناÙ:"
#: editor/editor_help.cpp
msgid "Search Classes"
-msgstr ""
+msgstr "إبحث ÙÙŠ الأصناÙ"
+
+#: editor/editor_help.cpp editor/plugins/spatial_editor_plugin.cpp
+msgid "Top"
+msgstr "Ùوق"
#: editor/editor_help.cpp editor/property_editor.cpp
msgid "Class:"
-msgstr ""
+msgstr "صنÙ:"
#: editor/editor_help.cpp editor/scene_tree_editor.cpp
msgid "Inherits:"
-msgstr ""
+msgstr "يرث:"
#: editor/editor_help.cpp
msgid "Inherited by:"
-msgstr ""
+msgstr "مورث بواسطة:"
#: editor/editor_help.cpp
msgid "Brief Description:"
-msgstr ""
+msgstr "وص٠مختصر:"
+
+#: editor/editor_help.cpp
+#, fuzzy
+msgid "Members"
+msgstr "الأعضاء:"
#: editor/editor_help.cpp modules/visual_script/visual_script_editor.cpp
msgid "Members:"
-msgstr ""
+msgstr "الأعضاء:"
+
+#: editor/editor_help.cpp
+#, fuzzy
+msgid "Public Methods"
+msgstr "الطرق العامة:"
#: editor/editor_help.cpp
msgid "Public Methods:"
-msgstr ""
+msgstr "الطرق العامة:"
+
+#: editor/editor_help.cpp
+#, fuzzy
+msgid "GUI Theme Items"
+msgstr "عناصر ثيم واجهة المستخدم:"
#: editor/editor_help.cpp
msgid "GUI Theme Items:"
-msgstr ""
+msgstr "عناصر ثيم واجهة المستخدم:"
#: editor/editor_help.cpp modules/visual_script/visual_script_editor.cpp
msgid "Signals:"
-msgstr ""
+msgstr "الإشارات:"
+
+#: editor/editor_help.cpp
+#, fuzzy
+msgid "Enumerations"
+msgstr "التعدادات:"
#: editor/editor_help.cpp
msgid "Enumerations:"
-msgstr ""
+msgstr "التعدادات:"
#: editor/editor_help.cpp
msgid "enum "
-msgstr ""
+msgstr "التعداد "
+
+#: editor/editor_help.cpp
+#, fuzzy
+msgid "Constants"
+msgstr "الثوابت:"
#: editor/editor_help.cpp
msgid "Constants:"
-msgstr ""
+msgstr "الثوابت:"
#: editor/editor_help.cpp
#, fuzzy
+msgid "Description"
+msgstr "الوصÙ:"
+
+#: editor/editor_help.cpp
+msgid "Properties"
+msgstr "خصائص"
+
+#: editor/editor_help.cpp
msgid "Property Description:"
-msgstr "عمل اشتراك"
+msgstr "وص٠الملكية:"
+
+#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this property. Please help us by "
+"[color=$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+"لا يوجد حاليا وص٠لهذه الخاصية. الرجاء المساعدة من خلال [url][/color/] "
+"المساهمة واحد [color=$color][url=$url]!"
+
+#: editor/editor_help.cpp
+#, fuzzy
+msgid "Methods"
+msgstr "قائمة الطرق:"
#: editor/editor_help.cpp
msgid "Method Description:"
+msgstr "وص٠الطريقة:"
+
+#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this method. Please help us by [color="
+"$color][url=$url]contributing one[/url][/color]!"
msgstr ""
+"لا يوجد حاليا وص٠لهذه الطريقة. الرجاء المساعدة من خلال [color=$color][url="
+"$url]المساهمة واحد[/url][/color] !"
#: editor/editor_help.cpp
msgid "Search Text"
-msgstr ""
+msgstr "إبحث عن كتابة"
#: editor/editor_log.cpp
msgid "Output:"
-msgstr ""
+msgstr "الخرج:"
#: editor/editor_log.cpp editor/plugins/animation_tree_editor_plugin.cpp
-#: editor/plugins/rich_text_editor_plugin.cpp editor/property_editor.cpp
-#: editor/script_editor_debugger.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/property_editor.cpp editor/script_editor_debugger.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Clear"
-msgstr ""
+msgstr "خالي"
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Error saving resource!"
-msgstr ""
+msgstr "خطأ ÙÙŠ Ø­Ùظ المورد!"
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Save Resource As.."
-msgstr ""
+msgstr "Ø­Ùظ المورد باسم..."
-#: editor/editor_node.cpp editor/export_template_manager.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "I see.."
-msgstr ""
+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."
+msgstr "خطأ خلال الحÙظ."
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Can't open '%s'."
+msgstr "لا يمكن الحل."
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Error while parsing '%s'."
+msgstr "خطأ خلال الحÙظ."
+
+#: editor/editor_node.cpp
+msgid "Unexpected end of file '%s'."
+msgstr "نهاية مل٠غير مرتقبة 's%'."
+
+#: editor/editor_node.cpp
+msgid "Missing '%s' or its dependencies."
msgstr ""
#: editor/editor_node.cpp
+#, fuzzy
+msgid "Error while loading '%s'."
+msgstr "خطأ خلال الحÙظ."
+
+#: editor/editor_node.cpp
msgid "Saving Scene"
-msgstr ""
+msgstr "Ø­Ùظ المشهد"
#: editor/editor_node.cpp
msgid "Analyzing"
-msgstr ""
+msgstr "يحلل"
#: editor/editor_node.cpp
msgid "Creating Thumbnail"
-msgstr ""
+msgstr "ينشئ الصورة المصغرة"
#: editor/editor_node.cpp
msgid "This operation can't be done without a tree root."
-msgstr ""
+msgstr "هذه العملية لا يمكنها الإكتمال من غير جزر الشجرة."
#: editor/editor_node.cpp
msgid ""
"Couldn't save scene. Likely dependencies (instances) couldn't be satisfied."
-msgstr ""
+msgstr "لا يمكن Ø­Ùظ المشهد. على الأرجح لا يمكن إستيÙاء التبعيات (مجسّدات)."
#: editor/editor_node.cpp
msgid "Failed to load resource."
-msgstr ""
+msgstr "Ùشل تحميل المورد."
#: editor/editor_node.cpp
msgid "Can't load MeshLibrary for merging!"
-msgstr ""
+msgstr "لا يمكن تحميل مكتبة الميش من أجل الدمج!"
#: editor/editor_node.cpp
msgid "Error saving MeshLibrary!"
-msgstr ""
+msgstr "خطأ ÙÙŠ Ø­Ùظ مكتبة الميش!"
#: editor/editor_node.cpp
msgid "Can't load TileSet for merging!"
-msgstr ""
+msgstr "لا يمكن تحميل مجموعة البلاط من أجل الدمج!"
#: editor/editor_node.cpp
msgid "Error saving TileSet!"
-msgstr ""
+msgstr "خطأ ÙÙŠ Ø­Ùظ مجموعة البلاط!"
#: editor/editor_node.cpp
msgid "Error trying to save layout!"
-msgstr ""
+msgstr "خطآ ÙÙŠ محاولة Ø­Ùظ النسق!"
#: editor/editor_node.cpp
msgid "Default editor layout overridden."
-msgstr ""
+msgstr "تخطي نسق المÙحرر الإÙتراضي."
#: editor/editor_node.cpp
msgid "Layout name not found!"
-msgstr ""
+msgstr "إسم النسق غير موجود!"
#: editor/editor_node.cpp
msgid "Restored default layout to base settings."
+msgstr "إسترجاع النسق الإÙتراضي إلي الإعدادات الأساسية."
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was imported, so it's not editable.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
msgstr ""
#: editor/editor_node.cpp
-msgid "Copy Params"
+msgid ""
+"This resource belongs to a scene that was instanced or inherited.\n"
+"Changes to it will not be kept when saving the current scene."
msgstr ""
#: editor/editor_node.cpp
-msgid "Paste Params"
+msgid ""
+"This resource was imported, so it's not editable. Change its settings in the "
+"import panel and then re-import."
msgstr ""
+#: editor/editor_node.cpp
+msgid ""
+"This scene was imported, so changes to it will not be kept.\n"
+"Instancing it or inheriting will allow making changes to it.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Copy Params"
+msgstr "إنسخ المÙعامل"
+
+#: editor/editor_node.cpp
+msgid "Paste Params"
+msgstr "لصق المÙعامل"
+
#: editor/editor_node.cpp editor/plugins/resource_preloader_editor_plugin.cpp
msgid "Paste Resource"
-msgstr ""
+msgstr "لصق الموارد"
#: editor/editor_node.cpp
msgid "Copy Resource"
-msgstr ""
+msgstr "نسخ الموارد"
#: editor/editor_node.cpp
msgid "Make Built-In"
-msgstr ""
+msgstr "إجعله Ù…Ùدمج"
#: editor/editor_node.cpp
msgid "Make Sub-Resources Unique"
-msgstr ""
+msgstr "إجعل الموارد الجانبية مميزة"
#: editor/editor_node.cpp
msgid "Open in Help"
-msgstr ""
+msgstr "Ø¥Ùتح ÙÙŠ المساعدة"
#: editor/editor_node.cpp
msgid "There is no defined scene to run."
-msgstr ""
+msgstr "ليس هناك مشهد محدد ليتم تشغيله."
#: editor/editor_node.cpp
msgid ""
@@ -1615,6 +1544,8 @@ msgid ""
"You can change it later in \"Project Settings\" under the 'application' "
"category."
msgstr ""
+"لا مشهد أساسي تم تحديده، حدد واحد؟\n"
+"يمكنك تغييره لاحقاً ÙÙŠ \"إعدادات المشروع\" تحت قسم 'التطبيق'."
#: editor/editor_node.cpp
msgid ""
@@ -1622,6 +1553,8 @@ msgid ""
"You can change it later in \"Project Settings\" under the 'application' "
"category."
msgstr ""
+"المشهد المÙحدد '%s' غير موجود، حدد مشهد صالح؟\n"
+"يمكنك تغييره لاحقاً ÙÙŠ \"إعدادات المشروع\" تحت قسم 'التطبيق'."
#: editor/editor_node.cpp
msgid ""
@@ -1632,7 +1565,7 @@ msgstr ""
#: editor/editor_node.cpp
msgid "Current scene was never saved, please save it prior to running."
-msgstr ""
+msgstr "المشهد الحالي لم يتم Ø­Ùظه. الرجاء Ø­Ùظ المشهد قبل تشغيله Ùˆ اختباره."
#: editor/editor_node.cpp
msgid "Could not start subprocess!"
@@ -1656,15 +1589,15 @@ msgstr ""
#: editor/editor_node.cpp
msgid "Save & Close"
-msgstr ""
+msgstr "Ø­Ùظ Ùˆ اغلاق"
#: editor/editor_node.cpp
msgid "Save changes to '%s' before closing?"
-msgstr ""
+msgstr "هل تريد Ø­Ùظ التغييرات Ù„'%s' قبل الاغلاق؟"
#: editor/editor_node.cpp
msgid "Save Scene As.."
-msgstr ""
+msgstr "Ø­Ùظ المشهد Ùƒ.."
#: editor/editor_node.cpp
msgid "No"
@@ -1676,7 +1609,7 @@ msgstr ""
#: editor/editor_node.cpp
msgid "This scene has never been saved. Save before running?"
-msgstr ""
+msgstr "هذا المشهد لم يتم Ø­Ùظه. هل تود Ø­Ùظه قبل تشغيله؟"
#: editor/editor_node.cpp editor/scene_tree_dock.cpp
msgid "This operation can't be done without a scene."
@@ -1696,11 +1629,11 @@ msgstr ""
#: editor/editor_node.cpp
msgid "Current scene not saved. Open anyway?"
-msgstr ""
+msgstr "لم يتم Ø­Ùظ المشهد الحالي. استمر بالÙتح على اية حال؟"
#: editor/editor_node.cpp
msgid "Can't reload a scene that was never saved."
-msgstr ""
+msgstr "لا يمكن اعادة تحميل مشهد لم يتم Ø­Ùظه من قبل."
#: editor/editor_node.cpp
msgid "Revert"
@@ -1728,34 +1661,47 @@ msgstr ""
#: editor/editor_node.cpp
msgid "Save & Quit"
-msgstr ""
+msgstr "Ø­Ùظ Ùˆ خروج"
#: editor/editor_node.cpp
msgid "Save changes to the following scene(s) before quitting?"
-msgstr ""
+msgstr "هل تريد Ø­Ùظ التغييرات للمشاهد التالية قبل الخروج؟"
#: editor/editor_node.cpp
msgid "Save changes the following scene(s) before opening Project Manager?"
msgstr ""
+"هل تود Ø­Ùظ التغييرات التي اجريت على المشاهد الحالية قبل Ùتح ناÙذة ادارة "
+"المشروع؟"
+
+#: editor/editor_node.cpp
+msgid ""
+"This option is deprecated. Situations where refresh must be forced are now "
+"considered a bug. Please report."
+msgstr ""
#: editor/editor_node.cpp
msgid "Pick a Main Scene"
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to enable addon plugin at: '"
+msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr ""
#: editor/editor_node.cpp
-msgid "' parsing of config failed."
+msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/"
+msgid "Unable to load addon script from path: '%s'."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to load addon script from path: '"
+msgid ""
+"Unable to load addon script from path: '%s' Base type is not EditorPlugin."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Unable to load addon script from path: '%s' Script is not in tool mode."
msgstr ""
#: editor/editor_node.cpp
@@ -1765,7 +1711,7 @@ msgid ""
msgstr ""
#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/scene_tree_dock.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Ugh"
msgstr ""
@@ -1774,18 +1720,20 @@ msgid ""
"Error loading scene, it must be inside the project path. Use 'Import' to "
"open the scene, then save it inside the project path."
msgstr ""
+"خطا ÙÙŠ تحميل المشهد، يجب ان يكون المشهد ÙÙŠ Ù†Ùس المل٠الخاص بالمشروع. يمكنك "
+"استخدام ناÙذة \"الاستيراد\" Ù„Ùتح المشهد٫ ثم احÙظه ÙÙŠ مل٠المشروع."
#: editor/editor_node.cpp
-msgid "Error loading scene."
+msgid "Scene '%s' has broken dependencies:"
msgstr ""
#: editor/editor_node.cpp
-msgid "Scene '%s' has broken dependencies:"
+msgid "Clear Recent Scenes"
msgstr ""
#: editor/editor_node.cpp
msgid "Save Layout"
-msgstr ""
+msgstr "Ø­Ùظ التخطيط"
#: editor/editor_node.cpp
msgid "Delete Layout"
@@ -1816,7 +1764,7 @@ msgstr ""
msgid "Toggle distraction-free mode."
msgstr ""
-#: editor/editor_node.cpp editor/io_plugins/editor_scene_import_plugin.cpp
+#: editor/editor_node.cpp
msgid "Scene"
msgstr ""
@@ -1854,11 +1802,11 @@ msgstr ""
#: editor/editor_node.cpp
msgid "Save Scene"
-msgstr ""
+msgstr "Ø­Ùظ المشهد"
#: editor/editor_node.cpp
msgid "Save all Scenes"
-msgstr ""
+msgstr "Ø­Ùظ جميع المشاهد"
#: editor/editor_node.cpp
msgid "Close Scene"
@@ -2021,7 +1969,7 @@ msgstr ""
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
msgid "Classes"
-msgstr ""
+msgstr "أصناÙ"
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
msgid "Online Docs"
@@ -2035,6 +1983,10 @@ msgstr ""
msgid "Issue Tracker"
msgstr ""
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+msgid "Community"
+msgstr "مجتمع"
+
#: editor/editor_node.cpp
msgid "About"
msgstr ""
@@ -2043,7 +1995,7 @@ msgstr ""
msgid "Play the project."
msgstr ""
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Play"
msgstr ""
@@ -2059,7 +2011,7 @@ msgstr ""
msgid "Stop the scene."
msgstr ""
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Stop"
msgstr ""
@@ -2109,11 +2061,11 @@ msgstr ""
#: editor/editor_node.cpp
msgid "Save the currently edited resource."
-msgstr ""
+msgstr "Ø­Ùظ المورد الذي يتم تعديله حاليا."
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
msgid "Save As.."
-msgstr ""
+msgstr "Ø­Ùظ باسم..."
#: editor/editor_node.cpp
msgid "Go to the previous edited object in history."
@@ -2132,6 +2084,15 @@ msgid "Object properties."
msgstr ""
#: editor/editor_node.cpp
+msgid "Changes may be lost!"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Import"
+msgstr "إستيراد"
+
+#: editor/editor_node.cpp
msgid "FileSystem"
msgstr ""
@@ -2145,15 +2106,7 @@ msgstr ""
#: editor/editor_node.cpp
msgid "Don't Save"
-msgstr ""
-
-#: editor/editor_node.cpp editor/editor_reimport_dialog.cpp
-msgid "Re-Import"
-msgstr ""
-
-#: editor/editor_node.cpp editor/editor_plugin_settings.cpp
-msgid "Update"
-msgstr ""
+msgstr "لا تقم بالحÙظ"
#: editor/editor_node.cpp
msgid "Import Templates From ZIP File"
@@ -2215,11 +2168,28 @@ msgstr ""
msgid "Open the previous Editor"
msgstr ""
+#: editor/editor_plugin.cpp
+msgid "Creating Mesh Previews"
+msgstr ""
+
+#: editor/editor_plugin.cpp
+msgid "Thumbnail.."
+msgstr ""
+
#: editor/editor_plugin_settings.cpp
msgid "Installed Plugins:"
msgstr ""
#: editor/editor_plugin_settings.cpp
+msgid "Update"
+msgstr ""
+
+#: editor/editor_plugin_settings.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Version:"
+msgstr "الاصدار:"
+
+#: editor/editor_plugin_settings.cpp
msgid "Author:"
msgstr ""
@@ -2252,7 +2222,7 @@ msgid "Frame %"
msgstr ""
#: editor/editor_profiler.cpp
-msgid "Fixed Frame %"
+msgid "Physics Frame %"
msgstr ""
#: editor/editor_profiler.cpp editor/script_editor_debugger.cpp
@@ -2271,26 +2241,6 @@ msgstr ""
msgid "Frame #:"
msgstr ""
-#: editor/editor_reimport_dialog.cpp
-msgid "Please wait for scan to complete."
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Current scene must be saved to re-import."
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Save & Re-Import"
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Importing"
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Import Changed Resources"
-msgstr ""
-
#: editor/editor_run_native.cpp
msgid "Select device from the list"
msgstr ""
@@ -2303,7 +2253,7 @@ msgstr ""
#: editor/editor_run_script.cpp
msgid "Write your logic in the _run() method."
-msgstr ""
+msgstr "أكتب منطقك ÙÙŠ الطريقة ()run_"
#: editor/editor_run_script.cpp
msgid "There is an edited scene already."
@@ -2323,7 +2273,7 @@ msgstr ""
#: editor/editor_run_script.cpp
msgid "Did you forget the '_run' method?"
-msgstr ""
+msgstr "هل نسيت الطريقة '_run' ؟"
#: editor/editor_settings.cpp
msgid "Default (Same as Editor)"
@@ -2400,10 +2350,6 @@ msgid "Importing:"
msgstr ""
#: editor/export_template_manager.cpp
-msgid "Loading Export Templates"
-msgstr ""
-
-#: editor/export_template_manager.cpp
msgid "Current Version:"
msgstr ""
@@ -2436,9 +2382,17 @@ msgid "Cannot navigate to '"
msgstr ""
#: editor/filesystem_dock.cpp
+msgid "View items as a grid of thumbnails"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "View items as a list"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
msgid ""
"\n"
-"Status: Needs Re-Import"
+"Status: Import of file failed. Please fix file and reimport manually."
msgstr ""
#: editor/filesystem_dock.cpp
@@ -2448,87 +2402,91 @@ msgid ""
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Same source and destination files, doing nothing."
+msgid "Cannot move/rename resources root."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Target file exists, can't overwrite. Delete first."
+msgid "Cannot move a folder into itself.\n"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Same source and destination paths, doing nothing."
-msgstr ""
+#, fuzzy
+msgid "Error moving:\n"
+msgstr "خطآ ÙÙŠ التحميل:"
#: editor/filesystem_dock.cpp
-msgid "Can't move directories to within themselves."
-msgstr ""
+#, fuzzy
+msgid "Unable to update dependencies:\n"
+msgstr "Ùشل ÙÙŠ تحميل المشهد بسبب وجود ملÙات Ù…Ùقودة يعتمد المشهد عليها:"
#: editor/filesystem_dock.cpp
-msgid "Can't rename deps for:\n"
+msgid "No name provided"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Error moving file:\n"
+msgid "Provided name contains invalid characters"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Error moving dir:\n"
+msgid "No name provided."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Can't operate on '..'"
-msgstr ""
+#, fuzzy
+msgid "Name contains invalid characters."
+msgstr "الأحر٠الصالحة:"
#: editor/filesystem_dock.cpp
-msgid "Pick New Name and Location For:"
+msgid "A file or folder with this name already exists."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "No files selected!"
+msgid "Renaming file:"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Expand all"
+msgid "Renaming folder:"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Collapse all"
+msgid "Expand all"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Show In File Manager"
+msgid "Collapse all"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Instance"
+msgid "Copy Path"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Edit Dependencies.."
+msgid "Rename.."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "View Owners.."
+msgid "Move To.."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Copy Path"
-msgstr ""
+#, fuzzy
+msgid "New Folder.."
+msgstr "أنشئ مجلد"
#: editor/filesystem_dock.cpp
-msgid "Rename or Move.."
+msgid "Show In File Manager"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Move To.."
+msgid "Instance"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Info"
+msgid "Edit Dependencies.."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Re-Import.."
+msgid "View Owners.."
msgstr ""
#: editor/filesystem_dock.cpp
@@ -2561,6 +2519,11 @@ msgstr ""
msgid "Move"
msgstr ""
+#: editor/filesystem_dock.cpp editor/plugins/animation_tree_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Rename"
+msgstr ""
+
#: editor/groups_editor.cpp
msgid "Add to Group"
msgstr ""
@@ -2574,6 +2537,10 @@ msgid "Import as Single Scene"
msgstr ""
#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
msgid "Import with Separate Materials"
msgstr ""
@@ -2586,6 +2553,18 @@ msgid "Import with Separate Objects+Materials"
msgstr ""
#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Materials+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Materials+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
msgid "Import as Multiple Scenes"
msgstr ""
@@ -2594,38 +2573,31 @@ msgid "Import as Multiple Scenes+Materials"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Import Scene"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Importing Scene.."
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Running Custom Script.."
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Couldn't load post-import script:"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Invalid/broken script for post-import (check console):"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Error running post-import script:"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Saving.."
msgstr ""
@@ -2653,579 +2625,54 @@ msgstr ""
msgid "Reimport"
msgstr ""
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "No bit masks to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path is empty."
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must be a complete resource path."
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must exist."
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Save path is empty!"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Import BitMasks"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s):"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Target Path:"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Accept"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Bit Mask"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No source font file!"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No target font resource!"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"Invalid file extension.\n"
-"Please use .font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Can't load/process source font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Couldn't save font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font Size:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Dest Resource:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "The quick brown fox jumps over the lazy dog."
-msgstr "أبجد هوز حطي كلمن صعÙص قرشت ثخذ ضظغ."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Test:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Options:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Font Import"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"This file is already a Godot font file, please supply a BMFont type file "
-"instead."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Failed opening as BMFont file."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error initializing FreeType."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Unknown font format."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error loading font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Invalid font size."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Invalid font custom source."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/plugins/theme_editor_plugin.cpp
-msgid "Font"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "No meshes to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Single Mesh Import"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Source Mesh(es):"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/plugins/mesh_instance_editor_plugin.cpp
-msgid "Mesh"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Surface %d"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "No samples to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Import Audio Samples"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Source Sample(s):"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Audio Sample"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "New Clip"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Animation Options"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Flags"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Bake FPS:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Optimizer"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Linear Error"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angular Error"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angle"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Clips"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Start(s)"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "End(s)"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Loop"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Filters"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source path is empty."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't load post-import script."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Invalid/broken script for post-import."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Error importing scene."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import 3D Scene"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source Scene:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Same as Target Scene"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Shared"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Target Texture Folder:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Post-Process Script:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Custom Root Node Type:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Auto"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Root Node Name:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "The Following Files are Missing:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Anyway"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp scene/gui/dialogs.cpp
-msgid "Cancel"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import & Open"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Edited scene has not been saved, open imported scene anyway?"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Image:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Can't import a file over itself:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't localize path: %s (already local)"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "3D Scene Animation"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Uncompressed"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossless (PNG)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossy (WebP)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress (VRAM)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Format"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Compression Quality (WebP):"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Options"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Please specify some files!"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "At least one file needed for Atlas."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Error importing:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Only one file is required for large texture."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Max Texture Size:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for Atlas (2D)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cell Size:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Large Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Textures (2D)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture"
+#: editor/multi_node_edit.cpp
+msgid "MultiNode Set"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Base Atlas Texture"
+#: editor/node_dock.cpp
+msgid "Groups"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s)"
+#: editor/node_dock.cpp
+msgid "Select a Node to edit Signals and Groups."
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 2D"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create Poly"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 3D"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Insert Point"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "2D Texture"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly (Remove Point)"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "3D Texture"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Remove Poly And Point"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Atlas Texture"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create a new polygon from scratch."
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
+#: editor/plugins/abstract_polygon_2d_editor.cpp
msgid ""
-"NOTICE: Importing 2D textures is not mandatory. Just copy png/jpg files to "
-"the project."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Crop empty space."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Load Source Image"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Slicing"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Inserting"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Saving"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save large texture:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Build Atlas For:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Loading Image:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't load image:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Converting Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cropping Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Blitting Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save atlas image:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save converted texture:"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid source!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid translation source!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Column"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/script_create_dialog.cpp
-msgid "Language"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No items to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No target path!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translations"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Couldn't import!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translation"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Source CSV:"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Ignore First Row"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Compress"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Add to Project (project.godot)"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Languages:"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Translation"
-msgstr ""
-
-#: editor/multi_node_edit.cpp
-msgid "MultiNode Set"
-msgstr ""
-
-#: editor/node_dock.cpp
-msgid "Groups"
-msgstr ""
-
-#: editor/node_dock.cpp
-msgid "Select a Node to edit Signals and Groups."
+"Edit existing polygon:\n"
+"LMB: Move Point.\n"
+"Ctrl+LMB: Split Segment.\n"
+"RMB: Erase Point."
msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
@@ -3309,7 +2756,7 @@ msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Play selected animation backwards from current pos. (A)"
-msgstr ""
+msgstr "تشغيل الحركة المختارة بشكل عكسي من الموقع الحالي. (زر A)"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Play selected animation backwards from end. (Shift+A)"
@@ -3325,7 +2772,7 @@ msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Play selected animation from current pos. (D)"
-msgstr ""
+msgstr "تشغيل الحركة المختارة من الموقع الحالي. (زر D)"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Animation position (in seconds)."
@@ -3381,7 +2828,6 @@ msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
#: editor/script_create_dialog.cpp
msgid "Error!"
@@ -3491,10 +2937,6 @@ msgid "Delete Input"
msgstr ""
#: editor/plugins/animation_tree_editor_plugin.cpp
-msgid "Rename"
-msgstr ""
-
-#: editor/plugins/animation_tree_editor_plugin.cpp
msgid "Animation tree is valid."
msgstr ""
@@ -3550,64 +2992,181 @@ msgstr ""
msgid "Filters.."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing %d Triangles:"
-msgstr ""
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Free"
+msgstr "مجاني/Ùارغ"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Triangle #"
-msgstr ""
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Contents:"
+msgstr "المحتويات:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Light Baker Setup:"
-msgstr ""
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "View Files"
+msgstr "إظهار الملÙات"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing Geometry"
-msgstr ""
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve hostname:"
+msgstr "لا يمكن حل أسم المÙضيÙ:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Fixing Lights"
-msgstr ""
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve."
+msgstr "لا يمكن الحل."
-#: editor/plugins/baked_light_baker.cpp
-msgid "Making BVH"
-msgstr ""
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connection error, please try again."
+msgstr "خطأ ÙÙŠ الإتصال، من Ùضلك حاول مجدداً."
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Light Octree"
-msgstr ""
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't connect."
+msgstr "لا يمكن إتمام الاتصال."
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Octree Texture"
-msgstr ""
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't connect to host:"
+msgstr "لا يمكن الإتصال بالمÙضيÙ:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Transfer to Lightmaps:"
-msgstr ""
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response from host:"
+msgstr "لا ردّ من المÙضيÙ:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Allocating Texture #"
-msgstr ""
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response."
+msgstr "لا يوجد إستجابة."
-#: editor/plugins/baked_light_baker.cpp
-msgid "Baking Triangle #"
-msgstr ""
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, return code:"
+msgstr "Ùشل إتمام الطلب٫ الرمز الذي تم إرجاعه:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Post-Processing Texture #"
-msgstr ""
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Req. Failed."
+msgstr "Ùشل الطلب."
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Bake!"
-msgstr ""
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, too many redirects"
+msgstr "Ùشل الطلب٫ السبب هو اعادة التحويل مرات اكثر من اللازم"
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Reset the lightmap octree baking process (start over)."
-msgstr ""
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Redirect Loop."
+msgstr "اعادة توجيه حلقة التكرار."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed:"
+msgstr "Ùشل:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Bad download hash, assuming file has been tampered with."
+msgstr "تجزئة تحميل سيئة، من المتوقع أن يكون المل٠قد تم العبث به."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Expected:"
+msgstr "ما كان متوقعاً:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Got:"
+msgstr "ما تم الحصول عليه:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed sha256 hash check"
+msgstr "Ùشل التاكد من ترميز sha256"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Asset Download Error:"
+msgstr "خطأ ÙÙŠ تنزيل الأصول:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Fetching:"
+msgstr "يجلب:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Resolving.."
+msgstr "جاري الحل..."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connecting.."
+msgstr "جاري الاتصال..."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Requesting.."
+msgstr "جار الطلب..."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Error making request"
+msgstr "خطأ ÙÙŠ إنشاء الطلب"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Idle"
+msgstr "عاطل"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Retry"
+msgstr "إعادة المحاولة"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download Error"
+msgstr "خطأ ÙÙŠ التحميل"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download for this asset is already in progress!"
+msgstr "تحميل هذه الأصول قيد التنÙيذ أصلاً!"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "first"
+msgstr "الأول"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "prev"
+msgstr "السابق"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "next"
+msgstr "التالي"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "last"
+msgstr "الأخير"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "All"
+msgstr "الكل"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Plugins"
+msgstr "إضاÙات"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Sort:"
+msgstr "ترتيب:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Reverse"
+msgstr "عكس"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Category:"
+msgstr "الÙئة:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Site:"
+msgstr "الموقع:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Support.."
+msgstr "الدعم..."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Official"
+msgstr "رسمياً"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Testing"
+msgstr "تجربة"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Assets ZIP File"
+msgstr "مل٠أصول مضغوط"
#: editor/plugins/camera_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
msgid "Preview"
msgstr ""
@@ -3650,11 +3209,15 @@ msgid "Edit CanvasItem"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Change Anchors"
+msgid "Anchors only"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom (%):"
+msgid "Change Anchors and Margins"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Change Anchors"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3706,59 +3269,72 @@ msgid "Pan Mode"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Lock the selected object in place (can't be moved)."
+msgid "Toggles snapping"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Unlock the selected object (can be moved)."
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Use Snap"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Makes sure the object's children are not selectable."
+msgid "Snapping options"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Restores the object's children's ability to be selected."
+msgid "Snap to grid"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Edit"
+msgid "Use Rotation Snap"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Use Snap"
+msgid "Configure Snap..."
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Show Grid"
+msgid "Snap Relative"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Rotation Snap"
+msgid "Use Pixel Snap"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap Relative"
+msgid "Smart snapping"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Configure Snap.."
+msgid "Snap to parent"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Pixel Snap"
+msgid "Snap to node anchor"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to node sides"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Skeleton.."
+msgid "Snap to other nodes"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Lock the selected object in place (can't be moved)."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Unlock the selected object (can be moved)."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Makes sure the object's children are not selectable."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Restores the object's children's ability to be selected."
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3787,11 +3363,16 @@ msgid "View"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Reset"
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Show Grid"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Show helpers"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Set.."
+msgid "Show rulers"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3803,8 +3384,9 @@ msgid "Frame Selection"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Anchor"
-msgstr ""
+#, fuzzy
+msgid "Layout"
+msgstr "Ø­Ùظ التخطيط"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Insert Keys"
@@ -3827,11 +3409,20 @@ msgid "Clear Pose"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Set a Value"
+msgid "Drag pivot from mouse position"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#, fuzzy
+msgid "Set pivot at mouse position"
+msgstr "عملية تحريك"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Multiply grid step by 2"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap (Pixels):"
+msgid "Divide grid step by 2"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3842,23 +3433,28 @@ msgstr ""
msgid "Adding %s..."
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Create Node"
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Error instancing scene from %s"
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "OK :("
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "No parent to instance a child at."
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "This operation requires a single selected node."
msgstr ""
@@ -3872,45 +3468,6 @@ msgid ""
"Drag & drop + Alt : Change node type"
msgstr ""
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Create Poly"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly (Remove Point)"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Create a new polygon from scratch."
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-msgid ""
-"Edit existing polygon:\n"
-"LMB: Move Point.\n"
-"Ctrl+LMB: Split Segment.\n"
-"RMB: Erase Point."
-msgstr ""
-
#: editor/plugins/collision_polygon_editor_plugin.cpp
msgid "Create Poly3D"
msgstr ""
@@ -3920,14 +3477,6 @@ msgid "Set Handle"
msgstr ""
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Creating Mesh Library"
-msgstr ""
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Thumbnail.."
-msgstr ""
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Remove item %d?"
msgstr ""
@@ -3950,6 +3499,26 @@ msgid "Update from Scene"
msgstr ""
#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat0"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat1"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Ease in"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Ease out"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Smoothstep"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
msgid "Modify Curve Point"
msgstr ""
@@ -4027,22 +3596,18 @@ msgid "Create Occluder Polygon"
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Edit existing polygon:"
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "LMB: Move Point."
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Ctrl+LMB: Split Segment."
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "RMB: Erase Point."
msgstr ""
@@ -4143,6 +3708,10 @@ msgid "Create Outline"
msgstr ""
#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Mesh"
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Create Trimesh Static Body"
msgstr ""
@@ -4270,12 +3839,73 @@ msgstr ""
msgid "Populate"
msgstr ""
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Create Navigation Polygon"
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake!"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake the navigation mesh.\n"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Clear the navigation mesh."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Setting up Configuration..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Calculating grid size..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating heightfield..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Marking walkable triangles..."
+msgstr "جاري تخزين التعديلات المحلية.."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Constructing compact heightfield..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Eroding walkable area..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Partitioning..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating contours..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating polymesh..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Converting to native navigation mesh..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Navigation Mesh Generator Setup:"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Parsing Geometry..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Done!"
msgstr ""
#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Remove Poly And Point"
+msgid "Create Navigation Polygon"
msgstr ""
#: editor/plugins/particles_2d_editor_plugin.cpp
@@ -4449,16 +4079,19 @@ msgid "Curve Point #"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve Point Position"
-msgstr ""
+msgstr "عملية تحريك"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve In Position"
-msgstr ""
+msgstr "عملية تحريك"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve Out Position"
-msgstr ""
+msgstr "عملية تحريك"
#: editor/plugins/path_editor_plugin.cpp
msgid "Split Path"
@@ -4518,6 +4151,14 @@ msgid "Scale Polygon"
msgstr ""
#: editor/plugins/polygon_2d_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Edit"
+msgstr ""
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Polygon->UV"
msgstr ""
@@ -4572,63 +4213,10 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/shader_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr ""
-#: editor/plugins/rich_text_editor_plugin.cpp
-msgid "Parse BBCode"
-msgstr ""
-
-#: editor/plugins/sample_editor_plugin.cpp
-msgid "Length:"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Open Sample File(s)"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "ERROR: Couldn't load sample!"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Add Sample"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Rename Sample"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Delete Sample"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "16 Bits"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "8 Bits"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Stereo"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Mono"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Format"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Pitch"
-msgstr ""
-
#: editor/plugins/script_editor_plugin.cpp
msgid "Clear Recent Files"
msgstr ""
@@ -4665,7 +4253,7 @@ msgstr ""
#: editor/plugins/script_editor_plugin.cpp
msgid " Class Reference"
-msgstr ""
+msgstr " مرجع الصنÙ"
#: editor/plugins/script_editor_plugin.cpp
msgid "Next script"
@@ -4719,6 +4307,10 @@ msgstr ""
msgid "Close All"
msgstr ""
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+msgid "Run"
+msgstr ""
+
#: editor/plugins/script_editor_plugin.cpp
msgid "Toggle Scripts Panel"
msgstr ""
@@ -4747,7 +4339,8 @@ msgstr ""
msgid "Break"
msgstr ""
-#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+#: editor/script_editor_debugger.cpp
msgid "Continue"
msgstr ""
@@ -4760,24 +4353,12 @@ msgid "Debug with external editor"
msgstr ""
#: editor/plugins/script_editor_plugin.cpp
-msgid "Window"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Left"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Right"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
msgid "Open Godot online documentation"
msgstr ""
#: editor/plugins/script_editor_plugin.cpp
msgid "Search the class hierarchy."
-msgstr ""
+msgstr "إبحث ÙÙŠ هرمية الأصناÙ."
#: editor/plugins/script_editor_plugin.cpp
msgid "Search the reference documentation."
@@ -4853,8 +4434,9 @@ msgid "Cut"
msgstr ""
#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr ""
@@ -5117,10 +4699,6 @@ msgid "View Plane Transform."
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Scaling to %s%%."
-msgstr ""
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rotating %s degrees."
msgstr ""
@@ -5137,10 +4715,6 @@ msgid "Top View."
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Top"
-msgstr ""
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rear View."
msgstr ""
@@ -5368,6 +4942,10 @@ msgid "Transform"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Configure Snap.."
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Local Coords"
msgstr ""
@@ -5513,6 +5091,10 @@ msgid "Speed (FPS):"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Loop"
+msgstr ""
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Animation Frames"
msgstr ""
@@ -5525,12 +5107,14 @@ msgid "Insert Empty (After)"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Up"
-msgstr ""
+#, fuzzy
+msgid "Move (Before)"
+msgstr "عملية تحريك"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Down"
-msgstr ""
+#, fuzzy
+msgid "Move (After)"
+msgstr "عملية تحريك"
#: editor/plugins/style_box_editor_plugin.cpp
msgid "StyleBox Preview:"
@@ -5607,16 +5191,20 @@ msgid "Remove All"
msgstr "عملية تحريك"
#: editor/plugins/theme_editor_plugin.cpp
-msgid "Theme"
+msgid "Edit theme.."
msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
-msgid "Add Class Items"
+msgid "Theme editing menu."
msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
+msgid "Add Class Items"
+msgstr "إضاÙØ© بنود للصنÙ"
+
+#: editor/plugins/theme_editor_plugin.cpp
msgid "Remove Class Items"
-msgstr ""
+msgstr "حذ٠بنود من الصنÙ"
#: editor/plugins/theme_editor_plugin.cpp
msgid "Create Empty Template"
@@ -5692,6 +5280,10 @@ msgid "Style"
msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
+msgid "Font"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
msgid "Color"
msgstr ""
@@ -5740,7 +5332,7 @@ msgid "Mirror Y"
msgstr ""
#: editor/plugins/tile_map_editor_plugin.cpp
-msgid "Bucket"
+msgid "Paint Tile"
msgstr ""
#: editor/plugins/tile_map_editor_plugin.cpp
@@ -5804,6 +5396,10 @@ msgid "Delete preset '%s'?"
msgstr ""
#: editor/project_export.cpp
+msgid "Export templates for this platform are missing/corrupted: "
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Presets"
msgstr ""
@@ -5874,19 +5470,30 @@ msgid "Export templates for this platform are missing:"
msgstr ""
#: editor/project_export.cpp
+msgid "Export templates for this platform are missing/corrupted:"
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Export With Debug"
msgstr ""
#: editor/project_manager.cpp
-msgid "Invalid project path, the path must exist!"
+#, fuzzy
+msgid "The path does not exist."
+msgstr "المل٠غير موجود."
+
+#: editor/project_manager.cpp
+msgid "Please choose a 'project.godot' file."
msgstr ""
#: editor/project_manager.cpp
-msgid "Invalid project path, project.godot must not exist."
+msgid ""
+"Your project will be created in a non empty folder (you might want to create "
+"a new folder)."
msgstr ""
#: editor/project_manager.cpp
-msgid "Invalid project path, project.godot must exist."
+msgid "Please choose a folder that does not contain a 'project.godot' file."
msgstr ""
#: editor/project_manager.cpp
@@ -5894,10 +5501,26 @@ msgid "Imported Project"
msgstr ""
#: editor/project_manager.cpp
+msgid " "
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "It would be a good idea to name your project."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Invalid project path (changed anything?)."
msgstr ""
#: editor/project_manager.cpp
+msgid "Couldn't get project.godot in project path."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Couldn't edit project.godot in project path."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
msgstr ""
@@ -5906,23 +5529,23 @@ msgid "The following files failed extraction from package:"
msgstr ""
#: editor/project_manager.cpp
-msgid "Import Existing Project"
+msgid "Rename Project"
msgstr ""
#: editor/project_manager.cpp
-msgid "Project Path (Must Exist):"
+msgid "Couldn't get project.godot in the project path."
msgstr ""
#: editor/project_manager.cpp
-msgid "Project Name:"
+msgid "New Game Project"
msgstr ""
#: editor/project_manager.cpp
-msgid "Create New Project"
+msgid "Import Existing Project"
msgstr ""
#: editor/project_manager.cpp
-msgid "Project Path:"
+msgid "Create New Project"
msgstr ""
#: editor/project_manager.cpp
@@ -5930,11 +5553,20 @@ msgid "Install Project:"
msgstr ""
#: editor/project_manager.cpp
-msgid "Browse"
+msgid "Project Name:"
msgstr ""
#: editor/project_manager.cpp
-msgid "New Game Project"
+#, fuzzy
+msgid "Create folder"
+msgstr "أنشئ مجلد"
+
+#: editor/project_manager.cpp
+msgid "Project Path:"
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Browse"
msgstr ""
#: editor/project_manager.cpp
@@ -5946,6 +5578,11 @@ msgid "Unnamed Project"
msgstr ""
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Can't open project"
+msgstr "لا يمكن إتمام الاتصال."
+
+#: editor/project_manager.cpp
msgid "Are you sure to open more than one project?"
msgstr ""
@@ -5972,16 +5609,18 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
-"You are about the scan %s folders for existing Godot projects. Do you "
-"confirm?"
+"Language changed.\n"
+"The UI will update next time the editor or project manager starts."
msgstr ""
#: editor/project_manager.cpp
-msgid "Project List"
+msgid ""
+"You are about the scan %s folders for existing Godot projects. Do you "
+"confirm?"
msgstr ""
#: editor/project_manager.cpp
-msgid "Run"
+msgid "Project List"
msgstr ""
#: editor/project_manager.cpp
@@ -6005,6 +5644,10 @@ msgid "Exit"
msgstr ""
#: editor/project_manager.cpp
+msgid "Restart Now"
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Can't run project"
msgstr ""
@@ -6041,17 +5684,14 @@ msgid "Add Input Action Event"
msgstr ""
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Meta+"
msgstr ""
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Shift+"
msgstr ""
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Alt+"
msgstr ""
@@ -6112,7 +5752,7 @@ msgstr ""
msgid "Joypad Axis Index:"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Axis"
msgstr ""
@@ -6132,31 +5772,31 @@ msgstr ""
msgid "Add Event"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Device"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Button"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Left Button."
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Right Button."
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Middle Button."
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Up."
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Down."
msgstr ""
@@ -6165,7 +5805,7 @@ msgid "Add Global Property"
msgstr ""
#: editor/project_settings_editor.cpp
-msgid "Select an setting item first!"
+msgid "Select a setting item first!"
msgstr ""
#: editor/project_settings_editor.cpp
@@ -6181,6 +5821,15 @@ msgid "Delete Item"
msgstr ""
#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Can't contain '/' or ':'"
+msgstr "لا يمكن الإتصال بالمÙضيÙ:"
+
+#: editor/project_settings_editor.cpp
+msgid "Already existing"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "Error saving settings."
msgstr ""
@@ -6221,6 +5870,14 @@ msgid "Remove Resource Remap Option"
msgstr ""
#: editor/project_settings_editor.cpp
+msgid "Changed Locale Filter"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Changed Locale Filter Mode"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "Project Settings (project.godot)"
msgstr ""
@@ -6281,6 +5938,27 @@ msgid "Locale"
msgstr ""
#: editor/project_settings_editor.cpp
+msgid "Locales Filter"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Show all locales"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Show only selected locales"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Filter mode:"
+msgstr "المÙصÙÙŠ:"
+
+#: editor/project_settings_editor.cpp
+msgid "Locales:"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "AutoLoad"
msgstr ""
@@ -6329,10 +6007,20 @@ msgid "New Script"
msgstr ""
#: editor/property_editor.cpp
+#, fuzzy
+msgid "Make Unique"
+msgstr "إجعل الموارد الجانبية مميزة"
+
+#: editor/property_editor.cpp
msgid "Show in File System"
msgstr ""
#: editor/property_editor.cpp
+#, fuzzy
+msgid "Convert To %s"
+msgstr "صلها بالعقدة:"
+
+#: editor/property_editor.cpp
msgid "Error loading file: Not a resource!"
msgstr ""
@@ -6369,8 +6057,12 @@ msgid "Select Property"
msgstr ""
#: editor/property_selector.cpp
+msgid "Select Virtual Method"
+msgstr "إختر طريقة Ø¥Ùتراضية"
+
+#: editor/property_selector.cpp
msgid "Select Method"
-msgstr ""
+msgstr "إختر طريقة"
#: editor/pvrtc_compress.cpp
msgid "Could not execute PVRTC tool:"
@@ -6396,26 +6088,6 @@ msgstr ""
msgid "Reparent"
msgstr ""
-#: editor/resources_dock.cpp
-msgid "Create New Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Open Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Save Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Resource Tools"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Make Local"
-msgstr ""
-
#: editor/run_settings_dialog.cpp
msgid "Run Mode:"
msgstr ""
@@ -6542,14 +6214,6 @@ msgid "Sub-Resources:"
msgstr ""
#: editor/scene_tree_dock.cpp
-msgid "Edit Groups"
-msgstr ""
-
-#: editor/scene_tree_dock.cpp
-msgid "Edit Connections"
-msgstr ""
-
-#: editor/scene_tree_dock.cpp
msgid "Clear Inheritance"
msgstr ""
@@ -6732,6 +6396,15 @@ msgid "Invalid base path"
msgstr ""
#: editor/script_create_dialog.cpp
+msgid "Directory of the same name exists"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
+#, fuzzy
+msgid "File exists, will be reused"
+msgstr "المل٠موجود، إستبدال؟"
+
+#: editor/script_create_dialog.cpp
msgid "Invalid extension"
msgstr ""
@@ -6745,7 +6418,7 @@ msgstr ""
#: editor/script_create_dialog.cpp
msgid "Invalid class name"
-msgstr ""
+msgstr "إسم صن٠غير صالح"
#: editor/script_create_dialog.cpp
msgid "Invalid inherited parent name or path"
@@ -6773,12 +6446,16 @@ msgid "Load existing script file"
msgstr ""
#: editor/script_create_dialog.cpp
+msgid "Language"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
msgid "Inherits"
msgstr ""
#: editor/script_create_dialog.cpp
msgid "Class Name"
-msgstr ""
+msgstr "إسم صنÙ"
#: editor/script_create_dialog.cpp
msgid "Template"
@@ -6813,6 +6490,10 @@ msgid "Function:"
msgstr ""
#: editor/script_editor_debugger.cpp
+msgid "Pick one or more items from the list to display the graph."
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
msgid "Errors"
msgstr ""
@@ -6893,6 +6574,10 @@ msgid "Type"
msgstr ""
#: editor/script_editor_debugger.cpp
+msgid "Format"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
msgid "Usage"
msgstr ""
@@ -6968,6 +6653,22 @@ msgstr ""
msgid "Change Probe Extents"
msgstr ""
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Library"
+msgstr ""
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Status"
+msgstr ""
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Libraries: "
+msgstr ""
+
+#: modules/gdnative/register_types.cpp
+msgid "GDNative"
+msgstr ""
+
#: modules/gdscript/gd_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
#, fuzzy
@@ -6976,7 +6677,7 @@ msgstr ""
"صن٠إحدى المتغيرات المدخلة (arguments) غير صحيح ÙÙŠ ()convert . إستعمل ثابتة "
"_*TYPE"
-#: modules/gdscript/gd_functions.cpp
+#: modules/gdscript/gd_functions.cpp modules/mono/glue/glue_header.h
#: modules/visual_script/visual_script_builtin_funcs.cpp
#, fuzzy
msgid "Not enough bytes for decoding bytes, or invalid format."
@@ -7020,9 +6721,7 @@ msgstr ""
#: modules/gdscript/gd_functions.cpp
msgid "Invalid instance dictionary (invalid subclasses)"
-msgstr ""
-"instance dictionary نموذج القاموس غير صالح - subclasses الÙئة الÙرعية غير "
-"صالحة"
+msgstr "مجسّد القاموس غير صالح (أصنا٠Ùرعية غير صالحة)"
#: modules/gdscript/gd_functions.cpp
msgid "Object can't provide a length."
@@ -7037,10 +6736,6 @@ msgid "GridMap Duplicate Selection"
msgstr ""
#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "GridMap Paint"
-msgstr ""
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Snap View"
msgstr ""
@@ -7132,12 +6827,8 @@ msgstr ""
msgid "Pick Distance:"
msgstr ""
-#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "Tiles"
-msgstr ""
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "Areas"
+#: modules/mono/editor/mono_bottom_panel.cpp
+msgid "Builds"
msgstr ""
#: modules/visual_script/visual_script.cpp
@@ -7328,10 +7019,18 @@ msgid "Return"
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
+msgid "Call"
+msgstr "نداء"
+
+#: modules/visual_script/visual_script_editor.cpp
msgid "Get"
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
+msgid "Script already has function '%s'"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
msgid "Change Input Value"
msgstr ""
@@ -7462,7 +7161,7 @@ msgstr ""
#: modules/visual_script/visual_script_nodes.cpp
msgid "Custom node has no _step() method, can't process graph."
-msgstr ""
+msgstr "العقدة المخصصة لا تحتوي طريقة ()step_ ، لا يمكن معالجة المخطوط."
#: modules/visual_script/visual_script_nodes.cpp
msgid ""
@@ -7472,23 +7171,23 @@ msgstr ""
#: platform/javascript/export/export.cpp
msgid "Run in Browser"
-msgstr ""
+msgstr "تشغيل ÙÙŠ المتصÙØ­"
#: platform/javascript/export/export.cpp
msgid "Run exported HTML in the system's default browser."
-msgstr ""
+msgstr "شغل مل٠HTML المÙصدر ÙÙŠ المتصÙØ­ الإÙتراضي للنظام."
#: platform/javascript/export/export.cpp
msgid "Could not write file:\n"
-msgstr ""
+msgstr "لا يمكن كتابة الملÙ:\n"
#: platform/javascript/export/export.cpp
msgid "Could not read file:\n"
-msgstr ""
+msgstr "لا يمكن قرأة الملÙ:\n"
#: platform/javascript/export/export.cpp
msgid "Could not open template for export:\n"
-msgstr ""
+msgstr "لا يمكن Ùتح القالب من أجل التصدير.\n"
#: scene/2d/animated_sprite.cpp
msgid ""
@@ -7690,6 +7389,12 @@ msgid ""
"order for AnimatedSprite3D to display frames."
msgstr ""
+#: scene/3d/vehicle_body.cpp
+msgid ""
+"VehicleWheel serves to provide a wheel system to a VehicleBody. Please use "
+"it as a child of a VehicleBody."
+msgstr ""
+
#: scene/gui/color_picker.cpp
msgid "Raw Mode"
msgstr ""
@@ -7699,16 +7404,16 @@ msgid "Add current color as a preset"
msgstr ""
#: scene/gui/dialogs.cpp
-msgid "Alert!"
+msgid "Cancel"
msgstr ""
#: scene/gui/dialogs.cpp
-msgid "Please Confirm..."
-msgstr ""
+msgid "Alert!"
+msgstr "تنبيه!"
-#: scene/gui/input_action.cpp
-msgid "Ctrl+"
-msgstr ""
+#: scene/gui/dialogs.cpp
+msgid "Please Confirm..."
+msgstr "يرجى التاكيد..."
#: scene/gui/popup.cpp
msgid ""
@@ -7738,5 +7443,51 @@ msgid ""
"texture to some node for display."
msgstr ""
+#: scene/resources/dynamic_font.cpp
+msgid "Error initializing FreeType."
+msgstr ""
+
+#: scene/resources/dynamic_font.cpp
+msgid "Unknown font format."
+msgstr ""
+
+#: scene/resources/dynamic_font.cpp
+msgid "Error loading font."
+msgstr ""
+
+#: scene/resources/dynamic_font.cpp
+msgid "Invalid font size."
+msgstr ""
+
+#~ msgid "Method List For '%s':"
+#~ msgstr "قائمة الطرق لـ '%s':"
+
+#~ msgid "Arguments:"
+#~ msgstr "البراهين:"
+
+#~ msgid "Return:"
+#~ msgstr "العودة:"
+
+#~ msgid "Added:"
+#~ msgstr "تم إضاÙته:"
+
+#~ msgid "Removed:"
+#~ msgstr "Ù…ÙسÙØ­:"
+
+#~ msgid "Error saving atlas:"
+#~ msgstr "خطأ ÙÙŠ Ø­Ùظ الأطلس:"
+
+#~ msgid "Could not save atlas subtexture:"
+#~ msgstr "لا يمكن Ø­Ùظ النسيج الÙرعي للأطلس:"
+
+#~ msgid "Exporting for %s"
+#~ msgstr "التصدير كـ %s"
+
+#~ msgid "Setting Up.."
+#~ msgstr "جاري الإعداد.."
+
+#~ msgid "The quick brown fox jumps over the lazy dog."
+#~ msgstr "أبجد هوز حطي كلمن صعÙص قرشت ثخذ ضظغ."
+
#~ msgid "Samples"
#~ msgstr "عينات (صوتية)"
diff --git a/editor/translations/bg.po b/editor/translations/bg.po
index 4e119a5fad..21e2b4f27d 100644
--- a/editor/translations/bg.po
+++ b/editor/translations/bg.po
@@ -1,5 +1,6 @@
# Bulgarian translation of the Godot Engine editor
-# Copyright (C) 2016-2017 Juan Linietsky, Ariel Manzur and the Godot community
+# Copyright (C) 2007-2017 Juan Linietsky, Ariel Manzur
+# Copyright (C) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)
# This file is distributed under the same license as the Godot source code.
#
# Bojidar Marinov <bojidar.marinov.bg@gmail.com>, 2016.
@@ -192,10 +193,9 @@ msgid "Create %d NEW tracks and insert keys?"
msgstr ""
#: editor/animation_editor.cpp editor/create_dialog.cpp
-#: editor/editor_audio_buses.cpp
+#: editor/editor_audio_buses.cpp editor/plugins/abstract_polygon_2d_editor.cpp
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
#: editor/plugins/mesh_instance_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp editor/project_manager.cpp
#: editor/script_create_dialog.cpp
msgid "Create"
@@ -357,262 +357,6 @@ msgstr ""
msgid "Change Array Value"
msgstr ""
-#: editor/asset_library_editor_plugin.cpp
-msgid "Free"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_plugin_settings.cpp
-msgid "Version:"
-msgstr "ВерÑиÑ:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Contents:"
-msgstr "Съдържание:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "View Files"
-msgstr "Преглед на файловете"
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_help.cpp editor/property_selector.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Description:"
-msgstr "ОпиÑание:"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-#: editor/project_manager.cpp
-msgid "Install"
-msgstr "ИнÑталиране"
-
-#: editor/asset_library_editor_plugin.cpp editor/call_dialog.cpp
-#: editor/connections_dialog.cpp editor/export_template_manager.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-#: editor/project_settings_editor.cpp editor/property_editor.cpp
-#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Close"
-msgstr "ЗатварÑне"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve hostname:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Connection error, please try again."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't connect."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't connect to host:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response from host:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Request failed, return code:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Req. Failed."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Request failed, too many redirects"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Redirect Loop."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Bad download hash, assuming file has been tampered with."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Expected:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Got:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Asset Download Error:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-msgid "Success!"
-msgstr "Готово!"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Fetching:"
-msgstr "ИзтеглÑне:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Resolving.."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Connecting.."
-msgstr "Свързване.."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Requesting.."
-msgstr "Запитване.."
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Error making request"
-msgstr "Имаше грешка при зареждане на Ñцената."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Idle"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Retry"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Download Error"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Download for this asset is already in progress!"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "first"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "prev"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "next"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "last"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "All"
-msgstr "Ð’Ñички"
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
-#: editor/settings_config_dialog.cpp
-msgid "Search:"
-msgstr "ТърÑене:"
-
-#: editor/asset_library_editor_plugin.cpp editor/code_editor.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Search"
-msgstr "ТърÑене"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/project_manager.cpp
-msgid "Import"
-msgstr "ВнаÑÑне"
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Plugins"
-msgstr "ПриÑтавки"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Sort:"
-msgstr "Подреждане:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Reverse"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Category:"
-msgstr "КатегориÑ:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Site:"
-msgstr "ÐœÑÑто:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Support.."
-msgstr "Поддръжка"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Official"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-msgid "Community"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Testing"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Assets ZIP File"
-msgstr ""
-
-#: editor/call_dialog.cpp
-msgid "Method List For '%s':"
-msgstr ""
-
-#: editor/call_dialog.cpp modules/visual_script/visual_script_editor.cpp
-msgid "Call"
-msgstr ""
-
-#: editor/call_dialog.cpp
-msgid "Method List:"
-msgstr ""
-
-#: editor/call_dialog.cpp
-msgid "Arguments:"
-msgstr ""
-
-#: editor/call_dialog.cpp
-msgid "Return:"
-msgstr ""
-
#: editor/code_editor.cpp
msgid "Go to Line"
msgstr ""
@@ -649,6 +393,14 @@ msgstr ""
msgid "Selection Only"
msgstr ""
+#: editor/code_editor.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
+msgid "Search"
+msgstr "ТърÑене"
+
#: editor/code_editor.cpp editor/editor_help.cpp
msgid "Find"
msgstr ""
@@ -681,11 +433,11 @@ msgstr ""
msgid "Skip"
msgstr ""
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom In"
msgstr ""
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom Out"
msgstr ""
@@ -752,6 +504,20 @@ msgstr ""
msgid "Oneshot"
msgstr ""
+#: editor/connections_dialog.cpp editor/dependency_editor.cpp
+#: editor/export_template_manager.cpp
+#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Close"
+msgstr "ЗатварÑне"
+
#: editor/connections_dialog.cpp
msgid "Connect"
msgstr ""
@@ -777,7 +543,7 @@ msgstr ""
msgid "Disconnect"
msgstr ""
-#: editor/connections_dialog.cpp editor/node_dock.cpp
+#: editor/connections_dialog.cpp editor/editor_help.cpp editor/node_dock.cpp
msgid "Signals"
msgstr ""
@@ -794,12 +560,25 @@ msgstr "Любими:"
msgid "Recent:"
msgstr ""
+#: editor/create_dialog.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/quick_open.cpp editor/settings_config_dialog.cpp
+msgid "Search:"
+msgstr "ТърÑене:"
+
#: editor/create_dialog.cpp editor/editor_help.cpp
#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/quick_open.cpp
msgid "Matches:"
msgstr ""
+#: editor/create_dialog.cpp editor/editor_help.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/property_selector.cpp
+#: editor/script_editor_debugger.cpp
+msgid "Description:"
+msgstr "ОпиÑание:"
+
#: editor/dependency_editor.cpp
msgid "Search Replacement For:"
msgstr ""
@@ -855,6 +634,10 @@ msgid "Owners Of:"
msgstr ""
#: editor/dependency_editor.cpp
+msgid "Remove selected files from the project? (no undo)"
+msgstr ""
+
+#: editor/dependency_editor.cpp
msgid ""
"The files being removed are required by other resources in order for them to "
"work.\n"
@@ -862,7 +645,7 @@ msgid ""
msgstr ""
#: editor/dependency_editor.cpp
-msgid "Remove selected files from the project? (no undo)"
+msgid "Cannot remove:\n"
msgstr ""
#: editor/dependency_editor.cpp
@@ -929,10 +712,6 @@ msgid "Godot Engine contributors"
msgstr ""
#: editor/editor_about.cpp
-msgid "Authors"
-msgstr ""
-
-#: editor/editor_about.cpp
#, fuzzy
msgid "Project Founders"
msgstr "ДиÑпечер на проектите"
@@ -950,6 +729,38 @@ msgid "Developers"
msgstr ""
#: editor/editor_about.cpp
+msgid "Authors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Platinum Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Gold Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Mini Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Gold Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Silver Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Bronze Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
msgid "License"
msgstr ""
@@ -993,6 +804,16 @@ msgid "Package Installed Successfully!"
msgstr ""
#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Success!"
+msgstr "Готово!"
+
+#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/project_manager.cpp
+msgid "Install"
+msgstr "ИнÑталиране"
+
+#: editor/editor_asset_installer.cpp
msgid "Package Installer"
msgstr ""
@@ -1041,11 +862,6 @@ msgid "Audio Bus, Drag and Drop to rearrange."
msgstr ""
#: editor/editor_audio_buses.cpp
-#, fuzzy
-msgid "Bus options"
-msgstr "ÐаÑтройки за отÑтранÑване на грешки"
-
-#: editor/editor_audio_buses.cpp
msgid "Solo"
msgstr ""
@@ -1057,12 +873,21 @@ msgstr ""
msgid "Bypass"
msgstr ""
+#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Bus options"
+msgstr "ÐаÑтройки за отÑтранÑване на грешки"
+
#: editor/editor_audio_buses.cpp editor/plugins/tile_map_editor_plugin.cpp
#: editor/scene_tree_dock.cpp
msgid "Duplicate"
msgstr ""
#: editor/editor_audio_buses.cpp
+msgid "Reset Volume"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
msgid "Delete Effect"
msgstr ""
@@ -1084,6 +909,10 @@ msgid "Duplicate Audio Bus"
msgstr ""
#: editor/editor_audio_buses.cpp
+msgid "Reset Bus Volume"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
msgid "Move Audio Bus"
msgstr ""
@@ -1115,7 +944,8 @@ msgstr ""
msgid "Create a new Bus Layout."
msgstr ""
-#: editor/editor_audio_buses.cpp editor/script_create_dialog.cpp
+#: editor/editor_audio_buses.cpp editor/property_editor.cpp
+#: editor/script_create_dialog.cpp
msgid "Load"
msgstr ""
@@ -1206,7 +1036,7 @@ msgid "Rearrange Autoloads"
msgstr ""
#: editor/editor_autoload_settings.cpp editor/editor_file_dialog.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp scene/gui/file_dialog.cpp
+#: scene/gui/file_dialog.cpp
msgid "Path:"
msgstr "Път:"
@@ -1214,9 +1044,7 @@ msgstr "Път:"
msgid "Node Name:"
msgstr ""
-#: editor/editor_autoload_settings.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp editor/project_manager.cpp
+#: editor/editor_autoload_settings.cpp editor/project_manager.cpp
msgid "Name"
msgstr ""
@@ -1250,18 +1078,19 @@ msgid "Choose a Directory"
msgstr ""
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Create Folder"
msgstr "Създаване на папка"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: editor/editor_plugin_settings.cpp editor/plugins/theme_editor_plugin.cpp
-#: editor/project_export.cpp scene/gui/file_dialog.cpp
+#: editor/editor_plugin_settings.cpp editor/filesystem_dock.cpp
+#: editor/plugins/theme_editor_plugin.cpp editor/project_export.cpp
+#: scene/gui/file_dialog.cpp
msgid "Name:"
msgstr "Име:"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Could not create folder."
msgstr "ÐеуÑпешно Ñъздаване на папка."
@@ -1281,30 +1110,6 @@ msgstr ""
msgid "Template file not found:\n"
msgstr ""
-#: editor/editor_export.cpp
-msgid "Added:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Removed:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Error saving atlas:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Could not save atlas subtexture:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Exporting for %s"
-msgstr "ИзнаÑÑне за %s"
-
-#: editor/editor_export.cpp
-msgid "Setting Up.."
-msgstr ""
-
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "File Exists, Overwrite?"
msgstr "Файлът ÑъщеÑтвува. ИÑкате ли да го презапишете?"
@@ -1389,6 +1194,11 @@ msgstr ""
msgid "Move Favorite Down"
msgstr ""
+#: editor/editor_file_dialog.cpp
+#, fuzzy
+msgid "Go to parent folder"
+msgstr "ÐеуÑпешно Ñъздаване на папка."
+
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Directories & Files:"
msgstr "Папки и файлове:"
@@ -1403,10 +1213,6 @@ msgid "File:"
msgstr "Файл:"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
-msgid "Filter:"
-msgstr ""
-
-#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Must use a valid extension."
msgstr "ТрÑбва да Ñе използва правилно разширение."
@@ -1431,6 +1237,10 @@ msgstr ""
msgid "Search Classes"
msgstr ""
+#: editor/editor_help.cpp editor/plugins/spatial_editor_plugin.cpp
+msgid "Top"
+msgstr ""
+
#: editor/editor_help.cpp editor/property_editor.cpp
msgid "Class:"
msgstr ""
@@ -1447,15 +1257,28 @@ msgstr ""
msgid "Brief Description:"
msgstr ""
+#: editor/editor_help.cpp
+msgid "Members"
+msgstr ""
+
#: editor/editor_help.cpp modules/visual_script/visual_script_editor.cpp
msgid "Members:"
msgstr ""
#: editor/editor_help.cpp
+#, fuzzy
+msgid "Public Methods"
+msgstr "Изберете метод"
+
+#: editor/editor_help.cpp
msgid "Public Methods:"
msgstr ""
#: editor/editor_help.cpp
+msgid "GUI Theme Items"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "GUI Theme Items:"
msgstr ""
@@ -1464,6 +1287,11 @@ msgid "Signals:"
msgstr ""
#: editor/editor_help.cpp
+#, fuzzy
+msgid "Enumerations"
+msgstr "Преходи"
+
+#: editor/editor_help.cpp
msgid "Enumerations:"
msgstr ""
@@ -1472,18 +1300,49 @@ msgid "enum "
msgstr ""
#: editor/editor_help.cpp
+#, fuzzy
+msgid "Constants"
+msgstr "ПоÑтоÑнно"
+
+#: editor/editor_help.cpp
msgid "Constants:"
msgstr ""
#: editor/editor_help.cpp
+#, fuzzy
+msgid "Description"
+msgstr "ОпиÑание:"
+
+#: editor/editor_help.cpp
+msgid "Properties"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Property Description:"
msgstr ""
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this property. Please help us by "
+"[color=$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+
+#: editor/editor_help.cpp
+#, fuzzy
+msgid "Methods"
+msgstr "Изберете метод"
+
+#: editor/editor_help.cpp
msgid "Method Description:"
msgstr ""
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this method. Please help us by [color="
+"$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Search Text"
msgstr ""
@@ -1492,24 +1351,21 @@ msgid "Output:"
msgstr ""
#: editor/editor_log.cpp editor/plugins/animation_tree_editor_plugin.cpp
-#: editor/plugins/rich_text_editor_plugin.cpp editor/property_editor.cpp
-#: editor/script_editor_debugger.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/property_editor.cpp editor/script_editor_debugger.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Clear"
msgstr "ИзчиÑтване"
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Error saving resource!"
msgstr ""
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Save Resource As.."
msgstr ""
-#: editor/editor_node.cpp editor/export_template_manager.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "I see.."
msgstr ""
@@ -1526,6 +1382,29 @@ msgid "Error while saving."
msgstr ""
#: editor/editor_node.cpp
+msgid "Can't open '%s'."
+msgstr ""
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Error while parsing '%s'."
+msgstr "Имаше грешка при внаÑÑнето на Ñцената."
+
+#: editor/editor_node.cpp
+msgid "Unexpected end of file '%s'."
+msgstr ""
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Missing '%s' or its dependencies."
+msgstr "Сцената '%s' има нарушени завиÑимоÑти:"
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Error while loading '%s'."
+msgstr "Имаше грешка при зареждане на Ñцената."
+
+#: editor/editor_node.cpp
msgid "Saving Scene"
msgstr "Запазване на Ñцената"
@@ -1583,6 +1462,33 @@ msgid "Restored default layout to base settings."
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was imported, so it's not editable.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was instanced or inherited.\n"
+"Changes to it will not be kept when saving the current scene."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource was imported, so it's not editable. Change its settings in the "
+"import panel and then re-import."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This scene was imported, so changes to it will not be kept.\n"
+"Instancing it or inheriting will allow making changes to it.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Copy Params"
msgstr ""
@@ -1748,23 +1654,35 @@ msgid "Save changes the following scene(s) before opening Project Manager?"
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"This option is deprecated. Situations where refresh must be forced are now "
+"considered a bug. Please report."
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Pick a Main Scene"
msgstr "Изберете главна Ñцена"
#: editor/editor_node.cpp
-msgid "Unable to enable addon plugin at: '"
+msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr ""
#: editor/editor_node.cpp
-msgid "' parsing of config failed."
+msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/"
+#, fuzzy
+msgid "Unable to load addon script from path: '%s'."
+msgstr "Грешка при зареждането на шрифта."
+
+#: editor/editor_node.cpp
+msgid ""
+"Unable to load addon script from path: '%s' Base type is not EditorPlugin."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to load addon script from path: '"
+msgid "Unable to load addon script from path: '%s' Script is not in tool mode."
msgstr ""
#: editor/editor_node.cpp
@@ -1774,7 +1692,7 @@ msgid ""
msgstr ""
#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/scene_tree_dock.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Ugh"
msgstr ""
@@ -1785,14 +1703,15 @@ msgid ""
msgstr ""
#: editor/editor_node.cpp
-msgid "Error loading scene."
-msgstr "Имаше грешка при зареждане на Ñцената."
-
-#: editor/editor_node.cpp
msgid "Scene '%s' has broken dependencies:"
msgstr "Сцената '%s' има нарушени завиÑимоÑти:"
#: editor/editor_node.cpp
+#, fuzzy
+msgid "Clear Recent Scenes"
+msgstr "ЗатварÑне на Ñцената"
+
+#: editor/editor_node.cpp
msgid "Save Layout"
msgstr ""
@@ -1825,7 +1744,7 @@ msgstr ""
msgid "Toggle distraction-free mode."
msgstr ""
-#: editor/editor_node.cpp editor/io_plugins/editor_scene_import_plugin.cpp
+#: editor/editor_node.cpp
msgid "Scene"
msgstr "Сцена"
@@ -2044,6 +1963,10 @@ msgstr ""
msgid "Issue Tracker"
msgstr ""
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+msgid "Community"
+msgstr ""
+
#: editor/editor_node.cpp
msgid "About"
msgstr "ОтноÑно"
@@ -2052,7 +1975,7 @@ msgstr "ОтноÑно"
msgid "Play the project."
msgstr "Възпроизвеждане на проекта."
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Play"
msgstr ""
@@ -2068,7 +1991,7 @@ msgstr "ПреуÑтановÑване на Ñцената"
msgid "Stop the scene."
msgstr "Спиране на Ñцената."
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Stop"
msgstr ""
@@ -2141,6 +2064,15 @@ msgid "Object properties."
msgstr ""
#: editor/editor_node.cpp
+msgid "Changes may be lost!"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Import"
+msgstr "ВнаÑÑне"
+
+#: editor/editor_node.cpp
msgid "FileSystem"
msgstr ""
@@ -2156,14 +2088,6 @@ msgstr ""
msgid "Don't Save"
msgstr ""
-#: editor/editor_node.cpp editor/editor_reimport_dialog.cpp
-msgid "Re-Import"
-msgstr "Повторно внаÑÑне"
-
-#: editor/editor_node.cpp editor/editor_plugin_settings.cpp
-msgid "Update"
-msgstr ""
-
#: editor/editor_node.cpp
msgid "Import Templates From ZIP File"
msgstr "ВнаÑÑне на шаблони от архив във формат ZIP"
@@ -2225,11 +2149,28 @@ msgstr ""
msgid "Open the previous Editor"
msgstr ""
+#: editor/editor_plugin.cpp
+msgid "Creating Mesh Previews"
+msgstr ""
+
+#: editor/editor_plugin.cpp
+msgid "Thumbnail.."
+msgstr ""
+
#: editor/editor_plugin_settings.cpp
msgid "Installed Plugins:"
msgstr "ИнÑталирани приÑтавки:"
#: editor/editor_plugin_settings.cpp
+msgid "Update"
+msgstr ""
+
+#: editor/editor_plugin_settings.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Version:"
+msgstr "ВерÑиÑ:"
+
+#: editor/editor_plugin_settings.cpp
msgid "Author:"
msgstr ""
@@ -2262,7 +2203,7 @@ msgid "Frame %"
msgstr ""
#: editor/editor_profiler.cpp
-msgid "Fixed Frame %"
+msgid "Physics Frame %"
msgstr ""
#: editor/editor_profiler.cpp editor/script_editor_debugger.cpp
@@ -2281,27 +2222,6 @@ msgstr ""
msgid "Frame #:"
msgstr ""
-#: editor/editor_reimport_dialog.cpp
-msgid "Please wait for scan to complete."
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Current scene must be saved to re-import."
-msgstr ""
-"За да Ñе извърши повторното внаÑÑне, текущата Ñцена Ñ‚Ñ€Ñбва да бъде запазена."
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Save & Re-Import"
-msgstr "Запазване и повторно внаÑÑне"
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Importing"
-msgstr "Извършва Ñе повторно внаÑÑне"
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Import Changed Resources"
-msgstr ""
-
#: editor/editor_run_native.cpp
msgid "Select device from the list"
msgstr ""
@@ -2413,10 +2333,6 @@ msgid "Importing:"
msgstr "ВнаÑÑне:"
#: editor/export_template_manager.cpp
-msgid "Loading Export Templates"
-msgstr ""
-
-#: editor/export_template_manager.cpp
msgid "Current Version:"
msgstr ""
@@ -2451,82 +2367,78 @@ msgid "Cannot navigate to '"
msgstr ""
#: editor/filesystem_dock.cpp
-#, fuzzy
-msgid ""
-"\n"
-"Status: Needs Re-Import"
-msgstr "Запазване и повторно внаÑÑне"
-
-#: editor/filesystem_dock.cpp
-msgid ""
-"\n"
-"Source: "
+msgid "View items as a grid of thumbnails"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Same source and destination files, doing nothing."
+msgid "View items as a list"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Target file exists, can't overwrite. Delete first."
+msgid ""
+"\n"
+"Status: Import of file failed. Please fix file and reimport manually."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Same source and destination paths, doing nothing."
+msgid ""
+"\n"
+"Source: "
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Can't move directories to within themselves."
+msgid "Cannot move/rename resources root."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Can't rename deps for:\n"
+msgid "Cannot move a folder into itself.\n"
msgstr ""
#: editor/filesystem_dock.cpp
#, fuzzy
-msgid "Error moving file:\n"
+msgid "Error moving:\n"
msgstr "Имаше грешка при внаÑÑнето:"
#: editor/filesystem_dock.cpp
#, fuzzy
-msgid "Error moving dir:\n"
-msgstr "Имаше грешка при внаÑÑнето:"
+msgid "Unable to update dependencies:\n"
+msgstr "Сцената '%s' има нарушени завиÑимоÑти:"
#: editor/filesystem_dock.cpp
-msgid "Can't operate on '..'"
+msgid "No name provided"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Pick New Name and Location For:"
+msgid "Provided name contains invalid characters"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "No files selected!"
+msgid "No name provided."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Expand all"
+msgid "Name contains invalid characters."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Collapse all"
+msgid "A file or folder with this name already exists."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Show In File Manager"
-msgstr ""
+#, fuzzy
+msgid "Renaming file:"
+msgstr "Имаше грешка при внаÑÑнето:"
#: editor/filesystem_dock.cpp
-msgid "Instance"
+msgid "Renaming folder:"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Edit Dependencies.."
+msgid "Expand all"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "View Owners.."
+msgid "Collapse all"
msgstr ""
#: editor/filesystem_dock.cpp
@@ -2534,7 +2446,7 @@ msgid "Copy Path"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Rename or Move.."
+msgid "Rename.."
msgstr ""
#: editor/filesystem_dock.cpp
@@ -2542,12 +2454,25 @@ msgid "Move To.."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Info"
+#, fuzzy
+msgid "New Folder.."
+msgstr "Създаване на папка"
+
+#: editor/filesystem_dock.cpp
+msgid "Show In File Manager"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Re-Import.."
-msgstr "Повторно внаÑÑне.."
+msgid "Instance"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "Edit Dependencies.."
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "View Owners.."
+msgstr ""
#: editor/filesystem_dock.cpp
msgid "Previous Directory"
@@ -2579,6 +2504,11 @@ msgstr ""
msgid "Move"
msgstr ""
+#: editor/filesystem_dock.cpp editor/plugins/animation_tree_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Rename"
+msgstr ""
+
#: editor/groups_editor.cpp
msgid "Add to Group"
msgstr ""
@@ -2593,6 +2523,11 @@ msgid "Import as Single Scene"
msgstr "ВнаÑÑне на Ñцената.."
#: editor/import/resource_importer_scene.cpp
+#, fuzzy
+msgid "Import with Separate Animations"
+msgstr "ВнаÑÑне на анимации.."
+
+#: editor/import/resource_importer_scene.cpp
msgid "Import with Separate Materials"
msgstr ""
@@ -2605,6 +2540,18 @@ msgid "Import with Separate Objects+Materials"
msgstr ""
#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Materials+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Materials+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
#, fuzzy
msgid "Import as Multiple Scenes"
msgstr "ВнаÑÑне на триизмерна Ñцена"
@@ -2614,38 +2561,31 @@ msgid "Import as Multiple Scenes+Materials"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Import Scene"
msgstr "ВнаÑÑне на Ñцена"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Importing Scene.."
msgstr "ВнаÑÑне на Ñцената.."
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Running Custom Script.."
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Couldn't load post-import script:"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Invalid/broken script for post-import (check console):"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Error running post-import script:"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Saving.."
msgstr ""
@@ -2674,579 +2614,54 @@ msgstr ""
msgid "Reimport"
msgstr "Повторно внаÑÑне"
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "No bit masks to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path is empty."
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must be a complete resource path."
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must exist."
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Save path is empty!"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Import BitMasks"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s):"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Target Path:"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Accept"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Bit Mask"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No source font file!"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No target font resource!"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"Invalid file extension.\n"
-"Please use .font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Can't load/process source font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Couldn't save font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font Size:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Dest Resource:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "The quick brown fox jumps over the lazy dog."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Test:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Options:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Font Import"
-msgstr "ВнаÑÑне на шрифт"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"This file is already a Godot font file, please supply a BMFont type file "
-"instead."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Failed opening as BMFont file."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error initializing FreeType."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Unknown font format."
-msgstr "Ðепознат формат за шрифтове."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error loading font."
-msgstr "Грешка при зареждането на шрифта."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Invalid font size."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Invalid font custom source."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/plugins/theme_editor_plugin.cpp
-msgid "Font"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "No meshes to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Single Mesh Import"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Source Mesh(es):"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/plugins/mesh_instance_editor_plugin.cpp
-msgid "Mesh"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Surface %d"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "No samples to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Import Audio Samples"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Source Sample(s):"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Audio Sample"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "New Clip"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Animation Options"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Flags"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Bake FPS:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Optimizer"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Linear Error"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angular Error"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angle"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Clips"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Start(s)"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "End(s)"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Loop"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Filters"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source path is empty."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't load post-import script."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Invalid/broken script for post-import."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Error importing scene."
-msgstr "Имаше грешка при внаÑÑнето на Ñцената."
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import 3D Scene"
-msgstr "ВнаÑÑне на триизмерна Ñцена"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source Scene:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Same as Target Scene"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Shared"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Target Texture Folder:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Post-Process Script:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Custom Root Node Type:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Auto"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Root Node Name:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "The Following Files are Missing:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Anyway"
-msgstr "ВнаÑÑне въпреки това"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp scene/gui/dialogs.cpp
-msgid "Cancel"
-msgstr "Отказ"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import & Open"
-msgstr "ВнаÑÑне и отварÑне"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Edited scene has not been saved, open imported scene anyway?"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Image:"
-msgstr "ВнаÑÑне на изображение:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Can't import a file over itself:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't localize path: %s (already local)"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "3D Scene Animation"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Uncompressed"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossless (PNG)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossy (WebP)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress (VRAM)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Format"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Compression Quality (WebP):"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Options"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Please specify some files!"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "At least one file needed for Atlas."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Error importing:"
-msgstr "Имаше грешка при внаÑÑнето:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Only one file is required for large texture."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Max Texture Size:"
+#: editor/multi_node_edit.cpp
+msgid "MultiNode Set"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for Atlas (2D)"
-msgstr "ВнаÑÑне на текÑтури за ÐÑ‚Ð»Ð°Ñ (двуизмерно)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cell Size:"
+#: editor/node_dock.cpp
+msgid "Groups"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Large Texture"
+#: editor/node_dock.cpp
+msgid "Select a Node to edit Signals and Groups."
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Textures (2D)"
-msgstr "ВнаÑÑне на големи текÑтури (двуизмерно)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create Poly"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Base Atlas Texture"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s)"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Insert Point"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 2D"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly (Remove Point)"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 3D"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Remove Poly And Point"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures"
-msgstr "ВнаÑÑне на текÑтури"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "2D Texture"
-msgstr "Двуизмерна текÑтура"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "3D Texture"
-msgstr "Триизмерна текÑтура"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Atlas Texture"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create a new polygon from scratch."
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
+#: editor/plugins/abstract_polygon_2d_editor.cpp
msgid ""
-"NOTICE: Importing 2D textures is not mandatory. Just copy png/jpg files to "
-"the project."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Crop empty space."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Texture"
-msgstr "ВнаÑÑне на голÑма текÑтура"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Load Source Image"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Slicing"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Inserting"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Saving"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save large texture:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Build Atlas For:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Loading Image:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't load image:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Converting Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cropping Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Blitting Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save atlas image:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save converted texture:"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid source!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid translation source!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Column"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/script_create_dialog.cpp
-msgid "Language"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No items to import!"
-msgstr "ÐÑма артикули за внаÑÑне!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No target path!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translations"
-msgstr "ВнаÑÑне на преводи"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Couldn't import!"
-msgstr "ÐеуÑпешно внаÑÑне!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translation"
-msgstr "ВнаÑÑне на превода"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Source CSV:"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Ignore First Row"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Compress"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Add to Project (project.godot)"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Languages:"
-msgstr "ВнаÑÑне на езици:"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Translation"
-msgstr ""
-
-#: editor/multi_node_edit.cpp
-msgid "MultiNode Set"
-msgstr ""
-
-#: editor/node_dock.cpp
-msgid "Groups"
-msgstr ""
-
-#: editor/node_dock.cpp
-msgid "Select a Node to edit Signals and Groups."
+"Edit existing polygon:\n"
+"LMB: Move Point.\n"
+"Ctrl+LMB: Split Segment.\n"
+"RMB: Erase Point."
msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
@@ -3402,7 +2817,6 @@ msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
#: editor/script_create_dialog.cpp
msgid "Error!"
@@ -3513,10 +2927,6 @@ msgid "Delete Input"
msgstr ""
#: editor/plugins/animation_tree_editor_plugin.cpp
-msgid "Rename"
-msgstr ""
-
-#: editor/plugins/animation_tree_editor_plugin.cpp
msgid "Animation tree is valid."
msgstr ""
@@ -3572,64 +2982,182 @@ msgstr ""
msgid "Filters.."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing %d Triangles:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Free"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Contents:"
+msgstr "Съдържание:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "View Files"
+msgstr "Преглед на файловете"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve hostname:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Triangle #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Light Baker Setup:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connection error, please try again."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing Geometry"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't connect."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Fixing Lights"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't connect to host:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Making BVH"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response from host:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Light Octree"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Octree Texture"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, return code:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Transfer to Lightmaps:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Req. Failed."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Allocating Texture #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, too many redirects"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Baking Triangle #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Redirect Loop."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Post-Processing Texture #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed:"
msgstr ""
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Bake!"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Bad download hash, assuming file has been tampered with."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Expected:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Got:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed sha256 hash check"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Asset Download Error:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Fetching:"
+msgstr "ИзтеглÑне:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Resolving.."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connecting.."
+msgstr "Свързване.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Requesting.."
+msgstr "Запитване.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Error making request"
+msgstr "Имаше грешка при зареждане на Ñцената."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Idle"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Retry"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download Error"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download for this asset is already in progress!"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "first"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "prev"
msgstr ""
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Reset the lightmap octree baking process (start over)."
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "next"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "last"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "All"
+msgstr "Ð’Ñички"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Plugins"
+msgstr "ПриÑтавки"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Sort:"
+msgstr "Подреждане:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Reverse"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Category:"
+msgstr "КатегориÑ:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Site:"
+msgstr "ÐœÑÑто:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Support.."
+msgstr "Поддръжка"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Official"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Testing"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Assets ZIP File"
msgstr ""
#: editor/plugins/camera_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
msgid "Preview"
msgstr ""
@@ -3672,11 +3200,15 @@ msgid "Edit CanvasItem"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Change Anchors"
+msgid "Anchors only"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom (%):"
+msgid "Change Anchors and Margins"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Change Anchors"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3728,59 +3260,72 @@ msgid "Pan Mode"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Lock the selected object in place (can't be moved)."
+msgid "Toggles snapping"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Unlock the selected object (can be moved)."
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Use Snap"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Makes sure the object's children are not selectable."
+msgid "Snapping options"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Restores the object's children's ability to be selected."
+msgid "Snap to grid"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Edit"
+msgid "Use Rotation Snap"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Use Snap"
+msgid "Configure Snap..."
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Show Grid"
+msgid "Snap Relative"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Rotation Snap"
+msgid "Use Pixel Snap"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap Relative"
+msgid "Smart snapping"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Configure Snap.."
+msgid "Snap to parent"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Pixel Snap"
+msgid "Snap to node anchor"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Skeleton.."
+msgid "Snap to node sides"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to other nodes"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Lock the selected object in place (can't be moved)."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Unlock the selected object (can be moved)."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Makes sure the object's children are not selectable."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Restores the object's children's ability to be selected."
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3809,11 +3354,16 @@ msgid "View"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Reset"
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Show Grid"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Set.."
+msgid "Show helpers"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Show rulers"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3825,7 +3375,7 @@ msgid "Frame Selection"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Anchor"
+msgid "Layout"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3849,11 +3399,19 @@ msgid "Clear Pose"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Set a Value"
+msgid "Drag pivot from mouse position"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Set pivot at mouse position"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap (Pixels):"
+msgid "Multiply grid step by 2"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Divide grid step by 2"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3864,23 +3422,28 @@ msgstr ""
msgid "Adding %s..."
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Create Node"
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Error instancing scene from %s"
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "OK :("
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "No parent to instance a child at."
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "This operation requires a single selected node."
msgstr ""
@@ -3894,45 +3457,6 @@ msgid ""
"Drag & drop + Alt : Change node type"
msgstr ""
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Create Poly"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly (Remove Point)"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Create a new polygon from scratch."
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-msgid ""
-"Edit existing polygon:\n"
-"LMB: Move Point.\n"
-"Ctrl+LMB: Split Segment.\n"
-"RMB: Erase Point."
-msgstr ""
-
#: editor/plugins/collision_polygon_editor_plugin.cpp
msgid "Create Poly3D"
msgstr ""
@@ -3942,14 +3466,6 @@ msgid "Set Handle"
msgstr ""
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Creating Mesh Library"
-msgstr ""
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Thumbnail.."
-msgstr ""
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Remove item %d?"
msgstr ""
@@ -3972,6 +3488,26 @@ msgid "Update from Scene"
msgstr "ОбновÑване от Ñцена"
#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat0"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat1"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Ease in"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Ease out"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Smoothstep"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
msgid "Modify Curve Point"
msgstr ""
@@ -4048,22 +3584,18 @@ msgid "Create Occluder Polygon"
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Edit existing polygon:"
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "LMB: Move Point."
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Ctrl+LMB: Split Segment."
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "RMB: Erase Point."
msgstr ""
@@ -4164,6 +3696,10 @@ msgid "Create Outline"
msgstr ""
#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Mesh"
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Create Trimesh Static Body"
msgstr ""
@@ -4291,12 +3827,72 @@ msgstr ""
msgid "Populate"
msgstr ""
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Create Navigation Polygon"
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake!"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake the navigation mesh.\n"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Clear the navigation mesh."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Setting up Configuration..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Calculating grid size..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating heightfield..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Marking walkable triangles..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Constructing compact heightfield..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Eroding walkable area..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Partitioning..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating contours..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating polymesh..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Converting to native navigation mesh..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Navigation Mesh Generator Setup:"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Parsing Geometry..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Done!"
msgstr ""
#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Remove Poly And Point"
+msgid "Create Navigation Polygon"
msgstr ""
#: editor/plugins/particles_2d_editor_plugin.cpp
@@ -4538,6 +4134,14 @@ msgid "Scale Polygon"
msgstr ""
#: editor/plugins/polygon_2d_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Edit"
+msgstr ""
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Polygon->UV"
msgstr ""
@@ -4592,63 +4196,10 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/shader_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "ПоÑтавÑне"
-#: editor/plugins/rich_text_editor_plugin.cpp
-msgid "Parse BBCode"
-msgstr ""
-
-#: editor/plugins/sample_editor_plugin.cpp
-msgid "Length:"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Open Sample File(s)"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "ERROR: Couldn't load sample!"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Add Sample"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Rename Sample"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Delete Sample"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "16 Bits"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "8 Bits"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Stereo"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Mono"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Format"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Pitch"
-msgstr ""
-
#: editor/plugins/script_editor_plugin.cpp
msgid "Clear Recent Files"
msgstr ""
@@ -4739,6 +4290,10 @@ msgstr ""
msgid "Close All"
msgstr "ЗатварÑне на вÑичко"
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+msgid "Run"
+msgstr "ПуÑкане"
+
#: editor/plugins/script_editor_plugin.cpp
msgid "Toggle Scripts Panel"
msgstr ""
@@ -4767,7 +4322,8 @@ msgstr ""
msgid "Break"
msgstr ""
-#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+#: editor/script_editor_debugger.cpp
msgid "Continue"
msgstr ""
@@ -4780,18 +4336,6 @@ msgid "Debug with external editor"
msgstr ""
#: editor/plugins/script_editor_plugin.cpp
-msgid "Window"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Left"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Right"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
msgid "Open Godot online documentation"
msgstr ""
@@ -4873,8 +4417,9 @@ msgid "Cut"
msgstr "ИзрÑзване"
#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "Копиране"
@@ -5138,10 +4683,6 @@ msgid "View Plane Transform."
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Scaling to %s%%."
-msgstr ""
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rotating %s degrees."
msgstr ""
@@ -5158,10 +4699,6 @@ msgid "Top View."
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Top"
-msgstr ""
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rear View."
msgstr ""
@@ -5391,6 +4928,10 @@ msgid "Transform"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Configure Snap.."
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Local Coords"
msgstr ""
@@ -5536,6 +5077,10 @@ msgid "Speed (FPS):"
msgstr "СкороÑÑ‚ (кадри в Ñекунда):"
#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Loop"
+msgstr ""
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Animation Frames"
msgstr ""
@@ -5548,11 +5093,12 @@ msgid "Insert Empty (After)"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Up"
-msgstr ""
+#, fuzzy
+msgid "Move (Before)"
+msgstr "ПоÑтавÑне на възелите"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Down"
+msgid "Move (After)"
msgstr ""
#: editor/plugins/style_box_editor_plugin.cpp
@@ -5630,7 +5176,11 @@ msgid "Remove All"
msgstr "ЗатварÑне на вÑичко"
#: editor/plugins/theme_editor_plugin.cpp
-msgid "Theme"
+msgid "Edit theme.."
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Theme editing menu."
msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
@@ -5715,6 +5265,10 @@ msgid "Style"
msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
+msgid "Font"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
msgid "Color"
msgstr ""
@@ -5764,7 +5318,7 @@ msgid "Mirror Y"
msgstr ""
#: editor/plugins/tile_map_editor_plugin.cpp
-msgid "Bucket"
+msgid "Paint Tile"
msgstr ""
#: editor/plugins/tile_map_editor_plugin.cpp
@@ -5828,6 +5382,10 @@ msgid "Delete preset '%s'?"
msgstr ""
#: editor/project_export.cpp
+msgid "Export templates for this platform are missing/corrupted: "
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Presets"
msgstr ""
@@ -5899,19 +5457,30 @@ msgid "Export templates for this platform are missing:"
msgstr ""
#: editor/project_export.cpp
+msgid "Export templates for this platform are missing/corrupted:"
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Export With Debug"
msgstr ""
#: editor/project_manager.cpp
-msgid "Invalid project path, the path must exist!"
-msgstr "ÐедейÑтвителен път. ПътÑÑ‚ Ñ‚Ñ€Ñбва да ÑъщеÑтвува!"
+msgid "The path does not exist."
+msgstr ""
#: editor/project_manager.cpp
-msgid "Invalid project path, project.godot must not exist."
+#, fuzzy
+msgid "Please choose a 'project.godot' file."
+msgstr "МолÑ, изнеÑете извън папката на проекта!"
+
+#: editor/project_manager.cpp
+msgid ""
+"Your project will be created in a non empty folder (you might want to create "
+"a new folder)."
msgstr ""
#: editor/project_manager.cpp
-msgid "Invalid project path, project.godot must exist."
+msgid "Please choose a folder that does not contain a 'project.godot' file."
msgstr ""
#: editor/project_manager.cpp
@@ -5919,10 +5488,26 @@ msgid "Imported Project"
msgstr "ВнеÑен проект"
#: editor/project_manager.cpp
+msgid " "
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "It would be a good idea to name your project."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Invalid project path (changed anything?)."
msgstr ""
#: editor/project_manager.cpp
+msgid "Couldn't get project.godot in project path."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Couldn't edit project.godot in project path."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
msgstr ""
@@ -5931,11 +5516,28 @@ msgid "The following files failed extraction from package:"
msgstr ""
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Rename Project"
+msgstr "Ðов проект"
+
+#: editor/project_manager.cpp
+msgid "Couldn't get project.godot in the project path."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "New Game Project"
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Import Existing Project"
msgstr "ВнаÑÑне на ÑъщеÑтвуващ проект"
#: editor/project_manager.cpp
-msgid "Project Path (Must Exist):"
+msgid "Create New Project"
+msgstr "Създаване на нов проект"
+
+#: editor/project_manager.cpp
+msgid "Install Project:"
msgstr ""
#: editor/project_manager.cpp
@@ -5943,26 +5545,19 @@ msgid "Project Name:"
msgstr "Име:"
#: editor/project_manager.cpp
-msgid "Create New Project"
-msgstr "Създаване на нов проект"
+#, fuzzy
+msgid "Create folder"
+msgstr "Създаване на папка"
#: editor/project_manager.cpp
msgid "Project Path:"
msgstr "Път:"
#: editor/project_manager.cpp
-msgid "Install Project:"
-msgstr ""
-
-#: editor/project_manager.cpp
msgid "Browse"
msgstr "Разглеждане"
#: editor/project_manager.cpp
-msgid "New Game Project"
-msgstr ""
-
-#: editor/project_manager.cpp
msgid "That's a BINGO!"
msgstr ""
@@ -5971,6 +5566,11 @@ msgid "Unnamed Project"
msgstr ""
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Can't open project"
+msgstr "Създаване на нов проект"
+
+#: editor/project_manager.cpp
msgid "Are you sure to open more than one project?"
msgstr ""
@@ -5997,6 +5597,12 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
+"Language changed.\n"
+"The UI will update next time the editor or project manager starts."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid ""
"You are about the scan %s folders for existing Godot projects. Do you "
"confirm?"
msgstr ""
@@ -6006,10 +5612,6 @@ msgid "Project List"
msgstr "СпиÑък Ñ Ð¿Ñ€Ð¾ÐµÐºÑ‚Ð¸"
#: editor/project_manager.cpp
-msgid "Run"
-msgstr "ПуÑкане"
-
-#: editor/project_manager.cpp
msgid "Scan"
msgstr "Сканиране"
@@ -6030,6 +5632,10 @@ msgid "Exit"
msgstr "Изход"
#: editor/project_manager.cpp
+msgid "Restart Now"
+msgstr ""
+
+#: editor/project_manager.cpp
#, fuzzy
msgid "Can't run project"
msgstr "Създаване на нов проект"
@@ -6067,17 +5673,14 @@ msgid "Add Input Action Event"
msgstr ""
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Meta+"
msgstr ""
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Shift+"
msgstr ""
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Alt+"
msgstr ""
@@ -6138,7 +5741,7 @@ msgstr ""
msgid "Joypad Axis Index:"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Axis"
msgstr "ОÑ"
@@ -6158,31 +5761,31 @@ msgstr ""
msgid "Add Event"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Device"
msgstr "УÑтройÑтво"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Button"
msgstr "Копче"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Left Button."
msgstr "ЛÑво копче."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Right Button."
msgstr "ДÑÑно копче."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Middle Button."
msgstr "Средно копче."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Up."
msgstr "Колелцето нагоре."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Down."
msgstr "Колелцето надолу."
@@ -6191,7 +5794,7 @@ msgid "Add Global Property"
msgstr ""
#: editor/project_settings_editor.cpp
-msgid "Select an setting item first!"
+msgid "Select a setting item first!"
msgstr ""
#: editor/project_settings_editor.cpp
@@ -6208,6 +5811,14 @@ msgid "Delete Item"
msgstr ""
#: editor/project_settings_editor.cpp
+msgid "Can't contain '/' or ':'"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Already existing"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "Error saving settings."
msgstr ""
@@ -6248,6 +5859,14 @@ msgid "Remove Resource Remap Option"
msgstr ""
#: editor/project_settings_editor.cpp
+msgid "Changed Locale Filter"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Changed Locale Filter Mode"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "Project Settings (project.godot)"
msgstr "ÐаÑтройки на проекта"
@@ -6308,6 +5927,27 @@ msgid "Locale"
msgstr ""
#: editor/project_settings_editor.cpp
+msgid "Locales Filter"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Show all locales"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Show only selected locales"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Filter mode:"
+msgstr "ПоÑтавÑне на възелите"
+
+#: editor/project_settings_editor.cpp
+msgid "Locales:"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "AutoLoad"
msgstr ""
@@ -6357,10 +5997,18 @@ msgid "New Script"
msgstr "Ðов Ñкрипт"
#: editor/property_editor.cpp
+msgid "Make Unique"
+msgstr ""
+
+#: editor/property_editor.cpp
msgid "Show in File System"
msgstr ""
#: editor/property_editor.cpp
+msgid "Convert To %s"
+msgstr ""
+
+#: editor/property_editor.cpp
msgid "Error loading file: Not a resource!"
msgstr ""
@@ -6398,6 +6046,11 @@ msgid "Select Property"
msgstr "Изберете ÑвойÑтво"
#: editor/property_selector.cpp
+#, fuzzy
+msgid "Select Virtual Method"
+msgstr "Изберете метод"
+
+#: editor/property_selector.cpp
msgid "Select Method"
msgstr "Изберете метод"
@@ -6425,26 +6078,6 @@ msgstr ""
msgid "Reparent"
msgstr ""
-#: editor/resources_dock.cpp
-msgid "Create New Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Open Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Save Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Resource Tools"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Make Local"
-msgstr ""
-
#: editor/run_settings_dialog.cpp
msgid "Run Mode:"
msgstr ""
@@ -6571,14 +6204,6 @@ msgid "Sub-Resources:"
msgstr ""
#: editor/scene_tree_dock.cpp
-msgid "Edit Groups"
-msgstr ""
-
-#: editor/scene_tree_dock.cpp
-msgid "Edit Connections"
-msgstr ""
-
-#: editor/scene_tree_dock.cpp
msgid "Clear Inheritance"
msgstr ""
@@ -6767,6 +6392,15 @@ msgid "Invalid base path"
msgstr ""
#: editor/script_create_dialog.cpp
+msgid "Directory of the same name exists"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
+#, fuzzy
+msgid "File exists, will be reused"
+msgstr "Файлът ÑъщеÑтвува. ИÑкате ли да го презапишете?"
+
+#: editor/script_create_dialog.cpp
msgid "Invalid extension"
msgstr ""
@@ -6807,6 +6441,10 @@ msgid "Load existing script file"
msgstr ""
#: editor/script_create_dialog.cpp
+msgid "Language"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
msgid "Inherits"
msgstr ""
@@ -6848,6 +6486,10 @@ msgid "Function:"
msgstr ""
#: editor/script_editor_debugger.cpp
+msgid "Pick one or more items from the list to display the graph."
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
msgid "Errors"
msgstr "Грешки"
@@ -6928,6 +6570,10 @@ msgid "Type"
msgstr ""
#: editor/script_editor_debugger.cpp
+msgid "Format"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
msgid "Usage"
msgstr ""
@@ -7003,6 +6649,23 @@ msgstr ""
msgid "Change Probe Extents"
msgstr ""
+#: modules/gdnative/gd_native_library_editor.cpp
+#, fuzzy
+msgid "Library"
+msgstr "ИзнаÑÑне на библиотеката"
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Status"
+msgstr ""
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Libraries: "
+msgstr ""
+
+#: modules/gdnative/register_types.cpp
+msgid "GDNative"
+msgstr ""
+
#: modules/gdscript/gd_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Invalid type argument to convert(), use TYPE_* constants."
@@ -7010,7 +6673,7 @@ msgstr ""
"Ðевалиден агрумент тип на convert(), използвайте конÑтантите започващи Ñ "
"TYPE_*."
-#: modules/gdscript/gd_functions.cpp
+#: modules/gdscript/gd_functions.cpp modules/mono/glue/glue_header.h
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Not enough bytes for decoding bytes, or invalid format."
msgstr "ÐедоÑтатъчно байтове за разкодиране или недейÑтвителен формат."
@@ -7068,10 +6731,6 @@ msgid "GridMap Duplicate Selection"
msgstr ""
#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "GridMap Paint"
-msgstr ""
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Snap View"
msgstr ""
@@ -7167,13 +6826,8 @@ msgstr "ÐаÑтройки"
msgid "Pick Distance:"
msgstr ""
-#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
-msgid "Tiles"
-msgstr "Файл:"
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "Areas"
+#: modules/mono/editor/mono_bottom_panel.cpp
+msgid "Builds"
msgstr ""
#: modules/visual_script/visual_script.cpp
@@ -7365,10 +7019,18 @@ msgid "Return"
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
+msgid "Call"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
msgid "Get"
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
+msgid "Script already has function '%s'"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
msgid "Change Input Value"
msgstr ""
@@ -7756,6 +7418,12 @@ msgid ""
"order for AnimatedSprite3D to display frames."
msgstr ""
+#: scene/3d/vehicle_body.cpp
+msgid ""
+"VehicleWheel serves to provide a wheel system to a VehicleBody. Please use "
+"it as a child of a VehicleBody."
+msgstr ""
+
#: scene/gui/color_picker.cpp
msgid "Raw Mode"
msgstr ""
@@ -7765,6 +7433,10 @@ msgid "Add current color as a preset"
msgstr ""
#: scene/gui/dialogs.cpp
+msgid "Cancel"
+msgstr "Отказ"
+
+#: scene/gui/dialogs.cpp
msgid "Alert!"
msgstr "Тревога!"
@@ -7772,10 +7444,6 @@ msgstr "Тревога!"
msgid "Please Confirm..."
msgstr "МолÑ, потвърдете..."
-#: scene/gui/input_action.cpp
-msgid "Ctrl+"
-msgstr ""
-
#: scene/gui/popup.cpp
msgid ""
"Popups will hide by default unless you call popup() or any of the popup*() "
@@ -7804,6 +7472,106 @@ msgid ""
"texture to some node for display."
msgstr ""
+#: scene/resources/dynamic_font.cpp
+msgid "Error initializing FreeType."
+msgstr ""
+
+#: scene/resources/dynamic_font.cpp
+msgid "Unknown font format."
+msgstr "Ðепознат формат за шрифтове."
+
+#: scene/resources/dynamic_font.cpp
+msgid "Error loading font."
+msgstr "Грешка при зареждането на шрифта."
+
+#: scene/resources/dynamic_font.cpp
+msgid "Invalid font size."
+msgstr ""
+
+#~ msgid "Exporting for %s"
+#~ msgstr "ИзнаÑÑне за %s"
+
+#~ msgid "Re-Import"
+#~ msgstr "Повторно внаÑÑне"
+
+#~ msgid "Current scene must be saved to re-import."
+#~ msgstr ""
+#~ "За да Ñе извърши повторното внаÑÑне, текущата Ñцена Ñ‚Ñ€Ñбва да бъде "
+#~ "запазена."
+
+#~ msgid "Save & Re-Import"
+#~ msgstr "Запазване и повторно внаÑÑне"
+
+#~ msgid "Re-Importing"
+#~ msgstr "Извършва Ñе повторно внаÑÑне"
+
+#, fuzzy
+#~ msgid ""
+#~ "\n"
+#~ "Status: Needs Re-Import"
+#~ msgstr "Запазване и повторно внаÑÑне"
+
+#~ msgid "Re-Import.."
+#~ msgstr "Повторно внаÑÑне.."
+
+#~ msgid "Font Import"
+#~ msgstr "ВнаÑÑне на шрифт"
+
+#~ msgid "Import 3D Scene"
+#~ msgstr "ВнаÑÑне на триизмерна Ñцена"
+
+#~ msgid "Import Anyway"
+#~ msgstr "ВнаÑÑне въпреки това"
+
+#~ msgid "Import & Open"
+#~ msgstr "ВнаÑÑне и отварÑне"
+
+#~ msgid "Import Image:"
+#~ msgstr "ВнаÑÑне на изображение:"
+
+#~ msgid "Error importing:"
+#~ msgstr "Имаше грешка при внаÑÑнето:"
+
+#~ msgid "Import Textures for Atlas (2D)"
+#~ msgstr "ВнаÑÑне на текÑтури за ÐÑ‚Ð»Ð°Ñ (двуизмерно)"
+
+#~ msgid "Import Large Textures (2D)"
+#~ msgstr "ВнаÑÑне на големи текÑтури (двуизмерно)"
+
+#~ msgid "Import Textures"
+#~ msgstr "ВнаÑÑне на текÑтури"
+
+#~ msgid "2D Texture"
+#~ msgstr "Двуизмерна текÑтура"
+
+#~ msgid "3D Texture"
+#~ msgstr "Триизмерна текÑтура"
+
+#~ msgid "Import Large Texture"
+#~ msgstr "ВнаÑÑне на голÑма текÑтура"
+
+#~ msgid "No items to import!"
+#~ msgstr "ÐÑма артикули за внаÑÑне!"
+
+#~ msgid "Import Translations"
+#~ msgstr "ВнаÑÑне на преводи"
+
+#~ msgid "Couldn't import!"
+#~ msgstr "ÐеуÑпешно внаÑÑне!"
+
+#~ msgid "Import Translation"
+#~ msgstr "ВнаÑÑне на превода"
+
+#~ msgid "Import Languages:"
+#~ msgstr "ВнаÑÑне на езици:"
+
+#~ msgid "Invalid project path, the path must exist!"
+#~ msgstr "ÐедейÑтвителен път. ПътÑÑ‚ Ñ‚Ñ€Ñбва да ÑъщеÑтвува!"
+
+#, fuzzy
+#~ msgid "Tiles"
+#~ msgstr "Файл:"
+
#~ msgid "Close scene? (Unsaved changes will be lost)"
#~ msgstr "Да Ñе затвори ли Ñцената? (незаразените промени ще Ñе загубÑÑ‚)"
@@ -7829,9 +7597,6 @@ msgstr ""
#~ "За да изпълнÑва звук, SamplePlayer Ñ‚Ñ€Ñбва да има един SampleLibrary "
#~ "реÑÑƒÑ€Ñ Ð² параметъра 'samples'."
-#~ msgid "Please export outside the project folder!"
-#~ msgstr "МолÑ, изнеÑете извън папката на проекта!"
-
#~ msgid "Error exporting project!"
#~ msgstr "Имаше грешка при изнаÑÑне на проекта!"
diff --git a/editor/translations/bn.po b/editor/translations/bn.po
index 7be067aedd..3e93381dcd 100644
--- a/editor/translations/bn.po
+++ b/editor/translations/bn.po
@@ -1,5 +1,6 @@
# Bengali translation of the Godot Engine editor
-# Copyright (C) 2016-2017 Juan Linietsky, Ariel Manzur and the Godot community
+# Copyright (C) 2007-2017 Juan Linietsky, Ariel Manzur
+# Copyright (C) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)
# This file is distributed under the same license as the Godot source code.
#
# Abu Md. Maruf Sarker <maruf.webdev@gmail.com>, 2016-2017.
@@ -193,10 +194,9 @@ msgid "Create %d NEW tracks and insert keys?"
msgstr "%d à¦à¦° জনà§à¦¯ নতà§à¦¨ টà§à¦°à§à¦¯à¦¾à¦•/পথ-সমূহ তৈরি করতে à¦à¦¬à¦‚ চাবিসমূহ পà§à¦°à¦¬à§‡à¦¶ করাতে চান?"
#: editor/animation_editor.cpp editor/create_dialog.cpp
-#: editor/editor_audio_buses.cpp
+#: editor/editor_audio_buses.cpp editor/plugins/abstract_polygon_2d_editor.cpp
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
#: editor/plugins/mesh_instance_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp editor/project_manager.cpp
#: editor/script_create_dialog.cpp
msgid "Create"
@@ -359,271 +359,6 @@ msgstr "শà§à¦°à§‡à¦£à§€à¦¬à¦¿à¦¨à§à¦¯à¦¾à¦¸/সারির মানের
msgid "Change Array Value"
msgstr "শà§à¦°à§‡à¦£à§€à¦¬à¦¿à¦¨à§à¦¯à¦¾à¦¸/সারির মান পরিবরà§à¦¤à¦¨ করà§à¦¨"
-#: editor/asset_library_editor_plugin.cpp
-msgid "Free"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_plugin_settings.cpp
-msgid "Version:"
-msgstr "সংসà§à¦•à¦°à¦£:"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Contents:"
-msgstr "ধà§à¦°à§à¦¬à¦•à¦¸à¦®à§‚হ:"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "View Files"
-msgstr "ফাইল"
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_help.cpp editor/property_selector.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Description:"
-msgstr "বরà§à¦£à¦¨à¦¾:"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-#: editor/project_manager.cpp
-msgid "Install"
-msgstr "ইনà§à¦¸à¦Ÿà¦²"
-
-#: editor/asset_library_editor_plugin.cpp editor/call_dialog.cpp
-#: editor/connections_dialog.cpp editor/export_template_manager.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-#: editor/project_settings_editor.cpp editor/property_editor.cpp
-#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Close"
-msgstr "বনà§à¦§ করà§à¦¨"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve hostname:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Connection error, please try again."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Can't connect."
-msgstr "সংযোগ.."
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Can't connect to host:"
-msgstr "নোডের সাথে সংযà§à¦•à§à¦¤ করà§à¦¨:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response from host:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Request failed, return code:"
-msgstr "আবেদনকৃত ফাইল ফরমà§à¦¯à¦¾à¦Ÿ/ধরণ অজানা:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Req. Failed."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Request failed, too many redirects"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Redirect Loop."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Bad download hash, assuming file has been tampered with."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Expected:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Got:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Asset Download Error:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-msgid "Success!"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Fetching:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Resolving.."
-msgstr "সংরকà§à¦·à¦¿à¦¤ হচà§à¦›à§‡.."
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Connecting.."
-msgstr "সংযোগ.."
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Requesting.."
-msgstr "পরীকà§à¦·à¦¾à¦®à§‚লক উৎস"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Error making request"
-msgstr "রিসোরà§à¦¸ সংরকà§à¦·à¦£à§‡ সমসà§à¦¯à¦¾ হয়েছে!"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Idle"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Retry"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Download Error"
-msgstr "নীচে"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Download for this asset is already in progress!"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "first"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "prev"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "next"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "last"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "All"
-msgstr "সকল"
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
-#: editor/settings_config_dialog.cpp
-msgid "Search:"
-msgstr "অনà§à¦¸à¦¨à§à¦§à¦¾à¦¨ করà§à¦¨:"
-
-#: editor/asset_library_editor_plugin.cpp editor/code_editor.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Search"
-msgstr "অনà§à¦¸à¦¨à§à¦§à¦¾à¦¨ করà§à¦¨"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/project_manager.cpp
-msgid "Import"
-msgstr "ইমà§à¦ªà§‹à¦°à§à¦Ÿ"
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Plugins"
-msgstr "পà§à¦²à¦¾à¦—ইন-সমূহ"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Sort:"
-msgstr "সাজান:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Reverse"
-msgstr "উলà§à¦Ÿà¦¾à¦¨/বিপরীত দিকে ফিরান"
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Category:"
-msgstr "বিভাগ:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Site:"
-msgstr "ওয়েবসাইট:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Support.."
-msgstr "সমরà§à¦¥à¦¨.."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Official"
-msgstr "অফিসিয়াল/পà§à¦°à¦¾à¦¥à¦®à¦¿à¦• উৎস"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-msgid "Community"
-msgstr "কমিউনিটি/যৌথ-সামাজিক উৎস"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Testing"
-msgstr "পরীকà§à¦·à¦¾à¦®à§‚লক উৎস"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Assets ZIP File"
-msgstr "পà§à¦°à¦¯à¦¼à§‡à¦¾à¦œà¦¨à§€à¦¯à¦¼ উপকরণসমূহের ZIP ফাইল"
-
-#: editor/call_dialog.cpp
-msgid "Method List For '%s':"
-msgstr "'%s' à¦à¦° জনà§à¦¯ মেথডের তালিকা:"
-
-#: editor/call_dialog.cpp modules/visual_script/visual_script_editor.cpp
-msgid "Call"
-msgstr "ডাকà§à¦¨ (Call)"
-
-#: editor/call_dialog.cpp
-msgid "Method List:"
-msgstr "মেথডের তালিকা:"
-
-#: editor/call_dialog.cpp
-msgid "Arguments:"
-msgstr "মান/আরà§à¦—à§à¦®à§‡à¦¨à§à¦Ÿ-সমূহ:"
-
-#: editor/call_dialog.cpp
-msgid "Return:"
-msgstr "পà§à¦°à¦¤à§à¦¯à¦¾à¦¬à¦°à§à¦¤à¦¨:"
-
#: editor/code_editor.cpp
msgid "Go to Line"
msgstr "লাইন-ঠযান"
@@ -661,6 +396,14 @@ msgstr "সমà§à¦ªà§‚রà§à¦£ শবà§à¦¦"
msgid "Selection Only"
msgstr "শà§à¦§à§à¦®à¦¾à¦¤à§à¦° নিরà§à¦¬à¦¾à¦šà¦¿à¦¤à¦¸à¦®à§‚হ"
+#: editor/code_editor.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
+msgid "Search"
+msgstr "অনà§à¦¸à¦¨à§à¦§à¦¾à¦¨ করà§à¦¨"
+
#: editor/code_editor.cpp editor/editor_help.cpp
msgid "Find"
msgstr "সনà§à¦§à¦¾à¦¨ করà§à¦¨"
@@ -693,11 +436,11 @@ msgstr "পà§à¦°à¦¤à¦¿à¦¸à§à¦¥à¦¾à¦ªà¦¨à§‡ অবহিত করà§à¦¨"
msgid "Skip"
msgstr "অতিকà§à¦°à¦® করে যান"
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom In"
msgstr "সমà§à¦ªà§à¦°à¦¸à¦¾à¦°à¦¿à¦¤ করà§à¦¨ (জà§à¦®à§ ইন)"
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom Out"
msgstr "সংকà§à¦šà¦¿à¦¤ করà§à¦¨ (জà§à¦®à§ আউট)"
@@ -766,6 +509,20 @@ msgstr "বিলমà§à¦¬à¦¿à¦¤"
msgid "Oneshot"
msgstr "ওয়ান-শট"
+#: editor/connections_dialog.cpp editor/dependency_editor.cpp
+#: editor/export_template_manager.cpp
+#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Close"
+msgstr "বনà§à¦§ করà§à¦¨"
+
#: editor/connections_dialog.cpp
msgid "Connect"
msgstr "সংযোগ"
@@ -791,7 +548,7 @@ msgstr "সংযোগ.."
msgid "Disconnect"
msgstr "সংযোগ বিচà§à¦›à¦¿à¦¨à§à¦¨ করà§à¦¨"
-#: editor/connections_dialog.cpp editor/node_dock.cpp
+#: editor/connections_dialog.cpp editor/editor_help.cpp editor/node_dock.cpp
msgid "Signals"
msgstr "সংকেতসমূহ"
@@ -808,12 +565,25 @@ msgstr "ফেবরিট/পà§à¦°à¦¿à¦¯à¦¼-সমূহ:"
msgid "Recent:"
msgstr "সামà§à¦ªà§à¦°à¦¤à¦¿à¦•:"
+#: editor/create_dialog.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/quick_open.cpp editor/settings_config_dialog.cpp
+msgid "Search:"
+msgstr "অনà§à¦¸à¦¨à§à¦§à¦¾à¦¨ করà§à¦¨:"
+
#: editor/create_dialog.cpp editor/editor_help.cpp
#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/quick_open.cpp
msgid "Matches:"
msgstr "মিলসমূহ:"
+#: editor/create_dialog.cpp editor/editor_help.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/property_selector.cpp
+#: editor/script_editor_debugger.cpp
+msgid "Description:"
+msgstr "বরà§à¦£à¦¨à¦¾:"
+
#: editor/dependency_editor.cpp
msgid "Search Replacement For:"
msgstr "à¦à¦° জনà§à¦¯ পà§à¦°à¦¤à¦¿à¦¸à§à¦¥à¦¾à¦ªà¦•à§‡à¦° অনà§à¦¸à¦¨à§à¦§à¦¾à¦¨ করà§à¦¨:"
@@ -873,6 +643,10 @@ msgid "Owners Of:"
msgstr "সà§à¦¬à¦¤à§à¦¬à¦¾à¦§à¦¿à¦•à¦¾à¦°à§€à¦¸à¦®à§‚হ:"
#: editor/dependency_editor.cpp
+msgid "Remove selected files from the project? (no undo)"
+msgstr "নিরà§à¦¬à¦¾à¦šà¦¿à¦¤ ফাইলসমূহ পà§à¦°à¦•à¦²à§à¦ª হতে অপসারণ করবেন? (অফেরৎযোগà§à¦¯)"
+
+#: editor/dependency_editor.cpp
msgid ""
"The files being removed are required by other resources in order for them to "
"work.\n"
@@ -883,8 +657,8 @@ msgstr ""
"তবà§à¦“ তাদের অপসারণ করবেন? (অফেরৎযোগà§à¦¯)"
#: editor/dependency_editor.cpp
-msgid "Remove selected files from the project? (no undo)"
-msgstr "নিরà§à¦¬à¦¾à¦šà¦¿à¦¤ ফাইলসমূহ পà§à¦°à¦•à¦²à§à¦ª হতে অপসারণ করবেন? (অফেরৎযোগà§à¦¯)"
+msgid "Cannot remove:\n"
+msgstr ""
#: editor/dependency_editor.cpp
msgid "Error loading:"
@@ -951,11 +725,6 @@ msgstr ""
#: editor/editor_about.cpp
#, fuzzy
-msgid "Authors"
-msgstr "লেখক:"
-
-#: editor/editor_about.cpp
-#, fuzzy
msgid "Project Founders"
msgstr "পà§à¦°à¦•à¦²à§à¦ª মà§à¦¯à¦¾à¦¨à§‡à¦œà¦¾à¦°"
@@ -972,6 +741,40 @@ msgid "Developers"
msgstr ""
#: editor/editor_about.cpp
+#, fuzzy
+msgid "Authors"
+msgstr "লেখক:"
+
+#: editor/editor_about.cpp
+msgid "Platinum Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Gold Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Mini Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Gold Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Silver Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+#, fuzzy
+msgid "Bronze Donors"
+msgstr "কà§à¦²à§‹à¦¨ করে নীচে নিন"
+
+#: editor/editor_about.cpp
+msgid "Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
msgid "License"
msgstr ""
@@ -1015,6 +818,16 @@ msgid "Package Installed Successfully!"
msgstr "পà§à¦¯à¦¾à¦•à§‡à¦œ ইনà§à¦¸à¦Ÿà¦² সফল হয়েছে!"
#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Success!"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/project_manager.cpp
+msgid "Install"
+msgstr "ইনà§à¦¸à¦Ÿà¦²"
+
+#: editor/editor_asset_installer.cpp
#, fuzzy
msgid "Package Installer"
msgstr "পà§à¦¯à¦¾à¦•à§‡à¦œ ইনà§à¦¸à¦Ÿà¦² সফল হয়েছে!"
@@ -1068,11 +881,6 @@ msgid "Audio Bus, Drag and Drop to rearrange."
msgstr ""
#: editor/editor_audio_buses.cpp
-#, fuzzy
-msgid "Bus options"
-msgstr "ডিবাগের সিদà§à¦§à¦¾à¦¨à§à¦¤à¦¸à¦®à§‚হ"
-
-#: editor/editor_audio_buses.cpp
msgid "Solo"
msgstr ""
@@ -1084,6 +892,11 @@ msgstr ""
msgid "Bypass"
msgstr ""
+#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Bus options"
+msgstr "ডিবাগের সিদà§à¦§à¦¾à¦¨à§à¦¤à¦¸à¦®à§‚হ"
+
#: editor/editor_audio_buses.cpp editor/plugins/tile_map_editor_plugin.cpp
#: editor/scene_tree_dock.cpp
msgid "Duplicate"
@@ -1091,6 +904,11 @@ msgstr "পà§à¦°à¦¤à¦¿à¦²à¦¿à¦ªà¦¿"
#: editor/editor_audio_buses.cpp
#, fuzzy
+msgid "Reset Volume"
+msgstr "সমà§à¦ªà§à¦°à¦¸à¦¾à¦°à¦¨/সংকোচন অপসারণ করà§à¦¨ (রিসেট জà§à¦®à§)"
+
+#: editor/editor_audio_buses.cpp
+#, fuzzy
msgid "Delete Effect"
msgstr "নিরà§à¦¬à¦¾à¦šà¦¿à¦¤ সমূহ অপসারণ করà§à¦¨"
@@ -1115,6 +933,11 @@ msgstr "অà§à¦¯à¦¾à¦¨à¦¿à¦®à§‡à¦¶à¦¨ পà§à¦°à¦¤à¦¿à¦²à¦¿à¦ªà¦¿ করà§à¦¨"
#: editor/editor_audio_buses.cpp
#, fuzzy
+msgid "Reset Bus Volume"
+msgstr "সমà§à¦ªà§à¦°à¦¸à¦¾à¦°à¦¨/সংকোচন অপসারণ করà§à¦¨ (রিসেট জà§à¦®à§)"
+
+#: editor/editor_audio_buses.cpp
+#, fuzzy
msgid "Move Audio Bus"
msgstr "পà§à¦°à¦•à§à¦°à¦¿à¦¯à¦¼à¦¾ সà§à¦¥à¦¾à¦¨à¦¾à¦¨à§à¦¤à¦° করà§à¦¨"
@@ -1151,7 +974,8 @@ msgstr "%s সংযà§à¦•à§à¦¤ করà§à¦¨"
msgid "Create a new Bus Layout."
msgstr "নতà§à¦¨ রিসোরà§à¦¸ তৈরি করà§à¦¨"
-#: editor/editor_audio_buses.cpp editor/script_create_dialog.cpp
+#: editor/editor_audio_buses.cpp editor/property_editor.cpp
+#: editor/script_create_dialog.cpp
msgid "Load"
msgstr "লোড"
@@ -1249,7 +1073,7 @@ msgid "Rearrange Autoloads"
msgstr "Autoload সমূহ পà§à¦¨à¦°à§à¦¬à¦¿à¦¨à§à¦¯à¦¸à§à¦¤ করà§à¦¨"
#: editor/editor_autoload_settings.cpp editor/editor_file_dialog.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp scene/gui/file_dialog.cpp
+#: scene/gui/file_dialog.cpp
msgid "Path:"
msgstr "পথ:"
@@ -1257,9 +1081,7 @@ msgstr "পথ:"
msgid "Node Name:"
msgstr "নোডের নাম:"
-#: editor/editor_autoload_settings.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp editor/project_manager.cpp
+#: editor/editor_autoload_settings.cpp editor/project_manager.cpp
msgid "Name"
msgstr "নাম"
@@ -1293,18 +1115,19 @@ msgid "Choose a Directory"
msgstr "à¦à¦•à¦Ÿà¦¿ সà§à¦¥à¦¾à¦¨ পছনà§à¦¦ করà§à¦¨"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Create Folder"
msgstr "ফোলà§à¦¡à¦¾à¦° তৈরি করà§à¦¨"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: editor/editor_plugin_settings.cpp editor/plugins/theme_editor_plugin.cpp
-#: editor/project_export.cpp scene/gui/file_dialog.cpp
+#: editor/editor_plugin_settings.cpp editor/filesystem_dock.cpp
+#: editor/plugins/theme_editor_plugin.cpp editor/project_export.cpp
+#: scene/gui/file_dialog.cpp
msgid "Name:"
msgstr "নাম:"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Could not create folder."
msgstr "ফোলà§à¦¡à¦¾à¦° তৈরী করা সমà§à¦­à¦¬ হয়নি।"
@@ -1324,30 +1147,6 @@ msgstr "পà§à¦¯à¦¾à¦•/গà§à¦šà§à¦›à¦¿à¦¤ করা"
msgid "Template file not found:\n"
msgstr ""
-#: editor/editor_export.cpp
-msgid "Added:"
-msgstr "সংযোজিত:"
-
-#: editor/editor_export.cpp
-msgid "Removed:"
-msgstr "অপসারিত:"
-
-#: editor/editor_export.cpp
-msgid "Error saving atlas:"
-msgstr "à¦à¦Ÿà¦²à¦¾à¦¸/মানচিতà§à¦°à¦¾à¦¬à¦²à§€ সংরকà§à¦·à¦£à§‡ সমসà§à¦¯à¦¾ হয়েছে:"
-
-#: editor/editor_export.cpp
-msgid "Could not save atlas subtexture:"
-msgstr "à¦à¦Ÿà¦²à¦¾à¦¸/মানচিতà§à¦°à¦¾à¦¬à¦²à§€à¦° উপ-গঠনবিনà§à¦¯à¦¾à¦¸ (subtexture) সংরকà§à¦·à¦£ অসমরà§à¦¥ হয়েছে:"
-
-#: editor/editor_export.cpp
-msgid "Exporting for %s"
-msgstr "%s à¦à¦° জনà§à¦¯ à¦à¦•à§à¦¸à¦ªà§‹à¦°à§à¦Ÿ (export) হচà§à¦›à§‡"
-
-#: editor/editor_export.cpp
-msgid "Setting Up.."
-msgstr "সà§à¦¥à¦¾à¦ªà¦¿à¦¤/বিনà§à¦¯à¦¸à§à¦¤ হচà§à¦›à§‡.."
-
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "File Exists, Overwrite?"
msgstr "à¦à¦•à¦‡ নামের ফাইল উপসà§à¦¥à¦¿à¦¤, তা মà§à¦›à§‡ লিখবেন?"
@@ -1432,6 +1231,11 @@ msgstr "ফেবরিট/পà§à¦°à¦¿à¦¯à¦¼à¦•à§‡ উপরের দিকে
msgid "Move Favorite Down"
msgstr "ফেবরিট/পà§à¦°à¦¿à¦¯à¦¼à¦•à§‡ নিচের দিকে নামান"
+#: editor/editor_file_dialog.cpp
+#, fuzzy
+msgid "Go to parent folder"
+msgstr "ফোলà§à¦¡à¦¾à¦° তৈরী করা সমà§à¦­à¦¬ হয়নি।"
+
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Directories & Files:"
msgstr "পথ à¦à¦¬à¦‚ ফাইল:"
@@ -1446,10 +1250,6 @@ msgid "File:"
msgstr "ফাইল:"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
-msgid "Filter:"
-msgstr "ফিলà§à¦Ÿà¦¾à¦°:"
-
-#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Must use a valid extension."
msgstr "à¦à¦•à¦Ÿà¦¿ কারà§à¦¯à¦•à¦° à¦à¦•à§à¦¸à¦Ÿà§‡à¦¨à¦¶à¦¨ বà§à¦¯à¦¬à¦¹à¦¾à¦° করা আবশà§à¦¯à¦•à¥¤"
@@ -1475,6 +1275,10 @@ msgstr "কà§à¦²à¦¾à¦¸à§‡à¦° তালিকা:"
msgid "Search Classes"
msgstr "কà§à¦²à¦¾à¦¸à§‡à¦° অনà§à¦¸à¦¨à§à¦§à¦¾à¦¨ করà§à¦¨"
+#: editor/editor_help.cpp editor/plugins/spatial_editor_plugin.cpp
+msgid "Top"
+msgstr "শীরà§à¦·"
+
#: editor/editor_help.cpp editor/property_editor.cpp
msgid "Class:"
msgstr "কà§à¦²à¦¾à¦¸:"
@@ -1491,15 +1295,30 @@ msgstr "গৃহীত হয়েছে:"
msgid "Brief Description:"
msgstr "সংকà§à¦·à¦¿à¦ªà§à¦¤ বরà§à¦£à¦¨à¦¾:"
+#: editor/editor_help.cpp
+#, fuzzy
+msgid "Members"
+msgstr "সদসà§à¦¯à¦—ণ (Members):"
+
#: editor/editor_help.cpp modules/visual_script/visual_script_editor.cpp
msgid "Members:"
msgstr "সদসà§à¦¯à¦—ণ (Members):"
#: editor/editor_help.cpp
+#, fuzzy
+msgid "Public Methods"
+msgstr "সরà§à¦¬à¦œà¦¨à§€à¦¨/পà§à¦°à¦•à¦¾à¦¶à§à¦¯ মেথডসমূহ:"
+
+#: editor/editor_help.cpp
msgid "Public Methods:"
msgstr "সরà§à¦¬à¦œà¦¨à§€à¦¨/পà§à¦°à¦•à¦¾à¦¶à§à¦¯ মেথডসমূহ:"
#: editor/editor_help.cpp
+#, fuzzy
+msgid "GUI Theme Items"
+msgstr "GUI থিম à¦à¦° বসà§à¦¤à§à¦¸à¦®à§‚হ:"
+
+#: editor/editor_help.cpp
msgid "GUI Theme Items:"
msgstr "GUI থিম à¦à¦° বসà§à¦¤à§à¦¸à¦®à§‚হ:"
@@ -1509,6 +1328,11 @@ msgstr "সিগনà§à¦¯à¦¾à¦²à¦¸/সংকেতসমূহ:"
#: editor/editor_help.cpp
#, fuzzy
+msgid "Enumerations"
+msgstr "অà§à¦¯à¦¾à¦¨à¦¿à¦®à§‡à¦¶à¦¨à¦¸à¦®à§‚হ"
+
+#: editor/editor_help.cpp
+#, fuzzy
msgid "Enumerations:"
msgstr "অà§à¦¯à¦¾à¦¨à¦¿à¦®à§‡à¦¶à¦¨à¦¸à¦®à§‚হ"
@@ -1517,18 +1341,50 @@ msgid "enum "
msgstr ""
#: editor/editor_help.cpp
+#, fuzzy
+msgid "Constants"
+msgstr "ধà§à¦°à§à¦¬à¦•à¦¸à¦®à§‚হ:"
+
+#: editor/editor_help.cpp
msgid "Constants:"
msgstr "ধà§à¦°à§à¦¬à¦•à¦¸à¦®à§‚হ:"
#: editor/editor_help.cpp
+#, fuzzy
+msgid "Description"
+msgstr "বরà§à¦£à¦¨à¦¾:"
+
+#: editor/editor_help.cpp
+#, fuzzy
+msgid "Properties"
+msgstr "পà§à¦°à§‹à¦ªà¦¾à¦°à§à¦Ÿà¦¿-সমূহ:"
+
+#: editor/editor_help.cpp
msgid "Property Description:"
msgstr "মান/পà§à¦°à§‹à¦ªà¦¾à¦°à§à¦Ÿà¦¿à¦° বরà§à¦£à¦¨à¦¾:"
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this property. Please help us by "
+"[color=$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+
+#: editor/editor_help.cpp
+#, fuzzy
+msgid "Methods"
+msgstr "মেথডের তালিকা:"
+
+#: editor/editor_help.cpp
msgid "Method Description:"
msgstr "মেথডের বরà§à¦£à§à¦¨à¦¾:"
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this method. Please help us by [color="
+"$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Search Text"
msgstr "টেকà§à¦¸à¦Ÿ অনà§à¦¸à¦¨à§à¦§à¦¾à¦¨ করà§à¦¨"
@@ -1538,24 +1394,21 @@ msgid "Output:"
msgstr " আউটপà§à¦Ÿ/ফলাফল:"
#: editor/editor_log.cpp editor/plugins/animation_tree_editor_plugin.cpp
-#: editor/plugins/rich_text_editor_plugin.cpp editor/property_editor.cpp
-#: editor/script_editor_debugger.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/property_editor.cpp editor/script_editor_debugger.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Clear"
msgstr "পরিসà§à¦•à¦¾à¦° করà§à¦¨/কà§à¦²à§€à§Ÿà¦¾à¦°"
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Error saving resource!"
msgstr "রিসোরà§à¦¸ সংরকà§à¦·à¦£à§‡ সমসà§à¦¯à¦¾ হয়েছে!"
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Save Resource As.."
msgstr "রিসোরà§à¦¸ à¦à¦‡à¦°à§‚পে সংরকà§à¦·à¦£ করà§à¦¨.."
-#: editor/editor_node.cpp editor/export_template_manager.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "I see.."
msgstr "বà§à¦à¦²à¦¾à¦®.."
@@ -1572,6 +1425,30 @@ msgid "Error while saving."
msgstr "সংরকà§à¦·à¦£à§‡à¦° সময় সমসà§à¦¯à¦¾ হয়েছে।"
#: editor/editor_node.cpp
+#, fuzzy
+msgid "Can't open '%s'."
+msgstr "'..' তে পরিচালনা করা সমà§à¦­à¦¬ নয়"
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Error while parsing '%s'."
+msgstr "সংরকà§à¦·à¦£à§‡à¦° সময় সমসà§à¦¯à¦¾ হয়েছে।"
+
+#: editor/editor_node.cpp
+msgid "Unexpected end of file '%s'."
+msgstr ""
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Missing '%s' or its dependencies."
+msgstr "'%s' দৃশà§à¦¯à¦Ÿà¦¿à¦° অসংলগà§à¦¨ নিরà§à¦­à¦°à¦¤à¦¾ রয়েছে:"
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Error while loading '%s'."
+msgstr "সংরকà§à¦·à¦£à§‡à¦° সময় সমসà§à¦¯à¦¾ হয়েছে।"
+
+#: editor/editor_node.cpp
msgid "Saving Scene"
msgstr "দৃশà§à¦¯ সংরকà§à¦·à¦¿à¦¤ হচà§à¦›à§‡"
@@ -1632,6 +1509,33 @@ msgid "Restored default layout to base settings."
msgstr "সাধারণ লেআউট/নকশা আদি সেটিংসে পà§à¦°à¦¤à§à¦¯à¦¾à¦¬à¦°à§à¦¤à¦¿à¦¤ হয়েছে।"
#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was imported, so it's not editable.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was instanced or inherited.\n"
+"Changes to it will not be kept when saving the current scene."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource was imported, so it's not editable. Change its settings in the "
+"import panel and then re-import."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This scene was imported, so changes to it will not be kept.\n"
+"Instancing it or inheriting will allow making changes to it.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Copy Params"
msgstr "মানসমূহ পà§à¦°à¦¤à¦¿à¦²à¦¿à¦ªà¦¿/কপি করà§à¦¨"
@@ -1810,23 +1714,35 @@ msgid "Save changes the following scene(s) before opening Project Manager?"
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"This option is deprecated. Situations where refresh must be forced are now "
+"considered a bug. Please report."
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Pick a Main Scene"
msgstr "à¦à¦•à¦Ÿà¦¿ মà§à¦–à§à¦¯ দৃশà§à¦¯ মনোনীত করà§à¦¨"
#: editor/editor_node.cpp
-msgid "Unable to enable addon plugin at: '"
+msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr ""
#: editor/editor_node.cpp
-msgid "' parsing of config failed."
+msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/"
+#, fuzzy
+msgid "Unable to load addon script from path: '%s'."
+msgstr "%s হতে সà§à¦•à§à¦°à¦¿à¦ªà§à¦Ÿ তà§à¦²à¦¤à§‡/লোডে সমসà§à¦¯à¦¾ হয়েছে"
+
+#: editor/editor_node.cpp
+msgid ""
+"Unable to load addon script from path: '%s' Base type is not EditorPlugin."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to load addon script from path: '"
+msgid "Unable to load addon script from path: '%s' Script is not in tool mode."
msgstr ""
#: editor/editor_node.cpp
@@ -1836,7 +1752,7 @@ msgid ""
msgstr ""
#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/scene_tree_dock.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Ugh"
msgstr "আহà§â€Œ"
@@ -1849,14 +1765,15 @@ msgstr ""
"(Import)' বà§à¦¯à¦¬à¦¹à¦¾à¦° করে দৃশà§à¦¯à¦Ÿà¦¿ খà§à¦²à§à¦¨, তারপর তা পà§à¦°à¦•à¦²à§à¦ªà§‡à¦° পথের ভিতরে সংরকà§à¦·à¦£ করà§à¦¨à¥¤"
#: editor/editor_node.cpp
-msgid "Error loading scene."
-msgstr "দৃশà§à¦¯ লোডে সমসà§à¦¯à¦¾ হয়েছে।"
-
-#: editor/editor_node.cpp
msgid "Scene '%s' has broken dependencies:"
msgstr "'%s' দৃশà§à¦¯à¦Ÿà¦¿à¦° অসংলগà§à¦¨ নিরà§à¦­à¦°à¦¤à¦¾ রয়েছে:"
#: editor/editor_node.cpp
+#, fuzzy
+msgid "Clear Recent Scenes"
+msgstr "বোনà§â€Œ/হাড় পরিষà§à¦•à¦¾à¦° করà§à¦¨"
+
+#: editor/editor_node.cpp
msgid "Save Layout"
msgstr "লেআউট/নকশা সংরকà§à¦·à¦£ করà§à¦¨"
@@ -1890,7 +1807,7 @@ msgstr "বিকà§à¦·à§‡à¦ª-হীন মোড"
msgid "Toggle distraction-free mode."
msgstr "বিকà§à¦·à§‡à¦ª-হীন মোড"
-#: editor/editor_node.cpp editor/io_plugins/editor_scene_import_plugin.cpp
+#: editor/editor_node.cpp
msgid "Scene"
msgstr "দৃশà§à¦¯"
@@ -2134,6 +2051,10 @@ msgstr ""
msgid "Issue Tracker"
msgstr ""
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+msgid "Community"
+msgstr "কমিউনিটি/যৌথ-সামাজিক উৎস"
+
#: editor/editor_node.cpp
msgid "About"
msgstr "সমà§à¦¬à¦¨à§à¦§à§‡/সমà§à¦ªà¦°à§à¦•à§‡"
@@ -2142,7 +2063,7 @@ msgstr "সমà§à¦¬à¦¨à§à¦§à§‡/সমà§à¦ªà¦°à§à¦•à§‡"
msgid "Play the project."
msgstr "পà§à¦°à¦•à¦²à§à¦ªà¦Ÿà¦¿ চালান।"
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Play"
msgstr "চালান"
@@ -2158,7 +2079,7 @@ msgstr "দৃশà§à¦¯à¦•à§‡ বিরতি দিন"
msgid "Stop the scene."
msgstr "দৃশà§à¦¯à¦Ÿà¦¿à¦•à§‡ থামান।"
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Stop"
msgstr "থামান"
@@ -2231,6 +2152,16 @@ msgid "Object properties."
msgstr "বসà§à¦¤à§à¦° বৈশিষà§à¦Ÿà§à¦¯à¦¸à¦®à§‚হ।"
#: editor/editor_node.cpp
+#, fuzzy
+msgid "Changes may be lost!"
+msgstr "ছবির গà§à¦°à§à¦ª পরিবরà§à¦¤à¦¨ করà§à¦¨"
+
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Import"
+msgstr "ইমà§à¦ªà§‹à¦°à§à¦Ÿ"
+
+#: editor/editor_node.cpp
msgid "FileSystem"
msgstr "ফাইলসিসà§à¦Ÿà§‡à¦®"
@@ -2246,14 +2177,6 @@ msgstr "আউটপà§à¦Ÿ/ফলাফল"
msgid "Don't Save"
msgstr ""
-#: editor/editor_node.cpp editor/editor_reimport_dialog.cpp
-msgid "Re-Import"
-msgstr "পà§à¦¨-ইমà§à¦ªà§‹à¦°à§à¦Ÿ"
-
-#: editor/editor_node.cpp editor/editor_plugin_settings.cpp
-msgid "Update"
-msgstr "হালনাগাদ"
-
#: editor/editor_node.cpp
msgid "Import Templates From ZIP File"
msgstr "ZIP ফাইল হতে টেমপà§à¦²à§‡à¦Ÿ-সমূহ ইমà§à¦ªà§‹à¦°à§à¦Ÿ করà§à¦¨"
@@ -2321,11 +2244,29 @@ msgstr "à¦à¦¡à¦¿à¦Ÿà¦°à§‡ খà§à¦²à§à¦¨"
msgid "Open the previous Editor"
msgstr "à¦à¦¡à¦¿à¦Ÿà¦°à§‡ খà§à¦²à§à¦¨"
+#: editor/editor_plugin.cpp
+#, fuzzy
+msgid "Creating Mesh Previews"
+msgstr "মেস লাইবà§à¦°à§‡à¦°à¦¿ তৈরি হচà§à¦›à§‡"
+
+#: editor/editor_plugin.cpp
+msgid "Thumbnail.."
+msgstr "থামà§à¦¬à¦¨à§‡à¦‡à¦².."
+
#: editor/editor_plugin_settings.cpp
msgid "Installed Plugins:"
msgstr "ইনà§à¦¸à¦Ÿà¦²-কৃত পà§à¦²à¦¾à¦—ইন-সমূহ:"
#: editor/editor_plugin_settings.cpp
+msgid "Update"
+msgstr "হালনাগাদ"
+
+#: editor/editor_plugin_settings.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Version:"
+msgstr "সংসà§à¦•à¦°à¦£:"
+
+#: editor/editor_plugin_settings.cpp
msgid "Author:"
msgstr "লেখক:"
@@ -2358,7 +2299,8 @@ msgid "Frame %"
msgstr "ফà§à¦°à§‡à¦® %"
#: editor/editor_profiler.cpp
-msgid "Fixed Frame %"
+#, fuzzy
+msgid "Physics Frame %"
msgstr "সà§à¦¥à¦¿à¦°/বদà§à¦§ ফà§à¦°à§‡à¦® %"
#: editor/editor_profiler.cpp editor/script_editor_debugger.cpp
@@ -2377,26 +2319,6 @@ msgstr "সà§à¦¬à§€à¦¯à¦¼"
msgid "Frame #:"
msgstr "ফà§à¦°à§‡à¦® #:"
-#: editor/editor_reimport_dialog.cpp
-msgid "Please wait for scan to complete."
-msgstr "সà§à¦•à§à¦¯à¦¾à¦¨ সমà§à¦ªà¦¨à§à¦¨ হওয়া পরà§à¦¯à¦¨à§à¦¤ অনà§à¦—à§à¦°à¦¹ করে অপেকà§à¦·à¦¾ করà§à¦¨à¥¤"
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Current scene must be saved to re-import."
-msgstr "পà§à¦¨à¦°à¦¾à§Ÿ-ইমà§à¦ªà§‹à¦°à§à¦Ÿ করতে বরà§à¦¤à¦®à¦¾à¦¨ দৃশà§à¦¯à¦Ÿà¦¿à¦•à§‡ অবশà§à¦¯à¦‡ সংরকà§à¦·à¦£ করতে হবে।"
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Save & Re-Import"
-msgstr "সংরকà§à¦·à¦£ à¦à¦¬à¦‚ পà§à¦¨-ইমà§à¦ªà§‹à¦°à§à¦Ÿ করà§à¦¨"
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Importing"
-msgstr "পà§à¦¨à¦°à¦¾à§Ÿ ইমà§à¦ªà§‹à¦°à§à¦Ÿ হচà§à¦›à§‡"
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Import Changed Resources"
-msgstr "পà§à¦¨-ইমà§à¦ªà§‹à¦°à§à¦Ÿà§‡ রিসোরà§à¦¸-সমূহ পরিবরà§à¦¤à¦¿à¦¤ হয়েছে"
-
#: editor/editor_run_native.cpp
msgid "Select device from the list"
msgstr ""
@@ -2513,10 +2435,6 @@ msgid "Importing:"
msgstr "ইমà§à¦ªà§‹à¦°à§à¦Ÿ হচà§à¦›à§‡:"
#: editor/export_template_manager.cpp
-msgid "Loading Export Templates"
-msgstr "à¦à¦•à§à¦¸à¦ªà§‹à¦°à§à¦Ÿ টেমপà§à¦²à§‡à¦Ÿà¦¸à¦®à§‚হ লোড হচà§à¦›à§‡"
-
-#: editor/export_template_manager.cpp
#, fuzzy
msgid "Current Version:"
msgstr "বরà§à¦¤à¦®à¦¾à¦¨ দৃশà§à¦¯"
@@ -2557,11 +2475,18 @@ msgid "Cannot navigate to '"
msgstr ""
#: editor/filesystem_dock.cpp
-#, fuzzy
+msgid "View items as a grid of thumbnails"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "View items as a list"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
msgid ""
"\n"
-"Status: Needs Re-Import"
-msgstr "সংরকà§à¦·à¦£ à¦à¦¬à¦‚ পà§à¦¨-ইমà§à¦ªà§‹à¦°à§à¦Ÿ করà§à¦¨"
+"Status: Import of file failed. Please fix file and reimport manually."
+msgstr ""
#: editor/filesystem_dock.cpp
#, fuzzy
@@ -2571,46 +2496,57 @@ msgid ""
msgstr "উৎস:"
#: editor/filesystem_dock.cpp
-msgid "Same source and destination files, doing nothing."
-msgstr "ফাইলà§à¦—à§à¦²à§‹à¦° à¦à¦•à¦‡ উৎস à¦à¦¬à¦‚ গনà§à¦¤à¦¬à§à¦¯à¦¸à§à¦¥à¦¾à¦¨, কিছà§à¦‡ করা হচà§à¦›à§‡ না।"
+#, fuzzy
+msgid "Cannot move/rename resources root."
+msgstr "ফনà§à¦Ÿà§‡à¦° উৎস লোড/পà§à¦°à¦¸à§‡à¦¸ করা সমà§à¦­à¦¬ হচà§à¦›à§‡ না।"
#: editor/filesystem_dock.cpp
-msgid "Target file exists, can't overwrite. Delete first."
-msgstr ""
+#, fuzzy
+msgid "Cannot move a folder into itself.\n"
+msgstr "ফাইলকে তার নিজের উপরেই ইমà§à¦ªà§‹à¦°à§à¦Ÿ করা সমà§à¦­à¦¬ নয়:"
#: editor/filesystem_dock.cpp
-msgid "Same source and destination paths, doing nothing."
-msgstr "পথগà§à¦²à§‹à¦° à¦à¦•à¦‡ উৎস à¦à¦¬à¦‚ গনà§à¦¤à¦¬à§à¦¯à¦¸à§à¦¥à¦¾à¦¨, কিছà§à¦‡ করা হচà§à¦›à§‡ না।"
+#, fuzzy
+msgid "Error moving:\n"
+msgstr "ইমà§à¦ªà§‹à¦°à§à¦Ÿà§‡ সমসà§à¦¯à¦¾ হয়েছে:"
#: editor/filesystem_dock.cpp
-msgid "Can't move directories to within themselves."
-msgstr "সà§à¦¥à¦¾à¦¨à¦¸à¦®à§‚হকে তাদের মাà¦à§‡à¦‡ সà§à¦¥à¦¾à¦¨à¦¾à¦¨à§à¦¤à¦° করা সমà§à¦­à¦¬ নয়।"
+#, fuzzy
+msgid "Unable to update dependencies:\n"
+msgstr "'%s' দৃশà§à¦¯à¦Ÿà¦¿à¦° অসংলগà§à¦¨ নিরà§à¦­à¦°à¦¤à¦¾ রয়েছে:"
#: editor/filesystem_dock.cpp
-msgid "Can't rename deps for:\n"
+msgid "No name provided"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "Provided name contains invalid characters"
msgstr ""
#: editor/filesystem_dock.cpp
#, fuzzy
-msgid "Error moving file:\n"
-msgstr "ছবি লোডে সমসà§à¦¯à¦¾ হয়েছে:"
+msgid "No name provided."
+msgstr "পà§à¦¨à¦ƒà¦¨à¦¾à¦®à¦•à¦°à¦£ করà§à¦¨ অথবা সরান.."
#: editor/filesystem_dock.cpp
#, fuzzy
-msgid "Error moving dir:\n"
-msgstr "ইমà§à¦ªà§‹à¦°à§à¦Ÿà§‡ সমসà§à¦¯à¦¾ হয়েছে:"
+msgid "Name contains invalid characters."
+msgstr "গà§à¦°à¦¹à¦¨à¦¯à§‹à¦—à§à¦¯ অকà§à¦·à¦°à¦¸à¦®à§‚হ:"
#: editor/filesystem_dock.cpp
-msgid "Can't operate on '..'"
-msgstr "'..' তে পরিচালনা করা সমà§à¦­à¦¬ নয়"
+#, fuzzy
+msgid "A file or folder with this name already exists."
+msgstr "গà§à¦°à§à¦ªà§‡à¦° নাম ইতিমধà§à¦¯à§‡à¦‡ আছে!"
#: editor/filesystem_dock.cpp
-msgid "Pick New Name and Location For:"
-msgstr "নতà§à¦¨ নাম à¦à¦¬à¦‚ অবসà§à¦¥à¦¾à¦¨ বাছাই করà§à¦¨:"
+#, fuzzy
+msgid "Renaming file:"
+msgstr "চলক/ভেরিয়েবল-à¦à¦° নামানà§à¦¤à¦° করà§à¦¨"
#: editor/filesystem_dock.cpp
-msgid "No files selected!"
-msgstr "কোনো ফাইল নিরà§à¦¬à¦¾à¦šà¦¿à¦¤ হয়নি!"
+#, fuzzy
+msgid "Renaming folder:"
+msgstr "নোড পà§à¦¨à¦ƒà¦¨à¦¾à¦®à¦•à¦°à¦£ করà§à¦¨"
#: editor/filesystem_dock.cpp
#, fuzzy
@@ -2622,40 +2558,38 @@ msgid "Collapse all"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Show In File Manager"
-msgstr "ফাইল-মà§à¦¯à¦¾à¦¨à§‡à¦œà¦¾à¦°à§‡ দেখà§à¦¨"
-
-#: editor/filesystem_dock.cpp
-msgid "Instance"
-msgstr "ইনসà§à¦Ÿà§à¦¯à¦¾à¦¨à§à¦¸"
+msgid "Copy Path"
+msgstr "পথ পà§à¦°à¦¤à¦¿à¦²à¦¿à¦ªà¦¿/কপি করà§à¦¨"
#: editor/filesystem_dock.cpp
-msgid "Edit Dependencies.."
-msgstr "নিরà§à¦­à¦°à¦¤à¦¾à¦¸à¦®à§‚হ সমà§à¦ªà¦¾à¦¦à¦¨ করà§à¦¨.."
+#, fuzzy
+msgid "Rename.."
+msgstr "পà§à¦¨à¦ƒà¦¨à¦¾à¦®à¦•à¦°à¦£ করà§à¦¨"
#: editor/filesystem_dock.cpp
-msgid "View Owners.."
-msgstr "সà§à¦¬à¦¤à§à¦¬à¦¾à¦§à¦¿à¦•à¦¾à¦°à§€à¦¦à§‡à¦° দেখà§à¦¨.."
+msgid "Move To.."
+msgstr "à¦à¦–ানে সরান.."
#: editor/filesystem_dock.cpp
-msgid "Copy Path"
-msgstr "পথ পà§à¦°à¦¤à¦¿à¦²à¦¿à¦ªà¦¿/কপি করà§à¦¨"
+#, fuzzy
+msgid "New Folder.."
+msgstr "ফোলà§à¦¡à¦¾à¦° তৈরি করà§à¦¨"
#: editor/filesystem_dock.cpp
-msgid "Rename or Move.."
-msgstr "পà§à¦¨à¦ƒà¦¨à¦¾à¦®à¦•à¦°à¦£ করà§à¦¨ অথবা সরান.."
+msgid "Show In File Manager"
+msgstr "ফাইল-মà§à¦¯à¦¾à¦¨à§‡à¦œà¦¾à¦°à§‡ দেখà§à¦¨"
#: editor/filesystem_dock.cpp
-msgid "Move To.."
-msgstr "à¦à¦–ানে সরান.."
+msgid "Instance"
+msgstr "ইনসà§à¦Ÿà§à¦¯à¦¾à¦¨à§à¦¸"
#: editor/filesystem_dock.cpp
-msgid "Info"
-msgstr "তথà§à¦¯"
+msgid "Edit Dependencies.."
+msgstr "নিরà§à¦­à¦°à¦¤à¦¾à¦¸à¦®à§‚হ সমà§à¦ªà¦¾à¦¦à¦¨ করà§à¦¨.."
#: editor/filesystem_dock.cpp
-msgid "Re-Import.."
-msgstr "পà§à¦¨-ইমà§à¦ªà§‹à¦°à§à¦Ÿ.."
+msgid "View Owners.."
+msgstr "সà§à¦¬à¦¤à§à¦¬à¦¾à¦§à¦¿à¦•à¦¾à¦°à§€à¦¦à§‡à¦° দেখà§à¦¨.."
#: editor/filesystem_dock.cpp
msgid "Previous Directory"
@@ -2687,6 +2621,11 @@ msgstr ""
msgid "Move"
msgstr "সরান"
+#: editor/filesystem_dock.cpp editor/plugins/animation_tree_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Rename"
+msgstr "পà§à¦¨à¦ƒà¦¨à¦¾à¦®à¦•à¦°à¦£ করà§à¦¨"
+
#: editor/groups_editor.cpp
msgid "Add to Group"
msgstr "গà§à¦°à§à¦ª/দলে যোগ করà§à¦¨"
@@ -2701,6 +2640,11 @@ msgid "Import as Single Scene"
msgstr "দৃশà§à¦¯ ইমà§à¦ªà§‹à¦°à§à¦Ÿ করা হচà§à¦›à§‡.."
#: editor/import/resource_importer_scene.cpp
+#, fuzzy
+msgid "Import with Separate Animations"
+msgstr "অà§à¦¯à¦¾à¦¨à¦¿à¦®à§‡à¦¶à¦¨à¦¸à¦®à§‚হ ইমà§à¦ªà§‹à¦°à§à¦Ÿ করà§à¦¨.."
+
+#: editor/import/resource_importer_scene.cpp
msgid "Import with Separate Materials"
msgstr ""
@@ -2713,6 +2657,18 @@ msgid "Import with Separate Objects+Materials"
msgstr ""
#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Materials+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Materials+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
#, fuzzy
msgid "Import as Multiple Scenes"
msgstr "3D দৃশà§à¦¯ ইমà§à¦ªà§‹à¦°à§à¦Ÿ করà§à¦¨"
@@ -2722,38 +2678,31 @@ msgid "Import as Multiple Scenes+Materials"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Import Scene"
msgstr "দৃশà§à¦¯ ইমà§à¦ªà§‹à¦°à§à¦Ÿ করà§à¦¨"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Importing Scene.."
msgstr "দৃশà§à¦¯ ইমà§à¦ªà§‹à¦°à§à¦Ÿ করা হচà§à¦›à§‡.."
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Running Custom Script.."
msgstr "সà§à¦¬à¦¨à¦¿à¦°à§à¦®à¦¿à¦¤ সà§à¦•à§à¦°à¦¿à¦ªà§à¦Ÿ চালানো হচà§à¦›à§‡.."
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Couldn't load post-import script:"
msgstr "ইমà§à¦ªà§‹à¦°à§à¦Ÿ-পরবরà§à¦¤à§€ সà§à¦•à§à¦°à¦¿à¦ªà§à¦Ÿ লোড করা সমà§à¦­à¦¬ হয়নি:"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Invalid/broken script for post-import (check console):"
msgstr "ইমà§à¦ªà§‹à¦°à§à¦Ÿ-পরবরà§à¦¤à§€ সà§à¦•à§à¦°à¦¿à¦ªà§à¦Ÿ অকারà§à¦¯à¦•à¦°/তà§à¦°à§à¦Ÿà¦¿à¦ªà§‚রà§à¦£ (কনসোল দেখà§à¦¨):"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Error running post-import script:"
msgstr "ইমà§à¦ªà§‹à¦°à§à¦Ÿ-পরবরà§à¦¤à§€ সà§à¦•à§à¦°à¦¿à¦ªà§à¦Ÿ চালানোয় সমসà§à¦¯à¦¾ হয়েছে:"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Saving.."
msgstr "সংরকà§à¦·à¦¿à¦¤ হচà§à¦›à§‡.."
@@ -2784,590 +2733,56 @@ msgstr "পà§à¦°à¦¿à¦¸à§‡à¦Ÿ.."
msgid "Reimport"
msgstr "পà§à¦¨-ইমà§à¦ªà§‹à¦°à§à¦Ÿ"
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "No bit masks to import!"
-msgstr "ইমà§à¦ªà§‹à¦°à§à¦Ÿ করার জনà§à¦¯ কোনো বিট মাসà§à¦• নেই!"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path is empty."
-msgstr "উদà§à¦¦à§‡à¦¶à§à¦¯à¦¿à¦¤ পথটি খালি।"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must be a complete resource path."
-msgstr "উদà§à¦¦à§‡à¦¶à§à¦¯à¦¿à¦¤ পথটি অবশà§à¦¯à¦‡ à¦à¦•à¦Ÿà¦¿ সমà§à¦ªà§à¦°à§à¦£ রিসোরà§à¦¸ পথ হতে হবে।"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must exist."
-msgstr "উদà§à¦¦à§‡à¦¶à§à¦¯à¦¿à¦¤ পথটি অবশà§à¦¯à¦‡ বিদà§à¦¯à¦®à¦¾à¦¨ হতে হবে।"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Save path is empty!"
-msgstr "সংরকà§à¦·à¦£à§‡à¦° পথটি খালি!"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Import BitMasks"
-msgstr "BitMasks ইমà§à¦ªà§‹à¦°à§à¦Ÿ করà§à¦¨"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s):"
-msgstr "টেকà§à¦¸à¦¾à¦°(সমূহ)-à¦à¦° উৎস:"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Target Path:"
-msgstr "উদà§à¦¦à§‡à¦¶à§à¦¯à¦¿à¦¤ পথ:"
+#: editor/multi_node_edit.cpp
+msgid "MultiNode Set"
+msgstr "মালà§à¦Ÿà¦¿-নোড সà§à¦¥à¦¾à¦ªà¦¨ করà§à¦¨"
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Accept"
-msgstr "গà§à¦°à¦¹à¦£ করà§à¦¨"
+#: editor/node_dock.cpp
+msgid "Groups"
+msgstr "দলসমূহ"
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Bit Mask"
-msgstr "বিট-মাসà§à¦• (Bit Mask)"
+#: editor/node_dock.cpp
+msgid "Select a Node to edit Signals and Groups."
+msgstr "সিগনà§à¦¯à¦¾à¦²-সমূহ à¦à¦¬à¦‚ দলসমূহ সমà§à¦ªà¦¾à¦¦à¦¨ করতে à¦à¦•à¦Ÿà¦¿ নোড নিরà§à¦¬à¦¾à¦šà¦¨ করà§à¦¨à¥¤"
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No source font file!"
-msgstr "ফনà§à¦Ÿà§‡à¦° কোনো উৎস ফাইল নেই!"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create Poly"
+msgstr "Poly তৈরি করà§à¦¨"
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No target font resource!"
-msgstr "ফনà§à¦Ÿà§‡à¦° কোনো উদà§à¦¦à§‡à¦¶à§à¦¯à¦¿à¦¤ রিসোরà§à¦¸ নেই!"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly"
+msgstr "Poly সমà§à¦ªà¦¾à¦¦à¦¨ করà§à¦¨"
-#: editor/io_plugins/editor_font_import_plugin.cpp
+#: editor/plugins/abstract_polygon_2d_editor.cpp
#, fuzzy
-msgid ""
-"Invalid file extension.\n"
-"Please use .font."
-msgstr ""
-"ফাইলের অগà§à¦°à¦¹à¦¨à¦¯à§‹à¦—à§à¦¯ à¦à¦•à§à¦¸à¦Ÿà§‡à¦¨à¦¶à¦¨à¥¤\n"
-"অনà§à¦—à§à¦°à¦¹ করে .fnt বà§à¦¯à¦¬à¦¹à¦¾à¦° করà§à¦¨à¥¤"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Can't load/process source font."
-msgstr "ফনà§à¦Ÿà§‡à¦° উৎস লোড/পà§à¦°à¦¸à§‡à¦¸ করা সমà§à¦­à¦¬ হচà§à¦›à§‡ না।"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Couldn't save font."
-msgstr "ফনà§à¦Ÿ সংরকà§à¦·à¦£ করা সমà§à¦­à¦¬ হয়নি।"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font:"
-msgstr "ফনà§à¦Ÿà§‡à¦° উৎস:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font Size:"
-msgstr "উৎস ফনà§à¦Ÿà§‡à¦° আকার:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Dest Resource:"
-msgstr "রিসোরà§à¦¸à§‡à¦° গনà§à¦¤à¦¬à§à¦¯à¦¸à§à¦¥à¦¾à¦¨:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "The quick brown fox jumps over the lazy dog."
-msgstr ""
-"বাদামী রঙà§à¦—ের দà§à¦°à§à¦¤ শিয়ালটি অলস কà§à¦•à§à¦°à§‡à¦° উপর দিয়ে লাফিয়ে যায় (The quick brown fox "
-"jumps over the lazy dog.)।"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Test:"
-msgstr "পরীকà§à¦·à¦¾:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Options:"
-msgstr "সিদà§à¦§à¦¾à¦¨à§à¦¤à¦¸à¦®à§‚হ (অপশন):"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Font Import"
-msgstr "ফনà§à¦Ÿ ইমà§à¦ªà§‹à¦°à§à¦Ÿ করà§à¦¨"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"This file is already a Godot font file, please supply a BMFont type file "
-"instead."
-msgstr ""
-"à¦à¦‡ ফাইলটি ইতিমধà§à¦¯à§‡à¦‡ à¦à¦•à¦Ÿà¦¿ Godot ফনà§à¦Ÿ ফাইল, পরিবরà§à¦¤à§‡ অনà§à¦—à§à¦°à¦¹ করে BMFont ধরণের ফাইল "
-"পà§à¦°à¦¦à¦¾à¦¨ করà§à¦¨à¥¤"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Failed opening as BMFont file."
-msgstr "BMFont ফাইল খোলা বà§à¦¯à¦°à§à¦¥ হয়েছে।"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error initializing FreeType."
-msgstr "FreeType আরমà§à¦­à§‡ সমসà§à¦¯à¦¾ হয়েছে।"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Unknown font format."
-msgstr "অজানা ধরনের ফনà§à¦Ÿà¥¤"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error loading font."
-msgstr "ফনà§à¦Ÿ তà§à¦²à¦¤à§‡/লোডে সমসà§à¦¯à¦¾ হয়েছে।"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Invalid font size."
-msgstr "ফনà§à¦Ÿà§‡à¦° আকার অগà§à¦°à¦¹à¦¨à¦¯à§‹à¦—à§à¦¯à¥¤"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Invalid font custom source."
-msgstr "সà§à¦¬à¦¨à¦¿à¦°à§à¦®à¦¿à¦¤ ফনà§à¦Ÿà§‡à¦° অগà§à¦°à¦¹à¦¨à¦¯à§‹à¦—à§à¦¯ উৎস।"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/plugins/theme_editor_plugin.cpp
-msgid "Font"
-msgstr "ফনà§à¦Ÿ"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "No meshes to import!"
-msgstr "ইমà§à¦ªà§‹à¦°à§à¦Ÿ করার মতো কোনো মেস নেই!"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Single Mesh Import"
-msgstr "à¦à¦•à¦• মেস ইমà§à¦ªà§‹à¦°à§à¦Ÿ করà§à¦¨"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Source Mesh(es):"
-msgstr "মেস(সমূহ)-à¦à¦° উৎস:"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/plugins/mesh_instance_editor_plugin.cpp
-msgid "Mesh"
-msgstr "মেস"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Surface %d"
-msgstr "পৃষà§à¦ à¦¤à¦² %d"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "No samples to import!"
-msgstr "ইমà§à¦ªà§‹à¦°à§à¦Ÿ করার মতো কোনো নমà§à¦¨à¦¾ নেই!"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Import Audio Samples"
-msgstr "শবà§à¦¦à§‡à¦° নমà§à¦¨à¦¾à¦¸à¦®à§‚হ ইমà§à¦ªà§‹à¦°à§à¦Ÿ করà§à¦¨"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Source Sample(s):"
-msgstr "নমà§à¦¨à¦¾(সমূহ)-à¦à¦° উৎস:"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Audio Sample"
-msgstr "শবà§à¦¦à§‡à¦° নমà§à¦¨à¦¾"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "New Clip"
-msgstr "নতà§à¦¨ কà§à¦²à¦¿à¦ª"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Animation Options"
-msgstr "অà§à¦¯à¦¾à¦¨à¦¿à¦®à§‡à¦¶à¦¨à§‡à¦° সিদà§à¦§à¦¾à¦¨à§à¦¤à¦¸à¦®à§‚হ"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Flags"
-msgstr "পতাকাসমূহ"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Bake FPS:"
-msgstr "সিদà§à¦§ FPS:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Optimizer"
-msgstr "পরিমারà§à¦œà¦•"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Linear Error"
-msgstr "সরà§à¦¬à§‡à¦¾à¦šà§à¦š রৈখিক ভà§à¦²/সমসà§à¦¯à¦¾"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angular Error"
-msgstr "সরà§à¦¬à§‡à¦¾à¦šà§à¦š কৌণিক ভà§à¦²/সমসà§à¦¯à¦¾"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angle"
-msgstr "সরà§à¦¬à§‡à¦¾à¦šà§à¦š কোণ"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Clips"
-msgstr "কà§à¦²à¦¿à¦ªà¦¸à¦®à§‚হ"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Start(s)"
-msgstr "আরমà§à¦­(সমূহ)"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "End(s)"
-msgstr "সমাপà§à¦¤à¦¿(সমূহ)"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Loop"
-msgstr "লà§à¦ª"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Filters"
-msgstr "ফিলà§à¦Ÿà¦¾à¦°à¦¸à¦®à§‚হ"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source path is empty."
-msgstr "উৎসের পথটি খালি।"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't load post-import script."
-msgstr "ইমà§à¦ªà§‹à¦°à§à¦Ÿ-পরবরà§à¦¤à§€ সà§à¦•à§à¦°à¦¿à¦ªà§à¦Ÿ লোড করা সমà§à¦­à¦¬ হয়নি।"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Invalid/broken script for post-import."
-msgstr "ইমà§à¦ªà§‹à¦°à§à¦Ÿ-পরবরà§à¦¤à§€ সà§à¦•à§à¦°à¦¿à¦ªà§à¦Ÿ অকারà§à¦¯à¦•à¦°/তà§à¦°à§à¦Ÿà¦¿à¦ªà§‚রà§à¦£à¥¤"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Error importing scene."
-msgstr "দৃশà§à¦¯ ইমà§à¦ªà§‹à¦°à§à¦Ÿà§‡ সমসà§à¦¯à¦¾ হয়েছে।"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import 3D Scene"
-msgstr "3D দৃশà§à¦¯ ইমà§à¦ªà§‹à¦°à§à¦Ÿ করà§à¦¨"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source Scene:"
-msgstr "উৎস দৃশà§à¦¯:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Same as Target Scene"
-msgstr "উদà§à¦¦à§‡à¦¶à§à¦¯à¦¿à¦¤ দৃশà§à¦¯à§‡à¦° নà§à¦¯à¦¾à§Ÿ"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Shared"
-msgstr "শেয়ারকৃত"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Target Texture Folder:"
-msgstr "গঠনবিনà§à¦¯à¦¾à¦¸à§‡à¦° উদà§à¦¦à§‡à¦¶à§à¦¯à¦¿à¦¤ ফোলà§à¦¡à¦¾à¦°:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Post-Process Script:"
-msgstr "পà§à¦°à¦•à§à¦°à¦¿à¦¯à¦¼à¦¾-পরবরà§à¦¤à§€ সà§à¦•à§à¦°à¦¿à¦ªà§à¦Ÿ:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Custom Root Node Type:"
-msgstr "সà§à¦¬à¦¨à¦¿à¦°à§à¦®à¦¿à¦¤ মূল নোডের ধরণ:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Auto"
-msgstr "সà§à¦¬à§Ÿà¦‚কà§à¦°à¦¿à§Ÿ"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Root Node Name:"
-msgstr "মূল নোডের নাম:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "The Following Files are Missing:"
-msgstr "নিমà§à¦¨à§‹à¦•à§à¦¤ ফাইলসমূহ অনà§à¦ªà¦¸à§à¦¥à¦¿à¦¤:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Anyway"
-msgstr "যেকোনো উপায়েই ইমà§à¦ªà§‹à¦°à§à¦Ÿ করà§à¦¨"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp scene/gui/dialogs.cpp
-msgid "Cancel"
-msgstr "বাতিল"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import & Open"
-msgstr "ইমà§à¦ªà§‹à¦°à§à¦Ÿ করà§à¦¨ à¦à¦¬à¦‚ খà§à¦²à§à¦¨"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Edited scene has not been saved, open imported scene anyway?"
-msgstr "সমà§à¦ªà¦¾à¦¦à¦¿à¦¤ দৃশà§à¦¯ সংরকà§à¦·à¦£ করা হয়নি, তবà§à¦“ ইমà§à¦ªà§‹à¦°à§à¦Ÿ করা দৃশà§à¦¯à¦Ÿà¦¿ খà§à¦²à¦¬à§‡à¦¨?"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Image:"
-msgstr "ছবি ইমà§à¦ªà§‹à¦°à§à¦Ÿ করà§à¦¨:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Can't import a file over itself:"
-msgstr "ফাইলকে তার নিজের উপরেই ইমà§à¦ªà§‹à¦°à§à¦Ÿ করা সমà§à¦­à¦¬ নয়:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't localize path: %s (already local)"
-msgstr "পথ সà§à¦¥à¦¾à¦¨à§€à¦¯à¦¼à¦•à¦°à¦£ সমà§à¦­à¦¬ হচà§à¦›à§‡ না: %s (ইতিমধà§à¦¯à§‡à¦‡ সà§à¦¥à¦¾à¦¨à§€à¦¯à¦¼)"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "3D Scene Animation"
-msgstr "3D দৃশà§à¦¯à§‡à¦° অà§à¦¯à¦¾à¦¨à¦¿à¦®à§‡à¦¶à¦¨"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Uncompressed"
-msgstr "অসংকà§à¦šà¦¿à¦¤"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossless (PNG)"
-msgstr "ধà§à¦¬à¦‚সবিহীন সঙà§à¦•à§‹à¦šà¦¨ (PNG)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossy (WebP)"
-msgstr "ধà§à¦¬à¦‚সাতà§à¦®à¦• সঙà§à¦•à§‹à¦šà¦¨ (WebP)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress (VRAM)"
-msgstr "সঙà§à¦•à§‹à¦šà¦¨ (VRAM)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Format"
-msgstr "গঠনবিনà§à¦¯à¦¾à¦¸à§‡à¦° ফরমà§à¦¯à¦¾à¦Ÿ"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Compression Quality (WebP):"
-msgstr "গঠনবিনà§à¦¯à¦¾à¦¸ সঙà§à¦•à§‹à¦šà¦¨à§‡à¦° গà§à¦£à¦®à¦¾à¦¨ (WebP):"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Options"
-msgstr "গঠনবিনà§à¦¯à¦¾à¦¸à§‡à¦° সিদà§à¦§à¦¾à¦¨à§à¦¤ (অপশন)-সমূহ"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Please specify some files!"
-msgstr "অনà§à¦—à§à¦°à¦¹ করে কিছৠফাইল নিরà§à¦¦à¦¿à¦·à§à¦Ÿ করে দিন!"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "At least one file needed for Atlas."
-msgstr "à¦à¦Ÿà¦²à¦¾à¦¸/মানচিতà§à¦°à¦¾à¦¬à¦²à§€à¦° জনà§à¦¯ কমপকà§à¦·à§‡ à¦à¦•à¦Ÿà¦¿ ফাইল পà§à¦°à¦¯à¦¼à§‹à¦œà¦¨à¥¤"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Error importing:"
-msgstr "ইমà§à¦ªà§‹à¦°à§à¦Ÿà§‡ সমসà§à¦¯à¦¾ হয়েছে:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Only one file is required for large texture."
-msgstr "বৃহৎ গঠনবিনà§à¦¯à¦¾à¦¸à§‡à¦° জনà§à¦¯ শà§à¦§à§à¦®à¦¾à¦¤à§à¦° à¦à¦•à¦Ÿà¦¿ ফাইল পà§à¦°à§Ÿà§‹à¦œà¦¨à¥¤"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Max Texture Size:"
-msgstr "গঠনবিনà§à¦¯à¦¾à¦¸à§‡à¦° সরà§à¦¬à§‡à¦¾à¦šà§à¦š আকার:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for Atlas (2D)"
-msgstr "à¦à¦Ÿà¦²à¦¾à¦¸/মানচিতà§à¦°à¦¾à¦¬à¦²à§€à¦° জনà§à¦¯ গঠনবিনà§à¦¯à¦¾à¦¸ ইমà§à¦ªà§‹à¦°à§à¦Ÿ করà§à¦¨ (2D)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cell Size:"
-msgstr "সেল (Cell)-à¦à¦° আকার:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Large Texture"
-msgstr "বৃহৎ গঠনবিনà§à¦¯à¦¾à¦¸"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Textures (2D)"
-msgstr "বৃহৎ গঠনবিনà§à¦¯à¦¾à¦¸ ইমà§à¦ªà§‹à¦°à§à¦Ÿ করà§à¦¨ (2D)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture"
-msgstr "গঠনবিনà§à¦¯à¦¾à¦¸à§‡à¦° উৎস"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Base Atlas Texture"
-msgstr "গোড়ার à¦à¦Ÿà¦²à¦¾à¦¸/মানচিতà§à¦°à¦¾à¦¬à¦²à§€à¦° গঠনবিনà§à¦¯à¦¾à¦¸"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s)"
-msgstr "গঠনবিনà§à¦¯à¦¾à¦¸(সমূহ)-à¦à¦° উৎস"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 2D"
-msgstr "2D-à¦à¦° জনà§à¦¯ গঠনবিনà§à¦¯à¦¾à¦¸à¦¸à¦®à§‚হ ইমà§à¦ªà§‹à¦°à§à¦Ÿ করà§à¦¨"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 3D"
-msgstr "3D-à¦à¦° জনà§à¦¯ গঠনবিনà§à¦¯à¦¾à¦¸à¦¸à¦®à§‚হ ইমà§à¦ªà§‹à¦°à§à¦Ÿ করà§à¦¨"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures"
-msgstr "গঠনবিনà§à¦¯à¦¾à¦¸à¦¸à¦®à§‚হ ইমà§à¦ªà§‹à¦°à§à¦Ÿ করà§à¦¨"
+msgid "Insert Point"
+msgstr "সনà§à¦¨à¦¿à¦¬à§‡à¦¶à¦¿à¦¤ হচà§à¦›à§‡"
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "2D Texture"
-msgstr "2D গঠনবিনà§à¦¯à¦¾à¦¸"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly (Remove Point)"
+msgstr "Poly সমà§à¦ªà¦¾à¦¦à¦¨ করà§à¦¨ (বিনà§à¦¦à§ অপসারণ করà§à¦¨)"
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "3D Texture"
-msgstr "3D গঠনবিনà§à¦¯à¦¾à¦¸"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Remove Poly And Point"
+msgstr "পলি à¦à¦¬à¦‚ বিনà§à¦¦à§ অপসারণ করà§à¦¨"
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Atlas Texture"
-msgstr "à¦à¦Ÿà¦²à¦¾à¦¸/মানচিতà§à¦°à¦¾à¦¬à¦²à§€à¦° গঠনবিনà§à¦¯à¦¾à¦¸"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create a new polygon from scratch."
+msgstr "আরমà§à¦­ হতে নতà§à¦¨ polygon তৈরি করà§à¦¨à¥¤"
-#: editor/io_plugins/editor_texture_import_plugin.cpp
+#: editor/plugins/abstract_polygon_2d_editor.cpp
msgid ""
-"NOTICE: Importing 2D textures is not mandatory. Just copy png/jpg files to "
-"the project."
+"Edit existing polygon:\n"
+"LMB: Move Point.\n"
+"Ctrl+LMB: Split Segment.\n"
+"RMB: Erase Point."
msgstr ""
-"নোটিশ: 2D টেকà§à¦¸à¦šà¦¾à¦° (texture) ইমà§à¦ªà§‹à¦°à§à¦Ÿ (import) করা অতà§à¦¯à¦¾à¦¬à¦¶à§à¦¯à¦• নয়। শà§à¦§à§à¦®à¦¾à¦¤à§à¦° png/jpg "
-"ফাইলসমূহ পà§à¦°à¦•à¦²à§à¦ªà§‡ পà§à¦°à¦¤à¦¿à¦²à¦¿à¦ªà¦¿/কপি করà§à¦¨à¥¤"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Crop empty space."
-msgstr "খালি সà§à¦¥à¦¾à¦¨ ছেà¦à¦Ÿà§‡ ফেলà§à¦¨à¥¤"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture"
-msgstr "গঠনবিনà§à¦¯à¦¾à¦¸"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Texture"
-msgstr "বৃহৎ গঠনবিনà§à¦¯à¦¾à¦¸ ইমà§à¦ªà§‹à¦°à§à¦Ÿ করà§à¦¨"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Load Source Image"
-msgstr "উৎস হতে ছবি লোড করà§à¦¨"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Slicing"
-msgstr "টà§à¦•à¦°à§‹ করà§à¦¨"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Inserting"
-msgstr "সনà§à¦¨à¦¿à¦¬à§‡à¦¶à¦¿à¦¤ হচà§à¦›à§‡"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Saving"
-msgstr "সংরকà§à¦·à¦¿à¦¤ হচà§à¦›à§‡"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save large texture:"
-msgstr "বৃহৎ গঠনবিনà§à¦¯à¦¾à¦¸ সংরকà§à¦·à¦£ করা সমà§à¦­à¦¬ হচà§à¦›à§‡ না:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Build Atlas For:"
-msgstr "à¦à¦Ÿà¦²à¦¾à¦¸/মানচিতà§à¦°à¦¾à¦¬à¦²à§€ নিরà§à¦®à¦¾à¦£ করà§à¦¨:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Loading Image:"
-msgstr "ছবি লোড করা হচà§à¦›à§‡:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't load image:"
-msgstr "ছবি লোড করা সমà§à¦­à¦¬ হচà§à¦›à§‡ না:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Converting Images"
-msgstr "ছবিসমূহ রূপানà§à¦¤à¦° করা হচà§à¦›à§‡"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cropping Images"
-msgstr "ছবিসমূহ ছাà¦à¦Ÿà¦¾ হচà§à¦›à§‡"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Blitting Images"
-msgstr "ছবিসমূহ বà§à¦²à¦¿à¦Ÿà¦¿à¦‚ (Blitting) করা হচà§à¦›à§‡"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save atlas image:"
-msgstr "à¦à¦Ÿà¦²à¦¾à¦¸/মানচিতà§à¦°à¦¾à¦¬à¦²à§€à¦° ছবি সংরকà§à¦·à¦£ করা সমà§à¦­à¦¬ হচà§à¦›à§‡ না:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save converted texture:"
-msgstr "রূপানà§à¦¤à¦°à¦¿à¦¤ গঠনবিনà§à¦¯à¦¾à¦¸ সংরকà§à¦·à¦£ করা সমà§à¦­à¦¬ হচà§à¦›à§‡ না:"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid source!"
-msgstr "অকারà§à¦¯à¦•à¦° উৎস!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid translation source!"
-msgstr "অকারà§à¦¯à¦•à¦° অনà§à¦¬à¦¾à¦¦à§‡à¦° উৎস!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Column"
-msgstr "কলাম"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/script_create_dialog.cpp
-msgid "Language"
-msgstr "ভাষা"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No items to import!"
-msgstr "ইমà§à¦ªà§‹à¦°à§à¦Ÿ করার মতো কোনো বসà§à¦¤à§ নেই!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No target path!"
-msgstr "কোনো উদà§à¦¦à§‡à¦¶à§à¦¯à¦¿à¦¤ পথ নেই!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translations"
-msgstr "অনà§à¦¬à¦¾à¦¦à¦¸à¦®à§‚হ ইমà§à¦ªà§‹à¦°à§à¦Ÿ করà§à¦¨"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Couldn't import!"
-msgstr "ইমà§à¦ªà§‹à¦°à§à¦Ÿ করা সমà§à¦­à¦¬ হচà§à¦›à§‡ না!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translation"
-msgstr "অনà§à¦¬à¦¾à¦¦ ইমà§à¦ªà§‹à¦°à§à¦Ÿ করà§à¦¨"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Source CSV:"
-msgstr "CSV-à¦à¦° উৎস:"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Ignore First Row"
-msgstr "পà§à¦°à¦¥à¦® সারি অগà§à¦°à¦¾à¦¹à§à¦¯ করà§à¦¨"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Compress"
-msgstr "সঙà§à¦•à§‹à¦šà¦¨ করà§à¦¨"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#, fuzzy
-msgid "Add to Project (project.godot)"
-msgstr "পà§à¦°à¦•à¦²à§à¦ªà§‡ সংযà§à¦•à§à¦¤ করà§à¦¨ (engine.cfg)"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Languages:"
-msgstr "ভাষাসমূহ ইমà§à¦ªà§‹à¦°à§à¦Ÿ করà§à¦¨:"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Translation"
-msgstr "অনà§à¦¬à¦¾à¦¦"
-
-#: editor/multi_node_edit.cpp
-msgid "MultiNode Set"
-msgstr "মালà§à¦Ÿà¦¿-নোড সà§à¦¥à¦¾à¦ªà¦¨ করà§à¦¨"
-
-#: editor/node_dock.cpp
-msgid "Groups"
-msgstr "দলসমূহ"
-
-#: editor/node_dock.cpp
-msgid "Select a Node to edit Signals and Groups."
-msgstr "সিগনà§à¦¯à¦¾à¦²-সমূহ à¦à¦¬à¦‚ দলসমূহ সমà§à¦ªà¦¾à¦¦à¦¨ করতে à¦à¦•à¦Ÿà¦¿ নোড নিরà§à¦¬à¦¾à¦šà¦¨ করà§à¦¨à¥¤"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Toggle Autoplay"
@@ -3523,7 +2938,6 @@ msgstr "অà§à¦¯à¦¾à¦¨à¦¿à¦®à§‡à¦¶à¦¨à§‡à¦° নাম:"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
#: editor/script_create_dialog.cpp
msgid "Error!"
@@ -3634,10 +3048,6 @@ msgid "Delete Input"
msgstr "ইনপà§à¦Ÿ অপসারণ করà§à¦¨"
#: editor/plugins/animation_tree_editor_plugin.cpp
-msgid "Rename"
-msgstr "পà§à¦¨à¦ƒà¦¨à¦¾à¦®à¦•à¦°à¦£ করà§à¦¨"
-
-#: editor/plugins/animation_tree_editor_plugin.cpp
msgid "Animation tree is valid."
msgstr "অà§à¦¯à¦¾à¦¨à¦¿à¦®à§‡à¦¶à¦¨à§‡à¦° তালিকাটি কারà§à¦¯à¦•à¦°à¥¤"
@@ -3693,65 +3103,191 @@ msgstr "নোড ফিলà§à¦Ÿà¦¾à¦°à¦¸à¦®à§‚হ সমà§à¦ªà¦¾à¦¦à¦¨ কর
msgid "Filters.."
msgstr "ফিলà§à¦Ÿà¦¾à¦°à¦¸à¦®à§‚হ.."
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing %d Triangles:"
-msgstr "%d টি তà§à¦°à¦¿à¦­à§à¦œ বিশà§à¦²à§‡à¦·à¦£ করা হচà§à¦›à§‡:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Free"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Contents:"
+msgstr "ধà§à¦°à§à¦¬à¦•à¦¸à¦®à§‚হ:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Triangle #"
-msgstr "তà§à¦°à¦¿à¦­à§à¦œ #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "View Files"
+msgstr "ফাইল"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Light Baker Setup:"
-msgstr "লাইটà§â€Œ সিদà§à¦§/বেকà§â€Œ-à¦à¦° সেটআপ:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve hostname:"
+msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing Geometry"
-msgstr "জà§à¦¯à¦¾à¦®à¦¿à¦¤à¦¿à¦•-আকার বিশà§à¦²à§‡à¦·à¦£ করা হচà§à¦›à§‡"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve."
+msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Fixing Lights"
-msgstr "লাইটà§â€Œà¦¸à¦®à§‚হ ঠিক করা হচà§à¦›à§‡"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connection error, please try again."
+msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Making BVH"
-msgstr "BVH তৈরি করা হচà§à¦›à§‡"
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Can't connect."
+msgstr "সংযোগ.."
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Light Octree"
-msgstr "লাইটের ওকটà§à¦°à§€ (octree) তৈরি করা হচà§à¦›à§‡"
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Can't connect to host:"
+msgstr "নোডের সাথে সংযà§à¦•à§à¦¤ করà§à¦¨:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Octree Texture"
-msgstr "ওকটà§à¦°à§€ (octree) গঠনবিনà§à¦¯à¦¾à¦¸ তৈরি করা হচà§à¦›à§‡"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response from host:"
+msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Transfer to Lightmaps:"
-msgstr "লাইটà§à¦®à§à¦¯à¦¾à¦ªà§‡ হসà§à¦¤à¦¾à¦¨à§à¦¤à¦° করà§à¦¨:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response."
+msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Allocating Texture #"
-msgstr "গঠনবিনà§à¦¯à¦¾à¦¸ বণà§à¦Ÿà¦¿à¦¤ হচà§à¦›à§‡ #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Request failed, return code:"
+msgstr "আবেদনকৃত ফাইল ফরমà§à¦¯à¦¾à¦Ÿ/ধরণ অজানা:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Req. Failed."
+msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Baking Triangle #"
-msgstr "তà§à¦°à¦¿à¦­à§à¦œ সিদà§à¦§/বেকà§â€Œ করা হচà§à¦›à§‡ #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, too many redirects"
+msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Post-Processing Texture #"
-msgstr "গঠনবিনà§à¦¯à¦¾à¦¸à§‡à¦° পà§à¦°à¦•à§à¦°à¦¿à¦¯à¦¼à¦¾-পরবরà§à¦¤à§€ পà§à¦°à¦•à§à¦°à¦¿à¦¯à¦¼à¦¾à¦•à¦°à¦£ #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Redirect Loop."
+msgstr ""
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Bake!"
-msgstr "সিদà§à¦§/বেকà§â€Œ!"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Bad download hash, assuming file has been tampered with."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Expected:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Got:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed sha256 hash check"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Asset Download Error:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Fetching:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Resolving.."
+msgstr "সংরকà§à¦·à¦¿à¦¤ হচà§à¦›à§‡.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Connecting.."
+msgstr "সংযোগ.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Requesting.."
+msgstr "পরীকà§à¦·à¦¾à¦®à§‚লক উৎস"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Error making request"
+msgstr "রিসোরà§à¦¸ সংরকà§à¦·à¦£à§‡ সমসà§à¦¯à¦¾ হয়েছে!"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Idle"
+msgstr ""
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Reset the lightmap octree baking process (start over)."
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Retry"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Download Error"
+msgstr "নীচে"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download for this asset is already in progress!"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "first"
msgstr ""
-"লাইটà§à¦®à§à¦¯à¦¾à¦ª ওকটà§à¦°à§€à¦° (octree) সিদà§à¦§/বেকà§â€Œ-à¦à¦° পà§à¦°à¦•à§à¦°à¦¿à¦¯à¦¼à¦¾à¦•à¦°à¦£ পà§à¦¨:সà§à¦¥à¦¾à¦ªà¦¨ করà§à¦¨ (পà§à¦¨à¦°à¦¾à¦°à¦®à§à¦­)।"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "prev"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "next"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "last"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "All"
+msgstr "সকল"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Plugins"
+msgstr "পà§à¦²à¦¾à¦—ইন-সমূহ"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Sort:"
+msgstr "সাজান:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Reverse"
+msgstr "উলà§à¦Ÿà¦¾à¦¨/বিপরীত দিকে ফিরান"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Category:"
+msgstr "বিভাগ:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Site:"
+msgstr "ওয়েবসাইট:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Support.."
+msgstr "সমরà§à¦¥à¦¨.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Official"
+msgstr "অফিসিয়াল/পà§à¦°à¦¾à¦¥à¦®à¦¿à¦• উৎস"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Testing"
+msgstr "পরীকà§à¦·à¦¾à¦®à§‚লক উৎস"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Assets ZIP File"
+msgstr "পà§à¦°à¦¯à¦¼à§‡à¦¾à¦œà¦¨à§€à¦¯à¦¼ উপকরণসমূহের ZIP ফাইল"
#: editor/plugins/camera_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
msgid "Preview"
msgstr "পà§à¦°à¦¿à¦­à¦¿à¦‰"
@@ -3794,12 +3330,18 @@ msgid "Edit CanvasItem"
msgstr "CanvasItem সমà§à¦ªà¦¾à¦¦à¦¨ করà§à¦¨"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Change Anchors"
+#, fuzzy
+msgid "Anchors only"
+msgstr "অà§à¦¯à¦¾à¦‚কর"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#, fuzzy
+msgid "Change Anchors and Margins"
msgstr "অà§à¦¯à¦¾à¦‚করসমূহ পরিবরà§à¦¤à¦¨ করà§à¦¨"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom (%):"
-msgstr "জà§à¦®à§ (%):"
+msgid "Change Anchors"
+msgstr "অà§à¦¯à¦¾à¦‚করসমূহ পরিবরà§à¦¤à¦¨ করà§à¦¨"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Paste Pose"
@@ -3851,60 +3393,78 @@ msgid "Pan Mode"
msgstr "পà§à¦¯à¦¾à¦¨ মোড"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Lock the selected object in place (can't be moved)."
-msgstr "নিরà§à¦¬à¦¾à¦šà¦¿à¦¤ বসà§à¦¤à§à¦Ÿà¦¿à¦•à§‡ à¦à¦‡ সà§à¦¥à¦¾à¦¨à§‡ আটকিয়ে রাখà§à¦¨ (সরানো সমà§à¦­à¦¬ হবেনা)।"
+#, fuzzy
+msgid "Toggles snapping"
+msgstr "ছেদবিনà§à¦¦à§ অদলবদল করà§à¦¨ (টগল বà§à¦°à§‡à¦•à¦ªà§Ÿà§‡à¦¨à§à¦Ÿ)"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Unlock the selected object (can be moved)."
-msgstr "নিরà§à¦¬à¦¾à¦šà¦¿à¦¤ বসà§à¦¤à§à¦Ÿà¦¿à¦•à§‡ মà§à¦•à§à¦¤ করà§à¦¨ (সরানো সমà§à¦­à¦¬ হবে)।"
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Use Snap"
+msgstr "সà§à¦¨à§à¦¯à¦¾à¦ª বà§à¦¯à¦¬à¦¹à¦¾à¦° করà§à¦¨"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Makes sure the object's children are not selectable."
-msgstr "বসà§à¦¤à§à¦° অনà§à¦¤à¦°à§à¦­à§à¦•à§à¦¤-সমূহ যাতে নিরà§à¦¬à¦¾à¦šà¦¨à¦¯à§‹à¦—à§à¦¯ না হয় তা নিশà§à¦šà¦¿à¦¤ করে।"
+#, fuzzy
+msgid "Snapping options"
+msgstr "অà§à¦¯à¦¾à¦¨à¦¿à¦®à§‡à¦¶à¦¨à§‡à¦° সিদà§à¦§à¦¾à¦¨à§à¦¤à¦¸à¦®à§‚হ"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Restores the object's children's ability to be selected."
-msgstr "বসà§à¦¤à§à¦° অনà§à¦¤à¦°à§à¦­à§à¦•à§à¦¤-সমূহের নিরà§à¦¬à¦¾à¦šà¦¨à¦¯à§‹à¦—à§à¦¯à¦¤à¦¾ পà§à¦¨à¦°à¦¾à§Ÿ ফিরিয়ে আনে।"
+#, fuzzy
+msgid "Snap to grid"
+msgstr "সà§à¦¨à§à¦¯à¦¾à¦ª মোড:"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Edit"
-msgstr "সমà§à¦ªà¦¾à¦¦à¦¨ করà§à¦¨ (Edit)"
+msgid "Use Rotation Snap"
+msgstr "ঘূরà§à¦£à¦¨ সà§à¦¨à§à¦¯à¦¾à¦ª বà§à¦¯à¦¬à¦¹à¦¾à¦° করà§à¦¨"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Use Snap"
-msgstr "সà§à¦¨à§à¦¯à¦¾à¦ª বà§à¦¯à¦¬à¦¹à¦¾à¦° করà§à¦¨"
+#, fuzzy
+msgid "Configure Snap..."
+msgstr "সà§à¦¨à§à¦¯à¦¾à¦ª কনফিগার করà§à¦¨.."
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Show Grid"
-msgstr "গà§à¦°à¦¿à¦¡ দেখান"
+msgid "Snap Relative"
+msgstr "আপেকà§à¦·à¦¿à¦• সà§à¦¨à§à¦¯à¦¾à¦ª"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Rotation Snap"
-msgstr "ঘূরà§à¦£à¦¨ সà§à¦¨à§à¦¯à¦¾à¦ª বà§à¦¯à¦¬à¦¹à¦¾à¦° করà§à¦¨"
+msgid "Use Pixel Snap"
+msgstr "পিকà§à¦¸à§‡à¦² সà§à¦¨à§à¦¯à¦¾à¦ª বà§à¦¯à¦¬à¦¹à¦¾à¦° করà§à¦¨"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap Relative"
-msgstr "আপেকà§à¦·à¦¿à¦• সà§à¦¨à§à¦¯à¦¾à¦ª"
+msgid "Smart snapping"
+msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Configure Snap.."
-msgstr "সà§à¦¨à§à¦¯à¦¾à¦ª কনফিগার করà§à¦¨.."
+#, fuzzy
+msgid "Snap to parent"
+msgstr "ধারক/বাহক পরà§à¦¯à¦¨à§à¦¤ বিসà§à¦¤à§ƒà¦¤ করà§à¦¨"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Pixel Snap"
-msgstr "পিকà§à¦¸à§‡à¦² সà§à¦¨à§à¦¯à¦¾à¦ª বà§à¦¯à¦¬à¦¹à¦¾à¦° করà§à¦¨"
+msgid "Snap to node anchor"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to node sides"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to other nodes"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Lock the selected object in place (can't be moved)."
+msgstr "নিরà§à¦¬à¦¾à¦šà¦¿à¦¤ বসà§à¦¤à§à¦Ÿà¦¿à¦•à§‡ à¦à¦‡ সà§à¦¥à¦¾à¦¨à§‡ আটকিয়ে রাখà§à¦¨ (সরানো সমà§à¦­à¦¬ হবেনা)।"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Skeleton.."
-msgstr "সà§à¦•à§‡à¦²à§‡à¦Ÿà¦¨/কাঠাম.."
+msgid "Unlock the selected object (can be moved)."
+msgstr "নিরà§à¦¬à¦¾à¦šà¦¿à¦¤ বসà§à¦¤à§à¦Ÿà¦¿à¦•à§‡ মà§à¦•à§à¦¤ করà§à¦¨ (সরানো সমà§à¦­à¦¬ হবে)।"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Makes sure the object's children are not selectable."
+msgstr "বসà§à¦¤à§à¦° অনà§à¦¤à¦°à§à¦­à§à¦•à§à¦¤-সমূহ যাতে নিরà§à¦¬à¦¾à¦šà¦¨à¦¯à§‹à¦—à§à¦¯ না হয় তা নিশà§à¦šà¦¿à¦¤ করে।"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Restores the object's children's ability to be selected."
+msgstr "বসà§à¦¤à§à¦° অনà§à¦¤à¦°à§à¦­à§à¦•à§à¦¤-সমূহের নিরà§à¦¬à¦¾à¦šà¦¨à¦¯à§‹à¦—à§à¦¯à¦¤à¦¾ পà§à¦¨à¦°à¦¾à§Ÿ ফিরিয়ে আনে।"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Make Bones"
@@ -3932,12 +3492,19 @@ msgid "View"
msgstr "দৃশà§à¦¯/পরিদরà§à¦¶à¦¨"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Reset"
-msgstr "জà§à¦®à§ পà§à¦¨:সà§à¦¥à¦¾à¦ªà¦¨ করà§à¦¨"
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Show Grid"
+msgstr "গà§à¦°à¦¿à¦¡ দেখান"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Set.."
-msgstr "জà§à¦®à§ নিরà§à¦§à¦¾à¦°à¦£ করà§à¦¨.."
+#, fuzzy
+msgid "Show helpers"
+msgstr "বোনà§â€Œ/হাড় দেখান"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#, fuzzy
+msgid "Show rulers"
+msgstr "বোনà§â€Œ/হাড় দেখান"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Center Selection"
@@ -3948,8 +3515,9 @@ msgid "Frame Selection"
msgstr "নিরà§à¦¬à¦¾à¦šà¦¨à¦•à§‡ ফà§à¦°à§‡à¦®à¦­à§‚কà§à¦¤ করà§à¦¨"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Anchor"
-msgstr "অà§à¦¯à¦¾à¦‚কর"
+#, fuzzy
+msgid "Layout"
+msgstr "লেআউট/নকশা সংরকà§à¦·à¦£ করà§à¦¨"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Insert Keys"
@@ -3972,12 +3540,21 @@ msgid "Clear Pose"
msgstr "ভঙà§à¦—ি পরিষà§à¦•à¦¾à¦° করà§à¦¨"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Set a Value"
-msgstr "à¦à¦•à¦Ÿà¦¿ মান নিরà§à¦§à¦¾à¦°à¦£ করà§à¦¨"
+msgid "Drag pivot from mouse position"
+msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap (Pixels):"
-msgstr "সà§à¦¨à§à¦¯à¦¾à¦ª (পিকà§à¦¸à§‡à¦²à¦¸à¦®à§‚হ):"
+#, fuzzy
+msgid "Set pivot at mouse position"
+msgstr "বহিঃ-বকà§à¦°à¦°à§‡à¦–ার সà§à¦¥à¦¾à¦¨ নিরà§à¦§à¦¾à¦°à¦£ করà§à¦¨"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Multiply grid step by 2"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Divide grid step by 2"
+msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Add %s"
@@ -3987,23 +3564,28 @@ msgstr "%s সংযà§à¦•à§à¦¤ করà§à¦¨"
msgid "Adding %s..."
msgstr "%s সংযà§à¦•à§à¦¤ হচà§à¦›à§‡..."
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Create Node"
msgstr "নোড তৈরি করà§à¦¨"
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Error instancing scene from %s"
msgstr "%s হতে দৃশà§à¦¯ ইনসà§à¦Ÿà§à¦¯à¦¾à¦¨à§à¦¸ করাতে সমসà§à¦¯à¦¾ হয়েছে"
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "OK :("
msgstr "ঠিক আছে :("
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "No parent to instance a child at."
msgstr "ইনসà§à¦Ÿà§à¦¯à¦¾à¦¨à§à¦¸ করার জনà§à¦¯ পà§à¦°à§Ÿà§‹à¦œà¦¨à§€à§Ÿ ধারক উপসà§à¦¥à¦¿à¦¤ নেই।"
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "This operation requires a single selected node."
msgstr "à¦à¦‡ কাজটি করার জনà§à¦¯ à¦à¦•à¦Ÿà¦¿ à¦à¦•à¦• নিরà§à¦¬à¦¾à¦šà¦¿à¦¤ নোড পà§à¦°à§Ÿà§‹à¦œà¦¨à¥¤"
@@ -4019,45 +3601,6 @@ msgstr ""
"টানà§à¦¨ à¦à¦¬à¦‚ ফেলà§à¦¨ + শিফট কী (Shift) : সহোদর নোড সংযোজন করতে\n"
"টানà§à¦¨ à¦à¦¬à¦‚ ফেলà§à¦¨ + অলà§à¦Ÿà¦¾à¦° কী (Alt) : নোডের ধরণ পরিবরà§à¦¤à¦¨ করতে"
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Create Poly"
-msgstr "Poly তৈরি করà§à¦¨"
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly"
-msgstr "Poly সমà§à¦ªà¦¾à¦¦à¦¨ করà§à¦¨"
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly (Remove Point)"
-msgstr "Poly সমà§à¦ªà¦¾à¦¦à¦¨ করà§à¦¨ (বিনà§à¦¦à§ অপসারণ করà§à¦¨)"
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Create a new polygon from scratch."
-msgstr "আরমà§à¦­ হতে নতà§à¦¨ polygon তৈরি করà§à¦¨à¥¤"
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-msgid ""
-"Edit existing polygon:\n"
-"LMB: Move Point.\n"
-"Ctrl+LMB: Split Segment.\n"
-"RMB: Erase Point."
-msgstr ""
-
#: editor/plugins/collision_polygon_editor_plugin.cpp
msgid "Create Poly3D"
msgstr "Poly3D তৈরি করà§à¦¨"
@@ -4067,14 +3610,6 @@ msgid "Set Handle"
msgstr "হà§à¦¯à¦¾à¦¨à§à¦¡à§‡à¦² সà§à¦¥à¦¾à¦ªà¦¨ করà§à¦¨"
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Creating Mesh Library"
-msgstr "মেস লাইবà§à¦°à§‡à¦°à¦¿ তৈরি হচà§à¦›à§‡"
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Thumbnail.."
-msgstr "থামà§à¦¬à¦¨à§‡à¦‡à¦².."
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Remove item %d?"
msgstr "%d টি বসà§à¦¤à§ অপসারণ করবেন?"
@@ -4097,6 +3632,28 @@ msgid "Update from Scene"
msgstr "দৃশà§à¦¯ হতে হালনাগাদ করà§à¦¨"
#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat0"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat1"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+#, fuzzy
+msgid "Ease in"
+msgstr "আনà§à¦¤-সহজাগমন"
+
+#: editor/plugins/curve_editor_plugin.cpp
+#, fuzzy
+msgid "Ease out"
+msgstr "বহিঃ-সহজাগমন"
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Smoothstep"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
#, fuzzy
msgid "Modify Curve Point"
msgstr "Curve Map পরিবরà§à¦¤à¦¨ করà§à¦¨"
@@ -4181,22 +3738,18 @@ msgid "Create Occluder Polygon"
msgstr "অকলà§à¦¡à¦¾à¦° (occluder) পলিগন তৈরি করà§à¦¨"
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Edit existing polygon:"
msgstr "বিদà§à¦¯à¦®à¦¾à¦¨ পলিগন সমà§à¦ªà¦¾à¦¦à¦¨ করà§à¦¨:"
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "LMB: Move Point."
msgstr "মাউসের বাম বোতাম: বিনà§à¦¦à§ সরান।"
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Ctrl+LMB: Split Segment."
msgstr "কনà§à¦Ÿà§à¦°à§‹à¦² + মাউসের বাম বোতাম: অংশ বিভকà§à¦¤ করà§à¦¨à¥¤"
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "RMB: Erase Point."
msgstr "মাউসের ডান বোতাম: বিনà§à¦¦à§ মà§à¦›à§‡ ফেলà§à¦¨à¥¤"
@@ -4301,6 +3854,10 @@ msgid "Create Outline"
msgstr "পà§à¦°à¦¾à¦¨à§à¦¤à¦°à§‡à¦–া তৈরি করà§à¦¨"
#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Mesh"
+msgstr "মেস"
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Create Trimesh Static Body"
msgstr "সà§à¦¥à¦¿à¦¤-টà§à¦°à¦¾à¦‡à¦®à§‡à¦¸ বডি তৈরি করà§à¦¨"
@@ -4428,14 +3985,83 @@ msgstr "যথেচà§à¦› মাপ:"
msgid "Populate"
msgstr "পপà§à¦²à§‡à¦Ÿ"
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake!"
+msgstr "সিদà§à¦§/বেকà§â€Œ!"
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+#, fuzzy
+msgid "Bake the navigation mesh.\n"
+msgstr "Navigation Mesh তৈরি করà§à¦¨"
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+#, fuzzy
+msgid "Clear the navigation mesh."
+msgstr "Navigation Mesh তৈরি করà§à¦¨"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Setting up Configuration..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Calculating grid size..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Creating heightfield..."
+msgstr "লাইটের ওকটà§à¦°à§€ (octree) তৈরি করা হচà§à¦›à§‡"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Marking walkable triangles..."
+msgstr "অনà§à¦¬à¦¾à¦¦-সমà§à¦­à¦¬ শবà§à¦¦à¦®à¦¾à¦²à¦¾/বাকà§à¦¯-সমূহ.."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Constructing compact heightfield..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Eroding walkable area..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Partitioning..."
+msgstr "সতরà§à¦•à¦¤à¦¾"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Creating contours..."
+msgstr "ওকটà§à¦°à§€ (octree) গঠনবিনà§à¦¯à¦¾à¦¸ তৈরি করা হচà§à¦›à§‡"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Creating polymesh..."
+msgstr "পà§à¦°à¦¾à¦¨à§à¦¤à¦°à§‡à¦–া মেস তৈরি করà§à¦¨.."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Converting to native navigation mesh..."
+msgstr "Navigation Mesh তৈরি করà§à¦¨"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Navigation Mesh Generator Setup:"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Parsing Geometry..."
+msgstr "জà§à¦¯à¦¾à¦®à¦¿à¦¤à¦¿à¦•-আকার বিশà§à¦²à§‡à¦·à¦£ করা হচà§à¦›à§‡"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Done!"
+msgstr ""
+
#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Create Navigation Polygon"
msgstr "Navigation Polygon তৈরি করà§à¦¨"
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Remove Poly And Point"
-msgstr "পলি à¦à¦¬à¦‚ বিনà§à¦¦à§ অপসারণ করà§à¦¨"
-
#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Clear Emission Mask"
msgstr "Emission Mask পরিসà§à¦•à¦¾à¦° করà§à¦¨"
@@ -4621,14 +4247,17 @@ msgid "Curve Point #"
msgstr "বকà§à¦°à¦°à§‡à¦–ার বিনà§à¦¦à§ #"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve Point Position"
msgstr "বকà§à¦°à¦°à§‡à¦–ার বিনà§à¦¦à§à¦° সà§à¦¥à¦¾à¦¨ নিরà§à¦§à¦¾à¦°à¦£ করà§à¦¨"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve In Position"
msgstr "আনà§à¦¤-বকà§à¦°à¦°à§‡à¦–ার সà§à¦¥à¦¾à¦¨ নিরà§à¦§à¦¾à¦°à¦£ করà§à¦¨"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve Out Position"
msgstr "বহিঃ-বকà§à¦°à¦°à§‡à¦–ার সà§à¦¥à¦¾à¦¨ নিরà§à¦§à¦¾à¦°à¦£ করà§à¦¨"
@@ -4691,6 +4320,14 @@ msgid "Scale Polygon"
msgstr "পলিগন মাপ করà§à¦¨"
#: editor/plugins/polygon_2d_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Edit"
+msgstr "সমà§à¦ªà¦¾à¦¦à¦¨ করà§à¦¨ (Edit)"
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Polygon->UV"
msgstr "পলিগন->UV"
@@ -4745,63 +4382,10 @@ msgstr "রিসোরà§à¦¸ লোড করà§à¦¨"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/shader_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "পà§à¦°à¦¤à¦¿à¦²à§‡à¦ªà¦¨/পেসà§à¦Ÿ করà§à¦¨"
-#: editor/plugins/rich_text_editor_plugin.cpp
-msgid "Parse BBCode"
-msgstr "BBCode বিশà§à¦²à§‡à¦·à¦£ করà§à¦¨"
-
-#: editor/plugins/sample_editor_plugin.cpp
-msgid "Length:"
-msgstr "লমà§à¦¬à¦¾:"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Open Sample File(s)"
-msgstr "নমà§à¦¨à¦¾ ফাইল(সমূহ) খà§à¦²à§à¦¨"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "ERROR: Couldn't load sample!"
-msgstr "সমসà§à¦¯à¦¾: নমà§à¦¨à¦¾ লোড করা সমà§à¦­à¦¬ হয়নি!"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Add Sample"
-msgstr "নমà§à¦¨à¦¾ যোগ করà§à¦¨"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Rename Sample"
-msgstr "নমà§à¦¨à¦¾ পà§à¦¨à¦ƒà¦¨à¦¾à¦®à¦•à¦°à¦£ করà§à¦¨"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Delete Sample"
-msgstr "নমà§à¦¨à¦¾ অপসারণ করà§à¦¨"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "16 Bits"
-msgstr "১৬ বিটসà§â€Œ"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "8 Bits"
-msgstr "৮ বিটসà§â€Œ"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Stereo"
-msgstr "সà§à¦Ÿà§‡à¦°à¦¿à¦“"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Mono"
-msgstr "মনো"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Format"
-msgstr "ফরমà§à¦¯à¦¾à¦Ÿ"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Pitch"
-msgstr "পিচà§â€Œ"
-
#: editor/plugins/script_editor_plugin.cpp
#, fuzzy
msgid "Clear Recent Files"
@@ -4893,6 +4477,10 @@ msgstr "ডকà§à¦®à§‡à¦¨à§à¦Ÿà¦¸à¦®à§‚হ বনà§à¦§ করà§à¦¨"
msgid "Close All"
msgstr "সবগà§à¦²à¦¿ বনà§à¦§ করà§à¦¨"
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+msgid "Run"
+msgstr "চালান"
+
#: editor/plugins/script_editor_plugin.cpp
#, fuzzy
msgid "Toggle Scripts Panel"
@@ -4922,7 +4510,8 @@ msgstr "পদারà§à¦ªà¦£ করà§à¦¨"
msgid "Break"
msgstr "বিরতি/ভাঙà§à¦—ন"
-#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+#: editor/script_editor_debugger.cpp
msgid "Continue"
msgstr "সচল"
@@ -4936,18 +4525,6 @@ msgid "Debug with external editor"
msgstr "à¦à¦¡à¦¿à¦Ÿà¦°à§‡ খà§à¦²à§à¦¨"
#: editor/plugins/script_editor_plugin.cpp
-msgid "Window"
-msgstr "উইনà§à¦¡à§‹"
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Left"
-msgstr "বামে সরান"
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Right"
-msgstr "ডানে সরান"
-
-#: editor/plugins/script_editor_plugin.cpp
#, fuzzy
msgid "Open Godot online documentation"
msgstr "রেফারেনà§à¦¸à§‡à¦° ডকà§à¦®à§‡à¦¨à§à¦Ÿà§‡à¦¶à¦¨à§‡ খà§à¦à¦œà§à¦¨à¥¤"
@@ -5034,8 +4611,9 @@ msgid "Cut"
msgstr "করà§à¦¤à¦¨/কাট করà§à¦¨"
#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "পà§à¦°à¦¤à¦¿à¦²à¦¿à¦ªà¦¿/কপি করà§à¦¨"
@@ -5301,10 +4879,6 @@ msgid "View Plane Transform."
msgstr "পà§à¦²à§‡à¦¨-à¦à¦° রà§à¦ªà¦¾à¦¨à§à¦¤à¦° দেখà§à¦¨à¥¤"
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Scaling to %s%%."
-msgstr "%s%% -ঠমাপিত হচà§à¦›à§‡à¥¤"
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rotating %s degrees."
msgstr "%s ডিগà§à¦°à¦¿ ঘূরà§à¦£à¦¿à¦¤ হচà§à¦›à§‡à¥¤"
@@ -5321,10 +4895,6 @@ msgid "Top View."
msgstr "শীরà§à¦· দরà§à¦¶à¦¨à¥¤"
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Top"
-msgstr "শীরà§à¦·"
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rear View."
msgstr "পশà§à¦šà¦¾à§Ž দরà§à¦¶à¦¨à¥¤"
@@ -5570,6 +5140,10 @@ msgid "Transform"
msgstr "রà§à¦ªà¦¾à¦¨à§à¦¤à¦°"
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Configure Snap.."
+msgstr "সà§à¦¨à§à¦¯à¦¾à¦ª কনফিগার করà§à¦¨.."
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Local Coords"
msgstr "সà§à¦¥à¦¾à¦¨à§€à§Ÿ সà§à¦¥à¦¾à¦¨à¦¾à¦™à§à¦•à¦¸à¦®à§‚হ"
@@ -5715,6 +5289,10 @@ msgid "Speed (FPS):"
msgstr "গতি (FPS):"
#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Loop"
+msgstr "লà§à¦ª"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Animation Frames"
msgstr "অà§à¦¯à¦¾à¦¨à¦¿à¦®à§‡à¦¶à¦¨à§‡à¦° ফà§à¦°à§‡à¦®à¦¸à¦®à§‚হ"
@@ -5727,12 +5305,14 @@ msgid "Insert Empty (After)"
msgstr "খালি বসà§à¦¤à§ যà§à¦•à§à¦¤ করà§à¦¨ (পরে)"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Up"
-msgstr "উপরে"
+#, fuzzy
+msgid "Move (Before)"
+msgstr "নোড(সমূহ) অপসারণ করà§à¦¨"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Down"
-msgstr "নীচে"
+#, fuzzy
+msgid "Move (After)"
+msgstr "বামে সরান"
#: editor/plugins/style_box_editor_plugin.cpp
msgid "StyleBox Preview:"
@@ -5811,8 +5391,12 @@ msgid "Remove All"
msgstr "অপসারণ করà§à¦¨"
#: editor/plugins/theme_editor_plugin.cpp
-msgid "Theme"
-msgstr "থিম"
+msgid "Edit theme.."
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Theme editing menu."
+msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
msgid "Add Class Items"
@@ -5896,6 +5480,10 @@ msgid "Style"
msgstr "সà§à¦Ÿà¦¾à¦‡à¦²"
#: editor/plugins/theme_editor_plugin.cpp
+msgid "Font"
+msgstr "ফনà§à¦Ÿ"
+
+#: editor/plugins/theme_editor_plugin.cpp
msgid "Color"
msgstr "রঙ"
@@ -5947,8 +5535,9 @@ msgid "Mirror Y"
msgstr "পà§à¦°à¦¤à¦¿à¦¬à¦¿à¦®à§à¦¬ Y"
#: editor/plugins/tile_map_editor_plugin.cpp
-msgid "Bucket"
-msgstr "বাকেটà§â€Œ"
+#, fuzzy
+msgid "Paint Tile"
+msgstr "TileMap আà¦à¦•à§à¦¨"
#: editor/plugins/tile_map_editor_plugin.cpp
msgid "Pick Tile"
@@ -6014,6 +5603,10 @@ msgid "Delete preset '%s'?"
msgstr "নিরà§à¦¬à¦¾à¦šà¦¿à¦¤ ফাইলসমূহ অপসারণ করবেন?"
#: editor/project_export.cpp
+msgid "Export templates for this platform are missing/corrupted: "
+msgstr ""
+
+#: editor/project_export.cpp
#, fuzzy
msgid "Presets"
msgstr "পà§à¦°à¦¿à¦¸à§‡à¦Ÿ.."
@@ -6098,34 +5691,62 @@ msgid "Export templates for this platform are missing:"
msgstr ""
#: editor/project_export.cpp
+msgid "Export templates for this platform are missing/corrupted:"
+msgstr ""
+
+#: editor/project_export.cpp
#, fuzzy
msgid "Export With Debug"
msgstr "Tile Set à¦à¦•à§à¦¸à¦ªà§‹à¦°à§à¦Ÿ করà§à¦¨"
#: editor/project_manager.cpp
-msgid "Invalid project path, the path must exist!"
-msgstr "অকারà§à¦¯à¦•à¦° পà§à¦°à¦•à¦²à§à¦ªà§‡à¦° পথ, পথটি অবশà§à¦¯à¦‡ বিদà§à¦¯à¦®à¦¾à¦¨ হতে হবে!"
+#, fuzzy
+msgid "The path does not exist."
+msgstr "ফাইলটি বিদà§à¦¯à¦®à¦¾à¦¨ নয়।"
#: editor/project_manager.cpp
#, fuzzy
-msgid "Invalid project path, project.godot must not exist."
-msgstr "অকারà§à¦¯à¦•à¦° পà§à¦°à¦•à¦²à§à¦ªà§‡à¦° পথ, engine.cfg অবশà§à¦¯à¦‡ অনà§à¦ªà¦¸à§à¦¥à¦¿à¦¤ হতে হবে।"
+msgid "Please choose a 'project.godot' file."
+msgstr "অনà§à¦—à§à¦°à¦¹ করে পà§à¦°à¦•à¦²à§à¦ªà§‡à¦° ফোলà§à¦¡à¦¾à¦°à§‡à¦° বাইরে à¦à¦•à§à¦¸à¦ªà§‹à¦°à§à¦Ÿ করà§à¦¨!"
#: editor/project_manager.cpp
-#, fuzzy
-msgid "Invalid project path, project.godot must exist."
-msgstr "অকারà§à¦¯à¦•à¦° পà§à¦°à¦•à¦²à§à¦ªà§‡à¦° পথ, engine.cfg অবশà§à¦¯à¦‡ উপসà§à¦¥à¦¿à¦¤ হতে হবে।"
+msgid ""
+"Your project will be created in a non empty folder (you might want to create "
+"a new folder)."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Please choose a folder that does not contain a 'project.godot' file."
+msgstr ""
#: editor/project_manager.cpp
msgid "Imported Project"
msgstr "পà§à¦°à¦•à¦²à§à¦ª ইমà§à¦ªà§‹à¦°à§à¦Ÿ করা হয়েছে"
#: editor/project_manager.cpp
+msgid " "
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "It would be a good idea to name your project."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Invalid project path (changed anything?)."
msgstr "অকারà§à¦¯à¦•à¦° পà§à¦°à¦•à¦²à§à¦ªà§‡à¦° পথ (কোনোকিছৠপরিবরà§à¦¤à¦¨ করেছেন?)।"
#: editor/project_manager.cpp
#, fuzzy
+msgid "Couldn't get project.godot in project path."
+msgstr "পà§à¦°à¦•à¦²à§à¦ªà§‡à¦° পথে engine.cfg তৈরি করা সমà§à¦­à¦¬ হয়নি।"
+
+#: editor/project_manager.cpp
+#, fuzzy
+msgid "Couldn't edit project.godot in project path."
+msgstr "পà§à¦°à¦•à¦²à§à¦ªà§‡à¦° পথে engine.cfg তৈরি করা সমà§à¦­à¦¬ হয়নি।"
+
+#: editor/project_manager.cpp
+#, fuzzy
msgid "Couldn't create project.godot in project path."
msgstr "পà§à¦°à¦•à¦²à§à¦ªà§‡à¦° পথে engine.cfg তৈরি করা সমà§à¦­à¦¬ হয়নি।"
@@ -6134,38 +5755,49 @@ msgid "The following files failed extraction from package:"
msgstr "পà§à¦¯à¦¾à¦•à§‡à¦œ হতে নীমà§à¦¨à§‹à¦•à§à¦¤ ফাইলসমূহ à¦à¦•à§à¦¸à¦Ÿà§à¦°à¦¾à¦•à§à¦Ÿ করা অসফল হয়েছে:"
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Rename Project"
+msgstr "নামহীন পà§à¦°à¦•à¦²à§à¦ª"
+
+#: editor/project_manager.cpp
+#, fuzzy
+msgid "Couldn't get project.godot in the project path."
+msgstr "পà§à¦°à¦•à¦²à§à¦ªà§‡à¦° পথে engine.cfg তৈরি করা সমà§à¦­à¦¬ হয়নি।"
+
+#: editor/project_manager.cpp
+msgid "New Game Project"
+msgstr "নতà§à¦¨ গেম পà§à¦°à¦•à¦²à§à¦ª"
+
+#: editor/project_manager.cpp
msgid "Import Existing Project"
msgstr "বিদà§à¦¯à¦®à¦¾à¦¨ পà§à¦°à¦•à¦²à§à¦ª ইমà§à¦ªà§‹à¦°à§à¦Ÿ করà§à¦¨"
#: editor/project_manager.cpp
-msgid "Project Path (Must Exist):"
-msgstr "পà§à¦°à¦•à¦²à§à¦ªà§‡à¦° পথ (অবশà§à¦¯à¦‡ বিদà§à¦¯à¦®à¦¾à¦¨ হতে হবে):"
+msgid "Create New Project"
+msgstr "নতà§à¦¨ পà§à¦°à¦•à¦²à§à¦ª তৈরি করà§à¦¨"
+
+#: editor/project_manager.cpp
+msgid "Install Project:"
+msgstr "পà§à¦°à¦•à¦²à§à¦ª ইনà§à¦¸à¦Ÿà¦² করà§à¦¨:"
#: editor/project_manager.cpp
msgid "Project Name:"
msgstr "পà§à¦°à¦•à¦²à§à¦ªà§‡à¦° নাম:"
#: editor/project_manager.cpp
-msgid "Create New Project"
-msgstr "নতà§à¦¨ পà§à¦°à¦•à¦²à§à¦ª তৈরি করà§à¦¨"
+#, fuzzy
+msgid "Create folder"
+msgstr "ফোলà§à¦¡à¦¾à¦° তৈরি করà§à¦¨"
#: editor/project_manager.cpp
msgid "Project Path:"
msgstr "পà§à¦°à¦•à¦²à§à¦ªà§‡à¦° পথ:"
#: editor/project_manager.cpp
-msgid "Install Project:"
-msgstr "পà§à¦°à¦•à¦²à§à¦ª ইনà§à¦¸à¦Ÿà¦² করà§à¦¨:"
-
-#: editor/project_manager.cpp
msgid "Browse"
msgstr "বà§à¦°à¦¾à¦‰à¦¸"
#: editor/project_manager.cpp
-msgid "New Game Project"
-msgstr "নতà§à¦¨ গেম পà§à¦°à¦•à¦²à§à¦ª"
-
-#: editor/project_manager.cpp
msgid "That's a BINGO!"
msgstr "দারà§à¦£ খবর!"
@@ -6174,6 +5806,11 @@ msgid "Unnamed Project"
msgstr "নামহীন পà§à¦°à¦•à¦²à§à¦ª"
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Can't open project"
+msgstr "সংযোগ.."
+
+#: editor/project_manager.cpp
msgid "Are you sure to open more than one project?"
msgstr "à¦à¦•à¦§à¦¿à¦• পà§à¦°à¦•à¦²à§à¦ª খোলায় আপনি সà§à¦¨à¦¿à¦¶à§à¦šà¦¿à¦¤?"
@@ -6204,6 +5841,12 @@ msgstr "তালিকা হতে পà§à¦°à¦•à¦²à§à¦ª অপসারণ à¦
#: editor/project_manager.cpp
msgid ""
+"Language changed.\n"
+"The UI will update next time the editor or project manager starts."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid ""
"You are about the scan %s folders for existing Godot projects. Do you "
"confirm?"
msgstr ""
@@ -6215,10 +5858,6 @@ msgid "Project List"
msgstr "পà§à¦°à¦•à¦²à§à¦ªà§‡à¦° তালিকা"
#: editor/project_manager.cpp
-msgid "Run"
-msgstr "চালান"
-
-#: editor/project_manager.cpp
msgid "Scan"
msgstr "সà§à¦•à§à¦¯à¦¾à¦¨"
@@ -6241,6 +5880,11 @@ msgstr "পà§à¦°à¦¸à§à¦¥à¦¾à¦¨ করà§à¦¨"
#: editor/project_manager.cpp
#, fuzzy
+msgid "Restart Now"
+msgstr "পà§à¦¨à¦°à¦¾à¦°à¦®à§à¦­ (সেঃ):"
+
+#: editor/project_manager.cpp
+#, fuzzy
msgid "Can't run project"
msgstr "সংযোগ.."
@@ -6277,17 +5921,14 @@ msgid "Add Input Action Event"
msgstr "ইনপà§à¦Ÿ অà§à¦¯à¦¾à¦•à¦¶à¦¨ ইভেনà§à¦Ÿ যোগ করà§à¦¨"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Meta+"
msgstr "Meta+"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Shift+"
msgstr "Shift+"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Alt+"
msgstr "Alt+"
@@ -6349,7 +5990,7 @@ msgstr "পরিবরà§à¦¤à¦¨ করà§à¦¨"
msgid "Joypad Axis Index:"
msgstr "জয়সà§à¦Ÿà¦¿à¦• অকà§à¦· ইনà§à¦¡à§‡à¦•à§à¦¸:"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Axis"
msgstr "অকà§à¦·"
@@ -6371,31 +6012,31 @@ msgstr "ইনপà§à¦Ÿ অà§à¦¯à¦¾à¦•à¦¶à¦¨ ইভেনà§à¦Ÿ মà§à¦›à§‡ à¦
msgid "Add Event"
msgstr "খালি বসà§à¦¤à§ যোগ করà§à¦¨"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Device"
msgstr "ডিভাইস/যনà§à¦¤à§à¦°"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Button"
msgstr "বাটন/বোতাম"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Left Button."
msgstr "বাম বোতাম/বাটন।"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Right Button."
msgstr "ডান বোতাম/বাটন।"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Middle Button."
msgstr "মাঠবোতাম/বাটন।"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Up."
msgstr "মাউসের চাকা উপরের দিকে চকà§à¦•à¦°à¥¤"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Down."
msgstr "মাউসের চাকা নিচের দিকে চকà§à¦•à¦°à¥¤"
@@ -6405,7 +6046,7 @@ msgid "Add Global Property"
msgstr "গেটার (Getter) à¦à¦° বৈশিষà§à¦Ÿà§à¦¯à§‡ যà§à¦•à§à¦¤ করà§à¦¨"
#: editor/project_settings_editor.cpp
-msgid "Select an setting item first!"
+msgid "Select a setting item first!"
msgstr ""
#: editor/project_settings_editor.cpp
@@ -6424,6 +6065,16 @@ msgid "Delete Item"
msgstr "ইনপà§à¦Ÿ অপসারণ করà§à¦¨"
#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Can't contain '/' or ':'"
+msgstr "নোডের সাথে সংযà§à¦•à§à¦¤ করà§à¦¨:"
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Already existing"
+msgstr "সà§à¦¥à¦¾à§Ÿà§€à§Ÿà¦¤à¦¾ টগল করà§à¦¨"
+
+#: editor/project_settings_editor.cpp
msgid "Error saving settings."
msgstr "সংরকà§à¦·à¦£à§‡ সমসà§à¦¯à¦¾ হয়েছে।"
@@ -6465,6 +6116,15 @@ msgstr "রিসোরà§à¦¸à§‡à¦° পà§à¦¨à¦ƒ-নকশার সিদà§à¦§
#: editor/project_settings_editor.cpp
#, fuzzy
+msgid "Changed Locale Filter"
+msgstr "বà§à¦²à§‡à¦¨à§à¦¡-à¦à¦° সময় পরিবরà§à¦¤à¦¨ করà§à¦¨"
+
+#: editor/project_settings_editor.cpp
+msgid "Changed Locale Filter Mode"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
msgid "Project Settings (project.godot)"
msgstr "পà§à¦°à¦•à¦²à§à¦ªà§‡à¦° সেটিংস (engine.cfg)"
@@ -6525,6 +6185,30 @@ msgid "Locale"
msgstr "ঘটনাসà§à¦¥à¦²"
#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Locales Filter"
+msgstr "ছবির ফিলà§à¦Ÿà¦¾à¦°:"
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Show all locales"
+msgstr "বোনà§â€Œ/হাড় দেখান"
+
+#: editor/project_settings_editor.cpp
+msgid "Show only selected locales"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Filter mode:"
+msgstr "ফিলà§à¦Ÿà¦¾à¦°à¦¸à¦®à§‚হ"
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Locales:"
+msgstr "ঘটনাসà§à¦¥à¦²"
+
+#: editor/project_settings_editor.cpp
msgid "AutoLoad"
msgstr "সà§à¦¬à§Ÿà¦‚কà§à¦°à¦¿à§Ÿ-লোড"
@@ -6576,10 +6260,20 @@ msgstr "নতà§à¦¨ সà§à¦•à§à¦°à¦¿à¦ªà§à¦Ÿ"
#: editor/property_editor.cpp
#, fuzzy
+msgid "Make Unique"
+msgstr "বোনà§â€Œ/হাড় তৈরি করà§à¦¨"
+
+#: editor/property_editor.cpp
+#, fuzzy
msgid "Show in File System"
msgstr "ফাইলসিসà§à¦Ÿà§‡à¦®"
#: editor/property_editor.cpp
+#, fuzzy
+msgid "Convert To %s"
+msgstr "à¦à¦¤à§‡ রূপানà§à¦¤à¦° করà§à¦¨.."
+
+#: editor/property_editor.cpp
msgid "Error loading file: Not a resource!"
msgstr "ফাইল লোডে সমসà§à¦¯à¦¾: রিসোরà§à¦¸ নয়!"
@@ -6618,6 +6312,11 @@ msgid "Select Property"
msgstr "গà§à¦£à¦¾à¦—à§à¦£/বৈশিষà§à¦Ÿà§à¦¯ বাছাই করà§à¦¨"
#: editor/property_selector.cpp
+#, fuzzy
+msgid "Select Virtual Method"
+msgstr "মেথড/পদà§à¦§à¦¤à¦¿ বাছাই করà§à¦¨"
+
+#: editor/property_selector.cpp
msgid "Select Method"
msgstr "মেথড/পদà§à¦§à¦¤à¦¿ বাছাই করà§à¦¨"
@@ -6645,26 +6344,6 @@ msgstr "সারà§à¦¬à¦œà¦¨à§€à¦¨ রূপানà§à¦¤à¦° রাখà§à¦¨"
msgid "Reparent"
msgstr "নতà§à¦¨ অভিভাবক দান করà§à¦¨"
-#: editor/resources_dock.cpp
-msgid "Create New Resource"
-msgstr "নতà§à¦¨ রিসোরà§à¦¸ তৈরি করà§à¦¨"
-
-#: editor/resources_dock.cpp
-msgid "Open Resource"
-msgstr "রিসোরà§à¦¸ খà§à¦²à§à¦¨"
-
-#: editor/resources_dock.cpp
-msgid "Save Resource"
-msgstr "রিসোরà§à¦¸ সংরকà§à¦·à¦£ করà§à¦¨"
-
-#: editor/resources_dock.cpp
-msgid "Resource Tools"
-msgstr "রিসোরà§à¦¸-à¦à¦° সরঞà§à¦œà¦¾à¦®à¦¸à¦®à§‚হ"
-
-#: editor/resources_dock.cpp
-msgid "Make Local"
-msgstr "সà§à¦¥à¦¾à¦¨à§€à§Ÿ করà§à¦¨"
-
#: editor/run_settings_dialog.cpp
msgid "Run Mode:"
msgstr "চালানোর মোড:"
@@ -6796,14 +6475,6 @@ msgid "Sub-Resources:"
msgstr "রিসোরà§à¦¸à¦¸à¦®à§‚হ:"
#: editor/scene_tree_dock.cpp
-msgid "Edit Groups"
-msgstr "গà§à¦°à§à¦ªà¦¸à¦®à§‚হ সমà§à¦ªà¦¾à¦¦à¦¨ করà§à¦¨"
-
-#: editor/scene_tree_dock.cpp
-msgid "Edit Connections"
-msgstr "সংযোগসমূহ সমà§à¦ªà¦¾à¦¦à¦¨ করà§à¦¨"
-
-#: editor/scene_tree_dock.cpp
msgid "Clear Inheritance"
msgstr "উতà§à¦¤à¦°à¦¾à¦§à¦¿à¦•à¦¾à¦°à¦¤à§à¦¬ পরিসà§à¦•à¦¾à¦° করà§à¦¨"
@@ -6992,6 +6663,15 @@ msgid "Invalid base path"
msgstr "বেস পথ অগà§à¦°à¦¹à¦£à¦¯à§‹à¦—à§à¦¯"
#: editor/script_create_dialog.cpp
+msgid "Directory of the same name exists"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
+#, fuzzy
+msgid "File exists, will be reused"
+msgstr "à¦à¦•à¦‡ নামের ফাইল উপসà§à¦¥à¦¿à¦¤, তা মà§à¦›à§‡ লিখবেন?"
+
+#: editor/script_create_dialog.cpp
msgid "Invalid extension"
msgstr "অগà§à¦°à¦¹à¦£à¦¯à§‹à¦—à§à¦¯ à¦à¦•à§à¦¸à¦Ÿà§‡à¦¨à¦¶à¦¨"
@@ -7037,6 +6717,10 @@ msgid "Load existing script file"
msgstr "বিদà§à¦¯à¦®à¦¾à¦¨ সà§à¦•à§à¦°à¦¿à¦ªà§à¦Ÿ লোড করà§à¦¨"
#: editor/script_create_dialog.cpp
+msgid "Language"
+msgstr "ভাষা"
+
+#: editor/script_create_dialog.cpp
#, fuzzy
msgid "Inherits"
msgstr "গà§à¦°à¦¹à¦£ করে:"
@@ -7081,6 +6765,10 @@ msgid "Function:"
msgstr "ফাংশন:"
#: editor/script_editor_debugger.cpp
+msgid "Pick one or more items from the list to display the graph."
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
msgid "Errors"
msgstr "সমসà§à¦¯à¦¾à¦¸à¦®à§‚হ"
@@ -7161,6 +6849,10 @@ msgid "Type"
msgstr "ধরণ"
#: editor/script_editor_debugger.cpp
+msgid "Format"
+msgstr "ফরমà§à¦¯à¦¾à¦Ÿ"
+
+#: editor/script_editor_debugger.cpp
msgid "Usage"
msgstr "বà§à¦¯à¦¬à¦¹à¦¾à¦°"
@@ -7236,12 +6928,30 @@ msgstr ""
msgid "Change Probe Extents"
msgstr "পà§à¦°à§‹à¦¬à§‡à¦° (Probe) পরিবà§à¦¯à¦¾à¦ªà§à¦¤à¦¿ পরিবরà§à¦¤à¦¨ করà§à¦¨"
+#: modules/gdnative/gd_native_library_editor.cpp
+#, fuzzy
+msgid "Library"
+msgstr "MeshLibrary (মেস-লাইবà§à¦°à§‡à¦°à¦¿).."
+
+#: modules/gdnative/gd_native_library_editor.cpp
+#, fuzzy
+msgid "Status"
+msgstr "অবসà§à¦¥à¦¾:"
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Libraries: "
+msgstr ""
+
+#: modules/gdnative/register_types.cpp
+msgid "GDNative"
+msgstr ""
+
#: modules/gdscript/gd_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Invalid type argument to convert(), use TYPE_* constants."
msgstr "অগà§à¦°à¦¹à¦£à¦¯à§‹à¦—à§à¦¯ মান/আরà§à¦—à§à¦®à§‡à¦¨à§à¦Ÿ convert()-ঠগিয়েছে, TYPE_* ধà§à¦°à§à¦¬à¦• বà§à¦¯à¦¬à¦¹à¦¾à¦° করà§à¦¨à¥¤"
-#: modules/gdscript/gd_functions.cpp
+#: modules/gdscript/gd_functions.cpp modules/mono/glue/glue_header.h
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Not enough bytes for decoding bytes, or invalid format."
msgstr "বিনà§à¦¯à¦¾à¦¸ জানার জনà§à¦¯ যথেষà§à¦Ÿ বাইট নেই, অথবা ভà§à¦² ফরমà§à¦¯à¦¾à¦Ÿà¥¤"
@@ -7293,10 +7003,6 @@ msgid "GridMap Duplicate Selection"
msgstr "নিরà§à¦¬à¦¾à¦šà¦¿à¦¤ সমূহ অনà§à¦²à¦¿à¦ªà¦¿ করà§à¦¨"
#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "GridMap Paint"
-msgstr ""
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
#, fuzzy
msgid "Snap View"
msgstr "শীরà§à¦· দরà§à¦¶à¦¨"
@@ -7400,13 +7106,8 @@ msgstr "সà§à¦¨à§à¦¯à¦¾à¦ª সেটিংস"
msgid "Pick Distance:"
msgstr "ইনà§à¦¸à¦Ÿà§à¦¯à¦¾à¦¨à§à¦¸:"
-#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
-msgid "Tiles"
-msgstr "ফাইল"
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "Areas"
+#: modules/mono/editor/mono_bottom_panel.cpp
+msgid "Builds"
msgstr ""
#: modules/visual_script/visual_script.cpp
@@ -7620,10 +7321,18 @@ msgid "Return"
msgstr "ফেরৎ পাঠান (Return)"
#: modules/visual_script/visual_script_editor.cpp
+msgid "Call"
+msgstr "ডাকà§à¦¨ (Call)"
+
+#: modules/visual_script/visual_script_editor.cpp
msgid "Get"
msgstr "মান পান (Get)"
#: modules/visual_script/visual_script_editor.cpp
+msgid "Script already has function '%s'"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
#, fuzzy
msgid "Change Input Value"
msgstr "ইনপà§à¦Ÿ নাম পরিবরà§à¦¤à¦¨ করà§à¦¨"
@@ -8030,6 +7739,12 @@ msgstr ""
"AnimatedSprite3D দà§à¦¬à¦¾à¦°à¦¾ ফà§à¦°à§‡à¦® দেখাতে SpriteFrames রিসোরà§à¦¸ অবশà§à¦¯à¦‡ তৈরি করতে হবে "
"অথবা 'Frames' à¦à¦° মান-ঠনিরà§à¦§à¦¾à¦°à¦¨ করে দিতে হবে।"
+#: scene/3d/vehicle_body.cpp
+msgid ""
+"VehicleWheel serves to provide a wheel system to a VehicleBody. Please use "
+"it as a child of a VehicleBody."
+msgstr ""
+
#: scene/gui/color_picker.cpp
#, fuzzy
msgid "Raw Mode"
@@ -8040,6 +7755,10 @@ msgid "Add current color as a preset"
msgstr ""
#: scene/gui/dialogs.cpp
+msgid "Cancel"
+msgstr "বাতিল"
+
+#: scene/gui/dialogs.cpp
msgid "Alert!"
msgstr "সতরà§à¦•à¦¤à¦¾!"
@@ -8047,10 +7766,6 @@ msgstr "সতরà§à¦•à¦¤à¦¾!"
msgid "Please Confirm..."
msgstr "অনà§à¦—à§à¦°à¦¹ করে নিশà§à¦šà¦¿à¦¤ করà§à¦¨..."
-#: scene/gui/input_action.cpp
-msgid "Ctrl+"
-msgstr "Ctrl+"
-
#: scene/gui/popup.cpp
msgid ""
"Popups will hide by default unless you call popup() or any of the popup*() "
@@ -8086,6 +7801,625 @@ msgstr ""
"আকার ধারণ করতে পারে। অনà§à¦¯à¦¥à¦¾à§Ÿ, à¦à¦Ÿà¦¿à¦•à§‡ à¦à¦•à¦Ÿà¦¿ RenderTarget করà§à¦¨ à¦à¦¬à¦‚ à¦à¦° অভà§à¦¯à¦¨à§à¦¤à¦°à§€à¦£ "
"দৃশà§à¦¯à¦¾à¦¬à¦²à¦¿à¦•à§‡ (texture) দৃশà§à¦¯à¦®à¦¾à¦¨ করতে কোনো নোডে হসà§à¦¤à¦¾à¦¨à§à¦¤à¦° করà§à¦¨à¥¤"
+#: scene/resources/dynamic_font.cpp
+msgid "Error initializing FreeType."
+msgstr "FreeType আরমà§à¦­à§‡ সমসà§à¦¯à¦¾ হয়েছে।"
+
+#: scene/resources/dynamic_font.cpp
+msgid "Unknown font format."
+msgstr "অজানা ধরনের ফনà§à¦Ÿà¥¤"
+
+#: scene/resources/dynamic_font.cpp
+msgid "Error loading font."
+msgstr "ফনà§à¦Ÿ তà§à¦²à¦¤à§‡/লোডে সমসà§à¦¯à¦¾ হয়েছে।"
+
+#: scene/resources/dynamic_font.cpp
+msgid "Invalid font size."
+msgstr "ফনà§à¦Ÿà§‡à¦° আকার অগà§à¦°à¦¹à¦¨à¦¯à§‹à¦—à§à¦¯à¥¤"
+
+#~ msgid "Filter:"
+#~ msgstr "ফিলà§à¦Ÿà¦¾à¦°:"
+
+#~ msgid "Theme"
+#~ msgstr "থিম"
+
+#~ msgid "Method List For '%s':"
+#~ msgstr "'%s' à¦à¦° জনà§à¦¯ মেথডের তালিকা:"
+
+#~ msgid "Arguments:"
+#~ msgstr "মান/আরà§à¦—à§à¦®à§‡à¦¨à§à¦Ÿ-সমূহ:"
+
+#~ msgid "Return:"
+#~ msgstr "পà§à¦°à¦¤à§à¦¯à¦¾à¦¬à¦°à§à¦¤à¦¨:"
+
+#~ msgid "Added:"
+#~ msgstr "সংযোজিত:"
+
+#~ msgid "Removed:"
+#~ msgstr "অপসারিত:"
+
+#~ msgid "Error saving atlas:"
+#~ msgstr "à¦à¦Ÿà¦²à¦¾à¦¸/মানচিতà§à¦°à¦¾à¦¬à¦²à§€ সংরকà§à¦·à¦£à§‡ সমসà§à¦¯à¦¾ হয়েছে:"
+
+#~ msgid "Could not save atlas subtexture:"
+#~ msgstr "à¦à¦Ÿà¦²à¦¾à¦¸/মানচিতà§à¦°à¦¾à¦¬à¦²à§€à¦° উপ-গঠনবিনà§à¦¯à¦¾à¦¸ (subtexture) সংরকà§à¦·à¦£ অসমরà§à¦¥ হয়েছে:"
+
+#~ msgid "Exporting for %s"
+#~ msgstr "%s à¦à¦° জনà§à¦¯ à¦à¦•à§à¦¸à¦ªà§‹à¦°à§à¦Ÿ (export) হচà§à¦›à§‡"
+
+#~ msgid "Setting Up.."
+#~ msgstr "সà§à¦¥à¦¾à¦ªà¦¿à¦¤/বিনà§à¦¯à¦¸à§à¦¤ হচà§à¦›à§‡.."
+
+#~ msgid "Error loading scene."
+#~ msgstr "দৃশà§à¦¯ লোডে সমসà§à¦¯à¦¾ হয়েছে।"
+
+#~ msgid "Re-Import"
+#~ msgstr "পà§à¦¨-ইমà§à¦ªà§‹à¦°à§à¦Ÿ"
+
+#~ msgid "Please wait for scan to complete."
+#~ msgstr "সà§à¦•à§à¦¯à¦¾à¦¨ সমà§à¦ªà¦¨à§à¦¨ হওয়া পরà§à¦¯à¦¨à§à¦¤ অনà§à¦—à§à¦°à¦¹ করে অপেকà§à¦·à¦¾ করà§à¦¨à¥¤"
+
+#~ msgid "Current scene must be saved to re-import."
+#~ msgstr "পà§à¦¨à¦°à¦¾à§Ÿ-ইমà§à¦ªà§‹à¦°à§à¦Ÿ করতে বরà§à¦¤à¦®à¦¾à¦¨ দৃশà§à¦¯à¦Ÿà¦¿à¦•à§‡ অবশà§à¦¯à¦‡ সংরকà§à¦·à¦£ করতে হবে।"
+
+#~ msgid "Save & Re-Import"
+#~ msgstr "সংরকà§à¦·à¦£ à¦à¦¬à¦‚ পà§à¦¨-ইমà§à¦ªà§‹à¦°à§à¦Ÿ করà§à¦¨"
+
+#~ msgid "Re-Importing"
+#~ msgstr "পà§à¦¨à¦°à¦¾à§Ÿ ইমà§à¦ªà§‹à¦°à§à¦Ÿ হচà§à¦›à§‡"
+
+#~ msgid "Re-Import Changed Resources"
+#~ msgstr "পà§à¦¨-ইমà§à¦ªà§‹à¦°à§à¦Ÿà§‡ রিসোরà§à¦¸-সমূহ পরিবরà§à¦¤à¦¿à¦¤ হয়েছে"
+
+#~ msgid "Loading Export Templates"
+#~ msgstr "à¦à¦•à§à¦¸à¦ªà§‹à¦°à§à¦Ÿ টেমপà§à¦²à§‡à¦Ÿà¦¸à¦®à§‚হ লোড হচà§à¦›à§‡"
+
+#, fuzzy
+#~ msgid ""
+#~ "\n"
+#~ "Status: Needs Re-Import"
+#~ msgstr "সংরকà§à¦·à¦£ à¦à¦¬à¦‚ পà§à¦¨-ইমà§à¦ªà§‹à¦°à§à¦Ÿ করà§à¦¨"
+
+#~ msgid "Same source and destination files, doing nothing."
+#~ msgstr "ফাইলà§à¦—à§à¦²à§‹à¦° à¦à¦•à¦‡ উৎস à¦à¦¬à¦‚ গনà§à¦¤à¦¬à§à¦¯à¦¸à§à¦¥à¦¾à¦¨, কিছà§à¦‡ করা হচà§à¦›à§‡ না।"
+
+#~ msgid "Same source and destination paths, doing nothing."
+#~ msgstr "পথগà§à¦²à§‹à¦° à¦à¦•à¦‡ উৎস à¦à¦¬à¦‚ গনà§à¦¤à¦¬à§à¦¯à¦¸à§à¦¥à¦¾à¦¨, কিছà§à¦‡ করা হচà§à¦›à§‡ না।"
+
+#~ msgid "Can't move directories to within themselves."
+#~ msgstr "সà§à¦¥à¦¾à¦¨à¦¸à¦®à§‚হকে তাদের মাà¦à§‡à¦‡ সà§à¦¥à¦¾à¦¨à¦¾à¦¨à§à¦¤à¦° করা সমà§à¦­à¦¬ নয়।"
+
+#, fuzzy
+#~ msgid "Error moving file:\n"
+#~ msgstr "ছবি লোডে সমসà§à¦¯à¦¾ হয়েছে:"
+
+#~ msgid "Pick New Name and Location For:"
+#~ msgstr "নতà§à¦¨ নাম à¦à¦¬à¦‚ অবসà§à¦¥à¦¾à¦¨ বাছাই করà§à¦¨:"
+
+#~ msgid "No files selected!"
+#~ msgstr "কোনো ফাইল নিরà§à¦¬à¦¾à¦šà¦¿à¦¤ হয়নি!"
+
+#~ msgid "Info"
+#~ msgstr "তথà§à¦¯"
+
+#~ msgid "Re-Import.."
+#~ msgstr "পà§à¦¨-ইমà§à¦ªà§‹à¦°à§à¦Ÿ.."
+
+#~ msgid "No bit masks to import!"
+#~ msgstr "ইমà§à¦ªà§‹à¦°à§à¦Ÿ করার জনà§à¦¯ কোনো বিট মাসà§à¦• নেই!"
+
+#~ msgid "Target path is empty."
+#~ msgstr "উদà§à¦¦à§‡à¦¶à§à¦¯à¦¿à¦¤ পথটি খালি।"
+
+#~ msgid "Target path must be a complete resource path."
+#~ msgstr "উদà§à¦¦à§‡à¦¶à§à¦¯à¦¿à¦¤ পথটি অবশà§à¦¯à¦‡ à¦à¦•à¦Ÿà¦¿ সমà§à¦ªà§à¦°à§à¦£ রিসোরà§à¦¸ পথ হতে হবে।"
+
+#~ msgid "Target path must exist."
+#~ msgstr "উদà§à¦¦à§‡à¦¶à§à¦¯à¦¿à¦¤ পথটি অবশà§à¦¯à¦‡ বিদà§à¦¯à¦®à¦¾à¦¨ হতে হবে।"
+
+#~ msgid "Save path is empty!"
+#~ msgstr "সংরকà§à¦·à¦£à§‡à¦° পথটি খালি!"
+
+#~ msgid "Import BitMasks"
+#~ msgstr "BitMasks ইমà§à¦ªà§‹à¦°à§à¦Ÿ করà§à¦¨"
+
+#~ msgid "Source Texture(s):"
+#~ msgstr "টেকà§à¦¸à¦¾à¦°(সমূহ)-à¦à¦° উৎস:"
+
+#~ msgid "Target Path:"
+#~ msgstr "উদà§à¦¦à§‡à¦¶à§à¦¯à¦¿à¦¤ পথ:"
+
+#~ msgid "Accept"
+#~ msgstr "গà§à¦°à¦¹à¦£ করà§à¦¨"
+
+#~ msgid "Bit Mask"
+#~ msgstr "বিট-মাসà§à¦• (Bit Mask)"
+
+#~ msgid "No source font file!"
+#~ msgstr "ফনà§à¦Ÿà§‡à¦° কোনো উৎস ফাইল নেই!"
+
+#~ msgid "No target font resource!"
+#~ msgstr "ফনà§à¦Ÿà§‡à¦° কোনো উদà§à¦¦à§‡à¦¶à§à¦¯à¦¿à¦¤ রিসোরà§à¦¸ নেই!"
+
+#, fuzzy
+#~ msgid ""
+#~ "Invalid file extension.\n"
+#~ "Please use .font."
+#~ msgstr ""
+#~ "ফাইলের অগà§à¦°à¦¹à¦¨à¦¯à§‹à¦—à§à¦¯ à¦à¦•à§à¦¸à¦Ÿà§‡à¦¨à¦¶à¦¨à¥¤\n"
+#~ "অনà§à¦—à§à¦°à¦¹ করে .fnt বà§à¦¯à¦¬à¦¹à¦¾à¦° করà§à¦¨à¥¤"
+
+#~ msgid "Couldn't save font."
+#~ msgstr "ফনà§à¦Ÿ সংরকà§à¦·à¦£ করা সমà§à¦­à¦¬ হয়নি।"
+
+#~ msgid "Source Font:"
+#~ msgstr "ফনà§à¦Ÿà§‡à¦° উৎস:"
+
+#~ msgid "Source Font Size:"
+#~ msgstr "উৎস ফনà§à¦Ÿà§‡à¦° আকার:"
+
+#~ msgid "Dest Resource:"
+#~ msgstr "রিসোরà§à¦¸à§‡à¦° গনà§à¦¤à¦¬à§à¦¯à¦¸à§à¦¥à¦¾à¦¨:"
+
+#~ msgid "The quick brown fox jumps over the lazy dog."
+#~ msgstr ""
+#~ "বাদামী রঙà§à¦—ের দà§à¦°à§à¦¤ শিয়ালটি অলস কà§à¦•à§à¦°à§‡à¦° উপর দিয়ে লাফিয়ে যায় (The quick brown "
+#~ "fox jumps over the lazy dog.)।"
+
+#~ msgid "Test:"
+#~ msgstr "পরীকà§à¦·à¦¾:"
+
+#~ msgid "Options:"
+#~ msgstr "সিদà§à¦§à¦¾à¦¨à§à¦¤à¦¸à¦®à§‚হ (অপশন):"
+
+#~ msgid "Font Import"
+#~ msgstr "ফনà§à¦Ÿ ইমà§à¦ªà§‹à¦°à§à¦Ÿ করà§à¦¨"
+
+#~ msgid ""
+#~ "This file is already a Godot font file, please supply a BMFont type file "
+#~ "instead."
+#~ msgstr ""
+#~ "à¦à¦‡ ফাইলটি ইতিমধà§à¦¯à§‡à¦‡ à¦à¦•à¦Ÿà¦¿ Godot ফনà§à¦Ÿ ফাইল, পরিবরà§à¦¤à§‡ অনà§à¦—à§à¦°à¦¹ করে BMFont ধরণের "
+#~ "ফাইল পà§à¦°à¦¦à¦¾à¦¨ করà§à¦¨à¥¤"
+
+#~ msgid "Failed opening as BMFont file."
+#~ msgstr "BMFont ফাইল খোলা বà§à¦¯à¦°à§à¦¥ হয়েছে।"
+
+#~ msgid "Invalid font custom source."
+#~ msgstr "সà§à¦¬à¦¨à¦¿à¦°à§à¦®à¦¿à¦¤ ফনà§à¦Ÿà§‡à¦° অগà§à¦°à¦¹à¦¨à¦¯à§‹à¦—à§à¦¯ উৎস।"
+
+#~ msgid "No meshes to import!"
+#~ msgstr "ইমà§à¦ªà§‹à¦°à§à¦Ÿ করার মতো কোনো মেস নেই!"
+
+#~ msgid "Single Mesh Import"
+#~ msgstr "à¦à¦•à¦• মেস ইমà§à¦ªà§‹à¦°à§à¦Ÿ করà§à¦¨"
+
+#~ msgid "Source Mesh(es):"
+#~ msgstr "মেস(সমূহ)-à¦à¦° উৎস:"
+
+#~ msgid "Surface %d"
+#~ msgstr "পৃষà§à¦ à¦¤à¦² %d"
+
+#~ msgid "No samples to import!"
+#~ msgstr "ইমà§à¦ªà§‹à¦°à§à¦Ÿ করার মতো কোনো নমà§à¦¨à¦¾ নেই!"
+
+#~ msgid "Import Audio Samples"
+#~ msgstr "শবà§à¦¦à§‡à¦° নমà§à¦¨à¦¾à¦¸à¦®à§‚হ ইমà§à¦ªà§‹à¦°à§à¦Ÿ করà§à¦¨"
+
+#~ msgid "Source Sample(s):"
+#~ msgstr "নমà§à¦¨à¦¾(সমূহ)-à¦à¦° উৎস:"
+
+#~ msgid "Audio Sample"
+#~ msgstr "শবà§à¦¦à§‡à¦° নমà§à¦¨à¦¾"
+
+#~ msgid "New Clip"
+#~ msgstr "নতà§à¦¨ কà§à¦²à¦¿à¦ª"
+
+#~ msgid "Flags"
+#~ msgstr "পতাকাসমূহ"
+
+#~ msgid "Bake FPS:"
+#~ msgstr "সিদà§à¦§ FPS:"
+
+#~ msgid "Optimizer"
+#~ msgstr "পরিমারà§à¦œà¦•"
+
+#~ msgid "Max Linear Error"
+#~ msgstr "সরà§à¦¬à§‡à¦¾à¦šà§à¦š রৈখিক ভà§à¦²/সমসà§à¦¯à¦¾"
+
+#~ msgid "Max Angular Error"
+#~ msgstr "সরà§à¦¬à§‡à¦¾à¦šà§à¦š কৌণিক ভà§à¦²/সমসà§à¦¯à¦¾"
+
+#~ msgid "Max Angle"
+#~ msgstr "সরà§à¦¬à§‡à¦¾à¦šà§à¦š কোণ"
+
+#~ msgid "Clips"
+#~ msgstr "কà§à¦²à¦¿à¦ªà¦¸à¦®à§‚হ"
+
+#~ msgid "Start(s)"
+#~ msgstr "আরমà§à¦­(সমূহ)"
+
+#~ msgid "End(s)"
+#~ msgstr "সমাপà§à¦¤à¦¿(সমূহ)"
+
+#~ msgid "Filters"
+#~ msgstr "ফিলà§à¦Ÿà¦¾à¦°à¦¸à¦®à§‚হ"
+
+#~ msgid "Source path is empty."
+#~ msgstr "উৎসের পথটি খালি।"
+
+#~ msgid "Couldn't load post-import script."
+#~ msgstr "ইমà§à¦ªà§‹à¦°à§à¦Ÿ-পরবরà§à¦¤à§€ সà§à¦•à§à¦°à¦¿à¦ªà§à¦Ÿ লোড করা সমà§à¦­à¦¬ হয়নি।"
+
+#~ msgid "Invalid/broken script for post-import."
+#~ msgstr "ইমà§à¦ªà§‹à¦°à§à¦Ÿ-পরবরà§à¦¤à§€ সà§à¦•à§à¦°à¦¿à¦ªà§à¦Ÿ অকারà§à¦¯à¦•à¦°/তà§à¦°à§à¦Ÿà¦¿à¦ªà§‚রà§à¦£à¥¤"
+
+#~ msgid "Error importing scene."
+#~ msgstr "দৃশà§à¦¯ ইমà§à¦ªà§‹à¦°à§à¦Ÿà§‡ সমসà§à¦¯à¦¾ হয়েছে।"
+
+#~ msgid "Import 3D Scene"
+#~ msgstr "3D দৃশà§à¦¯ ইমà§à¦ªà§‹à¦°à§à¦Ÿ করà§à¦¨"
+
+#~ msgid "Source Scene:"
+#~ msgstr "উৎস দৃশà§à¦¯:"
+
+#~ msgid "Same as Target Scene"
+#~ msgstr "উদà§à¦¦à§‡à¦¶à§à¦¯à¦¿à¦¤ দৃশà§à¦¯à§‡à¦° নà§à¦¯à¦¾à§Ÿ"
+
+#~ msgid "Shared"
+#~ msgstr "শেয়ারকৃত"
+
+#~ msgid "Target Texture Folder:"
+#~ msgstr "গঠনবিনà§à¦¯à¦¾à¦¸à§‡à¦° উদà§à¦¦à§‡à¦¶à§à¦¯à¦¿à¦¤ ফোলà§à¦¡à¦¾à¦°:"
+
+#~ msgid "Post-Process Script:"
+#~ msgstr "পà§à¦°à¦•à§à¦°à¦¿à¦¯à¦¼à¦¾-পরবরà§à¦¤à§€ সà§à¦•à§à¦°à¦¿à¦ªà§à¦Ÿ:"
+
+#~ msgid "Custom Root Node Type:"
+#~ msgstr "সà§à¦¬à¦¨à¦¿à¦°à§à¦®à¦¿à¦¤ মূল নোডের ধরণ:"
+
+#~ msgid "Auto"
+#~ msgstr "সà§à¦¬à§Ÿà¦‚কà§à¦°à¦¿à§Ÿ"
+
+#~ msgid "Root Node Name:"
+#~ msgstr "মূল নোডের নাম:"
+
+#~ msgid "The Following Files are Missing:"
+#~ msgstr "নিমà§à¦¨à§‹à¦•à§à¦¤ ফাইলসমূহ অনà§à¦ªà¦¸à§à¦¥à¦¿à¦¤:"
+
+#~ msgid "Import Anyway"
+#~ msgstr "যেকোনো উপায়েই ইমà§à¦ªà§‹à¦°à§à¦Ÿ করà§à¦¨"
+
+#~ msgid "Import & Open"
+#~ msgstr "ইমà§à¦ªà§‹à¦°à§à¦Ÿ করà§à¦¨ à¦à¦¬à¦‚ খà§à¦²à§à¦¨"
+
+#~ msgid "Edited scene has not been saved, open imported scene anyway?"
+#~ msgstr "সমà§à¦ªà¦¾à¦¦à¦¿à¦¤ দৃশà§à¦¯ সংরকà§à¦·à¦£ করা হয়নি, তবà§à¦“ ইমà§à¦ªà§‹à¦°à§à¦Ÿ করা দৃশà§à¦¯à¦Ÿà¦¿ খà§à¦²à¦¬à§‡à¦¨?"
+
+#~ msgid "Import Image:"
+#~ msgstr "ছবি ইমà§à¦ªà§‹à¦°à§à¦Ÿ করà§à¦¨:"
+
+#~ msgid "Couldn't localize path: %s (already local)"
+#~ msgstr "পথ সà§à¦¥à¦¾à¦¨à§€à¦¯à¦¼à¦•à¦°à¦£ সমà§à¦­à¦¬ হচà§à¦›à§‡ না: %s (ইতিমধà§à¦¯à§‡à¦‡ সà§à¦¥à¦¾à¦¨à§€à¦¯à¦¼)"
+
+#~ msgid "3D Scene Animation"
+#~ msgstr "3D দৃশà§à¦¯à§‡à¦° অà§à¦¯à¦¾à¦¨à¦¿à¦®à§‡à¦¶à¦¨"
+
+#~ msgid "Uncompressed"
+#~ msgstr "অসংকà§à¦šà¦¿à¦¤"
+
+#~ msgid "Compress Lossless (PNG)"
+#~ msgstr "ধà§à¦¬à¦‚সবিহীন সঙà§à¦•à§‹à¦šà¦¨ (PNG)"
+
+#~ msgid "Compress Lossy (WebP)"
+#~ msgstr "ধà§à¦¬à¦‚সাতà§à¦®à¦• সঙà§à¦•à§‹à¦šà¦¨ (WebP)"
+
+#~ msgid "Compress (VRAM)"
+#~ msgstr "সঙà§à¦•à§‹à¦šà¦¨ (VRAM)"
+
+#~ msgid "Texture Format"
+#~ msgstr "গঠনবিনà§à¦¯à¦¾à¦¸à§‡à¦° ফরমà§à¦¯à¦¾à¦Ÿ"
+
+#~ msgid "Texture Compression Quality (WebP):"
+#~ msgstr "গঠনবিনà§à¦¯à¦¾à¦¸ সঙà§à¦•à§‹à¦šà¦¨à§‡à¦° গà§à¦£à¦®à¦¾à¦¨ (WebP):"
+
+#~ msgid "Texture Options"
+#~ msgstr "গঠনবিনà§à¦¯à¦¾à¦¸à§‡à¦° সিদà§à¦§à¦¾à¦¨à§à¦¤ (অপশন)-সমূহ"
+
+#~ msgid "Please specify some files!"
+#~ msgstr "অনà§à¦—à§à¦°à¦¹ করে কিছৠফাইল নিরà§à¦¦à¦¿à¦·à§à¦Ÿ করে দিন!"
+
+#~ msgid "At least one file needed for Atlas."
+#~ msgstr "à¦à¦Ÿà¦²à¦¾à¦¸/মানচিতà§à¦°à¦¾à¦¬à¦²à§€à¦° জনà§à¦¯ কমপকà§à¦·à§‡ à¦à¦•à¦Ÿà¦¿ ফাইল পà§à¦°à¦¯à¦¼à§‹à¦œà¦¨à¥¤"
+
+#~ msgid "Error importing:"
+#~ msgstr "ইমà§à¦ªà§‹à¦°à§à¦Ÿà§‡ সমসà§à¦¯à¦¾ হয়েছে:"
+
+#~ msgid "Only one file is required for large texture."
+#~ msgstr "বৃহৎ গঠনবিনà§à¦¯à¦¾à¦¸à§‡à¦° জনà§à¦¯ শà§à¦§à§à¦®à¦¾à¦¤à§à¦° à¦à¦•à¦Ÿà¦¿ ফাইল পà§à¦°à§Ÿà§‹à¦œà¦¨à¥¤"
+
+#~ msgid "Max Texture Size:"
+#~ msgstr "গঠনবিনà§à¦¯à¦¾à¦¸à§‡à¦° সরà§à¦¬à§‡à¦¾à¦šà§à¦š আকার:"
+
+#~ msgid "Import Textures for Atlas (2D)"
+#~ msgstr "à¦à¦Ÿà¦²à¦¾à¦¸/মানচিতà§à¦°à¦¾à¦¬à¦²à§€à¦° জনà§à¦¯ গঠনবিনà§à¦¯à¦¾à¦¸ ইমà§à¦ªà§‹à¦°à§à¦Ÿ করà§à¦¨ (2D)"
+
+#~ msgid "Cell Size:"
+#~ msgstr "সেল (Cell)-à¦à¦° আকার:"
+
+#~ msgid "Large Texture"
+#~ msgstr "বৃহৎ গঠনবিনà§à¦¯à¦¾à¦¸"
+
+#~ msgid "Import Large Textures (2D)"
+#~ msgstr "বৃহৎ গঠনবিনà§à¦¯à¦¾à¦¸ ইমà§à¦ªà§‹à¦°à§à¦Ÿ করà§à¦¨ (2D)"
+
+#~ msgid "Source Texture"
+#~ msgstr "গঠনবিনà§à¦¯à¦¾à¦¸à§‡à¦° উৎস"
+
+#~ msgid "Base Atlas Texture"
+#~ msgstr "গোড়ার à¦à¦Ÿà¦²à¦¾à¦¸/মানচিতà§à¦°à¦¾à¦¬à¦²à§€à¦° গঠনবিনà§à¦¯à¦¾à¦¸"
+
+#~ msgid "Source Texture(s)"
+#~ msgstr "গঠনবিনà§à¦¯à¦¾à¦¸(সমূহ)-à¦à¦° উৎস"
+
+#~ msgid "Import Textures for 2D"
+#~ msgstr "2D-à¦à¦° জনà§à¦¯ গঠনবিনà§à¦¯à¦¾à¦¸à¦¸à¦®à§‚হ ইমà§à¦ªà§‹à¦°à§à¦Ÿ করà§à¦¨"
+
+#~ msgid "Import Textures for 3D"
+#~ msgstr "3D-à¦à¦° জনà§à¦¯ গঠনবিনà§à¦¯à¦¾à¦¸à¦¸à¦®à§‚হ ইমà§à¦ªà§‹à¦°à§à¦Ÿ করà§à¦¨"
+
+#~ msgid "Import Textures"
+#~ msgstr "গঠনবিনà§à¦¯à¦¾à¦¸à¦¸à¦®à§‚হ ইমà§à¦ªà§‹à¦°à§à¦Ÿ করà§à¦¨"
+
+#~ msgid "2D Texture"
+#~ msgstr "2D গঠনবিনà§à¦¯à¦¾à¦¸"
+
+#~ msgid "3D Texture"
+#~ msgstr "3D গঠনবিনà§à¦¯à¦¾à¦¸"
+
+#~ msgid "Atlas Texture"
+#~ msgstr "à¦à¦Ÿà¦²à¦¾à¦¸/মানচিতà§à¦°à¦¾à¦¬à¦²à§€à¦° গঠনবিনà§à¦¯à¦¾à¦¸"
+
+#~ msgid ""
+#~ "NOTICE: Importing 2D textures is not mandatory. Just copy png/jpg files "
+#~ "to the project."
+#~ msgstr ""
+#~ "নোটিশ: 2D টেকà§à¦¸à¦šà¦¾à¦° (texture) ইমà§à¦ªà§‹à¦°à§à¦Ÿ (import) করা অতà§à¦¯à¦¾à¦¬à¦¶à§à¦¯à¦• নয়। শà§à¦§à§à¦®à¦¾à¦¤à§à¦° png/"
+#~ "jpg ফাইলসমূহ পà§à¦°à¦•à¦²à§à¦ªà§‡ পà§à¦°à¦¤à¦¿à¦²à¦¿à¦ªà¦¿/কপি করà§à¦¨à¥¤"
+
+#~ msgid "Crop empty space."
+#~ msgstr "খালি সà§à¦¥à¦¾à¦¨ ছেà¦à¦Ÿà§‡ ফেলà§à¦¨à¥¤"
+
+#~ msgid "Texture"
+#~ msgstr "গঠনবিনà§à¦¯à¦¾à¦¸"
+
+#~ msgid "Import Large Texture"
+#~ msgstr "বৃহৎ গঠনবিনà§à¦¯à¦¾à¦¸ ইমà§à¦ªà§‹à¦°à§à¦Ÿ করà§à¦¨"
+
+#~ msgid "Load Source Image"
+#~ msgstr "উৎস হতে ছবি লোড করà§à¦¨"
+
+#~ msgid "Slicing"
+#~ msgstr "টà§à¦•à¦°à§‹ করà§à¦¨"
+
+#~ msgid "Saving"
+#~ msgstr "সংরকà§à¦·à¦¿à¦¤ হচà§à¦›à§‡"
+
+#~ msgid "Couldn't save large texture:"
+#~ msgstr "বৃহৎ গঠনবিনà§à¦¯à¦¾à¦¸ সংরকà§à¦·à¦£ করা সমà§à¦­à¦¬ হচà§à¦›à§‡ না:"
+
+#~ msgid "Build Atlas For:"
+#~ msgstr "à¦à¦Ÿà¦²à¦¾à¦¸/মানচিতà§à¦°à¦¾à¦¬à¦²à§€ নিরà§à¦®à¦¾à¦£ করà§à¦¨:"
+
+#~ msgid "Loading Image:"
+#~ msgstr "ছবি লোড করা হচà§à¦›à§‡:"
+
+#~ msgid "Couldn't load image:"
+#~ msgstr "ছবি লোড করা সমà§à¦­à¦¬ হচà§à¦›à§‡ না:"
+
+#~ msgid "Converting Images"
+#~ msgstr "ছবিসমূহ রূপানà§à¦¤à¦° করা হচà§à¦›à§‡"
+
+#~ msgid "Cropping Images"
+#~ msgstr "ছবিসমূহ ছাà¦à¦Ÿà¦¾ হচà§à¦›à§‡"
+
+#~ msgid "Blitting Images"
+#~ msgstr "ছবিসমূহ বà§à¦²à¦¿à¦Ÿà¦¿à¦‚ (Blitting) করা হচà§à¦›à§‡"
+
+#~ msgid "Couldn't save atlas image:"
+#~ msgstr "à¦à¦Ÿà¦²à¦¾à¦¸/মানচিতà§à¦°à¦¾à¦¬à¦²à§€à¦° ছবি সংরকà§à¦·à¦£ করা সমà§à¦­à¦¬ হচà§à¦›à§‡ না:"
+
+#~ msgid "Couldn't save converted texture:"
+#~ msgstr "রূপানà§à¦¤à¦°à¦¿à¦¤ গঠনবিনà§à¦¯à¦¾à¦¸ সংরকà§à¦·à¦£ করা সমà§à¦­à¦¬ হচà§à¦›à§‡ না:"
+
+#~ msgid "Invalid source!"
+#~ msgstr "অকারà§à¦¯à¦•à¦° উৎস!"
+
+#~ msgid "Invalid translation source!"
+#~ msgstr "অকারà§à¦¯à¦•à¦° অনà§à¦¬à¦¾à¦¦à§‡à¦° উৎস!"
+
+#~ msgid "Column"
+#~ msgstr "কলাম"
+
+#~ msgid "No items to import!"
+#~ msgstr "ইমà§à¦ªà§‹à¦°à§à¦Ÿ করার মতো কোনো বসà§à¦¤à§ নেই!"
+
+#~ msgid "No target path!"
+#~ msgstr "কোনো উদà§à¦¦à§‡à¦¶à§à¦¯à¦¿à¦¤ পথ নেই!"
+
+#~ msgid "Import Translations"
+#~ msgstr "অনà§à¦¬à¦¾à¦¦à¦¸à¦®à§‚হ ইমà§à¦ªà§‹à¦°à§à¦Ÿ করà§à¦¨"
+
+#~ msgid "Couldn't import!"
+#~ msgstr "ইমà§à¦ªà§‹à¦°à§à¦Ÿ করা সমà§à¦­à¦¬ হচà§à¦›à§‡ না!"
+
+#~ msgid "Import Translation"
+#~ msgstr "অনà§à¦¬à¦¾à¦¦ ইমà§à¦ªà§‹à¦°à§à¦Ÿ করà§à¦¨"
+
+#~ msgid "Source CSV:"
+#~ msgstr "CSV-à¦à¦° উৎস:"
+
+#~ msgid "Ignore First Row"
+#~ msgstr "পà§à¦°à¦¥à¦® সারি অগà§à¦°à¦¾à¦¹à§à¦¯ করà§à¦¨"
+
+#~ msgid "Compress"
+#~ msgstr "সঙà§à¦•à§‹à¦šà¦¨ করà§à¦¨"
+
+#, fuzzy
+#~ msgid "Add to Project (project.godot)"
+#~ msgstr "পà§à¦°à¦•à¦²à§à¦ªà§‡ সংযà§à¦•à§à¦¤ করà§à¦¨ (engine.cfg)"
+
+#~ msgid "Import Languages:"
+#~ msgstr "ভাষাসমূহ ইমà§à¦ªà§‹à¦°à§à¦Ÿ করà§à¦¨:"
+
+#~ msgid "Translation"
+#~ msgstr "অনà§à¦¬à¦¾à¦¦"
+
+#~ msgid "Parsing %d Triangles:"
+#~ msgstr "%d টি তà§à¦°à¦¿à¦­à§à¦œ বিশà§à¦²à§‡à¦·à¦£ করা হচà§à¦›à§‡:"
+
+#~ msgid "Triangle #"
+#~ msgstr "তà§à¦°à¦¿à¦­à§à¦œ #"
+
+#~ msgid "Light Baker Setup:"
+#~ msgstr "লাইটà§â€Œ সিদà§à¦§/বেকà§â€Œ-à¦à¦° সেটআপ:"
+
+#~ msgid "Fixing Lights"
+#~ msgstr "লাইটà§â€Œà¦¸à¦®à§‚হ ঠিক করা হচà§à¦›à§‡"
+
+#~ msgid "Making BVH"
+#~ msgstr "BVH তৈরি করা হচà§à¦›à§‡"
+
+#~ msgid "Transfer to Lightmaps:"
+#~ msgstr "লাইটà§à¦®à§à¦¯à¦¾à¦ªà§‡ হসà§à¦¤à¦¾à¦¨à§à¦¤à¦° করà§à¦¨:"
+
+#~ msgid "Allocating Texture #"
+#~ msgstr "গঠনবিনà§à¦¯à¦¾à¦¸ বণà§à¦Ÿà¦¿à¦¤ হচà§à¦›à§‡ #"
+
+#~ msgid "Baking Triangle #"
+#~ msgstr "তà§à¦°à¦¿à¦­à§à¦œ সিদà§à¦§/বেকà§â€Œ করা হচà§à¦›à§‡ #"
+
+#~ msgid "Post-Processing Texture #"
+#~ msgstr "গঠনবিনà§à¦¯à¦¾à¦¸à§‡à¦° পà§à¦°à¦•à§à¦°à¦¿à¦¯à¦¼à¦¾-পরবরà§à¦¤à§€ পà§à¦°à¦•à§à¦°à¦¿à¦¯à¦¼à¦¾à¦•à¦°à¦£ #"
+
+#~ msgid "Reset the lightmap octree baking process (start over)."
+#~ msgstr ""
+#~ "লাইটà§à¦®à§à¦¯à¦¾à¦ª ওকটà§à¦°à§€à¦° (octree) সিদà§à¦§/বেকà§â€Œ-à¦à¦° পà§à¦°à¦•à§à¦°à¦¿à¦¯à¦¼à¦¾à¦•à¦°à¦£ পà§à¦¨:সà§à¦¥à¦¾à¦ªà¦¨ করà§à¦¨ (পà§à¦¨à¦°à¦¾à¦°à¦®à§à¦­)।"
+
+#~ msgid "Zoom (%):"
+#~ msgstr "জà§à¦®à§ (%):"
+
+#~ msgid "Skeleton.."
+#~ msgstr "সà§à¦•à§‡à¦²à§‡à¦Ÿà¦¨/কাঠাম.."
+
+#~ msgid "Zoom Reset"
+#~ msgstr "জà§à¦®à§ পà§à¦¨:সà§à¦¥à¦¾à¦ªà¦¨ করà§à¦¨"
+
+#~ msgid "Zoom Set.."
+#~ msgstr "জà§à¦®à§ নিরà§à¦§à¦¾à¦°à¦£ করà§à¦¨.."
+
+#~ msgid "Set a Value"
+#~ msgstr "à¦à¦•à¦Ÿà¦¿ মান নিরà§à¦§à¦¾à¦°à¦£ করà§à¦¨"
+
+#~ msgid "Snap (Pixels):"
+#~ msgstr "সà§à¦¨à§à¦¯à¦¾à¦ª (পিকà§à¦¸à§‡à¦²à¦¸à¦®à§‚হ):"
+
+#~ msgid "Parse BBCode"
+#~ msgstr "BBCode বিশà§à¦²à§‡à¦·à¦£ করà§à¦¨"
+
+#~ msgid "Length:"
+#~ msgstr "লমà§à¦¬à¦¾:"
+
+#~ msgid "Open Sample File(s)"
+#~ msgstr "নমà§à¦¨à¦¾ ফাইল(সমূহ) খà§à¦²à§à¦¨"
+
+#~ msgid "ERROR: Couldn't load sample!"
+#~ msgstr "সমসà§à¦¯à¦¾: নমà§à¦¨à¦¾ লোড করা সমà§à¦­à¦¬ হয়নি!"
+
+#~ msgid "Add Sample"
+#~ msgstr "নমà§à¦¨à¦¾ যোগ করà§à¦¨"
+
+#~ msgid "Rename Sample"
+#~ msgstr "নমà§à¦¨à¦¾ পà§à¦¨à¦ƒà¦¨à¦¾à¦®à¦•à¦°à¦£ করà§à¦¨"
+
+#~ msgid "Delete Sample"
+#~ msgstr "নমà§à¦¨à¦¾ অপসারণ করà§à¦¨"
+
+#~ msgid "16 Bits"
+#~ msgstr "১৬ বিটসà§â€Œ"
+
+#~ msgid "8 Bits"
+#~ msgstr "৮ বিটসà§â€Œ"
+
+#~ msgid "Stereo"
+#~ msgstr "সà§à¦Ÿà§‡à¦°à¦¿à¦“"
+
+#~ msgid "Mono"
+#~ msgstr "মনো"
+
+#~ msgid "Pitch"
+#~ msgstr "পিচà§â€Œ"
+
+#~ msgid "Window"
+#~ msgstr "উইনà§à¦¡à§‹"
+
+#~ msgid "Move Right"
+#~ msgstr "ডানে সরান"
+
+#~ msgid "Scaling to %s%%."
+#~ msgstr "%s%% -ঠমাপিত হচà§à¦›à§‡à¥¤"
+
+#~ msgid "Up"
+#~ msgstr "উপরে"
+
+#~ msgid "Down"
+#~ msgstr "নীচে"
+
+#~ msgid "Bucket"
+#~ msgstr "বাকেটà§â€Œ"
+
+#~ msgid "Invalid project path, the path must exist!"
+#~ msgstr "অকারà§à¦¯à¦•à¦° পà§à¦°à¦•à¦²à§à¦ªà§‡à¦° পথ, পথটি অবশà§à¦¯à¦‡ বিদà§à¦¯à¦®à¦¾à¦¨ হতে হবে!"
+
+#, fuzzy
+#~ msgid "Invalid project path, project.godot must not exist."
+#~ msgstr "অকারà§à¦¯à¦•à¦° পà§à¦°à¦•à¦²à§à¦ªà§‡à¦° পথ, engine.cfg অবশà§à¦¯à¦‡ অনà§à¦ªà¦¸à§à¦¥à¦¿à¦¤ হতে হবে।"
+
+#, fuzzy
+#~ msgid "Invalid project path, project.godot must exist."
+#~ msgstr "অকারà§à¦¯à¦•à¦° পà§à¦°à¦•à¦²à§à¦ªà§‡à¦° পথ, engine.cfg অবশà§à¦¯à¦‡ উপসà§à¦¥à¦¿à¦¤ হতে হবে।"
+
+#~ msgid "Project Path (Must Exist):"
+#~ msgstr "পà§à¦°à¦•à¦²à§à¦ªà§‡à¦° পথ (অবশà§à¦¯à¦‡ বিদà§à¦¯à¦®à¦¾à¦¨ হতে হবে):"
+
+#~ msgid "Create New Resource"
+#~ msgstr "নতà§à¦¨ রিসোরà§à¦¸ তৈরি করà§à¦¨"
+
+#~ msgid "Open Resource"
+#~ msgstr "রিসোরà§à¦¸ খà§à¦²à§à¦¨"
+
+#~ msgid "Save Resource"
+#~ msgstr "রিসোরà§à¦¸ সংরকà§à¦·à¦£ করà§à¦¨"
+
+#~ msgid "Resource Tools"
+#~ msgstr "রিসোরà§à¦¸-à¦à¦° সরঞà§à¦œà¦¾à¦®à¦¸à¦®à§‚হ"
+
+#~ msgid "Make Local"
+#~ msgstr "সà§à¦¥à¦¾à¦¨à§€à§Ÿ করà§à¦¨"
+
+#~ msgid "Edit Groups"
+#~ msgstr "গà§à¦°à§à¦ªà¦¸à¦®à§‚হ সমà§à¦ªà¦¾à¦¦à¦¨ করà§à¦¨"
+
+#~ msgid "Edit Connections"
+#~ msgstr "সংযোগসমূহ সমà§à¦ªà¦¾à¦¦à¦¨ করà§à¦¨"
+
+#, fuzzy
+#~ msgid "Tiles"
+#~ msgstr "ফাইল"
+
+#~ msgid "Ctrl+"
+#~ msgstr "Ctrl+"
+
#~ msgid "Close scene? (Unsaved changes will be lost)"
#~ msgstr "দৃশà§à¦¯ বনà§à¦§ করবেন? (অসংরকà§à¦·à¦¿à¦¤ পরিবরà§à¦¤à¦¨à¦¸à¦®à§‚হ হারিয়ে যাবে)"
@@ -8099,9 +8433,6 @@ msgstr ""
#~ msgid "Close Goto Prev. Scene"
#~ msgstr "বনà§à¦§ করে পূরà§à¦¬à§‡à¦° দৃশà§à¦¯à§‡ যান"
-#~ msgid "Expand to Parent"
-#~ msgstr "ধারক/বাহক পরà§à¦¯à¦¨à§à¦¤ বিসà§à¦¤à§ƒà¦¤ করà§à¦¨"
-
#~ msgid "Del"
#~ msgstr "ডিলিট/অপসারণ"
@@ -8265,18 +8596,12 @@ msgstr ""
#~ msgid "Save Translatable Strings"
#~ msgstr "অনà§à¦¬à¦¾à¦¦-সমà§à¦­à¦¬ শবà§à¦¦à¦®à¦¾à¦²à¦¾/বাকà§à¦¯-সমূহ সংরকà§à¦·à¦£ করà§à¦¨"
-#~ msgid "Translatable Strings.."
-#~ msgstr "অনà§à¦¬à¦¾à¦¦-সমà§à¦­à¦¬ শবà§à¦¦à¦®à¦¾à¦²à¦¾/বাকà§à¦¯-সমূহ.."
-
#~ msgid "Install Export Templates"
#~ msgstr "à¦à¦•à§à¦¸à¦ªà§‹à¦°à§à¦Ÿà§‡à¦° টেমপà§à¦²à§‡à¦Ÿà¦¸à¦®à§‚হ ইনà§à¦¸à¦Ÿà¦² করà§à¦¨"
#~ msgid "Edit Script Options"
#~ msgstr "সà§à¦•à§à¦°à¦¿à¦ªà§à¦Ÿ-à¦à¦° সিদà§à¦§à¦¾à¦¨à§à¦¤à¦¸à¦®à§‚হ সমà§à¦ªà¦¾à¦¦à¦¨ করà§à¦¨"
-#~ msgid "Please export outside the project folder!"
-#~ msgstr "অনà§à¦—à§à¦°à¦¹ করে পà§à¦°à¦•à¦²à§à¦ªà§‡à¦° ফোলà§à¦¡à¦¾à¦°à§‡à¦° বাইরে à¦à¦•à§à¦¸à¦ªà§‹à¦°à§à¦Ÿ করà§à¦¨!"
-
#~ msgid "Error exporting project!"
#~ msgstr "পà§à¦°à¦•à¦²à§à¦ª à¦à¦•à§à¦¸à¦ªà§‹à¦°à§à¦Ÿà§‡ সমসà§à¦¯à¦¾ হয়েছে!"
@@ -8336,18 +8661,12 @@ msgstr ""
#~ msgid "Include"
#~ msgstr "অনà§à¦¤à¦°à§à¦­à§à¦•à§à¦¤ করà§à¦¨"
-#~ msgid "Change Image Group"
-#~ msgstr "ছবির গà§à¦°à§à¦ª পরিবরà§à¦¤à¦¨ করà§à¦¨"
-
#~ msgid "Group name can't be empty!"
#~ msgstr "গà§à¦°à§à¦ªà§‡à¦° নাম খালি হতে পারবে না!"
#~ msgid "Invalid character in group name!"
#~ msgstr "গà§à¦°à§à¦ªà§‡à¦° নামে অগà§à¦°à¦¹à¦¨à¦¯à§‹à¦—à§à¦¯ অকà§à¦·à¦°!"
-#~ msgid "Group name already exists!"
-#~ msgstr "গà§à¦°à§à¦ªà§‡à¦° নাম ইতিমধà§à¦¯à§‡à¦‡ আছে!"
-
#~ msgid "Add Image Group"
#~ msgstr "ছবির গà§à¦°à§à¦ª যোগ করà§à¦¨"
@@ -8426,9 +8745,6 @@ msgstr ""
#~ msgid "Preview Atlas"
#~ msgstr "à¦à¦Ÿà¦²à¦¾à¦¸/মানচিতà§à¦°à¦¾à¦¬à¦²à§€ পà§à¦°à¦¿à¦­à¦¿à¦‰"
-#~ msgid "Image Filter:"
-#~ msgstr "ছবির ফিলà§à¦Ÿà¦¾à¦°:"
-
#~ msgid "Images:"
#~ msgstr "ছবিসমূহ:"
@@ -8495,9 +8811,6 @@ msgstr ""
#~ msgid "Lighting"
#~ msgstr "লাইটিং"
-#~ msgid "Toggle Persisting"
-#~ msgstr "সà§à¦¥à¦¾à§Ÿà§€à§Ÿà¦¤à¦¾ টগল করà§à¦¨"
-
#~ msgid "Global"
#~ msgstr "সারà§à¦¬à¦œà¦¨à§€à¦¨"
diff --git a/editor/translations/ca.po b/editor/translations/ca.po
index 80f4b246b5..1a5a285b94 100644
--- a/editor/translations/ca.po
+++ b/editor/translations/ca.po
@@ -1,5 +1,6 @@
# Catalan translation of the Godot Engine editor
-# Copyright (C) 2016-2017 Juan Linietsky, Ariel Manzur and the Godot community
+# Copyright (C) 2007-2017 Juan Linietsky, Ariel Manzur
+# Copyright (C) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)
# This file is distributed under the same license as the Godot source code.
#
# Roger BR <drai_kin@hotmail.com>, 2016.
@@ -193,10 +194,9 @@ msgid "Create %d NEW tracks and insert keys?"
msgstr "Vol crear %d noves pistes i inserir-hi claus?"
#: editor/animation_editor.cpp editor/create_dialog.cpp
-#: editor/editor_audio_buses.cpp
+#: editor/editor_audio_buses.cpp editor/plugins/abstract_polygon_2d_editor.cpp
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
#: editor/plugins/mesh_instance_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp editor/project_manager.cpp
#: editor/script_create_dialog.cpp
msgid "Create"
@@ -359,271 +359,6 @@ msgstr "Canvia Tipus de la Matriu"
msgid "Change Array Value"
msgstr "Canvia Valor de la Matriu"
-#: editor/asset_library_editor_plugin.cpp
-msgid "Free"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_plugin_settings.cpp
-msgid "Version:"
-msgstr "Versió:"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Contents:"
-msgstr "Constants:"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "View Files"
-msgstr "Fitxer:"
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_help.cpp editor/property_selector.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Description:"
-msgstr "Descripció:"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-#: editor/project_manager.cpp
-msgid "Install"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/call_dialog.cpp
-#: editor/connections_dialog.cpp editor/export_template_manager.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-#: editor/project_settings_editor.cpp editor/property_editor.cpp
-#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Close"
-msgstr "Tanca"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve hostname:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Connection error, please try again."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Can't connect."
-msgstr "Connecta.."
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Can't connect to host:"
-msgstr "Connecta al Node:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response from host:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Request failed, return code:"
-msgstr "Format de fitxer desconegut:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Req. Failed."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Request failed, too many redirects"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Redirect Loop."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Bad download hash, assuming file has been tampered with."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Expected:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Got:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Asset Download Error:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-msgid "Success!"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Fetching:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Resolving.."
-msgstr "Desant..."
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Connecting.."
-msgstr "Connecta.."
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Requesting.."
-msgstr "Provant"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Error making request"
-msgstr "Error en desar recurs!"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Idle"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Retry"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Download Error"
-msgstr "Errors de Càrrega"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Download for this asset is already in progress!"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "first"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "prev"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "next"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "last"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "All"
-msgstr "Tot"
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
-#: editor/settings_config_dialog.cpp
-msgid "Search:"
-msgstr "Cerca:"
-
-#: editor/asset_library_editor_plugin.cpp editor/code_editor.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Search"
-msgstr "Cerca"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/project_manager.cpp
-msgid "Import"
-msgstr "Importa"
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Plugins"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Sort:"
-msgstr "Ordena:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Reverse"
-msgstr "Inverteix"
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Category:"
-msgstr "Categoria:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Site:"
-msgstr "Lloc:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Support.."
-msgstr "Suport..."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Official"
-msgstr "Oficial"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-msgid "Community"
-msgstr "Comunitat"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Testing"
-msgstr "Provant"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Assets ZIP File"
-msgstr "Arxiu ZIP d'Actius"
-
-#: editor/call_dialog.cpp
-msgid "Method List For '%s':"
-msgstr "Llista de mètodes de '%s':"
-
-#: editor/call_dialog.cpp modules/visual_script/visual_script_editor.cpp
-msgid "Call"
-msgstr "Crida"
-
-#: editor/call_dialog.cpp
-msgid "Method List:"
-msgstr "Llista de mètodes:"
-
-#: editor/call_dialog.cpp
-msgid "Arguments:"
-msgstr "Arguments:"
-
-#: editor/call_dialog.cpp
-msgid "Return:"
-msgstr "Retorn:"
-
#: editor/code_editor.cpp
msgid "Go to Line"
msgstr "Vés a la Línia"
@@ -661,6 +396,14 @@ msgstr "Paraules senceres"
msgid "Selection Only"
msgstr "Selecció Només"
+#: editor/code_editor.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
+msgid "Search"
+msgstr "Cerca"
+
#: editor/code_editor.cpp editor/editor_help.cpp
msgid "Find"
msgstr "Troba"
@@ -693,11 +436,11 @@ msgstr "Indica en reemplaçar"
msgid "Skip"
msgstr "Omet"
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom In"
msgstr "Apropa"
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom Out"
msgstr "Allunya"
@@ -765,6 +508,20 @@ msgstr "Diferit"
msgid "Oneshot"
msgstr "D'un cop"
+#: editor/connections_dialog.cpp editor/dependency_editor.cpp
+#: editor/export_template_manager.cpp
+#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Close"
+msgstr "Tanca"
+
#: editor/connections_dialog.cpp
msgid "Connect"
msgstr "Connecta"
@@ -790,7 +547,7 @@ msgstr "Connecta.."
msgid "Disconnect"
msgstr "Desconnecta"
-#: editor/connections_dialog.cpp editor/node_dock.cpp
+#: editor/connections_dialog.cpp editor/editor_help.cpp editor/node_dock.cpp
msgid "Signals"
msgstr "Senyals"
@@ -807,12 +564,25 @@ msgstr "Favorits:"
msgid "Recent:"
msgstr "Recents:"
+#: editor/create_dialog.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/quick_open.cpp editor/settings_config_dialog.cpp
+msgid "Search:"
+msgstr "Cerca:"
+
#: editor/create_dialog.cpp editor/editor_help.cpp
#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/quick_open.cpp
msgid "Matches:"
msgstr "Coincidències:"
+#: editor/create_dialog.cpp editor/editor_help.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/property_selector.cpp
+#: editor/script_editor_debugger.cpp
+msgid "Description:"
+msgstr "Descripció:"
+
#: editor/dependency_editor.cpp
msgid "Search Replacement For:"
msgstr "Cerca Reemplaçant per a:"
@@ -872,6 +642,10 @@ msgid "Owners Of:"
msgstr "Propietaris de:"
#: editor/dependency_editor.cpp
+msgid "Remove selected files from the project? (no undo)"
+msgstr "Elimina fitxer seleccionats del project? (no es pot desfer)"
+
+#: editor/dependency_editor.cpp
msgid ""
"The files being removed are required by other resources in order for them to "
"work.\n"
@@ -881,8 +655,8 @@ msgstr ""
"Eliminar de totes formes? (No es pot desfer)"
#: editor/dependency_editor.cpp
-msgid "Remove selected files from the project? (no undo)"
-msgstr "Elimina fitxer seleccionats del project? (no es pot desfer)"
+msgid "Cannot remove:\n"
+msgstr ""
#: editor/dependency_editor.cpp
msgid "Error loading:"
@@ -949,11 +723,6 @@ msgstr ""
#: editor/editor_about.cpp
#, fuzzy
-msgid "Authors"
-msgstr "Autor:"
-
-#: editor/editor_about.cpp
-#, fuzzy
msgid "Project Founders"
msgstr "Configuració del Projecte"
@@ -970,6 +739,39 @@ msgid "Developers"
msgstr ""
#: editor/editor_about.cpp
+#, fuzzy
+msgid "Authors"
+msgstr "Autor:"
+
+#: editor/editor_about.cpp
+msgid "Platinum Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Gold Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Mini Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Gold Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Silver Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Bronze Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
msgid "License"
msgstr ""
@@ -1013,6 +815,16 @@ msgid "Package Installed Successfully!"
msgstr ""
#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Success!"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/project_manager.cpp
+msgid "Install"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
msgid "Package Installer"
msgstr ""
@@ -1063,11 +875,6 @@ msgid "Audio Bus, Drag and Drop to rearrange."
msgstr ""
#: editor/editor_audio_buses.cpp
-#, fuzzy
-msgid "Bus options"
-msgstr "Opcions de Depuració (Debug)"
-
-#: editor/editor_audio_buses.cpp
msgid "Solo"
msgstr ""
@@ -1079,6 +886,11 @@ msgstr ""
msgid "Bypass"
msgstr ""
+#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Bus options"
+msgstr "Opcions de Depuració (Debug)"
+
#: editor/editor_audio_buses.cpp editor/plugins/tile_map_editor_plugin.cpp
#: editor/scene_tree_dock.cpp
msgid "Duplicate"
@@ -1086,6 +898,11 @@ msgstr ""
#: editor/editor_audio_buses.cpp
#, fuzzy
+msgid "Reset Volume"
+msgstr "Reinicia el Zoom"
+
+#: editor/editor_audio_buses.cpp
+#, fuzzy
msgid "Delete Effect"
msgstr "Elimina Seleccionats"
@@ -1109,6 +926,11 @@ msgstr "Duplica la Selecció"
#: editor/editor_audio_buses.cpp
#, fuzzy
+msgid "Reset Bus Volume"
+msgstr "Reinicia el Zoom"
+
+#: editor/editor_audio_buses.cpp
+#, fuzzy
msgid "Move Audio Bus"
msgstr "Mou Afegir Clau"
@@ -1143,7 +965,8 @@ msgstr ""
msgid "Create a new Bus Layout."
msgstr ""
-#: editor/editor_audio_buses.cpp editor/script_create_dialog.cpp
+#: editor/editor_audio_buses.cpp editor/property_editor.cpp
+#: editor/script_create_dialog.cpp
msgid "Load"
msgstr ""
@@ -1238,7 +1061,7 @@ msgid "Rearrange Autoloads"
msgstr "Reorganitza AutoCàrregues"
#: editor/editor_autoload_settings.cpp editor/editor_file_dialog.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp scene/gui/file_dialog.cpp
+#: scene/gui/file_dialog.cpp
msgid "Path:"
msgstr "Camí:"
@@ -1246,9 +1069,7 @@ msgstr "Camí:"
msgid "Node Name:"
msgstr "Nom del node:"
-#: editor/editor_autoload_settings.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp editor/project_manager.cpp
+#: editor/editor_autoload_settings.cpp editor/project_manager.cpp
msgid "Name"
msgstr "Nom"
@@ -1282,18 +1103,19 @@ msgid "Choose a Directory"
msgstr "Tria un Directori"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Create Folder"
msgstr "Crea una Carpeta"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: editor/editor_plugin_settings.cpp editor/plugins/theme_editor_plugin.cpp
-#: editor/project_export.cpp scene/gui/file_dialog.cpp
+#: editor/editor_plugin_settings.cpp editor/filesystem_dock.cpp
+#: editor/plugins/theme_editor_plugin.cpp editor/project_export.cpp
+#: scene/gui/file_dialog.cpp
msgid "Name:"
msgstr "Nom:"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Could not create folder."
msgstr "No s'ha pogut crear la carpeta."
@@ -1313,30 +1135,6 @@ msgstr "Compressió"
msgid "Template file not found:\n"
msgstr ""
-#: editor/editor_export.cpp
-msgid "Added:"
-msgstr "Afegit:"
-
-#: editor/editor_export.cpp
-msgid "Removed:"
-msgstr "Eliminat:"
-
-#: editor/editor_export.cpp
-msgid "Error saving atlas:"
-msgstr "Error en desar atles:"
-
-#: editor/editor_export.cpp
-msgid "Could not save atlas subtexture:"
-msgstr "No s'ha pogut desar la subtextura de l'atles:"
-
-#: editor/editor_export.cpp
-msgid "Exporting for %s"
-msgstr "Exportació per a %s"
-
-#: editor/editor_export.cpp
-msgid "Setting Up.."
-msgstr "Instal·lant.."
-
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "File Exists, Overwrite?"
msgstr "Fitxer Existent, Sobreescriure?"
@@ -1421,6 +1219,11 @@ msgstr "Mou Favorit Amunt"
msgid "Move Favorite Down"
msgstr "Mou Favorit Avall"
+#: editor/editor_file_dialog.cpp
+#, fuzzy
+msgid "Go to parent folder"
+msgstr "No s'ha pogut crear la carpeta."
+
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Directories & Files:"
msgstr "Directoris i Fitxers:"
@@ -1435,10 +1238,6 @@ msgid "File:"
msgstr "Fitxer:"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
-msgid "Filter:"
-msgstr "Filtre:"
-
-#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Must use a valid extension."
msgstr "Cal utilitzar una extensió vàlida."
@@ -1464,6 +1263,10 @@ msgstr "Llista de Classes:"
msgid "Search Classes"
msgstr "Cerca Classes"
+#: editor/editor_help.cpp editor/plugins/spatial_editor_plugin.cpp
+msgid "Top"
+msgstr ""
+
#: editor/editor_help.cpp editor/property_editor.cpp
msgid "Class:"
msgstr "Classe:"
@@ -1480,15 +1283,30 @@ msgstr "Heretat per:"
msgid "Brief Description:"
msgstr "Descripció breu:"
+#: editor/editor_help.cpp
+#, fuzzy
+msgid "Members"
+msgstr "Membres:"
+
#: editor/editor_help.cpp modules/visual_script/visual_script_editor.cpp
msgid "Members:"
msgstr "Membres:"
#: editor/editor_help.cpp
+#, fuzzy
+msgid "Public Methods"
+msgstr "Mètodes públics:"
+
+#: editor/editor_help.cpp
msgid "Public Methods:"
msgstr "Mètodes públics:"
#: editor/editor_help.cpp
+#, fuzzy
+msgid "GUI Theme Items"
+msgstr "Elements del Tema de la GUI:"
+
+#: editor/editor_help.cpp
msgid "GUI Theme Items:"
msgstr "Elements del Tema de la GUI:"
@@ -1498,6 +1316,11 @@ msgstr "Senyals:"
#: editor/editor_help.cpp
#, fuzzy
+msgid "Enumerations"
+msgstr "Funcions:"
+
+#: editor/editor_help.cpp
+#, fuzzy
msgid "Enumerations:"
msgstr "Funcions:"
@@ -1506,19 +1329,51 @@ msgid "enum "
msgstr ""
#: editor/editor_help.cpp
+#, fuzzy
+msgid "Constants"
+msgstr "Constants:"
+
+#: editor/editor_help.cpp
msgid "Constants:"
msgstr "Constants:"
#: editor/editor_help.cpp
#, fuzzy
+msgid "Description"
+msgstr "Descripció:"
+
+#: editor/editor_help.cpp
+#, fuzzy
+msgid "Properties"
+msgstr "Propietats de l'objecte."
+
+#: editor/editor_help.cpp
+#, fuzzy
msgid "Property Description:"
msgstr "Descripció breu:"
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this property. Please help us by "
+"[color=$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+
+#: editor/editor_help.cpp
+#, fuzzy
+msgid "Methods"
+msgstr "Llista de mètodes:"
+
+#: editor/editor_help.cpp
msgid "Method Description:"
msgstr "Descripció del mètode:"
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this method. Please help us by [color="
+"$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Search Text"
msgstr "Cerca Text"
@@ -1528,24 +1383,21 @@ msgid "Output:"
msgstr " Sortida:"
#: editor/editor_log.cpp editor/plugins/animation_tree_editor_plugin.cpp
-#: editor/plugins/rich_text_editor_plugin.cpp editor/property_editor.cpp
-#: editor/script_editor_debugger.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/property_editor.cpp editor/script_editor_debugger.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Clear"
msgstr "Neteja"
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Error saving resource!"
msgstr "Error en desar recurs!"
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Save Resource As.."
msgstr "Desar Recurs com..."
-#: editor/editor_node.cpp editor/export_template_manager.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "I see.."
msgstr "Vaja..."
@@ -1562,6 +1414,30 @@ msgid "Error while saving."
msgstr "Error en desar."
#: editor/editor_node.cpp
+#, fuzzy
+msgid "Can't open '%s'."
+msgstr "No es pot operar en '..'"
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Error while parsing '%s'."
+msgstr "Error en desar."
+
+#: editor/editor_node.cpp
+msgid "Unexpected end of file '%s'."
+msgstr ""
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Missing '%s' or its dependencies."
+msgstr "Escena '%s' té dependències no vàlides:"
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Error while loading '%s'."
+msgstr "Error en desar."
+
+#: editor/editor_node.cpp
msgid "Saving Scene"
msgstr "Desant Escena"
@@ -1622,6 +1498,33 @@ msgid "Restored default layout to base settings."
msgstr "S'ha restaurat la configuració predeterminada."
#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was imported, so it's not editable.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was instanced or inherited.\n"
+"Changes to it will not be kept when saving the current scene."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource was imported, so it's not editable. Change its settings in the "
+"import panel and then re-import."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This scene was imported, so changes to it will not be kept.\n"
+"Instancing it or inheriting will allow making changes to it.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Copy Params"
msgstr "Copia Paràmetres"
@@ -1798,23 +1701,35 @@ msgid "Save changes the following scene(s) before opening Project Manager?"
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"This option is deprecated. Situations where refresh must be forced are now "
+"considered a bug. Please report."
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Pick a Main Scene"
msgstr "Tria una Escena Principal"
#: editor/editor_node.cpp
-msgid "Unable to enable addon plugin at: '"
+msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr ""
#: editor/editor_node.cpp
-msgid "' parsing of config failed."
+msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/"
+#, fuzzy
+msgid "Unable to load addon script from path: '%s'."
+msgstr "Error carregant lletra."
+
+#: editor/editor_node.cpp
+msgid ""
+"Unable to load addon script from path: '%s' Base type is not EditorPlugin."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to load addon script from path: '"
+msgid "Unable to load addon script from path: '%s' Script is not in tool mode."
msgstr ""
#: editor/editor_node.cpp
@@ -1824,7 +1739,7 @@ msgid ""
msgstr ""
#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/scene_tree_dock.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Ugh"
msgstr "Uf..."
@@ -1837,14 +1752,15 @@ msgstr ""
"Utilitzeu 'Importa' per obrir l'escena i deseu-la dins del camí del projecte."
#: editor/editor_node.cpp
-msgid "Error loading scene."
-msgstr "No s'ha pogut carregar l'escena."
-
-#: editor/editor_node.cpp
msgid "Scene '%s' has broken dependencies:"
msgstr "Escena '%s' té dependències no vàlides:"
#: editor/editor_node.cpp
+#, fuzzy
+msgid "Clear Recent Scenes"
+msgstr "Reverteix Escena"
+
+#: editor/editor_node.cpp
msgid "Save Layout"
msgstr "Desar Disposició (Layout)"
@@ -1878,7 +1794,7 @@ msgstr "Mode Lliure de Distraccions"
msgid "Toggle distraction-free mode."
msgstr "Mode Lliure de Distraccions"
-#: editor/editor_node.cpp editor/io_plugins/editor_scene_import_plugin.cpp
+#: editor/editor_node.cpp
msgid "Scene"
msgstr "Escena"
@@ -2122,6 +2038,10 @@ msgstr ""
msgid "Issue Tracker"
msgstr ""
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+msgid "Community"
+msgstr "Comunitat"
+
#: editor/editor_node.cpp
msgid "About"
msgstr "Quant a"
@@ -2130,7 +2050,7 @@ msgstr "Quant a"
msgid "Play the project."
msgstr "Reprodueix el projecte."
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Play"
msgstr "Reprodueix"
@@ -2146,7 +2066,7 @@ msgstr "Pausa Escena"
msgid "Stop the scene."
msgstr "Atura l'escena."
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Stop"
msgstr "Atura"
@@ -2219,6 +2139,15 @@ msgid "Object properties."
msgstr "Propietats de l'objecte."
#: editor/editor_node.cpp
+msgid "Changes may be lost!"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Import"
+msgstr "Importa"
+
+#: editor/editor_node.cpp
msgid "FileSystem"
msgstr "SistemaDeFitxers"
@@ -2234,14 +2163,6 @@ msgstr "Sortida"
msgid "Don't Save"
msgstr ""
-#: editor/editor_node.cpp editor/editor_reimport_dialog.cpp
-msgid "Re-Import"
-msgstr "ReImporta"
-
-#: editor/editor_node.cpp editor/editor_plugin_settings.cpp
-msgid "Update"
-msgstr "Actualitza"
-
#: editor/editor_node.cpp
msgid "Import Templates From ZIP File"
msgstr "Importa Plantilles des d'un Fitxer ZIP"
@@ -2308,11 +2229,28 @@ msgstr "Editor de Dependències"
msgid "Open the previous Editor"
msgstr ""
+#: editor/editor_plugin.cpp
+msgid "Creating Mesh Previews"
+msgstr ""
+
+#: editor/editor_plugin.cpp
+msgid "Thumbnail.."
+msgstr ""
+
#: editor/editor_plugin_settings.cpp
msgid "Installed Plugins:"
msgstr "Connectors Instal·lats:"
#: editor/editor_plugin_settings.cpp
+msgid "Update"
+msgstr "Actualitza"
+
+#: editor/editor_plugin_settings.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Version:"
+msgstr "Versió:"
+
+#: editor/editor_plugin_settings.cpp
msgid "Author:"
msgstr "Autor:"
@@ -2345,7 +2283,8 @@ msgid "Frame %"
msgstr "% del Fotograma"
#: editor/editor_profiler.cpp
-msgid "Fixed Frame %"
+#, fuzzy
+msgid "Physics Frame %"
msgstr "% del Fotograma Fix"
#: editor/editor_profiler.cpp editor/script_editor_debugger.cpp
@@ -2364,26 +2303,6 @@ msgstr "Propi"
msgid "Frame #:"
msgstr "Fotograma núm.:"
-#: editor/editor_reimport_dialog.cpp
-msgid "Please wait for scan to complete."
-msgstr "Espera que s'acabi l'anàlisi."
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Current scene must be saved to re-import."
-msgstr "S'ha de desar l'escena abans de reimportar-la."
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Save & Re-Import"
-msgstr "Desa i ReImporta"
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Importing"
-msgstr "Re-Importació"
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Import Changed Resources"
-msgstr "ReImporta Recursos Modificats"
-
#: editor/editor_run_native.cpp
msgid "Select device from the list"
msgstr ""
@@ -2496,10 +2415,6 @@ msgid "Importing:"
msgstr "Importació:"
#: editor/export_template_manager.cpp
-msgid "Loading Export Templates"
-msgstr "Carregant Plantilles d'Exportació"
-
-#: editor/export_template_manager.cpp
#, fuzzy
msgid "Current Version:"
msgstr "Versió:"
@@ -2539,11 +2454,18 @@ msgid "Cannot navigate to '"
msgstr ""
#: editor/filesystem_dock.cpp
-#, fuzzy
+msgid "View items as a grid of thumbnails"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "View items as a list"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
msgid ""
"\n"
-"Status: Needs Re-Import"
-msgstr "Desa i ReImporta"
+"Status: Import of file failed. Please fix file and reimport manually."
+msgstr ""
#: editor/filesystem_dock.cpp
#, fuzzy
@@ -2553,48 +2475,55 @@ msgid ""
msgstr "Lletra:"
#: editor/filesystem_dock.cpp
-msgid "Same source and destination files, doing nothing."
-msgstr ""
-"Els fitxers d'origen i destinació són els mateixos. No s'ha produït cap "
-"acció."
+#, fuzzy
+msgid "Cannot move/rename resources root."
+msgstr "No es pot carregar/processar la lletra."
#: editor/filesystem_dock.cpp
-msgid "Target file exists, can't overwrite. Delete first."
-msgstr ""
+#, fuzzy
+msgid "Cannot move a folder into itself.\n"
+msgstr "No es pot importar un fitxer dins de si mateix:"
#: editor/filesystem_dock.cpp
-msgid "Same source and destination paths, doing nothing."
-msgstr "El camí d'origen i destinació es idèntic. No s'ha produït cap acció."
+#, fuzzy
+msgid "Error moving:\n"
+msgstr "Error en carregar:"
#: editor/filesystem_dock.cpp
-msgid "Can't move directories to within themselves."
-msgstr "No es poden moure directoris en si mateixos."
+#, fuzzy
+msgid "Unable to update dependencies:\n"
+msgstr "Escena '%s' té dependències no vàlides:"
#: editor/filesystem_dock.cpp
-msgid "Can't rename deps for:\n"
+msgid "No name provided"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "Provided name contains invalid characters"
msgstr ""
#: editor/filesystem_dock.cpp
#, fuzzy
-msgid "Error moving file:\n"
-msgstr "Error en desar TileSet!"
+msgid "No name provided."
+msgstr "Renomena o Mou..."
#: editor/filesystem_dock.cpp
#, fuzzy
-msgid "Error moving dir:\n"
-msgstr "Error en carregar:"
+msgid "Name contains invalid characters."
+msgstr "Caràcters vàlids:"
#: editor/filesystem_dock.cpp
-msgid "Can't operate on '..'"
-msgstr "No es pot operar en '..'"
+msgid "A file or folder with this name already exists."
+msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Pick New Name and Location For:"
-msgstr "Tria un Nou Nom i Ubicació per a:"
+#, fuzzy
+msgid "Renaming file:"
+msgstr "Reanomena Variable"
#: editor/filesystem_dock.cpp
-msgid "No files selected!"
-msgstr "Cap fitxer seleccionat!"
+msgid "Renaming folder:"
+msgstr ""
#: editor/filesystem_dock.cpp
msgid "Expand all"
@@ -2605,40 +2534,38 @@ msgid "Collapse all"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Show In File Manager"
-msgstr "Mostra en el Gestor de Fitxers"
-
-#: editor/filesystem_dock.cpp
-msgid "Instance"
-msgstr "Instància"
+msgid "Copy Path"
+msgstr "Copia Camí"
#: editor/filesystem_dock.cpp
-msgid "Edit Dependencies.."
-msgstr "Edita Dependències..."
+#, fuzzy
+msgid "Rename.."
+msgstr "Renomena o Mou..."
#: editor/filesystem_dock.cpp
-msgid "View Owners.."
-msgstr "Mostra Propietaris..."
+msgid "Move To.."
+msgstr "Mou cap a..."
#: editor/filesystem_dock.cpp
-msgid "Copy Path"
-msgstr "Copia Camí"
+#, fuzzy
+msgid "New Folder.."
+msgstr "Crea una Carpeta"
#: editor/filesystem_dock.cpp
-msgid "Rename or Move.."
-msgstr "Renomena o Mou..."
+msgid "Show In File Manager"
+msgstr "Mostra en el Gestor de Fitxers"
#: editor/filesystem_dock.cpp
-msgid "Move To.."
-msgstr "Mou cap a..."
+msgid "Instance"
+msgstr "Instància"
#: editor/filesystem_dock.cpp
-msgid "Info"
-msgstr "Informació"
+msgid "Edit Dependencies.."
+msgstr "Edita Dependències..."
#: editor/filesystem_dock.cpp
-msgid "Re-Import.."
-msgstr "ReImporta..."
+msgid "View Owners.."
+msgstr "Mostra Propietaris..."
#: editor/filesystem_dock.cpp
msgid "Previous Directory"
@@ -2670,6 +2597,11 @@ msgstr ""
msgid "Move"
msgstr "Mou"
+#: editor/filesystem_dock.cpp editor/plugins/animation_tree_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Rename"
+msgstr ""
+
#: editor/groups_editor.cpp
msgid "Add to Group"
msgstr "Afegeix al Grup"
@@ -2684,6 +2616,10 @@ msgid "Import as Single Scene"
msgstr "Important Escena..."
#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
msgid "Import with Separate Materials"
msgstr ""
@@ -2696,6 +2632,18 @@ msgid "Import with Separate Objects+Materials"
msgstr ""
#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Materials+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Materials+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
#, fuzzy
msgid "Import as Multiple Scenes"
msgstr "Importa Escena 3D"
@@ -2705,38 +2653,31 @@ msgid "Import as Multiple Scenes+Materials"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Import Scene"
msgstr "Importa Escena"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Importing Scene.."
msgstr "Important Escena..."
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Running Custom Script.."
msgstr "Executant Script Personalitzat..."
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Couldn't load post-import script:"
msgstr "No s'ha pogut carregar l'script de post-importació:"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Invalid/broken script for post-import (check console):"
msgstr "L'script de post-importació no és vàlid (comprova el terminal):"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Error running post-import script:"
msgstr "Error en l'execució de l'script de post-importació:"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Saving.."
msgstr "Desant..."
@@ -2767,589 +2708,54 @@ msgstr ""
msgid "Reimport"
msgstr "ReImporta"
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "No bit masks to import!"
-msgstr "Cap màscara de bits per importar!"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path is empty."
-msgstr "El camí de Destinació és buit."
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must be a complete resource path."
-msgstr "El camí de Destinació ha de ser un camí de recursos complet."
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must exist."
-msgstr "El camí de Destinació ha d'existir."
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Save path is empty!"
-msgstr "El camí per desar és buit!"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Import BitMasks"
-msgstr "Importa Màscares de Bit"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s):"
-msgstr "Textures Font:"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Target Path:"
-msgstr "Camí de Destinació:"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Accept"
-msgstr "Accepta"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Bit Mask"
-msgstr "Màscara de bits"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No source font file!"
-msgstr "Cap fitxer de lletra font!"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No target font resource!"
-msgstr "Cap recurs de Lletra!"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#, fuzzy
-msgid ""
-"Invalid file extension.\n"
-"Please use .font."
-msgstr ""
-"Extensió de fitxer no vàlida.\n"
-"Utilitzeu .fnt."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Can't load/process source font."
-msgstr "No es pot carregar/processar la lletra."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Couldn't save font."
-msgstr "No s'ha pogut desar la lletra."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font:"
-msgstr "Lletra:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font Size:"
-msgstr "Mida de la lletra:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Dest Resource:"
-msgstr "Recurs Objectiu:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "The quick brown fox jumps over the lazy dog."
-msgstr ""
-"«Dóna amor que seràs feliç!». Això, il·lús veí i company geniüt, ja és un "
-"lluït rètol d'onze kWh."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Test:"
-msgstr "Prova:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Options:"
-msgstr "Opcions:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Font Import"
-msgstr "Importa lletra"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"This file is already a Godot font file, please supply a BMFont type file "
-"instead."
-msgstr ""
-"Aquest fitxer ja és un fitxer de lletra de Godot. Proveïu un fitxer de tipus "
-"BMFont."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Failed opening as BMFont file."
-msgstr "No s'ha pogut obrir com a fitxer BMFont."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error initializing FreeType."
-msgstr "Error inicialitzant FreeType."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Unknown font format."
-msgstr "Format de lletra desconegut."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error loading font."
-msgstr "Error carregant lletra."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Invalid font size."
-msgstr "La mida de la lletra no és vàlida."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Invalid font custom source."
-msgstr "Lletra personalitzada no vàlida."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/plugins/theme_editor_plugin.cpp
-msgid "Font"
-msgstr "Lletra"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "No meshes to import!"
-msgstr "Cap malla per importar!"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Single Mesh Import"
-msgstr "Importa una Malla"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Source Mesh(es):"
-msgstr "Malla/es :"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/plugins/mesh_instance_editor_plugin.cpp
-msgid "Mesh"
-msgstr "Malla"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Surface %d"
-msgstr "Superfície %d"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "No samples to import!"
-msgstr "No s'ha trobat cap mostra d'Àudio per importar!"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Import Audio Samples"
-msgstr "Importa Mostra d'Àudio"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Source Sample(s):"
-msgstr "Mostra/es d'Origen:"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Audio Sample"
-msgstr "Mostra d'Àudio"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "New Clip"
-msgstr "Nou Clip"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Animation Options"
-msgstr "Opcions d'Animació"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#, fuzzy
-msgid "Flags"
-msgstr "Indicadors (flags)"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Bake FPS:"
-msgstr "Fer Bake dels FPS:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Optimizer"
-msgstr "Optimitzador"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Linear Error"
-msgstr "Error Lineal Màxim"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angular Error"
-msgstr "Error Angular Màxim"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angle"
-msgstr "Angle Màxim"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Clips"
-msgstr "Clips"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Start(s)"
-msgstr "Inici/s"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "End(s)"
-msgstr "Final/s"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Loop"
-msgstr "Bucle"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Filters"
-msgstr "Filtres"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source path is empty."
-msgstr "El camí d'origen és buit."
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't load post-import script."
-msgstr "No s'ha pogut carregar l'script de post-importació."
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Invalid/broken script for post-import."
-msgstr "L'script de post-importació no és vàlid ."
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Error importing scene."
-msgstr "No s'ha pogut importar l'escena."
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import 3D Scene"
-msgstr "Importa Escena 3D"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source Scene:"
-msgstr "Escena d'Origen:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Same as Target Scene"
-msgstr "Igual que l'Escena de Destinació"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Shared"
-msgstr "Compartit"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Target Texture Folder:"
-msgstr "Directori per a Textures escollit:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Post-Process Script:"
-msgstr "Script de Post-Processat:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Custom Root Node Type:"
-msgstr "Tipus de Node Arrel Personalitzat:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Auto"
-msgstr "Auto"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#, fuzzy
-msgid "Root Node Name:"
-msgstr "Nom del node:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "The Following Files are Missing:"
-msgstr "Manquen els següents Fitxers:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Anyway"
-msgstr "Importa Igualment"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp scene/gui/dialogs.cpp
-msgid "Cancel"
-msgstr "Cancel·la"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import & Open"
-msgstr "Importa i Obre"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Edited scene has not been saved, open imported scene anyway?"
-msgstr ""
-"No s'ha desat l'escena editada. Vol obrir l'escena importada igualment?"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Image:"
-msgstr "Importa Imatge:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Can't import a file over itself:"
-msgstr "No es pot importar un fitxer dins de si mateix:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't localize path: %s (already local)"
-msgstr "No s'ha pogut localitzar el camí: %s (ja és local)"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "3D Scene Animation"
-msgstr "Animació d'Escenes 3D"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Uncompressed"
-msgstr "Sense Compressió"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossless (PNG)"
-msgstr "Compressió sense Pèrdua (PNG)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossy (WebP)"
-msgstr "Compressió amb Pèrdua (WebP)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress (VRAM)"
-msgstr "Compressió (VRAM)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Format"
-msgstr "Format de Textura"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Compression Quality (WebP):"
-msgstr "Qualitat de Compressió de Textura (WebP):"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Options"
-msgstr "Opcions de Textura"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Please specify some files!"
-msgstr "Cal especificar algun fitxer!"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "At least one file needed for Atlas."
-msgstr "Es necessita com a mínim un fitxer per a l'Atles."
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Error importing:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Only one file is required for large texture."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Max Texture Size:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for Atlas (2D)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cell Size:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Large Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Textures (2D)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture"
+#: editor/multi_node_edit.cpp
+msgid "MultiNode Set"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Base Atlas Texture"
+#: editor/node_dock.cpp
+msgid "Groups"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s)"
+#: editor/node_dock.cpp
+msgid "Select a Node to edit Signals and Groups."
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 2D"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create Poly"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 3D"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Insert Point"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "2D Texture"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly (Remove Point)"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "3D Texture"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Remove Poly And Point"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Atlas Texture"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create a new polygon from scratch."
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
+#: editor/plugins/abstract_polygon_2d_editor.cpp
msgid ""
-"NOTICE: Importing 2D textures is not mandatory. Just copy png/jpg files to "
-"the project."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Crop empty space."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Load Source Image"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Slicing"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Inserting"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Saving"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save large texture:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Build Atlas For:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Loading Image:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't load image:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Converting Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cropping Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Blitting Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save atlas image:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save converted texture:"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid source!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid translation source!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Column"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/script_create_dialog.cpp
-msgid "Language"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No items to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No target path!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translations"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Couldn't import!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translation"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Source CSV:"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Ignore First Row"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Compress"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Add to Project (project.godot)"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Languages:"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Translation"
-msgstr ""
-
-#: editor/multi_node_edit.cpp
-msgid "MultiNode Set"
-msgstr ""
-
-#: editor/node_dock.cpp
-msgid "Groups"
-msgstr ""
-
-#: editor/node_dock.cpp
-msgid "Select a Node to edit Signals and Groups."
+"Edit existing polygon:\n"
+"LMB: Move Point.\n"
+"Ctrl+LMB: Split Segment.\n"
+"RMB: Erase Point."
msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
@@ -3506,7 +2912,6 @@ msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
#: editor/script_create_dialog.cpp
msgid "Error!"
@@ -3617,10 +3022,6 @@ msgid "Delete Input"
msgstr ""
#: editor/plugins/animation_tree_editor_plugin.cpp
-msgid "Rename"
-msgstr ""
-
-#: editor/plugins/animation_tree_editor_plugin.cpp
msgid "Animation tree is valid."
msgstr ""
@@ -3676,64 +3077,191 @@ msgstr ""
msgid "Filters.."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing %d Triangles:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Free"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Triangle #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Contents:"
+msgstr "Constants:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "View Files"
+msgstr "Fitxer:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve hostname:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Light Baker Setup:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing Geometry"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connection error, please try again."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Fixing Lights"
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Can't connect."
+msgstr "Connecta.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Can't connect to host:"
+msgstr "Connecta al Node:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response from host:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Making BVH"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Light Octree"
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Request failed, return code:"
+msgstr "Format de fitxer desconegut:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Req. Failed."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Octree Texture"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, too many redirects"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Transfer to Lightmaps:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Redirect Loop."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Allocating Texture #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Baking Triangle #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Bad download hash, assuming file has been tampered with."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Post-Processing Texture #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Expected:"
msgstr ""
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Bake!"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Got:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed sha256 hash check"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Asset Download Error:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Fetching:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Resolving.."
+msgstr "Desant..."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Connecting.."
+msgstr "Connecta.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Requesting.."
+msgstr "Provant"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Error making request"
+msgstr "Error en desar recurs!"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Idle"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Retry"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Download Error"
+msgstr "Errors de Càrrega"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download for this asset is already in progress!"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "first"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "prev"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "next"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "last"
msgstr ""
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Reset the lightmap octree baking process (start over)."
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "All"
+msgstr "Tot"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Plugins"
msgstr ""
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Sort:"
+msgstr "Ordena:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Reverse"
+msgstr "Inverteix"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Category:"
+msgstr "Categoria:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Site:"
+msgstr "Lloc:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Support.."
+msgstr "Suport..."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Official"
+msgstr "Oficial"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Testing"
+msgstr "Provant"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Assets ZIP File"
+msgstr "Arxiu ZIP d'Actius"
+
#: editor/plugins/camera_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
msgid "Preview"
msgstr ""
@@ -3776,11 +3304,15 @@ msgid "Edit CanvasItem"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Change Anchors"
+msgid "Anchors only"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom (%):"
+msgid "Change Anchors and Margins"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Change Anchors"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3831,59 +3363,74 @@ msgid "Pan Mode"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Lock the selected object in place (can't be moved)."
+#, fuzzy
+msgid "Toggles snapping"
+msgstr "Commuta el punt d'Interrupció"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Use Snap"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Unlock the selected object (can be moved)."
+#, fuzzy
+msgid "Snapping options"
+msgstr "Opcions d'Animació"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to grid"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Makes sure the object's children are not selectable."
+msgid "Use Rotation Snap"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Restores the object's children's ability to be selected."
+msgid "Configure Snap..."
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Edit"
-msgstr "Edita"
+msgid "Snap Relative"
+msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Use Snap"
+msgid "Use Pixel Snap"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Show Grid"
+msgid "Smart snapping"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Rotation Snap"
+msgid "Snap to parent"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap Relative"
+msgid "Snap to node anchor"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Configure Snap.."
+msgid "Snap to node sides"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Pixel Snap"
+msgid "Snap to other nodes"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Skeleton.."
+msgid "Lock the selected object in place (can't be moved)."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Unlock the selected object (can be moved)."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Makes sure the object's children are not selectable."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Restores the object's children's ability to be selected."
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3912,11 +3459,16 @@ msgid "View"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Reset"
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Show Grid"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Show helpers"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Set.."
+msgid "Show rulers"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3928,8 +3480,9 @@ msgid "Frame Selection"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Anchor"
-msgstr ""
+#, fuzzy
+msgid "Layout"
+msgstr "Desar Disposició (Layout)"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Insert Keys"
@@ -3952,11 +3505,20 @@ msgid "Clear Pose"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Set a Value"
+msgid "Drag pivot from mouse position"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap (Pixels):"
+#, fuzzy
+msgid "Set pivot at mouse position"
+msgstr "Treu Senyal"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Multiply grid step by 2"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Divide grid step by 2"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3967,23 +3529,28 @@ msgstr ""
msgid "Adding %s..."
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Create Node"
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Error instancing scene from %s"
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "OK :("
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "No parent to instance a child at."
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "This operation requires a single selected node."
msgstr ""
@@ -3998,45 +3565,6 @@ msgid ""
"Drag & drop + Alt : Change node type"
msgstr ""
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Create Poly"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly (Remove Point)"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Create a new polygon from scratch."
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-msgid ""
-"Edit existing polygon:\n"
-"LMB: Move Point.\n"
-"Ctrl+LMB: Split Segment.\n"
-"RMB: Erase Point."
-msgstr ""
-
#: editor/plugins/collision_polygon_editor_plugin.cpp
msgid "Create Poly3D"
msgstr ""
@@ -4046,14 +3574,6 @@ msgid "Set Handle"
msgstr ""
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Creating Mesh Library"
-msgstr ""
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Thumbnail.."
-msgstr ""
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Remove item %d?"
msgstr ""
@@ -4076,6 +3596,27 @@ msgid "Update from Scene"
msgstr ""
#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat0"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat1"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+#, fuzzy
+msgid "Ease in"
+msgstr "Escala la Selecció"
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Ease out"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Smoothstep"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
msgid "Modify Curve Point"
msgstr ""
@@ -4157,22 +3698,18 @@ msgid "Create Occluder Polygon"
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Edit existing polygon:"
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "LMB: Move Point."
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Ctrl+LMB: Split Segment."
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "RMB: Erase Point."
msgstr ""
@@ -4274,6 +3811,10 @@ msgid "Create Outline"
msgstr ""
#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Mesh"
+msgstr "Malla"
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Create Trimesh Static Body"
msgstr ""
@@ -4401,12 +3942,73 @@ msgstr ""
msgid "Populate"
msgstr ""
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Create Navigation Polygon"
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake!"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake the navigation mesh.\n"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Clear the navigation mesh."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Setting up Configuration..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Calculating grid size..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating heightfield..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Marking walkable triangles..."
+msgstr "Cadenes Traduïbles..."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Constructing compact heightfield..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Eroding walkable area..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Partitioning..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating contours..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating polymesh..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Converting to native navigation mesh..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Navigation Mesh Generator Setup:"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Parsing Geometry..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Done!"
msgstr ""
#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Remove Poly And Point"
+msgid "Create Navigation Polygon"
msgstr ""
#: editor/plugins/particles_2d_editor_plugin.cpp
@@ -4582,16 +4184,19 @@ msgid "Curve Point #"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve Point Position"
-msgstr ""
+msgstr "Treu Senyal"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve In Position"
-msgstr ""
+msgstr "Treu Senyal"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve Out Position"
-msgstr ""
+msgstr "Treu Senyal"
#: editor/plugins/path_editor_plugin.cpp
msgid "Split Path"
@@ -4651,6 +4256,14 @@ msgid "Scale Polygon"
msgstr ""
#: editor/plugins/polygon_2d_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Edit"
+msgstr "Edita"
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Polygon->UV"
msgstr ""
@@ -4705,63 +4318,10 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/shader_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "Enganxa"
-#: editor/plugins/rich_text_editor_plugin.cpp
-msgid "Parse BBCode"
-msgstr ""
-
-#: editor/plugins/sample_editor_plugin.cpp
-msgid "Length:"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Open Sample File(s)"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "ERROR: Couldn't load sample!"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Add Sample"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Rename Sample"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Delete Sample"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "16 Bits"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "8 Bits"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Stereo"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Mono"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Format"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Pitch"
-msgstr ""
-
#: editor/plugins/script_editor_plugin.cpp
msgid "Clear Recent Files"
msgstr ""
@@ -4853,6 +4413,10 @@ msgstr ""
msgid "Close All"
msgstr "Tanca"
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+msgid "Run"
+msgstr ""
+
#: editor/plugins/script_editor_plugin.cpp
#, fuzzy
msgid "Toggle Scripts Panel"
@@ -4882,7 +4446,8 @@ msgstr ""
msgid "Break"
msgstr ""
-#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+#: editor/script_editor_debugger.cpp
msgid "Continue"
msgstr ""
@@ -4896,18 +4461,6 @@ msgid "Debug with external editor"
msgstr "Editor de Dependències"
#: editor/plugins/script_editor_plugin.cpp
-msgid "Window"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Left"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Right"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
msgid "Open Godot online documentation"
msgstr ""
@@ -4991,8 +4544,9 @@ msgid "Cut"
msgstr "Talla"
#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "Copia"
@@ -5258,10 +4812,6 @@ msgid "View Plane Transform."
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Scaling to %s%%."
-msgstr ""
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rotating %s degrees."
msgstr ""
@@ -5278,10 +4828,6 @@ msgid "Top View."
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Top"
-msgstr ""
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rear View."
msgstr ""
@@ -5520,6 +5066,10 @@ msgid "Transform"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Configure Snap.."
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Local Coords"
msgstr ""
@@ -5665,6 +5215,10 @@ msgid "Speed (FPS):"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Loop"
+msgstr "Bucle"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Animation Frames"
msgstr ""
@@ -5677,11 +5231,12 @@ msgid "Insert Empty (After)"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Up"
-msgstr ""
+#, fuzzy
+msgid "Move (Before)"
+msgstr "Copia Nodes"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Down"
+msgid "Move (After)"
msgstr ""
#: editor/plugins/style_box_editor_plugin.cpp
@@ -5760,7 +5315,11 @@ msgid "Remove All"
msgstr "Treu"
#: editor/plugins/theme_editor_plugin.cpp
-msgid "Theme"
+msgid "Edit theme.."
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Theme editing menu."
msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
@@ -5845,6 +5404,10 @@ msgid "Style"
msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
+msgid "Font"
+msgstr "Lletra"
+
+#: editor/plugins/theme_editor_plugin.cpp
msgid "Color"
msgstr ""
@@ -5895,7 +5458,7 @@ msgid "Mirror Y"
msgstr ""
#: editor/plugins/tile_map_editor_plugin.cpp
-msgid "Bucket"
+msgid "Paint Tile"
msgstr ""
#: editor/plugins/tile_map_editor_plugin.cpp
@@ -5962,6 +5525,10 @@ msgid "Delete preset '%s'?"
msgstr "Esborra fitxers seleccionats?"
#: editor/project_export.cpp
+msgid "Export templates for this platform are missing/corrupted: "
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Presets"
msgstr ""
@@ -6038,33 +5605,58 @@ msgid "Export templates for this platform are missing:"
msgstr ""
#: editor/project_export.cpp
+msgid "Export templates for this platform are missing/corrupted:"
+msgstr ""
+
+#: editor/project_export.cpp
#, fuzzy
msgid "Export With Debug"
msgstr "Exporta el joc de Mosaics (Tiles)"
#: editor/project_manager.cpp
-msgid "Invalid project path, the path must exist!"
+#, fuzzy
+msgid "The path does not exist."
+msgstr "El Fitxer no existeix."
+
+#: editor/project_manager.cpp
+msgid "Please choose a 'project.godot' file."
msgstr ""
#: editor/project_manager.cpp
-#, fuzzy
-msgid "Invalid project path, project.godot must not exist."
-msgstr "El camí de Destinació ha d'existir."
+msgid ""
+"Your project will be created in a non empty folder (you might want to create "
+"a new folder)."
+msgstr ""
#: editor/project_manager.cpp
-#, fuzzy
-msgid "Invalid project path, project.godot must exist."
-msgstr "El camí de Destinació ha d'existir."
+msgid "Please choose a folder that does not contain a 'project.godot' file."
+msgstr ""
#: editor/project_manager.cpp
msgid "Imported Project"
msgstr ""
#: editor/project_manager.cpp
+msgid " "
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "It would be a good idea to name your project."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Invalid project path (changed anything?)."
msgstr ""
#: editor/project_manager.cpp
+msgid "Couldn't get project.godot in project path."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Couldn't edit project.godot in project path."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
msgstr ""
@@ -6073,15 +5665,20 @@ msgid "The following files failed extraction from package:"
msgstr ""
#: editor/project_manager.cpp
-msgid "Import Existing Project"
+#, fuzzy
+msgid "Rename Project"
+msgstr "Exporta Projecte"
+
+#: editor/project_manager.cpp
+msgid "Couldn't get project.godot in the project path."
msgstr ""
#: editor/project_manager.cpp
-msgid "Project Path (Must Exist):"
+msgid "New Game Project"
msgstr ""
#: editor/project_manager.cpp
-msgid "Project Name:"
+msgid "Import Existing Project"
msgstr ""
#: editor/project_manager.cpp
@@ -6089,19 +5686,24 @@ msgid "Create New Project"
msgstr ""
#: editor/project_manager.cpp
-msgid "Project Path:"
+msgid "Install Project:"
msgstr ""
#: editor/project_manager.cpp
-msgid "Install Project:"
+msgid "Project Name:"
msgstr ""
#: editor/project_manager.cpp
-msgid "Browse"
+#, fuzzy
+msgid "Create folder"
+msgstr "Crea una Carpeta"
+
+#: editor/project_manager.cpp
+msgid "Project Path:"
msgstr ""
#: editor/project_manager.cpp
-msgid "New Game Project"
+msgid "Browse"
msgstr ""
#: editor/project_manager.cpp
@@ -6113,6 +5715,11 @@ msgid "Unnamed Project"
msgstr ""
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Can't open project"
+msgstr "Connecta.."
+
+#: editor/project_manager.cpp
msgid "Are you sure to open more than one project?"
msgstr ""
@@ -6143,16 +5750,18 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
-"You are about the scan %s folders for existing Godot projects. Do you "
-"confirm?"
+"Language changed.\n"
+"The UI will update next time the editor or project manager starts."
msgstr ""
#: editor/project_manager.cpp
-msgid "Project List"
+msgid ""
+"You are about the scan %s folders for existing Godot projects. Do you "
+"confirm?"
msgstr ""
#: editor/project_manager.cpp
-msgid "Run"
+msgid "Project List"
msgstr ""
#: editor/project_manager.cpp
@@ -6177,6 +5786,10 @@ msgid "Exit"
msgstr ""
#: editor/project_manager.cpp
+msgid "Restart Now"
+msgstr ""
+
+#: editor/project_manager.cpp
#, fuzzy
msgid "Can't run project"
msgstr "Connecta.."
@@ -6214,17 +5827,14 @@ msgid "Add Input Action Event"
msgstr ""
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Meta+"
msgstr "Meta +"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Shift+"
msgstr "Maj +"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Alt+"
msgstr "Alt +"
@@ -6285,7 +5895,7 @@ msgstr "Canvia"
msgid "Joypad Axis Index:"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Axis"
msgstr "Eix"
@@ -6305,31 +5915,31 @@ msgstr ""
msgid "Add Event"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Device"
msgstr "Dispositiu"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Button"
msgstr "Botó"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Left Button."
msgstr "Botó Esquerre."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Right Button."
msgstr "Botó Dret."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Middle Button."
msgstr "Botó del Mig."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Up."
msgstr "Roda Amunt."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Down."
msgstr "Roda Avall."
@@ -6339,7 +5949,7 @@ msgid "Add Global Property"
msgstr "Afegeix Propietat d'Accés (Getter)"
#: editor/project_settings_editor.cpp
-msgid "Select an setting item first!"
+msgid "Select a setting item first!"
msgstr ""
#: editor/project_settings_editor.cpp
@@ -6357,6 +5967,15 @@ msgid "Delete Item"
msgstr "Esborra"
#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Can't contain '/' or ':'"
+msgstr "Connecta al Node:"
+
+#: editor/project_settings_editor.cpp
+msgid "Already existing"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "Error saving settings."
msgstr "No s'ha pogut desar la configuració."
@@ -6398,6 +6017,15 @@ msgstr ""
#: editor/project_settings_editor.cpp
#, fuzzy
+msgid "Changed Locale Filter"
+msgstr "Canvia Tipus de la Matriu"
+
+#: editor/project_settings_editor.cpp
+msgid "Changed Locale Filter Mode"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
msgid "Project Settings (project.godot)"
msgstr "Configuració del Projecte (engine.cfg)"
@@ -6458,6 +6086,27 @@ msgid "Locale"
msgstr ""
#: editor/project_settings_editor.cpp
+msgid "Locales Filter"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Show all locales"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Show only selected locales"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Filter mode:"
+msgstr "Filtres"
+
+#: editor/project_settings_editor.cpp
+msgid "Locales:"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "AutoLoad"
msgstr ""
@@ -6510,10 +6159,20 @@ msgstr "Executa Script"
#: editor/property_editor.cpp
#, fuzzy
+msgid "Make Unique"
+msgstr "Crea SubRecurs Únic"
+
+#: editor/property_editor.cpp
+#, fuzzy
msgid "Show in File System"
msgstr "SistemaDeFitxers"
#: editor/property_editor.cpp
+#, fuzzy
+msgid "Convert To %s"
+msgstr "Converteix a..."
+
+#: editor/property_editor.cpp
msgid "Error loading file: Not a resource!"
msgstr ""
@@ -6554,6 +6213,11 @@ msgstr "Afegeix Col.locador de Proprietat (Setter)"
#: editor/property_selector.cpp
#, fuzzy
+msgid "Select Virtual Method"
+msgstr "Mètodes públics:"
+
+#: editor/property_selector.cpp
+#, fuzzy
msgid "Select Method"
msgstr "Mètodes públics:"
@@ -6581,26 +6245,6 @@ msgstr ""
msgid "Reparent"
msgstr ""
-#: editor/resources_dock.cpp
-msgid "Create New Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Open Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Save Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Resource Tools"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Make Local"
-msgstr ""
-
#: editor/run_settings_dialog.cpp
msgid "Run Mode:"
msgstr ""
@@ -6728,14 +6372,6 @@ msgid "Sub-Resources:"
msgstr "Recurs"
#: editor/scene_tree_dock.cpp
-msgid "Edit Groups"
-msgstr ""
-
-#: editor/scene_tree_dock.cpp
-msgid "Edit Connections"
-msgstr ""
-
-#: editor/scene_tree_dock.cpp
msgid "Clear Inheritance"
msgstr ""
@@ -6924,6 +6560,15 @@ msgid "Invalid base path"
msgstr ""
#: editor/script_create_dialog.cpp
+msgid "Directory of the same name exists"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
+#, fuzzy
+msgid "File exists, will be reused"
+msgstr "Fitxer Existent, Sobreescriure?"
+
+#: editor/script_create_dialog.cpp
msgid "Invalid extension"
msgstr ""
@@ -6968,6 +6613,10 @@ msgid "Load existing script file"
msgstr "No s'ha pogut instanciar l'script:"
#: editor/script_create_dialog.cpp
+msgid "Language"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
#, fuzzy
msgid "Inherits"
msgstr "Hereta:"
@@ -7013,6 +6662,10 @@ msgid "Function:"
msgstr ""
#: editor/script_editor_debugger.cpp
+msgid "Pick one or more items from the list to display the graph."
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
msgid "Errors"
msgstr ""
@@ -7093,6 +6746,10 @@ msgid "Type"
msgstr ""
#: editor/script_editor_debugger.cpp
+msgid "Format"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
msgid "Usage"
msgstr ""
@@ -7168,12 +6825,30 @@ msgstr ""
msgid "Change Probe Extents"
msgstr ""
+#: modules/gdnative/gd_native_library_editor.cpp
+#, fuzzy
+msgid "Library"
+msgstr "Biblioteca de Models (MeshLibrary)..."
+
+#: modules/gdnative/gd_native_library_editor.cpp
+#, fuzzy
+msgid "Status"
+msgstr "Estat:"
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Libraries: "
+msgstr ""
+
+#: modules/gdnative/register_types.cpp
+msgid "GDNative"
+msgstr ""
+
#: modules/gdscript/gd_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Invalid type argument to convert(), use TYPE_* constants."
msgstr "Argument de tipus invàlid per a convert(), utilitzi constants TYPE_*."
-#: modules/gdscript/gd_functions.cpp
+#: modules/gdscript/gd_functions.cpp modules/mono/glue/glue_header.h
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Not enough bytes for decoding bytes, or invalid format."
msgstr ""
@@ -7229,10 +6904,6 @@ msgid "GridMap Duplicate Selection"
msgstr "Duplica la Selecció"
#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "GridMap Paint"
-msgstr ""
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Snap View"
msgstr ""
@@ -7329,13 +7000,8 @@ msgstr "Configuració de Desplaçament"
msgid "Pick Distance:"
msgstr ""
-#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
-msgid "Tiles"
-msgstr "Fitxer:"
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "Areas"
+#: modules/mono/editor/mono_bottom_panel.cpp
+msgid "Builds"
msgstr ""
#: modules/visual_script/visual_script.cpp
@@ -7549,10 +7215,18 @@ msgid "Return"
msgstr "Retorn:"
#: modules/visual_script/visual_script_editor.cpp
+msgid "Call"
+msgstr "Crida"
+
+#: modules/visual_script/visual_script_editor.cpp
msgid "Get"
msgstr "Obtenir"
#: modules/visual_script/visual_script_editor.cpp
+msgid "Script already has function '%s'"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
#, fuzzy
msgid "Change Input Value"
msgstr "Canvia Valor de la Matriu"
@@ -7971,6 +7645,12 @@ msgstr ""
"Cal crear o establir un recurs SpriteFrames en la propietat 'Frames' perquè "
"AnimatedSprite3D dibuixi els quadres."
+#: scene/3d/vehicle_body.cpp
+msgid ""
+"VehicleWheel serves to provide a wheel system to a VehicleBody. Please use "
+"it as a child of a VehicleBody."
+msgstr ""
+
#: scene/gui/color_picker.cpp
msgid "Raw Mode"
msgstr ""
@@ -7980,6 +7660,10 @@ msgid "Add current color as a preset"
msgstr ""
#: scene/gui/dialogs.cpp
+msgid "Cancel"
+msgstr "Cancel·la"
+
+#: scene/gui/dialogs.cpp
msgid "Alert!"
msgstr "Ep!"
@@ -7987,10 +7671,6 @@ msgstr "Ep!"
msgid "Please Confirm..."
msgstr "Confirmeu..."
-#: scene/gui/input_action.cpp
-msgid "Ctrl+"
-msgstr "Ctrl +"
-
#: scene/gui/popup.cpp
msgid ""
"Popups will hide by default unless you call popup() or any of the popup*() "
@@ -8026,6 +7706,355 @@ msgstr ""
"forma per tal d'obtenir-ne la mida. Altrament, establiu-la com a Destinació "
"de Renderització i assigneu-ne la textura interna a algun node."
+#: scene/resources/dynamic_font.cpp
+msgid "Error initializing FreeType."
+msgstr "Error inicialitzant FreeType."
+
+#: scene/resources/dynamic_font.cpp
+msgid "Unknown font format."
+msgstr "Format de lletra desconegut."
+
+#: scene/resources/dynamic_font.cpp
+msgid "Error loading font."
+msgstr "Error carregant lletra."
+
+#: scene/resources/dynamic_font.cpp
+msgid "Invalid font size."
+msgstr "La mida de la lletra no és vàlida."
+
+#~ msgid "Filter:"
+#~ msgstr "Filtre:"
+
+#~ msgid "Method List For '%s':"
+#~ msgstr "Llista de mètodes de '%s':"
+
+#~ msgid "Arguments:"
+#~ msgstr "Arguments:"
+
+#~ msgid "Return:"
+#~ msgstr "Retorn:"
+
+#~ msgid "Added:"
+#~ msgstr "Afegit:"
+
+#~ msgid "Removed:"
+#~ msgstr "Eliminat:"
+
+#~ msgid "Error saving atlas:"
+#~ msgstr "Error en desar atles:"
+
+#~ msgid "Could not save atlas subtexture:"
+#~ msgstr "No s'ha pogut desar la subtextura de l'atles:"
+
+#~ msgid "Exporting for %s"
+#~ msgstr "Exportació per a %s"
+
+#~ msgid "Setting Up.."
+#~ msgstr "Instal·lant.."
+
+#~ msgid "Error loading scene."
+#~ msgstr "No s'ha pogut carregar l'escena."
+
+#~ msgid "Re-Import"
+#~ msgstr "ReImporta"
+
+#~ msgid "Please wait for scan to complete."
+#~ msgstr "Espera que s'acabi l'anàlisi."
+
+#~ msgid "Current scene must be saved to re-import."
+#~ msgstr "S'ha de desar l'escena abans de reimportar-la."
+
+#~ msgid "Save & Re-Import"
+#~ msgstr "Desa i ReImporta"
+
+#~ msgid "Re-Importing"
+#~ msgstr "Re-Importació"
+
+#~ msgid "Re-Import Changed Resources"
+#~ msgstr "ReImporta Recursos Modificats"
+
+#~ msgid "Loading Export Templates"
+#~ msgstr "Carregant Plantilles d'Exportació"
+
+#, fuzzy
+#~ msgid ""
+#~ "\n"
+#~ "Status: Needs Re-Import"
+#~ msgstr "Desa i ReImporta"
+
+#~ msgid "Same source and destination files, doing nothing."
+#~ msgstr ""
+#~ "Els fitxers d'origen i destinació són els mateixos. No s'ha produït cap "
+#~ "acció."
+
+#~ msgid "Same source and destination paths, doing nothing."
+#~ msgstr ""
+#~ "El camí d'origen i destinació es idèntic. No s'ha produït cap acció."
+
+#~ msgid "Can't move directories to within themselves."
+#~ msgstr "No es poden moure directoris en si mateixos."
+
+#, fuzzy
+#~ msgid "Error moving file:\n"
+#~ msgstr "Error en desar TileSet!"
+
+#~ msgid "Pick New Name and Location For:"
+#~ msgstr "Tria un Nou Nom i Ubicació per a:"
+
+#~ msgid "No files selected!"
+#~ msgstr "Cap fitxer seleccionat!"
+
+#~ msgid "Info"
+#~ msgstr "Informació"
+
+#~ msgid "Re-Import.."
+#~ msgstr "ReImporta..."
+
+#~ msgid "No bit masks to import!"
+#~ msgstr "Cap màscara de bits per importar!"
+
+#~ msgid "Target path is empty."
+#~ msgstr "El camí de Destinació és buit."
+
+#~ msgid "Target path must be a complete resource path."
+#~ msgstr "El camí de Destinació ha de ser un camí de recursos complet."
+
+#~ msgid "Target path must exist."
+#~ msgstr "El camí de Destinació ha d'existir."
+
+#~ msgid "Save path is empty!"
+#~ msgstr "El camí per desar és buit!"
+
+#~ msgid "Import BitMasks"
+#~ msgstr "Importa Màscares de Bit"
+
+#~ msgid "Source Texture(s):"
+#~ msgstr "Textures Font:"
+
+#~ msgid "Target Path:"
+#~ msgstr "Camí de Destinació:"
+
+#~ msgid "Accept"
+#~ msgstr "Accepta"
+
+#~ msgid "Bit Mask"
+#~ msgstr "Màscara de bits"
+
+#~ msgid "No source font file!"
+#~ msgstr "Cap fitxer de lletra font!"
+
+#~ msgid "No target font resource!"
+#~ msgstr "Cap recurs de Lletra!"
+
+#, fuzzy
+#~ msgid ""
+#~ "Invalid file extension.\n"
+#~ "Please use .font."
+#~ msgstr ""
+#~ "Extensió de fitxer no vàlida.\n"
+#~ "Utilitzeu .fnt."
+
+#~ msgid "Couldn't save font."
+#~ msgstr "No s'ha pogut desar la lletra."
+
+#~ msgid "Source Font:"
+#~ msgstr "Lletra:"
+
+#~ msgid "Source Font Size:"
+#~ msgstr "Mida de la lletra:"
+
+#~ msgid "Dest Resource:"
+#~ msgstr "Recurs Objectiu:"
+
+#~ msgid "The quick brown fox jumps over the lazy dog."
+#~ msgstr ""
+#~ "«Dóna amor que seràs feliç!». Això, il·lús veí i company geniüt, ja és un "
+#~ "lluït rètol d'onze kWh."
+
+#~ msgid "Test:"
+#~ msgstr "Prova:"
+
+#~ msgid "Options:"
+#~ msgstr "Opcions:"
+
+#~ msgid "Font Import"
+#~ msgstr "Importa lletra"
+
+#~ msgid ""
+#~ "This file is already a Godot font file, please supply a BMFont type file "
+#~ "instead."
+#~ msgstr ""
+#~ "Aquest fitxer ja és un fitxer de lletra de Godot. Proveïu un fitxer de "
+#~ "tipus BMFont."
+
+#~ msgid "Failed opening as BMFont file."
+#~ msgstr "No s'ha pogut obrir com a fitxer BMFont."
+
+#~ msgid "Invalid font custom source."
+#~ msgstr "Lletra personalitzada no vàlida."
+
+#~ msgid "No meshes to import!"
+#~ msgstr "Cap malla per importar!"
+
+#~ msgid "Single Mesh Import"
+#~ msgstr "Importa una Malla"
+
+#~ msgid "Source Mesh(es):"
+#~ msgstr "Malla/es :"
+
+#~ msgid "Surface %d"
+#~ msgstr "Superfície %d"
+
+#~ msgid "No samples to import!"
+#~ msgstr "No s'ha trobat cap mostra d'Àudio per importar!"
+
+#~ msgid "Import Audio Samples"
+#~ msgstr "Importa Mostra d'Àudio"
+
+#~ msgid "Source Sample(s):"
+#~ msgstr "Mostra/es d'Origen:"
+
+#~ msgid "Audio Sample"
+#~ msgstr "Mostra d'Àudio"
+
+#~ msgid "New Clip"
+#~ msgstr "Nou Clip"
+
+#, fuzzy
+#~ msgid "Flags"
+#~ msgstr "Indicadors (flags)"
+
+#~ msgid "Bake FPS:"
+#~ msgstr "Fer Bake dels FPS:"
+
+#~ msgid "Optimizer"
+#~ msgstr "Optimitzador"
+
+#~ msgid "Max Linear Error"
+#~ msgstr "Error Lineal Màxim"
+
+#~ msgid "Max Angular Error"
+#~ msgstr "Error Angular Màxim"
+
+#~ msgid "Max Angle"
+#~ msgstr "Angle Màxim"
+
+#~ msgid "Clips"
+#~ msgstr "Clips"
+
+#~ msgid "Start(s)"
+#~ msgstr "Inici/s"
+
+#~ msgid "End(s)"
+#~ msgstr "Final/s"
+
+#~ msgid "Filters"
+#~ msgstr "Filtres"
+
+#~ msgid "Source path is empty."
+#~ msgstr "El camí d'origen és buit."
+
+#~ msgid "Couldn't load post-import script."
+#~ msgstr "No s'ha pogut carregar l'script de post-importació."
+
+#~ msgid "Invalid/broken script for post-import."
+#~ msgstr "L'script de post-importació no és vàlid ."
+
+#~ msgid "Error importing scene."
+#~ msgstr "No s'ha pogut importar l'escena."
+
+#~ msgid "Import 3D Scene"
+#~ msgstr "Importa Escena 3D"
+
+#~ msgid "Source Scene:"
+#~ msgstr "Escena d'Origen:"
+
+#~ msgid "Same as Target Scene"
+#~ msgstr "Igual que l'Escena de Destinació"
+
+#~ msgid "Shared"
+#~ msgstr "Compartit"
+
+#~ msgid "Target Texture Folder:"
+#~ msgstr "Directori per a Textures escollit:"
+
+#~ msgid "Post-Process Script:"
+#~ msgstr "Script de Post-Processat:"
+
+#~ msgid "Custom Root Node Type:"
+#~ msgstr "Tipus de Node Arrel Personalitzat:"
+
+#~ msgid "Auto"
+#~ msgstr "Auto"
+
+#, fuzzy
+#~ msgid "Root Node Name:"
+#~ msgstr "Nom del node:"
+
+#~ msgid "The Following Files are Missing:"
+#~ msgstr "Manquen els següents Fitxers:"
+
+#~ msgid "Import Anyway"
+#~ msgstr "Importa Igualment"
+
+#~ msgid "Import & Open"
+#~ msgstr "Importa i Obre"
+
+#~ msgid "Edited scene has not been saved, open imported scene anyway?"
+#~ msgstr ""
+#~ "No s'ha desat l'escena editada. Vol obrir l'escena importada igualment?"
+
+#~ msgid "Import Image:"
+#~ msgstr "Importa Imatge:"
+
+#~ msgid "Couldn't localize path: %s (already local)"
+#~ msgstr "No s'ha pogut localitzar el camí: %s (ja és local)"
+
+#~ msgid "3D Scene Animation"
+#~ msgstr "Animació d'Escenes 3D"
+
+#~ msgid "Uncompressed"
+#~ msgstr "Sense Compressió"
+
+#~ msgid "Compress Lossless (PNG)"
+#~ msgstr "Compressió sense Pèrdua (PNG)"
+
+#~ msgid "Compress Lossy (WebP)"
+#~ msgstr "Compressió amb Pèrdua (WebP)"
+
+#~ msgid "Compress (VRAM)"
+#~ msgstr "Compressió (VRAM)"
+
+#~ msgid "Texture Format"
+#~ msgstr "Format de Textura"
+
+#~ msgid "Texture Compression Quality (WebP):"
+#~ msgstr "Qualitat de Compressió de Textura (WebP):"
+
+#~ msgid "Texture Options"
+#~ msgstr "Opcions de Textura"
+
+#~ msgid "Please specify some files!"
+#~ msgstr "Cal especificar algun fitxer!"
+
+#~ msgid "At least one file needed for Atlas."
+#~ msgstr "Es necessita com a mínim un fitxer per a l'Atles."
+
+#, fuzzy
+#~ msgid "Invalid project path, project.godot must not exist."
+#~ msgstr "El camí de Destinació ha d'existir."
+
+#, fuzzy
+#~ msgid "Invalid project path, project.godot must exist."
+#~ msgstr "El camí de Destinació ha d'existir."
+
+#, fuzzy
+#~ msgid "Tiles"
+#~ msgstr "Fitxer:"
+
+#~ msgid "Ctrl+"
+#~ msgstr "Ctrl +"
+
#~ msgid "Close scene? (Unsaved changes will be lost)"
#~ msgstr "Tanca l'Escena? (Es perdran els canvis sense desar)"
@@ -8150,9 +8179,6 @@ msgstr ""
#~ msgid "Save Translatable Strings"
#~ msgstr "Desa els texts Traduïbles"
-#~ msgid "Translatable Strings.."
-#~ msgstr "Cadenes Traduïbles..."
-
#~ msgid "Install Export Templates"
#~ msgstr "Instal·la Plantilles d'Exportació"
diff --git a/editor/translations/cs.po b/editor/translations/cs.po
index 929aa6eb30..8083094a39 100644
--- a/editor/translations/cs.po
+++ b/editor/translations/cs.po
@@ -1,5 +1,6 @@
# Czech translation of the Godot Engine editor
-# Copyright (C) 2016-2017 Juan Linietsky, Ariel Manzur and the Godot community
+# Copyright (C) 2007-2017 Juan Linietsky, Ariel Manzur
+# Copyright (C) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)
# This file is distributed under the same license as the Godot source code.
#
# Jan 'spl!te' Kondelík <j.kondelik@centrum.cz>, 2016.
@@ -194,10 +195,9 @@ msgid "Create %d NEW tracks and insert keys?"
msgstr "VytvoÅ™it %d NOVÃCH stop a vložit klíÄe?"
#: editor/animation_editor.cpp editor/create_dialog.cpp
-#: editor/editor_audio_buses.cpp
+#: editor/editor_audio_buses.cpp editor/plugins/abstract_polygon_2d_editor.cpp
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
#: editor/plugins/mesh_instance_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp editor/project_manager.cpp
#: editor/script_create_dialog.cpp
msgid "Create"
@@ -359,268 +359,6 @@ msgstr "Změnit typ hodnot pole"
msgid "Change Array Value"
msgstr "Změnit hodnotu pole"
-#: editor/asset_library_editor_plugin.cpp
-msgid "Free"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_plugin_settings.cpp
-msgid "Version:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Contents:"
-msgstr "Spojité"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "View Files"
-msgstr "Soubor:"
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_help.cpp editor/property_selector.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Description:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-#: editor/project_manager.cpp
-msgid "Install"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/call_dialog.cpp
-#: editor/connections_dialog.cpp editor/export_template_manager.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-#: editor/project_settings_editor.cpp editor/property_editor.cpp
-#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Close"
-msgstr "Zavřít"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve hostname:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Connection error, please try again."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Can't connect."
-msgstr "Připojit.."
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Can't connect to host:"
-msgstr "Připojit k uzlu:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response from host:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Request failed, return code:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Req. Failed."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Request failed, too many redirects"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Redirect Loop."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Bad download hash, assuming file has been tampered with."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Expected:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Got:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Asset Download Error:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-msgid "Success!"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Fetching:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Resolving.."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Connecting.."
-msgstr "Připojit.."
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Requesting.."
-msgstr "Testované"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Error making request"
-msgstr "Chyba nahrávání fontu."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Idle"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Retry"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Download Error"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Download for this asset is already in progress!"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "first"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "prev"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "next"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "last"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "All"
-msgstr "VÅ¡echny"
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
-#: editor/settings_config_dialog.cpp
-msgid "Search:"
-msgstr "Hledat:"
-
-#: editor/asset_library_editor_plugin.cpp editor/code_editor.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Search"
-msgstr "Hledat"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/project_manager.cpp
-msgid "Import"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Plugins"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Sort:"
-msgstr "Řadit:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Reverse"
-msgstr "Naopak"
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Category:"
-msgstr "Kategorie:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Site:"
-msgstr "Web:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Support.."
-msgstr "Podpora.."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Official"
-msgstr "Oficiální"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-msgid "Community"
-msgstr "Z komunity"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Testing"
-msgstr "Testované"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Assets ZIP File"
-msgstr "ZIP soubor asetů"
-
-#: editor/call_dialog.cpp
-msgid "Method List For '%s':"
-msgstr "Seznam metod '%s':"
-
-#: editor/call_dialog.cpp modules/visual_script/visual_script_editor.cpp
-msgid "Call"
-msgstr "Zavolat"
-
-#: editor/call_dialog.cpp
-msgid "Method List:"
-msgstr "Seznam metod:"
-
-#: editor/call_dialog.cpp
-msgid "Arguments:"
-msgstr "Argumenty:"
-
-#: editor/call_dialog.cpp
-msgid "Return:"
-msgstr "Vrátit:"
-
#: editor/code_editor.cpp
msgid "Go to Line"
msgstr "Běž na řádek"
@@ -658,6 +396,14 @@ msgstr "Celá slova"
msgid "Selection Only"
msgstr "Pouze výběr"
+#: editor/code_editor.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
+msgid "Search"
+msgstr "Hledat"
+
#: editor/code_editor.cpp editor/editor_help.cpp
msgid "Find"
msgstr "Najít"
@@ -690,11 +436,11 @@ msgstr "Potvrzovat nahrazení"
msgid "Skip"
msgstr "PÅ™eskoÄit"
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom In"
msgstr "Přiblížit"
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom Out"
msgstr "Oddálit"
@@ -761,6 +507,20 @@ msgstr "Odloženě"
msgid "Oneshot"
msgstr "Jednorázově"
+#: editor/connections_dialog.cpp editor/dependency_editor.cpp
+#: editor/export_template_manager.cpp
+#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Close"
+msgstr "Zavřít"
+
#: editor/connections_dialog.cpp
msgid "Connect"
msgstr "Připojit"
@@ -786,7 +546,7 @@ msgstr "Připojit.."
msgid "Disconnect"
msgstr "Odpojit"
-#: editor/connections_dialog.cpp editor/node_dock.cpp
+#: editor/connections_dialog.cpp editor/editor_help.cpp editor/node_dock.cpp
msgid "Signals"
msgstr "Signály"
@@ -803,12 +563,25 @@ msgstr ""
msgid "Recent:"
msgstr ""
+#: editor/create_dialog.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/quick_open.cpp editor/settings_config_dialog.cpp
+msgid "Search:"
+msgstr "Hledat:"
+
#: editor/create_dialog.cpp editor/editor_help.cpp
#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/quick_open.cpp
msgid "Matches:"
msgstr "Shody:"
+#: editor/create_dialog.cpp editor/editor_help.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/property_selector.cpp
+#: editor/script_editor_debugger.cpp
+msgid "Description:"
+msgstr ""
+
#: editor/dependency_editor.cpp
msgid "Search Replacement For:"
msgstr "Hledat náhradu za:"
@@ -868,6 +641,10 @@ msgid "Owners Of:"
msgstr "Vlastníci:"
#: editor/dependency_editor.cpp
+msgid "Remove selected files from the project? (no undo)"
+msgstr "Odebrat vybrané soubory z projektu? (nelze vrátit zpět)"
+
+#: editor/dependency_editor.cpp
msgid ""
"The files being removed are required by other resources in order for them to "
"work.\n"
@@ -877,8 +654,8 @@ msgstr ""
"Přesto je chcete smazat? (nelze vrátit zpět)"
#: editor/dependency_editor.cpp
-msgid "Remove selected files from the project? (no undo)"
-msgstr "Odebrat vybrané soubory z projektu? (nelze vrátit zpět)"
+msgid "Cannot remove:\n"
+msgstr ""
#: editor/dependency_editor.cpp
msgid "Error loading:"
@@ -944,10 +721,6 @@ msgid "Godot Engine contributors"
msgstr ""
#: editor/editor_about.cpp
-msgid "Authors"
-msgstr ""
-
-#: editor/editor_about.cpp
#, fuzzy
msgid "Project Founders"
msgstr "Nastavení projektu"
@@ -965,6 +738,38 @@ msgid "Developers"
msgstr ""
#: editor/editor_about.cpp
+msgid "Authors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Platinum Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Gold Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Mini Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Gold Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Silver Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Bronze Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
msgid "License"
msgstr ""
@@ -1007,6 +812,16 @@ msgid "Package Installed Successfully!"
msgstr ""
#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Success!"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/project_manager.cpp
+msgid "Install"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
msgid "Package Installer"
msgstr ""
@@ -1057,10 +872,6 @@ msgid "Audio Bus, Drag and Drop to rearrange."
msgstr ""
#: editor/editor_audio_buses.cpp
-msgid "Bus options"
-msgstr ""
-
-#: editor/editor_audio_buses.cpp
msgid "Solo"
msgstr ""
@@ -1072,6 +883,10 @@ msgstr ""
msgid "Bypass"
msgstr ""
+#: editor/editor_audio_buses.cpp
+msgid "Bus options"
+msgstr ""
+
#: editor/editor_audio_buses.cpp editor/plugins/tile_map_editor_plugin.cpp
#: editor/scene_tree_dock.cpp
msgid "Duplicate"
@@ -1079,6 +894,11 @@ msgstr ""
#: editor/editor_audio_buses.cpp
#, fuzzy
+msgid "Reset Volume"
+msgstr "Obnovit původní přiblížení"
+
+#: editor/editor_audio_buses.cpp
+#, fuzzy
msgid "Delete Effect"
msgstr "Smazat vybraný"
@@ -1101,6 +921,11 @@ msgid "Duplicate Audio Bus"
msgstr "Duplikovat výběr"
#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Reset Bus Volume"
+msgstr "Obnovit původní přiblížení"
+
+#: editor/editor_audio_buses.cpp
msgid "Move Audio Bus"
msgstr ""
@@ -1132,7 +957,8 @@ msgstr ""
msgid "Create a new Bus Layout."
msgstr ""
-#: editor/editor_audio_buses.cpp editor/script_create_dialog.cpp
+#: editor/editor_audio_buses.cpp editor/property_editor.cpp
+#: editor/script_create_dialog.cpp
msgid "Load"
msgstr ""
@@ -1224,7 +1050,7 @@ msgid "Rearrange Autoloads"
msgstr ""
#: editor/editor_autoload_settings.cpp editor/editor_file_dialog.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp scene/gui/file_dialog.cpp
+#: scene/gui/file_dialog.cpp
msgid "Path:"
msgstr "Cesta:"
@@ -1232,9 +1058,7 @@ msgstr "Cesta:"
msgid "Node Name:"
msgstr ""
-#: editor/editor_autoload_settings.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp editor/project_manager.cpp
+#: editor/editor_autoload_settings.cpp editor/project_manager.cpp
msgid "Name"
msgstr "Název"
@@ -1267,18 +1091,19 @@ msgid "Choose a Directory"
msgstr ""
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Create Folder"
msgstr "Vytvořit složku"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: editor/editor_plugin_settings.cpp editor/plugins/theme_editor_plugin.cpp
-#: editor/project_export.cpp scene/gui/file_dialog.cpp
+#: editor/editor_plugin_settings.cpp editor/filesystem_dock.cpp
+#: editor/plugins/theme_editor_plugin.cpp editor/project_export.cpp
+#: scene/gui/file_dialog.cpp
msgid "Name:"
msgstr "Jméno:"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Could not create folder."
msgstr "Nelze vytvořit složku."
@@ -1298,30 +1123,6 @@ msgstr ""
msgid "Template file not found:\n"
msgstr ""
-#: editor/editor_export.cpp
-msgid "Added:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Removed:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Error saving atlas:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Could not save atlas subtexture:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Exporting for %s"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Setting Up.."
-msgstr ""
-
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "File Exists, Overwrite?"
msgstr "Soubor už existuje. Přepsat?"
@@ -1406,6 +1207,11 @@ msgstr ""
msgid "Move Favorite Down"
msgstr ""
+#: editor/editor_file_dialog.cpp
+#, fuzzy
+msgid "Go to parent folder"
+msgstr "Nelze vytvořit složku."
+
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Directories & Files:"
msgstr "Složky a soubory:"
@@ -1420,10 +1226,6 @@ msgid "File:"
msgstr "Soubor:"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
-msgid "Filter:"
-msgstr "Filtr:"
-
-#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Must use a valid extension."
msgstr "Je nutné použít platnou příponu."
@@ -1448,6 +1250,10 @@ msgstr ""
msgid "Search Classes"
msgstr ""
+#: editor/editor_help.cpp editor/plugins/spatial_editor_plugin.cpp
+msgid "Top"
+msgstr ""
+
#: editor/editor_help.cpp editor/property_editor.cpp
msgid "Class:"
msgstr ""
@@ -1464,15 +1270,29 @@ msgstr ""
msgid "Brief Description:"
msgstr ""
+#: editor/editor_help.cpp
+#, fuzzy
+msgid "Members"
+msgstr "Členové:"
+
#: editor/editor_help.cpp modules/visual_script/visual_script_editor.cpp
msgid "Members:"
msgstr "Členové:"
#: editor/editor_help.cpp
+#, fuzzy
+msgid "Public Methods"
+msgstr "Vybrat vše"
+
+#: editor/editor_help.cpp
msgid "Public Methods:"
msgstr ""
#: editor/editor_help.cpp
+msgid "GUI Theme Items"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "GUI Theme Items:"
msgstr ""
@@ -1482,6 +1302,11 @@ msgstr "Signály:"
#: editor/editor_help.cpp
#, fuzzy
+msgid "Enumerations"
+msgstr "Funkce:"
+
+#: editor/editor_help.cpp
+#, fuzzy
msgid "Enumerations:"
msgstr "Funkce:"
@@ -1490,19 +1315,50 @@ msgid "enum "
msgstr ""
#: editor/editor_help.cpp
+#, fuzzy
+msgid "Constants"
+msgstr "Konstantní"
+
+#: editor/editor_help.cpp
msgid "Constants:"
msgstr ""
#: editor/editor_help.cpp
#, fuzzy
+msgid "Description"
+msgstr "Vytvořit odběr"
+
+#: editor/editor_help.cpp
+msgid "Properties"
+msgstr ""
+
+#: editor/editor_help.cpp
+#, fuzzy
msgid "Property Description:"
msgstr "Vytvořit odběr"
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this property. Please help us by "
+"[color=$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+
+#: editor/editor_help.cpp
+#, fuzzy
+msgid "Methods"
+msgstr "Seznam metod:"
+
+#: editor/editor_help.cpp
msgid "Method Description:"
msgstr ""
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this method. Please help us by [color="
+"$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Search Text"
msgstr ""
@@ -1511,24 +1367,21 @@ msgid "Output:"
msgstr ""
#: editor/editor_log.cpp editor/plugins/animation_tree_editor_plugin.cpp
-#: editor/plugins/rich_text_editor_plugin.cpp editor/property_editor.cpp
-#: editor/script_editor_debugger.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/property_editor.cpp editor/script_editor_debugger.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Clear"
msgstr "VyÄistit"
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Error saving resource!"
msgstr ""
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Save Resource As.."
msgstr ""
-#: editor/editor_node.cpp editor/export_template_manager.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "I see.."
msgstr ""
@@ -1545,6 +1398,29 @@ msgid "Error while saving."
msgstr ""
#: editor/editor_node.cpp
+#, fuzzy
+msgid "Can't open '%s'."
+msgstr "Připojit.."
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Error while parsing '%s'."
+msgstr "Chyba nahrávání fontu."
+
+#: editor/editor_node.cpp
+msgid "Unexpected end of file '%s'."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Missing '%s' or its dependencies."
+msgstr ""
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Error while loading '%s'."
+msgstr "Chyba nahrávání fontu."
+
+#: editor/editor_node.cpp
msgid "Saving Scene"
msgstr ""
@@ -1602,6 +1478,33 @@ msgid "Restored default layout to base settings."
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was imported, so it's not editable.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was instanced or inherited.\n"
+"Changes to it will not be kept when saving the current scene."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource was imported, so it's not editable. Change its settings in the "
+"import panel and then re-import."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This scene was imported, so changes to it will not be kept.\n"
+"Instancing it or inheriting will allow making changes to it.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Copy Params"
msgstr ""
@@ -1765,23 +1668,35 @@ msgid "Save changes the following scene(s) before opening Project Manager?"
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"This option is deprecated. Situations where refresh must be forced are now "
+"considered a bug. Please report."
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Pick a Main Scene"
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to enable addon plugin at: '"
+msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr ""
#: editor/editor_node.cpp
-msgid "' parsing of config failed."
+msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/"
+#, fuzzy
+msgid "Unable to load addon script from path: '%s'."
+msgstr "Chyba nahrávání fontu."
+
+#: editor/editor_node.cpp
+msgid ""
+"Unable to load addon script from path: '%s' Base type is not EditorPlugin."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to load addon script from path: '"
+msgid "Unable to load addon script from path: '%s' Script is not in tool mode."
msgstr ""
#: editor/editor_node.cpp
@@ -1791,7 +1706,7 @@ msgid ""
msgstr ""
#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/scene_tree_dock.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Ugh"
msgstr ""
@@ -1802,11 +1717,11 @@ msgid ""
msgstr ""
#: editor/editor_node.cpp
-msgid "Error loading scene."
+msgid "Scene '%s' has broken dependencies:"
msgstr ""
#: editor/editor_node.cpp
-msgid "Scene '%s' has broken dependencies:"
+msgid "Clear Recent Scenes"
msgstr ""
#: editor/editor_node.cpp
@@ -1842,7 +1757,7 @@ msgstr ""
msgid "Toggle distraction-free mode."
msgstr ""
-#: editor/editor_node.cpp editor/io_plugins/editor_scene_import_plugin.cpp
+#: editor/editor_node.cpp
msgid "Scene"
msgstr ""
@@ -2063,6 +1978,10 @@ msgstr ""
msgid "Issue Tracker"
msgstr ""
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+msgid "Community"
+msgstr "Z komunity"
+
#: editor/editor_node.cpp
msgid "About"
msgstr ""
@@ -2071,7 +1990,7 @@ msgstr ""
msgid "Play the project."
msgstr ""
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Play"
msgstr ""
@@ -2087,7 +2006,7 @@ msgstr ""
msgid "Stop the scene."
msgstr ""
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Stop"
msgstr ""
@@ -2161,6 +2080,15 @@ msgid "Object properties."
msgstr ""
#: editor/editor_node.cpp
+msgid "Changes may be lost!"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Import"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "FileSystem"
msgstr ""
@@ -2176,14 +2104,6 @@ msgstr ""
msgid "Don't Save"
msgstr ""
-#: editor/editor_node.cpp editor/editor_reimport_dialog.cpp
-msgid "Re-Import"
-msgstr ""
-
-#: editor/editor_node.cpp editor/editor_plugin_settings.cpp
-msgid "Update"
-msgstr ""
-
#: editor/editor_node.cpp
msgid "Import Templates From ZIP File"
msgstr ""
@@ -2248,11 +2168,28 @@ msgstr "Editor závislostí"
msgid "Open the previous Editor"
msgstr ""
+#: editor/editor_plugin.cpp
+msgid "Creating Mesh Previews"
+msgstr ""
+
+#: editor/editor_plugin.cpp
+msgid "Thumbnail.."
+msgstr ""
+
#: editor/editor_plugin_settings.cpp
msgid "Installed Plugins:"
msgstr ""
#: editor/editor_plugin_settings.cpp
+msgid "Update"
+msgstr ""
+
+#: editor/editor_plugin_settings.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Version:"
+msgstr ""
+
+#: editor/editor_plugin_settings.cpp
msgid "Author:"
msgstr ""
@@ -2285,7 +2222,7 @@ msgid "Frame %"
msgstr ""
#: editor/editor_profiler.cpp
-msgid "Fixed Frame %"
+msgid "Physics Frame %"
msgstr ""
#: editor/editor_profiler.cpp editor/script_editor_debugger.cpp
@@ -2304,26 +2241,6 @@ msgstr ""
msgid "Frame #:"
msgstr ""
-#: editor/editor_reimport_dialog.cpp
-msgid "Please wait for scan to complete."
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Current scene must be saved to re-import."
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Save & Re-Import"
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Importing"
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Import Changed Resources"
-msgstr ""
-
#: editor/editor_run_native.cpp
msgid "Select device from the list"
msgstr ""
@@ -2434,10 +2351,6 @@ msgid "Importing:"
msgstr ""
#: editor/export_template_manager.cpp
-msgid "Loading Export Templates"
-msgstr ""
-
-#: editor/export_template_manager.cpp
msgid "Current Version:"
msgstr ""
@@ -2472,9 +2385,17 @@ msgid "Cannot navigate to '"
msgstr ""
#: editor/filesystem_dock.cpp
+msgid "View items as a grid of thumbnails"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "View items as a list"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
msgid ""
"\n"
-"Status: Needs Re-Import"
+"Status: Import of file failed. Please fix file and reimport manually."
msgstr ""
#: editor/filesystem_dock.cpp
@@ -2485,45 +2406,51 @@ msgid ""
msgstr "Zdroj"
#: editor/filesystem_dock.cpp
-msgid "Same source and destination files, doing nothing."
+msgid "Cannot move/rename resources root."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Target file exists, can't overwrite. Delete first."
+msgid "Cannot move a folder into itself.\n"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Same source and destination paths, doing nothing."
-msgstr ""
+#, fuzzy
+msgid "Error moving:\n"
+msgstr "Chyba pÅ™i naÄítání:"
#: editor/filesystem_dock.cpp
-msgid "Can't move directories to within themselves."
+#, fuzzy
+msgid "Unable to update dependencies:\n"
+msgstr "Scénu se nepodaÅ™ilo naÄíst kvůli chybÄ›jícím závislostem:"
+
+#: editor/filesystem_dock.cpp
+msgid "No name provided"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Can't rename deps for:\n"
+msgid "Provided name contains invalid characters"
msgstr ""
#: editor/filesystem_dock.cpp
-#, fuzzy
-msgid "Error moving file:\n"
-msgstr "Chyba pÅ™i naÄítání:"
+msgid "No name provided."
+msgstr ""
#: editor/filesystem_dock.cpp
#, fuzzy
-msgid "Error moving dir:\n"
-msgstr "Chyba pÅ™i naÄítání:"
+msgid "Name contains invalid characters."
+msgstr "Platné znaky:"
#: editor/filesystem_dock.cpp
-msgid "Can't operate on '..'"
+msgid "A file or folder with this name already exists."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Pick New Name and Location For:"
-msgstr ""
+#, fuzzy
+msgid "Renaming file:"
+msgstr "Přejmenovat proměnnou"
#: editor/filesystem_dock.cpp
-msgid "No files selected!"
+msgid "Renaming folder:"
msgstr ""
#: editor/filesystem_dock.cpp
@@ -2535,39 +2462,36 @@ msgid "Collapse all"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Show In File Manager"
-msgstr ""
-
-#: editor/filesystem_dock.cpp
-msgid "Instance"
+msgid "Copy Path"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Edit Dependencies.."
+msgid "Rename.."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "View Owners.."
+msgid "Move To.."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Copy Path"
-msgstr ""
+#, fuzzy
+msgid "New Folder.."
+msgstr "Vytvořit složku"
#: editor/filesystem_dock.cpp
-msgid "Rename or Move.."
+msgid "Show In File Manager"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Move To.."
+msgid "Instance"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Info"
+msgid "Edit Dependencies.."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Re-Import.."
+msgid "View Owners.."
msgstr ""
#: editor/filesystem_dock.cpp
@@ -2600,6 +2524,11 @@ msgstr ""
msgid "Move"
msgstr ""
+#: editor/filesystem_dock.cpp editor/plugins/animation_tree_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Rename"
+msgstr ""
+
#: editor/groups_editor.cpp
msgid "Add to Group"
msgstr ""
@@ -2613,6 +2542,10 @@ msgid "Import as Single Scene"
msgstr ""
#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
msgid "Import with Separate Materials"
msgstr ""
@@ -2625,6 +2558,18 @@ msgid "Import with Separate Objects+Materials"
msgstr ""
#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Materials+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Materials+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
msgid "Import as Multiple Scenes"
msgstr ""
@@ -2633,38 +2578,31 @@ msgid "Import as Multiple Scenes+Materials"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Import Scene"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Importing Scene.."
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Running Custom Script.."
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Couldn't load post-import script:"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Invalid/broken script for post-import (check console):"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Error running post-import script:"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Saving.."
msgstr ""
@@ -2693,579 +2631,54 @@ msgstr ""
msgid "Reimport"
msgstr ""
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "No bit masks to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path is empty."
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must be a complete resource path."
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must exist."
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Save path is empty!"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Import BitMasks"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s):"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Target Path:"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Accept"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Bit Mask"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No source font file!"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No target font resource!"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"Invalid file extension.\n"
-"Please use .font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Can't load/process source font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Couldn't save font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font Size:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Dest Resource:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "The quick brown fox jumps over the lazy dog."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Test:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Options:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Font Import"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"This file is already a Godot font file, please supply a BMFont type file "
-"instead."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Failed opening as BMFont file."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error initializing FreeType."
-msgstr "Chyba při inicializaci FreeType."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Unknown font format."
-msgstr "Neznámý formát fontu."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error loading font."
-msgstr "Chyba nahrávání fontu."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Invalid font size."
-msgstr "Neplatná velikost fontu."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Invalid font custom source."
-msgstr "Nevalidní písmo z vlastního zdroje."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/plugins/theme_editor_plugin.cpp
-msgid "Font"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "No meshes to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Single Mesh Import"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Source Mesh(es):"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/plugins/mesh_instance_editor_plugin.cpp
-msgid "Mesh"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Surface %d"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "No samples to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Import Audio Samples"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Source Sample(s):"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Audio Sample"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "New Clip"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Animation Options"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Flags"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Bake FPS:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Optimizer"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Linear Error"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angular Error"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angle"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Clips"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Start(s)"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "End(s)"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Loop"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Filters"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source path is empty."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't load post-import script."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Invalid/broken script for post-import."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Error importing scene."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import 3D Scene"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source Scene:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Same as Target Scene"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Shared"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Target Texture Folder:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Post-Process Script:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Custom Root Node Type:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Auto"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Root Node Name:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "The Following Files are Missing:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Anyway"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp scene/gui/dialogs.cpp
-msgid "Cancel"
-msgstr "Zrušit"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import & Open"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Edited scene has not been saved, open imported scene anyway?"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Image:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Can't import a file over itself:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't localize path: %s (already local)"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "3D Scene Animation"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Uncompressed"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossless (PNG)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossy (WebP)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress (VRAM)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Format"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Compression Quality (WebP):"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Options"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Please specify some files!"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "At least one file needed for Atlas."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Error importing:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Only one file is required for large texture."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Max Texture Size:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for Atlas (2D)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cell Size:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Large Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Textures (2D)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture"
+#: editor/multi_node_edit.cpp
+msgid "MultiNode Set"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Base Atlas Texture"
+#: editor/node_dock.cpp
+msgid "Groups"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s)"
+#: editor/node_dock.cpp
+msgid "Select a Node to edit Signals and Groups."
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 2D"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create Poly"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 3D"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Insert Point"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "2D Texture"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly (Remove Point)"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "3D Texture"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Remove Poly And Point"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Atlas Texture"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create a new polygon from scratch."
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
+#: editor/plugins/abstract_polygon_2d_editor.cpp
msgid ""
-"NOTICE: Importing 2D textures is not mandatory. Just copy png/jpg files to "
-"the project."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Crop empty space."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Load Source Image"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Slicing"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Inserting"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Saving"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save large texture:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Build Atlas For:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Loading Image:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't load image:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Converting Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cropping Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Blitting Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save atlas image:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save converted texture:"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid source!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid translation source!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Column"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/script_create_dialog.cpp
-msgid "Language"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No items to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No target path!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translations"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Couldn't import!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translation"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Source CSV:"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Ignore First Row"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Compress"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Add to Project (project.godot)"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Languages:"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Translation"
-msgstr ""
-
-#: editor/multi_node_edit.cpp
-msgid "MultiNode Set"
-msgstr ""
-
-#: editor/node_dock.cpp
-msgid "Groups"
-msgstr ""
-
-#: editor/node_dock.cpp
-msgid "Select a Node to edit Signals and Groups."
+"Edit existing polygon:\n"
+"LMB: Move Point.\n"
+"Ctrl+LMB: Split Segment.\n"
+"RMB: Erase Point."
msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
@@ -3422,7 +2835,6 @@ msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
#: editor/script_create_dialog.cpp
msgid "Error!"
@@ -3533,10 +2945,6 @@ msgid "Delete Input"
msgstr ""
#: editor/plugins/animation_tree_editor_plugin.cpp
-msgid "Rename"
-msgstr ""
-
-#: editor/plugins/animation_tree_editor_plugin.cpp
msgid "Animation tree is valid."
msgstr ""
@@ -3592,64 +3000,188 @@ msgstr ""
msgid "Filters.."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing %d Triangles:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Free"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Triangle #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Contents:"
+msgstr "Spojité"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "View Files"
+msgstr "Soubor:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve hostname:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Light Baker Setup:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing Geometry"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connection error, please try again."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Fixing Lights"
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Can't connect."
+msgstr "Připojit.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Can't connect to host:"
+msgstr "Připojit k uzlu:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response from host:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Making BVH"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Light Octree"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, return code:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Octree Texture"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Req. Failed."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Transfer to Lightmaps:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, too many redirects"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Allocating Texture #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Redirect Loop."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Baking Triangle #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Post-Processing Texture #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Bad download hash, assuming file has been tampered with."
msgstr ""
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Bake!"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Expected:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Got:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed sha256 hash check"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Asset Download Error:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Fetching:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Resolving.."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Connecting.."
+msgstr "Připojit.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Requesting.."
+msgstr "Testované"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Error making request"
+msgstr "Chyba nahrávání fontu."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Idle"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Retry"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download Error"
msgstr ""
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Reset the lightmap octree baking process (start over)."
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download for this asset is already in progress!"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "first"
msgstr ""
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "prev"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "next"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "last"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "All"
+msgstr "VÅ¡echny"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Plugins"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Sort:"
+msgstr "Řadit:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Reverse"
+msgstr "Naopak"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Category:"
+msgstr "Kategorie:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Site:"
+msgstr "Web:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Support.."
+msgstr "Podpora.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Official"
+msgstr "Oficiální"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Testing"
+msgstr "Testované"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Assets ZIP File"
+msgstr "ZIP soubor asetů"
+
#: editor/plugins/camera_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
msgid "Preview"
msgstr ""
@@ -3692,11 +3224,15 @@ msgid "Edit CanvasItem"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Change Anchors"
+msgid "Anchors only"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Change Anchors and Margins"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom (%):"
+msgid "Change Anchors"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3748,59 +3284,73 @@ msgid "Pan Mode"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Lock the selected object in place (can't be moved)."
+#, fuzzy
+msgid "Toggles snapping"
+msgstr "Přepnout breakpoint"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Use Snap"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Unlock the selected object (can be moved)."
+msgid "Snapping options"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Makes sure the object's children are not selectable."
+msgid "Snap to grid"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Restores the object's children's ability to be selected."
+msgid "Use Rotation Snap"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Edit"
-msgstr "Upravit"
+msgid "Configure Snap..."
+msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Use Snap"
+msgid "Snap Relative"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Show Grid"
+msgid "Use Pixel Snap"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Rotation Snap"
+msgid "Smart snapping"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap Relative"
+msgid "Snap to parent"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Configure Snap.."
+msgid "Snap to node anchor"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Pixel Snap"
+msgid "Snap to node sides"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to other nodes"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Lock the selected object in place (can't be moved)."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Unlock the selected object (can be moved)."
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Skeleton.."
+msgid "Makes sure the object's children are not selectable."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Restores the object's children's ability to be selected."
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3829,11 +3379,16 @@ msgid "View"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Reset"
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Show Grid"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Show helpers"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Set.."
+msgid "Show rulers"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3845,7 +3400,7 @@ msgid "Frame Selection"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Anchor"
+msgid "Layout"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3869,11 +3424,20 @@ msgid "Clear Pose"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Set a Value"
+msgid "Drag pivot from mouse position"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap (Pixels):"
+#, fuzzy
+msgid "Set pivot at mouse position"
+msgstr "Odstranit signál"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Multiply grid step by 2"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Divide grid step by 2"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3884,23 +3448,28 @@ msgstr ""
msgid "Adding %s..."
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Create Node"
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Error instancing scene from %s"
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "OK :("
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "No parent to instance a child at."
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "This operation requires a single selected node."
msgstr ""
@@ -3915,45 +3484,6 @@ msgid ""
"Drag & drop + Alt : Change node type"
msgstr ""
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Create Poly"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly (Remove Point)"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Create a new polygon from scratch."
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-msgid ""
-"Edit existing polygon:\n"
-"LMB: Move Point.\n"
-"Ctrl+LMB: Split Segment.\n"
-"RMB: Erase Point."
-msgstr ""
-
#: editor/plugins/collision_polygon_editor_plugin.cpp
msgid "Create Poly3D"
msgstr ""
@@ -3963,14 +3493,6 @@ msgid "Set Handle"
msgstr ""
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Creating Mesh Library"
-msgstr ""
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Thumbnail.."
-msgstr ""
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Remove item %d?"
msgstr ""
@@ -3993,6 +3515,27 @@ msgid "Update from Scene"
msgstr ""
#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat0"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat1"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+#, fuzzy
+msgid "Ease in"
+msgstr "Změnit měřítko výběru"
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Ease out"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Smoothstep"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
msgid "Modify Curve Point"
msgstr ""
@@ -4072,22 +3615,18 @@ msgid "Create Occluder Polygon"
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Edit existing polygon:"
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "LMB: Move Point."
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Ctrl+LMB: Split Segment."
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "RMB: Erase Point."
msgstr ""
@@ -4189,6 +3728,10 @@ msgid "Create Outline"
msgstr ""
#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Mesh"
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Create Trimesh Static Body"
msgstr ""
@@ -4316,12 +3859,72 @@ msgstr ""
msgid "Populate"
msgstr ""
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Create Navigation Polygon"
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake!"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake the navigation mesh.\n"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Clear the navigation mesh."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Setting up Configuration..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Calculating grid size..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating heightfield..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Marking walkable triangles..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Constructing compact heightfield..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Eroding walkable area..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Partitioning..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating contours..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating polymesh..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Converting to native navigation mesh..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Navigation Mesh Generator Setup:"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Parsing Geometry..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Done!"
msgstr ""
#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Remove Poly And Point"
+msgid "Create Navigation Polygon"
msgstr ""
#: editor/plugins/particles_2d_editor_plugin.cpp
@@ -4495,16 +4098,19 @@ msgid "Curve Point #"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve Point Position"
-msgstr ""
+msgstr "Odstranit signál"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve In Position"
-msgstr ""
+msgstr "Odstranit signál"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve Out Position"
-msgstr ""
+msgstr "Odstranit signál"
#: editor/plugins/path_editor_plugin.cpp
msgid "Split Path"
@@ -4564,6 +4170,14 @@ msgid "Scale Polygon"
msgstr ""
#: editor/plugins/polygon_2d_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Edit"
+msgstr "Upravit"
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Polygon->UV"
msgstr ""
@@ -4618,63 +4232,10 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/shader_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "Vložit"
-#: editor/plugins/rich_text_editor_plugin.cpp
-msgid "Parse BBCode"
-msgstr ""
-
-#: editor/plugins/sample_editor_plugin.cpp
-msgid "Length:"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Open Sample File(s)"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "ERROR: Couldn't load sample!"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Add Sample"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Rename Sample"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Delete Sample"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "16 Bits"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "8 Bits"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Stereo"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Mono"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Format"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Pitch"
-msgstr ""
-
#: editor/plugins/script_editor_plugin.cpp
msgid "Clear Recent Files"
msgstr ""
@@ -4766,6 +4327,10 @@ msgstr ""
msgid "Close All"
msgstr "Zavřít"
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+msgid "Run"
+msgstr ""
+
#: editor/plugins/script_editor_plugin.cpp
msgid "Toggle Scripts Panel"
msgstr ""
@@ -4794,7 +4359,8 @@ msgstr ""
msgid "Break"
msgstr ""
-#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+#: editor/script_editor_debugger.cpp
msgid "Continue"
msgstr ""
@@ -4808,18 +4374,6 @@ msgid "Debug with external editor"
msgstr "Editor závislostí"
#: editor/plugins/script_editor_plugin.cpp
-msgid "Window"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Left"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Right"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
msgid "Open Godot online documentation"
msgstr ""
@@ -4902,8 +4456,9 @@ msgid "Cut"
msgstr "Vyjmout"
#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "Kopírovat"
@@ -5168,10 +4723,6 @@ msgid "View Plane Transform."
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Scaling to %s%%."
-msgstr ""
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rotating %s degrees."
msgstr ""
@@ -5188,10 +4739,6 @@ msgid "Top View."
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Top"
-msgstr ""
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rear View."
msgstr ""
@@ -5424,6 +4971,10 @@ msgid "Transform"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Configure Snap.."
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Local Coords"
msgstr ""
@@ -5569,6 +5120,10 @@ msgid "Speed (FPS):"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Loop"
+msgstr ""
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Animation Frames"
msgstr ""
@@ -5581,11 +5136,12 @@ msgid "Insert Empty (After)"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Up"
-msgstr ""
+#, fuzzy
+msgid "Move (Before)"
+msgstr "Zkopírovat uzly"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Down"
+msgid "Move (After)"
msgstr ""
#: editor/plugins/style_box_editor_plugin.cpp
@@ -5664,7 +5220,11 @@ msgid "Remove All"
msgstr "Odebrat"
#: editor/plugins/theme_editor_plugin.cpp
-msgid "Theme"
+msgid "Edit theme.."
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Theme editing menu."
msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
@@ -5749,6 +5309,10 @@ msgid "Style"
msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
+msgid "Font"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
msgid "Color"
msgstr ""
@@ -5799,7 +5363,7 @@ msgid "Mirror Y"
msgstr ""
#: editor/plugins/tile_map_editor_plugin.cpp
-msgid "Bucket"
+msgid "Paint Tile"
msgstr ""
#: editor/plugins/tile_map_editor_plugin.cpp
@@ -5866,6 +5430,10 @@ msgid "Delete preset '%s'?"
msgstr "Odstranit vybrané soubory?"
#: editor/project_export.cpp
+msgid "Export templates for this platform are missing/corrupted: "
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Presets"
msgstr ""
@@ -5938,19 +5506,30 @@ msgid "Export templates for this platform are missing:"
msgstr ""
#: editor/project_export.cpp
+msgid "Export templates for this platform are missing/corrupted:"
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Export With Debug"
msgstr ""
#: editor/project_manager.cpp
-msgid "Invalid project path, the path must exist!"
+#, fuzzy
+msgid "The path does not exist."
+msgstr "Soubor neexistuje."
+
+#: editor/project_manager.cpp
+msgid "Please choose a 'project.godot' file."
msgstr ""
#: editor/project_manager.cpp
-msgid "Invalid project path, project.godot must not exist."
+msgid ""
+"Your project will be created in a non empty folder (you might want to create "
+"a new folder)."
msgstr ""
#: editor/project_manager.cpp
-msgid "Invalid project path, project.godot must exist."
+msgid "Please choose a folder that does not contain a 'project.godot' file."
msgstr ""
#: editor/project_manager.cpp
@@ -5958,10 +5537,26 @@ msgid "Imported Project"
msgstr ""
#: editor/project_manager.cpp
+msgid " "
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "It would be a good idea to name your project."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Invalid project path (changed anything?)."
msgstr ""
#: editor/project_manager.cpp
+msgid "Couldn't get project.godot in project path."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Couldn't edit project.godot in project path."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
msgstr ""
@@ -5970,15 +5565,20 @@ msgid "The following files failed extraction from package:"
msgstr ""
#: editor/project_manager.cpp
-msgid "Import Existing Project"
+#, fuzzy
+msgid "Rename Project"
+msgstr "Nastavení projektu"
+
+#: editor/project_manager.cpp
+msgid "Couldn't get project.godot in the project path."
msgstr ""
#: editor/project_manager.cpp
-msgid "Project Path (Must Exist):"
+msgid "New Game Project"
msgstr ""
#: editor/project_manager.cpp
-msgid "Project Name:"
+msgid "Import Existing Project"
msgstr ""
#: editor/project_manager.cpp
@@ -5986,19 +5586,24 @@ msgid "Create New Project"
msgstr ""
#: editor/project_manager.cpp
-msgid "Project Path:"
+msgid "Install Project:"
msgstr ""
#: editor/project_manager.cpp
-msgid "Install Project:"
+msgid "Project Name:"
msgstr ""
#: editor/project_manager.cpp
-msgid "Browse"
+#, fuzzy
+msgid "Create folder"
+msgstr "Vytvořit složku"
+
+#: editor/project_manager.cpp
+msgid "Project Path:"
msgstr ""
#: editor/project_manager.cpp
-msgid "New Game Project"
+msgid "Browse"
msgstr ""
#: editor/project_manager.cpp
@@ -6010,6 +5615,11 @@ msgid "Unnamed Project"
msgstr ""
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Can't open project"
+msgstr "Připojit.."
+
+#: editor/project_manager.cpp
msgid "Are you sure to open more than one project?"
msgstr ""
@@ -6036,16 +5646,18 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
-"You are about the scan %s folders for existing Godot projects. Do you "
-"confirm?"
+"Language changed.\n"
+"The UI will update next time the editor or project manager starts."
msgstr ""
#: editor/project_manager.cpp
-msgid "Project List"
+msgid ""
+"You are about the scan %s folders for existing Godot projects. Do you "
+"confirm?"
msgstr ""
#: editor/project_manager.cpp
-msgid "Run"
+msgid "Project List"
msgstr ""
#: editor/project_manager.cpp
@@ -6070,6 +5682,10 @@ msgid "Exit"
msgstr ""
#: editor/project_manager.cpp
+msgid "Restart Now"
+msgstr ""
+
+#: editor/project_manager.cpp
#, fuzzy
msgid "Can't run project"
msgstr "Připojit.."
@@ -6107,17 +5723,14 @@ msgid "Add Input Action Event"
msgstr ""
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Meta+"
msgstr ""
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Shift+"
msgstr "Shift+"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Alt+"
msgstr "Alt+"
@@ -6178,7 +5791,7 @@ msgstr "Změnit"
msgid "Joypad Axis Index:"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Axis"
msgstr "Osa"
@@ -6198,31 +5811,31 @@ msgstr ""
msgid "Add Event"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Device"
msgstr "Zařízení"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Button"
msgstr "TlaÄítko"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Left Button."
msgstr "Levé tlaÄítko."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Right Button."
msgstr "Pravé tlaÄítko."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Middle Button."
msgstr "ProstÅ™ední tlaÄítko."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Up."
msgstr "KoleÄko nahoru."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Down."
msgstr "KoleÄko dolů."
@@ -6232,7 +5845,7 @@ msgid "Add Global Property"
msgstr "Přidat vlastnost getter"
#: editor/project_settings_editor.cpp
-msgid "Select an setting item first!"
+msgid "Select a setting item first!"
msgstr ""
#: editor/project_settings_editor.cpp
@@ -6250,6 +5863,15 @@ msgid "Delete Item"
msgstr "Odstranit"
#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Can't contain '/' or ':'"
+msgstr "Připojit k uzlu:"
+
+#: editor/project_settings_editor.cpp
+msgid "Already existing"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "Error saving settings."
msgstr ""
@@ -6291,6 +5913,15 @@ msgstr ""
#: editor/project_settings_editor.cpp
#, fuzzy
+msgid "Changed Locale Filter"
+msgstr "Změnit typ hodnot pole"
+
+#: editor/project_settings_editor.cpp
+msgid "Changed Locale Filter Mode"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
msgid "Project Settings (project.godot)"
msgstr "Nastavení projektu"
@@ -6351,6 +5982,27 @@ msgid "Locale"
msgstr ""
#: editor/project_settings_editor.cpp
+msgid "Locales Filter"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Show all locales"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Show only selected locales"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Filter mode:"
+msgstr "Filtr:"
+
+#: editor/project_settings_editor.cpp
+msgid "Locales:"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "AutoLoad"
msgstr ""
@@ -6400,10 +6052,19 @@ msgid "New Script"
msgstr ""
#: editor/property_editor.cpp
+msgid "Make Unique"
+msgstr ""
+
+#: editor/property_editor.cpp
msgid "Show in File System"
msgstr ""
#: editor/property_editor.cpp
+#, fuzzy
+msgid "Convert To %s"
+msgstr "Připojit k uzlu:"
+
+#: editor/property_editor.cpp
msgid "Error loading file: Not a resource!"
msgstr ""
@@ -6443,6 +6104,11 @@ msgstr "Přidat vlastnost setter"
#: editor/property_selector.cpp
#, fuzzy
+msgid "Select Virtual Method"
+msgstr "Vybrat vše"
+
+#: editor/property_selector.cpp
+#, fuzzy
msgid "Select Method"
msgstr "Vybrat vše"
@@ -6470,26 +6136,6 @@ msgstr ""
msgid "Reparent"
msgstr ""
-#: editor/resources_dock.cpp
-msgid "Create New Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Open Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Save Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Resource Tools"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Make Local"
-msgstr ""
-
#: editor/run_settings_dialog.cpp
msgid "Run Mode:"
msgstr ""
@@ -6617,14 +6263,6 @@ msgid "Sub-Resources:"
msgstr "Zdroj"
#: editor/scene_tree_dock.cpp
-msgid "Edit Groups"
-msgstr ""
-
-#: editor/scene_tree_dock.cpp
-msgid "Edit Connections"
-msgstr ""
-
-#: editor/scene_tree_dock.cpp
msgid "Clear Inheritance"
msgstr ""
@@ -6813,6 +6451,15 @@ msgid "Invalid base path"
msgstr ""
#: editor/script_create_dialog.cpp
+msgid "Directory of the same name exists"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
+#, fuzzy
+msgid "File exists, will be reused"
+msgstr "Soubor už existuje. Přepsat?"
+
+#: editor/script_create_dialog.cpp
msgid "Invalid extension"
msgstr ""
@@ -6856,6 +6503,10 @@ msgid "Load existing script file"
msgstr ""
#: editor/script_create_dialog.cpp
+msgid "Language"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
msgid "Inherits"
msgstr ""
@@ -6898,6 +6549,10 @@ msgid "Function:"
msgstr ""
#: editor/script_editor_debugger.cpp
+msgid "Pick one or more items from the list to display the graph."
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
msgid "Errors"
msgstr ""
@@ -6978,6 +6633,10 @@ msgid "Type"
msgstr ""
#: editor/script_editor_debugger.cpp
+msgid "Format"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
msgid "Usage"
msgstr ""
@@ -7053,13 +6712,29 @@ msgstr ""
msgid "Change Probe Extents"
msgstr ""
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Library"
+msgstr ""
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Status"
+msgstr ""
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Libraries: "
+msgstr ""
+
+#: modules/gdnative/register_types.cpp
+msgid "GDNative"
+msgstr ""
+
#: modules/gdscript/gd_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Invalid type argument to convert(), use TYPE_* constants."
msgstr ""
"Neplatný typ argumentu funkce convert(), použijte některou z konstant TYPE_*"
-#: modules/gdscript/gd_functions.cpp
+#: modules/gdscript/gd_functions.cpp modules/mono/glue/glue_header.h
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Not enough bytes for decoding bytes, or invalid format."
msgstr "Nedostatek bajtů pro dekódování bajtů, nebo špatný formát."
@@ -7111,10 +6786,6 @@ msgid "GridMap Duplicate Selection"
msgstr "Duplikovat výběr"
#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "GridMap Paint"
-msgstr ""
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Snap View"
msgstr ""
@@ -7211,13 +6882,8 @@ msgstr "Nastavení projektu"
msgid "Pick Distance:"
msgstr ""
-#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
-msgid "Tiles"
-msgstr "Soubor:"
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "Areas"
+#: modules/mono/editor/mono_bottom_panel.cpp
+msgid "Builds"
msgstr ""
#: modules/visual_script/visual_script.cpp
@@ -7432,10 +7098,18 @@ msgid "Return"
msgstr "Vrátit"
#: modules/visual_script/visual_script_editor.cpp
+msgid "Call"
+msgstr "Zavolat"
+
+#: modules/visual_script/visual_script_editor.cpp
msgid "Get"
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
+msgid "Script already has function '%s'"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
#, fuzzy
msgid "Change Input Value"
msgstr "Změnit hodnotu pole"
@@ -7843,6 +7517,12 @@ msgstr ""
"Zdroj SpriteFrames musí být vytvořen nebo nastaven ve vlastnosti 'Frames', "
"aby mohl AnimatedSprite3D zobrazit rámeÄky."
+#: scene/3d/vehicle_body.cpp
+msgid ""
+"VehicleWheel serves to provide a wheel system to a VehicleBody. Please use "
+"it as a child of a VehicleBody."
+msgstr ""
+
#: scene/gui/color_picker.cpp
msgid "Raw Mode"
msgstr ""
@@ -7852,6 +7532,10 @@ msgid "Add current color as a preset"
msgstr ""
#: scene/gui/dialogs.cpp
+msgid "Cancel"
+msgstr "Zrušit"
+
+#: scene/gui/dialogs.cpp
msgid "Alert!"
msgstr "Pozor!"
@@ -7859,10 +7543,6 @@ msgstr "Pozor!"
msgid "Please Confirm..."
msgstr "PotvrÄte prosím..."
-#: scene/gui/input_action.cpp
-msgid "Ctrl+"
-msgstr "Ctrl+"
-
#: scene/gui/popup.cpp
msgid ""
"Popups will hide by default unless you call popup() or any of the popup*() "
@@ -7898,6 +7578,48 @@ msgstr ""
"mohl získat velikost. Jinak ho nastavte jako render target a pÅ™iÅ™aÄte jeho "
"vnitřní texturu nějakému uzlu k zobrazení."
+#: scene/resources/dynamic_font.cpp
+msgid "Error initializing FreeType."
+msgstr "Chyba při inicializaci FreeType."
+
+#: scene/resources/dynamic_font.cpp
+msgid "Unknown font format."
+msgstr "Neznámý formát fontu."
+
+#: scene/resources/dynamic_font.cpp
+msgid "Error loading font."
+msgstr "Chyba nahrávání fontu."
+
+#: scene/resources/dynamic_font.cpp
+msgid "Invalid font size."
+msgstr "Neplatná velikost fontu."
+
+#~ msgid "Filter:"
+#~ msgstr "Filtr:"
+
+#~ msgid "Method List For '%s':"
+#~ msgstr "Seznam metod '%s':"
+
+#~ msgid "Arguments:"
+#~ msgstr "Argumenty:"
+
+#~ msgid "Return:"
+#~ msgstr "Vrátit:"
+
+#, fuzzy
+#~ msgid "Error moving file:\n"
+#~ msgstr "Chyba pÅ™i naÄítání:"
+
+#~ msgid "Invalid font custom source."
+#~ msgstr "Nevalidní písmo z vlastního zdroje."
+
+#, fuzzy
+#~ msgid "Tiles"
+#~ msgstr "Soubor:"
+
+#~ msgid "Ctrl+"
+#~ msgstr "Ctrl+"
+
#~ msgid "just pressed"
#~ msgstr "právě stisknuto"
diff --git a/editor/translations/da.po b/editor/translations/da.po
index 47409d5293..50da2c54b8 100644
--- a/editor/translations/da.po
+++ b/editor/translations/da.po
@@ -1,5 +1,6 @@
# Danish translation of the Godot Engine editor
-# Copyright (C) 2016-2017 Juan Linietsky, Ariel Manzur and the Godot community
+# Copyright (C) 2007-2017 Juan Linietsky, Ariel Manzur
+# Copyright (C) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)
# This file is distributed under the same license as the Godot source code.
#
# David Lamhauge <davidlamhauge@gmail.com>, 2016.
@@ -192,10 +193,9 @@ msgid "Create %d NEW tracks and insert keys?"
msgstr "Oprette %d nye numre og indsætte nøgler?"
#: editor/animation_editor.cpp editor/create_dialog.cpp
-#: editor/editor_audio_buses.cpp
+#: editor/editor_audio_buses.cpp editor/plugins/abstract_polygon_2d_editor.cpp
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
#: editor/plugins/mesh_instance_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp editor/project_manager.cpp
#: editor/script_create_dialog.cpp
msgid "Create"
@@ -357,268 +357,6 @@ msgstr "Skift Array værditype"
msgid "Change Array Value"
msgstr "Ændre Array-værdi"
-#: editor/asset_library_editor_plugin.cpp
-msgid "Free"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_plugin_settings.cpp
-msgid "Version:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Contents:"
-msgstr "Kontinuerlig"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "View Files"
-msgstr "Fil:"
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_help.cpp editor/property_selector.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Description:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-#: editor/project_manager.cpp
-msgid "Install"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/call_dialog.cpp
-#: editor/connections_dialog.cpp editor/export_template_manager.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-#: editor/project_settings_editor.cpp editor/property_editor.cpp
-#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Close"
-msgstr "Luk"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve hostname:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Connection error, please try again."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Can't connect."
-msgstr "Forbind..."
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Can't connect to host:"
-msgstr "Opret forbindelse til Node:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response from host:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Request failed, return code:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Req. Failed."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Request failed, too many redirects"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Redirect Loop."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Bad download hash, assuming file has been tampered with."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Expected:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Got:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Asset Download Error:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-msgid "Success!"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Fetching:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Resolving.."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Connecting.."
-msgstr "Forbind..."
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Requesting.."
-msgstr "Tester"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Error making request"
-msgstr "Error loading skrifttype."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Idle"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Retry"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Download Error"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Download for this asset is already in progress!"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "first"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "prev"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "next"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "last"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "All"
-msgstr "Alle"
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
-#: editor/settings_config_dialog.cpp
-msgid "Search:"
-msgstr "Søgning:"
-
-#: editor/asset_library_editor_plugin.cpp editor/code_editor.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Search"
-msgstr "Søg"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/project_manager.cpp
-msgid "Import"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Plugins"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Sort:"
-msgstr "Sorter:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Reverse"
-msgstr "Omvendt"
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Category:"
-msgstr "Kategori:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Site:"
-msgstr "Websted:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Support.."
-msgstr "Støtte..."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Official"
-msgstr "Officiel"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-msgid "Community"
-msgstr "Fællesskabet"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Testing"
-msgstr "Tester"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Assets ZIP File"
-msgstr "Assets zipfil"
-
-#: editor/call_dialog.cpp
-msgid "Method List For '%s':"
-msgstr "Metode liste For '%s':"
-
-#: editor/call_dialog.cpp modules/visual_script/visual_script_editor.cpp
-msgid "Call"
-msgstr "Kald"
-
-#: editor/call_dialog.cpp
-msgid "Method List:"
-msgstr "Metode liste:"
-
-#: editor/call_dialog.cpp
-msgid "Arguments:"
-msgstr "Argumenter:"
-
-#: editor/call_dialog.cpp
-msgid "Return:"
-msgstr "Tilbage:"
-
#: editor/code_editor.cpp
msgid "Go to Line"
msgstr "GÃ¥ til linje"
@@ -656,6 +394,14 @@ msgstr "Hele ord"
msgid "Selection Only"
msgstr "Kun Valgte"
+#: editor/code_editor.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
+msgid "Search"
+msgstr "Søg"
+
#: editor/code_editor.cpp editor/editor_help.cpp
msgid "Find"
msgstr "Find"
@@ -688,11 +434,11 @@ msgstr "Spørg ved Erstat"
msgid "Skip"
msgstr "Spring over"
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom In"
msgstr "Zoom ind"
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom Out"
msgstr "Zoom ud"
@@ -759,6 +505,20 @@ msgstr "Udskudt"
msgid "Oneshot"
msgstr "OneShot"
+#: editor/connections_dialog.cpp editor/dependency_editor.cpp
+#: editor/export_template_manager.cpp
+#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Close"
+msgstr "Luk"
+
#: editor/connections_dialog.cpp
msgid "Connect"
msgstr "Tilslut"
@@ -784,7 +544,7 @@ msgstr "Forbind..."
msgid "Disconnect"
msgstr "Afbryd"
-#: editor/connections_dialog.cpp editor/node_dock.cpp
+#: editor/connections_dialog.cpp editor/editor_help.cpp editor/node_dock.cpp
msgid "Signals"
msgstr "Signaler"
@@ -801,12 +561,25 @@ msgstr ""
msgid "Recent:"
msgstr ""
+#: editor/create_dialog.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/quick_open.cpp editor/settings_config_dialog.cpp
+msgid "Search:"
+msgstr "Søgning:"
+
#: editor/create_dialog.cpp editor/editor_help.cpp
#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/quick_open.cpp
msgid "Matches:"
msgstr "Matches:"
+#: editor/create_dialog.cpp editor/editor_help.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/property_selector.cpp
+#: editor/script_editor_debugger.cpp
+msgid "Description:"
+msgstr ""
+
#: editor/dependency_editor.cpp
msgid "Search Replacement For:"
msgstr "Søg erstatning For:"
@@ -866,6 +639,10 @@ msgid "Owners Of:"
msgstr ""
#: editor/dependency_editor.cpp
+msgid "Remove selected files from the project? (no undo)"
+msgstr ""
+
+#: editor/dependency_editor.cpp
msgid ""
"The files being removed are required by other resources in order for them to "
"work.\n"
@@ -873,7 +650,7 @@ msgid ""
msgstr ""
#: editor/dependency_editor.cpp
-msgid "Remove selected files from the project? (no undo)"
+msgid "Cannot remove:\n"
msgstr ""
#: editor/dependency_editor.cpp
@@ -940,10 +717,6 @@ msgid "Godot Engine contributors"
msgstr ""
#: editor/editor_about.cpp
-msgid "Authors"
-msgstr ""
-
-#: editor/editor_about.cpp
msgid "Project Founders"
msgstr ""
@@ -960,6 +733,38 @@ msgid "Developers"
msgstr ""
#: editor/editor_about.cpp
+msgid "Authors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Platinum Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Gold Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Mini Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Gold Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Silver Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Bronze Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
msgid "License"
msgstr ""
@@ -1002,6 +807,16 @@ msgid "Package Installed Successfully!"
msgstr ""
#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Success!"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/project_manager.cpp
+msgid "Install"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
msgid "Package Installer"
msgstr ""
@@ -1052,10 +867,6 @@ msgid "Audio Bus, Drag and Drop to rearrange."
msgstr ""
#: editor/editor_audio_buses.cpp
-msgid "Bus options"
-msgstr ""
-
-#: editor/editor_audio_buses.cpp
msgid "Solo"
msgstr ""
@@ -1067,6 +878,10 @@ msgstr ""
msgid "Bypass"
msgstr ""
+#: editor/editor_audio_buses.cpp
+msgid "Bus options"
+msgstr ""
+
#: editor/editor_audio_buses.cpp editor/plugins/tile_map_editor_plugin.cpp
#: editor/scene_tree_dock.cpp
msgid "Duplicate"
@@ -1074,6 +889,11 @@ msgstr ""
#: editor/editor_audio_buses.cpp
#, fuzzy
+msgid "Reset Volume"
+msgstr "Nulstil Zoom"
+
+#: editor/editor_audio_buses.cpp
+#, fuzzy
msgid "Delete Effect"
msgstr "Slet Valgte"
@@ -1097,6 +917,11 @@ msgstr "Dubler valg"
#: editor/editor_audio_buses.cpp
#, fuzzy
+msgid "Reset Bus Volume"
+msgstr "Nulstil Zoom"
+
+#: editor/editor_audio_buses.cpp
+#, fuzzy
msgid "Move Audio Bus"
msgstr "Flyt Add Key"
@@ -1128,7 +953,8 @@ msgstr ""
msgid "Create a new Bus Layout."
msgstr ""
-#: editor/editor_audio_buses.cpp editor/script_create_dialog.cpp
+#: editor/editor_audio_buses.cpp editor/property_editor.cpp
+#: editor/script_create_dialog.cpp
msgid "Load"
msgstr ""
@@ -1218,7 +1044,7 @@ msgid "Rearrange Autoloads"
msgstr ""
#: editor/editor_autoload_settings.cpp editor/editor_file_dialog.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp scene/gui/file_dialog.cpp
+#: scene/gui/file_dialog.cpp
msgid "Path:"
msgstr "Sti:"
@@ -1226,9 +1052,7 @@ msgstr "Sti:"
msgid "Node Name:"
msgstr ""
-#: editor/editor_autoload_settings.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp editor/project_manager.cpp
+#: editor/editor_autoload_settings.cpp editor/project_manager.cpp
msgid "Name"
msgstr ""
@@ -1261,18 +1085,19 @@ msgid "Choose a Directory"
msgstr ""
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Create Folder"
msgstr "Opret mappe"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: editor/editor_plugin_settings.cpp editor/plugins/theme_editor_plugin.cpp
-#: editor/project_export.cpp scene/gui/file_dialog.cpp
+#: editor/editor_plugin_settings.cpp editor/filesystem_dock.cpp
+#: editor/plugins/theme_editor_plugin.cpp editor/project_export.cpp
+#: scene/gui/file_dialog.cpp
msgid "Name:"
msgstr "Navn:"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Could not create folder."
msgstr "Kunne ikke oprette mappe."
@@ -1292,30 +1117,6 @@ msgstr ""
msgid "Template file not found:\n"
msgstr ""
-#: editor/editor_export.cpp
-msgid "Added:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Removed:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Error saving atlas:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Could not save atlas subtexture:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Exporting for %s"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Setting Up.."
-msgstr ""
-
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "File Exists, Overwrite?"
msgstr "Filen findes, overskrives?"
@@ -1400,6 +1201,11 @@ msgstr ""
msgid "Move Favorite Down"
msgstr ""
+#: editor/editor_file_dialog.cpp
+#, fuzzy
+msgid "Go to parent folder"
+msgstr "Kunne ikke oprette mappe."
+
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Directories & Files:"
msgstr "Mapper & filer:"
@@ -1414,10 +1220,6 @@ msgid "File:"
msgstr "Fil:"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
-msgid "Filter:"
-msgstr "Filter:"
-
-#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Must use a valid extension."
msgstr "Skal bruge en gyldig udvidelse."
@@ -1442,6 +1244,10 @@ msgstr ""
msgid "Search Classes"
msgstr ""
+#: editor/editor_help.cpp editor/plugins/spatial_editor_plugin.cpp
+msgid "Top"
+msgstr ""
+
#: editor/editor_help.cpp editor/property_editor.cpp
msgid "Class:"
msgstr ""
@@ -1458,15 +1264,29 @@ msgstr ""
msgid "Brief Description:"
msgstr ""
+#: editor/editor_help.cpp
+#, fuzzy
+msgid "Members"
+msgstr "Medlemmer:"
+
#: editor/editor_help.cpp modules/visual_script/visual_script_editor.cpp
msgid "Members:"
msgstr "Medlemmer:"
#: editor/editor_help.cpp
+#, fuzzy
+msgid "Public Methods"
+msgstr "Vælg alle"
+
+#: editor/editor_help.cpp
msgid "Public Methods:"
msgstr ""
#: editor/editor_help.cpp
+msgid "GUI Theme Items"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "GUI Theme Items:"
msgstr ""
@@ -1476,6 +1296,11 @@ msgstr "Signaler:"
#: editor/editor_help.cpp
#, fuzzy
+msgid "Enumerations"
+msgstr "Funktioner:"
+
+#: editor/editor_help.cpp
+#, fuzzy
msgid "Enumerations:"
msgstr "Funktioner:"
@@ -1484,19 +1309,50 @@ msgid "enum "
msgstr ""
#: editor/editor_help.cpp
+#, fuzzy
+msgid "Constants"
+msgstr "Konstant"
+
+#: editor/editor_help.cpp
msgid "Constants:"
msgstr ""
#: editor/editor_help.cpp
#, fuzzy
+msgid "Description"
+msgstr "Opret abonnement"
+
+#: editor/editor_help.cpp
+msgid "Properties"
+msgstr ""
+
+#: editor/editor_help.cpp
+#, fuzzy
msgid "Property Description:"
msgstr "Opret abonnement"
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this property. Please help us by "
+"[color=$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+
+#: editor/editor_help.cpp
+#, fuzzy
+msgid "Methods"
+msgstr "Metode liste:"
+
+#: editor/editor_help.cpp
msgid "Method Description:"
msgstr ""
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this method. Please help us by [color="
+"$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Search Text"
msgstr ""
@@ -1505,24 +1361,21 @@ msgid "Output:"
msgstr ""
#: editor/editor_log.cpp editor/plugins/animation_tree_editor_plugin.cpp
-#: editor/plugins/rich_text_editor_plugin.cpp editor/property_editor.cpp
-#: editor/script_editor_debugger.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/property_editor.cpp editor/script_editor_debugger.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Clear"
msgstr "Clear"
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Error saving resource!"
msgstr ""
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Save Resource As.."
msgstr ""
-#: editor/editor_node.cpp editor/export_template_manager.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "I see.."
msgstr ""
@@ -1539,6 +1392,29 @@ msgid "Error while saving."
msgstr ""
#: editor/editor_node.cpp
+#, fuzzy
+msgid "Can't open '%s'."
+msgstr "Forbind..."
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Error while parsing '%s'."
+msgstr "Error loading skrifttype."
+
+#: editor/editor_node.cpp
+msgid "Unexpected end of file '%s'."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Missing '%s' or its dependencies."
+msgstr ""
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Error while loading '%s'."
+msgstr "Error loading skrifttype."
+
+#: editor/editor_node.cpp
msgid "Saving Scene"
msgstr ""
@@ -1596,6 +1472,33 @@ msgid "Restored default layout to base settings."
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was imported, so it's not editable.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was instanced or inherited.\n"
+"Changes to it will not be kept when saving the current scene."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource was imported, so it's not editable. Change its settings in the "
+"import panel and then re-import."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This scene was imported, so changes to it will not be kept.\n"
+"Instancing it or inheriting will allow making changes to it.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Copy Params"
msgstr ""
@@ -1759,23 +1662,35 @@ msgid "Save changes the following scene(s) before opening Project Manager?"
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"This option is deprecated. Situations where refresh must be forced are now "
+"considered a bug. Please report."
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Pick a Main Scene"
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to enable addon plugin at: '"
+msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr ""
#: editor/editor_node.cpp
-msgid "' parsing of config failed."
+msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/"
+#, fuzzy
+msgid "Unable to load addon script from path: '%s'."
+msgstr "Error loading skrifttype."
+
+#: editor/editor_node.cpp
+msgid ""
+"Unable to load addon script from path: '%s' Base type is not EditorPlugin."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to load addon script from path: '"
+msgid "Unable to load addon script from path: '%s' Script is not in tool mode."
msgstr ""
#: editor/editor_node.cpp
@@ -1785,7 +1700,7 @@ msgid ""
msgstr ""
#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/scene_tree_dock.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Ugh"
msgstr ""
@@ -1796,11 +1711,11 @@ msgid ""
msgstr ""
#: editor/editor_node.cpp
-msgid "Error loading scene."
+msgid "Scene '%s' has broken dependencies:"
msgstr ""
#: editor/editor_node.cpp
-msgid "Scene '%s' has broken dependencies:"
+msgid "Clear Recent Scenes"
msgstr ""
#: editor/editor_node.cpp
@@ -1836,7 +1751,7 @@ msgstr ""
msgid "Toggle distraction-free mode."
msgstr ""
-#: editor/editor_node.cpp editor/io_plugins/editor_scene_import_plugin.cpp
+#: editor/editor_node.cpp
msgid "Scene"
msgstr ""
@@ -2056,6 +1971,10 @@ msgstr ""
msgid "Issue Tracker"
msgstr ""
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+msgid "Community"
+msgstr "Fællesskabet"
+
#: editor/editor_node.cpp
msgid "About"
msgstr ""
@@ -2064,7 +1983,7 @@ msgstr ""
msgid "Play the project."
msgstr ""
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Play"
msgstr ""
@@ -2080,7 +1999,7 @@ msgstr ""
msgid "Stop the scene."
msgstr ""
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Stop"
msgstr ""
@@ -2153,6 +2072,15 @@ msgid "Object properties."
msgstr ""
#: editor/editor_node.cpp
+msgid "Changes may be lost!"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Import"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "FileSystem"
msgstr ""
@@ -2168,14 +2096,6 @@ msgstr ""
msgid "Don't Save"
msgstr ""
-#: editor/editor_node.cpp editor/editor_reimport_dialog.cpp
-msgid "Re-Import"
-msgstr ""
-
-#: editor/editor_node.cpp editor/editor_plugin_settings.cpp
-msgid "Update"
-msgstr ""
-
#: editor/editor_node.cpp
msgid "Import Templates From ZIP File"
msgstr ""
@@ -2240,11 +2160,28 @@ msgstr "Afhængigheds Editor"
msgid "Open the previous Editor"
msgstr ""
+#: editor/editor_plugin.cpp
+msgid "Creating Mesh Previews"
+msgstr ""
+
+#: editor/editor_plugin.cpp
+msgid "Thumbnail.."
+msgstr ""
+
#: editor/editor_plugin_settings.cpp
msgid "Installed Plugins:"
msgstr ""
#: editor/editor_plugin_settings.cpp
+msgid "Update"
+msgstr ""
+
+#: editor/editor_plugin_settings.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Version:"
+msgstr ""
+
+#: editor/editor_plugin_settings.cpp
msgid "Author:"
msgstr ""
@@ -2277,7 +2214,7 @@ msgid "Frame %"
msgstr ""
#: editor/editor_profiler.cpp
-msgid "Fixed Frame %"
+msgid "Physics Frame %"
msgstr ""
#: editor/editor_profiler.cpp editor/script_editor_debugger.cpp
@@ -2296,26 +2233,6 @@ msgstr ""
msgid "Frame #:"
msgstr ""
-#: editor/editor_reimport_dialog.cpp
-msgid "Please wait for scan to complete."
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Current scene must be saved to re-import."
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Save & Re-Import"
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Importing"
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Import Changed Resources"
-msgstr ""
-
#: editor/editor_run_native.cpp
msgid "Select device from the list"
msgstr ""
@@ -2425,10 +2342,6 @@ msgid "Importing:"
msgstr ""
#: editor/export_template_manager.cpp
-msgid "Loading Export Templates"
-msgstr ""
-
-#: editor/export_template_manager.cpp
msgid "Current Version:"
msgstr ""
@@ -2463,9 +2376,17 @@ msgid "Cannot navigate to '"
msgstr ""
#: editor/filesystem_dock.cpp
+msgid "View items as a grid of thumbnails"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "View items as a list"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
msgid ""
"\n"
-"Status: Needs Re-Import"
+"Status: Import of file failed. Please fix file and reimport manually."
msgstr ""
#: editor/filesystem_dock.cpp
@@ -2476,45 +2397,49 @@ msgid ""
msgstr "Ressource"
#: editor/filesystem_dock.cpp
-msgid "Same source and destination files, doing nothing."
+msgid "Cannot move/rename resources root."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Target file exists, can't overwrite. Delete first."
+msgid "Cannot move a folder into itself.\n"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Same source and destination paths, doing nothing."
-msgstr ""
+#, fuzzy
+msgid "Error moving:\n"
+msgstr "Error loading skrifttype."
#: editor/filesystem_dock.cpp
-msgid "Can't move directories to within themselves."
+msgid "Unable to update dependencies:\n"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Can't rename deps for:\n"
+msgid "No name provided"
msgstr ""
#: editor/filesystem_dock.cpp
-#, fuzzy
-msgid "Error moving file:\n"
-msgstr "Error loading skrifttype."
+msgid "Provided name contains invalid characters"
+msgstr ""
#: editor/filesystem_dock.cpp
-#, fuzzy
-msgid "Error moving dir:\n"
-msgstr "Error loading skrifttype."
+msgid "No name provided."
+msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Can't operate on '..'"
+msgid "Name contains invalid characters."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Pick New Name and Location For:"
+msgid "A file or folder with this name already exists."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "No files selected!"
+#, fuzzy
+msgid "Renaming file:"
+msgstr "Omdøbe variablen"
+
+#: editor/filesystem_dock.cpp
+msgid "Renaming folder:"
msgstr ""
#: editor/filesystem_dock.cpp
@@ -2526,39 +2451,36 @@ msgid "Collapse all"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Show In File Manager"
+msgid "Copy Path"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Instance"
+msgid "Rename.."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Edit Dependencies.."
-msgstr ""
-
-#: editor/filesystem_dock.cpp
-msgid "View Owners.."
+msgid "Move To.."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Copy Path"
-msgstr ""
+#, fuzzy
+msgid "New Folder.."
+msgstr "Opret mappe"
#: editor/filesystem_dock.cpp
-msgid "Rename or Move.."
+msgid "Show In File Manager"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Move To.."
+msgid "Instance"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Info"
+msgid "Edit Dependencies.."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Re-Import.."
+msgid "View Owners.."
msgstr ""
#: editor/filesystem_dock.cpp
@@ -2591,6 +2513,11 @@ msgstr ""
msgid "Move"
msgstr ""
+#: editor/filesystem_dock.cpp editor/plugins/animation_tree_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Rename"
+msgstr ""
+
#: editor/groups_editor.cpp
msgid "Add to Group"
msgstr ""
@@ -2604,6 +2531,10 @@ msgid "Import as Single Scene"
msgstr ""
#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
msgid "Import with Separate Materials"
msgstr ""
@@ -2616,6 +2547,18 @@ msgid "Import with Separate Objects+Materials"
msgstr ""
#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Materials+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Materials+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
msgid "Import as Multiple Scenes"
msgstr ""
@@ -2624,38 +2567,31 @@ msgid "Import as Multiple Scenes+Materials"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Import Scene"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Importing Scene.."
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Running Custom Script.."
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Couldn't load post-import script:"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Invalid/broken script for post-import (check console):"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Error running post-import script:"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Saving.."
msgstr ""
@@ -2684,579 +2620,54 @@ msgstr ""
msgid "Reimport"
msgstr ""
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "No bit masks to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path is empty."
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must be a complete resource path."
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must exist."
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Save path is empty!"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Import BitMasks"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s):"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Target Path:"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Accept"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Bit Mask"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No source font file!"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No target font resource!"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"Invalid file extension.\n"
-"Please use .font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Can't load/process source font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Couldn't save font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font Size:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Dest Resource:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "The quick brown fox jumps over the lazy dog."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Test:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Options:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Font Import"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"This file is already a Godot font file, please supply a BMFont type file "
-"instead."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Failed opening as BMFont file."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error initializing FreeType."
-msgstr "Fejl under initialisering af FreeType."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Unknown font format."
-msgstr "Ukendt skrifttypeformat."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error loading font."
-msgstr "Error loading skrifttype."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Invalid font size."
-msgstr "Ugyldig skriftstørrelse."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Invalid font custom source."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/plugins/theme_editor_plugin.cpp
-msgid "Font"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "No meshes to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Single Mesh Import"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Source Mesh(es):"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/plugins/mesh_instance_editor_plugin.cpp
-msgid "Mesh"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Surface %d"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "No samples to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Import Audio Samples"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Source Sample(s):"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Audio Sample"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "New Clip"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Animation Options"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Flags"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Bake FPS:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Optimizer"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Linear Error"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angular Error"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angle"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Clips"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Start(s)"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "End(s)"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Loop"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Filters"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source path is empty."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't load post-import script."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Invalid/broken script for post-import."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Error importing scene."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import 3D Scene"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source Scene:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Same as Target Scene"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Shared"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Target Texture Folder:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Post-Process Script:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Custom Root Node Type:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Auto"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Root Node Name:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "The Following Files are Missing:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Anyway"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp scene/gui/dialogs.cpp
-msgid "Cancel"
-msgstr "Annuller"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import & Open"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Edited scene has not been saved, open imported scene anyway?"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Image:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Can't import a file over itself:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't localize path: %s (already local)"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "3D Scene Animation"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Uncompressed"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossless (PNG)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossy (WebP)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress (VRAM)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Format"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Compression Quality (WebP):"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Options"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Please specify some files!"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "At least one file needed for Atlas."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Error importing:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Only one file is required for large texture."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Max Texture Size:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for Atlas (2D)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cell Size:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Large Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Textures (2D)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture"
+#: editor/multi_node_edit.cpp
+msgid "MultiNode Set"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Base Atlas Texture"
+#: editor/node_dock.cpp
+msgid "Groups"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s)"
+#: editor/node_dock.cpp
+msgid "Select a Node to edit Signals and Groups."
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 2D"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create Poly"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 3D"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Insert Point"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "2D Texture"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly (Remove Point)"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "3D Texture"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Remove Poly And Point"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Atlas Texture"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create a new polygon from scratch."
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
+#: editor/plugins/abstract_polygon_2d_editor.cpp
msgid ""
-"NOTICE: Importing 2D textures is not mandatory. Just copy png/jpg files to "
-"the project."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Crop empty space."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Load Source Image"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Slicing"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Inserting"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Saving"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save large texture:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Build Atlas For:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Loading Image:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't load image:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Converting Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cropping Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Blitting Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save atlas image:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save converted texture:"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid source!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid translation source!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Column"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/script_create_dialog.cpp
-msgid "Language"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No items to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No target path!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translations"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Couldn't import!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translation"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Source CSV:"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Ignore First Row"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Compress"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Add to Project (project.godot)"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Languages:"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Translation"
-msgstr ""
-
-#: editor/multi_node_edit.cpp
-msgid "MultiNode Set"
-msgstr ""
-
-#: editor/node_dock.cpp
-msgid "Groups"
-msgstr ""
-
-#: editor/node_dock.cpp
-msgid "Select a Node to edit Signals and Groups."
+"Edit existing polygon:\n"
+"LMB: Move Point.\n"
+"Ctrl+LMB: Split Segment.\n"
+"RMB: Erase Point."
msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
@@ -3413,7 +2824,6 @@ msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
#: editor/script_create_dialog.cpp
msgid "Error!"
@@ -3524,10 +2934,6 @@ msgid "Delete Input"
msgstr ""
#: editor/plugins/animation_tree_editor_plugin.cpp
-msgid "Rename"
-msgstr ""
-
-#: editor/plugins/animation_tree_editor_plugin.cpp
msgid "Animation tree is valid."
msgstr ""
@@ -3583,64 +2989,188 @@ msgstr ""
msgid "Filters.."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing %d Triangles:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Free"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Triangle #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Contents:"
+msgstr "Kontinuerlig"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "View Files"
+msgstr "Fil:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve hostname:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Light Baker Setup:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing Geometry"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connection error, please try again."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Fixing Lights"
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Can't connect."
+msgstr "Forbind..."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Can't connect to host:"
+msgstr "Opret forbindelse til Node:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response from host:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Making BVH"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Light Octree"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, return code:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Octree Texture"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Req. Failed."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Transfer to Lightmaps:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, too many redirects"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Allocating Texture #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Redirect Loop."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Baking Triangle #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Post-Processing Texture #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Bad download hash, assuming file has been tampered with."
msgstr ""
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Bake!"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Expected:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Got:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed sha256 hash check"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Asset Download Error:"
msgstr ""
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Reset the lightmap octree baking process (start over)."
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Fetching:"
msgstr ""
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Resolving.."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Connecting.."
+msgstr "Forbind..."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Requesting.."
+msgstr "Tester"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Error making request"
+msgstr "Error loading skrifttype."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Idle"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Retry"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download Error"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download for this asset is already in progress!"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "first"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "prev"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "next"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "last"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "All"
+msgstr "Alle"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Plugins"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Sort:"
+msgstr "Sorter:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Reverse"
+msgstr "Omvendt"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Category:"
+msgstr "Kategori:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Site:"
+msgstr "Websted:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Support.."
+msgstr "Støtte..."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Official"
+msgstr "Officiel"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Testing"
+msgstr "Tester"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Assets ZIP File"
+msgstr "Assets zipfil"
+
#: editor/plugins/camera_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
msgid "Preview"
msgstr ""
@@ -3683,11 +3213,15 @@ msgid "Edit CanvasItem"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Change Anchors"
+msgid "Anchors only"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Change Anchors and Margins"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom (%):"
+msgid "Change Anchors"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3738,59 +3272,73 @@ msgid "Pan Mode"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Lock the selected object in place (can't be moved)."
+#, fuzzy
+msgid "Toggles snapping"
+msgstr "Skift/Toggle Breakpoint"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Use Snap"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Unlock the selected object (can be moved)."
+msgid "Snapping options"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Makes sure the object's children are not selectable."
+msgid "Snap to grid"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Restores the object's children's ability to be selected."
+msgid "Use Rotation Snap"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Edit"
-msgstr "Rediger"
+msgid "Configure Snap..."
+msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Use Snap"
+msgid "Snap Relative"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Show Grid"
+msgid "Use Pixel Snap"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Rotation Snap"
+msgid "Smart snapping"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap Relative"
+msgid "Snap to parent"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Configure Snap.."
+msgid "Snap to node anchor"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Pixel Snap"
+msgid "Snap to node sides"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to other nodes"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Lock the selected object in place (can't be moved)."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Unlock the selected object (can be moved)."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Makes sure the object's children are not selectable."
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Skeleton.."
+msgid "Restores the object's children's ability to be selected."
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3819,11 +3367,16 @@ msgid "View"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Reset"
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Show Grid"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Show helpers"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Set.."
+msgid "Show rulers"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3835,7 +3388,7 @@ msgid "Frame Selection"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Anchor"
+msgid "Layout"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3859,11 +3412,20 @@ msgid "Clear Pose"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Set a Value"
+msgid "Drag pivot from mouse position"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap (Pixels):"
+#, fuzzy
+msgid "Set pivot at mouse position"
+msgstr "Fjern Signal"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Multiply grid step by 2"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Divide grid step by 2"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3874,23 +3436,28 @@ msgstr ""
msgid "Adding %s..."
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Create Node"
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Error instancing scene from %s"
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "OK :("
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "No parent to instance a child at."
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "This operation requires a single selected node."
msgstr ""
@@ -3905,45 +3472,6 @@ msgid ""
"Drag & drop + Alt : Change node type"
msgstr ""
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Create Poly"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly (Remove Point)"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Create a new polygon from scratch."
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-msgid ""
-"Edit existing polygon:\n"
-"LMB: Move Point.\n"
-"Ctrl+LMB: Split Segment.\n"
-"RMB: Erase Point."
-msgstr ""
-
#: editor/plugins/collision_polygon_editor_plugin.cpp
msgid "Create Poly3D"
msgstr ""
@@ -3953,14 +3481,6 @@ msgid "Set Handle"
msgstr ""
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Creating Mesh Library"
-msgstr ""
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Thumbnail.."
-msgstr ""
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Remove item %d?"
msgstr ""
@@ -3983,6 +3503,27 @@ msgid "Update from Scene"
msgstr ""
#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat0"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat1"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+#, fuzzy
+msgid "Ease in"
+msgstr "Skalering Valg"
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Ease out"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Smoothstep"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
msgid "Modify Curve Point"
msgstr ""
@@ -4062,22 +3603,18 @@ msgid "Create Occluder Polygon"
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Edit existing polygon:"
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "LMB: Move Point."
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Ctrl+LMB: Split Segment."
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "RMB: Erase Point."
msgstr ""
@@ -4179,6 +3716,10 @@ msgid "Create Outline"
msgstr ""
#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Mesh"
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Create Trimesh Static Body"
msgstr ""
@@ -4306,12 +3847,72 @@ msgstr ""
msgid "Populate"
msgstr ""
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Create Navigation Polygon"
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake!"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake the navigation mesh.\n"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Clear the navigation mesh."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Setting up Configuration..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Calculating grid size..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating heightfield..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Marking walkable triangles..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Constructing compact heightfield..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Eroding walkable area..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Partitioning..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating contours..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating polymesh..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Converting to native navigation mesh..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Navigation Mesh Generator Setup:"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Parsing Geometry..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Done!"
msgstr ""
#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Remove Poly And Point"
+msgid "Create Navigation Polygon"
msgstr ""
#: editor/plugins/particles_2d_editor_plugin.cpp
@@ -4485,16 +4086,19 @@ msgid "Curve Point #"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve Point Position"
-msgstr ""
+msgstr "Fjern Signal"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve In Position"
-msgstr ""
+msgstr "Fjern Signal"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve Out Position"
-msgstr ""
+msgstr "Fjern Signal"
#: editor/plugins/path_editor_plugin.cpp
msgid "Split Path"
@@ -4554,6 +4158,14 @@ msgid "Scale Polygon"
msgstr ""
#: editor/plugins/polygon_2d_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Edit"
+msgstr "Rediger"
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Polygon->UV"
msgstr ""
@@ -4608,63 +4220,10 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/shader_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "Indsæt"
-#: editor/plugins/rich_text_editor_plugin.cpp
-msgid "Parse BBCode"
-msgstr ""
-
-#: editor/plugins/sample_editor_plugin.cpp
-msgid "Length:"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Open Sample File(s)"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "ERROR: Couldn't load sample!"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Add Sample"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Rename Sample"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Delete Sample"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "16 Bits"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "8 Bits"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Stereo"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Mono"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Format"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Pitch"
-msgstr ""
-
#: editor/plugins/script_editor_plugin.cpp
msgid "Clear Recent Files"
msgstr ""
@@ -4756,6 +4315,10 @@ msgstr ""
msgid "Close All"
msgstr "Luk"
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+msgid "Run"
+msgstr ""
+
#: editor/plugins/script_editor_plugin.cpp
msgid "Toggle Scripts Panel"
msgstr ""
@@ -4784,7 +4347,8 @@ msgstr ""
msgid "Break"
msgstr ""
-#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+#: editor/script_editor_debugger.cpp
msgid "Continue"
msgstr ""
@@ -4798,18 +4362,6 @@ msgid "Debug with external editor"
msgstr "Afhængigheds Editor"
#: editor/plugins/script_editor_plugin.cpp
-msgid "Window"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Left"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Right"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
msgid "Open Godot online documentation"
msgstr ""
@@ -4892,8 +4444,9 @@ msgid "Cut"
msgstr "Cut"
#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "Kopier"
@@ -5158,10 +4711,6 @@ msgid "View Plane Transform."
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Scaling to %s%%."
-msgstr ""
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rotating %s degrees."
msgstr ""
@@ -5178,10 +4727,6 @@ msgid "Top View."
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Top"
-msgstr ""
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rear View."
msgstr ""
@@ -5414,6 +4959,10 @@ msgid "Transform"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Configure Snap.."
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Local Coords"
msgstr ""
@@ -5559,6 +5108,10 @@ msgid "Speed (FPS):"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Loop"
+msgstr ""
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Animation Frames"
msgstr ""
@@ -5571,11 +5124,12 @@ msgid "Insert Empty (After)"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Up"
-msgstr ""
+#, fuzzy
+msgid "Move (Before)"
+msgstr "Sti til Node:"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Down"
+msgid "Move (After)"
msgstr ""
#: editor/plugins/style_box_editor_plugin.cpp
@@ -5654,7 +5208,11 @@ msgid "Remove All"
msgstr "Fjern"
#: editor/plugins/theme_editor_plugin.cpp
-msgid "Theme"
+msgid "Edit theme.."
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Theme editing menu."
msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
@@ -5739,6 +5297,10 @@ msgid "Style"
msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
+msgid "Font"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
msgid "Color"
msgstr ""
@@ -5789,7 +5351,7 @@ msgid "Mirror Y"
msgstr ""
#: editor/plugins/tile_map_editor_plugin.cpp
-msgid "Bucket"
+msgid "Paint Tile"
msgstr ""
#: editor/plugins/tile_map_editor_plugin.cpp
@@ -5853,6 +5415,10 @@ msgid "Delete preset '%s'?"
msgstr ""
#: editor/project_export.cpp
+msgid "Export templates for this platform are missing/corrupted: "
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Presets"
msgstr ""
@@ -5925,19 +5491,29 @@ msgid "Export templates for this platform are missing:"
msgstr ""
#: editor/project_export.cpp
+msgid "Export templates for this platform are missing/corrupted:"
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Export With Debug"
msgstr ""
#: editor/project_manager.cpp
-msgid "Invalid project path, the path must exist!"
+msgid "The path does not exist."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Please choose a 'project.godot' file."
msgstr ""
#: editor/project_manager.cpp
-msgid "Invalid project path, project.godot must not exist."
+msgid ""
+"Your project will be created in a non empty folder (you might want to create "
+"a new folder)."
msgstr ""
#: editor/project_manager.cpp
-msgid "Invalid project path, project.godot must exist."
+msgid "Please choose a folder that does not contain a 'project.godot' file."
msgstr ""
#: editor/project_manager.cpp
@@ -5945,10 +5521,26 @@ msgid "Imported Project"
msgstr ""
#: editor/project_manager.cpp
+msgid " "
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "It would be a good idea to name your project."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Invalid project path (changed anything?)."
msgstr ""
#: editor/project_manager.cpp
+msgid "Couldn't get project.godot in project path."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Couldn't edit project.godot in project path."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
msgstr ""
@@ -5957,15 +5549,20 @@ msgid "The following files failed extraction from package:"
msgstr ""
#: editor/project_manager.cpp
-msgid "Import Existing Project"
+#, fuzzy
+msgid "Rename Project"
+msgstr "Omdøb Funktion"
+
+#: editor/project_manager.cpp
+msgid "Couldn't get project.godot in the project path."
msgstr ""
#: editor/project_manager.cpp
-msgid "Project Path (Must Exist):"
+msgid "New Game Project"
msgstr ""
#: editor/project_manager.cpp
-msgid "Project Name:"
+msgid "Import Existing Project"
msgstr ""
#: editor/project_manager.cpp
@@ -5973,19 +5570,24 @@ msgid "Create New Project"
msgstr ""
#: editor/project_manager.cpp
-msgid "Project Path:"
+msgid "Install Project:"
msgstr ""
#: editor/project_manager.cpp
-msgid "Install Project:"
+msgid "Project Name:"
msgstr ""
#: editor/project_manager.cpp
-msgid "Browse"
+#, fuzzy
+msgid "Create folder"
+msgstr "Opret mappe"
+
+#: editor/project_manager.cpp
+msgid "Project Path:"
msgstr ""
#: editor/project_manager.cpp
-msgid "New Game Project"
+msgid "Browse"
msgstr ""
#: editor/project_manager.cpp
@@ -5997,6 +5599,11 @@ msgid "Unnamed Project"
msgstr ""
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Can't open project"
+msgstr "Forbind..."
+
+#: editor/project_manager.cpp
msgid "Are you sure to open more than one project?"
msgstr ""
@@ -6023,16 +5630,18 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
-"You are about the scan %s folders for existing Godot projects. Do you "
-"confirm?"
+"Language changed.\n"
+"The UI will update next time the editor or project manager starts."
msgstr ""
#: editor/project_manager.cpp
-msgid "Project List"
+msgid ""
+"You are about the scan %s folders for existing Godot projects. Do you "
+"confirm?"
msgstr ""
#: editor/project_manager.cpp
-msgid "Run"
+msgid "Project List"
msgstr ""
#: editor/project_manager.cpp
@@ -6057,6 +5666,10 @@ msgid "Exit"
msgstr ""
#: editor/project_manager.cpp
+msgid "Restart Now"
+msgstr ""
+
+#: editor/project_manager.cpp
#, fuzzy
msgid "Can't run project"
msgstr "Forbind..."
@@ -6094,17 +5707,14 @@ msgid "Add Input Action Event"
msgstr ""
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Meta+"
msgstr "Meta +"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Shift+"
msgstr "Shift+"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Alt+"
msgstr "Alt +"
@@ -6165,7 +5775,7 @@ msgstr "Skift"
msgid "Joypad Axis Index:"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Axis"
msgstr "Akse"
@@ -6185,31 +5795,31 @@ msgstr ""
msgid "Add Event"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Device"
msgstr "Enhed"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Button"
msgstr "Knap"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Left Button."
msgstr "Venstre knap."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Right Button."
msgstr "Højre knap."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Middle Button."
msgstr "Midterste knap."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Up."
msgstr "Hjulet op."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Down."
msgstr "Hjulet ned."
@@ -6219,7 +5829,7 @@ msgid "Add Global Property"
msgstr "Tilføj Getter Egenskab"
#: editor/project_settings_editor.cpp
-msgid "Select an setting item first!"
+msgid "Select a setting item first!"
msgstr ""
#: editor/project_settings_editor.cpp
@@ -6237,6 +5847,15 @@ msgid "Delete Item"
msgstr "Slet Valgte"
#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Can't contain '/' or ':'"
+msgstr "Opret forbindelse til Node:"
+
+#: editor/project_settings_editor.cpp
+msgid "Already existing"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "Error saving settings."
msgstr ""
@@ -6277,6 +5896,15 @@ msgid "Remove Resource Remap Option"
msgstr ""
#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Changed Locale Filter"
+msgstr "Skift Array værditype"
+
+#: editor/project_settings_editor.cpp
+msgid "Changed Locale Filter Mode"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "Project Settings (project.godot)"
msgstr ""
@@ -6337,6 +5965,27 @@ msgid "Locale"
msgstr ""
#: editor/project_settings_editor.cpp
+msgid "Locales Filter"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Show all locales"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Show only selected locales"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Filter mode:"
+msgstr "Filter:"
+
+#: editor/project_settings_editor.cpp
+msgid "Locales:"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "AutoLoad"
msgstr ""
@@ -6386,10 +6035,19 @@ msgid "New Script"
msgstr ""
#: editor/property_editor.cpp
+msgid "Make Unique"
+msgstr ""
+
+#: editor/property_editor.cpp
msgid "Show in File System"
msgstr ""
#: editor/property_editor.cpp
+#, fuzzy
+msgid "Convert To %s"
+msgstr "Opret forbindelse til Node:"
+
+#: editor/property_editor.cpp
msgid "Error loading file: Not a resource!"
msgstr ""
@@ -6429,6 +6087,11 @@ msgstr "Tilføj Setter Egenskab"
#: editor/property_selector.cpp
#, fuzzy
+msgid "Select Virtual Method"
+msgstr "Vælg alle"
+
+#: editor/property_selector.cpp
+#, fuzzy
msgid "Select Method"
msgstr "Vælg alle"
@@ -6456,26 +6119,6 @@ msgstr ""
msgid "Reparent"
msgstr ""
-#: editor/resources_dock.cpp
-msgid "Create New Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Open Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Save Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Resource Tools"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Make Local"
-msgstr ""
-
#: editor/run_settings_dialog.cpp
msgid "Run Mode:"
msgstr ""
@@ -6603,14 +6246,6 @@ msgid "Sub-Resources:"
msgstr "Ressource"
#: editor/scene_tree_dock.cpp
-msgid "Edit Groups"
-msgstr ""
-
-#: editor/scene_tree_dock.cpp
-msgid "Edit Connections"
-msgstr ""
-
-#: editor/scene_tree_dock.cpp
msgid "Clear Inheritance"
msgstr ""
@@ -6797,6 +6432,15 @@ msgid "Invalid base path"
msgstr ""
#: editor/script_create_dialog.cpp
+msgid "Directory of the same name exists"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
+#, fuzzy
+msgid "File exists, will be reused"
+msgstr "Filen findes, overskrives?"
+
+#: editor/script_create_dialog.cpp
msgid "Invalid extension"
msgstr ""
@@ -6840,6 +6484,10 @@ msgid "Load existing script file"
msgstr ""
#: editor/script_create_dialog.cpp
+msgid "Language"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
msgid "Inherits"
msgstr ""
@@ -6881,6 +6529,10 @@ msgid "Function:"
msgstr ""
#: editor/script_editor_debugger.cpp
+msgid "Pick one or more items from the list to display the graph."
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
msgid "Errors"
msgstr ""
@@ -6961,6 +6613,10 @@ msgid "Type"
msgstr ""
#: editor/script_editor_debugger.cpp
+msgid "Format"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
msgid "Usage"
msgstr ""
@@ -7036,12 +6692,28 @@ msgstr ""
msgid "Change Probe Extents"
msgstr ""
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Library"
+msgstr ""
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Status"
+msgstr ""
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Libraries: "
+msgstr ""
+
+#: modules/gdnative/register_types.cpp
+msgid "GDNative"
+msgstr ""
+
#: modules/gdscript/gd_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Invalid type argument to convert(), use TYPE_* constants."
msgstr "Ugyldigt type argument til convert(), brug TYPE_* konstanter."
-#: modules/gdscript/gd_functions.cpp
+#: modules/gdscript/gd_functions.cpp modules/mono/glue/glue_header.h
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Not enough bytes for decoding bytes, or invalid format."
msgstr "Ikke nok bytes til afkodning af bytes, eller ugyldigt format."
@@ -7093,10 +6765,6 @@ msgid "GridMap Duplicate Selection"
msgstr "Dubler valg"
#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "GridMap Paint"
-msgstr ""
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Snap View"
msgstr ""
@@ -7192,13 +6860,8 @@ msgstr ""
msgid "Pick Distance:"
msgstr ""
-#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
-msgid "Tiles"
-msgstr "Fil:"
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "Areas"
+#: modules/mono/editor/mono_bottom_panel.cpp
+msgid "Builds"
msgstr ""
#: modules/visual_script/visual_script.cpp
@@ -7407,10 +7070,18 @@ msgid "Return"
msgstr "Tilbage:"
#: modules/visual_script/visual_script_editor.cpp
+msgid "Call"
+msgstr "Kald"
+
+#: modules/visual_script/visual_script_editor.cpp
msgid "Get"
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
+msgid "Script already has function '%s'"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
#, fuzzy
msgid "Change Input Value"
msgstr "Ændre Array-værdi"
@@ -7821,6 +7492,12 @@ msgstr ""
"En SpriteFrames ressource skal oprettes eller angivets i egenskaben 'Frames' "
"for at AnimatedSprite3D kan vise frames."
+#: scene/3d/vehicle_body.cpp
+msgid ""
+"VehicleWheel serves to provide a wheel system to a VehicleBody. Please use "
+"it as a child of a VehicleBody."
+msgstr ""
+
#: scene/gui/color_picker.cpp
msgid "Raw Mode"
msgstr ""
@@ -7830,6 +7507,10 @@ msgid "Add current color as a preset"
msgstr ""
#: scene/gui/dialogs.cpp
+msgid "Cancel"
+msgstr "Annuller"
+
+#: scene/gui/dialogs.cpp
msgid "Alert!"
msgstr "Advarsel!"
@@ -7837,10 +7518,6 @@ msgstr "Advarsel!"
msgid "Please Confirm..."
msgstr "Bekræft venligst..."
-#: scene/gui/input_action.cpp
-msgid "Ctrl+"
-msgstr "CTRL +"
-
#: scene/gui/popup.cpp
msgid ""
"Popups will hide by default unless you call popup() or any of the popup*() "
@@ -7876,6 +7553,45 @@ msgstr ""
"den kan opnå en størrelse. Ellers gør den til en RenderTarget og tildel dens "
"indre textur til en node så den kan vises."
+#: scene/resources/dynamic_font.cpp
+msgid "Error initializing FreeType."
+msgstr "Fejl under initialisering af FreeType."
+
+#: scene/resources/dynamic_font.cpp
+msgid "Unknown font format."
+msgstr "Ukendt skrifttypeformat."
+
+#: scene/resources/dynamic_font.cpp
+msgid "Error loading font."
+msgstr "Error loading skrifttype."
+
+#: scene/resources/dynamic_font.cpp
+msgid "Invalid font size."
+msgstr "Ugyldig skriftstørrelse."
+
+#~ msgid "Filter:"
+#~ msgstr "Filter:"
+
+#~ msgid "Method List For '%s':"
+#~ msgstr "Metode liste For '%s':"
+
+#~ msgid "Arguments:"
+#~ msgstr "Argumenter:"
+
+#~ msgid "Return:"
+#~ msgstr "Tilbage:"
+
+#, fuzzy
+#~ msgid "Error moving file:\n"
+#~ msgstr "Error loading skrifttype."
+
+#, fuzzy
+#~ msgid "Tiles"
+#~ msgstr "Fil:"
+
+#~ msgid "Ctrl+"
+#~ msgstr "CTRL +"
+
#, fuzzy
#~ msgid "Invalid unique name."
#~ msgstr "Ugyldigt index egenskabsnavn."
diff --git a/editor/translations/de.po b/editor/translations/de.po
index 98e2e35922..986987978c 100644
--- a/editor/translations/de.po
+++ b/editor/translations/de.po
@@ -1,5 +1,6 @@
# German translation of the Godot Engine editor
-# Copyright (C) 2016-2017 Juan Linietsky, Ariel Manzur and the Godot community
+# Copyright (C) 2007-2017 Juan Linietsky, Ariel Manzur
+# Copyright (C) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)
# This file is distributed under the same license as the Godot source code.
#
# Alexander Mahr <alex.mahr@gmail.com>, 2016.
@@ -24,8 +25,8 @@ msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2017-06-28 09:12+0000\n"
-"Last-Translator: So Wieso <sowieso@dukun.de>\n"
+"PO-Revision-Date: 2017-10-07 04:45+0000\n"
+"Last-Translator: anonymous <>\n"
"Language-Team: German <https://hosted.weblate.org/projects/godot-engine/"
"godot/de/>\n"
"Language: de\n"
@@ -33,7 +34,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 2.15-dev\n"
+"X-Generator: Weblate 2.17-dev\n"
#: editor/animation_editor.cpp
msgid "Disabled"
@@ -209,10 +210,9 @@ msgid "Create %d NEW tracks and insert keys?"
msgstr "Erstelle %d NEUE Spuren und füge Schlüsselbilder hinzu?"
#: editor/animation_editor.cpp editor/create_dialog.cpp
-#: editor/editor_audio_buses.cpp
+#: editor/editor_audio_buses.cpp editor/plugins/abstract_polygon_2d_editor.cpp
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
#: editor/plugins/mesh_instance_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp editor/project_manager.cpp
#: editor/script_create_dialog.cpp
msgid "Create"
@@ -375,262 +375,6 @@ msgstr "Wertetyp des Arrays ändern"
msgid "Change Array Value"
msgstr "Array-Wert ändern"
-#: editor/asset_library_editor_plugin.cpp
-msgid "Free"
-msgstr "Frei"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_plugin_settings.cpp
-msgid "Version:"
-msgstr "Version:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Contents:"
-msgstr "Inhalt:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "View Files"
-msgstr "Dateien anzeigen"
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_help.cpp editor/property_selector.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Description:"
-msgstr "Beschreibung:"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-#: editor/project_manager.cpp
-msgid "Install"
-msgstr "Installieren"
-
-#: editor/asset_library_editor_plugin.cpp editor/call_dialog.cpp
-#: editor/connections_dialog.cpp editor/export_template_manager.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-#: editor/project_settings_editor.cpp editor/property_editor.cpp
-#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Close"
-msgstr "Schließen"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve hostname:"
-msgstr "Kann Hostnamen nicht auflösen:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve."
-msgstr "Kann nicht auflösen."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Connection error, please try again."
-msgstr "Verbindungsfehler, bitte erneut versuchen."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't connect."
-msgstr "Kann nicht verbinden."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't connect to host:"
-msgstr "Kann nicht zu Host verbinden:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response from host:"
-msgstr "Keine Antwort von Host:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response."
-msgstr "Keine Antwort."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Request failed, return code:"
-msgstr "Anfrage fehlgeschlagen: Rückgabewert:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Req. Failed."
-msgstr "Anfrage fehlgeschlagen."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Request failed, too many redirects"
-msgstr "Anfrage fehlgeschlagen, zu viele Weiterleitungen"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Redirect Loop."
-msgstr "Weiterleitungsschleife."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed:"
-msgstr "Fehlgeschlagen:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Bad download hash, assuming file has been tampered with."
-msgstr "Falsche Download-Prüfsumme, Datei könnte manipuliert worden sein."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Expected:"
-msgstr "Erwartet:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Got:"
-msgstr "Erhalten:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
-msgstr "Sha256-Prüfung fehlgeschlagen"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Asset Download Error:"
-msgstr "Asset-Download-Fehler:"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-msgid "Success!"
-msgstr "Erfolgreich!"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Fetching:"
-msgstr "Hole:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Resolving.."
-msgstr "Löse auf.."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Connecting.."
-msgstr "Verbinde.."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Requesting.."
-msgstr "Frage an.."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Error making request"
-msgstr "Fehler bei Anfrage"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Idle"
-msgstr "Leerlauf"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Retry"
-msgstr "Erneut versuchen"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Download Error"
-msgstr "Ãœbertragungsfehler"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Download for this asset is already in progress!"
-msgstr "Dieser Posten wird bereits herunter geladen!"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "first"
-msgstr "Anfang"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "prev"
-msgstr "zurück"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "next"
-msgstr "vor"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "last"
-msgstr "Ende"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "All"
-msgstr "Alle"
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
-#: editor/settings_config_dialog.cpp
-msgid "Search:"
-msgstr "Suche:"
-
-#: editor/asset_library_editor_plugin.cpp editor/code_editor.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Search"
-msgstr "Suche"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/project_manager.cpp
-msgid "Import"
-msgstr "Import"
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Plugins"
-msgstr "Erweiterungen"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Sort:"
-msgstr "Sortiere:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Reverse"
-msgstr "Umkehren"
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Category:"
-msgstr "Kategorie:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Site:"
-msgstr "Seite:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Support.."
-msgstr "Unterstützung.."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Official"
-msgstr "Offiziell"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-msgid "Community"
-msgstr "Gemeinschaft"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Testing"
-msgstr "Testphase"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Assets ZIP File"
-msgstr "Projektdaten als ZIP-Datei"
-
-#: editor/call_dialog.cpp
-msgid "Method List For '%s':"
-msgstr "Methodenliste für '%s':"
-
-#: editor/call_dialog.cpp modules/visual_script/visual_script_editor.cpp
-msgid "Call"
-msgstr "Aufruf"
-
-#: editor/call_dialog.cpp
-msgid "Method List:"
-msgstr "Methodenliste:"
-
-#: editor/call_dialog.cpp
-msgid "Arguments:"
-msgstr "Argumente:"
-
-#: editor/call_dialog.cpp
-msgid "Return:"
-msgstr "Rückgabe:"
-
#: editor/code_editor.cpp
msgid "Go to Line"
msgstr "Gehe zu Zeile"
@@ -644,7 +388,6 @@ msgid "No Matches"
msgstr "Keine Ãœbereinstimmungen"
#: editor/code_editor.cpp
-#, fuzzy
msgid "Replaced %d occurrence(s)."
msgstr "Suchbegriff wurde %d mal ersetzt."
@@ -668,6 +411,14 @@ msgstr "Ganze Wörter"
msgid "Selection Only"
msgstr "Nur Auswahl"
+#: editor/code_editor.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
+msgid "Search"
+msgstr "Suche"
+
#: editor/code_editor.cpp editor/editor_help.cpp
msgid "Find"
msgstr "Finde"
@@ -700,11 +451,11 @@ msgstr "Aufforderung beim Ersetzen"
msgid "Skip"
msgstr "Ãœberspringen"
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom In"
msgstr "Vergrößern"
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom Out"
msgstr "Verkleinern"
@@ -773,6 +524,20 @@ msgstr "Verzögert"
msgid "Oneshot"
msgstr "Einmalig"
+#: editor/connections_dialog.cpp editor/dependency_editor.cpp
+#: editor/export_template_manager.cpp
+#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Close"
+msgstr "Schließen"
+
#: editor/connections_dialog.cpp
msgid "Connect"
msgstr "Verbinden"
@@ -798,7 +563,7 @@ msgstr "Verbinde.."
msgid "Disconnect"
msgstr "Trennen"
-#: editor/connections_dialog.cpp editor/node_dock.cpp
+#: editor/connections_dialog.cpp editor/editor_help.cpp editor/node_dock.cpp
msgid "Signals"
msgstr "Signale"
@@ -815,12 +580,25 @@ msgstr "Favoriten:"
msgid "Recent:"
msgstr "Kürzlich:"
+#: editor/create_dialog.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/quick_open.cpp editor/settings_config_dialog.cpp
+msgid "Search:"
+msgstr "Suche:"
+
#: editor/create_dialog.cpp editor/editor_help.cpp
#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/quick_open.cpp
msgid "Matches:"
msgstr "Treffer:"
+#: editor/create_dialog.cpp editor/editor_help.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/property_selector.cpp
+#: editor/script_editor_debugger.cpp
+msgid "Description:"
+msgstr "Beschreibung:"
+
#: editor/dependency_editor.cpp
msgid "Search Replacement For:"
msgstr "Suche Ersatz für:"
@@ -880,6 +658,10 @@ msgid "Owners Of:"
msgstr "Besitzer von:"
#: editor/dependency_editor.cpp
+msgid "Remove selected files from the project? (no undo)"
+msgstr "Lösche ausgewählte Dateien aus dem Projekt? (nicht umkehrbar)"
+
+#: editor/dependency_editor.cpp
msgid ""
"The files being removed are required by other resources in order for them to "
"work.\n"
@@ -890,8 +672,9 @@ msgstr ""
"Trotzdem entfernen? (Nicht Wiederherstellbar)"
#: editor/dependency_editor.cpp
-msgid "Remove selected files from the project? (no undo)"
-msgstr "Lösche ausgewählte Dateien aus dem Projekt? (nicht umkehrbar)"
+#, fuzzy
+msgid "Cannot remove:\n"
+msgstr "Kann nicht auflösen."
#: editor/dependency_editor.cpp
msgid "Error loading:"
@@ -957,19 +740,12 @@ msgid "Godot Engine contributors"
msgstr "Godot-Engine-Mitwirkende"
#: editor/editor_about.cpp
-#, fuzzy
-msgid "Authors"
-msgstr "Autor:"
-
-#: editor/editor_about.cpp
-#, fuzzy
msgid "Project Founders"
-msgstr "Projektverwaltung"
+msgstr "Projektgründer"
#: editor/editor_about.cpp
-#, fuzzy
msgid "Lead Developer"
-msgstr "Entwickler"
+msgstr "Hauptentwickler"
#: editor/editor_about.cpp editor/project_manager.cpp
msgid "Project Manager"
@@ -980,118 +756,157 @@ msgid "Developers"
msgstr "Entwickler"
#: editor/editor_about.cpp
-msgid "License"
+msgid "Authors"
+msgstr "Autoren"
+
+#: editor/editor_about.cpp
+msgid "Platinum Sponsors"
msgstr ""
#: editor/editor_about.cpp
-msgid "Thirdparty License"
+msgid "Gold Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Mini Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Gold Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Silver Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+#, fuzzy
+msgid "Bronze Donors"
+msgstr "Klone herunter"
+
+#: editor/editor_about.cpp
+msgid "Donors"
msgstr ""
#: editor/editor_about.cpp
+msgid "License"
+msgstr "Lizenz"
+
+#: editor/editor_about.cpp
+msgid "Thirdparty License"
+msgstr "Drittpartei-Lizenz"
+
+#: editor/editor_about.cpp
msgid ""
"Godot Engine relies on a number of thirdparty free and open source "
"libraries, all compatible with the terms of its MIT license. The following "
"is an exhaustive list of all such thirdparty components with their "
"respective copyright statements and license terms."
msgstr ""
+"Die Godot-Engine baut auf einer Vielzahl freier und quelloffener projekt-"
+"externer Bibliotheken auf, die alle kompatibel mit den Auflagen der MIT-"
+"Lizenz sind. Es folgt eine vollständige Liste aller verwendeten externen "
+"Bibliotheken mit den jeweiligen zugehörigen Urheberrechtserklärungen und "
+"Lizenzbedingungen."
#: editor/editor_about.cpp
-#, fuzzy
msgid "All Components"
-msgstr "Inhalt:"
+msgstr "Alle Komponenten"
#: editor/editor_about.cpp
-#, fuzzy
msgid "Components"
-msgstr "Inhalt:"
+msgstr "Komponenten"
#: editor/editor_about.cpp
msgid "Licenses"
-msgstr ""
+msgstr "Lizenzen"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Error opening package file, not in zip format."
-msgstr ""
+msgstr "Fehler beim Öffnen der Paketdatei, kein Zip-Format."
#: editor/editor_asset_installer.cpp
-#, fuzzy
msgid "Uncompressing Assets"
-msgstr "Unkomprimiert"
+msgstr "Entpacke Assets"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package Installed Successfully!"
msgstr "Paket erfolgreich installiert!"
#: editor/editor_asset_installer.cpp
-#, fuzzy
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Success!"
+msgstr "Erfolgreich!"
+
+#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/project_manager.cpp
+msgid "Install"
+msgstr "Installieren"
+
+#: editor/editor_asset_installer.cpp
msgid "Package Installer"
-msgstr "Paket erfolgreich installiert!"
+msgstr "Paketinstallierung"
#: editor/editor_audio_buses.cpp
msgid "Speakers"
-msgstr ""
+msgstr "Lautsprecher"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Add Effect"
-msgstr "Ereignis hinzufügen"
+msgstr "Audiobuseffekt hinzufügen"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Rename Audio Bus"
-msgstr "Öffne Audiobus-Layout"
+msgstr "Audiobus umbenennen"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Toggle Audio Bus Solo"
-msgstr "Öffne Audiobus-Layout"
+msgstr "Audiobus Solo-Status umschalten"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Toggle Audio Bus Mute"
-msgstr "Öffne Audiobus-Layout"
+msgstr "Audiobus stumm schalten"
#: editor/editor_audio_buses.cpp
msgid "Toggle Audio Bus Bypass Effects"
-msgstr ""
+msgstr "Audiobus-Bypasseffekte umschalten"
#: editor/editor_audio_buses.cpp
+#, fuzzy
msgid "Select Audio Bus Send"
-msgstr ""
+msgstr "Audiobus Senden auswählen"
#: editor/editor_audio_buses.cpp
msgid "Add Audio Bus Effect"
-msgstr ""
+msgstr "Audiobuseffekt hinzufügen"
#: editor/editor_audio_buses.cpp
msgid "Move Bus Effect"
-msgstr ""
+msgstr "Audiobuseffekt verschieben"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Delete Bus Effect"
-msgstr "Ausgewähltes löschen"
+msgstr "Audiobuseffekt löschen"
#: editor/editor_audio_buses.cpp
msgid "Audio Bus, Drag and Drop to rearrange."
-msgstr ""
-
-#: editor/editor_audio_buses.cpp
-#, fuzzy
-msgid "Bus options"
-msgstr "Unterszenen-Optionen"
+msgstr "Audiobus, ziehen um umzusortieren."
#: editor/editor_audio_buses.cpp
msgid "Solo"
-msgstr ""
+msgstr "Solo"
#: editor/editor_audio_buses.cpp
msgid "Mute"
-msgstr ""
+msgstr "Stumm"
#: editor/editor_audio_buses.cpp
msgid "Bypass"
-msgstr ""
+msgstr "Bypass"
+
+#: editor/editor_audio_buses.cpp
+msgid "Bus options"
+msgstr "Audiobusoptionen"
#: editor/editor_audio_buses.cpp editor/plugins/tile_map_editor_plugin.cpp
#: editor/scene_tree_dock.cpp
@@ -1100,41 +915,45 @@ msgstr "Duplizieren"
#: editor/editor_audio_buses.cpp
#, fuzzy
+msgid "Reset Volume"
+msgstr "Vergrößerung zurücksetzen"
+
+#: editor/editor_audio_buses.cpp
msgid "Delete Effect"
-msgstr "Ausgewähltes löschen"
+msgstr "Effekt löschen"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Add Audio Bus"
msgstr "Audiobus hinzufügen"
#: editor/editor_audio_buses.cpp
msgid "Master bus can't be deleted!"
-msgstr ""
+msgstr "Master-Audiobus kann nicht gelöscht werden!"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Delete Audio Bus"
-msgstr "Layout löschen"
+msgstr "Audiobus löschen"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Duplicate Audio Bus"
-msgstr "Animation duplizieren"
+msgstr "Audiobus duplizieren"
#: editor/editor_audio_buses.cpp
#, fuzzy
+msgid "Reset Bus Volume"
+msgstr "Vergrößerung zurücksetzen"
+
+#: editor/editor_audio_buses.cpp
msgid "Move Audio Bus"
-msgstr "Aktion verschieben"
+msgstr "Audiobus verschieben"
#: editor/editor_audio_buses.cpp
msgid "Save Audio Bus Layout As.."
-msgstr "Audiobus-Layout speichern als…"
+msgstr "Audiobus-Layout speichern als.."
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Location for New Layout.."
-msgstr "Ort für neues Layout…"
+msgstr "Speicherort für neues Layout.."
#: editor/editor_audio_buses.cpp
msgid "Open Audio Bus Layout"
@@ -1142,32 +961,28 @@ msgstr "Öffne Audiobus-Layout"
#: editor/editor_audio_buses.cpp
msgid "There is no 'res://default_bus_layout.tres' file."
-msgstr ""
+msgstr "Datei ‚res://default_bus_layout.tres‘ existiert nicht."
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Invalid file, not an audio bus layout."
-msgstr ""
-"Ungültige Dateiendung.\n"
-"Nutze .font als Dateiendung."
+msgstr "Ungültige Datei, kein Audiobus-Layout."
#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr "Audiobus hinzufügen"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Create a new Bus Layout."
-msgstr "Erstelle neue Ressource"
+msgstr "Neues Audiobus-Layout erstellen."
-#: editor/editor_audio_buses.cpp editor/script_create_dialog.cpp
+#: editor/editor_audio_buses.cpp editor/property_editor.cpp
+#: editor/script_create_dialog.cpp
msgid "Load"
msgstr "Lade"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Load an existing Bus Layout."
-msgstr "Lade eine bestehende Ressource von der Festplatte und bearbeite sie."
+msgstr "Lade ein existierendes Bus-Layout."
#: editor/editor_audio_buses.cpp
#: editor/plugins/animation_player_editor_plugin.cpp
@@ -1175,18 +990,16 @@ msgid "Save As"
msgstr "Speichern als"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Save this Bus Layout to a file."
-msgstr "Audiobus-Layout speichern als…"
+msgstr "Bus-Layout in Datei speichern."
#: editor/editor_audio_buses.cpp editor/import_dock.cpp
-#, fuzzy
msgid "Load Default"
-msgstr "Standard"
+msgstr "Standard laden"
#: editor/editor_audio_buses.cpp
msgid "Load the default Bus Layout."
-msgstr ""
+msgstr "Standart Bus Layout laden."
#: editor/editor_autoload_settings.cpp
msgid "Invalid name."
@@ -1259,7 +1072,7 @@ msgid "Rearrange Autoloads"
msgstr "Autoloads neu anordnen"
#: editor/editor_autoload_settings.cpp editor/editor_file_dialog.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp scene/gui/file_dialog.cpp
+#: scene/gui/file_dialog.cpp
msgid "Path:"
msgstr "Pfad:"
@@ -1267,9 +1080,7 @@ msgstr "Pfad:"
msgid "Node Name:"
msgstr "Node-Name:"
-#: editor/editor_autoload_settings.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp editor/project_manager.cpp
+#: editor/editor_autoload_settings.cpp editor/project_manager.cpp
msgid "Name"
msgstr "Name"
@@ -1294,27 +1105,27 @@ msgid "Updating scene.."
msgstr "Aktualisiere Szene..."
#: editor/editor_dir_dialog.cpp
-#, fuzzy
msgid "Please select a base directory first"
-msgstr "Bitte speichere die Szene zuerst."
+msgstr "Zuerst ein Wurzelverzeichnis setzen"
#: editor/editor_dir_dialog.cpp
msgid "Choose a Directory"
msgstr "Wähle ein Verzeichnis"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Create Folder"
msgstr "Ordner erstellen"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: editor/editor_plugin_settings.cpp editor/plugins/theme_editor_plugin.cpp
-#: editor/project_export.cpp scene/gui/file_dialog.cpp
+#: editor/editor_plugin_settings.cpp editor/filesystem_dock.cpp
+#: editor/plugins/theme_editor_plugin.cpp editor/project_export.cpp
+#: scene/gui/file_dialog.cpp
msgid "Name:"
msgstr "Name:"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Could not create folder."
msgstr "Ordner konnte nicht erstellt werden."
@@ -1334,30 +1145,6 @@ msgstr "Packe"
msgid "Template file not found:\n"
msgstr "Template-Datei nicht gefunden:\n"
-#: editor/editor_export.cpp
-msgid "Added:"
-msgstr "Hinzugefügt:"
-
-#: editor/editor_export.cpp
-msgid "Removed:"
-msgstr "Entfernt:"
-
-#: editor/editor_export.cpp
-msgid "Error saving atlas:"
-msgstr "Fehler beim speichern des Atlas:"
-
-#: editor/editor_export.cpp
-msgid "Could not save atlas subtexture:"
-msgstr "Atlas Untertextur konnte nicht gespeichert werden:"
-
-#: editor/editor_export.cpp
-msgid "Exporting for %s"
-msgstr "Exportiere für %s"
-
-#: editor/editor_export.cpp
-msgid "Setting Up.."
-msgstr "Bereite vor..."
-
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "File Exists, Overwrite?"
msgstr "Datei existiert bereits. Ãœberschreiben?"
@@ -1442,6 +1229,11 @@ msgstr "Favorit nach oben schieben"
msgid "Move Favorite Down"
msgstr "Favorit nach unten schieben"
+#: editor/editor_file_dialog.cpp
+#, fuzzy
+msgid "Go to parent folder"
+msgstr "Ordner konnte nicht erstellt werden."
+
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Directories & Files:"
msgstr "Verzeichnisse & Dateien:"
@@ -1456,10 +1248,6 @@ msgid "File:"
msgstr "Datei:"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
-msgid "Filter:"
-msgstr "Filter:"
-
-#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Must use a valid extension."
msgstr "Eine gültige Datei-Endung muss verwendet werden."
@@ -1468,9 +1256,8 @@ msgid "ScanSources"
msgstr "Lese Quellen"
#: editor/editor_file_system.cpp
-#, fuzzy
msgid "(Re)Importing Assets"
-msgstr "Importiere erneut"
+msgstr "Importiere Assets erneut"
#: editor/editor_help.cpp editor/editor_node.cpp
#: editor/plugins/script_editor_plugin.cpp
@@ -1485,6 +1272,10 @@ msgstr "Klassenliste:"
msgid "Search Classes"
msgstr "Klassen suchen"
+#: editor/editor_help.cpp editor/plugins/spatial_editor_plugin.cpp
+msgid "Top"
+msgstr "Oben"
+
#: editor/editor_help.cpp editor/property_editor.cpp
msgid "Class:"
msgstr "Klasse:"
@@ -1501,15 +1292,30 @@ msgstr "Geerbt von:"
msgid "Brief Description:"
msgstr "Kurze Beschreibung:"
+#: editor/editor_help.cpp
+#, fuzzy
+msgid "Members"
+msgstr "Mitglieder:"
+
#: editor/editor_help.cpp modules/visual_script/visual_script_editor.cpp
msgid "Members:"
msgstr "Mitglieder:"
#: editor/editor_help.cpp
+#, fuzzy
+msgid "Public Methods"
+msgstr "Öffentliche Methoden:"
+
+#: editor/editor_help.cpp
msgid "Public Methods:"
msgstr "Öffentliche Methoden:"
#: editor/editor_help.cpp
+#, fuzzy
+msgid "GUI Theme Items"
+msgstr "GUI-Theme-Elemente:"
+
+#: editor/editor_help.cpp
msgid "GUI Theme Items:"
msgstr "GUI-Theme-Elemente:"
@@ -1519,53 +1325,85 @@ msgstr "Signale:"
#: editor/editor_help.cpp
#, fuzzy
+msgid "Enumerations"
+msgstr "Enums:"
+
+#: editor/editor_help.cpp
msgid "Enumerations:"
-msgstr "Animationen"
+msgstr "Enums:"
#: editor/editor_help.cpp
msgid "enum "
-msgstr ""
+msgstr "Enum "
+
+#: editor/editor_help.cpp
+#, fuzzy
+msgid "Constants"
+msgstr "Konstanten:"
#: editor/editor_help.cpp
msgid "Constants:"
msgstr "Konstanten:"
#: editor/editor_help.cpp
+#, fuzzy
+msgid "Description"
+msgstr "Beschreibung:"
+
+#: editor/editor_help.cpp
+#, fuzzy
+msgid "Properties"
+msgstr "Eigenschaften:"
+
+#: editor/editor_help.cpp
msgid "Property Description:"
msgstr "Eigenschaft-Beschreibung:"
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this property. Please help us by "
+"[color=$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+
+#: editor/editor_help.cpp
+#, fuzzy
+msgid "Methods"
+msgstr "Methodenliste:"
+
+#: editor/editor_help.cpp
msgid "Method Description:"
msgstr "Methoden-Beschreibung:"
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this method. Please help us by [color="
+"$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Search Text"
msgstr "Suchtext"
#: editor/editor_log.cpp
-#, fuzzy
msgid "Output:"
-msgstr " Ausgabe:"
+msgstr "Ausgabe:"
#: editor/editor_log.cpp editor/plugins/animation_tree_editor_plugin.cpp
-#: editor/plugins/rich_text_editor_plugin.cpp editor/property_editor.cpp
-#: editor/script_editor_debugger.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/property_editor.cpp editor/script_editor_debugger.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Clear"
msgstr "Löschen"
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Error saving resource!"
msgstr "Fehler beim speichern der Ressource!"
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Save Resource As.."
msgstr "Speichere Ressource als.."
-#: editor/editor_node.cpp editor/export_template_manager.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "I see.."
msgstr "Verstehe..."
@@ -1582,6 +1420,30 @@ msgid "Error while saving."
msgstr "Fehler beim speichern."
#: editor/editor_node.cpp
+#, fuzzy
+msgid "Can't open '%s'."
+msgstr "Kann mit ‚..‘ nicht arbeiten"
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Error while parsing '%s'."
+msgstr "Fehler beim speichern."
+
+#: editor/editor_node.cpp
+msgid "Unexpected end of file '%s'."
+msgstr ""
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Missing '%s' or its dependencies."
+msgstr "Szene '%s' hat defekte Abhängigkeiten:"
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Error while loading '%s'."
+msgstr "Fehler beim speichern."
+
+#: editor/editor_node.cpp
msgid "Saving Scene"
msgstr "Speichere Szene"
@@ -1594,9 +1456,8 @@ msgid "Creating Thumbnail"
msgstr "Erzeuge Miniaturansicht"
#: editor/editor_node.cpp
-#, fuzzy
msgid "This operation can't be done without a tree root."
-msgstr "Diese Aktion kann nicht ohne eine Szene ausgeführt werden."
+msgstr "Diese Aktion kann nicht ohne eine Wurzel ausgeführt werden."
#: editor/editor_node.cpp
msgid ""
@@ -1642,6 +1503,33 @@ msgid "Restored default layout to base settings."
msgstr "Layout wurde auf die Standardeinstellungen zurückgesetzt."
#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was imported, so it's not editable.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was instanced or inherited.\n"
+"Changes to it will not be kept when saving the current scene."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource was imported, so it's not editable. Change its settings in the "
+"import panel and then re-import."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This scene was imported, so changes to it will not be kept.\n"
+"Instancing it or inheriting will allow making changes to it.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Copy Params"
msgstr "Parameter kopieren"
@@ -1674,14 +1562,14 @@ msgid "There is no defined scene to run."
msgstr "Es ist keine zu startende Szene definiert."
#: editor/editor_node.cpp
-#, fuzzy
msgid ""
"No main scene has ever been defined, select one?\n"
"You can change it later in \"Project Settings\" under the 'application' "
"category."
msgstr ""
-"Es ist keine Hauptszene definiert worden.\n"
-"Wähle eine in den Projekteinstellungen unter der Kategorie „Anwendung“."
+"Es ist keine Hauptszene wurde jemals bestimmt, soll eine ausgewählt werden?\n"
+"Dies kann später in den Projekteinstellungen unter der Kategorie ‚Anwendung‘ "
+"geändert werden."
#: editor/editor_node.cpp
msgid ""
@@ -1730,13 +1618,12 @@ msgid "Quick Open Script.."
msgstr "Schnell Skripte öffnen.."
#: editor/editor_node.cpp
-#, fuzzy
msgid "Save & Close"
-msgstr "Datei speichern"
+msgstr "Speichern und schließen"
#: editor/editor_node.cpp
msgid "Save changes to '%s' before closing?"
-msgstr ""
+msgstr "Änderungen in ‚%s‘ vor dem Schließen speichern?"
#: editor/editor_node.cpp
msgid "Save Scene As.."
@@ -1767,9 +1654,8 @@ msgid "Export Tile Set"
msgstr "Tileset exportieren"
#: editor/editor_node.cpp
-#, fuzzy
msgid "This operation can't be done without a selected node."
-msgstr "Diese Aktion kann nicht ohne eine Szene ausgeführt werden."
+msgstr "Diese Aktion kann nicht ohne ein ausgewähltes Node ausgeführt werden."
#: editor/editor_node.cpp
msgid "Current scene not saved. Open anyway?"
@@ -1802,42 +1688,59 @@ msgid "Exit the editor?"
msgstr "Editor verlassen?"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Open Project Manager?"
-msgstr "Projektverwaltung"
+msgstr "Projektverwaltung öffnen?"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Save & Quit"
-msgstr "Datei speichern"
+msgstr "Speichern und beenden"
#: editor/editor_node.cpp
msgid "Save changes to the following scene(s) before quitting?"
-msgstr ""
+msgstr "Änderungen in den folgenden Szenen vor dem Schließen speichern?"
#: editor/editor_node.cpp
msgid "Save changes the following scene(s) before opening Project Manager?"
msgstr ""
+"Änderungen in den folgenden Szenen vor dem Öffnen der Projektverwaltung "
+"speichern?"
+
+#: editor/editor_node.cpp
+msgid ""
+"This option is deprecated. Situations where refresh must be forced are now "
+"considered a bug. Please report."
+msgstr ""
#: editor/editor_node.cpp
msgid "Pick a Main Scene"
msgstr "Wähle eine Hauptszene"
#: editor/editor_node.cpp
-msgid "Unable to enable addon plugin at: '"
-msgstr ""
+#, fuzzy
+msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
+msgstr "Plugin bei ‚"
#: editor/editor_node.cpp
-msgid "' parsing of config failed."
+#, fuzzy
+msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
msgstr ""
+"Skript-Feld für Addon-Plugin in ‚res://addons/‘ konnte nicht gefunden werden."
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/"
-msgstr ""
+#, fuzzy
+msgid "Unable to load addon script from path: '%s'."
+msgstr "AddOn-Skript konnte nicht geladen werden: '"
#: editor/editor_node.cpp
-msgid "Unable to load addon script from path: '"
-msgstr ""
+#, fuzzy
+msgid ""
+"Unable to load addon script from path: '%s' Base type is not EditorPlugin."
+msgstr "AddOn-Skript konnte nicht geladen werden: '"
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Unable to load addon script from path: '%s' Script is not in tool mode."
+msgstr "AddOn-Skript konnte nicht geladen werden: '"
#: editor/editor_node.cpp
msgid ""
@@ -1850,7 +1753,7 @@ msgstr ""
"werden."
#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/scene_tree_dock.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Ugh"
msgstr "Ähm"
@@ -1864,14 +1767,15 @@ msgstr ""
"die Szene innerhalb des Projektpfades gespeichert werden."
#: editor/editor_node.cpp
-msgid "Error loading scene."
-msgstr "Fehler beim laden der Szene."
-
-#: editor/editor_node.cpp
msgid "Scene '%s' has broken dependencies:"
msgstr "Szene '%s' hat defekte Abhängigkeiten:"
#: editor/editor_node.cpp
+#, fuzzy
+msgid "Clear Recent Scenes"
+msgstr "Letzte Dateien leeren"
+
+#: editor/editor_node.cpp
msgid "Save Layout"
msgstr "Layout speichern"
@@ -1901,11 +1805,10 @@ msgid "Distraction Free Mode"
msgstr "Ablenkungsfreier Modus"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Toggle distraction-free mode."
-msgstr "Ablenkungsfreier Modus"
+msgstr "Ablenkungsfreien Modus umschalten."
-#: editor/editor_node.cpp editor/io_plugins/editor_scene_import_plugin.cpp
+#: editor/editor_node.cpp
msgid "Scene"
msgstr "Szene"
@@ -2145,6 +2048,10 @@ msgstr "Fragen&Antworten"
msgid "Issue Tracker"
msgstr "Problem-Melder"
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+msgid "Community"
+msgstr "Gemeinschaft"
+
#: editor/editor_node.cpp
msgid "About"
msgstr "Ãœber"
@@ -2153,7 +2060,7 @@ msgstr "Ãœber"
msgid "Play the project."
msgstr "Projekt abspielen."
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Play"
msgstr "Starten"
@@ -2169,7 +2076,7 @@ msgstr "Szene pausieren"
msgid "Stop the scene."
msgstr "Szene stoppen."
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Stop"
msgstr "Stop"
@@ -2242,6 +2149,16 @@ msgid "Object properties."
msgstr "Objekteigenschaften."
#: editor/editor_node.cpp
+#, fuzzy
+msgid "Changes may be lost!"
+msgstr "Ändere Bildergruppe"
+
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Import"
+msgstr "Import"
+
+#: editor/editor_node.cpp
msgid "FileSystem"
msgstr "Dateisystem"
@@ -2255,15 +2172,7 @@ msgstr "Ausgabe"
#: editor/editor_node.cpp
msgid "Don't Save"
-msgstr ""
-
-#: editor/editor_node.cpp editor/editor_reimport_dialog.cpp
-msgid "Re-Import"
-msgstr "Neuimport"
-
-#: editor/editor_node.cpp editor/editor_plugin_settings.cpp
-msgid "Update"
-msgstr "Update"
+msgstr "Nicht speichern"
#: editor/editor_node.cpp
msgid "Import Templates From ZIP File"
@@ -2290,9 +2199,8 @@ msgid "Open & Run a Script"
msgstr "Skript öffnen und ausführen"
#: editor/editor_node.cpp
-#, fuzzy
msgid "New Inherited"
-msgstr "Neue gererbte Szene.."
+msgstr "Neue geerbte Szene.."
#: editor/editor_node.cpp
msgid "Load Errors"
@@ -2326,11 +2234,29 @@ msgstr "Nächsten Editor öffnen"
msgid "Open the previous Editor"
msgstr "Vorigen Editor öffnen"
+#: editor/editor_plugin.cpp
+#, fuzzy
+msgid "Creating Mesh Previews"
+msgstr "Erzeuge MeshLibrary"
+
+#: editor/editor_plugin.cpp
+msgid "Thumbnail.."
+msgstr "Vorschau.."
+
#: editor/editor_plugin_settings.cpp
msgid "Installed Plugins:"
msgstr "Installierte Erweiterungen:"
#: editor/editor_plugin_settings.cpp
+msgid "Update"
+msgstr "Update"
+
+#: editor/editor_plugin_settings.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Version:"
+msgstr "Version:"
+
+#: editor/editor_plugin_settings.cpp
msgid "Author:"
msgstr "Autor:"
@@ -2363,7 +2289,8 @@ msgid "Frame %"
msgstr "Bild %"
#: editor/editor_profiler.cpp
-msgid "Fixed Frame %"
+#, fuzzy
+msgid "Physics Frame %"
msgstr "Fixiertes Bild %"
#: editor/editor_profiler.cpp editor/script_editor_debugger.cpp
@@ -2382,35 +2309,17 @@ msgstr "Selbst"
msgid "Frame #:"
msgstr "Bild #:"
-#: editor/editor_reimport_dialog.cpp
-msgid "Please wait for scan to complete."
-msgstr "Bitte warten bis Operation abgeschlossen ist."
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Current scene must be saved to re-import."
-msgstr "Aktuelle Szene muss gespeichert sein um sie erneut zu importieren."
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Save & Re-Import"
-msgstr "Speichern & neu importieren"
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Importing"
-msgstr "Importiere erneut"
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Import Changed Resources"
-msgstr "Veränderte Ressourcen neu importieren"
-
#: editor/editor_run_native.cpp
msgid "Select device from the list"
-msgstr ""
+msgstr "Gerät aus Liste auswählen"
#: editor/editor_run_native.cpp
msgid ""
"No runnable export preset found for this platform.\n"
"Please add a runnable preset in the export menu."
msgstr ""
+"Keine ausführbare Exportvorlage für diese Plattform gefunden.\n"
+"Im Exportmenü kann eine ausführbare Vorlage hinzugefügt werden."
#: editor/editor_run_script.cpp
msgid "Write your logic in the _run() method."
@@ -2513,10 +2422,6 @@ msgid "Importing:"
msgstr "Importiere:"
#: editor/export_template_manager.cpp
-msgid "Loading Export Templates"
-msgstr "Lade Exportvorlagen"
-
-#: editor/export_template_manager.cpp
msgid "Current Version:"
msgstr "Aktuelle Version:"
@@ -2551,60 +2456,79 @@ msgid "Cannot navigate to '"
msgstr "Kann Ordner ‚"
#: editor/filesystem_dock.cpp
-#, fuzzy
+msgid "View items as a grid of thumbnails"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "View items as a list"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
msgid ""
"\n"
-"Status: Needs Re-Import"
-msgstr "Speichern & neu importieren"
+"Status: Import of file failed. Please fix file and reimport manually."
+msgstr ""
#: editor/filesystem_dock.cpp
-#, fuzzy
msgid ""
"\n"
"Source: "
-msgstr "Quelle:"
+msgstr ""
+"\n"
+"Quelle: "
#: editor/filesystem_dock.cpp
-msgid "Same source and destination files, doing nothing."
-msgstr "Quell- und Zieldatei sind gleich, ignoriere Anweisung."
+#, fuzzy
+msgid "Cannot move/rename resources root."
+msgstr "Quellschriftart kann nicht geladen/verarbeitet werden."
#: editor/filesystem_dock.cpp
-msgid "Target file exists, can't overwrite. Delete first."
-msgstr ""
+#, fuzzy
+msgid "Cannot move a folder into itself.\n"
+msgstr "Datei kann nicht in sich selbst importiert werden:"
+
+#: editor/filesystem_dock.cpp
+#, fuzzy
+msgid "Error moving:\n"
+msgstr "Fehler beim Verzeichnisverschieben:\n"
#: editor/filesystem_dock.cpp
-msgid "Same source and destination paths, doing nothing."
-msgstr "Quell- und Zielpfad sind gleich, ignoriere Anweisung."
+#, fuzzy
+msgid "Unable to update dependencies:\n"
+msgstr "Szene '%s' hat defekte Abhängigkeiten:"
#: editor/filesystem_dock.cpp
-msgid "Can't move directories to within themselves."
-msgstr "Verzeichnisse lassen sich nicht in sich selbst verschieben."
+msgid "No name provided"
+msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Can't rename deps for:\n"
+msgid "Provided name contains invalid characters"
msgstr ""
#: editor/filesystem_dock.cpp
#, fuzzy
-msgid "Error moving file:\n"
-msgstr "Fehler beim Laden des Bilds:"
+msgid "No name provided."
+msgstr "Umbenennen oder Verschieben.."
#: editor/filesystem_dock.cpp
#, fuzzy
-msgid "Error moving dir:\n"
-msgstr "Fehler beim importieren:"
+msgid "Name contains invalid characters."
+msgstr "Gültige Zeichen:"
#: editor/filesystem_dock.cpp
-msgid "Can't operate on '..'"
-msgstr "Kann mit ‚..‘ nicht arbeiten"
+#, fuzzy
+msgid "A file or folder with this name already exists."
+msgstr "Gruppenname existiert bereits!"
#: editor/filesystem_dock.cpp
-msgid "Pick New Name and Location For:"
-msgstr "Wähle neuen Namen und Ort für:"
+#, fuzzy
+msgid "Renaming file:"
+msgstr "Variable umbenennen"
#: editor/filesystem_dock.cpp
-msgid "No files selected!"
-msgstr "Keine Dateien ausgewählt!"
+#, fuzzy
+msgid "Renaming folder:"
+msgstr "Node umbenennen"
#: editor/filesystem_dock.cpp
msgid "Expand all"
@@ -2615,40 +2539,38 @@ msgid "Collapse all"
msgstr "Alle einklappen"
#: editor/filesystem_dock.cpp
-msgid "Show In File Manager"
-msgstr "Zeige im Dateimanager"
-
-#: editor/filesystem_dock.cpp
-msgid "Instance"
-msgstr "Instanz"
+msgid "Copy Path"
+msgstr "Pfad kopieren"
#: editor/filesystem_dock.cpp
-msgid "Edit Dependencies.."
-msgstr "Abhängigkeiten bearbeiten.."
+#, fuzzy
+msgid "Rename.."
+msgstr "Umbenennen"
#: editor/filesystem_dock.cpp
-msgid "View Owners.."
-msgstr "Zeige Besitzer.."
+msgid "Move To.."
+msgstr "Verschiebe zu.."
#: editor/filesystem_dock.cpp
-msgid "Copy Path"
-msgstr "Pfad kopieren"
+#, fuzzy
+msgid "New Folder.."
+msgstr "Ordner erstellen"
#: editor/filesystem_dock.cpp
-msgid "Rename or Move.."
-msgstr "Umbenennen oder Verschieben.."
+msgid "Show In File Manager"
+msgstr "Zeige im Dateimanager"
#: editor/filesystem_dock.cpp
-msgid "Move To.."
-msgstr "Verschiebe zu.."
+msgid "Instance"
+msgstr "Instanz"
#: editor/filesystem_dock.cpp
-msgid "Info"
-msgstr "Info"
+msgid "Edit Dependencies.."
+msgstr "Abhängigkeiten bearbeiten.."
#: editor/filesystem_dock.cpp
-msgid "Re-Import.."
-msgstr "Neuimport.."
+msgid "View Owners.."
+msgstr "Zeige Besitzer.."
#: editor/filesystem_dock.cpp
msgid "Previous Directory"
@@ -2675,11 +2597,18 @@ msgid ""
"Scanning Files,\n"
"Please Wait.."
msgstr ""
+"Lese Dateien,\n"
+"Bitte warten.."
#: editor/filesystem_dock.cpp
msgid "Move"
msgstr "Verschieben"
+#: editor/filesystem_dock.cpp editor/plugins/animation_tree_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Rename"
+msgstr "Umbenennen"
+
#: editor/groups_editor.cpp
msgid "Add to Group"
msgstr "Zu Gruppe hinzufügen"
@@ -2689,74 +2618,85 @@ msgid "Remove from Group"
msgstr "Aus Gruppe entfernen"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Import as Single Scene"
-msgstr "Szene wird importiert.."
+msgstr "Als einzelne Szene importieren"
+
+#: editor/import/resource_importer_scene.cpp
+#, fuzzy
+msgid "Import with Separate Animations"
+msgstr "Import mit separaten Materialien"
#: editor/import/resource_importer_scene.cpp
msgid "Import with Separate Materials"
-msgstr ""
+msgstr "Import mit separaten Materialien"
#: editor/import/resource_importer_scene.cpp
msgid "Import with Separate Objects"
-msgstr ""
+msgstr "Import mit separaten Objekten"
#: editor/import/resource_importer_scene.cpp
msgid "Import with Separate Objects+Materials"
-msgstr ""
+msgstr "Import mit separaten Objekten und Materialien"
+
+#: editor/import/resource_importer_scene.cpp
+#, fuzzy
+msgid "Import with Separate Objects+Animations"
+msgstr "Import mit separaten Objekten und Materialien"
+
+#: editor/import/resource_importer_scene.cpp
+#, fuzzy
+msgid "Import with Separate Materials+Animations"
+msgstr "Import mit separaten Materialien"
#: editor/import/resource_importer_scene.cpp
#, fuzzy
+msgid "Import with Separate Objects+Materials+Animations"
+msgstr "Import mit separaten Objekten und Materialien"
+
+#: editor/import/resource_importer_scene.cpp
msgid "Import as Multiple Scenes"
-msgstr "3D-Szene importieren"
+msgstr "Als mehrere Szenen importieren"
#: editor/import/resource_importer_scene.cpp
msgid "Import as Multiple Scenes+Materials"
-msgstr ""
+msgstr "Import als mehrere Szenen und Materialien"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Import Scene"
msgstr "Szene importieren"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Importing Scene.."
msgstr "Szene wird importiert.."
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Running Custom Script.."
msgstr "Angepasstes Skript wird ausgeführt.."
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Couldn't load post-import script:"
msgstr "Post-Import Skript konnte nicht geladen werden:"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Invalid/broken script for post-import (check console):"
msgstr "Ungültiges oder fehlerhaftes Skript für Post-Import (siehe Konsole):"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Error running post-import script:"
msgstr "Fehler beim ausführen des Post-Import Skripts:"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Saving.."
msgstr "Speichere.."
#: editor/import_dock.cpp
msgid "Set as Default for '%s'"
-msgstr ""
+msgstr "Standard für ‚%s‘ setzen"
#: editor/import_dock.cpp
msgid "Clear Default for '%s'"
-msgstr ""
+msgstr "Standard für ‚%s‘ löschen"
#: editor/import_dock.cpp
msgid " Files"
@@ -2774,576 +2714,6 @@ msgstr "Voreinstellungen.."
msgid "Reimport"
msgstr "Neuimport"
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "No bit masks to import!"
-msgstr "Keine Bitmasken zu importieren!"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path is empty."
-msgstr "Zielpfad ist leer."
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must be a complete resource path."
-msgstr "Zielpfad muss ein kompletter Ressourcenpfad sein."
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must exist."
-msgstr "Zielpfad muss existieren."
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Save path is empty!"
-msgstr "Speicherpfad ist leer!"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Import BitMasks"
-msgstr "BitMasks importieren"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s):"
-msgstr "Quelltextur(en):"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Target Path:"
-msgstr "Zielpfad:"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Accept"
-msgstr "Akzeptieren"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Bit Mask"
-msgstr "Bitmaske"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No source font file!"
-msgstr "Keine Quellschriftart-Datei gefunden!"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No target font resource!"
-msgstr "Keine Zielschriftart-Ressource!"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"Invalid file extension.\n"
-"Please use .font."
-msgstr ""
-"Ungültige Dateiendung.\n"
-"Nutze .font als Dateiendung."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Can't load/process source font."
-msgstr "Quellschriftart kann nicht geladen/verarbeitet werden."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Couldn't save font."
-msgstr "Schriftart konnte nicht gespeichert werden."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font:"
-msgstr "Quellschriftart:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font Size:"
-msgstr "Quellschriftgröße:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Dest Resource:"
-msgstr "Ziel-Ressource:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "The quick brown fox jumps over the lazy dog."
-msgstr "Franz jagt im komplett verwahrlosten Taxi quer durch Bayern."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Test:"
-msgstr "Test:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Options:"
-msgstr "Optionen:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Font Import"
-msgstr "Schriftart importieren"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"This file is already a Godot font file, please supply a BMFont type file "
-"instead."
-msgstr ""
-"Diese Datei ist bereits eine Godot Schriftart. Bitte stattdessen eine Datei "
-"im BMFont-Format angeben."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Failed opening as BMFont file."
-msgstr "Öffnen der BMFont-Datei fehlgeschlagen."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error initializing FreeType."
-msgstr "Fehler beim initialisieren von FreeType."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Unknown font format."
-msgstr "Unbekanntes Schriftformat."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error loading font."
-msgstr "Fehler beim Laden der Schriftart."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Invalid font size."
-msgstr "Ungültige Schriftgröße."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Invalid font custom source."
-msgstr "Eigene Schriftart-Quelle ist ungültig."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/plugins/theme_editor_plugin.cpp
-msgid "Font"
-msgstr "Schriftart"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "No meshes to import!"
-msgstr "Keine Meshes zu importieren!"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Single Mesh Import"
-msgstr "Einzelnes Mesh importieren"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Source Mesh(es):"
-msgstr "Quell Mesh(es):"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/plugins/mesh_instance_editor_plugin.cpp
-msgid "Mesh"
-msgstr "Mesh"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Surface %d"
-msgstr "Oberfläche %d"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "No samples to import!"
-msgstr "Keine Samples zu importieren!"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Import Audio Samples"
-msgstr "Audio-Samples importieren"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Source Sample(s):"
-msgstr "Quell Sample(s):"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Audio Sample"
-msgstr "Audio-Sample"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "New Clip"
-msgstr "Neuer Clip"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Animation Options"
-msgstr "Animationseinstellungen"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Flags"
-msgstr "Flags"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Bake FPS:"
-msgstr "FPS fixieren:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Optimizer"
-msgstr "Optimierung"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Linear Error"
-msgstr "Obere lineare Fehlergrenze"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angular Error"
-msgstr "Obere Winkelfehlergrenze"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angle"
-msgstr "Maximaler Winkel"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Clips"
-msgstr "Ausschnitte"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Start(s)"
-msgstr "Start"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "End(s)"
-msgstr "Ende"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Loop"
-msgstr "Wiederholung"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Filters"
-msgstr "Filter"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source path is empty."
-msgstr "Quellpfad ist leer."
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't load post-import script."
-msgstr "Post-Import Skript konnte nicht geladen werden."
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Invalid/broken script for post-import."
-msgstr "Ungültiges / Fehlerhaftes Skript für Post-Import."
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Error importing scene."
-msgstr "Fehler beim importieren der Szene."
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import 3D Scene"
-msgstr "3D-Szene importieren"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source Scene:"
-msgstr "Quellszene:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Same as Target Scene"
-msgstr "Dieselbe wie die Zielszene"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Shared"
-msgstr "Geteilt"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Target Texture Folder:"
-msgstr "Ziel-Texturenordner:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Post-Process Script:"
-msgstr "Post-Process Skript:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Custom Root Node Type:"
-msgstr "Angepasster Root-Node-Typ:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Auto"
-msgstr "Auto"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Root Node Name:"
-msgstr "Name des Root-Node:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "The Following Files are Missing:"
-msgstr "Die folgenden Dateien fehlen:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Anyway"
-msgstr "Trotzdem importieren"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp scene/gui/dialogs.cpp
-msgid "Cancel"
-msgstr "Abbrechen"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import & Open"
-msgstr "Importieren & Öffnen"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Edited scene has not been saved, open imported scene anyway?"
-msgstr ""
-"Bearbeitete Szene wurde nicht gespeichert, trotzdem importierte Szene öffnen?"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Image:"
-msgstr "Bild importieren:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Can't import a file over itself:"
-msgstr "Datei kann nicht in sich selbst importiert werden:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't localize path: %s (already local)"
-msgstr "Pfad konnte nicht gefunden werden: %s (bereits lokal)"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "3D Scene Animation"
-msgstr "3D-Szenenanimation"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Uncompressed"
-msgstr "Unkomprimiert"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossless (PNG)"
-msgstr "Verlustfrei komprimieren (PNG)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossy (WebP)"
-msgstr "Verlustbehaftet komprimieren (WebP)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress (VRAM)"
-msgstr "Komprimieren (VRAM)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Format"
-msgstr "Texturformat"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Compression Quality (WebP):"
-msgstr "Texturkompressionsqualität (WebP):"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Options"
-msgstr "Textureinstellungen"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Please specify some files!"
-msgstr "Bitte gib einige Dateien an!"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "At least one file needed for Atlas."
-msgstr "Es wird zumindest eine Datei für den Atlas benötigt."
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Error importing:"
-msgstr "Fehler beim importieren:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Only one file is required for large texture."
-msgstr "Es ist nur eine Datei für eine große Textur erforderlich."
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Max Texture Size:"
-msgstr "Maximale Texturgröße:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for Atlas (2D)"
-msgstr "Texturen für Atlas (2D) importieren"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cell Size:"
-msgstr "Zellgröße:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Large Texture"
-msgstr "Große Textur"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Textures (2D)"
-msgstr "Große Texturen (2D) importieren"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture"
-msgstr "Quelltextur"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Base Atlas Texture"
-msgstr "Basis-Atlastextur"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s)"
-msgstr "Quelltextur(en)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 2D"
-msgstr "Texturen für 2D importieren"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 3D"
-msgstr "Texturen für 3D importieren"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures"
-msgstr "Texturen importieren"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "2D Texture"
-msgstr "2D-Textur"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "3D Texture"
-msgstr "3D-Textur"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Atlas Texture"
-msgstr "Atlastextur"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid ""
-"NOTICE: Importing 2D textures is not mandatory. Just copy png/jpg files to "
-"the project."
-msgstr ""
-"MERKE: Das importieren von 2D Texturen ist nicht zwingend notwendig. Kopiere "
-"einfach png/jpg Dateien in das Projekt."
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Crop empty space."
-msgstr "Leere Bereiche beschneiden."
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture"
-msgstr "Textur"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Texture"
-msgstr "Große Textur importieren"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Load Source Image"
-msgstr "Quellbild laden"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Slicing"
-msgstr "Teile"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Inserting"
-msgstr "Füge Ein"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Saving"
-msgstr "Speichere"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save large texture:"
-msgstr "Große Textur konnte nicht gespeichert werden:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Build Atlas For:"
-msgstr "Erstelle Atlas für:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Loading Image:"
-msgstr "Lade Bild:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't load image:"
-msgstr "Bild konnte nicht geladen werden:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Converting Images"
-msgstr "Bilder werden konvertiert"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cropping Images"
-msgstr "Bilder werden beschnitten"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Blitting Images"
-msgstr "Blitting Bilder"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save atlas image:"
-msgstr "Atlas-Bild konnte nicht gespeichert werden:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save converted texture:"
-msgstr "Konvertierte Textur konnte nicht gespeichert werden:"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid source!"
-msgstr "Fehlerhafte Quelle!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid translation source!"
-msgstr "Fehlerhafte Ãœbersetzungsquelle!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Column"
-msgstr "Reihe"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/script_create_dialog.cpp
-msgid "Language"
-msgstr "Sprache"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No items to import!"
-msgstr "Keine Elemente zu importieren!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No target path!"
-msgstr "Kein Zielpfad!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translations"
-msgstr "Ãœbersetzungen importieren"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Couldn't import!"
-msgstr "Konnte nicht importiert werden!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translation"
-msgstr "Ãœbersetzung importieren"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Source CSV:"
-msgstr "Quell-CSV:"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Ignore First Row"
-msgstr "Erste Zeile ignorieren"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Compress"
-msgstr "Komprimieren"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Add to Project (project.godot)"
-msgstr "Zu Projekt hinzufügen (project.godot)"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Languages:"
-msgstr "Sprachen importieren:"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Translation"
-msgstr "Ãœbersetzung"
-
#: editor/multi_node_edit.cpp
msgid "MultiNode Set"
msgstr "MultiNode setzen"
@@ -3356,6 +2726,49 @@ msgstr "Gruppen"
msgid "Select a Node to edit Signals and Groups."
msgstr "Wähle ein Node um Signale und Gruppen zu bearbeiten."
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create Poly"
+msgstr "Polygon erstellen"
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly"
+msgstr "Polygon bearbeiten"
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#, fuzzy
+msgid "Insert Point"
+msgstr "Füge Ein"
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly (Remove Point)"
+msgstr "Polygon bearbeiten (Punkt entfernen)"
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Remove Poly And Point"
+msgstr "Polygon und Punkt entfernen"
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create a new polygon from scratch."
+msgstr "Polygon von Grund auf neu erstellen."
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid ""
+"Edit existing polygon:\n"
+"LMB: Move Point.\n"
+"Ctrl+LMB: Split Segment.\n"
+"RMB: Erase Point."
+msgstr ""
+"Existierendes Polygon editieren:\n"
+"LMT: Punkt verschieben.\n"
+"Strg+LMT: Segment aufteilen.\n"
+"RMT: Punkt löschen."
+
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Toggle Autoplay"
msgstr "Automatisches Abspielen umschalten"
@@ -3509,7 +2922,6 @@ msgstr "Animationsname:"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
#: editor/script_create_dialog.cpp
msgid "Error!"
@@ -3537,9 +2949,8 @@ msgid "New name:"
msgstr "Neuer Name:"
#: editor/plugins/animation_tree_editor_plugin.cpp
-#, fuzzy
msgid "Edit Filters"
-msgstr "Nodefilter bearbeiten"
+msgstr "Filter bearbeiten"
#: editor/plugins/animation_tree_editor_plugin.cpp
#: editor/plugins/multimesh_editor_plugin.cpp
@@ -3620,10 +3031,6 @@ msgid "Delete Input"
msgstr "Eingang löschen"
#: editor/plugins/animation_tree_editor_plugin.cpp
-msgid "Rename"
-msgstr "Umbenennen"
-
-#: editor/plugins/animation_tree_editor_plugin.cpp
msgid "Animation tree is valid."
msgstr "Animationsbaum ist gültig."
@@ -3679,64 +3086,181 @@ msgstr "Nodefilter bearbeiten"
msgid "Filters.."
msgstr "Filter.."
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing %d Triangles:"
-msgstr "Analysiere %d Dreiecke:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Free"
+msgstr "Frei"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Triangle #"
-msgstr "Dreieck #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Contents:"
+msgstr "Inhalt:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Light Baker Setup:"
-msgstr "Light-Baker einrichten:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "View Files"
+msgstr "Dateien anzeigen"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing Geometry"
-msgstr "Analysiere Geometrie"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve hostname:"
+msgstr "Kann Hostnamen nicht auflösen:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Fixing Lights"
-msgstr "Fixiere Lampen"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve."
+msgstr "Kann nicht auflösen."
-#: editor/plugins/baked_light_baker.cpp
-msgid "Making BVH"
-msgstr "Erstelle BVH"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connection error, please try again."
+msgstr "Verbindungsfehler, bitte erneut versuchen."
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Light Octree"
-msgstr "erstelle Licht-Octree"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't connect."
+msgstr "Kann nicht verbinden."
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Octree Texture"
-msgstr "Erstelle Octree-Textur"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't connect to host:"
+msgstr "Kann nicht zu Host verbinden:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Transfer to Lightmaps:"
-msgstr "übertrage zu Lightmaps:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response from host:"
+msgstr "Keine Antwort von Host:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Allocating Texture #"
-msgstr "Zuweisen von Textur #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response."
+msgstr "Keine Antwort."
-#: editor/plugins/baked_light_baker.cpp
-msgid "Baking Triangle #"
-msgstr "Baking von Dreieck #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, return code:"
+msgstr "Anfrage fehlgeschlagen: Rückgabewert:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Post-Processing Texture #"
-msgstr "Nachbearbeiten von Textur #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Req. Failed."
+msgstr "Anfrage fehlgeschlagen."
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Bake!"
-msgstr "Backen!"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, too many redirects"
+msgstr "Anfrage fehlgeschlagen, zu viele Weiterleitungen"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Redirect Loop."
+msgstr "Weiterleitungsschleife."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed:"
+msgstr "Fehlgeschlagen:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Bad download hash, assuming file has been tampered with."
+msgstr "Falsche Download-Prüfsumme, Datei könnte manipuliert worden sein."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Expected:"
+msgstr "Erwartet:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Got:"
+msgstr "Erhalten:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed sha256 hash check"
+msgstr "Sha256-Prüfung fehlgeschlagen"
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Reset the lightmap octree baking process (start over)."
-msgstr "Lightmap-Octree-Backing-Prozess zurücksetzen (neu starten)."
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Asset Download Error:"
+msgstr "Asset-Download-Fehler:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Fetching:"
+msgstr "Hole:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Resolving.."
+msgstr "Löse auf.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connecting.."
+msgstr "Verbinde.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Requesting.."
+msgstr "Frage an.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Error making request"
+msgstr "Fehler bei Anfrage"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Idle"
+msgstr "Leerlauf"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Retry"
+msgstr "Erneut versuchen"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download Error"
+msgstr "Ãœbertragungsfehler"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download for this asset is already in progress!"
+msgstr "Dieser Posten wird bereits herunter geladen!"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "first"
+msgstr "Anfang"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "prev"
+msgstr "zurück"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "next"
+msgstr "vor"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "last"
+msgstr "Ende"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "All"
+msgstr "Alle"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Plugins"
+msgstr "Erweiterungen"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Sort:"
+msgstr "Sortiere:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Reverse"
+msgstr "Umkehren"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Category:"
+msgstr "Kategorie:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Site:"
+msgstr "Seite:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Support.."
+msgstr "Unterstützung.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Official"
+msgstr "Offiziell"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Testing"
+msgstr "Testphase"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Assets ZIP File"
+msgstr "Projektdaten als ZIP-Datei"
#: editor/plugins/camera_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
msgid "Preview"
msgstr "Vorschau"
@@ -3779,12 +3303,18 @@ msgid "Edit CanvasItem"
msgstr "CanvasItem bearbeiten"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Change Anchors"
+#, fuzzy
+msgid "Anchors only"
+msgstr "Anker"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#, fuzzy
+msgid "Change Anchors and Margins"
msgstr "Ankerpunkte ändern"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom (%):"
-msgstr "Vergrößerung (%):"
+msgid "Change Anchors"
+msgstr "Ankerpunkte ändern"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Paste Pose"
@@ -3839,61 +3369,79 @@ msgid "Pan Mode"
msgstr "Schwenkmodus"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Lock the selected object in place (can't be moved)."
-msgstr ""
-"Das ausgewählte Objekt an seiner Position sperren (kann nicht bewegt werden)."
+#, fuzzy
+msgid "Toggles snapping"
+msgstr "Haltepunkt umschalten"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Unlock the selected object (can be moved)."
-msgstr "Das ausgewählte Objekt entsperren (kann bewegt werden)."
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Use Snap"
+msgstr "Einrasten aktivieren"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Makes sure the object's children are not selectable."
-msgstr "Verhindert das Auswählen von Unterobjekten dieses Nodes."
+#, fuzzy
+msgid "Snapping options"
+msgstr "Animationseinstellungen"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Restores the object's children's ability to be selected."
-msgstr "Macht Unterobjekte dieses Objekts wieder auswählbar."
+#, fuzzy
+msgid "Snap to grid"
+msgstr "Einrastmodus:"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Edit"
-msgstr "Bearbeiten"
+msgid "Use Rotation Snap"
+msgstr "Rotationsraster benutzen"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Use Snap"
-msgstr "Einrasten aktivieren"
+#, fuzzy
+msgid "Configure Snap..."
+msgstr "Einrasten konfigurieren.."
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Show Grid"
-msgstr "Raster anzeigen"
+msgid "Snap Relative"
+msgstr "Relatives Einrasten benutzen"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Rotation Snap"
-msgstr "Rotationsraster benutzen"
+msgid "Use Pixel Snap"
+msgstr "Pixelraster benutzen"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap Relative"
-msgstr "Relatives Einrasten benutzen"
+msgid "Smart snapping"
+msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Configure Snap.."
-msgstr "Einrasten konfigurieren.."
+#, fuzzy
+msgid "Snap to parent"
+msgstr "Auf übergeordnetes Node ausdehnen"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Pixel Snap"
-msgstr "Pixelraster benutzen"
+msgid "Snap to node anchor"
+msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Skeleton.."
-msgstr "Skelett.."
+msgid "Snap to node sides"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to other nodes"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Lock the selected object in place (can't be moved)."
+msgstr ""
+"Das ausgewählte Objekt an seiner Position sperren (kann nicht bewegt werden)."
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Unlock the selected object (can be moved)."
+msgstr "Das ausgewählte Objekt entsperren (kann bewegt werden)."
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Makes sure the object's children are not selectable."
+msgstr "Verhindert das Auswählen von Unterobjekten dieses Nodes."
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Restores the object's children's ability to be selected."
+msgstr "Macht Unterobjekte dieses Objekts wieder auswählbar."
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Make Bones"
@@ -3921,12 +3469,19 @@ msgid "View"
msgstr "Ansicht"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Reset"
-msgstr "Vergrößerung zurücksetzen"
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Show Grid"
+msgstr "Raster anzeigen"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#, fuzzy
+msgid "Show helpers"
+msgstr "Knochen anzeigen"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Set.."
-msgstr "Vergrößerung setzen.."
+#, fuzzy
+msgid "Show rulers"
+msgstr "Knochen anzeigen"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Center Selection"
@@ -3937,8 +3492,9 @@ msgid "Frame Selection"
msgstr "Auswahl einrahmen"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Anchor"
-msgstr "Anker"
+#, fuzzy
+msgid "Layout"
+msgstr "Layout speichern"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Insert Keys"
@@ -3961,12 +3517,21 @@ msgid "Clear Pose"
msgstr "Pose zurücksetzen"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Set a Value"
-msgstr "Einen Wert setzen"
+msgid "Drag pivot from mouse position"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#, fuzzy
+msgid "Set pivot at mouse position"
+msgstr "Position der Ausgangskurve setzen"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Multiply grid step by 2"
+msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap (Pixels):"
-msgstr "Einrasten (Pixel):"
+msgid "Divide grid step by 2"
+msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Add %s"
@@ -3976,23 +3541,28 @@ msgstr "%s hinzufügen"
msgid "Adding %s..."
msgstr "%s hinzufügen…"
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Create Node"
msgstr "Erzeuge Node"
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Error instancing scene from %s"
msgstr "Fehler beim Instanziieren von %s"
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "OK :("
msgstr "Verstehe"
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "No parent to instance a child at."
msgstr "Kein Node unter dem Unterobjekt instantiiert werden könnte vorhanden."
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "This operation requires a single selected node."
msgstr "Diese Aktion benötigt ein einzelnes ausgewähltes Node."
@@ -4008,45 +3578,6 @@ msgstr ""
"Ziehen + Umschalt: Node auf gleicher Ebene einfügen\n"
"Ziehen + Alt: Nodetyp ändern"
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Create Poly"
-msgstr "Polygon erstellen"
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly"
-msgstr "Polygon bearbeiten"
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly (Remove Point)"
-msgstr "Polygon bearbeiten (Punkt entfernen)"
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Create a new polygon from scratch."
-msgstr "Polygon von Grund auf neu erstellen."
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-msgid ""
-"Edit existing polygon:\n"
-"LMB: Move Point.\n"
-"Ctrl+LMB: Split Segment.\n"
-"RMB: Erase Point."
-msgstr ""
-
#: editor/plugins/collision_polygon_editor_plugin.cpp
msgid "Create Poly3D"
msgstr "Polygon3D erstellen"
@@ -4056,14 +3587,6 @@ msgid "Set Handle"
msgstr "Wähle Griff"
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Creating Mesh Library"
-msgstr "Erzeuge MeshLibrary"
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Thumbnail.."
-msgstr "Vorschau.."
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Remove item %d?"
msgstr "Element %d entfernen?"
@@ -4086,19 +3609,38 @@ msgid "Update from Scene"
msgstr "Aus Szene aktualisieren"
#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat0"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat1"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
#, fuzzy
-msgid "Modify Curve Point"
-msgstr "Kurve ändern"
+msgid "Ease in"
+msgstr "Einblenden"
#: editor/plugins/curve_editor_plugin.cpp
#, fuzzy
+msgid "Ease out"
+msgstr "Ausblenden"
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Smoothstep"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Modify Curve Point"
+msgstr "Kurvenpunkt ändern"
+
+#: editor/plugins/curve_editor_plugin.cpp
msgid "Modify Curve Tangent"
-msgstr "Verändere Curve-Map"
+msgstr "Kurventangente ändern"
#: editor/plugins/curve_editor_plugin.cpp
-#, fuzzy
msgid "Load Curve Preset"
-msgstr "Vorlage laden"
+msgstr "Kurvenvorlage laden"
#: editor/plugins/curve_editor_plugin.cpp
msgid "Add point"
@@ -4109,31 +3651,28 @@ msgid "Remove point"
msgstr "Punkt entfernen"
#: editor/plugins/curve_editor_plugin.cpp
-#, fuzzy
msgid "Left linear"
-msgstr "Linear"
+msgstr "Links linear"
#: editor/plugins/curve_editor_plugin.cpp
-#, fuzzy
msgid "Right linear"
-msgstr "Sicht von rechts"
+msgstr "Rechts linear"
#: editor/plugins/curve_editor_plugin.cpp
msgid "Load preset"
msgstr "Vorlage laden"
#: editor/plugins/curve_editor_plugin.cpp
-#, fuzzy
msgid "Remove Curve Point"
-msgstr "Pfadpunkt entfernen"
+msgstr "Kurvenpunkt entfernen"
#: editor/plugins/curve_editor_plugin.cpp
msgid "Toggle Curve Linear Tangent"
-msgstr ""
+msgstr "Lineare Kurventangente umschalten"
#: editor/plugins/curve_editor_plugin.cpp
msgid "Hold Shift to edit tangents individually"
-msgstr ""
+msgstr "Umsch halten um Tangenten einzeln zu bearbeiten"
#: editor/plugins/gradient_editor_plugin.cpp
msgid "Add/Remove Color Ramp Point"
@@ -4161,28 +3700,26 @@ msgid ""
"No OccluderPolygon2D resource on this node.\n"
"Create and assign one?"
msgstr ""
+"Keine OccluderPolygon2D-Ressource für dieses Node gefunden.\n"
+"Neues erstellen und zuweisen?"
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
msgid "Create Occluder Polygon"
msgstr "Occluder-Polygon erzeugen"
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Edit existing polygon:"
msgstr "Bestehendes Polygon bearbeiten:"
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "LMB: Move Point."
msgstr "LMT: Punkt verschieben."
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Ctrl+LMB: Split Segment."
msgstr "Strg+LMT: Segment aufteilen."
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "RMB: Erase Point."
msgstr "RMT: Punkt entfernen."
@@ -4283,6 +3820,10 @@ msgid "Create Outline"
msgstr "Umriss erzeugen"
#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Mesh"
+msgstr "Mesh"
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Create Trimesh Static Body"
msgstr "Statischen Trimesh-Körper erzeugen"
@@ -4411,14 +3952,83 @@ msgstr "Zufällige Skalieren:"
msgid "Populate"
msgstr "Füllen"
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake!"
+msgstr "Backen!"
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+#, fuzzy
+msgid "Bake the navigation mesh.\n"
+msgstr "Navigations-Mesh erzeugen"
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+#, fuzzy
+msgid "Clear the navigation mesh."
+msgstr "Navigations-Mesh erzeugen"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Setting up Configuration..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Calculating grid size..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Creating heightfield..."
+msgstr "erstelle Licht-Octree"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Marking walkable triangles..."
+msgstr "Ãœbersetzbare Textbausteine.."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Constructing compact heightfield..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Eroding walkable area..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Partitioning..."
+msgstr "Warnung"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Creating contours..."
+msgstr "Erstelle Octree-Textur"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Creating polymesh..."
+msgstr "Umriss-Mesh erzeugen.."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Converting to native navigation mesh..."
+msgstr "Navigations-Mesh erzeugen"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Navigation Mesh Generator Setup:"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Parsing Geometry..."
+msgstr "Analysiere Geometrie"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Done!"
+msgstr ""
+
#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Create Navigation Polygon"
msgstr "Erzeuge Navigationspolygon"
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Remove Poly And Point"
-msgstr "Polygon und Punkt entfernen"
-
#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Clear Emission Mask"
msgstr "Emissionsmaske leeren"
@@ -4456,9 +4066,8 @@ msgstr "Emissionsmaske laden"
#: editor/plugins/particles_2d_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp
-#, fuzzy
msgid "Particles"
-msgstr "Vertices"
+msgstr "Partikel"
#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Generated Point Count:"
@@ -4593,14 +4202,17 @@ msgid "Curve Point #"
msgstr "Kurvenpunkt #"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve Point Position"
msgstr "Position des Kurvenpunkts setzen"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve In Position"
msgstr "Position der Eingangskurve setzen"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve Out Position"
msgstr "Position der Ausgangskurve setzen"
@@ -4661,6 +4273,14 @@ msgid "Scale Polygon"
msgstr "Polygon skalieren"
#: editor/plugins/polygon_2d_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Edit"
+msgstr "Bearbeiten"
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Polygon->UV"
msgstr "Polygon→UV"
@@ -4715,63 +4335,10 @@ msgstr "Ressource laden"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/shader_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "Einfügen"
-#: editor/plugins/rich_text_editor_plugin.cpp
-msgid "Parse BBCode"
-msgstr "BBCode parsen"
-
-#: editor/plugins/sample_editor_plugin.cpp
-msgid "Length:"
-msgstr "Länge:"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Open Sample File(s)"
-msgstr "Audiodatei(en) öffnen"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "ERROR: Couldn't load sample!"
-msgstr "Fehler: Konnte Audio nicht laden!"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Add Sample"
-msgstr "Sample hinzufügen"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Rename Sample"
-msgstr "Sample umbenennen"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Delete Sample"
-msgstr "Sample löschen"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "16 Bits"
-msgstr "16 Bit"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "8 Bits"
-msgstr "8 Bit"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Stereo"
-msgstr "Stereo"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Mono"
-msgstr "Mono"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Format"
-msgstr "Format"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Pitch"
-msgstr "Tonhöhe"
-
#: editor/plugins/script_editor_plugin.cpp
msgid "Clear Recent Files"
msgstr "Letzte Dateien leeren"
@@ -4781,6 +4348,8 @@ msgid ""
"Close and save changes?\n"
"\""
msgstr ""
+"Schließen und Änderungen speichern?\n"
+"„"
#: editor/plugins/script_editor_plugin.cpp
msgid "Error while saving theme"
@@ -4808,7 +4377,7 @@ msgstr "Motiv speichern als.."
#: editor/plugins/script_editor_plugin.cpp
msgid " Class Reference"
-msgstr ""
+msgstr " Klassenreferenz"
#: editor/plugins/script_editor_plugin.cpp
msgid "Next script"
@@ -4862,10 +4431,13 @@ msgstr "Dokumentation schließen"
msgid "Close All"
msgstr "Alle schließen"
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+msgid "Run"
+msgstr "Ausführen"
+
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Toggle Scripts Panel"
-msgstr "Favoriten ein- und ausblenden"
+msgstr "Seitenleiste umschalten"
#: editor/plugins/script_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
@@ -4891,7 +4463,8 @@ msgstr "Hineinspringen"
msgid "Break"
msgstr "Unterbrechung"
-#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+#: editor/script_editor_debugger.cpp
msgid "Continue"
msgstr "Fortfahren"
@@ -4900,21 +4473,8 @@ msgid "Keep Debugger Open"
msgstr "Debugger offen halten"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Debug with external editor"
-msgstr "Nächsten Editor öffnen"
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Window"
-msgstr "Fenster"
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Left"
-msgstr "nach links"
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Right"
-msgstr "nach rechts"
+msgstr "Mit externem Editor debuggen"
#: editor/plugins/script_editor_plugin.cpp
msgid "Open Godot online documentation"
@@ -4973,7 +4533,7 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
msgid "Only resources from filesystem can be dropped."
-msgstr ""
+msgstr "Nur Ressourcen aus dem Dateisystem können hier fallen gelassen werden."
#: editor/plugins/script_text_editor.cpp
msgid "Pick Color"
@@ -5002,8 +4562,9 @@ msgid "Cut"
msgstr "Ausschneiden"
#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "Kopieren"
@@ -5022,9 +4583,8 @@ msgid "Move Down"
msgstr "Schiebe herunter"
#: editor/plugins/script_text_editor.cpp
-#, fuzzy
msgid "Delete Line"
-msgstr "Punk löschen"
+msgstr "Linie löschen"
#: editor/plugins/script_text_editor.cpp
msgid "Indent Left"
@@ -5267,10 +4827,6 @@ msgid "View Plane Transform."
msgstr "Zeige Flächentransformation."
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Scaling to %s%%."
-msgstr "Skaliere auf %s%%."
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rotating %s degrees."
msgstr "Rotiere %s Grad."
@@ -5287,10 +4843,6 @@ msgid "Top View."
msgstr "Sicht von oben."
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Top"
-msgstr "Oben"
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rear View."
msgstr "Sicht von hinten."
@@ -5391,9 +4943,8 @@ msgid "Audio Listener"
msgstr "Audiosenke"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Doppler Enable"
-msgstr "Aktivieren"
+msgstr "Dopplereffekt aktivieren"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Freelook Left"
@@ -5424,7 +4975,6 @@ msgid "Freelook Speed Modifier"
msgstr "Freisicht Geschwindigkeitsregler"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "preview"
msgstr "Vorschau"
@@ -5433,17 +4983,18 @@ msgid "XForm Dialog"
msgstr "Transformationsdialog"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Select Mode (Q)\n"
-msgstr "Auswahlmodus"
+msgstr "Auswahlmodus (Q)\n"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid ""
"Drag: Rotate\n"
"Alt+Drag: Move\n"
"Alt+RMB: Depth list selection"
-msgstr "Alt+Rechtsklick: Listenauswahl nach Tiefe"
+msgstr ""
+"Ziehen: Rotieren\n"
+"Alt+Ziehen: Verschieben\n"
+"Alt+RMT: Tiefenauswahl"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Move Mode (W)"
@@ -5522,6 +5073,10 @@ msgid "Transform"
msgstr "Transformation"
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Configure Snap.."
+msgstr "Einrasten konfigurieren.."
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Local Coords"
msgstr "Lokale Koordinaten"
@@ -5667,6 +5222,10 @@ msgid "Speed (FPS):"
msgstr "Geschwindigkeit (FPS):"
#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Loop"
+msgstr "Wiederholung"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Animation Frames"
msgstr "Animationsframes"
@@ -5679,21 +5238,22 @@ msgid "Insert Empty (After)"
msgstr "Empty einfügen (danach)"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Up"
-msgstr "Hoch"
+#, fuzzy
+msgid "Move (Before)"
+msgstr "Node(s) verschieben"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Down"
-msgstr "Herunter"
+#, fuzzy
+msgid "Move (After)"
+msgstr "nach links"
#: editor/plugins/style_box_editor_plugin.cpp
msgid "StyleBox Preview:"
msgstr "StyleBox-Vorschau:"
#: editor/plugins/texture_region_editor_plugin.cpp
-#, fuzzy
msgid "Set Region Rect"
-msgstr "Skalierungsbegrenzungseditor"
+msgstr "Bereichsrechteck setzen"
#: editor/plugins/texture_region_editor_plugin.cpp
msgid "Snap Mode:"
@@ -5753,18 +5313,20 @@ msgid "Remove Item"
msgstr "Entferne Element"
#: editor/plugins/theme_editor_plugin.cpp
-#, fuzzy
msgid "Remove All Items"
-msgstr "Entferne Klassen-Element"
+msgstr "Alle Elemente entfernen"
#: editor/plugins/theme_editor_plugin.cpp
-#, fuzzy
msgid "Remove All"
-msgstr "Entfernen"
+msgstr "Alles entfernen"
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Edit theme.."
+msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
-msgid "Theme"
-msgstr "Motiv"
+msgid "Theme editing menu."
+msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
msgid "Add Class Items"
@@ -5848,31 +5410,32 @@ msgid "Style"
msgstr "Stil"
#: editor/plugins/theme_editor_plugin.cpp
+msgid "Font"
+msgstr "Schriftart"
+
+#: editor/plugins/theme_editor_plugin.cpp
msgid "Color"
msgstr "Farbe"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Erase Selection"
-msgstr "Lösche Auswahl"
+msgstr "Auswahl löschen"
#: editor/plugins/tile_map_editor_plugin.cpp
msgid "Paint TileMap"
msgstr "Zeichne TileMap"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Line Draw"
-msgstr "Linear"
+msgstr "Linie zeichnen"
#: editor/plugins/tile_map_editor_plugin.cpp
msgid "Rectangle Paint"
-msgstr ""
+msgstr "Rechteck zeichnen"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Bucket Fill"
-msgstr "Eimer"
+msgstr "Fülleimer"
#: editor/plugins/tile_map_editor_plugin.cpp
msgid "Erase TileMap"
@@ -5899,8 +5462,9 @@ msgid "Mirror Y"
msgstr "Y-Koordinaten spiegeln"
#: editor/plugins/tile_map_editor_plugin.cpp
-msgid "Bucket"
-msgstr "Eimer"
+#, fuzzy
+msgid "Paint Tile"
+msgstr "Zeichne TileMap"
#: editor/plugins/tile_map_editor_plugin.cpp
msgid "Pick Tile"
@@ -5963,6 +5527,11 @@ msgid "Delete preset '%s'?"
msgstr "Vorlage ‚%s‘ löschen?"
#: editor/project_export.cpp
+#, fuzzy
+msgid "Export templates for this platform are missing/corrupted: "
+msgstr "Export-Templates für diese Systeme fehlen:"
+
+#: editor/project_export.cpp
msgid "Presets"
msgstr "Vorlagen"
@@ -6017,18 +5586,16 @@ msgid "Make Patch"
msgstr "Erstelle Patch"
#: editor/project_export.cpp
-#, fuzzy
msgid "Features"
-msgstr "Textur"
+msgstr "Funktionen"
#: editor/project_export.cpp
msgid "Custom (comma-separated):"
-msgstr ""
+msgstr "Benutzerdefiniert (komma-separiert):"
#: editor/project_export.cpp
-#, fuzzy
msgid "Feature List:"
-msgstr "Methodenliste:"
+msgstr "Funktionalitätsliste:"
#: editor/project_export.cpp
msgid "Export PCK/Zip"
@@ -6039,30 +5606,61 @@ msgid "Export templates for this platform are missing:"
msgstr "Export-Templates für diese Systeme fehlen:"
#: editor/project_export.cpp
+#, fuzzy
+msgid "Export templates for this platform are missing/corrupted:"
+msgstr "Export-Templates für diese Systeme fehlen:"
+
+#: editor/project_export.cpp
msgid "Export With Debug"
msgstr "Exportiere mit Debuginformationen"
#: editor/project_manager.cpp
-msgid "Invalid project path, the path must exist!"
-msgstr "Ungültiger Projektpfad, der Pfad muss existieren!"
+#, fuzzy
+msgid "The path does not exist."
+msgstr "Datei existiert nicht."
#: editor/project_manager.cpp
-msgid "Invalid project path, project.godot must not exist."
-msgstr "Ungültiger Projektpfad, project.godot darf nicht existieren."
+#, fuzzy
+msgid "Please choose a 'project.godot' file."
+msgstr "Bitte außerhalb des Projektordners exportieren!"
#: editor/project_manager.cpp
-msgid "Invalid project path, project.godot must exist."
-msgstr "Ungültiger Projektpfad, project.godot muss existieren."
+msgid ""
+"Your project will be created in a non empty folder (you might want to create "
+"a new folder)."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Please choose a folder that does not contain a 'project.godot' file."
+msgstr ""
#: editor/project_manager.cpp
msgid "Imported Project"
msgstr "Importiertes Projekt"
#: editor/project_manager.cpp
+msgid " "
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "It would be a good idea to name your project."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Invalid project path (changed anything?)."
msgstr "Ungültiger Projektpfad (etwas geändert?)."
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Couldn't get project.godot in project path."
+msgstr "Konnte project.godot im Projektpfad nicht erzeugen."
+
+#: editor/project_manager.cpp
+#, fuzzy
+msgid "Couldn't edit project.godot in project path."
+msgstr "Konnte project.godot im Projektpfad nicht erzeugen."
+
+#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
msgstr "Konnte project.godot im Projektpfad nicht erzeugen."
@@ -6071,38 +5669,49 @@ msgid "The following files failed extraction from package:"
msgstr "Die folgenden Dateien ließen sich nicht aus dem Paket extrahieren:"
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Rename Project"
+msgstr "Unbenanntes Projekt"
+
+#: editor/project_manager.cpp
+#, fuzzy
+msgid "Couldn't get project.godot in the project path."
+msgstr "Konnte project.godot im Projektpfad nicht erzeugen."
+
+#: editor/project_manager.cpp
+msgid "New Game Project"
+msgstr "Neues Spiel"
+
+#: editor/project_manager.cpp
msgid "Import Existing Project"
msgstr "Existierendes Projekt importieren"
#: editor/project_manager.cpp
-msgid "Project Path (Must Exist):"
-msgstr "Projektpfad (muss existieren):"
+msgid "Create New Project"
+msgstr "Erstelle neues Projekt"
+
+#: editor/project_manager.cpp
+msgid "Install Project:"
+msgstr "Installiere Projekt:"
#: editor/project_manager.cpp
msgid "Project Name:"
msgstr "Projektname:"
#: editor/project_manager.cpp
-msgid "Create New Project"
-msgstr "Erstelle neues Projekt"
+#, fuzzy
+msgid "Create folder"
+msgstr "Ordner erstellen"
#: editor/project_manager.cpp
msgid "Project Path:"
msgstr "Projektpfad:"
#: editor/project_manager.cpp
-msgid "Install Project:"
-msgstr "Installiere Projekt:"
-
-#: editor/project_manager.cpp
msgid "Browse"
msgstr "Durchstöbern"
#: editor/project_manager.cpp
-msgid "New Game Project"
-msgstr "Neues Spiel"
-
-#: editor/project_manager.cpp
msgid "That's a BINGO!"
msgstr "Aber klar :-) !"
@@ -6111,24 +5720,31 @@ msgid "Unnamed Project"
msgstr "Unbenanntes Projekt"
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Can't open project"
+msgstr "Projekt kann nicht ausgeführt werden"
+
+#: editor/project_manager.cpp
msgid "Are you sure to open more than one project?"
msgstr "Sollen wirklich mehrere Projekte geöffnet werden?"
#: editor/project_manager.cpp
-#, fuzzy
msgid ""
"Can't run project: no main scene defined.\n"
"Please edit the project and set the main scene in \"Project Settings\" under "
"the \"Application\" category."
msgstr ""
-"Es ist keine Hauptszene definiert worden.\n"
-"Wähle eine in den Projekteinstellungen unter der Kategorie „Anwendung“."
+"Projekt kann nicht ausgeführt werden: Keine Hauptszene festgelegt.\n"
+"In den Projekteinstellungen unter der Kategorie „Anwendung“ kann die "
+"Hauptszene festgelegt werden."
#: editor/project_manager.cpp
msgid ""
"Can't run project: Assets need to be imported.\n"
"Please edit the project to trigger the initial import."
msgstr ""
+"Projekt kann nicht ausgeführt werden: Assets müssen importiert werden.\n"
+"Das Projekt muss eingestellt werden einen ersten Import einzuleiten."
#: editor/project_manager.cpp
msgid "Are you sure to run more than one project?"
@@ -6142,6 +5758,12 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
+"Language changed.\n"
+"The UI will update next time the editor or project manager starts."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid ""
"You are about the scan %s folders for existing Godot projects. Do you "
"confirm?"
msgstr "Sollen wirklich %s Ordner nach Godot-Projekten durchsucht werden?"
@@ -6151,10 +5773,6 @@ msgid "Project List"
msgstr "Projektliste"
#: editor/project_manager.cpp
-msgid "Run"
-msgstr "Ausführen"
-
-#: editor/project_manager.cpp
msgid "Scan"
msgstr "Scannen"
@@ -6176,8 +5794,12 @@ msgstr "Verlassen"
#: editor/project_manager.cpp
#, fuzzy
+msgid "Restart Now"
+msgstr "Neu starten (s):"
+
+#: editor/project_manager.cpp
msgid "Can't run project"
-msgstr "Kann nicht verbinden."
+msgstr "Projekt kann nicht ausgeführt werden"
#: editor/project_settings_editor.cpp
msgid "Key "
@@ -6212,17 +5834,14 @@ msgid "Add Input Action Event"
msgstr "Eingabeaktionsereignis hinzufügen"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Meta+"
msgstr "Meta+"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Shift+"
msgstr "Umschalt+"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Alt+"
msgstr "Alt+"
@@ -6280,16 +5899,14 @@ msgid "Change"
msgstr "Ändern"
#: editor/project_settings_editor.cpp
-#, fuzzy
msgid "Joypad Axis Index:"
msgstr "Joystickachsen-Index:"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Axis"
msgstr "Achse"
#: editor/project_settings_editor.cpp
-#, fuzzy
msgid "Joypad Button Index:"
msgstr "Joysticktasten-Index:"
@@ -6305,57 +5922,64 @@ msgstr "Lösche Eingabeaktionsereignis"
msgid "Add Event"
msgstr "Ereignis hinzufügen"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Device"
msgstr "Gerät"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Button"
msgstr "Schaltfläche"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Left Button."
msgstr "Linke Taste."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Right Button."
msgstr "Rechte Taste."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Middle Button."
msgstr "Mittlere Taste."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Up."
msgstr "Mausrad hoch."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Down."
msgstr "Mausrad runter."
#: editor/project_settings_editor.cpp
-#, fuzzy
msgid "Add Global Property"
-msgstr "Getter-Eigenschaft hinzufügen"
+msgstr "Globale Eigenschaft hinzufügen"
#: editor/project_settings_editor.cpp
-msgid "Select an setting item first!"
-msgstr ""
+#, fuzzy
+msgid "Select a setting item first!"
+msgstr "Ein Einstellungspunkt muss zuerst ausgewählt werden!"
#: editor/project_settings_editor.cpp
-#, fuzzy
msgid "No property '"
-msgstr "Eigenschaft:"
+msgstr "Keine Eigenschaft ‚"
#: editor/project_settings_editor.cpp
-#, fuzzy
msgid "Setting '"
-msgstr "Einstellungen"
+msgstr "Einstellung ‚"
#: editor/project_settings_editor.cpp
-#, fuzzy
msgid "Delete Item"
-msgstr "Eingang löschen"
+msgstr "Eintrag löschen"
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Can't contain '/' or ':'"
+msgstr "Kann nicht zu Host verbinden:"
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Already existing"
+msgstr "Persistente an- und ausschalten"
#: editor/project_settings_editor.cpp
msgid "Error saving settings."
@@ -6367,7 +5991,7 @@ msgstr "Einstellungen gespeichert OK."
#: editor/project_settings_editor.cpp
msgid "Override for Feature"
-msgstr ""
+msgstr "Für Funktion überschreiben"
#: editor/project_settings_editor.cpp
msgid "Add Translation"
@@ -6398,6 +6022,15 @@ msgid "Remove Resource Remap Option"
msgstr "Ressourcen-Remap-Option entfernen"
#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Changed Locale Filter"
+msgstr "Überblendungszeit ändern"
+
+#: editor/project_settings_editor.cpp
+msgid "Changed Locale Filter Mode"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "Project Settings (project.godot)"
msgstr "Projekteinstellungen (project.godot)"
@@ -6411,7 +6044,7 @@ msgstr "Eigenschaft:"
#: editor/project_settings_editor.cpp
msgid "Override For.."
-msgstr ""
+msgstr "Überschreiben für.."
#: editor/project_settings_editor.cpp
msgid "Input Map"
@@ -6458,6 +6091,30 @@ msgid "Locale"
msgstr "Lokalisierung"
#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Locales Filter"
+msgstr "Bildfilter:"
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Show all locales"
+msgstr "Knochen anzeigen"
+
+#: editor/project_settings_editor.cpp
+msgid "Show only selected locales"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Filter mode:"
+msgstr "Nodes filtern"
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Locales:"
+msgstr "Lokalisierung"
+
+#: editor/project_settings_editor.cpp
msgid "AutoLoad"
msgstr "Autoload"
@@ -6498,26 +6155,34 @@ msgid "Assign"
msgstr "Zuweisen"
#: editor/property_editor.cpp
-#, fuzzy
msgid "Select Node"
-msgstr "Wähle ein Node"
+msgstr "Node auswählen"
#: editor/property_editor.cpp
msgid "New Script"
msgstr "Neues Skript"
#: editor/property_editor.cpp
+#, fuzzy
+msgid "Make Unique"
+msgstr "Knochen erstellen"
+
+#: editor/property_editor.cpp
msgid "Show in File System"
msgstr "Im Dateisystem anzeigen"
#: editor/property_editor.cpp
+#, fuzzy
+msgid "Convert To %s"
+msgstr "Umwandeln zu.."
+
+#: editor/property_editor.cpp
msgid "Error loading file: Not a resource!"
msgstr "Fehler beim Laden der Datei: Keine Ressource!"
#: editor/property_editor.cpp
-#, fuzzy
msgid "Selected node is not a Viewport!"
-msgstr "Selektiere Node(s) für den Import"
+msgstr "Ausgewähltes Node ist kein Viewport!"
#: editor/property_editor.cpp
msgid "Pick a Node"
@@ -6548,6 +6213,11 @@ msgid "Select Property"
msgstr "Eigenschaft auswählen"
#: editor/property_selector.cpp
+#, fuzzy
+msgid "Select Virtual Method"
+msgstr "Methode auswählen"
+
+#: editor/property_selector.cpp
msgid "Select Method"
msgstr "Methode auswählen"
@@ -6576,26 +6246,6 @@ msgstr "Behalte globale Transformation"
msgid "Reparent"
msgstr "Umhängen"
-#: editor/resources_dock.cpp
-msgid "Create New Resource"
-msgstr "Erstelle neue Ressource"
-
-#: editor/resources_dock.cpp
-msgid "Open Resource"
-msgstr "Ressource öffnen"
-
-#: editor/resources_dock.cpp
-msgid "Save Resource"
-msgstr "Ressource speichern"
-
-#: editor/resources_dock.cpp
-msgid "Resource Tools"
-msgstr "Ressourcenwerkzeuge"
-
-#: editor/resources_dock.cpp
-msgid "Make Local"
-msgstr "Lokal machen"
-
#: editor/run_settings_dialog.cpp
msgid "Run Mode:"
msgstr "Ausführungsmodus:"
@@ -6728,14 +6378,6 @@ msgid "Sub-Resources:"
msgstr "Unter-Ressourcen:"
#: editor/scene_tree_dock.cpp
-msgid "Edit Groups"
-msgstr "Gruppen bearbeiten"
-
-#: editor/scene_tree_dock.cpp
-msgid "Edit Connections"
-msgstr "Verbindungen bearbeiten"
-
-#: editor/scene_tree_dock.cpp
msgid "Clear Inheritance"
msgstr "Leere Vererbung"
@@ -6796,9 +6438,8 @@ msgstr ""
"kein Root-Node existiert."
#: editor/scene_tree_dock.cpp
-#, fuzzy
msgid "Filter nodes"
-msgstr "Filter"
+msgstr "Nodes filtern"
#: editor/scene_tree_dock.cpp
msgid "Attach a new or existing script for the selected node."
@@ -6903,9 +6544,8 @@ msgid "Select a Node"
msgstr "Wähle ein Node"
#: editor/script_create_dialog.cpp
-#, fuzzy
msgid "Error loading template '%s'"
-msgstr "Fehler beim Laden des Bilds:"
+msgstr "Fehler beim Laden der Vorlage ‚%s‘"
#: editor/script_create_dialog.cpp
msgid "Error - Could not create script in filesystem."
@@ -6932,6 +6572,15 @@ msgid "Invalid base path"
msgstr "Ungültiger Pfad"
#: editor/script_create_dialog.cpp
+msgid "Directory of the same name exists"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
+#, fuzzy
+msgid "File exists, will be reused"
+msgstr "Datei existiert bereits. Ãœberschreiben?"
+
+#: editor/script_create_dialog.cpp
msgid "Invalid extension"
msgstr "Ungültige Erweiterung"
@@ -6972,6 +6621,10 @@ msgid "Load existing script file"
msgstr "Lade bestehende Skriptdatei"
#: editor/script_create_dialog.cpp
+msgid "Language"
+msgstr "Sprache"
+
+#: editor/script_create_dialog.cpp
msgid "Inherits"
msgstr "Erbt"
@@ -7012,6 +6665,10 @@ msgid "Function:"
msgstr "Funktion:"
#: editor/script_editor_debugger.cpp
+msgid "Pick one or more items from the list to display the graph."
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
msgid "Errors"
msgstr "Fehler"
@@ -7092,6 +6749,10 @@ msgid "Type"
msgstr "Art"
#: editor/script_editor_debugger.cpp
+msgid "Format"
+msgstr "Format"
+
+#: editor/script_editor_debugger.cpp
msgid "Usage"
msgstr "Nutzung"
@@ -7125,7 +6786,7 @@ msgstr "Ändere Lichtradius"
#: editor/spatial_editor_gizmos.cpp
msgid "Change AudioStreamPlayer3D Emission Angle"
-msgstr ""
+msgstr "Emissionswinkel für AudioStreamPlayer3D ändern"
#: editor/spatial_editor_gizmos.cpp
msgid "Change Camera FOV"
@@ -7168,13 +6829,31 @@ msgstr "Ändere Partikel AABB"
msgid "Change Probe Extents"
msgstr "Sondenausmaße ändern"
+#: modules/gdnative/gd_native_library_editor.cpp
+#, fuzzy
+msgid "Library"
+msgstr "MeshLibrary.."
+
+#: modules/gdnative/gd_native_library_editor.cpp
+#, fuzzy
+msgid "Status"
+msgstr "Status:"
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Libraries: "
+msgstr ""
+
+#: modules/gdnative/register_types.cpp
+msgid "GDNative"
+msgstr ""
+
#: modules/gdscript/gd_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Invalid type argument to convert(), use TYPE_* constants."
msgstr ""
"Ungültiger Argument-Typ in convert()-Aufruf, TYPE_*-Konstanten benötigt."
-#: modules/gdscript/gd_functions.cpp
+#: modules/gdscript/gd_functions.cpp modules/mono/glue/glue_header.h
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Not enough bytes for decoding bytes, or invalid format."
msgstr ""
@@ -7216,26 +6895,19 @@ msgstr "Ungültiges Instanz-Verzeichnisformat (ungültige Unterklasse)"
#: modules/gdscript/gd_functions.cpp
msgid "Object can't provide a length."
-msgstr ""
+msgstr "Objekt kann keine Länge vorweisen."
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "GridMap Delete Selection"
-msgstr "Ausgewähltes löschen"
+msgstr "GridMap-Auswahl löschen"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "GridMap Duplicate Selection"
-msgstr "Auswahl duplizieren"
+msgstr "GridMap-Auswahl duplizieren"
#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "GridMap Paint"
-msgstr ""
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Snap View"
-msgstr "Sicht von oben"
+msgstr "Sicht einrasten"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Prev Level (%sDown Wheel)"
@@ -7246,103 +6918,87 @@ msgid "Next Level (%sUp Wheel)"
msgstr ""
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Clip Disabled"
-msgstr "Deaktiviert"
+msgstr "Einrasten deaktiviert"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Clip Above"
-msgstr ""
+msgstr "Oben einrasten"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Clip Below"
-msgstr ""
+msgstr "Unten einrasten"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Edit X Axis"
-msgstr ""
+msgstr "X-Achse editieren"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Edit Y Axis"
-msgstr ""
+msgstr "Y-Achse editieren"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Edit Z Axis"
-msgstr ""
+msgstr "Z-Achse editieren"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Cursor Rotate X"
-msgstr "Strg: Rotieren"
+msgstr "X-Rotation am Mauszeiger"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Cursor Rotate Y"
-msgstr "Strg: Rotieren"
+msgstr "Y-Rotation am Mauszeiger"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Cursor Rotate Z"
-msgstr "Strg: Rotieren"
+msgstr "Z-Rotation am Mauszeiger"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Cursor Back Rotate X"
-msgstr ""
+msgstr "Rückwärts X-Rotation am Mauszeiger"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Cursor Back Rotate Y"
-msgstr ""
+msgstr "Rückwärts Y-Rotation am Mauszeiger"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Cursor Back Rotate Z"
-msgstr ""
+msgstr "Rückwärts Z-Rotation am Mauszeiger"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Cursor Clear Rotation"
-msgstr ""
+msgstr "Rotation am Mauszeiger zurücksetzen"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Create Area"
-msgstr "Neu erstellen"
+msgstr "Bereich erzeugen"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Create Exterior Connector"
-msgstr "Erstelle neues Projekt"
+msgstr "Exterior-Connector erstellen"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Erase Area"
-msgstr "Lösche TileMap"
+msgstr "Bereich entfernen"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Selection -> Duplicate"
-msgstr "Nur Auswahl"
+msgstr "Auswahl → Duplizieren"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Selection -> Clear"
-msgstr "Nur Auswahl"
+msgstr "Auswahl → Löschen"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "GridMap Settings"
-msgstr "Einrasteinstellungen"
+msgstr "GridMap-Einstellungen"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Pick Distance:"
-msgstr "Instanz:"
+msgstr "Auswahlradius:"
-#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
-msgid "Tiles"
-msgstr " Dateien"
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "Areas"
+#: modules/mono/editor/mono_bottom_panel.cpp
+msgid "Builds"
msgstr ""
#: modules/visual_script/visual_script.cpp
@@ -7384,29 +7040,24 @@ msgid "Stack overflow with stack depth: "
msgstr "Stack-Overflow mit Stack-Tiefe: "
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Change Signal Arguments"
-msgstr "Signalparameter bearbeiten:"
+msgstr "Signalparameter ändern"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Change Argument Type"
-msgstr "Wertetyp des Arrays ändern"
+msgstr "Parametertyp ändern"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Change Argument name"
-msgstr "Ändere Eingabename"
+msgstr "Parametername ändern"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Set Variable Default Value"
-msgstr "Ändere Standardwert"
+msgstr "Variablenstandardwert setzen"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Set Variable Type"
-msgstr "Variable bearbeiten:"
+msgstr "Variablentyp festlegen"
#: modules/visual_script/visual_script_editor.cpp
msgid "Functions:"
@@ -7457,14 +7108,12 @@ msgid "Add Node"
msgstr "Node hinzufügen"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Remove VisualScript Nodes"
-msgstr "Ungültige Schlüsselbilder entfernen"
+msgstr "VisualScript-Nodes entfernen"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Duplicate VisualScript Nodes"
-msgstr "Dupliziere Graph-Node(s)"
+msgstr "VisualScript-Nodes duplizieren"
#: modules/visual_script/visual_script_editor.cpp
msgid "Hold Meta to drop a Getter. Hold Shift to drop a generic signature."
@@ -7511,24 +7160,20 @@ msgid "Add Setter Property"
msgstr "Setter-Eigenschaft hinzufügen"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Change Base Type"
-msgstr "Typ ändern"
+msgstr "Basistyp ändern"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Move Node(s)"
-msgstr "Entferne Node(s)"
+msgstr "Node(s) verschieben"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Remove VisualScript Node"
-msgstr "Entferne Shader-Graph-Node"
+msgstr "VisualScript-Node entfernen"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Connect Nodes"
-msgstr "Verbinde mit Node:"
+msgstr "Nodes verbinden"
#: modules/visual_script/visual_script_editor.cpp
msgid "Condition"
@@ -7555,46 +7200,48 @@ msgid "Return"
msgstr "Rückgabe"
#: modules/visual_script/visual_script_editor.cpp
+msgid "Call"
+msgstr "Aufruf"
+
+#: modules/visual_script/visual_script_editor.cpp
msgid "Get"
msgstr "Abfragen"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
+msgid "Script already has function '%s'"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
msgid "Change Input Value"
-msgstr "Ändere Eingabename"
+msgstr "Eingabewert ändern"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Can't copy the function node."
-msgstr "Kann mit ‚..‘ nicht arbeiten"
+msgstr "Das Function-Node kann nicht kopiert werden."
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Clipboard is empty!"
-msgstr "Zwischenablage für Ressourcen ist leer!"
+msgstr "Zwischenablage ist leer!"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Paste VisualScript Nodes"
-msgstr "Nodes einfügen"
+msgstr "VisualScript-Nodes einfügen"
#: modules/visual_script/visual_script_editor.cpp
msgid "Remove Function"
msgstr "Funktion entfernen"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Edit Variable"
-msgstr "Variable bearbeiten:"
+msgstr "Variable bearbeiten"
#: modules/visual_script/visual_script_editor.cpp
msgid "Remove Variable"
msgstr "Variable entfernen"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Edit Signal"
-msgstr "bearbeite Signal:"
+msgstr "Signal bearbeiten"
#: modules/visual_script/visual_script_editor.cpp
msgid "Remove Signal"
@@ -7843,6 +7490,10 @@ msgid ""
"by the physics engine when running.\n"
"Change the size in children collision shapes instead."
msgstr ""
+"Größenänderungen von RigidBody2D (in den Character- oder Rigid-Modi) werden "
+"überschrieben wenn die Physikengine läuft.\n"
+"Die Größe der entsprechenden Collisionshape-Unterobjekte sollte stattdessen "
+"geändert werden."
#: scene/2d/remote_transform_2d.cpp
msgid "Path property must point to a valid Node2D node to work."
@@ -7876,31 +7527,35 @@ msgstr ""
#: scene/3d/arvr_nodes.cpp
msgid "ARVRCamera must have an ARVROrigin node as its parent"
-msgstr ""
+msgstr "ARVRCamera braucht ein ARVROrigin-Node als Ãœberobjekt"
#: scene/3d/arvr_nodes.cpp
msgid "ARVRController must have an ARVROrigin node as its parent"
-msgstr ""
+msgstr "ARVRController braucht ein ARVROrigin-Node als Ãœberobjekt"
#: scene/3d/arvr_nodes.cpp
msgid ""
"The controller id must not be 0 or this controller will not be bound to an "
"actual controller"
msgstr ""
+"Die Controller-ID sollte nicht null sein, sonst wird der Controller nicht an "
+"einen echten Controller gebunden"
#: scene/3d/arvr_nodes.cpp
msgid "ARVRAnchor must have an ARVROrigin node as its parent"
-msgstr ""
+msgstr "ARVRAnchor braucht ein ARVROrigin-Node als Ãœberobjekt"
#: scene/3d/arvr_nodes.cpp
msgid ""
"The anchor id must not be 0 or this anchor will not be bound to an actual "
"anchor"
msgstr ""
+"Die Anker-ID darf nicht null sein, sonst wird der Anker nicht an einen "
+"echten Anker gebunden"
#: scene/3d/arvr_nodes.cpp
msgid "ARVROrigin requires an ARVRCamera child node"
-msgstr ""
+msgstr "ARVROrigin benötigt ein ARVRCamera-Unterobjekt"
#: scene/3d/collision_polygon.cpp
msgid ""
@@ -7960,6 +7615,10 @@ msgid ""
"the physics engine when running.\n"
"Change the size in children collision shapes instead."
msgstr ""
+"Größenänderungen von RigidBody (in Character- oder Rigid-Modus) werden "
+"überschrieben wenn die Physikengine läuft.\n"
+"Die Größe der entsprechenden Collisionshape-Unterobjekte sollte stattdessen "
+"geändert werden."
#: scene/3d/remote_transform.cpp
msgid "Path property must point to a valid Spatial node to work."
@@ -7980,16 +7639,25 @@ msgstr ""
"Eine SpriteFrames-Ressource muss in der ‚Frames‘-Eigenschaft erzeugt oder "
"definiert werden, damit AnimatedSprite3D Einzelbilder anzeigen kann."
+#: scene/3d/vehicle_body.cpp
+msgid ""
+"VehicleWheel serves to provide a wheel system to a VehicleBody. Please use "
+"it as a child of a VehicleBody."
+msgstr ""
+
#: scene/gui/color_picker.cpp
-#, fuzzy
msgid "Raw Mode"
-msgstr "Schwenkmodus"
+msgstr "Rohdatenmodus"
#: scene/gui/color_picker.cpp
msgid "Add current color as a preset"
msgstr "Füge aktuelle Farbe als Vorlage hinzu"
#: scene/gui/dialogs.cpp
+msgid "Cancel"
+msgstr "Abbrechen"
+
+#: scene/gui/dialogs.cpp
msgid "Alert!"
msgstr "Warnung!"
@@ -7997,10 +7665,6 @@ msgstr "Warnung!"
msgid "Please Confirm..."
msgstr "Bitte bestätigen..."
-#: scene/gui/input_action.cpp
-msgid "Ctrl+"
-msgstr "Strg+"
-
#: scene/gui/popup.cpp
msgid ""
"Popups will hide by default unless you call popup() or any of the popup*() "
@@ -8045,6 +7709,638 @@ msgstr ""
"Eigenschaft ‚Render Target‘ des Viewports aktiviert und seine Textur "
"irgendeinem Node zum Anzeigen zugewiesen werden."
+#: scene/resources/dynamic_font.cpp
+msgid "Error initializing FreeType."
+msgstr "Fehler beim initialisieren von FreeType."
+
+#: scene/resources/dynamic_font.cpp
+msgid "Unknown font format."
+msgstr "Unbekanntes Schriftformat."
+
+#: scene/resources/dynamic_font.cpp
+msgid "Error loading font."
+msgstr "Fehler beim Laden der Schriftart."
+
+#: scene/resources/dynamic_font.cpp
+msgid "Invalid font size."
+msgstr "Ungültige Schriftgröße."
+
+#~ msgid "Filter:"
+#~ msgstr "Filter:"
+
+#~ msgid "' parsing of config failed."
+#~ msgstr ""
+#~ "‘ kann nicht aktiviert werden, Einlesen der Konfigurationsdatei "
+#~ "fehlgeschlagen."
+
+#~ msgid "Theme"
+#~ msgstr "Motiv"
+
+#~ msgid "Method List For '%s':"
+#~ msgstr "Methodenliste für '%s':"
+
+#~ msgid "Arguments:"
+#~ msgstr "Argumente:"
+
+#~ msgid "Return:"
+#~ msgstr "Rückgabe:"
+
+#~ msgid "Added:"
+#~ msgstr "Hinzugefügt:"
+
+#~ msgid "Removed:"
+#~ msgstr "Entfernt:"
+
+#~ msgid "Error saving atlas:"
+#~ msgstr "Fehler beim speichern des Atlas:"
+
+#~ msgid "Could not save atlas subtexture:"
+#~ msgstr "Atlas Untertextur konnte nicht gespeichert werden:"
+
+#~ msgid "Exporting for %s"
+#~ msgstr "Exportiere für %s"
+
+#~ msgid "Setting Up.."
+#~ msgstr "Bereite vor..."
+
+#~ msgid "Error loading scene."
+#~ msgstr "Fehler beim laden der Szene."
+
+#~ msgid "Re-Import"
+#~ msgstr "Neuimport"
+
+#~ msgid "Please wait for scan to complete."
+#~ msgstr "Bitte warten bis Operation abgeschlossen ist."
+
+#~ msgid "Current scene must be saved to re-import."
+#~ msgstr "Aktuelle Szene muss gespeichert sein um sie erneut zu importieren."
+
+#~ msgid "Save & Re-Import"
+#~ msgstr "Speichern & neu importieren"
+
+#~ msgid "Re-Importing"
+#~ msgstr "Importiere erneut"
+
+#~ msgid "Re-Import Changed Resources"
+#~ msgstr "Veränderte Ressourcen neu importieren"
+
+#~ msgid "Loading Export Templates"
+#~ msgstr "Lade Exportvorlagen"
+
+#~ msgid ""
+#~ "\n"
+#~ "Status: Needs Re-Import"
+#~ msgstr ""
+#~ "\n"
+#~ "Status: Benötigt Neu-Import"
+
+#~ msgid "Same source and destination files, doing nothing."
+#~ msgstr "Quell- und Zieldatei sind gleich, ignoriere Anweisung."
+
+#~ msgid "Target file exists, can't overwrite. Delete first."
+#~ msgstr ""
+#~ "Zieldatei existiert bereits und kann nicht überschrieben werden. Ggf "
+#~ "manuell löschen."
+
+#~ msgid "Same source and destination paths, doing nothing."
+#~ msgstr "Quell- und Zielpfad sind gleich, ignoriere Anweisung."
+
+#~ msgid "Can't move directories to within themselves."
+#~ msgstr "Verzeichnisse lassen sich nicht in sich selbst verschieben."
+
+#~ msgid "Can't rename deps for:\n"
+#~ msgstr "Abhängigkeiten können nicht umbenannt werden für:\n"
+
+#~ msgid "Error moving file:\n"
+#~ msgstr "Fehler beim Dateiverschieben:\n"
+
+#~ msgid "Pick New Name and Location For:"
+#~ msgstr "Wähle neuen Namen und Ort für:"
+
+#~ msgid "No files selected!"
+#~ msgstr "Keine Dateien ausgewählt!"
+
+#~ msgid "Info"
+#~ msgstr "Info"
+
+#~ msgid "Re-Import.."
+#~ msgstr "Neuimport.."
+
+#~ msgid "No bit masks to import!"
+#~ msgstr "Keine Bitmasken zu importieren!"
+
+#~ msgid "Target path is empty."
+#~ msgstr "Zielpfad ist leer."
+
+#~ msgid "Target path must be a complete resource path."
+#~ msgstr "Zielpfad muss ein kompletter Ressourcenpfad sein."
+
+#~ msgid "Target path must exist."
+#~ msgstr "Zielpfad muss existieren."
+
+#~ msgid "Save path is empty!"
+#~ msgstr "Speicherpfad ist leer!"
+
+#~ msgid "Import BitMasks"
+#~ msgstr "BitMasks importieren"
+
+#~ msgid "Source Texture(s):"
+#~ msgstr "Quelltextur(en):"
+
+#~ msgid "Target Path:"
+#~ msgstr "Zielpfad:"
+
+#~ msgid "Accept"
+#~ msgstr "Akzeptieren"
+
+#~ msgid "Bit Mask"
+#~ msgstr "Bitmaske"
+
+#~ msgid "No source font file!"
+#~ msgstr "Keine Quellschriftart-Datei gefunden!"
+
+#~ msgid "No target font resource!"
+#~ msgstr "Keine Zielschriftart-Ressource!"
+
+#~ msgid ""
+#~ "Invalid file extension.\n"
+#~ "Please use .font."
+#~ msgstr ""
+#~ "Ungültige Dateiendung.\n"
+#~ "Nutze .font als Dateiendung."
+
+#~ msgid "Couldn't save font."
+#~ msgstr "Schriftart konnte nicht gespeichert werden."
+
+#~ msgid "Source Font:"
+#~ msgstr "Quellschriftart:"
+
+#~ msgid "Source Font Size:"
+#~ msgstr "Quellschriftgröße:"
+
+#~ msgid "Dest Resource:"
+#~ msgstr "Ziel-Ressource:"
+
+#~ msgid "The quick brown fox jumps over the lazy dog."
+#~ msgstr "Franz jagt im komplett verwahrlosten Taxi quer durch Bayern."
+
+#~ msgid "Test:"
+#~ msgstr "Test:"
+
+#~ msgid "Options:"
+#~ msgstr "Optionen:"
+
+#~ msgid "Font Import"
+#~ msgstr "Schriftart importieren"
+
+#~ msgid ""
+#~ "This file is already a Godot font file, please supply a BMFont type file "
+#~ "instead."
+#~ msgstr ""
+#~ "Diese Datei ist bereits eine Godot Schriftart. Bitte stattdessen eine "
+#~ "Datei im BMFont-Format angeben."
+
+#~ msgid "Failed opening as BMFont file."
+#~ msgstr "Öffnen der BMFont-Datei fehlgeschlagen."
+
+#~ msgid "Invalid font custom source."
+#~ msgstr "Eigene Schriftart-Quelle ist ungültig."
+
+#~ msgid "No meshes to import!"
+#~ msgstr "Keine Meshes zu importieren!"
+
+#~ msgid "Single Mesh Import"
+#~ msgstr "Einzelnes Mesh importieren"
+
+#~ msgid "Source Mesh(es):"
+#~ msgstr "Quell Mesh(es):"
+
+#~ msgid "Surface %d"
+#~ msgstr "Oberfläche %d"
+
+#~ msgid "No samples to import!"
+#~ msgstr "Keine Samples zu importieren!"
+
+#~ msgid "Import Audio Samples"
+#~ msgstr "Audio-Samples importieren"
+
+#~ msgid "Source Sample(s):"
+#~ msgstr "Quell Sample(s):"
+
+#~ msgid "Audio Sample"
+#~ msgstr "Audio-Sample"
+
+#~ msgid "New Clip"
+#~ msgstr "Neuer Clip"
+
+#~ msgid "Flags"
+#~ msgstr "Flags"
+
+#~ msgid "Bake FPS:"
+#~ msgstr "FPS fixieren:"
+
+#~ msgid "Optimizer"
+#~ msgstr "Optimierung"
+
+#~ msgid "Max Linear Error"
+#~ msgstr "Obere lineare Fehlergrenze"
+
+#~ msgid "Max Angular Error"
+#~ msgstr "Obere Winkelfehlergrenze"
+
+#~ msgid "Max Angle"
+#~ msgstr "Maximaler Winkel"
+
+#~ msgid "Clips"
+#~ msgstr "Ausschnitte"
+
+#~ msgid "Start(s)"
+#~ msgstr "Start"
+
+#~ msgid "End(s)"
+#~ msgstr "Ende"
+
+#~ msgid "Filters"
+#~ msgstr "Filter"
+
+#~ msgid "Source path is empty."
+#~ msgstr "Quellpfad ist leer."
+
+#~ msgid "Couldn't load post-import script."
+#~ msgstr "Post-Import Skript konnte nicht geladen werden."
+
+#~ msgid "Invalid/broken script for post-import."
+#~ msgstr "Ungültiges / Fehlerhaftes Skript für Post-Import."
+
+#~ msgid "Error importing scene."
+#~ msgstr "Fehler beim importieren der Szene."
+
+#~ msgid "Import 3D Scene"
+#~ msgstr "3D-Szene importieren"
+
+#~ msgid "Source Scene:"
+#~ msgstr "Quellszene:"
+
+#~ msgid "Same as Target Scene"
+#~ msgstr "Dieselbe wie die Zielszene"
+
+#~ msgid "Shared"
+#~ msgstr "Geteilt"
+
+#~ msgid "Target Texture Folder:"
+#~ msgstr "Ziel-Texturenordner:"
+
+#~ msgid "Post-Process Script:"
+#~ msgstr "Post-Process Skript:"
+
+#~ msgid "Custom Root Node Type:"
+#~ msgstr "Angepasster Root-Node-Typ:"
+
+#~ msgid "Auto"
+#~ msgstr "Auto"
+
+#~ msgid "Root Node Name:"
+#~ msgstr "Name des Root-Node:"
+
+#~ msgid "The Following Files are Missing:"
+#~ msgstr "Die folgenden Dateien fehlen:"
+
+#~ msgid "Import Anyway"
+#~ msgstr "Trotzdem importieren"
+
+#~ msgid "Import & Open"
+#~ msgstr "Importieren & Öffnen"
+
+#~ msgid "Edited scene has not been saved, open imported scene anyway?"
+#~ msgstr ""
+#~ "Bearbeitete Szene wurde nicht gespeichert, trotzdem importierte Szene "
+#~ "öffnen?"
+
+#~ msgid "Import Image:"
+#~ msgstr "Bild importieren:"
+
+#~ msgid "Couldn't localize path: %s (already local)"
+#~ msgstr "Pfad konnte nicht gefunden werden: %s (bereits lokal)"
+
+#~ msgid "3D Scene Animation"
+#~ msgstr "3D-Szenenanimation"
+
+#~ msgid "Uncompressed"
+#~ msgstr "Unkomprimiert"
+
+#~ msgid "Compress Lossless (PNG)"
+#~ msgstr "Verlustfrei komprimieren (PNG)"
+
+#~ msgid "Compress Lossy (WebP)"
+#~ msgstr "Verlustbehaftet komprimieren (WebP)"
+
+#~ msgid "Compress (VRAM)"
+#~ msgstr "Komprimieren (VRAM)"
+
+#~ msgid "Texture Format"
+#~ msgstr "Texturformat"
+
+#~ msgid "Texture Compression Quality (WebP):"
+#~ msgstr "Texturkompressionsqualität (WebP):"
+
+#~ msgid "Texture Options"
+#~ msgstr "Textureinstellungen"
+
+#~ msgid "Please specify some files!"
+#~ msgstr "Bitte gib einige Dateien an!"
+
+#~ msgid "At least one file needed for Atlas."
+#~ msgstr "Es wird zumindest eine Datei für den Atlas benötigt."
+
+#~ msgid "Error importing:"
+#~ msgstr "Fehler beim importieren:"
+
+#~ msgid "Only one file is required for large texture."
+#~ msgstr "Es ist nur eine Datei für eine große Textur erforderlich."
+
+#~ msgid "Max Texture Size:"
+#~ msgstr "Maximale Texturgröße:"
+
+#~ msgid "Import Textures for Atlas (2D)"
+#~ msgstr "Texturen für Atlas (2D) importieren"
+
+#~ msgid "Cell Size:"
+#~ msgstr "Zellgröße:"
+
+#~ msgid "Large Texture"
+#~ msgstr "Große Textur"
+
+#~ msgid "Import Large Textures (2D)"
+#~ msgstr "Große Texturen (2D) importieren"
+
+#~ msgid "Source Texture"
+#~ msgstr "Quelltextur"
+
+#~ msgid "Base Atlas Texture"
+#~ msgstr "Basis-Atlastextur"
+
+#~ msgid "Source Texture(s)"
+#~ msgstr "Quelltextur(en)"
+
+#~ msgid "Import Textures for 2D"
+#~ msgstr "Texturen für 2D importieren"
+
+#~ msgid "Import Textures for 3D"
+#~ msgstr "Texturen für 3D importieren"
+
+#~ msgid "Import Textures"
+#~ msgstr "Texturen importieren"
+
+#~ msgid "2D Texture"
+#~ msgstr "2D-Textur"
+
+#~ msgid "3D Texture"
+#~ msgstr "3D-Textur"
+
+#~ msgid "Atlas Texture"
+#~ msgstr "Atlastextur"
+
+#~ msgid ""
+#~ "NOTICE: Importing 2D textures is not mandatory. Just copy png/jpg files "
+#~ "to the project."
+#~ msgstr ""
+#~ "MERKE: Das importieren von 2D Texturen ist nicht zwingend notwendig. "
+#~ "Kopiere einfach png/jpg Dateien in das Projekt."
+
+#~ msgid "Crop empty space."
+#~ msgstr "Leere Bereiche beschneiden."
+
+#~ msgid "Texture"
+#~ msgstr "Textur"
+
+#~ msgid "Import Large Texture"
+#~ msgstr "Große Textur importieren"
+
+#~ msgid "Load Source Image"
+#~ msgstr "Quellbild laden"
+
+#~ msgid "Slicing"
+#~ msgstr "Teile"
+
+#~ msgid "Saving"
+#~ msgstr "Speichere"
+
+#~ msgid "Couldn't save large texture:"
+#~ msgstr "Große Textur konnte nicht gespeichert werden:"
+
+#~ msgid "Build Atlas For:"
+#~ msgstr "Erstelle Atlas für:"
+
+#~ msgid "Loading Image:"
+#~ msgstr "Lade Bild:"
+
+#~ msgid "Couldn't load image:"
+#~ msgstr "Bild konnte nicht geladen werden:"
+
+#~ msgid "Converting Images"
+#~ msgstr "Bilder werden konvertiert"
+
+#~ msgid "Cropping Images"
+#~ msgstr "Bilder werden beschnitten"
+
+#~ msgid "Blitting Images"
+#~ msgstr "Blitting Bilder"
+
+#~ msgid "Couldn't save atlas image:"
+#~ msgstr "Atlas-Bild konnte nicht gespeichert werden:"
+
+#~ msgid "Couldn't save converted texture:"
+#~ msgstr "Konvertierte Textur konnte nicht gespeichert werden:"
+
+#~ msgid "Invalid source!"
+#~ msgstr "Fehlerhafte Quelle!"
+
+#~ msgid "Invalid translation source!"
+#~ msgstr "Fehlerhafte Ãœbersetzungsquelle!"
+
+#~ msgid "Column"
+#~ msgstr "Reihe"
+
+#~ msgid "No items to import!"
+#~ msgstr "Keine Elemente zu importieren!"
+
+#~ msgid "No target path!"
+#~ msgstr "Kein Zielpfad!"
+
+#~ msgid "Import Translations"
+#~ msgstr "Ãœbersetzungen importieren"
+
+#~ msgid "Couldn't import!"
+#~ msgstr "Konnte nicht importiert werden!"
+
+#~ msgid "Import Translation"
+#~ msgstr "Ãœbersetzung importieren"
+
+#~ msgid "Source CSV:"
+#~ msgstr "Quell-CSV:"
+
+#~ msgid "Ignore First Row"
+#~ msgstr "Erste Zeile ignorieren"
+
+#~ msgid "Compress"
+#~ msgstr "Komprimieren"
+
+#~ msgid "Add to Project (project.godot)"
+#~ msgstr "Zu Projekt hinzufügen (project.godot)"
+
+#~ msgid "Import Languages:"
+#~ msgstr "Sprachen importieren:"
+
+#~ msgid "Translation"
+#~ msgstr "Ãœbersetzung"
+
+#~ msgid "Parsing %d Triangles:"
+#~ msgstr "Analysiere %d Dreiecke:"
+
+#~ msgid "Triangle #"
+#~ msgstr "Dreieck #"
+
+#~ msgid "Light Baker Setup:"
+#~ msgstr "Light-Baker einrichten:"
+
+#~ msgid "Fixing Lights"
+#~ msgstr "Fixiere Lampen"
+
+#~ msgid "Making BVH"
+#~ msgstr "Erstelle BVH"
+
+#~ msgid "Transfer to Lightmaps:"
+#~ msgstr "übertrage zu Lightmaps:"
+
+#~ msgid "Allocating Texture #"
+#~ msgstr "Zuweisen von Textur #"
+
+#~ msgid "Baking Triangle #"
+#~ msgstr "Baking von Dreieck #"
+
+#~ msgid "Post-Processing Texture #"
+#~ msgstr "Nachbearbeiten von Textur #"
+
+#~ msgid "Reset the lightmap octree baking process (start over)."
+#~ msgstr "Lightmap-Octree-Backing-Prozess zurücksetzen (neu starten)."
+
+#~ msgid "Zoom (%):"
+#~ msgstr "Vergrößerung (%):"
+
+#~ msgid "Skeleton.."
+#~ msgstr "Skelett.."
+
+#~ msgid "Zoom Reset"
+#~ msgstr "Vergrößerung zurücksetzen"
+
+#~ msgid "Zoom Set.."
+#~ msgstr "Vergrößerung setzen.."
+
+#~ msgid "Set a Value"
+#~ msgstr "Einen Wert setzen"
+
+#~ msgid "Snap (Pixels):"
+#~ msgstr "Einrasten (Pixel):"
+
+#~ msgid "Parse BBCode"
+#~ msgstr "BBCode parsen"
+
+#~ msgid "Length:"
+#~ msgstr "Länge:"
+
+#~ msgid "Open Sample File(s)"
+#~ msgstr "Audiodatei(en) öffnen"
+
+#~ msgid "ERROR: Couldn't load sample!"
+#~ msgstr "Fehler: Konnte Audio nicht laden!"
+
+#~ msgid "Add Sample"
+#~ msgstr "Sample hinzufügen"
+
+#~ msgid "Rename Sample"
+#~ msgstr "Sample umbenennen"
+
+#~ msgid "Delete Sample"
+#~ msgstr "Sample löschen"
+
+#~ msgid "16 Bits"
+#~ msgstr "16 Bit"
+
+#~ msgid "8 Bits"
+#~ msgstr "8 Bit"
+
+#~ msgid "Stereo"
+#~ msgstr "Stereo"
+
+#~ msgid "Mono"
+#~ msgstr "Mono"
+
+#~ msgid "Pitch"
+#~ msgstr "Tonhöhe"
+
+#~ msgid "Window"
+#~ msgstr "Fenster"
+
+#~ msgid "Move Right"
+#~ msgstr "nach rechts"
+
+#~ msgid "Scaling to %s%%."
+#~ msgstr "Skaliere auf %s%%."
+
+#~ msgid "Up"
+#~ msgstr "Hoch"
+
+#~ msgid "Down"
+#~ msgstr "Herunter"
+
+#~ msgid "Bucket"
+#~ msgstr "Eimer"
+
+#~ msgid "Invalid project path, the path must exist!"
+#~ msgstr "Ungültiger Projektpfad, der Pfad muss existieren!"
+
+#~ msgid "Invalid project path, project.godot must not exist."
+#~ msgstr "Ungültiger Projektpfad, project.godot darf nicht existieren."
+
+#~ msgid "Invalid project path, project.godot must exist."
+#~ msgstr "Ungültiger Projektpfad, project.godot muss existieren."
+
+#~ msgid "Project Path (Must Exist):"
+#~ msgstr "Projektpfad (muss existieren):"
+
+#~ msgid "Create New Resource"
+#~ msgstr "Erstelle neue Ressource"
+
+#~ msgid "Open Resource"
+#~ msgstr "Ressource öffnen"
+
+#~ msgid "Save Resource"
+#~ msgstr "Ressource speichern"
+
+#~ msgid "Resource Tools"
+#~ msgstr "Ressourcenwerkzeuge"
+
+#~ msgid "Make Local"
+#~ msgstr "Lokal machen"
+
+#~ msgid "Edit Groups"
+#~ msgstr "Gruppen bearbeiten"
+
+#~ msgid "Edit Connections"
+#~ msgstr "Verbindungen bearbeiten"
+
+#~ msgid "GridMap Paint"
+#~ msgstr "GridMap zeichnen"
+
+#~ msgid "Tiles"
+#~ msgstr "Kacheln"
+
+#~ msgid "Areas"
+#~ msgstr "Bereiche"
+
+#~ msgid "Ctrl+"
+#~ msgstr "Strg+"
+
#~ msgid "Close scene? (Unsaved changes will be lost)"
#~ msgstr "Szene schließen? (Nicht gespeicherte Änderungen gehen verloren)"
@@ -8058,9 +8354,6 @@ msgstr ""
#~ msgid "Close Goto Prev. Scene"
#~ msgstr "Schließen und zur letzten Szene wechseln"
-#~ msgid "Expand to Parent"
-#~ msgstr "Auf übergeordnetes Node ausdehnen"
-
#~ msgid "Del"
#~ msgstr "Entfernen"
@@ -8226,18 +8519,12 @@ msgstr ""
#~ msgid "Save Translatable Strings"
#~ msgstr "Speichere übersetzbare Zeichenketten"
-#~ msgid "Translatable Strings.."
-#~ msgstr "Ãœbersetzbare Textbausteine.."
-
#~ msgid "Install Export Templates"
#~ msgstr "Exportvorlagen installieren"
#~ msgid "Edit Script Options"
#~ msgstr "Skriptoptionen bearbeiten"
-#~ msgid "Please export outside the project folder!"
-#~ msgstr "Bitte außerhalb des Projektordners exportieren!"
-
#~ msgid "Error exporting project!"
#~ msgstr "Fehler beim Exportieren des Projekts!"
@@ -8296,18 +8583,12 @@ msgstr ""
#~ msgid "Include"
#~ msgstr "Einbeziehen"
-#~ msgid "Change Image Group"
-#~ msgstr "Ändere Bildergruppe"
-
#~ msgid "Group name can't be empty!"
#~ msgstr "Gruppenname muss vorhanden sein!"
#~ msgid "Invalid character in group name!"
#~ msgstr "Ungültiges Zeichen in Gruppenname!"
-#~ msgid "Group name already exists!"
-#~ msgstr "Gruppenname existiert bereits!"
-
#~ msgid "Add Image Group"
#~ msgstr "Füge Bildergruppe hinzu"
@@ -8387,9 +8668,6 @@ msgstr ""
#~ msgid "Preview Atlas"
#~ msgstr "Zeige Atlas-Vorschau"
-#~ msgid "Image Filter:"
-#~ msgstr "Bildfilter:"
-
#~ msgid "Images:"
#~ msgstr "Bilder:"
@@ -8456,9 +8734,6 @@ msgstr ""
#~ msgid "Lighting"
#~ msgstr "Belichtung"
-#~ msgid "Toggle Persisting"
-#~ msgstr "Persistente an- und ausschalten"
-
#~ msgid "Global"
#~ msgstr "Global"
diff --git a/editor/translations/de_CH.po b/editor/translations/de_CH.po
index c5234c20d9..8c9e4cc1de 100644
--- a/editor/translations/de_CH.po
+++ b/editor/translations/de_CH.po
@@ -1,5 +1,6 @@
# Swiss High German translation of the Godot Engine editor
-# Copyright (C) 2016-2017 Juan Linietsky, Ariel Manzur and the Godot community
+# Copyright (C) 2007-2017 Juan Linietsky, Ariel Manzur
+# Copyright (C) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)
# This file is distributed under the same license as the Godot source code.
#
# Christian Fisch <christian.fiesel@gmail.com>, 2016.
@@ -191,10 +192,9 @@ msgid "Create %d NEW tracks and insert keys?"
msgstr "Erstelle %d in neuer Ebene inklusiv Bild?"
#: editor/animation_editor.cpp editor/create_dialog.cpp
-#: editor/editor_audio_buses.cpp
+#: editor/editor_audio_buses.cpp editor/plugins/abstract_polygon_2d_editor.cpp
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
#: editor/plugins/mesh_instance_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp editor/project_manager.cpp
#: editor/script_create_dialog.cpp
msgid "Create"
@@ -356,265 +356,6 @@ msgstr ""
msgid "Change Array Value"
msgstr ""
-#: editor/asset_library_editor_plugin.cpp
-msgid "Free"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_plugin_settings.cpp
-msgid "Version:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Contents:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "View Files"
-msgstr "Datei(en) öffnen"
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_help.cpp editor/property_selector.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Description:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-#: editor/project_manager.cpp
-msgid "Install"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/call_dialog.cpp
-#: editor/connections_dialog.cpp editor/export_template_manager.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-#: editor/project_settings_editor.cpp editor/property_editor.cpp
-#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Close"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve hostname:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Connection error, please try again."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't connect."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Can't connect to host:"
-msgstr "Verbindung zu Node:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response from host:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Request failed, return code:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Req. Failed."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Request failed, too many redirects"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Redirect Loop."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Bad download hash, assuming file has been tampered with."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Expected:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Got:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Asset Download Error:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-msgid "Success!"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Fetching:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Resolving.."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Connecting.."
-msgstr "Connections editieren"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Requesting.."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Error making request"
-msgstr "Szene kann nicht gespeichert werden."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Idle"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Retry"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Download Error"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Download for this asset is already in progress!"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "first"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "prev"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "next"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "last"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "All"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
-#: editor/settings_config_dialog.cpp
-msgid "Search:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/code_editor.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Search"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/project_manager.cpp
-msgid "Import"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Plugins"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Sort:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Reverse"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Category:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Site:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Support.."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Official"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-msgid "Community"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Testing"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Assets ZIP File"
-msgstr ""
-
-#: editor/call_dialog.cpp
-msgid "Method List For '%s':"
-msgstr ""
-
-#: editor/call_dialog.cpp modules/visual_script/visual_script_editor.cpp
-msgid "Call"
-msgstr ""
-
-#: editor/call_dialog.cpp
-msgid "Method List:"
-msgstr ""
-
-#: editor/call_dialog.cpp
-msgid "Arguments:"
-msgstr ""
-
-#: editor/call_dialog.cpp
-msgid "Return:"
-msgstr ""
-
#: editor/code_editor.cpp
msgid "Go to Line"
msgstr ""
@@ -651,6 +392,14 @@ msgstr ""
msgid "Selection Only"
msgstr ""
+#: editor/code_editor.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
+msgid "Search"
+msgstr ""
+
#: editor/code_editor.cpp editor/editor_help.cpp
msgid "Find"
msgstr ""
@@ -683,11 +432,11 @@ msgstr ""
msgid "Skip"
msgstr ""
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom In"
msgstr ""
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom Out"
msgstr ""
@@ -755,6 +504,20 @@ msgstr ""
msgid "Oneshot"
msgstr ""
+#: editor/connections_dialog.cpp editor/dependency_editor.cpp
+#: editor/export_template_manager.cpp
+#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Close"
+msgstr ""
+
#: editor/connections_dialog.cpp
msgid "Connect"
msgstr ""
@@ -780,7 +543,7 @@ msgstr ""
msgid "Disconnect"
msgstr ""
-#: editor/connections_dialog.cpp editor/node_dock.cpp
+#: editor/connections_dialog.cpp editor/editor_help.cpp editor/node_dock.cpp
msgid "Signals"
msgstr ""
@@ -797,12 +560,25 @@ msgstr ""
msgid "Recent:"
msgstr ""
+#: editor/create_dialog.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/quick_open.cpp editor/settings_config_dialog.cpp
+msgid "Search:"
+msgstr ""
+
#: editor/create_dialog.cpp editor/editor_help.cpp
#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/quick_open.cpp
msgid "Matches:"
msgstr ""
+#: editor/create_dialog.cpp editor/editor_help.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/property_selector.cpp
+#: editor/script_editor_debugger.cpp
+msgid "Description:"
+msgstr ""
+
#: editor/dependency_editor.cpp
msgid "Search Replacement For:"
msgstr ""
@@ -858,6 +634,10 @@ msgid "Owners Of:"
msgstr ""
#: editor/dependency_editor.cpp
+msgid "Remove selected files from the project? (no undo)"
+msgstr ""
+
+#: editor/dependency_editor.cpp
msgid ""
"The files being removed are required by other resources in order for them to "
"work.\n"
@@ -865,7 +645,7 @@ msgid ""
msgstr ""
#: editor/dependency_editor.cpp
-msgid "Remove selected files from the project? (no undo)"
+msgid "Cannot remove:\n"
msgstr ""
#: editor/dependency_editor.cpp
@@ -932,10 +712,6 @@ msgid "Godot Engine contributors"
msgstr ""
#: editor/editor_about.cpp
-msgid "Authors"
-msgstr ""
-
-#: editor/editor_about.cpp
#, fuzzy
msgid "Project Founders"
msgstr "Projekt exportieren"
@@ -953,6 +729,38 @@ msgid "Developers"
msgstr ""
#: editor/editor_about.cpp
+msgid "Authors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Platinum Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Gold Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Mini Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Gold Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Silver Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Bronze Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
msgid "License"
msgstr ""
@@ -993,6 +801,16 @@ msgid "Package Installed Successfully!"
msgstr ""
#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Success!"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/project_manager.cpp
+msgid "Install"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
msgid "Package Installer"
msgstr ""
@@ -1042,10 +860,6 @@ msgid "Audio Bus, Drag and Drop to rearrange."
msgstr ""
#: editor/editor_audio_buses.cpp
-msgid "Bus options"
-msgstr ""
-
-#: editor/editor_audio_buses.cpp
msgid "Solo"
msgstr ""
@@ -1057,12 +871,20 @@ msgstr ""
msgid "Bypass"
msgstr ""
+#: editor/editor_audio_buses.cpp
+msgid "Bus options"
+msgstr ""
+
#: editor/editor_audio_buses.cpp editor/plugins/tile_map_editor_plugin.cpp
#: editor/scene_tree_dock.cpp
msgid "Duplicate"
msgstr ""
#: editor/editor_audio_buses.cpp
+msgid "Reset Volume"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
msgid "Delete Effect"
msgstr ""
@@ -1085,6 +907,10 @@ msgid "Duplicate Audio Bus"
msgstr "Node(s) duplizieren"
#: editor/editor_audio_buses.cpp
+msgid "Reset Bus Volume"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
#, fuzzy
msgid "Move Audio Bus"
msgstr "Bild bewegen/einfügen"
@@ -1117,7 +943,8 @@ msgstr ""
msgid "Create a new Bus Layout."
msgstr ""
-#: editor/editor_audio_buses.cpp editor/script_create_dialog.cpp
+#: editor/editor_audio_buses.cpp editor/property_editor.cpp
+#: editor/script_create_dialog.cpp
msgid "Load"
msgstr ""
@@ -1207,7 +1034,7 @@ msgid "Rearrange Autoloads"
msgstr ""
#: editor/editor_autoload_settings.cpp editor/editor_file_dialog.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp scene/gui/file_dialog.cpp
+#: scene/gui/file_dialog.cpp
msgid "Path:"
msgstr ""
@@ -1215,9 +1042,7 @@ msgstr ""
msgid "Node Name:"
msgstr ""
-#: editor/editor_autoload_settings.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp editor/project_manager.cpp
+#: editor/editor_autoload_settings.cpp editor/project_manager.cpp
msgid "Name"
msgstr ""
@@ -1250,18 +1075,19 @@ msgid "Choose a Directory"
msgstr ""
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Create Folder"
msgstr ""
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: editor/editor_plugin_settings.cpp editor/plugins/theme_editor_plugin.cpp
-#: editor/project_export.cpp scene/gui/file_dialog.cpp
+#: editor/editor_plugin_settings.cpp editor/filesystem_dock.cpp
+#: editor/plugins/theme_editor_plugin.cpp editor/project_export.cpp
+#: scene/gui/file_dialog.cpp
msgid "Name:"
msgstr ""
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Could not create folder."
msgstr ""
@@ -1281,30 +1107,6 @@ msgstr ""
msgid "Template file not found:\n"
msgstr ""
-#: editor/editor_export.cpp
-msgid "Added:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Removed:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Error saving atlas:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Could not save atlas subtexture:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Exporting for %s"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Setting Up.."
-msgstr ""
-
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "File Exists, Overwrite?"
msgstr "Datei existiert, Ãœberschreiben?"
@@ -1389,6 +1191,10 @@ msgstr ""
msgid "Move Favorite Down"
msgstr ""
+#: editor/editor_file_dialog.cpp
+msgid "Go to parent folder"
+msgstr ""
+
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Directories & Files:"
msgstr ""
@@ -1403,10 +1209,6 @@ msgid "File:"
msgstr ""
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
-msgid "Filter:"
-msgstr ""
-
-#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Must use a valid extension."
msgstr ""
@@ -1431,6 +1233,10 @@ msgstr ""
msgid "Search Classes"
msgstr ""
+#: editor/editor_help.cpp editor/plugins/spatial_editor_plugin.cpp
+msgid "Top"
+msgstr ""
+
#: editor/editor_help.cpp editor/property_editor.cpp
msgid "Class:"
msgstr ""
@@ -1447,15 +1253,27 @@ msgstr ""
msgid "Brief Description:"
msgstr ""
+#: editor/editor_help.cpp
+msgid "Members"
+msgstr ""
+
#: editor/editor_help.cpp modules/visual_script/visual_script_editor.cpp
msgid "Members:"
msgstr ""
#: editor/editor_help.cpp
+msgid "Public Methods"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Public Methods:"
msgstr ""
#: editor/editor_help.cpp
+msgid "GUI Theme Items"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "GUI Theme Items:"
msgstr ""
@@ -1464,6 +1282,10 @@ msgid "Signals:"
msgstr ""
#: editor/editor_help.cpp
+msgid "Enumerations"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Enumerations:"
msgstr ""
@@ -1472,18 +1294,47 @@ msgid "enum "
msgstr ""
#: editor/editor_help.cpp
+msgid "Constants"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Constants:"
msgstr ""
#: editor/editor_help.cpp
+#, fuzzy
+msgid "Description"
+msgstr "Script hinzufügen"
+
+#: editor/editor_help.cpp
+msgid "Properties"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Property Description:"
msgstr ""
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this property. Please help us by "
+"[color=$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+
+#: editor/editor_help.cpp
+msgid "Methods"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Method Description:"
msgstr ""
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this method. Please help us by [color="
+"$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Search Text"
msgstr ""
@@ -1492,24 +1343,21 @@ msgid "Output:"
msgstr ""
#: editor/editor_log.cpp editor/plugins/animation_tree_editor_plugin.cpp
-#: editor/plugins/rich_text_editor_plugin.cpp editor/property_editor.cpp
-#: editor/script_editor_debugger.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/property_editor.cpp editor/script_editor_debugger.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Clear"
msgstr ""
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Error saving resource!"
msgstr ""
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Save Resource As.."
msgstr ""
-#: editor/editor_node.cpp editor/export_template_manager.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "I see.."
msgstr ""
@@ -1526,6 +1374,29 @@ msgid "Error while saving."
msgstr ""
#: editor/editor_node.cpp
+msgid "Can't open '%s'."
+msgstr ""
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Error while parsing '%s'."
+msgstr "Fehler beim Instanzieren der %s Szene"
+
+#: editor/editor_node.cpp
+msgid "Unexpected end of file '%s'."
+msgstr ""
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Missing '%s' or its dependencies."
+msgstr "Szene '%s' hat kapute Abhängigkeiten:"
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Error while loading '%s'."
+msgstr "Fehler beim Instanzieren der %s Szene"
+
+#: editor/editor_node.cpp
msgid "Saving Scene"
msgstr ""
@@ -1584,6 +1455,33 @@ msgid "Restored default layout to base settings."
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was imported, so it's not editable.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was instanced or inherited.\n"
+"Changes to it will not be kept when saving the current scene."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource was imported, so it's not editable. Change its settings in the "
+"import panel and then re-import."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This scene was imported, so changes to it will not be kept.\n"
+"Instancing it or inheriting will allow making changes to it.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Copy Params"
msgstr ""
@@ -1749,23 +1647,35 @@ msgid "Save changes the following scene(s) before opening Project Manager?"
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"This option is deprecated. Situations where refresh must be forced are now "
+"considered a bug. Please report."
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Pick a Main Scene"
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to enable addon plugin at: '"
+msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr ""
#: editor/editor_node.cpp
-msgid "' parsing of config failed."
+msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/"
+#, fuzzy
+msgid "Unable to load addon script from path: '%s'."
+msgstr "Fehler beim Instanzieren der %s Szene"
+
+#: editor/editor_node.cpp
+msgid ""
+"Unable to load addon script from path: '%s' Base type is not EditorPlugin."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to load addon script from path: '"
+msgid "Unable to load addon script from path: '%s' Script is not in tool mode."
msgstr ""
#: editor/editor_node.cpp
@@ -1775,7 +1685,7 @@ msgid ""
msgstr ""
#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/scene_tree_dock.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Ugh"
msgstr ""
@@ -1786,14 +1696,14 @@ msgid ""
msgstr ""
#: editor/editor_node.cpp
-msgid "Error loading scene."
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Scene '%s' has broken dependencies:"
msgstr "Szene '%s' hat kapute Abhängigkeiten:"
#: editor/editor_node.cpp
+msgid "Clear Recent Scenes"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Save Layout"
msgstr ""
@@ -1826,7 +1736,7 @@ msgstr ""
msgid "Toggle distraction-free mode."
msgstr ""
-#: editor/editor_node.cpp editor/io_plugins/editor_scene_import_plugin.cpp
+#: editor/editor_node.cpp
msgid "Scene"
msgstr ""
@@ -2050,6 +1960,10 @@ msgstr ""
msgid "Issue Tracker"
msgstr ""
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+msgid "Community"
+msgstr ""
+
#: editor/editor_node.cpp
msgid "About"
msgstr ""
@@ -2058,7 +1972,7 @@ msgstr ""
msgid "Play the project."
msgstr "Projekt starten."
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Play"
msgstr "Abspielen"
@@ -2074,7 +1988,7 @@ msgstr ""
msgid "Stop the scene."
msgstr ""
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Stop"
msgstr ""
@@ -2148,6 +2062,15 @@ msgid "Object properties."
msgstr ""
#: editor/editor_node.cpp
+msgid "Changes may be lost!"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Import"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "FileSystem"
msgstr ""
@@ -2163,14 +2086,6 @@ msgstr ""
msgid "Don't Save"
msgstr ""
-#: editor/editor_node.cpp editor/editor_reimport_dialog.cpp
-msgid "Re-Import"
-msgstr ""
-
-#: editor/editor_node.cpp editor/editor_plugin_settings.cpp
-msgid "Update"
-msgstr ""
-
#: editor/editor_node.cpp
msgid "Import Templates From ZIP File"
msgstr ""
@@ -2234,11 +2149,28 @@ msgstr ""
msgid "Open the previous Editor"
msgstr ""
+#: editor/editor_plugin.cpp
+msgid "Creating Mesh Previews"
+msgstr ""
+
+#: editor/editor_plugin.cpp
+msgid "Thumbnail.."
+msgstr ""
+
#: editor/editor_plugin_settings.cpp
msgid "Installed Plugins:"
msgstr ""
#: editor/editor_plugin_settings.cpp
+msgid "Update"
+msgstr ""
+
+#: editor/editor_plugin_settings.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Version:"
+msgstr ""
+
+#: editor/editor_plugin_settings.cpp
msgid "Author:"
msgstr ""
@@ -2271,7 +2203,7 @@ msgid "Frame %"
msgstr ""
#: editor/editor_profiler.cpp
-msgid "Fixed Frame %"
+msgid "Physics Frame %"
msgstr ""
#: editor/editor_profiler.cpp editor/script_editor_debugger.cpp
@@ -2290,26 +2222,6 @@ msgstr ""
msgid "Frame #:"
msgstr ""
-#: editor/editor_reimport_dialog.cpp
-msgid "Please wait for scan to complete."
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Current scene must be saved to re-import."
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Save & Re-Import"
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Importing"
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Import Changed Resources"
-msgstr ""
-
#: editor/editor_run_native.cpp
msgid "Select device from the list"
msgstr ""
@@ -2420,10 +2332,6 @@ msgid "Importing:"
msgstr ""
#: editor/export_template_manager.cpp
-msgid "Loading Export Templates"
-msgstr ""
-
-#: editor/export_template_manager.cpp
msgid "Current Version:"
msgstr ""
@@ -2457,9 +2365,17 @@ msgid "Cannot navigate to '"
msgstr ""
#: editor/filesystem_dock.cpp
+msgid "View items as a grid of thumbnails"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "View items as a list"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
msgid ""
"\n"
-"Status: Needs Re-Import"
+"Status: Import of file failed. Please fix file and reimport manually."
msgstr ""
#: editor/filesystem_dock.cpp
@@ -2469,89 +2385,90 @@ msgid ""
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Same source and destination files, doing nothing."
+msgid "Cannot move/rename resources root."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Target file exists, can't overwrite. Delete first."
+msgid "Cannot move a folder into itself.\n"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Same source and destination paths, doing nothing."
-msgstr ""
+#, fuzzy
+msgid "Error moving:\n"
+msgstr "Szene kann nicht gespeichert werden."
#: editor/filesystem_dock.cpp
-msgid "Can't move directories to within themselves."
-msgstr ""
+#, fuzzy
+msgid "Unable to update dependencies:\n"
+msgstr "Szene '%s' hat kapute Abhängigkeiten:"
#: editor/filesystem_dock.cpp
-msgid "Can't rename deps for:\n"
+msgid "No name provided"
msgstr ""
#: editor/filesystem_dock.cpp
-#, fuzzy
-msgid "Error moving file:\n"
-msgstr "Szene kann nicht gespeichert werden."
+msgid "Provided name contains invalid characters"
+msgstr ""
#: editor/filesystem_dock.cpp
-#, fuzzy
-msgid "Error moving dir:\n"
-msgstr "Szene kann nicht gespeichert werden."
+msgid "No name provided."
+msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Can't operate on '..'"
+msgid "Name contains invalid characters."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Pick New Name and Location For:"
+msgid "A file or folder with this name already exists."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "No files selected!"
-msgstr ""
+#, fuzzy
+msgid "Renaming file:"
+msgstr "Szene kann nicht gespeichert werden."
#: editor/filesystem_dock.cpp
-msgid "Expand all"
+msgid "Renaming folder:"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Collapse all"
+msgid "Expand all"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Show In File Manager"
+msgid "Collapse all"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Instance"
+msgid "Copy Path"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Edit Dependencies.."
+msgid "Rename.."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "View Owners.."
+msgid "Move To.."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Copy Path"
+msgid "New Folder.."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Rename or Move.."
+msgid "Show In File Manager"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Move To.."
+msgid "Instance"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Info"
+msgid "Edit Dependencies.."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Re-Import.."
+msgid "View Owners.."
msgstr ""
#: editor/filesystem_dock.cpp
@@ -2584,6 +2501,11 @@ msgstr ""
msgid "Move"
msgstr ""
+#: editor/filesystem_dock.cpp editor/plugins/animation_tree_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Rename"
+msgstr ""
+
#: editor/groups_editor.cpp
msgid "Add to Group"
msgstr ""
@@ -2597,6 +2519,10 @@ msgid "Import as Single Scene"
msgstr ""
#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
msgid "Import with Separate Materials"
msgstr ""
@@ -2609,6 +2535,18 @@ msgid "Import with Separate Objects+Materials"
msgstr ""
#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Materials+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Materials+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
msgid "Import as Multiple Scenes"
msgstr ""
@@ -2617,38 +2555,31 @@ msgid "Import as Multiple Scenes+Materials"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Import Scene"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Importing Scene.."
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Running Custom Script.."
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Couldn't load post-import script:"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Invalid/broken script for post-import (check console):"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Error running post-import script:"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Saving.."
msgstr ""
@@ -2677,587 +2608,58 @@ msgstr ""
msgid "Reimport"
msgstr ""
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "No bit masks to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path is empty."
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must be a complete resource path."
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must exist."
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Save path is empty!"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Import BitMasks"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s):"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Target Path:"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Accept"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Bit Mask"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No source font file!"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No target font resource!"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"Invalid file extension.\n"
-"Please use .font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Can't load/process source font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Couldn't save font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font Size:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Dest Resource:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "The quick brown fox jumps over the lazy dog."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Test:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Options:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Font Import"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"This file is already a Godot font file, please supply a BMFont type file "
-"instead."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Failed opening as BMFont file."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
+#: editor/multi_node_edit.cpp
#, fuzzy
-msgid "Error initializing FreeType."
-msgstr "Fehler bei der FreeType Inizialisierung."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Unknown font format."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error loading font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Invalid font size."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Invalid font custom source."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/plugins/theme_editor_plugin.cpp
-msgid "Font"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "No meshes to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Single Mesh Import"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Source Mesh(es):"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/plugins/mesh_instance_editor_plugin.cpp
-msgid "Mesh"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Surface %d"
-msgstr "Oberfläche %d"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "No samples to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Import Audio Samples"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Source Sample(s):"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Audio Sample"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "New Clip"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Animation Options"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Flags"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Bake FPS:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Optimizer"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Linear Error"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angular Error"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angle"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Clips"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Start(s)"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "End(s)"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Loop"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Filters"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source path is empty."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't load post-import script."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Invalid/broken script for post-import."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Error importing scene."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import 3D Scene"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source Scene:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Same as Target Scene"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Shared"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Target Texture Folder:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Post-Process Script:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Custom Root Node Type:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Auto"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Root Node Name:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "The Following Files are Missing:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Anyway"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp scene/gui/dialogs.cpp
-msgid "Cancel"
-msgstr "Abbrechen"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import & Open"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Edited scene has not been saved, open imported scene anyway?"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Image:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Can't import a file over itself:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't localize path: %s (already local)"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "3D Scene Animation"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Uncompressed"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossless (PNG)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossy (WebP)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress (VRAM)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Format"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Compression Quality (WebP):"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Options"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Please specify some files!"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "At least one file needed for Atlas."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Error importing:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Only one file is required for large texture."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Max Texture Size:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for Atlas (2D)"
-msgstr "Importiere Texturen für Atlas (2D)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cell Size:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Large Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Textures (2D)"
-msgstr "Importiere Große Texturen (2D)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Base Atlas Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 2D"
-msgstr "Importiere Texturen für 2D"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 3D"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "2D Texture"
-msgstr "2D-Textur"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "3D Texture"
-msgstr ""
+msgid "MultiNode Set"
+msgstr "MultiNode Set"
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Atlas Texture"
+#: editor/node_dock.cpp
+msgid "Groups"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
+#: editor/node_dock.cpp
#, fuzzy
-msgid ""
-"NOTICE: Importing 2D textures is not mandatory. Just copy png/jpg files to "
-"the project."
-msgstr ""
-"MERKE: Das importieren von 2D Texturen ist nicht zwingend notwendig. Kopiere "
-"einfach png/jpg Dateien in das Projekt."
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Crop empty space."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Load Source Image"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Slicing"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Inserting"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Saving"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save large texture:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Build Atlas For:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Loading Image:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't load image:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Converting Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cropping Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Blitting Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save atlas image:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save converted texture:"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid source!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid translation source!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Column"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/script_create_dialog.cpp
-msgid "Language"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No items to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No target path!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translations"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Couldn't import!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translation"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Source CSV:"
-msgstr ""
+msgid "Select a Node to edit Signals and Groups."
+msgstr "Selektiere ein Node um deren Signale und Gruppen zu ändern."
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Ignore First Row"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create Poly"
msgstr ""
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Compress"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly"
msgstr ""
-#: editor/io_plugins/editor_translation_import_plugin.cpp
+#: editor/plugins/abstract_polygon_2d_editor.cpp
#, fuzzy
-msgid "Add to Project (project.godot)"
-msgstr "Zum Projekt hinzufügen (engine.cfg)"
+msgid "Insert Point"
+msgstr "Bild einfügen"
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Languages:"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly (Remove Point)"
msgstr ""
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Translation"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Remove Poly And Point"
msgstr ""
-#: editor/multi_node_edit.cpp
-#, fuzzy
-msgid "MultiNode Set"
-msgstr "MultiNode Set"
-
-#: editor/node_dock.cpp
-msgid "Groups"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create a new polygon from scratch."
msgstr ""
-#: editor/node_dock.cpp
-#, fuzzy
-msgid "Select a Node to edit Signals and Groups."
-msgstr "Selektiere ein Node um deren Signale und Gruppen zu ändern."
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid ""
+"Edit existing polygon:\n"
+"LMB: Move Point.\n"
+"Ctrl+LMB: Split Segment.\n"
+"RMB: Erase Point."
+msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Toggle Autoplay"
@@ -3417,7 +2819,6 @@ msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
#: editor/script_create_dialog.cpp
msgid "Error!"
@@ -3528,10 +2929,6 @@ msgid "Delete Input"
msgstr ""
#: editor/plugins/animation_tree_editor_plugin.cpp
-msgid "Rename"
-msgstr ""
-
-#: editor/plugins/animation_tree_editor_plugin.cpp
msgid "Animation tree is valid."
msgstr ""
@@ -3587,64 +2984,185 @@ msgstr "Node Filter editieren"
msgid "Filters.."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing %d Triangles:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Free"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Triangle #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Contents:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Light Baker Setup:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "View Files"
+msgstr "Datei(en) öffnen"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve hostname:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing Geometry"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Fixing Lights"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connection error, please try again."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Making BVH"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't connect."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Light Octree"
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Can't connect to host:"
+msgstr "Verbindung zu Node:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response from host:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Octree Texture"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Transfer to Lightmaps:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, return code:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Allocating Texture #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Req. Failed."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Baking Triangle #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, too many redirects"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Post-Processing Texture #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Redirect Loop."
msgstr ""
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Bake!"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Bad download hash, assuming file has been tampered with."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Expected:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Got:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed sha256 hash check"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Asset Download Error:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Fetching:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Resolving.."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Connecting.."
+msgstr "Connections editieren"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Requesting.."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Error making request"
+msgstr "Szene kann nicht gespeichert werden."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Idle"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Retry"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download Error"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download for this asset is already in progress!"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "first"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "prev"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "next"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "last"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "All"
msgstr ""
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Reset the lightmap octree baking process (start over)."
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Plugins"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Sort:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Reverse"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Category:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Site:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Support.."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Official"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Testing"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Assets ZIP File"
msgstr ""
#: editor/plugins/camera_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
msgid "Preview"
msgstr ""
@@ -3687,11 +3205,15 @@ msgid "Edit CanvasItem"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Change Anchors"
+msgid "Anchors only"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Change Anchors and Margins"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom (%):"
+msgid "Change Anchors"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3744,59 +3266,72 @@ msgid "Pan Mode"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Lock the selected object in place (can't be moved)."
+msgid "Toggles snapping"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Unlock the selected object (can be moved)."
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Use Snap"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Makes sure the object's children are not selectable."
+msgid "Snapping options"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Restores the object's children's ability to be selected."
+msgid "Snap to grid"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Edit"
+msgid "Use Rotation Snap"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Use Snap"
+msgid "Configure Snap..."
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Show Grid"
+msgid "Snap Relative"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Rotation Snap"
+msgid "Use Pixel Snap"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap Relative"
+msgid "Smart snapping"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Configure Snap.."
+msgid "Snap to parent"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Pixel Snap"
+msgid "Snap to node anchor"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to node sides"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to other nodes"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Lock the selected object in place (can't be moved)."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Unlock the selected object (can be moved)."
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Skeleton.."
+msgid "Makes sure the object's children are not selectable."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Restores the object's children's ability to be selected."
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3825,11 +3360,16 @@ msgid "View"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Reset"
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Show Grid"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Set.."
+msgid "Show helpers"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Show rulers"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3841,7 +3381,7 @@ msgid "Frame Selection"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Anchor"
+msgid "Layout"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3866,11 +3406,20 @@ msgid "Clear Pose"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Set a Value"
+msgid "Drag pivot from mouse position"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#, fuzzy
+msgid "Set pivot at mouse position"
+msgstr "Ungültige Bilder löschen"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Multiply grid step by 2"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap (Pixels):"
+msgid "Divide grid step by 2"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3881,23 +3430,28 @@ msgstr ""
msgid "Adding %s..."
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Create Node"
msgstr "Node erstellen"
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Error instancing scene from %s"
msgstr "Fehler beim Instanzieren der %s Szene"
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "OK :("
msgstr "Okay :("
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "No parent to instance a child at."
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "This operation requires a single selected node."
msgstr "Bitte nur ein Node selektieren."
@@ -3912,45 +3466,6 @@ msgid ""
"Drag & drop + Alt : Change node type"
msgstr ""
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Create Poly"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly (Remove Point)"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Create a new polygon from scratch."
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-msgid ""
-"Edit existing polygon:\n"
-"LMB: Move Point.\n"
-"Ctrl+LMB: Split Segment.\n"
-"RMB: Erase Point."
-msgstr ""
-
#: editor/plugins/collision_polygon_editor_plugin.cpp
msgid "Create Poly3D"
msgstr ""
@@ -3960,14 +3475,6 @@ msgid "Set Handle"
msgstr ""
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Creating Mesh Library"
-msgstr ""
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Thumbnail.."
-msgstr ""
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Remove item %d?"
msgstr ""
@@ -3990,6 +3497,26 @@ msgid "Update from Scene"
msgstr ""
#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat0"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat1"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Ease in"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Ease out"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Smoothstep"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
msgid "Modify Curve Point"
msgstr ""
@@ -4068,22 +3595,18 @@ msgid "Create Occluder Polygon"
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Edit existing polygon:"
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "LMB: Move Point."
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Ctrl+LMB: Split Segment."
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "RMB: Erase Point."
msgstr ""
@@ -4184,6 +3707,10 @@ msgid "Create Outline"
msgstr ""
#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Mesh"
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Create Trimesh Static Body"
msgstr ""
@@ -4312,12 +3839,72 @@ msgstr ""
msgid "Populate"
msgstr ""
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Create Navigation Polygon"
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake!"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake the navigation mesh.\n"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Clear the navigation mesh."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Setting up Configuration..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Calculating grid size..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating heightfield..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Marking walkable triangles..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Constructing compact heightfield..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Eroding walkable area..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Partitioning..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating contours..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating polymesh..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Converting to native navigation mesh..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Navigation Mesh Generator Setup:"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Parsing Geometry..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Done!"
msgstr ""
#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Remove Poly And Point"
+msgid "Create Navigation Polygon"
msgstr ""
#: editor/plugins/particles_2d_editor_plugin.cpp
@@ -4496,16 +4083,19 @@ msgid "Curve Point #"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve Point Position"
-msgstr ""
+msgstr "Ungültige Bilder löschen"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve In Position"
-msgstr ""
+msgstr "Ungültige Bilder löschen"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve Out Position"
-msgstr ""
+msgstr "Ungültige Bilder löschen"
#: editor/plugins/path_editor_plugin.cpp
msgid "Split Path"
@@ -4564,6 +4154,14 @@ msgid "Scale Polygon"
msgstr ""
#: editor/plugins/polygon_2d_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Edit"
+msgstr ""
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Polygon->UV"
msgstr ""
@@ -4618,63 +4216,10 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/shader_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr ""
-#: editor/plugins/rich_text_editor_plugin.cpp
-msgid "Parse BBCode"
-msgstr ""
-
-#: editor/plugins/sample_editor_plugin.cpp
-msgid "Length:"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Open Sample File(s)"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "ERROR: Couldn't load sample!"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Add Sample"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Rename Sample"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Delete Sample"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "16 Bits"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "8 Bits"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Stereo"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Mono"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Format"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Pitch"
-msgstr ""
-
#: editor/plugins/script_editor_plugin.cpp
msgid "Clear Recent Files"
msgstr ""
@@ -4765,6 +4310,10 @@ msgstr ""
msgid "Close All"
msgstr ""
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+msgid "Run"
+msgstr ""
+
#: editor/plugins/script_editor_plugin.cpp
msgid "Toggle Scripts Panel"
msgstr ""
@@ -4793,7 +4342,8 @@ msgstr ""
msgid "Break"
msgstr ""
-#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+#: editor/script_editor_debugger.cpp
msgid "Continue"
msgstr ""
@@ -4806,18 +4356,6 @@ msgid "Debug with external editor"
msgstr ""
#: editor/plugins/script_editor_plugin.cpp
-msgid "Window"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Left"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Right"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
msgid "Open Godot online documentation"
msgstr ""
@@ -4899,8 +4437,9 @@ msgid "Cut"
msgstr ""
#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr ""
@@ -5165,10 +4704,6 @@ msgid "View Plane Transform."
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Scaling to %s%%."
-msgstr ""
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rotating %s degrees."
msgstr ""
@@ -5185,10 +4720,6 @@ msgid "Top View."
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Top"
-msgstr ""
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rear View."
msgstr ""
@@ -5420,6 +4951,10 @@ msgid "Transform"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Configure Snap.."
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Local Coords"
msgstr ""
@@ -5565,6 +5100,10 @@ msgid "Speed (FPS):"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Loop"
+msgstr ""
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Animation Frames"
msgstr ""
@@ -5577,11 +5116,12 @@ msgid "Insert Empty (After)"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Up"
-msgstr ""
+#, fuzzy
+msgid "Move (Before)"
+msgstr "Node(s) entfernen"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Down"
+msgid "Move (After)"
msgstr ""
#: editor/plugins/style_box_editor_plugin.cpp
@@ -5660,7 +5200,11 @@ msgid "Remove All"
msgstr "Ungültige Bilder löschen"
#: editor/plugins/theme_editor_plugin.cpp
-msgid "Theme"
+msgid "Edit theme.."
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Theme editing menu."
msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
@@ -5745,6 +5289,10 @@ msgid "Style"
msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
+msgid "Font"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
msgid "Color"
msgstr ""
@@ -5793,7 +5341,7 @@ msgid "Mirror Y"
msgstr ""
#: editor/plugins/tile_map_editor_plugin.cpp
-msgid "Bucket"
+msgid "Paint Tile"
msgstr ""
#: editor/plugins/tile_map_editor_plugin.cpp
@@ -5857,6 +5405,10 @@ msgid "Delete preset '%s'?"
msgstr ""
#: editor/project_export.cpp
+msgid "Export templates for this platform are missing/corrupted: "
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Presets"
msgstr ""
@@ -5930,33 +5482,60 @@ msgid "Export templates for this platform are missing:"
msgstr ""
#: editor/project_export.cpp
+msgid "Export templates for this platform are missing/corrupted:"
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Export With Debug"
msgstr ""
#: editor/project_manager.cpp
-msgid "Invalid project path, the path must exist!"
-msgstr "Ungültiger Projektpfad, Pfad existiert nicht!"
+msgid "The path does not exist."
+msgstr ""
#: editor/project_manager.cpp
#, fuzzy
-msgid "Invalid project path, project.godot must not exist."
-msgstr "Ungültiger Projektpfad, engine.cfg vorhanden!"
+msgid "Please choose a 'project.godot' file."
+msgstr "Bitte ausserhalb des Projekt Verzeichnis exportieren!"
#: editor/project_manager.cpp
-#, fuzzy
-msgid "Invalid project path, project.godot must exist."
-msgstr "Ungültiger Projektpfad, engine.cfg nicht vorhanden!"
+msgid ""
+"Your project will be created in a non empty folder (you might want to create "
+"a new folder)."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Please choose a folder that does not contain a 'project.godot' file."
+msgstr ""
#: editor/project_manager.cpp
msgid "Imported Project"
msgstr "Importierte Projekte"
#: editor/project_manager.cpp
+msgid " "
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "It would be a good idea to name your project."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Invalid project path (changed anything?)."
msgstr "Ungültiger Projektpfad, (wurde was geändert?)!"
#: editor/project_manager.cpp
#, fuzzy
+msgid "Couldn't get project.godot in project path."
+msgstr "Die engine.cfg kann im Projektverzeichnis nicht erstellt werden."
+
+#: editor/project_manager.cpp
+#, fuzzy
+msgid "Couldn't edit project.godot in project path."
+msgstr "Die engine.cfg kann im Projektverzeichnis nicht erstellt werden."
+
+#: editor/project_manager.cpp
+#, fuzzy
msgid "Couldn't create project.godot in project path."
msgstr "Die engine.cfg kann im Projektverzeichnis nicht erstellt werden."
@@ -5965,35 +5544,46 @@ msgid "The following files failed extraction from package:"
msgstr ""
#: editor/project_manager.cpp
-msgid "Import Existing Project"
-msgstr "Existierendes Projekt importieren"
+#, fuzzy
+msgid "Rename Project"
+msgstr "Neues Projekt erstellen"
#: editor/project_manager.cpp
-msgid "Project Path (Must Exist):"
-msgstr "Projektpfad (muss existieren):"
+#, fuzzy
+msgid "Couldn't get project.godot in the project path."
+msgstr "Die engine.cfg kann im Projektverzeichnis nicht erstellt werden."
#: editor/project_manager.cpp
-msgid "Project Name:"
-msgstr "Projektname:"
+msgid "New Game Project"
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Import Existing Project"
+msgstr "Existierendes Projekt importieren"
#: editor/project_manager.cpp
msgid "Create New Project"
msgstr "Neues Projekt erstellen"
#: editor/project_manager.cpp
-msgid "Project Path:"
+msgid "Install Project:"
msgstr ""
#: editor/project_manager.cpp
-msgid "Install Project:"
-msgstr ""
+msgid "Project Name:"
+msgstr "Projektname:"
#: editor/project_manager.cpp
-msgid "Browse"
+#, fuzzy
+msgid "Create folder"
+msgstr "Node erstellen"
+
+#: editor/project_manager.cpp
+msgid "Project Path:"
msgstr ""
#: editor/project_manager.cpp
-msgid "New Game Project"
+msgid "Browse"
msgstr ""
#: editor/project_manager.cpp
@@ -6005,6 +5595,11 @@ msgid "Unnamed Project"
msgstr ""
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Can't open project"
+msgstr "Neues Projekt erstellen"
+
+#: editor/project_manager.cpp
msgid "Are you sure to open more than one project?"
msgstr ""
@@ -6031,16 +5626,18 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
-"You are about the scan %s folders for existing Godot projects. Do you "
-"confirm?"
+"Language changed.\n"
+"The UI will update next time the editor or project manager starts."
msgstr ""
#: editor/project_manager.cpp
-msgid "Project List"
+msgid ""
+"You are about the scan %s folders for existing Godot projects. Do you "
+"confirm?"
msgstr ""
#: editor/project_manager.cpp
-msgid "Run"
+msgid "Project List"
msgstr ""
#: editor/project_manager.cpp
@@ -6065,6 +5662,10 @@ msgid "Exit"
msgstr ""
#: editor/project_manager.cpp
+msgid "Restart Now"
+msgstr ""
+
+#: editor/project_manager.cpp
#, fuzzy
msgid "Can't run project"
msgstr "Neues Projekt erstellen"
@@ -6102,17 +5703,14 @@ msgid "Add Input Action Event"
msgstr ""
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Meta+"
msgstr ""
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Shift+"
msgstr ""
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Alt+"
msgstr ""
@@ -6174,7 +5772,7 @@ msgstr "Typ ändern"
msgid "Joypad Axis Index:"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Axis"
msgstr ""
@@ -6194,31 +5792,31 @@ msgstr ""
msgid "Add Event"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Device"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Button"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Left Button."
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Right Button."
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Middle Button."
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Up."
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Down."
msgstr ""
@@ -6227,7 +5825,7 @@ msgid "Add Global Property"
msgstr ""
#: editor/project_settings_editor.cpp
-msgid "Select an setting item first!"
+msgid "Select a setting item first!"
msgstr ""
#: editor/project_settings_editor.cpp
@@ -6244,6 +5842,15 @@ msgid "Delete Item"
msgstr "Node(s) löschen"
#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Can't contain '/' or ':'"
+msgstr "Verbindung zu Node:"
+
+#: editor/project_settings_editor.cpp
+msgid "Already existing"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "Error saving settings."
msgstr ""
@@ -6285,6 +5892,15 @@ msgstr ""
#: editor/project_settings_editor.cpp
#, fuzzy
+msgid "Changed Locale Filter"
+msgstr "Typ ändern"
+
+#: editor/project_settings_editor.cpp
+msgid "Changed Locale Filter Mode"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
msgid "Project Settings (project.godot)"
msgstr "Projekteinstellungen"
@@ -6345,6 +5961,27 @@ msgid "Locale"
msgstr ""
#: editor/project_settings_editor.cpp
+msgid "Locales Filter"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Show all locales"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Show only selected locales"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Filter mode:"
+msgstr "Node erstellen"
+
+#: editor/project_settings_editor.cpp
+msgid "Locales:"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "AutoLoad"
msgstr ""
@@ -6395,10 +6032,19 @@ msgid "New Script"
msgstr "Script hinzufügen"
#: editor/property_editor.cpp
+msgid "Make Unique"
+msgstr ""
+
+#: editor/property_editor.cpp
msgid "Show in File System"
msgstr ""
#: editor/property_editor.cpp
+#, fuzzy
+msgid "Convert To %s"
+msgstr "Verbindung zu Node:"
+
+#: editor/property_editor.cpp
msgid "Error loading file: Not a resource!"
msgstr ""
@@ -6437,6 +6083,10 @@ msgid "Select Property"
msgstr ""
#: editor/property_selector.cpp
+msgid "Select Virtual Method"
+msgstr ""
+
+#: editor/property_selector.cpp
msgid "Select Method"
msgstr ""
@@ -6464,26 +6114,6 @@ msgstr ""
msgid "Reparent"
msgstr ""
-#: editor/resources_dock.cpp
-msgid "Create New Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Open Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Save Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Resource Tools"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Make Local"
-msgstr ""
-
#: editor/run_settings_dialog.cpp
msgid "Run Mode:"
msgstr ""
@@ -6611,14 +6241,6 @@ msgid "Sub-Resources:"
msgstr ""
#: editor/scene_tree_dock.cpp
-msgid "Edit Groups"
-msgstr ""
-
-#: editor/scene_tree_dock.cpp
-msgid "Edit Connections"
-msgstr "Connections editieren"
-
-#: editor/scene_tree_dock.cpp
msgid "Clear Inheritance"
msgstr ""
@@ -6806,6 +6428,15 @@ msgid "Invalid base path"
msgstr ""
#: editor/script_create_dialog.cpp
+msgid "Directory of the same name exists"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
+#, fuzzy
+msgid "File exists, will be reused"
+msgstr "Datei existiert, Ãœberschreiben?"
+
+#: editor/script_create_dialog.cpp
msgid "Invalid extension"
msgstr ""
@@ -6847,6 +6478,10 @@ msgid "Load existing script file"
msgstr ""
#: editor/script_create_dialog.cpp
+msgid "Language"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
msgid "Inherits"
msgstr ""
@@ -6889,6 +6524,10 @@ msgid "Function:"
msgstr ""
#: editor/script_editor_debugger.cpp
+msgid "Pick one or more items from the list to display the graph."
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
msgid "Errors"
msgstr ""
@@ -6969,6 +6608,10 @@ msgid "Type"
msgstr ""
#: editor/script_editor_debugger.cpp
+msgid "Format"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
msgid "Usage"
msgstr ""
@@ -7044,12 +6687,28 @@ msgstr ""
msgid "Change Probe Extents"
msgstr ""
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Library"
+msgstr ""
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Status"
+msgstr ""
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Libraries: "
+msgstr ""
+
+#: modules/gdnative/register_types.cpp
+msgid "GDNative"
+msgstr ""
+
#: modules/gdscript/gd_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Invalid type argument to convert(), use TYPE_* constants."
msgstr ""
-#: modules/gdscript/gd_functions.cpp
+#: modules/gdscript/gd_functions.cpp modules/mono/glue/glue_header.h
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Not enough bytes for decoding bytes, or invalid format."
msgstr ""
@@ -7099,10 +6758,6 @@ msgid "GridMap Duplicate Selection"
msgstr ""
#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "GridMap Paint"
-msgstr ""
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Snap View"
msgstr ""
@@ -7197,13 +6852,8 @@ msgstr "Projekteinstellungen"
msgid "Pick Distance:"
msgstr ""
-#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
-msgid "Tiles"
-msgstr "Datei(en) öffnen"
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "Areas"
+#: modules/mono/editor/mono_bottom_panel.cpp
+msgid "Builds"
msgstr ""
#: modules/visual_script/visual_script.cpp
@@ -7406,10 +7056,18 @@ msgid "Return"
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
+msgid "Call"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
msgid "Get"
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
+msgid "Script already has function '%s'"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
#, fuzzy
msgid "Change Input Value"
msgstr "Typ ändern"
@@ -7795,6 +7453,12 @@ msgid ""
"order for AnimatedSprite3D to display frames."
msgstr ""
+#: scene/3d/vehicle_body.cpp
+msgid ""
+"VehicleWheel serves to provide a wheel system to a VehicleBody. Please use "
+"it as a child of a VehicleBody."
+msgstr ""
+
#: scene/gui/color_picker.cpp
#, fuzzy
msgid "Raw Mode"
@@ -7805,6 +7469,10 @@ msgid "Add current color as a preset"
msgstr ""
#: scene/gui/dialogs.cpp
+msgid "Cancel"
+msgstr "Abbrechen"
+
+#: scene/gui/dialogs.cpp
msgid "Alert!"
msgstr "Alert!"
@@ -7812,10 +7480,6 @@ msgstr "Alert!"
msgid "Please Confirm..."
msgstr "Bitte bestätigen..."
-#: scene/gui/input_action.cpp
-msgid "Ctrl+"
-msgstr ""
-
#: scene/gui/popup.cpp
msgid ""
"Popups will hide by default unless you call popup() or any of the popup*() "
@@ -7844,6 +7508,71 @@ msgid ""
"texture to some node for display."
msgstr ""
+#: scene/resources/dynamic_font.cpp
+#, fuzzy
+msgid "Error initializing FreeType."
+msgstr "Fehler bei der FreeType Inizialisierung."
+
+#: scene/resources/dynamic_font.cpp
+msgid "Unknown font format."
+msgstr ""
+
+#: scene/resources/dynamic_font.cpp
+msgid "Error loading font."
+msgstr ""
+
+#: scene/resources/dynamic_font.cpp
+msgid "Invalid font size."
+msgstr ""
+
+#~ msgid "Surface %d"
+#~ msgstr "Oberfläche %d"
+
+#~ msgid "Import Textures for Atlas (2D)"
+#~ msgstr "Importiere Texturen für Atlas (2D)"
+
+#~ msgid "Import Large Textures (2D)"
+#~ msgstr "Importiere Große Texturen (2D)"
+
+#~ msgid "Import Textures for 2D"
+#~ msgstr "Importiere Texturen für 2D"
+
+#~ msgid "2D Texture"
+#~ msgstr "2D-Textur"
+
+#, fuzzy
+#~ msgid ""
+#~ "NOTICE: Importing 2D textures is not mandatory. Just copy png/jpg files "
+#~ "to the project."
+#~ msgstr ""
+#~ "MERKE: Das importieren von 2D Texturen ist nicht zwingend notwendig. "
+#~ "Kopiere einfach png/jpg Dateien in das Projekt."
+
+#, fuzzy
+#~ msgid "Add to Project (project.godot)"
+#~ msgstr "Zum Projekt hinzufügen (engine.cfg)"
+
+#~ msgid "Invalid project path, the path must exist!"
+#~ msgstr "Ungültiger Projektpfad, Pfad existiert nicht!"
+
+#, fuzzy
+#~ msgid "Invalid project path, project.godot must not exist."
+#~ msgstr "Ungültiger Projektpfad, engine.cfg vorhanden!"
+
+#, fuzzy
+#~ msgid "Invalid project path, project.godot must exist."
+#~ msgstr "Ungültiger Projektpfad, engine.cfg nicht vorhanden!"
+
+#~ msgid "Project Path (Must Exist):"
+#~ msgstr "Projektpfad (muss existieren):"
+
+#~ msgid "Edit Connections"
+#~ msgstr "Connections editieren"
+
+#, fuzzy
+#~ msgid "Tiles"
+#~ msgstr "Datei(en) öffnen"
+
#, fuzzy
#~ msgid "Error creating the signature object."
#~ msgstr "Fehler beim Schreiben des Projekts PCK!"
@@ -7879,9 +7608,6 @@ msgstr ""
#~ "SampleLibrary Ressource in der 'samples' Eigenschaft erzeugt oder "
#~ "definiert werden."
-#~ msgid "Please export outside the project folder!"
-#~ msgstr "Bitte ausserhalb des Projekt Verzeichnis exportieren!"
-
#~ msgid "Error exporting project!"
#~ msgstr "Fehler beim Exportieren des Projekts!"
diff --git a/editor/translations/editor.pot b/editor/translations/editor.pot
index a1247ab925..efddb63796 100644
--- a/editor/translations/editor.pot
+++ b/editor/translations/editor.pot
@@ -186,10 +186,9 @@ msgid "Create %d NEW tracks and insert keys?"
msgstr ""
#: editor/animation_editor.cpp editor/create_dialog.cpp
-#: editor/editor_audio_buses.cpp
+#: editor/editor_audio_buses.cpp editor/plugins/abstract_polygon_2d_editor.cpp
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
#: editor/plugins/mesh_instance_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp editor/project_manager.cpp
#: editor/script_create_dialog.cpp
msgid "Create"
@@ -351,261 +350,6 @@ msgstr ""
msgid "Change Array Value"
msgstr ""
-#: editor/asset_library_editor_plugin.cpp
-msgid "Free"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_plugin_settings.cpp
-msgid "Version:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Contents:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "View Files"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_help.cpp editor/property_selector.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Description:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-#: editor/project_manager.cpp
-msgid "Install"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/call_dialog.cpp
-#: editor/connections_dialog.cpp editor/export_template_manager.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-#: editor/project_settings_editor.cpp editor/property_editor.cpp
-#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Close"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve hostname:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Connection error, please try again."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't connect."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't connect to host:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response from host:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Request failed, return code:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Req. Failed."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Request failed, too many redirects"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Redirect Loop."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Bad download hash, assuming file has been tampered with."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Expected:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Got:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Asset Download Error:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-msgid "Success!"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Fetching:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Resolving.."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Connecting.."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Requesting.."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Error making request"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Idle"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Retry"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Download Error"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Download for this asset is already in progress!"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "first"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "prev"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "next"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "last"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "All"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
-#: editor/settings_config_dialog.cpp
-msgid "Search:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/code_editor.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Search"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/project_manager.cpp
-msgid "Import"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Plugins"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Sort:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Reverse"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Category:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Site:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Support.."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Official"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-msgid "Community"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Testing"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Assets ZIP File"
-msgstr ""
-
-#: editor/call_dialog.cpp
-msgid "Method List For '%s':"
-msgstr ""
-
-#: editor/call_dialog.cpp modules/visual_script/visual_script_editor.cpp
-msgid "Call"
-msgstr ""
-
-#: editor/call_dialog.cpp
-msgid "Method List:"
-msgstr ""
-
-#: editor/call_dialog.cpp
-msgid "Arguments:"
-msgstr ""
-
-#: editor/call_dialog.cpp
-msgid "Return:"
-msgstr ""
-
#: editor/code_editor.cpp
msgid "Go to Line"
msgstr ""
@@ -642,6 +386,14 @@ msgstr ""
msgid "Selection Only"
msgstr ""
+#: editor/code_editor.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
+msgid "Search"
+msgstr ""
+
#: editor/code_editor.cpp editor/editor_help.cpp
msgid "Find"
msgstr ""
@@ -674,11 +426,11 @@ msgstr ""
msgid "Skip"
msgstr ""
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom In"
msgstr ""
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom Out"
msgstr ""
@@ -745,6 +497,20 @@ msgstr ""
msgid "Oneshot"
msgstr ""
+#: editor/connections_dialog.cpp editor/dependency_editor.cpp
+#: editor/export_template_manager.cpp
+#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Close"
+msgstr ""
+
#: editor/connections_dialog.cpp
msgid "Connect"
msgstr ""
@@ -770,7 +536,7 @@ msgstr ""
msgid "Disconnect"
msgstr ""
-#: editor/connections_dialog.cpp editor/node_dock.cpp
+#: editor/connections_dialog.cpp editor/editor_help.cpp editor/node_dock.cpp
msgid "Signals"
msgstr ""
@@ -787,12 +553,25 @@ msgstr ""
msgid "Recent:"
msgstr ""
+#: editor/create_dialog.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/quick_open.cpp editor/settings_config_dialog.cpp
+msgid "Search:"
+msgstr ""
+
#: editor/create_dialog.cpp editor/editor_help.cpp
#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/quick_open.cpp
msgid "Matches:"
msgstr ""
+#: editor/create_dialog.cpp editor/editor_help.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/property_selector.cpp
+#: editor/script_editor_debugger.cpp
+msgid "Description:"
+msgstr ""
+
#: editor/dependency_editor.cpp
msgid "Search Replacement For:"
msgstr ""
@@ -848,6 +627,10 @@ msgid "Owners Of:"
msgstr ""
#: editor/dependency_editor.cpp
+msgid "Remove selected files from the project? (no undo)"
+msgstr ""
+
+#: editor/dependency_editor.cpp
msgid ""
"The files being removed are required by other resources in order for them to "
"work.\n"
@@ -855,7 +638,7 @@ msgid ""
msgstr ""
#: editor/dependency_editor.cpp
-msgid "Remove selected files from the project? (no undo)"
+msgid "Cannot remove:\n"
msgstr ""
#: editor/dependency_editor.cpp
@@ -922,10 +705,6 @@ msgid "Godot Engine contributors"
msgstr ""
#: editor/editor_about.cpp
-msgid "Authors"
-msgstr ""
-
-#: editor/editor_about.cpp
msgid "Project Founders"
msgstr ""
@@ -942,6 +721,38 @@ msgid "Developers"
msgstr ""
#: editor/editor_about.cpp
+msgid "Authors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Platinum Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Gold Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Mini Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Gold Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Silver Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Bronze Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
msgid "License"
msgstr ""
@@ -982,6 +793,16 @@ msgid "Package Installed Successfully!"
msgstr ""
#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Success!"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/project_manager.cpp
+msgid "Install"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
msgid "Package Installer"
msgstr ""
@@ -1030,10 +851,6 @@ msgid "Audio Bus, Drag and Drop to rearrange."
msgstr ""
#: editor/editor_audio_buses.cpp
-msgid "Bus options"
-msgstr ""
-
-#: editor/editor_audio_buses.cpp
msgid "Solo"
msgstr ""
@@ -1045,12 +862,20 @@ msgstr ""
msgid "Bypass"
msgstr ""
+#: editor/editor_audio_buses.cpp
+msgid "Bus options"
+msgstr ""
+
#: editor/editor_audio_buses.cpp editor/plugins/tile_map_editor_plugin.cpp
#: editor/scene_tree_dock.cpp
msgid "Duplicate"
msgstr ""
#: editor/editor_audio_buses.cpp
+msgid "Reset Volume"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
msgid "Delete Effect"
msgstr ""
@@ -1071,6 +896,10 @@ msgid "Duplicate Audio Bus"
msgstr ""
#: editor/editor_audio_buses.cpp
+msgid "Reset Bus Volume"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
msgid "Move Audio Bus"
msgstr ""
@@ -1102,7 +931,8 @@ msgstr ""
msgid "Create a new Bus Layout."
msgstr ""
-#: editor/editor_audio_buses.cpp editor/script_create_dialog.cpp
+#: editor/editor_audio_buses.cpp editor/property_editor.cpp
+#: editor/script_create_dialog.cpp
msgid "Load"
msgstr ""
@@ -1192,7 +1022,7 @@ msgid "Rearrange Autoloads"
msgstr ""
#: editor/editor_autoload_settings.cpp editor/editor_file_dialog.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp scene/gui/file_dialog.cpp
+#: scene/gui/file_dialog.cpp
msgid "Path:"
msgstr ""
@@ -1200,9 +1030,7 @@ msgstr ""
msgid "Node Name:"
msgstr ""
-#: editor/editor_autoload_settings.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp editor/project_manager.cpp
+#: editor/editor_autoload_settings.cpp editor/project_manager.cpp
msgid "Name"
msgstr ""
@@ -1235,18 +1063,19 @@ msgid "Choose a Directory"
msgstr ""
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Create Folder"
msgstr ""
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: editor/editor_plugin_settings.cpp editor/plugins/theme_editor_plugin.cpp
-#: editor/project_export.cpp scene/gui/file_dialog.cpp
+#: editor/editor_plugin_settings.cpp editor/filesystem_dock.cpp
+#: editor/plugins/theme_editor_plugin.cpp editor/project_export.cpp
+#: scene/gui/file_dialog.cpp
msgid "Name:"
msgstr ""
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Could not create folder."
msgstr ""
@@ -1266,30 +1095,6 @@ msgstr ""
msgid "Template file not found:\n"
msgstr ""
-#: editor/editor_export.cpp
-msgid "Added:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Removed:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Error saving atlas:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Could not save atlas subtexture:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Exporting for %s"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Setting Up.."
-msgstr ""
-
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "File Exists, Overwrite?"
msgstr ""
@@ -1374,6 +1179,10 @@ msgstr ""
msgid "Move Favorite Down"
msgstr ""
+#: editor/editor_file_dialog.cpp
+msgid "Go to parent folder"
+msgstr ""
+
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Directories & Files:"
msgstr ""
@@ -1388,10 +1197,6 @@ msgid "File:"
msgstr ""
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
-msgid "Filter:"
-msgstr ""
-
-#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Must use a valid extension."
msgstr ""
@@ -1416,6 +1221,10 @@ msgstr ""
msgid "Search Classes"
msgstr ""
+#: editor/editor_help.cpp editor/plugins/spatial_editor_plugin.cpp
+msgid "Top"
+msgstr ""
+
#: editor/editor_help.cpp editor/property_editor.cpp
msgid "Class:"
msgstr ""
@@ -1432,15 +1241,27 @@ msgstr ""
msgid "Brief Description:"
msgstr ""
+#: editor/editor_help.cpp
+msgid "Members"
+msgstr ""
+
#: editor/editor_help.cpp modules/visual_script/visual_script_editor.cpp
msgid "Members:"
msgstr ""
#: editor/editor_help.cpp
+msgid "Public Methods"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Public Methods:"
msgstr ""
#: editor/editor_help.cpp
+msgid "GUI Theme Items"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "GUI Theme Items:"
msgstr ""
@@ -1449,6 +1270,10 @@ msgid "Signals:"
msgstr ""
#: editor/editor_help.cpp
+msgid "Enumerations"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Enumerations:"
msgstr ""
@@ -1457,18 +1282,46 @@ msgid "enum "
msgstr ""
#: editor/editor_help.cpp
+msgid "Constants"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Constants:"
msgstr ""
#: editor/editor_help.cpp
+msgid "Description"
+msgstr ""
+
+#: editor/editor_help.cpp
+msgid "Properties"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Property Description:"
msgstr ""
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this property. Please help us by "
+"[color=$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+
+#: editor/editor_help.cpp
+msgid "Methods"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Method Description:"
msgstr ""
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this method. Please help us by [color="
+"$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Search Text"
msgstr ""
@@ -1477,24 +1330,21 @@ msgid "Output:"
msgstr ""
#: editor/editor_log.cpp editor/plugins/animation_tree_editor_plugin.cpp
-#: editor/plugins/rich_text_editor_plugin.cpp editor/property_editor.cpp
-#: editor/script_editor_debugger.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/property_editor.cpp editor/script_editor_debugger.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Clear"
msgstr ""
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Error saving resource!"
msgstr ""
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Save Resource As.."
msgstr ""
-#: editor/editor_node.cpp editor/export_template_manager.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "I see.."
msgstr ""
@@ -1511,6 +1361,26 @@ msgid "Error while saving."
msgstr ""
#: editor/editor_node.cpp
+msgid "Can't open '%s'."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Error while parsing '%s'."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Unexpected end of file '%s'."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Missing '%s' or its dependencies."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Error while loading '%s'."
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Saving Scene"
msgstr ""
@@ -1568,6 +1438,33 @@ msgid "Restored default layout to base settings."
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was imported, so it's not editable.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was instanced or inherited.\n"
+"Changes to it will not be kept when saving the current scene."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource was imported, so it's not editable. Change its settings in the "
+"import panel and then re-import."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This scene was imported, so changes to it will not be kept.\n"
+"Instancing it or inheriting will allow making changes to it.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Copy Params"
msgstr ""
@@ -1729,23 +1626,34 @@ msgid "Save changes the following scene(s) before opening Project Manager?"
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"This option is deprecated. Situations where refresh must be forced are now "
+"considered a bug. Please report."
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Pick a Main Scene"
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to enable addon plugin at: '"
+msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
msgstr ""
#: editor/editor_node.cpp
-msgid "' parsing of config failed."
+msgid "Unable to load addon script from path: '%s'."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/"
+msgid ""
+"Unable to load addon script from path: '%s' Base type is not EditorPlugin."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to load addon script from path: '"
+msgid "Unable to load addon script from path: '%s' Script is not in tool mode."
msgstr ""
#: editor/editor_node.cpp
@@ -1755,7 +1663,7 @@ msgid ""
msgstr ""
#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/scene_tree_dock.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Ugh"
msgstr ""
@@ -1766,11 +1674,11 @@ msgid ""
msgstr ""
#: editor/editor_node.cpp
-msgid "Error loading scene."
+msgid "Scene '%s' has broken dependencies:"
msgstr ""
#: editor/editor_node.cpp
-msgid "Scene '%s' has broken dependencies:"
+msgid "Clear Recent Scenes"
msgstr ""
#: editor/editor_node.cpp
@@ -1806,7 +1714,7 @@ msgstr ""
msgid "Toggle distraction-free mode."
msgstr ""
-#: editor/editor_node.cpp editor/io_plugins/editor_scene_import_plugin.cpp
+#: editor/editor_node.cpp
msgid "Scene"
msgstr ""
@@ -2025,6 +1933,10 @@ msgstr ""
msgid "Issue Tracker"
msgstr ""
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+msgid "Community"
+msgstr ""
+
#: editor/editor_node.cpp
msgid "About"
msgstr ""
@@ -2033,7 +1945,7 @@ msgstr ""
msgid "Play the project."
msgstr ""
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Play"
msgstr ""
@@ -2049,7 +1961,7 @@ msgstr ""
msgid "Stop the scene."
msgstr ""
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Stop"
msgstr ""
@@ -2122,6 +2034,15 @@ msgid "Object properties."
msgstr ""
#: editor/editor_node.cpp
+msgid "Changes may be lost!"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Import"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "FileSystem"
msgstr ""
@@ -2137,14 +2058,6 @@ msgstr ""
msgid "Don't Save"
msgstr ""
-#: editor/editor_node.cpp editor/editor_reimport_dialog.cpp
-msgid "Re-Import"
-msgstr ""
-
-#: editor/editor_node.cpp editor/editor_plugin_settings.cpp
-msgid "Update"
-msgstr ""
-
#: editor/editor_node.cpp
msgid "Import Templates From ZIP File"
msgstr ""
@@ -2205,11 +2118,28 @@ msgstr ""
msgid "Open the previous Editor"
msgstr ""
+#: editor/editor_plugin.cpp
+msgid "Creating Mesh Previews"
+msgstr ""
+
+#: editor/editor_plugin.cpp
+msgid "Thumbnail.."
+msgstr ""
+
#: editor/editor_plugin_settings.cpp
msgid "Installed Plugins:"
msgstr ""
#: editor/editor_plugin_settings.cpp
+msgid "Update"
+msgstr ""
+
+#: editor/editor_plugin_settings.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Version:"
+msgstr ""
+
+#: editor/editor_plugin_settings.cpp
msgid "Author:"
msgstr ""
@@ -2242,7 +2172,7 @@ msgid "Frame %"
msgstr ""
#: editor/editor_profiler.cpp
-msgid "Fixed Frame %"
+msgid "Physics Frame %"
msgstr ""
#: editor/editor_profiler.cpp editor/script_editor_debugger.cpp
@@ -2261,26 +2191,6 @@ msgstr ""
msgid "Frame #:"
msgstr ""
-#: editor/editor_reimport_dialog.cpp
-msgid "Please wait for scan to complete."
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Current scene must be saved to re-import."
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Save & Re-Import"
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Importing"
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Import Changed Resources"
-msgstr ""
-
#: editor/editor_run_native.cpp
msgid "Select device from the list"
msgstr ""
@@ -2390,10 +2300,6 @@ msgid "Importing:"
msgstr ""
#: editor/export_template_manager.cpp
-msgid "Loading Export Templates"
-msgstr ""
-
-#: editor/export_template_manager.cpp
msgid "Current Version:"
msgstr ""
@@ -2426,9 +2332,17 @@ msgid "Cannot navigate to '"
msgstr ""
#: editor/filesystem_dock.cpp
+msgid "View items as a grid of thumbnails"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "View items as a list"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
msgid ""
"\n"
-"Status: Needs Re-Import"
+"Status: Import of file failed. Please fix file and reimport manually."
msgstr ""
#: editor/filesystem_dock.cpp
@@ -2438,87 +2352,87 @@ msgid ""
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Same source and destination files, doing nothing."
+msgid "Cannot move/rename resources root."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Target file exists, can't overwrite. Delete first."
+msgid "Cannot move a folder into itself.\n"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Same source and destination paths, doing nothing."
+msgid "Error moving:\n"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Can't move directories to within themselves."
+msgid "Unable to update dependencies:\n"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Can't rename deps for:\n"
+msgid "No name provided"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Error moving file:\n"
+msgid "Provided name contains invalid characters"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Error moving dir:\n"
+msgid "No name provided."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Can't operate on '..'"
+msgid "Name contains invalid characters."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Pick New Name and Location For:"
+msgid "A file or folder with this name already exists."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "No files selected!"
+msgid "Renaming file:"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Expand all"
+msgid "Renaming folder:"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Collapse all"
+msgid "Expand all"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Show In File Manager"
+msgid "Collapse all"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Instance"
+msgid "Copy Path"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Edit Dependencies.."
+msgid "Rename.."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "View Owners.."
+msgid "Move To.."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Copy Path"
+msgid "New Folder.."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Rename or Move.."
+msgid "Show In File Manager"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Move To.."
+msgid "Instance"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Info"
+msgid "Edit Dependencies.."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Re-Import.."
+msgid "View Owners.."
msgstr ""
#: editor/filesystem_dock.cpp
@@ -2551,6 +2465,11 @@ msgstr ""
msgid "Move"
msgstr ""
+#: editor/filesystem_dock.cpp editor/plugins/animation_tree_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Rename"
+msgstr ""
+
#: editor/groups_editor.cpp
msgid "Add to Group"
msgstr ""
@@ -2564,6 +2483,10 @@ msgid "Import as Single Scene"
msgstr ""
#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
msgid "Import with Separate Materials"
msgstr ""
@@ -2576,6 +2499,18 @@ msgid "Import with Separate Objects+Materials"
msgstr ""
#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Materials+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Materials+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
msgid "Import as Multiple Scenes"
msgstr ""
@@ -2584,38 +2519,31 @@ msgid "Import as Multiple Scenes+Materials"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Import Scene"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Importing Scene.."
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Running Custom Script.."
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Couldn't load post-import script:"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Invalid/broken script for post-import (check console):"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Error running post-import script:"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Saving.."
msgstr ""
@@ -2643,579 +2571,54 @@ msgstr ""
msgid "Reimport"
msgstr ""
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "No bit masks to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path is empty."
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must be a complete resource path."
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must exist."
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Save path is empty!"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Import BitMasks"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s):"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Target Path:"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Accept"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Bit Mask"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No source font file!"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No target font resource!"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"Invalid file extension.\n"
-"Please use .font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Can't load/process source font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Couldn't save font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font Size:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Dest Resource:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "The quick brown fox jumps over the lazy dog."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Test:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Options:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Font Import"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"This file is already a Godot font file, please supply a BMFont type file "
-"instead."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Failed opening as BMFont file."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error initializing FreeType."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Unknown font format."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error loading font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Invalid font size."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Invalid font custom source."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/plugins/theme_editor_plugin.cpp
-msgid "Font"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "No meshes to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Single Mesh Import"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Source Mesh(es):"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/plugins/mesh_instance_editor_plugin.cpp
-msgid "Mesh"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Surface %d"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "No samples to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Import Audio Samples"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Source Sample(s):"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Audio Sample"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "New Clip"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Animation Options"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Flags"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Bake FPS:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Optimizer"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Linear Error"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angular Error"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angle"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Clips"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Start(s)"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "End(s)"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Loop"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Filters"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source path is empty."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't load post-import script."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Invalid/broken script for post-import."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Error importing scene."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import 3D Scene"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source Scene:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Same as Target Scene"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Shared"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Target Texture Folder:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Post-Process Script:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Custom Root Node Type:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Auto"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Root Node Name:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "The Following Files are Missing:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Anyway"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp scene/gui/dialogs.cpp
-msgid "Cancel"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import & Open"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Edited scene has not been saved, open imported scene anyway?"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Image:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Can't import a file over itself:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't localize path: %s (already local)"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "3D Scene Animation"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Uncompressed"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossless (PNG)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossy (WebP)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress (VRAM)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Format"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Compression Quality (WebP):"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Options"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Please specify some files!"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "At least one file needed for Atlas."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Error importing:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Only one file is required for large texture."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Max Texture Size:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for Atlas (2D)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cell Size:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Large Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Textures (2D)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture"
+#: editor/multi_node_edit.cpp
+msgid "MultiNode Set"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Base Atlas Texture"
+#: editor/node_dock.cpp
+msgid "Groups"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s)"
+#: editor/node_dock.cpp
+msgid "Select a Node to edit Signals and Groups."
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 2D"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create Poly"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 3D"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Insert Point"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "2D Texture"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly (Remove Point)"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "3D Texture"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Remove Poly And Point"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Atlas Texture"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create a new polygon from scratch."
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
+#: editor/plugins/abstract_polygon_2d_editor.cpp
msgid ""
-"NOTICE: Importing 2D textures is not mandatory. Just copy png/jpg files to "
-"the project."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Crop empty space."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Load Source Image"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Slicing"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Inserting"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Saving"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save large texture:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Build Atlas For:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Loading Image:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't load image:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Converting Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cropping Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Blitting Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save atlas image:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save converted texture:"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid source!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid translation source!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Column"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/script_create_dialog.cpp
-msgid "Language"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No items to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No target path!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translations"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Couldn't import!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translation"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Source CSV:"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Ignore First Row"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Compress"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Add to Project (project.godot)"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Languages:"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Translation"
-msgstr ""
-
-#: editor/multi_node_edit.cpp
-msgid "MultiNode Set"
-msgstr ""
-
-#: editor/node_dock.cpp
-msgid "Groups"
-msgstr ""
-
-#: editor/node_dock.cpp
-msgid "Select a Node to edit Signals and Groups."
+"Edit existing polygon:\n"
+"LMB: Move Point.\n"
+"Ctrl+LMB: Split Segment.\n"
+"RMB: Erase Point."
msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
@@ -3371,7 +2774,6 @@ msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
#: editor/script_create_dialog.cpp
msgid "Error!"
@@ -3481,10 +2883,6 @@ msgid "Delete Input"
msgstr ""
#: editor/plugins/animation_tree_editor_plugin.cpp
-msgid "Rename"
-msgstr ""
-
-#: editor/plugins/animation_tree_editor_plugin.cpp
msgid "Animation tree is valid."
msgstr ""
@@ -3540,64 +2938,181 @@ msgstr ""
msgid "Filters.."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing %d Triangles:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Free"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Contents:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "View Files"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Triangle #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve hostname:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Light Baker Setup:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing Geometry"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connection error, please try again."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Fixing Lights"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't connect."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Making BVH"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't connect to host:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Light Octree"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response from host:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Octree Texture"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Transfer to Lightmaps:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, return code:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Allocating Texture #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Req. Failed."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Baking Triangle #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, too many redirects"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Post-Processing Texture #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Redirect Loop."
msgstr ""
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Bake!"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Bad download hash, assuming file has been tampered with."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Expected:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Got:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed sha256 hash check"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Asset Download Error:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Fetching:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Resolving.."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connecting.."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Requesting.."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Error making request"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Idle"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Retry"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download Error"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download for this asset is already in progress!"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "first"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "prev"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "next"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "last"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "All"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Plugins"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Sort:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Reverse"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Category:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Site:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Support.."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Official"
msgstr ""
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Reset the lightmap octree baking process (start over)."
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Testing"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Assets ZIP File"
msgstr ""
#: editor/plugins/camera_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
msgid "Preview"
msgstr ""
@@ -3640,11 +3155,15 @@ msgid "Edit CanvasItem"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Change Anchors"
+msgid "Anchors only"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom (%):"
+msgid "Change Anchors and Margins"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Change Anchors"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3695,59 +3214,72 @@ msgid "Pan Mode"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Lock the selected object in place (can't be moved)."
+msgid "Toggles snapping"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Unlock the selected object (can be moved)."
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Use Snap"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Makes sure the object's children are not selectable."
+msgid "Snapping options"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Restores the object's children's ability to be selected."
+msgid "Snap to grid"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Edit"
+msgid "Use Rotation Snap"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Use Snap"
+msgid "Configure Snap..."
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Show Grid"
+msgid "Snap Relative"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Rotation Snap"
+msgid "Use Pixel Snap"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap Relative"
+msgid "Smart snapping"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Configure Snap.."
+msgid "Snap to parent"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Pixel Snap"
+msgid "Snap to node anchor"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to node sides"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to other nodes"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Lock the selected object in place (can't be moved)."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Unlock the selected object (can be moved)."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Makes sure the object's children are not selectable."
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Skeleton.."
+msgid "Restores the object's children's ability to be selected."
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3776,11 +3308,16 @@ msgid "View"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Reset"
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Show Grid"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Show helpers"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Set.."
+msgid "Show rulers"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3792,7 +3329,7 @@ msgid "Frame Selection"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Anchor"
+msgid "Layout"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3816,11 +3353,19 @@ msgid "Clear Pose"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Set a Value"
+msgid "Drag pivot from mouse position"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Set pivot at mouse position"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap (Pixels):"
+msgid "Multiply grid step by 2"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Divide grid step by 2"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3831,23 +3376,28 @@ msgstr ""
msgid "Adding %s..."
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Create Node"
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Error instancing scene from %s"
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "OK :("
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "No parent to instance a child at."
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "This operation requires a single selected node."
msgstr ""
@@ -3861,45 +3411,6 @@ msgid ""
"Drag & drop + Alt : Change node type"
msgstr ""
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Create Poly"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly (Remove Point)"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Create a new polygon from scratch."
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-msgid ""
-"Edit existing polygon:\n"
-"LMB: Move Point.\n"
-"Ctrl+LMB: Split Segment.\n"
-"RMB: Erase Point."
-msgstr ""
-
#: editor/plugins/collision_polygon_editor_plugin.cpp
msgid "Create Poly3D"
msgstr ""
@@ -3909,14 +3420,6 @@ msgid "Set Handle"
msgstr ""
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Creating Mesh Library"
-msgstr ""
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Thumbnail.."
-msgstr ""
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Remove item %d?"
msgstr ""
@@ -3939,6 +3442,26 @@ msgid "Update from Scene"
msgstr ""
#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat0"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat1"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Ease in"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Ease out"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Smoothstep"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
msgid "Modify Curve Point"
msgstr ""
@@ -4014,22 +3537,18 @@ msgid "Create Occluder Polygon"
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Edit existing polygon:"
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "LMB: Move Point."
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Ctrl+LMB: Split Segment."
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "RMB: Erase Point."
msgstr ""
@@ -4130,6 +3649,10 @@ msgid "Create Outline"
msgstr ""
#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Mesh"
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Create Trimesh Static Body"
msgstr ""
@@ -4257,12 +3780,72 @@ msgstr ""
msgid "Populate"
msgstr ""
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Create Navigation Polygon"
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake!"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake the navigation mesh.\n"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Clear the navigation mesh."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Setting up Configuration..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Calculating grid size..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating heightfield..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Marking walkable triangles..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Constructing compact heightfield..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Eroding walkable area..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Partitioning..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating contours..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating polymesh..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Converting to native navigation mesh..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Navigation Mesh Generator Setup:"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Parsing Geometry..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Done!"
msgstr ""
#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Remove Poly And Point"
+msgid "Create Navigation Polygon"
msgstr ""
#: editor/plugins/particles_2d_editor_plugin.cpp
@@ -4504,6 +4087,14 @@ msgid "Scale Polygon"
msgstr ""
#: editor/plugins/polygon_2d_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Edit"
+msgstr ""
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Polygon->UV"
msgstr ""
@@ -4558,63 +4149,10 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/shader_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr ""
-#: editor/plugins/rich_text_editor_plugin.cpp
-msgid "Parse BBCode"
-msgstr ""
-
-#: editor/plugins/sample_editor_plugin.cpp
-msgid "Length:"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Open Sample File(s)"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "ERROR: Couldn't load sample!"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Add Sample"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Rename Sample"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Delete Sample"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "16 Bits"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "8 Bits"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Stereo"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Mono"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Format"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Pitch"
-msgstr ""
-
#: editor/plugins/script_editor_plugin.cpp
msgid "Clear Recent Files"
msgstr ""
@@ -4705,6 +4243,10 @@ msgstr ""
msgid "Close All"
msgstr ""
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+msgid "Run"
+msgstr ""
+
#: editor/plugins/script_editor_plugin.cpp
msgid "Toggle Scripts Panel"
msgstr ""
@@ -4733,7 +4275,8 @@ msgstr ""
msgid "Break"
msgstr ""
-#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+#: editor/script_editor_debugger.cpp
msgid "Continue"
msgstr ""
@@ -4746,18 +4289,6 @@ msgid "Debug with external editor"
msgstr ""
#: editor/plugins/script_editor_plugin.cpp
-msgid "Window"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Left"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Right"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
msgid "Open Godot online documentation"
msgstr ""
@@ -4839,8 +4370,9 @@ msgid "Cut"
msgstr ""
#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr ""
@@ -5103,10 +4635,6 @@ msgid "View Plane Transform."
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Scaling to %s%%."
-msgstr ""
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rotating %s degrees."
msgstr ""
@@ -5123,10 +4651,6 @@ msgid "Top View."
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Top"
-msgstr ""
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rear View."
msgstr ""
@@ -5354,6 +4878,10 @@ msgid "Transform"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Configure Snap.."
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Local Coords"
msgstr ""
@@ -5499,6 +5027,10 @@ msgid "Speed (FPS):"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Loop"
+msgstr ""
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Animation Frames"
msgstr ""
@@ -5511,11 +5043,11 @@ msgid "Insert Empty (After)"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Up"
+msgid "Move (Before)"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Down"
+msgid "Move (After)"
msgstr ""
#: editor/plugins/style_box_editor_plugin.cpp
@@ -5592,7 +5124,11 @@ msgid "Remove All"
msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
-msgid "Theme"
+msgid "Edit theme.."
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Theme editing menu."
msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
@@ -5677,6 +5213,10 @@ msgid "Style"
msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
+msgid "Font"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
msgid "Color"
msgstr ""
@@ -5725,7 +5265,7 @@ msgid "Mirror Y"
msgstr ""
#: editor/plugins/tile_map_editor_plugin.cpp
-msgid "Bucket"
+msgid "Paint Tile"
msgstr ""
#: editor/plugins/tile_map_editor_plugin.cpp
@@ -5789,6 +5329,10 @@ msgid "Delete preset '%s'?"
msgstr ""
#: editor/project_export.cpp
+msgid "Export templates for this platform are missing/corrupted: "
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Presets"
msgstr ""
@@ -5859,19 +5403,29 @@ msgid "Export templates for this platform are missing:"
msgstr ""
#: editor/project_export.cpp
+msgid "Export templates for this platform are missing/corrupted:"
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Export With Debug"
msgstr ""
#: editor/project_manager.cpp
-msgid "Invalid project path, the path must exist!"
+msgid "The path does not exist."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Please choose a 'project.godot' file."
msgstr ""
#: editor/project_manager.cpp
-msgid "Invalid project path, project.godot must not exist."
+msgid ""
+"Your project will be created in a non empty folder (you might want to create "
+"a new folder)."
msgstr ""
#: editor/project_manager.cpp
-msgid "Invalid project path, project.godot must exist."
+msgid "Please choose a folder that does not contain a 'project.godot' file."
msgstr ""
#: editor/project_manager.cpp
@@ -5879,10 +5433,26 @@ msgid "Imported Project"
msgstr ""
#: editor/project_manager.cpp
+msgid " "
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "It would be a good idea to name your project."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Invalid project path (changed anything?)."
msgstr ""
#: editor/project_manager.cpp
+msgid "Couldn't get project.godot in project path."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Couldn't edit project.godot in project path."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
msgstr ""
@@ -5891,23 +5461,23 @@ msgid "The following files failed extraction from package:"
msgstr ""
#: editor/project_manager.cpp
-msgid "Import Existing Project"
+msgid "Rename Project"
msgstr ""
#: editor/project_manager.cpp
-msgid "Project Path (Must Exist):"
+msgid "Couldn't get project.godot in the project path."
msgstr ""
#: editor/project_manager.cpp
-msgid "Project Name:"
+msgid "New Game Project"
msgstr ""
#: editor/project_manager.cpp
-msgid "Create New Project"
+msgid "Import Existing Project"
msgstr ""
#: editor/project_manager.cpp
-msgid "Project Path:"
+msgid "Create New Project"
msgstr ""
#: editor/project_manager.cpp
@@ -5915,11 +5485,19 @@ msgid "Install Project:"
msgstr ""
#: editor/project_manager.cpp
-msgid "Browse"
+msgid "Project Name:"
msgstr ""
#: editor/project_manager.cpp
-msgid "New Game Project"
+msgid "Create folder"
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Project Path:"
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Browse"
msgstr ""
#: editor/project_manager.cpp
@@ -5931,6 +5509,10 @@ msgid "Unnamed Project"
msgstr ""
#: editor/project_manager.cpp
+msgid "Can't open project"
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Are you sure to open more than one project?"
msgstr ""
@@ -5957,16 +5539,18 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
-"You are about the scan %s folders for existing Godot projects. Do you "
-"confirm?"
+"Language changed.\n"
+"The UI will update next time the editor or project manager starts."
msgstr ""
#: editor/project_manager.cpp
-msgid "Project List"
+msgid ""
+"You are about the scan %s folders for existing Godot projects. Do you "
+"confirm?"
msgstr ""
#: editor/project_manager.cpp
-msgid "Run"
+msgid "Project List"
msgstr ""
#: editor/project_manager.cpp
@@ -5990,6 +5574,10 @@ msgid "Exit"
msgstr ""
#: editor/project_manager.cpp
+msgid "Restart Now"
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Can't run project"
msgstr ""
@@ -6026,17 +5614,14 @@ msgid "Add Input Action Event"
msgstr ""
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Meta+"
msgstr ""
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Shift+"
msgstr ""
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Alt+"
msgstr ""
@@ -6097,7 +5682,7 @@ msgstr ""
msgid "Joypad Axis Index:"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Axis"
msgstr ""
@@ -6117,31 +5702,31 @@ msgstr ""
msgid "Add Event"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Device"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Button"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Left Button."
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Right Button."
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Middle Button."
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Up."
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Down."
msgstr ""
@@ -6150,7 +5735,7 @@ msgid "Add Global Property"
msgstr ""
#: editor/project_settings_editor.cpp
-msgid "Select an setting item first!"
+msgid "Select a setting item first!"
msgstr ""
#: editor/project_settings_editor.cpp
@@ -6166,6 +5751,14 @@ msgid "Delete Item"
msgstr ""
#: editor/project_settings_editor.cpp
+msgid "Can't contain '/' or ':'"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Already existing"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "Error saving settings."
msgstr ""
@@ -6206,6 +5799,14 @@ msgid "Remove Resource Remap Option"
msgstr ""
#: editor/project_settings_editor.cpp
+msgid "Changed Locale Filter"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Changed Locale Filter Mode"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "Project Settings (project.godot)"
msgstr ""
@@ -6266,6 +5867,26 @@ msgid "Locale"
msgstr ""
#: editor/project_settings_editor.cpp
+msgid "Locales Filter"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Show all locales"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Show only selected locales"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Filter mode:"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Locales:"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "AutoLoad"
msgstr ""
@@ -6314,10 +5935,18 @@ msgid "New Script"
msgstr ""
#: editor/property_editor.cpp
+msgid "Make Unique"
+msgstr ""
+
+#: editor/property_editor.cpp
msgid "Show in File System"
msgstr ""
#: editor/property_editor.cpp
+msgid "Convert To %s"
+msgstr ""
+
+#: editor/property_editor.cpp
msgid "Error loading file: Not a resource!"
msgstr ""
@@ -6354,6 +5983,10 @@ msgid "Select Property"
msgstr ""
#: editor/property_selector.cpp
+msgid "Select Virtual Method"
+msgstr ""
+
+#: editor/property_selector.cpp
msgid "Select Method"
msgstr ""
@@ -6381,26 +6014,6 @@ msgstr ""
msgid "Reparent"
msgstr ""
-#: editor/resources_dock.cpp
-msgid "Create New Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Open Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Save Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Resource Tools"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Make Local"
-msgstr ""
-
#: editor/run_settings_dialog.cpp
msgid "Run Mode:"
msgstr ""
@@ -6527,14 +6140,6 @@ msgid "Sub-Resources:"
msgstr ""
#: editor/scene_tree_dock.cpp
-msgid "Edit Groups"
-msgstr ""
-
-#: editor/scene_tree_dock.cpp
-msgid "Edit Connections"
-msgstr ""
-
-#: editor/scene_tree_dock.cpp
msgid "Clear Inheritance"
msgstr ""
@@ -6715,6 +6320,14 @@ msgid "Invalid base path"
msgstr ""
#: editor/script_create_dialog.cpp
+msgid "Directory of the same name exists"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
+msgid "File exists, will be reused"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
msgid "Invalid extension"
msgstr ""
@@ -6755,6 +6368,10 @@ msgid "Load existing script file"
msgstr ""
#: editor/script_create_dialog.cpp
+msgid "Language"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
msgid "Inherits"
msgstr ""
@@ -6795,6 +6412,10 @@ msgid "Function:"
msgstr ""
#: editor/script_editor_debugger.cpp
+msgid "Pick one or more items from the list to display the graph."
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
msgid "Errors"
msgstr ""
@@ -6875,6 +6496,10 @@ msgid "Type"
msgstr ""
#: editor/script_editor_debugger.cpp
+msgid "Format"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
msgid "Usage"
msgstr ""
@@ -6950,12 +6575,28 @@ msgstr ""
msgid "Change Probe Extents"
msgstr ""
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Library"
+msgstr ""
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Status"
+msgstr ""
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Libraries: "
+msgstr ""
+
+#: modules/gdnative/register_types.cpp
+msgid "GDNative"
+msgstr ""
+
#: modules/gdscript/gd_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Invalid type argument to convert(), use TYPE_* constants."
msgstr ""
-#: modules/gdscript/gd_functions.cpp
+#: modules/gdscript/gd_functions.cpp modules/mono/glue/glue_header.h
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Not enough bytes for decoding bytes, or invalid format."
msgstr ""
@@ -7005,10 +6646,6 @@ msgid "GridMap Duplicate Selection"
msgstr ""
#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "GridMap Paint"
-msgstr ""
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Snap View"
msgstr ""
@@ -7100,12 +6737,8 @@ msgstr ""
msgid "Pick Distance:"
msgstr ""
-#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "Tiles"
-msgstr ""
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "Areas"
+#: modules/mono/editor/mono_bottom_panel.cpp
+msgid "Builds"
msgstr ""
#: modules/visual_script/visual_script.cpp
@@ -7295,10 +6928,18 @@ msgid "Return"
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
+msgid "Call"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
msgid "Get"
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
+msgid "Script already has function '%s'"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
msgid "Change Input Value"
msgstr ""
@@ -7652,6 +7293,12 @@ msgid ""
"order for AnimatedSprite3D to display frames."
msgstr ""
+#: scene/3d/vehicle_body.cpp
+msgid ""
+"VehicleWheel serves to provide a wheel system to a VehicleBody. Please use "
+"it as a child of a VehicleBody."
+msgstr ""
+
#: scene/gui/color_picker.cpp
msgid "Raw Mode"
msgstr ""
@@ -7661,15 +7308,15 @@ msgid "Add current color as a preset"
msgstr ""
#: scene/gui/dialogs.cpp
-msgid "Alert!"
+msgid "Cancel"
msgstr ""
#: scene/gui/dialogs.cpp
-msgid "Please Confirm..."
+msgid "Alert!"
msgstr ""
-#: scene/gui/input_action.cpp
-msgid "Ctrl+"
+#: scene/gui/dialogs.cpp
+msgid "Please Confirm..."
msgstr ""
#: scene/gui/popup.cpp
@@ -7699,3 +7346,19 @@ msgid ""
"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
"texture to some node for display."
msgstr ""
+
+#: scene/resources/dynamic_font.cpp
+msgid "Error initializing FreeType."
+msgstr ""
+
+#: scene/resources/dynamic_font.cpp
+msgid "Unknown font format."
+msgstr ""
+
+#: scene/resources/dynamic_font.cpp
+msgid "Error loading font."
+msgstr ""
+
+#: scene/resources/dynamic_font.cpp
+msgid "Invalid font size."
+msgstr ""
diff --git a/editor/translations/el.po b/editor/translations/el.po
index 0532753542..02de498110 100644
--- a/editor/translations/el.po
+++ b/editor/translations/el.po
@@ -1,21 +1,22 @@
# Greek translation of the Godot Engine editor
-# Copyright (C) 2016-2017 Juan Linietsky, Ariel Manzur and the Godot community
+# Copyright (C) 2007-2017 Juan Linietsky, Ariel Manzur
+# Copyright (C) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)
# This file is distributed under the same license as the Godot source code.
#
-# gtsiam <gtsiam@windowslive.com>, 2017.
+# George Tsiamasiotis <gtsiam@windowslive.com>, 2017.
#
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
-"PO-Revision-Date: 2017-06-29 17:12+0000\n"
-"Last-Translator: gtsiam <gtsiam@windowslive.com>\n"
+"PO-Revision-Date: 2017-10-24 18:46+0000\n"
+"Last-Translator: George Tsiamasiotis <gtsiam@windowslive.com>\n"
"Language-Team: Greek <https://hosted.weblate.org/projects/godot-engine/godot/"
"el/>\n"
"Language: el\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8-bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 2.15-dev\n"
+"X-Generator: Weblate 2.17\n"
#: editor/animation_editor.cpp
msgid "Disabled"
@@ -191,10 +192,9 @@ msgid "Create %d NEW tracks and insert keys?"
msgstr "ΔημιουÏγία %d νέων κομματιών και εισαγωγή κλειδιών;"
#: editor/animation_editor.cpp editor/create_dialog.cpp
-#: editor/editor_audio_buses.cpp
+#: editor/editor_audio_buses.cpp editor/plugins/abstract_polygon_2d_editor.cpp
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
#: editor/plugins/mesh_instance_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp editor/project_manager.cpp
#: editor/script_create_dialog.cpp
msgid "Create"
@@ -358,262 +358,6 @@ msgstr "Αλλαγή Ï„Ïπου τιμής πίνακα"
msgid "Change Array Value"
msgstr "Αλλαγή τιμής πίνακα"
-#: editor/asset_library_editor_plugin.cpp
-msgid "Free"
-msgstr "ΔωÏεάν"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_plugin_settings.cpp
-msgid "Version:"
-msgstr "Έκδοση:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Contents:"
-msgstr "ΠεÏιεχόμενα:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "View Files"
-msgstr "ΠÏοβολή αÏχείων"
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_help.cpp editor/property_selector.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Description:"
-msgstr "ΠεÏιγÏαφή:"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-#: editor/project_manager.cpp
-msgid "Install"
-msgstr "Εγκατάσταση"
-
-#: editor/asset_library_editor_plugin.cpp editor/call_dialog.cpp
-#: editor/connections_dialog.cpp editor/export_template_manager.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-#: editor/project_settings_editor.cpp editor/property_editor.cpp
-#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Close"
-msgstr "Κλείσιμο"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve hostname:"
-msgstr "Δεν είναι δυνατή η επίλυση του ονόματος του κεντÏÎ¹ÎºÎ¿Ï Ï…Ï€Î¿Î»Î¿Î³Î¹ÏƒÏ„Î®:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve."
-msgstr "Δεν είναι δυνατή η επίλυση."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Connection error, please try again."
-msgstr "Σφάλμα σÏνδεσης, παÏακαλώ ξαναπÏοσπαθήστε."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't connect."
-msgstr "Δεν ήταν δυνατή η σÏνδεση."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't connect to host:"
-msgstr "Δεν ήταν δυνατή η σÏνδεση στον κεντÏικό υπολογιστή:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response from host:"
-msgstr "Δεν λήφθηκε απόκÏιση από τον κεντÏικό υπολογιστή:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response."
-msgstr "Δεν λήφθηκε απόκÏιση."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Request failed, return code:"
-msgstr "Το αίτημα απέτυχε, κώδικας επιστÏοφής:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Req. Failed."
-msgstr "Το αίτημα απέτυχε."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Request failed, too many redirects"
-msgstr "Το αίτημα απέτυχε, πάÏα πολλές ανακατευθήνσεις"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Redirect Loop."
-msgstr "Î’Ïόχος ανακατευθήνσεων."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed:"
-msgstr "Απέτυχε:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Bad download hash, assuming file has been tampered with."
-msgstr ""
-"Εσφαλμένος κωδικός κατακεÏματισμοÏ, θα θεωÏηθεί ότι το αÏχείο έχει αλοιωθεί."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Expected:"
-msgstr "Αναμενόμενο:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Got:"
-msgstr "Δοσμένο:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
-msgstr "Η δοκιμή κατακεÏÎ¼Î±Ï„Î¹ÏƒÎ¼Î¿Ï sha256 απέτυχε"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Asset Download Error:"
-msgstr "Σφάλμα λήψης:"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-msgid "Success!"
-msgstr "Επιτυχία!"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Fetching:"
-msgstr "Λήψη:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Resolving.."
-msgstr "Επίλυση..."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Connecting.."
-msgstr "ΣÏνδεση.."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Requesting.."
-msgstr "Γίνεται αίτημα.."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Error making request"
-msgstr "Σφάλμα κατά την Ï€Ïαγματοποίηση αιτήματος"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Idle"
-msgstr "ΑνενεÏγό"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Retry"
-msgstr "Ξαναδοκίμασε"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Download Error"
-msgstr "Σφάλμα λήψης"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Download for this asset is already in progress!"
-msgstr "Η λήψη είναι ήδη σε εξέλιξη!"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "first"
-msgstr "ΠÏώτο"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "prev"
-msgstr "ΠÏοηγοÏμενο"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "next"
-msgstr "Επόμενο"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "last"
-msgstr "ΠÏοηγοÏμενο"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "All"
-msgstr "Όλα"
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
-#: editor/settings_config_dialog.cpp
-msgid "Search:"
-msgstr "Αναζήτηση:"
-
-#: editor/asset_library_editor_plugin.cpp editor/code_editor.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Search"
-msgstr "Αναζήτηση"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/project_manager.cpp
-msgid "Import"
-msgstr "Εισαγωγή"
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Plugins"
-msgstr "ΠÏόσθετα"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Sort:"
-msgstr "Ταξινόμηση:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Reverse"
-msgstr "ΑντιστÏοφή"
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Category:"
-msgstr "ΚατηγοÏία:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Site:"
-msgstr "ΔιεÏθυνση:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Support.."
-msgstr "ΥποστήÏιξη.."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Official"
-msgstr "Επίσημα"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-msgid "Community"
-msgstr "Κοινότητα"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Testing"
-msgstr "Δοκιμιμαστικά"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Assets ZIP File"
-msgstr "ΑÏχείο ZIP των Asset"
-
-#: editor/call_dialog.cpp
-msgid "Method List For '%s':"
-msgstr "Λίστα συναÏτήσεων για '%s':"
-
-#: editor/call_dialog.cpp modules/visual_script/visual_script_editor.cpp
-msgid "Call"
-msgstr "Κλήση"
-
-#: editor/call_dialog.cpp
-msgid "Method List:"
-msgstr "Λίστα συναÏτήσεων:"
-
-#: editor/call_dialog.cpp
-msgid "Arguments:"
-msgstr "ΠαÏάμετÏοι:"
-
-#: editor/call_dialog.cpp
-msgid "Return:"
-msgstr "ΕπιστÏέφει:"
-
#: editor/code_editor.cpp
msgid "Go to Line"
msgstr "Πήγαινε στη γÏαμμή"
@@ -650,6 +394,14 @@ msgstr "ΟλόκληÏες λέξεις"
msgid "Selection Only"
msgstr "Μόνο στην επιλογή"
+#: editor/code_editor.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
+msgid "Search"
+msgstr "Αναζήτηση"
+
#: editor/code_editor.cpp editor/editor_help.cpp
msgid "Find"
msgstr "ΕÏÏεση"
@@ -682,11 +434,11 @@ msgstr "Ρώτησε στην αντικατάσταση"
msgid "Skip"
msgstr "ΠαÏάλειψη"
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom In"
msgstr "Μεγέθυνση"
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom Out"
msgstr "ΣμÏκÏινση"
@@ -755,6 +507,20 @@ msgstr "Αναβλημένη"
msgid "Oneshot"
msgstr "Μία κλήση"
+#: editor/connections_dialog.cpp editor/dependency_editor.cpp
+#: editor/export_template_manager.cpp
+#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Close"
+msgstr "Κλείσιμο"
+
#: editor/connections_dialog.cpp
msgid "Connect"
msgstr "ΣÏνδεση"
@@ -780,7 +546,7 @@ msgstr "ΣÏνδεση.."
msgid "Disconnect"
msgstr "ΑποσÏνδεση"
-#: editor/connections_dialog.cpp editor/node_dock.cpp
+#: editor/connections_dialog.cpp editor/editor_help.cpp editor/node_dock.cpp
msgid "Signals"
msgstr "Σήματα"
@@ -797,12 +563,25 @@ msgstr "Αγαπημένα:"
msgid "Recent:"
msgstr "ΠÏόσφατα:"
+#: editor/create_dialog.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/quick_open.cpp editor/settings_config_dialog.cpp
+msgid "Search:"
+msgstr "Αναζήτηση:"
+
#: editor/create_dialog.cpp editor/editor_help.cpp
#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/quick_open.cpp
msgid "Matches:"
msgstr "Αντιστοιχίες:"
+#: editor/create_dialog.cpp editor/editor_help.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/property_selector.cpp
+#: editor/script_editor_debugger.cpp
+msgid "Description:"
+msgstr "ΠεÏιγÏαφή:"
+
#: editor/dependency_editor.cpp
msgid "Search Replacement For:"
msgstr "Αναζήτηση αντικατάστασης για:"
@@ -862,6 +641,10 @@ msgid "Owners Of:"
msgstr "Ιδιοκτήτες του:"
#: editor/dependency_editor.cpp
+msgid "Remove selected files from the project? (no undo)"
+msgstr "Îα αφαιÏεθοÏν τα επιλεγμένα αÏχεία από το έÏγο; (ΑδÏνατη η αναίÏεση)"
+
+#: editor/dependency_editor.cpp
msgid ""
"The files being removed are required by other resources in order for them to "
"work.\n"
@@ -871,8 +654,8 @@ msgstr ""
"Îα αφαιÏεθοÏν; (ΑδÏνατη η αναίÏεση)"
#: editor/dependency_editor.cpp
-msgid "Remove selected files from the project? (no undo)"
-msgstr "Îα αφαιÏεθοÏν τα επιλεγμένα αÏχεία από το έÏγο; (ΑδÏνατη η αναίÏεση)"
+msgid "Cannot remove:\n"
+msgstr "ΑδÏνατη η αφαίÏεση:\n"
#: editor/dependency_editor.cpp
msgid "Error loading:"
@@ -938,19 +721,12 @@ msgid "Godot Engine contributors"
msgstr "ΣυνεισφέÏοντες στην Godot Engine"
#: editor/editor_about.cpp
-#, fuzzy
-msgid "Authors"
-msgstr "ΣυγγÏαφέας:"
-
-#: editor/editor_about.cpp
-#, fuzzy
msgid "Project Founders"
-msgstr "ΔιαχειÏιστής"
+msgstr "ΙδÏυτές του έÏγου"
#: editor/editor_about.cpp
-#, fuzzy
msgid "Lead Developer"
-msgstr "ΠÏογÏαμματιστές"
+msgstr "Επικεφαλής Ï€ÏογÏαμματιστής"
#: editor/editor_about.cpp editor/project_manager.cpp
msgid "Project Manager"
@@ -961,12 +737,44 @@ msgid "Developers"
msgstr "ΠÏογÏαμματιστές"
#: editor/editor_about.cpp
+msgid "Authors"
+msgstr "ΣυγγÏαφείς"
+
+#: editor/editor_about.cpp
+msgid "Platinum Sponsors"
+msgstr "ΚοÏυφαίοι ΧοÏηγοί"
+
+#: editor/editor_about.cpp
+msgid "Gold Sponsors"
+msgstr "ΧÏυσοί ΧοÏυγοί"
+
+#: editor/editor_about.cpp
+msgid "Mini Sponsors"
+msgstr "ΜικÏοί ΧοÏηγοί"
+
+#: editor/editor_about.cpp
+msgid "Gold Donors"
+msgstr "ΧÏυσοί ΔωÏητές"
+
+#: editor/editor_about.cpp
+msgid "Silver Donors"
+msgstr "ΑÏγυÏοί ΔωÏητές"
+
+#: editor/editor_about.cpp
+msgid "Bronze Donors"
+msgstr "Χάλκινοι ΔωÏητές"
+
+#: editor/editor_about.cpp
+msgid "Donors"
+msgstr "ΔωÏητές"
+
+#: editor/editor_about.cpp
msgid "License"
-msgstr ""
+msgstr "Άδεια"
#: editor/editor_about.cpp
msgid "Thirdparty License"
-msgstr ""
+msgstr "Άδεια Ï„Ïίτων ομάδων"
#: editor/editor_about.cpp
msgid ""
@@ -975,104 +783,109 @@ msgid ""
"is an exhaustive list of all such thirdparty components with their "
"respective copyright statements and license terms."
msgstr ""
+"Η μηχανή Godot βασίζεται σε μια σειÏά από δωÏεάν και Î±Î½Î¿Î¹Ï‡Ï„Î¿Ï ÎºÏŽÎ´Î¹ÎºÎ± "
+"βιβλιοθήκες Ï„Ïίτων ομάδων, όλες συμβατές με τους ÏŒÏους της άδειας MIT. "
+"Ακολουθεί μία εκτενής λίστα με όλα τα σχετικά συστατικά της μηχανής μαζί με "
+"όλες τις αντοίστοιχες δηλώσεις Ï€Ïοστασίας πνευματικών δικαιωμάτων και τους "
+"ÏŒÏους των αδειών τους."
#: editor/editor_about.cpp
-#, fuzzy
msgid "All Components"
-msgstr "ΠεÏιεχόμενα:"
+msgstr "Όλα τα συστατικά"
#: editor/editor_about.cpp
-#, fuzzy
msgid "Components"
-msgstr "ΠεÏιεχόμενα:"
+msgstr "Συστατικά"
#: editor/editor_about.cpp
msgid "Licenses"
-msgstr ""
+msgstr "Άδειες"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Error opening package file, not in zip format."
-msgstr ""
+msgstr "Σφάλμα κατά το άνοιγμα του πακέτου, δεν είναι αÏχείο zip."
#: editor/editor_asset_installer.cpp
-#, fuzzy
msgid "Uncompressing Assets"
-msgstr "Ασυμπίεστο"
+msgstr "Αποσυμπίεση asset"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package Installed Successfully!"
msgstr "Το πακέτο εγκαταστάθηκε επιτυχώς!"
#: editor/editor_asset_installer.cpp
-#, fuzzy
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Success!"
+msgstr "Επιτυχία!"
+
+#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/project_manager.cpp
+msgid "Install"
+msgstr "Εγκατάσταση"
+
+#: editor/editor_asset_installer.cpp
msgid "Package Installer"
-msgstr "Το πακέτο εγκαταστάθηκε επιτυχώς!"
+msgstr "ΠÏόγÏαμμα εγκατάστασης πακέτων"
#: editor/editor_audio_buses.cpp
msgid "Speakers"
-msgstr ""
+msgstr "Ηχεία"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Add Effect"
-msgstr "ΠÏοσθήκη συμβάντος"
+msgstr "ΠÏοσθήκη εφέ"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Rename Audio Bus"
-msgstr "Άνοιγμα διάταξης διαÏλων ήχου"
+msgstr "Μετονομασία διαÏλου ήχου"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Toggle Audio Bus Solo"
-msgstr "Άνοιγμα διάταξης διαÏλων ήχου"
+msgstr "Εναλλαγή σόλο διαÏλου ήχου"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Toggle Audio Bus Mute"
-msgstr "Άνοιγμα διάταξης διαÏλων ήχου"
+msgstr "Εναλλαγή σίγασης διαÏλου ήχου"
#: editor/editor_audio_buses.cpp
msgid "Toggle Audio Bus Bypass Effects"
-msgstr ""
+msgstr "Εναλλαγή παÏάκαμψης εφέ διαÏλου ήχου"
#: editor/editor_audio_buses.cpp
msgid "Select Audio Bus Send"
-msgstr ""
+msgstr "Επιλογή Ï€ÏοοÏÎ¹ÏƒÎ¼Î¿Ï Î´Î¹Î±Ïλου ήχου"
#: editor/editor_audio_buses.cpp
msgid "Add Audio Bus Effect"
-msgstr ""
+msgstr "ΠÏοσθήκη εφέ διαÏλου ήχου"
#: editor/editor_audio_buses.cpp
msgid "Move Bus Effect"
-msgstr ""
+msgstr "Μετακίνηση εφέ διαÏλου ήχου"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Delete Bus Effect"
-msgstr "ΔιαγÏαφή επιλεγμένου"
+msgstr "ΔιαγÏαφή εφέ διαÏλου ήχου"
#: editor/editor_audio_buses.cpp
msgid "Audio Bus, Drag and Drop to rearrange."
-msgstr ""
-
-#: editor/editor_audio_buses.cpp
-#, fuzzy
-msgid "Bus options"
-msgstr "Επιλογές υπο-σκηνής"
+msgstr "Δίαυλος ήχου, ΣÏÏσιμο και απόθεση για αναδιάταξη."
#: editor/editor_audio_buses.cpp
msgid "Solo"
-msgstr ""
+msgstr "Σόλο"
#: editor/editor_audio_buses.cpp
msgid "Mute"
-msgstr ""
+msgstr "Σίγαση"
#: editor/editor_audio_buses.cpp
msgid "Bypass"
-msgstr ""
+msgstr "ΠαÏάκαμψη"
+
+#: editor/editor_audio_buses.cpp
+msgid "Bus options"
+msgstr "Επιλογές διαÏλου"
#: editor/editor_audio_buses.cpp editor/plugins/tile_map_editor_plugin.cpp
#: editor/scene_tree_dock.cpp
@@ -1080,33 +893,36 @@ msgid "Duplicate"
msgstr "Διπλασιασμός"
#: editor/editor_audio_buses.cpp
-#, fuzzy
+msgid "Reset Volume"
+msgstr "ΕπαναφοÏά Έντασης"
+
+#: editor/editor_audio_buses.cpp
msgid "Delete Effect"
-msgstr "ΔιαγÏαφή επιλεγμένου"
+msgstr "ΔιαγÏαφή εφέ"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Add Audio Bus"
-msgstr "ΠÏοσθήκη διαÏλου"
+msgstr "ΠÏοσθήκη διαÏλου ήχου"
#: editor/editor_audio_buses.cpp
msgid "Master bus can't be deleted!"
-msgstr ""
+msgstr "Ο Ï€ÏωτεÏον δίαυλος δεν μποÏεί να διαγÏαφεί!"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Delete Audio Bus"
-msgstr "ΔιαγÏαφή διάταξης"
+msgstr "ΔιαγÏαφή διαÏλου ήχου"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Duplicate Audio Bus"
-msgstr "ΑναπαÏαγωγή κίνησης"
+msgstr "ΑναπαÏαγωγή διαÏλου ήχου"
+
+#: editor/editor_audio_buses.cpp
+msgid "Reset Bus Volume"
+msgstr "ΕπαναφοÏά Έντασης ΔιαÏλου"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Move Audio Bus"
-msgstr "ΕνέÏγεια μετακίνησης"
+msgstr "Μετακίνηση διαÏλου ήχου"
#: editor/editor_audio_buses.cpp
msgid "Save Audio Bus Layout As.."
@@ -1122,32 +938,28 @@ msgstr "Άνοιγμα διάταξης διαÏλων ήχου"
#: editor/editor_audio_buses.cpp
msgid "There is no 'res://default_bus_layout.tres' file."
-msgstr ""
+msgstr "Δεν υπάÏχει αÏχείο 'res://default_bus_layout.tres'."
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Invalid file, not an audio bus layout."
-msgstr ""
-"ΆκυÏη επέκταση αÏχείου.\n"
-"ΠαÏακαλώ χÏησιμοποιήστε .font."
+msgstr "ΆκυÏο αÏχείο, δεν είναι διάταξη διαÏλων ήχου."
#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr "ΠÏοσθήκη διαÏλου"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Create a new Bus Layout."
-msgstr "ΔημιουÏγία νέου πόÏου"
+msgstr "ΔημιουÏγία νέας διάταξης διαÏλων ήχου."
-#: editor/editor_audio_buses.cpp editor/script_create_dialog.cpp
+#: editor/editor_audio_buses.cpp editor/property_editor.cpp
+#: editor/script_create_dialog.cpp
msgid "Load"
msgstr "ΦόÏτωσε"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Load an existing Bus Layout."
-msgstr "ΦόÏτωσε υπάÏχων πόÏο στη μνήμη και επεξεÏγάσου τον."
+msgstr "ΦόÏτωση υπαÏκτής διάταξης διαÏλων ήχου."
#: editor/editor_audio_buses.cpp
#: editor/plugins/animation_player_editor_plugin.cpp
@@ -1155,18 +967,16 @@ msgid "Save As"
msgstr "Αποθήκευση ώς"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Save this Bus Layout to a file."
-msgstr "Αποθήκευση διάταξης διαÏλων ήχου ÏŽÏ‚.."
+msgstr "Αποθήκευση διάταξης διαÏλων ήχου σε αÏχείο."
#: editor/editor_audio_buses.cpp editor/import_dock.cpp
-#, fuzzy
msgid "Load Default"
-msgstr "ΠÏοεπιλογή"
+msgstr "ΦόÏτωση Ï€Ïοεπιλογής"
#: editor/editor_audio_buses.cpp
msgid "Load the default Bus Layout."
-msgstr ""
+msgstr "ΦόÏτωση Ï€Ïοεπιλεγμένης διάταξης διαÏλων ήχου."
#: editor/editor_autoload_settings.cpp
msgid "Invalid name."
@@ -1235,7 +1045,7 @@ msgid "Rearrange Autoloads"
msgstr "Αναδιάταξη των AutoLoad"
#: editor/editor_autoload_settings.cpp editor/editor_file_dialog.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp scene/gui/file_dialog.cpp
+#: scene/gui/file_dialog.cpp
msgid "Path:"
msgstr "ΔιαδÏομή:"
@@ -1243,9 +1053,7 @@ msgstr "ΔιαδÏομή:"
msgid "Node Name:"
msgstr "Όνομα κόμβου:"
-#: editor/editor_autoload_settings.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp editor/project_manager.cpp
+#: editor/editor_autoload_settings.cpp editor/project_manager.cpp
msgid "Name"
msgstr "Όνομα"
@@ -1270,27 +1078,27 @@ msgid "Updating scene.."
msgstr "ΕνημέÏωση σκηνής.."
#: editor/editor_dir_dialog.cpp
-#, fuzzy
msgid "Please select a base directory first"
-msgstr "ΠαÏακαλοÏμε αποθηκεÏστε την σκηνή Ï€Ïώτα."
+msgstr "ΠαÏακαλοÏμε επιλέξτε Ï€Ïώτα έναν βασικό κατάλογο"
#: editor/editor_dir_dialog.cpp
msgid "Choose a Directory"
msgstr "Επιλέξτε ένα λεξικό"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Create Folder"
msgstr "ΔημιουÏγία φακέλου"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: editor/editor_plugin_settings.cpp editor/plugins/theme_editor_plugin.cpp
-#: editor/project_export.cpp scene/gui/file_dialog.cpp
+#: editor/editor_plugin_settings.cpp editor/filesystem_dock.cpp
+#: editor/plugins/theme_editor_plugin.cpp editor/project_export.cpp
+#: scene/gui/file_dialog.cpp
msgid "Name:"
msgstr "Όνομα:"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Could not create folder."
msgstr "ΑδÏνατη η δημιουÏγία φακέλου."
@@ -1310,30 +1118,6 @@ msgstr "ΠακετάÏισμα"
msgid "Template file not found:\n"
msgstr "Δεν βÏέθηκε το αÏχείο Ï€ÏοτÏπου:\n"
-#: editor/editor_export.cpp
-msgid "Added:"
-msgstr "ΠÏοστέθηκαν:"
-
-#: editor/editor_export.cpp
-msgid "Removed:"
-msgstr "ΑφαιÏέθηκαν:"
-
-#: editor/editor_export.cpp
-msgid "Error saving atlas:"
-msgstr "Σφάλμα κατά την αποθήκευση άτλαντα:"
-
-#: editor/editor_export.cpp
-msgid "Could not save atlas subtexture:"
-msgstr "ΑδÏνατη η αποθήκευση υπό-εικόνας άτλαντα:"
-
-#: editor/editor_export.cpp
-msgid "Exporting for %s"
-msgstr "Εξαγωγή για %s"
-
-#: editor/editor_export.cpp
-msgid "Setting Up.."
-msgstr "ΑÏχικοποίηση.."
-
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "File Exists, Overwrite?"
msgstr "Το αÏχείο υπάÏχει. Θέλετε να το αντικαταστήσετε;"
@@ -1418,6 +1202,10 @@ msgstr "Μετακίνηση αγαπημένου πάνω"
msgid "Move Favorite Down"
msgstr "Μετακίνηση αγαπημένου κάτω"
+#: editor/editor_file_dialog.cpp
+msgid "Go to parent folder"
+msgstr "Πήγαινε στον γονικό φάκελο"
+
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Directories & Files:"
msgstr "Φάκελοι & ΑÏχεία:"
@@ -1432,10 +1220,6 @@ msgid "File:"
msgstr "ΑÏχείο:"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
-msgid "Filter:"
-msgstr "ΦίλτÏο:"
-
-#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Must use a valid extension."
msgstr "Απαιτείται η χÏήση έγκυÏης επέκτασης."
@@ -1460,6 +1244,10 @@ msgstr "Λίστα κλάσεων:"
msgid "Search Classes"
msgstr "Αναζήτηση κλάσεων"
+#: editor/editor_help.cpp editor/plugins/spatial_editor_plugin.cpp
+msgid "Top"
+msgstr "Πάνω"
+
#: editor/editor_help.cpp editor/property_editor.cpp
msgid "Class:"
msgstr "Κλάση:"
@@ -1476,15 +1264,27 @@ msgstr "ΚληÏονομείται από:"
msgid "Brief Description:"
msgstr "ΣÏντομη πεÏιγÏαφή:"
+#: editor/editor_help.cpp
+msgid "Members"
+msgstr "Μέλη"
+
#: editor/editor_help.cpp modules/visual_script/visual_script_editor.cpp
msgid "Members:"
msgstr "Μέλη:"
#: editor/editor_help.cpp
+msgid "Public Methods"
+msgstr "Δημόσιες συναÏτήσεις"
+
+#: editor/editor_help.cpp
msgid "Public Methods:"
msgstr "Δημόσιες συναÏτήσεις:"
#: editor/editor_help.cpp
+msgid "GUI Theme Items"
+msgstr "Στοιχεία του θέματος GUI"
+
+#: editor/editor_help.cpp
msgid "GUI Theme Items:"
msgstr "Στοιχεία του θέματος GUI:"
@@ -1493,54 +1293,81 @@ msgid "Signals:"
msgstr "Σήματα:"
#: editor/editor_help.cpp
-#, fuzzy
+msgid "Enumerations"
+msgstr "ΑπαÏιθμήσεις"
+
+#: editor/editor_help.cpp
msgid "Enumerations:"
-msgstr "Κινήσεις"
+msgstr "ΑπαÏιθμήσεις:"
#: editor/editor_help.cpp
msgid "enum "
-msgstr ""
+msgstr "απαÏίθμηση "
+
+#: editor/editor_help.cpp
+msgid "Constants"
+msgstr "ΣταθεÏές"
#: editor/editor_help.cpp
msgid "Constants:"
msgstr "ΣταθεÏές:"
#: editor/editor_help.cpp
+msgid "Description"
+msgstr "ΠεÏιγÏαφή"
+
+#: editor/editor_help.cpp
+msgid "Properties"
+msgstr "Ιδιότητες"
+
+#: editor/editor_help.cpp
msgid "Property Description:"
msgstr "ΠεÏιγÏαφή ιδιότητας:"
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this property. Please help us by "
+"[color=$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+
+#: editor/editor_help.cpp
+msgid "Methods"
+msgstr "ΣυναÏτήσεις"
+
+#: editor/editor_help.cpp
msgid "Method Description:"
msgstr "ΠεÏιγÏαφή μεθόδου:"
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this method. Please help us by [color="
+"$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Search Text"
msgstr "Αναζήτηση κειμένου"
#: editor/editor_log.cpp
-#, fuzzy
msgid "Output:"
-msgstr " Έξοδος:"
+msgstr "Έξοδος:"
#: editor/editor_log.cpp editor/plugins/animation_tree_editor_plugin.cpp
-#: editor/plugins/rich_text_editor_plugin.cpp editor/property_editor.cpp
-#: editor/script_editor_debugger.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/property_editor.cpp editor/script_editor_debugger.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Clear"
msgstr "ΕκκαθάÏιση"
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Error saving resource!"
msgstr "Σφάλμα κατά την αποθήκευση πόÏου!"
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Save Resource As.."
msgstr "Αποθήκευση πόÏου ως.."
-#: editor/editor_node.cpp editor/export_template_manager.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "I see.."
msgstr "Εντάξει.."
@@ -1557,6 +1384,26 @@ msgid "Error while saving."
msgstr "Σφάλμα κατά την αποθήκευση."
#: editor/editor_node.cpp
+msgid "Can't open '%s'."
+msgstr "ΑδÏνατο το άνοιγμα του '%s'."
+
+#: editor/editor_node.cpp
+msgid "Error while parsing '%s'."
+msgstr "Σφάλμα κατά η ανάλυση του '%s'."
+
+#: editor/editor_node.cpp
+msgid "Unexpected end of file '%s'."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Missing '%s' or its dependencies."
+msgstr "Λείπει το '%s' ή οι εξαÏτήσεις του."
+
+#: editor/editor_node.cpp
+msgid "Error while loading '%s'."
+msgstr "Σφάλμα κατά την φόÏτωση του '%s'."
+
+#: editor/editor_node.cpp
msgid "Saving Scene"
msgstr "Αποθήκευση σκηνής"
@@ -1569,9 +1416,8 @@ msgid "Creating Thumbnail"
msgstr "ΔημιουÏγία μικÏογÏαφίας"
#: editor/editor_node.cpp
-#, fuzzy
msgid "This operation can't be done without a tree root."
-msgstr "Αυτή η λειτουÏγία δεν μποÏεί να γίνει χωÏίς σκηνή."
+msgstr "Αυτή η λειτουÏγία δεν μποÏεί να γίνει χωÏίς Ïίζα δέντÏου."
#: editor/editor_node.cpp
msgid ""
@@ -1617,6 +1463,33 @@ msgid "Restored default layout to base settings."
msgstr "ΕπαναφοÏά της Ï€Ïοεπιλεγμένης διάταξης στις βασικές Ïυθμίσεις."
#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was imported, so it's not editable.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was instanced or inherited.\n"
+"Changes to it will not be kept when saving the current scene."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource was imported, so it's not editable. Change its settings in the "
+"import panel and then re-import."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This scene was imported, so changes to it will not be kept.\n"
+"Instancing it or inheriting will allow making changes to it.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Copy Params"
msgstr "ΑντιγÏαφή παÏαμέτÏων"
@@ -1706,13 +1579,12 @@ msgid "Quick Open Script.."
msgstr "ΓÏήγοÏη άνοιγμα δεσμής ενεÏγειών..."
#: editor/editor_node.cpp
-#, fuzzy
msgid "Save & Close"
-msgstr "Αποθήκευση αÏχείου"
+msgstr "Αποθήκευση & Κλείσιμο"
#: editor/editor_node.cpp
msgid "Save changes to '%s' before closing?"
-msgstr ""
+msgstr "Αποθήκευση αλλαγών στο '%s' Ï€Ïιν το κλείσιμο;"
#: editor/editor_node.cpp
msgid "Save Scene As.."
@@ -1743,9 +1615,8 @@ msgid "Export Tile Set"
msgstr "Εξαγωγή σετ πλακιδίων"
#: editor/editor_node.cpp
-#, fuzzy
msgid "This operation can't be done without a selected node."
-msgstr "Αυτή η λειτουÏγία δεν μποÏεί να γίνει χωÏίς σκηνή."
+msgstr "Αυτή η λειτουÏγία δεν μποÏεί να γίνει χωÏίς έναν επιλεγμένο κόμβο."
#: editor/editor_node.cpp
msgid "Current scene not saved. Open anyway?"
@@ -1779,42 +1650,60 @@ msgid "Exit the editor?"
msgstr "ΤεÏματισμός του Ï€ÏογÏάμματος επεξεÏγασίας;"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Open Project Manager?"
-msgstr "ΔιαχειÏιστής"
+msgstr "Άνοιγμα του διαχειÏιστή έÏγων;"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Save & Quit"
-msgstr "Αποθήκευση αÏχείου"
+msgstr "Αποθήκευση & Έξοδος"
#: editor/editor_node.cpp
msgid "Save changes to the following scene(s) before quitting?"
-msgstr ""
+msgstr "Αποθήκευση αλλαγών στις ακόλουθες σκηνές σκηνές Ï€Ïιν την έξοδο;"
#: editor/editor_node.cpp
msgid "Save changes the following scene(s) before opening Project Manager?"
msgstr ""
+"Αποθήκευση αλλαγών στις ακόλουθες σκηνές σκηνές Ï€Ïιν το άνοιγμα του "
+"διαχειÏιστή έÏγων;"
+
+#: editor/editor_node.cpp
+msgid ""
+"This option is deprecated. Situations where refresh must be forced are now "
+"considered a bug. Please report."
+msgstr ""
#: editor/editor_node.cpp
msgid "Pick a Main Scene"
msgstr "Επιλογή κÏÏιας σκηνής"
#: editor/editor_node.cpp
-msgid "Unable to enable addon plugin at: '"
-msgstr ""
+#, fuzzy
+msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
+msgstr "ΑδÏνατη η ενεÏγοποίηση Ï€Ïόσθετης επέκτασης στο: '"
#: editor/editor_node.cpp
-msgid "' parsing of config failed."
+#, fuzzy
+msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
msgstr ""
+"ΑδÏνατη η έυÏεση του πεδίου 'script' για την Ï€Ïόσθετη επέκταση στο: 'res://"
+"addons/"
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/"
-msgstr ""
+#, fuzzy
+msgid "Unable to load addon script from path: '%s'."
+msgstr "ΑδÏνατη η φόÏτωση δεσμής ενεÏγειών Ï€Ïοσθέτου από τη διαδÏομή: '"
#: editor/editor_node.cpp
-msgid "Unable to load addon script from path: '"
-msgstr ""
+#, fuzzy
+msgid ""
+"Unable to load addon script from path: '%s' Base type is not EditorPlugin."
+msgstr "ΑδÏνατη η φόÏτωση δεσμής ενεÏγειών Ï€Ïοσθέτου από τη διαδÏομή: '"
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Unable to load addon script from path: '%s' Script is not in tool mode."
+msgstr "ΑδÏνατη η φόÏτωση δεσμής ενεÏγειών Ï€Ïοσθέτου από τη διαδÏομή: '"
#: editor/editor_node.cpp
msgid ""
@@ -1826,7 +1715,7 @@ msgstr ""
"σκηνή."
#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/scene_tree_dock.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Ugh"
msgstr "α..."
@@ -1840,14 +1729,14 @@ msgstr ""
"συνέχεια, αποθηκεÏστε τη μέσα στη διαδÏομή του έÏγου."
#: editor/editor_node.cpp
-msgid "Error loading scene."
-msgstr "Σφάλμα κατά τη φόÏτωση σκηνής."
-
-#: editor/editor_node.cpp
msgid "Scene '%s' has broken dependencies:"
msgstr "Η σκηνή '%s' έχει σπασμένες εξαÏτήσεις:"
#: editor/editor_node.cpp
+msgid "Clear Recent Scenes"
+msgstr "ΕκκαθάÏιση Ï€Ïόσφατων σκηνών"
+
+#: editor/editor_node.cpp
msgid "Save Layout"
msgstr "Αποθήκευση διάταξης"
@@ -1877,11 +1766,10 @@ msgid "Distraction Free Mode"
msgstr "ΛειτουÏγία χωÏίς διάσπαση Ï€Ïοσοχής"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Toggle distraction-free mode."
-msgstr "ΛειτουÏγία χωÏίς διάσπαση Ï€Ïοσοχής"
+msgstr "Εναλλαγή λειτουÏγίας χωÏίς πεÏισπασμοÏÏ‚."
-#: editor/editor_node.cpp editor/io_plugins/editor_scene_import_plugin.cpp
+#: editor/editor_node.cpp
msgid "Scene"
msgstr "Σκηνή"
@@ -2120,6 +2008,10 @@ msgstr "ΕÏώτηση&Απάντηση"
msgid "Issue Tracker"
msgstr "ΔιαχείÏιση Ï€Ïοβλημάτων"
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+msgid "Community"
+msgstr "Κοινότητα"
+
#: editor/editor_node.cpp
msgid "About"
msgstr "Σχετικά"
@@ -2128,7 +2020,7 @@ msgstr "Σχετικά"
msgid "Play the project."
msgstr "ΑναπαÏαγωγή του έÏγου."
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Play"
msgstr "ΑναπαÏαγωγή"
@@ -2144,7 +2036,7 @@ msgstr "ΠαÏση της σκηνής"
msgid "Stop the scene."
msgstr "Διέκοψε τη σκηνή."
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Stop"
msgstr "Διακοπή"
@@ -2217,6 +2109,15 @@ msgid "Object properties."
msgstr "Ιδιότητες αντικειμένου."
#: editor/editor_node.cpp
+msgid "Changes may be lost!"
+msgstr "Οι αλλαγές μποÏεί να χαθοÏν!"
+
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Import"
+msgstr "Εισαγωγή"
+
+#: editor/editor_node.cpp
msgid "FileSystem"
msgstr "ΣÏστημα αÏχείων"
@@ -2230,15 +2131,7 @@ msgstr "Έξοδος"
#: editor/editor_node.cpp
msgid "Don't Save"
-msgstr ""
-
-#: editor/editor_node.cpp editor/editor_reimport_dialog.cpp
-msgid "Re-Import"
-msgstr "Επανεισαγωγή"
-
-#: editor/editor_node.cpp editor/editor_plugin_settings.cpp
-msgid "Update"
-msgstr "ΕνημέÏωση"
+msgstr "ΧωÏις αποθήκευση"
#: editor/editor_node.cpp
msgid "Import Templates From ZIP File"
@@ -2265,9 +2158,8 @@ msgid "Open & Run a Script"
msgstr "Άνοιξε & ΤÏέξε μία δεσμή ενεÏγειών"
#: editor/editor_node.cpp
-#, fuzzy
msgid "New Inherited"
-msgstr "Îέα κληÏονομημένη σκηνή.."
+msgstr "Îέα κληÏονομημένη"
#: editor/editor_node.cpp
msgid "Load Errors"
@@ -2301,11 +2193,29 @@ msgstr "Άνοιγμα του επόμενου επεξεÏγαστή"
msgid "Open the previous Editor"
msgstr "Άνοιγμα του Ï€ÏοηγοÏμενου επεξεÏγαστή"
+#: editor/editor_plugin.cpp
+#, fuzzy
+msgid "Creating Mesh Previews"
+msgstr "ΔημιουÏγία Ï€Ïοεπισκοπήσεων πλεγμάτων"
+
+#: editor/editor_plugin.cpp
+msgid "Thumbnail.."
+msgstr "ΜικÏογÏαφία.."
+
#: editor/editor_plugin_settings.cpp
msgid "Installed Plugins:"
msgstr "Εγκατεστημένα Ï€Ïόσθετα:"
#: editor/editor_plugin_settings.cpp
+msgid "Update"
+msgstr "ΕνημέÏωση"
+
+#: editor/editor_plugin_settings.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Version:"
+msgstr "Έκδοση:"
+
+#: editor/editor_plugin_settings.cpp
msgid "Author:"
msgstr "ΣυγγÏαφέας:"
@@ -2338,7 +2248,8 @@ msgid "Frame %"
msgstr "ΚαÏέ %"
#: editor/editor_profiler.cpp
-msgid "Fixed Frame %"
+#, fuzzy
+msgid "Physics Frame %"
msgstr "ΣταθεÏÏŒ καÏέ %"
#: editor/editor_profiler.cpp editor/script_editor_debugger.cpp
@@ -2357,35 +2268,17 @@ msgstr "Εαυτός"
msgid "Frame #:"
msgstr "ΚαÏέ #:"
-#: editor/editor_reimport_dialog.cpp
-msgid "Please wait for scan to complete."
-msgstr "ΠαÏακαλώ πεÏιμένετε να ολοκληÏωθεί η σάÏωση."
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Current scene must be saved to re-import."
-msgstr "Η Ï„Ïέχουσα σκηνή Ï€Ïέπει να αποθηκευτεί για να επαν-εισάγετε."
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Save & Re-Import"
-msgstr "Αποθήκευση & Επανεισαγωγή"
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Importing"
-msgstr "Επανεισαγωγή"
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Import Changed Resources"
-msgstr "Επανεισαγωγή Ï„Ïοποπιημένων πόÏων"
-
#: editor/editor_run_native.cpp
msgid "Select device from the list"
-msgstr ""
+msgstr "Επιλέξτε συσκευή από την λίστα"
#: editor/editor_run_native.cpp
msgid ""
"No runnable export preset found for this platform.\n"
"Please add a runnable preset in the export menu."
msgstr ""
+"Δεν βÏέθηκε εκτελέσιμη διαμόÏφωση εξαγωγής για αυτή την πλατφόÏμα.\n"
+"ΠαÏακαλοÏμε Ï€Ïοσθέστε μία εκτελέσιμη διαμόÏφωση στο Î¼ÎµÎ½Î¿Ï ÎµÎ¾Î±Î³Ï‰Î³Î®Ï‚."
#: editor/editor_run_script.cpp
msgid "Write your logic in the _run() method."
@@ -2488,10 +2381,6 @@ msgid "Importing:"
msgstr "Εισαγωγή:"
#: editor/export_template_manager.cpp
-msgid "Loading Export Templates"
-msgstr "ΦόÏτωση Ï€ÏοτÏπων εξαγωγής"
-
-#: editor/export_template_manager.cpp
msgid "Current Version:"
msgstr "ΤÏέχουσα έκδοση:"
@@ -2526,60 +2415,78 @@ msgid "Cannot navigate to '"
msgstr "ΑδÏνατη η πλοήγηση στο '"
#: editor/filesystem_dock.cpp
-#, fuzzy
+msgid "View items as a grid of thumbnails"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "View items as a list"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
msgid ""
"\n"
-"Status: Needs Re-Import"
-msgstr "Αποθήκευση & Επανεισαγωγή"
+"Status: Import of file failed. Please fix file and reimport manually."
+msgstr ""
#: editor/filesystem_dock.cpp
-#, fuzzy
msgid ""
"\n"
"Source: "
-msgstr "Πηγή:"
+msgstr ""
+"\n"
+"Πηγή: "
#: editor/filesystem_dock.cpp
-msgid "Same source and destination files, doing nothing."
-msgstr "Ίδια αÏχεία πηγής και Ï€ÏοοÏισμοÏ, παÏάλειψη ενέÏγειας."
+#, fuzzy
+msgid "Cannot move/rename resources root."
+msgstr "Δεν ήταν δυνατή η φόÏτωση/επεξεÏγασία της πηγαίας γÏαμματοσειÏάς."
#: editor/filesystem_dock.cpp
-msgid "Target file exists, can't overwrite. Delete first."
-msgstr ""
+#, fuzzy
+msgid "Cannot move a folder into itself.\n"
+msgstr "Δεν είναι δυνατή η εισαγωγή ενός αÏχείου πάνω στον εαυτό του:"
#: editor/filesystem_dock.cpp
-msgid "Same source and destination paths, doing nothing."
-msgstr "Ίδιες διαδÏομές πηγής και Ï€ÏοοÏισμοÏ, παÏάλειψη ενέÏγειας."
+#, fuzzy
+msgid "Error moving:\n"
+msgstr "Σφάλμα κατά την μετακίνηση καταλόγου:\n"
+
+#: editor/filesystem_dock.cpp
+#, fuzzy
+msgid "Unable to update dependencies:\n"
+msgstr "Η σκηνή '%s' έχει σπασμένες εξαÏτήσεις:"
#: editor/filesystem_dock.cpp
-msgid "Can't move directories to within themselves."
-msgstr "ΑδÏνατη η μετακίνηση καταλόγων μέσα στους εαυτοÏÏ‚ τους."
+msgid "No name provided"
+msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Can't rename deps for:\n"
+msgid "Provided name contains invalid characters"
msgstr ""
#: editor/filesystem_dock.cpp
#, fuzzy
-msgid "Error moving file:\n"
-msgstr "Σφάλμα κατά την φόÏτωση εικόνας:"
+msgid "No name provided."
+msgstr "Μετονομασία ή μετακίνηση.."
#: editor/filesystem_dock.cpp
#, fuzzy
-msgid "Error moving dir:\n"
-msgstr "Σφάλμα κατά την εισαγωγή:"
+msgid "Name contains invalid characters."
+msgstr "ΈγκυÏοι χαÏακτήÏες:"
#: editor/filesystem_dock.cpp
-msgid "Can't operate on '..'"
-msgstr "ΑδÏνατη η λειτουÏγία στο '..'"
+msgid "A file or folder with this name already exists."
+msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Pick New Name and Location For:"
-msgstr "Επιλέξτε νέο όνομα και θέση για:"
+#, fuzzy
+msgid "Renaming file:"
+msgstr "Μετονομασία μεταβλητής"
#: editor/filesystem_dock.cpp
-msgid "No files selected!"
-msgstr "Δεν επιλέχθηκαν αÏχεία!"
+#, fuzzy
+msgid "Renaming folder:"
+msgstr "Μετονομασία κόμβου"
#: editor/filesystem_dock.cpp
msgid "Expand all"
@@ -2590,40 +2497,38 @@ msgid "Collapse all"
msgstr "ΣÏμπτηξη όλων"
#: editor/filesystem_dock.cpp
-msgid "Show In File Manager"
-msgstr "Εμφάνιση στη διαχείÏιση αÏχείων"
-
-#: editor/filesystem_dock.cpp
-msgid "Instance"
-msgstr "Στιγμιότυπο"
+msgid "Copy Path"
+msgstr "ΑντιγÏαφή διαδÏομής"
#: editor/filesystem_dock.cpp
-msgid "Edit Dependencies.."
-msgstr "ΕπεξεÏγασία εξαÏτήσεων .."
+#, fuzzy
+msgid "Rename.."
+msgstr "Μετονομασία"
#: editor/filesystem_dock.cpp
-msgid "View Owners.."
-msgstr "ΠÏοβολή Ιδιοκτητών .."
+msgid "Move To.."
+msgstr "Μετακίνηση σε..."
#: editor/filesystem_dock.cpp
-msgid "Copy Path"
-msgstr "ΑντιγÏαφή διαδÏομής"
+#, fuzzy
+msgid "New Folder.."
+msgstr "ΔημιουÏγία φακέλου"
#: editor/filesystem_dock.cpp
-msgid "Rename or Move.."
-msgstr "Μετονομασία ή μετακίνηση.."
+msgid "Show In File Manager"
+msgstr "Εμφάνιση στη διαχείÏιση αÏχείων"
#: editor/filesystem_dock.cpp
-msgid "Move To.."
-msgstr "Μετακίνηση σε..."
+msgid "Instance"
+msgstr "Στιγμιότυπο"
#: editor/filesystem_dock.cpp
-msgid "Info"
-msgstr "ΠληÏοφοÏίες"
+msgid "Edit Dependencies.."
+msgstr "ΕπεξεÏγασία εξαÏτήσεων .."
#: editor/filesystem_dock.cpp
-msgid "Re-Import.."
-msgstr "Εκ νέου εισαγωγή..."
+msgid "View Owners.."
+msgstr "ΠÏοβολή Ιδιοκτητών .."
#: editor/filesystem_dock.cpp
msgid "Previous Directory"
@@ -2652,11 +2557,18 @@ msgid ""
"Scanning Files,\n"
"Please Wait.."
msgstr ""
+"ΣάÏωση αÏχείων,\n"
+"ΠαÏακαλώ πεÏιμένετε.."
#: editor/filesystem_dock.cpp
msgid "Move"
msgstr "Μετακίνηση"
+#: editor/filesystem_dock.cpp editor/plugins/animation_tree_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Rename"
+msgstr "Μετονομασία"
+
#: editor/groups_editor.cpp
msgid "Add to Group"
msgstr "ΠÏοσθήκη σε Ομάδα"
@@ -2666,76 +2578,87 @@ msgid "Remove from Group"
msgstr "ΚατάÏγηση από την ομάδα"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Import as Single Scene"
-msgstr "Εισαγωγή σκηνής..."
+msgstr "Εισαγωγή ως μονή σκηνή"
+
+#: editor/import/resource_importer_scene.cpp
+#, fuzzy
+msgid "Import with Separate Animations"
+msgstr "Εισαγωγή με ξεχωÏιστά υλικά"
#: editor/import/resource_importer_scene.cpp
msgid "Import with Separate Materials"
-msgstr ""
+msgstr "Εισαγωγή με ξεχωÏιστά υλικά"
#: editor/import/resource_importer_scene.cpp
msgid "Import with Separate Objects"
-msgstr ""
+msgstr "Εισαγωγή με ξεχωÏιστά αντικείμενα"
#: editor/import/resource_importer_scene.cpp
msgid "Import with Separate Objects+Materials"
-msgstr ""
+msgstr "Εισαγωγή με ξεχωÏιστά υλικά και αντικείμενα"
+
+#: editor/import/resource_importer_scene.cpp
+#, fuzzy
+msgid "Import with Separate Objects+Animations"
+msgstr "Εισαγωγή με ξεχωÏιστά υλικά και αντικείμενα"
#: editor/import/resource_importer_scene.cpp
#, fuzzy
+msgid "Import with Separate Materials+Animations"
+msgstr "Εισαγωγή με ξεχωÏιστά υλικά"
+
+#: editor/import/resource_importer_scene.cpp
+#, fuzzy
+msgid "Import with Separate Objects+Materials+Animations"
+msgstr "Εισαγωγή με ξεχωÏιστά υλικά και αντικείμενα"
+
+#: editor/import/resource_importer_scene.cpp
msgid "Import as Multiple Scenes"
-msgstr "Εισαγωγή 3D σκηνής"
+msgstr "Εισαγωγή ως πολλαπλές σκηνές"
#: editor/import/resource_importer_scene.cpp
msgid "Import as Multiple Scenes+Materials"
-msgstr ""
+msgstr "Εισαγωγή ως πολλαπλές σκηνές και υλικά"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Import Scene"
msgstr "Εισαγωγή σκηνής"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Importing Scene.."
msgstr "Εισαγωγή σκηνής..."
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Running Custom Script.."
msgstr "Εκτέλεση Ï€ÏοσαÏμοσμένης δέσμης ενεÏγειών..."
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Couldn't load post-import script:"
msgstr "Δεν ήταν δυνατή η φόÏτωση της δεσμής ενεÏγειών για μετά την εισαγωγή:"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Invalid/broken script for post-import (check console):"
msgstr ""
"ΆκυÏη / χαλασμένη δεσμή ενεÏγειών για την διαδικασία της μετ-εισαγωγής "
"(ελέγξτε την κονσόλα):"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Error running post-import script:"
msgstr "Σφάλμα κατά την εκτέλεση της δέσμης ενεÏγειών μετ-εισαγωγής:"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Saving.."
msgstr "Αποθήκευση..."
#: editor/import_dock.cpp
msgid "Set as Default for '%s'"
-msgstr ""
+msgstr "ΟÏισμός ως Ï€Ïοεπιλογής για '%s'"
#: editor/import_dock.cpp
msgid "Clear Default for '%s'"
-msgstr ""
+msgstr "ΕκκαθάÏιση Ï€Ïοεπιλογής για '%s'"
#: editor/import_dock.cpp
msgid " Files"
@@ -2747,585 +2670,12 @@ msgstr "Εισαγωγή ώς:"
#: editor/import_dock.cpp editor/property_editor.cpp
msgid "Preset.."
-msgstr "ΠÏοκαθοÏισμένο..."
+msgstr "ΔιαμόÏφωση..."
#: editor/import_dock.cpp
msgid "Reimport"
msgstr "Επανεισαγωγή"
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "No bit masks to import!"
-msgstr "Δεν υπάÏχουν μάσκες bit για εισαγωγή!"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path is empty."
-msgstr "Η διαδÏομή Ï€ÏοοÏÎ¹ÏƒÎ¼Î¿Ï ÎµÎ¯Î½Î±Î¹ άδεια."
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must be a complete resource path."
-msgstr "Η διαδÏομή Ï€ÏοοÏÎ¹ÏƒÎ¼Î¿Ï Ï€Ïέπει να είναι μία πλήÏης διαδÏομή σε πόÏο."
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must exist."
-msgstr "Η διαδÏομή Ï€ÏοοÏÎ¹ÏƒÎ¼Î¿Ï Ï€Ïέπει να υπάÏχει."
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Save path is empty!"
-msgstr "Η διαδÏομή αποθήκευσης είναι άδεια!"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Import BitMasks"
-msgstr "Εισαγωγή μάσκας bit"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s):"
-msgstr "Πηγαίες υφές:"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Target Path:"
-msgstr "ΔιαδÏομή Ï€ÏοοÏισμοÏ:"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Accept"
-msgstr "Αποδοχή"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Bit Mask"
-msgstr "Μάσκα bit"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No source font file!"
-msgstr "Δεν δόθηκε πηγαίο αÏχείο γÏαμματοσειÏάς!"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No target font resource!"
-msgstr "Δε δόθηκε πόÏος γÏαμματοσειÏάς Ï€ÏοοÏισμοÏ!"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"Invalid file extension.\n"
-"Please use .font."
-msgstr ""
-"ΆκυÏη επέκταση αÏχείου.\n"
-"ΠαÏακαλώ χÏησιμοποιήστε .font."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Can't load/process source font."
-msgstr "Δεν ήταν δυνατή η φόÏτωση/επεξεÏγασία της πηγαίας γÏαμματοσειÏάς."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Couldn't save font."
-msgstr "Δεν ήταν δυνατή η αποθήκευση της γÏαμματοσειÏάς."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font:"
-msgstr "Πηγαία γÏαμματοσειÏά:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font Size:"
-msgstr "Μέγεθος πηγαίας γÏαμματοσειÏάς:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Dest Resource:"
-msgstr "ΠόÏος Ï€ÏοοÏισμοÏ:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "The quick brown fox jumps over the lazy dog."
-msgstr "Γαζέες καὶ μυÏτιὲς δὲν θὰ βÏῶ πιὰ στὸ χÏυσαφὶ ξέφωτο."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Test:"
-msgstr "Δοκιμή:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Options:"
-msgstr "Επιλογές:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Font Import"
-msgstr "Εισαγωγή γÏαμματοσειÏάς"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"This file is already a Godot font file, please supply a BMFont type file "
-"instead."
-msgstr ""
-"Αυτό το αÏχείο είναι ήδη ένα αÏχείο γÏαμματοσειÏάς της Godot, παÏακαλώ "
-"υποβάλετε ένα αÏχείο Ï„Ïπου BMFont."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Failed opening as BMFont file."
-msgstr "Απέτυχε το άνοιγμα ως αÏχείο BMFont."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error initializing FreeType."
-msgstr "Σφάλμα κατά την αÏχικοποίηση του FreeType."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Unknown font format."
-msgstr "Άγνωστη μοÏφή γÏαμματοσειÏάς."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error loading font."
-msgstr "Σφάλμα κατά την φόÏτωση της γÏαμματοσειÏάς."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Invalid font size."
-msgstr "Μη έγκυÏο μέγεθος γÏαμματοσειÏάς."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Invalid font custom source."
-msgstr "ΆκυÏη Ï€ÏοσαÏμοσμένη πηγή γÏαμματοσειÏάς."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/plugins/theme_editor_plugin.cpp
-msgid "Font"
-msgstr "ΓÏαμματοσειÏά"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "No meshes to import!"
-msgstr "Δεν υπάÏχουν πλέγματα για εισαγωγή!"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Single Mesh Import"
-msgstr "Εισαγωγή ενός πλέγματος"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Source Mesh(es):"
-msgstr "Πηγαία πλέγματα:"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/plugins/mesh_instance_editor_plugin.cpp
-msgid "Mesh"
-msgstr "Πλέγμα"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Surface %d"
-msgstr "Επιφάνεια %d"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "No samples to import!"
-msgstr "Δεν υπάÏχουν δείγματα για εισαγωγή!"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Import Audio Samples"
-msgstr "Εισαγωγή δειγμάτων ήχου"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Source Sample(s):"
-msgstr "Πηγαία δείγματα:"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Audio Sample"
-msgstr "Δείγμα ήχου"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "New Clip"
-msgstr "Îέο απόσπασμα"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Animation Options"
-msgstr "Επιλογές κίνησης"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Flags"
-msgstr "Σημαίες"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Bake FPS:"
-msgstr "Ψήστε FPS:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Optimizer"
-msgstr "ΕÏγαλείο βελτιστοποίησης"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Linear Error"
-msgstr "Μέγιστο γÏαμμικό σφάλμα"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angular Error"
-msgstr "Μέγιστο γωνιακό σφάλμα"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angle"
-msgstr "Ανώτατη Γωνία"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Clips"
-msgstr "Αποσπάσματα"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Start(s)"
-msgstr "ΑÏχή"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "End(s)"
-msgstr "Τέλος"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Loop"
-msgstr "Επανάληψη"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Filters"
-msgstr "ΦίλτÏα"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source path is empty."
-msgstr "Η διαδÏομή Ï€Ïοέλευσης είναι άδεια."
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't load post-import script."
-msgstr "Δεν ήταν δυνατή η φόÏτωση της δεσμής ενεÏγειών μετ-εισαγωγής."
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Invalid/broken script for post-import."
-msgstr ""
-"ΆκυÏη / χαλασμένη δεσμή ενεÏγειών για την διαδικασία της μετ-εισαγωγής."
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Error importing scene."
-msgstr "Σφάλμα κατά την εισαγωγή της σκηνής."
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import 3D Scene"
-msgstr "Εισαγωγή 3D σκηνής"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source Scene:"
-msgstr "Σκηνή Ï€Ïοέλευσης:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Same as Target Scene"
-msgstr "Το ίδιο με την στοχευμένη σκηνή"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Shared"
-msgstr "ΚοινόχÏηστο"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Target Texture Folder:"
-msgstr "Επιλεγμένος φάκλος υφών:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Post-Process Script:"
-msgstr "Δεσμή ενεÏγειών μετ-επεξεÏγασίας:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Custom Root Node Type:"
-msgstr "ΠÏοσαÏμοσμένος Ï„Ïπος ÏÎ¹Î¶Î¹ÎºÎ¿Ï ÎºÏŒÎ¼Î²Î¿Ï…:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Auto"
-msgstr "Αυτόματο"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Root Node Name:"
-msgstr "Όνομα ÏÎ¹Î¶Î¹ÎºÎ¿Ï ÎºÏŒÎ¼Î²Î¿Ï…:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "The Following Files are Missing:"
-msgstr "Τα ακόλουθα αÏχεία λείπουν:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Anyway"
-msgstr "Εισαγωγή οÏτως ή άλλως"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp scene/gui/dialogs.cpp
-msgid "Cancel"
-msgstr "ΑκÏÏωση"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import & Open"
-msgstr "Εισαγωγή & Άνοιγμα"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Edited scene has not been saved, open imported scene anyway?"
-msgstr ""
-"Η Ï„Ïέχουσα σκηνή δεν έχει αποθηκευτεί, άνοιγμα της εισαγμένης σκηνής οÏτως ή "
-"άλλως;"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Image:"
-msgstr "Εισαγωγή εικόνας:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Can't import a file over itself:"
-msgstr "Δεν είναι δυνατή η εισαγωγή ενός αÏχείου πάνω στον εαυτό του:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't localize path: %s (already local)"
-msgstr ""
-"Δεν είναι δυνατή η μετατÏοπή της διαδÏομής σε τοπική: %s (είναι ήδη τοπικό)"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "3D Scene Animation"
-msgstr "Κίνηση Ï„Ïισδιάστατης σκηνής"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Uncompressed"
-msgstr "Ασυμπίεστο"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossless (PNG)"
-msgstr "Συμπίεση χωÏίς απώλειες (PNG)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossy (WebP)"
-msgstr "Συμπίεση με απώλειες (WebP)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress (VRAM)"
-msgstr "Συμπίεση (VRAM)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Format"
-msgstr "ΜοÏφή υφής"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Compression Quality (WebP):"
-msgstr "Ποιότητα συμπίεσης υφής (WebP):"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Options"
-msgstr "Επιλογές υφής"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Please specify some files!"
-msgstr "ΠαÏακαλώ καθοÏίστε κάποια αÏχεία!"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "At least one file needed for Atlas."
-msgstr "Τουλάχιστον ένα αÏχείο απαιτείται για τον άτλαντα."
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Error importing:"
-msgstr "Σφάλμα κατά την εισαγωγή:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Only one file is required for large texture."
-msgstr "Μόνο ένα αÏχείο είναι απαÏαίτητη για μεγάλη υφή."
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Max Texture Size:"
-msgstr "Μέγιστο μέγεθος υφής:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for Atlas (2D)"
-msgstr "Εισαγωγή υφών για τον άτλαντα (2D)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cell Size:"
-msgstr "Μέγεθος κελιοÏ:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Large Texture"
-msgstr "Μεγάλη υφή"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Textures (2D)"
-msgstr "Εισαγωγής Μεγάλων Υφών (2D)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture"
-msgstr "Υφή Ï€Ïοέλευσης"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Base Atlas Texture"
-msgstr "Βασική υφή άτλαντα"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s)"
-msgstr "Υφές Ï€Ïοέλευσης"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 2D"
-msgstr "Εισαγωγή υφών για 2 διαστάσεις"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 3D"
-msgstr "Εισαγωγή υφών για 3 διαστάσεις"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures"
-msgstr "Εισαγωγή υφών"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "2D Texture"
-msgstr "Υφή 2 διαστάσεων"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "3D Texture"
-msgstr "Υφή 3 διαστάσεων"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Atlas Texture"
-msgstr "Υφή άτλαντα"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid ""
-"NOTICE: Importing 2D textures is not mandatory. Just copy png/jpg files to "
-"the project."
-msgstr ""
-"ΣΗΜΕΙΩΣΗ: Η εισαγωγή δισδιάστατων υφών δεν είναι υποχÏεωτική. Απλά "
-"αντιγÏάψτε τα αÏχεία png/jpg στο έÏγο."
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Crop empty space."
-msgstr "ΠεÏικοπή άδειου χώÏου."
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture"
-msgstr "Υφή"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Texture"
-msgstr "Εισαγωγή μεγάλης υφής"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Load Source Image"
-msgstr "ΦόÏτωση εικόνας Ï€Ïοέλευσης"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Slicing"
-msgstr "Κατάτμηση"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Inserting"
-msgstr "Εισαγωγή"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Saving"
-msgstr "Αποθήκευση"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save large texture:"
-msgstr "Δεν ήταν δυνατή η αποθήκευση μεγάλης υφής:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Build Atlas For:"
-msgstr "Κατασκευή άτλαντα για:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Loading Image:"
-msgstr "ΦόÏτωση εικόνας:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't load image:"
-msgstr "Δεν ήταν δυνατή η φόÏτωση της εικόνας:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Converting Images"
-msgstr "ΜετατÏοπή Εικόνων"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cropping Images"
-msgstr "ΠεÏικοπή Εικόνων"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Blitting Images"
-msgstr "Συνδυασμός εικόνων"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save atlas image:"
-msgstr "Δεν ήταν δυνατή η αποθήκευση εικόνας άτλαντα:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save converted texture:"
-msgstr "Δεν ήταν δυνατή η αποθήκευση υφής που έχει μετατÏαπεί:"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid source!"
-msgstr "Μη έγκυÏη πηγή!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid translation source!"
-msgstr "Μη έγκυÏη πηγή μετάφÏασης!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Column"
-msgstr "Στήλη"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/script_create_dialog.cpp
-msgid "Language"
-msgstr "Γλώσσα"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No items to import!"
-msgstr "Δεν υπάÏχουν στοιχεία για εισαγωγή!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No target path!"
-msgstr "Καμία διαδÏομή Ï€ÏοοÏισμοÏ!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translations"
-msgstr "Εισαγωγή μεταφÏάσεων"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Couldn't import!"
-msgstr "Δεν ήταν δυνατή η εισαγωγή!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translation"
-msgstr "Εισαγωγή μετάφÏασης"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Source CSV:"
-msgstr "CSV Ï€Ïοέλευσης:"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Ignore First Row"
-msgstr "Αγνόησε την Ï€Ïώτη γÏαμμή"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Compress"
-msgstr "Συμπίεση"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Add to Project (project.godot)"
-msgstr "ΠÏόσθεσε στο έÏγο (project.godot)"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Languages:"
-msgstr "Εισαγωγή γλωσσών:"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Translation"
-msgstr "ΜετάφÏαση"
-
#: editor/multi_node_edit.cpp
msgid "MultiNode Set"
msgstr "Σετ πολλαπλών κόμβων"
@@ -3338,6 +2688,49 @@ msgstr "Ομάδες"
msgid "Select a Node to edit Signals and Groups."
msgstr "Επιλέξτε ένα κόμβο για να επεξεÏγαστείτε τα σήματα και τις ομάδες."
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create Poly"
+msgstr "Δημιουγία πολυγώνου"
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly"
+msgstr "ΕπεγεÏγασία πολυγώνου"
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#, fuzzy
+msgid "Insert Point"
+msgstr "Εισαγωγή"
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly (Remove Point)"
+msgstr "ΕπεγεÏγασία πολυγώνου (ΑφαίÏεση σημείου)"
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Remove Poly And Point"
+msgstr "ΑφαίÏεση πολυγώνου και σημείου"
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create a new polygon from scratch."
+msgstr "ΔημιουÏγία νέου πολυγώνου από την αÏχή."
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid ""
+"Edit existing polygon:\n"
+"LMB: Move Point.\n"
+"Ctrl+LMB: Split Segment.\n"
+"RMB: Erase Point."
+msgstr ""
+"ΕπεξεÏγασία υπαÏÎºÏ„Î¿Ï Ï€Î¿Î»Ï…Î³ÏŒÎ½Î¿Ï…:\n"
+"ΑÏιστεÏÏŒ κλικ: Μετακίνηση σημείου.\n"
+"Ctrl + ΑÏιστεÏÏŒ κλικ: ΔιαίÏεση τμήματος.\n"
+"Δεξί κλικ: ΔιαγÏαφή σημείου."
+
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Toggle Autoplay"
msgstr "Εναλλαγή αυτόματης αναπαÏαγωγής"
@@ -3491,7 +2884,6 @@ msgstr "Όνομα κίνησης:"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
#: editor/script_create_dialog.cpp
msgid "Error!"
@@ -3519,9 +2911,8 @@ msgid "New name:"
msgstr "Îέο όνομα:"
#: editor/plugins/animation_tree_editor_plugin.cpp
-#, fuzzy
msgid "Edit Filters"
-msgstr "ΕπεξεÏγασία φίλτÏων κόμβων"
+msgstr "ΕπεξεÏγασία φίλτÏων"
#: editor/plugins/animation_tree_editor_plugin.cpp
#: editor/plugins/multimesh_editor_plugin.cpp
@@ -3602,10 +2993,6 @@ msgid "Delete Input"
msgstr "ΔιαγÏαφή εισόδου"
#: editor/plugins/animation_tree_editor_plugin.cpp
-msgid "Rename"
-msgstr "Μετονομασία"
-
-#: editor/plugins/animation_tree_editor_plugin.cpp
msgid "Animation tree is valid."
msgstr "Το δέντÏο κίνησης είναι έγκυÏο."
@@ -3661,66 +3048,182 @@ msgstr "ΕπεξεÏγασία φίλτÏων κόμβων"
msgid "Filters.."
msgstr "ΦίλτÏα.."
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing %d Triangles:"
-msgstr "Ανάλυση %d ΤÏιγώνων:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Free"
+msgstr "ΔωÏεάν"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Triangle #"
-msgstr "ΤÏίγωνο #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Contents:"
+msgstr "ΠεÏιεχόμενα:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Light Baker Setup:"
-msgstr "ΡÏθμιση Ï€ÏοεπεγεÏγαστή φωτός:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "View Files"
+msgstr "ΠÏοβολή αÏχείων"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing Geometry"
-msgstr "Ανάλυση γεωμετÏίας"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve hostname:"
+msgstr "Δεν είναι δυνατή η επίλυση του ονόματος του κεντÏÎ¹ÎºÎ¿Ï Ï…Ï€Î¿Î»Î¿Î³Î¹ÏƒÏ„Î®:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Fixing Lights"
-msgstr "ΔιόÏθωση φώτων"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve."
+msgstr "Δεν είναι δυνατή η επίλυση."
-#: editor/plugins/baked_light_baker.cpp
-msgid "Making BVH"
-msgstr "ΔημιουÏγία BVH"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connection error, please try again."
+msgstr "Σφάλμα σÏνδεσης, παÏακαλώ ξαναπÏοσπαθήστε."
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Light Octree"
-msgstr "ΔημιουÏγία Î¿ÎºÏ„Î±Î´Î¹ÎºÎ¿Ï Î´Î­Î½Ï„Ïου φωτός"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't connect."
+msgstr "Δεν ήταν δυνατή η σÏνδεση."
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Octree Texture"
-msgstr "ΔημιουÏγία υφής Î¿ÎºÏ„Î±Î´Î¹ÎºÎ¿Ï Î´Î­Î½Ï„Ïου"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't connect to host:"
+msgstr "Δεν ήταν δυνατή η σÏνδεση στον κεντÏικό υπολογιστή:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Transfer to Lightmaps:"
-msgstr "ΜεταφοÏά στους χάÏτες φωτός:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response from host:"
+msgstr "Δεν λήφθηκε απόκÏιση από τον κεντÏικό υπολογιστή:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Allocating Texture #"
-msgstr "Δέσμευση υφής #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response."
+msgstr "Δεν λήφθηκε απόκÏιση."
-#: editor/plugins/baked_light_baker.cpp
-msgid "Baking Triangle #"
-msgstr "ΠÏοεπεξεÏγασία Ï„Ïιγώνου #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, return code:"
+msgstr "Το αίτημα απέτυχε, κώδικας επιστÏοφής:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Post-Processing Texture #"
-msgstr "ΜετεπεξεÏγασία υφής #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Req. Failed."
+msgstr "Το αίτημα απέτυχε."
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Bake!"
-msgstr "ΠÏοεπεξεÏγάσου!"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, too many redirects"
+msgstr "Το αίτημα απέτυχε, πάÏα πολλές ανακατευθήνσεις"
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Reset the lightmap octree baking process (start over)."
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Redirect Loop."
+msgstr "Î’Ïόχος ανακατευθήνσεων."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed:"
+msgstr "Απέτυχε:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Bad download hash, assuming file has been tampered with."
msgstr ""
-"ΕπαναφοÏά της Ï€ÏοεπεξεÏγασίας του Î¿ÎºÏ„Î±Î´Î¹ÎºÎ¿Ï Î´Î­Î½Ï„Ïου του χάÏτη φωτός "
-"(Εκκίνηση από την αÏχή)."
+"Εσφαλμένος κωδικός κατακεÏματισμοÏ, θα θεωÏηθεί ότι το αÏχείο έχει αλοιωθεί."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Expected:"
+msgstr "Αναμενόμενο:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Got:"
+msgstr "Δοσμένο:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed sha256 hash check"
+msgstr "Η δοκιμή κατακεÏÎ¼Î±Ï„Î¹ÏƒÎ¼Î¿Ï sha256 απέτυχε"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Asset Download Error:"
+msgstr "Σφάλμα λήψης:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Fetching:"
+msgstr "Λήψη:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Resolving.."
+msgstr "Επίλυση..."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connecting.."
+msgstr "ΣÏνδεση.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Requesting.."
+msgstr "Γίνεται αίτημα.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Error making request"
+msgstr "Σφάλμα κατά την Ï€Ïαγματοποίηση αιτήματος"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Idle"
+msgstr "ΑνενεÏγό"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Retry"
+msgstr "Ξαναδοκίμασε"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download Error"
+msgstr "Σφάλμα λήψης"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download for this asset is already in progress!"
+msgstr "Η λήψη είναι ήδη σε εξέλιξη!"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "first"
+msgstr "ΠÏώτο"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "prev"
+msgstr "ΠÏοηγοÏμενο"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "next"
+msgstr "Επόμενο"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "last"
+msgstr "ΠÏοηγοÏμενο"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "All"
+msgstr "Όλα"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Plugins"
+msgstr "ΠÏόσθετα"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Sort:"
+msgstr "Ταξινόμηση:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Reverse"
+msgstr "ΑντιστÏοφή"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Category:"
+msgstr "ΚατηγοÏία:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Site:"
+msgstr "ΔιεÏθυνση:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Support.."
+msgstr "ΥποστήÏιξη.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Official"
+msgstr "Επίσημα"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Testing"
+msgstr "Δοκιμιμαστικά"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Assets ZIP File"
+msgstr "ΑÏχείο ZIP των Asset"
#: editor/plugins/camera_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
msgid "Preview"
msgstr "ΠÏοεπισκόπηση"
@@ -3763,12 +3266,18 @@ msgid "Edit CanvasItem"
msgstr "ΕπεξεÏγασία στοιχείου κανβά"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Change Anchors"
+#, fuzzy
+msgid "Anchors only"
+msgstr "ΆγκυÏα"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#, fuzzy
+msgid "Change Anchors and Margins"
msgstr "Αλλαγή αγκυÏών"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom (%):"
-msgstr "Μεγέθυνση (%):"
+msgid "Change Anchors"
+msgstr "Αλλαγή αγκυÏών"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Paste Pose"
@@ -3822,60 +3331,78 @@ msgid "Pan Mode"
msgstr "ΛειτουÏγία Μετακίνησης κάμεÏας"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Lock the selected object in place (can't be moved)."
-msgstr "Κλείδωμα του επιλεγμένου αντικείμένου (Δεν μποÏεί να μετακινηθεί)."
+#, fuzzy
+msgid "Toggles snapping"
+msgstr "Εναλλαγή σημείου διακοπής"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Unlock the selected object (can be moved)."
-msgstr "Ξεκλείδωμα του επιλεγμένου αντικείμένου (ΜποÏεί να μετακινηθεί)."
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Use Snap"
+msgstr "ΧÏήση κουμπώματος"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Makes sure the object's children are not selectable."
-msgstr "ΣιγουÏεÏεται ότι τα παιδιά του αντικειμένου δεν μποÏοÏν να επιλεχθοÏν."
+#, fuzzy
+msgid "Snapping options"
+msgstr "Επιλογές κίνησης"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Restores the object's children's ability to be selected."
-msgstr "ΕπαναφέÏει την δυνατότητα των παιδιών του αντικειμένου να επιλεγοÏν."
+#, fuzzy
+msgid "Snap to grid"
+msgstr "ΛειτουÏγία κουμπώματος:"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Edit"
-msgstr "ΕπεξεÏγασία"
+msgid "Use Rotation Snap"
+msgstr "ΧÏήση κουμπώματος πεÏιστÏοφής"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Use Snap"
-msgstr "ΧÏήση κουμπώματος"
+#, fuzzy
+msgid "Configure Snap..."
+msgstr "ΔιαμόÏφωση κουμπώματος.."
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Show Grid"
-msgstr "Εμφάνιση πλέγματος"
+msgid "Snap Relative"
+msgstr "Σχετικό κοÏμπωμα"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Rotation Snap"
-msgstr "ΧÏήση κουμπώματος πεÏιστÏοφής"
+msgid "Use Pixel Snap"
+msgstr "ΧÏήση κουμπώματος εικονοστοιχείου"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap Relative"
-msgstr "Σχετικό κοÏμπωμα"
+msgid "Smart snapping"
+msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Configure Snap.."
-msgstr "ΔιαμόÏφωση κουμπώματος.."
+#, fuzzy
+msgid "Snap to parent"
+msgstr "Επικάλυψη γονέα"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Pixel Snap"
-msgstr "ΧÏήση κουμπώματος εικονοστοιχείου"
+msgid "Snap to node anchor"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to node sides"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to other nodes"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Lock the selected object in place (can't be moved)."
+msgstr "Κλείδωμα του επιλεγμένου αντικείμένου (Δεν μποÏεί να μετακινηθεί)."
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Unlock the selected object (can be moved)."
+msgstr "Ξεκλείδωμα του επιλεγμένου αντικείμένου (ΜποÏεί να μετακινηθεί)."
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Skeleton.."
-msgstr "Σκελετός.."
+msgid "Makes sure the object's children are not selectable."
+msgstr "ΣιγουÏεÏεται ότι τα παιδιά του αντικειμένου δεν μποÏοÏν να επιλεχθοÏν."
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Restores the object's children's ability to be selected."
+msgstr "ΕπαναφέÏει την δυνατότητα των παιδιών του αντικειμένου να επιλεγοÏν."
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Make Bones"
@@ -3903,12 +3430,19 @@ msgid "View"
msgstr "ΚάμεÏα"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Reset"
-msgstr "ΕπαναφοÏά μεγέθυνσης"
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Show Grid"
+msgstr "Εμφάνιση πλέγματος"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Set.."
-msgstr "ΟÏισμός μεγέθυνσης.."
+#, fuzzy
+msgid "Show helpers"
+msgstr "Εμφάνιση οστών"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#, fuzzy
+msgid "Show rulers"
+msgstr "Εμφάνιση οστών"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Center Selection"
@@ -3919,8 +3453,9 @@ msgid "Frame Selection"
msgstr "Πλαισίωμα επιλογής"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Anchor"
-msgstr "ΆγκυÏα"
+#, fuzzy
+msgid "Layout"
+msgstr "Αποθήκευση διάταξης"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Insert Keys"
@@ -3943,12 +3478,21 @@ msgid "Clear Pose"
msgstr "ΕκκαθάÏιση στάσης"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Set a Value"
-msgstr "ΟÏισμός τιμής"
+msgid "Drag pivot from mouse position"
+msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap (Pixels):"
-msgstr "ΚοÏμπωμα (Εικονοστοιχεία):"
+#, fuzzy
+msgid "Set pivot at mouse position"
+msgstr "ΟÏισμός θέσης εξόδου καμπÏλης"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Multiply grid step by 2"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Divide grid step by 2"
+msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Add %s"
@@ -3958,24 +3502,29 @@ msgstr "ΠÏόσθεσε %s"
msgid "Adding %s..."
msgstr "ΠÏοσθήκη %s..."
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Create Node"
msgstr "ΔημιουÏγία κόμβου"
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Error instancing scene from %s"
msgstr "Σφάλμα κατά την αÏχικοποίηση σκηνής από %s"
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "OK :("
msgstr "Εντάξει :("
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "No parent to instance a child at."
msgstr ""
"Δεν υπάÏχει γονέας στον οποίο μποÏεί να γίνει αÏχικοποίηση του παιδιοÏ."
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "This operation requires a single selected node."
msgstr "Αυτή η λειτουÏγία απαιτεί έναν μόνο επιλεγμένο κόμβο."
@@ -3991,45 +3540,6 @@ msgstr ""
"ΣÏÏσιμο & απόθεση + Shift: ΠÏοσθήκη του κόμβου ως αδελφό\n"
"ΣÏÏσιμο & απόθεση + Alt: Αλλαγή του Ï„Ïπου του κόμβου"
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Create Poly"
-msgstr "Δημιουγία πολυγώνου"
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly"
-msgstr "ΕπεγεÏγασία πολυγώνου"
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly (Remove Point)"
-msgstr "ΕπεγεÏγασία πολυγώνου (ΑφαίÏεση σημείου)"
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Create a new polygon from scratch."
-msgstr "ΔημιουÏγία νέου πολυγώνου από την αÏχή."
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-msgid ""
-"Edit existing polygon:\n"
-"LMB: Move Point.\n"
-"Ctrl+LMB: Split Segment.\n"
-"RMB: Erase Point."
-msgstr ""
-
#: editor/plugins/collision_polygon_editor_plugin.cpp
msgid "Create Poly3D"
msgstr "ΔημιουÏγία πολυγώνου 3D"
@@ -4039,14 +3549,6 @@ msgid "Set Handle"
msgstr "ΟÏισμός λαβής"
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Creating Mesh Library"
-msgstr "ΔημιουÏγία βιβλιοθήκης πλεγμάτων"
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Thumbnail.."
-msgstr "ΜικÏογÏαφία.."
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Remove item %d?"
msgstr "ΑφαίÏεση του στοιχείου %d?"
@@ -4069,19 +3571,38 @@ msgid "Update from Scene"
msgstr "ΑναπÏοσαÏμογή από την σκηνή"
#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat0"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat1"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
#, fuzzy
-msgid "Modify Curve Point"
-msgstr "ΤÏοποπίηση καμπÏλης"
+msgid "Ease in"
+msgstr "Ομαλή κίνηση Ï€Ïος τα μέσα"
#: editor/plugins/curve_editor_plugin.cpp
#, fuzzy
+msgid "Ease out"
+msgstr "Ομαλή κίνηση Ï€Ïος τα έξω"
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Smoothstep"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Modify Curve Point"
+msgstr "ΤÏοποπίηση σημείου καμπÏλης"
+
+#: editor/plugins/curve_editor_plugin.cpp
msgid "Modify Curve Tangent"
-msgstr "ΤÏοποποίηση χάÏτη καμπÏλης"
+msgstr "ΤÏοποπίηση εφαπτομένης καμπÏλης"
#: editor/plugins/curve_editor_plugin.cpp
-#, fuzzy
msgid "Load Curve Preset"
-msgstr "ΦόÏτωση Ï€ÏοκαθοÏισμένης"
+msgstr "ΦόÏτωση Ï€ÏοκαθοÏισμένης καμπÏλης"
#: editor/plugins/curve_editor_plugin.cpp
msgid "Add point"
@@ -4092,31 +3613,28 @@ msgid "Remove point"
msgstr "ΑφαίÏεση σημείου"
#: editor/plugins/curve_editor_plugin.cpp
-#, fuzzy
msgid "Left linear"
-msgstr "ΓÏαμμική"
+msgstr "ΑÏιστεÏή γÏαμμική"
#: editor/plugins/curve_editor_plugin.cpp
-#, fuzzy
msgid "Right linear"
-msgstr "Δεξιά όψη"
+msgstr "Δεξιά γÏαμμική"
#: editor/plugins/curve_editor_plugin.cpp
msgid "Load preset"
-msgstr "ΦόÏτωση Ï€ÏοκαθοÏισμένης"
+msgstr "ΦόÏτωση διαμόÏφωσης"
#: editor/plugins/curve_editor_plugin.cpp
-#, fuzzy
msgid "Remove Curve Point"
-msgstr "ΑφαίÏεση σημείου διαδÏομής"
+msgstr "ΑφαίÏεση σημείου καμπÏλης"
#: editor/plugins/curve_editor_plugin.cpp
msgid "Toggle Curve Linear Tangent"
-msgstr ""
+msgstr "Εναλλαγή γÏαμμικής εφαπτομένης καμπÏλης"
#: editor/plugins/curve_editor_plugin.cpp
msgid "Hold Shift to edit tangents individually"
-msgstr ""
+msgstr "Πατήστε το Shift για να επεξεÏγαστείτε εφαπτομένες μεμονωμένα"
#: editor/plugins/gradient_editor_plugin.cpp
msgid "Add/Remove Color Ramp Point"
@@ -4144,28 +3662,26 @@ msgid ""
"No OccluderPolygon2D resource on this node.\n"
"Create and assign one?"
msgstr ""
+"Δεν υπάÏχει πόÏος OccluderPolygon2D σε αυτόν τον κόμβο.\n"
+"Îα δημιουÏγία και να οÏισθεί ένας;"
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
msgid "Create Occluder Polygon"
msgstr "ΔημιουÏγία πολυγώνου εμποδίου"
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Edit existing polygon:"
msgstr "ΕπεξεÏγασία υπαÏÎºÏ„Î¿Ï Ï€Î¿Î»Ï…Î³ÏŽÎ½Î¿Ï…:"
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "LMB: Move Point."
msgstr "ΑÏιστεÏÏŒ κλίκ: ΜΕτακίνηση σημείου."
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Ctrl+LMB: Split Segment."
msgstr "Ctrl+ΑÏιστεÏÏŒ κλικ: ΔιαχωÏσμός τμήματος."
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "RMB: Erase Point."
msgstr "Δεξί κλικ: ΔιαγÏαφή σημείου."
@@ -4266,6 +3782,10 @@ msgid "Create Outline"
msgstr "ΔημιουÏγία πεÏιγÏάμματος"
#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Mesh"
+msgstr "Πλέγμα"
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Create Trimesh Static Body"
msgstr "ΔημιουÏγία ÏƒÏ„Î±Ï„Î¹ÎºÎ¿Ï ÏƒÏŽÎ¼Î±Ï„Î¿Ï‚ πλέγματος Ï„Ïιγώνων"
@@ -4395,14 +3915,83 @@ msgstr "Τυχαία κλιμάκωση:"
msgid "Populate"
msgstr "ΣυμπλήÏωση"
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake!"
+msgstr "ΠÏοεπεξεÏγάσου!"
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+#, fuzzy
+msgid "Bake the navigation mesh.\n"
+msgstr "ΔημιουÏγία πλέγματος πλοήγησης"
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+#, fuzzy
+msgid "Clear the navigation mesh."
+msgstr "ΔημιουÏγία πλέγματος πλοήγησης"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Setting up Configuration..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Calculating grid size..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Creating heightfield..."
+msgstr "ΔημιουÏγία Î¿ÎºÏ„Î±Î´Î¹ÎºÎ¿Ï Î´Î­Î½Ï„Ïου φωτός"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Marking walkable triangles..."
+msgstr "ΜεταφÏάσιμες συμβολοσειÏές..."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Constructing compact heightfield..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Eroding walkable area..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Partitioning..."
+msgstr "ΠÏοειδοποίηση"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Creating contours..."
+msgstr "ΔημιουÏγία υφής Î¿ÎºÏ„Î±Î´Î¹ÎºÎ¿Ï Î´Î­Î½Ï„Ïου"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Creating polymesh..."
+msgstr "ΔημιουÏγία πλέγματος πεÏιγÏάμματος.."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Converting to native navigation mesh..."
+msgstr "ΔημιουÏγία πλέγματος πλοήγησης"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Navigation Mesh Generator Setup:"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Parsing Geometry..."
+msgstr "Ανάλυση γεωμετÏίας"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Done!"
+msgstr ""
+
#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Create Navigation Polygon"
msgstr "ΔημιουÏγία πολυγώνου πλοήγησης"
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Remove Poly And Point"
-msgstr "ΑφαίÏεση πολυγώνου και σημείου"
-
#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Clear Emission Mask"
msgstr "ΕκκαθάÏιση μάσκας εκπομπής"
@@ -4440,9 +4029,8 @@ msgstr "ΦόÏτωση μάσκας εκπομπής"
#: editor/plugins/particles_2d_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp
-#, fuzzy
msgid "Particles"
-msgstr "ΚοÏυφές"
+msgstr "Σωματίδια"
#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Generated Point Count:"
@@ -4577,14 +4165,17 @@ msgid "Curve Point #"
msgstr "Σημείο καμπÏλης #"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve Point Position"
msgstr "ΟÏισμός θέσης σημείου καμπÏλης"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve In Position"
msgstr "ΟÏισμός θέσης εισόδου καμπÏλης"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve Out Position"
msgstr "ΟÏισμός θέσης εξόδου καμπÏλης"
@@ -4645,6 +4236,14 @@ msgid "Scale Polygon"
msgstr "Κλιμάκωση πολυγώνου"
#: editor/plugins/polygon_2d_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Edit"
+msgstr "ΕπεξεÏγασία"
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Polygon->UV"
msgstr "ΠολÏγωνο -> UV"
@@ -4699,63 +4298,10 @@ msgstr "ΦόÏτωση πόÏου"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/shader_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "Επικόληση"
-#: editor/plugins/rich_text_editor_plugin.cpp
-msgid "Parse BBCode"
-msgstr "Ανάλυση BBCode"
-
-#: editor/plugins/sample_editor_plugin.cpp
-msgid "Length:"
-msgstr "Μήκος:"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Open Sample File(s)"
-msgstr "Άνοιγμα αÏχείων δειγμάτων"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "ERROR: Couldn't load sample!"
-msgstr "ΣΦΑΛΜΑ: Δεν ήταν δυνατή η φόÏτωση δείγματος!"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Add Sample"
-msgstr "ΠÏοσθήκη δείγματος"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Rename Sample"
-msgstr "Μετονομασία δείγματος"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Delete Sample"
-msgstr "ΔιαγÏαφή δείγματος"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "16 Bits"
-msgstr "16 Δυαδικά ψηφία"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "8 Bits"
-msgstr "8 Δυαδικά ψηφία"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Stereo"
-msgstr "ΣτεÏεοφωνικό"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Mono"
-msgstr "Μονοφωνικό"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Format"
-msgstr "ΜοÏφή"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Pitch"
-msgstr "Τόνος"
-
#: editor/plugins/script_editor_plugin.cpp
msgid "Clear Recent Files"
msgstr "ΕκκαθάÏιση Ï€Ïόσφατων αÏχείων"
@@ -4765,6 +4311,8 @@ msgid ""
"Close and save changes?\n"
"\""
msgstr ""
+"Κλείσιμο και αποθήκευση αλλαγών;\n"
+"\""
#: editor/plugins/script_editor_plugin.cpp
msgid "Error while saving theme"
@@ -4792,7 +4340,7 @@ msgstr "Αποθήκευση θέματος ως.."
#: editor/plugins/script_editor_plugin.cpp
msgid " Class Reference"
-msgstr ""
+msgstr " ΑναφοÏά κλασεων"
#: editor/plugins/script_editor_plugin.cpp
msgid "Next script"
@@ -4846,10 +4394,13 @@ msgstr "Κλείσιμο τεκμηÏίωσης"
msgid "Close All"
msgstr "Κλείσιμο όλων"
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+msgid "Run"
+msgstr "Εκτέλεση"
+
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Toggle Scripts Panel"
-msgstr "Εναλλαγή αγαπημένου"
+msgstr "Εναλλαγή πλαισίου δεσμών ενεÏγειών"
#: editor/plugins/script_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
@@ -4875,7 +4426,8 @@ msgstr "Βήμα μέσα"
msgid "Break"
msgstr "Διακοπή"
-#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+#: editor/script_editor_debugger.cpp
msgid "Continue"
msgstr "Συνέχιση"
@@ -4884,21 +4436,8 @@ msgid "Keep Debugger Open"
msgstr "ΔιατήÏησε τον αποσφαλματωτή ανοιχτό"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Debug with external editor"
-msgstr "Άνοιγμα του επόμενου επεξεÏγαστή"
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Window"
-msgstr "ΠαÏάθυÏο"
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Left"
-msgstr "Μετκίνιση αÏιστεÏά"
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Right"
-msgstr "Μετακίνηση δεξιά"
+msgstr "Αποσφαλμάτωση με εξωτεÏικό επεξεÏγαστή"
#: editor/plugins/script_editor_plugin.cpp
msgid "Open Godot online documentation"
@@ -4957,7 +4496,7 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
msgid "Only resources from filesystem can be dropped."
-msgstr ""
+msgstr "Μόνο οι πόÏοι από το σÏστημα αÏχείων μποÏοÏν να διαγÏαφοÏν."
#: editor/plugins/script_text_editor.cpp
msgid "Pick Color"
@@ -4986,8 +4525,9 @@ msgid "Cut"
msgstr "Αποκοπή"
#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "ΑντιγÏαφή"
@@ -5006,9 +4546,8 @@ msgid "Move Down"
msgstr "Μετακίνηση κάτω"
#: editor/plugins/script_text_editor.cpp
-#, fuzzy
msgid "Delete Line"
-msgstr "ΔιαγÏαφή σημείου"
+msgstr "ΔιαγÏαφή γÏαμμής"
#: editor/plugins/script_text_editor.cpp
msgid "Indent Left"
@@ -5251,10 +4790,6 @@ msgid "View Plane Transform."
msgstr "Μετασχηματισμός στο επίπεδο θέασης."
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Scaling to %s%%."
-msgstr "Κλιμάκωση to %s%%."
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rotating %s degrees."
msgstr "ΠεÏιστÏοφή %s μοίÏες."
@@ -5271,10 +4806,6 @@ msgid "Top View."
msgstr "Πάνω όψη."
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Top"
-msgstr "Πάνω"
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rear View."
msgstr "Πίσω όψη."
@@ -5376,9 +4907,8 @@ msgid "Audio Listener"
msgstr "ΑκÏοατής ήχου"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Doppler Enable"
-msgstr "ΕνεÏγοποίηση"
+msgstr "ΕνεÏγοποίηση φαινομένου dollper"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Freelook Left"
@@ -5409,7 +4939,6 @@ msgid "Freelook Speed Modifier"
msgstr "ΤαχÏτητα ελεÏθεÏου κοιτάγματος"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "preview"
msgstr "ΠÏοεπισκόπηση"
@@ -5418,17 +4947,18 @@ msgid "XForm Dialog"
msgstr "Διάλογος XForm"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Select Mode (Q)\n"
-msgstr "Επιλογή λειτουÏγίας"
+msgstr "Επιλογή λειτουÏγίας (Q)\n"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid ""
"Drag: Rotate\n"
"Alt+Drag: Move\n"
"Alt+RMB: Depth list selection"
-msgstr "Alt+Δεξί κλικ: Επιλογή λίστας βάθους"
+msgstr ""
+"Μετακίνηση: ΠεÏιστÏοφή\n"
+"Alt + ΣÏÏσιμο: Μετακίνηση\n"
+"Alt + Δεξί κλικ: Επιλογή λίστας βάθους"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Move Mode (W)"
@@ -5507,6 +5037,10 @@ msgid "Transform"
msgstr "Μετασχηματισμός"
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Configure Snap.."
+msgstr "ΔιαμόÏφωση κουμπώματος.."
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Local Coords"
msgstr "Τοπικές συντεταγμένες"
@@ -5652,6 +5186,10 @@ msgid "Speed (FPS):"
msgstr "ΤαχÏτητα (FPS):"
#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Loop"
+msgstr "Επανάληψη"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Animation Frames"
msgstr "ΚαÏέ κίνησης"
@@ -5664,21 +5202,22 @@ msgid "Insert Empty (After)"
msgstr "Εισαγωγή άδειου (Μετά)"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Up"
-msgstr "Πάνω"
+#, fuzzy
+msgid "Move (Before)"
+msgstr "Μετακίνηση κόμβων"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Down"
-msgstr "Κάτω"
+#, fuzzy
+msgid "Move (After)"
+msgstr "Μετκίνιση αÏιστεÏά"
#: editor/plugins/style_box_editor_plugin.cpp
msgid "StyleBox Preview:"
msgstr "ΠÏοεπισκόπηση StyleBox:"
#: editor/plugins/texture_region_editor_plugin.cpp
-#, fuzzy
msgid "Set Region Rect"
-msgstr "ΠεÏιοχή υφής"
+msgstr "ΟÏισμός οÏθογωνίου πεÏιοχής"
#: editor/plugins/texture_region_editor_plugin.cpp
msgid "Snap Mode:"
@@ -5738,18 +5277,20 @@ msgid "Remove Item"
msgstr "ΑφαίÏεση στοιχείου"
#: editor/plugins/theme_editor_plugin.cpp
-#, fuzzy
msgid "Remove All Items"
-msgstr "ΑφαίÏεση στοιχείων κλάσης"
+msgstr "ΑφαίÏεση όλων των στοιχείων"
#: editor/plugins/theme_editor_plugin.cpp
-#, fuzzy
msgid "Remove All"
-msgstr "ΑφαίÏεση"
+msgstr "ΑφαίÏεση όλων"
#: editor/plugins/theme_editor_plugin.cpp
-msgid "Theme"
-msgstr "Θέμα"
+msgid "Edit theme.."
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Theme editing menu."
+msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
msgid "Add Class Items"
@@ -5833,11 +5374,14 @@ msgid "Style"
msgstr "Στυλ"
#: editor/plugins/theme_editor_plugin.cpp
+msgid "Font"
+msgstr "ΓÏαμματοσειÏά"
+
+#: editor/plugins/theme_editor_plugin.cpp
msgid "Color"
msgstr "ΧÏώμα"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Erase Selection"
msgstr "ΔιαγÏαφή επιλογής"
@@ -5846,18 +5390,16 @@ msgid "Paint TileMap"
msgstr "Βάψιμο TileMap"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Line Draw"
-msgstr "ΓÏαμμική"
+msgstr "Σχεδιασμός γÏαμμής"
#: editor/plugins/tile_map_editor_plugin.cpp
msgid "Rectangle Paint"
-msgstr ""
+msgstr "ΧÏωματοσμός οÏθογωνίου"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Bucket Fill"
-msgstr "Κουβάς"
+msgstr "Γέμισμα κουβά"
#: editor/plugins/tile_map_editor_plugin.cpp
msgid "Erase TileMap"
@@ -5884,8 +5426,9 @@ msgid "Mirror Y"
msgstr "ΣυμμετÏία στον άξονα Î¥"
#: editor/plugins/tile_map_editor_plugin.cpp
-msgid "Bucket"
-msgstr "Κουβάς"
+#, fuzzy
+msgid "Paint Tile"
+msgstr "Βάψιμο TileMap"
#: editor/plugins/tile_map_editor_plugin.cpp
msgid "Pick Tile"
@@ -5948,6 +5491,11 @@ msgid "Delete preset '%s'?"
msgstr "ΔιαγÏαφή διαμόÏφωσης '%s';"
#: editor/project_export.cpp
+#, fuzzy
+msgid "Export templates for this platform are missing/corrupted: "
+msgstr "Τα Ï€Ïότυπα εξαγωγής για αυτή την πλατφόÏτμα λείπουν:"
+
+#: editor/project_export.cpp
msgid "Presets"
msgstr "ΔιαμοÏφώσεις"
@@ -6002,53 +5550,80 @@ msgid "Make Patch"
msgstr "ΔημιουÏγία ενημέÏωσης"
#: editor/project_export.cpp
-#, fuzzy
msgid "Features"
-msgstr "Υφή"
+msgstr "Δυνατότητες"
#: editor/project_export.cpp
msgid "Custom (comma-separated):"
-msgstr ""
+msgstr "ΠÏοσαÏομένο (χωÏισμός με κόμμα):"
#: editor/project_export.cpp
-#, fuzzy
msgid "Feature List:"
-msgstr "Λίστα συναÏτήσεων:"
+msgstr "Λίστα δυνατοτήτων:"
#: editor/project_export.cpp
-#, fuzzy
msgid "Export PCK/Zip"
-msgstr "Εξαγωγή"
+msgstr "Εξαγωγή PCK/ZIP"
#: editor/project_export.cpp
msgid "Export templates for this platform are missing:"
msgstr "Τα Ï€Ïότυπα εξαγωγής για αυτή την πλατφόÏτμα λείπουν:"
#: editor/project_export.cpp
+#, fuzzy
+msgid "Export templates for this platform are missing/corrupted:"
+msgstr "Τα Ï€Ïότυπα εξαγωγής για αυτή την πλατφόÏτμα λείπουν:"
+
+#: editor/project_export.cpp
msgid "Export With Debug"
msgstr "Εξαγωγή με αποσφαλμάτωση"
#: editor/project_manager.cpp
-msgid "Invalid project path, the path must exist!"
-msgstr "Μη έγκυÏη διαδÏομή έÏγου, η διαδÏομή Ï€Ïέπει να υπάÏχει!"
+#, fuzzy
+msgid "The path does not exist."
+msgstr "Το αÏχείο δεν υπάÏχει."
+
+#: editor/project_manager.cpp
+msgid "Please choose a 'project.godot' file."
+msgstr ""
#: editor/project_manager.cpp
-msgid "Invalid project path, project.godot must not exist."
-msgstr "Μη έγκυÏη διαδÏομή έÏγου, το project.godot δεν Ï€Ïέπει να υπάÏχει."
+msgid ""
+"Your project will be created in a non empty folder (you might want to create "
+"a new folder)."
+msgstr ""
#: editor/project_manager.cpp
-msgid "Invalid project path, project.godot must exist."
-msgstr "Μη έγκυÏη διαδÏομή έÏγου, το project.godot Ï€Ïέπει να υπάÏχει."
+msgid "Please choose a folder that does not contain a 'project.godot' file."
+msgstr ""
#: editor/project_manager.cpp
msgid "Imported Project"
msgstr "Εισαγμένο έÏγο"
#: editor/project_manager.cpp
+msgid " "
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "It would be a good idea to name your project."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Invalid project path (changed anything?)."
msgstr "Μη έγκυÏη διαδÏομή έÏγου (Αλλάξατε τίποτα;)."
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Couldn't get project.godot in project path."
+msgstr "Δεν ήταν δυνατή η δημιουÏγία του project.godot στη διαδÏομή έÏγου."
+
+#: editor/project_manager.cpp
+#, fuzzy
+msgid "Couldn't edit project.godot in project path."
+msgstr "Δεν ήταν δυνατή η δημιουÏγία του project.godot στη διαδÏομή έÏγου."
+
+#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
msgstr "Δεν ήταν δυνατή η δημιουÏγία του project.godot στη διαδÏομή έÏγου."
@@ -6057,38 +5632,49 @@ msgid "The following files failed extraction from package:"
msgstr "Η εξαγωγή των ακόλουθων αÏχείων από το πακέτο απέτυχε:"
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Rename Project"
+msgstr "Ανώνυμο έÏγο"
+
+#: editor/project_manager.cpp
+#, fuzzy
+msgid "Couldn't get project.godot in the project path."
+msgstr "Δεν ήταν δυνατή η δημιουÏγία του project.godot στη διαδÏομή έÏγου."
+
+#: editor/project_manager.cpp
+msgid "New Game Project"
+msgstr "Îέο έÏγο παιχνιδιοÏ"
+
+#: editor/project_manager.cpp
msgid "Import Existing Project"
msgstr "Εισαγωγή υπαÏÎºÏ„Î¿Ï Î­Ïγου"
#: editor/project_manager.cpp
-msgid "Project Path (Must Exist):"
-msgstr "ΔιαδÏομή έÏγου (ΠÏέπει να υπάÏχει):"
+msgid "Create New Project"
+msgstr "ΔημιουÏγία νέου έÏγου"
+
+#: editor/project_manager.cpp
+msgid "Install Project:"
+msgstr "Εγκατάσταση έÏγου:"
#: editor/project_manager.cpp
msgid "Project Name:"
msgstr "Όνομα έÏγου:"
#: editor/project_manager.cpp
-msgid "Create New Project"
-msgstr "ΔημιουÏγία νέου έÏγου"
+#, fuzzy
+msgid "Create folder"
+msgstr "ΔημιουÏγία φακέλου"
#: editor/project_manager.cpp
msgid "Project Path:"
msgstr "ΔιαδÏομή έÏγου:"
#: editor/project_manager.cpp
-msgid "Install Project:"
-msgstr "Εγκατάσταση έÏγου:"
-
-#: editor/project_manager.cpp
msgid "Browse"
msgstr "ΠεÏιήγηση"
#: editor/project_manager.cpp
-msgid "New Game Project"
-msgstr "Îέο έÏγο παιχνιδιοÏ"
-
-#: editor/project_manager.cpp
msgid "That's a BINGO!"
msgstr "Αυτό είναι ένα «ΕÏÏηκα»!"
@@ -6097,25 +5683,31 @@ msgid "Unnamed Project"
msgstr "Ανώνυμο έÏγο"
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Can't open project"
+msgstr "Δεν είναι δυνατή η εκτέλεση του έÏγου"
+
+#: editor/project_manager.cpp
msgid "Are you sure to open more than one project?"
msgstr "Είστε σίγουÏοι πως θέλετε να ανοίξετε πεÏισσότεÏα από ένα έÏγα;"
#: editor/project_manager.cpp
-#, fuzzy
msgid ""
"Can't run project: no main scene defined.\n"
"Please edit the project and set the main scene in \"Project Settings\" under "
"the \"Application\" category."
msgstr ""
-"Δεν έχει καθοÏιστεί κÏÏια σκηνή, θέλετε να επιλέξετε μία;\n"
-"ΜποÏείτε να την αλλάξετε αÏγότεÏα στις «Ρυθμίσεις έÏγου» κάτω από την "
-"κατηγοÏία «ΕφαÏμογή»."
+"Δεν είναι δυνατή η εκτέλεση του έÏγου: Δεν έχει καθοÏιστεί κÏÏια σκηνή.\n"
+"ΠαÏακαλώ επεξεÏγαστείτε το έÏγο και οÏίστε την κÏÏια σκηνή στις «Ρυθμίσεις "
+"έÏγου» κάτω από την κατηγοÏία «ΕφαÏμογή»."
#: editor/project_manager.cpp
msgid ""
"Can't run project: Assets need to be imported.\n"
"Please edit the project to trigger the initial import."
msgstr ""
+"Δεν είναι δυνατή η εκτέλεση του έÏγου: Τα asset Ï€Ïέπει να εισαχθοÏν.\n"
+"ΠαÏακαλώ επεξεÏγαστείτε το έÏγο για να γίνει η αÏχική εισαγωγή."
#: editor/project_manager.cpp
msgid "Are you sure to run more than one project?"
@@ -6129,6 +5721,12 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
+"Language changed.\n"
+"The UI will update next time the editor or project manager starts."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid ""
"You are about the scan %s folders for existing Godot projects. Do you "
"confirm?"
msgstr ""
@@ -6139,10 +5737,6 @@ msgid "Project List"
msgstr "Λίστα έÏγων"
#: editor/project_manager.cpp
-msgid "Run"
-msgstr "Εκτέλεση"
-
-#: editor/project_manager.cpp
msgid "Scan"
msgstr "ΣάÏωση"
@@ -6164,8 +5758,12 @@ msgstr "Έξοδος"
#: editor/project_manager.cpp
#, fuzzy
+msgid "Restart Now"
+msgstr "Επανεκκίνηση (δευτεÏόλεπτα):"
+
+#: editor/project_manager.cpp
msgid "Can't run project"
-msgstr "Δεν ήταν δυνατή η σÏνδεση."
+msgstr "Δεν είναι δυνατή η εκτέλεση του έÏγου"
#: editor/project_settings_editor.cpp
msgid "Key "
@@ -6200,17 +5798,14 @@ msgid "Add Input Action Event"
msgstr "ΠÏοσθήκη συμβάντος εισόδου"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Meta+"
msgstr "Meta+"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Shift+"
msgstr "Shift+"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Alt+"
msgstr "Alt+"
@@ -6271,7 +5866,7 @@ msgstr "Αλλαγή"
msgid "Joypad Axis Index:"
msgstr "ΑÏιθμός άξονα Joypad:"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Axis"
msgstr "Άξονας"
@@ -6291,57 +5886,64 @@ msgstr "ΔιαγÏαφή συμβάντος ενέÏγειας εισόδου"
msgid "Add Event"
msgstr "ΠÏοσθήκη συμβάντος"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Device"
msgstr "Συσκευή"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Button"
msgstr "Κουμπί"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Left Button."
msgstr "ΑÏιστεÏÏŒ κουμπί."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Right Button."
msgstr "Δεξί κουμπί."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Middle Button."
msgstr "Μεσαίο κουμπί."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Up."
msgstr "Ροδέλα πάνω."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Down."
msgstr "Ροδέλα κάτω."
#: editor/project_settings_editor.cpp
-#, fuzzy
msgid "Add Global Property"
-msgstr "ΠÏοσθέστε ιδιότητα Getter"
+msgstr "ΠÏοσθήκη καθολικής ιδιότητας"
#: editor/project_settings_editor.cpp
-msgid "Select an setting item first!"
-msgstr ""
+#, fuzzy
+msgid "Select a setting item first!"
+msgstr "Επιλέξτε ένα αντικείμενο ÏÏθμισης Ï€Ïώτα!"
#: editor/project_settings_editor.cpp
-#, fuzzy
msgid "No property '"
-msgstr "Ιδιότητα:"
+msgstr "Δεν υπάÏχει ιδιότητα '"
#: editor/project_settings_editor.cpp
-#, fuzzy
msgid "Setting '"
-msgstr "Ρυθμίσεις"
+msgstr "Ρυθμίση '"
#: editor/project_settings_editor.cpp
-#, fuzzy
msgid "Delete Item"
-msgstr "ΔιαγÏαφή εισόδου"
+msgstr "ΔιαγÏαφή αντικειμένου"
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Can't contain '/' or ':'"
+msgstr "Δεν ήταν δυνατή η σÏνδεση στον κεντÏικό υπολογιστή:"
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Already existing"
+msgstr "Η ενέÏγεια '%s' υπάÏχει ήδη!"
#: editor/project_settings_editor.cpp
msgid "Error saving settings."
@@ -6353,7 +5955,7 @@ msgstr "Οι Ïυθμίσεις αποθηκεÏτικαν εντάξει."
#: editor/project_settings_editor.cpp
msgid "Override for Feature"
-msgstr ""
+msgstr "ΠαÏάκαμψη για δυνατότητα"
#: editor/project_settings_editor.cpp
msgid "Add Translation"
@@ -6384,6 +5986,15 @@ msgid "Remove Resource Remap Option"
msgstr "ΑφαίÏεση επιλογής ανακατεÏθυνσης πόÏου"
#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Changed Locale Filter"
+msgstr "Αλλαγή χÏόνου ανάμειξης"
+
+#: editor/project_settings_editor.cpp
+msgid "Changed Locale Filter Mode"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "Project Settings (project.godot)"
msgstr "Ρυθμίσεις έÏγου (project.godot)"
@@ -6397,7 +6008,7 @@ msgstr "Ιδιότητα:"
#: editor/project_settings_editor.cpp
msgid "Override For.."
-msgstr ""
+msgstr "ΠαÏάκαμψη για..."
#: editor/project_settings_editor.cpp
msgid "Input Map"
@@ -6444,6 +6055,30 @@ msgid "Locale"
msgstr "ΠεÏιοχή"
#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Locales Filter"
+msgstr "ΠεÏιοχή"
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Show all locales"
+msgstr "Εμφάνιση οστών"
+
+#: editor/project_settings_editor.cpp
+msgid "Show only selected locales"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Filter mode:"
+msgstr "ΦιλτÏάÏισμα κόμβων"
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Locales:"
+msgstr "ΠεÏιοχή"
+
+#: editor/project_settings_editor.cpp
msgid "AutoLoad"
msgstr "Αυτόματη φόÏτωση"
@@ -6484,26 +6119,34 @@ msgid "Assign"
msgstr "Ανάθεση"
#: editor/property_editor.cpp
-#, fuzzy
msgid "Select Node"
-msgstr "Επιλέξτε έναν κόμβο"
+msgstr "Επιλογή κόμβου"
#: editor/property_editor.cpp
msgid "New Script"
msgstr "Îεα δεσμή ενεÏγειών"
#: editor/property_editor.cpp
+#, fuzzy
+msgid "Make Unique"
+msgstr "ΔημιουÏγία οστών"
+
+#: editor/property_editor.cpp
msgid "Show in File System"
msgstr "Εμφάνιση στο σÏστημα αÏχείων"
#: editor/property_editor.cpp
+#, fuzzy
+msgid "Convert To %s"
+msgstr "ΜετατÏοπή σε..."
+
+#: editor/property_editor.cpp
msgid "Error loading file: Not a resource!"
msgstr "Σφάλμα κατά την φόÏτωση αÏχείου: Δεν είναι πόÏος!"
#: editor/property_editor.cpp
-#, fuzzy
msgid "Selected node is not a Viewport!"
-msgstr "Επιλέξτε κόμβους για εισαγωγή"
+msgstr "Ο επιλεγμένος κόμβος δεν είναι Viewport!"
#: editor/property_editor.cpp
msgid "Pick a Node"
@@ -6534,6 +6177,11 @@ msgid "Select Property"
msgstr "Επιλογή ιδιότητας"
#: editor/property_selector.cpp
+#, fuzzy
+msgid "Select Virtual Method"
+msgstr "Επιλογή μεθόδου"
+
+#: editor/property_selector.cpp
msgid "Select Method"
msgstr "Επιλογή μεθόδου"
@@ -6563,26 +6211,6 @@ msgstr "ΔιατήÏηση παγκόσμιου μετασχηματισμοÏ"
msgid "Reparent"
msgstr "ΕπαναπÏοσδιοÏισμός γονέα"
-#: editor/resources_dock.cpp
-msgid "Create New Resource"
-msgstr "ΔημιουÏγία νέου πόÏου"
-
-#: editor/resources_dock.cpp
-msgid "Open Resource"
-msgstr "Άνοιγμα πόÏου"
-
-#: editor/resources_dock.cpp
-msgid "Save Resource"
-msgstr "Αποθήκευση πόÏου"
-
-#: editor/resources_dock.cpp
-msgid "Resource Tools"
-msgstr "ΕÏγαλεία πόÏων"
-
-#: editor/resources_dock.cpp
-msgid "Make Local"
-msgstr "Κάνε τοπικό"
-
#: editor/run_settings_dialog.cpp
msgid "Run Mode:"
msgstr "ΛειτουÏγία εκτέλεσης:"
@@ -6717,14 +6345,6 @@ msgid "Sub-Resources:"
msgstr "Yπο-ΠόÏοι:"
#: editor/scene_tree_dock.cpp
-msgid "Edit Groups"
-msgstr "ΕπεξεÏγασία Ομάδων"
-
-#: editor/scene_tree_dock.cpp
-msgid "Edit Connections"
-msgstr "ΕπεξεÏγασία συνδέσεων"
-
-#: editor/scene_tree_dock.cpp
msgid "Clear Inheritance"
msgstr "ΕκκαθάÏιση κληÏονομικότητας"
@@ -6785,9 +6405,8 @@ msgstr ""
"υπάÏχει πηγαίος κόμβος."
#: editor/scene_tree_dock.cpp
-#, fuzzy
msgid "Filter nodes"
-msgstr "ΦίλτÏα"
+msgstr "ΦιλτÏάÏισμα κόμβων"
#: editor/scene_tree_dock.cpp
msgid "Attach a new or existing script for the selected node."
@@ -6882,18 +6501,16 @@ msgid "Scene Tree (Nodes):"
msgstr "ΔέντÏο σκηνής (Κόμβοι):"
#: editor/scene_tree_editor.cpp
-#, fuzzy
msgid "Node Configuration Warning!"
-msgstr "ΠÏοειδοποίηση διαμόÏφωσης κόμβου:"
+msgstr "ΠÏοειδοποίηση διαμόÏφωσης κόμβου!"
#: editor/scene_tree_editor.cpp
msgid "Select a Node"
msgstr "Επιλέξτε έναν κόμβο"
#: editor/script_create_dialog.cpp
-#, fuzzy
msgid "Error loading template '%s'"
-msgstr "Σφάλμα κατά την φόÏτωση εικόνας:"
+msgstr "Σφάλμα κατά την φόÏτωση Ï€ÏοτÏπου '%s'"
#: editor/script_create_dialog.cpp
msgid "Error - Could not create script in filesystem."
@@ -6921,6 +6538,15 @@ msgid "Invalid base path"
msgstr "Μη έγκυÏη βασική διαδÏομή"
#: editor/script_create_dialog.cpp
+msgid "Directory of the same name exists"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
+#, fuzzy
+msgid "File exists, will be reused"
+msgstr "Το αÏχείο υπάÏχει. Θέλετε να το αντικαταστήσετε;"
+
+#: editor/script_create_dialog.cpp
msgid "Invalid extension"
msgstr "Μη έγκυÏη επέκταση"
@@ -6961,6 +6587,10 @@ msgid "Load existing script file"
msgstr "ΦόÏτωση υπαÏÎºÏ„Î¿Ï Î±Ïχείου δεσμής ενεÏγειών"
#: editor/script_create_dialog.cpp
+msgid "Language"
+msgstr "Γλώσσα"
+
+#: editor/script_create_dialog.cpp
msgid "Inherits"
msgstr "ΚληÏονομεί"
@@ -7001,6 +6631,10 @@ msgid "Function:"
msgstr "ΣυνάÏτηση:"
#: editor/script_editor_debugger.cpp
+msgid "Pick one or more items from the list to display the graph."
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
msgid "Errors"
msgstr "Σφάλματα"
@@ -7081,6 +6715,10 @@ msgid "Type"
msgstr "ΤÏπος"
#: editor/script_editor_debugger.cpp
+msgid "Format"
+msgstr "ΜοÏφή"
+
+#: editor/script_editor_debugger.cpp
msgid "Usage"
msgstr "ΧÏήση"
@@ -7114,7 +6752,7 @@ msgstr "Αλλαγή διαμέτÏου φωτός"
#: editor/spatial_editor_gizmos.cpp
msgid "Change AudioStreamPlayer3D Emission Angle"
-msgstr ""
+msgstr "Αλλαγή γωνίας εκπομπής του AudioStreamPlayer3D"
#: editor/spatial_editor_gizmos.cpp
msgid "Change Camera FOV"
@@ -7156,13 +6794,31 @@ msgstr "Αλλαγή AABB σωματιδίων"
msgid "Change Probe Extents"
msgstr "Αλλαγή διαστάσεων αισθητήÏα"
+#: modules/gdnative/gd_native_library_editor.cpp
+#, fuzzy
+msgid "Library"
+msgstr "Βιβλιοθήκη πλεγμάτων..."
+
+#: modules/gdnative/gd_native_library_editor.cpp
+#, fuzzy
+msgid "Status"
+msgstr "Κατάσταση:"
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Libraries: "
+msgstr ""
+
+#: modules/gdnative/register_types.cpp
+msgid "GDNative"
+msgstr ""
+
#: modules/gdscript/gd_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Invalid type argument to convert(), use TYPE_* constants."
msgstr ""
"Μη έγκυÏη παÏάμετÏος στην convert(). ΧÏησιμοποιήστε τις σταθεÏές TYPE_*."
-#: modules/gdscript/gd_functions.cpp
+#: modules/gdscript/gd_functions.cpp modules/mono/glue/glue_header.h
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Not enough bytes for decoding bytes, or invalid format."
msgstr "Δεν υπάÏχουν αÏκετά byte για την αποκωδικοποίηση, ή άκυÏη μοÏφή."
@@ -7203,133 +6859,112 @@ msgstr "ΆκυÏη μοÏφή Î»ÎµÎ¾Î¹ÎºÎ¿Ï ÏƒÏ„Î¹Î³Î¼Î¹Î¿Ï„Ïπων (άκυÏÎ
#: modules/gdscript/gd_functions.cpp
msgid "Object can't provide a length."
-msgstr ""
+msgstr "Το αντικείμενο δεν έχει μήκος."
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "GridMap Delete Selection"
-msgstr "ΔιαγÏαφή επιλεγμένου"
+msgstr "GridMap ΔιαγÏαφή επιλογής"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "GridMap Duplicate Selection"
-msgstr "Διπλασιασμός επιλογής"
+msgstr "GridMap Διπλασιασμός επιλογής"
#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "GridMap Paint"
-msgstr ""
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Snap View"
-msgstr "Πάνω όψη"
+msgstr "ΚοÏμπωμα όψης"
#: modules/gridmap/grid_map_editor_plugin.cpp
+#, fuzzy
msgid "Prev Level (%sDown Wheel)"
-msgstr ""
+msgstr "ΠÏοηγοÏμενο επίπεδο ("
#: modules/gridmap/grid_map_editor_plugin.cpp
+#, fuzzy
msgid "Next Level (%sUp Wheel)"
-msgstr ""
+msgstr "Επόμενο επίπεδο ("
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Clip Disabled"
-msgstr "ΑπενεÏγοποιημένο"
+msgstr "Η πεÏικοπή είναι απενεÏγοποιημένη"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Clip Above"
-msgstr ""
+msgstr "ΠεÏικοπή πάνω"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Clip Below"
-msgstr ""
+msgstr "ΠεÏικοπή κάτω"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Edit X Axis"
-msgstr ""
+msgstr "ΕπεξεÏγασία άξονα Χ"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Edit Y Axis"
-msgstr ""
+msgstr "ΕπεξεÏγασία άξονα Î¥"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Edit Z Axis"
-msgstr ""
+msgstr "ΕπεξεÏγασία άξονα Ζ"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Cursor Rotate X"
-msgstr "Ctrl: ΠεÏιστÏοφή"
+msgstr "ΔÏομέας πεÏιστÏοφή Χ"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Cursor Rotate Y"
-msgstr "Ctrl: ΠεÏιστÏοφή"
+msgstr "ΔÏομέας πεÏιστÏοφή Î¥"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Cursor Rotate Z"
-msgstr "Ctrl: ΠεÏιστÏοφή"
+msgstr "ΔÏομέας πεÏιστÏοφή Ζ"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Cursor Back Rotate X"
-msgstr ""
+msgstr "Πίσω δÏομέας πεÏιστÏοφή Χ"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Cursor Back Rotate Y"
-msgstr ""
+msgstr "Πίσω δÏομέας πεÏιστÏοφή Î¥"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Cursor Back Rotate Z"
-msgstr ""
+msgstr "Πίσω δÏομέας πεÏιστÏοφή Ζ"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Cursor Clear Rotation"
-msgstr ""
+msgstr "ΕκκαθάÏιση πεÏιστÏοφής δÏομέα"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Create Area"
-msgstr "ΔημιουÏγία νέου"
+msgstr "ΔημιουÏγία πεÏιοχής"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Create Exterior Connector"
-msgstr "ΔημιουÏγία νέου έÏγου"
+msgstr "ΔημιουÏγία εξωτεÏικής σÏνδεσης"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Erase Area"
-msgstr "ΔιαγÏαφή TileMap"
+msgstr "ΔιαγÏαφή πεÏσιοχής"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Selection -> Duplicate"
-msgstr "Μόνο στην επιλογή"
+msgstr "Επιλογή -> Διπλασιασμός"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Selection -> Clear"
-msgstr "Μόνο στην επιλογή"
+msgstr "Επιλογή -> ΕκκαθάÏιση"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "GridMap Settings"
-msgstr "Ρυθμίσεις κουμπώματος"
+msgstr "Ρυθμίσεις GridMap"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Pick Distance:"
-msgstr "Στιγμιότυπο:"
+msgstr "Επιλογή απόστασης:"
-#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
-msgid "Tiles"
-msgstr " ΑÏχεία"
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "Areas"
+#: modules/mono/editor/mono_bottom_panel.cpp
+msgid "Builds"
msgstr ""
#: modules/visual_script/visual_script.cpp
@@ -7371,29 +7006,24 @@ msgid "Stack overflow with stack depth: "
msgstr "ΥπεÏχείλιση στοίβας με βάθος στοίβας: "
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Change Signal Arguments"
-msgstr "ΕπεξεÏγασία παÏαμέτÏων σήματος:"
+msgstr "Αλλαγή παÏαμέτÏων σήματος"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Change Argument Type"
-msgstr "Αλλαγή Ï„Ïπου τιμής πίνακα"
+msgstr "Αλλαγή Ï„Ïπου παÏαμέτÏου"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Change Argument name"
-msgstr "Αλλαγή ονόματος εισόδου"
+msgstr "Αλλαγή ονόματος παÏαμέτÏου"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Set Variable Default Value"
-msgstr "Αλλαγή Ï€Ïοεπιλλεγμένης τιμής"
+msgstr "ΟÏισμός Ï€Ïοεπιλλεγμένης τιμής μεταβλητής"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Set Variable Type"
-msgstr "ΕπεξεÏγασία μεταβλητής:"
+msgstr "ΟÏισμός Ï„Ïπου μεταβλητής"
#: modules/visual_script/visual_script_editor.cpp
msgid "Functions:"
@@ -7444,14 +7074,12 @@ msgid "Add Node"
msgstr "ΠÏοσθήκη κόμβου"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Remove VisualScript Nodes"
-msgstr "ΑφαίÏεση άκυÏων κλειδιών"
+msgstr "ΑφαίÏεση κόμβων VisualScript"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Duplicate VisualScript Nodes"
-msgstr "Διπλασιασμός κόμβων γÏαφήματος"
+msgstr "Διπλασιασμός κόμβων VisualScript"
#: modules/visual_script/visual_script_editor.cpp
msgid "Hold Meta to drop a Getter. Hold Shift to drop a generic signature."
@@ -7502,24 +7130,20 @@ msgid "Add Setter Property"
msgstr "ΠÏοσθέστε ιδιότητα Setter"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Change Base Type"
-msgstr "Αλλαγή Ï„Ïπου"
+msgstr "Αλλαγή Î²Î±ÏƒÎ¹ÎºÎ¿Ï Ï„Ïπου"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Move Node(s)"
-msgstr "ΑφαίÏεση κόμβων"
+msgstr "Μετακίνηση κόμβων"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Remove VisualScript Node"
-msgstr "ΑφαίÏεση κόμβου γÏαφήματος"
+msgstr "ΑφαίÏεση κόμβου VisualScript"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Connect Nodes"
-msgstr "ΣÏνδεση στον κόμβο:"
+msgstr "ΣÏνδεση κόμβων"
#: modules/visual_script/visual_script_editor.cpp
msgid "Condition"
@@ -7546,46 +7170,48 @@ msgid "Return"
msgstr "ΕπιστÏοφή"
#: modules/visual_script/visual_script_editor.cpp
+msgid "Call"
+msgstr "Κλήση"
+
+#: modules/visual_script/visual_script_editor.cpp
msgid "Get"
msgstr "ΠάÏε"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
+msgid "Script already has function '%s'"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
msgid "Change Input Value"
-msgstr "Αλλαγή ονόματος εισόδου"
+msgstr "Αλλαγή τιμής εισόδου"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Can't copy the function node."
-msgstr "ΑδÏνατη η λειτουÏγία στο '..'"
+msgstr "ΑδÏνατη η αντιγÏαφή του κόμβου συνάÏτησης."
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Clipboard is empty!"
-msgstr "Το Ï€ÏόχειÏο πόÏων είναι άδειο!"
+msgstr "Το Ï€ÏόχειÏο είναι άδειο!"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Paste VisualScript Nodes"
-msgstr "Επικόλληση κόμβων"
+msgstr "Επικόλληση κόμβων VisualScript"
#: modules/visual_script/visual_script_editor.cpp
msgid "Remove Function"
msgstr "ΑφαίÏεση συνάÏτησης"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Edit Variable"
-msgstr "ΕπεξεÏγασία μεταβλητής:"
+msgstr "ΕπεξεÏγασία μεταβλητής"
#: modules/visual_script/visual_script_editor.cpp
msgid "Remove Variable"
msgstr "ΑφαίÏεση μεταβλητής"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Edit Signal"
-msgstr "ΕπεξεÏγασία σήματος:"
+msgstr "ΕπεξεÏγασία σήματος"
#: modules/visual_script/visual_script_editor.cpp
msgid "Remove Signal"
@@ -7827,6 +7453,9 @@ msgid ""
"by the physics engine when running.\n"
"Change the size in children collision shapes instead."
msgstr ""
+"Αλλαγές στο μέγεθος του RigidBody2D (στις λειτουÏγίες character ή rigid) θα "
+"αντικατασταθοÏνε από την μηχανή φυσικής κατά την εκτέλεση.\n"
+"Αλλάξτε μέγεθος στα σχήματα σÏγκÏουσης των παιδιών."
#: scene/2d/remote_transform_2d.cpp
msgid "Path property must point to a valid Node2D node to work."
@@ -7860,31 +7489,35 @@ msgstr ""
#: scene/3d/arvr_nodes.cpp
msgid "ARVRCamera must have an ARVROrigin node as its parent"
-msgstr ""
+msgstr "Η ARVRCamera Ï€Ïέπει να έχει έναν κόμβο ARVROrigin ως γονέα"
#: scene/3d/arvr_nodes.cpp
msgid "ARVRController must have an ARVROrigin node as its parent"
-msgstr ""
+msgstr "Ο ARVRController Ï€Ïέπει να έχει έναν κόμβο ARVROrigin ως γονέα"
#: scene/3d/arvr_nodes.cpp
msgid ""
"The controller id must not be 0 or this controller will not be bound to an "
"actual controller"
msgstr ""
+"Ο δείκτης χειÏιστή δεν Ï€Ïέπει να είναι 0 για να είναι συνδεδεμένος αυτός ο "
+"χειÏιστής με έναν υπαÏκτό χειÏιστή"
#: scene/3d/arvr_nodes.cpp
msgid "ARVRAnchor must have an ARVROrigin node as its parent"
-msgstr ""
+msgstr "Ο ARVRAnchor Ï€Ïέπει να έχει έναν κόμβο ARVROrigin ως γονέα"
#: scene/3d/arvr_nodes.cpp
msgid ""
"The anchor id must not be 0 or this anchor will not be bound to an actual "
"anchor"
msgstr ""
+"Ο δείκτης άγκυÏας δεν Ï€Ïέπει να είναι 0 για να είναι συνδεδεμένη αυτή η "
+"άγκυÏα με μία υπαÏκτή άγκυÏα"
#: scene/3d/arvr_nodes.cpp
msgid "ARVROrigin requires an ARVRCamera child node"
-msgstr ""
+msgstr "Το ARVROrigin απαιτεί έναν κόμβο ARVRCamera ως παιδί"
#: scene/3d/collision_polygon.cpp
msgid ""
@@ -7946,6 +7579,9 @@ msgid ""
"the physics engine when running.\n"
"Change the size in children collision shapes instead."
msgstr ""
+"Αλλαγές στο μέγεθος του RigidBody (στις λειτουÏγίες character ή rigid) θα "
+"αντικατασταθοÏνε από την μηχανή φυσικής κατά την εκτέλεση.\n"
+"Αλλάξτε μέγεθος στα σχήματα σÏγκÏουσης των παιδιών."
#: scene/3d/remote_transform.cpp
msgid "Path property must point to a valid Spatial node to work."
@@ -7968,16 +7604,25 @@ msgstr ""
"Ένας πόÏος SpriteFrames Ï€Ïέπει να δημιουÏγηθεί ή οÏισθεί στην ιδιότητα "
"'Frames' για να δείξει frames το AnimatedSprite3D."
+#: scene/3d/vehicle_body.cpp
+msgid ""
+"VehicleWheel serves to provide a wheel system to a VehicleBody. Please use "
+"it as a child of a VehicleBody."
+msgstr ""
+
#: scene/gui/color_picker.cpp
-#, fuzzy
msgid "Raw Mode"
-msgstr "ΛειτουÏγία Μετακίνησης κάμεÏας"
+msgstr "Ωμή λειτουÏγία"
#: scene/gui/color_picker.cpp
msgid "Add current color as a preset"
msgstr "ΠÏοσθήκη του Ï„Ïέχοντος χÏώματος ως Ï€ÏοκαθοÏισμένο"
#: scene/gui/dialogs.cpp
+msgid "Cancel"
+msgstr "ΑκÏÏωση"
+
+#: scene/gui/dialogs.cpp
msgid "Alert!"
msgstr "Ειδοποίηση!"
@@ -7985,10 +7630,6 @@ msgstr "Ειδοποίηση!"
msgid "Please Confirm..."
msgstr "ΠαÏακαλώ επιβεβαιώστε..."
-#: scene/gui/input_action.cpp
-msgid "Ctrl+"
-msgstr "Ctrl+"
-
#: scene/gui/popup.cpp
msgid ""
"Popups will hide by default unless you call popup() or any of the popup*() "
@@ -8030,6 +7671,647 @@ msgstr ""
"μέγεθος. Αλλιώς, κάντε το ένα RenderTarget και οÏίστε το internal texture σε "
"έναν κόμβο για απεικόνιση."
+#: scene/resources/dynamic_font.cpp
+msgid "Error initializing FreeType."
+msgstr "Σφάλμα κατά την αÏχικοποίηση του FreeType."
+
+#: scene/resources/dynamic_font.cpp
+msgid "Unknown font format."
+msgstr "Άγνωστη μοÏφή γÏαμματοσειÏάς."
+
+#: scene/resources/dynamic_font.cpp
+msgid "Error loading font."
+msgstr "Σφάλμα κατά την φόÏτωση της γÏαμματοσειÏάς."
+
+#: scene/resources/dynamic_font.cpp
+msgid "Invalid font size."
+msgstr "Μη έγκυÏο μέγεθος γÏαμματοσειÏάς."
+
+#~ msgid "Filter:"
+#~ msgstr "ΦίλτÏο:"
+
+#~ msgid "' parsing of config failed."
+#~ msgstr "' απέτυχε η ανάλυση του αÏγείου παÏαμέτÏων."
+
+#~ msgid "Theme"
+#~ msgstr "Θέμα"
+
+#~ msgid "Method List For '%s':"
+#~ msgstr "Λίστα συναÏτήσεων για '%s':"
+
+#~ msgid "Arguments:"
+#~ msgstr "ΠαÏάμετÏοι:"
+
+#~ msgid "Return:"
+#~ msgstr "ΕπιστÏέφει:"
+
+#~ msgid "Added:"
+#~ msgstr "ΠÏοστέθηκαν:"
+
+#~ msgid "Removed:"
+#~ msgstr "ΑφαιÏέθηκαν:"
+
+#~ msgid "Error saving atlas:"
+#~ msgstr "Σφάλμα κατά την αποθήκευση άτλαντα:"
+
+#~ msgid "Could not save atlas subtexture:"
+#~ msgstr "ΑδÏνατη η αποθήκευση υπό-εικόνας άτλαντα:"
+
+#~ msgid "Exporting for %s"
+#~ msgstr "Εξαγωγή για %s"
+
+#~ msgid "Setting Up.."
+#~ msgstr "ΑÏχικοποίηση.."
+
+#~ msgid "Error loading scene."
+#~ msgstr "Σφάλμα κατά τη φόÏτωση σκηνής."
+
+#~ msgid "Re-Import"
+#~ msgstr "Επανεισαγωγή"
+
+#~ msgid "Please wait for scan to complete."
+#~ msgstr "ΠαÏακαλώ πεÏιμένετε να ολοκληÏωθεί η σάÏωση."
+
+#~ msgid "Current scene must be saved to re-import."
+#~ msgstr "Η Ï„Ïέχουσα σκηνή Ï€Ïέπει να αποθηκευτεί για να επαν-εισάγετε."
+
+#~ msgid "Save & Re-Import"
+#~ msgstr "Αποθήκευση & Επανεισαγωγή"
+
+#~ msgid "Re-Importing"
+#~ msgstr "Επανεισαγωγή"
+
+#~ msgid "Re-Import Changed Resources"
+#~ msgstr "Επανεισαγωγή Ï„Ïοποπιημένων πόÏων"
+
+#~ msgid "Loading Export Templates"
+#~ msgstr "ΦόÏτωση Ï€ÏοτÏπων εξαγωγής"
+
+#~ msgid ""
+#~ "\n"
+#~ "Status: Needs Re-Import"
+#~ msgstr ""
+#~ "\n"
+#~ "Κατάσταση: ΧÏειάζεται επανεισαγωγή"
+
+#~ msgid "Same source and destination files, doing nothing."
+#~ msgstr "Ίδια αÏχεία πηγής και Ï€ÏοοÏισμοÏ, παÏάλειψη ενέÏγειας."
+
+#~ msgid "Target file exists, can't overwrite. Delete first."
+#~ msgstr ""
+#~ "Το αÏχείο Ï€ÏοοÏÎ¹ÏƒÎ¼Î¿Ï Ï…Ï€Î¬Ïχει, όμως είναι αδÏνατη η αντικατάσταση. "
+#~ "ΔιαγÏάψτε το Ï€Ïώτα."
+
+#~ msgid "Same source and destination paths, doing nothing."
+#~ msgstr "Ίδιες διαδÏομές πηγής και Ï€ÏοοÏισμοÏ, παÏάλειψη ενέÏγειας."
+
+#~ msgid "Can't move directories to within themselves."
+#~ msgstr "ΑδÏνατη η μετακίνηση καταλόγων μέσα στους εαυτοÏÏ‚ τους."
+
+#~ msgid "Can't rename deps for:\n"
+#~ msgstr "Δεν είναι δυνατή η μετονομασία εξαÏτήσεων για:\n"
+
+#~ msgid "Error moving file:\n"
+#~ msgstr "Σφάλμα κατά την μετακίνηση αÏχείου:\n"
+
+#~ msgid "Pick New Name and Location For:"
+#~ msgstr "Επιλέξτε νέο όνομα και θέση για:"
+
+#~ msgid "No files selected!"
+#~ msgstr "Δεν επιλέχθηκαν αÏχεία!"
+
+#~ msgid "Info"
+#~ msgstr "ΠληÏοφοÏίες"
+
+#~ msgid "Re-Import.."
+#~ msgstr "Εκ νέου εισαγωγή..."
+
+#~ msgid "No bit masks to import!"
+#~ msgstr "Δεν υπάÏχουν μάσκες bit για εισαγωγή!"
+
+#~ msgid "Target path is empty."
+#~ msgstr "Η διαδÏομή Ï€ÏοοÏÎ¹ÏƒÎ¼Î¿Ï ÎµÎ¯Î½Î±Î¹ άδεια."
+
+#~ msgid "Target path must be a complete resource path."
+#~ msgstr "Η διαδÏομή Ï€ÏοοÏÎ¹ÏƒÎ¼Î¿Ï Ï€Ïέπει να είναι μία πλήÏης διαδÏομή σε πόÏο."
+
+#~ msgid "Target path must exist."
+#~ msgstr "Η διαδÏομή Ï€ÏοοÏÎ¹ÏƒÎ¼Î¿Ï Ï€Ïέπει να υπάÏχει."
+
+#~ msgid "Save path is empty!"
+#~ msgstr "Η διαδÏομή αποθήκευσης είναι άδεια!"
+
+#~ msgid "Import BitMasks"
+#~ msgstr "Εισαγωγή μάσκας bit"
+
+#~ msgid "Source Texture(s):"
+#~ msgstr "Πηγαίες υφές:"
+
+#~ msgid "Target Path:"
+#~ msgstr "ΔιαδÏομή Ï€ÏοοÏισμοÏ:"
+
+#~ msgid "Accept"
+#~ msgstr "Αποδοχή"
+
+#~ msgid "Bit Mask"
+#~ msgstr "Μάσκα bit"
+
+#~ msgid "No source font file!"
+#~ msgstr "Δεν δόθηκε πηγαίο αÏχείο γÏαμματοσειÏάς!"
+
+#~ msgid "No target font resource!"
+#~ msgstr "Δε δόθηκε πόÏος γÏαμματοσειÏάς Ï€ÏοοÏισμοÏ!"
+
+#~ msgid ""
+#~ "Invalid file extension.\n"
+#~ "Please use .font."
+#~ msgstr ""
+#~ "ΆκυÏη επέκταση αÏχείου.\n"
+#~ "ΠαÏακαλώ χÏησιμοποιήστε .font."
+
+#~ msgid "Couldn't save font."
+#~ msgstr "Δεν ήταν δυνατή η αποθήκευση της γÏαμματοσειÏάς."
+
+#~ msgid "Source Font:"
+#~ msgstr "Πηγαία γÏαμματοσειÏά:"
+
+#~ msgid "Source Font Size:"
+#~ msgstr "Μέγεθος πηγαίας γÏαμματοσειÏάς:"
+
+#~ msgid "Dest Resource:"
+#~ msgstr "ΠόÏος Ï€ÏοοÏισμοÏ:"
+
+#~ msgid "The quick brown fox jumps over the lazy dog."
+#~ msgstr "Γαζέες καὶ μυÏτιὲς δὲν θὰ βÏῶ πιὰ στὸ χÏυσαφὶ ξέφωτο."
+
+#~ msgid "Test:"
+#~ msgstr "Δοκιμή:"
+
+#~ msgid "Options:"
+#~ msgstr "Επιλογές:"
+
+#~ msgid "Font Import"
+#~ msgstr "Εισαγωγή γÏαμματοσειÏάς"
+
+#~ msgid ""
+#~ "This file is already a Godot font file, please supply a BMFont type file "
+#~ "instead."
+#~ msgstr ""
+#~ "Αυτό το αÏχείο είναι ήδη ένα αÏχείο γÏαμματοσειÏάς της Godot, παÏακαλώ "
+#~ "υποβάλετε ένα αÏχείο Ï„Ïπου BMFont."
+
+#~ msgid "Failed opening as BMFont file."
+#~ msgstr "Απέτυχε το άνοιγμα ως αÏχείο BMFont."
+
+#~ msgid "Invalid font custom source."
+#~ msgstr "ΆκυÏη Ï€ÏοσαÏμοσμένη πηγή γÏαμματοσειÏάς."
+
+#~ msgid "No meshes to import!"
+#~ msgstr "Δεν υπάÏχουν πλέγματα για εισαγωγή!"
+
+#~ msgid "Single Mesh Import"
+#~ msgstr "Εισαγωγή ενός πλέγματος"
+
+#~ msgid "Source Mesh(es):"
+#~ msgstr "Πηγαία πλέγματα:"
+
+#~ msgid "Surface %d"
+#~ msgstr "Επιφάνεια %d"
+
+#~ msgid "No samples to import!"
+#~ msgstr "Δεν υπάÏχουν δείγματα για εισαγωγή!"
+
+#~ msgid "Import Audio Samples"
+#~ msgstr "Εισαγωγή δειγμάτων ήχου"
+
+#~ msgid "Source Sample(s):"
+#~ msgstr "Πηγαία δείγματα:"
+
+#~ msgid "Audio Sample"
+#~ msgstr "Δείγμα ήχου"
+
+#~ msgid "New Clip"
+#~ msgstr "Îέο απόσπασμα"
+
+#~ msgid "Flags"
+#~ msgstr "Σημαίες"
+
+#~ msgid "Bake FPS:"
+#~ msgstr "Ψήστε FPS:"
+
+#~ msgid "Optimizer"
+#~ msgstr "ΕÏγαλείο βελτιστοποίησης"
+
+#~ msgid "Max Linear Error"
+#~ msgstr "Μέγιστο γÏαμμικό σφάλμα"
+
+#~ msgid "Max Angular Error"
+#~ msgstr "Μέγιστο γωνιακό σφάλμα"
+
+#~ msgid "Max Angle"
+#~ msgstr "Ανώτατη Γωνία"
+
+#~ msgid "Clips"
+#~ msgstr "Αποσπάσματα"
+
+#~ msgid "Start(s)"
+#~ msgstr "ΑÏχή"
+
+#~ msgid "End(s)"
+#~ msgstr "Τέλος"
+
+#~ msgid "Filters"
+#~ msgstr "ΦίλτÏα"
+
+#~ msgid "Source path is empty."
+#~ msgstr "Η διαδÏομή Ï€Ïοέλευσης είναι άδεια."
+
+#~ msgid "Couldn't load post-import script."
+#~ msgstr "Δεν ήταν δυνατή η φόÏτωση της δεσμής ενεÏγειών μετ-εισαγωγής."
+
+#~ msgid "Invalid/broken script for post-import."
+#~ msgstr ""
+#~ "ΆκυÏη / χαλασμένη δεσμή ενεÏγειών για την διαδικασία της μετ-εισαγωγής."
+
+#~ msgid "Error importing scene."
+#~ msgstr "Σφάλμα κατά την εισαγωγή της σκηνής."
+
+#~ msgid "Import 3D Scene"
+#~ msgstr "Εισαγωγή 3D σκηνής"
+
+#~ msgid "Source Scene:"
+#~ msgstr "Σκηνή Ï€Ïοέλευσης:"
+
+#~ msgid "Same as Target Scene"
+#~ msgstr "Το ίδιο με την στοχευμένη σκηνή"
+
+#~ msgid "Shared"
+#~ msgstr "ΚοινόχÏηστο"
+
+#~ msgid "Target Texture Folder:"
+#~ msgstr "Επιλεγμένος φάκλος υφών:"
+
+#~ msgid "Post-Process Script:"
+#~ msgstr "Δεσμή ενεÏγειών μετ-επεξεÏγασίας:"
+
+#~ msgid "Custom Root Node Type:"
+#~ msgstr "ΠÏοσαÏμοσμένος Ï„Ïπος ÏÎ¹Î¶Î¹ÎºÎ¿Ï ÎºÏŒÎ¼Î²Î¿Ï…:"
+
+#~ msgid "Auto"
+#~ msgstr "Αυτόματο"
+
+#~ msgid "Root Node Name:"
+#~ msgstr "Όνομα ÏÎ¹Î¶Î¹ÎºÎ¿Ï ÎºÏŒÎ¼Î²Î¿Ï…:"
+
+#~ msgid "The Following Files are Missing:"
+#~ msgstr "Τα ακόλουθα αÏχεία λείπουν:"
+
+#~ msgid "Import Anyway"
+#~ msgstr "Εισαγωγή οÏτως ή άλλως"
+
+#~ msgid "Import & Open"
+#~ msgstr "Εισαγωγή & Άνοιγμα"
+
+#~ msgid "Edited scene has not been saved, open imported scene anyway?"
+#~ msgstr ""
+#~ "Η Ï„Ïέχουσα σκηνή δεν έχει αποθηκευτεί, άνοιγμα της εισαγμένης σκηνής "
+#~ "οÏτως ή άλλως;"
+
+#~ msgid "Import Image:"
+#~ msgstr "Εισαγωγή εικόνας:"
+
+#~ msgid "Couldn't localize path: %s (already local)"
+#~ msgstr ""
+#~ "Δεν είναι δυνατή η μετατÏοπή της διαδÏομής σε τοπική: %s (είναι ήδη "
+#~ "τοπικό)"
+
+#~ msgid "3D Scene Animation"
+#~ msgstr "Κίνηση Ï„Ïισδιάστατης σκηνής"
+
+#~ msgid "Uncompressed"
+#~ msgstr "Ασυμπίεστο"
+
+#~ msgid "Compress Lossless (PNG)"
+#~ msgstr "Συμπίεση χωÏίς απώλειες (PNG)"
+
+#~ msgid "Compress Lossy (WebP)"
+#~ msgstr "Συμπίεση με απώλειες (WebP)"
+
+#~ msgid "Compress (VRAM)"
+#~ msgstr "Συμπίεση (VRAM)"
+
+#~ msgid "Texture Format"
+#~ msgstr "ΜοÏφή υφής"
+
+#~ msgid "Texture Compression Quality (WebP):"
+#~ msgstr "Ποιότητα συμπίεσης υφής (WebP):"
+
+#~ msgid "Texture Options"
+#~ msgstr "Επιλογές υφής"
+
+#~ msgid "Please specify some files!"
+#~ msgstr "ΠαÏακαλώ καθοÏίστε κάποια αÏχεία!"
+
+#~ msgid "At least one file needed for Atlas."
+#~ msgstr "Τουλάχιστον ένα αÏχείο απαιτείται για τον άτλαντα."
+
+#~ msgid "Error importing:"
+#~ msgstr "Σφάλμα κατά την εισαγωγή:"
+
+#~ msgid "Only one file is required for large texture."
+#~ msgstr "Μόνο ένα αÏχείο είναι απαÏαίτητη για μεγάλη υφή."
+
+#~ msgid "Max Texture Size:"
+#~ msgstr "Μέγιστο μέγεθος υφής:"
+
+#~ msgid "Import Textures for Atlas (2D)"
+#~ msgstr "Εισαγωγή υφών για τον άτλαντα (2D)"
+
+#~ msgid "Cell Size:"
+#~ msgstr "Μέγεθος κελιοÏ:"
+
+#~ msgid "Large Texture"
+#~ msgstr "Μεγάλη υφή"
+
+#~ msgid "Import Large Textures (2D)"
+#~ msgstr "Εισαγωγής Μεγάλων Υφών (2D)"
+
+#~ msgid "Source Texture"
+#~ msgstr "Υφή Ï€Ïοέλευσης"
+
+#~ msgid "Base Atlas Texture"
+#~ msgstr "Βασική υφή άτλαντα"
+
+#~ msgid "Source Texture(s)"
+#~ msgstr "Υφές Ï€Ïοέλευσης"
+
+#~ msgid "Import Textures for 2D"
+#~ msgstr "Εισαγωγή υφών για 2 διαστάσεις"
+
+#~ msgid "Import Textures for 3D"
+#~ msgstr "Εισαγωγή υφών για 3 διαστάσεις"
+
+#~ msgid "Import Textures"
+#~ msgstr "Εισαγωγή υφών"
+
+#~ msgid "2D Texture"
+#~ msgstr "Υφή 2 διαστάσεων"
+
+#~ msgid "3D Texture"
+#~ msgstr "Υφή 3 διαστάσεων"
+
+#~ msgid "Atlas Texture"
+#~ msgstr "Υφή άτλαντα"
+
+#~ msgid ""
+#~ "NOTICE: Importing 2D textures is not mandatory. Just copy png/jpg files "
+#~ "to the project."
+#~ msgstr ""
+#~ "ΣΗΜΕΙΩΣΗ: Η εισαγωγή δισδιάστατων υφών δεν είναι υποχÏεωτική. Απλά "
+#~ "αντιγÏάψτε τα αÏχεία png/jpg στο έÏγο."
+
+#~ msgid "Crop empty space."
+#~ msgstr "ΠεÏικοπή άδειου χώÏου."
+
+#~ msgid "Texture"
+#~ msgstr "Υφή"
+
+#~ msgid "Import Large Texture"
+#~ msgstr "Εισαγωγή μεγάλης υφής"
+
+#~ msgid "Load Source Image"
+#~ msgstr "ΦόÏτωση εικόνας Ï€Ïοέλευσης"
+
+#~ msgid "Slicing"
+#~ msgstr "Κατάτμηση"
+
+#~ msgid "Saving"
+#~ msgstr "Αποθήκευση"
+
+#~ msgid "Couldn't save large texture:"
+#~ msgstr "Δεν ήταν δυνατή η αποθήκευση μεγάλης υφής:"
+
+#~ msgid "Build Atlas For:"
+#~ msgstr "Κατασκευή άτλαντα για:"
+
+#~ msgid "Loading Image:"
+#~ msgstr "ΦόÏτωση εικόνας:"
+
+#~ msgid "Couldn't load image:"
+#~ msgstr "Δεν ήταν δυνατή η φόÏτωση της εικόνας:"
+
+#~ msgid "Converting Images"
+#~ msgstr "ΜετατÏοπή Εικόνων"
+
+#~ msgid "Cropping Images"
+#~ msgstr "ΠεÏικοπή Εικόνων"
+
+#~ msgid "Blitting Images"
+#~ msgstr "Συνδυασμός εικόνων"
+
+#~ msgid "Couldn't save atlas image:"
+#~ msgstr "Δεν ήταν δυνατή η αποθήκευση εικόνας άτλαντα:"
+
+#~ msgid "Couldn't save converted texture:"
+#~ msgstr "Δεν ήταν δυνατή η αποθήκευση υφής που έχει μετατÏαπεί:"
+
+#~ msgid "Invalid source!"
+#~ msgstr "Μη έγκυÏη πηγή!"
+
+#~ msgid "Invalid translation source!"
+#~ msgstr "Μη έγκυÏη πηγή μετάφÏασης!"
+
+#~ msgid "Column"
+#~ msgstr "Στήλη"
+
+#~ msgid "No items to import!"
+#~ msgstr "Δεν υπάÏχουν στοιχεία για εισαγωγή!"
+
+#~ msgid "No target path!"
+#~ msgstr "Καμία διαδÏομή Ï€ÏοοÏισμοÏ!"
+
+#~ msgid "Import Translations"
+#~ msgstr "Εισαγωγή μεταφÏάσεων"
+
+#~ msgid "Couldn't import!"
+#~ msgstr "Δεν ήταν δυνατή η εισαγωγή!"
+
+#~ msgid "Import Translation"
+#~ msgstr "Εισαγωγή μετάφÏασης"
+
+#~ msgid "Source CSV:"
+#~ msgstr "CSV Ï€Ïοέλευσης:"
+
+#~ msgid "Ignore First Row"
+#~ msgstr "Αγνόησε την Ï€Ïώτη γÏαμμή"
+
+#~ msgid "Compress"
+#~ msgstr "Συμπίεση"
+
+#~ msgid "Add to Project (project.godot)"
+#~ msgstr "ΠÏόσθεσε στο έÏγο (project.godot)"
+
+#~ msgid "Import Languages:"
+#~ msgstr "Εισαγωγή γλωσσών:"
+
+#~ msgid "Translation"
+#~ msgstr "ΜετάφÏαση"
+
+#~ msgid "Parsing %d Triangles:"
+#~ msgstr "Ανάλυση %d ΤÏιγώνων:"
+
+#~ msgid "Triangle #"
+#~ msgstr "ΤÏίγωνο #"
+
+#~ msgid "Light Baker Setup:"
+#~ msgstr "ΡÏθμιση Ï€ÏοεπεγεÏγαστή φωτός:"
+
+#~ msgid "Fixing Lights"
+#~ msgstr "ΔιόÏθωση φώτων"
+
+#~ msgid "Making BVH"
+#~ msgstr "ΔημιουÏγία BVH"
+
+#~ msgid "Transfer to Lightmaps:"
+#~ msgstr "ΜεταφοÏά στους χάÏτες φωτός:"
+
+#~ msgid "Allocating Texture #"
+#~ msgstr "Δέσμευση υφής #"
+
+#~ msgid "Baking Triangle #"
+#~ msgstr "ΠÏοεπεξεÏγασία Ï„Ïιγώνου #"
+
+#~ msgid "Post-Processing Texture #"
+#~ msgstr "ΜετεπεξεÏγασία υφής #"
+
+#~ msgid "Reset the lightmap octree baking process (start over)."
+#~ msgstr ""
+#~ "ΕπαναφοÏά της Ï€ÏοεπεξεÏγασίας του Î¿ÎºÏ„Î±Î´Î¹ÎºÎ¿Ï Î´Î­Î½Ï„Ïου του χάÏτη φωτός "
+#~ "(Εκκίνηση από την αÏχή)."
+
+#~ msgid "Zoom (%):"
+#~ msgstr "Μεγέθυνση (%):"
+
+#~ msgid "Skeleton.."
+#~ msgstr "Σκελετός.."
+
+#~ msgid "Zoom Reset"
+#~ msgstr "ΕπαναφοÏά μεγέθυνσης"
+
+#~ msgid "Zoom Set.."
+#~ msgstr "ΟÏισμός μεγέθυνσης.."
+
+#~ msgid "Set a Value"
+#~ msgstr "ΟÏισμός τιμής"
+
+#~ msgid "Snap (Pixels):"
+#~ msgstr "ΚοÏμπωμα (Εικονοστοιχεία):"
+
+#~ msgid "Parse BBCode"
+#~ msgstr "Ανάλυση BBCode"
+
+#~ msgid "Length:"
+#~ msgstr "Μήκος:"
+
+#~ msgid "Open Sample File(s)"
+#~ msgstr "Άνοιγμα αÏχείων δειγμάτων"
+
+#~ msgid "ERROR: Couldn't load sample!"
+#~ msgstr "ΣΦΑΛΜΑ: Δεν ήταν δυνατή η φόÏτωση δείγματος!"
+
+#~ msgid "Add Sample"
+#~ msgstr "ΠÏοσθήκη δείγματος"
+
+#~ msgid "Rename Sample"
+#~ msgstr "Μετονομασία δείγματος"
+
+#~ msgid "Delete Sample"
+#~ msgstr "ΔιαγÏαφή δείγματος"
+
+#~ msgid "16 Bits"
+#~ msgstr "16 Δυαδικά ψηφία"
+
+#~ msgid "8 Bits"
+#~ msgstr "8 Δυαδικά ψηφία"
+
+#~ msgid "Stereo"
+#~ msgstr "ΣτεÏεοφωνικό"
+
+#~ msgid "Mono"
+#~ msgstr "Μονοφωνικό"
+
+#~ msgid "Pitch"
+#~ msgstr "Τόνος"
+
+#~ msgid "Window"
+#~ msgstr "ΠαÏάθυÏο"
+
+#~ msgid "Move Right"
+#~ msgstr "Μετακίνηση δεξιά"
+
+#~ msgid "Scaling to %s%%."
+#~ msgstr "Κλιμάκωση to %s%%."
+
+#~ msgid "Up"
+#~ msgstr "Πάνω"
+
+#~ msgid "Down"
+#~ msgstr "Κάτω"
+
+#~ msgid "Bucket"
+#~ msgstr "Κουβάς"
+
+#~ msgid "Invalid project path, the path must exist!"
+#~ msgstr "Μη έγκυÏη διαδÏομή έÏγου, η διαδÏομή Ï€Ïέπει να υπάÏχει!"
+
+#~ msgid "Invalid project path, project.godot must not exist."
+#~ msgstr "Μη έγκυÏη διαδÏομή έÏγου, το project.godot δεν Ï€Ïέπει να υπάÏχει."
+
+#~ msgid "Invalid project path, project.godot must exist."
+#~ msgstr "Μη έγκυÏη διαδÏομή έÏγου, το project.godot Ï€Ïέπει να υπάÏχει."
+
+#~ msgid "Project Path (Must Exist):"
+#~ msgstr "ΔιαδÏομή έÏγου (ΠÏέπει να υπάÏχει):"
+
+#~ msgid "Create New Resource"
+#~ msgstr "ΔημιουÏγία νέου πόÏου"
+
+#~ msgid "Open Resource"
+#~ msgstr "Άνοιγμα πόÏου"
+
+#~ msgid "Save Resource"
+#~ msgstr "Αποθήκευση πόÏου"
+
+#~ msgid "Resource Tools"
+#~ msgstr "ΕÏγαλεία πόÏων"
+
+#~ msgid "Make Local"
+#~ msgstr "Κάνε τοπικό"
+
+#~ msgid "Edit Groups"
+#~ msgstr "ΕπεξεÏγασία Ομάδων"
+
+#~ msgid "Edit Connections"
+#~ msgstr "ΕπεξεÏγασία συνδέσεων"
+
+#~ msgid "GridMap Paint"
+#~ msgstr "GridMap ΖωγÏαφική"
+
+#~ msgid "Tiles"
+#~ msgstr "Πλακίδια"
+
+#~ msgid "Areas"
+#~ msgstr "ΠεÏιοχές"
+
+#~ msgid "Ctrl+"
+#~ msgstr "Ctrl+"
+
+#~ msgid "Down Wheel)"
+#~ msgstr "Κάτω Ïοδέλα)"
+
+#~ msgid "Up Wheel)"
+#~ msgstr "Πάνω Ïοδέλα)"
+
#~ msgid "Close scene? (Unsaved changes will be lost)"
#~ msgstr "Κλείσιμο σκηνής; (Οι μη αποθηκευμένες αλλαγές θα χαθοÏν)"
@@ -8043,9 +8325,6 @@ msgstr ""
#~ msgid "Close Goto Prev. Scene"
#~ msgstr "Κλείσιμο και μετάβαση στην Ï€ÏοηγοÏμενη σκηνή"
-#~ msgid "Expand to Parent"
-#~ msgstr "Επικάλυψη γονέα"
-
#~ msgid "Del"
#~ msgstr "ΔιαγÏαφή"
@@ -8209,8 +8488,5 @@ msgstr ""
#~ msgid "Save Translatable Strings"
#~ msgstr "Αποθήκευση μεταφÏάσιμων συμβολοσειÏών"
-#~ msgid "Translatable Strings.."
-#~ msgstr "ΜεταφÏάσιμες συμβολοσειÏές..."
-
#~ msgid "Install Export Templates"
#~ msgstr "Εγκατάσταση Ï€ÏοτÏπων εξαγωγής"
diff --git a/editor/translations/es.po b/editor/translations/es.po
index 8b2cab5fb9..dd4b811bff 100644
--- a/editor/translations/es.po
+++ b/editor/translations/es.po
@@ -1,5 +1,6 @@
# Spanish translation of the Godot Engine editor
-# Copyright (C) 2016-2017 Juan Linietsky, Ariel Manzur and the Godot community
+# Copyright (C) 2007-2017 Juan Linietsky, Ariel Manzur
+# Copyright (C) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)
# This file is distributed under the same license as the Godot source code.
#
# Addiel Lucena Perez <addiell2017@gmail.com>, 2017.
@@ -7,6 +8,7 @@
# BLaDoM GUY <simplybladom@gmail.com>, 2017.
# Carlos López <genetita@gmail.com>, 2016.
# Lisandro Lorea <lisandrolorea@gmail.com>, 2016-2017.
+# Rabid Orange <theorangerabid@gmail.com>, 2017.
# Roger BR <drai_kin@hotmail.com>, 2016.
# Sebastian Silva <sebastian@fuentelibre.org>, 2016.
# Swyter <swyterzone@gmail.com>, 2016-2017.
@@ -15,8 +17,8 @@ msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2017-07-08 01:05+0000\n"
-"Last-Translator: BLaDoM GUY <simplybladom@gmail.com>\n"
+"PO-Revision-Date: 2017-10-23 01:48+0000\n"
+"Last-Translator: Lisandro Lorea <lisandrolorea@gmail.com>\n"
"Language-Team: Spanish <https://hosted.weblate.org/projects/godot-engine/"
"godot/es/>\n"
"Language: es\n"
@@ -24,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 2.16-dev\n"
+"X-Generator: Weblate 2.17\n"
#: editor/animation_editor.cpp
msgid "Disabled"
@@ -198,13 +200,12 @@ msgstr "¿Quieres crear una NUEVA pista para %s e insertar clave?"
#: editor/animation_editor.cpp
msgid "Create %d NEW tracks and insert keys?"
-msgstr "¿Quieres crear %d NUEVOS pistas e insertar claves?"
+msgstr "¿Quieres crear %d NUEVAS pistas e insertar claves?"
#: editor/animation_editor.cpp editor/create_dialog.cpp
-#: editor/editor_audio_buses.cpp
+#: editor/editor_audio_buses.cpp editor/plugins/abstract_polygon_2d_editor.cpp
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
#: editor/plugins/mesh_instance_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp editor/project_manager.cpp
#: editor/script_create_dialog.cpp
msgid "Create"
@@ -369,272 +370,6 @@ msgstr "Cambiar tipo de valor del «array»"
msgid "Change Array Value"
msgstr "Cambiar valor del «array»"
-#: editor/asset_library_editor_plugin.cpp
-msgid "Free"
-msgstr "Libre"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_plugin_settings.cpp
-msgid "Version:"
-msgstr "Versión:"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Contents:"
-msgstr "Constantes:"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "View Files"
-msgstr "Archivo"
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_help.cpp editor/property_selector.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Description:"
-msgstr "Descripción:"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-#: editor/project_manager.cpp
-msgid "Install"
-msgstr "Instalar"
-
-#: editor/asset_library_editor_plugin.cpp editor/call_dialog.cpp
-#: editor/connections_dialog.cpp editor/export_template_manager.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-#: editor/project_settings_editor.cpp editor/property_editor.cpp
-#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Close"
-msgstr "Cerrar"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve hostname:"
-msgstr "No se ha podido resolver el nombre de Dominio:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve."
-msgstr "No se ha podido resolver."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Connection error, please try again."
-msgstr "Error de conexion, por favor intente otra vez."
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Can't connect."
-msgstr "Conectar.."
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Can't connect to host:"
-msgstr "Conectar a nodo:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response from host:"
-msgstr "No hay respuesta desde el host:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response."
-msgstr "No responde."
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Request failed, return code:"
-msgstr "Formato de archivo desconocido:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Req. Failed."
-msgstr "Solicitud fallida."
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Request failed, too many redirects"
-msgstr "Solicitud fallida, ha redireccionado demasiado"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Redirect Loop."
-msgstr "Bucle de redireccionamiento."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed:"
-msgstr "Fallido:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Bad download hash, assuming file has been tampered with."
-msgstr "Error de descarga, al pareser el archivo ha sido manipulado."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Expected:"
-msgstr "Esperado:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Got:"
-msgstr "Tiene:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Asset Download Error:"
-msgstr "Error en la descarga del asset:"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-msgid "Success!"
-msgstr "Finalizado!"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Fetching:"
-msgstr "Buscando:"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Resolving.."
-msgstr "Guardando…"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Connecting.."
-msgstr "Conectar.."
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Requesting.."
-msgstr "Prueba"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Error making request"
-msgstr "¡Hubo un error al guardar el recurso!"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Idle"
-msgstr "Inactivo"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Retry"
-msgstr "Reintente"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Download Error"
-msgstr "Abajo"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Download for this asset is already in progress!"
-msgstr "Este asset ya esta descargandose!"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "first"
-msgstr "primero"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "prev"
-msgstr "anterior"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "next"
-msgstr "siguiente"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "last"
-msgstr "ultimo"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "All"
-msgstr "Todos"
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
-#: editor/settings_config_dialog.cpp
-msgid "Search:"
-msgstr "Buscar:"
-
-#: editor/asset_library_editor_plugin.cpp editor/code_editor.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Search"
-msgstr "Buscar"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/project_manager.cpp
-msgid "Import"
-msgstr "Importar"
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Plugins"
-msgstr "Plugins"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Sort:"
-msgstr "Ordenar:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Reverse"
-msgstr "Invertir"
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Category:"
-msgstr "Categoría:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Site:"
-msgstr "Sitio:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Support.."
-msgstr "Soporte.."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Official"
-msgstr "Oficial"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-msgid "Community"
-msgstr "Comunidad"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Testing"
-msgstr "Prueba"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Assets ZIP File"
-msgstr "Archivo ZIP de elementos"
-
-#: editor/call_dialog.cpp
-msgid "Method List For '%s':"
-msgstr "Lista de métodos Para '%s':"
-
-#: editor/call_dialog.cpp modules/visual_script/visual_script_editor.cpp
-msgid "Call"
-msgstr "Llamada"
-
-#: editor/call_dialog.cpp
-msgid "Method List:"
-msgstr "Lista de métodos:"
-
-#: editor/call_dialog.cpp
-msgid "Arguments:"
-msgstr "Argumentos:"
-
-#: editor/call_dialog.cpp
-msgid "Return:"
-msgstr "Devuelve:"
-
#: editor/code_editor.cpp
msgid "Go to Line"
msgstr "Ir a línea"
@@ -648,9 +383,8 @@ msgid "No Matches"
msgstr "Sin soincidencias"
#: editor/code_editor.cpp
-#, fuzzy
msgid "Replaced %d occurrence(s)."
-msgstr "%d ocurrencias reemplazadas."
+msgstr "%d ocurrencia/s reemplazadas."
#: editor/code_editor.cpp
msgid "Replace"
@@ -672,6 +406,14 @@ msgstr "Palabras completas"
msgid "Selection Only"
msgstr "Sólo selección"
+#: editor/code_editor.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
+msgid "Search"
+msgstr "Buscar"
+
#: editor/code_editor.cpp editor/editor_help.cpp
msgid "Find"
msgstr "Búsqueda"
@@ -704,11 +446,11 @@ msgstr "Preguntar antes de reemplazar"
msgid "Skip"
msgstr "Saltar"
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom In"
msgstr "Acercar"
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom Out"
msgstr "Alejar"
@@ -779,6 +521,20 @@ msgstr "Diferido"
msgid "Oneshot"
msgstr "Una vez"
+#: editor/connections_dialog.cpp editor/dependency_editor.cpp
+#: editor/export_template_manager.cpp
+#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Close"
+msgstr "Cerrar"
+
#: editor/connections_dialog.cpp
msgid "Connect"
msgstr "Conectar"
@@ -804,7 +560,7 @@ msgstr "Conectar.."
msgid "Disconnect"
msgstr "Desconectar"
-#: editor/connections_dialog.cpp editor/node_dock.cpp
+#: editor/connections_dialog.cpp editor/editor_help.cpp editor/node_dock.cpp
msgid "Signals"
msgstr "Señales"
@@ -821,12 +577,25 @@ msgstr "Favoritos:"
msgid "Recent:"
msgstr "Recientes:"
+#: editor/create_dialog.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/quick_open.cpp editor/settings_config_dialog.cpp
+msgid "Search:"
+msgstr "Buscar:"
+
#: editor/create_dialog.cpp editor/editor_help.cpp
#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/quick_open.cpp
msgid "Matches:"
msgstr "Coincidencias:"
+#: editor/create_dialog.cpp editor/editor_help.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/property_selector.cpp
+#: editor/script_editor_debugger.cpp
+msgid "Description:"
+msgstr "Descripción:"
+
#: editor/dependency_editor.cpp
msgid "Search Replacement For:"
msgstr "Buscar reemplazo para:"
@@ -886,6 +655,12 @@ msgid "Owners Of:"
msgstr "Dueños de:"
#: editor/dependency_editor.cpp
+msgid "Remove selected files from the project? (no undo)"
+msgstr ""
+"¿Quieres quitar los archivos seleccionados del proyecto? (No puedes "
+"deshacerlo)"
+
+#: editor/dependency_editor.cpp
msgid ""
"The files being removed are required by other resources in order for them to "
"work.\n"
@@ -896,10 +671,9 @@ msgstr ""
"¿Seguro que quieres quitarlos? (No puedes deshacerlo)"
#: editor/dependency_editor.cpp
-msgid "Remove selected files from the project? (no undo)"
-msgstr ""
-"¿Quieres quitar los archivos seleccionados del proyecto? (No puedes "
-"deshacerlo)"
+#, fuzzy
+msgid "Cannot remove:\n"
+msgstr "No se ha podido resolver."
#: editor/dependency_editor.cpp
msgid "Error loading:"
@@ -966,11 +740,6 @@ msgstr "Contribuidores de Godot"
#: editor/editor_about.cpp
#, fuzzy
-msgid "Authors"
-msgstr "Autor:"
-
-#: editor/editor_about.cpp
-#, fuzzy
msgid "Project Founders"
msgstr "Administrador de proyectos"
@@ -988,20 +757,58 @@ msgid "Developers"
msgstr "Desarrolladores"
#: editor/editor_about.cpp
-msgid "License"
+#, fuzzy
+msgid "Authors"
+msgstr "Autor:"
+
+#: editor/editor_about.cpp
+msgid "Platinum Sponsors"
msgstr ""
#: editor/editor_about.cpp
-msgid "Thirdparty License"
+msgid "Gold Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Mini Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Gold Donors"
msgstr ""
#: editor/editor_about.cpp
+msgid "Silver Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+#, fuzzy
+msgid "Bronze Donors"
+msgstr "Clonar hacia abajo"
+
+#: editor/editor_about.cpp
+msgid "Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "License"
+msgstr "Licencia"
+
+#: editor/editor_about.cpp
+msgid "Thirdparty License"
+msgstr "Licencia de terceros"
+
+#: editor/editor_about.cpp
msgid ""
"Godot Engine relies on a number of thirdparty free and open source "
"libraries, all compatible with the terms of its MIT license. The following "
"is an exhaustive list of all such thirdparty components with their "
"respective copyright statements and license terms."
msgstr ""
+"Godot Engine se basa en una serie de bibliotecas libres y de código abierto "
+"de terceros, todas ellas compatibles con los términos de su licencia MIT. La "
+"siguiente es una lista exhaustiva de todos estos componentes de terceros con "
+"sus respectivas declaraciones de derechos de autor y términos de licencia."
#: editor/editor_about.cpp
#, fuzzy
@@ -1015,11 +822,11 @@ msgstr "Constantes:"
#: editor/editor_about.cpp
msgid "Licenses"
-msgstr ""
+msgstr "Licencias"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Error opening package file, not in zip format."
-msgstr ""
+msgstr "Error al abrir el paquete, no se encuentra en formato zip."
#: editor/editor_asset_installer.cpp
#, fuzzy
@@ -1031,13 +838,23 @@ msgid "Package Installed Successfully!"
msgstr "¡El paquete se ha instalado correctamente!"
#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Success!"
+msgstr "Finalizado!"
+
+#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/project_manager.cpp
+msgid "Install"
+msgstr "Instalar"
+
+#: editor/editor_asset_installer.cpp
#, fuzzy
msgid "Package Installer"
msgstr "¡El paquete se ha instalado correctamente!"
#: editor/editor_audio_buses.cpp
msgid "Speakers"
-msgstr ""
+msgstr "Altavoces"
#: editor/editor_audio_buses.cpp
#, fuzzy
@@ -1060,20 +877,24 @@ msgid "Toggle Audio Bus Mute"
msgstr "Abrir diseño del Audio Bus"
#: editor/editor_audio_buses.cpp
+#, fuzzy
msgid "Toggle Audio Bus Bypass Effects"
-msgstr ""
+msgstr "Cambiar efectos de bypass del Bus de Audio"
#: editor/editor_audio_buses.cpp
+#, fuzzy
msgid "Select Audio Bus Send"
-msgstr ""
+msgstr "Seleccionar Bus de audio de envío"
#: editor/editor_audio_buses.cpp
+#, fuzzy
msgid "Add Audio Bus Effect"
-msgstr ""
+msgstr "Añadir Efecto de Bus de Audio"
#: editor/editor_audio_buses.cpp
+#, fuzzy
msgid "Move Bus Effect"
-msgstr ""
+msgstr "Mover Efecto de Bus"
#: editor/editor_audio_buses.cpp
#, fuzzy
@@ -1081,25 +902,28 @@ msgid "Delete Bus Effect"
msgstr "Quitar seleccionados"
#: editor/editor_audio_buses.cpp
+#, fuzzy
msgid "Audio Bus, Drag and Drop to rearrange."
-msgstr ""
+msgstr "Bus de Audio, arrastra y suelta para reordenar."
#: editor/editor_audio_buses.cpp
#, fuzzy
-msgid "Bus options"
-msgstr "Opciones de depuración"
-
-#: editor/editor_audio_buses.cpp
msgid "Solo"
-msgstr ""
+msgstr "Solo"
#: editor/editor_audio_buses.cpp
msgid "Mute"
-msgstr ""
+msgstr "Silenciar"
#: editor/editor_audio_buses.cpp
+#, fuzzy
msgid "Bypass"
-msgstr ""
+msgstr "Bypass"
+
+#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Bus options"
+msgstr "Opciones de depuración"
#: editor/editor_audio_buses.cpp editor/plugins/tile_map_editor_plugin.cpp
#: editor/scene_tree_dock.cpp
@@ -1108,6 +932,11 @@ msgstr "Duplicar"
#: editor/editor_audio_buses.cpp
#, fuzzy
+msgid "Reset Volume"
+msgstr "Restablecer zoom"
+
+#: editor/editor_audio_buses.cpp
+#, fuzzy
msgid "Delete Effect"
msgstr "Quitar seleccionados"
@@ -1118,7 +947,7 @@ msgstr "Añadir todos"
#: editor/editor_audio_buses.cpp
msgid "Master bus can't be deleted!"
-msgstr ""
+msgstr "¡El Bus Maestro no puede ser borrado!"
#: editor/editor_audio_buses.cpp
#, fuzzy
@@ -1132,6 +961,11 @@ msgstr "Duplicar animación"
#: editor/editor_audio_buses.cpp
#, fuzzy
+msgid "Reset Bus Volume"
+msgstr "Restablecer zoom"
+
+#: editor/editor_audio_buses.cpp
+#, fuzzy
msgid "Move Audio Bus"
msgstr "Mover acción"
@@ -1148,8 +982,9 @@ msgid "Open Audio Bus Layout"
msgstr "Abrir diseño del Audio Bus"
#: editor/editor_audio_buses.cpp
+#, fuzzy
msgid "There is no 'res://default_bus_layout.tres' file."
-msgstr ""
+msgstr "No existe el archivo 'res://default_bus_layout.tres'."
#: editor/editor_audio_buses.cpp
#, fuzzy
@@ -1168,7 +1003,8 @@ msgstr "Añadir todos"
msgid "Create a new Bus Layout."
msgstr "Crear recurso nuevo"
-#: editor/editor_audio_buses.cpp editor/script_create_dialog.cpp
+#: editor/editor_audio_buses.cpp editor/property_editor.cpp
+#: editor/script_create_dialog.cpp
msgid "Load"
msgstr "Cargar"
@@ -1193,8 +1029,9 @@ msgid "Load Default"
msgstr "Predeterminado"
#: editor/editor_audio_buses.cpp
+#, fuzzy
msgid "Load the default Bus Layout."
-msgstr ""
+msgstr "Cargar el Diseño del Bus por defecto."
#: editor/editor_autoload_settings.cpp
msgid "Invalid name."
@@ -1267,7 +1104,7 @@ msgid "Rearrange Autoloads"
msgstr "Reordenar «Autoloads»"
#: editor/editor_autoload_settings.cpp editor/editor_file_dialog.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp scene/gui/file_dialog.cpp
+#: scene/gui/file_dialog.cpp
msgid "Path:"
msgstr "Ruta:"
@@ -1275,9 +1112,7 @@ msgstr "Ruta:"
msgid "Node Name:"
msgstr "Nombre del nodo:"
-#: editor/editor_autoload_settings.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp editor/project_manager.cpp
+#: editor/editor_autoload_settings.cpp editor/project_manager.cpp
msgid "Name"
msgstr "Nombre"
@@ -1311,18 +1146,19 @@ msgid "Choose a Directory"
msgstr "Elige una carpeta"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Create Folder"
msgstr "Crear carpeta"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: editor/editor_plugin_settings.cpp editor/plugins/theme_editor_plugin.cpp
-#: editor/project_export.cpp scene/gui/file_dialog.cpp
+#: editor/editor_plugin_settings.cpp editor/filesystem_dock.cpp
+#: editor/plugins/theme_editor_plugin.cpp editor/project_export.cpp
+#: scene/gui/file_dialog.cpp
msgid "Name:"
msgstr "Nombre:"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Could not create folder."
msgstr "No se pudo crear la carpeta."
@@ -1343,30 +1179,6 @@ msgstr "Empaquetando"
msgid "Template file not found:\n"
msgstr "No se encontró archivo de base:\n"
-#: editor/editor_export.cpp
-msgid "Added:"
-msgstr "Añadido:"
-
-#: editor/editor_export.cpp
-msgid "Removed:"
-msgstr "Eliminado:"
-
-#: editor/editor_export.cpp
-msgid "Error saving atlas:"
-msgstr "Error al guardar atlas:"
-
-#: editor/editor_export.cpp
-msgid "Could not save atlas subtexture:"
-msgstr "No se pudo guardar la subtextura del altas:"
-
-#: editor/editor_export.cpp
-msgid "Exporting for %s"
-msgstr "Exportando para %s"
-
-#: editor/editor_export.cpp
-msgid "Setting Up.."
-msgstr "Configurando…"
-
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "File Exists, Overwrite?"
msgstr "El archivo ya existe, ¿quieres sobreescribirlo?"
@@ -1451,6 +1263,11 @@ msgstr "Subir favorito"
msgid "Move Favorite Down"
msgstr "Bajar favorito"
+#: editor/editor_file_dialog.cpp
+#, fuzzy
+msgid "Go to parent folder"
+msgstr "No se pudo crear la carpeta."
+
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Directories & Files:"
msgstr "Carpetas y archivos:"
@@ -1465,10 +1282,6 @@ msgid "File:"
msgstr "Archivo:"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
-msgid "Filter:"
-msgstr "Filtro:"
-
-#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Must use a valid extension."
msgstr "Debe ser una extensión válida."
@@ -1494,6 +1307,10 @@ msgstr "Lista de clases:"
msgid "Search Classes"
msgstr "Buscar clases"
+#: editor/editor_help.cpp editor/plugins/spatial_editor_plugin.cpp
+msgid "Top"
+msgstr "Cima"
+
#: editor/editor_help.cpp editor/property_editor.cpp
msgid "Class:"
msgstr "Clase:"
@@ -1510,15 +1327,30 @@ msgstr "Heredada por:"
msgid "Brief Description:"
msgstr "Descripción breve:"
+#: editor/editor_help.cpp
+#, fuzzy
+msgid "Members"
+msgstr "Miembros:"
+
#: editor/editor_help.cpp modules/visual_script/visual_script_editor.cpp
msgid "Members:"
msgstr "Miembros:"
#: editor/editor_help.cpp
+#, fuzzy
+msgid "Public Methods"
+msgstr "Métodos públicos:"
+
+#: editor/editor_help.cpp
msgid "Public Methods:"
msgstr "Métodos públicos:"
#: editor/editor_help.cpp
+#, fuzzy
+msgid "GUI Theme Items"
+msgstr "Elementos de tema de interfaz:"
+
+#: editor/editor_help.cpp
msgid "GUI Theme Items:"
msgstr "Elementos de tema de interfaz:"
@@ -1528,12 +1360,23 @@ msgstr "Señales:"
#: editor/editor_help.cpp
#, fuzzy
+msgid "Enumerations"
+msgstr "Animaciones"
+
+#: editor/editor_help.cpp
+#, fuzzy
msgid "Enumerations:"
msgstr "Animaciones"
#: editor/editor_help.cpp
+#, fuzzy
msgid "enum "
-msgstr ""
+msgstr "enum "
+
+#: editor/editor_help.cpp
+#, fuzzy
+msgid "Constants"
+msgstr "Constantes:"
#: editor/editor_help.cpp
msgid "Constants:"
@@ -1541,14 +1384,41 @@ msgstr "Constantes:"
#: editor/editor_help.cpp
#, fuzzy
+msgid "Description"
+msgstr "Descripción:"
+
+#: editor/editor_help.cpp
+#, fuzzy
+msgid "Properties"
+msgstr "Propiedades:"
+
+#: editor/editor_help.cpp
+#, fuzzy
msgid "Property Description:"
msgstr "Descripción breve:"
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this property. Please help us by "
+"[color=$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+
+#: editor/editor_help.cpp
+#, fuzzy
+msgid "Methods"
+msgstr "Lista de métodos:"
+
+#: editor/editor_help.cpp
msgid "Method Description:"
msgstr "Descripción de métodos:"
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this method. Please help us by [color="
+"$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Search Text"
msgstr "Texto de búsqueda"
@@ -1558,26 +1428,24 @@ msgid "Output:"
msgstr " Salida:"
#: editor/editor_log.cpp editor/plugins/animation_tree_editor_plugin.cpp
-#: editor/plugins/rich_text_editor_plugin.cpp editor/property_editor.cpp
-#: editor/script_editor_debugger.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/property_editor.cpp editor/script_editor_debugger.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Clear"
msgstr "Borrar todo"
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Error saving resource!"
msgstr "¡Hubo un error al guardar el recurso!"
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Save Resource As.."
-msgstr "Guardar recurso como…"
+msgstr "Guardar recurso como.."
-#: editor/editor_node.cpp editor/export_template_manager.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
+#, fuzzy
msgid "I see.."
-msgstr "Muy bien…"
+msgstr "Ya veo.."
#: editor/editor_node.cpp
msgid "Can't open file for writing:"
@@ -1592,6 +1460,30 @@ msgid "Error while saving."
msgstr "Error al guardar."
#: editor/editor_node.cpp
+#, fuzzy
+msgid "Can't open '%s'."
+msgstr "No se puede operar en «…»"
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Error while parsing '%s'."
+msgstr "Error al guardar."
+
+#: editor/editor_node.cpp
+msgid "Unexpected end of file '%s'."
+msgstr ""
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Missing '%s' or its dependencies."
+msgstr "La escena «%s» tiene dependencias rotas:"
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Error while loading '%s'."
+msgstr "Error al guardar."
+
+#: editor/editor_node.cpp
msgid "Saving Scene"
msgstr "Guardar escena"
@@ -1652,6 +1544,33 @@ msgid "Restored default layout to base settings."
msgstr "Se han restaurado los ajustes predeterminados."
#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was imported, so it's not editable.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was instanced or inherited.\n"
+"Changes to it will not be kept when saving the current scene."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource was imported, so it's not editable. Change its settings in the "
+"import panel and then re-import."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This scene was imported, so changes to it will not be kept.\n"
+"Instancing it or inheriting will allow making changes to it.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Copy Params"
msgstr "Copiar parámetros"
@@ -1734,11 +1653,11 @@ msgstr "Abrir escena base"
#: editor/editor_node.cpp
msgid "Quick Open Scene.."
-msgstr "Apertura rápida de escena…"
+msgstr "Apertura rápida de escena.."
#: editor/editor_node.cpp
msgid "Quick Open Script.."
-msgstr "Apertura rápida de script…"
+msgstr "Apertura rápida de script.."
#: editor/editor_node.cpp
#, fuzzy
@@ -1746,12 +1665,13 @@ msgid "Save & Close"
msgstr "Guardar un archivo"
#: editor/editor_node.cpp
+#, fuzzy
msgid "Save changes to '%s' before closing?"
-msgstr ""
+msgstr "¿Guardar cambios a '%s' antes de cerrar?"
#: editor/editor_node.cpp
msgid "Save Scene As.."
-msgstr "Guardar escena como…"
+msgstr "Guardar escena como.."
#: editor/editor_node.cpp
#, fuzzy
@@ -1802,7 +1722,7 @@ msgstr "Esta acción es irreversible. ¿Quieres revertirla de todos modos?"
#: editor/editor_node.cpp
msgid "Quick Run Scene.."
-msgstr "Ejecución rápida de escena…"
+msgstr "Ejecución rápida de escena.."
#: editor/editor_node.cpp
msgid "Quit"
@@ -1824,31 +1744,52 @@ msgstr "Guardar un archivo"
#: editor/editor_node.cpp
msgid "Save changes to the following scene(s) before quitting?"
-msgstr ""
+msgstr "¿Guardar cambios a la(s) siguiente(s) escena(s) antes de salir?"
#: editor/editor_node.cpp
+#, fuzzy
msgid "Save changes the following scene(s) before opening Project Manager?"
msgstr ""
+"¿Guardar cambios a la(s) siguiente(s) escena(s) antes de abrir el Gestor de "
+"Proyectos?"
+
+#: editor/editor_node.cpp
+msgid ""
+"This option is deprecated. Situations where refresh must be forced are now "
+"considered a bug. Please report."
+msgstr ""
#: editor/editor_node.cpp
msgid "Pick a Main Scene"
msgstr "Elige una escena principal"
#: editor/editor_node.cpp
-msgid "Unable to enable addon plugin at: '"
-msgstr ""
+#, fuzzy
+msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
+msgstr "No se pudo activar el plugin addon en: '"
#: editor/editor_node.cpp
-msgid "' parsing of config failed."
+#, fuzzy
+msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
msgstr ""
+"No se pudo encontrar el campo del script para el plugin addon en: 'res://"
+"addons/"
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/"
-msgstr ""
+#, fuzzy
+msgid "Unable to load addon script from path: '%s'."
+msgstr "No se pudo cargar el script addon desde la ruta: '"
#: editor/editor_node.cpp
-msgid "Unable to load addon script from path: '"
-msgstr ""
+#, fuzzy
+msgid ""
+"Unable to load addon script from path: '%s' Base type is not EditorPlugin."
+msgstr "No se pudo cargar el script addon desde la ruta: '"
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Unable to load addon script from path: '%s' Script is not in tool mode."
+msgstr "No se pudo cargar el script addon desde la ruta: '"
#: editor/editor_node.cpp
msgid ""
@@ -1860,7 +1801,7 @@ msgstr ""
"Para poder modificarla, se tiene que crear una nueva escena heredada."
#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/scene_tree_dock.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Ugh"
msgstr "Vaya"
@@ -1874,14 +1815,15 @@ msgstr ""
"la ruta del proyecto."
#: editor/editor_node.cpp
-msgid "Error loading scene."
-msgstr "Hubo un error al cargar la escena."
-
-#: editor/editor_node.cpp
msgid "Scene '%s' has broken dependencies:"
msgstr "La escena «%s» tiene dependencias rotas:"
#: editor/editor_node.cpp
+#, fuzzy
+msgid "Clear Recent Scenes"
+msgstr "Reestablecer huesos"
+
+#: editor/editor_node.cpp
msgid "Save Layout"
msgstr "Guardar ajustes"
@@ -1915,7 +1857,7 @@ msgstr "Modo sin distracciones"
msgid "Toggle distraction-free mode."
msgstr "Modo sin distracciones"
-#: editor/editor_node.cpp editor/io_plugins/editor_scene_import_plugin.cpp
+#: editor/editor_node.cpp
msgid "Scene"
msgstr "Escena"
@@ -1946,7 +1888,7 @@ msgstr "Nueva escena"
#: editor/editor_node.cpp
msgid "New Inherited Scene.."
-msgstr "Nueva escena heredada…"
+msgstr "Nueva escena heredada.."
#: editor/editor_node.cpp
msgid "Open Scene.."
@@ -1970,15 +1912,16 @@ msgstr "Abrir reciente"
#: editor/editor_node.cpp
msgid "Convert To.."
-msgstr "Convertir a…"
+msgstr "Convertir a.."
#: editor/editor_node.cpp
msgid "MeshLibrary.."
-msgstr "MeshLibrary…"
+msgstr "MeshLibrary.."
#: editor/editor_node.cpp
+#, fuzzy
msgid "TileSet.."
-msgstr "TileSet…"
+msgstr "TileSet.."
#: editor/editor_node.cpp editor/plugins/script_text_editor.cpp
#: editor/plugins/shader_editor_plugin.cpp scene/gui/line_edit.cpp
@@ -2159,6 +2102,10 @@ msgstr "P&R"
msgid "Issue Tracker"
msgstr "Registros de problemas"
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+msgid "Community"
+msgstr "Comunidad"
+
#: editor/editor_node.cpp
msgid "About"
msgstr "Acerca de"
@@ -2167,7 +2114,7 @@ msgstr "Acerca de"
msgid "Play the project."
msgstr "Inicia el proyecto para poder jugarlo."
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Play"
msgstr "Reproducir"
@@ -2183,7 +2130,7 @@ msgstr "Pausar la escena"
msgid "Stop the scene."
msgstr "Detener la escena."
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Stop"
msgstr "Detener"
@@ -2238,7 +2185,7 @@ msgstr "Guardar el recurso editado actualmente."
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
msgid "Save As.."
-msgstr "Guardar como…"
+msgstr "Guardar como.."
#: editor/editor_node.cpp
msgid "Go to the previous edited object in history."
@@ -2257,6 +2204,16 @@ msgid "Object properties."
msgstr "Propiedades del objeto."
#: editor/editor_node.cpp
+#, fuzzy
+msgid "Changes may be lost!"
+msgstr "Cambiar grupo de imágenes"
+
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Import"
+msgstr "Importar"
+
+#: editor/editor_node.cpp
msgid "FileSystem"
msgstr "SistDeArchivos"
@@ -2270,15 +2227,7 @@ msgstr "Salida"
#: editor/editor_node.cpp
msgid "Don't Save"
-msgstr ""
-
-#: editor/editor_node.cpp editor/editor_reimport_dialog.cpp
-msgid "Re-Import"
-msgstr "Reimportar"
-
-#: editor/editor_node.cpp editor/editor_plugin_settings.cpp
-msgid "Update"
-msgstr "Actualizar"
+msgstr "No guardar"
#: editor/editor_node.cpp
msgid "Import Templates From ZIP File"
@@ -2347,11 +2296,29 @@ msgstr "Abrir en el editor"
msgid "Open the previous Editor"
msgstr "Abrir en el editor"
+#: editor/editor_plugin.cpp
+#, fuzzy
+msgid "Creating Mesh Previews"
+msgstr "Crear biblioteca de modelos 3D"
+
+#: editor/editor_plugin.cpp
+msgid "Thumbnail.."
+msgstr "Miniatura.."
+
#: editor/editor_plugin_settings.cpp
msgid "Installed Plugins:"
msgstr "Plugins instalados:"
#: editor/editor_plugin_settings.cpp
+msgid "Update"
+msgstr "Actualizar"
+
+#: editor/editor_plugin_settings.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Version:"
+msgstr "Versión:"
+
+#: editor/editor_plugin_settings.cpp
msgid "Author:"
msgstr "Autor:"
@@ -2384,7 +2351,8 @@ msgid "Frame %"
msgstr "% de cuadro"
#: editor/editor_profiler.cpp
-msgid "Fixed Frame %"
+#, fuzzy
+msgid "Physics Frame %"
msgstr "% de cuadro fijo"
#: editor/editor_profiler.cpp editor/script_editor_debugger.cpp
@@ -2403,35 +2371,19 @@ msgstr "Propio"
msgid "Frame #:"
msgstr "Nº de cuadro:"
-#: editor/editor_reimport_dialog.cpp
-msgid "Please wait for scan to complete."
-msgstr "Espera a que termine el análisis."
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Current scene must be saved to re-import."
-msgstr "La escena actual debe ser guardada para reimportar."
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Save & Re-Import"
-msgstr "Guardar y reimportar"
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Importing"
-msgstr "Reimportando"
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Import Changed Resources"
-msgstr "Reimportar recursos cambiados"
-
#: editor/editor_run_native.cpp
msgid "Select device from the list"
-msgstr ""
+msgstr "Seleccionar dispositivo de la lista"
#: editor/editor_run_native.cpp
+#, fuzzy
msgid ""
"No runnable export preset found for this platform.\n"
"Please add a runnable preset in the export menu."
msgstr ""
+"No se ha encontrado un preset ejecutable de exportación para esta "
+"plataforma.\n"
+"Por favor, añade un preset ejecutable en el menú de exportación."
#: editor/editor_run_script.cpp
msgid "Write your logic in the _run() method."
@@ -2447,7 +2399,7 @@ msgstr "No se pudo instanciar el script:"
#: editor/editor_run_script.cpp
msgid "Did you forget the 'tool' keyword?"
-msgstr "Te olvidaste de la palabra clave 'tool'?"
+msgstr "Has olvidado la palabra clave 'tool'?"
#: editor/editor_run_script.cpp
msgid "Couldn't run script:"
@@ -2524,7 +2476,7 @@ msgstr ""
#: editor/export_template_manager.cpp
msgid "No version.txt found inside templates."
-msgstr ""
+msgstr "No se ha encontrado el archivo version.txt dentro de las plantillas."
#: editor/export_template_manager.cpp
#, fuzzy
@@ -2541,10 +2493,6 @@ msgid "Importing:"
msgstr "Importando:"
#: editor/export_template_manager.cpp
-msgid "Loading Export Templates"
-msgstr "Cargando plantillas de exportación"
-
-#: editor/export_template_manager.cpp
#, fuzzy
msgid "Current Version:"
msgstr "Escena actual"
@@ -2582,14 +2530,21 @@ msgstr ""
#: editor/filesystem_dock.cpp
msgid "Cannot navigate to '"
+msgstr "No se puede navegar a '"
+
+#: editor/filesystem_dock.cpp
+msgid "View items as a grid of thumbnails"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "View items as a list"
msgstr ""
#: editor/filesystem_dock.cpp
-#, fuzzy
msgid ""
"\n"
-"Status: Needs Re-Import"
-msgstr "Guardar y reimportar"
+"Status: Import of file failed. Please fix file and reimport manually."
+msgstr ""
#: editor/filesystem_dock.cpp
#, fuzzy
@@ -2599,48 +2554,57 @@ msgid ""
msgstr "Fuente:"
#: editor/filesystem_dock.cpp
-msgid "Same source and destination files, doing nothing."
-msgstr ""
-"Los archivos de origen y destino son iguales, no se realizará ninguna acción."
+#, fuzzy
+msgid "Cannot move/rename resources root."
+msgstr "No se puede cargar/procesar la tipografía elegida."
#: editor/filesystem_dock.cpp
-msgid "Target file exists, can't overwrite. Delete first."
-msgstr ""
+#, fuzzy
+msgid "Cannot move a folder into itself.\n"
+msgstr "No se puede importar un archivo sobre si mismo:"
#: editor/filesystem_dock.cpp
-msgid "Same source and destination paths, doing nothing."
-msgstr ""
-"Las rutas de origen y destino son iguales, no se realizará ninguna acción."
+#, fuzzy
+msgid "Error moving:\n"
+msgstr "Hubo un error al importar:"
#: editor/filesystem_dock.cpp
-msgid "Can't move directories to within themselves."
-msgstr "No se pueden mover carpetas dentro de si mismas."
+#, fuzzy
+msgid "Unable to update dependencies:\n"
+msgstr "La escena «%s» tiene dependencias rotas:"
+
+#: editor/filesystem_dock.cpp
+msgid "No name provided"
+msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Can't rename deps for:\n"
+msgid "Provided name contains invalid characters"
msgstr ""
#: editor/filesystem_dock.cpp
#, fuzzy
-msgid "Error moving file:\n"
-msgstr "Error al cargar la imagen:"
+msgid "No name provided."
+msgstr "Renombrar o mover.."
#: editor/filesystem_dock.cpp
#, fuzzy
-msgid "Error moving dir:\n"
-msgstr "Hubo un error al importar:"
+msgid "Name contains invalid characters."
+msgstr "Letras válidas:"
#: editor/filesystem_dock.cpp
-msgid "Can't operate on '..'"
-msgstr "No se puede operar en «…»"
+#, fuzzy
+msgid "A file or folder with this name already exists."
+msgstr "¡El nombre de grupo ya existe!"
#: editor/filesystem_dock.cpp
-msgid "Pick New Name and Location For:"
-msgstr "Elige un nombre nuevo y ubicación para:"
+#, fuzzy
+msgid "Renaming file:"
+msgstr "Renombrar variable"
#: editor/filesystem_dock.cpp
-msgid "No files selected!"
-msgstr "¡No has seleccionado ningún archivo!"
+#, fuzzy
+msgid "Renaming folder:"
+msgstr "Renombrar nodo"
#: editor/filesystem_dock.cpp
#, fuzzy
@@ -2649,43 +2613,42 @@ msgstr "Expandir al padre"
#: editor/filesystem_dock.cpp
msgid "Collapse all"
-msgstr ""
-
-#: editor/filesystem_dock.cpp
-msgid "Show In File Manager"
-msgstr "Mostrar en el navegador de archivos"
+msgstr "Colapsar todo"
#: editor/filesystem_dock.cpp
-msgid "Instance"
-msgstr "Instanciar"
+msgid "Copy Path"
+msgstr "Copiar ruta"
#: editor/filesystem_dock.cpp
-msgid "Edit Dependencies.."
-msgstr "Editar dependencias…"
+#, fuzzy
+msgid "Rename.."
+msgstr "Renombrar"
#: editor/filesystem_dock.cpp
-msgid "View Owners.."
-msgstr "Ver dueños…"
+msgid "Move To.."
+msgstr "Mover a.."
#: editor/filesystem_dock.cpp
-msgid "Copy Path"
-msgstr "Copiar ruta"
+#, fuzzy
+msgid "New Folder.."
+msgstr "Crear carpeta"
#: editor/filesystem_dock.cpp
-msgid "Rename or Move.."
-msgstr "Renombrar o mover…"
+msgid "Show In File Manager"
+msgstr "Mostrar en el navegador de archivos"
#: editor/filesystem_dock.cpp
-msgid "Move To.."
-msgstr "Mover a…"
+msgid "Instance"
+msgstr "Instanciar"
#: editor/filesystem_dock.cpp
-msgid "Info"
-msgstr "Info"
+msgid "Edit Dependencies.."
+msgstr "Editar dependencias.."
#: editor/filesystem_dock.cpp
-msgid "Re-Import.."
-msgstr "Reimportando…"
+#, fuzzy
+msgid "View Owners.."
+msgstr "Ver propietarios.."
#: editor/filesystem_dock.cpp
msgid "Previous Directory"
@@ -2713,11 +2676,18 @@ msgid ""
"Scanning Files,\n"
"Please Wait.."
msgstr ""
+"Escaneando archivos,\n"
+"Por favor, espere..."
#: editor/filesystem_dock.cpp
msgid "Move"
msgstr "Mover"
+#: editor/filesystem_dock.cpp editor/plugins/animation_tree_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Rename"
+msgstr "Renombrar"
+
#: editor/groups_editor.cpp
msgid "Add to Group"
msgstr "Añadir al grupo"
@@ -2732,16 +2702,37 @@ msgid "Import as Single Scene"
msgstr "Importando escena…"
#: editor/import/resource_importer_scene.cpp
+#, fuzzy
+msgid "Import with Separate Animations"
+msgstr "Importar con materiales separados"
+
+#: editor/import/resource_importer_scene.cpp
msgid "Import with Separate Materials"
-msgstr ""
+msgstr "Importar con materiales separados"
#: editor/import/resource_importer_scene.cpp
msgid "Import with Separate Objects"
-msgstr ""
+msgstr "Importar con objetos separados"
#: editor/import/resource_importer_scene.cpp
+#, fuzzy
msgid "Import with Separate Objects+Materials"
-msgstr ""
+msgstr "Importar con objetos y materiales separados"
+
+#: editor/import/resource_importer_scene.cpp
+#, fuzzy
+msgid "Import with Separate Objects+Animations"
+msgstr "Importar con objetos y materiales separados"
+
+#: editor/import/resource_importer_scene.cpp
+#, fuzzy
+msgid "Import with Separate Materials+Animations"
+msgstr "Importar con materiales separados"
+
+#: editor/import/resource_importer_scene.cpp
+#, fuzzy
+msgid "Import with Separate Objects+Materials+Animations"
+msgstr "Importar con objetos y materiales separados"
#: editor/import/resource_importer_scene.cpp
#, fuzzy
@@ -2750,52 +2741,45 @@ msgstr "Importar escena 3D"
#: editor/import/resource_importer_scene.cpp
msgid "Import as Multiple Scenes+Materials"
-msgstr ""
+msgstr "Importar como escenas y materiales múltiples"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Import Scene"
msgstr "Importar escena"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Importing Scene.."
-msgstr "Importando escena…"
+msgstr "Importando escena.."
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Running Custom Script.."
-msgstr "Ejecutando script personalizado…"
+msgstr "Ejecutando script personalizado.."
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Couldn't load post-import script:"
msgstr "No se pudo cargar el script posimportación:"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Invalid/broken script for post-import (check console):"
msgstr ""
"El script de posimportación no es correcto o está roto. (revisa la consola):"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Error running post-import script:"
msgstr "Error ejecutando el script de posimportacion:"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Saving.."
-msgstr "Guardando…"
+msgstr "Guardando.."
#: editor/import_dock.cpp
msgid "Set as Default for '%s'"
-msgstr ""
+msgstr "Configurar por defecto para '%s'"
#: editor/import_dock.cpp
msgid "Clear Default for '%s'"
-msgstr ""
+msgstr "Borrar por defecto para '%s'"
#: editor/import_dock.cpp
#, fuzzy
@@ -2809,598 +2793,67 @@ msgstr "Importar"
#: editor/import_dock.cpp editor/property_editor.cpp
msgid "Preset.."
-msgstr "Ajuste…"
+msgstr "Ajuste.."
#: editor/import_dock.cpp
#, fuzzy
msgid "Reimport"
msgstr "Reimportar"
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "No bit masks to import!"
-msgstr "¡Sin máscaras de bits para importar!"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path is empty."
-msgstr "La ruta de destino está vacía."
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must be a complete resource path."
-msgstr "La ruta de destino debe ser una ruta de recursos completa."
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must exist."
-msgstr "La ruta de destino debe existir."
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Save path is empty!"
-msgstr "La ruta de guardado esta vacía!"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Import BitMasks"
-msgstr "Importar BitMasks"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s):"
-msgstr "Texturas de origen:"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Target Path:"
-msgstr "Ruta de destino:"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Accept"
-msgstr "Aceptar"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Bit Mask"
-msgstr "Máscara de bits"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No source font file!"
-msgstr "¡No se ha elegido ningún archivo de tipografías!"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No target font resource!"
-msgstr "¡No se ha elegido ningún recurso de tipografías!"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#, fuzzy
-msgid ""
-"Invalid file extension.\n"
-"Please use .font."
-msgstr ""
-"La extensión del archivo no es correcta.\n"
-"Prueba con la extensión .fnt."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Can't load/process source font."
-msgstr "No se puede cargar/procesar la tipografía elegida."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Couldn't save font."
-msgstr "No se pudo guardar la tipografía."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font:"
-msgstr "Tipografía elegida:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font Size:"
-msgstr "Tamaño de la tipografía elegida:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Dest Resource:"
-msgstr "Recurso de destino:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "The quick brown fox jumps over the lazy dog."
-msgstr "El veloz murciélago hindú comía feliz cardillo y kiwi."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Test:"
-msgstr "Prueba:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Options:"
-msgstr "Opciones:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Font Import"
-msgstr "Importar tipografías"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"This file is already a Godot font file, please supply a BMFont type file "
-"instead."
-msgstr ""
-"Este archivo ya es un archivo de tipografías de Godot, tienes que utilizar "
-"un archivo de tipo BMFont."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Failed opening as BMFont file."
-msgstr "Error al abrir como archivo BMFont."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error initializing FreeType."
-msgstr "Error al arrancar FreeType."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Unknown font format."
-msgstr "Formato de tipografía desconocido."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error loading font."
-msgstr "Error al cargar la tipografía."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Invalid font size."
-msgstr "Tamaño de tipografía incorrecto."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Invalid font custom source."
-msgstr "El origen personalizado de tipografía no es correcto."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/plugins/theme_editor_plugin.cpp
-msgid "Font"
-msgstr "Tipografía"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "No meshes to import!"
-msgstr "¡No hay ningún modelo que se pueda importar!"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Single Mesh Import"
-msgstr "Importar modelo individual"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Source Mesh(es):"
-msgstr "Modelo/s elegidos:"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/plugins/mesh_instance_editor_plugin.cpp
-msgid "Mesh"
-msgstr "Modelos 3D"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Surface %d"
-msgstr "Superficie %d"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "No samples to import!"
-msgstr "¡No hay ningún sonido a importar!"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Import Audio Samples"
-msgstr "Importar archivo de sonido"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Source Sample(s):"
-msgstr "Muestra(s) de Origen:"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Audio Sample"
-msgstr "Archivo de sonido"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "New Clip"
-msgstr "Nuevo clip"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Animation Options"
-msgstr "Opciones de Animación"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Flags"
-msgstr "Identificadores"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Bake FPS:"
-msgstr "Hacer Bake de FPS:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Optimizer"
-msgstr "Optimizar"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Linear Error"
-msgstr "Error lineal máximo"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angular Error"
-msgstr "Error angular máximo"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angle"
-msgstr "Ãngulo máximo"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Clips"
-msgstr "Clips"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Start(s)"
-msgstr "Inicios"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "End(s)"
-msgstr "Finales"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Loop"
-msgstr "Repetir"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Filters"
-msgstr "Filtros"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source path is empty."
-msgstr "La ruta de origen esta vacía."
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't load post-import script."
-msgstr "No se pudo cargar el script post-importación."
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Invalid/broken script for post-import."
-msgstr "El script de postimportación no es correcto o está roto."
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Error importing scene."
-msgstr "Error al importar escena."
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import 3D Scene"
-msgstr "Importar escena 3D"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source Scene:"
-msgstr "Escena de origen:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Same as Target Scene"
-msgstr "Igual que escena de destino"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Shared"
-msgstr "Compartido"
+#: editor/multi_node_edit.cpp
+msgid "MultiNode Set"
+msgstr "Establecer multinodo"
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Target Texture Folder:"
-msgstr "Carpeta de texturas elegida:"
+#: editor/node_dock.cpp
+msgid "Groups"
+msgstr "Grupos"
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Post-Process Script:"
-msgstr "Script de posprocesado:"
+#: editor/node_dock.cpp
+msgid "Select a Node to edit Signals and Groups."
+msgstr "Selecciona un nodo para editar señales y grupos."
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Custom Root Node Type:"
-msgstr "Tipo de Nodo Raiz Customizado:"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create Poly"
+msgstr "Crear polígono"
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Auto"
-msgstr "Auto"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly"
+msgstr "Editar polígono"
-#: editor/io_plugins/editor_scene_import_plugin.cpp
+#: editor/plugins/abstract_polygon_2d_editor.cpp
#, fuzzy
-msgid "Root Node Name:"
-msgstr "Nombre del nodo:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "The Following Files are Missing:"
-msgstr "Faltan los siguientes archivos:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Anyway"
-msgstr "Importar de todos modos"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp scene/gui/dialogs.cpp
-msgid "Cancel"
-msgstr "Cancelar"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import & Open"
-msgstr "Importar y abrir"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Edited scene has not been saved, open imported scene anyway?"
-msgstr ""
-"La escena editada no se ha guardado, ¿Quieres abrir la escena importada de "
-"todos modos?"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Image:"
-msgstr "Importar imagen:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Can't import a file over itself:"
-msgstr "No se puede importar un archivo sobre si mismo:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't localize path: %s (already local)"
-msgstr "No se pudo encontrar la ruta: %s (ya es local)"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "3D Scene Animation"
-msgstr "Animación de escena 3D"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Uncompressed"
-msgstr "Sin comprimir"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossless (PNG)"
-msgstr "Compresión sin pérdidas (PNG)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossy (WebP)"
-msgstr "Compresión con pérdidas (WebP)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress (VRAM)"
-msgstr "Comprimir (VRAM)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Format"
-msgstr "Formato de textura"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Compression Quality (WebP):"
-msgstr "Calidad de compresión de textura (WebP):"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Options"
-msgstr "Opciones de textura"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Please specify some files!"
-msgstr "¡Selecciona algunos archivos!"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "At least one file needed for Atlas."
-msgstr "Se necesita al menos un archivo para el atlas."
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Error importing:"
-msgstr "Hubo un error al importar:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Only one file is required for large texture."
-msgstr "Solo se requiere un archivo para textura grande."
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Max Texture Size:"
-msgstr "Tamaño máximo de textura:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for Atlas (2D)"
-msgstr "Importar texturas para atlas (2D)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cell Size:"
-msgstr "Tamaño de celda:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Large Texture"
-msgstr "Textura grande"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Textures (2D)"
-msgstr "Importar texturas grandes (2D)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture"
-msgstr "Textura de origen"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Base Atlas Texture"
-msgstr "Textura base de atlas"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s)"
-msgstr "Texturas de origen"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 2D"
-msgstr "Importar texturas para 2D"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 3D"
-msgstr "Importar texturas para 3D"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures"
-msgstr "Importar texturas"
+msgid "Insert Point"
+msgstr "Insertando"
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "2D Texture"
-msgstr "Textura 2D"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly (Remove Point)"
+msgstr "Editar polígono (quitar punto)"
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "3D Texture"
-msgstr "Textura 3D"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Remove Poly And Point"
+msgstr "Quitar polígono y punto"
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Atlas Texture"
-msgstr "Textura de atlas"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create a new polygon from scratch."
+msgstr "Crea un nuevo polígono desde cero."
-#: editor/io_plugins/editor_texture_import_plugin.cpp
+#: editor/plugins/abstract_polygon_2d_editor.cpp
msgid ""
-"NOTICE: Importing 2D textures is not mandatory. Just copy png/jpg files to "
-"the project."
+"Edit existing polygon:\n"
+"LMB: Move Point.\n"
+"Ctrl+LMB: Split Segment.\n"
+"RMB: Erase Point."
msgstr ""
-"AVISO: No es necesario importar texturas 2D. Limítate a copia los archivos "
-"png/jpg al proyecto."
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Crop empty space."
-msgstr "Recortar espacio vacío."
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture"
-msgstr "Textura"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Texture"
-msgstr "Importar textura grande"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Load Source Image"
-msgstr "Cargar imagen de origen"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Slicing"
-msgstr "Troceando"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Inserting"
-msgstr "Insertando"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Saving"
-msgstr "Guardando"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save large texture:"
-msgstr "No se pudo guardar la textura grande:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Build Atlas For:"
-msgstr "Construir atlas para:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Loading Image:"
-msgstr "Cargando imagen:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't load image:"
-msgstr "No se pudo cargar la imagen:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Converting Images"
-msgstr "Convirtiendo imágenes"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cropping Images"
-msgstr "Recortando imágenes"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Blitting Images"
-msgstr "Copiando datos de imágenes"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save atlas image:"
-msgstr "No se pudo guardar la imagen de atlas:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save converted texture:"
-msgstr "No se pudo guardar la textura convertida:"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid source!"
-msgstr "¡Origen incorrecto!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid translation source!"
-msgstr "¡Origen de traducción incorrecto!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Column"
-msgstr "Columna"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/script_create_dialog.cpp
-msgid "Language"
-msgstr "Idioma"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No items to import!"
-msgstr "Sin elementos para importar!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No target path!"
-msgstr "¡El objetivo no tiene ruta!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translations"
-msgstr "Importar traducciones"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Couldn't import!"
-msgstr "¡No se pudo importar!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translation"
-msgstr "Importar traducción"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Source CSV:"
-msgstr "CSV de origen:"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Ignore First Row"
-msgstr "Ignorar Primera Columna"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Compress"
-msgstr "Comprimir"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#, fuzzy
-msgid "Add to Project (project.godot)"
-msgstr "Añadir al proyecto (engine.cfg)"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Languages:"
-msgstr "Importar idiomas:"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Translation"
-msgstr "Traducción"
-
-#: editor/multi_node_edit.cpp
-msgid "MultiNode Set"
-msgstr "Establecer multinodo"
-
-#: editor/node_dock.cpp
-msgid "Groups"
-msgstr "Grupos"
-
-#: editor/node_dock.cpp
-msgid "Select a Node to edit Signals and Groups."
-msgstr "Selecciona un nodo para editar señales y grupos."
+"Editar polígono existente:\n"
+"Click izquierdo: Mover punto.\n"
+"Control + Click izquierdo: Dividir segmento.\n"
+"Click derecho: Borrar punto."
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Toggle Autoplay"
@@ -3558,7 +3011,6 @@ msgstr "Nombre de Animación:"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
#: editor/script_create_dialog.cpp
msgid "Error!"
@@ -3669,10 +3121,6 @@ msgid "Delete Input"
msgstr "Eliminar entrada"
#: editor/plugins/animation_tree_editor_plugin.cpp
-msgid "Rename"
-msgstr "Renombrar"
-
-#: editor/plugins/animation_tree_editor_plugin.cpp
msgid "Animation tree is valid."
msgstr "El árbol de animación es correcto."
@@ -3718,7 +3166,7 @@ msgstr "Nodo de transición"
#: editor/plugins/animation_tree_editor_plugin.cpp
msgid "Import Animations.."
-msgstr "Importar animaciones…"
+msgstr "Importar animaciones.."
#: editor/plugins/animation_tree_editor_plugin.cpp
msgid "Edit Node Filters"
@@ -3726,68 +3174,187 @@ msgstr "Editar filtros de nodo"
#: editor/plugins/animation_tree_editor_plugin.cpp
msgid "Filters.."
-msgstr "Filtros…"
+msgstr "Filtros.."
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing %d Triangles:"
-msgstr "Leyendo %d triángulos:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Free"
+msgstr "Libre"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Triangle #"
-msgstr "Nº de triángulos"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Contents:"
+msgstr "Contenido:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Light Baker Setup:"
-msgstr "Configuración de Baker de Luces:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "View Files"
+msgstr "Ver Archivos"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing Geometry"
-msgstr "Leyendo geometría"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve hostname:"
+msgstr "No se ha podido resolver el nombre de Dominio:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Fixing Lights"
-msgstr "Procesando luces"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve."
+msgstr "No se ha podido resolver."
-#: editor/plugins/baked_light_baker.cpp
-msgid "Making BVH"
-msgstr "Creando BVH"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connection error, please try again."
+msgstr "Error de conexion, por favor intente otra vez."
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Light Octree"
-msgstr "Creando octree de luces"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't connect."
+msgstr "No se puede conectar."
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Octree Texture"
-msgstr "Creando octree de texturas"
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Can't connect to host:"
+msgstr "No se puede conectar al host:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Transfer to Lightmaps:"
-msgstr "Transfiriendo a «lightmaps»:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response from host:"
+msgstr "No hay respuesta desde el host:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Allocating Texture #"
-msgstr "Asignando nº de textura"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response."
+msgstr "No responde."
-#: editor/plugins/baked_light_baker.cpp
-msgid "Baking Triangle #"
-msgstr "Quemando nº de triángulo"
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Request failed, return code:"
+msgstr "Petición falida, código de retorno:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Post-Processing Texture #"
-msgstr "Posprocesando nº de textura"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Req. Failed."
+msgstr "Solicitud fallida."
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Bake!"
-msgstr "¡Quemar!"
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Request failed, too many redirects"
+msgstr "Petición fallida, demasiadas redirecciones"
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Reset the lightmap octree baking process (start over)."
-msgstr ""
-"Restablece el proceso de «bake» del «octree» del «lightmap» (empezar de "
-"nuevo)."
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Redirect Loop."
+msgstr "Bucle de redireccionamiento."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed:"
+msgstr "Fallido:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Bad download hash, assuming file has been tampered with."
+msgstr "Error de descarga, al pareser el archivo ha sido manipulado."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Expected:"
+msgstr "Esperado:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Got:"
+msgstr "Tiene:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed sha256 hash check"
+msgstr "Fallo en la comprobación del hash sha256"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Asset Download Error:"
+msgstr "Error en la descarga del asset:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Fetching:"
+msgstr "Buscando:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Resolving.."
+msgstr "Guardando…"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connecting.."
+msgstr "Conectando.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Requesting.."
+msgstr "Solicitando.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Error making request"
+msgstr "Error al realizar la solicitud"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Idle"
+msgstr "Inactivo"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Retry"
+msgstr "Reintente"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download Error"
+msgstr "Error de Descarga"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download for this asset is already in progress!"
+msgstr "Este asset ya esta descargandose!"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "first"
+msgstr "primero"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "prev"
+msgstr "anterior"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "next"
+msgstr "siguiente"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "last"
+msgstr "ultimo"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "All"
+msgstr "Todos"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Plugins"
+msgstr "Plugins"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Sort:"
+msgstr "Ordenar:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Reverse"
+msgstr "Invertir"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Category:"
+msgstr "Categoría:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Site:"
+msgstr "Sitio:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Support.."
+msgstr "Soporte.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Official"
+msgstr "Oficial"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Testing"
+msgstr "Prueba"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Assets ZIP File"
+msgstr "Archivo ZIP de elementos"
#: editor/plugins/camera_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
msgid "Preview"
msgstr "Vista previa"
@@ -3830,12 +3397,18 @@ msgid "Edit CanvasItem"
msgstr "Editar CanvasItem"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Change Anchors"
+#, fuzzy
+msgid "Anchors only"
+msgstr "Ancla"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#, fuzzy
+msgid "Change Anchors and Margins"
msgstr "Cambiar anclas"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom (%):"
-msgstr "Zoom (%):"
+msgid "Change Anchors"
+msgstr "Cambiar anclas"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Paste Pose"
@@ -3889,60 +3462,78 @@ msgid "Pan Mode"
msgstr "Modo desplazamiento lateral"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Lock the selected object in place (can't be moved)."
-msgstr "Inmovilizar el objeto."
+#, fuzzy
+msgid "Toggles snapping"
+msgstr "Des/activar «breakpoint»"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Unlock the selected object (can be moved)."
-msgstr "Liberar el objeto."
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Use Snap"
+msgstr "Fijar a cuadrícula"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Makes sure the object's children are not selectable."
-msgstr "Asegurarse que los hijos de un objeto no sean seleccionables."
+#, fuzzy
+msgid "Snapping options"
+msgstr "Opciones de Animación"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Restores the object's children's ability to be selected."
-msgstr "Restaurar la habilidad de seleccionar los hijos de un objeto."
+#, fuzzy
+msgid "Snap to grid"
+msgstr "Modo de fijado:"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Edit"
-msgstr "Editar"
+msgid "Use Rotation Snap"
+msgstr "Fijar rotación"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Use Snap"
-msgstr "Fijar a cuadrícula"
+#, fuzzy
+msgid "Configure Snap..."
+msgstr "Configurar fijado.."
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Show Grid"
-msgstr "Mostrar rejilla"
+msgid "Snap Relative"
+msgstr "Fijado relativo"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Rotation Snap"
-msgstr "Fijar rotación"
+msgid "Use Pixel Snap"
+msgstr "Adherir a píxeles"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap Relative"
-msgstr "Fijado relativo"
+msgid "Smart snapping"
+msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Configure Snap.."
-msgstr "Configurar fijado…"
+#, fuzzy
+msgid "Snap to parent"
+msgstr "Expandir al padre"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Pixel Snap"
-msgstr "Adherir a píxeles"
+msgid "Snap to node anchor"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to node sides"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to other nodes"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Lock the selected object in place (can't be moved)."
+msgstr "Inmovilizar el objeto."
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Unlock the selected object (can be moved)."
+msgstr "Liberar el objeto."
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Skeleton.."
-msgstr "Esqueleto…"
+msgid "Makes sure the object's children are not selectable."
+msgstr "Asegurarse que los hijos de un objeto no sean seleccionables."
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Restores the object's children's ability to be selected."
+msgstr "Restaurar la habilidad de seleccionar los hijos de un objeto."
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Make Bones"
@@ -3971,12 +3562,19 @@ msgid "View"
msgstr "Ver"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Reset"
-msgstr "Restablecer zoom"
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Show Grid"
+msgstr "Mostrar rejilla"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Set.."
-msgstr "Ajustar zoom…"
+#, fuzzy
+msgid "Show helpers"
+msgstr "Crear huesos"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#, fuzzy
+msgid "Show rulers"
+msgstr "Crear huesos"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Center Selection"
@@ -3987,8 +3585,9 @@ msgid "Frame Selection"
msgstr "Encuadrar selección"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Anchor"
-msgstr "Ancla"
+#, fuzzy
+msgid "Layout"
+msgstr "Guardar ajustes"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Insert Keys"
@@ -4011,12 +3610,21 @@ msgid "Clear Pose"
msgstr "Restablecer pose"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Set a Value"
-msgstr "Establecer valor"
+msgid "Drag pivot from mouse position"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#, fuzzy
+msgid "Set pivot at mouse position"
+msgstr "Establecer pos. de salida de curva"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Multiply grid step by 2"
+msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap (Pixels):"
-msgstr "Fijar (Pixeles):"
+msgid "Divide grid step by 2"
+msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
#, fuzzy
@@ -4028,23 +3636,28 @@ msgstr "Añadir todos"
msgid "Adding %s..."
msgstr "Añadiendo %s..."
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Create Node"
msgstr "Crear nodo"
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Error instancing scene from %s"
msgstr "Error al instanciar escena desde %s"
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "OK :("
msgstr "Muy bien :("
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "No parent to instance a child at."
msgstr "No hay padre al que instanciarle un hijo."
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "This operation requires a single selected node."
msgstr "Esta operación requiere un solo nodo seleccionado."
@@ -4062,45 +3675,6 @@ msgstr ""
"Arrastrar y soltar + Mayús: Añadir nodo como hermano\n"
"Arrastrar y soltar + Alt: Cambiar tipo de nodo"
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Create Poly"
-msgstr "Crear polígono"
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly"
-msgstr "Editar polígono"
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly (Remove Point)"
-msgstr "Editar polígono (quitar punto)"
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Create a new polygon from scratch."
-msgstr "Crea un nuevo polígono desde cero."
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-msgid ""
-"Edit existing polygon:\n"
-"LMB: Move Point.\n"
-"Ctrl+LMB: Split Segment.\n"
-"RMB: Erase Point."
-msgstr ""
-
#: editor/plugins/collision_polygon_editor_plugin.cpp
msgid "Create Poly3D"
msgstr "Crear Poly3D"
@@ -4110,14 +3684,6 @@ msgid "Set Handle"
msgstr "Establecer handle"
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Creating Mesh Library"
-msgstr "Crear biblioteca de modelos 3D"
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Thumbnail.."
-msgstr "Miniatura…"
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Remove item %d?"
msgstr "¿Quieres borrar el elemento %d?"
@@ -4140,6 +3706,28 @@ msgid "Update from Scene"
msgstr "Actualizar desde escena"
#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat0"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat1"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+#, fuzzy
+msgid "Ease in"
+msgstr "Transición entrada"
+
+#: editor/plugins/curve_editor_plugin.cpp
+#, fuzzy
+msgid "Ease out"
+msgstr "Transición salida"
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Smoothstep"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
#, fuzzy
msgid "Modify Curve Point"
msgstr "Modificar Mapa de Curvas"
@@ -4185,12 +3773,13 @@ msgid "Remove Curve Point"
msgstr "Quitar Punto de ruta"
#: editor/plugins/curve_editor_plugin.cpp
+#, fuzzy
msgid "Toggle Curve Linear Tangent"
-msgstr ""
+msgstr "Cambiar tangente de curva lineal"
#: editor/plugins/curve_editor_plugin.cpp
msgid "Hold Shift to edit tangents individually"
-msgstr ""
+msgstr "Mantén Mayus para editar las tangentes individualmente"
#: editor/plugins/gradient_editor_plugin.cpp
#, fuzzy
@@ -4219,28 +3808,26 @@ msgid ""
"No OccluderPolygon2D resource on this node.\n"
"Create and assign one?"
msgstr ""
+"No se ha encontrado el recurso OccluderPolygon2D en este nodo.\n"
+"¿Crear uno y asignarlo?"
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
msgid "Create Occluder Polygon"
msgstr "Crear polígono oclusor"
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Edit existing polygon:"
msgstr "Editar polígono existente:"
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "LMB: Move Point."
msgstr "Clic izquierdo: Mover punto."
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Ctrl+LMB: Split Segment."
msgstr "Ctrl + LMB: Partir segmento."
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "RMB: Erase Point."
msgstr "Clic derecho: Borrar punto."
@@ -4346,6 +3933,10 @@ msgid "Create Outline"
msgstr "Crear contorno"
#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Mesh"
+msgstr "Modelos 3D"
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Create Trimesh Static Body"
msgstr "Crear colisión estática triangular"
@@ -4363,7 +3954,7 @@ msgstr "Crear colisión hermanada convexa"
#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Create Outline Mesh.."
-msgstr "Crear modelo 3D de contorno…"
+msgstr "Crear modelo 3D de contorno.."
#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Create Outline Mesh"
@@ -4477,14 +4068,83 @@ msgstr "Escala al azar:"
msgid "Populate"
msgstr "Rellenar"
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake!"
+msgstr "¡Quemar!"
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+#, fuzzy
+msgid "Bake the navigation mesh.\n"
+msgstr "Crear modelo de navegación 3D"
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+#, fuzzy
+msgid "Clear the navigation mesh."
+msgstr "Crear modelo de navegación 3D"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Setting up Configuration..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Calculating grid size..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Creating heightfield..."
+msgstr "Creando octree de luces"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Marking walkable triangles..."
+msgstr "Cadenas traducibles…"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Constructing compact heightfield..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Eroding walkable area..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Partitioning..."
+msgstr "Advertencia"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Creating contours..."
+msgstr "Creando octree de texturas"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Creating polymesh..."
+msgstr "Crear modelo 3D de contorno.."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Converting to native navigation mesh..."
+msgstr "Crear modelo de navegación 3D"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Navigation Mesh Generator Setup:"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Parsing Geometry..."
+msgstr "Leyendo geometría"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Done!"
+msgstr ""
+
#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Create Navigation Polygon"
msgstr "Crear polígono de navegación"
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Remove Poly And Point"
-msgstr "Quitar polígono y punto"
-
#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Clear Emission Mask"
msgstr "Borrar máscara de emisión"
@@ -4496,17 +4156,20 @@ msgid "Generating AABB"
msgstr "Generar AABB"
#: editor/plugins/particles_2d_editor_plugin.cpp
+#, fuzzy
msgid "Can only set point into a ParticlesMaterial process material"
msgstr ""
+"Solo se puede asignar el punto a un material procesado del tipo "
+"ParticlesMaterial."
#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Error loading image:"
msgstr "Error al cargar la imagen:"
#: editor/plugins/particles_2d_editor_plugin.cpp
+#, fuzzy
msgid "No pixels with transparency > 128 in image.."
-msgstr ""
-"No hay píxeles que tengan menos de un 128/255 de transparencia en la imagen…"
+msgstr "No hay píxeles con una transparencia mayor que 128 en la imagen.."
#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Set Emission Mask"
@@ -4514,7 +4177,7 @@ msgstr "Establecer máscara de emisión"
#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Generate Visibility Rect"
-msgstr ""
+msgstr "Generar rectángulo de visibilidad"
#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Load Emission Mask"
@@ -4561,7 +4224,7 @@ msgstr "El nodo no contiene geometría (caras)."
#: editor/plugins/particles_editor_plugin.cpp
msgid "A processor material of type 'ParticlesMaterial' is required."
-msgstr ""
+msgstr "Se requiere un material procesador del tipo 'ParticlesMaterial'."
#: editor/plugins/particles_editor_plugin.cpp
msgid "Faces contain no area!"
@@ -4604,8 +4267,9 @@ msgid "Surface Points"
msgstr "Superficie %d"
#: editor/plugins/particles_editor_plugin.cpp
+#, fuzzy
msgid "Surface Points+Normal (Directed)"
-msgstr ""
+msgstr "Puntos de superficio + Normal (Dirigida)"
#: editor/plugins/particles_editor_plugin.cpp
msgid "Volume"
@@ -4672,14 +4336,17 @@ msgid "Curve Point #"
msgstr "Nº de punto en curva"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve Point Position"
msgstr "Establecer pos. de punto de curva"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve In Position"
msgstr "Establecer pos. de entrada de curva"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve Out Position"
msgstr "Establecer pos. de salida de curva"
@@ -4742,6 +4409,14 @@ msgid "Scale Polygon"
msgstr "Escalar polígono"
#: editor/plugins/polygon_2d_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Edit"
+msgstr "Editar"
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Polygon->UV"
msgstr "Polígono->UV"
@@ -4796,63 +4471,10 @@ msgstr "Cargar recurso"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/shader_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "Pegar"
-#: editor/plugins/rich_text_editor_plugin.cpp
-msgid "Parse BBCode"
-msgstr "Leer BBCode"
-
-#: editor/plugins/sample_editor_plugin.cpp
-msgid "Length:"
-msgstr "Duración:"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Open Sample File(s)"
-msgstr "Abrir archivos de sonido"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "ERROR: Couldn't load sample!"
-msgstr "¡ERROR: No se pudo cargar el archivo de sonido!"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Add Sample"
-msgstr "Añadir archivo de sonido"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Rename Sample"
-msgstr "Renombrar archivo de sonido"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Delete Sample"
-msgstr "Eliminar archivo de sonido"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "16 Bits"
-msgstr "16 bits"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "8 Bits"
-msgstr "8 bits"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Stereo"
-msgstr "Estéreo"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Mono"
-msgstr "Mono"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Format"
-msgstr "Formato"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Pitch"
-msgstr "Altura"
-
#: editor/plugins/script_editor_plugin.cpp
#, fuzzy
msgid "Clear Recent Files"
@@ -4863,6 +4485,8 @@ msgid ""
"Close and save changes?\n"
"\""
msgstr ""
+"¿Cerrar y guardar cambios?\n"
+"\""
#: editor/plugins/script_editor_plugin.cpp
msgid "Error while saving theme"
@@ -4886,11 +4510,11 @@ msgstr "Importar tema"
#: editor/plugins/script_editor_plugin.cpp
msgid "Save Theme As.."
-msgstr "Guardar tema como…"
+msgstr "Guardar tema como.."
#: editor/plugins/script_editor_plugin.cpp
msgid " Class Reference"
-msgstr ""
+msgstr " Referencia de clase"
#: editor/plugins/script_editor_plugin.cpp
msgid "Next script"
@@ -4945,6 +4569,10 @@ msgstr "Cerrar documentación"
msgid "Close All"
msgstr "Cerrar"
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+msgid "Run"
+msgstr "Ejecutar"
+
#: editor/plugins/script_editor_plugin.cpp
#, fuzzy
msgid "Toggle Scripts Panel"
@@ -4954,7 +4582,7 @@ msgstr "Añadir/quitar favorito"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Find.."
-msgstr "Buscar…"
+msgstr "Buscar.."
#: editor/plugins/script_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
@@ -4974,7 +4602,8 @@ msgstr "Step Into"
msgid "Break"
msgstr "Break"
-#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+#: editor/script_editor_debugger.cpp
msgid "Continue"
msgstr "Continuar"
@@ -4988,18 +4617,6 @@ msgid "Debug with external editor"
msgstr "Abrir en el editor"
#: editor/plugins/script_editor_plugin.cpp
-msgid "Window"
-msgstr "Ventana"
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Left"
-msgstr "Mover a la izquierda"
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Right"
-msgstr "Mover a la derecha"
-
-#: editor/plugins/script_editor_plugin.cpp
#, fuzzy
msgid "Open Godot online documentation"
msgstr "Buscar en la documentación de referencia."
@@ -5057,8 +4674,9 @@ msgstr ""
"pertenecen está cargada"
#: editor/plugins/script_text_editor.cpp
+#, fuzzy
msgid "Only resources from filesystem can be dropped."
-msgstr ""
+msgstr "Solo se pueden soltar recursos del sistema."
#: editor/plugins/script_text_editor.cpp
#, fuzzy
@@ -5072,15 +4690,15 @@ msgstr "Convirtiendo imágenes"
#: editor/plugins/script_text_editor.cpp
msgid "Uppercase"
-msgstr ""
+msgstr "Mayúscula"
#: editor/plugins/script_text_editor.cpp
msgid "Lowercase"
-msgstr ""
+msgstr "Minúscula"
#: editor/plugins/script_text_editor.cpp
msgid "Capitalize"
-msgstr ""
+msgstr "Insertar mayúsculas"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/shader_editor_plugin.cpp scene/gui/line_edit.cpp
@@ -5089,8 +4707,9 @@ msgid "Cut"
msgstr "Cortar"
#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "Copiar"
@@ -5139,11 +4758,12 @@ msgstr "Borrar espacios sobrantes al final"
#: editor/plugins/script_text_editor.cpp
msgid "Convert Indent To Spaces"
-msgstr ""
+msgstr "Convertir Indentación a Espacios"
#: editor/plugins/script_text_editor.cpp
+#, fuzzy
msgid "Convert Indent To Tabs"
-msgstr ""
+msgstr "Convertir Indentación a Tabuladores"
#: editor/plugins/script_text_editor.cpp
msgid "Auto Indent"
@@ -5184,16 +4804,16 @@ msgstr "Buscar anterior"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Replace.."
-msgstr "Reemplazar…"
+msgstr "Reemplazar.."
#: editor/plugins/script_text_editor.cpp
msgid "Goto Function.."
-msgstr "Ir a función…"
+msgstr "Ir a función.."
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Goto Line.."
-msgstr "Ir a línea…"
+msgstr "Ir a línea.."
#: editor/plugins/script_text_editor.cpp
msgid "Contextual Help"
@@ -5201,7 +4821,7 @@ msgstr "Ayuda contextual"
#: editor/plugins/shader_editor_plugin.cpp
msgid "Shader"
-msgstr ""
+msgstr "Shader"
#: editor/plugins/shader_graph_editor_plugin.cpp
msgid "Change Scalar Constant"
@@ -5358,10 +4978,6 @@ msgid "View Plane Transform."
msgstr "Ver transformación en plano."
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Scaling to %s%%."
-msgstr "Escalando al %s%%."
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rotating %s degrees."
msgstr "Girando %s grados."
@@ -5378,10 +4994,6 @@ msgid "Top View."
msgstr "Vista superior."
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Top"
-msgstr "Cima"
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rear View."
msgstr "Vista anterior."
@@ -5422,8 +5034,9 @@ msgid "Animation Key Inserted."
msgstr "Clave de animación insertada."
#: editor/plugins/spatial_editor_plugin.cpp
+#, fuzzy
msgid "Objects Drawn"
-msgstr ""
+msgstr "Objetos dibujados"
#: editor/plugins/spatial_editor_plugin.cpp
#, fuzzy
@@ -5441,8 +5054,9 @@ msgid "Surface Changes"
msgstr "Actualizar cambios"
#: editor/plugins/spatial_editor_plugin.cpp
+#, fuzzy
msgid "Draw Calls"
-msgstr ""
+msgstr "Llamadas de dibujado"
#: editor/plugins/spatial_editor_plugin.cpp
#, fuzzy
@@ -5482,7 +5096,7 @@ msgstr "Gizmos"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "View Information"
-msgstr ""
+msgstr "Ver información"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Audio Listener"
@@ -5494,12 +5108,14 @@ msgid "Doppler Enable"
msgstr "Activar"
#: editor/plugins/spatial_editor_plugin.cpp
+#, fuzzy
msgid "Freelook Left"
-msgstr ""
+msgstr "Vista libre izquierda"
#: editor/plugins/spatial_editor_plugin.cpp
+#, fuzzy
msgid "Freelook Right"
-msgstr ""
+msgstr "Vista libre derecha"
#: editor/plugins/spatial_editor_plugin.cpp
#, fuzzy
@@ -5512,8 +5128,9 @@ msgid "Freelook Backwards"
msgstr "Hacia atrás"
#: editor/plugins/spatial_editor_plugin.cpp
+#, fuzzy
msgid "Freelook Up"
-msgstr ""
+msgstr "Vista libre superior"
#: editor/plugins/spatial_editor_plugin.cpp
#, fuzzy
@@ -5521,8 +5138,9 @@ msgid "Freelook Down"
msgstr "Rueda hacia abajo."
#: editor/plugins/spatial_editor_plugin.cpp
+#, fuzzy
msgid "Freelook Speed Modifier"
-msgstr ""
+msgstr "Modificador de velocidad de la vista libre"
#: editor/plugins/spatial_editor_plugin.cpp
#, fuzzy
@@ -5628,12 +5246,16 @@ msgid "Transform"
msgstr "Transformar"
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Configure Snap.."
+msgstr "Configurar fijado.."
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Local Coords"
msgstr "Coordenadas locales"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Transform Dialog.."
-msgstr "Ventana de transformación…"
+msgstr "Ventana de transformación.."
#: editor/plugins/spatial_editor_plugin.cpp
msgid "1 Viewport"
@@ -5773,6 +5395,10 @@ msgid "Speed (FPS):"
msgstr "Velocidad (FPS):"
#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Loop"
+msgstr "Repetir"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Animation Frames"
msgstr "Cuadros de animación"
@@ -5785,12 +5411,14 @@ msgid "Insert Empty (After)"
msgstr "Insertar vacío (después)"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Up"
-msgstr "Arriba"
+#, fuzzy
+msgid "Move (Before)"
+msgstr "Borrar nodos"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Down"
-msgstr "Abajo"
+#, fuzzy
+msgid "Move (After)"
+msgstr "Mover a la izquierda"
#: editor/plugins/style_box_editor_plugin.cpp
msgid "StyleBox Preview:"
@@ -5869,9 +5497,12 @@ msgid "Remove All"
msgstr "Quitar"
#: editor/plugins/theme_editor_plugin.cpp
-#, fuzzy
-msgid "Theme"
-msgstr "Guardar tema"
+msgid "Edit theme.."
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Theme editing menu."
+msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
msgid "Add Class Items"
@@ -5955,6 +5586,10 @@ msgid "Style"
msgstr "Estilo"
#: editor/plugins/theme_editor_plugin.cpp
+msgid "Font"
+msgstr "Tipografía"
+
+#: editor/plugins/theme_editor_plugin.cpp
msgid "Color"
msgstr "Color"
@@ -5973,8 +5608,9 @@ msgid "Line Draw"
msgstr "Lineal"
#: editor/plugins/tile_map_editor_plugin.cpp
+#, fuzzy
msgid "Rectangle Paint"
-msgstr ""
+msgstr "Rectángulo de pintura"
#: editor/plugins/tile_map_editor_plugin.cpp
#, fuzzy
@@ -6006,8 +5642,9 @@ msgid "Mirror Y"
msgstr "Voltear verticalmente"
#: editor/plugins/tile_map_editor_plugin.cpp
-msgid "Bucket"
-msgstr "Cubo"
+#, fuzzy
+msgid "Paint Tile"
+msgstr "Pintar TileMap"
#: editor/plugins/tile_map_editor_plugin.cpp
msgid "Pick Tile"
@@ -6074,12 +5711,17 @@ msgstr "¿Quieres eliminar los archivos seleccionados?"
#: editor/project_export.cpp
#, fuzzy
+msgid "Export templates for this platform are missing/corrupted: "
+msgstr "Faltan las siguientes plantillas de exportación para esta plataforma:"
+
+#: editor/project_export.cpp
+#, fuzzy
msgid "Presets"
msgstr "Ajuste…"
#: editor/project_export.cpp editor/project_settings_editor.cpp
msgid "Add.."
-msgstr "Añadir…"
+msgstr "Añadir.."
#: editor/project_export.cpp
msgid "Resources"
@@ -6141,8 +5783,9 @@ msgid "Features"
msgstr "Textura"
#: editor/project_export.cpp
+#, fuzzy
msgid "Custom (comma-separated):"
-msgstr ""
+msgstr "Personalizado (separado por comas):"
#: editor/project_export.cpp
#, fuzzy
@@ -6154,8 +5797,14 @@ msgid "Export PCK/Zip"
msgstr "Exportar PCK/Zip"
#: editor/project_export.cpp
+#, fuzzy
msgid "Export templates for this platform are missing:"
-msgstr ""
+msgstr "Faltan las siguientes plantillas de exportación para esta plataforma:"
+
+#: editor/project_export.cpp
+#, fuzzy
+msgid "Export templates for this platform are missing/corrupted:"
+msgstr "Faltan las siguientes plantillas de exportación para esta plataforma:"
#: editor/project_export.cpp
#, fuzzy
@@ -6163,29 +5812,53 @@ msgid "Export With Debug"
msgstr "Exportar Tile Set"
#: editor/project_manager.cpp
-msgid "Invalid project path, the path must exist!"
-msgstr "¡La ruta del proyecto no es correcta, tiene que existir!"
+#, fuzzy
+msgid "The path does not exist."
+msgstr "El archivo existe."
#: editor/project_manager.cpp
#, fuzzy
-msgid "Invalid project path, project.godot must not exist."
-msgstr "La ruta del proyecto no es correcta, engine.cfg no debe existir."
+msgid "Please choose a 'project.godot' file."
+msgstr "¡Prueba exportando fuera de la carpeta del proyecto!"
#: editor/project_manager.cpp
-#, fuzzy
-msgid "Invalid project path, project.godot must exist."
-msgstr "¡La ruta del proyecto no es correcta, engine.cfg debe existir."
+msgid ""
+"Your project will be created in a non empty folder (you might want to create "
+"a new folder)."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Please choose a folder that does not contain a 'project.godot' file."
+msgstr ""
#: editor/project_manager.cpp
msgid "Imported Project"
msgstr "Proyecto importado"
#: editor/project_manager.cpp
+msgid " "
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "It would be a good idea to name your project."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Invalid project path (changed anything?)."
msgstr "La ruta del proyecto no es correcta (¿has cambiado algo?)."
#: editor/project_manager.cpp
#, fuzzy
+msgid "Couldn't get project.godot in project path."
+msgstr "No se pudo crear engine.cfg en la ruta de proyecto."
+
+#: editor/project_manager.cpp
+#, fuzzy
+msgid "Couldn't edit project.godot in project path."
+msgstr "No se pudo crear engine.cfg en la ruta de proyecto."
+
+#: editor/project_manager.cpp
+#, fuzzy
msgid "Couldn't create project.godot in project path."
msgstr "No se pudo crear engine.cfg en la ruta de proyecto."
@@ -6194,38 +5867,49 @@ msgid "The following files failed extraction from package:"
msgstr "Los siguientes archivos no se pudieron extraer del paquete:"
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Rename Project"
+msgstr "Proyecto sin nombre"
+
+#: editor/project_manager.cpp
+#, fuzzy
+msgid "Couldn't get project.godot in the project path."
+msgstr "No se pudo crear engine.cfg en la ruta de proyecto."
+
+#: editor/project_manager.cpp
+msgid "New Game Project"
+msgstr "Nuevo proyecto de juego"
+
+#: editor/project_manager.cpp
msgid "Import Existing Project"
msgstr "Importar proyecto existente"
#: editor/project_manager.cpp
-msgid "Project Path (Must Exist):"
-msgstr "Ruta del proyecto (debe existir):"
+msgid "Create New Project"
+msgstr "Crear proyecto nuevo"
+
+#: editor/project_manager.cpp
+msgid "Install Project:"
+msgstr "Instalar proyecto:"
#: editor/project_manager.cpp
msgid "Project Name:"
msgstr "Nombre del proyecto:"
#: editor/project_manager.cpp
-msgid "Create New Project"
-msgstr "Crear proyecto nuevo"
+#, fuzzy
+msgid "Create folder"
+msgstr "Crear carpeta"
#: editor/project_manager.cpp
msgid "Project Path:"
msgstr "Ruta del proyecto:"
#: editor/project_manager.cpp
-msgid "Install Project:"
-msgstr "Instalar proyecto:"
-
-#: editor/project_manager.cpp
msgid "Browse"
msgstr "Examinar"
#: editor/project_manager.cpp
-msgid "New Game Project"
-msgstr "Nuevo proyecto de juego"
-
-#: editor/project_manager.cpp
msgid "That's a BINGO!"
msgstr "BINGO!"
@@ -6234,6 +5918,11 @@ msgid "Unnamed Project"
msgstr "Proyecto sin nombre"
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Can't open project"
+msgstr "Conectar.."
+
+#: editor/project_manager.cpp
msgid "Are you sure to open more than one project?"
msgstr "¿Seguro que quieres abrir más de un proyecto?"
@@ -6249,10 +5938,13 @@ msgstr ""
"«aplicación»."
#: editor/project_manager.cpp
+#, fuzzy
msgid ""
"Can't run project: Assets need to be imported.\n"
"Please edit the project to trigger the initial import."
msgstr ""
+"No se puede ejecutar el proyecto: Los assets necesitan ser importados.\n"
+"Por favor, edita el proyecto para activar el importado inicial."
#: editor/project_manager.cpp
msgid "Are you sure to run more than one project?"
@@ -6266,6 +5958,12 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
+"Language changed.\n"
+"The UI will update next time the editor or project manager starts."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid ""
"You are about the scan %s folders for existing Godot projects. Do you "
"confirm?"
msgstr ""
@@ -6277,10 +5975,6 @@ msgid "Project List"
msgstr "Lista de proyectos"
#: editor/project_manager.cpp
-msgid "Run"
-msgstr "Ejecutar"
-
-#: editor/project_manager.cpp
msgid "Scan"
msgstr "Analizar"
@@ -6303,6 +5997,11 @@ msgstr "Salir"
#: editor/project_manager.cpp
#, fuzzy
+msgid "Restart Now"
+msgstr "Reiniciar (s):"
+
+#: editor/project_manager.cpp
+#, fuzzy
msgid "Can't run project"
msgstr "Conectar.."
@@ -6339,17 +6038,14 @@ msgid "Add Input Action Event"
msgstr "Añadir evento de acción de entrada"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Meta+"
msgstr "Meta+"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Shift+"
msgstr "Mayús+"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Alt+"
msgstr "Alt+"
@@ -6359,7 +6055,7 @@ msgstr "Control+"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
msgid "Press a Key.."
-msgstr "Presiona una tecla…"
+msgstr "Presiona una tecla.."
#: editor/project_settings_editor.cpp
msgid "Mouse Button Index:"
@@ -6411,7 +6107,7 @@ msgstr "Cambiar"
msgid "Joypad Axis Index:"
msgstr "Ãndice de ejes del mando:"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Axis"
msgstr "Eje"
@@ -6433,31 +6129,31 @@ msgstr "Borrar evento de acción de entrada"
msgid "Add Event"
msgstr "Añadir elemento vacío"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Device"
msgstr "Dispositivo"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Button"
msgstr "Botón"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Left Button."
msgstr "Botón izquierdo."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Right Button."
msgstr "Botón derecho."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Middle Button."
msgstr "Botón central."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Up."
msgstr "Rueda hacia arriba."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Down."
msgstr "Rueda hacia abajo."
@@ -6467,8 +6163,9 @@ msgid "Add Global Property"
msgstr "Añadir propiedad «Getter»"
#: editor/project_settings_editor.cpp
-msgid "Select an setting item first!"
-msgstr ""
+#, fuzzy
+msgid "Select a setting item first!"
+msgstr "¡Selecciona un item primero!"
#: editor/project_settings_editor.cpp
#, fuzzy
@@ -6486,6 +6183,16 @@ msgid "Delete Item"
msgstr "Eliminar entrada"
#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Can't contain '/' or ':'"
+msgstr "No se puede conectar al host:"
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Already existing"
+msgstr "Des/activar persistencia"
+
+#: editor/project_settings_editor.cpp
msgid "Error saving settings."
msgstr "Error al guardar los ajustes."
@@ -6494,8 +6201,9 @@ msgid "Settings saved OK."
msgstr "Los ajustes se han guardado correctamente."
#: editor/project_settings_editor.cpp
+#, fuzzy
msgid "Override for Feature"
-msgstr ""
+msgstr "Sobreescribir para esta característica"
#: editor/project_settings_editor.cpp
msgid "Add Translation"
@@ -6527,6 +6235,15 @@ msgstr "Quitar opción de remapeo de recursos"
#: editor/project_settings_editor.cpp
#, fuzzy
+msgid "Changed Locale Filter"
+msgstr "Cambiar tiempo de mezcla"
+
+#: editor/project_settings_editor.cpp
+msgid "Changed Locale Filter Mode"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
msgid "Project Settings (project.godot)"
msgstr "Ajustes de proyecto (engine.cfg)"
@@ -6539,8 +6256,9 @@ msgid "Property:"
msgstr "Propiedad:"
#: editor/project_settings_editor.cpp
+#, fuzzy
msgid "Override For.."
-msgstr ""
+msgstr "Sobreescribir para.."
#: editor/project_settings_editor.cpp
msgid "Input Map"
@@ -6587,6 +6305,30 @@ msgid "Locale"
msgstr "Idioma"
#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Locales Filter"
+msgstr "Filtrado de imágenes:"
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Show all locales"
+msgstr "Crear huesos"
+
+#: editor/project_settings_editor.cpp
+msgid "Show only selected locales"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Filter mode:"
+msgstr "Filtros"
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Locales:"
+msgstr "Idioma"
+
+#: editor/project_settings_editor.cpp
msgid "AutoLoad"
msgstr "AutoLoad"
@@ -6617,11 +6359,11 @@ msgstr "Transición salida-entrada"
#: editor/property_editor.cpp
msgid "File.."
-msgstr "Archivo…"
+msgstr "Archivo.."
#: editor/property_editor.cpp
msgid "Dir.."
-msgstr "Dir…"
+msgstr "Directorio.."
#: editor/property_editor.cpp
msgid "Assign"
@@ -6639,10 +6381,20 @@ msgstr "Script siguiente"
#: editor/property_editor.cpp
#, fuzzy
+msgid "Make Unique"
+msgstr "Crear huesos"
+
+#: editor/property_editor.cpp
+#, fuzzy
msgid "Show in File System"
msgstr "SistDeArchivos"
#: editor/property_editor.cpp
+#, fuzzy
+msgid "Convert To %s"
+msgstr "Convertir a.."
+
+#: editor/property_editor.cpp
msgid "Error loading file: Not a resource!"
msgstr "Error al cargar el archivo: ¡No es un recurso!"
@@ -6683,6 +6435,11 @@ msgstr "Seleccionar puntos"
#: editor/property_selector.cpp
#, fuzzy
+msgid "Select Virtual Method"
+msgstr "Modo de selección"
+
+#: editor/property_selector.cpp
+#, fuzzy
msgid "Select Method"
msgstr "Modo de selección"
@@ -6711,26 +6468,6 @@ msgstr "Mantener transformación global"
msgid "Reparent"
msgstr "Reemparentar"
-#: editor/resources_dock.cpp
-msgid "Create New Resource"
-msgstr "Crear recurso nuevo"
-
-#: editor/resources_dock.cpp
-msgid "Open Resource"
-msgstr "Abrir recurso"
-
-#: editor/resources_dock.cpp
-msgid "Save Resource"
-msgstr "Guardar recurso"
-
-#: editor/resources_dock.cpp
-msgid "Resource Tools"
-msgstr "Herramientas de recursos"
-
-#: editor/resources_dock.cpp
-msgid "Make Local"
-msgstr "Crear local"
-
#: editor/run_settings_dialog.cpp
msgid "Run Mode:"
msgstr "Modo de ejecución:"
@@ -6801,8 +6538,9 @@ msgid "Delete Node(s)?"
msgstr "¿Quieres borrar los nodos?"
#: editor/scene_tree_dock.cpp
+#, fuzzy
msgid "Can not perform with the root node."
-msgstr ""
+msgstr "No se puede efectuar con el nodo raíz."
#: editor/scene_tree_dock.cpp
msgid "This operation can't be done on instanced scenes."
@@ -6810,7 +6548,7 @@ msgstr "Esta operación no puede realizarse en escenas instanciadas."
#: editor/scene_tree_dock.cpp
msgid "Save New Scene As.."
-msgstr "Guardar nueva escena como…"
+msgstr "Guardar nueva escena como.."
#: editor/scene_tree_dock.cpp
msgid "Editable Children"
@@ -6862,14 +6600,6 @@ msgid "Sub-Resources:"
msgstr "Recursos:"
#: editor/scene_tree_dock.cpp
-msgid "Edit Groups"
-msgstr "Editar grupos"
-
-#: editor/scene_tree_dock.cpp
-msgid "Edit Connections"
-msgstr "Editar conexiones"
-
-#: editor/scene_tree_dock.cpp
msgid "Clear Inheritance"
msgstr "Limpiar heredado"
@@ -6964,26 +6694,35 @@ msgid "Toggle CanvasItem Visible"
msgstr "Act/Desact. CanvasItem Visible"
#: editor/scene_tree_editor.cpp
+#, fuzzy
msgid "Node configuration warning:"
-msgstr ""
+msgstr "Alerta de configuración de Nodos:"
#: editor/scene_tree_editor.cpp
+#, fuzzy
msgid ""
"Node has connection(s) and group(s)\n"
"Click to show signals dock."
msgstr ""
+"El nodo tiene conexion(es) y grupo(s)\n"
+"Haz click para mostrar el panel de señales."
#: editor/scene_tree_editor.cpp
+#, fuzzy
msgid ""
"Node has connections.\n"
"Click to show signals dock."
msgstr ""
+"El nodo tiene conexiones.\n"
+"Haz click para mostrar el panel de señales."
#: editor/scene_tree_editor.cpp
msgid ""
"Node is in group(s).\n"
"Click to show groups dock."
msgstr ""
+"El nodo está en el/los grupo(s).\n"
+"Click para mostrar el panel de grupos."
#: editor/scene_tree_editor.cpp
msgid "Instance:"
@@ -6999,12 +6738,16 @@ msgid ""
"Node is locked.\n"
"Click to unlock"
msgstr ""
+"El nodo está bloqueado.\n"
+"Click para desbloquear"
#: editor/scene_tree_editor.cpp
msgid ""
"Children are not selectable.\n"
"Click to make selectable"
msgstr ""
+"Los hijos no son seleccionables.\n"
+"Haz click para hacerlos seleccionables"
#: editor/scene_tree_editor.cpp
#, fuzzy
@@ -7026,7 +6769,7 @@ msgstr "Ãrbol de escenas (nodos):"
#: editor/scene_tree_editor.cpp
msgid "Node Configuration Warning!"
-msgstr ""
+msgstr "¡Alerta de configuración de nodos!"
#: editor/scene_tree_editor.cpp
msgid "Select a Node"
@@ -7064,12 +6807,22 @@ msgid "Invalid base path"
msgstr "Ruta base incorrecta"
#: editor/script_create_dialog.cpp
+msgid "Directory of the same name exists"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
+#, fuzzy
+msgid "File exists, will be reused"
+msgstr "El archivo ya existe, ¿quieres sobreescribirlo?"
+
+#: editor/script_create_dialog.cpp
msgid "Invalid extension"
msgstr "La extensión no es correcta"
#: editor/script_create_dialog.cpp
+#, fuzzy
msgid "Wrong extension chosen"
-msgstr ""
+msgstr "Extensión seleccionada errónea"
#: editor/script_create_dialog.cpp
#, fuzzy
@@ -7092,11 +6845,12 @@ msgstr "Script"
#: editor/script_create_dialog.cpp
msgid "Allowed: a-z, A-Z, 0-9 and _"
-msgstr ""
+msgstr "Permitido: a-z, A-Z, 0-9 y _"
#: editor/script_create_dialog.cpp
+#, fuzzy
msgid "Built-in script (into scene file)"
-msgstr ""
+msgstr "Script integrado (en el archivo de escena)"
#: editor/script_create_dialog.cpp
#, fuzzy
@@ -7109,6 +6863,10 @@ msgid "Load existing script file"
msgstr "Script siguiente"
#: editor/script_create_dialog.cpp
+msgid "Language"
+msgstr "Idioma"
+
+#: editor/script_create_dialog.cpp
#, fuzzy
msgid "Inherits"
msgstr "Hereda:"
@@ -7154,6 +6912,10 @@ msgid "Function:"
msgstr "Función:"
#: editor/script_editor_debugger.cpp
+msgid "Pick one or more items from the list to display the graph."
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
msgid "Errors"
msgstr "Errores"
@@ -7234,6 +6996,10 @@ msgid "Type"
msgstr "Tipo"
#: editor/script_editor_debugger.cpp
+msgid "Format"
+msgstr "Formato"
+
+#: editor/script_editor_debugger.cpp
msgid "Usage"
msgstr "Uso"
@@ -7267,7 +7033,7 @@ msgstr "Cambiar Radio de Luces"
#: editor/spatial_editor_gizmos.cpp
msgid "Change AudioStreamPlayer3D Emission Angle"
-msgstr ""
+msgstr "Cambiar el ángulo de emisión de AudioStreamPlayer3D"
#: editor/spatial_editor_gizmos.cpp
msgid "Change Camera FOV"
@@ -7303,13 +7069,31 @@ msgstr "Cambiar Alcances de Notificadores"
#: editor/spatial_editor_gizmos.cpp
msgid "Change Particles AABB"
-msgstr ""
+msgstr "Cambiar partículas AABB"
#: editor/spatial_editor_gizmos.cpp
#, fuzzy
msgid "Change Probe Extents"
msgstr "Cambiar Alcances de Notificadores"
+#: modules/gdnative/gd_native_library_editor.cpp
+#, fuzzy
+msgid "Library"
+msgstr "MeshLibrary.."
+
+#: modules/gdnative/gd_native_library_editor.cpp
+#, fuzzy
+msgid "Status"
+msgstr "Estado:"
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Libraries: "
+msgstr ""
+
+#: modules/gdnative/register_types.cpp
+msgid "GDNative"
+msgstr ""
+
#: modules/gdscript/gd_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Invalid type argument to convert(), use TYPE_* constants."
@@ -7317,7 +7101,7 @@ msgstr ""
"El argumento para convert() no es correcto, prueba utilizando constantes "
"TYPE_*."
-#: modules/gdscript/gd_functions.cpp
+#: modules/gdscript/gd_functions.cpp modules/mono/glue/glue_header.h
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Not enough bytes for decoding bytes, or invalid format."
msgstr ""
@@ -7362,7 +7146,7 @@ msgstr "El diccionario de instancias no es correcto (subclases erróneas)"
#: modules/gdscript/gd_functions.cpp
msgid "Object can't provide a length."
-msgstr ""
+msgstr "El objeto no puede proporcionar una longitud."
#: modules/gridmap/grid_map_editor_plugin.cpp
#, fuzzy
@@ -7375,21 +7159,19 @@ msgid "GridMap Duplicate Selection"
msgstr "Duplicar selección"
#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "GridMap Paint"
-msgstr ""
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
#, fuzzy
msgid "Snap View"
msgstr "Vista superior"
#: modules/gridmap/grid_map_editor_plugin.cpp
+#, fuzzy
msgid "Prev Level (%sDown Wheel)"
-msgstr ""
+msgstr "Nivel anterior ("
#: modules/gridmap/grid_map_editor_plugin.cpp
+#, fuzzy
msgid "Next Level (%sUp Wheel)"
-msgstr ""
+msgstr "Siguiente nivel ("
#: modules/gridmap/grid_map_editor_plugin.cpp
#, fuzzy
@@ -7397,24 +7179,26 @@ msgid "Clip Disabled"
msgstr "Desactivado"
#: modules/gridmap/grid_map_editor_plugin.cpp
+#, fuzzy
msgid "Clip Above"
-msgstr ""
+msgstr "Clip superior"
#: modules/gridmap/grid_map_editor_plugin.cpp
+#, fuzzy
msgid "Clip Below"
-msgstr ""
+msgstr "Clip inferior"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Edit X Axis"
-msgstr ""
+msgstr "Editar eje X"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Edit Y Axis"
-msgstr ""
+msgstr "Editar eje Y"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Edit Z Axis"
-msgstr ""
+msgstr "Editar eje Z"
#: modules/gridmap/grid_map_editor_plugin.cpp
#, fuzzy
@@ -7432,20 +7216,24 @@ msgid "Cursor Rotate Z"
msgstr "Ctrl: Rotar"
#: modules/gridmap/grid_map_editor_plugin.cpp
+#, fuzzy
msgid "Cursor Back Rotate X"
-msgstr ""
+msgstr "Rotar cursor trasero X"
#: modules/gridmap/grid_map_editor_plugin.cpp
+#, fuzzy
msgid "Cursor Back Rotate Y"
-msgstr ""
+msgstr "Rotar cursor trasero Y"
#: modules/gridmap/grid_map_editor_plugin.cpp
+#, fuzzy
msgid "Cursor Back Rotate Z"
-msgstr ""
+msgstr "Rotar cursor trasero Z"
#: modules/gridmap/grid_map_editor_plugin.cpp
+#, fuzzy
msgid "Cursor Clear Rotation"
-msgstr ""
+msgstr "Quitar rotación del cursor"
#: modules/gridmap/grid_map_editor_plugin.cpp
#, fuzzy
@@ -7482,13 +7270,8 @@ msgstr "Ajustes de fijado"
msgid "Pick Distance:"
msgstr "Instancia:"
-#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
-msgid "Tiles"
-msgstr "Archivo"
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "Areas"
+#: modules/mono/editor/mono_bottom_panel.cpp
+msgid "Builds"
msgstr ""
#: modules/visual_script/visual_script.cpp
@@ -7705,10 +7488,18 @@ msgid "Return"
msgstr "Devuelve"
#: modules/visual_script/visual_script_editor.cpp
+msgid "Call"
+msgstr "Llamada"
+
+#: modules/visual_script/visual_script_editor.cpp
msgid "Get"
msgstr "Obtener"
#: modules/visual_script/visual_script_editor.cpp
+msgid "Script already has function '%s'"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
#, fuzzy
msgid "Change Input Value"
msgstr "Cambiar Nombre de Entrada"
@@ -7867,7 +7658,7 @@ msgstr "Examinar"
#: platform/javascript/export/export.cpp
msgid "Run exported HTML in the system's default browser."
-msgstr ""
+msgstr "Ejecutar HTML exportado en el navegador por defecto del sistema."
#: platform/javascript/export/export.cpp
#, fuzzy
@@ -7975,10 +7766,13 @@ msgstr ""
"ParallaxBackground."
#: scene/2d/particles_2d.cpp scene/3d/particles.cpp
+#, fuzzy
msgid ""
"A material to process the particles is not assigned, so no behavior is "
"imprinted."
msgstr ""
+"No se ha asignado un material para procesar las partículas, por lo que no se "
+"ha grabado ningún comportamiento."
#: scene/2d/path_2d.cpp
msgid "PathFollow2D only works when set as a child of a Path2D node."
@@ -7986,11 +7780,15 @@ msgstr ""
"PathFollow2D solo funciona cuando está seteado como hijo de un nodo Path2D."
#: scene/2d/physics_body_2d.cpp
+#, fuzzy
msgid ""
"Size changes to RigidBody2D (in character or rigid modes) will be overriden "
"by the physics engine when running.\n"
"Change the size in children collision shapes instead."
msgstr ""
+"Los cambios en el tamaño del RigidBody2D (en el personaje o modos rígidos) "
+"serán sobreescritas por el engine de físicas cuando se ejecute.\n"
+"En vez de eso, cambia el tamaño en las formas de colisión hijas."
#: scene/2d/remote_transform_2d.cpp
msgid "Path property must point to a valid Node2D node to work."
@@ -8022,31 +7820,37 @@ msgstr ""
#: scene/3d/arvr_nodes.cpp
msgid "ARVRCamera must have an ARVROrigin node as its parent"
-msgstr ""
+msgstr "ARVRCamera tiene que tener un nodo ARVROrigin como padre"
#: scene/3d/arvr_nodes.cpp
msgid "ARVRController must have an ARVROrigin node as its parent"
-msgstr ""
+msgstr "ARVRController tiene que tener un nodo ARVROrigin como padre"
#: scene/3d/arvr_nodes.cpp
+#, fuzzy
msgid ""
"The controller id must not be 0 or this controller will not be bound to an "
"actual controller"
msgstr ""
+"El id del controlador no puede ser 0 o este controlador no se asignará a un "
+"controlador de verdad."
#: scene/3d/arvr_nodes.cpp
msgid "ARVRAnchor must have an ARVROrigin node as its parent"
-msgstr ""
+msgstr "ARVRAnchor tiene que tener un nodo ARVROrigin como padre"
#: scene/3d/arvr_nodes.cpp
+#, fuzzy
msgid ""
"The anchor id must not be 0 or this anchor will not be bound to an actual "
"anchor"
msgstr ""
+"El id del ancla no puede ser 0 o este ancla no se asignará a un ancla de "
+"verdad"
#: scene/3d/arvr_nodes.cpp
msgid "ARVROrigin requires an ARVRCamera child node"
-msgstr ""
+msgstr "ARVROrigin necesita un nodo ARVCamera hijo"
#: scene/3d/collision_polygon.cpp
msgid ""
@@ -8095,16 +7899,23 @@ msgstr ""
"que sólo proporciona los datos de navegación."
#: scene/3d/particles.cpp
+#, fuzzy
msgid ""
"Nothing is visible because meshes have not been assigned to draw passes."
msgstr ""
+"Nada es visible porque los modelos 3D no se han asignado a las pasadas de "
+"dibujo."
#: scene/3d/physics_body.cpp
+#, fuzzy
msgid ""
"Size changes to RigidBody (in character or rigid modes) will be overriden by "
"the physics engine when running.\n"
"Change the size in children collision shapes instead."
msgstr ""
+"Los cambios en el tamaño del RigidBody (en el personaje o modos rígidos) "
+"serán sobreescritas por el engine de físicas cuando se ejecute.\n"
+"En vez de eso, cambia el tamaño en las formas de colisión hijas."
#: scene/3d/remote_transform.cpp
#, fuzzy
@@ -8127,6 +7938,12 @@ msgstr ""
"Un recurso SpriteFrames debe ser creado o asignado en la propiedad 'Frames' "
"para que AnimatedSprite3D pueda mostrar frames."
+#: scene/3d/vehicle_body.cpp
+msgid ""
+"VehicleWheel serves to provide a wheel system to a VehicleBody. Please use "
+"it as a child of a VehicleBody."
+msgstr ""
+
#: scene/gui/color_picker.cpp
#, fuzzy
msgid "Raw Mode"
@@ -8134,7 +7951,11 @@ msgstr "Modo desplazamiento lateral"
#: scene/gui/color_picker.cpp
msgid "Add current color as a preset"
-msgstr ""
+msgstr "Añadir el color actual como predefinido"
+
+#: scene/gui/dialogs.cpp
+msgid "Cancel"
+msgstr "Cancelar"
#: scene/gui/dialogs.cpp
msgid "Alert!"
@@ -8144,10 +7965,6 @@ msgstr "Alerta!"
msgid "Please Confirm..."
msgstr "Confirmar decisión…"
-#: scene/gui/input_action.cpp
-msgid "Ctrl+"
-msgstr "Ctrl+"
-
#: scene/gui/popup.cpp
msgid ""
"Popups will hide by default unless you call popup() or any of the popup*() "
@@ -8159,17 +7976,24 @@ msgstr ""
"hacerlos visibles para editar, aunque se esconderán al ejecutar."
#: scene/gui/scroll_container.cpp
+#, fuzzy
msgid ""
"ScrollContainer is intended to work with a single child control.\n"
"Use a container as child (VBox,HBox,etc), or a Control and set the custom "
"minimum size manually."
msgstr ""
+"ScrollContainer debe funcionar con un único control de hijos.\n"
+"Usa un container como hijo (VBox,HBox,etc), o un Control y ajusta el tamaño "
+"mínimo personalizado manualmente."
#: scene/main/scene_tree.cpp
+#, fuzzy
msgid ""
"Default Environment as specified in Project Setings (Rendering -> Viewport -"
"> Default Environment) could not be loaded."
msgstr ""
+"El entorno por defecto especificado en los Ajustes del Proyecto (Renderizado "
+"-> Ventana -> Entorno por Defecto) no se ha podido cargar."
#: scene/main/viewport.cpp
msgid ""
@@ -8183,6 +8007,658 @@ msgstr ""
"que pueda obtener un tamaño. Alternativamente, hacelo un RenderTarget y "
"asigná su textura interna a algún otro nodo para mostrar."
+#: scene/resources/dynamic_font.cpp
+msgid "Error initializing FreeType."
+msgstr "Error al arrancar FreeType."
+
+#: scene/resources/dynamic_font.cpp
+msgid "Unknown font format."
+msgstr "Formato de tipografía desconocido."
+
+#: scene/resources/dynamic_font.cpp
+msgid "Error loading font."
+msgstr "Error al cargar la tipografía."
+
+#: scene/resources/dynamic_font.cpp
+msgid "Invalid font size."
+msgstr "Tamaño de tipografía incorrecto."
+
+#~ msgid "Filter:"
+#~ msgstr "Filtro:"
+
+#, fuzzy
+#~ msgid "' parsing of config failed."
+#~ msgstr "' análisis de config fallido."
+
+#, fuzzy
+#~ msgid "Theme"
+#~ msgstr "Guardar tema"
+
+#~ msgid "Method List For '%s':"
+#~ msgstr "Lista de métodos Para '%s':"
+
+#~ msgid "Arguments:"
+#~ msgstr "Argumentos:"
+
+#~ msgid "Return:"
+#~ msgstr "Devuelve:"
+
+#~ msgid "Added:"
+#~ msgstr "Añadido:"
+
+#~ msgid "Removed:"
+#~ msgstr "Eliminado:"
+
+#~ msgid "Error saving atlas:"
+#~ msgstr "Error al guardar atlas:"
+
+#~ msgid "Could not save atlas subtexture:"
+#~ msgstr "No se pudo guardar la subtextura del altas:"
+
+#~ msgid "Exporting for %s"
+#~ msgstr "Exportando para %s"
+
+#~ msgid "Setting Up.."
+#~ msgstr "Configurando.."
+
+#~ msgid "Error loading scene."
+#~ msgstr "Hubo un error al cargar la escena."
+
+#~ msgid "Re-Import"
+#~ msgstr "Reimportar"
+
+#~ msgid "Please wait for scan to complete."
+#~ msgstr "Espera a que termine el análisis."
+
+#~ msgid "Current scene must be saved to re-import."
+#~ msgstr "La escena actual debe ser guardada para reimportar."
+
+#~ msgid "Save & Re-Import"
+#~ msgstr "Guardar y reimportar"
+
+#~ msgid "Re-Importing"
+#~ msgstr "Reimportando"
+
+#~ msgid "Re-Import Changed Resources"
+#~ msgstr "Reimportar recursos cambiados"
+
+#~ msgid "Loading Export Templates"
+#~ msgstr "Cargando plantillas de exportación"
+
+#, fuzzy
+#~ msgid ""
+#~ "\n"
+#~ "Status: Needs Re-Import"
+#~ msgstr "Guardar y reimportar"
+
+#~ msgid "Same source and destination files, doing nothing."
+#~ msgstr ""
+#~ "Los archivos de origen y destino son iguales, no se realizará ninguna "
+#~ "acción."
+
+#~ msgid "Target file exists, can't overwrite. Delete first."
+#~ msgstr ""
+#~ "El archivo objetivo ya existe, no se puede sobreescribir. Bórralo primero."
+
+#~ msgid "Same source and destination paths, doing nothing."
+#~ msgstr ""
+#~ "Las rutas de origen y destino son iguales, no se realizará ninguna acción."
+
+#~ msgid "Can't move directories to within themselves."
+#~ msgstr "No se pueden mover carpetas dentro de si mismas."
+
+#, fuzzy
+#~ msgid "Can't rename deps for:\n"
+#~ msgstr "No se pueden renombrar las dependencias para:\n"
+
+#, fuzzy
+#~ msgid "Error moving file:\n"
+#~ msgstr "Error al cargar la imagen:"
+
+#~ msgid "Pick New Name and Location For:"
+#~ msgstr "Elige un nombre nuevo y ubicación para:"
+
+#~ msgid "No files selected!"
+#~ msgstr "¡No has seleccionado ningún archivo!"
+
+#~ msgid "Info"
+#~ msgstr "Info"
+
+#~ msgid "Re-Import.."
+#~ msgstr "Reimportar.."
+
+#~ msgid "No bit masks to import!"
+#~ msgstr "¡Sin máscaras de bits para importar!"
+
+#~ msgid "Target path is empty."
+#~ msgstr "La ruta de destino está vacía."
+
+#~ msgid "Target path must be a complete resource path."
+#~ msgstr "La ruta de destino debe ser una ruta de recursos completa."
+
+#~ msgid "Target path must exist."
+#~ msgstr "La ruta de destino debe existir."
+
+#~ msgid "Save path is empty!"
+#~ msgstr "La ruta de guardado esta vacía!"
+
+#~ msgid "Import BitMasks"
+#~ msgstr "Importar BitMasks"
+
+#~ msgid "Source Texture(s):"
+#~ msgstr "Texturas de origen:"
+
+#~ msgid "Target Path:"
+#~ msgstr "Ruta de destino:"
+
+#~ msgid "Accept"
+#~ msgstr "Aceptar"
+
+#~ msgid "Bit Mask"
+#~ msgstr "Máscara de bits"
+
+#~ msgid "No source font file!"
+#~ msgstr "¡No se ha elegido ningún archivo de tipografías!"
+
+#~ msgid "No target font resource!"
+#~ msgstr "¡No se ha elegido ningún recurso de tipografías!"
+
+#, fuzzy
+#~ msgid ""
+#~ "Invalid file extension.\n"
+#~ "Please use .font."
+#~ msgstr ""
+#~ "La extensión del archivo no es correcta.\n"
+#~ "Prueba con la extensión .fnt."
+
+#~ msgid "Couldn't save font."
+#~ msgstr "No se pudo guardar la tipografía."
+
+#~ msgid "Source Font:"
+#~ msgstr "Tipografía elegida:"
+
+#~ msgid "Source Font Size:"
+#~ msgstr "Tamaño de la tipografía elegida:"
+
+#~ msgid "Dest Resource:"
+#~ msgstr "Recurso de destino:"
+
+#~ msgid "The quick brown fox jumps over the lazy dog."
+#~ msgstr "El veloz murciélago hindú comía feliz cardillo y kiwi."
+
+#~ msgid "Test:"
+#~ msgstr "Prueba:"
+
+#~ msgid "Options:"
+#~ msgstr "Opciones:"
+
+#~ msgid "Font Import"
+#~ msgstr "Importar tipografías"
+
+#~ msgid ""
+#~ "This file is already a Godot font file, please supply a BMFont type file "
+#~ "instead."
+#~ msgstr ""
+#~ "Este archivo ya es un archivo de tipografías de Godot, tienes que "
+#~ "utilizar un archivo de tipo BMFont."
+
+#~ msgid "Failed opening as BMFont file."
+#~ msgstr "Error al abrir como archivo BMFont."
+
+#~ msgid "Invalid font custom source."
+#~ msgstr "El origen personalizado de tipografía no es correcto."
+
+#~ msgid "No meshes to import!"
+#~ msgstr "¡No hay ningún modelo que se pueda importar!"
+
+#~ msgid "Single Mesh Import"
+#~ msgstr "Importar modelo individual"
+
+#~ msgid "Source Mesh(es):"
+#~ msgstr "Modelo/s elegidos:"
+
+#~ msgid "Surface %d"
+#~ msgstr "Superficie %d"
+
+#~ msgid "No samples to import!"
+#~ msgstr "¡No hay ningún sonido a importar!"
+
+#~ msgid "Import Audio Samples"
+#~ msgstr "Importar archivo de sonido"
+
+#~ msgid "Source Sample(s):"
+#~ msgstr "Muestra(s) de Origen:"
+
+#~ msgid "Audio Sample"
+#~ msgstr "Archivo de sonido"
+
+#~ msgid "New Clip"
+#~ msgstr "Nuevo clip"
+
+#~ msgid "Flags"
+#~ msgstr "Identificadores"
+
+#~ msgid "Bake FPS:"
+#~ msgstr "Hacer Bake de FPS:"
+
+#~ msgid "Optimizer"
+#~ msgstr "Optimizar"
+
+#~ msgid "Max Linear Error"
+#~ msgstr "Error lineal máximo"
+
+#~ msgid "Max Angular Error"
+#~ msgstr "Error angular máximo"
+
+#~ msgid "Max Angle"
+#~ msgstr "Ãngulo máximo"
+
+#~ msgid "Clips"
+#~ msgstr "Clips"
+
+#~ msgid "Start(s)"
+#~ msgstr "Inicios"
+
+#~ msgid "End(s)"
+#~ msgstr "Finales"
+
+#~ msgid "Filters"
+#~ msgstr "Filtros"
+
+#~ msgid "Source path is empty."
+#~ msgstr "La ruta de origen esta vacía."
+
+#~ msgid "Couldn't load post-import script."
+#~ msgstr "No se pudo cargar el script post-importación."
+
+#~ msgid "Invalid/broken script for post-import."
+#~ msgstr "El script de postimportación no es correcto o está roto."
+
+#~ msgid "Error importing scene."
+#~ msgstr "Error al importar escena."
+
+#~ msgid "Import 3D Scene"
+#~ msgstr "Importar escena 3D"
+
+#~ msgid "Source Scene:"
+#~ msgstr "Escena de origen:"
+
+#~ msgid "Same as Target Scene"
+#~ msgstr "Igual que escena de destino"
+
+#~ msgid "Shared"
+#~ msgstr "Compartido"
+
+#~ msgid "Target Texture Folder:"
+#~ msgstr "Carpeta de texturas elegida:"
+
+#~ msgid "Post-Process Script:"
+#~ msgstr "Script de posprocesado:"
+
+#~ msgid "Custom Root Node Type:"
+#~ msgstr "Tipo de Nodo Raiz Customizado:"
+
+#~ msgid "Auto"
+#~ msgstr "Auto"
+
+#, fuzzy
+#~ msgid "Root Node Name:"
+#~ msgstr "Nombre del nodo:"
+
+#~ msgid "The Following Files are Missing:"
+#~ msgstr "Faltan los siguientes archivos:"
+
+#~ msgid "Import Anyway"
+#~ msgstr "Importar de todos modos"
+
+#~ msgid "Import & Open"
+#~ msgstr "Importar y abrir"
+
+#~ msgid "Edited scene has not been saved, open imported scene anyway?"
+#~ msgstr ""
+#~ "La escena editada no se ha guardado, ¿Quieres abrir la escena importada "
+#~ "de todos modos?"
+
+#~ msgid "Import Image:"
+#~ msgstr "Importar imagen:"
+
+#~ msgid "Couldn't localize path: %s (already local)"
+#~ msgstr "No se pudo encontrar la ruta: %s (ya es local)"
+
+#~ msgid "3D Scene Animation"
+#~ msgstr "Animación de escena 3D"
+
+#~ msgid "Uncompressed"
+#~ msgstr "Sin comprimir"
+
+#~ msgid "Compress Lossless (PNG)"
+#~ msgstr "Compresión sin pérdidas (PNG)"
+
+#~ msgid "Compress Lossy (WebP)"
+#~ msgstr "Compresión con pérdidas (WebP)"
+
+#~ msgid "Compress (VRAM)"
+#~ msgstr "Comprimir (VRAM)"
+
+#~ msgid "Texture Format"
+#~ msgstr "Formato de textura"
+
+#~ msgid "Texture Compression Quality (WebP):"
+#~ msgstr "Calidad de compresión de textura (WebP):"
+
+#~ msgid "Texture Options"
+#~ msgstr "Opciones de textura"
+
+#~ msgid "Please specify some files!"
+#~ msgstr "¡Selecciona algunos archivos!"
+
+#~ msgid "At least one file needed for Atlas."
+#~ msgstr "Se necesita al menos un archivo para el atlas."
+
+#~ msgid "Error importing:"
+#~ msgstr "Hubo un error al importar:"
+
+#~ msgid "Only one file is required for large texture."
+#~ msgstr "Solo se requiere un archivo para textura grande."
+
+#~ msgid "Max Texture Size:"
+#~ msgstr "Tamaño máximo de textura:"
+
+#~ msgid "Import Textures for Atlas (2D)"
+#~ msgstr "Importar texturas para atlas (2D)"
+
+#~ msgid "Cell Size:"
+#~ msgstr "Tamaño de celda:"
+
+#~ msgid "Large Texture"
+#~ msgstr "Textura grande"
+
+#~ msgid "Import Large Textures (2D)"
+#~ msgstr "Importar texturas grandes (2D)"
+
+#~ msgid "Source Texture"
+#~ msgstr "Textura de origen"
+
+#~ msgid "Base Atlas Texture"
+#~ msgstr "Textura base de atlas"
+
+#~ msgid "Source Texture(s)"
+#~ msgstr "Texturas de origen"
+
+#~ msgid "Import Textures for 2D"
+#~ msgstr "Importar texturas para 2D"
+
+#~ msgid "Import Textures for 3D"
+#~ msgstr "Importar texturas para 3D"
+
+#~ msgid "Import Textures"
+#~ msgstr "Importar texturas"
+
+#~ msgid "2D Texture"
+#~ msgstr "Textura 2D"
+
+#~ msgid "3D Texture"
+#~ msgstr "Textura 3D"
+
+#~ msgid "Atlas Texture"
+#~ msgstr "Textura de atlas"
+
+#~ msgid ""
+#~ "NOTICE: Importing 2D textures is not mandatory. Just copy png/jpg files "
+#~ "to the project."
+#~ msgstr ""
+#~ "AVISO: No es necesario importar texturas 2D. Limítate a copia los "
+#~ "archivos png/jpg al proyecto."
+
+#~ msgid "Crop empty space."
+#~ msgstr "Recortar espacio vacío."
+
+#~ msgid "Texture"
+#~ msgstr "Textura"
+
+#~ msgid "Import Large Texture"
+#~ msgstr "Importar textura grande"
+
+#~ msgid "Load Source Image"
+#~ msgstr "Cargar imagen de origen"
+
+#~ msgid "Slicing"
+#~ msgstr "Troceando"
+
+#~ msgid "Saving"
+#~ msgstr "Guardando"
+
+#~ msgid "Couldn't save large texture:"
+#~ msgstr "No se pudo guardar la textura grande:"
+
+#~ msgid "Build Atlas For:"
+#~ msgstr "Construir atlas para:"
+
+#~ msgid "Loading Image:"
+#~ msgstr "Cargando imagen:"
+
+#~ msgid "Couldn't load image:"
+#~ msgstr "No se pudo cargar la imagen:"
+
+#~ msgid "Converting Images"
+#~ msgstr "Convirtiendo imágenes"
+
+#~ msgid "Cropping Images"
+#~ msgstr "Recortando imágenes"
+
+#~ msgid "Blitting Images"
+#~ msgstr "Copiando datos de imágenes"
+
+#~ msgid "Couldn't save atlas image:"
+#~ msgstr "No se pudo guardar la imagen de atlas:"
+
+#~ msgid "Couldn't save converted texture:"
+#~ msgstr "No se pudo guardar la textura convertida:"
+
+#~ msgid "Invalid source!"
+#~ msgstr "¡Origen incorrecto!"
+
+#~ msgid "Invalid translation source!"
+#~ msgstr "¡Origen de traducción incorrecto!"
+
+#~ msgid "Column"
+#~ msgstr "Columna"
+
+#~ msgid "No items to import!"
+#~ msgstr "Sin elementos para importar!"
+
+#~ msgid "No target path!"
+#~ msgstr "¡El objetivo no tiene ruta!"
+
+#~ msgid "Import Translations"
+#~ msgstr "Importar traducciones"
+
+#~ msgid "Couldn't import!"
+#~ msgstr "¡No se pudo importar!"
+
+#~ msgid "Import Translation"
+#~ msgstr "Importar traducción"
+
+#~ msgid "Source CSV:"
+#~ msgstr "CSV de origen:"
+
+#~ msgid "Ignore First Row"
+#~ msgstr "Ignorar Primera Columna"
+
+#~ msgid "Compress"
+#~ msgstr "Comprimir"
+
+#, fuzzy
+#~ msgid "Add to Project (project.godot)"
+#~ msgstr "Añadir al proyecto (engine.cfg)"
+
+#~ msgid "Import Languages:"
+#~ msgstr "Importar idiomas:"
+
+#~ msgid "Translation"
+#~ msgstr "Traducción"
+
+#~ msgid "Parsing %d Triangles:"
+#~ msgstr "Leyendo %d triángulos:"
+
+#~ msgid "Triangle #"
+#~ msgstr "Nº de triángulos"
+
+#~ msgid "Light Baker Setup:"
+#~ msgstr "Configuración de Baker de Luces:"
+
+#~ msgid "Fixing Lights"
+#~ msgstr "Procesando luces"
+
+#~ msgid "Making BVH"
+#~ msgstr "Creando BVH"
+
+#~ msgid "Transfer to Lightmaps:"
+#~ msgstr "Transfiriendo a «lightmaps»:"
+
+#~ msgid "Allocating Texture #"
+#~ msgstr "Asignando nº de textura"
+
+#~ msgid "Baking Triangle #"
+#~ msgstr "Quemando nº de triángulo"
+
+#~ msgid "Post-Processing Texture #"
+#~ msgstr "Posprocesando nº de textura"
+
+#~ msgid "Reset the lightmap octree baking process (start over)."
+#~ msgstr ""
+#~ "Restablece el proceso de «bake» del «octree» del «lightmap» (empezar de "
+#~ "nuevo)."
+
+#~ msgid "Zoom (%):"
+#~ msgstr "Zoom (%):"
+
+#~ msgid "Skeleton.."
+#~ msgstr "Esqueleto.."
+
+#~ msgid "Zoom Reset"
+#~ msgstr "Restablecer zoom"
+
+#~ msgid "Zoom Set.."
+#~ msgstr "Ajustar zoom.."
+
+#~ msgid "Set a Value"
+#~ msgstr "Establecer valor"
+
+#~ msgid "Snap (Pixels):"
+#~ msgstr "Fijar (Pixeles):"
+
+#~ msgid "Parse BBCode"
+#~ msgstr "Leer BBCode"
+
+#~ msgid "Length:"
+#~ msgstr "Duración:"
+
+#~ msgid "Open Sample File(s)"
+#~ msgstr "Abrir archivos de sonido"
+
+#~ msgid "ERROR: Couldn't load sample!"
+#~ msgstr "¡ERROR: No se pudo cargar el archivo de sonido!"
+
+#~ msgid "Add Sample"
+#~ msgstr "Añadir archivo de sonido"
+
+#~ msgid "Rename Sample"
+#~ msgstr "Renombrar archivo de sonido"
+
+#~ msgid "Delete Sample"
+#~ msgstr "Eliminar archivo de sonido"
+
+#~ msgid "16 Bits"
+#~ msgstr "16 bits"
+
+#~ msgid "8 Bits"
+#~ msgstr "8 bits"
+
+#~ msgid "Stereo"
+#~ msgstr "Estéreo"
+
+#~ msgid "Mono"
+#~ msgstr "Mono"
+
+#~ msgid "Pitch"
+#~ msgstr "Altura"
+
+#~ msgid "Window"
+#~ msgstr "Ventana"
+
+#~ msgid "Move Right"
+#~ msgstr "Mover a la derecha"
+
+#~ msgid "Scaling to %s%%."
+#~ msgstr "Escalando al %s%%."
+
+#~ msgid "Up"
+#~ msgstr "Arriba"
+
+#~ msgid "Down"
+#~ msgstr "Abajo"
+
+#~ msgid "Bucket"
+#~ msgstr "Cubo"
+
+#~ msgid "Invalid project path, the path must exist!"
+#~ msgstr "¡La ruta del proyecto no es correcta, tiene que existir!"
+
+#, fuzzy
+#~ msgid "Invalid project path, project.godot must not exist."
+#~ msgstr "La ruta del proyecto no es correcta, engine.cfg no debe existir."
+
+#, fuzzy
+#~ msgid "Invalid project path, project.godot must exist."
+#~ msgstr "¡La ruta del proyecto no es correcta, engine.cfg debe existir."
+
+#~ msgid "Project Path (Must Exist):"
+#~ msgstr "Ruta del proyecto (debe existir):"
+
+#~ msgid "Create New Resource"
+#~ msgstr "Crear recurso nuevo"
+
+#~ msgid "Open Resource"
+#~ msgstr "Abrir recurso"
+
+#~ msgid "Save Resource"
+#~ msgstr "Guardar recurso"
+
+#~ msgid "Resource Tools"
+#~ msgstr "Herramientas de recursos"
+
+#~ msgid "Make Local"
+#~ msgstr "Crear local"
+
+#~ msgid "Edit Groups"
+#~ msgstr "Editar grupos"
+
+#~ msgid "Edit Connections"
+#~ msgstr "Editar conexiones"
+
+#, fuzzy
+#~ msgid "GridMap Paint"
+#~ msgstr "Coloreado de GridMap"
+
+#, fuzzy
+#~ msgid "Tiles"
+#~ msgstr "Archivo"
+
+#~ msgid "Areas"
+#~ msgstr "Ãreas"
+
+#~ msgid "Ctrl+"
+#~ msgstr "Ctrl+"
+
+#, fuzzy
+#~ msgid "Down Wheel)"
+#~ msgstr "Rueda de ratón hacia abajo)"
+
+#, fuzzy
+#~ msgid "Up Wheel)"
+#~ msgstr "Rueda de ratón hacia arriba)"
+
#~ msgid "Close scene? (Unsaved changes will be lost)"
#~ msgstr "¿Quieres cerrar la escena? (Los cambios sin guardar se perderán)"
@@ -8196,9 +8672,6 @@ msgstr ""
#~ msgid "Close Goto Prev. Scene"
#~ msgstr "Cerrar e ir a escena anterior"
-#~ msgid "Expand to Parent"
-#~ msgstr "Expandir al padre"
-
#~ msgid "Del"
#~ msgstr "Eliminar"
@@ -8387,18 +8860,12 @@ msgstr ""
#~ msgid "Save Translatable Strings"
#~ msgstr "Guardar cadenas traducibles"
-#~ msgid "Translatable Strings.."
-#~ msgstr "Cadenas traducibles…"
-
#~ msgid "Install Export Templates"
#~ msgstr "Instalar plantillas de exportación"
#~ msgid "Edit Script Options"
#~ msgstr "Editar opciones de script"
-#~ msgid "Please export outside the project folder!"
-#~ msgstr "¡Prueba exportando fuera de la carpeta del proyecto!"
-
#~ msgid "Error exporting project!"
#~ msgstr "¡Error al exportar el proyecto!"
@@ -8464,18 +8931,12 @@ msgstr ""
#~ msgid "Include"
#~ msgstr "Incluir"
-#~ msgid "Change Image Group"
-#~ msgstr "Cambiar grupo de imágenes"
-
#~ msgid "Group name can't be empty!"
#~ msgstr "¡El nombre del grupo no puede estar vacío!"
#~ msgid "Invalid character in group name!"
#~ msgstr "¡El nombre del grupo contiene una letra no permitida!"
-#~ msgid "Group name already exists!"
-#~ msgstr "¡El nombre de grupo ya existe!"
-
#~ msgid "Add Image Group"
#~ msgstr "Añadir grupo de imágenes"
@@ -8554,9 +9015,6 @@ msgstr ""
#~ msgid "Preview Atlas"
#~ msgstr "Vista previa del atlas"
-#~ msgid "Image Filter:"
-#~ msgstr "Filtrado de imágenes:"
-
#~ msgid "Images:"
#~ msgstr "Imágenes:"
@@ -8623,9 +9081,6 @@ msgstr ""
#~ msgid "Lighting"
#~ msgstr "Iluminación"
-#~ msgid "Toggle Persisting"
-#~ msgstr "Des/activar persistencia"
-
#~ msgid "Global"
#~ msgstr "Global"
diff --git a/editor/translations/es_AR.po b/editor/translations/es_AR.po
index dd5f8ad597..3d0c4ee410 100644
--- a/editor/translations/es_AR.po
+++ b/editor/translations/es_AR.po
@@ -1,5 +1,6 @@
# Spanish (Argentina) translation of the Godot Engine editor
-# Copyright (C) 2016-2017 Juan Linietsky, Ariel Manzur and the Godot community
+# Copyright (C) 2007-2017 Juan Linietsky, Ariel Manzur
+# Copyright (C) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)
# This file is distributed under the same license as the Godot source code.
#
# Lisandro Lorea <lisandrolorea@gmail.com>, 2016-2017.
@@ -10,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2017-06-29 19:59+0000\n"
+"PO-Revision-Date: 2017-10-23 00:50+0000\n"
"Last-Translator: Lisandro Lorea <lisandrolorea@gmail.com>\n"
"Language-Team: Spanish (Argentina) <https://hosted.weblate.org/projects/"
"godot-engine/godot/es_AR/>\n"
@@ -19,7 +20,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 2.15-dev\n"
+"X-Generator: Weblate 2.17\n"
#: editor/animation_editor.cpp
msgid "Disabled"
@@ -195,10 +196,9 @@ msgid "Create %d NEW tracks and insert keys?"
msgstr "Crear %d NUEVOS tracks e insertar claves?"
#: editor/animation_editor.cpp editor/create_dialog.cpp
-#: editor/editor_audio_buses.cpp
+#: editor/editor_audio_buses.cpp editor/plugins/abstract_polygon_2d_editor.cpp
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
#: editor/plugins/mesh_instance_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp editor/project_manager.cpp
#: editor/script_create_dialog.cpp
msgid "Create"
@@ -361,261 +361,6 @@ msgstr "Cambiar Tipo de Valor del Array"
msgid "Change Array Value"
msgstr "Cambiar Valor del Array"
-#: editor/asset_library_editor_plugin.cpp
-msgid "Free"
-msgstr "Libre"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_plugin_settings.cpp
-msgid "Version:"
-msgstr "Version:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Contents:"
-msgstr "Contenido:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "View Files"
-msgstr "Ver Archivos"
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_help.cpp editor/property_selector.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Description:"
-msgstr "Descripción:"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-#: editor/project_manager.cpp
-msgid "Install"
-msgstr "Instalar"
-
-#: editor/asset_library_editor_plugin.cpp editor/call_dialog.cpp
-#: editor/connections_dialog.cpp editor/export_template_manager.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-#: editor/project_settings_editor.cpp editor/property_editor.cpp
-#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Close"
-msgstr "Cerrar"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve hostname:"
-msgstr "No se ha podido resolver el nombre del host:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve."
-msgstr "No se ha podido resolver."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Connection error, please try again."
-msgstr "Error de conexión, por favor intentá de nuevo."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't connect."
-msgstr "No se puede conectar."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't connect to host:"
-msgstr "No se puede conectar al host:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response from host:"
-msgstr "No hay respuesta desde el host:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response."
-msgstr "Sin respuesta."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Request failed, return code:"
-msgstr "Solicitud fallida. Código de retorno:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Req. Failed."
-msgstr "Solicitud fallida."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Request failed, too many redirects"
-msgstr "Solicitud fallida, demasiadas redireccinoes"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Redirect Loop."
-msgstr "Bucle de redireccionamiento."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed:"
-msgstr "Fallido:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Bad download hash, assuming file has been tampered with."
-msgstr "Hash de descarga incorrecto, asumiendo que el archivo fue manipulado."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Expected:"
-msgstr "Esperado:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Got:"
-msgstr "Recibido:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
-msgstr "Fallo el chequeo del hash sha256"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Asset Download Error:"
-msgstr "Error de Descarga del Asset:"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-msgid "Success!"
-msgstr "Conseguido!"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Fetching:"
-msgstr "Obteniendo:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Resolving.."
-msgstr "Resolviendo.."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Connecting.."
-msgstr "Conectando.."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Requesting.."
-msgstr "Solicitando.."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Error making request"
-msgstr "Error al realizar la solicitud"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Idle"
-msgstr "Desocupado"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Retry"
-msgstr "Reintentar"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Download Error"
-msgstr "Error de Descarga"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Download for this asset is already in progress!"
-msgstr "La descarga de este asset ya esta en progreso!"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "first"
-msgstr "primero"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "prev"
-msgstr "anterior"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "next"
-msgstr "siguiente"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "last"
-msgstr "último"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "All"
-msgstr "Todos"
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
-#: editor/settings_config_dialog.cpp
-msgid "Search:"
-msgstr "Buscar:"
-
-#: editor/asset_library_editor_plugin.cpp editor/code_editor.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Search"
-msgstr "Buscar"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/project_manager.cpp
-msgid "Import"
-msgstr "Importar"
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Plugins"
-msgstr "Plugins"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Sort:"
-msgstr "Ordenar:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Reverse"
-msgstr "Invertir"
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Category:"
-msgstr "Categoría:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Site:"
-msgstr "Sitio:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Support.."
-msgstr "Soporte.."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Official"
-msgstr "Oficial"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-msgid "Community"
-msgstr "Comunidad"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Testing"
-msgstr "Testeo"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Assets ZIP File"
-msgstr "Archivo ZIP de Assets"
-
-#: editor/call_dialog.cpp
-msgid "Method List For '%s':"
-msgstr "Lista de Métodos Para '%s':"
-
-#: editor/call_dialog.cpp modules/visual_script/visual_script_editor.cpp
-msgid "Call"
-msgstr "Llamar"
-
-#: editor/call_dialog.cpp
-msgid "Method List:"
-msgstr "Lista de Métodos:"
-
-#: editor/call_dialog.cpp
-msgid "Arguments:"
-msgstr "Argumentos:"
-
-#: editor/call_dialog.cpp
-msgid "Return:"
-msgstr "Retornar:"
-
#: editor/code_editor.cpp
msgid "Go to Line"
msgstr "Ir a Línea"
@@ -652,6 +397,14 @@ msgstr "Palabras Completas"
msgid "Selection Only"
msgstr "Solo Selección"
+#: editor/code_editor.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
+msgid "Search"
+msgstr "Buscar"
+
#: editor/code_editor.cpp editor/editor_help.cpp
msgid "Find"
msgstr "Encontrar"
@@ -684,11 +437,11 @@ msgstr "Preguntar Antes de Reemplazar"
msgid "Skip"
msgstr "Saltear"
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom In"
msgstr "Zoom In"
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom Out"
msgstr "Zoom Out"
@@ -757,6 +510,20 @@ msgstr "Diferido"
msgid "Oneshot"
msgstr "Oneshot"
+#: editor/connections_dialog.cpp editor/dependency_editor.cpp
+#: editor/export_template_manager.cpp
+#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Close"
+msgstr "Cerrar"
+
#: editor/connections_dialog.cpp
msgid "Connect"
msgstr "Conectar"
@@ -782,7 +549,7 @@ msgstr "Conectar.."
msgid "Disconnect"
msgstr "Desconectar"
-#: editor/connections_dialog.cpp editor/node_dock.cpp
+#: editor/connections_dialog.cpp editor/editor_help.cpp editor/node_dock.cpp
msgid "Signals"
msgstr "Señales"
@@ -799,12 +566,25 @@ msgstr "Favoritos:"
msgid "Recent:"
msgstr "Recientes:"
+#: editor/create_dialog.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/quick_open.cpp editor/settings_config_dialog.cpp
+msgid "Search:"
+msgstr "Buscar:"
+
#: editor/create_dialog.cpp editor/editor_help.cpp
#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/quick_open.cpp
msgid "Matches:"
msgstr "Coincidencias:"
+#: editor/create_dialog.cpp editor/editor_help.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/property_selector.cpp
+#: editor/script_editor_debugger.cpp
+msgid "Description:"
+msgstr "Descripción:"
+
#: editor/dependency_editor.cpp
msgid "Search Replacement For:"
msgstr "Buscar Reemplazo Para:"
@@ -862,6 +642,10 @@ msgid "Owners Of:"
msgstr "Dueños De:"
#: editor/dependency_editor.cpp
+msgid "Remove selected files from the project? (no undo)"
+msgstr "Quitar los archivos seleccionados del proyecto? (imposible deshacer)"
+
+#: editor/dependency_editor.cpp
msgid ""
"The files being removed are required by other resources in order for them to "
"work.\n"
@@ -872,8 +656,8 @@ msgstr ""
"Quitarlos de todos modos? (imposible deshacer)"
#: editor/dependency_editor.cpp
-msgid "Remove selected files from the project? (no undo)"
-msgstr "Quitar los archivos seleccionados del proyecto? (imposible deshacer)"
+msgid "Cannot remove:\n"
+msgstr "No se puede remover:\n"
#: editor/dependency_editor.cpp
msgid "Error loading:"
@@ -940,19 +724,12 @@ msgid "Godot Engine contributors"
msgstr "Colaboradores de Godot Engine"
#: editor/editor_about.cpp
-#, fuzzy
-msgid "Authors"
-msgstr "Autor:"
-
-#: editor/editor_about.cpp
-#, fuzzy
msgid "Project Founders"
-msgstr "Gestor de Proyectos"
+msgstr "Fundadores del Proyecto"
#: editor/editor_about.cpp
-#, fuzzy
msgid "Lead Developer"
-msgstr "Desarrolladores"
+msgstr "Desarrollador Principal"
#: editor/editor_about.cpp editor/project_manager.cpp
msgid "Project Manager"
@@ -963,12 +740,44 @@ msgid "Developers"
msgstr "Desarrolladores"
#: editor/editor_about.cpp
+msgid "Authors"
+msgstr "Autores"
+
+#: editor/editor_about.cpp
+msgid "Platinum Sponsors"
+msgstr "Sponsor Platino"
+
+#: editor/editor_about.cpp
+msgid "Gold Sponsors"
+msgstr "Sponsor Oro"
+
+#: editor/editor_about.cpp
+msgid "Mini Sponsors"
+msgstr "Mini Sponsors"
+
+#: editor/editor_about.cpp
+msgid "Gold Donors"
+msgstr "Donantes Oro"
+
+#: editor/editor_about.cpp
+msgid "Silver Donors"
+msgstr "Donantes Plata"
+
+#: editor/editor_about.cpp
+msgid "Bronze Donors"
+msgstr "Donantes Bronce"
+
+#: editor/editor_about.cpp
+msgid "Donors"
+msgstr "Donantes"
+
+#: editor/editor_about.cpp
msgid "License"
-msgstr ""
+msgstr "Licencia"
#: editor/editor_about.cpp
msgid "Thirdparty License"
-msgstr ""
+msgstr "Licencia de Terceros"
#: editor/editor_about.cpp
msgid ""
@@ -977,104 +786,108 @@ msgid ""
"is an exhaustive list of all such thirdparty components with their "
"respective copyright statements and license terms."
msgstr ""
+"Godot Engine depende de un número de licencias de terceros, libres y de "
+"código abierto, todas compatibles con los términos de su licencia MIT. La "
+"siguiente es una lista exhaustiva de los mencionados componentes de terceros "
+"con sus respectivas declaraciones de copyright y términos de licencia."
#: editor/editor_about.cpp
-#, fuzzy
msgid "All Components"
-msgstr "Contenido:"
+msgstr "Todos los Componentes"
#: editor/editor_about.cpp
-#, fuzzy
msgid "Components"
-msgstr "Contenido:"
+msgstr "Componentes"
#: editor/editor_about.cpp
msgid "Licenses"
-msgstr ""
+msgstr "Licencias"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Error opening package file, not in zip format."
-msgstr ""
+msgstr "Error al abrir el archivo de paquete. No está en formato zip."
#: editor/editor_asset_installer.cpp
-#, fuzzy
msgid "Uncompressing Assets"
-msgstr "Sin Comprimir"
+msgstr "Descomprimiendo Assets"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package Installed Successfully!"
msgstr "El Paquete se Instaló Exitosamente!"
#: editor/editor_asset_installer.cpp
-#, fuzzy
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Success!"
+msgstr "Conseguido!"
+
+#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/project_manager.cpp
+msgid "Install"
+msgstr "Instalar"
+
+#: editor/editor_asset_installer.cpp
msgid "Package Installer"
-msgstr "El Paquete se Instaló Exitosamente!"
+msgstr "Instalador de Paquetes"
#: editor/editor_audio_buses.cpp
msgid "Speakers"
-msgstr ""
+msgstr "Parlantes"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Add Effect"
-msgstr "Agregar Evento"
+msgstr "Agregar Efecto"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Rename Audio Bus"
-msgstr "Abrir Layout de Bus de Audio"
+msgstr "Renombrar Bus de Audio"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Toggle Audio Bus Solo"
-msgstr "Abrir Layout de Bus de Audio"
+msgstr "Act./Desact. Solo de Bus de Audio"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Toggle Audio Bus Mute"
-msgstr "Abrir Layout de Bus de Audio"
+msgstr "Slienciar/Desilenciar Bus de Audio"
#: editor/editor_audio_buses.cpp
msgid "Toggle Audio Bus Bypass Effects"
-msgstr ""
+msgstr "Act./Desact. Bypass de Efectos de Audio Bus"
#: editor/editor_audio_buses.cpp
msgid "Select Audio Bus Send"
-msgstr ""
+msgstr "Seleccionar Envío de Audio Bus"
#: editor/editor_audio_buses.cpp
msgid "Add Audio Bus Effect"
-msgstr ""
+msgstr "Agregar Efecto de Audio Bus"
#: editor/editor_audio_buses.cpp
msgid "Move Bus Effect"
-msgstr ""
+msgstr "Mover Efecto de Bus"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Delete Bus Effect"
-msgstr "Eliminar Seleccionados"
+msgstr "Eliminar Efecto de Bus"
#: editor/editor_audio_buses.cpp
msgid "Audio Bus, Drag and Drop to rearrange."
-msgstr ""
-
-#: editor/editor_audio_buses.cpp
-#, fuzzy
-msgid "Bus options"
-msgstr "Opciones de Subescena"
+msgstr "Audio Bus, Arrastrar y Soltar para reordenar."
#: editor/editor_audio_buses.cpp
msgid "Solo"
-msgstr ""
+msgstr "Solo"
#: editor/editor_audio_buses.cpp
msgid "Mute"
-msgstr ""
+msgstr "Silenciado"
#: editor/editor_audio_buses.cpp
msgid "Bypass"
-msgstr ""
+msgstr "Bypass"
+
+#: editor/editor_audio_buses.cpp
+msgid "Bus options"
+msgstr "Opciones de Bus"
#: editor/editor_audio_buses.cpp editor/plugins/tile_map_editor_plugin.cpp
#: editor/scene_tree_dock.cpp
@@ -1082,33 +895,36 @@ msgid "Duplicate"
msgstr "Duplicar"
#: editor/editor_audio_buses.cpp
-#, fuzzy
+msgid "Reset Volume"
+msgstr "Resetear Volumen"
+
+#: editor/editor_audio_buses.cpp
msgid "Delete Effect"
-msgstr "Eliminar Seleccionados"
+msgstr "Eliminar Efecto"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Add Audio Bus"
-msgstr "Agregar Bus"
+msgstr "Agregar Bus de Audio"
#: editor/editor_audio_buses.cpp
msgid "Master bus can't be deleted!"
-msgstr ""
+msgstr "El bus maestro no puede ser eliminado!"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Delete Audio Bus"
-msgstr "Eliminar Layout"
+msgstr "Eliminar Bus de Audio"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Duplicate Audio Bus"
-msgstr "Duplicar Animación"
+msgstr "Duplicar Bus de Audio"
+
+#: editor/editor_audio_buses.cpp
+msgid "Reset Bus Volume"
+msgstr "Resetear Volumen de Bus"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Move Audio Bus"
-msgstr "Mover Acción"
+msgstr "Mover Bus de Audio"
#: editor/editor_audio_buses.cpp
msgid "Save Audio Bus Layout As.."
@@ -1124,32 +940,28 @@ msgstr "Abrir Layout de Bus de Audio"
#: editor/editor_audio_buses.cpp
msgid "There is no 'res://default_bus_layout.tres' file."
-msgstr ""
+msgstr "No hay nigún archivo 'res://default_bus_layout.tres'."
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Invalid file, not an audio bus layout."
-msgstr ""
-"Extension de archivo inválida.\n"
-"Usá .fnt, por favor."
+msgstr "Archivo inválido. No es un layout de bus de audio."
#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr "Agregar Bus"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Create a new Bus Layout."
-msgstr "Crear Nuevo Recurso"
+msgstr "Crear un nuevo Layout Bus."
-#: editor/editor_audio_buses.cpp editor/script_create_dialog.cpp
+#: editor/editor_audio_buses.cpp editor/property_editor.cpp
+#: editor/script_create_dialog.cpp
msgid "Load"
msgstr "Cargar"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Load an existing Bus Layout."
-msgstr "Cargar un recurso existente desde disco y editarlo."
+msgstr "Cargar un Bus Layout existente."
#: editor/editor_audio_buses.cpp
#: editor/plugins/animation_player_editor_plugin.cpp
@@ -1157,18 +969,16 @@ msgid "Save As"
msgstr "Guardar Como"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Save this Bus Layout to a file."
-msgstr "Guardar Layout de Bus de Audio Como.."
+msgstr "Guardar este Bus Layout a un archivo."
#: editor/editor_audio_buses.cpp editor/import_dock.cpp
-#, fuzzy
msgid "Load Default"
-msgstr "Por Defecto"
+msgstr "Cargar Valores por Defecto"
#: editor/editor_audio_buses.cpp
msgid "Load the default Bus Layout."
-msgstr ""
+msgstr "Cargar el Bus Layout predeterminado."
#: editor/editor_autoload_settings.cpp
msgid "Invalid name."
@@ -1241,7 +1051,7 @@ msgid "Rearrange Autoloads"
msgstr "Reordenar Autoloads"
#: editor/editor_autoload_settings.cpp editor/editor_file_dialog.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp scene/gui/file_dialog.cpp
+#: scene/gui/file_dialog.cpp
msgid "Path:"
msgstr "Ruta:"
@@ -1249,9 +1059,7 @@ msgstr "Ruta:"
msgid "Node Name:"
msgstr "Nombre de Nodo:"
-#: editor/editor_autoload_settings.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp editor/project_manager.cpp
+#: editor/editor_autoload_settings.cpp editor/project_manager.cpp
msgid "Name"
msgstr "Nombre"
@@ -1276,27 +1084,27 @@ msgid "Updating scene.."
msgstr "Actualizando escena.."
#: editor/editor_dir_dialog.cpp
-#, fuzzy
msgid "Please select a base directory first"
-msgstr "Por favor guardá la escena primero."
+msgstr "Por favor elegí un directorio base primero"
#: editor/editor_dir_dialog.cpp
msgid "Choose a Directory"
msgstr "Elegí un Directorio"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Create Folder"
msgstr "Crear Carpeta"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: editor/editor_plugin_settings.cpp editor/plugins/theme_editor_plugin.cpp
-#: editor/project_export.cpp scene/gui/file_dialog.cpp
+#: editor/editor_plugin_settings.cpp editor/filesystem_dock.cpp
+#: editor/plugins/theme_editor_plugin.cpp editor/project_export.cpp
+#: scene/gui/file_dialog.cpp
msgid "Name:"
msgstr "Nombre:"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Could not create folder."
msgstr "No se pudo crear la carpeta."
@@ -1316,30 +1124,6 @@ msgstr "Empaquetando"
msgid "Template file not found:\n"
msgstr "Plantilla no encontrada:\n"
-#: editor/editor_export.cpp
-msgid "Added:"
-msgstr "Agregado:"
-
-#: editor/editor_export.cpp
-msgid "Removed:"
-msgstr "Removido:"
-
-#: editor/editor_export.cpp
-msgid "Error saving atlas:"
-msgstr "Error al guardar atlas:"
-
-#: editor/editor_export.cpp
-msgid "Could not save atlas subtexture:"
-msgstr "No se pudo guardar la subtextura de altas:"
-
-#: editor/editor_export.cpp
-msgid "Exporting for %s"
-msgstr "Exportando para %s"
-
-#: editor/editor_export.cpp
-msgid "Setting Up.."
-msgstr "Configurando.."
-
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "File Exists, Overwrite?"
msgstr "El Archivo Existe, Sobreescribir?"
@@ -1424,6 +1208,10 @@ msgstr "Subir Favorito"
msgid "Move Favorite Down"
msgstr "Bajar Favorito"
+#: editor/editor_file_dialog.cpp
+msgid "Go to parent folder"
+msgstr "Ir a carpeta padre"
+
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Directories & Files:"
msgstr "Directorios y Archivos:"
@@ -1438,10 +1226,6 @@ msgid "File:"
msgstr "Archivo:"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
-msgid "Filter:"
-msgstr "Filtro:"
-
-#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Must use a valid extension."
msgstr "Debe ser una extensión válida."
@@ -1466,6 +1250,10 @@ msgstr "Lista de Clases:"
msgid "Search Classes"
msgstr "Buscar Clases"
+#: editor/editor_help.cpp editor/plugins/spatial_editor_plugin.cpp
+msgid "Top"
+msgstr "Cima"
+
#: editor/editor_help.cpp editor/property_editor.cpp
msgid "Class:"
msgstr "Clase:"
@@ -1482,15 +1270,27 @@ msgstr "Heredada por:"
msgid "Brief Description:"
msgstr "Descripción Breve:"
+#: editor/editor_help.cpp
+msgid "Members"
+msgstr "Miembros"
+
#: editor/editor_help.cpp modules/visual_script/visual_script_editor.cpp
msgid "Members:"
msgstr "Miembros:"
#: editor/editor_help.cpp
+msgid "Public Methods"
+msgstr "Métodos Públicos"
+
+#: editor/editor_help.cpp
msgid "Public Methods:"
msgstr "Métodos Públicos:"
#: editor/editor_help.cpp
+msgid "GUI Theme Items"
+msgstr "Items de Tema de la GUI"
+
+#: editor/editor_help.cpp
msgid "GUI Theme Items:"
msgstr "Items de Tema de la GUI:"
@@ -1499,54 +1299,85 @@ msgid "Signals:"
msgstr "Señales:"
#: editor/editor_help.cpp
-#, fuzzy
+msgid "Enumerations"
+msgstr "Enumeraciones"
+
+#: editor/editor_help.cpp
msgid "Enumerations:"
-msgstr "Animaciones"
+msgstr "Enumeraciones:"
#: editor/editor_help.cpp
msgid "enum "
-msgstr ""
+msgstr "enum "
+
+#: editor/editor_help.cpp
+msgid "Constants"
+msgstr "Constantes"
#: editor/editor_help.cpp
msgid "Constants:"
msgstr "Constantes:"
#: editor/editor_help.cpp
+msgid "Description"
+msgstr "Descripción"
+
+#: editor/editor_help.cpp
+msgid "Properties"
+msgstr "Propiedades"
+
+#: editor/editor_help.cpp
msgid "Property Description:"
msgstr "Descripción de Propiedad:"
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this property. Please help us by "
+"[color=$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+"Actualmente no existe descripción para esta propiedad. Por favor ayudanos "
+"[color=$color][url=$url]contribuyendo una[/url][/color]!"
+
+#: editor/editor_help.cpp
+msgid "Methods"
+msgstr "Métodos"
+
+#: editor/editor_help.cpp
msgid "Method Description:"
msgstr "Descripción de Métodos:"
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this method. Please help us by [color="
+"$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+"Actualmente no existe descripción para este método. Por favor ayudanos "
+"[color=$color][url=$url]contribuyendo una[/url][/color]!"
+
+#: editor/editor_help.cpp
msgid "Search Text"
msgstr "Texto de Búsqueda"
#: editor/editor_log.cpp
-#, fuzzy
msgid "Output:"
-msgstr " Salida:"
+msgstr "Salida:"
#: editor/editor_log.cpp editor/plugins/animation_tree_editor_plugin.cpp
-#: editor/plugins/rich_text_editor_plugin.cpp editor/property_editor.cpp
-#: editor/script_editor_debugger.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/property_editor.cpp editor/script_editor_debugger.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Clear"
msgstr "Limpiar"
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Error saving resource!"
msgstr "Error al guardar el recurso!"
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Save Resource As.."
msgstr "Guardar Recurso Como.."
-#: editor/editor_node.cpp editor/export_template_manager.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "I see.."
msgstr "Ya Veo.."
@@ -1563,6 +1394,26 @@ msgid "Error while saving."
msgstr "Error al grabar."
#: editor/editor_node.cpp
+msgid "Can't open '%s'."
+msgstr "No se puede abrir '%s'."
+
+#: editor/editor_node.cpp
+msgid "Error while parsing '%s'."
+msgstr "Error parsear '%s'."
+
+#: editor/editor_node.cpp
+msgid "Unexpected end of file '%s'."
+msgstr "Final de archivo inesperado en '%s'."
+
+#: editor/editor_node.cpp
+msgid "Missing '%s' or its dependencies."
+msgstr "No se encuentra '%s' o sus dependecias."
+
+#: editor/editor_node.cpp
+msgid "Error while loading '%s'."
+msgstr "Error al cargar '%s'."
+
+#: editor/editor_node.cpp
msgid "Saving Scene"
msgstr "Guardar Escena"
@@ -1575,9 +1426,8 @@ msgid "Creating Thumbnail"
msgstr "Creando Miniatura"
#: editor/editor_node.cpp
-#, fuzzy
msgid "This operation can't be done without a tree root."
-msgstr "Esta operación no puede hacerse sin una escena."
+msgstr "Esta operación no puede hacerse sin una raíz de árbol."
#: editor/editor_node.cpp
msgid ""
@@ -1623,6 +1473,46 @@ msgid "Restored default layout to base settings."
msgstr "Se restauró el layout por defecto a sus seteos base."
#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was imported, so it's not editable.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+"Este recurso pertenece a una escena que fue importada, por lo tanto no es "
+"editable.\n"
+"Por favor leé la documentación relevante a importar escenas para entender "
+"mejor este workflow."
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was instanced or inherited.\n"
+"Changes to it will not be kept when saving the current scene."
+msgstr ""
+"Este recurso pertenece a una escena que fue instanciada o heredada.\n"
+"Los cambios que se le realicen no perduraran al guardar la escena actual."
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource was imported, so it's not editable. Change its settings in the "
+"import panel and then re-import."
+msgstr ""
+"Este recurso fue importado, por ende no es editable. Cambiá sus ajustes en "
+"el panel de importación y luego reimportá."
+
+#: editor/editor_node.cpp
+msgid ""
+"This scene was imported, so changes to it will not be kept.\n"
+"Instancing it or inheriting will allow making changes to it.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+"Esta escena fue importada, por ende los cambios que se le realicen no "
+"perduraran.\n"
+"Instanciá o hereda para poder realizar cambios.\n"
+"Por favor leé la documentación relevante a importar escenas para entender "
+"mejor este workflow."
+
+#: editor/editor_node.cpp
msgid "Copy Params"
msgstr "Copiar Params"
@@ -1711,13 +1601,12 @@ msgid "Quick Open Script.."
msgstr "Abrir Script Rapido.."
#: editor/editor_node.cpp
-#, fuzzy
msgid "Save & Close"
-msgstr "Guardar un Archivo"
+msgstr "Guardar y Cerrar"
#: editor/editor_node.cpp
msgid "Save changes to '%s' before closing?"
-msgstr ""
+msgstr "Guardar cambios a '%s' antes de cerrar?"
#: editor/editor_node.cpp
msgid "Save Scene As.."
@@ -1748,9 +1637,8 @@ msgid "Export Tile Set"
msgstr "Exportar Tile Set"
#: editor/editor_node.cpp
-#, fuzzy
msgid "This operation can't be done without a selected node."
-msgstr "Esta operación no puede hacerse sin una escena."
+msgstr "Esta operación no puede hacerse sin un nodo seleccionado."
#: editor/editor_node.cpp
msgid "Current scene not saved. Open anyway?"
@@ -1781,42 +1669,62 @@ msgid "Exit the editor?"
msgstr "Salir del editor?"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Open Project Manager?"
-msgstr "Gestor de Proyectos"
+msgstr "Abrir Gestor de Proyectos?"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Save & Quit"
-msgstr "Guardar un Archivo"
+msgstr "Guardar y Salir"
#: editor/editor_node.cpp
msgid "Save changes to the following scene(s) before quitting?"
-msgstr ""
+msgstr "Guardar cambios a la(s) siguiente(s) escena(s) antes de salir?"
#: editor/editor_node.cpp
msgid "Save changes the following scene(s) before opening Project Manager?"
msgstr ""
+"Guardar cambios a la(s) siguiente(s) escena(s) antes de abrir el Gestor de "
+"Proyectos?"
+
+#: editor/editor_node.cpp
+msgid ""
+"This option is deprecated. Situations where refresh must be forced are now "
+"considered a bug. Please report."
+msgstr ""
+"Esta opción esta deprecada. Las situaciones donde se debe forzar un refresco "
+"son ahora consideradas bugs. Por favor reportalo."
#: editor/editor_node.cpp
msgid "Pick a Main Scene"
msgstr "Elegí una Escena Principal"
#: editor/editor_node.cpp
-msgid "Unable to enable addon plugin at: '"
-msgstr ""
+#, fuzzy
+msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
+msgstr "No se pudo activar el plugin de addon en : '"
#: editor/editor_node.cpp
-msgid "' parsing of config failed."
+#, fuzzy
+msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
msgstr ""
+"No se pudo encontrar el campo script para el plugin de addon en: 'res://"
+"addons/"
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/"
-msgstr ""
+#, fuzzy
+msgid "Unable to load addon script from path: '%s'."
+msgstr "No se pudo cargar el script de addon desde la ruta: '"
#: editor/editor_node.cpp
-msgid "Unable to load addon script from path: '"
-msgstr ""
+#, fuzzy
+msgid ""
+"Unable to load addon script from path: '%s' Base type is not EditorPlugin."
+msgstr "No se pudo cargar el script de addon desde la ruta: '"
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Unable to load addon script from path: '%s' Script is not in tool mode."
+msgstr "No se pudo cargar el script de addon desde la ruta: '"
#: editor/editor_node.cpp
msgid ""
@@ -1828,7 +1736,7 @@ msgstr ""
"Para realizar cambios, se debe crear una nueva escena heredada."
#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/scene_tree_dock.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Ugh"
msgstr "Ugh"
@@ -1842,14 +1750,14 @@ msgstr ""
"proyecto."
#: editor/editor_node.cpp
-msgid "Error loading scene."
-msgstr "Error al cargar la escena."
-
-#: editor/editor_node.cpp
msgid "Scene '%s' has broken dependencies:"
msgstr "La escena '%s' tiene dependencias rotas:"
#: editor/editor_node.cpp
+msgid "Clear Recent Scenes"
+msgstr "Reestablecer Escenas Recientes"
+
+#: editor/editor_node.cpp
msgid "Save Layout"
msgstr "Guardar Layout"
@@ -1879,11 +1787,10 @@ msgid "Distraction Free Mode"
msgstr "Modo Sin Distracciones"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Toggle distraction-free mode."
-msgstr "Modo Sin Distracciones"
+msgstr "Act./Desact. modo sin distracciones."
-#: editor/editor_node.cpp editor/io_plugins/editor_scene_import_plugin.cpp
+#: editor/editor_node.cpp
msgid "Scene"
msgstr "Escena"
@@ -2122,6 +2029,10 @@ msgstr "Q&A"
msgid "Issue Tracker"
msgstr "Issue Tracker"
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+msgid "Community"
+msgstr "Comunidad"
+
#: editor/editor_node.cpp
msgid "About"
msgstr "Acerca de"
@@ -2130,7 +2041,7 @@ msgstr "Acerca de"
msgid "Play the project."
msgstr "Reproducir el proyecto."
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Play"
msgstr "Reproducir"
@@ -2146,7 +2057,7 @@ msgstr "Pausar la Escena"
msgid "Stop the scene."
msgstr "Parar la escena."
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Stop"
msgstr "Detener"
@@ -2219,6 +2130,15 @@ msgid "Object properties."
msgstr "Propiedades del objeto."
#: editor/editor_node.cpp
+msgid "Changes may be lost!"
+msgstr "Podrían perderse los cambios!"
+
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Import"
+msgstr "Importar"
+
+#: editor/editor_node.cpp
msgid "FileSystem"
msgstr "FileSystem"
@@ -2232,15 +2152,7 @@ msgstr "Salida"
#: editor/editor_node.cpp
msgid "Don't Save"
-msgstr ""
-
-#: editor/editor_node.cpp editor/editor_reimport_dialog.cpp
-msgid "Re-Import"
-msgstr "Reimportar"
-
-#: editor/editor_node.cpp editor/editor_plugin_settings.cpp
-msgid "Update"
-msgstr "Actualizar"
+msgstr "No Guardar"
#: editor/editor_node.cpp
msgid "Import Templates From ZIP File"
@@ -2267,9 +2179,8 @@ msgid "Open & Run a Script"
msgstr "Abrir y Correr un Script"
#: editor/editor_node.cpp
-#, fuzzy
msgid "New Inherited"
-msgstr "Nueva Escena Heredada.."
+msgstr "Nuevo Heredado"
#: editor/editor_node.cpp
msgid "Load Errors"
@@ -2303,11 +2214,28 @@ msgstr "Abrir el Editor siguiente"
msgid "Open the previous Editor"
msgstr "Abrir el Editor anterior"
+#: editor/editor_plugin.cpp
+msgid "Creating Mesh Previews"
+msgstr "Creando Vistas Previas de Mesh/es"
+
+#: editor/editor_plugin.cpp
+msgid "Thumbnail.."
+msgstr "Miniatura.."
+
#: editor/editor_plugin_settings.cpp
msgid "Installed Plugins:"
msgstr "Plugins Instalados:"
#: editor/editor_plugin_settings.cpp
+msgid "Update"
+msgstr "Actualizar"
+
+#: editor/editor_plugin_settings.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Version:"
+msgstr "Version:"
+
+#: editor/editor_plugin_settings.cpp
msgid "Author:"
msgstr "Autor:"
@@ -2340,7 +2268,8 @@ msgid "Frame %"
msgstr "Frame %"
#: editor/editor_profiler.cpp
-msgid "Fixed Frame %"
+#, fuzzy
+msgid "Physics Frame %"
msgstr "Fixed Frame %"
#: editor/editor_profiler.cpp editor/script_editor_debugger.cpp
@@ -2359,35 +2288,18 @@ msgstr "Propio"
msgid "Frame #:"
msgstr "Frame #:"
-#: editor/editor_reimport_dialog.cpp
-msgid "Please wait for scan to complete."
-msgstr "Por favor aguarda a que el scan termine."
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Current scene must be saved to re-import."
-msgstr "La escena actual debe ser guardada para reimportar."
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Save & Re-Import"
-msgstr "Guardar y Reimportar"
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Importing"
-msgstr "Reimportando"
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Import Changed Resources"
-msgstr "Reimportar Recursos Cambiados"
-
#: editor/editor_run_native.cpp
msgid "Select device from the list"
-msgstr ""
+msgstr "Seleccionar dispositivo de la lista"
#: editor/editor_run_native.cpp
msgid ""
"No runnable export preset found for this platform.\n"
"Please add a runnable preset in the export menu."
msgstr ""
+"No se encontró ningún preset de exportación ejecutable para esta "
+"plataforma.\n"
+"Por favor agregá un preset ejecutable en el menú de exportación."
#: editor/editor_run_script.cpp
msgid "Write your logic in the _run() method."
@@ -2490,10 +2402,6 @@ msgid "Importing:"
msgstr "Importando:"
#: editor/export_template_manager.cpp
-msgid "Loading Export Templates"
-msgstr "Cargando Plantillas de Exportación"
-
-#: editor/export_template_manager.cpp
msgid "Current Version:"
msgstr "Version Actual:"
@@ -2528,60 +2436,73 @@ msgid "Cannot navigate to '"
msgstr "No se puede navegar a '"
#: editor/filesystem_dock.cpp
-#, fuzzy
+msgid "View items as a grid of thumbnails"
+msgstr "Ver items como una grilla de miniaturas"
+
+#: editor/filesystem_dock.cpp
+msgid "View items as a list"
+msgstr "Ver items como una lista"
+
+#: editor/filesystem_dock.cpp
msgid ""
"\n"
-"Status: Needs Re-Import"
-msgstr "Guardar y Reimportar"
+"Status: Import of file failed. Please fix file and reimport manually."
+msgstr ""
+"\n"
+"Estado: Fallo la importación del archivo. Por favor arreglá el archivo y "
+"reimportá manualmente."
#: editor/filesystem_dock.cpp
-#, fuzzy
msgid ""
"\n"
"Source: "
-msgstr "Fuente:"
+msgstr ""
+"\n"
+"Fuente: "
#: editor/filesystem_dock.cpp
-msgid "Same source and destination files, doing nothing."
-msgstr "Archivos de origen y destino iguales, no se realizará ninguna acción."
+msgid "Cannot move/rename resources root."
+msgstr "No se puede mover/renombrar la raiz de recursos."
#: editor/filesystem_dock.cpp
-msgid "Target file exists, can't overwrite. Delete first."
-msgstr ""
+msgid "Cannot move a folder into itself.\n"
+msgstr "No se puede mover una carpeta dento de si misma.\n"
#: editor/filesystem_dock.cpp
-msgid "Same source and destination paths, doing nothing."
-msgstr "Ruta de origen y destino iguales, no se realizará ninguna acción."
+msgid "Error moving:\n"
+msgstr "Error al mover:\n"
#: editor/filesystem_dock.cpp
-msgid "Can't move directories to within themselves."
-msgstr "No se pueden mover directorios dentro de si mismos."
+msgid "Unable to update dependencies:\n"
+msgstr "No se pudieron actualizar las dependencias:\n"
#: editor/filesystem_dock.cpp
-msgid "Can't rename deps for:\n"
-msgstr ""
+msgid "No name provided"
+msgstr "No se indicó ningún nombre"
#: editor/filesystem_dock.cpp
-#, fuzzy
-msgid "Error moving file:\n"
-msgstr "Error al cargar la imagen:"
+msgid "Provided name contains invalid characters"
+msgstr "El nombre indicado contiene caracteres inválidos"
#: editor/filesystem_dock.cpp
-#, fuzzy
-msgid "Error moving dir:\n"
-msgstr "Error al importar:"
+msgid "No name provided."
+msgstr "No se indicó ningún nombre."
#: editor/filesystem_dock.cpp
-msgid "Can't operate on '..'"
-msgstr "No se puede operar en '..'"
+msgid "Name contains invalid characters."
+msgstr "El nombre indicado contiene caracteres inválidos."
#: editor/filesystem_dock.cpp
-msgid "Pick New Name and Location For:"
-msgstr "Elejí un Nuevo Nombre y Ubicación Para:"
+msgid "A file or folder with this name already exists."
+msgstr "Un archivo o carpeta con este nombre ya existe."
#: editor/filesystem_dock.cpp
-msgid "No files selected!"
-msgstr "Ningún Archivo seleccionado!"
+msgid "Renaming file:"
+msgstr "Renombrando archivo:"
+
+#: editor/filesystem_dock.cpp
+msgid "Renaming folder:"
+msgstr "Renombrar carpeta:"
#: editor/filesystem_dock.cpp
msgid "Expand all"
@@ -2592,40 +2513,36 @@ msgid "Collapse all"
msgstr "Colapsar todos"
#: editor/filesystem_dock.cpp
-msgid "Show In File Manager"
-msgstr "Mostrar en Gestor de Archivos"
-
-#: editor/filesystem_dock.cpp
-msgid "Instance"
-msgstr "Instancia"
+msgid "Copy Path"
+msgstr "Copiar Ruta"
#: editor/filesystem_dock.cpp
-msgid "Edit Dependencies.."
-msgstr "Editar Dependencias.."
+msgid "Rename.."
+msgstr "Renombrar.."
#: editor/filesystem_dock.cpp
-msgid "View Owners.."
-msgstr "Ver Dueños.."
+msgid "Move To.."
+msgstr "Mover A.."
#: editor/filesystem_dock.cpp
-msgid "Copy Path"
-msgstr "Copiar Ruta"
+msgid "New Folder.."
+msgstr "Nueva Carpeta.."
#: editor/filesystem_dock.cpp
-msgid "Rename or Move.."
-msgstr "Renombrar o Mover.."
+msgid "Show In File Manager"
+msgstr "Mostrar en Gestor de Archivos"
#: editor/filesystem_dock.cpp
-msgid "Move To.."
-msgstr "Mover A.."
+msgid "Instance"
+msgstr "Instancia"
#: editor/filesystem_dock.cpp
-msgid "Info"
-msgstr "Info"
+msgid "Edit Dependencies.."
+msgstr "Editar Dependencias.."
#: editor/filesystem_dock.cpp
-msgid "Re-Import.."
-msgstr "Reimportando.."
+msgid "View Owners.."
+msgstr "Ver Dueños.."
#: editor/filesystem_dock.cpp
msgid "Previous Directory"
@@ -2653,11 +2570,18 @@ msgid ""
"Scanning Files,\n"
"Please Wait.."
msgstr ""
+"Examinando Archivos,\n"
+"Aguardá, por favor."
#: editor/filesystem_dock.cpp
msgid "Move"
msgstr "Mover"
+#: editor/filesystem_dock.cpp editor/plugins/animation_tree_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Rename"
+msgstr "Renombrar"
+
#: editor/groups_editor.cpp
msgid "Add to Group"
msgstr "Agregar al Grupo"
@@ -2667,74 +2591,81 @@ msgid "Remove from Group"
msgstr "Quitar del Grupo"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Import as Single Scene"
-msgstr "Importando Escena.."
+msgstr "Importar como Escena Única"
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Animations"
+msgstr "Importar con Animaciones Separadas"
#: editor/import/resource_importer_scene.cpp
msgid "Import with Separate Materials"
-msgstr ""
+msgstr "Importar con Materiales Separados"
#: editor/import/resource_importer_scene.cpp
msgid "Import with Separate Objects"
-msgstr ""
+msgstr "Importar con Objetos Separados"
#: editor/import/resource_importer_scene.cpp
msgid "Import with Separate Objects+Materials"
-msgstr ""
+msgstr "Importar con Objetos+Materiales Separados"
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Animations"
+msgstr "Importar con Objetos+Animaciones Separados"
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Materials+Animations"
+msgstr "Importar con Materiales+Animaciones Separados"
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Materials+Animations"
+msgstr "Importar con Objetos+Materiales+Animaciones Separados"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Import as Multiple Scenes"
-msgstr "Importar Escena 3D"
+msgstr "Importar como Escenas Múltiples"
#: editor/import/resource_importer_scene.cpp
msgid "Import as Multiple Scenes+Materials"
-msgstr ""
+msgstr "Importar como Escenas+Materiales Múltiples"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Import Scene"
msgstr "Importar Escena"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Importing Scene.."
msgstr "Importando Escena.."
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Running Custom Script.."
msgstr "Ejecutando Script Personalizado.."
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Couldn't load post-import script:"
msgstr "No se pudo cargar el script post importación:"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Invalid/broken script for post-import (check console):"
msgstr "Script para post importación inválido/roto (revisá la consola):"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Error running post-import script:"
msgstr "Error ejecutando el script de post-importacion:"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Saving.."
msgstr "Guardando.."
#: editor/import_dock.cpp
msgid "Set as Default for '%s'"
-msgstr ""
+msgstr "Asignar como Predeterminado para '%s'"
#: editor/import_dock.cpp
msgid "Clear Default for '%s'"
-msgstr ""
+msgstr "Reestablecer Predeterminados para '%s'"
#: editor/import_dock.cpp
msgid " Files"
@@ -2752,577 +2683,6 @@ msgstr "Preseteo.."
msgid "Reimport"
msgstr "Reimportar"
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "No bit masks to import!"
-msgstr "Sin máscaras de bits para importar!"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path is empty."
-msgstr "La ruta de destino está vacía."
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must be a complete resource path."
-msgstr "La ruta de destino debe ser una ruta de recursos completa."
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must exist."
-msgstr "La ruta de destino debe existir."
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Save path is empty!"
-msgstr "La ruta de guardado esta vacía!"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Import BitMasks"
-msgstr "Importar BitMasks"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s):"
-msgstr "Textura(s) de Origen:"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Target Path:"
-msgstr "Ruta de Destino:"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Accept"
-msgstr "Aceptar"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Bit Mask"
-msgstr "Máscara de Bits"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No source font file!"
-msgstr "Sin archivo de tipografías de origen!"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No target font resource!"
-msgstr "Sin recurso de tipografías de destino!"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"Invalid file extension.\n"
-"Please use .font."
-msgstr ""
-"Extension de archivo inválida.\n"
-"Usá .fnt, por favor."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Can't load/process source font."
-msgstr "No se puede cargar/procesar la tipografía de origen."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Couldn't save font."
-msgstr "No se pudo guardar la tipografía."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font:"
-msgstr "Tipografía de Origen:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font Size:"
-msgstr "Tamaño de la Tipografía de Origen:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Dest Resource:"
-msgstr "Recurso de Dest:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "The quick brown fox jumps over the lazy dog."
-msgstr "El veloz murciélago hindú comía feliz cardillo y kiwi."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Test:"
-msgstr "Prueba:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Options:"
-msgstr "Opciones:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Font Import"
-msgstr "Importar Tipografías"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"This file is already a Godot font file, please supply a BMFont type file "
-"instead."
-msgstr ""
-"Este archivo ya es un archivo de tipografías de Godot, por favor suministrar "
-"un archivo tipo BMFont."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Failed opening as BMFont file."
-msgstr "Error al abrir como archivo BMFont."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error initializing FreeType."
-msgstr "Error inicializando FreeType."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Unknown font format."
-msgstr "Formato de tipografía desconocido."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error loading font."
-msgstr "Error cargando tipografía."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Invalid font size."
-msgstr "Tamaño de tipografía inválido."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Invalid font custom source."
-msgstr "Origen personalizado de tipografía inválido."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/plugins/theme_editor_plugin.cpp
-msgid "Font"
-msgstr "Tipografía"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "No meshes to import!"
-msgstr "Sin meshes para importar!"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Single Mesh Import"
-msgstr "Importar Mesh Individual"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Source Mesh(es):"
-msgstr "Importar Mesh(es) de Origen:"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/plugins/mesh_instance_editor_plugin.cpp
-msgid "Mesh"
-msgstr "Mesh"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Surface %d"
-msgstr "Superficie %d"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "No samples to import!"
-msgstr "Sin muestras que importar!"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Import Audio Samples"
-msgstr "Importar Muestras de Audio"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Source Sample(s):"
-msgstr "Muestra(s) de Origen:"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Audio Sample"
-msgstr "Muestra de Audio"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "New Clip"
-msgstr "Nuevo Clip"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Animation Options"
-msgstr "Opciones de Animación"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Flags"
-msgstr "Flags"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Bake FPS:"
-msgstr "Hacer Bake de FPS:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Optimizer"
-msgstr "Optimizar"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Linear Error"
-msgstr "Error Lineal Máximo"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angular Error"
-msgstr "Error Angular Máximo"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angle"
-msgstr "Angulo Máximo"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Clips"
-msgstr "Clips"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Start(s)"
-msgstr "Comienzo(s)"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "End(s)"
-msgstr "Fin(es)"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Loop"
-msgstr "Loop"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Filters"
-msgstr "Filtros"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source path is empty."
-msgstr "La ruta de origen esta vacía."
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't load post-import script."
-msgstr "No se pudo cargar el script post-importación."
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Invalid/broken script for post-import."
-msgstr "Script post-importación inválido o roto."
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Error importing scene."
-msgstr "Error al importar escena."
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import 3D Scene"
-msgstr "Importar Escena 3D"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source Scene:"
-msgstr "Escena de Origen:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Same as Target Scene"
-msgstr "Igual que Escena de Destino"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Shared"
-msgstr "Compartido"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Target Texture Folder:"
-msgstr "Carpeta de Textura de Destino:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Post-Process Script:"
-msgstr "Script de Postprocesado:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Custom Root Node Type:"
-msgstr "Tipo de Nodo Raiz Customizado:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Auto"
-msgstr "Auto"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Root Node Name:"
-msgstr "Nombre del Nodo Raíz:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "The Following Files are Missing:"
-msgstr "Los Siguientes Archivos estan Faltando:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Anyway"
-msgstr "Importar de Todos Modos"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp scene/gui/dialogs.cpp
-msgid "Cancel"
-msgstr "Cancelar"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import & Open"
-msgstr "Importar y Abrir"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Edited scene has not been saved, open imported scene anyway?"
-msgstr ""
-"La escena editada no ha sido guardada, abrir la escena importada de todos "
-"modos?"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Image:"
-msgstr "Importar Imagen:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Can't import a file over itself:"
-msgstr "No se puede importar un archivo sobre si mismo:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't localize path: %s (already local)"
-msgstr "No se pudo localizar la ruta: %s (ya es local)"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "3D Scene Animation"
-msgstr "Animacion de Escena 3D"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Uncompressed"
-msgstr "Sin Comprimir"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossless (PNG)"
-msgstr "Compresión Sin Pérdidas (PNG)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossy (WebP)"
-msgstr "Compresión con Pérdidas (WebP)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress (VRAM)"
-msgstr "Comprimir (VRAM)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Format"
-msgstr "Formato de Textura"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Compression Quality (WebP):"
-msgstr "Calidad de Compresión de Textura (WebP):"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Options"
-msgstr "Opciones de Textura"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Please specify some files!"
-msgstr "Por favor especificá algunos archivos!"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "At least one file needed for Atlas."
-msgstr "Se necesita al menos un archivo para el Atlas."
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Error importing:"
-msgstr "Error al importar:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Only one file is required for large texture."
-msgstr "Solo se requiere un archivo para textura grande."
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Max Texture Size:"
-msgstr "Tamaño Max. de Textura:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for Atlas (2D)"
-msgstr "Importar Texturas para Atlas (2D)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cell Size:"
-msgstr "Tamaño de Celda:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Large Texture"
-msgstr "Textura Grande"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Textures (2D)"
-msgstr "Importar Texturas Grandes (2D)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture"
-msgstr "Textura de Origen"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Base Atlas Texture"
-msgstr "Textura Base de Atlas"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s)"
-msgstr "Textura(s) de Origen"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 2D"
-msgstr "Importar Texturas para 2D"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 3D"
-msgstr "Importar Texturas para 3D"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures"
-msgstr "Importar Texturas"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "2D Texture"
-msgstr "Textura 2D"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "3D Texture"
-msgstr "Textura 3D"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Atlas Texture"
-msgstr "Textura de Atlas"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid ""
-"NOTICE: Importing 2D textures is not mandatory. Just copy png/jpg files to "
-"the project."
-msgstr ""
-"AVISO: Importar texturas 2D no es obligatorio. Simplemente copiá los "
-"archivos png/jpg al proyecto."
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Crop empty space."
-msgstr "Cropear espacio vacio."
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture"
-msgstr "Textura"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Texture"
-msgstr "Importar Textura Grande"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Load Source Image"
-msgstr "Cargar Imagen de Origen"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Slicing"
-msgstr "Rebanar"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Inserting"
-msgstr "Insertando"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Saving"
-msgstr "Guardando"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save large texture:"
-msgstr "No se pudo guardar la textura grande:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Build Atlas For:"
-msgstr "Construir Atlar Para:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Loading Image:"
-msgstr "Cargando Imagen:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't load image:"
-msgstr "No se pudo cargar la imagen:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Converting Images"
-msgstr "Convirtiendo Imágenes"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cropping Images"
-msgstr "Cropeando Imágenes"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Blitting Images"
-msgstr "Haciendo Blitting de Imágenes"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save atlas image:"
-msgstr "No se pudo guardar la imagen de atlas:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save converted texture:"
-msgstr "No se pudo guardar la textura convertida:"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid source!"
-msgstr "Fuente inválida!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid translation source!"
-msgstr "Fuente de traducción inválida!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Column"
-msgstr "Columna"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/script_create_dialog.cpp
-msgid "Language"
-msgstr "Lenguaje"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No items to import!"
-msgstr "Sin elementos para importar!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No target path!"
-msgstr "Sin ruta de destino!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translations"
-msgstr "Importar Traducciones"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Couldn't import!"
-msgstr "No se pudo importar!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translation"
-msgstr "Importar Traducción"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Source CSV:"
-msgstr "CSV de Origen:"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Ignore First Row"
-msgstr "Ignorar Primera Columna"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Compress"
-msgstr "Comprimir"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Add to Project (project.godot)"
-msgstr "Agregar al Proyecto (project.godot)"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Languages:"
-msgstr "Importar Lenguajes:"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Translation"
-msgstr "Traducción"
-
#: editor/multi_node_edit.cpp
msgid "MultiNode Set"
msgstr "Setear MultiNodo"
@@ -3335,6 +2695,48 @@ msgstr "Grupos"
msgid "Select a Node to edit Signals and Groups."
msgstr "Seleccionar un Nodo para editar Señales y Grupos."
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create Poly"
+msgstr "Crear Polígono"
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly"
+msgstr "Editar Polígono"
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Insert Point"
+msgstr "Insertar Punto"
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly (Remove Point)"
+msgstr "Editar Polígono (Remover Punto)"
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Remove Poly And Point"
+msgstr "Remover Polígono y Punto"
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create a new polygon from scratch."
+msgstr "Crear un nuevo polígono de cero."
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid ""
+"Edit existing polygon:\n"
+"LMB: Move Point.\n"
+"Ctrl+LMB: Split Segment.\n"
+"RMB: Erase Point."
+msgstr ""
+"Editar polígono existente:\n"
+"Click izq: Mover Punto.\n"
+"Ctrl+Click izq: Dividir Segmento.\n"
+"Click der: Eliminar Punto."
+
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Toggle Autoplay"
msgstr "Activar/Desact. Autoplay"
@@ -3490,7 +2892,6 @@ msgstr "Nombre de Animación:"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
#: editor/script_create_dialog.cpp
msgid "Error!"
@@ -3518,9 +2919,8 @@ msgid "New name:"
msgstr "Nuevo nombre:"
#: editor/plugins/animation_tree_editor_plugin.cpp
-#, fuzzy
msgid "Edit Filters"
-msgstr "Editar Filtros de Nodo"
+msgstr "Editar Filtros"
#: editor/plugins/animation_tree_editor_plugin.cpp
#: editor/plugins/multimesh_editor_plugin.cpp
@@ -3601,10 +3001,6 @@ msgid "Delete Input"
msgstr "Eliminar Entrada"
#: editor/plugins/animation_tree_editor_plugin.cpp
-msgid "Rename"
-msgstr "Renombrar"
-
-#: editor/plugins/animation_tree_editor_plugin.cpp
msgid "Animation tree is valid."
msgstr "El árbol de animación es válido."
@@ -3660,65 +3056,181 @@ msgstr "Editar Filtros de Nodo"
msgid "Filters.."
msgstr "Filtros.."
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing %d Triangles:"
-msgstr "Parseando %d Triángulos:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Free"
+msgstr "Libre"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Triangle #"
-msgstr "Triangulo #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Contents:"
+msgstr "Contenido:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Light Baker Setup:"
-msgstr "Configuración de Baker de Luces:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "View Files"
+msgstr "Ver Archivos"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing Geometry"
-msgstr "Parseando Geometría"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve hostname:"
+msgstr "No se ha podido resolver el nombre del host:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Fixing Lights"
-msgstr "Fijando/Corrigiendo Luces"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve."
+msgstr "No se ha podido resolver."
-#: editor/plugins/baked_light_baker.cpp
-msgid "Making BVH"
-msgstr "Creando BVH"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connection error, please try again."
+msgstr "Error de conexión, por favor intentá de nuevo."
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Light Octree"
-msgstr "Creando Octree de Luces"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't connect."
+msgstr "No se puede conectar."
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Octree Texture"
-msgstr "Creando Octree de Texturas"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't connect to host:"
+msgstr "No se puede conectar al host:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Transfer to Lightmaps:"
-msgstr "Transferencia a Lightmaps:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response from host:"
+msgstr "No hay respuesta desde el host:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Allocating Texture #"
-msgstr "Asignando Textura #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response."
+msgstr "Sin respuesta."
-#: editor/plugins/baked_light_baker.cpp
-msgid "Baking Triangle #"
-msgstr "Haciendo Bake de Triangulo #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, return code:"
+msgstr "Solicitud fallida. Código de retorno:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Post-Processing Texture #"
-msgstr "Postprocesando Textura #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Req. Failed."
+msgstr "Solicitud fallida."
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Bake!"
-msgstr "Hacer Bake!"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, too many redirects"
+msgstr "Solicitud fallida, demasiadas redireccinoes"
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Reset the lightmap octree baking process (start over)."
-msgstr ""
-"Resetear el proceso de bake del octree de mapa de luces (empezar de nuevo)."
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Redirect Loop."
+msgstr "Bucle de redireccionamiento."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed:"
+msgstr "Fallido:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Bad download hash, assuming file has been tampered with."
+msgstr "Hash de descarga incorrecto, asumiendo que el archivo fue manipulado."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Expected:"
+msgstr "Esperado:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Got:"
+msgstr "Recibido:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed sha256 hash check"
+msgstr "Fallo el chequeo del hash sha256"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Asset Download Error:"
+msgstr "Error de Descarga del Asset:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Fetching:"
+msgstr "Obteniendo:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Resolving.."
+msgstr "Resolviendo.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connecting.."
+msgstr "Conectando.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Requesting.."
+msgstr "Solicitando.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Error making request"
+msgstr "Error al realizar la solicitud"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Idle"
+msgstr "Desocupado"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Retry"
+msgstr "Reintentar"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download Error"
+msgstr "Error de Descarga"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download for this asset is already in progress!"
+msgstr "La descarga de este asset ya esta en progreso!"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "first"
+msgstr "primero"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "prev"
+msgstr "anterior"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "next"
+msgstr "siguiente"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "last"
+msgstr "último"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "All"
+msgstr "Todos"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Plugins"
+msgstr "Plugins"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Sort:"
+msgstr "Ordenar:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Reverse"
+msgstr "Invertir"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Category:"
+msgstr "Categoría:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Site:"
+msgstr "Sitio:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Support.."
+msgstr "Soporte.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Official"
+msgstr "Oficial"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Testing"
+msgstr "Testeo"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Assets ZIP File"
+msgstr "Archivo ZIP de Assets"
#: editor/plugins/camera_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
msgid "Preview"
msgstr "Vista Previa"
@@ -3761,12 +3273,16 @@ msgid "Edit CanvasItem"
msgstr "Editar CanvasItem"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Change Anchors"
-msgstr "Cambiar Anclas"
+msgid "Anchors only"
+msgstr "Solo anclas"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom (%):"
-msgstr "Zoom (%):"
+msgid "Change Anchors and Margins"
+msgstr "Cambiar Anclas y Márgenes"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Change Anchors"
+msgstr "Cambiar Anclas"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Paste Pose"
@@ -3820,60 +3336,73 @@ msgid "Pan Mode"
msgstr "Modo Paneo"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Lock the selected object in place (can't be moved)."
-msgstr "Inmovilizar Objeto."
+msgid "Toggles snapping"
+msgstr "Act/Desact. alineado"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Unlock the selected object (can be moved)."
-msgstr "Desinmovilizar Objeto."
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Use Snap"
+msgstr "Usar Snap"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Makes sure the object's children are not selectable."
-msgstr "Asegurarse que los hijos de un objeto no sean seleccionables."
+msgid "Snapping options"
+msgstr "Opciones de alineado"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Restores the object's children's ability to be selected."
-msgstr "Restaurar la habilidad de seleccionar los hijos de un objeto."
+msgid "Snap to grid"
+msgstr "Alinear a la grilla"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Edit"
-msgstr "Editar"
+msgid "Use Rotation Snap"
+msgstr "Usar Snap de Rotación"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Use Snap"
-msgstr "Usar Snap"
+msgid "Configure Snap..."
+msgstr "Configurar alineado.."
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Show Grid"
-msgstr "Mostrar la Grilla"
+msgid "Snap Relative"
+msgstr "Usar Snap Relativo"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Rotation Snap"
-msgstr "Usar Snap de Rotación"
+msgid "Use Pixel Snap"
+msgstr "Usar Pixel Snap"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap Relative"
-msgstr "Usar Snap Relativo"
+msgid "Smart snapping"
+msgstr "Alineado inteligente"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Configure Snap.."
-msgstr "Configurar Snap.."
+msgid "Snap to parent"
+msgstr "Alinear al Padre"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Pixel Snap"
-msgstr "Usar Pixel Snap"
+msgid "Snap to node anchor"
+msgstr "Alinear al ancla de nodo"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to node sides"
+msgstr "Alinear a lados de nodo"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to other nodes"
+msgstr "Alinear a otros nodos"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Lock the selected object in place (can't be moved)."
+msgstr "Inmovilizar Objeto."
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Unlock the selected object (can be moved)."
+msgstr "Desinmovilizar Objeto."
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Skeleton.."
-msgstr "Esqueleto.."
+msgid "Makes sure the object's children are not selectable."
+msgstr "Asegurarse que los hijos de un objeto no sean seleccionables."
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Restores the object's children's ability to be selected."
+msgstr "Restaurar la habilidad de seleccionar los hijos de un objeto."
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Make Bones"
@@ -3901,12 +3430,17 @@ msgid "View"
msgstr "Ver"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Reset"
-msgstr "Resetear Zoom"
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Show Grid"
+msgstr "Mostrar la Grilla"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Show helpers"
+msgstr "Mostrar ayudantes"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Set.."
-msgstr "Setear Zoom.."
+msgid "Show rulers"
+msgstr "Mostrar reglas"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Center Selection"
@@ -3917,8 +3451,8 @@ msgid "Frame Selection"
msgstr "Encuadrar Selección"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Anchor"
-msgstr "Anchor"
+msgid "Layout"
+msgstr "Layout"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Insert Keys"
@@ -3941,12 +3475,20 @@ msgid "Clear Pose"
msgstr "Reestablecer Pose"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Set a Value"
-msgstr "Setear un Valor"
+msgid "Drag pivot from mouse position"
+msgstr "Arrastrar pivote desde la posición del mouse"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap (Pixels):"
-msgstr "Snap (Pixeles):"
+msgid "Set pivot at mouse position"
+msgstr "Setear pivote a la posición del mouse"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Multiply grid step by 2"
+msgstr "Multiplicar ingremento de grilla por 2"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Divide grid step by 2"
+msgstr "Dividir incremento de grilla por 2"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Add %s"
@@ -3956,23 +3498,28 @@ msgstr "Agregar %s"
msgid "Adding %s..."
msgstr "Agregando %s..."
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Create Node"
msgstr "Crear Nodo"
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Error instancing scene from %s"
msgstr "Error al instanciar escena desde %s"
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "OK :("
msgstr "OK :("
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "No parent to instance a child at."
msgstr "No hay padre al que instanciarle un hijo."
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "This operation requires a single selected node."
msgstr "Esta operación requiere un solo nodo seleccionado."
@@ -3988,45 +3535,6 @@ msgstr ""
"Drag & drop + Shift : Agregar nodo como hermano\n"
"Drag & drop + Alt : Cambiar tipo de nodo"
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Create Poly"
-msgstr "Crear Polígono"
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly"
-msgstr "Editar Polígono"
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly (Remove Point)"
-msgstr "Editar Polígono (Remover Punto)"
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Create a new polygon from scratch."
-msgstr "Crear un nuevo polígono de cero."
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-msgid ""
-"Edit existing polygon:\n"
-"LMB: Move Point.\n"
-"Ctrl+LMB: Split Segment.\n"
-"RMB: Erase Point."
-msgstr ""
-
#: editor/plugins/collision_polygon_editor_plugin.cpp
msgid "Create Poly3D"
msgstr "Crear Poly3D"
@@ -4036,14 +3544,6 @@ msgid "Set Handle"
msgstr "Setear Handle"
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Creating Mesh Library"
-msgstr "Crear Librería de Meshes"
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Thumbnail.."
-msgstr "Miniatura.."
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Remove item %d?"
msgstr "Remover item %d?"
@@ -4066,19 +3566,36 @@ msgid "Update from Scene"
msgstr "Acutalizar desde Escena"
#: editor/plugins/curve_editor_plugin.cpp
-#, fuzzy
+msgid "Flat0"
+msgstr "Flat0"
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat1"
+msgstr "Flat1"
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Ease in"
+msgstr "Ease in"
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Ease out"
+msgstr "Ease out"
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Smoothstep"
+msgstr "Smoothstep"
+
+#: editor/plugins/curve_editor_plugin.cpp
msgid "Modify Curve Point"
-msgstr "Modificar Curva"
+msgstr "Modificar Punto de Curva"
#: editor/plugins/curve_editor_plugin.cpp
-#, fuzzy
msgid "Modify Curve Tangent"
-msgstr "Modificar Mapa de Curvas"
+msgstr "Modificar Tangente de Curva"
#: editor/plugins/curve_editor_plugin.cpp
-#, fuzzy
msgid "Load Curve Preset"
-msgstr "Cargar preset"
+msgstr "Cargar Preset de Curva"
#: editor/plugins/curve_editor_plugin.cpp
msgid "Add point"
@@ -4089,31 +3606,28 @@ msgid "Remove point"
msgstr "Quitar punto"
#: editor/plugins/curve_editor_plugin.cpp
-#, fuzzy
msgid "Left linear"
-msgstr "Lineal"
+msgstr "Lineal izquierda"
#: editor/plugins/curve_editor_plugin.cpp
-#, fuzzy
msgid "Right linear"
-msgstr "Vista Derecha"
+msgstr "Lineal derecha"
#: editor/plugins/curve_editor_plugin.cpp
msgid "Load preset"
msgstr "Cargar preset"
#: editor/plugins/curve_editor_plugin.cpp
-#, fuzzy
msgid "Remove Curve Point"
-msgstr "Quitar Punto del Path"
+msgstr "Quitar Punto de Curva"
#: editor/plugins/curve_editor_plugin.cpp
msgid "Toggle Curve Linear Tangent"
-msgstr ""
+msgstr "Act./Desact. Tangente Lineal de Curva"
#: editor/plugins/curve_editor_plugin.cpp
msgid "Hold Shift to edit tangents individually"
-msgstr ""
+msgstr "Mantené Shift para editar tangentes individualmente"
#: editor/plugins/gradient_editor_plugin.cpp
msgid "Add/Remove Color Ramp Point"
@@ -4141,28 +3655,26 @@ msgid ""
"No OccluderPolygon2D resource on this node.\n"
"Create and assign one?"
msgstr ""
+"No hay ningún recurso OccluderPolygon2D en este nodo.\n"
+"Crear y asignar uno?"
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
msgid "Create Occluder Polygon"
msgstr "Crear Polígono Oclusor"
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Edit existing polygon:"
msgstr "Editar polígono existente:"
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "LMB: Move Point."
msgstr "Click. Izq: Mover Punto."
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Ctrl+LMB: Split Segment."
msgstr "Ctrl+Click Izq.: Partir Segmento en Dos."
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "RMB: Erase Point."
msgstr "Click Der.: Borrar Punto."
@@ -4263,6 +3775,10 @@ msgid "Create Outline"
msgstr "Crear Outline"
#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Mesh"
+msgstr "Mesh"
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Create Trimesh Static Body"
msgstr "Crear Body Estático Trimesh"
@@ -4391,14 +3907,75 @@ msgstr "Escala al Azar:"
msgid "Populate"
msgstr "Poblar"
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake!"
+msgstr "Hacer Bake!"
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake the navigation mesh.\n"
+msgstr "Hacer bake de mesh de navegación.\n"
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Clear the navigation mesh."
+msgstr "Reestablecer mesh de navegación."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Setting up Configuration..."
+msgstr "Seteando Configuración..."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Calculating grid size..."
+msgstr "Calculando tamaño de grilla..."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating heightfield..."
+msgstr "Creando campo de alturas..."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Marking walkable triangles..."
+msgstr "Marcando triangulos caminables..."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Constructing compact heightfield..."
+msgstr "Construyendo campo de alturas compacto..."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Eroding walkable area..."
+msgstr "Erocionando area caminable..."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Partitioning..."
+msgstr "Particionando..."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating contours..."
+msgstr "Creando contornos..."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating polymesh..."
+msgstr "Creando polymesh..."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Converting to native navigation mesh..."
+msgstr "Convirtiendo a mesh de navegación nativa..."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Navigation Mesh Generator Setup:"
+msgstr "Setup de Generador de Meshes de Navegación:"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Parsing Geometry..."
+msgstr "Parseando Geometría..."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Done!"
+msgstr "Hecho!"
+
#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Create Navigation Polygon"
msgstr "Crear Polígono de Navegación"
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Remove Poly And Point"
-msgstr "Remover Polígono y Punto"
-
#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Clear Emission Mask"
msgstr "Limpiar Máscara de Emisión"
@@ -4435,9 +4012,8 @@ msgstr "Cargar Máscara de Emisión"
#: editor/plugins/particles_2d_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp
-#, fuzzy
msgid "Particles"
-msgstr "Vértices"
+msgstr "Partículas"
#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Generated Point Count:"
@@ -4573,15 +4149,15 @@ msgstr "Punto # de Curva"
#: editor/plugins/path_editor_plugin.cpp
msgid "Set Curve Point Position"
-msgstr "Setear Pos. de Punto de Curva"
+msgstr "Setear Posición de Punto de Curva"
#: editor/plugins/path_editor_plugin.cpp
msgid "Set Curve In Position"
-msgstr "Setear Pos. In de Curva"
+msgstr "Setear Posición de Entrada de Curva"
#: editor/plugins/path_editor_plugin.cpp
msgid "Set Curve Out Position"
-msgstr "Setear Pos. Out de Curva"
+msgstr "Setear Posición de Salida de Curva"
#: editor/plugins/path_editor_plugin.cpp
msgid "Split Path"
@@ -4640,6 +4216,14 @@ msgid "Scale Polygon"
msgstr "Escalar Polígono"
#: editor/plugins/polygon_2d_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Edit"
+msgstr "Editar"
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Polygon->UV"
msgstr "Polígono->UV"
@@ -4694,63 +4278,10 @@ msgstr "Cargar Recurso"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/shader_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "Pegar"
-#: editor/plugins/rich_text_editor_plugin.cpp
-msgid "Parse BBCode"
-msgstr "Parsear BBCode"
-
-#: editor/plugins/sample_editor_plugin.cpp
-msgid "Length:"
-msgstr "Largo:"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Open Sample File(s)"
-msgstr "Abrir Archivo(s) de Muestra"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "ERROR: Couldn't load sample!"
-msgstr "ERROR: No se pudo cargar la muestra!"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Add Sample"
-msgstr "Agregar Muestra"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Rename Sample"
-msgstr "Renombrar Muestra"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Delete Sample"
-msgstr "Eliminar Muestra"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "16 Bits"
-msgstr "16 Bits"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "8 Bits"
-msgstr "8 Bits"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Stereo"
-msgstr "Estereo"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Mono"
-msgstr "Mono"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Format"
-msgstr "Formato"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Pitch"
-msgstr "Altura"
-
#: editor/plugins/script_editor_plugin.cpp
msgid "Clear Recent Files"
msgstr "Reestablecer Archivos Recientes"
@@ -4760,6 +4291,8 @@ msgid ""
"Close and save changes?\n"
"\""
msgstr ""
+"Cerrar y guardar cambios?\n"
+"\""
#: editor/plugins/script_editor_plugin.cpp
msgid "Error while saving theme"
@@ -4787,7 +4320,7 @@ msgstr "Guardar Tema Como.."
#: editor/plugins/script_editor_plugin.cpp
msgid " Class Reference"
-msgstr ""
+msgstr " Referencia de Clases"
#: editor/plugins/script_editor_plugin.cpp
msgid "Next script"
@@ -4841,10 +4374,13 @@ msgstr "Cerrar Docs"
msgid "Close All"
msgstr "Cerrar Todos"
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+msgid "Run"
+msgstr "Ejecutar"
+
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Toggle Scripts Panel"
-msgstr "Act/Desact. Favorito"
+msgstr "Act/Desact. Panel de Scripts"
#: editor/plugins/script_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
@@ -4870,7 +4406,8 @@ msgstr "Step Into"
msgid "Break"
msgstr "Break"
-#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+#: editor/script_editor_debugger.cpp
msgid "Continue"
msgstr "Continuar"
@@ -4879,21 +4416,8 @@ msgid "Keep Debugger Open"
msgstr "Mantener el Debugger Abierto"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Debug with external editor"
-msgstr "Abrir el Editor siguiente"
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Window"
-msgstr "Ventana"
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Left"
-msgstr "Mover a la Izquierda"
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Right"
-msgstr "Mover a la Derecha"
+msgstr "Debuguear con editor externo"
#: editor/plugins/script_editor_plugin.cpp
msgid "Open Godot online documentation"
@@ -4952,7 +4476,7 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
msgid "Only resources from filesystem can be dropped."
-msgstr ""
+msgstr "Solo se pueden depositar recursos del sistema de archivos."
#: editor/plugins/script_text_editor.cpp
msgid "Pick Color"
@@ -4981,8 +4505,9 @@ msgid "Cut"
msgstr "Cortar"
#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "Copiar"
@@ -5001,9 +4526,8 @@ msgid "Move Down"
msgstr "Bajar"
#: editor/plugins/script_text_editor.cpp
-#, fuzzy
msgid "Delete Line"
-msgstr "Eliminar Punto"
+msgstr "Eliminar Línea"
#: editor/plugins/script_text_editor.cpp
msgid "Indent Left"
@@ -5246,10 +4770,6 @@ msgid "View Plane Transform."
msgstr "Ver Transformación en Plano."
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Scaling to %s%%."
-msgstr "Escalando a %s%%."
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rotating %s degrees."
msgstr "Torando %s grados."
@@ -5266,10 +4786,6 @@ msgid "Top View."
msgstr "Vista Superior."
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Top"
-msgstr "Cima"
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rear View."
msgstr "Vista Anterior."
@@ -5370,9 +4886,8 @@ msgid "Audio Listener"
msgstr "Oyente de Audio"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Doppler Enable"
-msgstr "Activar"
+msgstr "Activar Doppler"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Freelook Left"
@@ -5403,26 +4918,26 @@ msgid "Freelook Speed Modifier"
msgstr "Modificador de Velocidad de Vista Libre"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "preview"
-msgstr "Vista Previa"
+msgstr "vista previa"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "XForm Dialog"
msgstr "Dialogo XForm"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Select Mode (Q)\n"
-msgstr "Modo Seleccionar"
+msgstr "Modo Seleccionar (Q)\n"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid ""
"Drag: Rotate\n"
"Alt+Drag: Move\n"
"Alt+RMB: Depth list selection"
-msgstr "Alt+Click Der.: Selección en depth list"
+msgstr ""
+"Arrastrar: Rotar\n"
+"Alt+Arrastrar: Mover\n"
+"Alt+Click Der.: Selección en depth list"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Move Mode (W)"
@@ -5501,6 +5016,10 @@ msgid "Transform"
msgstr "Transformar"
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Configure Snap.."
+msgstr "Configurar Snap.."
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Local Coords"
msgstr "Coordenadas Locales"
@@ -5646,6 +5165,10 @@ msgid "Speed (FPS):"
msgstr "Velocidad (FPS):"
#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Loop"
+msgstr "Loop"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Animation Frames"
msgstr "Cuadros de Animación"
@@ -5658,21 +5181,20 @@ msgid "Insert Empty (After)"
msgstr "Insertar Vacío (Después)"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Up"
-msgstr "Arriba"
+msgid "Move (Before)"
+msgstr "Mover (Antes)"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Down"
-msgstr "Abajo"
+msgid "Move (After)"
+msgstr "Mover (Despues)"
#: editor/plugins/style_box_editor_plugin.cpp
msgid "StyleBox Preview:"
msgstr "Vista Previa de StyleBox:"
#: editor/plugins/texture_region_editor_plugin.cpp
-#, fuzzy
msgid "Set Region Rect"
-msgstr "Setear region_rect"
+msgstr "Setear Region Rect"
#: editor/plugins/texture_region_editor_plugin.cpp
msgid "Snap Mode:"
@@ -5732,18 +5254,20 @@ msgid "Remove Item"
msgstr "Remover Item"
#: editor/plugins/theme_editor_plugin.cpp
-#, fuzzy
msgid "Remove All Items"
-msgstr "Quitar Items de Clases"
+msgstr "Quitar Todos los Ãtems"
#: editor/plugins/theme_editor_plugin.cpp
-#, fuzzy
msgid "Remove All"
-msgstr "Quitar"
+msgstr "Quitar Todos"
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Edit theme.."
+msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
-msgid "Theme"
-msgstr "Tema"
+msgid "Theme editing menu."
+msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
msgid "Add Class Items"
@@ -5827,11 +5351,14 @@ msgid "Style"
msgstr "Estilo"
#: editor/plugins/theme_editor_plugin.cpp
+msgid "Font"
+msgstr "Tipografía"
+
+#: editor/plugins/theme_editor_plugin.cpp
msgid "Color"
msgstr "Color"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Erase Selection"
msgstr "Eliminar Selección"
@@ -5840,16 +5367,14 @@ msgid "Paint TileMap"
msgstr "Pintar TileMap"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Line Draw"
-msgstr "Lineal"
+msgstr "Dibujar Línea"
#: editor/plugins/tile_map_editor_plugin.cpp
msgid "Rectangle Paint"
-msgstr ""
+msgstr "Pintar Rectángulo"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Bucket Fill"
msgstr "Balde"
@@ -5878,8 +5403,8 @@ msgid "Mirror Y"
msgstr "Espejar Y"
#: editor/plugins/tile_map_editor_plugin.cpp
-msgid "Bucket"
-msgstr "Balde"
+msgid "Paint Tile"
+msgstr "Pintar Tile"
#: editor/plugins/tile_map_editor_plugin.cpp
msgid "Pick Tile"
@@ -5942,6 +5467,12 @@ msgid "Delete preset '%s'?"
msgstr "Eliminar preset '%s'?"
#: editor/project_export.cpp
+msgid "Export templates for this platform are missing/corrupted: "
+msgstr ""
+"Las plantillas de exportación para esta plataforma estan faltando o "
+"corruptas: "
+
+#: editor/project_export.cpp
msgid "Presets"
msgstr "Presets"
@@ -5996,18 +5527,16 @@ msgid "Make Patch"
msgstr "Crear Parche"
#: editor/project_export.cpp
-#, fuzzy
msgid "Features"
-msgstr "Textura"
+msgstr "Características"
#: editor/project_export.cpp
msgid "Custom (comma-separated):"
-msgstr ""
+msgstr "Personalizado (separado por comas):"
#: editor/project_export.cpp
-#, fuzzy
msgid "Feature List:"
-msgstr "Lista de Métodos:"
+msgstr "Lista de Características:"
#: editor/project_export.cpp
msgid "Export PCK/Zip"
@@ -6018,30 +5547,61 @@ msgid "Export templates for this platform are missing:"
msgstr "Faltan las plantillas de exportación para esta plataforma:"
#: editor/project_export.cpp
+msgid "Export templates for this platform are missing/corrupted:"
+msgstr ""
+"Las plantillas de exportación para esta plataforma estan faltando o "
+"corruptas:"
+
+#: editor/project_export.cpp
msgid "Export With Debug"
msgstr "Exportar Como Debug"
#: editor/project_manager.cpp
-msgid "Invalid project path, the path must exist!"
-msgstr "Ruta de proyecto inválida, la ruta debe existir!"
+msgid "The path does not exist."
+msgstr "La ruta no existe."
+
+#: editor/project_manager.cpp
+msgid "Please choose a 'project.godot' file."
+msgstr "Por favor elegí un archivo 'project.godot'."
#: editor/project_manager.cpp
-msgid "Invalid project path, project.godot must not exist."
-msgstr "Ruta de proyecto inválida, project.godot no debe existir."
+msgid ""
+"Your project will be created in a non empty folder (you might want to create "
+"a new folder)."
+msgstr ""
+"Tu proyecto será creado en una carpeta no vacía (podrías preferir crear una "
+"carpeta nueva)."
#: editor/project_manager.cpp
-msgid "Invalid project path, project.godot must exist."
-msgstr "Ruta de proyecto inválida, project.godot debe existir."
+msgid "Please choose a folder that does not contain a 'project.godot' file."
+msgstr ""
+"Por favor elegí una carpeta que no contenga un archivo 'project.godot'."
#: editor/project_manager.cpp
msgid "Imported Project"
msgstr "Proyecto Importado"
#: editor/project_manager.cpp
+msgid " "
+msgstr " "
+
+#: editor/project_manager.cpp
+msgid "It would be a good idea to name your project."
+msgstr "Sería buena idea darle un nombre a tu proyecto."
+
+#: editor/project_manager.cpp
msgid "Invalid project path (changed anything?)."
msgstr "Ruta de proyecto inválida (cambiaste algo?)."
#: editor/project_manager.cpp
+msgid "Couldn't get project.godot in project path."
+msgstr "No se pudo obtener project.godot en la ruta de proyecto."
+
+#: editor/project_manager.cpp
+msgid "Couldn't edit project.godot in project path."
+msgstr "No se pudo editar project.godot en la ruta de proyecto."
+
+#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
msgstr "No se pudo crear project.godot en la ruta de proyecto."
@@ -6050,38 +5610,46 @@ 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"
+
+#: editor/project_manager.cpp
+msgid "Couldn't get project.godot in the project path."
+msgstr "No se pudo obtener project.godot en la ruta de proyecto."
+
+#: editor/project_manager.cpp
+msgid "New Game Project"
+msgstr "Nuevo Proyecto de Juego"
+
+#: editor/project_manager.cpp
msgid "Import Existing Project"
msgstr "Importar Proyecto Existente"
#: editor/project_manager.cpp
-msgid "Project Path (Must Exist):"
-msgstr "Ruta del Proyecto (Debe Existir):"
+msgid "Create New Project"
+msgstr "Crear Proyecto Nuevo"
+
+#: editor/project_manager.cpp
+msgid "Install Project:"
+msgstr "Instalar Proyecto:"
#: editor/project_manager.cpp
msgid "Project Name:"
msgstr "Nombre del Proyecto:"
#: editor/project_manager.cpp
-msgid "Create New Project"
-msgstr "Crear Proyecto Nuevo"
+msgid "Create folder"
+msgstr "Crear carpeta"
#: editor/project_manager.cpp
msgid "Project Path:"
msgstr "Ruta del Proyecto:"
#: editor/project_manager.cpp
-msgid "Install Project:"
-msgstr "Instalar Proyecto:"
-
-#: editor/project_manager.cpp
msgid "Browse"
msgstr "Examinar"
#: editor/project_manager.cpp
-msgid "New Game Project"
-msgstr "Nuevo Proyecto de Juego"
-
-#: editor/project_manager.cpp
msgid "That's a BINGO!"
msgstr "BINGO!"
@@ -6090,25 +5658,31 @@ msgid "Unnamed Project"
msgstr "Proyecto Sin Nombre"
#: editor/project_manager.cpp
+msgid "Can't open project"
+msgstr "No se pudo abrir el proyecto"
+
+#: editor/project_manager.cpp
msgid "Are you sure to open more than one project?"
msgstr "¿Estás seguro/a que querés abrir mas de un proyecto?"
#: editor/project_manager.cpp
-#, fuzzy
msgid ""
"Can't run project: no main scene defined.\n"
"Please edit the project and set the main scene in \"Project Settings\" under "
"the \"Application\" category."
msgstr ""
-"No se ha definido ninguna escena principal, ¿elegir una?\n"
-"Es posible cambiarla más tarde en \"Ajustes del Proyecto\" bajo la categoría "
-"'aplicación'."
+"No sé puede ejecutar el proyecto: No se ha definido ninguna escena "
+"principal.\n"
+"Por favor editá el proyecto y seteá la escena principal en \"Ajustes de "
+"Proyecto\" bajo la categoría 'Aplicación'."
#: editor/project_manager.cpp
msgid ""
"Can't run project: Assets need to be imported.\n"
"Please edit the project to trigger the initial import."
msgstr ""
+"No sé puede ejecutar el proyecto: Es necesario importar los assets.\n"
+"Por favor editá el proyecto para provocar la importación inicial."
#: editor/project_manager.cpp
msgid "Are you sure to run more than one project?"
@@ -6122,6 +5696,12 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
+"Language changed.\n"
+"The UI will update next time the editor or project manager starts."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid ""
"You are about the scan %s folders for existing Godot projects. Do you "
"confirm?"
msgstr ""
@@ -6133,10 +5713,6 @@ msgid "Project List"
msgstr "Listado de Proyectos"
#: editor/project_manager.cpp
-msgid "Run"
-msgstr "Ejecutar"
-
-#: editor/project_manager.cpp
msgid "Scan"
msgstr "Escanear"
@@ -6158,8 +5734,12 @@ msgstr "Salir"
#: editor/project_manager.cpp
#, fuzzy
+msgid "Restart Now"
+msgstr "Reiniciar (s):"
+
+#: editor/project_manager.cpp
msgid "Can't run project"
-msgstr "No se puede conectar."
+msgstr "No se puede ejecutar el proyecto"
#: editor/project_settings_editor.cpp
msgid "Key "
@@ -6194,17 +5774,14 @@ msgid "Add Input Action Event"
msgstr "Agregar Evento de Acción de Entrada"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Meta+"
msgstr "Meta+"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Shift+"
msgstr "Shift+"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Alt+"
msgstr "Alt+"
@@ -6265,7 +5842,7 @@ msgstr "Cambiar"
msgid "Joypad Axis Index:"
msgstr "Indice del Eje del Gamepad:"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Axis"
msgstr "Eje"
@@ -6285,57 +5862,61 @@ msgstr "Borrar Evento de Acción de Entrada"
msgid "Add Event"
msgstr "Agregar Evento"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Device"
msgstr "Dispositivo"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Button"
msgstr "Botón"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Left Button."
msgstr "Botón Izquierdo."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Right Button."
msgstr "Botón Derecho."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Middle Button."
msgstr "Botón del Medio."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Up."
msgstr "Rueda Arriba."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Down."
msgstr "Rueda Abajo."
#: editor/project_settings_editor.cpp
-#, fuzzy
msgid "Add Global Property"
-msgstr "Agregar Propiedad Getter"
+msgstr "Agregar Propiedad Global"
#: editor/project_settings_editor.cpp
-msgid "Select an setting item first!"
-msgstr ""
+msgid "Select a setting item first!"
+msgstr "Selecciona un ítem primero!"
#: editor/project_settings_editor.cpp
-#, fuzzy
msgid "No property '"
-msgstr "Propiedad:"
+msgstr "No existe la propiedad '"
#: editor/project_settings_editor.cpp
-#, fuzzy
msgid "Setting '"
-msgstr "Configuración"
+msgstr "Ajuste '"
#: editor/project_settings_editor.cpp
-#, fuzzy
msgid "Delete Item"
-msgstr "Eliminar Entrada"
+msgstr "Eliminar Ãtem"
+
+#: editor/project_settings_editor.cpp
+msgid "Can't contain '/' or ':'"
+msgstr "No puede contener '/' o ':'"
+
+#: editor/project_settings_editor.cpp
+msgid "Already existing"
+msgstr "Ya existe"
#: editor/project_settings_editor.cpp
msgid "Error saving settings."
@@ -6347,7 +5928,7 @@ msgstr "Ajustes guardados satisfactoriamente."
#: editor/project_settings_editor.cpp
msgid "Override for Feature"
-msgstr ""
+msgstr "Sobreescribir para Característica"
#: editor/project_settings_editor.cpp
msgid "Add Translation"
@@ -6378,6 +5959,15 @@ msgid "Remove Resource Remap Option"
msgstr "Remover Opción de Remapeo de Recursos"
#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Changed Locale Filter"
+msgstr "Cambiar Tiempo de Blend"
+
+#: editor/project_settings_editor.cpp
+msgid "Changed Locale Filter Mode"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "Project Settings (project.godot)"
msgstr "Configuración de Proyecto (project.godot)"
@@ -6391,7 +5981,7 @@ msgstr "Propiedad:"
#: editor/project_settings_editor.cpp
msgid "Override For.."
-msgstr ""
+msgstr "Sobreescribir Para.."
#: editor/project_settings_editor.cpp
msgid "Input Map"
@@ -6438,6 +6028,30 @@ msgid "Locale"
msgstr "Locale"
#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Locales Filter"
+msgstr "Filtro de Imágenes:"
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Show all locales"
+msgstr "Mostrar Huesos"
+
+#: editor/project_settings_editor.cpp
+msgid "Show only selected locales"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Filter mode:"
+msgstr "Filtrar nodos"
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Locales:"
+msgstr "Locale"
+
+#: editor/project_settings_editor.cpp
msgid "AutoLoad"
msgstr "AutoLoad"
@@ -6478,26 +6092,32 @@ msgid "Assign"
msgstr "Asignar"
#: editor/property_editor.cpp
-#, fuzzy
msgid "Select Node"
-msgstr "Seleccionar un Nodo"
+msgstr "Seleccionar Nodo"
#: editor/property_editor.cpp
msgid "New Script"
msgstr "Nuevo Script"
#: editor/property_editor.cpp
+msgid "Make Unique"
+msgstr "Convertir en Unico"
+
+#: editor/property_editor.cpp
msgid "Show in File System"
msgstr "Mostrar en Sistema de Archivos"
#: editor/property_editor.cpp
+msgid "Convert To %s"
+msgstr "Convertir A %s"
+
+#: editor/property_editor.cpp
msgid "Error loading file: Not a resource!"
msgstr "Error al cargar el archivo: No es un recurso!"
#: editor/property_editor.cpp
-#, fuzzy
msgid "Selected node is not a Viewport!"
-msgstr "Seleccionar Nodo(s) para Importar"
+msgstr "El nodo seleccionado no es un Viewport!"
#: editor/property_editor.cpp
msgid "Pick a Node"
@@ -6528,6 +6148,10 @@ msgid "Select Property"
msgstr "Seleccionar Propiedad"
#: editor/property_selector.cpp
+msgid "Select Virtual Method"
+msgstr "Seleccionar Método Virtual"
+
+#: editor/property_selector.cpp
msgid "Select Method"
msgstr "Seleccionar Método"
@@ -6556,26 +6180,6 @@ msgstr "Mantener Transformación Global"
msgid "Reparent"
msgstr "Reemparentar"
-#: editor/resources_dock.cpp
-msgid "Create New Resource"
-msgstr "Crear Nuevo Recurso"
-
-#: editor/resources_dock.cpp
-msgid "Open Resource"
-msgstr "Abrir Recurso"
-
-#: editor/resources_dock.cpp
-msgid "Save Resource"
-msgstr "Guardar Recurso"
-
-#: editor/resources_dock.cpp
-msgid "Resource Tools"
-msgstr "Herramientas de Recursos"
-
-#: editor/resources_dock.cpp
-msgid "Make Local"
-msgstr "Crear Local"
-
#: editor/run_settings_dialog.cpp
msgid "Run Mode:"
msgstr "Modo de Ejecución:"
@@ -6707,14 +6311,6 @@ msgid "Sub-Resources:"
msgstr "Sub-Recursos:"
#: editor/scene_tree_dock.cpp
-msgid "Edit Groups"
-msgstr "Editar Grupos"
-
-#: editor/scene_tree_dock.cpp
-msgid "Edit Connections"
-msgstr "Editar Conexiones"
-
-#: editor/scene_tree_dock.cpp
msgid "Clear Inheritance"
msgstr "Limpiar Herencia"
@@ -6775,9 +6371,8 @@ msgstr ""
"existe ningún nodo raíz."
#: editor/scene_tree_dock.cpp
-#, fuzzy
msgid "Filter nodes"
-msgstr "Filtros"
+msgstr "Filtrar nodos"
#: editor/scene_tree_dock.cpp
msgid "Attach a new or existing script for the selected node."
@@ -6872,18 +6467,16 @@ msgid "Scene Tree (Nodes):"
msgstr "Arbol de Escenas (Nodos):"
#: editor/scene_tree_editor.cpp
-#, fuzzy
msgid "Node Configuration Warning!"
-msgstr "Advertencia de configuración de nodo:"
+msgstr "Advertencia de Configuración de Nodo!"
#: editor/scene_tree_editor.cpp
msgid "Select a Node"
msgstr "Seleccionar un Nodo"
#: editor/script_create_dialog.cpp
-#, fuzzy
msgid "Error loading template '%s'"
-msgstr "Error al cargar la imagen:"
+msgstr "Error al cargar la plantilla '%s'"
#: editor/script_create_dialog.cpp
msgid "Error - Could not create script in filesystem."
@@ -6910,6 +6503,14 @@ msgid "Invalid base path"
msgstr "Ruta base inválida"
#: editor/script_create_dialog.cpp
+msgid "Directory of the same name exists"
+msgstr "Existe un directorio con el mismo nombre"
+
+#: editor/script_create_dialog.cpp
+msgid "File exists, will be reused"
+msgstr "El archivo existe, será reutilizado"
+
+#: editor/script_create_dialog.cpp
msgid "Invalid extension"
msgstr "Extensión invalida"
@@ -6950,6 +6551,10 @@ msgid "Load existing script file"
msgstr "Cargar script existente"
#: editor/script_create_dialog.cpp
+msgid "Language"
+msgstr "Lenguaje"
+
+#: editor/script_create_dialog.cpp
msgid "Inherits"
msgstr "Hereda"
@@ -6990,6 +6595,10 @@ msgid "Function:"
msgstr "Funcion:"
#: editor/script_editor_debugger.cpp
+msgid "Pick one or more items from the list to display the graph."
+msgstr "Elegir uno o mas items de la lista para mostrar el gráfico."
+
+#: editor/script_editor_debugger.cpp
msgid "Errors"
msgstr "Errores"
@@ -7070,6 +6679,10 @@ msgid "Type"
msgstr "Tipo"
#: editor/script_editor_debugger.cpp
+msgid "Format"
+msgstr "Formato"
+
+#: editor/script_editor_debugger.cpp
msgid "Usage"
msgstr "Uso"
@@ -7103,7 +6716,7 @@ msgstr "Cambiar Radio de Luces"
#: editor/spatial_editor_gizmos.cpp
msgid "Change AudioStreamPlayer3D Emission Angle"
-msgstr ""
+msgstr "Cambiar el Ãngulo de Emisión del AudioStreamPlayer3D"
#: editor/spatial_editor_gizmos.cpp
msgid "Change Camera FOV"
@@ -7145,12 +6758,28 @@ msgstr "Cambiar Particulas AABB"
msgid "Change Probe Extents"
msgstr "Cambiar Extensión de Sonda"
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Library"
+msgstr "Biblioteca"
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Status"
+msgstr "Estado"
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Libraries: "
+msgstr "Bibliotecas: "
+
+#: modules/gdnative/register_types.cpp
+msgid "GDNative"
+msgstr "GDNative"
+
#: modules/gdscript/gd_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Invalid type argument to convert(), use TYPE_* constants."
msgstr "Argumento de tipo inválido para convert(), usá constantes TYPE_*."
-#: modules/gdscript/gd_functions.cpp
+#: modules/gdscript/gd_functions.cpp modules/mono/glue/glue_header.h
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Not enough bytes for decoding bytes, or invalid format."
msgstr ""
@@ -7193,134 +6822,111 @@ msgstr "Diccionario de instancias inválido (subclases inválidas)"
#: modules/gdscript/gd_functions.cpp
msgid "Object can't provide a length."
-msgstr ""
+msgstr "El objeto no puede proveer un largo."
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "GridMap Delete Selection"
-msgstr "Eliminar Seleccionados"
+msgstr "Eliminar Seleccionados en GridMap"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "GridMap Duplicate Selection"
-msgstr "Duplicar Selección"
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "GridMap Paint"
-msgstr ""
+msgstr "Duplicar Selección en GridMap"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Snap View"
-msgstr "Vista Superior"
+msgstr "Anclar Vista"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Prev Level (%sDown Wheel)"
-msgstr ""
+msgstr "Nivel Previo (%sRueda Abajo)"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Next Level (%sUp Wheel)"
-msgstr ""
+msgstr "Nivel Siguiente (%sRueda Arriba)"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Clip Disabled"
-msgstr "Desactivado"
+msgstr "Clip Desactivado"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Clip Above"
-msgstr ""
+msgstr "Clip Arriba"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Clip Below"
-msgstr ""
+msgstr "Clip Debajo"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Edit X Axis"
-msgstr ""
+msgstr "Editar Eje X"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Edit Y Axis"
-msgstr ""
+msgstr "Editar Eje Y"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Edit Z Axis"
-msgstr ""
+msgstr "Editar Eje Z"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Cursor Rotate X"
-msgstr "Ctrl: Rotar"
+msgstr "Rotar X en Cursor"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Cursor Rotate Y"
-msgstr "Ctrl: Rotar"
+msgstr "Rotar Y en Cursor"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Cursor Rotate Z"
-msgstr "Ctrl: Rotar"
+msgstr "Rotar Z en Cursor"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Cursor Back Rotate X"
-msgstr ""
+msgstr "Rotación Inversa X en Cursor"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Cursor Back Rotate Y"
-msgstr ""
+msgstr "Rotación Inversa Y en Cursor"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Cursor Back Rotate Z"
-msgstr ""
+msgstr "Rotación Inversa Z en Cursor"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Cursor Clear Rotation"
-msgstr ""
+msgstr "Restablecer Rotación en Cursor"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Create Area"
-msgstr "Crear Nuevo"
+msgstr "Crear Ãrea"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Create Exterior Connector"
-msgstr "Crear Proyecto Nuevo"
+msgstr "Crear Conector Exterior"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Erase Area"
-msgstr "Borrar TileMap"
+msgstr "Borrar Ãrea"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Selection -> Duplicate"
-msgstr "Solo Selección"
+msgstr "Selección -> Duplicar"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Selection -> Clear"
-msgstr "Solo Selección"
+msgstr "Selección -> Restablecer"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "GridMap Settings"
-msgstr "Ajustes de Snap"
+msgstr "Ajustes de GridMap"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Pick Distance:"
-msgstr "Instancia:"
+msgstr "Elegir Instancia:"
-#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
-msgid "Tiles"
-msgstr " Archivos"
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "Areas"
-msgstr ""
+#: modules/mono/editor/mono_bottom_panel.cpp
+msgid "Builds"
+msgstr "Builds"
#: modules/visual_script/visual_script.cpp
msgid ""
@@ -7360,29 +6966,24 @@ msgid "Stack overflow with stack depth: "
msgstr "Stack overflow con la profundidad del stack: "
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Change Signal Arguments"
-msgstr "Editar Argumentos de Señal:"
+msgstr "Editar Argumentos de Señal"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Change Argument Type"
-msgstr "Cambiar Tipo de Valor del Array"
+msgstr "Cambiar Tipo de Argumento"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Change Argument name"
-msgstr "Cambiar Nombre de Entrada"
+msgstr "Cambiar Nombre de Argumento"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Set Variable Default Value"
-msgstr "Cambiar Valor por Defecto"
+msgstr "Asignar Valor Predeterminado de Variable"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Set Variable Type"
-msgstr "Editar Variable:"
+msgstr "Editar Tipo de Variable"
#: modules/visual_script/visual_script_editor.cpp
msgid "Functions:"
@@ -7433,14 +7034,12 @@ msgid "Add Node"
msgstr "Agregar Nodo"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Remove VisualScript Nodes"
-msgstr "Quitar claves inválidas"
+msgstr "Quitar Nodos VisualScript"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Duplicate VisualScript Nodes"
-msgstr "Duplicar Nodo(s) de Gráfico"
+msgstr "Duplicar Nodos VisualScript"
#: modules/visual_script/visual_script_editor.cpp
msgid "Hold Meta to drop a Getter. Hold Shift to drop a generic signature."
@@ -7487,24 +7086,20 @@ msgid "Add Setter Property"
msgstr "Agregar Propiedad Setter"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Change Base Type"
-msgstr "Cambiar Tipo"
+msgstr "Cambiar Tipo Base"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Move Node(s)"
-msgstr "Quitar Nodo(s)"
+msgstr "Mover Nodo(s)"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Remove VisualScript Node"
-msgstr "Quitar Nodo de Gráfico de Shaders"
+msgstr "Quitar Nodo de VisualScript"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Connect Nodes"
-msgstr "Conectar a Nodo:"
+msgstr "Conectar Nodos"
#: modules/visual_script/visual_script_editor.cpp
msgid "Condition"
@@ -7531,46 +7126,48 @@ msgid "Return"
msgstr "Retornar"
#: modules/visual_script/visual_script_editor.cpp
+msgid "Call"
+msgstr "Llamar"
+
+#: modules/visual_script/visual_script_editor.cpp
msgid "Get"
msgstr "Obtener"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
+msgid "Script already has function '%s'"
+msgstr "El script ya tiene una función '%s'"
+
+#: modules/visual_script/visual_script_editor.cpp
msgid "Change Input Value"
-msgstr "Cambiar Nombre de Entrada"
+msgstr "Cambiar Valor de Entrada"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Can't copy the function node."
-msgstr "No se puede operar en '..'"
+msgstr "No se puede copiar el nodo de función."
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Clipboard is empty!"
-msgstr "Clipboard de Recursos vacío!"
+msgstr "El portapapeles está vacío!"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Paste VisualScript Nodes"
-msgstr "Pegar Nodos"
+msgstr "Pegar Nodos de VisualScript"
#: modules/visual_script/visual_script_editor.cpp
msgid "Remove Function"
msgstr "Quitar Función"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Edit Variable"
-msgstr "Editar Variable:"
+msgstr "Editar Variable"
#: modules/visual_script/visual_script_editor.cpp
msgid "Remove Variable"
msgstr "Quitar Variable"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Edit Signal"
-msgstr "Editando Señal:"
+msgstr "Editar Señal"
#: modules/visual_script/visual_script_editor.cpp
msgid "Remove Signal"
@@ -7811,6 +7408,9 @@ msgid ""
"by the physics engine when running.\n"
"Change the size in children collision shapes instead."
msgstr ""
+"Los cambios de tamaño a un RigidBody2D (en modos character o rigid) serán "
+"sobreescritos por el motor de física al ejecutar.\n"
+"Cambiá el tamaño de los collision shapes hijos."
#: scene/2d/remote_transform_2d.cpp
msgid "Path property must point to a valid Node2D node to work."
@@ -7842,31 +7442,35 @@ msgstr ""
#: scene/3d/arvr_nodes.cpp
msgid "ARVRCamera must have an ARVROrigin node as its parent"
-msgstr ""
+msgstr "ARVRCamera debe tener un nodo ARVROrigin como su padre"
#: scene/3d/arvr_nodes.cpp
msgid "ARVRController must have an ARVROrigin node as its parent"
-msgstr ""
+msgstr "ARVRController debe tener un nodo ARVROrigin como su padre"
#: scene/3d/arvr_nodes.cpp
msgid ""
"The controller id must not be 0 or this controller will not be bound to an "
"actual controller"
msgstr ""
+"El id de controlador no debe ser 0 o este controlador no será vinculado a un "
+"controlador real"
#: scene/3d/arvr_nodes.cpp
msgid "ARVRAnchor must have an ARVROrigin node as its parent"
-msgstr ""
+msgstr "ARVRAnchor debe tener un nodo ARVROrigin como su padre"
#: scene/3d/arvr_nodes.cpp
msgid ""
"The anchor id must not be 0 or this anchor will not be bound to an actual "
"anchor"
msgstr ""
+"El id de anclaje no debe ser 0 o este anclaje no podrá ser vinculado a un "
+"anclaje real"
#: scene/3d/arvr_nodes.cpp
msgid "ARVROrigin requires an ARVRCamera child node"
-msgstr ""
+msgstr "ARVROrigin requiere un nodo hijo ARVRCamera"
#: scene/3d/collision_polygon.cpp
msgid ""
@@ -7924,6 +7528,9 @@ msgid ""
"the physics engine when running.\n"
"Change the size in children collision shapes instead."
msgstr ""
+"Los cambios de tamaño a RigidBody (en modo character o rigid) seran "
+"sobreescritos por el motor de física al ejecutar.\n"
+"Cambiá el tamaño de los collision shapes hijos."
#: scene/3d/remote_transform.cpp
msgid "Path property must point to a valid Spatial node to work."
@@ -7945,16 +7552,27 @@ msgstr ""
"Un recurso SpriteFrames debe ser creado o asignado en la propiedad 'Frames' "
"para que AnimatedSprite3D pueda mostrar frames."
+#: scene/3d/vehicle_body.cpp
+msgid ""
+"VehicleWheel serves to provide a wheel system to a VehicleBody. Please use "
+"it as a child of a VehicleBody."
+msgstr ""
+"VehicleWheel sirve para proveer un sistema de ruedas a VehicleBody. Por "
+"favor usálo como hijo de VehicleBody."
+
#: scene/gui/color_picker.cpp
-#, fuzzy
msgid "Raw Mode"
-msgstr "Modo Paneo"
+msgstr "Modo Raw"
#: scene/gui/color_picker.cpp
msgid "Add current color as a preset"
msgstr "Agregar color actual como preset"
#: scene/gui/dialogs.cpp
+msgid "Cancel"
+msgstr "Cancelar"
+
+#: scene/gui/dialogs.cpp
msgid "Alert!"
msgstr "Alerta!"
@@ -7962,10 +7580,6 @@ msgstr "Alerta!"
msgid "Please Confirm..."
msgstr "Confirmá, por favor..."
-#: scene/gui/input_action.cpp
-msgid "Ctrl+"
-msgstr "Ctrl+"
-
#: scene/gui/popup.cpp
msgid ""
"Popups will hide by default unless you call popup() or any of the popup*() "
@@ -8006,6 +7620,644 @@ msgstr ""
"que pueda obtener un tamaño. Alternativamente, hacelo un RenderTarget y "
"asigná su textura interna a algún otro nodo para mostrar."
+#: scene/resources/dynamic_font.cpp
+msgid "Error initializing FreeType."
+msgstr "Error inicializando FreeType."
+
+#: scene/resources/dynamic_font.cpp
+msgid "Unknown font format."
+msgstr "Formato de tipografía desconocido."
+
+#: scene/resources/dynamic_font.cpp
+msgid "Error loading font."
+msgstr "Error cargando tipografía."
+
+#: scene/resources/dynamic_font.cpp
+msgid "Invalid font size."
+msgstr "Tamaño de tipografía inválido."
+
+#~ msgid "Filter:"
+#~ msgstr "Filtro:"
+
+#~ msgid "' parsing of config failed."
+#~ msgstr "' falló el parseo de la configuración."
+
+#~ msgid "Theme"
+#~ msgstr "Tema"
+
+#~ msgid "Method List For '%s':"
+#~ msgstr "Lista de Métodos Para '%s':"
+
+#~ msgid "Arguments:"
+#~ msgstr "Argumentos:"
+
+#~ msgid "Return:"
+#~ msgstr "Retornar:"
+
+#~ msgid "Added:"
+#~ msgstr "Agregado:"
+
+#~ msgid "Removed:"
+#~ msgstr "Removido:"
+
+#~ msgid "Error saving atlas:"
+#~ msgstr "Error al guardar atlas:"
+
+#~ msgid "Could not save atlas subtexture:"
+#~ msgstr "No se pudo guardar la subtextura de altas:"
+
+#~ msgid "Exporting for %s"
+#~ msgstr "Exportando para %s"
+
+#~ msgid "Setting Up.."
+#~ msgstr "Configurando.."
+
+#~ msgid "Error loading scene."
+#~ msgstr "Error al cargar la escena."
+
+#~ msgid "Re-Import"
+#~ msgstr "Reimportar"
+
+#~ msgid "Please wait for scan to complete."
+#~ msgstr "Por favor aguarda a que el scan termine."
+
+#~ msgid "Current scene must be saved to re-import."
+#~ msgstr "La escena actual debe ser guardada para reimportar."
+
+#~ msgid "Save & Re-Import"
+#~ msgstr "Guardar y Reimportar"
+
+#~ msgid "Re-Importing"
+#~ msgstr "Reimportando"
+
+#~ msgid "Re-Import Changed Resources"
+#~ msgstr "Reimportar Recursos Cambiados"
+
+#~ msgid "Loading Export Templates"
+#~ msgstr "Cargando Plantillas de Exportación"
+
+#~ msgid ""
+#~ "\n"
+#~ "Status: Needs Re-Import"
+#~ msgstr ""
+#~ "\n"
+#~ "Estado: Necesita Reimportación"
+
+#~ msgid "Same source and destination files, doing nothing."
+#~ msgstr ""
+#~ "Archivos de origen y destino iguales, no se realizará ninguna acción."
+
+#~ msgid "Target file exists, can't overwrite. Delete first."
+#~ msgstr ""
+#~ "El archivo destino existe; no sé puede sobreescribir. Eliminalo primero."
+
+#~ msgid "Same source and destination paths, doing nothing."
+#~ msgstr "Ruta de origen y destino iguales, no se realizará ninguna acción."
+
+#~ msgid "Can't move directories to within themselves."
+#~ msgstr "No se pueden mover directorios dentro de si mismos."
+
+#~ msgid "Can't rename deps for:\n"
+#~ msgstr "No se pueden renombrar las dependencias para:\n"
+
+#~ msgid "Error moving file:\n"
+#~ msgstr "Error al mover el archivo:\n"
+
+#~ msgid "Pick New Name and Location For:"
+#~ msgstr "Elejí un Nuevo Nombre y Ubicación Para:"
+
+#~ msgid "No files selected!"
+#~ msgstr "Ningún Archivo seleccionado!"
+
+#~ msgid "Info"
+#~ msgstr "Info"
+
+#~ msgid "Re-Import.."
+#~ msgstr "Reimportando.."
+
+#~ msgid "No bit masks to import!"
+#~ msgstr "Sin máscaras de bits para importar!"
+
+#~ msgid "Target path is empty."
+#~ msgstr "La ruta de destino está vacía."
+
+#~ msgid "Target path must be a complete resource path."
+#~ msgstr "La ruta de destino debe ser una ruta de recursos completa."
+
+#~ msgid "Target path must exist."
+#~ msgstr "La ruta de destino debe existir."
+
+#~ msgid "Save path is empty!"
+#~ msgstr "La ruta de guardado esta vacía!"
+
+#~ msgid "Import BitMasks"
+#~ msgstr "Importar BitMasks"
+
+#~ msgid "Source Texture(s):"
+#~ msgstr "Textura(s) de Origen:"
+
+#~ msgid "Target Path:"
+#~ msgstr "Ruta de Destino:"
+
+#~ msgid "Accept"
+#~ msgstr "Aceptar"
+
+#~ msgid "Bit Mask"
+#~ msgstr "Máscara de Bits"
+
+#~ msgid "No source font file!"
+#~ msgstr "Sin archivo de tipografías de origen!"
+
+#~ msgid "No target font resource!"
+#~ msgstr "Sin recurso de tipografías de destino!"
+
+#~ msgid ""
+#~ "Invalid file extension.\n"
+#~ "Please use .font."
+#~ msgstr ""
+#~ "Extension de archivo inválida.\n"
+#~ "Usá .fnt, por favor."
+
+#~ msgid "Couldn't save font."
+#~ msgstr "No se pudo guardar la tipografía."
+
+#~ msgid "Source Font:"
+#~ msgstr "Tipografía de Origen:"
+
+#~ msgid "Source Font Size:"
+#~ msgstr "Tamaño de la Tipografía de Origen:"
+
+#~ msgid "Dest Resource:"
+#~ msgstr "Recurso de Dest:"
+
+#~ msgid "The quick brown fox jumps over the lazy dog."
+#~ msgstr "El veloz murciélago hindú comía feliz cardillo y kiwi."
+
+#~ msgid "Test:"
+#~ msgstr "Prueba:"
+
+#~ msgid "Options:"
+#~ msgstr "Opciones:"
+
+#~ msgid "Font Import"
+#~ msgstr "Importar Tipografías"
+
+#~ msgid ""
+#~ "This file is already a Godot font file, please supply a BMFont type file "
+#~ "instead."
+#~ msgstr ""
+#~ "Este archivo ya es un archivo de tipografías de Godot, por favor "
+#~ "suministrar un archivo tipo BMFont."
+
+#~ msgid "Failed opening as BMFont file."
+#~ msgstr "Error al abrir como archivo BMFont."
+
+#~ msgid "Invalid font custom source."
+#~ msgstr "Origen personalizado de tipografía inválido."
+
+#~ msgid "No meshes to import!"
+#~ msgstr "Sin meshes para importar!"
+
+#~ msgid "Single Mesh Import"
+#~ msgstr "Importar Mesh Individual"
+
+#~ msgid "Source Mesh(es):"
+#~ msgstr "Importar Mesh(es) de Origen:"
+
+#~ msgid "Surface %d"
+#~ msgstr "Superficie %d"
+
+#~ msgid "No samples to import!"
+#~ msgstr "Sin muestras que importar!"
+
+#~ msgid "Import Audio Samples"
+#~ msgstr "Importar Muestras de Audio"
+
+#~ msgid "Source Sample(s):"
+#~ msgstr "Muestra(s) de Origen:"
+
+#~ msgid "Audio Sample"
+#~ msgstr "Muestra de Audio"
+
+#~ msgid "New Clip"
+#~ msgstr "Nuevo Clip"
+
+#~ msgid "Flags"
+#~ msgstr "Flags"
+
+#~ msgid "Bake FPS:"
+#~ msgstr "Hacer Bake de FPS:"
+
+#~ msgid "Optimizer"
+#~ msgstr "Optimizar"
+
+#~ msgid "Max Linear Error"
+#~ msgstr "Error Lineal Máximo"
+
+#~ msgid "Max Angular Error"
+#~ msgstr "Error Angular Máximo"
+
+#~ msgid "Max Angle"
+#~ msgstr "Angulo Máximo"
+
+#~ msgid "Clips"
+#~ msgstr "Clips"
+
+#~ msgid "Start(s)"
+#~ msgstr "Comienzo(s)"
+
+#~ msgid "End(s)"
+#~ msgstr "Fin(es)"
+
+#~ msgid "Filters"
+#~ msgstr "Filtros"
+
+#~ msgid "Source path is empty."
+#~ msgstr "La ruta de origen esta vacía."
+
+#~ msgid "Couldn't load post-import script."
+#~ msgstr "No se pudo cargar el script post-importación."
+
+#~ msgid "Invalid/broken script for post-import."
+#~ msgstr "Script post-importación inválido o roto."
+
+#~ msgid "Error importing scene."
+#~ msgstr "Error al importar escena."
+
+#~ msgid "Import 3D Scene"
+#~ msgstr "Importar Escena 3D"
+
+#~ msgid "Source Scene:"
+#~ msgstr "Escena de Origen:"
+
+#~ msgid "Same as Target Scene"
+#~ msgstr "Igual que Escena de Destino"
+
+#~ msgid "Shared"
+#~ msgstr "Compartido"
+
+#~ msgid "Target Texture Folder:"
+#~ msgstr "Carpeta de Textura de Destino:"
+
+#~ msgid "Post-Process Script:"
+#~ msgstr "Script de Postprocesado:"
+
+#~ msgid "Custom Root Node Type:"
+#~ msgstr "Tipo de Nodo Raiz Customizado:"
+
+#~ msgid "Auto"
+#~ msgstr "Auto"
+
+#~ msgid "Root Node Name:"
+#~ msgstr "Nombre del Nodo Raíz:"
+
+#~ msgid "The Following Files are Missing:"
+#~ msgstr "Los Siguientes Archivos estan Faltando:"
+
+#~ msgid "Import Anyway"
+#~ msgstr "Importar de Todos Modos"
+
+#~ msgid "Import & Open"
+#~ msgstr "Importar y Abrir"
+
+#~ msgid "Edited scene has not been saved, open imported scene anyway?"
+#~ msgstr ""
+#~ "La escena editada no ha sido guardada, abrir la escena importada de todos "
+#~ "modos?"
+
+#~ msgid "Import Image:"
+#~ msgstr "Importar Imagen:"
+
+#~ msgid "Couldn't localize path: %s (already local)"
+#~ msgstr "No se pudo localizar la ruta: %s (ya es local)"
+
+#~ msgid "3D Scene Animation"
+#~ msgstr "Animacion de Escena 3D"
+
+#~ msgid "Uncompressed"
+#~ msgstr "Sin Comprimir"
+
+#~ msgid "Compress Lossless (PNG)"
+#~ msgstr "Compresión Sin Pérdidas (PNG)"
+
+#~ msgid "Compress Lossy (WebP)"
+#~ msgstr "Compresión con Pérdidas (WebP)"
+
+#~ msgid "Compress (VRAM)"
+#~ msgstr "Comprimir (VRAM)"
+
+#~ msgid "Texture Format"
+#~ msgstr "Formato de Textura"
+
+#~ msgid "Texture Compression Quality (WebP):"
+#~ msgstr "Calidad de Compresión de Textura (WebP):"
+
+#~ msgid "Texture Options"
+#~ msgstr "Opciones de Textura"
+
+#~ msgid "Please specify some files!"
+#~ msgstr "Por favor especificá algunos archivos!"
+
+#~ msgid "At least one file needed for Atlas."
+#~ msgstr "Se necesita al menos un archivo para el Atlas."
+
+#~ msgid "Error importing:"
+#~ msgstr "Error al importar:"
+
+#~ msgid "Only one file is required for large texture."
+#~ msgstr "Solo se requiere un archivo para textura grande."
+
+#~ msgid "Max Texture Size:"
+#~ msgstr "Tamaño Max. de Textura:"
+
+#~ msgid "Import Textures for Atlas (2D)"
+#~ msgstr "Importar Texturas para Atlas (2D)"
+
+#~ msgid "Cell Size:"
+#~ msgstr "Tamaño de Celda:"
+
+#~ msgid "Large Texture"
+#~ msgstr "Textura Grande"
+
+#~ msgid "Import Large Textures (2D)"
+#~ msgstr "Importar Texturas Grandes (2D)"
+
+#~ msgid "Source Texture"
+#~ msgstr "Textura de Origen"
+
+#~ msgid "Base Atlas Texture"
+#~ msgstr "Textura Base de Atlas"
+
+#~ msgid "Source Texture(s)"
+#~ msgstr "Textura(s) de Origen"
+
+#~ msgid "Import Textures for 2D"
+#~ msgstr "Importar Texturas para 2D"
+
+#~ msgid "Import Textures for 3D"
+#~ msgstr "Importar Texturas para 3D"
+
+#~ msgid "Import Textures"
+#~ msgstr "Importar Texturas"
+
+#~ msgid "2D Texture"
+#~ msgstr "Textura 2D"
+
+#~ msgid "3D Texture"
+#~ msgstr "Textura 3D"
+
+#~ msgid "Atlas Texture"
+#~ msgstr "Textura de Atlas"
+
+#~ msgid ""
+#~ "NOTICE: Importing 2D textures is not mandatory. Just copy png/jpg files "
+#~ "to the project."
+#~ msgstr ""
+#~ "AVISO: Importar texturas 2D no es obligatorio. Simplemente copiá los "
+#~ "archivos png/jpg al proyecto."
+
+#~ msgid "Crop empty space."
+#~ msgstr "Cropear espacio vacio."
+
+#~ msgid "Texture"
+#~ msgstr "Textura"
+
+#~ msgid "Import Large Texture"
+#~ msgstr "Importar Textura Grande"
+
+#~ msgid "Load Source Image"
+#~ msgstr "Cargar Imagen de Origen"
+
+#~ msgid "Slicing"
+#~ msgstr "Rebanar"
+
+#~ msgid "Saving"
+#~ msgstr "Guardando"
+
+#~ msgid "Couldn't save large texture:"
+#~ msgstr "No se pudo guardar la textura grande:"
+
+#~ msgid "Build Atlas For:"
+#~ msgstr "Construir Atlar Para:"
+
+#~ msgid "Loading Image:"
+#~ msgstr "Cargando Imagen:"
+
+#~ msgid "Couldn't load image:"
+#~ msgstr "No se pudo cargar la imagen:"
+
+#~ msgid "Converting Images"
+#~ msgstr "Convirtiendo Imágenes"
+
+#~ msgid "Cropping Images"
+#~ msgstr "Cropeando Imágenes"
+
+#~ msgid "Blitting Images"
+#~ msgstr "Haciendo Blitting de Imágenes"
+
+#~ msgid "Couldn't save atlas image:"
+#~ msgstr "No se pudo guardar la imagen de atlas:"
+
+#~ msgid "Couldn't save converted texture:"
+#~ msgstr "No se pudo guardar la textura convertida:"
+
+#~ msgid "Invalid source!"
+#~ msgstr "Fuente inválida!"
+
+#~ msgid "Invalid translation source!"
+#~ msgstr "Fuente de traducción inválida!"
+
+#~ msgid "Column"
+#~ msgstr "Columna"
+
+#~ msgid "No items to import!"
+#~ msgstr "Sin elementos para importar!"
+
+#~ msgid "No target path!"
+#~ msgstr "Sin ruta de destino!"
+
+#~ msgid "Import Translations"
+#~ msgstr "Importar Traducciones"
+
+#~ msgid "Couldn't import!"
+#~ msgstr "No se pudo importar!"
+
+#~ msgid "Import Translation"
+#~ msgstr "Importar Traducción"
+
+#~ msgid "Source CSV:"
+#~ msgstr "CSV de Origen:"
+
+#~ msgid "Ignore First Row"
+#~ msgstr "Ignorar Primera Columna"
+
+#~ msgid "Compress"
+#~ msgstr "Comprimir"
+
+#~ msgid "Add to Project (project.godot)"
+#~ msgstr "Agregar al Proyecto (project.godot)"
+
+#~ msgid "Import Languages:"
+#~ msgstr "Importar Lenguajes:"
+
+#~ msgid "Translation"
+#~ msgstr "Traducción"
+
+#~ msgid "Parsing %d Triangles:"
+#~ msgstr "Parseando %d Triángulos:"
+
+#~ msgid "Triangle #"
+#~ msgstr "Triangulo #"
+
+#~ msgid "Light Baker Setup:"
+#~ msgstr "Configuración de Baker de Luces:"
+
+#~ msgid "Fixing Lights"
+#~ msgstr "Fijando/Corrigiendo Luces"
+
+#~ msgid "Making BVH"
+#~ msgstr "Creando BVH"
+
+#~ msgid "Transfer to Lightmaps:"
+#~ msgstr "Transferencia a Lightmaps:"
+
+#~ msgid "Allocating Texture #"
+#~ msgstr "Asignando Textura #"
+
+#~ msgid "Baking Triangle #"
+#~ msgstr "Haciendo Bake de Triangulo #"
+
+#~ msgid "Post-Processing Texture #"
+#~ msgstr "Postprocesando Textura #"
+
+#~ msgid "Reset the lightmap octree baking process (start over)."
+#~ msgstr ""
+#~ "Resetear el proceso de bake del octree de mapa de luces (empezar de "
+#~ "nuevo)."
+
+#~ msgid "Zoom (%):"
+#~ msgstr "Zoom (%):"
+
+#~ msgid "Skeleton.."
+#~ msgstr "Esqueleto.."
+
+#~ msgid "Zoom Reset"
+#~ msgstr "Resetear Zoom"
+
+#~ msgid "Zoom Set.."
+#~ msgstr "Setear Zoom.."
+
+#~ msgid "Set a Value"
+#~ msgstr "Setear un Valor"
+
+#~ msgid "Snap (Pixels):"
+#~ msgstr "Snap (Pixeles):"
+
+#~ msgid "Parse BBCode"
+#~ msgstr "Parsear BBCode"
+
+#~ msgid "Length:"
+#~ msgstr "Largo:"
+
+#~ msgid "Open Sample File(s)"
+#~ msgstr "Abrir Archivo(s) de Muestra"
+
+#~ msgid "ERROR: Couldn't load sample!"
+#~ msgstr "ERROR: No se pudo cargar la muestra!"
+
+#~ msgid "Add Sample"
+#~ msgstr "Agregar Muestra"
+
+#~ msgid "Rename Sample"
+#~ msgstr "Renombrar Muestra"
+
+#~ msgid "Delete Sample"
+#~ msgstr "Eliminar Muestra"
+
+#~ msgid "16 Bits"
+#~ msgstr "16 Bits"
+
+#~ msgid "8 Bits"
+#~ msgstr "8 Bits"
+
+#~ msgid "Stereo"
+#~ msgstr "Estereo"
+
+#~ msgid "Mono"
+#~ msgstr "Mono"
+
+#~ msgid "Pitch"
+#~ msgstr "Altura"
+
+#~ msgid "Window"
+#~ msgstr "Ventana"
+
+#~ msgid "Move Right"
+#~ msgstr "Mover a la Derecha"
+
+#~ msgid "Scaling to %s%%."
+#~ msgstr "Escalando a %s%%."
+
+#~ msgid "Up"
+#~ msgstr "Arriba"
+
+#~ msgid "Down"
+#~ msgstr "Abajo"
+
+#~ msgid "Bucket"
+#~ msgstr "Balde"
+
+#~ msgid "Invalid project path, the path must exist!"
+#~ msgstr "Ruta de proyecto inválida, la ruta debe existir!"
+
+#~ msgid "Invalid project path, project.godot must not exist."
+#~ msgstr "Ruta de proyecto inválida, project.godot no debe existir."
+
+#~ msgid "Invalid project path, project.godot must exist."
+#~ msgstr "Ruta de proyecto inválida, project.godot debe existir."
+
+#~ msgid "Project Path (Must Exist):"
+#~ msgstr "Ruta del Proyecto (Debe Existir):"
+
+#~ msgid "Create New Resource"
+#~ msgstr "Crear Nuevo Recurso"
+
+#~ msgid "Open Resource"
+#~ msgstr "Abrir Recurso"
+
+#~ msgid "Save Resource"
+#~ msgstr "Guardar Recurso"
+
+#~ msgid "Resource Tools"
+#~ msgstr "Herramientas de Recursos"
+
+#~ msgid "Make Local"
+#~ msgstr "Crear Local"
+
+#~ msgid "Edit Groups"
+#~ msgstr "Editar Grupos"
+
+#~ msgid "Edit Connections"
+#~ msgstr "Editar Conexiones"
+
+#~ msgid "GridMap Paint"
+#~ msgstr "Pintar GridMap"
+
+#~ msgid "Tiles"
+#~ msgstr "Tiles"
+
+#~ msgid "Areas"
+#~ msgstr "Ãreas"
+
+#~ msgid "Ctrl+"
+#~ msgstr "Ctrl+"
+
+#~ msgid "Down Wheel)"
+#~ msgstr "Rueda Abajo)"
+
+#~ msgid "Up Wheel)"
+#~ msgstr "Rueda Arriba)"
+
#~ msgid "Close scene? (Unsaved changes will be lost)"
#~ msgstr "Cerrar escena? (Los cambios sin guardar se perderán)"
@@ -8017,9 +8269,6 @@ msgstr ""
#~ msgid "Close Goto Prev. Scene"
#~ msgstr "Cerrar e Ir a Escena Prev."
-#~ msgid "Expand to Parent"
-#~ msgstr "Expandir al Padre"
-
#~ msgid "Del"
#~ msgstr "Eliminar"
@@ -8194,18 +8443,12 @@ msgstr ""
#~ msgid "Save Translatable Strings"
#~ msgstr "Guardar Strings Traducibles"
-#~ msgid "Translatable Strings.."
-#~ msgstr "Strings Traducibles.."
-
#~ msgid "Install Export Templates"
#~ msgstr "Instalar Templates de Exportación"
#~ msgid "Edit Script Options"
#~ msgstr "Editar Opciones de Script"
-#~ msgid "Please export outside the project folder!"
-#~ msgstr "Por favor exportá afuera de la carpeta de proyecto!"
-
#~ msgid "Error exporting project!"
#~ msgstr "Error al exportar el proyecto!"
@@ -8264,18 +8507,12 @@ msgstr ""
#~ msgid "Include"
#~ msgstr "Incluir"
-#~ msgid "Change Image Group"
-#~ msgstr "Cambiar Grupo de Imágenes"
-
#~ msgid "Group name can't be empty!"
#~ msgstr "El nombre del grupo no puede estar vacío!"
#~ msgid "Invalid character in group name!"
#~ msgstr "Caracter invalido en el nombre de grupo!"
-#~ msgid "Group name already exists!"
-#~ msgstr "El nombre de grupo ya existe!"
-
#~ msgid "Add Image Group"
#~ msgstr "Agregar Grupo de Imágenes"
@@ -8354,9 +8591,6 @@ msgstr ""
#~ msgid "Preview Atlas"
#~ msgstr "Vista Previa de Atlas"
-#~ msgid "Image Filter:"
-#~ msgstr "Filtro de Imágenes:"
-
#~ msgid "Images:"
#~ msgstr "Imágenes:"
@@ -8423,9 +8657,6 @@ msgstr ""
#~ msgid "Lighting"
#~ msgstr "Iluminación"
-#~ msgid "Toggle Persisting"
-#~ msgstr "Act/Desact. Persistente"
-
#~ msgid "Global"
#~ msgstr "Global"
diff --git a/editor/translations/fa.po b/editor/translations/fa.po
index 7b77165a53..87e473d49c 100644
--- a/editor/translations/fa.po
+++ b/editor/translations/fa.po
@@ -1,5 +1,6 @@
# Persian translation of the Godot Engine editor
-# Copyright (C) 2016-2017 Juan Linietsky, Ariel Manzur and the Godot community
+# Copyright (C) 2007-2017 Juan Linietsky, Ariel Manzur
+# Copyright (C) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)
# This file is distributed under the same license as the Godot source code.
#
# alabd14313 <alabd14313@yahoo.com>, 2016.
@@ -195,10 +196,9 @@ msgid "Create %d NEW tracks and insert keys?"
msgstr "تعداد d% ترک جدید ایجاد، و کلیدها را درج کن؟"
#: editor/animation_editor.cpp editor/create_dialog.cpp
-#: editor/editor_audio_buses.cpp
+#: editor/editor_audio_buses.cpp editor/plugins/abstract_polygon_2d_editor.cpp
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
#: editor/plugins/mesh_instance_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp editor/project_manager.cpp
#: editor/script_create_dialog.cpp
msgid "Create"
@@ -361,269 +361,6 @@ msgstr "نوع مقدار آرایه را تغییر بده"
msgid "Change Array Value"
msgstr "مقدار آرایه را تغییر بده"
-#: editor/asset_library_editor_plugin.cpp
-msgid "Free"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_plugin_settings.cpp
-msgid "Version:"
-msgstr "نسخه:"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Contents:"
-msgstr "مستمر"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "View Files"
-msgstr "پرونده:"
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_help.cpp editor/property_selector.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Description:"
-msgstr "توضیح:"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-#: editor/project_manager.cpp
-msgid "Install"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/call_dialog.cpp
-#: editor/connections_dialog.cpp editor/export_template_manager.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-#: editor/project_settings_editor.cpp editor/property_editor.cpp
-#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Close"
-msgstr "بستن"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve hostname:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Connection error, please try again."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Can't connect."
-msgstr "در حال اتصال..."
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Can't connect to host:"
-msgstr "اتصال به گره:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response from host:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Request failed, return code:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Req. Failed."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Request failed, too many redirects"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Redirect Loop."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Bad download hash, assuming file has been tampered with."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Expected:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Got:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Asset Download Error:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-msgid "Success!"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Fetching:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Resolving.."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Connecting.."
-msgstr "در حال اتصال..."
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Requesting.."
-msgstr "آزمودن"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Error making request"
-msgstr "خطای بارگذاری قلم."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Idle"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Retry"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Download Error"
-msgstr "خطاهای بارگذاری"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Download for this asset is already in progress!"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "first"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "prev"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "next"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "last"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "All"
-msgstr "همه"
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
-#: editor/settings_config_dialog.cpp
-msgid "Search:"
-msgstr "جستجو:"
-
-#: editor/asset_library_editor_plugin.cpp editor/code_editor.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Search"
-msgstr "جستجو"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/project_manager.cpp
-msgid "Import"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Plugins"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Sort:"
-msgstr "مرتب‌سازی:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Reverse"
-msgstr "معکوس"
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Category:"
-msgstr "طبقه‌بندی:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Site:"
-msgstr "تارنما:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Support.."
-msgstr "پشتیبانی.."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Official"
-msgstr "دÙتری"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-msgid "Community"
-msgstr "انجمن"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Testing"
-msgstr "آزمودن"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Assets ZIP File"
-msgstr "Ùایل های ZIP‌ منابع بازی"
-
-#: editor/call_dialog.cpp
-msgid "Method List For '%s':"
-msgstr "لیست متد برای 's%' :"
-
-#: editor/call_dialog.cpp modules/visual_script/visual_script_editor.cpp
-msgid "Call"
-msgstr "Ùراخوانی"
-
-#: editor/call_dialog.cpp
-msgid "Method List:"
-msgstr "Ùهرست متدها:"
-
-#: editor/call_dialog.cpp
-msgid "Arguments:"
-msgstr "نشانوندها:"
-
-#: editor/call_dialog.cpp
-msgid "Return:"
-msgstr "بازگشت:"
-
#: editor/code_editor.cpp
msgid "Go to Line"
msgstr "برو به خط"
@@ -661,6 +398,14 @@ msgstr "عین کلمات (بدون هیچ کم و کاستی)"
msgid "Selection Only"
msgstr "تنها در قسمت انتخاب شده"
+#: editor/code_editor.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
+msgid "Search"
+msgstr "جستجو"
+
#: editor/code_editor.cpp editor/editor_help.cpp
msgid "Find"
msgstr "یاÙتن"
@@ -693,11 +438,11 @@ msgstr "موقع جایگزینی از کاربر بپرس"
msgid "Skip"
msgstr "رد کردن"
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom In"
msgstr "بزرگنمایی بیشتر"
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom Out"
msgstr "بزرگنمایی کمتر"
@@ -765,6 +510,20 @@ msgstr "معوق"
msgid "Oneshot"
msgstr "تک شات"
+#: editor/connections_dialog.cpp editor/dependency_editor.cpp
+#: editor/export_template_manager.cpp
+#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Close"
+msgstr "بستن"
+
#: editor/connections_dialog.cpp
msgid "Connect"
msgstr "اتصال"
@@ -790,7 +549,7 @@ msgstr "در حال اتصال..."
msgid "Disconnect"
msgstr "عدم اتصال"
-#: editor/connections_dialog.cpp editor/node_dock.cpp
+#: editor/connections_dialog.cpp editor/editor_help.cpp editor/node_dock.cpp
msgid "Signals"
msgstr "سیگنال‌ها"
@@ -807,12 +566,25 @@ msgstr ""
msgid "Recent:"
msgstr ""
+#: editor/create_dialog.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/quick_open.cpp editor/settings_config_dialog.cpp
+msgid "Search:"
+msgstr "جستجو:"
+
#: editor/create_dialog.cpp editor/editor_help.cpp
#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/quick_open.cpp
msgid "Matches:"
msgstr "تطبیق‌ها:"
+#: editor/create_dialog.cpp editor/editor_help.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/property_selector.cpp
+#: editor/script_editor_debugger.cpp
+msgid "Description:"
+msgstr "توضیح:"
+
#: editor/dependency_editor.cpp
#, fuzzy
msgid "Search Replacement For:"
@@ -873,6 +645,10 @@ msgid "Owners Of:"
msgstr "مالکانÙ:"
#: editor/dependency_editor.cpp
+msgid "Remove selected files from the project? (no undo)"
+msgstr "آیا پرونده‌های انتخاب شده از پروژه حذ٠شوند؟ (بدون undo)"
+
+#: editor/dependency_editor.cpp
msgid ""
"The files being removed are required by other resources in order for them to "
"work.\n"
@@ -883,8 +659,8 @@ msgstr ""
"آیا در هر صورت حذ٠شوند (بدون undo)؟"
#: editor/dependency_editor.cpp
-msgid "Remove selected files from the project? (no undo)"
-msgstr "آیا پرونده‌های انتخاب شده از پروژه حذ٠شوند؟ (بدون undo)"
+msgid "Cannot remove:\n"
+msgstr ""
#: editor/dependency_editor.cpp
msgid "Error loading:"
@@ -952,11 +728,6 @@ msgstr ""
#: editor/editor_about.cpp
#, fuzzy
-msgid "Authors"
-msgstr "خالق:"
-
-#: editor/editor_about.cpp
-#, fuzzy
msgid "Project Founders"
msgstr "صادر کردن پروژه"
@@ -973,6 +744,39 @@ msgid "Developers"
msgstr ""
#: editor/editor_about.cpp
+#, fuzzy
+msgid "Authors"
+msgstr "خالق:"
+
+#: editor/editor_about.cpp
+msgid "Platinum Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Gold Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Mini Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Gold Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Silver Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Bronze Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
msgid "License"
msgstr ""
@@ -1016,6 +820,16 @@ msgid "Package Installed Successfully!"
msgstr ""
#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Success!"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/project_manager.cpp
+msgid "Install"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
msgid "Package Installer"
msgstr ""
@@ -1066,10 +880,6 @@ msgid "Audio Bus, Drag and Drop to rearrange."
msgstr ""
#: editor/editor_audio_buses.cpp
-msgid "Bus options"
-msgstr ""
-
-#: editor/editor_audio_buses.cpp
msgid "Solo"
msgstr ""
@@ -1081,6 +891,10 @@ msgstr ""
msgid "Bypass"
msgstr ""
+#: editor/editor_audio_buses.cpp
+msgid "Bus options"
+msgstr ""
+
#: editor/editor_audio_buses.cpp editor/plugins/tile_map_editor_plugin.cpp
#: editor/scene_tree_dock.cpp
msgid "Duplicate"
@@ -1088,6 +902,11 @@ msgstr ""
#: editor/editor_audio_buses.cpp
#, fuzzy
+msgid "Reset Volume"
+msgstr "بازنشانی بزرگنمایی"
+
+#: editor/editor_audio_buses.cpp
+#, fuzzy
msgid "Delete Effect"
msgstr "انتخاب شده را حذ٠کن"
@@ -1111,6 +930,11 @@ msgstr "انتخاب شده را به دو تا تکثیر کن"
#: editor/editor_audio_buses.cpp
#, fuzzy
+msgid "Reset Bus Volume"
+msgstr "بازنشانی بزرگنمایی"
+
+#: editor/editor_audio_buses.cpp
+#, fuzzy
msgid "Move Audio Bus"
msgstr "کلید Add را جابجا کن"
@@ -1142,7 +966,8 @@ msgstr ""
msgid "Create a new Bus Layout."
msgstr ""
-#: editor/editor_audio_buses.cpp editor/script_create_dialog.cpp
+#: editor/editor_audio_buses.cpp editor/property_editor.cpp
+#: editor/script_create_dialog.cpp
msgid "Load"
msgstr ""
@@ -1233,7 +1058,7 @@ msgid "Rearrange Autoloads"
msgstr ""
#: editor/editor_autoload_settings.cpp editor/editor_file_dialog.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp scene/gui/file_dialog.cpp
+#: scene/gui/file_dialog.cpp
msgid "Path:"
msgstr "مسیر:"
@@ -1241,9 +1066,7 @@ msgstr "مسیر:"
msgid "Node Name:"
msgstr ""
-#: editor/editor_autoload_settings.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp editor/project_manager.cpp
+#: editor/editor_autoload_settings.cpp editor/project_manager.cpp
msgid "Name"
msgstr ""
@@ -1276,18 +1099,19 @@ msgid "Choose a Directory"
msgstr ""
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Create Folder"
msgstr "پوشه ایجاد کن"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: editor/editor_plugin_settings.cpp editor/plugins/theme_editor_plugin.cpp
-#: editor/project_export.cpp scene/gui/file_dialog.cpp
+#: editor/editor_plugin_settings.cpp editor/filesystem_dock.cpp
+#: editor/plugins/theme_editor_plugin.cpp editor/project_export.cpp
+#: scene/gui/file_dialog.cpp
msgid "Name:"
msgstr "نام:"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Could not create folder."
msgstr "نمی‌تواند یک پوشه ایجاد شود."
@@ -1307,30 +1131,6 @@ msgstr ""
msgid "Template file not found:\n"
msgstr ""
-#: editor/editor_export.cpp
-msgid "Added:"
-msgstr "اÙزوده شده:"
-
-#: editor/editor_export.cpp
-msgid "Removed:"
-msgstr "برداشته شده:"
-
-#: editor/editor_export.cpp
-msgid "Error saving atlas:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Could not save atlas subtexture:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Exporting for %s"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Setting Up.."
-msgstr ""
-
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "File Exists, Overwrite?"
msgstr "Ùایل وجود دارد، آیا بازنویسی شود؟"
@@ -1415,6 +1215,11 @@ msgstr ""
msgid "Move Favorite Down"
msgstr ""
+#: editor/editor_file_dialog.cpp
+#, fuzzy
+msgid "Go to parent folder"
+msgstr "نمی‌تواند یک پوشه ایجاد شود."
+
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Directories & Files:"
msgstr "پوشه‌ها و پرونده‌ها:"
@@ -1429,10 +1234,6 @@ msgid "File:"
msgstr "پرونده:"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
-msgid "Filter:"
-msgstr "صاÙÛŒ:"
-
-#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Must use a valid extension."
msgstr "باید از یک پسوند معتبر استÙاده شود."
@@ -1458,6 +1259,10 @@ msgstr "Ùهرست کلاس:"
msgid "Search Classes"
msgstr "جستجوی کلاسها"
+#: editor/editor_help.cpp editor/plugins/spatial_editor_plugin.cpp
+msgid "Top"
+msgstr ""
+
#: editor/editor_help.cpp editor/property_editor.cpp
msgid "Class:"
msgstr "کلاس:"
@@ -1474,15 +1279,29 @@ msgstr "به ارث رسیده به وسیله:"
msgid "Brief Description:"
msgstr "خلاصه توضیحات:"
+#: editor/editor_help.cpp
+#, fuzzy
+msgid "Members"
+msgstr "عضوها:"
+
#: editor/editor_help.cpp modules/visual_script/visual_script_editor.cpp
msgid "Members:"
msgstr "عضوها:"
#: editor/editor_help.cpp
+#, fuzzy
+msgid "Public Methods"
+msgstr "انتخاب حالت"
+
+#: editor/editor_help.cpp
msgid "Public Methods:"
msgstr ""
#: editor/editor_help.cpp
+msgid "GUI Theme Items"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "GUI Theme Items:"
msgstr ""
@@ -1492,6 +1311,11 @@ msgstr "سیگنال ها:"
#: editor/editor_help.cpp
#, fuzzy
+msgid "Enumerations"
+msgstr "وظایÙ:"
+
+#: editor/editor_help.cpp
+#, fuzzy
msgid "Enumerations:"
msgstr "وظایÙ:"
@@ -1500,19 +1324,50 @@ msgid "enum "
msgstr ""
#: editor/editor_help.cpp
+#, fuzzy
+msgid "Constants"
+msgstr "ثابت"
+
+#: editor/editor_help.cpp
msgid "Constants:"
msgstr ""
#: editor/editor_help.cpp
#, fuzzy
+msgid "Description"
+msgstr "توضیح:"
+
+#: editor/editor_help.cpp
+msgid "Properties"
+msgstr ""
+
+#: editor/editor_help.cpp
+#, fuzzy
msgid "Property Description:"
msgstr "خلاصه توضیحات:"
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this property. Please help us by "
+"[color=$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+
+#: editor/editor_help.cpp
+#, fuzzy
+msgid "Methods"
+msgstr "Ùهرست متدها:"
+
+#: editor/editor_help.cpp
msgid "Method Description:"
msgstr ""
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this method. Please help us by [color="
+"$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Search Text"
msgstr "جستجوی متن"
@@ -1522,24 +1377,21 @@ msgid "Output:"
msgstr " خروجی:"
#: editor/editor_log.cpp editor/plugins/animation_tree_editor_plugin.cpp
-#: editor/plugins/rich_text_editor_plugin.cpp editor/property_editor.cpp
-#: editor/script_editor_debugger.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/property_editor.cpp editor/script_editor_debugger.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Clear"
msgstr "پاک کردن"
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Error saving resource!"
msgstr ""
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Save Resource As.."
msgstr "ذخیره منبع از ..."
-#: editor/editor_node.cpp editor/export_template_manager.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "I see.."
msgstr "من میبینم ..."
@@ -1556,6 +1408,29 @@ msgid "Error while saving."
msgstr ""
#: editor/editor_node.cpp
+#, fuzzy
+msgid "Can't open '%s'."
+msgstr "در حال اتصال..."
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Error while parsing '%s'."
+msgstr "خطای بارگذاری قلم."
+
+#: editor/editor_node.cpp
+msgid "Unexpected end of file '%s'."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Missing '%s' or its dependencies."
+msgstr ""
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Error while loading '%s'."
+msgstr "خطای بارگذاری قلم."
+
+#: editor/editor_node.cpp
msgid "Saving Scene"
msgstr "ذخیره سازی صحنه"
@@ -1613,6 +1488,33 @@ msgid "Restored default layout to base settings."
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was imported, so it's not editable.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was instanced or inherited.\n"
+"Changes to it will not be kept when saving the current scene."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource was imported, so it's not editable. Change its settings in the "
+"import panel and then re-import."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This scene was imported, so changes to it will not be kept.\n"
+"Instancing it or inheriting will allow making changes to it.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Copy Params"
msgstr ""
@@ -1776,23 +1678,35 @@ msgid "Save changes the following scene(s) before opening Project Manager?"
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"This option is deprecated. Situations where refresh must be forced are now "
+"considered a bug. Please report."
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Pick a Main Scene"
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to enable addon plugin at: '"
+msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr ""
#: editor/editor_node.cpp
-msgid "' parsing of config failed."
+msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/"
+#, fuzzy
+msgid "Unable to load addon script from path: '%s'."
+msgstr "خطای بارگذاری قلم."
+
+#: editor/editor_node.cpp
+msgid ""
+"Unable to load addon script from path: '%s' Base type is not EditorPlugin."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to load addon script from path: '"
+msgid "Unable to load addon script from path: '%s' Script is not in tool mode."
msgstr ""
#: editor/editor_node.cpp
@@ -1802,7 +1716,7 @@ msgid ""
msgstr ""
#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/scene_tree_dock.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Ugh"
msgstr ""
@@ -1813,11 +1727,11 @@ msgid ""
msgstr ""
#: editor/editor_node.cpp
-msgid "Error loading scene."
+msgid "Scene '%s' has broken dependencies:"
msgstr ""
#: editor/editor_node.cpp
-msgid "Scene '%s' has broken dependencies:"
+msgid "Clear Recent Scenes"
msgstr ""
#: editor/editor_node.cpp
@@ -1853,7 +1767,7 @@ msgstr ""
msgid "Toggle distraction-free mode."
msgstr ""
-#: editor/editor_node.cpp editor/io_plugins/editor_scene_import_plugin.cpp
+#: editor/editor_node.cpp
msgid "Scene"
msgstr "صحنه"
@@ -2075,6 +1989,10 @@ msgstr ""
msgid "Issue Tracker"
msgstr ""
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+msgid "Community"
+msgstr "انجمن"
+
#: editor/editor_node.cpp
msgid "About"
msgstr "معرÙÛŒ"
@@ -2083,7 +2001,7 @@ msgstr "معرÙÛŒ"
msgid "Play the project."
msgstr ""
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Play"
msgstr "پخش"
@@ -2099,7 +2017,7 @@ msgstr ""
msgid "Stop the scene."
msgstr ""
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Stop"
msgstr ""
@@ -2172,6 +2090,15 @@ msgid "Object properties."
msgstr ""
#: editor/editor_node.cpp
+msgid "Changes may be lost!"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Import"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "FileSystem"
msgstr ""
@@ -2187,14 +2114,6 @@ msgstr "خروجی"
msgid "Don't Save"
msgstr ""
-#: editor/editor_node.cpp editor/editor_reimport_dialog.cpp
-msgid "Re-Import"
-msgstr ""
-
-#: editor/editor_node.cpp editor/editor_plugin_settings.cpp
-msgid "Update"
-msgstr "بروز رسانی"
-
#: editor/editor_node.cpp
msgid "Import Templates From ZIP File"
msgstr "واردکردن قالب ها از درون یک Ùایل ZIP"
@@ -2261,11 +2180,28 @@ msgstr "ویرایشگر بستگی"
msgid "Open the previous Editor"
msgstr ""
+#: editor/editor_plugin.cpp
+msgid "Creating Mesh Previews"
+msgstr ""
+
+#: editor/editor_plugin.cpp
+msgid "Thumbnail.."
+msgstr ""
+
#: editor/editor_plugin_settings.cpp
msgid "Installed Plugins:"
msgstr "اÙزونه های نصب شده:"
#: editor/editor_plugin_settings.cpp
+msgid "Update"
+msgstr "بروز رسانی"
+
+#: editor/editor_plugin_settings.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Version:"
+msgstr "نسخه:"
+
+#: editor/editor_plugin_settings.cpp
msgid "Author:"
msgstr "خالق:"
@@ -2298,7 +2234,7 @@ msgid "Frame %"
msgstr ""
#: editor/editor_profiler.cpp
-msgid "Fixed Frame %"
+msgid "Physics Frame %"
msgstr ""
#: editor/editor_profiler.cpp editor/script_editor_debugger.cpp
@@ -2317,26 +2253,6 @@ msgstr ""
msgid "Frame #:"
msgstr ""
-#: editor/editor_reimport_dialog.cpp
-msgid "Please wait for scan to complete."
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Current scene must be saved to re-import."
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Save & Re-Import"
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Importing"
-msgstr "در حال وارد کردن دوباره..."
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Import Changed Resources"
-msgstr ""
-
#: editor/editor_run_native.cpp
msgid "Select device from the list"
msgstr ""
@@ -2447,10 +2363,6 @@ msgid "Importing:"
msgstr ""
#: editor/export_template_manager.cpp
-msgid "Loading Export Templates"
-msgstr ""
-
-#: editor/export_template_manager.cpp
#, fuzzy
msgid "Current Version:"
msgstr "نسخه:"
@@ -2487,9 +2399,17 @@ msgid "Cannot navigate to '"
msgstr ""
#: editor/filesystem_dock.cpp
+msgid "View items as a grid of thumbnails"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "View items as a list"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
msgid ""
"\n"
-"Status: Needs Re-Import"
+"Status: Import of file failed. Please fix file and reimport manually."
msgstr ""
#: editor/filesystem_dock.cpp
@@ -2500,45 +2420,51 @@ msgid ""
msgstr "منبع"
#: editor/filesystem_dock.cpp
-msgid "Same source and destination files, doing nothing."
+msgid "Cannot move/rename resources root."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Target file exists, can't overwrite. Delete first."
+msgid "Cannot move a folder into itself.\n"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Same source and destination paths, doing nothing."
-msgstr ""
+#, fuzzy
+msgid "Error moving:\n"
+msgstr "خطا در بارگذاری:"
#: editor/filesystem_dock.cpp
-msgid "Can't move directories to within themselves."
+#, fuzzy
+msgid "Unable to update dependencies:\n"
+msgstr "خطا در بارگذاری صحنه به دلیل بستگی‌های Ù…Ùقود:"
+
+#: editor/filesystem_dock.cpp
+msgid "No name provided"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Can't rename deps for:\n"
+msgid "Provided name contains invalid characters"
msgstr ""
#: editor/filesystem_dock.cpp
-#, fuzzy
-msgid "Error moving file:\n"
-msgstr "خطا در بارگذاری:"
+msgid "No name provided."
+msgstr ""
#: editor/filesystem_dock.cpp
#, fuzzy
-msgid "Error moving dir:\n"
-msgstr "خطا در بارگذاری:"
+msgid "Name contains invalid characters."
+msgstr "کاراکترهای معتبر:"
#: editor/filesystem_dock.cpp
-msgid "Can't operate on '..'"
+msgid "A file or folder with this name already exists."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Pick New Name and Location For:"
-msgstr ""
+#, fuzzy
+msgid "Renaming file:"
+msgstr "تغییر متغیر"
#: editor/filesystem_dock.cpp
-msgid "No files selected!"
+msgid "Renaming folder:"
msgstr ""
#: editor/filesystem_dock.cpp
@@ -2550,39 +2476,36 @@ msgid "Collapse all"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Show In File Manager"
+msgid "Copy Path"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Instance"
+msgid "Rename.."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Edit Dependencies.."
-msgstr ""
-
-#: editor/filesystem_dock.cpp
-msgid "View Owners.."
+msgid "Move To.."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Copy Path"
-msgstr ""
+#, fuzzy
+msgid "New Folder.."
+msgstr "پوشه ایجاد کن"
#: editor/filesystem_dock.cpp
-msgid "Rename or Move.."
+msgid "Show In File Manager"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Move To.."
+msgid "Instance"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Info"
+msgid "Edit Dependencies.."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Re-Import.."
+msgid "View Owners.."
msgstr ""
#: editor/filesystem_dock.cpp
@@ -2615,6 +2538,11 @@ msgstr ""
msgid "Move"
msgstr ""
+#: editor/filesystem_dock.cpp editor/plugins/animation_tree_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Rename"
+msgstr ""
+
#: editor/groups_editor.cpp
msgid "Add to Group"
msgstr ""
@@ -2628,6 +2556,10 @@ msgid "Import as Single Scene"
msgstr ""
#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
msgid "Import with Separate Materials"
msgstr ""
@@ -2640,6 +2572,18 @@ msgid "Import with Separate Objects+Materials"
msgstr ""
#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Materials+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Materials+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
msgid "Import as Multiple Scenes"
msgstr ""
@@ -2648,38 +2592,31 @@ msgid "Import as Multiple Scenes+Materials"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Import Scene"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Importing Scene.."
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Running Custom Script.."
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Couldn't load post-import script:"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Invalid/broken script for post-import (check console):"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Error running post-import script:"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Saving.."
msgstr ""
@@ -2709,581 +2646,54 @@ msgstr ""
msgid "Reimport"
msgstr "در حال وارد کردن دوباره..."
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "No bit masks to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path is empty."
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must be a complete resource path."
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must exist."
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Save path is empty!"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Import BitMasks"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s):"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Target Path:"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Accept"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Bit Mask"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No source font file!"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No target font resource!"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"Invalid file extension.\n"
-"Please use .font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Can't load/process source font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Couldn't save font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font Size:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Dest Resource:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "The quick brown fox jumps over the lazy dog."
-msgstr ""
-"کلاغ Ùرز Ùˆ چابک، ظهر هر روز با صدای ضخیم Ùˆ عذاب‌آورش بـه جستجوی یک مثقال گنج "
-"پنهان در حیاط رژه Ù…ÛŒ رÙت."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Test:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Options:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Font Import"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"This file is already a Godot font file, please supply a BMFont type file "
-"instead."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Failed opening as BMFont file."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error initializing FreeType."
-msgstr "خطا در ارزش‌دهی آغارین به FreeType."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Unknown font format."
-msgstr "Ùرمت قلم ناشناخته."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error loading font."
-msgstr "خطای بارگذاری قلم."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Invalid font size."
-msgstr "اندازه‌ی قلم نامعتبر."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Invalid font custom source."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/plugins/theme_editor_plugin.cpp
-msgid "Font"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "No meshes to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Single Mesh Import"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Source Mesh(es):"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/plugins/mesh_instance_editor_plugin.cpp
-msgid "Mesh"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Surface %d"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "No samples to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Import Audio Samples"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Source Sample(s):"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Audio Sample"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "New Clip"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Animation Options"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Flags"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Bake FPS:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Optimizer"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Linear Error"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angular Error"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angle"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Clips"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Start(s)"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "End(s)"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Loop"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Filters"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source path is empty."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't load post-import script."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Invalid/broken script for post-import."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Error importing scene."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import 3D Scene"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source Scene:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Same as Target Scene"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Shared"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Target Texture Folder:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Post-Process Script:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Custom Root Node Type:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Auto"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Root Node Name:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "The Following Files are Missing:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Anyway"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp scene/gui/dialogs.cpp
-msgid "Cancel"
-msgstr "لغو"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import & Open"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Edited scene has not been saved, open imported scene anyway?"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Image:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Can't import a file over itself:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't localize path: %s (already local)"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "3D Scene Animation"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Uncompressed"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossless (PNG)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossy (WebP)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress (VRAM)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Format"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Compression Quality (WebP):"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Options"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Please specify some files!"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "At least one file needed for Atlas."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Error importing:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Only one file is required for large texture."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Max Texture Size:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for Atlas (2D)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cell Size:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Large Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Textures (2D)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture"
+#: editor/multi_node_edit.cpp
+msgid "MultiNode Set"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Base Atlas Texture"
+#: editor/node_dock.cpp
+msgid "Groups"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s)"
+#: editor/node_dock.cpp
+msgid "Select a Node to edit Signals and Groups."
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 2D"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create Poly"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 3D"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Insert Point"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "2D Texture"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly (Remove Point)"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "3D Texture"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Remove Poly And Point"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Atlas Texture"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create a new polygon from scratch."
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
+#: editor/plugins/abstract_polygon_2d_editor.cpp
msgid ""
-"NOTICE: Importing 2D textures is not mandatory. Just copy png/jpg files to "
-"the project."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Crop empty space."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Load Source Image"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Slicing"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Inserting"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Saving"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save large texture:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Build Atlas For:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Loading Image:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't load image:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Converting Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cropping Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Blitting Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save atlas image:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save converted texture:"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid source!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid translation source!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Column"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/script_create_dialog.cpp
-msgid "Language"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No items to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No target path!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translations"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Couldn't import!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translation"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Source CSV:"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Ignore First Row"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Compress"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Add to Project (project.godot)"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Languages:"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Translation"
-msgstr ""
-
-#: editor/multi_node_edit.cpp
-msgid "MultiNode Set"
-msgstr ""
-
-#: editor/node_dock.cpp
-msgid "Groups"
-msgstr ""
-
-#: editor/node_dock.cpp
-msgid "Select a Node to edit Signals and Groups."
+"Edit existing polygon:\n"
+"LMB: Move Point.\n"
+"Ctrl+LMB: Split Segment.\n"
+"RMB: Erase Point."
msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
@@ -3440,7 +2850,6 @@ msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
#: editor/script_create_dialog.cpp
msgid "Error!"
@@ -3551,10 +2960,6 @@ msgid "Delete Input"
msgstr ""
#: editor/plugins/animation_tree_editor_plugin.cpp
-msgid "Rename"
-msgstr ""
-
-#: editor/plugins/animation_tree_editor_plugin.cpp
msgid "Animation tree is valid."
msgstr ""
@@ -3610,64 +3015,189 @@ msgstr ""
msgid "Filters.."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing %d Triangles:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Free"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Triangle #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Contents:"
+msgstr "مستمر"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "View Files"
+msgstr "پرونده:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve hostname:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Light Baker Setup:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing Geometry"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connection error, please try again."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Fixing Lights"
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Can't connect."
+msgstr "در حال اتصال..."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Can't connect to host:"
+msgstr "اتصال به گره:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response from host:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Making BVH"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Light Octree"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, return code:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Octree Texture"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Req. Failed."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Transfer to Lightmaps:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, too many redirects"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Allocating Texture #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Redirect Loop."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Baking Triangle #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Post-Processing Texture #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Bad download hash, assuming file has been tampered with."
msgstr ""
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Bake!"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Expected:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Got:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed sha256 hash check"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Asset Download Error:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Fetching:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Resolving.."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Connecting.."
+msgstr "در حال اتصال..."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Requesting.."
+msgstr "آزمودن"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Error making request"
+msgstr "خطای بارگذاری قلم."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Idle"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Retry"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Download Error"
+msgstr "خطاهای بارگذاری"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download for this asset is already in progress!"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "first"
msgstr ""
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Reset the lightmap octree baking process (start over)."
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "prev"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "next"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "last"
msgstr ""
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "All"
+msgstr "همه"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Plugins"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Sort:"
+msgstr "مرتب‌سازی:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Reverse"
+msgstr "معکوس"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Category:"
+msgstr "طبقه‌بندی:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Site:"
+msgstr "تارنما:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Support.."
+msgstr "پشتیبانی.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Official"
+msgstr "دÙتری"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Testing"
+msgstr "آزمودن"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Assets ZIP File"
+msgstr "Ùایل های ZIP‌ منابع بازی"
+
#: editor/plugins/camera_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
msgid "Preview"
msgstr ""
@@ -3710,11 +3240,15 @@ msgid "Edit CanvasItem"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Change Anchors"
+msgid "Anchors only"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Change Anchors and Margins"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom (%):"
+msgid "Change Anchors"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3765,59 +3299,73 @@ msgid "Pan Mode"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Lock the selected object in place (can't be moved)."
+#, fuzzy
+msgid "Toggles snapping"
+msgstr "یک Breakpoint درج کن"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Use Snap"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Unlock the selected object (can be moved)."
+msgid "Snapping options"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Makes sure the object's children are not selectable."
+msgid "Snap to grid"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Restores the object's children's ability to be selected."
+msgid "Use Rotation Snap"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Edit"
-msgstr "ویرایش کردن"
+msgid "Configure Snap..."
+msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Use Snap"
+msgid "Snap Relative"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Show Grid"
+msgid "Use Pixel Snap"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Rotation Snap"
+msgid "Smart snapping"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap Relative"
+msgid "Snap to parent"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Configure Snap.."
+msgid "Snap to node anchor"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Pixel Snap"
+msgid "Snap to node sides"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to other nodes"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Lock the selected object in place (can't be moved)."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Unlock the selected object (can be moved)."
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Skeleton.."
+msgid "Makes sure the object's children are not selectable."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Restores the object's children's ability to be selected."
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3846,11 +3394,16 @@ msgid "View"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Reset"
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Show Grid"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Set.."
+msgid "Show helpers"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Show rulers"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3862,7 +3415,7 @@ msgid "Frame Selection"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Anchor"
+msgid "Layout"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3886,11 +3439,20 @@ msgid "Clear Pose"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Set a Value"
+msgid "Drag pivot from mouse position"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap (Pixels):"
+#, fuzzy
+msgid "Set pivot at mouse position"
+msgstr "برداشتن موج"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Multiply grid step by 2"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Divide grid step by 2"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3901,23 +3463,28 @@ msgstr ""
msgid "Adding %s..."
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Create Node"
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Error instancing scene from %s"
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "OK :("
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "No parent to instance a child at."
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "This operation requires a single selected node."
msgstr ""
@@ -3932,45 +3499,6 @@ msgid ""
"Drag & drop + Alt : Change node type"
msgstr ""
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Create Poly"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly (Remove Point)"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Create a new polygon from scratch."
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-msgid ""
-"Edit existing polygon:\n"
-"LMB: Move Point.\n"
-"Ctrl+LMB: Split Segment.\n"
-"RMB: Erase Point."
-msgstr ""
-
#: editor/plugins/collision_polygon_editor_plugin.cpp
msgid "Create Poly3D"
msgstr ""
@@ -3980,14 +3508,6 @@ msgid "Set Handle"
msgstr ""
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Creating Mesh Library"
-msgstr ""
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Thumbnail.."
-msgstr ""
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Remove item %d?"
msgstr ""
@@ -4010,6 +3530,27 @@ msgid "Update from Scene"
msgstr ""
#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat0"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat1"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+#, fuzzy
+msgid "Ease in"
+msgstr "انتخاب شده را تغییر مقیاس بده"
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Ease out"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Smoothstep"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
msgid "Modify Curve Point"
msgstr ""
@@ -4091,22 +3632,18 @@ msgid "Create Occluder Polygon"
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Edit existing polygon:"
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "LMB: Move Point."
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Ctrl+LMB: Split Segment."
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "RMB: Erase Point."
msgstr ""
@@ -4208,6 +3745,10 @@ msgid "Create Outline"
msgstr ""
#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Mesh"
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Create Trimesh Static Body"
msgstr ""
@@ -4335,12 +3876,72 @@ msgstr ""
msgid "Populate"
msgstr ""
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Create Navigation Polygon"
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake!"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake the navigation mesh.\n"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Clear the navigation mesh."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Setting up Configuration..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Calculating grid size..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating heightfield..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Marking walkable triangles..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Constructing compact heightfield..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Eroding walkable area..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Partitioning..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating contours..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating polymesh..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Converting to native navigation mesh..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Navigation Mesh Generator Setup:"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Parsing Geometry..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Done!"
msgstr ""
#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Remove Poly And Point"
+msgid "Create Navigation Polygon"
msgstr ""
#: editor/plugins/particles_2d_editor_plugin.cpp
@@ -4514,16 +4115,19 @@ msgid "Curve Point #"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve Point Position"
-msgstr ""
+msgstr "برداشتن موج"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve In Position"
-msgstr ""
+msgstr "برداشتن موج"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve Out Position"
-msgstr ""
+msgstr "برداشتن موج"
#: editor/plugins/path_editor_plugin.cpp
msgid "Split Path"
@@ -4583,6 +4187,14 @@ msgid "Scale Polygon"
msgstr ""
#: editor/plugins/polygon_2d_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Edit"
+msgstr "ویرایش کردن"
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Polygon->UV"
msgstr ""
@@ -4637,63 +4249,10 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/shader_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "چسباندن"
-#: editor/plugins/rich_text_editor_plugin.cpp
-msgid "Parse BBCode"
-msgstr ""
-
-#: editor/plugins/sample_editor_plugin.cpp
-msgid "Length:"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Open Sample File(s)"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "ERROR: Couldn't load sample!"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Add Sample"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Rename Sample"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Delete Sample"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "16 Bits"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "8 Bits"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Stereo"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Mono"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Format"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Pitch"
-msgstr ""
-
#: editor/plugins/script_editor_plugin.cpp
msgid "Clear Recent Files"
msgstr ""
@@ -4785,6 +4344,10 @@ msgstr ""
msgid "Close All"
msgstr "بستن"
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+msgid "Run"
+msgstr ""
+
#: editor/plugins/script_editor_plugin.cpp
msgid "Toggle Scripts Panel"
msgstr ""
@@ -4813,7 +4376,8 @@ msgstr ""
msgid "Break"
msgstr ""
-#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+#: editor/script_editor_debugger.cpp
msgid "Continue"
msgstr ""
@@ -4827,18 +4391,6 @@ msgid "Debug with external editor"
msgstr "ویرایشگر بستگی"
#: editor/plugins/script_editor_plugin.cpp
-msgid "Window"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Left"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Right"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
msgid "Open Godot online documentation"
msgstr ""
@@ -4921,8 +4473,9 @@ msgid "Cut"
msgstr "بریدن"
#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "کپی کردن"
@@ -5187,10 +4740,6 @@ msgid "View Plane Transform."
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Scaling to %s%%."
-msgstr ""
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rotating %s degrees."
msgstr ""
@@ -5207,10 +4756,6 @@ msgid "Top View."
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Top"
-msgstr ""
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rear View."
msgstr ""
@@ -5443,6 +4988,10 @@ msgid "Transform"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Configure Snap.."
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Local Coords"
msgstr ""
@@ -5588,6 +5137,10 @@ msgid "Speed (FPS):"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Loop"
+msgstr ""
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Animation Frames"
msgstr ""
@@ -5600,11 +5153,12 @@ msgid "Insert Empty (After)"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Up"
-msgstr ""
+#, fuzzy
+msgid "Move (Before)"
+msgstr "مسیر به سمت گره:"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Down"
+msgid "Move (After)"
msgstr ""
#: editor/plugins/style_box_editor_plugin.cpp
@@ -5683,7 +5237,11 @@ msgid "Remove All"
msgstr "برداشتن"
#: editor/plugins/theme_editor_plugin.cpp
-msgid "Theme"
+msgid "Edit theme.."
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Theme editing menu."
msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
@@ -5768,6 +5326,10 @@ msgid "Style"
msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
+msgid "Font"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
msgid "Color"
msgstr ""
@@ -5818,7 +5380,7 @@ msgid "Mirror Y"
msgstr ""
#: editor/plugins/tile_map_editor_plugin.cpp
-msgid "Bucket"
+msgid "Paint Tile"
msgstr ""
#: editor/plugins/tile_map_editor_plugin.cpp
@@ -5884,6 +5446,10 @@ msgid "Delete preset '%s'?"
msgstr "آیا پرونده‌های انتخاب شده حذ٠شود؟"
#: editor/project_export.cpp
+msgid "Export templates for this platform are missing/corrupted: "
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Presets"
msgstr ""
@@ -5956,19 +5522,30 @@ msgid "Export templates for this platform are missing:"
msgstr ""
#: editor/project_export.cpp
+msgid "Export templates for this platform are missing/corrupted:"
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Export With Debug"
msgstr ""
#: editor/project_manager.cpp
-msgid "Invalid project path, the path must exist!"
+#, fuzzy
+msgid "The path does not exist."
+msgstr "پرونده موجود نیست."
+
+#: editor/project_manager.cpp
+msgid "Please choose a 'project.godot' file."
msgstr ""
#: editor/project_manager.cpp
-msgid "Invalid project path, project.godot must not exist."
+msgid ""
+"Your project will be created in a non empty folder (you might want to create "
+"a new folder)."
msgstr ""
#: editor/project_manager.cpp
-msgid "Invalid project path, project.godot must exist."
+msgid "Please choose a folder that does not contain a 'project.godot' file."
msgstr ""
#: editor/project_manager.cpp
@@ -5976,10 +5553,26 @@ msgid "Imported Project"
msgstr ""
#: editor/project_manager.cpp
+msgid " "
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "It would be a good idea to name your project."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Invalid project path (changed anything?)."
msgstr ""
#: editor/project_manager.cpp
+msgid "Couldn't get project.godot in project path."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Couldn't edit project.godot in project path."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
msgstr ""
@@ -5988,15 +5581,20 @@ msgid "The following files failed extraction from package:"
msgstr ""
#: editor/project_manager.cpp
-msgid "Import Existing Project"
+#, fuzzy
+msgid "Rename Project"
+msgstr "صادر کردن پروژه"
+
+#: editor/project_manager.cpp
+msgid "Couldn't get project.godot in the project path."
msgstr ""
#: editor/project_manager.cpp
-msgid "Project Path (Must Exist):"
+msgid "New Game Project"
msgstr ""
#: editor/project_manager.cpp
-msgid "Project Name:"
+msgid "Import Existing Project"
msgstr ""
#: editor/project_manager.cpp
@@ -6004,19 +5602,24 @@ msgid "Create New Project"
msgstr ""
#: editor/project_manager.cpp
-msgid "Project Path:"
+msgid "Install Project:"
msgstr ""
#: editor/project_manager.cpp
-msgid "Install Project:"
+msgid "Project Name:"
msgstr ""
#: editor/project_manager.cpp
-msgid "Browse"
+#, fuzzy
+msgid "Create folder"
+msgstr "پوشه ایجاد کن"
+
+#: editor/project_manager.cpp
+msgid "Project Path:"
msgstr ""
#: editor/project_manager.cpp
-msgid "New Game Project"
+msgid "Browse"
msgstr ""
#: editor/project_manager.cpp
@@ -6028,6 +5631,11 @@ msgid "Unnamed Project"
msgstr ""
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Can't open project"
+msgstr "در حال اتصال..."
+
+#: editor/project_manager.cpp
msgid "Are you sure to open more than one project?"
msgstr ""
@@ -6054,6 +5662,12 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
+"Language changed.\n"
+"The UI will update next time the editor or project manager starts."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid ""
"You are about the scan %s folders for existing Godot projects. Do you "
"confirm?"
msgstr ""
@@ -6065,10 +5679,6 @@ msgid "Project List"
msgstr ""
#: editor/project_manager.cpp
-msgid "Run"
-msgstr ""
-
-#: editor/project_manager.cpp
msgid "Scan"
msgstr ""
@@ -6090,6 +5700,10 @@ msgid "Exit"
msgstr ""
#: editor/project_manager.cpp
+msgid "Restart Now"
+msgstr ""
+
+#: editor/project_manager.cpp
#, fuzzy
msgid "Can't run project"
msgstr "در حال اتصال..."
@@ -6127,17 +5741,14 @@ msgid "Add Input Action Event"
msgstr ""
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Meta+"
msgstr "+Meta"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Shift+"
msgstr "+Shift"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Alt+"
msgstr "+Alt"
@@ -6198,7 +5809,7 @@ msgstr "تغییر بده"
msgid "Joypad Axis Index:"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Axis"
msgstr "محور"
@@ -6218,31 +5829,31 @@ msgstr ""
msgid "Add Event"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Device"
msgstr "دستگاه"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Button"
msgstr "دکمه"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Left Button."
msgstr "دکمه‌ی چپ."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Right Button."
msgstr "دکمه‌ی راست."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Middle Button."
msgstr "دکمه‌ی وسط."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Up."
msgstr "غلطاندن به بالا."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Down."
msgstr "غلطاندن به پایین."
@@ -6252,7 +5863,7 @@ msgid "Add Global Property"
msgstr "دارایی Getter را اضاÙÙ‡ Ú©Ù†"
#: editor/project_settings_editor.cpp
-msgid "Select an setting item first!"
+msgid "Select a setting item first!"
msgstr ""
#: editor/project_settings_editor.cpp
@@ -6270,6 +5881,15 @@ msgid "Delete Item"
msgstr "حذ٠کن"
#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Can't contain '/' or ':'"
+msgstr "اتصال به گره:"
+
+#: editor/project_settings_editor.cpp
+msgid "Already existing"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "Error saving settings."
msgstr ""
@@ -6310,6 +5930,15 @@ msgid "Remove Resource Remap Option"
msgstr ""
#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Changed Locale Filter"
+msgstr "نوع مقدار آرایه را تغییر بده"
+
+#: editor/project_settings_editor.cpp
+msgid "Changed Locale Filter Mode"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "Project Settings (project.godot)"
msgstr ""
@@ -6370,6 +5999,27 @@ msgid "Locale"
msgstr ""
#: editor/project_settings_editor.cpp
+msgid "Locales Filter"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Show all locales"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Show only selected locales"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Filter mode:"
+msgstr "صاÙÛŒ:"
+
+#: editor/project_settings_editor.cpp
+msgid "Locales:"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "AutoLoad"
msgstr ""
@@ -6420,10 +6070,19 @@ msgid "New Script"
msgstr "صحنه جدید"
#: editor/property_editor.cpp
+msgid "Make Unique"
+msgstr ""
+
+#: editor/property_editor.cpp
msgid "Show in File System"
msgstr ""
#: editor/property_editor.cpp
+#, fuzzy
+msgid "Convert To %s"
+msgstr "اتصال به گره:"
+
+#: editor/property_editor.cpp
msgid "Error loading file: Not a resource!"
msgstr ""
@@ -6463,6 +6122,11 @@ msgstr "دارایی Setter را اضاÙÙ‡ Ú©Ù†"
#: editor/property_selector.cpp
#, fuzzy
+msgid "Select Virtual Method"
+msgstr "انتخاب حالت"
+
+#: editor/property_selector.cpp
+#, fuzzy
msgid "Select Method"
msgstr "انتخاب حالت"
@@ -6490,26 +6154,6 @@ msgstr ""
msgid "Reparent"
msgstr ""
-#: editor/resources_dock.cpp
-msgid "Create New Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Open Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Save Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Resource Tools"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Make Local"
-msgstr ""
-
#: editor/run_settings_dialog.cpp
msgid "Run Mode:"
msgstr ""
@@ -6637,14 +6281,6 @@ msgid "Sub-Resources:"
msgstr "منبع"
#: editor/scene_tree_dock.cpp
-msgid "Edit Groups"
-msgstr ""
-
-#: editor/scene_tree_dock.cpp
-msgid "Edit Connections"
-msgstr ""
-
-#: editor/scene_tree_dock.cpp
msgid "Clear Inheritance"
msgstr ""
@@ -6832,6 +6468,15 @@ msgid "Invalid base path"
msgstr ""
#: editor/script_create_dialog.cpp
+msgid "Directory of the same name exists"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
+#, fuzzy
+msgid "File exists, will be reused"
+msgstr "Ùایل وجود دارد، آیا بازنویسی شود؟"
+
+#: editor/script_create_dialog.cpp
msgid "Invalid extension"
msgstr ""
@@ -6875,6 +6520,10 @@ msgid "Load existing script file"
msgstr ""
#: editor/script_create_dialog.cpp
+msgid "Language"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
#, fuzzy
msgid "Inherits"
msgstr "میراث:"
@@ -6919,6 +6568,10 @@ msgid "Function:"
msgstr ""
#: editor/script_editor_debugger.cpp
+msgid "Pick one or more items from the list to display the graph."
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
msgid "Errors"
msgstr ""
@@ -6999,6 +6652,10 @@ msgid "Type"
msgstr ""
#: editor/script_editor_debugger.cpp
+msgid "Format"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
msgid "Usage"
msgstr ""
@@ -7074,6 +6731,24 @@ msgstr ""
msgid "Change Probe Extents"
msgstr ""
+#: modules/gdnative/gd_native_library_editor.cpp
+#, fuzzy
+msgid "Library"
+msgstr "صادکردن Ùایل کتابخانه ای"
+
+#: modules/gdnative/gd_native_library_editor.cpp
+#, fuzzy
+msgid "Status"
+msgstr "وضعیت:"
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Libraries: "
+msgstr ""
+
+#: modules/gdnative/register_types.cpp
+msgid "GDNative"
+msgstr ""
+
#: modules/gdscript/gd_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Invalid type argument to convert(), use TYPE_* constants."
@@ -7081,7 +6756,7 @@ msgstr ""
"نوع آرگومان برای متد ()convert ‌ نامعتبر است ،‌ از ثابت های *_TYPE‌ استÙاده "
"کنید ."
-#: modules/gdscript/gd_functions.cpp
+#: modules/gdscript/gd_functions.cpp modules/mono/glue/glue_header.h
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Not enough bytes for decoding bytes, or invalid format."
msgstr ""
@@ -7138,10 +6813,6 @@ msgid "GridMap Duplicate Selection"
msgstr "انتخاب شده را به دو تا تکثیر کن"
#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "GridMap Paint"
-msgstr ""
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Snap View"
msgstr ""
@@ -7238,13 +6909,8 @@ msgstr "ترجیحات"
msgid "Pick Distance:"
msgstr ""
-#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
-msgid "Tiles"
-msgstr "پرونده:"
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "Areas"
+#: modules/mono/editor/mono_bottom_panel.cpp
+msgid "Builds"
msgstr ""
#: modules/visual_script/visual_script.cpp
@@ -7455,10 +7121,18 @@ msgid "Return"
msgstr "بازگشت:"
#: modules/visual_script/visual_script_editor.cpp
+msgid "Call"
+msgstr "Ùراخوانی"
+
+#: modules/visual_script/visual_script_editor.cpp
msgid "Get"
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
+msgid "Script already has function '%s'"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
#, fuzzy
msgid "Change Input Value"
msgstr "مقدار آرایه را تغییر بده"
@@ -7874,6 +7548,12 @@ msgstr ""
"یک منبع SpriteFrames باید در دارایی Frames ایجاد شده باشد تا "
"AnimatedSprite3D Ùریم‌ها را نمایش دهد."
+#: scene/3d/vehicle_body.cpp
+msgid ""
+"VehicleWheel serves to provide a wheel system to a VehicleBody. Please use "
+"it as a child of a VehicleBody."
+msgstr ""
+
#: scene/gui/color_picker.cpp
msgid "Raw Mode"
msgstr ""
@@ -7883,6 +7563,10 @@ msgid "Add current color as a preset"
msgstr ""
#: scene/gui/dialogs.cpp
+msgid "Cancel"
+msgstr "لغو"
+
+#: scene/gui/dialogs.cpp
msgid "Alert!"
msgstr "هشدار!"
@@ -7890,10 +7574,6 @@ msgstr "هشدار!"
msgid "Please Confirm..."
msgstr "لطÙا تأیید کنید..."
-#: scene/gui/input_action.cpp
-msgid "Ctrl+"
-msgstr "+Ctrl"
-
#: scene/gui/popup.cpp
msgid ""
"Popups will hide by default unless you call popup() or any of the popup*() "
@@ -7929,6 +7609,59 @@ msgstr ""
"تا بتواند یک اندازه بگیرد. در غیر اینصورت، آن را یک RenderTarget قرار دهید و "
"باÙت داخلی آن را برای نمایش به تعدادی گره تخصیص دهید."
+#: scene/resources/dynamic_font.cpp
+msgid "Error initializing FreeType."
+msgstr "خطا در ارزش‌دهی آغارین به FreeType."
+
+#: scene/resources/dynamic_font.cpp
+msgid "Unknown font format."
+msgstr "Ùرمت قلم ناشناخته."
+
+#: scene/resources/dynamic_font.cpp
+msgid "Error loading font."
+msgstr "خطای بارگذاری قلم."
+
+#: scene/resources/dynamic_font.cpp
+msgid "Invalid font size."
+msgstr "اندازه‌ی قلم نامعتبر."
+
+#~ msgid "Filter:"
+#~ msgstr "صاÙÛŒ:"
+
+#~ msgid "Method List For '%s':"
+#~ msgstr "لیست متد برای 's%' :"
+
+#~ msgid "Arguments:"
+#~ msgstr "نشانوندها:"
+
+#~ msgid "Return:"
+#~ msgstr "بازگشت:"
+
+#~ msgid "Added:"
+#~ msgstr "اÙزوده شده:"
+
+#~ msgid "Removed:"
+#~ msgstr "برداشته شده:"
+
+#~ msgid "Re-Importing"
+#~ msgstr "در حال وارد کردن دوباره..."
+
+#, fuzzy
+#~ msgid "Error moving file:\n"
+#~ msgstr "خطا در بارگذاری:"
+
+#~ msgid "The quick brown fox jumps over the lazy dog."
+#~ msgstr ""
+#~ "کلاغ Ùرز Ùˆ چابک، ظهر هر روز با صدای ضخیم Ùˆ عذاب‌آورش بـه جستجوی یک مثقال "
+#~ "گنج پنهان در حیاط رژه Ù…ÛŒ رÙت."
+
+#, fuzzy
+#~ msgid "Tiles"
+#~ msgstr "پرونده:"
+
+#~ msgid "Ctrl+"
+#~ msgstr "+Ctrl"
+
#, fuzzy
#~ msgid "Invalid unique name."
#~ msgstr "نام نامعتبر."
diff --git a/editor/translations/fi.po b/editor/translations/fi.po
index af1d46eae0..12cafa85fc 100644
--- a/editor/translations/fi.po
+++ b/editor/translations/fi.po
@@ -1,5 +1,6 @@
# Finnish translation of the Godot Engine editor
-# Copyright (C) 2016-2017 Juan Linietsky, Ariel Manzur and the Godot community
+# Copyright (C) 2007-2017 Juan Linietsky, Ariel Manzur
+# Copyright (C) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)
# This file is distributed under the same license as the Godot source code.
#
# ekeimaja <ekeimaja@gmail.com>, 2017.
@@ -195,10 +196,9 @@ msgid "Create %d NEW tracks and insert keys?"
msgstr ""
#: editor/animation_editor.cpp editor/create_dialog.cpp
-#: editor/editor_audio_buses.cpp
+#: editor/editor_audio_buses.cpp editor/plugins/abstract_polygon_2d_editor.cpp
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
#: editor/plugins/mesh_instance_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp editor/project_manager.cpp
#: editor/script_create_dialog.cpp
msgid "Create"
@@ -361,272 +361,6 @@ msgstr "Vaihda taulukon arvon tyyppiä"
msgid "Change Array Value"
msgstr "Vaihda taulukon arvoa"
-#: editor/asset_library_editor_plugin.cpp
-msgid "Free"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_plugin_settings.cpp
-msgid "Version:"
-msgstr "Versio:"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Contents:"
-msgstr "Vakiot:"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "View Files"
-msgstr " Tiedostot"
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_help.cpp editor/property_selector.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Description:"
-msgstr "Kuvaus:"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-#: editor/project_manager.cpp
-msgid "Install"
-msgstr "Asenna"
-
-#: editor/asset_library_editor_plugin.cpp editor/call_dialog.cpp
-#: editor/connections_dialog.cpp editor/export_template_manager.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-#: editor/project_settings_editor.cpp editor/property_editor.cpp
-#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Close"
-msgstr "Sulje"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve hostname:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Connection error, please try again."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Can't connect."
-msgstr "Yhdistä..."
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Can't connect to host:"
-msgstr "Yhdistä Nodeen:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response from host:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Request failed, return code:"
-msgstr "Pyydetty tiedostomuoto tuntematon:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Req. Failed."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Request failed, too many redirects"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Redirect Loop."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Bad download hash, assuming file has been tampered with."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Expected:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Got:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Asset Download Error:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-msgid "Success!"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Fetching:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Resolving.."
-msgstr "Tallennetaan..."
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Connecting.."
-msgstr "Yhdistä..."
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Requesting.."
-msgstr "Testaus"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Error making request"
-msgstr "Virhe tallennettaessa resurssia!"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Idle"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Retry"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Download Error"
-msgstr "Lataa"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Download for this asset is already in progress!"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "first"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "prev"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "next"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "last"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "All"
-msgstr "Kaikki"
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
-#: editor/settings_config_dialog.cpp
-msgid "Search:"
-msgstr "Hae:"
-
-#: editor/asset_library_editor_plugin.cpp editor/code_editor.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Search"
-msgstr "Hae"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/project_manager.cpp
-msgid "Import"
-msgstr "Tuo"
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Plugins"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Sort:"
-msgstr "Lajittele:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Reverse"
-msgstr "Käänteinen"
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Category:"
-msgstr "Kategoria:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Site:"
-msgstr "Sivu:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Support.."
-msgstr "Tuki..."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Official"
-msgstr "Virallinen"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-msgid "Community"
-msgstr "Yhteisö"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Testing"
-msgstr "Testaus"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Assets ZIP File"
-msgstr ""
-
-#: editor/call_dialog.cpp
-msgid "Method List For '%s':"
-msgstr ""
-
-#: editor/call_dialog.cpp modules/visual_script/visual_script_editor.cpp
-msgid "Call"
-msgstr "Kutsu"
-
-#: editor/call_dialog.cpp
-msgid "Method List:"
-msgstr "Metodilista:"
-
-#: editor/call_dialog.cpp
-msgid "Arguments:"
-msgstr "Argumentit:"
-
-#: editor/call_dialog.cpp
-msgid "Return:"
-msgstr "Palaa:"
-
#: editor/code_editor.cpp
msgid "Go to Line"
msgstr "Mene riville"
@@ -663,6 +397,14 @@ msgstr "Kokonaisia sanoja"
msgid "Selection Only"
msgstr "Pelkkä valinta"
+#: editor/code_editor.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
+msgid "Search"
+msgstr "Hae"
+
#: editor/code_editor.cpp editor/editor_help.cpp
msgid "Find"
msgstr "Etsi"
@@ -695,11 +437,11 @@ msgstr ""
msgid "Skip"
msgstr "Ohita"
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom In"
msgstr "Lähennä"
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom Out"
msgstr "Loitonna"
@@ -767,6 +509,20 @@ msgstr "Lykätty"
msgid "Oneshot"
msgstr "Ainoa"
+#: editor/connections_dialog.cpp editor/dependency_editor.cpp
+#: editor/export_template_manager.cpp
+#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Close"
+msgstr "Sulje"
+
#: editor/connections_dialog.cpp
msgid "Connect"
msgstr "Yhdistä"
@@ -792,7 +548,7 @@ msgstr "Yhdistä..."
msgid "Disconnect"
msgstr "Katkaise yhteys"
-#: editor/connections_dialog.cpp editor/node_dock.cpp
+#: editor/connections_dialog.cpp editor/editor_help.cpp editor/node_dock.cpp
msgid "Signals"
msgstr "Signaalit"
@@ -810,12 +566,25 @@ msgstr "Suosikit:"
msgid "Recent:"
msgstr "Viimeaikainen / Viimeaikaiset:"
+#: editor/create_dialog.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/quick_open.cpp editor/settings_config_dialog.cpp
+msgid "Search:"
+msgstr "Hae:"
+
#: editor/create_dialog.cpp editor/editor_help.cpp
#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/quick_open.cpp
msgid "Matches:"
msgstr "Osumat:"
+#: editor/create_dialog.cpp editor/editor_help.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/property_selector.cpp
+#: editor/script_editor_debugger.cpp
+msgid "Description:"
+msgstr "Kuvaus:"
+
#: editor/dependency_editor.cpp
msgid "Search Replacement For:"
msgstr "Hae korvattava:"
@@ -875,6 +644,10 @@ msgid "Owners Of:"
msgstr ""
#: editor/dependency_editor.cpp
+msgid "Remove selected files from the project? (no undo)"
+msgstr "Poista valitut tiedostot projektista? (ei voi kumota)"
+
+#: editor/dependency_editor.cpp
msgid ""
"The files being removed are required by other resources in order for them to "
"work.\n"
@@ -882,8 +655,8 @@ msgid ""
msgstr ""
#: editor/dependency_editor.cpp
-msgid "Remove selected files from the project? (no undo)"
-msgstr "Poista valitut tiedostot projektista? (ei voi kumota)"
+msgid "Cannot remove:\n"
+msgstr ""
#: editor/dependency_editor.cpp
msgid "Error loading:"
@@ -952,11 +725,6 @@ msgstr ""
#: editor/editor_about.cpp
#, fuzzy
-msgid "Authors"
-msgstr "Tekijä:"
-
-#: editor/editor_about.cpp
-#, fuzzy
msgid "Project Founders"
msgstr "Projektinhallinta"
@@ -973,6 +741,40 @@ msgid "Developers"
msgstr ""
#: editor/editor_about.cpp
+#, fuzzy
+msgid "Authors"
+msgstr "Tekijä:"
+
+#: editor/editor_about.cpp
+msgid "Platinum Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Gold Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Mini Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Gold Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Silver Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+#, fuzzy
+msgid "Bronze Donors"
+msgstr "Kloonaa alas"
+
+#: editor/editor_about.cpp
+msgid "Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
msgid "License"
msgstr ""
@@ -1016,6 +818,16 @@ msgid "Package Installed Successfully!"
msgstr "Paketti asennettu onnistuneesti!"
#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Success!"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/project_manager.cpp
+msgid "Install"
+msgstr "Asenna"
+
+#: editor/editor_asset_installer.cpp
#, fuzzy
msgid "Package Installer"
msgstr "Paketti asennettu onnistuneesti!"
@@ -1068,11 +880,6 @@ msgid "Audio Bus, Drag and Drop to rearrange."
msgstr ""
#: editor/editor_audio_buses.cpp
-#, fuzzy
-msgid "Bus options"
-msgstr "Debug-asetukset"
-
-#: editor/editor_audio_buses.cpp
msgid "Solo"
msgstr ""
@@ -1084,6 +891,11 @@ msgstr ""
msgid "Bypass"
msgstr ""
+#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Bus options"
+msgstr "Debug-asetukset"
+
#: editor/editor_audio_buses.cpp editor/plugins/tile_map_editor_plugin.cpp
#: editor/scene_tree_dock.cpp
msgid "Duplicate"
@@ -1091,6 +903,11 @@ msgstr "Monista"
#: editor/editor_audio_buses.cpp
#, fuzzy
+msgid "Reset Volume"
+msgstr "Nollaa lähennys"
+
+#: editor/editor_audio_buses.cpp
+#, fuzzy
msgid "Delete Effect"
msgstr "Poista valitut"
@@ -1115,6 +932,11 @@ msgstr "Monista animaatio"
#: editor/editor_audio_buses.cpp
#, fuzzy
+msgid "Reset Bus Volume"
+msgstr "Nollaa lähennys"
+
+#: editor/editor_audio_buses.cpp
+#, fuzzy
msgid "Move Audio Bus"
msgstr "Siirrä lisäyspainiketta"
@@ -1149,7 +971,8 @@ msgstr "Lisää väylä"
msgid "Create a new Bus Layout."
msgstr ""
-#: editor/editor_audio_buses.cpp editor/script_create_dialog.cpp
+#: editor/editor_audio_buses.cpp editor/property_editor.cpp
+#: editor/script_create_dialog.cpp
msgid "Load"
msgstr "Lataa"
@@ -1241,7 +1064,7 @@ msgid "Rearrange Autoloads"
msgstr ""
#: editor/editor_autoload_settings.cpp editor/editor_file_dialog.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp scene/gui/file_dialog.cpp
+#: scene/gui/file_dialog.cpp
msgid "Path:"
msgstr "Polku:"
@@ -1249,9 +1072,7 @@ msgstr "Polku:"
msgid "Node Name:"
msgstr "Noden nimi:"
-#: editor/editor_autoload_settings.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp editor/project_manager.cpp
+#: editor/editor_autoload_settings.cpp editor/project_manager.cpp
msgid "Name"
msgstr "Nimi"
@@ -1284,18 +1105,19 @@ msgid "Choose a Directory"
msgstr "Valitse hakemisto"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Create Folder"
msgstr "Luo kansio"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: editor/editor_plugin_settings.cpp editor/plugins/theme_editor_plugin.cpp
-#: editor/project_export.cpp scene/gui/file_dialog.cpp
+#: editor/editor_plugin_settings.cpp editor/filesystem_dock.cpp
+#: editor/plugins/theme_editor_plugin.cpp editor/project_export.cpp
+#: scene/gui/file_dialog.cpp
msgid "Name:"
msgstr "Nimi:"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Could not create folder."
msgstr "Kansiota ei voitu luoda."
@@ -1315,30 +1137,6 @@ msgstr "Pakataan"
msgid "Template file not found:\n"
msgstr "Mallitiedostoa ei löytynyt:\n"
-#: editor/editor_export.cpp
-msgid "Added:"
-msgstr "Lisätty:"
-
-#: editor/editor_export.cpp
-msgid "Removed:"
-msgstr "Poistettu:"
-
-#: editor/editor_export.cpp
-msgid "Error saving atlas:"
-msgstr "Virhe tallennettaessa atlas-kuvaa:"
-
-#: editor/editor_export.cpp
-msgid "Could not save atlas subtexture:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Exporting for %s"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Setting Up.."
-msgstr ""
-
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "File Exists, Overwrite?"
msgstr "Tiedosto on jo olemassa, korvaa?"
@@ -1425,6 +1223,11 @@ msgstr "Siirrä suosikkia ylös"
msgid "Move Favorite Down"
msgstr "Siirrä suosikkia alas"
+#: editor/editor_file_dialog.cpp
+#, fuzzy
+msgid "Go to parent folder"
+msgstr "Kansiota ei voitu luoda."
+
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Directories & Files:"
msgstr "Hakemistot & tiedostot:"
@@ -1439,10 +1242,6 @@ msgid "File:"
msgstr "Tiedosto:"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
-msgid "Filter:"
-msgstr "Suodatin:"
-
-#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
#, fuzzy
msgid "Must use a valid extension."
msgstr "Käytä sopivaa laajennusta"
@@ -1469,6 +1268,10 @@ msgstr "Luokkaluettelo:"
msgid "Search Classes"
msgstr "Etsi luokkia"
+#: editor/editor_help.cpp editor/plugins/spatial_editor_plugin.cpp
+msgid "Top"
+msgstr "Pinta"
+
#: editor/editor_help.cpp editor/property_editor.cpp
msgid "Class:"
msgstr "Luokka:"
@@ -1486,15 +1289,29 @@ msgstr "Peritty:"
msgid "Brief Description:"
msgstr "Lyhyt kuvaus:"
+#: editor/editor_help.cpp
+#, fuzzy
+msgid "Members"
+msgstr "Jäsenet:"
+
#: editor/editor_help.cpp modules/visual_script/visual_script_editor.cpp
msgid "Members:"
msgstr "Jäsenet:"
#: editor/editor_help.cpp
+#, fuzzy
+msgid "Public Methods"
+msgstr "Julkiset metodit:"
+
+#: editor/editor_help.cpp
msgid "Public Methods:"
msgstr "Julkiset metodit:"
#: editor/editor_help.cpp
+msgid "GUI Theme Items"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "GUI Theme Items:"
msgstr ""
@@ -1504,6 +1321,11 @@ msgstr ""
#: editor/editor_help.cpp
#, fuzzy
+msgid "Enumerations"
+msgstr "Animaatiot"
+
+#: editor/editor_help.cpp
+#, fuzzy
msgid "Enumerations:"
msgstr "Animaatiot"
@@ -1512,19 +1334,51 @@ msgid "enum "
msgstr ""
#: editor/editor_help.cpp
+#, fuzzy
+msgid "Constants"
+msgstr "Vakiot:"
+
+#: editor/editor_help.cpp
msgid "Constants:"
msgstr "Vakiot:"
#: editor/editor_help.cpp
#, fuzzy
+msgid "Description"
+msgstr "Kuvaus:"
+
+#: editor/editor_help.cpp
+#, fuzzy
+msgid "Properties"
+msgstr "Ominaisuudet:"
+
+#: editor/editor_help.cpp
+#, fuzzy
msgid "Property Description:"
msgstr "Ominaisuuden kuvaus:"
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this property. Please help us by "
+"[color=$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+
+#: editor/editor_help.cpp
+#, fuzzy
+msgid "Methods"
+msgstr "Metodilista:"
+
+#: editor/editor_help.cpp
msgid "Method Description:"
msgstr "Metodin kuvaus:"
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this method. Please help us by [color="
+"$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Search Text"
msgstr "Hae tekstiä"
@@ -1534,24 +1388,21 @@ msgid "Output:"
msgstr " Tuloste:"
#: editor/editor_log.cpp editor/plugins/animation_tree_editor_plugin.cpp
-#: editor/plugins/rich_text_editor_plugin.cpp editor/property_editor.cpp
-#: editor/script_editor_debugger.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/property_editor.cpp editor/script_editor_debugger.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Clear"
msgstr "Tyhjennä"
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Error saving resource!"
msgstr "Virhe tallennettaessa resurssia!"
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Save Resource As.."
msgstr "Tallenna resurssi nimellä..."
-#: editor/editor_node.cpp editor/export_template_manager.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "I see.."
msgstr "Ymmärrän..."
@@ -1568,6 +1419,30 @@ msgid "Error while saving."
msgstr "Virhe tallennettaessa."
#: editor/editor_node.cpp
+#, fuzzy
+msgid "Can't open '%s'."
+msgstr "Yhdistä..."
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Error while parsing '%s'."
+msgstr "Virhe tallennettaessa."
+
+#: editor/editor_node.cpp
+msgid "Unexpected end of file '%s'."
+msgstr ""
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Missing '%s' or its dependencies."
+msgstr "Scenellä '%s' on rikkinäisiä riippuvuuksia:"
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Error while loading '%s'."
+msgstr "Virhe tallennettaessa."
+
+#: editor/editor_node.cpp
msgid "Saving Scene"
msgstr "Tallennetaan sceneä"
@@ -1626,6 +1501,33 @@ msgid "Restored default layout to base settings."
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was imported, so it's not editable.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was instanced or inherited.\n"
+"Changes to it will not be kept when saving the current scene."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource was imported, so it's not editable. Change its settings in the "
+"import panel and then re-import."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This scene was imported, so changes to it will not be kept.\n"
+"Instancing it or inheriting will allow making changes to it.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Copy Params"
msgstr "Kopioi parametrit"
@@ -1801,23 +1703,35 @@ msgid "Save changes the following scene(s) before opening Project Manager?"
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"This option is deprecated. Situations where refresh must be forced are now "
+"considered a bug. Please report."
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Pick a Main Scene"
msgstr "Valitse pääscene"
#: editor/editor_node.cpp
-msgid "Unable to enable addon plugin at: '"
+msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr ""
#: editor/editor_node.cpp
-msgid "' parsing of config failed."
+msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/"
+#, fuzzy
+msgid "Unable to load addon script from path: '%s'."
+msgstr "Virhe ladattaessa skripti %s:stä"
+
+#: editor/editor_node.cpp
+msgid ""
+"Unable to load addon script from path: '%s' Base type is not EditorPlugin."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to load addon script from path: '"
+msgid "Unable to load addon script from path: '%s' Script is not in tool mode."
msgstr ""
#: editor/editor_node.cpp
@@ -1829,7 +1743,7 @@ msgstr ""
"Muokataksesi sitä voit luoda uuden perityn Scenen."
#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/scene_tree_dock.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Ugh"
msgstr "Äh"
@@ -1842,14 +1756,15 @@ msgstr ""
"toimintoa avataksesi Scenen ja tallenna se projektin polkuun."
#: editor/editor_node.cpp
-msgid "Error loading scene."
-msgstr "Virhe ladatessa Sceneä."
-
-#: editor/editor_node.cpp
msgid "Scene '%s' has broken dependencies:"
msgstr "Scenellä '%s' on rikkinäisiä riippuvuuksia:"
#: editor/editor_node.cpp
+#, fuzzy
+msgid "Clear Recent Scenes"
+msgstr "Tyhjennä luut"
+
+#: editor/editor_node.cpp
msgid "Save Layout"
msgstr "Tallenna Layout"
@@ -1883,7 +1798,7 @@ msgstr ""
msgid "Toggle distraction-free mode."
msgstr ""
-#: editor/editor_node.cpp editor/io_plugins/editor_scene_import_plugin.cpp
+#: editor/editor_node.cpp
msgid "Scene"
msgstr "Scene"
@@ -2105,6 +2020,10 @@ msgstr ""
msgid "Issue Tracker"
msgstr ""
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+msgid "Community"
+msgstr "Yhteisö"
+
#: editor/editor_node.cpp
msgid "About"
msgstr "Tietoja"
@@ -2114,7 +2033,7 @@ msgstr "Tietoja"
msgid "Play the project."
msgstr "Toista projekti"
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
#, fuzzy
msgid "Play"
msgstr "Toista"
@@ -2131,7 +2050,7 @@ msgstr "Pysäytä Scene"
msgid "Stop the scene."
msgstr "Lopeta Scene."
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Stop"
msgstr "Pysäytä"
@@ -2204,6 +2123,16 @@ msgid "Object properties."
msgstr "Objektin ominaisuudet."
#: editor/editor_node.cpp
+#, fuzzy
+msgid "Changes may be lost!"
+msgstr "Vaihda säteen muodon pituutta"
+
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Import"
+msgstr "Tuo"
+
+#: editor/editor_node.cpp
msgid "FileSystem"
msgstr "Tiedostojärjestelmä"
@@ -2219,14 +2148,6 @@ msgstr "Tuloste"
msgid "Don't Save"
msgstr ""
-#: editor/editor_node.cpp editor/editor_reimport_dialog.cpp
-msgid "Re-Import"
-msgstr "Tuo uudelleen"
-
-#: editor/editor_node.cpp editor/editor_plugin_settings.cpp
-msgid "Update"
-msgstr "Päivitä"
-
#: editor/editor_node.cpp
msgid "Import Templates From ZIP File"
msgstr "Tuo mallit ZIP-tiedostosta"
@@ -2294,11 +2215,28 @@ msgstr "Avaa editorissa"
msgid "Open the previous Editor"
msgstr "Avaa editorissa"
+#: editor/editor_plugin.cpp
+msgid "Creating Mesh Previews"
+msgstr ""
+
+#: editor/editor_plugin.cpp
+msgid "Thumbnail.."
+msgstr "Pienoiskuva..."
+
#: editor/editor_plugin_settings.cpp
msgid "Installed Plugins:"
msgstr "Asennetut lisäosat:"
#: editor/editor_plugin_settings.cpp
+msgid "Update"
+msgstr "Päivitä"
+
+#: editor/editor_plugin_settings.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Version:"
+msgstr "Versio:"
+
+#: editor/editor_plugin_settings.cpp
msgid "Author:"
msgstr "Tekijä:"
@@ -2332,7 +2270,8 @@ msgid "Frame %"
msgstr "Frame %"
#: editor/editor_profiler.cpp
-msgid "Fixed Frame %"
+#, fuzzy
+msgid "Physics Frame %"
msgstr "Kiinteä Frame %"
#: editor/editor_profiler.cpp editor/script_editor_debugger.cpp
@@ -2351,27 +2290,6 @@ msgstr "Itse"
msgid "Frame #:"
msgstr ""
-#: editor/editor_reimport_dialog.cpp
-#, fuzzy
-msgid "Please wait for scan to complete."
-msgstr "Ole hyvä ja odota läpikäynnin valmistumista."
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Current scene must be saved to re-import."
-msgstr "Nykyinen Scene täytyy tallentaa, jotta se voidaan tuoda uudelleen."
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Save & Re-Import"
-msgstr "Tallenna & tuo uudelleen"
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Importing"
-msgstr "Tuodaan uudelleen"
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Import Changed Resources"
-msgstr "Tuo uudelleen vaihtuneet resurssit"
-
#: editor/editor_run_native.cpp
msgid "Select device from the list"
msgstr ""
@@ -2481,10 +2399,6 @@ msgid "Importing:"
msgstr "Tuodaan:"
#: editor/export_template_manager.cpp
-msgid "Loading Export Templates"
-msgstr ""
-
-#: editor/export_template_manager.cpp
msgid "Current Version:"
msgstr "Nykyinen versio:"
@@ -2517,11 +2431,18 @@ msgid "Cannot navigate to '"
msgstr "Ei voida navigoida '"
#: editor/filesystem_dock.cpp
-#, fuzzy
+msgid "View items as a grid of thumbnails"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "View items as a list"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
msgid ""
"\n"
-"Status: Needs Re-Import"
-msgstr "Tallenna & tuo uudelleen"
+"Status: Import of file failed. Please fix file and reimport manually."
+msgstr ""
#: editor/filesystem_dock.cpp
#, fuzzy
@@ -2531,46 +2452,55 @@ msgid ""
msgstr "Lähde:"
#: editor/filesystem_dock.cpp
-msgid "Same source and destination files, doing nothing."
-msgstr "Sama lähde ja kohdetiedosto, ei toimenpiteitä."
+msgid "Cannot move/rename resources root."
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+#, fuzzy
+msgid "Cannot move a folder into itself.\n"
+msgstr "Tiedostoa ei voi tuoda itseensä:"
#: editor/filesystem_dock.cpp
-msgid "Target file exists, can't overwrite. Delete first."
-msgstr ""
+#, fuzzy
+msgid "Error moving:\n"
+msgstr "Virhe tuotaessa:"
#: editor/filesystem_dock.cpp
-msgid "Same source and destination paths, doing nothing."
-msgstr "Sama lähde ja kohdepolku, ei toimenpiteitä."
+#, fuzzy
+msgid "Unable to update dependencies:\n"
+msgstr "Scenellä '%s' on rikkinäisiä riippuvuuksia:"
#: editor/filesystem_dock.cpp
-msgid "Can't move directories to within themselves."
-msgstr "Hakemisto(j)a ei voida siirtää itseensä."
+msgid "No name provided"
+msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Can't rename deps for:\n"
+msgid "Provided name contains invalid characters"
msgstr ""
#: editor/filesystem_dock.cpp
#, fuzzy
-msgid "Error moving file:\n"
-msgstr "Virhe ladattaessa kuvaa:"
+msgid "No name provided."
+msgstr "Nimeä uudelleen tai siirrä..."
#: editor/filesystem_dock.cpp
#, fuzzy
-msgid "Error moving dir:\n"
-msgstr "Virhe tuotaessa:"
+msgid "Name contains invalid characters."
+msgstr "Kelvolliset merkit:"
#: editor/filesystem_dock.cpp
-msgid "Can't operate on '..'"
+msgid "A file or folder with this name already exists."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Pick New Name and Location For:"
-msgstr "Valitse uusi nimi ja sijainti:"
+#, fuzzy
+msgid "Renaming file:"
+msgstr "Nimeä muuttuja uudelleen"
#: editor/filesystem_dock.cpp
-msgid "No files selected!"
-msgstr "Ei valittuja tiedostoja!"
+#, fuzzy
+msgid "Renaming folder:"
+msgstr "Nimeä Node uudelleen"
#: editor/filesystem_dock.cpp
msgid "Expand all"
@@ -2581,40 +2511,38 @@ msgid "Collapse all"
msgstr "Pienennä kaikki"
#: editor/filesystem_dock.cpp
-msgid "Show In File Manager"
-msgstr "Näytä tiedostonhallinnassa"
-
-#: editor/filesystem_dock.cpp
-msgid "Instance"
-msgstr "Instanssi"
+msgid "Copy Path"
+msgstr "Kopioi polku"
#: editor/filesystem_dock.cpp
-msgid "Edit Dependencies.."
-msgstr "Muokkaa riippuvuuksia..."
+#, fuzzy
+msgid "Rename.."
+msgstr "Nimeä uudelleen"
#: editor/filesystem_dock.cpp
-msgid "View Owners.."
-msgstr "Tarkastele omistajia..."
+msgid "Move To.."
+msgstr "Siirrä..."
#: editor/filesystem_dock.cpp
-msgid "Copy Path"
-msgstr "Kopioi polku"
+#, fuzzy
+msgid "New Folder.."
+msgstr "Luo kansio"
#: editor/filesystem_dock.cpp
-msgid "Rename or Move.."
-msgstr "Nimeä uudelleen tai siirrä..."
+msgid "Show In File Manager"
+msgstr "Näytä tiedostonhallinnassa"
#: editor/filesystem_dock.cpp
-msgid "Move To.."
-msgstr "Siirrä..."
+msgid "Instance"
+msgstr "Instanssi"
#: editor/filesystem_dock.cpp
-msgid "Info"
-msgstr "Tietoja"
+msgid "Edit Dependencies.."
+msgstr "Muokkaa riippuvuuksia..."
#: editor/filesystem_dock.cpp
-msgid "Re-Import.."
-msgstr "Tuo uudelleen..."
+msgid "View Owners.."
+msgstr "Tarkastele omistajia..."
#: editor/filesystem_dock.cpp
msgid "Previous Directory"
@@ -2646,6 +2574,11 @@ msgstr ""
msgid "Move"
msgstr "Siirrä"
+#: editor/filesystem_dock.cpp editor/plugins/animation_tree_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Rename"
+msgstr "Nimeä uudelleen"
+
#: editor/groups_editor.cpp
msgid "Add to Group"
msgstr "Lisää ryhmään"
@@ -2660,6 +2593,11 @@ msgid "Import as Single Scene"
msgstr "Tuodaan Scene..."
#: editor/import/resource_importer_scene.cpp
+#, fuzzy
+msgid "Import with Separate Animations"
+msgstr "Tuo animaatiot..."
+
+#: editor/import/resource_importer_scene.cpp
msgid "Import with Separate Materials"
msgstr ""
@@ -2672,6 +2610,18 @@ msgid "Import with Separate Objects+Materials"
msgstr ""
#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Materials+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Materials+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
#, fuzzy
msgid "Import as Multiple Scenes"
msgstr "Tuo 3D Scene"
@@ -2681,38 +2631,31 @@ msgid "Import as Multiple Scenes+Materials"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Import Scene"
msgstr "Tuo Scene"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Importing Scene.."
msgstr "Tuodaan Scene..."
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Running Custom Script.."
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Couldn't load post-import script:"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Invalid/broken script for post-import (check console):"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Error running post-import script:"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Saving.."
msgstr "Tallennetaan..."
@@ -2741,595 +2684,55 @@ msgstr "Esiasetus..."
msgid "Reimport"
msgstr "Tuo uudelleen"
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "No bit masks to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path is empty."
-msgstr "Kohdepolku on tyhjä."
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must be a complete resource path."
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must exist."
-msgstr "Kohdepolku täytyy olla olemassa."
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Save path is empty!"
-msgstr "Tallennuspolku on tyhjä!"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Import BitMasks"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s):"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Target Path:"
-msgstr "Kohdepolku:"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Accept"
-msgstr "Hyväksy"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Bit Mask"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No source font file!"
-msgstr "Ei fontin lähdetiedostoa!"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No target font resource!"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#, fuzzy
-msgid ""
-"Invalid file extension.\n"
-"Please use .font."
-msgstr ""
-"Virheellinen tiedostolaajennus.\n"
-"Käytä .fnt -tiedostoa."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Can't load/process source font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Couldn't save font."
-msgstr "Fonttia ei voitu tallentaa."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font Size:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Dest Resource:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "The quick brown fox jumps over the lazy dog."
-msgstr "Ovela kettu punaturkki laiskan koiran takaa kurkki."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Test:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Options:"
-msgstr "Asetukset:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Font Import"
-msgstr "Fontin tuonti"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"This file is already a Godot font file, please supply a BMFont type file "
-"instead."
-msgstr ""
-"Tämä tiedosto on jo Godotin fonttitiedosto, ole hyvä ja syötä BMFont -"
-"tiedosto."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Failed opening as BMFont file."
-msgstr "BMFont -tiedoston avaus epäonnistui."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error initializing FreeType."
-msgstr "Virhe FreetType:n alustamisessa."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Unknown font format."
-msgstr "Tuntematon fonttimuoto."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error loading font."
-msgstr "Virhe fontin latauksessa."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Invalid font size."
-msgstr "Virheellinen fonttikoko."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Invalid font custom source."
-msgstr "Virheellinen fontin lähde."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/plugins/theme_editor_plugin.cpp
-msgid "Font"
-msgstr "Fontti"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "No meshes to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Single Mesh Import"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Source Mesh(es):"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/plugins/mesh_instance_editor_plugin.cpp
-msgid "Mesh"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Surface %d"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "No samples to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Import Audio Samples"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Source Sample(s):"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Audio Sample"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "New Clip"
-msgstr "Uusi klippi"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Animation Options"
-msgstr "Animaation asetukset"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Flags"
-msgstr "Liput"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Bake FPS:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Optimizer"
-msgstr "Optimoija"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Linear Error"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angular Error"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angle"
-msgstr "Enimmäiskulma"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Clips"
-msgstr "Klippejä"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#, fuzzy
-msgid "Start(s)"
-msgstr "Alkaa"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#, fuzzy
-msgid "End(s)"
-msgstr "Loppu(u)"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-#, fuzzy
-msgid "Loop"
-msgstr "Toisto"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Filters"
-msgstr "Suodattimet"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source path is empty."
-msgstr "Lähdepolku on tyhjä."
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't load post-import script."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Invalid/broken script for post-import."
+#: editor/multi_node_edit.cpp
+msgid "MultiNode Set"
msgstr ""
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Error importing scene."
-msgstr "Virhe tuotaessa Sceneä."
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import 3D Scene"
-msgstr "Tuo 3D Scene"
+#: editor/node_dock.cpp
+msgid "Groups"
+msgstr "Ryhmät"
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source Scene:"
+#: editor/node_dock.cpp
+msgid "Select a Node to edit Signals and Groups."
msgstr ""
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Same as Target Scene"
-msgstr "Sama kuin kohdescene"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create Poly"
+msgstr "Luo polygoni"
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Shared"
-msgstr "Jaettu"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly"
+msgstr "Muokkaa polygonia"
-#: editor/io_plugins/editor_scene_import_plugin.cpp
+#: editor/plugins/abstract_polygon_2d_editor.cpp
#, fuzzy
-msgid "Target Texture Folder:"
-msgstr "Kohdetekstuurin kansio:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Post-Process Script:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Custom Root Node Type:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Auto"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Root Node Name:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "The Following Files are Missing:"
-msgstr "Seuraavat tiedostot puuttuvat:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Anyway"
-msgstr "Tuo joka tapauksessa"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp scene/gui/dialogs.cpp
-msgid "Cancel"
-msgstr "Peru"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import & Open"
-msgstr "Tuo & Avaa"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Edited scene has not been saved, open imported scene anyway?"
-msgstr ""
-"Muokattua Sceneä ei ole tallennettu, avaa tuotu Scene joka tapauksessa?"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Image:"
-msgstr "Tuo kuva:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Can't import a file over itself:"
-msgstr "Tiedostoa ei voi tuoda itseensä:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't localize path: %s (already local)"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "3D Scene Animation"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Uncompressed"
-msgstr "Purettu"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossless (PNG)"
-msgstr "Pakkaa häviötön (PNG)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossy (WebP)"
-msgstr "Pakkaa häviöllinen (WebP)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress (VRAM)"
-msgstr "Pakkaa (VRAM)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Format"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Compression Quality (WebP):"
-msgstr "Tekstuurin pakkauksen latu (WebP):"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Options"
-msgstr "Tekstuurin asetukset"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Please specify some files!"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "At least one file needed for Atlas."
-msgstr "Ainakin yksi tiedosto tarvitaan Atlas-kuvaa varten."
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Error importing:"
-msgstr "Virhe tuotaessa:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Only one file is required for large texture."
-msgstr "Vain yksi tiedosto vaaditaan suurikokoiselle tekstuurille."
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Max Texture Size:"
-msgstr "Tekstuurin enimmäiskoko:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for Atlas (2D)"
-msgstr "Tuo tekstuuri Atlakselle (2D)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cell Size:"
-msgstr "Solun koko:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Large Texture"
-msgstr "Suurikokoinen tekstuuri"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Textures (2D)"
-msgstr "Tuo suurikokoisia tekstuureita (2D)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture"
-msgstr "Lähdetekstuuri"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Base Atlas Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s)"
-msgstr "Lähdetekstuuri(t)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 2D"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 3D"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures"
-msgstr "Tuo tekstuurit"
+msgid "Insert Point"
+msgstr "Poista piste"
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "2D Texture"
-msgstr "2D tekstuuri"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly (Remove Point)"
+msgstr "Muokkaa polygonia (poista piste)"
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "3D Texture"
-msgstr "Kolmiulotteinen tekstuuri"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Remove Poly And Point"
+msgstr "Poista polygoni ja piste"
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Atlas Texture"
-msgstr "Atlastekstuuri"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create a new polygon from scratch."
+msgstr "Luo uusi piste tyhjästä."
-#: editor/io_plugins/editor_texture_import_plugin.cpp
+#: editor/plugins/abstract_polygon_2d_editor.cpp
msgid ""
-"NOTICE: Importing 2D textures is not mandatory. Just copy png/jpg files to "
-"the project."
-msgstr ""
-"HUOMAA: 2D tekstuurin tuonti ei ole pakollista. Voit kopioida png/jpg -"
-"tiedostot projektiin."
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Crop empty space."
-msgstr "Leikkaa pois tyhjä tila."
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture"
-msgstr "Tekstuuri"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Texture"
-msgstr "Tuo suurikokoinen tekstuuri"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Load Source Image"
-msgstr "Lataa lähdekuva"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#, fuzzy
-msgid "Slicing"
-msgstr "Siivutus"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Inserting"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Saving"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save large texture:"
-msgstr "Isoa tekstuuria ei voitu tallentaa:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#, fuzzy
-msgid "Build Atlas For:"
-msgstr "Luo atlas:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Loading Image:"
-msgstr "Ladataan kuvaa:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't load image:"
-msgstr "Kuvaa ei voitu ladata:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Converting Images"
-msgstr "Muunnetaan kuvia"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cropping Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Blitting Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save atlas image:"
-msgstr "Atlas-kuvaa ei voitu tallentaa:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save converted texture:"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid source!"
-msgstr "Virheellinen lähde!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid translation source!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Column"
-msgstr "Kolumni"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/script_create_dialog.cpp
-msgid "Language"
-msgstr "Kieli"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#, fuzzy
-msgid "No items to import!"
-msgstr "Ei tuotavia asioita!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No target path!"
-msgstr "Ei kohdepolkua!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translations"
-msgstr "Tuo käännökset"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Couldn't import!"
-msgstr "Ei voitu tuoda!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translation"
-msgstr "Tuo käännös"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Source CSV:"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Ignore First Row"
-msgstr "Sivuuta ensimmäinen rivi"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Compress"
-msgstr "Tiivistä"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#, fuzzy
-msgid "Add to Project (project.godot)"
-msgstr "Lisää projektiin (godot.cfg)"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Languages:"
-msgstr "Tuo kielet:"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Translation"
-msgstr "Siirtymä"
-
-#: editor/multi_node_edit.cpp
-msgid "MultiNode Set"
-msgstr ""
-
-#: editor/node_dock.cpp
-msgid "Groups"
-msgstr "Ryhmät"
-
-#: editor/node_dock.cpp
-msgid "Select a Node to edit Signals and Groups."
+"Edit existing polygon:\n"
+"LMB: Move Point.\n"
+"Ctrl+LMB: Split Segment.\n"
+"RMB: Erase Point."
msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
@@ -3485,7 +2888,6 @@ msgstr "Animaation nimi:"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
#: editor/script_create_dialog.cpp
msgid "Error!"
@@ -3596,10 +2998,6 @@ msgid "Delete Input"
msgstr "Poista syöte"
#: editor/plugins/animation_tree_editor_plugin.cpp
-msgid "Rename"
-msgstr "Nimeä uudelleen"
-
-#: editor/plugins/animation_tree_editor_plugin.cpp
msgid "Animation tree is valid."
msgstr "Animaatiopuu on kelvollinen."
@@ -3655,64 +3053,192 @@ msgstr ""
msgid "Filters.."
msgstr "Suodattimet..."
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing %d Triangles:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Free"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Contents:"
+msgstr "Vakiot:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "View Files"
+msgstr " Tiedostot"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve hostname:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connection error, please try again."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Can't connect."
+msgstr "Yhdistä..."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Can't connect to host:"
+msgstr "Yhdistä Nodeen:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response from host:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Request failed, return code:"
+msgstr "Pyydetty tiedostomuoto tuntematon:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Req. Failed."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, too many redirects"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Redirect Loop."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Triangle #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Light Baker Setup:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Bad download hash, assuming file has been tampered with."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing Geometry"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Expected:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Fixing Lights"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Got:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Making BVH"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed sha256 hash check"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Light Octree"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Asset Download Error:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Octree Texture"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Fetching:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Transfer to Lightmaps:"
-msgstr "Muunna Lightmapiksi:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Resolving.."
+msgstr "Tallennetaan..."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Connecting.."
+msgstr "Yhdistä..."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Requesting.."
+msgstr "Testaus"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Error making request"
+msgstr "Virhe tallennettaessa resurssia!"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Idle"
+msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Allocating Texture #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Retry"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Baking Triangle #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Download Error"
+msgstr "Lataa"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download for this asset is already in progress!"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Post-Processing Texture #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "first"
msgstr ""
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Bake!"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "prev"
msgstr ""
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Reset the lightmap octree baking process (start over)."
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "next"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "last"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "All"
+msgstr "Kaikki"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Plugins"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Sort:"
+msgstr "Lajittele:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Reverse"
+msgstr "Käänteinen"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Category:"
+msgstr "Kategoria:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Site:"
+msgstr "Sivu:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Support.."
+msgstr "Tuki..."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Official"
+msgstr "Virallinen"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Testing"
+msgstr "Testaus"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Assets ZIP File"
msgstr ""
#: editor/plugins/camera_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
msgid "Preview"
msgstr "Esikatselu"
@@ -3755,12 +3281,18 @@ msgid "Edit CanvasItem"
msgstr "Muokkaa CanvasItemiä"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Change Anchors"
+#, fuzzy
+msgid "Anchors only"
+msgstr "Ankkuri"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#, fuzzy
+msgid "Change Anchors and Margins"
msgstr "Muuta ankkureita"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom (%):"
-msgstr "Lähennä (%):"
+msgid "Change Anchors"
+msgstr "Muuta ankkureita"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Paste Pose"
@@ -3812,60 +3344,75 @@ msgid "Pan Mode"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Lock the selected object in place (can't be moved)."
-msgstr "Lukitse valitut objektit paikalleen (ei voi liikutella)."
+msgid "Toggles snapping"
+msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Unlock the selected object (can be moved)."
-msgstr "Poista valittujen objektien lukitus (voi liikutella)."
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Use Snap"
+msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Makes sure the object's children are not selectable."
-msgstr "Varmistaa ettei objektin lapsia voi valita."
+#, fuzzy
+msgid "Snapping options"
+msgstr "Animaation asetukset"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Restores the object's children's ability to be selected."
+msgid "Snap to grid"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Edit"
-msgstr "Muokkaa"
+msgid "Use Rotation Snap"
+msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Use Snap"
+msgid "Configure Snap..."
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Show Grid"
-msgstr "Näytä ruudukko"
+msgid "Snap Relative"
+msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Rotation Snap"
+msgid "Use Pixel Snap"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap Relative"
+msgid "Smart snapping"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Configure Snap.."
+#, fuzzy
+msgid "Snap to parent"
+msgstr "Laajenna Parentiin"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to node anchor"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Pixel Snap"
+msgid "Snap to node sides"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to other nodes"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Skeleton.."
-msgstr "Luuranko..."
+msgid "Lock the selected object in place (can't be moved)."
+msgstr "Lukitse valitut objektit paikalleen (ei voi liikutella)."
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Unlock the selected object (can be moved)."
+msgstr "Poista valittujen objektien lukitus (voi liikutella)."
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Makes sure the object's children are not selectable."
+msgstr "Varmistaa ettei objektin lapsia voi valita."
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Restores the object's children's ability to be selected."
+msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Make Bones"
@@ -3894,12 +3441,19 @@ msgid "View"
msgstr "Näytä/Tarkastele"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Reset"
-msgstr "Palauta lähennys"
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Show Grid"
+msgstr "Näytä ruudukko"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#, fuzzy
+msgid "Show helpers"
+msgstr "Näytä luut"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Set.."
-msgstr "Aseta Zoomaus..."
+#, fuzzy
+msgid "Show rulers"
+msgstr "Näytä luut"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Center Selection"
@@ -3910,8 +3464,9 @@ msgid "Frame Selection"
msgstr "Framen valinta"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Anchor"
-msgstr "Ankkuri"
+#, fuzzy
+msgid "Layout"
+msgstr "Tallenna Layout"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Insert Keys"
@@ -3934,11 +3489,20 @@ msgid "Clear Pose"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Set a Value"
-msgstr "Aseta arvo"
+msgid "Drag pivot from mouse position"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#, fuzzy
+msgid "Set pivot at mouse position"
+msgstr "Siirrä pistettä"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Multiply grid step by 2"
+msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap (Pixels):"
+msgid "Divide grid step by 2"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3949,23 +3513,28 @@ msgstr "Lisää %s"
msgid "Adding %s..."
msgstr "Lisätään %s..."
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Create Node"
msgstr "Luo Node"
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Error instancing scene from %s"
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "OK :("
msgstr "Asia kunnossa :("
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "No parent to instance a child at."
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "This operation requires a single selected node."
msgstr ""
@@ -3981,45 +3550,6 @@ msgstr ""
"Vedä & pudota + Shift: Lisää Node sisarena\n"
"Vedä & pudota + Alt: Muuta Noden tyyppiä"
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Create Poly"
-msgstr "Luo polygoni"
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly"
-msgstr "Muokkaa polygonia"
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly (Remove Point)"
-msgstr "Muokkaa polygonia (poista piste)"
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Create a new polygon from scratch."
-msgstr "Luo uusi piste tyhjästä."
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-msgid ""
-"Edit existing polygon:\n"
-"LMB: Move Point.\n"
-"Ctrl+LMB: Split Segment.\n"
-"RMB: Erase Point."
-msgstr ""
-
#: editor/plugins/collision_polygon_editor_plugin.cpp
msgid "Create Poly3D"
msgstr "Luo Poly3D"
@@ -4029,14 +3559,6 @@ msgid "Set Handle"
msgstr ""
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Creating Mesh Library"
-msgstr ""
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Thumbnail.."
-msgstr "Pienoiskuva..."
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Remove item %d?"
msgstr ""
@@ -4061,6 +3583,27 @@ msgid "Update from Scene"
msgstr "Päivitä Scenestä"
#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat0"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat1"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+#, fuzzy
+msgid "Ease in"
+msgstr "Framen valinta"
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Ease out"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Smoothstep"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
#, fuzzy
msgid "Modify Curve Point"
msgstr "Muokkaa käyrää"
@@ -4145,22 +3688,18 @@ msgid "Create Occluder Polygon"
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Edit existing polygon:"
msgstr "Muokkaa olemassaolevaa polygonia:"
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "LMB: Move Point."
msgstr "VHP: Siirrä pistettä."
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Ctrl+LMB: Split Segment."
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "RMB: Erase Point."
msgstr "OHP: Pyyhi piste."
@@ -4262,6 +3801,10 @@ msgid "Create Outline"
msgstr "Luo ääriviivat"
#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Mesh"
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Create Trimesh Static Body"
msgstr ""
@@ -4390,13 +3933,75 @@ msgstr "Satunnainen skaalaus:"
msgid "Populate"
msgstr ""
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Create Navigation Polygon"
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake!"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake the navigation mesh.\n"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Clear the navigation mesh."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Setting up Configuration..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Calculating grid size..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating heightfield..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Marking walkable triangles..."
+msgstr "Varastoidaan paikalliset muutokset..."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Constructing compact heightfield..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Eroding walkable area..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Partitioning..."
+msgstr "Varoitus"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating contours..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating polymesh..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Converting to native navigation mesh..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Navigation Mesh Generator Setup:"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Parsing Geometry..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Done!"
msgstr ""
#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Remove Poly And Point"
-msgstr "Poista polygoni ja piste"
+msgid "Create Navigation Polygon"
+msgstr ""
#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Clear Emission Mask"
@@ -4577,16 +4182,19 @@ msgid "Curve Point #"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve Point Position"
-msgstr ""
+msgstr "Siirrä pistettä"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve In Position"
-msgstr ""
+msgstr "Siirrä pistettä"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve Out Position"
-msgstr ""
+msgstr "Siirrä pistettä"
#: editor/plugins/path_editor_plugin.cpp
msgid "Split Path"
@@ -4648,6 +4256,14 @@ msgid "Scale Polygon"
msgstr "Skaalaa polygonia"
#: editor/plugins/polygon_2d_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Edit"
+msgstr "Muokkaa"
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Polygon->UV"
msgstr ""
@@ -4702,63 +4318,10 @@ msgstr "Lataa resurssi"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/shader_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "Liitä"
-#: editor/plugins/rich_text_editor_plugin.cpp
-msgid "Parse BBCode"
-msgstr "Liitä BBCode"
-
-#: editor/plugins/sample_editor_plugin.cpp
-msgid "Length:"
-msgstr "Pituus:"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Open Sample File(s)"
-msgstr "Avaa Sample-tiedosto(t)"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "ERROR: Couldn't load sample!"
-msgstr "VIRHE: Samplea ei voitu ladata!"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Add Sample"
-msgstr "Lisää Sample"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Rename Sample"
-msgstr "Nimeä Sample uudelleen"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Delete Sample"
-msgstr "Poista Sample"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "16 Bits"
-msgstr "16 bittiä"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "8 Bits"
-msgstr "8 bittiä"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Stereo"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Mono"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Format"
-msgstr "Muoto"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Pitch"
-msgstr "Sävelkorkeus"
-
#: editor/plugins/script_editor_plugin.cpp
#, fuzzy
msgid "Clear Recent Files"
@@ -4850,6 +4413,10 @@ msgstr "Sulje dokumentaatio"
msgid "Close All"
msgstr "Sulje kaikki"
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+msgid "Run"
+msgstr "Aja"
+
#: editor/plugins/script_editor_plugin.cpp
#, fuzzy
msgid "Toggle Scripts Panel"
@@ -4880,7 +4447,8 @@ msgstr ""
msgid "Break"
msgstr "Keskeytä"
-#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+#: editor/script_editor_debugger.cpp
msgid "Continue"
msgstr "Jatka"
@@ -4894,18 +4462,6 @@ msgid "Debug with external editor"
msgstr "Avaa editorissa"
#: editor/plugins/script_editor_plugin.cpp
-msgid "Window"
-msgstr "Ikkuna"
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Left"
-msgstr "Siirry vasemmalle"
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Right"
-msgstr "Siirry oikealle"
-
-#: editor/plugins/script_editor_plugin.cpp
msgid "Open Godot online documentation"
msgstr ""
@@ -4992,8 +4548,9 @@ msgid "Cut"
msgstr "Leikkaa"
#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "Kopioi"
@@ -5259,10 +4816,6 @@ msgid "View Plane Transform."
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Scaling to %s%%."
-msgstr ""
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rotating %s degrees."
msgstr "Kierto %s astetta."
@@ -5279,10 +4832,6 @@ msgid "Top View."
msgstr "Pintanäkymä."
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Top"
-msgstr "Pinta"
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rear View."
msgstr "Takanäkymä."
@@ -5528,6 +5077,10 @@ msgid "Transform"
msgstr "Muunna"
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Configure Snap.."
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Local Coords"
msgstr "Paikalliset koordinaatit"
@@ -5673,6 +5226,11 @@ msgid "Speed (FPS):"
msgstr "Nopeus (FPS):"
#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
+msgid "Loop"
+msgstr "Toisto"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Animation Frames"
msgstr "Animaatioframet"
@@ -5685,12 +5243,14 @@ msgid "Insert Empty (After)"
msgstr "Syötä tyhjä (jälkeen)"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Up"
-msgstr "Ylös"
+#, fuzzy
+msgid "Move (Before)"
+msgstr "Poista Node(t)"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Down"
-msgstr "Alas"
+#, fuzzy
+msgid "Move (After)"
+msgstr "Siirry vasemmalle"
#: editor/plugins/style_box_editor_plugin.cpp
msgid "StyleBox Preview:"
@@ -5770,8 +5330,12 @@ msgid "Remove All"
msgstr "Poista"
#: editor/plugins/theme_editor_plugin.cpp
-msgid "Theme"
-msgstr "Teema"
+msgid "Edit theme.."
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Theme editing menu."
+msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
msgid "Add Class Items"
@@ -5858,6 +5422,10 @@ msgid "Style"
msgstr "Tyyli"
#: editor/plugins/theme_editor_plugin.cpp
+msgid "Font"
+msgstr "Fontti"
+
+#: editor/plugins/theme_editor_plugin.cpp
msgid "Color"
msgstr "Väri"
@@ -5909,8 +5477,9 @@ msgid "Mirror Y"
msgstr "Peilaa Y"
#: editor/plugins/tile_map_editor_plugin.cpp
-msgid "Bucket"
-msgstr "Sanko"
+#, fuzzy
+msgid "Paint Tile"
+msgstr "Poimi tile"
#: editor/plugins/tile_map_editor_plugin.cpp
msgid "Pick Tile"
@@ -5973,6 +5542,10 @@ msgid "Delete preset '%s'?"
msgstr ""
#: editor/project_export.cpp
+msgid "Export templates for this platform are missing/corrupted: "
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Presets"
msgstr ""
@@ -6046,34 +5619,60 @@ msgid "Export templates for this platform are missing:"
msgstr ""
#: editor/project_export.cpp
+msgid "Export templates for this platform are missing/corrupted:"
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Export With Debug"
msgstr "Vie debugaten"
#: editor/project_manager.cpp
-msgid "Invalid project path, the path must exist!"
-msgstr "Virheellinen projektin polku, polku täytyy olla olemassa!"
+#, fuzzy
+msgid "The path does not exist."
+msgstr "Tiedostoa ei ole olemassa."
#: editor/project_manager.cpp
-#, fuzzy
-msgid "Invalid project path, project.godot must not exist."
-msgstr "Virheellinen projektin polku, godot.cfg -tiedostoa ei saa olla."
+msgid "Please choose a 'project.godot' file."
+msgstr ""
#: editor/project_manager.cpp
-#, fuzzy
-msgid "Invalid project path, project.godot must exist."
+msgid ""
+"Your project will be created in a non empty folder (you might want to create "
+"a new folder)."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Please choose a folder that does not contain a 'project.godot' file."
msgstr ""
-"Virheellinen projektin polku, godot.cfg -tiedosto täytyy olla olemassa."
#: editor/project_manager.cpp
msgid "Imported Project"
msgstr "Tuotu projekti"
#: editor/project_manager.cpp
+msgid " "
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "It would be a good idea to name your project."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Invalid project path (changed anything?)."
msgstr "Virheellinen projektin polku (muuttuiko mikään?)."
#: editor/project_manager.cpp
#, fuzzy
+msgid "Couldn't get project.godot in project path."
+msgstr "Ei voitu luoda godot.cfg -tiedostoa projektin polkuun."
+
+#: editor/project_manager.cpp
+#, fuzzy
+msgid "Couldn't edit project.godot in project path."
+msgstr "Ei voitu luoda godot.cfg -tiedostoa projektin polkuun."
+
+#: editor/project_manager.cpp
+#, fuzzy
msgid "Couldn't create project.godot in project path."
msgstr "Ei voitu luoda godot.cfg -tiedostoa projektin polkuun."
@@ -6082,38 +5681,49 @@ msgid "The following files failed extraction from package:"
msgstr "Seuraavien tiedostojen purku paketista epäonnistui:"
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Rename Project"
+msgstr "Nimetön projekti"
+
+#: editor/project_manager.cpp
+#, fuzzy
+msgid "Couldn't get project.godot in the project path."
+msgstr "Ei voitu luoda godot.cfg -tiedostoa projektin polkuun."
+
+#: editor/project_manager.cpp
+msgid "New Game Project"
+msgstr "Uusi peliprojekti"
+
+#: editor/project_manager.cpp
msgid "Import Existing Project"
msgstr "Tuo olemassaoleva projekti"
#: editor/project_manager.cpp
-msgid "Project Path (Must Exist):"
-msgstr "Projektin polku (täytyy olla olemassa):"
+msgid "Create New Project"
+msgstr "Luo uusi projekti"
+
+#: editor/project_manager.cpp
+msgid "Install Project:"
+msgstr "Asenna projekti:"
#: editor/project_manager.cpp
msgid "Project Name:"
msgstr "Projektin nimi:"
#: editor/project_manager.cpp
-msgid "Create New Project"
-msgstr "Luo uusi projekti"
+#, fuzzy
+msgid "Create folder"
+msgstr "Luo kansio"
#: editor/project_manager.cpp
msgid "Project Path:"
msgstr "Projektin polku:"
#: editor/project_manager.cpp
-msgid "Install Project:"
-msgstr "Asenna projekti:"
-
-#: editor/project_manager.cpp
msgid "Browse"
msgstr "Selaa"
#: editor/project_manager.cpp
-msgid "New Game Project"
-msgstr "Uusi peliprojekti"
-
-#: editor/project_manager.cpp
msgid "That's a BINGO!"
msgstr ""
@@ -6122,6 +5732,11 @@ msgid "Unnamed Project"
msgstr "Nimetön projekti"
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Can't open project"
+msgstr "Yhdistä..."
+
+#: editor/project_manager.cpp
msgid "Are you sure to open more than one project?"
msgstr "Haluatko varmasti avata useamman kuin yhden projektin?"
@@ -6151,6 +5766,12 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
+"Language changed.\n"
+"The UI will update next time the editor or project manager starts."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid ""
"You are about the scan %s folders for existing Godot projects. Do you "
"confirm?"
msgstr ""
@@ -6160,10 +5781,6 @@ msgid "Project List"
msgstr "Projektiluettelo"
#: editor/project_manager.cpp
-msgid "Run"
-msgstr "Aja"
-
-#: editor/project_manager.cpp
msgid "Scan"
msgstr ""
@@ -6186,6 +5803,11 @@ msgstr "Poistu"
#: editor/project_manager.cpp
#, fuzzy
+msgid "Restart Now"
+msgstr "Käynnistä uudelleen (s):"
+
+#: editor/project_manager.cpp
+#, fuzzy
msgid "Can't run project"
msgstr "Yhdistä..."
@@ -6222,17 +5844,14 @@ msgid "Add Input Action Event"
msgstr ""
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Meta+"
msgstr ""
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Shift+"
msgstr ""
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Alt+"
msgstr ""
@@ -6293,7 +5912,7 @@ msgstr "Muuta"
msgid "Joypad Axis Index:"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Axis"
msgstr "Akseli"
@@ -6314,31 +5933,31 @@ msgstr ""
msgid "Add Event"
msgstr "Lisää tyhjä"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Device"
msgstr "Laite"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Button"
msgstr "Painike"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Left Button."
msgstr "Vasen painike."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Right Button."
msgstr "Oikea painike."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Middle Button."
msgstr "Keskimmäinen painike."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Up."
msgstr "Rulla ylös."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Down."
msgstr "Rulla alas."
@@ -6347,7 +5966,7 @@ msgid "Add Global Property"
msgstr ""
#: editor/project_settings_editor.cpp
-msgid "Select an setting item first!"
+msgid "Select a setting item first!"
msgstr ""
#: editor/project_settings_editor.cpp
@@ -6365,6 +5984,15 @@ msgid "Delete Item"
msgstr "Poista syöte"
#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Can't contain '/' or ':'"
+msgstr "Yhdistä Nodeen:"
+
+#: editor/project_settings_editor.cpp
+msgid "Already existing"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "Error saving settings."
msgstr "Virhe tallennettaessa asetuksia."
@@ -6406,6 +6034,15 @@ msgstr ""
#: editor/project_settings_editor.cpp
#, fuzzy
+msgid "Changed Locale Filter"
+msgstr "Muuta kameran kokoa"
+
+#: editor/project_settings_editor.cpp
+msgid "Changed Locale Filter Mode"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
msgid "Project Settings (project.godot)"
msgstr "Projektin asetukset"
@@ -6466,6 +6103,29 @@ msgid "Locale"
msgstr ""
#: editor/project_settings_editor.cpp
+msgid "Locales Filter"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Show all locales"
+msgstr "Näytä luut"
+
+#: editor/project_settings_editor.cpp
+msgid "Show only selected locales"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Filter mode:"
+msgstr "Suodattimet"
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Locales:"
+msgstr "Skaalaus:"
+
+#: editor/project_settings_editor.cpp
msgid "AutoLoad"
msgstr ""
@@ -6515,10 +6175,20 @@ msgid "New Script"
msgstr ""
#: editor/property_editor.cpp
+#, fuzzy
+msgid "Make Unique"
+msgstr "Tee luut"
+
+#: editor/property_editor.cpp
msgid "Show in File System"
msgstr ""
#: editor/property_editor.cpp
+#, fuzzy
+msgid "Convert To %s"
+msgstr "Muunna..."
+
+#: editor/property_editor.cpp
msgid "Error loading file: Not a resource!"
msgstr ""
@@ -6556,6 +6226,11 @@ msgid "Select Property"
msgstr "Valitse ominaisuus"
#: editor/property_selector.cpp
+#, fuzzy
+msgid "Select Virtual Method"
+msgstr "Valitse metodi"
+
+#: editor/property_selector.cpp
msgid "Select Method"
msgstr "Valitse metodi"
@@ -6583,26 +6258,6 @@ msgstr ""
msgid "Reparent"
msgstr ""
-#: editor/resources_dock.cpp
-msgid "Create New Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Open Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Save Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Resource Tools"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Make Local"
-msgstr ""
-
#: editor/run_settings_dialog.cpp
msgid "Run Mode:"
msgstr ""
@@ -6730,14 +6385,6 @@ msgid "Sub-Resources:"
msgstr "Resurssit"
#: editor/scene_tree_dock.cpp
-msgid "Edit Groups"
-msgstr "Muokkaa ryhmiä"
-
-#: editor/scene_tree_dock.cpp
-msgid "Edit Connections"
-msgstr "Muokkaa yhteyksiä"
-
-#: editor/scene_tree_dock.cpp
msgid "Clear Inheritance"
msgstr ""
@@ -6922,6 +6569,15 @@ msgid "Invalid base path"
msgstr ""
#: editor/script_create_dialog.cpp
+msgid "Directory of the same name exists"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
+#, fuzzy
+msgid "File exists, will be reused"
+msgstr "Tiedosto on jo olemassa, korvaa?"
+
+#: editor/script_create_dialog.cpp
msgid "Invalid extension"
msgstr "Virheellinen laajennus"
@@ -6965,6 +6621,10 @@ msgid "Load existing script file"
msgstr "Lataa olemassaoleva skripti"
#: editor/script_create_dialog.cpp
+msgid "Language"
+msgstr "Kieli"
+
+#: editor/script_create_dialog.cpp
#, fuzzy
msgid "Inherits"
msgstr "Perii:"
@@ -7009,6 +6669,10 @@ msgid "Function:"
msgstr "Funktio:"
#: editor/script_editor_debugger.cpp
+msgid "Pick one or more items from the list to display the graph."
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
msgid "Errors"
msgstr "Virheet"
@@ -7089,6 +6753,10 @@ msgid "Type"
msgstr ""
#: editor/script_editor_debugger.cpp
+msgid "Format"
+msgstr "Muoto"
+
+#: editor/script_editor_debugger.cpp
msgid "Usage"
msgstr ""
@@ -7164,12 +6832,30 @@ msgstr ""
msgid "Change Probe Extents"
msgstr ""
+#: modules/gdnative/gd_native_library_editor.cpp
+#, fuzzy
+msgid "Library"
+msgstr "Vie kirjasto"
+
+#: modules/gdnative/gd_native_library_editor.cpp
+#, fuzzy
+msgid "Status"
+msgstr "Tila:"
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Libraries: "
+msgstr ""
+
+#: modules/gdnative/register_types.cpp
+msgid "GDNative"
+msgstr ""
+
#: modules/gdscript/gd_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Invalid type argument to convert(), use TYPE_* constants."
msgstr ""
-#: modules/gdscript/gd_functions.cpp
+#: modules/gdscript/gd_functions.cpp modules/mono/glue/glue_header.h
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Not enough bytes for decoding bytes, or invalid format."
msgstr ""
@@ -7221,10 +6907,6 @@ msgid "GridMap Duplicate Selection"
msgstr "Monista valinta"
#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "GridMap Paint"
-msgstr ""
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
#, fuzzy
msgid "Snap View"
msgstr "Huippunäkymä"
@@ -7327,13 +7009,8 @@ msgstr "Näyttöruudun asetukset"
msgid "Pick Distance:"
msgstr "Poimi tile"
-#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
-msgid "Tiles"
-msgstr " Tiedostot"
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "Areas"
+#: modules/mono/editor/mono_bottom_panel.cpp
+msgid "Builds"
msgstr ""
#: modules/visual_script/visual_script.cpp
@@ -7531,10 +7208,18 @@ msgid "Return"
msgstr "Palauta"
#: modules/visual_script/visual_script_editor.cpp
+msgid "Call"
+msgstr "Kutsu"
+
+#: modules/visual_script/visual_script_editor.cpp
msgid "Get"
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
+msgid "Script already has function '%s'"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
#, fuzzy
msgid "Change Input Value"
msgstr "Vaihda syötteen nimi"
@@ -7895,6 +7580,12 @@ msgid ""
"order for AnimatedSprite3D to display frames."
msgstr ""
+#: scene/3d/vehicle_body.cpp
+msgid ""
+"VehicleWheel serves to provide a wheel system to a VehicleBody. Please use "
+"it as a child of a VehicleBody."
+msgstr ""
+
#: scene/gui/color_picker.cpp
#, fuzzy
msgid "Raw Mode"
@@ -7905,6 +7596,10 @@ msgid "Add current color as a preset"
msgstr "Lisää nykyinen väri esiasetukseksi"
#: scene/gui/dialogs.cpp
+msgid "Cancel"
+msgstr "Peru"
+
+#: scene/gui/dialogs.cpp
msgid "Alert!"
msgstr "Huomio!"
@@ -7912,10 +7607,6 @@ msgstr "Huomio!"
msgid "Please Confirm..."
msgstr "Ole hyvä ja vahvista..."
-#: scene/gui/input_action.cpp
-msgid "Ctrl+"
-msgstr "Ctrl+"
-
#: scene/gui/popup.cpp
msgid ""
"Popups will hide by default unless you call popup() or any of the popup*() "
@@ -7954,6 +7645,439 @@ msgstr ""
"koon. Muutoin tee siitä RenderTarget ja aseta sen sisäinen tekstuuri "
"johonkin Nodeen näkyväksi."
+#: scene/resources/dynamic_font.cpp
+msgid "Error initializing FreeType."
+msgstr "Virhe FreetType:n alustamisessa."
+
+#: scene/resources/dynamic_font.cpp
+msgid "Unknown font format."
+msgstr "Tuntematon fonttimuoto."
+
+#: scene/resources/dynamic_font.cpp
+msgid "Error loading font."
+msgstr "Virhe fontin latauksessa."
+
+#: scene/resources/dynamic_font.cpp
+msgid "Invalid font size."
+msgstr "Virheellinen fonttikoko."
+
+#~ msgid "Filter:"
+#~ msgstr "Suodatin:"
+
+#~ msgid "Theme"
+#~ msgstr "Teema"
+
+#~ msgid "Arguments:"
+#~ msgstr "Argumentit:"
+
+#~ msgid "Return:"
+#~ msgstr "Palaa:"
+
+#~ msgid "Added:"
+#~ msgstr "Lisätty:"
+
+#~ msgid "Removed:"
+#~ msgstr "Poistettu:"
+
+#~ msgid "Error saving atlas:"
+#~ msgstr "Virhe tallennettaessa atlas-kuvaa:"
+
+#~ msgid "Error loading scene."
+#~ msgstr "Virhe ladatessa Sceneä."
+
+#~ msgid "Re-Import"
+#~ msgstr "Tuo uudelleen"
+
+#, fuzzy
+#~ msgid "Please wait for scan to complete."
+#~ msgstr "Ole hyvä ja odota läpikäynnin valmistumista."
+
+#~ msgid "Current scene must be saved to re-import."
+#~ msgstr "Nykyinen Scene täytyy tallentaa, jotta se voidaan tuoda uudelleen."
+
+#~ msgid "Save & Re-Import"
+#~ msgstr "Tallenna & tuo uudelleen"
+
+#~ msgid "Re-Importing"
+#~ msgstr "Tuodaan uudelleen"
+
+#~ msgid "Re-Import Changed Resources"
+#~ msgstr "Tuo uudelleen vaihtuneet resurssit"
+
+#, fuzzy
+#~ msgid ""
+#~ "\n"
+#~ "Status: Needs Re-Import"
+#~ msgstr "Tallenna & tuo uudelleen"
+
+#~ msgid "Same source and destination files, doing nothing."
+#~ msgstr "Sama lähde ja kohdetiedosto, ei toimenpiteitä."
+
+#~ msgid "Same source and destination paths, doing nothing."
+#~ msgstr "Sama lähde ja kohdepolku, ei toimenpiteitä."
+
+#~ msgid "Can't move directories to within themselves."
+#~ msgstr "Hakemisto(j)a ei voida siirtää itseensä."
+
+#, fuzzy
+#~ msgid "Error moving file:\n"
+#~ msgstr "Virhe ladattaessa kuvaa:"
+
+#~ msgid "Pick New Name and Location For:"
+#~ msgstr "Valitse uusi nimi ja sijainti:"
+
+#~ msgid "No files selected!"
+#~ msgstr "Ei valittuja tiedostoja!"
+
+#~ msgid "Info"
+#~ msgstr "Tietoja"
+
+#~ msgid "Re-Import.."
+#~ msgstr "Tuo uudelleen..."
+
+#~ msgid "Target path is empty."
+#~ msgstr "Kohdepolku on tyhjä."
+
+#~ msgid "Target path must exist."
+#~ msgstr "Kohdepolku täytyy olla olemassa."
+
+#~ msgid "Save path is empty!"
+#~ msgstr "Tallennuspolku on tyhjä!"
+
+#~ msgid "Target Path:"
+#~ msgstr "Kohdepolku:"
+
+#~ msgid "Accept"
+#~ msgstr "Hyväksy"
+
+#~ msgid "No source font file!"
+#~ msgstr "Ei fontin lähdetiedostoa!"
+
+#, fuzzy
+#~ msgid ""
+#~ "Invalid file extension.\n"
+#~ "Please use .font."
+#~ msgstr ""
+#~ "Virheellinen tiedostolaajennus.\n"
+#~ "Käytä .fnt -tiedostoa."
+
+#~ msgid "Couldn't save font."
+#~ msgstr "Fonttia ei voitu tallentaa."
+
+#~ msgid "The quick brown fox jumps over the lazy dog."
+#~ msgstr "Ovela kettu punaturkki laiskan koiran takaa kurkki."
+
+#~ msgid "Options:"
+#~ msgstr "Asetukset:"
+
+#~ msgid "Font Import"
+#~ msgstr "Fontin tuonti"
+
+#~ msgid ""
+#~ "This file is already a Godot font file, please supply a BMFont type file "
+#~ "instead."
+#~ msgstr ""
+#~ "Tämä tiedosto on jo Godotin fonttitiedosto, ole hyvä ja syötä BMFont -"
+#~ "tiedosto."
+
+#~ msgid "Failed opening as BMFont file."
+#~ msgstr "BMFont -tiedoston avaus epäonnistui."
+
+#~ msgid "Invalid font custom source."
+#~ msgstr "Virheellinen fontin lähde."
+
+#~ msgid "New Clip"
+#~ msgstr "Uusi klippi"
+
+#~ msgid "Flags"
+#~ msgstr "Liput"
+
+#~ msgid "Optimizer"
+#~ msgstr "Optimoija"
+
+#~ msgid "Max Angle"
+#~ msgstr "Enimmäiskulma"
+
+#~ msgid "Clips"
+#~ msgstr "Klippejä"
+
+#, fuzzy
+#~ msgid "Start(s)"
+#~ msgstr "Alkaa"
+
+#, fuzzy
+#~ msgid "End(s)"
+#~ msgstr "Loppu(u)"
+
+#~ msgid "Filters"
+#~ msgstr "Suodattimet"
+
+#~ msgid "Source path is empty."
+#~ msgstr "Lähdepolku on tyhjä."
+
+#~ msgid "Error importing scene."
+#~ msgstr "Virhe tuotaessa Sceneä."
+
+#~ msgid "Import 3D Scene"
+#~ msgstr "Tuo 3D Scene"
+
+#~ msgid "Same as Target Scene"
+#~ msgstr "Sama kuin kohdescene"
+
+#~ msgid "Shared"
+#~ msgstr "Jaettu"
+
+#, fuzzy
+#~ msgid "Target Texture Folder:"
+#~ msgstr "Kohdetekstuurin kansio:"
+
+#~ msgid "The Following Files are Missing:"
+#~ msgstr "Seuraavat tiedostot puuttuvat:"
+
+#~ msgid "Import Anyway"
+#~ msgstr "Tuo joka tapauksessa"
+
+#~ msgid "Import & Open"
+#~ msgstr "Tuo & Avaa"
+
+#~ msgid "Edited scene has not been saved, open imported scene anyway?"
+#~ msgstr ""
+#~ "Muokattua Sceneä ei ole tallennettu, avaa tuotu Scene joka tapauksessa?"
+
+#~ msgid "Import Image:"
+#~ msgstr "Tuo kuva:"
+
+#~ msgid "Uncompressed"
+#~ msgstr "Purettu"
+
+#~ msgid "Compress Lossless (PNG)"
+#~ msgstr "Pakkaa häviötön (PNG)"
+
+#~ msgid "Compress Lossy (WebP)"
+#~ msgstr "Pakkaa häviöllinen (WebP)"
+
+#~ msgid "Compress (VRAM)"
+#~ msgstr "Pakkaa (VRAM)"
+
+#~ msgid "Texture Compression Quality (WebP):"
+#~ msgstr "Tekstuurin pakkauksen latu (WebP):"
+
+#~ msgid "Texture Options"
+#~ msgstr "Tekstuurin asetukset"
+
+#~ msgid "At least one file needed for Atlas."
+#~ msgstr "Ainakin yksi tiedosto tarvitaan Atlas-kuvaa varten."
+
+#~ msgid "Error importing:"
+#~ msgstr "Virhe tuotaessa:"
+
+#~ msgid "Only one file is required for large texture."
+#~ msgstr "Vain yksi tiedosto vaaditaan suurikokoiselle tekstuurille."
+
+#~ msgid "Max Texture Size:"
+#~ msgstr "Tekstuurin enimmäiskoko:"
+
+#~ msgid "Import Textures for Atlas (2D)"
+#~ msgstr "Tuo tekstuuri Atlakselle (2D)"
+
+#~ msgid "Cell Size:"
+#~ msgstr "Solun koko:"
+
+#~ msgid "Large Texture"
+#~ msgstr "Suurikokoinen tekstuuri"
+
+#~ msgid "Import Large Textures (2D)"
+#~ msgstr "Tuo suurikokoisia tekstuureita (2D)"
+
+#~ msgid "Source Texture"
+#~ msgstr "Lähdetekstuuri"
+
+#~ msgid "Source Texture(s)"
+#~ msgstr "Lähdetekstuuri(t)"
+
+#~ msgid "Import Textures"
+#~ msgstr "Tuo tekstuurit"
+
+#~ msgid "2D Texture"
+#~ msgstr "2D tekstuuri"
+
+#~ msgid "3D Texture"
+#~ msgstr "Kolmiulotteinen tekstuuri"
+
+#~ msgid "Atlas Texture"
+#~ msgstr "Atlastekstuuri"
+
+#~ msgid ""
+#~ "NOTICE: Importing 2D textures is not mandatory. Just copy png/jpg files "
+#~ "to the project."
+#~ msgstr ""
+#~ "HUOMAA: 2D tekstuurin tuonti ei ole pakollista. Voit kopioida png/jpg -"
+#~ "tiedostot projektiin."
+
+#~ msgid "Crop empty space."
+#~ msgstr "Leikkaa pois tyhjä tila."
+
+#~ msgid "Texture"
+#~ msgstr "Tekstuuri"
+
+#~ msgid "Import Large Texture"
+#~ msgstr "Tuo suurikokoinen tekstuuri"
+
+#~ msgid "Load Source Image"
+#~ msgstr "Lataa lähdekuva"
+
+#, fuzzy
+#~ msgid "Slicing"
+#~ msgstr "Siivutus"
+
+#~ msgid "Couldn't save large texture:"
+#~ msgstr "Isoa tekstuuria ei voitu tallentaa:"
+
+#, fuzzy
+#~ msgid "Build Atlas For:"
+#~ msgstr "Luo atlas:"
+
+#~ msgid "Loading Image:"
+#~ msgstr "Ladataan kuvaa:"
+
+#~ msgid "Couldn't load image:"
+#~ msgstr "Kuvaa ei voitu ladata:"
+
+#~ msgid "Converting Images"
+#~ msgstr "Muunnetaan kuvia"
+
+#~ msgid "Couldn't save atlas image:"
+#~ msgstr "Atlas-kuvaa ei voitu tallentaa:"
+
+#~ msgid "Invalid source!"
+#~ msgstr "Virheellinen lähde!"
+
+#~ msgid "Column"
+#~ msgstr "Kolumni"
+
+#, fuzzy
+#~ msgid "No items to import!"
+#~ msgstr "Ei tuotavia asioita!"
+
+#~ msgid "No target path!"
+#~ msgstr "Ei kohdepolkua!"
+
+#~ msgid "Import Translations"
+#~ msgstr "Tuo käännökset"
+
+#~ msgid "Couldn't import!"
+#~ msgstr "Ei voitu tuoda!"
+
+#~ msgid "Import Translation"
+#~ msgstr "Tuo käännös"
+
+#~ msgid "Ignore First Row"
+#~ msgstr "Sivuuta ensimmäinen rivi"
+
+#~ msgid "Compress"
+#~ msgstr "Tiivistä"
+
+#, fuzzy
+#~ msgid "Add to Project (project.godot)"
+#~ msgstr "Lisää projektiin (godot.cfg)"
+
+#~ msgid "Import Languages:"
+#~ msgstr "Tuo kielet:"
+
+#~ msgid "Translation"
+#~ msgstr "Siirtymä"
+
+#~ msgid "Transfer to Lightmaps:"
+#~ msgstr "Muunna Lightmapiksi:"
+
+#~ msgid "Zoom (%):"
+#~ msgstr "Lähennä (%):"
+
+#~ msgid "Skeleton.."
+#~ msgstr "Luuranko..."
+
+#~ msgid "Zoom Reset"
+#~ msgstr "Palauta lähennys"
+
+#~ msgid "Zoom Set.."
+#~ msgstr "Aseta Zoomaus..."
+
+#~ msgid "Set a Value"
+#~ msgstr "Aseta arvo"
+
+#~ msgid "Parse BBCode"
+#~ msgstr "Liitä BBCode"
+
+#~ msgid "Length:"
+#~ msgstr "Pituus:"
+
+#~ msgid "Open Sample File(s)"
+#~ msgstr "Avaa Sample-tiedosto(t)"
+
+#~ msgid "ERROR: Couldn't load sample!"
+#~ msgstr "VIRHE: Samplea ei voitu ladata!"
+
+#~ msgid "Add Sample"
+#~ msgstr "Lisää Sample"
+
+#~ msgid "Rename Sample"
+#~ msgstr "Nimeä Sample uudelleen"
+
+#~ msgid "Delete Sample"
+#~ msgstr "Poista Sample"
+
+#~ msgid "16 Bits"
+#~ msgstr "16 bittiä"
+
+#~ msgid "8 Bits"
+#~ msgstr "8 bittiä"
+
+#~ msgid "Pitch"
+#~ msgstr "Sävelkorkeus"
+
+#~ msgid "Window"
+#~ msgstr "Ikkuna"
+
+#~ msgid "Move Right"
+#~ msgstr "Siirry oikealle"
+
+#~ msgid "Up"
+#~ msgstr "Ylös"
+
+#~ msgid "Down"
+#~ msgstr "Alas"
+
+#~ msgid "Bucket"
+#~ msgstr "Sanko"
+
+#~ msgid "Invalid project path, the path must exist!"
+#~ msgstr "Virheellinen projektin polku, polku täytyy olla olemassa!"
+
+#, fuzzy
+#~ msgid "Invalid project path, project.godot must not exist."
+#~ msgstr "Virheellinen projektin polku, godot.cfg -tiedostoa ei saa olla."
+
+#, fuzzy
+#~ msgid "Invalid project path, project.godot must exist."
+#~ msgstr ""
+#~ "Virheellinen projektin polku, godot.cfg -tiedosto täytyy olla olemassa."
+
+#~ msgid "Project Path (Must Exist):"
+#~ msgstr "Projektin polku (täytyy olla olemassa):"
+
+#~ msgid "Edit Groups"
+#~ msgstr "Muokkaa ryhmiä"
+
+#~ msgid "Edit Connections"
+#~ msgstr "Muokkaa yhteyksiä"
+
+#, fuzzy
+#~ msgid "Tiles"
+#~ msgstr " Tiedostot"
+
+#~ msgid "Ctrl+"
+#~ msgstr "Ctrl+"
+
#~ msgid "Close scene? (Unsaved changes will be lost)"
#~ msgstr "Sulje scene? (tallentamattomat muutokset menetetään)"
@@ -7964,9 +8088,6 @@ msgstr ""
#~ "Avaa projektinhallinta?\n"
#~ "(tallentamattomat muutokset menetetään)"
-#~ msgid "Expand to Parent"
-#~ msgstr "Laajenna Parentiin"
-
#~ msgid "just pressed"
#~ msgstr "juuri painettu"
diff --git a/editor/translations/fr.po b/editor/translations/fr.po
index 4e3aad6cf6..9e2f80498d 100644
--- a/editor/translations/fr.po
+++ b/editor/translations/fr.po
@@ -1,5 +1,6 @@
# French translation of the Godot Engine editor
-# Copyright (C) 2016-2017 Juan Linietsky, Ariel Manzur and the Godot community
+# Copyright (C) 2007-2017 Juan Linietsky, Ariel Manzur
+# Copyright (C) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)
# This file is distributed under the same license as the Godot source code.
#
# Antoine Carrier <ac.g392@gmail.com>, 2017.
@@ -9,6 +10,7 @@
# finkiki <specialpopol@gmx.fr>, 2016.
# Gilles Roudiere <gilles.roudiere@gmail.com>, 2017.
# Hugo Locurcio <hugo.l@openmailbox.org>, 2016-2017.
+# keltwookie <keltwookie@protonmail.com>, 2017.
# Marc <marc.gilleron@gmail.com>, 2016-2017.
# Nathan Lovato <nathan.lovato.art@gmail.com>, 2017.
# Nicolas Lehuen <nicolas@lehuen.com>, 2016.
@@ -16,6 +18,7 @@
# Onyx Steinheim <thevoxelmanonyx@gmail.com>, 2016.
# rafeu <duchainer@gmail.com>, 2016-2017.
# Rémi Verschelde <rverschelde@gmail.com>, 2016-2017.
+# Robin Arys <robinarys@hotmail.com>, 2017.
# Roger BR <drai_kin@hotmail.com>, 2016.
# Thomas Baijot <thomasbaijot@gmail.com>, 2016.
#
@@ -23,8 +26,8 @@ msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2017-07-03 19:36+0000\n"
-"Last-Translator: Gilles Roudiere <gilles.roudiere@gmail.com>\n"
+"PO-Revision-Date: 2017-10-25 22:46+0000\n"
+"Last-Translator: Robin Arys <robinarys@hotmail.com>\n"
"Language-Team: French <https://hosted.weblate.org/projects/godot-engine/"
"godot/fr/>\n"
"Language: fr\n"
@@ -32,7 +35,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n > 1;\n"
-"X-Generator: Weblate 2.16-dev\n"
+"X-Generator: Weblate 2.17\n"
#: editor/animation_editor.cpp
msgid "Disabled"
@@ -208,10 +211,9 @@ msgid "Create %d NEW tracks and insert keys?"
msgstr "Créer %d NOUVELLES pistes et insérer des clés ?"
#: editor/animation_editor.cpp editor/create_dialog.cpp
-#: editor/editor_audio_buses.cpp
+#: editor/editor_audio_buses.cpp editor/plugins/abstract_polygon_2d_editor.cpp
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
#: editor/plugins/mesh_instance_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp editor/project_manager.cpp
#: editor/script_create_dialog.cpp
msgid "Create"
@@ -375,264 +377,6 @@ msgstr "Modifier type de valeur du tableau"
msgid "Change Array Value"
msgstr "Modifier valeur du tableau"
-#: editor/asset_library_editor_plugin.cpp
-msgid "Free"
-msgstr "Libérer"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_plugin_settings.cpp
-msgid "Version:"
-msgstr "Version :"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Contents:"
-msgstr "Contenu:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "View Files"
-msgstr "Voir Fichiers"
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_help.cpp editor/property_selector.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Description:"
-msgstr "Description :"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-#: editor/project_manager.cpp
-msgid "Install"
-msgstr "Installer"
-
-#: editor/asset_library_editor_plugin.cpp editor/call_dialog.cpp
-#: editor/connections_dialog.cpp editor/export_template_manager.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-#: editor/project_settings_editor.cpp editor/property_editor.cpp
-#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Close"
-msgstr "Fermer"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve hostname:"
-msgstr "Impossible de résoudre le nom de l'hôte:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve."
-msgstr "Impossible à résoudre."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Connection error, please try again."
-msgstr "Erreur de connection, veuillez essayer à nouveau."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't connect."
-msgstr "Connection impossible."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't connect to host:"
-msgstr "Connection à l'hôte impossible:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response from host:"
-msgstr "Pas de réponse de l'hôte:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response."
-msgstr "Pas de réponse."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Request failed, return code:"
-msgstr "La requête a échoué, code retourné:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Req. Failed."
-msgstr "Req. a Échoué."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Request failed, too many redirects"
-msgstr "La requête a échoué, trop de redirections"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Redirect Loop."
-msgstr "Boucle de Redirection."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed:"
-msgstr "Échec:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Bad download hash, assuming file has been tampered with."
-msgstr "Vérification du téléchargement échouée, le fichier a été altéré."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Expected:"
-msgstr "Attendu:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Got:"
-msgstr "A:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
-msgstr "Vérification de brouillage sha256 échouée"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Asset Download Error:"
-msgstr "Erreur dans le téléchargement d'une ressource:"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-msgid "Success!"
-msgstr "Succès!"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Fetching:"
-msgstr "Récupération:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Resolving.."
-msgstr "Résolution.."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Connecting.."
-msgstr "Connexion en cours.."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Requesting.."
-msgstr "Envoi d'une requête.."
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Error making request"
-msgstr "Erreur d'enregistrement de la ressource !"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Idle"
-msgstr "Inactif"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Retry"
-msgstr "Réessayer"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Download Error"
-msgstr "Télécharger"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Download for this asset is already in progress!"
-msgstr "Le téléchargement de cette ressource est déjà en cours!"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "first"
-msgstr "prem"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "prev"
-msgstr "préc"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "next"
-msgstr "suiv"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "last"
-msgstr "dern"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "All"
-msgstr "Tout"
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
-#: editor/settings_config_dialog.cpp
-msgid "Search:"
-msgstr "Rechercher :"
-
-#: editor/asset_library_editor_plugin.cpp editor/code_editor.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Search"
-msgstr "Rechercher"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/project_manager.cpp
-msgid "Import"
-msgstr "Importer"
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Plugins"
-msgstr "Extensions"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Sort:"
-msgstr "Trier :"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Reverse"
-msgstr "Inverser"
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Category:"
-msgstr "Catégorie :"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Site:"
-msgstr "Site :"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Support.."
-msgstr "Support…"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Official"
-msgstr "Officiel"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-msgid "Community"
-msgstr "Communauté"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Testing"
-msgstr "En test"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Assets ZIP File"
-msgstr "Fichier ZIP de données"
-
-#: editor/call_dialog.cpp
-msgid "Method List For '%s':"
-msgstr "Liste des méthodes pour « %s » :"
-
-#: editor/call_dialog.cpp modules/visual_script/visual_script_editor.cpp
-msgid "Call"
-msgstr "Appel"
-
-#: editor/call_dialog.cpp
-msgid "Method List:"
-msgstr "Liste des méthodes :"
-
-#: editor/call_dialog.cpp
-msgid "Arguments:"
-msgstr "Paramètres :"
-
-#: editor/call_dialog.cpp
-msgid "Return:"
-msgstr "Retourne :"
-
#: editor/code_editor.cpp
msgid "Go to Line"
msgstr "Aller à la ligne"
@@ -669,6 +413,14 @@ msgstr "Mots entiers"
msgid "Selection Only"
msgstr "Sélection uniquement"
+#: editor/code_editor.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
+msgid "Search"
+msgstr "Rechercher"
+
#: editor/code_editor.cpp editor/editor_help.cpp
msgid "Find"
msgstr "Trouver"
@@ -701,11 +453,11 @@ msgstr "Avertir lors du remplacement"
msgid "Skip"
msgstr "Passer"
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom In"
msgstr "Zoomer"
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom Out"
msgstr "Dézoomer"
@@ -774,6 +526,20 @@ msgstr "Différé"
msgid "Oneshot"
msgstr "One-shot"
+#: editor/connections_dialog.cpp editor/dependency_editor.cpp
+#: editor/export_template_manager.cpp
+#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Close"
+msgstr "Fermer"
+
#: editor/connections_dialog.cpp
msgid "Connect"
msgstr "Connecter"
@@ -799,7 +565,7 @@ msgstr "Connecter…"
msgid "Disconnect"
msgstr "Déconnecter"
-#: editor/connections_dialog.cpp editor/node_dock.cpp
+#: editor/connections_dialog.cpp editor/editor_help.cpp editor/node_dock.cpp
msgid "Signals"
msgstr "Signaux"
@@ -816,12 +582,25 @@ msgstr "Favoris :"
msgid "Recent:"
msgstr "Récents :"
+#: editor/create_dialog.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/quick_open.cpp editor/settings_config_dialog.cpp
+msgid "Search:"
+msgstr "Rechercher :"
+
#: editor/create_dialog.cpp editor/editor_help.cpp
#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/quick_open.cpp
msgid "Matches:"
msgstr "Correspondances :"
+#: editor/create_dialog.cpp editor/editor_help.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/property_selector.cpp
+#: editor/script_editor_debugger.cpp
+msgid "Description:"
+msgstr "Description :"
+
#: editor/dependency_editor.cpp
msgid "Search Replacement For:"
msgstr "Rechercher un remplacement pour :"
@@ -881,6 +660,12 @@ msgid "Owners Of:"
msgstr "Propriétaires de :"
#: editor/dependency_editor.cpp
+msgid "Remove selected files from the project? (no undo)"
+msgstr ""
+"Supprimer les fichiers sélectionnés de ce projet ? (pas d'annulation "
+"possible)"
+
+#: editor/dependency_editor.cpp
msgid ""
"The files being removed are required by other resources in order for them to "
"work.\n"
@@ -891,10 +676,9 @@ msgstr ""
"Les supprimer tout de même ? (pas d'annulation possible)"
#: editor/dependency_editor.cpp
-msgid "Remove selected files from the project? (no undo)"
-msgstr ""
-"Supprimer les fichiers sélectionnés de ce projet ? (pas d'annulation "
-"possible)"
+#, fuzzy
+msgid "Cannot remove:\n"
+msgstr "Impossible à résoudre."
#: editor/dependency_editor.cpp
msgid "Error loading:"
@@ -955,26 +739,19 @@ msgstr "La communauté Godot vous dit merci !"
#: editor/editor_about.cpp
msgid "Thanks!"
-msgstr "Merci !"
+msgstr "Merci!"
#: editor/editor_about.cpp
msgid "Godot Engine contributors"
-msgstr "Contributeurs Godot Engine"
-
-#: editor/editor_about.cpp
-#, fuzzy
-msgid "Authors"
-msgstr "Auteur :"
+msgstr "Contributeurs de Godot Engine"
#: editor/editor_about.cpp
-#, fuzzy
msgid "Project Founders"
-msgstr "Gestionnaire de projets"
+msgstr "Fondateurs du projet"
#: editor/editor_about.cpp
-#, fuzzy
msgid "Lead Developer"
-msgstr "Développeurs"
+msgstr "Développeur principal"
#: editor/editor_about.cpp editor/project_manager.cpp
msgid "Project Manager"
@@ -985,118 +762,155 @@ msgid "Developers"
msgstr "Développeurs"
#: editor/editor_about.cpp
-msgid "License"
+msgid "Authors"
+msgstr "Auteurs"
+
+#: editor/editor_about.cpp
+msgid "Platinum Sponsors"
msgstr ""
#: editor/editor_about.cpp
-msgid "Thirdparty License"
+msgid "Gold Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Mini Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Gold Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Silver Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+#, fuzzy
+msgid "Bronze Donors"
+msgstr "Cloner en dessous"
+
+#: editor/editor_about.cpp
+msgid "Donors"
msgstr ""
#: editor/editor_about.cpp
+msgid "License"
+msgstr "Licence"
+
+#: editor/editor_about.cpp
+msgid "Thirdparty License"
+msgstr "Licence tierce partie"
+
+#: editor/editor_about.cpp
msgid ""
"Godot Engine relies on a number of thirdparty free and open source "
"libraries, all compatible with the terms of its MIT license. The following "
"is an exhaustive list of all such thirdparty components with their "
"respective copyright statements and license terms."
msgstr ""
+"Le moteur Godot s'appuie sur un certain nombre de bibliothèques gratuites et "
+"open source tierce parties, toutes compatibles avec les termes de sa licence "
+"MIT. Voici une liste exhaustive de tous ces composants tiers avec leurs "
+"énoncés de droits d'auteur respectifs ainsi que les termes de leurs licences."
#: editor/editor_about.cpp
-#, fuzzy
msgid "All Components"
-msgstr "Contenu:"
+msgstr "Tous les composants"
#: editor/editor_about.cpp
-#, fuzzy
msgid "Components"
-msgstr "Contenu:"
+msgstr "Composants"
#: editor/editor_about.cpp
msgid "Licenses"
-msgstr ""
+msgstr "Licences"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Error opening package file, not in zip format."
-msgstr ""
+msgstr "Erreur d'ouverture de paquetage, pas au format zip."
#: editor/editor_asset_installer.cpp
-#, fuzzy
msgid "Uncompressing Assets"
-msgstr "Non compressé"
+msgstr "Ressource non compressé"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package Installed Successfully!"
msgstr "Paquetage installé avec succès !"
#: editor/editor_asset_installer.cpp
-#, fuzzy
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Success!"
+msgstr "Succès!"
+
+#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/project_manager.cpp
+msgid "Install"
+msgstr "Installer"
+
+#: editor/editor_asset_installer.cpp
msgid "Package Installer"
-msgstr "Paquetage installé avec succès !"
+msgstr "Installeur de paquetage"
#: editor/editor_audio_buses.cpp
msgid "Speakers"
-msgstr ""
+msgstr "Haut- parleurs"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Add Effect"
-msgstr "Ajouter vide"
+msgstr "Ajouter effet"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Rename Audio Bus"
-msgstr "Ouvrir la Mise en Page des Bus Audio"
+msgstr "Renommer bus audio"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Toggle Audio Bus Solo"
-msgstr "Ouvrir la Mise en Page des Bus Audio"
+msgstr "Basculer vers transport audio solo"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Toggle Audio Bus Mute"
-msgstr "Ouvrir la Mise en Page des Bus Audio"
+msgstr "Basculer vers désactivation de transport audio"
#: editor/editor_audio_buses.cpp
msgid "Toggle Audio Bus Bypass Effects"
-msgstr ""
+msgstr "Basculer vers effets de contournement de transport audio"
#: editor/editor_audio_buses.cpp
msgid "Select Audio Bus Send"
-msgstr ""
+msgstr "Sélectionner l'envoi de tranport audio"
#: editor/editor_audio_buses.cpp
msgid "Add Audio Bus Effect"
-msgstr ""
+msgstr "Ajouter effet de tranport audio"
#: editor/editor_audio_buses.cpp
msgid "Move Bus Effect"
-msgstr ""
+msgstr "Déplacer effet de transport"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Delete Bus Effect"
-msgstr "Supprimer la selection"
+msgstr "Supprimer l'effet de transport"
#: editor/editor_audio_buses.cpp
msgid "Audio Bus, Drag and Drop to rearrange."
-msgstr ""
-
-#: editor/editor_audio_buses.cpp
-#, fuzzy
-msgid "Bus options"
-msgstr "Options de débogage"
+msgstr "Transport audio, glisser-déposer pour réorganiser."
#: editor/editor_audio_buses.cpp
msgid "Solo"
-msgstr ""
+msgstr "Solo"
#: editor/editor_audio_buses.cpp
msgid "Mute"
-msgstr ""
+msgstr "Assourdir"
#: editor/editor_audio_buses.cpp
msgid "Bypass"
-msgstr ""
+msgstr "Contournement"
+
+#: editor/editor_audio_buses.cpp
+msgid "Bus options"
+msgstr "Options de tranport"
#: editor/editor_audio_buses.cpp editor/plugins/tile_map_editor_plugin.cpp
#: editor/scene_tree_dock.cpp
@@ -1105,75 +919,74 @@ msgstr "Dupliquer"
#: editor/editor_audio_buses.cpp
#, fuzzy
+msgid "Reset Volume"
+msgstr "Réinitialiser le zoom"
+
+#: editor/editor_audio_buses.cpp
msgid "Delete Effect"
-msgstr "Supprimer la selection"
+msgstr "Supprimer l'effet"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Add Audio Bus"
-msgstr "Ajouter un bus"
+msgstr "Ajouter un transport audio"
#: editor/editor_audio_buses.cpp
msgid "Master bus can't be deleted!"
-msgstr ""
+msgstr "Le transport maître ne peut pas être supprimé !"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Delete Audio Bus"
-msgstr "Supprimer la disposition"
+msgstr "Supprimer le transport audio"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Duplicate Audio Bus"
-msgstr "Dupliquer l'animation"
+msgstr "Dupliquer le transport audio"
#: editor/editor_audio_buses.cpp
#, fuzzy
+msgid "Reset Bus Volume"
+msgstr "Réinitialiser le zoom"
+
+#: editor/editor_audio_buses.cpp
msgid "Move Audio Bus"
-msgstr "Déplacer l'action"
+msgstr "Déplacer le transport audio"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Save Audio Bus Layout As.."
-msgstr "Enregistrer la Disposition des Bus Audio Sous.."
+msgstr "Enregistrer l'agencement du transport audio sous.."
#: editor/editor_audio_buses.cpp
msgid "Location for New Layout.."
-msgstr "Emplacement de la Nouvelle Mise en Page.."
+msgstr "Emplacement du nouvel agencement.."
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Open Audio Bus Layout"
-msgstr "Ouvrir la Mise en Page des Bus Audio"
+msgstr "Ouvrir agencement de transport audio"
#: editor/editor_audio_buses.cpp
msgid "There is no 'res://default_bus_layout.tres' file."
-msgstr ""
+msgstr "Il n'existe aucun 'res://default_bus_layout.tres'."
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Invalid file, not an audio bus layout."
-msgstr ""
-"Extension de fichier non valide.\n"
-"Veuillez utiliser .fnt."
+msgstr "Fichier invalide, pas un agencement de transport audio."
#: editor/editor_audio_buses.cpp
msgid "Add Bus"
-msgstr "Ajouter un bus"
+msgstr "Ajouter un transport"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Create a new Bus Layout."
-msgstr "Créer une nouvelle ressource"
+msgstr "Créer une nouvel agencement de tranport."
-#: editor/editor_audio_buses.cpp editor/script_create_dialog.cpp
+#: editor/editor_audio_buses.cpp editor/property_editor.cpp
+#: editor/script_create_dialog.cpp
msgid "Load"
msgstr "Charger"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Load an existing Bus Layout."
-msgstr "Charger une ressource existante depuis la disque et la modifier."
+msgstr "Charger un agencement de tranport existant."
#: editor/editor_audio_buses.cpp
#: editor/plugins/animation_player_editor_plugin.cpp
@@ -1181,18 +994,16 @@ msgid "Save As"
msgstr "Enregistrer sous"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Save this Bus Layout to a file."
-msgstr "Enregistrer la Disposition des Bus Audio Sous.."
+msgstr "Sauvegarder l'agencement de ce transport vers un fichier."
#: editor/editor_audio_buses.cpp editor/import_dock.cpp
-#, fuzzy
msgid "Load Default"
-msgstr "Par défaut"
+msgstr "Charger défaut"
#: editor/editor_audio_buses.cpp
msgid "Load the default Bus Layout."
-msgstr ""
+msgstr "Charger l'agencement de transport par défaut."
#: editor/editor_autoload_settings.cpp
msgid "Invalid name."
@@ -1265,7 +1076,7 @@ msgid "Rearrange Autoloads"
msgstr "Ré-organiser les AutoLoads"
#: editor/editor_autoload_settings.cpp editor/editor_file_dialog.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp scene/gui/file_dialog.cpp
+#: scene/gui/file_dialog.cpp
msgid "Path:"
msgstr "Chemin :"
@@ -1273,9 +1084,7 @@ msgstr "Chemin :"
msgid "Node Name:"
msgstr "Nom de nœud :"
-#: editor/editor_autoload_settings.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp editor/project_manager.cpp
+#: editor/editor_autoload_settings.cpp editor/project_manager.cpp
msgid "Name"
msgstr "Nom"
@@ -1300,27 +1109,27 @@ msgid "Updating scene.."
msgstr "Mise à jour de la scène…"
#: editor/editor_dir_dialog.cpp
-#, fuzzy
msgid "Please select a base directory first"
-msgstr "Veuillez enregistrer la scène d'abord."
+msgstr "Veuillez sélectionner un répertoire de base en premier"
#: editor/editor_dir_dialog.cpp
msgid "Choose a Directory"
msgstr "Choisir un répertoire"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Create Folder"
msgstr "Créer un dossier"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: editor/editor_plugin_settings.cpp editor/plugins/theme_editor_plugin.cpp
-#: editor/project_export.cpp scene/gui/file_dialog.cpp
+#: editor/editor_plugin_settings.cpp editor/filesystem_dock.cpp
+#: editor/plugins/theme_editor_plugin.cpp editor/project_export.cpp
+#: scene/gui/file_dialog.cpp
msgid "Name:"
msgstr "Nom :"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Could not create folder."
msgstr "Impossible de créer le dossier."
@@ -1340,30 +1149,6 @@ msgstr "Empaquetage"
msgid "Template file not found:\n"
msgstr "Fichier modèle introuvable :\n"
-#: editor/editor_export.cpp
-msgid "Added:"
-msgstr "Ajouté :"
-
-#: editor/editor_export.cpp
-msgid "Removed:"
-msgstr "Supprimé :"
-
-#: editor/editor_export.cpp
-msgid "Error saving atlas:"
-msgstr "Erreur de sauvegarde de l'atlas :"
-
-#: editor/editor_export.cpp
-msgid "Could not save atlas subtexture:"
-msgstr "Impossible d'enregistrer la sous-texture atlas :"
-
-#: editor/editor_export.cpp
-msgid "Exporting for %s"
-msgstr "Exportation pour %s"
-
-#: editor/editor_export.cpp
-msgid "Setting Up.."
-msgstr "Configuration…"
-
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "File Exists, Overwrite?"
msgstr "Le fichier existe, l'écraser ?"
@@ -1448,22 +1233,23 @@ msgstr "Déplacer le favori vers le haut"
msgid "Move Favorite Down"
msgstr "Déplacer le favori vers le bas"
+#: editor/editor_file_dialog.cpp
+#, fuzzy
+msgid "Go to parent folder"
+msgstr "Impossible de créer le dossier."
+
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Directories & Files:"
msgstr "Répertoires et fichiers :"
#: editor/editor_file_dialog.cpp
msgid "Preview:"
-msgstr "Aperçu :"
+msgstr "Aperçu:"
#: editor/editor_file_dialog.cpp editor/script_editor_debugger.cpp
#: scene/gui/file_dialog.cpp
msgid "File:"
-msgstr "Fichier :"
-
-#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
-msgid "Filter:"
-msgstr "Filtre :"
+msgstr "Fichier:"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Must use a valid extension."
@@ -1490,6 +1276,10 @@ msgstr "Liste des classes :"
msgid "Search Classes"
msgstr "Chercher dans les classes"
+#: editor/editor_help.cpp editor/plugins/spatial_editor_plugin.cpp
+msgid "Top"
+msgstr "Dessus"
+
#: editor/editor_help.cpp editor/property_editor.cpp
msgid "Class:"
msgstr "Classe :"
@@ -1506,15 +1296,30 @@ msgstr "Héritée par :"
msgid "Brief Description:"
msgstr "Brève description :"
+#: editor/editor_help.cpp
+#, fuzzy
+msgid "Members"
+msgstr "Membres :"
+
#: editor/editor_help.cpp modules/visual_script/visual_script_editor.cpp
msgid "Members:"
msgstr "Membres :"
#: editor/editor_help.cpp
+#, fuzzy
+msgid "Public Methods"
+msgstr "Méthodes publiques :"
+
+#: editor/editor_help.cpp
msgid "Public Methods:"
msgstr "Méthodes publiques :"
#: editor/editor_help.cpp
+#, fuzzy
+msgid "GUI Theme Items"
+msgstr "Items de thème GUI :"
+
+#: editor/editor_help.cpp
msgid "GUI Theme Items:"
msgstr "Items de thème GUI :"
@@ -1524,53 +1329,85 @@ msgstr "Signaux :"
#: editor/editor_help.cpp
#, fuzzy
+msgid "Enumerations"
+msgstr "Recensements :"
+
+#: editor/editor_help.cpp
msgid "Enumerations:"
-msgstr "Animations"
+msgstr "Recensements:"
#: editor/editor_help.cpp
msgid "enum "
-msgstr ""
+msgstr "enum_ "
+
+#: editor/editor_help.cpp
+#, fuzzy
+msgid "Constants"
+msgstr "Constantes :"
#: editor/editor_help.cpp
msgid "Constants:"
msgstr "Constantes :"
#: editor/editor_help.cpp
+#, fuzzy
+msgid "Description"
+msgstr "Description :"
+
+#: editor/editor_help.cpp
+#, fuzzy
+msgid "Properties"
+msgstr "Propriétés :"
+
+#: editor/editor_help.cpp
msgid "Property Description:"
msgstr "Description des propriétés :"
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this property. Please help us by "
+"[color=$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+
+#: editor/editor_help.cpp
+#, fuzzy
+msgid "Methods"
+msgstr "Liste des méthodes :"
+
+#: editor/editor_help.cpp
msgid "Method Description:"
msgstr "Description de la méthode :"
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this method. Please help us by [color="
+"$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Search Text"
msgstr "Chercher du texte"
#: editor/editor_log.cpp
-#, fuzzy
msgid "Output:"
-msgstr " Sortie :"
+msgstr "Sortie:"
#: editor/editor_log.cpp editor/plugins/animation_tree_editor_plugin.cpp
-#: editor/plugins/rich_text_editor_plugin.cpp editor/property_editor.cpp
-#: editor/script_editor_debugger.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/property_editor.cpp editor/script_editor_debugger.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Clear"
msgstr "Effacer"
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Error saving resource!"
msgstr "Erreur d'enregistrement de la ressource !"
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Save Resource As.."
msgstr "Enregistrer la ressource sous…"
-#: editor/editor_node.cpp editor/export_template_manager.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "I see.."
msgstr "Je vois…"
@@ -1587,6 +1424,30 @@ msgid "Error while saving."
msgstr "Erreur lors de l'enregistrement."
#: editor/editor_node.cpp
+#, fuzzy
+msgid "Can't open '%s'."
+msgstr "Impossible d'opérer sur « .. »"
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Error while parsing '%s'."
+msgstr "Erreur lors de l'enregistrement."
+
+#: editor/editor_node.cpp
+msgid "Unexpected end of file '%s'."
+msgstr ""
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Missing '%s' or its dependencies."
+msgstr "La scène « %s » a des dépendences cassées :"
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Error while loading '%s'."
+msgstr "Erreur lors de l'enregistrement."
+
+#: editor/editor_node.cpp
msgid "Saving Scene"
msgstr "Enregistrement de la scène"
@@ -1599,9 +1460,8 @@ msgid "Creating Thumbnail"
msgstr "Création de l'aperçu"
#: editor/editor_node.cpp
-#, fuzzy
msgid "This operation can't be done without a tree root."
-msgstr "Cette opération ne peut être réalisée sans une scène."
+msgstr "Cette opération ne peut être réalisée sans une arborescence racine."
#: editor/editor_node.cpp
msgid ""
@@ -1647,6 +1507,33 @@ msgid "Restored default layout to base settings."
msgstr "Disposition par défaut remise à zéro."
#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was imported, so it's not editable.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was instanced or inherited.\n"
+"Changes to it will not be kept when saving the current scene."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource was imported, so it's not editable. Change its settings in the "
+"import panel and then re-import."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This scene was imported, so changes to it will not be kept.\n"
+"Instancing it or inheriting will allow making changes to it.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Copy Params"
msgstr "Copier paramètres"
@@ -1679,7 +1566,6 @@ msgid "There is no defined scene to run."
msgstr "Il n'y a pas de scène définie pour être lancée."
#: editor/editor_node.cpp
-#, fuzzy
msgid ""
"No main scene has ever been defined, select one?\n"
"You can change it later in \"Project Settings\" under the 'application' "
@@ -1687,7 +1573,7 @@ msgid ""
msgstr ""
"Aucune scène principale n'a jamais été définie, en sélectionner une ?\n"
"Vous pouvez la modifier ultérieurement dans les « Paramètres du projet » "
-"dans la catégorie « application »."
+"sous la catégorie « application »."
#: editor/editor_node.cpp
msgid ""
@@ -1737,22 +1623,20 @@ msgid "Quick Open Script.."
msgstr "Ouvrir un script rapidement…"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Save & Close"
-msgstr "Enregistrer un fichier"
+msgstr "Enregistrer & fermer"
#: editor/editor_node.cpp
msgid "Save changes to '%s' before closing?"
-msgstr ""
+msgstr "Sauvegarder modifications de '%s' avant de quitter ?"
#: editor/editor_node.cpp
msgid "Save Scene As.."
msgstr "Enregistrer la scène sous…"
#: editor/editor_node.cpp
-#, fuzzy
msgid "No"
-msgstr "NÅ“ud"
+msgstr "Non"
#: editor/editor_node.cpp
msgid "Yes"
@@ -1776,9 +1660,8 @@ msgid "Export Tile Set"
msgstr "Exporter un ensemble de tuiles"
#: editor/editor_node.cpp
-#, fuzzy
msgid "This operation can't be done without a selected node."
-msgstr "Cette opération ne peut être réalisée sans une scène."
+msgstr "Cette opération ne peut être réalisée sans noeud sélectionné."
#: editor/editor_node.cpp
msgid "Current scene not saved. Open anyway?"
@@ -1809,42 +1692,61 @@ msgid "Exit the editor?"
msgstr "Quitter l'éditeur ?"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Open Project Manager?"
-msgstr "Gestionnaire de projets"
+msgstr "Ouvrir gestionnaire de projets ?"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Save & Quit"
-msgstr "Enregistrer un fichier"
+msgstr "Sauvegarder & quitter"
#: editor/editor_node.cpp
msgid "Save changes to the following scene(s) before quitting?"
msgstr ""
+"Sauvegarder les modifications sur la (les) scène(s) suivante(s) avant de "
+"quitter ?"
#: editor/editor_node.cpp
msgid "Save changes the following scene(s) before opening Project Manager?"
msgstr ""
+"Enregistrer les modifications sur la (les) scène(s) suivante(s) avant "
+"d'ouvrir le gestionnaire de projet ?"
+
+#: editor/editor_node.cpp
+msgid ""
+"This option is deprecated. Situations where refresh must be forced are now "
+"considered a bug. Please report."
+msgstr ""
#: editor/editor_node.cpp
msgid "Pick a Main Scene"
msgstr "Choisir une scène principale"
#: editor/editor_node.cpp
-msgid "Unable to enable addon plugin at: '"
-msgstr ""
+#, fuzzy
+msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
+msgstr "impossible d'activer le plugin depuis :"
#: editor/editor_node.cpp
-msgid "' parsing of config failed."
+#, fuzzy
+msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
msgstr ""
+"Impossible de trouver le champ de script pour le plugin dans : 'res://addons/"
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/"
-msgstr ""
+#, fuzzy
+msgid "Unable to load addon script from path: '%s'."
+msgstr "Impossible de charger le script d'ajout depuis le chemin :"
#: editor/editor_node.cpp
-msgid "Unable to load addon script from path: '"
-msgstr ""
+#, fuzzy
+msgid ""
+"Unable to load addon script from path: '%s' Base type is not EditorPlugin."
+msgstr "Impossible de charger le script d'ajout depuis le chemin :"
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Unable to load addon script from path: '%s' Script is not in tool mode."
+msgstr "Impossible de charger le script d'ajout depuis le chemin :"
#: editor/editor_node.cpp
msgid ""
@@ -1856,7 +1758,7 @@ msgstr ""
"Pour y apporter des modification, une scène fille peut être créée."
#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/scene_tree_dock.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Ugh"
msgstr "Oups"
@@ -1870,14 +1772,15 @@ msgstr ""
"le répertoire du projet."
#: editor/editor_node.cpp
-msgid "Error loading scene."
-msgstr "Erreur lors du chargement de la scène."
-
-#: editor/editor_node.cpp
msgid "Scene '%s' has broken dependencies:"
msgstr "La scène « %s » a des dépendences cassées :"
#: editor/editor_node.cpp
+#, fuzzy
+msgid "Clear Recent Scenes"
+msgstr "Effacer les fichiers récents"
+
+#: editor/editor_node.cpp
msgid "Save Layout"
msgstr "Enregistrer la disposition"
@@ -1900,18 +1803,17 @@ msgstr "%d fichier(s) supplémentaire(s)"
#: editor/editor_node.cpp
msgid "%d more file(s) or folder(s)"
-msgstr "%s fichier(s) ou dossier(s) supplémentaire(s)"
+msgstr "%d fichier(s) ou dossier(s) supplémentaire(s)"
#: editor/editor_node.cpp
msgid "Distraction Free Mode"
-msgstr "Mode sans distraction"
+msgstr "Mode Sans Distraction"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Toggle distraction-free mode."
-msgstr "Mode sans distraction"
+msgstr "Basculer vers mode sans-distraction."
-#: editor/editor_node.cpp editor/io_plugins/editor_scene_import_plugin.cpp
+#: editor/editor_node.cpp
msgid "Scene"
msgstr "Scène"
@@ -2112,9 +2014,8 @@ msgstr ""
"plus efficace avec le système de fichiers réseau."
#: editor/editor_node.cpp
-#, fuzzy
msgid "Editor"
-msgstr "Modifier"
+msgstr "Editeur"
#: editor/editor_node.cpp editor/settings_config_dialog.cpp
msgid "Editor Settings"
@@ -2141,20 +2042,21 @@ msgid "Classes"
msgstr "Classes"
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Online Docs"
-msgstr "Fermer les documentations"
+msgstr "Documentation en ligne"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Q&A"
msgstr "Questions et Réponses"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Issue Tracker"
msgstr "Traqueur de problèmes"
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+msgid "Community"
+msgstr "Communauté"
+
#: editor/editor_node.cpp
msgid "About"
msgstr "À propos"
@@ -2163,7 +2065,7 @@ msgstr "À propos"
msgid "Play the project."
msgstr "Lancer le projet."
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Play"
msgstr "Jouer"
@@ -2179,7 +2081,7 @@ msgstr "Mettre en pause la scène"
msgid "Stop the scene."
msgstr "Arrêter la scène."
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Stop"
msgstr "Arrêter"
@@ -2252,6 +2154,16 @@ msgid "Object properties."
msgstr "Propriétés de l'objet."
#: editor/editor_node.cpp
+#, fuzzy
+msgid "Changes may be lost!"
+msgstr "Changer le groupe d'images"
+
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Import"
+msgstr "Importer"
+
+#: editor/editor_node.cpp
msgid "FileSystem"
msgstr "Système de fichiers"
@@ -2265,15 +2177,7 @@ msgstr "Sortie"
#: editor/editor_node.cpp
msgid "Don't Save"
-msgstr ""
-
-#: editor/editor_node.cpp editor/editor_reimport_dialog.cpp
-msgid "Re-Import"
-msgstr "Ré-importer"
-
-#: editor/editor_node.cpp editor/editor_plugin_settings.cpp
-msgid "Update"
-msgstr "Mettre à jour"
+msgstr "Ne pas enregistrer"
#: editor/editor_node.cpp
msgid "Import Templates From ZIP File"
@@ -2300,9 +2204,8 @@ msgid "Open & Run a Script"
msgstr "Ouvrir et exécuter un script"
#: editor/editor_node.cpp
-#, fuzzy
msgid "New Inherited"
-msgstr "Nouvelle scène héritée…"
+msgstr "Nouveau hérité"
#: editor/editor_node.cpp
msgid "Load Errors"
@@ -2313,40 +2216,52 @@ msgid "Select"
msgstr "Sélectionner"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Open 2D Editor"
-msgstr "Ouvrir dans l'éditeur"
+msgstr "Ouvrir éditeur 2D"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Open 3D Editor"
-msgstr "Ouvrir dans l'éditeur"
+msgstr "Ouvrir éditeur 3D"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Open Script Editor"
-msgstr "Ouvrir dans l'éditeur"
+msgstr "Ouvrir éditeur de script"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Open Asset Library"
-msgstr "Bibliothèque d'exportation"
+msgstr "Ouvrir bibliothèque de ressource"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Open the next Editor"
-msgstr "Ouvrir dans l'éditeur"
+msgstr "Ouvrir éditeur suivant"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Open the previous Editor"
-msgstr "Ouvrir dans l'éditeur"
+msgstr "Ouvrir éditeur précédant"
+
+#: editor/editor_plugin.cpp
+#, fuzzy
+msgid "Creating Mesh Previews"
+msgstr "Création de la bibliothèque de maillages"
+
+#: editor/editor_plugin.cpp
+msgid "Thumbnail.."
+msgstr "Aperçu…"
#: editor/editor_plugin_settings.cpp
msgid "Installed Plugins:"
msgstr "Extensions installées :"
#: editor/editor_plugin_settings.cpp
+msgid "Update"
+msgstr "Mettre à jour"
+
+#: editor/editor_plugin_settings.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Version:"
+msgstr "Version :"
+
+#: editor/editor_plugin_settings.cpp
msgid "Author:"
msgstr "Auteur :"
@@ -2380,8 +2295,8 @@ msgstr "% d'image"
#: editor/editor_profiler.cpp
#, fuzzy
-msgid "Fixed Frame %"
-msgstr "Cadre prédéfini %"
+msgid "Physics Frame %"
+msgstr "Frame fixe %"
#: editor/editor_profiler.cpp editor/script_editor_debugger.cpp
msgid "Time:"
@@ -2396,39 +2311,20 @@ msgid "Self"
msgstr "Soi"
#: editor/editor_profiler.cpp
-#, fuzzy
msgid "Frame #:"
-msgstr "Image #:"
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Please wait for scan to complete."
-msgstr "Veuillez attendre la fin du scan."
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Current scene must be saved to re-import."
-msgstr "La scène actuelle doit être enregistrée afin de pouvoir ré-importer."
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Save & Re-Import"
-msgstr "Enregistrer et ré-importer"
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Importing"
-msgstr "Ré-importation"
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Import Changed Resources"
-msgstr "Ré-importer les ressources modifiées"
+msgstr "Frame # :"
#: editor/editor_run_native.cpp
msgid "Select device from the list"
-msgstr ""
+msgstr "Sélectionner appareil depuis la liste"
#: editor/editor_run_native.cpp
msgid ""
"No runnable export preset found for this platform.\n"
"Please add a runnable preset in the export menu."
msgstr ""
+"Aucun préréglage d'exportation exécutable trouvé pour cette plate-forme. \n"
+"Ajoutez un préréglage exécutable dans le menu d'exportation."
#: editor/editor_run_script.cpp
msgid "Write your logic in the _run() method."
@@ -2503,71 +2399,56 @@ msgid "Can't open export templates zip."
msgstr "Impossible d'ouvrir le ZIP de modèles d'exportation."
#: editor/export_template_manager.cpp
-#, fuzzy
msgid "Invalid version.txt format inside templates."
-msgstr "Le format de version.txt invalide dans les modèles."
+msgstr "Format de version.txt invalide dans les modèles."
#: editor/export_template_manager.cpp
-#, fuzzy
msgid ""
"Invalid version.txt format inside templates. Revision is not a valid "
"identifier."
msgstr ""
-"Le format de version.txt invalide dans les modèles. Revision n'est pas un "
+"Format de version.txt invalide dans les modèles. Revision n'est pas un "
"identifiant valide."
#: editor/export_template_manager.cpp
-#, fuzzy
msgid "No version.txt found inside templates."
-msgstr "Le fichier version.txt n'a pas été trouvé dans les modèles."
+msgstr "Aucun version.txt n'a été trouvé dans les modèles."
#: editor/export_template_manager.cpp
-#, fuzzy
msgid "Error creating path for templates:\n"
-msgstr "Erreur de sauvegarde de l'atlas :"
+msgstr "Erreur lors de la création du chemin pour les modèles:\n"
#: editor/export_template_manager.cpp
-#, fuzzy
msgid "Extracting Export Templates"
-msgstr "Chargement des modèles d'exportation"
+msgstr "Extraction des modèles d'exportation"
#: editor/export_template_manager.cpp
msgid "Importing:"
msgstr "Importation :"
#: editor/export_template_manager.cpp
-msgid "Loading Export Templates"
-msgstr "Chargement des modèles d'exportation"
-
-#: editor/export_template_manager.cpp
-#, fuzzy
msgid "Current Version:"
-msgstr "Version actuelle :"
+msgstr "Version courante :"
#: editor/export_template_manager.cpp
-#, fuzzy
msgid "Installed Versions:"
-msgstr "Extensions installées :"
+msgstr "Versions installées :"
#: editor/export_template_manager.cpp
-#, fuzzy
msgid "Install From File"
-msgstr "Projets récents :"
+msgstr "Installer depuis fichier :"
#: editor/export_template_manager.cpp
-#, fuzzy
msgid "Remove Template"
-msgstr "Supprimer l'item"
+msgstr "Supprimer le modèle"
#: editor/export_template_manager.cpp
-#, fuzzy
msgid "Select template file"
-msgstr "Supprimer les fichiers sélectionnés ?"
+msgstr "Sélectionner le fichier de modèle"
#: editor/export_template_manager.cpp
-#, fuzzy
msgid "Export Template Manager"
-msgstr "Chargement des modèles d'exportation"
+msgstr "Gestionnaire d'export de modèles"
#: editor/file_type_cache.cpp
msgid "Can't open file_type_cache.cch for writing, not saving file type cache!"
@@ -2580,105 +2461,121 @@ msgid "Cannot navigate to '"
msgstr "Ne peux pas acceder à '"
#: editor/filesystem_dock.cpp
-#, fuzzy
+msgid "View items as a grid of thumbnails"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "View items as a list"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
msgid ""
"\n"
-"Status: Needs Re-Import"
-msgstr "Enregistrer et ré-importer"
+"Status: Import of file failed. Please fix file and reimport manually."
+msgstr ""
#: editor/filesystem_dock.cpp
-#, fuzzy
msgid ""
"\n"
"Source: "
-msgstr "Source :"
+msgstr ""
+"\n"
+"Source : "
#: editor/filesystem_dock.cpp
-msgid "Same source and destination files, doing nothing."
-msgstr "Fichiers source et destination identiques, rien à faire."
+#, fuzzy
+msgid "Cannot move/rename resources root."
+msgstr "Impossible de charger ou traiter la police source."
#: editor/filesystem_dock.cpp
-msgid "Target file exists, can't overwrite. Delete first."
-msgstr ""
+#, fuzzy
+msgid "Cannot move a folder into itself.\n"
+msgstr "Impossible d'importer un fichier par-dessus lui-même :"
#: editor/filesystem_dock.cpp
-msgid "Same source and destination paths, doing nothing."
-msgstr "Chemins source et destination identiques, rien à faire."
+#, fuzzy
+msgid "Error moving:\n"
+msgstr "Erreur lors du déplacement du répertoire :\n"
#: editor/filesystem_dock.cpp
-msgid "Can't move directories to within themselves."
-msgstr "Impossible de déplacer des répertoires vers eux-mêmes."
+#, fuzzy
+msgid "Unable to update dependencies:\n"
+msgstr "La scène « %s » a des dépendences cassées :"
#: editor/filesystem_dock.cpp
-msgid "Can't rename deps for:\n"
+msgid "No name provided"
msgstr ""
#: editor/filesystem_dock.cpp
-#, fuzzy
-msgid "Error moving file:\n"
-msgstr "Erreur de chargement d'image :"
+msgid "Provided name contains invalid characters"
+msgstr ""
#: editor/filesystem_dock.cpp
#, fuzzy
-msgid "Error moving dir:\n"
-msgstr "Erreur d'importation :"
+msgid "No name provided."
+msgstr "Renommer ou déplacer…"
#: editor/filesystem_dock.cpp
-msgid "Can't operate on '..'"
-msgstr "Impossible d'opérer sur « .. »"
+#, fuzzy
+msgid "Name contains invalid characters."
+msgstr "Caractères valides :"
#: editor/filesystem_dock.cpp
-msgid "Pick New Name and Location For:"
-msgstr "Entrez un nouveau nom et chemin pour :"
+#, fuzzy
+msgid "A file or folder with this name already exists."
+msgstr "Le nom du groupe existe déjà !"
#: editor/filesystem_dock.cpp
-msgid "No files selected!"
-msgstr "Pas de fichiers sélectionnés !"
+#, fuzzy
+msgid "Renaming file:"
+msgstr "Renommer la variable"
#: editor/filesystem_dock.cpp
#, fuzzy
+msgid "Renaming folder:"
+msgstr "Renommer le nœud"
+
+#: editor/filesystem_dock.cpp
msgid "Expand all"
-msgstr "Étendre au parent"
+msgstr "Développer tout"
#: editor/filesystem_dock.cpp
msgid "Collapse all"
msgstr "Réduire tout"
#: editor/filesystem_dock.cpp
-msgid "Show In File Manager"
-msgstr "Montrer dans le gestionnaire de fichiers"
-
-#: editor/filesystem_dock.cpp
-msgid "Instance"
-msgstr "Instance"
+msgid "Copy Path"
+msgstr "Copier le chemin"
#: editor/filesystem_dock.cpp
-msgid "Edit Dependencies.."
-msgstr "Modifier les dépendances…"
+#, fuzzy
+msgid "Rename.."
+msgstr "Renommer"
#: editor/filesystem_dock.cpp
-msgid "View Owners.."
-msgstr "Voir les propriétaires…"
+msgid "Move To.."
+msgstr "Déplacer vers…"
#: editor/filesystem_dock.cpp
-msgid "Copy Path"
-msgstr "Copier le chemin"
+#, fuzzy
+msgid "New Folder.."
+msgstr "Créer un dossier"
#: editor/filesystem_dock.cpp
-msgid "Rename or Move.."
-msgstr "Renommer ou déplacer…"
+msgid "Show In File Manager"
+msgstr "Montrer dans le gestionnaire de fichiers"
#: editor/filesystem_dock.cpp
-msgid "Move To.."
-msgstr "Déplacer vers…"
+msgid "Instance"
+msgstr "Instance"
#: editor/filesystem_dock.cpp
-msgid "Info"
-msgstr "Information"
+msgid "Edit Dependencies.."
+msgstr "Modifier les dépendances…"
#: editor/filesystem_dock.cpp
-msgid "Re-Import.."
-msgstr "Ré-importer…"
+msgid "View Owners.."
+msgstr "Voir les propriétaires…"
#: editor/filesystem_dock.cpp
msgid "Previous Directory"
@@ -2707,11 +2604,18 @@ msgid ""
"Scanning Files,\n"
"Please Wait.."
msgstr ""
+"Analyse des fichiers en cours,\n"
+"Veuillez patienter..."
#: editor/filesystem_dock.cpp
msgid "Move"
msgstr "Déplacer"
+#: editor/filesystem_dock.cpp editor/plugins/animation_tree_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Rename"
+msgstr "Renommer"
+
#: editor/groups_editor.cpp
msgid "Add to Group"
msgstr "Ajouter au groupe"
@@ -2721,682 +2625,157 @@ msgid "Remove from Group"
msgstr "Supprimer du groupe"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Import as Single Scene"
-msgstr "Importation de la scène…"
+msgstr "Importer comme scène unique"
+
+#: editor/import/resource_importer_scene.cpp
+#, fuzzy
+msgid "Import with Separate Animations"
+msgstr "Importer avec matériaux séparés"
#: editor/import/resource_importer_scene.cpp
msgid "Import with Separate Materials"
-msgstr ""
+msgstr "Importer avec matériaux séparés"
#: editor/import/resource_importer_scene.cpp
msgid "Import with Separate Objects"
-msgstr ""
+msgstr "Importer avec des objets séparés"
#: editor/import/resource_importer_scene.cpp
msgid "Import with Separate Objects+Materials"
-msgstr ""
+msgstr "Importer avec objets+matériaux séparés"
+
+#: editor/import/resource_importer_scene.cpp
+#, fuzzy
+msgid "Import with Separate Objects+Animations"
+msgstr "Importer avec objets+matériaux séparés"
#: editor/import/resource_importer_scene.cpp
#, fuzzy
+msgid "Import with Separate Materials+Animations"
+msgstr "Importer avec matériaux séparés"
+
+#: editor/import/resource_importer_scene.cpp
+#, fuzzy
+msgid "Import with Separate Objects+Materials+Animations"
+msgstr "Importer avec objets+matériaux séparés"
+
+#: editor/import/resource_importer_scene.cpp
msgid "Import as Multiple Scenes"
-msgstr "Importer une scène 3D"
+msgstr "Importer comme scènes multiples"
#: editor/import/resource_importer_scene.cpp
msgid "Import as Multiple Scenes+Materials"
-msgstr ""
+msgstr "Importer comme scènes+matériaux multiples"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Import Scene"
msgstr "Importer une scène"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Importing Scene.."
msgstr "Importation de la scène…"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Running Custom Script.."
msgstr "Lancement du script personnalisé…"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Couldn't load post-import script:"
msgstr "Impossible de charger le script de post-importation :"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Invalid/broken script for post-import (check console):"
msgstr ""
"Script de post-importation invalide ou corrompu (vérifiez la console) :"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Error running post-import script:"
msgstr "Erreur d'exécution du script de post-importation :"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Saving.."
msgstr "Enregistrement…"
#: editor/import_dock.cpp
msgid "Set as Default for '%s'"
-msgstr ""
+msgstr "Définir comme défaut pour '%s'"
#: editor/import_dock.cpp
msgid "Clear Default for '%s'"
-msgstr ""
+msgstr "Effacer défaut pour '%s'"
#: editor/import_dock.cpp
-#, fuzzy
msgid " Files"
-msgstr "Fichier"
+msgstr " Fichiers"
#: editor/import_dock.cpp
-#, fuzzy
msgid "Import As:"
-msgstr "Importer"
+msgstr "Importer comme :"
#: editor/import_dock.cpp editor/property_editor.cpp
msgid "Preset.."
msgstr "Pré-réglage…"
#: editor/import_dock.cpp
-#, fuzzy
msgid "Reimport"
msgstr "Ré-importer"
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "No bit masks to import!"
-msgstr "Pas de masques de bits à importer !"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path is empty."
-msgstr "Le chemin de destination est vide."
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must be a complete resource path."
-msgstr ""
-"Le chemin de destination doit être un chemin complet vers une ressource."
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must exist."
-msgstr "Le chemin de destination doit exister."
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Save path is empty!"
-msgstr "Le chemin de sauvegarde est vide !"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Import BitMasks"
-msgstr "Importer des BitMasks"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s):"
-msgstr "Texture(s) source :"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Target Path:"
-msgstr "Chemin de destination :"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Accept"
-msgstr "Accepter"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#, fuzzy
-msgid "Bit Mask"
-msgstr "Masque de bits"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No source font file!"
-msgstr "Pas de fichier de police source !"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No target font resource!"
-msgstr "Pas de ressource de police de destination !"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#, fuzzy
-msgid ""
-"Invalid file extension.\n"
-"Please use .font."
-msgstr ""
-"Extension de fichier non valide.\n"
-"Veuillez utiliser .fnt."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Can't load/process source font."
-msgstr "Impossible de charger ou traiter la police source."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Couldn't save font."
-msgstr "Impossible d'enregistrer la police."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font:"
-msgstr "Police source :"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font Size:"
-msgstr "Taille de la police source :"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Dest Resource:"
-msgstr "Ressource de destination :"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "The quick brown fox jumps over the lazy dog."
-msgstr "Voix ambiguë d'un cœur qui, au zéphyr, préfère les jattes de kiwis."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Test:"
-msgstr "Test :"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Options:"
-msgstr "Options :"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Font Import"
-msgstr "Importation d'une police"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"This file is already a Godot font file, please supply a BMFont type file "
-"instead."
-msgstr ""
-"Ce fichier est déjà un fichier de police Godot, veuillez fournir un fichier "
-"de type BMFont à la place."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Failed opening as BMFont file."
-msgstr "Impossible d'ouvrir le fichier en tant que fichier BMFont."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error initializing FreeType."
-msgstr "Erreur à l'initialisation de Freetype."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Unknown font format."
-msgstr "Format de police inconnu."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error loading font."
-msgstr "Erreur lors du chargement de la police."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Invalid font size."
-msgstr "Taille de police invalide."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Invalid font custom source."
-msgstr "Source personnalisée de police invalide."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/plugins/theme_editor_plugin.cpp
-msgid "Font"
-msgstr "Police"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "No meshes to import!"
-msgstr "Pas de maillages à importer !"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Single Mesh Import"
-msgstr "Importer un maillage"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Source Mesh(es):"
-msgstr "Maillage(s) source :"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/plugins/mesh_instance_editor_plugin.cpp
-msgid "Mesh"
-msgstr "Maillage"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Surface %d"
-msgstr "Surface %d"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "No samples to import!"
-msgstr "Pas d'échantillons à importer !"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Import Audio Samples"
-msgstr "Importer des échantillons audio"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Source Sample(s):"
-msgstr "Échantillon(s) source :"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Audio Sample"
-msgstr "Échantillon audio"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "New Clip"
-msgstr "Nouvelle séquence"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Animation Options"
-msgstr "Options d'animation"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Flags"
-msgstr "Drapeaux"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Bake FPS:"
-msgstr "FPS de calcul :"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Optimizer"
-msgstr "Optimiseur"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Linear Error"
-msgstr "Erreur linéaire maximale"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angular Error"
-msgstr "Erreur angulaire maximale"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angle"
-msgstr "Angle maximal"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Clips"
-msgstr "Séquences"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Start(s)"
-msgstr "Départ(s)"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "End(s)"
-msgstr "Fin(s)"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Loop"
-msgstr "Boucle"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Filters"
-msgstr "Filtres"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source path is empty."
-msgstr "Le chemin source est vide."
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't load post-import script."
-msgstr "Impossible de charger le script de post-importation."
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Invalid/broken script for post-import."
-msgstr "Script invalide ou cassé de post-importation."
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Error importing scene."
-msgstr "Erreur à l'importation de la scène."
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import 3D Scene"
-msgstr "Importer une scène 3D"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source Scene:"
-msgstr "Scène source :"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Same as Target Scene"
-msgstr "Identique à la scène de destination"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Shared"
-msgstr "Partagé"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Target Texture Folder:"
-msgstr "Dossier de destination des textures :"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Post-Process Script:"
-msgstr "Script de post-traitement :"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Custom Root Node Type:"
-msgstr "Type de nœud racine personnalisé :"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Auto"
-msgstr "Auto."
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Root Node Name:"
-msgstr "Nom de nœud racine :"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "The Following Files are Missing:"
-msgstr "Les fichiers suivants sont manquants :"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Anyway"
-msgstr "Importer quand même"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp scene/gui/dialogs.cpp
-msgid "Cancel"
-msgstr "Annuler"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import & Open"
-msgstr "Importer et ouvrir"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Edited scene has not been saved, open imported scene anyway?"
-msgstr ""
-"La scène modifiée actuellement n'a pas été enregistrée, ouvrir la scène "
-"importée quand même ?"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Image:"
-msgstr "Importer une image :"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Can't import a file over itself:"
-msgstr "Impossible d'importer un fichier par-dessus lui-même :"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't localize path: %s (already local)"
-msgstr "Impossible de rendre le chemin local : %s (déjà local)"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "3D Scene Animation"
-msgstr "Animation de scène 3D"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Uncompressed"
-msgstr "Non compressé"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossless (PNG)"
-msgstr "Compression sans perte (PNG)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossy (WebP)"
-msgstr "Compression avec perte (WebP)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress (VRAM)"
-msgstr "Compression GPU (VRAM)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Format"
-msgstr "Format de texture"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Compression Quality (WebP):"
-msgstr "Qualité de compression de la texture (WebP) :"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Options"
-msgstr "Options de texture"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Please specify some files!"
-msgstr "Veuillez spécifier des fichiers !"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "At least one file needed for Atlas."
-msgstr "Il faut au moins un fichier pour créer un atlas."
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Error importing:"
-msgstr "Erreur d'importation :"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Only one file is required for large texture."
-msgstr "Un seul fichier est nécessaire pour créer une grande texture."
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Max Texture Size:"
-msgstr "Taille de texture maximale :"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for Atlas (2D)"
-msgstr "Importer des textures pour un atlas (2D)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cell Size:"
-msgstr "Taille des cellules :"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Large Texture"
-msgstr "Grande texture"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Textures (2D)"
-msgstr "Importer des grandes textures (2D)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture"
-msgstr "Texture source"
+#: editor/multi_node_edit.cpp
+msgid "MultiNode Set"
+msgstr "Ensemble multi-nœud"
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Base Atlas Texture"
-msgstr "Texture d'atlas de base"
+#: editor/node_dock.cpp
+msgid "Groups"
+msgstr "Groupes"
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s)"
-msgstr "Texture(s) source"
+#: editor/node_dock.cpp
+msgid "Select a Node to edit Signals and Groups."
+msgstr "Sélectionnez un nœud pour editer des signaux et des groupes."
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 2D"
-msgstr "Importer des textures pour la 2D"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create Poly"
+msgstr "Créer un polygone"
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 3D"
-msgstr "Importer des textures pour la 3D"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly"
+msgstr "Modifier le polygone"
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures"
-msgstr "Importer des textures"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#, fuzzy
+msgid "Insert Point"
+msgstr "Insertion"
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "2D Texture"
-msgstr "Texture 2D"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly (Remove Point)"
+msgstr "Modifier le polygone (supprimer un point)"
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "3D Texture"
-msgstr "Texture 3D"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Remove Poly And Point"
+msgstr "Retirer Polygone et Point"
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Atlas Texture"
-msgstr "Texture atlas"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create a new polygon from scratch."
+msgstr "Créer un nouveau polygone à partir de rien."
-#: editor/io_plugins/editor_texture_import_plugin.cpp
+#: editor/plugins/abstract_polygon_2d_editor.cpp
msgid ""
-"NOTICE: Importing 2D textures is not mandatory. Just copy png/jpg files to "
-"the project."
+"Edit existing polygon:\n"
+"LMB: Move Point.\n"
+"Ctrl+LMB: Split Segment.\n"
+"RMB: Erase Point."
msgstr ""
-"REMARQUE : L'import de textures 2D n'est pas obligatoire. Copiez directement "
-"les fichiers PNG ou JPEG dans le projet."
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Crop empty space."
-msgstr "Rogner l'espace vide."
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture"
-msgstr "Texture"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Texture"
-msgstr "Importer une grande texture"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Load Source Image"
-msgstr "Charger une image source"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Slicing"
-msgstr "Découpage"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Inserting"
-msgstr "Insertion"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Saving"
-msgstr "Enregistrement"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save large texture:"
-msgstr "Impossible d'enregistrer la grande texture :"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Build Atlas For:"
-msgstr "Construire l'atlas pour :"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Loading Image:"
-msgstr "Chargement de l'image :"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't load image:"
-msgstr "Impossible de charger l'image :"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Converting Images"
-msgstr "Conversion des images"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cropping Images"
-msgstr "Rognage des images"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Blitting Images"
-msgstr "Découpage des images"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save atlas image:"
-msgstr "Impossible d'enregistrer l'image d'atlas :"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save converted texture:"
-msgstr "Impossible d'enregistrer la texture convertie :"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid source!"
-msgstr "Source invalide !"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid translation source!"
-msgstr "Source de traduction invalide !"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Column"
-msgstr "Colonne"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/script_create_dialog.cpp
-msgid "Language"
-msgstr "Langage"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No items to import!"
-msgstr "Pas d'objets à importer !"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No target path!"
-msgstr "Pas de chemin de destination !"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translations"
-msgstr "Importer des traductions"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Couldn't import!"
-msgstr "Impossible d'importer !"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translation"
-msgstr "Importer une traduction"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Source CSV:"
-msgstr "CSV source :"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Ignore First Row"
-msgstr "Ignorer la première ligne"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Compress"
-msgstr "Compresser"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#, fuzzy
-msgid "Add to Project (project.godot)"
-msgstr "Ajouter au projet (engine.cfg)"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Languages:"
-msgstr "Importer les langues :"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Translation"
-msgstr "Traduction"
-
-#: editor/multi_node_edit.cpp
-msgid "MultiNode Set"
-msgstr "Ensemble multi-nœud"
-
-#: editor/node_dock.cpp
-msgid "Groups"
-msgstr "Groupes"
-
-#: editor/node_dock.cpp
-#, fuzzy
-msgid "Select a Node to edit Signals and Groups."
-msgstr "Sélectionnez un nœud pour modifier des signaux et des groupes."
+"Editer polygones existants :\n"
+"Bouton gauche : Déplacer point\n"
+"Ctrl+Bouton gauche : Diviser section.\n"
+"Bouton droit: Effeacer point."
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Toggle Autoplay"
@@ -3415,9 +2794,8 @@ msgid "Change Animation Name:"
msgstr "Modifier le nom de l'animation :"
#: editor/plugins/animation_player_editor_plugin.cpp
-#, fuzzy
msgid "Delete Animation?"
-msgstr "Dupliquer l'animation"
+msgstr "Supprimer l'animation ?"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
@@ -3443,12 +2821,10 @@ msgid "Add Animation"
msgstr "Ajouter une animation"
#: editor/plugins/animation_player_editor_plugin.cpp
-#, fuzzy
msgid "Blend Next Changed"
-msgstr "Mélange Suivant Changé"
+msgstr "Mélange suivant modifié"
#: editor/plugins/animation_player_editor_plugin.cpp
-#, fuzzy
msgid "Change Blend Time"
msgstr "Changer le temps de mélange"
@@ -3486,16 +2862,14 @@ msgstr ""
"Jouer l'animation sélectionnée à rebours depuis la position actuelle. (A)"
#: editor/plugins/animation_player_editor_plugin.cpp
-#, fuzzy
msgid "Play selected animation backwards from end. (Shift+A)"
-msgstr "Lire l'animation sélectionnée à rebours de la fin. (Maj + A)"
+msgstr "Lire l'animation sélectionnée à rebours depuis la fin. (Maj + A)"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Stop animation playback. (S)"
msgstr "Arrêter la lecture de l'animation. (S)"
#: editor/plugins/animation_player_editor_plugin.cpp
-#, fuzzy
msgid "Play selected animation from start. (Shift+D)"
msgstr "Lire l'animation sélectionnée depuis le début. (Maj + D)"
@@ -3536,7 +2910,6 @@ msgid "Autoplay on Load"
msgstr "Lecture automatique au chargement"
#: editor/plugins/animation_player_editor_plugin.cpp
-#, fuzzy
msgid "Edit Target Blend Times"
msgstr "Modifier les temps de mélange des cibles"
@@ -3558,16 +2931,14 @@ msgstr "Nom de l'animation :"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
#: editor/script_create_dialog.cpp
msgid "Error!"
msgstr "Erreur !"
#: editor/plugins/animation_player_editor_plugin.cpp
-#, fuzzy
msgid "Blend Times:"
-msgstr "Temps de mélange"
+msgstr "Temps de mélange :"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Next (Auto Queue):"
@@ -3587,9 +2958,8 @@ msgid "New name:"
msgstr "Nouveau nom :"
#: editor/plugins/animation_tree_editor_plugin.cpp
-#, fuzzy
msgid "Edit Filters"
-msgstr "Modifier les filtres de nœud"
+msgstr "Editer les filtres"
#: editor/plugins/animation_tree_editor_plugin.cpp
#: editor/plugins/multimesh_editor_plugin.cpp
@@ -3670,10 +3040,6 @@ msgid "Delete Input"
msgstr "Supprimer l'entrée"
#: editor/plugins/animation_tree_editor_plugin.cpp
-msgid "Rename"
-msgstr "Renommer"
-
-#: editor/plugins/animation_tree_editor_plugin.cpp
msgid "Animation tree is valid."
msgstr "L'arbre d'animations est valide."
@@ -3729,64 +3095,181 @@ msgstr "Modifier les filtres de nœud"
msgid "Filters.."
msgstr "Filtres…"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing %d Triangles:"
-msgstr "Analyse de %d triangles :"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Free"
+msgstr "Libérer"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Triangle #"
-msgstr "Triangle #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Contents:"
+msgstr "Contenu:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Light Baker Setup:"
-msgstr "Paramètres du calculateur d'éclairage :"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "View Files"
+msgstr "Voir Fichiers"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing Geometry"
-msgstr "Analyse de la géométrie"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve hostname:"
+msgstr "Impossible de résoudre le nom de l'hôte:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Fixing Lights"
-msgstr "Correction des lumières"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve."
+msgstr "Impossible à résoudre."
-#: editor/plugins/baked_light_baker.cpp
-msgid "Making BVH"
-msgstr "Création du BVH"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connection error, please try again."
+msgstr "Erreur de connection, veuillez essayer à nouveau."
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Light Octree"
-msgstr "Création de l'octree de lumière"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't connect."
+msgstr "Connection impossible."
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Octree Texture"
-msgstr "Création de la texture d'octree"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't connect to host:"
+msgstr "Connection à l'hôte impossible:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Transfer to Lightmaps:"
-msgstr "Transfert vers des lightmaps :"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response from host:"
+msgstr "Pas de réponse de l'hôte:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Allocating Texture #"
-msgstr "Allocation de la texture #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response."
+msgstr "Pas de réponse."
-#: editor/plugins/baked_light_baker.cpp
-msgid "Baking Triangle #"
-msgstr "Calcul de la texture #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, return code:"
+msgstr "La requête a échoué, code retourné:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Post-Processing Texture #"
-msgstr "Post-traitement de la texture #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Req. Failed."
+msgstr "Req. a Échoué."
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Bake!"
-msgstr "Calculer !"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, too many redirects"
+msgstr "La requête a échoué, trop de redirections"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Redirect Loop."
+msgstr "Boucle de Redirection."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed:"
+msgstr "Échec:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Bad download hash, assuming file has been tampered with."
+msgstr "Vérification du téléchargement échouée, le fichier a été altéré."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Expected:"
+msgstr "Attendu:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Got:"
+msgstr "A:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed sha256 hash check"
+msgstr "Vérification de brouillage sha256 échouée"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Asset Download Error:"
+msgstr "Erreur dans le téléchargement d'une ressource:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Fetching:"
+msgstr "Récupération:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Resolving.."
+msgstr "Résolution.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connecting.."
+msgstr "Connexion en cours.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Requesting.."
+msgstr "Envoi d'une requête.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Error making request"
+msgstr "Erreur lors de la requête"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Idle"
+msgstr "Inactif"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Retry"
+msgstr "Réessayer"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download Error"
+msgstr "Erreur de téléchargement"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download for this asset is already in progress!"
+msgstr "Le téléchargement de cette ressource est déjà en cours!"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "first"
+msgstr "premier"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "prev"
+msgstr "préc"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "next"
+msgstr "suiv"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "last"
+msgstr "dern"
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Reset the lightmap octree baking process (start over)."
-msgstr "Remettre le processus de calcul de l'éclairage à zéro (recommencer)."
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "All"
+msgstr "Tout"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Plugins"
+msgstr "Extensions"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Sort:"
+msgstr "Trier :"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Reverse"
+msgstr "Inverser"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Category:"
+msgstr "Catégorie :"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Site:"
+msgstr "Site :"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Support.."
+msgstr "Support…"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Official"
+msgstr "Officiel"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Testing"
+msgstr "En test"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Assets ZIP File"
+msgstr "Fichier ZIP de données"
#: editor/plugins/camera_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
msgid "Preview"
msgstr "Aperçu"
@@ -3829,12 +3312,18 @@ msgid "Edit CanvasItem"
msgstr "Modifier le CanvasItem"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Change Anchors"
+#, fuzzy
+msgid "Anchors only"
+msgstr "Ancre"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#, fuzzy
+msgid "Change Anchors and Margins"
msgstr "Modifier les ancres"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom (%):"
-msgstr "Zoom (%) :"
+msgid "Change Anchors"
+msgstr "Modifier les ancres"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Paste Pose"
@@ -3867,9 +3356,8 @@ msgid "Move Mode"
msgstr "Mode déplacement"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Rotate Mode"
-msgstr "Mode rotation (E)"
+msgstr "Mode rotation"
#: editor/plugins/canvas_item_editor_plugin.cpp
#: editor/plugins/spatial_editor_plugin.cpp
@@ -3889,60 +3377,78 @@ msgid "Pan Mode"
msgstr "Mode navigation"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Lock the selected object in place (can't be moved)."
-msgstr "Verrouiller l'objet sélectionné (il ne pourra plus être déplacé)."
+#, fuzzy
+msgid "Toggles snapping"
+msgstr "Placer un point d'arrêt"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Unlock the selected object (can be moved)."
-msgstr "Déverouiller l'objet sélectionné (il pourra être déplacé de nouveau)."
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Use Snap"
+msgstr "Aligner sur la grille"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Makes sure the object's children are not selectable."
-msgstr "Rendre la sélection des enfants de l'objet impossible."
+#, fuzzy
+msgid "Snapping options"
+msgstr "Options d'animation"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Restores the object's children's ability to be selected."
-msgstr "Rendre la sélection des enfants de l'objet de nouveau possible."
+#, fuzzy
+msgid "Snap to grid"
+msgstr "Mode d'aimantation :"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Edit"
-msgstr "Modifier"
+msgid "Use Rotation Snap"
+msgstr "Rotation alignée"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Use Snap"
-msgstr "Aligner sur la grille"
+#, fuzzy
+msgid "Configure Snap..."
+msgstr "Configurer la grille…"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Show Grid"
-msgstr "Afficher la grille"
+msgid "Snap Relative"
+msgstr "Alignement relatif"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Rotation Snap"
-msgstr "Rotation alignée"
+msgid "Use Pixel Snap"
+msgstr "Aligner au pixel près"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap Relative"
-msgstr "Alignement relatif"
+msgid "Smart snapping"
+msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Configure Snap.."
-msgstr "Configurer la grille…"
+#, fuzzy
+msgid "Snap to parent"
+msgstr "Étendre au parent"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Pixel Snap"
-msgstr "Aligner au pixel près"
+msgid "Snap to node anchor"
+msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Skeleton.."
-msgstr "Squelette…"
+msgid "Snap to node sides"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to other nodes"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Lock the selected object in place (can't be moved)."
+msgstr "Verrouiller l'objet sélectionné (il ne pourra plus être déplacé)."
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Unlock the selected object (can be moved)."
+msgstr "Déverouiller l'objet sélectionné (il pourra être déplacé de nouveau)."
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Makes sure the object's children are not selectable."
+msgstr "Rendre la sélection des enfants de l'objet impossible."
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Restores the object's children's ability to be selected."
+msgstr "Rendre la sélection des enfants de l'objet de nouveau possible."
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Make Bones"
@@ -3970,12 +3476,19 @@ msgid "View"
msgstr "Affichage"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Reset"
-msgstr "Réinitialiser le zoom"
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Show Grid"
+msgstr "Afficher la grille"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Set.."
-msgstr "Définir le zoom…"
+#, fuzzy
+msgid "Show helpers"
+msgstr "Afficher les os"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#, fuzzy
+msgid "Show rulers"
+msgstr "Afficher les os"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Center Selection"
@@ -3986,8 +3499,9 @@ msgid "Frame Selection"
msgstr "Cadrer la sélection"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Anchor"
-msgstr "Ancre"
+#, fuzzy
+msgid "Layout"
+msgstr "Enregistrer la disposition"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Insert Keys"
@@ -4010,48 +3524,60 @@ msgid "Clear Pose"
msgstr "Vider la pose"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Set a Value"
-msgstr "Définir une valeur"
+msgid "Drag pivot from mouse position"
+msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap (Pixels):"
-msgstr "Aligner (pixels) :"
+#, fuzzy
+msgid "Set pivot at mouse position"
+msgstr "Définir courbe hors position"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Multiply grid step by 2"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Divide grid step by 2"
+msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Add %s"
-msgstr "Tout ajouter"
+msgstr "Ajouter %s"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Adding %s..."
msgstr "Ajout de %s..."
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Create Node"
msgstr "Créer un nœud"
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Error instancing scene from %s"
msgstr "Erreur d'instanciation de la scène depuis %s"
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "OK :("
msgstr "OK :("
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "No parent to instance a child at."
msgstr "Pas de parent dans lequel instancier l'enfant."
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "This operation requires a single selected node."
msgstr ""
"Cette opération ne peut être réalisée uniquement avec un seul nœud "
"sélectionné."
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Change default type"
-msgstr "Changer la valeur par défaut"
+msgstr "Changer le type par défaut"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid ""
@@ -4061,45 +3587,6 @@ msgstr ""
"Glisser-déposer + Maj : Ajouter un nœud frère\n"
"Glisser-déposer + Alt : Modifier le type de nœud"
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Create Poly"
-msgstr "Créer un polygone"
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly"
-msgstr "Modifier le polygone"
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly (Remove Point)"
-msgstr "Modifier le polygone (supprimer un point)"
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Create a new polygon from scratch."
-msgstr "Créer un nouveau polygone à partir de rien."
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-msgid ""
-"Edit existing polygon:\n"
-"LMB: Move Point.\n"
-"Ctrl+LMB: Split Segment.\n"
-"RMB: Erase Point."
-msgstr ""
-
#: editor/plugins/collision_polygon_editor_plugin.cpp
msgid "Create Poly3D"
msgstr "Créer un Poly3D"
@@ -4109,14 +3596,6 @@ msgid "Set Handle"
msgstr "Définir la poignée"
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Creating Mesh Library"
-msgstr "Création de la bibliothèque de maillages"
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Thumbnail.."
-msgstr "Aperçu…"
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Remove item %d?"
msgstr "Supprimer l'objet %d ?"
@@ -4139,57 +3618,70 @@ msgid "Update from Scene"
msgstr "Mettre à jour depuis la scène"
#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat0"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat1"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
#, fuzzy
-msgid "Modify Curve Point"
-msgstr "Modifier la carte de courbes"
+msgid "Ease in"
+msgstr "Ease in"
#: editor/plugins/curve_editor_plugin.cpp
#, fuzzy
+msgid "Ease out"
+msgstr "Ease out"
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Smoothstep"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Modify Curve Point"
+msgstr "Modifier le point de courbe"
+
+#: editor/plugins/curve_editor_plugin.cpp
msgid "Modify Curve Tangent"
-msgstr "Modifier la carte de courbes"
+msgstr "Modifier la tangente de courbes"
#: editor/plugins/curve_editor_plugin.cpp
-#, fuzzy
msgid "Load Curve Preset"
-msgstr "Charger une ressource"
+msgstr "Charger un pré-réglage de courbe"
#: editor/plugins/curve_editor_plugin.cpp
-#, fuzzy
msgid "Add point"
-msgstr "Ajouter une entrée"
+msgstr "Ajouter un point"
#: editor/plugins/curve_editor_plugin.cpp
-#, fuzzy
msgid "Remove point"
-msgstr "Supprimer le chemin du point"
+msgstr "Supprimer point"
#: editor/plugins/curve_editor_plugin.cpp
-#, fuzzy
msgid "Left linear"
-msgstr "Linéaire"
+msgstr "Linéaire gauche"
#: editor/plugins/curve_editor_plugin.cpp
-#, fuzzy
msgid "Right linear"
-msgstr "Vue de droite"
+msgstr "Linéaire droite"
#: editor/plugins/curve_editor_plugin.cpp
-#, fuzzy
msgid "Load preset"
-msgstr "Charger une ressource"
+msgstr "Charger prérèglage"
#: editor/plugins/curve_editor_plugin.cpp
-#, fuzzy
msgid "Remove Curve Point"
-msgstr "Supprimer le chemin du point"
+msgstr "Supprimer point de courbe"
#: editor/plugins/curve_editor_plugin.cpp
msgid "Toggle Curve Linear Tangent"
-msgstr ""
+msgstr "Basculer vers tangente linéaire de courbe"
#: editor/plugins/curve_editor_plugin.cpp
msgid "Hold Shift to edit tangents individually"
-msgstr ""
+msgstr "Maintenez l'appui sur Maj pour éditer les tangentes individuellement"
#: editor/plugins/gradient_editor_plugin.cpp
msgid "Add/Remove Color Ramp Point"
@@ -4217,45 +3709,39 @@ msgid ""
"No OccluderPolygon2D resource on this node.\n"
"Create and assign one?"
msgstr ""
+"Aucune ressource OccluderPolygon2D sur ce nœud. En créer et en attribuer un ?"
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
msgid "Create Occluder Polygon"
msgstr "Créer un polygone occulteur"
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Edit existing polygon:"
msgstr "Modifier un polygone existant :"
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "LMB: Move Point."
msgstr "Bouton gauche : déplacer un point."
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Ctrl+LMB: Split Segment."
msgstr "Contrôle + Bouton gauche : séparer le segment."
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "RMB: Erase Point."
msgstr "Bouton droit : effacer un point."
#: editor/plugins/line_2d_editor_plugin.cpp
-#, fuzzy
msgid "Remove Point from Line2D"
-msgstr "Supprimer le point d'une courbe"
+msgstr "Supprimer point de Line2D"
#: editor/plugins/line_2d_editor_plugin.cpp
-#, fuzzy
msgid "Add Point to Line2D"
-msgstr "Ajouter un point à la courbe"
+msgstr "Ajouter point à Line2D"
#: editor/plugins/line_2d_editor_plugin.cpp
-#, fuzzy
msgid "Move Point in Line2D"
-msgstr "Déplacer le point dans la courbe"
+msgstr "Déplacer point de Line2D"
#: editor/plugins/line_2d_editor_plugin.cpp
#: editor/plugins/path_2d_editor_plugin.cpp
@@ -4288,9 +3774,8 @@ msgid "Add Point (in empty space)"
msgstr "Ajouter un point (dans un espace vide)"
#: editor/plugins/line_2d_editor_plugin.cpp
-#, fuzzy
msgid "Split Segment (in line)"
-msgstr "Diviser le segment (en courbe)"
+msgstr "Diviser le segment (dans la ligne)"
#: editor/plugins/line_2d_editor_plugin.cpp
#: editor/plugins/path_2d_editor_plugin.cpp
@@ -4344,6 +3829,10 @@ msgid "Create Outline"
msgstr "Créer le contour"
#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Mesh"
+msgstr "Maillage"
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Create Trimesh Static Body"
msgstr "Créer un corps statique Trimesh"
@@ -4476,14 +3965,83 @@ msgstr "Échelle aléatoire :"
msgid "Populate"
msgstr "Peupler"
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake!"
+msgstr "Calculer !"
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+#, fuzzy
+msgid "Bake the navigation mesh.\n"
+msgstr "Créer un maillage de navigation"
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+#, fuzzy
+msgid "Clear the navigation mesh."
+msgstr "Créer un maillage de navigation"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Setting up Configuration..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Calculating grid size..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Creating heightfield..."
+msgstr "Création de l'octree de lumière"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Marking walkable triangles..."
+msgstr "Chaînes traduisibles…"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Constructing compact heightfield..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Eroding walkable area..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Partitioning..."
+msgstr "Avertissement"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Creating contours..."
+msgstr "Création de la texture d'octree"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Creating polymesh..."
+msgstr "Créer un maillage de contour…"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Converting to native navigation mesh..."
+msgstr "Créer un maillage de navigation"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Navigation Mesh Generator Setup:"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Parsing Geometry..."
+msgstr "Analyse de la géométrie"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Done!"
+msgstr ""
+
#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Create Navigation Polygon"
msgstr "Créer Polygone de Navigation"
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Remove Poly And Point"
-msgstr "Retirer Polygone et Point"
-
#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Clear Emission Mask"
msgstr "Effacer Masque d'Émission"
@@ -4496,6 +4054,7 @@ msgstr "Générer AABB"
#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Can only set point into a ParticlesMaterial process material"
msgstr ""
+"Ne peut définir qu'un point dans un matériau de processus ParticlesMaterial"
#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Error loading image:"
@@ -4519,9 +4078,8 @@ msgstr "Charger Masque d'Émission"
#: editor/plugins/particles_2d_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp
-#, fuzzy
msgid "Particles"
-msgstr "Vertex"
+msgstr "Particules"
#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Generated Point Count:"
@@ -4533,9 +4091,8 @@ msgid "Generation Time (sec):"
msgstr "Temps de Génération (sec):"
#: editor/plugins/particles_2d_editor_plugin.cpp
-#, fuzzy
msgid "Emission Mask"
-msgstr "Définir le masque d'émission"
+msgstr "Masque d'émission"
#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Capture from Pixel"
@@ -4554,14 +4111,12 @@ msgid "Node does not contain geometry (faces)."
msgstr "Nœud ne contient pas de géométrie (faces)."
#: editor/plugins/particles_editor_plugin.cpp
-#, fuzzy
msgid "A processor material of type 'ParticlesMaterial' is required."
msgstr "Un matériel processeur de type 'ParticlesMaterial' est requis."
#: editor/plugins/particles_editor_plugin.cpp
-#, fuzzy
msgid "Faces contain no area!"
-msgstr "Faces ne contiennent pas de zone!"
+msgstr "Des faces ne contiennent pas de zone !"
#: editor/plugins/particles_editor_plugin.cpp
msgid "No faces!"
@@ -4596,7 +4151,6 @@ msgid "Surface Points"
msgstr "Points de Surface"
#: editor/plugins/particles_editor_plugin.cpp
-#, fuzzy
msgid "Surface Points+Normal (Directed)"
msgstr "Points de Surface+Normale (Dirigée)"
@@ -4617,14 +4171,12 @@ msgid "Remove Point from Curve"
msgstr "Supprimer Point de la Courbe"
#: editor/plugins/path_2d_editor_plugin.cpp
-#, fuzzy
msgid "Remove Out-Control from Curve"
-msgstr "Supprimer le point d'une courbe"
+msgstr "Supprimer Out-Control d'une courbe"
#: editor/plugins/path_2d_editor_plugin.cpp
-#, fuzzy
msgid "Remove In-Control from Curve"
-msgstr "Supprimer le point d'une courbe"
+msgstr "Supprimer In-Control d'une courbe"
#: editor/plugins/path_2d_editor_plugin.cpp
#: editor/plugins/path_editor_plugin.cpp
@@ -4637,11 +4189,11 @@ msgstr "Déplacer le point dans la courbe"
#: editor/plugins/path_2d_editor_plugin.cpp
msgid "Move In-Control in Curve"
-msgstr ""
+msgstr "Déplacer In-Control dans courbe"
#: editor/plugins/path_2d_editor_plugin.cpp
msgid "Move Out-Control in Curve"
-msgstr ""
+msgstr "Déplacer Out-Control dans courbe"
#: editor/plugins/path_2d_editor_plugin.cpp
msgid "Select Control Points (Shift+Drag)"
@@ -4662,16 +4214,19 @@ msgid "Curve Point #"
msgstr "Point de courbe #"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve Point Position"
msgstr "Définir la position du point de la courbe"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve In Position"
-msgstr ""
+msgstr "Définir courbe en position"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve Out Position"
-msgstr ""
+msgstr "Définir courbe hors position"
#: editor/plugins/path_editor_plugin.cpp
msgid "Split Path"
@@ -4682,14 +4237,12 @@ msgid "Remove Path Point"
msgstr "Supprimer le chemin du point"
#: editor/plugins/path_editor_plugin.cpp
-#, fuzzy
msgid "Remove Out-Control Point"
-msgstr "Supprimer le chemin du point"
+msgstr "Supprimer point Out-Control"
#: editor/plugins/path_editor_plugin.cpp
-#, fuzzy
msgid "Remove In-Control Point"
-msgstr "Supprimer le chemin du point"
+msgstr "Supprimer point In-Control"
#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Create UV Map"
@@ -4732,6 +4285,14 @@ msgid "Scale Polygon"
msgstr "Mettre à l'échelle le polygone"
#: editor/plugins/polygon_2d_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Edit"
+msgstr "Modifier"
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Polygon->UV"
msgstr "Polygone -> UV"
@@ -4786,73 +4347,19 @@ msgstr "Charger une ressource"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/shader_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "Coller"
-#: editor/plugins/rich_text_editor_plugin.cpp
-msgid "Parse BBCode"
-msgstr "Analyser le BBCode"
-
-#: editor/plugins/sample_editor_plugin.cpp
-msgid "Length:"
-msgstr "Longueur :"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Open Sample File(s)"
-msgstr "Ouvrir un ou des fichiers d'échantillons"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "ERROR: Couldn't load sample!"
-msgstr "ERREUR : Impossible de charger l'échantillon !"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Add Sample"
-msgstr "Ajouter un échantillon"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Rename Sample"
-msgstr "Renommer l'échantillon"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Delete Sample"
-msgstr "Supprimer l'échantillon"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "16 Bits"
-msgstr "16 bits"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "8 Bits"
-msgstr "8 bits"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Stereo"
-msgstr "Stéréo"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Mono"
-msgstr "Mono"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Format"
-msgstr "Format"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Pitch"
-msgstr "Hauteur"
-
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Clear Recent Files"
-msgstr "Effacer les os"
+msgstr "Effacer les fichiers récents"
#: editor/plugins/script_editor_plugin.cpp
msgid ""
"Close and save changes?\n"
"\""
-msgstr ""
+msgstr "Quitter et sauvegarder les modifications?"
#: editor/plugins/script_editor_plugin.cpp
msgid "Error while saving theme"
@@ -4880,7 +4387,7 @@ msgstr "Enregistrer le thème sous…"
#: editor/plugins/script_editor_plugin.cpp
msgid " Class Reference"
-msgstr ""
+msgstr " Référence de classe"
#: editor/plugins/script_editor_plugin.cpp
msgid "Next script"
@@ -4903,7 +4410,6 @@ msgid "Save All"
msgstr "Tout enregistrer"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Soft Reload Script"
msgstr "Recharger le script (mode doux)"
@@ -4935,10 +4441,13 @@ msgstr "Fermer les documentations"
msgid "Close All"
msgstr "Fermer tout"
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+msgid "Run"
+msgstr "Lancer"
+
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Toggle Scripts Panel"
-msgstr "Basculer le favori"
+msgstr "Basculer vers le panneau de scripts"
#: editor/plugins/script_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
@@ -4964,7 +4473,8 @@ msgstr "Rentrer"
msgid "Break"
msgstr "Mettre en pause"
-#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+#: editor/script_editor_debugger.cpp
msgid "Continue"
msgstr "Continuer"
@@ -4973,26 +4483,12 @@ msgid "Keep Debugger Open"
msgstr "Garder le débogueur ouvert"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Debug with external editor"
-msgstr "Ouvrir dans l'éditeur"
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Window"
-msgstr "Fenêtre"
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Left"
-msgstr "Aller à gauche"
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Right"
-msgstr "Aller à droite"
+msgstr "Deboguer avec un éditeur externe"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Open Godot online documentation"
-msgstr "Chercher dans la documentation de référence."
+msgstr "Ouvrir la documentation Godot en ligne"
#: editor/plugins/script_editor_plugin.cpp
msgid "Search the class hierarchy."
@@ -5011,9 +4507,8 @@ msgid "Go to next edited document."
msgstr "Aller au document modifié suivant."
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Discard"
-msgstr "Discret"
+msgstr "Abandonner"
#: editor/plugins/script_editor_plugin.cpp
msgid "Create Script"
@@ -5048,28 +4543,27 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
msgid "Only resources from filesystem can be dropped."
-msgstr ""
+msgstr "Seules les ressources du système de fichiers peuvent être abaissées."
#: editor/plugins/script_text_editor.cpp
msgid "Pick Color"
msgstr "Prélever une couleur"
#: editor/plugins/script_text_editor.cpp
-#, fuzzy
msgid "Convert Case"
-msgstr "Conversion des images"
+msgstr "Cas de conversion"
#: editor/plugins/script_text_editor.cpp
msgid "Uppercase"
-msgstr ""
+msgstr "Majuscule"
#: editor/plugins/script_text_editor.cpp
msgid "Lowercase"
-msgstr ""
+msgstr "Minuscule"
#: editor/plugins/script_text_editor.cpp
msgid "Capitalize"
-msgstr ""
+msgstr "Capitaliser"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/shader_editor_plugin.cpp scene/gui/line_edit.cpp
@@ -5078,8 +4572,9 @@ msgid "Cut"
msgstr "Couper"
#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "Copier"
@@ -5098,9 +4593,8 @@ msgid "Move Down"
msgstr "Déplacer vers le bas"
#: editor/plugins/script_text_editor.cpp
-#, fuzzy
msgid "Delete Line"
-msgstr "Supprimer le point"
+msgstr "Supprimer ligne"
#: editor/plugins/script_text_editor.cpp
msgid "Indent Left"
@@ -5128,11 +4622,11 @@ msgstr "Supprimer les espaces de fin de ligne"
#: editor/plugins/script_text_editor.cpp
msgid "Convert Indent To Spaces"
-msgstr ""
+msgstr "Convertir indentations en espaces"
#: editor/plugins/script_text_editor.cpp
msgid "Convert Indent To Tabs"
-msgstr ""
+msgstr "Convertir indentations en espaces"
#: editor/plugins/script_text_editor.cpp
msgid "Auto Indent"
@@ -5156,14 +4650,12 @@ msgid "Goto Previous Breakpoint"
msgstr "Aller au point d'arrêt précédent"
#: editor/plugins/script_text_editor.cpp
-#, fuzzy
msgid "Convert To Uppercase"
-msgstr "Convertir vers…"
+msgstr "Convertir en majuscule"
#: editor/plugins/script_text_editor.cpp
-#, fuzzy
msgid "Convert To Lowercase"
-msgstr "Convertir vers…"
+msgstr "Convertir en minuscule"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/shader_editor_plugin.cpp
@@ -5190,7 +4682,7 @@ msgstr "Aide contextuelle"
#: editor/plugins/shader_editor_plugin.cpp
msgid "Shader"
-msgstr ""
+msgstr "Shader"
#: editor/plugins/shader_graph_editor_plugin.cpp
msgid "Change Scalar Constant"
@@ -5234,15 +4726,15 @@ msgstr "Modifier une fonction vecteur"
#: editor/plugins/shader_graph_editor_plugin.cpp
msgid "Change Scalar Uniform"
-msgstr ""
+msgstr "Modifier échelle"
#: editor/plugins/shader_graph_editor_plugin.cpp
msgid "Change Vec Uniform"
-msgstr ""
+msgstr "Modifier vecteur"
#: editor/plugins/shader_graph_editor_plugin.cpp
msgid "Change RGB Uniform"
-msgstr ""
+msgstr "Modifier RGB"
#: editor/plugins/shader_graph_editor_plugin.cpp
msgid "Change Default Value"
@@ -5250,15 +4742,15 @@ msgstr "Changer la valeur par défaut"
#: editor/plugins/shader_graph_editor_plugin.cpp
msgid "Change XForm Uniform"
-msgstr ""
+msgstr "Modifier XForm"
#: editor/plugins/shader_graph_editor_plugin.cpp
msgid "Change Texture Uniform"
-msgstr ""
+msgstr "Modifier texture"
#: editor/plugins/shader_graph_editor_plugin.cpp
msgid "Change Cubemap Uniform"
-msgstr ""
+msgstr "Modifier Cubemap"
#: editor/plugins/shader_graph_editor_plugin.cpp
msgid "Change Comment"
@@ -5345,10 +4837,6 @@ msgid "View Plane Transform."
msgstr "Transformation du plan de vue."
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Scaling to %s%%."
-msgstr "Mise à l'échelle %s%%."
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rotating %s degrees."
msgstr "Rotation de %s degrés."
@@ -5365,10 +4853,6 @@ msgid "Top View."
msgstr "Vue de dessus."
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Top"
-msgstr "Dessus"
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rear View."
msgstr "Vue arrière."
@@ -5410,29 +4894,25 @@ msgstr "Clé d'animation insérée."
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
-msgstr ""
+msgstr "Objets dessinés"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Material Changes"
-msgstr "Repeindre quand modifié"
+msgstr "Modifications de materiau"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Shader Changes"
-msgstr "Repeindre quand modifié"
+msgstr "Modification de shader"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Surface Changes"
-msgstr "Repeindre quand modifié"
+msgstr "Modifications de surface"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Draw Calls"
-msgstr ""
+msgstr "Appels de graphes"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Vertices"
msgstr "Vertex"
@@ -5453,66 +4933,58 @@ msgid "Display Overdraw"
msgstr "Affichage des surimpressions"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Display Unshaded"
-msgstr "Affichage sans ombrage"
+msgstr "Afficher sans ombrage"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "View Environment"
-msgstr "Environnement"
+msgstr "Voir environnement"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "View Gizmos"
-msgstr "Gizmos"
+msgstr "Voir les gadgets"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "View Information"
-msgstr ""
+msgstr "Voir information"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Audio Listener"
msgstr "Écouteur audio"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Doppler Enable"
-msgstr "Activer"
+msgstr "Activer Doppler"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Freelook Left"
-msgstr ""
+msgstr "Vue libre gauche"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Freelook Right"
-msgstr ""
+msgstr "Vue libre droite"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Freelook Forward"
-msgstr "Avancer"
+msgstr "Vue libre de devant"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Freelook Backwards"
-msgstr "À l'envers"
+msgstr "Vue libre de derrière"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Freelook Up"
-msgstr ""
+msgstr "Vue libre de dessus"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Freelook Down"
-msgstr "Molette vers le bas."
+msgstr "Vue libre de dessous"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Freelook Speed Modifier"
-msgstr ""
+msgstr "Modificateur de vitesse de la vue libre"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "preview"
msgstr "Aperçu"
@@ -5521,17 +4993,18 @@ msgid "XForm Dialog"
msgstr "Dialogue XForm"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Select Mode (Q)\n"
-msgstr "Sélectionner le mode"
+msgstr "Sélectionner le mode (Q)\n"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid ""
"Drag: Rotate\n"
"Alt+Drag: Move\n"
"Alt+RMB: Depth list selection"
-msgstr "Alt + Bouton droit : sélection détaillée par liste"
+msgstr ""
+"Glisser : Rotation\n"
+"ALt+glisser : Déplacer\n"
+"Alt + Bouton droit : sélection détaillée par liste"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Move Mode (W)"
@@ -5590,30 +5063,30 @@ msgid "Align Selection With View"
msgstr "Aligner la sélection avec la vue"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Tool Select"
-msgstr "Sélectionner"
+msgstr "Outil sélection"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Tool Move"
-msgstr "Déplacer"
+msgstr "Outil déplacement"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Tool Rotate"
-msgstr "Contrôle: Tourner"
+msgstr "Outil rotation"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Tool Scale"
-msgstr "Échelle :"
+msgstr "Outil échelle"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Transform"
msgstr "Transformation"
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Configure Snap.."
+msgstr "Configurer la grille…"
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Local Coords"
msgstr "Coordonnées locales"
@@ -5731,7 +5204,6 @@ msgid "Resource clipboard is empty or not a texture!"
msgstr "Le presse-papiers des ressources est vide ou n'est pas une texture !"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-#, fuzzy
msgid "Paste Frame"
msgstr "Coller Frame"
@@ -5760,6 +5232,10 @@ msgid "Speed (FPS):"
msgstr "Vitesse (FPS) :"
#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Loop"
+msgstr "Boucle"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Animation Frames"
msgstr "Trames d'animation"
@@ -5772,21 +5248,22 @@ msgid "Insert Empty (After)"
msgstr "Insérer vide (après)"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Up"
-msgstr "Haut"
+#, fuzzy
+msgid "Move (Before)"
+msgstr "Déplacer le(s) nœud(s)"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Down"
-msgstr "Bas"
+#, fuzzy
+msgid "Move (After)"
+msgstr "Aller à gauche"
#: editor/plugins/style_box_editor_plugin.cpp
msgid "StyleBox Preview:"
msgstr "Aperçu de la StyleBox :"
#: editor/plugins/texture_region_editor_plugin.cpp
-#, fuzzy
msgid "Set Region Rect"
-msgstr "Région de texture"
+msgstr "Définir région rectangulaire"
#: editor/plugins/texture_region_editor_plugin.cpp
msgid "Snap Mode:"
@@ -5813,7 +5290,6 @@ msgid "Offset:"
msgstr "Décalage :"
#: editor/plugins/texture_region_editor_plugin.cpp
-#, fuzzy
msgid "Step:"
msgstr "Pas (s) :"
@@ -5847,18 +5323,20 @@ msgid "Remove Item"
msgstr "Supprimer l'item"
#: editor/plugins/theme_editor_plugin.cpp
-#, fuzzy
msgid "Remove All Items"
-msgstr "Supprimer des items de classe"
+msgstr "Supprimer tous"
#: editor/plugins/theme_editor_plugin.cpp
-#, fuzzy
msgid "Remove All"
-msgstr "Supprimer"
+msgstr "Supprimer tout"
#: editor/plugins/theme_editor_plugin.cpp
-msgid "Theme"
-msgstr "Thème"
+msgid "Edit theme.."
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Theme editing menu."
+msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
msgid "Add Class Items"
@@ -5942,11 +5420,14 @@ msgid "Style"
msgstr "Style"
#: editor/plugins/theme_editor_plugin.cpp
+msgid "Font"
+msgstr "Police"
+
+#: editor/plugins/theme_editor_plugin.cpp
msgid "Color"
msgstr "Couleur"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Erase Selection"
msgstr "Supprimer la sélection"
@@ -5955,18 +5436,16 @@ msgid "Paint TileMap"
msgstr "Peindre sur la TileMap"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Line Draw"
-msgstr "Linéaire"
+msgstr "Dessin de ligne"
#: editor/plugins/tile_map_editor_plugin.cpp
msgid "Rectangle Paint"
-msgstr ""
+msgstr "Peinture de rectangle"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Bucket Fill"
-msgstr "Seau"
+msgstr "Remplissage du seau"
#: editor/plugins/tile_map_editor_plugin.cpp
msgid "Erase TileMap"
@@ -5993,8 +5472,9 @@ msgid "Mirror Y"
msgstr "Miroir Y"
#: editor/plugins/tile_map_editor_plugin.cpp
-msgid "Bucket"
-msgstr "Seau"
+#, fuzzy
+msgid "Paint Tile"
+msgstr "Peindre sur la TileMap"
#: editor/plugins/tile_map_editor_plugin.cpp
msgid "Pick Tile"
@@ -6045,24 +5525,25 @@ msgid "Error"
msgstr "Erreur"
#: editor/project_export.cpp
-#, fuzzy
msgid "Runnable"
-msgstr "Activer"
+msgstr "Activable"
#: editor/project_export.cpp
-#, fuzzy
msgid "Delete patch '"
-msgstr "Supprimer l'entrée"
+msgstr "Supprimer patch"
#: editor/project_export.cpp
-#, fuzzy
msgid "Delete preset '%s'?"
-msgstr "Supprimer les fichiers sélectionnés ?"
+msgstr "Supprimer pré-réglage '%s' ?"
#: editor/project_export.cpp
#, fuzzy
+msgid "Export templates for this platform are missing/corrupted: "
+msgstr "Modèles d'exportation manquants pour cette plateforme :"
+
+#: editor/project_export.cpp
msgid "Presets"
-msgstr "Pré-réglage…"
+msgstr "Pré-réglages"
#: editor/project_export.cpp editor/project_settings_editor.cpp
msgid "Add.."
@@ -6073,68 +5554,58 @@ msgid "Resources"
msgstr "Ressources"
#: editor/project_export.cpp
-#, fuzzy
msgid "Export all resources in the project"
-msgstr "Exporter toutes les ressources dans le projet."
+msgstr "Exporter toutes les ressources dans le projet"
#: editor/project_export.cpp
-#, fuzzy
msgid "Export selected scenes (and dependencies)"
-msgstr "Exporter les ressources sélectionnées (y compris les dépendences)."
+msgstr "Exporter les scènes sélectionnées (y compris les dépendences)"
#: editor/project_export.cpp
-#, fuzzy
msgid "Export selected resources (and dependencies)"
-msgstr "Exporter les ressources sélectionnées (y compris les dépendences)."
+msgstr "Exporter les ressources sélectionnées (y compris les dépendences)"
#: editor/project_export.cpp
msgid "Export Mode:"
msgstr "Mode d'exportation :"
#: editor/project_export.cpp
-#, fuzzy
msgid "Resources to export:"
msgstr "Ressources à exporter :"
#: editor/project_export.cpp
-#, fuzzy
msgid ""
"Filters to export non-resource files (comma separated, e.g: *.json, *.txt)"
msgstr ""
-"Filtres à utiliser pour l'exportation des fichiers (séparés par des "
-"virgules, par exemple : *.json, *.txt) :"
+"Filtres d'export de fichiers non ressources (séparés par des virgules, par "
+"exemple : *.json, *.txt) :"
#: editor/project_export.cpp
-#, fuzzy
msgid ""
"Filters to exclude files from project (comma separated, e.g: *.json, *.txt)"
msgstr ""
-"Filtres à utiliser pour exclure des fichiers (séparés par des virgules, par "
+"Filtres pour exclure des fichiers du projet (séparés par des virgules, par "
"exemple: *.json, *.txt) :"
#: editor/project_export.cpp
-#, fuzzy
msgid "Patches"
-msgstr "Correspondances :"
+msgstr "Patches"
#: editor/project_export.cpp
-#, fuzzy
msgid "Make Patch"
-msgstr "Chemin de destination :"
+msgstr "Conçevoir un patch"
#: editor/project_export.cpp
-#, fuzzy
msgid "Features"
-msgstr "Texture"
+msgstr "Fonctionnalités"
#: editor/project_export.cpp
msgid "Custom (comma-separated):"
-msgstr ""
+msgstr "Personnalisé (séparé par des virgules) :"
#: editor/project_export.cpp
-#, fuzzy
msgid "Feature List:"
-msgstr "Liste des méthodes :"
+msgstr "Liste des fonctionnalités :"
#: editor/project_export.cpp
msgid "Export PCK/Zip"
@@ -6142,82 +5613,115 @@ msgstr "Exporter le PCK/ZIP"
#: editor/project_export.cpp
msgid "Export templates for this platform are missing:"
-msgstr ""
+msgstr "Modèles d'exportation manquants pour cette plateforme :"
#: editor/project_export.cpp
#, fuzzy
+msgid "Export templates for this platform are missing/corrupted:"
+msgstr "Modèles d'exportation manquants pour cette plateforme :"
+
+#: editor/project_export.cpp
msgid "Export With Debug"
-msgstr "Exporter un ensemble de tuiles"
+msgstr "Exporter avec debug"
#: editor/project_manager.cpp
-msgid "Invalid project path, the path must exist!"
-msgstr "Chemin de projet invalide, le chemin doit exister !"
+#, fuzzy
+msgid "The path does not exist."
+msgstr "Le fichier n'existe pas."
#: editor/project_manager.cpp
#, fuzzy
-msgid "Invalid project path, project.godot must not exist."
-msgstr "Chemin de projet invalide, engine.cfg ne doit pas exister."
+msgid "Please choose a 'project.godot' file."
+msgstr "Veuillez exporter en dehors du dossier du projet !"
#: editor/project_manager.cpp
-#, fuzzy
-msgid "Invalid project path, project.godot must exist."
-msgstr "Chemin de projet invalide, engine.cfg doit exister."
+msgid ""
+"Your project will be created in a non empty folder (you might want to create "
+"a new folder)."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Please choose a folder that does not contain a 'project.godot' file."
+msgstr ""
#: editor/project_manager.cpp
msgid "Imported Project"
msgstr "Projet importé"
#: editor/project_manager.cpp
+msgid " "
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "It would be a good idea to name your project."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Invalid project path (changed anything?)."
msgstr "Chemin de projet non valide (avez-vous changé quelque chose ?)."
#: editor/project_manager.cpp
#, fuzzy
-msgid "Couldn't create project.godot in project path."
-msgstr ""
-"Impossible de créer le fichier engine.cfg dans le répertoire du projet."
+msgid "Couldn't get project.godot in project path."
+msgstr "Impossible de créer le fichier project.godot dans le chemin du projet."
#: editor/project_manager.cpp
#, fuzzy
+msgid "Couldn't edit project.godot in project path."
+msgstr "Impossible de créer le fichier project.godot dans le chemin du projet."
+
+#: editor/project_manager.cpp
+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 ""
-"Les fichiers suivants sont plus récents sur le disque.\n"
-"Quelle action doit être prise ? :"
+msgstr "L'extraction des fichiers suivants a échoué depuis le paquetage :"
+
+#: editor/project_manager.cpp
+#, fuzzy
+msgid "Rename Project"
+msgstr "Projet sans titre"
+
+#: editor/project_manager.cpp
+#, fuzzy
+msgid "Couldn't get project.godot in the project path."
+msgstr "Impossible de créer le fichier project.godot dans le chemin du projet."
+
+#: editor/project_manager.cpp
+msgid "New Game Project"
+msgstr "Nouveau projet de jeu"
#: editor/project_manager.cpp
msgid "Import Existing Project"
msgstr "Importer un projet existant"
#: editor/project_manager.cpp
-msgid "Project Path (Must Exist):"
-msgstr "Chemin du projet (doit exister) :"
+msgid "Create New Project"
+msgstr "Créer un nouveau projet"
+
+#: editor/project_manager.cpp
+msgid "Install Project:"
+msgstr "Installer projet :"
#: editor/project_manager.cpp
msgid "Project Name:"
msgstr "Nom du projet :"
#: editor/project_manager.cpp
-msgid "Create New Project"
-msgstr "Créer un nouveau projet"
+#, fuzzy
+msgid "Create folder"
+msgstr "Créer un dossier"
#: editor/project_manager.cpp
msgid "Project Path:"
msgstr "Chemin du projet :"
#: editor/project_manager.cpp
-#, fuzzy
-msgid "Install Project:"
-msgstr "Projets récents :"
-
-#: editor/project_manager.cpp
msgid "Browse"
msgstr "Parcourir"
#: editor/project_manager.cpp
-msgid "New Game Project"
-msgstr "Nouveau projet de jeu"
-
-#: editor/project_manager.cpp
msgid "That's a BINGO!"
msgstr "C'est un BINGO !"
@@ -6227,28 +5731,32 @@ msgstr "Projet sans titre"
#: editor/project_manager.cpp
#, fuzzy
+msgid "Can't open project"
+msgstr "Impossible de lancer le projet"
+
+#: editor/project_manager.cpp
msgid "Are you sure to open more than one project?"
msgstr "Voulez-vous vraiment ouvrir plus d'un projet à la fois ?"
#: editor/project_manager.cpp
-#, fuzzy
msgid ""
"Can't run project: no main scene defined.\n"
"Please edit the project and set the main scene in \"Project Settings\" under "
"the \"Application\" category."
msgstr ""
-"Aucune scène principale n'a jamais été définie, en sélectionner une ?\n"
-"Vous pouvez la modifier ultérieurement dans les « Paramètres du projet » "
-"dans la catégorie « application »."
+"Impossible de lancer le projet : Pas de scène principale définie\n"
+"Veuillez éditer le projet et définir la scène principale dans \"Paramètres "
+"du projet\" sous la catégorie \"Application\"."
#: editor/project_manager.cpp
msgid ""
"Can't run project: Assets need to be imported.\n"
"Please edit the project to trigger the initial import."
msgstr ""
+"Impossible d'exécuter le projet: Des ressources doivent être importées. \n"
+"Veuillez éditer le projet pour déclencher l'importation initiale."
#: editor/project_manager.cpp
-#, fuzzy
msgid "Are you sure to run more than one project?"
msgstr "Voulez-vous vraiment lancer plus d'un projet à la fois ?"
@@ -6259,6 +5767,12 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
+"Language changed.\n"
+"The UI will update next time the editor or project manager starts."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid ""
"You are about the scan %s folders for existing Godot projects. Do you "
"confirm?"
msgstr ""
@@ -6270,10 +5784,6 @@ msgid "Project List"
msgstr "Liste des projets"
#: editor/project_manager.cpp
-msgid "Run"
-msgstr "Lancer"
-
-#: editor/project_manager.cpp
msgid "Scan"
msgstr "Scanner"
@@ -6286,9 +5796,8 @@ msgid "New Project"
msgstr "Nouveau projet"
#: editor/project_manager.cpp
-#, fuzzy
msgid "Templates"
-msgstr "Supprimer l'item"
+msgstr "Modèles"
#: editor/project_manager.cpp
msgid "Exit"
@@ -6296,8 +5805,12 @@ msgstr "Quitter"
#: editor/project_manager.cpp
#, fuzzy
+msgid "Restart Now"
+msgstr "Redémarrer (s) :"
+
+#: editor/project_manager.cpp
msgid "Can't run project"
-msgstr "Connection impossible."
+msgstr "Impossible de lancer le projet"
#: editor/project_settings_editor.cpp
msgid "Key "
@@ -6332,17 +5845,14 @@ msgid "Add Input Action Event"
msgstr "Ajouter un événement d'action d'entrée"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Meta+"
msgstr "Méta+"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Shift+"
msgstr "Maj+"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Alt+"
msgstr "Alt+"
@@ -6400,18 +5910,16 @@ msgid "Change"
msgstr "Changer"
#: editor/project_settings_editor.cpp
-#, fuzzy
msgid "Joypad Axis Index:"
-msgstr "Index de l'axe du joystick :"
+msgstr "Index de l'axe de la manette de jeu :"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Axis"
msgstr "Axe"
#: editor/project_settings_editor.cpp
-#, fuzzy
msgid "Joypad Button Index:"
-msgstr "Index du bouton du joystick :"
+msgstr "Index de bouton de la manette de jeu :"
#: editor/project_settings_editor.cpp
msgid "Add Input Action"
@@ -6422,61 +5930,67 @@ msgid "Erase Input Action Event"
msgstr "Effacer l'événement d'action d'entrée"
#: editor/project_settings_editor.cpp
-#, fuzzy
msgid "Add Event"
-msgstr "Ajouter vide"
+msgstr "Ajouter évènement"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Device"
msgstr "Périphérique"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Button"
msgstr "Bouton"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Left Button."
msgstr "Bouton gauche."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Right Button."
msgstr "Bouton droite."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Middle Button."
msgstr "Bouton du milieu."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Up."
msgstr "Molette vers le haut."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Down."
msgstr "Molette vers le bas."
#: editor/project_settings_editor.cpp
-#, fuzzy
msgid "Add Global Property"
-msgstr "Ajouter une propriété accesseur"
+msgstr "Ajouter une propriété globale"
#: editor/project_settings_editor.cpp
-msgid "Select an setting item first!"
-msgstr ""
+#, fuzzy
+msgid "Select a setting item first!"
+msgstr "Choisissez d'abord un élément de réglage !"
#: editor/project_settings_editor.cpp
-#, fuzzy
msgid "No property '"
-msgstr "Propriété :"
+msgstr "Pas de propriété"
#: editor/project_settings_editor.cpp
-#, fuzzy
msgid "Setting '"
-msgstr "Paramètres"
+msgstr "Paramètre"
#: editor/project_settings_editor.cpp
-#, fuzzy
msgid "Delete Item"
-msgstr "Supprimer l'entrée"
+msgstr "Supprimer élément"
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Can't contain '/' or ':'"
+msgstr "Connection à l'hôte impossible:"
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Already existing"
+msgstr "Mode persistant"
#: editor/project_settings_editor.cpp
msgid "Error saving settings."
@@ -6488,7 +6002,7 @@ msgstr "Paramètres enregistrés avec succès."
#: editor/project_settings_editor.cpp
msgid "Override for Feature"
-msgstr ""
+msgstr "Remplacement de fonctionnalité"
#: editor/project_settings_editor.cpp
msgid "Add Translation"
@@ -6504,24 +6018,32 @@ msgstr "Ajouter un chemin remappé"
#: editor/project_settings_editor.cpp
msgid "Resource Remap Add Remap"
-msgstr ""
+msgstr "Remap de ressources ajout de remap"
#: editor/project_settings_editor.cpp
msgid "Change Resource Remap Language"
-msgstr ""
+msgstr "Modifier language de remap de ressource"
#: editor/project_settings_editor.cpp
msgid "Remove Resource Remap"
-msgstr ""
+msgstr "Supprimer remap de ressource"
#: editor/project_settings_editor.cpp
msgid "Remove Resource Remap Option"
-msgstr ""
+msgstr "Supprimer option de remap de ressource"
#: editor/project_settings_editor.cpp
#, fuzzy
+msgid "Changed Locale Filter"
+msgstr "Changer le temps de mélange"
+
+#: editor/project_settings_editor.cpp
+msgid "Changed Locale Filter Mode"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "Project Settings (project.godot)"
-msgstr "Paramètres du projet (engine.cfg)"
+msgstr "Paramètres du projet (project.godot)"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
msgid "General"
@@ -6533,7 +6055,7 @@ msgstr "Propriété :"
#: editor/project_settings_editor.cpp
msgid "Override For.."
-msgstr ""
+msgstr "Remplacement pour.."
#: editor/project_settings_editor.cpp
msgid "Input Map"
@@ -6580,13 +6102,36 @@ msgid "Locale"
msgstr "Langue"
#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Locales Filter"
+msgstr "Filtre d'image :"
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Show all locales"
+msgstr "Afficher les os"
+
+#: editor/project_settings_editor.cpp
+msgid "Show only selected locales"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Filter mode:"
+msgstr "Filtrer les noeuds"
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Locales:"
+msgstr "Langue"
+
+#: editor/project_settings_editor.cpp
msgid "AutoLoad"
msgstr "AutoLoad"
#: editor/property_editor.cpp
-#, fuzzy
msgid "Pick a Viewport"
-msgstr "1 vue"
+msgstr "Choisissez un viewport"
#: editor/property_editor.cpp
msgid "Ease In"
@@ -6621,7 +6166,6 @@ msgid "Assign"
msgstr "Assigner"
#: editor/property_editor.cpp
-#, fuzzy
msgid "Select Node"
msgstr "Sélectionner un nœud"
@@ -6631,22 +6175,29 @@ msgstr "Nouveau script"
#: editor/property_editor.cpp
#, fuzzy
+msgid "Make Unique"
+msgstr "Créer les os"
+
+#: editor/property_editor.cpp
msgid "Show in File System"
-msgstr "Système de fichiers"
+msgstr "Montrer dans le système de fichiers"
+
+#: editor/property_editor.cpp
+#, fuzzy
+msgid "Convert To %s"
+msgstr "Convertir vers…"
#: editor/property_editor.cpp
msgid "Error loading file: Not a resource!"
msgstr "Erreur de chargement du fichier : ce n'est pas une ressource !"
#: editor/property_editor.cpp
-#, fuzzy
msgid "Selected node is not a Viewport!"
-msgstr "Sélectionner les nœuds à importer"
+msgstr "Le noeud sélectionné n'est pas un viewport !"
#: editor/property_editor.cpp
-#, fuzzy
msgid "Pick a Node"
-msgstr "Sélectionner un nœud"
+msgstr "Choisissez un nœud"
#: editor/property_editor.cpp
msgid "Bit %d, val %d."
@@ -6673,6 +6224,11 @@ msgid "Select Property"
msgstr "Sélectionnez une propriété"
#: editor/property_selector.cpp
+#, fuzzy
+msgid "Select Virtual Method"
+msgstr "Sélectionner une méthode"
+
+#: editor/property_selector.cpp
msgid "Select Method"
msgstr "Sélectionner une méthode"
@@ -6701,26 +6257,6 @@ msgstr "Conserver la transformation globale"
msgid "Reparent"
msgstr "Re-parenter"
-#: editor/resources_dock.cpp
-msgid "Create New Resource"
-msgstr "Créer une nouvelle ressource"
-
-#: editor/resources_dock.cpp
-msgid "Open Resource"
-msgstr "Ouvrir la ressource"
-
-#: editor/resources_dock.cpp
-msgid "Save Resource"
-msgstr "Enregistrer la ressource"
-
-#: editor/resources_dock.cpp
-msgid "Resource Tools"
-msgstr "Outils des ressources"
-
-#: editor/resources_dock.cpp
-msgid "Make Local"
-msgstr "Rendre local"
-
#: editor/run_settings_dialog.cpp
msgid "Run Mode:"
msgstr "Mode d'exécution :"
@@ -6792,7 +6328,7 @@ msgstr "Supprimer le(s) nœud(s) ?"
#: editor/scene_tree_dock.cpp
msgid "Can not perform with the root node."
-msgstr ""
+msgstr "Ne peut fonctionner avec le noeud racine."
#: editor/scene_tree_dock.cpp
msgid "This operation can't be done on instanced scenes."
@@ -6847,17 +6383,8 @@ msgid "Error duplicating scene to save it."
msgstr "Erreur de duplication de la scène afin de l'enregistrer."
#: editor/scene_tree_dock.cpp
-#, fuzzy
msgid "Sub-Resources:"
-msgstr "Ressources :"
-
-#: editor/scene_tree_dock.cpp
-msgid "Edit Groups"
-msgstr "Modifier les groupes"
-
-#: editor/scene_tree_dock.cpp
-msgid "Edit Connections"
-msgstr "Modifier les connexions"
+msgstr "Ressources secondaires :"
#: editor/scene_tree_dock.cpp
msgid "Clear Inheritance"
@@ -6884,9 +6411,8 @@ msgid "Change Type"
msgstr "Changer le type"
#: editor/scene_tree_dock.cpp
-#, fuzzy
msgid "Attach Script"
-msgstr "Ajouter un script"
+msgstr "Attacher un script"
#: editor/scene_tree_dock.cpp
msgid "Clear Script"
@@ -6901,9 +6427,8 @@ msgid "Save Branch as Scene"
msgstr "Sauvegarder la branche comme scène"
#: editor/scene_tree_dock.cpp
-#, fuzzy
msgid "Copy Node Path"
-msgstr "Copier le chemin"
+msgstr "Copier le chemin du noeud"
#: editor/scene_tree_dock.cpp
msgid "Delete (No Confirm)"
@@ -6922,19 +6447,17 @@ msgstr ""
"nœud racine n'existe."
#: editor/scene_tree_dock.cpp
-#, fuzzy
msgid "Filter nodes"
-msgstr "Filtres"
+msgstr "Filtrer les noeuds"
#: editor/scene_tree_dock.cpp
-#, fuzzy
msgid "Attach a new or existing script for the selected node."
-msgstr "Créer un nouveau script pour le nœud sélectionné."
+msgstr ""
+"Attacher un nouveau script ou un script existant pour le nœud sélectionné ."
#: editor/scene_tree_dock.cpp
-#, fuzzy
msgid "Clear a script for the selected node."
-msgstr "Créer un nouveau script pour le nœud sélectionné."
+msgstr "Effacer un script pour le nœud sélectionné."
#: editor/scene_tree_dock.cpp
msgid "Clear Inheritance? (No Undo!)"
@@ -6954,51 +6477,59 @@ msgstr "Afficher/cacher le CanvasItem"
#: editor/scene_tree_editor.cpp
msgid "Node configuration warning:"
-msgstr ""
+msgstr "Avertissement de configuration de noeud :"
#: editor/scene_tree_editor.cpp
msgid ""
"Node has connection(s) and group(s)\n"
"Click to show signals dock."
msgstr ""
+"Le noeud possède une (des) connection(s) et un (des) groupe(s)\n"
+"Cliquez pour montrer l'arrimage de signaux."
#: editor/scene_tree_editor.cpp
msgid ""
"Node has connections.\n"
"Click to show signals dock."
msgstr ""
+"Le noeud possède des connections.\n"
+"Cliquez pour montrer l'arrimage de signaux."
#: editor/scene_tree_editor.cpp
msgid ""
"Node is in group(s).\n"
"Click to show groups dock."
msgstr ""
+"Le noeud fait partie d'un (de) groupe(s).\n"
+"Cliquez pour montrer l'arrimage de goupes."
#: editor/scene_tree_editor.cpp
msgid "Instance:"
msgstr "Instance :"
#: editor/scene_tree_editor.cpp
-#, fuzzy
msgid "Open script"
-msgstr "Script suivant"
+msgstr "Ouvrir script"
#: editor/scene_tree_editor.cpp
msgid ""
"Node is locked.\n"
"Click to unlock"
msgstr ""
+"Noeud verouillé.\n"
+"Cliquez pour dévérouiller"
#: editor/scene_tree_editor.cpp
msgid ""
"Children are not selectable.\n"
"Click to make selectable"
msgstr ""
+"Enfants non séléctionnable.\n"
+"Cliquez pour les rendre sélectionnable"
#: editor/scene_tree_editor.cpp
-#, fuzzy
msgid "Toggle Visibility"
-msgstr "Afficher/cacher le Spatial"
+msgstr "Basculer visibilité"
#: editor/scene_tree_editor.cpp
msgid "Invalid node name, the following characters are not allowed:"
@@ -7014,26 +6545,23 @@ msgstr "Arbre de scène (nœuds) :"
#: editor/scene_tree_editor.cpp
msgid "Node Configuration Warning!"
-msgstr ""
+msgstr "Avertissement de configuration de noeud !"
#: editor/scene_tree_editor.cpp
msgid "Select a Node"
msgstr "Sélectionner un nœud"
#: editor/script_create_dialog.cpp
-#, fuzzy
msgid "Error loading template '%s'"
-msgstr "Erreur de chargement d'image :"
+msgstr "Erreur de chargement de modèle '%s'"
#: editor/script_create_dialog.cpp
-#, fuzzy
msgid "Error - Could not create script in filesystem."
-msgstr "Impossible de créer le script dans le système de fichiers."
+msgstr "Erreur - Impossible de créer le script dans le système de fichiers."
#: editor/script_create_dialog.cpp
-#, fuzzy
msgid "Error loading script from %s"
-msgstr "Erreur de chargement de la scène depuis %s"
+msgstr "Erreur de chargement de script depuis %s"
#: editor/script_create_dialog.cpp
msgid "N/A"
@@ -7052,74 +6580,77 @@ msgid "Invalid base path"
msgstr "Chemin de base invalide"
#: editor/script_create_dialog.cpp
+msgid "Directory of the same name exists"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
+#, fuzzy
+msgid "File exists, will be reused"
+msgstr "Le fichier existe, l'écraser ?"
+
+#: editor/script_create_dialog.cpp
msgid "Invalid extension"
msgstr "Extension invalide"
#: editor/script_create_dialog.cpp
msgid "Wrong extension chosen"
-msgstr ""
+msgstr "Choix d'extension erroné"
#: editor/script_create_dialog.cpp
-#, fuzzy
msgid "Invalid Path"
-msgstr "Chemin invalide."
+msgstr "Chemin invalide"
#: editor/script_create_dialog.cpp
msgid "Invalid class name"
msgstr "Nom de classe invalide"
#: editor/script_create_dialog.cpp
-#, fuzzy
msgid "Invalid inherited parent name or path"
-msgstr "Indice de nom de propriété invalide."
+msgstr "Nom ou chemin parent hérité invalide"
#: editor/script_create_dialog.cpp
-#, fuzzy
msgid "Script valid"
-msgstr "Script"
+msgstr "Script valide"
#: editor/script_create_dialog.cpp
msgid "Allowed: a-z, A-Z, 0-9 and _"
-msgstr ""
+msgstr "Autorisé : a-z, A-Z, 0-9 et _"
#: editor/script_create_dialog.cpp
msgid "Built-in script (into scene file)"
-msgstr ""
+msgstr "Script intégré (dans le fichier scène)"
#: editor/script_create_dialog.cpp
-#, fuzzy
msgid "Create new script file"
-msgstr "Créer un script"
+msgstr "Créer nouveau fichier de script"
#: editor/script_create_dialog.cpp
-#, fuzzy
msgid "Load existing script file"
-msgstr "Script suivant"
+msgstr "Charger fichier de script existant"
+
+#: editor/script_create_dialog.cpp
+msgid "Language"
+msgstr "Langage"
#: editor/script_create_dialog.cpp
-#, fuzzy
msgid "Inherits"
-msgstr "Hérite de :"
+msgstr "Hérité de :"
#: editor/script_create_dialog.cpp
-#, fuzzy
msgid "Class Name"
-msgstr "Nom de classe :"
+msgstr "Nom de classe"
#: editor/script_create_dialog.cpp
-#, fuzzy
msgid "Template"
-msgstr "Supprimer l'item"
+msgstr "Modèle"
#: editor/script_create_dialog.cpp
-#, fuzzy
msgid "Built-in Script"
msgstr "Script intégré"
#: editor/script_create_dialog.cpp
-#, fuzzy
msgid "Attach Node Script"
-msgstr "Créer le script de nœud"
+msgstr "Attacher script de nœud"
#: editor/script_editor_debugger.cpp
msgid "Bytes:"
@@ -7142,6 +6673,10 @@ msgid "Function:"
msgstr "Fonction :"
#: editor/script_editor_debugger.cpp
+msgid "Pick one or more items from the list to display the graph."
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
msgid "Errors"
msgstr "Erreurs"
@@ -7222,6 +6757,10 @@ msgid "Type"
msgstr "Type"
#: editor/script_editor_debugger.cpp
+msgid "Format"
+msgstr "Format"
+
+#: editor/script_editor_debugger.cpp
msgid "Usage"
msgstr "Utilisation"
@@ -7255,7 +6794,7 @@ msgstr "Changer le rayon d'une lumière"
#: editor/spatial_editor_gizmos.cpp
msgid "Change AudioStreamPlayer3D Emission Angle"
-msgstr ""
+msgstr "Changer l'angle d'émission AudioStreamPlayer3D"
#: editor/spatial_editor_gizmos.cpp
msgid "Change Camera FOV"
@@ -7291,12 +6830,29 @@ msgstr "Changer les extents d'un notificateur"
#: editor/spatial_editor_gizmos.cpp
msgid "Change Particles AABB"
-msgstr ""
+msgstr "Changer particules AABB"
#: editor/spatial_editor_gizmos.cpp
-#, fuzzy
msgid "Change Probe Extents"
-msgstr "Changer les extents d'un notificateur"
+msgstr "Changer les ampleurs de la sonde"
+
+#: modules/gdnative/gd_native_library_editor.cpp
+#, fuzzy
+msgid "Library"
+msgstr "MeshLibrary…"
+
+#: modules/gdnative/gd_native_library_editor.cpp
+#, fuzzy
+msgid "Status"
+msgstr "État :"
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Libraries: "
+msgstr ""
+
+#: modules/gdnative/register_types.cpp
+msgid "GDNative"
+msgstr ""
#: modules/gdscript/gd_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -7304,7 +6860,7 @@ msgid "Invalid type argument to convert(), use TYPE_* constants."
msgstr ""
"Argument de type incorrect dans convert(), utilisez les constantes TYPE_*."
-#: modules/gdscript/gd_functions.cpp
+#: modules/gdscript/gd_functions.cpp modules/mono/glue/glue_header.h
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Not enough bytes for decoding bytes, or invalid format."
msgstr "Pas assez d'octets pour les octets de décodage, ou format non valide."
@@ -7347,133 +6903,112 @@ msgstr ""
#: modules/gdscript/gd_functions.cpp
msgid "Object can't provide a length."
-msgstr ""
+msgstr "L'objet ne peut fournir une longueur."
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "GridMap Delete Selection"
-msgstr "Supprimer la selection"
+msgstr "Sélection de la supression de GridMap"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "GridMap Duplicate Selection"
-msgstr "Dupliquer la sélection"
+msgstr "Sélection de la duplication de GridMap"
#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "GridMap Paint"
-msgstr ""
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Snap View"
-msgstr "Vue de dessus"
+msgstr "Vue instantanée"
#: modules/gridmap/grid_map_editor_plugin.cpp
+#, fuzzy
msgid "Prev Level (%sDown Wheel)"
-msgstr ""
+msgstr "Niveau de prévisualisation ("
#: modules/gridmap/grid_map_editor_plugin.cpp
+#, fuzzy
msgid "Next Level (%sUp Wheel)"
-msgstr ""
+msgstr "Niveau suivant ("
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Clip Disabled"
-msgstr "Désactivé"
+msgstr "Âgrafe désactivée"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Clip Above"
-msgstr ""
+msgstr "Agrafe ci-dessus"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Clip Below"
-msgstr ""
+msgstr "Agrafe ci-dessous"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Edit X Axis"
-msgstr ""
+msgstr "Editer axe X"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Edit Y Axis"
-msgstr ""
+msgstr "Editer axe Y"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Edit Z Axis"
-msgstr ""
+msgstr "Editer axe Z"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Cursor Rotate X"
-msgstr "Contrôle: Tourner"
+msgstr "Rotation de curseur X"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Cursor Rotate Y"
-msgstr "Contrôle: Tourner"
+msgstr "Rotation de curseur Y"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Cursor Rotate Z"
-msgstr "Contrôle: Tourner"
+msgstr "Rotation de curseur Z"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Cursor Back Rotate X"
-msgstr ""
+msgstr "Rotation arrière curseur X"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Cursor Back Rotate Y"
-msgstr ""
+msgstr "Rotation arrière curseur Y"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Cursor Back Rotate Z"
-msgstr ""
+msgstr "Rotation arrière curseur Z"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Cursor Clear Rotation"
-msgstr ""
+msgstr "Effacer rotation curseur"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Create Area"
-msgstr "Créer un nouveau"
+msgstr "Créer zone"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Create Exterior Connector"
-msgstr "Créer un nouveau projet"
+msgstr "Créer connecteur extérieur"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Erase Area"
-msgstr "Supprimer la TileMap"
+msgstr "Effacer zone"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Selection -> Duplicate"
-msgstr "Sélection uniquement"
+msgstr "Sélection -> Dupliquer"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Selection -> Clear"
-msgstr "Sélection uniquement"
+msgstr "Sélection -> Effacer"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "GridMap Settings"
-msgstr "Paramètres d'alignement"
+msgstr "Paramètres GridMap"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Pick Distance:"
-msgstr "Instance :"
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
-msgid "Tiles"
-msgstr "Fichier"
+msgstr "Choisissez distance :"
-#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "Areas"
+#: modules/mono/editor/mono_bottom_panel.cpp
+msgid "Builds"
msgstr ""
#: modules/visual_script/visual_script.cpp
@@ -7515,29 +7050,24 @@ msgid "Stack overflow with stack depth: "
msgstr "Débordement de pile avec profondeur de pile: "
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Change Signal Arguments"
-msgstr "Modifier les arguments du signal :"
+msgstr "Modifier les arguments du signal"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Change Argument Type"
-msgstr "Modifier type de valeur du tableau"
+msgstr "Modifier type d'argument"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Change Argument name"
-msgstr "Changer le nom de l'entrée"
+msgstr "Changer nom d'argument"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Set Variable Default Value"
-msgstr "Changer la valeur par défaut"
+msgstr "Changer valeur de la variable par défaut"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Set Variable Type"
-msgstr "Modifier la variable :"
+msgstr "Définir type de variable"
#: modules/visual_script/visual_script_editor.cpp
msgid "Functions:"
@@ -7588,14 +7118,12 @@ msgid "Add Node"
msgstr "Ajouter un nœud"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Remove VisualScript Nodes"
-msgstr "Supprimer les clés invalides"
+msgstr "Supprimer noeuds VisualScript"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Duplicate VisualScript Nodes"
-msgstr "Dupliquer le(s) nœud(s) de graphe"
+msgstr "Dupliquer noeuds VisualScript"
#: modules/visual_script/visual_script_editor.cpp
msgid "Hold Meta to drop a Getter. Hold Shift to drop a generic signature."
@@ -7642,24 +7170,20 @@ msgid "Add Setter Property"
msgstr "Ajouter une propriété mutateur"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Change Base Type"
-msgstr "Changer le type"
+msgstr "Changer le type de base"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Move Node(s)"
-msgstr "Supprimer le(s) nœud(s)"
+msgstr "Déplacer le(s) nœud(s)"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Remove VisualScript Node"
-msgstr "Supprimer le nœud de graphe Shader"
+msgstr "Supprimer nœud VisualScript"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Connect Nodes"
-msgstr "Connecter au nœud :"
+msgstr "Connecter nœud"
#: modules/visual_script/visual_script_editor.cpp
msgid "Condition"
@@ -7686,46 +7210,48 @@ msgid "Return"
msgstr "Retour"
#: modules/visual_script/visual_script_editor.cpp
+msgid "Call"
+msgstr "Appel"
+
+#: modules/visual_script/visual_script_editor.cpp
msgid "Get"
msgstr "Récupérer"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
+msgid "Script already has function '%s'"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
msgid "Change Input Value"
-msgstr "Changer le nom de l'entrée"
+msgstr "Changer nom de l'entrée"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Can't copy the function node."
-msgstr "Impossible d'opérer sur « .. »"
+msgstr "Impossible de copier le noeud de fonction."
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Clipboard is empty!"
-msgstr "Le presse-papiers des ressources est vide !"
+msgstr "Le presse-papiers est vide !"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Paste VisualScript Nodes"
-msgstr "Coller les nœuds"
+msgstr "Coller les nœuds VisualScript"
#: modules/visual_script/visual_script_editor.cpp
msgid "Remove Function"
msgstr "Supprimer la fonction"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Edit Variable"
-msgstr "Modifier la variable :"
+msgstr "Editerr la variable :"
#: modules/visual_script/visual_script_editor.cpp
msgid "Remove Variable"
msgstr "Supprimer la variable"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Edit Signal"
-msgstr "Modification du signal :"
+msgstr "Editer signal :"
#: modules/visual_script/visual_script_editor.cpp
msgid "Remove Signal"
@@ -7838,28 +7364,24 @@ msgstr ""
"out), ou une chaîne (erreur)."
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Run in Browser"
-msgstr "Parcourir"
+msgstr "Exécuter dans le navigateur"
#: platform/javascript/export/export.cpp
msgid "Run exported HTML in the system's default browser."
-msgstr ""
+msgstr "Exécutez le HTML exporté dans le navigateur par défaut du système."
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Could not write file:\n"
-msgstr "Impossible de trouver la tuile :"
+msgstr "Impossible d'écrire le fichier:\n"
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Could not read file:\n"
-msgstr "Impossible de trouver la tuile :"
+msgstr "Impossible de lire le fichier:\n"
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Could not open template for export:\n"
-msgstr "Impossible de créer le dossier."
+msgstr "Impossible d'ouvrir le modèle pour exportation:\n"
#: scene/2d/animated_sprite.cpp
msgid ""
@@ -7959,6 +7481,8 @@ msgid ""
"A material to process the particles is not assigned, so no behavior is "
"imprinted."
msgstr ""
+"Un matériau de traitement des particules n'est pas assigné, aucun "
+"comportement n'est donc imprimé."
#: scene/2d/path_2d.cpp
msgid "PathFollow2D only works when set as a child of a Path2D node."
@@ -7972,6 +7496,9 @@ msgid ""
"by the physics engine when running.\n"
"Change the size in children collision shapes instead."
msgstr ""
+"Les changements de taille pour RigidBody2D (en mode caractère ou rigide) "
+"seront remplacés par le moteur physique lors de l'exécution. Modifiez la "
+"taille des formes de collision enfants à la place."
#: scene/2d/remote_transform_2d.cpp
msgid "Path property must point to a valid Node2D node to work."
@@ -8005,31 +7532,35 @@ msgstr ""
#: scene/3d/arvr_nodes.cpp
msgid "ARVRCamera must have an ARVROrigin node as its parent"
-msgstr ""
+msgstr "ARVRCamera doit avoir un noeud ARVROrigin comme parent"
#: scene/3d/arvr_nodes.cpp
msgid "ARVRController must have an ARVROrigin node as its parent"
-msgstr ""
+msgstr "ARVRController doit avoir un noeud ARVROrigin comme parent"
#: scene/3d/arvr_nodes.cpp
msgid ""
"The controller id must not be 0 or this controller will not be bound to an "
"actual controller"
msgstr ""
+"L'identifiant contrôleur ne doit pas être 0 ou ce contrôleur ne sera pas lié "
+"à un contrôleur valide"
#: scene/3d/arvr_nodes.cpp
msgid "ARVRAnchor must have an ARVROrigin node as its parent"
-msgstr ""
+msgstr "ARVRAnchor doit avoir un noeud ARVROrigin comme parent"
#: scene/3d/arvr_nodes.cpp
msgid ""
"The anchor id must not be 0 or this anchor will not be bound to an actual "
"anchor"
msgstr ""
+"L'identifiant d'ancrage ne doit pas être 0 ou cette ancre ne sera pas liée à "
+"une ancre valide"
#: scene/3d/arvr_nodes.cpp
msgid "ARVROrigin requires an ARVRCamera child node"
-msgstr ""
+msgstr "ARVROrigin requiert un nœud enfant ARVRCamera"
#: scene/3d/collision_polygon.cpp
msgid ""
@@ -8079,6 +7610,8 @@ msgstr ""
msgid ""
"Nothing is visible because meshes have not been assigned to draw passes."
msgstr ""
+"Rien n'est visible car les maillages n'ont pas été assignés au tirage des "
+"passes."
#: scene/3d/physics_body.cpp
msgid ""
@@ -8086,6 +7619,9 @@ msgid ""
"the physics engine when running.\n"
"Change the size in children collision shapes instead."
msgstr ""
+"Les changements de taille pour RigidBody (dans les modes caractère ou "
+"rigide) seront remplacés par le moteur physique lors de l'exécution. "
+"Modifiez la taille dans les formes de collision enfants à la place."
#: scene/3d/remote_transform.cpp
msgid "Path property must point to a valid Spatial node to work."
@@ -8107,14 +7643,23 @@ msgstr ""
"Une ressource de type SampleFrames doit être créée ou définie dans la "
"propriété « Frames » afin qu'une AnimatedSprite3D fonctionne."
+#: scene/3d/vehicle_body.cpp
+msgid ""
+"VehicleWheel serves to provide a wheel system to a VehicleBody. Please use "
+"it as a child of a VehicleBody."
+msgstr ""
+
#: scene/gui/color_picker.cpp
-#, fuzzy
msgid "Raw Mode"
-msgstr "Mode navigation"
+msgstr "Mode brut"
#: scene/gui/color_picker.cpp
msgid "Add current color as a preset"
-msgstr ""
+msgstr "Ajouter la couleur courante comme pré-réglage"
+
+#: scene/gui/dialogs.cpp
+msgid "Cancel"
+msgstr "Annuler"
#: scene/gui/dialogs.cpp
msgid "Alert!"
@@ -8124,10 +7669,6 @@ msgstr "Alerte !"
msgid "Please Confirm..."
msgstr "Veuillez confirmer…"
-#: scene/gui/input_action.cpp
-msgid "Ctrl+"
-msgstr "Ctrl+"
-
#: scene/gui/popup.cpp
msgid ""
"Popups will hide by default unless you call popup() or any of the popup*() "
@@ -8145,12 +7686,17 @@ msgid ""
"Use a container as child (VBox,HBox,etc), or a Control and set the custom "
"minimum size manually."
msgstr ""
+"ScrollContainer est destiné à fonctionner avec un contrôle enfant unique. "
+"Utilisez un conteneur comme enfant (VBox, HBox, etc.) ou un contrôle et "
+"définissez manuellement la taille minimale personnalisée."
#: scene/main/scene_tree.cpp
msgid ""
"Default Environment as specified in Project Setings (Rendering -> Viewport -"
"> Default Environment) could not be loaded."
msgstr ""
+"L'environnement par défaut spécifié dans les réglages du projet (Rendu -> "
+"Viewport -> Environnement par défaut) ne peut pas être chargé."
#: scene/main/viewport.cpp
msgid ""
@@ -8164,6 +7710,644 @@ msgstr ""
"nœud de type Control afin qu'il en obtienne une taille. Sinon, faites-en une "
"RenderTarget et assignez sa texture à un nœud pouvant l'afficher."
+#: scene/resources/dynamic_font.cpp
+msgid "Error initializing FreeType."
+msgstr "Erreur à l'initialisation de Freetype."
+
+#: scene/resources/dynamic_font.cpp
+msgid "Unknown font format."
+msgstr "Format de police inconnu."
+
+#: scene/resources/dynamic_font.cpp
+msgid "Error loading font."
+msgstr "Erreur lors du chargement de la police."
+
+#: scene/resources/dynamic_font.cpp
+msgid "Invalid font size."
+msgstr "Taille de police invalide."
+
+#~ msgid "Filter:"
+#~ msgstr "Filtre:"
+
+#~ msgid "' parsing of config failed."
+#~ msgstr "L'analyse de la configuration a échoué."
+
+#~ msgid "Theme"
+#~ msgstr "Thème"
+
+#~ msgid "Method List For '%s':"
+#~ msgstr "Liste des méthodes pour « %s » :"
+
+#~ msgid "Arguments:"
+#~ msgstr "Paramètres :"
+
+#~ msgid "Return:"
+#~ msgstr "Retourne :"
+
+#~ msgid "Added:"
+#~ msgstr "Ajouté :"
+
+#~ msgid "Removed:"
+#~ msgstr "Supprimé :"
+
+#~ msgid "Error saving atlas:"
+#~ msgstr "Erreur de sauvegarde de l'atlas :"
+
+#~ msgid "Could not save atlas subtexture:"
+#~ msgstr "Impossible d'enregistrer la sous-texture atlas :"
+
+#~ msgid "Exporting for %s"
+#~ msgstr "Exportation pour %s"
+
+#~ msgid "Setting Up.."
+#~ msgstr "Configuration…"
+
+#~ msgid "Error loading scene."
+#~ msgstr "Erreur lors du chargement de la scène."
+
+#~ msgid "Re-Import"
+#~ msgstr "Ré-importer"
+
+#~ msgid "Please wait for scan to complete."
+#~ msgstr "Veuillez attendre la fin du scan."
+
+#~ msgid "Current scene must be saved to re-import."
+#~ msgstr ""
+#~ "La scène actuelle doit être enregistrée afin de pouvoir ré-importer."
+
+#~ msgid "Save & Re-Import"
+#~ msgstr "Enregistrer et ré-importer"
+
+#~ msgid "Re-Importing"
+#~ msgstr "Ré-importation"
+
+#~ msgid "Re-Import Changed Resources"
+#~ msgstr "Ré-importer les ressources modifiées"
+
+#~ msgid "Loading Export Templates"
+#~ msgstr "Chargement des modèles d'exportation"
+
+#~ msgid ""
+#~ "\n"
+#~ "Status: Needs Re-Import"
+#~ msgstr ""
+#~ "\n"
+#~ "Statut: Réimportation nécessaire"
+
+#~ msgid "Same source and destination files, doing nothing."
+#~ msgstr "Fichiers source et destination identiques, rien à faire."
+
+#~ msgid "Target file exists, can't overwrite. Delete first."
+#~ msgstr ""
+#~ "Le fichier cible existe et ne peut être réécrit. Supprimez le d'abord."
+
+#~ msgid "Same source and destination paths, doing nothing."
+#~ msgstr "Chemins source et destination identiques, rien à faire."
+
+#~ msgid "Can't move directories to within themselves."
+#~ msgstr "Impossible de déplacer des répertoires vers eux-mêmes."
+
+#~ msgid "Can't rename deps for:\n"
+#~ msgstr "Impossible de renommer dependances pour :\n"
+
+#~ msgid "Error moving file:\n"
+#~ msgstr "Erreur lors du déplacement de fichier :\n"
+
+#~ msgid "Pick New Name and Location For:"
+#~ msgstr "Entrez un nouveau nom et chemin pour :"
+
+#~ msgid "No files selected!"
+#~ msgstr "Pas de fichiers sélectionnés !"
+
+#~ msgid "Info"
+#~ msgstr "Information"
+
+#~ msgid "Re-Import.."
+#~ msgstr "Ré-importer…"
+
+#~ msgid "No bit masks to import!"
+#~ msgstr "Pas de masques de bits à importer !"
+
+#~ msgid "Target path is empty."
+#~ msgstr "Le chemin de destination est vide."
+
+#~ msgid "Target path must be a complete resource path."
+#~ msgstr ""
+#~ "Le chemin de destination doit être un chemin complet vers une ressource."
+
+#~ msgid "Target path must exist."
+#~ msgstr "Le chemin de destination doit exister."
+
+#~ msgid "Save path is empty!"
+#~ msgstr "Le chemin de sauvegarde est vide !"
+
+#~ msgid "Import BitMasks"
+#~ msgstr "Importer des BitMasks"
+
+#~ msgid "Source Texture(s):"
+#~ msgstr "Texture(s) source :"
+
+#~ msgid "Target Path:"
+#~ msgstr "Chemin de destination :"
+
+#~ msgid "Accept"
+#~ msgstr "Accepter"
+
+#~ msgid "Bit Mask"
+#~ msgstr "Masque de bits"
+
+#~ msgid "No source font file!"
+#~ msgstr "Pas de fichier de police source !"
+
+#~ msgid "No target font resource!"
+#~ msgstr "Pas de ressource de police de destination !"
+
+#~ msgid ""
+#~ "Invalid file extension.\n"
+#~ "Please use .font."
+#~ msgstr ""
+#~ "Extension de fichier invalide.\n"
+#~ "Veuillez utiliser .font."
+
+#~ msgid "Couldn't save font."
+#~ msgstr "Impossible d'enregistrer la police."
+
+#~ msgid "Source Font:"
+#~ msgstr "Police source :"
+
+#~ msgid "Source Font Size:"
+#~ msgstr "Taille de la police source :"
+
+#~ msgid "Dest Resource:"
+#~ msgstr "Ressource de destination :"
+
+#~ msgid "The quick brown fox jumps over the lazy dog."
+#~ msgstr "Voix ambiguë d'un cœur qui, au zéphyr, préfère les jattes de kiwis."
+
+#~ msgid "Test:"
+#~ msgstr "Test :"
+
+#~ msgid "Options:"
+#~ msgstr "Options :"
+
+#~ msgid "Font Import"
+#~ msgstr "Importation d'une police"
+
+#~ msgid ""
+#~ "This file is already a Godot font file, please supply a BMFont type file "
+#~ "instead."
+#~ msgstr ""
+#~ "Ce fichier est déjà un fichier de police Godot, veuillez fournir un "
+#~ "fichier de type BMFont à la place."
+
+#~ msgid "Failed opening as BMFont file."
+#~ msgstr "Impossible d'ouvrir le fichier en tant que fichier BMFont."
+
+#~ msgid "Invalid font custom source."
+#~ msgstr "Source personnalisée de police invalide."
+
+#~ msgid "No meshes to import!"
+#~ msgstr "Pas de maillages à importer !"
+
+#~ msgid "Single Mesh Import"
+#~ msgstr "Importer un maillage"
+
+#~ msgid "Source Mesh(es):"
+#~ msgstr "Maillage(s) source :"
+
+#~ msgid "Surface %d"
+#~ msgstr "Surface %d"
+
+#~ msgid "No samples to import!"
+#~ msgstr "Pas d'échantillons à importer !"
+
+#~ msgid "Import Audio Samples"
+#~ msgstr "Importer des échantillons audio"
+
+#~ msgid "Source Sample(s):"
+#~ msgstr "Échantillon(s) source :"
+
+#~ msgid "Audio Sample"
+#~ msgstr "Échantillon audio"
+
+#~ msgid "New Clip"
+#~ msgstr "Nouvelle séquence"
+
+#~ msgid "Flags"
+#~ msgstr "Drapeaux"
+
+#~ msgid "Bake FPS:"
+#~ msgstr "FPS de calcul :"
+
+#~ msgid "Optimizer"
+#~ msgstr "Optimiseur"
+
+#~ msgid "Max Linear Error"
+#~ msgstr "Erreur linéaire maximale"
+
+#~ msgid "Max Angular Error"
+#~ msgstr "Erreur angulaire maximale"
+
+#~ msgid "Max Angle"
+#~ msgstr "Angle maximal"
+
+#~ msgid "Clips"
+#~ msgstr "Séquences"
+
+#~ msgid "Start(s)"
+#~ msgstr "Départ(s)"
+
+#~ msgid "End(s)"
+#~ msgstr "Fin(s)"
+
+#~ msgid "Filters"
+#~ msgstr "Filtres"
+
+#~ msgid "Source path is empty."
+#~ msgstr "Le chemin source est vide."
+
+#~ msgid "Couldn't load post-import script."
+#~ msgstr "Impossible de charger le script de post-importation."
+
+#~ msgid "Invalid/broken script for post-import."
+#~ msgstr "Script invalide ou cassé de post-importation."
+
+#~ msgid "Error importing scene."
+#~ msgstr "Erreur à l'importation de la scène."
+
+#~ msgid "Import 3D Scene"
+#~ msgstr "Importer une scène 3D"
+
+#~ msgid "Source Scene:"
+#~ msgstr "Scène source :"
+
+#~ msgid "Same as Target Scene"
+#~ msgstr "Identique à la scène de destination"
+
+#~ msgid "Shared"
+#~ msgstr "Partagé"
+
+#~ msgid "Target Texture Folder:"
+#~ msgstr "Dossier de destination des textures :"
+
+#~ msgid "Post-Process Script:"
+#~ msgstr "Script de post-traitement :"
+
+#~ msgid "Custom Root Node Type:"
+#~ msgstr "Type de nœud racine personnalisé :"
+
+#~ msgid "Auto"
+#~ msgstr "Auto."
+
+#~ msgid "Root Node Name:"
+#~ msgstr "Nom de nœud racine :"
+
+#~ msgid "The Following Files are Missing:"
+#~ msgstr "Les fichiers suivants sont manquants :"
+
+#~ msgid "Import Anyway"
+#~ msgstr "Importer quand même"
+
+#~ msgid "Import & Open"
+#~ msgstr "Importer et ouvrir"
+
+#~ msgid "Edited scene has not been saved, open imported scene anyway?"
+#~ msgstr ""
+#~ "La scène modifiée actuellement n'a pas été enregistrée, ouvrir la scène "
+#~ "importée quand même ?"
+
+#~ msgid "Import Image:"
+#~ msgstr "Importer une image :"
+
+#~ msgid "Couldn't localize path: %s (already local)"
+#~ msgstr "Impossible de rendre le chemin local : %s (déjà local)"
+
+#~ msgid "3D Scene Animation"
+#~ msgstr "Animation de scène 3D"
+
+#~ msgid "Uncompressed"
+#~ msgstr "Non compressé"
+
+#~ msgid "Compress Lossless (PNG)"
+#~ msgstr "Compression sans perte (PNG)"
+
+#~ msgid "Compress Lossy (WebP)"
+#~ msgstr "Compression avec perte (WebP)"
+
+#~ msgid "Compress (VRAM)"
+#~ msgstr "Compression GPU (VRAM)"
+
+#~ msgid "Texture Format"
+#~ msgstr "Format de texture"
+
+#~ msgid "Texture Compression Quality (WebP):"
+#~ msgstr "Qualité de compression de la texture (WebP) :"
+
+#~ msgid "Texture Options"
+#~ msgstr "Options de texture"
+
+#~ msgid "Please specify some files!"
+#~ msgstr "Veuillez spécifier des fichiers !"
+
+#~ msgid "At least one file needed for Atlas."
+#~ msgstr "Il faut au moins un fichier pour créer un atlas."
+
+#~ msgid "Error importing:"
+#~ msgstr "Erreur d'importation :"
+
+#~ msgid "Only one file is required for large texture."
+#~ msgstr "Un seul fichier est nécessaire pour créer une grande texture."
+
+#~ msgid "Max Texture Size:"
+#~ msgstr "Taille de texture maximale :"
+
+#~ msgid "Import Textures for Atlas (2D)"
+#~ msgstr "Importer des textures pour un atlas (2D)"
+
+#~ msgid "Cell Size:"
+#~ msgstr "Taille des cellules :"
+
+#~ msgid "Large Texture"
+#~ msgstr "Grande texture"
+
+#~ msgid "Import Large Textures (2D)"
+#~ msgstr "Importer des grandes textures (2D)"
+
+#~ msgid "Source Texture"
+#~ msgstr "Texture source"
+
+#~ msgid "Base Atlas Texture"
+#~ msgstr "Texture d'atlas de base"
+
+#~ msgid "Source Texture(s)"
+#~ msgstr "Texture(s) source"
+
+#~ msgid "Import Textures for 2D"
+#~ msgstr "Importer des textures pour la 2D"
+
+#~ msgid "Import Textures for 3D"
+#~ msgstr "Importer des textures pour la 3D"
+
+#~ msgid "Import Textures"
+#~ msgstr "Importer des textures"
+
+#~ msgid "2D Texture"
+#~ msgstr "Texture 2D"
+
+#~ msgid "3D Texture"
+#~ msgstr "Texture 3D"
+
+#~ msgid "Atlas Texture"
+#~ msgstr "Texture atlas"
+
+#~ msgid ""
+#~ "NOTICE: Importing 2D textures is not mandatory. Just copy png/jpg files "
+#~ "to the project."
+#~ msgstr ""
+#~ "REMARQUE : L'import de textures 2D n'est pas obligatoire. Copiez "
+#~ "directement les fichiers PNG ou JPEG dans le projet."
+
+#~ msgid "Crop empty space."
+#~ msgstr "Rogner l'espace vide."
+
+#~ msgid "Texture"
+#~ msgstr "Texture"
+
+#~ msgid "Import Large Texture"
+#~ msgstr "Importer une grande texture"
+
+#~ msgid "Load Source Image"
+#~ msgstr "Charger une image source"
+
+#~ msgid "Slicing"
+#~ msgstr "Découpage"
+
+#~ msgid "Saving"
+#~ msgstr "Enregistrement"
+
+#~ msgid "Couldn't save large texture:"
+#~ msgstr "Impossible d'enregistrer la grande texture :"
+
+#~ msgid "Build Atlas For:"
+#~ msgstr "Construire l'atlas pour :"
+
+#~ msgid "Loading Image:"
+#~ msgstr "Chargement de l'image :"
+
+#~ msgid "Couldn't load image:"
+#~ msgstr "Impossible de charger l'image :"
+
+#~ msgid "Converting Images"
+#~ msgstr "Conversion des images"
+
+#~ msgid "Cropping Images"
+#~ msgstr "Rognage des images"
+
+#~ msgid "Blitting Images"
+#~ msgstr "Découpage des images"
+
+#~ msgid "Couldn't save atlas image:"
+#~ msgstr "Impossible d'enregistrer l'image d'atlas :"
+
+#~ msgid "Couldn't save converted texture:"
+#~ msgstr "Impossible d'enregistrer la texture convertie :"
+
+#~ msgid "Invalid source!"
+#~ msgstr "Source invalide !"
+
+#~ msgid "Invalid translation source!"
+#~ msgstr "Source de traduction invalide !"
+
+#~ msgid "Column"
+#~ msgstr "Colonne"
+
+#~ msgid "No items to import!"
+#~ msgstr "Pas d'objets à importer !"
+
+#~ msgid "No target path!"
+#~ msgstr "Pas de chemin de destination !"
+
+#~ msgid "Import Translations"
+#~ msgstr "Importer des traductions"
+
+#~ msgid "Couldn't import!"
+#~ msgstr "Impossible d'importer !"
+
+#~ msgid "Import Translation"
+#~ msgstr "Importer une traduction"
+
+#~ msgid "Source CSV:"
+#~ msgstr "CSV source :"
+
+#~ msgid "Ignore First Row"
+#~ msgstr "Ignorer la première ligne"
+
+#~ msgid "Compress"
+#~ msgstr "Compresser"
+
+#~ msgid "Add to Project (project.godot)"
+#~ msgstr "Ajouter au projet (project.godot)"
+
+#~ msgid "Import Languages:"
+#~ msgstr "Importer les langues :"
+
+#~ msgid "Translation"
+#~ msgstr "Traduction"
+
+#~ msgid "Parsing %d Triangles:"
+#~ msgstr "Analyse de %d triangles :"
+
+#~ msgid "Triangle #"
+#~ msgstr "Triangle #"
+
+#~ msgid "Light Baker Setup:"
+#~ msgstr "Paramètres du calculateur d'éclairage :"
+
+#~ msgid "Fixing Lights"
+#~ msgstr "Correction des lumières"
+
+#~ msgid "Making BVH"
+#~ msgstr "Création du BVH"
+
+#~ msgid "Transfer to Lightmaps:"
+#~ msgstr "Transfert vers des lightmaps :"
+
+#~ msgid "Allocating Texture #"
+#~ msgstr "Allocation de la texture #"
+
+#~ msgid "Baking Triangle #"
+#~ msgstr "Calcul de la texture #"
+
+#~ msgid "Post-Processing Texture #"
+#~ msgstr "Post-traitement de la texture #"
+
+#~ msgid "Reset the lightmap octree baking process (start over)."
+#~ msgstr ""
+#~ "Remettre le processus de calcul de l'éclairage à zéro (recommencer)."
+
+#~ msgid "Zoom (%):"
+#~ msgstr "Zoom (%) :"
+
+#~ msgid "Skeleton.."
+#~ msgstr "Squelette…"
+
+#~ msgid "Zoom Reset"
+#~ msgstr "Réinitialiser le zoom"
+
+#~ msgid "Zoom Set.."
+#~ msgstr "Définir le zoom…"
+
+#~ msgid "Set a Value"
+#~ msgstr "Définir une valeur"
+
+#~ msgid "Snap (Pixels):"
+#~ msgstr "Aligner (pixels) :"
+
+#~ msgid "Parse BBCode"
+#~ msgstr "Analyser le BBCode"
+
+#~ msgid "Length:"
+#~ msgstr "Longueur :"
+
+#~ msgid "Open Sample File(s)"
+#~ msgstr "Ouvrir un ou des fichiers d'échantillons"
+
+#~ msgid "ERROR: Couldn't load sample!"
+#~ msgstr "ERREUR : Impossible de charger l'échantillon !"
+
+#~ msgid "Add Sample"
+#~ msgstr "Ajouter un échantillon"
+
+#~ msgid "Rename Sample"
+#~ msgstr "Renommer l'échantillon"
+
+#~ msgid "Delete Sample"
+#~ msgstr "Supprimer l'échantillon"
+
+#~ msgid "16 Bits"
+#~ msgstr "16 bits"
+
+#~ msgid "8 Bits"
+#~ msgstr "8 bits"
+
+#~ msgid "Stereo"
+#~ msgstr "Stéréo"
+
+#~ msgid "Mono"
+#~ msgstr "Mono"
+
+#~ msgid "Pitch"
+#~ msgstr "Hauteur"
+
+#~ msgid "Window"
+#~ msgstr "Fenêtre"
+
+#~ msgid "Move Right"
+#~ msgstr "Aller à droite"
+
+#~ msgid "Scaling to %s%%."
+#~ msgstr "Mise à l'échelle %s%%."
+
+#~ msgid "Up"
+#~ msgstr "Haut"
+
+#~ msgid "Down"
+#~ msgstr "Bas"
+
+#~ msgid "Bucket"
+#~ msgstr "Seau"
+
+#~ msgid "Invalid project path, the path must exist!"
+#~ msgstr "Chemin de projet invalide, le chemin doit exister !"
+
+#~ msgid "Invalid project path, project.godot must not exist."
+#~ msgstr "Chemin de projet invalide, project.godot ne doit pas exister."
+
+#~ msgid "Invalid project path, project.godot must exist."
+#~ msgstr "Chemin de projet invalide, project.godot doit exister."
+
+#~ msgid "Project Path (Must Exist):"
+#~ msgstr "Chemin du projet (doit exister) :"
+
+#~ msgid "Create New Resource"
+#~ msgstr "Créer une nouvelle ressource"
+
+#~ msgid "Open Resource"
+#~ msgstr "Ouvrir la ressource"
+
+#~ msgid "Save Resource"
+#~ msgstr "Enregistrer la ressource"
+
+#~ msgid "Resource Tools"
+#~ msgstr "Outils des ressources"
+
+#~ msgid "Make Local"
+#~ msgstr "Rendre local"
+
+#~ msgid "Edit Groups"
+#~ msgstr "Modifier les groupes"
+
+#~ msgid "Edit Connections"
+#~ msgstr "Modifier les connexions"
+
+#~ msgid "GridMap Paint"
+#~ msgstr "Peinture de GridMap"
+
+#~ msgid "Tiles"
+#~ msgstr "Tuiles"
+
+#~ msgid "Areas"
+#~ msgstr "Aires"
+
+#~ msgid "Ctrl+"
+#~ msgstr "Ctrl+"
+
+#~ msgid "Down Wheel)"
+#~ msgstr "Roue descendante)"
+
+#~ msgid "Up Wheel)"
+#~ msgstr "Roue ascendante)"
+
#~ msgid "Close scene? (Unsaved changes will be lost)"
#~ msgstr ""
#~ "Fermer la scène ? (les modifications non sauvegardées seront perdues)"
@@ -8178,9 +8362,6 @@ msgstr ""
#~ msgid "Close Goto Prev. Scene"
#~ msgstr "Fermer, aller à la scène précédente"
-#~ msgid "Expand to Parent"
-#~ msgstr "Étendre au parent"
-
#~ msgid "Del"
#~ msgstr "Supprimer"
@@ -8355,18 +8536,12 @@ msgstr ""
#~ msgid "Save Translatable Strings"
#~ msgstr "Enregistrer les chaînes traduisibles"
-#~ msgid "Translatable Strings.."
-#~ msgstr "Chaînes traduisibles…"
-
#~ msgid "Install Export Templates"
#~ msgstr "Installer les modèles d'exportation"
#~ msgid "Edit Script Options"
#~ msgstr "Modifier les options du script"
-#~ msgid "Please export outside the project folder!"
-#~ msgstr "Veuillez exporter en dehors du dossier du projet !"
-
#~ msgid "Error exporting project!"
#~ msgstr "Erreur d'exportation du projet !"
@@ -8416,18 +8591,12 @@ msgstr ""
#~ msgid "Include"
#~ msgstr "Inclure"
-#~ msgid "Change Image Group"
-#~ msgstr "Changer le groupe d'images"
-
#~ msgid "Group name can't be empty!"
#~ msgstr "Le nom du groupe ne peut pas être vide !"
#~ msgid "Invalid character in group name!"
#~ msgstr "Caractère invalide dans le nom du groupe !"
-#~ msgid "Group name already exists!"
-#~ msgstr "Le nom du groupe existe déjà !"
-
#~ msgid "Add Image Group"
#~ msgstr "Ajouter un groupe d'images"
@@ -8507,9 +8676,6 @@ msgstr ""
#~ msgid "Preview Atlas"
#~ msgstr "Aperçu de l'atlas"
-#~ msgid "Image Filter:"
-#~ msgstr "Filtre d'image :"
-
#~ msgid "Images:"
#~ msgstr "Images :"
@@ -8576,9 +8742,6 @@ msgstr ""
#~ msgid "Lighting"
#~ msgstr "Éclairage"
-#~ msgid "Toggle Persisting"
-#~ msgstr "Mode persistant"
-
#~ msgid "Global"
#~ msgstr "Global"
diff --git a/editor/translations/hu.po b/editor/translations/hu.po
index a8681feaf5..07457b4692 100644
--- a/editor/translations/hu.po
+++ b/editor/translations/hu.po
@@ -1,5 +1,6 @@
# Hungarian translation of the Godot Engine editor
-# Copyright (C) 2016-2017 Juan Linietsky, Ariel Manzur and the Godot community
+# Copyright (C) 2007-2017 Juan Linietsky, Ariel Manzur
+# Copyright (C) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)
# This file is distributed under the same license as the Godot source code.
#
# Varga Dániel <danikah.danikah@gmail.com>, 2016.
@@ -191,10 +192,9 @@ msgid "Create %d NEW tracks and insert keys?"
msgstr ""
#: editor/animation_editor.cpp editor/create_dialog.cpp
-#: editor/editor_audio_buses.cpp
+#: editor/editor_audio_buses.cpp editor/plugins/abstract_polygon_2d_editor.cpp
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
#: editor/plugins/mesh_instance_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp editor/project_manager.cpp
#: editor/script_create_dialog.cpp
msgid "Create"
@@ -356,261 +356,6 @@ msgstr ""
msgid "Change Array Value"
msgstr ""
-#: editor/asset_library_editor_plugin.cpp
-msgid "Free"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_plugin_settings.cpp
-msgid "Version:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Contents:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "View Files"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_help.cpp editor/property_selector.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Description:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-#: editor/project_manager.cpp
-msgid "Install"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/call_dialog.cpp
-#: editor/connections_dialog.cpp editor/export_template_manager.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-#: editor/project_settings_editor.cpp editor/property_editor.cpp
-#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Close"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve hostname:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Connection error, please try again."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't connect."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't connect to host:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response from host:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Request failed, return code:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Req. Failed."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Request failed, too many redirects"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Redirect Loop."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Bad download hash, assuming file has been tampered with."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Expected:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Got:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Asset Download Error:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-msgid "Success!"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Fetching:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Resolving.."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Connecting.."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Requesting.."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Error making request"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Idle"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Retry"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Download Error"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Download for this asset is already in progress!"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "first"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "prev"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "next"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "last"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "All"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
-#: editor/settings_config_dialog.cpp
-msgid "Search:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/code_editor.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Search"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/project_manager.cpp
-msgid "Import"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Plugins"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Sort:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Reverse"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Category:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Site:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Support.."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Official"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-msgid "Community"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Testing"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Assets ZIP File"
-msgstr ""
-
-#: editor/call_dialog.cpp
-msgid "Method List For '%s':"
-msgstr ""
-
-#: editor/call_dialog.cpp modules/visual_script/visual_script_editor.cpp
-msgid "Call"
-msgstr ""
-
-#: editor/call_dialog.cpp
-msgid "Method List:"
-msgstr ""
-
-#: editor/call_dialog.cpp
-msgid "Arguments:"
-msgstr ""
-
-#: editor/call_dialog.cpp
-msgid "Return:"
-msgstr ""
-
#: editor/code_editor.cpp
msgid "Go to Line"
msgstr ""
@@ -647,6 +392,14 @@ msgstr ""
msgid "Selection Only"
msgstr ""
+#: editor/code_editor.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
+msgid "Search"
+msgstr ""
+
#: editor/code_editor.cpp editor/editor_help.cpp
msgid "Find"
msgstr ""
@@ -679,11 +432,11 @@ msgstr ""
msgid "Skip"
msgstr ""
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom In"
msgstr ""
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom Out"
msgstr ""
@@ -750,6 +503,20 @@ msgstr ""
msgid "Oneshot"
msgstr ""
+#: editor/connections_dialog.cpp editor/dependency_editor.cpp
+#: editor/export_template_manager.cpp
+#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Close"
+msgstr ""
+
#: editor/connections_dialog.cpp
msgid "Connect"
msgstr ""
@@ -775,7 +542,7 @@ msgstr ""
msgid "Disconnect"
msgstr ""
-#: editor/connections_dialog.cpp editor/node_dock.cpp
+#: editor/connections_dialog.cpp editor/editor_help.cpp editor/node_dock.cpp
msgid "Signals"
msgstr ""
@@ -792,12 +559,25 @@ msgstr ""
msgid "Recent:"
msgstr ""
+#: editor/create_dialog.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/quick_open.cpp editor/settings_config_dialog.cpp
+msgid "Search:"
+msgstr ""
+
#: editor/create_dialog.cpp editor/editor_help.cpp
#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/quick_open.cpp
msgid "Matches:"
msgstr ""
+#: editor/create_dialog.cpp editor/editor_help.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/property_selector.cpp
+#: editor/script_editor_debugger.cpp
+msgid "Description:"
+msgstr ""
+
#: editor/dependency_editor.cpp
msgid "Search Replacement For:"
msgstr ""
@@ -853,6 +633,10 @@ msgid "Owners Of:"
msgstr ""
#: editor/dependency_editor.cpp
+msgid "Remove selected files from the project? (no undo)"
+msgstr ""
+
+#: editor/dependency_editor.cpp
msgid ""
"The files being removed are required by other resources in order for them to "
"work.\n"
@@ -860,7 +644,7 @@ msgid ""
msgstr ""
#: editor/dependency_editor.cpp
-msgid "Remove selected files from the project? (no undo)"
+msgid "Cannot remove:\n"
msgstr ""
#: editor/dependency_editor.cpp
@@ -927,10 +711,6 @@ msgid "Godot Engine contributors"
msgstr ""
#: editor/editor_about.cpp
-msgid "Authors"
-msgstr ""
-
-#: editor/editor_about.cpp
msgid "Project Founders"
msgstr ""
@@ -947,6 +727,38 @@ msgid "Developers"
msgstr ""
#: editor/editor_about.cpp
+msgid "Authors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Platinum Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Gold Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Mini Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Gold Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Silver Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Bronze Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
msgid "License"
msgstr ""
@@ -987,6 +799,16 @@ msgid "Package Installed Successfully!"
msgstr ""
#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Success!"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/project_manager.cpp
+msgid "Install"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
msgid "Package Installer"
msgstr ""
@@ -1035,10 +857,6 @@ msgid "Audio Bus, Drag and Drop to rearrange."
msgstr ""
#: editor/editor_audio_buses.cpp
-msgid "Bus options"
-msgstr ""
-
-#: editor/editor_audio_buses.cpp
msgid "Solo"
msgstr ""
@@ -1050,12 +868,20 @@ msgstr ""
msgid "Bypass"
msgstr ""
+#: editor/editor_audio_buses.cpp
+msgid "Bus options"
+msgstr ""
+
#: editor/editor_audio_buses.cpp editor/plugins/tile_map_editor_plugin.cpp
#: editor/scene_tree_dock.cpp
msgid "Duplicate"
msgstr ""
#: editor/editor_audio_buses.cpp
+msgid "Reset Volume"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
msgid "Delete Effect"
msgstr ""
@@ -1076,6 +902,10 @@ msgid "Duplicate Audio Bus"
msgstr ""
#: editor/editor_audio_buses.cpp
+msgid "Reset Bus Volume"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
msgid "Move Audio Bus"
msgstr ""
@@ -1107,7 +937,8 @@ msgstr ""
msgid "Create a new Bus Layout."
msgstr ""
-#: editor/editor_audio_buses.cpp editor/script_create_dialog.cpp
+#: editor/editor_audio_buses.cpp editor/property_editor.cpp
+#: editor/script_create_dialog.cpp
msgid "Load"
msgstr ""
@@ -1197,7 +1028,7 @@ msgid "Rearrange Autoloads"
msgstr ""
#: editor/editor_autoload_settings.cpp editor/editor_file_dialog.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp scene/gui/file_dialog.cpp
+#: scene/gui/file_dialog.cpp
msgid "Path:"
msgstr ""
@@ -1205,9 +1036,7 @@ msgstr ""
msgid "Node Name:"
msgstr ""
-#: editor/editor_autoload_settings.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp editor/project_manager.cpp
+#: editor/editor_autoload_settings.cpp editor/project_manager.cpp
msgid "Name"
msgstr ""
@@ -1240,18 +1069,19 @@ msgid "Choose a Directory"
msgstr ""
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Create Folder"
msgstr ""
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: editor/editor_plugin_settings.cpp editor/plugins/theme_editor_plugin.cpp
-#: editor/project_export.cpp scene/gui/file_dialog.cpp
+#: editor/editor_plugin_settings.cpp editor/filesystem_dock.cpp
+#: editor/plugins/theme_editor_plugin.cpp editor/project_export.cpp
+#: scene/gui/file_dialog.cpp
msgid "Name:"
msgstr ""
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Could not create folder."
msgstr ""
@@ -1271,30 +1101,6 @@ msgstr ""
msgid "Template file not found:\n"
msgstr ""
-#: editor/editor_export.cpp
-msgid "Added:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Removed:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Error saving atlas:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Could not save atlas subtexture:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Exporting for %s"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Setting Up.."
-msgstr ""
-
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "File Exists, Overwrite?"
msgstr ""
@@ -1379,6 +1185,10 @@ msgstr ""
msgid "Move Favorite Down"
msgstr ""
+#: editor/editor_file_dialog.cpp
+msgid "Go to parent folder"
+msgstr ""
+
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Directories & Files:"
msgstr ""
@@ -1393,10 +1203,6 @@ msgid "File:"
msgstr ""
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
-msgid "Filter:"
-msgstr ""
-
-#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Must use a valid extension."
msgstr ""
@@ -1421,6 +1227,10 @@ msgstr ""
msgid "Search Classes"
msgstr ""
+#: editor/editor_help.cpp editor/plugins/spatial_editor_plugin.cpp
+msgid "Top"
+msgstr ""
+
#: editor/editor_help.cpp editor/property_editor.cpp
msgid "Class:"
msgstr ""
@@ -1437,15 +1247,27 @@ msgstr ""
msgid "Brief Description:"
msgstr ""
+#: editor/editor_help.cpp
+msgid "Members"
+msgstr ""
+
#: editor/editor_help.cpp modules/visual_script/visual_script_editor.cpp
msgid "Members:"
msgstr ""
#: editor/editor_help.cpp
+msgid "Public Methods"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Public Methods:"
msgstr ""
#: editor/editor_help.cpp
+msgid "GUI Theme Items"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "GUI Theme Items:"
msgstr ""
@@ -1454,6 +1276,10 @@ msgid "Signals:"
msgstr ""
#: editor/editor_help.cpp
+msgid "Enumerations"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Enumerations:"
msgstr ""
@@ -1462,18 +1288,46 @@ msgid "enum "
msgstr ""
#: editor/editor_help.cpp
+msgid "Constants"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Constants:"
msgstr ""
#: editor/editor_help.cpp
+msgid "Description"
+msgstr ""
+
+#: editor/editor_help.cpp
+msgid "Properties"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Property Description:"
msgstr ""
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this property. Please help us by "
+"[color=$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+
+#: editor/editor_help.cpp
+msgid "Methods"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Method Description:"
msgstr ""
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this method. Please help us by [color="
+"$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Search Text"
msgstr ""
@@ -1482,24 +1336,21 @@ msgid "Output:"
msgstr ""
#: editor/editor_log.cpp editor/plugins/animation_tree_editor_plugin.cpp
-#: editor/plugins/rich_text_editor_plugin.cpp editor/property_editor.cpp
-#: editor/script_editor_debugger.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/property_editor.cpp editor/script_editor_debugger.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Clear"
msgstr ""
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Error saving resource!"
msgstr ""
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Save Resource As.."
msgstr ""
-#: editor/editor_node.cpp editor/export_template_manager.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "I see.."
msgstr ""
@@ -1516,6 +1367,26 @@ msgid "Error while saving."
msgstr ""
#: editor/editor_node.cpp
+msgid "Can't open '%s'."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Error while parsing '%s'."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Unexpected end of file '%s'."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Missing '%s' or its dependencies."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Error while loading '%s'."
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Saving Scene"
msgstr ""
@@ -1573,6 +1444,33 @@ msgid "Restored default layout to base settings."
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was imported, so it's not editable.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was instanced or inherited.\n"
+"Changes to it will not be kept when saving the current scene."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource was imported, so it's not editable. Change its settings in the "
+"import panel and then re-import."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This scene was imported, so changes to it will not be kept.\n"
+"Instancing it or inheriting will allow making changes to it.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Copy Params"
msgstr ""
@@ -1734,23 +1632,34 @@ msgid "Save changes the following scene(s) before opening Project Manager?"
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"This option is deprecated. Situations where refresh must be forced are now "
+"considered a bug. Please report."
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Pick a Main Scene"
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to enable addon plugin at: '"
+msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
msgstr ""
#: editor/editor_node.cpp
-msgid "' parsing of config failed."
+msgid "Unable to load addon script from path: '%s'."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/"
+msgid ""
+"Unable to load addon script from path: '%s' Base type is not EditorPlugin."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to load addon script from path: '"
+msgid "Unable to load addon script from path: '%s' Script is not in tool mode."
msgstr ""
#: editor/editor_node.cpp
@@ -1760,7 +1669,7 @@ msgid ""
msgstr ""
#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/scene_tree_dock.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Ugh"
msgstr ""
@@ -1771,11 +1680,11 @@ msgid ""
msgstr ""
#: editor/editor_node.cpp
-msgid "Error loading scene."
+msgid "Scene '%s' has broken dependencies:"
msgstr ""
#: editor/editor_node.cpp
-msgid "Scene '%s' has broken dependencies:"
+msgid "Clear Recent Scenes"
msgstr ""
#: editor/editor_node.cpp
@@ -1811,7 +1720,7 @@ msgstr ""
msgid "Toggle distraction-free mode."
msgstr ""
-#: editor/editor_node.cpp editor/io_plugins/editor_scene_import_plugin.cpp
+#: editor/editor_node.cpp
msgid "Scene"
msgstr ""
@@ -2030,6 +1939,10 @@ msgstr ""
msgid "Issue Tracker"
msgstr ""
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+msgid "Community"
+msgstr ""
+
#: editor/editor_node.cpp
msgid "About"
msgstr ""
@@ -2038,7 +1951,7 @@ msgstr ""
msgid "Play the project."
msgstr ""
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Play"
msgstr ""
@@ -2054,7 +1967,7 @@ msgstr ""
msgid "Stop the scene."
msgstr ""
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Stop"
msgstr ""
@@ -2127,6 +2040,15 @@ msgid "Object properties."
msgstr ""
#: editor/editor_node.cpp
+msgid "Changes may be lost!"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Import"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "FileSystem"
msgstr ""
@@ -2142,14 +2064,6 @@ msgstr ""
msgid "Don't Save"
msgstr ""
-#: editor/editor_node.cpp editor/editor_reimport_dialog.cpp
-msgid "Re-Import"
-msgstr ""
-
-#: editor/editor_node.cpp editor/editor_plugin_settings.cpp
-msgid "Update"
-msgstr ""
-
#: editor/editor_node.cpp
msgid "Import Templates From ZIP File"
msgstr ""
@@ -2210,11 +2124,28 @@ msgstr ""
msgid "Open the previous Editor"
msgstr ""
+#: editor/editor_plugin.cpp
+msgid "Creating Mesh Previews"
+msgstr ""
+
+#: editor/editor_plugin.cpp
+msgid "Thumbnail.."
+msgstr ""
+
#: editor/editor_plugin_settings.cpp
msgid "Installed Plugins:"
msgstr ""
#: editor/editor_plugin_settings.cpp
+msgid "Update"
+msgstr ""
+
+#: editor/editor_plugin_settings.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Version:"
+msgstr ""
+
+#: editor/editor_plugin_settings.cpp
msgid "Author:"
msgstr ""
@@ -2247,7 +2178,7 @@ msgid "Frame %"
msgstr ""
#: editor/editor_profiler.cpp
-msgid "Fixed Frame %"
+msgid "Physics Frame %"
msgstr ""
#: editor/editor_profiler.cpp editor/script_editor_debugger.cpp
@@ -2266,26 +2197,6 @@ msgstr ""
msgid "Frame #:"
msgstr ""
-#: editor/editor_reimport_dialog.cpp
-msgid "Please wait for scan to complete."
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Current scene must be saved to re-import."
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Save & Re-Import"
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Importing"
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Import Changed Resources"
-msgstr ""
-
#: editor/editor_run_native.cpp
msgid "Select device from the list"
msgstr ""
@@ -2395,10 +2306,6 @@ msgid "Importing:"
msgstr ""
#: editor/export_template_manager.cpp
-msgid "Loading Export Templates"
-msgstr ""
-
-#: editor/export_template_manager.cpp
msgid "Current Version:"
msgstr ""
@@ -2431,9 +2338,17 @@ msgid "Cannot navigate to '"
msgstr ""
#: editor/filesystem_dock.cpp
+msgid "View items as a grid of thumbnails"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "View items as a list"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
msgid ""
"\n"
-"Status: Needs Re-Import"
+"Status: Import of file failed. Please fix file and reimport manually."
msgstr ""
#: editor/filesystem_dock.cpp
@@ -2443,87 +2358,87 @@ msgid ""
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Same source and destination files, doing nothing."
+msgid "Cannot move/rename resources root."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Target file exists, can't overwrite. Delete first."
+msgid "Cannot move a folder into itself.\n"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Same source and destination paths, doing nothing."
+msgid "Error moving:\n"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Can't move directories to within themselves."
+msgid "Unable to update dependencies:\n"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Can't rename deps for:\n"
+msgid "No name provided"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Error moving file:\n"
+msgid "Provided name contains invalid characters"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Error moving dir:\n"
+msgid "No name provided."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Can't operate on '..'"
+msgid "Name contains invalid characters."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Pick New Name and Location For:"
+msgid "A file or folder with this name already exists."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "No files selected!"
+msgid "Renaming file:"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Expand all"
+msgid "Renaming folder:"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Collapse all"
+msgid "Expand all"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Show In File Manager"
+msgid "Collapse all"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Instance"
+msgid "Copy Path"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Edit Dependencies.."
+msgid "Rename.."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "View Owners.."
+msgid "Move To.."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Copy Path"
+msgid "New Folder.."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Rename or Move.."
+msgid "Show In File Manager"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Move To.."
+msgid "Instance"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Info"
+msgid "Edit Dependencies.."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Re-Import.."
+msgid "View Owners.."
msgstr ""
#: editor/filesystem_dock.cpp
@@ -2556,6 +2471,11 @@ msgstr ""
msgid "Move"
msgstr ""
+#: editor/filesystem_dock.cpp editor/plugins/animation_tree_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Rename"
+msgstr ""
+
#: editor/groups_editor.cpp
msgid "Add to Group"
msgstr ""
@@ -2569,6 +2489,10 @@ msgid "Import as Single Scene"
msgstr ""
#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
msgid "Import with Separate Materials"
msgstr ""
@@ -2581,6 +2505,18 @@ msgid "Import with Separate Objects+Materials"
msgstr ""
#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Materials+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Materials+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
msgid "Import as Multiple Scenes"
msgstr ""
@@ -2589,38 +2525,31 @@ msgid "Import as Multiple Scenes+Materials"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Import Scene"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Importing Scene.."
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Running Custom Script.."
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Couldn't load post-import script:"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Invalid/broken script for post-import (check console):"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Error running post-import script:"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Saving.."
msgstr ""
@@ -2648,579 +2577,54 @@ msgstr ""
msgid "Reimport"
msgstr ""
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "No bit masks to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path is empty."
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must be a complete resource path."
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must exist."
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Save path is empty!"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Import BitMasks"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s):"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Target Path:"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Accept"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Bit Mask"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No source font file!"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No target font resource!"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"Invalid file extension.\n"
-"Please use .font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Can't load/process source font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Couldn't save font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font Size:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Dest Resource:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "The quick brown fox jumps over the lazy dog."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Test:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Options:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Font Import"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"This file is already a Godot font file, please supply a BMFont type file "
-"instead."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Failed opening as BMFont file."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error initializing FreeType."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Unknown font format."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error loading font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Invalid font size."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Invalid font custom source."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/plugins/theme_editor_plugin.cpp
-msgid "Font"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "No meshes to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Single Mesh Import"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Source Mesh(es):"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/plugins/mesh_instance_editor_plugin.cpp
-msgid "Mesh"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Surface %d"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "No samples to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Import Audio Samples"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Source Sample(s):"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Audio Sample"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "New Clip"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Animation Options"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Flags"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Bake FPS:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Optimizer"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Linear Error"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angular Error"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angle"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Clips"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Start(s)"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "End(s)"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Loop"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Filters"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source path is empty."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't load post-import script."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Invalid/broken script for post-import."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Error importing scene."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import 3D Scene"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source Scene:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Same as Target Scene"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Shared"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Target Texture Folder:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Post-Process Script:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Custom Root Node Type:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Auto"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Root Node Name:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "The Following Files are Missing:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Anyway"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp scene/gui/dialogs.cpp
-msgid "Cancel"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import & Open"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Edited scene has not been saved, open imported scene anyway?"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Image:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Can't import a file over itself:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't localize path: %s (already local)"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "3D Scene Animation"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Uncompressed"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossless (PNG)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossy (WebP)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress (VRAM)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Format"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Compression Quality (WebP):"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Options"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Please specify some files!"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "At least one file needed for Atlas."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Error importing:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Only one file is required for large texture."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Max Texture Size:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for Atlas (2D)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cell Size:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Large Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Textures (2D)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture"
+#: editor/multi_node_edit.cpp
+msgid "MultiNode Set"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Base Atlas Texture"
+#: editor/node_dock.cpp
+msgid "Groups"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s)"
+#: editor/node_dock.cpp
+msgid "Select a Node to edit Signals and Groups."
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 2D"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create Poly"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 3D"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Insert Point"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "2D Texture"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly (Remove Point)"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "3D Texture"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Remove Poly And Point"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Atlas Texture"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create a new polygon from scratch."
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
+#: editor/plugins/abstract_polygon_2d_editor.cpp
msgid ""
-"NOTICE: Importing 2D textures is not mandatory. Just copy png/jpg files to "
-"the project."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Crop empty space."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Load Source Image"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Slicing"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Inserting"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Saving"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save large texture:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Build Atlas For:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Loading Image:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't load image:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Converting Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cropping Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Blitting Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save atlas image:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save converted texture:"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid source!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid translation source!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Column"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/script_create_dialog.cpp
-msgid "Language"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No items to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No target path!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translations"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Couldn't import!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translation"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Source CSV:"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Ignore First Row"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Compress"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Add to Project (project.godot)"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Languages:"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Translation"
-msgstr ""
-
-#: editor/multi_node_edit.cpp
-msgid "MultiNode Set"
-msgstr ""
-
-#: editor/node_dock.cpp
-msgid "Groups"
-msgstr ""
-
-#: editor/node_dock.cpp
-msgid "Select a Node to edit Signals and Groups."
+"Edit existing polygon:\n"
+"LMB: Move Point.\n"
+"Ctrl+LMB: Split Segment.\n"
+"RMB: Erase Point."
msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
@@ -3376,7 +2780,6 @@ msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
#: editor/script_create_dialog.cpp
msgid "Error!"
@@ -3486,10 +2889,6 @@ msgid "Delete Input"
msgstr ""
#: editor/plugins/animation_tree_editor_plugin.cpp
-msgid "Rename"
-msgstr ""
-
-#: editor/plugins/animation_tree_editor_plugin.cpp
msgid "Animation tree is valid."
msgstr ""
@@ -3545,64 +2944,181 @@ msgstr ""
msgid "Filters.."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing %d Triangles:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Free"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Contents:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "View Files"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Triangle #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve hostname:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Light Baker Setup:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing Geometry"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connection error, please try again."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Fixing Lights"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't connect."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Making BVH"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't connect to host:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Light Octree"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response from host:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Octree Texture"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Transfer to Lightmaps:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, return code:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Allocating Texture #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Req. Failed."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Baking Triangle #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, too many redirects"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Post-Processing Texture #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Redirect Loop."
msgstr ""
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Bake!"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Bad download hash, assuming file has been tampered with."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Expected:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Got:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed sha256 hash check"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Asset Download Error:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Fetching:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Resolving.."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connecting.."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Requesting.."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Error making request"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Idle"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Retry"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download Error"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download for this asset is already in progress!"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "first"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "prev"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "next"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "last"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "All"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Plugins"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Sort:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Reverse"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Category:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Site:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Support.."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Official"
msgstr ""
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Reset the lightmap octree baking process (start over)."
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Testing"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Assets ZIP File"
msgstr ""
#: editor/plugins/camera_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
msgid "Preview"
msgstr ""
@@ -3645,11 +3161,15 @@ msgid "Edit CanvasItem"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Change Anchors"
+msgid "Anchors only"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom (%):"
+msgid "Change Anchors and Margins"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Change Anchors"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3700,59 +3220,72 @@ msgid "Pan Mode"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Lock the selected object in place (can't be moved)."
+msgid "Toggles snapping"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Unlock the selected object (can be moved)."
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Use Snap"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Makes sure the object's children are not selectable."
+msgid "Snapping options"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Restores the object's children's ability to be selected."
+msgid "Snap to grid"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Edit"
+msgid "Use Rotation Snap"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Use Snap"
+msgid "Configure Snap..."
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Show Grid"
+msgid "Snap Relative"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Rotation Snap"
+msgid "Use Pixel Snap"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap Relative"
+msgid "Smart snapping"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Configure Snap.."
+msgid "Snap to parent"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Pixel Snap"
+msgid "Snap to node anchor"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to node sides"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to other nodes"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Lock the selected object in place (can't be moved)."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Unlock the selected object (can be moved)."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Makes sure the object's children are not selectable."
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Skeleton.."
+msgid "Restores the object's children's ability to be selected."
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3781,11 +3314,16 @@ msgid "View"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Reset"
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Show Grid"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Show helpers"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Set.."
+msgid "Show rulers"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3797,7 +3335,7 @@ msgid "Frame Selection"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Anchor"
+msgid "Layout"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3821,11 +3359,19 @@ msgid "Clear Pose"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Set a Value"
+msgid "Drag pivot from mouse position"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Set pivot at mouse position"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap (Pixels):"
+msgid "Multiply grid step by 2"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Divide grid step by 2"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3836,23 +3382,28 @@ msgstr ""
msgid "Adding %s..."
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Create Node"
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Error instancing scene from %s"
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "OK :("
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "No parent to instance a child at."
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "This operation requires a single selected node."
msgstr ""
@@ -3866,45 +3417,6 @@ msgid ""
"Drag & drop + Alt : Change node type"
msgstr ""
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Create Poly"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly (Remove Point)"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Create a new polygon from scratch."
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-msgid ""
-"Edit existing polygon:\n"
-"LMB: Move Point.\n"
-"Ctrl+LMB: Split Segment.\n"
-"RMB: Erase Point."
-msgstr ""
-
#: editor/plugins/collision_polygon_editor_plugin.cpp
msgid "Create Poly3D"
msgstr ""
@@ -3914,14 +3426,6 @@ msgid "Set Handle"
msgstr ""
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Creating Mesh Library"
-msgstr ""
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Thumbnail.."
-msgstr ""
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Remove item %d?"
msgstr ""
@@ -3944,6 +3448,26 @@ msgid "Update from Scene"
msgstr ""
#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat0"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat1"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Ease in"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Ease out"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Smoothstep"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
msgid "Modify Curve Point"
msgstr ""
@@ -4019,22 +3543,18 @@ msgid "Create Occluder Polygon"
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Edit existing polygon:"
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "LMB: Move Point."
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Ctrl+LMB: Split Segment."
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "RMB: Erase Point."
msgstr ""
@@ -4135,6 +3655,10 @@ msgid "Create Outline"
msgstr ""
#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Mesh"
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Create Trimesh Static Body"
msgstr ""
@@ -4262,12 +3786,72 @@ msgstr ""
msgid "Populate"
msgstr ""
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Create Navigation Polygon"
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake!"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake the navigation mesh.\n"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Clear the navigation mesh."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Setting up Configuration..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Calculating grid size..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating heightfield..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Marking walkable triangles..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Constructing compact heightfield..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Eroding walkable area..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Partitioning..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating contours..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating polymesh..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Converting to native navigation mesh..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Navigation Mesh Generator Setup:"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Parsing Geometry..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Done!"
msgstr ""
#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Remove Poly And Point"
+msgid "Create Navigation Polygon"
msgstr ""
#: editor/plugins/particles_2d_editor_plugin.cpp
@@ -4509,6 +4093,14 @@ msgid "Scale Polygon"
msgstr ""
#: editor/plugins/polygon_2d_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Edit"
+msgstr ""
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Polygon->UV"
msgstr ""
@@ -4563,63 +4155,10 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/shader_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr ""
-#: editor/plugins/rich_text_editor_plugin.cpp
-msgid "Parse BBCode"
-msgstr ""
-
-#: editor/plugins/sample_editor_plugin.cpp
-msgid "Length:"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Open Sample File(s)"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "ERROR: Couldn't load sample!"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Add Sample"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Rename Sample"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Delete Sample"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "16 Bits"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "8 Bits"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Stereo"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Mono"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Format"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Pitch"
-msgstr ""
-
#: editor/plugins/script_editor_plugin.cpp
msgid "Clear Recent Files"
msgstr ""
@@ -4710,6 +4249,10 @@ msgstr ""
msgid "Close All"
msgstr ""
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+msgid "Run"
+msgstr ""
+
#: editor/plugins/script_editor_plugin.cpp
msgid "Toggle Scripts Panel"
msgstr ""
@@ -4738,7 +4281,8 @@ msgstr ""
msgid "Break"
msgstr ""
-#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+#: editor/script_editor_debugger.cpp
msgid "Continue"
msgstr ""
@@ -4751,18 +4295,6 @@ msgid "Debug with external editor"
msgstr ""
#: editor/plugins/script_editor_plugin.cpp
-msgid "Window"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Left"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Right"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
msgid "Open Godot online documentation"
msgstr ""
@@ -4844,8 +4376,9 @@ msgid "Cut"
msgstr ""
#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr ""
@@ -5108,10 +4641,6 @@ msgid "View Plane Transform."
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Scaling to %s%%."
-msgstr ""
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rotating %s degrees."
msgstr ""
@@ -5128,10 +4657,6 @@ msgid "Top View."
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Top"
-msgstr ""
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rear View."
msgstr ""
@@ -5359,6 +4884,10 @@ msgid "Transform"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Configure Snap.."
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Local Coords"
msgstr ""
@@ -5504,6 +5033,10 @@ msgid "Speed (FPS):"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Loop"
+msgstr ""
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Animation Frames"
msgstr ""
@@ -5516,11 +5049,11 @@ msgid "Insert Empty (After)"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Up"
+msgid "Move (Before)"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Down"
+msgid "Move (After)"
msgstr ""
#: editor/plugins/style_box_editor_plugin.cpp
@@ -5597,7 +5130,11 @@ msgid "Remove All"
msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
-msgid "Theme"
+msgid "Edit theme.."
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Theme editing menu."
msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
@@ -5682,6 +5219,10 @@ msgid "Style"
msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
+msgid "Font"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
msgid "Color"
msgstr ""
@@ -5730,7 +5271,7 @@ msgid "Mirror Y"
msgstr ""
#: editor/plugins/tile_map_editor_plugin.cpp
-msgid "Bucket"
+msgid "Paint Tile"
msgstr ""
#: editor/plugins/tile_map_editor_plugin.cpp
@@ -5794,6 +5335,10 @@ msgid "Delete preset '%s'?"
msgstr ""
#: editor/project_export.cpp
+msgid "Export templates for this platform are missing/corrupted: "
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Presets"
msgstr ""
@@ -5864,19 +5409,29 @@ msgid "Export templates for this platform are missing:"
msgstr ""
#: editor/project_export.cpp
+msgid "Export templates for this platform are missing/corrupted:"
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Export With Debug"
msgstr ""
#: editor/project_manager.cpp
-msgid "Invalid project path, the path must exist!"
+msgid "The path does not exist."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Please choose a 'project.godot' file."
msgstr ""
#: editor/project_manager.cpp
-msgid "Invalid project path, project.godot must not exist."
+msgid ""
+"Your project will be created in a non empty folder (you might want to create "
+"a new folder)."
msgstr ""
#: editor/project_manager.cpp
-msgid "Invalid project path, project.godot must exist."
+msgid "Please choose a folder that does not contain a 'project.godot' file."
msgstr ""
#: editor/project_manager.cpp
@@ -5884,10 +5439,26 @@ msgid "Imported Project"
msgstr ""
#: editor/project_manager.cpp
+msgid " "
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "It would be a good idea to name your project."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Invalid project path (changed anything?)."
msgstr ""
#: editor/project_manager.cpp
+msgid "Couldn't get project.godot in project path."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Couldn't edit project.godot in project path."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
msgstr ""
@@ -5896,23 +5467,23 @@ msgid "The following files failed extraction from package:"
msgstr ""
#: editor/project_manager.cpp
-msgid "Import Existing Project"
+msgid "Rename Project"
msgstr ""
#: editor/project_manager.cpp
-msgid "Project Path (Must Exist):"
+msgid "Couldn't get project.godot in the project path."
msgstr ""
#: editor/project_manager.cpp
-msgid "Project Name:"
+msgid "New Game Project"
msgstr ""
#: editor/project_manager.cpp
-msgid "Create New Project"
+msgid "Import Existing Project"
msgstr ""
#: editor/project_manager.cpp
-msgid "Project Path:"
+msgid "Create New Project"
msgstr ""
#: editor/project_manager.cpp
@@ -5920,11 +5491,19 @@ msgid "Install Project:"
msgstr ""
#: editor/project_manager.cpp
-msgid "Browse"
+msgid "Project Name:"
msgstr ""
#: editor/project_manager.cpp
-msgid "New Game Project"
+msgid "Create folder"
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Project Path:"
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Browse"
msgstr ""
#: editor/project_manager.cpp
@@ -5936,6 +5515,10 @@ msgid "Unnamed Project"
msgstr ""
#: editor/project_manager.cpp
+msgid "Can't open project"
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Are you sure to open more than one project?"
msgstr ""
@@ -5962,16 +5545,18 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
-"You are about the scan %s folders for existing Godot projects. Do you "
-"confirm?"
+"Language changed.\n"
+"The UI will update next time the editor or project manager starts."
msgstr ""
#: editor/project_manager.cpp
-msgid "Project List"
+msgid ""
+"You are about the scan %s folders for existing Godot projects. Do you "
+"confirm?"
msgstr ""
#: editor/project_manager.cpp
-msgid "Run"
+msgid "Project List"
msgstr ""
#: editor/project_manager.cpp
@@ -5995,6 +5580,10 @@ msgid "Exit"
msgstr ""
#: editor/project_manager.cpp
+msgid "Restart Now"
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Can't run project"
msgstr ""
@@ -6031,17 +5620,14 @@ msgid "Add Input Action Event"
msgstr ""
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Meta+"
msgstr ""
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Shift+"
msgstr ""
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Alt+"
msgstr ""
@@ -6102,7 +5688,7 @@ msgstr ""
msgid "Joypad Axis Index:"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Axis"
msgstr ""
@@ -6122,31 +5708,31 @@ msgstr ""
msgid "Add Event"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Device"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Button"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Left Button."
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Right Button."
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Middle Button."
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Up."
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Down."
msgstr ""
@@ -6155,7 +5741,7 @@ msgid "Add Global Property"
msgstr ""
#: editor/project_settings_editor.cpp
-msgid "Select an setting item first!"
+msgid "Select a setting item first!"
msgstr ""
#: editor/project_settings_editor.cpp
@@ -6171,6 +5757,14 @@ msgid "Delete Item"
msgstr ""
#: editor/project_settings_editor.cpp
+msgid "Can't contain '/' or ':'"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Already existing"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "Error saving settings."
msgstr ""
@@ -6211,6 +5805,14 @@ msgid "Remove Resource Remap Option"
msgstr ""
#: editor/project_settings_editor.cpp
+msgid "Changed Locale Filter"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Changed Locale Filter Mode"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "Project Settings (project.godot)"
msgstr ""
@@ -6271,6 +5873,26 @@ msgid "Locale"
msgstr ""
#: editor/project_settings_editor.cpp
+msgid "Locales Filter"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Show all locales"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Show only selected locales"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Filter mode:"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Locales:"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "AutoLoad"
msgstr ""
@@ -6319,10 +5941,18 @@ msgid "New Script"
msgstr ""
#: editor/property_editor.cpp
+msgid "Make Unique"
+msgstr ""
+
+#: editor/property_editor.cpp
msgid "Show in File System"
msgstr ""
#: editor/property_editor.cpp
+msgid "Convert To %s"
+msgstr ""
+
+#: editor/property_editor.cpp
msgid "Error loading file: Not a resource!"
msgstr ""
@@ -6359,6 +5989,10 @@ msgid "Select Property"
msgstr ""
#: editor/property_selector.cpp
+msgid "Select Virtual Method"
+msgstr ""
+
+#: editor/property_selector.cpp
msgid "Select Method"
msgstr ""
@@ -6386,26 +6020,6 @@ msgstr ""
msgid "Reparent"
msgstr ""
-#: editor/resources_dock.cpp
-msgid "Create New Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Open Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Save Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Resource Tools"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Make Local"
-msgstr ""
-
#: editor/run_settings_dialog.cpp
msgid "Run Mode:"
msgstr ""
@@ -6532,14 +6146,6 @@ msgid "Sub-Resources:"
msgstr ""
#: editor/scene_tree_dock.cpp
-msgid "Edit Groups"
-msgstr ""
-
-#: editor/scene_tree_dock.cpp
-msgid "Edit Connections"
-msgstr ""
-
-#: editor/scene_tree_dock.cpp
msgid "Clear Inheritance"
msgstr ""
@@ -6720,6 +6326,14 @@ msgid "Invalid base path"
msgstr ""
#: editor/script_create_dialog.cpp
+msgid "Directory of the same name exists"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
+msgid "File exists, will be reused"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
msgid "Invalid extension"
msgstr ""
@@ -6760,6 +6374,10 @@ msgid "Load existing script file"
msgstr ""
#: editor/script_create_dialog.cpp
+msgid "Language"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
msgid "Inherits"
msgstr ""
@@ -6800,6 +6418,10 @@ msgid "Function:"
msgstr ""
#: editor/script_editor_debugger.cpp
+msgid "Pick one or more items from the list to display the graph."
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
msgid "Errors"
msgstr ""
@@ -6880,6 +6502,10 @@ msgid "Type"
msgstr ""
#: editor/script_editor_debugger.cpp
+msgid "Format"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
msgid "Usage"
msgstr ""
@@ -6955,12 +6581,28 @@ msgstr ""
msgid "Change Probe Extents"
msgstr ""
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Library"
+msgstr ""
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Status"
+msgstr ""
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Libraries: "
+msgstr ""
+
+#: modules/gdnative/register_types.cpp
+msgid "GDNative"
+msgstr ""
+
#: modules/gdscript/gd_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Invalid type argument to convert(), use TYPE_* constants."
msgstr ""
-#: modules/gdscript/gd_functions.cpp
+#: modules/gdscript/gd_functions.cpp modules/mono/glue/glue_header.h
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Not enough bytes for decoding bytes, or invalid format."
msgstr ""
@@ -7010,10 +6652,6 @@ msgid "GridMap Duplicate Selection"
msgstr ""
#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "GridMap Paint"
-msgstr ""
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Snap View"
msgstr ""
@@ -7105,12 +6743,8 @@ msgstr ""
msgid "Pick Distance:"
msgstr ""
-#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "Tiles"
-msgstr ""
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "Areas"
+#: modules/mono/editor/mono_bottom_panel.cpp
+msgid "Builds"
msgstr ""
#: modules/visual_script/visual_script.cpp
@@ -7300,10 +6934,18 @@ msgid "Return"
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
+msgid "Call"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
msgid "Get"
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
+msgid "Script already has function '%s'"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
msgid "Change Input Value"
msgstr ""
@@ -7657,6 +7299,12 @@ msgid ""
"order for AnimatedSprite3D to display frames."
msgstr ""
+#: scene/3d/vehicle_body.cpp
+msgid ""
+"VehicleWheel serves to provide a wheel system to a VehicleBody. Please use "
+"it as a child of a VehicleBody."
+msgstr ""
+
#: scene/gui/color_picker.cpp
msgid "Raw Mode"
msgstr ""
@@ -7666,15 +7314,15 @@ msgid "Add current color as a preset"
msgstr ""
#: scene/gui/dialogs.cpp
-msgid "Alert!"
+msgid "Cancel"
msgstr ""
#: scene/gui/dialogs.cpp
-msgid "Please Confirm..."
+msgid "Alert!"
msgstr ""
-#: scene/gui/input_action.cpp
-msgid "Ctrl+"
+#: scene/gui/dialogs.cpp
+msgid "Please Confirm..."
msgstr ""
#: scene/gui/popup.cpp
@@ -7704,3 +7352,19 @@ msgid ""
"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
"texture to some node for display."
msgstr ""
+
+#: scene/resources/dynamic_font.cpp
+msgid "Error initializing FreeType."
+msgstr ""
+
+#: scene/resources/dynamic_font.cpp
+msgid "Unknown font format."
+msgstr ""
+
+#: scene/resources/dynamic_font.cpp
+msgid "Error loading font."
+msgstr ""
+
+#: scene/resources/dynamic_font.cpp
+msgid "Invalid font size."
+msgstr ""
diff --git a/editor/translations/id.po b/editor/translations/id.po
index 2f13c11082..06fc7eb599 100644
--- a/editor/translations/id.po
+++ b/editor/translations/id.po
@@ -1,5 +1,6 @@
# Indonesian translation of the Godot Engine editor
-# Copyright (C) 2016-2017 Juan Linietsky, Ariel Manzur and the Godot community
+# Copyright (C) 2007-2017 Juan Linietsky, Ariel Manzur
+# Copyright (C) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)
# This file is distributed under the same license as the Godot source code.
#
# Abdul Aziz Muslim Alqudsy <abdul.aziz.muslim.alqudsy@gmail.com>, 2016.
@@ -7,20 +8,22 @@
# Andinawan Asa <asaandinawan@gmail.com>, 2016.
# Damar S. M <the.last.walla@gmail.com>, 2017.
# Khairul Hidayat <khairulcyber4rt@gmail.com>, 2016.
+# Sofyan Sugianto <sofyanartem@gmail.com>, 2017.
+# Tom My <tom.asadinawan@gmail.com>, 2017.
# yursan9 <rizal.sagi@gmail.com>, 2016.
#
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
-"PO-Revision-Date: 2017-01-18 13:18+0000\n"
-"Last-Translator: Damar S. M. <the.last.walla@gmail.com>\n"
+"PO-Revision-Date: 2017-09-13 10:49+0000\n"
+"Last-Translator: Sofyan Sugianto <sofyanartem@gmail.com>\n"
"Language-Team: Indonesian <https://hosted.weblate.org/projects/godot-engine/"
"godot/id/>\n"
"Language: id\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8-bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
-"X-Generator: Weblate 2.11-dev\n"
+"X-Generator: Weblate 2.17-dev\n"
#: editor/animation_editor.cpp
msgid "Disabled"
@@ -35,19 +38,16 @@ msgid "Move Add Key"
msgstr "Pindahkan Kunci Tambah"
#: editor/animation_editor.cpp
-#, fuzzy
msgid "Anim Change Transition"
-msgstr "Ubah Transisi Anim"
+msgstr "Ubah Transisi Animasi"
#: editor/animation_editor.cpp
-#, fuzzy
msgid "Anim Change Transform"
-msgstr "Ubah Transformasi Anim"
+msgstr "Ubah Transformasi Animasi"
#: editor/animation_editor.cpp
-#, fuzzy
msgid "Anim Change Value"
-msgstr "Ubah Nilai Anim"
+msgstr "Ubah Nilai Animasi"
#: editor/animation_editor.cpp
#, fuzzy
@@ -211,10 +211,9 @@ msgid "Create %d NEW tracks and insert keys?"
msgstr "Buat track BARU %d dan masukkan tombol-tombol?"
#: editor/animation_editor.cpp editor/create_dialog.cpp
-#: editor/editor_audio_buses.cpp
+#: editor/editor_audio_buses.cpp editor/plugins/abstract_polygon_2d_editor.cpp
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
#: editor/plugins/mesh_instance_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp editor/project_manager.cpp
#: editor/script_create_dialog.cpp
msgid "Create"
@@ -381,277 +380,13 @@ msgstr "Ubah Tipe Nilai Array"
msgid "Change Array Value"
msgstr "Ubah Nilai Array"
-#: editor/asset_library_editor_plugin.cpp
-msgid "Free"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_plugin_settings.cpp
-msgid "Version:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Contents:"
-msgstr "Konstanta:"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "View Files"
-msgstr "File:"
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_help.cpp editor/property_selector.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Description:"
-msgstr "Deskripsi:"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-#: editor/project_manager.cpp
-msgid "Install"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/call_dialog.cpp
-#: editor/connections_dialog.cpp editor/export_template_manager.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-#: editor/project_settings_editor.cpp editor/property_editor.cpp
-#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Close"
-msgstr "Tutup"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve hostname:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Connection error, please try again."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Can't connect."
-msgstr "Menyambungkan.."
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Can't connect to host:"
-msgstr "Sambungkan Ke Node:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response from host:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Request failed, return code:"
-msgstr "Format file yang diminta tidak diketahui:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Req. Failed."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Request failed, too many redirects"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Redirect Loop."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Bad download hash, assuming file has been tampered with."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Expected:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Got:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Asset Download Error:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-msgid "Success!"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Fetching:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Resolving.."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Connecting.."
-msgstr "Menyambungkan.."
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Requesting.."
-msgstr "Menguji"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Error making request"
-msgstr "Error menyimpan resource!"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Idle"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Retry"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Download Error"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Download for this asset is already in progress!"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "first"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "prev"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "next"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "last"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "All"
-msgstr "Semua"
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
-#: editor/settings_config_dialog.cpp
-msgid "Search:"
-msgstr "Cari:"
-
-#: editor/asset_library_editor_plugin.cpp editor/code_editor.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Search"
-msgstr "Cari"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/project_manager.cpp
-msgid "Import"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Plugins"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Sort:"
-msgstr "Sortir:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Reverse"
-msgstr "Terbalik"
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Category:"
-msgstr "Kategori:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Site:"
-msgstr "Situs:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Support.."
-msgstr "Dukungan.."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Official"
-msgstr "Resmi"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-msgid "Community"
-msgstr "Komunitas"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Testing"
-msgstr "Menguji"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Assets ZIP File"
-msgstr "Aset-aset File ZIP"
-
-#: editor/call_dialog.cpp
-msgid "Method List For '%s':"
-msgstr "Daftar Fungsi Untuk '%s':"
-
-#: editor/call_dialog.cpp modules/visual_script/visual_script_editor.cpp
-msgid "Call"
-msgstr "Panggil"
-
-#: editor/call_dialog.cpp
-msgid "Method List:"
-msgstr "Daftar Fungsi:"
-
-#: editor/call_dialog.cpp
-msgid "Arguments:"
-msgstr "Argumen:"
-
-#: editor/call_dialog.cpp
-#, fuzzy
-msgid "Return:"
-msgstr "Kembali:"
-
#: editor/code_editor.cpp
msgid "Go to Line"
-msgstr "Pergi ke Barisan"
+msgstr "Pergi ke Baris"
#: editor/code_editor.cpp
msgid "Line Number:"
-msgstr "Nomor Barisan:"
+msgstr "Baris Nomor:"
#: editor/code_editor.cpp
msgid "No Matches"
@@ -664,11 +399,11 @@ msgstr "Diganti kejadian (kejadian-kejadian) %d."
#: editor/code_editor.cpp
msgid "Replace"
-msgstr "Tukar"
+msgstr "Ubah"
#: editor/code_editor.cpp
msgid "Replace All"
-msgstr "Tukar Semua"
+msgstr "Ubah Semua"
#: editor/code_editor.cpp
msgid "Match Case"
@@ -682,6 +417,14 @@ msgstr "Semua Kata"
msgid "Selection Only"
msgstr "Hanya yang Dipilih"
+#: editor/code_editor.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
+msgid "Search"
+msgstr "Cari"
+
#: editor/code_editor.cpp editor/editor_help.cpp
msgid "Find"
msgstr "Cari"
@@ -716,11 +459,11 @@ msgstr "Cepat Pada Penggantian"
msgid "Skip"
msgstr "Lalui"
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom In"
msgstr "Perbesar Pandangan"
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom Out"
msgstr "Perkecil Pandangan"
@@ -787,6 +530,20 @@ msgstr "Ditunda"
msgid "Oneshot"
msgstr "Satu Waktu"
+#: editor/connections_dialog.cpp editor/dependency_editor.cpp
+#: editor/export_template_manager.cpp
+#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Close"
+msgstr "Tutup"
+
#: editor/connections_dialog.cpp
msgid "Connect"
msgstr "Menghubungkan"
@@ -812,7 +569,7 @@ msgstr "Menyambungkan.."
msgid "Disconnect"
msgstr "Tidak tersambung"
-#: editor/connections_dialog.cpp editor/node_dock.cpp
+#: editor/connections_dialog.cpp editor/editor_help.cpp editor/node_dock.cpp
msgid "Signals"
msgstr "Sinyal-sinyal"
@@ -829,6 +586,13 @@ msgstr "Favorit:"
msgid "Recent:"
msgstr "Saat ini:"
+#: editor/create_dialog.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/quick_open.cpp editor/settings_config_dialog.cpp
+msgid "Search:"
+msgstr "Cari:"
+
#: editor/create_dialog.cpp editor/editor_help.cpp
#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/quick_open.cpp
@@ -836,6 +600,12 @@ msgstr "Saat ini:"
msgid "Matches:"
msgstr "Kecocokan:"
+#: editor/create_dialog.cpp editor/editor_help.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/property_selector.cpp
+#: editor/script_editor_debugger.cpp
+msgid "Description:"
+msgstr "Deskripsi:"
+
#: editor/dependency_editor.cpp
msgid "Search Replacement For:"
msgstr "Cari Ganti Untuk:"
@@ -897,6 +667,11 @@ msgstr "Pemilik Dari:"
#: editor/dependency_editor.cpp
#, fuzzy
+msgid "Remove selected files from the project? (no undo)"
+msgstr "Hapus file-file yang dipilih dari proyek? (tanpa membatalkan/undo)"
+
+#: editor/dependency_editor.cpp
+#, fuzzy
msgid ""
"The files being removed are required by other resources in order for them to "
"work.\n"
@@ -907,9 +682,8 @@ msgstr ""
"Hapus saja mereka? (tanpa membatalkan/undo)"
#: editor/dependency_editor.cpp
-#, fuzzy
-msgid "Remove selected files from the project? (no undo)"
-msgstr "Hapus file-file yang dipilih dari proyek? (tanpa membatalkan/undo)"
+msgid "Cannot remove:\n"
+msgstr ""
#: editor/dependency_editor.cpp
msgid "Error loading:"
@@ -978,10 +752,6 @@ msgid "Godot Engine contributors"
msgstr ""
#: editor/editor_about.cpp
-msgid "Authors"
-msgstr ""
-
-#: editor/editor_about.cpp
msgid "Project Founders"
msgstr ""
@@ -998,6 +768,38 @@ msgid "Developers"
msgstr ""
#: editor/editor_about.cpp
+msgid "Authors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Platinum Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Gold Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Mini Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Gold Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Silver Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Bronze Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
msgid "License"
msgstr ""
@@ -1041,6 +843,16 @@ msgid "Package Installed Successfully!"
msgstr ""
#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Success!"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/project_manager.cpp
+msgid "Install"
+msgstr "Pasang"
+
+#: editor/editor_asset_installer.cpp
msgid "Package Installer"
msgstr ""
@@ -1091,10 +903,6 @@ msgid "Audio Bus, Drag and Drop to rearrange."
msgstr ""
#: editor/editor_audio_buses.cpp
-msgid "Bus options"
-msgstr ""
-
-#: editor/editor_audio_buses.cpp
msgid "Solo"
msgstr ""
@@ -1106,6 +914,10 @@ msgstr ""
msgid "Bypass"
msgstr ""
+#: editor/editor_audio_buses.cpp
+msgid "Bus options"
+msgstr ""
+
#: editor/editor_audio_buses.cpp editor/plugins/tile_map_editor_plugin.cpp
#: editor/scene_tree_dock.cpp
msgid "Duplicate"
@@ -1113,6 +925,11 @@ msgstr ""
#: editor/editor_audio_buses.cpp
#, fuzzy
+msgid "Reset Volume"
+msgstr "Kebalikan Semula Pandangan"
+
+#: editor/editor_audio_buses.cpp
+#, fuzzy
msgid "Delete Effect"
msgstr "Hapus yang Dipilih"
@@ -1136,6 +953,11 @@ msgstr "Duplikat Pilihan"
#: editor/editor_audio_buses.cpp
#, fuzzy
+msgid "Reset Bus Volume"
+msgstr "Kebalikan Semula Pandangan"
+
+#: editor/editor_audio_buses.cpp
+#, fuzzy
msgid "Move Audio Bus"
msgstr "Pindahkan Kunci Tambah"
@@ -1167,7 +989,8 @@ msgstr ""
msgid "Create a new Bus Layout."
msgstr ""
-#: editor/editor_audio_buses.cpp editor/script_create_dialog.cpp
+#: editor/editor_audio_buses.cpp editor/property_editor.cpp
+#: editor/script_create_dialog.cpp
msgid "Load"
msgstr ""
@@ -1261,7 +1084,7 @@ msgid "Rearrange Autoloads"
msgstr "Mengatur kembali Autoload-autoload"
#: editor/editor_autoload_settings.cpp editor/editor_file_dialog.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp scene/gui/file_dialog.cpp
+#: scene/gui/file_dialog.cpp
msgid "Path:"
msgstr "Path:"
@@ -1269,9 +1092,7 @@ msgstr "Path:"
msgid "Node Name:"
msgstr "Nama Node:"
-#: editor/editor_autoload_settings.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp editor/project_manager.cpp
+#: editor/editor_autoload_settings.cpp editor/project_manager.cpp
msgid "Name"
msgstr "Nama"
@@ -1305,18 +1126,19 @@ msgid "Choose a Directory"
msgstr "Pilih sebuah Direktori"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Create Folder"
msgstr "Buat Folder"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: editor/editor_plugin_settings.cpp editor/plugins/theme_editor_plugin.cpp
-#: editor/project_export.cpp scene/gui/file_dialog.cpp
+#: editor/editor_plugin_settings.cpp editor/filesystem_dock.cpp
+#: editor/plugins/theme_editor_plugin.cpp editor/project_export.cpp
+#: scene/gui/file_dialog.cpp
msgid "Name:"
msgstr "Nama:"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Could not create folder."
msgstr "Tidak dapat membuat folder."
@@ -1336,30 +1158,6 @@ msgstr "Mengemas"
msgid "Template file not found:\n"
msgstr ""
-#: editor/editor_export.cpp
-msgid "Added:"
-msgstr "Ditambahkan:"
-
-#: editor/editor_export.cpp
-msgid "Removed:"
-msgstr "Dihapus:"
-
-#: editor/editor_export.cpp
-msgid "Error saving atlas:"
-msgstr "Gagal menyimpan atlas:"
-
-#: editor/editor_export.cpp
-msgid "Could not save atlas subtexture:"
-msgstr "Tidak dapat menyimpan sub tekstur atlas:"
-
-#: editor/editor_export.cpp
-msgid "Exporting for %s"
-msgstr "Mengekspor untuk %s"
-
-#: editor/editor_export.cpp
-msgid "Setting Up.."
-msgstr "Mengatur.."
-
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "File Exists, Overwrite?"
msgstr "File telah ada, Overwrite?"
@@ -1447,6 +1245,11 @@ msgstr "Pindahkan Favorit Keatas"
msgid "Move Favorite Down"
msgstr "Pindahkan Favorit Kebawah"
+#: editor/editor_file_dialog.cpp
+#, fuzzy
+msgid "Go to parent folder"
+msgstr "Tidak dapat membuat folder."
+
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Directories & Files:"
msgstr "Direktori-direktori & File-file:"
@@ -1461,10 +1264,6 @@ msgid "File:"
msgstr "File:"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
-msgid "Filter:"
-msgstr "Filter:"
-
-#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Must use a valid extension."
msgstr "Harus menggunakan ekstensi yang sah."
@@ -1490,6 +1289,10 @@ msgstr "Daftar Class:"
msgid "Search Classes"
msgstr "Cari Kelas"
+#: editor/editor_help.cpp editor/plugins/spatial_editor_plugin.cpp
+msgid "Top"
+msgstr "Atas"
+
#: editor/editor_help.cpp editor/property_editor.cpp
msgid "Class:"
msgstr "Kelas:"
@@ -1506,15 +1309,30 @@ msgstr "Diturunkan oleh:"
msgid "Brief Description:"
msgstr "Deskripsi Singkat:"
+#: editor/editor_help.cpp
+#, fuzzy
+msgid "Members"
+msgstr "Member-member:"
+
#: editor/editor_help.cpp modules/visual_script/visual_script_editor.cpp
msgid "Members:"
msgstr "Member-member:"
#: editor/editor_help.cpp
+#, fuzzy
+msgid "Public Methods"
+msgstr "Metode Publik:"
+
+#: editor/editor_help.cpp
msgid "Public Methods:"
msgstr "Metode Publik:"
#: editor/editor_help.cpp
+#, fuzzy
+msgid "GUI Theme Items"
+msgstr "Item-item Tema GUI:"
+
+#: editor/editor_help.cpp
msgid "GUI Theme Items:"
msgstr "Item-item Tema GUI:"
@@ -1524,6 +1342,11 @@ msgstr "Sinyal-sinyal:"
#: editor/editor_help.cpp
#, fuzzy
+msgid "Enumerations"
+msgstr "Fungsi-fungsi:"
+
+#: editor/editor_help.cpp
+#, fuzzy
msgid "Enumerations:"
msgstr "Fungsi-fungsi:"
@@ -1532,19 +1355,51 @@ msgid "enum "
msgstr ""
#: editor/editor_help.cpp
+#, fuzzy
+msgid "Constants"
+msgstr "Konstanta:"
+
+#: editor/editor_help.cpp
msgid "Constants:"
msgstr "Konstanta:"
#: editor/editor_help.cpp
#, fuzzy
+msgid "Description"
+msgstr "Deskripsi:"
+
+#: editor/editor_help.cpp
+#, fuzzy
+msgid "Properties"
+msgstr "Properti Objek."
+
+#: editor/editor_help.cpp
+#, fuzzy
msgid "Property Description:"
msgstr "Deskripsi Singkat:"
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this property. Please help us by "
+"[color=$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+
+#: editor/editor_help.cpp
+#, fuzzy
+msgid "Methods"
+msgstr "Daftar Fungsi:"
+
+#: editor/editor_help.cpp
msgid "Method Description:"
msgstr "Deskripsi Metode:"
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this method. Please help us by [color="
+"$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Search Text"
msgstr "Mencari Teks"
@@ -1554,24 +1409,21 @@ msgid "Output:"
msgstr " Keluaran:"
#: editor/editor_log.cpp editor/plugins/animation_tree_editor_plugin.cpp
-#: editor/plugins/rich_text_editor_plugin.cpp editor/property_editor.cpp
-#: editor/script_editor_debugger.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/property_editor.cpp editor/script_editor_debugger.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Clear"
msgstr "Bersihkan"
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Error saving resource!"
msgstr "Error menyimpan resource!"
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Save Resource As.."
msgstr "Simpan Resource Sebagai.."
-#: editor/editor_node.cpp editor/export_template_manager.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
#, fuzzy
msgid "I see.."
msgstr "Aku tahu.."
@@ -1589,6 +1441,30 @@ msgid "Error while saving."
msgstr "Error saat menyimpan."
#: editor/editor_node.cpp
+#, fuzzy
+msgid "Can't open '%s'."
+msgstr "Menyambungkan.."
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Error while parsing '%s'."
+msgstr "Error saat menyimpan."
+
+#: editor/editor_node.cpp
+msgid "Unexpected end of file '%s'."
+msgstr ""
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Missing '%s' or its dependencies."
+msgstr "Scene '%s' memiliki dependensi yang rusak:"
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Error while loading '%s'."
+msgstr "Error saat menyimpan."
+
+#: editor/editor_node.cpp
msgid "Saving Scene"
msgstr "Menyimpan Scene"
@@ -1649,6 +1525,33 @@ msgid "Restored default layout to base settings."
msgstr "Mengembalikan semula layout default ke pengaturan-pengaturan awal."
#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was imported, so it's not editable.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was instanced or inherited.\n"
+"Changes to it will not be kept when saving the current scene."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource was imported, so it's not editable. Change its settings in the "
+"import panel and then re-import."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This scene was imported, so changes to it will not be kept.\n"
+"Instancing it or inheriting will allow making changes to it.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Copy Params"
msgstr "Salin Parameter"
@@ -1816,11 +1719,19 @@ msgid "Save & Quit"
msgstr "Simpan sebuah File"
#: editor/editor_node.cpp
+#, fuzzy
msgid "Save changes to the following scene(s) before quitting?"
-msgstr ""
+msgstr "Simpan perubahan saat ini sebelum keluar?"
#: editor/editor_node.cpp
+#, fuzzy
msgid "Save changes the following scene(s) before opening Project Manager?"
+msgstr "Simpan perubahan saat ini sebelum membuka Manajer Projek?"
+
+#: editor/editor_node.cpp
+msgid ""
+"This option is deprecated. Situations where refresh must be forced are now "
+"considered a bug. Please report."
msgstr ""
#: editor/editor_node.cpp
@@ -1828,19 +1739,25 @@ msgid "Pick a Main Scene"
msgstr "Pilih sebuah Scene Utama"
#: editor/editor_node.cpp
-msgid "Unable to enable addon plugin at: '"
+msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr ""
#: editor/editor_node.cpp
-msgid "' parsing of config failed."
+msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/"
+#, fuzzy
+msgid "Unable to load addon script from path: '%s'."
+msgstr "Error memuat font."
+
+#: editor/editor_node.cpp
+msgid ""
+"Unable to load addon script from path: '%s' Base type is not EditorPlugin."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to load addon script from path: '"
+msgid "Unable to load addon script from path: '%s' Script is not in tool mode."
msgstr ""
#: editor/editor_node.cpp
@@ -1850,7 +1767,7 @@ msgid ""
msgstr ""
#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/scene_tree_dock.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
#, fuzzy
msgid "Ugh"
msgstr "Wadoo"
@@ -1864,14 +1781,14 @@ msgstr ""
"membuka scene tersebut, kemudian simpan di dalam alamat proyek."
#: editor/editor_node.cpp
-msgid "Error loading scene."
-msgstr "Gagal memuat scene."
-
-#: editor/editor_node.cpp
msgid "Scene '%s' has broken dependencies:"
msgstr "Scene '%s' memiliki dependensi yang rusak:"
#: editor/editor_node.cpp
+msgid "Clear Recent Scenes"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Save Layout"
msgstr "Simpan Penampilan"
@@ -1905,7 +1822,7 @@ msgstr "Mode Tanpa Gangguan"
msgid "Toggle distraction-free mode."
msgstr "Mode Tanpa Gangguan"
-#: editor/editor_node.cpp editor/io_plugins/editor_scene_import_plugin.cpp
+#: editor/editor_node.cpp
msgid "Scene"
msgstr "Suasana"
@@ -2127,6 +2044,10 @@ msgstr ""
msgid "Issue Tracker"
msgstr ""
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+msgid "Community"
+msgstr "Komunitas"
+
#: editor/editor_node.cpp
msgid "About"
msgstr ""
@@ -2135,7 +2056,7 @@ msgstr ""
msgid "Play the project."
msgstr ""
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Play"
msgstr ""
@@ -2151,7 +2072,7 @@ msgstr ""
msgid "Stop the scene."
msgstr ""
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Stop"
msgstr ""
@@ -2221,55 +2142,59 @@ msgstr ""
#: editor/editor_node.cpp
msgid "Object properties."
+msgstr "Properti Objek."
+
+#: editor/editor_node.cpp
+msgid "Changes may be lost!"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Import"
msgstr ""
#: editor/editor_node.cpp
msgid "FileSystem"
-msgstr ""
+msgstr "Berkas Sistem"
#: editor/editor_node.cpp editor/node_dock.cpp
+#, fuzzy
msgid "Node"
-msgstr ""
+msgstr "Titik"
#: editor/editor_node.cpp
msgid "Output"
-msgstr ""
+msgstr "Luaran"
#: editor/editor_node.cpp
msgid "Don't Save"
-msgstr ""
-
-#: editor/editor_node.cpp editor/editor_reimport_dialog.cpp
-msgid "Re-Import"
-msgstr ""
-
-#: editor/editor_node.cpp editor/editor_plugin_settings.cpp
-msgid "Update"
-msgstr ""
+msgstr "Jangan Simpan"
#: editor/editor_node.cpp
+#, fuzzy
msgid "Import Templates From ZIP File"
-msgstr ""
+msgstr "Impor Templat dari Berkas ZIP"
#: editor/editor_node.cpp editor/project_export.cpp
msgid "Export Project"
-msgstr ""
+msgstr "Ekspor Projek"
#: editor/editor_node.cpp
msgid "Export Library"
-msgstr ""
+msgstr "Ekspor Pustaka"
#: editor/editor_node.cpp
+#, fuzzy
msgid "Merge With Existing"
-msgstr ""
+msgstr "Gabung dengan yang Ada"
#: editor/editor_node.cpp
msgid "Password:"
-msgstr ""
+msgstr "Sandi:"
#: editor/editor_node.cpp
msgid "Open & Run a Script"
-msgstr ""
+msgstr "Buka & Jalankan Skrip"
#: editor/editor_node.cpp
#, fuzzy
@@ -2277,39 +2202,46 @@ msgid "New Inherited"
msgstr "Scene Turunan Baru.."
#: editor/editor_node.cpp
+#, fuzzy
msgid "Load Errors"
-msgstr ""
+msgstr "Muat Galat"
#: editor/editor_node.cpp editor/plugins/tile_map_editor_plugin.cpp
msgid "Select"
-msgstr ""
+msgstr "Pilih"
#: editor/editor_node.cpp
#, fuzzy
msgid "Open 2D Editor"
-msgstr "Buka sebuah Direktori"
+msgstr "Buka Penyunting 2D"
#: editor/editor_node.cpp
#, fuzzy
msgid "Open 3D Editor"
-msgstr "Buka sebuah Direktori"
+msgstr "Buka Penyunting 3D"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Open Script Editor"
-msgstr "Editor Ketergantungan"
+msgstr "Buka Penyunting Skrip"
#: editor/editor_node.cpp
msgid "Open Asset Library"
-msgstr ""
+msgstr "Buka Pustaka Aset"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Open the next Editor"
-msgstr "Editor Ketergantungan"
+msgstr "Buka Penyunting Selanjutnya"
#: editor/editor_node.cpp
msgid "Open the previous Editor"
+msgstr "Buka Penyunting Sebelumnya"
+
+#: editor/editor_plugin.cpp
+msgid "Creating Mesh Previews"
+msgstr ""
+
+#: editor/editor_plugin.cpp
+msgid "Thumbnail.."
msgstr ""
#: editor/editor_plugin_settings.cpp
@@ -2317,6 +2249,15 @@ msgid "Installed Plugins:"
msgstr ""
#: editor/editor_plugin_settings.cpp
+msgid "Update"
+msgstr "Perbarui"
+
+#: editor/editor_plugin_settings.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Version:"
+msgstr ""
+
+#: editor/editor_plugin_settings.cpp
msgid "Author:"
msgstr ""
@@ -2349,7 +2290,7 @@ msgid "Frame %"
msgstr ""
#: editor/editor_profiler.cpp
-msgid "Fixed Frame %"
+msgid "Physics Frame %"
msgstr ""
#: editor/editor_profiler.cpp editor/script_editor_debugger.cpp
@@ -2368,26 +2309,6 @@ msgstr ""
msgid "Frame #:"
msgstr ""
-#: editor/editor_reimport_dialog.cpp
-msgid "Please wait for scan to complete."
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Current scene must be saved to re-import."
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Save & Re-Import"
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Importing"
-msgstr "Mengimpor ulang"
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Import Changed Resources"
-msgstr ""
-
#: editor/editor_run_native.cpp
msgid "Select device from the list"
msgstr ""
@@ -2499,10 +2420,6 @@ msgid "Importing:"
msgstr "Mengimpor:"
#: editor/export_template_manager.cpp
-msgid "Loading Export Templates"
-msgstr "Memuat Ekspor Template-template."
-
-#: editor/export_template_manager.cpp
msgid "Current Version:"
msgstr ""
@@ -2538,9 +2455,17 @@ msgid "Cannot navigate to '"
msgstr ""
#: editor/filesystem_dock.cpp
+msgid "View items as a grid of thumbnails"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "View items as a list"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
msgid ""
"\n"
-"Status: Needs Re-Import"
+"Status: Import of file failed. Please fix file and reimport manually."
msgstr ""
#: editor/filesystem_dock.cpp
@@ -2551,45 +2476,52 @@ msgid ""
msgstr "Resource"
#: editor/filesystem_dock.cpp
-msgid "Same source and destination files, doing nothing."
+msgid "Cannot move/rename resources root."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Target file exists, can't overwrite. Delete first."
+msgid "Cannot move a folder into itself.\n"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Same source and destination paths, doing nothing."
-msgstr ""
+#, fuzzy
+msgid "Error moving:\n"
+msgstr "Error memuat:"
+
+#: editor/filesystem_dock.cpp
+#, fuzzy
+msgid "Unable to update dependencies:\n"
+msgstr "Scene '%s' memiliki dependensi yang rusak:"
#: editor/filesystem_dock.cpp
-msgid "Can't move directories to within themselves."
+msgid "No name provided"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Can't rename deps for:\n"
+msgid "Provided name contains invalid characters"
msgstr ""
#: editor/filesystem_dock.cpp
#, fuzzy
-msgid "Error moving file:\n"
-msgstr "Error menyimpan TileSet!"
+msgid "No name provided."
+msgstr "Ubah Nama atau Pindahkan.."
#: editor/filesystem_dock.cpp
#, fuzzy
-msgid "Error moving dir:\n"
-msgstr "Error memuat:"
+msgid "Name contains invalid characters."
+msgstr "Karakter sah:"
#: editor/filesystem_dock.cpp
-msgid "Can't operate on '..'"
+msgid "A file or folder with this name already exists."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Pick New Name and Location For:"
-msgstr ""
+#, fuzzy
+msgid "Renaming file:"
+msgstr "Namai kembali Variabel"
#: editor/filesystem_dock.cpp
-msgid "No files selected!"
+msgid "Renaming folder:"
msgstr ""
#: editor/filesystem_dock.cpp
@@ -2601,52 +2533,50 @@ msgid "Collapse all"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Show In File Manager"
-msgstr ""
-
-#: editor/filesystem_dock.cpp
-msgid "Instance"
+msgid "Copy Path"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Edit Dependencies.."
-msgstr ""
+#, fuzzy
+msgid "Rename.."
+msgstr "Ubah Nama atau Pindahkan.."
#: editor/filesystem_dock.cpp
-msgid "View Owners.."
-msgstr ""
+msgid "Move To.."
+msgstr "Pindah Ke.."
#: editor/filesystem_dock.cpp
-msgid "Copy Path"
-msgstr ""
+#, fuzzy
+msgid "New Folder.."
+msgstr "Buat Folder"
#: editor/filesystem_dock.cpp
-msgid "Rename or Move.."
-msgstr ""
+msgid "Show In File Manager"
+msgstr "Tampilkan di Manajer Berkas"
#: editor/filesystem_dock.cpp
-msgid "Move To.."
+msgid "Instance"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Info"
+msgid "Edit Dependencies.."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Re-Import.."
+msgid "View Owners.."
msgstr ""
#: editor/filesystem_dock.cpp
msgid "Previous Directory"
-msgstr ""
+msgstr "Direktori Sebelumnya"
#: editor/filesystem_dock.cpp
msgid "Next Directory"
-msgstr ""
+msgstr "Direktori Selanjutnya"
#: editor/filesystem_dock.cpp
msgid "Re-Scan Filesystem"
-msgstr ""
+msgstr "Pindai Ulang Berkas Sistem"
#: editor/filesystem_dock.cpp
msgid "Toggle folder status as Favorite"
@@ -2657,18 +2587,26 @@ msgid "Instance the selected scene(s) as child of the selected node."
msgstr ""
#: editor/filesystem_dock.cpp
+#, fuzzy
msgid ""
"Scanning Files,\n"
"Please Wait.."
msgstr ""
+"Memindai Berkas,\n"
+"Silakan Tunggu.."
#: editor/filesystem_dock.cpp
msgid "Move"
+msgstr "Pindahkan"
+
+#: editor/filesystem_dock.cpp editor/plugins/animation_tree_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Rename"
msgstr ""
#: editor/groups_editor.cpp
msgid "Add to Group"
-msgstr ""
+msgstr "Tambahkan ke Grup"
#: editor/groups_editor.cpp
msgid "Remove from Group"
@@ -2680,6 +2618,10 @@ msgid "Import as Single Scene"
msgstr "Memperbaharui Scene"
#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
msgid "Import with Separate Materials"
msgstr ""
@@ -2692,6 +2634,18 @@ msgid "Import with Separate Objects+Materials"
msgstr ""
#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Materials+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Materials+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
msgid "Import as Multiple Scenes"
msgstr ""
@@ -2700,38 +2654,31 @@ msgid "Import as Multiple Scenes+Materials"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Import Scene"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Importing Scene.."
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Running Custom Script.."
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Couldn't load post-import script:"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Invalid/broken script for post-import (check console):"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Error running post-import script:"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Saving.."
msgstr ""
@@ -2762,580 +2709,54 @@ msgstr ""
msgid "Reimport"
msgstr "Mengimpor ulang"
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "No bit masks to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path is empty."
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must be a complete resource path."
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must exist."
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Save path is empty!"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Import BitMasks"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s):"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Target Path:"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Accept"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Bit Mask"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No source font file!"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No target font resource!"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"Invalid file extension.\n"
-"Please use .font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Can't load/process source font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Couldn't save font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font Size:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Dest Resource:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "The quick brown fox jumps over the lazy dog."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Test:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Options:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Font Import"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"This file is already a Godot font file, please supply a BMFont type file "
-"instead."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Failed opening as BMFont file."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error initializing FreeType."
-msgstr "Error menginisialisasi FreeType."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Unknown font format."
-msgstr "Format font tidak diketahui."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error loading font."
-msgstr "Error memuat font."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Invalid font size."
-msgstr "Ukuran font tidak sah."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Invalid font custom source."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/plugins/theme_editor_plugin.cpp
-msgid "Font"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "No meshes to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Single Mesh Import"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Source Mesh(es):"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/plugins/mesh_instance_editor_plugin.cpp
-msgid "Mesh"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Surface %d"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "No samples to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Import Audio Samples"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Source Sample(s):"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Audio Sample"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "New Clip"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Animation Options"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Flags"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Bake FPS:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Optimizer"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Linear Error"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angular Error"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angle"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Clips"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Start(s)"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "End(s)"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Loop"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Filters"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source path is empty."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't load post-import script."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Invalid/broken script for post-import."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Error importing scene."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import 3D Scene"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source Scene:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Same as Target Scene"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Shared"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Target Texture Folder:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Post-Process Script:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Custom Root Node Type:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Auto"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#, fuzzy
-msgid "Root Node Name:"
-msgstr "Nama Node:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "The Following Files are Missing:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Anyway"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp scene/gui/dialogs.cpp
-msgid "Cancel"
-msgstr "Batal"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import & Open"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Edited scene has not been saved, open imported scene anyway?"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Image:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Can't import a file over itself:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't localize path: %s (already local)"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "3D Scene Animation"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Uncompressed"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossless (PNG)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossy (WebP)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress (VRAM)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Format"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Compression Quality (WebP):"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Options"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Please specify some files!"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "At least one file needed for Atlas."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Error importing:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Only one file is required for large texture."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Max Texture Size:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for Atlas (2D)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cell Size:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Large Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Textures (2D)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture"
+#: editor/multi_node_edit.cpp
+msgid "MultiNode Set"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Base Atlas Texture"
+#: editor/node_dock.cpp
+msgid "Groups"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s)"
+#: editor/node_dock.cpp
+msgid "Select a Node to edit Signals and Groups."
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 2D"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create Poly"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 3D"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Insert Point"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "2D Texture"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly (Remove Point)"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "3D Texture"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Remove Poly And Point"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Atlas Texture"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create a new polygon from scratch."
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
+#: editor/plugins/abstract_polygon_2d_editor.cpp
msgid ""
-"NOTICE: Importing 2D textures is not mandatory. Just copy png/jpg files to "
-"the project."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Crop empty space."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Load Source Image"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Slicing"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Inserting"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Saving"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save large texture:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Build Atlas For:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Loading Image:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't load image:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Converting Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cropping Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Blitting Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save atlas image:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save converted texture:"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid source!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid translation source!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Column"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/script_create_dialog.cpp
-msgid "Language"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No items to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No target path!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translations"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Couldn't import!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translation"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Source CSV:"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Ignore First Row"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Compress"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Add to Project (project.godot)"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Languages:"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Translation"
-msgstr ""
-
-#: editor/multi_node_edit.cpp
-msgid "MultiNode Set"
-msgstr ""
-
-#: editor/node_dock.cpp
-msgid "Groups"
-msgstr ""
-
-#: editor/node_dock.cpp
-msgid "Select a Node to edit Signals and Groups."
+"Edit existing polygon:\n"
+"LMB: Move Point.\n"
+"Ctrl+LMB: Split Segment.\n"
+"RMB: Erase Point."
msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
@@ -3492,7 +2913,6 @@ msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
#: editor/script_create_dialog.cpp
msgid "Error!"
@@ -3513,7 +2933,7 @@ msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Animation"
-msgstr ""
+msgstr "Animasi"
#: editor/plugins/animation_tree_editor_plugin.cpp
msgid "New name:"
@@ -3603,10 +3023,6 @@ msgid "Delete Input"
msgstr ""
#: editor/plugins/animation_tree_editor_plugin.cpp
-msgid "Rename"
-msgstr ""
-
-#: editor/plugins/animation_tree_editor_plugin.cpp
msgid "Animation tree is valid."
msgstr ""
@@ -3662,64 +3078,190 @@ msgstr ""
msgid "Filters.."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing %d Triangles:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Free"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Contents:"
+msgstr "Konstanta:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "View Files"
+msgstr "File:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve hostname:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Connection error, please try again."
+msgstr "Gangguan koneks, silakan coba lagi."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Can't connect."
+msgstr "Menyambungkan.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Can't connect to host:"
+msgstr "Sambungkan Ke Node:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response from host:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response."
+msgstr "Tidak ada respon."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Request failed, return code:"
+msgstr "Format file yang diminta tidak diketahui:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Req. Failed."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, too many redirects"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Redirect Loop."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Triangle #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Light Baker Setup:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Bad download hash, assuming file has been tampered with."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing Geometry"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Expected:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Fixing Lights"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Got:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed sha256 hash check"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Asset Download Error:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Fetching:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Resolving.."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Making BVH"
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Connecting.."
+msgstr "Menyambungkan.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Requesting.."
+msgstr "Menguji"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Error making request"
+msgstr "Error menyimpan resource!"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Idle"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Light Octree"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Retry"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Octree Texture"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download Error"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Transfer to Lightmaps:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download for this asset is already in progress!"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Allocating Texture #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "first"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Baking Triangle #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "prev"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Post-Processing Texture #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "next"
msgstr ""
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Bake!"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "last"
msgstr ""
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Reset the lightmap octree baking process (start over)."
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "All"
+msgstr "Semua"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Plugins"
msgstr ""
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Sort:"
+msgstr "Sortir:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Reverse"
+msgstr "Terbalik"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Category:"
+msgstr "Kategori:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Site:"
+msgstr "Situs:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Support.."
+msgstr "Dukungan.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Official"
+msgstr "Resmi"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Testing"
+msgstr "Menguji"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Assets ZIP File"
+msgstr "Aset-aset File ZIP"
+
#: editor/plugins/camera_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
msgid "Preview"
msgstr ""
@@ -3762,11 +3304,15 @@ msgid "Edit CanvasItem"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Change Anchors"
+msgid "Anchors only"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom (%):"
+msgid "Change Anchors and Margins"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Change Anchors"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3817,59 +3363,73 @@ msgid "Pan Mode"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Lock the selected object in place (can't be moved)."
+#, fuzzy
+msgid "Toggles snapping"
+msgstr "Beralih Breakpoint"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Use Snap"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Unlock the selected object (can be moved)."
+msgid "Snapping options"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Makes sure the object's children are not selectable."
+msgid "Snap to grid"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Restores the object's children's ability to be selected."
+msgid "Use Rotation Snap"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Edit"
-msgstr "Edit"
+msgid "Configure Snap..."
+msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Use Snap"
+msgid "Snap Relative"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Show Grid"
+msgid "Use Pixel Snap"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Rotation Snap"
+msgid "Smart snapping"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap Relative"
+msgid "Snap to parent"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Configure Snap.."
+msgid "Snap to node anchor"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Pixel Snap"
+msgid "Snap to node sides"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to other nodes"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Lock the selected object in place (can't be moved)."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Unlock the selected object (can be moved)."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Makes sure the object's children are not selectable."
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Skeleton.."
+msgid "Restores the object's children's ability to be selected."
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3898,11 +3458,16 @@ msgid "View"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Reset"
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Show Grid"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Set.."
+msgid "Show helpers"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Show rulers"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3914,8 +3479,9 @@ msgid "Frame Selection"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Anchor"
-msgstr ""
+#, fuzzy
+msgid "Layout"
+msgstr "Simpan Penampilan"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Insert Keys"
@@ -3938,11 +3504,20 @@ msgid "Clear Pose"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Set a Value"
+msgid "Drag pivot from mouse position"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#, fuzzy
+msgid "Set pivot at mouse position"
+msgstr "Hapus Sinyal"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Multiply grid step by 2"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap (Pixels):"
+msgid "Divide grid step by 2"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3953,23 +3528,28 @@ msgstr ""
msgid "Adding %s..."
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Create Node"
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Error instancing scene from %s"
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "OK :("
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "No parent to instance a child at."
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "This operation requires a single selected node."
msgstr ""
@@ -3984,45 +3564,6 @@ msgid ""
"Drag & drop + Alt : Change node type"
msgstr ""
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Create Poly"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly (Remove Point)"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Create a new polygon from scratch."
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-msgid ""
-"Edit existing polygon:\n"
-"LMB: Move Point.\n"
-"Ctrl+LMB: Split Segment.\n"
-"RMB: Erase Point."
-msgstr ""
-
#: editor/plugins/collision_polygon_editor_plugin.cpp
msgid "Create Poly3D"
msgstr ""
@@ -4032,14 +3573,6 @@ msgid "Set Handle"
msgstr ""
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Creating Mesh Library"
-msgstr ""
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Thumbnail.."
-msgstr ""
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Remove item %d?"
msgstr ""
@@ -4062,6 +3595,27 @@ msgid "Update from Scene"
msgstr ""
#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat0"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat1"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+#, fuzzy
+msgid "Ease in"
+msgstr "Beri Skala Seleksi"
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Ease out"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Smoothstep"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
msgid "Modify Curve Point"
msgstr ""
@@ -4141,22 +3695,18 @@ msgid "Create Occluder Polygon"
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Edit existing polygon:"
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "LMB: Move Point."
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Ctrl+LMB: Split Segment."
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "RMB: Erase Point."
msgstr ""
@@ -4258,6 +3808,10 @@ msgid "Create Outline"
msgstr ""
#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Mesh"
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Create Trimesh Static Body"
msgstr ""
@@ -4385,12 +3939,73 @@ msgstr ""
msgid "Populate"
msgstr ""
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Create Navigation Polygon"
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake!"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake the navigation mesh.\n"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Clear the navigation mesh."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Setting up Configuration..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Calculating grid size..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating heightfield..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Marking walkable triangles..."
+msgstr "Menyimpan perubahan-perubahan lokal.."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Constructing compact heightfield..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Eroding walkable area..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Partitioning..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating contours..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating polymesh..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Converting to native navigation mesh..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Navigation Mesh Generator Setup:"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Parsing Geometry..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Done!"
msgstr ""
#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Remove Poly And Point"
+msgid "Create Navigation Polygon"
msgstr ""
#: editor/plugins/particles_2d_editor_plugin.cpp
@@ -4408,7 +4023,7 @@ msgstr ""
#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Error loading image:"
-msgstr ""
+msgstr "Galat saat memuat gambar:"
#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "No pixels with transparency > 128 in image.."
@@ -4429,7 +4044,7 @@ msgstr ""
#: editor/plugins/particles_2d_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp
msgid "Particles"
-msgstr ""
+msgstr "Partikel"
#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Generated Point Count:"
@@ -4564,16 +4179,19 @@ msgid "Curve Point #"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve Point Position"
-msgstr ""
+msgstr "Hapus Sinyal"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve In Position"
-msgstr ""
+msgstr "Hapus Sinyal"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve Out Position"
-msgstr ""
+msgstr "Hapus Sinyal"
#: editor/plugins/path_editor_plugin.cpp
msgid "Split Path"
@@ -4633,6 +4251,14 @@ msgid "Scale Polygon"
msgstr ""
#: editor/plugins/polygon_2d_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Edit"
+msgstr "Edit"
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Polygon->UV"
msgstr ""
@@ -4687,63 +4313,10 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/shader_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "Tempel"
-#: editor/plugins/rich_text_editor_plugin.cpp
-msgid "Parse BBCode"
-msgstr ""
-
-#: editor/plugins/sample_editor_plugin.cpp
-msgid "Length:"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Open Sample File(s)"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "ERROR: Couldn't load sample!"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Add Sample"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Rename Sample"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Delete Sample"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "16 Bits"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "8 Bits"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Stereo"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Mono"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Format"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Pitch"
-msgstr ""
-
#: editor/plugins/script_editor_plugin.cpp
msgid "Clear Recent Files"
msgstr ""
@@ -4792,15 +4365,15 @@ msgstr ""
#: editor/plugins/script_editor_plugin.cpp
msgid "File"
-msgstr ""
+msgstr "Berkas"
#: editor/plugins/script_editor_plugin.cpp editor/property_editor.cpp
msgid "New"
-msgstr ""
+msgstr "Baru"
#: editor/plugins/script_editor_plugin.cpp
msgid "Save All"
-msgstr ""
+msgstr "Simpan Semua"
#: editor/plugins/script_editor_plugin.cpp
msgid "Soft Reload Script"
@@ -4816,24 +4389,27 @@ msgstr ""
#: editor/plugins/script_editor_plugin.cpp
msgid "Reload Theme"
-msgstr ""
+msgstr "Muat Ulang Tema"
#: editor/plugins/script_editor_plugin.cpp
msgid "Save Theme"
-msgstr ""
+msgstr "Simpan Tema"
#: editor/plugins/script_editor_plugin.cpp
msgid "Save Theme As"
-msgstr ""
+msgstr "Simpan Tema Sebagai"
#: editor/plugins/script_editor_plugin.cpp
msgid "Close Docs"
-msgstr ""
+msgstr "Tutup Dokumentasi"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Close All"
-msgstr "Tutup"
+msgstr "Tutup Semua"
+
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+msgid "Run"
+msgstr "Jalankan"
#: editor/plugins/script_editor_plugin.cpp
#, fuzzy
@@ -4844,13 +4420,13 @@ msgstr "Beralih Favorit"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Find.."
-msgstr ""
+msgstr "Cari.."
#: editor/plugins/script_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Find Next"
-msgstr ""
+msgstr "Pencarian Selanjutnya"
#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
msgid "Step Over"
@@ -4864,7 +4440,8 @@ msgstr ""
msgid "Break"
msgstr ""
-#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+#: editor/script_editor_debugger.cpp
msgid "Continue"
msgstr ""
@@ -4878,18 +4455,6 @@ msgid "Debug with external editor"
msgstr "Editor Ketergantungan"
#: editor/plugins/script_editor_plugin.cpp
-msgid "Window"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Left"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Right"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
msgid "Open Godot online documentation"
msgstr ""
@@ -4972,8 +4537,9 @@ msgid "Cut"
msgstr "Potong"
#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "Kopy"
@@ -5238,60 +4804,52 @@ msgid "View Plane Transform."
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Scaling to %s%%."
-msgstr ""
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rotating %s degrees."
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Bottom View."
-msgstr ""
+msgstr "Tampilan Bawah."
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Bottom"
-msgstr ""
+msgstr "Bawah"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Top View."
-msgstr ""
-
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Top"
-msgstr ""
+msgstr "Tampilan Atas."
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rear View."
-msgstr ""
+msgstr "Tampilan Belakang."
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rear"
-msgstr ""
+msgstr "Belakang"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Front View."
-msgstr ""
+msgstr "Tampilan Depan."
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Front"
-msgstr ""
+msgstr "Depan"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Left View."
-msgstr ""
+msgstr "Tampilan Kiri."
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Left"
-msgstr ""
+msgstr "Kiri"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Right View."
-msgstr ""
+msgstr "Tampilan Kanan."
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Right"
-msgstr ""
+msgstr "Kanan"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Keying is disabled (no key inserted)."
@@ -5498,6 +5056,10 @@ msgid "Transform"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Configure Snap.."
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Local Coords"
msgstr ""
@@ -5643,6 +5205,10 @@ msgid "Speed (FPS):"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Loop"
+msgstr ""
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Animation Frames"
msgstr ""
@@ -5655,11 +5221,12 @@ msgid "Insert Empty (After)"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Up"
-msgstr ""
+#, fuzzy
+msgid "Move (Before)"
+msgstr "Salin Resource"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Down"
+msgid "Move (After)"
msgstr ""
#: editor/plugins/style_box_editor_plugin.cpp
@@ -5738,7 +5305,11 @@ msgid "Remove All"
msgstr "Hapus"
#: editor/plugins/theme_editor_plugin.cpp
-msgid "Theme"
+msgid "Edit theme.."
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Theme editing menu."
msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
@@ -5816,16 +5387,20 @@ msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
msgid "Icon"
-msgstr ""
+msgstr "Ikon"
#: editor/plugins/theme_editor_plugin.cpp
msgid "Style"
msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
-msgid "Color"
+msgid "Font"
msgstr ""
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Color"
+msgstr "Warna"
+
#: editor/plugins/tile_map_editor_plugin.cpp
#, fuzzy
msgid "Erase Selection"
@@ -5873,7 +5448,7 @@ msgid "Mirror Y"
msgstr ""
#: editor/plugins/tile_map_editor_plugin.cpp
-msgid "Bucket"
+msgid "Paint Tile"
msgstr ""
#: editor/plugins/tile_map_editor_plugin.cpp
@@ -5940,6 +5515,10 @@ msgid "Delete preset '%s'?"
msgstr "Hapus file yang dipilih?"
#: editor/project_export.cpp
+msgid "Export templates for this platform are missing/corrupted: "
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Presets"
msgstr ""
@@ -6012,20 +5591,31 @@ msgid "Export templates for this platform are missing:"
msgstr ""
#: editor/project_export.cpp
+msgid "Export templates for this platform are missing/corrupted:"
+msgstr ""
+
+#: editor/project_export.cpp
#, fuzzy
msgid "Export With Debug"
msgstr "Ekspor Tile Set"
#: editor/project_manager.cpp
-msgid "Invalid project path, the path must exist!"
+#, fuzzy
+msgid "The path does not exist."
+msgstr "File tidak ada."
+
+#: editor/project_manager.cpp
+msgid "Please choose a 'project.godot' file."
msgstr ""
#: editor/project_manager.cpp
-msgid "Invalid project path, project.godot must not exist."
+msgid ""
+"Your project will be created in a non empty folder (you might want to create "
+"a new folder)."
msgstr ""
#: editor/project_manager.cpp
-msgid "Invalid project path, project.godot must exist."
+msgid "Please choose a folder that does not contain a 'project.godot' file."
msgstr ""
#: editor/project_manager.cpp
@@ -6033,47 +5623,74 @@ msgid "Imported Project"
msgstr ""
#: editor/project_manager.cpp
-msgid "Invalid project path (changed anything?)."
+msgid " "
msgstr ""
#: editor/project_manager.cpp
-msgid "Couldn't create project.godot in project path."
+msgid "It would be a good idea to name your project."
msgstr ""
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
+msgid "Invalid project path (changed anything?)."
msgstr ""
#: editor/project_manager.cpp
-msgid "Import Existing Project"
+msgid "Couldn't get project.godot in project path."
msgstr ""
#: editor/project_manager.cpp
-msgid "Project Path (Must Exist):"
+msgid "Couldn't edit project.godot in project path."
msgstr ""
#: editor/project_manager.cpp
-msgid "Project Name:"
+msgid "Couldn't create project.godot in project path."
msgstr ""
#: editor/project_manager.cpp
-msgid "Create New Project"
+msgid "The following files failed extraction from package:"
msgstr ""
#: editor/project_manager.cpp
-msgid "Project Path:"
+#, fuzzy
+msgid "Rename Project"
+msgstr "Projek Baru Permainan"
+
+#: editor/project_manager.cpp
+msgid "Couldn't get project.godot in the project path."
msgstr ""
#: editor/project_manager.cpp
+#, fuzzy
+msgid "New Game Project"
+msgstr "Projek Baru Permainan"
+
+#: editor/project_manager.cpp
+msgid "Import Existing Project"
+msgstr "Impor Projek yang Sudah Ada"
+
+#: editor/project_manager.cpp
+msgid "Create New Project"
+msgstr "Buat Projek Baru"
+
+#: editor/project_manager.cpp
msgid "Install Project:"
msgstr ""
#: editor/project_manager.cpp
-msgid "Browse"
-msgstr ""
+msgid "Project Name:"
+msgstr "Nama Projek:"
#: editor/project_manager.cpp
-msgid "New Game Project"
+#, fuzzy
+msgid "Create folder"
+msgstr "Buat Folder"
+
+#: editor/project_manager.cpp
+msgid "Project Path:"
+msgstr "Lokasi Projek:"
+
+#: editor/project_manager.cpp
+msgid "Browse"
msgstr ""
#: editor/project_manager.cpp
@@ -6085,8 +5702,14 @@ msgid "Unnamed Project"
msgstr ""
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Can't open project"
+msgstr "Menyambungkan.."
+
+#: editor/project_manager.cpp
+#, fuzzy
msgid "Are you sure to open more than one project?"
-msgstr ""
+msgstr "Apakah Anda yakin membuka lebih dari satu projek?"
#: editor/project_manager.cpp
#, fuzzy
@@ -6106,8 +5729,9 @@ msgid ""
msgstr ""
#: editor/project_manager.cpp
+#, fuzzy
msgid "Are you sure to run more than one project?"
-msgstr ""
+msgstr "Apakah Anda yakin menjalankan lebih dari satu projek?"
#: editor/project_manager.cpp
msgid "Remove project from the list? (Folder contents will not be modified)"
@@ -6115,29 +5739,31 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
-"You are about the scan %s folders for existing Godot projects. Do you "
-"confirm?"
+"Language changed.\n"
+"The UI will update next time the editor or project manager starts."
msgstr ""
#: editor/project_manager.cpp
-msgid "Project List"
+msgid ""
+"You are about the scan %s folders for existing Godot projects. Do you "
+"confirm?"
msgstr ""
#: editor/project_manager.cpp
-msgid "Run"
-msgstr ""
+msgid "Project List"
+msgstr "Daftar Projek"
#: editor/project_manager.cpp
msgid "Scan"
-msgstr ""
+msgstr "Pindai"
#: editor/project_manager.cpp
msgid "Select a Folder to Scan"
-msgstr ""
+msgstr "Pilih Berkas untuk Dipindai"
#: editor/project_manager.cpp
msgid "New Project"
-msgstr ""
+msgstr "Projek Baru"
#: editor/project_manager.cpp
#, fuzzy
@@ -6146,6 +5772,10 @@ msgstr "Hapus Pilihan"
#: editor/project_manager.cpp
msgid "Exit"
+msgstr "Keluar"
+
+#: editor/project_manager.cpp
+msgid "Restart Now"
msgstr ""
#: editor/project_manager.cpp
@@ -6186,17 +5816,14 @@ msgid "Add Input Action Event"
msgstr ""
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Meta+"
msgstr "Meta+"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Shift+"
msgstr "Shift+"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Alt+"
msgstr "Alt+"
@@ -6257,7 +5884,7 @@ msgstr "Ubah"
msgid "Joypad Axis Index:"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Axis"
msgstr "Axis"
@@ -6277,32 +5904,32 @@ msgstr ""
msgid "Add Event"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Device"
msgstr "Perangkat"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Button"
msgstr "Tombol"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Left Button."
msgstr "Tombol Kiri."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Right Button."
msgstr "Tombol Kanan."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Middle Button."
msgstr "Tombol Tengah."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
#, fuzzy
msgid "Wheel Up."
msgstr "Scroll keatas."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
#, fuzzy
msgid "Wheel Down."
msgstr "Scroll kebawah."
@@ -6313,7 +5940,7 @@ msgid "Add Global Property"
msgstr "Tambahkan Properti Getter"
#: editor/project_settings_editor.cpp
-msgid "Select an setting item first!"
+msgid "Select a setting item first!"
msgstr ""
#: editor/project_settings_editor.cpp
@@ -6331,6 +5958,15 @@ msgid "Delete Item"
msgstr "Hapus"
#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Can't contain '/' or ':'"
+msgstr "Sambungkan Ke Node:"
+
+#: editor/project_settings_editor.cpp
+msgid "Already existing"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "Error saving settings."
msgstr ""
@@ -6371,6 +6007,15 @@ msgid "Remove Resource Remap Option"
msgstr ""
#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Changed Locale Filter"
+msgstr "Ganti Ukuran Kamera"
+
+#: editor/project_settings_editor.cpp
+msgid "Changed Locale Filter Mode"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "Project Settings (project.godot)"
msgstr ""
@@ -6431,6 +6076,27 @@ msgid "Locale"
msgstr ""
#: editor/project_settings_editor.cpp
+msgid "Locales Filter"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Show all locales"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Show only selected locales"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Filter mode:"
+msgstr "Filter:"
+
+#: editor/project_settings_editor.cpp
+msgid "Locales:"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "AutoLoad"
msgstr ""
@@ -6460,7 +6126,7 @@ msgstr ""
#: editor/property_editor.cpp
msgid "File.."
-msgstr ""
+msgstr "Berkas.."
#: editor/property_editor.cpp
msgid "Dir.."
@@ -6481,12 +6147,24 @@ msgid "New Script"
msgstr "Scene Baru"
#: editor/property_editor.cpp
+#, fuzzy
+msgid "Make Unique"
+msgstr "Membuat sub-Resource Unik"
+
+#: editor/property_editor.cpp
+#, fuzzy
msgid "Show in File System"
-msgstr ""
+msgstr "Tampilkan dalam Manajer Berkas"
#: editor/property_editor.cpp
+#, fuzzy
+msgid "Convert To %s"
+msgstr "Sambungkan Ke Node:"
+
+#: editor/property_editor.cpp
+#, fuzzy
msgid "Error loading file: Not a resource!"
-msgstr ""
+msgstr "Gagal saat memuat berkas: Bukan berkas resource!"
#: editor/property_editor.cpp
msgid "Selected node is not a Viewport!"
@@ -6524,6 +6202,11 @@ msgstr "Tambahkan Properti Setter"
#: editor/property_selector.cpp
#, fuzzy
+msgid "Select Virtual Method"
+msgstr "Metode Publik:"
+
+#: editor/property_selector.cpp
+#, fuzzy
msgid "Select Method"
msgstr "Metode Publik:"
@@ -6551,26 +6234,6 @@ msgstr ""
msgid "Reparent"
msgstr ""
-#: editor/resources_dock.cpp
-msgid "Create New Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Open Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Save Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Resource Tools"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Make Local"
-msgstr ""
-
#: editor/run_settings_dialog.cpp
msgid "Run Mode:"
msgstr ""
@@ -6698,14 +6361,6 @@ msgid "Sub-Resources:"
msgstr "Resource"
#: editor/scene_tree_dock.cpp
-msgid "Edit Groups"
-msgstr ""
-
-#: editor/scene_tree_dock.cpp
-msgid "Edit Connections"
-msgstr ""
-
-#: editor/scene_tree_dock.cpp
msgid "Clear Inheritance"
msgstr ""
@@ -6894,6 +6549,15 @@ msgid "Invalid base path"
msgstr ""
#: editor/script_create_dialog.cpp
+msgid "Directory of the same name exists"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
+#, fuzzy
+msgid "File exists, will be reused"
+msgstr "File telah ada, Overwrite?"
+
+#: editor/script_create_dialog.cpp
msgid "Invalid extension"
msgstr ""
@@ -6937,6 +6601,10 @@ msgid "Load existing script file"
msgstr ""
#: editor/script_create_dialog.cpp
+msgid "Language"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
#, fuzzy
msgid "Inherits"
msgstr "Turunan:"
@@ -6981,6 +6649,10 @@ msgid "Function:"
msgstr ""
#: editor/script_editor_debugger.cpp
+msgid "Pick one or more items from the list to display the graph."
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
msgid "Errors"
msgstr ""
@@ -7061,6 +6733,10 @@ msgid "Type"
msgstr ""
#: editor/script_editor_debugger.cpp
+msgid "Format"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
msgid "Usage"
msgstr ""
@@ -7139,13 +6815,30 @@ msgstr ""
msgid "Change Probe Extents"
msgstr ""
+#: modules/gdnative/gd_native_library_editor.cpp
+#, fuzzy
+msgid "Library"
+msgstr "Ekspor Pustaka"
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Status"
+msgstr ""
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Libraries: "
+msgstr ""
+
+#: modules/gdnative/register_types.cpp
+msgid "GDNative"
+msgstr ""
+
#: modules/gdscript/gd_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Invalid type argument to convert(), use TYPE_* constants."
msgstr ""
"Tipe argument salah dalam menggunakan convert(), gunakan konstanta TYPE_*."
-#: modules/gdscript/gd_functions.cpp
+#: modules/gdscript/gd_functions.cpp modules/mono/glue/glue_header.h
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Not enough bytes for decoding bytes, or invalid format."
msgstr "Tidak cukup bytes untuk menerjemahkan, atau format tidak sah."
@@ -7197,10 +6890,6 @@ msgid "GridMap Duplicate Selection"
msgstr "Duplikat Pilihan"
#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "GridMap Paint"
-msgstr ""
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Snap View"
msgstr ""
@@ -7296,13 +6985,8 @@ msgstr ""
msgid "Pick Distance:"
msgstr ""
-#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
-msgid "Tiles"
-msgstr "File:"
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "Areas"
+#: modules/mono/editor/mono_bottom_panel.cpp
+msgid "Builds"
msgstr ""
#: modules/visual_script/visual_script.cpp
@@ -7514,10 +7198,18 @@ msgid "Return"
msgstr "Kembali:"
#: modules/visual_script/visual_script_editor.cpp
+msgid "Call"
+msgstr "Panggil"
+
+#: modules/visual_script/visual_script_editor.cpp
msgid "Get"
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
+msgid "Script already has function '%s'"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
#, fuzzy
msgid "Change Input Value"
msgstr "Ubah Nilai Array"
@@ -7940,13 +7632,24 @@ msgstr ""
"Sebuah resource SpriteFrames harus diciptakan atau diatur didalam properti "
"'Frames' agar AnimatedSprite3D menampilkan frame-frame."
+#: scene/3d/vehicle_body.cpp
+msgid ""
+"VehicleWheel serves to provide a wheel system to a VehicleBody. Please use "
+"it as a child of a VehicleBody."
+msgstr ""
+
#: scene/gui/color_picker.cpp
msgid "Raw Mode"
msgstr ""
#: scene/gui/color_picker.cpp
+#, fuzzy
msgid "Add current color as a preset"
-msgstr ""
+msgstr "Tambah warna sekarang sebagai preset"
+
+#: scene/gui/dialogs.cpp
+msgid "Cancel"
+msgstr "Batal"
#: scene/gui/dialogs.cpp
msgid "Alert!"
@@ -7956,10 +7659,6 @@ msgstr "Peringatan!"
msgid "Please Confirm..."
msgstr "Mohon konfirmasi..."
-#: scene/gui/input_action.cpp
-msgid "Ctrl+"
-msgstr "Ctrl+"
-
#: scene/gui/popup.cpp
msgid ""
"Popups will hide by default unless you call popup() or any of the popup*() "
@@ -7978,10 +7677,13 @@ msgid ""
msgstr ""
#: scene/main/scene_tree.cpp
+#, fuzzy
msgid ""
"Default Environment as specified in Project Setings (Rendering -> Viewport -"
"> Default Environment) could not be loaded."
msgstr ""
+"Lingkungan Baku yang ditetapkan di Pengaturan Proyek (Rendering -> Viewport -"
+"> Lingkungan Baku) tidak dapat dimuat"
#: scene/main/viewport.cpp
#, fuzzy
@@ -7997,6 +7699,105 @@ msgstr ""
"sebuah RenderTarget dan tetapkannya tekstur internal untuk beberapa node "
"untuk ditampilkan."
+#: scene/resources/dynamic_font.cpp
+msgid "Error initializing FreeType."
+msgstr "Error menginisialisasi FreeType."
+
+#: scene/resources/dynamic_font.cpp
+msgid "Unknown font format."
+msgstr "Format font tidak diketahui."
+
+#: scene/resources/dynamic_font.cpp
+msgid "Error loading font."
+msgstr "Error memuat font."
+
+#: scene/resources/dynamic_font.cpp
+msgid "Invalid font size."
+msgstr "Ukuran font tidak sah."
+
+#~ msgid "Filter:"
+#~ msgstr "Filter:"
+
+#~ msgid "Method List For '%s':"
+#~ msgstr "Daftar Fungsi Untuk '%s':"
+
+#~ msgid "Arguments:"
+#~ msgstr "Argumen:"
+
+#, fuzzy
+#~ msgid "Return:"
+#~ msgstr "Kembali:"
+
+#~ msgid "Added:"
+#~ msgstr "Ditambahkan:"
+
+#~ msgid "Removed:"
+#~ msgstr "Dihapus:"
+
+#~ msgid "Error saving atlas:"
+#~ msgstr "Gagal menyimpan atlas:"
+
+#~ msgid "Could not save atlas subtexture:"
+#~ msgstr "Tidak dapat menyimpan sub tekstur atlas:"
+
+#~ msgid "Exporting for %s"
+#~ msgstr "Mengekspor untuk %s"
+
+#~ msgid "Setting Up.."
+#~ msgstr "Mengatur.."
+
+#~ msgid "Error loading scene."
+#~ msgstr "Gagal memuat scene."
+
+#~ msgid "Re-Import"
+#~ msgstr "Impor Ulang"
+
+#~ msgid "Re-Importing"
+#~ msgstr "Mengimpor ulang"
+
+#~ msgid "Loading Export Templates"
+#~ msgstr "Memuat Ekspor Template-template."
+
+#, fuzzy
+#~ msgid "Error moving file:\n"
+#~ msgstr "Error menyimpan TileSet!"
+
+#~ msgid "Pick New Name and Location For:"
+#~ msgstr "Tentukan Nama dan Lokasi Baru untuk:"
+
+#~ msgid "No files selected!"
+#~ msgstr "Tidak ada berkas dipilih!"
+
+#~ msgid "Re-Import.."
+#~ msgstr "Impor Ulang.."
+
+#, fuzzy
+#~ msgid "Root Node Name:"
+#~ msgstr "Nama Node:"
+
+#~ msgid "Texture Format"
+#~ msgstr "Format Tekstur"
+
+#, fuzzy
+#~ msgid "Texture Options"
+#~ msgstr "Opsi Tekstur"
+
+#~ msgid "Error importing:"
+#~ msgstr "Galat saat mengimpor:"
+
+#~ msgid "Max Texture Size:"
+#~ msgstr "Ukuran Tekstur Maksimum:"
+
+#~ msgid "Project Path (Must Exist):"
+#~ msgstr "Lokasi Projek (Harus Ada):"
+
+#, fuzzy
+#~ msgid "Tiles"
+#~ msgstr "File:"
+
+#~ msgid "Ctrl+"
+#~ msgstr "Ctrl+"
+
#~ msgid "Close scene? (Unsaved changes will be lost)"
#~ msgstr "Tutup scene? (Perubahan-perubahan yang belum disimpan akan hilang)"
diff --git a/editor/translations/it.po b/editor/translations/it.po
index 060e9551e0..45c48d6ac4 100644
--- a/editor/translations/it.po
+++ b/editor/translations/it.po
@@ -1,8 +1,11 @@
# Italian translation of the Godot Engine editor
-# Copyright (C) 2016-2017 Juan Linietsky, Ariel Manzur and the Godot community
+# Copyright (C) 2007-2017 Juan Linietsky, Ariel Manzur
+# Copyright (C) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)
# This file is distributed under the same license as the Godot source code.
#
# Dario Bonfanti <bonfi.96@hotmail.it>, 2016-2017.
+# dariocavada <cavada@ectrlsolutions.com>, 2017.
+# Giovanni Solimeno (Crax97) <gsolimeno97@gmail.com>, 2017.
# Marco Melorio <m.melorio@icloud.com>, 2017.
# RealAquilus <JamesHeller@live.it>, 2017.
#
@@ -10,7 +13,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2017-08-21 16:46+0000\n"
+"PO-Revision-Date: 2017-10-23 16:46+0000\n"
"Last-Translator: Dario Bonfanti <bonfi.96@hotmail.it>\n"
"Language-Team: Italian <https://hosted.weblate.org/projects/godot-engine/"
"godot/it/>\n"
@@ -19,7 +22,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 2.17-dev\n"
+"X-Generator: Weblate 2.17\n"
#: editor/animation_editor.cpp
msgid "Disabled"
@@ -195,10 +198,9 @@ msgid "Create %d NEW tracks and insert keys?"
msgstr "Creare %d NUOVE tracce e inserire key?"
#: editor/animation_editor.cpp editor/create_dialog.cpp
-#: editor/editor_audio_buses.cpp
+#: editor/editor_audio_buses.cpp editor/plugins/abstract_polygon_2d_editor.cpp
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
#: editor/plugins/mesh_instance_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp editor/project_manager.cpp
#: editor/script_create_dialog.cpp
msgid "Create"
@@ -361,261 +363,6 @@ msgstr "Cambia Tipo del Valore Array"
msgid "Change Array Value"
msgstr "Cambia Valore Array"
-#: editor/asset_library_editor_plugin.cpp
-msgid "Free"
-msgstr "Gratuito"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_plugin_settings.cpp
-msgid "Version:"
-msgstr "Versione:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Contents:"
-msgstr "Contenuti:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "View Files"
-msgstr "Vedi Files"
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_help.cpp editor/property_selector.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Description:"
-msgstr "Descrizione:"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-#: editor/project_manager.cpp
-msgid "Install"
-msgstr "Installa"
-
-#: editor/asset_library_editor_plugin.cpp editor/call_dialog.cpp
-#: editor/connections_dialog.cpp editor/export_template_manager.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-#: editor/project_settings_editor.cpp editor/property_editor.cpp
-#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Close"
-msgstr "Chiudi"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve hostname:"
-msgstr "Impossibile risolvere l'hostname:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve."
-msgstr "Impossibile risolvete."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Connection error, please try again."
-msgstr "Errore di connessione, si prega di riprovare."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't connect."
-msgstr "Impossibile connettersi."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't connect to host:"
-msgstr "Impossibile connetersi all'host:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response from host:"
-msgstr "Nessuna risposta dall'host:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response."
-msgstr "Nessuna risposta."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Request failed, return code:"
-msgstr "Richiesta fallita, codice di return:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Req. Failed."
-msgstr "Rich. Fall."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Request failed, too many redirects"
-msgstr "Richiesta fallita, troppi ridirezionamenti"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Redirect Loop."
-msgstr "Ridirigi Loop."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed:"
-msgstr "Fallito:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Bad download hash, assuming file has been tampered with."
-msgstr "Hash di download non buono, si presume il file sia stato manipolato."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Expected:"
-msgstr "Previsto:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Got:"
-msgstr "Ottenuto:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
-msgstr "Check hash sha256 fallito"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Asset Download Error:"
-msgstr "Errore di Download Asset:"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-msgid "Success!"
-msgstr "Successo!"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Fetching:"
-msgstr "Recupero:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Resolving.."
-msgstr "Risolvendo.."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Connecting.."
-msgstr "Connettendo.."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Requesting.."
-msgstr "Richiedendo.."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Error making request"
-msgstr "Errore nel fare richiesta"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Idle"
-msgstr "Inattivo"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Retry"
-msgstr "Riprova"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Download Error"
-msgstr "Errore durante il download"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Download for this asset is already in progress!"
-msgstr "Il download per questo asset è già in corso!"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "first"
-msgstr "primo"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "prev"
-msgstr "prec"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "next"
-msgstr "seguente"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "last"
-msgstr "ultimo"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "All"
-msgstr "Tutti"
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
-#: editor/settings_config_dialog.cpp
-msgid "Search:"
-msgstr "Cerca:"
-
-#: editor/asset_library_editor_plugin.cpp editor/code_editor.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Search"
-msgstr "Cerca"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/project_manager.cpp
-msgid "Import"
-msgstr "Importa"
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Plugins"
-msgstr "Plugins"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Sort:"
-msgstr "Ordina:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Reverse"
-msgstr "Inverti"
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Category:"
-msgstr "Categoria:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Site:"
-msgstr "Sito:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Support.."
-msgstr "Supporta.."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Official"
-msgstr "Ufficiale"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-msgid "Community"
-msgstr "Comunità"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Testing"
-msgstr "Testing"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Assets ZIP File"
-msgstr "ZIP File degli Asset"
-
-#: editor/call_dialog.cpp
-msgid "Method List For '%s':"
-msgstr "Lista Metodi Per '%s':"
-
-#: editor/call_dialog.cpp modules/visual_script/visual_script_editor.cpp
-msgid "Call"
-msgstr "Chiama"
-
-#: editor/call_dialog.cpp
-msgid "Method List:"
-msgstr "Lista Metodi:"
-
-#: editor/call_dialog.cpp
-msgid "Arguments:"
-msgstr "Argomenti:"
-
-#: editor/call_dialog.cpp
-msgid "Return:"
-msgstr "Ritorna:"
-
#: editor/code_editor.cpp
msgid "Go to Line"
msgstr "Vai alla Linea"
@@ -652,6 +399,14 @@ msgstr "Parole Intere"
msgid "Selection Only"
msgstr "Solo Selezione"
+#: editor/code_editor.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
+msgid "Search"
+msgstr "Cerca"
+
#: editor/code_editor.cpp editor/editor_help.cpp
msgid "Find"
msgstr "Trova"
@@ -684,11 +439,11 @@ msgstr "Richiedi Per Sostituire"
msgid "Skip"
msgstr "Salta"
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom In"
msgstr "Zoom In"
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom Out"
msgstr "Zoom Out"
@@ -757,6 +512,20 @@ msgstr "Differita"
msgid "Oneshot"
msgstr "Oneshot"
+#: editor/connections_dialog.cpp editor/dependency_editor.cpp
+#: editor/export_template_manager.cpp
+#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Close"
+msgstr "Chiudi"
+
#: editor/connections_dialog.cpp
msgid "Connect"
msgstr "Connetti"
@@ -782,7 +551,7 @@ msgstr "Connetti.."
msgid "Disconnect"
msgstr "Disconnetti"
-#: editor/connections_dialog.cpp editor/node_dock.cpp
+#: editor/connections_dialog.cpp editor/editor_help.cpp editor/node_dock.cpp
msgid "Signals"
msgstr "Segnali"
@@ -799,12 +568,25 @@ msgstr "Preferiti:"
msgid "Recent:"
msgstr "Recenti:"
+#: editor/create_dialog.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/quick_open.cpp editor/settings_config_dialog.cpp
+msgid "Search:"
+msgstr "Cerca:"
+
#: editor/create_dialog.cpp editor/editor_help.cpp
#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/quick_open.cpp
msgid "Matches:"
msgstr "Corrispondenze:"
+#: editor/create_dialog.cpp editor/editor_help.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/property_selector.cpp
+#: editor/script_editor_debugger.cpp
+msgid "Description:"
+msgstr "Descrizione:"
+
#: editor/dependency_editor.cpp
msgid "Search Replacement For:"
msgstr "Cerca Rimpiazzo Per:"
@@ -864,6 +646,10 @@ msgid "Owners Of:"
msgstr "Proprietari Di:"
#: editor/dependency_editor.cpp
+msgid "Remove selected files from the project? (no undo)"
+msgstr "Rimuovi i file selezionati dal progetto? (no undo)"
+
+#: editor/dependency_editor.cpp
msgid ""
"The files being removed are required by other resources in order for them to "
"work.\n"
@@ -874,8 +660,8 @@ msgstr ""
"Rimuoverli comunque? (no undo)"
#: editor/dependency_editor.cpp
-msgid "Remove selected files from the project? (no undo)"
-msgstr "Rimuovi i file selezionati dal progetto? (no undo)"
+msgid "Cannot remove:\n"
+msgstr "Impossibile rimouvere:\n"
#: editor/dependency_editor.cpp
msgid "Error loading:"
@@ -903,7 +689,7 @@ msgstr "Errori in caricamento!"
#: editor/dependency_editor.cpp
msgid "Permanently delete %d item(s)? (No undo!)"
-msgstr "Elimina permanentemente %d elementi? (No undo!)"
+msgstr "Eliminare permanentemente %d elementi? (No undo!)"
#: editor/dependency_editor.cpp
msgid "Owns"
@@ -911,7 +697,7 @@ msgstr "Possiede"
#: editor/dependency_editor.cpp
msgid "Resources Without Explicit Ownership:"
-msgstr "Risorse Senza Proprietà Esplicita:"
+msgstr "Risorse Non Possedute Esplicitamente:"
#: editor/dependency_editor.cpp editor/editor_node.cpp
msgid "Orphan Resource Explorer"
@@ -941,19 +727,12 @@ msgid "Godot Engine contributors"
msgstr "Contributori a Godot Engine"
#: editor/editor_about.cpp
-#, fuzzy
-msgid "Authors"
-msgstr "Autore:"
-
-#: editor/editor_about.cpp
-#, fuzzy
msgid "Project Founders"
-msgstr "Gestione Progetti"
+msgstr "Fondatori Progetto"
#: editor/editor_about.cpp
-#, fuzzy
msgid "Lead Developer"
-msgstr "Sviluppatori"
+msgstr "Lead Developer"
#: editor/editor_about.cpp editor/project_manager.cpp
msgid "Project Manager"
@@ -964,12 +743,44 @@ msgid "Developers"
msgstr "Sviluppatori"
#: editor/editor_about.cpp
+msgid "Authors"
+msgstr "Autori"
+
+#: editor/editor_about.cpp
+msgid "Platinum Sponsors"
+msgstr "Sponsors Platino"
+
+#: editor/editor_about.cpp
+msgid "Gold Sponsors"
+msgstr "Sponsors Oro"
+
+#: editor/editor_about.cpp
+msgid "Mini Sponsors"
+msgstr "Sponsors Mini"
+
+#: editor/editor_about.cpp
+msgid "Gold Donors"
+msgstr "Donatori Oro"
+
+#: editor/editor_about.cpp
+msgid "Silver Donors"
+msgstr "Sponsors Argento"
+
+#: editor/editor_about.cpp
+msgid "Bronze Donors"
+msgstr "Donatori Bronzo"
+
+#: editor/editor_about.cpp
+msgid "Donors"
+msgstr "Donatori"
+
+#: editor/editor_about.cpp
msgid "License"
-msgstr ""
+msgstr "Licenza"
#: editor/editor_about.cpp
msgid "Thirdparty License"
-msgstr ""
+msgstr "Licenza di Terze Parti"
#: editor/editor_about.cpp
msgid ""
@@ -978,104 +789,108 @@ msgid ""
"is an exhaustive list of all such thirdparty components with their "
"respective copyright statements and license terms."
msgstr ""
+"Godot Engine si appoggia su un numero di librerie gratuite ed open source, "
+"tutte compatibili con la licenza MIT. La seguente é una lista esaustiva di "
+"tali componenti di terze parti con le rispettive dichiarazioni di copyright "
+"e termini di licenza."
#: editor/editor_about.cpp
-#, fuzzy
msgid "All Components"
-msgstr "Contenuti:"
+msgstr "Tutte le Componenti"
#: editor/editor_about.cpp
-#, fuzzy
msgid "Components"
-msgstr "Contenuti:"
+msgstr "Componenti"
#: editor/editor_about.cpp
msgid "Licenses"
-msgstr ""
+msgstr "Licenze"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Error opening package file, not in zip format."
-msgstr ""
+msgstr "Errore nell'apertura del package, non in formato zip."
#: editor/editor_asset_installer.cpp
-#, fuzzy
msgid "Uncompressing Assets"
-msgstr "Decompressi"
+msgstr "Decompressione Assets"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package Installed Successfully!"
msgstr "Pacchetto Installato Con Successo!"
#: editor/editor_asset_installer.cpp
-#, fuzzy
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Success!"
+msgstr "Successo!"
+
+#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/project_manager.cpp
+msgid "Install"
+msgstr "Installa"
+
+#: editor/editor_asset_installer.cpp
msgid "Package Installer"
-msgstr "Pacchetto Installato Con Successo!"
+msgstr "Installer Pacchetto"
#: editor/editor_audio_buses.cpp
msgid "Speakers"
-msgstr ""
+msgstr "Altoparlanti"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Add Effect"
-msgstr "Aggiungi Evento"
+msgstr "Aggiungi Effetto"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Rename Audio Bus"
-msgstr "Apri Layout Audio Bus"
+msgstr "Rinomina Bus Audio"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Toggle Audio Bus Solo"
-msgstr "Apri Layout Audio Bus"
+msgstr "Imposta Bus Audio su Solo"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Toggle Audio Bus Mute"
-msgstr "Apri Layout Audio Bus"
+msgstr "Imposta Bus Audio su Mute"
#: editor/editor_audio_buses.cpp
msgid "Toggle Audio Bus Bypass Effects"
-msgstr ""
+msgstr "Imposta Audio Bus Bypassa Effetti"
#: editor/editor_audio_buses.cpp
msgid "Select Audio Bus Send"
-msgstr ""
+msgstr "Seleziona Bus Audio Invio"
#: editor/editor_audio_buses.cpp
msgid "Add Audio Bus Effect"
-msgstr ""
+msgstr "Aggiungi un effetto Bus Audio"
#: editor/editor_audio_buses.cpp
msgid "Move Bus Effect"
-msgstr ""
+msgstr "Sposta effetti bus"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Delete Bus Effect"
-msgstr "Elimina selezionati"
+msgstr "Cancella effetto bus"
#: editor/editor_audio_buses.cpp
msgid "Audio Bus, Drag and Drop to rearrange."
-msgstr ""
-
-#: editor/editor_audio_buses.cpp
-#, fuzzy
-msgid "Bus options"
-msgstr "Opzioni subscena"
+msgstr "Bus Audio, prendi e trascina per riordinare."
#: editor/editor_audio_buses.cpp
msgid "Solo"
-msgstr ""
+msgstr "Solo"
#: editor/editor_audio_buses.cpp
msgid "Mute"
-msgstr ""
+msgstr "Muto"
#: editor/editor_audio_buses.cpp
msgid "Bypass"
-msgstr ""
+msgstr "Bypassa"
+
+#: editor/editor_audio_buses.cpp
+msgid "Bus options"
+msgstr "Opzioni bus"
#: editor/editor_audio_buses.cpp editor/plugins/tile_map_editor_plugin.cpp
#: editor/scene_tree_dock.cpp
@@ -1083,33 +898,36 @@ msgid "Duplicate"
msgstr "duplica"
#: editor/editor_audio_buses.cpp
-#, fuzzy
+msgid "Reset Volume"
+msgstr "Ripristina Volume"
+
+#: editor/editor_audio_buses.cpp
msgid "Delete Effect"
-msgstr "Elimina selezionati"
+msgstr "Elimina Effetto"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Add Audio Bus"
-msgstr "Aggiungi Bus"
+msgstr "Aggiungi Bus Audio"
#: editor/editor_audio_buses.cpp
msgid "Master bus can't be deleted!"
-msgstr ""
+msgstr "Il bus principale non può essere cancellato!"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Delete Audio Bus"
-msgstr "Elimina Layout"
+msgstr "Elimina bus audio"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Duplicate Audio Bus"
-msgstr "Duplica Animazione"
+msgstr "Duplica bus audio"
+
+#: editor/editor_audio_buses.cpp
+msgid "Reset Bus Volume"
+msgstr "Ripristina Volume del Bus"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Move Audio Bus"
-msgstr "Azione di spostamento"
+msgstr "Sposta bus audio"
#: editor/editor_audio_buses.cpp
msgid "Save Audio Bus Layout As.."
@@ -1117,40 +935,36 @@ msgstr "Salva Layout Bus Audio Come..."
#: editor/editor_audio_buses.cpp
msgid "Location for New Layout.."
-msgstr "Posizione per Nuovo Layout..."
+msgstr "Posizione per Nuovo Layout.."
#: editor/editor_audio_buses.cpp
msgid "Open Audio Bus Layout"
-msgstr "Apri Layout Audio Bus"
+msgstr "Apri Layout Bus Audio"
#: editor/editor_audio_buses.cpp
msgid "There is no 'res://default_bus_layout.tres' file."
-msgstr ""
+msgstr "Non esiste il file 'res://default_bus_layout.tres'."
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Invalid file, not an audio bus layout."
-msgstr ""
-"Estensione file invalida.\n"
-"Si prega di usare .font."
+msgstr "File non valido, non è un layout di tipo bus audio."
#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr "Aggiungi Bus"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Create a new Bus Layout."
-msgstr "Crea Nuova Risorsa"
+msgstr "Crea nuovo layout di tipo bus."
-#: editor/editor_audio_buses.cpp editor/script_create_dialog.cpp
+#: editor/editor_audio_buses.cpp editor/property_editor.cpp
+#: editor/script_create_dialog.cpp
msgid "Load"
msgstr "Carica"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Load an existing Bus Layout."
-msgstr "Carica una risorsa esistente dal disco e modificala."
+msgstr "Carica un layout esistente di tipo bus."
#: editor/editor_audio_buses.cpp
#: editor/plugins/animation_player_editor_plugin.cpp
@@ -1158,18 +972,16 @@ msgid "Save As"
msgstr "Salva Come"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Save this Bus Layout to a file."
-msgstr "Salva Layout Bus Audio Come..."
+msgstr "Salva questo layout di tipo bus in un file."
#: editor/editor_audio_buses.cpp editor/import_dock.cpp
-#, fuzzy
msgid "Load Default"
-msgstr "Default"
+msgstr "Carica predefiniti"
#: editor/editor_audio_buses.cpp
msgid "Load the default Bus Layout."
-msgstr ""
+msgstr "Carica il layout di tipo bus predefinito."
#: editor/editor_autoload_settings.cpp
msgid "Invalid name."
@@ -1242,7 +1054,7 @@ msgid "Rearrange Autoloads"
msgstr "Riordina gli Autoload"
#: editor/editor_autoload_settings.cpp editor/editor_file_dialog.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp scene/gui/file_dialog.cpp
+#: scene/gui/file_dialog.cpp
msgid "Path:"
msgstr "Percorso:"
@@ -1250,9 +1062,7 @@ msgstr "Percorso:"
msgid "Node Name:"
msgstr "Nome Nodo:"
-#: editor/editor_autoload_settings.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp editor/project_manager.cpp
+#: editor/editor_autoload_settings.cpp editor/project_manager.cpp
msgid "Name"
msgstr "Nome"
@@ -1277,27 +1087,27 @@ msgid "Updating scene.."
msgstr "Aggiornando la scena.."
#: editor/editor_dir_dialog.cpp
-#, fuzzy
msgid "Please select a base directory first"
-msgstr "Si prega di salvare prima la scena."
+msgstr "Si prega di selezionare prima una directory di base"
#: editor/editor_dir_dialog.cpp
msgid "Choose a Directory"
msgstr "Scegli una Directory"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Create Folder"
msgstr "Crea Cartella"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: editor/editor_plugin_settings.cpp editor/plugins/theme_editor_plugin.cpp
-#: editor/project_export.cpp scene/gui/file_dialog.cpp
+#: editor/editor_plugin_settings.cpp editor/filesystem_dock.cpp
+#: editor/plugins/theme_editor_plugin.cpp editor/project_export.cpp
+#: scene/gui/file_dialog.cpp
msgid "Name:"
msgstr "Nome:"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Could not create folder."
msgstr "Impossibile creare cartella."
@@ -1317,30 +1127,6 @@ msgstr "Impacchettando"
msgid "Template file not found:\n"
msgstr "File template non trovato:\n"
-#: editor/editor_export.cpp
-msgid "Added:"
-msgstr "Agginto:"
-
-#: editor/editor_export.cpp
-msgid "Removed:"
-msgstr "Rimosso:"
-
-#: editor/editor_export.cpp
-msgid "Error saving atlas:"
-msgstr "Errore di salvataggio dell'atlas:"
-
-#: editor/editor_export.cpp
-msgid "Could not save atlas subtexture:"
-msgstr "Impossibile salvare la substruttura dell'atlas:"
-
-#: editor/editor_export.cpp
-msgid "Exporting for %s"
-msgstr "Esportando per %s"
-
-#: editor/editor_export.cpp
-msgid "Setting Up.."
-msgstr "Impostando.."
-
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "File Exists, Overwrite?"
msgstr "File Esistente, Sovrascrivere?"
@@ -1425,6 +1211,10 @@ msgstr "Sposta Preferito Su"
msgid "Move Favorite Down"
msgstr "Sposta Preferito Giù"
+#: editor/editor_file_dialog.cpp
+msgid "Go to parent folder"
+msgstr "Vai nella cartella padre"
+
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Directories & Files:"
msgstr "Directory e File:"
@@ -1439,10 +1229,6 @@ msgid "File:"
msgstr "File:"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
-msgid "Filter:"
-msgstr "Filtro:"
-
-#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Must use a valid extension."
msgstr "Necessaria un'estensione valida."
@@ -1467,6 +1253,10 @@ msgstr "Lista Classi:"
msgid "Search Classes"
msgstr "Cerca Classi"
+#: editor/editor_help.cpp editor/plugins/spatial_editor_plugin.cpp
+msgid "Top"
+msgstr "Alto"
+
#: editor/editor_help.cpp editor/property_editor.cpp
msgid "Class:"
msgstr "Classe:"
@@ -1483,15 +1273,27 @@ msgstr "Ereditato da:"
msgid "Brief Description:"
msgstr "Breve Descrizione:"
+#: editor/editor_help.cpp
+msgid "Members"
+msgstr "Membri"
+
#: editor/editor_help.cpp modules/visual_script/visual_script_editor.cpp
msgid "Members:"
msgstr "Membri:"
#: editor/editor_help.cpp
+msgid "Public Methods"
+msgstr "Metodi Pubblici"
+
+#: editor/editor_help.cpp
msgid "Public Methods:"
msgstr "Metodi Pubblici:"
#: editor/editor_help.cpp
+msgid "GUI Theme Items"
+msgstr "Elementi Tema GUI"
+
+#: editor/editor_help.cpp
msgid "GUI Theme Items:"
msgstr "Elementi Tema GUI:"
@@ -1500,54 +1302,85 @@ msgid "Signals:"
msgstr "Segnali:"
#: editor/editor_help.cpp
-#, fuzzy
+msgid "Enumerations"
+msgstr "Enumerazioni"
+
+#: editor/editor_help.cpp
msgid "Enumerations:"
-msgstr "Animazioni"
+msgstr "Enumerazioni:"
#: editor/editor_help.cpp
msgid "enum "
-msgstr ""
+msgstr "enum "
+
+#: editor/editor_help.cpp
+msgid "Constants"
+msgstr "Costanti"
#: editor/editor_help.cpp
msgid "Constants:"
msgstr "Costanti:"
#: editor/editor_help.cpp
+msgid "Description"
+msgstr "Descrizione"
+
+#: editor/editor_help.cpp
+msgid "Properties"
+msgstr "Proprietà"
+
+#: editor/editor_help.cpp
msgid "Property Description:"
msgstr "Descrizione Proprietà:"
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this property. Please help us by "
+"[color=$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+"Al momento una descrizione per questa proprietà non esiste. Aiutaci [color="
+"$color][url=$url]aggiungendone una[/url][/color]!"
+
+#: editor/editor_help.cpp
+msgid "Methods"
+msgstr "Metodi"
+
+#: editor/editor_help.cpp
msgid "Method Description:"
msgstr "Descrizione Metodo:"
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this method. Please help us by [color="
+"$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+"Al momento una descrizione per questo metodo non esiste. Aiutaci [color="
+"$color][url=$url]aggiungendone una[/url][/color]!"
+
+#: editor/editor_help.cpp
msgid "Search Text"
msgstr "Cerca Testo"
#: editor/editor_log.cpp
-#, fuzzy
msgid "Output:"
-msgstr " Output:"
+msgstr "Output:"
#: editor/editor_log.cpp editor/plugins/animation_tree_editor_plugin.cpp
-#: editor/plugins/rich_text_editor_plugin.cpp editor/property_editor.cpp
-#: editor/script_editor_debugger.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/property_editor.cpp editor/script_editor_debugger.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Clear"
msgstr "Rimuovi"
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Error saving resource!"
msgstr "Errore salvando la Risorsa!"
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Save Resource As.."
msgstr "Salva Risorsa Come.."
-#: editor/editor_node.cpp editor/export_template_manager.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "I see.."
msgstr "Capisco.."
@@ -1564,6 +1397,26 @@ msgid "Error while saving."
msgstr "Errore durante il salvataggio."
#: editor/editor_node.cpp
+msgid "Can't open '%s'."
+msgstr "Impossibile aprire '%s'."
+
+#: editor/editor_node.cpp
+msgid "Error while parsing '%s'."
+msgstr "Errore durante l'elaborazione di '%s'."
+
+#: editor/editor_node.cpp
+msgid "Unexpected end of file '%s'."
+msgstr "Fine file '%s' non prevista."
+
+#: editor/editor_node.cpp
+msgid "Missing '%s' or its dependencies."
+msgstr "'%s' mancante o dipendenze mancanti."
+
+#: editor/editor_node.cpp
+msgid "Error while loading '%s'."
+msgstr "Errore durante il caricamento di '%s'."
+
+#: editor/editor_node.cpp
msgid "Saving Scene"
msgstr "Salvataggio Scena"
@@ -1576,9 +1429,9 @@ msgid "Creating Thumbnail"
msgstr "Creazione Miniature"
#: editor/editor_node.cpp
-#, fuzzy
msgid "This operation can't be done without a tree root."
-msgstr "Questa operazione non può essere eseguita senza una scena."
+msgstr ""
+"Questa operazione non può essere eseguita senza una radice dell'albero."
#: editor/editor_node.cpp
msgid ""
@@ -1624,6 +1477,46 @@ msgid "Restored default layout to base settings."
msgstr "Ripristinato il layout di default ai settaggi di base."
#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was imported, so it's not editable.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+"Questa risorsa appartiene a una scena che è stata importata, di conseguenza "
+"non è modificabile.\n"
+"Si consiglia di leggere la documentazione riguardante l'importazione delle "
+"scene per comprendere al meglio questo workflow."
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was instanced or inherited.\n"
+"Changes to it will not be kept when saving the current scene."
+msgstr ""
+"Questa risorsa appartiene a una scena istanziata o ereditata.\n"
+"Le modifiche ad essa non verranno mantenute salvando la scena corrente."
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource was imported, so it's not editable. Change its settings in the "
+"import panel and then re-import."
+msgstr ""
+"Questa risorsa è stata importata, non è quindi modificabile. Modificane le "
+"impostazioni nel pannello di importazione e re-importala."
+
+#: editor/editor_node.cpp
+msgid ""
+"This scene was imported, so changes to it will not be kept.\n"
+"Instancing it or inheriting will allow making changes to it.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+"Questa scena é stata importata, pertanto i cambiamenti ad essa non verranno "
+"mantenuti.\n"
+"Istanziarla o ereditarla consentirà di effettuare dei cambiamenti.\n"
+"Si conaiglia di leggere la documentazione relativa all'importazione delle "
+"scene per comprendere meglio questo workflow."
+
+#: editor/editor_node.cpp
msgid "Copy Params"
msgstr "Copia parametri"
@@ -1712,13 +1605,12 @@ msgid "Quick Open Script.."
msgstr "Apri Script Rapido.."
#: editor/editor_node.cpp
-#, fuzzy
msgid "Save & Close"
-msgstr "Salva un File"
+msgstr "Salva e Chiudi"
#: editor/editor_node.cpp
msgid "Save changes to '%s' before closing?"
-msgstr ""
+msgstr "Salvare le modifiche a '%s' prima di chiudere?"
#: editor/editor_node.cpp
msgid "Save Scene As.."
@@ -1749,9 +1641,8 @@ msgid "Export Tile Set"
msgstr "Esporta Tile Set"
#: editor/editor_node.cpp
-#, fuzzy
msgid "This operation can't be done without a selected node."
-msgstr "Questa operazione non può essere eseguita senza una scena."
+msgstr "Questa operazione non può essere eseguita senza un nodo selezionato."
#: editor/editor_node.cpp
msgid "Current scene not saved. Open anyway?"
@@ -1782,42 +1673,60 @@ msgid "Exit the editor?"
msgstr "Uscire dall'editor?"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Open Project Manager?"
-msgstr "Gestione Progetti"
+msgstr "Aprire Gestione Progetti?"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Save & Quit"
-msgstr "Salva un File"
+msgstr "Salva e Esci"
#: editor/editor_node.cpp
msgid "Save changes to the following scene(s) before quitting?"
-msgstr ""
+msgstr "Salvare le modifiche alle scene seguenti prima di uscire?"
#: editor/editor_node.cpp
msgid "Save changes the following scene(s) before opening Project Manager?"
msgstr ""
+"Salvare le modifiche alle scene seguenti prima di aprire il Manager Progetti?"
+
+#: editor/editor_node.cpp
+msgid ""
+"This option is deprecated. Situations where refresh must be forced are now "
+"considered a bug. Please report."
+msgstr ""
+"Questa opzione é deprecata. Situazioni dove un refresh é obbligatorio sono "
+"ora considerate come bug. Si prega di effettuare un report."
#: editor/editor_node.cpp
msgid "Pick a Main Scene"
msgstr "Scegli una Scena Principale"
#: editor/editor_node.cpp
-msgid "Unable to enable addon plugin at: '"
-msgstr ""
+#, fuzzy
+msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
+msgstr "Non riesco ad abilitare il plugin aggiunto a: '"
#: editor/editor_node.cpp
-msgid "' parsing of config failed."
+#, fuzzy
+msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
msgstr ""
+"Impossibile trovare il campo per lo script aggiuntivo in: 'res://addons/"
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/"
-msgstr ""
+#, fuzzy
+msgid "Unable to load addon script from path: '%s'."
+msgstr "Impossibile caricare uno script aggiuntivo dal percorso: '"
#: editor/editor_node.cpp
-msgid "Unable to load addon script from path: '"
-msgstr ""
+#, fuzzy
+msgid ""
+"Unable to load addon script from path: '%s' Base type is not EditorPlugin."
+msgstr "Impossibile caricare uno script aggiuntivo dal percorso: '"
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Unable to load addon script from path: '%s' Script is not in tool mode."
+msgstr "Impossibile caricare uno script aggiuntivo dal percorso: '"
#: editor/editor_node.cpp
msgid ""
@@ -1829,7 +1738,7 @@ msgstr ""
"Per effettuare cambiamenti, puo essere creata una nuova scena ereditata."
#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/scene_tree_dock.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Ugh"
msgstr "Ugh"
@@ -1843,14 +1752,14 @@ msgstr ""
"progetto."
#: editor/editor_node.cpp
-msgid "Error loading scene."
-msgstr "Errore di caricamento della scena."
-
-#: editor/editor_node.cpp
msgid "Scene '%s' has broken dependencies:"
msgstr "La scena '%s' ha rotto le dipendenze:"
#: editor/editor_node.cpp
+msgid "Clear Recent Scenes"
+msgstr "Rimuovi Scene Recenti"
+
+#: editor/editor_node.cpp
msgid "Save Layout"
msgstr "Salva layout"
@@ -1880,11 +1789,10 @@ msgid "Distraction Free Mode"
msgstr "Modalità Senza Distrazioni"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Toggle distraction-free mode."
-msgstr "Modalità Senza Distrazioni"
+msgstr "Abilita modalità senza distrazioni."
-#: editor/editor_node.cpp editor/io_plugins/editor_scene_import_plugin.cpp
+#: editor/editor_node.cpp
msgid "Scene"
msgstr "Scena"
@@ -2122,6 +2030,10 @@ msgstr "Domande e Risposte"
msgid "Issue Tracker"
msgstr "Tracciatore Segnalazioni"
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+msgid "Community"
+msgstr "Comunità"
+
#: editor/editor_node.cpp
msgid "About"
msgstr "Riguardo a"
@@ -2130,7 +2042,7 @@ msgstr "Riguardo a"
msgid "Play the project."
msgstr "Esegui il progetto."
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Play"
msgstr "Play"
@@ -2146,7 +2058,7 @@ msgstr "Pausa Scena"
msgid "Stop the scene."
msgstr "Ferma la scena."
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Stop"
msgstr "Stop"
@@ -2219,6 +2131,15 @@ msgid "Object properties."
msgstr "Proprietà oggetto."
#: editor/editor_node.cpp
+msgid "Changes may be lost!"
+msgstr "I cambiamenti potrebbero essere persi!"
+
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Import"
+msgstr "Importa"
+
+#: editor/editor_node.cpp
msgid "FileSystem"
msgstr "FileSystem"
@@ -2232,15 +2153,7 @@ msgstr "Output"
#: editor/editor_node.cpp
msgid "Don't Save"
-msgstr ""
-
-#: editor/editor_node.cpp editor/editor_reimport_dialog.cpp
-msgid "Re-Import"
-msgstr "Re-Importa"
-
-#: editor/editor_node.cpp editor/editor_plugin_settings.cpp
-msgid "Update"
-msgstr "Aggiorna"
+msgstr "Non salvare"
#: editor/editor_node.cpp
msgid "Import Templates From ZIP File"
@@ -2267,9 +2180,8 @@ msgid "Open & Run a Script"
msgstr "Apri e Esegui uno Script"
#: editor/editor_node.cpp
-#, fuzzy
msgid "New Inherited"
-msgstr "Nuova Scena Ereditata.."
+msgstr "Nuova Ereditata"
#: editor/editor_node.cpp
msgid "Load Errors"
@@ -2303,11 +2215,28 @@ msgstr "Apri l'Editor successivo"
msgid "Open the previous Editor"
msgstr "Apri l'Editor precedente"
+#: editor/editor_plugin.cpp
+msgid "Creating Mesh Previews"
+msgstr "Creazione Anteprime Mesh"
+
+#: editor/editor_plugin.cpp
+msgid "Thumbnail.."
+msgstr "Miniatura.."
+
#: editor/editor_plugin_settings.cpp
msgid "Installed Plugins:"
msgstr "Plugins Installati:"
#: editor/editor_plugin_settings.cpp
+msgid "Update"
+msgstr "Aggiorna"
+
+#: editor/editor_plugin_settings.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Version:"
+msgstr "Versione:"
+
+#: editor/editor_plugin_settings.cpp
msgid "Author:"
msgstr "Autore:"
@@ -2340,7 +2269,8 @@ msgid "Frame %"
msgstr "Frame %"
#: editor/editor_profiler.cpp
-msgid "Fixed Frame %"
+#, fuzzy
+msgid "Physics Frame %"
msgstr "Frame Fisso %"
#: editor/editor_profiler.cpp editor/script_editor_debugger.cpp
@@ -2359,35 +2289,18 @@ msgstr "Se stesso"
msgid "Frame #:"
msgstr "Frame #:"
-#: editor/editor_reimport_dialog.cpp
-msgid "Please wait for scan to complete."
-msgstr "Si prega di attendere che lo scan venga completato."
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Current scene must be saved to re-import."
-msgstr "La scena corrente deve essere salvata per re-importare."
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Save & Re-Import"
-msgstr "Salva e Re-Importa"
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Importing"
-msgstr "Re-Importando"
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Import Changed Resources"
-msgstr "Re-Importando Risorse Cambiate"
-
#: editor/editor_run_native.cpp
msgid "Select device from the list"
-msgstr ""
+msgstr "Seleziona il dispositivo dall'elenco"
#: editor/editor_run_native.cpp
msgid ""
"No runnable export preset found for this platform.\n"
"Please add a runnable preset in the export menu."
msgstr ""
+"Non sono stati trovati dei modelli di export eseguibili per questa "
+"piattaforma.\n"
+"Prego aggiungere un modello di export eseguibile nel menu export."
#: editor/editor_run_script.cpp
msgid "Write your logic in the _run() method."
@@ -2490,10 +2403,6 @@ msgid "Importing:"
msgstr "Importo:"
#: editor/export_template_manager.cpp
-msgid "Loading Export Templates"
-msgstr "Caricamento Template d'Esportazione"
-
-#: editor/export_template_manager.cpp
msgid "Current Version:"
msgstr "Versione Corrente:"
@@ -2528,62 +2437,73 @@ msgid "Cannot navigate to '"
msgstr "Impossibile navigare a '"
#: editor/filesystem_dock.cpp
-#, fuzzy
+msgid "View items as a grid of thumbnails"
+msgstr "Visualizza elementi come una griglia di miniature"
+
+#: editor/filesystem_dock.cpp
+msgid "View items as a list"
+msgstr "Visualizza elementi come una lista"
+
+#: editor/filesystem_dock.cpp
msgid ""
"\n"
-"Status: Needs Re-Import"
-msgstr "Salva e Re-Importa"
+"Status: Import of file failed. Please fix file and reimport manually."
+msgstr ""
+"\n"
+"Stato: Importazione file fallita. Si prega di sistemare il file e "
+"reimportarlo manualmente."
#: editor/filesystem_dock.cpp
-#, fuzzy
msgid ""
"\n"
"Source: "
-msgstr "Sorgente:"
+msgstr ""
+"\n"
+"Sorgente: "
#: editor/filesystem_dock.cpp
-msgid "Same source and destination files, doing nothing."
-msgstr "Stessi file di origine e e destinazione, non faccio nulla."
+msgid "Cannot move/rename resources root."
+msgstr "Impossibile spostare/rinominare risorse root."
#: editor/filesystem_dock.cpp
-msgid "Target file exists, can't overwrite. Delete first."
-msgstr ""
+msgid "Cannot move a folder into itself.\n"
+msgstr "Impossibile spostare una cartella in se stessa.\n"
#: editor/filesystem_dock.cpp
-msgid "Same source and destination paths, doing nothing."
-msgstr ""
-"Stessi percorsi \n"
-"di origine e e destinazione, non faccio nulla."
+msgid "Error moving:\n"
+msgstr "Errore spostamento:\n"
#: editor/filesystem_dock.cpp
-msgid "Can't move directories to within themselves."
-msgstr "Impossibile muovere le directory dentro se stesse."
+msgid "Unable to update dependencies:\n"
+msgstr "Impossibile aggiornare le dipendenze:\n"
#: editor/filesystem_dock.cpp
-msgid "Can't rename deps for:\n"
-msgstr ""
+msgid "No name provided"
+msgstr "Nessun nome fornito"
#: editor/filesystem_dock.cpp
-#, fuzzy
-msgid "Error moving file:\n"
-msgstr "Errore di caricamento immagine:"
+msgid "Provided name contains invalid characters"
+msgstr "Il nome fornito contiene caratteri non validi"
#: editor/filesystem_dock.cpp
-#, fuzzy
-msgid "Error moving dir:\n"
-msgstr "Errore di importazione:"
+msgid "No name provided."
+msgstr "Nessun nome fornito."
#: editor/filesystem_dock.cpp
-msgid "Can't operate on '..'"
-msgstr "Non posso operare su '..'"
+msgid "Name contains invalid characters."
+msgstr "Il nome contiene caratteri non validi."
+
+#: editor/filesystem_dock.cpp
+msgid "A file or folder with this name already exists."
+msgstr "Un file o cartella con questo nome é già esistente."
#: editor/filesystem_dock.cpp
-msgid "Pick New Name and Location For:"
-msgstr "Scegli un Nuovo Nome e Posizione Per:"
+msgid "Renaming file:"
+msgstr "Rinomina file:"
#: editor/filesystem_dock.cpp
-msgid "No files selected!"
-msgstr "Nessun File selezionato!"
+msgid "Renaming folder:"
+msgstr "Rinomina cartella:"
#: editor/filesystem_dock.cpp
msgid "Expand all"
@@ -2594,40 +2514,36 @@ msgid "Collapse all"
msgstr "Comprimi tutto"
#: editor/filesystem_dock.cpp
-msgid "Show In File Manager"
-msgstr "Mostra nel File Manager"
-
-#: editor/filesystem_dock.cpp
-msgid "Instance"
-msgstr "Istanza"
+msgid "Copy Path"
+msgstr "Copia Percorso"
#: editor/filesystem_dock.cpp
-msgid "Edit Dependencies.."
-msgstr "Modifica Dipendenze.."
+msgid "Rename.."
+msgstr "Rinomina.."
#: editor/filesystem_dock.cpp
-msgid "View Owners.."
-msgstr "Vedi Proprietari.."
+msgid "Move To.."
+msgstr "Sposta in.."
#: editor/filesystem_dock.cpp
-msgid "Copy Path"
-msgstr "Copia Percorso"
+msgid "New Folder.."
+msgstr "Nuova Cartella.."
#: editor/filesystem_dock.cpp
-msgid "Rename or Move.."
-msgstr "Rinomina o Sposta.."
+msgid "Show In File Manager"
+msgstr "Mostra nel File Manager"
#: editor/filesystem_dock.cpp
-msgid "Move To.."
-msgstr "Sposta in.."
+msgid "Instance"
+msgstr "Istanza"
#: editor/filesystem_dock.cpp
-msgid "Info"
-msgstr "Info"
+msgid "Edit Dependencies.."
+msgstr "Modifica Dipendenze.."
#: editor/filesystem_dock.cpp
-msgid "Re-Import.."
-msgstr "Re-Importa.."
+msgid "View Owners.."
+msgstr "Vedi Proprietari.."
#: editor/filesystem_dock.cpp
msgid "Previous Directory"
@@ -2654,11 +2570,18 @@ msgid ""
"Scanning Files,\n"
"Please Wait.."
msgstr ""
+"Scansione File,\n"
+"Si prega di attendere.."
#: editor/filesystem_dock.cpp
msgid "Move"
msgstr "Sposta"
+#: editor/filesystem_dock.cpp editor/plugins/animation_tree_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Rename"
+msgstr "Rinomina"
+
#: editor/groups_editor.cpp
msgid "Add to Group"
msgstr "Aggiungi a Gruppo"
@@ -2668,17 +2591,20 @@ msgid "Remove from Group"
msgstr "Rimuovi da Gruppo"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Import as Single Scene"
-msgstr "Importando Scena.."
+msgstr "Importa come Scena Singola"
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Animations"
+msgstr "Importa con Animazioni Separate"
#: editor/import/resource_importer_scene.cpp
msgid "Import with Separate Materials"
-msgstr ""
+msgstr "Importa con Materiali Separati"
#: editor/import/resource_importer_scene.cpp
msgid "Import with Separate Objects"
-msgstr ""
+msgstr "Importa con Oggetti Separati"
#: editor/import/resource_importer_scene.cpp
msgid "Import with Separate Objects+Materials"
@@ -2686,6 +2612,21 @@ msgstr ""
#: editor/import/resource_importer_scene.cpp
#, fuzzy
+msgid "Import with Separate Objects+Animations"
+msgstr "Importa con Oggetti Separati"
+
+#: editor/import/resource_importer_scene.cpp
+#, fuzzy
+msgid "Import with Separate Materials+Animations"
+msgstr "Importa con Materiali Separati"
+
+#: editor/import/resource_importer_scene.cpp
+#, fuzzy
+msgid "Import with Separate Objects+Materials+Animations"
+msgstr "Importa con Materiali Separati"
+
+#: editor/import/resource_importer_scene.cpp
+#, fuzzy
msgid "Import as Multiple Scenes"
msgstr "Importa Scena 3D"
@@ -2694,38 +2635,31 @@ msgid "Import as Multiple Scenes+Materials"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Import Scene"
msgstr "Importa Scena"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Importing Scene.."
msgstr "Importando Scena.."
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Running Custom Script.."
msgstr "Eseguendo Script Personalizzato.."
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Couldn't load post-import script:"
msgstr "Impossibile caricare lo script di post-import:"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Invalid/broken script for post-import (check console):"
msgstr "Script di post-import invalido/non funzionante (controllare console):"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Error running post-import script:"
msgstr "Errore di esecuzione dello script di post-import:"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Saving.."
msgstr "Salvataggio.."
@@ -2753,577 +2687,6 @@ msgstr "Preset.."
msgid "Reimport"
msgstr "Reimporta"
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "No bit masks to import!"
-msgstr "Nessuna bit mask da importare!"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path is empty."
-msgstr "Il percorso di destinazione vuoto."
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must be a complete resource path."
-msgstr ""
-"Il percorso di destinazione deve essere un percorso completo di risorsa."
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must exist."
-msgstr "Il percorso di destinazione deve esistere."
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Save path is empty!"
-msgstr "Il percorso di salvataggio è vuoto!"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Import BitMasks"
-msgstr "Importa BitMasks"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s):"
-msgstr "Texture Sorgenti:"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Target Path:"
-msgstr "Percorso di destinazione:"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Accept"
-msgstr "Accetta"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Bit Mask"
-msgstr "Bit Mask"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No source font file!"
-msgstr "Nessun file font sorgente!"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No target font resource!"
-msgstr "Nessuna risorsa font di destinazione!"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"Invalid file extension.\n"
-"Please use .font."
-msgstr ""
-"Estensione file invalida.\n"
-"Si prega di usare .font."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Can't load/process source font."
-msgstr "Impossibile caricare/processare il font sorgente."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Couldn't save font."
-msgstr "Impossibile salvare font."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font:"
-msgstr "Font Sorgente:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font Size:"
-msgstr "Dimensione Font sorgente:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Dest Resource:"
-msgstr "Risorsa di destin. :"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "The quick brown fox jumps over the lazy dog."
-msgstr "La rapida volpe bianca scavalca il cane pigro."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Test:"
-msgstr "Test:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Options:"
-msgstr "Opzioni:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Font Import"
-msgstr "Importazione font"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"This file is already a Godot font file, please supply a BMFont type file "
-"instead."
-msgstr ""
-"Questo file è già un file font di Godot, si prega di fornire invece un file "
-"di tipo BMfont."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Failed opening as BMFont file."
-msgstr "Apertura come BMFont file fallita."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error initializing FreeType."
-msgstr "Errore inizializzazione FreeType."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Unknown font format."
-msgstr "Formato font sconosciuto."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error loading font."
-msgstr "Errore caricamento font."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Invalid font size."
-msgstr "Dimensione font Invalida."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Invalid font custom source."
-msgstr "Sorgente font personalizzato invalido."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/plugins/theme_editor_plugin.cpp
-msgid "Font"
-msgstr "Font"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "No meshes to import!"
-msgstr "Nessuna mesh da importare!"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Single Mesh Import"
-msgstr "Importa Mesh Singola"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Source Mesh(es):"
-msgstr "Mesh Sorgente(i):"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/plugins/mesh_instance_editor_plugin.cpp
-msgid "Mesh"
-msgstr "Mesh"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Surface %d"
-msgstr "Superficie %d"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "No samples to import!"
-msgstr "Nessun sample da importare!"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Import Audio Samples"
-msgstr "Importa Sample Audio"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Source Sample(s):"
-msgstr "Sample Sorgente(i):"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Audio Sample"
-msgstr "Sample Audio"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "New Clip"
-msgstr "Nuova Clip"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Animation Options"
-msgstr "Opzioni Animazione"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Flags"
-msgstr "Flags"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Bake FPS:"
-msgstr "Bake FPS:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Optimizer"
-msgstr "Ottimizzatore"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Linear Error"
-msgstr "Errore Lineare Max"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angular Error"
-msgstr "Errore Angolare Max"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angle"
-msgstr "Angolo Max"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Clips"
-msgstr "Clips"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Start(s)"
-msgstr "Inizio(i)"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "End(s)"
-msgstr "Fine(i)"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Loop"
-msgstr "Loop"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Filters"
-msgstr "Filtri"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source path is empty."
-msgstr "Il percorso sorgente è vuoto."
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't load post-import script."
-msgstr "Impossibile caricare script di post-importazione."
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Invalid/broken script for post-import."
-msgstr "Script di post-importazione invalido/non funzionante."
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Error importing scene."
-msgstr "Errore di importazione scena."
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import 3D Scene"
-msgstr "Importa Scena 3D"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source Scene:"
-msgstr "Scena Sorgente:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Same as Target Scene"
-msgstr "Stesso che Scena di Destinazione"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Shared"
-msgstr "Condiviso"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Target Texture Folder:"
-msgstr "Cartella Texture di Destinazione:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Post-Process Script:"
-msgstr "Script di Post-Process:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Custom Root Node Type:"
-msgstr "Tipo di Nodo Root Personalizzato:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Auto"
-msgstr "Auto"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Root Node Name:"
-msgstr "Nome Nodo di Root:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "The Following Files are Missing:"
-msgstr "I File Seguenti sono Mancanti:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Anyway"
-msgstr "Importa ComunqueImporta Comunque"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp scene/gui/dialogs.cpp
-msgid "Cancel"
-msgstr "Annulla"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import & Open"
-msgstr "Importa e Apri"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Edited scene has not been saved, open imported scene anyway?"
-msgstr ""
-"La scena modificata non è stata salvata, aprire la scena importata comunque?"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Image:"
-msgstr "Importa Immagine:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Can't import a file over itself:"
-msgstr "Impossibile importare un file su se stesso:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't localize path: %s (already local)"
-msgstr "Impossibile localizzare il percorso: %s (già locale)"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "3D Scene Animation"
-msgstr "Animazione Scena 3D"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Uncompressed"
-msgstr "Decompressi"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossless (PNG)"
-msgstr "Comprimi Lossless (PNG)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossy (WebP)"
-msgstr "Comprimi Lossy (WebP)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress (VRAM)"
-msgstr "Comprimi (VRAM)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Format"
-msgstr "Formato Texture"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Compression Quality (WebP):"
-msgstr "Qualità Compressione Texture (WebP):"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Options"
-msgstr "Opzioni Texture"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Please specify some files!"
-msgstr "Si prega di specificare qualche file!"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "At least one file needed for Atlas."
-msgstr "Almeno un file è richiesto per l'Atlas."
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Error importing:"
-msgstr "Errore di importazione:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Only one file is required for large texture."
-msgstr "Solo un file è richiesto per una texture grande."
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Max Texture Size:"
-msgstr "Dimensione Texture Massima:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for Atlas (2D)"
-msgstr "Importa Textures per Atlas (2D)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cell Size:"
-msgstr "Dimensione Cella:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Large Texture"
-msgstr "Texture Grande"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Textures (2D)"
-msgstr "Importa Texture Grandi (2D)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture"
-msgstr "Texture Sorgente"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Base Atlas Texture"
-msgstr "Texture Base Atlas"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s)"
-msgstr "Texture Sorgente(i)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 2D"
-msgstr "Importa Textures per 2D"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 3D"
-msgstr "Importa Textures per 3D"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures"
-msgstr "Importa Textures"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "2D Texture"
-msgstr "Texture 2D"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "3D Texture"
-msgstr "Texture 3D"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Atlas Texture"
-msgstr "Texture dell'Atlas"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid ""
-"NOTICE: Importing 2D textures is not mandatory. Just copy png/jpg files to "
-"the project."
-msgstr ""
-"NOTA: Importare texture 2D non è obbligatorio. Basta copiare i file png/jpg "
-"nel progetto."
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Crop empty space."
-msgstr "Ritaglia spazio vuoto."
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture"
-msgstr "Texture"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Texture"
-msgstr "Importa Texture Grande"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Load Source Image"
-msgstr "Carica Immagine Sorgente"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Slicing"
-msgstr "Taglio"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Inserting"
-msgstr "Inserimento"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Saving"
-msgstr "Salvataggio"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save large texture:"
-msgstr "Impossibile salvare texture grande:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Build Atlas For:"
-msgstr "Costruisci Atlas Per:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Loading Image:"
-msgstr "Immagine Caricamento:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't load image:"
-msgstr "Impossibile caricare immagine:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Converting Images"
-msgstr "Convertendo Immagini"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cropping Images"
-msgstr "Tagliando Immagini"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Blitting Images"
-msgstr "Bliting Immagini"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save atlas image:"
-msgstr "Impossibile salvare l'immagine di atlas:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save converted texture:"
-msgstr "Impossibile salvare la texture convertita:"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid source!"
-msgstr "Sorgente invalida!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid translation source!"
-msgstr "Sorgente traduzione invalida!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Column"
-msgstr "Colonna"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/script_create_dialog.cpp
-msgid "Language"
-msgstr "Linguaggio"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No items to import!"
-msgstr "Nessun elemento da importare!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No target path!"
-msgstr "Nessun percorso di destinazione!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translations"
-msgstr "Importa Traduzioni"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Couldn't import!"
-msgstr "Impossibile Importare!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translation"
-msgstr "Importa Traduzione"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Source CSV:"
-msgstr "CSV Sorgente:"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Ignore First Row"
-msgstr "Ignora Prima Riga"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Compress"
-msgstr "Comprimi"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Add to Project (project.godot)"
-msgstr "Aggiungi a Progetto (project.godot)"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Languages:"
-msgstr "Importa Lingue:"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Translation"
-msgstr "Traduzione"
-
#: editor/multi_node_edit.cpp
msgid "MultiNode Set"
msgstr "MultiNode Set"
@@ -3336,6 +2699,45 @@ msgstr "Gruppi"
msgid "Select a Node to edit Signals and Groups."
msgstr "Seleziona un Nodo per modificare Segnali e Gruppi."
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create Poly"
+msgstr "Crea Poly"
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly"
+msgstr "Modifica Poly"
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#, fuzzy
+msgid "Insert Point"
+msgstr "Inserimento"
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly (Remove Point)"
+msgstr "Modifica Poly (Rimuovi Punto)"
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Remove Poly And Point"
+msgstr "Rimuovi Poligono e Punto"
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create a new polygon from scratch."
+msgstr "Crea un nuovo poligono dal nulla."
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid ""
+"Edit existing polygon:\n"
+"LMB: Move Point.\n"
+"Ctrl+LMB: Split Segment.\n"
+"RMB: Erase Point."
+msgstr ""
+
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Toggle Autoplay"
msgstr "Abilità Autoplay"
@@ -3490,7 +2892,6 @@ msgstr "Nome Animazione:"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
#: editor/script_create_dialog.cpp
msgid "Error!"
@@ -3601,10 +3002,6 @@ msgid "Delete Input"
msgstr "Elimina Input"
#: editor/plugins/animation_tree_editor_plugin.cpp
-msgid "Rename"
-msgstr "Rinomina"
-
-#: editor/plugins/animation_tree_editor_plugin.cpp
msgid "Animation tree is valid."
msgstr "Animation tree valido."
@@ -3660,64 +3057,181 @@ msgstr "Modifica Filtri Nodi"
msgid "Filters.."
msgstr "Filtri.."
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing %d Triangles:"
-msgstr "Elaborazione %d Triangoli:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Free"
+msgstr "Gratuito"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Triangle #"
-msgstr "Triangolo #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Contents:"
+msgstr "Contenuti:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Light Baker Setup:"
-msgstr "Impostazioni Baker Luci:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "View Files"
+msgstr "Vedi Files"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing Geometry"
-msgstr "Elaborazione Geometria"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve hostname:"
+msgstr "Impossibile risolvere l'hostname:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Fixing Lights"
-msgstr "Aggiustando le Luci"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve."
+msgstr "Impossibile risolvete."
-#: editor/plugins/baked_light_baker.cpp
-msgid "Making BVH"
-msgstr "Creazione BVH"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connection error, please try again."
+msgstr "Errore di connessione, si prega di riprovare."
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Light Octree"
-msgstr "Creazione Octree Luci"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't connect."
+msgstr "Impossibile connettersi."
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Octree Texture"
-msgstr "Creazione Octree Texture"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't connect to host:"
+msgstr "Impossibile connetersi all'host:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response from host:"
+msgstr "Nessuna risposta dall'host:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response."
+msgstr "Nessuna risposta."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, return code:"
+msgstr "Richiesta fallita, codice di return:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Transfer to Lightmaps:"
-msgstr "Trasferisci a Lightmap:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Req. Failed."
+msgstr "Rich. Fall."
-#: editor/plugins/baked_light_baker.cpp
-msgid "Allocating Texture #"
-msgstr "Allocazione Texture #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, too many redirects"
+msgstr "Richiesta fallita, troppi ridirezionamenti"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Baking Triangle #"
-msgstr "Backing Triangoli #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Redirect Loop."
+msgstr "Ridirigi Loop."
-#: editor/plugins/baked_light_baker.cpp
-msgid "Post-Processing Texture #"
-msgstr "Texture Post-Processing #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed:"
+msgstr "Fallito:"
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Bake!"
-msgstr "Bake!"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Bad download hash, assuming file has been tampered with."
+msgstr "Hash di download non buono, si presume il file sia stato manipolato."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Expected:"
+msgstr "Previsto:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Got:"
+msgstr "Ottenuto:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed sha256 hash check"
+msgstr "Check hash sha256 fallito"
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Reset the lightmap octree baking process (start over)."
-msgstr "Resetta il processo di baking dell'octree (ricomincia da capo)."
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Asset Download Error:"
+msgstr "Errore di Download Asset:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Fetching:"
+msgstr "Recupero:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Resolving.."
+msgstr "Risolvendo.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connecting.."
+msgstr "Connettendo.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Requesting.."
+msgstr "Richiedendo.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Error making request"
+msgstr "Errore nel fare richiesta"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Idle"
+msgstr "Inattivo"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Retry"
+msgstr "Riprova"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download Error"
+msgstr "Errore durante il download"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download for this asset is already in progress!"
+msgstr "Il download per questo asset è già in corso!"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "first"
+msgstr "primo"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "prev"
+msgstr "prec"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "next"
+msgstr "seguente"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "last"
+msgstr "ultimo"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "All"
+msgstr "Tutti"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Plugins"
+msgstr "Plugins"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Sort:"
+msgstr "Ordina:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Reverse"
+msgstr "Inverti"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Category:"
+msgstr "Categoria:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Site:"
+msgstr "Sito:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Support.."
+msgstr "Supporta.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Official"
+msgstr "Ufficiale"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Testing"
+msgstr "Testing"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Assets ZIP File"
+msgstr "ZIP File degli Asset"
#: editor/plugins/camera_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
msgid "Preview"
msgstr "Anteprima"
@@ -3760,12 +3274,18 @@ msgid "Edit CanvasItem"
msgstr "Modifica CanvasItem"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Change Anchors"
+#, fuzzy
+msgid "Anchors only"
+msgstr "Ancora"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#, fuzzy
+msgid "Change Anchors and Margins"
msgstr "Cambia Ancore"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom (%):"
-msgstr "Zoom(%):"
+msgid "Change Anchors"
+msgstr "Cambia Ancore"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Paste Pose"
@@ -3819,60 +3339,78 @@ msgid "Pan Mode"
msgstr "Modalità di Pan"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Lock the selected object in place (can't be moved)."
-msgstr "Blocca l'oggetto selezionato sul posto (non può essere mosso)."
+#, fuzzy
+msgid "Toggles snapping"
+msgstr "Abilita Breakpoint"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Unlock the selected object (can be moved)."
-msgstr "Sblocca l'oggetto selezionato (può essere mosso)."
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Use Snap"
+msgstr "Usa lo Snap"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Makes sure the object's children are not selectable."
-msgstr "Accerta che I figli dell'oggetto non siano selezionabili."
+#, fuzzy
+msgid "Snapping options"
+msgstr "Opzioni Animazione"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Restores the object's children's ability to be selected."
-msgstr "Ripristina l'abilità dei figli dell'oggetto di essere selezionati."
+#, fuzzy
+msgid "Snap to grid"
+msgstr "Modalità Snap:"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Edit"
-msgstr "Modifica"
+msgid "Use Rotation Snap"
+msgstr "Usa lo Snap di Rotazione"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Use Snap"
-msgstr "Usa lo Snap"
+#, fuzzy
+msgid "Configure Snap..."
+msgstr "Configura Snap..."
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Show Grid"
-msgstr "Mostra Griglia"
+msgid "Snap Relative"
+msgstr "Snap Relativo"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Rotation Snap"
-msgstr "Usa lo Snap di Rotazione"
+msgid "Use Pixel Snap"
+msgstr "Usa Snap a Pixel"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap Relative"
-msgstr "Snap Relativo"
+msgid "Smart snapping"
+msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Configure Snap.."
-msgstr "Configura Snap..."
+#, fuzzy
+msgid "Snap to parent"
+msgstr "Espandi a Genitore"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Pixel Snap"
-msgstr "Usa Snap a Pixel"
+msgid "Snap to node anchor"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to node sides"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to other nodes"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Lock the selected object in place (can't be moved)."
+msgstr "Blocca l'oggetto selezionato sul posto (non può essere mosso)."
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Unlock the selected object (can be moved)."
+msgstr "Sblocca l'oggetto selezionato (può essere mosso)."
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Skeleton.."
-msgstr "Scheletro.."
+msgid "Makes sure the object's children are not selectable."
+msgstr "Accerta che I figli dell'oggetto non siano selezionabili."
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Restores the object's children's ability to be selected."
+msgstr "Ripristina l'abilità dei figli dell'oggetto di essere selezionati."
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Make Bones"
@@ -3900,12 +3438,19 @@ msgid "View"
msgstr "Vista"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Reset"
-msgstr "Zoom Reset"
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Show Grid"
+msgstr "Mostra Griglia"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#, fuzzy
+msgid "Show helpers"
+msgstr "Mostra Ossa"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Set.."
-msgstr "Imposta Zoom.."
+#, fuzzy
+msgid "Show rulers"
+msgstr "Mostra Ossa"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Center Selection"
@@ -3916,8 +3461,9 @@ msgid "Frame Selection"
msgstr "Selezione Frame"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Anchor"
-msgstr "Ancora"
+#, fuzzy
+msgid "Layout"
+msgstr "Salva layout"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Insert Keys"
@@ -3940,12 +3486,21 @@ msgid "Clear Pose"
msgstr "Pulisci Posa"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Set a Value"
-msgstr "Imposta un Valore"
+msgid "Drag pivot from mouse position"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#, fuzzy
+msgid "Set pivot at mouse position"
+msgstr "Imposta Posizione Curve Out"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Multiply grid step by 2"
+msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap (Pixels):"
-msgstr "Snap (Pixels):"
+msgid "Divide grid step by 2"
+msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Add %s"
@@ -3955,23 +3510,28 @@ msgstr "Aggiungi %s"
msgid "Adding %s..."
msgstr "Aggiungendo %s..."
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Create Node"
msgstr "Crea Nodo"
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Error instancing scene from %s"
msgstr "Errore istanziamento scena da %s"
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "OK :("
msgstr "OK :("
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "No parent to instance a child at."
msgstr "Nessun genitore del quale istanziare un figlio."
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "This operation requires a single selected node."
msgstr "Questa operazione richiede un solo nodo selezionato."
@@ -3987,45 +3547,6 @@ msgstr ""
"Premi & Trascina + Shift : Aggiungi nodo come fratello\n"
"Premi & Trascina + Alt : Cambia tipo del nodo"
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Create Poly"
-msgstr "Crea Poly"
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly"
-msgstr "Modifica Poly"
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly (Remove Point)"
-msgstr "Modifica Poly (Rimuovi Punto)"
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Create a new polygon from scratch."
-msgstr "Crea un nuovo poligono dal nulla."
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-msgid ""
-"Edit existing polygon:\n"
-"LMB: Move Point.\n"
-"Ctrl+LMB: Split Segment.\n"
-"RMB: Erase Point."
-msgstr ""
-
#: editor/plugins/collision_polygon_editor_plugin.cpp
msgid "Create Poly3D"
msgstr "Crea Poly3D"
@@ -4035,14 +3556,6 @@ msgid "Set Handle"
msgstr "Imposta Maniglia"
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Creating Mesh Library"
-msgstr "Creazione Libreria Mesh"
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Thumbnail.."
-msgstr "Miniatura.."
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Remove item %d?"
msgstr "Rimuovi elemento %d?"
@@ -4065,6 +3578,28 @@ msgid "Update from Scene"
msgstr "Aggiorna da Scena"
#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat0"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat1"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+#, fuzzy
+msgid "Ease in"
+msgstr "Ease In"
+
+#: editor/plugins/curve_editor_plugin.cpp
+#, fuzzy
+msgid "Ease out"
+msgstr "Ease Out"
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Smoothstep"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
#, fuzzy
msgid "Modify Curve Point"
msgstr "Modifica Curva"
@@ -4146,22 +3681,18 @@ msgid "Create Occluder Polygon"
msgstr "Crea Poligono di occlusione"
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Edit existing polygon:"
msgstr "Modifica poligono esistente:"
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "LMB: Move Point."
msgstr "LMB: Sposta punto."
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Ctrl+LMB: Split Segment."
msgstr "Ctrl+LMB: dividi Segmento."
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "RMB: Erase Point."
msgstr "RMB: Elimina Punto."
@@ -4262,6 +3793,10 @@ msgid "Create Outline"
msgstr "Crea Outline"
#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Mesh"
+msgstr "Mesh"
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Create Trimesh Static Body"
msgstr "Crea Corpo Statico Trimesh"
@@ -4391,14 +3926,83 @@ msgstr "Scala Casuale:"
msgid "Populate"
msgstr "Popola"
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake!"
+msgstr "Bake!"
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+#, fuzzy
+msgid "Bake the navigation mesh.\n"
+msgstr "Crea Mesh di Navigazione"
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+#, fuzzy
+msgid "Clear the navigation mesh."
+msgstr "Crea Mesh di Navigazione"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Setting up Configuration..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Calculating grid size..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Creating heightfield..."
+msgstr "Creazione Octree Luci"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Marking walkable triangles..."
+msgstr "Stringhe Traducibili.."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Constructing compact heightfield..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Eroding walkable area..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Partitioning..."
+msgstr "Avvertimento"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Creating contours..."
+msgstr "Creazione Octree Texture"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Creating polymesh..."
+msgstr "Crea Mesh di Outline.."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Converting to native navigation mesh..."
+msgstr "Crea Mesh di Navigazione"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Navigation Mesh Generator Setup:"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Parsing Geometry..."
+msgstr "Elaborazione Geometria"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Done!"
+msgstr ""
+
#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Create Navigation Polygon"
msgstr "Crea Poligono di Navigazione"
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Remove Poly And Point"
-msgstr "Rimuovi Poligono e Punto"
-
#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Clear Emission Mask"
msgstr "Cancella Maschera Emissione"
@@ -4573,14 +4177,17 @@ msgid "Curve Point #"
msgstr "Punto Curva #"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve Point Position"
msgstr "Imposta Posizione Punti curva"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve In Position"
msgstr "Imposta Posizione Curve In"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve Out Position"
msgstr "Imposta Posizione Curve Out"
@@ -4641,6 +4248,14 @@ msgid "Scale Polygon"
msgstr "Scala Poligono"
#: editor/plugins/polygon_2d_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Edit"
+msgstr "Modifica"
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Polygon->UV"
msgstr "Poligono->UV"
@@ -4695,63 +4310,10 @@ msgstr "Carica Risorsa"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/shader_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "Incolla"
-#: editor/plugins/rich_text_editor_plugin.cpp
-msgid "Parse BBCode"
-msgstr "Decodifica BBCode"
-
-#: editor/plugins/sample_editor_plugin.cpp
-msgid "Length:"
-msgstr "Lunghezza:"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Open Sample File(s)"
-msgstr "Apri File(s) Sample"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "ERROR: Couldn't load sample!"
-msgstr "ERRORE: Impossibile caricare sample!"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Add Sample"
-msgstr "Aggiungi Sample"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Rename Sample"
-msgstr "Rinomina Sample"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Delete Sample"
-msgstr "Elimina Sample"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "16 Bits"
-msgstr "16 Bits"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "8 Bits"
-msgstr "8 Bits"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Stereo"
-msgstr "Stereo"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Mono"
-msgstr "Mono"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Format"
-msgstr "Formato"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Pitch"
-msgstr "Pitch"
-
#: editor/plugins/script_editor_plugin.cpp
msgid "Clear Recent Files"
msgstr "Elimina File recenti"
@@ -4842,6 +4404,10 @@ msgstr "Chiudi Documentazione"
msgid "Close All"
msgstr "Chiudi Tutto"
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+msgid "Run"
+msgstr "Esegui"
+
#: editor/plugins/script_editor_plugin.cpp
#, fuzzy
msgid "Toggle Scripts Panel"
@@ -4871,7 +4437,8 @@ msgstr "Step Into"
msgid "Break"
msgstr "Break"
-#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+#: editor/script_editor_debugger.cpp
msgid "Continue"
msgstr "Continua"
@@ -4885,18 +4452,6 @@ msgid "Debug with external editor"
msgstr "Apri l'Editor successivo"
#: editor/plugins/script_editor_plugin.cpp
-msgid "Window"
-msgstr "Finestra"
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Left"
-msgstr "Sposta a Sinistra"
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Right"
-msgstr "Sposta a Destra"
-
-#: editor/plugins/script_editor_plugin.cpp
msgid "Open Godot online documentation"
msgstr "Apri la documentazione online di Godot"
@@ -4982,8 +4537,9 @@ msgid "Cut"
msgstr "Taglia"
#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "Copia"
@@ -5247,10 +4803,6 @@ msgid "View Plane Transform."
msgstr "Visualizza Tranform del Piano."
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Scaling to %s%%."
-msgstr "Scalando a %s%%."
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rotating %s degrees."
msgstr "Ruotando di %s gradi."
@@ -5267,10 +4819,6 @@ msgid "Top View."
msgstr "Vista dall'Alto."
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Top"
-msgstr "Alto"
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rear View."
msgstr "Vista dal Retro."
@@ -5483,7 +5031,7 @@ msgstr "Allinea Selezione Con Vista"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Tool Select"
-msgstr "Strumento Selezione"
+msgstr "Strumento Seleziona"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Tool Move"
@@ -5502,6 +5050,10 @@ msgid "Transform"
msgstr "Transform"
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Configure Snap.."
+msgstr "Configura Snap..."
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Local Coords"
msgstr "Coordinate locali"
@@ -5647,6 +5199,10 @@ msgid "Speed (FPS):"
msgstr "Velocità (FPS):"
#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Loop"
+msgstr "Loop"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Animation Frames"
msgstr "Frames Animazione"
@@ -5659,12 +5215,14 @@ msgid "Insert Empty (After)"
msgstr "Inserisci Vuoto (Dopo)"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Up"
-msgstr "Su"
+#, fuzzy
+msgid "Move (Before)"
+msgstr "Rimuovi nodo(i)"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Down"
-msgstr "Giù"
+#, fuzzy
+msgid "Move (After)"
+msgstr "Sposta a Sinistra"
#: editor/plugins/style_box_editor_plugin.cpp
msgid "StyleBox Preview:"
@@ -5743,8 +5301,12 @@ msgid "Remove All"
msgstr "Rimuovi"
#: editor/plugins/theme_editor_plugin.cpp
-msgid "Theme"
-msgstr "Tema"
+msgid "Edit theme.."
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Theme editing menu."
+msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
msgid "Add Class Items"
@@ -5828,6 +5390,10 @@ msgid "Style"
msgstr "Stile"
#: editor/plugins/theme_editor_plugin.cpp
+msgid "Font"
+msgstr "Font"
+
+#: editor/plugins/theme_editor_plugin.cpp
msgid "Color"
msgstr "Colore"
@@ -5879,8 +5445,9 @@ msgid "Mirror Y"
msgstr "Specchia Y"
#: editor/plugins/tile_map_editor_plugin.cpp
-msgid "Bucket"
-msgstr "Secchiello"
+#, fuzzy
+msgid "Paint Tile"
+msgstr "Disegna TileMap"
#: editor/plugins/tile_map_editor_plugin.cpp
msgid "Pick Tile"
@@ -5943,6 +5510,11 @@ msgid "Delete preset '%s'?"
msgstr "Eliminare preset '%s'?"
#: editor/project_export.cpp
+#, fuzzy
+msgid "Export templates for this platform are missing/corrupted: "
+msgstr "Le export templates per questa piattaforma sono mancanti:"
+
+#: editor/project_export.cpp
msgid "Presets"
msgstr "Presets"
@@ -6019,30 +5591,61 @@ msgid "Export templates for this platform are missing:"
msgstr "Le export templates per questa piattaforma sono mancanti:"
#: editor/project_export.cpp
+#, fuzzy
+msgid "Export templates for this platform are missing/corrupted:"
+msgstr "Le export templates per questa piattaforma sono mancanti:"
+
+#: editor/project_export.cpp
msgid "Export With Debug"
msgstr "Esporta Con Debug"
#: editor/project_manager.cpp
-msgid "Invalid project path, the path must exist!"
-msgstr "Percorso di progetto invalido, il percorso deve esistere!"
+#, fuzzy
+msgid "The path does not exist."
+msgstr "File non esistente."
+
+#: editor/project_manager.cpp
+#, fuzzy
+msgid "Please choose a 'project.godot' file."
+msgstr "Si prega di esportare al di fuori della cartella del progetto!"
#: editor/project_manager.cpp
-msgid "Invalid project path, project.godot must not exist."
-msgstr "Percorso di progetto invalido, project.godot non esiste."
+msgid ""
+"Your project will be created in a non empty folder (you might want to create "
+"a new folder)."
+msgstr ""
#: editor/project_manager.cpp
-msgid "Invalid project path, project.godot must exist."
-msgstr "Percorso di progetto invalido, project.godot deve esistere."
+msgid "Please choose a folder that does not contain a 'project.godot' file."
+msgstr ""
#: editor/project_manager.cpp
msgid "Imported Project"
msgstr "Progetto Importato"
#: editor/project_manager.cpp
+msgid " "
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "It would be a good idea to name your project."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Invalid project path (changed anything?)."
msgstr "Percorso di progetto invalido (cambiato qualcosa?)."
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Couldn't get project.godot in project path."
+msgstr "Impossibile creare project.godot nel percorso di progetto."
+
+#: editor/project_manager.cpp
+#, fuzzy
+msgid "Couldn't edit project.godot in project path."
+msgstr "Impossibile creare project.godot nel percorso di progetto."
+
+#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
msgstr "Impossibile creare project.godot nel percorso di progetto."
@@ -6051,38 +5654,49 @@ msgid "The following files failed extraction from package:"
msgstr "Impossibile estrarre i file seguenti dal pacchetto:"
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Rename Project"
+msgstr "Progetto Senza Nome"
+
+#: editor/project_manager.cpp
+#, fuzzy
+msgid "Couldn't get project.godot in the project path."
+msgstr "Impossibile creare project.godot nel percorso di progetto."
+
+#: editor/project_manager.cpp
+msgid "New Game Project"
+msgstr "Nuovo Progetto di Gioco"
+
+#: editor/project_manager.cpp
msgid "Import Existing Project"
msgstr "Importa Progetto Esistente"
#: editor/project_manager.cpp
-msgid "Project Path (Must Exist):"
-msgstr "Percorso Progetto (Deve Esistere):"
+msgid "Create New Project"
+msgstr "Crea Nuovo Progetto"
+
+#: editor/project_manager.cpp
+msgid "Install Project:"
+msgstr "Installa Progetto:"
#: editor/project_manager.cpp
msgid "Project Name:"
msgstr "Nome Progetto:"
#: editor/project_manager.cpp
-msgid "Create New Project"
-msgstr "Crea Nuovo Progetto"
+#, fuzzy
+msgid "Create folder"
+msgstr "Crea Cartella"
#: editor/project_manager.cpp
msgid "Project Path:"
msgstr "Percorso Progetto:"
#: editor/project_manager.cpp
-msgid "Install Project:"
-msgstr "Installa Progetto:"
-
-#: editor/project_manager.cpp
msgid "Browse"
msgstr "Sfoglia"
#: editor/project_manager.cpp
-msgid "New Game Project"
-msgstr "Nuovo Progetto di Gioco"
-
-#: editor/project_manager.cpp
msgid "That's a BINGO!"
msgstr "Questo è un BINGO!"
@@ -6091,6 +5705,11 @@ msgid "Unnamed Project"
msgstr "Progetto Senza Nome"
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Can't open project"
+msgstr "Impossibile connettersi."
+
+#: editor/project_manager.cpp
msgid "Are you sure to open more than one project?"
msgstr "Sei sicuro di voler aprire più di un progetto?"
@@ -6123,6 +5742,12 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
+"Language changed.\n"
+"The UI will update next time the editor or project manager starts."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid ""
"You are about the scan %s folders for existing Godot projects. Do you "
"confirm?"
msgstr "Stai per esaminare %s cartelle per progetti Godot esistenti. Confermi?"
@@ -6132,10 +5757,6 @@ msgid "Project List"
msgstr "Lista Progetti"
#: editor/project_manager.cpp
-msgid "Run"
-msgstr "Esegui"
-
-#: editor/project_manager.cpp
msgid "Scan"
msgstr "Esamina"
@@ -6157,6 +5778,11 @@ msgstr "Esci"
#: editor/project_manager.cpp
#, fuzzy
+msgid "Restart Now"
+msgstr "Restart (s):"
+
+#: editor/project_manager.cpp
+#, fuzzy
msgid "Can't run project"
msgstr "Impossibile connettersi."
@@ -6193,17 +5819,14 @@ msgid "Add Input Action Event"
msgstr "Aggiungi Evento di Azione Input"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Meta+"
msgstr "Meta+"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Shift+"
msgstr "Shift+"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Alt+"
msgstr "Alt+"
@@ -6264,7 +5887,7 @@ msgstr "Cambia"
msgid "Joypad Axis Index:"
msgstr "Indice Asse Joypad:"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Axis"
msgstr "Asse"
@@ -6284,31 +5907,31 @@ msgstr "Elimina Evento di Azione Input"
msgid "Add Event"
msgstr "Aggiungi Evento"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Device"
msgstr "Dispositivo"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Button"
msgstr "Pulsante"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Left Button."
msgstr "Pulsante Sinistro."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Right Button."
msgstr "Pulsante DEstro."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Middle Button."
msgstr "Pulsante centrale."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Up."
msgstr "Rotellina su."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Down."
msgstr "Rotellina Giù."
@@ -6318,7 +5941,7 @@ msgid "Add Global Property"
msgstr "Aggiungi Proprietà Getter"
#: editor/project_settings_editor.cpp
-msgid "Select an setting item first!"
+msgid "Select a setting item first!"
msgstr ""
#: editor/project_settings_editor.cpp
@@ -6337,6 +5960,16 @@ msgid "Delete Item"
msgstr "Elimina Input"
#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Can't contain '/' or ':'"
+msgstr "Impossibile connetersi all'host:"
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Already existing"
+msgstr "Attiva Persistenza"
+
+#: editor/project_settings_editor.cpp
msgid "Error saving settings."
msgstr "Errore nel salvare le impostazioni."
@@ -6377,6 +6010,15 @@ msgid "Remove Resource Remap Option"
msgstr "Rimuovi Opzione di Remap Rimorse"
#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Changed Locale Filter"
+msgstr "Cambia tempo di Blend"
+
+#: editor/project_settings_editor.cpp
+msgid "Changed Locale Filter Mode"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "Project Settings (project.godot)"
msgstr "Impostazioni Progetto (project.godot)"
@@ -6437,6 +6079,30 @@ msgid "Locale"
msgstr "Locale"
#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Locales Filter"
+msgstr "Filtro Immagine:"
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Show all locales"
+msgstr "Mostra Ossa"
+
+#: editor/project_settings_editor.cpp
+msgid "Show only selected locales"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Filter mode:"
+msgstr "Filtri"
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Locales:"
+msgstr "Locale"
+
+#: editor/project_settings_editor.cpp
msgid "AutoLoad"
msgstr "AutoLoad"
@@ -6486,10 +6152,20 @@ msgid "New Script"
msgstr "Nuovo Script"
#: editor/property_editor.cpp
+#, fuzzy
+msgid "Make Unique"
+msgstr "Crea Ossa"
+
+#: editor/property_editor.cpp
msgid "Show in File System"
msgstr "Mostra nel File System"
#: editor/property_editor.cpp
+#, fuzzy
+msgid "Convert To %s"
+msgstr "Converti In.."
+
+#: editor/property_editor.cpp
msgid "Error loading file: Not a resource!"
msgstr "Errore caricamento file: Non è una risorsa!"
@@ -6527,6 +6203,11 @@ msgid "Select Property"
msgstr "Seleziona Proprietà"
#: editor/property_selector.cpp
+#, fuzzy
+msgid "Select Virtual Method"
+msgstr "Seleziona Metodo"
+
+#: editor/property_selector.cpp
msgid "Select Method"
msgstr "Seleziona Metodo"
@@ -6554,26 +6235,6 @@ msgstr "Mantieni Transform Globale"
msgid "Reparent"
msgstr "Cambia Genitore"
-#: editor/resources_dock.cpp
-msgid "Create New Resource"
-msgstr "Crea Nuova Risorsa"
-
-#: editor/resources_dock.cpp
-msgid "Open Resource"
-msgstr "Apri Risorsa"
-
-#: editor/resources_dock.cpp
-msgid "Save Resource"
-msgstr "Salva Risorsa"
-
-#: editor/resources_dock.cpp
-msgid "Resource Tools"
-msgstr "Strumenti Risorsa"
-
-#: editor/resources_dock.cpp
-msgid "Make Local"
-msgstr "Rendi Locale"
-
#: editor/run_settings_dialog.cpp
msgid "Run Mode:"
msgstr "Modalità esecuzione:"
@@ -6704,14 +6365,6 @@ msgid "Sub-Resources:"
msgstr "Sub-Risorse:"
#: editor/scene_tree_dock.cpp
-msgid "Edit Groups"
-msgstr "Modifica Gruppi"
-
-#: editor/scene_tree_dock.cpp
-msgid "Edit Connections"
-msgstr "Modifica Connessioni"
-
-#: editor/scene_tree_dock.cpp
msgid "Clear Inheritance"
msgstr "Liberare ereditarietà"
@@ -6908,6 +6561,15 @@ msgid "Invalid base path"
msgstr "Percorso di base invalido"
#: editor/script_create_dialog.cpp
+msgid "Directory of the same name exists"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
+#, fuzzy
+msgid "File exists, will be reused"
+msgstr "File Esistente, Sovrascrivere?"
+
+#: editor/script_create_dialog.cpp
msgid "Invalid extension"
msgstr "Estensione Invalida"
@@ -6948,6 +6610,10 @@ msgid "Load existing script file"
msgstr "Carica file script esistente"
#: editor/script_create_dialog.cpp
+msgid "Language"
+msgstr "Linguaggio"
+
+#: editor/script_create_dialog.cpp
msgid "Inherits"
msgstr "Eredita"
@@ -6988,6 +6654,10 @@ msgid "Function:"
msgstr "Funzione:"
#: editor/script_editor_debugger.cpp
+msgid "Pick one or more items from the list to display the graph."
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
msgid "Errors"
msgstr "Errori"
@@ -7068,6 +6738,10 @@ msgid "Type"
msgstr "Tipo"
#: editor/script_editor_debugger.cpp
+msgid "Format"
+msgstr "Formato"
+
+#: editor/script_editor_debugger.cpp
msgid "Usage"
msgstr "Utilizzo"
@@ -7143,12 +6817,30 @@ msgstr "Cambia AABB Particelle"
msgid "Change Probe Extents"
msgstr "Cambia Estensione Probe"
+#: modules/gdnative/gd_native_library_editor.cpp
+#, fuzzy
+msgid "Library"
+msgstr "MeshLibrary.."
+
+#: modules/gdnative/gd_native_library_editor.cpp
+#, fuzzy
+msgid "Status"
+msgstr "Stato:"
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Libraries: "
+msgstr ""
+
+#: modules/gdnative/register_types.cpp
+msgid "GDNative"
+msgstr ""
+
#: modules/gdscript/gd_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Invalid type argument to convert(), use TYPE_* constants."
msgstr "Argomento tipo invalido per convert(), usare le costanti TYPE_*."
-#: modules/gdscript/gd_functions.cpp
+#: modules/gdscript/gd_functions.cpp modules/mono/glue/glue_header.h
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Not enough bytes for decoding bytes, or invalid format."
msgstr ""
@@ -7203,10 +6895,6 @@ msgid "GridMap Duplicate Selection"
msgstr "Duplica Selezione"
#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "GridMap Paint"
-msgstr ""
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
#, fuzzy
msgid "Snap View"
msgstr "Vista dall'Alto"
@@ -7310,13 +6998,8 @@ msgstr "Impostazioni Snap"
msgid "Pick Distance:"
msgstr "Istanza:"
-#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
-msgid "Tiles"
-msgstr " Files"
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "Areas"
+#: modules/mono/editor/mono_bottom_panel.cpp
+msgid "Builds"
msgstr ""
#: modules/visual_script/visual_script.cpp
@@ -7527,10 +7210,18 @@ msgid "Return"
msgstr "Ritorna"
#: modules/visual_script/visual_script_editor.cpp
+msgid "Call"
+msgstr "Chiama"
+
+#: modules/visual_script/visual_script_editor.cpp
msgid "Get"
msgstr "Get"
#: modules/visual_script/visual_script_editor.cpp
+msgid "Script already has function '%s'"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
#, fuzzy
msgid "Change Input Value"
msgstr "Cambia Nome Input"
@@ -7952,6 +7643,12 @@ msgstr ""
"Una risorsa SpriteFrames deve essere creata o impostata nella proprietà "
"'Frames' affinché AnimatedSprite3D mostri i frame."
+#: scene/3d/vehicle_body.cpp
+msgid ""
+"VehicleWheel serves to provide a wheel system to a VehicleBody. Please use "
+"it as a child of a VehicleBody."
+msgstr ""
+
#: scene/gui/color_picker.cpp
#, fuzzy
msgid "Raw Mode"
@@ -7962,6 +7659,10 @@ msgid "Add current color as a preset"
msgstr "Aggiungi colore attuale come preset"
#: scene/gui/dialogs.cpp
+msgid "Cancel"
+msgstr "Annulla"
+
+#: scene/gui/dialogs.cpp
msgid "Alert!"
msgstr "Attenzione!"
@@ -7969,10 +7670,6 @@ msgstr "Attenzione!"
msgid "Please Confirm..."
msgstr "Per Favore Conferma..."
-#: scene/gui/input_action.cpp
-msgid "Ctrl+"
-msgstr "Ctrl+"
-
#: scene/gui/popup.cpp
msgid ""
"Popups will hide by default unless you call popup() or any of the popup*() "
@@ -8013,6 +7710,634 @@ msgstr ""
"Control, in modo che possa ottenere una dimensione. Altrimenti, renderlo un "
"RenderTarget e assegnare alla sua texture interna qualche nodo da mostrare."
+#: scene/resources/dynamic_font.cpp
+msgid "Error initializing FreeType."
+msgstr "Errore inizializzazione FreeType."
+
+#: scene/resources/dynamic_font.cpp
+msgid "Unknown font format."
+msgstr "Formato font sconosciuto."
+
+#: scene/resources/dynamic_font.cpp
+msgid "Error loading font."
+msgstr "Errore caricamento font."
+
+#: scene/resources/dynamic_font.cpp
+msgid "Invalid font size."
+msgstr "Dimensione font Invalida."
+
+#~ msgid "Filter:"
+#~ msgstr "Filtro:"
+
+#~ msgid "' parsing of config failed."
+#~ msgstr "' fallita lettura della configurazione."
+
+#~ msgid "Theme"
+#~ msgstr "Tema"
+
+#~ msgid "Method List For '%s':"
+#~ msgstr "Lista Metodi Per '%s':"
+
+#~ msgid "Arguments:"
+#~ msgstr "Argomenti:"
+
+#~ msgid "Return:"
+#~ msgstr "Ritorna:"
+
+#~ msgid "Added:"
+#~ msgstr "Agginto:"
+
+#~ msgid "Removed:"
+#~ msgstr "Rimosso:"
+
+#~ msgid "Error saving atlas:"
+#~ msgstr "Errore di salvataggio dell'atlas:"
+
+#~ msgid "Could not save atlas subtexture:"
+#~ msgstr "Impossibile salvare la substruttura dell'atlas:"
+
+#~ msgid "Exporting for %s"
+#~ msgstr "Esportando per %s"
+
+#~ msgid "Setting Up.."
+#~ msgstr "Impostando.."
+
+#~ msgid "Error loading scene."
+#~ msgstr "Errore di caricamento della scena."
+
+#~ msgid "Re-Import"
+#~ msgstr "Re-Importa"
+
+#~ msgid "Please wait for scan to complete."
+#~ msgstr "Si prega di attendere che lo scan venga completato."
+
+#~ msgid "Current scene must be saved to re-import."
+#~ msgstr "La scena corrente deve essere salvata per re-importare."
+
+#~ msgid "Save & Re-Import"
+#~ msgstr "Salva e Re-Importa"
+
+#~ msgid "Re-Importing"
+#~ msgstr "Re-Importando"
+
+#~ msgid "Re-Import Changed Resources"
+#~ msgstr "Re-Importando Risorse Cambiate"
+
+#~ msgid "Loading Export Templates"
+#~ msgstr "Caricamento Template d'Esportazione"
+
+#~ msgid ""
+#~ "\n"
+#~ "Status: Needs Re-Import"
+#~ msgstr ""
+#~ "\n"
+#~ "Stato: Richiede Re-Importazione"
+
+#~ msgid "Same source and destination files, doing nothing."
+#~ msgstr "Stessi file di origine e e destinazione, non faccio nulla."
+
+#~ msgid "Target file exists, can't overwrite. Delete first."
+#~ msgstr ""
+#~ "Il file di destinazione esiste, non è possibile sovrascriverlo. Occorre "
+#~ "prima cancellarlo."
+
+#~ msgid "Same source and destination paths, doing nothing."
+#~ msgstr ""
+#~ "Stessi percorsi \n"
+#~ "di origine e e destinazione, non faccio nulla."
+
+#~ msgid "Can't move directories to within themselves."
+#~ msgstr "Impossibile muovere le directory dentro se stesse."
+
+#~ msgid "Can't rename deps for:\n"
+#~ msgstr "Impossibile rinominare dipendenze per:\n"
+
+#~ msgid "Error moving file:\n"
+#~ msgstr "Errore spostamento file:\n"
+
+#~ msgid "Pick New Name and Location For:"
+#~ msgstr "Scegli un Nuovo Nome e Posizione Per:"
+
+#~ msgid "No files selected!"
+#~ msgstr "Nessun File selezionato!"
+
+#~ msgid "Info"
+#~ msgstr "Info"
+
+#~ msgid "Re-Import.."
+#~ msgstr "Re-Importa.."
+
+#~ msgid "No bit masks to import!"
+#~ msgstr "Nessuna bit mask da importare!"
+
+#~ msgid "Target path is empty."
+#~ msgstr "Il percorso di destinazione vuoto."
+
+#~ msgid "Target path must be a complete resource path."
+#~ msgstr ""
+#~ "Il percorso di destinazione deve essere un percorso completo di risorsa."
+
+#~ msgid "Target path must exist."
+#~ msgstr "Il percorso di destinazione deve esistere."
+
+#~ msgid "Save path is empty!"
+#~ msgstr "Il percorso di salvataggio è vuoto!"
+
+#~ msgid "Import BitMasks"
+#~ msgstr "Importa BitMasks"
+
+#~ msgid "Source Texture(s):"
+#~ msgstr "Texture Sorgenti:"
+
+#~ msgid "Target Path:"
+#~ msgstr "Percorso di destinazione:"
+
+#~ msgid "Accept"
+#~ msgstr "Accetta"
+
+#~ msgid "Bit Mask"
+#~ msgstr "Bit Mask"
+
+#~ msgid "No source font file!"
+#~ msgstr "Nessun file font sorgente!"
+
+#~ msgid "No target font resource!"
+#~ msgstr "Nessuna risorsa font di destinazione!"
+
+#~ msgid ""
+#~ "Invalid file extension.\n"
+#~ "Please use .font."
+#~ msgstr ""
+#~ "Estensione file invalida.\n"
+#~ "Si prega di usare .font."
+
+#~ msgid "Couldn't save font."
+#~ msgstr "Impossibile salvare font."
+
+#~ msgid "Source Font:"
+#~ msgstr "Font Sorgente:"
+
+#~ msgid "Source Font Size:"
+#~ msgstr "Dimensione Font sorgente:"
+
+#~ msgid "Dest Resource:"
+#~ msgstr "Risorsa di destin. :"
+
+#~ msgid "The quick brown fox jumps over the lazy dog."
+#~ msgstr "La rapida volpe bianca scavalca il cane pigro."
+
+#~ msgid "Test:"
+#~ msgstr "Test:"
+
+#~ msgid "Options:"
+#~ msgstr "Opzioni:"
+
+#~ msgid "Font Import"
+#~ msgstr "Importazione font"
+
+#~ msgid ""
+#~ "This file is already a Godot font file, please supply a BMFont type file "
+#~ "instead."
+#~ msgstr ""
+#~ "Questo file è già un file font di Godot, si prega di fornire invece un "
+#~ "file di tipo BMfont."
+
+#~ msgid "Failed opening as BMFont file."
+#~ msgstr "Apertura come BMFont file fallita."
+
+#~ msgid "Invalid font custom source."
+#~ msgstr "Sorgente font personalizzato invalido."
+
+#~ msgid "No meshes to import!"
+#~ msgstr "Nessuna mesh da importare!"
+
+#~ msgid "Single Mesh Import"
+#~ msgstr "Importa Mesh Singola"
+
+#~ msgid "Source Mesh(es):"
+#~ msgstr "Mesh Sorgente(i):"
+
+#~ msgid "Surface %d"
+#~ msgstr "Superficie %d"
+
+#~ msgid "No samples to import!"
+#~ msgstr "Nessun sample da importare!"
+
+#~ msgid "Import Audio Samples"
+#~ msgstr "Importa Sample Audio"
+
+#~ msgid "Source Sample(s):"
+#~ msgstr "Sample Sorgente(i):"
+
+#~ msgid "Audio Sample"
+#~ msgstr "Sample Audio"
+
+#~ msgid "New Clip"
+#~ msgstr "Nuova Clip"
+
+#~ msgid "Flags"
+#~ msgstr "Flags"
+
+#~ msgid "Bake FPS:"
+#~ msgstr "Bake FPS:"
+
+#~ msgid "Optimizer"
+#~ msgstr "Ottimizzatore"
+
+#~ msgid "Max Linear Error"
+#~ msgstr "Errore Lineare Max"
+
+#~ msgid "Max Angular Error"
+#~ msgstr "Errore Angolare Max"
+
+#~ msgid "Max Angle"
+#~ msgstr "Angolo Max"
+
+#~ msgid "Clips"
+#~ msgstr "Clips"
+
+#~ msgid "Start(s)"
+#~ msgstr "Inizio(i)"
+
+#~ msgid "End(s)"
+#~ msgstr "Fine(i)"
+
+#~ msgid "Filters"
+#~ msgstr "Filtri"
+
+#~ msgid "Source path is empty."
+#~ msgstr "Il percorso sorgente è vuoto."
+
+#~ msgid "Couldn't load post-import script."
+#~ msgstr "Impossibile caricare script di post-importazione."
+
+#~ msgid "Invalid/broken script for post-import."
+#~ msgstr "Script di post-importazione invalido/non funzionante."
+
+#~ msgid "Error importing scene."
+#~ msgstr "Errore di importazione scena."
+
+#~ msgid "Import 3D Scene"
+#~ msgstr "Importa Scena 3D"
+
+#~ msgid "Source Scene:"
+#~ msgstr "Scena Sorgente:"
+
+#~ msgid "Same as Target Scene"
+#~ msgstr "Stesso che Scena di Destinazione"
+
+#~ msgid "Shared"
+#~ msgstr "Condiviso"
+
+#~ msgid "Target Texture Folder:"
+#~ msgstr "Cartella Texture di Destinazione:"
+
+#~ msgid "Post-Process Script:"
+#~ msgstr "Script di Post-Process:"
+
+#~ msgid "Custom Root Node Type:"
+#~ msgstr "Tipo di Nodo Root Personalizzato:"
+
+#~ msgid "Auto"
+#~ msgstr "Auto"
+
+#~ msgid "Root Node Name:"
+#~ msgstr "Nome Nodo di Root:"
+
+#~ msgid "The Following Files are Missing:"
+#~ msgstr "I File Seguenti sono Mancanti:"
+
+#~ msgid "Import Anyway"
+#~ msgstr "Importa ComunqueImporta Comunque"
+
+#~ msgid "Import & Open"
+#~ msgstr "Importa e Apri"
+
+#~ msgid "Edited scene has not been saved, open imported scene anyway?"
+#~ msgstr ""
+#~ "La scena modificata non è stata salvata, aprire la scena importata "
+#~ "comunque?"
+
+#~ msgid "Import Image:"
+#~ msgstr "Importa Immagine:"
+
+#~ msgid "Couldn't localize path: %s (already local)"
+#~ msgstr "Impossibile localizzare il percorso: %s (già locale)"
+
+#~ msgid "3D Scene Animation"
+#~ msgstr "Animazione Scena 3D"
+
+#~ msgid "Uncompressed"
+#~ msgstr "Decompressi"
+
+#~ msgid "Compress Lossless (PNG)"
+#~ msgstr "Comprimi Lossless (PNG)"
+
+#~ msgid "Compress Lossy (WebP)"
+#~ msgstr "Comprimi Lossy (WebP)"
+
+#~ msgid "Compress (VRAM)"
+#~ msgstr "Comprimi (VRAM)"
+
+#~ msgid "Texture Format"
+#~ msgstr "Formato Texture"
+
+#~ msgid "Texture Compression Quality (WebP):"
+#~ msgstr "Qualità Compressione Texture (WebP):"
+
+#~ msgid "Texture Options"
+#~ msgstr "Opzioni Texture"
+
+#~ msgid "Please specify some files!"
+#~ msgstr "Si prega di specificare qualche file!"
+
+#~ msgid "At least one file needed for Atlas."
+#~ msgstr "Almeno un file è richiesto per l'Atlas."
+
+#~ msgid "Error importing:"
+#~ msgstr "Errore di importazione:"
+
+#~ msgid "Only one file is required for large texture."
+#~ msgstr "Solo un file è richiesto per una texture grande."
+
+#~ msgid "Max Texture Size:"
+#~ msgstr "Dimensione Texture Massima:"
+
+#~ msgid "Import Textures for Atlas (2D)"
+#~ msgstr "Importa Textures per Atlas (2D)"
+
+#~ msgid "Cell Size:"
+#~ msgstr "Dimensione Cella:"
+
+#~ msgid "Large Texture"
+#~ msgstr "Texture Grande"
+
+#~ msgid "Import Large Textures (2D)"
+#~ msgstr "Importa Texture Grandi (2D)"
+
+#~ msgid "Source Texture"
+#~ msgstr "Texture Sorgente"
+
+#~ msgid "Base Atlas Texture"
+#~ msgstr "Texture Base Atlas"
+
+#~ msgid "Source Texture(s)"
+#~ msgstr "Texture Sorgente(i)"
+
+#~ msgid "Import Textures for 2D"
+#~ msgstr "Importa Textures per 2D"
+
+#~ msgid "Import Textures for 3D"
+#~ msgstr "Importa Textures per 3D"
+
+#~ msgid "Import Textures"
+#~ msgstr "Importa Textures"
+
+#~ msgid "2D Texture"
+#~ msgstr "Texture 2D"
+
+#~ msgid "3D Texture"
+#~ msgstr "Texture 3D"
+
+#~ msgid "Atlas Texture"
+#~ msgstr "Texture dell'Atlas"
+
+#~ msgid ""
+#~ "NOTICE: Importing 2D textures is not mandatory. Just copy png/jpg files "
+#~ "to the project."
+#~ msgstr ""
+#~ "NOTA: Importare texture 2D non è obbligatorio. Basta copiare i file png/"
+#~ "jpg nel progetto."
+
+#~ msgid "Crop empty space."
+#~ msgstr "Ritaglia spazio vuoto."
+
+#~ msgid "Texture"
+#~ msgstr "Texture"
+
+#~ msgid "Import Large Texture"
+#~ msgstr "Importa Texture Grande"
+
+#~ msgid "Load Source Image"
+#~ msgstr "Carica Immagine Sorgente"
+
+#~ msgid "Slicing"
+#~ msgstr "Taglio"
+
+#~ msgid "Saving"
+#~ msgstr "Salvataggio"
+
+#~ msgid "Couldn't save large texture:"
+#~ msgstr "Impossibile salvare texture grande:"
+
+#~ msgid "Build Atlas For:"
+#~ msgstr "Costruisci Atlas Per:"
+
+#~ msgid "Loading Image:"
+#~ msgstr "Immagine Caricamento:"
+
+#~ msgid "Couldn't load image:"
+#~ msgstr "Impossibile caricare immagine:"
+
+#~ msgid "Converting Images"
+#~ msgstr "Convertendo Immagini"
+
+#~ msgid "Cropping Images"
+#~ msgstr "Tagliando Immagini"
+
+#~ msgid "Blitting Images"
+#~ msgstr "Bliting Immagini"
+
+#~ msgid "Couldn't save atlas image:"
+#~ msgstr "Impossibile salvare l'immagine di atlas:"
+
+#~ msgid "Couldn't save converted texture:"
+#~ msgstr "Impossibile salvare la texture convertita:"
+
+#~ msgid "Invalid source!"
+#~ msgstr "Sorgente invalida!"
+
+#~ msgid "Invalid translation source!"
+#~ msgstr "Sorgente traduzione invalida!"
+
+#~ msgid "Column"
+#~ msgstr "Colonna"
+
+#~ msgid "No items to import!"
+#~ msgstr "Nessun elemento da importare!"
+
+#~ msgid "No target path!"
+#~ msgstr "Nessun percorso di destinazione!"
+
+#~ msgid "Import Translations"
+#~ msgstr "Importa Traduzioni"
+
+#~ msgid "Couldn't import!"
+#~ msgstr "Impossibile Importare!"
+
+#~ msgid "Import Translation"
+#~ msgstr "Importa Traduzione"
+
+#~ msgid "Source CSV:"
+#~ msgstr "CSV Sorgente:"
+
+#~ msgid "Ignore First Row"
+#~ msgstr "Ignora Prima Riga"
+
+#~ msgid "Compress"
+#~ msgstr "Comprimi"
+
+#~ msgid "Add to Project (project.godot)"
+#~ msgstr "Aggiungi a Progetto (project.godot)"
+
+#~ msgid "Import Languages:"
+#~ msgstr "Importa Lingue:"
+
+#~ msgid "Translation"
+#~ msgstr "Traduzione"
+
+#~ msgid "Parsing %d Triangles:"
+#~ msgstr "Elaborazione %d Triangoli:"
+
+#~ msgid "Triangle #"
+#~ msgstr "Triangolo #"
+
+#~ msgid "Light Baker Setup:"
+#~ msgstr "Impostazioni Baker Luci:"
+
+#~ msgid "Fixing Lights"
+#~ msgstr "Aggiustando le Luci"
+
+#~ msgid "Making BVH"
+#~ msgstr "Creazione BVH"
+
+#~ msgid "Transfer to Lightmaps:"
+#~ msgstr "Trasferisci a Lightmap:"
+
+#~ msgid "Allocating Texture #"
+#~ msgstr "Allocazione Texture #"
+
+#~ msgid "Baking Triangle #"
+#~ msgstr "Backing Triangoli #"
+
+#~ msgid "Post-Processing Texture #"
+#~ msgstr "Texture Post-Processing #"
+
+#~ msgid "Reset the lightmap octree baking process (start over)."
+#~ msgstr "Resetta il processo di baking dell'octree (ricomincia da capo)."
+
+#~ msgid "Zoom (%):"
+#~ msgstr "Zoom(%):"
+
+#~ msgid "Skeleton.."
+#~ msgstr "Scheletro.."
+
+#~ msgid "Zoom Reset"
+#~ msgstr "Zoom Reset"
+
+#~ msgid "Zoom Set.."
+#~ msgstr "Imposta Zoom.."
+
+#~ msgid "Set a Value"
+#~ msgstr "Imposta un Valore"
+
+#~ msgid "Snap (Pixels):"
+#~ msgstr "Snap (Pixels):"
+
+#~ msgid "Parse BBCode"
+#~ msgstr "Decodifica BBCode"
+
+#~ msgid "Length:"
+#~ msgstr "Lunghezza:"
+
+#~ msgid "Open Sample File(s)"
+#~ msgstr "Apri File(s) Sample"
+
+#~ msgid "ERROR: Couldn't load sample!"
+#~ msgstr "ERRORE: Impossibile caricare sample!"
+
+#~ msgid "Add Sample"
+#~ msgstr "Aggiungi Sample"
+
+#~ msgid "Rename Sample"
+#~ msgstr "Rinomina Sample"
+
+#~ msgid "Delete Sample"
+#~ msgstr "Elimina Sample"
+
+#~ msgid "16 Bits"
+#~ msgstr "16 Bits"
+
+#~ msgid "8 Bits"
+#~ msgstr "8 Bits"
+
+#~ msgid "Stereo"
+#~ msgstr "Stereo"
+
+#~ msgid "Mono"
+#~ msgstr "Mono"
+
+#~ msgid "Pitch"
+#~ msgstr "Pitch"
+
+#~ msgid "Window"
+#~ msgstr "Finestra"
+
+#~ msgid "Move Right"
+#~ msgstr "Sposta a Destra"
+
+#~ msgid "Scaling to %s%%."
+#~ msgstr "Scalando a %s%%."
+
+#~ msgid "Up"
+#~ msgstr "Su"
+
+#~ msgid "Down"
+#~ msgstr "Giù"
+
+#~ msgid "Bucket"
+#~ msgstr "Secchiello"
+
+#~ msgid "Invalid project path, the path must exist!"
+#~ msgstr "Percorso di progetto invalido, il percorso deve esistere!"
+
+#~ msgid "Invalid project path, project.godot must not exist."
+#~ msgstr "Percorso di progetto invalido, project.godot non esiste."
+
+#~ msgid "Invalid project path, project.godot must exist."
+#~ msgstr "Percorso di progetto invalido, project.godot deve esistere."
+
+#~ msgid "Project Path (Must Exist):"
+#~ msgstr "Percorso Progetto (Deve Esistere):"
+
+#~ msgid "Create New Resource"
+#~ msgstr "Crea Nuova Risorsa"
+
+#~ msgid "Open Resource"
+#~ msgstr "Apri Risorsa"
+
+#~ msgid "Save Resource"
+#~ msgstr "Salva Risorsa"
+
+#~ msgid "Resource Tools"
+#~ msgstr "Strumenti Risorsa"
+
+#~ msgid "Make Local"
+#~ msgstr "Rendi Locale"
+
+#~ msgid "Edit Groups"
+#~ msgstr "Modifica Gruppi"
+
+#~ msgid "Edit Connections"
+#~ msgstr "Modifica Connessioni"
+
+#, fuzzy
+#~ msgid "Tiles"
+#~ msgstr " Files"
+
+#~ msgid "Ctrl+"
+#~ msgstr "Ctrl+"
+
#~ msgid "Close scene? (Unsaved changes will be lost)"
#~ msgstr "Chiudi scena? (I cambiamenti non salvati saranno persi)"
@@ -8026,9 +8351,6 @@ msgstr ""
#~ msgid "Close Goto Prev. Scene"
#~ msgstr "Vai a Scena Preced."
-#~ msgid "Expand to Parent"
-#~ msgstr "Espandi a Genitore"
-
#~ msgid "Del"
#~ msgstr "Elim."
@@ -8205,18 +8527,12 @@ msgstr ""
#~ msgid "Save Translatable Strings"
#~ msgstr "Salva Stringhe Traducibili"
-#~ msgid "Translatable Strings.."
-#~ msgstr "Stringhe Traducibili.."
-
#~ msgid "Install Export Templates"
#~ msgstr "Installa Template di Esportazione"
#~ msgid "Edit Script Options"
#~ msgstr "Modifica le opzioni di script"
-#~ msgid "Please export outside the project folder!"
-#~ msgstr "Si prega di esportare al di fuori della cartella del progetto!"
-
#~ msgid "Error exporting project!"
#~ msgstr "Errore di esportazione del progetto!"
@@ -8275,18 +8591,12 @@ msgstr ""
#~ msgid "Include"
#~ msgstr "Includi"
-#~ msgid "Change Image Group"
-#~ msgstr "Cambia Gruppo Immagine"
-
#~ msgid "Group name can't be empty!"
#~ msgstr "Il nome del gruppo non può essere vuoto!"
#~ msgid "Invalid character in group name!"
#~ msgstr "Carattere invalido nel nome del gruppo!"
-#~ msgid "Group name already exists!"
-#~ msgstr "Il nome del gruppo è già esistente!"
-
#~ msgid "Add Image Group"
#~ msgstr "Aggiungi Gruppo Immagini"
@@ -8365,9 +8675,6 @@ msgstr ""
#~ msgid "Preview Atlas"
#~ msgstr "Anteprima Atlas"
-#~ msgid "Image Filter:"
-#~ msgstr "Filtro Immagine:"
-
#~ msgid "Images:"
#~ msgstr "Immagini:"
@@ -8434,9 +8741,6 @@ msgstr ""
#~ msgid "Lighting"
#~ msgstr "Illuminazione"
-#~ msgid "Toggle Persisting"
-#~ msgstr "Attiva Persistenza"
-
#~ msgid "Global"
#~ msgstr "Globale"
diff --git a/editor/translations/ja.po b/editor/translations/ja.po
index 51c481f3d4..59d3b9499b 100644
--- a/editor/translations/ja.po
+++ b/editor/translations/ja.po
@@ -1,9 +1,10 @@
# Japanese translation of the Godot Engine editor
-# Copyright (C) 2016-2017 Juan Linietsky, Ariel Manzur and the Godot community
+# Copyright (C) 2007-2017 Juan Linietsky, Ariel Manzur
+# Copyright (C) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)
# This file is distributed under the same license as the Godot source code.
#
# akirakido <achts.y@gmail.com>, 2016-2017.
-# hopping tappy (ãŸã£ã´ã•ã‚“) <hopping.tappy@gmail.com>, 2016.
+# hopping tappy (ãŸã£ã´ã•ã‚“) <hopping.tappy@gmail.com>, 2016-2017.
# Lexi Grafen <shfeedly@gmail.com>, 2017.
# Tetsuji Ochiai <ochiaixp@gmail.com>, 2017.
# Tohru Ike (rokujyouhitoma) <rokujyouhitomajp@gmail.com>, 2017.
@@ -11,15 +12,15 @@
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
-"PO-Revision-Date: 2017-07-27 05:10+0000\n"
-"Last-Translator: Tetsuji Ochiai <ochiaixp@gmail.com>\n"
+"PO-Revision-Date: 2017-08-28 04:47+0000\n"
+"Last-Translator: hopping tappy <hopping.tappy@gmail.com>\n"
"Language-Team: Japanese <https://hosted.weblate.org/projects/godot-engine/"
"godot/ja/>\n"
"Language: ja\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8-bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
-"X-Generator: Weblate 2.16-dev\n"
+"X-Generator: Weblate 2.17-dev\n"
#: editor/animation_editor.cpp
msgid "Disabled"
@@ -211,10 +212,9 @@ msgid "Create %d NEW tracks and insert keys?"
msgstr "æ–°ã—ã„ %d トラックを作æˆã—ã€ã‚­ãƒ¼ã‚’挿入ã—ã¾ã™ã‹ï¼Ÿ"
#: editor/animation_editor.cpp editor/create_dialog.cpp
-#: editor/editor_audio_buses.cpp
+#: editor/editor_audio_buses.cpp editor/plugins/abstract_polygon_2d_editor.cpp
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
#: editor/plugins/mesh_instance_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp editor/project_manager.cpp
#: editor/script_create_dialog.cpp
msgid "Create"
@@ -378,313 +378,6 @@ msgstr "é…列ã®å€¤ã®ç¨®é¡žã®å¤‰æ›´"
msgid "Change Array Value"
msgstr "é…列ã®å€¤ã‚’変更"
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Free"
-msgstr "解放"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_plugin_settings.cpp
-#, fuzzy
-msgid "Version:"
-msgstr "ãƒãƒ¼ã‚¸ãƒ§ãƒ³:"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Contents:"
-msgstr "コンテンツ:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "View Files"
-msgstr "ビューファイル:"
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_help.cpp editor/property_selector.cpp
-#: editor/script_editor_debugger.cpp
-#, fuzzy
-msgid "Description:"
-msgstr "記述:"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-#: editor/project_manager.cpp
-#, fuzzy
-msgid "Install"
-msgstr "インストール"
-
-#: editor/asset_library_editor_plugin.cpp editor/call_dialog.cpp
-#: editor/connections_dialog.cpp editor/export_template_manager.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-#: editor/project_settings_editor.cpp editor/property_editor.cpp
-#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Close"
-msgstr "é–‰ã˜ã‚‹"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve hostname:"
-msgstr "ホストåを解決ã§ãã¾ã›ã‚“:"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Can't resolve."
-msgstr "解決ã§ãã¾ã›ã‚“."
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Connection error, please try again."
-msgstr "接続失敗 å†è©¦è¡Œã‚’"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Can't connect."
-msgstr "接続失敗."
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Can't connect to host:"
-msgstr "ホストã«æŽ¥ç¶šã§ãã¾ã›ã‚“:"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "No response from host:"
-msgstr "ホストã‹ã‚‰å¿œç­”ãŒã‚ã‚Šã¾ã›ã‚“:"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "No response."
-msgstr "応答ãŒã‚ã‚Šã¾ã›ã‚“."
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Request failed, return code:"
-msgstr "リクエスト失敗 リターン コード:"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Req. Failed."
-msgstr "リクエスト失敗."
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Request failed, too many redirects"
-msgstr "リクエスト失敗 リダイレクトã®å›žæ•°ãŒå¤šã™ãŽã¾ã™"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Redirect Loop."
-msgstr "リダイレクトã®ãƒ«ãƒ¼ãƒ—."
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Failed:"
-msgstr "失敗:"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Bad download hash, assuming file has been tampered with."
-msgstr "ダウンロード内容ã®ãƒãƒƒã‚·ãƒ¥ãŒä¸æ•´åˆã€€æ”¹ã–ã‚“ã®å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™."
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Expected:"
-msgstr "予測:"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Got:"
-msgstr "å–å¾—:"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Failed sha256 hash check"
-msgstr "sha256ã®ãƒãƒƒã‚·ãƒ¥ãƒã‚§ãƒƒã‚¯å¤±æ•—"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Asset Download Error:"
-msgstr "アセットã®ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰å¤±æ•—:"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-#, fuzzy
-msgid "Success!"
-msgstr "æˆåŠŸï¼"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Fetching:"
-msgstr "å–得中:"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Resolving.."
-msgstr "解決中.."
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Connecting.."
-msgstr "接続中.."
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Requesting.."
-msgstr "リクエスト中.."
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Error making request"
-msgstr "リクエスト発行エラー"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Idle"
-msgstr "待機中"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Retry"
-msgstr "å†è©¦è¡Œ"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Download Error"
-msgstr "ダウンロード失敗"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Download for this asset is already in progress!"
-msgstr "ã“ã®ã‚¢ã‚»ãƒƒãƒˆã®ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ã¯æ—¢ã«é€²è¡Œä¸­ï¼"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "first"
-msgstr "最åˆã®"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "prev"
-msgstr "å‰ã®"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "next"
-msgstr "次ã®"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "last"
-msgstr "最後ã®"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "All"
-msgstr "ã™ã¹ã¦ã®"
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
-#: editor/settings_config_dialog.cpp
-#, fuzzy
-msgid "Search:"
-msgstr "検索:"
-
-#: editor/asset_library_editor_plugin.cpp editor/code_editor.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
-#, fuzzy
-msgid "Search"
-msgstr "検索"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/project_manager.cpp
-msgid "Import"
-msgstr "インãƒãƒ¼ãƒˆï¼ˆå–ã‚Šè¾¼ã¿ï¼‰"
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-#, fuzzy
-msgid "Plugins"
-msgstr "プラグイン"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Sort:"
-msgstr "並ã¹æ›¿ãˆ:"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Reverse"
-msgstr "逆"
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-#, fuzzy
-msgid "Category:"
-msgstr "カテゴリー:"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Site:"
-msgstr "サイト:"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Support.."
-msgstr "サãƒãƒ¼ãƒˆ.."
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Official"
-msgstr "å…¬å¼"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-#, fuzzy
-msgid "Community"
-msgstr "コミュニティ"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Testing"
-msgstr "テスト中"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Assets ZIP File"
-msgstr "アセットã®zipファイル"
-
-#: editor/call_dialog.cpp
-#, fuzzy
-msgid "Method List For '%s':"
-msgstr "'%s' ã®ãƒ¡ã‚½ãƒƒãƒ‰ä¸€è¦§ï¼š"
-
-#: editor/call_dialog.cpp modules/visual_script/visual_script_editor.cpp
-#, fuzzy
-msgid "Call"
-msgstr "呼ã³å‡ºã—"
-
-#: editor/call_dialog.cpp
-#, fuzzy
-msgid "Method List:"
-msgstr "メソッド一覧:"
-
-#: editor/call_dialog.cpp
-#, fuzzy
-msgid "Arguments:"
-msgstr "引数:"
-
-#: editor/call_dialog.cpp
-#, fuzzy
-msgid "Return:"
-msgstr "戻り値:"
-
#: editor/code_editor.cpp
#, fuzzy
msgid "Go to Line"
@@ -730,6 +423,15 @@ msgstr "å˜èªžå…¨ä½“"
msgid "Selection Only"
msgstr "é¸æŠžç¯„囲ã®ã¿"
+#: editor/code_editor.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Search"
+msgstr "検索"
+
#: editor/code_editor.cpp editor/editor_help.cpp
#, fuzzy
msgid "Find"
@@ -769,12 +471,12 @@ msgstr "ç½®æ›æ™‚ã«ç¢ºèª"
msgid "Skip"
msgstr "スキップ"
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
#, fuzzy
msgid "Zoom In"
msgstr "ズームイン"
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
#, fuzzy
msgid "Zoom Out"
msgstr "ズームアウト"
@@ -855,6 +557,20 @@ msgstr "é…延"
msgid "Oneshot"
msgstr "一括"
+#: editor/connections_dialog.cpp editor/dependency_editor.cpp
+#: editor/export_template_manager.cpp
+#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Close"
+msgstr "é–‰ã˜ã‚‹"
+
#: editor/connections_dialog.cpp
#, fuzzy
msgid "Connect"
@@ -886,7 +602,7 @@ msgstr "接続.."
msgid "Disconnect"
msgstr "切断"
-#: editor/connections_dialog.cpp editor/node_dock.cpp
+#: editor/connections_dialog.cpp editor/editor_help.cpp editor/node_dock.cpp
#, fuzzy
msgid "Signals"
msgstr "シグナル"
@@ -905,6 +621,14 @@ msgstr "ãŠæ°—ã«å…¥ã‚Š:"
msgid "Recent:"
msgstr "最近ã®:"
+#: editor/create_dialog.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/quick_open.cpp editor/settings_config_dialog.cpp
+#, fuzzy
+msgid "Search:"
+msgstr "検索:"
+
#: editor/create_dialog.cpp editor/editor_help.cpp
#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/quick_open.cpp
@@ -912,6 +636,13 @@ msgstr "最近ã®:"
msgid "Matches:"
msgstr "一致:"
+#: editor/create_dialog.cpp editor/editor_help.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/property_selector.cpp
+#: editor/script_editor_debugger.cpp
+#, fuzzy
+msgid "Description:"
+msgstr "記述:"
+
#: editor/dependency_editor.cpp
#, fuzzy
msgid "Search Replacement For:"
@@ -981,6 +712,11 @@ msgstr "~ã®ã‚ªãƒ¼ãƒŠãƒ¼:"
#: editor/dependency_editor.cpp
#, fuzzy
+msgid "Remove selected files from the project? (no undo)"
+msgstr "é¸æŠžã—ãŸãƒ•ã‚¡ã‚¤ãƒ«ã‚’プロジェクトã‹ã‚‰å–り除ã(å–り消ã—ã§ãã¾ã›ã‚“)"
+
+#: editor/dependency_editor.cpp
+#, fuzzy
msgid ""
"The files being removed are required by other resources in order for them to "
"work.\n"
@@ -991,8 +727,8 @@ msgstr ""
#: editor/dependency_editor.cpp
#, fuzzy
-msgid "Remove selected files from the project? (no undo)"
-msgstr "é¸æŠžã—ãŸãƒ•ã‚¡ã‚¤ãƒ«ã‚’プロジェクトã‹ã‚‰å–り除ã(å–り消ã—ã§ãã¾ã›ã‚“)"
+msgid "Cannot remove:\n"
+msgstr "解決ã§ãã¾ã›ã‚“."
#: editor/dependency_editor.cpp
#, fuzzy
@@ -1070,11 +806,6 @@ msgstr "Godotエンジンã«è²¢çŒ®ã—ãŸäººã€…"
#: editor/editor_about.cpp
#, fuzzy
-msgid "Authors"
-msgstr "作者:"
-
-#: editor/editor_about.cpp
-#, fuzzy
msgid "Project Founders"
msgstr "プロジェクトマãƒãƒ¼ã‚¸ãƒ£ãƒ¼"
@@ -1093,10 +824,44 @@ msgid "Developers"
msgstr "開発者"
#: editor/editor_about.cpp
-msgid "License"
+#, fuzzy
+msgid "Authors"
+msgstr "作者:"
+
+#: editor/editor_about.cpp
+msgid "Platinum Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Gold Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Mini Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Gold Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Silver Donors"
msgstr ""
#: editor/editor_about.cpp
+#, fuzzy
+msgid "Bronze Donors"
+msgstr "複製ã—ã¦ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰"
+
+#: editor/editor_about.cpp
+msgid "Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "License"
+msgstr "ライセンス"
+
+#: editor/editor_about.cpp
msgid "Thirdparty License"
msgstr ""
@@ -1136,13 +901,25 @@ msgid "Package Installed Successfully!"
msgstr "パッケージインストールæˆåŠŸ!"
#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Success!"
+msgstr "æˆåŠŸï¼"
+
+#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/project_manager.cpp
+#, fuzzy
+msgid "Install"
+msgstr "インストール"
+
+#: editor/editor_asset_installer.cpp
#, fuzzy
msgid "Package Installer"
msgstr "パッケージインストールæˆåŠŸ!"
#: editor/editor_audio_buses.cpp
msgid "Speakers"
-msgstr ""
+msgstr "スピーカー"
#: editor/editor_audio_buses.cpp
#, fuzzy
@@ -1190,11 +967,6 @@ msgid "Audio Bus, Drag and Drop to rearrange."
msgstr ""
#: editor/editor_audio_buses.cpp
-#, fuzzy
-msgid "Bus options"
-msgstr "サブシーンã®ã‚ªãƒ—ション"
-
-#: editor/editor_audio_buses.cpp
msgid "Solo"
msgstr ""
@@ -1206,6 +978,11 @@ msgstr ""
msgid "Bypass"
msgstr ""
+#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Bus options"
+msgstr "サブシーンã®ã‚ªãƒ—ション"
+
#: editor/editor_audio_buses.cpp editor/plugins/tile_map_editor_plugin.cpp
#: editor/scene_tree_dock.cpp
msgid "Duplicate"
@@ -1213,6 +990,11 @@ msgstr "複製"
#: editor/editor_audio_buses.cpp
#, fuzzy
+msgid "Reset Volume"
+msgstr "ズームをリセット"
+
+#: editor/editor_audio_buses.cpp
+#, fuzzy
msgid "Delete Effect"
msgstr "é¸æŠžç¯„囲を消去"
@@ -1237,6 +1019,11 @@ msgstr "アニメーションを複製"
#: editor/editor_audio_buses.cpp
#, fuzzy
+msgid "Reset Bus Volume"
+msgstr "ズームをリセット"
+
+#: editor/editor_audio_buses.cpp
+#, fuzzy
msgid "Move Audio Bus"
msgstr "移動動作"
@@ -1276,7 +1063,8 @@ msgstr "ãƒã‚¹ã‚’追加ã™ã‚‹"
msgid "Create a new Bus Layout."
msgstr "æ–°ã—ã„リソースを生æˆ"
-#: editor/editor_audio_buses.cpp editor/script_create_dialog.cpp
+#: editor/editor_audio_buses.cpp editor/property_editor.cpp
+#: editor/script_create_dialog.cpp
#, fuzzy
msgid "Load"
msgstr "読ã¿è¾¼ã‚€"
@@ -1385,7 +1173,7 @@ msgid "Rearrange Autoloads"
msgstr "自動読ã¿è¾¼ã¿ã‚’組ã¿æ›¿ãˆã‚‹"
#: editor/editor_autoload_settings.cpp editor/editor_file_dialog.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp scene/gui/file_dialog.cpp
+#: scene/gui/file_dialog.cpp
msgid "Path:"
msgstr "Path:"
@@ -1394,9 +1182,7 @@ msgstr "Path:"
msgid "Node Name:"
msgstr "ノードã®åå‰:"
-#: editor/editor_autoload_settings.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp editor/project_manager.cpp
+#: editor/editor_autoload_settings.cpp editor/project_manager.cpp
#, fuzzy
msgid "Name"
msgstr "åå‰"
@@ -1434,18 +1220,19 @@ msgid "Choose a Directory"
msgstr "ディレクトリをé¸ã¶"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Create Folder"
msgstr "フォルダを作æˆã™ã‚‹"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: editor/editor_plugin_settings.cpp editor/plugins/theme_editor_plugin.cpp
-#: editor/project_export.cpp scene/gui/file_dialog.cpp
+#: editor/editor_plugin_settings.cpp editor/filesystem_dock.cpp
+#: editor/plugins/theme_editor_plugin.cpp editor/project_export.cpp
+#: scene/gui/file_dialog.cpp
msgid "Name:"
msgstr "åå‰:"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Could not create folder."
msgstr "フォルダを作æˆã§ãã¾ã›ã‚“ã§ã—ãŸã€‚"
@@ -1469,35 +1256,6 @@ msgstr "パッキングã™ã‚‹"
msgid "Template file not found:\n"
msgstr "テンプレートファイルãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“:\n"
-#: editor/editor_export.cpp
-#, fuzzy
-msgid "Added:"
-msgstr "加ãˆãŸã®ã¯:"
-
-#: editor/editor_export.cpp
-msgid "Removed:"
-msgstr "å–り除ã„ãŸã®ã¯:"
-
-#: editor/editor_export.cpp
-#, fuzzy
-msgid "Error saving atlas:"
-msgstr "アトラスã®ä¿å­˜ã«å¤±æ•—ã—ã¾ã—ãŸ:"
-
-#: editor/editor_export.cpp
-#, fuzzy
-msgid "Could not save atlas subtexture:"
-msgstr "アトラスã®è¦ç´ ã§ã‚るテクスãƒãƒ£ã®ä¿å­˜ãŒã§ãã¾ã›ã‚“:"
-
-#: editor/editor_export.cpp
-#, fuzzy
-msgid "Exporting for %s"
-msgstr "%sã«ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆä¸­"
-
-#: editor/editor_export.cpp
-#, fuzzy
-msgid "Setting Up.."
-msgstr "セットアップ中.."
-
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "File Exists, Overwrite?"
msgstr "ファイルãŒæ—¢ã«å­˜åœ¨ã—ã¾ã™ã€‚上書ãã—ã¾ã™ã‹ï¼Ÿ"
@@ -1593,6 +1351,11 @@ msgstr "ãŠæ°—ã«å…¥ã‚Šã‚’上ã’ã‚‹"
msgid "Move Favorite Down"
msgstr "ãŠæ°—ã«å…¥ã‚Šã‚’下ã’ã‚‹"
+#: editor/editor_file_dialog.cpp
+#, fuzzy
+msgid "Go to parent folder"
+msgstr "フォルダを作æˆã§ãã¾ã›ã‚“ã§ã—ãŸã€‚"
+
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Directories & Files:"
msgstr "ディレクトリã¾ãŸã¯ãƒ•ã‚¡ã‚¤ãƒ«:"
@@ -1608,10 +1371,6 @@ msgid "File:"
msgstr "ファイル:"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
-msgid "Filter:"
-msgstr "フィルター:"
-
-#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Must use a valid extension."
msgstr "有効ãªæ‹¡å¼µå­ã‚’使用ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚"
@@ -1640,6 +1399,10 @@ msgstr "クラスã®ãƒªã‚¹ãƒˆ:"
msgid "Search Classes"
msgstr "クラスã®æ¤œç´¢"
+#: editor/editor_help.cpp editor/plugins/spatial_editor_plugin.cpp
+msgid "Top"
+msgstr "上é¢"
+
#: editor/editor_help.cpp editor/property_editor.cpp
#, fuzzy
msgid "Class:"
@@ -1660,6 +1423,11 @@ msgstr "~ã«ç¶™æ‰¿ã•ã‚Œã‚‹:"
msgid "Brief Description:"
msgstr "è¦ç´„:"
+#: editor/editor_help.cpp
+#, fuzzy
+msgid "Members"
+msgstr "メンãƒãƒ¼:"
+
#: editor/editor_help.cpp modules/visual_script/visual_script_editor.cpp
#, fuzzy
msgid "Members:"
@@ -1667,11 +1435,21 @@ msgstr "メンãƒãƒ¼:"
#: editor/editor_help.cpp
#, fuzzy
+msgid "Public Methods"
+msgstr "公開メソッド:"
+
+#: editor/editor_help.cpp
+#, fuzzy
msgid "Public Methods:"
msgstr "公開メソッド:"
#: editor/editor_help.cpp
#, fuzzy
+msgid "GUI Theme Items"
+msgstr "GUIテーマã®éƒ¨å“:"
+
+#: editor/editor_help.cpp
+#, fuzzy
msgid "GUI Theme Items:"
msgstr "GUIテーマã®éƒ¨å“:"
@@ -1682,6 +1460,11 @@ msgstr "シグナル:"
#: editor/editor_help.cpp
#, fuzzy
+msgid "Enumerations"
+msgstr "アニメーション"
+
+#: editor/editor_help.cpp
+#, fuzzy
msgid "Enumerations:"
msgstr "アニメーション"
@@ -1691,20 +1474,52 @@ msgstr ""
#: editor/editor_help.cpp
#, fuzzy
+msgid "Constants"
+msgstr "定数:"
+
+#: editor/editor_help.cpp
+#, fuzzy
msgid "Constants:"
msgstr "定数:"
#: editor/editor_help.cpp
#, fuzzy
+msgid "Description"
+msgstr "記述:"
+
+#: editor/editor_help.cpp
+#, fuzzy
+msgid "Properties"
+msgstr "プロパティ:"
+
+#: editor/editor_help.cpp
+#, fuzzy
msgid "Property Description:"
msgstr "プロパティã«ã¤ã„ã¦ã®è¨˜è¼‰:"
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this property. Please help us by "
+"[color=$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+
+#: editor/editor_help.cpp
+#, fuzzy
+msgid "Methods"
+msgstr "メソッド一覧:"
+
+#: editor/editor_help.cpp
#, fuzzy
msgid "Method Description:"
msgstr "メソッドã«ã¤ã„ã¦ã®è¨˜è¼‰:"
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this method. Please help us by [color="
+"$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+
+#: editor/editor_help.cpp
#, fuzzy
msgid "Search Text"
msgstr "テキストを探ã™"
@@ -1715,26 +1530,23 @@ msgid "Output:"
msgstr " 出力:"
#: editor/editor_log.cpp editor/plugins/animation_tree_editor_plugin.cpp
-#: editor/plugins/rich_text_editor_plugin.cpp editor/property_editor.cpp
-#: editor/script_editor_debugger.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/property_editor.cpp editor/script_editor_debugger.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Clear"
msgstr "削除"
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
#, fuzzy
msgid "Error saving resource!"
msgstr "リソースä¿å­˜ã‚¨ãƒ©ãƒ¼!"
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
#, fuzzy
msgid "Save Resource As.."
msgstr "~ã¨ã„ã†åå‰ã§ãƒªã‚½ãƒ¼ã‚¹ã‚’ä¿å­˜ã™ã‚‹"
-#: editor/editor_node.cpp editor/export_template_manager.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
#, fuzzy
msgid "I see.."
msgstr "ã‚ã‹ã£ãŸ.."
@@ -1755,6 +1567,30 @@ msgid "Error while saving."
msgstr "ä¿å­˜ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒèµ·ãã¾ã—ãŸ."
#: editor/editor_node.cpp
+#, fuzzy
+msgid "Can't open '%s'."
+msgstr "'..'を処ç†ã§ãã¾ã›ã‚“"
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Error while parsing '%s'."
+msgstr "ä¿å­˜ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒèµ·ãã¾ã—ãŸ."
+
+#: editor/editor_node.cpp
+msgid "Unexpected end of file '%s'."
+msgstr ""
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Missing '%s' or its dependencies."
+msgstr "シーン'%s' ã¯ä¾å­˜é–¢ä¿‚ãŒå£Šã‚Œã¦ã„ã¾ã™:"
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Error while loading '%s'."
+msgstr "ä¿å­˜ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒèµ·ãã¾ã—ãŸ."
+
+#: editor/editor_node.cpp
msgid "Saving Scene"
msgstr "シーンをä¿å­˜"
@@ -1826,6 +1662,33 @@ msgid "Restored default layout to base settings."
msgstr "標準レイアウトを基本設定ã«æˆ»ã—ã¾ã—ãŸ"
#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was imported, so it's not editable.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was instanced or inherited.\n"
+"Changes to it will not be kept when saving the current scene."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource was imported, so it's not editable. Change its settings in the "
+"import panel and then re-import."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This scene was imported, so changes to it will not be kept.\n"
+"Instancing it or inheriting will allow making changes to it.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+
+#: editor/editor_node.cpp
#, fuzzy
msgid "Copy Params"
msgstr "パラメーターをコピーã™ã‚‹"
@@ -2025,24 +1888,36 @@ msgid "Save changes the following scene(s) before opening Project Manager?"
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"This option is deprecated. Situations where refresh must be forced are now "
+"considered a bug. Please report."
+msgstr ""
+
+#: editor/editor_node.cpp
#, fuzzy
msgid "Pick a Main Scene"
msgstr "メインシーンを指定"
#: editor/editor_node.cpp
-msgid "Unable to enable addon plugin at: '"
+msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr ""
#: editor/editor_node.cpp
-msgid "' parsing of config failed."
+msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/"
+#, fuzzy
+msgid "Unable to load addon script from path: '%s'."
+msgstr "フォント読ã¿è¾¼ã¿ã‚¨ãƒ©ãƒ¼ã€‚"
+
+#: editor/editor_node.cpp
+msgid ""
+"Unable to load addon script from path: '%s' Base type is not EditorPlugin."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to load addon script from path: '"
+msgid "Unable to load addon script from path: '%s' Script is not in tool mode."
msgstr ""
#: editor/editor_node.cpp
@@ -2054,7 +1929,7 @@ msgstr ""
"変更ã™ã‚‹ãŸã‚ã«ã¯ã€ã‚·ãƒ¼ãƒ³ã‚’継承ã—ã¦æ–°ã—ã生æˆã—ã¾ã™."
#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/scene_tree_dock.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
#, fuzzy
msgid "Ugh"
msgstr "ã†ã‡"
@@ -2070,13 +1945,13 @@ msgstr ""
#: editor/editor_node.cpp
#, fuzzy
-msgid "Error loading scene."
-msgstr "シーンã®èª­ã¿è¾¼ã¿ã‚¨ãƒ©ãƒ¼"
+msgid "Scene '%s' has broken dependencies:"
+msgstr "シーン'%s' ã¯ä¾å­˜é–¢ä¿‚ãŒå£Šã‚Œã¦ã„ã¾ã™:"
#: editor/editor_node.cpp
#, fuzzy
-msgid "Scene '%s' has broken dependencies:"
-msgstr "シーン'%s' ã¯ä¾å­˜é–¢ä¿‚ãŒå£Šã‚Œã¦ã„ã¾ã™:"
+msgid "Clear Recent Scenes"
+msgstr "最近開ã„ãŸãƒ•ã‚¡ã‚¤ãƒ«ã®è¨˜éŒ²ã‚’クリア"
#: editor/editor_node.cpp
msgid "Save Layout"
@@ -2117,7 +1992,7 @@ msgstr "最低é™ãƒ¢ãƒ¼ãƒ‰"
msgid "Toggle distraction-free mode."
msgstr "最低é™ãƒ¢ãƒ¼ãƒ‰"
-#: editor/editor_node.cpp editor/io_plugins/editor_scene_import_plugin.cpp
+#: editor/editor_node.cpp
#, fuzzy
msgid "Scene"
msgstr "シーン"
@@ -2177,9 +2052,8 @@ msgid "Close Scene"
msgstr "シーンを閉ã˜ã‚‹"
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Open Recent"
-msgstr "最近ã®ã‚’é–‹ã"
+msgstr "最近使ã£ãŸãƒ•ã‚¡ã‚¤ãƒ«ã‚’é–‹ã"
#: editor/editor_node.cpp
#, fuzzy
@@ -2394,6 +2268,11 @@ msgstr "Q&A"
msgid "Issue Tracker"
msgstr "課題(ãƒã‚°ï¼‰ç®¡ç†ã‚·ã‚¹ãƒ†ãƒ "
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Community"
+msgstr "コミュニティ"
+
#: editor/editor_node.cpp
#, fuzzy
msgid "About"
@@ -2404,7 +2283,7 @@ msgstr "ã«ã¤ã„ã¦"
msgid "Play the project."
msgstr "プロジェクトã®å®Ÿè¡Œ"
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
#, fuzzy
msgid "Play"
msgstr "実行"
@@ -2424,7 +2303,7 @@ msgstr "シーンを一時åœæ­¢"
msgid "Stop the scene."
msgstr "シーンを止ã‚ã‚‹"
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
#, fuzzy
msgid "Stop"
msgstr "æ­¢ã‚ã‚‹"
@@ -2513,6 +2392,16 @@ msgstr "オブジェクトã®ãƒ—ロパティ"
#: editor/editor_node.cpp
#, fuzzy
+msgid "Changes may be lost!"
+msgstr "ベクトル定数を変更"
+
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Import"
+msgstr "インãƒãƒ¼ãƒˆï¼ˆå–ã‚Šè¾¼ã¿ï¼‰"
+
+#: editor/editor_node.cpp
+#, fuzzy
msgid "FileSystem"
msgstr "ファイルシステム"
@@ -2530,14 +2419,6 @@ msgstr "出力"
msgid "Don't Save"
msgstr ""
-#: editor/editor_node.cpp editor/editor_reimport_dialog.cpp
-msgid "Re-Import"
-msgstr "å†ã‚¤ãƒ³ãƒãƒ¼ãƒˆ"
-
-#: editor/editor_node.cpp editor/editor_plugin_settings.cpp
-msgid "Update"
-msgstr "アップデート"
-
#: editor/editor_node.cpp
#, fuzzy
msgid "Import Templates From ZIP File"
@@ -2607,11 +2488,30 @@ msgstr "次ã®ã‚¨ãƒ‡ã‚£ã‚¿ã‚’é–‹ã"
msgid "Open the previous Editor"
msgstr "å‰ã®ã‚¨ãƒ‡ã‚£ã‚¿ã‚’é–‹ã"
+#: editor/editor_plugin.cpp
+#, fuzzy
+msgid "Creating Mesh Previews"
+msgstr "メッシュライブラリを生æˆ"
+
+#: editor/editor_plugin.cpp
+msgid "Thumbnail.."
+msgstr "サムãƒã‚¤ãƒ«.."
+
#: editor/editor_plugin_settings.cpp
msgid "Installed Plugins:"
msgstr "インストール済ã¿ã®ãƒ—ラグイン:"
#: editor/editor_plugin_settings.cpp
+msgid "Update"
+msgstr "アップデート"
+
+#: editor/editor_plugin_settings.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Version:"
+msgstr "ãƒãƒ¼ã‚¸ãƒ§ãƒ³:"
+
+#: editor/editor_plugin_settings.cpp
#, fuzzy
msgid "Author:"
msgstr "作者:"
@@ -2652,7 +2552,7 @@ msgstr "フレーム %"
#: editor/editor_profiler.cpp
#, fuzzy
-msgid "Fixed Frame %"
+msgid "Physics Frame %"
msgstr "固定フレーム %"
#: editor/editor_profiler.cpp editor/script_editor_debugger.cpp
@@ -2675,31 +2575,6 @@ msgstr "セルフ"
msgid "Frame #:"
msgstr "フレーム #:"
-#: editor/editor_reimport_dialog.cpp
-#, fuzzy
-msgid "Please wait for scan to complete."
-msgstr "走査完了をãŠå¾…ã¡ãã ã•ã„"
-
-#: editor/editor_reimport_dialog.cpp
-#, fuzzy
-msgid "Current scene must be saved to re-import."
-msgstr "å†ã‚¤ãƒ³ãƒãƒ¼ãƒˆã™ã‚‹ãŸã‚ã«ã¯ç¾åœ¨ã®ã‚·ãƒ¼ãƒ³ã‚’ä¿å­˜ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™"
-
-#: editor/editor_reimport_dialog.cpp
-#, fuzzy
-msgid "Save & Re-Import"
-msgstr "ä¿å­˜ã—ã¦å†ã‚¤ãƒ³ãƒãƒ¼ãƒˆ"
-
-#: editor/editor_reimport_dialog.cpp
-#, fuzzy
-msgid "Re-Importing"
-msgstr "å†ã‚¤ãƒ³ãƒãƒ¼ãƒˆ"
-
-#: editor/editor_reimport_dialog.cpp
-#, fuzzy
-msgid "Re-Import Changed Resources"
-msgstr "変更ã—ãŸãƒªã‚½ãƒ¼ã‚¹ã‚’å†ã‚¤ãƒ³ãƒãƒ¼ãƒˆ"
-
#: editor/editor_run_native.cpp
msgid "Select device from the list"
msgstr ""
@@ -2833,11 +2708,6 @@ msgstr "インãƒãƒ¼ãƒˆ:"
#: editor/export_template_manager.cpp
#, fuzzy
-msgid "Loading Export Templates"
-msgstr "エクスãƒãƒ¼ãƒˆã€€ãƒ†ãƒ³ãƒ—レートã®èª­ã¿è¾¼ã¿"
-
-#: editor/export_template_manager.cpp
-#, fuzzy
msgid "Current Version:"
msgstr "ç¾åœ¨ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³:"
@@ -2879,11 +2749,18 @@ msgid "Cannot navigate to '"
msgstr "~ã«ç§»å‹•ã§ãã¾ã›ã‚“"
#: editor/filesystem_dock.cpp
-#, fuzzy
+msgid "View items as a grid of thumbnails"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "View items as a list"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
msgid ""
"\n"
-"Status: Needs Re-Import"
-msgstr "ä¿å­˜ã—ã¦å†ã‚¤ãƒ³ãƒãƒ¼ãƒˆ"
+"Status: Import of file failed. Please fix file and reimport manually."
+msgstr ""
#: editor/filesystem_dock.cpp
#, fuzzy
@@ -2894,51 +2771,55 @@ msgstr "ソース:"
#: editor/filesystem_dock.cpp
#, fuzzy
-msgid "Same source and destination files, doing nothing."
-msgstr "åŒã˜ãƒ•ã‚¡ã‚¤ãƒ«ãŒæŒ‡å®šã•ã‚Œã¦ã„ã‚‹ã®ã§ã€ä½•ã‚‚è¡Œã„ã¾ã›ã‚“."
+msgid "Cannot move/rename resources root."
+msgstr "ソースã®ãƒ•ã‚©ãƒ³ãƒˆã‚’読ã¿è¾¼ã¿/処ç†ã§ãã¾ã›ã‚“."
#: editor/filesystem_dock.cpp
-msgid "Target file exists, can't overwrite. Delete first."
-msgstr ""
+#, fuzzy
+msgid "Cannot move a folder into itself.\n"
+msgstr "åŒã˜ãƒ•ã‚¡ã‚¤ãƒ«ã«ã‚¤ãƒ³ãƒãƒ¼ãƒˆã§ãã¾ã›ã‚“:"
#: editor/filesystem_dock.cpp
#, fuzzy
-msgid "Same source and destination paths, doing nothing."
-msgstr "åŒã˜ãƒ‘スãŒæŒ‡å®šã•ã‚Œã¦ã„ã‚‹ã®ã§ã€ä½•ã‚‚è¡Œã„ã¾ã›ã‚“"
+msgid "Error moving:\n"
+msgstr "エラーをインãƒãƒ¼ãƒˆä¸­:"
#: editor/filesystem_dock.cpp
#, fuzzy
-msgid "Can't move directories to within themselves."
-msgstr "ディレクトリを自身ã®å†…部ã«ã¯ç§»å‹•ã§ãã¾ã›ã‚“"
+msgid "Unable to update dependencies:\n"
+msgstr "シーン'%s' ã¯ä¾å­˜é–¢ä¿‚ãŒå£Šã‚Œã¦ã„ã¾ã™:"
#: editor/filesystem_dock.cpp
-msgid "Can't rename deps for:\n"
+msgid "No name provided"
msgstr ""
#: editor/filesystem_dock.cpp
-#, fuzzy
-msgid "Error moving file:\n"
-msgstr "イメージ読ã¿è¾¼ã¿ã‚¨ãƒ©ãƒ¼:"
+msgid "Provided name contains invalid characters"
+msgstr ""
#: editor/filesystem_dock.cpp
#, fuzzy
-msgid "Error moving dir:\n"
-msgstr "エラーをインãƒãƒ¼ãƒˆä¸­:"
+msgid "No name provided."
+msgstr "åå‰ã‚’変ãˆã‚‹ã‹ç§»å‹•ã—ã¦ãã ã•ã„.."
#: editor/filesystem_dock.cpp
#, fuzzy
-msgid "Can't operate on '..'"
-msgstr "'..'を処ç†ã§ãã¾ã›ã‚“"
+msgid "Name contains invalid characters."
+msgstr "使用å¯èƒ½ãªæ–‡å­—:"
+
+#: editor/filesystem_dock.cpp
+msgid "A file or folder with this name already exists."
+msgstr ""
#: editor/filesystem_dock.cpp
#, fuzzy
-msgid "Pick New Name and Location For:"
-msgstr "æ–°ã—ã„åå‰ã¨ãƒ­ã‚±ãƒ¼ã‚·ãƒ§ãƒ³ã‚’é¸æŠž:"
+msgid "Renaming file:"
+msgstr "変数ã®åå‰ã‚’変ãˆã‚‹"
#: editor/filesystem_dock.cpp
#, fuzzy
-msgid "No files selected!"
-msgstr "ファイルãŒé¸æŠžã•ã‚Œã¦ã„ã¾ã›ã‚“!"
+msgid "Renaming folder:"
+msgstr "ノードã®åå‰ã‚’変更"
#: editor/filesystem_dock.cpp
#, fuzzy
@@ -2952,48 +2833,43 @@ msgstr "ã™ã¹ã¦æŠ˜ã‚ŠãŸãŸã‚€"
#: editor/filesystem_dock.cpp
#, fuzzy
-msgid "Show In File Manager"
-msgstr "ファイルマãƒãƒ¼ã‚¸ãƒ£ãƒ¼ã§è¡¨ç¤º"
-
-#: editor/filesystem_dock.cpp
-#, fuzzy
-msgid "Instance"
-msgstr "インスタンス"
+msgid "Copy Path"
+msgstr "パスをコピーã™ã‚‹"
#: editor/filesystem_dock.cpp
#, fuzzy
-msgid "Edit Dependencies.."
-msgstr "ä¾å­˜é–¢ä¿‚を編集.."
+msgid "Rename.."
+msgstr "åå‰ã‚’変更ã™ã‚‹"
#: editor/filesystem_dock.cpp
#, fuzzy
-msgid "View Owners.."
-msgstr "オーナーを見る.."
+msgid "Move To.."
+msgstr "~ã¸ç§»å‹•ã™ã‚‹.."
#: editor/filesystem_dock.cpp
#, fuzzy
-msgid "Copy Path"
-msgstr "パスをコピーã™ã‚‹"
+msgid "New Folder.."
+msgstr "フォルダを作æˆã™ã‚‹"
#: editor/filesystem_dock.cpp
#, fuzzy
-msgid "Rename or Move.."
-msgstr "åå‰ã‚’変ãˆã‚‹ã‹ç§»å‹•ã—ã¦ãã ã•ã„.."
+msgid "Show In File Manager"
+msgstr "ファイルマãƒãƒ¼ã‚¸ãƒ£ãƒ¼ã§è¡¨ç¤º"
#: editor/filesystem_dock.cpp
#, fuzzy
-msgid "Move To.."
-msgstr "~ã¸ç§»å‹•ã™ã‚‹.."
+msgid "Instance"
+msgstr "インスタンス"
#: editor/filesystem_dock.cpp
#, fuzzy
-msgid "Info"
-msgstr "インフォーメーション"
+msgid "Edit Dependencies.."
+msgstr "ä¾å­˜é–¢ä¿‚を編集.."
#: editor/filesystem_dock.cpp
#, fuzzy
-msgid "Re-Import.."
-msgstr "å†ã‚¤ãƒ³ãƒãƒ¼ãƒˆ.."
+msgid "View Owners.."
+msgstr "オーナーを見る.."
#: editor/filesystem_dock.cpp
msgid "Previous Directory"
@@ -3030,6 +2906,11 @@ msgstr ""
msgid "Move"
msgstr "移動"
+#: editor/filesystem_dock.cpp editor/plugins/animation_tree_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Rename"
+msgstr "åå‰ã‚’変更ã™ã‚‹"
+
#: editor/groups_editor.cpp
#, fuzzy
msgid "Add to Group"
@@ -3046,6 +2927,11 @@ msgid "Import as Single Scene"
msgstr "シーンをインãƒãƒ¼ãƒˆä¸­.."
#: editor/import/resource_importer_scene.cpp
+#, fuzzy
+msgid "Import with Separate Animations"
+msgstr "アニメーションをインãƒãƒ¼ãƒˆ.."
+
+#: editor/import/resource_importer_scene.cpp
msgid "Import with Separate Materials"
msgstr ""
@@ -3058,6 +2944,18 @@ msgid "Import with Separate Objects+Materials"
msgstr ""
#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Materials+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Materials+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
#, fuzzy
msgid "Import as Multiple Scenes"
msgstr "3Dシーンをインãƒãƒ¼ãƒˆ"
@@ -3067,45 +2965,38 @@ msgid "Import as Multiple Scenes+Materials"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
#, fuzzy
msgid "Import Scene"
msgstr "シーンをインãƒãƒ¼ãƒˆ"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
#, fuzzy
msgid "Importing Scene.."
msgstr "シーンをインãƒãƒ¼ãƒˆä¸­.."
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
#, fuzzy
msgid "Running Custom Script.."
msgstr "カスタムスクリプトを実行中"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
#, fuzzy
msgid "Couldn't load post-import script:"
msgstr "æ—¢ã«ã‚¤ãƒ³ãƒãƒ¼ãƒˆã—ãŸã‚¹ã‚¯ãƒªãƒ—トを読ã¿è¾¼ã‚ã¾ã›ã‚“ã§ã—ãŸ:"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
#, fuzzy
msgid "Invalid/broken script for post-import (check console):"
msgstr ""
"無効ãª/壊れãŸã‚¤ãƒ³ãƒãƒ¼ãƒˆæ¸ˆã¿ã®ã‚¹ã‚¯ãƒªãƒ—ト(コンソールをãƒã‚§ãƒƒã‚¯ã—ã¦ãã ã•ã„)"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
#, fuzzy
msgid "Error running post-import script:"
msgstr "インãƒãƒ¼ãƒˆæ¸ˆã¿ã®ã‚¹ã‚¯ãƒªãƒ—ト実行エラー"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
#, fuzzy
msgid "Saving.."
msgstr "ä¿å­˜ä¸­.."
@@ -3137,686 +3028,59 @@ msgstr "åˆæœŸè¨­å®šå€¤.."
msgid "Reimport"
msgstr "å†ã‚¤ãƒ³ãƒãƒ¼ãƒˆ"
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#, fuzzy
-msgid "No bit masks to import!"
-msgstr "インãƒãƒ¼ãƒˆã™ã‚‹ãƒ“ットマスクãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“!"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#, fuzzy
-msgid "Target path is empty."
-msgstr "ターゲットã®ãƒ‘スã«ä½•ã‚‚ã‚ã‚Šã¾ã›ã‚“"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#, fuzzy
-msgid "Target path must be a complete resource path."
-msgstr "ターゲットã®ãƒ‘スã¯ãƒªã‚½ãƒ¼ã‚¹ã®å®Œå…¨ãªãƒ‘スã§ãªã‘ã‚Œã°ã„ã‘ã¾ã›ã‚“."
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#, fuzzy
-msgid "Target path must exist."
-msgstr "ターゲットã®ãƒ‘スãŒå­˜åœ¨ã—ã¾ã›ã‚“"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#, fuzzy
-msgid "Save path is empty!"
-msgstr "ä¿å­˜ã™ã‚‹ãƒ‘スãŒã‚ã‚Šã¾ã›ã‚“!"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#, fuzzy
-msgid "Import BitMasks"
-msgstr "ビットマスクをインãƒãƒ¼ãƒˆ"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#, fuzzy
-msgid "Source Texture(s):"
-msgstr "ソースã®ãƒ†ã‚¯ã‚¹ãƒãƒ£:"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#, fuzzy
-msgid "Target Path:"
-msgstr "ターゲットã®ãƒ‘ス:"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#, fuzzy
-msgid "Accept"
-msgstr "å—å–OK"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Bit Mask"
-msgstr "ビットマスク"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#, fuzzy
-msgid "No source font file!"
-msgstr "ソースã®ãƒ•ã‚©ãƒ³ãƒˆãƒ•ã‚¡ã‚¤ãƒ«ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“!"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#, fuzzy
-msgid "No target font resource!"
-msgstr "ターゲットã®ãƒ•ã‚©ãƒ³ãƒˆãƒªã‚½ãƒ¼ã‚¹ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“!"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#, fuzzy
-msgid ""
-"Invalid file extension.\n"
-"Please use .font."
-msgstr ""
-"ファイル拡張å­ãŒä¸æ­£ã§ã™.\n"
-" .fontを使ã£ã¦ãã ã•ã„."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#, fuzzy
-msgid "Can't load/process source font."
-msgstr "ソースã®ãƒ•ã‚©ãƒ³ãƒˆã‚’読ã¿è¾¼ã¿/処ç†ã§ãã¾ã›ã‚“."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#, fuzzy
-msgid "Couldn't save font."
-msgstr "フォントをä¿å­˜ã§ãã¾ã›ã‚“ã§ã—ãŸ"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#, fuzzy
-msgid "Source Font:"
-msgstr "ソース フォント:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#, fuzzy
-msgid "Source Font Size:"
-msgstr "ソース フォントサイズ:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#, fuzzy
-msgid "Dest Resource:"
-msgstr "é€ã‚Šå…ˆã®ãƒªã‚½ãƒ¼ã‚¹:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#, fuzzy
-msgid "The quick brown fox jumps over the lazy dog."
-msgstr "ã„ã‚ã¯ã«ã»ã¸ã¨ï½ž."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Test:"
-msgstr "テスト:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Options:"
-msgstr "オプション:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#, fuzzy
-msgid "Font Import"
-msgstr "フォントã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆ"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#, fuzzy
-msgid ""
-"This file is already a Godot font file, please supply a BMFont type file "
-"instead."
-msgstr ""
-"ã“ã®ãƒ•ã‚¡ã‚¤ãƒ«ã¯ã‚‚ã†Godotã®ãƒ•ã‚©ãƒ³ãƒˆãƒ•ã‚¡ã‚¤ãƒ«ã§ã™. BMFont type ã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’代ã‚ã‚Š"
-"ã«åˆ©ç”¨ã—ã¦ãã ã•ã„."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#, fuzzy
-msgid "Failed opening as BMFont file."
-msgstr "BMFont ファイルを開ã‘ã¾ã›ã‚“ã§ã—ãŸ"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error initializing FreeType."
-msgstr "FreeType ã®åˆæœŸåŒ–エラー。"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Unknown font format."
-msgstr "ä¸æ˜Žãªãƒ•ã‚©ãƒ³ãƒˆå½¢å¼ã§ã™ã€‚"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error loading font."
-msgstr "フォント読ã¿è¾¼ã¿ã‚¨ãƒ©ãƒ¼ã€‚"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Invalid font size."
-msgstr "無効ãªãƒ•ã‚©ãƒ³ãƒˆ サイズã§ã™ã€‚"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#, fuzzy
-msgid "Invalid font custom source."
-msgstr "ä¸æ­£ãªãƒ•ã‚©ãƒ³ãƒˆã‚«ã‚¹ã‚¿ãƒ ã‚½ãƒ¼ã‚¹"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/plugins/theme_editor_plugin.cpp
-msgid "Font"
-msgstr "フォント"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#, fuzzy
-msgid "No meshes to import!"
-msgstr "インãƒãƒ¼ãƒˆã™ã‚‹ãƒ¡ãƒƒã‚·ãƒ¥ãŒã‚ã‚Šã¾ã›ã‚“"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#, fuzzy
-msgid "Single Mesh Import"
-msgstr "シングルメッシュをインãƒãƒ¼ãƒˆ"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#, fuzzy
-msgid "Source Mesh(es):"
-msgstr "ソース メッシュ:"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/plugins/mesh_instance_editor_plugin.cpp
-msgid "Mesh"
-msgstr "メッシュ"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#, fuzzy
-msgid "Surface %d"
-msgstr "サーフェース %d"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#, fuzzy
-msgid "No samples to import!"
-msgstr "インãƒãƒ¼ãƒˆã™ã‚‹ã‚µãƒ³ãƒ—ルãŒã‚ã‚Šã¾ã›ã‚“!"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#, fuzzy
-msgid "Import Audio Samples"
-msgstr "オーディオサンプルをインãƒãƒ¼ãƒˆ"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#, fuzzy
-msgid "Source Sample(s):"
-msgstr "ソースã®ã‚µãƒ³ãƒ—ル:"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Audio Sample"
-msgstr "オーディオサンプル"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#, fuzzy
-msgid "New Clip"
-msgstr "æ–°ã—ã„クリップ"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Animation Options"
-msgstr "アニメーションã®ã‚ªãƒ—ション"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#, fuzzy
-msgid "Flags"
-msgstr "フラグ"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#, fuzzy
-msgid "Bake FPS:"
-msgstr "FPSを焼ãè¾¼ã¿(ベイク):"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Optimizer"
-msgstr "オプティマイザ"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#, fuzzy
-msgid "Max Linear Error"
-msgstr "最大ä½ç½®ã‚¨ãƒ©ãƒ¼"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#, fuzzy
-msgid "Max Angular Error"
-msgstr "最大角度エラー"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#, fuzzy
-msgid "Max Angle"
-msgstr "最大角度"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Clips"
-msgstr "クリップ"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Start(s)"
-msgstr "開始"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "End(s)"
-msgstr "終了"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Loop"
-msgstr "ループ"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Filters"
-msgstr "フィルター"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#, fuzzy
-msgid "Source path is empty."
-msgstr "ソースã®ãƒ‘スã¯ç©ºã§ã™"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#, fuzzy
-msgid "Couldn't load post-import script."
-msgstr "インãƒãƒ¼ãƒˆæ¸ˆã¿ã®ã‚¹ã‚¯ãƒªãƒ—トを読ã¿è¾¼ã¿ã¾ã›ã‚“ã§ã—ãŸ"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#, fuzzy
-msgid "Invalid/broken script for post-import."
-msgstr "インãƒãƒ¼ãƒˆæ¸ˆã¿ã®ã‚¹ã‚¯ãƒªãƒ—トã¯ä¸æ­£ãª/壊れãŸã‚¹ã‚¯ãƒªãƒ—トã§ã™"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#, fuzzy
-msgid "Error importing scene."
-msgstr "シーン インãƒãƒ¼ãƒˆã®ã‚¨ãƒ©ãƒ¼"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#, fuzzy
-msgid "Import 3D Scene"
-msgstr "3Dシーンをインãƒãƒ¼ãƒˆ"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source Scene:"
-msgstr "ソース シーン:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#, fuzzy
-msgid "Same as Target Scene"
-msgstr "ターゲットシーンã¨åŒã˜"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Shared"
-msgstr "共有ã•ã‚Œã¦ã„ã‚‹"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#, fuzzy
-msgid "Target Texture Folder:"
-msgstr "ターゲットテクスãƒãƒ£ã®ãƒ•ã‚©ãƒ«ãƒ€:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#, fuzzy
-msgid "Post-Process Script:"
-msgstr "後処ç†ã‚¹ã‚¯ãƒªãƒ—ト:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#, fuzzy
-msgid "Custom Root Node Type:"
-msgstr "ルートノードã®ã‚«ã‚¹ã‚¿ãƒ ã‚¿ã‚¤ãƒ—:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Auto"
-msgstr "自動"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#, fuzzy
-msgid "Root Node Name:"
-msgstr "ルートノードã®åå‰:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#, fuzzy
-msgid "The Following Files are Missing:"
-msgstr "以下ã®ãƒ•ã‚¡ã‚¤ãƒ«ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#, fuzzy
-msgid "Import Anyway"
-msgstr "ã¨ã‚Šã‚ãˆãšã‚¤ãƒ³ãƒãƒ¼ãƒˆ"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp scene/gui/dialogs.cpp
-msgid "Cancel"
-msgstr "キャンセル"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#, fuzzy
-msgid "Import & Open"
-msgstr "インãƒãƒ¼ãƒˆã—ã¦é–‹ã"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#, fuzzy
-msgid "Edited scene has not been saved, open imported scene anyway?"
-msgstr ""
-"編集ã—ãŸã‚·ãƒ¼ãƒ³ã¯ä¿å­˜ã•ã‚Œã¦ã„ã¾ã›ã‚“ãŒã€ãã‚Œã§ã‚‚インãƒãƒ¼ãƒˆã—ãŸã‚·ãƒ¼ãƒ³ã‚’é–‹ãã¾ã™"
-"ã‹ï¼Ÿ"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#, fuzzy
-msgid "Import Image:"
-msgstr "イメージをインãƒãƒ¼ãƒˆ:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#, fuzzy
-msgid "Can't import a file over itself:"
-msgstr "åŒã˜ãƒ•ã‚¡ã‚¤ãƒ«ã«ã‚¤ãƒ³ãƒãƒ¼ãƒˆã§ãã¾ã›ã‚“:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#, fuzzy
-msgid "Couldn't localize path: %s (already local)"
-msgstr "パスをローカライズã§ãã¾ã›ã‚“: %s (ã™ã§ã«ãƒ­ãƒ¼ã‚«ãƒ«)"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#, fuzzy
-msgid "3D Scene Animation"
-msgstr "3Dシーンアニメーション"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Uncompressed"
-msgstr "éžåœ§ç¸®"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#, fuzzy
-msgid "Compress Lossless (PNG)"
-msgstr "ロスレス圧縮(PNG)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#, fuzzy
-msgid "Compress Lossy (WebP)"
-msgstr "éžå¯é€†åœ§ç¸®(WebP)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#, fuzzy
-msgid "Compress (VRAM)"
-msgstr "圧縮 (VRAM)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Format"
-msgstr "テクスãƒãƒ£ãƒ•ã‚©ãƒ¼ãƒžãƒƒãƒˆ"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#, fuzzy
-msgid "Texture Compression Quality (WebP):"
-msgstr "テクスãƒãƒ£åœ§ç¸®å“質 (WebP):"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#, fuzzy
-msgid "Texture Options"
-msgstr "テクスãƒãƒ£ã€€ã‚ªãƒ—ション"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#, fuzzy
-msgid "Please specify some files!"
-msgstr "ãªã«ã‹ãƒ•ã‚¡ã‚¤ãƒ«ã‚’指定ã—ã¦ãã ã•ã„!"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#, fuzzy
-msgid "At least one file needed for Atlas."
-msgstr "アトラスã«æœ€ä½Žä¸€ã¤ã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’指定ã—ã¦ãã ã•ã„"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#, fuzzy
-msgid "Error importing:"
-msgstr "エラーをインãƒãƒ¼ãƒˆä¸­:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#, fuzzy
-msgid "Only one file is required for large texture."
-msgstr "大ããªãƒ†ã‚¯ã‚¹ãƒãƒ£ã®ãŸã‚ã«ä¸€ã¤ãƒ•ã‚¡ã‚¤ãƒ«ãŒå¿…è¦ã§ã™"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#, fuzzy
-msgid "Max Texture Size:"
-msgstr "最大テクスãƒãƒ£ã‚µã‚¤ã‚º:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#, fuzzy
-msgid "Import Textures for Atlas (2D)"
-msgstr "アトラスã®ãƒ†ã‚¯ã‚¹ãƒãƒ£ã‚’インãƒãƒ¼ãƒˆ (2D)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#, fuzzy
-msgid "Cell Size:"
-msgstr "セルサイズ:"
+#: editor/multi_node_edit.cpp
+msgid "MultiNode Set"
+msgstr "複数ノード セット"
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#, fuzzy
-msgid "Large Texture"
-msgstr "大ããªãƒ†ã‚¯ã‚¹ãƒãƒ£"
+#: editor/node_dock.cpp
+msgid "Groups"
+msgstr "グループ"
-#: editor/io_plugins/editor_texture_import_plugin.cpp
+#: editor/node_dock.cpp
#, fuzzy
-msgid "Import Large Textures (2D)"
-msgstr "大ããªãƒ†ã‚¯ã‚¹ãƒãƒ£ã‚’インãƒãƒ¼ãƒˆ (2D)"
+msgid "Select a Node to edit Signals and Groups."
+msgstr "シグナルã¨ã‚°ãƒ«ãƒ¼ãƒ—を編集ã™ã‚‹ãŸã‚ノードをé¸æŠž"
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#, fuzzy
-msgid "Source Texture"
-msgstr "ソーステクスãƒãƒ£"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create Poly"
+msgstr "ãƒãƒªã‚´ãƒ³ã‚’生æˆ"
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#, fuzzy
-msgid "Base Atlas Texture"
-msgstr "基本アトラステクスãƒãƒ£"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly"
+msgstr "ãƒãƒªã‚´ãƒ³ã‚’編集"
-#: editor/io_plugins/editor_texture_import_plugin.cpp
+#: editor/plugins/abstract_polygon_2d_editor.cpp
#, fuzzy
-msgid "Source Texture(s)"
-msgstr "ソース テクスãƒãƒ£"
+msgid "Insert Point"
+msgstr "挿入"
-#: editor/io_plugins/editor_texture_import_plugin.cpp
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
#, fuzzy
-msgid "Import Textures for 2D"
-msgstr "2Dテクスãƒãƒ£ã‚’インãƒãƒ¼ãƒˆ"
+msgid "Edit Poly (Remove Point)"
+msgstr "ãƒãƒªã‚´ãƒ³ã‚’編集(ãƒã‚¤ãƒ³ãƒˆï¼ç‚¹ã‚’除去)"
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#, fuzzy
-msgid "Import Textures for 3D"
-msgstr "3Dテクスãƒãƒ£ã‚’インãƒãƒ¼ãƒˆ"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Remove Poly And Point"
+msgstr "ãƒãƒªã‚´ãƒ³ã¨ãƒã‚¤ãƒ³ãƒˆã‚’除去"
-#: editor/io_plugins/editor_texture_import_plugin.cpp
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
#, fuzzy
-msgid "Import Textures"
-msgstr "テクスãƒãƒ£ã‚’インãƒãƒ¼ãƒˆ"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "2D Texture"
-msgstr "2Dテクスãƒãƒ£"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "3D Texture"
-msgstr "3Dテクスãƒãƒ£"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Atlas Texture"
-msgstr "アトラステクスãƒãƒ£"
+msgid "Create a new polygon from scratch."
+msgstr "æ–°è¦ã«ãƒãƒªã‚´ãƒ³ã‚’生æˆã™ã‚‹"
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#, fuzzy
+#: editor/plugins/abstract_polygon_2d_editor.cpp
msgid ""
-"NOTICE: Importing 2D textures is not mandatory. Just copy png/jpg files to "
-"the project."
+"Edit existing polygon:\n"
+"LMB: Move Point.\n"
+"Ctrl+LMB: Split Segment.\n"
+"RMB: Erase Point."
msgstr ""
-"注æ„:2Dテクスãƒãƒ£ã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆã¯å¿…é ˆã§ã¯ã‚ã‚Šã¾ã›ã‚“. png/jpgファイルをプロジェ"
-"クトã«ã‚³ãƒ”ーã—ã¦ãã ã•ã„."
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#, fuzzy
-msgid "Crop empty space."
-msgstr "空白を刈り込む"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture"
-msgstr "テクスãƒãƒ£"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#, fuzzy
-msgid "Import Large Texture"
-msgstr "大ããªãƒ†ã‚¯ã‚¹ãƒãƒ£ã‚’インãƒãƒ¼ãƒˆ"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#, fuzzy
-msgid "Load Source Image"
-msgstr "ソースイメージを読ã¿è¾¼ã‚€"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Slicing"
-msgstr "スライシング"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Inserting"
-msgstr "挿入"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Saving"
-msgstr "ä¿å­˜ä¸­"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save large texture:"
-msgstr "大ããªãƒ†ã‚¯ã‚¹ãƒãƒ£ãŒä¿å­˜ã§ãã¾ã›ã‚“ã§ã—ãŸ:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#, fuzzy
-msgid "Build Atlas For:"
-msgstr "~ã®ã‚¢ãƒˆãƒ©ã‚¹ã‚’ビルド:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#, fuzzy
-msgid "Loading Image:"
-msgstr "イメージを読ã¿è¾¼ã¿ä¸­:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#, fuzzy
-msgid "Couldn't load image:"
-msgstr "イメージを読ã¿è¾¼ã‚ã¾ã›ã‚“ã§ã—ãŸ:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#, fuzzy
-msgid "Converting Images"
-msgstr "イメージを変æ›ä¸­"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#, fuzzy
-msgid "Cropping Images"
-msgstr "イメージをクロッピング(トリミング)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#, fuzzy
-msgid "Blitting Images"
-msgstr "イメージをé…ç½®(Blit)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#, fuzzy
-msgid "Couldn't save atlas image:"
-msgstr "アトラスイメージをä¿å­˜ã§ãã¾ã›ã‚“ã§ã—ãŸ:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#, fuzzy
-msgid "Couldn't save converted texture:"
-msgstr "変æ›ã—ãŸãƒ†ã‚¯ã‚¹ãƒãƒ£ã‚’ä¿å­˜ã§ãã¾ã›ã‚“ã§ã—ãŸ:"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#, fuzzy
-msgid "Invalid source!"
-msgstr "ä¸æ­£ãªã‚½ãƒ¼ã‚¹!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid translation source!"
-msgstr "ä¸æ­£ãªç¿»è¨³ã‚½ãƒ¼ã‚¹!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#, fuzzy
-msgid "Column"
-msgstr "カラム"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/script_create_dialog.cpp
-#, fuzzy
-msgid "Language"
-msgstr "言語"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#, fuzzy
-msgid "No items to import!"
-msgstr "インãƒãƒ¼ãƒˆã™ã‚‹ã‚‚ã®ãŒã‚ã‚Šã¾ã›ã‚“!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#, fuzzy
-msgid "No target path!"
-msgstr "ターゲットã®ãƒ‘スãŒã‚ã‚Šã¾ã›ã‚“!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#, fuzzy
-msgid "Import Translations"
-msgstr "翻訳をインãƒãƒ¼ãƒˆ"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#, fuzzy
-msgid "Couldn't import!"
-msgstr "インãƒãƒ¼ãƒˆã§ãã¾ã›ã‚“ã§ã—ãŸ!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#, fuzzy
-msgid "Import Translation"
-msgstr "翻訳をインãƒãƒ¼ãƒˆ"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#, fuzzy
-msgid "Source CSV:"
-msgstr "ソースCSVファイル:"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#, fuzzy
-msgid "Ignore First Row"
-msgstr "最åˆã®è¡Œã‚’無視"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Compress"
-msgstr "圧縮"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#, fuzzy
-msgid "Add to Project (project.godot)"
-msgstr "プロジェクトã«è¿½åŠ  (project.godot)"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#, fuzzy
-msgid "Import Languages:"
-msgstr "言語をインãƒãƒ¼ãƒˆ:"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Translation"
-msgstr "翻訳"
-
-#: editor/multi_node_edit.cpp
-msgid "MultiNode Set"
-msgstr "複数ノード セット"
-
-#: editor/node_dock.cpp
-msgid "Groups"
-msgstr "グループ"
-
-#: editor/node_dock.cpp
-#, fuzzy
-msgid "Select a Node to edit Signals and Groups."
-msgstr "シグナルã¨ã‚°ãƒ«ãƒ¼ãƒ—を編集ã™ã‚‹ãŸã‚ノードをé¸æŠž"
#: editor/plugins/animation_player_editor_plugin.cpp
#, fuzzy
@@ -4003,7 +3267,6 @@ msgstr "アニメーションã®åå‰:"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
#: editor/script_create_dialog.cpp
msgid "Error!"
@@ -4132,10 +3395,6 @@ msgid "Delete Input"
msgstr "入力を消去"
#: editor/plugins/animation_tree_editor_plugin.cpp
-msgid "Rename"
-msgstr "åå‰ã‚’変更ã™ã‚‹"
-
-#: editor/plugins/animation_tree_editor_plugin.cpp
#, fuzzy
msgid "Animation tree is valid."
msgstr "アニメーションツリーã¯å•é¡Œã‚ã‚Šã¾ã›ã‚“."
@@ -4199,76 +3458,221 @@ msgstr "ノードフィルターã®ç·¨é›†"
msgid "Filters.."
msgstr "フィルター.."
-#: editor/plugins/baked_light_baker.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
#, fuzzy
-msgid "Parsing %d Triangles:"
-msgstr "%d 三角形をパース中ã§ã™:"
+msgid "Free"
+msgstr "解放"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Triangle #"
-msgstr "三角形 #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Contents:"
+msgstr "コンテンツ:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "View Files"
+msgstr "ビューファイル:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve hostname:"
+msgstr "ホストåを解決ã§ãã¾ã›ã‚“:"
-#: editor/plugins/baked_light_baker.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
#, fuzzy
-msgid "Light Baker Setup:"
-msgstr "ライティング(照明)ベイク設定:"
+msgid "Can't resolve."
+msgstr "解決ã§ãã¾ã›ã‚“."
-#: editor/plugins/baked_light_baker.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
#, fuzzy
-msgid "Parsing Geometry"
-msgstr "ジオメトリーをパース"
+msgid "Connection error, please try again."
+msgstr "接続失敗 å†è©¦è¡Œã‚’"
-#: editor/plugins/baked_light_baker.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
#, fuzzy
-msgid "Fixing Lights"
-msgstr "照明(ライティング)ã®ä¿®å¾©"
+msgid "Can't connect."
+msgstr "接続失敗."
-#: editor/plugins/baked_light_baker.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
#, fuzzy
-msgid "Making BVH"
-msgstr "BVHデータを生æˆ"
+msgid "Can't connect to host:"
+msgstr "ホストã«æŽ¥ç¶šã§ãã¾ã›ã‚“:"
-#: editor/plugins/baked_light_baker.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
#, fuzzy
-msgid "Creating Light Octree"
-msgstr "照明ã®å…«åˆ†æœ¨ã‚’生æˆ"
+msgid "No response from host:"
+msgstr "ホストã‹ã‚‰å¿œç­”ãŒã‚ã‚Šã¾ã›ã‚“:"
-#: editor/plugins/baked_light_baker.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
#, fuzzy
-msgid "Creating Octree Texture"
-msgstr "八分木テクスãƒãƒ£ã‚’生æˆ"
+msgid "No response."
+msgstr "応答ãŒã‚ã‚Šã¾ã›ã‚“."
-#: editor/plugins/baked_light_baker.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
#, fuzzy
-msgid "Transfer to Lightmaps:"
-msgstr "ライトマップã¸ã®è»¢å†™:"
+msgid "Request failed, return code:"
+msgstr "リクエスト失敗 リターン コード:"
-#: editor/plugins/baked_light_baker.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
#, fuzzy
-msgid "Allocating Texture #"
-msgstr "テクスãƒãƒ£ã‚’(メモリ上ã§ï¼‰ç¢ºä¿#"
+msgid "Req. Failed."
+msgstr "リクエスト失敗."
-#: editor/plugins/baked_light_baker.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
#, fuzzy
-msgid "Baking Triangle #"
-msgstr "三角形をベイク#"
+msgid "Request failed, too many redirects"
+msgstr "リクエスト失敗 リダイレクトã®å›žæ•°ãŒå¤šã™ãŽã¾ã™"
-#: editor/plugins/baked_light_baker.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
#, fuzzy
-msgid "Post-Processing Texture #"
-msgstr "後処ç†ã®ãƒ†ã‚¯ã‚¹ãƒãƒ£#"
+msgid "Redirect Loop."
+msgstr "リダイレクトã®ãƒ«ãƒ¼ãƒ—."
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Bake!"
-msgstr "ベイク!"
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Failed:"
+msgstr "失敗:"
-#: editor/plugins/baked_light_editor_plugin.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
#, fuzzy
-msgid "Reset the lightmap octree baking process (start over)."
-msgstr "ライトマップ八分木ベイクã®ãƒ—ロセスをリセット(やり直ã—)."
+msgid "Bad download hash, assuming file has been tampered with."
+msgstr "ダウンロード内容ã®ãƒãƒƒã‚·ãƒ¥ãŒä¸æ•´åˆã€€æ”¹ã–ã‚“ã®å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Expected:"
+msgstr "予測:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Got:"
+msgstr "å–å¾—:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Failed sha256 hash check"
+msgstr "sha256ã®ãƒãƒƒã‚·ãƒ¥ãƒã‚§ãƒƒã‚¯å¤±æ•—"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Asset Download Error:"
+msgstr "アセットã®ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰å¤±æ•—:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Fetching:"
+msgstr "å–得中:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Resolving.."
+msgstr "解決中.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Connecting.."
+msgstr "接続中.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Requesting.."
+msgstr "リクエスト中.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Error making request"
+msgstr "リクエスト発行エラー"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Idle"
+msgstr "待機中"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Retry"
+msgstr "å†è©¦è¡Œ"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Download Error"
+msgstr "ダウンロード失敗"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Download for this asset is already in progress!"
+msgstr "ã“ã®ã‚¢ã‚»ãƒƒãƒˆã®ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ã¯æ—¢ã«é€²è¡Œä¸­ï¼"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "first"
+msgstr "最åˆã®"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "prev"
+msgstr "å‰ã®"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "next"
+msgstr "次ã®"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "last"
+msgstr "最後ã®"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "All"
+msgstr "ã™ã¹ã¦ã®"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Plugins"
+msgstr "プラグイン"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Sort:"
+msgstr "並ã¹æ›¿ãˆ:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Reverse"
+msgstr "逆"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Category:"
+msgstr "カテゴリー:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Site:"
+msgstr "サイト:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Support.."
+msgstr "サãƒãƒ¼ãƒˆ.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Official"
+msgstr "å…¬å¼"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Testing"
+msgstr "テスト中"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Assets ZIP File"
+msgstr "アセットã®zipファイル"
#: editor/plugins/camera_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
msgid "Preview"
msgstr "プレビュー"
@@ -4321,12 +3725,18 @@ msgstr "キャンãƒã‚¹ã‚¢ã‚¤ãƒ†ãƒ ã®ç·¨é›†"
#: editor/plugins/canvas_item_editor_plugin.cpp
#, fuzzy
-msgid "Change Anchors"
+msgid "Anchors only"
+msgstr "アンカー"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#, fuzzy
+msgid "Change Anchors and Margins"
msgstr "アンカーを変更ã™ã‚‹"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom (%):"
-msgstr "ズーム (%):"
+#, fuzzy
+msgid "Change Anchors"
+msgstr "アンカーを変更ã™ã‚‹"
#: editor/plugins/canvas_item_editor_plugin.cpp
#, fuzzy
@@ -4389,69 +3799,85 @@ msgstr "パン・モード"
#: editor/plugins/canvas_item_editor_plugin.cpp
#, fuzzy
-msgid "Lock the selected object in place (can't be moved)."
-msgstr "é¸æŠžã—ãŸã‚ªãƒ–ジェクトをロックã—ã¦ç§»å‹•ä¸èƒ½ã¨ã™ã‚‹."
+msgid "Toggles snapping"
+msgstr "ブレークãƒã‚¤ãƒ³ãƒˆã‚’切替"
#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp
#, fuzzy
-msgid "Unlock the selected object (can be moved)."
-msgstr "é¸æŠžã—ãŸã‚ªãƒ–ジェクトをロック解除ã—ã¦ç§»å‹•å¯èƒ½ã¨ã™ã‚‹."
+msgid "Use Snap"
+msgstr "スナップ機能を使ã†"
#: editor/plugins/canvas_item_editor_plugin.cpp
#, fuzzy
-msgid "Makes sure the object's children are not selectable."
-msgstr "ã“ã®ã‚ªãƒ–ジェクトã®å­ï¼ˆã‚ªãƒ–ジェクト)をé¸æŠžä¸å¯ã¨ã™ã‚‹."
+msgid "Snapping options"
+msgstr "アニメーションã®ã‚ªãƒ—ション"
#: editor/plugins/canvas_item_editor_plugin.cpp
#, fuzzy
-msgid "Restores the object's children's ability to be selected."
-msgstr "ã“ã®ã‚ªãƒ–ジェクトã®å­ï¼ˆã‚ªãƒ–ジェクト)をé¸æŠžå¯èƒ½ã¨ã™ã‚‹."
+msgid "Snap to grid"
+msgstr "Snapモード:"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Edit"
-msgstr "編集"
+#, fuzzy
+msgid "Use Rotation Snap"
+msgstr "回転スナップ機能を使ã†"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
#, fuzzy
-msgid "Use Snap"
-msgstr "スナップ機能を使ã†"
+msgid "Configure Snap..."
+msgstr "スナップ機能ã®è¨­å®š"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Show Grid"
-msgstr "グリッドを表示"
+#, fuzzy
+msgid "Snap Relative"
+msgstr "相対スナップ機能"
#: editor/plugins/canvas_item_editor_plugin.cpp
#, fuzzy
-msgid "Use Rotation Snap"
-msgstr "回転スナップ機能を使ã†"
+msgid "Use Pixel Snap"
+msgstr "ピクセルå˜ä½ã‚¹ãƒŠãƒƒãƒ—"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Smart snapping"
+msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
#, fuzzy
-msgid "Snap Relative"
-msgstr "相対スナップ機能"
+msgid "Snap to parent"
+msgstr "親ã¾ã§å±•é–‹ã™ã‚‹"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to node anchor"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to node sides"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to other nodes"
+msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
#, fuzzy
-msgid "Configure Snap.."
-msgstr "スナップ機能ã®è¨­å®š"
+msgid "Lock the selected object in place (can't be moved)."
+msgstr "é¸æŠžã—ãŸã‚ªãƒ–ジェクトをロックã—ã¦ç§»å‹•ä¸èƒ½ã¨ã™ã‚‹."
#: editor/plugins/canvas_item_editor_plugin.cpp
#, fuzzy
-msgid "Use Pixel Snap"
-msgstr "ピクセルå˜ä½ã‚¹ãƒŠãƒƒãƒ—"
+msgid "Unlock the selected object (can be moved)."
+msgstr "é¸æŠžã—ãŸã‚ªãƒ–ジェクトをロック解除ã—ã¦ç§»å‹•å¯èƒ½ã¨ã™ã‚‹."
#: editor/plugins/canvas_item_editor_plugin.cpp
#, fuzzy
-msgid "Skeleton.."
-msgstr "スケルトン.."
+msgid "Makes sure the object's children are not selectable."
+msgstr "ã“ã®ã‚ªãƒ–ジェクトã®å­ï¼ˆã‚ªãƒ–ジェクト)をé¸æŠžä¸å¯ã¨ã™ã‚‹."
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#, fuzzy
+msgid "Restores the object's children's ability to be selected."
+msgstr "ã“ã®ã‚ªãƒ–ジェクトã®å­ï¼ˆã‚ªãƒ–ジェクト)をé¸æŠžå¯èƒ½ã¨ã™ã‚‹."
#: editor/plugins/canvas_item_editor_plugin.cpp
#, fuzzy
@@ -4485,13 +3911,19 @@ msgid "View"
msgstr "ビュー"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Reset"
-msgstr "ズームをリセット"
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Show Grid"
+msgstr "グリッドを表示"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#, fuzzy
+msgid "Show helpers"
+msgstr "ボーンを表示ã™ã‚‹"
#: editor/plugins/canvas_item_editor_plugin.cpp
#, fuzzy
-msgid "Zoom Set.."
-msgstr "ズームをセットã™ã‚‹.."
+msgid "Show rulers"
+msgstr "ボーンを表示ã™ã‚‹"
#: editor/plugins/canvas_item_editor_plugin.cpp
#, fuzzy
@@ -4505,8 +3937,8 @@ msgstr "é¸æŠžå¯¾è±¡ã‚’フレームã®ä¸­å¤®ã«"
#: editor/plugins/canvas_item_editor_plugin.cpp
#, fuzzy
-msgid "Anchor"
-msgstr "アンカー"
+msgid "Layout"
+msgstr "レイアウトをä¿å­˜"
#: editor/plugins/canvas_item_editor_plugin.cpp
#, fuzzy
@@ -4532,13 +3964,21 @@ msgid "Clear Pose"
msgstr "ãƒãƒ¼ã‚ºã‚’クリアã™ã‚‹"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Set a Value"
-msgstr "値を設定ã™ã‚‹"
+msgid "Drag pivot from mouse position"
+msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
#, fuzzy
-msgid "Snap (Pixels):"
-msgstr "スナップ機能(ピクセルå˜ä½ï¼‰:"
+msgid "Set pivot at mouse position"
+msgstr "曲線ã®Out-ãƒãƒ³ãƒ‰ãƒ«ã®ä½ç½®ã‚’指定"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Multiply grid step by 2"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Divide grid step by 2"
+msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
#, fuzzy
@@ -4550,26 +3990,31 @@ msgstr "%s追加ã™ã‚‹"
msgid "Adding %s..."
msgstr "%s追加中..."
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
#, fuzzy
msgid "Create Node"
msgstr "ノードを生æˆ"
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
#, fuzzy
msgid "Error instancing scene from %s"
msgstr "%sシーンã®ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹åŒ–エラー"
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "OK :("
msgstr "ãŠãƒ¼ã‘ー :("
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
#, fuzzy
msgid "No parent to instance a child at."
msgstr "å­ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ã‚’生æˆã™ã‚‹ãŸã‚ã®è¦ªãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“"
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
#, fuzzy
msgid "This operation requires a single selected node."
msgstr "一ã¤ãƒŽãƒ¼ãƒ‰ã‚’指定ã—ãªã„ã¨ã€ã“ã®æ“作ã¯ã§ãã¾ã›ã‚“"
@@ -4587,47 +4032,6 @@ msgstr ""
"ドラッグ&ドロップ + Shift : 兄弟ノードã¨ã—ã¦åŠ ãˆã‚‹ \n"
"ドラッグ&ドロップ + Alt : ノードã®ã‚¿ã‚¤ãƒ—を変更ã™ã‚‹"
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Create Poly"
-msgstr "ãƒãƒªã‚´ãƒ³ã‚’生æˆ"
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly"
-msgstr "ãƒãƒªã‚´ãƒ³ã‚’編集"
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-#, fuzzy
-msgid "Edit Poly (Remove Point)"
-msgstr "ãƒãƒªã‚´ãƒ³ã‚’編集(ãƒã‚¤ãƒ³ãƒˆï¼ç‚¹ã‚’除去)"
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#, fuzzy
-msgid "Create a new polygon from scratch."
-msgstr "æ–°è¦ã«ãƒãƒªã‚´ãƒ³ã‚’生æˆã™ã‚‹"
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-msgid ""
-"Edit existing polygon:\n"
-"LMB: Move Point.\n"
-"Ctrl+LMB: Split Segment.\n"
-"RMB: Erase Point."
-msgstr ""
-
#: editor/plugins/collision_polygon_editor_plugin.cpp
msgid "Create Poly3D"
msgstr "3Dãƒãƒªã‚´ãƒ³ã‚’生æˆã™ã‚‹"
@@ -4638,15 +4042,6 @@ msgid "Set Handle"
msgstr "ãƒãƒ³ãƒ‰ãƒ«ã‚’設定ã™ã‚‹"
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-#, fuzzy
-msgid "Creating Mesh Library"
-msgstr "メッシュライブラリを生æˆ"
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Thumbnail.."
-msgstr "サムãƒã‚¤ãƒ«.."
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Remove item %d?"
msgstr "アイテム%dã‚’å–り除ãã¾ã™ã‹ï¼Ÿ"
@@ -4669,6 +4064,28 @@ msgid "Update from Scene"
msgstr "シーンã‹ã‚‰ã‚¢ãƒƒãƒ—デート"
#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat0"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat1"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+#, fuzzy
+msgid "Ease in"
+msgstr "イージング(Ease In)"
+
+#: editor/plugins/curve_editor_plugin.cpp
+#, fuzzy
+msgid "Ease out"
+msgstr "イージング(Ease Out)"
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Smoothstep"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
#, fuzzy
msgid "Modify Curve Point"
msgstr "カーブを修正ã™ã‚‹"
@@ -4751,23 +4168,19 @@ msgid "Create Occluder Polygon"
msgstr "オクルージョンを生ã˜ã‚‹ãƒãƒªã‚´ãƒ³ã‚’生æˆ"
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Edit existing polygon:"
msgstr "既存ã®ãƒãƒªã‚´ãƒ³ã‚’編集:"
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "LMB: Move Point."
msgstr "マウス左ボタン:ãƒã‚¤ãƒ³ãƒˆï¼ç‚¹ã‚’移動."
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
#, fuzzy
msgid "Ctrl+LMB: Split Segment."
msgstr "Ctrl+マウス左ボタン: セグメントを分割"
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "RMB: Erase Point."
msgstr "マウスå³ãƒœã‚¿ãƒ³:ãƒã‚¤ãƒ³ãƒˆï¼ç‚¹ã‚’除去."
@@ -4881,6 +4294,10 @@ msgid "Create Outline"
msgstr "アウトラインを生æˆ"
#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Mesh"
+msgstr "メッシュ"
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
#, fuzzy
msgid "Create Trimesh Static Body"
msgstr "スタティック(ä¸å¤‰ï¼‰ä¸‰è§’形メッシュ ボディを作æˆ"
@@ -5037,14 +4454,83 @@ msgstr "縮尺をランダムã«å¤‰æ›´:"
msgid "Populate"
msgstr "åˆæœŸå€¤ã‚’設定"
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake!"
+msgstr "ベイク!"
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+#, fuzzy
+msgid "Bake the navigation mesh.\n"
+msgstr "ナビメッシュ(ナビゲーションメッシュ)ã®ç”Ÿæˆ"
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+#, fuzzy
+msgid "Clear the navigation mesh."
+msgstr "ナビメッシュ(ナビゲーションメッシュ)ã®ç”Ÿæˆ"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Setting up Configuration..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Calculating grid size..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Creating heightfield..."
+msgstr "照明ã®å…«åˆ†æœ¨ã‚’生æˆ"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Marking walkable triangles..."
+msgstr "ローカル環境ã®å¤‰æ›´ã‚’ä¿å­˜ã™ã‚‹.."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Constructing compact heightfield..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Eroding walkable area..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Partitioning..."
+msgstr "警告"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Creating contours..."
+msgstr "八分木テクスãƒãƒ£ã‚’生æˆ"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Creating polymesh..."
+msgstr "アウトラインメッシュを生æˆ.."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Converting to native navigation mesh..."
+msgstr "ナビメッシュ(ナビゲーションメッシュ)ã®ç”Ÿæˆ"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Navigation Mesh Generator Setup:"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Parsing Geometry..."
+msgstr "ジオメトリーをパース"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Done!"
+msgstr ""
+
#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Create Navigation Polygon"
msgstr "ナビゲーションãƒãƒªã‚´ãƒ³ã‚’生æˆ"
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Remove Poly And Point"
-msgstr "ãƒãƒªã‚´ãƒ³ã¨ãƒã‚¤ãƒ³ãƒˆã‚’除去"
-
#: editor/plugins/particles_2d_editor_plugin.cpp
#, fuzzy
msgid "Clear Emission Mask"
@@ -5331,6 +4817,14 @@ msgid "Scale Polygon"
msgstr "ãƒãƒªã‚´ãƒ³ã®ç¸®å°ºã‚’変更"
#: editor/plugins/polygon_2d_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Edit"
+msgstr "編集"
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
#, fuzzy
msgid "Polygon->UV"
msgstr "ãƒãƒªã‚´ãƒ³->UV"
@@ -5393,67 +4887,10 @@ msgstr "リソースを読ã¿è¾¼ã‚€"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/shader_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "貼り付ã‘"
-#: editor/plugins/rich_text_editor_plugin.cpp
-#, fuzzy
-msgid "Parse BBCode"
-msgstr "BBコードをパースã™ã‚‹"
-
-#: editor/plugins/sample_editor_plugin.cpp
-#, fuzzy
-msgid "Length:"
-msgstr "é•·ã•:"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-#, fuzzy
-msgid "Open Sample File(s)"
-msgstr "サンプルファイルを開ã‘ã‚‹"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-#, fuzzy
-msgid "ERROR: Couldn't load sample!"
-msgstr "エラー:サンプルを読ã¿è¾¼ã‚ã¾ã›ã‚“!"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Add Sample"
-msgstr "サンプルを追加"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Rename Sample"
-msgstr "サンプルã®åå‰ã‚’変ãˆã‚‹"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Delete Sample"
-msgstr "サンプルを消去ã™ã‚‹"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "16 Bits"
-msgstr "16ビット"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "8 Bits"
-msgstr "8ビット"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Stereo"
-msgstr "ステレオ音声"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Mono"
-msgstr "モノラル音声"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Format"
-msgstr "フォーマット"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Pitch"
-msgstr "ピッãƒ"
-
#: editor/plugins/script_editor_plugin.cpp
#, fuzzy
msgid "Clear Recent Files"
@@ -5552,6 +4989,10 @@ msgstr "é–‰ã˜ã‚‹"
msgid "Close All"
msgstr "é–‰ã˜ã‚‹"
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+msgid "Run"
+msgstr "実行"
+
#: editor/plugins/script_editor_plugin.cpp
#, fuzzy
msgid "Toggle Scripts Panel"
@@ -5584,7 +5025,8 @@ msgstr "ステップイン"
msgid "Break"
msgstr "(デãƒãƒƒã‚°ã§ï¼‰ãƒ–レーク"
-#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+#: editor/script_editor_debugger.cpp
msgid "Continue"
msgstr "実行を継続"
@@ -5598,20 +5040,6 @@ msgid "Debug with external editor"
msgstr "次ã®ã‚¨ãƒ‡ã‚£ã‚¿ã‚’é–‹ã"
#: editor/plugins/script_editor_plugin.cpp
-msgid "Window"
-msgstr "ウィンドウ"
-
-#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
-msgid "Move Left"
-msgstr "å·¦ã«ç§»å‹•"
-
-#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
-msgid "Move Right"
-msgstr "å³ã«ç§»å‹•"
-
-#: editor/plugins/script_editor_plugin.cpp
msgid "Open Godot online documentation"
msgstr "Godotã®ã‚ªãƒ³ãƒ©ã‚¤ãƒ³æ–‡æ›¸ã‚’é–‹ã"
@@ -5700,8 +5128,9 @@ msgid "Cut"
msgstr "切りå–ã‚Š"
#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "コピー"
@@ -5989,11 +5418,6 @@ msgid "View Plane Transform."
msgstr "ビュー平é¢ãƒˆãƒ©ãƒ³ã‚¹ãƒ•ã‚©ãƒ¼ãƒ ."
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
-msgid "Scaling to %s%%."
-msgstr "拡大縮å°æ¯”率%s%%."
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rotating %s degrees."
msgstr "%s 度回転."
@@ -6010,10 +5434,6 @@ msgid "Top View."
msgstr "上é¢å›³."
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Top"
-msgstr "上é¢"
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rear View."
msgstr "後é¢å›³."
@@ -6258,6 +5678,11 @@ msgid "Transform"
msgstr "トランスフォーム"
#: editor/plugins/spatial_editor_plugin.cpp
+#, fuzzy
+msgid "Configure Snap.."
+msgstr "スナップ機能ã®è¨­å®š"
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Local Coords"
msgstr "ローカル座標系"
@@ -6414,6 +5839,10 @@ msgid "Speed (FPS):"
msgstr "速度(FPS):"
#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Loop"
+msgstr "ループ"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Animation Frames"
msgstr "アニメーションã®ãƒ•ãƒ¬ãƒ¼ãƒ "
@@ -6426,12 +5855,14 @@ msgid "Insert Empty (After)"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Up"
-msgstr "上"
+#, fuzzy
+msgid "Move (Before)"
+msgstr "ノードを除去"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Down"
-msgstr "下"
+#, fuzzy
+msgid "Move (After)"
+msgstr "å·¦ã«ç§»å‹•"
#: editor/plugins/style_box_editor_plugin.cpp
msgid "StyleBox Preview:"
@@ -6512,8 +5943,12 @@ msgid "Remove All"
msgstr "削除"
#: editor/plugins/theme_editor_plugin.cpp
-msgid "Theme"
-msgstr "テーマ"
+msgid "Edit theme.."
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Theme editing menu."
+msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
msgid "Add Class Items"
@@ -6601,6 +6036,10 @@ msgid "Style"
msgstr "スタイル"
#: editor/plugins/theme_editor_plugin.cpp
+msgid "Font"
+msgstr "フォント"
+
+#: editor/plugins/theme_editor_plugin.cpp
msgid "Color"
msgstr "色"
@@ -6653,7 +6092,7 @@ msgid "Mirror Y"
msgstr ""
#: editor/plugins/tile_map_editor_plugin.cpp
-msgid "Bucket"
+msgid "Paint Tile"
msgstr ""
#: editor/plugins/tile_map_editor_plugin.cpp
@@ -6724,6 +6163,12 @@ msgid "Delete preset '%s'?"
msgstr "åˆæœŸè¨­å®šå€¤ '%s'?を削除ã—ã¾ã™ã‹ï¼Ÿ"
#: editor/project_export.cpp
+#, fuzzy
+msgid "Export templates for this platform are missing/corrupted: "
+msgstr ""
+"ã“ã®ãƒ—ラットフォームã«å‘ã‘ã¦ã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã®ãƒ†ãƒ³ãƒ—レートãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“:"
+
+#: editor/project_export.cpp
msgid "Presets"
msgstr "åˆæœŸè¨­å®šå€¤"
@@ -6808,35 +6253,63 @@ msgstr ""
"ã“ã®ãƒ—ラットフォームã«å‘ã‘ã¦ã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã®ãƒ†ãƒ³ãƒ—レートãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“:"
#: editor/project_export.cpp
+#, fuzzy
+msgid "Export templates for this platform are missing/corrupted:"
+msgstr ""
+"ã“ã®ãƒ—ラットフォームã«å‘ã‘ã¦ã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã®ãƒ†ãƒ³ãƒ—レートãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“:"
+
+#: editor/project_export.cpp
msgid "Export With Debug"
msgstr "デãƒãƒƒã‚°ä»˜ãエクスãƒãƒ¼ãƒˆ"
#: editor/project_manager.cpp
#, fuzzy
-msgid "Invalid project path, the path must exist!"
-msgstr "パスãŒä¸æ­£ã§ã™.パスãŒå­˜åœ¨ã—ãªã„ã¨ã„ã‘ã¾ã›ã‚“."
+msgid "The path does not exist."
+msgstr "ファイルãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“."
#: editor/project_manager.cpp
-#, fuzzy
-msgid "Invalid project path, project.godot must not exist."
-msgstr "プロジェクトã®ãƒ‘スãŒä¸æ­£ã§ã™.project.godotã¯å­˜åœ¨ã—ã¾ã›ã‚“."
+msgid "Please choose a 'project.godot' file."
+msgstr ""
#: editor/project_manager.cpp
-#, fuzzy
-msgid "Invalid project path, project.godot must exist."
-msgstr "プロジェクトã®ãƒ‘スãŒä¸æ­£ã§ã™.project.godotã¯å­˜åœ¨ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚"
+msgid ""
+"Your project will be created in a non empty folder (you might want to create "
+"a new folder)."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Please choose a folder that does not contain a 'project.godot' file."
+msgstr ""
#: editor/project_manager.cpp
msgid "Imported Project"
msgstr "インãƒãƒ¼ãƒˆã•ã‚ŒãŸãƒ—ロジェクト"
#: editor/project_manager.cpp
+msgid " "
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "It would be a good idea to name your project."
+msgstr ""
+
+#: editor/project_manager.cpp
#, fuzzy
msgid "Invalid project path (changed anything?)."
msgstr "ä¸æ­£ãªãƒ—ロジェクトã®ãƒ‘ス(何ã‹å¤‰ãˆã¾ã—ãŸã‹ï¼Ÿï¼‰"
#: editor/project_manager.cpp
#, fuzzy
+msgid "Couldn't get project.godot in project path."
+msgstr "project.godotをプロジェクトパスã«ç”Ÿæˆã§ãã¾ã›ã‚“ã§ã—ãŸ"
+
+#: editor/project_manager.cpp
+#, fuzzy
+msgid "Couldn't edit project.godot in project path."
+msgstr "project.godotをプロジェクトパスã«ç”Ÿæˆã§ãã¾ã›ã‚“ã§ã—ãŸ"
+
+#: editor/project_manager.cpp
+#, fuzzy
msgid "Couldn't create project.godot in project path."
msgstr "project.godotをプロジェクトパスã«ç”Ÿæˆã§ãã¾ã›ã‚“ã§ã—ãŸ"
@@ -6846,13 +6319,30 @@ msgid "The following files failed extraction from package:"
msgstr "以下ã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’パッケージã‹ã‚‰æŠ½å‡ºã§ãã¾ã›ã‚“ã§ã—ãŸ:"
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Rename Project"
+msgstr "åç„¡ã—ã®ãƒ—ロジェクト"
+
+#: editor/project_manager.cpp
+#, fuzzy
+msgid "Couldn't get project.godot in the project path."
+msgstr "project.godotをプロジェクトパスã«ç”Ÿæˆã§ãã¾ã›ã‚“ã§ã—ãŸ"
+
+#: editor/project_manager.cpp
+msgid "New Game Project"
+msgstr "æ–°ã—ã„ゲームプロジェクト"
+
+#: editor/project_manager.cpp
msgid "Import Existing Project"
msgstr "既存ã®ãƒ—ロジェクトをインãƒãƒ¼ãƒˆ"
#: editor/project_manager.cpp
-#, fuzzy
-msgid "Project Path (Must Exist):"
-msgstr "プロジェクトパス(存在ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ï¼‰"
+msgid "Create New Project"
+msgstr "æ–°ã—ã„プロジェクトを作る"
+
+#: editor/project_manager.cpp
+msgid "Install Project:"
+msgstr "プロジェクトをインストール:"
#: editor/project_manager.cpp
#, fuzzy
@@ -6860,26 +6350,19 @@ msgid "Project Name:"
msgstr "プロジェクトå:"
#: editor/project_manager.cpp
-msgid "Create New Project"
-msgstr "æ–°ã—ã„プロジェクトを作る"
+#, fuzzy
+msgid "Create folder"
+msgstr "フォルダを作æˆã™ã‚‹"
#: editor/project_manager.cpp
msgid "Project Path:"
msgstr "プロジェクトパス:"
#: editor/project_manager.cpp
-msgid "Install Project:"
-msgstr "プロジェクトをインストール:"
-
-#: editor/project_manager.cpp
msgid "Browse"
msgstr ""
#: editor/project_manager.cpp
-msgid "New Game Project"
-msgstr "æ–°ã—ã„ゲームプロジェクト"
-
-#: editor/project_manager.cpp
msgid "That's a BINGO!"
msgstr "当ãŸã‚Š!"
@@ -6888,6 +6371,11 @@ msgid "Unnamed Project"
msgstr "åç„¡ã—ã®ãƒ—ロジェクト"
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Can't open project"
+msgstr "接続失敗."
+
+#: editor/project_manager.cpp
msgid "Are you sure to open more than one project?"
msgstr "複数ã®ãƒ—ロジェクトを本当ã«é–‹ã‘ã¾ã™ã‹ï¼Ÿ"
@@ -6921,6 +6409,12 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
+"Language changed.\n"
+"The UI will update next time the editor or project manager starts."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid ""
"You are about the scan %s folders for existing Godot projects. Do you "
"confirm?"
msgstr ""
@@ -6930,10 +6424,6 @@ msgid "Project List"
msgstr "プロジェクトã®ãƒªã‚¹ãƒˆ"
#: editor/project_manager.cpp
-msgid "Run"
-msgstr "実行"
-
-#: editor/project_manager.cpp
msgid "Scan"
msgstr "スキャン"
@@ -6956,6 +6446,11 @@ msgstr "終了"
#: editor/project_manager.cpp
#, fuzzy
+msgid "Restart Now"
+msgstr "アニメーションを最åˆã‹ã‚‰å†ç”Ÿã™ã‚‹ :"
+
+#: editor/project_manager.cpp
+#, fuzzy
msgid "Can't run project"
msgstr "接続失敗."
@@ -6996,17 +6491,14 @@ msgid "Add Input Action Event"
msgstr "入力アクションイベントを追加"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Meta+"
msgstr "Meta+"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Shift+"
msgstr "Shift+"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Alt+"
msgstr "Alt+"
@@ -7072,7 +6564,7 @@ msgstr "変更"
msgid "Joypad Axis Index:"
msgstr "ジョイパッド軸ã®Index:"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Axis"
msgstr "アナログ"
@@ -7095,32 +6587,32 @@ msgstr "入力アクションイベントを消去"
msgid "Add Event"
msgstr "イベントを追加"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Device"
msgstr "デãƒã‚¤ã‚¹"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Button"
msgstr "ボタン"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Left Button."
msgstr "左クリック"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Right Button."
msgstr "å³ã‚¯ãƒªãƒƒã‚¯"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Middle Button."
msgstr "中クリック"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
#, fuzzy
msgid "Wheel Up."
msgstr "マウスホイールを上ã¸."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Down."
msgstr "マウスホイールを下."
@@ -7130,7 +6622,7 @@ msgid "Add Global Property"
msgstr "プロパティã«getter(get method)を作る"
#: editor/project_settings_editor.cpp
-msgid "Select an setting item first!"
+msgid "Select a setting item first!"
msgstr ""
#: editor/project_settings_editor.cpp
@@ -7150,6 +6642,16 @@ msgstr "入力を消去"
#: editor/project_settings_editor.cpp
#, fuzzy
+msgid "Can't contain '/' or ':'"
+msgstr "ホストã«æŽ¥ç¶šã§ãã¾ã›ã‚“:"
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Already existing"
+msgstr "アクション'%s'ã¯æ—¢ã«ã‚ã‚Šã¾ã™!"
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
msgid "Error saving settings."
msgstr "設定をä¿å­˜ã§ãã¾ã›ã‚“ã§ã—ãŸ."
@@ -7196,6 +6698,15 @@ msgstr "リソースã®ãƒªãƒžãƒƒãƒ—オプションを除去"
#: editor/project_settings_editor.cpp
#, fuzzy
+msgid "Changed Locale Filter"
+msgstr "ブレンドã™ã‚‹æ™‚間を変更"
+
+#: editor/project_settings_editor.cpp
+msgid "Changed Locale Filter Mode"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
msgid "Project Settings (project.godot)"
msgstr "プロジェクト設定 (project.godot)"
@@ -7258,6 +6769,30 @@ msgid "Locale"
msgstr "ロケール"
#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Locales Filter"
+msgstr "ロケール"
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Show all locales"
+msgstr "ボーンを表示ã™ã‚‹"
+
+#: editor/project_settings_editor.cpp
+msgid "Show only selected locales"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Filter mode:"
+msgstr "フィルター"
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Locales:"
+msgstr "ロケール"
+
+#: editor/project_settings_editor.cpp
msgid "AutoLoad"
msgstr "自動読ã¿è¾¼ã¿"
@@ -7309,11 +6844,21 @@ msgid "New Script"
msgstr "æ–°è¦ã‚¹ã‚¯ãƒªãƒ—ト"
#: editor/property_editor.cpp
+#, fuzzy
+msgid "Make Unique"
+msgstr "ボーンを生æˆ"
+
+#: editor/property_editor.cpp
msgid "Show in File System"
msgstr ""
#: editor/property_editor.cpp
#, fuzzy
+msgid "Convert To %s"
+msgstr "~ã«å¤‰æ›ã™ã‚‹.."
+
+#: editor/property_editor.cpp
+#, fuzzy
msgid "Error loading file: Not a resource!"
msgstr "ファイル読ã¿è¾¼ã¿ã‚¨ãƒ©ãƒ¼:リソースã§ã¯ã‚ã‚Šã¾ã›ã‚“!"
@@ -7356,6 +6901,11 @@ msgstr "ã™ã¹ã¦é¸æŠž"
#: editor/property_selector.cpp
#, fuzzy
+msgid "Select Virtual Method"
+msgstr "ã™ã¹ã¦é¸æŠž"
+
+#: editor/property_selector.cpp
+#, fuzzy
msgid "Select Method"
msgstr "ã™ã¹ã¦é¸æŠž"
@@ -7383,27 +6933,6 @@ msgstr ""
msgid "Reparent"
msgstr ""
-#: editor/resources_dock.cpp
-msgid "Create New Resource"
-msgstr "æ–°ã—ã„リソースを生æˆ"
-
-#: editor/resources_dock.cpp
-msgid "Open Resource"
-msgstr "リソースを開ã‘ã‚‹"
-
-#: editor/resources_dock.cpp
-msgid "Save Resource"
-msgstr "リソースをä¿å­˜"
-
-#: editor/resources_dock.cpp
-#, fuzzy
-msgid "Resource Tools"
-msgstr "リソースã®ãƒ„ール"
-
-#: editor/resources_dock.cpp
-msgid "Make Local"
-msgstr ""
-
#: editor/run_settings_dialog.cpp
msgid "Run Mode:"
msgstr ""
@@ -7552,14 +7081,6 @@ msgid "Sub-Resources:"
msgstr "サブリソース:"
#: editor/scene_tree_dock.cpp
-msgid "Edit Groups"
-msgstr "グループを編集"
-
-#: editor/scene_tree_dock.cpp
-msgid "Edit Connections"
-msgstr "コãƒã‚¯ã‚·ãƒ§ãƒ³ã‚’編集"
-
-#: editor/scene_tree_dock.cpp
#, fuzzy
msgid "Clear Inheritance"
msgstr "継承をクリアã™ã‚‹"
@@ -7778,6 +7299,15 @@ msgid "Invalid base path"
msgstr "ä¸æ­£ãªãƒ™ãƒ¼ã‚¹ï¼ˆbase)パス"
#: editor/script_create_dialog.cpp
+msgid "Directory of the same name exists"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
+#, fuzzy
+msgid "File exists, will be reused"
+msgstr "ファイルãŒæ—¢ã«å­˜åœ¨ã—ã¾ã™ã€‚上書ãã—ã¾ã™ã‹ï¼Ÿ"
+
+#: editor/script_create_dialog.cpp
msgid "Invalid extension"
msgstr ""
@@ -7822,6 +7352,11 @@ msgid "Load existing script file"
msgstr "既存ã®ã‚¹ã‚¯ãƒªãƒ—トファイルを読ã¿è¾¼ã‚€"
#: editor/script_create_dialog.cpp
+#, fuzzy
+msgid "Language"
+msgstr "言語"
+
+#: editor/script_create_dialog.cpp
msgid "Inherits"
msgstr "継承"
@@ -7864,6 +7399,10 @@ msgid "Function:"
msgstr "関数:"
#: editor/script_editor_debugger.cpp
+msgid "Pick one or more items from the list to display the graph."
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
msgid "Errors"
msgstr "エラー"
@@ -7947,6 +7486,10 @@ msgid "Type"
msgstr "タイプ(型)"
#: editor/script_editor_debugger.cpp
+msgid "Format"
+msgstr "フォーマット"
+
+#: editor/script_editor_debugger.cpp
msgid "Usage"
msgstr "使用"
@@ -8027,13 +7570,31 @@ msgstr "パーティクルã®è»¸å¹³è¡Œå¢ƒç•Œãƒœãƒƒã‚¯ã‚¹ã‚’変更"
msgid "Change Probe Extents"
msgstr ""
+#: modules/gdnative/gd_native_library_editor.cpp
+#, fuzzy
+msgid "Library"
+msgstr "メッシュライブラリ.."
+
+#: modules/gdnative/gd_native_library_editor.cpp
+#, fuzzy
+msgid "Status"
+msgstr "ステータス:"
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Libraries: "
+msgstr ""
+
+#: modules/gdnative/register_types.cpp
+msgid "GDNative"
+msgstr ""
+
#: modules/gdscript/gd_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
#, fuzzy
msgid "Invalid type argument to convert(), use TYPE_* constants."
msgstr "Convert()ã«å¯¾ã—ã¦ç„¡åŠ¹ãªåž‹ã®å¼•æ•°ã§ã™ã€‚TYPE_* 定数を使ã£ã¦ãã ã•ã„。"
-#: modules/gdscript/gd_functions.cpp
+#: modules/gdscript/gd_functions.cpp modules/mono/glue/glue_header.h
#: modules/visual_script/visual_script_builtin_funcs.cpp
#, fuzzy
msgid "Not enough bytes for decoding bytes, or invalid format."
@@ -8090,10 +7651,6 @@ msgid "GridMap Duplicate Selection"
msgstr "é¸æŠžç¯„囲を複製"
#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "GridMap Paint"
-msgstr ""
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
#, fuzzy
msgid "Snap View"
msgstr "上é¢å›³"
@@ -8197,13 +7754,8 @@ msgstr "Snapã®è¨­å®š"
msgid "Pick Distance:"
msgstr "インスタンス:"
-#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
-msgid "Tiles"
-msgstr "ファイル:"
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "Areas"
+#: modules/mono/editor/mono_bottom_panel.cpp
+msgid "Builds"
msgstr ""
#: modules/visual_script/visual_script.cpp
@@ -8439,10 +7991,19 @@ msgstr "戻り値"
#: modules/visual_script/visual_script_editor.cpp
#, fuzzy
+msgid "Call"
+msgstr "呼ã³å‡ºã—"
+
+#: modules/visual_script/visual_script_editor.cpp
+#, fuzzy
msgid "Get"
msgstr "Getメソッド"
#: modules/visual_script/visual_script_editor.cpp
+msgid "Script already has function '%s'"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
#, fuzzy
msgid "Change Input Value"
msgstr "入力ã®åå‰ã‚’変更"
@@ -8889,6 +8450,12 @@ msgstr ""
"SpriteFrames リソースを作æˆã¾ãŸã¯ AnimatedSprite3D フレームを表示ã™ã‚‹ãŸã‚ã«"
"㯠'Frames' プロパティã«è¨­å®šã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚"
+#: scene/3d/vehicle_body.cpp
+msgid ""
+"VehicleWheel serves to provide a wheel system to a VehicleBody. Please use "
+"it as a child of a VehicleBody."
+msgstr ""
+
#: scene/gui/color_picker.cpp
#, fuzzy
msgid "Raw Mode"
@@ -8900,6 +8467,10 @@ msgid "Add current color as a preset"
msgstr "ã“ã®è‰²ã‚’åˆæœŸè¨­å®šå€¤ã¨ã—ã¦è¿½åŠ ã™ã‚‹"
#: scene/gui/dialogs.cpp
+msgid "Cancel"
+msgstr "キャンセル"
+
+#: scene/gui/dialogs.cpp
msgid "Alert!"
msgstr "警告!"
@@ -8907,10 +8478,6 @@ msgstr "警告!"
msgid "Please Confirm..."
msgstr "確èªã—ã¦ãã ã•ã„。"
-#: scene/gui/input_action.cpp
-msgid "Ctrl+"
-msgstr "Ctrl+"
-
#: scene/gui/popup.cpp
msgid ""
"Popups will hide by default unless you call popup() or any of the popup*() "
@@ -8953,6 +8520,754 @@ msgstr ""
"ãã‚Šã¾ã™ã€‚ãれ以外ã®å ´åˆã€ãƒ¬ãƒ³ãƒ€ãƒ¼ ターゲットã—ã€ãã®å†…部ã®ãƒ†ã‚¯ã‚¹ãƒãƒ£è¡¨ç¤ºã®ã„"
"ãã¤ã‹ã®ãƒŽãƒ¼ãƒ‰ã«å‰²ã‚Šå½“ã¦ã¾ã™ã€‚"
+#: scene/resources/dynamic_font.cpp
+msgid "Error initializing FreeType."
+msgstr "FreeType ã®åˆæœŸåŒ–エラー。"
+
+#: scene/resources/dynamic_font.cpp
+msgid "Unknown font format."
+msgstr "ä¸æ˜Žãªãƒ•ã‚©ãƒ³ãƒˆå½¢å¼ã§ã™ã€‚"
+
+#: scene/resources/dynamic_font.cpp
+msgid "Error loading font."
+msgstr "フォント読ã¿è¾¼ã¿ã‚¨ãƒ©ãƒ¼ã€‚"
+
+#: scene/resources/dynamic_font.cpp
+msgid "Invalid font size."
+msgstr "無効ãªãƒ•ã‚©ãƒ³ãƒˆ サイズã§ã™ã€‚"
+
+#~ msgid "Filter:"
+#~ msgstr "フィルター:"
+
+#~ msgid "Theme"
+#~ msgstr "テーマ"
+
+#, fuzzy
+#~ msgid "Method List For '%s':"
+#~ msgstr "'%s' ã®ãƒ¡ã‚½ãƒƒãƒ‰ä¸€è¦§ï¼š"
+
+#, fuzzy
+#~ msgid "Arguments:"
+#~ msgstr "引数:"
+
+#, fuzzy
+#~ msgid "Return:"
+#~ msgstr "戻り値:"
+
+#, fuzzy
+#~ msgid "Added:"
+#~ msgstr "加ãˆãŸã®ã¯:"
+
+#~ msgid "Removed:"
+#~ msgstr "å–り除ã„ãŸã®ã¯:"
+
+#, fuzzy
+#~ msgid "Error saving atlas:"
+#~ msgstr "アトラスã®ä¿å­˜ã«å¤±æ•—ã—ã¾ã—ãŸ:"
+
+#, fuzzy
+#~ msgid "Could not save atlas subtexture:"
+#~ msgstr "アトラスã®è¦ç´ ã§ã‚るテクスãƒãƒ£ã®ä¿å­˜ãŒã§ãã¾ã›ã‚“:"
+
+#, fuzzy
+#~ msgid "Exporting for %s"
+#~ msgstr "%sã«ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆä¸­"
+
+#, fuzzy
+#~ msgid "Setting Up.."
+#~ msgstr "セットアップ中.."
+
+#, fuzzy
+#~ msgid "Error loading scene."
+#~ msgstr "シーンã®èª­ã¿è¾¼ã¿ã‚¨ãƒ©ãƒ¼"
+
+#~ msgid "Re-Import"
+#~ msgstr "å†ã‚¤ãƒ³ãƒãƒ¼ãƒˆ"
+
+#, fuzzy
+#~ msgid "Please wait for scan to complete."
+#~ msgstr "走査完了をãŠå¾…ã¡ãã ã•ã„"
+
+#, fuzzy
+#~ msgid "Current scene must be saved to re-import."
+#~ msgstr "å†ã‚¤ãƒ³ãƒãƒ¼ãƒˆã™ã‚‹ãŸã‚ã«ã¯ç¾åœ¨ã®ã‚·ãƒ¼ãƒ³ã‚’ä¿å­˜ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™"
+
+#, fuzzy
+#~ msgid "Save & Re-Import"
+#~ msgstr "ä¿å­˜ã—ã¦å†ã‚¤ãƒ³ãƒãƒ¼ãƒˆ"
+
+#, fuzzy
+#~ msgid "Re-Importing"
+#~ msgstr "å†ã‚¤ãƒ³ãƒãƒ¼ãƒˆ"
+
+#, fuzzy
+#~ msgid "Re-Import Changed Resources"
+#~ msgstr "変更ã—ãŸãƒªã‚½ãƒ¼ã‚¹ã‚’å†ã‚¤ãƒ³ãƒãƒ¼ãƒˆ"
+
+#, fuzzy
+#~ msgid "Loading Export Templates"
+#~ msgstr "エクスãƒãƒ¼ãƒˆã€€ãƒ†ãƒ³ãƒ—レートã®èª­ã¿è¾¼ã¿"
+
+#, fuzzy
+#~ msgid ""
+#~ "\n"
+#~ "Status: Needs Re-Import"
+#~ msgstr "ä¿å­˜ã—ã¦å†ã‚¤ãƒ³ãƒãƒ¼ãƒˆ"
+
+#, fuzzy
+#~ msgid "Same source and destination files, doing nothing."
+#~ msgstr "åŒã˜ãƒ•ã‚¡ã‚¤ãƒ«ãŒæŒ‡å®šã•ã‚Œã¦ã„ã‚‹ã®ã§ã€ä½•ã‚‚è¡Œã„ã¾ã›ã‚“."
+
+#, fuzzy
+#~ msgid "Same source and destination paths, doing nothing."
+#~ msgstr "åŒã˜ãƒ‘スãŒæŒ‡å®šã•ã‚Œã¦ã„ã‚‹ã®ã§ã€ä½•ã‚‚è¡Œã„ã¾ã›ã‚“"
+
+#, fuzzy
+#~ msgid "Can't move directories to within themselves."
+#~ msgstr "ディレクトリを自身ã®å†…部ã«ã¯ç§»å‹•ã§ãã¾ã›ã‚“"
+
+#, fuzzy
+#~ msgid "Error moving file:\n"
+#~ msgstr "イメージ読ã¿è¾¼ã¿ã‚¨ãƒ©ãƒ¼:"
+
+#, fuzzy
+#~ msgid "Pick New Name and Location For:"
+#~ msgstr "æ–°ã—ã„åå‰ã¨ãƒ­ã‚±ãƒ¼ã‚·ãƒ§ãƒ³ã‚’é¸æŠž:"
+
+#, fuzzy
+#~ msgid "No files selected!"
+#~ msgstr "ファイルãŒé¸æŠžã•ã‚Œã¦ã„ã¾ã›ã‚“!"
+
+#, fuzzy
+#~ msgid "Info"
+#~ msgstr "インフォーメーション"
+
+#, fuzzy
+#~ msgid "Re-Import.."
+#~ msgstr "å†ã‚¤ãƒ³ãƒãƒ¼ãƒˆ.."
+
+#, fuzzy
+#~ msgid "No bit masks to import!"
+#~ msgstr "インãƒãƒ¼ãƒˆã™ã‚‹ãƒ“ットマスクãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“!"
+
+#, fuzzy
+#~ msgid "Target path is empty."
+#~ msgstr "ターゲットã®ãƒ‘スã«ä½•ã‚‚ã‚ã‚Šã¾ã›ã‚“"
+
+#, fuzzy
+#~ msgid "Target path must be a complete resource path."
+#~ msgstr "ターゲットã®ãƒ‘スã¯ãƒªã‚½ãƒ¼ã‚¹ã®å®Œå…¨ãªãƒ‘スã§ãªã‘ã‚Œã°ã„ã‘ã¾ã›ã‚“."
+
+#, fuzzy
+#~ msgid "Target path must exist."
+#~ msgstr "ターゲットã®ãƒ‘スãŒå­˜åœ¨ã—ã¾ã›ã‚“"
+
+#, fuzzy
+#~ msgid "Save path is empty!"
+#~ msgstr "ä¿å­˜ã™ã‚‹ãƒ‘スãŒã‚ã‚Šã¾ã›ã‚“!"
+
+#, fuzzy
+#~ msgid "Import BitMasks"
+#~ msgstr "ビットマスクをインãƒãƒ¼ãƒˆ"
+
+#, fuzzy
+#~ msgid "Source Texture(s):"
+#~ msgstr "ソースã®ãƒ†ã‚¯ã‚¹ãƒãƒ£:"
+
+#, fuzzy
+#~ msgid "Target Path:"
+#~ msgstr "ターゲットã®ãƒ‘ス:"
+
+#, fuzzy
+#~ msgid "Accept"
+#~ msgstr "å—å–OK"
+
+#~ msgid "Bit Mask"
+#~ msgstr "ビットマスク"
+
+#, fuzzy
+#~ msgid "No source font file!"
+#~ msgstr "ソースã®ãƒ•ã‚©ãƒ³ãƒˆãƒ•ã‚¡ã‚¤ãƒ«ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“!"
+
+#, fuzzy
+#~ msgid "No target font resource!"
+#~ msgstr "ターゲットã®ãƒ•ã‚©ãƒ³ãƒˆãƒªã‚½ãƒ¼ã‚¹ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“!"
+
+#, fuzzy
+#~ msgid ""
+#~ "Invalid file extension.\n"
+#~ "Please use .font."
+#~ msgstr ""
+#~ "ファイル拡張å­ãŒä¸æ­£ã§ã™.\n"
+#~ " .fontを使ã£ã¦ãã ã•ã„."
+
+#, fuzzy
+#~ msgid "Couldn't save font."
+#~ msgstr "フォントをä¿å­˜ã§ãã¾ã›ã‚“ã§ã—ãŸ"
+
+#, fuzzy
+#~ msgid "Source Font:"
+#~ msgstr "ソース フォント:"
+
+#, fuzzy
+#~ msgid "Source Font Size:"
+#~ msgstr "ソース フォントサイズ:"
+
+#, fuzzy
+#~ msgid "Dest Resource:"
+#~ msgstr "é€ã‚Šå…ˆã®ãƒªã‚½ãƒ¼ã‚¹:"
+
+#, fuzzy
+#~ msgid "The quick brown fox jumps over the lazy dog."
+#~ msgstr "ã„ã‚ã¯ã«ã»ã¸ã¨ï½ž."
+
+#~ msgid "Test:"
+#~ msgstr "テスト:"
+
+#~ msgid "Options:"
+#~ msgstr "オプション:"
+
+#, fuzzy
+#~ msgid "Font Import"
+#~ msgstr "フォントã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆ"
+
+#, fuzzy
+#~ msgid ""
+#~ "This file is already a Godot font file, please supply a BMFont type file "
+#~ "instead."
+#~ msgstr ""
+#~ "ã“ã®ãƒ•ã‚¡ã‚¤ãƒ«ã¯ã‚‚ã†Godotã®ãƒ•ã‚©ãƒ³ãƒˆãƒ•ã‚¡ã‚¤ãƒ«ã§ã™. BMFont type ã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’代"
+#~ "ã‚ã‚Šã«åˆ©ç”¨ã—ã¦ãã ã•ã„."
+
+#, fuzzy
+#~ msgid "Failed opening as BMFont file."
+#~ msgstr "BMFont ファイルを開ã‘ã¾ã›ã‚“ã§ã—ãŸ"
+
+#, fuzzy
+#~ msgid "Invalid font custom source."
+#~ msgstr "ä¸æ­£ãªãƒ•ã‚©ãƒ³ãƒˆã‚«ã‚¹ã‚¿ãƒ ã‚½ãƒ¼ã‚¹"
+
+#, fuzzy
+#~ msgid "No meshes to import!"
+#~ msgstr "インãƒãƒ¼ãƒˆã™ã‚‹ãƒ¡ãƒƒã‚·ãƒ¥ãŒã‚ã‚Šã¾ã›ã‚“"
+
+#, fuzzy
+#~ msgid "Single Mesh Import"
+#~ msgstr "シングルメッシュをインãƒãƒ¼ãƒˆ"
+
+#, fuzzy
+#~ msgid "Source Mesh(es):"
+#~ msgstr "ソース メッシュ:"
+
+#, fuzzy
+#~ msgid "Surface %d"
+#~ msgstr "サーフェース %d"
+
+#, fuzzy
+#~ msgid "No samples to import!"
+#~ msgstr "インãƒãƒ¼ãƒˆã™ã‚‹ã‚µãƒ³ãƒ—ルãŒã‚ã‚Šã¾ã›ã‚“!"
+
+#, fuzzy
+#~ msgid "Import Audio Samples"
+#~ msgstr "オーディオサンプルをインãƒãƒ¼ãƒˆ"
+
+#, fuzzy
+#~ msgid "Source Sample(s):"
+#~ msgstr "ソースã®ã‚µãƒ³ãƒ—ル:"
+
+#~ msgid "Audio Sample"
+#~ msgstr "オーディオサンプル"
+
+#, fuzzy
+#~ msgid "New Clip"
+#~ msgstr "æ–°ã—ã„クリップ"
+
+#, fuzzy
+#~ msgid "Flags"
+#~ msgstr "フラグ"
+
+#, fuzzy
+#~ msgid "Bake FPS:"
+#~ msgstr "FPSを焼ãè¾¼ã¿(ベイク):"
+
+#~ msgid "Optimizer"
+#~ msgstr "オプティマイザ"
+
+#, fuzzy
+#~ msgid "Max Linear Error"
+#~ msgstr "最大ä½ç½®ã‚¨ãƒ©ãƒ¼"
+
+#, fuzzy
+#~ msgid "Max Angular Error"
+#~ msgstr "最大角度エラー"
+
+#, fuzzy
+#~ msgid "Max Angle"
+#~ msgstr "最大角度"
+
+#~ msgid "Clips"
+#~ msgstr "クリップ"
+
+#~ msgid "Start(s)"
+#~ msgstr "開始"
+
+#~ msgid "End(s)"
+#~ msgstr "終了"
+
+#~ msgid "Filters"
+#~ msgstr "フィルター"
+
+#, fuzzy
+#~ msgid "Source path is empty."
+#~ msgstr "ソースã®ãƒ‘スã¯ç©ºã§ã™"
+
+#, fuzzy
+#~ msgid "Couldn't load post-import script."
+#~ msgstr "インãƒãƒ¼ãƒˆæ¸ˆã¿ã®ã‚¹ã‚¯ãƒªãƒ—トを読ã¿è¾¼ã¿ã¾ã›ã‚“ã§ã—ãŸ"
+
+#, fuzzy
+#~ msgid "Invalid/broken script for post-import."
+#~ msgstr "インãƒãƒ¼ãƒˆæ¸ˆã¿ã®ã‚¹ã‚¯ãƒªãƒ—トã¯ä¸æ­£ãª/壊れãŸã‚¹ã‚¯ãƒªãƒ—トã§ã™"
+
+#, fuzzy
+#~ msgid "Error importing scene."
+#~ msgstr "シーン インãƒãƒ¼ãƒˆã®ã‚¨ãƒ©ãƒ¼"
+
+#, fuzzy
+#~ msgid "Import 3D Scene"
+#~ msgstr "3Dシーンをインãƒãƒ¼ãƒˆ"
+
+#~ msgid "Source Scene:"
+#~ msgstr "ソース シーン:"
+
+#, fuzzy
+#~ msgid "Same as Target Scene"
+#~ msgstr "ターゲットシーンã¨åŒã˜"
+
+#~ msgid "Shared"
+#~ msgstr "共有ã•ã‚Œã¦ã„ã‚‹"
+
+#, fuzzy
+#~ msgid "Target Texture Folder:"
+#~ msgstr "ターゲットテクスãƒãƒ£ã®ãƒ•ã‚©ãƒ«ãƒ€:"
+
+#, fuzzy
+#~ msgid "Post-Process Script:"
+#~ msgstr "後処ç†ã‚¹ã‚¯ãƒªãƒ—ト:"
+
+#, fuzzy
+#~ msgid "Custom Root Node Type:"
+#~ msgstr "ルートノードã®ã‚«ã‚¹ã‚¿ãƒ ã‚¿ã‚¤ãƒ—:"
+
+#~ msgid "Auto"
+#~ msgstr "自動"
+
+#, fuzzy
+#~ msgid "Root Node Name:"
+#~ msgstr "ルートノードã®åå‰:"
+
+#, fuzzy
+#~ msgid "The Following Files are Missing:"
+#~ msgstr "以下ã®ãƒ•ã‚¡ã‚¤ãƒ«ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“:"
+
+#, fuzzy
+#~ msgid "Import Anyway"
+#~ msgstr "ã¨ã‚Šã‚ãˆãšã‚¤ãƒ³ãƒãƒ¼ãƒˆ"
+
+#, fuzzy
+#~ msgid "Import & Open"
+#~ msgstr "インãƒãƒ¼ãƒˆã—ã¦é–‹ã"
+
+#, fuzzy
+#~ msgid "Edited scene has not been saved, open imported scene anyway?"
+#~ msgstr ""
+#~ "編集ã—ãŸã‚·ãƒ¼ãƒ³ã¯ä¿å­˜ã•ã‚Œã¦ã„ã¾ã›ã‚“ãŒã€ãã‚Œã§ã‚‚インãƒãƒ¼ãƒˆã—ãŸã‚·ãƒ¼ãƒ³ã‚’é–‹ãã¾"
+#~ "ã™ã‹ï¼Ÿ"
+
+#, fuzzy
+#~ msgid "Import Image:"
+#~ msgstr "イメージをインãƒãƒ¼ãƒˆ:"
+
+#, fuzzy
+#~ msgid "Couldn't localize path: %s (already local)"
+#~ msgstr "パスをローカライズã§ãã¾ã›ã‚“: %s (ã™ã§ã«ãƒ­ãƒ¼ã‚«ãƒ«)"
+
+#, fuzzy
+#~ msgid "3D Scene Animation"
+#~ msgstr "3Dシーンアニメーション"
+
+#~ msgid "Uncompressed"
+#~ msgstr "éžåœ§ç¸®"
+
+#, fuzzy
+#~ msgid "Compress Lossless (PNG)"
+#~ msgstr "ロスレス圧縮(PNG)"
+
+#, fuzzy
+#~ msgid "Compress Lossy (WebP)"
+#~ msgstr "éžå¯é€†åœ§ç¸®(WebP)"
+
+#, fuzzy
+#~ msgid "Compress (VRAM)"
+#~ msgstr "圧縮 (VRAM)"
+
+#~ msgid "Texture Format"
+#~ msgstr "テクスãƒãƒ£ãƒ•ã‚©ãƒ¼ãƒžãƒƒãƒˆ"
+
+#, fuzzy
+#~ msgid "Texture Compression Quality (WebP):"
+#~ msgstr "テクスãƒãƒ£åœ§ç¸®å“質 (WebP):"
+
+#, fuzzy
+#~ msgid "Texture Options"
+#~ msgstr "テクスãƒãƒ£ã€€ã‚ªãƒ—ション"
+
+#, fuzzy
+#~ msgid "Please specify some files!"
+#~ msgstr "ãªã«ã‹ãƒ•ã‚¡ã‚¤ãƒ«ã‚’指定ã—ã¦ãã ã•ã„!"
+
+#, fuzzy
+#~ msgid "At least one file needed for Atlas."
+#~ msgstr "アトラスã«æœ€ä½Žä¸€ã¤ã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’指定ã—ã¦ãã ã•ã„"
+
+#, fuzzy
+#~ msgid "Error importing:"
+#~ msgstr "エラーをインãƒãƒ¼ãƒˆä¸­:"
+
+#, fuzzy
+#~ msgid "Only one file is required for large texture."
+#~ msgstr "大ããªãƒ†ã‚¯ã‚¹ãƒãƒ£ã®ãŸã‚ã«ä¸€ã¤ãƒ•ã‚¡ã‚¤ãƒ«ãŒå¿…è¦ã§ã™"
+
+#, fuzzy
+#~ msgid "Max Texture Size:"
+#~ msgstr "最大テクスãƒãƒ£ã‚µã‚¤ã‚º:"
+
+#, fuzzy
+#~ msgid "Import Textures for Atlas (2D)"
+#~ msgstr "アトラスã®ãƒ†ã‚¯ã‚¹ãƒãƒ£ã‚’インãƒãƒ¼ãƒˆ (2D)"
+
+#, fuzzy
+#~ msgid "Cell Size:"
+#~ msgstr "セルサイズ:"
+
+#, fuzzy
+#~ msgid "Large Texture"
+#~ msgstr "大ããªãƒ†ã‚¯ã‚¹ãƒãƒ£"
+
+#, fuzzy
+#~ msgid "Import Large Textures (2D)"
+#~ msgstr "大ããªãƒ†ã‚¯ã‚¹ãƒãƒ£ã‚’インãƒãƒ¼ãƒˆ (2D)"
+
+#, fuzzy
+#~ msgid "Source Texture"
+#~ msgstr "ソーステクスãƒãƒ£"
+
+#, fuzzy
+#~ msgid "Base Atlas Texture"
+#~ msgstr "基本アトラステクスãƒãƒ£"
+
+#, fuzzy
+#~ msgid "Source Texture(s)"
+#~ msgstr "ソース テクスãƒãƒ£"
+
+#, fuzzy
+#~ msgid "Import Textures for 2D"
+#~ msgstr "2Dテクスãƒãƒ£ã‚’インãƒãƒ¼ãƒˆ"
+
+#, fuzzy
+#~ msgid "Import Textures for 3D"
+#~ msgstr "3Dテクスãƒãƒ£ã‚’インãƒãƒ¼ãƒˆ"
+
+#, fuzzy
+#~ msgid "Import Textures"
+#~ msgstr "テクスãƒãƒ£ã‚’インãƒãƒ¼ãƒˆ"
+
+#~ msgid "2D Texture"
+#~ msgstr "2Dテクスãƒãƒ£"
+
+#~ msgid "3D Texture"
+#~ msgstr "3Dテクスãƒãƒ£"
+
+#~ msgid "Atlas Texture"
+#~ msgstr "アトラステクスãƒãƒ£"
+
+#, fuzzy
+#~ msgid ""
+#~ "NOTICE: Importing 2D textures is not mandatory. Just copy png/jpg files "
+#~ "to the project."
+#~ msgstr ""
+#~ "注æ„:2Dテクスãƒãƒ£ã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆã¯å¿…é ˆã§ã¯ã‚ã‚Šã¾ã›ã‚“. png/jpgファイルをプロ"
+#~ "ジェクトã«ã‚³ãƒ”ーã—ã¦ãã ã•ã„."
+
+#, fuzzy
+#~ msgid "Crop empty space."
+#~ msgstr "空白を刈り込む"
+
+#~ msgid "Texture"
+#~ msgstr "テクスãƒãƒ£"
+
+#, fuzzy
+#~ msgid "Import Large Texture"
+#~ msgstr "大ããªãƒ†ã‚¯ã‚¹ãƒãƒ£ã‚’インãƒãƒ¼ãƒˆ"
+
+#, fuzzy
+#~ msgid "Load Source Image"
+#~ msgstr "ソースイメージを読ã¿è¾¼ã‚€"
+
+#~ msgid "Slicing"
+#~ msgstr "スライシング"
+
+#~ msgid "Saving"
+#~ msgstr "ä¿å­˜ä¸­"
+
+#~ msgid "Couldn't save large texture:"
+#~ msgstr "大ããªãƒ†ã‚¯ã‚¹ãƒãƒ£ãŒä¿å­˜ã§ãã¾ã›ã‚“ã§ã—ãŸ:"
+
+#, fuzzy
+#~ msgid "Build Atlas For:"
+#~ msgstr "~ã®ã‚¢ãƒˆãƒ©ã‚¹ã‚’ビルド:"
+
+#, fuzzy
+#~ msgid "Loading Image:"
+#~ msgstr "イメージを読ã¿è¾¼ã¿ä¸­:"
+
+#, fuzzy
+#~ msgid "Couldn't load image:"
+#~ msgstr "イメージを読ã¿è¾¼ã‚ã¾ã›ã‚“ã§ã—ãŸ:"
+
+#, fuzzy
+#~ msgid "Converting Images"
+#~ msgstr "イメージを変æ›ä¸­"
+
+#, fuzzy
+#~ msgid "Cropping Images"
+#~ msgstr "イメージをクロッピング(トリミング)"
+
+#, fuzzy
+#~ msgid "Blitting Images"
+#~ msgstr "イメージをé…ç½®(Blit)"
+
+#, fuzzy
+#~ msgid "Couldn't save atlas image:"
+#~ msgstr "アトラスイメージをä¿å­˜ã§ãã¾ã›ã‚“ã§ã—ãŸ:"
+
+#, fuzzy
+#~ msgid "Couldn't save converted texture:"
+#~ msgstr "変æ›ã—ãŸãƒ†ã‚¯ã‚¹ãƒãƒ£ã‚’ä¿å­˜ã§ãã¾ã›ã‚“ã§ã—ãŸ:"
+
+#, fuzzy
+#~ msgid "Invalid source!"
+#~ msgstr "ä¸æ­£ãªã‚½ãƒ¼ã‚¹!"
+
+#~ msgid "Invalid translation source!"
+#~ msgstr "ä¸æ­£ãªç¿»è¨³ã‚½ãƒ¼ã‚¹!"
+
+#, fuzzy
+#~ msgid "Column"
+#~ msgstr "カラム"
+
+#, fuzzy
+#~ msgid "No items to import!"
+#~ msgstr "インãƒãƒ¼ãƒˆã™ã‚‹ã‚‚ã®ãŒã‚ã‚Šã¾ã›ã‚“!"
+
+#, fuzzy
+#~ msgid "No target path!"
+#~ msgstr "ターゲットã®ãƒ‘スãŒã‚ã‚Šã¾ã›ã‚“!"
+
+#, fuzzy
+#~ msgid "Import Translations"
+#~ msgstr "翻訳をインãƒãƒ¼ãƒˆ"
+
+#, fuzzy
+#~ msgid "Couldn't import!"
+#~ msgstr "インãƒãƒ¼ãƒˆã§ãã¾ã›ã‚“ã§ã—ãŸ!"
+
+#, fuzzy
+#~ msgid "Import Translation"
+#~ msgstr "翻訳をインãƒãƒ¼ãƒˆ"
+
+#, fuzzy
+#~ msgid "Source CSV:"
+#~ msgstr "ソースCSVファイル:"
+
+#, fuzzy
+#~ msgid "Ignore First Row"
+#~ msgstr "最åˆã®è¡Œã‚’無視"
+
+#~ msgid "Compress"
+#~ msgstr "圧縮"
+
+#, fuzzy
+#~ msgid "Add to Project (project.godot)"
+#~ msgstr "プロジェクトã«è¿½åŠ  (project.godot)"
+
+#, fuzzy
+#~ msgid "Import Languages:"
+#~ msgstr "言語をインãƒãƒ¼ãƒˆ:"
+
+#~ msgid "Translation"
+#~ msgstr "翻訳"
+
+#, fuzzy
+#~ msgid "Parsing %d Triangles:"
+#~ msgstr "%d 三角形をパース中ã§ã™:"
+
+#~ msgid "Triangle #"
+#~ msgstr "三角形 #"
+
+#, fuzzy
+#~ msgid "Light Baker Setup:"
+#~ msgstr "ライティング(照明)ベイク設定:"
+
+#, fuzzy
+#~ msgid "Fixing Lights"
+#~ msgstr "照明(ライティング)ã®ä¿®å¾©"
+
+#, fuzzy
+#~ msgid "Making BVH"
+#~ msgstr "BVHデータを生æˆ"
+
+#, fuzzy
+#~ msgid "Transfer to Lightmaps:"
+#~ msgstr "ライトマップã¸ã®è»¢å†™:"
+
+#, fuzzy
+#~ msgid "Allocating Texture #"
+#~ msgstr "テクスãƒãƒ£ã‚’(メモリ上ã§ï¼‰ç¢ºä¿#"
+
+#, fuzzy
+#~ msgid "Baking Triangle #"
+#~ msgstr "三角形をベイク#"
+
+#, fuzzy
+#~ msgid "Post-Processing Texture #"
+#~ msgstr "後処ç†ã®ãƒ†ã‚¯ã‚¹ãƒãƒ£#"
+
+#, fuzzy
+#~ msgid "Reset the lightmap octree baking process (start over)."
+#~ msgstr "ライトマップ八分木ベイクã®ãƒ—ロセスをリセット(やり直ã—)."
+
+#~ msgid "Zoom (%):"
+#~ msgstr "ズーム (%):"
+
+#, fuzzy
+#~ msgid "Skeleton.."
+#~ msgstr "スケルトン.."
+
+#~ msgid "Zoom Reset"
+#~ msgstr "ズームをリセット"
+
+#, fuzzy
+#~ msgid "Zoom Set.."
+#~ msgstr "ズームをセットã™ã‚‹.."
+
+#~ msgid "Set a Value"
+#~ msgstr "値を設定ã™ã‚‹"
+
+#, fuzzy
+#~ msgid "Snap (Pixels):"
+#~ msgstr "スナップ機能(ピクセルå˜ä½ï¼‰:"
+
+#, fuzzy
+#~ msgid "Parse BBCode"
+#~ msgstr "BBコードをパースã™ã‚‹"
+
+#, fuzzy
+#~ msgid "Length:"
+#~ msgstr "é•·ã•:"
+
+#, fuzzy
+#~ msgid "Open Sample File(s)"
+#~ msgstr "サンプルファイルを開ã‘ã‚‹"
+
+#, fuzzy
+#~ msgid "ERROR: Couldn't load sample!"
+#~ msgstr "エラー:サンプルを読ã¿è¾¼ã‚ã¾ã›ã‚“!"
+
+#~ msgid "Add Sample"
+#~ msgstr "サンプルを追加"
+
+#~ msgid "Rename Sample"
+#~ msgstr "サンプルã®åå‰ã‚’変ãˆã‚‹"
+
+#~ msgid "Delete Sample"
+#~ msgstr "サンプルを消去ã™ã‚‹"
+
+#~ msgid "16 Bits"
+#~ msgstr "16ビット"
+
+#~ msgid "8 Bits"
+#~ msgstr "8ビット"
+
+#~ msgid "Stereo"
+#~ msgstr "ステレオ音声"
+
+#~ msgid "Mono"
+#~ msgstr "モノラル音声"
+
+#~ msgid "Pitch"
+#~ msgstr "ピッãƒ"
+
+#~ msgid "Window"
+#~ msgstr "ウィンドウ"
+
+#, fuzzy
+#~ msgid "Move Right"
+#~ msgstr "å³ã«ç§»å‹•"
+
+#, fuzzy
+#~ msgid "Scaling to %s%%."
+#~ msgstr "拡大縮å°æ¯”率%s%%."
+
+#~ msgid "Up"
+#~ msgstr "上"
+
+#~ msgid "Down"
+#~ msgstr "下"
+
+#, fuzzy
+#~ msgid "Invalid project path, the path must exist!"
+#~ msgstr "パスãŒä¸æ­£ã§ã™.パスãŒå­˜åœ¨ã—ãªã„ã¨ã„ã‘ã¾ã›ã‚“."
+
+#, fuzzy
+#~ msgid "Invalid project path, project.godot must not exist."
+#~ msgstr "プロジェクトã®ãƒ‘スãŒä¸æ­£ã§ã™.project.godotã¯å­˜åœ¨ã—ã¾ã›ã‚“."
+
+#, fuzzy
+#~ msgid "Invalid project path, project.godot must exist."
+#~ msgstr ""
+#~ "プロジェクトã®ãƒ‘スãŒä¸æ­£ã§ã™.project.godotã¯å­˜åœ¨ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚"
+
+#, fuzzy
+#~ msgid "Project Path (Must Exist):"
+#~ msgstr "プロジェクトパス(存在ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ï¼‰"
+
+#~ msgid "Create New Resource"
+#~ msgstr "æ–°ã—ã„リソースを生æˆ"
+
+#~ msgid "Open Resource"
+#~ msgstr "リソースを開ã‘ã‚‹"
+
+#~ msgid "Save Resource"
+#~ msgstr "リソースをä¿å­˜"
+
+#, fuzzy
+#~ msgid "Resource Tools"
+#~ msgstr "リソースã®ãƒ„ール"
+
+#~ msgid "Edit Groups"
+#~ msgstr "グループを編集"
+
+#~ msgid "Edit Connections"
+#~ msgstr "コãƒã‚¯ã‚·ãƒ§ãƒ³ã‚’編集"
+
+#, fuzzy
+#~ msgid "Tiles"
+#~ msgstr "ファイル:"
+
+#~ msgid "Ctrl+"
+#~ msgstr "Ctrl+"
+
#, fuzzy
#~ msgid "Close scene? (Unsaved changes will be lost)"
#~ msgstr "シーンを閉ã˜ã¾ã™ã‹?(セーブã—ã¦ã„ãªã„変更ã¯å¤±ã‚ã‚Œã¾ã™ï¼‰"
@@ -8969,10 +9284,6 @@ msgstr ""
#~ msgid "Close Goto Prev. Scene"
#~ msgstr "é–‰ã˜ã¦éŽåŽ»é–‹ã„ãŸã‚·ãƒ¼ãƒ³ã«ç§»å‹•"
-#, fuzzy
-#~ msgid "Expand to Parent"
-#~ msgstr "親ã¾ã§å±•é–‹ã™ã‚‹"
-
#~ msgid "Del"
#~ msgstr "deleteキー"
diff --git a/editor/translations/ko.po b/editor/translations/ko.po
index f559faf1f3..02141b6dc3 100644
--- a/editor/translations/ko.po
+++ b/editor/translations/ko.po
@@ -1,14 +1,16 @@
# Korean translation of the Godot Engine editor
-# Copyright (C) 2016-2017 Juan Linietsky, Ariel Manzur and the Godot community
+# Copyright (C) 2007-2017 Juan Linietsky, Ariel Manzur
+# Copyright (C) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)
# This file is distributed under the same license as the Godot source code.
#
# 박한얼 (volzhs) <volzhs@gmail.com>, 2016-2017.
+# Ch <ccwpc@hanmail.net>, 2017.
#
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2017-02-08 16:38+0000\n"
+"PO-Revision-Date: 2017-10-24 20:47+0000\n"
"Last-Translator: 박한얼 <volzhs@gmail.com>\n"
"Language-Team: Korean <https://hosted.weblate.org/projects/godot-engine/"
"godot/ko/>\n"
@@ -17,11 +19,11 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
-"X-Generator: Weblate 2.12-dev\n"
+"X-Generator: Weblate 2.17\n"
#: editor/animation_editor.cpp
msgid "Disabled"
-msgstr "사용 안함"
+msgstr "비활성화ë¨"
#: editor/animation_editor.cpp
msgid "All Selection"
@@ -84,9 +86,8 @@ msgid "Anim Track Change Value Mode"
msgstr "트랙 값 모드 변경"
#: editor/animation_editor.cpp
-#, fuzzy
msgid "Anim Track Change Wrap Mode"
-msgstr "트랙 값 모드 변경"
+msgstr "애니메ì´ì…˜ 트랙 ëž© 모드 변경"
#: editor/animation_editor.cpp
msgid "Edit Node Curve"
@@ -194,10 +195,9 @@ msgid "Create %d NEW tracks and insert keys?"
msgstr "%dê°œì˜ ìƒˆ íŠ¸ëž™ì„ ìƒì„±í•˜ê³  키를 추가하시겠습니까?"
#: editor/animation_editor.cpp editor/create_dialog.cpp
-#: editor/editor_audio_buses.cpp
+#: editor/editor_audio_buses.cpp editor/plugins/abstract_polygon_2d_editor.cpp
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
#: editor/plugins/mesh_instance_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp editor/project_manager.cpp
#: editor/script_create_dialog.cpp
msgid "Create"
@@ -359,271 +359,6 @@ msgstr "배열 값 타입 변경"
msgid "Change Array Value"
msgstr "배열 값 변경"
-#: editor/asset_library_editor_plugin.cpp
-msgid "Free"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_plugin_settings.cpp
-msgid "Version:"
-msgstr "버전:"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Contents:"
-msgstr "ìƒìˆ˜:"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "View Files"
-msgstr "파ì¼"
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_help.cpp editor/property_selector.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Description:"
-msgstr "설명:"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-#: editor/project_manager.cpp
-msgid "Install"
-msgstr "설치"
-
-#: editor/asset_library_editor_plugin.cpp editor/call_dialog.cpp
-#: editor/connections_dialog.cpp editor/export_template_manager.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-#: editor/project_settings_editor.cpp editor/property_editor.cpp
-#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Close"
-msgstr "닫기"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve hostname:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Connection error, please try again."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Can't connect."
-msgstr "연결하기.."
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Can't connect to host:"
-msgstr "연결할 노드:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response from host:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Request failed, return code:"
-msgstr "요청한 íŒŒì¼ í˜•ì‹ì„ ì•Œ 수 ì—†ìŒ:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Req. Failed."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Request failed, too many redirects"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Redirect Loop."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Bad download hash, assuming file has been tampered with."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Expected:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Got:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Asset Download Error:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-msgid "Success!"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Fetching:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Resolving.."
-msgstr "저장 중.."
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Connecting.."
-msgstr "연결하기.."
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Requesting.."
-msgstr "테스팅"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Error making request"
-msgstr "리소스 저장 중 ì—러!"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Idle"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Retry"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Download Error"
-msgstr "아래"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Download for this asset is already in progress!"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "first"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "prev"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "next"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "last"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "All"
-msgstr "모ë‘"
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
-#: editor/settings_config_dialog.cpp
-msgid "Search:"
-msgstr "검색:"
-
-#: editor/asset_library_editor_plugin.cpp editor/code_editor.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Search"
-msgstr "검색"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/project_manager.cpp
-msgid "Import"
-msgstr "가져오기"
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Plugins"
-msgstr "플러그ì¸"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Sort:"
-msgstr "ì •ë ¬:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Reverse"
-msgstr "뒤집기"
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Category:"
-msgstr "카테고리:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Site:"
-msgstr "사ì´íŠ¸:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Support.."
-msgstr "지ì›.."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Official"
-msgstr "ê³µì‹"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-msgid "Community"
-msgstr "커뮤니티"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Testing"
-msgstr "테스팅"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Assets ZIP File"
-msgstr "ì—ì…‹ ZIP 파ì¼"
-
-#: editor/call_dialog.cpp
-msgid "Method List For '%s':"
-msgstr "'%s' 함수 목ë¡:"
-
-#: editor/call_dialog.cpp modules/visual_script/visual_script_editor.cpp
-msgid "Call"
-msgstr "호출"
-
-#: editor/call_dialog.cpp
-msgid "Method List:"
-msgstr "함수 목ë¡:"
-
-#: editor/call_dialog.cpp
-msgid "Arguments:"
-msgstr "ì¸ìˆ˜:"
-
-#: editor/call_dialog.cpp
-msgid "Return:"
-msgstr "리턴:"
-
#: editor/code_editor.cpp
msgid "Go to Line"
msgstr "ë¼ì¸ìœ¼ë¡œ ì´ë™"
@@ -637,9 +372,8 @@ msgid "No Matches"
msgstr "ì¼ì¹˜ ê²°ê³¼ ì—†ìŒ"
#: editor/code_editor.cpp
-#, fuzzy
msgid "Replaced %d occurrence(s)."
-msgstr "%d 회 변경ë¨."
+msgstr "%d 회 êµì²´ë¨."
#: editor/code_editor.cpp
msgid "Replace"
@@ -661,6 +395,14 @@ msgstr "전체 단어"
msgid "Selection Only"
msgstr "ì„ íƒì˜ì—­ë§Œ"
+#: editor/code_editor.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
+msgid "Search"
+msgstr "검색"
+
#: editor/code_editor.cpp editor/editor_help.cpp
msgid "Find"
msgstr "찾기"
@@ -693,11 +435,11 @@ msgstr "변경 시 알림"
msgid "Skip"
msgstr "건너뛰기"
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom In"
msgstr "확대"
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom Out"
msgstr "축소"
@@ -766,6 +508,20 @@ msgstr "지연"
msgid "Oneshot"
msgstr "1회"
+#: editor/connections_dialog.cpp editor/dependency_editor.cpp
+#: editor/export_template_manager.cpp
+#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Close"
+msgstr "닫기"
+
#: editor/connections_dialog.cpp
msgid "Connect"
msgstr "ì—°ê²°"
@@ -791,7 +547,7 @@ msgstr "연결하기.."
msgid "Disconnect"
msgstr "연결해제"
-#: editor/connections_dialog.cpp editor/node_dock.cpp
+#: editor/connections_dialog.cpp editor/editor_help.cpp editor/node_dock.cpp
msgid "Signals"
msgstr "시그ë„"
@@ -808,12 +564,25 @@ msgstr "ì¦ê²¨ì°¾ê¸°:"
msgid "Recent:"
msgstr "최근:"
+#: editor/create_dialog.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/quick_open.cpp editor/settings_config_dialog.cpp
+msgid "Search:"
+msgstr "검색:"
+
#: editor/create_dialog.cpp editor/editor_help.cpp
#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/quick_open.cpp
msgid "Matches:"
msgstr "ì¼ì¹˜:"
+#: editor/create_dialog.cpp editor/editor_help.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/property_selector.cpp
+#: editor/script_editor_debugger.cpp
+msgid "Description:"
+msgstr "설명:"
+
#: editor/dependency_editor.cpp
msgid "Search Replacement For:"
msgstr "대체할 ëŒ€ìƒ ì°¾ê¸°:"
@@ -873,6 +642,10 @@ msgid "Owners Of:"
msgstr "소유ìž:"
#: editor/dependency_editor.cpp
+msgid "Remove selected files from the project? (no undo)"
+msgstr "프로ì íŠ¸ì—ì„œ ì„ íƒëœ 파ì¼ë“¤ì„ 삭제하시겠습니까? (ë˜ëŒë¦¬ê¸° 불가)"
+
+#: editor/dependency_editor.cpp
msgid ""
"The files being removed are required by other resources in order for them to "
"work.\n"
@@ -882,8 +655,8 @@ msgstr ""
"ì •ë§ë¡œ 삭제하시겠습니까? (ë˜ëŒë¦¬ê¸° 불가)"
#: editor/dependency_editor.cpp
-msgid "Remove selected files from the project? (no undo)"
-msgstr "프로ì íŠ¸ì—ì„œ ì„ íƒëœ 파ì¼ë“¤ì„ 삭제하시겠습니까? (ë˜ëŒë¦¬ê¸° 불가)"
+msgid "Cannot remove:\n"
+msgstr "제거할 수 없습니다:\n"
#: editor/dependency_editor.cpp
msgid "Error loading:"
@@ -946,21 +719,15 @@ msgstr "ê°ì‚¬í•©ë‹ˆë‹¤!"
#: editor/editor_about.cpp
msgid "Godot Engine contributors"
-msgstr ""
+msgstr "Godot Engine 기여ìž"
#: editor/editor_about.cpp
-#, fuzzy
-msgid "Authors"
-msgstr "ì €ìž:"
-
-#: editor/editor_about.cpp
-#, fuzzy
msgid "Project Founders"
-msgstr "프로ì íŠ¸ 매니저"
+msgstr "프로ì íŠ¸ 창립ìž"
#: editor/editor_about.cpp
msgid "Lead Developer"
-msgstr ""
+msgstr "리드 개발ìž"
#: editor/editor_about.cpp editor/project_manager.cpp
msgid "Project Manager"
@@ -968,15 +735,47 @@ msgstr "프로ì íŠ¸ 매니저"
#: editor/editor_about.cpp
msgid "Developers"
-msgstr ""
+msgstr "개발ìžë“¤"
+
+#: editor/editor_about.cpp
+msgid "Authors"
+msgstr "ì €ìž"
+
+#: editor/editor_about.cpp
+msgid "Platinum Sponsors"
+msgstr "플래티넘 스í°ì„œ"
+
+#: editor/editor_about.cpp
+msgid "Gold Sponsors"
+msgstr "골드 스í°ì„œ"
+
+#: editor/editor_about.cpp
+msgid "Mini Sponsors"
+msgstr "미니 스í°ì„œ"
+
+#: editor/editor_about.cpp
+msgid "Gold Donors"
+msgstr "골드 기ì¦ìž"
+
+#: editor/editor_about.cpp
+msgid "Silver Donors"
+msgstr "브론즈 기ì¦ìž"
+
+#: editor/editor_about.cpp
+msgid "Bronze Donors"
+msgstr "브론즈 기ì¦ìž"
+
+#: editor/editor_about.cpp
+msgid "Donors"
+msgstr "기ì¦ìž"
#: editor/editor_about.cpp
msgid "License"
-msgstr ""
+msgstr "ë¼ì´ì„ ìŠ¤"
#: editor/editor_about.cpp
msgid "Thirdparty License"
-msgstr ""
+msgstr "서드파티 ë¼ì´ì„ ìŠ¤"
#: editor/editor_about.cpp
msgid ""
@@ -985,103 +784,109 @@ msgid ""
"is an exhaustive list of all such thirdparty components with their "
"respective copyright statements and license terms."
msgstr ""
+"Godot Engineì€ MIT ë¼ì´ì„ ìŠ¤ì™€ 호환ë˜ëŠ” ìˆ˜ë§Žì€ ì„œë“œíŒŒí‹° ìžìœ  오픈소스 ë¼ì´ë¸ŒëŸ¬"
+"ë¦¬ì— ì˜ì¡´í•©ë‹ˆë‹¤. 다ìŒì€ 그러한 서드파티 ì»´í¬ë„ŒíŠ¸ì˜ 완전한 목ë¡ê³¼ ì´ì— 대ì‘하"
+"는 저작권 선언문 ë° ë¼ì´ì„¼ìŠ¤ìž…니다."
#: editor/editor_about.cpp
-#, fuzzy
msgid "All Components"
-msgstr "ìƒìˆ˜:"
+msgstr "모든 ì»´í¬ë„ŒíŠ¸"
#: editor/editor_about.cpp
-#, fuzzy
msgid "Components"
-msgstr "ìƒìˆ˜:"
+msgstr "ì»´í¬ë„ŒíŠ¸"
#: editor/editor_about.cpp
msgid "Licenses"
-msgstr ""
+msgstr "ë¼ì´ì„ ìŠ¤"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Error opening package file, not in zip format."
-msgstr ""
+msgstr "패키지 파ì¼ì„ 여는 ë° ì˜¤ë¥˜ê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤. zip í¬ë§·ì´ 아닙니다."
#: editor/editor_asset_installer.cpp
-#, fuzzy
msgid "Uncompressing Assets"
-msgstr "무압축"
+msgstr "어셋 압축해제"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package Installed Successfully!"
msgstr "패키지가 성공ì ìœ¼ë¡œ 설치ë˜ì—ˆìŠµë‹ˆë‹¤!"
#: editor/editor_asset_installer.cpp
-#, fuzzy
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Success!"
+msgstr "성공!"
+
+#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/project_manager.cpp
+msgid "Install"
+msgstr "설치"
+
+#: editor/editor_asset_installer.cpp
msgid "Package Installer"
-msgstr "패키지가 성공ì ìœ¼ë¡œ 설치ë˜ì—ˆìŠµë‹ˆë‹¤!"
+msgstr "패키지 ì¸ìŠ¤í†¨ëŸ¬"
#: editor/editor_audio_buses.cpp
msgid "Speakers"
-msgstr ""
+msgstr "스피커"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Add Effect"
-msgstr "빈 프레임 추가"
+msgstr "ì´íŽ™íŠ¸ 추가"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Rename Audio Bus"
-msgstr "ìžë™ 로드 ì´ë¦„ 변경"
+msgstr "오디오 버스 ì´ë¦„ 변경"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Toggle Audio Bus Solo"
-msgstr "ìžë™ ìž¬ìƒ ì „í™˜"
+msgstr "오디오 버스 솔로 토글"
#: editor/editor_audio_buses.cpp
msgid "Toggle Audio Bus Mute"
-msgstr ""
+msgstr "오디오 버스 뮤트 토글"
#: editor/editor_audio_buses.cpp
+#, fuzzy
msgid "Toggle Audio Bus Bypass Effects"
-msgstr ""
+msgstr "오디오 버스 ì´íŽ™íŠ¸ 무시 토글"
#: editor/editor_audio_buses.cpp
msgid "Select Audio Bus Send"
-msgstr ""
+msgstr "오디오 버스 전송 ì„ íƒ"
#: editor/editor_audio_buses.cpp
msgid "Add Audio Bus Effect"
-msgstr ""
+msgstr "오디오 버스 ì´íŽ™íŠ¸ 추가"
#: editor/editor_audio_buses.cpp
msgid "Move Bus Effect"
-msgstr ""
+msgstr "버스 ì´íŽ™íŠ¸ ì´ë™"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Delete Bus Effect"
-msgstr "ì„ íƒ í•­ëª© ì‚­ì œ"
+msgstr "버스 ì´íŽ™íŠ¸ ì‚­ì œ"
#: editor/editor_audio_buses.cpp
msgid "Audio Bus, Drag and Drop to rearrange."
-msgstr ""
-
-#: editor/editor_audio_buses.cpp
-#, fuzzy
-msgid "Bus options"
-msgstr "디버그 옵션"
+msgstr "오디오 버스, 드래그 ë° ë“œë¡­ìœ¼ë¡œ 재배치하세요."
#: editor/editor_audio_buses.cpp
msgid "Solo"
-msgstr ""
+msgstr "솔로"
#: editor/editor_audio_buses.cpp
msgid "Mute"
-msgstr ""
+msgstr "뮤트"
#: editor/editor_audio_buses.cpp
+#, fuzzy
msgid "Bypass"
-msgstr ""
+msgstr "ë°”ì´íŒ¨ìŠ¤"
+
+#: editor/editor_audio_buses.cpp
+msgid "Bus options"
+msgstr "버스 옵션"
#: editor/editor_audio_buses.cpp editor/plugins/tile_map_editor_plugin.cpp
#: editor/scene_tree_dock.cpp
@@ -1089,75 +894,73 @@ msgid "Duplicate"
msgstr "복제"
#: editor/editor_audio_buses.cpp
-#, fuzzy
+msgid "Reset Volume"
+msgstr "볼륨 리셋"
+
+#: editor/editor_audio_buses.cpp
msgid "Delete Effect"
-msgstr "ì„ íƒ í•­ëª© ì‚­ì œ"
+msgstr "ì´íŽ™íŠ¸ ì‚­ì œ"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Add Audio Bus"
-msgstr "%s 추가"
+msgstr "오디오 버스 추가"
#: editor/editor_audio_buses.cpp
msgid "Master bus can't be deleted!"
-msgstr ""
+msgstr "주 버스는 삭제할 수 없습니다!"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Delete Audio Bus"
-msgstr "ë ˆì´ì•„웃 ì‚­ì œ"
+msgstr "오디오 버스 삭제"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Duplicate Audio Bus"
-msgstr "애니메ì´ì…˜ 복제하기"
+msgstr "오디오 버스 복제"
+
+#: editor/editor_audio_buses.cpp
+msgid "Reset Bus Volume"
+msgstr "버스 볼륨 리셋"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Move Audio Bus"
-msgstr "ì´ë™ ì•¡ì…˜"
+msgstr "오디오 버스 ì´ë™"
#: editor/editor_audio_buses.cpp
msgid "Save Audio Bus Layout As.."
-msgstr ""
+msgstr "오디오 버스 ë ˆì´ì•„ì›ƒì„ ë‹¤ë¥¸ ì´ë¦„으로 저장.."
#: editor/editor_audio_buses.cpp
msgid "Location for New Layout.."
-msgstr ""
+msgstr "새 ë ˆì´ì•„ì›ƒì„ ì €ìž¥í•  장소.."
#: editor/editor_audio_buses.cpp
msgid "Open Audio Bus Layout"
-msgstr ""
+msgstr "오디오 버스 ë ˆì´ì•„웃 열기"
#: editor/editor_audio_buses.cpp
msgid "There is no 'res://default_bus_layout.tres' file."
-msgstr ""
+msgstr "'res://default_bus_layout.tres' 파ì¼ì´ 없습니다."
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Invalid file, not an audio bus layout."
-msgstr ""
-"유효하지 ì•Šì€ íŒŒì¼ í™•ìž¥ìž.\n"
-".fnt 를 사용하세요."
+msgstr "올바르지 ì•Šì€ íŒŒì¼ìž…니다. 오디오 버스 ë ˆì´ì•„ì›ƒì´ ì•„ë‹™ë‹ˆë‹¤."
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Add Bus"
-msgstr "%s 추가"
+msgstr "버스 추가"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Create a new Bus Layout."
-msgstr "새 리소스 만들기"
+msgstr "새로운 버스 ë ˆì´ì•„ì›ƒì„ ë§Œë“­ë‹ˆë‹¤."
-#: editor/editor_audio_buses.cpp editor/script_create_dialog.cpp
+#: editor/editor_audio_buses.cpp editor/property_editor.cpp
+#: editor/script_create_dialog.cpp
msgid "Load"
msgstr "로드"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Load an existing Bus Layout."
-msgstr "디스í¬ì—ì„œ 기존 리소스를 로드하여 편집합니다."
+msgstr "기존 버스 ë ˆì´ì•„ì›ƒì„ ë¶ˆëŸ¬ì˜µë‹ˆë‹¤."
#: editor/editor_audio_buses.cpp
#: editor/plugins/animation_player_editor_plugin.cpp
@@ -1166,16 +969,15 @@ msgstr "다른 ì´ë¦„으로 저장"
#: editor/editor_audio_buses.cpp
msgid "Save this Bus Layout to a file."
-msgstr ""
+msgstr "ì´ ë²„ìŠ¤ ë ˆì´ì•„ì›ƒì„ íŒŒì¼ë¡œ 저장합니다.."
#: editor/editor_audio_buses.cpp editor/import_dock.cpp
-#, fuzzy
msgid "Load Default"
-msgstr "Default"
+msgstr "기본값 불러오기"
#: editor/editor_audio_buses.cpp
msgid "Load the default Bus Layout."
-msgstr ""
+msgstr "기본 버스 ë ˆì´ì•„ì›ƒì„ ë¶ˆëŸ¬ì˜µë‹ˆë‹¤."
#: editor/editor_autoload_settings.cpp
msgid "Invalid name."
@@ -1213,7 +1015,7 @@ msgstr "리소스 경로가 아닙니다."
#: editor/editor_autoload_settings.cpp
msgid "Add AutoLoad"
-msgstr "ìžë™ 로드 추가"
+msgstr "오토 로드 추가"
#: editor/editor_autoload_settings.cpp
msgid "Autoload '%s' already exists!"
@@ -1244,7 +1046,7 @@ msgid "Rearrange Autoloads"
msgstr "ìžë™ 로드 위치 변경"
#: editor/editor_autoload_settings.cpp editor/editor_file_dialog.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp scene/gui/file_dialog.cpp
+#: scene/gui/file_dialog.cpp
msgid "Path:"
msgstr "경로:"
@@ -1252,9 +1054,7 @@ msgstr "경로:"
msgid "Node Name:"
msgstr "노드 ì´ë¦„:"
-#: editor/editor_autoload_settings.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp editor/project_manager.cpp
+#: editor/editor_autoload_settings.cpp editor/project_manager.cpp
msgid "Name"
msgstr "ì´ë¦„"
@@ -1279,27 +1079,27 @@ msgid "Updating scene.."
msgstr "씬 ì—…ë°ì´íŠ¸ 중.."
#: editor/editor_dir_dialog.cpp
-#, fuzzy
msgid "Please select a base directory first"
-msgstr "먼저 ì”¬ì„ ì €ìž¥í•´ì£¼ì„¸ìš”."
+msgstr "먼저 기본 디렉토리를 ì„ íƒí•´ì£¼ì„¸ìš”"
#: editor/editor_dir_dialog.cpp
msgid "Choose a Directory"
msgstr "디렉토리 ì„ íƒ"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Create Folder"
msgstr "í´ë” ìƒì„±"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: editor/editor_plugin_settings.cpp editor/plugins/theme_editor_plugin.cpp
-#: editor/project_export.cpp scene/gui/file_dialog.cpp
+#: editor/editor_plugin_settings.cpp editor/filesystem_dock.cpp
+#: editor/plugins/theme_editor_plugin.cpp editor/project_export.cpp
+#: scene/gui/file_dialog.cpp
msgid "Name:"
msgstr "ì´ë¦„:"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Could not create folder."
msgstr "í´ë”를 만들 수 없습니다."
@@ -1317,31 +1117,7 @@ msgstr "패킹중"
#: editor/editor_export.cpp platform/javascript/export/export.cpp
msgid "Template file not found:\n"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Added:"
-msgstr "추가ë¨:"
-
-#: editor/editor_export.cpp
-msgid "Removed:"
-msgstr "제거ë¨:"
-
-#: editor/editor_export.cpp
-msgid "Error saving atlas:"
-msgstr "ì•„í‹€ë¼ìŠ¤ 저장 중 ì—러:"
-
-#: editor/editor_export.cpp
-msgid "Could not save atlas subtexture:"
-msgstr "ì•„í‹€ë¼ìŠ¤ 서브 í…스ì³ë¥¼ 저장할 수 없습니다:"
-
-#: editor/editor_export.cpp
-msgid "Exporting for %s"
-msgstr "%s 내보내기"
-
-#: editor/editor_export.cpp
-msgid "Setting Up.."
-msgstr "설정 중.."
+msgstr "í…œí”Œë¦¿ì„ ì°¾ì„ ìˆ˜ 없습니다:\n"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "File Exists, Overwrite?"
@@ -1427,6 +1203,10 @@ msgstr "ì¦ê²¨ì°¾ê¸° 위로 ì´ë™"
msgid "Move Favorite Down"
msgstr "ì¦ê²¨ì°¾ê¸° 아래로 ì´ë™"
+#: editor/editor_file_dialog.cpp
+msgid "Go to parent folder"
+msgstr "부모 í´ë”ë¡œ ì´ë™"
+
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Directories & Files:"
msgstr "디렉토리와 파ì¼:"
@@ -1441,10 +1221,6 @@ msgid "File:"
msgstr "파ì¼:"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
-msgid "Filter:"
-msgstr "í•„í„°:"
-
-#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Must use a valid extension."
msgstr "유효한 확장ìžë¥¼ 사용해야 합니다."
@@ -1453,9 +1229,8 @@ msgid "ScanSources"
msgstr "소스 조사"
#: editor/editor_file_system.cpp
-#, fuzzy
msgid "(Re)Importing Assets"
-msgstr "다시 가져오기"
+msgstr "어셋 (다시) 가져오기"
#: editor/editor_help.cpp editor/editor_node.cpp
#: editor/plugins/script_editor_plugin.cpp
@@ -1470,6 +1245,10 @@ msgstr "í´ëž˜ìŠ¤ 목ë¡:"
msgid "Search Classes"
msgstr "í´ëž˜ìŠ¤ 검색"
+#: editor/editor_help.cpp editor/plugins/spatial_editor_plugin.cpp
+msgid "Top"
+msgstr "윗면"
+
#: editor/editor_help.cpp editor/property_editor.cpp
msgid "Class:"
msgstr "í´ëž˜ìŠ¤:"
@@ -1486,15 +1265,27 @@ msgstr "ìƒì†í•œ í´ëž˜ìŠ¤:"
msgid "Brief Description:"
msgstr "간단한 설명:"
+#: editor/editor_help.cpp
+msgid "Members"
+msgstr "멤버"
+
#: editor/editor_help.cpp modules/visual_script/visual_script_editor.cpp
msgid "Members:"
msgstr "멤버:"
#: editor/editor_help.cpp
+msgid "Public Methods"
+msgstr "공개 메소드"
+
+#: editor/editor_help.cpp
msgid "Public Methods:"
msgstr "공개 함수:"
#: editor/editor_help.cpp
+msgid "GUI Theme Items"
+msgstr "GUI 테마 항목"
+
+#: editor/editor_help.cpp
msgid "GUI Theme Items:"
msgstr "GUI 테마 항목:"
@@ -1503,54 +1294,86 @@ msgid "Signals:"
msgstr "시그ë„:"
#: editor/editor_help.cpp
-#, fuzzy
+msgid "Enumerations"
+msgstr "Enumerations"
+
+#: editor/editor_help.cpp
msgid "Enumerations:"
-msgstr "애니메ì´ì…˜"
+msgstr "Enumerations:"
#: editor/editor_help.cpp
msgid "enum "
-msgstr ""
+msgstr "enum "
+
+#: editor/editor_help.cpp
+msgid "Constants"
+msgstr "ìƒìˆ˜"
#: editor/editor_help.cpp
msgid "Constants:"
msgstr "ìƒìˆ˜:"
#: editor/editor_help.cpp
+msgid "Description"
+msgstr "설명"
+
+#: editor/editor_help.cpp
+msgid "Properties"
+msgstr "ì†ì„±"
+
+#: editor/editor_help.cpp
msgid "Property Description:"
msgstr "ì†ì„± 설명:"
#: editor/editor_help.cpp
+#, fuzzy
+msgid ""
+"There is currently no description for this property. Please help us by "
+"[color=$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+"현재 ì´ ì†ì„±ì— 대한 ìƒì„¸ì„¤ëª…ì´ ì—†ìŠµë‹ˆë‹¤. [color=$color][url=$url]관련 정보를 "
+"기여하여[/url][/color] ë” ë‚˜ì•„ì§€ê²Œ ë„와주세요!"
+
+#: editor/editor_help.cpp
+msgid "Methods"
+msgstr "메서드"
+
+#: editor/editor_help.cpp
msgid "Method Description:"
msgstr "함수 설명:"
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this method. Please help us by [color="
+"$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+"현재 ì´ ë©”ì„œë“œì— ëŒ€í•œ ìƒì„¸ì„¤ëª…ì´ ì—†ìŠµë‹ˆë‹¤. [color=$color][url=$url]관련 ì •ë³´"
+"를 기여하여[/url][/color] ë” ë‚˜ì•„ì§€ê²Œ ë„와주세요!"
+
+#: editor/editor_help.cpp
msgid "Search Text"
msgstr "ë¬¸ìž ê²€ìƒ‰"
#: editor/editor_log.cpp
-#, fuzzy
msgid "Output:"
-msgstr " 출력:"
+msgstr "출력:"
#: editor/editor_log.cpp editor/plugins/animation_tree_editor_plugin.cpp
-#: editor/plugins/rich_text_editor_plugin.cpp editor/property_editor.cpp
-#: editor/script_editor_debugger.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/property_editor.cpp editor/script_editor_debugger.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Clear"
msgstr "지우기"
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Error saving resource!"
msgstr "리소스 저장 중 ì—러!"
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Save Resource As.."
msgstr "리소스를 다른 ì´ë¦„으로 저장.."
-#: editor/editor_node.cpp editor/export_template_manager.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "I see.."
msgstr "알겠습니다.."
@@ -1567,6 +1390,26 @@ msgid "Error while saving."
msgstr "저장 중 ì—러."
#: editor/editor_node.cpp
+msgid "Can't open '%s'."
+msgstr "'%s' 열수 ì—†ìŒ."
+
+#: editor/editor_node.cpp
+msgid "Error while parsing '%s'."
+msgstr "'%s' 파싱 중 ì—러."
+
+#: editor/editor_node.cpp
+msgid "Unexpected end of file '%s'."
+msgstr "예ìƒì¹˜ 못한 파ì¼ì˜ ë '%s' 입니다.."
+
+#: editor/editor_node.cpp
+msgid "Missing '%s' or its dependencies."
+msgstr "'%s' 없거나 ì¢…ì† í•­ëª©ì´ ì—†ìŠµë‹ˆë‹¤."
+
+#: editor/editor_node.cpp
+msgid "Error while loading '%s'."
+msgstr "'%s' 로딩 중 ì—러."
+
+#: editor/editor_node.cpp
msgid "Saving Scene"
msgstr "씬 저장"
@@ -1579,9 +1422,8 @@ msgid "Creating Thumbnail"
msgstr "ì¸ë„¤ì¼ ìƒì„± 중"
#: editor/editor_node.cpp
-#, fuzzy
msgid "This operation can't be done without a tree root."
-msgstr "ì´ ìž‘ì—…ì€ ì”¬ ì—†ì´ëŠ” 불가합니다."
+msgstr "ì´ ìž‘ì—…ì€ íŠ¸ë¦¬ 루트 ì—†ì´ëŠ” 불가합니다."
#: editor/editor_node.cpp
msgid ""
@@ -1626,6 +1468,44 @@ msgid "Restored default layout to base settings."
msgstr "기본 ë ˆì´ì•„ì›ƒì´ ì´ˆê¸° 설정으로 ë³µì›ë˜ì—ˆìŠµë‹ˆë‹¤."
#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was imported, so it's not editable.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+"ì´ ë¦¬ì†ŒìŠ¤ëŠ” ê°€ì ¸ì™”ë˜ ì”¬ì— ì†í•œ 것ì´ë¯€ë¡œ 수정할 수 없습니다.\n"
+"관련 ìž‘ì—… 절차를 ë” ìž˜ ì´í•´í•˜ë ¤ë©´ 씬 가져오기(scene importing)ê³¼ ê´€ë ¨ëœ ë¬¸ì„œ"
+"를 확ì¸í•´ì£¼ì‹­ì‹œì˜¤."
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was instanced or inherited.\n"
+"Changes to it will not be kept when saving the current scene."
+msgstr ""
+"ì´ ë¦¬ì†ŒìŠ¤ëŠ” ì¸ìŠ¤í„´ìŠ¤ ë˜ì—ˆê±°ë‚˜ ìƒì†ëœ ê²ƒì— ì†í•©ë‹ˆë‹¤.\n"
+"ì´ ë¦¬ì†ŒìŠ¤ì— ëŒ€í•œ ìˆ˜ì •ì€ í˜„ìž¬ ì”¬ì„ ì €ìž¥í•˜ëŠ” 경우 유지ë˜ì§€ 않습니다."
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource was imported, so it's not editable. Change its settings in the "
+"import panel and then re-import."
+msgstr ""
+"ì´ ë¦¬ì†ŒìŠ¤ëŠ” 가져오기ë˜ì—ˆìœ¼ë¯€ë¡œ 수정할 수 없습니다. 가져오기 패ë„ì—ì„œ ì†ì„±ì„ "
+"변경한 뒤 다시 가져오십시오."
+
+#: editor/editor_node.cpp
+msgid ""
+"This scene was imported, so changes to it will not be kept.\n"
+"Instancing it or inheriting will allow making changes to it.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+"ì´ ì”¬ì€ ê°€ì ¸ì˜¤ê¸°ë˜ì—ˆìœ¼ë¯€ë¡œ ë³€ê²½ì‚¬í•­ì´ ìœ ì§€ë˜ì§€ ì•Šì„ ê²ƒìž…ë‹ˆë‹¤.\n"
+"ì¸ìŠ¤í„´ìŠ¤í™” í˜¹ì€ ìƒì†ì„ 하면 ì”¬ì„ ìˆ˜ì •í•  수 있게 ë©ë‹ˆë‹¤.\n"
+"관련 ìž‘ì—… 절차를 ë” ìž˜ ì´í•´í•˜ë ¤ë©´ 씬 가져오기(scene importing)와 ê´€ë ¨ëœ ë¬¸ì„œ"
+"를 확ì¸í•´ì£¼ì‹­ì‹œì˜¤."
+
+#: editor/editor_node.cpp
msgid "Copy Params"
msgstr "ì†ì„± 복사"
@@ -1658,7 +1538,6 @@ msgid "There is no defined scene to run."
msgstr "실행하기 위해 ì •ì˜ëœ ì”¬ì´ ì—†ìŠµë‹ˆë‹¤."
#: editor/editor_node.cpp
-#, fuzzy
msgid ""
"No main scene has ever been defined, select one?\n"
"You can change it later in \"Project Settings\" under the 'application' "
@@ -1710,22 +1589,20 @@ msgid "Quick Open Script.."
msgstr "빠른 스í¬ë¦½íŠ¸ 열기.."
#: editor/editor_node.cpp
-#, fuzzy
msgid "Save & Close"
-msgstr "파ì¼ë¡œ 저장하기"
+msgstr "저장 ë° ë‹«ê¸°"
#: editor/editor_node.cpp
msgid "Save changes to '%s' before closing?"
-msgstr ""
+msgstr "닫기 ì „ì— '%s' ì— ë³€ê²½ì‚¬í•­ì„ ì €ìž¥í•˜ì‹œê² ìŠµë‹ˆê¹Œ?"
#: editor/editor_node.cpp
msgid "Save Scene As.."
msgstr "ì”¬ì„ ë‹¤ë¥¸ ì´ë¦„으로 저장.."
#: editor/editor_node.cpp
-#, fuzzy
msgid "No"
-msgstr "노드"
+msgstr "아니오"
#: editor/editor_node.cpp
msgid "Yes"
@@ -1748,9 +1625,8 @@ msgid "Export Tile Set"
msgstr "íƒ€ì¼ ì…‹ 내보내기"
#: editor/editor_node.cpp
-#, fuzzy
msgid "This operation can't be done without a selected node."
-msgstr "ì´ ìž‘ì—…ì€ ì”¬ ì—†ì´ëŠ” 불가합니다."
+msgstr "ì´ ìž‘ì—…ì€ ì„ íƒëœ 노드가 ì—†ì„때는 불가합니다."
#: editor/editor_node.cpp
msgid "Current scene not saved. Open anyway?"
@@ -1781,41 +1657,55 @@ msgid "Exit the editor?"
msgstr "ì—디터를 종료하시겠습니까?"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Open Project Manager?"
-msgstr "프로ì íŠ¸ 매니저"
+msgstr "프로ì íŠ¸ 매니저를 여시겠습니까?"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Save & Quit"
-msgstr "파ì¼ë¡œ 저장하기"
+msgstr "저장 ë° ì¢…ë£Œ"
#: editor/editor_node.cpp
msgid "Save changes to the following scene(s) before quitting?"
-msgstr ""
+msgstr "닫기 ì „ì— ë‹¤ìŒ ì”¬(들)ì˜ ë³€ê²½ì‚¬í•­ì„ ì €ìž¥í•˜ì‹œê² ìŠµë‹ˆê¹Œ?"
#: editor/editor_node.cpp
msgid "Save changes the following scene(s) before opening Project Manager?"
+msgstr "프로ì íŠ¸ 매니저를 열기 ì „ì— ë‹¤ìŒ ì”¬(들)ì˜ ë³€ê²½ì‚¬í•­ì„ ì €ìž¥í•˜ì‹œê² ìŠµë‹ˆê¹Œ?"
+
+#: editor/editor_node.cpp
+msgid ""
+"This option is deprecated. Situations where refresh must be forced are now "
+"considered a bug. Please report."
msgstr ""
+"ì´ ì˜µì…˜ì€ ë” ì´ìƒ 사용ë˜ì§€ 않습니다. 반드시 ìƒˆë¡œê³ ì¹¨ì„ í•´ì•¼ 하는 ìƒí™©ì€ ì´ì œ "
+"버그입니다. 신고해주십시오."
#: editor/editor_node.cpp
msgid "Pick a Main Scene"
msgstr "ë©”ì¸ ì”¬ ì„ íƒ"
#: editor/editor_node.cpp
-msgid "Unable to enable addon plugin at: '"
-msgstr ""
+#, fuzzy
+msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
+msgstr "ì´ ê³³ì— ìžˆëŠ” 확장기능 플러그ì¸ì„ 활성화할 수 없습니다: '"
#: editor/editor_node.cpp
-msgid "' parsing of config failed."
-msgstr ""
+#, fuzzy
+msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
+msgstr "ì´ ê³³ì— ìžˆëŠ” 확장기능 플러그ì¸ì„ 활성화할 수 없습니다: '"
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Unable to load addon script from path: '%s'."
+msgstr "ì´ ê³³ì— ìžˆëŠ” 확장기능 플러그ì¸ì„ 활성화할 수 없습니다: '"
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/"
+msgid ""
+"Unable to load addon script from path: '%s' Base type is not EditorPlugin."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to load addon script from path: '"
+msgid "Unable to load addon script from path: '%s' Script is not in tool mode."
msgstr ""
#: editor/editor_node.cpp
@@ -1823,9 +1713,11 @@ msgid ""
"Scene '%s' was automatically imported, so it can't be modified.\n"
"To make changes to it, a new inherited scene can be created."
msgstr ""
+"'%s' ì”¬ì€ ìžë™ìœ¼ë¡œ ìž„í¬íŠ¸ ë˜ì™¸ì„œ, 변경할 수 없습니다.\n"
+"ë³€ê²½ì‚¬í•­ì„ ì ìš©í•˜ë ¤ë©´, 새로운 ìƒì† ì”¬ì„ ë§Œë“œì„¸ìš”."
#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/scene_tree_dock.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Ugh"
msgstr "오우"
@@ -1838,14 +1730,14 @@ msgstr ""
"기'ë¡œ ì”¬ì„ ì—° 후ì—, 프로ì íŠ¸ 경로 ì•ˆì— ì €ìž¥í•˜ì„¸ìš”."
#: editor/editor_node.cpp
-msgid "Error loading scene."
-msgstr "씬 로딩 중 ì—러."
-
-#: editor/editor_node.cpp
msgid "Scene '%s' has broken dependencies:"
msgstr "'%s' ì”¬ì˜ ì¢…ì† í•­ëª©ì´ ê¹¨ì ¸ìžˆìŠµë‹ˆë‹¤.:"
#: editor/editor_node.cpp
+msgid "Clear Recent Scenes"
+msgstr "최근 씬 지우기"
+
+#: editor/editor_node.cpp
msgid "Save Layout"
msgstr "ë ˆì´ì•„웃 저장"
@@ -1875,11 +1767,10 @@ msgid "Distraction Free Mode"
msgstr "초집중 모드"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Toggle distraction-free mode."
-msgstr "초집중 모드"
+msgstr "집중 모드 토글."
-#: editor/editor_node.cpp editor/io_plugins/editor_scene_import_plugin.cpp
+#: editor/editor_node.cpp
msgid "Scene"
msgstr "씬"
@@ -1896,9 +1787,8 @@ msgid "Previous tab"
msgstr "ì´ì „ 탭"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Filter Files.."
-msgstr "빠른 íŒŒì¼ í•„í„°ë§.."
+msgstr "íŒŒì¼ í•„í„°ë§.."
#: editor/editor_node.cpp
msgid "Operations with scene files."
@@ -1964,9 +1854,8 @@ msgid "Miscellaneous project or scene-wide tools."
msgstr "프로ì íŠ¸ ë˜ëŠ” 씬 관련 여러가지 ë„구들."
#: editor/editor_node.cpp
-#, fuzzy
msgid "Project"
-msgstr "새 프로ì íŠ¸"
+msgstr "프로ì íŠ¸"
#: editor/editor_node.cpp
msgid "Project Settings"
@@ -2081,9 +1970,8 @@ msgstr ""
"니다."
#: editor/editor_node.cpp
-#, fuzzy
msgid "Editor"
-msgstr "편집"
+msgstr "ì—디터"
#: editor/editor_node.cpp editor/settings_config_dialog.cpp
msgid "Editor Settings"
@@ -2098,9 +1986,8 @@ msgid "Toggle Fullscreen"
msgstr "전체화면 토글"
#: editor/editor_node.cpp editor/project_export.cpp
-#, fuzzy
msgid "Manage Export Templates"
-msgstr "내보내기 템플릿 로딩 중"
+msgstr "내보내기 템플릿 관리"
#: editor/editor_node.cpp
msgid "Help"
@@ -2111,17 +1998,20 @@ msgid "Classes"
msgstr "í´ëž˜ìŠ¤"
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Online Docs"
-msgstr "문서 닫기"
+msgstr "온ë¼ì¸ 문서"
#: editor/editor_node.cpp
msgid "Q&A"
-msgstr ""
+msgstr "Q&A"
#: editor/editor_node.cpp
msgid "Issue Tracker"
-msgstr ""
+msgstr "ì´ìŠˆ 트래커"
+
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+msgid "Community"
+msgstr "커뮤니티"
#: editor/editor_node.cpp
msgid "About"
@@ -2131,7 +2021,7 @@ msgstr "ì •ë³´"
msgid "Play the project."
msgstr "프로ì íŠ¸ 실행."
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Play"
msgstr "재성"
@@ -2147,7 +2037,7 @@ msgstr "씬 ì¼ì‹œ 정지"
msgid "Stop the scene."
msgstr "씬 정지."
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Stop"
msgstr "정지"
@@ -2220,6 +2110,15 @@ msgid "Object properties."
msgstr "오브ì íŠ¸ ì†ì„±."
#: editor/editor_node.cpp
+msgid "Changes may be lost!"
+msgstr "ë³€ê²½ì‚¬í•­ì„ ìžƒì„ ìˆ˜ 있습니다!"
+
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Import"
+msgstr "가져오기"
+
+#: editor/editor_node.cpp
msgid "FileSystem"
msgstr "íŒŒì¼ ì‹œìŠ¤í…œ"
@@ -2233,15 +2132,7 @@ msgstr "출력"
#: editor/editor_node.cpp
msgid "Don't Save"
-msgstr ""
-
-#: editor/editor_node.cpp editor/editor_reimport_dialog.cpp
-msgid "Re-Import"
-msgstr "다시 가져오기"
-
-#: editor/editor_node.cpp editor/editor_plugin_settings.cpp
-msgid "Update"
-msgstr "갱신"
+msgstr "저장하지 ì•ŠìŒ"
#: editor/editor_node.cpp
msgid "Import Templates From ZIP File"
@@ -2268,9 +2159,8 @@ msgid "Open & Run a Script"
msgstr "스í¬ë¦½íŠ¸ë¥¼ ì—´ê³  실행"
#: editor/editor_node.cpp
-#, fuzzy
msgid "New Inherited"
-msgstr "새 ìƒì† 씬.."
+msgstr "새 ìƒì† 씬"
#: editor/editor_node.cpp
msgid "Load Errors"
@@ -2281,40 +2171,51 @@ msgid "Select"
msgstr "ì„ íƒ"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Open 2D Editor"
-msgstr "ì—디터ì—ì„œ 열기"
+msgstr "2D ì—디터 열기"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Open 3D Editor"
-msgstr "ì—디터ì—ì„œ 열기"
+msgstr "3D ì—디터 열기"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Open Script Editor"
-msgstr "ì—디터ì—ì„œ 열기"
+msgstr "스í¬ë¦½íŠ¸ ì—디터 열기"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Open Asset Library"
-msgstr "ë¼ì´ë¸ŒëŸ¬ë¦¬ 내보내기"
+msgstr "ì–´ì…‹ ë¼ì´ë¸ŒëŸ¬ë¦¬ 열기"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Open the next Editor"
-msgstr "ì—디터ì—ì„œ 열기"
+msgstr "ë‹¤ìŒ ì—디터 열기"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Open the previous Editor"
-msgstr "ì—디터ì—ì„œ 열기"
+msgstr "ì´ì „ ì—디터 열기"
+
+#: editor/editor_plugin.cpp
+msgid "Creating Mesh Previews"
+msgstr "메쉬 미리보기 ìƒì„± 중"
+
+#: editor/editor_plugin.cpp
+msgid "Thumbnail.."
+msgstr "ì¸ë„¤ì¼.."
#: editor/editor_plugin_settings.cpp
msgid "Installed Plugins:"
msgstr "ì„¤ì¹˜ëœ í”ŒëŸ¬ê·¸ì¸:"
#: editor/editor_plugin_settings.cpp
+msgid "Update"
+msgstr "갱신"
+
+#: editor/editor_plugin_settings.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Version:"
+msgstr "버전:"
+
+#: editor/editor_plugin_settings.cpp
msgid "Author:"
msgstr "ì €ìž:"
@@ -2347,7 +2248,8 @@ msgid "Frame %"
msgstr "프레임 %"
#: editor/editor_profiler.cpp
-msgid "Fixed Frame %"
+#, fuzzy
+msgid "Physics Frame %"
msgstr "고정 프레임 %"
#: editor/editor_profiler.cpp editor/script_editor_debugger.cpp
@@ -2366,29 +2268,9 @@ msgstr "ìžì‹ "
msgid "Frame #:"
msgstr "프레임 #:"
-#: editor/editor_reimport_dialog.cpp
-msgid "Please wait for scan to complete."
-msgstr "ìŠ¤ìº”ì´ ì™„ë£Œë  ë•Œê¹Œì§€ 기다려주세요."
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Current scene must be saved to re-import."
-msgstr "다시 가져오기 위해서는 현재 ì”¬ì„ ì €ìž¥í•´ì•¼ 합니다."
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Save & Re-Import"
-msgstr "저장 ë° ë‹¤ì‹œ 가져오기"
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Importing"
-msgstr "다시 가져오기"
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Import Changed Resources"
-msgstr "ë³€ê²½ëœ ë¦¬ì†ŒìŠ¤ 다시 가져오기"
-
#: editor/editor_run_native.cpp
msgid "Select device from the list"
-msgstr ""
+msgstr "목ë¡ì—ì„œ 기기를 ì„ íƒí•˜ì„¸ìš”"
#: editor/editor_run_native.cpp
msgid ""
@@ -2437,33 +2319,28 @@ msgid "Import From Node:"
msgstr "노드ì—ì„œ 가져오기:"
#: editor/export_template_manager.cpp
-#, fuzzy
msgid "Re-Download"
-msgstr "다시 로드"
+msgstr "다시 다운로드"
#: editor/export_template_manager.cpp
-#, fuzzy
msgid "Uninstall"
-msgstr "설치"
+msgstr "삭제"
#: editor/export_template_manager.cpp
-#, fuzzy
msgid "(Installed)"
-msgstr "설치"
+msgstr "(설치ë¨)"
#: editor/export_template_manager.cpp
-#, fuzzy
msgid "Download"
-msgstr "아래"
+msgstr "다운로드"
#: editor/export_template_manager.cpp
msgid "(Missing)"
msgstr ""
#: editor/export_template_manager.cpp
-#, fuzzy
msgid "(Current)"
-msgstr "현재:"
+msgstr "(현재)"
#: editor/export_template_manager.cpp
msgid "Remove template version '%s'?"
@@ -2488,52 +2365,40 @@ msgid "No version.txt found inside templates."
msgstr ""
#: editor/export_template_manager.cpp
-#, fuzzy
msgid "Error creating path for templates:\n"
-msgstr "ì•„í‹€ë¼ìŠ¤ 저장 중 ì—러:"
+msgstr "템플릿 경로 ìƒì„± ì—러:\n"
#: editor/export_template_manager.cpp
-#, fuzzy
msgid "Extracting Export Templates"
-msgstr "내보내기 템플릿 로딩 중"
+msgstr "내보내기 템플릿 압축해제 중"
#: editor/export_template_manager.cpp
msgid "Importing:"
msgstr "가져오는 중:"
#: editor/export_template_manager.cpp
-msgid "Loading Export Templates"
-msgstr "내보내기 템플릿 로딩 중"
-
-#: editor/export_template_manager.cpp
-#, fuzzy
msgid "Current Version:"
-msgstr "현재 씬"
+msgstr "현재 버전:"
#: editor/export_template_manager.cpp
-#, fuzzy
msgid "Installed Versions:"
-msgstr "ì„¤ì¹˜ëœ í”ŒëŸ¬ê·¸ì¸:"
+msgstr "ì„¤ì¹˜ëœ ë²„ì „:"
#: editor/export_template_manager.cpp
-#, fuzzy
msgid "Install From File"
-msgstr "프로ì íŠ¸ 설치:"
+msgstr "파ì¼ë¡œë¶€í„° 설치"
#: editor/export_template_manager.cpp
-#, fuzzy
msgid "Remove Template"
-msgstr "ì•„ì´í…œ ì‚­ì œ"
+msgstr "템플릿 제거"
#: editor/export_template_manager.cpp
-#, fuzzy
msgid "Select template file"
-msgstr "ì„ íƒëœ 파ì¼ë“¤ì„ 삭제하시겠습니까?"
+msgstr "템플릿 íŒŒì¼ ì„ íƒ"
#: editor/export_template_manager.cpp
-#, fuzzy
msgid "Export Template Manager"
-msgstr "내보내기 템플릿 로딩 중"
+msgstr "내보내기 템플릿 매니저"
#: editor/file_type_cache.cpp
msgid "Can't open file_type_cache.cch for writing, not saving file type cache!"
@@ -2544,105 +2409,110 @@ msgid "Cannot navigate to '"
msgstr ""
#: editor/filesystem_dock.cpp
-#, fuzzy
+msgid "View items as a grid of thumbnails"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "View items as a list"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
msgid ""
"\n"
-"Status: Needs Re-Import"
-msgstr "저장 ë° ë‹¤ì‹œ 가져오기"
+"Status: Import of file failed. Please fix file and reimport manually."
+msgstr ""
#: editor/filesystem_dock.cpp
-#, fuzzy
msgid ""
"\n"
"Source: "
-msgstr "소스:"
+msgstr ""
+"\n"
+"소스: "
#: editor/filesystem_dock.cpp
-msgid "Same source and destination files, doing nothing."
-msgstr "소스와 ëŒ€ìƒ íŒŒì¼ì´ ë™ì¼í•˜ì—¬, 무시ë©ë‹ˆë‹¤."
+msgid "Cannot move/rename resources root."
+msgstr "리소스 루트를 옮기거나 ì´ë¦„ì„ ë³€ê²½í•  수 없습니다."
#: editor/filesystem_dock.cpp
-msgid "Target file exists, can't overwrite. Delete first."
-msgstr ""
+msgid "Cannot move a folder into itself.\n"
+msgstr "í´ë”를 ìžì‹ ì˜ 하위로 ì´ë™í•  수 없습니다.\n"
#: editor/filesystem_dock.cpp
-msgid "Same source and destination paths, doing nothing."
-msgstr "소스와 ëŒ€ìƒ ê²½ë¡œê°€ ë™ì¼í•˜ì—¬, 무시ë©ë‹ˆë‹¤."
+msgid "Error moving:\n"
+msgstr "ì´ë™ ì—러:\n"
#: editor/filesystem_dock.cpp
-msgid "Can't move directories to within themselves."
-msgstr "디렉토리를 ìžì‹ ìœ¼ë¡œ ì´ë™í•  수 없습니다."
+msgid "Unable to update dependencies:\n"
+msgstr "종ì†í•­ëª©ì„ ì—…ë°ì´íŠ¸ í•  수 없습니다:\n"
#: editor/filesystem_dock.cpp
-msgid "Can't rename deps for:\n"
+msgid "No name provided"
msgstr ""
#: editor/filesystem_dock.cpp
-#, fuzzy
-msgid "Error moving file:\n"
-msgstr "ì´ë¯¸ì§€ 로드 ì—러:"
+msgid "Provided name contains invalid characters"
+msgstr ""
#: editor/filesystem_dock.cpp
-#, fuzzy
-msgid "Error moving dir:\n"
-msgstr "가져오기 ì—러:"
+msgid "No name provided."
+msgstr "ì´ë¦„ì´ ì œê³µë˜ì§€ 않았습니다."
#: editor/filesystem_dock.cpp
-msgid "Can't operate on '..'"
-msgstr "'..'ì— ìˆ˜í–‰í•  수 ì—†ìŒ"
+msgid "Name contains invalid characters."
+msgstr "ì´ë¦„ì— ìœ íš¨í•˜ì§€ ì•Šì€ ë¬¸ìžê°€ 있습니다."
#: editor/filesystem_dock.cpp
-msgid "Pick New Name and Location For:"
-msgstr "새로운 ì´ë¦„ê³¼ 위치를 고르세요:"
+msgid "A file or folder with this name already exists."
+msgstr "파ì¼ì´ë‚˜ í´ë”ê°€ 해당 ì´ë¦„ì„ ì‚¬ìš©ì¤‘ìž…ë‹ˆë‹¤."
#: editor/filesystem_dock.cpp
-msgid "No files selected!"
-msgstr "파ì¼ì´ ì„ íƒë˜ì§€ 않았습니다!"
+msgid "Renaming file:"
+msgstr "파ì¼ëª… 변경:"
+
+#: editor/filesystem_dock.cpp
+msgid "Renaming folder:"
+msgstr "í´ë”명 변경:"
#: editor/filesystem_dock.cpp
-#, fuzzy
msgid "Expand all"
-msgstr "부모로 확장"
+msgstr "ëª¨ë‘ í™•ìž¥"
#: editor/filesystem_dock.cpp
msgid "Collapse all"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Show In File Manager"
-msgstr "íŒŒì¼ ë§¤ë‹ˆì €ì—ì„œ 보기"
-
-#: editor/filesystem_dock.cpp
-msgid "Instance"
-msgstr "ì¸ìŠ¤í„´ìŠ¤"
+msgid "Copy Path"
+msgstr "경로 복사"
#: editor/filesystem_dock.cpp
-msgid "Edit Dependencies.."
-msgstr "ì¢…ì† ê´€ê³„ 편집.."
+msgid "Rename.."
+msgstr "ì´ë¦„ 변경.."
#: editor/filesystem_dock.cpp
-msgid "View Owners.."
-msgstr "ì†Œìœ ìž ë³´ê¸°.."
+msgid "Move To.."
+msgstr "ì´ë™.."
#: editor/filesystem_dock.cpp
-msgid "Copy Path"
-msgstr "경로 복사"
+msgid "New Folder.."
+msgstr "새 í´ë”.."
#: editor/filesystem_dock.cpp
-msgid "Rename or Move.."
-msgstr "ì´ë¦„ 변경 ë˜ëŠ” ì´ë™.."
+msgid "Show In File Manager"
+msgstr "íŒŒì¼ ë§¤ë‹ˆì €ì—ì„œ 보기"
#: editor/filesystem_dock.cpp
-msgid "Move To.."
-msgstr "ì´ë™.."
+msgid "Instance"
+msgstr "ì¸ìŠ¤í„´ìŠ¤"
#: editor/filesystem_dock.cpp
-msgid "Info"
-msgstr "ì •ë³´"
+msgid "Edit Dependencies.."
+msgstr "ì¢…ì† ê´€ê³„ 편집.."
#: editor/filesystem_dock.cpp
-msgid "Re-Import.."
-msgstr "다시 가져오기.."
+msgid "View Owners.."
+msgstr "ì†Œìœ ìž ë³´ê¸°.."
#: editor/filesystem_dock.cpp
msgid "Previous Directory"
@@ -2674,6 +2544,11 @@ msgstr ""
msgid "Move"
msgstr "ì´ë™"
+#: editor/filesystem_dock.cpp editor/plugins/animation_tree_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Rename"
+msgstr "ì´ë¦„ 변경"
+
#: editor/groups_editor.cpp
msgid "Add to Group"
msgstr "ê·¸ë£¹ì— ì¶”ê°€"
@@ -2683,9 +2558,12 @@ msgid "Remove from Group"
msgstr "그룹ì—ì„œ 제거"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Import as Single Scene"
-msgstr "씬 가져오는 중.."
+msgstr "ë‹¨ì¼ ì”¬ìœ¼ë¡œ 가져오기"
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Animations"
+msgstr "애니메ì´ì…˜ì„ 분리시켜 가져오기"
#: editor/import/resource_importer_scene.cpp
msgid "Import with Separate Materials"
@@ -2700,48 +2578,52 @@ msgid "Import with Separate Objects+Materials"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
+msgid "Import with Separate Objects+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Materials+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Materials+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
msgid "Import as Multiple Scenes"
-msgstr "3D 씬 가져오기"
+msgstr "ì—¬ëŸ¬ê°œì˜ ì”¬ìœ¼ë¡œ 가져오기"
#: editor/import/resource_importer_scene.cpp
msgid "Import as Multiple Scenes+Materials"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Import Scene"
msgstr "씬 가져오기"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Importing Scene.."
msgstr "씬 가져오는 중.."
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Running Custom Script.."
msgstr "ì‚¬ìš©ìž ì •ì˜ ìŠ¤í¬ë¦½íŠ¸ 실행중.."
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Couldn't load post-import script:"
msgstr "가져오기 후 실행할 스í¬ë¦½íŠ¸ë¥¼ 로드할 수 없습니다:"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Invalid/broken script for post-import (check console):"
msgstr ""
"가져오기 후 실행할 스í¬ë¦½íŠ¸ê°€ 유효하지 않거나 깨져있습니다 (콘솔 확ì¸):"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Error running post-import script:"
msgstr "가져오기 후 실행할 스í¬ë¦½íŠ¸ 실행 중 ì—러:"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Saving.."
msgstr "저장 중.."
@@ -2754,595 +2636,21 @@ msgid "Clear Default for '%s'"
msgstr ""
#: editor/import_dock.cpp
-#, fuzzy
msgid " Files"
-msgstr "파ì¼"
+msgstr " 파ì¼"
#: editor/import_dock.cpp
-#, fuzzy
msgid "Import As:"
-msgstr "가져오기"
+msgstr "ë‹¤ìŒ í˜•ì‹ìœ¼ë¡œ 가져오기:"
#: editor/import_dock.cpp editor/property_editor.cpp
msgid "Preset.."
msgstr "프리셋.."
#: editor/import_dock.cpp
-#, fuzzy
msgid "Reimport"
msgstr "다시 가져오기"
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "No bit masks to import!"
-msgstr "가져올 비트 마스í¬ê°€ 없습니다!"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path is empty."
-msgstr "ëŒ€ìƒ ê²½ë¡œê°€ 없습니다."
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must be a complete resource path."
-msgstr "ëŒ€ìƒ ê²½ë¡œëŠ” 완전한 리소스 경로여야 합니다."
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must exist."
-msgstr "ëŒ€ìƒ ê²½ë¡œê°€ 존재해야 합니다."
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Save path is empty!"
-msgstr "저장 경로가 없습니다!"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Import BitMasks"
-msgstr "ë¹„íŠ¸ë§ˆìŠ¤í¬ ê°€ì ¸ì˜¤ê¸°"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s):"
-msgstr "소스 í…스ì³:"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Target Path:"
-msgstr "ëŒ€ìƒ ê²½ë¡œ:"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Accept"
-msgstr "수ë½"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Bit Mask"
-msgstr "비트 마스í¬"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No source font file!"
-msgstr "소스 í°íŠ¸ 파ì¼ì´ 없습니다!"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No target font resource!"
-msgstr "í°íŠ¸ 리소스 경로가 없습니다!"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#, fuzzy
-msgid ""
-"Invalid file extension.\n"
-"Please use .font."
-msgstr ""
-"유효하지 ì•Šì€ íŒŒì¼ í™•ìž¥ìž.\n"
-".fnt 를 사용하세요."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Can't load/process source font."
-msgstr "소스 í°íŠ¸ë¥¼ 로드/처리할 수 없습니다."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Couldn't save font."
-msgstr "í°íŠ¸ë¥¼ 저장할 수 없습니다."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font:"
-msgstr "소스 í°íŠ¸:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font Size:"
-msgstr "소스 í°íŠ¸ í¬ê¸°:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Dest Resource:"
-msgstr "리소스 경로:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "The quick brown fox jumps over the lazy dog."
-msgstr ""
-"The quick brown fox jumps over the lazy dog.\n"
-"ë‹¤ëžŒì¥ í—Œ ì³‡ë°”í€´ì— íƒ€ê³ íŒŒ."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Test:"
-msgstr "테스트:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Options:"
-msgstr "옵션:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Font Import"
-msgstr "í°íŠ¸ 가져오기"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"This file is already a Godot font file, please supply a BMFont type file "
-"instead."
-msgstr "ì´ íŒŒì¼ì€ ì´ë¯¸ Godot í°íŠ¸ 파ì¼ìž…니다. BMFont 파ì¼ì„ ì„ íƒí•˜ì„¸ìš”."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Failed opening as BMFont file."
-msgstr "BMFont 파ì¼ì„ ì—¬ëŠ”ë° ì‹¤íŒ¨í–ˆìŠµë‹ˆë‹¤."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error initializing FreeType."
-msgstr "FreeType 초기화 ì—러."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Unknown font format."
-msgstr "ì•Œ 수 없는 í°íŠ¸ í¬ë©§."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error loading font."
-msgstr "í°íŠ¸ 로딩 ì—러."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Invalid font size."
-msgstr "유요하지 ì•Šì€ í°íŠ¸ 사ì´ì¦ˆ."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Invalid font custom source."
-msgstr "ì‚¬ìš©ìž ì§€ì • í°íŠ¸ 소스가 유효하지 않습니다."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/plugins/theme_editor_plugin.cpp
-msgid "Font"
-msgstr "í°íŠ¸"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "No meshes to import!"
-msgstr "가져올 메쉬가 없습니다!"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Single Mesh Import"
-msgstr "ë‹¨ì¼ ë©”ì‰¬ 가져오기"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Source Mesh(es):"
-msgstr "소스 메쉬:"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/plugins/mesh_instance_editor_plugin.cpp
-msgid "Mesh"
-msgstr "메쉬"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Surface %d"
-msgstr "서페ì´ìŠ¤ %d"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "No samples to import!"
-msgstr "가져올 ìƒ˜í”Œì´ ì—†ìŠµë‹ˆë‹¤!"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Import Audio Samples"
-msgstr "오디오 샘플 가져오기"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Source Sample(s):"
-msgstr "소스 샘플:"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Audio Sample"
-msgstr "오디오 샘플"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "New Clip"
-msgstr "새 í´ë¦½"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Animation Options"
-msgstr "애니메ì´ì…˜ 옵션"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Flags"
-msgstr "플래그"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Bake FPS:"
-msgstr "FPS 설정:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Optimizer"
-msgstr "최ì í™”"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Linear Error"
-msgstr "최대 선형 오류"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angular Error"
-msgstr "최대 ê°ë„ 오류"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angle"
-msgstr "최대 ê°ë„"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Clips"
-msgstr "í´ë¦½"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Start(s)"
-msgstr "시작(초)"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "End(s)"
-msgstr "ë(ì´ˆ)"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Loop"
-msgstr "루프"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Filters"
-msgstr "í•„í„°"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source path is empty."
-msgstr "소스 경로가 비어있습니다."
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't load post-import script."
-msgstr "가져오기 후 실행할 스í¬ë¦½íŠ¸ë¥¼ 로드할 수 없습니다."
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Invalid/broken script for post-import."
-msgstr "가져오기 후 실행할 스í¬ë¦½íŠ¸ê°€ 유효하지 않거나 깨져있습니다."
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Error importing scene."
-msgstr "씬 가져오기 ì—러."
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import 3D Scene"
-msgstr "3D 씬 가져오기"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source Scene:"
-msgstr "소스 씬:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Same as Target Scene"
-msgstr "ëŒ€ìƒ ì”¬ê³¼ ê°™ìŒ"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Shared"
-msgstr "공유ë¨"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Target Texture Folder:"
-msgstr "ëŒ€ìƒ í…ìŠ¤ì³ í´ë”:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Post-Process Script:"
-msgstr "가져오기 후 수행할 스í¬ë¦½íŠ¸:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Custom Root Node Type:"
-msgstr "ì‚¬ìš©ìž ì •ì˜ ë£¨íŠ¸ 노드 타입:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Auto"
-msgstr "ìžë™"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Root Node Name:"
-msgstr "루트 노드 ì´ë¦„:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "The Following Files are Missing:"
-msgstr "다ìŒì˜ 파ì¼ë“¤ì´ 빠져있습니다:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Anyway"
-msgstr "무시하고 가져오기"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp scene/gui/dialogs.cpp
-msgid "Cancel"
-msgstr "취소"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import & Open"
-msgstr "가져오기 후 열기"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Edited scene has not been saved, open imported scene anyway?"
-msgstr "íŽ¸ì§‘ëœ ì”¬ì´ ì €ìž¥ë˜ì§€ 않았습니다. 무시하고 가져온 ì”¬ì„ ì—¬ì‹œê² ìŠµë‹ˆê¹Œ?"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Image:"
-msgstr "ì´ë¯¸ì§€ 가져오기:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Can't import a file over itself:"
-msgstr "ìžì‹ ì„ 가져올 수 없습니다:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't localize path: %s (already local)"
-msgstr "경로를 로컬 경로로 바꿀 수 없습니다: %s (ì´ë¯¸ 로컬 경로)"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "3D Scene Animation"
-msgstr "3D 씬 애니메ì´ì…˜"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Uncompressed"
-msgstr "무압축"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossless (PNG)"
-msgstr "무ì†ì‹¤ 압축 (PNG)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossy (WebP)"
-msgstr "ì†ì‹¤ 압축 (PNG)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress (VRAM)"
-msgstr "압축 (VRAM)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Format"
-msgstr "í…ìŠ¤ì³ í¬ë©§"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Compression Quality (WebP):"
-msgstr "í…ìŠ¤ì³ ì••ì¶• 품질 (WebP):"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Options"
-msgstr "í…ìŠ¤ì³ ì˜µì…˜"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Please specify some files!"
-msgstr "파ì¼ì„ 지정하세요!"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "At least one file needed for Atlas."
-msgstr "ì•„í‹€ë¼ìŠ¤ ìƒì„±ì„ 위해서는 최소 1ê°œ ì´ìƒì˜ 파ì¼ì´ 필요합니다."
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Error importing:"
-msgstr "가져오기 ì—러:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Only one file is required for large texture."
-msgstr "í° í…스ì³ë¥¼ 위해서는 단 í•˜ë‚˜ì˜ íŒŒì¼ë§Œ 요구ë©ë‹ˆë‹¤."
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Max Texture Size:"
-msgstr "최대 í…ìŠ¤ì³ ì‚¬ì´ì¦ˆ:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for Atlas (2D)"
-msgstr "ì•„í‹€ë¼ìŠ¤ë¥¼ 위한 í…ìŠ¤ì³ ê°€ì ¸ì˜¤ê¸° (2D)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cell Size:"
-msgstr "쎌 사ì´ì¦ˆ:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Large Texture"
-msgstr "í° í…스ì³"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Textures (2D)"
-msgstr "í° í…ìŠ¤ì³ ê°€ì ¸ì˜¤ê¸° (2D)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture"
-msgstr "소스 í…스ì³"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Base Atlas Texture"
-msgstr "기본 ì•„í‹€ë¼ìŠ¤ í…스ì³"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s)"
-msgstr "소트 í…스ì³"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 2D"
-msgstr "2D í…ìŠ¤ì³ ê°€ì ¸ì˜¤ê¸°"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 3D"
-msgstr "3D í…ìŠ¤ì³ ê°€ì ¸ì˜¤ê¸°"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures"
-msgstr "í…ìŠ¤ì³ ê°€ì ¸ì˜¤ê¸°"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "2D Texture"
-msgstr "2D í…스ì³"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "3D Texture"
-msgstr "3D í…스ì³"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Atlas Texture"
-msgstr "í…ìŠ¤ì³ ì•„í‹€ë¼ìŠ¤"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid ""
-"NOTICE: Importing 2D textures is not mandatory. Just copy png/jpg files to "
-"the project."
-msgstr ""
-"알림: 2D í…ìŠ¤ì³ ê°€ì ¸ì˜¤ê¸°ê°€ 필수는 아닙니다. png/jpg 파ì¼ë“¤ì„ 프로ì íŠ¸ì— 복사"
-"í•´ì„œ ì‚¬ìš©í•´ë„ ë©ë‹ˆë‹¤."
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Crop empty space."
-msgstr "빈 ì˜ì—­ 잘ë¼ë‚´ê¸°."
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture"
-msgstr "í…스ì³"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Texture"
-msgstr "í° í…ìŠ¤ì³ ê°€ì ¸ì˜¤ê¸°"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Load Source Image"
-msgstr "소스 ì´ë¯¸ì§€ 로드"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Slicing"
-msgstr "ìžë¥´ëŠ” 중"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Inserting"
-msgstr "삽입 중"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Saving"
-msgstr "저장 중"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save large texture:"
-msgstr "í° í…스ì³ë¥¼ 저장할 수 ì—†ìŒ:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Build Atlas For:"
-msgstr "ì•„í‹€ë¼ìŠ¤ ìƒì„±:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Loading Image:"
-msgstr "ì´ë¯¸ì§€ 로딩:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't load image:"
-msgstr "ì´ë¯¸ì§€ë¥¼ 로드할 수 ì—†ìŒ:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Converting Images"
-msgstr "ì´ë¯¸ì§€ 변환 중"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cropping Images"
-msgstr "ì´ë¯¸ì§€ ìžë¥´ëŠ” 중"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Blitting Images"
-msgstr "ì´ë¯¸ì§€ 병합 중"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save atlas image:"
-msgstr "ì•„í‹€ë¼ìŠ¤ ì´ë¯¸ì§€ë¥¼ 저장할 수 ì—†ìŒ:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save converted texture:"
-msgstr "ë³€í™˜ëœ í…스ì³ë¥¼ 저장할 수 ì—†ìŒ:"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid source!"
-msgstr "유효하지 ì•Šì€ ì†ŒìŠ¤!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid translation source!"
-msgstr "유효하지 ì•Šì€ ë²ˆì—­ 소스!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Column"
-msgstr "ì—´"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/script_create_dialog.cpp
-msgid "Language"
-msgstr "언어"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No items to import!"
-msgstr "가져올 í•­ëª©ì´ ì—†ìŠµë‹ˆë‹¤!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No target path!"
-msgstr "ëŒ€ìƒ ê²½ë¡œê°€ 없습니다!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translations"
-msgstr "번역 가져오기"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Couldn't import!"
-msgstr "가져올 수 없습니다!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translation"
-msgstr "번역 가져오기"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Source CSV:"
-msgstr "소스 CSV:"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Ignore First Row"
-msgstr "첫째줄 무시"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Compress"
-msgstr "압축"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#, fuzzy
-msgid "Add to Project (project.godot)"
-msgstr "프로ì íŠ¸ì— 추가 (engine.cfg)"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Languages:"
-msgstr "언어 가져오기:"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Translation"
-msgstr "번역"
-
#: editor/multi_node_edit.cpp
msgid "MultiNode Set"
msgstr "다중 노드 설정"
@@ -3355,6 +2663,44 @@ msgstr "그룹"
msgid "Select a Node to edit Signals and Groups."
msgstr "시그ë„ê³¼ ê·¸ë£¹ì„ íŽ¸ì§‘í•  노드를 ì„ íƒí•˜ì„¸ìš”."
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create Poly"
+msgstr "í´ë¦¬ê³¤ ìƒì„±"
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly"
+msgstr "í´ë¦¬ê³¤ 편집"
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Insert Point"
+msgstr "í¬ì¸íŠ¸ 삽입"
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly (Remove Point)"
+msgstr "í´ë¦¬ê³¤ 편집 (ì  ì‚­ì œ)"
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Remove Poly And Point"
+msgstr "í´ë¦¬ê³¤ê³¼ í¬ì¸íŠ¸ ì‚­ì œ"
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create a new polygon from scratch."
+msgstr "처ìŒë¶€í„° 새로운 í´ë¦¬ê³¤ 만들기."
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid ""
+"Edit existing polygon:\n"
+"LMB: Move Point.\n"
+"Ctrl+LMB: Split Segment.\n"
+"RMB: Erase Point."
+msgstr ""
+
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Toggle Autoplay"
msgstr "ìžë™ ìž¬ìƒ ì „í™˜"
@@ -3372,9 +2718,8 @@ msgid "Change Animation Name:"
msgstr "애니메ì´ì…˜ ì´ë¦„ 변경:"
#: editor/plugins/animation_player_editor_plugin.cpp
-#, fuzzy
msgid "Delete Animation?"
-msgstr "애니메ì´ì…˜ 복제하기"
+msgstr "애니메ì´ì…˜ì„ 삭제하시겠습니까?"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
@@ -3509,7 +2854,6 @@ msgstr "애니메ì´ì…˜ ì´ë¦„:"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
#: editor/script_create_dialog.cpp
msgid "Error!"
@@ -3537,9 +2881,8 @@ msgid "New name:"
msgstr "새 ì´ë¦„:"
#: editor/plugins/animation_tree_editor_plugin.cpp
-#, fuzzy
msgid "Edit Filters"
-msgstr "노드 필터 편집"
+msgstr "필터 편집"
#: editor/plugins/animation_tree_editor_plugin.cpp
#: editor/plugins/multimesh_editor_plugin.cpp
@@ -3620,10 +2963,6 @@ msgid "Delete Input"
msgstr "입력 삭제"
#: editor/plugins/animation_tree_editor_plugin.cpp
-msgid "Rename"
-msgstr "ì´ë¦„ 변경"
-
-#: editor/plugins/animation_tree_editor_plugin.cpp
msgid "Animation tree is valid."
msgstr "애니메ì´ì…˜ 트리가 유효합니다."
@@ -3679,64 +3018,181 @@ msgstr "노드 필터 편집"
msgid "Filters.."
msgstr "í•„í„°.."
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing %d Triangles:"
-msgstr "%dê°œ 삼ê°í˜• ë¶„ì„ ì¤‘:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Free"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Contents:"
+msgstr "컨í…츠:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Triangle #"
-msgstr "삼ê°í˜• #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "View Files"
+msgstr "íŒŒì¼ ë³´ê¸°"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Light Baker Setup:"
-msgstr "ë¼ì´íŠ¸ ë² ì´ì»¤ 설정:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve hostname:"
+msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing Geometry"
-msgstr "지오미트리 ë¶„ì„ ì¤‘"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connection error, please try again."
+msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Fixing Lights"
-msgstr "ë¼ì´íŠ¸ 수정 중"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't connect."
+msgstr "ì—°ê²°í•  수 ì—†ìŒ."
-#: editor/plugins/baked_light_baker.cpp
-msgid "Making BVH"
-msgstr "BVH 만드는 중"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't connect to host:"
+msgstr "í˜¸ìŠ¤íŠ¸ì— ì—°ê²°í•  수 ì—†ìŒ:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Light Octree"
-msgstr "ë¼ì´íŠ¸ 오í¬íŠ¸ë¦¬ ìƒì„± 중"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response from host:"
+msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Octree Texture"
-msgstr "오í¬íŠ¸ë¦¬ í…ìŠ¤ì³ ìƒì„± 중"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response."
+msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Transfer to Lightmaps:"
-msgstr "ë¼ì´íŠ¸ë§µìœ¼ë¡œ 전송:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, return code:"
+msgstr "요청 실패, 리턴 코드:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Allocating Texture #"
-msgstr "í…ìŠ¤ì³ í• ë‹¹ 중 #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Req. Failed."
+msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Baking Triangle #"
-msgstr "삼ê°í˜• 굽는 중 #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, too many redirects"
+msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Post-Processing Texture #"
-msgstr "í…ìŠ¤ì³ í›„ì²˜ë¦¬ 중 #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Redirect Loop."
+msgstr ""
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Bake!"
-msgstr "굽기!"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Bad download hash, assuming file has been tampered with."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Expected:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Got:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed sha256 hash check"
+msgstr ""
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Reset the lightmap octree baking process (start over)."
-msgstr "ë¼ì´íŠ¸ë§µ 오í¬íŠ¸ë¦¬ 굽기 프로세스 재설정 (처ìŒë¶€í„° 다시)."
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Asset Download Error:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Fetching:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Resolving.."
+msgstr "해결 중.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connecting.."
+msgstr "연결중.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Requesting.."
+msgstr "요청중.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Error making request"
+msgstr "요청 ì—러"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Idle"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Retry"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download Error"
+msgstr "다운로드 ì—러"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download for this asset is already in progress!"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "first"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "prev"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "next"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "last"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "All"
+msgstr "모ë‘"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Plugins"
+msgstr "플러그ì¸"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Sort:"
+msgstr "ì •ë ¬:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Reverse"
+msgstr "뒤집기"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Category:"
+msgstr "카테고리:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Site:"
+msgstr "사ì´íŠ¸:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Support.."
+msgstr "지ì›.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Official"
+msgstr "ê³µì‹"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Testing"
+msgstr "테스팅"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Assets ZIP File"
+msgstr "ì—ì…‹ ZIP 파ì¼"
#: editor/plugins/camera_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
msgid "Preview"
msgstr "미리보기"
@@ -3779,12 +3235,16 @@ msgid "Edit CanvasItem"
msgstr "CanvasItem 편집"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Change Anchors"
-msgstr "앵커 변경"
+msgid "Anchors only"
+msgstr "앵커만"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom (%):"
-msgstr "확대 (%):"
+msgid "Change Anchors and Margins"
+msgstr "앵커와 마진 변경"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Change Anchors"
+msgstr "앵커 변경"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Paste Pose"
@@ -3836,60 +3296,73 @@ msgid "Pan Mode"
msgstr "팬 모드"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Lock the selected object in place (can't be moved)."
-msgstr "ì„ íƒëœ 오브ì íŠ¸ë¥¼ 잠급니다 (ì´ë™ë¶ˆê°€)."
+msgid "Toggles snapping"
+msgstr "스냅 토글"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Unlock the selected object (can be moved)."
-msgstr "ì„ íƒëœ 오브ì íŠ¸ë¥¼ 잠금 해제합니다 (ì´ë™ê°€ëŠ¥)."
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Use Snap"
+msgstr "스냅 사용"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Makes sure the object's children are not selectable."
-msgstr "오브ì íŠ¸ì˜ ìžì‹ë…¸ë“œê°€ ì„ íƒë  수 ì—†ë„ë¡ ì„¤ì •í•©ë‹ˆë‹¤."
+msgid "Snapping options"
+msgstr "스냅 옵션"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Restores the object's children's ability to be selected."
-msgstr "오브ì íŠ¸ì˜ ìžì‹ë…¸ë“œê°€ ì„ íƒë  수 있ë„ë¡ ë³µì›í•©ë‹ˆë‹¤."
+msgid "Snap to grid"
+msgstr "ê·¸ë¦¬ë“œì— ë§žì¶¤"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Edit"
-msgstr "편집"
+msgid "Use Rotation Snap"
+msgstr "회전 스냅 사용"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Use Snap"
-msgstr "스냅 사용"
+msgid "Configure Snap..."
+msgstr "스냅 설정..."
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Show Grid"
-msgstr "그리드 ë³´ì´ê¸°"
+msgid "Snap Relative"
+msgstr "ìƒëŒ€ì ì¸ 스냅"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Rotation Snap"
-msgstr "회전 스냅 사용"
+msgid "Use Pixel Snap"
+msgstr "픽셀 스냅 사용"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap Relative"
-msgstr "ìƒëŒ€ì ì¸ 스냅"
+msgid "Smart snapping"
+msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Configure Snap.."
-msgstr "스냅 설정.."
+msgid "Snap to parent"
+msgstr "ë¶€ëª¨ì— ë§žì¶¤"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Pixel Snap"
-msgstr "픽셀 스냅 사용"
+msgid "Snap to node anchor"
+msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Skeleton.."
-msgstr "스켈레톤.."
+msgid "Snap to node sides"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to other nodes"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Lock the selected object in place (can't be moved)."
+msgstr "ì„ íƒëœ 오브ì íŠ¸ë¥¼ 잠급니다 (ì´ë™ë¶ˆê°€)."
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Unlock the selected object (can be moved)."
+msgstr "ì„ íƒëœ 오브ì íŠ¸ë¥¼ 잠금 해제합니다 (ì´ë™ê°€ëŠ¥)."
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Makes sure the object's children are not selectable."
+msgstr "오브ì íŠ¸ì˜ ìžì‹ë…¸ë“œê°€ ì„ íƒë  수 ì—†ë„ë¡ ì„¤ì •í•©ë‹ˆë‹¤."
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Restores the object's children's ability to be selected."
+msgstr "오브ì íŠ¸ì˜ ìžì‹ë…¸ë“œê°€ ì„ íƒë  수 있ë„ë¡ ë³µì›í•©ë‹ˆë‹¤."
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Make Bones"
@@ -3917,12 +3390,17 @@ msgid "View"
msgstr "보기"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Reset"
-msgstr "확대 초기화"
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Show Grid"
+msgstr "그리드 ë³´ì´ê¸°"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Set.."
-msgstr "확대 설정.."
+msgid "Show helpers"
+msgstr "í—¬í¼ ë³´ê¸°"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Show rulers"
+msgstr "ìž ë³´ê¸°"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Center Selection"
@@ -3933,8 +3411,8 @@ msgid "Frame Selection"
msgstr "ì„ íƒí•­ëª© 화면 꽉차게 표시"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Anchor"
-msgstr "앵커"
+msgid "Layout"
+msgstr "ë ˆì´ì•„웃"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Insert Keys"
@@ -3957,12 +3435,20 @@ msgid "Clear Pose"
msgstr "í¬ì¦ˆ 정리"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Set a Value"
-msgstr "값 설정"
+msgid "Drag pivot from mouse position"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Set pivot at mouse position"
+msgstr "마우스 ìœ„ì¹˜ì— í”¼ë²— 설정"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap (Pixels):"
-msgstr "스냅 (픽셀):"
+msgid "Multiply grid step by 2"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Divide grid step by 2"
+msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Add %s"
@@ -3972,23 +3458,28 @@ msgstr "%s 추가"
msgid "Adding %s..."
msgstr "%s 추가중..."
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Create Node"
msgstr "노드 ìƒì„±"
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Error instancing scene from %s"
msgstr "'%s' 로부터 씬 ì¸ìŠ¤í„´ìŠ¤ 중 ì—러"
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "OK :("
msgstr "넹 :("
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "No parent to instance a child at."
msgstr "ì„ íƒëœ 부모 노드가 없어서 ìžì‹ë…¸ë“œë¥¼ ì¸ìŠ¤í„´ìŠ¤í•  수 없습니다."
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "This operation requires a single selected node."
msgstr "ì´ ìž‘ì—…ì€ í•˜ë‚˜ì˜ ì„ íƒëœ 노드를 필요로 합니다."
@@ -4004,45 +3495,6 @@ msgstr ""
"드래그 & ë“œëž + 쉬프트 : 형제 노드로 추가\n"
"드래그 & ë“œëž + 알트 : 노드 타입 변경"
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Create Poly"
-msgstr "í´ë¦¬ê³¤ ìƒì„±"
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly"
-msgstr "í´ë¦¬ê³¤ 편집"
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly (Remove Point)"
-msgstr "í´ë¦¬ê³¤ 편집 (ì  ì‚­ì œ)"
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Create a new polygon from scratch."
-msgstr "처ìŒë¶€í„° 새로운 í´ë¦¬ê³¤ 만들기."
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-msgid ""
-"Edit existing polygon:\n"
-"LMB: Move Point.\n"
-"Ctrl+LMB: Split Segment.\n"
-"RMB: Erase Point."
-msgstr ""
-
#: editor/plugins/collision_polygon_editor_plugin.cpp
msgid "Create Poly3D"
msgstr "í´ë¦¬ê³¤3D 만들기"
@@ -4052,14 +3504,6 @@ msgid "Set Handle"
msgstr "핸들 설정"
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Creating Mesh Library"
-msgstr "메쉬 ë¼ì´ë¸ŒëŸ¬ë¦¬ ìƒì„± 중"
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Thumbnail.."
-msgstr "ì¸ë„¤ì¼.."
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Remove item %d?"
msgstr "%d í•­ëª©ì„ ì‚­ì œí•˜ì‹œê² ìŠµë‹ˆê¹Œ?"
@@ -4082,49 +3526,60 @@ msgid "Update from Scene"
msgstr "씬으로부터 갱신하기"
#: editor/plugins/curve_editor_plugin.cpp
-#, fuzzy
+msgid "Flat0"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat1"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Ease in"
+msgstr "Ease in"
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Ease out"
+msgstr "Ease out"
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Smoothstep"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
msgid "Modify Curve Point"
-msgstr "커브맵 수정"
+msgstr "커브 í¬ì¸íŠ¸ 수정"
#: editor/plugins/curve_editor_plugin.cpp
-#, fuzzy
msgid "Modify Curve Tangent"
-msgstr "커브맵 수정"
+msgstr "커브 탄젠트 수정"
#: editor/plugins/curve_editor_plugin.cpp
-#, fuzzy
msgid "Load Curve Preset"
-msgstr "리소스 로드"
+msgstr "커브 프리셋 로드"
#: editor/plugins/curve_editor_plugin.cpp
-#, fuzzy
msgid "Add point"
-msgstr "입력 추가"
+msgstr "í¬ì¸íŠ¸ 추가"
#: editor/plugins/curve_editor_plugin.cpp
-#, fuzzy
msgid "Remove point"
-msgstr "경로 í¬ì¸íŠ¸ ì‚­ì œ"
+msgstr "í¬ì¸íŠ¸ 제거"
#: editor/plugins/curve_editor_plugin.cpp
-#, fuzzy
msgid "Left linear"
-msgstr "ì§ì„ í˜•"
+msgstr "왼쪽 선형"
#: editor/plugins/curve_editor_plugin.cpp
-#, fuzzy
msgid "Right linear"
-msgstr "우측 뷰"
+msgstr "오른쪽 선형"
#: editor/plugins/curve_editor_plugin.cpp
-#, fuzzy
msgid "Load preset"
-msgstr "리소스 로드"
+msgstr "프리셋 로드"
#: editor/plugins/curve_editor_plugin.cpp
-#, fuzzy
msgid "Remove Curve Point"
-msgstr "경로 í¬ì¸íŠ¸ ì‚­ì œ"
+msgstr "커프 í¬ì¸íŠ¸ ì‚­ì œ"
#: editor/plugins/curve_editor_plugin.cpp
msgid "Toggle Curve Linear Tangent"
@@ -4166,39 +3621,32 @@ msgid "Create Occluder Polygon"
msgstr "Occluder í´ë¦¬ê³¤ 만들기"
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Edit existing polygon:"
msgstr "기존 í´ë¦¬ê³¤ 편집:"
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "LMB: Move Point."
msgstr "좌í´ë¦­: í¬ì¸íŠ¸ ì´ë™."
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Ctrl+LMB: Split Segment."
msgstr "컨트롤+좌í´ë¦­: 세그먼트 분할."
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "RMB: Erase Point."
msgstr "ìš°í´ë¦­: í¬ì¸íŠ¸ ì‚­ì œ."
#: editor/plugins/line_2d_editor_plugin.cpp
-#, fuzzy
msgid "Remove Point from Line2D"
-msgstr "커브ì—ì„œ í¬ì¸íŠ¸ ì‚­ì œ"
+msgstr "Line2Dì—ì„œ í¬ì¸íŠ¸ ì‚­ì œ"
#: editor/plugins/line_2d_editor_plugin.cpp
-#, fuzzy
msgid "Add Point to Line2D"
-msgstr "ì»¤ë¸Œì— í¬ì¸íŠ¸ 추가"
+msgstr "Line2Dì— í¬ì¸íŠ¸ 추가"
#: editor/plugins/line_2d_editor_plugin.cpp
-#, fuzzy
msgid "Move Point in Line2D"
-msgstr "ì»¤ë¸Œì˜ í¬ì¸íŠ¸ ì´ë™"
+msgstr "Line2Dì˜ í¬ì¸íŠ¸ ì´ë™"
#: editor/plugins/line_2d_editor_plugin.cpp
#: editor/plugins/path_2d_editor_plugin.cpp
@@ -4231,9 +3679,8 @@ msgid "Add Point (in empty space)"
msgstr "í¬ì¸íŠ¸ 추가 (빈 공간)"
#: editor/plugins/line_2d_editor_plugin.cpp
-#, fuzzy
msgid "Split Segment (in line)"
-msgstr "세그먼트 분할 (커브)"
+msgstr "세그먼트 분할 (ë¼ì¸)"
#: editor/plugins/line_2d_editor_plugin.cpp
#: editor/plugins/path_2d_editor_plugin.cpp
@@ -4286,6 +3733,10 @@ msgid "Create Outline"
msgstr "외곽선 만들기"
#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Mesh"
+msgstr "메쉬"
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Create Trimesh Static Body"
msgstr "Trimesh Static Body 만들기"
@@ -4413,23 +3864,83 @@ msgstr "ìž„ì˜ í¬ê¸°:"
msgid "Populate"
msgstr "ìƒì„±"
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake!"
+msgstr "굽기!"
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake the navigation mesh.\n"
+msgstr "네비게ì´ì…˜ 메쉬 만들기.\n"
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Clear the navigation mesh."
+msgstr "네비게ì´ì…˜ 메쉬 지우기."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Setting up Configuration..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Calculating grid size..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating heightfield..."
+msgstr "Heightfield ìƒì„± 중..."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Marking walkable triangles..."
+msgstr "걷기 가능한 트ë¼ì´ì•µê¸€ 표시 중..."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Constructing compact heightfield..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Eroding walkable area..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Partitioning..."
+msgstr "분할중..."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating contours..."
+msgstr "윤곽선 ìƒì„± 중..."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating polymesh..."
+msgstr "í´ë¦¬ 메쉬 ìƒì„± 중..."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Converting to native navigation mesh..."
+msgstr "네ì´í‹°ë¸Œ 네비게ì´ì…˜ 메쉬로 변환 중..."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Navigation Mesh Generator Setup:"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Parsing Geometry..."
+msgstr "지오미트리 ë¶„ì„ ì¤‘..."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Done!"
+msgstr ""
+
#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Create Navigation Polygon"
msgstr "네비게ì´ì…˜ í´ë¦¬ê³¤ 만들기"
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Remove Poly And Point"
-msgstr "í´ë¦¬ê³¤ê³¼ í¬ì¸íŠ¸ ì‚­ì œ"
-
#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Clear Emission Mask"
msgstr "ì—미션 ë§ˆìŠ¤í¬ ì •ë¦¬"
#: editor/plugins/particles_2d_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp
-#, fuzzy
msgid "Generating AABB"
-msgstr "AABB ìƒì„±"
+msgstr "AABB ìƒì„± 중"
#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Can only set point into a ParticlesMaterial process material"
@@ -4457,9 +3968,8 @@ msgstr "ì—미션 ë§ˆìŠ¤í¬ ë¡œë“œ"
#: editor/plugins/particles_2d_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp
-#, fuzzy
msgid "Particles"
-msgstr "버í…스"
+msgstr "파티í´"
#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Generated Point Count:"
@@ -4467,24 +3977,20 @@ msgstr "ìƒì„±ëœ í¬ì¸íŠ¸ 개수:"
#: editor/plugins/particles_2d_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp
-#, fuzzy
msgid "Generation Time (sec):"
-msgstr "í‰ê·  시간 (ì´ˆ)"
+msgstr "ìƒì„± 시간 (ì´ˆ):"
#: editor/plugins/particles_2d_editor_plugin.cpp
-#, fuzzy
msgid "Emission Mask"
-msgstr "ì—미션 ë§ˆìŠ¤í¬ ì„¤ì •"
+msgstr "ì—미션 마스í¬"
#: editor/plugins/particles_2d_editor_plugin.cpp
-#, fuzzy
msgid "Capture from Pixel"
-msgstr "씬으로부터 만들기"
+msgstr "픽셀로부터 캡ì³"
#: editor/plugins/particles_2d_editor_plugin.cpp
-#, fuzzy
msgid "Emission Colors"
-msgstr "ì—미션 위치:"
+msgstr "ì—미션 ì¹¼ë¼"
#: editor/plugins/particles_editor_plugin.cpp
msgid "Node does not contain geometry."
@@ -4511,14 +4017,12 @@ msgid "Generate AABB"
msgstr "AABB ìƒì„±"
#: editor/plugins/particles_editor_plugin.cpp
-#, fuzzy
msgid "Create Emission Points From Mesh"
-msgstr "메쉬로부터 ì—미터 만들기"
+msgstr "메쉬로부터 ì—미션 í¬ì¸íŠ¸ 만들기"
#: editor/plugins/particles_editor_plugin.cpp
-#, fuzzy
msgid "Create Emission Points From Node"
-msgstr "노드로부터 ì—미터 만들기"
+msgstr "노드로부터 ì—미터 í¬ì¸íŠ¸ 만들기"
#: editor/plugins/particles_editor_plugin.cpp
msgid "Clear Emitter"
@@ -4529,14 +4033,12 @@ msgid "Create Emitter"
msgstr "ì—미터 만들기"
#: editor/plugins/particles_editor_plugin.cpp
-#, fuzzy
msgid "Emission Points:"
-msgstr "ì—미션 위치:"
+msgstr "ì—미션 í¬ì¸íŠ¸:"
#: editor/plugins/particles_editor_plugin.cpp
-#, fuzzy
msgid "Surface Points"
-msgstr "서페ì´ìŠ¤ %d"
+msgstr "서페ì´ìŠ¤ í¬ì¸íŠ¸"
#: editor/plugins/particles_editor_plugin.cpp
msgid "Surface Points+Normal (Directed)"
@@ -4547,9 +4049,8 @@ msgid "Volume"
msgstr "배출량"
#: editor/plugins/particles_editor_plugin.cpp
-#, fuzzy
msgid "Emission Source: "
-msgstr "ì—미션 채움:"
+msgstr "ì—미션 소스: "
#: editor/plugins/particles_editor_plugin.cpp
#, fuzzy
@@ -4561,14 +4062,12 @@ msgid "Remove Point from Curve"
msgstr "커브ì—ì„œ í¬ì¸íŠ¸ ì‚­ì œ"
#: editor/plugins/path_2d_editor_plugin.cpp
-#, fuzzy
msgid "Remove Out-Control from Curve"
-msgstr "ì»¤ë¸Œì˜ ì•„ì›ƒ-컨트롤 ì´ë™"
+msgstr "ì»¤ë¸Œì˜ ì•„ì›ƒ-컨트롤 ì‚­ì œ"
#: editor/plugins/path_2d_editor_plugin.cpp
-#, fuzzy
msgid "Remove In-Control from Curve"
-msgstr "커브ì—ì„œ í¬ì¸íŠ¸ ì‚­ì œ"
+msgstr "ì»¤ë¸Œì˜ ì¸-컨트롤 ì‚­ì œ"
#: editor/plugins/path_2d_editor_plugin.cpp
#: editor/plugins/path_editor_plugin.cpp
@@ -4611,11 +4110,11 @@ msgstr "커브 í¬ì¸íŠ¸ 위치 설정"
#: editor/plugins/path_editor_plugin.cpp
msgid "Set Curve In Position"
-msgstr "커브 í¬ì¸íŠ¸ In 설정"
+msgstr "ì»¤ë¸Œì˜ In 위치 설정"
#: editor/plugins/path_editor_plugin.cpp
msgid "Set Curve Out Position"
-msgstr "커브 í¬ì¸íŠ¸ Out 설정"
+msgstr "ì»¤ë¸Œì˜ Out 위치 설정"
#: editor/plugins/path_editor_plugin.cpp
msgid "Split Path"
@@ -4626,14 +4125,12 @@ msgid "Remove Path Point"
msgstr "경로 í¬ì¸íŠ¸ ì‚­ì œ"
#: editor/plugins/path_editor_plugin.cpp
-#, fuzzy
msgid "Remove Out-Control Point"
-msgstr "ì»¤ë¸Œì˜ ì•„ì›ƒ-컨트롤 ì´ë™"
+msgstr "아웃-컨트롤 í¬ì¸íŠ¸ ì‚­ì œ"
#: editor/plugins/path_editor_plugin.cpp
-#, fuzzy
msgid "Remove In-Control Point"
-msgstr "ì»¤ë¸Œì˜ ì¸-컨트롤 ì´ë™"
+msgstr "ì¸-컨트롤 í¬ì¸íŠ¸ ì‚­ì œ"
#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Create UV Map"
@@ -4676,6 +4173,14 @@ msgid "Scale Polygon"
msgstr "í´ë¦¬ê³¤ í¬ê¸° ì¡°ì ˆ"
#: editor/plugins/polygon_2d_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Edit"
+msgstr "편집"
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Polygon->UV"
msgstr "í´ë¦¬ê³¤->UV"
@@ -4730,73 +4235,21 @@ msgstr "리소스 로드"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/shader_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "붙여넣기"
-#: editor/plugins/rich_text_editor_plugin.cpp
-msgid "Parse BBCode"
-msgstr "BBCode ì½ê¸°"
-
-#: editor/plugins/sample_editor_plugin.cpp
-msgid "Length:"
-msgstr "길ì´:"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Open Sample File(s)"
-msgstr "샘플 íŒŒì¼ ì—´ê¸°"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "ERROR: Couldn't load sample!"
-msgstr "ì—러: ìƒ˜í”Œì„ ë¡œë“œí•  수 없습니다!"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Add Sample"
-msgstr "샘플 추가"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Rename Sample"
-msgstr "샘플 ì´ë¦„ 변경"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Delete Sample"
-msgstr "샘플 삭제"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "16 Bits"
-msgstr "16 비트"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "8 Bits"
-msgstr "8 비트"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Stereo"
-msgstr "스테레오"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Mono"
-msgstr "모노"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Format"
-msgstr "í¬ë©§"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Pitch"
-msgstr "피치"
-
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Clear Recent Files"
-msgstr "Bones 없애기"
+msgstr "최근 íŒŒì¼ ì§€ìš°ê¸°"
#: editor/plugins/script_editor_plugin.cpp
msgid ""
"Close and save changes?\n"
"\""
msgstr ""
+"ë³€ê²½ì‚¬í•­ì„ ì €ìž¥í•˜ê³  닫겠습니까?\n"
+"\""
#: editor/plugins/script_editor_plugin.cpp
msgid "Error while saving theme"
@@ -4878,10 +4331,13 @@ msgstr "문서 닫기"
msgid "Close All"
msgstr "ëª¨ë‘ ë‹«ê¸°"
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+msgid "Run"
+msgstr "실행"
+
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Toggle Scripts Panel"
-msgstr "ì¦ê²¨ì°¾ê¸° 토글"
+msgstr "스í¬ë¦½íŠ¸ íŒ¨ë„ í† ê¸€"
#: editor/plugins/script_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
@@ -4907,7 +4363,8 @@ msgstr "프로시저 단위 실행"
msgid "Break"
msgstr "정지"
-#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+#: editor/script_editor_debugger.cpp
msgid "Continue"
msgstr "계ì†"
@@ -4916,26 +4373,12 @@ msgid "Keep Debugger Open"
msgstr "디버거 í•­ìƒ ì—´ì–´ë†“ê¸°"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Debug with external editor"
-msgstr "ì—디터ì—ì„œ 열기"
+msgstr "외부 ì—디터와 디버그"
#: editor/plugins/script_editor_plugin.cpp
-msgid "Window"
-msgstr "윈ë„ìš°"
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Left"
-msgstr "왼쪽으로 ì´ë™"
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Right"
-msgstr "오른쪽으로 ì´ë™"
-
-#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Open Godot online documentation"
-msgstr "ë ˆí¼ëŸ°ìŠ¤ 문서 검색."
+msgstr "Godot 온ë¼ì¸ 문서 열기"
#: editor/plugins/script_editor_plugin.cpp
msgid "Search the class hierarchy."
@@ -4954,9 +4397,8 @@ msgid "Go to next edited document."
msgstr "ë‹¤ìŒ íŽ¸ì§‘ 문서로 ì´ë™."
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Discard"
-msgstr "비연ì†ì ì¸"
+msgstr "저장 안함"
#: editor/plugins/script_editor_plugin.cpp
msgid "Create Script"
@@ -4996,9 +4438,8 @@ msgid "Pick Color"
msgstr "ìƒ‰ìƒ ì„ íƒ"
#: editor/plugins/script_text_editor.cpp
-#, fuzzy
msgid "Convert Case"
-msgstr "ì´ë¯¸ì§€ 변환 중"
+msgstr "ëŒ€ì†Œë¬¸ìž ë³€í™˜"
#: editor/plugins/script_text_editor.cpp
msgid "Uppercase"
@@ -5019,8 +4460,9 @@ msgid "Cut"
msgstr "잘ë¼ë‚´ê¸°"
#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "복사하기"
@@ -5039,9 +4481,8 @@ msgid "Move Down"
msgstr "아래로 ì´ë™"
#: editor/plugins/script_text_editor.cpp
-#, fuzzy
msgid "Delete Line"
-msgstr "í¬ì¸íŠ¸ ì‚­ì œ"
+msgstr "ë¼ì¸ ì‚­ì œ"
#: editor/plugins/script_text_editor.cpp
msgid "Indent Left"
@@ -5097,14 +4538,12 @@ msgid "Goto Previous Breakpoint"
msgstr "ì´ì „ 중단ì ìœ¼ë¡œ ì´ë™"
#: editor/plugins/script_text_editor.cpp
-#, fuzzy
msgid "Convert To Uppercase"
-msgstr "변환.."
+msgstr "대문ìžë¡œ 변환"
#: editor/plugins/script_text_editor.cpp
-#, fuzzy
msgid "Convert To Lowercase"
-msgstr "변환.."
+msgstr "소문ìžë¡œ 변환"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/shader_editor_plugin.cpp
@@ -5286,10 +4725,6 @@ msgid "View Plane Transform."
msgstr "ë·° í‰ë©´ 변형."
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Scaling to %s%%."
-msgstr "%s%%ë¡œ í¬ê¸° 변경."
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rotating %s degrees."
msgstr "%së„ë¡œ 회전."
@@ -5306,10 +4741,6 @@ msgid "Top View."
msgstr "윗면 보기."
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Top"
-msgstr "윗면"
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rear View."
msgstr "뒷면 보기."
@@ -5354,28 +4785,24 @@ msgid "Objects Drawn"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Material Changes"
-msgstr "변경사항만 갱신"
+msgstr "머터리얼 변경"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Shader Changes"
-msgstr "변경사항만 갱신"
+msgstr "ì…°ì´ë” 변경"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Surface Changes"
-msgstr "변경사항만 갱신"
+msgstr "서피스 변경"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Draw Calls"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Vertices"
-msgstr "버í…스"
+msgstr "버틱스"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Align with view"
@@ -5394,19 +4821,16 @@ msgid "Display Overdraw"
msgstr "Overdraw 표시"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Display Unshaded"
-msgstr "Shadeless 표시"
+msgstr "ìŒì˜ ì—†ì´ í‘œì‹œ"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "View Environment"
-msgstr "환경"
+msgstr "환경 보기"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "View Gizmos"
-msgstr "기즈모"
+msgstr "기즈모 보기"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "View Information"
@@ -5417,9 +4841,8 @@ msgid "Audio Listener"
msgstr "오디오 리스너"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Doppler Enable"
-msgstr "활성화"
+msgstr "ë„플러 활성화"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Freelook Left"
@@ -5430,30 +4853,26 @@ msgid "Freelook Right"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Freelook Forward"
-msgstr "앞으로 가기"
+msgstr "ìžìœ ì‹œì  앞으로 ì´ë™"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Freelook Backwards"
-msgstr "뒤로"
+msgstr "ìžìœ ì‹œì  뒤로 ì´ë™"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Freelook Up"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Freelook Down"
-msgstr "휠 아래로."
+msgstr "ìžìœ ì‹œì  아래로 ì´ë™"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Freelook Speed Modifier"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "preview"
msgstr "미리보기"
@@ -5462,17 +4881,18 @@ msgid "XForm Dialog"
msgstr "변환 다ì´ì–¼ë¡œê·¸"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Select Mode (Q)\n"
-msgstr "ì„ íƒ ëª¨ë“œ"
+msgstr "ì„ íƒ ëª¨ë“œ (Q)\n"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid ""
"Drag: Rotate\n"
"Alt+Drag: Move\n"
"Alt+RMB: Depth list selection"
-msgstr "알트+ìš°í´ë¦­: 겹친 오브ì íŠ¸ ì„ íƒ"
+msgstr ""
+"드래그: 회전\n"
+"알트+드래그: ì´ë™\n"
+"알트+ìš°í´ë¦­: 겹친 오브ì íŠ¸ ì„ íƒ"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Move Mode (W)"
@@ -5531,30 +4951,30 @@ msgid "Align Selection With View"
msgstr "ì„ íƒ í•­ëª©ì„ ë·°ì— ì •ë ¬"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Tool Select"
-msgstr "ì„ íƒ"
+msgstr "ì„ íƒ íˆ´"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Tool Move"
-msgstr "ì´ë™"
+msgstr "ì´ë™ 툴"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Tool Rotate"
-msgstr "컨트롤: 회전"
+msgstr "회전 툴"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Tool Scale"
-msgstr "í¬ê¸°:"
+msgstr "í¬ê¸°ì¡°ì ˆ 툴"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Transform"
msgstr "변환"
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Configure Snap.."
+msgstr "스냅 설정.."
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Local Coords"
msgstr "로컬 좌표"
@@ -5700,6 +5120,10 @@ msgid "Speed (FPS):"
msgstr "ì†ë„ (FPS):"
#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Loop"
+msgstr "루프"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Animation Frames"
msgstr "애니메ì´ì…˜ 프레임"
@@ -5712,19 +5136,18 @@ msgid "Insert Empty (After)"
msgstr "빈 프레임 삽입 (ì´í›„)"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Up"
-msgstr "위"
+msgid "Move (Before)"
+msgstr "ì´ë™ (ì´ì „)"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Down"
-msgstr "아래"
+msgid "Move (After)"
+msgstr "ì´ë™ (ì´í›„)"
#: editor/plugins/style_box_editor_plugin.cpp
msgid "StyleBox Preview:"
msgstr "StyleBox 미리보기:"
#: editor/plugins/texture_region_editor_plugin.cpp
-#, fuzzy
msgid "Set Region Rect"
msgstr "구역 설정"
@@ -5786,18 +5209,20 @@ msgid "Remove Item"
msgstr "ì•„ì´í…œ ì‚­ì œ"
#: editor/plugins/theme_editor_plugin.cpp
-#, fuzzy
msgid "Remove All Items"
-msgstr "í´ëž˜ìŠ¤ ì•„ì´í…œ ì‚­ì œ"
+msgstr "모든 ì•„ì´í…œ ì‚­ì œ"
#: editor/plugins/theme_editor_plugin.cpp
-#, fuzzy
msgid "Remove All"
-msgstr "삭제"
+msgstr "ëª¨ë‘ ì‚­ì œ"
#: editor/plugins/theme_editor_plugin.cpp
-msgid "Theme"
-msgstr "테마"
+msgid "Edit theme.."
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Theme editing menu."
+msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
msgid "Add Class Items"
@@ -5881,13 +5306,16 @@ msgid "Style"
msgstr "스타ì¼"
#: editor/plugins/theme_editor_plugin.cpp
+msgid "Font"
+msgstr "í°íŠ¸"
+
+#: editor/plugins/theme_editor_plugin.cpp
msgid "Color"
msgstr "색깔"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Erase Selection"
-msgstr "ì„ íƒë¶€ë¶„ 지우기"
+msgstr "ì„ íƒ ì§€ìš°ê¸°"
#: editor/plugins/tile_map_editor_plugin.cpp
msgid "Paint TileMap"
@@ -5932,8 +5360,9 @@ msgid "Mirror Y"
msgstr "Y축 뒤집기"
#: editor/plugins/tile_map_editor_plugin.cpp
-msgid "Bucket"
-msgstr "채우기"
+#, fuzzy
+msgid "Paint Tile"
+msgstr "타ì¼ë§µ 칠하기"
#: editor/plugins/tile_map_editor_plugin.cpp
msgid "Pick Tile"
@@ -5999,6 +5428,10 @@ msgid "Delete preset '%s'?"
msgstr "ì„ íƒëœ 파ì¼ë“¤ì„ 삭제하시겠습니까?"
#: editor/project_export.cpp
+msgid "Export templates for this platform are missing/corrupted: "
+msgstr ""
+
+#: editor/project_export.cpp
#, fuzzy
msgid "Presets"
msgstr "프리셋.."
@@ -6080,34 +5513,62 @@ msgid "Export templates for this platform are missing:"
msgstr ""
#: editor/project_export.cpp
+msgid "Export templates for this platform are missing/corrupted:"
+msgstr ""
+
+#: editor/project_export.cpp
#, fuzzy
msgid "Export With Debug"
msgstr "íƒ€ì¼ ì…‹ 내보내기"
#: editor/project_manager.cpp
-msgid "Invalid project path, the path must exist!"
-msgstr "프로ì íŠ¸ 경로가 유효하지 않습니다. 경로가 반드시 존재해야 합니다!"
+#, fuzzy
+msgid "The path does not exist."
+msgstr "파ì¼ì´ 존재하지 않습니다."
#: editor/project_manager.cpp
#, fuzzy
-msgid "Invalid project path, project.godot must not exist."
-msgstr "프로ì íŠ¸ 경로가 유효하지 않습니다. engine.cfgê°€ 있으면 안ë©ë‹ˆë‹¤."
+msgid "Please choose a 'project.godot' file."
+msgstr "프로ì íŠ¸ í´ë” ë°”ê¹¥ì— ë‚´ë³´ë‚´ê¸°ë¥¼ 하세요!"
#: editor/project_manager.cpp
-#, fuzzy
-msgid "Invalid project path, project.godot must exist."
-msgstr "프로ì íŠ¸ 경로가 유효하지 않습니다. engine.cfgê°€ 존재해야합니다."
+msgid ""
+"Your project will be created in a non empty folder (you might want to create "
+"a new folder)."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Please choose a folder that does not contain a 'project.godot' file."
+msgstr ""
#: editor/project_manager.cpp
msgid "Imported Project"
msgstr "가져온 프로ì íŠ¸"
#: editor/project_manager.cpp
+msgid " "
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "It would be a good idea to name your project."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Invalid project path (changed anything?)."
msgstr "유효하지 ì•Šì€ í”„ë¡œì íŠ¸ 경로 (뭔가 변경하신 ê±°ë¼ë„?)."
#: editor/project_manager.cpp
#, fuzzy
+msgid "Couldn't get project.godot in project path."
+msgstr "프로ì íŠ¸ ê²½ë¡œì— engine.cfg를 ìƒì„±í•  수 없습니다."
+
+#: editor/project_manager.cpp
+#, fuzzy
+msgid "Couldn't edit project.godot in project path."
+msgstr "프로ì íŠ¸ ê²½ë¡œì— engine.cfg를 ìƒì„±í•  수 없습니다."
+
+#: editor/project_manager.cpp
+#, fuzzy
msgid "Couldn't create project.godot in project path."
msgstr "프로ì íŠ¸ ê²½ë¡œì— engine.cfg를 ìƒì„±í•  수 없습니다."
@@ -6116,38 +5577,49 @@ msgid "The following files failed extraction from package:"
msgstr "다ìŒì˜ 파ì¼ë“¤ì„ 패키지로부터 ì¶”ì¶œí•˜ëŠ”ë° ì‹¤íŒ¨í–ˆìŠµë‹ˆë‹¤:"
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Rename Project"
+msgstr "ì´ë¦„없는 프로ì íŠ¸"
+
+#: editor/project_manager.cpp
+#, fuzzy
+msgid "Couldn't get project.godot in the project path."
+msgstr "프로ì íŠ¸ ê²½ë¡œì— engine.cfg를 ìƒì„±í•  수 없습니다."
+
+#: editor/project_manager.cpp
+msgid "New Game Project"
+msgstr "새 게임 프로ì íŠ¸"
+
+#: editor/project_manager.cpp
msgid "Import Existing Project"
msgstr "기존 프로ì íŠ¸ 가져오기"
#: editor/project_manager.cpp
-msgid "Project Path (Must Exist):"
-msgstr "프로ì íŠ¸ 경로 (반드시 í•„ìš”):"
+msgid "Create New Project"
+msgstr "새 프로ì íŠ¸ 만들기"
+
+#: editor/project_manager.cpp
+msgid "Install Project:"
+msgstr "프로ì íŠ¸ 설치:"
#: editor/project_manager.cpp
msgid "Project Name:"
msgstr "프로ì íŠ¸ 명:"
#: editor/project_manager.cpp
-msgid "Create New Project"
-msgstr "새 프로ì íŠ¸ 만들기"
+#, fuzzy
+msgid "Create folder"
+msgstr "í´ë” ìƒì„±"
#: editor/project_manager.cpp
msgid "Project Path:"
msgstr "프로ì íŠ¸ 경로:"
#: editor/project_manager.cpp
-msgid "Install Project:"
-msgstr "프로ì íŠ¸ 설치:"
-
-#: editor/project_manager.cpp
msgid "Browse"
msgstr "찾아보기"
#: editor/project_manager.cpp
-msgid "New Game Project"
-msgstr "새 게임 프로ì íŠ¸"
-
-#: editor/project_manager.cpp
msgid "That's a BINGO!"
msgstr "빙고!"
@@ -6156,6 +5628,11 @@ msgid "Unnamed Project"
msgstr "ì´ë¦„없는 프로ì íŠ¸"
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Can't open project"
+msgstr "연결하기.."
+
+#: editor/project_manager.cpp
msgid "Are you sure to open more than one project?"
msgstr "ë‘ê°œ ì´ìƒì˜ 프로ì íŠ¸ë¥¼ 열려는 ê²ƒì´ í™•ì‹¤í•©ë‹ˆê¹Œ?"
@@ -6186,6 +5663,12 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
+"Language changed.\n"
+"The UI will update next time the editor or project manager starts."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid ""
"You are about the scan %s folders for existing Godot projects. Do you "
"confirm?"
msgstr "%s ì—ì„œ 기존 Godot 프로ì íŠ¸ë“¤ì„ 스캔하려고 합니다. 진행하시겠습니까?"
@@ -6195,10 +5678,6 @@ msgid "Project List"
msgstr "프로ì íŠ¸ 목ë¡"
#: editor/project_manager.cpp
-msgid "Run"
-msgstr "실행"
-
-#: editor/project_manager.cpp
msgid "Scan"
msgstr "스캔"
@@ -6221,6 +5700,11 @@ msgstr "종료"
#: editor/project_manager.cpp
#, fuzzy
+msgid "Restart Now"
+msgstr "재시작 (초):"
+
+#: editor/project_manager.cpp
+#, fuzzy
msgid "Can't run project"
msgstr "연결하기.."
@@ -6257,17 +5741,14 @@ msgid "Add Input Action Event"
msgstr "ìž…ë ¥ ì•¡ì…˜ ì´ë²¤íŠ¸ 추가"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Meta+"
msgstr "메타+"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Shift+"
msgstr "쉬프트+"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Alt+"
msgstr "알트+"
@@ -6329,7 +5810,7 @@ msgstr "변경"
msgid "Joypad Axis Index:"
msgstr "ì¡°ì´ìŠ¤í‹± 축 ì¸ë±ìŠ¤:"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Axis"
msgstr "축"
@@ -6351,31 +5832,31 @@ msgstr "ìž…ë ¥ ì•¡ì…˜ ì´ë²¤íŠ¸ ì‚­ì œ"
msgid "Add Event"
msgstr "빈 프레임 추가"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Device"
msgstr "기기"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Button"
msgstr "버튼"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Left Button."
msgstr "왼쪽 버튼."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Right Button."
msgstr "오른쪽 버튼."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Middle Button."
msgstr "ê°€ìš´ë° ë²„íŠ¼."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Up."
msgstr "휠 위로."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Down."
msgstr "휠 아래로."
@@ -6384,7 +5865,7 @@ msgid "Add Global Property"
msgstr ""
#: editor/project_settings_editor.cpp
-msgid "Select an setting item first!"
+msgid "Select a setting item first!"
msgstr ""
#: editor/project_settings_editor.cpp
@@ -6403,6 +5884,16 @@ msgid "Delete Item"
msgstr "입력 삭제"
#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Can't contain '/' or ':'"
+msgstr "í˜¸ìŠ¤íŠ¸ì— ì—°ê²°í•  수 ì—†ìŒ:"
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Already existing"
+msgstr "ì§€ì† ì „í™˜"
+
+#: editor/project_settings_editor.cpp
msgid "Error saving settings."
msgstr "설정 저장 중 ì—러."
@@ -6444,6 +5935,15 @@ msgstr "리소스 리맵핑 옵션 제거"
#: editor/project_settings_editor.cpp
#, fuzzy
+msgid "Changed Locale Filter"
+msgstr "연결 시간 변경"
+
+#: editor/project_settings_editor.cpp
+msgid "Changed Locale Filter Mode"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
msgid "Project Settings (project.godot)"
msgstr "프로ì íŠ¸ 설정 (engine.cfg)"
@@ -6504,6 +6004,30 @@ msgid "Locale"
msgstr "지역"
#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Locales Filter"
+msgstr "ì´ë¯¸ì§€ í•„í„°:"
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Show all locales"
+msgstr "뼈대 보기"
+
+#: editor/project_settings_editor.cpp
+msgid "Show only selected locales"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Filter mode:"
+msgstr "í•„í„°"
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Locales:"
+msgstr "지역"
+
+#: editor/project_settings_editor.cpp
msgid "AutoLoad"
msgstr "ìžë™ 로드"
@@ -6555,10 +6079,20 @@ msgstr "새 스í¬ë¦½íŠ¸"
#: editor/property_editor.cpp
#, fuzzy
+msgid "Make Unique"
+msgstr "Bones 만들기"
+
+#: editor/property_editor.cpp
+#, fuzzy
msgid "Show in File System"
msgstr "íŒŒì¼ ì‹œìŠ¤í…œ"
#: editor/property_editor.cpp
+#, fuzzy
+msgid "Convert To %s"
+msgstr "변환.."
+
+#: editor/property_editor.cpp
msgid "Error loading file: Not a resource!"
msgstr "íŒŒì¼ ë¡œë“œ ì—러: 리소스가 아닙니다!"
@@ -6597,6 +6131,11 @@ msgid "Select Property"
msgstr "ì†ì„± ì„ íƒ"
#: editor/property_selector.cpp
+#, fuzzy
+msgid "Select Virtual Method"
+msgstr "메소드 ì„ íƒ"
+
+#: editor/property_selector.cpp
msgid "Select Method"
msgstr "메소드 ì„ íƒ"
@@ -6624,26 +6163,6 @@ msgstr "현재 모양새 유지"
msgid "Reparent"
msgstr "부모노드 재지정"
-#: editor/resources_dock.cpp
-msgid "Create New Resource"
-msgstr "새 리소스 만들기"
-
-#: editor/resources_dock.cpp
-msgid "Open Resource"
-msgstr "리소스 열기"
-
-#: editor/resources_dock.cpp
-msgid "Save Resource"
-msgstr "리로스 저장"
-
-#: editor/resources_dock.cpp
-msgid "Resource Tools"
-msgstr "리소스 ë„구"
-
-#: editor/resources_dock.cpp
-msgid "Make Local"
-msgstr "로컬로 만들기"
-
#: editor/run_settings_dialog.cpp
msgid "Run Mode:"
msgstr "실행 모드:"
@@ -6772,14 +6291,6 @@ msgid "Sub-Resources:"
msgstr "리소스:"
#: editor/scene_tree_dock.cpp
-msgid "Edit Groups"
-msgstr "그룹 편집"
-
-#: editor/scene_tree_dock.cpp
-msgid "Edit Connections"
-msgstr "연결 편집"
-
-#: editor/scene_tree_dock.cpp
msgid "Clear Inheritance"
msgstr "ìƒì† 없애기"
@@ -6967,6 +6478,15 @@ msgid "Invalid base path"
msgstr "기본 경로가 유요하지 ì•ŠìŒ"
#: editor/script_create_dialog.cpp
+msgid "Directory of the same name exists"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
+#, fuzzy
+msgid "File exists, will be reused"
+msgstr "파ì¼ì´ 존재합니다. ë®ì–´ì“°ì‹œê² ìŠµë‹ˆê¹Œ?"
+
+#: editor/script_create_dialog.cpp
msgid "Invalid extension"
msgstr "확장ìžê°€ 유요하지 ì•ŠìŒ"
@@ -7012,6 +6532,10 @@ msgid "Load existing script file"
msgstr "기존 스í¬ë¦½íŠ¸ 로드하기"
#: editor/script_create_dialog.cpp
+msgid "Language"
+msgstr "언어"
+
+#: editor/script_create_dialog.cpp
#, fuzzy
msgid "Inherits"
msgstr "ìƒì†:"
@@ -7056,6 +6580,10 @@ msgid "Function:"
msgstr "함수:"
#: editor/script_editor_debugger.cpp
+msgid "Pick one or more items from the list to display the graph."
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
msgid "Errors"
msgstr "ì—러"
@@ -7136,6 +6664,10 @@ msgid "Type"
msgstr "타입"
#: editor/script_editor_debugger.cpp
+msgid "Format"
+msgstr "í¬ë©§"
+
+#: editor/script_editor_debugger.cpp
msgid "Usage"
msgstr "사용"
@@ -7211,13 +6743,31 @@ msgstr ""
msgid "Change Probe Extents"
msgstr "프로브 범위 변경"
+#: modules/gdnative/gd_native_library_editor.cpp
+#, fuzzy
+msgid "Library"
+msgstr "메쉬 ë¼ì´ë¸ŒëŸ¬ë¦¬.."
+
+#: modules/gdnative/gd_native_library_editor.cpp
+#, fuzzy
+msgid "Status"
+msgstr "ìƒíƒœ:"
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Libraries: "
+msgstr ""
+
+#: modules/gdnative/register_types.cpp
+msgid "GDNative"
+msgstr ""
+
#: modules/gdscript/gd_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Invalid type argument to convert(), use TYPE_* constants."
msgstr ""
"convert()하기 위한 ì¸ìž íƒ€ìž…ì´ ìœ íš¨í•˜ì§€ 않습니다, TYPE_* ìƒìˆ˜ë¥¼ 사용하세요."
-#: modules/gdscript/gd_functions.cpp
+#: modules/gdscript/gd_functions.cpp modules/mono/glue/glue_header.h
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Not enough bytes for decoding bytes, or invalid format."
msgstr "디코딩할 ë°”ì´íŠ¸ê°€ 모ìžë¼ê±°ë‚˜, 유효하지 ì•Šì€ í˜•ì‹ìž…니다."
@@ -7271,10 +6821,6 @@ msgid "GridMap Duplicate Selection"
msgstr "ì„ íƒí‚¤ 복제"
#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "GridMap Paint"
-msgstr ""
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
#, fuzzy
msgid "Snap View"
msgstr "ìƒë‹¨ ë·°"
@@ -7378,13 +6924,8 @@ msgstr "스냅 설정"
msgid "Pick Distance:"
msgstr "ì¸ìŠ¤í„´ìŠ¤:"
-#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
-msgid "Tiles"
-msgstr "파ì¼"
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "Areas"
+#: modules/mono/editor/mono_bottom_panel.cpp
+msgid "Builds"
msgstr ""
#: modules/visual_script/visual_script.cpp
@@ -7585,10 +7126,18 @@ msgid "Return"
msgstr "리턴"
#: modules/visual_script/visual_script_editor.cpp
+msgid "Call"
+msgstr "호출"
+
+#: modules/visual_script/visual_script_editor.cpp
msgid "Get"
msgstr "얻기"
#: modules/visual_script/visual_script_editor.cpp
+msgid "Script already has function '%s'"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
#, fuzzy
msgid "Change Input Value"
msgstr "ìž…ë ¥ ì´ë¦„ 변경"
@@ -7990,6 +7539,12 @@ msgstr ""
"AnimatedSprite3Dê°€ í”„ë ˆìž„ì„ ë³´ì—¬ì£¼ê¸° 위해서는 'Frames' ì†ì„±ì— SpriteFrames 리"
"소스 만들거나 지정해야 합니다."
+#: scene/3d/vehicle_body.cpp
+msgid ""
+"VehicleWheel serves to provide a wheel system to a VehicleBody. Please use "
+"it as a child of a VehicleBody."
+msgstr ""
+
#: scene/gui/color_picker.cpp
#, fuzzy
msgid "Raw Mode"
@@ -8000,6 +7555,10 @@ msgid "Add current color as a preset"
msgstr ""
#: scene/gui/dialogs.cpp
+msgid "Cancel"
+msgstr "취소"
+
+#: scene/gui/dialogs.cpp
msgid "Alert!"
msgstr "경고!"
@@ -8007,10 +7566,6 @@ msgstr "경고!"
msgid "Please Confirm..."
msgstr "확ì¸í•´ì£¼ì„¸ìš”..."
-#: scene/gui/input_action.cpp
-msgid "Ctrl+"
-msgstr "컨트롤+"
-
#: scene/gui/popup.cpp
msgid ""
"Popups will hide by default unless you call popup() or any of the popup*() "
@@ -8045,6 +7600,620 @@ msgstr ""
"합니다. 그렇지 ì•Šì„ ê²½ìš°, í™”ë©´ì— í‘œì‹œí•˜ê¸° 위해서는 Render target으로 설정하"
"ê³  내부ì ì¸ í…스ì³ë¥¼ 다른 ë…¸ë“œì— í• ë‹¹í•´ì•¼ 합니다."
+#: scene/resources/dynamic_font.cpp
+msgid "Error initializing FreeType."
+msgstr "FreeType 초기화 ì—러."
+
+#: scene/resources/dynamic_font.cpp
+msgid "Unknown font format."
+msgstr "ì•Œ 수 없는 í°íŠ¸ í¬ë©§."
+
+#: scene/resources/dynamic_font.cpp
+msgid "Error loading font."
+msgstr "í°íŠ¸ 로딩 ì—러."
+
+#: scene/resources/dynamic_font.cpp
+msgid "Invalid font size."
+msgstr "유요하지 ì•Šì€ í°íŠ¸ 사ì´ì¦ˆ."
+
+#~ msgid "Filter:"
+#~ msgstr "í•„í„°:"
+
+#~ msgid "Theme"
+#~ msgstr "테마"
+
+#~ msgid "Method List For '%s':"
+#~ msgstr "'%s' 함수 목ë¡:"
+
+#~ msgid "Arguments:"
+#~ msgstr "ì¸ìˆ˜:"
+
+#~ msgid "Return:"
+#~ msgstr "리턴:"
+
+#~ msgid "Added:"
+#~ msgstr "추가ë¨:"
+
+#~ msgid "Removed:"
+#~ msgstr "제거ë¨:"
+
+#~ msgid "Error saving atlas:"
+#~ msgstr "ì•„í‹€ë¼ìŠ¤ 저장 중 ì—러:"
+
+#~ msgid "Could not save atlas subtexture:"
+#~ msgstr "ì•„í‹€ë¼ìŠ¤ 서브 í…스ì³ë¥¼ 저장할 수 없습니다:"
+
+#~ msgid "Exporting for %s"
+#~ msgstr "%s 내보내기"
+
+#~ msgid "Setting Up.."
+#~ msgstr "설정 중.."
+
+#~ msgid "Error loading scene."
+#~ msgstr "씬 로딩 중 ì—러."
+
+#~ msgid "Re-Import"
+#~ msgstr "다시 가져오기"
+
+#~ msgid "Please wait for scan to complete."
+#~ msgstr "ìŠ¤ìº”ì´ ì™„ë£Œë  ë•Œê¹Œì§€ 기다려주세요."
+
+#~ msgid "Current scene must be saved to re-import."
+#~ msgstr "다시 가져오기 위해서는 현재 ì”¬ì„ ì €ìž¥í•´ì•¼ 합니다."
+
+#~ msgid "Save & Re-Import"
+#~ msgstr "저장 ë° ë‹¤ì‹œ 가져오기"
+
+#~ msgid "Re-Importing"
+#~ msgstr "다시 가져오기"
+
+#~ msgid "Re-Import Changed Resources"
+#~ msgstr "ë³€ê²½ëœ ë¦¬ì†ŒìŠ¤ 다시 가져오기"
+
+#~ msgid "Loading Export Templates"
+#~ msgstr "내보내기 템플릿 로딩 중"
+
+#~ msgid ""
+#~ "\n"
+#~ "Status: Needs Re-Import"
+#~ msgstr ""
+#~ "\n"
+#~ "ìƒíƒœ: 다시 ìž„í¬íŠ¸ í•„ìš”"
+
+#~ msgid "Same source and destination files, doing nothing."
+#~ msgstr "소스와 ëŒ€ìƒ íŒŒì¼ì´ ë™ì¼í•˜ì—¬, 무시ë©ë‹ˆë‹¤."
+
+#~ msgid "Same source and destination paths, doing nothing."
+#~ msgstr "소스와 ëŒ€ìƒ ê²½ë¡œê°€ ë™ì¼í•˜ì—¬, 무시ë©ë‹ˆë‹¤."
+
+#~ msgid "Can't move directories to within themselves."
+#~ msgstr "디렉토리를 ìžì‹ ìœ¼ë¡œ ì´ë™í•  수 없습니다."
+
+#~ msgid "Error moving file:\n"
+#~ msgstr "íŒŒì¼ ì´ë™ ì—러:\n"
+
+#~ msgid "Pick New Name and Location For:"
+#~ msgstr "새로운 ì´ë¦„ê³¼ 위치를 고르세요:"
+
+#~ msgid "No files selected!"
+#~ msgstr "파ì¼ì´ ì„ íƒë˜ì§€ 않았습니다!"
+
+#~ msgid "Info"
+#~ msgstr "ì •ë³´"
+
+#~ msgid "Re-Import.."
+#~ msgstr "다시 가져오기.."
+
+#~ msgid "No bit masks to import!"
+#~ msgstr "가져올 비트 마스í¬ê°€ 없습니다!"
+
+#~ msgid "Target path is empty."
+#~ msgstr "ëŒ€ìƒ ê²½ë¡œê°€ 없습니다."
+
+#~ msgid "Target path must be a complete resource path."
+#~ msgstr "ëŒ€ìƒ ê²½ë¡œëŠ” 완전한 리소스 경로여야 합니다."
+
+#~ msgid "Target path must exist."
+#~ msgstr "ëŒ€ìƒ ê²½ë¡œê°€ 존재해야 합니다."
+
+#~ msgid "Save path is empty!"
+#~ msgstr "저장 경로가 없습니다!"
+
+#~ msgid "Import BitMasks"
+#~ msgstr "ë¹„íŠ¸ë§ˆìŠ¤í¬ ê°€ì ¸ì˜¤ê¸°"
+
+#~ msgid "Source Texture(s):"
+#~ msgstr "소스 í…스ì³:"
+
+#~ msgid "Target Path:"
+#~ msgstr "ëŒ€ìƒ ê²½ë¡œ:"
+
+#~ msgid "Accept"
+#~ msgstr "수ë½"
+
+#~ msgid "Bit Mask"
+#~ msgstr "비트 마스í¬"
+
+#~ msgid "No source font file!"
+#~ msgstr "소스 í°íŠ¸ 파ì¼ì´ 없습니다!"
+
+#~ msgid "No target font resource!"
+#~ msgstr "í°íŠ¸ 리소스 경로가 없습니다!"
+
+#~ msgid ""
+#~ "Invalid file extension.\n"
+#~ "Please use .font."
+#~ msgstr ""
+#~ "유효하지 ì•Šì€ íŒŒì¼ í™•ìž¥ìž.\n"
+#~ ".font 를 사용하세요."
+
+#~ msgid "Couldn't save font."
+#~ msgstr "í°íŠ¸ë¥¼ 저장할 수 없습니다."
+
+#~ msgid "Source Font:"
+#~ msgstr "소스 í°íŠ¸:"
+
+#~ msgid "Source Font Size:"
+#~ msgstr "소스 í°íŠ¸ í¬ê¸°:"
+
+#~ msgid "Dest Resource:"
+#~ msgstr "리소스 경로:"
+
+#~ msgid "The quick brown fox jumps over the lazy dog."
+#~ msgstr ""
+#~ "The quick brown fox jumps over the lazy dog.\n"
+#~ "ë‹¤ëžŒì¥ í—Œ ì³‡ë°”í€´ì— íƒ€ê³ íŒŒ."
+
+#~ msgid "Test:"
+#~ msgstr "테스트:"
+
+#~ msgid "Options:"
+#~ msgstr "옵션:"
+
+#~ msgid "Font Import"
+#~ msgstr "í°íŠ¸ 가져오기"
+
+#~ msgid ""
+#~ "This file is already a Godot font file, please supply a BMFont type file "
+#~ "instead."
+#~ msgstr "ì´ íŒŒì¼ì€ ì´ë¯¸ Godot í°íŠ¸ 파ì¼ìž…니다. BMFont 파ì¼ì„ ì„ íƒí•˜ì„¸ìš”."
+
+#~ msgid "Failed opening as BMFont file."
+#~ msgstr "BMFont 파ì¼ì„ ì—¬ëŠ”ë° ì‹¤íŒ¨í–ˆìŠµë‹ˆë‹¤."
+
+#~ msgid "Invalid font custom source."
+#~ msgstr "ì‚¬ìš©ìž ì§€ì • í°íŠ¸ 소스가 유효하지 않습니다."
+
+#~ msgid "No meshes to import!"
+#~ msgstr "가져올 메쉬가 없습니다!"
+
+#~ msgid "Single Mesh Import"
+#~ msgstr "ë‹¨ì¼ ë©”ì‰¬ 가져오기"
+
+#~ msgid "Source Mesh(es):"
+#~ msgstr "소스 메쉬:"
+
+#~ msgid "Surface %d"
+#~ msgstr "서페ì´ìŠ¤ %d"
+
+#~ msgid "No samples to import!"
+#~ msgstr "가져올 ìƒ˜í”Œì´ ì—†ìŠµë‹ˆë‹¤!"
+
+#~ msgid "Import Audio Samples"
+#~ msgstr "오디오 샘플 가져오기"
+
+#~ msgid "Source Sample(s):"
+#~ msgstr "소스 샘플:"
+
+#~ msgid "Audio Sample"
+#~ msgstr "오디오 샘플"
+
+#~ msgid "New Clip"
+#~ msgstr "새 í´ë¦½"
+
+#~ msgid "Flags"
+#~ msgstr "플래그"
+
+#~ msgid "Bake FPS:"
+#~ msgstr "FPS 설정:"
+
+#~ msgid "Optimizer"
+#~ msgstr "최ì í™”"
+
+#~ msgid "Max Linear Error"
+#~ msgstr "최대 선형 오류"
+
+#~ msgid "Max Angular Error"
+#~ msgstr "최대 ê°ë„ 오류"
+
+#~ msgid "Max Angle"
+#~ msgstr "최대 ê°ë„"
+
+#~ msgid "Clips"
+#~ msgstr "í´ë¦½"
+
+#~ msgid "Start(s)"
+#~ msgstr "시작(초)"
+
+#~ msgid "End(s)"
+#~ msgstr "ë(ì´ˆ)"
+
+#~ msgid "Filters"
+#~ msgstr "í•„í„°"
+
+#~ msgid "Source path is empty."
+#~ msgstr "소스 경로가 비어있습니다."
+
+#~ msgid "Couldn't load post-import script."
+#~ msgstr "가져오기 후 실행할 스í¬ë¦½íŠ¸ë¥¼ 로드할 수 없습니다."
+
+#~ msgid "Invalid/broken script for post-import."
+#~ msgstr "가져오기 후 실행할 스í¬ë¦½íŠ¸ê°€ 유효하지 않거나 깨져있습니다."
+
+#~ msgid "Error importing scene."
+#~ msgstr "씬 가져오기 ì—러."
+
+#~ msgid "Import 3D Scene"
+#~ msgstr "3D 씬 가져오기"
+
+#~ msgid "Source Scene:"
+#~ msgstr "소스 씬:"
+
+#~ msgid "Same as Target Scene"
+#~ msgstr "ëŒ€ìƒ ì”¬ê³¼ ê°™ìŒ"
+
+#~ msgid "Shared"
+#~ msgstr "공유ë¨"
+
+#~ msgid "Target Texture Folder:"
+#~ msgstr "ëŒ€ìƒ í…ìŠ¤ì³ í´ë”:"
+
+#~ msgid "Post-Process Script:"
+#~ msgstr "가져오기 후 수행할 스í¬ë¦½íŠ¸:"
+
+#~ msgid "Custom Root Node Type:"
+#~ msgstr "ì‚¬ìš©ìž ì •ì˜ ë£¨íŠ¸ 노드 타입:"
+
+#~ msgid "Auto"
+#~ msgstr "ìžë™"
+
+#~ msgid "Root Node Name:"
+#~ msgstr "루트 노드 ì´ë¦„:"
+
+#~ msgid "The Following Files are Missing:"
+#~ msgstr "다ìŒì˜ 파ì¼ë“¤ì´ 빠져있습니다:"
+
+#~ msgid "Import Anyway"
+#~ msgstr "무시하고 가져오기"
+
+#~ msgid "Import & Open"
+#~ msgstr "가져오기 후 열기"
+
+#~ msgid "Edited scene has not been saved, open imported scene anyway?"
+#~ msgstr "íŽ¸ì§‘ëœ ì”¬ì´ ì €ìž¥ë˜ì§€ 않았습니다. 무시하고 가져온 ì”¬ì„ ì—¬ì‹œê² ìŠµë‹ˆê¹Œ?"
+
+#~ msgid "Import Image:"
+#~ msgstr "ì´ë¯¸ì§€ 가져오기:"
+
+#~ msgid "Couldn't localize path: %s (already local)"
+#~ msgstr "경로를 로컬 경로로 바꿀 수 없습니다: %s (ì´ë¯¸ 로컬 경로)"
+
+#~ msgid "3D Scene Animation"
+#~ msgstr "3D 씬 애니메ì´ì…˜"
+
+#~ msgid "Uncompressed"
+#~ msgstr "무압축"
+
+#~ msgid "Compress Lossless (PNG)"
+#~ msgstr "무ì†ì‹¤ 압축 (PNG)"
+
+#~ msgid "Compress Lossy (WebP)"
+#~ msgstr "ì†ì‹¤ 압축 (PNG)"
+
+#~ msgid "Compress (VRAM)"
+#~ msgstr "압축 (VRAM)"
+
+#~ msgid "Texture Format"
+#~ msgstr "í…ìŠ¤ì³ í¬ë©§"
+
+#~ msgid "Texture Compression Quality (WebP):"
+#~ msgstr "í…ìŠ¤ì³ ì••ì¶• 품질 (WebP):"
+
+#~ msgid "Texture Options"
+#~ msgstr "í…ìŠ¤ì³ ì˜µì…˜"
+
+#~ msgid "Please specify some files!"
+#~ msgstr "파ì¼ì„ 지정하세요!"
+
+#~ msgid "At least one file needed for Atlas."
+#~ msgstr "ì•„í‹€ë¼ìŠ¤ ìƒì„±ì„ 위해서는 최소 1ê°œ ì´ìƒì˜ 파ì¼ì´ 필요합니다."
+
+#~ msgid "Error importing:"
+#~ msgstr "가져오기 ì—러:"
+
+#~ msgid "Only one file is required for large texture."
+#~ msgstr "í° í…스ì³ë¥¼ 위해서는 단 í•˜ë‚˜ì˜ íŒŒì¼ë§Œ 요구ë©ë‹ˆë‹¤."
+
+#~ msgid "Max Texture Size:"
+#~ msgstr "최대 í…ìŠ¤ì³ ì‚¬ì´ì¦ˆ:"
+
+#~ msgid "Import Textures for Atlas (2D)"
+#~ msgstr "ì•„í‹€ë¼ìŠ¤ë¥¼ 위한 í…ìŠ¤ì³ ê°€ì ¸ì˜¤ê¸° (2D)"
+
+#~ msgid "Cell Size:"
+#~ msgstr "쎌 사ì´ì¦ˆ:"
+
+#~ msgid "Large Texture"
+#~ msgstr "í° í…스ì³"
+
+#~ msgid "Import Large Textures (2D)"
+#~ msgstr "í° í…ìŠ¤ì³ ê°€ì ¸ì˜¤ê¸° (2D)"
+
+#~ msgid "Source Texture"
+#~ msgstr "소스 í…스ì³"
+
+#~ msgid "Base Atlas Texture"
+#~ msgstr "기본 ì•„í‹€ë¼ìŠ¤ í…스ì³"
+
+#~ msgid "Source Texture(s)"
+#~ msgstr "소트 í…스ì³"
+
+#~ msgid "Import Textures for 2D"
+#~ msgstr "2D í…ìŠ¤ì³ ê°€ì ¸ì˜¤ê¸°"
+
+#~ msgid "Import Textures for 3D"
+#~ msgstr "3D í…ìŠ¤ì³ ê°€ì ¸ì˜¤ê¸°"
+
+#~ msgid "Import Textures"
+#~ msgstr "í…ìŠ¤ì³ ê°€ì ¸ì˜¤ê¸°"
+
+#~ msgid "2D Texture"
+#~ msgstr "2D í…스ì³"
+
+#~ msgid "3D Texture"
+#~ msgstr "3D í…스ì³"
+
+#~ msgid "Atlas Texture"
+#~ msgstr "í…ìŠ¤ì³ ì•„í‹€ë¼ìŠ¤"
+
+#~ msgid ""
+#~ "NOTICE: Importing 2D textures is not mandatory. Just copy png/jpg files "
+#~ "to the project."
+#~ msgstr ""
+#~ "알림: 2D í…ìŠ¤ì³ ê°€ì ¸ì˜¤ê¸°ê°€ 필수는 아닙니다. png/jpg 파ì¼ë“¤ì„ 프로ì íŠ¸ì— ë³µ"
+#~ "사해서 ì‚¬ìš©í•´ë„ ë©ë‹ˆë‹¤."
+
+#~ msgid "Crop empty space."
+#~ msgstr "빈 ì˜ì—­ 잘ë¼ë‚´ê¸°."
+
+#~ msgid "Texture"
+#~ msgstr "í…스ì³"
+
+#~ msgid "Import Large Texture"
+#~ msgstr "í° í…ìŠ¤ì³ ê°€ì ¸ì˜¤ê¸°"
+
+#~ msgid "Load Source Image"
+#~ msgstr "소스 ì´ë¯¸ì§€ 로드"
+
+#~ msgid "Slicing"
+#~ msgstr "ìžë¥´ëŠ” 중"
+
+#~ msgid "Saving"
+#~ msgstr "저장 중"
+
+#~ msgid "Couldn't save large texture:"
+#~ msgstr "í° í…스ì³ë¥¼ 저장할 수 ì—†ìŒ:"
+
+#~ msgid "Build Atlas For:"
+#~ msgstr "ì•„í‹€ë¼ìŠ¤ ìƒì„±:"
+
+#~ msgid "Loading Image:"
+#~ msgstr "ì´ë¯¸ì§€ 로딩:"
+
+#~ msgid "Couldn't load image:"
+#~ msgstr "ì´ë¯¸ì§€ë¥¼ 로드할 수 ì—†ìŒ:"
+
+#~ msgid "Converting Images"
+#~ msgstr "ì´ë¯¸ì§€ 변환 중"
+
+#~ msgid "Cropping Images"
+#~ msgstr "ì´ë¯¸ì§€ ìžë¥´ëŠ” 중"
+
+#~ msgid "Blitting Images"
+#~ msgstr "ì´ë¯¸ì§€ 병합 중"
+
+#~ msgid "Couldn't save atlas image:"
+#~ msgstr "ì•„í‹€ë¼ìŠ¤ ì´ë¯¸ì§€ë¥¼ 저장할 수 ì—†ìŒ:"
+
+#~ msgid "Couldn't save converted texture:"
+#~ msgstr "ë³€í™˜ëœ í…스ì³ë¥¼ 저장할 수 ì—†ìŒ:"
+
+#~ msgid "Invalid source!"
+#~ msgstr "유효하지 ì•Šì€ ì†ŒìŠ¤!"
+
+#~ msgid "Invalid translation source!"
+#~ msgstr "유효하지 ì•Šì€ ë²ˆì—­ 소스!"
+
+#~ msgid "Column"
+#~ msgstr "ì—´"
+
+#~ msgid "No items to import!"
+#~ msgstr "가져올 í•­ëª©ì´ ì—†ìŠµë‹ˆë‹¤!"
+
+#~ msgid "No target path!"
+#~ msgstr "ëŒ€ìƒ ê²½ë¡œê°€ 없습니다!"
+
+#~ msgid "Import Translations"
+#~ msgstr "번역 가져오기"
+
+#~ msgid "Couldn't import!"
+#~ msgstr "가져올 수 없습니다!"
+
+#~ msgid "Import Translation"
+#~ msgstr "번역 가져오기"
+
+#~ msgid "Source CSV:"
+#~ msgstr "소스 CSV:"
+
+#~ msgid "Ignore First Row"
+#~ msgstr "첫째줄 무시"
+
+#~ msgid "Compress"
+#~ msgstr "압축"
+
+#~ msgid "Add to Project (project.godot)"
+#~ msgstr "프로ì íŠ¸ì— 추가 (project.godot)"
+
+#~ msgid "Import Languages:"
+#~ msgstr "언어 가져오기:"
+
+#~ msgid "Translation"
+#~ msgstr "번역"
+
+#~ msgid "Parsing %d Triangles:"
+#~ msgstr "%dê°œ 삼ê°í˜• ë¶„ì„ ì¤‘:"
+
+#~ msgid "Triangle #"
+#~ msgstr "삼ê°í˜• #"
+
+#~ msgid "Light Baker Setup:"
+#~ msgstr "ë¼ì´íŠ¸ ë² ì´ì»¤ 설정:"
+
+#~ msgid "Fixing Lights"
+#~ msgstr "ë¼ì´íŠ¸ 수정 중"
+
+#~ msgid "Making BVH"
+#~ msgstr "BVH 만드는 중"
+
+#~ msgid "Transfer to Lightmaps:"
+#~ msgstr "ë¼ì´íŠ¸ë§µìœ¼ë¡œ 전송:"
+
+#~ msgid "Allocating Texture #"
+#~ msgstr "í…ìŠ¤ì³ í• ë‹¹ 중 #"
+
+#~ msgid "Baking Triangle #"
+#~ msgstr "삼ê°í˜• 굽는 중 #"
+
+#~ msgid "Post-Processing Texture #"
+#~ msgstr "í…ìŠ¤ì³ í›„ì²˜ë¦¬ 중 #"
+
+#~ msgid "Reset the lightmap octree baking process (start over)."
+#~ msgstr "ë¼ì´íŠ¸ë§µ 오í¬íŠ¸ë¦¬ 굽기 프로세스 재설정 (처ìŒë¶€í„° 다시)."
+
+#~ msgid "Zoom (%):"
+#~ msgstr "확대 (%):"
+
+#~ msgid "Skeleton.."
+#~ msgstr "스켈레톤.."
+
+#~ msgid "Zoom Reset"
+#~ msgstr "확대 초기화"
+
+#~ msgid "Zoom Set.."
+#~ msgstr "확대 설정.."
+
+#~ msgid "Set a Value"
+#~ msgstr "값 설정"
+
+#~ msgid "Snap (Pixels):"
+#~ msgstr "스냅 (픽셀):"
+
+#~ msgid "Parse BBCode"
+#~ msgstr "BBCode ì½ê¸°"
+
+#~ msgid "Length:"
+#~ msgstr "길ì´:"
+
+#~ msgid "Open Sample File(s)"
+#~ msgstr "샘플 íŒŒì¼ ì—´ê¸°"
+
+#~ msgid "ERROR: Couldn't load sample!"
+#~ msgstr "ì—러: ìƒ˜í”Œì„ ë¡œë“œí•  수 없습니다!"
+
+#~ msgid "Add Sample"
+#~ msgstr "샘플 추가"
+
+#~ msgid "Rename Sample"
+#~ msgstr "샘플 ì´ë¦„ 변경"
+
+#~ msgid "Delete Sample"
+#~ msgstr "샘플 삭제"
+
+#~ msgid "16 Bits"
+#~ msgstr "16 비트"
+
+#~ msgid "8 Bits"
+#~ msgstr "8 비트"
+
+#~ msgid "Stereo"
+#~ msgstr "스테레오"
+
+#~ msgid "Mono"
+#~ msgstr "모노"
+
+#~ msgid "Pitch"
+#~ msgstr "피치"
+
+#~ msgid "Window"
+#~ msgstr "윈ë„ìš°"
+
+#~ msgid "Move Right"
+#~ msgstr "오른쪽으로 ì´ë™"
+
+#~ msgid "Scaling to %s%%."
+#~ msgstr "%s%%ë¡œ í¬ê¸° 변경."
+
+#~ msgid "Up"
+#~ msgstr "위"
+
+#~ msgid "Down"
+#~ msgstr "아래"
+
+#~ msgid "Bucket"
+#~ msgstr "채우기"
+
+#~ msgid "Invalid project path, the path must exist!"
+#~ msgstr "프로ì íŠ¸ 경로가 유효하지 않습니다. 경로가 반드시 존재해야 합니다!"
+
+#, fuzzy
+#~ msgid "Invalid project path, project.godot must not exist."
+#~ msgstr "프로ì íŠ¸ 경로가 유효하지 않습니다. engine.cfgê°€ 있으면 안ë©ë‹ˆë‹¤."
+
+#, fuzzy
+#~ msgid "Invalid project path, project.godot must exist."
+#~ msgstr "프로ì íŠ¸ 경로가 유효하지 않습니다. engine.cfgê°€ 존재해야합니다."
+
+#~ msgid "Project Path (Must Exist):"
+#~ msgstr "프로ì íŠ¸ 경로 (반드시 í•„ìš”):"
+
+#~ msgid "Create New Resource"
+#~ msgstr "새 리소스 만들기"
+
+#~ msgid "Open Resource"
+#~ msgstr "리소스 열기"
+
+#~ msgid "Save Resource"
+#~ msgstr "리로스 저장"
+
+#~ msgid "Resource Tools"
+#~ msgstr "리소스 ë„구"
+
+#~ msgid "Make Local"
+#~ msgstr "로컬로 만들기"
+
+#~ msgid "Edit Groups"
+#~ msgstr "그룹 편집"
+
+#~ msgid "Edit Connections"
+#~ msgstr "연결 편집"
+
+#, fuzzy
+#~ msgid "Tiles"
+#~ msgstr "파ì¼"
+
+#~ msgid "Ctrl+"
+#~ msgstr "컨트롤+"
+
#~ msgid "Close scene? (Unsaved changes will be lost)"
#~ msgstr "ì”¬ì„ ë‹«ìœ¼ì‹œê² ìŠµë‹ˆê¹Œ? (저장하지 ì•Šì€ ë³€ê²½ì‚¬í•­ì€ ì‚¬ë¼ì§‘니다.)"
@@ -8058,9 +8227,6 @@ msgstr ""
#~ msgid "Close Goto Prev. Scene"
#~ msgstr "ë‹«ê³  ì´ì „ 씬으로 ì´ë™"
-#~ msgid "Expand to Parent"
-#~ msgstr "부모로 확장"
-
#~ msgid "Del"
#~ msgstr "삭제"
@@ -8216,18 +8382,12 @@ msgstr ""
#~ msgid "Save Translatable Strings"
#~ msgstr "번역가능한 문ìžì—´ 저장"
-#~ msgid "Translatable Strings.."
-#~ msgstr "번역 가능한 문ìžì—´.."
-
#~ msgid "Install Export Templates"
#~ msgstr "내보내기 템플릿 설치"
#~ msgid "Edit Script Options"
#~ msgstr "스í¬ë¦½íŠ¸ 옵션 편집"
-#~ msgid "Please export outside the project folder!"
-#~ msgstr "프로ì íŠ¸ í´ë” ë°”ê¹¥ì— ë‚´ë³´ë‚´ê¸°ë¥¼ 하세요!"
-
#~ msgid "Error exporting project!"
#~ msgstr "프로ì íŠ¸ 내보내기 중 ì—러!"
@@ -8261,18 +8421,12 @@ msgstr ""
#~ msgid "Include"
#~ msgstr "í¬í•¨"
-#~ msgid "Change Image Group"
-#~ msgstr "ì´ë¯¸ì§€ 그룹 변경"
-
#~ msgid "Group name can't be empty!"
#~ msgstr "그룹 ì´ë¦„ì„ ì§€ì •í•´ì•¼ 합니다!"
#~ msgid "Invalid character in group name!"
#~ msgstr "그룹 ì´ë¦„ì— ìœ íš¨í•˜ì§€ ì•Šì€ ë¬¸ìžê°€ 사용ë˜ì—ˆìŠµë‹ˆë‹¤!"
-#~ msgid "Group name already exists!"
-#~ msgstr "그룹 ì´ë¦„ì´ ì´ë¯¸ 사용중입니다!"
-
#~ msgid "Add Image Group"
#~ msgstr "ì´ë¯¸ì§€ 그룹 추가"
@@ -8351,9 +8505,6 @@ msgstr ""
#~ msgid "Preview Atlas"
#~ msgstr "ì•„í‹€ë¼ìŠ¤ 미리보기"
-#~ msgid "Image Filter:"
-#~ msgstr "ì´ë¯¸ì§€ í•„í„°:"
-
#~ msgid "Images:"
#~ msgstr "ì´ë¯¸ì§€:"
@@ -8420,9 +8571,6 @@ msgstr ""
#~ msgid "Lighting"
#~ msgstr "ë¼ì´íŒ…"
-#~ msgid "Toggle Persisting"
-#~ msgstr "ì§€ì† ì „í™˜"
-
#~ msgid "Global"
#~ msgstr "Global"
diff --git a/editor/translations/lt.po b/editor/translations/lt.po
new file mode 100644
index 0000000000..b85e8e01aa
--- /dev/null
+++ b/editor/translations/lt.po
@@ -0,0 +1,7371 @@
+# Lithuanian translation of the Godot Engine editor
+# Copyright (C) 2007-2017 Juan Linietsky, Ariel Manzur
+# Copyright (C) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)
+# This file is distributed under the same license as the Godot source code.
+#
+# Ignas Kiela <ignaskiela@super.lt>, 2017.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Godot Engine editor\n"
+"PO-Revision-Date: 2017-10-23 18:47+0000\n"
+"Last-Translator: Ignas Kiela <ignaskiela@super.lt>\n"
+"Language-Team: Lithuanian <https://hosted.weblate.org/projects/godot-engine/"
+"godot/lt/>\n"
+"Language: lt\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8-bit\n"
+"Plural-Forms: nplurals=4; plural=n==1 ? 0 : n%10>=2 && (n%100<10 || n"
+"%100>=20) ? 1 : n%10==0 || (n%100>10 && n%100<20) ? 2 : 3;\n"
+"X-Generator: Weblate 2.17\n"
+
+#: editor/animation_editor.cpp
+msgid "Disabled"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "All Selection"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Move Add Key"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Anim Change Transition"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Anim Change Transform"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Anim Change Value"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Anim Change Call"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Anim Add Track"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Anim Duplicate Keys"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Move Anim Track Up"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Move Anim Track Down"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Remove Anim Track"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Set Transitions to:"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Anim Track Rename"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Anim Track Change Interpolation"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Anim Track Change Value Mode"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Anim Track Change Wrap Mode"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Edit Node Curve"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Edit Selection Curve"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Anim Delete Keys"
+msgstr ""
+
+#: editor/animation_editor.cpp editor/plugins/tile_map_editor_plugin.cpp
+msgid "Duplicate Selection"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Duplicate Transposed"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Remove Selection"
+msgstr "Panaikinti pasirinkimÄ…"
+
+#: editor/animation_editor.cpp
+msgid "Continuous"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Discrete"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Trigger"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Anim Add Key"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Anim Move Keys"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Scale Selection"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Scale From Cursor"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Goto Next Step"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Goto Prev Step"
+msgstr ""
+
+#: editor/animation_editor.cpp editor/plugins/curve_editor_plugin.cpp
+#: editor/property_editor.cpp
+msgid "Linear"
+msgstr ""
+
+#: editor/animation_editor.cpp editor/plugins/theme_editor_plugin.cpp
+msgid "Constant"
+msgstr "Konstanta"
+
+#: editor/animation_editor.cpp
+msgid "In"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Out"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "In-Out"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Out-In"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Transitions"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Optimize Animation"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Clean-Up Animation"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Create NEW track for %s and insert key?"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Create %d NEW tracks and insert keys?"
+msgstr ""
+
+#: editor/animation_editor.cpp editor/create_dialog.cpp
+#: editor/editor_audio_buses.cpp editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+#: editor/plugins/particles_editor_plugin.cpp editor/project_manager.cpp
+#: editor/script_create_dialog.cpp
+msgid "Create"
+msgstr "Sukurti"
+
+#: editor/animation_editor.cpp
+msgid "Anim Create & Insert"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Anim Insert Track & Key"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Anim Insert Key"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Change Anim Len"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Change Anim Loop"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Anim Create Typed Value Key"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Anim Insert"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Anim Scale Keys"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Anim Add Call Track"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Animation zoom."
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Length (s):"
+msgstr "Ilgis:"
+
+#: editor/animation_editor.cpp
+msgid "Animation length (in seconds)."
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Step (s):"
+msgstr "Žingsnis(iai):"
+
+#: editor/animation_editor.cpp
+msgid "Cursor step snap (in seconds)."
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Enable/Disable looping in animation."
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Add new tracks."
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Move current track up."
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Move current track down."
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Remove selected track."
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Track tools"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Enable editing of individual keys by clicking them."
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Anim. Optimizer"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Max. Linear Error:"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Max. Angular Error:"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Max Optimizable Angle:"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Optimize"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Select an AnimationPlayer from the Scene Tree to edit animations."
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Key"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Transition"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Scale Ratio:"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Call Functions in Which Node?"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Remove invalid keys"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Remove unresolved and empty tracks"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Clean-up all animations"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Clean-Up Animation(s) (NO UNDO!)"
+msgstr ""
+
+#: editor/animation_editor.cpp
+msgid "Clean-Up"
+msgstr ""
+
+#: editor/array_property_edit.cpp
+msgid "Resize Array"
+msgstr ""
+
+#: editor/array_property_edit.cpp
+msgid "Change Array Value Type"
+msgstr ""
+
+#: editor/array_property_edit.cpp
+msgid "Change Array Value"
+msgstr ""
+
+#: editor/code_editor.cpp
+msgid "Go to Line"
+msgstr ""
+
+#: editor/code_editor.cpp
+msgid "Line Number:"
+msgstr ""
+
+#: editor/code_editor.cpp
+msgid "No Matches"
+msgstr ""
+
+#: editor/code_editor.cpp
+msgid "Replaced %d occurrence(s)."
+msgstr ""
+
+#: editor/code_editor.cpp
+msgid "Replace"
+msgstr ""
+
+#: editor/code_editor.cpp
+msgid "Replace All"
+msgstr ""
+
+#: editor/code_editor.cpp
+msgid "Match Case"
+msgstr ""
+
+#: editor/code_editor.cpp
+msgid "Whole Words"
+msgstr ""
+
+#: editor/code_editor.cpp
+msgid "Selection Only"
+msgstr ""
+
+#: editor/code_editor.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
+msgid "Search"
+msgstr ""
+
+#: editor/code_editor.cpp editor/editor_help.cpp
+msgid "Find"
+msgstr ""
+
+#: editor/code_editor.cpp
+msgid "Next"
+msgstr ""
+
+#: editor/code_editor.cpp
+msgid "Not found!"
+msgstr ""
+
+#: editor/code_editor.cpp
+msgid "Replace By"
+msgstr ""
+
+#: editor/code_editor.cpp
+msgid "Case Sensitive"
+msgstr ""
+
+#: editor/code_editor.cpp
+msgid "Backwards"
+msgstr ""
+
+#: editor/code_editor.cpp
+msgid "Prompt On Replace"
+msgstr ""
+
+#: editor/code_editor.cpp
+msgid "Skip"
+msgstr ""
+
+#: editor/code_editor.cpp
+msgid "Zoom In"
+msgstr ""
+
+#: editor/code_editor.cpp
+msgid "Zoom Out"
+msgstr ""
+
+#: editor/code_editor.cpp
+msgid "Reset Zoom"
+msgstr ""
+
+#: editor/code_editor.cpp editor/script_editor_debugger.cpp
+msgid "Line:"
+msgstr ""
+
+#: editor/code_editor.cpp
+msgid "Col:"
+msgstr ""
+
+#: editor/connections_dialog.cpp
+msgid "Method in target Node must be specified!"
+msgstr ""
+
+#: editor/connections_dialog.cpp
+msgid ""
+"Target method not found! Specify a valid method or attach a script to target "
+"Node."
+msgstr ""
+
+#: editor/connections_dialog.cpp
+msgid "Connect To Node:"
+msgstr ""
+
+#: editor/connections_dialog.cpp editor/editor_autoload_settings.cpp
+#: editor/groups_editor.cpp editor/plugins/item_list_editor_plugin.cpp
+#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp
+msgid "Add"
+msgstr ""
+
+#: editor/connections_dialog.cpp editor/dependency_editor.cpp
+#: editor/plugins/animation_tree_editor_plugin.cpp
+#: editor/plugins/theme_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp
+msgid "Remove"
+msgstr ""
+
+#: editor/connections_dialog.cpp
+msgid "Add Extra Call Argument:"
+msgstr ""
+
+#: editor/connections_dialog.cpp
+msgid "Extra Call Arguments:"
+msgstr ""
+
+#: editor/connections_dialog.cpp
+msgid "Path to Node:"
+msgstr ""
+
+#: editor/connections_dialog.cpp
+msgid "Make Function"
+msgstr ""
+
+#: editor/connections_dialog.cpp
+msgid "Deferred"
+msgstr ""
+
+#: editor/connections_dialog.cpp
+msgid "Oneshot"
+msgstr ""
+
+#: editor/connections_dialog.cpp editor/dependency_editor.cpp
+#: editor/export_template_manager.cpp
+#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Close"
+msgstr ""
+
+#: editor/connections_dialog.cpp
+msgid "Connect"
+msgstr ""
+
+#: editor/connections_dialog.cpp
+msgid "Connect '%s' to '%s'"
+msgstr ""
+
+#: editor/connections_dialog.cpp
+msgid "Connecting Signal:"
+msgstr ""
+
+#: editor/connections_dialog.cpp
+msgid "Create Subscription"
+msgstr ""
+
+#: editor/connections_dialog.cpp
+msgid "Connect.."
+msgstr ""
+
+#: editor/connections_dialog.cpp
+#: editor/plugins/animation_tree_editor_plugin.cpp
+msgid "Disconnect"
+msgstr ""
+
+#: editor/connections_dialog.cpp editor/editor_help.cpp editor/node_dock.cpp
+msgid "Signals"
+msgstr ""
+
+#: editor/create_dialog.cpp
+msgid "Create New"
+msgstr ""
+
+#: editor/create_dialog.cpp editor/editor_file_dialog.cpp
+#: editor/filesystem_dock.cpp
+msgid "Favorites:"
+msgstr ""
+
+#: editor/create_dialog.cpp editor/editor_file_dialog.cpp
+msgid "Recent:"
+msgstr ""
+
+#: editor/create_dialog.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/quick_open.cpp editor/settings_config_dialog.cpp
+msgid "Search:"
+msgstr ""
+
+#: editor/create_dialog.cpp editor/editor_help.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/quick_open.cpp
+msgid "Matches:"
+msgstr ""
+
+#: editor/create_dialog.cpp editor/editor_help.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/property_selector.cpp
+#: editor/script_editor_debugger.cpp
+msgid "Description:"
+msgstr ""
+
+#: editor/dependency_editor.cpp
+msgid "Search Replacement For:"
+msgstr ""
+
+#: editor/dependency_editor.cpp
+msgid "Dependencies For:"
+msgstr ""
+
+#: editor/dependency_editor.cpp
+msgid ""
+"Scene '%s' is currently being edited.\n"
+"Changes will not take effect unless reloaded."
+msgstr ""
+
+#: editor/dependency_editor.cpp
+msgid ""
+"Resource '%s' is in use.\n"
+"Changes will take effect when reloaded."
+msgstr ""
+
+#: editor/dependency_editor.cpp
+msgid "Dependencies"
+msgstr ""
+
+#: editor/dependency_editor.cpp
+msgid "Resource"
+msgstr ""
+
+#: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp
+#: editor/project_manager.cpp editor/project_settings_editor.cpp
+#: editor/script_create_dialog.cpp
+msgid "Path"
+msgstr ""
+
+#: editor/dependency_editor.cpp
+msgid "Dependencies:"
+msgstr ""
+
+#: editor/dependency_editor.cpp
+msgid "Fix Broken"
+msgstr ""
+
+#: editor/dependency_editor.cpp
+msgid "Dependency Editor"
+msgstr ""
+
+#: editor/dependency_editor.cpp
+msgid "Search Replacement Resource:"
+msgstr ""
+
+#: editor/dependency_editor.cpp
+msgid "Owners Of:"
+msgstr ""
+
+#: editor/dependency_editor.cpp
+msgid "Remove selected files from the project? (no undo)"
+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 ""
+
+#: editor/dependency_editor.cpp
+msgid "Cannot remove:\n"
+msgstr ""
+
+#: editor/dependency_editor.cpp
+msgid "Error loading:"
+msgstr ""
+
+#: editor/dependency_editor.cpp
+msgid "Scene failed to load due to missing dependencies:"
+msgstr ""
+
+#: editor/dependency_editor.cpp editor/editor_node.cpp
+msgid "Open Anyway"
+msgstr ""
+
+#: editor/dependency_editor.cpp
+msgid "Which action should be taken?"
+msgstr ""
+
+#: editor/dependency_editor.cpp
+msgid "Fix Dependencies"
+msgstr ""
+
+#: editor/dependency_editor.cpp
+msgid "Errors loading!"
+msgstr ""
+
+#: editor/dependency_editor.cpp
+msgid "Permanently delete %d item(s)? (No undo!)"
+msgstr ""
+
+#: editor/dependency_editor.cpp
+msgid "Owns"
+msgstr ""
+
+#: editor/dependency_editor.cpp
+msgid "Resources Without Explicit Ownership:"
+msgstr ""
+
+#: editor/dependency_editor.cpp editor/editor_node.cpp
+msgid "Orphan Resource Explorer"
+msgstr ""
+
+#: editor/dependency_editor.cpp
+msgid "Delete selected files?"
+msgstr ""
+
+#: editor/dependency_editor.cpp editor/editor_audio_buses.cpp
+#: editor/editor_node.cpp editor/filesystem_dock.cpp
+#: editor/plugins/item_list_editor_plugin.cpp editor/project_export.cpp
+#: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp
+msgid "Delete"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Thanks from the Godot community!"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Thanks!"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Godot Engine contributors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Project Founders"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Lead Developer"
+msgstr ""
+
+#: editor/editor_about.cpp editor/project_manager.cpp
+msgid "Project Manager"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Developers"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Authors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Platinum Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Gold Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Mini Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Gold Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Silver Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Bronze Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "License"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Thirdparty License"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid ""
+"Godot Engine relies on a number of thirdparty free and open source "
+"libraries, all compatible with the terms of its MIT license. The following "
+"is an exhaustive list of all such thirdparty components with their "
+"respective copyright statements and license terms."
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "All Components"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Components"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Licenses"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "Error opening package file, not in zip format."
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+msgid "Uncompressing Assets"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "Package Installed Successfully!"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Success!"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/project_manager.cpp
+msgid "Install"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+msgid "Package Installer"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
+msgid "Speakers"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
+msgid "Add Effect"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
+msgid "Rename Audio Bus"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
+msgid "Toggle Audio Bus Solo"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
+msgid "Toggle Audio Bus Mute"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
+msgid "Toggle Audio Bus Bypass Effects"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
+msgid "Select Audio Bus Send"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
+msgid "Add Audio Bus Effect"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
+msgid "Move Bus Effect"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
+msgid "Delete Bus Effect"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
+msgid "Audio Bus, Drag and Drop to rearrange."
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
+msgid "Solo"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
+msgid "Mute"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
+msgid "Bypass"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
+msgid "Bus options"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp editor/plugins/tile_map_editor_plugin.cpp
+#: editor/scene_tree_dock.cpp
+msgid "Duplicate"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
+msgid "Reset Volume"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
+msgid "Delete Effect"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
+msgid "Add Audio Bus"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
+msgid "Master bus can't be deleted!"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
+msgid "Delete Audio Bus"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
+msgid "Duplicate Audio Bus"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
+msgid "Reset Bus Volume"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
+msgid "Move Audio Bus"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
+msgid "Save Audio Bus Layout As.."
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
+msgid "Location for New Layout.."
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
+msgid "Open Audio Bus Layout"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
+msgid "There is no 'res://default_bus_layout.tres' file."
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
+msgid "Invalid file, not an audio bus layout."
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
+msgid "Add Bus"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
+msgid "Create a new Bus Layout."
+msgstr ""
+
+#: editor/editor_audio_buses.cpp editor/property_editor.cpp
+#: editor/script_create_dialog.cpp
+msgid "Load"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
+msgid "Load an existing Bus Layout."
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Save As"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
+msgid "Save this Bus Layout to a file."
+msgstr ""
+
+#: editor/editor_audio_buses.cpp editor/import_dock.cpp
+msgid "Load Default"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
+msgid "Load the default Bus Layout."
+msgstr ""
+
+#: editor/editor_autoload_settings.cpp
+msgid "Invalid name."
+msgstr ""
+
+#: editor/editor_autoload_settings.cpp
+msgid "Valid characters:"
+msgstr ""
+
+#: editor/editor_autoload_settings.cpp
+msgid "Invalid name. Must not collide with an existing engine class name."
+msgstr ""
+
+#: editor/editor_autoload_settings.cpp
+msgid "Invalid name. Must not collide with an existing buit-in type name."
+msgstr ""
+
+#: editor/editor_autoload_settings.cpp
+msgid "Invalid name. Must not collide with an existing global constant name."
+msgstr ""
+
+#: editor/editor_autoload_settings.cpp
+msgid "Invalid Path."
+msgstr ""
+
+#: editor/editor_autoload_settings.cpp
+msgid "File does not exist."
+msgstr ""
+
+#: editor/editor_autoload_settings.cpp
+msgid "Not in resource path."
+msgstr ""
+
+#: editor/editor_autoload_settings.cpp
+msgid "Add AutoLoad"
+msgstr ""
+
+#: editor/editor_autoload_settings.cpp
+msgid "Autoload '%s' already exists!"
+msgstr ""
+
+#: editor/editor_autoload_settings.cpp
+msgid "Rename Autoload"
+msgstr ""
+
+#: editor/editor_autoload_settings.cpp
+msgid "Toggle AutoLoad Globals"
+msgstr ""
+
+#: editor/editor_autoload_settings.cpp
+msgid "Move Autoload"
+msgstr ""
+
+#: editor/editor_autoload_settings.cpp
+msgid "Remove Autoload"
+msgstr ""
+
+#: editor/editor_autoload_settings.cpp
+msgid "Enable"
+msgstr ""
+
+#: editor/editor_autoload_settings.cpp
+msgid "Rearrange Autoloads"
+msgstr ""
+
+#: editor/editor_autoload_settings.cpp editor/editor_file_dialog.cpp
+#: scene/gui/file_dialog.cpp
+msgid "Path:"
+msgstr ""
+
+#: editor/editor_autoload_settings.cpp
+msgid "Node Name:"
+msgstr ""
+
+#: editor/editor_autoload_settings.cpp editor/project_manager.cpp
+msgid "Name"
+msgstr ""
+
+#: editor/editor_autoload_settings.cpp
+msgid "Singleton"
+msgstr ""
+
+#: editor/editor_autoload_settings.cpp
+msgid "List:"
+msgstr ""
+
+#: editor/editor_data.cpp
+msgid "Updating Scene"
+msgstr ""
+
+#: editor/editor_data.cpp
+msgid "Storing local changes.."
+msgstr ""
+
+#: editor/editor_data.cpp
+msgid "Updating scene.."
+msgstr ""
+
+#: editor/editor_dir_dialog.cpp
+msgid "Please select a base directory first"
+msgstr ""
+
+#: editor/editor_dir_dialog.cpp
+msgid "Choose a Directory"
+msgstr ""
+
+#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
+msgid "Create Folder"
+msgstr ""
+
+#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
+#: editor/editor_plugin_settings.cpp editor/filesystem_dock.cpp
+#: editor/plugins/theme_editor_plugin.cpp editor/project_export.cpp
+#: scene/gui/file_dialog.cpp
+msgid "Name:"
+msgstr ""
+
+#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
+msgid "Could not create folder."
+msgstr ""
+
+#: editor/editor_dir_dialog.cpp
+msgid "Choose"
+msgstr ""
+
+#: editor/editor_export.cpp
+msgid "Storing File:"
+msgstr ""
+
+#: editor/editor_export.cpp
+msgid "Packing"
+msgstr ""
+
+#: editor/editor_export.cpp platform/javascript/export/export.cpp
+msgid "Template file not found:\n"
+msgstr ""
+
+#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
+msgid "File Exists, Overwrite?"
+msgstr ""
+
+#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
+msgid "All Recognized"
+msgstr ""
+
+#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
+msgid "All Files (*)"
+msgstr ""
+
+#: editor/editor_file_dialog.cpp editor/editor_help.cpp editor/editor_node.cpp
+#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
+#: editor/property_selector.cpp editor/quick_open.cpp scene/gui/file_dialog.cpp
+msgid "Open"
+msgstr ""
+
+#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
+msgid "Open a File"
+msgstr ""
+
+#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
+msgid "Open File(s)"
+msgstr ""
+
+#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
+msgid "Open a Directory"
+msgstr ""
+
+#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
+msgid "Open a File or Directory"
+msgstr ""
+
+#: editor/editor_file_dialog.cpp editor/editor_node.cpp
+#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp
+msgid "Save"
+msgstr ""
+
+#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
+msgid "Save a File"
+msgstr ""
+
+#: editor/editor_file_dialog.cpp
+msgid "Go Back"
+msgstr ""
+
+#: editor/editor_file_dialog.cpp
+msgid "Go Forward"
+msgstr ""
+
+#: editor/editor_file_dialog.cpp
+msgid "Go Up"
+msgstr ""
+
+#: editor/editor_file_dialog.cpp
+msgid "Refresh"
+msgstr ""
+
+#: editor/editor_file_dialog.cpp
+msgid "Toggle Hidden Files"
+msgstr ""
+
+#: editor/editor_file_dialog.cpp
+msgid "Toggle Favorite"
+msgstr ""
+
+#: editor/editor_file_dialog.cpp
+msgid "Toggle Mode"
+msgstr ""
+
+#: editor/editor_file_dialog.cpp
+msgid "Focus Path"
+msgstr ""
+
+#: editor/editor_file_dialog.cpp
+msgid "Move Favorite Up"
+msgstr ""
+
+#: editor/editor_file_dialog.cpp
+msgid "Move Favorite Down"
+msgstr ""
+
+#: editor/editor_file_dialog.cpp
+msgid "Go to parent folder"
+msgstr ""
+
+#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
+msgid "Directories & Files:"
+msgstr ""
+
+#: editor/editor_file_dialog.cpp
+msgid "Preview:"
+msgstr ""
+
+#: editor/editor_file_dialog.cpp editor/script_editor_debugger.cpp
+#: scene/gui/file_dialog.cpp
+msgid "File:"
+msgstr ""
+
+#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
+msgid "Must use a valid extension."
+msgstr ""
+
+#: editor/editor_file_system.cpp
+msgid "ScanSources"
+msgstr ""
+
+#: editor/editor_file_system.cpp
+msgid "(Re)Importing Assets"
+msgstr ""
+
+#: editor/editor_help.cpp editor/editor_node.cpp
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Search Help"
+msgstr ""
+
+#: editor/editor_help.cpp
+msgid "Class List:"
+msgstr ""
+
+#: editor/editor_help.cpp
+msgid "Search Classes"
+msgstr ""
+
+#: editor/editor_help.cpp editor/plugins/spatial_editor_plugin.cpp
+msgid "Top"
+msgstr ""
+
+#: editor/editor_help.cpp editor/property_editor.cpp
+msgid "Class:"
+msgstr ""
+
+#: editor/editor_help.cpp editor/scene_tree_editor.cpp
+msgid "Inherits:"
+msgstr ""
+
+#: editor/editor_help.cpp
+msgid "Inherited by:"
+msgstr ""
+
+#: editor/editor_help.cpp
+msgid "Brief Description:"
+msgstr ""
+
+#: editor/editor_help.cpp
+msgid "Members"
+msgstr ""
+
+#: editor/editor_help.cpp modules/visual_script/visual_script_editor.cpp
+msgid "Members:"
+msgstr ""
+
+#: editor/editor_help.cpp
+msgid "Public Methods"
+msgstr ""
+
+#: editor/editor_help.cpp
+msgid "Public Methods:"
+msgstr ""
+
+#: editor/editor_help.cpp
+msgid "GUI Theme Items"
+msgstr ""
+
+#: editor/editor_help.cpp
+msgid "GUI Theme Items:"
+msgstr ""
+
+#: editor/editor_help.cpp modules/visual_script/visual_script_editor.cpp
+msgid "Signals:"
+msgstr ""
+
+#: editor/editor_help.cpp
+msgid "Enumerations"
+msgstr ""
+
+#: editor/editor_help.cpp
+msgid "Enumerations:"
+msgstr ""
+
+#: editor/editor_help.cpp
+msgid "enum "
+msgstr ""
+
+#: editor/editor_help.cpp
+msgid "Constants"
+msgstr ""
+
+#: editor/editor_help.cpp
+msgid "Constants:"
+msgstr ""
+
+#: editor/editor_help.cpp
+msgid "Description"
+msgstr ""
+
+#: editor/editor_help.cpp
+msgid "Properties"
+msgstr ""
+
+#: editor/editor_help.cpp
+msgid "Property Description:"
+msgstr ""
+
+#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this property. Please help us by "
+"[color=$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+
+#: editor/editor_help.cpp
+msgid "Methods"
+msgstr ""
+
+#: editor/editor_help.cpp
+msgid "Method Description:"
+msgstr ""
+
+#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this method. Please help us by [color="
+"$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+
+#: editor/editor_help.cpp
+msgid "Search Text"
+msgstr ""
+
+#: editor/editor_log.cpp
+msgid "Output:"
+msgstr ""
+
+#: editor/editor_log.cpp editor/plugins/animation_tree_editor_plugin.cpp
+#: editor/property_editor.cpp editor/script_editor_debugger.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+msgid "Clear"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
+msgid "Error saving resource!"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
+msgid "Save Resource As.."
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
+msgid "I see.."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Can't open file for writing:"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Requested file format unknown:"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Error while saving."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Can't open '%s'."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Error while parsing '%s'."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Unexpected end of file '%s'."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Missing '%s' or its dependencies."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Error while loading '%s'."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Saving Scene"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Analyzing"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Creating Thumbnail"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "This operation can't be done without a tree root."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"Couldn't save scene. Likely dependencies (instances) couldn't be satisfied."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Failed to load resource."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Can't load MeshLibrary for merging!"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Error saving MeshLibrary!"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Can't load TileSet for merging!"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Error saving TileSet!"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Error trying to save layout!"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Default editor layout overridden."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Layout name not found!"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Restored default layout to base settings."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was imported, so it's not editable.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was instanced or inherited.\n"
+"Changes to it will not be kept when saving the current scene."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource was imported, so it's not editable. Change its settings in the "
+"import panel and then re-import."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This scene was imported, so changes to it will not be kept.\n"
+"Instancing it or inheriting will allow making changes to it.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Copy Params"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Paste Params"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/resource_preloader_editor_plugin.cpp
+msgid "Paste Resource"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Copy Resource"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Make Built-In"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Make Sub-Resources Unique"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Open in Help"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "There is no defined scene to run."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"No main scene has ever been defined, select one?\n"
+"You can change it later in \"Project Settings\" under the 'application' "
+"category."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"Selected scene '%s' does not exist, select a valid one?\n"
+"You can change it later in \"Project Settings\" under the 'application' "
+"category."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"Selected scene '%s' is not a scene file, select a valid one?\n"
+"You can change it later in \"Project Settings\" under the 'application' "
+"category."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Current scene was never saved, please save it prior to running."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Could not start subprocess!"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Open Scene"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Open Base Scene"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Quick Open Scene.."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Quick Open Script.."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Save & Close"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Save changes to '%s' before closing?"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Save Scene As.."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "No"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Yes"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "This scene has never been saved. Save before running?"
+msgstr ""
+
+#: editor/editor_node.cpp editor/scene_tree_dock.cpp
+msgid "This operation can't be done without a scene."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Export Mesh Library"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Export Tile Set"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "This operation can't be done without a selected node."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Current scene not saved. Open anyway?"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Can't reload a scene that was never saved."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Revert"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "This action cannot be undone. Revert anyway?"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Quick Run Scene.."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Quit"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Exit the editor?"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Open Project Manager?"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Save & Quit"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Save changes to the following scene(s) before quitting?"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Save changes the following scene(s) before opening Project Manager?"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This option is deprecated. Situations where refresh must be forced are now "
+"considered a bug. Please report."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Pick a Main Scene"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Unable to load addon script from path: '%s'."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"Unable to load addon script from path: '%s' Base type is not EditorPlugin."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Unable to load addon script from path: '%s' Script is not in tool mode."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"Scene '%s' was automatically imported, so it can't be modified.\n"
+"To make changes to it, a new inherited scene can be created."
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
+msgid "Ugh"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"Error loading scene, it must be inside the project path. Use 'Import' to "
+"open the scene, then save it inside the project path."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Scene '%s' has broken dependencies:"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Clear Recent Scenes"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Save Layout"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Delete Layout"
+msgstr ""
+
+#: editor/editor_node.cpp editor/import_dock.cpp
+#: editor/script_create_dialog.cpp
+msgid "Default"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Switch Scene Tab"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "%d more file(s)"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "%d more file(s) or folder(s)"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Distraction Free Mode"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Toggle distraction-free mode."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Scene"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Go to previously opened scene."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Next tab"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Previous tab"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Filter Files.."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Operations with scene files."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "New Scene"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "New Inherited Scene.."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Open Scene.."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Save Scene"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Save all Scenes"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Close Scene"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+msgid "Open Recent"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Convert To.."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "MeshLibrary.."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "TileSet.."
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp scene/gui/line_edit.cpp
+#: scene/gui/text_edit.cpp
+msgid "Undo"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Redo"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Revert Scene"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Miscellaneous project or scene-wide tools."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Project"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Project Settings"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Run Script"
+msgstr ""
+
+#: editor/editor_node.cpp editor/project_export.cpp
+msgid "Export"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Tools"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Quit to Project List"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+msgid "Debug"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Deploy with Remote Debug"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"When exporting or deploying, the resulting executable will attempt to "
+"connect to the IP of this computer in order to be debugged."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Small Deploy with Network FS"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"When this option is enabled, export or deploy will produce a minimal "
+"executable.\n"
+"The filesystem will be provided from the project by the editor over the "
+"network.\n"
+"On Android, deploy will use the USB cable for faster performance. This "
+"option speeds up testing for games with a large footprint."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Visible Collision Shapes"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"Collision shapes and raycast nodes (for 2D and 3D) will be visible on the "
+"running game if this option is turned on."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Visible Navigation"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"Navigation meshes and polygons will be visible on the running game if this "
+"option is turned on."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Sync Scene Changes"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"When this option is turned on, any changes made to the scene in the editor "
+"will be replicated in the running game.\n"
+"When used remotely on a device, this is more efficient with network "
+"filesystem."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Sync Script Changes"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"When this option is turned on, any script that is saved will be reloaded on "
+"the running game.\n"
+"When used remotely on a device, this is more efficient with network "
+"filesystem."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Editor"
+msgstr ""
+
+#: editor/editor_node.cpp editor/settings_config_dialog.cpp
+msgid "Editor Settings"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Editor Layout"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Toggle Fullscreen"
+msgstr ""
+
+#: editor/editor_node.cpp editor/project_export.cpp
+msgid "Manage Export Templates"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Help"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+msgid "Classes"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+msgid "Online Docs"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Q&A"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Issue Tracker"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+msgid "Community"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "About"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Play the project."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Play"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Pause the scene"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Pause Scene"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Stop the scene."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Stop"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Play the edited scene."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Play Scene"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Play custom scene"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Play Custom Scene"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Spins when the editor window repaints!"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Update Always"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Update Changes"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Disable Update Spinner"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Inspector"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Create a new resource in memory and edit it."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Load an existing resource from disk and edit it."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Save the currently edited resource."
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
+msgid "Save As.."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Go to the previous edited object in history."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Go to the next edited object in history."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "History of recently edited objects."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Object properties."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Changes may be lost!"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Import"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "FileSystem"
+msgstr ""
+
+#: editor/editor_node.cpp editor/node_dock.cpp
+msgid "Node"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Output"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Don't Save"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Import Templates From ZIP File"
+msgstr ""
+
+#: editor/editor_node.cpp editor/project_export.cpp
+msgid "Export Project"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Export Library"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Merge With Existing"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Password:"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Open & Run a Script"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "New Inherited"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Load Errors"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/tile_map_editor_plugin.cpp
+msgid "Select"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Open 2D Editor"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Open 3D Editor"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Open Script Editor"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Open Asset Library"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Open the next Editor"
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Open the previous Editor"
+msgstr ""
+
+#: editor/editor_plugin.cpp
+msgid "Creating Mesh Previews"
+msgstr ""
+
+#: editor/editor_plugin.cpp
+msgid "Thumbnail.."
+msgstr ""
+
+#: editor/editor_plugin_settings.cpp
+msgid "Installed Plugins:"
+msgstr ""
+
+#: editor/editor_plugin_settings.cpp
+msgid "Update"
+msgstr ""
+
+#: editor/editor_plugin_settings.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Version:"
+msgstr ""
+
+#: editor/editor_plugin_settings.cpp
+msgid "Author:"
+msgstr ""
+
+#: editor/editor_plugin_settings.cpp
+msgid "Status:"
+msgstr ""
+
+#: editor/editor_profiler.cpp
+msgid "Stop Profiling"
+msgstr ""
+
+#: editor/editor_profiler.cpp
+msgid "Start Profiling"
+msgstr ""
+
+#: editor/editor_profiler.cpp
+msgid "Measure:"
+msgstr ""
+
+#: editor/editor_profiler.cpp
+msgid "Frame Time (sec)"
+msgstr ""
+
+#: editor/editor_profiler.cpp
+msgid "Average Time (sec)"
+msgstr ""
+
+#: editor/editor_profiler.cpp
+msgid "Frame %"
+msgstr ""
+
+#: editor/editor_profiler.cpp
+msgid "Physics Frame %"
+msgstr ""
+
+#: editor/editor_profiler.cpp editor/script_editor_debugger.cpp
+msgid "Time:"
+msgstr ""
+
+#: editor/editor_profiler.cpp
+msgid "Inclusive"
+msgstr ""
+
+#: editor/editor_profiler.cpp
+msgid "Self"
+msgstr ""
+
+#: editor/editor_profiler.cpp
+msgid "Frame #:"
+msgstr ""
+
+#: editor/editor_run_native.cpp
+msgid "Select device from the list"
+msgstr ""
+
+#: editor/editor_run_native.cpp
+msgid ""
+"No runnable export preset found for this platform.\n"
+"Please add a runnable preset in the export menu."
+msgstr ""
+
+#: editor/editor_run_script.cpp
+msgid "Write your logic in the _run() method."
+msgstr ""
+
+#: editor/editor_run_script.cpp
+msgid "There is an edited scene already."
+msgstr ""
+
+#: editor/editor_run_script.cpp
+msgid "Couldn't instance script:"
+msgstr ""
+
+#: editor/editor_run_script.cpp
+msgid "Did you forget the 'tool' keyword?"
+msgstr ""
+
+#: editor/editor_run_script.cpp
+msgid "Couldn't run script:"
+msgstr ""
+
+#: editor/editor_run_script.cpp
+msgid "Did you forget the '_run' method?"
+msgstr ""
+
+#: editor/editor_settings.cpp
+msgid "Default (Same as Editor)"
+msgstr ""
+
+#: editor/editor_sub_scene.cpp
+msgid "Select Node(s) to Import"
+msgstr ""
+
+#: editor/editor_sub_scene.cpp
+msgid "Scene Path:"
+msgstr ""
+
+#: editor/editor_sub_scene.cpp
+msgid "Import From Node:"
+msgstr ""
+
+#: editor/export_template_manager.cpp
+msgid "Re-Download"
+msgstr ""
+
+#: editor/export_template_manager.cpp
+msgid "Uninstall"
+msgstr ""
+
+#: editor/export_template_manager.cpp
+msgid "(Installed)"
+msgstr ""
+
+#: editor/export_template_manager.cpp
+msgid "Download"
+msgstr ""
+
+#: editor/export_template_manager.cpp
+msgid "(Missing)"
+msgstr ""
+
+#: editor/export_template_manager.cpp
+msgid "(Current)"
+msgstr ""
+
+#: editor/export_template_manager.cpp
+msgid "Remove template version '%s'?"
+msgstr ""
+
+#: editor/export_template_manager.cpp
+msgid "Can't open export templates zip."
+msgstr ""
+
+#: editor/export_template_manager.cpp
+msgid "Invalid version.txt format inside templates."
+msgstr ""
+
+#: editor/export_template_manager.cpp
+msgid ""
+"Invalid version.txt format inside templates. Revision is not a valid "
+"identifier."
+msgstr ""
+
+#: editor/export_template_manager.cpp
+msgid "No version.txt found inside templates."
+msgstr ""
+
+#: editor/export_template_manager.cpp
+msgid "Error creating path for templates:\n"
+msgstr ""
+
+#: editor/export_template_manager.cpp
+msgid "Extracting Export Templates"
+msgstr ""
+
+#: editor/export_template_manager.cpp
+msgid "Importing:"
+msgstr ""
+
+#: editor/export_template_manager.cpp
+msgid "Current Version:"
+msgstr ""
+
+#: editor/export_template_manager.cpp
+msgid "Installed Versions:"
+msgstr ""
+
+#: editor/export_template_manager.cpp
+msgid "Install From File"
+msgstr ""
+
+#: editor/export_template_manager.cpp
+msgid "Remove Template"
+msgstr ""
+
+#: editor/export_template_manager.cpp
+msgid "Select template file"
+msgstr ""
+
+#: editor/export_template_manager.cpp
+msgid "Export Template Manager"
+msgstr ""
+
+#: editor/file_type_cache.cpp
+msgid "Can't open file_type_cache.cch for writing, not saving file type cache!"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "Cannot navigate to '"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "View items as a grid of thumbnails"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "View items as a list"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid ""
+"\n"
+"Status: Import of file failed. Please fix file and reimport manually."
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid ""
+"\n"
+"Source: "
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "Cannot move/rename resources root."
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "Cannot move a folder into itself.\n"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "Error moving:\n"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "Unable to update dependencies:\n"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "No name provided"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "Provided name contains invalid characters"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "No name provided."
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "Name contains invalid characters."
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "A file or folder with this name already exists."
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "Renaming file:"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "Renaming folder:"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "Expand all"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "Collapse all"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "Copy Path"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "Rename.."
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "Move To.."
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "New Folder.."
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "Show In File Manager"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "Instance"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "Edit Dependencies.."
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "View Owners.."
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "Previous Directory"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "Next Directory"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "Re-Scan Filesystem"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "Toggle folder status as Favorite"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "Instance the selected scene(s) as child of the selected node."
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid ""
+"Scanning Files,\n"
+"Please Wait.."
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "Move"
+msgstr ""
+
+#: editor/filesystem_dock.cpp editor/plugins/animation_tree_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Rename"
+msgstr ""
+
+#: editor/groups_editor.cpp
+msgid "Add to Group"
+msgstr ""
+
+#: editor/groups_editor.cpp
+msgid "Remove from Group"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import as Single Scene"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Materials"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Materials"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Materials+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Materials+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import as Multiple Scenes"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import as Multiple Scenes+Materials"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+#: editor/plugins/cube_grid_theme_editor_plugin.cpp
+msgid "Import Scene"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Importing Scene.."
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Running Custom Script.."
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Couldn't load post-import script:"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Invalid/broken script for post-import (check console):"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Error running post-import script:"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Saving.."
+msgstr ""
+
+#: editor/import_dock.cpp
+msgid "Set as Default for '%s'"
+msgstr ""
+
+#: editor/import_dock.cpp
+msgid "Clear Default for '%s'"
+msgstr ""
+
+#: editor/import_dock.cpp
+msgid " Files"
+msgstr ""
+
+#: editor/import_dock.cpp
+msgid "Import As:"
+msgstr ""
+
+#: editor/import_dock.cpp editor/property_editor.cpp
+msgid "Preset.."
+msgstr ""
+
+#: editor/import_dock.cpp
+msgid "Reimport"
+msgstr ""
+
+#: editor/multi_node_edit.cpp
+msgid "MultiNode Set"
+msgstr ""
+
+#: editor/node_dock.cpp
+msgid "Groups"
+msgstr ""
+
+#: editor/node_dock.cpp
+msgid "Select a Node to edit Signals and Groups."
+msgstr ""
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create Poly"
+msgstr ""
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly"
+msgstr ""
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Insert Point"
+msgstr ""
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly (Remove Point)"
+msgstr ""
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Remove Poly And Point"
+msgstr ""
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create a new polygon from scratch."
+msgstr ""
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid ""
+"Edit existing polygon:\n"
+"LMB: Move Point.\n"
+"Ctrl+LMB: Split Segment.\n"
+"RMB: Erase Point."
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Toggle Autoplay"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "New Animation Name:"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "New Anim"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Change Animation Name:"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Delete Animation?"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Remove Animation"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "ERROR: Invalid animation name!"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "ERROR: Animation name already exists!"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Rename Animation"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Add Animation"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Blend Next Changed"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Change Blend Time"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Load Animation"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Duplicate Animation"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "ERROR: No animation to copy!"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "ERROR: No animation resource on clipboard!"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Pasted Animation"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Paste Animation"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "ERROR: No animation to edit!"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Play selected animation backwards from current pos. (A)"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Play selected animation backwards from end. (Shift+A)"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Stop animation playback. (S)"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Play selected animation from start. (Shift+D)"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Play selected animation from current pos. (D)"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Animation position (in seconds)."
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Scale animation playback globally for the node."
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Create new animation in player."
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Load animation from disk."
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Load an animation from disk."
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Save the current animation"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Display list of animations in player."
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Autoplay on Load"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Edit Target Blend Times"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Animation Tools"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Copy Animation"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Create New Animation"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Animation Name:"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
+#: editor/script_create_dialog.cpp
+msgid "Error!"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Blend Times:"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Next (Auto Queue):"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+msgid "Cross-Animation Blend Times"
+msgstr ""
+
+#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Animation"
+msgstr ""
+
+#: editor/plugins/animation_tree_editor_plugin.cpp
+msgid "New name:"
+msgstr ""
+
+#: editor/plugins/animation_tree_editor_plugin.cpp
+msgid "Edit Filters"
+msgstr ""
+
+#: editor/plugins/animation_tree_editor_plugin.cpp
+#: editor/plugins/multimesh_editor_plugin.cpp
+msgid "Scale:"
+msgstr ""
+
+#: editor/plugins/animation_tree_editor_plugin.cpp
+msgid "Fade In (s):"
+msgstr ""
+
+#: editor/plugins/animation_tree_editor_plugin.cpp
+msgid "Fade Out (s):"
+msgstr ""
+
+#: editor/plugins/animation_tree_editor_plugin.cpp
+msgid "Blend"
+msgstr ""
+
+#: editor/plugins/animation_tree_editor_plugin.cpp
+msgid "Mix"
+msgstr ""
+
+#: editor/plugins/animation_tree_editor_plugin.cpp
+msgid "Auto Restart:"
+msgstr ""
+
+#: editor/plugins/animation_tree_editor_plugin.cpp
+msgid "Restart (s):"
+msgstr ""
+
+#: editor/plugins/animation_tree_editor_plugin.cpp
+msgid "Random Restart (s):"
+msgstr ""
+
+#: editor/plugins/animation_tree_editor_plugin.cpp
+msgid "Start!"
+msgstr ""
+
+#: editor/plugins/animation_tree_editor_plugin.cpp
+#: editor/plugins/multimesh_editor_plugin.cpp
+msgid "Amount:"
+msgstr ""
+
+#: editor/plugins/animation_tree_editor_plugin.cpp
+msgid "Blend:"
+msgstr ""
+
+#: editor/plugins/animation_tree_editor_plugin.cpp
+msgid "Blend 0:"
+msgstr ""
+
+#: editor/plugins/animation_tree_editor_plugin.cpp
+msgid "Blend 1:"
+msgstr ""
+
+#: editor/plugins/animation_tree_editor_plugin.cpp
+msgid "X-Fade Time (s):"
+msgstr ""
+
+#: editor/plugins/animation_tree_editor_plugin.cpp
+msgid "Current:"
+msgstr ""
+
+#: editor/plugins/animation_tree_editor_plugin.cpp
+msgid "Add Input"
+msgstr ""
+
+#: editor/plugins/animation_tree_editor_plugin.cpp
+msgid "Clear Auto-Advance"
+msgstr ""
+
+#: editor/plugins/animation_tree_editor_plugin.cpp
+msgid "Set Auto-Advance"
+msgstr ""
+
+#: editor/plugins/animation_tree_editor_plugin.cpp
+msgid "Delete Input"
+msgstr ""
+
+#: editor/plugins/animation_tree_editor_plugin.cpp
+msgid "Animation tree is valid."
+msgstr ""
+
+#: editor/plugins/animation_tree_editor_plugin.cpp
+msgid "Animation tree is invalid."
+msgstr ""
+
+#: editor/plugins/animation_tree_editor_plugin.cpp
+msgid "Animation Node"
+msgstr ""
+
+#: editor/plugins/animation_tree_editor_plugin.cpp
+msgid "OneShot Node"
+msgstr ""
+
+#: editor/plugins/animation_tree_editor_plugin.cpp
+msgid "Mix Node"
+msgstr ""
+
+#: editor/plugins/animation_tree_editor_plugin.cpp
+msgid "Blend2 Node"
+msgstr ""
+
+#: editor/plugins/animation_tree_editor_plugin.cpp
+msgid "Blend3 Node"
+msgstr ""
+
+#: editor/plugins/animation_tree_editor_plugin.cpp
+msgid "Blend4 Node"
+msgstr ""
+
+#: editor/plugins/animation_tree_editor_plugin.cpp
+msgid "TimeScale Node"
+msgstr ""
+
+#: editor/plugins/animation_tree_editor_plugin.cpp
+msgid "TimeSeek Node"
+msgstr ""
+
+#: editor/plugins/animation_tree_editor_plugin.cpp
+msgid "Transition Node"
+msgstr ""
+
+#: editor/plugins/animation_tree_editor_plugin.cpp
+msgid "Import Animations.."
+msgstr ""
+
+#: editor/plugins/animation_tree_editor_plugin.cpp
+msgid "Edit Node Filters"
+msgstr ""
+
+#: editor/plugins/animation_tree_editor_plugin.cpp
+msgid "Filters.."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Free"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Contents:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "View Files"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve hostname:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connection error, please try again."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't connect."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't connect to host:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response from host:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, return code:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Req. Failed."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, too many redirects"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Redirect Loop."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Bad download hash, assuming file has been tampered with."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Expected:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Got:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed sha256 hash check"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Asset Download Error:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Fetching:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Resolving.."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connecting.."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Requesting.."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Error making request"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Idle"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Retry"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download Error"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download for this asset is already in progress!"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "first"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "prev"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "next"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "last"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "All"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Plugins"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Sort:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Reverse"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Category:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Site:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Support.."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Official"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Testing"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Assets ZIP File"
+msgstr ""
+
+#: editor/plugins/camera_editor_plugin.cpp
+msgid "Preview"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Configure Snap"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Grid Offset:"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Grid Step:"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Rotation Offset:"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Rotation Step:"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Move Pivot"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Move Action"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Edit IK Chain"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Edit CanvasItem"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Anchors only"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Change Anchors and Margins"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Change Anchors"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Paste Pose"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Select Mode"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Drag: Rotate"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Alt+Drag: Move"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Press 'v' to Change Pivot, 'Shift+v' to Drag Pivot (while moving)."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Alt+RMB: Depth list selection"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Move Mode"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Rotate Mode"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid ""
+"Show a list of all objects at the position clicked\n"
+"(same as Alt+RMB in select mode)."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Click to change object's rotation pivot."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Pan Mode"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Toggles snapping"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Use Snap"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snapping options"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to grid"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Use Rotation Snap"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Configure Snap..."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap Relative"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Use Pixel Snap"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Smart snapping"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to parent"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to node anchor"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to node sides"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to other nodes"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Lock the selected object in place (can't be moved)."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Unlock the selected object (can be moved)."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Makes sure the object's children are not selectable."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Restores the object's children's ability to be selected."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Make Bones"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Clear Bones"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Show Bones"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Make IK Chain"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Clear IK Chain"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "View"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Show Grid"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Show helpers"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Show rulers"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Center Selection"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Frame Selection"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Layout"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Insert Keys"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Insert Key"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Insert Key (Existing Tracks)"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Copy Pose"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Clear Pose"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Drag pivot from mouse position"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Set pivot at mouse position"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Multiply grid step by 2"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Divide grid step by 2"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Add %s"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Adding %s..."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
+msgid "Create Node"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
+msgid "Error instancing scene from %s"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
+msgid "OK :("
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
+msgid "No parent to instance a child at."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
+msgid "This operation requires a single selected node."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Change default type"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid ""
+"Drag & drop + Shift : Add node as sibling\n"
+"Drag & drop + Alt : Change node type"
+msgstr ""
+
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+msgid "Create Poly3D"
+msgstr ""
+
+#: editor/plugins/collision_shape_2d_editor_plugin.cpp
+msgid "Set Handle"
+msgstr ""
+
+#: editor/plugins/cube_grid_theme_editor_plugin.cpp
+msgid "Remove item %d?"
+msgstr ""
+
+#: editor/plugins/cube_grid_theme_editor_plugin.cpp
+#: editor/plugins/theme_editor_plugin.cpp
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Add Item"
+msgstr ""
+
+#: editor/plugins/cube_grid_theme_editor_plugin.cpp
+msgid "Remove Selected Item"
+msgstr ""
+
+#: editor/plugins/cube_grid_theme_editor_plugin.cpp
+msgid "Import from Scene"
+msgstr ""
+
+#: editor/plugins/cube_grid_theme_editor_plugin.cpp
+msgid "Update from Scene"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat0"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat1"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Ease in"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Ease out"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Smoothstep"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Modify Curve Point"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Modify Curve Tangent"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Load Curve Preset"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Add point"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Remove point"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Left linear"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Right linear"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Load preset"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Remove Curve Point"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Toggle Curve Linear Tangent"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Hold Shift to edit tangents individually"
+msgstr ""
+
+#: editor/plugins/gradient_editor_plugin.cpp
+msgid "Add/Remove Color Ramp Point"
+msgstr ""
+
+#: editor/plugins/gradient_editor_plugin.cpp
+#: editor/plugins/shader_graph_editor_plugin.cpp
+msgid "Modify Color Ramp"
+msgstr ""
+
+#: editor/plugins/item_list_editor_plugin.cpp
+msgid "Item %d"
+msgstr ""
+
+#: editor/plugins/item_list_editor_plugin.cpp
+msgid "Items"
+msgstr ""
+
+#: editor/plugins/item_list_editor_plugin.cpp
+msgid "Item List Editor"
+msgstr ""
+
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid ""
+"No OccluderPolygon2D resource on this node.\n"
+"Create and assign one?"
+msgstr ""
+
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create Occluder Polygon"
+msgstr ""
+
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit existing polygon:"
+msgstr ""
+
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "LMB: Move Point."
+msgstr ""
+
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Ctrl+LMB: Split Segment."
+msgstr ""
+
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "RMB: Erase Point."
+msgstr ""
+
+#: editor/plugins/line_2d_editor_plugin.cpp
+msgid "Remove Point from Line2D"
+msgstr ""
+
+#: editor/plugins/line_2d_editor_plugin.cpp
+msgid "Add Point to Line2D"
+msgstr ""
+
+#: editor/plugins/line_2d_editor_plugin.cpp
+msgid "Move Point in Line2D"
+msgstr ""
+
+#: editor/plugins/line_2d_editor_plugin.cpp
+#: editor/plugins/path_2d_editor_plugin.cpp
+#: editor/plugins/path_editor_plugin.cpp
+msgid "Select Points"
+msgstr ""
+
+#: editor/plugins/line_2d_editor_plugin.cpp
+#: editor/plugins/path_2d_editor_plugin.cpp
+#: editor/plugins/path_editor_plugin.cpp
+msgid "Shift+Drag: Select Control Points"
+msgstr ""
+
+#: editor/plugins/line_2d_editor_plugin.cpp
+#: editor/plugins/path_2d_editor_plugin.cpp
+#: editor/plugins/path_editor_plugin.cpp
+msgid "Click: Add Point"
+msgstr ""
+
+#: editor/plugins/line_2d_editor_plugin.cpp
+#: editor/plugins/path_2d_editor_plugin.cpp
+#: editor/plugins/path_editor_plugin.cpp
+msgid "Right Click: Delete Point"
+msgstr ""
+
+#: editor/plugins/line_2d_editor_plugin.cpp
+#: editor/plugins/path_2d_editor_plugin.cpp
+#: editor/plugins/path_editor_plugin.cpp
+msgid "Add Point (in empty space)"
+msgstr ""
+
+#: editor/plugins/line_2d_editor_plugin.cpp
+msgid "Split Segment (in line)"
+msgstr ""
+
+#: editor/plugins/line_2d_editor_plugin.cpp
+#: editor/plugins/path_2d_editor_plugin.cpp
+#: editor/plugins/path_editor_plugin.cpp
+msgid "Delete Point"
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Mesh is empty!"
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Create Static Trimesh Body"
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Create Static Convex Body"
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "This doesn't work on scene root!"
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Create Trimesh Shape"
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Create Convex Shape"
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Create Navigation Mesh"
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "MeshInstance lacks a Mesh!"
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Mesh has not surface to create outlines from!"
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Could not create outline!"
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Create Outline"
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Mesh"
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Create Trimesh Static Body"
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Create Convex Static Body"
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Create Trimesh Collision Sibling"
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Create Convex Collision Sibling"
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Create Outline Mesh.."
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Create Outline Mesh"
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Outline Size:"
+msgstr ""
+
+#: editor/plugins/multimesh_editor_plugin.cpp
+msgid "No mesh source specified (and no MultiMesh set in node)."
+msgstr ""
+
+#: editor/plugins/multimesh_editor_plugin.cpp
+msgid "No mesh source specified (and MultiMesh contains no Mesh)."
+msgstr ""
+
+#: editor/plugins/multimesh_editor_plugin.cpp
+msgid "Mesh source is invalid (invalid path)."
+msgstr ""
+
+#: editor/plugins/multimesh_editor_plugin.cpp
+msgid "Mesh source is invalid (not a MeshInstance)."
+msgstr ""
+
+#: editor/plugins/multimesh_editor_plugin.cpp
+msgid "Mesh source is invalid (contains no Mesh resource)."
+msgstr ""
+
+#: editor/plugins/multimesh_editor_plugin.cpp
+msgid "No surface source specified."
+msgstr ""
+
+#: editor/plugins/multimesh_editor_plugin.cpp
+msgid "Surface source is invalid (invalid path)."
+msgstr ""
+
+#: editor/plugins/multimesh_editor_plugin.cpp
+msgid "Surface source is invalid (no geometry)."
+msgstr ""
+
+#: editor/plugins/multimesh_editor_plugin.cpp
+msgid "Surface source is invalid (no faces)."
+msgstr ""
+
+#: editor/plugins/multimesh_editor_plugin.cpp
+msgid "Parent has no solid faces to populate."
+msgstr ""
+
+#: editor/plugins/multimesh_editor_plugin.cpp
+msgid "Couldn't map area."
+msgstr ""
+
+#: editor/plugins/multimesh_editor_plugin.cpp
+msgid "Select a Source Mesh:"
+msgstr ""
+
+#: editor/plugins/multimesh_editor_plugin.cpp
+msgid "Select a Target Surface:"
+msgstr ""
+
+#: editor/plugins/multimesh_editor_plugin.cpp
+msgid "Populate Surface"
+msgstr ""
+
+#: editor/plugins/multimesh_editor_plugin.cpp
+msgid "Populate MultiMesh"
+msgstr ""
+
+#: editor/plugins/multimesh_editor_plugin.cpp
+msgid "Target Surface:"
+msgstr ""
+
+#: editor/plugins/multimesh_editor_plugin.cpp
+msgid "Source Mesh:"
+msgstr ""
+
+#: editor/plugins/multimesh_editor_plugin.cpp
+msgid "X-Axis"
+msgstr ""
+
+#: editor/plugins/multimesh_editor_plugin.cpp
+msgid "Y-Axis"
+msgstr ""
+
+#: editor/plugins/multimesh_editor_plugin.cpp
+msgid "Z-Axis"
+msgstr ""
+
+#: editor/plugins/multimesh_editor_plugin.cpp
+msgid "Mesh Up Axis:"
+msgstr ""
+
+#: editor/plugins/multimesh_editor_plugin.cpp
+msgid "Random Rotation:"
+msgstr ""
+
+#: editor/plugins/multimesh_editor_plugin.cpp
+msgid "Random Tilt:"
+msgstr ""
+
+#: editor/plugins/multimesh_editor_plugin.cpp
+msgid "Random Scale:"
+msgstr ""
+
+#: editor/plugins/multimesh_editor_plugin.cpp
+msgid "Populate"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake!"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake the navigation mesh.\n"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Clear the navigation mesh."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Setting up Configuration..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Calculating grid size..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating heightfield..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Marking walkable triangles..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Constructing compact heightfield..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Eroding walkable area..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Partitioning..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating contours..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating polymesh..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Converting to native navigation mesh..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Navigation Mesh Generator Setup:"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Parsing Geometry..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Done!"
+msgstr ""
+
+#: editor/plugins/navigation_polygon_editor_plugin.cpp
+msgid "Create Navigation Polygon"
+msgstr ""
+
+#: editor/plugins/particles_2d_editor_plugin.cpp
+msgid "Clear Emission Mask"
+msgstr ""
+
+#: editor/plugins/particles_2d_editor_plugin.cpp
+#: editor/plugins/particles_editor_plugin.cpp
+msgid "Generating AABB"
+msgstr ""
+
+#: editor/plugins/particles_2d_editor_plugin.cpp
+msgid "Can only set point into a ParticlesMaterial process material"
+msgstr ""
+
+#: editor/plugins/particles_2d_editor_plugin.cpp
+msgid "Error loading image:"
+msgstr ""
+
+#: editor/plugins/particles_2d_editor_plugin.cpp
+msgid "No pixels with transparency > 128 in image.."
+msgstr ""
+
+#: editor/plugins/particles_2d_editor_plugin.cpp
+msgid "Set Emission Mask"
+msgstr ""
+
+#: editor/plugins/particles_2d_editor_plugin.cpp
+msgid "Generate Visibility Rect"
+msgstr ""
+
+#: editor/plugins/particles_2d_editor_plugin.cpp
+msgid "Load Emission Mask"
+msgstr ""
+
+#: editor/plugins/particles_2d_editor_plugin.cpp
+#: editor/plugins/particles_editor_plugin.cpp
+msgid "Particles"
+msgstr ""
+
+#: editor/plugins/particles_2d_editor_plugin.cpp
+msgid "Generated Point Count:"
+msgstr ""
+
+#: editor/plugins/particles_2d_editor_plugin.cpp
+#: editor/plugins/particles_editor_plugin.cpp
+msgid "Generation Time (sec):"
+msgstr ""
+
+#: editor/plugins/particles_2d_editor_plugin.cpp
+msgid "Emission Mask"
+msgstr ""
+
+#: editor/plugins/particles_2d_editor_plugin.cpp
+msgid "Capture from Pixel"
+msgstr ""
+
+#: editor/plugins/particles_2d_editor_plugin.cpp
+msgid "Emission Colors"
+msgstr ""
+
+#: editor/plugins/particles_editor_plugin.cpp
+msgid "Node does not contain geometry."
+msgstr ""
+
+#: editor/plugins/particles_editor_plugin.cpp
+msgid "Node does not contain geometry (faces)."
+msgstr ""
+
+#: editor/plugins/particles_editor_plugin.cpp
+msgid "A processor material of type 'ParticlesMaterial' is required."
+msgstr ""
+
+#: editor/plugins/particles_editor_plugin.cpp
+msgid "Faces contain no area!"
+msgstr ""
+
+#: editor/plugins/particles_editor_plugin.cpp
+msgid "No faces!"
+msgstr ""
+
+#: editor/plugins/particles_editor_plugin.cpp
+msgid "Generate AABB"
+msgstr ""
+
+#: editor/plugins/particles_editor_plugin.cpp
+msgid "Create Emission Points From Mesh"
+msgstr ""
+
+#: editor/plugins/particles_editor_plugin.cpp
+msgid "Create Emission Points From Node"
+msgstr ""
+
+#: editor/plugins/particles_editor_plugin.cpp
+msgid "Clear Emitter"
+msgstr ""
+
+#: editor/plugins/particles_editor_plugin.cpp
+msgid "Create Emitter"
+msgstr ""
+
+#: editor/plugins/particles_editor_plugin.cpp
+msgid "Emission Points:"
+msgstr ""
+
+#: editor/plugins/particles_editor_plugin.cpp
+msgid "Surface Points"
+msgstr ""
+
+#: editor/plugins/particles_editor_plugin.cpp
+msgid "Surface Points+Normal (Directed)"
+msgstr ""
+
+#: editor/plugins/particles_editor_plugin.cpp
+msgid "Volume"
+msgstr ""
+
+#: editor/plugins/particles_editor_plugin.cpp
+msgid "Emission Source: "
+msgstr ""
+
+#: editor/plugins/particles_editor_plugin.cpp
+msgid "Generate Visibility AABB"
+msgstr ""
+
+#: editor/plugins/path_2d_editor_plugin.cpp
+msgid "Remove Point from Curve"
+msgstr ""
+
+#: editor/plugins/path_2d_editor_plugin.cpp
+msgid "Remove Out-Control from Curve"
+msgstr ""
+
+#: editor/plugins/path_2d_editor_plugin.cpp
+msgid "Remove In-Control from Curve"
+msgstr ""
+
+#: editor/plugins/path_2d_editor_plugin.cpp
+#: editor/plugins/path_editor_plugin.cpp
+msgid "Add Point to Curve"
+msgstr ""
+
+#: editor/plugins/path_2d_editor_plugin.cpp
+msgid "Move Point in Curve"
+msgstr ""
+
+#: editor/plugins/path_2d_editor_plugin.cpp
+msgid "Move In-Control in Curve"
+msgstr ""
+
+#: editor/plugins/path_2d_editor_plugin.cpp
+msgid "Move Out-Control in Curve"
+msgstr ""
+
+#: editor/plugins/path_2d_editor_plugin.cpp
+msgid "Select Control Points (Shift+Drag)"
+msgstr ""
+
+#: editor/plugins/path_2d_editor_plugin.cpp
+#: editor/plugins/path_editor_plugin.cpp
+msgid "Split Segment (in curve)"
+msgstr ""
+
+#: editor/plugins/path_2d_editor_plugin.cpp
+#: editor/plugins/path_editor_plugin.cpp
+msgid "Close Curve"
+msgstr ""
+
+#: editor/plugins/path_editor_plugin.cpp
+msgid "Curve Point #"
+msgstr ""
+
+#: editor/plugins/path_editor_plugin.cpp
+msgid "Set Curve Point Position"
+msgstr ""
+
+#: editor/plugins/path_editor_plugin.cpp
+msgid "Set Curve In Position"
+msgstr ""
+
+#: editor/plugins/path_editor_plugin.cpp
+msgid "Set Curve Out Position"
+msgstr ""
+
+#: editor/plugins/path_editor_plugin.cpp
+msgid "Split Path"
+msgstr ""
+
+#: editor/plugins/path_editor_plugin.cpp
+msgid "Remove Path Point"
+msgstr ""
+
+#: editor/plugins/path_editor_plugin.cpp
+msgid "Remove Out-Control Point"
+msgstr ""
+
+#: editor/plugins/path_editor_plugin.cpp
+msgid "Remove In-Control Point"
+msgstr ""
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Create UV Map"
+msgstr ""
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Transform UV Map"
+msgstr ""
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Polygon 2D UV Editor"
+msgstr ""
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Move Point"
+msgstr ""
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Ctrl: Rotate"
+msgstr ""
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Shift: Move All"
+msgstr ""
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Shift+Ctrl: Scale"
+msgstr ""
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Move Polygon"
+msgstr ""
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Rotate Polygon"
+msgstr ""
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Scale Polygon"
+msgstr ""
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Edit"
+msgstr ""
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Polygon->UV"
+msgstr ""
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "UV->Polygon"
+msgstr ""
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Clear UV"
+msgstr ""
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Snap"
+msgstr ""
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Enable Snap"
+msgstr ""
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Grid"
+msgstr ""
+
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+msgid "ERROR: Couldn't load resource!"
+msgstr ""
+
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+msgid "Add Resource"
+msgstr ""
+
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+msgid "Rename Resource"
+msgstr ""
+
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Delete Resource"
+msgstr ""
+
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+msgid "Resource clipboard is empty!"
+msgstr ""
+
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Load Resource"
+msgstr ""
+
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+msgid "Paste"
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Clear Recent Files"
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid ""
+"Close and save changes?\n"
+"\""
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Error while saving theme"
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Error saving"
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Error importing theme"
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Error importing"
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Import Theme"
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Save Theme As.."
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid " Class Reference"
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Next script"
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Previous script"
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "File"
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp editor/property_editor.cpp
+msgid "New"
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Save All"
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Soft Reload Script"
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "History Prev"
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "History Next"
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Reload Theme"
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Save Theme"
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Save Theme As"
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Close Docs"
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Close All"
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+msgid "Run"
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Toggle Scripts Panel"
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Find.."
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Find Next"
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
+msgid "Step Over"
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
+msgid "Step Into"
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
+msgid "Break"
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+#: editor/script_editor_debugger.cpp
+msgid "Continue"
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Keep Debugger Open"
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Debug with external editor"
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Open Godot online documentation"
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Search the class hierarchy."
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Search the reference documentation."
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Go to previous edited document."
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Go to next edited document."
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Discard"
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Create Script"
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid ""
+"The following files are newer on disk.\n"
+"What action should be taken?:"
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Reload"
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid "Resave"
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
+msgid "Debugger"
+msgstr ""
+
+#: editor/plugins/script_editor_plugin.cpp
+msgid ""
+"Built-in scripts can only be edited when the scene they belong to is loaded"
+msgstr ""
+
+#: editor/plugins/script_text_editor.cpp
+msgid "Only resources from filesystem can be dropped."
+msgstr ""
+
+#: editor/plugins/script_text_editor.cpp
+msgid "Pick Color"
+msgstr ""
+
+#: editor/plugins/script_text_editor.cpp
+msgid "Convert Case"
+msgstr ""
+
+#: editor/plugins/script_text_editor.cpp
+msgid "Uppercase"
+msgstr ""
+
+#: editor/plugins/script_text_editor.cpp
+msgid "Lowercase"
+msgstr ""
+
+#: editor/plugins/script_text_editor.cpp
+msgid "Capitalize"
+msgstr ""
+
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp scene/gui/line_edit.cpp
+#: scene/gui/text_edit.cpp
+msgid "Cut"
+msgstr ""
+
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+msgid "Copy"
+msgstr ""
+
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp scene/gui/line_edit.cpp
+#: scene/gui/text_edit.cpp
+msgid "Select All"
+msgstr ""
+
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+msgid "Move Up"
+msgstr ""
+
+#: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp
+msgid "Move Down"
+msgstr ""
+
+#: editor/plugins/script_text_editor.cpp
+msgid "Delete Line"
+msgstr ""
+
+#: editor/plugins/script_text_editor.cpp
+msgid "Indent Left"
+msgstr ""
+
+#: editor/plugins/script_text_editor.cpp
+msgid "Indent Right"
+msgstr ""
+
+#: editor/plugins/script_text_editor.cpp
+msgid "Toggle Comment"
+msgstr ""
+
+#: editor/plugins/script_text_editor.cpp
+msgid "Clone Down"
+msgstr ""
+
+#: editor/plugins/script_text_editor.cpp
+msgid "Complete Symbol"
+msgstr ""
+
+#: editor/plugins/script_text_editor.cpp
+msgid "Trim Trailing Whitespace"
+msgstr ""
+
+#: editor/plugins/script_text_editor.cpp
+msgid "Convert Indent To Spaces"
+msgstr ""
+
+#: editor/plugins/script_text_editor.cpp
+msgid "Convert Indent To Tabs"
+msgstr ""
+
+#: editor/plugins/script_text_editor.cpp
+msgid "Auto Indent"
+msgstr ""
+
+#: editor/plugins/script_text_editor.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Toggle Breakpoint"
+msgstr ""
+
+#: editor/plugins/script_text_editor.cpp
+msgid "Remove All Breakpoints"
+msgstr ""
+
+#: editor/plugins/script_text_editor.cpp
+msgid "Goto Next Breakpoint"
+msgstr ""
+
+#: editor/plugins/script_text_editor.cpp
+msgid "Goto Previous Breakpoint"
+msgstr ""
+
+#: editor/plugins/script_text_editor.cpp
+msgid "Convert To Uppercase"
+msgstr ""
+
+#: editor/plugins/script_text_editor.cpp
+msgid "Convert To Lowercase"
+msgstr ""
+
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Find Previous"
+msgstr ""
+
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Replace.."
+msgstr ""
+
+#: editor/plugins/script_text_editor.cpp
+msgid "Goto Function.."
+msgstr ""
+
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Goto Line.."
+msgstr ""
+
+#: editor/plugins/script_text_editor.cpp
+msgid "Contextual Help"
+msgstr ""
+
+#: editor/plugins/shader_editor_plugin.cpp
+msgid "Shader"
+msgstr ""
+
+#: editor/plugins/shader_graph_editor_plugin.cpp
+msgid "Change Scalar Constant"
+msgstr ""
+
+#: editor/plugins/shader_graph_editor_plugin.cpp
+msgid "Change Vec Constant"
+msgstr ""
+
+#: editor/plugins/shader_graph_editor_plugin.cpp
+msgid "Change RGB Constant"
+msgstr ""
+
+#: editor/plugins/shader_graph_editor_plugin.cpp
+msgid "Change Scalar Operator"
+msgstr ""
+
+#: editor/plugins/shader_graph_editor_plugin.cpp
+msgid "Change Vec Operator"
+msgstr ""
+
+#: editor/plugins/shader_graph_editor_plugin.cpp
+msgid "Change Vec Scalar Operator"
+msgstr ""
+
+#: editor/plugins/shader_graph_editor_plugin.cpp
+msgid "Change RGB Operator"
+msgstr ""
+
+#: editor/plugins/shader_graph_editor_plugin.cpp
+msgid "Toggle Rot Only"
+msgstr ""
+
+#: editor/plugins/shader_graph_editor_plugin.cpp
+msgid "Change Scalar Function"
+msgstr ""
+
+#: editor/plugins/shader_graph_editor_plugin.cpp
+msgid "Change Vec Function"
+msgstr ""
+
+#: editor/plugins/shader_graph_editor_plugin.cpp
+msgid "Change Scalar Uniform"
+msgstr ""
+
+#: editor/plugins/shader_graph_editor_plugin.cpp
+msgid "Change Vec Uniform"
+msgstr ""
+
+#: editor/plugins/shader_graph_editor_plugin.cpp
+msgid "Change RGB Uniform"
+msgstr ""
+
+#: editor/plugins/shader_graph_editor_plugin.cpp
+msgid "Change Default Value"
+msgstr ""
+
+#: editor/plugins/shader_graph_editor_plugin.cpp
+msgid "Change XForm Uniform"
+msgstr ""
+
+#: editor/plugins/shader_graph_editor_plugin.cpp
+msgid "Change Texture Uniform"
+msgstr ""
+
+#: editor/plugins/shader_graph_editor_plugin.cpp
+msgid "Change Cubemap Uniform"
+msgstr ""
+
+#: editor/plugins/shader_graph_editor_plugin.cpp
+msgid "Change Comment"
+msgstr ""
+
+#: editor/plugins/shader_graph_editor_plugin.cpp
+msgid "Add/Remove to Color Ramp"
+msgstr ""
+
+#: editor/plugins/shader_graph_editor_plugin.cpp
+msgid "Add/Remove to Curve Map"
+msgstr ""
+
+#: editor/plugins/shader_graph_editor_plugin.cpp
+msgid "Modify Curve Map"
+msgstr ""
+
+#: editor/plugins/shader_graph_editor_plugin.cpp
+msgid "Change Input Name"
+msgstr ""
+
+#: editor/plugins/shader_graph_editor_plugin.cpp
+msgid "Connect Graph Nodes"
+msgstr ""
+
+#: editor/plugins/shader_graph_editor_plugin.cpp
+msgid "Disconnect Graph Nodes"
+msgstr ""
+
+#: editor/plugins/shader_graph_editor_plugin.cpp
+msgid "Remove Shader Graph Node"
+msgstr ""
+
+#: editor/plugins/shader_graph_editor_plugin.cpp
+msgid "Move Shader Graph Node"
+msgstr ""
+
+#: editor/plugins/shader_graph_editor_plugin.cpp
+msgid "Duplicate Graph Node(s)"
+msgstr ""
+
+#: editor/plugins/shader_graph_editor_plugin.cpp
+msgid "Delete Shader Graph Node(s)"
+msgstr ""
+
+#: editor/plugins/shader_graph_editor_plugin.cpp
+msgid "Error: Cyclic Connection Link"
+msgstr ""
+
+#: editor/plugins/shader_graph_editor_plugin.cpp
+msgid "Error: Missing Input Connections"
+msgstr ""
+
+#: editor/plugins/shader_graph_editor_plugin.cpp
+msgid "Add Shader Graph Node"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Orthogonal"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Perspective"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Transform Aborted."
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "X-Axis Transform."
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Y-Axis Transform."
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Z-Axis Transform."
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "View Plane Transform."
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Rotating %s degrees."
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Bottom View."
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Bottom"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Top View."
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Rear View."
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Rear"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Front View."
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Front"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Left View."
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Left"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Right View."
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Right"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Keying is disabled (no key inserted)."
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Animation Key Inserted."
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Objects Drawn"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Material Changes"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Shader Changes"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Surface Changes"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Draw Calls"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Vertices"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Align with view"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Display Normal"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Display Wireframe"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Display Overdraw"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Display Unshaded"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "View Environment"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "View Gizmos"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "View Information"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Audio Listener"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Doppler Enable"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Freelook Left"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Freelook Right"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Freelook Forward"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Freelook Backwards"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Freelook Up"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Freelook Down"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Freelook Speed Modifier"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "preview"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "XForm Dialog"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Select Mode (Q)\n"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid ""
+"Drag: Rotate\n"
+"Alt+Drag: Move\n"
+"Alt+RMB: Depth list selection"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Move Mode (W)"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Rotate Mode (E)"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Scale Mode (R)"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Bottom View"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Top View"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Rear View"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Front View"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Left View"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Right View"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Switch Perspective/Orthogonal view"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Insert Animation Key"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Focus Origin"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Focus Selection"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Align Selection With View"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Tool Select"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Tool Move"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Tool Rotate"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Tool Scale"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Transform"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Configure Snap.."
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Local Coords"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Transform Dialog.."
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "1 Viewport"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "2 Viewports"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "2 Viewports (Alt)"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "3 Viewports"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "3 Viewports (Alt)"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "4 Viewports"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "View Origin"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "View Grid"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "Settings"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Snap Settings"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Translate Snap:"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Rotate Snap (deg.):"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Scale Snap (%):"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Viewport Settings"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Perspective FOV (deg.):"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "View Z-Near:"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "View Z-Far:"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Transform Change"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Translate:"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Rotate (deg.):"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Scale (ratio):"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Transform Type"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Pre"
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Post"
+msgstr ""
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "ERROR: Couldn't load frame resource!"
+msgstr ""
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Add Frame"
+msgstr ""
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Resource clipboard is empty or not a texture!"
+msgstr ""
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Paste Frame"
+msgstr ""
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Add Empty"
+msgstr ""
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Change Animation Loop"
+msgstr ""
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Change Animation FPS"
+msgstr ""
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "(empty)"
+msgstr ""
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Animations"
+msgstr ""
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Speed (FPS):"
+msgstr ""
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Loop"
+msgstr ""
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Animation Frames"
+msgstr ""
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Insert Empty (Before)"
+msgstr ""
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Insert Empty (After)"
+msgstr ""
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Move (Before)"
+msgstr ""
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Move (After)"
+msgstr ""
+
+#: editor/plugins/style_box_editor_plugin.cpp
+msgid "StyleBox Preview:"
+msgstr ""
+
+#: editor/plugins/texture_region_editor_plugin.cpp
+msgid "Set Region Rect"
+msgstr ""
+
+#: editor/plugins/texture_region_editor_plugin.cpp
+msgid "Snap Mode:"
+msgstr ""
+
+#: editor/plugins/texture_region_editor_plugin.cpp
+msgid "<None>"
+msgstr ""
+
+#: editor/plugins/texture_region_editor_plugin.cpp
+msgid "Pixel Snap"
+msgstr ""
+
+#: editor/plugins/texture_region_editor_plugin.cpp
+msgid "Grid Snap"
+msgstr ""
+
+#: editor/plugins/texture_region_editor_plugin.cpp
+msgid "Auto Slice"
+msgstr ""
+
+#: editor/plugins/texture_region_editor_plugin.cpp
+msgid "Offset:"
+msgstr ""
+
+#: editor/plugins/texture_region_editor_plugin.cpp
+msgid "Step:"
+msgstr ""
+
+#: editor/plugins/texture_region_editor_plugin.cpp
+msgid "Separation:"
+msgstr ""
+
+#: editor/plugins/texture_region_editor_plugin.cpp
+msgid "Texture Region"
+msgstr ""
+
+#: editor/plugins/texture_region_editor_plugin.cpp
+msgid "Texture Region Editor"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Can't save theme to file:"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Add All Items"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Add All"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Remove Item"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Remove All Items"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Remove All"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Edit theme.."
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Theme editing menu."
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Add Class Items"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Remove Class Items"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Create Empty Template"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Create Empty Editor Template"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "CheckBox Radio1"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "CheckBox Radio2"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Item"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Check Item"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Checked Item"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Has"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Many"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp editor/project_export.cpp
+msgid "Options"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Have,Many,Several,Options!"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Tab 1"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Tab 2"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Tab 3"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp
+#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp
+msgid "Type:"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Data Type:"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Icon"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Style"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Font"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Color"
+msgstr ""
+
+#: editor/plugins/tile_map_editor_plugin.cpp
+msgid "Erase Selection"
+msgstr ""
+
+#: editor/plugins/tile_map_editor_plugin.cpp
+msgid "Paint TileMap"
+msgstr ""
+
+#: editor/plugins/tile_map_editor_plugin.cpp
+msgid "Line Draw"
+msgstr ""
+
+#: editor/plugins/tile_map_editor_plugin.cpp
+msgid "Rectangle Paint"
+msgstr ""
+
+#: editor/plugins/tile_map_editor_plugin.cpp
+msgid "Bucket Fill"
+msgstr ""
+
+#: editor/plugins/tile_map_editor_plugin.cpp
+msgid "Erase TileMap"
+msgstr ""
+
+#: editor/plugins/tile_map_editor_plugin.cpp
+msgid "Erase selection"
+msgstr ""
+
+#: editor/plugins/tile_map_editor_plugin.cpp
+msgid "Find tile"
+msgstr ""
+
+#: editor/plugins/tile_map_editor_plugin.cpp
+msgid "Transpose"
+msgstr ""
+
+#: editor/plugins/tile_map_editor_plugin.cpp
+msgid "Mirror X"
+msgstr ""
+
+#: editor/plugins/tile_map_editor_plugin.cpp
+msgid "Mirror Y"
+msgstr ""
+
+#: editor/plugins/tile_map_editor_plugin.cpp
+msgid "Paint Tile"
+msgstr ""
+
+#: editor/plugins/tile_map_editor_plugin.cpp
+msgid "Pick Tile"
+msgstr ""
+
+#: editor/plugins/tile_map_editor_plugin.cpp
+msgid "Rotate 0 degrees"
+msgstr ""
+
+#: editor/plugins/tile_map_editor_plugin.cpp
+msgid "Rotate 90 degrees"
+msgstr ""
+
+#: editor/plugins/tile_map_editor_plugin.cpp
+msgid "Rotate 180 degrees"
+msgstr ""
+
+#: editor/plugins/tile_map_editor_plugin.cpp
+msgid "Rotate 270 degrees"
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Could not find tile:"
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Item name or ID:"
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Create from scene?"
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Merge from scene?"
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Create from Scene"
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp
+msgid "Merge from Scene"
+msgstr ""
+
+#: editor/plugins/tile_set_editor_plugin.cpp editor/script_editor_debugger.cpp
+msgid "Error"
+msgstr ""
+
+#: editor/project_export.cpp
+msgid "Runnable"
+msgstr ""
+
+#: editor/project_export.cpp
+msgid "Delete patch '"
+msgstr ""
+
+#: editor/project_export.cpp
+msgid "Delete preset '%s'?"
+msgstr ""
+
+#: editor/project_export.cpp
+msgid "Export templates for this platform are missing/corrupted: "
+msgstr ""
+
+#: editor/project_export.cpp
+msgid "Presets"
+msgstr ""
+
+#: editor/project_export.cpp editor/project_settings_editor.cpp
+msgid "Add.."
+msgstr ""
+
+#: editor/project_export.cpp
+msgid "Resources"
+msgstr ""
+
+#: editor/project_export.cpp
+msgid "Export all resources in the project"
+msgstr ""
+
+#: editor/project_export.cpp
+msgid "Export selected scenes (and dependencies)"
+msgstr ""
+
+#: editor/project_export.cpp
+msgid "Export selected resources (and dependencies)"
+msgstr ""
+
+#: editor/project_export.cpp
+msgid "Export Mode:"
+msgstr ""
+
+#: editor/project_export.cpp
+msgid "Resources to export:"
+msgstr ""
+
+#: editor/project_export.cpp
+msgid ""
+"Filters to export non-resource files (comma separated, e.g: *.json, *.txt)"
+msgstr ""
+
+#: editor/project_export.cpp
+msgid ""
+"Filters to exclude files from project (comma separated, e.g: *.json, *.txt)"
+msgstr ""
+
+#: editor/project_export.cpp
+msgid "Patches"
+msgstr ""
+
+#: editor/project_export.cpp
+msgid "Make Patch"
+msgstr ""
+
+#: editor/project_export.cpp
+msgid "Features"
+msgstr ""
+
+#: editor/project_export.cpp
+msgid "Custom (comma-separated):"
+msgstr ""
+
+#: editor/project_export.cpp
+msgid "Feature List:"
+msgstr ""
+
+#: editor/project_export.cpp
+msgid "Export PCK/Zip"
+msgstr ""
+
+#: editor/project_export.cpp
+msgid "Export templates for this platform are missing:"
+msgstr ""
+
+#: editor/project_export.cpp
+msgid "Export templates for this platform are missing/corrupted:"
+msgstr ""
+
+#: editor/project_export.cpp
+msgid "Export With Debug"
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "The path does not exist."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Please choose a 'project.godot' file."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid ""
+"Your project will be created in a non empty folder (you might want to create "
+"a new folder)."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Please choose a folder that does not contain a 'project.godot' file."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Imported Project"
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid " "
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "It would be a good idea to name your project."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Invalid project path (changed anything?)."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Couldn't get project.godot in project path."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Couldn't edit project.godot in project path."
+msgstr ""
+
+#: editor/project_manager.cpp
+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 ""
+
+#: editor/project_manager.cpp
+msgid "Couldn't get project.godot in the project path."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "New Game Project"
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Import Existing Project"
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Create New Project"
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Install Project:"
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Project Name:"
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Create folder"
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Project Path:"
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Browse"
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "That's a BINGO!"
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Unnamed Project"
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Can't open project"
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Are you sure to open more than one project?"
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid ""
+"Can't run project: no main scene defined.\n"
+"Please edit the project and set the main scene in \"Project Settings\" under "
+"the \"Application\" category."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid ""
+"Can't run project: Assets need to be imported.\n"
+"Please edit the project to trigger the initial import."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Are you sure to run more than one project?"
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Remove project from the list? (Folder contents will not be modified)"
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid ""
+"Language changed.\n"
+"The UI will update next time the editor or project manager starts."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid ""
+"You are about the scan %s folders for existing Godot projects. Do you "
+"confirm?"
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Project List"
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Scan"
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Select a Folder to Scan"
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "New Project"
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Templates"
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Exit"
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Restart Now"
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Can't run project"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Key "
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Joy Button"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Joy Axis"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Mouse Button"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Invalid action (anything goes but '/' or ':')."
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Action '%s' already exists!"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Rename Input Action Event"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Add Input Action Event"
+msgstr ""
+
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Meta+"
+msgstr ""
+
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Shift+"
+msgstr ""
+
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Alt+"
+msgstr ""
+
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Control+"
+msgstr ""
+
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "Press a Key.."
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Mouse Button Index:"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Left Button"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Right Button"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Middle Button"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Wheel Up Button"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Wheel Down Button"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Button 6"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Button 7"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Button 8"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Button 9"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Change"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Joypad Axis Index:"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Axis"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Joypad Button Index:"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Add Input Action"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Erase Input Action Event"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Add Event"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Device"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Button"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Left Button."
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Right Button."
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Middle Button."
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Wheel Up."
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Wheel Down."
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Add Global Property"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Select a setting item first!"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "No property '"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Setting '"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Delete Item"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Can't contain '/' or ':'"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Already existing"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Error saving settings."
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Settings saved OK."
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Override for Feature"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Add Translation"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Remove Translation"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Add Remapped Path"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Resource Remap Add Remap"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Change Resource Remap Language"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Remove Resource Remap"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Remove Resource Remap Option"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Changed Locale Filter"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Changed Locale Filter Mode"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Project Settings (project.godot)"
+msgstr ""
+
+#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
+msgid "General"
+msgstr ""
+
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+msgid "Property:"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Override For.."
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Input Map"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Action:"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Device:"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Index:"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Localization"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Translations"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Translations:"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Remaps"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Resources:"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Remaps by Locale:"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Locale"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Locales Filter"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Show all locales"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Show only selected locales"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Filter mode:"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Locales:"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "AutoLoad"
+msgstr ""
+
+#: editor/property_editor.cpp
+msgid "Pick a Viewport"
+msgstr ""
+
+#: editor/property_editor.cpp
+msgid "Ease In"
+msgstr ""
+
+#: editor/property_editor.cpp
+msgid "Ease Out"
+msgstr ""
+
+#: editor/property_editor.cpp
+msgid "Zero"
+msgstr ""
+
+#: editor/property_editor.cpp
+msgid "Easing In-Out"
+msgstr ""
+
+#: editor/property_editor.cpp
+msgid "Easing Out-In"
+msgstr ""
+
+#: editor/property_editor.cpp
+msgid "File.."
+msgstr ""
+
+#: editor/property_editor.cpp
+msgid "Dir.."
+msgstr ""
+
+#: editor/property_editor.cpp
+msgid "Assign"
+msgstr ""
+
+#: editor/property_editor.cpp
+msgid "Select Node"
+msgstr ""
+
+#: editor/property_editor.cpp
+msgid "New Script"
+msgstr ""
+
+#: editor/property_editor.cpp
+msgid "Make Unique"
+msgstr ""
+
+#: editor/property_editor.cpp
+msgid "Show in File System"
+msgstr ""
+
+#: editor/property_editor.cpp
+msgid "Convert To %s"
+msgstr ""
+
+#: editor/property_editor.cpp
+msgid "Error loading file: Not a resource!"
+msgstr ""
+
+#: editor/property_editor.cpp
+msgid "Selected node is not a Viewport!"
+msgstr ""
+
+#: editor/property_editor.cpp
+msgid "Pick a Node"
+msgstr ""
+
+#: editor/property_editor.cpp
+msgid "Bit %d, val %d."
+msgstr ""
+
+#: editor/property_editor.cpp
+msgid "On"
+msgstr ""
+
+#: editor/property_editor.cpp modules/visual_script/visual_script_editor.cpp
+msgid "Set"
+msgstr ""
+
+#: editor/property_editor.cpp
+msgid "Properties:"
+msgstr ""
+
+#: editor/property_editor.cpp
+msgid "Sections:"
+msgstr ""
+
+#: editor/property_selector.cpp
+msgid "Select Property"
+msgstr ""
+
+#: editor/property_selector.cpp
+msgid "Select Virtual Method"
+msgstr ""
+
+#: editor/property_selector.cpp
+msgid "Select Method"
+msgstr ""
+
+#: editor/pvrtc_compress.cpp
+msgid "Could not execute PVRTC tool:"
+msgstr ""
+
+#: editor/pvrtc_compress.cpp
+msgid "Can't load back converted image using PVRTC tool:"
+msgstr ""
+
+#: editor/reparent_dialog.cpp editor/scene_tree_dock.cpp
+msgid "Reparent Node"
+msgstr ""
+
+#: editor/reparent_dialog.cpp
+msgid "Reparent Location (Select new Parent):"
+msgstr ""
+
+#: editor/reparent_dialog.cpp
+msgid "Keep Global Transform"
+msgstr ""
+
+#: editor/reparent_dialog.cpp editor/scene_tree_dock.cpp
+msgid "Reparent"
+msgstr ""
+
+#: editor/run_settings_dialog.cpp
+msgid "Run Mode:"
+msgstr ""
+
+#: editor/run_settings_dialog.cpp
+msgid "Current Scene"
+msgstr ""
+
+#: editor/run_settings_dialog.cpp
+msgid "Main Scene"
+msgstr ""
+
+#: editor/run_settings_dialog.cpp
+msgid "Main Scene Arguments:"
+msgstr ""
+
+#: editor/run_settings_dialog.cpp
+msgid "Scene Run Settings"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp editor/script_create_dialog.cpp
+#: scene/gui/dialogs.cpp
+msgid "OK"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "No parent to instance the scenes at."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Error loading scene from %s"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Ok"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid ""
+"Cannot instance the scene '%s' because the current scene exists within one "
+"of its nodes."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Instance Scene(s)"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "This operation can't be done on the tree root."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Move Node In Parent"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Move Nodes In Parent"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Duplicate Node(s)"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Delete Node(s)?"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Can not perform with the root node."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "This operation can't be done on instanced scenes."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Save New Scene As.."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Editable Children"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Load As Placeholder"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Discard Instancing"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Makes Sense!"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Can't operate on nodes from a foreign scene!"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Can't operate on nodes the current scene inherits from!"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Remove Node(s)"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid ""
+"Couldn't save new scene. Likely dependencies (instances) couldn't be "
+"satisfied."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Error saving scene."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Error duplicating scene to save it."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Sub-Resources:"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Clear Inheritance"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp
+msgid "Open in Editor"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Delete Node(s)"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Add Child Node"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Instance Child Scene"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Change Type"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Attach Script"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Clear Script"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Merge From Scene"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Save Branch as Scene"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Copy Node Path"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Delete (No Confirm)"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Add/Create a New Node"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid ""
+"Instance a scene file as a Node. Creates an inherited scene if no root node "
+"exists."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Filter nodes"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Attach a new or existing script for the selected node."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Clear a script for the selected node."
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Clear Inheritance? (No Undo!)"
+msgstr ""
+
+#: editor/scene_tree_dock.cpp
+msgid "Clear!"
+msgstr ""
+
+#: editor/scene_tree_editor.cpp
+msgid "Toggle Spatial Visible"
+msgstr ""
+
+#: editor/scene_tree_editor.cpp
+msgid "Toggle CanvasItem Visible"
+msgstr ""
+
+#: editor/scene_tree_editor.cpp
+msgid "Node configuration warning:"
+msgstr ""
+
+#: editor/scene_tree_editor.cpp
+msgid ""
+"Node has connection(s) and group(s)\n"
+"Click to show signals dock."
+msgstr ""
+
+#: editor/scene_tree_editor.cpp
+msgid ""
+"Node has connections.\n"
+"Click to show signals dock."
+msgstr ""
+
+#: editor/scene_tree_editor.cpp
+msgid ""
+"Node is in group(s).\n"
+"Click to show groups dock."
+msgstr ""
+
+#: editor/scene_tree_editor.cpp
+msgid "Instance:"
+msgstr ""
+
+#: editor/scene_tree_editor.cpp
+msgid "Open script"
+msgstr ""
+
+#: editor/scene_tree_editor.cpp
+msgid ""
+"Node is locked.\n"
+"Click to unlock"
+msgstr ""
+
+#: editor/scene_tree_editor.cpp
+msgid ""
+"Children are not selectable.\n"
+"Click to make selectable"
+msgstr ""
+
+#: editor/scene_tree_editor.cpp
+msgid "Toggle Visibility"
+msgstr ""
+
+#: editor/scene_tree_editor.cpp
+msgid "Invalid node name, the following characters are not allowed:"
+msgstr ""
+
+#: editor/scene_tree_editor.cpp
+msgid "Rename Node"
+msgstr ""
+
+#: editor/scene_tree_editor.cpp
+msgid "Scene Tree (Nodes):"
+msgstr ""
+
+#: editor/scene_tree_editor.cpp
+msgid "Node Configuration Warning!"
+msgstr ""
+
+#: editor/scene_tree_editor.cpp
+msgid "Select a Node"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
+msgid "Error loading template '%s'"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
+msgid "Error - Could not create script in filesystem."
+msgstr ""
+
+#: editor/script_create_dialog.cpp
+msgid "Error loading script from %s"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
+msgid "N/A"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
+msgid "Path is empty"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
+msgid "Path is not local"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
+msgid "Invalid base path"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
+msgid "Directory of the same name exists"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
+msgid "File exists, will be reused"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
+msgid "Invalid extension"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
+msgid "Wrong extension chosen"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
+msgid "Invalid Path"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
+msgid "Invalid class name"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
+msgid "Invalid inherited parent name or path"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
+msgid "Script valid"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
+msgid "Allowed: a-z, A-Z, 0-9 and _"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
+msgid "Built-in script (into scene file)"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
+msgid "Create new script file"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
+msgid "Load existing script file"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
+msgid "Language"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
+msgid "Inherits"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
+msgid "Class Name"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
+msgid "Template"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
+msgid "Built-in Script"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
+msgid "Attach Node Script"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
+msgid "Bytes:"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
+msgid "Warning"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
+msgid "Error:"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
+msgid "Source:"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
+msgid "Function:"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
+msgid "Pick one or more items from the list to display the graph."
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
+msgid "Errors"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
+msgid "Child Process Connected"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
+msgid "Inspect Previous Instance"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
+msgid "Inspect Next Instance"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
+msgid "Stack Frames"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
+msgid "Variable"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
+msgid "Errors:"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
+msgid "Stack Trace (if applicable):"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
+msgid "Remote Inspector"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
+msgid "Live Scene Tree:"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
+msgid "Remote Object Properties: "
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
+msgid "Profiler"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
+msgid "Monitor"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
+msgid "Value"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
+msgid "Monitors"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
+msgid "List of Video Memory Usage by Resource:"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
+msgid "Total:"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
+msgid "Video Mem"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
+msgid "Resource Path"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
+msgid "Type"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
+msgid "Format"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
+msgid "Usage"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
+msgid "Misc"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
+msgid "Clicked Control:"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
+msgid "Clicked Control Type:"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
+msgid "Live Edit Root:"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
+msgid "Set From Tree"
+msgstr ""
+
+#: editor/settings_config_dialog.cpp
+msgid "Shortcuts"
+msgstr ""
+
+#: editor/spatial_editor_gizmos.cpp
+msgid "Change Light Radius"
+msgstr ""
+
+#: editor/spatial_editor_gizmos.cpp
+msgid "Change AudioStreamPlayer3D Emission Angle"
+msgstr ""
+
+#: editor/spatial_editor_gizmos.cpp
+msgid "Change Camera FOV"
+msgstr ""
+
+#: editor/spatial_editor_gizmos.cpp
+msgid "Change Camera Size"
+msgstr ""
+
+#: editor/spatial_editor_gizmos.cpp
+msgid "Change Sphere Shape Radius"
+msgstr ""
+
+#: editor/spatial_editor_gizmos.cpp
+msgid "Change Box Shape Extents"
+msgstr ""
+
+#: editor/spatial_editor_gizmos.cpp
+msgid "Change Capsule Shape Radius"
+msgstr ""
+
+#: editor/spatial_editor_gizmos.cpp
+msgid "Change Capsule Shape Height"
+msgstr ""
+
+#: editor/spatial_editor_gizmos.cpp
+msgid "Change Ray Shape Length"
+msgstr ""
+
+#: editor/spatial_editor_gizmos.cpp
+msgid "Change Notifier Extents"
+msgstr ""
+
+#: editor/spatial_editor_gizmos.cpp
+msgid "Change Particles AABB"
+msgstr ""
+
+#: editor/spatial_editor_gizmos.cpp
+msgid "Change Probe Extents"
+msgstr ""
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Library"
+msgstr ""
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Status"
+msgstr ""
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Libraries: "
+msgstr ""
+
+#: modules/gdnative/register_types.cpp
+msgid "GDNative"
+msgstr ""
+
+#: modules/gdscript/gd_functions.cpp
+#: modules/visual_script/visual_script_builtin_funcs.cpp
+msgid "Invalid type argument to convert(), use TYPE_* constants."
+msgstr ""
+
+#: modules/gdscript/gd_functions.cpp modules/mono/glue/glue_header.h
+#: modules/visual_script/visual_script_builtin_funcs.cpp
+msgid "Not enough bytes for decoding bytes, or invalid format."
+msgstr ""
+
+#: modules/gdscript/gd_functions.cpp
+msgid "step argument is zero!"
+msgstr ""
+
+#: modules/gdscript/gd_functions.cpp
+msgid "Not a script with an instance"
+msgstr ""
+
+#: modules/gdscript/gd_functions.cpp
+msgid "Not based on a script"
+msgstr ""
+
+#: modules/gdscript/gd_functions.cpp
+msgid "Not based on a resource file"
+msgstr ""
+
+#: modules/gdscript/gd_functions.cpp
+msgid "Invalid instance dictionary format (missing @path)"
+msgstr ""
+
+#: modules/gdscript/gd_functions.cpp
+msgid "Invalid instance dictionary format (can't load script at @path)"
+msgstr ""
+
+#: modules/gdscript/gd_functions.cpp
+msgid "Invalid instance dictionary format (invalid script at @path)"
+msgstr ""
+
+#: modules/gdscript/gd_functions.cpp
+msgid "Invalid instance dictionary (invalid subclasses)"
+msgstr ""
+
+#: modules/gdscript/gd_functions.cpp
+msgid "Object can't provide a length."
+msgstr ""
+
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "GridMap Delete Selection"
+msgstr ""
+
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "GridMap Duplicate Selection"
+msgstr ""
+
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "Snap View"
+msgstr ""
+
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "Prev Level (%sDown Wheel)"
+msgstr ""
+
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "Next Level (%sUp Wheel)"
+msgstr ""
+
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "Clip Disabled"
+msgstr ""
+
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "Clip Above"
+msgstr ""
+
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "Clip Below"
+msgstr ""
+
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "Edit X Axis"
+msgstr ""
+
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "Edit Y Axis"
+msgstr ""
+
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "Edit Z Axis"
+msgstr ""
+
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "Cursor Rotate X"
+msgstr ""
+
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "Cursor Rotate Y"
+msgstr ""
+
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "Cursor Rotate Z"
+msgstr ""
+
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "Cursor Back Rotate X"
+msgstr ""
+
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "Cursor Back Rotate Y"
+msgstr ""
+
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "Cursor Back Rotate Z"
+msgstr ""
+
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "Cursor Clear Rotation"
+msgstr ""
+
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "Create Area"
+msgstr ""
+
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "Create Exterior Connector"
+msgstr ""
+
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "Erase Area"
+msgstr ""
+
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "Selection -> Duplicate"
+msgstr ""
+
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "Selection -> Clear"
+msgstr ""
+
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "GridMap Settings"
+msgstr ""
+
+#: modules/gridmap/grid_map_editor_plugin.cpp
+msgid "Pick Distance:"
+msgstr ""
+
+#: modules/mono/editor/mono_bottom_panel.cpp
+msgid "Builds"
+msgstr ""
+
+#: modules/visual_script/visual_script.cpp
+msgid ""
+"A node yielded without working memory, please read the docs on how to yield "
+"properly!"
+msgstr ""
+
+#: modules/visual_script/visual_script.cpp
+msgid ""
+"Node yielded, but did not return a function state in the first working "
+"memory."
+msgstr ""
+
+#: modules/visual_script/visual_script.cpp
+msgid ""
+"Return value must be assigned to first element of node working memory! Fix "
+"your node please."
+msgstr ""
+
+#: modules/visual_script/visual_script.cpp
+msgid "Node returned an invalid sequence output: "
+msgstr ""
+
+#: modules/visual_script/visual_script.cpp
+msgid "Found sequence bit but not the node in the stack, report bug!"
+msgstr ""
+
+#: modules/visual_script/visual_script.cpp
+msgid "Stack overflow with stack depth: "
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Change Signal Arguments"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Change Argument Type"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Change Argument name"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Set Variable Default Value"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Set Variable Type"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Functions:"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Variables:"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Name is not a valid identifier:"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Name already in use by another func/var/signal:"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Rename Function"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Rename Variable"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Rename Signal"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Add Function"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Add Variable"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Add Signal"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Change Expression"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Add Node"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Remove VisualScript Nodes"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Duplicate VisualScript Nodes"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Hold Meta to drop a Getter. Hold Shift to drop a generic signature."
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Hold Ctrl to drop a Getter. Hold Shift to drop a generic signature."
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Hold Meta to drop a simple reference to the node."
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Hold Ctrl to drop a simple reference to the node."
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Hold Meta to drop a Variable Setter."
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Hold Ctrl to drop a Variable Setter."
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Add Preload Node"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Add Node(s) From Tree"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Add Getter Property"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Add Setter Property"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Change Base Type"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Move Node(s)"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Remove VisualScript Node"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Connect Nodes"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Condition"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Sequence"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Switch"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Iterator"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "While"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Return"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Call"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Get"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Script already has function '%s'"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Change Input Value"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Can't copy the function node."
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Clipboard is empty!"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Paste VisualScript Nodes"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Remove Function"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Edit Variable"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Remove Variable"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Edit Signal"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Remove Signal"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Editing Variable:"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Editing Signal:"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Base Type:"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Available Nodes:"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Select or create a function to edit graph"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Edit Signal Arguments:"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Edit Variable:"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Delete Selected"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Find Node Type"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Copy Nodes"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Cut Nodes"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Paste Nodes"
+msgstr ""
+
+#: modules/visual_script/visual_script_flow_control.cpp
+msgid "Input type not iterable: "
+msgstr ""
+
+#: modules/visual_script/visual_script_flow_control.cpp
+msgid "Iterator became invalid"
+msgstr ""
+
+#: modules/visual_script/visual_script_flow_control.cpp
+msgid "Iterator became invalid: "
+msgstr ""
+
+#: modules/visual_script/visual_script_func_nodes.cpp
+msgid "Invalid index property name."
+msgstr ""
+
+#: modules/visual_script/visual_script_func_nodes.cpp
+msgid "Base object is not a Node!"
+msgstr ""
+
+#: modules/visual_script/visual_script_func_nodes.cpp
+msgid "Path does not lead Node!"
+msgstr ""
+
+#: modules/visual_script/visual_script_func_nodes.cpp
+msgid "Invalid index property name '%s' in node %s."
+msgstr ""
+
+#: modules/visual_script/visual_script_nodes.cpp
+msgid ": Invalid argument of type: "
+msgstr ""
+
+#: modules/visual_script/visual_script_nodes.cpp
+msgid ": Invalid arguments: "
+msgstr ""
+
+#: modules/visual_script/visual_script_nodes.cpp
+msgid "VariableGet not found in script: "
+msgstr ""
+
+#: modules/visual_script/visual_script_nodes.cpp
+msgid "VariableSet not found in script: "
+msgstr ""
+
+#: modules/visual_script/visual_script_nodes.cpp
+msgid "Custom node has no _step() method, can't process graph."
+msgstr ""
+
+#: modules/visual_script/visual_script_nodes.cpp
+msgid ""
+"Invalid return value from _step(), must be integer (seq out), or string "
+"(error)."
+msgstr ""
+
+#: platform/javascript/export/export.cpp
+msgid "Run in Browser"
+msgstr ""
+
+#: platform/javascript/export/export.cpp
+msgid "Run exported HTML in the system's default browser."
+msgstr ""
+
+#: platform/javascript/export/export.cpp
+msgid "Could not write file:\n"
+msgstr ""
+
+#: platform/javascript/export/export.cpp
+msgid "Could not read file:\n"
+msgstr ""
+
+#: platform/javascript/export/export.cpp
+msgid "Could not open template for export:\n"
+msgstr ""
+
+#: scene/2d/animated_sprite.cpp
+msgid ""
+"A SpriteFrames resource must be created or set in the 'Frames' property in "
+"order for AnimatedSprite to display frames."
+msgstr ""
+
+#: scene/2d/canvas_modulate.cpp
+msgid ""
+"Only one visible CanvasModulate is allowed per scene (or set of instanced "
+"scenes). The first created one will work, while the rest will be ignored."
+msgstr ""
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid ""
+"CollisionPolygon2D only serves to provide a collision shape to a "
+"CollisionObject2D derived node. Please only use it as a child of Area2D, "
+"StaticBody2D, RigidBody2D, KinematicBody2D, etc. to give them a shape."
+msgstr ""
+
+#: scene/2d/collision_polygon_2d.cpp
+msgid "An empty CollisionPolygon2D has no effect on collision."
+msgstr ""
+
+#: scene/2d/collision_shape_2d.cpp
+msgid ""
+"CollisionShape2D only serves to provide a collision shape to a "
+"CollisionObject2D derived node. Please only use it as a child of Area2D, "
+"StaticBody2D, RigidBody2D, KinematicBody2D, etc. to give them a shape."
+msgstr ""
+
+#: scene/2d/collision_shape_2d.cpp
+msgid ""
+"A shape must be provided for CollisionShape2D to function. Please create a "
+"shape resource for it!"
+msgstr ""
+
+#: scene/2d/light_2d.cpp
+msgid ""
+"A texture with the shape of the light must be supplied to the 'texture' "
+"property."
+msgstr ""
+
+#: scene/2d/light_occluder_2d.cpp
+msgid ""
+"An occluder polygon must be set (or drawn) for this occluder to take effect."
+msgstr ""
+
+#: scene/2d/light_occluder_2d.cpp
+msgid "The occluder polygon for this occluder is empty. Please draw a polygon!"
+msgstr ""
+
+#: scene/2d/navigation_polygon.cpp
+msgid ""
+"A NavigationPolygon resource must be set or created for this node to work. "
+"Please set a property or draw a polygon."
+msgstr ""
+
+#: scene/2d/navigation_polygon.cpp
+msgid ""
+"NavigationPolygonInstance must be a child or grandchild to a Navigation2D "
+"node. It only provides navigation data."
+msgstr ""
+
+#: scene/2d/parallax_layer.cpp
+msgid ""
+"ParallaxLayer node only works when set as child of a ParallaxBackground node."
+msgstr ""
+
+#: scene/2d/particles_2d.cpp scene/3d/particles.cpp
+msgid ""
+"A material to process the particles is not assigned, so no behavior is "
+"imprinted."
+msgstr ""
+
+#: scene/2d/path_2d.cpp
+msgid "PathFollow2D only works when set as a child of a Path2D node."
+msgstr ""
+
+#: scene/2d/physics_body_2d.cpp
+msgid ""
+"Size changes to RigidBody2D (in character or rigid modes) will be overriden "
+"by the physics engine when running.\n"
+"Change the size in children collision shapes instead."
+msgstr ""
+
+#: scene/2d/remote_transform_2d.cpp
+msgid "Path property must point to a valid Node2D node to work."
+msgstr ""
+
+#: scene/2d/sprite.cpp
+msgid ""
+"Path property must point to a valid Viewport node to work. Such Viewport "
+"must be set to 'render target' mode."
+msgstr ""
+
+#: scene/2d/sprite.cpp
+msgid ""
+"The Viewport set in the path property must be set as 'render target' in "
+"order for this sprite to work."
+msgstr ""
+
+#: scene/2d/visibility_notifier_2d.cpp
+msgid ""
+"VisibilityEnable2D works best when used with the edited scene root directly "
+"as parent."
+msgstr ""
+
+#: scene/3d/arvr_nodes.cpp
+msgid "ARVRCamera must have an ARVROrigin node as its parent"
+msgstr ""
+
+#: scene/3d/arvr_nodes.cpp
+msgid "ARVRController must have an ARVROrigin node as its parent"
+msgstr ""
+
+#: scene/3d/arvr_nodes.cpp
+msgid ""
+"The controller id must not be 0 or this controller will not be bound to an "
+"actual controller"
+msgstr ""
+
+#: scene/3d/arvr_nodes.cpp
+msgid "ARVRAnchor must have an ARVROrigin node as its parent"
+msgstr ""
+
+#: scene/3d/arvr_nodes.cpp
+msgid ""
+"The anchor id must not be 0 or this anchor will not be bound to an actual "
+"anchor"
+msgstr ""
+
+#: scene/3d/arvr_nodes.cpp
+msgid "ARVROrigin requires an ARVRCamera child node"
+msgstr ""
+
+#: scene/3d/collision_polygon.cpp
+msgid ""
+"CollisionPolygon only serves to provide a collision shape to a "
+"CollisionObject derived node. Please only use it as a child of Area, "
+"StaticBody, RigidBody, KinematicBody, etc. to give them a shape."
+msgstr ""
+
+#: scene/3d/collision_polygon.cpp
+msgid "An empty CollisionPolygon has no effect on collision."
+msgstr ""
+
+#: scene/3d/collision_shape.cpp
+msgid ""
+"CollisionShape only serves to provide a collision shape to a CollisionObject "
+"derived node. Please only use it as a child of Area, StaticBody, RigidBody, "
+"KinematicBody, etc. to give them a shape."
+msgstr ""
+
+#: scene/3d/collision_shape.cpp
+msgid ""
+"A shape must be provided for CollisionShape to function. Please create a "
+"shape resource for it!"
+msgstr ""
+
+#: scene/3d/navigation_mesh.cpp
+msgid "A NavigationMesh resource must be set or created for this node to work."
+msgstr ""
+
+#: scene/3d/navigation_mesh.cpp
+msgid ""
+"NavigationMeshInstance must be a child or grandchild to a Navigation node. "
+"It only provides navigation data."
+msgstr ""
+
+#: scene/3d/particles.cpp
+msgid ""
+"Nothing is visible because meshes have not been assigned to draw passes."
+msgstr ""
+
+#: scene/3d/physics_body.cpp
+msgid ""
+"Size changes to RigidBody (in character or rigid modes) will be overriden by "
+"the physics engine when running.\n"
+"Change the size in children collision shapes instead."
+msgstr ""
+
+#: scene/3d/remote_transform.cpp
+msgid "Path property must point to a valid Spatial node to work."
+msgstr ""
+
+#: scene/3d/scenario_fx.cpp
+msgid ""
+"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)."
+msgstr ""
+
+#: scene/3d/sprite_3d.cpp
+msgid ""
+"A SpriteFrames resource must be created or set in the 'Frames' property in "
+"order for AnimatedSprite3D to display frames."
+msgstr ""
+
+#: scene/3d/vehicle_body.cpp
+msgid ""
+"VehicleWheel serves to provide a wheel system to a VehicleBody. Please use "
+"it as a child of a VehicleBody."
+msgstr ""
+
+#: scene/gui/color_picker.cpp
+msgid "Raw Mode"
+msgstr ""
+
+#: scene/gui/color_picker.cpp
+msgid "Add current color as a preset"
+msgstr ""
+
+#: scene/gui/dialogs.cpp
+msgid "Cancel"
+msgstr ""
+
+#: scene/gui/dialogs.cpp
+msgid "Alert!"
+msgstr ""
+
+#: scene/gui/dialogs.cpp
+msgid "Please Confirm..."
+msgstr ""
+
+#: scene/gui/popup.cpp
+msgid ""
+"Popups will hide by default unless you call popup() or any of the popup*() "
+"functions. Making them visible for editing is fine though, but they will "
+"hide upon running."
+msgstr ""
+
+#: scene/gui/scroll_container.cpp
+msgid ""
+"ScrollContainer is intended to work with a single child control.\n"
+"Use a container as child (VBox,HBox,etc), or a Control and set the custom "
+"minimum size manually."
+msgstr ""
+
+#: scene/main/scene_tree.cpp
+msgid ""
+"Default Environment as specified in Project Setings (Rendering -> Viewport -"
+"> Default Environment) could not be loaded."
+msgstr ""
+
+#: scene/main/viewport.cpp
+msgid ""
+"This viewport is not set as render target. If you intend for it to display "
+"its contents directly to the screen, make it a child of a Control so it can "
+"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
+"texture to some node for display."
+msgstr ""
+
+#: scene/resources/dynamic_font.cpp
+msgid "Error initializing FreeType."
+msgstr ""
+
+#: scene/resources/dynamic_font.cpp
+msgid "Unknown font format."
+msgstr ""
+
+#: scene/resources/dynamic_font.cpp
+msgid "Error loading font."
+msgstr ""
+
+#: scene/resources/dynamic_font.cpp
+msgid "Invalid font size."
+msgstr ""
diff --git a/editor/translations/nb.po b/editor/translations/nb.po
index 6dc635daa6..b4c3df0fb9 100644
--- a/editor/translations/nb.po
+++ b/editor/translations/nb.po
@@ -1,5 +1,6 @@
# Norwegian Bokmål translation of the Godot Engine editor
-# Copyright (C) 2016-2017 Juan Linietsky, Ariel Manzur and the Godot community
+# Copyright (C) 2007-2017 Juan Linietsky, Ariel Manzur
+# Copyright (C) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)
# This file is distributed under the same license as the Godot source code.
#
# Anonymous <GentleSaucepan@protonmail.com>, 2017.
@@ -192,10 +193,9 @@ msgid "Create %d NEW tracks and insert keys?"
msgstr ""
#: editor/animation_editor.cpp editor/create_dialog.cpp
-#: editor/editor_audio_buses.cpp
+#: editor/editor_audio_buses.cpp editor/plugins/abstract_polygon_2d_editor.cpp
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
#: editor/plugins/mesh_instance_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp editor/project_manager.cpp
#: editor/script_create_dialog.cpp
msgid "Create"
@@ -357,262 +357,6 @@ msgstr ""
msgid "Change Array Value"
msgstr ""
-#: editor/asset_library_editor_plugin.cpp
-msgid "Free"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_plugin_settings.cpp
-msgid "Version:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Contents:"
-msgstr "Kontinuerlig"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "View Files"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_help.cpp editor/property_selector.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Description:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-#: editor/project_manager.cpp
-msgid "Install"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/call_dialog.cpp
-#: editor/connections_dialog.cpp editor/export_template_manager.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-#: editor/project_settings_editor.cpp editor/property_editor.cpp
-#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Close"
-msgstr "Lukk"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve hostname:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Connection error, please try again."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't connect."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't connect to host:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response from host:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Request failed, return code:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Req. Failed."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Request failed, too many redirects"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Redirect Loop."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Bad download hash, assuming file has been tampered with."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Expected:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Got:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Asset Download Error:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-msgid "Success!"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Fetching:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Resolving.."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Connecting.."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Requesting.."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Error making request"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Idle"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Retry"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Download Error"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Download for this asset is already in progress!"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "first"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "prev"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "next"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "last"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "All"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
-#: editor/settings_config_dialog.cpp
-msgid "Search:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/code_editor.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Search"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/project_manager.cpp
-msgid "Import"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Plugins"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Sort:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Reverse"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Category:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Site:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Support.."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Official"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-msgid "Community"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Testing"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Assets ZIP File"
-msgstr ""
-
-#: editor/call_dialog.cpp
-msgid "Method List For '%s':"
-msgstr ""
-
-#: editor/call_dialog.cpp modules/visual_script/visual_script_editor.cpp
-msgid "Call"
-msgstr "Ring"
-
-#: editor/call_dialog.cpp
-msgid "Method List:"
-msgstr ""
-
-#: editor/call_dialog.cpp
-msgid "Arguments:"
-msgstr ""
-
-#: editor/call_dialog.cpp
-msgid "Return:"
-msgstr ""
-
#: editor/code_editor.cpp
msgid "Go to Line"
msgstr ""
@@ -649,6 +393,14 @@ msgstr ""
msgid "Selection Only"
msgstr ""
+#: editor/code_editor.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
+msgid "Search"
+msgstr ""
+
#: editor/code_editor.cpp editor/editor_help.cpp
msgid "Find"
msgstr ""
@@ -681,11 +433,11 @@ msgstr ""
msgid "Skip"
msgstr ""
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom In"
msgstr ""
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom Out"
msgstr ""
@@ -752,6 +504,20 @@ msgstr ""
msgid "Oneshot"
msgstr ""
+#: editor/connections_dialog.cpp editor/dependency_editor.cpp
+#: editor/export_template_manager.cpp
+#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Close"
+msgstr "Lukk"
+
#: editor/connections_dialog.cpp
msgid "Connect"
msgstr ""
@@ -777,7 +543,7 @@ msgstr ""
msgid "Disconnect"
msgstr ""
-#: editor/connections_dialog.cpp editor/node_dock.cpp
+#: editor/connections_dialog.cpp editor/editor_help.cpp editor/node_dock.cpp
msgid "Signals"
msgstr ""
@@ -794,12 +560,25 @@ msgstr ""
msgid "Recent:"
msgstr ""
+#: editor/create_dialog.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/quick_open.cpp editor/settings_config_dialog.cpp
+msgid "Search:"
+msgstr ""
+
#: editor/create_dialog.cpp editor/editor_help.cpp
#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/quick_open.cpp
msgid "Matches:"
msgstr ""
+#: editor/create_dialog.cpp editor/editor_help.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/property_selector.cpp
+#: editor/script_editor_debugger.cpp
+msgid "Description:"
+msgstr ""
+
#: editor/dependency_editor.cpp
msgid "Search Replacement For:"
msgstr ""
@@ -855,6 +634,10 @@ msgid "Owners Of:"
msgstr ""
#: editor/dependency_editor.cpp
+msgid "Remove selected files from the project? (no undo)"
+msgstr ""
+
+#: editor/dependency_editor.cpp
msgid ""
"The files being removed are required by other resources in order for them to "
"work.\n"
@@ -862,7 +645,7 @@ msgid ""
msgstr ""
#: editor/dependency_editor.cpp
-msgid "Remove selected files from the project? (no undo)"
+msgid "Cannot remove:\n"
msgstr ""
#: editor/dependency_editor.cpp
@@ -929,10 +712,6 @@ msgid "Godot Engine contributors"
msgstr ""
#: editor/editor_about.cpp
-msgid "Authors"
-msgstr ""
-
-#: editor/editor_about.cpp
msgid "Project Founders"
msgstr ""
@@ -949,6 +728,38 @@ msgid "Developers"
msgstr ""
#: editor/editor_about.cpp
+msgid "Authors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Platinum Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Gold Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Mini Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Gold Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Silver Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Bronze Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
msgid "License"
msgstr ""
@@ -991,6 +802,16 @@ msgid "Package Installed Successfully!"
msgstr ""
#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Success!"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/project_manager.cpp
+msgid "Install"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
msgid "Package Installer"
msgstr ""
@@ -1040,10 +861,6 @@ msgid "Audio Bus, Drag and Drop to rearrange."
msgstr ""
#: editor/editor_audio_buses.cpp
-msgid "Bus options"
-msgstr ""
-
-#: editor/editor_audio_buses.cpp
msgid "Solo"
msgstr ""
@@ -1055,12 +872,20 @@ msgstr ""
msgid "Bypass"
msgstr ""
+#: editor/editor_audio_buses.cpp
+msgid "Bus options"
+msgstr ""
+
#: editor/editor_audio_buses.cpp editor/plugins/tile_map_editor_plugin.cpp
#: editor/scene_tree_dock.cpp
msgid "Duplicate"
msgstr ""
#: editor/editor_audio_buses.cpp
+msgid "Reset Volume"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
#, fuzzy
msgid "Delete Effect"
msgstr "Slett Valgte"
@@ -1083,6 +908,10 @@ msgid "Duplicate Audio Bus"
msgstr "Dupliser Utvalg"
#: editor/editor_audio_buses.cpp
+msgid "Reset Bus Volume"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
#, fuzzy
msgid "Move Audio Bus"
msgstr "Flytt Legg til Nøkkel"
@@ -1115,7 +944,8 @@ msgstr ""
msgid "Create a new Bus Layout."
msgstr ""
-#: editor/editor_audio_buses.cpp editor/script_create_dialog.cpp
+#: editor/editor_audio_buses.cpp editor/property_editor.cpp
+#: editor/script_create_dialog.cpp
msgid "Load"
msgstr ""
@@ -1205,7 +1035,7 @@ msgid "Rearrange Autoloads"
msgstr ""
#: editor/editor_autoload_settings.cpp editor/editor_file_dialog.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp scene/gui/file_dialog.cpp
+#: scene/gui/file_dialog.cpp
msgid "Path:"
msgstr ""
@@ -1213,9 +1043,7 @@ msgstr ""
msgid "Node Name:"
msgstr ""
-#: editor/editor_autoload_settings.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp editor/project_manager.cpp
+#: editor/editor_autoload_settings.cpp editor/project_manager.cpp
msgid "Name"
msgstr ""
@@ -1248,18 +1076,19 @@ msgid "Choose a Directory"
msgstr ""
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Create Folder"
msgstr ""
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: editor/editor_plugin_settings.cpp editor/plugins/theme_editor_plugin.cpp
-#: editor/project_export.cpp scene/gui/file_dialog.cpp
+#: editor/editor_plugin_settings.cpp editor/filesystem_dock.cpp
+#: editor/plugins/theme_editor_plugin.cpp editor/project_export.cpp
+#: scene/gui/file_dialog.cpp
msgid "Name:"
msgstr ""
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Could not create folder."
msgstr ""
@@ -1279,30 +1108,6 @@ msgstr ""
msgid "Template file not found:\n"
msgstr ""
-#: editor/editor_export.cpp
-msgid "Added:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Removed:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Error saving atlas:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Could not save atlas subtexture:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Exporting for %s"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Setting Up.."
-msgstr ""
-
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "File Exists, Overwrite?"
msgstr ""
@@ -1387,6 +1192,10 @@ msgstr ""
msgid "Move Favorite Down"
msgstr ""
+#: editor/editor_file_dialog.cpp
+msgid "Go to parent folder"
+msgstr ""
+
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Directories & Files:"
msgstr ""
@@ -1401,10 +1210,6 @@ msgid "File:"
msgstr ""
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
-msgid "Filter:"
-msgstr ""
-
-#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Must use a valid extension."
msgstr ""
@@ -1429,6 +1234,10 @@ msgstr ""
msgid "Search Classes"
msgstr ""
+#: editor/editor_help.cpp editor/plugins/spatial_editor_plugin.cpp
+msgid "Top"
+msgstr ""
+
#: editor/editor_help.cpp editor/property_editor.cpp
msgid "Class:"
msgstr ""
@@ -1445,15 +1254,28 @@ msgstr ""
msgid "Brief Description:"
msgstr ""
+#: editor/editor_help.cpp
+#, fuzzy
+msgid "Members"
+msgstr "Medlemmer:"
+
#: editor/editor_help.cpp modules/visual_script/visual_script_editor.cpp
msgid "Members:"
msgstr "Medlemmer:"
#: editor/editor_help.cpp
+msgid "Public Methods"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Public Methods:"
msgstr ""
#: editor/editor_help.cpp
+msgid "GUI Theme Items"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "GUI Theme Items:"
msgstr ""
@@ -1463,6 +1285,11 @@ msgstr "Signaler:"
#: editor/editor_help.cpp
#, fuzzy
+msgid "Enumerations"
+msgstr "Funksjoner:"
+
+#: editor/editor_help.cpp
+#, fuzzy
msgid "Enumerations:"
msgstr "Funksjoner:"
@@ -1471,18 +1298,46 @@ msgid "enum "
msgstr ""
#: editor/editor_help.cpp
+msgid "Constants"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Constants:"
msgstr ""
#: editor/editor_help.cpp
+msgid "Description"
+msgstr ""
+
+#: editor/editor_help.cpp
+msgid "Properties"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Property Description:"
msgstr ""
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this property. Please help us by "
+"[color=$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+
+#: editor/editor_help.cpp
+msgid "Methods"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Method Description:"
msgstr ""
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this method. Please help us by [color="
+"$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Search Text"
msgstr ""
@@ -1491,24 +1346,21 @@ msgid "Output:"
msgstr ""
#: editor/editor_log.cpp editor/plugins/animation_tree_editor_plugin.cpp
-#: editor/plugins/rich_text_editor_plugin.cpp editor/property_editor.cpp
-#: editor/script_editor_debugger.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/property_editor.cpp editor/script_editor_debugger.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Clear"
msgstr ""
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Error saving resource!"
msgstr ""
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Save Resource As.."
msgstr ""
-#: editor/editor_node.cpp editor/export_template_manager.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "I see.."
msgstr ""
@@ -1525,6 +1377,26 @@ msgid "Error while saving."
msgstr ""
#: editor/editor_node.cpp
+msgid "Can't open '%s'."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Error while parsing '%s'."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Unexpected end of file '%s'."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Missing '%s' or its dependencies."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Error while loading '%s'."
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Saving Scene"
msgstr ""
@@ -1582,6 +1454,33 @@ msgid "Restored default layout to base settings."
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was imported, so it's not editable.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was instanced or inherited.\n"
+"Changes to it will not be kept when saving the current scene."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource was imported, so it's not editable. Change its settings in the "
+"import panel and then re-import."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This scene was imported, so changes to it will not be kept.\n"
+"Instancing it or inheriting will allow making changes to it.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Copy Params"
msgstr ""
@@ -1743,23 +1642,34 @@ msgid "Save changes the following scene(s) before opening Project Manager?"
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"This option is deprecated. Situations where refresh must be forced are now "
+"considered a bug. Please report."
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Pick a Main Scene"
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to enable addon plugin at: '"
+msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr ""
#: editor/editor_node.cpp
-msgid "' parsing of config failed."
+msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/"
+msgid "Unable to load addon script from path: '%s'."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to load addon script from path: '"
+msgid ""
+"Unable to load addon script from path: '%s' Base type is not EditorPlugin."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Unable to load addon script from path: '%s' Script is not in tool mode."
msgstr ""
#: editor/editor_node.cpp
@@ -1769,7 +1679,7 @@ msgid ""
msgstr ""
#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/scene_tree_dock.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Ugh"
msgstr ""
@@ -1780,11 +1690,11 @@ msgid ""
msgstr ""
#: editor/editor_node.cpp
-msgid "Error loading scene."
+msgid "Scene '%s' has broken dependencies:"
msgstr ""
#: editor/editor_node.cpp
-msgid "Scene '%s' has broken dependencies:"
+msgid "Clear Recent Scenes"
msgstr ""
#: editor/editor_node.cpp
@@ -1820,7 +1730,7 @@ msgstr ""
msgid "Toggle distraction-free mode."
msgstr ""
-#: editor/editor_node.cpp editor/io_plugins/editor_scene_import_plugin.cpp
+#: editor/editor_node.cpp
msgid "Scene"
msgstr ""
@@ -2040,6 +1950,10 @@ msgstr ""
msgid "Issue Tracker"
msgstr ""
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+msgid "Community"
+msgstr ""
+
#: editor/editor_node.cpp
msgid "About"
msgstr ""
@@ -2048,7 +1962,7 @@ msgstr ""
msgid "Play the project."
msgstr ""
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Play"
msgstr ""
@@ -2064,7 +1978,7 @@ msgstr ""
msgid "Stop the scene."
msgstr ""
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Stop"
msgstr ""
@@ -2137,6 +2051,15 @@ msgid "Object properties."
msgstr ""
#: editor/editor_node.cpp
+msgid "Changes may be lost!"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Import"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "FileSystem"
msgstr ""
@@ -2152,14 +2075,6 @@ msgstr ""
msgid "Don't Save"
msgstr ""
-#: editor/editor_node.cpp editor/editor_reimport_dialog.cpp
-msgid "Re-Import"
-msgstr ""
-
-#: editor/editor_node.cpp editor/editor_plugin_settings.cpp
-msgid "Update"
-msgstr ""
-
#: editor/editor_node.cpp
msgid "Import Templates From ZIP File"
msgstr ""
@@ -2220,11 +2135,28 @@ msgstr ""
msgid "Open the previous Editor"
msgstr ""
+#: editor/editor_plugin.cpp
+msgid "Creating Mesh Previews"
+msgstr ""
+
+#: editor/editor_plugin.cpp
+msgid "Thumbnail.."
+msgstr ""
+
#: editor/editor_plugin_settings.cpp
msgid "Installed Plugins:"
msgstr ""
#: editor/editor_plugin_settings.cpp
+msgid "Update"
+msgstr ""
+
+#: editor/editor_plugin_settings.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Version:"
+msgstr ""
+
+#: editor/editor_plugin_settings.cpp
msgid "Author:"
msgstr ""
@@ -2257,7 +2189,7 @@ msgid "Frame %"
msgstr ""
#: editor/editor_profiler.cpp
-msgid "Fixed Frame %"
+msgid "Physics Frame %"
msgstr ""
#: editor/editor_profiler.cpp editor/script_editor_debugger.cpp
@@ -2276,26 +2208,6 @@ msgstr ""
msgid "Frame #:"
msgstr ""
-#: editor/editor_reimport_dialog.cpp
-msgid "Please wait for scan to complete."
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Current scene must be saved to re-import."
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Save & Re-Import"
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Importing"
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Import Changed Resources"
-msgstr ""
-
#: editor/editor_run_native.cpp
msgid "Select device from the list"
msgstr ""
@@ -2405,10 +2317,6 @@ msgid "Importing:"
msgstr ""
#: editor/export_template_manager.cpp
-msgid "Loading Export Templates"
-msgstr ""
-
-#: editor/export_template_manager.cpp
msgid "Current Version:"
msgstr ""
@@ -2441,9 +2349,17 @@ msgid "Cannot navigate to '"
msgstr ""
#: editor/filesystem_dock.cpp
+msgid "View items as a grid of thumbnails"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "View items as a list"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
msgid ""
"\n"
-"Status: Needs Re-Import"
+"Status: Import of file failed. Please fix file and reimport manually."
msgstr ""
#: editor/filesystem_dock.cpp
@@ -2453,87 +2369,87 @@ msgid ""
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Same source and destination files, doing nothing."
+msgid "Cannot move/rename resources root."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Target file exists, can't overwrite. Delete first."
+msgid "Cannot move a folder into itself.\n"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Same source and destination paths, doing nothing."
+msgid "Error moving:\n"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Can't move directories to within themselves."
+msgid "Unable to update dependencies:\n"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Can't rename deps for:\n"
+msgid "No name provided"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Error moving file:\n"
+msgid "Provided name contains invalid characters"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Error moving dir:\n"
+msgid "No name provided."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Can't operate on '..'"
+msgid "Name contains invalid characters."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Pick New Name and Location For:"
+msgid "A file or folder with this name already exists."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "No files selected!"
+msgid "Renaming file:"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Expand all"
+msgid "Renaming folder:"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Collapse all"
+msgid "Expand all"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Show In File Manager"
+msgid "Collapse all"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Instance"
+msgid "Copy Path"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Edit Dependencies.."
+msgid "Rename.."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "View Owners.."
+msgid "Move To.."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Copy Path"
+msgid "New Folder.."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Rename or Move.."
+msgid "Show In File Manager"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Move To.."
+msgid "Instance"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Info"
+msgid "Edit Dependencies.."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Re-Import.."
+msgid "View Owners.."
msgstr ""
#: editor/filesystem_dock.cpp
@@ -2566,6 +2482,11 @@ msgstr ""
msgid "Move"
msgstr ""
+#: editor/filesystem_dock.cpp editor/plugins/animation_tree_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Rename"
+msgstr ""
+
#: editor/groups_editor.cpp
msgid "Add to Group"
msgstr ""
@@ -2579,6 +2500,10 @@ msgid "Import as Single Scene"
msgstr ""
#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
msgid "Import with Separate Materials"
msgstr ""
@@ -2591,6 +2516,18 @@ msgid "Import with Separate Objects+Materials"
msgstr ""
#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Materials+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Materials+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
msgid "Import as Multiple Scenes"
msgstr ""
@@ -2599,38 +2536,31 @@ msgid "Import as Multiple Scenes+Materials"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Import Scene"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Importing Scene.."
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Running Custom Script.."
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Couldn't load post-import script:"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Invalid/broken script for post-import (check console):"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Error running post-import script:"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Saving.."
msgstr ""
@@ -2658,579 +2588,54 @@ msgstr ""
msgid "Reimport"
msgstr ""
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "No bit masks to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path is empty."
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must be a complete resource path."
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must exist."
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Save path is empty!"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Import BitMasks"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s):"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Target Path:"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Accept"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Bit Mask"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No source font file!"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No target font resource!"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"Invalid file extension.\n"
-"Please use .font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Can't load/process source font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Couldn't save font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font Size:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Dest Resource:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "The quick brown fox jumps over the lazy dog."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Test:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Options:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Font Import"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"This file is already a Godot font file, please supply a BMFont type file "
-"instead."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Failed opening as BMFont file."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error initializing FreeType."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Unknown font format."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error loading font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Invalid font size."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Invalid font custom source."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/plugins/theme_editor_plugin.cpp
-msgid "Font"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "No meshes to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Single Mesh Import"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Source Mesh(es):"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/plugins/mesh_instance_editor_plugin.cpp
-msgid "Mesh"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Surface %d"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "No samples to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Import Audio Samples"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Source Sample(s):"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Audio Sample"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "New Clip"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Animation Options"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Flags"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Bake FPS:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Optimizer"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Linear Error"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angular Error"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angle"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Clips"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Start(s)"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "End(s)"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Loop"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Filters"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source path is empty."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't load post-import script."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Invalid/broken script for post-import."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Error importing scene."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import 3D Scene"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source Scene:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Same as Target Scene"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Shared"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Target Texture Folder:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Post-Process Script:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Custom Root Node Type:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Auto"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Root Node Name:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "The Following Files are Missing:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Anyway"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp scene/gui/dialogs.cpp
-msgid "Cancel"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import & Open"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Edited scene has not been saved, open imported scene anyway?"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Image:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Can't import a file over itself:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't localize path: %s (already local)"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "3D Scene Animation"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Uncompressed"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossless (PNG)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossy (WebP)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress (VRAM)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Format"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Compression Quality (WebP):"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Options"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Please specify some files!"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "At least one file needed for Atlas."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Error importing:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Only one file is required for large texture."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Max Texture Size:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for Atlas (2D)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cell Size:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Large Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Textures (2D)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture"
+#: editor/multi_node_edit.cpp
+msgid "MultiNode Set"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Base Atlas Texture"
+#: editor/node_dock.cpp
+msgid "Groups"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s)"
+#: editor/node_dock.cpp
+msgid "Select a Node to edit Signals and Groups."
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 2D"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create Poly"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 3D"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Insert Point"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "2D Texture"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly (Remove Point)"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "3D Texture"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Remove Poly And Point"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Atlas Texture"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create a new polygon from scratch."
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
+#: editor/plugins/abstract_polygon_2d_editor.cpp
msgid ""
-"NOTICE: Importing 2D textures is not mandatory. Just copy png/jpg files to "
-"the project."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Crop empty space."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Load Source Image"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Slicing"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Inserting"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Saving"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save large texture:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Build Atlas For:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Loading Image:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't load image:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Converting Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cropping Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Blitting Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save atlas image:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save converted texture:"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid source!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid translation source!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Column"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/script_create_dialog.cpp
-msgid "Language"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No items to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No target path!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translations"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Couldn't import!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translation"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Source CSV:"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Ignore First Row"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Compress"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Add to Project (project.godot)"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Languages:"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Translation"
-msgstr ""
-
-#: editor/multi_node_edit.cpp
-msgid "MultiNode Set"
-msgstr ""
-
-#: editor/node_dock.cpp
-msgid "Groups"
-msgstr ""
-
-#: editor/node_dock.cpp
-msgid "Select a Node to edit Signals and Groups."
+"Edit existing polygon:\n"
+"LMB: Move Point.\n"
+"Ctrl+LMB: Split Segment.\n"
+"RMB: Erase Point."
msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
@@ -3386,7 +2791,6 @@ msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
#: editor/script_create_dialog.cpp
msgid "Error!"
@@ -3497,10 +2901,6 @@ msgid "Delete Input"
msgstr ""
#: editor/plugins/animation_tree_editor_plugin.cpp
-msgid "Rename"
-msgstr ""
-
-#: editor/plugins/animation_tree_editor_plugin.cpp
msgid "Animation tree is valid."
msgstr ""
@@ -3556,64 +2956,182 @@ msgstr ""
msgid "Filters.."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing %d Triangles:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Free"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Triangle #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Contents:"
+msgstr "Kontinuerlig"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "View Files"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Light Baker Setup:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve hostname:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing Geometry"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Fixing Lights"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connection error, please try again."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Making BVH"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't connect."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Light Octree"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't connect to host:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Octree Texture"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response from host:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Transfer to Lightmaps:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, return code:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Allocating Texture #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Req. Failed."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Baking Triangle #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, too many redirects"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Post-Processing Texture #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Redirect Loop."
msgstr ""
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Bake!"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Bad download hash, assuming file has been tampered with."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Expected:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Got:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed sha256 hash check"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Asset Download Error:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Fetching:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Resolving.."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connecting.."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Requesting.."
msgstr ""
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Reset the lightmap octree baking process (start over)."
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Error making request"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Idle"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Retry"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download Error"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download for this asset is already in progress!"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "first"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "prev"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "next"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "last"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "All"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Plugins"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Sort:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Reverse"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Category:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Site:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Support.."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Official"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Testing"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Assets ZIP File"
msgstr ""
#: editor/plugins/camera_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
msgid "Preview"
msgstr ""
@@ -3656,11 +3174,15 @@ msgid "Edit CanvasItem"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Change Anchors"
+msgid "Anchors only"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Change Anchors and Margins"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom (%):"
+msgid "Change Anchors"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3711,59 +3233,72 @@ msgid "Pan Mode"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Lock the selected object in place (can't be moved)."
+msgid "Toggles snapping"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Unlock the selected object (can be moved)."
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Use Snap"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Makes sure the object's children are not selectable."
+msgid "Snapping options"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Restores the object's children's ability to be selected."
+msgid "Snap to grid"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Edit"
-msgstr "Rediger"
+msgid "Use Rotation Snap"
+msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Use Snap"
+msgid "Configure Snap..."
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Show Grid"
+msgid "Snap Relative"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Rotation Snap"
+msgid "Use Pixel Snap"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap Relative"
+msgid "Smart snapping"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Configure Snap.."
+msgid "Snap to parent"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Pixel Snap"
+msgid "Snap to node anchor"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Skeleton.."
+msgid "Snap to node sides"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to other nodes"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Lock the selected object in place (can't be moved)."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Unlock the selected object (can be moved)."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Makes sure the object's children are not selectable."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Restores the object's children's ability to be selected."
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3792,11 +3327,16 @@ msgid "View"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Reset"
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Show Grid"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Show helpers"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Set.."
+msgid "Show rulers"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3808,7 +3348,7 @@ msgid "Frame Selection"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Anchor"
+msgid "Layout"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3832,11 +3372,20 @@ msgid "Clear Pose"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Set a Value"
+msgid "Drag pivot from mouse position"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#, fuzzy
+msgid "Set pivot at mouse position"
+msgstr "Fjern Funksjon"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Multiply grid step by 2"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap (Pixels):"
+msgid "Divide grid step by 2"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3847,23 +3396,28 @@ msgstr ""
msgid "Adding %s..."
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Create Node"
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Error instancing scene from %s"
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "OK :("
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "No parent to instance a child at."
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "This operation requires a single selected node."
msgstr ""
@@ -3877,45 +3431,6 @@ msgid ""
"Drag & drop + Alt : Change node type"
msgstr ""
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Create Poly"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly (Remove Point)"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Create a new polygon from scratch."
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-msgid ""
-"Edit existing polygon:\n"
-"LMB: Move Point.\n"
-"Ctrl+LMB: Split Segment.\n"
-"RMB: Erase Point."
-msgstr ""
-
#: editor/plugins/collision_polygon_editor_plugin.cpp
msgid "Create Poly3D"
msgstr ""
@@ -3925,14 +3440,6 @@ msgid "Set Handle"
msgstr ""
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Creating Mesh Library"
-msgstr ""
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Thumbnail.."
-msgstr ""
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Remove item %d?"
msgstr ""
@@ -3955,6 +3462,27 @@ msgid "Update from Scene"
msgstr ""
#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat0"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat1"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+#, fuzzy
+msgid "Ease in"
+msgstr "Fjern Utvalg"
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Ease out"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Smoothstep"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
msgid "Modify Curve Point"
msgstr ""
@@ -4032,22 +3560,18 @@ msgid "Create Occluder Polygon"
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Edit existing polygon:"
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "LMB: Move Point."
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Ctrl+LMB: Split Segment."
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "RMB: Erase Point."
msgstr ""
@@ -4148,6 +3672,10 @@ msgid "Create Outline"
msgstr ""
#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Mesh"
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Create Trimesh Static Body"
msgstr ""
@@ -4275,12 +3803,72 @@ msgstr ""
msgid "Populate"
msgstr ""
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Create Navigation Polygon"
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake!"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake the navigation mesh.\n"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Clear the navigation mesh."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Setting up Configuration..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Calculating grid size..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating heightfield..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Marking walkable triangles..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Constructing compact heightfield..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Eroding walkable area..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Partitioning..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating contours..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating polymesh..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Converting to native navigation mesh..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Navigation Mesh Generator Setup:"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Parsing Geometry..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Done!"
msgstr ""
#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Remove Poly And Point"
+msgid "Create Navigation Polygon"
msgstr ""
#: editor/plugins/particles_2d_editor_plugin.cpp
@@ -4454,16 +4042,19 @@ msgid "Curve Point #"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve Point Position"
-msgstr ""
+msgstr "Fjern Funksjon"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve In Position"
-msgstr ""
+msgstr "Fjern Funksjon"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve Out Position"
-msgstr ""
+msgstr "Fjern Funksjon"
#: editor/plugins/path_editor_plugin.cpp
msgid "Split Path"
@@ -4523,6 +4114,14 @@ msgid "Scale Polygon"
msgstr ""
#: editor/plugins/polygon_2d_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Edit"
+msgstr "Rediger"
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Polygon->UV"
msgstr ""
@@ -4577,63 +4176,10 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/shader_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr ""
-#: editor/plugins/rich_text_editor_plugin.cpp
-msgid "Parse BBCode"
-msgstr ""
-
-#: editor/plugins/sample_editor_plugin.cpp
-msgid "Length:"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Open Sample File(s)"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "ERROR: Couldn't load sample!"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Add Sample"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Rename Sample"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Delete Sample"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "16 Bits"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "8 Bits"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Stereo"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Mono"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Format"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Pitch"
-msgstr ""
-
#: editor/plugins/script_editor_plugin.cpp
msgid "Clear Recent Files"
msgstr ""
@@ -4724,6 +4270,10 @@ msgstr ""
msgid "Close All"
msgstr ""
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+msgid "Run"
+msgstr ""
+
#: editor/plugins/script_editor_plugin.cpp
msgid "Toggle Scripts Panel"
msgstr ""
@@ -4752,7 +4302,8 @@ msgstr ""
msgid "Break"
msgstr ""
-#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+#: editor/script_editor_debugger.cpp
msgid "Continue"
msgstr ""
@@ -4765,18 +4316,6 @@ msgid "Debug with external editor"
msgstr ""
#: editor/plugins/script_editor_plugin.cpp
-msgid "Window"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Left"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Right"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
msgid "Open Godot online documentation"
msgstr ""
@@ -4858,8 +4397,9 @@ msgid "Cut"
msgstr ""
#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr ""
@@ -5123,10 +4663,6 @@ msgid "View Plane Transform."
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Scaling to %s%%."
-msgstr ""
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rotating %s degrees."
msgstr ""
@@ -5143,10 +4679,6 @@ msgid "Top View."
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Top"
-msgstr ""
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rear View."
msgstr ""
@@ -5376,6 +4908,10 @@ msgid "Transform"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Configure Snap.."
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Local Coords"
msgstr ""
@@ -5521,6 +5057,10 @@ msgid "Speed (FPS):"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Loop"
+msgstr ""
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Animation Frames"
msgstr ""
@@ -5533,11 +5073,12 @@ msgid "Insert Empty (After)"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Up"
-msgstr ""
+#, fuzzy
+msgid "Move (Before)"
+msgstr "Kopier Noder"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Down"
+msgid "Move (After)"
msgstr ""
#: editor/plugins/style_box_editor_plugin.cpp
@@ -5615,7 +5156,11 @@ msgid "Remove All"
msgstr "Fjern Funksjon"
#: editor/plugins/theme_editor_plugin.cpp
-msgid "Theme"
+msgid "Edit theme.."
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Theme editing menu."
msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
@@ -5700,6 +5245,10 @@ msgid "Style"
msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
+msgid "Font"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
msgid "Color"
msgstr ""
@@ -5749,7 +5298,7 @@ msgid "Mirror Y"
msgstr ""
#: editor/plugins/tile_map_editor_plugin.cpp
-msgid "Bucket"
+msgid "Paint Tile"
msgstr ""
#: editor/plugins/tile_map_editor_plugin.cpp
@@ -5813,6 +5362,10 @@ msgid "Delete preset '%s'?"
msgstr ""
#: editor/project_export.cpp
+msgid "Export templates for this platform are missing/corrupted: "
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Presets"
msgstr ""
@@ -5883,19 +5436,29 @@ msgid "Export templates for this platform are missing:"
msgstr ""
#: editor/project_export.cpp
+msgid "Export templates for this platform are missing/corrupted:"
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Export With Debug"
msgstr ""
#: editor/project_manager.cpp
-msgid "Invalid project path, the path must exist!"
+msgid "The path does not exist."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Please choose a 'project.godot' file."
msgstr ""
#: editor/project_manager.cpp
-msgid "Invalid project path, project.godot must not exist."
+msgid ""
+"Your project will be created in a non empty folder (you might want to create "
+"a new folder)."
msgstr ""
#: editor/project_manager.cpp
-msgid "Invalid project path, project.godot must exist."
+msgid "Please choose a folder that does not contain a 'project.godot' file."
msgstr ""
#: editor/project_manager.cpp
@@ -5903,10 +5466,26 @@ msgid "Imported Project"
msgstr ""
#: editor/project_manager.cpp
+msgid " "
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "It would be a good idea to name your project."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Invalid project path (changed anything?)."
msgstr ""
#: editor/project_manager.cpp
+msgid "Couldn't get project.godot in project path."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Couldn't edit project.godot in project path."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
msgstr ""
@@ -5915,23 +5494,23 @@ msgid "The following files failed extraction from package:"
msgstr ""
#: editor/project_manager.cpp
-msgid "Import Existing Project"
+msgid "Rename Project"
msgstr ""
#: editor/project_manager.cpp
-msgid "Project Path (Must Exist):"
+msgid "Couldn't get project.godot in the project path."
msgstr ""
#: editor/project_manager.cpp
-msgid "Project Name:"
+msgid "New Game Project"
msgstr ""
#: editor/project_manager.cpp
-msgid "Create New Project"
+msgid "Import Existing Project"
msgstr ""
#: editor/project_manager.cpp
-msgid "Project Path:"
+msgid "Create New Project"
msgstr ""
#: editor/project_manager.cpp
@@ -5939,11 +5518,19 @@ msgid "Install Project:"
msgstr ""
#: editor/project_manager.cpp
-msgid "Browse"
+msgid "Project Name:"
msgstr ""
#: editor/project_manager.cpp
-msgid "New Game Project"
+msgid "Create folder"
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Project Path:"
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Browse"
msgstr ""
#: editor/project_manager.cpp
@@ -5955,6 +5542,10 @@ msgid "Unnamed Project"
msgstr ""
#: editor/project_manager.cpp
+msgid "Can't open project"
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Are you sure to open more than one project?"
msgstr ""
@@ -5981,16 +5572,18 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
-"You are about the scan %s folders for existing Godot projects. Do you "
-"confirm?"
+"Language changed.\n"
+"The UI will update next time the editor or project manager starts."
msgstr ""
#: editor/project_manager.cpp
-msgid "Project List"
+msgid ""
+"You are about the scan %s folders for existing Godot projects. Do you "
+"confirm?"
msgstr ""
#: editor/project_manager.cpp
-msgid "Run"
+msgid "Project List"
msgstr ""
#: editor/project_manager.cpp
@@ -6014,6 +5607,10 @@ msgid "Exit"
msgstr ""
#: editor/project_manager.cpp
+msgid "Restart Now"
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Can't run project"
msgstr ""
@@ -6050,17 +5647,14 @@ msgid "Add Input Action Event"
msgstr ""
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Meta+"
msgstr ""
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Shift+"
msgstr ""
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Alt+"
msgstr ""
@@ -6121,7 +5715,7 @@ msgstr "Forandre"
msgid "Joypad Axis Index:"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Axis"
msgstr ""
@@ -6141,31 +5735,31 @@ msgstr ""
msgid "Add Event"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Device"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Button"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Left Button."
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Right Button."
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Middle Button."
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Up."
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Down."
msgstr ""
@@ -6174,7 +5768,7 @@ msgid "Add Global Property"
msgstr ""
#: editor/project_settings_editor.cpp
-msgid "Select an setting item first!"
+msgid "Select a setting item first!"
msgstr ""
#: editor/project_settings_editor.cpp
@@ -6191,6 +5785,14 @@ msgid "Delete Item"
msgstr "Slett Valgte"
#: editor/project_settings_editor.cpp
+msgid "Can't contain '/' or ':'"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Already existing"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "Error saving settings."
msgstr ""
@@ -6231,6 +5833,14 @@ msgid "Remove Resource Remap Option"
msgstr ""
#: editor/project_settings_editor.cpp
+msgid "Changed Locale Filter"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Changed Locale Filter Mode"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "Project Settings (project.godot)"
msgstr ""
@@ -6291,6 +5901,27 @@ msgid "Locale"
msgstr ""
#: editor/project_settings_editor.cpp
+msgid "Locales Filter"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Show all locales"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Show only selected locales"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Filter mode:"
+msgstr "Lim inn Noder"
+
+#: editor/project_settings_editor.cpp
+msgid "Locales:"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "AutoLoad"
msgstr ""
@@ -6340,10 +5971,18 @@ msgid "New Script"
msgstr ""
#: editor/property_editor.cpp
+msgid "Make Unique"
+msgstr ""
+
+#: editor/property_editor.cpp
msgid "Show in File System"
msgstr ""
#: editor/property_editor.cpp
+msgid "Convert To %s"
+msgstr ""
+
+#: editor/property_editor.cpp
msgid "Error loading file: Not a resource!"
msgstr ""
@@ -6381,6 +6020,10 @@ msgid "Select Property"
msgstr ""
#: editor/property_selector.cpp
+msgid "Select Virtual Method"
+msgstr ""
+
+#: editor/property_selector.cpp
msgid "Select Method"
msgstr ""
@@ -6408,26 +6051,6 @@ msgstr ""
msgid "Reparent"
msgstr ""
-#: editor/resources_dock.cpp
-msgid "Create New Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Open Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Save Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Resource Tools"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Make Local"
-msgstr ""
-
#: editor/run_settings_dialog.cpp
msgid "Run Mode:"
msgstr ""
@@ -6554,14 +6177,6 @@ msgid "Sub-Resources:"
msgstr ""
#: editor/scene_tree_dock.cpp
-msgid "Edit Groups"
-msgstr ""
-
-#: editor/scene_tree_dock.cpp
-msgid "Edit Connections"
-msgstr ""
-
-#: editor/scene_tree_dock.cpp
msgid "Clear Inheritance"
msgstr ""
@@ -6744,6 +6359,14 @@ msgid "Invalid base path"
msgstr ""
#: editor/script_create_dialog.cpp
+msgid "Directory of the same name exists"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
+msgid "File exists, will be reused"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
msgid "Invalid extension"
msgstr ""
@@ -6785,6 +6408,10 @@ msgid "Load existing script file"
msgstr ""
#: editor/script_create_dialog.cpp
+msgid "Language"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
msgid "Inherits"
msgstr ""
@@ -6825,6 +6452,10 @@ msgid "Function:"
msgstr ""
#: editor/script_editor_debugger.cpp
+msgid "Pick one or more items from the list to display the graph."
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
msgid "Errors"
msgstr ""
@@ -6905,6 +6536,10 @@ msgid "Type"
msgstr ""
#: editor/script_editor_debugger.cpp
+msgid "Format"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
msgid "Usage"
msgstr ""
@@ -6980,12 +6615,28 @@ msgstr ""
msgid "Change Probe Extents"
msgstr ""
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Library"
+msgstr ""
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Status"
+msgstr ""
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Libraries: "
+msgstr ""
+
+#: modules/gdnative/register_types.cpp
+msgid "GDNative"
+msgstr ""
+
#: modules/gdscript/gd_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Invalid type argument to convert(), use TYPE_* constants."
msgstr "Ugyldig argument til convert(), bruk TYPE_*-konstantene."
-#: modules/gdscript/gd_functions.cpp
+#: modules/gdscript/gd_functions.cpp modules/mono/glue/glue_header.h
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Not enough bytes for decoding bytes, or invalid format."
msgstr ""
@@ -7037,10 +6688,6 @@ msgid "GridMap Duplicate Selection"
msgstr "Dupliser Utvalg"
#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "GridMap Paint"
-msgstr ""
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Snap View"
msgstr ""
@@ -7134,12 +6781,8 @@ msgstr ""
msgid "Pick Distance:"
msgstr ""
-#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "Tiles"
-msgstr ""
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "Areas"
+#: modules/mono/editor/mono_bottom_panel.cpp
+msgid "Builds"
msgstr ""
#: modules/visual_script/visual_script.cpp
@@ -7337,10 +6980,18 @@ msgid "Return"
msgstr "Returner"
#: modules/visual_script/visual_script_editor.cpp
+msgid "Call"
+msgstr "Ring"
+
+#: modules/visual_script/visual_script_editor.cpp
msgid "Get"
msgstr "FÃ¥"
#: modules/visual_script/visual_script_editor.cpp
+msgid "Script already has function '%s'"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
#, fuzzy
msgid "Change Input Value"
msgstr "Anim Forandre Verdi"
@@ -7699,6 +7350,12 @@ msgid ""
"order for AnimatedSprite3D to display frames."
msgstr ""
+#: scene/3d/vehicle_body.cpp
+msgid ""
+"VehicleWheel serves to provide a wheel system to a VehicleBody. Please use "
+"it as a child of a VehicleBody."
+msgstr ""
+
#: scene/gui/color_picker.cpp
msgid "Raw Mode"
msgstr ""
@@ -7708,15 +7365,15 @@ msgid "Add current color as a preset"
msgstr ""
#: scene/gui/dialogs.cpp
-msgid "Alert!"
+msgid "Cancel"
msgstr ""
#: scene/gui/dialogs.cpp
-msgid "Please Confirm..."
+msgid "Alert!"
msgstr ""
-#: scene/gui/input_action.cpp
-msgid "Ctrl+"
+#: scene/gui/dialogs.cpp
+msgid "Please Confirm..."
msgstr ""
#: scene/gui/popup.cpp
@@ -7746,3 +7403,19 @@ msgid ""
"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
"texture to some node for display."
msgstr ""
+
+#: scene/resources/dynamic_font.cpp
+msgid "Error initializing FreeType."
+msgstr ""
+
+#: scene/resources/dynamic_font.cpp
+msgid "Unknown font format."
+msgstr ""
+
+#: scene/resources/dynamic_font.cpp
+msgid "Error loading font."
+msgstr ""
+
+#: scene/resources/dynamic_font.cpp
+msgid "Invalid font size."
+msgstr ""
diff --git a/editor/translations/nl.po b/editor/translations/nl.po
index b13d86e0f2..a9ed678eac 100644
--- a/editor/translations/nl.po
+++ b/editor/translations/nl.po
@@ -1,21 +1,24 @@
# Dutch translation of the Godot Engine editor
-# Copyright (C) 2016-2017 Juan Linietsky, Ariel Manzur and the Godot community
+# Copyright (C) 2007-2017 Juan Linietsky, Ariel Manzur
+# Copyright (C) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)
# This file is distributed under the same license as the Godot source code.
#
-# Aram Nap <xyphex.aram@gmail.com>, 2017
+# Aram Nap <xyphex.aram@gmail.com>, 2017.
+# Robin Arys <robinarys@hotmail.com>, 2017.
+# Senno Kaasjager <senno.kaasjager@gmail.com>, 2017.
#
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
-"PO-Revision-Date: 2017-04-13 18:15+0000\n"
-"Last-Translator: Aram Nap <xyphex.aram@gmail.com>\n"
+"PO-Revision-Date: 2017-10-25 23:45+0000\n"
+"Last-Translator: Robin Arys <robinarys@hotmail.com>\n"
"Language-Team: Dutch <https://hosted.weblate.org/projects/godot-engine/godot/"
"nl/>\n"
"Language: nl\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8-bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 2.14-dev\n"
+"X-Generator: Weblate 2.17\n"
#: editor/animation_editor.cpp
msgid "Disabled"
@@ -84,7 +87,7 @@ msgstr "Anim Track Wijzig Waarde Modus"
#: editor/animation_editor.cpp
#, fuzzy
msgid "Anim Track Change Wrap Mode"
-msgstr "Anim Track Wijzig Waarde Modus"
+msgstr "Animatiespoor Wijzig Wikkelmodus"
#: editor/animation_editor.cpp
msgid "Edit Node Curve"
@@ -153,7 +156,7 @@ msgstr "Lineair"
#: editor/animation_editor.cpp editor/plugins/theme_editor_plugin.cpp
msgid "Constant"
-msgstr "Constant"
+msgstr "Constante"
#: editor/animation_editor.cpp
msgid "In"
@@ -192,10 +195,9 @@ msgid "Create %d NEW tracks and insert keys?"
msgstr "Maak %d NIEUWE tracks aan en keys invoeren?"
#: editor/animation_editor.cpp editor/create_dialog.cpp
-#: editor/editor_audio_buses.cpp
+#: editor/editor_audio_buses.cpp editor/plugins/abstract_polygon_2d_editor.cpp
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
#: editor/plugins/mesh_instance_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp editor/project_manager.cpp
#: editor/script_create_dialog.cpp
msgid "Create"
@@ -279,7 +281,7 @@ msgstr "Verwijder geselecteerde track."
#: editor/animation_editor.cpp
msgid "Track tools"
-msgstr "Track tools"
+msgstr "Spoorgereedschappen"
#: editor/animation_editor.cpp
msgid "Enable editing of individual keys by clicking them."
@@ -312,7 +314,7 @@ msgstr ""
#: editor/animation_editor.cpp
msgid "Key"
-msgstr "Key"
+msgstr "Sleutel"
#: editor/animation_editor.cpp
msgid "Transition"
@@ -358,277 +360,13 @@ msgstr "Wijzig Array Waarde Type"
msgid "Change Array Value"
msgstr "Wijzig Array Waarde"
-#: editor/asset_library_editor_plugin.cpp
-msgid "Free"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_plugin_settings.cpp
-msgid "Version:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Contents:"
-msgstr "Constanten:"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "View Files"
-msgstr "Bestand:"
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_help.cpp editor/property_selector.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Description:"
-msgstr "Omschrijving:"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-#: editor/project_manager.cpp
-msgid "Install"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/call_dialog.cpp
-#: editor/connections_dialog.cpp editor/export_template_manager.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-#: editor/project_settings_editor.cpp editor/property_editor.cpp
-#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Close"
-msgstr "Sluiten"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve hostname:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Connection error, please try again."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Can't connect."
-msgstr "Verbind.."
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Can't connect to host:"
-msgstr "Verbind Aan Node:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response from host:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Request failed, return code:"
-msgstr "Opgevraagde bestandsformaat onbekend:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Req. Failed."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Request failed, too many redirects"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Redirect Loop."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Bad download hash, assuming file has been tampered with."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Expected:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Got:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Asset Download Error:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-msgid "Success!"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Fetching:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Resolving.."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Connecting.."
-msgstr "Verbind.."
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Requesting.."
-msgstr "Testen"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Error making request"
-msgstr "Error bij het opslaan van resource!"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Idle"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Retry"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Download Error"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Download for this asset is already in progress!"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "first"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "prev"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "next"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "last"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "All"
-msgstr "Alle"
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
-#: editor/settings_config_dialog.cpp
-msgid "Search:"
-msgstr "Zoeken:"
-
-#: editor/asset_library_editor_plugin.cpp editor/code_editor.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Search"
-msgstr "Zoeken"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/project_manager.cpp
-msgid "Import"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Plugins"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Sort:"
-msgstr "Sorteren:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Reverse"
-msgstr "Omkeren"
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Category:"
-msgstr "Categorie:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Site:"
-msgstr "Site:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Support.."
-msgstr "Ondersteuning.."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Official"
-msgstr "Officieel"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-msgid "Community"
-msgstr "Gemeenschap"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Testing"
-msgstr "Testen"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Assets ZIP File"
-msgstr "Assets ZIP Bestand"
-
-#: editor/call_dialog.cpp
-msgid "Method List For '%s':"
-msgstr "Methode Lijst Voor '%s':"
-
-#: editor/call_dialog.cpp modules/visual_script/visual_script_editor.cpp
-msgid "Call"
-msgstr "Aanroep"
-
-#: editor/call_dialog.cpp
-msgid "Method List:"
-msgstr "Methode Lijst:"
-
-#: editor/call_dialog.cpp
-msgid "Arguments:"
-msgstr "Argumenten:"
-
-#: editor/call_dialog.cpp
-msgid "Return:"
-msgstr "Teruggave:"
-
#: editor/code_editor.cpp
msgid "Go to Line"
msgstr "Ga naar Regel"
#: editor/code_editor.cpp
msgid "Line Number:"
-msgstr "Regel Nummer:"
+msgstr "Regelnummer:"
#: editor/code_editor.cpp
msgid "No Matches"
@@ -659,6 +397,14 @@ msgstr "Hele Woorden"
msgid "Selection Only"
msgstr "Alleen Selectie"
+#: editor/code_editor.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
+msgid "Search"
+msgstr "Zoeken"
+
#: editor/code_editor.cpp editor/editor_help.cpp
msgid "Find"
msgstr "Zoeken"
@@ -691,11 +437,11 @@ msgstr "Vragen Bij Vervangen"
msgid "Skip"
msgstr "Overslaan"
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom In"
msgstr "Inzoomen"
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom Out"
msgstr "Uitzoomen"
@@ -764,6 +510,20 @@ msgstr "Uitgesteld"
msgid "Oneshot"
msgstr "Eénschots"
+#: editor/connections_dialog.cpp editor/dependency_editor.cpp
+#: editor/export_template_manager.cpp
+#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Close"
+msgstr "Sluiten"
+
#: editor/connections_dialog.cpp
msgid "Connect"
msgstr "Verbinden"
@@ -790,7 +550,7 @@ msgstr "Verbind.."
msgid "Disconnect"
msgstr "Losmaken"
-#: editor/connections_dialog.cpp editor/node_dock.cpp
+#: editor/connections_dialog.cpp editor/editor_help.cpp editor/node_dock.cpp
msgid "Signals"
msgstr "Signalen"
@@ -807,11 +567,24 @@ msgstr "Favorieten:"
msgid "Recent:"
msgstr "Recente:"
+#: editor/create_dialog.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/quick_open.cpp editor/settings_config_dialog.cpp
+msgid "Search:"
+msgstr "Zoeken:"
+
#: editor/create_dialog.cpp editor/editor_help.cpp
#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/quick_open.cpp
msgid "Matches:"
-msgstr "Matches:"
+msgstr "Overeenkomsten:"
+
+#: editor/create_dialog.cpp editor/editor_help.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/property_selector.cpp
+#: editor/script_editor_debugger.cpp
+msgid "Description:"
+msgstr "Omschrijving:"
#: editor/dependency_editor.cpp
msgid "Search Replacement For:"
@@ -872,6 +645,12 @@ msgid "Owners Of:"
msgstr "Eigenaren Van:"
#: editor/dependency_editor.cpp
+msgid "Remove selected files from the project? (no undo)"
+msgstr ""
+"Verwijder geselecteerde bestanden van het project? (Kan niet ongedaan "
+"worden.)"
+
+#: editor/dependency_editor.cpp
msgid ""
"The files being removed are required by other resources in order for them to "
"work.\n"
@@ -882,10 +661,8 @@ msgstr ""
"Toch verwijderen? (Kan niet ongedaan worden.)"
#: editor/dependency_editor.cpp
-msgid "Remove selected files from the project? (no undo)"
-msgstr ""
-"Verwijder geselecteerde bestanden van het project? (Kan niet ongedaan "
-"worden.)"
+msgid "Cannot remove:\n"
+msgstr "Niet wisbaar:\n"
#: editor/dependency_editor.cpp
msgid "Error loading:"
@@ -940,43 +717,71 @@ msgstr "Verwijder"
#: editor/editor_about.cpp
msgid "Thanks from the Godot community!"
-msgstr ""
+msgstr "Bedankt van de Godot gemeenschap!"
#: editor/editor_about.cpp
msgid "Thanks!"
-msgstr ""
+msgstr "Bedankt!"
#: editor/editor_about.cpp
msgid "Godot Engine contributors"
-msgstr ""
-
-#: editor/editor_about.cpp
-msgid "Authors"
-msgstr ""
+msgstr "Godot Engine medewerkers"
#: editor/editor_about.cpp
msgid "Project Founders"
-msgstr ""
+msgstr "Projectoprichters"
#: editor/editor_about.cpp
msgid "Lead Developer"
-msgstr ""
+msgstr "Hoofdontwikkelaar"
#: editor/editor_about.cpp editor/project_manager.cpp
msgid "Project Manager"
-msgstr ""
+msgstr "Project Manager"
#: editor/editor_about.cpp
msgid "Developers"
-msgstr ""
+msgstr "Ontwikkelaars"
+
+#: editor/editor_about.cpp
+msgid "Authors"
+msgstr "Auteurs"
+
+#: editor/editor_about.cpp
+msgid "Platinum Sponsors"
+msgstr "Platina Sponsors"
+
+#: editor/editor_about.cpp
+msgid "Gold Sponsors"
+msgstr "Gouden Sponsors"
+
+#: editor/editor_about.cpp
+msgid "Mini Sponsors"
+msgstr "Mini Sponsors"
+
+#: editor/editor_about.cpp
+msgid "Gold Donors"
+msgstr "Gouden Donors"
+
+#: editor/editor_about.cpp
+msgid "Silver Donors"
+msgstr "Zilveren Donors"
+
+#: editor/editor_about.cpp
+msgid "Bronze Donors"
+msgstr "Bronzen Donors"
+
+#: editor/editor_about.cpp
+msgid "Donors"
+msgstr "Donors"
#: editor/editor_about.cpp
msgid "License"
-msgstr ""
+msgstr "Licentie"
#: editor/editor_about.cpp
msgid "Thirdparty License"
-msgstr ""
+msgstr "Derde partijslicentie"
#: editor/editor_about.cpp
msgid ""
@@ -985,135 +790,146 @@ msgid ""
"is an exhaustive list of all such thirdparty components with their "
"respective copyright statements and license terms."
msgstr ""
+"Godot Engine maakt gebruik van enkele gratis en open-source bibliotheken, "
+"ontwikkeld door derden, die compatibel zijn met onze MIT licentie. Wat volgt "
+"is een exhaustieve lijst van alle componenten van een derde partij met hun "
+"respectievelijke copyrightberichten en licentietermen."
#: editor/editor_about.cpp
-#, fuzzy
msgid "All Components"
-msgstr "Constanten:"
+msgstr "Alle Componenten"
#: editor/editor_about.cpp
-#, fuzzy
msgid "Components"
-msgstr "Constanten:"
+msgstr "Componenten"
#: editor/editor_about.cpp
msgid "Licenses"
-msgstr ""
+msgstr "Licenties"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Error opening package file, not in zip format."
-msgstr ""
+msgstr "Fout bij het openen van het pakketbestand, geen zip-formaat."
#: editor/editor_asset_installer.cpp
-#, fuzzy
msgid "Uncompressing Assets"
-msgstr "Aan Het Herimporteren"
+msgstr "Bronnen aan het uitpakken"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package Installed Successfully!"
-msgstr ""
+msgstr "Pakket Succesvol Geïnstalleerd!"
+
+#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Success!"
+msgstr "Succes!"
+
+#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/project_manager.cpp
+msgid "Install"
+msgstr "Installeer"
#: editor/editor_asset_installer.cpp
msgid "Package Installer"
-msgstr ""
+msgstr "Pakketinstalleerder"
#: editor/editor_audio_buses.cpp
msgid "Speakers"
-msgstr ""
+msgstr "Luidsprekers"
#: editor/editor_audio_buses.cpp
msgid "Add Effect"
-msgstr ""
+msgstr "Geluidseffect Toevoegen"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Rename Audio Bus"
-msgstr "Open Audio Bus Layout"
+msgstr "Hernoem audiobus"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Toggle Audio Bus Solo"
-msgstr "Open Audio Bus Layout"
+msgstr "Verander audiobus solo"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Toggle Audio Bus Mute"
-msgstr "Open Audio Bus Layout"
+msgstr "Verander audiobus stil"
#: editor/editor_audio_buses.cpp
msgid "Toggle Audio Bus Bypass Effects"
-msgstr ""
+msgstr "Verander audiobusomleiding"
#: editor/editor_audio_buses.cpp
+#, fuzzy
msgid "Select Audio Bus Send"
-msgstr ""
+msgstr "Selecteer audiobus verzend"
#: editor/editor_audio_buses.cpp
msgid "Add Audio Bus Effect"
-msgstr ""
+msgstr "Voeg audiobuseffect toe"
#: editor/editor_audio_buses.cpp
msgid "Move Bus Effect"
-msgstr ""
+msgstr "Verplaats audiobuseffect"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Delete Bus Effect"
-msgstr "Geselecteerde Verwijderen"
+msgstr "Verwijder audiobuseffect"
#: editor/editor_audio_buses.cpp
msgid "Audio Bus, Drag and Drop to rearrange."
-msgstr ""
-
-#: editor/editor_audio_buses.cpp
-msgid "Bus options"
-msgstr ""
+msgstr "Audiobus, versleep om volgorde te veranderen."
#: editor/editor_audio_buses.cpp
msgid "Solo"
-msgstr ""
+msgstr "Solo"
#: editor/editor_audio_buses.cpp
msgid "Mute"
-msgstr ""
+msgstr "Stil"
#: editor/editor_audio_buses.cpp
msgid "Bypass"
-msgstr ""
+msgstr "Omleiden"
+
+#: editor/editor_audio_buses.cpp
+msgid "Bus options"
+msgstr "Audiobusopties"
#: editor/editor_audio_buses.cpp editor/plugins/tile_map_editor_plugin.cpp
#: editor/scene_tree_dock.cpp
msgid "Duplicate"
-msgstr ""
+msgstr "Dupliceren"
+
+#: editor/editor_audio_buses.cpp
+msgid "Reset Volume"
+msgstr "Herstel Volume"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Delete Effect"
-msgstr "Geselecteerde Verwijderen"
+msgstr "Effect Verwijderen"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Add Audio Bus"
-msgstr "Bus Toevoegen"
+msgstr "Audiobus Toevoegen"
#: editor/editor_audio_buses.cpp
msgid "Master bus can't be deleted!"
-msgstr ""
+msgstr "Hoofdaudiobus kan niet verwijderd worden!"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Delete Audio Bus"
-msgstr "Optimaliseer Animatie"
+msgstr "Verwijder audiobus"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Duplicate Audio Bus"
-msgstr "Dupliceer Selectie"
+msgstr "Dupliceer Audiobus"
+
+#: editor/editor_audio_buses.cpp
+msgid "Reset Bus Volume"
+msgstr "Reset Audiobus Volume"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Move Audio Bus"
-msgstr "Open Audio Bus Layout"
+msgstr "Verplaats audiobus"
#: editor/editor_audio_buses.cpp
msgid "Save Audio Bus Layout As.."
@@ -1125,32 +941,32 @@ msgstr "Locatie voor Nieuwe Layout.."
#: editor/editor_audio_buses.cpp
msgid "Open Audio Bus Layout"
-msgstr "Open Audio Bus Layout"
+msgstr "Open Audio Bus Lay-out"
#: editor/editor_audio_buses.cpp
msgid "There is no 'res://default_bus_layout.tres' file."
-msgstr ""
+msgstr "Er is geen 'res://default_bus_layout.tres' bestand."
#: editor/editor_audio_buses.cpp
msgid "Invalid file, not an audio bus layout."
-msgstr ""
+msgstr "Ongeldig bestand, geen audiobus layout."
#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr "Bus Toevoegen"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Create a new Bus Layout."
-msgstr "Sla Audio Bus Layout Op Als.."
+msgstr "Maak een nieuwe audiobus layout."
-#: editor/editor_audio_buses.cpp editor/script_create_dialog.cpp
+#: editor/editor_audio_buses.cpp editor/property_editor.cpp
+#: editor/script_create_dialog.cpp
msgid "Load"
msgstr "Laden"
#: editor/editor_audio_buses.cpp
msgid "Load an existing Bus Layout."
-msgstr ""
+msgstr "Laad een bestaand audiobus layout."
#: editor/editor_audio_buses.cpp
#: editor/plugins/animation_player_editor_plugin.cpp
@@ -1158,18 +974,16 @@ msgid "Save As"
msgstr "Opslaan Als"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Save this Bus Layout to a file."
-msgstr "Sla Audio Bus Layout Op Als.."
+msgstr "Sla deze audiobus layout op in een bestand."
#: editor/editor_audio_buses.cpp editor/import_dock.cpp
-#, fuzzy
msgid "Load Default"
-msgstr "Standaard"
+msgstr "Laad Standaard"
#: editor/editor_audio_buses.cpp
msgid "Load the default Bus Layout."
-msgstr ""
+msgstr "Laad de standaard audiobus layout."
#: editor/editor_autoload_settings.cpp
msgid "Invalid name."
@@ -1220,7 +1034,7 @@ msgstr "Autoload Hernoemen"
#: editor/editor_autoload_settings.cpp
msgid "Toggle AutoLoad Globals"
-msgstr "Toggle AutoLoad Globals"
+msgstr "AutoLoad-Globalen omschakelen"
#: editor/editor_autoload_settings.cpp
msgid "Move Autoload"
@@ -1239,7 +1053,7 @@ msgid "Rearrange Autoloads"
msgstr "Herschik Autoloads"
#: editor/editor_autoload_settings.cpp editor/editor_file_dialog.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp scene/gui/file_dialog.cpp
+#: scene/gui/file_dialog.cpp
msgid "Path:"
msgstr "Pad:"
@@ -1247,9 +1061,7 @@ msgstr "Pad:"
msgid "Node Name:"
msgstr "Node Naam:"
-#: editor/editor_autoload_settings.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp editor/project_manager.cpp
+#: editor/editor_autoload_settings.cpp editor/project_manager.cpp
msgid "Name"
msgstr "Naam"
@@ -1275,25 +1087,26 @@ msgstr "Scene aan het updaten.."
#: editor/editor_dir_dialog.cpp
msgid "Please select a base directory first"
-msgstr ""
+msgstr "Kies eerst een basisfolder"
#: editor/editor_dir_dialog.cpp
msgid "Choose a Directory"
msgstr "Kies een Map"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Create Folder"
msgstr "Map Maken"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: editor/editor_plugin_settings.cpp editor/plugins/theme_editor_plugin.cpp
-#: editor/project_export.cpp scene/gui/file_dialog.cpp
+#: editor/editor_plugin_settings.cpp editor/filesystem_dock.cpp
+#: editor/plugins/theme_editor_plugin.cpp editor/project_export.cpp
+#: scene/gui/file_dialog.cpp
msgid "Name:"
msgstr "Naam:"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Could not create folder."
msgstr "Map kon niet gemaakt worden."
@@ -1302,12 +1115,10 @@ msgid "Choose"
msgstr "Kies"
#: editor/editor_export.cpp
-#, fuzzy
msgid "Storing File:"
-msgstr "Opslag Bestand:"
+msgstr "Bestand Opslaan:"
#: editor/editor_export.cpp
-#, fuzzy
msgid "Packing"
msgstr "Inpakken"
@@ -1315,30 +1126,6 @@ msgstr "Inpakken"
msgid "Template file not found:\n"
msgstr "Template bestand niet gevonden:\n"
-#: editor/editor_export.cpp
-msgid "Added:"
-msgstr "Toegevoegd:"
-
-#: editor/editor_export.cpp
-msgid "Removed:"
-msgstr "Verwijderd:"
-
-#: editor/editor_export.cpp
-msgid "Error saving atlas:"
-msgstr "Error bij het opslaan van atlas:"
-
-#: editor/editor_export.cpp
-msgid "Could not save atlas subtexture:"
-msgstr "Kon atlas subtexture niet opslaan:"
-
-#: editor/editor_export.cpp
-msgid "Exporting for %s"
-msgstr "Aan het exporteren voor %s"
-
-#: editor/editor_export.cpp
-msgid "Setting Up.."
-msgstr "Aan Het Opzetten.."
-
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "File Exists, Overwrite?"
msgstr "Bestand Bestaat, Overschrijven?"
@@ -1423,13 +1210,17 @@ msgstr "Verplaats Favoriet Naar Boven"
msgid "Move Favorite Down"
msgstr "Verplaats Favoriet Naar Beneden"
+#: editor/editor_file_dialog.cpp
+msgid "Go to parent folder"
+msgstr "Ga naar bovenliggende folder"
+
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Directories & Files:"
msgstr "Mappen & Bestanden:"
#: editor/editor_file_dialog.cpp
msgid "Preview:"
-msgstr "Preview:"
+msgstr "Voorbeeld:"
#: editor/editor_file_dialog.cpp editor/script_editor_debugger.cpp
#: scene/gui/file_dialog.cpp
@@ -1437,10 +1228,6 @@ msgid "File:"
msgstr "Bestand:"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
-msgid "Filter:"
-msgstr "Filter:"
-
-#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Must use a valid extension."
msgstr "Een geldige extensie moet gebruikt worden."
@@ -1450,9 +1237,8 @@ msgid "ScanSources"
msgstr "Scan Bronnen"
#: editor/editor_file_system.cpp
-#, fuzzy
msgid "(Re)Importing Assets"
-msgstr "Aan Het Herimporteren"
+msgstr "Bronnen (Her)Importeren"
#: editor/editor_help.cpp editor/editor_node.cpp
#: editor/plugins/script_editor_plugin.cpp
@@ -1467,6 +1253,10 @@ msgstr "Klasse Lijst:"
msgid "Search Classes"
msgstr "Zoek Klasses"
+#: editor/editor_help.cpp editor/plugins/spatial_editor_plugin.cpp
+msgid "Top"
+msgstr "Boven"
+
#: editor/editor_help.cpp editor/property_editor.cpp
msgid "Class:"
msgstr "Klasse:"
@@ -1483,15 +1273,27 @@ msgstr "Geërfd door:"
msgid "Brief Description:"
msgstr "Korte Beschrijving:"
+#: editor/editor_help.cpp
+msgid "Members"
+msgstr "Leden"
+
#: editor/editor_help.cpp modules/visual_script/visual_script_editor.cpp
msgid "Members:"
msgstr "Leden:"
#: editor/editor_help.cpp
+msgid "Public Methods"
+msgstr "Publieke Methodes"
+
+#: editor/editor_help.cpp
msgid "Public Methods:"
msgstr "Publieke Methodes:"
#: editor/editor_help.cpp
+msgid "GUI Theme Items"
+msgstr "GUI Thema Items"
+
+#: editor/editor_help.cpp
msgid "GUI Theme Items:"
msgstr "GUI Thema Items:"
@@ -1500,55 +1302,85 @@ msgid "Signals:"
msgstr "Signalen:"
#: editor/editor_help.cpp
-#, fuzzy
+msgid "Enumerations"
+msgstr "Enumeraties"
+
+#: editor/editor_help.cpp
msgid "Enumerations:"
-msgstr "Functies:"
+msgstr "Enumeraties:"
#: editor/editor_help.cpp
msgid "enum "
-msgstr ""
+msgstr "enum "
+
+#: editor/editor_help.cpp
+msgid "Constants"
+msgstr "Constanten"
#: editor/editor_help.cpp
msgid "Constants:"
msgstr "Constanten:"
#: editor/editor_help.cpp
+msgid "Description"
+msgstr "Beschrijving"
+
+#: editor/editor_help.cpp
+msgid "Properties"
+msgstr "Eigenschappen"
+
+#: editor/editor_help.cpp
msgid "Property Description:"
msgstr "Eigenschap Beschrijving:"
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this property. Please help us by "
+"[color=$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+"Er is momenteel geen beschrijving voor deze eigenschap. Help ons alsjeblieft "
+"door [color=$color][url=$url]een toe te voegen[/url][/color]!"
+
+#: editor/editor_help.cpp
+msgid "Methods"
+msgstr "Methodes"
+
+#: editor/editor_help.cpp
msgid "Method Description:"
msgstr "Methode Beschrijving:"
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this method. Please help us by [color="
+"$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+"Er is momenteel geen beschrijving voor deze methode. Help ons alsjeblieft "
+"door [color=$color][url=$url]een toe te voegen[/url][/color]!"
+
+#: editor/editor_help.cpp
msgid "Search Text"
msgstr "Zoek Tekst"
#: editor/editor_log.cpp
-#, fuzzy
msgid "Output:"
-msgstr " Uitvoer:"
+msgstr "Uitvoer:"
#: editor/editor_log.cpp editor/plugins/animation_tree_editor_plugin.cpp
-#: editor/plugins/rich_text_editor_plugin.cpp editor/property_editor.cpp
-#: editor/script_editor_debugger.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/property_editor.cpp editor/script_editor_debugger.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Clear"
msgstr "Leegmaken"
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Error saving resource!"
msgstr "Error bij het opslaan van resource!"
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Save Resource As.."
msgstr "Resource Opslaan Als.."
-#: editor/editor_node.cpp editor/export_template_manager.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
-#, fuzzy
+#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "I see.."
msgstr "Ik snap het.."
@@ -1562,7 +1394,27 @@ msgstr "Opgevraagde bestandsformaat onbekend:"
#: editor/editor_node.cpp
msgid "Error while saving."
-msgstr "Error bij het opslaan."
+msgstr "Fout bij het opslaan."
+
+#: editor/editor_node.cpp
+msgid "Can't open '%s'."
+msgstr "Kan '%s' niet openen."
+
+#: editor/editor_node.cpp
+msgid "Error while parsing '%s'."
+msgstr "Fout tijdens het parsen van '%s'."
+
+#: editor/editor_node.cpp
+msgid "Unexpected end of file '%s'."
+msgstr "Onverwacht einde van het bestand '%s'."
+
+#: editor/editor_node.cpp
+msgid "Missing '%s' or its dependencies."
+msgstr "'%s' of zijn afhankelijkheden ontbreken."
+
+#: editor/editor_node.cpp
+msgid "Error while loading '%s'."
+msgstr "Fout tijdens het laden van '%s'."
#: editor/editor_node.cpp
msgid "Saving Scene"
@@ -1578,7 +1430,7 @@ msgstr "Thumbnail Aan Het Maken"
#: editor/editor_node.cpp
msgid "This operation can't be done without a tree root."
-msgstr ""
+msgstr "Deze operatie kan niet gedaan worden zonder boomwortel."
#: editor/editor_node.cpp
msgid ""
@@ -1613,47 +1465,89 @@ msgstr "Error bij het opslaan van layout!"
#: editor/editor_node.cpp
msgid "Default editor layout overridden."
-msgstr ""
+msgstr "Standaard editor layout overschreven."
#: editor/editor_node.cpp
msgid "Layout name not found!"
-msgstr ""
+msgstr "Lay-out naam niet gevonden!"
#: editor/editor_node.cpp
msgid "Restored default layout to base settings."
+msgstr "Standaard layout hersteld naar basisinstellingen."
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid ""
+"This resource belongs to a scene that was imported, so it's not editable.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
msgstr ""
+"Dit bestand hoort bij een scene die geïmporteerd werd, dus het is niet "
+"bewerkbaar.\n"
+"Lees de documentatie over scenes importeren om deze workflow beter te "
+"begrijpen."
#: editor/editor_node.cpp
-msgid "Copy Params"
+msgid ""
+"This resource belongs to a scene that was instanced or inherited.\n"
+"Changes to it will not be kept when saving the current scene."
msgstr ""
+"Dit bestand hoort bij een scene die werd geïnstantieerd of overgeërfd.\n"
+"Aanpassingen zullen niet worden bijgehouden bij het opslaan van de huidige "
+"scene."
#: editor/editor_node.cpp
-msgid "Paste Params"
+msgid ""
+"This resource was imported, so it's not editable. Change its settings in the "
+"import panel and then re-import."
+msgstr ""
+"Dit bestand werd geïmporteerd, dus het is niet bewerkbaar. Pas de "
+"instellingen aan in het importeerpaneel en importeer het nadien opnieuw."
+
+#: editor/editor_node.cpp
+msgid ""
+"This scene was imported, so changes to it will not be kept.\n"
+"Instancing it or inheriting will allow making changes to it.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
msgstr ""
+"Deze scene werd geïmporteerd, dus aanpassingen zullen niet worden "
+"opgeslagen.\n"
+"Instantieer het of erf het over om er aanpassingen aan te maken.\n"
+"Lees de documentatie over scenes importeren om deze workflow beter te "
+"begrijpen."
+
+#: editor/editor_node.cpp
+msgid "Copy Params"
+msgstr "Kopieer Parameters"
+
+#: editor/editor_node.cpp
+msgid "Paste Params"
+msgstr "Plak Parameters"
#: editor/editor_node.cpp editor/plugins/resource_preloader_editor_plugin.cpp
msgid "Paste Resource"
-msgstr ""
+msgstr "Plak Bron"
#: editor/editor_node.cpp
msgid "Copy Resource"
-msgstr ""
+msgstr "Kopieer Bron"
#: editor/editor_node.cpp
msgid "Make Built-In"
-msgstr ""
+msgstr "Integreer"
#: editor/editor_node.cpp
msgid "Make Sub-Resources Unique"
-msgstr ""
+msgstr "Maak Onderliggende Bronnen Uniek"
#: editor/editor_node.cpp
msgid "Open in Help"
-msgstr ""
+msgstr "Open in Help"
#: editor/editor_node.cpp
msgid "There is no defined scene to run."
-msgstr ""
+msgstr "Er is geen startscene gedefinieerd."
#: editor/editor_node.cpp
msgid ""
@@ -1661,6 +1555,9 @@ msgid ""
"You can change it later in \"Project Settings\" under the 'application' "
"category."
msgstr ""
+"Er is nooit een hoofdscene gekozen, wil je er een selecteren?\n"
+"Je kan dit later nog aanpassen in \"Projectinstellingen\" onder de categorie "
+"'toepassing'."
#: editor/editor_node.cpp
msgid ""
@@ -1668,6 +1565,9 @@ msgid ""
"You can change it later in \"Project Settings\" under the 'application' "
"category."
msgstr ""
+"De geselecteerde scene '%s' bestaat niet, selecteer een andere?\n"
+"Je kan dit later aanpassen in \"Projectinstellingen\" onder de categorie "
+"'toepassing'."
#: editor/editor_node.cpp
msgid ""
@@ -1675,169 +1575,197 @@ msgid ""
"You can change it later in \"Project Settings\" under the 'application' "
"category."
msgstr ""
+"De geselecteerde scene '%s' is geen scenebestand, selecteer een andere?\n"
+"Je kan dit later aanpassen in \"Projectinstellingen\" onder de categorie "
+"'toepassing'."
#: editor/editor_node.cpp
msgid "Current scene was never saved, please save it prior to running."
-msgstr ""
+msgstr "De huidige scene werd nooit opgeslagen, sla ze op voor het uitvoeren."
#: editor/editor_node.cpp
msgid "Could not start subprocess!"
-msgstr ""
+msgstr "Kon het subproces niet opstarten!"
#: editor/editor_node.cpp
msgid "Open Scene"
-msgstr ""
+msgstr "Scene Openen"
#: editor/editor_node.cpp
msgid "Open Base Scene"
-msgstr ""
+msgstr "Open Basisscene"
#: editor/editor_node.cpp
msgid "Quick Open Scene.."
-msgstr ""
+msgstr "Open Scene Snel..."
#: editor/editor_node.cpp
msgid "Quick Open Script.."
-msgstr ""
+msgstr "Open Script Snel..."
#: editor/editor_node.cpp
-#, fuzzy
msgid "Save & Close"
-msgstr "Sla een Bestand Op"
+msgstr "Opslaan & Sluiten"
#: editor/editor_node.cpp
msgid "Save changes to '%s' before closing?"
-msgstr ""
+msgstr "Sla wijzigen aan '%s' op voor het afsluiten?"
#: editor/editor_node.cpp
msgid "Save Scene As.."
-msgstr ""
+msgstr "Sla Scene Op Als..."
#: editor/editor_node.cpp
msgid "No"
-msgstr ""
+msgstr "Nee"
#: editor/editor_node.cpp
msgid "Yes"
-msgstr ""
+msgstr "Ja"
#: editor/editor_node.cpp
msgid "This scene has never been saved. Save before running?"
-msgstr ""
+msgstr "Deze scene is nooit opgeslagen. Sla op voor het uitvoeren?"
#: editor/editor_node.cpp editor/scene_tree_dock.cpp
msgid "This operation can't be done without a scene."
-msgstr ""
+msgstr "Deze operatie kan niet uitgevoerd worden zonder scene."
#: editor/editor_node.cpp
msgid "Export Mesh Library"
-msgstr ""
+msgstr "Exporteer Mesh Library"
#: editor/editor_node.cpp
msgid "Export Tile Set"
-msgstr ""
+msgstr "Exporteer Tile Set"
#: editor/editor_node.cpp
msgid "This operation can't be done without a selected node."
msgstr ""
+"Deze operatie kan niet uitgevoerd worden zonder een geselecteerde knoop."
#: editor/editor_node.cpp
msgid "Current scene not saved. Open anyway?"
-msgstr ""
+msgstr "De huidige scene is nog niet opgeslagen. Toch openen?"
#: editor/editor_node.cpp
msgid "Can't reload a scene that was never saved."
-msgstr ""
+msgstr "Een scene die nooit opgeslagen is kan je niet opnieuw laden."
#: editor/editor_node.cpp
msgid "Revert"
-msgstr ""
+msgstr "Herstellen"
#: editor/editor_node.cpp
msgid "This action cannot be undone. Revert anyway?"
-msgstr ""
+msgstr "Deze actie kan niet ongedaan gemaakt worden. Toch herstellen?"
#: editor/editor_node.cpp
msgid "Quick Run Scene.."
-msgstr ""
+msgstr "Snel Scene Uitvoeren..."
#: editor/editor_node.cpp
msgid "Quit"
-msgstr ""
+msgstr "Afsluiten"
#: editor/editor_node.cpp
msgid "Exit the editor?"
-msgstr ""
+msgstr "Sluit de editor af?"
#: editor/editor_node.cpp
msgid "Open Project Manager?"
-msgstr ""
+msgstr "Open de Project Manager?"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Save & Quit"
-msgstr "Sla een Bestand Op"
+msgstr "Opslaan & Afsluiten"
#: editor/editor_node.cpp
msgid "Save changes to the following scene(s) before quitting?"
msgstr ""
+"Wil je de wijzigen aan de volgende scene(s) opslaan voor het afsluiten?"
#: editor/editor_node.cpp
msgid "Save changes the following scene(s) before opening Project Manager?"
msgstr ""
+"Wil je de wijzigen aan de volgende scene(s) opslaan voor de Project Manager "
+"opent?"
#: editor/editor_node.cpp
-msgid "Pick a Main Scene"
+msgid ""
+"This option is deprecated. Situations where refresh must be forced are now "
+"considered a bug. Please report."
msgstr ""
+"Deze optie is verouderd. Situaties waar een hernieuwing geforceerd moet "
+"worden zijn softwarefouten. Rapporteer dit alsjeblieft."
#: editor/editor_node.cpp
-msgid "Unable to enable addon plugin at: '"
-msgstr ""
+msgid "Pick a Main Scene"
+msgstr "Kies een Hoofdscene"
#: editor/editor_node.cpp
-msgid "' parsing of config failed."
-msgstr ""
+#, fuzzy
+msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
+msgstr "Onmogelijk om de plugin op: '"
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/"
-msgstr ""
+#, fuzzy
+msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
+msgstr "Onmogelijk om scriptveld te vinden voor de plugin op: 'res://addons/"
#: editor/editor_node.cpp
-msgid "Unable to load addon script from path: '"
-msgstr ""
+#, fuzzy
+msgid "Unable to load addon script from path: '%s'."
+msgstr "Volgend script kon niet geladen worden: '"
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid ""
+"Unable to load addon script from path: '%s' Base type is not EditorPlugin."
+msgstr "Volgend script kon niet geladen worden: '"
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Unable to load addon script from path: '%s' Script is not in tool mode."
+msgstr "Volgend script kon niet geladen worden: '"
#: editor/editor_node.cpp
msgid ""
"Scene '%s' was automatically imported, so it can't be modified.\n"
"To make changes to it, a new inherited scene can be created."
msgstr ""
+"Scene '%s' werd automatisch geïmporteerd, dus ze kan niet aangepast worden.\n"
+"Om aanpassingen te doen kan je een erfende scene aanmaken."
#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/scene_tree_dock.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Ugh"
-msgstr ""
+msgstr "Oeps"
#: editor/editor_node.cpp
msgid ""
"Error loading scene, it must be inside the project path. Use 'Import' to "
"open the scene, then save it inside the project path."
msgstr ""
+"Fout tijdens het laden van de scene, ze moet zich in het projectpad "
+"bevinden. Gebruik 'Importeer' om de scene te openen en sla ze nadien ergens "
+"in het projectpad op."
#: editor/editor_node.cpp
-msgid "Error loading scene."
-msgstr ""
+msgid "Scene '%s' has broken dependencies:"
+msgstr "De scene '%s' heeft kapotte afhankelijkheden:"
#: editor/editor_node.cpp
-msgid "Scene '%s' has broken dependencies:"
-msgstr ""
+msgid "Clear Recent Scenes"
+msgstr "Maak Leeg"
#: editor/editor_node.cpp
msgid "Save Layout"
-msgstr ""
+msgstr "Layout Opslaan"
#: editor/editor_node.cpp
msgid "Delete Layout"
-msgstr ""
+msgstr "Layout Verwijderen"
#: editor/editor_node.cpp editor/import_dock.cpp
#: editor/script_create_dialog.cpp
@@ -1846,87 +1774,87 @@ msgstr "Standaard"
#: editor/editor_node.cpp
msgid "Switch Scene Tab"
-msgstr ""
+msgstr "Scenetab Wisselen"
#: editor/editor_node.cpp
msgid "%d more file(s)"
-msgstr ""
+msgstr "nog %d bestand(en)"
#: editor/editor_node.cpp
msgid "%d more file(s) or folder(s)"
-msgstr ""
+msgstr "nog %d bestand(en) of folder(s)"
#: editor/editor_node.cpp
msgid "Distraction Free Mode"
-msgstr ""
+msgstr "Afleidingsvrije Modus"
#: editor/editor_node.cpp
msgid "Toggle distraction-free mode."
-msgstr ""
+msgstr "Afleidingsvrije modus veranderen."
-#: editor/editor_node.cpp editor/io_plugins/editor_scene_import_plugin.cpp
+#: editor/editor_node.cpp
msgid "Scene"
-msgstr ""
+msgstr "Scène"
#: editor/editor_node.cpp
msgid "Go to previously opened scene."
-msgstr ""
+msgstr "Ga naar de vorige geopende scene."
#: editor/editor_node.cpp
msgid "Next tab"
-msgstr ""
+msgstr "Volgend tabblad"
#: editor/editor_node.cpp
msgid "Previous tab"
-msgstr ""
+msgstr "Vorig tabblad"
#: editor/editor_node.cpp
msgid "Filter Files.."
-msgstr ""
+msgstr "Bestanden Filteren..."
#: editor/editor_node.cpp
msgid "Operations with scene files."
-msgstr ""
+msgstr "Operaties met scenebestanden."
#: editor/editor_node.cpp
msgid "New Scene"
-msgstr ""
+msgstr "Nieuwe Scene"
#: editor/editor_node.cpp
msgid "New Inherited Scene.."
-msgstr ""
+msgstr "Nieuwe Geërfde Scene..."
#: editor/editor_node.cpp
msgid "Open Scene.."
-msgstr ""
+msgstr "Scene Openen..."
#: editor/editor_node.cpp
msgid "Save Scene"
-msgstr ""
+msgstr "Scene Opslaan"
#: editor/editor_node.cpp
msgid "Save all Scenes"
-msgstr ""
+msgstr "Alle Scenes Opslaan"
#: editor/editor_node.cpp
msgid "Close Scene"
-msgstr ""
+msgstr "Scene Sluiten"
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
msgid "Open Recent"
-msgstr ""
+msgstr "Recente Scenes Openen"
#: editor/editor_node.cpp
msgid "Convert To.."
-msgstr ""
+msgstr "Converteer Naar..."
#: editor/editor_node.cpp
msgid "MeshLibrary.."
-msgstr ""
+msgstr "MeshLibrary..."
#: editor/editor_node.cpp
msgid "TileSet.."
-msgstr ""
+msgstr "TileSet..."
#: editor/editor_node.cpp editor/plugins/script_text_editor.cpp
#: editor/plugins/shader_editor_plugin.cpp scene/gui/line_edit.cpp
@@ -1937,57 +1865,59 @@ msgstr "Ongedaan Maken"
#: editor/editor_node.cpp editor/plugins/script_text_editor.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Redo"
-msgstr ""
+msgstr "Opnieuw"
#: editor/editor_node.cpp
msgid "Revert Scene"
-msgstr ""
+msgstr "Scene Herstellen"
#: editor/editor_node.cpp
msgid "Miscellaneous project or scene-wide tools."
-msgstr ""
+msgstr "Diverse project of scene-brede gereedschappen."
#: editor/editor_node.cpp
msgid "Project"
-msgstr ""
+msgstr "Project"
#: editor/editor_node.cpp
msgid "Project Settings"
-msgstr ""
+msgstr "Projectinstellingen"
#: editor/editor_node.cpp
msgid "Run Script"
-msgstr ""
+msgstr "Voer Script Uit"
#: editor/editor_node.cpp editor/project_export.cpp
msgid "Export"
-msgstr ""
+msgstr "Exporteren"
#: editor/editor_node.cpp
msgid "Tools"
-msgstr ""
+msgstr "Gereedschappen"
#: editor/editor_node.cpp
msgid "Quit to Project List"
-msgstr ""
+msgstr "Sluit af naar Projectlijst"
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
msgid "Debug"
-msgstr ""
+msgstr "Debuggen"
#: editor/editor_node.cpp
msgid "Deploy with Remote Debug"
-msgstr ""
+msgstr "Start met Debuggen op Afstand"
#: editor/editor_node.cpp
msgid ""
"When exporting or deploying, the resulting executable will attempt to "
"connect to the IP of this computer in order to be debugged."
msgstr ""
+"Na het exporteren of opstarten van het programma zal het proberen verbinding "
+"maken met het IP-adres van deze computer zodat het gedebugd kan worden."
#: editor/editor_node.cpp
msgid "Small Deploy with Network FS"
-msgstr ""
+msgstr "Kleine Deployatie over het Netwerk"
#: editor/editor_node.cpp
msgid ""
@@ -2001,7 +1931,7 @@ msgstr ""
#: editor/editor_node.cpp
msgid "Visible Collision Shapes"
-msgstr ""
+msgstr "Collision Shapes Zichtbaar"
#: editor/editor_node.cpp
msgid ""
@@ -2011,7 +1941,7 @@ msgstr ""
#: editor/editor_node.cpp
msgid "Visible Navigation"
-msgstr ""
+msgstr "Navigatie Zichtbaar"
#: editor/editor_node.cpp
msgid ""
@@ -2084,6 +2014,10 @@ msgstr ""
msgid "Issue Tracker"
msgstr ""
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+msgid "Community"
+msgstr "Gemeenschap"
+
#: editor/editor_node.cpp
msgid "About"
msgstr ""
@@ -2092,7 +2026,7 @@ msgstr ""
msgid "Play the project."
msgstr ""
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Play"
msgstr ""
@@ -2108,7 +2042,7 @@ msgstr ""
msgid "Stop the scene."
msgstr ""
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Stop"
msgstr ""
@@ -2181,6 +2115,15 @@ msgid "Object properties."
msgstr ""
#: editor/editor_node.cpp
+msgid "Changes may be lost!"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Import"
+msgstr "Importeren"
+
+#: editor/editor_node.cpp
msgid "FileSystem"
msgstr ""
@@ -2196,14 +2139,6 @@ msgstr ""
msgid "Don't Save"
msgstr ""
-#: editor/editor_node.cpp editor/editor_reimport_dialog.cpp
-msgid "Re-Import"
-msgstr ""
-
-#: editor/editor_node.cpp editor/editor_plugin_settings.cpp
-msgid "Update"
-msgstr ""
-
#: editor/editor_node.cpp
msgid "Import Templates From ZIP File"
msgstr ""
@@ -2269,11 +2204,28 @@ msgstr "Afhankelijkheden Editor"
msgid "Open the previous Editor"
msgstr ""
+#: editor/editor_plugin.cpp
+msgid "Creating Mesh Previews"
+msgstr ""
+
+#: editor/editor_plugin.cpp
+msgid "Thumbnail.."
+msgstr ""
+
#: editor/editor_plugin_settings.cpp
msgid "Installed Plugins:"
msgstr ""
#: editor/editor_plugin_settings.cpp
+msgid "Update"
+msgstr ""
+
+#: editor/editor_plugin_settings.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Version:"
+msgstr "Versie:"
+
+#: editor/editor_plugin_settings.cpp
msgid "Author:"
msgstr ""
@@ -2306,7 +2258,7 @@ msgid "Frame %"
msgstr ""
#: editor/editor_profiler.cpp
-msgid "Fixed Frame %"
+msgid "Physics Frame %"
msgstr ""
#: editor/editor_profiler.cpp editor/script_editor_debugger.cpp
@@ -2325,26 +2277,6 @@ msgstr ""
msgid "Frame #:"
msgstr ""
-#: editor/editor_reimport_dialog.cpp
-msgid "Please wait for scan to complete."
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Current scene must be saved to re-import."
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Save & Re-Import"
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Importing"
-msgstr "Aan Het Herimporteren"
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Import Changed Resources"
-msgstr ""
-
#: editor/editor_run_native.cpp
msgid "Select device from the list"
msgstr ""
@@ -2455,10 +2387,6 @@ msgid "Importing:"
msgstr "Aan Het Importeren:"
#: editor/export_template_manager.cpp
-msgid "Loading Export Templates"
-msgstr ""
-
-#: editor/export_template_manager.cpp
msgid "Current Version:"
msgstr ""
@@ -2493,9 +2421,17 @@ msgid "Cannot navigate to '"
msgstr ""
#: editor/filesystem_dock.cpp
+msgid "View items as a grid of thumbnails"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "View items as a list"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
msgid ""
"\n"
-"Status: Needs Re-Import"
+"Status: Import of file failed. Please fix file and reimport manually."
msgstr ""
#: editor/filesystem_dock.cpp
@@ -2506,45 +2442,51 @@ msgid ""
msgstr "Resource"
#: editor/filesystem_dock.cpp
-msgid "Same source and destination files, doing nothing."
+msgid "Cannot move/rename resources root."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Target file exists, can't overwrite. Delete first."
+msgid "Cannot move a folder into itself.\n"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Same source and destination paths, doing nothing."
-msgstr ""
+#, fuzzy
+msgid "Error moving:\n"
+msgstr "Error bij het laden van:"
+
+#: editor/filesystem_dock.cpp
+#, fuzzy
+msgid "Unable to update dependencies:\n"
+msgstr "Scene faalde om te laden door ontbrekende afhankelijkheden:"
#: editor/filesystem_dock.cpp
-msgid "Can't move directories to within themselves."
+msgid "No name provided"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Can't rename deps for:\n"
+msgid "Provided name contains invalid characters"
msgstr ""
#: editor/filesystem_dock.cpp
-#, fuzzy
-msgid "Error moving file:\n"
-msgstr "Error bij het opslaan van TileSet!"
+msgid "No name provided."
+msgstr ""
#: editor/filesystem_dock.cpp
#, fuzzy
-msgid "Error moving dir:\n"
-msgstr "Error bij het laden van:"
+msgid "Name contains invalid characters."
+msgstr "Geldige karakters:"
#: editor/filesystem_dock.cpp
-msgid "Can't operate on '..'"
+msgid "A file or folder with this name already exists."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Pick New Name and Location For:"
-msgstr ""
+#, fuzzy
+msgid "Renaming file:"
+msgstr "Hernoem Variabele"
#: editor/filesystem_dock.cpp
-msgid "No files selected!"
+msgid "Renaming folder:"
msgstr ""
#: editor/filesystem_dock.cpp
@@ -2556,39 +2498,36 @@ msgid "Collapse all"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Show In File Manager"
-msgstr ""
-
-#: editor/filesystem_dock.cpp
-msgid "Instance"
+msgid "Copy Path"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Edit Dependencies.."
+msgid "Rename.."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "View Owners.."
+msgid "Move To.."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Copy Path"
-msgstr ""
+#, fuzzy
+msgid "New Folder.."
+msgstr "Map Maken"
#: editor/filesystem_dock.cpp
-msgid "Rename or Move.."
+msgid "Show In File Manager"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Move To.."
+msgid "Instance"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Info"
+msgid "Edit Dependencies.."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Re-Import.."
+msgid "View Owners.."
msgstr ""
#: editor/filesystem_dock.cpp
@@ -2621,6 +2560,11 @@ msgstr ""
msgid "Move"
msgstr ""
+#: editor/filesystem_dock.cpp editor/plugins/animation_tree_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Rename"
+msgstr ""
+
#: editor/groups_editor.cpp
msgid "Add to Group"
msgstr ""
@@ -2635,6 +2579,10 @@ msgid "Import as Single Scene"
msgstr "Scene aan het Updaten"
#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
msgid "Import with Separate Materials"
msgstr ""
@@ -2647,6 +2595,18 @@ msgid "Import with Separate Objects+Materials"
msgstr ""
#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Materials+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Materials+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
msgid "Import as Multiple Scenes"
msgstr ""
@@ -2655,38 +2615,31 @@ msgid "Import as Multiple Scenes+Materials"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Import Scene"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Importing Scene.."
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Running Custom Script.."
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Couldn't load post-import script:"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Invalid/broken script for post-import (check console):"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Error running post-import script:"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Saving.."
msgstr ""
@@ -2717,579 +2670,54 @@ msgstr ""
msgid "Reimport"
msgstr "Aan Het Herimporteren"
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "No bit masks to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path is empty."
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must be a complete resource path."
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must exist."
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Save path is empty!"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Import BitMasks"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s):"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Target Path:"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Accept"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Bit Mask"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No source font file!"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No target font resource!"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"Invalid file extension.\n"
-"Please use .font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Can't load/process source font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Couldn't save font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font Size:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Dest Resource:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "The quick brown fox jumps over the lazy dog."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Test:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Options:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Font Import"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"This file is already a Godot font file, please supply a BMFont type file "
-"instead."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Failed opening as BMFont file."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error initializing FreeType."
-msgstr "Error bij het initialiseren van FreeType."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Unknown font format."
-msgstr "Onbekende lettertype formaat."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error loading font."
-msgstr "Error bij het laden van lettertype."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Invalid font size."
-msgstr "Ongeldige lettertype grootte."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Invalid font custom source."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/plugins/theme_editor_plugin.cpp
-msgid "Font"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "No meshes to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Single Mesh Import"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Source Mesh(es):"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/plugins/mesh_instance_editor_plugin.cpp
-msgid "Mesh"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Surface %d"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "No samples to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Import Audio Samples"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Source Sample(s):"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Audio Sample"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "New Clip"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Animation Options"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Flags"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Bake FPS:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Optimizer"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Linear Error"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angular Error"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angle"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Clips"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Start(s)"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "End(s)"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Loop"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Filters"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source path is empty."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't load post-import script."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Invalid/broken script for post-import."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Error importing scene."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import 3D Scene"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source Scene:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Same as Target Scene"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Shared"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Target Texture Folder:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Post-Process Script:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Custom Root Node Type:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Auto"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Root Node Name:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "The Following Files are Missing:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Anyway"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp scene/gui/dialogs.cpp
-msgid "Cancel"
-msgstr "Annuleren"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import & Open"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Edited scene has not been saved, open imported scene anyway?"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Image:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Can't import a file over itself:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't localize path: %s (already local)"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "3D Scene Animation"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Uncompressed"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossless (PNG)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossy (WebP)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress (VRAM)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Format"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Compression Quality (WebP):"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Options"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Please specify some files!"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "At least one file needed for Atlas."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Error importing:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Only one file is required for large texture."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Max Texture Size:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for Atlas (2D)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cell Size:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Large Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Textures (2D)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture"
+#: editor/multi_node_edit.cpp
+msgid "MultiNode Set"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Base Atlas Texture"
+#: editor/node_dock.cpp
+msgid "Groups"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s)"
+#: editor/node_dock.cpp
+msgid "Select a Node to edit Signals and Groups."
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 2D"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create Poly"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 3D"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Insert Point"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "2D Texture"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly (Remove Point)"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "3D Texture"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Remove Poly And Point"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Atlas Texture"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create a new polygon from scratch."
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
+#: editor/plugins/abstract_polygon_2d_editor.cpp
msgid ""
-"NOTICE: Importing 2D textures is not mandatory. Just copy png/jpg files to "
-"the project."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Crop empty space."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Load Source Image"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Slicing"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Inserting"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Saving"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save large texture:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Build Atlas For:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Loading Image:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't load image:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Converting Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cropping Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Blitting Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save atlas image:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save converted texture:"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid source!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid translation source!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Column"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/script_create_dialog.cpp
-msgid "Language"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No items to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No target path!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translations"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Couldn't import!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translation"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Source CSV:"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Ignore First Row"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Compress"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Add to Project (project.godot)"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Languages:"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Translation"
-msgstr ""
-
-#: editor/multi_node_edit.cpp
-msgid "MultiNode Set"
-msgstr ""
-
-#: editor/node_dock.cpp
-msgid "Groups"
-msgstr ""
-
-#: editor/node_dock.cpp
-msgid "Select a Node to edit Signals and Groups."
+"Edit existing polygon:\n"
+"LMB: Move Point.\n"
+"Ctrl+LMB: Split Segment.\n"
+"RMB: Erase Point."
msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
@@ -3446,7 +2874,6 @@ msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
#: editor/script_create_dialog.cpp
msgid "Error!"
@@ -3557,10 +2984,6 @@ msgid "Delete Input"
msgstr ""
#: editor/plugins/animation_tree_editor_plugin.cpp
-msgid "Rename"
-msgstr ""
-
-#: editor/plugins/animation_tree_editor_plugin.cpp
msgid "Animation tree is valid."
msgstr ""
@@ -3616,64 +3039,182 @@ msgstr ""
msgid "Filters.."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing %d Triangles:"
-msgstr ""
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Free"
+msgstr "Vrij"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Triangle #"
-msgstr ""
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Contents:"
+msgstr "Inhoud:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "View Files"
+msgstr "Bekijk Bestanden"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Light Baker Setup:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve hostname:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing Geometry"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Fixing Lights"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connection error, please try again."
+msgstr "Verbindingsfout, probeer het nog eens."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't connect."
+msgstr "Kan niet verbinden."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't connect to host:"
+msgstr "Kan niet verbinden met host:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response from host:"
+msgstr "Geen antwoord van host:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response."
+msgstr "Geen antwoord."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, return code:"
+msgstr "Aanvraag mislukt, retourcode:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Req. Failed."
+msgstr "Aanv. Mislukt."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, too many redirects"
+msgstr "Aanvraag mislukt, te veel redirects"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Redirect Loop."
+msgstr "Redirectlus."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed:"
+msgstr "Mislukt:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Bad download hash, assuming file has been tampered with."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Making BVH"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Expected:"
+msgstr "Verwacht:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Got:"
+msgstr "Gekregen:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed sha256 hash check"
+msgstr "Sha256 hash controle mislukt"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Asset Download Error:"
+msgstr "Asset download fout:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Fetching:"
+msgstr "Ophalen:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Resolving.."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Light Octree"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connecting.."
+msgstr "Verbinden.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Requesting.."
+msgstr "Opvragen..."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Error making request"
+msgstr "Fout bij opvragen"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Idle"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Octree Texture"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Retry"
+msgstr "Probeer opnieuw"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download Error"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Transfer to Lightmaps:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download for this asset is already in progress!"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Allocating Texture #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "first"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Baking Triangle #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "prev"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Post-Processing Texture #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "next"
msgstr ""
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Bake!"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "last"
msgstr ""
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Reset the lightmap octree baking process (start over)."
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "All"
+msgstr "Alle"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Plugins"
msgstr ""
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Sort:"
+msgstr "Sorteren:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Reverse"
+msgstr "Omkeren"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Category:"
+msgstr "Categorie:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Site:"
+msgstr "Site:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Support.."
+msgstr "Ondersteuning.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Official"
+msgstr "Officieel"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Testing"
+msgstr "Testen"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Assets ZIP File"
+msgstr "Assets ZIP Bestand"
+
#: editor/plugins/camera_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
msgid "Preview"
msgstr ""
@@ -3716,11 +3257,15 @@ msgid "Edit CanvasItem"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Change Anchors"
+msgid "Anchors only"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Change Anchors and Margins"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom (%):"
+msgid "Change Anchors"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3771,59 +3316,73 @@ msgid "Pan Mode"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Lock the selected object in place (can't be moved)."
+#, fuzzy
+msgid "Toggles snapping"
+msgstr "Breekpunt Aan- of Uitschakelen"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Use Snap"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Unlock the selected object (can be moved)."
+msgid "Snapping options"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Makes sure the object's children are not selectable."
+msgid "Snap to grid"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Restores the object's children's ability to be selected."
+msgid "Use Rotation Snap"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Edit"
-msgstr "Bewerken"
+msgid "Configure Snap..."
+msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Use Snap"
+msgid "Snap Relative"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Show Grid"
+msgid "Use Pixel Snap"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Rotation Snap"
+msgid "Smart snapping"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap Relative"
+msgid "Snap to parent"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Configure Snap.."
+msgid "Snap to node anchor"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Pixel Snap"
+msgid "Snap to node sides"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to other nodes"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Skeleton.."
+msgid "Lock the selected object in place (can't be moved)."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Unlock the selected object (can be moved)."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Makes sure the object's children are not selectable."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Restores the object's children's ability to be selected."
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3852,11 +3411,16 @@ msgid "View"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Reset"
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Show Grid"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Show helpers"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Set.."
+msgid "Show rulers"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3868,7 +3432,7 @@ msgid "Frame Selection"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Anchor"
+msgid "Layout"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3892,11 +3456,20 @@ msgid "Clear Pose"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Set a Value"
+msgid "Drag pivot from mouse position"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap (Pixels):"
+#, fuzzy
+msgid "Set pivot at mouse position"
+msgstr "Verwijder Signaal"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Multiply grid step by 2"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Divide grid step by 2"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3907,23 +3480,28 @@ msgstr ""
msgid "Adding %s..."
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Create Node"
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Error instancing scene from %s"
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "OK :("
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "No parent to instance a child at."
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "This operation requires a single selected node."
msgstr ""
@@ -3937,45 +3515,6 @@ msgid ""
"Drag & drop + Alt : Change node type"
msgstr ""
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Create Poly"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly (Remove Point)"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Create a new polygon from scratch."
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-msgid ""
-"Edit existing polygon:\n"
-"LMB: Move Point.\n"
-"Ctrl+LMB: Split Segment.\n"
-"RMB: Erase Point."
-msgstr ""
-
#: editor/plugins/collision_polygon_editor_plugin.cpp
msgid "Create Poly3D"
msgstr ""
@@ -3985,14 +3524,6 @@ msgid "Set Handle"
msgstr ""
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Creating Mesh Library"
-msgstr ""
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Thumbnail.."
-msgstr ""
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Remove item %d?"
msgstr ""
@@ -4015,6 +3546,27 @@ msgid "Update from Scene"
msgstr ""
#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat0"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat1"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+#, fuzzy
+msgid "Ease in"
+msgstr "Schaal Selectie"
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Ease out"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Smoothstep"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
msgid "Modify Curve Point"
msgstr ""
@@ -4094,22 +3646,18 @@ msgid "Create Occluder Polygon"
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Edit existing polygon:"
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "LMB: Move Point."
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Ctrl+LMB: Split Segment."
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "RMB: Erase Point."
msgstr ""
@@ -4211,6 +3759,10 @@ msgid "Create Outline"
msgstr ""
#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Mesh"
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Create Trimesh Static Body"
msgstr ""
@@ -4338,12 +3890,73 @@ msgstr ""
msgid "Populate"
msgstr ""
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Create Navigation Polygon"
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake!"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake the navigation mesh.\n"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Clear the navigation mesh."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Setting up Configuration..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Calculating grid size..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating heightfield..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Marking walkable triangles..."
+msgstr "Lokale wijziging aan het opslaan.."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Constructing compact heightfield..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Eroding walkable area..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Partitioning..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating contours..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating polymesh..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Converting to native navigation mesh..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Navigation Mesh Generator Setup:"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Parsing Geometry..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Done!"
msgstr ""
#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Remove Poly And Point"
+msgid "Create Navigation Polygon"
msgstr ""
#: editor/plugins/particles_2d_editor_plugin.cpp
@@ -4517,16 +4130,19 @@ msgid "Curve Point #"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve Point Position"
-msgstr ""
+msgstr "Verwijder Signaal"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve In Position"
-msgstr ""
+msgstr "Verwijder Signaal"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve Out Position"
-msgstr ""
+msgstr "Verwijder Signaal"
#: editor/plugins/path_editor_plugin.cpp
msgid "Split Path"
@@ -4586,6 +4202,14 @@ msgid "Scale Polygon"
msgstr ""
#: editor/plugins/polygon_2d_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Edit"
+msgstr "Bewerken"
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Polygon->UV"
msgstr ""
@@ -4640,63 +4264,10 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/shader_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "Plakken"
-#: editor/plugins/rich_text_editor_plugin.cpp
-msgid "Parse BBCode"
-msgstr ""
-
-#: editor/plugins/sample_editor_plugin.cpp
-msgid "Length:"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Open Sample File(s)"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "ERROR: Couldn't load sample!"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Add Sample"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Rename Sample"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Delete Sample"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "16 Bits"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "8 Bits"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Stereo"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Mono"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Format"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Pitch"
-msgstr ""
-
#: editor/plugins/script_editor_plugin.cpp
msgid "Clear Recent Files"
msgstr ""
@@ -4787,6 +4358,10 @@ msgstr ""
msgid "Close All"
msgstr ""
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+msgid "Run"
+msgstr ""
+
#: editor/plugins/script_editor_plugin.cpp
#, fuzzy
msgid "Toggle Scripts Panel"
@@ -4816,7 +4391,8 @@ msgstr ""
msgid "Break"
msgstr ""
-#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+#: editor/script_editor_debugger.cpp
msgid "Continue"
msgstr ""
@@ -4830,18 +4406,6 @@ msgid "Debug with external editor"
msgstr "Afhankelijkheden Editor"
#: editor/plugins/script_editor_plugin.cpp
-msgid "Window"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Left"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Right"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
msgid "Open Godot online documentation"
msgstr ""
@@ -4924,8 +4488,9 @@ msgid "Cut"
msgstr "Knippen"
#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "Kopiëren"
@@ -5190,10 +4755,6 @@ msgid "View Plane Transform."
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Scaling to %s%%."
-msgstr ""
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rotating %s degrees."
msgstr ""
@@ -5210,10 +4771,6 @@ msgid "Top View."
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Top"
-msgstr ""
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rear View."
msgstr ""
@@ -5449,6 +5006,10 @@ msgid "Transform"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Configure Snap.."
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Local Coords"
msgstr ""
@@ -5594,6 +5155,10 @@ msgid "Speed (FPS):"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Loop"
+msgstr ""
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Animation Frames"
msgstr ""
@@ -5606,11 +5171,12 @@ msgid "Insert Empty (After)"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Up"
-msgstr ""
+#, fuzzy
+msgid "Move (Before)"
+msgstr "Kopiëer Nodes"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Down"
+msgid "Move (After)"
msgstr ""
#: editor/plugins/style_box_editor_plugin.cpp
@@ -5689,7 +5255,11 @@ msgid "Remove All"
msgstr "Verwijderen"
#: editor/plugins/theme_editor_plugin.cpp
-msgid "Theme"
+msgid "Edit theme.."
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Theme editing menu."
msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
@@ -5774,6 +5344,10 @@ msgid "Style"
msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
+msgid "Font"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
msgid "Color"
msgstr ""
@@ -5824,7 +5398,7 @@ msgid "Mirror Y"
msgstr ""
#: editor/plugins/tile_map_editor_plugin.cpp
-msgid "Bucket"
+msgid "Paint Tile"
msgstr ""
#: editor/plugins/tile_map_editor_plugin.cpp
@@ -5891,6 +5465,10 @@ msgid "Delete preset '%s'?"
msgstr "Verwijder geselecteerde bestanden?"
#: editor/project_export.cpp
+msgid "Export templates for this platform are missing/corrupted: "
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Presets"
msgstr ""
@@ -5963,19 +5541,30 @@ msgid "Export templates for this platform are missing:"
msgstr ""
#: editor/project_export.cpp
+msgid "Export templates for this platform are missing/corrupted:"
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Export With Debug"
msgstr ""
#: editor/project_manager.cpp
-msgid "Invalid project path, the path must exist!"
+#, fuzzy
+msgid "The path does not exist."
+msgstr "Bestand bestaat niet."
+
+#: editor/project_manager.cpp
+msgid "Please choose a 'project.godot' file."
msgstr ""
#: editor/project_manager.cpp
-msgid "Invalid project path, project.godot must not exist."
+msgid ""
+"Your project will be created in a non empty folder (you might want to create "
+"a new folder)."
msgstr ""
#: editor/project_manager.cpp
-msgid "Invalid project path, project.godot must exist."
+msgid "Please choose a folder that does not contain a 'project.godot' file."
msgstr ""
#: editor/project_manager.cpp
@@ -5983,10 +5572,26 @@ msgid "Imported Project"
msgstr ""
#: editor/project_manager.cpp
+msgid " "
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "It would be a good idea to name your project."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Invalid project path (changed anything?)."
msgstr ""
#: editor/project_manager.cpp
+msgid "Couldn't get project.godot in project path."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Couldn't edit project.godot in project path."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
msgstr ""
@@ -5995,15 +5600,20 @@ msgid "The following files failed extraction from package:"
msgstr ""
#: editor/project_manager.cpp
-msgid "Import Existing Project"
+#, fuzzy
+msgid "Rename Project"
+msgstr "Hernoem Functie"
+
+#: editor/project_manager.cpp
+msgid "Couldn't get project.godot in the project path."
msgstr ""
#: editor/project_manager.cpp
-msgid "Project Path (Must Exist):"
+msgid "New Game Project"
msgstr ""
#: editor/project_manager.cpp
-msgid "Project Name:"
+msgid "Import Existing Project"
msgstr ""
#: editor/project_manager.cpp
@@ -6011,19 +5621,24 @@ msgid "Create New Project"
msgstr ""
#: editor/project_manager.cpp
-msgid "Project Path:"
+msgid "Install Project:"
msgstr ""
#: editor/project_manager.cpp
-msgid "Install Project:"
+msgid "Project Name:"
msgstr ""
#: editor/project_manager.cpp
-msgid "Browse"
+#, fuzzy
+msgid "Create folder"
+msgstr "Map Maken"
+
+#: editor/project_manager.cpp
+msgid "Project Path:"
msgstr ""
#: editor/project_manager.cpp
-msgid "New Game Project"
+msgid "Browse"
msgstr ""
#: editor/project_manager.cpp
@@ -6035,6 +5650,11 @@ msgid "Unnamed Project"
msgstr ""
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Can't open project"
+msgstr "Verbind.."
+
+#: editor/project_manager.cpp
msgid "Are you sure to open more than one project?"
msgstr ""
@@ -6061,16 +5681,18 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
-"You are about the scan %s folders for existing Godot projects. Do you "
-"confirm?"
+"Language changed.\n"
+"The UI will update next time the editor or project manager starts."
msgstr ""
#: editor/project_manager.cpp
-msgid "Project List"
+msgid ""
+"You are about the scan %s folders for existing Godot projects. Do you "
+"confirm?"
msgstr ""
#: editor/project_manager.cpp
-msgid "Run"
+msgid "Project List"
msgstr ""
#: editor/project_manager.cpp
@@ -6095,6 +5717,10 @@ msgid "Exit"
msgstr ""
#: editor/project_manager.cpp
+msgid "Restart Now"
+msgstr ""
+
+#: editor/project_manager.cpp
#, fuzzy
msgid "Can't run project"
msgstr "Verbind.."
@@ -6132,17 +5758,14 @@ msgid "Add Input Action Event"
msgstr ""
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Meta+"
msgstr "Meta+"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Shift+"
msgstr "Shift+"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Alt+"
msgstr "Alt+"
@@ -6203,7 +5826,7 @@ msgstr "Wijzig"
msgid "Joypad Axis Index:"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Axis"
msgstr "As"
@@ -6223,31 +5846,31 @@ msgstr ""
msgid "Add Event"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Device"
msgstr "Apparaat"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Button"
msgstr "Knop"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Left Button."
msgstr "Linker Knop."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Right Button."
msgstr "Rechter Knop."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Middle Button."
msgstr "Middelste Knop."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Up."
msgstr "Scrollwiel Omhoog."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Down."
msgstr "Scrollwiel Omlaag."
@@ -6257,7 +5880,7 @@ msgid "Add Global Property"
msgstr "Getter Property Toevoegen"
#: editor/project_settings_editor.cpp
-msgid "Select an setting item first!"
+msgid "Select a setting item first!"
msgstr ""
#: editor/project_settings_editor.cpp
@@ -6275,6 +5898,15 @@ msgid "Delete Item"
msgstr "Verwijder"
#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Can't contain '/' or ':'"
+msgstr "Kan niet verbinden met host:"
+
+#: editor/project_settings_editor.cpp
+msgid "Already existing"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "Error saving settings."
msgstr ""
@@ -6315,6 +5947,14 @@ msgid "Remove Resource Remap Option"
msgstr ""
#: editor/project_settings_editor.cpp
+msgid "Changed Locale Filter"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Changed Locale Filter Mode"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "Project Settings (project.godot)"
msgstr ""
@@ -6375,6 +6015,27 @@ msgid "Locale"
msgstr ""
#: editor/project_settings_editor.cpp
+msgid "Locales Filter"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Show all locales"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Show only selected locales"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Filter mode:"
+msgstr "Filter:"
+
+#: editor/project_settings_editor.cpp
+msgid "Locales:"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "AutoLoad"
msgstr ""
@@ -6424,10 +6085,19 @@ msgid "New Script"
msgstr ""
#: editor/property_editor.cpp
+msgid "Make Unique"
+msgstr ""
+
+#: editor/property_editor.cpp
msgid "Show in File System"
msgstr ""
#: editor/property_editor.cpp
+#, fuzzy
+msgid "Convert To %s"
+msgstr "Verbind Aan Node:"
+
+#: editor/property_editor.cpp
msgid "Error loading file: Not a resource!"
msgstr ""
@@ -6465,6 +6135,10 @@ msgid "Select Property"
msgstr ""
#: editor/property_selector.cpp
+msgid "Select Virtual Method"
+msgstr ""
+
+#: editor/property_selector.cpp
msgid "Select Method"
msgstr ""
@@ -6492,26 +6166,6 @@ msgstr ""
msgid "Reparent"
msgstr ""
-#: editor/resources_dock.cpp
-msgid "Create New Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Open Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Save Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Resource Tools"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Make Local"
-msgstr ""
-
#: editor/run_settings_dialog.cpp
msgid "Run Mode:"
msgstr ""
@@ -6639,14 +6293,6 @@ msgid "Sub-Resources:"
msgstr "Resource"
#: editor/scene_tree_dock.cpp
-msgid "Edit Groups"
-msgstr ""
-
-#: editor/scene_tree_dock.cpp
-msgid "Edit Connections"
-msgstr ""
-
-#: editor/scene_tree_dock.cpp
msgid "Clear Inheritance"
msgstr ""
@@ -6832,6 +6478,15 @@ msgid "Invalid base path"
msgstr ""
#: editor/script_create_dialog.cpp
+msgid "Directory of the same name exists"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
+#, fuzzy
+msgid "File exists, will be reused"
+msgstr "Bestand Bestaat, Overschrijven?"
+
+#: editor/script_create_dialog.cpp
msgid "Invalid extension"
msgstr ""
@@ -6875,6 +6530,10 @@ msgid "Load existing script file"
msgstr ""
#: editor/script_create_dialog.cpp
+msgid "Language"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
#, fuzzy
msgid "Inherits"
msgstr "Erft:"
@@ -6918,6 +6577,10 @@ msgid "Function:"
msgstr ""
#: editor/script_editor_debugger.cpp
+msgid "Pick one or more items from the list to display the graph."
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
msgid "Errors"
msgstr ""
@@ -6998,6 +6661,10 @@ msgid "Type"
msgstr ""
#: editor/script_editor_debugger.cpp
+msgid "Format"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
msgid "Usage"
msgstr ""
@@ -7073,12 +6740,28 @@ msgstr ""
msgid "Change Probe Extents"
msgstr ""
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Library"
+msgstr ""
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Status"
+msgstr ""
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Libraries: "
+msgstr ""
+
+#: modules/gdnative/register_types.cpp
+msgid "GDNative"
+msgstr ""
+
#: modules/gdscript/gd_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Invalid type argument to convert(), use TYPE_* constants."
msgstr "Ongeldige type argument voor convert(), gebruik TYPE_* constanten."
-#: modules/gdscript/gd_functions.cpp
+#: modules/gdscript/gd_functions.cpp modules/mono/glue/glue_header.h
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Not enough bytes for decoding bytes, or invalid format."
msgstr "Niet genoeg bytes om bytes te decoderen, of ongeldig formaat."
@@ -7131,10 +6814,6 @@ msgid "GridMap Duplicate Selection"
msgstr "Dupliceer Selectie"
#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "GridMap Paint"
-msgstr ""
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Snap View"
msgstr ""
@@ -7230,13 +6909,8 @@ msgstr ""
msgid "Pick Distance:"
msgstr ""
-#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
-msgid "Tiles"
-msgstr "Bestand:"
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "Areas"
+#: modules/mono/editor/mono_bottom_panel.cpp
+msgid "Builds"
msgstr ""
#: modules/visual_script/visual_script.cpp
@@ -7449,10 +7123,18 @@ msgid "Return"
msgstr "Teruggave"
#: modules/visual_script/visual_script_editor.cpp
+msgid "Call"
+msgstr "Aanroep"
+
+#: modules/visual_script/visual_script_editor.cpp
msgid "Get"
msgstr "Krijg"
#: modules/visual_script/visual_script_editor.cpp
+msgid "Script already has function '%s'"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
#, fuzzy
msgid "Change Input Value"
msgstr "Wijzig Array Waarde"
@@ -7867,6 +7549,12 @@ msgstr ""
"Een SpriteFrames resource moet gemaakt of gegeven worden in de 'Frames' "
"eigenschap om AnimatedSprite3D frames te laten tonen."
+#: scene/3d/vehicle_body.cpp
+msgid ""
+"VehicleWheel serves to provide a wheel system to a VehicleBody. Please use "
+"it as a child of a VehicleBody."
+msgstr ""
+
#: scene/gui/color_picker.cpp
msgid "Raw Mode"
msgstr ""
@@ -7876,6 +7564,10 @@ msgid "Add current color as a preset"
msgstr ""
#: scene/gui/dialogs.cpp
+msgid "Cancel"
+msgstr "Annuleren"
+
+#: scene/gui/dialogs.cpp
msgid "Alert!"
msgstr "Alarm!"
@@ -7883,10 +7575,6 @@ msgstr "Alarm!"
msgid "Please Confirm..."
msgstr "Bevestig Alsjeblieft..."
-#: scene/gui/input_action.cpp
-msgid "Ctrl+"
-msgstr "Ctrl+"
-
#: scene/gui/popup.cpp
msgid ""
"Popups will hide by default unless you call popup() or any of the popup*() "
@@ -7922,6 +7610,69 @@ msgstr ""
"inhoud direct op het scherm te weergeven. Anders, maak er een RenderTarget "
"van en wijs zijn interne texture toe aan een node om te tonen."
+#: scene/resources/dynamic_font.cpp
+msgid "Error initializing FreeType."
+msgstr "Error bij het initialiseren van FreeType."
+
+#: scene/resources/dynamic_font.cpp
+msgid "Unknown font format."
+msgstr "Onbekende lettertype formaat."
+
+#: scene/resources/dynamic_font.cpp
+msgid "Error loading font."
+msgstr "Error bij het laden van lettertype."
+
+#: scene/resources/dynamic_font.cpp
+msgid "Invalid font size."
+msgstr "Ongeldige lettertype grootte."
+
+#~ msgid "Filter:"
+#~ msgstr "Filter:"
+
+#~ msgid "' parsing of config failed."
+#~ msgstr "' te activeren. Het configuratiebestand kon niet gelezen worden."
+
+#~ msgid "Method List For '%s':"
+#~ msgstr "Methodelijst voor '%s':"
+
+#~ msgid "Arguments:"
+#~ msgstr "Argumenten:"
+
+#~ msgid "Return:"
+#~ msgstr "Teruggave:"
+
+#~ msgid "Added:"
+#~ msgstr "Toegevoegd:"
+
+#~ msgid "Removed:"
+#~ msgstr "Verwijderd:"
+
+#~ msgid "Error saving atlas:"
+#~ msgstr "Error bij het opslaan van atlas:"
+
+#~ msgid "Could not save atlas subtexture:"
+#~ msgstr "Kon atlas subtexture niet opslaan:"
+
+#~ msgid "Exporting for %s"
+#~ msgstr "Aan het exporteren voor %s"
+
+#~ msgid "Setting Up.."
+#~ msgstr "Aan Het Opzetten.."
+
+#~ msgid "Re-Importing"
+#~ msgstr "Aan Het Herimporteren"
+
+#, fuzzy
+#~ msgid "Error moving file:\n"
+#~ msgstr "Error bij het opslaan van TileSet!"
+
+#, fuzzy
+#~ msgid "Tiles"
+#~ msgstr "Bestand:"
+
+#~ msgid "Ctrl+"
+#~ msgstr "Ctrl+"
+
#~ msgid "just pressed"
#~ msgstr "reeds ingedrukt"
diff --git a/editor/translations/pl.po b/editor/translations/pl.po
index baffd09f33..1d14c94e1f 100644
--- a/editor/translations/pl.po
+++ b/editor/translations/pl.po
@@ -1,5 +1,6 @@
# Polish translation of the Godot Engine editor
-# Copyright (C) 2016-2017 Juan Linietsky, Ariel Manzur and the Godot community
+# Copyright (C) 2007-2017 Juan Linietsky, Ariel Manzur
+# Copyright (C) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)
# This file is distributed under the same license as the Godot source code.
#
# 8-bit Pixel <dawdejw@gmail.com>, 2016.
@@ -11,13 +12,14 @@
# Maksymilian Świąć <maksymilian.swiac@gmail.com>, 2017.
# Mietek Szcześniak <ravaging@go2.pl>, 2016.
# Rafal Brozio <rafal.brozio@gmail.com>, 2016.
+# Sebastian Krzyszkowiak <dos@dosowisko.net>, 2017.
# siatek papieros <sbigneu@gmail.com>, 2016.
#
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
-"PO-Revision-Date: 2017-06-26 08:24+0000\n"
-"Last-Translator: Daniel Lewan <vision360.daniel@gmail.com>\n"
+"PO-Revision-Date: 2017-10-23 16:47+0000\n"
+"Last-Translator: Sebastian Krzyszkowiak <dos@dosowisko.net>\n"
"Language-Team: Polish <https://hosted.weblate.org/projects/godot-engine/"
"godot/pl/>\n"
"Language: pl\n"
@@ -25,7 +27,7 @@ msgstr ""
"Content-Transfer-Encoding: 8-bit\n"
"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
"|| n%100>=20) ? 1 : 2;\n"
-"X-Generator: Weblate 2.15-dev\n"
+"X-Generator: Weblate 2.17\n"
#: editor/animation_editor.cpp
msgid "Disabled"
@@ -208,10 +210,9 @@ msgid "Create %d NEW tracks and insert keys?"
msgstr "Utworzyć NOWĄ ścieżkę i dodać klatkę kluczową?"
#: editor/animation_editor.cpp editor/create_dialog.cpp
-#: editor/editor_audio_buses.cpp
+#: editor/editor_audio_buses.cpp editor/plugins/abstract_polygon_2d_editor.cpp
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
#: editor/plugins/mesh_instance_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp editor/project_manager.cpp
#: editor/script_create_dialog.cpp
msgid "Create"
@@ -378,272 +379,6 @@ msgstr "Zmień Typ Tablicy"
msgid "Change Array Value"
msgstr "Zmień Wartość Tablicy"
-#: editor/asset_library_editor_plugin.cpp
-msgid "Free"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_plugin_settings.cpp
-msgid "Version:"
-msgstr "Wersja:"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Contents:"
-msgstr "Stałe:"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "View Files"
-msgstr "Plik"
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_help.cpp editor/property_selector.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Description:"
-msgstr "Opis:"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-#: editor/project_manager.cpp
-msgid "Install"
-msgstr "Instaluj"
-
-#: editor/asset_library_editor_plugin.cpp editor/call_dialog.cpp
-#: editor/connections_dialog.cpp editor/export_template_manager.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-#: editor/project_settings_editor.cpp editor/property_editor.cpp
-#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Close"
-msgstr "Zamknij"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve hostname:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Connection error, please try again."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Can't connect."
-msgstr "Połącz.."
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Can't connect to host:"
-msgstr "Podłącz do węzła:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response from host:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Request failed, return code:"
-msgstr "Nieznany format pliku:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Req. Failed."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Request failed, too many redirects"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Redirect Loop."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Bad download hash, assuming file has been tampered with."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Expected:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Got:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Asset Download Error:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-msgid "Success!"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Fetching:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Resolving.."
-msgstr "Zapisywanie.."
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Connecting.."
-msgstr "Połącz.."
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Requesting.."
-msgstr "Testowanie"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Error making request"
-msgstr "BÅ‚Ä…d podczas zapisu zasobu!"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Idle"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Retry"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Download Error"
-msgstr "Pobierz"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Download for this asset is already in progress!"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "first"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "prev"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "next"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "last"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "All"
-msgstr "Wszystko"
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
-#: editor/settings_config_dialog.cpp
-msgid "Search:"
-msgstr "Szukaj:"
-
-#: editor/asset_library_editor_plugin.cpp editor/code_editor.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Search"
-msgstr "Szukaj"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/project_manager.cpp
-msgid "Import"
-msgstr "Importuj"
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Plugins"
-msgstr "Wtyczki"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Sort:"
-msgstr "Sortuj:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Reverse"
-msgstr "Odwróć"
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Category:"
-msgstr "Kategoria:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Site:"
-msgstr "Źródło:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Support.."
-msgstr "Wsparcie.."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Official"
-msgstr "Oficjalny"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-msgid "Community"
-msgstr "Społeczność"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Testing"
-msgstr "Testowanie"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Assets ZIP File"
-msgstr "Plik ZIP assetów"
-
-#: editor/call_dialog.cpp
-msgid "Method List For '%s':"
-msgstr "Lista metod '%s':"
-
-#: editor/call_dialog.cpp modules/visual_script/visual_script_editor.cpp
-msgid "Call"
-msgstr "Wywołanie"
-
-#: editor/call_dialog.cpp
-msgid "Method List:"
-msgstr "Lista metod:"
-
-#: editor/call_dialog.cpp
-msgid "Arguments:"
-msgstr "Argumenty:"
-
-#: editor/call_dialog.cpp
-msgid "Return:"
-msgstr "Zwraca:"
-
#: editor/code_editor.cpp
msgid "Go to Line"
msgstr "Idź do lini"
@@ -681,6 +416,14 @@ msgstr "Całe słowa"
msgid "Selection Only"
msgstr "Tylko zaznaczenie"
+#: editor/code_editor.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
+msgid "Search"
+msgstr "Szukaj"
+
#: editor/code_editor.cpp editor/editor_help.cpp
msgid "Find"
msgstr "Szukaj"
@@ -713,11 +456,11 @@ msgstr "Zaptytaj przy zastÄ…pieniu"
msgid "Skip"
msgstr "Pomiń"
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom In"
msgstr "Przybliż"
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom Out"
msgstr "Oddal"
@@ -788,6 +531,20 @@ msgstr "Odroczone"
msgid "Oneshot"
msgstr "Wywołaj raz"
+#: editor/connections_dialog.cpp editor/dependency_editor.cpp
+#: editor/export_template_manager.cpp
+#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Close"
+msgstr "Zamknij"
+
#: editor/connections_dialog.cpp
msgid "Connect"
msgstr "Połącz"
@@ -814,7 +571,7 @@ msgstr "Połącz.."
msgid "Disconnect"
msgstr "Rozłącz"
-#: editor/connections_dialog.cpp editor/node_dock.cpp
+#: editor/connections_dialog.cpp editor/editor_help.cpp editor/node_dock.cpp
msgid "Signals"
msgstr "Sygnały"
@@ -831,12 +588,25 @@ msgstr "Ulubione:"
msgid "Recent:"
msgstr "Ostatnie:"
+#: editor/create_dialog.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/quick_open.cpp editor/settings_config_dialog.cpp
+msgid "Search:"
+msgstr "Szukaj:"
+
#: editor/create_dialog.cpp editor/editor_help.cpp
#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/quick_open.cpp
msgid "Matches:"
msgstr "PasujÄ…ce:"
+#: editor/create_dialog.cpp editor/editor_help.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/property_selector.cpp
+#: editor/script_editor_debugger.cpp
+msgid "Description:"
+msgstr "Opis:"
+
#: editor/dependency_editor.cpp
msgid "Search Replacement For:"
msgstr "Znajdź i zamień:"
@@ -897,6 +667,10 @@ msgid "Owners Of:"
msgstr "Właściciele:"
#: editor/dependency_editor.cpp
+msgid "Remove selected files from the project? (no undo)"
+msgstr "Usunąć wybrane pliki z projektu? (Nie można tego cofnąć)"
+
+#: editor/dependency_editor.cpp
msgid ""
"The files being removed are required by other resources in order for them to "
"work.\n"
@@ -906,8 +680,8 @@ msgstr ""
"Usunąć mimo to? (Nie można tego cofnąć)"
#: editor/dependency_editor.cpp
-msgid "Remove selected files from the project? (no undo)"
-msgstr "Usunąć wybrane pliki z projektu? (Nie można tego cofnąć)"
+msgid "Cannot remove:\n"
+msgstr ""
#: editor/dependency_editor.cpp
msgid "Error loading:"
@@ -962,7 +736,7 @@ msgstr "Usuń"
#: editor/editor_about.cpp
msgid "Thanks from the Godot community!"
-msgstr "Podziękowania od społeczności Godot'a!"
+msgstr "Podziękowania od społeczności Godota!"
#: editor/editor_about.cpp
msgid "Thanks!"
@@ -974,11 +748,6 @@ msgstr ""
#: editor/editor_about.cpp
#, fuzzy
-msgid "Authors"
-msgstr "Autor:"
-
-#: editor/editor_about.cpp
-#, fuzzy
msgid "Project Founders"
msgstr "Menedżer projektów"
@@ -995,6 +764,40 @@ msgid "Developers"
msgstr ""
#: editor/editor_about.cpp
+#, fuzzy
+msgid "Authors"
+msgstr "Autor:"
+
+#: editor/editor_about.cpp
+msgid "Platinum Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Gold Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Mini Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Gold Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Silver Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+#, fuzzy
+msgid "Bronze Donors"
+msgstr "Duplikuj liniÄ™"
+
+#: editor/editor_about.cpp
+msgid "Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
msgid "License"
msgstr ""
@@ -1038,6 +841,16 @@ msgid "Package Installed Successfully!"
msgstr "Pakiet zastał zainstalowany poprawnie!"
#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Success!"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/project_manager.cpp
+msgid "Install"
+msgstr "Instaluj"
+
+#: editor/editor_asset_installer.cpp
#, fuzzy
msgid "Package Installer"
msgstr "Pakiet zastał zainstalowany poprawnie!"
@@ -1092,11 +905,6 @@ msgid "Audio Bus, Drag and Drop to rearrange."
msgstr ""
#: editor/editor_audio_buses.cpp
-#, fuzzy
-msgid "Bus options"
-msgstr "Opcje debugowania"
-
-#: editor/editor_audio_buses.cpp
msgid "Solo"
msgstr ""
@@ -1108,6 +916,11 @@ msgstr ""
msgid "Bypass"
msgstr ""
+#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Bus options"
+msgstr "Opcje debugowania"
+
#: editor/editor_audio_buses.cpp editor/plugins/tile_map_editor_plugin.cpp
#: editor/scene_tree_dock.cpp
msgid "Duplicate"
@@ -1115,6 +928,11 @@ msgstr "Duplikuj"
#: editor/editor_audio_buses.cpp
#, fuzzy
+msgid "Reset Volume"
+msgstr "Wyzeruj przybliżenie"
+
+#: editor/editor_audio_buses.cpp
+#, fuzzy
msgid "Delete Effect"
msgstr "Usuń zaznaczone"
@@ -1139,6 +957,11 @@ msgstr "Duplikuj animacje"
#: editor/editor_audio_buses.cpp
#, fuzzy
+msgid "Reset Bus Volume"
+msgstr "Wyzeruj przybliżenie"
+
+#: editor/editor_audio_buses.cpp
+#, fuzzy
msgid "Move Audio Bus"
msgstr "Otwórz układ magistrali audio"
@@ -1174,7 +997,8 @@ msgstr "Dodaj magistralÄ™"
msgid "Create a new Bus Layout."
msgstr "Utwórz nowy zasób"
-#: editor/editor_audio_buses.cpp editor/script_create_dialog.cpp
+#: editor/editor_audio_buses.cpp editor/property_editor.cpp
+#: editor/script_create_dialog.cpp
msgid "Load"
msgstr "Wczytaj"
@@ -1269,7 +1093,7 @@ msgid "Rearrange Autoloads"
msgstr "Przestaw Autoloady"
#: editor/editor_autoload_settings.cpp editor/editor_file_dialog.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp scene/gui/file_dialog.cpp
+#: scene/gui/file_dialog.cpp
msgid "Path:"
msgstr "Ścieżka:"
@@ -1277,9 +1101,7 @@ msgstr "Ścieżka:"
msgid "Node Name:"
msgstr "Nazwa węzła:"
-#: editor/editor_autoload_settings.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp editor/project_manager.cpp
+#: editor/editor_autoload_settings.cpp editor/project_manager.cpp
msgid "Name"
msgstr "Nazwa"
@@ -1313,18 +1135,19 @@ msgid "Choose a Directory"
msgstr "Wybierz katalog"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Create Folder"
msgstr "Utwórz katalog"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: editor/editor_plugin_settings.cpp editor/plugins/theme_editor_plugin.cpp
-#: editor/project_export.cpp scene/gui/file_dialog.cpp
+#: editor/editor_plugin_settings.cpp editor/filesystem_dock.cpp
+#: editor/plugins/theme_editor_plugin.cpp editor/project_export.cpp
+#: scene/gui/file_dialog.cpp
msgid "Name:"
msgstr "Nazwa:"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Could not create folder."
msgstr "Nie można utworzyć katalogu."
@@ -1344,30 +1167,6 @@ msgstr "Pakowanie"
msgid "Template file not found:\n"
msgstr "Nie znaleziono pliku szablonu:\n"
-#: editor/editor_export.cpp
-msgid "Added:"
-msgstr "Dodane:"
-
-#: editor/editor_export.cpp
-msgid "Removed:"
-msgstr "Usunięte:"
-
-#: editor/editor_export.cpp
-msgid "Error saving atlas:"
-msgstr "BÅ‚Ä…d podczas zapisywania atlasu:"
-
-#: editor/editor_export.cpp
-msgid "Could not save atlas subtexture:"
-msgstr "Nie udało się zapisać tekstury atlasu:"
-
-#: editor/editor_export.cpp
-msgid "Exporting for %s"
-msgstr "Exportowanie do %s"
-
-#: editor/editor_export.cpp
-msgid "Setting Up.."
-msgstr "Konfigurowanie .."
-
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "File Exists, Overwrite?"
msgstr "Plik istnieje, nadpisać?"
@@ -1452,6 +1251,11 @@ msgstr "Przesuń Ulubiony w górę"
msgid "Move Favorite Down"
msgstr "Przesuń Ulubiony w dół"
+#: editor/editor_file_dialog.cpp
+#, fuzzy
+msgid "Go to parent folder"
+msgstr "Nie można utworzyć katalogu."
+
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Directories & Files:"
msgstr "Katalogi i pliki:"
@@ -1466,10 +1270,6 @@ msgid "File:"
msgstr "Plik:"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
-msgid "Filter:"
-msgstr "Filtr:"
-
-#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Must use a valid extension."
msgstr "Rozszerzenie musi być poprawne."
@@ -1495,6 +1295,10 @@ msgstr "List klas:"
msgid "Search Classes"
msgstr "Przeszukaj klasy"
+#: editor/editor_help.cpp editor/plugins/spatial_editor_plugin.cpp
+msgid "Top"
+msgstr "Góra"
+
#: editor/editor_help.cpp editor/property_editor.cpp
msgid "Class:"
msgstr "Klasa:"
@@ -1511,15 +1315,30 @@ msgstr "Dziedziczone przez:"
msgid "Brief Description:"
msgstr "Krótki opis:"
+#: editor/editor_help.cpp
+#, fuzzy
+msgid "Members"
+msgstr "Członkowie:"
+
#: editor/editor_help.cpp modules/visual_script/visual_script_editor.cpp
msgid "Members:"
msgstr "Członkowie:"
#: editor/editor_help.cpp
+#, fuzzy
+msgid "Public Methods"
+msgstr "Metody publiczne:"
+
+#: editor/editor_help.cpp
msgid "Public Methods:"
msgstr "Metody publiczne:"
#: editor/editor_help.cpp
+#, fuzzy
+msgid "GUI Theme Items"
+msgstr "Elementy motywu GUI:"
+
+#: editor/editor_help.cpp
msgid "GUI Theme Items:"
msgstr "Elementy motywu GUI:"
@@ -1529,6 +1348,11 @@ msgstr "Sygnały:"
#: editor/editor_help.cpp
#, fuzzy
+msgid "Enumerations"
+msgstr "Animacje"
+
+#: editor/editor_help.cpp
+#, fuzzy
msgid "Enumerations:"
msgstr "Animacje"
@@ -1537,19 +1361,51 @@ msgid "enum "
msgstr ""
#: editor/editor_help.cpp
+#, fuzzy
+msgid "Constants"
+msgstr "Stałe:"
+
+#: editor/editor_help.cpp
msgid "Constants:"
msgstr "Stałe:"
#: editor/editor_help.cpp
#, fuzzy
+msgid "Description"
+msgstr "Opis:"
+
+#: editor/editor_help.cpp
+#, fuzzy
+msgid "Properties"
+msgstr "Właściwości:"
+
+#: editor/editor_help.cpp
+#, fuzzy
msgid "Property Description:"
msgstr "Krótki opis:"
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this property. Please help us by "
+"[color=$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+
+#: editor/editor_help.cpp
+#, fuzzy
+msgid "Methods"
+msgstr "Lista metod:"
+
+#: editor/editor_help.cpp
msgid "Method Description:"
msgstr "Opis metody:"
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this method. Please help us by [color="
+"$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Search Text"
msgstr "Wyszukaj w tekście"
@@ -1559,24 +1415,21 @@ msgid "Output:"
msgstr " Konsola:"
#: editor/editor_log.cpp editor/plugins/animation_tree_editor_plugin.cpp
-#: editor/plugins/rich_text_editor_plugin.cpp editor/property_editor.cpp
-#: editor/script_editor_debugger.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/property_editor.cpp editor/script_editor_debugger.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Clear"
msgstr "Wyczyść"
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Error saving resource!"
msgstr "BÅ‚Ä…d podczas zapisu zasobu!"
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Save Resource As.."
msgstr "Zapisz zasób jako..."
-#: editor/editor_node.cpp editor/export_template_manager.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "I see.."
msgstr "WidzÄ™.."
@@ -1593,6 +1446,30 @@ msgid "Error while saving."
msgstr "BÅ‚Ä…d podczas zapisywania."
#: editor/editor_node.cpp
+#, fuzzy
+msgid "Can't open '%s'."
+msgstr "Nie można operować na '..'"
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Error while parsing '%s'."
+msgstr "BÅ‚Ä…d podczas zapisywania."
+
+#: editor/editor_node.cpp
+msgid "Unexpected end of file '%s'."
+msgstr ""
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Missing '%s' or its dependencies."
+msgstr "Scena '%s' ma niespełnione zależności:"
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Error while loading '%s'."
+msgstr "BÅ‚Ä…d podczas zapisywania."
+
+#: editor/editor_node.cpp
msgid "Saving Scene"
msgstr "Zapisywanie Sceny"
@@ -1653,6 +1530,33 @@ msgid "Restored default layout to base settings."
msgstr "Przywrócono domyślny układ do ustawień bazowych."
#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was imported, so it's not editable.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was instanced or inherited.\n"
+"Changes to it will not be kept when saving the current scene."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource was imported, so it's not editable. Change its settings in the "
+"import panel and then re-import."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This scene was imported, so changes to it will not be kept.\n"
+"Instancing it or inheriting will allow making changes to it.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Copy Params"
msgstr "Kopiuj parametry"
@@ -1828,23 +1732,35 @@ msgid "Save changes the following scene(s) before opening Project Manager?"
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"This option is deprecated. Situations where refresh must be forced are now "
+"considered a bug. Please report."
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Pick a Main Scene"
msgstr "Wybierz główną scenę"
#: editor/editor_node.cpp
-msgid "Unable to enable addon plugin at: '"
+msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr ""
#: editor/editor_node.cpp
-msgid "' parsing of config failed."
+msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/"
+#, fuzzy
+msgid "Unable to load addon script from path: '%s'."
+msgstr "BÅ‚Ä…d przy Å‚adowaniu sceny z %s"
+
+#: editor/editor_node.cpp
+msgid ""
+"Unable to load addon script from path: '%s' Base type is not EditorPlugin."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to load addon script from path: '"
+msgid "Unable to load addon script from path: '%s' Script is not in tool mode."
msgstr ""
#: editor/editor_node.cpp
@@ -1858,7 +1774,7 @@ msgstr ""
"Aby dokonać na niej zmian, można utworzyć nową odziedziczoną scenę."
#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/scene_tree_dock.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
#, fuzzy
msgid "Ugh"
msgstr "BÅ‚Ä…d"
@@ -1873,14 +1789,15 @@ msgstr ""
"projektu."
#: editor/editor_node.cpp
-msgid "Error loading scene."
-msgstr "BÅ‚Ä…d Å‚adowania sceny."
-
-#: editor/editor_node.cpp
msgid "Scene '%s' has broken dependencies:"
msgstr "Scena '%s' ma niespełnione zależności:"
#: editor/editor_node.cpp
+#, fuzzy
+msgid "Clear Recent Scenes"
+msgstr "Wyczyść Kości"
+
+#: editor/editor_node.cpp
msgid "Save Layout"
msgstr "Zapisz układ"
@@ -1914,7 +1831,7 @@ msgstr "Tryb bez rozproszeń"
msgid "Toggle distraction-free mode."
msgstr "Tryb bez rozproszeń"
-#: editor/editor_node.cpp editor/io_plugins/editor_scene_import_plugin.cpp
+#: editor/editor_node.cpp
msgid "Scene"
msgstr "Scena"
@@ -2153,6 +2070,10 @@ msgstr ""
msgid "Issue Tracker"
msgstr ""
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+msgid "Community"
+msgstr "Społeczność"
+
#: editor/editor_node.cpp
msgid "About"
msgstr "O programie"
@@ -2161,7 +2082,7 @@ msgstr "O programie"
msgid "Play the project."
msgstr "Uruchom projekt."
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Play"
msgstr "Uruchom"
@@ -2177,7 +2098,7 @@ msgstr "Zapauzuj scenÄ™"
msgid "Stop the scene."
msgstr "Zatrzymaj scene."
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Stop"
msgstr "Stop"
@@ -2251,6 +2172,16 @@ msgid "Object properties."
msgstr "Właściwości obiektu."
#: editor/editor_node.cpp
+#, fuzzy
+msgid "Changes may be lost!"
+msgstr "Zmień grupę obrazków"
+
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Import"
+msgstr "Importuj"
+
+#: editor/editor_node.cpp
msgid "FileSystem"
msgstr "System plików"
@@ -2266,14 +2197,6 @@ msgstr "Konsola"
msgid "Don't Save"
msgstr ""
-#: editor/editor_node.cpp editor/editor_reimport_dialog.cpp
-msgid "Re-Import"
-msgstr "Importuj ponownie"
-
-#: editor/editor_node.cpp editor/editor_plugin_settings.cpp
-msgid "Update"
-msgstr "Odśwież"
-
#: editor/editor_node.cpp
msgid "Import Templates From ZIP File"
msgstr "Zaimportuj Szablony z pliku ZIP"
@@ -2341,11 +2264,29 @@ msgstr "Otwórz w edytorze"
msgid "Open the previous Editor"
msgstr "Otwórz w edytorze"
+#: editor/editor_plugin.cpp
+#, fuzzy
+msgid "Creating Mesh Previews"
+msgstr "Tworzenie Mesh Library"
+
+#: editor/editor_plugin.cpp
+msgid "Thumbnail.."
+msgstr "Miniatura.."
+
#: editor/editor_plugin_settings.cpp
msgid "Installed Plugins:"
msgstr "Zainstalowane wtyczki:"
#: editor/editor_plugin_settings.cpp
+msgid "Update"
+msgstr "Odśwież"
+
+#: editor/editor_plugin_settings.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Version:"
+msgstr "Wersja:"
+
+#: editor/editor_plugin_settings.cpp
msgid "Author:"
msgstr "Autor:"
@@ -2378,7 +2319,8 @@ msgid "Frame %"
msgstr "% Ramek"
#: editor/editor_profiler.cpp
-msgid "Fixed Frame %"
+#, fuzzy
+msgid "Physics Frame %"
msgstr "% Ramek Fixed"
#: editor/editor_profiler.cpp editor/script_editor_debugger.cpp
@@ -2398,26 +2340,6 @@ msgstr "Ten obiekt"
msgid "Frame #:"
msgstr "Klatka #:"
-#: editor/editor_reimport_dialog.cpp
-msgid "Please wait for scan to complete."
-msgstr "Proszę poczekać na zakończenie skanowania."
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Current scene must be saved to re-import."
-msgstr "Bieżąca scena musi być zapisana aby ponownie zaimportować."
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Save & Re-Import"
-msgstr "Zapisz i importuj ponownie"
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Importing"
-msgstr "Prze-Importowanie"
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Import Changed Resources"
-msgstr "Zaimportuj ponownie zmienione zasoby"
-
#: editor/editor_run_native.cpp
msgid "Select device from the list"
msgstr ""
@@ -2535,10 +2457,6 @@ msgid "Importing:"
msgstr "Importowanie:"
#: editor/export_template_manager.cpp
-msgid "Loading Export Templates"
-msgstr "Wczytywanie szablonów eksportu"
-
-#: editor/export_template_manager.cpp
#, fuzzy
msgid "Current Version:"
msgstr "Aktualna scena"
@@ -2576,11 +2494,18 @@ msgid "Cannot navigate to '"
msgstr "Nie można przejść do '"
#: editor/filesystem_dock.cpp
-#, fuzzy
+msgid "View items as a grid of thumbnails"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "View items as a list"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
msgid ""
"\n"
-"Status: Needs Re-Import"
-msgstr "Zapisz i importuj ponownie"
+"Status: Import of file failed. Please fix file and reimport manually."
+msgstr ""
#: editor/filesystem_dock.cpp
#, fuzzy
@@ -2591,48 +2516,56 @@ msgstr "Źródło:"
#: editor/filesystem_dock.cpp
#, fuzzy
-msgid "Same source and destination files, doing nothing."
-msgstr "Pliki źródłowe i docelowe są te same, nie podjęto żadnej akcji."
+msgid "Cannot move/rename resources root."
+msgstr "Nie można wczytać/przetworzyć źródłowego fontu."
#: editor/filesystem_dock.cpp
-msgid "Target file exists, can't overwrite. Delete first."
-msgstr ""
+#, fuzzy
+msgid "Cannot move a folder into itself.\n"
+msgstr "Nie można zaimportować pliku wewnątrz siebie samego:"
#: editor/filesystem_dock.cpp
-msgid "Same source and destination paths, doing nothing."
-msgstr ""
-"Ścieżki źródłowa i docelowa są takie same, żadna akcja nie została wykonana."
+#, fuzzy
+msgid "Error moving:\n"
+msgstr "BÅ‚Ä…d importowania:"
#: editor/filesystem_dock.cpp
#, fuzzy
-msgid "Can't move directories to within themselves."
-msgstr "Nie możesz przenieść danego katalogu do jego wnętrza."
+msgid "Unable to update dependencies:\n"
+msgstr "Scena '%s' ma niespełnione zależności:"
+
+#: editor/filesystem_dock.cpp
+msgid "No name provided"
+msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Can't rename deps for:\n"
+msgid "Provided name contains invalid characters"
msgstr ""
#: editor/filesystem_dock.cpp
#, fuzzy
-msgid "Error moving file:\n"
-msgstr "BÅ‚Ä…d wczytywania obrazu:"
+msgid "No name provided."
+msgstr "Zmień nazwę lub Przenieś..."
#: editor/filesystem_dock.cpp
#, fuzzy
-msgid "Error moving dir:\n"
-msgstr "BÅ‚Ä…d importowania:"
+msgid "Name contains invalid characters."
+msgstr "Dopuszczalne znaki:"
#: editor/filesystem_dock.cpp
-msgid "Can't operate on '..'"
-msgstr "Nie można operować na '..'"
+#, fuzzy
+msgid "A file or folder with this name already exists."
+msgstr "Nazwa grupy już istnieje!"
#: editor/filesystem_dock.cpp
-msgid "Pick New Name and Location For:"
-msgstr "Wybierz nowÄ… nazwÄ™ i lokacjÄ™ dla:"
+#, fuzzy
+msgid "Renaming file:"
+msgstr "Zmień nawę zmiennej"
#: editor/filesystem_dock.cpp
-msgid "No files selected!"
-msgstr "Nie wybrano pliku!"
+#, fuzzy
+msgid "Renaming folder:"
+msgstr "Zmień nazwę węzła"
#: editor/filesystem_dock.cpp
msgid "Expand all"
@@ -2643,40 +2576,38 @@ msgid "Collapse all"
msgstr "Zwiń foldery"
#: editor/filesystem_dock.cpp
-msgid "Show In File Manager"
-msgstr "Pokaż w menadżerze plików"
-
-#: editor/filesystem_dock.cpp
-msgid "Instance"
-msgstr "Instancja"
+msgid "Copy Path"
+msgstr "Skopiuj Ścieżkę"
#: editor/filesystem_dock.cpp
-msgid "Edit Dependencies.."
-msgstr "Edytuj Zależności..."
+#, fuzzy
+msgid "Rename.."
+msgstr "Zmień nazwę"
#: editor/filesystem_dock.cpp
-msgid "View Owners.."
-msgstr "Pokaż właścicieli.."
+msgid "Move To.."
+msgstr "PrzenieÅ› Do..."
#: editor/filesystem_dock.cpp
-msgid "Copy Path"
-msgstr "Skopiuj Ścieżkę"
+#, fuzzy
+msgid "New Folder.."
+msgstr "Utwórz katalog"
#: editor/filesystem_dock.cpp
-msgid "Rename or Move.."
-msgstr "Zmień nazwę lub Przenieś..."
+msgid "Show In File Manager"
+msgstr "Pokaż w menadżerze plików"
#: editor/filesystem_dock.cpp
-msgid "Move To.."
-msgstr "PrzenieÅ› Do..."
+msgid "Instance"
+msgstr "Instancja"
#: editor/filesystem_dock.cpp
-msgid "Info"
-msgstr "Informacje"
+msgid "Edit Dependencies.."
+msgstr "Edytuj Zależności..."
#: editor/filesystem_dock.cpp
-msgid "Re-Import.."
-msgstr "Importuj ponownie.."
+msgid "View Owners.."
+msgstr "Pokaż właścicieli.."
#: editor/filesystem_dock.cpp
msgid "Previous Directory"
@@ -2708,6 +2639,11 @@ msgstr ""
msgid "Move"
msgstr "PrzenieÅ›"
+#: editor/filesystem_dock.cpp editor/plugins/animation_tree_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Rename"
+msgstr "Zmień nazwę"
+
#: editor/groups_editor.cpp
msgid "Add to Group"
msgstr "Dodaj do Grupy"
@@ -2722,6 +2658,11 @@ msgid "Import as Single Scene"
msgstr "Importowanie Sceny.."
#: editor/import/resource_importer_scene.cpp
+#, fuzzy
+msgid "Import with Separate Animations"
+msgstr "Zaimportuj animacje.."
+
+#: editor/import/resource_importer_scene.cpp
msgid "Import with Separate Materials"
msgstr ""
@@ -2734,6 +2675,18 @@ msgid "Import with Separate Objects+Materials"
msgstr ""
#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Materials+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Materials+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
#, fuzzy
msgid "Import as Multiple Scenes"
msgstr "Zaimportuj Scene 3D"
@@ -2743,40 +2696,33 @@ msgid "Import as Multiple Scenes+Materials"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Import Scene"
msgstr "Importuj ScenÄ™"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Importing Scene.."
msgstr "Importowanie Sceny.."
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Running Custom Script.."
msgstr "Uruchamiam skrypt..."
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Couldn't load post-import script:"
msgstr "Nie udało się wczytać skryptu po imporcie:"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Invalid/broken script for post-import (check console):"
msgstr ""
"Pojawiły się błędy podczas uruchamiania skryptu po imporcie (sprawdź "
"konsolÄ™):"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Error running post-import script:"
msgstr "BÅ‚Ä…d podczas uruchamiania skryptu po imporcie:"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Saving.."
msgstr "Zapisywanie.."
@@ -2806,589 +2752,56 @@ msgstr "Ustawienie predefiniowane.."
msgid "Reimport"
msgstr "Importuj ponownie"
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "No bit masks to import!"
-msgstr "Brak mask bitowych do zaimportowania!"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path is empty."
-msgstr "Docelowa ścieżka jest pusta."
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must be a complete resource path."
-msgstr "Ścieżka docelowa musi być bezwzględna."
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must exist."
-msgstr "Docelowa ścieżka musi istnieć."
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Save path is empty!"
-msgstr "Ścieżka zapisu jest pusta!"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Import BitMasks"
-msgstr "Importuj BitMasks"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s):"
-msgstr "Źródło tekstury:"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Target Path:"
-msgstr "Ścieżka docelowa:"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Accept"
-msgstr "Akceptuj"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Bit Mask"
-msgstr "BitMask"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No source font file!"
-msgstr "Brak pliku źródłowego fontu!"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No target font resource!"
-msgstr "Brak docelowego zasobu fontu!"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#, fuzzy
-msgid ""
-"Invalid file extension.\n"
-"Please use .font."
-msgstr ""
-"Błędne rozszerzenie pliku.\n"
-"Proszę użyć .fnt."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Can't load/process source font."
-msgstr "Nie można wczytać/przetworzyć źródłowego fontu."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Couldn't save font."
-msgstr "Nie udało się zapisać fontu."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font:"
-msgstr "Źródło fontu:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font Size:"
-msgstr "Wielkość oryginalna fontu:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Dest Resource:"
-msgstr "Zasób docelowy:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "The quick brown fox jumps over the lazy dog."
-msgstr "ŻżŹźĆćŃńĄąÅłĘęÓó."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Test:"
-msgstr "Test:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Options:"
-msgstr "Opcje:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Font Import"
-msgstr "Import fontu"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"This file is already a Godot font file, please supply a BMFont type file "
-"instead."
-msgstr "Ten plik jest już plikiem fontu Godot, proszę podać plik typu BMFont."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Failed opening as BMFont file."
-msgstr "Nie powiodło się, otwarcie pliku jako BMFont."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error initializing FreeType."
-msgstr "BÅ‚Ä…d przy inicjalizacji FreeType."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Unknown font format."
-msgstr "Nieznany format fontu."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error loading font."
-msgstr "BÅ‚Ä…d Å‚adowania fonta."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Invalid font size."
-msgstr "Niepoprawny rozmiar fonta."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Invalid font custom source."
-msgstr "Nie rozpoznano typu fontu."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/plugins/theme_editor_plugin.cpp
-msgid "Font"
-msgstr "Font"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "No meshes to import!"
-msgstr "Brak siatek do zaimportowania!"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Single Mesh Import"
-msgstr "Importuj Mesh"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Source Mesh(es):"
-msgstr "Źródło Mesh:"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/plugins/mesh_instance_editor_plugin.cpp
-msgid "Mesh"
-msgstr "Siatka"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Surface %d"
-msgstr "Powierzchnia %d"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "No samples to import!"
-msgstr "Brak sampli do importu!"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Import Audio Samples"
-msgstr "Importuj pliki dźwiękowe"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Source Sample(s):"
-msgstr "Źródło dźwięku:"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Audio Sample"
-msgstr "Dźwięk"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "New Clip"
-msgstr "Nowy klip"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Animation Options"
-msgstr "Opcje animacji"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Flags"
-msgstr "Flagi"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Bake FPS:"
-msgstr "Wypal FPS:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Optimizer"
-msgstr "Optymalizator"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Linear Error"
-msgstr "Maksymalny błąd liniowy"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angular Error"
-msgstr "Maksymalny błąd kątowy"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angle"
-msgstr "Maksymalny KÄ…t"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Clips"
-msgstr "Klipy"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Start(s)"
-msgstr "Start"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "End(s)"
-msgstr "Koniec"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Loop"
-msgstr "Pętla"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Filters"
-msgstr "Filtry"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source path is empty."
-msgstr "Ścieżka źródłowa jest pusta."
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't load post-import script."
-msgstr "Nie udało się wczytać skryptu po imporcie."
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Invalid/broken script for post-import."
-msgstr "Niepoprawny/uszkodzony skrypt post-importu."
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Error importing scene."
-msgstr "BÅ‚Ä…d podczas wczytywania sceny."
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import 3D Scene"
-msgstr "Zaimportuj Scene 3D"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source Scene:"
-msgstr "Scena źródłowa:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Same as Target Scene"
-msgstr "Taki sam jak scena docelowa"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Shared"
-msgstr "Współdzielone"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Target Texture Folder:"
-msgstr "Docelowy folder tekstur:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Post-Process Script:"
-msgstr "Skrypt do wywołania po imporcie:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Custom Root Node Type:"
-msgstr "Niestandardowy typ węzła głównego:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Auto"
-msgstr "Automatyczny"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#, fuzzy
-msgid "Root Node Name:"
-msgstr "Nazwa węzła:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "The Following Files are Missing:"
-msgstr "Brakuje następujących plików:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Anyway"
-msgstr "Zaimportuj Pomimo"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp scene/gui/dialogs.cpp
-msgid "Cancel"
-msgstr "Anuluj"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import & Open"
-msgstr "Importuj i Otwórz"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Edited scene has not been saved, open imported scene anyway?"
+#: editor/multi_node_edit.cpp
+msgid "MultiNode Set"
msgstr ""
-"Edytowana sceny nie została zapisana. Otworzyć importowaną scenę mimo tego?"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Image:"
-msgstr "Zaimportuj Obraz:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Can't import a file over itself:"
-msgstr "Nie można zaimportować pliku wewnątrz siebie samego:"
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't localize path: %s (already local)"
-msgstr "Nie można zlokalizować ścieżki: %s (już jest lokalna)"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "3D Scene Animation"
-msgstr "Scena animacji 3D"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Uncompressed"
-msgstr "Nieskompresowany"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossless (PNG)"
-msgstr "Bezstratna Kompresja (PNG)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossy (WebP)"
-msgstr "Kompresja Stratna (WebP)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress (VRAM)"
-msgstr "Skompresuj (VRAM)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Format"
-msgstr "Format Tekstury"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Compression Quality (WebP):"
-msgstr "Jakość Kompresji Textury (WebP):"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Options"
-msgstr "Opcje Tekstury"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Please specify some files!"
-msgstr "Proszę podać kilka plików !"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "At least one file needed for Atlas."
-msgstr "Co najmniej jeden plik potrzebny do \"Atlas'u\"."
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Error importing:"
-msgstr "BÅ‚Ä…d importowania:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Only one file is required for large texture."
-msgstr "Tylko jeden plik jest wymagany dla dużych tekstur."
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Max Texture Size:"
-msgstr "Maksymalny rozmiar tekstury:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for Atlas (2D)"
-msgstr "Zaimportuj Tekstury z \"Atlas'u\" (2D)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cell Size:"
-msgstr "Rozmiar komórki:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Large Texture"
-msgstr "Duża Tekstura"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Textures (2D)"
-msgstr "Zaimportuj Duże Tekstury (2D)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture"
-msgstr "Źródłowa Tekstura"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Base Atlas Texture"
-msgstr "Bazowa tekstura \"Atlas'u\""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s)"
-msgstr "Tekstura(y) źródłowe"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 2D"
-msgstr "Importuj tekstury dla 2D"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 3D"
-msgstr "Importuj tekstury dla 3D"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures"
-msgstr "Zaimportuj Tekstury"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "2D Texture"
-msgstr "Tekstura 2D"
+#: editor/node_dock.cpp
+msgid "Groups"
+msgstr "Grupy"
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "3D Texture"
-msgstr "Tekstura 3D"
+#: editor/node_dock.cpp
+msgid "Select a Node to edit Signals and Groups."
+msgstr "Wybierz węzeł do edycji sygnałów i grup."
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Atlas Texture"
-msgstr "Tekstura \"Atlas'u\""
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create Poly"
+msgstr "Utwórz Polygon"
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid ""
-"NOTICE: Importing 2D textures is not mandatory. Just copy png/jpg files to "
-"the project."
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly"
msgstr ""
-"UWAGA: Importowanie tekstur 2D nie jest wymagane. Po prostu skopiuj pliki "
-"png/jpg do folderu projektu."
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Crop empty space."
-msgstr "Przytnij pusty obszar."
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture"
-msgstr "Tekstura"
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Texture"
-msgstr "Importuj dużą teksturę"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Load Source Image"
-msgstr "Wczytaj obrazek źródłowy"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Slicing"
-msgstr "Przycinanie"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Inserting"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#, fuzzy
+msgid "Insert Point"
msgstr "Wstawianie"
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Saving"
-msgstr "Zapisywanie"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save large texture:"
-msgstr "Nie udało się zapisać dużej tekstury:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Build Atlas For:"
-msgstr "Zbuduj Atlas dla:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Loading Image:"
-msgstr "Åadowanie obrazu:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't load image:"
-msgstr "Nie można załadować obrazu:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Converting Images"
-msgstr "Konwersja obrazków"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cropping Images"
-msgstr "Przycinanie obrazków"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Blitting Images"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly (Remove Point)"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save atlas image:"
-msgstr "Nie można zapisać obrazu atlasu:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#, fuzzy
-msgid "Couldn't save converted texture:"
-msgstr "Nie można zapisać zkonwertowanej tekstury:"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid source!"
-msgstr "Wadliwe źródło!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid translation source!"
-msgstr "Nieprawidłowe źródło tłumaczenia!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Column"
-msgstr "Kolumna"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/script_create_dialog.cpp
-msgid "Language"
-msgstr "Język"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No items to import!"
-msgstr "Brak elementów do importu!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No target path!"
-msgstr "Brak ścieżki docelowej!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translations"
-msgstr "Importuj tłumaczenia"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Couldn't import!"
-msgstr "Nie można zaimportować!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translation"
-msgstr "Importuj tłumaczenie"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Source CSV:"
-msgstr "Źródłowy CSV:"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Ignore First Row"
-msgstr "Ignoruj pierwszy wiersz"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Compress"
-msgstr "Skompresuj"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#, fuzzy
-msgid "Add to Project (project.godot)"
-msgstr "Dodaj do projektu (engine.cfg)"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Languages:"
-msgstr "Zaimportuj Język:"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Translation"
-msgstr "TÅ‚umaczenie"
-
-#: editor/multi_node_edit.cpp
-msgid "MultiNode Set"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Remove Poly And Point"
msgstr ""
-#: editor/node_dock.cpp
-msgid "Groups"
-msgstr "Grupy"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create a new polygon from scratch."
+msgstr "Utwórz nowy wielokąt."
-#: editor/node_dock.cpp
-msgid "Select a Node to edit Signals and Groups."
-msgstr "Wybierz węzeł do edycji sygnałów i grup."
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid ""
+"Edit existing polygon:\n"
+"LMB: Move Point.\n"
+"Ctrl+LMB: Split Segment.\n"
+"RMB: Erase Point."
+msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Toggle Autoplay"
@@ -3544,7 +2957,6 @@ msgstr "Nazwa animacji:"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
#: editor/script_create_dialog.cpp
msgid "Error!"
@@ -3655,10 +3067,6 @@ msgid "Delete Input"
msgstr ""
#: editor/plugins/animation_tree_editor_plugin.cpp
-msgid "Rename"
-msgstr "Zmień nazwę"
-
-#: editor/plugins/animation_tree_editor_plugin.cpp
msgid "Animation tree is valid."
msgstr "Drzewo animacji jest poprawne."
@@ -3714,64 +3122,192 @@ msgstr "Edytuj filtry węzłów"
msgid "Filters.."
msgstr "Filtry.."
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing %d Triangles:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Free"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Contents:"
+msgstr "Stałe:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "View Files"
+msgstr "Plik"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve hostname:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Triangle #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Light Baker Setup:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connection error, please try again."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing Geometry"
-msgstr "Parsowanie Geometrii"
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Can't connect."
+msgstr "Połącz.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Can't connect to host:"
+msgstr "Podłącz do węzła:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response from host:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Request failed, return code:"
+msgstr "Nieznany format pliku:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Fixing Lights"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Req. Failed."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Making BVH"
-msgstr "Tworzenie BVH"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, too many redirects"
+msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Light Octree"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Redirect Loop."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Octree Texture"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Transfer to Lightmaps:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Bad download hash, assuming file has been tampered with."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Allocating Texture #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Expected:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Baking Triangle #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Got:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Post-Processing Texture #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed sha256 hash check"
msgstr ""
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Bake!"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Asset Download Error:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Fetching:"
msgstr ""
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Reset the lightmap octree baking process (start over)."
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Resolving.."
+msgstr "Zapisywanie.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Connecting.."
+msgstr "Połącz.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Requesting.."
+msgstr "Testowanie"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Error making request"
+msgstr "BÅ‚Ä…d podczas zapisu zasobu!"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Idle"
msgstr ""
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Retry"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Download Error"
+msgstr "Pobierz"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download for this asset is already in progress!"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "first"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "prev"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "next"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "last"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "All"
+msgstr "Wszystko"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Plugins"
+msgstr "Wtyczki"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Sort:"
+msgstr "Sortuj:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Reverse"
+msgstr "Odwróć"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Category:"
+msgstr "Kategoria:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Site:"
+msgstr "Źródło:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Support.."
+msgstr "Wsparcie.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Official"
+msgstr "Oficjalny"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Testing"
+msgstr "Testowanie"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Assets ZIP File"
+msgstr "Plik ZIP assetów"
+
#: editor/plugins/camera_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
msgid "Preview"
msgstr "PodglÄ…d"
@@ -3814,12 +3350,17 @@ msgid "Edit CanvasItem"
msgstr "Edytuj CanvasItem"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Change Anchors"
+msgid "Anchors only"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#, fuzzy
+msgid "Change Anchors and Margins"
msgstr "Zmień zakotwiczenie"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom (%):"
-msgstr "Powiększenie (%):"
+msgid "Change Anchors"
+msgstr "Zmień zakotwiczenie"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Paste Pose"
@@ -3874,60 +3415,77 @@ msgid "Pan Mode"
msgstr "Tryb przesuwania"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Lock the selected object in place (can't be moved)."
-msgstr "Zablokuj wybrany obiekt w miejscu (nie można go przesuwać)."
+#, fuzzy
+msgid "Toggles snapping"
+msgstr "Przełącz pułapkę"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Unlock the selected object (can be moved)."
-msgstr "Odblokuj wybrany obiekt (można go przesuwać)."
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Use Snap"
+msgstr "Użyj przyciągania"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Makes sure the object's children are not selectable."
-msgstr "Zablokuj selekcję węzłów podrzędnych."
+#, fuzzy
+msgid "Snapping options"
+msgstr "Opcje animacji"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Restores the object's children's ability to be selected."
-msgstr "Odblokuj selekcję węzłów podrzędnych."
+#, fuzzy
+msgid "Snap to grid"
+msgstr "Tryb przyciÄ…gania:"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Edit"
-msgstr "Edycja"
+msgid "Use Rotation Snap"
+msgstr "Użyj kroków obrotu"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Use Snap"
-msgstr "Użyj przyciągania"
+#, fuzzy
+msgid "Configure Snap..."
+msgstr "Konfiguruj krokowanie.."
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Show Grid"
-msgstr "Pokaż siatkę"
+msgid "Snap Relative"
+msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Rotation Snap"
-msgstr "Użyj kroków obrotu"
+msgid "Use Pixel Snap"
+msgstr "Użyj krokowania na poziomie pikseli"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap Relative"
+msgid "Smart snapping"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Configure Snap.."
-msgstr "Konfiguruj krokowanie.."
+msgid "Snap to parent"
+msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Pixel Snap"
-msgstr "Użyj krokowania na poziomie pikseli"
+msgid "Snap to node anchor"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to node sides"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to other nodes"
+msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Skeleton.."
-msgstr "Szkielet.."
+msgid "Lock the selected object in place (can't be moved)."
+msgstr "Zablokuj wybrany obiekt w miejscu (nie można go przesuwać)."
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Unlock the selected object (can be moved)."
+msgstr "Odblokuj wybrany obiekt (można go przesuwać)."
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Makes sure the object's children are not selectable."
+msgstr "Zablokuj selekcję węzłów podrzędnych."
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Restores the object's children's ability to be selected."
+msgstr "Odblokuj selekcję węzłów podrzędnych."
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Make Bones"
@@ -3956,12 +3514,19 @@ msgid "View"
msgstr "Widok"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Reset"
-msgstr "Wyzeruj przybliżenie"
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Show Grid"
+msgstr "Pokaż siatkę"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Set.."
-msgstr "Ustaw przybliżenie..."
+#, fuzzy
+msgid "Show helpers"
+msgstr "Utwórz Kości"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#, fuzzy
+msgid "Show rulers"
+msgstr "Utwórz Kości"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Center Selection"
@@ -3972,8 +3537,9 @@ msgid "Frame Selection"
msgstr "Powiększ do zaznaczenia"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Anchor"
-msgstr ""
+#, fuzzy
+msgid "Layout"
+msgstr "Zapisz układ"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Insert Keys"
@@ -3996,12 +3562,21 @@ msgid "Clear Pose"
msgstr "Wyczyść Pozę"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Set a Value"
-msgstr "Ustaw Wartość"
+msgid "Drag pivot from mouse position"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#, fuzzy
+msgid "Set pivot at mouse position"
+msgstr "Ustaw pozycje punktu krzywej"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Multiply grid step by 2"
+msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap (Pixels):"
-msgstr "PrzyciÄ…ganie (piksele):"
+msgid "Divide grid step by 2"
+msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
#, fuzzy
@@ -4012,24 +3587,29 @@ msgstr "Dodaj wszystko"
msgid "Adding %s..."
msgstr "Dodawanie %s..."
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Create Node"
msgstr "Utwórz węzeł"
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Error instancing scene from %s"
msgstr "BÅ‚Ä…d instancjacji sceny z %s"
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "OK :("
msgstr "OK :("
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
#, fuzzy
msgid "No parent to instance a child at."
msgstr "Brak elementu nadrzędnego do stworzenia instancji."
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "This operation requires a single selected node."
msgstr "Ta operacja wymaga pojedynczego wybranego węzła."
@@ -4046,45 +3626,6 @@ msgstr ""
"Przeciągnij i upuść + Shift: dodaj węzeł równorzędny\n"
"Przeciągnij i upuść + Alt: Zmień typ węzła"
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Create Poly"
-msgstr "Utwórz Polygon"
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly (Remove Point)"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Create a new polygon from scratch."
-msgstr "Utwórz nowy wielokąt."
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-msgid ""
-"Edit existing polygon:\n"
-"LMB: Move Point.\n"
-"Ctrl+LMB: Split Segment.\n"
-"RMB: Erase Point."
-msgstr ""
-
#: editor/plugins/collision_polygon_editor_plugin.cpp
msgid "Create Poly3D"
msgstr ""
@@ -4094,14 +3635,6 @@ msgid "Set Handle"
msgstr ""
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Creating Mesh Library"
-msgstr "Tworzenie Mesh Library"
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Thumbnail.."
-msgstr "Miniatura.."
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Remove item %d?"
msgstr "Usuń element %d?"
@@ -4124,6 +3657,27 @@ msgid "Update from Scene"
msgstr "Aktualizuj ze sceny"
#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat0"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat1"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+#, fuzzy
+msgid "Ease in"
+msgstr "Usuń zaznaczenie"
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Ease out"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Smoothstep"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
#, fuzzy
msgid "Modify Curve Point"
msgstr "Zamknij krzywÄ…"
@@ -4208,22 +3762,18 @@ msgid "Create Occluder Polygon"
msgstr "Stwórz Occluder Polygon"
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Edit existing polygon:"
msgstr "Edytuj istniejÄ…cy polygon:"
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "LMB: Move Point."
msgstr "LMB: Przesuń Punkt."
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Ctrl+LMB: Split Segment."
msgstr "Ctrl + LPM: Podziału segmentu."
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "RMB: Erase Point."
msgstr "RMB: Wymaż Punkt."
@@ -4328,6 +3878,10 @@ msgid "Create Outline"
msgstr ""
#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Mesh"
+msgstr "Siatka"
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Create Trimesh Static Body"
msgstr ""
@@ -4455,12 +4009,75 @@ msgstr "Losowa skala:"
msgid "Populate"
msgstr ""
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Create Navigation Polygon"
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake!"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake the navigation mesh.\n"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Clear the navigation mesh."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Setting up Configuration..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Calculating grid size..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating heightfield..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Marking walkable triangles..."
+msgstr "Zachowywanie lokalnych zmian.."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Constructing compact heightfield..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Eroding walkable area..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Partitioning..."
+msgstr "Ostrzeżenie"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating contours..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating polymesh..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Converting to native navigation mesh..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Navigation Mesh Generator Setup:"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Parsing Geometry..."
+msgstr "Parsowanie Geometrii"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Done!"
msgstr ""
#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Remove Poly And Point"
+msgid "Create Navigation Polygon"
msgstr ""
#: editor/plugins/particles_2d_editor_plugin.cpp
@@ -4644,16 +4261,19 @@ msgid "Curve Point #"
msgstr "Punkt Krzywej #"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve Point Position"
msgstr "Ustaw pozycje punktu krzywej"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve In Position"
-msgstr ""
+msgstr "Ustaw pozycje punktu krzywej"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve Out Position"
-msgstr ""
+msgstr "Ustaw pozycje punktu krzywej"
#: editor/plugins/path_editor_plugin.cpp
msgid "Split Path"
@@ -4714,6 +4334,14 @@ msgid "Scale Polygon"
msgstr "Skaluj WielokÄ…t"
#: editor/plugins/polygon_2d_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Edit"
+msgstr "Edycja"
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Polygon->UV"
msgstr "WielokÄ…t->UV"
@@ -4768,63 +4396,10 @@ msgstr "Wczytaj Zasób"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/shader_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "Wklej"
-#: editor/plugins/rich_text_editor_plugin.cpp
-msgid "Parse BBCode"
-msgstr "Parsuj BBCode"
-
-#: editor/plugins/sample_editor_plugin.cpp
-msgid "Length:"
-msgstr "Długość:"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Open Sample File(s)"
-msgstr "Otwórz plik(i) sampli"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "ERROR: Couldn't load sample!"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Add Sample"
-msgstr "Dodaj sampel"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Rename Sample"
-msgstr "Zmień nazwę sampla"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Delete Sample"
-msgstr "Usuń sampel"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "16 Bits"
-msgstr "16 Bits"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "8 Bits"
-msgstr "8 Bits"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Stereo"
-msgstr "Stereo"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Mono"
-msgstr "Mono"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Format"
-msgstr "Format"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Pitch"
-msgstr "Wysokość"
-
#: editor/plugins/script_editor_plugin.cpp
#, fuzzy
msgid "Clear Recent Files"
@@ -4917,6 +4492,10 @@ msgstr "Zamknij pliki pomocy"
msgid "Close All"
msgstr "Zamknij"
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+msgid "Run"
+msgstr "Uruchom"
+
#: editor/plugins/script_editor_plugin.cpp
#, fuzzy
msgid "Toggle Scripts Panel"
@@ -4949,7 +4528,8 @@ msgstr "Krok w"
msgid "Break"
msgstr "Przerwa"
-#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+#: editor/script_editor_debugger.cpp
msgid "Continue"
msgstr "Kontynuuj"
@@ -4963,18 +4543,6 @@ msgid "Debug with external editor"
msgstr "Otwórz w edytorze"
#: editor/plugins/script_editor_plugin.cpp
-msgid "Window"
-msgstr "Okno"
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Left"
-msgstr "Przesuń w lewo"
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Right"
-msgstr "Przesuń w prawo"
-
-#: editor/plugins/script_editor_plugin.cpp
#, fuzzy
msgid "Open Godot online documentation"
msgstr "Poszukaj w dokumentacji referencyjnej."
@@ -5064,8 +4632,9 @@ msgid "Cut"
msgstr "Wytnij"
#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "Kopiuj"
@@ -5331,10 +4900,6 @@ msgid "View Plane Transform."
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Scaling to %s%%."
-msgstr "Skalowanie do %s%%."
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rotating %s degrees."
msgstr "Obracanie o %s stopni."
@@ -5351,10 +4916,6 @@ msgid "Top View."
msgstr "Widok z góry."
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Top"
-msgstr "Góra"
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rear View."
msgstr "Widok z tyłu."
@@ -5599,6 +5160,10 @@ msgid "Transform"
msgstr "Przekształcanie"
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Configure Snap.."
+msgstr "Konfiguruj krokowanie.."
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Local Coords"
msgstr "Koordynaty lokalne"
@@ -5744,6 +5309,10 @@ msgid "Speed (FPS):"
msgstr "Prędkość (FPS):"
#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Loop"
+msgstr "Pętla"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Animation Frames"
msgstr "Klatki animacji"
@@ -5756,12 +5325,14 @@ msgid "Insert Empty (After)"
msgstr "Dodaj pusty (później)"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Up"
-msgstr "Góra"
+#, fuzzy
+msgid "Move (Before)"
+msgstr "Usuń węzeł(y)"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Down"
-msgstr "Dół"
+#, fuzzy
+msgid "Move (After)"
+msgstr "Przesuń w lewo"
#: editor/plugins/style_box_editor_plugin.cpp
msgid "StyleBox Preview:"
@@ -5840,9 +5411,12 @@ msgid "Remove All"
msgstr "Usuń"
#: editor/plugins/theme_editor_plugin.cpp
-#, fuzzy
-msgid "Theme"
-msgstr "Zapisz motyw"
+msgid "Edit theme.."
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Theme editing menu."
+msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
msgid "Add Class Items"
@@ -5927,6 +5501,10 @@ msgid "Style"
msgstr "Styl"
#: editor/plugins/theme_editor_plugin.cpp
+msgid "Font"
+msgstr "Font"
+
+#: editor/plugins/theme_editor_plugin.cpp
msgid "Color"
msgstr "Kolor"
@@ -5978,8 +5556,9 @@ msgid "Mirror Y"
msgstr "Odbij Y"
#: editor/plugins/tile_map_editor_plugin.cpp
-msgid "Bucket"
-msgstr "Wiadro"
+#, fuzzy
+msgid "Paint Tile"
+msgstr "Maluj TileMap"
#: editor/plugins/tile_map_editor_plugin.cpp
msgid "Pick Tile"
@@ -6045,6 +5624,11 @@ msgid "Delete preset '%s'?"
msgstr "Usunąć zaznaczone pliki?"
#: editor/project_export.cpp
+#, fuzzy
+msgid "Export templates for this platform are missing/corrupted: "
+msgstr "Brakuje eksportu szablonów dla tej platformy:"
+
+#: editor/project_export.cpp
msgid "Presets"
msgstr "Profile eksportu"
@@ -6127,33 +5711,62 @@ msgstr "Brakuje eksportu szablonów dla tej platformy:"
#: editor/project_export.cpp
#, fuzzy
+msgid "Export templates for this platform are missing/corrupted:"
+msgstr "Brakuje eksportu szablonów dla tej platformy:"
+
+#: editor/project_export.cpp
+#, fuzzy
msgid "Export With Debug"
msgstr "Eksportuj TileSet"
#: editor/project_manager.cpp
-msgid "Invalid project path, the path must exist!"
-msgstr "Niepoprawna ścieżka projektu, ścieżka musi istnieć!"
+#, fuzzy
+msgid "The path does not exist."
+msgstr "Plik nie istnieje."
#: editor/project_manager.cpp
#, fuzzy
-msgid "Invalid project path, project.godot must not exist."
-msgstr "Niepoprawna ścieżka projektu, engine.cfg nie może istnieć."
+msgid "Please choose a 'project.godot' file."
+msgstr "Eksportuj poza folderem projektu!"
#: editor/project_manager.cpp
-#, fuzzy
-msgid "Invalid project path, project.godot must exist."
-msgstr "Niepoprawna ścieżka projektu, engine.cfg musi istnieć."
+msgid ""
+"Your project will be created in a non empty folder (you might want to create "
+"a new folder)."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Please choose a folder that does not contain a 'project.godot' file."
+msgstr ""
#: editor/project_manager.cpp
msgid "Imported Project"
msgstr "Zaimportowano projekt"
#: editor/project_manager.cpp
+msgid " "
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "It would be a good idea to name your project."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Invalid project path (changed anything?)."
msgstr "Niepoprawna ścieżka projektu (zmienić cokolwiek?)."
#: editor/project_manager.cpp
#, fuzzy
+msgid "Couldn't get project.godot in project path."
+msgstr "Nie można było utworzyć engine.cfg w ścieżce projektu."
+
+#: editor/project_manager.cpp
+#, fuzzy
+msgid "Couldn't edit project.godot in project path."
+msgstr "Nie można było utworzyć engine.cfg w ścieżce projektu."
+
+#: editor/project_manager.cpp
+#, fuzzy
msgid "Couldn't create project.godot in project path."
msgstr "Nie można było utworzyć engine.cfg w ścieżce projektu."
@@ -6162,38 +5775,49 @@ 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
+#, fuzzy
+msgid "Rename Project"
+msgstr "Projekt bez nazwy"
+
+#: editor/project_manager.cpp
+#, fuzzy
+msgid "Couldn't get project.godot in the project path."
+msgstr "Nie można było utworzyć engine.cfg w ścieżce projektu."
+
+#: editor/project_manager.cpp
+msgid "New Game Project"
+msgstr "Nowy projekt gry"
+
+#: editor/project_manager.cpp
msgid "Import Existing Project"
msgstr "Importuj istniejÄ…cy projekt"
#: editor/project_manager.cpp
-msgid "Project Path (Must Exist):"
-msgstr "Ścieżka projektu (musi istnieć):"
+msgid "Create New Project"
+msgstr "Utwórz nowy projekt"
+
+#: editor/project_manager.cpp
+msgid "Install Project:"
+msgstr "Zainstaluj projekt:"
#: editor/project_manager.cpp
msgid "Project Name:"
msgstr "Nazwa projektu:"
#: editor/project_manager.cpp
-msgid "Create New Project"
-msgstr "Utwórz nowy projekt"
+#, fuzzy
+msgid "Create folder"
+msgstr "Utwórz katalog"
#: editor/project_manager.cpp
msgid "Project Path:"
msgstr "Ścieżka do projektu:"
#: editor/project_manager.cpp
-msgid "Install Project:"
-msgstr "Zainstaluj projekt:"
-
-#: editor/project_manager.cpp
msgid "Browse"
msgstr "Szukaj"
#: editor/project_manager.cpp
-msgid "New Game Project"
-msgstr "Nowy projekt gry"
-
-#: editor/project_manager.cpp
msgid "That's a BINGO!"
msgstr "To BINGO!"
@@ -6202,6 +5826,11 @@ msgid "Unnamed Project"
msgstr "Projekt bez nazwy"
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Can't open project"
+msgstr "Połącz.."
+
+#: editor/project_manager.cpp
msgid "Are you sure to open more than one project?"
msgstr "Czy jesteś pewny że chcesz otworzyć więcej niż jeden projekt?"
@@ -6231,6 +5860,12 @@ msgstr "Usunąć projekt z listy? (Zawartość folderu nie zostanie zmodyfikowan
#: editor/project_manager.cpp
msgid ""
+"Language changed.\n"
+"The UI will update next time the editor or project manager starts."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid ""
"You are about the scan %s folders for existing Godot projects. Do you "
"confirm?"
msgstr ""
@@ -6242,10 +5877,6 @@ msgid "Project List"
msgstr "Lista projektów"
#: editor/project_manager.cpp
-msgid "Run"
-msgstr "Uruchom"
-
-#: editor/project_manager.cpp
msgid "Scan"
msgstr "Skanuj"
@@ -6268,6 +5899,11 @@ msgstr "Wyjdź"
#: editor/project_manager.cpp
#, fuzzy
+msgid "Restart Now"
+msgstr "Restart(y):"
+
+#: editor/project_manager.cpp
+#, fuzzy
msgid "Can't run project"
msgstr "Połącz.."
@@ -6304,17 +5940,14 @@ msgid "Add Input Action Event"
msgstr "Dodaj zdarzenie akcji wejścia"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Meta+"
msgstr "Meta+"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Shift+"
msgstr "Shift+"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Alt+"
msgstr "Alt+"
@@ -6376,7 +6009,7 @@ msgstr "Zmień"
msgid "Joypad Axis Index:"
msgstr "OÅ› joysticka"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Axis"
msgstr "OÅ›"
@@ -6398,31 +6031,31 @@ msgstr "Wyczyść zdarzenie akcji wejścia"
msgid "Add Event"
msgstr "Dodaj pusty"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Device"
msgstr "UrzÄ…dzenie"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Button"
msgstr "Przycisk"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Left Button."
msgstr "Lewy przycisk."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Right Button."
msgstr "Prawy przycisk."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Middle Button."
msgstr "Åšrodkowy przycisk."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Up."
msgstr "Kółko myszy w górę."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Down."
msgstr "Kółko myszy w dół."
@@ -6431,7 +6064,7 @@ msgid "Add Global Property"
msgstr ""
#: editor/project_settings_editor.cpp
-msgid "Select an setting item first!"
+msgid "Select a setting item first!"
msgstr ""
#: editor/project_settings_editor.cpp
@@ -6450,6 +6083,16 @@ msgid "Delete Item"
msgstr "Usuń"
#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Can't contain '/' or ':'"
+msgstr "Podłącz do węzła:"
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Already existing"
+msgstr "Akcja %s już istnieje!"
+
+#: editor/project_settings_editor.cpp
msgid "Error saving settings."
msgstr "Błąd zapisu ustawień."
@@ -6491,6 +6134,15 @@ msgstr "Usuń opcję mapowania zasobu"
#: editor/project_settings_editor.cpp
#, fuzzy
+msgid "Changed Locale Filter"
+msgstr "Zmień rozmiar kamery"
+
+#: editor/project_settings_editor.cpp
+msgid "Changed Locale Filter Mode"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
msgid "Project Settings (project.godot)"
msgstr "Ustawienia projektu (engine.cfg)"
@@ -6552,6 +6204,30 @@ msgstr "Lokalizacja"
#: editor/project_settings_editor.cpp
#, fuzzy
+msgid "Locales Filter"
+msgstr "Lokalizacja"
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Show all locales"
+msgstr "Utwórz Kości"
+
+#: editor/project_settings_editor.cpp
+msgid "Show only selected locales"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Filter mode:"
+msgstr "Filtry"
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Locales:"
+msgstr "Lokalizacja"
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
msgid "AutoLoad"
msgstr "Autoładowanie"
@@ -6602,10 +6278,20 @@ msgstr "Nowy skrypt"
#: editor/property_editor.cpp
#, fuzzy
+msgid "Make Unique"
+msgstr "Utwórz Kości"
+
+#: editor/property_editor.cpp
+#, fuzzy
msgid "Show in File System"
msgstr "System plików"
#: editor/property_editor.cpp
+#, fuzzy
+msgid "Convert To %s"
+msgstr "Konwertuje na.."
+
+#: editor/property_editor.cpp
msgid "Error loading file: Not a resource!"
msgstr "BÅ‚Ä…d wczytania pliku: Brak zasobu!"
@@ -6646,6 +6332,11 @@ msgstr "Zaznacz Punkty"
#: editor/property_selector.cpp
#, fuzzy
+msgid "Select Virtual Method"
+msgstr "Tryb zaznaczenia"
+
+#: editor/property_selector.cpp
+#, fuzzy
msgid "Select Method"
msgstr "Tryb zaznaczenia"
@@ -6674,27 +6365,6 @@ msgstr "Zachowaj globalnÄ… transformacjÄ™"
msgid "Reparent"
msgstr "Zmień nadrzędny"
-#: editor/resources_dock.cpp
-msgid "Create New Resource"
-msgstr "Utwórz nowy zasób"
-
-#: editor/resources_dock.cpp
-msgid "Open Resource"
-msgstr "Otwórz zasób"
-
-#: editor/resources_dock.cpp
-msgid "Save Resource"
-msgstr "Zapisz zasób"
-
-#: editor/resources_dock.cpp
-msgid "Resource Tools"
-msgstr "Narzędzia zasobów"
-
-#: editor/resources_dock.cpp
-#, fuzzy
-msgid "Make Local"
-msgstr "Uczyń lokalnym"
-
#: editor/run_settings_dialog.cpp
msgid "Run Mode:"
msgstr "Tryb uruchamiania:"
@@ -6827,14 +6497,6 @@ msgid "Sub-Resources:"
msgstr "Zasoby:"
#: editor/scene_tree_dock.cpp
-msgid "Edit Groups"
-msgstr "Edytuj grupy"
-
-#: editor/scene_tree_dock.cpp
-msgid "Edit Connections"
-msgstr "Edytuj Połączenia"
-
-#: editor/scene_tree_dock.cpp
msgid "Clear Inheritance"
msgstr "Wyczyść dziedziczenie"
@@ -7028,6 +6690,15 @@ msgid "Invalid base path"
msgstr "Niepoprawna ścieżka bazowa"
#: editor/script_create_dialog.cpp
+msgid "Directory of the same name exists"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
+#, fuzzy
+msgid "File exists, will be reused"
+msgstr "Plik istnieje, nadpisać?"
+
+#: editor/script_create_dialog.cpp
msgid "Invalid extension"
msgstr "Niepoprawne rozszerzenie"
@@ -7073,6 +6744,10 @@ msgid "Load existing script file"
msgstr "Następny skrypt"
#: editor/script_create_dialog.cpp
+msgid "Language"
+msgstr "Język"
+
+#: editor/script_create_dialog.cpp
#, fuzzy
msgid "Inherits"
msgstr "Dziedziczy:"
@@ -7118,6 +6793,10 @@ msgid "Function:"
msgstr "Funkcja:"
#: editor/script_editor_debugger.cpp
+msgid "Pick one or more items from the list to display the graph."
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
msgid "Errors"
msgstr "Błędy"
@@ -7198,6 +6877,10 @@ msgid "Type"
msgstr "Typ"
#: editor/script_editor_debugger.cpp
+msgid "Format"
+msgstr "Format"
+
+#: editor/script_editor_debugger.cpp
msgid "Usage"
msgstr "Użycie"
@@ -7274,12 +6957,30 @@ msgstr ""
msgid "Change Probe Extents"
msgstr "Zmień rozmiar Box Shape"
+#: modules/gdnative/gd_native_library_editor.cpp
+#, fuzzy
+msgid "Library"
+msgstr "MeshLibrary..."
+
+#: modules/gdnative/gd_native_library_editor.cpp
+#, fuzzy
+msgid "Status"
+msgstr "Status:"
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Libraries: "
+msgstr ""
+
+#: modules/gdnative/register_types.cpp
+msgid "GDNative"
+msgstr ""
+
#: modules/gdscript/gd_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Invalid type argument to convert(), use TYPE_* constants."
msgstr "Niepoprawny typ argumentu funkcji convert(), użyj stałych TYPE_*."
-#: modules/gdscript/gd_functions.cpp
+#: modules/gdscript/gd_functions.cpp modules/mono/glue/glue_header.h
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Not enough bytes for decoding bytes, or invalid format."
msgstr ""
@@ -7333,10 +7034,6 @@ msgid "GridMap Duplicate Selection"
msgstr "Duplikuj zaznaczone"
#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "GridMap Paint"
-msgstr ""
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
#, fuzzy
msgid "Snap View"
msgstr "Widok z góry"
@@ -7440,13 +7137,8 @@ msgstr "Ustawienia przyciÄ…gania"
msgid "Pick Distance:"
msgstr "Instancja:"
-#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
-msgid "Tiles"
-msgstr "Plik"
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "Areas"
+#: modules/mono/editor/mono_bottom_panel.cpp
+msgid "Builds"
msgstr ""
#: modules/visual_script/visual_script.cpp
@@ -7654,11 +7346,19 @@ msgid "Return"
msgstr "Zwraca:"
#: modules/visual_script/visual_script_editor.cpp
+msgid "Call"
+msgstr "Wywołanie"
+
+#: modules/visual_script/visual_script_editor.cpp
#, fuzzy
msgid "Get"
msgstr "Ustaw"
#: modules/visual_script/visual_script_editor.cpp
+msgid "Script already has function '%s'"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
#, fuzzy
msgid "Change Input Value"
msgstr "Zmień Wartość Domyślną"
@@ -8073,6 +7773,12 @@ msgstr ""
"Zasób SpriteFrames musi być ustawiony jako wartość właściwości 'Frames' żeby "
"AnimatedSprite3D wyświetlał klatki."
+#: scene/3d/vehicle_body.cpp
+msgid ""
+"VehicleWheel serves to provide a wheel system to a VehicleBody. Please use "
+"it as a child of a VehicleBody."
+msgstr ""
+
#: scene/gui/color_picker.cpp
#, fuzzy
msgid "Raw Mode"
@@ -8083,6 +7789,10 @@ msgid "Add current color as a preset"
msgstr ""
#: scene/gui/dialogs.cpp
+msgid "Cancel"
+msgstr "Anuluj"
+
+#: scene/gui/dialogs.cpp
msgid "Alert!"
msgstr "Alarm!"
@@ -8090,10 +7800,6 @@ msgstr "Alarm!"
msgid "Please Confirm..."
msgstr "Proszę potwierdzić..."
-#: scene/gui/input_action.cpp
-msgid "Ctrl+"
-msgstr "Ctrl+"
-
#: scene/gui/popup.cpp
msgid ""
"Popups will hide by default unless you call popup() or any of the popup*() "
@@ -8133,6 +7839,598 @@ msgstr ""
"otrzymał jakiś rozmiar. W przeciwnym wypadku ustawi opcję RenderTarget i "
"przyporządkuj jego teksturę dla któregoś węzła."
+#: scene/resources/dynamic_font.cpp
+msgid "Error initializing FreeType."
+msgstr "BÅ‚Ä…d przy inicjalizacji FreeType."
+
+#: scene/resources/dynamic_font.cpp
+msgid "Unknown font format."
+msgstr "Nieznany format fontu."
+
+#: scene/resources/dynamic_font.cpp
+msgid "Error loading font."
+msgstr "BÅ‚Ä…d Å‚adowania fonta."
+
+#: scene/resources/dynamic_font.cpp
+msgid "Invalid font size."
+msgstr "Niepoprawny rozmiar fonta."
+
+#~ msgid "Filter:"
+#~ msgstr "Filtr:"
+
+#, fuzzy
+#~ msgid "Theme"
+#~ msgstr "Zapisz motyw"
+
+#~ msgid "Method List For '%s':"
+#~ msgstr "Lista metod '%s':"
+
+#~ msgid "Arguments:"
+#~ msgstr "Argumenty:"
+
+#~ msgid "Return:"
+#~ msgstr "Zwraca:"
+
+#~ msgid "Added:"
+#~ msgstr "Dodane:"
+
+#~ msgid "Removed:"
+#~ msgstr "Usunięte:"
+
+#~ msgid "Error saving atlas:"
+#~ msgstr "BÅ‚Ä…d podczas zapisywania atlasu:"
+
+#~ msgid "Could not save atlas subtexture:"
+#~ msgstr "Nie udało się zapisać tekstury atlasu:"
+
+#~ msgid "Exporting for %s"
+#~ msgstr "Exportowanie do %s"
+
+#~ msgid "Setting Up.."
+#~ msgstr "Konfigurowanie .."
+
+#~ msgid "Error loading scene."
+#~ msgstr "BÅ‚Ä…d Å‚adowania sceny."
+
+#~ msgid "Re-Import"
+#~ msgstr "Importuj ponownie"
+
+#~ msgid "Please wait for scan to complete."
+#~ msgstr "Proszę poczekać na zakończenie skanowania."
+
+#~ msgid "Current scene must be saved to re-import."
+#~ msgstr "Bieżąca scena musi być zapisana aby ponownie zaimportować."
+
+#~ msgid "Save & Re-Import"
+#~ msgstr "Zapisz i importuj ponownie"
+
+#~ msgid "Re-Importing"
+#~ msgstr "Prze-Importowanie"
+
+#~ msgid "Re-Import Changed Resources"
+#~ msgstr "Zaimportuj ponownie zmienione zasoby"
+
+#~ msgid "Loading Export Templates"
+#~ msgstr "Wczytywanie szablonów eksportu"
+
+#, fuzzy
+#~ msgid ""
+#~ "\n"
+#~ "Status: Needs Re-Import"
+#~ msgstr "Zapisz i importuj ponownie"
+
+#, fuzzy
+#~ msgid "Same source and destination files, doing nothing."
+#~ msgstr "Pliki źródłowe i docelowe są te same, nie podjęto żadnej akcji."
+
+#~ msgid "Same source and destination paths, doing nothing."
+#~ msgstr ""
+#~ "Ścieżki źródłowa i docelowa są takie same, żadna akcja nie została "
+#~ "wykonana."
+
+#, fuzzy
+#~ msgid "Can't move directories to within themselves."
+#~ msgstr "Nie możesz przenieść danego katalogu do jego wnętrza."
+
+#, fuzzy
+#~ msgid "Error moving file:\n"
+#~ msgstr "BÅ‚Ä…d wczytywania obrazu:"
+
+#~ msgid "Pick New Name and Location For:"
+#~ msgstr "Wybierz nowÄ… nazwÄ™ i lokacjÄ™ dla:"
+
+#~ msgid "No files selected!"
+#~ msgstr "Nie wybrano pliku!"
+
+#~ msgid "Info"
+#~ msgstr "Informacje"
+
+#~ msgid "Re-Import.."
+#~ msgstr "Importuj ponownie.."
+
+#~ msgid "No bit masks to import!"
+#~ msgstr "Brak mask bitowych do zaimportowania!"
+
+#~ msgid "Target path is empty."
+#~ msgstr "Docelowa ścieżka jest pusta."
+
+#~ msgid "Target path must be a complete resource path."
+#~ msgstr "Ścieżka docelowa musi być bezwzględna."
+
+#~ msgid "Target path must exist."
+#~ msgstr "Docelowa ścieżka musi istnieć."
+
+#~ msgid "Save path is empty!"
+#~ msgstr "Ścieżka zapisu jest pusta!"
+
+#~ msgid "Import BitMasks"
+#~ msgstr "Importuj BitMasks"
+
+#~ msgid "Source Texture(s):"
+#~ msgstr "Źródło tekstury:"
+
+#~ msgid "Target Path:"
+#~ msgstr "Ścieżka docelowa:"
+
+#~ msgid "Accept"
+#~ msgstr "Akceptuj"
+
+#~ msgid "Bit Mask"
+#~ msgstr "BitMask"
+
+#~ msgid "No source font file!"
+#~ msgstr "Brak pliku źródłowego fontu!"
+
+#~ msgid "No target font resource!"
+#~ msgstr "Brak docelowego zasobu fontu!"
+
+#, fuzzy
+#~ msgid ""
+#~ "Invalid file extension.\n"
+#~ "Please use .font."
+#~ msgstr ""
+#~ "Błędne rozszerzenie pliku.\n"
+#~ "Proszę użyć .fnt."
+
+#~ msgid "Couldn't save font."
+#~ msgstr "Nie udało się zapisać fontu."
+
+#~ msgid "Source Font:"
+#~ msgstr "Źródło fontu:"
+
+#~ msgid "Source Font Size:"
+#~ msgstr "Wielkość oryginalna fontu:"
+
+#~ msgid "Dest Resource:"
+#~ msgstr "Zasób docelowy:"
+
+#~ msgid "The quick brown fox jumps over the lazy dog."
+#~ msgstr "ŻżŹźĆćŃńĄąÅłĘęÓó."
+
+#~ msgid "Test:"
+#~ msgstr "Test:"
+
+#~ msgid "Options:"
+#~ msgstr "Opcje:"
+
+#~ msgid "Font Import"
+#~ msgstr "Import fontu"
+
+#~ msgid ""
+#~ "This file is already a Godot font file, please supply a BMFont type file "
+#~ "instead."
+#~ msgstr ""
+#~ "Ten plik jest już plikiem fontu Godot, proszę podać plik typu BMFont."
+
+#~ msgid "Failed opening as BMFont file."
+#~ msgstr "Nie powiodło się, otwarcie pliku jako BMFont."
+
+#~ msgid "Invalid font custom source."
+#~ msgstr "Nie rozpoznano typu fontu."
+
+#~ msgid "No meshes to import!"
+#~ msgstr "Brak siatek do zaimportowania!"
+
+#~ msgid "Single Mesh Import"
+#~ msgstr "Importuj Mesh"
+
+#~ msgid "Source Mesh(es):"
+#~ msgstr "Źródło Mesh:"
+
+#~ msgid "Surface %d"
+#~ msgstr "Powierzchnia %d"
+
+#~ msgid "No samples to import!"
+#~ msgstr "Brak sampli do importu!"
+
+#~ msgid "Import Audio Samples"
+#~ msgstr "Importuj pliki dźwiękowe"
+
+#~ msgid "Source Sample(s):"
+#~ msgstr "Źródło dźwięku:"
+
+#~ msgid "Audio Sample"
+#~ msgstr "Dźwięk"
+
+#~ msgid "New Clip"
+#~ msgstr "Nowy klip"
+
+#~ msgid "Flags"
+#~ msgstr "Flagi"
+
+#~ msgid "Bake FPS:"
+#~ msgstr "Wypal FPS:"
+
+#~ msgid "Optimizer"
+#~ msgstr "Optymalizator"
+
+#~ msgid "Max Linear Error"
+#~ msgstr "Maksymalny błąd liniowy"
+
+#~ msgid "Max Angular Error"
+#~ msgstr "Maksymalny błąd kątowy"
+
+#~ msgid "Max Angle"
+#~ msgstr "Maksymalny KÄ…t"
+
+#~ msgid "Clips"
+#~ msgstr "Klipy"
+
+#~ msgid "Start(s)"
+#~ msgstr "Start"
+
+#~ msgid "End(s)"
+#~ msgstr "Koniec"
+
+#~ msgid "Filters"
+#~ msgstr "Filtry"
+
+#~ msgid "Source path is empty."
+#~ msgstr "Ścieżka źródłowa jest pusta."
+
+#~ msgid "Couldn't load post-import script."
+#~ msgstr "Nie udało się wczytać skryptu po imporcie."
+
+#~ msgid "Invalid/broken script for post-import."
+#~ msgstr "Niepoprawny/uszkodzony skrypt post-importu."
+
+#~ msgid "Error importing scene."
+#~ msgstr "BÅ‚Ä…d podczas wczytywania sceny."
+
+#~ msgid "Import 3D Scene"
+#~ msgstr "Zaimportuj Scene 3D"
+
+#~ msgid "Source Scene:"
+#~ msgstr "Scena źródłowa:"
+
+#~ msgid "Same as Target Scene"
+#~ msgstr "Taki sam jak scena docelowa"
+
+#~ msgid "Shared"
+#~ msgstr "Współdzielone"
+
+#~ msgid "Target Texture Folder:"
+#~ msgstr "Docelowy folder tekstur:"
+
+#~ msgid "Post-Process Script:"
+#~ msgstr "Skrypt do wywołania po imporcie:"
+
+#~ msgid "Custom Root Node Type:"
+#~ msgstr "Niestandardowy typ węzła głównego:"
+
+#~ msgid "Auto"
+#~ msgstr "Automatyczny"
+
+#, fuzzy
+#~ msgid "Root Node Name:"
+#~ msgstr "Nazwa węzła:"
+
+#~ msgid "The Following Files are Missing:"
+#~ msgstr "Brakuje następujących plików:"
+
+#~ msgid "Import Anyway"
+#~ msgstr "Zaimportuj Pomimo"
+
+#~ msgid "Import & Open"
+#~ msgstr "Importuj i Otwórz"
+
+#~ msgid "Edited scene has not been saved, open imported scene anyway?"
+#~ msgstr ""
+#~ "Edytowana sceny nie została zapisana. Otworzyć importowaną scenę mimo "
+#~ "tego?"
+
+#~ msgid "Import Image:"
+#~ msgstr "Zaimportuj Obraz:"
+
+#~ msgid "Couldn't localize path: %s (already local)"
+#~ msgstr "Nie można zlokalizować ścieżki: %s (już jest lokalna)"
+
+#~ msgid "3D Scene Animation"
+#~ msgstr "Scena animacji 3D"
+
+#~ msgid "Uncompressed"
+#~ msgstr "Nieskompresowany"
+
+#~ msgid "Compress Lossless (PNG)"
+#~ msgstr "Bezstratna Kompresja (PNG)"
+
+#~ msgid "Compress Lossy (WebP)"
+#~ msgstr "Kompresja Stratna (WebP)"
+
+#~ msgid "Compress (VRAM)"
+#~ msgstr "Skompresuj (VRAM)"
+
+#~ msgid "Texture Format"
+#~ msgstr "Format Tekstury"
+
+#~ msgid "Texture Compression Quality (WebP):"
+#~ msgstr "Jakość Kompresji Textury (WebP):"
+
+#~ msgid "Texture Options"
+#~ msgstr "Opcje Tekstury"
+
+#~ msgid "Please specify some files!"
+#~ msgstr "Proszę podać kilka plików !"
+
+#~ msgid "At least one file needed for Atlas."
+#~ msgstr "Co najmniej jeden plik potrzebny do \"Atlas'u\"."
+
+#~ msgid "Error importing:"
+#~ msgstr "BÅ‚Ä…d importowania:"
+
+#~ msgid "Only one file is required for large texture."
+#~ msgstr "Tylko jeden plik jest wymagany dla dużych tekstur."
+
+#~ msgid "Max Texture Size:"
+#~ msgstr "Maksymalny rozmiar tekstury:"
+
+#~ msgid "Import Textures for Atlas (2D)"
+#~ msgstr "Zaimportuj Tekstury z \"Atlas'u\" (2D)"
+
+#~ msgid "Cell Size:"
+#~ msgstr "Rozmiar komórki:"
+
+#~ msgid "Large Texture"
+#~ msgstr "Duża Tekstura"
+
+#~ msgid "Import Large Textures (2D)"
+#~ msgstr "Zaimportuj Duże Tekstury (2D)"
+
+#~ msgid "Source Texture"
+#~ msgstr "Źródłowa Tekstura"
+
+#~ msgid "Base Atlas Texture"
+#~ msgstr "Bazowa tekstura \"Atlas'u\""
+
+#~ msgid "Source Texture(s)"
+#~ msgstr "Tekstura(y) źródłowe"
+
+#~ msgid "Import Textures for 2D"
+#~ msgstr "Importuj tekstury dla 2D"
+
+#~ msgid "Import Textures for 3D"
+#~ msgstr "Importuj tekstury dla 3D"
+
+#~ msgid "Import Textures"
+#~ msgstr "Zaimportuj Tekstury"
+
+#~ msgid "2D Texture"
+#~ msgstr "Tekstura 2D"
+
+#~ msgid "3D Texture"
+#~ msgstr "Tekstura 3D"
+
+#~ msgid "Atlas Texture"
+#~ msgstr "Tekstura \"Atlas'u\""
+
+#~ msgid ""
+#~ "NOTICE: Importing 2D textures is not mandatory. Just copy png/jpg files "
+#~ "to the project."
+#~ msgstr ""
+#~ "UWAGA: Importowanie tekstur 2D nie jest wymagane. Po prostu skopiuj pliki "
+#~ "png/jpg do folderu projektu."
+
+#~ msgid "Crop empty space."
+#~ msgstr "Przytnij pusty obszar."
+
+#~ msgid "Texture"
+#~ msgstr "Tekstura"
+
+#~ msgid "Import Large Texture"
+#~ msgstr "Importuj dużą teksturę"
+
+#~ msgid "Load Source Image"
+#~ msgstr "Wczytaj obrazek źródłowy"
+
+#~ msgid "Slicing"
+#~ msgstr "Przycinanie"
+
+#~ msgid "Saving"
+#~ msgstr "Zapisywanie"
+
+#~ msgid "Couldn't save large texture:"
+#~ msgstr "Nie udało się zapisać dużej tekstury:"
+
+#~ msgid "Build Atlas For:"
+#~ msgstr "Zbuduj Atlas dla:"
+
+#~ msgid "Loading Image:"
+#~ msgstr "Åadowanie obrazu:"
+
+#~ msgid "Couldn't load image:"
+#~ msgstr "Nie można załadować obrazu:"
+
+#~ msgid "Converting Images"
+#~ msgstr "Konwersja obrazków"
+
+#~ msgid "Cropping Images"
+#~ msgstr "Przycinanie obrazków"
+
+#~ msgid "Couldn't save atlas image:"
+#~ msgstr "Nie można zapisać obrazu atlasu:"
+
+#, fuzzy
+#~ msgid "Couldn't save converted texture:"
+#~ msgstr "Nie można zapisać zkonwertowanej tekstury:"
+
+#~ msgid "Invalid source!"
+#~ msgstr "Wadliwe źródło!"
+
+#~ msgid "Invalid translation source!"
+#~ msgstr "Nieprawidłowe źródło tłumaczenia!"
+
+#~ msgid "Column"
+#~ msgstr "Kolumna"
+
+#~ msgid "No items to import!"
+#~ msgstr "Brak elementów do importu!"
+
+#~ msgid "No target path!"
+#~ msgstr "Brak ścieżki docelowej!"
+
+#~ msgid "Import Translations"
+#~ msgstr "Importuj tłumaczenia"
+
+#~ msgid "Couldn't import!"
+#~ msgstr "Nie można zaimportować!"
+
+#~ msgid "Import Translation"
+#~ msgstr "Importuj tłumaczenie"
+
+#~ msgid "Source CSV:"
+#~ msgstr "Źródłowy CSV:"
+
+#~ msgid "Ignore First Row"
+#~ msgstr "Ignoruj pierwszy wiersz"
+
+#~ msgid "Compress"
+#~ msgstr "Skompresuj"
+
+#, fuzzy
+#~ msgid "Add to Project (project.godot)"
+#~ msgstr "Dodaj do projektu (engine.cfg)"
+
+#~ msgid "Import Languages:"
+#~ msgstr "Zaimportuj Język:"
+
+#~ msgid "Translation"
+#~ msgstr "TÅ‚umaczenie"
+
+#~ msgid "Making BVH"
+#~ msgstr "Tworzenie BVH"
+
+#~ msgid "Zoom (%):"
+#~ msgstr "Powiększenie (%):"
+
+#~ msgid "Skeleton.."
+#~ msgstr "Szkielet.."
+
+#~ msgid "Zoom Reset"
+#~ msgstr "Wyzeruj przybliżenie"
+
+#~ msgid "Zoom Set.."
+#~ msgstr "Ustaw przybliżenie..."
+
+#~ msgid "Set a Value"
+#~ msgstr "Ustaw Wartość"
+
+#~ msgid "Snap (Pixels):"
+#~ msgstr "PrzyciÄ…ganie (piksele):"
+
+#~ msgid "Parse BBCode"
+#~ msgstr "Parsuj BBCode"
+
+#~ msgid "Length:"
+#~ msgstr "Długość:"
+
+#~ msgid "Open Sample File(s)"
+#~ msgstr "Otwórz plik(i) sampli"
+
+#~ msgid "Add Sample"
+#~ msgstr "Dodaj sampel"
+
+#~ msgid "Rename Sample"
+#~ msgstr "Zmień nazwę sampla"
+
+#~ msgid "Delete Sample"
+#~ msgstr "Usuń sampel"
+
+#~ msgid "16 Bits"
+#~ msgstr "16 Bits"
+
+#~ msgid "8 Bits"
+#~ msgstr "8 Bits"
+
+#~ msgid "Stereo"
+#~ msgstr "Stereo"
+
+#~ msgid "Mono"
+#~ msgstr "Mono"
+
+#~ msgid "Pitch"
+#~ msgstr "Wysokość"
+
+#~ msgid "Window"
+#~ msgstr "Okno"
+
+#~ msgid "Move Right"
+#~ msgstr "Przesuń w prawo"
+
+#~ msgid "Scaling to %s%%."
+#~ msgstr "Skalowanie do %s%%."
+
+#~ msgid "Up"
+#~ msgstr "Góra"
+
+#~ msgid "Down"
+#~ msgstr "Dół"
+
+#~ msgid "Bucket"
+#~ msgstr "Wiadro"
+
+#~ msgid "Invalid project path, the path must exist!"
+#~ msgstr "Niepoprawna ścieżka projektu, ścieżka musi istnieć!"
+
+#, fuzzy
+#~ msgid "Invalid project path, project.godot must not exist."
+#~ msgstr "Niepoprawna ścieżka projektu, engine.cfg nie może istnieć."
+
+#, fuzzy
+#~ msgid "Invalid project path, project.godot must exist."
+#~ msgstr "Niepoprawna ścieżka projektu, engine.cfg musi istnieć."
+
+#~ msgid "Project Path (Must Exist):"
+#~ msgstr "Ścieżka projektu (musi istnieć):"
+
+#~ msgid "Create New Resource"
+#~ msgstr "Utwórz nowy zasób"
+
+#~ msgid "Open Resource"
+#~ msgstr "Otwórz zasób"
+
+#~ msgid "Save Resource"
+#~ msgstr "Zapisz zasób"
+
+#~ msgid "Resource Tools"
+#~ msgstr "Narzędzia zasobów"
+
+#, fuzzy
+#~ msgid "Make Local"
+#~ msgstr "Uczyń lokalnym"
+
+#~ msgid "Edit Groups"
+#~ msgstr "Edytuj grupy"
+
+#~ msgid "Edit Connections"
+#~ msgstr "Edytuj Połączenia"
+
+#, fuzzy
+#~ msgid "Tiles"
+#~ msgstr "Plik"
+
+#~ msgid "Ctrl+"
+#~ msgstr "Ctrl+"
+
#~ msgid "Close scene? (Unsaved changes will be lost)"
#~ msgstr "Zamknąć scenę? (Niezapisane zmiany zostaną utracone)"
@@ -8264,9 +8562,6 @@ msgstr ""
#~ msgid "Install Export Templates"
#~ msgstr "Zainstaluj Szablony Eksportu"
-#~ msgid "Please export outside the project folder!"
-#~ msgstr "Eksportuj poza folderem projektu!"
-
#~ msgid "Error exporting project!"
#~ msgstr "BÅ‚Ä…d przy eksporcie projektu!"
@@ -8304,18 +8599,12 @@ msgstr ""
#~ msgid "Include"
#~ msgstr "Zawiera"
-#~ msgid "Change Image Group"
-#~ msgstr "Zmień grupę obrazków"
-
#~ msgid "Group name can't be empty!"
#~ msgstr "Nazwa grupy nie może być pusta!"
#~ msgid "Invalid character in group name!"
#~ msgstr "Nieprawidłowy znak w nazwie grupy!"
-#~ msgid "Group name already exists!"
-#~ msgstr "Nazwa grupy już istnieje!"
-
#~ msgid "Add Image Group"
#~ msgstr "Dodaj grupę obrazków"
diff --git a/editor/translations/pr.po b/editor/translations/pr.po
index 9fbc17c9ca..6f42056ecf 100644
--- a/editor/translations/pr.po
+++ b/editor/translations/pr.po
@@ -1,5 +1,6 @@
# Pirate translation of the Godot Engine editor
-# Copyright (C) 2016-2017 Juan Linietsky, Ariel Manzur and the Godot community
+# Copyright (C) 2007-2017 Juan Linietsky, Ariel Manzur
+# Copyright (C) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)
# This file is distributed under the same license as the Godot source code.
#
# Zion Nimchuk <zionnimchuk@gmail.com>, 2016-2017.
@@ -191,10 +192,9 @@ msgid "Create %d NEW tracks and insert keys?"
msgstr ""
#: editor/animation_editor.cpp editor/create_dialog.cpp
-#: editor/editor_audio_buses.cpp
+#: editor/editor_audio_buses.cpp editor/plugins/abstract_polygon_2d_editor.cpp
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
#: editor/plugins/mesh_instance_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp editor/project_manager.cpp
#: editor/script_create_dialog.cpp
msgid "Create"
@@ -356,261 +356,6 @@ msgstr ""
msgid "Change Array Value"
msgstr ""
-#: editor/asset_library_editor_plugin.cpp
-msgid "Free"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_plugin_settings.cpp
-msgid "Version:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Contents:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "View Files"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_help.cpp editor/property_selector.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Description:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-#: editor/project_manager.cpp
-msgid "Install"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/call_dialog.cpp
-#: editor/connections_dialog.cpp editor/export_template_manager.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-#: editor/project_settings_editor.cpp editor/property_editor.cpp
-#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Close"
-msgstr "Close"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve hostname:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Connection error, please try again."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't connect."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't connect to host:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response from host:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Request failed, return code:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Req. Failed."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Request failed, too many redirects"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Redirect Loop."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Bad download hash, assuming file has been tampered with."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Expected:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Got:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Asset Download Error:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-msgid "Success!"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Fetching:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Resolving.."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Connecting.."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Requesting.."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Error making request"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Idle"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Retry"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Download Error"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Download for this asset is already in progress!"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "first"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "prev"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "next"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "last"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "All"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
-#: editor/settings_config_dialog.cpp
-msgid "Search:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/code_editor.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Search"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/project_manager.cpp
-msgid "Import"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Plugins"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Sort:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Reverse"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Category:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Site:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Support.."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Official"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-msgid "Community"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Testing"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Assets ZIP File"
-msgstr ""
-
-#: editor/call_dialog.cpp
-msgid "Method List For '%s':"
-msgstr ""
-
-#: editor/call_dialog.cpp modules/visual_script/visual_script_editor.cpp
-msgid "Call"
-msgstr "Call"
-
-#: editor/call_dialog.cpp
-msgid "Method List:"
-msgstr ""
-
-#: editor/call_dialog.cpp
-msgid "Arguments:"
-msgstr ""
-
-#: editor/call_dialog.cpp
-msgid "Return:"
-msgstr ""
-
#: editor/code_editor.cpp
msgid "Go to Line"
msgstr ""
@@ -647,6 +392,14 @@ msgstr ""
msgid "Selection Only"
msgstr ""
+#: editor/code_editor.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
+msgid "Search"
+msgstr ""
+
#: editor/code_editor.cpp editor/editor_help.cpp
msgid "Find"
msgstr ""
@@ -679,11 +432,11 @@ msgstr ""
msgid "Skip"
msgstr ""
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom In"
msgstr ""
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom Out"
msgstr ""
@@ -750,6 +503,20 @@ msgstr ""
msgid "Oneshot"
msgstr ""
+#: editor/connections_dialog.cpp editor/dependency_editor.cpp
+#: editor/export_template_manager.cpp
+#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Close"
+msgstr "Close"
+
#: editor/connections_dialog.cpp
msgid "Connect"
msgstr ""
@@ -775,7 +542,7 @@ msgstr ""
msgid "Disconnect"
msgstr ""
-#: editor/connections_dialog.cpp editor/node_dock.cpp
+#: editor/connections_dialog.cpp editor/editor_help.cpp editor/node_dock.cpp
msgid "Signals"
msgstr ""
@@ -792,12 +559,25 @@ msgstr ""
msgid "Recent:"
msgstr ""
+#: editor/create_dialog.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/quick_open.cpp editor/settings_config_dialog.cpp
+msgid "Search:"
+msgstr ""
+
#: editor/create_dialog.cpp editor/editor_help.cpp
#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/quick_open.cpp
msgid "Matches:"
msgstr ""
+#: editor/create_dialog.cpp editor/editor_help.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/property_selector.cpp
+#: editor/script_editor_debugger.cpp
+msgid "Description:"
+msgstr ""
+
#: editor/dependency_editor.cpp
msgid "Search Replacement For:"
msgstr ""
@@ -853,6 +633,10 @@ msgid "Owners Of:"
msgstr ""
#: editor/dependency_editor.cpp
+msgid "Remove selected files from the project? (no undo)"
+msgstr ""
+
+#: editor/dependency_editor.cpp
msgid ""
"The files being removed are required by other resources in order for them to "
"work.\n"
@@ -860,7 +644,7 @@ msgid ""
msgstr ""
#: editor/dependency_editor.cpp
-msgid "Remove selected files from the project? (no undo)"
+msgid "Cannot remove:\n"
msgstr ""
#: editor/dependency_editor.cpp
@@ -927,10 +711,6 @@ msgid "Godot Engine contributors"
msgstr ""
#: editor/editor_about.cpp
-msgid "Authors"
-msgstr ""
-
-#: editor/editor_about.cpp
msgid "Project Founders"
msgstr ""
@@ -947,6 +727,38 @@ msgid "Developers"
msgstr ""
#: editor/editor_about.cpp
+msgid "Authors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Platinum Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Gold Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Mini Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Gold Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Silver Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Bronze Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
msgid "License"
msgstr ""
@@ -987,6 +799,16 @@ msgid "Package Installed Successfully!"
msgstr ""
#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Success!"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/project_manager.cpp
+msgid "Install"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
msgid "Package Installer"
msgstr ""
@@ -1037,10 +859,6 @@ msgid "Audio Bus, Drag and Drop to rearrange."
msgstr ""
#: editor/editor_audio_buses.cpp
-msgid "Bus options"
-msgstr ""
-
-#: editor/editor_audio_buses.cpp
msgid "Solo"
msgstr ""
@@ -1052,12 +870,20 @@ msgstr ""
msgid "Bypass"
msgstr ""
+#: editor/editor_audio_buses.cpp
+msgid "Bus options"
+msgstr ""
+
#: editor/editor_audio_buses.cpp editor/plugins/tile_map_editor_plugin.cpp
#: editor/scene_tree_dock.cpp
msgid "Duplicate"
msgstr ""
#: editor/editor_audio_buses.cpp
+msgid "Reset Volume"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
#, fuzzy
msgid "Delete Effect"
msgstr "Yar, Blow th' Selected Down!"
@@ -1079,6 +905,10 @@ msgid "Duplicate Audio Bus"
msgstr ""
#: editor/editor_audio_buses.cpp
+msgid "Reset Bus Volume"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
msgid "Move Audio Bus"
msgstr ""
@@ -1110,7 +940,8 @@ msgstr ""
msgid "Create a new Bus Layout."
msgstr ""
-#: editor/editor_audio_buses.cpp editor/script_create_dialog.cpp
+#: editor/editor_audio_buses.cpp editor/property_editor.cpp
+#: editor/script_create_dialog.cpp
msgid "Load"
msgstr ""
@@ -1200,7 +1031,7 @@ msgid "Rearrange Autoloads"
msgstr ""
#: editor/editor_autoload_settings.cpp editor/editor_file_dialog.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp scene/gui/file_dialog.cpp
+#: scene/gui/file_dialog.cpp
msgid "Path:"
msgstr ""
@@ -1208,9 +1039,7 @@ msgstr ""
msgid "Node Name:"
msgstr ""
-#: editor/editor_autoload_settings.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp editor/project_manager.cpp
+#: editor/editor_autoload_settings.cpp editor/project_manager.cpp
msgid "Name"
msgstr ""
@@ -1243,18 +1072,19 @@ msgid "Choose a Directory"
msgstr ""
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Create Folder"
msgstr ""
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: editor/editor_plugin_settings.cpp editor/plugins/theme_editor_plugin.cpp
-#: editor/project_export.cpp scene/gui/file_dialog.cpp
+#: editor/editor_plugin_settings.cpp editor/filesystem_dock.cpp
+#: editor/plugins/theme_editor_plugin.cpp editor/project_export.cpp
+#: scene/gui/file_dialog.cpp
msgid "Name:"
msgstr ""
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Could not create folder."
msgstr ""
@@ -1274,30 +1104,6 @@ msgstr ""
msgid "Template file not found:\n"
msgstr ""
-#: editor/editor_export.cpp
-msgid "Added:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Removed:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Error saving atlas:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Could not save atlas subtexture:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Exporting for %s"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Setting Up.."
-msgstr ""
-
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "File Exists, Overwrite?"
msgstr ""
@@ -1382,6 +1188,10 @@ msgstr ""
msgid "Move Favorite Down"
msgstr ""
+#: editor/editor_file_dialog.cpp
+msgid "Go to parent folder"
+msgstr ""
+
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Directories & Files:"
msgstr ""
@@ -1396,10 +1206,6 @@ msgid "File:"
msgstr ""
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
-msgid "Filter:"
-msgstr ""
-
-#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Must use a valid extension."
msgstr ""
@@ -1424,6 +1230,10 @@ msgstr ""
msgid "Search Classes"
msgstr ""
+#: editor/editor_help.cpp editor/plugins/spatial_editor_plugin.cpp
+msgid "Top"
+msgstr ""
+
#: editor/editor_help.cpp editor/property_editor.cpp
msgid "Class:"
msgstr ""
@@ -1440,15 +1250,28 @@ msgstr ""
msgid "Brief Description:"
msgstr ""
+#: editor/editor_help.cpp
+#, fuzzy
+msgid "Members"
+msgstr "th' Members:"
+
#: editor/editor_help.cpp modules/visual_script/visual_script_editor.cpp
msgid "Members:"
msgstr "th' Members:"
#: editor/editor_help.cpp
+msgid "Public Methods"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Public Methods:"
msgstr ""
#: editor/editor_help.cpp
+msgid "GUI Theme Items"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "GUI Theme Items:"
msgstr ""
@@ -1458,6 +1281,11 @@ msgstr "Yer signals:"
#: editor/editor_help.cpp
#, fuzzy
+msgid "Enumerations"
+msgstr "Yer functions:"
+
+#: editor/editor_help.cpp
+#, fuzzy
msgid "Enumerations:"
msgstr "Yer functions:"
@@ -1466,18 +1294,46 @@ msgid "enum "
msgstr ""
#: editor/editor_help.cpp
+msgid "Constants"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Constants:"
msgstr ""
#: editor/editor_help.cpp
+msgid "Description"
+msgstr ""
+
+#: editor/editor_help.cpp
+msgid "Properties"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Property Description:"
msgstr ""
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this property. Please help us by "
+"[color=$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+
+#: editor/editor_help.cpp
+msgid "Methods"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Method Description:"
msgstr ""
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this method. Please help us by [color="
+"$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Search Text"
msgstr ""
@@ -1486,24 +1342,21 @@ msgid "Output:"
msgstr ""
#: editor/editor_log.cpp editor/plugins/animation_tree_editor_plugin.cpp
-#: editor/plugins/rich_text_editor_plugin.cpp editor/property_editor.cpp
-#: editor/script_editor_debugger.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/property_editor.cpp editor/script_editor_debugger.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Clear"
msgstr ""
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Error saving resource!"
msgstr ""
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Save Resource As.."
msgstr ""
-#: editor/editor_node.cpp editor/export_template_manager.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "I see.."
msgstr ""
@@ -1520,6 +1373,28 @@ msgid "Error while saving."
msgstr ""
#: editor/editor_node.cpp
+msgid "Can't open '%s'."
+msgstr ""
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Error while parsing '%s'."
+msgstr "Blimey! I can't make th' signature object!"
+
+#: editor/editor_node.cpp
+msgid "Unexpected end of file '%s'."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Missing '%s' or its dependencies."
+msgstr ""
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Error while loading '%s'."
+msgstr "Blimey! I can't make th' signature object!"
+
+#: editor/editor_node.cpp
msgid "Saving Scene"
msgstr ""
@@ -1577,6 +1452,33 @@ msgid "Restored default layout to base settings."
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was imported, so it's not editable.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was instanced or inherited.\n"
+"Changes to it will not be kept when saving the current scene."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource was imported, so it's not editable. Change its settings in the "
+"import panel and then re-import."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This scene was imported, so changes to it will not be kept.\n"
+"Instancing it or inheriting will allow making changes to it.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Copy Params"
msgstr ""
@@ -1738,23 +1640,34 @@ msgid "Save changes the following scene(s) before opening Project Manager?"
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"This option is deprecated. Situations where refresh must be forced are now "
+"considered a bug. Please report."
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Pick a Main Scene"
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to enable addon plugin at: '"
+msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr ""
#: editor/editor_node.cpp
-msgid "' parsing of config failed."
+msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/"
+msgid "Unable to load addon script from path: '%s'."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to load addon script from path: '"
+msgid ""
+"Unable to load addon script from path: '%s' Base type is not EditorPlugin."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Unable to load addon script from path: '%s' Script is not in tool mode."
msgstr ""
#: editor/editor_node.cpp
@@ -1764,7 +1677,7 @@ msgid ""
msgstr ""
#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/scene_tree_dock.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Ugh"
msgstr ""
@@ -1775,11 +1688,11 @@ msgid ""
msgstr ""
#: editor/editor_node.cpp
-msgid "Error loading scene."
+msgid "Scene '%s' has broken dependencies:"
msgstr ""
#: editor/editor_node.cpp
-msgid "Scene '%s' has broken dependencies:"
+msgid "Clear Recent Scenes"
msgstr ""
#: editor/editor_node.cpp
@@ -1815,7 +1728,7 @@ msgstr ""
msgid "Toggle distraction-free mode."
msgstr ""
-#: editor/editor_node.cpp editor/io_plugins/editor_scene_import_plugin.cpp
+#: editor/editor_node.cpp
msgid "Scene"
msgstr ""
@@ -2035,6 +1948,10 @@ msgstr ""
msgid "Issue Tracker"
msgstr ""
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+msgid "Community"
+msgstr ""
+
#: editor/editor_node.cpp
msgid "About"
msgstr ""
@@ -2043,7 +1960,7 @@ msgstr ""
msgid "Play the project."
msgstr ""
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Play"
msgstr ""
@@ -2059,7 +1976,7 @@ msgstr ""
msgid "Stop the scene."
msgstr ""
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Stop"
msgstr ""
@@ -2132,6 +2049,15 @@ msgid "Object properties."
msgstr ""
#: editor/editor_node.cpp
+msgid "Changes may be lost!"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Import"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "FileSystem"
msgstr ""
@@ -2147,14 +2073,6 @@ msgstr ""
msgid "Don't Save"
msgstr ""
-#: editor/editor_node.cpp editor/editor_reimport_dialog.cpp
-msgid "Re-Import"
-msgstr ""
-
-#: editor/editor_node.cpp editor/editor_plugin_settings.cpp
-msgid "Update"
-msgstr ""
-
#: editor/editor_node.cpp
msgid "Import Templates From ZIP File"
msgstr ""
@@ -2215,11 +2133,28 @@ msgstr ""
msgid "Open the previous Editor"
msgstr ""
+#: editor/editor_plugin.cpp
+msgid "Creating Mesh Previews"
+msgstr ""
+
+#: editor/editor_plugin.cpp
+msgid "Thumbnail.."
+msgstr ""
+
#: editor/editor_plugin_settings.cpp
msgid "Installed Plugins:"
msgstr ""
#: editor/editor_plugin_settings.cpp
+msgid "Update"
+msgstr ""
+
+#: editor/editor_plugin_settings.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Version:"
+msgstr ""
+
+#: editor/editor_plugin_settings.cpp
msgid "Author:"
msgstr ""
@@ -2252,7 +2187,7 @@ msgid "Frame %"
msgstr ""
#: editor/editor_profiler.cpp
-msgid "Fixed Frame %"
+msgid "Physics Frame %"
msgstr ""
#: editor/editor_profiler.cpp editor/script_editor_debugger.cpp
@@ -2271,26 +2206,6 @@ msgstr ""
msgid "Frame #:"
msgstr ""
-#: editor/editor_reimport_dialog.cpp
-msgid "Please wait for scan to complete."
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Current scene must be saved to re-import."
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Save & Re-Import"
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Importing"
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Import Changed Resources"
-msgstr ""
-
#: editor/editor_run_native.cpp
msgid "Select device from the list"
msgstr ""
@@ -2401,10 +2316,6 @@ msgid "Importing:"
msgstr ""
#: editor/export_template_manager.cpp
-msgid "Loading Export Templates"
-msgstr ""
-
-#: editor/export_template_manager.cpp
msgid "Current Version:"
msgstr ""
@@ -2438,9 +2349,17 @@ msgid "Cannot navigate to '"
msgstr ""
#: editor/filesystem_dock.cpp
+msgid "View items as a grid of thumbnails"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "View items as a list"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
msgid ""
"\n"
-"Status: Needs Re-Import"
+"Status: Import of file failed. Please fix file and reimport manually."
msgstr ""
#: editor/filesystem_dock.cpp
@@ -2450,87 +2369,88 @@ msgid ""
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Same source and destination files, doing nothing."
+msgid "Cannot move/rename resources root."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Target file exists, can't overwrite. Delete first."
+msgid "Cannot move a folder into itself.\n"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Same source and destination paths, doing nothing."
+msgid "Error moving:\n"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Can't move directories to within themselves."
+msgid "Unable to update dependencies:\n"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Can't rename deps for:\n"
+msgid "No name provided"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Error moving file:\n"
+msgid "Provided name contains invalid characters"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Error moving dir:\n"
+msgid "No name provided."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Can't operate on '..'"
+msgid "Name contains invalid characters."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Pick New Name and Location For:"
+msgid "A file or folder with this name already exists."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "No files selected!"
-msgstr ""
+#, fuzzy
+msgid "Renaming file:"
+msgstr "Rename Variable"
#: editor/filesystem_dock.cpp
-msgid "Expand all"
+msgid "Renaming folder:"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Collapse all"
+msgid "Expand all"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Show In File Manager"
+msgid "Collapse all"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Instance"
+msgid "Copy Path"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Edit Dependencies.."
+msgid "Rename.."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "View Owners.."
+msgid "Move To.."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Copy Path"
+msgid "New Folder.."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Rename or Move.."
+msgid "Show In File Manager"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Move To.."
+msgid "Instance"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Info"
+msgid "Edit Dependencies.."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Re-Import.."
+msgid "View Owners.."
msgstr ""
#: editor/filesystem_dock.cpp
@@ -2563,6 +2483,11 @@ msgstr ""
msgid "Move"
msgstr ""
+#: editor/filesystem_dock.cpp editor/plugins/animation_tree_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Rename"
+msgstr ""
+
#: editor/groups_editor.cpp
msgid "Add to Group"
msgstr ""
@@ -2576,6 +2501,10 @@ msgid "Import as Single Scene"
msgstr ""
#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
msgid "Import with Separate Materials"
msgstr ""
@@ -2588,6 +2517,18 @@ msgid "Import with Separate Objects+Materials"
msgstr ""
#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Materials+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Materials+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
msgid "Import as Multiple Scenes"
msgstr ""
@@ -2596,38 +2537,31 @@ msgid "Import as Multiple Scenes+Materials"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Import Scene"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Importing Scene.."
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Running Custom Script.."
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Couldn't load post-import script:"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Invalid/broken script for post-import (check console):"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Error running post-import script:"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Saving.."
msgstr ""
@@ -2655,579 +2589,54 @@ msgstr ""
msgid "Reimport"
msgstr ""
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "No bit masks to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path is empty."
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must be a complete resource path."
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must exist."
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Save path is empty!"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Import BitMasks"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s):"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Target Path:"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Accept"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Bit Mask"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No source font file!"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No target font resource!"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"Invalid file extension.\n"
-"Please use .font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Can't load/process source font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Couldn't save font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font Size:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Dest Resource:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "The quick brown fox jumps over the lazy dog."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Test:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Options:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Font Import"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"This file is already a Godot font file, please supply a BMFont type file "
-"instead."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Failed opening as BMFont file."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error initializing FreeType."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Unknown font format."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error loading font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Invalid font size."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Invalid font custom source."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/plugins/theme_editor_plugin.cpp
-msgid "Font"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "No meshes to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Single Mesh Import"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Source Mesh(es):"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/plugins/mesh_instance_editor_plugin.cpp
-msgid "Mesh"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Surface %d"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "No samples to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Import Audio Samples"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Source Sample(s):"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Audio Sample"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "New Clip"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Animation Options"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Flags"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Bake FPS:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Optimizer"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Linear Error"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angular Error"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angle"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Clips"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Start(s)"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "End(s)"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Loop"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Filters"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source path is empty."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't load post-import script."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Invalid/broken script for post-import."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Error importing scene."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import 3D Scene"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source Scene:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Same as Target Scene"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Shared"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Target Texture Folder:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Post-Process Script:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Custom Root Node Type:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Auto"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Root Node Name:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "The Following Files are Missing:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Anyway"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp scene/gui/dialogs.cpp
-msgid "Cancel"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import & Open"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Edited scene has not been saved, open imported scene anyway?"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Image:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Can't import a file over itself:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't localize path: %s (already local)"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "3D Scene Animation"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Uncompressed"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossless (PNG)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossy (WebP)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress (VRAM)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Format"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Compression Quality (WebP):"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Options"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Please specify some files!"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "At least one file needed for Atlas."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Error importing:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Only one file is required for large texture."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Max Texture Size:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for Atlas (2D)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cell Size:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Large Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Textures (2D)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture"
+#: editor/multi_node_edit.cpp
+msgid "MultiNode Set"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Base Atlas Texture"
+#: editor/node_dock.cpp
+msgid "Groups"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s)"
+#: editor/node_dock.cpp
+msgid "Select a Node to edit Signals and Groups."
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 2D"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create Poly"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 3D"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Insert Point"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "2D Texture"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly (Remove Point)"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "3D Texture"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Remove Poly And Point"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Atlas Texture"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create a new polygon from scratch."
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
+#: editor/plugins/abstract_polygon_2d_editor.cpp
msgid ""
-"NOTICE: Importing 2D textures is not mandatory. Just copy png/jpg files to "
-"the project."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Crop empty space."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Load Source Image"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Slicing"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Inserting"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Saving"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save large texture:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Build Atlas For:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Loading Image:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't load image:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Converting Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cropping Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Blitting Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save atlas image:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save converted texture:"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid source!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid translation source!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Column"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/script_create_dialog.cpp
-msgid "Language"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No items to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No target path!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translations"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Couldn't import!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translation"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Source CSV:"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Ignore First Row"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Compress"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Add to Project (project.godot)"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Languages:"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Translation"
-msgstr ""
-
-#: editor/multi_node_edit.cpp
-msgid "MultiNode Set"
-msgstr ""
-
-#: editor/node_dock.cpp
-msgid "Groups"
-msgstr ""
-
-#: editor/node_dock.cpp
-msgid "Select a Node to edit Signals and Groups."
+"Edit existing polygon:\n"
+"LMB: Move Point.\n"
+"Ctrl+LMB: Split Segment.\n"
+"RMB: Erase Point."
msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
@@ -3383,7 +2792,6 @@ msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
#: editor/script_create_dialog.cpp
msgid "Error!"
@@ -3494,10 +2902,6 @@ msgid "Delete Input"
msgstr ""
#: editor/plugins/animation_tree_editor_plugin.cpp
-msgid "Rename"
-msgstr ""
-
-#: editor/plugins/animation_tree_editor_plugin.cpp
msgid "Animation tree is valid."
msgstr ""
@@ -3553,64 +2957,181 @@ msgstr ""
msgid "Filters.."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing %d Triangles:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Free"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Triangle #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Contents:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Light Baker Setup:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "View Files"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing Geometry"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve hostname:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Fixing Lights"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Making BVH"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connection error, please try again."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Light Octree"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't connect."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Octree Texture"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't connect to host:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Transfer to Lightmaps:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response from host:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Allocating Texture #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Baking Triangle #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, return code:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Post-Processing Texture #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Req. Failed."
msgstr ""
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Bake!"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, too many redirects"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Redirect Loop."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Bad download hash, assuming file has been tampered with."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Expected:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Got:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed sha256 hash check"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Asset Download Error:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Fetching:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Resolving.."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connecting.."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Requesting.."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Error making request"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Idle"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Retry"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download Error"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download for this asset is already in progress!"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "first"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "prev"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "next"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "last"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "All"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Plugins"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Sort:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Reverse"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Category:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Site:"
msgstr ""
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Reset the lightmap octree baking process (start over)."
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Support.."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Official"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Testing"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Assets ZIP File"
msgstr ""
#: editor/plugins/camera_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
msgid "Preview"
msgstr ""
@@ -3653,11 +3174,15 @@ msgid "Edit CanvasItem"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Change Anchors"
+msgid "Anchors only"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Change Anchors and Margins"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom (%):"
+msgid "Change Anchors"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3708,59 +3233,73 @@ msgid "Pan Mode"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Lock the selected object in place (can't be moved)."
+#, fuzzy
+msgid "Toggles snapping"
+msgstr "Toggle ye Breakpoint"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Use Snap"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Unlock the selected object (can be moved)."
+msgid "Snapping options"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Makes sure the object's children are not selectable."
+msgid "Snap to grid"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Restores the object's children's ability to be selected."
+msgid "Use Rotation Snap"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Edit"
-msgstr "Edit"
+msgid "Configure Snap..."
+msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Use Snap"
+msgid "Snap Relative"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Show Grid"
+msgid "Use Pixel Snap"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Rotation Snap"
+msgid "Smart snapping"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap Relative"
+msgid "Snap to parent"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Configure Snap.."
+msgid "Snap to node anchor"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Pixel Snap"
+msgid "Snap to node sides"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Skeleton.."
+msgid "Snap to other nodes"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Lock the selected object in place (can't be moved)."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Unlock the selected object (can be moved)."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Makes sure the object's children are not selectable."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Restores the object's children's ability to be selected."
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3789,11 +3328,16 @@ msgid "View"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Reset"
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Show Grid"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Show helpers"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Set.."
+msgid "Show rulers"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3805,7 +3349,7 @@ msgid "Frame Selection"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Anchor"
+msgid "Layout"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3829,11 +3373,20 @@ msgid "Clear Pose"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Set a Value"
+msgid "Drag pivot from mouse position"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#, fuzzy
+msgid "Set pivot at mouse position"
+msgstr "Discharge ye' Signal"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Multiply grid step by 2"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap (Pixels):"
+msgid "Divide grid step by 2"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3844,23 +3397,28 @@ msgstr ""
msgid "Adding %s..."
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Create Node"
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Error instancing scene from %s"
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "OK :("
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "No parent to instance a child at."
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "This operation requires a single selected node."
msgstr ""
@@ -3874,45 +3432,6 @@ msgid ""
"Drag & drop + Alt : Change node type"
msgstr ""
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Create Poly"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly (Remove Point)"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Create a new polygon from scratch."
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-msgid ""
-"Edit existing polygon:\n"
-"LMB: Move Point.\n"
-"Ctrl+LMB: Split Segment.\n"
-"RMB: Erase Point."
-msgstr ""
-
#: editor/plugins/collision_polygon_editor_plugin.cpp
msgid "Create Poly3D"
msgstr ""
@@ -3922,14 +3441,6 @@ msgid "Set Handle"
msgstr ""
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Creating Mesh Library"
-msgstr ""
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Thumbnail.."
-msgstr ""
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Remove item %d?"
msgstr ""
@@ -3952,6 +3463,26 @@ msgid "Update from Scene"
msgstr ""
#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat0"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat1"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Ease in"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Ease out"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Smoothstep"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
msgid "Modify Curve Point"
msgstr ""
@@ -4030,22 +3561,18 @@ msgid "Create Occluder Polygon"
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Edit existing polygon:"
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "LMB: Move Point."
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Ctrl+LMB: Split Segment."
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "RMB: Erase Point."
msgstr ""
@@ -4146,6 +3673,10 @@ msgid "Create Outline"
msgstr ""
#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Mesh"
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Create Trimesh Static Body"
msgstr ""
@@ -4273,12 +3804,72 @@ msgstr ""
msgid "Populate"
msgstr ""
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Create Navigation Polygon"
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake!"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake the navigation mesh.\n"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Clear the navigation mesh."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Setting up Configuration..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Calculating grid size..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating heightfield..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Marking walkable triangles..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Constructing compact heightfield..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Eroding walkable area..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Partitioning..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating contours..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating polymesh..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Converting to native navigation mesh..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Navigation Mesh Generator Setup:"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Parsing Geometry..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Done!"
msgstr ""
#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Remove Poly And Point"
+msgid "Create Navigation Polygon"
msgstr ""
#: editor/plugins/particles_2d_editor_plugin.cpp
@@ -4452,16 +4043,19 @@ msgid "Curve Point #"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve Point Position"
-msgstr ""
+msgstr "Discharge ye' Signal"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve In Position"
-msgstr ""
+msgstr "Discharge ye' Signal"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve Out Position"
-msgstr ""
+msgstr "Discharge ye' Signal"
#: editor/plugins/path_editor_plugin.cpp
msgid "Split Path"
@@ -4521,6 +4115,14 @@ msgid "Scale Polygon"
msgstr ""
#: editor/plugins/polygon_2d_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Edit"
+msgstr "Edit"
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Polygon->UV"
msgstr ""
@@ -4575,63 +4177,10 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/shader_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr ""
-#: editor/plugins/rich_text_editor_plugin.cpp
-msgid "Parse BBCode"
-msgstr ""
-
-#: editor/plugins/sample_editor_plugin.cpp
-msgid "Length:"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Open Sample File(s)"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "ERROR: Couldn't load sample!"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Add Sample"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Rename Sample"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Delete Sample"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "16 Bits"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "8 Bits"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Stereo"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Mono"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Format"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Pitch"
-msgstr ""
-
#: editor/plugins/script_editor_plugin.cpp
msgid "Clear Recent Files"
msgstr ""
@@ -4722,6 +4271,10 @@ msgstr ""
msgid "Close All"
msgstr ""
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+msgid "Run"
+msgstr ""
+
#: editor/plugins/script_editor_plugin.cpp
msgid "Toggle Scripts Panel"
msgstr ""
@@ -4750,7 +4303,8 @@ msgstr ""
msgid "Break"
msgstr ""
-#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+#: editor/script_editor_debugger.cpp
msgid "Continue"
msgstr ""
@@ -4763,18 +4317,6 @@ msgid "Debug with external editor"
msgstr ""
#: editor/plugins/script_editor_plugin.cpp
-msgid "Window"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Left"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Right"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
msgid "Open Godot online documentation"
msgstr ""
@@ -4856,8 +4398,9 @@ msgid "Cut"
msgstr ""
#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr ""
@@ -5121,10 +4664,6 @@ msgid "View Plane Transform."
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Scaling to %s%%."
-msgstr ""
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rotating %s degrees."
msgstr ""
@@ -5141,10 +4680,6 @@ msgid "Top View."
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Top"
-msgstr ""
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rear View."
msgstr ""
@@ -5374,6 +4909,10 @@ msgid "Transform"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Configure Snap.."
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Local Coords"
msgstr ""
@@ -5519,6 +5058,10 @@ msgid "Speed (FPS):"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Loop"
+msgstr ""
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Animation Frames"
msgstr ""
@@ -5531,11 +5074,12 @@ msgid "Insert Empty (After)"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Up"
-msgstr ""
+#, fuzzy
+msgid "Move (Before)"
+msgstr "Forge yer Node!"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Down"
+msgid "Move (After)"
msgstr ""
#: editor/plugins/style_box_editor_plugin.cpp
@@ -5614,7 +5158,11 @@ msgid "Remove All"
msgstr "Discharge ye' Signal"
#: editor/plugins/theme_editor_plugin.cpp
-msgid "Theme"
+msgid "Edit theme.."
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Theme editing menu."
msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
@@ -5699,6 +5247,10 @@ msgid "Style"
msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
+msgid "Font"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
msgid "Color"
msgstr ""
@@ -5747,7 +5299,7 @@ msgid "Mirror Y"
msgstr ""
#: editor/plugins/tile_map_editor_plugin.cpp
-msgid "Bucket"
+msgid "Paint Tile"
msgstr ""
#: editor/plugins/tile_map_editor_plugin.cpp
@@ -5811,6 +5363,10 @@ msgid "Delete preset '%s'?"
msgstr ""
#: editor/project_export.cpp
+msgid "Export templates for this platform are missing/corrupted: "
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Presets"
msgstr ""
@@ -5881,19 +5437,29 @@ msgid "Export templates for this platform are missing:"
msgstr ""
#: editor/project_export.cpp
+msgid "Export templates for this platform are missing/corrupted:"
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Export With Debug"
msgstr ""
#: editor/project_manager.cpp
-msgid "Invalid project path, the path must exist!"
+msgid "The path does not exist."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Please choose a 'project.godot' file."
msgstr ""
#: editor/project_manager.cpp
-msgid "Invalid project path, project.godot must not exist."
+msgid ""
+"Your project will be created in a non empty folder (you might want to create "
+"a new folder)."
msgstr ""
#: editor/project_manager.cpp
-msgid "Invalid project path, project.godot must exist."
+msgid "Please choose a folder that does not contain a 'project.godot' file."
msgstr ""
#: editor/project_manager.cpp
@@ -5901,10 +5467,26 @@ msgid "Imported Project"
msgstr ""
#: editor/project_manager.cpp
+msgid " "
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "It would be a good idea to name your project."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Invalid project path (changed anything?)."
msgstr ""
#: editor/project_manager.cpp
+msgid "Couldn't get project.godot in project path."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Couldn't edit project.godot in project path."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
msgstr ""
@@ -5913,15 +5495,20 @@ msgid "The following files failed extraction from package:"
msgstr ""
#: editor/project_manager.cpp
-msgid "Import Existing Project"
+#, fuzzy
+msgid "Rename Project"
+msgstr "Rename Function"
+
+#: editor/project_manager.cpp
+msgid "Couldn't get project.godot in the project path."
msgstr ""
#: editor/project_manager.cpp
-msgid "Project Path (Must Exist):"
+msgid "New Game Project"
msgstr ""
#: editor/project_manager.cpp
-msgid "Project Name:"
+msgid "Import Existing Project"
msgstr ""
#: editor/project_manager.cpp
@@ -5929,19 +5516,23 @@ msgid "Create New Project"
msgstr ""
#: editor/project_manager.cpp
-msgid "Project Path:"
+msgid "Install Project:"
msgstr ""
#: editor/project_manager.cpp
-msgid "Install Project:"
+msgid "Project Name:"
msgstr ""
#: editor/project_manager.cpp
-msgid "Browse"
+msgid "Create folder"
msgstr ""
#: editor/project_manager.cpp
-msgid "New Game Project"
+msgid "Project Path:"
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Browse"
msgstr ""
#: editor/project_manager.cpp
@@ -5953,6 +5544,10 @@ msgid "Unnamed Project"
msgstr ""
#: editor/project_manager.cpp
+msgid "Can't open project"
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Are you sure to open more than one project?"
msgstr ""
@@ -5979,16 +5574,18 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
-"You are about the scan %s folders for existing Godot projects. Do you "
-"confirm?"
+"Language changed.\n"
+"The UI will update next time the editor or project manager starts."
msgstr ""
#: editor/project_manager.cpp
-msgid "Project List"
+msgid ""
+"You are about the scan %s folders for existing Godot projects. Do you "
+"confirm?"
msgstr ""
#: editor/project_manager.cpp
-msgid "Run"
+msgid "Project List"
msgstr ""
#: editor/project_manager.cpp
@@ -6013,6 +5610,10 @@ msgid "Exit"
msgstr ""
#: editor/project_manager.cpp
+msgid "Restart Now"
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Can't run project"
msgstr ""
@@ -6049,17 +5650,14 @@ msgid "Add Input Action Event"
msgstr ""
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Meta+"
msgstr ""
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Shift+"
msgstr ""
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Alt+"
msgstr ""
@@ -6120,7 +5718,7 @@ msgstr "Change"
msgid "Joypad Axis Index:"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Axis"
msgstr ""
@@ -6140,31 +5738,31 @@ msgstr ""
msgid "Add Event"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Device"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Button"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Left Button."
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Right Button."
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Middle Button."
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Up."
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Down."
msgstr ""
@@ -6174,7 +5772,7 @@ msgid "Add Global Property"
msgstr "Add yer Getter Property"
#: editor/project_settings_editor.cpp
-msgid "Select an setting item first!"
+msgid "Select a setting item first!"
msgstr ""
#: editor/project_settings_editor.cpp
@@ -6191,6 +5789,14 @@ msgid "Delete Item"
msgstr "Yar, Blow th' Selected Down!"
#: editor/project_settings_editor.cpp
+msgid "Can't contain '/' or ':'"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Already existing"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "Error saving settings."
msgstr ""
@@ -6231,6 +5837,14 @@ msgid "Remove Resource Remap Option"
msgstr ""
#: editor/project_settings_editor.cpp
+msgid "Changed Locale Filter"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Changed Locale Filter Mode"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "Project Settings (project.godot)"
msgstr ""
@@ -6291,6 +5905,27 @@ msgid "Locale"
msgstr ""
#: editor/project_settings_editor.cpp
+msgid "Locales Filter"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Show all locales"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Show only selected locales"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Filter mode:"
+msgstr "Paste yer Node"
+
+#: editor/project_settings_editor.cpp
+msgid "Locales:"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "AutoLoad"
msgstr ""
@@ -6340,10 +5975,18 @@ msgid "New Script"
msgstr ""
#: editor/property_editor.cpp
+msgid "Make Unique"
+msgstr ""
+
+#: editor/property_editor.cpp
msgid "Show in File System"
msgstr ""
#: editor/property_editor.cpp
+msgid "Convert To %s"
+msgstr ""
+
+#: editor/property_editor.cpp
msgid "Error loading file: Not a resource!"
msgstr ""
@@ -6381,6 +6024,10 @@ msgid "Select Property"
msgstr ""
#: editor/property_selector.cpp
+msgid "Select Virtual Method"
+msgstr ""
+
+#: editor/property_selector.cpp
msgid "Select Method"
msgstr ""
@@ -6408,26 +6055,6 @@ msgstr ""
msgid "Reparent"
msgstr ""
-#: editor/resources_dock.cpp
-msgid "Create New Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Open Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Save Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Resource Tools"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Make Local"
-msgstr ""
-
#: editor/run_settings_dialog.cpp
msgid "Run Mode:"
msgstr ""
@@ -6554,14 +6181,6 @@ msgid "Sub-Resources:"
msgstr ""
#: editor/scene_tree_dock.cpp
-msgid "Edit Groups"
-msgstr ""
-
-#: editor/scene_tree_dock.cpp
-msgid "Edit Connections"
-msgstr ""
-
-#: editor/scene_tree_dock.cpp
msgid "Clear Inheritance"
msgstr ""
@@ -6745,6 +6364,14 @@ msgid "Invalid base path"
msgstr ""
#: editor/script_create_dialog.cpp
+msgid "Directory of the same name exists"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
+msgid "File exists, will be reused"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
msgid "Invalid extension"
msgstr ""
@@ -6787,6 +6414,10 @@ msgid "Load existing script file"
msgstr ""
#: editor/script_create_dialog.cpp
+msgid "Language"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
msgid "Inherits"
msgstr ""
@@ -6828,6 +6459,10 @@ msgid "Function:"
msgstr ""
#: editor/script_editor_debugger.cpp
+msgid "Pick one or more items from the list to display the graph."
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
msgid "Errors"
msgstr ""
@@ -6908,6 +6543,10 @@ msgid "Type"
msgstr ""
#: editor/script_editor_debugger.cpp
+msgid "Format"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
msgid "Usage"
msgstr ""
@@ -6983,6 +6622,22 @@ msgstr ""
msgid "Change Probe Extents"
msgstr ""
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Library"
+msgstr ""
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Status"
+msgstr ""
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Libraries: "
+msgstr ""
+
+#: modules/gdnative/register_types.cpp
+msgid "GDNative"
+msgstr ""
+
#: modules/gdscript/gd_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Invalid type argument to convert(), use TYPE_* constants."
@@ -6990,7 +6645,7 @@ msgstr ""
"Shiver me timbers! ye type argument t' convert() be wrong! use yer TYPE_* "
"constants!"
-#: modules/gdscript/gd_functions.cpp
+#: modules/gdscript/gd_functions.cpp modules/mono/glue/glue_header.h
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Not enough bytes for decoding bytes, or invalid format."
msgstr "Nah enough bytes fer decodin' bytes, or ye got th' wrong ship."
@@ -7044,10 +6699,6 @@ msgid "GridMap Duplicate Selection"
msgstr ""
#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "GridMap Paint"
-msgstr ""
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Snap View"
msgstr ""
@@ -7139,12 +6790,8 @@ msgstr ""
msgid "Pick Distance:"
msgstr ""
-#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "Tiles"
-msgstr ""
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "Areas"
+#: modules/mono/editor/mono_bottom_panel.cpp
+msgid "Builds"
msgstr ""
#: modules/visual_script/visual_script.cpp
@@ -7354,10 +7001,18 @@ msgid "Return"
msgstr "Return"
#: modules/visual_script/visual_script_editor.cpp
+msgid "Call"
+msgstr "Call"
+
+#: modules/visual_script/visual_script_editor.cpp
msgid "Get"
msgstr "Get"
#: modules/visual_script/visual_script_editor.cpp
+msgid "Script already has function '%s'"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
msgid "Change Input Value"
msgstr ""
@@ -7716,6 +7371,12 @@ msgid ""
"order for AnimatedSprite3D to display frames."
msgstr ""
+#: scene/3d/vehicle_body.cpp
+msgid ""
+"VehicleWheel serves to provide a wheel system to a VehicleBody. Please use "
+"it as a child of a VehicleBody."
+msgstr ""
+
#: scene/gui/color_picker.cpp
msgid "Raw Mode"
msgstr ""
@@ -7725,15 +7386,15 @@ msgid "Add current color as a preset"
msgstr ""
#: scene/gui/dialogs.cpp
-msgid "Alert!"
+msgid "Cancel"
msgstr ""
#: scene/gui/dialogs.cpp
-msgid "Please Confirm..."
+msgid "Alert!"
msgstr ""
-#: scene/gui/input_action.cpp
-msgid "Ctrl+"
+#: scene/gui/dialogs.cpp
+msgid "Please Confirm..."
msgstr ""
#: scene/gui/popup.cpp
@@ -7764,6 +7425,22 @@ msgid ""
"texture to some node for display."
msgstr ""
+#: scene/resources/dynamic_font.cpp
+msgid "Error initializing FreeType."
+msgstr ""
+
+#: scene/resources/dynamic_font.cpp
+msgid "Unknown font format."
+msgstr ""
+
+#: scene/resources/dynamic_font.cpp
+msgid "Error loading font."
+msgstr ""
+
+#: scene/resources/dynamic_font.cpp
+msgid "Invalid font size."
+msgstr ""
+
#~ msgid "just pressed"
#~ msgstr "just smashed"
diff --git a/editor/translations/pt_BR.po b/editor/translations/pt_BR.po
index ed2bbb2fd3..490ad2accc 100644
--- a/editor/translations/pt_BR.po
+++ b/editor/translations/pt_BR.po
@@ -1,5 +1,6 @@
# Portuguese (Brazil) translation of the Godot Engine editor
-# Copyright (C) 2016-2017 Juan Linietsky, Ariel Manzur and the Godot community
+# Copyright (C) 2007-2017 Juan Linietsky, Ariel Manzur
+# Copyright (C) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)
# This file is distributed under the same license as the Godot source code.
#
# Allyson Souza <allyson_as@outlook.com>, 2017.
@@ -9,14 +10,15 @@
# Joaquim Ferreira <joaquimferreira1996@bol.com.br>, 2016.
# jonathan railarem <railarem@gmail.com>, 2017.
# Mailson Silva Marins <mailsons335@gmail.com>, 2016.
+# Marcus Correia <marknokalt@live.com>, 2017.
# Michael Alexsander Silva Dias <michael.a.s.dias@gmail.com>, 2017.
#
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: 2016-05-30\n"
-"PO-Revision-Date: 2017-08-15 19:47+0000\n"
-"Last-Translator: Michael Alexsander Silva Dias <michael.a.s.dias@gmail.com>\n"
+"PO-Revision-Date: 2017-10-22 02:54+0000\n"
+"Last-Translator: Marcus Correia <marknokalt@live.com>\n"
"Language-Team: Portuguese (Brazil) <https://hosted.weblate.org/projects/"
"godot-engine/godot/pt_BR/>\n"
"Language: pt_BR\n"
@@ -24,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 2.17-dev\n"
+"X-Generator: Weblate 2.17\n"
#: editor/animation_editor.cpp
msgid "Disabled"
@@ -91,9 +93,8 @@ msgid "Anim Track Change Value Mode"
msgstr "Mudar Modo de Valor da Trilha"
#: editor/animation_editor.cpp
-#, fuzzy
msgid "Anim Track Change Wrap Mode"
-msgstr "Mudar Modo de Valor da Trilha"
+msgstr "Mudar Modo de Cobertura da Trilha de Animação"
#: editor/animation_editor.cpp
msgid "Edit Node Curve"
@@ -201,10 +202,9 @@ msgid "Create %d NEW tracks and insert keys?"
msgstr "Criar %d NOVAS trilhas e inserir chaves?"
#: editor/animation_editor.cpp editor/create_dialog.cpp
-#: editor/editor_audio_buses.cpp
+#: editor/editor_audio_buses.cpp editor/plugins/abstract_polygon_2d_editor.cpp
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
#: editor/plugins/mesh_instance_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp editor/project_manager.cpp
#: editor/script_create_dialog.cpp
msgid "Create"
@@ -366,266 +366,6 @@ msgstr "Alterar Tipo de Valor do Vetor"
msgid "Change Array Value"
msgstr "Alterar Valor do Vetor"
-#: editor/asset_library_editor_plugin.cpp
-msgid "Free"
-msgstr "Livrar"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_plugin_settings.cpp
-msgid "Version:"
-msgstr "Versão:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Contents:"
-msgstr "Conteúdo:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "View Files"
-msgstr "Ver Arquivos"
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_help.cpp editor/property_selector.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Description:"
-msgstr "Descrição:"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-#: editor/project_manager.cpp
-msgid "Install"
-msgstr "Instalar"
-
-#: editor/asset_library_editor_plugin.cpp editor/call_dialog.cpp
-#: editor/connections_dialog.cpp editor/export_template_manager.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-#: editor/project_settings_editor.cpp editor/property_editor.cpp
-#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Close"
-msgstr "Fechar"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve hostname:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Connection error, please try again."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't connect."
-msgstr "Não é possível conectar..."
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Can't connect to host:"
-msgstr "Conectar ao Nó:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response from host:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response."
-msgstr "Sem resposta."
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Request failed, return code:"
-msgstr "Formato de arquivo requisitado desconhecido:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Req. Failed."
-msgstr "Sol. Falhou."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Request failed, too many redirects"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Redirect Loop."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed:"
-msgstr "Falhou:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Bad download hash, assuming file has been tampered with."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Expected:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Got:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Asset Download Error:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-msgid "Success!"
-msgstr "Sucesso!"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Fetching:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Resolving.."
-msgstr "Salvando..."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Connecting.."
-msgstr "Conectando..."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Requesting.."
-msgstr "Solicitando..."
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Error making request"
-msgstr "Erro ao salvar Recurso!"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Idle"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Retry"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Download Error"
-msgstr "Abaixo"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Download for this asset is already in progress!"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "first"
-msgstr "primeiro"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "prev"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "next"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "last"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "All"
-msgstr "Todos"
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
-#: editor/settings_config_dialog.cpp
-msgid "Search:"
-msgstr "Pesquisar:"
-
-#: editor/asset_library_editor_plugin.cpp editor/code_editor.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Search"
-msgstr "Pesquisar"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/project_manager.cpp
-msgid "Import"
-msgstr "Importar"
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Plugins"
-msgstr "Plugins"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Sort:"
-msgstr "Ordenar:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Reverse"
-msgstr "Reverso"
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Category:"
-msgstr "Categoria:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Site:"
-msgstr "Site:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Support.."
-msgstr "Suportado..."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Official"
-msgstr "Oficial"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-msgid "Community"
-msgstr "Comunidade"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Testing"
-msgstr "Em teste"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Assets ZIP File"
-msgstr "Arquivo ZIP de Assets"
-
-#: editor/call_dialog.cpp
-msgid "Method List For '%s':"
-msgstr "Lista de Métodos para \"%s\":"
-
-#: editor/call_dialog.cpp modules/visual_script/visual_script_editor.cpp
-msgid "Call"
-msgstr "Chamar"
-
-#: editor/call_dialog.cpp
-msgid "Method List:"
-msgstr "Lista de Métodos:"
-
-#: editor/call_dialog.cpp
-msgid "Arguments:"
-msgstr "Argumentos:"
-
-#: editor/call_dialog.cpp
-msgid "Return:"
-msgstr "Retornar:"
-
#: editor/code_editor.cpp
msgid "Go to Line"
msgstr "Ir para Linha"
@@ -639,7 +379,6 @@ msgid "No Matches"
msgstr "Sem Correspondências"
#: editor/code_editor.cpp
-#, fuzzy
msgid "Replaced %d occurrence(s)."
msgstr "%d ocorrência(s) substituída(s)."
@@ -663,6 +402,14 @@ msgstr "Palavras Inteiras"
msgid "Selection Only"
msgstr "Apenas na Seleção"
+#: editor/code_editor.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
+msgid "Search"
+msgstr "Pesquisar"
+
#: editor/code_editor.cpp editor/editor_help.cpp
msgid "Find"
msgstr "Localizar"
@@ -695,17 +442,17 @@ msgstr "Perguntar ao Substituir"
msgid "Skip"
msgstr "Pular"
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom In"
msgstr "Ampliar Mais"
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom Out"
msgstr "Ampliar Menos"
#: editor/code_editor.cpp
msgid "Reset Zoom"
-msgstr ""
+msgstr "Redefinir Ampliação"
#: editor/code_editor.cpp editor/script_editor_debugger.cpp
msgid "Line:"
@@ -724,6 +471,8 @@ msgid ""
"Target method not found! Specify a valid method or attach a script to target "
"Node."
msgstr ""
+"Método destino não encontrado! Específique um método válido ou anexe um "
+"script ao Nó destino."
#: editor/connections_dialog.cpp
msgid "Connect To Node:"
@@ -766,6 +515,20 @@ msgstr "Postergado"
msgid "Oneshot"
msgstr "Uma vez"
+#: editor/connections_dialog.cpp editor/dependency_editor.cpp
+#: editor/export_template_manager.cpp
+#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Close"
+msgstr "Fechar"
+
#: editor/connections_dialog.cpp
msgid "Connect"
msgstr "Conectar"
@@ -791,7 +554,7 @@ msgstr "Conectar..."
msgid "Disconnect"
msgstr "Disconectar"
-#: editor/connections_dialog.cpp editor/node_dock.cpp
+#: editor/connections_dialog.cpp editor/editor_help.cpp editor/node_dock.cpp
msgid "Signals"
msgstr "Sinais"
@@ -808,12 +571,25 @@ msgstr "Favoritos:"
msgid "Recent:"
msgstr "Recente:"
+#: editor/create_dialog.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/quick_open.cpp editor/settings_config_dialog.cpp
+msgid "Search:"
+msgstr "Pesquisar:"
+
#: editor/create_dialog.cpp editor/editor_help.cpp
#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/quick_open.cpp
msgid "Matches:"
msgstr "Combinações:"
+#: editor/create_dialog.cpp editor/editor_help.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/property_selector.cpp
+#: editor/script_editor_debugger.cpp
+msgid "Description:"
+msgstr "Descrição:"
+
#: editor/dependency_editor.cpp
msgid "Search Replacement For:"
msgstr "Buscar Substituição Para:"
@@ -873,6 +649,10 @@ msgid "Owners Of:"
msgstr "Donos De:"
#: editor/dependency_editor.cpp
+msgid "Remove selected files from the project? (no undo)"
+msgstr "Remover os arquivos selecionados do projeto? (impossível desfazer)"
+
+#: editor/dependency_editor.cpp
msgid ""
"The files being removed are required by other resources in order for them to "
"work.\n"
@@ -883,8 +663,8 @@ msgstr ""
"Removê-los mesmo assim? (irreversível)"
#: editor/dependency_editor.cpp
-msgid "Remove selected files from the project? (no undo)"
-msgstr "Remover os arquivos selecionados do projeto? (impossível desfazer)"
+msgid "Cannot remove:\n"
+msgstr "Não foi possível remover:\n"
#: editor/dependency_editor.cpp
msgid "Error loading:"
@@ -950,19 +730,12 @@ msgid "Godot Engine contributors"
msgstr "Contribuidores da Godot Engine"
#: editor/editor_about.cpp
-#, fuzzy
-msgid "Authors"
-msgstr "Autor:"
-
-#: editor/editor_about.cpp
-#, fuzzy
msgid "Project Founders"
-msgstr "Gerenciador de Projetos"
+msgstr "Fundadores do Projeto"
#: editor/editor_about.cpp
-#, fuzzy
msgid "Lead Developer"
-msgstr "Desenvolvedores"
+msgstr "Desenvolvedor-chefe"
#: editor/editor_about.cpp editor/project_manager.cpp
msgid "Project Manager"
@@ -973,12 +746,44 @@ msgid "Developers"
msgstr "Desenvolvedores"
#: editor/editor_about.cpp
+msgid "Authors"
+msgstr "Autores"
+
+#: editor/editor_about.cpp
+msgid "Platinum Sponsors"
+msgstr "Patrocinadores Platina"
+
+#: editor/editor_about.cpp
+msgid "Gold Sponsors"
+msgstr "Patrocinadores Ouro"
+
+#: editor/editor_about.cpp
+msgid "Mini Sponsors"
+msgstr "Patrocinadores Mini"
+
+#: editor/editor_about.cpp
+msgid "Gold Donors"
+msgstr "Doadores Ouro"
+
+#: editor/editor_about.cpp
+msgid "Silver Donors"
+msgstr "Doadores Prata"
+
+#: editor/editor_about.cpp
+msgid "Bronze Donors"
+msgstr "Doadores Bronze"
+
+#: editor/editor_about.cpp
+msgid "Donors"
+msgstr "Doadores"
+
+#: editor/editor_about.cpp
msgid "License"
-msgstr ""
+msgstr "LIcença"
#: editor/editor_about.cpp
msgid "Thirdparty License"
-msgstr ""
+msgstr "Licença de Terceiros"
#: editor/editor_about.cpp
msgid ""
@@ -987,103 +792,108 @@ msgid ""
"is an exhaustive list of all such thirdparty components with their "
"respective copyright statements and license terms."
msgstr ""
+"A Godot Engine conta com várias bibliotecas de código aberto e gratuitas de "
+"terceiros, todas compatíveis com os termos de sua licença MIT. O seguinte é "
+"uma lista exaustiva de todos esses componentes de terceiros com suas "
+"respectivas declarações de direitos autorais e termos de licença."
#: editor/editor_about.cpp
-#, fuzzy
msgid "All Components"
-msgstr "Conteúdo:"
+msgstr "Todos os Componentes"
#: editor/editor_about.cpp
-#, fuzzy
msgid "Components"
-msgstr "Conteúdo:"
+msgstr "Componentes"
#: editor/editor_about.cpp
msgid "Licenses"
-msgstr ""
+msgstr "Licenças"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Error opening package file, not in zip format."
-msgstr ""
+msgstr "Erro ao abrir arquivo de pacote, não está em formato zip."
#: editor/editor_asset_installer.cpp
-#, fuzzy
msgid "Uncompressing Assets"
-msgstr "Não comprimido"
+msgstr "Descompactando Assets"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package Installed Successfully!"
msgstr "Pacote Instalado com Sucesso!"
#: editor/editor_asset_installer.cpp
-#, fuzzy
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Success!"
+msgstr "Sucesso!"
+
+#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/project_manager.cpp
+msgid "Install"
+msgstr "Instalar"
+
+#: editor/editor_asset_installer.cpp
msgid "Package Installer"
-msgstr "Pacote Instalado com Sucesso!"
+msgstr "Instalador de Pacotes"
#: editor/editor_audio_buses.cpp
msgid "Speakers"
-msgstr ""
+msgstr "Caixas de Som"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Add Effect"
-msgstr "Adicionar Vazio"
+msgstr "Ad. Efeito"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Rename Audio Bus"
-msgstr "Renomear Autoload"
+msgstr "Renomear Canal de Ãudio"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Toggle Audio Bus Solo"
-msgstr "Alternar Inicio automático"
+msgstr "Alternar Solo do Canal de Ãudio"
#: editor/editor_audio_buses.cpp
msgid "Toggle Audio Bus Mute"
-msgstr ""
+msgstr "Alternar Silenciamento do Canal de Ãudio"
#: editor/editor_audio_buses.cpp
msgid "Toggle Audio Bus Bypass Effects"
-msgstr ""
+msgstr "Alternar Efeitos de Desvio do Canal de Ãudio"
#: editor/editor_audio_buses.cpp
msgid "Select Audio Bus Send"
-msgstr ""
+msgstr "Selecionar Canal de Ãudio para Envio"
#: editor/editor_audio_buses.cpp
msgid "Add Audio Bus Effect"
-msgstr ""
+msgstr "Adicionar Efeito ao Canal de Ãudio"
#: editor/editor_audio_buses.cpp
msgid "Move Bus Effect"
-msgstr ""
+msgstr "Mover Efeito de Canal"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Delete Bus Effect"
-msgstr "Excluir Selecionados"
+msgstr "Excluir Efeito de Canal"
#: editor/editor_audio_buses.cpp
msgid "Audio Bus, Drag and Drop to rearrange."
-msgstr ""
-
-#: editor/editor_audio_buses.cpp
-#, fuzzy
-msgid "Bus options"
-msgstr "Opções de depuração"
+msgstr "Pista de Ãudio, arraste e solte para reorganizar."
#: editor/editor_audio_buses.cpp
msgid "Solo"
-msgstr ""
+msgstr "Solo"
#: editor/editor_audio_buses.cpp
msgid "Mute"
-msgstr ""
+msgstr "Silenciar"
#: editor/editor_audio_buses.cpp
msgid "Bypass"
-msgstr ""
+msgstr "Ignorar"
+
+#: editor/editor_audio_buses.cpp
+msgid "Bus options"
+msgstr "Opções da pista"
#: editor/editor_audio_buses.cpp editor/plugins/tile_map_editor_plugin.cpp
#: editor/scene_tree_dock.cpp
@@ -1091,75 +901,73 @@ msgid "Duplicate"
msgstr "Duplicar"
#: editor/editor_audio_buses.cpp
-#, fuzzy
+msgid "Reset Volume"
+msgstr "Redefinir Volume"
+
+#: editor/editor_audio_buses.cpp
msgid "Delete Effect"
-msgstr "Excluir Selecionados"
+msgstr "Excluir Efeito"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Add Audio Bus"
-msgstr "Adicionar Todos"
+msgstr "Adicionar Canal de Ãudio"
#: editor/editor_audio_buses.cpp
msgid "Master bus can't be deleted!"
-msgstr ""
+msgstr "Pista mestre não pode ser deletada!"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Delete Audio Bus"
-msgstr "Excluir Layout"
+msgstr "Excluir Canal de Ãudio"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Duplicate Audio Bus"
-msgstr "Duplicar Animação"
+msgstr "Duplicar Canal de Ãudio"
+
+#: editor/editor_audio_buses.cpp
+msgid "Reset Bus Volume"
+msgstr "Redefinir Volume do Canal"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Move Audio Bus"
-msgstr "Ação de Mover"
+msgstr "Mover Canal de Ãudio"
#: editor/editor_audio_buses.cpp
msgid "Save Audio Bus Layout As.."
-msgstr ""
+msgstr "Salvar Layout de Canais de Ãudio Como..."
#: editor/editor_audio_buses.cpp
msgid "Location for New Layout.."
-msgstr ""
+msgstr "Localização para o Novo Layout.."
#: editor/editor_audio_buses.cpp
msgid "Open Audio Bus Layout"
-msgstr ""
+msgstr "Abrir Layout de Canais de Ãudio"
#: editor/editor_audio_buses.cpp
msgid "There is no 'res://default_bus_layout.tres' file."
-msgstr ""
+msgstr "Não há nenhum arquivo 'res://default_bus_layout.tres'."
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Invalid file, not an audio bus layout."
-msgstr ""
-"Extensão de arquivo inválida.\n"
-"Por favor use .font."
+msgstr "Arquivo inválido, não é um layout de canais de áudio."
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Add Bus"
-msgstr "Adicionar Todos"
+msgstr "Adicionar Canal"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Create a new Bus Layout."
-msgstr "Criar Novo Recurso"
+msgstr "Criar um novo Layout de Canais."
-#: editor/editor_audio_buses.cpp editor/script_create_dialog.cpp
+#: editor/editor_audio_buses.cpp editor/property_editor.cpp
+#: editor/script_create_dialog.cpp
msgid "Load"
msgstr "Carregar"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Load an existing Bus Layout."
-msgstr "Carrega um recurso existente do disco e o edita."
+msgstr "Carregar um Layout de Canais existente."
#: editor/editor_audio_buses.cpp
#: editor/plugins/animation_player_editor_plugin.cpp
@@ -1168,16 +976,15 @@ msgstr "Salvar Como"
#: editor/editor_audio_buses.cpp
msgid "Save this Bus Layout to a file."
-msgstr ""
+msgstr "Salvar este Layout de Canais em um arquivo."
#: editor/editor_audio_buses.cpp editor/import_dock.cpp
-#, fuzzy
msgid "Load Default"
-msgstr "Padrão"
+msgstr "Carregar Padrão"
#: editor/editor_audio_buses.cpp
msgid "Load the default Bus Layout."
-msgstr ""
+msgstr "Carregar o Layout de Canais padrão."
#: editor/editor_autoload_settings.cpp
msgid "Invalid name."
@@ -1247,7 +1054,7 @@ msgid "Rearrange Autoloads"
msgstr "Reordenar Autoloads"
#: editor/editor_autoload_settings.cpp editor/editor_file_dialog.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp scene/gui/file_dialog.cpp
+#: scene/gui/file_dialog.cpp
msgid "Path:"
msgstr "Caminho:"
@@ -1255,9 +1062,7 @@ msgstr "Caminho:"
msgid "Node Name:"
msgstr "Nome do Nó:"
-#: editor/editor_autoload_settings.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp editor/project_manager.cpp
+#: editor/editor_autoload_settings.cpp editor/project_manager.cpp
msgid "Name"
msgstr "Nome"
@@ -1282,27 +1087,27 @@ msgid "Updating scene.."
msgstr "Atualizando Cena..."
#: editor/editor_dir_dialog.cpp
-#, fuzzy
msgid "Please select a base directory first"
-msgstr "Por favor salve a cena primeiro."
+msgstr "Por favor selecione um diretório base primeiro"
#: editor/editor_dir_dialog.cpp
msgid "Choose a Directory"
msgstr "Escolha um Diretório"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Create Folder"
msgstr "Criar Pasta"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: editor/editor_plugin_settings.cpp editor/plugins/theme_editor_plugin.cpp
-#: editor/project_export.cpp scene/gui/file_dialog.cpp
+#: editor/editor_plugin_settings.cpp editor/filesystem_dock.cpp
+#: editor/plugins/theme_editor_plugin.cpp editor/project_export.cpp
+#: scene/gui/file_dialog.cpp
msgid "Name:"
msgstr "Nome:"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Could not create folder."
msgstr "Não foi possível criar a pasta."
@@ -1322,30 +1127,6 @@ msgstr "Empacotando"
msgid "Template file not found:\n"
msgstr "Arquivo de modelo não encontrado:\n"
-#: editor/editor_export.cpp
-msgid "Added:"
-msgstr "Adicionado:"
-
-#: editor/editor_export.cpp
-msgid "Removed:"
-msgstr "Removido:"
-
-#: editor/editor_export.cpp
-msgid "Error saving atlas:"
-msgstr "Erro ao salvar atlas:"
-
-#: editor/editor_export.cpp
-msgid "Could not save atlas subtexture:"
-msgstr "Não foi possível salvar Subtextura do Atlas:"
-
-#: editor/editor_export.cpp
-msgid "Exporting for %s"
-msgstr "Exportando para %s"
-
-#: editor/editor_export.cpp
-msgid "Setting Up.."
-msgstr "Ajustando..."
-
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "File Exists, Overwrite?"
msgstr "O arquivo existe. Sobrescrever?"
@@ -1430,6 +1211,10 @@ msgstr "Mover Favorito Acima"
msgid "Move Favorite Down"
msgstr "Mover Favorito Abaixo"
+#: editor/editor_file_dialog.cpp
+msgid "Go to parent folder"
+msgstr "Ir para pasta pai"
+
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Directories & Files:"
msgstr "Diretórios & Arquivos:"
@@ -1444,10 +1229,6 @@ msgid "File:"
msgstr "Arquivo:"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
-msgid "Filter:"
-msgstr "Filtro:"
-
-#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Must use a valid extension."
msgstr "Deve usar uma extensão válida."
@@ -1456,9 +1237,8 @@ msgid "ScanSources"
msgstr "BuscarFontes"
#: editor/editor_file_system.cpp
-#, fuzzy
msgid "(Re)Importing Assets"
-msgstr "Re-Importando"
+msgstr "(Re)Importando Assets"
#: editor/editor_help.cpp editor/editor_node.cpp
#: editor/plugins/script_editor_plugin.cpp
@@ -1473,6 +1253,10 @@ msgstr "Lista de Classes:"
msgid "Search Classes"
msgstr "Pesquisar Classes"
+#: editor/editor_help.cpp editor/plugins/spatial_editor_plugin.cpp
+msgid "Top"
+msgstr "Cima"
+
#: editor/editor_help.cpp editor/property_editor.cpp
msgid "Class:"
msgstr "Classe:"
@@ -1489,15 +1273,27 @@ msgstr "Herdado por:"
msgid "Brief Description:"
msgstr "Descrição breve:"
+#: editor/editor_help.cpp
+msgid "Members"
+msgstr "Membros"
+
#: editor/editor_help.cpp modules/visual_script/visual_script_editor.cpp
msgid "Members:"
msgstr "Membros:"
#: editor/editor_help.cpp
+msgid "Public Methods"
+msgstr "Métodos Públicos"
+
+#: editor/editor_help.cpp
msgid "Public Methods:"
msgstr "Métodos Públicos:"
#: editor/editor_help.cpp
+msgid "GUI Theme Items"
+msgstr "Itens do Tema de GUI"
+
+#: editor/editor_help.cpp
msgid "GUI Theme Items:"
msgstr "Itens do Tema de GUI:"
@@ -1506,54 +1302,85 @@ msgid "Signals:"
msgstr "Sinais:"
#: editor/editor_help.cpp
-#, fuzzy
+msgid "Enumerations"
+msgstr "Enumerações"
+
+#: editor/editor_help.cpp
msgid "Enumerations:"
-msgstr "Animações"
+msgstr "Enumerações:"
#: editor/editor_help.cpp
msgid "enum "
-msgstr ""
+msgstr "enum "
+
+#: editor/editor_help.cpp
+msgid "Constants"
+msgstr "Constantes"
#: editor/editor_help.cpp
msgid "Constants:"
msgstr "Constantes:"
#: editor/editor_help.cpp
+msgid "Description"
+msgstr "Descrição"
+
+#: editor/editor_help.cpp
+msgid "Properties"
+msgstr "Propriedades"
+
+#: editor/editor_help.cpp
msgid "Property Description:"
msgstr "Descrição da Propriedade:"
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this property. Please help us by "
+"[color=$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+"Atualmente não existe descrição para esta propriedade. Por favor nos ajude "
+"[color=$color][url=$url]contribuindo uma[/url][/color]!"
+
+#: editor/editor_help.cpp
+msgid "Methods"
+msgstr "Métodos"
+
+#: editor/editor_help.cpp
msgid "Method Description:"
msgstr "Descrição do Método:"
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this method. Please help us by [color="
+"$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+"Atualmente não existe descrição para este método. Por favor nos ajude [color="
+"$color][url=$url]contribuindo uma[/url][/color]!"
+
+#: editor/editor_help.cpp
msgid "Search Text"
msgstr "Pesquisar Texto"
#: editor/editor_log.cpp
-#, fuzzy
msgid "Output:"
-msgstr " Saída:"
+msgstr "Saída:"
#: editor/editor_log.cpp editor/plugins/animation_tree_editor_plugin.cpp
-#: editor/plugins/rich_text_editor_plugin.cpp editor/property_editor.cpp
-#: editor/script_editor_debugger.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/property_editor.cpp editor/script_editor_debugger.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Clear"
msgstr "Limpar"
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Error saving resource!"
msgstr "Erro ao salvar Recurso!"
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Save Resource As.."
msgstr "Salvar Recuso como..."
-#: editor/editor_node.cpp editor/export_template_manager.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "I see.."
msgstr "Entendo..."
@@ -1570,6 +1397,26 @@ msgid "Error while saving."
msgstr "Erro ao salvar."
#: editor/editor_node.cpp
+msgid "Can't open '%s'."
+msgstr "Não é possível abrir '%s'."
+
+#: editor/editor_node.cpp
+msgid "Error while parsing '%s'."
+msgstr "Erro ao processar '%s'."
+
+#: editor/editor_node.cpp
+msgid "Unexpected end of file '%s'."
+msgstr "Final inesperado do arquivo '%s'."
+
+#: editor/editor_node.cpp
+msgid "Missing '%s' or its dependencies."
+msgstr "Falta '%s' ou suas dependências."
+
+#: editor/editor_node.cpp
+msgid "Error while loading '%s'."
+msgstr "Erro ao carregar '%s'."
+
+#: editor/editor_node.cpp
msgid "Saving Scene"
msgstr "Salvando Cena"
@@ -1582,9 +1429,8 @@ msgid "Creating Thumbnail"
msgstr "Criando Miniatura"
#: editor/editor_node.cpp
-#, fuzzy
msgid "This operation can't be done without a tree root."
-msgstr "Essa operação não pode ser realizada sem uma cena."
+msgstr "Essa operação não pode ser realizada sem uma raiz da cena."
#: editor/editor_node.cpp
msgid ""
@@ -1630,6 +1476,44 @@ msgid "Restored default layout to base settings."
msgstr "Layout padrão restaurado às configurações base."
#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was imported, so it's not editable.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+"Este recurso pertence a uma cena que foi importada, mas não é editável.\n"
+"Por favor, leia a documentação referente a importação de cenas para entender "
+"melhor esse procedimento."
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was instanced or inherited.\n"
+"Changes to it will not be kept when saving the current scene."
+msgstr ""
+"Este recurso pertence a uma cena que foi instanciada ou herdada.\n"
+"Mudanças nele não serão mantidas ao salvar a cena atual."
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource was imported, so it's not editable. Change its settings in the "
+"import panel and then re-import."
+msgstr ""
+"Este recurso foi importado, então não é editável. Mude suas configurações no "
+"painel de importação e então re-importe."
+
+#: editor/editor_node.cpp
+msgid ""
+"This scene was imported, so changes to it will not be kept.\n"
+"Instancing it or inheriting will allow making changes to it.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+"Essa cena foi importada, então mudanças nela não irão ser mantidas.\n"
+"Instanciar ou herdar a cena permitirá fazer mudanças a ela.\n"
+"Por favor, leia a documentação referente a importação de cenas para entender "
+"melhor esse procedimento."
+
+#: editor/editor_node.cpp
msgid "Copy Params"
msgstr "Copiar Parâmetros"
@@ -1662,15 +1546,14 @@ msgid "There is no defined scene to run."
msgstr "Não há cena definida para rodar."
#: editor/editor_node.cpp
-#, fuzzy
msgid ""
"No main scene has ever been defined, select one?\n"
"You can change it later in \"Project Settings\" under the 'application' "
"category."
msgstr ""
"A cena principal não foi definida, selecionar uma?\n"
-"Você pode alterá-la mais tarde nas \"Configurações do Projeto\" na categoria "
-"\"application\"."
+"Você pode alterá-la mais tarde nas \"Configurações do Projeto\" na "
+"categoria 'Application'."
#: editor/editor_node.cpp
msgid ""
@@ -1714,16 +1597,15 @@ msgstr "Abri Cena Ãgil..."
#: editor/editor_node.cpp
msgid "Quick Open Script.."
-msgstr "Abrir Script Ãgil..."
+msgstr "Abrir Rápidamente Script.."
#: editor/editor_node.cpp
-#, fuzzy
msgid "Save & Close"
-msgstr "Salvar um Arquivo"
+msgstr "Salvar e Fechar"
#: editor/editor_node.cpp
msgid "Save changes to '%s' before closing?"
-msgstr ""
+msgstr "Salvar mudanças em '%s' antes de fechar?"
#: editor/editor_node.cpp
msgid "Save Scene As.."
@@ -1754,9 +1636,8 @@ msgid "Export Tile Set"
msgstr "Exportar Tile Set"
#: editor/editor_node.cpp
-#, fuzzy
msgid "This operation can't be done without a selected node."
-msgstr "Essa operação não pode ser realizada sem uma cena."
+msgstr "Esta operação não pode ser feita sem um nó selecionado."
#: editor/editor_node.cpp
msgid "Current scene not saved. Open anyway?"
@@ -1787,42 +1668,61 @@ msgid "Exit the editor?"
msgstr "Sair do editor?"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Open Project Manager?"
-msgstr "Gerenciador de Projetos"
+msgstr "Abrir Gerenciador de Projetos?"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Save & Quit"
-msgstr "Salvar um Arquivo"
+msgstr "Salvar e Sair"
#: editor/editor_node.cpp
msgid "Save changes to the following scene(s) before quitting?"
-msgstr ""
+msgstr "Salvar mudanças na(s) seguinte(s) cena(s) antes de sair?"
#: editor/editor_node.cpp
msgid "Save changes the following scene(s) before opening Project Manager?"
msgstr ""
+"Salvar mudanças na(s) seguinte(s) cena(s) antes de abrir o Gerenciador de "
+"Projetos?"
+
+#: editor/editor_node.cpp
+msgid ""
+"This option is deprecated. Situations where refresh must be forced are now "
+"considered a bug. Please report."
+msgstr ""
+"Esta opção está descontinuada. Situações em que a atualização precisa ser "
+"forçada são consideradas um bug agora. Reporte por favor."
#: editor/editor_node.cpp
msgid "Pick a Main Scene"
msgstr "Escolha uma Cena Principal"
#: editor/editor_node.cpp
-msgid "Unable to enable addon plugin at: '"
-msgstr ""
+#, fuzzy
+msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
+msgstr "Não foi possível ativar o plugin em: '"
#: editor/editor_node.cpp
-msgid "' parsing of config failed."
+#, fuzzy
+msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
msgstr ""
+"Não foi possível encontrar o campo de script para o plugin em: 'res://addons/"
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/"
-msgstr ""
+#, fuzzy
+msgid "Unable to load addon script from path: '%s'."
+msgstr "Não foi possível carregar o script de extensão no caminho: '"
#: editor/editor_node.cpp
-msgid "Unable to load addon script from path: '"
-msgstr ""
+#, fuzzy
+msgid ""
+"Unable to load addon script from path: '%s' Base type is not EditorPlugin."
+msgstr "Não foi possível carregar o script de extensão no caminho: '"
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Unable to load addon script from path: '%s' Script is not in tool mode."
+msgstr "Não foi possível carregar o script de extensão no caminho: '"
#: editor/editor_node.cpp
msgid ""
@@ -1833,7 +1733,7 @@ msgstr ""
"Para fazer alterações, uma nova cena herdada pode ser criada."
#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/scene_tree_dock.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Ugh"
msgstr "Ugh"
@@ -1846,14 +1746,14 @@ msgstr ""
"\"Importar\" para abrir a cena e então salve-a dentro do projeto."
#: editor/editor_node.cpp
-msgid "Error loading scene."
-msgstr "Erro ao carregar cena."
-
-#: editor/editor_node.cpp
msgid "Scene '%s' has broken dependencies:"
msgstr "A cena \"%s\" tem dependências quebradas:"
#: editor/editor_node.cpp
+msgid "Clear Recent Scenes"
+msgstr "Limpar Cenas Recentes"
+
+#: editor/editor_node.cpp
msgid "Save Layout"
msgstr "Salvar Layout"
@@ -1883,11 +1783,10 @@ msgid "Distraction Free Mode"
msgstr "Modo Sem Distrações"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Toggle distraction-free mode."
-msgstr "Modo Sem Distrações"
+msgstr "Alternar modo sem-distrações."
-#: editor/editor_node.cpp editor/io_plugins/editor_scene_import_plugin.cpp
+#: editor/editor_node.cpp
msgid "Scene"
msgstr "Cena"
@@ -2098,9 +1997,8 @@ msgid "Editor Layout"
msgstr "Layout do Editor"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Toggle Fullscreen"
-msgstr "Modo Tela-Cheia"
+msgstr "Alternar Tela-Cheia"
#: editor/editor_node.cpp editor/project_export.cpp
msgid "Manage Export Templates"
@@ -2120,11 +2018,15 @@ msgstr "Docs Online"
#: editor/editor_node.cpp
msgid "Q&A"
-msgstr ""
+msgstr "Perguntas e Respostas"
#: editor/editor_node.cpp
msgid "Issue Tracker"
-msgstr ""
+msgstr "Rastreador de Problemas"
+
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+msgid "Community"
+msgstr "Comunidade"
#: editor/editor_node.cpp
msgid "About"
@@ -2134,7 +2036,7 @@ msgstr "Sobre"
msgid "Play the project."
msgstr "Roda o projeto."
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Play"
msgstr "Tocar"
@@ -2150,7 +2052,7 @@ msgstr "Pausa a cena"
msgid "Stop the scene."
msgstr "Para a cena."
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Stop"
msgstr "Parar"
@@ -2184,7 +2086,7 @@ msgstr "Atualizar nas Mudanças"
#: editor/editor_node.cpp
msgid "Disable Update Spinner"
-msgstr ""
+msgstr "Desabilitar Spinner de Atualização"
#: editor/editor_node.cpp
msgid "Inspector"
@@ -2223,6 +2125,15 @@ msgid "Object properties."
msgstr "Propriedades do objeto."
#: editor/editor_node.cpp
+msgid "Changes may be lost!"
+msgstr "Mudanças podem ser perdidas!"
+
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Import"
+msgstr "Importar"
+
+#: editor/editor_node.cpp
msgid "FileSystem"
msgstr "Arquivos"
@@ -2236,15 +2147,7 @@ msgstr "Saída"
#: editor/editor_node.cpp
msgid "Don't Save"
-msgstr ""
-
-#: editor/editor_node.cpp editor/editor_reimport_dialog.cpp
-msgid "Re-Import"
-msgstr "Reimportar"
-
-#: editor/editor_node.cpp editor/editor_plugin_settings.cpp
-msgid "Update"
-msgstr "Atualizar"
+msgstr "Não Salvar"
#: editor/editor_node.cpp
msgid "Import Templates From ZIP File"
@@ -2271,9 +2174,8 @@ msgid "Open & Run a Script"
msgstr "Abrir e Rodar um Script"
#: editor/editor_node.cpp
-#, fuzzy
msgid "New Inherited"
-msgstr "Nova Cena Herdada..."
+msgstr "Novo Herdado"
#: editor/editor_node.cpp
msgid "Load Errors"
@@ -2296,9 +2198,8 @@ msgid "Open Script Editor"
msgstr "Abrir Editor de Scripts"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Open Asset Library"
-msgstr "Exportar Biblioteca"
+msgstr "Abrir Biblioteca de Assets"
#: editor/editor_node.cpp
msgid "Open the next Editor"
@@ -2308,11 +2209,28 @@ msgstr "Abrir o próximo Editor"
msgid "Open the previous Editor"
msgstr "Abrir o Editor anterior"
+#: editor/editor_plugin.cpp
+msgid "Creating Mesh Previews"
+msgstr "Criando Previsualizações de Malha"
+
+#: editor/editor_plugin.cpp
+msgid "Thumbnail.."
+msgstr "Miniatura..."
+
#: editor/editor_plugin_settings.cpp
msgid "Installed Plugins:"
msgstr "Plugins Instalados:"
#: editor/editor_plugin_settings.cpp
+msgid "Update"
+msgstr "Atualizar"
+
+#: editor/editor_plugin_settings.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Version:"
+msgstr "Versão:"
+
+#: editor/editor_plugin_settings.cpp
msgid "Author:"
msgstr "Autor:"
@@ -2345,7 +2263,8 @@ msgid "Frame %"
msgstr "% de Quadro"
#: editor/editor_profiler.cpp
-msgid "Fixed Frame %"
+#, fuzzy
+msgid "Physics Frame %"
msgstr "% de Quadro Fixo"
#: editor/editor_profiler.cpp editor/script_editor_debugger.cpp
@@ -2364,35 +2283,18 @@ msgstr "Mesmo"
msgid "Frame #:"
msgstr "Frame nº:"
-#: editor/editor_reimport_dialog.cpp
-msgid "Please wait for scan to complete."
-msgstr "Por favor aguarde a verificação completar."
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Current scene must be saved to re-import."
-msgstr "Cena Atual só deve ser salva para re-importação."
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Save & Re-Import"
-msgstr "Salvar e Re-Importar"
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Importing"
-msgstr "Re-Importando"
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Import Changed Resources"
-msgstr "Re-Importar Recursos Alterados"
-
#: editor/editor_run_native.cpp
msgid "Select device from the list"
-msgstr ""
+msgstr "Selecione um dispositivo da lista"
#: editor/editor_run_native.cpp
msgid ""
"No runnable export preset found for this platform.\n"
"Please add a runnable preset in the export menu."
msgstr ""
+"Não foi encontrado uma definição de exportação executável para esta "
+"plataforma.\n"
+"Por favor, adicione uma definição executável no menu de exportação."
#: editor/editor_run_script.cpp
msgid "Write your logic in the _run() method."
@@ -2435,9 +2337,8 @@ msgid "Import From Node:"
msgstr "Importar a Partir do Nó:"
#: editor/export_template_manager.cpp
-#, fuzzy
msgid "Re-Download"
-msgstr "Recarregar"
+msgstr "Baixar Novamente"
#: editor/export_template_manager.cpp
msgid "Uninstall"
@@ -2448,9 +2349,8 @@ msgid "(Installed)"
msgstr "(Instalado)"
#: editor/export_template_manager.cpp
-#, fuzzy
msgid "Download"
-msgstr "Abaixo"
+msgstr "Download"
#: editor/export_template_manager.cpp
msgid "(Missing)"
@@ -2462,7 +2362,7 @@ msgstr "(Atual)"
#: editor/export_template_manager.cpp
msgid "Remove template version '%s'?"
-msgstr ""
+msgstr "Remover versão '%s' do modelo?"
#: editor/export_template_manager.cpp
msgid "Can't open export templates zip."
@@ -2470,17 +2370,19 @@ msgstr "Não se pôde abrir zip dos modelos de exportação."
#: editor/export_template_manager.cpp
msgid "Invalid version.txt format inside templates."
-msgstr ""
+msgstr "Formato do version.txt dentro dos modelos é inválido."
#: editor/export_template_manager.cpp
msgid ""
"Invalid version.txt format inside templates. Revision is not a valid "
"identifier."
msgstr ""
+"Formato do version.txt dentro dos modelos é inválido. A revisão não é um "
+"identificador válido."
#: editor/export_template_manager.cpp
msgid "No version.txt found inside templates."
-msgstr ""
+msgstr "Não foi encontrado um version.txt dentro dos modelos."
#: editor/export_template_manager.cpp
msgid "Error creating path for templates:\n"
@@ -2495,10 +2397,6 @@ msgid "Importing:"
msgstr "Importando:"
#: editor/export_template_manager.cpp
-msgid "Loading Export Templates"
-msgstr "Carregando Modelos de Exportação"
-
-#: editor/export_template_manager.cpp
msgid "Current Version:"
msgstr "Versão Atual:"
@@ -2533,60 +2431,73 @@ msgid "Cannot navigate to '"
msgstr "Não é possível navegar para '"
#: editor/filesystem_dock.cpp
-#, fuzzy
+msgid "View items as a grid of thumbnails"
+msgstr "Visualizar itens como uma grade de miniaturas"
+
+#: editor/filesystem_dock.cpp
+msgid "View items as a list"
+msgstr "Visualizar itens como uma lista"
+
+#: editor/filesystem_dock.cpp
msgid ""
"\n"
-"Status: Needs Re-Import"
-msgstr "Salvar e Re-Importar"
+"Status: Import of file failed. Please fix file and reimport manually."
+msgstr ""
+"\n"
+"Estado: Falha na importação do arquivo. Por favor, conserte o arquivo e re-"
+"importe manualmente."
#: editor/filesystem_dock.cpp
-#, fuzzy
msgid ""
"\n"
"Source: "
-msgstr "Origem:"
+msgstr ""
+"\n"
+"Origem: "
#: editor/filesystem_dock.cpp
-msgid "Same source and destination files, doing nothing."
-msgstr "Mesmos arquivos de destino e origem, nada a fazer."
+msgid "Cannot move/rename resources root."
+msgstr "Não foi possível mover/renomear raiz dos recurso."
#: editor/filesystem_dock.cpp
-msgid "Target file exists, can't overwrite. Delete first."
-msgstr ""
+msgid "Cannot move a folder into itself.\n"
+msgstr "Não é possível mover uma pasta nela mesma.\n"
#: editor/filesystem_dock.cpp
-msgid "Same source and destination paths, doing nothing."
-msgstr "Mesmo caminhos de destino e origem, nada a fazer."
+msgid "Error moving:\n"
+msgstr "Erro ao mover:\n"
#: editor/filesystem_dock.cpp
-msgid "Can't move directories to within themselves."
-msgstr "Não é possível mover diretórios para dentro de si mesmos."
+msgid "Unable to update dependencies:\n"
+msgstr "Não foi possível atualizar dependências:\n"
#: editor/filesystem_dock.cpp
-msgid "Can't rename deps for:\n"
-msgstr ""
+msgid "No name provided"
+msgstr "Nenhum nome fornecido"
#: editor/filesystem_dock.cpp
-#, fuzzy
-msgid "Error moving file:\n"
-msgstr "Erro ao carregar imagem:"
+msgid "Provided name contains invalid characters"
+msgstr "O nome fornecido contém caracteres inválidos"
#: editor/filesystem_dock.cpp
-#, fuzzy
-msgid "Error moving dir:\n"
-msgstr "Erro ao importar:"
+msgid "No name provided."
+msgstr "Nenhum nome fornecido."
+
+#: editor/filesystem_dock.cpp
+msgid "Name contains invalid characters."
+msgstr "Nome contém caracteres inválidos."
#: editor/filesystem_dock.cpp
-msgid "Can't operate on '..'"
-msgstr "Não é possível operar em \"..\""
+msgid "A file or folder with this name already exists."
+msgstr "Um arquivo ou pasta com esse nome já existe."
#: editor/filesystem_dock.cpp
-msgid "Pick New Name and Location For:"
-msgstr "Escolha Novo Nome e Localização Para:"
+msgid "Renaming file:"
+msgstr "Renomear arquivo:"
#: editor/filesystem_dock.cpp
-msgid "No files selected!"
-msgstr "Nenhum arquivo selecionado!"
+msgid "Renaming folder:"
+msgstr "Renomear pasta:"
#: editor/filesystem_dock.cpp
msgid "Expand all"
@@ -2597,40 +2508,36 @@ msgid "Collapse all"
msgstr "Recolher tudo"
#: editor/filesystem_dock.cpp
-msgid "Show In File Manager"
-msgstr "Mostrar no Gerenciador de Arquivos"
-
-#: editor/filesystem_dock.cpp
-msgid "Instance"
-msgstr "Instanciar"
+msgid "Copy Path"
+msgstr "Copiar Caminho"
#: editor/filesystem_dock.cpp
-msgid "Edit Dependencies.."
-msgstr "Editar Dependências.."
+msgid "Rename.."
+msgstr "Renomear..."
#: editor/filesystem_dock.cpp
-msgid "View Owners.."
-msgstr "Visualizar Proprietários..."
+msgid "Move To.."
+msgstr "Mover Para..."
#: editor/filesystem_dock.cpp
-msgid "Copy Path"
-msgstr "Copiar Caminho"
+msgid "New Folder.."
+msgstr "Nova Pasta..."
#: editor/filesystem_dock.cpp
-msgid "Rename or Move.."
-msgstr "Renomear ou Mover..."
+msgid "Show In File Manager"
+msgstr "Mostrar no Gerenciador de Arquivos"
#: editor/filesystem_dock.cpp
-msgid "Move To.."
-msgstr "Mover Para..."
+msgid "Instance"
+msgstr "Instanciar"
#: editor/filesystem_dock.cpp
-msgid "Info"
-msgstr "Informação"
+msgid "Edit Dependencies.."
+msgstr "Editar Dependências.."
#: editor/filesystem_dock.cpp
-msgid "Re-Import.."
-msgstr "Re-importar..."
+msgid "View Owners.."
+msgstr "Visualizar Proprietários..."
#: editor/filesystem_dock.cpp
msgid "Previous Directory"
@@ -2657,11 +2564,18 @@ msgid ""
"Scanning Files,\n"
"Please Wait.."
msgstr ""
+"Analisando arquivos,\n"
+"Por favor aguarde..."
#: editor/filesystem_dock.cpp
msgid "Move"
msgstr "Mover"
+#: editor/filesystem_dock.cpp editor/plugins/animation_tree_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Rename"
+msgstr "Renomear"
+
#: editor/groups_editor.cpp
msgid "Add to Group"
msgstr "Adicionar ao Grupo"
@@ -2671,74 +2585,81 @@ msgid "Remove from Group"
msgstr "Remover do Grupo"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Import as Single Scene"
-msgstr "Importando Cena..."
+msgstr "Importar como Cena Única"
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Animations"
+msgstr "Importar com Animações Separadas"
#: editor/import/resource_importer_scene.cpp
msgid "Import with Separate Materials"
-msgstr ""
+msgstr "Importar com Materiais Separados"
#: editor/import/resource_importer_scene.cpp
msgid "Import with Separate Objects"
-msgstr ""
+msgstr "Importar com Objetos Separados"
#: editor/import/resource_importer_scene.cpp
msgid "Import with Separate Objects+Materials"
-msgstr ""
+msgstr "Importar com Objetos+Materiais serparados"
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Animations"
+msgstr "Importar com Objetos+Animações Separados"
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Materials+Animations"
+msgstr "Importar com Materiais+Animações Separados"
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Materials+Animations"
+msgstr "Importar com Objetos+Materiais+Animações Separados"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Import as Multiple Scenes"
-msgstr "Importar Cena 3D"
+msgstr "Importar como Múltiplas Cenas"
#: editor/import/resource_importer_scene.cpp
msgid "Import as Multiple Scenes+Materials"
-msgstr ""
+msgstr "Impotr como Múltiplas Cenas+Materiais"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Import Scene"
msgstr "Importar Cena"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Importing Scene.."
msgstr "Importando Cena..."
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Running Custom Script.."
msgstr "Rodando Script Personalizado..."
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Couldn't load post-import script:"
msgstr "Não se pôde carregar script pós-importação:"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Invalid/broken script for post-import (check console):"
msgstr "Script pós-importação inválido/quebrado (verifique o console):"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Error running post-import script:"
msgstr "Erro ao rodar script pós-importação:"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Saving.."
msgstr "Salvando..."
#: editor/import_dock.cpp
msgid "Set as Default for '%s'"
-msgstr ""
+msgstr "Definir como padrão para '%'"
#: editor/import_dock.cpp
msgid "Clear Default for '%s'"
-msgstr ""
+msgstr "Limpar padrão para '%'"
#: editor/import_dock.cpp
msgid " Files"
@@ -2753,581 +2674,9 @@ msgid "Preset.."
msgstr "Predefinição..."
#: editor/import_dock.cpp
-#, fuzzy
msgid "Reimport"
msgstr "Reimportar"
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "No bit masks to import!"
-msgstr "Sem máscaras de bits para importar!"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path is empty."
-msgstr "Caminho destino está vazio."
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must be a complete resource path."
-msgstr "Caminho destino deve ser um caminho completo a um recurso."
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must exist."
-msgstr "Caminho destino deve existir."
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Save path is empty!"
-msgstr "Caminho de salvamento vazio!"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Import BitMasks"
-msgstr "Importar Máscara de Bits"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s):"
-msgstr "Textura(s) de Origem:"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Target Path:"
-msgstr "Caminho Destino:"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Accept"
-msgstr "Aceitar"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Bit Mask"
-msgstr "Máscara de Bits"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No source font file!"
-msgstr "Falta arquivo de fonte origem!"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No target font resource!"
-msgstr "Falta recurso de fonte destino!"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"Invalid file extension.\n"
-"Please use .font."
-msgstr ""
-"Extensão de arquivo inválida.\n"
-"Por favor use .font."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Can't load/process source font."
-msgstr "Não se pôde carregar/processar fonte de origem."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Couldn't save font."
-msgstr "Não se pôde salvar fonte."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font:"
-msgstr "Fonte Origem:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font Size:"
-msgstr "Tamanho da Fonte de Origem:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Dest Resource:"
-msgstr "Recurso Destino:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "The quick brown fox jumps over the lazy dog."
-msgstr ""
-"À noite, vovô Kowalsky vê o ímã cair no pé do pinguim queixoso e vovó põe "
-"açúcar no chá de tâmaras do jabuti feliz."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Test:"
-msgstr "Teste:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Options:"
-msgstr "Opções:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Font Import"
-msgstr "Importar Fonte"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"This file is already a Godot font file, please supply a BMFont type file "
-"instead."
-msgstr ""
-"Este arquivo já é um arquivo de fonte Godot, por favor forneça um arquivo "
-"BMFont."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Failed opening as BMFont file."
-msgstr "Falha ao abrir como arquivo BMFont."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error initializing FreeType."
-msgstr "Erro ao inicializar FreeType."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Unknown font format."
-msgstr "Formato de fonte desconhecido."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error loading font."
-msgstr "Erro ao carregar fonte."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Invalid font size."
-msgstr "Tamanho de fonte inválido."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Invalid font custom source."
-msgstr "Origem personalizada da fonte inválida."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/plugins/theme_editor_plugin.cpp
-msgid "Font"
-msgstr "Fonte"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "No meshes to import!"
-msgstr "Sem meshes para importar!"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Single Mesh Import"
-msgstr "Importar Única Mesh"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Source Mesh(es):"
-msgstr "Origem de Mesh(es):"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/plugins/mesh_instance_editor_plugin.cpp
-msgid "Mesh"
-msgstr "Mesh"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Surface %d"
-msgstr "Superfície %d"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "No samples to import!"
-msgstr "Sem amostras para importar!"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Import Audio Samples"
-msgstr "Importar Amostras de Ãudio"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Source Sample(s):"
-msgstr "Amostra(s) de Origem:"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Audio Sample"
-msgstr "Amostra de Ãudio"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "New Clip"
-msgstr "Novo Clipe"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Animation Options"
-msgstr "Opções da Animação"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Flags"
-msgstr "Flags"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Bake FPS:"
-msgstr "Precalcular FPS:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Optimizer"
-msgstr "Otimizador"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Linear Error"
-msgstr "Erro Linear Máximo"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angular Error"
-msgstr "Erro Angular Máximo"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angle"
-msgstr "Ângulo Máximo"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Clips"
-msgstr "Clipes"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Start(s)"
-msgstr "Início(s)"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "End(s)"
-msgstr "Fim(ns)"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Loop"
-msgstr "Repetir"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Filters"
-msgstr "Filtros"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source path is empty."
-msgstr "Caminho de origem está vazio."
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't load post-import script."
-msgstr "Não se pôde carregar script pós-importação."
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Invalid/broken script for post-import."
-msgstr "Script pós-importação inválido/quebrado."
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Error importing scene."
-msgstr "Erro ao importar cena."
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import 3D Scene"
-msgstr "Importar Cena 3D"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source Scene:"
-msgstr "Cena de Origem:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Same as Target Scene"
-msgstr "Mesma da Cena Destino"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Shared"
-msgstr "Compartilhado"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Target Texture Folder:"
-msgstr "Pasta Destino para Textura:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Post-Process Script:"
-msgstr "Script de Pós-Processamento:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Custom Root Node Type:"
-msgstr "Tipo Personalizado de Nó Raiz:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Auto"
-msgstr "Auto"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Root Node Name:"
-msgstr "Nome do Nó Raíz:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "The Following Files are Missing:"
-msgstr "Os Seguintes Arquivos estão Faltando:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Anyway"
-msgstr "Importar Mesmo Assim"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp scene/gui/dialogs.cpp
-msgid "Cancel"
-msgstr "Cancelar"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import & Open"
-msgstr "Importar e Abrir"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Edited scene has not been saved, open imported scene anyway?"
-msgstr "A cena editada não foi salva, abrir cena importada ainda assim?"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Image:"
-msgstr "Importar Imagem:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Can't import a file over itself:"
-msgstr "Não é possível importar arquivo sobre si mesmo:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't localize path: %s (already local)"
-msgstr "Caminho não pôde ser localizado: %s (já é local)"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "3D Scene Animation"
-msgstr "Animação Cena 3D"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Uncompressed"
-msgstr "Não comprimido"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossless (PNG)"
-msgstr "Comprimido Sem Perdas (PNG)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossy (WebP)"
-msgstr "Comprido Com Perdas (WebP)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress (VRAM)"
-msgstr "Comprimido (VRAM)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Format"
-msgstr "Formato da Textura"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Compression Quality (WebP):"
-msgstr "Qualidade da Compressão da Textura (WebP):"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Options"
-msgstr "Opções da Textura"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Please specify some files!"
-msgstr "Por favor especifique alguns arquivos!"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "At least one file needed for Atlas."
-msgstr "Pelo menos um arquivo é preciso para o Atlas."
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Error importing:"
-msgstr "Erro ao importar:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Only one file is required for large texture."
-msgstr "Apenas um arquivo é requerido para textura grande."
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Max Texture Size:"
-msgstr "Tamanho Máximo de Textura:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for Atlas (2D)"
-msgstr "Importar Texturas para Atlas (2D)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cell Size:"
-msgstr "Tamanho da Célula:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Large Texture"
-msgstr "Textura Grande"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Textures (2D)"
-msgstr "Importar Texturas Grandes (2D)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture"
-msgstr "Textura Origem"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Base Atlas Texture"
-msgstr "Textura Base do Atlas"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s)"
-msgstr "Textura(s) Origem(ns)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 2D"
-msgstr "Importar Texturas para 2D"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 3D"
-msgstr "Importar Texturas para 3D"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures"
-msgstr "Importar Textura"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "2D Texture"
-msgstr "Textura 2D"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "3D Texture"
-msgstr "Textura 3D"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Atlas Texture"
-msgstr "Textura Atlas"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid ""
-"NOTICE: Importing 2D textures is not mandatory. Just copy png/jpg files to "
-"the project."
-msgstr ""
-"AVISO: Importar texturas 2D não é obrigatório. Apenas copie arquivos png/jpg "
-"para o projeto."
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Crop empty space."
-msgstr "Aparar espaço vazio."
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture"
-msgstr "Textura"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Texture"
-msgstr "Importar Textura Grande"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Load Source Image"
-msgstr "Carregar Imagem Origem"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Slicing"
-msgstr "Fatiando"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Inserting"
-msgstr "Inserindo"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Saving"
-msgstr "Salvando"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save large texture:"
-msgstr "Não se pôde salvar textura grande:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Build Atlas For:"
-msgstr "Montar Atlas Para:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Loading Image:"
-msgstr "Carregando Imagem:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't load image:"
-msgstr "Não se pôde carregar imagem:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Converting Images"
-msgstr "Convertendo Imagens"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cropping Images"
-msgstr "Aparando Imagens"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Blitting Images"
-msgstr "Fazendo Blitting das Imagens"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save atlas image:"
-msgstr "Não se pôde salva imagem de atlas:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save converted texture:"
-msgstr "Não se pôde salvar textura convertida:"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid source!"
-msgstr "Origem inválida!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid translation source!"
-msgstr "Origem de tradução inválida!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Column"
-msgstr "Coluna"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/script_create_dialog.cpp
-msgid "Language"
-msgstr "Idioma"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No items to import!"
-msgstr "Nenhum item a importar!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No target path!"
-msgstr "Nenhum caminho destino!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translations"
-msgstr "Importar Traduções"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Couldn't import!"
-msgstr "Não foi possível importar!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translation"
-msgstr "Importar Tradução"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Source CSV:"
-msgstr "Arquivo CSV Origem:"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Ignore First Row"
-msgstr "Ignorar Primeira Linha"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Compress"
-msgstr "Comprimir"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Add to Project (project.godot)"
-msgstr "Adicionar ao Projeto (project.godot)"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Languages:"
-msgstr "Importar Idiomas:"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Translation"
-msgstr "Tradução"
-
#: editor/multi_node_edit.cpp
msgid "MultiNode Set"
msgstr "Múltiplos Nós definidos"
@@ -3340,6 +2689,48 @@ msgstr "Grupos"
msgid "Select a Node to edit Signals and Groups."
msgstr "Selecione um Nó para editar Sinais e Grupos."
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create Poly"
+msgstr "Criar polígono"
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly"
+msgstr "Editar Polígono"
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Insert Point"
+msgstr "Inserir Ponto"
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly (Remove Point)"
+msgstr "Editar Polígono (Remover Ponto)"
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Remove Poly And Point"
+msgstr "Remover Polígono e Ponto"
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create a new polygon from scratch."
+msgstr "Criar um novo polígono do zero."
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid ""
+"Edit existing polygon:\n"
+"LMB: Move Point.\n"
+"Ctrl+LMB: Split Segment.\n"
+"RMB: Erase Point."
+msgstr ""
+"Editar polígono existente:\n"
+"LMB: Mover Ponto.\n"
+"Ctrl+LMB: Soltar Segmento.\n"
+"RMB: Apagar Ponto."
+
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Toggle Autoplay"
msgstr "Alternar Inicio automático"
@@ -3496,7 +2887,6 @@ msgstr "Nome da Animação:"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
#: editor/script_create_dialog.cpp
msgid "Error!"
@@ -3524,9 +2914,8 @@ msgid "New name:"
msgstr "Novo nome:"
#: editor/plugins/animation_tree_editor_plugin.cpp
-#, fuzzy
msgid "Edit Filters"
-msgstr "Editar Filtros de Nó"
+msgstr "Editar Filtros"
#: editor/plugins/animation_tree_editor_plugin.cpp
#: editor/plugins/multimesh_editor_plugin.cpp
@@ -3607,10 +2996,6 @@ msgid "Delete Input"
msgstr "Deletar Entrada"
#: editor/plugins/animation_tree_editor_plugin.cpp
-msgid "Rename"
-msgstr "Renomear"
-
-#: editor/plugins/animation_tree_editor_plugin.cpp
msgid "Animation tree is valid."
msgstr "Ãrvore de Animação é válida."
@@ -3666,64 +3051,181 @@ msgstr "Editar Filtros de Nó"
msgid "Filters.."
msgstr "Filtros..."
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing %d Triangles:"
-msgstr "Analisando %d Triângulos:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Free"
+msgstr "Livrar"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Contents:"
+msgstr "Conteúdo:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "View Files"
+msgstr "Ver Arquivos"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve hostname:"
+msgstr "Não foi possível resolver o hostname:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve."
+msgstr "Não foi possível resolver."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connection error, please try again."
+msgstr "Erro na conexão, por favor tente novamente."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't connect."
+msgstr "Não foi possível conectar."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't connect to host:"
+msgstr "Não foi possível conectar ao host:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response from host:"
+msgstr "Sem resposta do host:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Triangle #"
-msgstr "Triângulo nº"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response."
+msgstr "Sem resposta."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, return code:"
+msgstr "Solicitação falhou, código de retorno:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Req. Failed."
+msgstr "Sol. Falhou."
-#: editor/plugins/baked_light_baker.cpp
-msgid "Light Baker Setup:"
-msgstr "Configurar Baker de Luz:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, too many redirects"
+msgstr "Solicitação falhou, redirecionamentos demais"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing Geometry"
-msgstr "Analisando Geometria"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Redirect Loop."
+msgstr "Loop de Redirecionamento."
-#: editor/plugins/baked_light_baker.cpp
-msgid "Fixing Lights"
-msgstr "Consertando Luzes"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed:"
+msgstr "Falhou:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Making BVH"
-msgstr "Fazendo BVH"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Bad download hash, assuming file has been tampered with."
+msgstr "Hash de download ruim, assumindo que o arquivo foi adulterado."
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Light Octree"
-msgstr "Criando Luz Octree"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Expected:"
+msgstr "Esperado:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Octree Texture"
-msgstr "Criando Textura Octree"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Got:"
+msgstr "Obtido:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Transfer to Lightmaps:"
-msgstr "Transferir para Mapas de Luz:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed sha256 hash check"
+msgstr "Falha na verificação da hash sha256"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Allocating Texture #"
-msgstr "Alocando Textura nº"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Asset Download Error:"
+msgstr "Erro no Download do Asset:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Baking Triangle #"
-msgstr "Precalculando Triângulo nº"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Fetching:"
+msgstr "Procurando:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Post-Processing Texture #"
-msgstr "Pós-Processando Textura nº"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Resolving.."
+msgstr "Resolvendo.."
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Bake!"
-msgstr "Precalcular!"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connecting.."
+msgstr "Conectando.."
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Reset the lightmap octree baking process (start over)."
-msgstr "Redefinir o processo \"octree baking\" do lightmap (recomeçar)."
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Requesting.."
+msgstr "Solicitando.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Error making request"
+msgstr "Erro ao fazer solicitação"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Idle"
+msgstr "Ocioso"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Retry"
+msgstr "Tentar Novamente"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download Error"
+msgstr "Erro no Download"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download for this asset is already in progress!"
+msgstr "Download deste asset já está em progresso!"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "first"
+msgstr "prim"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "prev"
+msgstr "ant"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "next"
+msgstr "prox"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "last"
+msgstr "ult"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "All"
+msgstr "Todos"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Plugins"
+msgstr "Plugins"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Sort:"
+msgstr "Ordenar:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Reverse"
+msgstr "Reverso"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Category:"
+msgstr "Categoria:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Site:"
+msgstr "Site:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Support.."
+msgstr "Suporte.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Official"
+msgstr "Oficial"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Testing"
+msgstr "Em teste"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Assets ZIP File"
+msgstr "Arquivo ZIP de Assets"
#: editor/plugins/camera_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
msgid "Preview"
msgstr "Visualização"
@@ -3766,12 +3268,16 @@ msgid "Edit CanvasItem"
msgstr "Editar CanvaItem"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Change Anchors"
-msgstr "Alterar Âncoras"
+msgid "Anchors only"
+msgstr "Apenas âncoras"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom (%):"
-msgstr "Ampliação (%):"
+msgid "Change Anchors and Margins"
+msgstr "Alterar Âncoras e Margens"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Change Anchors"
+msgstr "Alterar Âncoras"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Paste Pose"
@@ -3800,12 +3306,10 @@ msgid "Alt+RMB: Depth list selection"
msgstr "Alt+RMB: Lista de seleção de profundidade"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Move Mode"
-msgstr "Modo Mover (W)"
+msgstr "Modo Mover"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Rotate Mode"
msgstr "Modo Rotacionar"
@@ -3827,60 +3331,73 @@ msgid "Pan Mode"
msgstr "Modo Panorâmico"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Lock the selected object in place (can't be moved)."
-msgstr "Travar o objeto selecionado no local (não pode ser movido)."
+msgid "Toggles snapping"
+msgstr "Alternar Encaixar"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Unlock the selected object (can be moved)."
-msgstr "Destravar o objeto selecionado (pode ser movido)."
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Use Snap"
+msgstr "Usar Snap"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Makes sure the object's children are not selectable."
-msgstr "Garante que os filhos do objeto não sejam selecionáveis."
+msgid "Snapping options"
+msgstr "Opções da Encaixe"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Restores the object's children's ability to be selected."
-msgstr "Restaura a habilidade dos filhos do objeto de serem selecionados."
+msgid "Snap to grid"
+msgstr "Encaixar na grade"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Edit"
-msgstr "Editar"
+msgid "Use Rotation Snap"
+msgstr "Usar Snap de Rotação"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Use Snap"
-msgstr "Usar Snap"
+msgid "Configure Snap..."
+msgstr "Configurar Encaixe..."
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Show Grid"
-msgstr "Mostrar Grade"
+msgid "Snap Relative"
+msgstr "Snap Relativo"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Rotation Snap"
-msgstr "Usar Snap de Rotação"
+msgid "Use Pixel Snap"
+msgstr "Usar Snap de Pixel"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap Relative"
-msgstr "Snap Relativo"
+msgid "Smart snapping"
+msgstr "Encaixe inteligente"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Configure Snap.."
-msgstr "Configurar Snap..."
+msgid "Snap to parent"
+msgstr "Encaixar no pai"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Pixel Snap"
-msgstr "Usar Snap de Pixel"
+msgid "Snap to node anchor"
+msgstr "Encaixar na âncora do nó"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Skeleton.."
-msgstr "Esqueleto..."
+msgid "Snap to node sides"
+msgstr "Encaixar nos lados do lá"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to other nodes"
+msgstr "Encaixar em outros nós"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Lock the selected object in place (can't be moved)."
+msgstr "Travar o objeto selecionado no local (não pode ser movido)."
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Unlock the selected object (can be moved)."
+msgstr "Destravar o objeto selecionado (pode ser movido)."
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Makes sure the object's children are not selectable."
+msgstr "Garante que os filhos do objeto não sejam selecionáveis."
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Restores the object's children's ability to be selected."
+msgstr "Restaura a habilidade dos filhos do objeto de serem selecionados."
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Make Bones"
@@ -3891,9 +3408,8 @@ msgid "Clear Bones"
msgstr "Limpar Ossos"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Show Bones"
-msgstr "Fazer Ossos"
+msgstr "Mostrar Ossos"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Make IK Chain"
@@ -3909,12 +3425,17 @@ msgid "View"
msgstr "Visualizar"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Reset"
-msgstr "Restaurar Ampliação"
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Show Grid"
+msgstr "Mostrar Grade"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Show helpers"
+msgstr "Mostrar auxiliadores"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Set.."
-msgstr "Definir Ampliação..."
+msgid "Show rulers"
+msgstr "Mostrar réguas"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Center Selection"
@@ -3925,8 +3446,8 @@ msgid "Frame Selection"
msgstr "Seleção de Quadros"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Anchor"
-msgstr "Âncora"
+msgid "Layout"
+msgstr "Layout"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Insert Keys"
@@ -3949,91 +3470,65 @@ msgid "Clear Pose"
msgstr "Limpar Pose"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Set a Value"
-msgstr "Defina um Valor"
+msgid "Drag pivot from mouse position"
+msgstr "Arrastar o pivô para a posição do mouse"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap (Pixels):"
-msgstr "Snap (Pixels):"
+msgid "Set pivot at mouse position"
+msgstr "Colocar o pivô na posição do mouse"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Multiply grid step by 2"
+msgstr "Multiplifcar passo da grade por 2"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Divide grid step by 2"
+msgstr "Dividir passo da grade por 2"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Add %s"
-msgstr "Adicionar Todos"
+msgstr "Adicionar %s"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Adding %s..."
-msgstr ""
+msgstr "Adicionando %s..."
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Create Node"
msgstr "Criar Nó"
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Error instancing scene from %s"
msgstr "Erro ao instanciar cena de %s"
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "OK :("
msgstr "OK :("
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "No parent to instance a child at."
-msgstr "Sem nó pai onde instanciar um filho."
+msgstr "Sem pai onde instanciar um filho."
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "This operation requires a single selected node."
msgstr "Essa operação requer um único nó selecionado."
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Change default type"
-msgstr "Alterar Valor Padrão"
+msgstr "Alterar tipo padrão"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid ""
"Drag & drop + Shift : Add node as sibling\n"
"Drag & drop + Alt : Change node type"
msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Create Poly"
-msgstr "Criar polígono"
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly"
-msgstr "Editar Polígono"
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly (Remove Point)"
-msgstr "Editar Polígono (Remover Ponto)"
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Create a new polygon from scratch."
-msgstr "Criar um novo polígono do zero."
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-msgid ""
-"Edit existing polygon:\n"
-"LMB: Move Point.\n"
-"Ctrl+LMB: Split Segment.\n"
-"RMB: Erase Point."
-msgstr ""
+"Arrastar e soltar + Shift : Adicionar nó como irmão\n"
+"Arrastar e soltar + Alt : Mudar tipo de nó"
#: editor/plugins/collision_polygon_editor_plugin.cpp
msgid "Create Poly3D"
@@ -4044,14 +3539,6 @@ msgid "Set Handle"
msgstr "Definir Manipulador"
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Creating Mesh Library"
-msgstr "Criando MeshLibrary"
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Thumbnail.."
-msgstr "Miniatura..."
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Remove item %d?"
msgstr "Remover item %d?"
@@ -4074,57 +3561,68 @@ msgid "Update from Scene"
msgstr "Atualizar a partir de Cena"
#: editor/plugins/curve_editor_plugin.cpp
-#, fuzzy
+msgid "Flat0"
+msgstr "Flat0"
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat1"
+msgstr "Flat1"
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Ease in"
+msgstr "Suavizar início"
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Ease out"
+msgstr "Suavizar final"
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Smoothstep"
+msgstr "Passo suave"
+
+#: editor/plugins/curve_editor_plugin.cpp
msgid "Modify Curve Point"
-msgstr "Modificar Curve Map"
+msgstr "Modificar Ponto da Curva"
#: editor/plugins/curve_editor_plugin.cpp
-#, fuzzy
msgid "Modify Curve Tangent"
-msgstr "Modificar Curve Map"
+msgstr "Modificar Tangente da Curva"
#: editor/plugins/curve_editor_plugin.cpp
-#, fuzzy
msgid "Load Curve Preset"
-msgstr "Carregar Recurso"
+msgstr "Carregar Definição de Curva"
#: editor/plugins/curve_editor_plugin.cpp
-#, fuzzy
msgid "Add point"
-msgstr "Adicionar Entrada"
+msgstr "Adicionar ponto"
#: editor/plugins/curve_editor_plugin.cpp
-#, fuzzy
msgid "Remove point"
-msgstr "Remover Ponto do Caminho"
+msgstr "Remover ponto"
#: editor/plugins/curve_editor_plugin.cpp
-#, fuzzy
msgid "Left linear"
-msgstr "Linear"
+msgstr "Linear esquerda"
#: editor/plugins/curve_editor_plugin.cpp
-#, fuzzy
msgid "Right linear"
-msgstr "Visão Direita"
+msgstr "Linear direita"
#: editor/plugins/curve_editor_plugin.cpp
-#, fuzzy
msgid "Load preset"
-msgstr "Carregar Recurso"
+msgstr "Carregar definição"
#: editor/plugins/curve_editor_plugin.cpp
-#, fuzzy
msgid "Remove Curve Point"
-msgstr "Remover Ponto do Caminho"
+msgstr "Remover Ponto da Curva"
#: editor/plugins/curve_editor_plugin.cpp
msgid "Toggle Curve Linear Tangent"
-msgstr ""
+msgstr "Alternar Curva Targente Linear"
#: editor/plugins/curve_editor_plugin.cpp
msgid "Hold Shift to edit tangents individually"
-msgstr ""
+msgstr "Segure Shift para editar tangentes individualmente"
#: editor/plugins/gradient_editor_plugin.cpp
msgid "Add/Remove Color Ramp Point"
@@ -4152,45 +3650,40 @@ msgid ""
"No OccluderPolygon2D resource on this node.\n"
"Create and assign one?"
msgstr ""
+"Nenhum recurso OccluderPolygon2D neste nó.\n"
+"Criar e atribuir um?"
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
msgid "Create Occluder Polygon"
msgstr "Criar Polígono de Oclusão"
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Edit existing polygon:"
msgstr "Editar polígono existente:"
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "LMB: Move Point."
msgstr "LMB: Mover Ponto."
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Ctrl+LMB: Split Segment."
msgstr "Ctrl+LMB: Dividir Segmento."
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "RMB: Erase Point."
msgstr "RMB: Apagar Ponto."
#: editor/plugins/line_2d_editor_plugin.cpp
-#, fuzzy
msgid "Remove Point from Line2D"
-msgstr "Remover Ponto da Curva"
+msgstr "Remover Ponto de Line2D"
#: editor/plugins/line_2d_editor_plugin.cpp
-#, fuzzy
msgid "Add Point to Line2D"
-msgstr "Adicionar Ponto à Curva"
+msgstr "Adicionar Ponto ao Line2D"
#: editor/plugins/line_2d_editor_plugin.cpp
-#, fuzzy
msgid "Move Point in Line2D"
-msgstr "Mover Ponto na Curva"
+msgstr "Mover Ponto em Line2D"
#: editor/plugins/line_2d_editor_plugin.cpp
#: editor/plugins/path_2d_editor_plugin.cpp
@@ -4223,9 +3716,8 @@ msgid "Add Point (in empty space)"
msgstr "Adicionar Ponto (em espaço vazio)"
#: editor/plugins/line_2d_editor_plugin.cpp
-#, fuzzy
msgid "Split Segment (in line)"
-msgstr "Dividir Segmentos (na curva)"
+msgstr "Dividir Segmento (em linha)"
#: editor/plugins/line_2d_editor_plugin.cpp
#: editor/plugins/path_2d_editor_plugin.cpp
@@ -4278,6 +3770,10 @@ msgid "Create Outline"
msgstr "Criar Contorno"
#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Mesh"
+msgstr "Mesh"
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Create Trimesh Static Body"
msgstr "Criar Corpo Trimesh Estático"
@@ -4406,27 +3902,88 @@ msgstr "Escala aleatória:"
msgid "Populate"
msgstr "Popular"
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake!"
+msgstr "Precalcular!"
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake the navigation mesh.\n"
+msgstr "Preparar a malha de navegação.\n"
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Clear the navigation mesh."
+msgstr "Apagar a malha de navegação."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Setting up Configuration..."
+msgstr "Preparando Configuração..."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Calculating grid size..."
+msgstr "Calculando tamanho da grade..."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating heightfield..."
+msgstr "Criando mapa de altura..."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Marking walkable triangles..."
+msgstr "Marcando triângulos caminháveis..."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Constructing compact heightfield..."
+msgstr "Construindo um mapa de altura compacto..."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Eroding walkable area..."
+msgstr "Erodindo área caminhável..."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Partitioning..."
+msgstr "Particionando..."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating contours..."
+msgstr "Criando contornos..."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating polymesh..."
+msgstr "Criando polimalha..."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Converting to native navigation mesh..."
+msgstr "Convertando para malha de navegação nativa..."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Navigation Mesh Generator Setup:"
+msgstr "Configuração do Gerador de Malha de Navegação:"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Parsing Geometry..."
+msgstr "Analisando Geometria..."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Done!"
+msgstr "Pronto!"
+
#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Create Navigation Polygon"
msgstr "Criar Polígono de Navegação"
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Remove Poly And Point"
-msgstr "Remover Polígono e Ponto"
-
#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Clear Emission Mask"
msgstr "Limpar Máscara de Emissão"
#: editor/plugins/particles_2d_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp
-#, fuzzy
msgid "Generating AABB"
-msgstr "Gerar AABB"
+msgstr "Gerando AABB"
#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Can only set point into a ParticlesMaterial process material"
msgstr ""
+"Só é permitido colocar um ponto em um material processador ParticlesMaterial"
#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Error loading image:"
@@ -4442,7 +3999,7 @@ msgstr "Definir Máscara de Emissão"
#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Generate Visibility Rect"
-msgstr ""
+msgstr "Gerar Retângulo de Visibilidade"
#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Load Emission Mask"
@@ -4450,9 +4007,8 @@ msgstr "Carregar Máscara de Emissão"
#: editor/plugins/particles_2d_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp
-#, fuzzy
msgid "Particles"
-msgstr "Vértice"
+msgstr "Partículas"
#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Generated Point Count:"
@@ -4460,24 +4016,20 @@ msgstr "Gerar Contagem de Pontos:"
#: editor/plugins/particles_2d_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp
-#, fuzzy
msgid "Generation Time (sec):"
-msgstr "Tempo Médio (seg)"
+msgstr "Gerando Tempo (seg):"
#: editor/plugins/particles_2d_editor_plugin.cpp
-#, fuzzy
msgid "Emission Mask"
-msgstr "Definir Máscara de Emissão"
+msgstr "Máscara de Emissão"
#: editor/plugins/particles_2d_editor_plugin.cpp
-#, fuzzy
msgid "Capture from Pixel"
-msgstr "Criar a partir de Cena"
+msgstr "Capturar a partir do Pixel"
#: editor/plugins/particles_2d_editor_plugin.cpp
-#, fuzzy
msgid "Emission Colors"
-msgstr "Posições de Emissão:"
+msgstr "Cores de Emissão"
#: editor/plugins/particles_editor_plugin.cpp
msgid "Node does not contain geometry."
@@ -4489,7 +4041,7 @@ msgstr "O nó não contém geometria (faces)."
#: editor/plugins/particles_editor_plugin.cpp
msgid "A processor material of type 'ParticlesMaterial' is required."
-msgstr ""
+msgstr "Um material processador do tipo 'ParticlesMaterial' é necessário."
#: editor/plugins/particles_editor_plugin.cpp
msgid "Faces contain no area!"
@@ -4504,14 +4056,12 @@ msgid "Generate AABB"
msgstr "Gerar AABB"
#: editor/plugins/particles_editor_plugin.cpp
-#, fuzzy
msgid "Create Emission Points From Mesh"
-msgstr "Criar Emissor a partir de Mesh"
+msgstr "Criar Pontos de Emissão a Partir do Mesh"
#: editor/plugins/particles_editor_plugin.cpp
-#, fuzzy
msgid "Create Emission Points From Node"
-msgstr "Criar Emissor a partir de Nó"
+msgstr "Criar Pontos de Emissão a Partir do Nó"
#: editor/plugins/particles_editor_plugin.cpp
msgid "Clear Emitter"
@@ -4522,46 +4072,40 @@ msgid "Create Emitter"
msgstr "Criar Emissor"
#: editor/plugins/particles_editor_plugin.cpp
-#, fuzzy
msgid "Emission Points:"
-msgstr "Posições de Emissão:"
+msgstr "Pontos de Emissão:"
#: editor/plugins/particles_editor_plugin.cpp
-#, fuzzy
msgid "Surface Points"
-msgstr "Superfície %d"
+msgstr "Pontos de Superfície"
#: editor/plugins/particles_editor_plugin.cpp
msgid "Surface Points+Normal (Directed)"
-msgstr ""
+msgstr "Pontos de Superfície+Normal (Direcionadas)"
#: editor/plugins/particles_editor_plugin.cpp
msgid "Volume"
msgstr "Volume"
#: editor/plugins/particles_editor_plugin.cpp
-#, fuzzy
msgid "Emission Source: "
-msgstr "Preenchimento de Emissão:"
+msgstr "Origem da Emissão: "
#: editor/plugins/particles_editor_plugin.cpp
-#, fuzzy
msgid "Generate Visibility AABB"
-msgstr "Gerar AABB"
+msgstr "Gerar AABB de Visibilidade"
#: editor/plugins/path_2d_editor_plugin.cpp
msgid "Remove Point from Curve"
msgstr "Remover Ponto da Curva"
#: editor/plugins/path_2d_editor_plugin.cpp
-#, fuzzy
msgid "Remove Out-Control from Curve"
-msgstr "Mover Controle de Saída na Curva"
+msgstr "Remover Controle de Saída da Curva"
#: editor/plugins/path_2d_editor_plugin.cpp
-#, fuzzy
msgid "Remove In-Control from Curve"
-msgstr "Remover Ponto da Curva"
+msgstr "Remover Controle de Entrada da Curva"
#: editor/plugins/path_2d_editor_plugin.cpp
#: editor/plugins/path_editor_plugin.cpp
@@ -4600,15 +4144,15 @@ msgstr "Ponto da Curva nº"
#: editor/plugins/path_editor_plugin.cpp
msgid "Set Curve Point Position"
-msgstr "Definir Pos do Ponto da Curva"
+msgstr "Definir Posição do Ponto da Curva"
#: editor/plugins/path_editor_plugin.cpp
msgid "Set Curve In Position"
-msgstr "Definir Pos da Entrada da Curva"
+msgstr "Colocar a Curva na Posição"
#: editor/plugins/path_editor_plugin.cpp
msgid "Set Curve Out Position"
-msgstr "Definir Pos da Saída da Curva"
+msgstr "Definir Posição de Saída da Curva"
#: editor/plugins/path_editor_plugin.cpp
msgid "Split Path"
@@ -4619,14 +4163,12 @@ msgid "Remove Path Point"
msgstr "Remover Ponto do Caminho"
#: editor/plugins/path_editor_plugin.cpp
-#, fuzzy
msgid "Remove Out-Control Point"
-msgstr "Mover Controle de Saída na Curva"
+msgstr "Remover Ponto de Controle de Saída"
#: editor/plugins/path_editor_plugin.cpp
-#, fuzzy
msgid "Remove In-Control Point"
-msgstr "Mover Controle de Entrada na Curva"
+msgstr "Remover Ponto de Controle de Entrada"
#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Create UV Map"
@@ -4669,6 +4211,14 @@ msgid "Scale Polygon"
msgstr "Escalonar Polígono"
#: editor/plugins/polygon_2d_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Edit"
+msgstr "Editar"
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Polygon->UV"
msgstr "Polígono->UV"
@@ -4723,73 +4273,21 @@ msgstr "Carregar Recurso"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/shader_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "Colar"
-#: editor/plugins/rich_text_editor_plugin.cpp
-msgid "Parse BBCode"
-msgstr "Analisar BBCode"
-
-#: editor/plugins/sample_editor_plugin.cpp
-msgid "Length:"
-msgstr "Duração:"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Open Sample File(s)"
-msgstr "Abrir Arquivo(s) de Amostra"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "ERROR: Couldn't load sample!"
-msgstr "ERRO: Não é possível carregar a amostra!"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Add Sample"
-msgstr "Adicionar Amostra"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Rename Sample"
-msgstr "Renomear Amostra"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Delete Sample"
-msgstr "Excluir Amostra"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "16 Bits"
-msgstr "16 bits"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "8 Bits"
-msgstr "8 Bits"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Stereo"
-msgstr "Estéreo"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Mono"
-msgstr "Mono"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Format"
-msgstr "Formato"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Pitch"
-msgstr "Pitch"
-
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Clear Recent Files"
-msgstr "Limpar Ossos"
+msgstr "Limpar Arquivos Recentes"
#: editor/plugins/script_editor_plugin.cpp
msgid ""
"Close and save changes?\n"
"\""
msgstr ""
+"Fechar e salvar mudanças?\n"
+"\""
#: editor/plugins/script_editor_plugin.cpp
msgid "Error while saving theme"
@@ -4817,7 +4315,7 @@ msgstr "Salvar Tema Como..."
#: editor/plugins/script_editor_plugin.cpp
msgid " Class Reference"
-msgstr ""
+msgstr " Referência de Classes"
#: editor/plugins/script_editor_plugin.cpp
msgid "Next script"
@@ -4868,14 +4366,16 @@ msgid "Close Docs"
msgstr "Fechar Docs"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Close All"
-msgstr "Fechar"
+msgstr "Fechar Tudo"
+
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+msgid "Run"
+msgstr "Rodar"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Toggle Scripts Panel"
-msgstr "Alternar Favorito"
+msgstr "Alternar Painel de Scripts"
#: editor/plugins/script_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
@@ -4901,7 +4401,8 @@ msgstr "Passo para dentro"
msgid "Break"
msgstr "Pausar"
-#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+#: editor/script_editor_debugger.cpp
msgid "Continue"
msgstr "Continuar"
@@ -4910,26 +4411,12 @@ msgid "Keep Debugger Open"
msgstr "Manter Depurador Aberto"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Debug with external editor"
-msgstr "Abrir o próximo Editor"
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Window"
-msgstr "Janela"
+msgstr "Depurar com um editor externo"
#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Left"
-msgstr "Mover para Esquerda"
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Right"
-msgstr "Mover para Direita"
-
-#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Open Godot online documentation"
-msgstr "Pesquise a documentação de referência."
+msgstr "Abrir a documentação online da Godot"
#: editor/plugins/script_editor_plugin.cpp
msgid "Search the class hierarchy."
@@ -4948,9 +4435,8 @@ msgid "Go to next edited document."
msgstr "Ir para o próximo documento editado."
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Discard"
-msgstr "Discreto"
+msgstr "Descartar"
#: editor/plugins/script_editor_plugin.cpp
msgid "Create Script"
@@ -4985,29 +4471,27 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
msgid "Only resources from filesystem can be dropped."
-msgstr ""
+msgstr "Apenas recursos de Arquivos podem ser soltos."
#: editor/plugins/script_text_editor.cpp
-#, fuzzy
msgid "Pick Color"
-msgstr "Cor"
+msgstr "Escolher Cor"
#: editor/plugins/script_text_editor.cpp
-#, fuzzy
msgid "Convert Case"
-msgstr "Convertendo Imagens"
+msgstr "Converter Maíusculas/Minúsculas"
#: editor/plugins/script_text_editor.cpp
msgid "Uppercase"
-msgstr ""
+msgstr "Maiúscula"
#: editor/plugins/script_text_editor.cpp
msgid "Lowercase"
-msgstr ""
+msgstr "Minúscula"
#: editor/plugins/script_text_editor.cpp
msgid "Capitalize"
-msgstr ""
+msgstr "Capitalizar"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/shader_editor_plugin.cpp scene/gui/line_edit.cpp
@@ -5016,8 +4500,9 @@ msgid "Cut"
msgstr "Recortar"
#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "Copiar"
@@ -5036,9 +4521,8 @@ msgid "Move Down"
msgstr "Mover para Baixo"
#: editor/plugins/script_text_editor.cpp
-#, fuzzy
msgid "Delete Line"
-msgstr "Excluir Ponto"
+msgstr "Excluir Linha"
#: editor/plugins/script_text_editor.cpp
msgid "Indent Left"
@@ -5066,11 +4550,11 @@ msgstr "Apagar Espaços em Branco"
#: editor/plugins/script_text_editor.cpp
msgid "Convert Indent To Spaces"
-msgstr ""
+msgstr "Converter Indentação Para Espaços"
#: editor/plugins/script_text_editor.cpp
msgid "Convert Indent To Tabs"
-msgstr ""
+msgstr "Converter Indentação Para Tabs"
#: editor/plugins/script_text_editor.cpp
msgid "Auto Indent"
@@ -5094,14 +4578,12 @@ msgid "Goto Previous Breakpoint"
msgstr "Ir ao Ponto de Interrupção Anterior"
#: editor/plugins/script_text_editor.cpp
-#, fuzzy
msgid "Convert To Uppercase"
-msgstr "Converter Para..."
+msgstr "Converter para Maíusculo"
#: editor/plugins/script_text_editor.cpp
-#, fuzzy
msgid "Convert To Lowercase"
-msgstr "Converter Para..."
+msgstr "Converter Para Minúsculo"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/shader_editor_plugin.cpp
@@ -5128,7 +4610,7 @@ msgstr "Ajuda Contextual"
#: editor/plugins/shader_editor_plugin.cpp
msgid "Shader"
-msgstr ""
+msgstr "Shader"
#: editor/plugins/shader_graph_editor_plugin.cpp
msgid "Change Scalar Constant"
@@ -5283,10 +4765,6 @@ msgid "View Plane Transform."
msgstr "Visualizar Transformação do Plano."
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Scaling to %s%%."
-msgstr "Escalonando para %s%%."
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rotating %s degrees."
msgstr "Rotacionando %s degraus."
@@ -5303,10 +4781,6 @@ msgid "Top View."
msgstr "Visão Superior."
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Top"
-msgstr "Cima"
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rear View."
msgstr "Visão Traseira."
@@ -5348,31 +4822,27 @@ msgstr "Chave de Animação Inserida."
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
-msgstr ""
+msgstr "Objetos Desenhados"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Material Changes"
-msgstr "Atualizar nas Mudanças"
+msgstr "Mudanças de Material"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Shader Changes"
-msgstr "Atualizar nas Mudanças"
+msgstr "Mudanças de Shader"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Surface Changes"
-msgstr "Atualizar nas Mudanças"
+msgstr "Mudanças de Superfície"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Draw Calls"
-msgstr ""
+msgstr "Chamadas de Desenho"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Vertices"
-msgstr "Vértice"
+msgstr "Vértices"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Align with view"
@@ -5391,85 +4861,78 @@ msgid "Display Overdraw"
msgstr "Exibição Overdraw"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Display Unshaded"
-msgstr "Exibição Shadeless"
+msgstr "Exibir Sem Sombreamento"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "View Environment"
-msgstr "Ambiente"
+msgstr "Visualizar Ambiente"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "View Gizmos"
-msgstr "Gizmos"
+msgstr "Visualizar Gizmos"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "View Information"
-msgstr ""
+msgstr "VIsualizar Informação"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Audio Listener"
msgstr "Ouvinte de Ãudio"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Doppler Enable"
-msgstr "Habilitar"
+msgstr "Habilitar Doppler"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Freelook Left"
-msgstr ""
+msgstr "Visão Livre Esquerda"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Freelook Right"
-msgstr ""
+msgstr "Visão Livre Direita"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Freelook Forward"
-msgstr "Avançar"
+msgstr "Visão Livre Frente"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Freelook Backwards"
-msgstr "Para trás"
+msgstr "Visão Livre Trás"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Freelook Up"
-msgstr ""
+msgstr "Visão Livre Cima"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Freelook Down"
-msgstr "Roda para Baixo."
+msgstr "Visão Livre Baixo"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Freelook Speed Modifier"
-msgstr ""
+msgstr "Modificador de velocidade da Visão Livre"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "preview"
-msgstr "Visualização"
+msgstr "previsualizar"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "XForm Dialog"
msgstr "Diálogo XForm"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Select Mode (Q)\n"
-msgstr "Modo de Seleção"
+msgstr "Modo de Seleção (Q)\n"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid ""
"Drag: Rotate\n"
"Alt+Drag: Move\n"
"Alt+RMB: Depth list selection"
-msgstr "Alt+RMB: Lista de seleção de profundidade"
+msgstr ""
+"Arrastar: Rotacionar\n"
+"Alt+Arrastar: Mover\n"
+"Alt+RMB: Lista de Profundidade"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Move Mode (W)"
@@ -5516,9 +4979,8 @@ msgid "Insert Animation Key"
msgstr "Inserir Chanve de Animação"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Focus Origin"
-msgstr "Ver Origem"
+msgstr "Origem do Foco"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Focus Selection"
@@ -5529,30 +4991,30 @@ msgid "Align Selection With View"
msgstr "Alinhar Seleção com Visualização"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Tool Select"
-msgstr "Selecionar"
+msgstr "Ferramenta Selecionar"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Tool Move"
-msgstr "Mover"
+msgstr "Ferramenta Mover"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Tool Rotate"
-msgstr "Ctrl: Rotaciona"
+msgstr "Ferramenta Rotacionar"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Tool Scale"
-msgstr "Escala:"
+msgstr "Ferramenta Escalar"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Transform"
msgstr "Transformação"
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Configure Snap.."
+msgstr "Configurar Snap..."
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Local Coords"
msgstr "Coordenadas Locais"
@@ -5698,6 +5160,10 @@ msgid "Speed (FPS):"
msgstr "Velocidade (FPS):"
#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Loop"
+msgstr "Repetir"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Animation Frames"
msgstr "Quadros da Animação"
@@ -5710,21 +5176,20 @@ msgid "Insert Empty (After)"
msgstr "Inserir Vazio (Depois)"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Up"
-msgstr "Acima"
+msgid "Move (Before)"
+msgstr "Mover (Antes)"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Down"
-msgstr "Abaixo"
+msgid "Move (After)"
+msgstr "Mover (Depois)"
#: editor/plugins/style_box_editor_plugin.cpp
msgid "StyleBox Preview:"
msgstr "Pré-Visualização do StyleBox:"
#: editor/plugins/texture_region_editor_plugin.cpp
-#, fuzzy
msgid "Set Region Rect"
-msgstr "Definir region_rect"
+msgstr "Definir Retângulo de Região"
#: editor/plugins/texture_region_editor_plugin.cpp
msgid "Snap Mode:"
@@ -5784,19 +5249,20 @@ msgid "Remove Item"
msgstr "Remover Item"
#: editor/plugins/theme_editor_plugin.cpp
-#, fuzzy
msgid "Remove All Items"
-msgstr "Remover Itens de Classe"
+msgstr "Remover Todos os Itens"
#: editor/plugins/theme_editor_plugin.cpp
-#, fuzzy
msgid "Remove All"
-msgstr "Remover"
+msgstr "Remover Tudo"
#: editor/plugins/theme_editor_plugin.cpp
-#, fuzzy
-msgid "Theme"
-msgstr "Salvar Tema"
+msgid "Edit theme.."
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Theme editing menu."
+msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
msgid "Add Class Items"
@@ -5820,7 +5286,7 @@ msgstr "Rádio Checkbox 1"
#: editor/plugins/theme_editor_plugin.cpp
msgid "CheckBox Radio2"
-msgstr "Rádio CheckBox 2"
+msgstr "Caixa de Seleção 2"
#: editor/plugins/theme_editor_plugin.cpp
msgid "Item"
@@ -5880,11 +5346,14 @@ msgid "Style"
msgstr "Estilo"
#: editor/plugins/theme_editor_plugin.cpp
+msgid "Font"
+msgstr "Fonte"
+
+#: editor/plugins/theme_editor_plugin.cpp
msgid "Color"
msgstr "Cor"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Erase Selection"
msgstr "Apagar Seleção"
@@ -5893,18 +5362,16 @@ msgid "Paint TileMap"
msgstr "Pintar TileMap"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Line Draw"
-msgstr "Linear"
+msgstr "Desenhar Linha"
#: editor/plugins/tile_map_editor_plugin.cpp
msgid "Rectangle Paint"
-msgstr ""
+msgstr "Pintura Retângular"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Bucket Fill"
-msgstr "Balde"
+msgstr "Preenchimento de Balde"
#: editor/plugins/tile_map_editor_plugin.cpp
msgid "Erase TileMap"
@@ -5931,8 +5398,8 @@ msgid "Mirror Y"
msgstr "Espelhar Y"
#: editor/plugins/tile_map_editor_plugin.cpp
-msgid "Bucket"
-msgstr "Balde"
+msgid "Paint Tile"
+msgstr "Pintar Tile"
#: editor/plugins/tile_map_editor_plugin.cpp
msgid "Pick Tile"
@@ -5983,24 +5450,26 @@ msgid "Error"
msgstr "Erro"
#: editor/project_export.cpp
-#, fuzzy
msgid "Runnable"
-msgstr "Habilitar"
+msgstr "Executável"
#: editor/project_export.cpp
-#, fuzzy
msgid "Delete patch '"
-msgstr "Deletar Entrada"
+msgstr "Deletar alteração '"
#: editor/project_export.cpp
-#, fuzzy
msgid "Delete preset '%s'?"
-msgstr "Excluir os arquivos selecionados?"
+msgstr "Excluir definição '%s'?"
+
+#: editor/project_export.cpp
+msgid "Export templates for this platform are missing/corrupted: "
+msgstr ""
+"Modelos de exportação para esta plataforma não foram encontrados/estão "
+"corrompidos: "
#: editor/project_export.cpp
-#, fuzzy
msgid "Presets"
-msgstr "Predefinição..."
+msgstr "Predefiniçoes"
#: editor/project_export.cpp editor/project_settings_editor.cpp
msgid "Add.."
@@ -6011,68 +5480,58 @@ msgid "Resources"
msgstr "Recursos"
#: editor/project_export.cpp
-#, fuzzy
msgid "Export all resources in the project"
-msgstr "Exportar todos os recursos no projeto."
+msgstr "Exportar todos os recursos do projeto"
#: editor/project_export.cpp
-#, fuzzy
msgid "Export selected scenes (and dependencies)"
-msgstr "Exportar recursos selecionados (incluindo dependências)."
+msgstr "Exportar cenas selecionadas (incluindo dependências)"
#: editor/project_export.cpp
-#, fuzzy
msgid "Export selected resources (and dependencies)"
-msgstr "Exportar recursos selecionados (incluindo dependências)."
+msgstr "Exportar recursos selecionados (incluindo dependências)"
#: editor/project_export.cpp
msgid "Export Mode:"
msgstr "Modo de Exportação:"
#: editor/project_export.cpp
-#, fuzzy
msgid "Resources to export:"
-msgstr "Recursos a Exportar:"
+msgstr "Recursos para Exportar:"
#: editor/project_export.cpp
-#, fuzzy
msgid ""
"Filters to export non-resource files (comma separated, e.g: *.json, *.txt)"
msgstr ""
"Filtros para exportar arquivos que não sejam recursos (separados por "
-"vírgula, e.g.: *.json, *.txt):"
+"vírgula, e.g.: *.json, *.txt)"
#: editor/project_export.cpp
-#, fuzzy
msgid ""
"Filters to exclude files from project (comma separated, e.g: *.json, *.txt)"
msgstr ""
"Filtros para excluir da exportação (separados por vírgula, e.g.: *.json, *."
-"txt):"
+"txt)"
#: editor/project_export.cpp
-#, fuzzy
msgid "Patches"
-msgstr "Combinações:"
+msgstr "Alterações"
#: editor/project_export.cpp
-#, fuzzy
msgid "Make Patch"
-msgstr "Caminho Destino:"
+msgstr "Criar Alteração"
#: editor/project_export.cpp
-#, fuzzy
msgid "Features"
-msgstr "Textura"
+msgstr "Funcionalidades"
#: editor/project_export.cpp
msgid "Custom (comma-separated):"
-msgstr ""
+msgstr "Personalizado (separado por vírgula):"
#: editor/project_export.cpp
-#, fuzzy
msgid "Feature List:"
-msgstr "Lista de Métodos:"
+msgstr "Lista de Funcionalidades:"
#: editor/project_export.cpp
msgid "Export PCK/Zip"
@@ -6080,77 +5539,112 @@ msgstr "Exportar PCK/Zip"
#: editor/project_export.cpp
msgid "Export templates for this platform are missing:"
+msgstr "Modelos de exportação para esta plataforma não foram encontrados:"
+
+#: editor/project_export.cpp
+msgid "Export templates for this platform are missing/corrupted:"
msgstr ""
+"Modelos de exportação para esta plataforma não foram encontrados/estão "
+"corrompidos:"
#: editor/project_export.cpp
-#, fuzzy
msgid "Export With Debug"
-msgstr "Exportar Tile Set"
+msgstr "Exportar Com Depuração"
#: editor/project_manager.cpp
-msgid "Invalid project path, the path must exist!"
-msgstr "Caminho de projeto inválido, o caminho deve existir!"
+msgid "The path does not exist."
+msgstr "O caminho não existe."
#: editor/project_manager.cpp
-#, fuzzy
-msgid "Invalid project path, project.godot must not exist."
-msgstr "Caminho de projeto inválido, engine.cfg não deve existir."
+msgid "Please choose a 'project.godot' file."
+msgstr "Por favor, escolha um arquivo 'project.godot'."
#: editor/project_manager.cpp
-#, fuzzy
-msgid "Invalid project path, project.godot must exist."
-msgstr "Caminho de projeto inválido, engine.cfg deve existir."
+msgid ""
+"Your project will be created in a non empty folder (you might want to create "
+"a new folder)."
+msgstr ""
+"Seu projeto será criado em uma pasta não vazia (você pode querer criar uma "
+"nova pasta)."
+
+#: editor/project_manager.cpp
+msgid "Please choose a folder that does not contain a 'project.godot' file."
+msgstr ""
+"Por favor, escolha uma pasta que não contenha um arquivo 'project.godot'."
#: editor/project_manager.cpp
msgid "Imported Project"
msgstr "Projeto Importado"
#: editor/project_manager.cpp
+msgid " "
+msgstr " "
+
+#: editor/project_manager.cpp
+msgid "It would be a good idea to name your project."
+msgstr "Seria uma boa ideia nomear o seu projeto."
+
+#: editor/project_manager.cpp
msgid "Invalid project path (changed anything?)."
msgstr "Caminho de projeto inválido (mudou alguma coisa?)."
#: editor/project_manager.cpp
-#, fuzzy
+msgid "Couldn't get project.godot in project path."
+msgstr "Não foi possível encontrar project.godot no caminho do projeto."
+
+#: editor/project_manager.cpp
+msgid "Couldn't edit project.godot in project path."
+msgstr "Não foi possível editar project.godot no caminho do projeto."
+
+#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
-msgstr "Não se pôde criar engine.cfg no caminho do projeto."
+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"
+
+#: editor/project_manager.cpp
+msgid "Couldn't get project.godot in the project path."
+msgstr "Não foi possível encontrar project.godot no caminho do projeto."
+
+#: editor/project_manager.cpp
+msgid "New Game Project"
+msgstr "Novo Projeto de Jogo"
+
+#: editor/project_manager.cpp
msgid "Import Existing Project"
msgstr "Importar Projeto Existente"
#: editor/project_manager.cpp
-msgid "Project Path (Must Exist):"
-msgstr "Caminho do Projeto (Deve Existir):"
+msgid "Create New Project"
+msgstr "Criar Novo Projeto"
+
+#: editor/project_manager.cpp
+msgid "Install Project:"
+msgstr "Instalar Projeto:"
#: editor/project_manager.cpp
msgid "Project Name:"
msgstr "Nome do Projeto:"
#: editor/project_manager.cpp
-msgid "Create New Project"
-msgstr "Criar Novo Projeto"
+msgid "Create folder"
+msgstr "Criar Pasta"
#: editor/project_manager.cpp
msgid "Project Path:"
msgstr "Caminho do Projeto:"
#: editor/project_manager.cpp
-msgid "Install Project:"
-msgstr "Instalar Projeto:"
-
-#: editor/project_manager.cpp
msgid "Browse"
msgstr "Navegar"
#: editor/project_manager.cpp
-msgid "New Game Project"
-msgstr "Novo Projeto de Jogo"
-
-#: editor/project_manager.cpp
msgid "That's a BINGO!"
msgstr "É um BINGO!"
@@ -6159,31 +5653,34 @@ msgid "Unnamed Project"
msgstr "Projeto Sem Nome"
#: editor/project_manager.cpp
-#, fuzzy
+msgid "Can't open project"
+msgstr "Não é possível abrir o projeto"
+
+#: editor/project_manager.cpp
msgid "Are you sure to open more than one project?"
msgstr "Tem certeza de que quer abrir mais de um projeto?"
#: editor/project_manager.cpp
-#, fuzzy
msgid ""
"Can't run project: no main scene defined.\n"
"Please edit the project and set the main scene in \"Project Settings\" under "
"the \"Application\" category."
msgstr ""
-"A cena principal não foi definida, selecionar uma?\n"
-"Você pode alterá-la mais tarde nas \"Configurações do Projeto\" na categoria "
-"\"application\"."
+"Não foi possível executar o projeto: cena principal não definida.\n"
+"Por favor, defina a cena principal nas Configurações do Projeto no menu "
+"Projeto."
#: editor/project_manager.cpp
msgid ""
"Can't run project: Assets need to be imported.\n"
"Please edit the project to trigger the initial import."
msgstr ""
+"Não foi possível executar o projeto: Os recursos precisam ser importados.\n"
+"Por favor, edite o projeto para iniciar a importação inicial."
#: editor/project_manager.cpp
-#, fuzzy
msgid "Are you sure to run more than one project?"
-msgstr "Tem certeza de que quer rodar mais de um projeto?"
+msgstr "Tem certeza de que quer executar mais de um projeto?"
#: editor/project_manager.cpp
msgid "Remove project from the list? (Folder contents will not be modified)"
@@ -6191,35 +5688,37 @@ msgstr "Remover projeto da lista? (O conteúdo da pasta não será modificado)"
#: editor/project_manager.cpp
msgid ""
+"Language changed.\n"
+"The UI will update next time the editor or project manager starts."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid ""
"You are about the scan %s folders for existing Godot projects. Do you "
"confirm?"
msgstr ""
+"Você está para analisar %s pastas por projetos existentes da Godot. Você "
+"confirma?"
#: editor/project_manager.cpp
msgid "Project List"
msgstr "Lista de Projetos"
#: editor/project_manager.cpp
-msgid "Run"
-msgstr "Rodar"
-
-#: editor/project_manager.cpp
msgid "Scan"
msgstr "Escanear"
#: editor/project_manager.cpp
-#, fuzzy
msgid "Select a Folder to Scan"
-msgstr "Selecione uma Pasta para Scanear"
+msgstr "Selecione uma Pasta para Analisar"
#: editor/project_manager.cpp
msgid "New Project"
msgstr "Novo Projeto"
#: editor/project_manager.cpp
-#, fuzzy
msgid "Templates"
-msgstr "Remover Item"
+msgstr "Modelos"
#: editor/project_manager.cpp
msgid "Exit"
@@ -6227,8 +5726,12 @@ msgstr "Sair"
#: editor/project_manager.cpp
#, fuzzy
+msgid "Restart Now"
+msgstr "Reinício (s):"
+
+#: editor/project_manager.cpp
msgid "Can't run project"
-msgstr "Não é possível conectar..."
+msgstr "Não é possível executar o projeto"
#: editor/project_settings_editor.cpp
msgid "Key "
@@ -6263,17 +5766,14 @@ msgid "Add Input Action Event"
msgstr "Adicionar Evento Ação de Entrada"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Meta+"
msgstr "Meta+"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Shift+"
msgstr "Shift+"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Alt+"
msgstr "Alt+"
@@ -6331,18 +5831,16 @@ msgid "Change"
msgstr "Alterar"
#: editor/project_settings_editor.cpp
-#, fuzzy
msgid "Joypad Axis Index:"
-msgstr "Eixo do Joystick:"
+msgstr "Ãndice de Eixo do Joypad:"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Axis"
msgstr "Eixo"
#: editor/project_settings_editor.cpp
-#, fuzzy
msgid "Joypad Button Index:"
-msgstr "Botão do Joystick:"
+msgstr "Ãndice de Botão do Joypad:"
#: editor/project_settings_editor.cpp
msgid "Add Input Action"
@@ -6353,61 +5851,64 @@ msgid "Erase Input Action Event"
msgstr "Apagar Evento Ação de Entrada"
#: editor/project_settings_editor.cpp
-#, fuzzy
msgid "Add Event"
-msgstr "Adicionar Vazio"
+msgstr "Adicionar VEvento"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Device"
msgstr "Dispositivo"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Button"
msgstr "Botão"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Left Button."
msgstr "Botão Esquerdo."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Right Button."
msgstr "Botão Direito."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Middle Button."
msgstr "Botão do Meio."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Up."
msgstr "Roda para Cima."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Down."
msgstr "Roda para Baixo."
#: editor/project_settings_editor.cpp
-#, fuzzy
msgid "Add Global Property"
-msgstr "Adicionar Getter de Propriedade"
+msgstr "Adicionar Propriedad Global"
#: editor/project_settings_editor.cpp
-msgid "Select an setting item first!"
-msgstr ""
+msgid "Select a setting item first!"
+msgstr "Selecione um item de configuração primeiro!"
#: editor/project_settings_editor.cpp
-#, fuzzy
msgid "No property '"
-msgstr "Propriedade:"
+msgstr "Não existe a propriedade '"
#: editor/project_settings_editor.cpp
-#, fuzzy
msgid "Setting '"
-msgstr "Configurações"
+msgstr "Configuração '"
#: editor/project_settings_editor.cpp
-#, fuzzy
msgid "Delete Item"
-msgstr "Deletar Entrada"
+msgstr "Excluir Item"
+
+#: editor/project_settings_editor.cpp
+msgid "Can't contain '/' or ':'"
+msgstr "Não pode conter '/' ou ':'"
+
+#: editor/project_settings_editor.cpp
+msgid "Already existing"
+msgstr "Já existe"
#: editor/project_settings_editor.cpp
msgid "Error saving settings."
@@ -6419,7 +5920,7 @@ msgstr "Configurações Salvas."
#: editor/project_settings_editor.cpp
msgid "Override for Feature"
-msgstr ""
+msgstr "Sobrescrever para Funcionalidade"
#: editor/project_settings_editor.cpp
msgid "Add Translation"
@@ -6451,8 +5952,16 @@ msgstr "Remover Opção de Remapeamento de Recurso"
#: editor/project_settings_editor.cpp
#, fuzzy
+msgid "Changed Locale Filter"
+msgstr "Mudar Tempo de Mistura"
+
+#: editor/project_settings_editor.cpp
+msgid "Changed Locale Filter Mode"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "Project Settings (project.godot)"
-msgstr "Configurações do Projeto (engine.cfg)"
+msgstr "Configurações do Projeto (project.godot)"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
msgid "General"
@@ -6464,7 +5973,7 @@ msgstr "Propriedade:"
#: editor/project_settings_editor.cpp
msgid "Override For.."
-msgstr ""
+msgstr "Sobrescrever Para..."
#: editor/project_settings_editor.cpp
msgid "Input Map"
@@ -6511,13 +6020,36 @@ msgid "Locale"
msgstr "Localidade"
#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Locales Filter"
+msgstr "Filtrar Imagens:"
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Show all locales"
+msgstr "Mostrar Ossos"
+
+#: editor/project_settings_editor.cpp
+msgid "Show only selected locales"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Filter mode:"
+msgstr "Filtrar nós"
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Locales:"
+msgstr "Localidade"
+
+#: editor/project_settings_editor.cpp
msgid "AutoLoad"
msgstr "AutoLoad"
#: editor/property_editor.cpp
-#, fuzzy
msgid "Pick a Viewport"
-msgstr "1 Viewport"
+msgstr "Escolha uma Viewport"
#: editor/property_editor.cpp
msgid "Ease In"
@@ -6552,33 +6084,36 @@ msgid "Assign"
msgstr "Atribuir"
#: editor/property_editor.cpp
-#, fuzzy
msgid "Select Node"
-msgstr "Selecione um Nó"
+msgstr "Selecionar Nó"
#: editor/property_editor.cpp
-#, fuzzy
msgid "New Script"
-msgstr "Próximo Script"
+msgstr "Novo Script"
+
+#: editor/property_editor.cpp
+msgid "Make Unique"
+msgstr "Tornar Único"
#: editor/property_editor.cpp
-#, fuzzy
msgid "Show in File System"
-msgstr "Arquivos"
+msgstr "Mostrar em Arquivos"
+
+#: editor/property_editor.cpp
+msgid "Convert To %s"
+msgstr "Converter Para %s"
#: editor/property_editor.cpp
msgid "Error loading file: Not a resource!"
msgstr "Erro ao carregar arquivo: Não é um recurso!"
#: editor/property_editor.cpp
-#, fuzzy
msgid "Selected node is not a Viewport!"
-msgstr "Selecionar Nó(s) para Importar"
+msgstr "Nó selecionado não é uma Viewport!"
#: editor/property_editor.cpp
-#, fuzzy
msgid "Pick a Node"
-msgstr "Selecione um Nó"
+msgstr "Escolha um Nó"
#: editor/property_editor.cpp
msgid "Bit %d, val %d."
@@ -6601,14 +6136,16 @@ msgid "Sections:"
msgstr "Seções:"
#: editor/property_selector.cpp
-#, fuzzy
msgid "Select Property"
-msgstr "Selecionar Pontos"
+msgstr "Selecionar Propriedade"
+
+#: editor/property_selector.cpp
+msgid "Select Virtual Method"
+msgstr "Selecionar Método Virtual"
#: editor/property_selector.cpp
-#, fuzzy
msgid "Select Method"
-msgstr "Modo de Seleção (Q)"
+msgstr "Selecionar Mtéodo"
#: editor/pvrtc_compress.cpp
msgid "Could not execute PVRTC tool:"
@@ -6624,7 +6161,7 @@ msgstr "Reparentar Nó"
#: editor/reparent_dialog.cpp
msgid "Reparent Location (Select new Parent):"
-msgstr "Local para Reparentar (Selecione Novo Pai):"
+msgstr "Local para Reparentar (Selecione novo Pai):"
#: editor/reparent_dialog.cpp
msgid "Keep Global Transform"
@@ -6634,26 +6171,6 @@ msgstr "Manter Transformação Global"
msgid "Reparent"
msgstr "Reparentar"
-#: editor/resources_dock.cpp
-msgid "Create New Resource"
-msgstr "Criar Novo Recurso"
-
-#: editor/resources_dock.cpp
-msgid "Open Resource"
-msgstr "Abrir Recurso"
-
-#: editor/resources_dock.cpp
-msgid "Save Resource"
-msgstr "Salvar Recurso"
-
-#: editor/resources_dock.cpp
-msgid "Resource Tools"
-msgstr "Ferramentas de Recurso"
-
-#: editor/resources_dock.cpp
-msgid "Make Local"
-msgstr "Tornar Local"
-
#: editor/run_settings_dialog.cpp
msgid "Run Mode:"
msgstr "Modo de Início:"
@@ -6680,9 +6197,8 @@ msgid "OK"
msgstr "OK"
#: editor/scene_tree_dock.cpp
-#, fuzzy
msgid "No parent to instance the scenes at."
-msgstr "Sem nó pai onde instanciar um filho."
+msgstr "Sem nó pai onde instanciar as cenas."
#: editor/scene_tree_dock.cpp
msgid "Error loading scene from %s"
@@ -6726,7 +6242,7 @@ msgstr "Excluir Nó(s)?"
#: editor/scene_tree_dock.cpp
msgid "Can not perform with the root node."
-msgstr ""
+msgstr "Não é possível trabalhar com o nó raiz."
#: editor/scene_tree_dock.cpp
msgid "This operation can't be done on instanced scenes."
@@ -6781,17 +6297,8 @@ msgid "Error duplicating scene to save it."
msgstr "Erro duplicando cena ao salvar."
#: editor/scene_tree_dock.cpp
-#, fuzzy
msgid "Sub-Resources:"
-msgstr "Recursos:"
-
-#: editor/scene_tree_dock.cpp
-msgid "Edit Groups"
-msgstr "Editar Grupos"
-
-#: editor/scene_tree_dock.cpp
-msgid "Edit Connections"
-msgstr "Editar Conexões"
+msgstr "Sub-Recursos:"
#: editor/scene_tree_dock.cpp
msgid "Clear Inheritance"
@@ -6818,14 +6325,12 @@ msgid "Change Type"
msgstr "Alterar Tipo"
#: editor/scene_tree_dock.cpp
-#, fuzzy
msgid "Attach Script"
msgstr "Adicionar Script"
#: editor/scene_tree_dock.cpp
-#, fuzzy
msgid "Clear Script"
-msgstr "Criar Script"
+msgstr "Remover Script"
#: editor/scene_tree_dock.cpp
msgid "Merge From Scene"
@@ -6836,9 +6341,8 @@ msgid "Save Branch as Scene"
msgstr "Salvar Ramo como Cena"
#: editor/scene_tree_dock.cpp
-#, fuzzy
msgid "Copy Node Path"
-msgstr "Copiar Caminho"
+msgstr "Copiar Caminho do Nó"
#: editor/scene_tree_dock.cpp
msgid "Delete (No Confirm)"
@@ -6857,19 +6361,16 @@ msgstr ""
"existe um nó raiz."
#: editor/scene_tree_dock.cpp
-#, fuzzy
msgid "Filter nodes"
-msgstr "Filtros"
+msgstr "Filtrar nós"
#: editor/scene_tree_dock.cpp
-#, fuzzy
msgid "Attach a new or existing script for the selected node."
-msgstr "Criar um script novo para o nó selecionado."
+msgstr "Adicionar um script novo ou existente para o nó selecionado."
#: editor/scene_tree_dock.cpp
-#, fuzzy
msgid "Clear a script for the selected node."
-msgstr "Criar um script novo para o nó selecionado."
+msgstr "Remove um script do nó selecionado."
#: editor/scene_tree_dock.cpp
msgid "Clear Inheritance? (No Undo!)"
@@ -6889,51 +6390,59 @@ msgstr "Alternar CanvasItem Visível"
#: editor/scene_tree_editor.cpp
msgid "Node configuration warning:"
-msgstr ""
+msgstr "Aviso de configuração de nó:"
#: editor/scene_tree_editor.cpp
msgid ""
"Node has connection(s) and group(s)\n"
"Click to show signals dock."
msgstr ""
+"O nó tem conexões e grupos\n"
+"Clique para mostrar o painel de sinais."
#: editor/scene_tree_editor.cpp
msgid ""
"Node has connections.\n"
"Click to show signals dock."
msgstr ""
+"O nó tem conexões.\n"
+"Clique para mostrar o painel de sinais."
#: editor/scene_tree_editor.cpp
msgid ""
"Node is in group(s).\n"
"Click to show groups dock."
msgstr ""
+"O nó tem grupos.\n"
+"Clique para mostrar o painel de grupos."
#: editor/scene_tree_editor.cpp
msgid "Instance:"
msgstr "Instância:"
#: editor/scene_tree_editor.cpp
-#, fuzzy
msgid "Open script"
-msgstr "Próximo Script"
+msgstr "Abrir script"
#: editor/scene_tree_editor.cpp
msgid ""
"Node is locked.\n"
"Click to unlock"
msgstr ""
+"O nó está travado.\n"
+"Clique para destravar"
#: editor/scene_tree_editor.cpp
msgid ""
"Children are not selectable.\n"
"Click to make selectable"
msgstr ""
+"Os filhos não são selecionáveis.\n"
+"Clique para fazê-los selecionáveis"
#: editor/scene_tree_editor.cpp
-#, fuzzy
msgid "Toggle Visibility"
-msgstr "Alternar Spatial Visível"
+msgstr "Alternar Visiblidade"
#: editor/scene_tree_editor.cpp
msgid "Invalid node name, the following characters are not allowed:"
@@ -6949,26 +6458,23 @@ msgstr "Ãrvore de Cena (Nós):"
#: editor/scene_tree_editor.cpp
msgid "Node Configuration Warning!"
-msgstr ""
+msgstr "Aviso de Configuração de Nó!"
#: editor/scene_tree_editor.cpp
msgid "Select a Node"
msgstr "Selecione um Nó"
#: editor/script_create_dialog.cpp
-#, fuzzy
msgid "Error loading template '%s'"
-msgstr "Erro ao carregar imagem:"
+msgstr "Erro ao carregar modelo '%s'"
#: editor/script_create_dialog.cpp
-#, fuzzy
msgid "Error - Could not create script in filesystem."
-msgstr "Não foi possível criar o script no sistema de arquivos."
+msgstr "Erro - Não foi possível criar o script no sistema de arquivos."
#: editor/script_create_dialog.cpp
-#, fuzzy
msgid "Error loading script from %s"
-msgstr "Erro ao carregar cena de %s"
+msgstr "Erro ao carregar script de %s"
#: editor/script_create_dialog.cpp
msgid "N/A"
@@ -6987,74 +6493,76 @@ msgid "Invalid base path"
msgstr "Caminho base inválido"
#: editor/script_create_dialog.cpp
+msgid "Directory of the same name exists"
+msgstr "Um diretório de mesmo nome existe"
+
+#: editor/script_create_dialog.cpp
+msgid "File exists, will be reused"
+msgstr "O arquivo existe, será reaproveitado"
+
+#: editor/script_create_dialog.cpp
msgid "Invalid extension"
msgstr "Extensão inválida"
#: editor/script_create_dialog.cpp
msgid "Wrong extension chosen"
-msgstr ""
+msgstr "Extensão errada escolhida"
#: editor/script_create_dialog.cpp
-#, fuzzy
msgid "Invalid Path"
-msgstr "Caminho inválido."
+msgstr "Caminho Inválido"
#: editor/script_create_dialog.cpp
msgid "Invalid class name"
msgstr "Nome de classe inválido"
#: editor/script_create_dialog.cpp
-#, fuzzy
msgid "Invalid inherited parent name or path"
-msgstr "Nome da propriedade de índice inválido."
+msgstr "Nome ou caminho de pai herdado invláido"
#: editor/script_create_dialog.cpp
-#, fuzzy
msgid "Script valid"
-msgstr "Script"
+msgstr "Script válido"
#: editor/script_create_dialog.cpp
msgid "Allowed: a-z, A-Z, 0-9 and _"
-msgstr ""
+msgstr "Permitidos: a-z, A-Z, 0-9 e _"
#: editor/script_create_dialog.cpp
msgid "Built-in script (into scene file)"
-msgstr ""
+msgstr "Script embutido (no arquivo da cena)"
#: editor/script_create_dialog.cpp
-#, fuzzy
msgid "Create new script file"
-msgstr "Criar Script"
+msgstr "Criar novo arquivo de script"
#: editor/script_create_dialog.cpp
-#, fuzzy
msgid "Load existing script file"
-msgstr "Próximo Script"
+msgstr "Carregar arquivo de script existente"
+
+#: editor/script_create_dialog.cpp
+msgid "Language"
+msgstr "Idioma"
#: editor/script_create_dialog.cpp
-#, fuzzy
msgid "Inherits"
-msgstr "Herda de:"
+msgstr "Herda de"
#: editor/script_create_dialog.cpp
-#, fuzzy
msgid "Class Name"
-msgstr "Nome da Classe:"
+msgstr "Nome da Classe"
#: editor/script_create_dialog.cpp
-#, fuzzy
msgid "Template"
-msgstr "Remover Item"
+msgstr "Modelo"
#: editor/script_create_dialog.cpp
-#, fuzzy
msgid "Built-in Script"
msgstr "Script Embutido"
#: editor/script_create_dialog.cpp
-#, fuzzy
msgid "Attach Node Script"
-msgstr "Criar Script para Nó"
+msgstr "Adicionar Script ao Nó"
#: editor/script_editor_debugger.cpp
msgid "Bytes:"
@@ -7077,6 +6585,10 @@ msgid "Function:"
msgstr "Função:"
#: editor/script_editor_debugger.cpp
+msgid "Pick one or more items from the list to display the graph."
+msgstr "Escolhe um ou mais itens da lista para mostrar o gráfico."
+
+#: editor/script_editor_debugger.cpp
msgid "Errors"
msgstr "Erros"
@@ -7138,7 +6650,7 @@ msgstr "Monitores"
#: editor/script_editor_debugger.cpp
msgid "List of Video Memory Usage by Resource:"
-msgstr "Listagem de Uso Memória de Vídeo por Recurso:"
+msgstr "Lista de Uso Memória de Vídeo por Recurso:"
#: editor/script_editor_debugger.cpp
msgid "Total:"
@@ -7157,6 +6669,10 @@ msgid "Type"
msgstr "Tipo"
#: editor/script_editor_debugger.cpp
+msgid "Format"
+msgstr "Formato"
+
+#: editor/script_editor_debugger.cpp
msgid "Usage"
msgstr "Uso"
@@ -7190,7 +6706,7 @@ msgstr "Mudar Raio da Luz"
#: editor/spatial_editor_gizmos.cpp
msgid "Change AudioStreamPlayer3D Emission Angle"
-msgstr ""
+msgstr "Mudar o Ângulo de Emissão do AudioStreamPlayer3D"
#: editor/spatial_editor_gizmos.cpp
msgid "Change Camera FOV"
@@ -7226,19 +6742,34 @@ msgstr "Alterar a Extensão do Notificador"
#: editor/spatial_editor_gizmos.cpp
msgid "Change Particles AABB"
-msgstr ""
+msgstr "Mudar o AABB das Partículas"
#: editor/spatial_editor_gizmos.cpp
-#, fuzzy
msgid "Change Probe Extents"
-msgstr "Alterar a Extensão do Notificador"
+msgstr "Alterar a Extensão da Sonda"
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Library"
+msgstr "Biblioteca"
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Status"
+msgstr "Estado"
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Libraries: "
+msgstr "Bibliotecas: "
+
+#: modules/gdnative/register_types.cpp
+msgid "GDNative"
+msgstr "GDNative"
#: modules/gdscript/gd_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Invalid type argument to convert(), use TYPE_* constants."
msgstr "Argumento de tipo inválido para convert(), use constantes TYPE_*."
-#: modules/gdscript/gd_functions.cpp
+#: modules/gdscript/gd_functions.cpp modules/mono/glue/glue_header.h
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Not enough bytes for decoding bytes, or invalid format."
msgstr "Não há bytes suficientes para decodificar, ou o formato é inválido."
@@ -7279,152 +6810,135 @@ msgstr "Dicionário de instância inválido (subclasses inválidas)"
#: modules/gdscript/gd_functions.cpp
msgid "Object can't provide a length."
-msgstr ""
+msgstr "Objeto não pôde fornecer um comprimento."
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "GridMap Delete Selection"
-msgstr "Excluir Selecionados"
+msgstr "Excluir Seleção do Gridap"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "GridMap Duplicate Selection"
-msgstr "Duplicar Seleção"
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "GridMap Paint"
-msgstr ""
+msgstr "Duplicar Seleção do GridMap"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Snap View"
-msgstr "Visão Superior"
+msgstr "Ancorar Vista"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Prev Level (%sDown Wheel)"
-msgstr ""
+msgstr "Nível anterior ("
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Next Level (%sUp Wheel)"
-msgstr ""
+msgstr "Nível seguinte ("
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Clip Disabled"
-msgstr "Desabilitado"
+msgstr "Corte Desabilitado"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Clip Above"
-msgstr ""
+msgstr "Cortar Acima"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Clip Below"
-msgstr ""
+msgstr "Cortar Abaixo"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Edit X Axis"
-msgstr ""
+msgstr "Editar Eixo X"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Edit Y Axis"
-msgstr ""
+msgstr "Eduitar Eixo Y"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Edit Z Axis"
-msgstr ""
+msgstr "Editar Eixo Z"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Cursor Rotate X"
-msgstr "Ctrl: Rotaciona"
+msgstr "Rotacionar Cursor em X"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Cursor Rotate Y"
-msgstr "Ctrl: Rotaciona"
+msgstr "Rotacionar Cursor em Y"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Cursor Rotate Z"
-msgstr "Ctrl: Rotaciona"
+msgstr "Rotacionar Cursor em Z"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Cursor Back Rotate X"
-msgstr ""
+msgstr "Contra-rotacionar Cursor em X"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Cursor Back Rotate Y"
-msgstr ""
+msgstr "Rotacionar Cursor em Y"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Cursor Back Rotate Z"
-msgstr ""
+msgstr "Contra-rotacionar Cursor em Z"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Cursor Clear Rotation"
-msgstr ""
+msgstr "Limpar Rotação do Cursor"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Create Area"
-msgstr "Criar Novo"
+msgstr "Criar Ãrea"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Create Exterior Connector"
-msgstr "Criar Novo Projeto"
+msgstr "Criar Conector de Exterior"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Erase Area"
-msgstr "Apagar TileMap"
+msgstr "Apagar Ãrea"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Selection -> Duplicate"
-msgstr "Apenas na Seleção"
+msgstr "Seleção -> Duplicar"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Selection -> Clear"
-msgstr "Apenas na Seleção"
+msgstr "Seleção -> Limpar"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "GridMap Settings"
-msgstr "Configurações do Snap"
+msgstr "Configurações do GridMap"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Pick Distance:"
-msgstr "Instância:"
+msgstr "Escolha uma Distância:"
-#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
-msgid "Tiles"
-msgstr " Arquivos"
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "Areas"
-msgstr ""
+#: modules/mono/editor/mono_bottom_panel.cpp
+msgid "Builds"
+msgstr "Compilações"
#: modules/visual_script/visual_script.cpp
msgid ""
"A node yielded without working memory, please read the docs on how to yield "
"properly!"
msgstr ""
+"Um nó fez um yield sem memória de trabalho, por favor leia a documentação "
+"sobre como usar yield corretamente!"
#: modules/visual_script/visual_script.cpp
msgid ""
"Node yielded, but did not return a function state in the first working "
"memory."
msgstr ""
+"Nó entrou em yield, mas não retornou um estado de função na primeira memória "
+"de trabalho."
#: modules/visual_script/visual_script.cpp
msgid ""
"Return value must be assigned to first element of node working memory! Fix "
"your node please."
msgstr ""
+"Um valor de retorno deve ser atribuído ao primeiro elemento da memória "
+"corrente do nó! Conserte seu node, por favor."
#: modules/visual_script/visual_script.cpp
msgid "Node returned an invalid sequence output: "
@@ -7432,36 +6946,31 @@ msgstr "O nó retornou uma saída de sequência inválida: "
#: modules/visual_script/visual_script.cpp
msgid "Found sequence bit but not the node in the stack, report bug!"
-msgstr ""
+msgstr "Sequência encontrada mas o nó não está na pilha, reporte um bug!"
#: modules/visual_script/visual_script.cpp
msgid "Stack overflow with stack depth: "
-msgstr ""
+msgstr "Sobrecarga da pilha com profundidade: "
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Change Signal Arguments"
-msgstr "Editar Argumentos do Sinal:"
+msgstr "Editar Argumentos do Sinal"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Change Argument Type"
-msgstr "Alterar Tipo de Valor do Vetor"
+msgstr "Alterar Tipo do Argumento"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Change Argument name"
-msgstr "Alterar Nome de Entrada"
+msgstr "Alterar Nome do Argumento"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Set Variable Default Value"
-msgstr "Alterar Valor Padrão"
+msgstr "Definir o Valor Padrão da Variável"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Set Variable Type"
-msgstr "Editar Variável:"
+msgstr "Definir o Tipo da Variável"
#: modules/visual_script/visual_script_editor.cpp
msgid "Functions:"
@@ -7504,7 +7013,6 @@ msgid "Add Signal"
msgstr "Adicionar Sinal"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Change Expression"
msgstr "Alterar Expressão"
@@ -7513,14 +7021,12 @@ msgid "Add Node"
msgstr "Adicionar Nó"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Remove VisualScript Nodes"
-msgstr "Remover Chaves Invalidas"
+msgstr "Remover Nós VisualScript"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Duplicate VisualScript Nodes"
-msgstr "Duplicar Nó(s) de Grafo(s)"
+msgstr "Duplicar Nós VisualScript"
#: modules/visual_script/visual_script_editor.cpp
msgid "Hold Meta to drop a Getter. Hold Shift to drop a generic signature."
@@ -7567,24 +7073,20 @@ msgid "Add Setter Property"
msgstr "Adicionar Setter de Propriedade"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Change Base Type"
-msgstr "Alterar Tipo"
+msgstr "Mudar Tipo Base"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Move Node(s)"
-msgstr "Remover Nó(s)"
+msgstr "Mover Nó(s)"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Remove VisualScript Node"
-msgstr "Remover Nó de Shader Graph"
+msgstr "Remover Nó VisualScript"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Connect Nodes"
-msgstr "Conectar ao Nó:"
+msgstr "Conectar Nós"
#: modules/visual_script/visual_script_editor.cpp
msgid "Condition"
@@ -7595,9 +7097,8 @@ msgid "Sequence"
msgstr "Sequência"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Switch"
-msgstr "Mudar"
+msgstr "Trocar"
#: modules/visual_script/visual_script_editor.cpp
msgid "Iterator"
@@ -7612,47 +7113,48 @@ msgid "Return"
msgstr "Retornar"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
+msgid "Call"
+msgstr "Chamar"
+
+#: modules/visual_script/visual_script_editor.cpp
msgid "Get"
msgstr "Obter"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
+msgid "Script already has function '%s'"
+msgstr "Script já tem uma função '%s'"
+
+#: modules/visual_script/visual_script_editor.cpp
msgid "Change Input Value"
-msgstr "Alterar Nome de Entrada"
+msgstr "Alterar Valor de Entrada"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Can't copy the function node."
-msgstr "Não é possível operar em \"..\""
+msgstr "Não é possível copiar o nó de função."
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Clipboard is empty!"
-msgstr "Recurso da área de transferência está vazio!"
+msgstr "Ãrea de transferência vazia!"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Paste VisualScript Nodes"
-msgstr "Colar Nós"
+msgstr "Colar Nós VisualScript"
#: modules/visual_script/visual_script_editor.cpp
msgid "Remove Function"
msgstr "Remover Função"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Edit Variable"
-msgstr "Editar Variável:"
+msgstr "Editar Variável"
#: modules/visual_script/visual_script_editor.cpp
msgid "Remove Variable"
msgstr "Remover Variável"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Edit Signal"
-msgstr "Editando Sinal:"
+msgstr "Editar Sinal"
#: modules/visual_script/visual_script_editor.cpp
msgid "Remove Signal"
@@ -7724,21 +7226,19 @@ msgstr "Nome da propriedade de índice inválido."
#: modules/visual_script/visual_script_func_nodes.cpp
msgid "Base object is not a Node!"
-msgstr ""
+msgstr "Objeto base não é um Node!"
#: modules/visual_script/visual_script_func_nodes.cpp
-#, fuzzy
msgid "Path does not lead Node!"
-msgstr "O caminho não é local"
+msgstr "O caminho não leva a um Node!"
#: modules/visual_script/visual_script_func_nodes.cpp
msgid "Invalid index property name '%s' in node %s."
-msgstr ""
+msgstr "Nome de propriedade '%s' inválido no nó %s."
#: modules/visual_script/visual_script_nodes.cpp
-#, fuzzy
msgid ": Invalid argument of type: "
-msgstr "Nome de classe pai inválido"
+msgstr ": Argumento inválido do tipo: "
#: modules/visual_script/visual_script_nodes.cpp
msgid ": Invalid arguments: "
@@ -7746,21 +7246,25 @@ msgstr ": Argumentos inválidos: "
#: modules/visual_script/visual_script_nodes.cpp
msgid "VariableGet not found in script: "
-msgstr ""
+msgstr "VariableGet não encontrada no script: "
#: modules/visual_script/visual_script_nodes.cpp
msgid "VariableSet not found in script: "
-msgstr ""
+msgstr "VariableSet não encontrada no script: "
#: modules/visual_script/visual_script_nodes.cpp
msgid "Custom node has no _step() method, can't process graph."
msgstr ""
+"Nó customizado não tem um método _step(), não foi possível processar o "
+"gráfico."
#: modules/visual_script/visual_script_nodes.cpp
msgid ""
"Invalid return value from _step(), must be integer (seq out), or string "
"(error)."
msgstr ""
+"Valor de retorno da _step() inválido, deve ser um inteiro (seq out), ou "
+"string (erro)."
#: platform/javascript/export/export.cpp
msgid "Run in Browser"
@@ -7771,18 +7275,16 @@ msgid "Run exported HTML in the system's default browser."
msgstr "Rodar HTML exportado no navegador padrão do sistema."
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Could not write file:\n"
-msgstr "Não se pôde achar tile:"
+msgstr "Não foi possível escrever o arquivo:\n"
#: platform/javascript/export/export.cpp
msgid "Could not read file:\n"
msgstr "Não foi possível ler o arquivo:\n"
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Could not open template for export:\n"
-msgstr "Não foi possível criar a pasta."
+msgstr "Não foi possível abrir o modelo para exportar:\n"
#: scene/2d/animated_sprite.cpp
msgid ""
@@ -7880,6 +7382,8 @@ msgid ""
"A material to process the particles is not assigned, so no behavior is "
"imprinted."
msgstr ""
+"Um material para processar partículas não foi atribuído, então nenhum "
+"comportamento será aplicado."
#: scene/2d/path_2d.cpp
msgid "PathFollow2D only works when set as a child of a Path2D node."
@@ -7892,6 +7396,9 @@ msgid ""
"by the physics engine when running.\n"
"Change the size in children collision shapes instead."
msgstr ""
+"Mudanças de tamanho no RigidBody2D (nos modos Character ou Rigid) serão "
+"sobrescritas pelo motor de física ao executar.\n"
+"Ao invés disso, mude o tamanho nas formas de colisão filhas."
#: scene/2d/remote_transform_2d.cpp
msgid "Path property must point to a valid Node2D node to work."
@@ -7925,31 +7432,35 @@ msgstr ""
#: scene/3d/arvr_nodes.cpp
msgid "ARVRCamera must have an ARVROrigin node as its parent"
-msgstr ""
+msgstr "ARVRCamera deve ter um nó ARVROrigin como seu pai"
#: scene/3d/arvr_nodes.cpp
msgid "ARVRController must have an ARVROrigin node as its parent"
-msgstr ""
+msgstr "ARVRController deve ter um nó ARVROrigin como seu pai"
#: scene/3d/arvr_nodes.cpp
msgid ""
"The controller id must not be 0 or this controller will not be bound to an "
"actual controller"
msgstr ""
+"A id do controlador não deve ser 0 ou este controlador não será atribúido a "
+"um controlador real"
#: scene/3d/arvr_nodes.cpp
msgid "ARVRAnchor must have an ARVROrigin node as its parent"
-msgstr ""
+msgstr "ARVRAnchor deve ter um nó ARVROrigin como seu pai"
#: scene/3d/arvr_nodes.cpp
msgid ""
"The anchor id must not be 0 or this anchor will not be bound to an actual "
"anchor"
msgstr ""
+"A id da âncore não deve ser 0 ou essa âncora não será atribuída a uma âncore "
+"geral"
#: scene/3d/arvr_nodes.cpp
msgid "ARVROrigin requires an ARVRCamera child node"
-msgstr ""
+msgstr "ARVROrigin necessita um nó ARVRCamera como filho"
#: scene/3d/collision_polygon.cpp
msgid ""
@@ -8001,6 +7512,7 @@ msgstr ""
msgid ""
"Nothing is visible because meshes have not been assigned to draw passes."
msgstr ""
+"Nada está visível porque as malhas não foram atribuídas a passes de desenho."
#: scene/3d/physics_body.cpp
msgid ""
@@ -8008,11 +7520,13 @@ msgid ""
"the physics engine when running.\n"
"Change the size in children collision shapes instead."
msgstr ""
+"Mudanças de tamanho no RigidBody (nos modos Character e Rigid) serão "
+"sobrescitas pelo motor de física ao executar.\n"
+"Ao invés disso, mude o tamanho nas formas de colisão filhas."
#: scene/3d/remote_transform.cpp
-#, fuzzy
msgid "Path property must point to a valid Spatial node to work."
-msgstr "A propriedade Caminho deve apontar a um nó Particles2D para funcionar."
+msgstr "A propriedade Caminho deve apontar para um nó Spatial para funcionar."
#: scene/3d/scenario_fx.cpp
msgid ""
@@ -8029,16 +7543,27 @@ msgstr ""
"Um recurso do tipo SpriteFrames deve ser criado ou definido na propriedade "
"\"Frames\" para que o nó AnimatedSprite mostre quadros."
+#: scene/3d/vehicle_body.cpp
+msgid ""
+"VehicleWheel serves to provide a wheel system to a VehicleBody. Please use "
+"it as a child of a VehicleBody."
+msgstr ""
+"VehiceWheel serve para fornecer um sistema de rodas para um VehicleBody. Por "
+"favor, use ele como um filho de um VehicleBody."
+
#: scene/gui/color_picker.cpp
-#, fuzzy
msgid "Raw Mode"
-msgstr "Modo Panorâmico"
+msgstr "Modo Bruto"
#: scene/gui/color_picker.cpp
msgid "Add current color as a preset"
msgstr "Adicionar cor atual como uma predefinição"
#: scene/gui/dialogs.cpp
+msgid "Cancel"
+msgstr "Cancelar"
+
+#: scene/gui/dialogs.cpp
msgid "Alert!"
msgstr "Alerta!"
@@ -8046,10 +7571,6 @@ msgstr "Alerta!"
msgid "Please Confirm..."
msgstr "Confirme Por Favor..."
-#: scene/gui/input_action.cpp
-msgid "Ctrl+"
-msgstr "Ctrl+"
-
#: scene/gui/popup.cpp
msgid ""
"Popups will hide by default unless you call popup() or any of the popup*() "
@@ -8066,12 +7587,17 @@ msgid ""
"Use a container as child (VBox,HBox,etc), or a Control and set the custom "
"minimum size manually."
msgstr ""
+"Um ScrollContainer foi feito para trabalhar com um componente filho único.\n"
+"Use um container como filho (VBox, HBox, etc) ou um Control e defina o "
+"tamanho mínimo manualmente."
#: scene/main/scene_tree.cpp
msgid ""
"Default Environment as specified in Project Setings (Rendering -> Viewport -"
"> Default Environment) could not be loaded."
msgstr ""
+"O Ambiente Padrão como especificado nas Configurações de Projeto "
+"(Renderização - Viewport -> Ambiente Padrão) não pôde ser carregado."
#: scene/main/viewport.cpp
msgid ""
@@ -8085,6 +7611,645 @@ msgstr ""
"para que ele possa ter um tamanho. Caso contrário, defina-o como destino de "
"render e atribua sua textura interna a algum nó para exibir."
+#: scene/resources/dynamic_font.cpp
+msgid "Error initializing FreeType."
+msgstr "Erro ao inicializar FreeType."
+
+#: scene/resources/dynamic_font.cpp
+msgid "Unknown font format."
+msgstr "Formato de fonte desconhecido."
+
+#: scene/resources/dynamic_font.cpp
+msgid "Error loading font."
+msgstr "Erro ao carregar fonte."
+
+#: scene/resources/dynamic_font.cpp
+msgid "Invalid font size."
+msgstr "Tamanho de fonte inválido."
+
+#~ msgid "Filter:"
+#~ msgstr "Filtro:"
+
+#~ msgid "' parsing of config failed."
+#~ msgstr "' falha no processamento de configurações."
+
+#~ msgid "Theme"
+#~ msgstr "Tema"
+
+#~ msgid "Method List For '%s':"
+#~ msgstr "Lista de Métodos para \"%s\":"
+
+#~ msgid "Arguments:"
+#~ msgstr "Argumentos:"
+
+#~ msgid "Return:"
+#~ msgstr "Retornar:"
+
+#~ msgid "Added:"
+#~ msgstr "Adicionado:"
+
+#~ msgid "Removed:"
+#~ msgstr "Removido:"
+
+#~ msgid "Error saving atlas:"
+#~ msgstr "Erro ao salvar atlas:"
+
+#~ msgid "Could not save atlas subtexture:"
+#~ msgstr "Não foi possível salvar Subtextura do Atlas:"
+
+#~ msgid "Exporting for %s"
+#~ msgstr "Exportando para %s"
+
+#~ msgid "Setting Up.."
+#~ msgstr "Ajustando..."
+
+#~ msgid "Error loading scene."
+#~ msgstr "Erro ao carregar cena."
+
+#~ msgid "Re-Import"
+#~ msgstr "Reimportar"
+
+#~ msgid "Please wait for scan to complete."
+#~ msgstr "Por favor aguarde a verificação completar."
+
+#~ msgid "Current scene must be saved to re-import."
+#~ msgstr "Cena Atual só deve ser salva para re-importação."
+
+#~ msgid "Save & Re-Import"
+#~ msgstr "Salvar e Re-Importar"
+
+#~ msgid "Re-Importing"
+#~ msgstr "Re-Importando"
+
+#~ msgid "Re-Import Changed Resources"
+#~ msgstr "Re-Importar Recursos Alterados"
+
+#~ msgid "Loading Export Templates"
+#~ msgstr "Carregando Modelos de Exportação"
+
+#~ msgid ""
+#~ "\n"
+#~ "Status: Needs Re-Import"
+#~ msgstr ""
+#~ "\n"
+#~ "Status: Necessita Re-Importação"
+
+#~ msgid "Same source and destination files, doing nothing."
+#~ msgstr "Mesmos arquivos de destino e origem, nada a fazer."
+
+#~ msgid "Target file exists, can't overwrite. Delete first."
+#~ msgstr ""
+#~ "Arquivo alvo existe, não é possível sobrescrever. Delete-o primeiro."
+
+#~ msgid "Same source and destination paths, doing nothing."
+#~ msgstr "Mesmo caminhos de destino e origem, nada a fazer."
+
+#~ msgid "Can't move directories to within themselves."
+#~ msgstr "Não é possível mover diretórios para dentro de si mesmos."
+
+#~ msgid "Can't rename deps for:\n"
+#~ msgstr "Não foi possível renomear dependências para:\n"
+
+#~ msgid "Error moving file:\n"
+#~ msgstr "Erro ao mover arquivo:\n"
+
+#~ msgid "Pick New Name and Location For:"
+#~ msgstr "Escolha Novo Nome e Localização Para:"
+
+#~ msgid "No files selected!"
+#~ msgstr "Nenhum arquivo selecionado!"
+
+#~ msgid "Info"
+#~ msgstr "Informação"
+
+#~ msgid "Re-Import.."
+#~ msgstr "Re-importar..."
+
+#~ msgid "No bit masks to import!"
+#~ msgstr "Sem máscaras de bits para importar!"
+
+#~ msgid "Target path is empty."
+#~ msgstr "Caminho destino está vazio."
+
+#~ msgid "Target path must be a complete resource path."
+#~ msgstr "Caminho destino deve ser um caminho completo a um recurso."
+
+#~ msgid "Target path must exist."
+#~ msgstr "Caminho destino deve existir."
+
+#~ msgid "Save path is empty!"
+#~ msgstr "Caminho de salvamento vazio!"
+
+#~ msgid "Import BitMasks"
+#~ msgstr "Importar Máscara de Bits"
+
+#~ msgid "Source Texture(s):"
+#~ msgstr "Textura(s) de Origem:"
+
+#~ msgid "Target Path:"
+#~ msgstr "Caminho Destino:"
+
+#~ msgid "Accept"
+#~ msgstr "Aceitar"
+
+#~ msgid "Bit Mask"
+#~ msgstr "Máscara de Bits"
+
+#~ msgid "No source font file!"
+#~ msgstr "Falta arquivo de fonte origem!"
+
+#~ msgid "No target font resource!"
+#~ msgstr "Falta recurso de fonte destino!"
+
+#~ msgid ""
+#~ "Invalid file extension.\n"
+#~ "Please use .font."
+#~ msgstr ""
+#~ "Extensão de arquivo inválida.\n"
+#~ "Por favor use .font."
+
+#~ msgid "Couldn't save font."
+#~ msgstr "Não se pôde salvar fonte."
+
+#~ msgid "Source Font:"
+#~ msgstr "Fonte Origem:"
+
+#~ msgid "Source Font Size:"
+#~ msgstr "Tamanho da Fonte de Origem:"
+
+#~ msgid "Dest Resource:"
+#~ msgstr "Recurso Destino:"
+
+#~ msgid "The quick brown fox jumps over the lazy dog."
+#~ msgstr ""
+#~ "À noite, vovô Kowalsky vê o ímã cair no pé do pinguim queixoso e vovó põe "
+#~ "açúcar no chá de tâmaras do jabuti feliz."
+
+#~ msgid "Test:"
+#~ msgstr "Teste:"
+
+#~ msgid "Options:"
+#~ msgstr "Opções:"
+
+#~ msgid "Font Import"
+#~ msgstr "Importar Fonte"
+
+#~ msgid ""
+#~ "This file is already a Godot font file, please supply a BMFont type file "
+#~ "instead."
+#~ msgstr ""
+#~ "Este arquivo já é um arquivo de fonte Godot, por favor forneça um arquivo "
+#~ "BMFont."
+
+#~ msgid "Failed opening as BMFont file."
+#~ msgstr "Falha ao abrir como arquivo BMFont."
+
+#~ msgid "Invalid font custom source."
+#~ msgstr "Origem personalizada da fonte inválida."
+
+#~ msgid "No meshes to import!"
+#~ msgstr "Sem meshes para importar!"
+
+#~ msgid "Single Mesh Import"
+#~ msgstr "Importar Única Mesh"
+
+#~ msgid "Source Mesh(es):"
+#~ msgstr "Origem de Mesh(es):"
+
+#~ msgid "Surface %d"
+#~ msgstr "Superfície %d"
+
+#~ msgid "No samples to import!"
+#~ msgstr "Sem amostras para importar!"
+
+#~ msgid "Import Audio Samples"
+#~ msgstr "Importar Amostras de Ãudio"
+
+#~ msgid "Source Sample(s):"
+#~ msgstr "Amostra(s) de Origem:"
+
+#~ msgid "Audio Sample"
+#~ msgstr "Amostra de Ãudio"
+
+#~ msgid "New Clip"
+#~ msgstr "Novo Clipe"
+
+#~ msgid "Flags"
+#~ msgstr "Flags"
+
+#~ msgid "Bake FPS:"
+#~ msgstr "Precalcular FPS:"
+
+#~ msgid "Optimizer"
+#~ msgstr "Otimizador"
+
+#~ msgid "Max Linear Error"
+#~ msgstr "Erro Linear Máximo"
+
+#~ msgid "Max Angular Error"
+#~ msgstr "Erro Angular Máximo"
+
+#~ msgid "Max Angle"
+#~ msgstr "Ângulo Máximo"
+
+#~ msgid "Clips"
+#~ msgstr "Clipes"
+
+#~ msgid "Start(s)"
+#~ msgstr "Início(s)"
+
+#~ msgid "End(s)"
+#~ msgstr "Fim(ns)"
+
+#~ msgid "Filters"
+#~ msgstr "Filtros"
+
+#~ msgid "Source path is empty."
+#~ msgstr "Caminho de origem está vazio."
+
+#~ msgid "Couldn't load post-import script."
+#~ msgstr "Não se pôde carregar script pós-importação."
+
+#~ msgid "Invalid/broken script for post-import."
+#~ msgstr "Script pós-importação inválido/quebrado."
+
+#~ msgid "Error importing scene."
+#~ msgstr "Erro ao importar cena."
+
+#~ msgid "Import 3D Scene"
+#~ msgstr "Importar Cena 3D"
+
+#~ msgid "Source Scene:"
+#~ msgstr "Cena de Origem:"
+
+#~ msgid "Same as Target Scene"
+#~ msgstr "Mesma da Cena Destino"
+
+#~ msgid "Shared"
+#~ msgstr "Compartilhado"
+
+#~ msgid "Target Texture Folder:"
+#~ msgstr "Pasta Destino para Textura:"
+
+#~ msgid "Post-Process Script:"
+#~ msgstr "Script de Pós-Processamento:"
+
+#~ msgid "Custom Root Node Type:"
+#~ msgstr "Tipo Personalizado de Nó Raiz:"
+
+#~ msgid "Auto"
+#~ msgstr "Auto"
+
+#~ msgid "Root Node Name:"
+#~ msgstr "Nome do Nó Raíz:"
+
+#~ msgid "The Following Files are Missing:"
+#~ msgstr "Os Seguintes Arquivos estão Faltando:"
+
+#~ msgid "Import Anyway"
+#~ msgstr "Importar Mesmo Assim"
+
+#~ msgid "Import & Open"
+#~ msgstr "Importar e Abrir"
+
+#~ msgid "Edited scene has not been saved, open imported scene anyway?"
+#~ msgstr "A cena editada não foi salva, abrir cena importada ainda assim?"
+
+#~ msgid "Import Image:"
+#~ msgstr "Importar Imagem:"
+
+#~ msgid "Couldn't localize path: %s (already local)"
+#~ msgstr "Caminho não pôde ser localizado: %s (já é local)"
+
+#~ msgid "3D Scene Animation"
+#~ msgstr "Animação Cena 3D"
+
+#~ msgid "Uncompressed"
+#~ msgstr "Não comprimido"
+
+#~ msgid "Compress Lossless (PNG)"
+#~ msgstr "Comprimido Sem Perdas (PNG)"
+
+#~ msgid "Compress Lossy (WebP)"
+#~ msgstr "Comprido Com Perdas (WebP)"
+
+#~ msgid "Compress (VRAM)"
+#~ msgstr "Comprimido (VRAM)"
+
+#~ msgid "Texture Format"
+#~ msgstr "Formato da Textura"
+
+#~ msgid "Texture Compression Quality (WebP):"
+#~ msgstr "Qualidade da Compressão da Textura (WebP):"
+
+#~ msgid "Texture Options"
+#~ msgstr "Opções da Textura"
+
+#~ msgid "Please specify some files!"
+#~ msgstr "Por favor especifique alguns arquivos!"
+
+#~ msgid "At least one file needed for Atlas."
+#~ msgstr "Pelo menos um arquivo é preciso para o Atlas."
+
+#~ msgid "Error importing:"
+#~ msgstr "Erro ao importar:"
+
+#~ msgid "Only one file is required for large texture."
+#~ msgstr "Apenas um arquivo é requerido para textura grande."
+
+#~ msgid "Max Texture Size:"
+#~ msgstr "Tamanho Máximo de Textura:"
+
+#~ msgid "Import Textures for Atlas (2D)"
+#~ msgstr "Importar Texturas para Atlas (2D)"
+
+#~ msgid "Cell Size:"
+#~ msgstr "Tamanho da Célula:"
+
+#~ msgid "Large Texture"
+#~ msgstr "Textura Grande"
+
+#~ msgid "Import Large Textures (2D)"
+#~ msgstr "Importar Texturas Grandes (2D)"
+
+#~ msgid "Source Texture"
+#~ msgstr "Textura Origem"
+
+#~ msgid "Base Atlas Texture"
+#~ msgstr "Textura Base do Atlas"
+
+#~ msgid "Source Texture(s)"
+#~ msgstr "Textura(s) Origem(ns)"
+
+#~ msgid "Import Textures for 2D"
+#~ msgstr "Importar Texturas para 2D"
+
+#~ msgid "Import Textures for 3D"
+#~ msgstr "Importar Texturas para 3D"
+
+#~ msgid "Import Textures"
+#~ msgstr "Importar Textura"
+
+#~ msgid "2D Texture"
+#~ msgstr "Textura 2D"
+
+#~ msgid "3D Texture"
+#~ msgstr "Textura 3D"
+
+#~ msgid "Atlas Texture"
+#~ msgstr "Textura Atlas"
+
+#~ msgid ""
+#~ "NOTICE: Importing 2D textures is not mandatory. Just copy png/jpg files "
+#~ "to the project."
+#~ msgstr ""
+#~ "AVISO: Importar texturas 2D não é obrigatório. Apenas copie arquivos png/"
+#~ "jpg para o projeto."
+
+#~ msgid "Crop empty space."
+#~ msgstr "Aparar espaço vazio."
+
+#~ msgid "Texture"
+#~ msgstr "Textura"
+
+#~ msgid "Import Large Texture"
+#~ msgstr "Importar Textura Grande"
+
+#~ msgid "Load Source Image"
+#~ msgstr "Carregar Imagem Origem"
+
+#~ msgid "Slicing"
+#~ msgstr "Fatiando"
+
+#~ msgid "Saving"
+#~ msgstr "Salvando"
+
+#~ msgid "Couldn't save large texture:"
+#~ msgstr "Não se pôde salvar textura grande:"
+
+#~ msgid "Build Atlas For:"
+#~ msgstr "Montar Atlas Para:"
+
+#~ msgid "Loading Image:"
+#~ msgstr "Carregando Imagem:"
+
+#~ msgid "Couldn't load image:"
+#~ msgstr "Não se pôde carregar imagem:"
+
+#~ msgid "Converting Images"
+#~ msgstr "Convertendo Imagens"
+
+#~ msgid "Cropping Images"
+#~ msgstr "Aparando Imagens"
+
+#~ msgid "Blitting Images"
+#~ msgstr "Fazendo Blitting das Imagens"
+
+#~ msgid "Couldn't save atlas image:"
+#~ msgstr "Não se pôde salva imagem de atlas:"
+
+#~ msgid "Couldn't save converted texture:"
+#~ msgstr "Não se pôde salvar textura convertida:"
+
+#~ msgid "Invalid source!"
+#~ msgstr "Origem inválida!"
+
+#~ msgid "Invalid translation source!"
+#~ msgstr "Origem de tradução inválida!"
+
+#~ msgid "Column"
+#~ msgstr "Coluna"
+
+#~ msgid "No items to import!"
+#~ msgstr "Nenhum item a importar!"
+
+#~ msgid "No target path!"
+#~ msgstr "Nenhum caminho destino!"
+
+#~ msgid "Import Translations"
+#~ msgstr "Importar Traduções"
+
+#~ msgid "Couldn't import!"
+#~ msgstr "Não foi possível importar!"
+
+#~ msgid "Import Translation"
+#~ msgstr "Importar Tradução"
+
+#~ msgid "Source CSV:"
+#~ msgstr "Arquivo CSV Origem:"
+
+#~ msgid "Ignore First Row"
+#~ msgstr "Ignorar Primeira Linha"
+
+#~ msgid "Compress"
+#~ msgstr "Comprimir"
+
+#~ msgid "Add to Project (project.godot)"
+#~ msgstr "Adicionar ao Projeto (project.godot)"
+
+#~ msgid "Import Languages:"
+#~ msgstr "Importar Idiomas:"
+
+#~ msgid "Translation"
+#~ msgstr "Tradução"
+
+#~ msgid "Parsing %d Triangles:"
+#~ msgstr "Analisando %d Triângulos:"
+
+#~ msgid "Triangle #"
+#~ msgstr "Triângulo nº"
+
+#~ msgid "Light Baker Setup:"
+#~ msgstr "Configurar Baker de Luz:"
+
+#~ msgid "Fixing Lights"
+#~ msgstr "Consertando Luzes"
+
+#~ msgid "Making BVH"
+#~ msgstr "Fazendo BVH"
+
+#~ msgid "Transfer to Lightmaps:"
+#~ msgstr "Transferir para Mapas de Luz:"
+
+#~ msgid "Allocating Texture #"
+#~ msgstr "Alocando Textura nº"
+
+#~ msgid "Baking Triangle #"
+#~ msgstr "Precalculando Triângulo nº"
+
+#~ msgid "Post-Processing Texture #"
+#~ msgstr "Pós-Processando Textura nº"
+
+#~ msgid "Reset the lightmap octree baking process (start over)."
+#~ msgstr "Redefinir o processo \"octree baking\" do lightmap (recomeçar)."
+
+#~ msgid "Zoom (%):"
+#~ msgstr "Ampliação (%):"
+
+#~ msgid "Skeleton.."
+#~ msgstr "Esqueleto..."
+
+#~ msgid "Zoom Reset"
+#~ msgstr "Restaurar Ampliação"
+
+#~ msgid "Zoom Set.."
+#~ msgstr "Definir Ampliação..."
+
+#~ msgid "Set a Value"
+#~ msgstr "Defina um Valor"
+
+#~ msgid "Snap (Pixels):"
+#~ msgstr "Snap (Pixels):"
+
+#~ msgid "Parse BBCode"
+#~ msgstr "Analisar BBCode"
+
+#~ msgid "Length:"
+#~ msgstr "Duração:"
+
+#~ msgid "Open Sample File(s)"
+#~ msgstr "Abrir Arquivo(s) de Amostra"
+
+#~ msgid "ERROR: Couldn't load sample!"
+#~ msgstr "ERRO: Não é possível carregar a amostra!"
+
+#~ msgid "Add Sample"
+#~ msgstr "Adicionar Amostra"
+
+#~ msgid "Rename Sample"
+#~ msgstr "Renomear Amostra"
+
+#~ msgid "Delete Sample"
+#~ msgstr "Excluir Amostra"
+
+#~ msgid "16 Bits"
+#~ msgstr "16 bits"
+
+#~ msgid "8 Bits"
+#~ msgstr "8 Bits"
+
+#~ msgid "Stereo"
+#~ msgstr "Estéreo"
+
+#~ msgid "Mono"
+#~ msgstr "Mono"
+
+#~ msgid "Pitch"
+#~ msgstr "Pitch"
+
+#~ msgid "Window"
+#~ msgstr "Janela"
+
+#~ msgid "Move Right"
+#~ msgstr "Mover para Direita"
+
+#~ msgid "Scaling to %s%%."
+#~ msgstr "Escalonando para %s%%."
+
+#~ msgid "Up"
+#~ msgstr "Acima"
+
+#~ msgid "Down"
+#~ msgstr "Abaixo"
+
+#~ msgid "Bucket"
+#~ msgstr "Balde"
+
+#~ msgid "Invalid project path, the path must exist!"
+#~ msgstr "Caminho de projeto inválido, o caminho deve existir!"
+
+#, fuzzy
+#~ msgid "Invalid project path, project.godot must not exist."
+#~ msgstr "Caminho de projeto inválido, engine.cfg não deve existir."
+
+#, fuzzy
+#~ msgid "Invalid project path, project.godot must exist."
+#~ msgstr "Caminho de projeto inválido, engine.cfg deve existir."
+
+#~ msgid "Project Path (Must Exist):"
+#~ msgstr "Caminho do Projeto (Deve Existir):"
+
+#~ msgid "Create New Resource"
+#~ msgstr "Criar Novo Recurso"
+
+#~ msgid "Open Resource"
+#~ msgstr "Abrir Recurso"
+
+#~ msgid "Save Resource"
+#~ msgstr "Salvar Recurso"
+
+#~ msgid "Resource Tools"
+#~ msgstr "Ferramentas de Recurso"
+
+#~ msgid "Make Local"
+#~ msgstr "Tornar Local"
+
+#~ msgid "Edit Groups"
+#~ msgstr "Editar Grupos"
+
+#~ msgid "Edit Connections"
+#~ msgstr "Editar Conexões"
+
+#~ msgid "GridMap Paint"
+#~ msgstr "Pintura GridMap"
+
+#, fuzzy
+#~ msgid "Tiles"
+#~ msgstr " Arquivos"
+
+#~ msgid "Areas"
+#~ msgstr "Ãreas"
+
+#~ msgid "Ctrl+"
+#~ msgstr "Ctrl+"
+
+#~ msgid "Down Wheel)"
+#~ msgstr "Rodar para Baixo)"
+
+#, fuzzy
+#~ msgid "Up Wheel)"
+#~ msgstr "Rodar para Cima"
+
#~ msgid "Close scene? (Unsaved changes will be lost)"
#~ msgstr "Fechar cena? (Mudanças não salvas serão perdidas)"
@@ -8098,9 +8263,6 @@ msgstr ""
#~ msgid "Close Goto Prev. Scene"
#~ msgstr "Ir a Cena Fechada Anterior"
-#~ msgid "Expand to Parent"
-#~ msgstr "Expandir para Pai"
-
#~ msgid "Del"
#~ msgstr "Del"
@@ -8224,18 +8386,12 @@ msgstr ""
#~ msgid "Save Translatable Strings"
#~ msgstr "Salvar Strings Traduzíveis"
-#~ msgid "Translatable Strings.."
-#~ msgstr "Strings Traduzíveis..."
-
#~ msgid "Install Export Templates"
#~ msgstr "Instalar Models de Exportação"
#~ msgid "Edit Script Options"
#~ msgstr "Editar Opções de Script"
-#~ msgid "Please export outside the project folder!"
-#~ msgstr "Por favor export para fora da pasta do projeto!"
-
#~ msgid "Error exporting project!"
#~ msgstr "Erro ao exportar o projeto!"
@@ -8276,18 +8432,12 @@ msgstr ""
#~ msgid "Include"
#~ msgstr "Incluir"
-#~ msgid "Change Image Group"
-#~ msgstr "Alterar Grupo de Imagens"
-
#~ msgid "Group name can't be empty!"
#~ msgstr "O nome do grupo não pode estar vazio!"
#~ msgid "Invalid character in group name!"
#~ msgstr "Caractere inválido no nome do grupo!"
-#~ msgid "Group name already exists!"
-#~ msgstr "O nome do grupo já existe!"
-
#~ msgid "Add Image Group"
#~ msgstr "Adicionar Grupo de Imagens"
@@ -8366,9 +8516,6 @@ msgstr ""
#~ msgid "Preview Atlas"
#~ msgstr "Prever Atlas"
-#~ msgid "Image Filter:"
-#~ msgstr "Filtrar Imagens:"
-
#~ msgid "Images:"
#~ msgstr "Imagens:"
@@ -8435,9 +8582,6 @@ msgstr ""
#~ msgid "Lighting"
#~ msgstr "Iluminação"
-#~ msgid "Toggle Persisting"
-#~ msgstr "Alternar Persistência"
-
#~ msgid "Global"
#~ msgstr "Global"
diff --git a/editor/translations/pt_PT.po b/editor/translations/pt_PT.po
index 7a178acdd5..4b4a98857c 100644
--- a/editor/translations/pt_PT.po
+++ b/editor/translations/pt_PT.po
@@ -1,33 +1,37 @@
# Portuguese (Portugal) translation of the Godot Engine editor
-# Copyright (C) 2016-2017 Juan Linietsky, Ariel Manzur and the Godot community
+# Copyright (C) 2007-2017 Juan Linietsky, Ariel Manzur
+# Copyright (C) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)
# This file is distributed under the same license as the Godot source code.
#
# António Sarmento <antonio.luis.sarmento@gmail.com>, 2016.
+# João Graça <jgraca95@gmail.com>, 2017.
+# Rueben Stevens <supercell03@gmail.com>, 2017.
#
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
-"PO-Revision-Date: 2016-08-11 15:42+0000\n"
-"Last-Translator: António Sarmento <antonio.luis.sarmento@gmail.com>\n"
+"PO-Revision-Date: 2017-10-25 01:48+0000\n"
+"Last-Translator: Rueben Stevens <supercell03@gmail.com>\n"
"Language-Team: Portuguese (Portugal) <https://hosted.weblate.org/projects/"
"godot-engine/godot/pt_PT/>\n"
"Language: pt_PT\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8-bit\n"
"Plural-Forms: nplurals=2; plural=n > 1;\n"
-"X-Generator: Weblate 2.8-dev\n"
+"X-Generator: Weblate 2.17\n"
#: editor/animation_editor.cpp
msgid "Disabled"
-msgstr ""
+msgstr "desativado"
#: editor/animation_editor.cpp
msgid "All Selection"
-msgstr ""
+msgstr "Toda a selecção"
#: editor/animation_editor.cpp
+#, fuzzy
msgid "Move Add Key"
-msgstr ""
+msgstr "Mover Chave Adcionada"
#: editor/animation_editor.cpp
msgid "Anim Change Transition"
@@ -63,15 +67,15 @@ msgstr ""
#: editor/animation_editor.cpp
msgid "Remove Anim Track"
-msgstr ""
+msgstr "Remover a banda de animação"
#: editor/animation_editor.cpp
msgid "Set Transitions to:"
-msgstr ""
+msgstr "Definir transições para:"
#: editor/animation_editor.cpp
msgid "Anim Track Rename"
-msgstr ""
+msgstr "Renomear Banda de Anim"
#: editor/animation_editor.cpp
msgid "Anim Track Change Interpolation"
@@ -86,12 +90,13 @@ msgid "Anim Track Change Wrap Mode"
msgstr ""
#: editor/animation_editor.cpp
+#, fuzzy
msgid "Edit Node Curve"
-msgstr ""
+msgstr "Editar Curva de Node"
#: editor/animation_editor.cpp
msgid "Edit Selection Curve"
-msgstr ""
+msgstr "Editar Curva de Selecção"
#: editor/animation_editor.cpp
msgid "Anim Delete Keys"
@@ -99,7 +104,7 @@ msgstr ""
#: editor/animation_editor.cpp editor/plugins/tile_map_editor_plugin.cpp
msgid "Duplicate Selection"
-msgstr ""
+msgstr "Duplicar Selecção"
#: editor/animation_editor.cpp
msgid "Duplicate Transposed"
@@ -107,19 +112,19 @@ msgstr ""
#: editor/animation_editor.cpp
msgid "Remove Selection"
-msgstr ""
+msgstr "Remover Selecção"
#: editor/animation_editor.cpp
msgid "Continuous"
-msgstr ""
+msgstr "Contínuo"
#: editor/animation_editor.cpp
msgid "Discrete"
-msgstr ""
+msgstr "Discreto"
#: editor/animation_editor.cpp
msgid "Trigger"
-msgstr ""
+msgstr "Gatilho"
#: editor/animation_editor.cpp
msgid "Anim Add Key"
@@ -131,28 +136,28 @@ msgstr ""
#: editor/animation_editor.cpp
msgid "Scale Selection"
-msgstr ""
+msgstr "Escalar Selecção"
#: editor/animation_editor.cpp
msgid "Scale From Cursor"
-msgstr ""
+msgstr "Alterar escala a partir do cursor"
#: editor/animation_editor.cpp
msgid "Goto Next Step"
-msgstr ""
+msgstr "Ir para o próximo passo"
#: editor/animation_editor.cpp
msgid "Goto Prev Step"
-msgstr ""
+msgstr "Ir para passo anterior"
#: editor/animation_editor.cpp editor/plugins/curve_editor_plugin.cpp
#: editor/property_editor.cpp
msgid "Linear"
-msgstr ""
+msgstr "Linear"
#: editor/animation_editor.cpp editor/plugins/theme_editor_plugin.cpp
msgid "Constant"
-msgstr ""
+msgstr "Constante"
#: editor/animation_editor.cpp
msgid "In"
@@ -172,15 +177,15 @@ msgstr ""
#: editor/animation_editor.cpp
msgid "Transitions"
-msgstr ""
+msgstr "Transições"
#: editor/animation_editor.cpp
msgid "Optimize Animation"
-msgstr ""
+msgstr "Optimizar Animação"
#: editor/animation_editor.cpp
msgid "Clean-Up Animation"
-msgstr ""
+msgstr "Limpar Animação"
#: editor/animation_editor.cpp
msgid "Create NEW track for %s and insert key?"
@@ -191,14 +196,13 @@ msgid "Create %d NEW tracks and insert keys?"
msgstr ""
#: editor/animation_editor.cpp editor/create_dialog.cpp
-#: editor/editor_audio_buses.cpp
+#: editor/editor_audio_buses.cpp editor/plugins/abstract_polygon_2d_editor.cpp
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
#: editor/plugins/mesh_instance_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp editor/project_manager.cpp
#: editor/script_create_dialog.cpp
msgid "Create"
-msgstr ""
+msgstr "Criar"
#: editor/animation_editor.cpp
msgid "Anim Create & Insert"
@@ -242,15 +246,15 @@ msgstr ""
#: editor/animation_editor.cpp
msgid "Length (s):"
-msgstr ""
+msgstr "Comprimento (s):"
#: editor/animation_editor.cpp
msgid "Animation length (in seconds)."
-msgstr ""
+msgstr "Duração da animação (em segundos)."
#: editor/animation_editor.cpp
msgid "Step (s):"
-msgstr ""
+msgstr "Passos (s):"
#: editor/animation_editor.cpp
msgid "Cursor step snap (in seconds)."
@@ -258,11 +262,11 @@ msgstr ""
#: editor/animation_editor.cpp
msgid "Enable/Disable looping in animation."
-msgstr ""
+msgstr "Habilitar/Desabilitar repetição na animação."
#: editor/animation_editor.cpp
msgid "Add new tracks."
-msgstr ""
+msgstr "Adicionar novas bandas."
#: editor/animation_editor.cpp
msgid "Move current track up."
@@ -274,7 +278,7 @@ msgstr ""
#: editor/animation_editor.cpp
msgid "Remove selected track."
-msgstr ""
+msgstr "Remover a banda seleccionada."
#: editor/animation_editor.cpp
msgid "Track tools"
@@ -282,7 +286,7 @@ msgstr ""
#: editor/animation_editor.cpp
msgid "Enable editing of individual keys by clicking them."
-msgstr ""
+msgstr "Habilitar a edição de chaves individuais ao clicar nelas."
#: editor/animation_editor.cpp
msgid "Anim. Optimizer"
@@ -356,261 +360,6 @@ msgstr ""
msgid "Change Array Value"
msgstr ""
-#: editor/asset_library_editor_plugin.cpp
-msgid "Free"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_plugin_settings.cpp
-msgid "Version:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Contents:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "View Files"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_help.cpp editor/property_selector.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Description:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-#: editor/project_manager.cpp
-msgid "Install"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/call_dialog.cpp
-#: editor/connections_dialog.cpp editor/export_template_manager.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-#: editor/project_settings_editor.cpp editor/property_editor.cpp
-#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Close"
-msgstr "Fechar"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve hostname:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Connection error, please try again."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't connect."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't connect to host:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response from host:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Request failed, return code:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Req. Failed."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Request failed, too many redirects"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Redirect Loop."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Bad download hash, assuming file has been tampered with."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Expected:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Got:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Asset Download Error:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-msgid "Success!"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Fetching:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Resolving.."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Connecting.."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Requesting.."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Error making request"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Idle"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Retry"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Download Error"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Download for this asset is already in progress!"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "first"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "prev"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "next"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "last"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "All"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
-#: editor/settings_config_dialog.cpp
-msgid "Search:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/code_editor.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Search"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/project_manager.cpp
-msgid "Import"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Plugins"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Sort:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Reverse"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Category:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Site:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Support.."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Official"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-msgid "Community"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Testing"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Assets ZIP File"
-msgstr ""
-
-#: editor/call_dialog.cpp
-msgid "Method List For '%s':"
-msgstr ""
-
-#: editor/call_dialog.cpp modules/visual_script/visual_script_editor.cpp
-msgid "Call"
-msgstr ""
-
-#: editor/call_dialog.cpp
-msgid "Method List:"
-msgstr ""
-
-#: editor/call_dialog.cpp
-msgid "Arguments:"
-msgstr ""
-
-#: editor/call_dialog.cpp
-msgid "Return:"
-msgstr ""
-
#: editor/code_editor.cpp
msgid "Go to Line"
msgstr ""
@@ -647,6 +396,14 @@ msgstr ""
msgid "Selection Only"
msgstr ""
+#: editor/code_editor.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
+msgid "Search"
+msgstr ""
+
#: editor/code_editor.cpp editor/editor_help.cpp
msgid "Find"
msgstr ""
@@ -679,11 +436,11 @@ msgstr ""
msgid "Skip"
msgstr ""
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom In"
msgstr ""
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom Out"
msgstr ""
@@ -750,6 +507,20 @@ msgstr ""
msgid "Oneshot"
msgstr ""
+#: editor/connections_dialog.cpp editor/dependency_editor.cpp
+#: editor/export_template_manager.cpp
+#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Close"
+msgstr "Fechar"
+
#: editor/connections_dialog.cpp
msgid "Connect"
msgstr ""
@@ -775,7 +546,7 @@ msgstr ""
msgid "Disconnect"
msgstr ""
-#: editor/connections_dialog.cpp editor/node_dock.cpp
+#: editor/connections_dialog.cpp editor/editor_help.cpp editor/node_dock.cpp
msgid "Signals"
msgstr ""
@@ -792,12 +563,25 @@ msgstr ""
msgid "Recent:"
msgstr ""
+#: editor/create_dialog.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/quick_open.cpp editor/settings_config_dialog.cpp
+msgid "Search:"
+msgstr ""
+
#: editor/create_dialog.cpp editor/editor_help.cpp
#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/quick_open.cpp
msgid "Matches:"
msgstr ""
+#: editor/create_dialog.cpp editor/editor_help.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/property_selector.cpp
+#: editor/script_editor_debugger.cpp
+msgid "Description:"
+msgstr ""
+
#: editor/dependency_editor.cpp
msgid "Search Replacement For:"
msgstr ""
@@ -853,6 +637,10 @@ msgid "Owners Of:"
msgstr ""
#: editor/dependency_editor.cpp
+msgid "Remove selected files from the project? (no undo)"
+msgstr ""
+
+#: editor/dependency_editor.cpp
msgid ""
"The files being removed are required by other resources in order for them to "
"work.\n"
@@ -860,7 +648,7 @@ msgid ""
msgstr ""
#: editor/dependency_editor.cpp
-msgid "Remove selected files from the project? (no undo)"
+msgid "Cannot remove:\n"
msgstr ""
#: editor/dependency_editor.cpp
@@ -927,10 +715,6 @@ msgid "Godot Engine contributors"
msgstr ""
#: editor/editor_about.cpp
-msgid "Authors"
-msgstr ""
-
-#: editor/editor_about.cpp
msgid "Project Founders"
msgstr ""
@@ -947,6 +731,38 @@ msgid "Developers"
msgstr ""
#: editor/editor_about.cpp
+msgid "Authors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Platinum Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Gold Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Mini Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Gold Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Silver Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Bronze Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
msgid "License"
msgstr ""
@@ -987,6 +803,16 @@ msgid "Package Installed Successfully!"
msgstr ""
#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Success!"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/project_manager.cpp
+msgid "Install"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
msgid "Package Installer"
msgstr ""
@@ -1037,10 +863,6 @@ msgid "Audio Bus, Drag and Drop to rearrange."
msgstr ""
#: editor/editor_audio_buses.cpp
-msgid "Bus options"
-msgstr ""
-
-#: editor/editor_audio_buses.cpp
msgid "Solo"
msgstr ""
@@ -1052,12 +874,20 @@ msgstr ""
msgid "Bypass"
msgstr ""
+#: editor/editor_audio_buses.cpp
+msgid "Bus options"
+msgstr ""
+
#: editor/editor_audio_buses.cpp editor/plugins/tile_map_editor_plugin.cpp
#: editor/scene_tree_dock.cpp
msgid "Duplicate"
msgstr ""
#: editor/editor_audio_buses.cpp
+msgid "Reset Volume"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
#, fuzzy
msgid "Delete Effect"
msgstr "Apagar Seleccionados"
@@ -1079,6 +909,10 @@ msgid "Duplicate Audio Bus"
msgstr ""
#: editor/editor_audio_buses.cpp
+msgid "Reset Bus Volume"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
msgid "Move Audio Bus"
msgstr ""
@@ -1110,7 +944,8 @@ msgstr ""
msgid "Create a new Bus Layout."
msgstr ""
-#: editor/editor_audio_buses.cpp editor/script_create_dialog.cpp
+#: editor/editor_audio_buses.cpp editor/property_editor.cpp
+#: editor/script_create_dialog.cpp
msgid "Load"
msgstr ""
@@ -1200,7 +1035,7 @@ msgid "Rearrange Autoloads"
msgstr ""
#: editor/editor_autoload_settings.cpp editor/editor_file_dialog.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp scene/gui/file_dialog.cpp
+#: scene/gui/file_dialog.cpp
msgid "Path:"
msgstr ""
@@ -1208,9 +1043,7 @@ msgstr ""
msgid "Node Name:"
msgstr ""
-#: editor/editor_autoload_settings.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp editor/project_manager.cpp
+#: editor/editor_autoload_settings.cpp editor/project_manager.cpp
msgid "Name"
msgstr ""
@@ -1243,18 +1076,19 @@ msgid "Choose a Directory"
msgstr ""
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Create Folder"
msgstr ""
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: editor/editor_plugin_settings.cpp editor/plugins/theme_editor_plugin.cpp
-#: editor/project_export.cpp scene/gui/file_dialog.cpp
+#: editor/editor_plugin_settings.cpp editor/filesystem_dock.cpp
+#: editor/plugins/theme_editor_plugin.cpp editor/project_export.cpp
+#: scene/gui/file_dialog.cpp
msgid "Name:"
msgstr ""
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Could not create folder."
msgstr ""
@@ -1274,30 +1108,6 @@ msgstr ""
msgid "Template file not found:\n"
msgstr ""
-#: editor/editor_export.cpp
-msgid "Added:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Removed:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Error saving atlas:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Could not save atlas subtexture:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Exporting for %s"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Setting Up.."
-msgstr ""
-
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "File Exists, Overwrite?"
msgstr ""
@@ -1382,6 +1192,10 @@ msgstr ""
msgid "Move Favorite Down"
msgstr ""
+#: editor/editor_file_dialog.cpp
+msgid "Go to parent folder"
+msgstr ""
+
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Directories & Files:"
msgstr ""
@@ -1396,10 +1210,6 @@ msgid "File:"
msgstr ""
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
-msgid "Filter:"
-msgstr ""
-
-#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Must use a valid extension."
msgstr ""
@@ -1424,6 +1234,10 @@ msgstr ""
msgid "Search Classes"
msgstr ""
+#: editor/editor_help.cpp editor/plugins/spatial_editor_plugin.cpp
+msgid "Top"
+msgstr ""
+
#: editor/editor_help.cpp editor/property_editor.cpp
msgid "Class:"
msgstr ""
@@ -1440,15 +1254,28 @@ msgstr ""
msgid "Brief Description:"
msgstr ""
+#: editor/editor_help.cpp
+#, fuzzy
+msgid "Members"
+msgstr "Membros:"
+
#: editor/editor_help.cpp modules/visual_script/visual_script_editor.cpp
msgid "Members:"
msgstr "Membros:"
#: editor/editor_help.cpp
+msgid "Public Methods"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Public Methods:"
msgstr ""
#: editor/editor_help.cpp
+msgid "GUI Theme Items"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "GUI Theme Items:"
msgstr ""
@@ -1458,6 +1285,11 @@ msgstr "Sinais:"
#: editor/editor_help.cpp
#, fuzzy
+msgid "Enumerations"
+msgstr "Funções:"
+
+#: editor/editor_help.cpp
+#, fuzzy
msgid "Enumerations:"
msgstr "Funções:"
@@ -1466,18 +1298,46 @@ msgid "enum "
msgstr ""
#: editor/editor_help.cpp
+msgid "Constants"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Constants:"
msgstr ""
#: editor/editor_help.cpp
+msgid "Description"
+msgstr ""
+
+#: editor/editor_help.cpp
+msgid "Properties"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Property Description:"
msgstr ""
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this property. Please help us by "
+"[color=$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+
+#: editor/editor_help.cpp
+msgid "Methods"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Method Description:"
msgstr ""
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this method. Please help us by [color="
+"$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Search Text"
msgstr ""
@@ -1486,24 +1346,21 @@ msgid "Output:"
msgstr ""
#: editor/editor_log.cpp editor/plugins/animation_tree_editor_plugin.cpp
-#: editor/plugins/rich_text_editor_plugin.cpp editor/property_editor.cpp
-#: editor/script_editor_debugger.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/property_editor.cpp editor/script_editor_debugger.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Clear"
msgstr ""
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Error saving resource!"
msgstr ""
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Save Resource As.."
msgstr ""
-#: editor/editor_node.cpp editor/export_template_manager.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "I see.."
msgstr ""
@@ -1520,6 +1377,26 @@ msgid "Error while saving."
msgstr ""
#: editor/editor_node.cpp
+msgid "Can't open '%s'."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Error while parsing '%s'."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Unexpected end of file '%s'."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Missing '%s' or its dependencies."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Error while loading '%s'."
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Saving Scene"
msgstr ""
@@ -1577,6 +1454,33 @@ msgid "Restored default layout to base settings."
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was imported, so it's not editable.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was instanced or inherited.\n"
+"Changes to it will not be kept when saving the current scene."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource was imported, so it's not editable. Change its settings in the "
+"import panel and then re-import."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This scene was imported, so changes to it will not be kept.\n"
+"Instancing it or inheriting will allow making changes to it.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Copy Params"
msgstr ""
@@ -1738,23 +1642,34 @@ msgid "Save changes the following scene(s) before opening Project Manager?"
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"This option is deprecated. Situations where refresh must be forced are now "
+"considered a bug. Please report."
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Pick a Main Scene"
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to enable addon plugin at: '"
+msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr ""
#: editor/editor_node.cpp
-msgid "' parsing of config failed."
+msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/"
+msgid "Unable to load addon script from path: '%s'."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to load addon script from path: '"
+msgid ""
+"Unable to load addon script from path: '%s' Base type is not EditorPlugin."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Unable to load addon script from path: '%s' Script is not in tool mode."
msgstr ""
#: editor/editor_node.cpp
@@ -1764,7 +1679,7 @@ msgid ""
msgstr ""
#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/scene_tree_dock.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Ugh"
msgstr ""
@@ -1775,11 +1690,11 @@ msgid ""
msgstr ""
#: editor/editor_node.cpp
-msgid "Error loading scene."
+msgid "Scene '%s' has broken dependencies:"
msgstr ""
#: editor/editor_node.cpp
-msgid "Scene '%s' has broken dependencies:"
+msgid "Clear Recent Scenes"
msgstr ""
#: editor/editor_node.cpp
@@ -1815,7 +1730,7 @@ msgstr ""
msgid "Toggle distraction-free mode."
msgstr ""
-#: editor/editor_node.cpp editor/io_plugins/editor_scene_import_plugin.cpp
+#: editor/editor_node.cpp
msgid "Scene"
msgstr ""
@@ -2035,6 +1950,10 @@ msgstr ""
msgid "Issue Tracker"
msgstr ""
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+msgid "Community"
+msgstr ""
+
#: editor/editor_node.cpp
msgid "About"
msgstr ""
@@ -2043,7 +1962,7 @@ msgstr ""
msgid "Play the project."
msgstr ""
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Play"
msgstr ""
@@ -2059,7 +1978,7 @@ msgstr ""
msgid "Stop the scene."
msgstr ""
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Stop"
msgstr ""
@@ -2132,6 +2051,15 @@ msgid "Object properties."
msgstr ""
#: editor/editor_node.cpp
+msgid "Changes may be lost!"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Import"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "FileSystem"
msgstr ""
@@ -2147,14 +2075,6 @@ msgstr ""
msgid "Don't Save"
msgstr ""
-#: editor/editor_node.cpp editor/editor_reimport_dialog.cpp
-msgid "Re-Import"
-msgstr ""
-
-#: editor/editor_node.cpp editor/editor_plugin_settings.cpp
-msgid "Update"
-msgstr ""
-
#: editor/editor_node.cpp
msgid "Import Templates From ZIP File"
msgstr ""
@@ -2215,11 +2135,28 @@ msgstr ""
msgid "Open the previous Editor"
msgstr ""
+#: editor/editor_plugin.cpp
+msgid "Creating Mesh Previews"
+msgstr ""
+
+#: editor/editor_plugin.cpp
+msgid "Thumbnail.."
+msgstr ""
+
#: editor/editor_plugin_settings.cpp
msgid "Installed Plugins:"
msgstr ""
#: editor/editor_plugin_settings.cpp
+msgid "Update"
+msgstr ""
+
+#: editor/editor_plugin_settings.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Version:"
+msgstr ""
+
+#: editor/editor_plugin_settings.cpp
msgid "Author:"
msgstr ""
@@ -2252,7 +2189,7 @@ msgid "Frame %"
msgstr ""
#: editor/editor_profiler.cpp
-msgid "Fixed Frame %"
+msgid "Physics Frame %"
msgstr ""
#: editor/editor_profiler.cpp editor/script_editor_debugger.cpp
@@ -2271,26 +2208,6 @@ msgstr ""
msgid "Frame #:"
msgstr ""
-#: editor/editor_reimport_dialog.cpp
-msgid "Please wait for scan to complete."
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Current scene must be saved to re-import."
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Save & Re-Import"
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Importing"
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Import Changed Resources"
-msgstr ""
-
#: editor/editor_run_native.cpp
msgid "Select device from the list"
msgstr ""
@@ -2400,10 +2317,6 @@ msgid "Importing:"
msgstr ""
#: editor/export_template_manager.cpp
-msgid "Loading Export Templates"
-msgstr ""
-
-#: editor/export_template_manager.cpp
msgid "Current Version:"
msgstr ""
@@ -2437,9 +2350,17 @@ msgid "Cannot navigate to '"
msgstr ""
#: editor/filesystem_dock.cpp
+msgid "View items as a grid of thumbnails"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "View items as a list"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
msgid ""
"\n"
-"Status: Needs Re-Import"
+"Status: Import of file failed. Please fix file and reimport manually."
msgstr ""
#: editor/filesystem_dock.cpp
@@ -2449,87 +2370,88 @@ msgid ""
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Same source and destination files, doing nothing."
+msgid "Cannot move/rename resources root."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Target file exists, can't overwrite. Delete first."
+msgid "Cannot move a folder into itself.\n"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Same source and destination paths, doing nothing."
+msgid "Error moving:\n"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Can't move directories to within themselves."
+msgid "Unable to update dependencies:\n"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Can't rename deps for:\n"
+msgid "No name provided"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Error moving file:\n"
+msgid "Provided name contains invalid characters"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Error moving dir:\n"
+msgid "No name provided."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Can't operate on '..'"
+msgid "Name contains invalid characters."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Pick New Name and Location For:"
+msgid "A file or folder with this name already exists."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "No files selected!"
-msgstr ""
+#, fuzzy
+msgid "Renaming file:"
+msgstr "Alterar nome da Variável"
#: editor/filesystem_dock.cpp
-msgid "Expand all"
+msgid "Renaming folder:"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Collapse all"
+msgid "Expand all"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Show In File Manager"
+msgid "Collapse all"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Instance"
+msgid "Copy Path"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Edit Dependencies.."
+msgid "Rename.."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "View Owners.."
+msgid "Move To.."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Copy Path"
+msgid "New Folder.."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Rename or Move.."
+msgid "Show In File Manager"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Move To.."
+msgid "Instance"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Info"
+msgid "Edit Dependencies.."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Re-Import.."
+msgid "View Owners.."
msgstr ""
#: editor/filesystem_dock.cpp
@@ -2562,6 +2484,11 @@ msgstr ""
msgid "Move"
msgstr ""
+#: editor/filesystem_dock.cpp editor/plugins/animation_tree_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Rename"
+msgstr ""
+
#: editor/groups_editor.cpp
msgid "Add to Group"
msgstr ""
@@ -2575,6 +2502,10 @@ msgid "Import as Single Scene"
msgstr ""
#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
msgid "Import with Separate Materials"
msgstr ""
@@ -2587,6 +2518,18 @@ msgid "Import with Separate Objects+Materials"
msgstr ""
#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Materials+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Materials+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
msgid "Import as Multiple Scenes"
msgstr ""
@@ -2595,38 +2538,31 @@ msgid "Import as Multiple Scenes+Materials"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Import Scene"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Importing Scene.."
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Running Custom Script.."
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Couldn't load post-import script:"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Invalid/broken script for post-import (check console):"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Error running post-import script:"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Saving.."
msgstr ""
@@ -2654,579 +2590,54 @@ msgstr ""
msgid "Reimport"
msgstr ""
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "No bit masks to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path is empty."
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must be a complete resource path."
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must exist."
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Save path is empty!"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Import BitMasks"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s):"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Target Path:"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Accept"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Bit Mask"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No source font file!"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No target font resource!"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"Invalid file extension.\n"
-"Please use .font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Can't load/process source font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Couldn't save font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font Size:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Dest Resource:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "The quick brown fox jumps over the lazy dog."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Test:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Options:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Font Import"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"This file is already a Godot font file, please supply a BMFont type file "
-"instead."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Failed opening as BMFont file."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error initializing FreeType."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Unknown font format."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error loading font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Invalid font size."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Invalid font custom source."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/plugins/theme_editor_plugin.cpp
-msgid "Font"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "No meshes to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Single Mesh Import"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Source Mesh(es):"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/plugins/mesh_instance_editor_plugin.cpp
-msgid "Mesh"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Surface %d"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "No samples to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Import Audio Samples"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Source Sample(s):"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Audio Sample"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "New Clip"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Animation Options"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Flags"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Bake FPS:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Optimizer"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Linear Error"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angular Error"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angle"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Clips"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Start(s)"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "End(s)"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Loop"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Filters"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source path is empty."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't load post-import script."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Invalid/broken script for post-import."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Error importing scene."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import 3D Scene"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source Scene:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Same as Target Scene"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Shared"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Target Texture Folder:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Post-Process Script:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Custom Root Node Type:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Auto"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Root Node Name:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "The Following Files are Missing:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Anyway"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp scene/gui/dialogs.cpp
-msgid "Cancel"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import & Open"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Edited scene has not been saved, open imported scene anyway?"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Image:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Can't import a file over itself:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't localize path: %s (already local)"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "3D Scene Animation"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Uncompressed"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossless (PNG)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossy (WebP)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress (VRAM)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Format"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Compression Quality (WebP):"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Options"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Please specify some files!"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "At least one file needed for Atlas."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Error importing:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Only one file is required for large texture."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Max Texture Size:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for Atlas (2D)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cell Size:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Large Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Textures (2D)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture"
+#: editor/multi_node_edit.cpp
+msgid "MultiNode Set"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Base Atlas Texture"
+#: editor/node_dock.cpp
+msgid "Groups"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s)"
+#: editor/node_dock.cpp
+msgid "Select a Node to edit Signals and Groups."
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 2D"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create Poly"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 3D"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Insert Point"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "2D Texture"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly (Remove Point)"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "3D Texture"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Remove Poly And Point"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Atlas Texture"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create a new polygon from scratch."
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
+#: editor/plugins/abstract_polygon_2d_editor.cpp
msgid ""
-"NOTICE: Importing 2D textures is not mandatory. Just copy png/jpg files to "
-"the project."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Crop empty space."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Load Source Image"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Slicing"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Inserting"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Saving"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save large texture:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Build Atlas For:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Loading Image:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't load image:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Converting Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cropping Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Blitting Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save atlas image:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save converted texture:"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid source!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid translation source!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Column"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/script_create_dialog.cpp
-msgid "Language"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No items to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No target path!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translations"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Couldn't import!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translation"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Source CSV:"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Ignore First Row"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Compress"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Add to Project (project.godot)"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Languages:"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Translation"
-msgstr ""
-
-#: editor/multi_node_edit.cpp
-msgid "MultiNode Set"
-msgstr ""
-
-#: editor/node_dock.cpp
-msgid "Groups"
-msgstr ""
-
-#: editor/node_dock.cpp
-msgid "Select a Node to edit Signals and Groups."
+"Edit existing polygon:\n"
+"LMB: Move Point.\n"
+"Ctrl+LMB: Split Segment.\n"
+"RMB: Erase Point."
msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
@@ -3382,7 +2793,6 @@ msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
#: editor/script_create_dialog.cpp
msgid "Error!"
@@ -3493,10 +2903,6 @@ msgid "Delete Input"
msgstr ""
#: editor/plugins/animation_tree_editor_plugin.cpp
-msgid "Rename"
-msgstr ""
-
-#: editor/plugins/animation_tree_editor_plugin.cpp
msgid "Animation tree is valid."
msgstr ""
@@ -3552,64 +2958,181 @@ msgstr ""
msgid "Filters.."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing %d Triangles:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Free"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Triangle #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Contents:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Light Baker Setup:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "View Files"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing Geometry"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve hostname:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Fixing Lights"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Making BVH"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connection error, please try again."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Light Octree"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't connect."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Octree Texture"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't connect to host:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Transfer to Lightmaps:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response from host:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Allocating Texture #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Baking Triangle #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, return code:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Post-Processing Texture #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Req. Failed."
msgstr ""
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Bake!"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, too many redirects"
msgstr ""
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Reset the lightmap octree baking process (start over)."
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Redirect Loop."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Bad download hash, assuming file has been tampered with."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Expected:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Got:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed sha256 hash check"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Asset Download Error:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Fetching:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Resolving.."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connecting.."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Requesting.."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Error making request"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Idle"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Retry"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download Error"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download for this asset is already in progress!"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "first"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "prev"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "next"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "last"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "All"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Plugins"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Sort:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Reverse"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Category:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Site:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Support.."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Official"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Testing"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Assets ZIP File"
msgstr ""
#: editor/plugins/camera_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
msgid "Preview"
msgstr ""
@@ -3652,11 +3175,15 @@ msgid "Edit CanvasItem"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Change Anchors"
+msgid "Anchors only"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom (%):"
+msgid "Change Anchors and Margins"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Change Anchors"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3707,59 +3234,73 @@ msgid "Pan Mode"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Lock the selected object in place (can't be moved)."
+#, fuzzy
+msgid "Toggles snapping"
+msgstr "Accionar Breakpoint"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Use Snap"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Unlock the selected object (can be moved)."
+msgid "Snapping options"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Makes sure the object's children are not selectable."
+msgid "Snap to grid"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Restores the object's children's ability to be selected."
+msgid "Use Rotation Snap"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Edit"
-msgstr "Editar"
+msgid "Configure Snap..."
+msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Use Snap"
+msgid "Snap Relative"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Show Grid"
+msgid "Use Pixel Snap"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Rotation Snap"
+msgid "Smart snapping"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap Relative"
+msgid "Snap to parent"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Configure Snap.."
+msgid "Snap to node anchor"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Pixel Snap"
+msgid "Snap to node sides"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to other nodes"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Lock the selected object in place (can't be moved)."
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Skeleton.."
+msgid "Unlock the selected object (can be moved)."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Makes sure the object's children are not selectable."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Restores the object's children's ability to be selected."
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3788,11 +3329,16 @@ msgid "View"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Reset"
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Show Grid"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Show helpers"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Set.."
+msgid "Show rulers"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3804,7 +3350,7 @@ msgid "Frame Selection"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Anchor"
+msgid "Layout"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3828,11 +3374,20 @@ msgid "Clear Pose"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Set a Value"
+msgid "Drag pivot from mouse position"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap (Pixels):"
+#, fuzzy
+msgid "Set pivot at mouse position"
+msgstr "Remover Sinal"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Multiply grid step by 2"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Divide grid step by 2"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3843,23 +3398,28 @@ msgstr ""
msgid "Adding %s..."
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Create Node"
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Error instancing scene from %s"
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "OK :("
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "No parent to instance a child at."
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "This operation requires a single selected node."
msgstr ""
@@ -3873,45 +3433,6 @@ msgid ""
"Drag & drop + Alt : Change node type"
msgstr ""
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Create Poly"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly (Remove Point)"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Create a new polygon from scratch."
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-msgid ""
-"Edit existing polygon:\n"
-"LMB: Move Point.\n"
-"Ctrl+LMB: Split Segment.\n"
-"RMB: Erase Point."
-msgstr ""
-
#: editor/plugins/collision_polygon_editor_plugin.cpp
msgid "Create Poly3D"
msgstr ""
@@ -3921,14 +3442,6 @@ msgid "Set Handle"
msgstr ""
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Creating Mesh Library"
-msgstr ""
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Thumbnail.."
-msgstr ""
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Remove item %d?"
msgstr ""
@@ -3951,6 +3464,26 @@ msgid "Update from Scene"
msgstr ""
#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat0"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat1"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Ease in"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Ease out"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Smoothstep"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
msgid "Modify Curve Point"
msgstr ""
@@ -4029,22 +3562,18 @@ msgid "Create Occluder Polygon"
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Edit existing polygon:"
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "LMB: Move Point."
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Ctrl+LMB: Split Segment."
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "RMB: Erase Point."
msgstr ""
@@ -4145,6 +3674,10 @@ msgid "Create Outline"
msgstr ""
#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Mesh"
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Create Trimesh Static Body"
msgstr ""
@@ -4272,12 +3805,72 @@ msgstr ""
msgid "Populate"
msgstr ""
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Create Navigation Polygon"
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake!"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake the navigation mesh.\n"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Clear the navigation mesh."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Setting up Configuration..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Calculating grid size..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating heightfield..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Marking walkable triangles..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Constructing compact heightfield..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Eroding walkable area..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Partitioning..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating contours..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating polymesh..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Converting to native navigation mesh..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Navigation Mesh Generator Setup:"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Parsing Geometry..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Done!"
msgstr ""
#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Remove Poly And Point"
+msgid "Create Navigation Polygon"
msgstr ""
#: editor/plugins/particles_2d_editor_plugin.cpp
@@ -4451,16 +4044,19 @@ msgid "Curve Point #"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve Point Position"
-msgstr ""
+msgstr "Remover Sinal"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve In Position"
-msgstr ""
+msgstr "Remover Sinal"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve Out Position"
-msgstr ""
+msgstr "Remover Sinal"
#: editor/plugins/path_editor_plugin.cpp
msgid "Split Path"
@@ -4520,6 +4116,14 @@ msgid "Scale Polygon"
msgstr ""
#: editor/plugins/polygon_2d_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Edit"
+msgstr "Editar"
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Polygon->UV"
msgstr ""
@@ -4574,63 +4178,10 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/shader_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr ""
-#: editor/plugins/rich_text_editor_plugin.cpp
-msgid "Parse BBCode"
-msgstr ""
-
-#: editor/plugins/sample_editor_plugin.cpp
-msgid "Length:"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Open Sample File(s)"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "ERROR: Couldn't load sample!"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Add Sample"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Rename Sample"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Delete Sample"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "16 Bits"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "8 Bits"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Stereo"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Mono"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Format"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Pitch"
-msgstr ""
-
#: editor/plugins/script_editor_plugin.cpp
msgid "Clear Recent Files"
msgstr ""
@@ -4722,6 +4273,10 @@ msgstr ""
msgid "Close All"
msgstr "Fechar"
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+msgid "Run"
+msgstr ""
+
#: editor/plugins/script_editor_plugin.cpp
msgid "Toggle Scripts Panel"
msgstr ""
@@ -4750,7 +4305,8 @@ msgstr ""
msgid "Break"
msgstr ""
-#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+#: editor/script_editor_debugger.cpp
msgid "Continue"
msgstr ""
@@ -4763,18 +4319,6 @@ msgid "Debug with external editor"
msgstr ""
#: editor/plugins/script_editor_plugin.cpp
-msgid "Window"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Left"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Right"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
msgid "Open Godot online documentation"
msgstr ""
@@ -4856,8 +4400,9 @@ msgid "Cut"
msgstr ""
#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr ""
@@ -5121,10 +4666,6 @@ msgid "View Plane Transform."
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Scaling to %s%%."
-msgstr ""
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rotating %s degrees."
msgstr ""
@@ -5141,10 +4682,6 @@ msgid "Top View."
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Top"
-msgstr ""
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rear View."
msgstr ""
@@ -5374,6 +4911,10 @@ msgid "Transform"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Configure Snap.."
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Local Coords"
msgstr ""
@@ -5519,6 +5060,10 @@ msgid "Speed (FPS):"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Loop"
+msgstr ""
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Animation Frames"
msgstr ""
@@ -5531,11 +5076,11 @@ msgid "Insert Empty (After)"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Up"
+msgid "Move (Before)"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Down"
+msgid "Move (After)"
msgstr ""
#: editor/plugins/style_box_editor_plugin.cpp
@@ -5614,7 +5159,11 @@ msgid "Remove All"
msgstr "Remover Sinal"
#: editor/plugins/theme_editor_plugin.cpp
-msgid "Theme"
+msgid "Edit theme.."
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Theme editing menu."
msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
@@ -5699,6 +5248,10 @@ msgid "Style"
msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
+msgid "Font"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
msgid "Color"
msgstr ""
@@ -5747,7 +5300,7 @@ msgid "Mirror Y"
msgstr ""
#: editor/plugins/tile_map_editor_plugin.cpp
-msgid "Bucket"
+msgid "Paint Tile"
msgstr ""
#: editor/plugins/tile_map_editor_plugin.cpp
@@ -5811,6 +5364,10 @@ msgid "Delete preset '%s'?"
msgstr ""
#: editor/project_export.cpp
+msgid "Export templates for this platform are missing/corrupted: "
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Presets"
msgstr ""
@@ -5881,19 +5438,29 @@ msgid "Export templates for this platform are missing:"
msgstr ""
#: editor/project_export.cpp
+msgid "Export templates for this platform are missing/corrupted:"
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Export With Debug"
msgstr ""
#: editor/project_manager.cpp
-msgid "Invalid project path, the path must exist!"
+msgid "The path does not exist."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Please choose a 'project.godot' file."
msgstr ""
#: editor/project_manager.cpp
-msgid "Invalid project path, project.godot must not exist."
+msgid ""
+"Your project will be created in a non empty folder (you might want to create "
+"a new folder)."
msgstr ""
#: editor/project_manager.cpp
-msgid "Invalid project path, project.godot must exist."
+msgid "Please choose a folder that does not contain a 'project.godot' file."
msgstr ""
#: editor/project_manager.cpp
@@ -5901,10 +5468,26 @@ msgid "Imported Project"
msgstr ""
#: editor/project_manager.cpp
+msgid " "
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "It would be a good idea to name your project."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Invalid project path (changed anything?)."
msgstr ""
#: editor/project_manager.cpp
+msgid "Couldn't get project.godot in project path."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Couldn't edit project.godot in project path."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
msgstr ""
@@ -5913,15 +5496,20 @@ msgid "The following files failed extraction from package:"
msgstr ""
#: editor/project_manager.cpp
-msgid "Import Existing Project"
+#, fuzzy
+msgid "Rename Project"
+msgstr "Alterar nome da Função"
+
+#: editor/project_manager.cpp
+msgid "Couldn't get project.godot in the project path."
msgstr ""
#: editor/project_manager.cpp
-msgid "Project Path (Must Exist):"
+msgid "New Game Project"
msgstr ""
#: editor/project_manager.cpp
-msgid "Project Name:"
+msgid "Import Existing Project"
msgstr ""
#: editor/project_manager.cpp
@@ -5929,19 +5517,23 @@ msgid "Create New Project"
msgstr ""
#: editor/project_manager.cpp
-msgid "Project Path:"
+msgid "Install Project:"
msgstr ""
#: editor/project_manager.cpp
-msgid "Install Project:"
+msgid "Project Name:"
msgstr ""
#: editor/project_manager.cpp
-msgid "Browse"
+msgid "Create folder"
msgstr ""
#: editor/project_manager.cpp
-msgid "New Game Project"
+msgid "Project Path:"
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Browse"
msgstr ""
#: editor/project_manager.cpp
@@ -5953,6 +5545,10 @@ msgid "Unnamed Project"
msgstr ""
#: editor/project_manager.cpp
+msgid "Can't open project"
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Are you sure to open more than one project?"
msgstr ""
@@ -5979,16 +5575,18 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
-"You are about the scan %s folders for existing Godot projects. Do you "
-"confirm?"
+"Language changed.\n"
+"The UI will update next time the editor or project manager starts."
msgstr ""
#: editor/project_manager.cpp
-msgid "Project List"
+msgid ""
+"You are about the scan %s folders for existing Godot projects. Do you "
+"confirm?"
msgstr ""
#: editor/project_manager.cpp
-msgid "Run"
+msgid "Project List"
msgstr ""
#: editor/project_manager.cpp
@@ -6013,6 +5611,10 @@ msgid "Exit"
msgstr ""
#: editor/project_manager.cpp
+msgid "Restart Now"
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Can't run project"
msgstr ""
@@ -6049,17 +5651,14 @@ msgid "Add Input Action Event"
msgstr ""
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Meta+"
msgstr ""
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Shift+"
msgstr ""
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Alt+"
msgstr ""
@@ -6120,7 +5719,7 @@ msgstr "Alterar"
msgid "Joypad Axis Index:"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Axis"
msgstr ""
@@ -6140,31 +5739,31 @@ msgstr ""
msgid "Add Event"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Device"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Button"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Left Button."
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Right Button."
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Middle Button."
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Up."
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Down."
msgstr ""
@@ -6174,7 +5773,7 @@ msgid "Add Global Property"
msgstr "Adicionar propriedade Getter"
#: editor/project_settings_editor.cpp
-msgid "Select an setting item first!"
+msgid "Select a setting item first!"
msgstr ""
#: editor/project_settings_editor.cpp
@@ -6191,6 +5790,14 @@ msgid "Delete Item"
msgstr "Apagar Seleccionados"
#: editor/project_settings_editor.cpp
+msgid "Can't contain '/' or ':'"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Already existing"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "Error saving settings."
msgstr ""
@@ -6231,6 +5838,14 @@ msgid "Remove Resource Remap Option"
msgstr ""
#: editor/project_settings_editor.cpp
+msgid "Changed Locale Filter"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Changed Locale Filter Mode"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "Project Settings (project.godot)"
msgstr ""
@@ -6291,6 +5906,26 @@ msgid "Locale"
msgstr ""
#: editor/project_settings_editor.cpp
+msgid "Locales Filter"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Show all locales"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Show only selected locales"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Filter mode:"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Locales:"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "AutoLoad"
msgstr ""
@@ -6340,10 +5975,18 @@ msgid "New Script"
msgstr ""
#: editor/property_editor.cpp
+msgid "Make Unique"
+msgstr ""
+
+#: editor/property_editor.cpp
msgid "Show in File System"
msgstr ""
#: editor/property_editor.cpp
+msgid "Convert To %s"
+msgstr ""
+
+#: editor/property_editor.cpp
msgid "Error loading file: Not a resource!"
msgstr ""
@@ -6381,6 +6024,10 @@ msgid "Select Property"
msgstr "Adicionar propriedade Setter"
#: editor/property_selector.cpp
+msgid "Select Virtual Method"
+msgstr ""
+
+#: editor/property_selector.cpp
msgid "Select Method"
msgstr ""
@@ -6408,26 +6055,6 @@ msgstr ""
msgid "Reparent"
msgstr ""
-#: editor/resources_dock.cpp
-msgid "Create New Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Open Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Save Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Resource Tools"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Make Local"
-msgstr ""
-
#: editor/run_settings_dialog.cpp
msgid "Run Mode:"
msgstr ""
@@ -6554,14 +6181,6 @@ msgid "Sub-Resources:"
msgstr ""
#: editor/scene_tree_dock.cpp
-msgid "Edit Groups"
-msgstr ""
-
-#: editor/scene_tree_dock.cpp
-msgid "Edit Connections"
-msgstr ""
-
-#: editor/scene_tree_dock.cpp
msgid "Clear Inheritance"
msgstr ""
@@ -6742,6 +6361,14 @@ msgid "Invalid base path"
msgstr ""
#: editor/script_create_dialog.cpp
+msgid "Directory of the same name exists"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
+msgid "File exists, will be reused"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
msgid "Invalid extension"
msgstr ""
@@ -6784,6 +6411,10 @@ msgid "Load existing script file"
msgstr ""
#: editor/script_create_dialog.cpp
+msgid "Language"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
msgid "Inherits"
msgstr ""
@@ -6825,6 +6456,10 @@ msgid "Function:"
msgstr ""
#: editor/script_editor_debugger.cpp
+msgid "Pick one or more items from the list to display the graph."
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
msgid "Errors"
msgstr ""
@@ -6905,6 +6540,10 @@ msgid "Type"
msgstr ""
#: editor/script_editor_debugger.cpp
+msgid "Format"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
msgid "Usage"
msgstr ""
@@ -6980,12 +6619,28 @@ msgstr ""
msgid "Change Probe Extents"
msgstr ""
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Library"
+msgstr ""
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Status"
+msgstr ""
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Libraries: "
+msgstr ""
+
+#: modules/gdnative/register_types.cpp
+msgid "GDNative"
+msgstr ""
+
#: modules/gdscript/gd_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Invalid type argument to convert(), use TYPE_* constants."
msgstr "Tipo de argumento inválido para convert(), use constantes TYPE_*."
-#: modules/gdscript/gd_functions.cpp
+#: modules/gdscript/gd_functions.cpp modules/mono/glue/glue_header.h
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Not enough bytes for decoding bytes, or invalid format."
msgstr ""
@@ -7039,10 +6694,6 @@ msgid "GridMap Duplicate Selection"
msgstr ""
#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "GridMap Paint"
-msgstr ""
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Snap View"
msgstr ""
@@ -7134,12 +6785,8 @@ msgstr ""
msgid "Pick Distance:"
msgstr ""
-#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "Tiles"
-msgstr ""
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "Areas"
+#: modules/mono/editor/mono_bottom_panel.cpp
+msgid "Builds"
msgstr ""
#: modules/visual_script/visual_script.cpp
@@ -7342,10 +6989,18 @@ msgid "Return"
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
+msgid "Call"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
msgid "Get"
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
+msgid "Script already has function '%s'"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
msgid "Change Input Value"
msgstr ""
@@ -7702,6 +7357,12 @@ msgid ""
"order for AnimatedSprite3D to display frames."
msgstr ""
+#: scene/3d/vehicle_body.cpp
+msgid ""
+"VehicleWheel serves to provide a wheel system to a VehicleBody. Please use "
+"it as a child of a VehicleBody."
+msgstr ""
+
#: scene/gui/color_picker.cpp
msgid "Raw Mode"
msgstr ""
@@ -7711,15 +7372,15 @@ msgid "Add current color as a preset"
msgstr ""
#: scene/gui/dialogs.cpp
-msgid "Alert!"
+msgid "Cancel"
msgstr ""
#: scene/gui/dialogs.cpp
-msgid "Please Confirm..."
+msgid "Alert!"
msgstr ""
-#: scene/gui/input_action.cpp
-msgid "Ctrl+"
+#: scene/gui/dialogs.cpp
+msgid "Please Confirm..."
msgstr ""
#: scene/gui/popup.cpp
@@ -7750,6 +7411,22 @@ msgid ""
"texture to some node for display."
msgstr ""
+#: scene/resources/dynamic_font.cpp
+msgid "Error initializing FreeType."
+msgstr ""
+
+#: scene/resources/dynamic_font.cpp
+msgid "Unknown font format."
+msgstr ""
+
+#: scene/resources/dynamic_font.cpp
+msgid "Error loading font."
+msgstr ""
+
+#: scene/resources/dynamic_font.cpp
+msgid "Invalid font size."
+msgstr ""
+
#, fuzzy
#~ msgid "Invalid unique name."
#~ msgstr "Nome de índice propriedade inválido."
diff --git a/editor/translations/ru.po b/editor/translations/ru.po
index 61d7ae7dae..05c164c3ee 100644
--- a/editor/translations/ru.po
+++ b/editor/translations/ru.po
@@ -1,17 +1,20 @@
# Russian translation of the Godot Engine editor
-# Copyright (C) 2016-2017 Juan Linietsky, Ariel Manzur and the Godot community
+# Copyright (C) 2007-2017 Juan Linietsky, Ariel Manzur
+# Copyright (C) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)
# This file is distributed under the same license as the Godot source code.
#
+# B10nicMachine <shumik1337@gmail.com>, 2017.
# DimOkGamer <dimokgamer@gmail.com>, 2016-2017.
# ijet <my-ijet@mail.ru>, 2017.
# Maxim Kim <habamax@gmail.com>, 2016.
# Maxim toby3d Lebedev <mail@toby3d.ru>, 2016.
+# pitchblack <pitchblack@mail.ru>, 2017.
#
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2017-07-25 09:47+0000\n"
+"PO-Revision-Date: 2017-10-26 14:49+0000\n"
"Last-Translator: ijet <my-ijet@mail.ru>\n"
"Language-Team: Russian <https://hosted.weblate.org/projects/godot-engine/"
"godot/ru/>\n"
@@ -21,7 +24,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
-"X-Generator: Weblate 2.16-dev\n"
+"X-Generator: Weblate 2.17\n"
#: editor/animation_editor.cpp
msgid "Disabled"
@@ -197,10 +200,9 @@ msgid "Create %d NEW tracks and insert keys?"
msgstr "Создать %d новые дорожки и вÑтавить ключи?"
#: editor/animation_editor.cpp editor/create_dialog.cpp
-#: editor/editor_audio_buses.cpp
+#: editor/editor_audio_buses.cpp editor/plugins/abstract_polygon_2d_editor.cpp
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
#: editor/plugins/mesh_instance_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp editor/project_manager.cpp
#: editor/script_create_dialog.cpp
msgid "Create"
@@ -362,261 +364,6 @@ msgstr "Изменение типа Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð¼Ð°ÑÑива"
msgid "Change Array Value"
msgstr "Изменить значение маÑÑива"
-#: editor/asset_library_editor_plugin.cpp
-msgid "Free"
-msgstr "ОÑвободить"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_plugin_settings.cpp
-msgid "Version:"
-msgstr "ВерÑиÑ:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Contents:"
-msgstr "Содержание:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "View Files"
-msgstr "ПроÑмотр Файлов"
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_help.cpp editor/property_selector.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Description:"
-msgstr "ОпиÑание:"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-#: editor/project_manager.cpp
-msgid "Install"
-msgstr "УÑтановить"
-
-#: editor/asset_library_editor_plugin.cpp editor/call_dialog.cpp
-#: editor/connections_dialog.cpp editor/export_template_manager.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-#: editor/project_settings_editor.cpp editor/property_editor.cpp
-#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Close"
-msgstr "Закрыть"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve hostname:"
-msgstr "Ðевозможно определить Ð¸Ð¼Ñ Ñ…Ð¾Ñта:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve."
-msgstr "Ðе удаетÑÑ Ñ€Ð°Ð·Ñ€ÐµÑˆÐ¸Ñ‚ÑŒ."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Connection error, please try again."
-msgstr "Ошибка подключениÑ, попробуйте еще раз."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't connect."
-msgstr "Ðе удаетÑÑ Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡Ð¸Ñ‚ÑŒÑÑ."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't connect to host:"
-msgstr "Ðе удаетÑÑ Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡Ð¸Ñ‚ÑŒÑÑ Ðº хоÑту:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response from host:"
-msgstr "Ðет ответа от хоÑта:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response."
-msgstr "Ðет ответа."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Request failed, return code:"
-msgstr "Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð½Ðµ удалÑÑ, код:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Req. Failed."
-msgstr "Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð½Ðµ прошел."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Request failed, too many redirects"
-msgstr "Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð½Ðµ прошел, Ñлишком много перенаправлений"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Redirect Loop."
-msgstr "ЦикличеÑкое перенаправление."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed:"
-msgstr "Ðе удалоÑÑŒ:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Bad download hash, assuming file has been tampered with."
-msgstr "ÐеÑовпадение Ñ…Ñша загрузки, возможно файл был изменен."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Expected:"
-msgstr "ОжидаетÑÑ:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Got:"
-msgstr "Получил:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
-msgstr "Ðе удалоÑÑŒ проверить sha256 Ñ…Ñш"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Asset Download Error:"
-msgstr "Ошибка Загрузки Шаблона:"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-msgid "Success!"
-msgstr "УÑпех!"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Fetching:"
-msgstr "Извлечение:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Resolving.."
-msgstr "ИнициализациÑ..."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Connecting.."
-msgstr "Подключение.."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Requesting.."
-msgstr "Запрашиваю.."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Error making request"
-msgstr "Ошибка во Ð²Ñ€ÐµÐ¼Ñ Ð·Ð°Ð¿Ñ€Ð¾Ñа"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Idle"
-msgstr "ПроÑтой"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Retry"
-msgstr "Повторить"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Download Error"
-msgstr "Ошибка Загрузки"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Download for this asset is already in progress!"
-msgstr "Загрузка Ñтого шаблона уже идет!"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "first"
-msgstr "первый"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "prev"
-msgstr "предыдущий"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "next"
-msgstr "далее"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "last"
-msgstr "поÑледний"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "All"
-msgstr "Ð’Ñе"
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
-#: editor/settings_config_dialog.cpp
-msgid "Search:"
-msgstr "ПоиÑк:"
-
-#: editor/asset_library_editor_plugin.cpp editor/code_editor.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Search"
-msgstr "ПоиÑк"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/project_manager.cpp
-msgid "Import"
-msgstr "Импорт"
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Plugins"
-msgstr "Плагины"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Sort:"
-msgstr "Сортировать:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Reverse"
-msgstr "Обратно"
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Category:"
-msgstr "КатегориÑ:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Site:"
-msgstr "Сайт:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Support.."
-msgstr "Поддержка.."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Official"
-msgstr "Официальные"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-msgid "Community"
-msgstr "ОбщеÑтвенные"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Testing"
-msgstr "ТеÑтируемые"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Assets ZIP File"
-msgstr "ZIP файл аÑÑетов"
-
-#: editor/call_dialog.cpp
-msgid "Method List For '%s':"
-msgstr "СпиÑок методов Ð´Ð»Ñ '%s':"
-
-#: editor/call_dialog.cpp modules/visual_script/visual_script_editor.cpp
-msgid "Call"
-msgstr "Вызов"
-
-#: editor/call_dialog.cpp
-msgid "Method List:"
-msgstr "СпиÑок методов:"
-
-#: editor/call_dialog.cpp
-msgid "Arguments:"
-msgstr "Ðргументы:"
-
-#: editor/call_dialog.cpp
-msgid "Return:"
-msgstr "Возвращение:"
-
#: editor/code_editor.cpp
msgid "Go to Line"
msgstr "Перейти к Ñтроке"
@@ -653,6 +400,14 @@ msgstr "Целые Ñлова"
msgid "Selection Only"
msgstr "Только выделÑÑ‚ÑŒ"
+#: editor/code_editor.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
+msgid "Search"
+msgstr "ПоиÑк"
+
#: editor/code_editor.cpp editor/editor_help.cpp
msgid "Find"
msgstr "Ðайти"
@@ -685,11 +440,11 @@ msgstr "Подтверждение замены"
msgid "Skip"
msgstr "ПропуÑтить"
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom In"
msgstr "Приблизить"
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom Out"
msgstr "Отдалить"
@@ -758,6 +513,20 @@ msgstr "Отложенное"
msgid "Oneshot"
msgstr "Один раз"
+#: editor/connections_dialog.cpp editor/dependency_editor.cpp
+#: editor/export_template_manager.cpp
+#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Close"
+msgstr "Закрыть"
+
#: editor/connections_dialog.cpp
msgid "Connect"
msgstr "ПриÑоединить"
@@ -783,7 +552,7 @@ msgstr "ПриÑоединить.."
msgid "Disconnect"
msgstr "ОтÑоединить"
-#: editor/connections_dialog.cpp editor/node_dock.cpp
+#: editor/connections_dialog.cpp editor/editor_help.cpp editor/node_dock.cpp
msgid "Signals"
msgstr "Сигналы"
@@ -800,12 +569,25 @@ msgstr "Избранное:"
msgid "Recent:"
msgstr "Ðедавнее:"
+#: editor/create_dialog.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/quick_open.cpp editor/settings_config_dialog.cpp
+msgid "Search:"
+msgstr "ПоиÑк:"
+
#: editor/create_dialog.cpp editor/editor_help.cpp
#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/quick_open.cpp
msgid "Matches:"
msgstr "СовпадениÑ:"
+#: editor/create_dialog.cpp editor/editor_help.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/property_selector.cpp
+#: editor/script_editor_debugger.cpp
+msgid "Description:"
+msgstr "ОпиÑание:"
+
#: editor/dependency_editor.cpp
msgid "Search Replacement For:"
msgstr "ПоиÑк замены длÑ:"
@@ -865,6 +647,10 @@ msgid "Owners Of:"
msgstr "Владельцы:"
#: editor/dependency_editor.cpp
+msgid "Remove selected files from the project? (no undo)"
+msgstr "Удалить выбранный файл из проекта? (ÐÐµÐ»ÑŒÐ·Ñ Ð¾Ñ‚Ð¼ÐµÐ½Ð¸Ñ‚ÑŒ!)"
+
+#: editor/dependency_editor.cpp
msgid ""
"The files being removed are required by other resources in order for them to "
"work.\n"
@@ -874,8 +660,8 @@ msgstr ""
"Ð’ÑÑ‘ равно удалить его? (ÐÐµÐ»ÑŒÐ·Ñ Ð¾Ñ‚Ð¼ÐµÐ½Ð¸Ñ‚ÑŒ!)"
#: editor/dependency_editor.cpp
-msgid "Remove selected files from the project? (no undo)"
-msgstr "Удалить выбранный файл из проекта? (ÐÐµÐ»ÑŒÐ·Ñ Ð¾Ñ‚Ð¼ÐµÐ½Ð¸Ñ‚ÑŒ!)"
+msgid "Cannot remove:\n"
+msgstr "Ðе удаетÑÑ ÑƒÐ´Ð°Ð»Ð¸Ñ‚ÑŒ:\n"
#: editor/dependency_editor.cpp
msgid "Error loading:"
@@ -941,19 +727,12 @@ msgid "Godot Engine contributors"
msgstr "Ðвторы Движка Godot"
#: editor/editor_about.cpp
-#, fuzzy
-msgid "Authors"
-msgstr "Ðвтор:"
-
-#: editor/editor_about.cpp
-#, fuzzy
msgid "Project Founders"
-msgstr "Менеджер проектов"
+msgstr "ОÑнователи Проекта"
#: editor/editor_about.cpp
-#, fuzzy
msgid "Lead Developer"
-msgstr "Разработчики"
+msgstr "Ведущий Разработчик"
#: editor/editor_about.cpp editor/project_manager.cpp
msgid "Project Manager"
@@ -964,12 +743,44 @@ msgid "Developers"
msgstr "Разработчики"
#: editor/editor_about.cpp
+msgid "Authors"
+msgstr "Ðвторы"
+
+#: editor/editor_about.cpp
+msgid "Platinum Sponsors"
+msgstr "Платиновые СпонÑоры"
+
+#: editor/editor_about.cpp
+msgid "Gold Sponsors"
+msgstr "Золотые СпонÑоры"
+
+#: editor/editor_about.cpp
+msgid "Mini Sponsors"
+msgstr "Мини СпонÑоры"
+
+#: editor/editor_about.cpp
+msgid "Gold Donors"
+msgstr "Золотые Доноры"
+
+#: editor/editor_about.cpp
+msgid "Silver Donors"
+msgstr "СеребрÑные Доноры"
+
+#: editor/editor_about.cpp
+msgid "Bronze Donors"
+msgstr "Бронзовые Доноры"
+
+#: editor/editor_about.cpp
+msgid "Donors"
+msgstr "Доноры"
+
+#: editor/editor_about.cpp
msgid "License"
-msgstr ""
+msgstr "ЛицензиÑ"
#: editor/editor_about.cpp
msgid "Thirdparty License"
-msgstr ""
+msgstr "Сторонние Лицензии"
#: editor/editor_about.cpp
msgid ""
@@ -978,104 +789,108 @@ msgid ""
"is an exhaustive list of all such thirdparty components with their "
"respective copyright statements and license terms."
msgstr ""
+"Движок godot опираетÑÑ Ð½Ð° Ñ€Ñд Ñторонних беÑплатных и открытых библиотек, "
+"ÑовмеÑтимых Ñ ÑƒÑловиÑми лицензии MIT. Ðиже приводитÑÑ Ð¸Ñчерпывающий ÑпиÑок "
+"вÑех Ñторонних компонентов вмеÑте Ñ Ð¸Ñ… авторÑкими правами и уÑловиÑми "
+"лицензионного ÑоглашениÑ."
#: editor/editor_about.cpp
-#, fuzzy
msgid "All Components"
-msgstr "Содержание:"
+msgstr "Ð’Ñе компоненты"
#: editor/editor_about.cpp
-#, fuzzy
msgid "Components"
-msgstr "Содержание:"
+msgstr "Компоненты"
#: editor/editor_about.cpp
msgid "Licenses"
-msgstr ""
+msgstr "Лицензии"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Error opening package file, not in zip format."
-msgstr ""
+msgstr "Ошибка при открытии файла, не в формате zip."
#: editor/editor_asset_installer.cpp
-#, fuzzy
msgid "Uncompressing Assets"
-msgstr "ÐеÑжатый"
+msgstr "РаÑпаковка аÑÑетов"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package Installed Successfully!"
msgstr "Пакет уÑпешно уÑтановлен!"
#: editor/editor_asset_installer.cpp
-#, fuzzy
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Success!"
+msgstr "УÑпех!"
+
+#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/project_manager.cpp
+msgid "Install"
+msgstr "УÑтановить"
+
+#: editor/editor_asset_installer.cpp
msgid "Package Installer"
-msgstr "Пакет уÑпешно уÑтановлен!"
+msgstr "УÑтановщик пакетов"
#: editor/editor_audio_buses.cpp
msgid "Speakers"
-msgstr ""
+msgstr "Колонки"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Add Effect"
-msgstr "Добавить Ñобытие"
+msgstr "Добавить Ñффект"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Rename Audio Bus"
-msgstr "Открыть раÑкладку звуковой шины"
+msgstr "Переименовать аудио шину"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Toggle Audio Bus Solo"
-msgstr "Открыть раÑкладку звуковой шины"
+msgstr "Переключить аудио шину - Ñоло"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Toggle Audio Bus Mute"
-msgstr "Открыть раÑкладку звуковой шины"
+msgstr "Переключить аудио шину - тишина"
#: editor/editor_audio_buses.cpp
msgid "Toggle Audio Bus Bypass Effects"
-msgstr ""
+msgstr "Переключить аудио шину - bypass Ñффект"
#: editor/editor_audio_buses.cpp
msgid "Select Audio Bus Send"
-msgstr ""
+msgstr "Выбор передача аудио шины"
#: editor/editor_audio_buses.cpp
msgid "Add Audio Bus Effect"
-msgstr ""
+msgstr "Добавить аудио Ñффект"
#: editor/editor_audio_buses.cpp
msgid "Move Bus Effect"
-msgstr ""
+msgstr "Передвинуть Ñффект"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Delete Bus Effect"
-msgstr "Удалить выделенное"
+msgstr "Удалить Ñффект шины"
#: editor/editor_audio_buses.cpp
msgid "Audio Bus, Drag and Drop to rearrange."
-msgstr ""
-
-#: editor/editor_audio_buses.cpp
-#, fuzzy
-msgid "Bus options"
-msgstr "Опции вложенной Ñцены"
+msgstr "Ðудио шина, перетащите Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ³Ñ€ÑƒÐ¿Ð¿Ð¸Ñ€Ð¾Ð²ÐºÐ¸."
#: editor/editor_audio_buses.cpp
msgid "Solo"
-msgstr ""
+msgstr "Соло"
#: editor/editor_audio_buses.cpp
msgid "Mute"
-msgstr ""
+msgstr "Заглушить"
#: editor/editor_audio_buses.cpp
msgid "Bypass"
-msgstr ""
+msgstr "Bypass"
+
+#: editor/editor_audio_buses.cpp
+msgid "Bus options"
+msgstr "Параметры шины"
#: editor/editor_audio_buses.cpp editor/plugins/tile_map_editor_plugin.cpp
#: editor/scene_tree_dock.cpp
@@ -1083,33 +898,36 @@ msgid "Duplicate"
msgstr "Дублировать"
#: editor/editor_audio_buses.cpp
-#, fuzzy
+msgid "Reset Volume"
+msgstr "СброÑить громкоÑÑ‚ÑŒ"
+
+#: editor/editor_audio_buses.cpp
msgid "Delete Effect"
-msgstr "Удалить выделенное"
+msgstr "Удалить Ñффект"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Add Audio Bus"
-msgstr "Добавить"
+msgstr "Добавить аудио шину"
#: editor/editor_audio_buses.cpp
msgid "Master bus can't be deleted!"
-msgstr ""
+msgstr "МаÑтер шина не может быть удалена!"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Delete Audio Bus"
-msgstr "Удалить макет"
+msgstr "Удалить аудио шину"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Duplicate Audio Bus"
-msgstr "Дублировать анимацию"
+msgstr "Дублировать аудио шину"
+
+#: editor/editor_audio_buses.cpp
+msgid "Reset Bus Volume"
+msgstr "СброÑить громкоÑÑ‚ÑŒ шины"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Move Audio Bus"
-msgstr "ПеремеÑтить дейÑтвие"
+msgstr "ПеремеÑтить аудио шину"
#: editor/editor_audio_buses.cpp
msgid "Save Audio Bus Layout As.."
@@ -1125,32 +943,28 @@ msgstr "Открыть раÑкладку звуковой шины"
#: editor/editor_audio_buses.cpp
msgid "There is no 'res://default_bus_layout.tres' file."
-msgstr ""
+msgstr "ОтÑутÑтвует файл «res://default_bus_layout.tres»."
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Invalid file, not an audio bus layout."
-msgstr ""
-"ÐедопуÑтимое раÑширение файла.\n"
-"ПожалуйÑта, иÑпользуйте .font."
+msgstr "ÐедопуÑтимый файл, не раÑкладка аудио шины."
#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr "Добавить"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Create a new Bus Layout."
-msgstr "Создать новый реÑурÑ"
+msgstr "Создать новую раÑкладку шины."
-#: editor/editor_audio_buses.cpp editor/script_create_dialog.cpp
+#: editor/editor_audio_buses.cpp editor/property_editor.cpp
+#: editor/script_create_dialog.cpp
msgid "Load"
msgstr "Загрузить"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Load an existing Bus Layout."
-msgstr "Загрузить ÑущеÑтвующий реÑÑƒÑ€Ñ Ñ Ð´Ð¸Ñка и редактировать его."
+msgstr "Загрузить ÑущеÑтвующую раÑкладку шины."
#: editor/editor_audio_buses.cpp
#: editor/plugins/animation_player_editor_plugin.cpp
@@ -1158,18 +972,16 @@ msgid "Save As"
msgstr "Сохранить как"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Save this Bus Layout to a file."
-msgstr "Сохранить раÑкладку звуковой шины как.."
+msgstr "Сохранить текущую раÑкладку звуковой шины в файл."
#: editor/editor_audio_buses.cpp editor/import_dock.cpp
-#, fuzzy
msgid "Load Default"
-msgstr "По-умолчанию"
+msgstr "Загрузить по умолчанию"
#: editor/editor_audio_buses.cpp
msgid "Load the default Bus Layout."
-msgstr ""
+msgstr "Загрузить Ñтандартную раÑкладку шины."
#: editor/editor_autoload_settings.cpp
msgid "Invalid name."
@@ -1242,7 +1054,7 @@ msgid "Rearrange Autoloads"
msgstr "ПереÑтановка автозагрузок"
#: editor/editor_autoload_settings.cpp editor/editor_file_dialog.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp scene/gui/file_dialog.cpp
+#: scene/gui/file_dialog.cpp
msgid "Path:"
msgstr "Путь:"
@@ -1250,9 +1062,7 @@ msgstr "Путь:"
msgid "Node Name:"
msgstr "Ð˜Ð¼Ñ Ð£Ð·Ð»Ð°:"
-#: editor/editor_autoload_settings.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp editor/project_manager.cpp
+#: editor/editor_autoload_settings.cpp editor/project_manager.cpp
msgid "Name"
msgstr "ИмÑ"
@@ -1277,27 +1087,27 @@ msgid "Updating scene.."
msgstr "Обновление Ñцены.."
#: editor/editor_dir_dialog.cpp
-#, fuzzy
msgid "Please select a base directory first"
-msgstr "ПожалуйÑта Ñначала Ñохраните Ñцену."
+msgstr "ПожалуйÑта, выберите базовый каталог"
#: editor/editor_dir_dialog.cpp
msgid "Choose a Directory"
msgstr "Выбрать каталог"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Create Folder"
msgstr "Создать папку"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: editor/editor_plugin_settings.cpp editor/plugins/theme_editor_plugin.cpp
-#: editor/project_export.cpp scene/gui/file_dialog.cpp
+#: editor/editor_plugin_settings.cpp editor/filesystem_dock.cpp
+#: editor/plugins/theme_editor_plugin.cpp editor/project_export.cpp
+#: scene/gui/file_dialog.cpp
msgid "Name:"
msgstr "ИмÑ:"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Could not create folder."
msgstr "Ðевозможно Ñоздать папку."
@@ -1317,30 +1127,6 @@ msgstr "Упаковывание"
msgid "Template file not found:\n"
msgstr "Файл шаблона не найден:\n"
-#: editor/editor_export.cpp
-msgid "Added:"
-msgstr "Добавлено:"
-
-#: editor/editor_export.cpp
-msgid "Removed:"
-msgstr "Удалено:"
-
-#: editor/editor_export.cpp
-msgid "Error saving atlas:"
-msgstr "Ошибка ÑÐ¾Ñ…Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ Ð°Ñ‚Ð»Ð°Ñа:"
-
-#: editor/editor_export.cpp
-msgid "Could not save atlas subtexture:"
-msgstr "Ðевозможно Ñохранить текÑтуру атлаÑа:"
-
-#: editor/editor_export.cpp
-msgid "Exporting for %s"
-msgstr "ЭкÑпортирование Ð´Ð»Ñ %s"
-
-#: editor/editor_export.cpp
-msgid "Setting Up.."
-msgstr "ÐаÑтройка.."
-
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "File Exists, Overwrite?"
msgstr "Файл ÑущеÑтвует, перезапиÑать?"
@@ -1425,6 +1211,10 @@ msgstr "ПеремеÑтить избранное вверх"
msgid "Move Favorite Down"
msgstr "ПеремеÑтить избранное вниз"
+#: editor/editor_file_dialog.cpp
+msgid "Go to parent folder"
+msgstr "Перейти к родительÑкой папке"
+
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Directories & Files:"
msgstr "Каталоги и файлы:"
@@ -1439,10 +1229,6 @@ msgid "File:"
msgstr "Файл:"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
-msgid "Filter:"
-msgstr "Фильтр:"
-
-#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Must use a valid extension."
msgstr "Ðужно иÑпользовать доÑтупное раÑширение."
@@ -1467,6 +1253,10 @@ msgstr "СпиÑок клаÑÑов:"
msgid "Search Classes"
msgstr "ПоиÑк клаÑÑов"
+#: editor/editor_help.cpp editor/plugins/spatial_editor_plugin.cpp
+msgid "Top"
+msgstr "Верх"
+
#: editor/editor_help.cpp editor/property_editor.cpp
msgid "Class:"
msgstr "КлаÑÑ:"
@@ -1483,15 +1273,27 @@ msgstr "УнаÑледован:"
msgid "Brief Description:"
msgstr "Краткое опиÑание:"
+#: editor/editor_help.cpp
+msgid "Members"
+msgstr "УчаÑтники"
+
#: editor/editor_help.cpp modules/visual_script/visual_script_editor.cpp
msgid "Members:"
msgstr "УчаÑтники:"
#: editor/editor_help.cpp
+msgid "Public Methods"
+msgstr "Публичные методы"
+
+#: editor/editor_help.cpp
msgid "Public Methods:"
msgstr "СпиÑок методов:"
#: editor/editor_help.cpp
+msgid "GUI Theme Items"
+msgstr "Тема Ñлементов GUI"
+
+#: editor/editor_help.cpp
msgid "GUI Theme Items:"
msgstr "Тема Ñлементов GUI:"
@@ -1500,54 +1302,85 @@ msgid "Signals:"
msgstr "Сигналы:"
#: editor/editor_help.cpp
-#, fuzzy
+msgid "Enumerations"
+msgstr "ПеречиÑлениÑ"
+
+#: editor/editor_help.cpp
msgid "Enumerations:"
-msgstr "Ðнимации"
+msgstr "ПеречиÑлениÑ:"
#: editor/editor_help.cpp
msgid "enum "
-msgstr ""
+msgstr "перечиÑление "
+
+#: editor/editor_help.cpp
+msgid "Constants"
+msgstr "КонÑтанты"
#: editor/editor_help.cpp
msgid "Constants:"
msgstr "КонÑтанты:"
#: editor/editor_help.cpp
+msgid "Description"
+msgstr "ОпиÑание"
+
+#: editor/editor_help.cpp
+msgid "Properties"
+msgstr "СвойÑтва"
+
+#: editor/editor_help.cpp
msgid "Property Description:"
msgstr "ОпиÑание ÑвойÑтва:"
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this property. Please help us by "
+"[color=$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+"Ð’ наÑтоÑщее Ð²Ñ€ÐµÐ¼Ñ Ð¾Ñ‚ÑутÑтвует опиÑание Ñтого ÑвойÑтва. ПожалуйÑта [color="
+"$color][url=$url]помогите нам[/url][/color]!"
+
+#: editor/editor_help.cpp
+msgid "Methods"
+msgstr "Методы"
+
+#: editor/editor_help.cpp
msgid "Method Description:"
msgstr "ОпиÑание методов:"
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this method. Please help us by [color="
+"$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+"Ð’ наÑтоÑщее Ð²Ñ€ÐµÐ¼Ñ Ð¾Ñ‚ÑутÑтвует опиÑание Ñтого метода. ПожалуйÑта [color="
+"$color][url=$url]помогите нам[/url][/color]!"
+
+#: editor/editor_help.cpp
msgid "Search Text"
msgstr "ИÑкать текÑÑ‚"
#: editor/editor_log.cpp
-#, fuzzy
msgid "Output:"
-msgstr " Вывод:"
+msgstr "Вывод:"
#: editor/editor_log.cpp editor/plugins/animation_tree_editor_plugin.cpp
-#: editor/plugins/rich_text_editor_plugin.cpp editor/property_editor.cpp
-#: editor/script_editor_debugger.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/property_editor.cpp editor/script_editor_debugger.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Clear"
msgstr "ОчиÑтить"
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Error saving resource!"
msgstr "Ошибка при Ñохранении реÑурÑа!"
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Save Resource As.."
msgstr "Сохранить реÑÑƒÑ€Ñ ÐºÐ°Ðº.."
-#: editor/editor_node.cpp editor/export_template_manager.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "I see.."
msgstr "ЯÑно.."
@@ -1564,6 +1397,26 @@ msgid "Error while saving."
msgstr "Ошибка при Ñохранении."
#: editor/editor_node.cpp
+msgid "Can't open '%s'."
+msgstr "Ðе удаетÑÑ Ð¾Ñ‚ÐºÑ€Ñ‹Ñ‚ÑŒ '%s'."
+
+#: editor/editor_node.cpp
+msgid "Error while parsing '%s'."
+msgstr "Ошибка при разборе '%s'."
+
+#: editor/editor_node.cpp
+msgid "Unexpected end of file '%s'."
+msgstr "Ðеожиданный конец файла '%s'."
+
+#: editor/editor_node.cpp
+msgid "Missing '%s' or its dependencies."
+msgstr "ОтÑутÑтвует '%s' или его завиÑимоÑти."
+
+#: editor/editor_node.cpp
+msgid "Error while loading '%s'."
+msgstr "Ошибка при загрузке '%s'."
+
+#: editor/editor_node.cpp
msgid "Saving Scene"
msgstr "Сохранение Ñцены"
@@ -1576,9 +1429,8 @@ msgid "Creating Thumbnail"
msgstr "Создание ÑÑкизов"
#: editor/editor_node.cpp
-#, fuzzy
msgid "This operation can't be done without a tree root."
-msgstr "Эта Ð¾Ð¿ÐµÑ€Ð°Ñ†Ð¸Ñ Ð½Ðµ может быть выполнена без Ñцены."
+msgstr "Эта Ð¾Ð¿ÐµÑ€Ð°Ñ†Ð¸Ñ Ð½Ðµ может быть выполнена без ÐºÐ¾Ñ€Ð½Ñ Ð´ÐµÑ€ÐµÐ²Ð°."
#: editor/editor_node.cpp
msgid ""
@@ -1624,6 +1476,48 @@ msgid "Restored default layout to base settings."
msgstr "Вернуть макет по-умолчанию к Ñтандартному."
#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was imported, so it's not editable.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+"Этот реÑÑƒÑ€Ñ Ð¿Ñ€Ð¸Ð½Ð°Ð´Ð»ÐµÐ¶Ð¸Ñ‚ Ñцене, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð±Ñ‹Ð»Ð° импортирована, поÑтому он не "
+"редактируетÑÑ.\n"
+"ПожалуйÑта, прочитайте документацию, имеющую отношение к импорту Ñцены, "
+"чтобы лучше понÑÑ‚ÑŒ Ñтот процеÑÑ."
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid ""
+"This resource belongs to a scene that was instanced or inherited.\n"
+"Changes to it will not be kept when saving the current scene."
+msgstr ""
+"Этот реÑÑƒÑ€Ñ Ð¿Ñ€Ð¸Ð½Ð°Ð´Ð»ÐµÐ¶Ð¸Ñ‚ к Ñцене, инÑтанцированной или унаÑледованной.\n"
+"Ð˜Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð½Ðµ будут Ñохранены при Ñохранении текущей Ñцены."
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid ""
+"This resource was imported, so it's not editable. Change its settings in the "
+"import panel and then re-import."
+msgstr ""
+"Этот реÑÑƒÑ€Ñ Ð±Ñ‹Ð» импортирован, поÑтому он не редактируетÑÑ. Измени наÑтройки "
+"в панеле импорта, а затем повторно импортируйте."
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid ""
+"This scene was imported, so changes to it will not be kept.\n"
+"Instancing it or inheriting will allow making changes to it.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+"Эта Ñцена была импортирована, так что Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð½Ðµ будут Ñохранены.\n"
+"ИнÑтанÑинг или наÑледование позволит внеÑти Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð² неё.\n"
+"ПожалуйÑта, прочитайте документацию, имеющую отношение к импорту Ñцены, "
+"чтобы лучше понÑÑ‚ÑŒ Ñтот процеÑÑ."
+
+#: editor/editor_node.cpp
msgid "Copy Params"
msgstr "Копировать параметры"
@@ -1710,13 +1604,12 @@ msgid "Quick Open Script.."
msgstr "БыÑтро открыть Ñкрипт.."
#: editor/editor_node.cpp
-#, fuzzy
msgid "Save & Close"
-msgstr "Сохранить файл"
+msgstr "Сохранить и закрыть"
#: editor/editor_node.cpp
msgid "Save changes to '%s' before closing?"
-msgstr ""
+msgstr "Сохранить Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð² «%s» перед закрытием?"
#: editor/editor_node.cpp
msgid "Save Scene As.."
@@ -1747,9 +1640,8 @@ msgid "Export Tile Set"
msgstr "ЭкÑпортировать набор тайлов"
#: editor/editor_node.cpp
-#, fuzzy
msgid "This operation can't be done without a selected node."
-msgstr "Эта Ð¾Ð¿ÐµÑ€Ð°Ñ†Ð¸Ñ Ð½Ðµ может быть выполнена без Ñцены."
+msgstr "Эта Ð¾Ð¿ÐµÑ€Ð°Ñ†Ð¸Ñ Ð½Ðµ может быть выполнена без выбранного узла."
#: editor/editor_node.cpp
msgid "Current scene not saved. Open anyway?"
@@ -1780,42 +1672,59 @@ msgid "Exit the editor?"
msgstr "Выйти из редактора?"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Open Project Manager?"
-msgstr "Менеджер проектов"
+msgstr "Открыть менеджер проектов?"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Save & Quit"
-msgstr "Сохранить файл"
+msgstr "Сохранить и выйти"
#: editor/editor_node.cpp
msgid "Save changes to the following scene(s) before quitting?"
-msgstr ""
+msgstr "Сохранить Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð² Ñледующей Ñцене(Ñ‹) перед выходом?"
#: editor/editor_node.cpp
msgid "Save changes the following scene(s) before opening Project Manager?"
msgstr ""
+"Сохранить Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð² Ñледующей Ñцене(Ñ‹) перед открытием менеджера проектов?"
+
+#: editor/editor_node.cpp
+msgid ""
+"This option is deprecated. Situations where refresh must be forced are now "
+"considered a bug. Please report."
+msgstr ""
+"Этот параметр уÑтаревший. Ситуации, в которых необходимо принудительное "
+"обновление ÑчитаютÑÑ Ð¾ÑˆÐ¸Ð±ÐºÐ¾Ð¹. ПроÑьба Ñообщить."
#: editor/editor_node.cpp
msgid "Pick a Main Scene"
msgstr "Выберите главную Ñцену"
#: editor/editor_node.cpp
-msgid "Unable to enable addon plugin at: '"
-msgstr ""
+#, fuzzy
+msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
+msgstr "Ðе удаетÑÑ Ð²ÐºÐ»ÑŽÑ‡Ð¸Ñ‚ÑŒ плагин: '"
#: editor/editor_node.cpp
-msgid "' parsing of config failed."
-msgstr ""
+#, fuzzy
+msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
+msgstr "Ðе удаетÑÑ Ð½Ð°Ð¹Ñ‚Ð¸ поле script Ð´Ð»Ñ Ð¿Ð»Ð°Ð³Ð¸Ð½Ð°: ' res://addons/"
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/"
-msgstr ""
+#, fuzzy
+msgid "Unable to load addon script from path: '%s'."
+msgstr "Ðе удалоÑÑŒ загрузить Ñкрипт из иÑточника: '"
#: editor/editor_node.cpp
-msgid "Unable to load addon script from path: '"
-msgstr ""
+#, fuzzy
+msgid ""
+"Unable to load addon script from path: '%s' Base type is not EditorPlugin."
+msgstr "Ðе удалоÑÑŒ загрузить Ñкрипт из иÑточника: '"
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Unable to load addon script from path: '%s' Script is not in tool mode."
+msgstr "Ðе удалоÑÑŒ загрузить Ñкрипт из иÑточника: '"
#: editor/editor_node.cpp
msgid ""
@@ -1827,7 +1736,7 @@ msgstr ""
"Чтобы её изменить нужно Ñоздать новую унаÑледованную Ñцену."
#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/scene_tree_dock.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Ugh"
msgstr "ЯÑно"
@@ -1841,14 +1750,14 @@ msgstr ""
"проекта."
#: editor/editor_node.cpp
-msgid "Error loading scene."
-msgstr "Ошибка загрузки Ñцены."
-
-#: editor/editor_node.cpp
msgid "Scene '%s' has broken dependencies:"
msgstr "Сцена '%s' имеет иÑпорченные завиÑимоÑти:"
#: editor/editor_node.cpp
+msgid "Clear Recent Scenes"
+msgstr "ОчиÑтить поÑледние Ñцены"
+
+#: editor/editor_node.cpp
msgid "Save Layout"
msgstr "Сохранить макет"
@@ -1863,7 +1772,7 @@ msgstr "По-умолчанию"
#: editor/editor_node.cpp
msgid "Switch Scene Tab"
-msgstr "Смена вкладки Ñо Ñценой"
+msgstr "Переключить вкладку Ñцены"
#: editor/editor_node.cpp
msgid "%d more file(s)"
@@ -1878,11 +1787,10 @@ msgid "Distraction Free Mode"
msgstr "Свободный режим"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Toggle distraction-free mode."
-msgstr "Свободный режим"
+msgstr "Переключить режим без отвлечениÑ."
-#: editor/editor_node.cpp editor/io_plugins/editor_scene_import_plugin.cpp
+#: editor/editor_node.cpp
msgid "Scene"
msgstr "Сцена"
@@ -2050,7 +1958,7 @@ msgstr ""
#: editor/editor_node.cpp
msgid "Sync Scene Changes"
-msgstr "Ð¡Ð¸Ð½Ñ…Ñ€Ð¾Ð½Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ð¹ на Ñцене"
+msgstr "Ð¡Ð¸Ð½Ñ…Ñ€Ð¾Ð½Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ð¹ в Ñцене"
#: editor/editor_node.cpp
msgid ""
@@ -2120,6 +2028,10 @@ msgstr "ВопроÑÑ‹ и ответы"
msgid "Issue Tracker"
msgstr "СиÑтема отÑÐ»ÐµÐ¶Ð¸Ð²Ð°Ð½Ð¸Ñ Ð¾ÑˆÐ¸Ð±Ð¾Ðº"
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+msgid "Community"
+msgstr "ОбщеÑтвенные"
+
#: editor/editor_node.cpp
msgid "About"
msgstr "О движке"
@@ -2128,7 +2040,7 @@ msgstr "О движке"
msgid "Play the project."
msgstr "ЗапуÑтить проект."
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Play"
msgstr "ВоÑпроизвеÑти"
@@ -2144,7 +2056,7 @@ msgstr "ПриоÑтановить Ñцену"
msgid "Stop the scene."
msgstr "ОÑтановить Ñцену."
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Stop"
msgstr "ОÑтановить"
@@ -2217,6 +2129,15 @@ msgid "Object properties."
msgstr "СвойÑтва объекта."
#: editor/editor_node.cpp
+msgid "Changes may be lost!"
+msgstr "Ð˜Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¼Ð¾Ð³ÑƒÑ‚ быть потерÑны!"
+
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Import"
+msgstr "Импорт"
+
+#: editor/editor_node.cpp
msgid "FileSystem"
msgstr "Ð¤Ð°Ð¹Ð»Ð¾Ð²Ð°Ñ ÑиÑтема"
@@ -2230,15 +2151,7 @@ msgstr "Вывод"
#: editor/editor_node.cpp
msgid "Don't Save"
-msgstr ""
-
-#: editor/editor_node.cpp editor/editor_reimport_dialog.cpp
-msgid "Re-Import"
-msgstr "Переимпортировать"
-
-#: editor/editor_node.cpp editor/editor_plugin_settings.cpp
-msgid "Update"
-msgstr "Обновление"
+msgstr "Ðе ÑохранÑÑ‚ÑŒ"
#: editor/editor_node.cpp
msgid "Import Templates From ZIP File"
@@ -2265,9 +2178,8 @@ msgid "Open & Run a Script"
msgstr "Открыть и запуÑтить Ñкрипт"
#: editor/editor_node.cpp
-#, fuzzy
msgid "New Inherited"
-msgstr "ÐÐ¾Ð²Ð°Ñ ÑƒÐ½Ð°ÑÐ»ÐµÐ´Ð¾Ð²Ð°Ð½Ð½Ð°Ñ Ð¡Ñ†ÐµÐ½Ð°.."
+msgstr "ÐÐ¾Ð²Ð°Ñ ÑƒÐ½Ð°ÑÐ»ÐµÐ´Ð¾Ð²Ð°Ð½Ð½Ð°Ñ Ð¡Ñ†ÐµÐ½Ð°"
#: editor/editor_node.cpp
msgid "Load Errors"
@@ -2301,11 +2213,28 @@ msgstr "Открыть Ñледующий редактор"
msgid "Open the previous Editor"
msgstr "Открыть предыдущий редактор"
+#: editor/editor_plugin.cpp
+msgid "Creating Mesh Previews"
+msgstr "Создание предпроÑмотра"
+
+#: editor/editor_plugin.cpp
+msgid "Thumbnail.."
+msgstr "Миниатюра.."
+
#: editor/editor_plugin_settings.cpp
msgid "Installed Plugins:"
msgstr "УÑтановленные плагины:"
#: editor/editor_plugin_settings.cpp
+msgid "Update"
+msgstr "Обновление"
+
+#: editor/editor_plugin_settings.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Version:"
+msgstr "ВерÑиÑ:"
+
+#: editor/editor_plugin_settings.cpp
msgid "Author:"
msgstr "Ðвтор:"
@@ -2338,7 +2267,8 @@ msgid "Frame %"
msgstr "Кадр %"
#: editor/editor_profiler.cpp
-msgid "Fixed Frame %"
+#, fuzzy
+msgid "Physics Frame %"
msgstr "ФикÑированный кадр %"
#: editor/editor_profiler.cpp editor/script_editor_debugger.cpp
@@ -2357,35 +2287,17 @@ msgstr "СущноÑÑ‚ÑŒ"
msgid "Frame #:"
msgstr "Кадр #:"
-#: editor/editor_reimport_dialog.cpp
-msgid "Please wait for scan to complete."
-msgstr "ПожалуйÑта дождитеÑÑŒ Ð¾ÐºÐ¾Ð½Ñ‡Ð°Ð½Ð¸Ñ ÑканированиÑ."
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Current scene must be saved to re-import."
-msgstr "Ð¢ÐµÐºÑƒÑ‰Ð°Ñ Ñцена должна быть Ñохранена Ð´Ð»Ñ Ð¿Ð¾Ð²Ñ‚Ð¾Ñ€Ð½Ð¾Ð³Ð¾ импорта."
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Save & Re-Import"
-msgstr "Сохранить и переимпортировать"
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Importing"
-msgstr "Переимпортировать"
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Import Changed Resources"
-msgstr "Переимпортировать изменённые реÑурÑÑ‹"
-
#: editor/editor_run_native.cpp
msgid "Select device from the list"
-msgstr ""
+msgstr "Выберите уÑтройÑтво из ÑпиÑка"
#: editor/editor_run_native.cpp
msgid ""
"No runnable export preset found for this platform.\n"
"Please add a runnable preset in the export menu."
msgstr ""
+"Ðе найден рабочий ÑкÑпортер Ð´Ð»Ñ Ñтой платформы.\n"
+"ПожалуйÑта, добавьте его в меню ÑкÑпорта."
#: editor/editor_run_script.cpp
msgid "Write your logic in the _run() method."
@@ -2488,10 +2400,6 @@ msgid "Importing:"
msgstr "ИмпортируетÑÑ:"
#: editor/export_template_manager.cpp
-msgid "Loading Export Templates"
-msgstr "Загрузка шаблонов ÑкÑпорта"
-
-#: editor/export_template_manager.cpp
msgid "Current Version:"
msgstr "Ð¢ÐµÐºÑƒÑ‰Ð°Ñ Ð²ÐµÑ€ÑиÑ:"
@@ -2526,60 +2434,73 @@ msgid "Cannot navigate to '"
msgstr "Ðе удалоÑÑŒ перейти к '"
#: editor/filesystem_dock.cpp
-#, fuzzy
+msgid "View items as a grid of thumbnails"
+msgstr "ПроÑмотр Ñлементов в виде миниатюр"
+
+#: editor/filesystem_dock.cpp
+msgid "View items as a list"
+msgstr "ПроÑмотр Ñлементов в виде ÑпиÑка"
+
+#: editor/filesystem_dock.cpp
msgid ""
"\n"
-"Status: Needs Re-Import"
-msgstr "Сохранить и переимпортировать"
+"Status: Import of file failed. Please fix file and reimport manually."
+msgstr ""
+"\n"
+"СтатуÑ: Импорт файла не удалÑÑ. ПожалуйÑта, иÑправьте файл и "
+"переимпортируйте вручную."
#: editor/filesystem_dock.cpp
-#, fuzzy
msgid ""
"\n"
"Source: "
-msgstr "ИÑточник:"
+msgstr ""
+"\n"
+"ИÑточник: "
#: editor/filesystem_dock.cpp
-msgid "Same source and destination files, doing nothing."
-msgstr "Файл Ð½Ð°Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð¸ иÑходный файлы Ñовпадают, нечего делать."
+msgid "Cannot move/rename resources root."
+msgstr "ÐÐµÐ»ÑŒÐ·Ñ Ð¿ÐµÑ€ÐµÐ¼ÐµÑтить/переименовать корень."
#: editor/filesystem_dock.cpp
-msgid "Target file exists, can't overwrite. Delete first."
-msgstr ""
+msgid "Cannot move a folder into itself.\n"
+msgstr "Ðевозможно перемеÑтить папку в ÑебÑ.\n"
#: editor/filesystem_dock.cpp
-msgid "Same source and destination paths, doing nothing."
-msgstr "Путь Ð½Ð°Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð¸ иÑходный пути Ñовпадают, нечего делать."
+msgid "Error moving:\n"
+msgstr "Ошибка перемещениÑ:\n"
#: editor/filesystem_dock.cpp
-msgid "Can't move directories to within themselves."
-msgstr "Ðевозможно перемеÑтить каталоги внутрь ÑебÑ."
+msgid "Unable to update dependencies:\n"
+msgstr "Ðе удаетÑÑ Ð¾Ð±Ð½Ð¾Ð²Ð¸Ñ‚ÑŒ завиÑимоÑти:\n"
#: editor/filesystem_dock.cpp
-msgid "Can't rename deps for:\n"
-msgstr ""
+msgid "No name provided"
+msgstr "Ðе указано имÑ"
#: editor/filesystem_dock.cpp
-#, fuzzy
-msgid "Error moving file:\n"
-msgstr "Ошибка при загрузке изображениÑ:"
+msgid "Provided name contains invalid characters"
+msgstr "Ð˜Ð¼Ñ Ñодержит недопуÑтимые Ñимволы"
#: editor/filesystem_dock.cpp
-#, fuzzy
-msgid "Error moving dir:\n"
-msgstr "Ошибка импортированиÑ:"
+msgid "No name provided."
+msgstr "Ðе предоÑтавлено имÑ."
#: editor/filesystem_dock.cpp
-msgid "Can't operate on '..'"
-msgstr "Ðевозможно работать Ñ '..'"
+msgid "Name contains invalid characters."
+msgstr "Ð˜Ð¼Ñ Ñодержит недопуÑтимые Ñимволы."
#: editor/filesystem_dock.cpp
-msgid "Pick New Name and Location For:"
-msgstr "Выберете новое Ð¸Ð¼Ñ Ð¸ раÑположение длÑ:"
+msgid "A file or folder with this name already exists."
+msgstr "Файл или папка Ñ Ñ‚Ð°ÐºÐ¸Ð¼ именем уже ÑущеÑтвует."
#: editor/filesystem_dock.cpp
-msgid "No files selected!"
-msgstr "Файлы не выбраны!"
+msgid "Renaming file:"
+msgstr "Переименование файла:"
+
+#: editor/filesystem_dock.cpp
+msgid "Renaming folder:"
+msgstr "Переименование папки:"
#: editor/filesystem_dock.cpp
msgid "Expand all"
@@ -2590,40 +2511,36 @@ msgid "Collapse all"
msgstr "Свернуть вÑе"
#: editor/filesystem_dock.cpp
-msgid "Show In File Manager"
-msgstr "ПроÑмотреть в проводнике"
-
-#: editor/filesystem_dock.cpp
-msgid "Instance"
-msgstr "Добавить ÑкземплÑÑ€"
+msgid "Copy Path"
+msgstr "Копировать путь"
#: editor/filesystem_dock.cpp
-msgid "Edit Dependencies.."
-msgstr "Редактировать завиÑимоÑти.."
+msgid "Rename.."
+msgstr "Переименовать.."
#: editor/filesystem_dock.cpp
-msgid "View Owners.."
-msgstr "ПроÑмотреть владельцев.."
+msgid "Move To.."
+msgstr "ПеремеÑтить в.."
#: editor/filesystem_dock.cpp
-msgid "Copy Path"
-msgstr "Копировать путь"
+msgid "New Folder.."
+msgstr "ÐÐ¾Ð²Ð°Ñ Ð¿Ð°Ð¿ÐºÐ°.."
#: editor/filesystem_dock.cpp
-msgid "Rename or Move.."
-msgstr "Переименовать или ПеремеÑтить.."
+msgid "Show In File Manager"
+msgstr "ПроÑмотреть в проводнике"
#: editor/filesystem_dock.cpp
-msgid "Move To.."
-msgstr "ПеремеÑтить в.."
+msgid "Instance"
+msgstr "Добавить ÑкземплÑÑ€"
#: editor/filesystem_dock.cpp
-msgid "Info"
-msgstr "ИнформациÑ"
+msgid "Edit Dependencies.."
+msgstr "Редактировать завиÑимоÑти.."
#: editor/filesystem_dock.cpp
-msgid "Re-Import.."
-msgstr "Переимпортировать.."
+msgid "View Owners.."
+msgstr "ПроÑмотреть владельцев.."
#: editor/filesystem_dock.cpp
msgid "Previous Directory"
@@ -2650,11 +2567,18 @@ msgid ""
"Scanning Files,\n"
"Please Wait.."
msgstr ""
+"Сканирование файлов,\n"
+"пожалуйÑта, подождите..."
#: editor/filesystem_dock.cpp
msgid "Move"
msgstr "ПеремеÑтить"
+#: editor/filesystem_dock.cpp editor/plugins/animation_tree_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Rename"
+msgstr "Переименовать"
+
#: editor/groups_editor.cpp
msgid "Add to Group"
msgstr "Добавить в группу"
@@ -2664,74 +2588,81 @@ msgid "Remove from Group"
msgstr "Удалить из группы"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Import as Single Scene"
-msgstr "Импортирование Ñцены.."
+msgstr "Импорт в виде единой Ñцены"
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Animations"
+msgstr "Импортировать Ñ Ð¾Ñ‚Ð´ÐµÐ»ÐµÐ½Ð½Ñ‹Ð¼Ð¸ анимациÑми"
#: editor/import/resource_importer_scene.cpp
msgid "Import with Separate Materials"
-msgstr ""
+msgstr "Импортировать Ñ Ð¾Ñ‚Ð´ÐµÐ»ÐµÐ½Ð½Ñ‹Ð¼Ð¸ материалами"
#: editor/import/resource_importer_scene.cpp
msgid "Import with Separate Objects"
-msgstr ""
+msgstr "Импортировать Ñ Ñ€Ð°Ð·Ð´ÐµÐ»ÐµÐ½Ð½Ñ‹Ð¼Ð¸ объектами"
#: editor/import/resource_importer_scene.cpp
msgid "Import with Separate Objects+Materials"
-msgstr ""
+msgstr "Импортировать Ñ Ñ€Ð°Ð·Ð´ÐµÐ»ÐµÐ½Ð½Ñ‹Ð¼Ð¸ объектами и материалами"
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Animations"
+msgstr "Импортировать Ñ Ñ€Ð°Ð·Ð´ÐµÐ»ÐµÐ½Ð½Ñ‹Ð¼Ð¸ объектами и анимациÑми"
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Materials+Animations"
+msgstr "Импортировать Ñ Ð¾Ñ‚Ð´ÐµÐ»ÐµÐ½Ð½Ñ‹Ð¼Ð¸ материалами и анимациÑми"
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Materials+Animations"
+msgstr "Импортировать Ñ Ñ€Ð°Ð·Ð´ÐµÐ»ÐµÐ½Ð½Ñ‹Ð¼Ð¸ объектами, материалами и анимациÑми"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Import as Multiple Scenes"
-msgstr "Импорт 3D Ñцены"
+msgstr "Импорт в виде неÑкольких Ñцен"
#: editor/import/resource_importer_scene.cpp
msgid "Import as Multiple Scenes+Materials"
-msgstr ""
+msgstr "Импортировать как неÑколько Ñцен и материалов"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Import Scene"
msgstr "Импортировать Ñцену"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Importing Scene.."
msgstr "Импортирование Ñцены.."
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Running Custom Script.."
msgstr "ЗапуÑк пользовательÑкого Ñкрипта.."
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Couldn't load post-import script:"
msgstr "Ðе могу загрузить Ñкрипт Ð´Ð»Ñ Ð¿Ð¾ÑÑ‚-импорта:"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Invalid/broken script for post-import (check console):"
msgstr "Повреждённый/Ñломанный Ñкрипт Ð´Ð»Ñ Ð¿Ð¾ÑÑ‚-импорта (проверьте конÑоль):"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Error running post-import script:"
msgstr "Ошибка запуÑка поÑÑ‚-импорт Ñкрипта:"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Saving.."
msgstr "Сохранение.."
#: editor/import_dock.cpp
msgid "Set as Default for '%s'"
-msgstr ""
+msgstr "УÑтановить по умолчанию Ð´Ð»Ñ '%s'"
#: editor/import_dock.cpp
msgid "Clear Default for '%s'"
-msgstr ""
+msgstr "ОчиÑтить по умолчанию Ð´Ð»Ñ '%s'"
#: editor/import_dock.cpp
msgid " Files"
@@ -2749,579 +2680,6 @@ msgstr "ПредуÑтановка.."
msgid "Reimport"
msgstr "Переимпортировать"
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "No bit masks to import!"
-msgstr "Ðет битовой маÑки Ð´Ð»Ñ Ð¸Ð¼Ð¿Ð¾Ñ€Ñ‚Ð°!"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path is empty."
-msgstr "Конечный путь пуÑÑ‚."
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must be a complete resource path."
-msgstr "Конечный путь должен быть полным путём к реÑурÑу."
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must exist."
-msgstr "Конечный путь должен ÑущеÑтвовать."
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Save path is empty!"
-msgstr "Путь ÑÐ¾Ñ…Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ Ð¿ÑƒÑÑ‚!"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Import BitMasks"
-msgstr "Импорт битовой маÑки"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s):"
-msgstr "ИÑходные текÑтура(Ñ‹):"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Target Path:"
-msgstr "Целевой путь:"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Accept"
-msgstr "ПринÑÑ‚ÑŒ"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Bit Mask"
-msgstr "Ð‘Ð¸Ñ‚Ð¾Ð²Ð°Ñ Ð¼Ð°Ñка"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No source font file!"
-msgstr "Ðет иÑходного файл шрифта!"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No target font resource!"
-msgstr "Ðет целевого реÑурÑа шрифта!"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"Invalid file extension.\n"
-"Please use .font."
-msgstr ""
-"ÐедопуÑтимое раÑширение файла.\n"
-"ПожалуйÑта, иÑпользуйте .font."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Can't load/process source font."
-msgstr "Ðе удалоÑÑŒ загрузить/иÑполнить иÑходный шрифт."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Couldn't save font."
-msgstr "Ðевозможно Ñохранить шрифт."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font:"
-msgstr "ИÑходный шрифт:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font Size:"
-msgstr "ИÑходный размер шрифта:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Dest Resource:"
-msgstr "РеÑÑƒÑ€Ñ Ð½Ð°Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "The quick brown fox jumps over the lazy dog."
-msgstr ""
-"Съешь ещё Ñтих мÑгких французÑких булок да выпей чаю. \n"
-"The quick brown fox jumps over the lazy dog.\n"
-"0123456789`!@#$%^&*()_+-=\\/."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Test:"
-msgstr "Проверка:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Options:"
-msgstr "Опции:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Font Import"
-msgstr "Импортирование шрифта"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"This file is already a Godot font file, please supply a BMFont type file "
-"instead."
-msgstr ""
-"Это итак файл шрифта Godot, пожалуйÑта иÑпользуйте BitMapFont вмеÑто него."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Failed opening as BMFont file."
-msgstr "Ошибка Ð¾Ñ‚ÐºÑ€Ñ‹Ñ‚Ð¸Ñ BitMapFont файла."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error initializing FreeType."
-msgstr "Ошибка инициализации FreeType."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Unknown font format."
-msgstr "ÐеизвеÑтный формат шрифта."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error loading font."
-msgstr "Ошибка загрузки шрифта."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Invalid font size."
-msgstr "ÐедопуÑтимый размер шрифта."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Invalid font custom source."
-msgstr "Ðеверный пользовательÑкий иÑточник Ð´Ð»Ñ ÑˆÑ€Ð¸Ñ„Ñ‚Ð°."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/plugins/theme_editor_plugin.cpp
-msgid "Font"
-msgstr "Шрифт"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "No meshes to import!"
-msgstr "Ðет полиÑетки Ð´Ð»Ñ Ð¸Ð¼Ð¿Ð¾Ñ€Ñ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ!"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Single Mesh Import"
-msgstr "Импорт одиночной полиÑетки"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Source Mesh(es):"
-msgstr "ИÑÑ…Ð¾Ð´Ð½Ð°Ñ Ð¿Ð¾Ð»Ð¸Ñетка(и):"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/plugins/mesh_instance_editor_plugin.cpp
-msgid "Mesh"
-msgstr "ПолиÑетка"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Surface %d"
-msgstr "ПоверхноÑтей %d"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "No samples to import!"
-msgstr "Ðет ÑÑмплов Ð´Ð»Ñ Ð¸Ð¼Ð¿Ð¾Ñ€Ñ‚Ð°!"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Import Audio Samples"
-msgstr "Импорт аудио ÑÑмплов"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Source Sample(s):"
-msgstr "ИÑходный ÑÑмпл(Ñ‹):"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Audio Sample"
-msgstr "Ðудио ÑÑмпл"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "New Clip"
-msgstr "ÐÐ¾Ð²Ð°Ñ Ð´Ð¾Ñ€Ð¾Ð¶ÐºÐ°"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Animation Options"
-msgstr "Параметры анимации"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Flags"
-msgstr "Флаги"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Bake FPS:"
-msgstr "FPS:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Optimizer"
-msgstr "Оптимизатор"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Linear Error"
-msgstr "МакÑ. Ð»Ð¸Ð½ÐµÐ¹Ð½Ð°Ñ Ð¿Ð¾Ð³Ñ€ÐµÑˆÐ½Ð¾ÑÑ‚ÑŒ"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angular Error"
-msgstr "МакÑ. ÑƒÐ³Ð»Ð¾Ð²Ð°Ñ Ð¿Ð¾Ð³Ñ€ÐµÑˆÐ½Ð¾ÑÑ‚ÑŒ"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angle"
-msgstr "МакÑ. угол"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Clips"
-msgstr "Дорожки"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Start(s)"
-msgstr "Ðач(Ñ.)"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "End(s)"
-msgstr "Кон(Ñ.)"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Loop"
-msgstr "Зациклить"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Filters"
-msgstr "Фильтры"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source path is empty."
-msgstr "Путь к иÑточнику пуÑÑ‚."
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't load post-import script."
-msgstr "Ðе могу загрузить Ñкрипт поÑÑ‚-процеÑÑа."
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Invalid/broken script for post-import."
-msgstr "Ðекорректный/поврежденный Ñценарий Ð´Ð»Ñ Ð¿Ð¾ÑÑ‚-импорта."
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Error importing scene."
-msgstr "Ошибка Ð¸Ð¼Ð¿Ð¾Ñ€Ñ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ñцены."
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import 3D Scene"
-msgstr "Импорт 3D Ñцены"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source Scene:"
-msgstr "ИÑÑ…Ð¾Ð´Ð½Ð°Ñ Ñцена:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Same as Target Scene"
-msgstr "Та же, что и у целевой Ñцены"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Shared"
-msgstr "Общий"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Target Texture Folder:"
-msgstr "Ð¦ÐµÐ»ÐµÐ²Ð°Ñ Ð¿Ð°Ð¿ÐºÐ° текÑтуры:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Post-Process Script:"
-msgstr "Скрипт поÑÑ‚-процеÑÑа:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Custom Root Node Type:"
-msgstr "ПользовательÑкий тип корневого узла:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Auto"
-msgstr "Ðвто"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Root Node Name:"
-msgstr "Ð˜Ð¼Ñ ÐºÐ¾Ñ€Ð½ÐµÐ²Ð¾Ð³Ð¾ узла:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "The Following Files are Missing:"
-msgstr "ОтÑутÑтвуют Ñледующие файлы:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Anyway"
-msgstr "Импортировать в любом Ñлучае"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp scene/gui/dialogs.cpp
-msgid "Cancel"
-msgstr "Отмена"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import & Open"
-msgstr "Импортировать и Открыть"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Edited scene has not been saved, open imported scene anyway?"
-msgstr ""
-"Ð ÐµÐ´Ð°ÐºÑ‚Ð¸Ñ€ÑƒÐµÐ¼Ð°Ñ Ñцена не была Ñохранена, открыть импортированную Ñцену в любом "
-"Ñлучае?"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Image:"
-msgstr "Импорт изображениÑ:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Can't import a file over itself:"
-msgstr "Ðевозможно импортировать файл поверх негоже:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't localize path: %s (already local)"
-msgstr "Ðевозможно локализовать путь: %s (уже локальный)"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "3D Scene Animation"
-msgstr "ÐÐ½Ð¸Ð¼Ð°Ñ†Ð¸Ñ 3D Ñцены"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Uncompressed"
-msgstr "ÐеÑжатый"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossless (PNG)"
-msgstr "Сжатие без потери качеÑтва (PNG)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossy (WebP)"
-msgstr "Сжатие Ñ Ð¿Ð¾Ñ‚ÐµÑ€Ñми (WebP)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress (VRAM)"
-msgstr "Сжатие (VRAM)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Format"
-msgstr "Формат текÑтуры"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Compression Quality (WebP):"
-msgstr "КачеÑтво ÑÐ¶Ð°Ñ‚Ð¸Ñ Ñ‚ÐµÐºÑтур (WebP):"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Options"
-msgstr "Параметры текÑтуры"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Please specify some files!"
-msgstr "ПожалуйÑта, укажите некоторые файлы!"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "At least one file needed for Atlas."
-msgstr "Ð”Ð»Ñ Ð°Ñ‚Ð»Ð°Ñа нужен Ñ…Ð¾Ñ‚Ñ Ð±Ñ‹ 1 файл."
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Error importing:"
-msgstr "Ошибка импортированиÑ:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Only one file is required for large texture."
-msgstr "Только один файл необходим Ð´Ð»Ñ Ð±Ð¾Ð»ÑŒÑˆÐ¾Ð¹ текÑтуры."
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Max Texture Size:"
-msgstr "МакÑимальный размер текÑтуры:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for Atlas (2D)"
-msgstr "Импортировать текÑтуры Ð´Ð»Ñ Ð°Ñ‚Ð»Ð°Ñа (2D)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cell Size:"
-msgstr "Размер Ñчейки:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Large Texture"
-msgstr "Ð‘Ð¾Ð»ÑŒÑˆÐ°Ñ Ñ‚ÐµÐºÑтура"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Textures (2D)"
-msgstr "Импорт больших текÑтур (2D)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture"
-msgstr "ИÑÑ…Ð¾Ð´Ð½Ð°Ñ Ñ‚ÐµÐºÑтура"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Base Atlas Texture"
-msgstr "Ð‘Ð°Ð·Ð¾Ð²Ð°Ñ Ñ‚ÐµÐºÑтура атлаÑа"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s)"
-msgstr "ИÑÑ…Ð¾Ð´Ð½Ð°Ñ Ñ‚ÐµÐºÑтура(Ñ‹)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 2D"
-msgstr "Импорт текÑтур Ð´Ð»Ñ 2D"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 3D"
-msgstr "Импорт текÑтур Ð´Ð»Ñ 3D"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures"
-msgstr "Импорт текÑтур"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "2D Texture"
-msgstr "2D текÑтура"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "3D Texture"
-msgstr "3D текÑтура"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Atlas Texture"
-msgstr "ТекÑтура атлаÑа"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid ""
-"NOTICE: Importing 2D textures is not mandatory. Just copy png/jpg files to "
-"the project."
-msgstr ""
-"Ð’ÐИМÐÐИЕ: Импортирование 2D текÑтур не обÑзательно. ПроÑто Ñкопируйте png/"
-"jpg файлы в папку проекта."
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Crop empty space."
-msgstr "Обрезать пуÑтое проÑтранÑтво."
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture"
-msgstr "ТекÑтура"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Texture"
-msgstr "Импорт большой текÑтуры"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Load Source Image"
-msgstr "Загрузка иÑходного изображениÑ"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Slicing"
-msgstr "Ðарезка"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Inserting"
-msgstr "Ð’Ñтавка"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Saving"
-msgstr "Сохранение"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save large texture:"
-msgstr "Ðевозможно Ñохранить большую текÑтуру:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Build Atlas For:"
-msgstr "ПоÑтроение атлаÑа длÑ:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Loading Image:"
-msgstr "Загрузка изображениÑ:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't load image:"
-msgstr "Ðевозможно загрузить изображение:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Converting Images"
-msgstr "Преобразование изображений"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cropping Images"
-msgstr "Обрезка изображений"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Blitting Images"
-msgstr "Блитирование Изображений"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save atlas image:"
-msgstr "Ðевозможно Ñохранить изображение атлаÑа:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save converted texture:"
-msgstr "Ðевозможно Ñохранить конвертированную текÑтуру:"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid source!"
-msgstr "Ðеверный иÑточник!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid translation source!"
-msgstr "Ðеверный иÑточник перевода!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Column"
-msgstr "Колонка"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/script_create_dialog.cpp
-msgid "Language"
-msgstr "Язык"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No items to import!"
-msgstr "Ðет Ñлементов Ð´Ð»Ñ Ð¸Ð¼Ð¿Ð¾Ñ€Ñ‚Ð°!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No target path!"
-msgstr "Ðет конечного пути!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translations"
-msgstr "Импорт переводов"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Couldn't import!"
-msgstr "Ðе удалоÑÑŒ импортировать!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translation"
-msgstr "Импортирование перевода"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Source CSV:"
-msgstr "ИÑходный CSV:"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Ignore First Row"
-msgstr "Игнорировать первую Ñтроку"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Compress"
-msgstr "Сжимать"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Add to Project (project.godot)"
-msgstr "Добавить к проекту (project.godot)"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Languages:"
-msgstr "Импортировать Ñзыки:"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Translation"
-msgstr "Перевод"
-
#: editor/multi_node_edit.cpp
msgid "MultiNode Set"
msgstr "Мульти-узловый набор"
@@ -3334,6 +2692,48 @@ msgstr "Группы"
msgid "Select a Node to edit Signals and Groups."
msgstr "Выберите узел Ð´Ð»Ñ Ñ€ÐµÐ´Ð°ÐºÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ñигналов и групп."
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create Poly"
+msgstr "Создан полигон"
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly"
+msgstr "Изменён полигон"
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Insert Point"
+msgstr "Ð’Ñтавить точку"
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly (Remove Point)"
+msgstr "Удалена точка полигона"
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Remove Poly And Point"
+msgstr "Удалить полигон и точку"
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create a new polygon from scratch."
+msgstr "Создать новый полигон Ñ Ð½ÑƒÐ»Ñ."
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid ""
+"Edit existing polygon:\n"
+"LMB: Move Point.\n"
+"Ctrl+LMB: Split Segment.\n"
+"RMB: Erase Point."
+msgstr ""
+"Редактирование полигона:\n"
+"ЛКМ: перемеÑтить точку.\n"
+"Ctrl+ЛКМ: разделить Ñегмент.\n"
+"ПКМ: удалить точку."
+
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Toggle Autoplay"
msgstr "Переключено автовоÑпроизведение"
@@ -3490,7 +2890,6 @@ msgstr "Ðазвание анимации:"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
#: editor/script_create_dialog.cpp
msgid "Error!"
@@ -3518,9 +2917,8 @@ msgid "New name:"
msgstr "Ðовое имÑ:"
#: editor/plugins/animation_tree_editor_plugin.cpp
-#, fuzzy
msgid "Edit Filters"
-msgstr "Редактировать фильтры узла"
+msgstr "Редактировать фильтры"
#: editor/plugins/animation_tree_editor_plugin.cpp
#: editor/plugins/multimesh_editor_plugin.cpp
@@ -3601,10 +2999,6 @@ msgid "Delete Input"
msgstr "Удалить вход"
#: editor/plugins/animation_tree_editor_plugin.cpp
-msgid "Rename"
-msgstr "Переименовать"
-
-#: editor/plugins/animation_tree_editor_plugin.cpp
msgid "Animation tree is valid."
msgstr "Дерево анимации дейÑтвительно."
@@ -3660,64 +3054,181 @@ msgstr "Редактировать фильтры узла"
msgid "Filters.."
msgstr "Фильтры.."
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing %d Triangles:"
-msgstr "ПарÑинг %d треугольников:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Free"
+msgstr "ОÑвободить"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Triangle #"
-msgstr "Треугольник #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Contents:"
+msgstr "Содержание:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Light Baker Setup:"
-msgstr "Параметры Ð·Ð°Ð¿ÐµÐºÐ°Ð½Ð¸Ñ Ñвета:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "View Files"
+msgstr "ПроÑмотр Файлов"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing Geometry"
-msgstr "ПарÑинг геометрии"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve hostname:"
+msgstr "Ðевозможно определить Ð¸Ð¼Ñ Ñ…Ð¾Ñта:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Fixing Lights"
-msgstr "ИÑправление Ñвета"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve."
+msgstr "Ðе удаетÑÑ Ñ€Ð°Ð·Ñ€ÐµÑˆÐ¸Ñ‚ÑŒ."
-#: editor/plugins/baked_light_baker.cpp
-msgid "Making BVH"
-msgstr "Создание BVH"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connection error, please try again."
+msgstr "Ошибка подключениÑ, попробуйте еще раз."
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Light Octree"
-msgstr "Создание октодерева Ñвета"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't connect."
+msgstr "Ðе удаетÑÑ Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡Ð¸Ñ‚ÑŒÑÑ."
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Octree Texture"
-msgstr "Создание текÑтуры октодерева"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't connect to host:"
+msgstr "Ðе удаетÑÑ Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡Ð¸Ñ‚ÑŒÑÑ Ðº хоÑту:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Transfer to Lightmaps:"
-msgstr "Передача в карты оÑвещениÑ:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response from host:"
+msgstr "Ðет ответа от хоÑта:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Allocating Texture #"
-msgstr "Выделение текÑтуры #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response."
+msgstr "Ðет ответа."
-#: editor/plugins/baked_light_baker.cpp
-msgid "Baking Triangle #"
-msgstr "Запекание треугольников #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, return code:"
+msgstr "Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð½Ðµ удалÑÑ, код:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Post-Processing Texture #"
-msgstr "ПоÑÑ‚-обработка текÑтуры #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Req. Failed."
+msgstr "Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð½Ðµ прошел."
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Bake!"
-msgstr "Запечь!"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, too many redirects"
+msgstr "Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð½Ðµ прошел, Ñлишком много перенаправлений"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Redirect Loop."
+msgstr "ЦикличеÑкое перенаправление."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed:"
+msgstr "Ðе удалоÑÑŒ:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Bad download hash, assuming file has been tampered with."
+msgstr "ÐеÑовпадение Ñ…Ñша загрузки, возможно файл был изменен."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Expected:"
+msgstr "ОжидаетÑÑ:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Got:"
+msgstr "Получил:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed sha256 hash check"
+msgstr "Ðе удалоÑÑŒ проверить sha256 Ñ…Ñш"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Asset Download Error:"
+msgstr "Ошибка Загрузки Шаблона:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Fetching:"
+msgstr "Извлечение:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Resolving.."
+msgstr "ИнициализациÑ..."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connecting.."
+msgstr "Подключение.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Requesting.."
+msgstr "Запрашиваю.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Error making request"
+msgstr "Ошибка во Ð²Ñ€ÐµÐ¼Ñ Ð·Ð°Ð¿Ñ€Ð¾Ñа"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Idle"
+msgstr "ПроÑтой"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Retry"
+msgstr "Повторить"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download Error"
+msgstr "Ошибка Загрузки"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download for this asset is already in progress!"
+msgstr "Загрузка Ñтого шаблона уже идет!"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "first"
+msgstr "первый"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "prev"
+msgstr "предыдущий"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "next"
+msgstr "далее"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "last"
+msgstr "поÑледний"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "All"
+msgstr "Ð’Ñе"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Plugins"
+msgstr "Плагины"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Sort:"
+msgstr "Сортировать:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Reverse"
+msgstr "Обратно"
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Reset the lightmap octree baking process (start over)."
-msgstr "Ð¡Ð±Ñ€Ð¾Ñ Ð·Ð°Ð¿ÐµÐºÐ°Ð½Ð¸Ñ Ñвета (начать Ñначала)."
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Category:"
+msgstr "КатегориÑ:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Site:"
+msgstr "Сайт:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Support.."
+msgstr "Поддержка.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Official"
+msgstr "Официальные"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Testing"
+msgstr "ТеÑтируемые"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Assets ZIP File"
+msgstr "ZIP файл аÑÑетов"
#: editor/plugins/camera_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
msgid "Preview"
msgstr "ПредпроÑмотр"
@@ -3760,12 +3271,16 @@ msgid "Edit CanvasItem"
msgstr "Редактировать CanvasItem"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Change Anchors"
-msgstr "Изменить привÑзку"
+msgid "Anchors only"
+msgstr "Только ÑкорÑ"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Change Anchors and Margins"
+msgstr "Изменить ÑÐºÐ¾Ñ€Ñ Ð¸ размеры"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom (%):"
-msgstr "МаÑштаб (%):"
+msgid "Change Anchors"
+msgstr "Изменить привÑзку"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Paste Pose"
@@ -3808,7 +3323,7 @@ msgid ""
"(same as Alt+RMB in select mode)."
msgstr ""
"Показывает ÑпиÑок вÑех объектов нажатой позиции,\n"
-"так же как и Alt+ПКМ в режиме выделениÑ."
+"(так же как и Alt+ПКМ в режиме выделениÑ)."
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Click to change object's rotation pivot."
@@ -3819,60 +3334,73 @@ msgid "Pan Mode"
msgstr "Режим оÑмотра"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Lock the selected object in place (can't be moved)."
-msgstr "ЗафикÑировать выбранный объект."
+msgid "Toggles snapping"
+msgstr "Переключение прилипаниÑ"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Unlock the selected object (can be moved)."
-msgstr "Разблокировать выбранный объект."
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Use Snap"
+msgstr "ИÑпользовать привÑзку"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Makes sure the object's children are not selectable."
-msgstr "Делает потомков объекта невыбираемыми."
+msgid "Snapping options"
+msgstr "Параметры прилипаниÑ"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Restores the object's children's ability to be selected."
-msgstr "ВоÑÑтанавливает возможноÑÑ‚ÑŒ выбора потомков объекта."
+msgid "Snap to grid"
+msgstr "Прилипание к Ñетке"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Edit"
-msgstr "Редактировать"
+msgid "Use Rotation Snap"
+msgstr "ИÑпользовать привÑзку вращениÑ"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Use Snap"
-msgstr "ИÑпользовать привÑзку"
+msgid "Configure Snap..."
+msgstr "ÐаÑтроить прилипание.."
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Show Grid"
-msgstr "Показать Ñетку"
+msgid "Snap Relative"
+msgstr "ОтноÑÐ¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ð¿Ñ€Ð¸Ð²Ñзка"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Rotation Snap"
-msgstr "ИÑпользовать привÑзку вращениÑ"
+msgid "Use Pixel Snap"
+msgstr "ИÑпользовать попикÑельную привÑзку"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap Relative"
-msgstr "ОтноÑÐ¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ð¿Ñ€Ð¸Ð²Ñзка"
+msgid "Smart snapping"
+msgstr "Ð˜Ð½Ñ‚ÐµÐ»Ð»ÐµÐºÑ‚ÑƒÐ°Ð»ÑŒÐ½Ð°Ñ Ð¿Ñ€Ð¸Ð²Ñзка"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Configure Snap.."
-msgstr "ÐаÑтроить привÑзку.."
+msgid "Snap to parent"
+msgstr "ПривÑзать к родителю"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Pixel Snap"
-msgstr "ИÑпользовать попикÑельную привÑзку"
+msgid "Snap to node anchor"
+msgstr "ПривÑзка к Ñкорю узла"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Skeleton.."
-msgstr "Скелет.."
+msgid "Snap to node sides"
+msgstr "ПривÑзка к Ñторонам узла"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to other nodes"
+msgstr "ПривÑзка к другим узлам"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Lock the selected object in place (can't be moved)."
+msgstr "ЗафикÑировать выбранный объект."
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Unlock the selected object (can be moved)."
+msgstr "Разблокировать выбранный объект."
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Makes sure the object's children are not selectable."
+msgstr "Делает потомков объекта невыбираемыми."
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Restores the object's children's ability to be selected."
+msgstr "ВоÑÑтанавливает возможноÑÑ‚ÑŒ выбора потомков объекта."
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Make Bones"
@@ -3900,12 +3428,17 @@ msgid "View"
msgstr "Обзор"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Reset"
-msgstr "СброÑить маÑштаб"
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Show Grid"
+msgstr "Показать Ñетку"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Show helpers"
+msgstr "Показывать помощники"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Set.."
-msgstr "УÑтановить маÑштаб.."
+msgid "Show rulers"
+msgstr "Показывать линейки"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Center Selection"
@@ -3916,8 +3449,8 @@ msgid "Frame Selection"
msgstr "Кадрировать выбранное"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Anchor"
-msgstr "ПривÑзка"
+msgid "Layout"
+msgstr "Макет"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Insert Keys"
@@ -3940,12 +3473,20 @@ msgid "Clear Pose"
msgstr "ОчиÑтить позу"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Set a Value"
-msgstr "УÑтановить значение"
+msgid "Drag pivot from mouse position"
+msgstr "Перетащить точку Ð²Ñ€Ð°Ñ‰ÐµÐ½Ð¸Ñ Ð¸Ð· Ð¿Ð¾Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¼Ñ‹ÑˆÐ¸"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Set pivot at mouse position"
+msgstr "УÑтановить точку Ð²Ñ€Ð°Ñ‰ÐµÐ½Ð¸Ñ Ð½Ð° меÑте ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ñ Ð¼Ñ‹ÑˆÐ¸"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap (Pixels):"
-msgstr "ПривÑзка (пикÑели):"
+msgid "Multiply grid step by 2"
+msgstr "Умножить шаг Ñетки на 2"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Divide grid step by 2"
+msgstr "Разделить шаг Ñетки на 2"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Add %s"
@@ -3955,23 +3496,28 @@ msgstr "Добавить %s"
msgid "Adding %s..."
msgstr "Добавление %s..."
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Create Node"
msgstr "Создать узел"
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Error instancing scene from %s"
msgstr "Ошибка Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ñцены из %s"
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "OK :("
msgstr "Ок :("
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "No parent to instance a child at."
msgstr "Ðе выбран родитель Ð´Ð»Ñ Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¿Ð¾Ñ‚Ð¾Ð¼ÐºÐ°."
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "This operation requires a single selected node."
msgstr "Эта Ð¾Ð¿ÐµÑ€Ð°Ñ†Ð¸Ñ Ñ‚Ñ€ÐµÐ±ÑƒÐµÑ‚ одного выбранного узла."
@@ -3987,45 +3533,6 @@ msgstr ""
"Drag & drop + Shift : Добавить узел к выделению\n"
"Drag & drop + Alt : Изменить тип узла"
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Create Poly"
-msgstr "Создан полигон"
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly"
-msgstr "Изменён полигон"
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly (Remove Point)"
-msgstr "Удалена точка полигона"
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Create a new polygon from scratch."
-msgstr "Создать новый полигон Ñ Ð½ÑƒÐ»Ñ."
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-msgid ""
-"Edit existing polygon:\n"
-"LMB: Move Point.\n"
-"Ctrl+LMB: Split Segment.\n"
-"RMB: Erase Point."
-msgstr ""
-
#: editor/plugins/collision_polygon_editor_plugin.cpp
msgid "Create Poly3D"
msgstr "Создан Poly3D"
@@ -4035,14 +3542,6 @@ msgid "Set Handle"
msgstr "УÑтановить обработчик"
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Creating Mesh Library"
-msgstr "Создание библиотеки полиÑеток"
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Thumbnail.."
-msgstr "Миниатюра.."
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Remove item %d?"
msgstr "Удалить Ñлемент %d?"
@@ -4065,19 +3564,38 @@ msgid "Update from Scene"
msgstr "Обновить из Ñцены"
#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat0"
+msgstr "ПлоÑкий0"
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat1"
+msgstr "ПлоÑкий1"
+
+#: editor/plugins/curve_editor_plugin.cpp
#, fuzzy
-msgid "Modify Curve Point"
-msgstr "Изменить кривую"
+msgid "Ease in"
+msgstr "Переход В"
#: editor/plugins/curve_editor_plugin.cpp
#, fuzzy
+msgid "Ease out"
+msgstr "Переход ИЗ"
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Smoothstep"
+msgstr "Сглаженный"
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Modify Curve Point"
+msgstr "Изменить точку кривой"
+
+#: editor/plugins/curve_editor_plugin.cpp
msgid "Modify Curve Tangent"
-msgstr "Изменена карта кривой"
+msgstr "Изменить каÑательную кривой"
#: editor/plugins/curve_editor_plugin.cpp
-#, fuzzy
msgid "Load Curve Preset"
-msgstr "Загрузить заготовку"
+msgstr "Загрузить заготовку кривой"
#: editor/plugins/curve_editor_plugin.cpp
msgid "Add point"
@@ -4088,31 +3606,28 @@ msgid "Remove point"
msgstr "Удалить точку"
#: editor/plugins/curve_editor_plugin.cpp
-#, fuzzy
msgid "Left linear"
-msgstr "Линейный"
+msgstr "Левый линейный"
#: editor/plugins/curve_editor_plugin.cpp
-#, fuzzy
msgid "Right linear"
-msgstr "Вид Ñправа"
+msgstr "Правый линейный"
#: editor/plugins/curve_editor_plugin.cpp
msgid "Load preset"
msgstr "Загрузить заготовку"
#: editor/plugins/curve_editor_plugin.cpp
-#, fuzzy
msgid "Remove Curve Point"
-msgstr "Удалить точку пути"
+msgstr "Удалить точку кривой"
#: editor/plugins/curve_editor_plugin.cpp
msgid "Toggle Curve Linear Tangent"
-msgstr ""
+msgstr "Переключить кривую линейный тангенÑ"
#: editor/plugins/curve_editor_plugin.cpp
msgid "Hold Shift to edit tangents individually"
-msgstr ""
+msgstr "Удерживайте Shift, чтобы изменить каÑательные индивидуально"
#: editor/plugins/gradient_editor_plugin.cpp
msgid "Add/Remove Color Ramp Point"
@@ -4140,28 +3655,26 @@ msgid ""
"No OccluderPolygon2D resource on this node.\n"
"Create and assign one?"
msgstr ""
+"Ðет OccluderPolygon2D реÑурÑа у Ñтого узла.\n"
+"Создать и назначить?"
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
msgid "Create Occluder Polygon"
msgstr "Создан затенÑющий полигон"
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Edit existing polygon:"
msgstr "Редактировать ÑущеÑтвующий полигон:"
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "LMB: Move Point."
msgstr "ЛКМ: Передвинуть точку."
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Ctrl+LMB: Split Segment."
msgstr "Ctrl+ЛКМ: Разделить Ñегмент."
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "RMB: Erase Point."
msgstr "ПКМ: Удалить точку."
@@ -4262,6 +3775,10 @@ msgid "Create Outline"
msgstr "Создать контур"
#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Mesh"
+msgstr "ПолиÑетка"
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Create Trimesh Static Body"
msgstr "Создать вогнутое Ñтатичное тело"
@@ -4389,14 +3906,76 @@ msgstr "Случайный размер:"
msgid "Populate"
msgstr "Заполнить"
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake!"
+msgstr "Запечь!"
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake the navigation mesh.\n"
+msgstr "Создать полиÑетку навигации.\n"
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Clear the navigation mesh."
+msgstr "ОчиÑтить полиÑетку навигации."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Setting up Configuration..."
+msgstr "ÐаÑтройка конфигурации..."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Calculating grid size..."
+msgstr "РаÑчет размера Ñетки..."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating heightfield..."
+msgstr "Создание карты выÑот..."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Marking walkable triangles..."
+msgstr "Маркировка проходимых треугольников..."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Constructing compact heightfield..."
+msgstr "ПоÑтроение компактной карты выÑот..."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Eroding walkable area..."
+msgstr "Размытие проходимого района..."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Partitioning..."
+msgstr "Разметка..."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating contours..."
+msgstr "Создание контуров..."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating polymesh..."
+msgstr "Создание полиÑетки..."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Converting to native navigation mesh..."
+msgstr "Преобразование в ÑобÑтвенную навигационную Ñетку..."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Navigation Mesh Generator Setup:"
+msgstr "ÐаÑтройка генератора навигационной Ñетки:"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Parsing Geometry..."
+msgstr "Ðнализ геометрии..."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Done!"
+msgstr "Сделано!"
+
#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Create Navigation Polygon"
msgstr "Создать Navigation Polygon"
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Remove Poly And Point"
-msgstr "Удалить полигон и точку"
-
#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Clear Emission Mask"
msgstr "МаÑка выброÑа очищена"
@@ -4432,9 +4011,8 @@ msgstr "МаÑка выброÑа загружена"
#: editor/plugins/particles_2d_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp
-#, fuzzy
msgid "Particles"
-msgstr "Вершины"
+msgstr "ЧаÑтицы"
#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Generated Point Count:"
@@ -4526,14 +4104,12 @@ msgid "Remove Point from Curve"
msgstr "Удалена точка Ñ ÐºÑ€Ð¸Ð²Ð¾Ð¹"
#: editor/plugins/path_2d_editor_plugin.cpp
-#, fuzzy
msgid "Remove Out-Control from Curve"
-msgstr "Передвинут выходной луч у кривой"
+msgstr "Удалить выходной контроль из кривой"
#: editor/plugins/path_2d_editor_plugin.cpp
-#, fuzzy
msgid "Remove In-Control from Curve"
-msgstr "Удалена точка Ñ ÐºÑ€Ð¸Ð²Ð¾Ð¹"
+msgstr "Удалить входной контроль из кривой"
#: editor/plugins/path_2d_editor_plugin.cpp
#: editor/plugins/path_editor_plugin.cpp
@@ -4572,13 +4148,15 @@ msgstr "Точка Кривой #"
#: editor/plugins/path_editor_plugin.cpp
msgid "Set Curve Point Position"
-msgstr "УÑтановить позицию точки кривой"
+msgstr "УÑтановить положение точки кривой"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve In Position"
msgstr "УÑтановить позицию входа кривой"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve Out Position"
msgstr "УÑтановить позицию выхода кривой"
@@ -4591,14 +4169,12 @@ msgid "Remove Path Point"
msgstr "Удалить точку пути"
#: editor/plugins/path_editor_plugin.cpp
-#, fuzzy
msgid "Remove Out-Control Point"
-msgstr "Передвинут выходной луч у кривой"
+msgstr "Удалить выходную контрольную точку"
#: editor/plugins/path_editor_plugin.cpp
-#, fuzzy
msgid "Remove In-Control Point"
-msgstr "Передвинут входной луч у кривой"
+msgstr "Удалить входную контрольную точку"
#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Create UV Map"
@@ -4641,6 +4217,14 @@ msgid "Scale Polygon"
msgstr "МаÑштабировать полигон"
#: editor/plugins/polygon_2d_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Edit"
+msgstr "Редактировать"
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Polygon->UV"
msgstr "Полигон -> UV"
@@ -4695,72 +4279,21 @@ msgstr "Загрузить реÑурÑ"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/shader_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "Ð’Ñтавить"
-#: editor/plugins/rich_text_editor_plugin.cpp
-msgid "Parse BBCode"
-msgstr "ПарÑить BB Код"
-
-#: editor/plugins/sample_editor_plugin.cpp
-msgid "Length:"
-msgstr "Длинна:"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Open Sample File(s)"
-msgstr "Открыть ÑÑмпл(Ñ‹)"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "ERROR: Couldn't load sample!"
-msgstr "ОШИБКÐ: Ðе удалоÑÑŒ загрузить ÑÑмпл!"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Add Sample"
-msgstr "Добавить ÑÑмпл"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Rename Sample"
-msgstr "Переименовать ÑÑмпл"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Delete Sample"
-msgstr "Удалить ÑÑмпл"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "16 Bits"
-msgstr "16 Бит"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "8 Bits"
-msgstr "8 Бит"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Stereo"
-msgstr "Стерео"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Mono"
-msgstr "Моно"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Format"
-msgstr "Формат"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Pitch"
-msgstr "Ð’Ñ‹Ñота"
-
#: editor/plugins/script_editor_plugin.cpp
msgid "Clear Recent Files"
-msgstr "ОчиÑтить недавние файлы"
+msgstr "ОчиÑтить Ðедавние Файлы"
#: editor/plugins/script_editor_plugin.cpp
msgid ""
"Close and save changes?\n"
"\""
msgstr ""
+"Закрыть и Ñохранить изменениÑ?\n"
+"\""
#: editor/plugins/script_editor_plugin.cpp
msgid "Error while saving theme"
@@ -4788,7 +4321,7 @@ msgstr "Сохранить тему как.."
#: editor/plugins/script_editor_plugin.cpp
msgid " Class Reference"
-msgstr ""
+msgstr " СÑылка на КлаÑÑ"
#: editor/plugins/script_editor_plugin.cpp
msgid "Next script"
@@ -4842,10 +4375,13 @@ msgstr "Закрыть документацию"
msgid "Close All"
msgstr "Закрыть вÑÑ‘"
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+msgid "Run"
+msgstr "ЗапуÑтить"
+
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Toggle Scripts Panel"
-msgstr "Добавить в избранное"
+msgstr "Переключить панель Ñкриптов"
#: editor/plugins/script_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
@@ -4871,7 +4407,8 @@ msgstr "Шаг в"
msgid "Break"
msgstr "Пауза"
-#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+#: editor/script_editor_debugger.cpp
msgid "Continue"
msgstr "Продолжить"
@@ -4880,21 +4417,8 @@ msgid "Keep Debugger Open"
msgstr "ОÑтавить отладчик открытым"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Debug with external editor"
-msgstr "Открыть Ñледующий редактор"
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Window"
-msgstr "Окно"
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Left"
-msgstr "Двигать влево"
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Right"
-msgstr "Двигать вправо"
+msgstr "Отладка Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ внешнего редактора"
#: editor/plugins/script_editor_plugin.cpp
msgid "Open Godot online documentation"
@@ -4953,7 +4477,7 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
msgid "Only resources from filesystem can be dropped."
-msgstr ""
+msgstr "Можно перетащить только реÑÑƒÑ€Ñ Ð¸Ð· файловой ÑиÑтемы."
#: editor/plugins/script_text_editor.cpp
msgid "Pick Color"
@@ -4982,8 +4506,9 @@ msgid "Cut"
msgstr "Вырезать"
#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "Копировать"
@@ -5002,9 +4527,8 @@ msgid "Move Down"
msgstr "ПеремеÑтить вниз"
#: editor/plugins/script_text_editor.cpp
-#, fuzzy
msgid "Delete Line"
-msgstr "Удалить точку"
+msgstr "Удалить Ñтроку"
#: editor/plugins/script_text_editor.cpp
msgid "Indent Left"
@@ -5247,10 +4771,6 @@ msgid "View Plane Transform."
msgstr "Вид Ð¿Ñ€ÐµÐ¾Ð±Ñ€Ð°Ð·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¿Ð»Ð¾ÑкоÑти."
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Scaling to %s%%."
-msgstr "МаÑштабирование до %s%%."
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rotating %s degrees."
msgstr "Поворот на %s градуÑов."
@@ -5267,10 +4787,6 @@ msgid "Top View."
msgstr "Вид Ñверху."
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Top"
-msgstr "Верх"
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rear View."
msgstr "Вид Ñзади."
@@ -5371,9 +4887,8 @@ msgid "Audio Listener"
msgstr "ПроÑлушиватель звука"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Doppler Enable"
-msgstr "Включить"
+msgstr "ДоплеровÑкий режим"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Freelook Left"
@@ -5404,26 +4919,26 @@ msgid "Freelook Speed Modifier"
msgstr "Обзор модификатор ÑкороÑти"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "preview"
-msgstr "ПредпроÑмотр"
+msgstr "предпроÑмотр"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "XForm Dialog"
msgstr "XForm диалоговое окно"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Select Mode (Q)\n"
-msgstr "Режим выделениÑ"
+msgstr "Режим Ð²Ñ‹Ð´ÐµÐ»ÐµÐ½Ð¸Ñ (Q)\n"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid ""
"Drag: Rotate\n"
"Alt+Drag: Move\n"
"Alt+RMB: Depth list selection"
-msgstr "Alt+ПКМ: СпиÑок выбора глубины"
+msgstr ""
+"ТÑнуть: Вращение\n"
+"Alt+ТÑнуть: Перемещение\n"
+"Ðльт+ПКМ: Выбор по ÑпиÑку"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Move Mode (W)"
@@ -5502,6 +5017,10 @@ msgid "Transform"
msgstr "Преобразование"
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Configure Snap.."
+msgstr "ÐаÑтроить привÑзку.."
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Local Coords"
msgstr "Локальные координаты"
@@ -5647,6 +5166,10 @@ msgid "Speed (FPS):"
msgstr "СкороÑÑ‚ÑŒ (FPS):"
#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Loop"
+msgstr "Зациклить"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Animation Frames"
msgstr "Кадры анимации"
@@ -5659,21 +5182,20 @@ msgid "Insert Empty (After)"
msgstr "Ð’Ñтавить пуÑтоту (ПоÑле)"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Up"
-msgstr "Вверх"
+msgid "Move (Before)"
+msgstr "ПеремеÑтить (до)"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Down"
-msgstr "Вниз"
+msgid "Move (After)"
+msgstr "ПеремеÑтить (поÑле)"
#: editor/plugins/style_box_editor_plugin.cpp
msgid "StyleBox Preview:"
msgstr "StyleBox предпроÑмотр:"
#: editor/plugins/texture_region_editor_plugin.cpp
-#, fuzzy
msgid "Set Region Rect"
-msgstr "УÑтановить прÑмоугольник региона"
+msgstr "Задать регион"
#: editor/plugins/texture_region_editor_plugin.cpp
msgid "Snap Mode:"
@@ -5733,18 +5255,20 @@ msgid "Remove Item"
msgstr "Удалить Ñлемент"
#: editor/plugins/theme_editor_plugin.cpp
-#, fuzzy
msgid "Remove All Items"
-msgstr "Удалить Ñлемент клаÑÑа"
+msgstr "Удалить вÑе Ñлементы"
#: editor/plugins/theme_editor_plugin.cpp
-#, fuzzy
msgid "Remove All"
-msgstr "Удалить"
+msgstr "Удалить вÑе"
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Edit theme.."
+msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
-msgid "Theme"
-msgstr "Тема"
+msgid "Theme editing menu."
+msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
msgid "Add Class Items"
@@ -5828,11 +5352,14 @@ msgid "Style"
msgstr "Стиль"
#: editor/plugins/theme_editor_plugin.cpp
+msgid "Font"
+msgstr "Шрифт"
+
+#: editor/plugins/theme_editor_plugin.cpp
msgid "Color"
msgstr "Цвет"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Erase Selection"
msgstr "ОчиÑтить выделенное"
@@ -5841,16 +5368,14 @@ msgid "Paint TileMap"
msgstr "РиÑовать карту тайлов"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Line Draw"
-msgstr "Линейный"
+msgstr "РиÑовать линиÑми"
#: editor/plugins/tile_map_editor_plugin.cpp
msgid "Rectangle Paint"
-msgstr ""
+msgstr "ПрÑÐ¼Ð¾ÑƒÐ³Ð¾Ð»ÑŒÐ½Ð°Ñ Ð¿Ð¾ÐºÑ€Ð°Ñка"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Bucket Fill"
msgstr "Заливка"
@@ -5879,8 +5404,8 @@ msgid "Mirror Y"
msgstr "Зеркально по Y"
#: editor/plugins/tile_map_editor_plugin.cpp
-msgid "Bucket"
-msgstr "Заливка"
+msgid "Paint Tile"
+msgstr "РиÑовать тайл"
#: editor/plugins/tile_map_editor_plugin.cpp
msgid "Pick Tile"
@@ -5943,6 +5468,10 @@ msgid "Delete preset '%s'?"
msgstr "Удалить '%s'?"
#: editor/project_export.cpp
+msgid "Export templates for this platform are missing/corrupted: "
+msgstr "Шаблоны ÑкÑпорта Ð´Ð»Ñ Ñтой платформы отÑутÑтвуют/повреждены: "
+
+#: editor/project_export.cpp
msgid "Presets"
msgstr "ПредуÑтановки"
@@ -5995,18 +5524,16 @@ msgid "Make Patch"
msgstr "Создать латку"
#: editor/project_export.cpp
-#, fuzzy
msgid "Features"
-msgstr "ТекÑтура"
+msgstr "СвойÑтва"
#: editor/project_export.cpp
msgid "Custom (comma-separated):"
-msgstr ""
+msgstr "ПользовательÑкий (через запÑтую):"
#: editor/project_export.cpp
-#, fuzzy
msgid "Feature List:"
-msgstr "СпиÑок методов:"
+msgstr "СпиÑок ÑвойÑтв:"
#: editor/project_export.cpp
msgid "Export PCK/Zip"
@@ -6017,30 +5544,56 @@ msgid "Export templates for this platform are missing:"
msgstr "Шаблоны ÑкÑпорта Ð´Ð»Ñ Ñтой платформы отÑутÑтвуют:"
#: editor/project_export.cpp
+msgid "Export templates for this platform are missing/corrupted:"
+msgstr "Шаблоны ÑкÑпорта Ð´Ð»Ñ Ñтой платформы отÑутÑтвуют/повреждены:"
+
+#: editor/project_export.cpp
msgid "Export With Debug"
msgstr "ЭкÑпорт в режиме отладки"
#: editor/project_manager.cpp
-msgid "Invalid project path, the path must exist!"
-msgstr "Ðеверный путь к проекту, путь должен ÑущеÑтвовать!"
+msgid "The path does not exist."
+msgstr "Путь не ÑущеÑтвует."
#: editor/project_manager.cpp
-msgid "Invalid project path, project.godot must not exist."
-msgstr "ÐедопуÑтимый путь, project.godot не должен приÑутÑтвовать."
+msgid "Please choose a 'project.godot' file."
+msgstr "ПожалуйÑта, выберите 'project.godot' файл."
#: editor/project_manager.cpp
-msgid "Invalid project path, project.godot must exist."
-msgstr "ÐедопуÑтимый путь, project.godot должен приÑутÑтвовать."
+msgid ""
+"Your project will be created in a non empty folder (you might want to create "
+"a new folder)."
+msgstr "Ваш проект будет Ñоздан не в пуÑтой папке (лучше Ñоздать новую папку)."
+
+#: editor/project_manager.cpp
+msgid "Please choose a folder that does not contain a 'project.godot' file."
+msgstr "ПожалуйÑта, выберите папку, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð½Ðµ Ñодержит файл 'project.godot'."
#: editor/project_manager.cpp
msgid "Imported Project"
msgstr "Импортированный проект"
#: editor/project_manager.cpp
+msgid " "
+msgstr " "
+
+#: editor/project_manager.cpp
+msgid "It would be a good idea to name your project."
+msgstr "Было бы неплохо назвать ваш проект."
+
+#: editor/project_manager.cpp
msgid "Invalid project path (changed anything?)."
msgstr "Ðеверный путь к проекту (Что-то изменили?)."
#: editor/project_manager.cpp
+msgid "Couldn't get project.godot in project path."
+msgstr "ОтÑутÑтвует project.godot в папке проекта."
+
+#: editor/project_manager.cpp
+msgid "Couldn't edit project.godot in project path."
+msgstr "Ðе удалоÑÑŒ изменить project.godot в папке проекта."
+
+#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
msgstr "Ðе удалоÑÑŒ Ñоздать project.godot в папке проекта."
@@ -6049,38 +5602,46 @@ msgid "The following files failed extraction from package:"
msgstr "Следующие файлы не удалоÑÑŒ Ð¸Ð·Ð²Ð»ÐµÑ‡ÐµÐ½Ð¸Ñ Ð¸Ð· пакета:"
#: editor/project_manager.cpp
+msgid "Rename Project"
+msgstr "Переименовать проект"
+
+#: editor/project_manager.cpp
+msgid "Couldn't get project.godot in the project path."
+msgstr "ОтÑутÑтвует project.godot в папке проекта."
+
+#: editor/project_manager.cpp
+msgid "New Game Project"
+msgstr "Ðовый игровой проект"
+
+#: editor/project_manager.cpp
msgid "Import Existing Project"
msgstr "Импортировать ÑущеÑтвующий проект"
#: editor/project_manager.cpp
-msgid "Project Path (Must Exist):"
-msgstr "Путь к проекту (должен ÑущеÑтвовать):"
+msgid "Create New Project"
+msgstr "Создать новый проект"
+
+#: editor/project_manager.cpp
+msgid "Install Project:"
+msgstr "УÑтановить проект:"
#: editor/project_manager.cpp
msgid "Project Name:"
msgstr "Ðазвание проекта:"
#: editor/project_manager.cpp
-msgid "Create New Project"
-msgstr "Создать новый проект"
+msgid "Create folder"
+msgstr "Создать папку"
#: editor/project_manager.cpp
msgid "Project Path:"
msgstr "Путь к проекту:"
#: editor/project_manager.cpp
-msgid "Install Project:"
-msgstr "УÑтановить проект:"
-
-#: editor/project_manager.cpp
msgid "Browse"
msgstr "Обзор"
#: editor/project_manager.cpp
-msgid "New Game Project"
-msgstr "Ðовый игровой проект"
-
-#: editor/project_manager.cpp
msgid "That's a BINGO!"
msgstr "Бинго!"
@@ -6089,25 +5650,30 @@ msgid "Unnamed Project"
msgstr "БезымÑнный проект"
#: editor/project_manager.cpp
+msgid "Can't open project"
+msgstr "Ðе удаетÑÑ Ð¾Ñ‚ÐºÑ€Ñ‹Ñ‚ÑŒ проект"
+
+#: editor/project_manager.cpp
msgid "Are you sure to open more than one project?"
msgstr "Вы уверены, что хотите открыть более одного проекта?"
#: editor/project_manager.cpp
-#, fuzzy
msgid ""
"Can't run project: no main scene defined.\n"
"Please edit the project and set the main scene in \"Project Settings\" under "
"the \"Application\" category."
msgstr ""
-"Ðе назначена Ð³Ð»Ð°Ð²Ð½Ð°Ñ Ñцена. Хотите выбрать?\n"
-"Позже вы можете указать её в параметре \"main_scene\" раÑположенном\n"
-"в \"ÐаÑтройки проекта - ОÑновное - application\"."
+"Ðе могу запуÑтить проект: не назначена Ð³Ð»Ð°Ð²Ð½Ð°Ñ Ñцена.\n"
+"ПожалуйÑта, отредактируйте проект и уÑтановите главную Ñцену в «ÐаÑтройки "
+"проекта» в категории «Приложение»."
#: editor/project_manager.cpp
msgid ""
"Can't run project: Assets need to be imported.\n"
"Please edit the project to trigger the initial import."
msgstr ""
+"Ðе могу запуÑтить проект: аÑÑеты должны быть импортированы.\n"
+"ПожалуйÑта, отредактируйте проект, Ñто инициирует начальный импорт."
#: editor/project_manager.cpp
msgid "Are you sure to run more than one project?"
@@ -6119,6 +5685,12 @@ msgstr "Удалить проект из ÑпиÑка? (Содержимое пÐ
#: editor/project_manager.cpp
msgid ""
+"Language changed.\n"
+"The UI will update next time the editor or project manager starts."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid ""
"You are about the scan %s folders for existing Godot projects. Do you "
"confirm?"
msgstr ""
@@ -6130,10 +5702,6 @@ msgid "Project List"
msgstr "СпиÑок проектов"
#: editor/project_manager.cpp
-msgid "Run"
-msgstr "ЗапуÑтить"
-
-#: editor/project_manager.cpp
msgid "Scan"
msgstr "Сканировать"
@@ -6155,8 +5723,12 @@ msgstr "Выход"
#: editor/project_manager.cpp
#, fuzzy
+msgid "Restart Now"
+msgstr "ПерезапуÑк (Ñек.):"
+
+#: editor/project_manager.cpp
msgid "Can't run project"
-msgstr "Ðе удаетÑÑ Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡Ð¸Ñ‚ÑŒÑÑ."
+msgstr "Ðе удаетÑÑ Ð·Ð°Ð¿ÑƒÑтить проект"
#: editor/project_settings_editor.cpp
msgid "Key "
@@ -6191,17 +5763,14 @@ msgid "Add Input Action Event"
msgstr "Добавить дейÑтвие"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Meta+"
msgstr "Meta+"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Shift+"
msgstr "Shift+"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Alt+"
msgstr "Alt+"
@@ -6262,7 +5831,7 @@ msgstr "Изменить"
msgid "Joypad Axis Index:"
msgstr "Ð˜Ð½Ð´ÐµÐºÑ Ð¾Ñи джойÑтика:"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Axis"
msgstr "ОÑÑŒ"
@@ -6282,57 +5851,61 @@ msgstr "Удалить дейÑтвие"
msgid "Add Event"
msgstr "Добавить Ñобытие"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Device"
msgstr "УÑтройÑтво"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Button"
msgstr "Кнопка"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Left Button."
msgstr "Ð›ÐµÐ²Ð°Ñ ÐºÐ½Ð¾Ð¿ÐºÐ°."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Right Button."
msgstr "ÐŸÑ€Ð°Ð²Ð°Ñ ÐºÐ½Ð¾Ð¿ÐºÐ°."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Middle Button."
msgstr "СреднÑÑ ÐºÐ½Ð¾Ð¿ÐºÐ°."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Up."
msgstr "КолёÑико вверх."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Down."
msgstr "КолёÑико вниз."
#: editor/project_settings_editor.cpp
-#, fuzzy
msgid "Add Global Property"
-msgstr "Добавить получающее ÑвойÑтво"
+msgstr "Добавить глобальное ÑвойÑтво"
#: editor/project_settings_editor.cpp
-msgid "Select an setting item first!"
-msgstr ""
+msgid "Select a setting item first!"
+msgstr "Сначала выберите Ñлемент наÑтроек!"
#: editor/project_settings_editor.cpp
-#, fuzzy
msgid "No property '"
-msgstr "Параметр:"
+msgstr "Ðет ÑвойÑтва '"
#: editor/project_settings_editor.cpp
-#, fuzzy
msgid "Setting '"
-msgstr "ÐаÑтройки"
+msgstr "ÐаÑтройки '"
#: editor/project_settings_editor.cpp
-#, fuzzy
msgid "Delete Item"
-msgstr "Удалить вход"
+msgstr "Удалить Ñлемент"
+
+#: editor/project_settings_editor.cpp
+msgid "Can't contain '/' or ':'"
+msgstr "Ðе может Ñодержать '/' или ':'"
+
+#: editor/project_settings_editor.cpp
+msgid "Already existing"
+msgstr "Уже ÑущеÑтвует"
#: editor/project_settings_editor.cpp
msgid "Error saving settings."
@@ -6344,7 +5917,7 @@ msgstr "ÐаÑтройки Ñохранены нормально."
#: editor/project_settings_editor.cpp
msgid "Override for Feature"
-msgstr ""
+msgstr "Переопределение СвойÑтва"
#: editor/project_settings_editor.cpp
msgid "Add Translation"
@@ -6375,6 +5948,15 @@ msgid "Remove Resource Remap Option"
msgstr "Удалён параметр реÑурÑа перенаправлениÑ"
#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Changed Locale Filter"
+msgstr "Изменено Ð²Ñ€ÐµÐ¼Ñ \"ÑмешиваниÑ\""
+
+#: editor/project_settings_editor.cpp
+msgid "Changed Locale Filter Mode"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "Project Settings (project.godot)"
msgstr "ÐаÑтройки проекта (project.godot)"
@@ -6388,7 +5970,7 @@ msgstr "Параметр:"
#: editor/project_settings_editor.cpp
msgid "Override For.."
-msgstr ""
+msgstr "Переопределить длÑ..."
#: editor/project_settings_editor.cpp
msgid "Input Map"
@@ -6435,6 +6017,30 @@ msgid "Locale"
msgstr "Язык"
#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Locales Filter"
+msgstr "Фильтр:"
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Show all locales"
+msgstr "Показать коÑти"
+
+#: editor/project_settings_editor.cpp
+msgid "Show only selected locales"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Filter mode:"
+msgstr "Ð¤Ð¸Ð»ÑŒÑ‚Ñ€Ð°Ñ†Ð¸Ñ ÑƒÐ·Ð»Ð¾Ð²"
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Locales:"
+msgstr "Язык"
+
+#: editor/project_settings_editor.cpp
msgid "AutoLoad"
msgstr "Ðвтозагрузка"
@@ -6475,7 +6081,6 @@ msgid "Assign"
msgstr "Ðазначить"
#: editor/property_editor.cpp
-#, fuzzy
msgid "Select Node"
msgstr "Выбрать узел"
@@ -6484,17 +6089,24 @@ msgid "New Script"
msgstr "Ðовый Ñкрипт"
#: editor/property_editor.cpp
+msgid "Make Unique"
+msgstr "Сделать уникальным"
+
+#: editor/property_editor.cpp
msgid "Show in File System"
msgstr "Показать в файловой ÑиÑтеме"
#: editor/property_editor.cpp
+msgid "Convert To %s"
+msgstr "Преобразовать в %s"
+
+#: editor/property_editor.cpp
msgid "Error loading file: Not a resource!"
msgstr "Ошибка загрузки файла: Это не реÑурÑ!"
#: editor/property_editor.cpp
-#, fuzzy
msgid "Selected node is not a Viewport!"
-msgstr "Выберите Узел(узлы) Ð´Ð»Ñ Ð¸Ð¼Ð¿Ð¾Ñ€Ñ‚Ð°"
+msgstr "Выбранный узел не Viewport!"
#: editor/property_editor.cpp
msgid "Pick a Node"
@@ -6525,6 +6137,10 @@ msgid "Select Property"
msgstr "Выбрать ÑвойÑтво"
#: editor/property_selector.cpp
+msgid "Select Virtual Method"
+msgstr "Выбрать виртуальный метод"
+
+#: editor/property_selector.cpp
msgid "Select Method"
msgstr "Выбрать метод"
@@ -6554,26 +6170,6 @@ msgstr "Сохранить глобальные преобразованиÑ"
msgid "Reparent"
msgstr "Переподчинить"
-#: editor/resources_dock.cpp
-msgid "Create New Resource"
-msgstr "Создать новый реÑурÑ"
-
-#: editor/resources_dock.cpp
-msgid "Open Resource"
-msgstr "Открыть реÑурÑ"
-
-#: editor/resources_dock.cpp
-msgid "Save Resource"
-msgstr "Сохранить реÑурÑ"
-
-#: editor/resources_dock.cpp
-msgid "Resource Tools"
-msgstr "ИнÑтрументы реÑурÑов"
-
-#: editor/resources_dock.cpp
-msgid "Make Local"
-msgstr "Сделать локальным"
-
#: editor/run_settings_dialog.cpp
msgid "Run Mode:"
msgstr "Режим запуÑка:"
@@ -6704,14 +6300,6 @@ msgid "Sub-Resources:"
msgstr "Вложенные РеÑурÑÑ‹:"
#: editor/scene_tree_dock.cpp
-msgid "Edit Groups"
-msgstr "Редактировать группы"
-
-#: editor/scene_tree_dock.cpp
-msgid "Edit Connections"
-msgstr "Редактировать ÑвÑзи"
-
-#: editor/scene_tree_dock.cpp
msgid "Clear Inheritance"
msgstr "ОчиÑтить наÑледование"
@@ -6772,9 +6360,8 @@ msgstr ""
"не ÑущеÑтвует."
#: editor/scene_tree_dock.cpp
-#, fuzzy
msgid "Filter nodes"
-msgstr "Фильтры"
+msgstr "Ð¤Ð¸Ð»ÑŒÑ‚Ñ€Ð°Ñ†Ð¸Ñ ÑƒÐ·Ð»Ð¾Ð²"
#: editor/scene_tree_dock.cpp
msgid "Attach a new or existing script for the selected node."
@@ -6869,18 +6456,16 @@ msgid "Scene Tree (Nodes):"
msgstr "Дерево Ñцены (Узлы):"
#: editor/scene_tree_editor.cpp
-#, fuzzy
msgid "Node Configuration Warning!"
-msgstr "Конфигурации узла, предупреждение:"
+msgstr "Предупреждение о конфигурации узла!"
#: editor/scene_tree_editor.cpp
msgid "Select a Node"
msgstr "Выбрать узел"
#: editor/script_create_dialog.cpp
-#, fuzzy
msgid "Error loading template '%s'"
-msgstr "Ошибка при загрузке изображениÑ:"
+msgstr "Ошибка при загрузке шаблона '%s'"
#: editor/script_create_dialog.cpp
msgid "Error - Could not create script in filesystem."
@@ -6907,6 +6492,14 @@ msgid "Invalid base path"
msgstr "ÐедопуÑтимый базовый путь"
#: editor/script_create_dialog.cpp
+msgid "Directory of the same name exists"
+msgstr "Каталог Ñ Ñ‚Ð°ÐºÐ¸Ð¼ же именем ÑущеÑтвует"
+
+#: editor/script_create_dialog.cpp
+msgid "File exists, will be reused"
+msgstr "Файл ÑущеÑтвует, будет иÑпользован повторно"
+
+#: editor/script_create_dialog.cpp
msgid "Invalid extension"
msgstr "ÐедопуÑтимое раÑширение"
@@ -6947,6 +6540,10 @@ msgid "Load existing script file"
msgstr "Загрузить ÑущеÑтвующий Ñкрипт"
#: editor/script_create_dialog.cpp
+msgid "Language"
+msgstr "Язык"
+
+#: editor/script_create_dialog.cpp
msgid "Inherits"
msgstr "ÐаÑледует"
@@ -6987,6 +6584,11 @@ msgid "Function:"
msgstr "ФункциÑ:"
#: editor/script_editor_debugger.cpp
+msgid "Pick one or more items from the list to display the graph."
+msgstr ""
+"Выбрать один или неÑколько Ñлементов из ÑпиÑка, чтобы отобразить график."
+
+#: editor/script_editor_debugger.cpp
msgid "Errors"
msgstr "Ошибки"
@@ -7067,6 +6669,10 @@ msgid "Type"
msgstr "Тип"
#: editor/script_editor_debugger.cpp
+msgid "Format"
+msgstr "Формат"
+
+#: editor/script_editor_debugger.cpp
msgid "Usage"
msgstr "ИÑпользует"
@@ -7100,7 +6706,7 @@ msgstr "Изменён Ñ€Ð°Ð´Ð¸ÑƒÑ Ñвета"
#: editor/spatial_editor_gizmos.cpp
msgid "Change AudioStreamPlayer3D Emission Angle"
-msgstr ""
+msgstr "Изменить угол AudioStreamPlayer3D"
#: editor/spatial_editor_gizmos.cpp
msgid "Change Camera FOV"
@@ -7142,12 +6748,29 @@ msgstr "Изменить AABB чаÑтиц"
msgid "Change Probe Extents"
msgstr "Изменены Probe Extents"
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Library"
+msgstr "Библиотека"
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Status"
+msgstr "СтатуÑ"
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Libraries: "
+msgstr "Библиотеки: "
+
+#: modules/gdnative/register_types.cpp
+#, fuzzy
+msgid "GDNative"
+msgstr "GDNative"
+
#: modules/gdscript/gd_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Invalid type argument to convert(), use TYPE_* constants."
msgstr "Ðеверный тип аргумента Ð´Ð»Ñ convert(), иÑпользуйте TYPE_* конÑтанты."
-#: modules/gdscript/gd_functions.cpp
+#: modules/gdscript/gd_functions.cpp modules/mono/glue/glue_header.h
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Not enough bytes for decoding bytes, or invalid format."
msgstr "Ðе хватает байтов Ð´Ð»Ñ Ð´ÐµÐºÐ¾Ð´Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð±Ð°Ð¹Ñ‚Ð¾Ð², или неверный формат."
@@ -7187,134 +6810,111 @@ msgstr "ÐедопуÑтимый ÑкземплÑÑ€ ÑÐ»Ð¾Ð²Ð°Ñ€Ñ (неверн
#: modules/gdscript/gd_functions.cpp
msgid "Object can't provide a length."
-msgstr ""
+msgstr "Объект не может предоÑтавить длину."
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "GridMap Delete Selection"
-msgstr "Удалить выделенное"
+msgstr "Удалить выделенную Ñетку"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "GridMap Duplicate Selection"
-msgstr "Дублировать выделенное"
+msgstr "Дублировать выделенную Ñетку"
#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "GridMap Paint"
-msgstr ""
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Snap View"
-msgstr "Вид Ñверху"
+msgstr "ПривÑзать вид"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Prev Level (%sDown Wheel)"
-msgstr ""
+msgstr "Пред уровень (%sКолеÑико вниз)"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Next Level (%sUp Wheel)"
-msgstr ""
+msgstr "Следующий уровень (%sКолеÑико вверх)"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Clip Disabled"
-msgstr "Отключено"
+msgstr "Отключить обрезку"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Clip Above"
-msgstr ""
+msgstr "Отрезать Ñверху"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Clip Below"
-msgstr ""
+msgstr "Отрезать Ñнизу"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Edit X Axis"
-msgstr ""
+msgstr "Редактирование оÑи X"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Edit Y Axis"
-msgstr ""
+msgstr "Редактирование оÑи Y"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Edit Z Axis"
-msgstr ""
+msgstr "Редактирование оÑи Z"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Cursor Rotate X"
-msgstr "Ctrl: Поворот"
+msgstr "КурÑор поворот по X"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Cursor Rotate Y"
-msgstr "Ctrl: Поворот"
+msgstr "КурÑор поворот по Y"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Cursor Rotate Z"
-msgstr "Ctrl: Поворот"
+msgstr "КурÑор поворот по Z"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Cursor Back Rotate X"
-msgstr ""
+msgstr "Обратное вращение курÑора по X"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Cursor Back Rotate Y"
-msgstr ""
+msgstr "Обратное вращение курÑора по Y"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Cursor Back Rotate Z"
-msgstr ""
+msgstr "Обратное вращение курÑора по Z"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Cursor Clear Rotation"
-msgstr ""
+msgstr "КурÑор очиÑтить поворот"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Create Area"
-msgstr "Создать новый"
+msgstr "Создать облаÑÑ‚ÑŒ"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Create Exterior Connector"
-msgstr "Создать новый проект"
+msgstr "Создать внешний коннектор"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Erase Area"
-msgstr "Стирать карту тайлов"
+msgstr "Стереть облаÑÑ‚ÑŒ"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Selection -> Duplicate"
-msgstr "Только выделÑÑ‚ÑŒ"
+msgstr "Выбор -> Дублировать"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Selection -> Clear"
-msgstr "Только выделÑÑ‚ÑŒ"
+msgstr "Выбор -> ОчиÑтить"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "GridMap Settings"
-msgstr "Параметры привÑзки"
+msgstr "GridMap Параметры"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Pick Distance:"
-msgstr "ЭкземплÑÑ€:"
+msgstr "РаÑÑтоÑние выбора:"
-#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
-msgid "Tiles"
-msgstr " Файлы"
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "Areas"
-msgstr ""
+#: modules/mono/editor/mono_bottom_panel.cpp
+msgid "Builds"
+msgstr "Билды"
#: modules/visual_script/visual_script.cpp
msgid ""
@@ -7353,29 +6953,24 @@ msgid "Stack overflow with stack depth: "
msgstr "Переполнение Ñтека Ñ Ð³Ð»ÑƒÐ±Ð¸Ð½Ð¾Ð¹ Ñтека: "
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Change Signal Arguments"
-msgstr "Редактирование аргументов Ñигнала:"
+msgstr "Изменить аргументы Ñигнала"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Change Argument Type"
-msgstr "Изменение типа Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð¼Ð°ÑÑива"
+msgstr "Изменить тип аргумента"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Change Argument name"
-msgstr "Изменено входное имÑ"
+msgstr "Изменить Ð¸Ð¼Ñ Ð°Ñ€Ð³ÑƒÐ¼ÐµÐ½Ñ‚Ð°"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Set Variable Default Value"
-msgstr "Изменено Ñтандартное значение"
+msgstr "УÑтановить значение по умолчанию Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð¾Ð¹"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Set Variable Type"
-msgstr "Редактировать переменную:"
+msgstr "УÑтановить тип переменной"
#: modules/visual_script/visual_script_editor.cpp
msgid "Functions:"
@@ -7426,14 +7021,12 @@ msgid "Add Node"
msgstr "Добавить узел"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Remove VisualScript Nodes"
-msgstr "Удалить недопуÑтимые ключи"
+msgstr "Удалить узлы VisualScript"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Duplicate VisualScript Nodes"
-msgstr "Граф(ы) дублированы"
+msgstr "Дублировать узлы VisualScript"
#: modules/visual_script/visual_script_editor.cpp
msgid "Hold Meta to drop a Getter. Hold Shift to drop a generic signature."
@@ -7480,24 +7073,20 @@ msgid "Add Setter Property"
msgstr "Добавить уÑтанавливающее ÑвойÑтво"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Change Base Type"
-msgstr "Изменить тип"
+msgstr "Изменить базовый тип"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Move Node(s)"
-msgstr "Удалить узел(узлы)"
+msgstr "ПеремеÑтить узел(Ñ‹)"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Remove VisualScript Node"
-msgstr "Удалён граф шейдера"
+msgstr "Удалить узел VisualScript"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Connect Nodes"
-msgstr "ПриÑоединить к узлу:"
+msgstr "ПриÑоединить узлы"
#: modules/visual_script/visual_script_editor.cpp
msgid "Condition"
@@ -7524,46 +7113,48 @@ msgid "Return"
msgstr "Возвращение"
#: modules/visual_script/visual_script_editor.cpp
+msgid "Call"
+msgstr "Вызов"
+
+#: modules/visual_script/visual_script_editor.cpp
msgid "Get"
msgstr "Получить"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
+msgid "Script already has function '%s'"
+msgstr "Скрипт уже имеет функцию '%s'"
+
+#: modules/visual_script/visual_script_editor.cpp
msgid "Change Input Value"
-msgstr "Изменено входное имÑ"
+msgstr "Изменить входное значение"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Can't copy the function node."
-msgstr "Ðевозможно работать Ñ '..'"
+msgstr "Ðе удаетÑÑ Ñкопировать узел функцию."
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Clipboard is empty!"
-msgstr "Ðет реÑурÑа в буфере обмена!"
+msgstr "Буфер обмена пуÑÑ‚!"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Paste VisualScript Nodes"
-msgstr "Ð’Ñтавить узлы"
+msgstr "Ð’Ñтавить узлы VisualScript"
#: modules/visual_script/visual_script_editor.cpp
msgid "Remove Function"
msgstr "Удалить функцию"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Edit Variable"
-msgstr "Редактировать переменную:"
+msgstr "Редактировать переменную"
#: modules/visual_script/visual_script_editor.cpp
msgid "Remove Variable"
msgstr "Удалить переменную"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Edit Signal"
-msgstr "Редактирование Ñигнала:"
+msgstr "Редактировать Ñигнал"
#: modules/visual_script/visual_script_editor.cpp
msgid "Remove Signal"
@@ -7805,6 +7396,9 @@ msgid ""
"by the physics engine when running.\n"
"Change the size in children collision shapes instead."
msgstr ""
+"Ð˜Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ñ€Ð°Ð·Ð¼ÐµÑ€Ð° RigidBody2D (в режиме character или rigid) будут "
+"переопределены движком при запуÑке.\n"
+"Измените размер дочерней формы коллизии."
#: scene/2d/remote_transform_2d.cpp
msgid "Path property must point to a valid Node2D node to work."
@@ -7838,31 +7432,35 @@ msgstr ""
#: scene/3d/arvr_nodes.cpp
msgid "ARVRCamera must have an ARVROrigin node as its parent"
-msgstr ""
+msgstr "ARVRCamera должна иметь узел ARVROrigin в качеÑтве предка"
#: scene/3d/arvr_nodes.cpp
msgid "ARVRController must have an ARVROrigin node as its parent"
-msgstr ""
+msgstr "ARVRController должен иметь узел ARVROrigin в качеÑтве предка"
#: scene/3d/arvr_nodes.cpp
msgid ""
"The controller id must not be 0 or this controller will not be bound to an "
"actual controller"
msgstr ""
+"Идентификатор контроллера не должен быть равен 0 или Ñтот контроллер не "
+"будет привÑзан к фактичеÑкому контроллеру"
#: scene/3d/arvr_nodes.cpp
msgid "ARVRAnchor must have an ARVROrigin node as its parent"
-msgstr ""
+msgstr "ARVRAnchor должен иметь узел ARVROrigin в качеÑтве предка"
#: scene/3d/arvr_nodes.cpp
msgid ""
"The anchor id must not be 0 or this anchor will not be bound to an actual "
"anchor"
msgstr ""
+"Идентификатор ÑÐºÐ¾Ñ€Ñ Ð½Ðµ должен быть равен 0 или Ñтот Ñкорь не будет привÑзан "
+"к фактичеÑкому Ñкорю"
#: scene/3d/arvr_nodes.cpp
msgid "ARVROrigin requires an ARVRCamera child node"
-msgstr ""
+msgstr "ARVROrigin требует дочерний узел ARVRCamera"
#: scene/3d/collision_polygon.cpp
msgid ""
@@ -7871,7 +7469,7 @@ msgid ""
"StaticBody, RigidBody, KinematicBody, etc. to give them a shape."
msgstr ""
"CollisionPolygon Ñлужит только Ð´Ð»Ñ Ð¾Ð±ÐµÑÐ¿ÐµÑ‡ÐµÐ½Ð¸Ñ Ñтолкновений фигурам типа "
-"CollisionObject. ПожалуйÑта иÑпользовать его только в качеÑтве дочернего Ð´Ð»Ñ "
+"CollisionObject. ПожалуйÑта, иÑпользуйте его только в качеÑтве дочернего Ð´Ð»Ñ "
"Area, StaticBody, RigidBody, KinematicBody и др. чтобы придать им форму."
#: scene/3d/collision_polygon.cpp
@@ -7920,6 +7518,9 @@ msgid ""
"the physics engine when running.\n"
"Change the size in children collision shapes instead."
msgstr ""
+"Ð˜Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ñ€Ð°Ð·Ð¼ÐµÑ€Ð° RigidBody (в режиме character или rigid) будут "
+"переопределены движком при запуÑке.\n"
+"Измените размер дочерней формы коллизии."
#: scene/3d/remote_transform.cpp
msgid "Path property must point to a valid Spatial node to work."
@@ -7940,16 +7541,28 @@ msgstr ""
"Чтобы AnimatedSprite3D отображал кадры, пожалуйÑта уÑтановите или Ñоздайте "
"реÑÑƒÑ€Ñ SpriteFrames в параметре 'Frames'."
-#: scene/gui/color_picker.cpp
+#: scene/3d/vehicle_body.cpp
#, fuzzy
+msgid ""
+"VehicleWheel serves to provide a wheel system to a VehicleBody. Please use "
+"it as a child of a VehicleBody."
+msgstr ""
+"VehicleWheel Ñлужит колеÑом Ð´Ð»Ñ VehicleBody. ПожалуйÑта, иÑпользуйте его как "
+"ребенка VehicleBody."
+
+#: scene/gui/color_picker.cpp
msgid "Raw Mode"
-msgstr "Режим оÑмотра"
+msgstr "RAW режим"
#: scene/gui/color_picker.cpp
msgid "Add current color as a preset"
msgstr "Добавить текущий цвет как преÑет"
#: scene/gui/dialogs.cpp
+msgid "Cancel"
+msgstr "Отмена"
+
+#: scene/gui/dialogs.cpp
msgid "Alert!"
msgstr "Внимание!"
@@ -7957,10 +7570,6 @@ msgstr "Внимание!"
msgid "Please Confirm..."
msgstr "Подтверждение..."
-#: scene/gui/input_action.cpp
-msgid "Ctrl+"
-msgstr "Ctrl+"
-
#: scene/gui/popup.cpp
msgid ""
"Popups will hide by default unless you call popup() or any of the popup*() "
@@ -8003,6 +7612,642 @@ msgstr ""
"Ñделайте его целью рендеринга и передайте его внутренние текÑтуры какому-то "
"другому узлу Ð´Ð»Ñ Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ."
+#: scene/resources/dynamic_font.cpp
+msgid "Error initializing FreeType."
+msgstr "Ошибка инициализации FreeType."
+
+#: scene/resources/dynamic_font.cpp
+msgid "Unknown font format."
+msgstr "ÐеизвеÑтный формат шрифта."
+
+#: scene/resources/dynamic_font.cpp
+msgid "Error loading font."
+msgstr "Ошибка загрузки шрифта."
+
+#: scene/resources/dynamic_font.cpp
+msgid "Invalid font size."
+msgstr "ÐедопуÑтимый размер шрифта."
+
+#~ msgid "Filter:"
+#~ msgstr "Фильтр:"
+
+#~ msgid "' parsing of config failed."
+#~ msgstr "' анализ конфигурации не удалÑÑ."
+
+#~ msgid "Theme"
+#~ msgstr "Тема"
+
+#~ msgid "Method List For '%s':"
+#~ msgstr "СпиÑок методов Ð´Ð»Ñ '%s':"
+
+#~ msgid "Arguments:"
+#~ msgstr "Ðргументы:"
+
+#~ msgid "Return:"
+#~ msgstr "Возвращение:"
+
+#~ msgid "Added:"
+#~ msgstr "Добавлено:"
+
+#~ msgid "Removed:"
+#~ msgstr "Удалено:"
+
+#~ msgid "Error saving atlas:"
+#~ msgstr "Ошибка ÑÐ¾Ñ…Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ Ð°Ñ‚Ð»Ð°Ñа:"
+
+#~ msgid "Could not save atlas subtexture:"
+#~ msgstr "Ðевозможно Ñохранить текÑтуру атлаÑа:"
+
+#~ msgid "Exporting for %s"
+#~ msgstr "ЭкÑпортирование Ð´Ð»Ñ %s"
+
+#~ msgid "Setting Up.."
+#~ msgstr "ÐаÑтройка.."
+
+#~ msgid "Error loading scene."
+#~ msgstr "Ошибка загрузки Ñцены."
+
+#~ msgid "Re-Import"
+#~ msgstr "Переимпортировать"
+
+#~ msgid "Please wait for scan to complete."
+#~ msgstr "ПожалуйÑта дождитеÑÑŒ Ð¾ÐºÐ¾Ð½Ñ‡Ð°Ð½Ð¸Ñ ÑканированиÑ."
+
+#~ msgid "Current scene must be saved to re-import."
+#~ msgstr "Ð¢ÐµÐºÑƒÑ‰Ð°Ñ Ñцена должна быть Ñохранена Ð´Ð»Ñ Ð¿Ð¾Ð²Ñ‚Ð¾Ñ€Ð½Ð¾Ð³Ð¾ импорта."
+
+#~ msgid "Save & Re-Import"
+#~ msgstr "Сохранить и переимпортировать"
+
+#~ msgid "Re-Importing"
+#~ msgstr "Переимпортировать"
+
+#~ msgid "Re-Import Changed Resources"
+#~ msgstr "Переимпортировать изменённые реÑурÑÑ‹"
+
+#~ msgid "Loading Export Templates"
+#~ msgstr "Загрузка шаблонов ÑкÑпорта"
+
+#~ msgid ""
+#~ "\n"
+#~ "Status: Needs Re-Import"
+#~ msgstr ""
+#~ "\n"
+#~ "СтатуÑ: требуетÑÑ Ñ€Ðµ-импорт"
+
+#~ msgid "Same source and destination files, doing nothing."
+#~ msgstr "Файл Ð½Ð°Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð¸ иÑходный файлы Ñовпадают, нечего делать."
+
+#~ msgid "Target file exists, can't overwrite. Delete first."
+#~ msgstr "Конечный файл ÑущеÑтвует, Ð½ÐµÐ»ÑŒÐ·Ñ Ð¿ÐµÑ€ÐµÐ·Ð°Ð¿Ð¸Ñать. Сначала удалите."
+
+#~ msgid "Same source and destination paths, doing nothing."
+#~ msgstr "Путь Ð½Ð°Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð¸ иÑходный пути Ñовпадают, нечего делать."
+
+#~ msgid "Can't move directories to within themselves."
+#~ msgstr "Ðевозможно перемеÑтить каталоги внутрь ÑебÑ."
+
+#~ msgid "Can't rename deps for:\n"
+#~ msgstr "Ðе могу переименовать завиÑимоÑти длÑ:\n"
+
+#~ msgid "Error moving file:\n"
+#~ msgstr "Ошибка Ð¿ÐµÑ€ÐµÐ¼ÐµÑ‰ÐµÐ½Ð¸Ñ Ñ„Ð°Ð¹Ð»Ð°:\n"
+
+#~ msgid "Pick New Name and Location For:"
+#~ msgstr "Выберете новое Ð¸Ð¼Ñ Ð¸ раÑположение длÑ:"
+
+#~ msgid "No files selected!"
+#~ msgstr "Файлы не выбраны!"
+
+#~ msgid "Info"
+#~ msgstr "ИнформациÑ"
+
+#~ msgid "Re-Import.."
+#~ msgstr "Переимпортировать.."
+
+#~ msgid "No bit masks to import!"
+#~ msgstr "Ðет битовой маÑки Ð´Ð»Ñ Ð¸Ð¼Ð¿Ð¾Ñ€Ñ‚Ð°!"
+
+#~ msgid "Target path is empty."
+#~ msgstr "Конечный путь пуÑÑ‚."
+
+#~ msgid "Target path must be a complete resource path."
+#~ msgstr "Конечный путь должен быть полным путём к реÑурÑу."
+
+#~ msgid "Target path must exist."
+#~ msgstr "Конечный путь должен ÑущеÑтвовать."
+
+#~ msgid "Save path is empty!"
+#~ msgstr "Путь ÑÐ¾Ñ…Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ Ð¿ÑƒÑÑ‚!"
+
+#~ msgid "Import BitMasks"
+#~ msgstr "Импорт битовой маÑки"
+
+#~ msgid "Source Texture(s):"
+#~ msgstr "ИÑходные текÑтура(Ñ‹):"
+
+#~ msgid "Target Path:"
+#~ msgstr "Целевой путь:"
+
+#~ msgid "Accept"
+#~ msgstr "ПринÑÑ‚ÑŒ"
+
+#~ msgid "Bit Mask"
+#~ msgstr "Ð‘Ð¸Ñ‚Ð¾Ð²Ð°Ñ Ð¼Ð°Ñка"
+
+#~ msgid "No source font file!"
+#~ msgstr "Ðет иÑходного файл шрифта!"
+
+#~ msgid "No target font resource!"
+#~ msgstr "Ðет целевого реÑурÑа шрифта!"
+
+#~ msgid ""
+#~ "Invalid file extension.\n"
+#~ "Please use .font."
+#~ msgstr ""
+#~ "ÐедопуÑтимое раÑширение файла.\n"
+#~ "ПожалуйÑта, иÑпользуйте .font."
+
+#~ msgid "Couldn't save font."
+#~ msgstr "Ðевозможно Ñохранить шрифт."
+
+#~ msgid "Source Font:"
+#~ msgstr "ИÑходный шрифт:"
+
+#~ msgid "Source Font Size:"
+#~ msgstr "ИÑходный размер шрифта:"
+
+#~ msgid "Dest Resource:"
+#~ msgstr "РеÑÑƒÑ€Ñ Ð½Ð°Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ:"
+
+#~ msgid "The quick brown fox jumps over the lazy dog."
+#~ msgstr ""
+#~ "Съешь ещё Ñтих мÑгких французÑких булок да выпей чаю. \n"
+#~ "The quick brown fox jumps over the lazy dog.\n"
+#~ "0123456789`!@#$%^&*()_+-=\\/."
+
+#~ msgid "Test:"
+#~ msgstr "Проверка:"
+
+#~ msgid "Options:"
+#~ msgstr "Опции:"
+
+#~ msgid "Font Import"
+#~ msgstr "Импортирование шрифта"
+
+#~ msgid ""
+#~ "This file is already a Godot font file, please supply a BMFont type file "
+#~ "instead."
+#~ msgstr ""
+#~ "Это итак файл шрифта Godot, пожалуйÑта иÑпользуйте BitMapFont вмеÑто него."
+
+#~ msgid "Failed opening as BMFont file."
+#~ msgstr "Ошибка Ð¾Ñ‚ÐºÑ€Ñ‹Ñ‚Ð¸Ñ BitMapFont файла."
+
+#~ msgid "Invalid font custom source."
+#~ msgstr "Ðеверный пользовательÑкий иÑточник Ð´Ð»Ñ ÑˆÑ€Ð¸Ñ„Ñ‚Ð°."
+
+#~ msgid "No meshes to import!"
+#~ msgstr "Ðет полиÑетки Ð´Ð»Ñ Ð¸Ð¼Ð¿Ð¾Ñ€Ñ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ!"
+
+#~ msgid "Single Mesh Import"
+#~ msgstr "Импорт одиночной полиÑетки"
+
+#~ msgid "Source Mesh(es):"
+#~ msgstr "ИÑÑ…Ð¾Ð´Ð½Ð°Ñ Ð¿Ð¾Ð»Ð¸Ñетка(и):"
+
+#~ msgid "Surface %d"
+#~ msgstr "ПоверхноÑтей %d"
+
+#~ msgid "No samples to import!"
+#~ msgstr "Ðет ÑÑмплов Ð´Ð»Ñ Ð¸Ð¼Ð¿Ð¾Ñ€Ñ‚Ð°!"
+
+#~ msgid "Import Audio Samples"
+#~ msgstr "Импорт аудио ÑÑмплов"
+
+#~ msgid "Source Sample(s):"
+#~ msgstr "ИÑходный ÑÑмпл(Ñ‹):"
+
+#~ msgid "Audio Sample"
+#~ msgstr "Ðудио ÑÑмпл"
+
+#~ msgid "New Clip"
+#~ msgstr "ÐÐ¾Ð²Ð°Ñ Ð´Ð¾Ñ€Ð¾Ð¶ÐºÐ°"
+
+#~ msgid "Flags"
+#~ msgstr "Флаги"
+
+#~ msgid "Bake FPS:"
+#~ msgstr "FPS:"
+
+#~ msgid "Optimizer"
+#~ msgstr "Оптимизатор"
+
+#~ msgid "Max Linear Error"
+#~ msgstr "МакÑ. Ð»Ð¸Ð½ÐµÐ¹Ð½Ð°Ñ Ð¿Ð¾Ð³Ñ€ÐµÑˆÐ½Ð¾ÑÑ‚ÑŒ"
+
+#~ msgid "Max Angular Error"
+#~ msgstr "МакÑ. ÑƒÐ³Ð»Ð¾Ð²Ð°Ñ Ð¿Ð¾Ð³Ñ€ÐµÑˆÐ½Ð¾ÑÑ‚ÑŒ"
+
+#~ msgid "Max Angle"
+#~ msgstr "МакÑ. угол"
+
+#~ msgid "Clips"
+#~ msgstr "Дорожки"
+
+#~ msgid "Start(s)"
+#~ msgstr "Ðач(Ñ.)"
+
+#~ msgid "End(s)"
+#~ msgstr "Кон(Ñ.)"
+
+#~ msgid "Filters"
+#~ msgstr "Фильтры"
+
+#~ msgid "Source path is empty."
+#~ msgstr "Путь к иÑточнику пуÑÑ‚."
+
+#~ msgid "Couldn't load post-import script."
+#~ msgstr "Ðе могу загрузить Ñкрипт поÑÑ‚-процеÑÑа."
+
+#~ msgid "Invalid/broken script for post-import."
+#~ msgstr "Ðекорректный/поврежденный Ñценарий Ð´Ð»Ñ Ð¿Ð¾ÑÑ‚-импорта."
+
+#~ msgid "Error importing scene."
+#~ msgstr "Ошибка Ð¸Ð¼Ð¿Ð¾Ñ€Ñ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ñцены."
+
+#~ msgid "Import 3D Scene"
+#~ msgstr "Импорт 3D Ñцены"
+
+#~ msgid "Source Scene:"
+#~ msgstr "ИÑÑ…Ð¾Ð´Ð½Ð°Ñ Ñцена:"
+
+#~ msgid "Same as Target Scene"
+#~ msgstr "Та же, что и у целевой Ñцены"
+
+#~ msgid "Shared"
+#~ msgstr "Общий"
+
+#~ msgid "Target Texture Folder:"
+#~ msgstr "Ð¦ÐµÐ»ÐµÐ²Ð°Ñ Ð¿Ð°Ð¿ÐºÐ° текÑтуры:"
+
+#~ msgid "Post-Process Script:"
+#~ msgstr "Скрипт поÑÑ‚-процеÑÑа:"
+
+#~ msgid "Custom Root Node Type:"
+#~ msgstr "ПользовательÑкий тип корневого узла:"
+
+#~ msgid "Auto"
+#~ msgstr "Ðвто"
+
+#~ msgid "Root Node Name:"
+#~ msgstr "Ð˜Ð¼Ñ ÐºÐ¾Ñ€Ð½ÐµÐ²Ð¾Ð³Ð¾ узла:"
+
+#~ msgid "The Following Files are Missing:"
+#~ msgstr "ОтÑутÑтвуют Ñледующие файлы:"
+
+#~ msgid "Import Anyway"
+#~ msgstr "Импортировать в любом Ñлучае"
+
+#~ msgid "Import & Open"
+#~ msgstr "Импортировать и Открыть"
+
+#~ msgid "Edited scene has not been saved, open imported scene anyway?"
+#~ msgstr ""
+#~ "Ð ÐµÐ´Ð°ÐºÑ‚Ð¸Ñ€ÑƒÐµÐ¼Ð°Ñ Ñцена не была Ñохранена, открыть импортированную Ñцену в "
+#~ "любом Ñлучае?"
+
+#~ msgid "Import Image:"
+#~ msgstr "Импорт изображениÑ:"
+
+#~ msgid "Couldn't localize path: %s (already local)"
+#~ msgstr "Ðевозможно локализовать путь: %s (уже локальный)"
+
+#~ msgid "3D Scene Animation"
+#~ msgstr "ÐÐ½Ð¸Ð¼Ð°Ñ†Ð¸Ñ 3D Ñцены"
+
+#~ msgid "Uncompressed"
+#~ msgstr "ÐеÑжатый"
+
+#~ msgid "Compress Lossless (PNG)"
+#~ msgstr "Сжатие без потери качеÑтва (PNG)"
+
+#~ msgid "Compress Lossy (WebP)"
+#~ msgstr "Сжатие Ñ Ð¿Ð¾Ñ‚ÐµÑ€Ñми (WebP)"
+
+#~ msgid "Compress (VRAM)"
+#~ msgstr "Сжатие (VRAM)"
+
+#~ msgid "Texture Format"
+#~ msgstr "Формат текÑтуры"
+
+#~ msgid "Texture Compression Quality (WebP):"
+#~ msgstr "КачеÑтво ÑÐ¶Ð°Ñ‚Ð¸Ñ Ñ‚ÐµÐºÑтур (WebP):"
+
+#~ msgid "Texture Options"
+#~ msgstr "Параметры текÑтуры"
+
+#~ msgid "Please specify some files!"
+#~ msgstr "ПожалуйÑта, укажите некоторые файлы!"
+
+#~ msgid "At least one file needed for Atlas."
+#~ msgstr "Ð”Ð»Ñ Ð°Ñ‚Ð»Ð°Ñа нужен Ñ…Ð¾Ñ‚Ñ Ð±Ñ‹ 1 файл."
+
+#~ msgid "Error importing:"
+#~ msgstr "Ошибка импортированиÑ:"
+
+#~ msgid "Only one file is required for large texture."
+#~ msgstr "Только один файл необходим Ð´Ð»Ñ Ð±Ð¾Ð»ÑŒÑˆÐ¾Ð¹ текÑтуры."
+
+#~ msgid "Max Texture Size:"
+#~ msgstr "МакÑимальный размер текÑтуры:"
+
+#~ msgid "Import Textures for Atlas (2D)"
+#~ msgstr "Импортировать текÑтуры Ð´Ð»Ñ Ð°Ñ‚Ð»Ð°Ñа (2D)"
+
+#~ msgid "Cell Size:"
+#~ msgstr "Размер Ñчейки:"
+
+#~ msgid "Large Texture"
+#~ msgstr "Ð‘Ð¾Ð»ÑŒÑˆÐ°Ñ Ñ‚ÐµÐºÑтура"
+
+#~ msgid "Import Large Textures (2D)"
+#~ msgstr "Импорт больших текÑтур (2D)"
+
+#~ msgid "Source Texture"
+#~ msgstr "ИÑÑ…Ð¾Ð´Ð½Ð°Ñ Ñ‚ÐµÐºÑтура"
+
+#~ msgid "Base Atlas Texture"
+#~ msgstr "Ð‘Ð°Ð·Ð¾Ð²Ð°Ñ Ñ‚ÐµÐºÑтура атлаÑа"
+
+#~ msgid "Source Texture(s)"
+#~ msgstr "ИÑÑ…Ð¾Ð´Ð½Ð°Ñ Ñ‚ÐµÐºÑтура(Ñ‹)"
+
+#~ msgid "Import Textures for 2D"
+#~ msgstr "Импорт текÑтур Ð´Ð»Ñ 2D"
+
+#~ msgid "Import Textures for 3D"
+#~ msgstr "Импорт текÑтур Ð´Ð»Ñ 3D"
+
+#~ msgid "Import Textures"
+#~ msgstr "Импорт текÑтур"
+
+#~ msgid "2D Texture"
+#~ msgstr "2D текÑтура"
+
+#~ msgid "3D Texture"
+#~ msgstr "3D текÑтура"
+
+#~ msgid "Atlas Texture"
+#~ msgstr "ТекÑтура атлаÑа"
+
+#~ msgid ""
+#~ "NOTICE: Importing 2D textures is not mandatory. Just copy png/jpg files "
+#~ "to the project."
+#~ msgstr ""
+#~ "Ð’ÐИМÐÐИЕ: Импортирование 2D текÑтур не обÑзательно. ПроÑто Ñкопируйте png/"
+#~ "jpg файлы в папку проекта."
+
+#~ msgid "Crop empty space."
+#~ msgstr "Обрезать пуÑтое проÑтранÑтво."
+
+#~ msgid "Texture"
+#~ msgstr "ТекÑтура"
+
+#~ msgid "Import Large Texture"
+#~ msgstr "Импорт большой текÑтуры"
+
+#~ msgid "Load Source Image"
+#~ msgstr "Загрузка иÑходного изображениÑ"
+
+#~ msgid "Slicing"
+#~ msgstr "Ðарезка"
+
+#~ msgid "Saving"
+#~ msgstr "Сохранение"
+
+#~ msgid "Couldn't save large texture:"
+#~ msgstr "Ðевозможно Ñохранить большую текÑтуру:"
+
+#~ msgid "Build Atlas For:"
+#~ msgstr "ПоÑтроение атлаÑа длÑ:"
+
+#~ msgid "Loading Image:"
+#~ msgstr "Загрузка изображениÑ:"
+
+#~ msgid "Couldn't load image:"
+#~ msgstr "Ðевозможно загрузить изображение:"
+
+#~ msgid "Converting Images"
+#~ msgstr "Преобразование изображений"
+
+#~ msgid "Cropping Images"
+#~ msgstr "Обрезка изображений"
+
+#~ msgid "Blitting Images"
+#~ msgstr "Блитирование Изображений"
+
+#~ msgid "Couldn't save atlas image:"
+#~ msgstr "Ðевозможно Ñохранить изображение атлаÑа:"
+
+#~ msgid "Couldn't save converted texture:"
+#~ msgstr "Ðевозможно Ñохранить конвертированную текÑтуру:"
+
+#~ msgid "Invalid source!"
+#~ msgstr "Ðеверный иÑточник!"
+
+#~ msgid "Invalid translation source!"
+#~ msgstr "Ðеверный иÑточник перевода!"
+
+#~ msgid "Column"
+#~ msgstr "Колонка"
+
+#~ msgid "No items to import!"
+#~ msgstr "Ðет Ñлементов Ð´Ð»Ñ Ð¸Ð¼Ð¿Ð¾Ñ€Ñ‚Ð°!"
+
+#~ msgid "No target path!"
+#~ msgstr "Ðет конечного пути!"
+
+#~ msgid "Import Translations"
+#~ msgstr "Импорт переводов"
+
+#~ msgid "Couldn't import!"
+#~ msgstr "Ðе удалоÑÑŒ импортировать!"
+
+#~ msgid "Import Translation"
+#~ msgstr "Импортирование перевода"
+
+#~ msgid "Source CSV:"
+#~ msgstr "ИÑходный CSV:"
+
+#~ msgid "Ignore First Row"
+#~ msgstr "Игнорировать первую Ñтроку"
+
+#~ msgid "Compress"
+#~ msgstr "Сжимать"
+
+#~ msgid "Add to Project (project.godot)"
+#~ msgstr "Добавить к проекту (project.godot)"
+
+#~ msgid "Import Languages:"
+#~ msgstr "Импортировать Ñзыки:"
+
+#~ msgid "Translation"
+#~ msgstr "Перевод"
+
+#~ msgid "Parsing %d Triangles:"
+#~ msgstr "ПарÑинг %d треугольников:"
+
+#~ msgid "Triangle #"
+#~ msgstr "Треугольник #"
+
+#~ msgid "Light Baker Setup:"
+#~ msgstr "Параметры Ð·Ð°Ð¿ÐµÐºÐ°Ð½Ð¸Ñ Ñвета:"
+
+#~ msgid "Fixing Lights"
+#~ msgstr "ИÑправление Ñвета"
+
+#~ msgid "Making BVH"
+#~ msgstr "Создание BVH"
+
+#~ msgid "Transfer to Lightmaps:"
+#~ msgstr "Передача в карты оÑвещениÑ:"
+
+#~ msgid "Allocating Texture #"
+#~ msgstr "Выделение текÑтуры #"
+
+#~ msgid "Baking Triangle #"
+#~ msgstr "Запекание треугольников #"
+
+#~ msgid "Post-Processing Texture #"
+#~ msgstr "ПоÑÑ‚-обработка текÑтуры #"
+
+#~ msgid "Reset the lightmap octree baking process (start over)."
+#~ msgstr "Ð¡Ð±Ñ€Ð¾Ñ Ð·Ð°Ð¿ÐµÐºÐ°Ð½Ð¸Ñ Ñвета (начать Ñначала)."
+
+#~ msgid "Zoom (%):"
+#~ msgstr "МаÑштаб (%):"
+
+#~ msgid "Skeleton.."
+#~ msgstr "Скелет.."
+
+#~ msgid "Zoom Reset"
+#~ msgstr "СброÑить маÑштаб"
+
+#~ msgid "Zoom Set.."
+#~ msgstr "УÑтановить маÑштаб.."
+
+#~ msgid "Set a Value"
+#~ msgstr "УÑтановить значение"
+
+#~ msgid "Snap (Pixels):"
+#~ msgstr "ПривÑзка (пикÑели):"
+
+#~ msgid "Parse BBCode"
+#~ msgstr "ПарÑить BB Код"
+
+#~ msgid "Length:"
+#~ msgstr "Длинна:"
+
+#~ msgid "Open Sample File(s)"
+#~ msgstr "Открыть ÑÑмпл(Ñ‹)"
+
+#~ msgid "ERROR: Couldn't load sample!"
+#~ msgstr "ОШИБКÐ: Ðе удалоÑÑŒ загрузить ÑÑмпл!"
+
+#~ msgid "Add Sample"
+#~ msgstr "Добавить ÑÑмпл"
+
+#~ msgid "Rename Sample"
+#~ msgstr "Переименовать ÑÑмпл"
+
+#~ msgid "Delete Sample"
+#~ msgstr "Удалить ÑÑмпл"
+
+#~ msgid "16 Bits"
+#~ msgstr "16 Бит"
+
+#~ msgid "8 Bits"
+#~ msgstr "8 Бит"
+
+#~ msgid "Stereo"
+#~ msgstr "Стерео"
+
+#~ msgid "Mono"
+#~ msgstr "Моно"
+
+#~ msgid "Pitch"
+#~ msgstr "Ð’Ñ‹Ñота"
+
+#~ msgid "Window"
+#~ msgstr "Окно"
+
+#~ msgid "Move Right"
+#~ msgstr "Двигать вправо"
+
+#~ msgid "Scaling to %s%%."
+#~ msgstr "МаÑштабирование до %s%%."
+
+#~ msgid "Up"
+#~ msgstr "Вверх"
+
+#~ msgid "Down"
+#~ msgstr "Вниз"
+
+#~ msgid "Bucket"
+#~ msgstr "Заливка"
+
+#~ msgid "Invalid project path, the path must exist!"
+#~ msgstr "Ðеверный путь к проекту, путь должен ÑущеÑтвовать!"
+
+#~ msgid "Invalid project path, project.godot must not exist."
+#~ msgstr "ÐедопуÑтимый путь, project.godot не должен приÑутÑтвовать."
+
+#~ msgid "Invalid project path, project.godot must exist."
+#~ msgstr "ÐедопуÑтимый путь, project.godot должен приÑутÑтвовать."
+
+#~ msgid "Project Path (Must Exist):"
+#~ msgstr "Путь к проекту (должен ÑущеÑтвовать):"
+
+#~ msgid "Create New Resource"
+#~ msgstr "Создать новый реÑурÑ"
+
+#~ msgid "Open Resource"
+#~ msgstr "Открыть реÑурÑ"
+
+#~ msgid "Save Resource"
+#~ msgstr "Сохранить реÑурÑ"
+
+#~ msgid "Resource Tools"
+#~ msgstr "ИнÑтрументы реÑурÑов"
+
+#~ msgid "Make Local"
+#~ msgstr "Сделать локальным"
+
+#~ msgid "Edit Groups"
+#~ msgstr "Редактировать группы"
+
+#~ msgid "Edit Connections"
+#~ msgstr "Редактировать ÑвÑзи"
+
+#~ msgid "GridMap Paint"
+#~ msgstr "РиÑование Ñетки"
+
+#~ msgid "Tiles"
+#~ msgstr "Тайлы"
+
+#~ msgid "Areas"
+#~ msgstr "ОблаÑти"
+
+#~ msgid "Ctrl+"
+#~ msgstr "Ctrl+"
+
+#~ msgid "Down Wheel)"
+#~ msgstr "КолеÑо мыши вниз"
+
+#~ msgid "Up Wheel)"
+#~ msgstr "КолеÑо мыши вверх"
+
#~ msgid "Close scene? (Unsaved changes will be lost)"
#~ msgstr "Закрыть Ñцену? (ÐеÑохранённые Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð±ÑƒÐ´ÑƒÑ‚ потерÑны.)"
@@ -8016,9 +8261,6 @@ msgstr ""
#~ msgid "Close Goto Prev. Scene"
#~ msgstr "Закрыть и перейти к предыдущей Ñцене"
-#~ msgid "Expand to Parent"
-#~ msgstr "РаÑÑ‚Ñнуть до размера родителей"
-
#~ msgid "Del"
#~ msgstr "Удалить"
@@ -8182,18 +8424,12 @@ msgstr ""
#~ msgid "Save Translatable Strings"
#~ msgstr "Сохранить переводимые Ñтроки"
-#~ msgid "Translatable Strings.."
-#~ msgstr "Переводимые Ñтроки.."
-
#~ msgid "Install Export Templates"
#~ msgstr "УÑтановить шаблоны ÑкÑпорта"
#~ msgid "Edit Script Options"
#~ msgstr "Редактировать параметры Ñкрипта"
-#~ msgid "Please export outside the project folder!"
-#~ msgstr "ПожалуйÑта ÑкÑпортируйте вне папки проекта!"
-
#~ msgid "Error exporting project!"
#~ msgstr "Ошибка ÑкÑÐ¿Ð¾Ñ€Ñ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¿Ñ€Ð¾ÐµÐºÑ‚Ð°!"
@@ -8252,18 +8488,12 @@ msgstr ""
#~ msgid "Include"
#~ msgstr "Включить"
-#~ msgid "Change Image Group"
-#~ msgstr "Измените изображение группы"
-
#~ msgid "Group name can't be empty!"
#~ msgstr "Ðазвание группы не может быть пуÑтым!"
#~ msgid "Invalid character in group name!"
#~ msgstr "ÐедопуÑтимый Ñимвол в названии группы!"
-#~ msgid "Group name already exists!"
-#~ msgstr "Ðазвание группы уже ÑущеÑтвует!"
-
#~ msgid "Add Image Group"
#~ msgstr "Добавлено изображение группы"
@@ -8342,9 +8572,6 @@ msgstr ""
#~ msgid "Preview Atlas"
#~ msgstr "ПредпроÑмотр атлаÑа"
-#~ msgid "Image Filter:"
-#~ msgstr "Фильтр:"
-
#~ msgid "Images:"
#~ msgstr "ИзображениÑ:"
@@ -8411,9 +8638,6 @@ msgstr ""
#~ msgid "Lighting"
#~ msgstr "ОÑвещение"
-#~ msgid "Toggle Persisting"
-#~ msgstr "Параметр изменён"
-
#~ msgid "Global"
#~ msgstr "Глобальные"
diff --git a/editor/translations/sk.po b/editor/translations/sk.po
index 381e5c53d1..e5ec2ed8d0 100644
--- a/editor/translations/sk.po
+++ b/editor/translations/sk.po
@@ -1,5 +1,6 @@
# Slovak translation of the Godot Engine editor
-# Copyright (C) 2016-2017 Juan Linietsky, Ariel Manzur and the Godot community
+# Copyright (C) 2007-2017 Juan Linietsky, Ariel Manzur
+# Copyright (C) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)
# This file is distributed under the same license as the Godot source code.
#
# J08nY <johnenter@gmail.com>, 2016.
@@ -192,10 +193,9 @@ msgid "Create %d NEW tracks and insert keys?"
msgstr ""
#: editor/animation_editor.cpp editor/create_dialog.cpp
-#: editor/editor_audio_buses.cpp
+#: editor/editor_audio_buses.cpp editor/plugins/abstract_polygon_2d_editor.cpp
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
#: editor/plugins/mesh_instance_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp editor/project_manager.cpp
#: editor/script_create_dialog.cpp
msgid "Create"
@@ -357,263 +357,6 @@ msgstr ""
msgid "Change Array Value"
msgstr ""
-#: editor/asset_library_editor_plugin.cpp
-msgid "Free"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_plugin_settings.cpp
-msgid "Version:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Contents:"
-msgstr "Konštanty:"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "View Files"
-msgstr "Súbor:"
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_help.cpp editor/property_selector.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Description:"
-msgstr "Popis:"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-#: editor/project_manager.cpp
-msgid "Install"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/call_dialog.cpp
-#: editor/connections_dialog.cpp editor/export_template_manager.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-#: editor/project_settings_editor.cpp editor/property_editor.cpp
-#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Close"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve hostname:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Connection error, please try again."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't connect."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't connect to host:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response from host:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Request failed, return code:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Req. Failed."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Request failed, too many redirects"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Redirect Loop."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Bad download hash, assuming file has been tampered with."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Expected:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Got:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Asset Download Error:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-msgid "Success!"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Fetching:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Resolving.."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Connecting.."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Requesting.."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Error making request"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Idle"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Retry"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Download Error"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Download for this asset is already in progress!"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "first"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "prev"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "next"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "last"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "All"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
-#: editor/settings_config_dialog.cpp
-msgid "Search:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/code_editor.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Search"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/project_manager.cpp
-msgid "Import"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Plugins"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Sort:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Reverse"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Category:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Site:"
-msgstr "Stránka:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Support.."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Official"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-msgid "Community"
-msgstr "Komunita"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Testing"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Assets ZIP File"
-msgstr ""
-
-#: editor/call_dialog.cpp
-msgid "Method List For '%s':"
-msgstr ""
-
-#: editor/call_dialog.cpp modules/visual_script/visual_script_editor.cpp
-msgid "Call"
-msgstr ""
-
-#: editor/call_dialog.cpp
-msgid "Method List:"
-msgstr ""
-
-#: editor/call_dialog.cpp
-msgid "Arguments:"
-msgstr ""
-
-#: editor/call_dialog.cpp
-msgid "Return:"
-msgstr ""
-
#: editor/code_editor.cpp
msgid "Go to Line"
msgstr ""
@@ -650,6 +393,14 @@ msgstr ""
msgid "Selection Only"
msgstr ""
+#: editor/code_editor.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
+msgid "Search"
+msgstr ""
+
#: editor/code_editor.cpp editor/editor_help.cpp
msgid "Find"
msgstr ""
@@ -682,11 +433,11 @@ msgstr ""
msgid "Skip"
msgstr ""
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom In"
msgstr ""
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom Out"
msgstr ""
@@ -753,6 +504,20 @@ msgstr ""
msgid "Oneshot"
msgstr ""
+#: editor/connections_dialog.cpp editor/dependency_editor.cpp
+#: editor/export_template_manager.cpp
+#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Close"
+msgstr ""
+
#: editor/connections_dialog.cpp
msgid "Connect"
msgstr ""
@@ -778,7 +543,7 @@ msgstr ""
msgid "Disconnect"
msgstr ""
-#: editor/connections_dialog.cpp editor/node_dock.cpp
+#: editor/connections_dialog.cpp editor/editor_help.cpp editor/node_dock.cpp
msgid "Signals"
msgstr ""
@@ -795,12 +560,25 @@ msgstr ""
msgid "Recent:"
msgstr ""
+#: editor/create_dialog.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/quick_open.cpp editor/settings_config_dialog.cpp
+msgid "Search:"
+msgstr ""
+
#: editor/create_dialog.cpp editor/editor_help.cpp
#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/quick_open.cpp
msgid "Matches:"
msgstr ""
+#: editor/create_dialog.cpp editor/editor_help.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/property_selector.cpp
+#: editor/script_editor_debugger.cpp
+msgid "Description:"
+msgstr "Popis:"
+
#: editor/dependency_editor.cpp
msgid "Search Replacement For:"
msgstr ""
@@ -856,6 +634,10 @@ msgid "Owners Of:"
msgstr ""
#: editor/dependency_editor.cpp
+msgid "Remove selected files from the project? (no undo)"
+msgstr ""
+
+#: editor/dependency_editor.cpp
msgid ""
"The files being removed are required by other resources in order for them to "
"work.\n"
@@ -863,7 +645,7 @@ msgid ""
msgstr ""
#: editor/dependency_editor.cpp
-msgid "Remove selected files from the project? (no undo)"
+msgid "Cannot remove:\n"
msgstr ""
#: editor/dependency_editor.cpp
@@ -930,10 +712,6 @@ msgid "Godot Engine contributors"
msgstr ""
#: editor/editor_about.cpp
-msgid "Authors"
-msgstr ""
-
-#: editor/editor_about.cpp
msgid "Project Founders"
msgstr ""
@@ -950,6 +728,38 @@ msgid "Developers"
msgstr ""
#: editor/editor_about.cpp
+msgid "Authors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Platinum Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Gold Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Mini Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Gold Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Silver Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Bronze Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
msgid "License"
msgstr ""
@@ -992,6 +802,16 @@ msgid "Package Installed Successfully!"
msgstr ""
#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Success!"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/project_manager.cpp
+msgid "Install"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
msgid "Package Installer"
msgstr ""
@@ -1041,10 +861,6 @@ msgid "Audio Bus, Drag and Drop to rearrange."
msgstr ""
#: editor/editor_audio_buses.cpp
-msgid "Bus options"
-msgstr ""
-
-#: editor/editor_audio_buses.cpp
msgid "Solo"
msgstr ""
@@ -1056,12 +872,20 @@ msgstr ""
msgid "Bypass"
msgstr ""
+#: editor/editor_audio_buses.cpp
+msgid "Bus options"
+msgstr ""
+
#: editor/editor_audio_buses.cpp editor/plugins/tile_map_editor_plugin.cpp
#: editor/scene_tree_dock.cpp
msgid "Duplicate"
msgstr ""
#: editor/editor_audio_buses.cpp
+msgid "Reset Volume"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
msgid "Delete Effect"
msgstr ""
@@ -1082,6 +906,10 @@ msgid "Duplicate Audio Bus"
msgstr ""
#: editor/editor_audio_buses.cpp
+msgid "Reset Bus Volume"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
msgid "Move Audio Bus"
msgstr ""
@@ -1113,7 +941,8 @@ msgstr ""
msgid "Create a new Bus Layout."
msgstr ""
-#: editor/editor_audio_buses.cpp editor/script_create_dialog.cpp
+#: editor/editor_audio_buses.cpp editor/property_editor.cpp
+#: editor/script_create_dialog.cpp
msgid "Load"
msgstr ""
@@ -1204,7 +1033,7 @@ msgid "Rearrange Autoloads"
msgstr ""
#: editor/editor_autoload_settings.cpp editor/editor_file_dialog.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp scene/gui/file_dialog.cpp
+#: scene/gui/file_dialog.cpp
msgid "Path:"
msgstr "Cesta:"
@@ -1212,9 +1041,7 @@ msgstr "Cesta:"
msgid "Node Name:"
msgstr ""
-#: editor/editor_autoload_settings.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp editor/project_manager.cpp
+#: editor/editor_autoload_settings.cpp editor/project_manager.cpp
msgid "Name"
msgstr ""
@@ -1247,18 +1074,19 @@ msgid "Choose a Directory"
msgstr ""
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Create Folder"
msgstr "Vytvoriť adresár"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: editor/editor_plugin_settings.cpp editor/plugins/theme_editor_plugin.cpp
-#: editor/project_export.cpp scene/gui/file_dialog.cpp
+#: editor/editor_plugin_settings.cpp editor/filesystem_dock.cpp
+#: editor/plugins/theme_editor_plugin.cpp editor/project_export.cpp
+#: scene/gui/file_dialog.cpp
msgid "Name:"
msgstr "Meno:"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Could not create folder."
msgstr ""
@@ -1278,30 +1106,6 @@ msgstr ""
msgid "Template file not found:\n"
msgstr ""
-#: editor/editor_export.cpp
-msgid "Added:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Removed:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Error saving atlas:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Could not save atlas subtexture:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Exporting for %s"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Setting Up.."
-msgstr ""
-
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "File Exists, Overwrite?"
msgstr ""
@@ -1386,6 +1190,10 @@ msgstr ""
msgid "Move Favorite Down"
msgstr ""
+#: editor/editor_file_dialog.cpp
+msgid "Go to parent folder"
+msgstr ""
+
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Directories & Files:"
msgstr "PrieÄinky a Súbory:"
@@ -1400,10 +1208,6 @@ msgid "File:"
msgstr "Súbor:"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
-msgid "Filter:"
-msgstr "Filter:"
-
-#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Must use a valid extension."
msgstr ""
@@ -1428,6 +1232,10 @@ msgstr "Zoznam tried:"
msgid "Search Classes"
msgstr ""
+#: editor/editor_help.cpp editor/plugins/spatial_editor_plugin.cpp
+msgid "Top"
+msgstr ""
+
#: editor/editor_help.cpp editor/property_editor.cpp
msgid "Class:"
msgstr "Trieda:"
@@ -1444,15 +1252,27 @@ msgstr ""
msgid "Brief Description:"
msgstr ""
+#: editor/editor_help.cpp
+msgid "Members"
+msgstr ""
+
#: editor/editor_help.cpp modules/visual_script/visual_script_editor.cpp
msgid "Members:"
msgstr ""
#: editor/editor_help.cpp
+msgid "Public Methods"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Public Methods:"
msgstr ""
#: editor/editor_help.cpp
+msgid "GUI Theme Items"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "GUI Theme Items:"
msgstr ""
@@ -1462,6 +1282,11 @@ msgstr "Signály:"
#: editor/editor_help.cpp
#, fuzzy
+msgid "Enumerations"
+msgstr "Popis:"
+
+#: editor/editor_help.cpp
+#, fuzzy
msgid "Enumerations:"
msgstr "Popis:"
@@ -1470,19 +1295,49 @@ msgid "enum "
msgstr ""
#: editor/editor_help.cpp
+#, fuzzy
+msgid "Constants"
+msgstr "Konštanty:"
+
+#: editor/editor_help.cpp
msgid "Constants:"
msgstr "Konštanty:"
#: editor/editor_help.cpp
#, fuzzy
+msgid "Description"
+msgstr "Popis:"
+
+#: editor/editor_help.cpp
+msgid "Properties"
+msgstr ""
+
+#: editor/editor_help.cpp
+#, fuzzy
msgid "Property Description:"
msgstr "Popis:"
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this property. Please help us by "
+"[color=$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+
+#: editor/editor_help.cpp
+msgid "Methods"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Method Description:"
msgstr ""
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this method. Please help us by [color="
+"$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Search Text"
msgstr ""
@@ -1491,24 +1346,21 @@ msgid "Output:"
msgstr ""
#: editor/editor_log.cpp editor/plugins/animation_tree_editor_plugin.cpp
-#: editor/plugins/rich_text_editor_plugin.cpp editor/property_editor.cpp
-#: editor/script_editor_debugger.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/property_editor.cpp editor/script_editor_debugger.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Clear"
msgstr ""
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Error saving resource!"
msgstr ""
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Save Resource As.."
msgstr ""
-#: editor/editor_node.cpp editor/export_template_manager.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "I see.."
msgstr ""
@@ -1525,6 +1377,26 @@ msgid "Error while saving."
msgstr ""
#: editor/editor_node.cpp
+msgid "Can't open '%s'."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Error while parsing '%s'."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Unexpected end of file '%s'."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Missing '%s' or its dependencies."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Error while loading '%s'."
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Saving Scene"
msgstr ""
@@ -1582,6 +1454,33 @@ msgid "Restored default layout to base settings."
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was imported, so it's not editable.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was instanced or inherited.\n"
+"Changes to it will not be kept when saving the current scene."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource was imported, so it's not editable. Change its settings in the "
+"import panel and then re-import."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This scene was imported, so changes to it will not be kept.\n"
+"Instancing it or inheriting will allow making changes to it.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Copy Params"
msgstr ""
@@ -1745,23 +1644,34 @@ msgid "Save changes the following scene(s) before opening Project Manager?"
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"This option is deprecated. Situations where refresh must be forced are now "
+"considered a bug. Please report."
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Pick a Main Scene"
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to enable addon plugin at: '"
+msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr ""
#: editor/editor_node.cpp
-msgid "' parsing of config failed."
+msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/"
+msgid "Unable to load addon script from path: '%s'."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to load addon script from path: '"
+msgid ""
+"Unable to load addon script from path: '%s' Base type is not EditorPlugin."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Unable to load addon script from path: '%s' Script is not in tool mode."
msgstr ""
#: editor/editor_node.cpp
@@ -1771,7 +1681,7 @@ msgid ""
msgstr ""
#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/scene_tree_dock.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Ugh"
msgstr ""
@@ -1782,11 +1692,11 @@ msgid ""
msgstr ""
#: editor/editor_node.cpp
-msgid "Error loading scene."
+msgid "Scene '%s' has broken dependencies:"
msgstr ""
#: editor/editor_node.cpp
-msgid "Scene '%s' has broken dependencies:"
+msgid "Clear Recent Scenes"
msgstr ""
#: editor/editor_node.cpp
@@ -1822,7 +1732,7 @@ msgstr ""
msgid "Toggle distraction-free mode."
msgstr ""
-#: editor/editor_node.cpp editor/io_plugins/editor_scene_import_plugin.cpp
+#: editor/editor_node.cpp
msgid "Scene"
msgstr ""
@@ -2042,6 +1952,10 @@ msgstr ""
msgid "Issue Tracker"
msgstr ""
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+msgid "Community"
+msgstr "Komunita"
+
#: editor/editor_node.cpp
msgid "About"
msgstr ""
@@ -2050,7 +1964,7 @@ msgstr ""
msgid "Play the project."
msgstr ""
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Play"
msgstr ""
@@ -2066,7 +1980,7 @@ msgstr ""
msgid "Stop the scene."
msgstr ""
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Stop"
msgstr ""
@@ -2139,6 +2053,15 @@ msgid "Object properties."
msgstr ""
#: editor/editor_node.cpp
+msgid "Changes may be lost!"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Import"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "FileSystem"
msgstr ""
@@ -2154,14 +2077,6 @@ msgstr ""
msgid "Don't Save"
msgstr ""
-#: editor/editor_node.cpp editor/editor_reimport_dialog.cpp
-msgid "Re-Import"
-msgstr ""
-
-#: editor/editor_node.cpp editor/editor_plugin_settings.cpp
-msgid "Update"
-msgstr ""
-
#: editor/editor_node.cpp
msgid "Import Templates From ZIP File"
msgstr ""
@@ -2225,11 +2140,28 @@ msgstr ""
msgid "Open the previous Editor"
msgstr ""
+#: editor/editor_plugin.cpp
+msgid "Creating Mesh Previews"
+msgstr ""
+
+#: editor/editor_plugin.cpp
+msgid "Thumbnail.."
+msgstr ""
+
#: editor/editor_plugin_settings.cpp
msgid "Installed Plugins:"
msgstr ""
#: editor/editor_plugin_settings.cpp
+msgid "Update"
+msgstr ""
+
+#: editor/editor_plugin_settings.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Version:"
+msgstr ""
+
+#: editor/editor_plugin_settings.cpp
msgid "Author:"
msgstr ""
@@ -2262,7 +2194,7 @@ msgid "Frame %"
msgstr ""
#: editor/editor_profiler.cpp
-msgid "Fixed Frame %"
+msgid "Physics Frame %"
msgstr ""
#: editor/editor_profiler.cpp editor/script_editor_debugger.cpp
@@ -2281,26 +2213,6 @@ msgstr ""
msgid "Frame #:"
msgstr ""
-#: editor/editor_reimport_dialog.cpp
-msgid "Please wait for scan to complete."
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Current scene must be saved to re-import."
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Save & Re-Import"
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Importing"
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Import Changed Resources"
-msgstr ""
-
#: editor/editor_run_native.cpp
msgid "Select device from the list"
msgstr ""
@@ -2410,10 +2322,6 @@ msgid "Importing:"
msgstr ""
#: editor/export_template_manager.cpp
-msgid "Loading Export Templates"
-msgstr ""
-
-#: editor/export_template_manager.cpp
msgid "Current Version:"
msgstr ""
@@ -2447,9 +2355,17 @@ msgid "Cannot navigate to '"
msgstr ""
#: editor/filesystem_dock.cpp
+msgid "View items as a grid of thumbnails"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "View items as a list"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
msgid ""
"\n"
-"Status: Needs Re-Import"
+"Status: Import of file failed. Please fix file and reimport manually."
msgstr ""
#: editor/filesystem_dock.cpp
@@ -2459,87 +2375,88 @@ msgid ""
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Same source and destination files, doing nothing."
+msgid "Cannot move/rename resources root."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Target file exists, can't overwrite. Delete first."
+msgid "Cannot move a folder into itself.\n"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Same source and destination paths, doing nothing."
+msgid "Error moving:\n"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Can't move directories to within themselves."
+msgid "Unable to update dependencies:\n"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Can't rename deps for:\n"
+msgid "No name provided"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Error moving file:\n"
+msgid "Provided name contains invalid characters"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Error moving dir:\n"
+msgid "No name provided."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Can't operate on '..'"
+msgid "Name contains invalid characters."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Pick New Name and Location For:"
+msgid "A file or folder with this name already exists."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "No files selected!"
+msgid "Renaming file:"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Expand all"
+msgid "Renaming folder:"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Collapse all"
+msgid "Expand all"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Show In File Manager"
+msgid "Collapse all"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Instance"
+msgid "Copy Path"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Edit Dependencies.."
+msgid "Rename.."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "View Owners.."
+msgid "Move To.."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Copy Path"
-msgstr ""
+#, fuzzy
+msgid "New Folder.."
+msgstr "Vytvoriť adresár"
#: editor/filesystem_dock.cpp
-msgid "Rename or Move.."
+msgid "Show In File Manager"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Move To.."
+msgid "Instance"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Info"
+msgid "Edit Dependencies.."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Re-Import.."
+msgid "View Owners.."
msgstr ""
#: editor/filesystem_dock.cpp
@@ -2572,6 +2489,11 @@ msgstr ""
msgid "Move"
msgstr ""
+#: editor/filesystem_dock.cpp editor/plugins/animation_tree_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Rename"
+msgstr ""
+
#: editor/groups_editor.cpp
msgid "Add to Group"
msgstr ""
@@ -2585,6 +2507,10 @@ msgid "Import as Single Scene"
msgstr ""
#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
msgid "Import with Separate Materials"
msgstr ""
@@ -2597,6 +2523,18 @@ msgid "Import with Separate Objects+Materials"
msgstr ""
#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Materials+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Materials+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
msgid "Import as Multiple Scenes"
msgstr ""
@@ -2605,38 +2543,31 @@ msgid "Import as Multiple Scenes+Materials"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Import Scene"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Importing Scene.."
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Running Custom Script.."
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Couldn't load post-import script:"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Invalid/broken script for post-import (check console):"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Error running post-import script:"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Saving.."
msgstr ""
@@ -2665,579 +2596,54 @@ msgstr ""
msgid "Reimport"
msgstr ""
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "No bit masks to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path is empty."
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must be a complete resource path."
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must exist."
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Save path is empty!"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Import BitMasks"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s):"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Target Path:"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Accept"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Bit Mask"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No source font file!"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No target font resource!"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"Invalid file extension.\n"
-"Please use .font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Can't load/process source font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Couldn't save font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font Size:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Dest Resource:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "The quick brown fox jumps over the lazy dog."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Test:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Options:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Font Import"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"This file is already a Godot font file, please supply a BMFont type file "
-"instead."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Failed opening as BMFont file."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error initializing FreeType."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Unknown font format."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error loading font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Invalid font size."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Invalid font custom source."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/plugins/theme_editor_plugin.cpp
-msgid "Font"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "No meshes to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Single Mesh Import"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Source Mesh(es):"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/plugins/mesh_instance_editor_plugin.cpp
-msgid "Mesh"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Surface %d"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "No samples to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Import Audio Samples"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Source Sample(s):"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Audio Sample"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "New Clip"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Animation Options"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Flags"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Bake FPS:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Optimizer"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Linear Error"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angular Error"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angle"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Clips"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Start(s)"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "End(s)"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Loop"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Filters"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source path is empty."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't load post-import script."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Invalid/broken script for post-import."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Error importing scene."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import 3D Scene"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source Scene:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Same as Target Scene"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Shared"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Target Texture Folder:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Post-Process Script:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Custom Root Node Type:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Auto"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Root Node Name:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "The Following Files are Missing:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Anyway"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp scene/gui/dialogs.cpp
-msgid "Cancel"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import & Open"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Edited scene has not been saved, open imported scene anyway?"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Image:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Can't import a file over itself:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't localize path: %s (already local)"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "3D Scene Animation"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Uncompressed"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossless (PNG)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossy (WebP)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress (VRAM)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Format"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Compression Quality (WebP):"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Options"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Please specify some files!"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "At least one file needed for Atlas."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Error importing:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Only one file is required for large texture."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Max Texture Size:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for Atlas (2D)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cell Size:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Large Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Textures (2D)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture"
+#: editor/multi_node_edit.cpp
+msgid "MultiNode Set"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Base Atlas Texture"
+#: editor/node_dock.cpp
+msgid "Groups"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s)"
+#: editor/node_dock.cpp
+msgid "Select a Node to edit Signals and Groups."
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 2D"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create Poly"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 3D"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Insert Point"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "2D Texture"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly (Remove Point)"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "3D Texture"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Remove Poly And Point"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Atlas Texture"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create a new polygon from scratch."
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
+#: editor/plugins/abstract_polygon_2d_editor.cpp
msgid ""
-"NOTICE: Importing 2D textures is not mandatory. Just copy png/jpg files to "
-"the project."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Crop empty space."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Load Source Image"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Slicing"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Inserting"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Saving"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save large texture:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Build Atlas For:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Loading Image:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't load image:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Converting Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cropping Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Blitting Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save atlas image:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save converted texture:"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid source!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid translation source!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Column"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/script_create_dialog.cpp
-msgid "Language"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No items to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No target path!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translations"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Couldn't import!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translation"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Source CSV:"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Ignore First Row"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Compress"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Add to Project (project.godot)"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Languages:"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Translation"
-msgstr ""
-
-#: editor/multi_node_edit.cpp
-msgid "MultiNode Set"
-msgstr ""
-
-#: editor/node_dock.cpp
-msgid "Groups"
-msgstr ""
-
-#: editor/node_dock.cpp
-msgid "Select a Node to edit Signals and Groups."
+"Edit existing polygon:\n"
+"LMB: Move Point.\n"
+"Ctrl+LMB: Split Segment.\n"
+"RMB: Erase Point."
msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
@@ -3393,7 +2799,6 @@ msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
#: editor/script_create_dialog.cpp
msgid "Error!"
@@ -3504,10 +2909,6 @@ msgid "Delete Input"
msgstr ""
#: editor/plugins/animation_tree_editor_plugin.cpp
-msgid "Rename"
-msgstr ""
-
-#: editor/plugins/animation_tree_editor_plugin.cpp
msgid "Animation tree is valid."
msgstr ""
@@ -3563,64 +2964,183 @@ msgstr ""
msgid "Filters.."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing %d Triangles:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Free"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Contents:"
+msgstr "Konštanty:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "View Files"
+msgstr "Súbor:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve hostname:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Triangle #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connection error, please try again."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Light Baker Setup:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't connect."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing Geometry"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't connect to host:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Fixing Lights"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response from host:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Making BVH"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Light Octree"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, return code:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Octree Texture"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Req. Failed."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Transfer to Lightmaps:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, too many redirects"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Allocating Texture #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Redirect Loop."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Baking Triangle #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Post-Processing Texture #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Bad download hash, assuming file has been tampered with."
msgstr ""
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Bake!"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Expected:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Got:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed sha256 hash check"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Asset Download Error:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Fetching:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Resolving.."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connecting.."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Requesting.."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Error making request"
msgstr ""
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Reset the lightmap octree baking process (start over)."
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Idle"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Retry"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download Error"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download for this asset is already in progress!"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "first"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "prev"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "next"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "last"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "All"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Plugins"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Sort:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Reverse"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Category:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Site:"
+msgstr "Stránka:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Support.."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Official"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Testing"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Assets ZIP File"
msgstr ""
#: editor/plugins/camera_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
msgid "Preview"
msgstr ""
@@ -3663,11 +3183,15 @@ msgid "Edit CanvasItem"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Change Anchors"
+msgid "Anchors only"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Change Anchors and Margins"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom (%):"
+msgid "Change Anchors"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3718,59 +3242,72 @@ msgid "Pan Mode"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Lock the selected object in place (can't be moved)."
+msgid "Toggles snapping"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Unlock the selected object (can be moved)."
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Use Snap"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Makes sure the object's children are not selectable."
+msgid "Snapping options"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Restores the object's children's ability to be selected."
+msgid "Snap to grid"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Edit"
+msgid "Use Rotation Snap"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Use Snap"
+msgid "Configure Snap..."
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Show Grid"
+msgid "Snap Relative"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Rotation Snap"
+msgid "Use Pixel Snap"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap Relative"
+msgid "Smart snapping"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Configure Snap.."
+msgid "Snap to parent"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Pixel Snap"
+msgid "Snap to node anchor"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to node sides"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Skeleton.."
+msgid "Snap to other nodes"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Lock the selected object in place (can't be moved)."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Unlock the selected object (can be moved)."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Makes sure the object's children are not selectable."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Restores the object's children's ability to be selected."
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3799,11 +3336,16 @@ msgid "View"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Reset"
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Show Grid"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Set.."
+msgid "Show helpers"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Show rulers"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3815,7 +3357,7 @@ msgid "Frame Selection"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Anchor"
+msgid "Layout"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3839,11 +3381,20 @@ msgid "Clear Pose"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Set a Value"
+msgid "Drag pivot from mouse position"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#, fuzzy
+msgid "Set pivot at mouse position"
+msgstr "Všetky vybrané"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Multiply grid step by 2"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap (Pixels):"
+msgid "Divide grid step by 2"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3854,23 +3405,28 @@ msgstr ""
msgid "Adding %s..."
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Create Node"
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Error instancing scene from %s"
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "OK :("
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "No parent to instance a child at."
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "This operation requires a single selected node."
msgstr ""
@@ -3884,45 +3440,6 @@ msgid ""
"Drag & drop + Alt : Change node type"
msgstr ""
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Create Poly"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly (Remove Point)"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Create a new polygon from scratch."
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-msgid ""
-"Edit existing polygon:\n"
-"LMB: Move Point.\n"
-"Ctrl+LMB: Split Segment.\n"
-"RMB: Erase Point."
-msgstr ""
-
#: editor/plugins/collision_polygon_editor_plugin.cpp
msgid "Create Poly3D"
msgstr ""
@@ -3932,14 +3449,6 @@ msgid "Set Handle"
msgstr ""
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Creating Mesh Library"
-msgstr ""
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Thumbnail.."
-msgstr ""
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Remove item %d?"
msgstr ""
@@ -3962,6 +3471,27 @@ msgid "Update from Scene"
msgstr ""
#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat0"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat1"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+#, fuzzy
+msgid "Ease in"
+msgstr "Všetky vybrané"
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Ease out"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Smoothstep"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
msgid "Modify Curve Point"
msgstr ""
@@ -4040,22 +3570,18 @@ msgid "Create Occluder Polygon"
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Edit existing polygon:"
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "LMB: Move Point."
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Ctrl+LMB: Split Segment."
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "RMB: Erase Point."
msgstr ""
@@ -4156,6 +3682,10 @@ msgid "Create Outline"
msgstr ""
#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Mesh"
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Create Trimesh Static Body"
msgstr ""
@@ -4283,12 +3813,72 @@ msgstr ""
msgid "Populate"
msgstr ""
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Create Navigation Polygon"
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake!"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake the navigation mesh.\n"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Clear the navigation mesh."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Setting up Configuration..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Calculating grid size..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating heightfield..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Marking walkable triangles..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Constructing compact heightfield..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Eroding walkable area..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Partitioning..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating contours..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating polymesh..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Converting to native navigation mesh..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Navigation Mesh Generator Setup:"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Parsing Geometry..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Done!"
msgstr ""
#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Remove Poly And Point"
+msgid "Create Navigation Polygon"
msgstr ""
#: editor/plugins/particles_2d_editor_plugin.cpp
@@ -4462,16 +4052,19 @@ msgid "Curve Point #"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve Point Position"
-msgstr ""
+msgstr "Všetky vybrané"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve In Position"
-msgstr ""
+msgstr "Všetky vybrané"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve Out Position"
-msgstr ""
+msgstr "Všetky vybrané"
#: editor/plugins/path_editor_plugin.cpp
msgid "Split Path"
@@ -4531,6 +4124,14 @@ msgid "Scale Polygon"
msgstr ""
#: editor/plugins/polygon_2d_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Edit"
+msgstr ""
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Polygon->UV"
msgstr ""
@@ -4585,63 +4186,10 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/shader_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "Vložiť"
-#: editor/plugins/rich_text_editor_plugin.cpp
-msgid "Parse BBCode"
-msgstr ""
-
-#: editor/plugins/sample_editor_plugin.cpp
-msgid "Length:"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Open Sample File(s)"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "ERROR: Couldn't load sample!"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Add Sample"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Rename Sample"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Delete Sample"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "16 Bits"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "8 Bits"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Stereo"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Mono"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Format"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Pitch"
-msgstr ""
-
#: editor/plugins/script_editor_plugin.cpp
msgid "Clear Recent Files"
msgstr ""
@@ -4733,6 +4281,10 @@ msgstr ""
msgid "Close All"
msgstr ""
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+msgid "Run"
+msgstr ""
+
#: editor/plugins/script_editor_plugin.cpp
msgid "Toggle Scripts Panel"
msgstr ""
@@ -4761,7 +4313,8 @@ msgstr ""
msgid "Break"
msgstr ""
-#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+#: editor/script_editor_debugger.cpp
msgid "Continue"
msgstr ""
@@ -4774,18 +4327,6 @@ msgid "Debug with external editor"
msgstr ""
#: editor/plugins/script_editor_plugin.cpp
-msgid "Window"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Left"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Right"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
msgid "Open Godot online documentation"
msgstr ""
@@ -4867,8 +4408,9 @@ msgid "Cut"
msgstr ""
#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "Kopírovať"
@@ -5131,10 +4673,6 @@ msgid "View Plane Transform."
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Scaling to %s%%."
-msgstr ""
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rotating %s degrees."
msgstr ""
@@ -5151,10 +4689,6 @@ msgid "Top View."
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Top"
-msgstr ""
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rear View."
msgstr ""
@@ -5385,6 +4919,10 @@ msgid "Transform"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Configure Snap.."
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Local Coords"
msgstr ""
@@ -5530,6 +5068,10 @@ msgid "Speed (FPS):"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Loop"
+msgstr ""
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Animation Frames"
msgstr ""
@@ -5542,11 +5084,12 @@ msgid "Insert Empty (After)"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Up"
-msgstr ""
+#, fuzzy
+msgid "Move (Before)"
+msgstr "Vložiť"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Down"
+msgid "Move (After)"
msgstr ""
#: editor/plugins/style_box_editor_plugin.cpp
@@ -5626,7 +5169,11 @@ msgid "Remove All"
msgstr "Všetky vybrané"
#: editor/plugins/theme_editor_plugin.cpp
-msgid "Theme"
+msgid "Edit theme.."
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Theme editing menu."
msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
@@ -5711,6 +5258,10 @@ msgid "Style"
msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
+msgid "Font"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
msgid "Color"
msgstr ""
@@ -5760,7 +5311,7 @@ msgid "Mirror Y"
msgstr ""
#: editor/plugins/tile_map_editor_plugin.cpp
-msgid "Bucket"
+msgid "Paint Tile"
msgstr ""
#: editor/plugins/tile_map_editor_plugin.cpp
@@ -5824,6 +5375,10 @@ msgid "Delete preset '%s'?"
msgstr ""
#: editor/project_export.cpp
+msgid "Export templates for this platform are missing/corrupted: "
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Presets"
msgstr ""
@@ -5894,19 +5449,29 @@ msgid "Export templates for this platform are missing:"
msgstr ""
#: editor/project_export.cpp
+msgid "Export templates for this platform are missing/corrupted:"
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Export With Debug"
msgstr ""
#: editor/project_manager.cpp
-msgid "Invalid project path, the path must exist!"
+msgid "The path does not exist."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Please choose a 'project.godot' file."
msgstr ""
#: editor/project_manager.cpp
-msgid "Invalid project path, project.godot must not exist."
+msgid ""
+"Your project will be created in a non empty folder (you might want to create "
+"a new folder)."
msgstr ""
#: editor/project_manager.cpp
-msgid "Invalid project path, project.godot must exist."
+msgid "Please choose a folder that does not contain a 'project.godot' file."
msgstr ""
#: editor/project_manager.cpp
@@ -5914,10 +5479,26 @@ msgid "Imported Project"
msgstr ""
#: editor/project_manager.cpp
+msgid " "
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "It would be a good idea to name your project."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Invalid project path (changed anything?)."
msgstr ""
#: editor/project_manager.cpp
+msgid "Couldn't get project.godot in project path."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Couldn't edit project.godot in project path."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
msgstr ""
@@ -5926,15 +5507,20 @@ msgid "The following files failed extraction from package:"
msgstr ""
#: editor/project_manager.cpp
-msgid "Import Existing Project"
+#, fuzzy
+msgid "Rename Project"
+msgstr "Všetky vybrané"
+
+#: editor/project_manager.cpp
+msgid "Couldn't get project.godot in the project path."
msgstr ""
#: editor/project_manager.cpp
-msgid "Project Path (Must Exist):"
+msgid "New Game Project"
msgstr ""
#: editor/project_manager.cpp
-msgid "Project Name:"
+msgid "Import Existing Project"
msgstr ""
#: editor/project_manager.cpp
@@ -5942,19 +5528,24 @@ msgid "Create New Project"
msgstr ""
#: editor/project_manager.cpp
-msgid "Project Path:"
+msgid "Install Project:"
msgstr ""
#: editor/project_manager.cpp
-msgid "Install Project:"
+msgid "Project Name:"
msgstr ""
#: editor/project_manager.cpp
-msgid "Browse"
+#, fuzzy
+msgid "Create folder"
+msgstr "Vytvoriť adresár"
+
+#: editor/project_manager.cpp
+msgid "Project Path:"
msgstr ""
#: editor/project_manager.cpp
-msgid "New Game Project"
+msgid "Browse"
msgstr ""
#: editor/project_manager.cpp
@@ -5966,6 +5557,10 @@ msgid "Unnamed Project"
msgstr ""
#: editor/project_manager.cpp
+msgid "Can't open project"
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Are you sure to open more than one project?"
msgstr ""
@@ -5992,16 +5587,18 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
-"You are about the scan %s folders for existing Godot projects. Do you "
-"confirm?"
+"Language changed.\n"
+"The UI will update next time the editor or project manager starts."
msgstr ""
#: editor/project_manager.cpp
-msgid "Project List"
+msgid ""
+"You are about the scan %s folders for existing Godot projects. Do you "
+"confirm?"
msgstr ""
#: editor/project_manager.cpp
-msgid "Run"
+msgid "Project List"
msgstr ""
#: editor/project_manager.cpp
@@ -6026,6 +5623,10 @@ msgid "Exit"
msgstr ""
#: editor/project_manager.cpp
+msgid "Restart Now"
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Can't run project"
msgstr ""
@@ -6062,17 +5663,14 @@ msgid "Add Input Action Event"
msgstr ""
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Meta+"
msgstr "Meta+"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Shift+"
msgstr "Shift+"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Alt+"
msgstr "Alt+"
@@ -6133,7 +5731,7 @@ msgstr ""
msgid "Joypad Axis Index:"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Axis"
msgstr "Os"
@@ -6153,31 +5751,31 @@ msgstr ""
msgid "Add Event"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Device"
msgstr "Zariadenie"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Button"
msgstr "TlaÄidlo"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Left Button."
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Right Button."
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Middle Button."
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Up."
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Down."
msgstr ""
@@ -6186,7 +5784,7 @@ msgid "Add Global Property"
msgstr ""
#: editor/project_settings_editor.cpp
-msgid "Select an setting item first!"
+msgid "Select a setting item first!"
msgstr ""
#: editor/project_settings_editor.cpp
@@ -6202,6 +5800,14 @@ msgid "Delete Item"
msgstr ""
#: editor/project_settings_editor.cpp
+msgid "Can't contain '/' or ':'"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Already existing"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "Error saving settings."
msgstr ""
@@ -6242,6 +5848,14 @@ msgid "Remove Resource Remap Option"
msgstr ""
#: editor/project_settings_editor.cpp
+msgid "Changed Locale Filter"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Changed Locale Filter Mode"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "Project Settings (project.godot)"
msgstr ""
@@ -6302,6 +5916,27 @@ msgid "Locale"
msgstr ""
#: editor/project_settings_editor.cpp
+msgid "Locales Filter"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Show all locales"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Show only selected locales"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Filter mode:"
+msgstr "Filter:"
+
+#: editor/project_settings_editor.cpp
+msgid "Locales:"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "AutoLoad"
msgstr ""
@@ -6351,10 +5986,18 @@ msgid "New Script"
msgstr "Popis:"
#: editor/property_editor.cpp
+msgid "Make Unique"
+msgstr ""
+
+#: editor/property_editor.cpp
msgid "Show in File System"
msgstr ""
#: editor/property_editor.cpp
+msgid "Convert To %s"
+msgstr ""
+
+#: editor/property_editor.cpp
msgid "Error loading file: Not a resource!"
msgstr ""
@@ -6392,6 +6035,10 @@ msgid "Select Property"
msgstr ""
#: editor/property_selector.cpp
+msgid "Select Virtual Method"
+msgstr ""
+
+#: editor/property_selector.cpp
msgid "Select Method"
msgstr ""
@@ -6419,26 +6066,6 @@ msgstr ""
msgid "Reparent"
msgstr ""
-#: editor/resources_dock.cpp
-msgid "Create New Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Open Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Save Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Resource Tools"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Make Local"
-msgstr ""
-
#: editor/run_settings_dialog.cpp
msgid "Run Mode:"
msgstr ""
@@ -6565,14 +6192,6 @@ msgid "Sub-Resources:"
msgstr ""
#: editor/scene_tree_dock.cpp
-msgid "Edit Groups"
-msgstr ""
-
-#: editor/scene_tree_dock.cpp
-msgid "Edit Connections"
-msgstr ""
-
-#: editor/scene_tree_dock.cpp
msgid "Clear Inheritance"
msgstr ""
@@ -6757,6 +6376,14 @@ msgid "Invalid base path"
msgstr ""
#: editor/script_create_dialog.cpp
+msgid "Directory of the same name exists"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
+msgid "File exists, will be reused"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
msgid "Invalid extension"
msgstr ""
@@ -6799,6 +6426,10 @@ msgid "Load existing script file"
msgstr "Popis:"
#: editor/script_create_dialog.cpp
+msgid "Language"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
msgid "Inherits"
msgstr ""
@@ -6842,6 +6473,10 @@ msgid "Function:"
msgstr ""
#: editor/script_editor_debugger.cpp
+msgid "Pick one or more items from the list to display the graph."
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
msgid "Errors"
msgstr ""
@@ -6922,6 +6557,10 @@ msgid "Type"
msgstr ""
#: editor/script_editor_debugger.cpp
+msgid "Format"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
msgid "Usage"
msgstr ""
@@ -6997,12 +6636,28 @@ msgstr ""
msgid "Change Probe Extents"
msgstr ""
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Library"
+msgstr ""
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Status"
+msgstr ""
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Libraries: "
+msgstr ""
+
+#: modules/gdnative/register_types.cpp
+msgid "GDNative"
+msgstr ""
+
#: modules/gdscript/gd_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Invalid type argument to convert(), use TYPE_* constants."
msgstr "Chybný argument convert(), použite TYPE_* konštanty."
-#: modules/gdscript/gd_functions.cpp
+#: modules/gdscript/gd_functions.cpp modules/mono/glue/glue_header.h
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Not enough bytes for decoding bytes, or invalid format."
msgstr "Nedostatok bajtov na dekódovanie, možný chybný formát."
@@ -7053,10 +6708,6 @@ msgid "GridMap Duplicate Selection"
msgstr ""
#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "GridMap Paint"
-msgstr ""
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Snap View"
msgstr ""
@@ -7149,13 +6800,8 @@ msgstr ""
msgid "Pick Distance:"
msgstr ""
-#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
-msgid "Tiles"
-msgstr "Súbor:"
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "Areas"
+#: modules/mono/editor/mono_bottom_panel.cpp
+msgid "Builds"
msgstr ""
#: modules/visual_script/visual_script.cpp
@@ -7348,10 +6994,18 @@ msgid "Return"
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
+msgid "Call"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
msgid "Get"
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
+msgid "Script already has function '%s'"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
msgid "Change Input Value"
msgstr ""
@@ -7718,6 +7372,12 @@ msgid ""
"order for AnimatedSprite3D to display frames."
msgstr ""
+#: scene/3d/vehicle_body.cpp
+msgid ""
+"VehicleWheel serves to provide a wheel system to a VehicleBody. Please use "
+"it as a child of a VehicleBody."
+msgstr ""
+
#: scene/gui/color_picker.cpp
msgid "Raw Mode"
msgstr ""
@@ -7727,6 +7387,10 @@ msgid "Add current color as a preset"
msgstr ""
#: scene/gui/dialogs.cpp
+msgid "Cancel"
+msgstr ""
+
+#: scene/gui/dialogs.cpp
msgid "Alert!"
msgstr ""
@@ -7734,10 +7398,6 @@ msgstr ""
msgid "Please Confirm..."
msgstr ""
-#: scene/gui/input_action.cpp
-msgid "Ctrl+"
-msgstr "Ctrl+"
-
#: scene/gui/popup.cpp
msgid ""
"Popups will hide by default unless you call popup() or any of the popup*() "
@@ -7766,6 +7426,32 @@ msgid ""
"texture to some node for display."
msgstr ""
+#: scene/resources/dynamic_font.cpp
+msgid "Error initializing FreeType."
+msgstr ""
+
+#: scene/resources/dynamic_font.cpp
+msgid "Unknown font format."
+msgstr ""
+
+#: scene/resources/dynamic_font.cpp
+msgid "Error loading font."
+msgstr ""
+
+#: scene/resources/dynamic_font.cpp
+msgid "Invalid font size."
+msgstr ""
+
+#~ msgid "Filter:"
+#~ msgstr "Filter:"
+
+#, fuzzy
+#~ msgid "Tiles"
+#~ msgstr "Súbor:"
+
+#~ msgid "Ctrl+"
+#~ msgstr "Ctrl+"
+
#, fuzzy
#~ msgid "Create Android keystore"
#~ msgstr "Vytvoriť adresár"
diff --git a/editor/translations/sl.po b/editor/translations/sl.po
index ff62db99ae..4a82428565 100644
--- a/editor/translations/sl.po
+++ b/editor/translations/sl.po
@@ -1,5 +1,6 @@
# Slovenian translation of the Godot Engine editor
-# Copyright (C) 2016-2017 Juan Linietsky, Ariel Manzur and the Godot community
+# Copyright (C) 2007-2017 Juan Linietsky, Ariel Manzur
+# Copyright (C) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)
# This file is distributed under the same license as the Godot source code.
#
# matevž lapajne <sivar.lapajne@gmail.com>, 2016.
@@ -192,10 +193,9 @@ msgid "Create %d NEW tracks and insert keys?"
msgstr ""
#: editor/animation_editor.cpp editor/create_dialog.cpp
-#: editor/editor_audio_buses.cpp
+#: editor/editor_audio_buses.cpp editor/plugins/abstract_polygon_2d_editor.cpp
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
#: editor/plugins/mesh_instance_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp editor/project_manager.cpp
#: editor/script_create_dialog.cpp
msgid "Create"
@@ -357,261 +357,6 @@ msgstr ""
msgid "Change Array Value"
msgstr ""
-#: editor/asset_library_editor_plugin.cpp
-msgid "Free"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_plugin_settings.cpp
-msgid "Version:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Contents:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "View Files"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_help.cpp editor/property_selector.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Description:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-#: editor/project_manager.cpp
-msgid "Install"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/call_dialog.cpp
-#: editor/connections_dialog.cpp editor/export_template_manager.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-#: editor/project_settings_editor.cpp editor/property_editor.cpp
-#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Close"
-msgstr "Zapri"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve hostname:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Connection error, please try again."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't connect."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't connect to host:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response from host:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Request failed, return code:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Req. Failed."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Request failed, too many redirects"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Redirect Loop."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Bad download hash, assuming file has been tampered with."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Expected:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Got:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Asset Download Error:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-msgid "Success!"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Fetching:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Resolving.."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Connecting.."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Requesting.."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Error making request"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Idle"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Retry"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Download Error"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Download for this asset is already in progress!"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "first"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "prev"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "next"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "last"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "All"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
-#: editor/settings_config_dialog.cpp
-msgid "Search:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/code_editor.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Search"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/project_manager.cpp
-msgid "Import"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Plugins"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Sort:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Reverse"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Category:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Site:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Support.."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Official"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-msgid "Community"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Testing"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Assets ZIP File"
-msgstr ""
-
-#: editor/call_dialog.cpp
-msgid "Method List For '%s':"
-msgstr ""
-
-#: editor/call_dialog.cpp modules/visual_script/visual_script_editor.cpp
-msgid "Call"
-msgstr ""
-
-#: editor/call_dialog.cpp
-msgid "Method List:"
-msgstr ""
-
-#: editor/call_dialog.cpp
-msgid "Arguments:"
-msgstr ""
-
-#: editor/call_dialog.cpp
-msgid "Return:"
-msgstr ""
-
#: editor/code_editor.cpp
msgid "Go to Line"
msgstr ""
@@ -648,6 +393,14 @@ msgstr ""
msgid "Selection Only"
msgstr ""
+#: editor/code_editor.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
+msgid "Search"
+msgstr ""
+
#: editor/code_editor.cpp editor/editor_help.cpp
msgid "Find"
msgstr ""
@@ -680,11 +433,11 @@ msgstr ""
msgid "Skip"
msgstr ""
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom In"
msgstr ""
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom Out"
msgstr ""
@@ -751,6 +504,20 @@ msgstr ""
msgid "Oneshot"
msgstr ""
+#: editor/connections_dialog.cpp editor/dependency_editor.cpp
+#: editor/export_template_manager.cpp
+#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Close"
+msgstr "Zapri"
+
#: editor/connections_dialog.cpp
msgid "Connect"
msgstr ""
@@ -776,7 +543,7 @@ msgstr ""
msgid "Disconnect"
msgstr ""
-#: editor/connections_dialog.cpp editor/node_dock.cpp
+#: editor/connections_dialog.cpp editor/editor_help.cpp editor/node_dock.cpp
msgid "Signals"
msgstr ""
@@ -793,12 +560,25 @@ msgstr ""
msgid "Recent:"
msgstr ""
+#: editor/create_dialog.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/quick_open.cpp editor/settings_config_dialog.cpp
+msgid "Search:"
+msgstr ""
+
#: editor/create_dialog.cpp editor/editor_help.cpp
#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/quick_open.cpp
msgid "Matches:"
msgstr ""
+#: editor/create_dialog.cpp editor/editor_help.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/property_selector.cpp
+#: editor/script_editor_debugger.cpp
+msgid "Description:"
+msgstr ""
+
#: editor/dependency_editor.cpp
msgid "Search Replacement For:"
msgstr ""
@@ -854,6 +634,10 @@ msgid "Owners Of:"
msgstr ""
#: editor/dependency_editor.cpp
+msgid "Remove selected files from the project? (no undo)"
+msgstr ""
+
+#: editor/dependency_editor.cpp
msgid ""
"The files being removed are required by other resources in order for them to "
"work.\n"
@@ -861,7 +645,7 @@ msgid ""
msgstr ""
#: editor/dependency_editor.cpp
-msgid "Remove selected files from the project? (no undo)"
+msgid "Cannot remove:\n"
msgstr ""
#: editor/dependency_editor.cpp
@@ -928,10 +712,6 @@ msgid "Godot Engine contributors"
msgstr ""
#: editor/editor_about.cpp
-msgid "Authors"
-msgstr ""
-
-#: editor/editor_about.cpp
msgid "Project Founders"
msgstr ""
@@ -948,6 +728,38 @@ msgid "Developers"
msgstr ""
#: editor/editor_about.cpp
+msgid "Authors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Platinum Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Gold Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Mini Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Gold Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Silver Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Bronze Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
msgid "License"
msgstr ""
@@ -988,6 +800,16 @@ msgid "Package Installed Successfully!"
msgstr ""
#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Success!"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/project_manager.cpp
+msgid "Install"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
msgid "Package Installer"
msgstr ""
@@ -1038,10 +860,6 @@ msgid "Audio Bus, Drag and Drop to rearrange."
msgstr ""
#: editor/editor_audio_buses.cpp
-msgid "Bus options"
-msgstr ""
-
-#: editor/editor_audio_buses.cpp
msgid "Solo"
msgstr ""
@@ -1053,12 +871,20 @@ msgstr ""
msgid "Bypass"
msgstr ""
+#: editor/editor_audio_buses.cpp
+msgid "Bus options"
+msgstr ""
+
#: editor/editor_audio_buses.cpp editor/plugins/tile_map_editor_plugin.cpp
#: editor/scene_tree_dock.cpp
msgid "Duplicate"
msgstr ""
#: editor/editor_audio_buses.cpp
+msgid "Reset Volume"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
#, fuzzy
msgid "Delete Effect"
msgstr "Izbriši Izbrano"
@@ -1080,6 +906,10 @@ msgid "Duplicate Audio Bus"
msgstr ""
#: editor/editor_audio_buses.cpp
+msgid "Reset Bus Volume"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
msgid "Move Audio Bus"
msgstr ""
@@ -1111,7 +941,8 @@ msgstr ""
msgid "Create a new Bus Layout."
msgstr ""
-#: editor/editor_audio_buses.cpp editor/script_create_dialog.cpp
+#: editor/editor_audio_buses.cpp editor/property_editor.cpp
+#: editor/script_create_dialog.cpp
msgid "Load"
msgstr ""
@@ -1201,7 +1032,7 @@ msgid "Rearrange Autoloads"
msgstr ""
#: editor/editor_autoload_settings.cpp editor/editor_file_dialog.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp scene/gui/file_dialog.cpp
+#: scene/gui/file_dialog.cpp
msgid "Path:"
msgstr ""
@@ -1209,9 +1040,7 @@ msgstr ""
msgid "Node Name:"
msgstr ""
-#: editor/editor_autoload_settings.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp editor/project_manager.cpp
+#: editor/editor_autoload_settings.cpp editor/project_manager.cpp
msgid "Name"
msgstr ""
@@ -1244,18 +1073,19 @@ msgid "Choose a Directory"
msgstr ""
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Create Folder"
msgstr ""
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: editor/editor_plugin_settings.cpp editor/plugins/theme_editor_plugin.cpp
-#: editor/project_export.cpp scene/gui/file_dialog.cpp
+#: editor/editor_plugin_settings.cpp editor/filesystem_dock.cpp
+#: editor/plugins/theme_editor_plugin.cpp editor/project_export.cpp
+#: scene/gui/file_dialog.cpp
msgid "Name:"
msgstr ""
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Could not create folder."
msgstr ""
@@ -1275,30 +1105,6 @@ msgstr ""
msgid "Template file not found:\n"
msgstr ""
-#: editor/editor_export.cpp
-msgid "Added:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Removed:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Error saving atlas:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Could not save atlas subtexture:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Exporting for %s"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Setting Up.."
-msgstr ""
-
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "File Exists, Overwrite?"
msgstr ""
@@ -1383,6 +1189,10 @@ msgstr ""
msgid "Move Favorite Down"
msgstr ""
+#: editor/editor_file_dialog.cpp
+msgid "Go to parent folder"
+msgstr ""
+
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Directories & Files:"
msgstr ""
@@ -1397,10 +1207,6 @@ msgid "File:"
msgstr ""
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
-msgid "Filter:"
-msgstr ""
-
-#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Must use a valid extension."
msgstr ""
@@ -1425,6 +1231,10 @@ msgstr ""
msgid "Search Classes"
msgstr ""
+#: editor/editor_help.cpp editor/plugins/spatial_editor_plugin.cpp
+msgid "Top"
+msgstr ""
+
#: editor/editor_help.cpp editor/property_editor.cpp
msgid "Class:"
msgstr ""
@@ -1441,15 +1251,28 @@ msgstr ""
msgid "Brief Description:"
msgstr ""
+#: editor/editor_help.cpp
+#, fuzzy
+msgid "Members"
+msgstr "ÄŒlani:"
+
#: editor/editor_help.cpp modules/visual_script/visual_script_editor.cpp
msgid "Members:"
msgstr "ÄŒlani:"
#: editor/editor_help.cpp
+msgid "Public Methods"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Public Methods:"
msgstr ""
#: editor/editor_help.cpp
+msgid "GUI Theme Items"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "GUI Theme Items:"
msgstr ""
@@ -1459,6 +1282,11 @@ msgstr "Signali:"
#: editor/editor_help.cpp
#, fuzzy
+msgid "Enumerations"
+msgstr "Funkcije:"
+
+#: editor/editor_help.cpp
+#, fuzzy
msgid "Enumerations:"
msgstr "Funkcije:"
@@ -1467,18 +1295,46 @@ msgid "enum "
msgstr ""
#: editor/editor_help.cpp
+msgid "Constants"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Constants:"
msgstr ""
#: editor/editor_help.cpp
+msgid "Description"
+msgstr ""
+
+#: editor/editor_help.cpp
+msgid "Properties"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Property Description:"
msgstr ""
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this property. Please help us by "
+"[color=$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+
+#: editor/editor_help.cpp
+msgid "Methods"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Method Description:"
msgstr ""
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this method. Please help us by [color="
+"$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Search Text"
msgstr ""
@@ -1487,24 +1343,21 @@ msgid "Output:"
msgstr ""
#: editor/editor_log.cpp editor/plugins/animation_tree_editor_plugin.cpp
-#: editor/plugins/rich_text_editor_plugin.cpp editor/property_editor.cpp
-#: editor/script_editor_debugger.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/property_editor.cpp editor/script_editor_debugger.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Clear"
msgstr ""
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Error saving resource!"
msgstr ""
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Save Resource As.."
msgstr ""
-#: editor/editor_node.cpp editor/export_template_manager.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "I see.."
msgstr ""
@@ -1521,6 +1374,26 @@ msgid "Error while saving."
msgstr ""
#: editor/editor_node.cpp
+msgid "Can't open '%s'."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Error while parsing '%s'."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Unexpected end of file '%s'."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Missing '%s' or its dependencies."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Error while loading '%s'."
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Saving Scene"
msgstr ""
@@ -1578,6 +1451,33 @@ msgid "Restored default layout to base settings."
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was imported, so it's not editable.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was instanced or inherited.\n"
+"Changes to it will not be kept when saving the current scene."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource was imported, so it's not editable. Change its settings in the "
+"import panel and then re-import."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This scene was imported, so changes to it will not be kept.\n"
+"Instancing it or inheriting will allow making changes to it.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Copy Params"
msgstr ""
@@ -1739,23 +1639,34 @@ msgid "Save changes the following scene(s) before opening Project Manager?"
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"This option is deprecated. Situations where refresh must be forced are now "
+"considered a bug. Please report."
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Pick a Main Scene"
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to enable addon plugin at: '"
+msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr ""
#: editor/editor_node.cpp
-msgid "' parsing of config failed."
+msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/"
+msgid "Unable to load addon script from path: '%s'."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to load addon script from path: '"
+msgid ""
+"Unable to load addon script from path: '%s' Base type is not EditorPlugin."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Unable to load addon script from path: '%s' Script is not in tool mode."
msgstr ""
#: editor/editor_node.cpp
@@ -1765,7 +1676,7 @@ msgid ""
msgstr ""
#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/scene_tree_dock.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Ugh"
msgstr ""
@@ -1776,11 +1687,11 @@ msgid ""
msgstr ""
#: editor/editor_node.cpp
-msgid "Error loading scene."
+msgid "Scene '%s' has broken dependencies:"
msgstr ""
#: editor/editor_node.cpp
-msgid "Scene '%s' has broken dependencies:"
+msgid "Clear Recent Scenes"
msgstr ""
#: editor/editor_node.cpp
@@ -1816,7 +1727,7 @@ msgstr ""
msgid "Toggle distraction-free mode."
msgstr ""
-#: editor/editor_node.cpp editor/io_plugins/editor_scene_import_plugin.cpp
+#: editor/editor_node.cpp
msgid "Scene"
msgstr ""
@@ -2036,6 +1947,10 @@ msgstr ""
msgid "Issue Tracker"
msgstr ""
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+msgid "Community"
+msgstr ""
+
#: editor/editor_node.cpp
msgid "About"
msgstr ""
@@ -2044,7 +1959,7 @@ msgstr ""
msgid "Play the project."
msgstr ""
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Play"
msgstr ""
@@ -2060,7 +1975,7 @@ msgstr ""
msgid "Stop the scene."
msgstr ""
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Stop"
msgstr ""
@@ -2133,6 +2048,15 @@ msgid "Object properties."
msgstr ""
#: editor/editor_node.cpp
+msgid "Changes may be lost!"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Import"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "FileSystem"
msgstr ""
@@ -2148,14 +2072,6 @@ msgstr ""
msgid "Don't Save"
msgstr ""
-#: editor/editor_node.cpp editor/editor_reimport_dialog.cpp
-msgid "Re-Import"
-msgstr ""
-
-#: editor/editor_node.cpp editor/editor_plugin_settings.cpp
-msgid "Update"
-msgstr ""
-
#: editor/editor_node.cpp
msgid "Import Templates From ZIP File"
msgstr ""
@@ -2216,11 +2132,28 @@ msgstr ""
msgid "Open the previous Editor"
msgstr ""
+#: editor/editor_plugin.cpp
+msgid "Creating Mesh Previews"
+msgstr ""
+
+#: editor/editor_plugin.cpp
+msgid "Thumbnail.."
+msgstr ""
+
#: editor/editor_plugin_settings.cpp
msgid "Installed Plugins:"
msgstr ""
#: editor/editor_plugin_settings.cpp
+msgid "Update"
+msgstr ""
+
+#: editor/editor_plugin_settings.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Version:"
+msgstr ""
+
+#: editor/editor_plugin_settings.cpp
msgid "Author:"
msgstr ""
@@ -2253,7 +2186,7 @@ msgid "Frame %"
msgstr ""
#: editor/editor_profiler.cpp
-msgid "Fixed Frame %"
+msgid "Physics Frame %"
msgstr ""
#: editor/editor_profiler.cpp editor/script_editor_debugger.cpp
@@ -2272,26 +2205,6 @@ msgstr ""
msgid "Frame #:"
msgstr ""
-#: editor/editor_reimport_dialog.cpp
-msgid "Please wait for scan to complete."
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Current scene must be saved to re-import."
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Save & Re-Import"
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Importing"
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Import Changed Resources"
-msgstr ""
-
#: editor/editor_run_native.cpp
msgid "Select device from the list"
msgstr ""
@@ -2401,10 +2314,6 @@ msgid "Importing:"
msgstr ""
#: editor/export_template_manager.cpp
-msgid "Loading Export Templates"
-msgstr ""
-
-#: editor/export_template_manager.cpp
msgid "Current Version:"
msgstr ""
@@ -2438,9 +2347,17 @@ msgid "Cannot navigate to '"
msgstr ""
#: editor/filesystem_dock.cpp
+msgid "View items as a grid of thumbnails"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "View items as a list"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
msgid ""
"\n"
-"Status: Needs Re-Import"
+"Status: Import of file failed. Please fix file and reimport manually."
msgstr ""
#: editor/filesystem_dock.cpp
@@ -2450,87 +2367,88 @@ msgid ""
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Same source and destination files, doing nothing."
+msgid "Cannot move/rename resources root."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Target file exists, can't overwrite. Delete first."
+msgid "Cannot move a folder into itself.\n"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Same source and destination paths, doing nothing."
+msgid "Error moving:\n"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Can't move directories to within themselves."
+msgid "Unable to update dependencies:\n"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Can't rename deps for:\n"
+msgid "No name provided"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Error moving file:\n"
+msgid "Provided name contains invalid characters"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Error moving dir:\n"
+msgid "No name provided."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Can't operate on '..'"
+msgid "Name contains invalid characters."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Pick New Name and Location For:"
+msgid "A file or folder with this name already exists."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "No files selected!"
-msgstr ""
+#, fuzzy
+msgid "Renaming file:"
+msgstr "Preimenuj Spremenljivko"
#: editor/filesystem_dock.cpp
-msgid "Expand all"
+msgid "Renaming folder:"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Collapse all"
+msgid "Expand all"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Show In File Manager"
+msgid "Collapse all"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Instance"
+msgid "Copy Path"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Edit Dependencies.."
+msgid "Rename.."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "View Owners.."
+msgid "Move To.."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Copy Path"
+msgid "New Folder.."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Rename or Move.."
+msgid "Show In File Manager"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Move To.."
+msgid "Instance"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Info"
+msgid "Edit Dependencies.."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Re-Import.."
+msgid "View Owners.."
msgstr ""
#: editor/filesystem_dock.cpp
@@ -2563,6 +2481,11 @@ msgstr ""
msgid "Move"
msgstr ""
+#: editor/filesystem_dock.cpp editor/plugins/animation_tree_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Rename"
+msgstr ""
+
#: editor/groups_editor.cpp
msgid "Add to Group"
msgstr ""
@@ -2576,6 +2499,10 @@ msgid "Import as Single Scene"
msgstr ""
#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
msgid "Import with Separate Materials"
msgstr ""
@@ -2588,6 +2515,18 @@ msgid "Import with Separate Objects+Materials"
msgstr ""
#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Materials+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Materials+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
msgid "Import as Multiple Scenes"
msgstr ""
@@ -2596,38 +2535,31 @@ msgid "Import as Multiple Scenes+Materials"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Import Scene"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Importing Scene.."
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Running Custom Script.."
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Couldn't load post-import script:"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Invalid/broken script for post-import (check console):"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Error running post-import script:"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Saving.."
msgstr ""
@@ -2655,579 +2587,54 @@ msgstr ""
msgid "Reimport"
msgstr ""
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "No bit masks to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path is empty."
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must be a complete resource path."
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must exist."
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Save path is empty!"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Import BitMasks"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s):"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Target Path:"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Accept"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Bit Mask"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No source font file!"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No target font resource!"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"Invalid file extension.\n"
-"Please use .font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Can't load/process source font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Couldn't save font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font Size:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Dest Resource:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "The quick brown fox jumps over the lazy dog."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Test:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Options:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Font Import"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"This file is already a Godot font file, please supply a BMFont type file "
-"instead."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Failed opening as BMFont file."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error initializing FreeType."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Unknown font format."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error loading font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Invalid font size."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Invalid font custom source."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/plugins/theme_editor_plugin.cpp
-msgid "Font"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "No meshes to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Single Mesh Import"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Source Mesh(es):"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/plugins/mesh_instance_editor_plugin.cpp
-msgid "Mesh"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Surface %d"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "No samples to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Import Audio Samples"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Source Sample(s):"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Audio Sample"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "New Clip"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Animation Options"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Flags"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Bake FPS:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Optimizer"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Linear Error"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angular Error"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angle"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Clips"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Start(s)"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "End(s)"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Loop"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Filters"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source path is empty."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't load post-import script."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Invalid/broken script for post-import."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Error importing scene."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import 3D Scene"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source Scene:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Same as Target Scene"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Shared"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Target Texture Folder:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Post-Process Script:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Custom Root Node Type:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Auto"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Root Node Name:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "The Following Files are Missing:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Anyway"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp scene/gui/dialogs.cpp
-msgid "Cancel"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import & Open"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Edited scene has not been saved, open imported scene anyway?"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Image:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Can't import a file over itself:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't localize path: %s (already local)"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "3D Scene Animation"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Uncompressed"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossless (PNG)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossy (WebP)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress (VRAM)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Format"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Compression Quality (WebP):"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Options"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Please specify some files!"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "At least one file needed for Atlas."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Error importing:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Only one file is required for large texture."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Max Texture Size:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for Atlas (2D)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cell Size:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Large Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Textures (2D)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture"
+#: editor/multi_node_edit.cpp
+msgid "MultiNode Set"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Base Atlas Texture"
+#: editor/node_dock.cpp
+msgid "Groups"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s)"
+#: editor/node_dock.cpp
+msgid "Select a Node to edit Signals and Groups."
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 2D"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create Poly"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 3D"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Insert Point"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "2D Texture"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly (Remove Point)"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "3D Texture"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Remove Poly And Point"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Atlas Texture"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create a new polygon from scratch."
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
+#: editor/plugins/abstract_polygon_2d_editor.cpp
msgid ""
-"NOTICE: Importing 2D textures is not mandatory. Just copy png/jpg files to "
-"the project."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Crop empty space."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Load Source Image"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Slicing"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Inserting"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Saving"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save large texture:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Build Atlas For:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Loading Image:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't load image:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Converting Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cropping Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Blitting Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save atlas image:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save converted texture:"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid source!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid translation source!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Column"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/script_create_dialog.cpp
-msgid "Language"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No items to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No target path!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translations"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Couldn't import!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translation"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Source CSV:"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Ignore First Row"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Compress"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Add to Project (project.godot)"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Languages:"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Translation"
-msgstr ""
-
-#: editor/multi_node_edit.cpp
-msgid "MultiNode Set"
-msgstr ""
-
-#: editor/node_dock.cpp
-msgid "Groups"
-msgstr ""
-
-#: editor/node_dock.cpp
-msgid "Select a Node to edit Signals and Groups."
+"Edit existing polygon:\n"
+"LMB: Move Point.\n"
+"Ctrl+LMB: Split Segment.\n"
+"RMB: Erase Point."
msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
@@ -3383,7 +2790,6 @@ msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
#: editor/script_create_dialog.cpp
msgid "Error!"
@@ -3494,10 +2900,6 @@ msgid "Delete Input"
msgstr ""
#: editor/plugins/animation_tree_editor_plugin.cpp
-msgid "Rename"
-msgstr ""
-
-#: editor/plugins/animation_tree_editor_plugin.cpp
msgid "Animation tree is valid."
msgstr ""
@@ -3553,64 +2955,181 @@ msgstr ""
msgid "Filters.."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing %d Triangles:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Free"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Triangle #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Contents:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Light Baker Setup:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "View Files"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing Geometry"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve hostname:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Fixing Lights"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Making BVH"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connection error, please try again."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Light Octree"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't connect."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Octree Texture"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't connect to host:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Transfer to Lightmaps:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response from host:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Allocating Texture #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Baking Triangle #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, return code:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Post-Processing Texture #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Req. Failed."
msgstr ""
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Bake!"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, too many redirects"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Redirect Loop."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Bad download hash, assuming file has been tampered with."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Expected:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Got:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed sha256 hash check"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Asset Download Error:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Fetching:"
msgstr ""
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Reset the lightmap octree baking process (start over)."
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Resolving.."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connecting.."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Requesting.."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Error making request"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Idle"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Retry"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download Error"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download for this asset is already in progress!"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "first"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "prev"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "next"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "last"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "All"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Plugins"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Sort:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Reverse"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Category:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Site:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Support.."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Official"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Testing"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Assets ZIP File"
msgstr ""
#: editor/plugins/camera_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
msgid "Preview"
msgstr ""
@@ -3653,11 +3172,15 @@ msgid "Edit CanvasItem"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Change Anchors"
+msgid "Anchors only"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom (%):"
+msgid "Change Anchors and Margins"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Change Anchors"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3708,59 +3231,73 @@ msgid "Pan Mode"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Lock the selected object in place (can't be moved)."
+#, fuzzy
+msgid "Toggles snapping"
+msgstr "Preklopi na Zaustavitev"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Use Snap"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Unlock the selected object (can be moved)."
+msgid "Snapping options"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Makes sure the object's children are not selectable."
+msgid "Snap to grid"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Restores the object's children's ability to be selected."
+msgid "Use Rotation Snap"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Edit"
-msgstr "Uredi"
+msgid "Configure Snap..."
+msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Use Snap"
+msgid "Snap Relative"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Show Grid"
+msgid "Use Pixel Snap"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Rotation Snap"
+msgid "Smart snapping"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap Relative"
+msgid "Snap to parent"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Configure Snap.."
+msgid "Snap to node anchor"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Pixel Snap"
+msgid "Snap to node sides"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Skeleton.."
+msgid "Snap to other nodes"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Lock the selected object in place (can't be moved)."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Unlock the selected object (can be moved)."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Makes sure the object's children are not selectable."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Restores the object's children's ability to be selected."
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3789,11 +3326,16 @@ msgid "View"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Reset"
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Show Grid"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Show helpers"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Set.."
+msgid "Show rulers"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3805,7 +3347,7 @@ msgid "Frame Selection"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Anchor"
+msgid "Layout"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3829,11 +3371,20 @@ msgid "Clear Pose"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Set a Value"
+msgid "Drag pivot from mouse position"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap (Pixels):"
+#, fuzzy
+msgid "Set pivot at mouse position"
+msgstr "Odstrani Signal"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Multiply grid step by 2"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Divide grid step by 2"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3844,23 +3395,28 @@ msgstr ""
msgid "Adding %s..."
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Create Node"
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Error instancing scene from %s"
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "OK :("
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "No parent to instance a child at."
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "This operation requires a single selected node."
msgstr ""
@@ -3874,45 +3430,6 @@ msgid ""
"Drag & drop + Alt : Change node type"
msgstr ""
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Create Poly"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly (Remove Point)"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Create a new polygon from scratch."
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-msgid ""
-"Edit existing polygon:\n"
-"LMB: Move Point.\n"
-"Ctrl+LMB: Split Segment.\n"
-"RMB: Erase Point."
-msgstr ""
-
#: editor/plugins/collision_polygon_editor_plugin.cpp
msgid "Create Poly3D"
msgstr ""
@@ -3922,14 +3439,6 @@ msgid "Set Handle"
msgstr ""
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Creating Mesh Library"
-msgstr ""
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Thumbnail.."
-msgstr ""
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Remove item %d?"
msgstr ""
@@ -3952,6 +3461,26 @@ msgid "Update from Scene"
msgstr ""
#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat0"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat1"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Ease in"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Ease out"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Smoothstep"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
msgid "Modify Curve Point"
msgstr ""
@@ -4030,22 +3559,18 @@ msgid "Create Occluder Polygon"
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Edit existing polygon:"
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "LMB: Move Point."
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Ctrl+LMB: Split Segment."
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "RMB: Erase Point."
msgstr ""
@@ -4146,6 +3671,10 @@ msgid "Create Outline"
msgstr ""
#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Mesh"
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Create Trimesh Static Body"
msgstr ""
@@ -4273,12 +3802,72 @@ msgstr ""
msgid "Populate"
msgstr ""
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Create Navigation Polygon"
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake!"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake the navigation mesh.\n"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Clear the navigation mesh."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Setting up Configuration..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Calculating grid size..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating heightfield..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Marking walkable triangles..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Constructing compact heightfield..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Eroding walkable area..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Partitioning..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating contours..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating polymesh..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Converting to native navigation mesh..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Navigation Mesh Generator Setup:"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Parsing Geometry..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Done!"
msgstr ""
#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Remove Poly And Point"
+msgid "Create Navigation Polygon"
msgstr ""
#: editor/plugins/particles_2d_editor_plugin.cpp
@@ -4452,16 +4041,19 @@ msgid "Curve Point #"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve Point Position"
-msgstr ""
+msgstr "Odstrani Signal"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve In Position"
-msgstr ""
+msgstr "Odstrani Signal"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve Out Position"
-msgstr ""
+msgstr "Odstrani Signal"
#: editor/plugins/path_editor_plugin.cpp
msgid "Split Path"
@@ -4521,6 +4113,14 @@ msgid "Scale Polygon"
msgstr ""
#: editor/plugins/polygon_2d_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Edit"
+msgstr "Uredi"
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Polygon->UV"
msgstr ""
@@ -4575,63 +4175,10 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/shader_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr ""
-#: editor/plugins/rich_text_editor_plugin.cpp
-msgid "Parse BBCode"
-msgstr ""
-
-#: editor/plugins/sample_editor_plugin.cpp
-msgid "Length:"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Open Sample File(s)"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "ERROR: Couldn't load sample!"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Add Sample"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Rename Sample"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Delete Sample"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "16 Bits"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "8 Bits"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Stereo"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Mono"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Format"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Pitch"
-msgstr ""
-
#: editor/plugins/script_editor_plugin.cpp
msgid "Clear Recent Files"
msgstr ""
@@ -4723,6 +4270,10 @@ msgstr ""
msgid "Close All"
msgstr "Zapri"
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+msgid "Run"
+msgstr ""
+
#: editor/plugins/script_editor_plugin.cpp
msgid "Toggle Scripts Panel"
msgstr ""
@@ -4751,7 +4302,8 @@ msgstr ""
msgid "Break"
msgstr ""
-#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+#: editor/script_editor_debugger.cpp
msgid "Continue"
msgstr ""
@@ -4764,18 +4316,6 @@ msgid "Debug with external editor"
msgstr ""
#: editor/plugins/script_editor_plugin.cpp
-msgid "Window"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Left"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Right"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
msgid "Open Godot online documentation"
msgstr ""
@@ -4857,8 +4397,9 @@ msgid "Cut"
msgstr ""
#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr ""
@@ -5122,10 +4663,6 @@ msgid "View Plane Transform."
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Scaling to %s%%."
-msgstr ""
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rotating %s degrees."
msgstr ""
@@ -5142,10 +4679,6 @@ msgid "Top View."
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Top"
-msgstr ""
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rear View."
msgstr ""
@@ -5375,6 +4908,10 @@ msgid "Transform"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Configure Snap.."
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Local Coords"
msgstr ""
@@ -5520,6 +5057,10 @@ msgid "Speed (FPS):"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Loop"
+msgstr ""
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Animation Frames"
msgstr ""
@@ -5532,11 +5073,11 @@ msgid "Insert Empty (After)"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Up"
+msgid "Move (Before)"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Down"
+msgid "Move (After)"
msgstr ""
#: editor/plugins/style_box_editor_plugin.cpp
@@ -5615,7 +5156,11 @@ msgid "Remove All"
msgstr "Odstrani Signal"
#: editor/plugins/theme_editor_plugin.cpp
-msgid "Theme"
+msgid "Edit theme.."
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Theme editing menu."
msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
@@ -5700,6 +5245,10 @@ msgid "Style"
msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
+msgid "Font"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
msgid "Color"
msgstr ""
@@ -5748,7 +5297,7 @@ msgid "Mirror Y"
msgstr ""
#: editor/plugins/tile_map_editor_plugin.cpp
-msgid "Bucket"
+msgid "Paint Tile"
msgstr ""
#: editor/plugins/tile_map_editor_plugin.cpp
@@ -5812,6 +5361,10 @@ msgid "Delete preset '%s'?"
msgstr ""
#: editor/project_export.cpp
+msgid "Export templates for this platform are missing/corrupted: "
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Presets"
msgstr ""
@@ -5882,19 +5435,29 @@ msgid "Export templates for this platform are missing:"
msgstr ""
#: editor/project_export.cpp
+msgid "Export templates for this platform are missing/corrupted:"
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Export With Debug"
msgstr ""
#: editor/project_manager.cpp
-msgid "Invalid project path, the path must exist!"
+msgid "The path does not exist."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Please choose a 'project.godot' file."
msgstr ""
#: editor/project_manager.cpp
-msgid "Invalid project path, project.godot must not exist."
+msgid ""
+"Your project will be created in a non empty folder (you might want to create "
+"a new folder)."
msgstr ""
#: editor/project_manager.cpp
-msgid "Invalid project path, project.godot must exist."
+msgid "Please choose a folder that does not contain a 'project.godot' file."
msgstr ""
#: editor/project_manager.cpp
@@ -5902,10 +5465,26 @@ msgid "Imported Project"
msgstr ""
#: editor/project_manager.cpp
+msgid " "
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "It would be a good idea to name your project."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Invalid project path (changed anything?)."
msgstr ""
#: editor/project_manager.cpp
+msgid "Couldn't get project.godot in project path."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Couldn't edit project.godot in project path."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
msgstr ""
@@ -5914,15 +5493,20 @@ msgid "The following files failed extraction from package:"
msgstr ""
#: editor/project_manager.cpp
-msgid "Import Existing Project"
+#, fuzzy
+msgid "Rename Project"
+msgstr "Preimenuj Funkcijo"
+
+#: editor/project_manager.cpp
+msgid "Couldn't get project.godot in the project path."
msgstr ""
#: editor/project_manager.cpp
-msgid "Project Path (Must Exist):"
+msgid "New Game Project"
msgstr ""
#: editor/project_manager.cpp
-msgid "Project Name:"
+msgid "Import Existing Project"
msgstr ""
#: editor/project_manager.cpp
@@ -5930,19 +5514,23 @@ msgid "Create New Project"
msgstr ""
#: editor/project_manager.cpp
-msgid "Project Path:"
+msgid "Install Project:"
msgstr ""
#: editor/project_manager.cpp
-msgid "Install Project:"
+msgid "Project Name:"
msgstr ""
#: editor/project_manager.cpp
-msgid "Browse"
+msgid "Create folder"
msgstr ""
#: editor/project_manager.cpp
-msgid "New Game Project"
+msgid "Project Path:"
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Browse"
msgstr ""
#: editor/project_manager.cpp
@@ -5954,6 +5542,10 @@ msgid "Unnamed Project"
msgstr ""
#: editor/project_manager.cpp
+msgid "Can't open project"
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Are you sure to open more than one project?"
msgstr ""
@@ -5980,16 +5572,18 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
-"You are about the scan %s folders for existing Godot projects. Do you "
-"confirm?"
+"Language changed.\n"
+"The UI will update next time the editor or project manager starts."
msgstr ""
#: editor/project_manager.cpp
-msgid "Project List"
+msgid ""
+"You are about the scan %s folders for existing Godot projects. Do you "
+"confirm?"
msgstr ""
#: editor/project_manager.cpp
-msgid "Run"
+msgid "Project List"
msgstr ""
#: editor/project_manager.cpp
@@ -6014,6 +5608,10 @@ msgid "Exit"
msgstr ""
#: editor/project_manager.cpp
+msgid "Restart Now"
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Can't run project"
msgstr ""
@@ -6050,17 +5648,14 @@ msgid "Add Input Action Event"
msgstr ""
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Meta+"
msgstr ""
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Shift+"
msgstr ""
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Alt+"
msgstr ""
@@ -6121,7 +5716,7 @@ msgstr "Spremeni"
msgid "Joypad Axis Index:"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Axis"
msgstr ""
@@ -6141,31 +5736,31 @@ msgstr ""
msgid "Add Event"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Device"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Button"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Left Button."
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Right Button."
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Middle Button."
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Up."
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Down."
msgstr ""
@@ -6175,7 +5770,7 @@ msgid "Add Global Property"
msgstr "Dodaj Getter Lastnost"
#: editor/project_settings_editor.cpp
-msgid "Select an setting item first!"
+msgid "Select a setting item first!"
msgstr ""
#: editor/project_settings_editor.cpp
@@ -6192,6 +5787,14 @@ msgid "Delete Item"
msgstr "Izbriši Izbrano"
#: editor/project_settings_editor.cpp
+msgid "Can't contain '/' or ':'"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Already existing"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "Error saving settings."
msgstr ""
@@ -6232,6 +5835,14 @@ msgid "Remove Resource Remap Option"
msgstr ""
#: editor/project_settings_editor.cpp
+msgid "Changed Locale Filter"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Changed Locale Filter Mode"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "Project Settings (project.godot)"
msgstr ""
@@ -6292,6 +5903,26 @@ msgid "Locale"
msgstr ""
#: editor/project_settings_editor.cpp
+msgid "Locales Filter"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Show all locales"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Show only selected locales"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Filter mode:"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Locales:"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "AutoLoad"
msgstr ""
@@ -6341,10 +5972,18 @@ msgid "New Script"
msgstr ""
#: editor/property_editor.cpp
+msgid "Make Unique"
+msgstr ""
+
+#: editor/property_editor.cpp
msgid "Show in File System"
msgstr ""
#: editor/property_editor.cpp
+msgid "Convert To %s"
+msgstr ""
+
+#: editor/property_editor.cpp
msgid "Error loading file: Not a resource!"
msgstr ""
@@ -6382,6 +6021,10 @@ msgid "Select Property"
msgstr "Dodaj Setter Lastnost"
#: editor/property_selector.cpp
+msgid "Select Virtual Method"
+msgstr ""
+
+#: editor/property_selector.cpp
msgid "Select Method"
msgstr ""
@@ -6409,26 +6052,6 @@ msgstr ""
msgid "Reparent"
msgstr ""
-#: editor/resources_dock.cpp
-msgid "Create New Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Open Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Save Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Resource Tools"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Make Local"
-msgstr ""
-
#: editor/run_settings_dialog.cpp
msgid "Run Mode:"
msgstr ""
@@ -6555,14 +6178,6 @@ msgid "Sub-Resources:"
msgstr ""
#: editor/scene_tree_dock.cpp
-msgid "Edit Groups"
-msgstr ""
-
-#: editor/scene_tree_dock.cpp
-msgid "Edit Connections"
-msgstr ""
-
-#: editor/scene_tree_dock.cpp
msgid "Clear Inheritance"
msgstr ""
@@ -6743,6 +6358,14 @@ msgid "Invalid base path"
msgstr ""
#: editor/script_create_dialog.cpp
+msgid "Directory of the same name exists"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
+msgid "File exists, will be reused"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
msgid "Invalid extension"
msgstr ""
@@ -6785,6 +6408,10 @@ msgid "Load existing script file"
msgstr ""
#: editor/script_create_dialog.cpp
+msgid "Language"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
msgid "Inherits"
msgstr ""
@@ -6826,6 +6453,10 @@ msgid "Function:"
msgstr ""
#: editor/script_editor_debugger.cpp
+msgid "Pick one or more items from the list to display the graph."
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
msgid "Errors"
msgstr ""
@@ -6906,6 +6537,10 @@ msgid "Type"
msgstr ""
#: editor/script_editor_debugger.cpp
+msgid "Format"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
msgid "Usage"
msgstr ""
@@ -6981,12 +6616,28 @@ msgstr ""
msgid "Change Probe Extents"
msgstr ""
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Library"
+msgstr ""
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Status"
+msgstr ""
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Libraries: "
+msgstr ""
+
+#: modules/gdnative/register_types.cpp
+msgid "GDNative"
+msgstr ""
+
#: modules/gdscript/gd_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Invalid type argument to convert(), use TYPE_* constants."
msgstr "Neveljavena vrsta argumenta za convert(), uporabite TYPE_* konstanto."
-#: modules/gdscript/gd_functions.cpp
+#: modules/gdscript/gd_functions.cpp modules/mono/glue/glue_header.h
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Not enough bytes for decoding bytes, or invalid format."
msgstr "Ni dovolj pomnilnika za dekodiranje bajtov, ali neveljaven format."
@@ -7038,10 +6689,6 @@ msgid "GridMap Duplicate Selection"
msgstr ""
#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "GridMap Paint"
-msgstr ""
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Snap View"
msgstr ""
@@ -7133,12 +6780,8 @@ msgstr ""
msgid "Pick Distance:"
msgstr ""
-#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "Tiles"
-msgstr ""
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "Areas"
+#: modules/mono/editor/mono_bottom_panel.cpp
+msgid "Builds"
msgstr ""
#: modules/visual_script/visual_script.cpp
@@ -7340,10 +6983,18 @@ msgid "Return"
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
+msgid "Call"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
msgid "Get"
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
+msgid "Script already has function '%s'"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
msgid "Change Input Value"
msgstr ""
@@ -7714,6 +7365,12 @@ msgid ""
"order for AnimatedSprite3D to display frames."
msgstr ""
+#: scene/3d/vehicle_body.cpp
+msgid ""
+"VehicleWheel serves to provide a wheel system to a VehicleBody. Please use "
+"it as a child of a VehicleBody."
+msgstr ""
+
#: scene/gui/color_picker.cpp
msgid "Raw Mode"
msgstr ""
@@ -7723,15 +7380,15 @@ msgid "Add current color as a preset"
msgstr ""
#: scene/gui/dialogs.cpp
-msgid "Alert!"
+msgid "Cancel"
msgstr ""
#: scene/gui/dialogs.cpp
-msgid "Please Confirm..."
+msgid "Alert!"
msgstr ""
-#: scene/gui/input_action.cpp
-msgid "Ctrl+"
+#: scene/gui/dialogs.cpp
+msgid "Please Confirm..."
msgstr ""
#: scene/gui/popup.cpp
@@ -7762,6 +7419,22 @@ msgid ""
"texture to some node for display."
msgstr ""
+#: scene/resources/dynamic_font.cpp
+msgid "Error initializing FreeType."
+msgstr ""
+
+#: scene/resources/dynamic_font.cpp
+msgid "Unknown font format."
+msgstr ""
+
+#: scene/resources/dynamic_font.cpp
+msgid "Error loading font."
+msgstr ""
+
+#: scene/resources/dynamic_font.cpp
+msgid "Invalid font size."
+msgstr ""
+
#, fuzzy
#~ msgid "Invalid unique name."
#~ msgstr "Neveljaven indeks lastnosti imena."
diff --git a/editor/translations/th.po b/editor/translations/th.po
index 0ccaf81e71..65bbafebb6 100644
--- a/editor/translations/th.po
+++ b/editor/translations/th.po
@@ -1,5 +1,6 @@
# Thai translation of the Godot Engine editor
-# Copyright (C) 2016-2017 Juan Linietsky, Ariel Manzur and the Godot community
+# Copyright (C) 2007-2017 Juan Linietsky, Ariel Manzur
+# Copyright (C) 2014-2017 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.
@@ -8,7 +9,7 @@
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
-"PO-Revision-Date: 2017-07-15 12:39+0000\n"
+"PO-Revision-Date: 2017-10-23 02:49+0000\n"
"Last-Translator: Poommetee Ketson <poommetee@protonmail.com>\n"
"Language-Team: Thai <https://hosted.weblate.org/projects/godot-engine/godot/"
"th/>\n"
@@ -16,7 +17,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8-bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
-"X-Generator: Weblate 2.16-dev\n"
+"X-Generator: Weblate 2.17\n"
#: editor/animation_editor.cpp
msgid "Disabled"
@@ -113,15 +114,15 @@ msgstr "ลบที่เลือà¸"
#: editor/animation_editor.cpp
msgid "Continuous"
-msgstr "ผันà¹à¸›à¸£"
+msgstr "ต่อเนื่อง"
#: editor/animation_editor.cpp
msgid "Discrete"
-msgstr "ค้าง"
+msgstr "ไม่ต่อเนื่อง"
#: editor/animation_editor.cpp
msgid "Trigger"
-msgstr "ไม่ค้าง"
+msgstr "ทริà¸à¹€à¸à¸­à¸£à¹Œ"
#: editor/animation_editor.cpp
msgid "Anim Add Key"
@@ -193,10 +194,9 @@ msgid "Create %d NEW tracks and insert keys?"
msgstr "เพิ่ม %d à¹à¸—ร็à¸à¹ƒà¸«à¸¡à¹ˆà¹à¸¥à¸°à¹€à¸žà¸´à¹ˆà¸¡à¸„ีย์?"
#: editor/animation_editor.cpp editor/create_dialog.cpp
-#: editor/editor_audio_buses.cpp
+#: editor/editor_audio_buses.cpp editor/plugins/abstract_polygon_2d_editor.cpp
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
#: editor/plugins/mesh_instance_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp editor/project_manager.cpp
#: editor/script_create_dialog.cpp
msgid "Create"
@@ -358,261 +358,6 @@ msgstr "เปลี่ยนประเภทตัวà¹à¸›à¸£à¹ƒà¸™à¸­à¸²à¸£
msgid "Change Array Value"
msgstr "เปลี่ยนค่าในอาร์เรย์"
-#: editor/asset_library_editor_plugin.cpp
-msgid "Free"
-msgstr "ฟรี"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_plugin_settings.cpp
-msgid "Version:"
-msgstr "รุ่น:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Contents:"
-msgstr "ประà¸à¸­à¸šà¸”้วย:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "View Files"
-msgstr "ดูไฟล์"
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_help.cpp editor/property_selector.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Description:"
-msgstr "รายละเอียด:"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-#: editor/project_manager.cpp
-msgid "Install"
-msgstr "ติดตั้ง"
-
-#: editor/asset_library_editor_plugin.cpp editor/call_dialog.cpp
-#: editor/connections_dialog.cpp editor/export_template_manager.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-#: editor/project_settings_editor.cpp editor/property_editor.cpp
-#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Close"
-msgstr "ปิด"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve hostname:"
-msgstr "ไม่พบตำà¹à¸«à¸™à¹ˆà¸‡à¸™à¸µà¹‰:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve."
-msgstr "ค้นหาไม่สำเร็จ"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Connection error, please try again."
-msgstr "เชื่อมต่อไม่ได้ à¸à¸£à¸¸à¸“าลองใหม่"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't connect."
-msgstr "เชื่อมต่อไม่ได้"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't connect to host:"
-msgstr "ไม่สามารถเชื่อมต่อà¸à¸±à¸šà¹‚ฮสต์:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response from host:"
-msgstr "ไม่มีà¸à¸²à¸£à¸•à¸­à¸šà¸à¸¥à¸±à¸šà¸ˆà¸²à¸à¹‚ฮสต์:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response."
-msgstr "ไม่มีà¸à¸²à¸£à¸•à¸­à¸šà¸à¸¥à¸±à¸š"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Request failed, return code:"
-msgstr "à¸à¸²à¸£à¸£à¹‰à¸­à¸‡à¸‚อผิดพลาด รหัส:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Req. Failed."
-msgstr "ร้องขอผิดพลาด"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Request failed, too many redirects"
-msgstr "à¸à¸²à¸£à¸£à¹‰à¸­à¸‡à¸‚อผิดพลาด เปลี่ยนทางมาà¸à¹€à¸à¸´à¸™à¹„ป"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Redirect Loop."
-msgstr "เปลี่ยนทางมาà¸à¹€à¸à¸´à¸™à¹„ป"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed:"
-msgstr "ผิดพลาด:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Bad download hash, assuming file has been tampered with."
-msgstr "à¹à¸®à¸Šà¸œà¸´à¸”พลาด ไฟล์ดาวน์โหลดอาจเสียหาย"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Expected:"
-msgstr "ที่ควรจะเป็น:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Got:"
-msgstr "ที่ได้รับ:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
-msgstr "ผิดพลาดในà¸à¸²à¸£à¸•à¸£à¸§à¸ˆà¸ªà¸­à¸šà¹à¸®à¸Š SHA256"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Asset Download Error:"
-msgstr "à¸à¸²à¸£à¸”าวน์โหลดผิดพลาด:"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-msgid "Success!"
-msgstr "สำเร็จ!"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Fetching:"
-msgstr "à¸à¸³à¸¥à¸±à¸‡à¸£à¸±à¸šà¸‚้อมูล:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Resolving.."
-msgstr "à¸à¸³à¸¥à¸±à¸‡à¸„้นหา.."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Connecting.."
-msgstr "à¸à¸³à¸¥à¸±à¸‡à¹€à¸Šà¸·à¹ˆà¸­à¸¡à¸•à¹ˆà¸­.."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Requesting.."
-msgstr "à¸à¸³à¸¥à¸±à¸‡à¸£à¹‰à¸­à¸‡à¸‚อ.."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Error making request"
-msgstr "à¸à¸²à¸£à¸£à¹‰à¸­à¸‡à¸‚อผิดพลาด"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Idle"
-msgstr "พร้อมใช้งาน"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Retry"
-msgstr "ลองใหม่"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Download Error"
-msgstr "ดาวน์โหลดผิดพลาด"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Download for this asset is already in progress!"
-msgstr "à¸à¸³à¸¥à¸±à¸‡à¸”าวน์โหลดไฟล์นี้อยู่à¹à¸¥à¹‰à¸§!"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "first"
-msgstr "à¹à¸£à¸à¸ªà¸¸à¸”"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "prev"
-msgstr "à¸à¹ˆà¸­à¸™à¸«à¸™à¹‰à¸²"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "next"
-msgstr "ถัดไป"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "last"
-msgstr "ท้ายสุด"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "All"
-msgstr "ทั้งหมด"
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
-#: editor/settings_config_dialog.cpp
-msgid "Search:"
-msgstr "ค้นหา:"
-
-#: editor/asset_library_editor_plugin.cpp editor/code_editor.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Search"
-msgstr "ค้นหา"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/project_manager.cpp
-msgid "Import"
-msgstr "นำเข้า"
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Plugins"
-msgstr "ปลั๊à¸à¸­à¸´à¸™"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Sort:"
-msgstr "เรียงตาม:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Reverse"
-msgstr "ย้อนà¸à¸¥à¸±à¸š"
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Category:"
-msgstr "หมวดหมู่:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Site:"
-msgstr "ไซต์:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Support.."
-msgstr "à¸à¸²à¸£à¸ªà¸™à¸±à¸šà¸ªà¸™à¸¸à¸™.."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Official"
-msgstr "ผู้พัฒนา"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-msgid "Community"
-msgstr "ชุมชน"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Testing"
-msgstr "ทดสอบ"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Assets ZIP File"
-msgstr "ไฟล์ ZIP"
-
-#: editor/call_dialog.cpp
-msgid "Method List For '%s':"
-msgstr "รายชื่อเมท็อดของ '%s':"
-
-#: editor/call_dialog.cpp modules/visual_script/visual_script_editor.cpp
-msgid "Call"
-msgstr "เรียà¸"
-
-#: editor/call_dialog.cpp
-msgid "Method List:"
-msgstr "รายชื่อเมท็อด:"
-
-#: editor/call_dialog.cpp
-msgid "Arguments:"
-msgstr "ตัวà¹à¸›à¸£:"
-
-#: editor/call_dialog.cpp
-msgid "Return:"
-msgstr "คืนค่า:"
-
#: editor/code_editor.cpp
msgid "Go to Line"
msgstr "ไปยังบรรทัด"
@@ -649,6 +394,14 @@ msgstr "ทั้งคำ"
msgid "Selection Only"
msgstr "เฉพาะที่à¸à¸³à¸¥à¸±à¸‡à¹€à¸¥à¸·à¸­à¸"
+#: editor/code_editor.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
+msgid "Search"
+msgstr "ค้นหา"
+
#: editor/code_editor.cpp editor/editor_help.cpp
msgid "Find"
msgstr "ค้นหา"
@@ -681,11 +434,11 @@ msgstr "เตือนà¸à¹ˆà¸­à¸™à¹à¸—นที่"
msgid "Skip"
msgstr "ข้าม"
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom In"
msgstr "ขยาย"
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom Out"
msgstr "ย่อ"
@@ -752,6 +505,20 @@ msgstr "เรียà¸à¸ à¸²à¸¢à¸«à¸¥à¸±à¸‡"
msgid "Oneshot"
msgstr "ครั้งเดียว"
+#: editor/connections_dialog.cpp editor/dependency_editor.cpp
+#: editor/export_template_manager.cpp
+#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Close"
+msgstr "ปิด"
+
#: editor/connections_dialog.cpp
msgid "Connect"
msgstr "เชื่อม"
@@ -777,7 +544,7 @@ msgstr "เชื่อมโยง.."
msgid "Disconnect"
msgstr "ลบà¸à¸²à¸£à¹€à¸Šà¸·à¹ˆà¸­à¸¡à¹‚ยง"
-#: editor/connections_dialog.cpp editor/node_dock.cpp
+#: editor/connections_dialog.cpp editor/editor_help.cpp editor/node_dock.cpp
msgid "Signals"
msgstr "สัà¸à¸à¸²à¸“"
@@ -794,12 +561,25 @@ msgstr "ที่ชื่นชอบ:"
msgid "Recent:"
msgstr "ล่าสุด:"
+#: editor/create_dialog.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/quick_open.cpp editor/settings_config_dialog.cpp
+msgid "Search:"
+msgstr "ค้นหา:"
+
#: editor/create_dialog.cpp editor/editor_help.cpp
#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/quick_open.cpp
msgid "Matches:"
msgstr "พบ:"
+#: editor/create_dialog.cpp editor/editor_help.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/property_selector.cpp
+#: editor/script_editor_debugger.cpp
+msgid "Description:"
+msgstr "รายละเอียด:"
+
#: editor/dependency_editor.cpp
msgid "Search Replacement For:"
msgstr "หาตัวà¹à¸—นของ:"
@@ -859,6 +639,10 @@ msgid "Owners Of:"
msgstr "เจ้าของของ:"
#: editor/dependency_editor.cpp
+msgid "Remove selected files from the project? (no undo)"
+msgstr "ลบไฟล์ที่เลือà¸à¸­à¸­à¸à¸ˆà¸²à¸à¹‚ปรเจà¸à¸•à¹Œ? (ย้อนà¸à¸¥à¸±à¸šà¹„ม่ได้)"
+
+#: editor/dependency_editor.cpp
msgid ""
"The files being removed are required by other resources in order for them to "
"work.\n"
@@ -868,8 +652,8 @@ msgstr ""
"ยืนยันจะลบหรือไม่? (ย้อนà¸à¸¥à¸±à¸šà¹„ม่ได้)"
#: editor/dependency_editor.cpp
-msgid "Remove selected files from the project? (no undo)"
-msgstr "ลบไฟล์ที่เลือà¸à¸­à¸­à¸à¸ˆà¸²à¸à¹‚ปรเจà¸à¸•à¹Œ? (ย้อนà¸à¸¥à¸±à¸šà¹„ม่ได้)"
+msgid "Cannot remove:\n"
+msgstr "ไม่สามารถลบ:\n"
#: editor/dependency_editor.cpp
msgid "Error loading:"
@@ -935,19 +719,12 @@ msgid "Godot Engine contributors"
msgstr "ผู้ช่วยพัฒนา Godot Engine"
#: editor/editor_about.cpp
-#, fuzzy
-msgid "Authors"
-msgstr "โดย:"
-
-#: editor/editor_about.cpp
-#, fuzzy
msgid "Project Founders"
-msgstr "ตัวจัดà¸à¸²à¸£à¹‚ปรเจà¸à¸•à¹Œ"
+msgstr "ผู้บุà¸à¹€à¸šà¸´à¸à¹‚ครงà¸à¸²à¸£"
#: editor/editor_about.cpp
-#, fuzzy
msgid "Lead Developer"
-msgstr "ผู้พัฒนา"
+msgstr "ผู้พัฒนาหลัà¸"
#: editor/editor_about.cpp editor/project_manager.cpp
msgid "Project Manager"
@@ -958,12 +735,44 @@ msgid "Developers"
msgstr "ผู้พัฒนา"
#: editor/editor_about.cpp
+msgid "Authors"
+msgstr "ทีมงาน"
+
+#: editor/editor_about.cpp
+msgid "Platinum Sponsors"
+msgstr "ผู้สนับสนุนระดับทองคำขาว"
+
+#: editor/editor_about.cpp
+msgid "Gold Sponsors"
+msgstr "ผู้สนับสนุนระดับทอง"
+
+#: editor/editor_about.cpp
+msgid "Mini Sponsors"
+msgstr "ผู้สนับสนุน"
+
+#: editor/editor_about.cpp
+msgid "Gold Donors"
+msgstr "ผู้บริจาคระดับทอง"
+
+#: editor/editor_about.cpp
+msgid "Silver Donors"
+msgstr "ผู้บริจาคระดับเงิน"
+
+#: editor/editor_about.cpp
+msgid "Bronze Donors"
+msgstr "ผู้บริจาคระดับทองà¹à¸”ง"
+
+#: editor/editor_about.cpp
+msgid "Donors"
+msgstr "ผู้บริจาค"
+
+#: editor/editor_about.cpp
msgid "License"
-msgstr ""
+msgstr "สัà¸à¸à¸²à¸­à¸™à¸¸à¸à¸²à¸•"
#: editor/editor_about.cpp
msgid "Thirdparty License"
-msgstr ""
+msgstr "สัà¸à¸à¸²à¸­à¸™à¸¸à¸à¸²à¸•à¹„ลบรารี"
#: editor/editor_about.cpp
msgid ""
@@ -972,104 +781,107 @@ msgid ""
"is an exhaustive list of all such thirdparty components with their "
"respective copyright statements and license terms."
msgstr ""
+"Godot Engine อาศัยไลบรารีต่าง ๆ ที่นำมาใช้ได้อย่างเสรีà¹à¸¥à¸°à¹€à¸›à¸´à¸”เผยโค้ดเป็นจำนวนมาภ"
+"ซึ่งเข้าà¸à¸±à¸™à¹„ด้à¸à¸±à¸šà¸ªà¸±à¸à¸à¸²à¸­à¸™à¸¸à¸à¸²à¸• MIT ต่อไปนี้เป็นรายชื่อของไลบรารีทั้งหมด รวมถึงข้อความลิขสิทธิ์ "
+"à¹à¸¥à¸°à¸‚้อà¸à¸³à¸«à¸™à¸”à¸à¸²à¸£à¹ƒà¸Šà¹‰à¸‡à¸²à¸™à¸‚องà¹à¸•à¹ˆà¸¥à¸°à¹„ลบรารี"
#: editor/editor_about.cpp
-#, fuzzy
msgid "All Components"
-msgstr "ประà¸à¸­à¸šà¸”้วย:"
+msgstr "ทั้งหมด"
#: editor/editor_about.cpp
-#, fuzzy
msgid "Components"
-msgstr "ประà¸à¸­à¸šà¸”้วย:"
+msgstr "ไลบรารี"
#: editor/editor_about.cpp
msgid "Licenses"
-msgstr ""
+msgstr "สัà¸à¸à¸²à¸­à¸™à¸¸à¸à¸²à¸•"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Error opening package file, not in zip format."
-msgstr ""
+msgstr "ผิดพลาดขณะเปิดไฟล์à¹à¸žà¸„เà¸à¸ˆ, ไม่ใช่รูปà¹à¸šà¸š zip"
#: editor/editor_asset_installer.cpp
-#, fuzzy
msgid "Uncompressing Assets"
-msgstr "ไม่บีบอัด"
+msgstr "à¸à¸³à¸¥à¸±à¸‡à¸„ลายบีบอัด"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package Installed Successfully!"
msgstr "ติดตั้งà¹à¸žà¸„เà¸à¸ˆà¹€à¸ªà¸£à¹‡à¸ˆà¸ªà¸¡à¸šà¸¹à¸£à¸“์!"
#: editor/editor_asset_installer.cpp
-#, fuzzy
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Success!"
+msgstr "สำเร็จ!"
+
+#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/project_manager.cpp
+msgid "Install"
+msgstr "ติดตั้ง"
+
+#: editor/editor_asset_installer.cpp
msgid "Package Installer"
-msgstr "ติดตั้งà¹à¸žà¸„เà¸à¸ˆà¹€à¸ªà¸£à¹‡à¸ˆà¸ªà¸¡à¸šà¸¹à¸£à¸“์!"
+msgstr "ตัวติดตั้งà¹à¸žà¸„เà¸à¸ˆ"
#: editor/editor_audio_buses.cpp
msgid "Speakers"
-msgstr ""
+msgstr "ลำโพง"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Add Effect"
-msgstr "เพิ่ม"
+msgstr "เพิ่มเอฟเฟà¸à¸•à¹Œ"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Rename Audio Bus"
-msgstr "เปิดเลย์เอาต์ของ Audio Bus"
+msgstr "เปลี่ยนชื่อ Audio Bus"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Toggle Audio Bus Solo"
-msgstr "เปิดเลย์เอาต์ของ Audio Bus"
+msgstr "สลับ Solo ของ Audio Bus"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Toggle Audio Bus Mute"
-msgstr "เปิดเลย์เอาต์ของ Audio Bus"
+msgstr "สลับ Mute ของ Audio Bus"
#: editor/editor_audio_buses.cpp
msgid "Toggle Audio Bus Bypass Effects"
-msgstr ""
+msgstr "สลับ Bypass ของ Audio Bus"
#: editor/editor_audio_buses.cpp
msgid "Select Audio Bus Send"
-msgstr ""
+msgstr "เลือภAudio Bus ที่ส่งต่อ"
#: editor/editor_audio_buses.cpp
msgid "Add Audio Bus Effect"
-msgstr ""
+msgstr "เพิ่มเอฟเฟà¸à¸•à¹Œà¹€à¸ªà¸µà¸¢à¸‡"
#: editor/editor_audio_buses.cpp
msgid "Move Bus Effect"
-msgstr ""
+msgstr "ย้ายเอฟเฟà¸à¸•à¹Œà¹€à¸ªà¸µà¸¢à¸‡"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Delete Bus Effect"
-msgstr "ลบสิ่งที่เลือà¸"
+msgstr "ลบเอฟเฟà¸à¸•à¹Œà¹€à¸ªà¸µà¸¢à¸‡"
#: editor/editor_audio_buses.cpp
msgid "Audio Bus, Drag and Drop to rearrange."
-msgstr ""
-
-#: editor/editor_audio_buses.cpp
-#, fuzzy
-msgid "Bus options"
-msgstr "ตัวเลือà¸à¸‰à¸²à¸à¸¢à¹ˆà¸­à¸¢"
+msgstr "Audio Bus, ลาà¸à¹à¸¥à¸°à¸§à¸²à¸‡à¹€à¸žà¸·à¹ˆà¸­à¸¢à¹‰à¸²à¸¢à¸•à¸³à¹à¸«à¸™à¹ˆà¸‡"
#: editor/editor_audio_buses.cpp
msgid "Solo"
-msgstr ""
+msgstr "โซโล"
#: editor/editor_audio_buses.cpp
msgid "Mute"
-msgstr ""
+msgstr "ปิดเสียง"
#: editor/editor_audio_buses.cpp
msgid "Bypass"
-msgstr ""
+msgstr "ข้าม"
+
+#: editor/editor_audio_buses.cpp
+msgid "Bus options"
+msgstr "ตัวเลือภBus"
#: editor/editor_audio_buses.cpp editor/plugins/tile_map_editor_plugin.cpp
#: editor/scene_tree_dock.cpp
@@ -1077,33 +889,36 @@ msgid "Duplicate"
msgstr "ทำซ้ำ"
#: editor/editor_audio_buses.cpp
-#, fuzzy
+msgid "Reset Volume"
+msgstr "รีเซ็ตระดับเสียง"
+
+#: editor/editor_audio_buses.cpp
msgid "Delete Effect"
-msgstr "ลบสิ่งที่เลือà¸"
+msgstr "ลบเอฟเฟà¸à¸•à¹Œ"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Add Audio Bus"
-msgstr "เพิ่ม Bus"
+msgstr "เพิ่ม Audio Bus"
#: editor/editor_audio_buses.cpp
msgid "Master bus can't be deleted!"
-msgstr ""
+msgstr "ลบ Bus หลัà¸à¹„ม่ได้!"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Delete Audio Bus"
-msgstr "ลบเลย์เอาต์"
+msgstr "ลบ Audio Bus"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Duplicate Audio Bus"
-msgstr "ทำซ้ำà¹à¸­à¸™à¸´à¹€à¸¡à¸Šà¸±à¸™"
+msgstr "ทำซ้ำ Audio Bus"
+
+#: editor/editor_audio_buses.cpp
+msgid "Reset Bus Volume"
+msgstr "รีเซ็ตระดับเสียงบัส"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Move Audio Bus"
-msgstr "เปิดเลย์เอาต์ของ Audio Bus"
+msgstr "ย้าย Audio Bus"
#: editor/editor_audio_buses.cpp
msgid "Save Audio Bus Layout As.."
@@ -1119,32 +934,28 @@ msgstr "เปิดเลย์เอาต์ของ Audio Bus"
#: editor/editor_audio_buses.cpp
msgid "There is no 'res://default_bus_layout.tres' file."
-msgstr ""
+msgstr "ไม่พบไฟล์ 'res://default_bus_layout.tres'"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Invalid file, not an audio bus layout."
-msgstr ""
-"นามสà¸à¸¸à¸¥à¹„ม่ถูà¸à¸•à¹‰à¸­à¸‡\n"
-"à¸à¸£à¸¸à¸“าใช้ .font"
+msgstr "ไฟล์ไม่ถูà¸à¸•à¹‰à¸­à¸‡, ไม่ใช่เลย์เอาต์ของ Audio Bus"
#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr "เพิ่ม Bus"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Create a new Bus Layout."
-msgstr "สร้างรีซอร์สใหม่"
+msgstr "สร้างเลย์เอาต์ Bus ใหม่"
-#: editor/editor_audio_buses.cpp editor/script_create_dialog.cpp
+#: editor/editor_audio_buses.cpp editor/property_editor.cpp
+#: editor/script_create_dialog.cpp
msgid "Load"
msgstr "โหลด"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Load an existing Bus Layout."
-msgstr "โหลดรีซอร์สที่มีอยู่à¹à¸¥à¹‰à¸§à¹ƒà¸™à¸”ิสà¸à¹Œà¹à¸¥à¸°à¸—ำà¸à¸²à¸£à¸›à¸£à¸±à¸šà¹à¸•à¹ˆà¸‡"
+msgstr "โหลดเลย์เอาต์ Bus จาà¸à¸”ิสà¸à¹Œ"
#: editor/editor_audio_buses.cpp
#: editor/plugins/animation_player_editor_plugin.cpp
@@ -1152,18 +963,16 @@ msgid "Save As"
msgstr "บันทึà¸à¹€à¸›à¹‡à¸™"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Save this Bus Layout to a file."
-msgstr "บันทึà¸à¹€à¸¥à¸¢à¹Œà¹€à¸­à¸²à¸•à¹Œà¸‚อง Audio Bus เป็น.."
+msgstr "บันทึà¸à¹€à¸¥à¸¢à¹Œà¹€à¸­à¸²à¸•à¹Œà¸‚อง Bus นี้เป็นไฟล์"
#: editor/editor_audio_buses.cpp editor/import_dock.cpp
-#, fuzzy
msgid "Load Default"
-msgstr "ค่าเริ่มต้น"
+msgstr "โหลดค่าเริ่มต้น"
#: editor/editor_audio_buses.cpp
msgid "Load the default Bus Layout."
-msgstr ""
+msgstr "โหลดค่าเริ่มต้นเลย์เอาต์ Bus"
#: editor/editor_autoload_settings.cpp
msgid "Invalid name."
@@ -1230,7 +1039,7 @@ msgid "Rearrange Autoloads"
msgstr "จัดลำดับออโต้โหลด"
#: editor/editor_autoload_settings.cpp editor/editor_file_dialog.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp scene/gui/file_dialog.cpp
+#: scene/gui/file_dialog.cpp
msgid "Path:"
msgstr "ตำà¹à¸«à¸™à¹ˆà¸‡:"
@@ -1238,9 +1047,7 @@ msgstr "ตำà¹à¸«à¸™à¹ˆà¸‡:"
msgid "Node Name:"
msgstr "ชื่อโหนด:"
-#: editor/editor_autoload_settings.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp editor/project_manager.cpp
+#: editor/editor_autoload_settings.cpp editor/project_manager.cpp
msgid "Name"
msgstr "ชื่อ"
@@ -1265,27 +1072,27 @@ msgid "Updating scene.."
msgstr "อัพเดทฉาà¸.."
#: editor/editor_dir_dialog.cpp
-#, fuzzy
msgid "Please select a base directory first"
-msgstr "à¸à¸£à¸¸à¸“าบันทึà¸à¸‰à¸²à¸à¸à¹ˆà¸­à¸™"
+msgstr "à¸à¸£à¸¸à¸“าเลือà¸à¹‚ฟลเดอร์เริ่มต้นà¸à¹ˆà¸­à¸™"
#: editor/editor_dir_dialog.cpp
msgid "Choose a Directory"
msgstr "เลือà¸à¹‚ฟลเดอร์"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Create Folder"
msgstr "สร้างโฟลเดอร์"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: editor/editor_plugin_settings.cpp editor/plugins/theme_editor_plugin.cpp
-#: editor/project_export.cpp scene/gui/file_dialog.cpp
+#: editor/editor_plugin_settings.cpp editor/filesystem_dock.cpp
+#: editor/plugins/theme_editor_plugin.cpp editor/project_export.cpp
+#: scene/gui/file_dialog.cpp
msgid "Name:"
msgstr "ชื่อ:"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Could not create folder."
msgstr "ไม่สามารถสร้างโฟลเดอร์"
@@ -1305,30 +1112,6 @@ msgstr "à¸à¸³à¸¥à¸±à¸‡à¸£à¸§à¸šà¸£à¸§à¸¡"
msgid "Template file not found:\n"
msgstr "ไม่พบà¹à¸¡à¹ˆà¹à¸šà¸š:\n"
-#: editor/editor_export.cpp
-msgid "Added:"
-msgstr "เพิ่ม:"
-
-#: editor/editor_export.cpp
-msgid "Removed:"
-msgstr "ลบ:"
-
-#: editor/editor_export.cpp
-msgid "Error saving atlas:"
-msgstr "ผิดพลาดขณะบันทึภatlas:"
-
-#: editor/editor_export.cpp
-msgid "Could not save atlas subtexture:"
-msgstr "บันทึภtexture ย่อยของ atlas ไม่ได้:"
-
-#: editor/editor_export.cpp
-msgid "Exporting for %s"
-msgstr "ส่งออà¸à¸ªà¸³à¸«à¸£à¸±à¸š %s"
-
-#: editor/editor_export.cpp
-msgid "Setting Up.."
-msgstr "à¸à¸³à¸¥à¸±à¸‡à¸•à¸±à¹‰à¸‡à¸„่า.."
-
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "File Exists, Overwrite?"
msgstr "มีไฟล์นี้อยู่à¹à¸¥à¹‰à¸§ จะเขียนทับหรือไม่?"
@@ -1402,7 +1185,6 @@ msgid "Toggle Mode"
msgstr "สลับโหมด"
#: editor/editor_file_dialog.cpp
-#, fuzzy
msgid "Focus Path"
msgstr "à¹à¸à¹‰à¹„ขตำà¹à¸«à¸™à¹ˆà¸‡"
@@ -1414,6 +1196,10 @@ msgstr "เลื่อนโฟลเดอร์ที่ชอบขึ้น
msgid "Move Favorite Down"
msgstr "เลื่อนโฟลเดอร์ที่ชอบลง"
+#: editor/editor_file_dialog.cpp
+msgid "Go to parent folder"
+msgstr "ไปยังโฟลเดอร์หลัà¸"
+
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Directories & Files:"
msgstr "ไฟล์à¹à¸¥à¸°à¹‚ฟลเดอร์:"
@@ -1428,10 +1214,6 @@ msgid "File:"
msgstr "ไฟล์:"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
-msgid "Filter:"
-msgstr "ตัวà¸à¸£à¸­à¸‡:"
-
-#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Must use a valid extension."
msgstr "นามสà¸à¸¸à¸¥à¹„ฟล์ไม่ถูà¸à¸•à¹‰à¸­à¸‡"
@@ -1456,6 +1238,10 @@ msgstr "รายชื่อคลาส:"
msgid "Search Classes"
msgstr "ค้นหาคลาส"
+#: editor/editor_help.cpp editor/plugins/spatial_editor_plugin.cpp
+msgid "Top"
+msgstr "บน"
+
#: editor/editor_help.cpp editor/property_editor.cpp
msgid "Class:"
msgstr "คลาส:"
@@ -1472,72 +1258,110 @@ msgstr "สืบทอดโดย:"
msgid "Brief Description:"
msgstr "รายละเอียด:"
+#: editor/editor_help.cpp
+msgid "Members"
+msgstr "ตัวà¹à¸›à¸£"
+
#: editor/editor_help.cpp modules/visual_script/visual_script_editor.cpp
msgid "Members:"
msgstr "ตัวà¹à¸›à¸£:"
#: editor/editor_help.cpp
+msgid "Public Methods"
+msgstr "เมท็อด"
+
+#: editor/editor_help.cpp
msgid "Public Methods:"
msgstr "เมท็อด:"
#: editor/editor_help.cpp
-#, fuzzy
+msgid "GUI Theme Items"
+msgstr "ตัวà¹à¸›à¸£à¸˜à¸µà¸¡"
+
+#: editor/editor_help.cpp
msgid "GUI Theme Items:"
-msgstr "ธีมหน้าต่าง:"
+msgstr "ตัวà¹à¸›à¸£à¸˜à¸µà¸¡:"
#: editor/editor_help.cpp modules/visual_script/visual_script_editor.cpp
msgid "Signals:"
msgstr "สัà¸à¸à¸²à¸“:"
#: editor/editor_help.cpp
-#, fuzzy
+msgid "Enumerations"
+msgstr "ค่าคงที่"
+
+#: editor/editor_help.cpp
msgid "Enumerations:"
-msgstr "à¹à¸­à¸™à¸´à¹€à¸¡à¸Šà¸±à¸™"
+msgstr "ค่าคงที่:"
#: editor/editor_help.cpp
msgid "enum "
-msgstr ""
+msgstr "à¸à¸¥à¸¸à¹ˆà¸¡à¸„่าคงที่ "
+
+#: editor/editor_help.cpp
+msgid "Constants"
+msgstr "ค่าคงที่"
#: editor/editor_help.cpp
msgid "Constants:"
msgstr "ค่าคงที่:"
#: editor/editor_help.cpp
+msgid "Description"
+msgstr "รายละเอียด"
+
+#: editor/editor_help.cpp
+msgid "Properties"
+msgstr "คุณสมบัติ"
+
+#: editor/editor_help.cpp
msgid "Property Description:"
msgstr "รายละเอียดตัวà¹à¸›à¸£:"
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this property. Please help us by "
+"[color=$color][url=$url]contributing one[/url][/color]!"
+msgstr "คุณสมบัตินี้ยังไม่มีคำอธิบาย โปรดช่วย[color=$color][url=$url]à¹à¸à¹‰à¹„ข[/url][/color]!"
+
+#: editor/editor_help.cpp
+msgid "Methods"
+msgstr "รายชื่อเมท็อด"
+
+#: editor/editor_help.cpp
msgid "Method Description:"
msgstr "รายละเอียดเมท็อด:"
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this method. Please help us by [color="
+"$color][url=$url]contributing one[/url][/color]!"
+msgstr "เมท็อดนี้ยังไม่มีคำอธิบาย โปรดช่วย[color=$color][url=$url]à¹à¸à¹‰à¹„ข[/url][/color]!"
+
+#: editor/editor_help.cpp
msgid "Search Text"
msgstr "ค้นหาคำ"
#: editor/editor_log.cpp
-#, fuzzy
msgid "Output:"
-msgstr " ข้อความ:"
+msgstr "ข้อความ:"
#: editor/editor_log.cpp editor/plugins/animation_tree_editor_plugin.cpp
-#: editor/plugins/rich_text_editor_plugin.cpp editor/property_editor.cpp
-#: editor/script_editor_debugger.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/property_editor.cpp editor/script_editor_debugger.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Clear"
msgstr "ลบ"
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Error saving resource!"
msgstr "บันทึà¸à¸£à¸µà¸‹à¸­à¸£à¹Œà¸ªà¸œà¸´à¸”พลาด!"
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Save Resource As.."
msgstr "บันทึà¸à¸£à¸µà¸‹à¸­à¸£à¹Œà¸ªà¹€à¸›à¹‡à¸™.."
-#: editor/editor_node.cpp editor/export_template_manager.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "I see.."
msgstr "ตà¸à¸¥à¸‡.."
@@ -1554,6 +1378,26 @@ msgid "Error while saving."
msgstr "ผิดพลาดขณะบันทึà¸"
#: editor/editor_node.cpp
+msgid "Can't open '%s'."
+msgstr "เปิด '%s' ไม่ได้"
+
+#: editor/editor_node.cpp
+msgid "Error while parsing '%s'."
+msgstr "ผิดพลาดขณะอ่านไฟล์ '%s'"
+
+#: editor/editor_node.cpp
+msgid "Unexpected end of file '%s'."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Missing '%s' or its dependencies."
+msgstr "ไฟล์ที่ '%s' ใช้สูà¸à¸«à¸²à¸¢"
+
+#: editor/editor_node.cpp
+msgid "Error while loading '%s'."
+msgstr "ผิดพลาดขณะโหลด '%s'"
+
+#: editor/editor_node.cpp
msgid "Saving Scene"
msgstr "บันทึà¸à¸‰à¸²à¸"
@@ -1566,7 +1410,6 @@ msgid "Creating Thumbnail"
msgstr "à¸à¸³à¸¥à¸±à¸‡à¸ªà¸£à¹‰à¸²à¸‡à¸£à¸¹à¸›à¸•à¸±à¸§à¸­à¸¢à¹ˆà¸²à¸‡"
#: editor/editor_node.cpp
-#, fuzzy
msgid "This operation can't be done without a tree root."
msgstr "ทำไม่ได้ถ้าไม่มีฉาà¸"
@@ -1612,6 +1455,40 @@ msgid "Restored default layout to base settings."
msgstr "คืนเลย์เอาต์เป็นค่าเริ่มต้น"
#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was imported, so it's not editable.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+"รีซอร์สนี้เป็นของฉาà¸à¸—ี่ถูà¸à¸™à¸³à¹€à¸‚้า จึงไม่สามารถà¹à¸à¹‰à¹„ขได้\n"
+"อ่านรายละเอียดเพิ่มเติมได้จาà¸à¸„ู่มือในส่วนของà¸à¸²à¸£à¸™à¸³à¹€à¸‚้าฉาà¸"
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was instanced or inherited.\n"
+"Changes to it will not be kept when saving the current scene."
+msgstr ""
+"รีซอร์สนี้เป็นของฉาà¸à¸—ี่ถูà¸à¸­à¸´à¸™à¸ªà¹à¸•à¸™à¸‹à¹Œà¸«à¸£à¸·à¸­à¸ªà¸·à¸šà¸—อด\n"
+"à¸à¸²à¸£à¹à¸à¹‰à¹„ขจะไม่ถูà¸à¸šà¸±à¸™à¸—ึà¸"
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource was imported, so it's not editable. Change its settings in the "
+"import panel and then re-import."
+msgstr "รีซอร์สนี้ถูà¸à¸™à¸³à¹€à¸‚้าจึงไม่สามารถà¹à¸à¹‰à¹„ขได้ ปรับตั้งค่าในà¹à¸œà¸‡à¸™à¸³à¹€à¸‚้าà¹à¸¥à¸°à¸™à¸³à¹€à¸‚้าใหม่"
+
+#: editor/editor_node.cpp
+msgid ""
+"This scene was imported, so changes to it will not be kept.\n"
+"Instancing it or inheriting will allow making changes to it.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+"ฉาà¸à¸™à¸µà¹‰à¸–ูà¸à¸™à¸³à¹€à¸‚้า à¸à¸²à¸£à¹à¸à¹‰à¹„ขจะไม่ถูà¸à¸šà¸±à¸™à¸—ึà¸\n"
+"ต้องอินสà¹à¸•à¸™à¸‹à¹Œà¸«à¸£à¸·à¸­à¸ªà¸·à¸šà¸—อดà¸à¹ˆà¸­à¸™à¸ˆà¸¶à¸‡à¸ˆà¸°à¸ªà¸²à¸¡à¸²à¸£à¸–à¹à¸à¹‰à¹„ขได้\n"
+"อ่านรายละเอียดเพิ่มเติมได้จาà¸à¸„ู่มือในส่วนของà¸à¸²à¸£à¸™à¸³à¹€à¸‚้าฉาà¸"
+
+#: editor/editor_node.cpp
msgid "Copy Params"
msgstr "คัดลอà¸à¸•à¸±à¸§à¹à¸›à¸£"
@@ -1632,9 +1509,8 @@ msgid "Make Built-In"
msgstr "à¸à¸±à¸‡"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Make Sub-Resources Unique"
-msgstr "ไม่ใช้รีซอร์สร่วมà¸à¸±à¸šà¸§à¸±à¸•à¸–ุอื่น"
+msgstr "ไม่ให้ใช้รีซอร์สร่วมà¸à¸±à¸šà¸§à¸±à¸•à¸–ุอื่น"
#: editor/editor_node.cpp
msgid "Open in Help"
@@ -1642,10 +1518,9 @@ msgstr "เปิดในคู่มือ"
#: editor/editor_node.cpp
msgid "There is no defined scene to run."
-msgstr "ไม่ได้à¸à¸³à¸«à¸™à¸”ฉาà¸à¹€à¸£à¸´à¹ˆà¸¡à¸•à¹‰à¸™"
+msgstr "ยังไม่ได้เลือà¸à¸‰à¸²à¸à¸—ี่จะเล่น"
#: editor/editor_node.cpp
-#, fuzzy
msgid ""
"No main scene has ever been defined, select one?\n"
"You can change it later in \"Project Settings\" under the 'application' "
@@ -1697,13 +1572,12 @@ msgid "Quick Open Script.."
msgstr "เปิดไฟล์สคริปต์ด่วน.."
#: editor/editor_node.cpp
-#, fuzzy
msgid "Save & Close"
-msgstr "บันทึà¸à¹„ฟล์"
+msgstr "บันทึà¸à¹à¸¥à¸°à¸›à¸´à¸”"
#: editor/editor_node.cpp
msgid "Save changes to '%s' before closing?"
-msgstr ""
+msgstr "บันทึภ'%s' à¸à¹ˆà¸­à¸™à¸›à¸´à¸”โปรà¹à¸à¸£à¸¡à¸«à¸£à¸·à¸­à¹„ม่?"
#: editor/editor_node.cpp
msgid "Save Scene As.."
@@ -1734,9 +1608,8 @@ msgid "Export Tile Set"
msgstr "ส่งออภTile Set"
#: editor/editor_node.cpp
-#, fuzzy
msgid "This operation can't be done without a selected node."
-msgstr "ทำไม่ได้ถ้าไม่มีฉาà¸"
+msgstr "ทำไม่ได้ถ้าไม่ได้เลือà¸à¹‚หนด"
#: editor/editor_node.cpp
msgid "Current scene not saved. Open anyway?"
@@ -1767,42 +1640,57 @@ msgid "Exit the editor?"
msgstr "ออà¸à¹‚ปรà¹à¸à¸£à¸¡?"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Open Project Manager?"
-msgstr "ตัวจัดà¸à¸²à¸£à¹‚ปรเจà¸à¸•à¹Œ"
+msgstr "เปิดตัวจัดà¸à¸²à¸£à¹‚ปรเจà¸à¸•à¹Œ?"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Save & Quit"
-msgstr "บันทึà¸à¹„ฟล์"
+msgstr "บันทึà¸à¹à¸¥à¸°à¸›à¸´à¸”"
#: editor/editor_node.cpp
msgid "Save changes to the following scene(s) before quitting?"
-msgstr ""
+msgstr "บันทึà¸à¸‰à¸²à¸à¸•à¹ˆà¸­à¹„ปนี้à¸à¹ˆà¸­à¸™à¸›à¸´à¸”โปรà¹à¸à¸£à¸¡à¸«à¸£à¸·à¸­à¹„ม่?"
#: editor/editor_node.cpp
msgid "Save changes the following scene(s) before opening Project Manager?"
+msgstr "บันทึà¸à¸‰à¸²à¸à¸•à¹ˆà¸­à¹„ปนี้à¸à¹ˆà¸­à¸™à¸à¸¥à¸±à¸šà¸ªà¸¹à¹ˆà¸•à¸±à¸§à¸ˆà¸±à¸”à¸à¸²à¸£à¹‚ปรเจà¸à¸•à¹Œà¸«à¸£à¸·à¸­à¹„ม่?"
+
+#: editor/editor_node.cpp
+msgid ""
+"This option is deprecated. Situations where refresh must be forced are now "
+"considered a bug. Please report."
msgstr ""
+"ตัวเลือà¸à¸™à¸µà¹‰à¸ˆà¸°à¸«à¸²à¸¢à¹„ปในรุ่นเสถียร สถานà¸à¸²à¸£à¸“์ที่จำเป็นต้องเปิดตัวเลือà¸à¸™à¸µà¹‰à¸ˆà¸°à¸–ือว่าเป็นบัค à¸à¸£à¸¸à¸“ารายงานบัค"
#: editor/editor_node.cpp
msgid "Pick a Main Scene"
msgstr "เลือà¸à¸‰à¸²à¸à¹€à¸£à¸´à¹ˆà¸¡à¸•à¹‰à¸™"
#: editor/editor_node.cpp
-msgid "Unable to enable addon plugin at: '"
-msgstr ""
+#, fuzzy
+msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
+msgstr "ไม่สามารถเปิดใช้งานปลั๊à¸à¸­à¸´à¸™: '"
#: editor/editor_node.cpp
-msgid "' parsing of config failed."
-msgstr ""
+#, fuzzy
+msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
+msgstr "ไม่พบชื่อสคริปต์ใน: 'res://addons/"
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/"
-msgstr ""
+#, fuzzy
+msgid "Unable to load addon script from path: '%s'."
+msgstr "ไม่สามารถโหลดสคริปต์จาà¸: '"
#: editor/editor_node.cpp
-msgid "Unable to load addon script from path: '"
-msgstr ""
+#, fuzzy
+msgid ""
+"Unable to load addon script from path: '%s' Base type is not EditorPlugin."
+msgstr "ไม่สามารถโหลดสคริปต์จาà¸: '"
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Unable to load addon script from path: '%s' Script is not in tool mode."
+msgstr "ไม่สามารถโหลดสคริปต์จาà¸: '"
#: editor/editor_node.cpp
msgid ""
@@ -1813,7 +1701,7 @@ msgstr ""
"สามารถสืบทอดไปยังฉาà¸à¹ƒà¸«à¸¡à¹ˆà¹€à¸žà¸·à¹ˆà¸­à¸—ำà¸à¸²à¸£à¹à¸à¹‰à¹„ข"
#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/scene_tree_dock.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Ugh"
msgstr "เออะ"
@@ -1826,14 +1714,14 @@ msgstr ""
"à¹à¸¥à¹‰à¸§à¸šà¸±à¸™à¸—ึà¸à¸¥à¸‡à¹ƒà¸™à¹‚ฟลเดอร์โปรเจà¸à¸•à¹Œ"
#: editor/editor_node.cpp
-msgid "Error loading scene."
-msgstr "ผิดพลาดขณะโหลดฉาà¸"
-
-#: editor/editor_node.cpp
msgid "Scene '%s' has broken dependencies:"
msgstr "ฉาภ'%s' มีà¸à¸²à¸£à¸­à¹‰à¸²à¸‡à¸­à¸´à¸‡à¸ªà¸¹à¸à¸«à¸²à¸¢:"
#: editor/editor_node.cpp
+msgid "Clear Recent Scenes"
+msgstr "ล้างรายà¸à¸²à¸£à¸‰à¸²à¸à¸¥à¹ˆà¸²à¸ªà¸¸à¸”"
+
+#: editor/editor_node.cpp
msgid "Save Layout"
msgstr "บันทึà¸à¹€à¸¥à¸¢à¹Œà¹€à¸­à¸²à¸•à¹Œ"
@@ -1863,11 +1751,10 @@ msgid "Distraction Free Mode"
msgstr "โหมดไร้สิ่งรบà¸à¸§à¸™"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Toggle distraction-free mode."
msgstr "โหมดไร้สิ่งรบà¸à¸§à¸™"
-#: editor/editor_node.cpp editor/io_plugins/editor_scene_import_plugin.cpp
+#: editor/editor_node.cpp
msgid "Scene"
msgstr "ฉาà¸"
@@ -2093,6 +1980,10 @@ msgstr "ถาม/ตอบ"
msgid "Issue Tracker"
msgstr "ระบบติดตามบัค"
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+msgid "Community"
+msgstr "ชุมชน"
+
#: editor/editor_node.cpp
msgid "About"
msgstr "เà¸à¸µà¹ˆà¸¢à¸§à¸à¸±à¸š"
@@ -2101,7 +1992,7 @@ msgstr "เà¸à¸µà¹ˆà¸¢à¸§à¸à¸±à¸š"
msgid "Play the project."
msgstr "เล่นโปรเจà¸à¸•à¹Œ"
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Play"
msgstr "เล่น"
@@ -2117,7 +2008,7 @@ msgstr "หยุดชั่วคราว"
msgid "Stop the scene."
msgstr "หยุด"
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Stop"
msgstr "หยุด"
@@ -2190,6 +2081,15 @@ msgid "Object properties."
msgstr "คุณสมบัติวัตถุ"
#: editor/editor_node.cpp
+msgid "Changes may be lost!"
+msgstr "à¸à¸²à¸£à¹à¸à¹‰à¹„ขจะไม่ถูà¸à¸šà¸±à¸™à¸—ึà¸!"
+
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Import"
+msgstr "นำเข้า"
+
+#: editor/editor_node.cpp
msgid "FileSystem"
msgstr "ระบบไฟล์"
@@ -2203,15 +2103,7 @@ msgstr "ข้อความ"
#: editor/editor_node.cpp
msgid "Don't Save"
-msgstr ""
-
-#: editor/editor_node.cpp editor/editor_reimport_dialog.cpp
-msgid "Re-Import"
-msgstr "นำเข้าอีà¸à¸„รั้ง"
-
-#: editor/editor_node.cpp editor/editor_plugin_settings.cpp
-msgid "Update"
-msgstr "อัพเดท"
+msgstr "ไม่บันทึà¸"
#: editor/editor_node.cpp
msgid "Import Templates From ZIP File"
@@ -2274,11 +2166,28 @@ msgstr "เปิดตัวà¹à¸à¹‰à¹„ขถัดไป"
msgid "Open the previous Editor"
msgstr "เปิดตัวà¹à¸à¹‰à¹„ขà¸à¹ˆà¸­à¸™à¸«à¸™à¹‰à¸²"
+#: editor/editor_plugin.cpp
+msgid "Creating Mesh Previews"
+msgstr "à¸à¸³à¸¥à¸±à¸‡à¸ªà¸£à¹‰à¸²à¸‡à¸ à¸²à¸žà¸•à¸±à¸§à¸­à¸¢à¹ˆà¸²à¸‡ Mesh"
+
+#: editor/editor_plugin.cpp
+msgid "Thumbnail.."
+msgstr "รูปตัวอย่าง.."
+
#: editor/editor_plugin_settings.cpp
msgid "Installed Plugins:"
msgstr "ปลั๊à¸à¸­à¸´à¸™à¸—ี่ติดตั้งà¹à¸¥à¹‰à¸§:"
#: editor/editor_plugin_settings.cpp
+msgid "Update"
+msgstr "อัพเดท"
+
+#: editor/editor_plugin_settings.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Version:"
+msgstr "รุ่น:"
+
+#: editor/editor_plugin_settings.cpp
msgid "Author:"
msgstr "โดย:"
@@ -2311,7 +2220,8 @@ msgid "Frame %"
msgstr "เฟรม %"
#: editor/editor_profiler.cpp
-msgid "Fixed Frame %"
+#, fuzzy
+msgid "Physics Frame %"
msgstr "เฟรมคงที่ %"
#: editor/editor_profiler.cpp editor/script_editor_debugger.cpp
@@ -2330,35 +2240,17 @@ msgstr ""
msgid "Frame #:"
msgstr "เฟรมที่:"
-#: editor/editor_reimport_dialog.cpp
-msgid "Please wait for scan to complete."
-msgstr "à¸à¸£à¸¸à¸“ารอให้à¸à¸²à¸£à¸ªà¹à¸à¸™à¹€à¸ªà¸£à¹‡à¸ˆ"
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Current scene must be saved to re-import."
-msgstr "ฉาà¸à¸›à¸±à¸ˆà¸ˆà¸¸à¸šà¸±à¸™à¸•à¹‰à¸­à¸‡à¸šà¸±à¸™à¸—ึà¸à¸à¹ˆà¸­à¸™à¸™à¸³à¹€à¸‚้าอีà¸à¸„รั้ง"
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Save & Re-Import"
-msgstr "บันทึà¸à¹à¸¥à¸°à¸™à¸³à¹€à¸‚้าอีà¸à¸„รั้ง"
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Importing"
-msgstr "นำเข้าอีà¸à¸„รั้ง"
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Import Changed Resources"
-msgstr "นำเข้ารีซอร์สที่à¹à¸à¹‰à¹„ขอีà¸à¸„รั้ง"
-
#: editor/editor_run_native.cpp
msgid "Select device from the list"
-msgstr ""
+msgstr "เลือà¸à¸­à¸¸à¸›à¸à¸£à¸“์จาà¸à¸£à¸²à¸¢à¸Šà¸·à¹ˆà¸­"
#: editor/editor_run_native.cpp
msgid ""
"No runnable export preset found for this platform.\n"
"Please add a runnable preset in the export menu."
msgstr ""
+"ไม่มีà¹à¸¡à¹ˆà¹à¸šà¸šà¸ªà¹ˆà¸‡à¸­à¸­à¸à¸—ี่สามารถรันเà¸à¸¡à¹„ด้ของà¹à¸žà¸¥à¸•à¸Ÿà¸­à¸£à¹Œà¸¡à¸™à¸µà¹‰\n"
+"à¸à¸£à¸¸à¸“าเพิ่มà¹à¸¡à¹ˆà¹à¸šà¸šà¸ªà¹ˆà¸‡à¸­à¸­à¸à¹ƒà¸™à¹€à¸¡à¸™à¸¹à¸ªà¹ˆà¸‡à¸­à¸­à¸"
#: editor/editor_run_script.cpp
msgid "Write your logic in the _run() method."
@@ -2437,11 +2329,10 @@ msgid "Invalid version.txt format inside templates."
msgstr "รูปà¹à¸šà¸šà¸‚อง version.txt ในà¹à¸¡à¹ˆà¹à¸šà¸šà¹„ม่ถูà¸à¸•à¹‰à¸­à¸‡"
#: editor/export_template_manager.cpp
-#, fuzzy
msgid ""
"Invalid version.txt format inside templates. Revision is not a valid "
"identifier."
-msgstr "รูปà¹à¸šà¸šà¸‚อง version.txt ในà¹à¸¡à¹ˆà¹à¸šà¸šà¹„ม่ถูà¸à¸•à¹‰à¸­à¸‡"
+msgstr "รูปà¹à¸šà¸šà¸‚อง version.txt ในà¹à¸¡à¹ˆà¹à¸šà¸šà¹„ม่ถูà¸à¸•à¹‰à¸­à¸‡ หมายเลขรุ่น revision ต้องใช้ระบุได้"
#: editor/export_template_manager.cpp
msgid "No version.txt found inside templates."
@@ -2460,10 +2351,6 @@ msgid "Importing:"
msgstr "นำเข้า:"
#: editor/export_template_manager.cpp
-msgid "Loading Export Templates"
-msgstr "à¸à¸³à¸¥à¸±à¸‡à¹‚หลดà¹à¸¡à¹ˆà¹à¸šà¸šà¸ªà¹ˆà¸‡à¸­à¸­à¸"
-
-#: editor/export_template_manager.cpp
msgid "Current Version:"
msgstr "รุ่นปัจจุบัน:"
@@ -2496,60 +2383,73 @@ msgid "Cannot navigate to '"
msgstr "ไม่สามารถไปยัง '"
#: editor/filesystem_dock.cpp
-#, fuzzy
+msgid "View items as a grid of thumbnails"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "View items as a list"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
msgid ""
"\n"
-"Status: Needs Re-Import"
-msgstr "บันทึà¸à¹à¸¥à¸°à¸™à¸³à¹€à¸‚้าอีà¸à¸„รั้ง"
+"Status: Import of file failed. Please fix file and reimport manually."
+msgstr ""
+"\n"
+"สถานะ: นำเข้าไฟล์ล้มเหลว à¸à¸£à¸¸à¸“าà¹à¸à¹‰à¹„ขไฟล์à¹à¸¥à¸°à¸™à¸³à¹€à¸‚้าใหม่"
#: editor/filesystem_dock.cpp
#, fuzzy
msgid ""
"\n"
"Source: "
-msgstr "ต้นฉบับ:"
+msgstr ""
+"\n"
+"ต้นฉบับ: "
#: editor/filesystem_dock.cpp
-msgid "Same source and destination files, doing nothing."
-msgstr "ไฟล์ต้นทางà¹à¸¥à¸°à¸›à¸¥à¸²à¸¢à¸—างเหมือนà¸à¸±à¸™ ไม่ทำอะไร"
+msgid "Cannot move/rename resources root."
+msgstr "ไม่สามารถย้าย/เปลี่ยนชื่อโฟลเดอร์ราà¸"
#: editor/filesystem_dock.cpp
-msgid "Target file exists, can't overwrite. Delete first."
-msgstr ""
+msgid "Cannot move a folder into itself.\n"
+msgstr "ย้ายโฟลเดอร์มาข้างในตัวมันเองไม่ได้\n"
#: editor/filesystem_dock.cpp
-msgid "Same source and destination paths, doing nothing."
-msgstr "ไฟล์ต้นทางà¹à¸¥à¸°à¸›à¸¥à¸²à¸¢à¸—างอยู่ที่เดียวà¸à¸±à¸™ ไม่ทำอะไร"
+msgid "Error moving:\n"
+msgstr "ผิดพลาดขณะย้าย:\n"
#: editor/filesystem_dock.cpp
-msgid "Can't move directories to within themselves."
-msgstr "ย้ายโฟลเดอร์เข้ามาในตัวเองไม่ได้"
+msgid "Unable to update dependencies:\n"
+msgstr "ไม่สามารถอัพเดทà¸à¸²à¸£à¸­à¹‰à¸²à¸‡à¸­à¸´à¸‡:\n"
#: editor/filesystem_dock.cpp
-msgid "Can't rename deps for:\n"
-msgstr ""
+msgid "No name provided"
+msgstr "ไม่ได้ระบุชื่อ"
#: editor/filesystem_dock.cpp
-#, fuzzy
-msgid "Error moving file:\n"
-msgstr "ผิดพลาดขณะโหลดรูป:"
+msgid "Provided name contains invalid characters"
+msgstr "ไม่สามารถใช้อัà¸à¸©à¸£à¸šà¸²à¸‡à¸•à¸±à¸§à¹ƒà¸™à¸Šà¸·à¹ˆà¸­à¹„ด้"
#: editor/filesystem_dock.cpp
-#, fuzzy
-msgid "Error moving dir:\n"
-msgstr "ผิดพลาดขณะนำเข้า:"
+msgid "No name provided."
+msgstr "ไม่ได้ระบุชื่อ"
#: editor/filesystem_dock.cpp
-msgid "Can't operate on '..'"
-msgstr "ทำงานใน '..' ไม่ได้"
+msgid "Name contains invalid characters."
+msgstr "อัà¸à¸©à¸£à¸šà¸²à¸‡à¸•à¸±à¸§à¹ƒà¸Šà¹‰à¹„ม่ได้"
#: editor/filesystem_dock.cpp
-msgid "Pick New Name and Location For:"
-msgstr "เลือà¸à¸Šà¸·à¹ˆà¸­à¹à¸¥à¸°à¸•à¸³à¹à¸«à¸™à¹ˆà¸‡à¸—ี่อยู่ใหม่ให้à¸à¸±à¸š:"
+msgid "A file or folder with this name already exists."
+msgstr "มีชื่อà¸à¸¥à¸¸à¹ˆà¸¡à¸™à¸µà¹‰à¸­à¸¢à¸¹à¹ˆà¹à¸¥à¹‰à¸§"
#: editor/filesystem_dock.cpp
-msgid "No files selected!"
-msgstr "ไม่ได้เลือà¸à¹„ฟล์ไว้!"
+msgid "Renaming file:"
+msgstr "เปลี่ยนชื่อไฟล์:"
+
+#: editor/filesystem_dock.cpp
+msgid "Renaming folder:"
+msgstr "เปลี่ยนชื่อโฟลเดอร์:"
#: editor/filesystem_dock.cpp
msgid "Expand all"
@@ -2560,40 +2460,36 @@ msgid "Collapse all"
msgstr "ยุบโฟลเดอร์"
#: editor/filesystem_dock.cpp
-msgid "Show In File Manager"
-msgstr "à¹à¸ªà¸”งในตัวจัดà¸à¸²à¸£à¹„ฟล์"
-
-#: editor/filesystem_dock.cpp
-msgid "Instance"
-msgstr "อินสà¹à¸•à¸™à¸‹à¹Œ"
+msgid "Copy Path"
+msgstr "คัดลอà¸à¸•à¸³à¹à¸«à¸™à¹ˆà¸‡"
#: editor/filesystem_dock.cpp
-msgid "Edit Dependencies.."
-msgstr "à¹à¸à¹‰à¹„ขà¸à¸²à¸£à¸­à¹‰à¸²à¸‡à¸­à¸´à¸‡.."
+msgid "Rename.."
+msgstr "เปลี่ยนชื่อ.."
#: editor/filesystem_dock.cpp
-msgid "View Owners.."
-msgstr "ดูเจ้าของ.."
+msgid "Move To.."
+msgstr "ย้ายไป.."
#: editor/filesystem_dock.cpp
-msgid "Copy Path"
-msgstr "คัดลอà¸à¸•à¸³à¹à¸«à¸™à¹ˆà¸‡"
+msgid "New Folder.."
+msgstr "สร้างโฟลเดอร์.."
#: editor/filesystem_dock.cpp
-msgid "Rename or Move.."
-msgstr "เปลี่ยนชื่อหรือย้าย.."
+msgid "Show In File Manager"
+msgstr "à¹à¸ªà¸”งในตัวจัดà¸à¸²à¸£à¹„ฟล์"
#: editor/filesystem_dock.cpp
-msgid "Move To.."
-msgstr "ย้ายไป.."
+msgid "Instance"
+msgstr "อินสà¹à¸•à¸™à¸‹à¹Œ"
#: editor/filesystem_dock.cpp
-msgid "Info"
-msgstr "ข้อมูล"
+msgid "Edit Dependencies.."
+msgstr "à¹à¸à¹‰à¹„ขà¸à¸²à¸£à¸­à¹‰à¸²à¸‡à¸­à¸´à¸‡.."
#: editor/filesystem_dock.cpp
-msgid "Re-Import.."
-msgstr "นำเข้าอีà¸à¸„รั้ง.."
+msgid "View Owners.."
+msgstr "ดูเจ้าของ.."
#: editor/filesystem_dock.cpp
msgid "Previous Directory"
@@ -2620,11 +2516,18 @@ msgid ""
"Scanning Files,\n"
"Please Wait.."
msgstr ""
+"à¸à¸³à¸¥à¸±à¸‡à¸ªà¹à¸à¸™à¹„ฟล์,\n"
+"à¸à¸£à¸¸à¸“ารอ.."
#: editor/filesystem_dock.cpp
msgid "Move"
msgstr "ย้าย"
+#: editor/filesystem_dock.cpp editor/plugins/animation_tree_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Rename"
+msgstr "เปลี่ยนชื่อ"
+
#: editor/groups_editor.cpp
msgid "Add to Group"
msgstr "เพิ่มไปยังà¸à¸¥à¸¸à¹ˆà¸¡"
@@ -2634,74 +2537,81 @@ msgid "Remove from Group"
msgstr "ลบออà¸à¸ˆà¸²à¸à¸à¸¥à¸¸à¹ˆà¸¡"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Import as Single Scene"
-msgstr "à¸à¸³à¸¥à¸±à¸‡à¸™à¸³à¹€à¸‚้าฉาà¸.."
+msgstr "นำเข้าเป็นฉาà¸à¹€à¸”ียว"
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Animations"
+msgstr "นำเข้าโดยà¹à¸¢à¸à¹à¸­à¸™à¸´à¹€à¸¡à¸Šà¸±à¸™"
#: editor/import/resource_importer_scene.cpp
msgid "Import with Separate Materials"
-msgstr ""
+msgstr "นำเข้าโดยà¹à¸¢à¸à¸§à¸±à¸ªà¸”ุ"
#: editor/import/resource_importer_scene.cpp
msgid "Import with Separate Objects"
-msgstr ""
+msgstr "นำเข้าโดยà¹à¸¢à¸à¸§à¸±à¸•à¸–ุ"
#: editor/import/resource_importer_scene.cpp
msgid "Import with Separate Objects+Materials"
-msgstr ""
+msgstr "นำเข้าโดยà¹à¸¢à¸à¸—ั้งวัตถุà¹à¸¥à¸°à¸§à¸±à¸ªà¸”ุ"
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Animations"
+msgstr "นำเข้าโดยà¹à¸¢à¸à¸§à¸±à¸•à¸–ุà¹à¸¥à¸°à¹à¸­à¸™à¸´à¹€à¸¡à¸Šà¸±à¸™"
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Materials+Animations"
+msgstr "นำเข้าโดยà¹à¸¢à¸à¸§à¸±à¸ªà¸”ุà¹à¸¥à¸°à¹à¸­à¸™à¸´à¹€à¸¡à¸Šà¸±à¸™"
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Materials+Animations"
+msgstr "นำเข้าโดยà¹à¸¢à¸à¸—ั้งวัตถุ วัสดุ à¹à¸¥à¸°à¹à¸­à¸™à¸´à¹€à¸¡à¸Šà¸±à¸™"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Import as Multiple Scenes"
-msgstr "นำเข้าฉาภ3D"
+msgstr "นำเข้าเป็นหลายฉาà¸"
#: editor/import/resource_importer_scene.cpp
msgid "Import as Multiple Scenes+Materials"
-msgstr ""
+msgstr "นำเข้าเป็นหลายฉาà¸à¹à¸¥à¸°à¸§à¸±à¸ªà¸”ุ"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Import Scene"
msgstr "นำเข้าฉาà¸"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Importing Scene.."
msgstr "à¸à¸³à¸¥à¸±à¸‡à¸™à¸³à¹€à¸‚้าฉาà¸.."
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Running Custom Script.."
msgstr "à¸à¸³à¸¥à¸±à¸‡à¸£à¸±à¸™à¸ªà¸„ริปต์.."
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Couldn't load post-import script:"
msgstr "โหลดสคริปต์หลังนำเข้าไม่ได้:"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Invalid/broken script for post-import (check console):"
msgstr "สคริปต์หลังนำเข้าผิดพลาด (ตรวจสอบคอนโซล):"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Error running post-import script:"
msgstr "ผิดพลาดขณะรันสคริปต์หลังนำเข้า:"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Saving.."
msgstr "à¸à¸³à¸¥à¸±à¸‡à¸šà¸±à¸™à¸—ึà¸.."
#: editor/import_dock.cpp
msgid "Set as Default for '%s'"
-msgstr ""
+msgstr "à¸à¸³à¸«à¸™à¸”เป็นค่าเริ่มต้นของ '%s'"
#: editor/import_dock.cpp
msgid "Clear Default for '%s'"
-msgstr ""
+msgstr "ลบค่าเริ่มต้นของ '%s'"
#: editor/import_dock.cpp
msgid " Files"
@@ -2719,572 +2629,6 @@ msgstr "à¹à¸šà¸š.."
msgid "Reimport"
msgstr "นำเข้าใหม่"
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "No bit masks to import!"
-msgstr "ไม่มีบิตà¹à¸¡à¸ªà¸à¹Œà¹ƒà¸«à¹‰à¸™à¸³à¹€à¸‚้า!"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path is empty."
-msgstr "ตำà¹à¸«à¸™à¹ˆà¸‡à¸—ี่อยู่ว่างเปล่า"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must be a complete resource path."
-msgstr "ต้องเป็นตำà¹à¸«à¸™à¹ˆà¸‡à¸—ี่อยู่à¹à¸šà¸šà¹€à¸•à¹‡à¸¡"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must exist."
-msgstr "ต้องมีตำà¹à¸«à¸™à¹ˆà¸‡à¸—ี่อยู่"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Save path is empty!"
-msgstr "ตำà¹à¸«à¸™à¹ˆà¸‡à¸šà¸±à¸™à¸—ึà¸à¸§à¹ˆà¸²à¸‡à¹€à¸›à¸¥à¹ˆà¸²!"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Import BitMasks"
-msgstr "นำเข้า BitMasks"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s):"
-msgstr "Texture ต้นฉบับ:"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Target Path:"
-msgstr "ตำà¹à¸«à¸™à¹ˆà¸‡à¸—ี่อยู่:"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Accept"
-msgstr "ยอมรับ"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Bit Mask"
-msgstr "บิตà¹à¸¡à¸ªà¸à¹Œ"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No source font file!"
-msgstr "ไม่ได้เลือà¸à¹„ฟล์ฟอนต์ต้นฉบับ!"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No target font resource!"
-msgstr "ไม่ได้เลือà¸à¸§à¹ˆà¸²à¸ˆà¸°à¸™à¸³à¹€à¸‚้ามาเป็นไฟล์ฟอนต์ชื่ออะไร!"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"Invalid file extension.\n"
-"Please use .font."
-msgstr ""
-"นามสà¸à¸¸à¸¥à¹„ม่ถูà¸à¸•à¹‰à¸­à¸‡\n"
-"à¸à¸£à¸¸à¸“าใช้ .font"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Can't load/process source font."
-msgstr "ไม่สามารถโหลด/ประมวลผลฟอนต์ต้นฉบับ"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Couldn't save font."
-msgstr "บันทึà¸à¸Ÿà¸­à¸™à¸•à¹Œà¹„ม่ได้"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font:"
-msgstr "ฟอนต์ต้นฉบับ:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font Size:"
-msgstr "ขนาดฟอนต์ต้นฉบับ:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Dest Resource:"
-msgstr "นำเข้ามาเป็นรีซอร์ส:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "The quick brown fox jumps over the lazy dog."
-msgstr "The quick brown fox jumps over the lazy dog."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Test:"
-msgstr "ทดสอบ:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Options:"
-msgstr "ตัวเลือà¸:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Font Import"
-msgstr "นำเข้าฟอนต์"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"This file is already a Godot font file, please supply a BMFont type file "
-"instead."
-msgstr "ไฟล์นี้เป็นฟอนต์ของ Godot อยู่à¹à¸¥à¹‰à¸§ à¸à¸£à¸¸à¸“าเลือà¸à¸Ÿà¸­à¸™à¸•à¹Œà¸—ี่มาจาภBMFont"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Failed opening as BMFont file."
-msgstr "ผิดพลาดขณะเปิดไฟล์เป็น BMFont"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error initializing FreeType."
-msgstr "ผิดพลาดขณะเริ่มต้น FreeType"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Unknown font format."
-msgstr "ไม่ทราบประเภทของฟอนต์"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error loading font."
-msgstr "ผิดพลาดขณะโหลดฟอนต์"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Invalid font size."
-msgstr "ขนาดฟอนต์ผิดพลาด"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#, fuzzy
-msgid "Invalid font custom source."
-msgstr "ต้นฉบับฟอนต์ที่à¸à¸³à¸«à¸™à¸”เองไม่ถูà¸à¸•à¹‰à¸­à¸‡"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/plugins/theme_editor_plugin.cpp
-msgid "Font"
-msgstr "ฟอนต์"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "No meshes to import!"
-msgstr "ไม่มี mesh ให้นำเข้า!"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Single Mesh Import"
-msgstr "นำเข้า Mesh เดี่ยว"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Source Mesh(es):"
-msgstr "Mesh ต้นฉบับ:"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/plugins/mesh_instance_editor_plugin.cpp
-msgid "Mesh"
-msgstr "Mesh"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Surface %d"
-msgstr "%d พื้นผิว"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "No samples to import!"
-msgstr "ไม่มีไฟล์เสียงให้นำเข้า!"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Import Audio Samples"
-msgstr "นำเข้าไฟล์เสียง"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Source Sample(s):"
-msgstr "ไฟล์เสียงต้นฉบับ:"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Audio Sample"
-msgstr "ไฟล์เสียง"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "New Clip"
-msgstr "คลิปใหม่"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Animation Options"
-msgstr "ตัวเลือà¸à¹à¸­à¸™à¸´à¹€à¸¡à¸Šà¸±à¸™"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Flags"
-msgstr "ตัวเลือà¸"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Bake FPS:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Optimizer"
-msgstr "ตัวเพิ่มประสิทธิภาพ"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Linear Error"
-msgstr "ผิดพลาดเชิงเส้นมาà¸à¸—ี่สุด"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angular Error"
-msgstr "ผิดพลาดเชิงมุมมาà¸à¸—ี่สุด"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angle"
-msgstr "มุมมาà¸à¸ªà¸¸à¸”"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Clips"
-msgstr "คลิป"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Start(s)"
-msgstr "เริ่ม"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "End(s)"
-msgstr "จบ"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Loop"
-msgstr "วน"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Filters"
-msgstr "ตัวà¸à¸£à¸­à¸‡"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source path is empty."
-msgstr "ที่อยู่ไฟล์ต้นฉบับว่างเปล่า"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't load post-import script."
-msgstr "โหลดสคริปต์หลังนำเข้าไม่ได้"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Invalid/broken script for post-import."
-msgstr "สคริปต์หลังนำเข้ามีข้อผิดพลาด"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Error importing scene."
-msgstr "ผิดพลาดขณะนำเข้าฉาà¸"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import 3D Scene"
-msgstr "นำเข้าฉาภ3D"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source Scene:"
-msgstr "ฉาà¸à¸•à¹‰à¸™à¸‰à¸šà¸±à¸š:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Same as Target Scene"
-msgstr "เหมือนà¸à¸±à¸™à¸à¸±à¸šà¸‰à¸²à¸à¸›à¸¥à¸²à¸¢à¸—าง"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Shared"
-msgstr "ใช้ร่วมà¸à¸±à¸™"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Target Texture Folder:"
-msgstr "โฟลเดอร์ Texture ปลายทาง:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Post-Process Script:"
-msgstr "สคริปต์หลังประมวลผล:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Custom Root Node Type:"
-msgstr "ประเภทโหนดราà¸à¸à¸³à¸«à¸™à¸”เอง:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Auto"
-msgstr "อัตโนมัติ"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Root Node Name:"
-msgstr "ชื่อโหนดราà¸:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "The Following Files are Missing:"
-msgstr "ไฟล์ต่อไปนี้หายไป:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Anyway"
-msgstr "ยืนยันนำเข้า"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp scene/gui/dialogs.cpp
-msgid "Cancel"
-msgstr "ยà¸à¹€à¸¥à¸´à¸"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import & Open"
-msgstr "นำเข้าà¹à¸¥à¸°à¹€à¸›à¸´à¸”"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Edited scene has not been saved, open imported scene anyway?"
-msgstr "ฉาà¸à¸›à¸±à¸ˆà¸ˆà¸¸à¸šà¸±à¸™à¸¢à¸±à¸‡à¹„ม่ได้บันทึภยืนยันเปิดไฟล์ฉาà¸à¸—ี่นำเข้า?"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Image:"
-msgstr "นำเข้าไฟล์รูป:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Can't import a file over itself:"
-msgstr "นำเข้าไฟล์ทับตัวเองไม่ได้:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't localize path: %s (already local)"
-msgstr "ทำที่อยู่ไฟล์ให้เป็นภายในไม่ได้: %s (เป็นภายในอยู่à¹à¸¥à¹‰à¸§)"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "3D Scene Animation"
-msgstr "à¹à¸­à¸™à¸´à¹€à¸¡à¸Šà¸±à¸™à¸‰à¸²à¸ 3D"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Uncompressed"
-msgstr "ไม่บีบอัด"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossless (PNG)"
-msgstr "บีบอัดà¹à¸šà¸šà¹„ม่เสียคุณภาพ (PNG)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossy (WebP)"
-msgstr "บีบอัดà¹à¸šà¸šà¹€à¸ªà¸µà¸¢à¸„ุณภาพ (WebP)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress (VRAM)"
-msgstr "บีบอัด (VRAM)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Format"
-msgstr "รูปà¹à¸šà¸š Texture"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Compression Quality (WebP):"
-msgstr "คุณภาพà¸à¸²à¸£à¸šà¸µà¸šà¸­à¸±à¸” Texture (WebP):"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Options"
-msgstr "ตัวเลือภTexture"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Please specify some files!"
-msgstr "à¸à¸£à¸¸à¸“าเลือà¸à¸ªà¸±à¸à¹„ฟล์!"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "At least one file needed for Atlas."
-msgstr "Atlas ต้องà¸à¸²à¸£à¹„ฟล์อย่างน้อย 1 ไฟล์"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Error importing:"
-msgstr "ผิดพลาดขณะนำเข้า:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Only one file is required for large texture."
-msgstr "Texture ขนาดใหà¸à¹ˆà¸•à¹‰à¸­à¸‡à¸à¸²à¸£à¹à¸„่ไฟล์เดียว"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Max Texture Size:"
-msgstr "ขนาด Texture ที่ใหà¸à¹ˆà¸—ี่สุด:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for Atlas (2D)"
-msgstr "นำเข้า Texture สำหรับ Atlas (2D)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cell Size:"
-msgstr "ขนาดเซลล์:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Large Texture"
-msgstr "Texture ขนาดใหà¸à¹ˆ"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Textures (2D)"
-msgstr "นำเข้า Texture ขนาดใหà¸à¹ˆ (2D)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture"
-msgstr "Texture ต้นฉบับ"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Base Atlas Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s)"
-msgstr "Texture ต้นฉบับ"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 2D"
-msgstr "นำเข้า Texture สำหรับ 2D"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 3D"
-msgstr "นำเข้า Texture สำหรับ 3D"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures"
-msgstr "นำเข้า Texture"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "2D Texture"
-msgstr "Texture 2D"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "3D Texture"
-msgstr "Texture 3D"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Atlas Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid ""
-"NOTICE: Importing 2D textures is not mandatory. Just copy png/jpg files to "
-"the project."
-msgstr "โปรดทราบ: ไม่จำเป็นต้องนำเข้า Texture 2D à¹à¸„่คัดลอà¸à¹„ฟล์ png/jpg เข้าสู่โปรเจà¸à¸•à¹Œ"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Crop empty space."
-msgstr "ครอบตัดพื้นที่ว่าง"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture"
-msgstr "Texture"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Texture"
-msgstr "นำเข้า Texture ขนาดใหà¸à¹ˆ"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Load Source Image"
-msgstr "โหลดรูปต้นฉบับ"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Slicing"
-msgstr "ตัด"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Inserting"
-msgstr "à¹à¸—รà¸"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Saving"
-msgstr "บันทึà¸"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save large texture:"
-msgstr "บันทึภTexture ขนาดใหà¸à¹ˆà¹„ม่ได้:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Build Atlas For:"
-msgstr "สร้าง Atlas สำหรับ:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Loading Image:"
-msgstr "โหลดรูป:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't load image:"
-msgstr "โหลดรูปไม่ได้:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Converting Images"
-msgstr "à¸à¸³à¸¥à¸±à¸‡à¹à¸›à¸¥à¸‡à¸£à¸¹à¸›"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cropping Images"
-msgstr "ครอบตัดรูป"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Blitting Images"
-msgstr "คัดลอà¸à¸£à¸¹à¸›"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save atlas image:"
-msgstr "บันทึภAtlas ไม่ได้:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save converted texture:"
-msgstr "บันทึภTexture ที่à¹à¸›à¸¥à¸‡à¹à¸¥à¹‰à¸§à¹„ม่ได้:"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid source!"
-msgstr "ต้นฉบับไม่ถูà¸à¸•à¹‰à¸­à¸‡!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid translation source!"
-msgstr "ต้นฉบับà¸à¸²à¸£à¹à¸›à¸¥à¹„ม่ถูà¸à¸•à¹‰à¸­à¸‡!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Column"
-msgstr "คอลัมน์"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/script_create_dialog.cpp
-msgid "Language"
-msgstr "ภาษา"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No items to import!"
-msgstr "ไม่มีอะไรให้นำเข้า!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No target path!"
-msgstr "ไม่มีที่อยู่ปลายทาง!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translations"
-msgstr "นำเข้าà¸à¸²à¸£à¹à¸›à¸¥"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Couldn't import!"
-msgstr "นำเข้าไม่ได้!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translation"
-msgstr "นำเข้าà¸à¸²à¸£à¹à¸›à¸¥"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Source CSV:"
-msgstr "CSV ต้นฉบับ:"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Ignore First Row"
-msgstr "ไม่สนใจà¹à¸–วà¹à¸£à¸"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Compress"
-msgstr "บีบอัด"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Add to Project (project.godot)"
-msgstr "เพิ่มเข้าโปรเจà¸à¸•à¹Œ (project.godot)"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Languages:"
-msgstr "นำเข้าภาษา:"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Translation"
-msgstr "à¸à¸²à¸£à¹à¸›à¸¥"
-
#: editor/multi_node_edit.cpp
msgid "MultiNode Set"
msgstr "à¸à¸³à¸«à¸™à¸” MultiNode"
@@ -3297,6 +2641,48 @@ msgstr "à¸à¸¥à¸¸à¹ˆà¸¡"
msgid "Select a Node to edit Signals and Groups."
msgstr "เลือà¸à¹‚หนดเพื่อà¹à¸à¹‰à¹„ขสัà¸à¸à¸²à¸“à¹à¸¥à¸°à¸à¸¥à¸¸à¹ˆà¸¡"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create Poly"
+msgstr "สร้างรูปหลายเหลี่ยม"
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly"
+msgstr "à¹à¸à¹‰à¹„ขรูปหลายเหลี่ยม"
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Insert Point"
+msgstr "à¹à¸—รà¸à¸ˆà¸¸à¸”"
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly (Remove Point)"
+msgstr "à¹à¸à¹‰à¹„ขรูปหลายเหลี่ยม (ลบจุด)"
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Remove Poly And Point"
+msgstr "ลบรูปหลายเหลี่ยมà¹à¸¥à¸°à¸ˆà¸¸à¸”"
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create a new polygon from scratch."
+msgstr "สร้างรูปหลายเหลี่ยมจาà¸à¸„วามว่างเปล่า"
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid ""
+"Edit existing polygon:\n"
+"LMB: Move Point.\n"
+"Ctrl+LMB: Split Segment.\n"
+"RMB: Erase Point."
+msgstr ""
+"à¹à¸à¹‰à¹„ขรูปหลายเหลี่ยม:\n"
+"เมาส์ซ้าย: ย้ายจุด\n"
+"Ctrl+เมาส์ซ้าย: à¹à¸¢à¸à¸ªà¹ˆà¸§à¸™\n"
+"เมาส์ขวา: ลบจุด"
+
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Toggle Autoplay"
msgstr "เปิดปิดà¸à¸²à¸£à¹€à¸¥à¹ˆà¸™à¸­à¸±à¸•à¹‚นมัติ"
@@ -3450,7 +2836,6 @@ msgstr "ชื่อà¹à¸­à¸™à¸´à¹€à¸¡à¸Šà¸±à¸™:"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
#: editor/script_create_dialog.cpp
msgid "Error!"
@@ -3478,9 +2863,8 @@ msgid "New name:"
msgstr "ชื่อใหม่:"
#: editor/plugins/animation_tree_editor_plugin.cpp
-#, fuzzy
msgid "Edit Filters"
-msgstr "à¹à¸à¹‰à¹„ขตัวà¸à¸£à¸­à¸‡à¹‚หนด"
+msgstr "à¹à¸à¹‰à¹„ขตัวà¸à¸£à¸­à¸‡"
#: editor/plugins/animation_tree_editor_plugin.cpp
#: editor/plugins/multimesh_editor_plugin.cpp
@@ -3562,10 +2946,6 @@ msgid "Delete Input"
msgstr "ลบอินพุต"
#: editor/plugins/animation_tree_editor_plugin.cpp
-msgid "Rename"
-msgstr "เปลี่ยนชื่อ"
-
-#: editor/plugins/animation_tree_editor_plugin.cpp
msgid "Animation tree is valid."
msgstr "ผังà¹à¸­à¸™à¸´à¹€à¸¡à¸Šà¸±à¸™à¸–ูà¸à¸•à¹‰à¸­à¸‡"
@@ -3621,64 +3001,181 @@ msgstr "à¹à¸à¹‰à¹„ขตัวà¸à¸£à¸­à¸‡à¹‚หนด"
msgid "Filters.."
msgstr "ตัวà¸à¸£à¸­à¸‡.."
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing %d Triangles:"
-msgstr "วิเคราะห์สามเหลี่ยม %d อัน:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Free"
+msgstr "ฟรี"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Contents:"
+msgstr "ประà¸à¸­à¸šà¸”้วย:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "View Files"
+msgstr "ดูไฟล์"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve hostname:"
+msgstr "ไม่พบตำà¹à¸«à¸™à¹ˆà¸‡à¸™à¸µà¹‰:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve."
+msgstr "ค้นหาไม่สำเร็จ"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connection error, please try again."
+msgstr "เชื่อมต่อไม่ได้ à¸à¸£à¸¸à¸“าลองใหม่"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Triangle #"
-msgstr "สามเหลี่ยม #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't connect."
+msgstr "เชื่อมต่อไม่ได้"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Light Baker Setup:"
-msgstr "ตั้งค่า Light Baker:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't connect to host:"
+msgstr "ไม่สามารถเชื่อมต่อà¸à¸±à¸šà¹‚ฮสต์:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing Geometry"
-msgstr "วิเคราะห์ Geometry"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response from host:"
+msgstr "ไม่มีà¸à¸²à¸£à¸•à¸­à¸šà¸à¸¥à¸±à¸šà¸ˆà¸²à¸à¹‚ฮสต์:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Fixing Lights"
-msgstr "ซ่อมà¹à¸‹à¸¡à¹à¸ªà¸‡"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response."
+msgstr "ไม่มีà¸à¸²à¸£à¸•à¸­à¸šà¸à¸¥à¸±à¸š"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Making BVH"
-msgstr "à¸à¸³à¸¥à¸±à¸‡à¸ªà¸£à¹‰à¸²à¸‡ BVH"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, return code:"
+msgstr "à¸à¸²à¸£à¸£à¹‰à¸­à¸‡à¸‚อผิดพลาด รหัส:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Light Octree"
-msgstr "à¸à¸³à¸¥à¸±à¸‡à¸ªà¸£à¹‰à¸²à¸‡ Light Octree"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Req. Failed."
+msgstr "ร้องขอผิดพลาด"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Octree Texture"
-msgstr "สร้าง Texture Octree"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, too many redirects"
+msgstr "à¸à¸²à¸£à¸£à¹‰à¸­à¸‡à¸‚อผิดพลาด เปลี่ยนทางมาà¸à¹€à¸à¸´à¸™à¹„ป"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Transfer to Lightmaps:"
-msgstr "ส่งผ่านไปยัง Lightmaps:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Redirect Loop."
+msgstr "เปลี่ยนทางมาà¸à¹€à¸à¸´à¸™à¹„ป"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Allocating Texture #"
-msgstr "จัดสรร Texture #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed:"
+msgstr "ผิดพลาด:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Baking Triangle #"
-msgstr "à¸à¸³à¸¥à¸±à¸‡ Bake สามเหลี่ยม #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Bad download hash, assuming file has been tampered with."
+msgstr "à¹à¸®à¸Šà¸œà¸´à¸”พลาด ไฟล์ดาวน์โหลดอาจเสียหาย"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Post-Processing Texture #"
-msgstr "ประมวลผล Texture #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Expected:"
+msgstr "ที่ควรจะเป็น:"
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Bake!"
-msgstr ""
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Got:"
+msgstr "ที่ได้รับ:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed sha256 hash check"
+msgstr "ผิดพลาดในà¸à¸²à¸£à¸•à¸£à¸§à¸ˆà¸ªà¸­à¸šà¹à¸®à¸Š SHA256"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Asset Download Error:"
+msgstr "à¸à¸²à¸£à¸”าวน์โหลดผิดพลาด:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Fetching:"
+msgstr "à¸à¸³à¸¥à¸±à¸‡à¸£à¸±à¸šà¸‚้อมูล:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Resolving.."
+msgstr "à¸à¸³à¸¥à¸±à¸‡à¸„้นหา.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connecting.."
+msgstr "à¸à¸³à¸¥à¸±à¸‡à¹€à¸Šà¸·à¹ˆà¸­à¸¡à¸•à¹ˆà¸­.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Requesting.."
+msgstr "à¸à¸³à¸¥à¸±à¸‡à¸£à¹‰à¸­à¸‡à¸‚อ.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Error making request"
+msgstr "à¸à¸²à¸£à¸£à¹‰à¸­à¸‡à¸‚อผิดพลาด"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Idle"
+msgstr "พร้อมใช้งาน"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Retry"
+msgstr "ลองใหม่"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download Error"
+msgstr "ดาวน์โหลดผิดพลาด"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download for this asset is already in progress!"
+msgstr "à¸à¸³à¸¥à¸±à¸‡à¸”าวน์โหลดไฟล์นี้อยู่à¹à¸¥à¹‰à¸§!"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "first"
+msgstr "à¹à¸£à¸à¸ªà¸¸à¸”"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "prev"
+msgstr "à¸à¹ˆà¸­à¸™à¸«à¸™à¹‰à¸²"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "next"
+msgstr "ถัดไป"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "last"
+msgstr "ท้ายสุด"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "All"
+msgstr "ทั้งหมด"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Plugins"
+msgstr "ปลั๊à¸à¸­à¸´à¸™"
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Reset the lightmap octree baking process (start over)."
-msgstr "รีเซ็ตขั้นตอนà¸à¸²à¸£ bake lightmap octree (เริ่มใหม่)"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Sort:"
+msgstr "เรียงตาม:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Reverse"
+msgstr "ย้อนà¸à¸¥à¸±à¸š"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Category:"
+msgstr "หมวดหมู่:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Site:"
+msgstr "ไซต์:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Support.."
+msgstr "à¸à¸²à¸£à¸ªà¸™à¸±à¸šà¸ªà¸™à¸¸à¸™.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Official"
+msgstr "ผู้พัฒนา"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Testing"
+msgstr "ทดสอบ"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Assets ZIP File"
+msgstr "ไฟล์ ZIP"
#: editor/plugins/camera_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
msgid "Preview"
msgstr "ตัวอย่าง"
@@ -3721,12 +3218,17 @@ msgid "Edit CanvasItem"
msgstr "à¹à¸à¹‰à¹„ข CanvasItem"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Change Anchors"
-msgstr "à¹à¸à¹‰à¹„ขà¸à¸²à¸£à¸•à¸£à¸¶à¸‡"
+#, fuzzy
+msgid "Anchors only"
+msgstr "ตรึง"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom (%):"
-msgstr "ซูม (%):"
+msgid "Change Anchors and Margins"
+msgstr "à¹à¸à¹‰à¹„ขà¸à¸²à¸£à¸•à¸£à¸¶à¸‡à¹à¸¥à¸°à¸‚อบ"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Change Anchors"
+msgstr "à¹à¸à¹‰à¹„ขà¸à¸²à¸£à¸•à¸£à¸¶à¸‡"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Paste Pose"
@@ -3778,60 +3280,78 @@ msgid "Pan Mode"
msgstr "โหมดมุมมอง"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Lock the selected object in place (can't be moved)."
-msgstr "ล็อคไม่ให้วัตถุที่เลือà¸à¸¢à¹‰à¸²à¸¢à¸•à¸³à¹à¸«à¸™à¹ˆà¸‡"
+#, fuzzy
+msgid "Toggles snapping"
+msgstr "เปิด/ปิด จุดพัà¸à¹‚ปรà¹à¸à¸£à¸¡"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Unlock the selected object (can be moved)."
-msgstr "ปลดล็อควัตถุที่เลือà¸"
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Use Snap"
+msgstr "จำà¸à¸±à¸”à¸à¸²à¸£à¹€à¸„ลื่อนย้าย"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Makes sure the object's children are not selectable."
-msgstr "ทำให้เลือà¸à¹‚หนดลูà¸à¹„ม่ได้"
+#, fuzzy
+msgid "Snapping options"
+msgstr "ตัวเลือà¸à¹à¸­à¸™à¸´à¹€à¸¡à¸Šà¸±à¸™"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Restores the object's children's ability to be selected."
-msgstr "ทำให้เลือà¸à¹‚หนดลูà¸à¹„ด้เหมือนเดิม"
+#, fuzzy
+msgid "Snap to grid"
+msgstr "โหมดà¸à¸²à¸£à¸ˆà¸³à¸à¸±à¸”:"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Edit"
-msgstr "à¹à¸à¹‰à¹„ข"
+msgid "Use Rotation Snap"
+msgstr "จำà¸à¸±à¸”à¸à¸²à¸£à¸«à¸¡à¸¸à¸™"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Use Snap"
-msgstr "จำà¸à¸±à¸”à¸à¸²à¸£à¹€à¸„ลื่อนย้าย"
+#, fuzzy
+msgid "Configure Snap..."
+msgstr "ตั้งค่าà¸à¸²à¸£à¸ˆà¸³à¸à¸±à¸”.."
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Show Grid"
-msgstr "à¹à¸ªà¸”งเส้นตาราง"
+msgid "Snap Relative"
+msgstr "จำà¸à¸±à¸”โดยใช้ตำà¹à¸«à¸™à¹ˆà¸‡à¸›à¸±à¸ˆà¸ˆà¸¸à¸šà¸±à¸™"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Rotation Snap"
-msgstr "จำà¸à¸±à¸”à¸à¸²à¸£à¸«à¸¡à¸¸à¸™"
+msgid "Use Pixel Snap"
+msgstr "จำà¸à¸±à¸”ให้ย้ายเป็นพิà¸à¹€à¸‹à¸¥"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap Relative"
-msgstr "จำà¸à¸±à¸”โดยใช้ตำà¹à¸«à¸™à¹ˆà¸‡à¸›à¸±à¸ˆà¸ˆà¸¸à¸šà¸±à¸™"
+msgid "Smart snapping"
+msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Configure Snap.."
-msgstr "ตั้งค่าà¸à¸²à¸£à¸ˆà¸³à¸à¸±à¸”.."
+#, fuzzy
+msgid "Snap to parent"
+msgstr "ขยายให้เต็มโหนดà¹à¸¡à¹ˆ"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Pixel Snap"
-msgstr "จำà¸à¸±à¸”ให้ย้ายเป็นพิà¸à¹€à¸‹à¸¥"
+msgid "Snap to node anchor"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to node sides"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to other nodes"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Lock the selected object in place (can't be moved)."
+msgstr "ล็อคไม่ให้วัตถุที่เลือà¸à¸¢à¹‰à¸²à¸¢à¸•à¸³à¹à¸«à¸™à¹ˆà¸‡"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Skeleton.."
-msgstr "โครงà¸à¸£à¸°à¸”ูà¸.."
+msgid "Unlock the selected object (can be moved)."
+msgstr "ปลดล็อควัตถุที่เลือà¸"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Makes sure the object's children are not selectable."
+msgstr "ทำให้เลือà¸à¹‚หนดลูà¸à¹„ม่ได้"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Restores the object's children's ability to be selected."
+msgstr "ทำให้เลือà¸à¹‚หนดลูà¸à¹„ด้เหมือนเดิม"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Make Bones"
@@ -3859,12 +3379,17 @@ msgid "View"
msgstr "มุมมอง"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Reset"
-msgstr "รีเซ็ตà¸à¸²à¸£à¸‹à¸¹à¸¡"
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Show Grid"
+msgstr "à¹à¸ªà¸”งเส้นตาราง"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Show helpers"
+msgstr "à¹à¸ªà¸”งตัวช่วย"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Set.."
-msgstr "ตั้งค่าà¸à¸²à¸£à¸‹à¸¹à¸¡.."
+msgid "Show rulers"
+msgstr "à¹à¸ªà¸”งไม้บรรทัด"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Center Selection"
@@ -3875,8 +3400,8 @@ msgid "Frame Selection"
msgstr "ให้สิ่งที่เลือà¸à¹€à¸•à¹‡à¸¡à¸ˆà¸­"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Anchor"
-msgstr "ตรึง"
+msgid "Layout"
+msgstr "เลย์เอาต์"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Insert Keys"
@@ -3899,12 +3424,20 @@ msgid "Clear Pose"
msgstr "ลบท่าทาง"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Set a Value"
-msgstr "เซ็ตค่า"
+msgid "Drag pivot from mouse position"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Set pivot at mouse position"
+msgstr "à¸à¸³à¸«à¸™à¸”จุดหมุนที่ตำà¹à¸«à¸™à¹ˆà¸‡à¹€à¸¡à¸²à¸ªà¹Œ"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Multiply grid step by 2"
+msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap (Pixels):"
-msgstr "Snap (พิà¸à¹€à¸‹à¸¥):"
+msgid "Divide grid step by 2"
+msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Add %s"
@@ -3914,23 +3447,28 @@ msgstr "เพิ่ม %s"
msgid "Adding %s..."
msgstr "à¸à¸³à¸¥à¸±à¸‡à¹€à¸žà¸´à¹ˆà¸¡ %s..."
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Create Node"
msgstr "สร้างโหนด"
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Error instancing scene from %s"
msgstr "ผิดพลาดขณะอินสà¹à¸•à¸™à¸‹à¹Œà¸‰à¸²à¸à¸ˆà¸²à¸ %s"
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "OK :("
msgstr "ตà¸à¸¥à¸‡ :("
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "No parent to instance a child at."
msgstr "ไม่พบโหนดà¹à¸¡à¹ˆà¸—ี่จะรับอินสà¹à¸•à¸™à¸‹à¹Œà¹‚หนดลูà¸"
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "This operation requires a single selected node."
msgstr "ต้องเลือà¸à¹€à¸žà¸µà¸¢à¸‡à¹‚หนดเดียว"
@@ -3946,45 +3484,6 @@ msgstr ""
"ลาภ& วาง + Shift: เพิ่มเป็นโหนดà¸à¸²à¸•à¸´\n"
"ลาภ& วาง + Alt: เปลี่ยนประเภทโหนด"
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Create Poly"
-msgstr "สร้างรูปหลายเหลี่ยม"
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly"
-msgstr "à¹à¸à¹‰à¹„ขรูปหลายเหลี่ยม"
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly (Remove Point)"
-msgstr "à¹à¸à¹‰à¹„ขรูปหลายเหลี่ยม (ลบจุด)"
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Create a new polygon from scratch."
-msgstr "สร้างรูปหลายเหลี่ยมจาà¸à¸„วามว่างเปล่า"
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-msgid ""
-"Edit existing polygon:\n"
-"LMB: Move Point.\n"
-"Ctrl+LMB: Split Segment.\n"
-"RMB: Erase Point."
-msgstr ""
-
#: editor/plugins/collision_polygon_editor_plugin.cpp
msgid "Create Poly3D"
msgstr "à¹à¸à¹‰à¹„ขรูปหลายเหลี่ยม 3D"
@@ -3994,14 +3493,6 @@ msgid "Set Handle"
msgstr "ปรับขนาดรูปร่าง"
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Creating Mesh Library"
-msgstr "à¸à¸³à¸¥à¸±à¸‡à¸ªà¸£à¹‰à¸²à¸‡ Mesh Library"
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Thumbnail.."
-msgstr "รูปตัวอย่าง.."
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Remove item %d?"
msgstr "ลบไอเทม %d?"
@@ -4024,19 +3515,36 @@ msgid "Update from Scene"
msgstr "อัพเดตจาà¸à¸‰à¸²à¸"
#: editor/plugins/curve_editor_plugin.cpp
-#, fuzzy
+msgid "Flat0"
+msgstr "เรียบ 0"
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat1"
+msgstr "เรียบ 1"
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Ease in"
+msgstr "เข้านุ่มนวล"
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Ease out"
+msgstr "ออà¸à¸™à¸¸à¹ˆà¸¡à¸™à¸§à¸¥"
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Smoothstep"
+msgstr "นุ่มนวล"
+
+#: editor/plugins/curve_editor_plugin.cpp
msgid "Modify Curve Point"
-msgstr "à¹à¸à¹‰à¹„ขเส้นโค้ง"
+msgstr "à¹à¸à¹‰à¹„ขจุดบนเส้นโค้ง"
#: editor/plugins/curve_editor_plugin.cpp
-#, fuzzy
msgid "Modify Curve Tangent"
-msgstr "à¹à¸à¹‰à¹„ขเส้นโค้ง"
+msgstr "à¹à¸à¹‰à¹„ขเส้นสัมผัสเส้นโค้ง"
#: editor/plugins/curve_editor_plugin.cpp
-#, fuzzy
msgid "Load Curve Preset"
-msgstr "โหลดค่าล่วงหน้า"
+msgstr "โหลดเส้นโค้งตัวอย่าง"
#: editor/plugins/curve_editor_plugin.cpp
msgid "Add point"
@@ -4047,23 +3555,20 @@ msgid "Remove point"
msgstr "ลบจุด"
#: editor/plugins/curve_editor_plugin.cpp
-#, fuzzy
msgid "Left linear"
-msgstr "เส้นตรง"
+msgstr "เส้นตรงซ้าย"
#: editor/plugins/curve_editor_plugin.cpp
-#, fuzzy
msgid "Right linear"
-msgstr "มุมขวา"
+msgstr "เส้นตรงขวา"
#: editor/plugins/curve_editor_plugin.cpp
msgid "Load preset"
msgstr "โหลดค่าล่วงหน้า"
#: editor/plugins/curve_editor_plugin.cpp
-#, fuzzy
msgid "Remove Curve Point"
-msgstr "ลบจุด"
+msgstr "ลบจุดบนเส้นโค้ง"
#: editor/plugins/curve_editor_plugin.cpp
msgid "Toggle Curve Linear Tangent"
@@ -4071,7 +3576,7 @@ msgstr ""
#: editor/plugins/curve_editor_plugin.cpp
msgid "Hold Shift to edit tangents individually"
-msgstr ""
+msgstr "à¸à¸” Shift ค้างเพื่อปรับเส้นสัมผัสà¹à¸¢à¸à¸à¸±à¸™"
#: editor/plugins/gradient_editor_plugin.cpp
msgid "Add/Remove Color Ramp Point"
@@ -4099,28 +3604,26 @@ msgid ""
"No OccluderPolygon2D resource on this node.\n"
"Create and assign one?"
msgstr ""
+"ไม่มี OccluderPolygon2D ในโหนดนี้\n"
+"สร้างà¹à¸¥à¸°à¸à¸³à¸«à¸™à¸”?"
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
msgid "Create Occluder Polygon"
msgstr "สร้างรูปหลายเหลี่ยมà¸à¸±à¹‰à¸™à¹à¸ªà¸‡"
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Edit existing polygon:"
msgstr "à¹à¸à¹‰à¹„ขรูปหลายเหลี่ยมเดิม:"
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "LMB: Move Point."
msgstr "คลิà¸à¸‹à¹‰à¸²à¸¢: ย้ายจุด"
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Ctrl+LMB: Split Segment."
msgstr "Ctrl+คลิà¸à¸‹à¹‰à¸²à¸¢: à¹à¸¢à¸à¸ªà¹ˆà¸§à¸™"
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "RMB: Erase Point."
msgstr "คลิà¸à¸‚วา: ลบจุด"
@@ -4221,6 +3724,10 @@ msgid "Create Outline"
msgstr "สร้างเส้นรอบรูป"
#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Mesh"
+msgstr "Mesh"
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Create Trimesh Static Body"
msgstr "สร้าง Trimesh Static Body"
@@ -4348,14 +3855,75 @@ msgstr "สุ่มขนาด:"
msgid "Populate"
msgstr ""
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake!"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake the navigation mesh.\n"
+msgstr "สร้าง Mesh นำทาง\n"
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Clear the navigation mesh."
+msgstr "ล้าง Mesh นำทาง"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Setting up Configuration..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Calculating grid size..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating heightfield..."
+msgstr "à¸à¸³à¸¥à¸±à¸‡à¸ªà¸£à¹‰à¸²à¸‡à¸ªà¸™à¸²à¸¡à¸„วามสูง..."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Marking walkable triangles..."
+msgstr "à¸à¸³à¸¥à¸±à¸‡à¸à¸³à¸«à¸™à¸”พื้นผิวที่เดินผ่านได้..."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Constructing compact heightfield..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Eroding walkable area..."
+msgstr "บีบà¹à¸„บส่วนที่เดินผ่านได้..."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Partitioning..."
+msgstr "à¸à¸³à¸¥à¸±à¸‡à¹à¸šà¹ˆà¸‡à¸ªà¹ˆà¸§à¸™..."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating contours..."
+msgstr "à¸à¸³à¸¥à¸±à¸‡à¸ªà¸£à¹‰à¸²à¸‡à¸„อนทัวร์..."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating polymesh..."
+msgstr "à¸à¸³à¸¥à¸±à¸‡à¸ªà¸£à¹‰à¸²à¸‡ Polymesh..."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Converting to native navigation mesh..."
+msgstr "à¸à¸³à¸¥à¸±à¸‡à¹à¸›à¸¥à¸‡à¸à¸¥à¸±à¸šà¹€à¸›à¹‡à¸™ Mesh นำทาง..."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Navigation Mesh Generator Setup:"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Parsing Geometry..."
+msgstr "วิเคราะห์พื้นผิว..."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Done!"
+msgstr ""
+
#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Create Navigation Polygon"
msgstr "สร้างรูปทรงนำทาง"
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Remove Poly And Point"
-msgstr "ลบรูปหลายเหลี่ยมà¹à¸¥à¸°à¸ˆà¸¸à¸”"
-
#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Clear Emission Mask"
msgstr "ลบ Mask à¸à¸²à¸£à¸›à¸¥à¹ˆà¸­à¸¢"
@@ -4392,9 +3960,8 @@ msgstr "โหลด Mask à¸à¸²à¸£à¸›à¸°à¸—ุ"
#: editor/plugins/particles_2d_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp
-#, fuzzy
msgid "Particles"
-msgstr "มุมรูปทรง"
+msgstr "อนุภาค"
#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Generated Point Count:"
@@ -4531,14 +4098,17 @@ msgid "Curve Point #"
msgstr "จุดเส้นโค้ง #"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve Point Position"
msgstr "à¸à¸³à¸«à¸™à¸”พิà¸à¸±à¸”จุดเส้นโค้ง"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve In Position"
msgstr "à¸à¸³à¸«à¸™à¸”เส้นโค้งขาเข้า"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve Out Position"
msgstr "à¸à¸³à¸«à¸™à¸”เส้นโค้งขาออà¸"
@@ -4599,6 +4169,14 @@ msgid "Scale Polygon"
msgstr "ปรับขนาดรูปหลายเหลี่ยม"
#: editor/plugins/polygon_2d_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Edit"
+msgstr "à¹à¸à¹‰à¹„ข"
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Polygon->UV"
msgstr "รูปหลายเหลี่ยม->UV"
@@ -4653,63 +4231,10 @@ msgstr "โหลดรีซอร์ส"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/shader_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "วาง"
-#: editor/plugins/rich_text_editor_plugin.cpp
-msgid "Parse BBCode"
-msgstr "ประมวลผล BBCode"
-
-#: editor/plugins/sample_editor_plugin.cpp
-msgid "Length:"
-msgstr "ความยาว:"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Open Sample File(s)"
-msgstr "เปิดไฟล์เสียง"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "ERROR: Couldn't load sample!"
-msgstr "ผิดพลาด: โหลดไฟล์เสียงไม่ได้!"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Add Sample"
-msgstr "เพิ่มไฟล์เสียง"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Rename Sample"
-msgstr "เปลี่ยนชื่อไฟล์เสียง"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Delete Sample"
-msgstr "ลบไฟล์เสียง"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "16 Bits"
-msgstr "16 บิต"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "8 Bits"
-msgstr "8 บิต"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Stereo"
-msgstr "สเตอริโอ"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Mono"
-msgstr "โมโน"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Format"
-msgstr "รูปà¹à¸šà¸š"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Pitch"
-msgstr "เสียงสูงต่ำ"
-
#: editor/plugins/script_editor_plugin.cpp
msgid "Clear Recent Files"
msgstr "ล้างรายà¸à¸²à¸£à¹„ฟล์ล่าสุด"
@@ -4719,6 +4244,8 @@ msgid ""
"Close and save changes?\n"
"\""
msgstr ""
+"ปิดà¹à¸¥à¸°à¸šà¸±à¸™à¸—ึà¸?\n"
+"\""
#: editor/plugins/script_editor_plugin.cpp
msgid "Error while saving theme"
@@ -4746,7 +4273,7 @@ msgstr "บันทึà¸à¸˜à¸µà¸¡à¹€à¸›à¹‡à¸™"
#: editor/plugins/script_editor_plugin.cpp
msgid " Class Reference"
-msgstr ""
+msgstr " ตำราอ้างอิงคลาส"
#: editor/plugins/script_editor_plugin.cpp
msgid "Next script"
@@ -4800,10 +4327,13 @@ msgstr "ปิดคู่มือ"
msgid "Close All"
msgstr "ปิดทั้งหมด"
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+msgid "Run"
+msgstr "รัน"
+
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Toggle Scripts Panel"
-msgstr "เลือà¸/ลบโฟลเดอร์ที่ชอบ"
+msgstr "เปิด/ปิดà¹à¸œà¸‡à¸ªà¸„ริปต์"
#: editor/plugins/script_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
@@ -4829,7 +4359,8 @@ msgstr "คำสั่งต่อไป"
msgid "Break"
msgstr "หยุดพัà¸"
-#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+#: editor/script_editor_debugger.cpp
msgid "Continue"
msgstr "ทำต่อไป"
@@ -4838,21 +4369,8 @@ msgid "Keep Debugger Open"
msgstr "เปิดตัวดีบัคค้างไว้"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Debug with external editor"
-msgstr "เปิดตัวà¹à¸à¹‰à¹„ขถัดไป"
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Window"
-msgstr "หน้าต่าง"
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Left"
-msgstr "ย้ายไปซ้าย"
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Right"
-msgstr "ย้ายไปขวา"
+msgstr "ดีบัคด้วยโปรà¹à¸à¸£à¸¡à¸­à¸·à¹ˆà¸™"
#: editor/plugins/script_editor_plugin.cpp
msgid "Open Godot online documentation"
@@ -4909,7 +4427,7 @@ msgstr "สคริปต์à¸à¸±à¸‡à¸ˆà¸°à¹à¸à¹‰à¹„ขได้ต่อเ
#: editor/plugins/script_text_editor.cpp
msgid "Only resources from filesystem can be dropped."
-msgstr ""
+msgstr "สามารถวางรีซอร์สจาà¸à¸£à¸°à¸šà¸šà¹„ฟล์ได้เท่านั้น"
#: editor/plugins/script_text_editor.cpp
msgid "Pick Color"
@@ -4938,8 +4456,9 @@ msgid "Cut"
msgstr "ตัด"
#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "คัดลอà¸"
@@ -4958,9 +4477,8 @@ msgid "Move Down"
msgstr "ย้ายลง"
#: editor/plugins/script_text_editor.cpp
-#, fuzzy
msgid "Delete Line"
-msgstr "ลบจุด"
+msgstr "ลบเส้น"
#: editor/plugins/script_text_editor.cpp
msgid "Indent Left"
@@ -4979,7 +4497,6 @@ msgid "Clone Down"
msgstr "คัดลอà¸à¸šà¸£à¸£à¸—ัดลงมา"
#: editor/plugins/script_text_editor.cpp
-#, fuzzy
msgid "Complete Symbol"
msgstr "เสนอà¹à¸™à¸°à¸„ำเต็ม"
@@ -4988,12 +4505,10 @@ msgid "Trim Trailing Whitespace"
msgstr "ลบตัวอัà¸à¸©à¸£à¸—ี่มองไม่เห็น"
#: editor/plugins/script_text_editor.cpp
-#, fuzzy
msgid "Convert Indent To Spaces"
msgstr "ใช้เว้นวรรคเป็นย่อหน้า"
#: editor/plugins/script_text_editor.cpp
-#, fuzzy
msgid "Convert Indent To Tabs"
msgstr "ใช้à¹à¸—็บเป็นย่อหน้า"
@@ -5130,16 +4645,18 @@ msgid "Add/Remove to Color Ramp"
msgstr "เพิ่ม/ลบในà¸à¸²à¸£à¹„ล่สี"
#: editor/plugins/shader_graph_editor_plugin.cpp
+#, fuzzy
msgid "Add/Remove to Curve Map"
-msgstr ""
+msgstr "เพิ่ม/ลบในเส้นโค้ง"
#: editor/plugins/shader_graph_editor_plugin.cpp
+#, fuzzy
msgid "Modify Curve Map"
-msgstr ""
+msgstr "à¹à¸à¹‰à¹„ขเส้นโค้ง"
#: editor/plugins/shader_graph_editor_plugin.cpp
msgid "Change Input Name"
-msgstr ""
+msgstr "เปลี่ยนชื่ออินพุต"
#: editor/plugins/shader_graph_editor_plugin.cpp
msgid "Connect Graph Nodes"
@@ -5206,10 +4723,6 @@ msgid "View Plane Transform."
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Scaling to %s%%."
-msgstr "ปรับขนาดเป็น %s%%"
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rotating %s degrees."
msgstr "หมุน %s องศา"
@@ -5226,10 +4739,6 @@ msgid "Top View."
msgstr "มุมบน"
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Top"
-msgstr "บน"
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rear View."
msgstr "มุมหลัง"
@@ -5310,17 +4819,14 @@ msgid "Display Overdraw"
msgstr "à¹à¸ªà¸”งà¸à¸²à¸£à¸§à¸²à¸”ทับซ้อน"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Display Unshaded"
msgstr "à¹à¸ªà¸”งà¹à¸šà¸šà¹„ร้เงา"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "View Environment"
msgstr "à¹à¸ªà¸”งสภาพà¹à¸§à¸”ล้อม"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "View Gizmos"
msgstr "à¹à¸ªà¸”งสัà¸à¸¥à¸±à¸à¸©à¸“์"
@@ -5333,9 +4839,8 @@ msgid "Audio Listener"
msgstr "ตัวรับเสียง"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Doppler Enable"
-msgstr "เปิด"
+msgstr "เปิดดอปเพลอร์"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Freelook Left"
@@ -5366,27 +4871,26 @@ msgid "Freelook Speed Modifier"
msgstr "มุมมองอิสระ ปรับความเร็ว"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "preview"
msgstr "ตัวอย่าง"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "XForm Dialog"
msgstr "เครื่องมือเคลื่อนย้าย"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Select Mode (Q)\n"
-msgstr "โหมดเลือà¸"
+msgstr "โหมดเลือภ(Q)\n"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid ""
"Drag: Rotate\n"
"Alt+Drag: Move\n"
"Alt+RMB: Depth list selection"
-msgstr "Alt+คลิà¸à¸‚วา: เลือà¸à¸—ี่ซ้อนà¸à¸±à¸™"
+msgstr ""
+"ลาà¸: หมุน\n"
+"Alt+ลาà¸: ย้าย\n"
+"Alt+คลิà¸à¸‚วา: เลือà¸à¸—ี่ซ้อนà¸à¸±à¸™"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Move Mode (W)"
@@ -5465,12 +4969,16 @@ msgid "Transform"
msgstr "เคลื่อนย้าย"
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Configure Snap.."
+msgstr "ตั้งค่าà¸à¸²à¸£à¸ˆà¸³à¸à¸±à¸”.."
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Local Coords"
msgstr "พิà¸à¸±à¸”ภายใน"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Transform Dialog.."
-msgstr ""
+msgstr "เครื่องมือเคลื่อนย้าย.."
#: editor/plugins/spatial_editor_plugin.cpp
msgid "1 Viewport"
@@ -5559,7 +5067,7 @@ msgstr "ปรับขนาด (อัตราส่วน):"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Transform Type"
-msgstr ""
+msgstr "ประเภทà¸à¸²à¸£à¹€à¸„ลื่อนย้าย"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Pre"
@@ -5610,6 +5118,10 @@ msgid "Speed (FPS):"
msgstr "ความเร็ว (เฟรมต่อวินาที):"
#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Loop"
+msgstr "วน"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Animation Frames"
msgstr "เฟรมà¹à¸­à¸™à¸´à¹€à¸¡à¸Šà¸±à¸™"
@@ -5622,12 +5134,12 @@ msgid "Insert Empty (After)"
msgstr "เพิ่มà¹à¸šà¸šà¸§à¹ˆà¸²à¸‡à¹€à¸›à¸¥à¹ˆà¸² (หลัง)"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Up"
-msgstr "ขึ้น"
+msgid "Move (Before)"
+msgstr "ย้าย (à¸à¹ˆà¸­à¸™)"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Down"
-msgstr "ลง"
+msgid "Move (After)"
+msgstr "ย้าย (หลัง)"
#: editor/plugins/style_box_editor_plugin.cpp
msgid "StyleBox Preview:"
@@ -5655,7 +5167,6 @@ msgid "Grid Snap"
msgstr "จำà¸à¸±à¸”ด้วยเส้นตาราง"
#: editor/plugins/texture_region_editor_plugin.cpp
-#, fuzzy
msgid "Auto Slice"
msgstr "à¹à¸šà¹ˆà¸‡à¸­à¸±à¸•à¹‚นมัติ"
@@ -5697,18 +5208,20 @@ msgid "Remove Item"
msgstr "ลบไอเทม"
#: editor/plugins/theme_editor_plugin.cpp
-#, fuzzy
msgid "Remove All Items"
-msgstr "ลบไอเทมคลาส"
+msgstr "ลบทั้งหมด"
#: editor/plugins/theme_editor_plugin.cpp
-#, fuzzy
msgid "Remove All"
-msgstr "ลบ"
+msgstr "ลบทั้งหมด"
#: editor/plugins/theme_editor_plugin.cpp
-msgid "Theme"
-msgstr "ธีม"
+msgid "Edit theme.."
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Theme editing menu."
+msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
msgid "Add Class Items"
@@ -5792,11 +5305,14 @@ msgid "Style"
msgstr "รูปà¹à¸šà¸š"
#: editor/plugins/theme_editor_plugin.cpp
+msgid "Font"
+msgstr "ฟอนต์"
+
+#: editor/plugins/theme_editor_plugin.cpp
msgid "Color"
msgstr "สี"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Erase Selection"
msgstr "ลบที่เลือà¸"
@@ -5805,18 +5321,16 @@ msgid "Paint TileMap"
msgstr "วาด TileMap"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Line Draw"
-msgstr "เส้นตรง"
+msgstr "วาดเส้น"
#: editor/plugins/tile_map_editor_plugin.cpp
msgid "Rectangle Paint"
-msgstr ""
+msgstr "วาดสี่เหลี่ยม"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Bucket Fill"
-msgstr "ถัง"
+msgstr "ถมเต็ม"
#: editor/plugins/tile_map_editor_plugin.cpp
msgid "Erase TileMap"
@@ -5843,8 +5357,8 @@ msgid "Mirror Y"
msgstr "สะท้อนซ้ายขวา"
#: editor/plugins/tile_map_editor_plugin.cpp
-msgid "Bucket"
-msgstr "ถัง"
+msgid "Paint Tile"
+msgstr "วาด Tile"
#: editor/plugins/tile_map_editor_plugin.cpp
msgid "Pick Tile"
@@ -5903,11 +5417,14 @@ msgid "Delete patch '"
msgstr "ลบà¹à¸žà¸•à¸Šà¹Œ '"
#: editor/project_export.cpp
-#, fuzzy
msgid "Delete preset '%s'?"
msgstr "ลบ '%s'?"
#: editor/project_export.cpp
+msgid "Export templates for this platform are missing/corrupted: "
+msgstr "à¹à¸¡à¹ˆà¹à¸šà¸šà¸ªà¹ˆà¸‡à¸­à¸­à¸à¸ªà¸³à¸«à¸£à¸±à¸šà¹à¸žà¸¥à¸•à¸Ÿà¸­à¸£à¹Œà¸¡à¸™à¸µà¹‰à¸ªà¸¹à¸à¸«à¸²à¸¢/เสียหาย: "
+
+#: editor/project_export.cpp
msgid "Presets"
msgstr "à¸à¸²à¸£à¸ªà¹ˆà¸‡à¸­à¸­à¸"
@@ -5958,18 +5475,16 @@ msgid "Make Patch"
msgstr "สร้างà¹à¸žà¸•à¸Šà¹Œ"
#: editor/project_export.cpp
-#, fuzzy
msgid "Features"
-msgstr "Texture"
+msgstr "ฟีเจอร์"
#: editor/project_export.cpp
msgid "Custom (comma-separated):"
-msgstr ""
+msgstr "à¸à¸³à¸«à¸™à¸”เอง (คั่นด้วยจุลภาค):"
#: editor/project_export.cpp
-#, fuzzy
msgid "Feature List:"
-msgstr "รายชื่อเมท็อด:"
+msgstr "รายชื่อฟีเจอร์:"
#: editor/project_export.cpp
msgid "Export PCK/Zip"
@@ -5980,71 +5495,105 @@ msgid "Export templates for this platform are missing:"
msgstr "ไม่พบà¹à¸¡à¹ˆà¹à¸šà¸šà¸ªà¹ˆà¸‡à¸­à¸­à¸à¸ªà¸³à¸«à¸£à¸±à¸šà¹à¸žà¸¥à¸•à¸Ÿà¸­à¸£à¹Œà¸¡à¸™à¸µà¹‰:"
#: editor/project_export.cpp
+msgid "Export templates for this platform are missing/corrupted:"
+msgstr "à¹à¸¡à¹ˆà¹à¸šà¸šà¸ªà¹ˆà¸‡à¸­à¸­à¸à¸ªà¸³à¸«à¸£à¸±à¸šà¹à¸žà¸¥à¸•à¸Ÿà¸­à¸£à¹Œà¸¡à¸™à¸µà¹‰à¸ªà¸¹à¸à¸«à¸²à¸¢/เสียหาย:"
+
+#: editor/project_export.cpp
msgid "Export With Debug"
msgstr "ส่งออà¸à¸žà¸£à¹‰à¸­à¸¡à¸•à¸±à¸§à¸”ีบัค"
#: editor/project_manager.cpp
-msgid "Invalid project path, the path must exist!"
-msgstr "ที่อยู่โปรเจà¸à¸•à¹Œà¸œà¸´à¸”พลาด ต้องมีอยู่จริง!"
+#, fuzzy
+msgid "The path does not exist."
+msgstr "ไม่พบไฟล์"
+
+#: editor/project_manager.cpp
+msgid "Please choose a 'project.godot' file."
+msgstr "à¸à¸£à¸¸à¸“าเลือà¸à¹„ฟล์ 'project.godot'"
#: editor/project_manager.cpp
-msgid "Invalid project path, project.godot must not exist."
-msgstr "ที่อยู่โปรเจà¸à¸•à¹Œà¸œà¸´à¸”พลาด ต้องไม่มี project.godot"
+msgid ""
+"Your project will be created in a non empty folder (you might want to create "
+"a new folder)."
+msgstr ""
#: editor/project_manager.cpp
-msgid "Invalid project path, project.godot must exist."
-msgstr "ที่อยู่โปรเจà¸à¸•à¹Œà¸œà¸´à¸”พลาด ต้องมี project.godot"
+msgid "Please choose a folder that does not contain a 'project.godot' file."
+msgstr ""
#: editor/project_manager.cpp
msgid "Imported Project"
msgstr "นำเข้าโปรเจà¸à¸•à¹Œà¹à¸¥à¹‰à¸§"
#: editor/project_manager.cpp
+msgid " "
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "It would be a good idea to name your project."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Invalid project path (changed anything?)."
msgstr "ตำà¹à¸«à¸™à¹ˆà¸‡à¹‚ปรเจà¸à¸•à¹Œà¸œà¸´à¸”พลาด (ได้à¹à¸à¹‰à¹„ขอะไรไปหรือไม่?)"
#: editor/project_manager.cpp
+msgid "Couldn't get project.godot in project path."
+msgstr "ไม่พบไฟล์ project.godot"
+
+#: editor/project_manager.cpp
+msgid "Couldn't edit project.godot in project path."
+msgstr "à¹à¸à¹‰à¹„ขไฟล์ project.godot ไม่ได้"
+
+#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
msgstr "สร้างไฟล์ project.godot ไม่ได้"
#: editor/project_manager.cpp
-#, fuzzy
msgid "The following files failed extraction from package:"
msgstr "ผิดพลาดขณะà¹à¸¢à¸à¹„ฟล์ต่อไปนี้จาà¸à¹à¸žà¸„เà¸à¸ˆ:"
#: editor/project_manager.cpp
+msgid "Rename Project"
+msgstr "เปลี่ยนชื่อโปรเจà¸à¸•à¹Œ"
+
+#: editor/project_manager.cpp
+msgid "Couldn't get project.godot in the project path."
+msgstr "ไม่พบไฟล์ project.godot"
+
+#: editor/project_manager.cpp
+msgid "New Game Project"
+msgstr "โปรเจà¸à¸•à¹Œà¹ƒà¸«à¸¡à¹ˆ"
+
+#: editor/project_manager.cpp
msgid "Import Existing Project"
msgstr "นำเข้าโปรเจà¸à¸•à¹Œà¸—ี่มีอยู่เดิม"
#: editor/project_manager.cpp
-msgid "Project Path (Must Exist):"
-msgstr "ที่อยู่โปรเจà¸à¸•à¹Œ (ต้องมีอยู่จริง):"
+msgid "Create New Project"
+msgstr "สร้างโปรเจà¸à¸•à¹Œà¹ƒà¸«à¸¡à¹ˆ"
+
+#: editor/project_manager.cpp
+msgid "Install Project:"
+msgstr "ติดตั้งโปรเจà¸à¸•à¹Œ:"
#: editor/project_manager.cpp
msgid "Project Name:"
msgstr "ชื่อโปรเจà¸à¸•à¹Œ:"
#: editor/project_manager.cpp
-msgid "Create New Project"
-msgstr "สร้างโปรเจà¸à¸•à¹Œà¹ƒà¸«à¸¡à¹ˆ"
+msgid "Create folder"
+msgstr "สร้างโฟลเดอร์"
#: editor/project_manager.cpp
msgid "Project Path:"
msgstr "ที่อยู่โปรเจà¸à¸•à¹Œ:"
#: editor/project_manager.cpp
-msgid "Install Project:"
-msgstr "ติดตั้งโปรเจà¸à¸•à¹Œ:"
-
-#: editor/project_manager.cpp
msgid "Browse"
msgstr "เลือà¸"
#: editor/project_manager.cpp
-msgid "New Game Project"
-msgstr "โปรเจà¸à¸•à¹Œà¹ƒà¸«à¸¡à¹ˆ"
-
-#: editor/project_manager.cpp
msgid "That's a BINGO!"
msgstr "บิงโà¸!"
@@ -6053,11 +5602,14 @@ msgid "Unnamed Project"
msgstr "โปรเจà¸à¸•à¹Œà¹„ม่มีชื่อ"
#: editor/project_manager.cpp
+msgid "Can't open project"
+msgstr "ไม่สามารถเปิดโปรเจà¸à¸•à¹Œ"
+
+#: editor/project_manager.cpp
msgid "Are you sure to open more than one project?"
msgstr "ยืนยันà¸à¸²à¸£à¹€à¸›à¸´à¸”โปรเจà¸à¸•à¹Œà¸¡à¸²à¸à¸à¸§à¹ˆà¸² 1 โปรเจà¸à¸•à¹Œ?"
#: editor/project_manager.cpp
-#, fuzzy
msgid ""
"Can't run project: no main scene defined.\n"
"Please edit the project and set the main scene in \"Project Settings\" under "
@@ -6071,6 +5623,8 @@ msgid ""
"Can't run project: Assets need to be imported.\n"
"Please edit the project to trigger the initial import."
msgstr ""
+"ไม่สามารถรันโปรเจà¸à¸•à¹Œ: ต้องนำเข้าไฟล์\n"
+"à¸à¸£à¸¸à¸“าเปิดà¹à¸à¹‰à¹„ขโปรเจà¸à¸•à¹Œà¹€à¸žà¸·à¹ˆà¸­à¸™à¸³à¹€à¸‚้าไฟล์"
#: editor/project_manager.cpp
msgid "Are you sure to run more than one project?"
@@ -6082,6 +5636,12 @@ msgstr "ลบโปรเจà¸à¸•à¹Œà¸­à¸­à¸à¸ˆà¸²à¸à¸£à¸²à¸¢à¸Šà¸·à¹ˆà¸­? (
#: editor/project_manager.cpp
msgid ""
+"Language changed.\n"
+"The UI will update next time the editor or project manager starts."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid ""
"You are about the scan %s folders for existing Godot projects. Do you "
"confirm?"
msgstr "จะทำà¸à¸²à¸£à¸ªà¹à¸à¸™à¸«à¸²à¹‚ปรเจà¸à¸•à¹Œà¹ƒà¸™ %s โฟลเดอร์ ยืนยัน?"
@@ -6091,10 +5651,6 @@ msgid "Project List"
msgstr "รายชื่อโปรเจà¸à¸•à¹Œ"
#: editor/project_manager.cpp
-msgid "Run"
-msgstr "รัน"
-
-#: editor/project_manager.cpp
msgid "Scan"
msgstr "สà¹à¸à¸™"
@@ -6116,8 +5672,12 @@ msgstr "ออà¸"
#: editor/project_manager.cpp
#, fuzzy
+msgid "Restart Now"
+msgstr "หาโหนดà¹à¸¡à¹ˆà¹ƒà¸«à¸¡à¹ˆ"
+
+#: editor/project_manager.cpp
msgid "Can't run project"
-msgstr "เชื่อมต่อไม่ได้"
+msgstr "ไม่สามารถรันโปรเจà¸à¸•à¹Œ"
#: editor/project_settings_editor.cpp
msgid "Key "
@@ -6152,17 +5712,14 @@ msgid "Add Input Action Event"
msgstr "เพิ่มà¸à¸²à¸£à¸à¸£à¸°à¸—ำ"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Meta+"
msgstr "Meta+"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Shift+"
msgstr "Shift+"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Alt+"
msgstr "Alt+"
@@ -6223,7 +5780,7 @@ msgstr "เปลี่ยน"
msgid "Joypad Axis Index:"
msgstr "คันบังคับจอย:"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Axis"
msgstr "à¹à¸à¸™"
@@ -6240,61 +5797,64 @@ msgid "Erase Input Action Event"
msgstr "ลบà¸à¸²à¸£à¸à¸£à¸°à¸—ำ"
#: editor/project_settings_editor.cpp
-#, fuzzy
msgid "Add Event"
-msgstr "เพิ่ม"
+msgstr "เพิ่มปุ่มà¸à¸”"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Device"
msgstr "อุปà¸à¸£à¸“์"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Button"
msgstr "ปุ่ม"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Left Button."
msgstr "ปุ่มเมาส์ซ้าย"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Right Button."
msgstr "ปุ่มเมาส์ขวา"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Middle Button."
msgstr "ปุ่มเมาส์à¸à¸¥à¸²à¸‡"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Up."
msgstr "ล้อเมาส์ขึ้น"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Down."
msgstr "ล้อเมาส์ลง"
#: editor/project_settings_editor.cpp
-#, fuzzy
msgid "Add Global Property"
-msgstr "เพิ่มตัวรับคุณสมบัติ"
+msgstr "เพิ่มคุณสมบัติทั่วไป"
#: editor/project_settings_editor.cpp
-msgid "Select an setting item first!"
-msgstr ""
+msgid "Select a setting item first!"
+msgstr "à¸à¸£à¸¸à¸“าเลือà¸à¸•à¸±à¸§à¹€à¸¥à¸·à¸­à¸à¸à¹ˆà¸­à¸™!"
#: editor/project_settings_editor.cpp
-#, fuzzy
msgid "No property '"
-msgstr "คุณสมบัติ:"
+msgstr "ไม่พบคุณสมบัติ '"
#: editor/project_settings_editor.cpp
-#, fuzzy
msgid "Setting '"
-msgstr "ตัวเลือà¸"
+msgstr "ตัวเลือภ'"
#: editor/project_settings_editor.cpp
-#, fuzzy
msgid "Delete Item"
-msgstr "ลบอินพุต"
+msgstr "ลบไอเทม"
+
+#: editor/project_settings_editor.cpp
+msgid "Can't contain '/' or ':'"
+msgstr "ต้องไม่มี '/' หรือ ':'"
+
+#: editor/project_settings_editor.cpp
+msgid "Already existing"
+msgstr "มีอยู่à¸à¹ˆà¸­à¸™à¹à¸¥à¹‰à¸§"
#: editor/project_settings_editor.cpp
msgid "Error saving settings."
@@ -6306,7 +5866,7 @@ msgstr "บันทึà¸à¹à¸¥à¹‰à¸§"
#: editor/project_settings_editor.cpp
msgid "Override for Feature"
-msgstr ""
+msgstr "à¸à¸³à¸«à¸™à¸”ค่าเฉพาะของฟีเจอร์"
#: editor/project_settings_editor.cpp
msgid "Add Translation"
@@ -6337,6 +5897,15 @@ msgid "Remove Resource Remap Option"
msgstr "ลบà¸à¸²à¸£à¹à¸—นที่"
#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Changed Locale Filter"
+msgstr "ปรับขนาดà¸à¸¥à¹‰à¸­à¸‡"
+
+#: editor/project_settings_editor.cpp
+msgid "Changed Locale Filter Mode"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "Project Settings (project.godot)"
msgstr "ตัวเลือà¸à¹‚ปรเจà¸à¸•à¹Œ (project.godot)"
@@ -6350,7 +5919,7 @@ msgstr "คุณสมบัติ:"
#: editor/project_settings_editor.cpp
msgid "Override For.."
-msgstr ""
+msgstr "à¸à¸³à¸«à¸™à¸”เฉพาะ.."
#: editor/project_settings_editor.cpp
msgid "Input Map"
@@ -6397,6 +5966,30 @@ msgid "Locale"
msgstr "ท้องถิ่น"
#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Locales Filter"
+msgstr "ท้องถิ่น"
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Show all locales"
+msgstr "à¹à¸ªà¸”งà¸à¸£à¸°à¸”ูà¸"
+
+#: editor/project_settings_editor.cpp
+msgid "Show only selected locales"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Filter mode:"
+msgstr "ตัวà¸à¸£à¸­à¸‡"
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Locales:"
+msgstr "ท้องถิ่น"
+
+#: editor/project_settings_editor.cpp
msgid "AutoLoad"
msgstr "ออโต้โหลด"
@@ -6437,7 +6030,6 @@ msgid "Assign"
msgstr "ระบุ"
#: editor/property_editor.cpp
-#, fuzzy
msgid "Select Node"
msgstr "เลือà¸à¹‚หนด"
@@ -6446,17 +6038,24 @@ msgid "New Script"
msgstr "สคริปต์ใหม่"
#: editor/property_editor.cpp
+msgid "Make Unique"
+msgstr "ไม่ใช้ร่วมà¸à¸±à¸šà¸§à¸±à¸•à¸–ุอื่น"
+
+#: editor/property_editor.cpp
msgid "Show in File System"
msgstr "เปิดในตัวจัดà¸à¸²à¸£à¹„ฟล์"
#: editor/property_editor.cpp
+msgid "Convert To %s"
+msgstr "à¹à¸›à¸¥à¸‡à¹€à¸›à¹‡à¸™ %s"
+
+#: editor/property_editor.cpp
msgid "Error loading file: Not a resource!"
msgstr "ผิดพลาดขณะโหลดไฟล์: ไม่ใช่รีซอร์ส!"
#: editor/property_editor.cpp
-#, fuzzy
msgid "Selected node is not a Viewport!"
-msgstr "เลือà¸à¹‚หนดเพื่อนำเข้า"
+msgstr "โหนดที่เลือà¸à¹„ม่ใช่ Viewport!"
#: editor/property_editor.cpp
msgid "Pick a Node"
@@ -6487,6 +6086,10 @@ msgid "Select Property"
msgstr "เลือà¸à¸„ุณสมบัติ"
#: editor/property_selector.cpp
+msgid "Select Virtual Method"
+msgstr "เลือà¸à¹€à¸¡à¸—็อด"
+
+#: editor/property_selector.cpp
msgid "Select Method"
msgstr "เลือà¸à¹€à¸¡à¸—็อด"
@@ -6514,26 +6117,6 @@ msgstr ""
msgid "Reparent"
msgstr "เลือà¸à¹‚หนดà¹à¸¡à¹ˆà¹ƒà¸«à¸¡à¹ˆ"
-#: editor/resources_dock.cpp
-msgid "Create New Resource"
-msgstr "สร้างรีซอร์สใหม่"
-
-#: editor/resources_dock.cpp
-msgid "Open Resource"
-msgstr "เปิดรีซอร์ส"
-
-#: editor/resources_dock.cpp
-msgid "Save Resource"
-msgstr "บันทึà¸à¸£à¸µà¸‹à¸­à¸£à¹Œà¸ª"
-
-#: editor/resources_dock.cpp
-msgid "Resource Tools"
-msgstr "เครื่องมือรีซอร์ส"
-
-#: editor/resources_dock.cpp
-msgid "Make Local"
-msgstr ""
-
#: editor/run_settings_dialog.cpp
msgid "Run Mode:"
msgstr ""
@@ -6656,17 +6239,8 @@ msgid "Error duplicating scene to save it."
msgstr "ผิดพลาดขณะทำซ้ำฉาà¸à¹€à¸žà¸·à¹ˆà¸­à¸šà¸±à¸™à¸—ึà¸"
#: editor/scene_tree_dock.cpp
-#, fuzzy
msgid "Sub-Resources:"
-msgstr "รีซอร์ส:"
-
-#: editor/scene_tree_dock.cpp
-msgid "Edit Groups"
-msgstr "à¹à¸à¹‰à¹„ขà¸à¸¥à¸¸à¹ˆà¸¡"
-
-#: editor/scene_tree_dock.cpp
-msgid "Edit Connections"
-msgstr "à¹à¸à¹‰à¹„ขà¸à¸²à¸£à¹€à¸Šà¸·à¹ˆà¸­à¸¡à¹‚ยง"
+msgstr "รีซอร์สย่อย:"
#: editor/scene_tree_dock.cpp
msgid "Clear Inheritance"
@@ -6727,7 +6301,6 @@ msgid ""
msgstr "อินสà¹à¸•à¸™à¸‹à¹Œà¸‰à¸²à¸à¹€à¸›à¹‡à¸™à¹‚หนด สร้างฉาà¸à¸ªà¸·à¸šà¸—อดถ้าไม่มีโหนดราà¸"
#: editor/scene_tree_dock.cpp
-#, fuzzy
msgid "Filter nodes"
msgstr "ตัวà¸à¸£à¸­à¸‡"
@@ -6808,7 +6381,6 @@ msgstr ""
"คลิà¸à¹€à¸žà¸·à¹ˆà¸­à¸—ำให้เลือà¸à¹„ด้"
#: editor/scene_tree_editor.cpp
-#, fuzzy
msgid "Toggle Visibility"
msgstr "ซ่อน/à¹à¸ªà¸”ง"
@@ -6825,23 +6397,20 @@ msgid "Scene Tree (Nodes):"
msgstr "ผังฉาภ(โหนด):"
#: editor/scene_tree_editor.cpp
-#, fuzzy
msgid "Node Configuration Warning!"
-msgstr "คำเตือนà¸à¸²à¸£à¸•à¸±à¹‰à¸‡à¸„่าโหนด:"
+msgstr "คำเตือนà¸à¸²à¸£à¸•à¸±à¹‰à¸‡à¸„่าโหนด!"
#: editor/scene_tree_editor.cpp
msgid "Select a Node"
msgstr "เลือà¸à¹‚หนด"
#: editor/script_create_dialog.cpp
-#, fuzzy
msgid "Error loading template '%s'"
-msgstr "ผิดพลาดขณะโหลดรูป:"
+msgstr "ผิดพลาดขณะโหลดà¹à¸¡à¹ˆà¹à¸šà¸š '%s'"
#: editor/script_create_dialog.cpp
-#, fuzzy
msgid "Error - Could not create script in filesystem."
-msgstr "สร้างสคริปต์ในระบบไฟล์ไม่ได้"
+msgstr "ผิดพลาด - สร้างสคริปต์ไม่ได้"
#: editor/script_create_dialog.cpp
msgid "Error loading script from %s"
@@ -6861,18 +6430,25 @@ msgstr "ตำà¹à¸«à¸™à¹ˆà¸‡à¸—ี่อยู่ไม่ใช่ภายใ
#: editor/script_create_dialog.cpp
msgid "Invalid base path"
+msgstr "ตำà¹à¸«à¸™à¹ˆà¸‡à¹€à¸£à¸´à¹ˆà¸¡à¸•à¹‰à¸™à¹„ม่ถูà¸à¸•à¹‰à¸­à¸‡"
+
+#: editor/script_create_dialog.cpp
+msgid "Directory of the same name exists"
msgstr ""
#: editor/script_create_dialog.cpp
+msgid "File exists, will be reused"
+msgstr "มีไฟล์นี้อยู่à¹à¸¥à¹‰à¸§ จะนำมาใช้"
+
+#: editor/script_create_dialog.cpp
msgid "Invalid extension"
msgstr "นามสà¸à¸¸à¸¥à¹„ม่ถูà¸à¸•à¹‰à¸­à¸‡"
#: editor/script_create_dialog.cpp
msgid "Wrong extension chosen"
-msgstr ""
+msgstr "นามสà¸à¸¸à¸¥à¹„ม่ถูà¸à¸•à¹‰à¸­à¸‡"
#: editor/script_create_dialog.cpp
-#, fuzzy
msgid "Invalid Path"
msgstr "ตำà¹à¸«à¸™à¹ˆà¸‡à¸œà¸´à¸”พลาด"
@@ -6898,31 +6474,30 @@ msgid "Built-in script (into scene file)"
msgstr "à¸à¸±à¸‡à¸ªà¸„ริปต์ในไฟล์ฉาà¸"
#: editor/script_create_dialog.cpp
-#, fuzzy
msgid "Create new script file"
msgstr "สร้างสคริปต์ใหม่"
#: editor/script_create_dialog.cpp
-#, fuzzy
msgid "Load existing script file"
-msgstr "โหลดสคริปต์ที่มีอยู่เดิม"
+msgstr "โหลดสคริปต์จาà¸à¸”ิสà¸à¹Œ"
+
+#: editor/script_create_dialog.cpp
+msgid "Language"
+msgstr "ภาษา"
#: editor/script_create_dialog.cpp
-#, fuzzy
msgid "Inherits"
-msgstr "สืบทอดจาà¸:"
+msgstr "สืบทอดจาà¸"
#: editor/script_create_dialog.cpp
-#, fuzzy
msgid "Class Name"
-msgstr "ชื่อคลาส:"
+msgstr "ชื่อคลาส"
#: editor/script_create_dialog.cpp
msgid "Template"
msgstr "à¹à¸¡à¹ˆà¹à¸šà¸š"
#: editor/script_create_dialog.cpp
-#, fuzzy
msgid "Built-in Script"
msgstr "à¸à¸±à¸‡à¸ªà¸„ริปต์"
@@ -6951,6 +6526,10 @@ msgid "Function:"
msgstr "ฟังà¸à¹Œà¸Šà¸±à¸™:"
#: editor/script_editor_debugger.cpp
+msgid "Pick one or more items from the list to display the graph."
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
msgid "Errors"
msgstr "ข้อผิดพลาด"
@@ -7031,6 +6610,10 @@ msgid "Type"
msgstr "ประเภท"
#: editor/script_editor_debugger.cpp
+msgid "Format"
+msgstr "รูปà¹à¸šà¸š"
+
+#: editor/script_editor_debugger.cpp
msgid "Usage"
msgstr "ใช้"
@@ -7107,12 +6690,29 @@ msgstr "เปลี่ยนà¸à¸£à¸­à¸šà¸­à¸™à¸¸à¸ à¸²à¸„"
msgid "Change Probe Extents"
msgstr "à¹à¸à¹‰à¹„ขขนาด Probe"
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Library"
+msgstr "ไลบรารี"
+
+#: modules/gdnative/gd_native_library_editor.cpp
+#, fuzzy
+msgid "Status"
+msgstr "สถานะ:"
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Libraries: "
+msgstr ""
+
+#: modules/gdnative/register_types.cpp
+msgid "GDNative"
+msgstr ""
+
#: modules/gdscript/gd_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Invalid type argument to convert(), use TYPE_* constants."
msgstr "ตัวà¹à¸›à¸£à¹ƒà¸™ convert() ผิดพลาด ใช้ค่าคงที่ TYPE_* เท่านั้น"
-#: modules/gdscript/gd_functions.cpp
+#: modules/gdscript/gd_functions.cpp modules/mono/glue/glue_header.h
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Not enough bytes for decoding bytes, or invalid format."
msgstr "ไบต์ไม่ครบหรือผิดรูปà¹à¸šà¸š ไม่สามารถà¹à¸›à¸¥à¸‡à¸„่าได้"
@@ -7151,34 +6751,27 @@ msgstr "ดิà¸à¸Šà¸±à¸™à¸™à¸²à¸£à¸µà¸—ี่เà¸à¹‡à¸šà¸­à¸´à¸™à¸ªà¹à¸•à¸™
#: modules/gdscript/gd_functions.cpp
msgid "Object can't provide a length."
-msgstr ""
+msgstr "ไม่สามารถบอà¸à¸„วามยาวของวัตถุได้"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "GridMap Delete Selection"
-msgstr "ลบสิ่งที่เลือà¸"
+msgstr "ลบที่เลือà¸à¹ƒà¸™ GridMap"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "GridMap Duplicate Selection"
-msgstr "ทำซ้ำในà¹à¸—ร็à¸à¹€à¸”ิม"
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "GridMap Paint"
-msgstr ""
+msgstr "ทำซ้ำใน GridMap"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Snap View"
-msgstr "มุมบน"
+msgstr ""
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Prev Level (%sDown Wheel)"
-msgstr ""
+msgstr "ชั้นà¸à¹ˆà¸­à¸™à¸«à¸™à¹‰à¸² (%sล้อเมาส์ลง)"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Next Level (%sUp Wheel)"
-msgstr ""
+msgstr "ชั้นถัดไป (%sล้อเมาส์ขึ้น)"
#: modules/gridmap/grid_map_editor_plugin.cpp
#, fuzzy
@@ -7195,30 +6788,27 @@ msgstr ""
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Edit X Axis"
-msgstr ""
+msgstr "à¹à¸à¹‰à¹„ขà¹à¸à¸™ X"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Edit Y Axis"
-msgstr ""
+msgstr "à¹à¸à¹‰à¹„ขà¹à¸à¸™ Y"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Edit Z Axis"
-msgstr ""
+msgstr "à¹à¸à¹‰à¹„ขà¹à¸à¸™ Z"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Cursor Rotate X"
-msgstr "Ctrl: หมุน"
+msgstr "หมุนตามà¹à¸à¸™ X"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Cursor Rotate Y"
-msgstr "Ctrl: หมุน"
+msgstr "หมุนตามà¹à¸à¸™ Y"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Cursor Rotate Z"
-msgstr "Ctrl: หมุน"
+msgstr "หมุนตามà¹à¸à¸™ Z"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Cursor Back Rotate X"
@@ -7237,51 +6827,38 @@ msgid "Cursor Clear Rotation"
msgstr ""
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Create Area"
-msgstr "สร้างใหม่"
+msgstr "สร้างพื้นที่ใหม่"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Create Exterior Connector"
-msgstr "สร้างโปรเจà¸à¸•à¹Œà¹ƒà¸«à¸¡à¹ˆ"
+msgstr ""
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Erase Area"
-msgstr "ลบ TileMap"
+msgstr "ลบพื้นที่"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Selection -> Duplicate"
-msgstr "เฉพาะที่à¸à¸³à¸¥à¸±à¸‡à¹€à¸¥à¸·à¸­à¸"
+msgstr "ทำซ้ำที่เลือà¸"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Selection -> Clear"
-msgstr "เฉพาะที่à¸à¸³à¸¥à¸±à¸‡à¹€à¸¥à¸·à¸­à¸"
+msgstr "ลบที่เลือà¸"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "GridMap Settings"
-msgstr "ตั้งค่าà¸à¸²à¸£à¸ˆà¸³à¸à¸±à¸”"
+msgstr ""
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Pick Distance:"
-msgstr "อินสà¹à¸•à¸™à¸‹à¹Œ:"
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
-msgid "Tiles"
-msgstr " ไฟล์"
+msgstr ""
-#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "Areas"
+#: modules/mono/editor/mono_bottom_panel.cpp
+msgid "Builds"
msgstr ""
#: modules/visual_script/visual_script.cpp
-#, fuzzy
msgid ""
"A node yielded without working memory, please read the docs on how to yield "
"properly!"
@@ -7289,14 +6866,12 @@ msgstr ""
"โหนดหยุดพัà¸à¹‚ปรà¹à¸à¸£à¸¡à¹‚ดยที่ไม่มีหน่วยความจำทำงาน à¸à¸£à¸¸à¸“าอ่านคู่มือเพื่อหยุดพัà¸à¹‚ปรà¹à¸à¸£à¸¡à¹ƒà¸«à¹‰à¸–ูà¸à¸•à¹‰à¸­à¸‡!"
#: modules/visual_script/visual_script.cpp
-#, fuzzy
msgid ""
"Node yielded, but did not return a function state in the first working "
"memory."
msgstr "โหนดหยุดพัภà¹à¸•à¹ˆà¹„ม่ได้คืนสถานะฟังà¸à¹Œà¸Šà¸±à¸™à¹ƒà¸™à¸«à¸™à¹ˆà¸§à¸¢à¸„วามจำทำงานà¹à¸£à¸"
#: modules/visual_script/visual_script.cpp
-#, fuzzy
msgid ""
"Return value must be assigned to first element of node working memory! Fix "
"your node please."
@@ -7315,29 +6890,24 @@ msgid "Stack overflow with stack depth: "
msgstr "สà¹à¸•à¸„ล้น ความสูงสà¹à¸•à¸„: "
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Change Signal Arguments"
-msgstr "à¹à¸à¹‰à¹„ขตัวà¹à¸›à¸£à¸ªà¸±à¸à¸à¸²à¸“:"
+msgstr "à¹à¸à¹‰à¹„ขตัวà¹à¸›à¸£à¸ªà¸±à¸à¸à¸²à¸“"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Change Argument Type"
-msgstr "เปลี่ยนประเภทตัวà¹à¸›à¸£à¹ƒà¸™à¸­à¸²à¸£à¹Œà¹€à¸£à¸¢à¹Œ"
+msgstr "เปลี่ยนประเภทตัวà¹à¸›à¸£"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Change Argument name"
-msgstr "เปลี่ยนชื่อà¹à¸­à¸™à¸´à¹€à¸¡à¸Šà¸±à¸™:"
+msgstr "เปลี่ยนชื่อตัวà¹à¸›à¸£"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Set Variable Default Value"
-msgstr "à¹à¸à¹‰à¹„ขค่าปริยาย"
+msgstr "à¹à¸à¹‰à¹„ขค่าปริยายของตัวà¹à¸›à¸£"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Set Variable Type"
-msgstr "à¹à¸à¹‰à¹„ขตัวà¹à¸›à¸£:"
+msgstr "à¹à¸à¹‰à¹„ขประเภทตัวà¹à¸›à¸£"
#: modules/visual_script/visual_script_editor.cpp
msgid "Functions:"
@@ -7389,12 +6959,10 @@ msgid "Add Node"
msgstr "เพิ่มโหนด"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Remove VisualScript Nodes"
-msgstr "ลบคีย์ที่ผิดพลาด"
+msgstr "ลบโหนด"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Duplicate VisualScript Nodes"
msgstr "ทำซ้ำโหนด"
@@ -7439,24 +7007,20 @@ msgid "Add Setter Property"
msgstr "เพิ่มตัวà¸à¸³à¸«à¸™à¸”คุณสมบัติ"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Change Base Type"
msgstr "เปลี่ยนประเภท"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Move Node(s)"
-msgstr "ลบโหนด"
+msgstr "ย้ายโหนด"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Remove VisualScript Node"
msgstr "ลบโหนด"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Connect Nodes"
-msgstr "เชื่อมไปยังโหนด:"
+msgstr "เชื่อมโหนด"
#: modules/visual_script/visual_script_editor.cpp
msgid "Condition"
@@ -7483,26 +7047,30 @@ msgid "Return"
msgstr "คืนค่า"
#: modules/visual_script/visual_script_editor.cpp
+msgid "Call"
+msgstr "เรียà¸"
+
+#: modules/visual_script/visual_script_editor.cpp
msgid "Get"
msgstr "รับ"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
+msgid "Script already has function '%s'"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
msgid "Change Input Value"
-msgstr "à¹à¸à¹‰à¹„ขค่าปริยาย"
+msgstr "à¹à¸à¹‰à¹„ขค่าอินพุต"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Can't copy the function node."
-msgstr "ทำงานใน '..' ไม่ได้"
+msgstr "คัดลอà¸à¹‚หนดฟังà¸à¹Œà¸Šà¸±à¸™à¹„ม่ได้"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Clipboard is empty!"
-msgstr "คลิปบอร์ดไม่มีรีซอร์ส!"
+msgstr "คลิปบอร์ดว่างเปล่า!"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Paste VisualScript Nodes"
msgstr "วางโหนด"
@@ -7511,18 +7079,16 @@ msgid "Remove Function"
msgstr "ลบฟังà¸à¹Œà¸Šà¸±à¸™"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Edit Variable"
-msgstr "à¹à¸à¹‰à¹„ขตัวà¹à¸›à¸£:"
+msgstr "à¹à¸à¹‰à¹„ขตัวà¹à¸›à¸£"
#: modules/visual_script/visual_script_editor.cpp
msgid "Remove Variable"
msgstr "ลบตัวà¹à¸›à¸£"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Edit Signal"
-msgstr "à¹à¸à¹‰à¹„ขสัà¸à¸à¸²à¸“:"
+msgstr "à¹à¸à¹‰à¹„ขสัà¸à¸à¸²à¸“"
#: modules/visual_script/visual_script_editor.cpp
msgid "Remove Signal"
@@ -7537,7 +7103,6 @@ msgid "Editing Signal:"
msgstr "à¹à¸à¹‰à¹„ขสัà¸à¸à¸²à¸“:"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Base Type:"
msgstr "ชนิด:"
@@ -7594,12 +7159,10 @@ msgid "Invalid index property name."
msgstr "ไม่พบคุณสมบัติ"
#: modules/visual_script/visual_script_func_nodes.cpp
-#, fuzzy
msgid "Base object is not a Node!"
msgstr "วัตถุนี้ไม่ใช่โหนด!"
#: modules/visual_script/visual_script_func_nodes.cpp
-#, fuzzy
msgid "Path does not lead Node!"
msgstr "ตำà¹à¸«à¸™à¹ˆà¸‡à¸—ี่ระบุไม่ได้นำไปยังโหนด!"
@@ -7736,7 +7299,7 @@ msgstr "ParallaxLayer จะทำงานได้ต้องเป็นโà
msgid ""
"A material to process the particles is not assigned, so no behavior is "
"imprinted."
-msgstr ""
+msgstr "ไม่ได้à¸à¸³à¸«à¸™à¸”วัสดุให้à¸à¸±à¸šà¸­à¸™à¸¸à¸ à¸²à¸„"
#: scene/2d/path_2d.cpp
msgid "PathFollow2D only works when set as a child of a Path2D node."
@@ -7748,6 +7311,8 @@ msgid ""
"by the physics engine when running.\n"
"Change the size in children collision shapes instead."
msgstr ""
+"ระบบฟิสิà¸à¸ªà¹Œà¸ˆà¸°à¸ˆà¸±à¸”à¸à¸²à¸£à¸‚นาดของ RigidBody2D (ในโหมด character หรือ rigid) เมื่อรันเà¸à¸¡\n"
+"à¸à¸£à¸¸à¸“าปรับขนาดของ Collision shape à¹à¸—น"
#: scene/2d/remote_transform_2d.cpp
msgid "Path property must point to a valid Node2D node to work."
@@ -7775,31 +7340,31 @@ msgstr "VisibilityEnable2D ควรจะเป็นโหนดลูà¸à¸‚à¸
#: scene/3d/arvr_nodes.cpp
msgid "ARVRCamera must have an ARVROrigin node as its parent"
-msgstr ""
+msgstr "ARVRCamera ต้องมี ARVROrigin เป็นโหนดà¹à¸¡à¹ˆ"
#: scene/3d/arvr_nodes.cpp
msgid "ARVRController must have an ARVROrigin node as its parent"
-msgstr ""
+msgstr "ARVRController ต้องมี ARVROrigin เป็นโหนดà¹à¸¡à¹ˆ"
#: scene/3d/arvr_nodes.cpp
msgid ""
"The controller id must not be 0 or this controller will not be bound to an "
"actual controller"
-msgstr ""
+msgstr "Controller id ต้องไม่เป็น 0 ไม่เช่นนั้นตัวควบคุมนี้จะไม่เชื่อมà¸à¸±à¸šà¸­à¸¸à¸›à¸à¸£à¸“์จริง"
#: scene/3d/arvr_nodes.cpp
msgid "ARVRAnchor must have an ARVROrigin node as its parent"
-msgstr ""
+msgstr "ARVRAnchor ต้องมี ARVROrigin เป็นโหนดà¹à¸¡à¹ˆ"
#: scene/3d/arvr_nodes.cpp
msgid ""
"The anchor id must not be 0 or this anchor will not be bound to an actual "
"anchor"
-msgstr ""
+msgstr "Anchor id ต้องไม่เป็น 0 ไม่เช่นนั้น anchor นี้จะไม่เชื่อมà¸à¸±à¸š anchor จริง"
#: scene/3d/arvr_nodes.cpp
msgid "ARVROrigin requires an ARVRCamera child node"
-msgstr ""
+msgstr "ARVROrigin ต้องมี ARVRCamera เป็นโหนดลูà¸"
#: scene/3d/collision_polygon.cpp
msgid ""
@@ -7844,7 +7409,7 @@ msgstr ""
#: scene/3d/particles.cpp
msgid ""
"Nothing is visible because meshes have not been assigned to draw passes."
-msgstr ""
+msgstr "ไม่มีà¸à¸²à¸£à¹à¸ªà¸”งผลเนื่องจาà¸à¹„ม่ได้à¸à¸³à¸«à¸™à¸” mesh ใน draw pass"
#: scene/3d/physics_body.cpp
msgid ""
@@ -7852,6 +7417,8 @@ msgid ""
"the physics engine when running.\n"
"Change the size in children collision shapes instead."
msgstr ""
+"ระบบฟิสิà¸à¸ªà¹Œà¸ˆà¸°à¸ˆà¸±à¸”à¸à¸²à¸£à¸‚นาดของ RigidBody (ในโหมด character หรือ rigid) เมื่อรันเà¸à¸¡\n"
+"à¸à¸£à¸¸à¸“าปรับขนาดของ Collision shape à¹à¸—น"
#: scene/3d/remote_transform.cpp
msgid "Path property must point to a valid Spatial node to work."
@@ -7868,16 +7435,25 @@ msgid ""
"order for AnimatedSprite3D to display frames."
msgstr "ต้องมี SpriteFrames ใน 'Frames' เพื่อให้ AnimatedSprite3D à¹à¸ªà¸”งผลได้"
+#: scene/3d/vehicle_body.cpp
+msgid ""
+"VehicleWheel serves to provide a wheel system to a VehicleBody. Please use "
+"it as a child of a VehicleBody."
+msgstr ""
+
#: scene/gui/color_picker.cpp
-#, fuzzy
msgid "Raw Mode"
-msgstr "โหมดมุมมอง"
+msgstr "โหมด Raw"
#: scene/gui/color_picker.cpp
msgid "Add current color as a preset"
msgstr "เพิ่มสีที่เลือà¸à¹ƒà¸™à¸£à¸²à¸¢à¸à¸²à¸£à¹‚ปรด"
#: scene/gui/dialogs.cpp
+msgid "Cancel"
+msgstr "ยà¸à¹€à¸¥à¸´à¸"
+
+#: scene/gui/dialogs.cpp
msgid "Alert!"
msgstr "à¹à¸ˆà¹‰à¸‡à¹€à¸•à¸·à¸­à¸™!"
@@ -7885,10 +7461,6 @@ msgstr "à¹à¸ˆà¹‰à¸‡à¹€à¸•à¸·à¸­à¸™!"
msgid "Please Confirm..."
msgstr "à¸à¸£à¸¸à¸“ายืนยัน..."
-#: scene/gui/input_action.cpp
-msgid "Ctrl+"
-msgstr "Ctrl+"
-
#: scene/gui/popup.cpp
msgid ""
"Popups will hide by default unless you call popup() or any of the popup*() "
@@ -7927,6 +7499,620 @@ msgstr ""
"ให้à¹à¸à¹‰à¹„ขโหนดนี้ให้เป็นโหนดลูà¸à¸‚อง Control à¹à¸•à¹ˆà¸–้าไม่ ให้ปรับเป็น render target à¹à¸¥à¸°à¸™à¸³à¹„ปใช้เป็น "
"texture ของโหนดอื่น"
+#: scene/resources/dynamic_font.cpp
+msgid "Error initializing FreeType."
+msgstr "ผิดพลาดขณะเริ่มต้น FreeType"
+
+#: scene/resources/dynamic_font.cpp
+msgid "Unknown font format."
+msgstr "ไม่ทราบประเภทของฟอนต์"
+
+#: scene/resources/dynamic_font.cpp
+msgid "Error loading font."
+msgstr "ผิดพลาดขณะโหลดฟอนต์"
+
+#: scene/resources/dynamic_font.cpp
+msgid "Invalid font size."
+msgstr "ขนาดฟอนต์ผิดพลาด"
+
+#~ msgid "Filter:"
+#~ msgstr "ตัวà¸à¸£à¸­à¸‡:"
+
+#~ msgid "' parsing of config failed."
+#~ msgstr "' ผิดพลาดขณะอ่านไฟล์"
+
+#~ msgid "Theme"
+#~ msgstr "ธีม"
+
+#~ msgid "Method List For '%s':"
+#~ msgstr "รายชื่อเมท็อดของ '%s':"
+
+#~ msgid "Arguments:"
+#~ msgstr "ตัวà¹à¸›à¸£:"
+
+#~ msgid "Return:"
+#~ msgstr "คืนค่า:"
+
+#~ msgid "Added:"
+#~ msgstr "เพิ่ม:"
+
+#~ msgid "Removed:"
+#~ msgstr "ลบ:"
+
+#~ msgid "Error saving atlas:"
+#~ msgstr "ผิดพลาดขณะบันทึภatlas:"
+
+#~ msgid "Could not save atlas subtexture:"
+#~ msgstr "บันทึภtexture ย่อยของ atlas ไม่ได้:"
+
+#~ msgid "Exporting for %s"
+#~ msgstr "ส่งออà¸à¸ªà¸³à¸«à¸£à¸±à¸š %s"
+
+#~ msgid "Setting Up.."
+#~ msgstr "à¸à¸³à¸¥à¸±à¸‡à¸•à¸±à¹‰à¸‡à¸„่า.."
+
+#~ msgid "Error loading scene."
+#~ msgstr "ผิดพลาดขณะโหลดฉาà¸"
+
+#~ msgid "Re-Import"
+#~ msgstr "นำเข้าอีà¸à¸„รั้ง"
+
+#~ msgid "Please wait for scan to complete."
+#~ msgstr "à¸à¸£à¸¸à¸“ารอให้à¸à¸²à¸£à¸ªà¹à¸à¸™à¹€à¸ªà¸£à¹‡à¸ˆ"
+
+#~ msgid "Current scene must be saved to re-import."
+#~ msgstr "ฉาà¸à¸›à¸±à¸ˆà¸ˆà¸¸à¸šà¸±à¸™à¸•à¹‰à¸­à¸‡à¸šà¸±à¸™à¸—ึà¸à¸à¹ˆà¸­à¸™à¸™à¸³à¹€à¸‚้าอีà¸à¸„รั้ง"
+
+#~ msgid "Save & Re-Import"
+#~ msgstr "บันทึà¸à¹à¸¥à¸°à¸™à¸³à¹€à¸‚้าอีà¸à¸„รั้ง"
+
+#~ msgid "Re-Importing"
+#~ msgstr "นำเข้าอีà¸à¸„รั้ง"
+
+#~ msgid "Re-Import Changed Resources"
+#~ msgstr "นำเข้ารีซอร์สที่à¹à¸à¹‰à¹„ขอีà¸à¸„รั้ง"
+
+#~ msgid "Loading Export Templates"
+#~ msgstr "à¸à¸³à¸¥à¸±à¸‡à¹‚หลดà¹à¸¡à¹ˆà¹à¸šà¸šà¸ªà¹ˆà¸‡à¸­à¸­à¸"
+
+#~ msgid ""
+#~ "\n"
+#~ "Status: Needs Re-Import"
+#~ msgstr ""
+#~ "\n"
+#~ "สถานะ: ต้องนำเข้าใหม่"
+
+#~ msgid "Same source and destination files, doing nothing."
+#~ msgstr "ไฟล์ต้นทางà¹à¸¥à¸°à¸›à¸¥à¸²à¸¢à¸—างเหมือนà¸à¸±à¸™ ไม่ทำอะไร"
+
+#~ msgid "Target file exists, can't overwrite. Delete first."
+#~ msgstr "ไฟล์ปลายทางมีอยู่ เขียนทับไม่ได้ à¸à¸£à¸¸à¸“าลบà¸à¹ˆà¸­à¸™"
+
+#~ msgid "Same source and destination paths, doing nothing."
+#~ msgstr "ไฟล์ต้นทางà¹à¸¥à¸°à¸›à¸¥à¸²à¸¢à¸—างอยู่ที่เดียวà¸à¸±à¸™ ไม่ทำอะไร"
+
+#~ msgid "Can't move directories to within themselves."
+#~ msgstr "ย้ายโฟลเดอร์เข้ามาในตัวเองไม่ได้"
+
+#~ msgid "Can't rename deps for:\n"
+#~ msgstr "ไม่สามารถà¹à¸à¹‰à¹„ขชื่อสำหรับ:\n"
+
+#~ msgid "Error moving file:\n"
+#~ msgstr "ผิดพลาดขณะย้ายไฟล์:\n"
+
+#~ msgid "Pick New Name and Location For:"
+#~ msgstr "เลือà¸à¸Šà¸·à¹ˆà¸­à¹à¸¥à¸°à¸•à¸³à¹à¸«à¸™à¹ˆà¸‡à¸—ี่อยู่ใหม่ให้à¸à¸±à¸š:"
+
+#~ msgid "No files selected!"
+#~ msgstr "ไม่ได้เลือà¸à¹„ฟล์ไว้!"
+
+#~ msgid "Info"
+#~ msgstr "ข้อมูล"
+
+#~ msgid "Re-Import.."
+#~ msgstr "นำเข้าอีà¸à¸„รั้ง.."
+
+#~ msgid "No bit masks to import!"
+#~ msgstr "ไม่มีบิตà¹à¸¡à¸ªà¸à¹Œà¹ƒà¸«à¹‰à¸™à¸³à¹€à¸‚้า!"
+
+#~ msgid "Target path is empty."
+#~ msgstr "ตำà¹à¸«à¸™à¹ˆà¸‡à¸—ี่อยู่ว่างเปล่า"
+
+#~ msgid "Target path must be a complete resource path."
+#~ msgstr "ต้องเป็นตำà¹à¸«à¸™à¹ˆà¸‡à¸—ี่อยู่à¹à¸šà¸šà¹€à¸•à¹‡à¸¡"
+
+#~ msgid "Target path must exist."
+#~ msgstr "ต้องมีตำà¹à¸«à¸™à¹ˆà¸‡à¸—ี่อยู่"
+
+#~ msgid "Save path is empty!"
+#~ msgstr "ตำà¹à¸«à¸™à¹ˆà¸‡à¸šà¸±à¸™à¸—ึà¸à¸§à¹ˆà¸²à¸‡à¹€à¸›à¸¥à¹ˆà¸²!"
+
+#~ msgid "Import BitMasks"
+#~ msgstr "นำเข้า BitMasks"
+
+#~ msgid "Source Texture(s):"
+#~ msgstr "Texture ต้นฉบับ:"
+
+#~ msgid "Target Path:"
+#~ msgstr "ตำà¹à¸«à¸™à¹ˆà¸‡à¸—ี่อยู่:"
+
+#~ msgid "Accept"
+#~ msgstr "ยอมรับ"
+
+#~ msgid "Bit Mask"
+#~ msgstr "บิตà¹à¸¡à¸ªà¸à¹Œ"
+
+#~ msgid "No source font file!"
+#~ msgstr "ไม่ได้เลือà¸à¹„ฟล์ฟอนต์ต้นฉบับ!"
+
+#~ msgid "No target font resource!"
+#~ msgstr "ไม่ได้เลือà¸à¸§à¹ˆà¸²à¸ˆà¸°à¸™à¸³à¹€à¸‚้ามาเป็นไฟล์ฟอนต์ชื่ออะไร!"
+
+#~ msgid ""
+#~ "Invalid file extension.\n"
+#~ "Please use .font."
+#~ msgstr ""
+#~ "นามสà¸à¸¸à¸¥à¹„ม่ถูà¸à¸•à¹‰à¸­à¸‡\n"
+#~ "à¸à¸£à¸¸à¸“าใช้ .font"
+
+#~ msgid "Couldn't save font."
+#~ msgstr "บันทึà¸à¸Ÿà¸­à¸™à¸•à¹Œà¹„ม่ได้"
+
+#~ msgid "Source Font:"
+#~ msgstr "ฟอนต์ต้นฉบับ:"
+
+#~ msgid "Source Font Size:"
+#~ msgstr "ขนาดฟอนต์ต้นฉบับ:"
+
+#~ msgid "Dest Resource:"
+#~ msgstr "นำเข้ามาเป็นรีซอร์ส:"
+
+#~ msgid "The quick brown fox jumps over the lazy dog."
+#~ msgstr "The quick brown fox jumps over the lazy dog."
+
+#~ msgid "Test:"
+#~ msgstr "ทดสอบ:"
+
+#~ msgid "Options:"
+#~ msgstr "ตัวเลือà¸:"
+
+#~ msgid "Font Import"
+#~ msgstr "นำเข้าฟอนต์"
+
+#~ msgid ""
+#~ "This file is already a Godot font file, please supply a BMFont type file "
+#~ "instead."
+#~ msgstr "ไฟล์นี้เป็นฟอนต์ของ Godot อยู่à¹à¸¥à¹‰à¸§ à¸à¸£à¸¸à¸“าเลือà¸à¸Ÿà¸­à¸™à¸•à¹Œà¸—ี่มาจาภBMFont"
+
+#~ msgid "Failed opening as BMFont file."
+#~ msgstr "ผิดพลาดขณะเปิดไฟล์เป็น BMFont"
+
+#, fuzzy
+#~ msgid "Invalid font custom source."
+#~ msgstr "ต้นฉบับฟอนต์ที่à¸à¸³à¸«à¸™à¸”เองไม่ถูà¸à¸•à¹‰à¸­à¸‡"
+
+#~ msgid "No meshes to import!"
+#~ msgstr "ไม่มี mesh ให้นำเข้า!"
+
+#~ msgid "Single Mesh Import"
+#~ msgstr "นำเข้า Mesh เดี่ยว"
+
+#~ msgid "Source Mesh(es):"
+#~ msgstr "Mesh ต้นฉบับ:"
+
+#~ msgid "Surface %d"
+#~ msgstr "%d พื้นผิว"
+
+#~ msgid "No samples to import!"
+#~ msgstr "ไม่มีไฟล์เสียงให้นำเข้า!"
+
+#~ msgid "Import Audio Samples"
+#~ msgstr "นำเข้าไฟล์เสียง"
+
+#~ msgid "Source Sample(s):"
+#~ msgstr "ไฟล์เสียงต้นฉบับ:"
+
+#~ msgid "Audio Sample"
+#~ msgstr "ไฟล์เสียง"
+
+#~ msgid "New Clip"
+#~ msgstr "คลิปใหม่"
+
+#~ msgid "Flags"
+#~ msgstr "ตัวเลือà¸"
+
+#~ msgid "Optimizer"
+#~ msgstr "ตัวเพิ่มประสิทธิภาพ"
+
+#~ msgid "Max Linear Error"
+#~ msgstr "ผิดพลาดเชิงเส้นมาà¸à¸—ี่สุด"
+
+#~ msgid "Max Angular Error"
+#~ msgstr "ผิดพลาดเชิงมุมมาà¸à¸—ี่สุด"
+
+#~ msgid "Max Angle"
+#~ msgstr "มุมมาà¸à¸ªà¸¸à¸”"
+
+#~ msgid "Clips"
+#~ msgstr "คลิป"
+
+#~ msgid "Start(s)"
+#~ msgstr "เริ่ม"
+
+#~ msgid "End(s)"
+#~ msgstr "จบ"
+
+#~ msgid "Filters"
+#~ msgstr "ตัวà¸à¸£à¸­à¸‡"
+
+#~ msgid "Source path is empty."
+#~ msgstr "ที่อยู่ไฟล์ต้นฉบับว่างเปล่า"
+
+#~ msgid "Couldn't load post-import script."
+#~ msgstr "โหลดสคริปต์หลังนำเข้าไม่ได้"
+
+#~ msgid "Invalid/broken script for post-import."
+#~ msgstr "สคริปต์หลังนำเข้ามีข้อผิดพลาด"
+
+#~ msgid "Error importing scene."
+#~ msgstr "ผิดพลาดขณะนำเข้าฉาà¸"
+
+#~ msgid "Import 3D Scene"
+#~ msgstr "นำเข้าฉาภ3D"
+
+#~ msgid "Source Scene:"
+#~ msgstr "ฉาà¸à¸•à¹‰à¸™à¸‰à¸šà¸±à¸š:"
+
+#~ msgid "Same as Target Scene"
+#~ msgstr "เหมือนà¸à¸±à¸™à¸à¸±à¸šà¸‰à¸²à¸à¸›à¸¥à¸²à¸¢à¸—าง"
+
+#~ msgid "Shared"
+#~ msgstr "ใช้ร่วมà¸à¸±à¸™"
+
+#~ msgid "Target Texture Folder:"
+#~ msgstr "โฟลเดอร์ Texture ปลายทาง:"
+
+#~ msgid "Post-Process Script:"
+#~ msgstr "สคริปต์หลังประมวลผล:"
+
+#~ msgid "Custom Root Node Type:"
+#~ msgstr "ประเภทโหนดราà¸à¸à¸³à¸«à¸™à¸”เอง:"
+
+#~ msgid "Auto"
+#~ msgstr "อัตโนมัติ"
+
+#~ msgid "Root Node Name:"
+#~ msgstr "ชื่อโหนดราà¸:"
+
+#~ msgid "The Following Files are Missing:"
+#~ msgstr "ไฟล์ต่อไปนี้หายไป:"
+
+#~ msgid "Import Anyway"
+#~ msgstr "ยืนยันนำเข้า"
+
+#~ msgid "Import & Open"
+#~ msgstr "นำเข้าà¹à¸¥à¸°à¹€à¸›à¸´à¸”"
+
+#~ msgid "Edited scene has not been saved, open imported scene anyway?"
+#~ msgstr "ฉาà¸à¸›à¸±à¸ˆà¸ˆà¸¸à¸šà¸±à¸™à¸¢à¸±à¸‡à¹„ม่ได้บันทึภยืนยันเปิดไฟล์ฉาà¸à¸—ี่นำเข้า?"
+
+#~ msgid "Import Image:"
+#~ msgstr "นำเข้าไฟล์รูป:"
+
+#~ msgid "Couldn't localize path: %s (already local)"
+#~ msgstr "ทำที่อยู่ไฟล์ให้เป็นภายในไม่ได้: %s (เป็นภายในอยู่à¹à¸¥à¹‰à¸§)"
+
+#~ msgid "3D Scene Animation"
+#~ msgstr "à¹à¸­à¸™à¸´à¹€à¸¡à¸Šà¸±à¸™à¸‰à¸²à¸ 3D"
+
+#~ msgid "Uncompressed"
+#~ msgstr "ไม่บีบอัด"
+
+#~ msgid "Compress Lossless (PNG)"
+#~ msgstr "บีบอัดà¹à¸šà¸šà¹„ม่เสียคุณภาพ (PNG)"
+
+#~ msgid "Compress Lossy (WebP)"
+#~ msgstr "บีบอัดà¹à¸šà¸šà¹€à¸ªà¸µà¸¢à¸„ุณภาพ (WebP)"
+
+#~ msgid "Compress (VRAM)"
+#~ msgstr "บีบอัด (VRAM)"
+
+#~ msgid "Texture Format"
+#~ msgstr "รูปà¹à¸šà¸š Texture"
+
+#~ msgid "Texture Compression Quality (WebP):"
+#~ msgstr "คุณภาพà¸à¸²à¸£à¸šà¸µà¸šà¸­à¸±à¸” Texture (WebP):"
+
+#~ msgid "Texture Options"
+#~ msgstr "ตัวเลือภTexture"
+
+#~ msgid "Please specify some files!"
+#~ msgstr "à¸à¸£à¸¸à¸“าเลือà¸à¸ªà¸±à¸à¹„ฟล์!"
+
+#~ msgid "At least one file needed for Atlas."
+#~ msgstr "Atlas ต้องà¸à¸²à¸£à¹„ฟล์อย่างน้อย 1 ไฟล์"
+
+#~ msgid "Error importing:"
+#~ msgstr "ผิดพลาดขณะนำเข้า:"
+
+#~ msgid "Only one file is required for large texture."
+#~ msgstr "Texture ขนาดใหà¸à¹ˆà¸•à¹‰à¸­à¸‡à¸à¸²à¸£à¹à¸„่ไฟล์เดียว"
+
+#~ msgid "Max Texture Size:"
+#~ msgstr "ขนาด Texture ที่ใหà¸à¹ˆà¸—ี่สุด:"
+
+#~ msgid "Import Textures for Atlas (2D)"
+#~ msgstr "นำเข้า Texture สำหรับ Atlas (2D)"
+
+#~ msgid "Cell Size:"
+#~ msgstr "ขนาดเซลล์:"
+
+#~ msgid "Large Texture"
+#~ msgstr "Texture ขนาดใหà¸à¹ˆ"
+
+#~ msgid "Import Large Textures (2D)"
+#~ msgstr "นำเข้า Texture ขนาดใหà¸à¹ˆ (2D)"
+
+#~ msgid "Source Texture"
+#~ msgstr "Texture ต้นฉบับ"
+
+#~ msgid "Source Texture(s)"
+#~ msgstr "Texture ต้นฉบับ"
+
+#~ msgid "Import Textures for 2D"
+#~ msgstr "นำเข้า Texture สำหรับ 2D"
+
+#~ msgid "Import Textures for 3D"
+#~ msgstr "นำเข้า Texture สำหรับ 3D"
+
+#~ msgid "Import Textures"
+#~ msgstr "นำเข้า Texture"
+
+#~ msgid "2D Texture"
+#~ msgstr "Texture 2D"
+
+#~ msgid "3D Texture"
+#~ msgstr "Texture 3D"
+
+#~ msgid ""
+#~ "NOTICE: Importing 2D textures is not mandatory. Just copy png/jpg files "
+#~ "to the project."
+#~ msgstr "โปรดทราบ: ไม่จำเป็นต้องนำเข้า Texture 2D à¹à¸„่คัดลอà¸à¹„ฟล์ png/jpg เข้าสู่โปรเจà¸à¸•à¹Œ"
+
+#~ msgid "Crop empty space."
+#~ msgstr "ครอบตัดพื้นที่ว่าง"
+
+#~ msgid "Texture"
+#~ msgstr "Texture"
+
+#~ msgid "Import Large Texture"
+#~ msgstr "นำเข้า Texture ขนาดใหà¸à¹ˆ"
+
+#~ msgid "Load Source Image"
+#~ msgstr "โหลดรูปต้นฉบับ"
+
+#~ msgid "Slicing"
+#~ msgstr "ตัด"
+
+#~ msgid "Saving"
+#~ msgstr "บันทึà¸"
+
+#~ msgid "Couldn't save large texture:"
+#~ msgstr "บันทึภTexture ขนาดใหà¸à¹ˆà¹„ม่ได้:"
+
+#~ msgid "Build Atlas For:"
+#~ msgstr "สร้าง Atlas สำหรับ:"
+
+#~ msgid "Loading Image:"
+#~ msgstr "โหลดรูป:"
+
+#~ msgid "Couldn't load image:"
+#~ msgstr "โหลดรูปไม่ได้:"
+
+#~ msgid "Converting Images"
+#~ msgstr "à¸à¸³à¸¥à¸±à¸‡à¹à¸›à¸¥à¸‡à¸£à¸¹à¸›"
+
+#~ msgid "Cropping Images"
+#~ msgstr "ครอบตัดรูป"
+
+#~ msgid "Blitting Images"
+#~ msgstr "คัดลอà¸à¸£à¸¹à¸›"
+
+#~ msgid "Couldn't save atlas image:"
+#~ msgstr "บันทึภAtlas ไม่ได้:"
+
+#~ msgid "Couldn't save converted texture:"
+#~ msgstr "บันทึภTexture ที่à¹à¸›à¸¥à¸‡à¹à¸¥à¹‰à¸§à¹„ม่ได้:"
+
+#~ msgid "Invalid source!"
+#~ msgstr "ต้นฉบับไม่ถูà¸à¸•à¹‰à¸­à¸‡!"
+
+#~ msgid "Invalid translation source!"
+#~ msgstr "ต้นฉบับà¸à¸²à¸£à¹à¸›à¸¥à¹„ม่ถูà¸à¸•à¹‰à¸­à¸‡!"
+
+#~ msgid "Column"
+#~ msgstr "คอลัมน์"
+
+#~ msgid "No items to import!"
+#~ msgstr "ไม่มีอะไรให้นำเข้า!"
+
+#~ msgid "No target path!"
+#~ msgstr "ไม่มีที่อยู่ปลายทาง!"
+
+#~ msgid "Import Translations"
+#~ msgstr "นำเข้าà¸à¸²à¸£à¹à¸›à¸¥"
+
+#~ msgid "Couldn't import!"
+#~ msgstr "นำเข้าไม่ได้!"
+
+#~ msgid "Import Translation"
+#~ msgstr "นำเข้าà¸à¸²à¸£à¹à¸›à¸¥"
+
+#~ msgid "Source CSV:"
+#~ msgstr "CSV ต้นฉบับ:"
+
+#~ msgid "Ignore First Row"
+#~ msgstr "ไม่สนใจà¹à¸–วà¹à¸£à¸"
+
+#~ msgid "Compress"
+#~ msgstr "บีบอัด"
+
+#~ msgid "Add to Project (project.godot)"
+#~ msgstr "เพิ่มเข้าโปรเจà¸à¸•à¹Œ (project.godot)"
+
+#~ msgid "Import Languages:"
+#~ msgstr "นำเข้าภาษา:"
+
+#~ msgid "Translation"
+#~ msgstr "à¸à¸²à¸£à¹à¸›à¸¥"
+
+#~ msgid "Parsing %d Triangles:"
+#~ msgstr "วิเคราะห์สามเหลี่ยม %d อัน:"
+
+#~ msgid "Triangle #"
+#~ msgstr "สามเหลี่ยม #"
+
+#~ msgid "Light Baker Setup:"
+#~ msgstr "ตั้งค่า Light Baker:"
+
+#~ msgid "Fixing Lights"
+#~ msgstr "ซ่อมà¹à¸‹à¸¡à¹à¸ªà¸‡"
+
+#~ msgid "Making BVH"
+#~ msgstr "à¸à¸³à¸¥à¸±à¸‡à¸ªà¸£à¹‰à¸²à¸‡ BVH"
+
+#~ msgid "Transfer to Lightmaps:"
+#~ msgstr "ส่งผ่านไปยัง Lightmaps:"
+
+#~ msgid "Allocating Texture #"
+#~ msgstr "จัดสรร Texture #"
+
+#~ msgid "Baking Triangle #"
+#~ msgstr "à¸à¸³à¸¥à¸±à¸‡ Bake สามเหลี่ยม #"
+
+#~ msgid "Post-Processing Texture #"
+#~ msgstr "ประมวลผล Texture #"
+
+#~ msgid "Reset the lightmap octree baking process (start over)."
+#~ msgstr "รีเซ็ตขั้นตอนà¸à¸²à¸£ bake lightmap octree (เริ่มใหม่)"
+
+#~ msgid "Zoom (%):"
+#~ msgstr "ซูม (%):"
+
+#~ msgid "Skeleton.."
+#~ msgstr "โครงà¸à¸£à¸°à¸”ูà¸.."
+
+#~ msgid "Zoom Reset"
+#~ msgstr "รีเซ็ตà¸à¸²à¸£à¸‹à¸¹à¸¡"
+
+#~ msgid "Zoom Set.."
+#~ msgstr "ตั้งค่าà¸à¸²à¸£à¸‹à¸¹à¸¡.."
+
+#~ msgid "Set a Value"
+#~ msgstr "เซ็ตค่า"
+
+#~ msgid "Snap (Pixels):"
+#~ msgstr "Snap (พิà¸à¹€à¸‹à¸¥):"
+
+#~ msgid "Parse BBCode"
+#~ msgstr "ประมวลผล BBCode"
+
+#~ msgid "Length:"
+#~ msgstr "ความยาว:"
+
+#~ msgid "Open Sample File(s)"
+#~ msgstr "เปิดไฟล์เสียง"
+
+#~ msgid "ERROR: Couldn't load sample!"
+#~ msgstr "ผิดพลาด: โหลดไฟล์เสียงไม่ได้!"
+
+#~ msgid "Add Sample"
+#~ msgstr "เพิ่มไฟล์เสียง"
+
+#~ msgid "Rename Sample"
+#~ msgstr "เปลี่ยนชื่อไฟล์เสียง"
+
+#~ msgid "Delete Sample"
+#~ msgstr "ลบไฟล์เสียง"
+
+#~ msgid "16 Bits"
+#~ msgstr "16 บิต"
+
+#~ msgid "8 Bits"
+#~ msgstr "8 บิต"
+
+#~ msgid "Stereo"
+#~ msgstr "สเตอริโอ"
+
+#~ msgid "Mono"
+#~ msgstr "โมโน"
+
+#~ msgid "Pitch"
+#~ msgstr "เสียงสูงต่ำ"
+
+#~ msgid "Window"
+#~ msgstr "หน้าต่าง"
+
+#~ msgid "Move Right"
+#~ msgstr "ย้ายไปขวา"
+
+#~ msgid "Scaling to %s%%."
+#~ msgstr "ปรับขนาดเป็น %s%%"
+
+#~ msgid "Up"
+#~ msgstr "ขึ้น"
+
+#~ msgid "Down"
+#~ msgstr "ลง"
+
+#~ msgid "Bucket"
+#~ msgstr "ถัง"
+
+#~ msgid "Invalid project path, the path must exist!"
+#~ msgstr "ที่อยู่โปรเจà¸à¸•à¹Œà¸œà¸´à¸”พลาด ต้องมีอยู่จริง!"
+
+#~ msgid "Invalid project path, project.godot must not exist."
+#~ msgstr "ที่อยู่โปรเจà¸à¸•à¹Œà¸œà¸´à¸”พลาด ต้องไม่มี project.godot"
+
+#~ msgid "Invalid project path, project.godot must exist."
+#~ msgstr "ที่อยู่โปรเจà¸à¸•à¹Œà¸œà¸´à¸”พลาด ต้องมี project.godot"
+
+#~ msgid "Project Path (Must Exist):"
+#~ msgstr "ที่อยู่โปรเจà¸à¸•à¹Œ (ต้องมีอยู่จริง):"
+
+#~ msgid "Create New Resource"
+#~ msgstr "สร้างรีซอร์สใหม่"
+
+#~ msgid "Open Resource"
+#~ msgstr "เปิดรีซอร์ส"
+
+#~ msgid "Save Resource"
+#~ msgstr "บันทึà¸à¸£à¸µà¸‹à¸­à¸£à¹Œà¸ª"
+
+#~ msgid "Resource Tools"
+#~ msgstr "เครื่องมือรีซอร์ส"
+
+#~ msgid "Edit Groups"
+#~ msgstr "à¹à¸à¹‰à¹„ขà¸à¸¥à¸¸à¹ˆà¸¡"
+
+#~ msgid "Edit Connections"
+#~ msgstr "à¹à¸à¹‰à¹„ขà¸à¸²à¸£à¹€à¸Šà¸·à¹ˆà¸­à¸¡à¹‚ยง"
+
+#~ msgid "GridMap Paint"
+#~ msgstr "วาด GridMap"
+
+#~ msgid "Areas"
+#~ msgstr "พื้นที่"
+
+#~ msgid "Ctrl+"
+#~ msgstr "Ctrl+"
+
+#~ msgid "Down Wheel)"
+#~ msgstr "ล้อเมาส์ลง)"
+
+#~ msgid "Up Wheel)"
+#~ msgstr "ล้อเมาส์ขึ้น)"
+
#~ msgid "Close scene? (Unsaved changes will be lost)"
#~ msgstr "ปิดไฟล์ฉาà¸? (à¸à¸²à¸£à¹à¸à¹‰à¹„ขที่ไม่ได้บันทึà¸à¸ˆà¸°à¸ªà¸¹à¸à¸«à¸²à¸¢)"
@@ -7940,9 +8126,6 @@ msgstr ""
#~ msgid "Close Goto Prev. Scene"
#~ msgstr "ปิดไปยังฉาà¸à¸à¹ˆà¸­à¸™à¸«à¸™à¹‰à¸²"
-#~ msgid "Expand to Parent"
-#~ msgstr "ขยายให้เต็มโหนดà¹à¸¡à¹ˆ"
-
#~ msgid "Del"
#~ msgstr "ลบ"
@@ -8092,18 +8275,12 @@ msgstr ""
#~ msgid "Save Translatable Strings"
#~ msgstr "บันทึà¸à¸ªà¸•à¸£à¸´à¸‡à¸«à¸¥à¸²à¸¢à¸ à¸²à¸©à¸²"
-#~ msgid "Translatable Strings.."
-#~ msgstr "สตริงหลายภาษา.."
-
#~ msgid "Install Export Templates"
#~ msgstr "ติดตั้งà¹à¸¡à¹ˆà¹à¸šà¸šà¸ªà¹ˆà¸‡à¸­à¸­à¸"
#~ msgid "Edit Script Options"
#~ msgstr "à¹à¸à¹‰à¹„ขตัวเลือà¸à¸ªà¸„ริปต์"
-#~ msgid "Please export outside the project folder!"
-#~ msgstr "à¸à¸£à¸¸à¸“าส่งออà¸à¹„ปนอà¸à¹‚ฟลเดอร์โปรเจà¸à¸•à¹Œ!"
-
#~ msgid "Error exporting project!"
#~ msgstr "ผิดพลาดขณะส่งออà¸à¹‚ปรเจà¸à¸•à¹Œ!"
@@ -8159,9 +8336,6 @@ msgstr ""
#~ msgid "Invalid character in group name!"
#~ msgstr "ใช้อัà¸à¸©à¸£à¸šà¸²à¸‡à¸•à¸±à¸§à¹ƒà¸™à¸Šà¸·à¹ˆà¸­à¸à¸¥à¸¸à¹ˆà¸¡à¹„ม่ได้!"
-#~ msgid "Group name already exists!"
-#~ msgstr "มีชื่อà¸à¸¥à¸¸à¹ˆà¸¡à¸™à¸µà¹‰à¸­à¸¢à¸¹à¹ˆà¹à¸¥à¹‰à¸§!"
-
#~ msgid "Atlas Preview"
#~ msgstr "ตัวอย่าง Atlas"
diff --git a/editor/translations/tr.po b/editor/translations/tr.po
index dd10336bca..afb2c82be1 100644
--- a/editor/translations/tr.po
+++ b/editor/translations/tr.po
@@ -1,5 +1,6 @@
# Turkish translation of the Godot Engine editor
-# Copyright (C) 2016-2017 Juan Linietsky, Ariel Manzur and the Godot community
+# Copyright (C) 2007-2017 Juan Linietsky, Ariel Manzur
+# Copyright (C) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)
# This file is distributed under the same license as the Godot source code.
#
# Aprın Çor Tigin <kabusturk38@gmail.com>, 2016-2017.
@@ -12,7 +13,7 @@
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
-"PO-Revision-Date: 2017-07-19 09:38+0000\n"
+"PO-Revision-Date: 2017-08-29 13:49+0000\n"
"Last-Translator: hubbyist <hub@legrud.net>\n"
"Language-Team: Turkish <https://hosted.weblate.org/projects/godot-engine/"
"godot/tr/>\n"
@@ -20,7 +21,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 2.16-dev\n"
+"X-Generator: Weblate 2.17-dev\n"
#: editor/animation_editor.cpp
msgid "Disabled"
@@ -196,10 +197,9 @@ msgid "Create %d NEW tracks and insert keys?"
msgstr "%d için yeni izler oluştur ve açar gir?"
#: editor/animation_editor.cpp editor/create_dialog.cpp
-#: editor/editor_audio_buses.cpp
+#: editor/editor_audio_buses.cpp editor/plugins/abstract_polygon_2d_editor.cpp
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
#: editor/plugins/mesh_instance_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp editor/project_manager.cpp
#: editor/script_create_dialog.cpp
msgid "Create"
@@ -363,266 +363,6 @@ msgstr "Dizinin türünü degistir"
msgid "Change Array Value"
msgstr "Dizi DeÄŸerini DeÄŸiÅŸtir"
-#: editor/asset_library_editor_plugin.cpp
-msgid "Free"
-msgstr "Özgür"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_plugin_settings.cpp
-msgid "Version:"
-msgstr "Sürüm:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Contents:"
-msgstr "İçerikler:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "View Files"
-msgstr "Dosyaları Görüntüle"
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_help.cpp editor/property_selector.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Description:"
-msgstr "Açıklama:"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-#: editor/project_manager.cpp
-msgid "Install"
-msgstr "Kur"
-
-#: editor/asset_library_editor_plugin.cpp editor/call_dialog.cpp
-#: editor/connections_dialog.cpp editor/export_template_manager.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-#: editor/project_settings_editor.cpp editor/property_editor.cpp
-#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Close"
-msgstr "Kapat"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve hostname:"
-msgstr "Ana makine adı çözümlenemedi:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve."
-msgstr "Çözümlenemedi."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Connection error, please try again."
-msgstr "Bağlantı hatası, lütfen tekrar deneyiniz."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't connect."
-msgstr "Bağlanamadı."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't connect to host:"
-msgstr "Ana makineye bağlanılamadı:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response from host:"
-msgstr "Ana makineden cevap yok:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response."
-msgstr "Cevap yok."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Request failed, return code:"
-msgstr "İstem başarısız, dönen kod:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Req. Failed."
-msgstr "İstem Başarısız."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Request failed, too many redirects"
-msgstr "İstem Başarısız, çok fazla yönlendirme"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Redirect Loop."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Bad download hash, assuming file has been tampered with."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Expected:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Got:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Asset Download Error:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-msgid "Success!"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Fetching:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Resolving.."
-msgstr "Kaydediliyor..."
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Connecting.."
-msgstr "BaÄŸlan..."
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Requesting.."
-msgstr "Deneme"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Error making request"
-msgstr "Kaynak kaydedilirken sorun!"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Idle"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Retry"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Download Error"
-msgstr "Aşağı"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Download for this asset is already in progress!"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "first"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "prev"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "next"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "last"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "All"
-msgstr "Hepsi"
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
-#: editor/settings_config_dialog.cpp
-msgid "Search:"
-msgstr "Ara:"
-
-#: editor/asset_library_editor_plugin.cpp editor/code_editor.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Search"
-msgstr "Ara"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/project_manager.cpp
-msgid "Import"
-msgstr "İçe Aktar"
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Plugins"
-msgstr "Eklentiler"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Sort:"
-msgstr "Sırala:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Reverse"
-msgstr "Tersi"
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Category:"
-msgstr "Katman:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Site:"
-msgstr "Yer:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Support.."
-msgstr "Destek..."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Official"
-msgstr "Resmi"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-msgid "Community"
-msgstr "Topluluk"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Testing"
-msgstr "Deneme"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Assets ZIP File"
-msgstr "Varlıkların ZIP Dizeci"
-
-#: editor/call_dialog.cpp
-msgid "Method List For '%s':"
-msgstr "'%s' İçin Yöntem Dizelgesi:"
-
-#: editor/call_dialog.cpp modules/visual_script/visual_script_editor.cpp
-msgid "Call"
-msgstr "Çağır"
-
-#: editor/call_dialog.cpp
-msgid "Method List:"
-msgstr "Yöntem Dizelgesi:"
-
-#: editor/call_dialog.cpp
-msgid "Arguments:"
-msgstr "DeÄŸiÅŸtirgenler:"
-
-#: editor/call_dialog.cpp
-msgid "Return:"
-msgstr "Döndür:"
-
#: editor/code_editor.cpp
msgid "Go to Line"
msgstr "Dizeye Git"
@@ -660,6 +400,14 @@ msgstr "Tüm Sözcükler"
msgid "Selection Only"
msgstr "Yalnızca Seçim"
+#: editor/code_editor.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
+msgid "Search"
+msgstr "Ara"
+
#: editor/code_editor.cpp editor/editor_help.cpp
msgid "Find"
msgstr "Bul"
@@ -692,11 +440,11 @@ msgstr "DeÄŸiÅŸimi Sor"
msgid "Skip"
msgstr "Geç"
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom In"
msgstr "YaklaÅŸ"
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom Out"
msgstr "Uzaklaştır"
@@ -765,6 +513,20 @@ msgstr "ErtelenmiÅŸ"
msgid "Oneshot"
msgstr "Tek sefer"
+#: editor/connections_dialog.cpp editor/dependency_editor.cpp
+#: editor/export_template_manager.cpp
+#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Close"
+msgstr "Kapat"
+
#: editor/connections_dialog.cpp
msgid "Connect"
msgstr "BaÄŸla"
@@ -790,7 +552,7 @@ msgstr "BaÄŸlan..."
msgid "Disconnect"
msgstr "Bağlantıyı kes"
-#: editor/connections_dialog.cpp editor/node_dock.cpp
+#: editor/connections_dialog.cpp editor/editor_help.cpp editor/node_dock.cpp
msgid "Signals"
msgstr "Ä°ÅŸaretler"
@@ -807,12 +569,25 @@ msgstr "BeÄŸeniler:"
msgid "Recent:"
msgstr "Yakın zamanda:"
+#: editor/create_dialog.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/quick_open.cpp editor/settings_config_dialog.cpp
+msgid "Search:"
+msgstr "Ara:"
+
#: editor/create_dialog.cpp editor/editor_help.cpp
#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/quick_open.cpp
msgid "Matches:"
msgstr "EÅŸleÅŸmeler:"
+#: editor/create_dialog.cpp editor/editor_help.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/property_selector.cpp
+#: editor/script_editor_debugger.cpp
+msgid "Description:"
+msgstr "Açıklama:"
+
#: editor/dependency_editor.cpp
msgid "Search Replacement For:"
msgstr "Şunun İçin Değişikliği Ara:"
@@ -872,6 +647,10 @@ msgid "Owners Of:"
msgstr "Bunun Sahibi:"
#: editor/dependency_editor.cpp
+msgid "Remove selected files from the project? (no undo)"
+msgstr "Seçili dizeçleri tasarıdan kaldır? (Geri alınamaz)"
+
+#: editor/dependency_editor.cpp
msgid ""
"The files being removed are required by other resources in order for them to "
"work.\n"
@@ -881,8 +660,9 @@ msgstr ""
"Yine de kaldırmak istiyor musunuz? (Geri alınamaz)"
#: editor/dependency_editor.cpp
-msgid "Remove selected files from the project? (no undo)"
-msgstr "Seçili dizeçleri tasarıdan kaldır? (Geri alınamaz)"
+#, fuzzy
+msgid "Cannot remove:\n"
+msgstr "Çözümlenemedi."
#: editor/dependency_editor.cpp
msgid "Error loading:"
@@ -945,12 +725,7 @@ msgstr "SaÄŸ olun!"
#: editor/editor_about.cpp
msgid "Godot Engine contributors"
-msgstr ""
-
-#: editor/editor_about.cpp
-#, fuzzy
-msgid "Authors"
-msgstr "Yazar:"
+msgstr "Godot Oyun Motoru katkı sağlayanlar"
#: editor/editor_about.cpp
#, fuzzy
@@ -959,7 +734,7 @@ msgstr "Tasarı Yöneticisi"
#: editor/editor_about.cpp
msgid "Lead Developer"
-msgstr ""
+msgstr "BaÅŸ GeliÅŸtirici"
#: editor/editor_about.cpp editor/project_manager.cpp
msgid "Project Manager"
@@ -967,17 +742,51 @@ msgstr "Tasarı Yöneticisi"
#: editor/editor_about.cpp
msgid "Developers"
+msgstr "GeliÅŸtiriciler"
+
+#: editor/editor_about.cpp
+#, fuzzy
+msgid "Authors"
+msgstr "Yazar:"
+
+#: editor/editor_about.cpp
+msgid "Platinum Sponsors"
msgstr ""
#: editor/editor_about.cpp
-msgid "License"
+msgid "Gold Sponsors"
msgstr ""
#: editor/editor_about.cpp
-msgid "Thirdparty License"
+msgid "Mini Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Gold Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Silver Donors"
msgstr ""
#: editor/editor_about.cpp
+#, fuzzy
+msgid "Bronze Donors"
+msgstr "Aşağıya Eşle"
+
+#: editor/editor_about.cpp
+msgid "Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "License"
+msgstr "Lisans"
+
+#: editor/editor_about.cpp
+msgid "Thirdparty License"
+msgstr "Üçüncü Parti Lisans"
+
+#: editor/editor_about.cpp
msgid ""
"Godot Engine relies on a number of thirdparty free and open source "
"libraries, all compatible with the terms of its MIT license. The following "
@@ -997,7 +806,7 @@ msgstr "İçerikler:"
#: editor/editor_about.cpp
msgid "Licenses"
-msgstr ""
+msgstr "Lisanslar"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Error opening package file, not in zip format."
@@ -1013,13 +822,23 @@ msgid "Package Installed Successfully!"
msgstr "Çıkın Başarı ile Kuruldu!"
#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Success!"
+msgstr "Başarılı!"
+
+#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/project_manager.cpp
+msgid "Install"
+msgstr "Kur"
+
+#: editor/editor_asset_installer.cpp
#, fuzzy
msgid "Package Installer"
msgstr "Çıkın Başarı ile Kuruldu!"
#: editor/editor_audio_buses.cpp
msgid "Speakers"
-msgstr ""
+msgstr "Hoparlörler"
#: editor/editor_audio_buses.cpp
#, fuzzy
@@ -1066,21 +885,21 @@ msgid "Audio Bus, Drag and Drop to rearrange."
msgstr ""
#: editor/editor_audio_buses.cpp
-#, fuzzy
-msgid "Bus options"
-msgstr "Sorun ayıklama seçenekleri"
-
-#: editor/editor_audio_buses.cpp
msgid "Solo"
-msgstr ""
+msgstr "Tekil"
#: editor/editor_audio_buses.cpp
msgid "Mute"
-msgstr ""
+msgstr "Sessiz"
#: editor/editor_audio_buses.cpp
msgid "Bypass"
-msgstr ""
+msgstr "Dolan"
+
+#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Bus options"
+msgstr "Sorun ayıklama seçenekleri"
#: editor/editor_audio_buses.cpp editor/plugins/tile_map_editor_plugin.cpp
#: editor/scene_tree_dock.cpp
@@ -1089,6 +908,11 @@ msgstr "Ä°kile"
#: editor/editor_audio_buses.cpp
#, fuzzy
+msgid "Reset Volume"
+msgstr "Yaklaşmayı Sıfırla"
+
+#: editor/editor_audio_buses.cpp
+#, fuzzy
msgid "Delete Effect"
msgstr "Seçilenleri Sil"
@@ -1113,6 +937,11 @@ msgstr "Canlandırmayı İkile"
#: editor/editor_audio_buses.cpp
#, fuzzy
+msgid "Reset Bus Volume"
+msgstr "Yaklaşmayı Sıfırla"
+
+#: editor/editor_audio_buses.cpp
+#, fuzzy
msgid "Move Audio Bus"
msgstr "Eylemi Taşı"
@@ -1149,7 +978,8 @@ msgstr "Ekle %s"
msgid "Create a new Bus Layout."
msgstr "Yeni Kaynak OluÅŸtur"
-#: editor/editor_audio_buses.cpp editor/script_create_dialog.cpp
+#: editor/editor_audio_buses.cpp editor/property_editor.cpp
+#: editor/script_create_dialog.cpp
msgid "Load"
msgstr "Yükle"
@@ -1241,7 +1071,7 @@ msgid "Rearrange Autoloads"
msgstr "KendindenYüklenme'leri Yeniden Sırala"
#: editor/editor_autoload_settings.cpp editor/editor_file_dialog.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp scene/gui/file_dialog.cpp
+#: scene/gui/file_dialog.cpp
msgid "Path:"
msgstr "Dizeç yolu:"
@@ -1249,9 +1079,7 @@ msgstr "Dizeç yolu:"
msgid "Node Name:"
msgstr "Düğüm adı:"
-#: editor/editor_autoload_settings.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp editor/project_manager.cpp
+#: editor/editor_autoload_settings.cpp editor/project_manager.cpp
msgid "Name"
msgstr "Ad"
@@ -1285,18 +1113,19 @@ msgid "Choose a Directory"
msgstr "Dizin Seç"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Create Folder"
msgstr "Dizin OluÅŸtur"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: editor/editor_plugin_settings.cpp editor/plugins/theme_editor_plugin.cpp
-#: editor/project_export.cpp scene/gui/file_dialog.cpp
+#: editor/editor_plugin_settings.cpp editor/filesystem_dock.cpp
+#: editor/plugins/theme_editor_plugin.cpp editor/project_export.cpp
+#: scene/gui/file_dialog.cpp
msgid "Name:"
msgstr "Ad:"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Could not create folder."
msgstr "Dizin oluşturulamadı."
@@ -1314,31 +1143,7 @@ msgstr "Çıkınla"
#: editor/editor_export.cpp platform/javascript/export/export.cpp
msgid "Template file not found:\n"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Added:"
-msgstr "Eklenen:"
-
-#: editor/editor_export.cpp
-msgid "Removed:"
-msgstr "Silinen:"
-
-#: editor/editor_export.cpp
-msgid "Error saving atlas:"
-msgstr "Atlas kaydedilirken sorun oluÅŸtu:"
-
-#: editor/editor_export.cpp
-msgid "Could not save atlas subtexture:"
-msgstr "Atlas alt dokusu kaydedilemedi:"
-
-#: editor/editor_export.cpp
-msgid "Exporting for %s"
-msgstr "%s için Dışa Aktarım"
-
-#: editor/editor_export.cpp
-msgid "Setting Up.."
-msgstr "Kurulum..."
+msgstr "Biçem dosyası bulunamadı:\n"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "File Exists, Overwrite?"
@@ -1424,6 +1229,11 @@ msgstr "Beğenileni Yukarı Taşı"
msgid "Move Favorite Down"
msgstr "Beğenileni Aşağı Taşı"
+#: editor/editor_file_dialog.cpp
+#, fuzzy
+msgid "Go to parent folder"
+msgstr "Dizin oluşturulamadı."
+
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Directories & Files:"
msgstr "Dizinler & Dizeçler:"
@@ -1438,10 +1248,6 @@ msgid "File:"
msgstr "Dizeç:"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
-msgid "Filter:"
-msgstr "Süzgeç:"
-
-#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Must use a valid extension."
msgstr "Gecerli bir uzantı kullanılmalı."
@@ -1467,6 +1273,10 @@ msgstr "Bölüt Dizelgesi:"
msgid "Search Classes"
msgstr "Bölütleri Ara"
+#: editor/editor_help.cpp editor/plugins/spatial_editor_plugin.cpp
+msgid "Top"
+msgstr "Ãœst"
+
#: editor/editor_help.cpp editor/property_editor.cpp
msgid "Class:"
msgstr "Bölüt:"
@@ -1483,15 +1293,30 @@ msgstr "Tarafından kalıt alındı:"
msgid "Brief Description:"
msgstr "Kısa Açıklama:"
+#: editor/editor_help.cpp
+#, fuzzy
+msgid "Members"
+msgstr "Ãœyeler:"
+
#: editor/editor_help.cpp modules/visual_script/visual_script_editor.cpp
msgid "Members:"
msgstr "Ãœyeler:"
#: editor/editor_help.cpp
+#, fuzzy
+msgid "Public Methods"
+msgstr "Açık Yöntemler:"
+
+#: editor/editor_help.cpp
msgid "Public Methods:"
msgstr "Açık Yöntemler:"
#: editor/editor_help.cpp
+#, fuzzy
+msgid "GUI Theme Items"
+msgstr "Arayüz Kalıbı Öğeleri:"
+
+#: editor/editor_help.cpp
msgid "GUI Theme Items:"
msgstr "Arayüz Kalıbı Öğeleri:"
@@ -1501,26 +1326,63 @@ msgstr "Ä°ÅŸaretler:"
#: editor/editor_help.cpp
#, fuzzy
+msgid "Enumerations"
+msgstr "Canlandırmalar"
+
+#: editor/editor_help.cpp
+#, fuzzy
msgid "Enumerations:"
msgstr "Canlandırmalar"
#: editor/editor_help.cpp
msgid "enum "
-msgstr ""
+msgstr "enum… "
+
+#: editor/editor_help.cpp
+#, fuzzy
+msgid "Constants"
+msgstr "Sabitler:"
#: editor/editor_help.cpp
msgid "Constants:"
msgstr "Sabitler:"
#: editor/editor_help.cpp
+#, fuzzy
+msgid "Description"
+msgstr "Açıklama:"
+
+#: editor/editor_help.cpp
+#, fuzzy
+msgid "Properties"
+msgstr "Özellikleri:"
+
+#: editor/editor_help.cpp
msgid "Property Description:"
msgstr "Özellik Açıklaması:"
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this property. Please help us by "
+"[color=$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+
+#: editor/editor_help.cpp
+#, fuzzy
+msgid "Methods"
+msgstr "Yöntem Dizelgesi:"
+
+#: editor/editor_help.cpp
msgid "Method Description:"
msgstr "Yöntem Açıklaması:"
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this method. Please help us by [color="
+"$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Search Text"
msgstr "Yazı Ara"
@@ -1530,24 +1392,21 @@ msgid "Output:"
msgstr " Çıktı:"
#: editor/editor_log.cpp editor/plugins/animation_tree_editor_plugin.cpp
-#: editor/plugins/rich_text_editor_plugin.cpp editor/property_editor.cpp
-#: editor/script_editor_debugger.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/property_editor.cpp editor/script_editor_debugger.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Clear"
msgstr "Temizle"
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Error saving resource!"
msgstr "Kaynak kaydedilirken sorun!"
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Save Resource As.."
msgstr "Kaynağı Başkaca Kaydet.."
-#: editor/editor_node.cpp editor/export_template_manager.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "I see.."
msgstr "Anlıyorum.."
@@ -1564,6 +1423,30 @@ msgid "Error while saving."
msgstr "Kaydedilirken sorun oluÅŸtu."
#: editor/editor_node.cpp
+#, fuzzy
+msgid "Can't open '%s'."
+msgstr "'..' üzerinde çalışılamıyor"
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Error while parsing '%s'."
+msgstr "Kaydedilirken sorun oluÅŸtu."
+
+#: editor/editor_node.cpp
+msgid "Unexpected end of file '%s'."
+msgstr ""
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Missing '%s' or its dependencies."
+msgstr "Sahne '%s' bağımlılıkları koptu:"
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Error while loading '%s'."
+msgstr "Kaydedilirken sorun oluÅŸtu."
+
+#: editor/editor_node.cpp
msgid "Saving Scene"
msgstr "Sahne Kaydediliyor"
@@ -1622,6 +1505,33 @@ msgid "Restored default layout to base settings."
msgstr "Önyüklü tasarım temel ayarlara onarıldı."
#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was imported, so it's not editable.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was instanced or inherited.\n"
+"Changes to it will not be kept when saving the current scene."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource was imported, so it's not editable. Change its settings in the "
+"import panel and then re-import."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This scene was imported, so changes to it will not be kept.\n"
+"Instancing it or inheriting will allow making changes to it.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Copy Params"
msgstr "Değişkenleri Tıpkıla"
@@ -1798,23 +1708,35 @@ msgid "Save changes the following scene(s) before opening Project Manager?"
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"This option is deprecated. Situations where refresh must be forced are now "
+"considered a bug. Please report."
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Pick a Main Scene"
msgstr "Bir Ana Sahne Seç"
#: editor/editor_node.cpp
-msgid "Unable to enable addon plugin at: '"
+msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr ""
#: editor/editor_node.cpp
-msgid "' parsing of config failed."
+msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/"
+#, fuzzy
+msgid "Unable to load addon script from path: '%s'."
+msgstr "Yazı tipi %s yüklerken sorun oluştu"
+
+#: editor/editor_node.cpp
+msgid ""
+"Unable to load addon script from path: '%s' Base type is not EditorPlugin."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to load addon script from path: '"
+msgid "Unable to load addon script from path: '%s' Script is not in tool mode."
msgstr ""
#: editor/editor_node.cpp
@@ -1824,7 +1746,7 @@ msgid ""
msgstr ""
#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/scene_tree_dock.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Ugh"
msgstr "Öff"
@@ -1838,14 +1760,15 @@ msgstr ""
"kaydedin."
#: editor/editor_node.cpp
-msgid "Error loading scene."
-msgstr "Sahne yüklenirken sorun oluştu."
-
-#: editor/editor_node.cpp
msgid "Scene '%s' has broken dependencies:"
msgstr "Sahne '%s' bağımlılıkları koptu:"
#: editor/editor_node.cpp
+#, fuzzy
+msgid "Clear Recent Scenes"
+msgstr "Kemikleri Temizle"
+
+#: editor/editor_node.cpp
msgid "Save Layout"
msgstr "Tasarımı Kaydet"
@@ -1879,7 +1802,7 @@ msgstr "Dikkat Dağıtmayan Biçim"
msgid "Toggle distraction-free mode."
msgstr "Dikkat Dağıtmayan Biçim"
-#: editor/editor_node.cpp editor/io_plugins/editor_scene_import_plugin.cpp
+#: editor/editor_node.cpp
msgid "Scene"
msgstr "Sahne"
@@ -2122,6 +2045,10 @@ msgstr ""
msgid "Issue Tracker"
msgstr ""
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+msgid "Community"
+msgstr "Topluluk"
+
#: editor/editor_node.cpp
msgid "About"
msgstr "Ä°liÅŸkin"
@@ -2130,7 +2057,7 @@ msgstr "Ä°liÅŸkin"
msgid "Play the project."
msgstr "Tasarıyı oynat."
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Play"
msgstr "Oynat"
@@ -2146,7 +2073,7 @@ msgstr "Sahneyi Duraklat"
msgid "Stop the scene."
msgstr "Sahneyi durdur."
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Stop"
msgstr "Durdur"
@@ -2219,6 +2146,16 @@ msgid "Object properties."
msgstr "Nesne özellikleri."
#: editor/editor_node.cpp
+#, fuzzy
+msgid "Changes may be lost!"
+msgstr "Bediz Öbeğini Değiştir"
+
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Import"
+msgstr "İçe Aktar"
+
+#: editor/editor_node.cpp
msgid "FileSystem"
msgstr "DizeçDüzeni"
@@ -2234,14 +2171,6 @@ msgstr "Çıktı"
msgid "Don't Save"
msgstr ""
-#: editor/editor_node.cpp editor/editor_reimport_dialog.cpp
-msgid "Re-Import"
-msgstr "Yeniden İçe Aktar"
-
-#: editor/editor_node.cpp editor/editor_plugin_settings.cpp
-msgid "Update"
-msgstr "Güncelle"
-
#: editor/editor_node.cpp
msgid "Import Templates From ZIP File"
msgstr "Kalıpları ZIP Dizecinden İçe Aktar"
@@ -2309,11 +2238,29 @@ msgstr "Düzenleyicide Aç"
msgid "Open the previous Editor"
msgstr "Düzenleyicide Aç"
+#: editor/editor_plugin.cpp
+#, fuzzy
+msgid "Creating Mesh Previews"
+msgstr "Örüntü Betikevi Oluştur"
+
+#: editor/editor_plugin.cpp
+msgid "Thumbnail.."
+msgstr "Küçük Bediz.."
+
#: editor/editor_plugin_settings.cpp
msgid "Installed Plugins:"
msgstr "Yüklü Eklentiler:"
#: editor/editor_plugin_settings.cpp
+msgid "Update"
+msgstr "Güncelle"
+
+#: editor/editor_plugin_settings.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Version:"
+msgstr "Sürüm:"
+
+#: editor/editor_plugin_settings.cpp
msgid "Author:"
msgstr "Yazar:"
@@ -2346,7 +2293,8 @@ msgid "Frame %"
msgstr "Kare %"
#: editor/editor_profiler.cpp
-msgid "Fixed Frame %"
+#, fuzzy
+msgid "Physics Frame %"
msgstr "Sabit Kare %"
#: editor/editor_profiler.cpp editor/script_editor_debugger.cpp
@@ -2365,26 +2313,6 @@ msgstr "Kendi"
msgid "Frame #:"
msgstr "Kare #:"
-#: editor/editor_reimport_dialog.cpp
-msgid "Please wait for scan to complete."
-msgstr "Tarama için bitmesini bekleyin."
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Current scene must be saved to re-import."
-msgstr "Yeniden içe aktarmak için şu anki sahneyi kaydet."
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Save & Re-Import"
-msgstr "Kaydet & Yeniden İçe Aktar"
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Importing"
-msgstr "Yeniden-İçe Aktarım"
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Import Changed Resources"
-msgstr "Değiştirilmiş Kaynakları Yeniden İçe Aktar"
-
#: editor/editor_run_native.cpp
msgid "Select device from the list"
msgstr ""
@@ -2501,10 +2429,6 @@ msgid "Importing:"
msgstr "İçe Aktarım:"
#: editor/export_template_manager.cpp
-msgid "Loading Export Templates"
-msgstr "Dışa Aktarım Kalıpları Yükleniyor"
-
-#: editor/export_template_manager.cpp
#, fuzzy
msgid "Current Version:"
msgstr "Åžu anki Sahne"
@@ -2545,11 +2469,18 @@ msgid "Cannot navigate to '"
msgstr ""
#: editor/filesystem_dock.cpp
-#, fuzzy
+msgid "View items as a grid of thumbnails"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "View items as a list"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
msgid ""
"\n"
-"Status: Needs Re-Import"
-msgstr "Kaydet & Yeniden İçe Aktar"
+"Status: Import of file failed. Please fix file and reimport manually."
+msgstr ""
#: editor/filesystem_dock.cpp
#, fuzzy
@@ -2559,46 +2490,57 @@ msgid ""
msgstr "Kaynak:"
#: editor/filesystem_dock.cpp
-msgid "Same source and destination files, doing nothing."
-msgstr "Özdeş kaynak ve varış dizeçleri, hiçbir şey yapılmıyor."
+#, fuzzy
+msgid "Cannot move/rename resources root."
+msgstr "Kaynak yazı tipi yüklenemiyor / işlenemiyor."
#: editor/filesystem_dock.cpp
-msgid "Target file exists, can't overwrite. Delete first."
-msgstr ""
+#, fuzzy
+msgid "Cannot move a folder into itself.\n"
+msgstr "Bir dizeç kendisi üzerine içe aktaramıyor:"
+
+#: editor/filesystem_dock.cpp
+#, fuzzy
+msgid "Error moving:\n"
+msgstr "İçe aktarırken sorun:"
#: editor/filesystem_dock.cpp
-msgid "Same source and destination paths, doing nothing."
-msgstr "Özdeş kaynak ve varış yolları, hiçbir şey yapılmıyor."
+#, fuzzy
+msgid "Unable to update dependencies:\n"
+msgstr "Sahne '%s' bağımlılıkları koptu:"
#: editor/filesystem_dock.cpp
-msgid "Can't move directories to within themselves."
-msgstr "Dizinleri kendi içlerine taşıyamazsınız."
+msgid "No name provided"
+msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Can't rename deps for:\n"
+msgid "Provided name contains invalid characters"
msgstr ""
#: editor/filesystem_dock.cpp
#, fuzzy
-msgid "Error moving file:\n"
-msgstr "Bediz yüklenirken sorun oluştu:"
+msgid "No name provided."
+msgstr "Yeniden Adlandır ya da Taşı.."
#: editor/filesystem_dock.cpp
#, fuzzy
-msgid "Error moving dir:\n"
-msgstr "İçe aktarırken sorun:"
+msgid "Name contains invalid characters."
+msgstr "Geçerli damgalar:"
#: editor/filesystem_dock.cpp
-msgid "Can't operate on '..'"
-msgstr "'..' üzerinde çalışılamıyor"
+#, fuzzy
+msgid "A file or folder with this name already exists."
+msgstr "Öbek adı zaten var!"
#: editor/filesystem_dock.cpp
-msgid "Pick New Name and Location For:"
-msgstr "Şunun için yeni ad ile konum seçin:"
+#, fuzzy
+msgid "Renaming file:"
+msgstr "Değişkeni Yeniden Adlandır"
#: editor/filesystem_dock.cpp
-msgid "No files selected!"
-msgstr "Hiçbir Dizeç Seçilmedi!"
+#, fuzzy
+msgid "Renaming folder:"
+msgstr "Düğümü Yeniden Adlandır"
#: editor/filesystem_dock.cpp
#, fuzzy
@@ -2610,40 +2552,38 @@ msgid "Collapse all"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Show In File Manager"
-msgstr "Dizeç Yöneticisinde Göster"
-
-#: editor/filesystem_dock.cpp
-msgid "Instance"
-msgstr "Örnek"
+msgid "Copy Path"
+msgstr "Dizeç Yolunu Tıpkıla"
#: editor/filesystem_dock.cpp
-msgid "Edit Dependencies.."
-msgstr "Bağımlılıkları Düzenle.."
+#, fuzzy
+msgid "Rename.."
+msgstr "Yeniden Adlandır"
#: editor/filesystem_dock.cpp
-msgid "View Owners.."
-msgstr "Sahipleri Görüntüle.."
+msgid "Move To.."
+msgstr "Şuraya Taşı.."
#: editor/filesystem_dock.cpp
-msgid "Copy Path"
-msgstr "Dizeç Yolunu Tıpkıla"
+#, fuzzy
+msgid "New Folder.."
+msgstr "Dizin OluÅŸtur"
#: editor/filesystem_dock.cpp
-msgid "Rename or Move.."
-msgstr "Yeniden Adlandır ya da Taşı.."
+msgid "Show In File Manager"
+msgstr "Dizeç Yöneticisinde Göster"
#: editor/filesystem_dock.cpp
-msgid "Move To.."
-msgstr "Şuraya Taşı.."
+msgid "Instance"
+msgstr "Örnek"
#: editor/filesystem_dock.cpp
-msgid "Info"
-msgstr "Bilgi"
+msgid "Edit Dependencies.."
+msgstr "Bağımlılıkları Düzenle.."
#: editor/filesystem_dock.cpp
-msgid "Re-Import.."
-msgstr "Yeniden İçe Aktar.."
+msgid "View Owners.."
+msgstr "Sahipleri Görüntüle.."
#: editor/filesystem_dock.cpp
msgid "Previous Directory"
@@ -2675,6 +2615,11 @@ msgstr ""
msgid "Move"
msgstr "Taşı"
+#: editor/filesystem_dock.cpp editor/plugins/animation_tree_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Rename"
+msgstr "Yeniden Adlandır"
+
#: editor/groups_editor.cpp
msgid "Add to Group"
msgstr "Öbeğe Ekle"
@@ -2689,6 +2634,11 @@ msgid "Import as Single Scene"
msgstr "Sahneyi İçe Aktarıyor..."
#: editor/import/resource_importer_scene.cpp
+#, fuzzy
+msgid "Import with Separate Animations"
+msgstr "Canlandırmaları İçe Aktar.."
+
+#: editor/import/resource_importer_scene.cpp
msgid "Import with Separate Materials"
msgstr ""
@@ -2701,6 +2651,18 @@ msgid "Import with Separate Objects+Materials"
msgstr ""
#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Materials+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Materials+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
#, fuzzy
msgid "Import as Multiple Scenes"
msgstr "3B Sahneyi İçe Aktar"
@@ -2710,40 +2672,33 @@ msgid "Import as Multiple Scenes+Materials"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Import Scene"
msgstr "Sahneyi İçe Aktar"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Importing Scene.."
msgstr "Sahneyi İçe Aktarıyor..."
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Running Custom Script.."
msgstr "Çalışan Özel Betik.."
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Couldn't load post-import script:"
msgstr "İçe aktarma sonrası betik dizeci yüklenemedi:"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Invalid/broken script for post-import (check console):"
msgstr ""
"İçe aktarma işlemi sonrası için geçersiz/bozuk betik dizeci (konsolu "
"denetleyin):"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Error running post-import script:"
msgstr "İçe aktarma sonrası betik dizeci çalıştırılırken sorun oluştu:"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Saving.."
msgstr "Kaydediliyor..."
@@ -2774,588 +2729,56 @@ msgstr "Ön ayar.."
msgid "Reimport"
msgstr "Yeniden İçe Aktar"
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "No bit masks to import!"
-msgstr "Alınacak hiç bit örteci yok!"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path is empty."
-msgstr "Amaçlanan dizeç yolu boş."
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must be a complete resource path."
-msgstr "Amaçlanan yol, tam bir kaynak yolu olmalıdır."
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must exist."
-msgstr "Amaçlanan dizeç yolu var olmalı."
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Save path is empty!"
-msgstr "Kayıt yolu boş!"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Import BitMasks"
-msgstr "BitMasks İçe Aktar"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s):"
-msgstr "Kaynak Doku(lar):"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Target Path:"
-msgstr "Amaçlanan Dizeç Yolu :"
+#: editor/multi_node_edit.cpp
+msgid "MultiNode Set"
+msgstr "MultiNode Kur"
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Accept"
-msgstr "Kabul"
+#: editor/node_dock.cpp
+msgid "Groups"
+msgstr "Öbekler"
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Bit Mask"
-msgstr "Bit Örteci"
+#: editor/node_dock.cpp
+msgid "Select a Node to edit Signals and Groups."
+msgstr "İşaretleri ve Öbekleri düzenlemek için bir Düğüm seçin."
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No source font file!"
-msgstr "Kaynak yazı türü dizeci yok!"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create Poly"
+msgstr "Çoklu Oluşturun"
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No target font resource!"
-msgstr "Amaçlanan yazı türü kaynağı yok!"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly"
+msgstr "Çokluyu Düzenleyin"
-#: editor/io_plugins/editor_font_import_plugin.cpp
+#: editor/plugins/abstract_polygon_2d_editor.cpp
#, fuzzy
-msgid ""
-"Invalid file extension.\n"
-"Please use .font."
-msgstr ""
-"Geçersiz dizeç uzantısı.\n"
-"Lütfen .fnt uzantısını kullanın."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Can't load/process source font."
-msgstr "Kaynak yazı tipi yüklenemiyor / işlenemiyor."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Couldn't save font."
-msgstr "Yazı türü kaydedilemedi."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font:"
-msgstr "Yazı Türü Kaynağı:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font Size:"
-msgstr "Kaynak Yazı Türü Boyutu:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Dest Resource:"
-msgstr "Varış Kaynağı:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "The quick brown fox jumps over the lazy dog."
-msgstr "Hızlı kahverengi tilki üşengeç köpeğin üstünden atlar."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Test:"
-msgstr "Deneme:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Options:"
-msgstr "Seçenekler:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Font Import"
-msgstr "Yazı Türü İçe Aktar"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"This file is already a Godot font file, please supply a BMFont type file "
-"instead."
-msgstr ""
-"Bu dizeç zaten bir Godot yazı türü dizecidir , lütfen bunun yerine bir "
-"BMFont türü dizeci sağlayın."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Failed opening as BMFont file."
-msgstr "BMFont dizeci olarak açma başarısız oldu."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error initializing FreeType."
-msgstr "FreeType başlatılırken sorun oluştu."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Unknown font format."
-msgstr "Bilinmeyen yazı türü."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error loading font."
-msgstr "Yazı türü yüklerken sorun oluştu."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Invalid font size."
-msgstr "Geçersiz yazı türü boyutu."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Invalid font custom source."
-msgstr "Geçersiz yazı türü özel kaynağı."
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/plugins/theme_editor_plugin.cpp
-msgid "Font"
-msgstr "Yazı Tipi"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "No meshes to import!"
-msgstr "İçe aktarılacak örüntü yok!"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Single Mesh Import"
-msgstr "Tekil Örüntü İçe Aktar"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Source Mesh(es):"
-msgstr "Kaynak Örüntü(leri):"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/plugins/mesh_instance_editor_plugin.cpp
-msgid "Mesh"
-msgstr "Örüntü"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Surface %d"
-msgstr "Yüzey %d"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "No samples to import!"
-msgstr "Alınacak örnek yok!"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Import Audio Samples"
-msgstr "Ses Örneklerini İçe Aktar"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Source Sample(s):"
-msgstr "Kaynak Örnek(leri):"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Audio Sample"
-msgstr "Ses Örneği"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "New Clip"
-msgstr "Yeni Parça"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Animation Options"
-msgstr "Canlandırma Seçenekleri"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Flags"
-msgstr "Bayraklar"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Bake FPS:"
-msgstr "FPS'i PiÅŸir:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Optimizer"
-msgstr "Ä°yileÅŸtirici"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Linear Error"
-msgstr "En üst Doğrusal Sorun"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angular Error"
-msgstr "En üst Açısal Sorun"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angle"
-msgstr "En üst Açı"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Clips"
-msgstr "Parçalar"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Start(s)"
-msgstr "Başlangıç(lar)"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "End(s)"
-msgstr "Son(lar)"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Loop"
-msgstr "Döngü"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Filters"
-msgstr "Süzgeçler"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source path is empty."
-msgstr "Kaynak yol boÅŸ."
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't load post-import script."
-msgstr "İçe aktarma sonrası betik dizeci yüklenemedi."
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Invalid/broken script for post-import."
-msgstr "İçe aktarma sonrası için geçersiz/bozuk betik dizeci."
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Error importing scene."
-msgstr "İçe aktarırken sorun oluştu."
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import 3D Scene"
-msgstr "3B Sahneyi İçe Aktar"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source Scene:"
-msgstr "Kaynak Sahne:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Same as Target Scene"
-msgstr "Hedef Sahne ile Aynı"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Shared"
-msgstr "Paylaşılan"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Target Texture Folder:"
-msgstr "Amaçlanan Doku Dizini:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Post-Process Script:"
-msgstr "İşlem Sonrası Betik Dizeci:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Custom Root Node Type:"
-msgstr "Özel Kök Düğüm Türü:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Auto"
-msgstr "KendiliÄŸinden"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Root Node Name:"
-msgstr "Kök Düğüm adı:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "The Following Files are Missing:"
-msgstr "Aşağıdaki Dizeçler Eksik:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Anyway"
-msgstr "Yine de İçe Aktar"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp scene/gui/dialogs.cpp
-msgid "Cancel"
-msgstr "Vazgeç"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import & Open"
-msgstr "İçe Aktar & Aç"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Edited scene has not been saved, open imported scene anyway?"
-msgstr "Düzenlenen sahne kaydedilmedi, yine de içe aktarılan sahne açılsın mı?"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Image:"
-msgstr "Bedizi İçe Aktar:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Can't import a file over itself:"
-msgstr "Bir dizeç kendisi üzerine içe aktaramıyor:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't localize path: %s (already local)"
-msgstr "Yol yerelleÅŸtirilemedi: %s (zaten yerel)"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "3D Scene Animation"
-msgstr "3B Sahne Canlandırması"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Uncompressed"
-msgstr "Sıkıştırılmamış"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossless (PNG)"
-msgstr "Kayıpsız Sıkıştırma (PNG)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossy (WebP)"
-msgstr "Kayıplı Sıkıştırma (WebP)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress (VRAM)"
-msgstr "Sıkıştır (VRAM)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Format"
-msgstr "Doku Biçemi"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Compression Quality (WebP):"
-msgstr "Doku Sıkıştırma Niteliği (WebP):"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Options"
-msgstr "Doku Seçenekleri"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Please specify some files!"
-msgstr "Lütfen bazı dizeçleri belirtin!"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "At least one file needed for Atlas."
-msgstr "Atlas için en az bir dizeç gerekli."
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Error importing:"
-msgstr "İçe aktarırken sorun:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Only one file is required for large texture."
-msgstr "Büyük doku için yalnızca bir dizeç gereklidir."
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Max Texture Size:"
-msgstr "En üst Doku Boyutu:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for Atlas (2D)"
-msgstr "Dokuları Atlas(2B) için içe aktar"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cell Size:"
-msgstr "Odacık Boyutu:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Large Texture"
-msgstr "GeniÅŸ Doku"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Textures (2D)"
-msgstr "Büyük Boyutlu(2D) Dokuları İçe Aktar"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture"
-msgstr "Kaynak Doku"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Base Atlas Texture"
-msgstr "Temel Atlas Doku"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s)"
-msgstr "Kaynak Doku(lar)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 2D"
-msgstr "2B için Dokuları İçe Aktar"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 3D"
-msgstr "3B için Dokuları İçe Aktar"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures"
-msgstr "Dokuları İçe Aktar"
+msgid "Insert Point"
+msgstr "Girdileme"
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "2D Texture"
-msgstr "2B Doku"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly (Remove Point)"
+msgstr "Çokluyu Düzenleyin (Noktayı Silin)"
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "3D Texture"
-msgstr "3B Doku"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Remove Poly And Point"
+msgstr "Çokluyu ve Noktayı Kaldır"
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Atlas Texture"
-msgstr "Atlas Doku"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create a new polygon from scratch."
+msgstr "Sıfırdan yeni bir çokgen oluşturun."
-#: editor/io_plugins/editor_texture_import_plugin.cpp
+#: editor/plugins/abstract_polygon_2d_editor.cpp
msgid ""
-"NOTICE: Importing 2D textures is not mandatory. Just copy png/jpg files to "
-"the project."
+"Edit existing polygon:\n"
+"LMB: Move Point.\n"
+"Ctrl+LMB: Split Segment.\n"
+"RMB: Erase Point."
msgstr ""
-"UYARI: 2B dokuların içe aktarılması zorunlu değildir. Png / jpg dizeçlerini "
-"tasarıya tıpkılamanız yeterlidir."
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Crop empty space."
-msgstr "Boş alanı kırp."
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture"
-msgstr "Doku"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Texture"
-msgstr "Büyük Dokuyu İçe Aktar"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Load Source Image"
-msgstr "Kaynak Bedizi Yükle"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Slicing"
-msgstr "Dilimleme"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Inserting"
-msgstr "Girdileme"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Saving"
-msgstr "Kaydediyor"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save large texture:"
-msgstr "Büyük doku kaydedilemedi:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Build Atlas For:"
-msgstr "Atlası Şunun için Oluştur:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Loading Image:"
-msgstr "Bediz Yükleniyor:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't load image:"
-msgstr "Bediz yüklenemedi:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Converting Images"
-msgstr "Bedizleri Dönüştürüyor"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cropping Images"
-msgstr "Bedizleri Kırpıyor"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Blitting Images"
-msgstr "Bedizleri Blitle"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save atlas image:"
-msgstr "Atlas bedizi kaydedilemedi:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save converted texture:"
-msgstr "Dönüştürülmüş doku kaydedilemedi:"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid source!"
-msgstr "Geçersiz kaynak!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid translation source!"
-msgstr "Geçersiz çeviri kaynağı!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Column"
-msgstr "Dikeç"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/script_create_dialog.cpp
-msgid "Language"
-msgstr "Dil"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No items to import!"
-msgstr "Alınacak öğe yok!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No target path!"
-msgstr "Amaçlanan yol yok!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translations"
-msgstr "Çevirileri İçe Aktar"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Couldn't import!"
-msgstr "Alınamadı!"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translation"
-msgstr "Çeviriyi İçe Aktar"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Source CSV:"
-msgstr "Kaynak CSV:"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Ignore First Row"
-msgstr "İlk Sırayı Yoksay"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Compress"
-msgstr "Sıkıştır"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#, fuzzy
-msgid "Add to Project (project.godot)"
-msgstr "Tasarıya Ekle (engine.cfg)"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Languages:"
-msgstr "Dilleri İçe Aktar:"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Translation"
-msgstr "Çeviri"
-
-#: editor/multi_node_edit.cpp
-msgid "MultiNode Set"
-msgstr "MultiNode Kur"
-
-#: editor/node_dock.cpp
-msgid "Groups"
-msgstr "Öbekler"
-
-#: editor/node_dock.cpp
-msgid "Select a Node to edit Signals and Groups."
-msgstr "İşaretleri ve Öbekleri düzenlemek için bir Düğüm seçin."
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Toggle Autoplay"
@@ -3511,7 +2934,6 @@ msgstr "Canlandırma Adı:"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
#: editor/script_create_dialog.cpp
msgid "Error!"
@@ -3622,10 +3044,6 @@ msgid "Delete Input"
msgstr "GiriÅŸi Sil"
#: editor/plugins/animation_tree_editor_plugin.cpp
-msgid "Rename"
-msgstr "Yeniden Adlandır"
-
-#: editor/plugins/animation_tree_editor_plugin.cpp
msgid "Animation tree is valid."
msgstr "Canlandırma ağacı geçerlidir."
@@ -3681,64 +3099,185 @@ msgstr "Düğüm Süzgeçlerini Düzenle"
msgid "Filters.."
msgstr "Süzgeçler..."
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing %d Triangles:"
-msgstr "%d Üçgenlerini Ayrıştırma:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Free"
+msgstr "Özgür"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Triangle #"
-msgstr "Üçgen #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Contents:"
+msgstr "İçerikler:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Light Baker Setup:"
-msgstr "Işık Pişirici Kurulumu:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "View Files"
+msgstr "Dosyaları Görüntüle"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing Geometry"
-msgstr "Uzambilgisini Ayrıştırıyor"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve hostname:"
+msgstr "Ana makine adı çözümlenemedi:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Fixing Lights"
-msgstr "Işıkları Sabitliyor"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve."
+msgstr "Çözümlenemedi."
-#: editor/plugins/baked_light_baker.cpp
-msgid "Making BVH"
-msgstr "BVH Yapıyor"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connection error, please try again."
+msgstr "Bağlantı hatası, lütfen tekrar deneyiniz."
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Light Octree"
-msgstr "Işık Sekağacı Oluşturuyor"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't connect."
+msgstr "Bağlanamadı."
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Octree Texture"
-msgstr "Sekağaç Dokusu Oluşturuyor"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't connect to host:"
+msgstr "Ana makineye bağlanılamadı:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Transfer to Lightmaps:"
-msgstr "Işık Haritalarına Aktar:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response from host:"
+msgstr "Ana makineden cevap yok:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Allocating Texture #"
-msgstr "Doku Paylaşımı #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response."
+msgstr "Cevap yok."
-#: editor/plugins/baked_light_baker.cpp
-msgid "Baking Triangle #"
-msgstr "Pişirme Üçgeni #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, return code:"
+msgstr "İstem başarısız, dönen kod:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Post-Processing Texture #"
-msgstr "İşleme-Sonrası Dokusu #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Req. Failed."
+msgstr "İstem Başarısız."
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Bake!"
-msgstr "PiÅŸir!"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, too many redirects"
+msgstr "İstem Başarısız, çok fazla yönlendirme"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Redirect Loop."
+msgstr "Yönlendirme Döngüsü."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed:"
+msgstr "Başarısız:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Bad download hash, assuming file has been tampered with."
+msgstr ""
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Reset the lightmap octree baking process (start over)."
-msgstr "Işık haritası sekağacı pişirme işlemini sıfırlayın (baştan başlayın)."
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Expected:"
+msgstr "Beklenen:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Got:"
+msgstr "Alınan:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed sha256 hash check"
+msgstr "Başarısız sha256 hash sınaması"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Asset Download Error:"
+msgstr "Nesne İndirme Hatası:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Fetching:"
+msgstr "Alınıyor:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Resolving.."
+msgstr "Kaydediliyor..."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Connecting.."
+msgstr "BaÄŸlan..."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Requesting.."
+msgstr "Deneme"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Error making request"
+msgstr "Kaynak kaydedilirken sorun!"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Idle"
+msgstr "BoÅŸta"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Retry"
+msgstr "Tekrarla"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download Error"
+msgstr "İndirme Hatası"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download for this asset is already in progress!"
+msgstr "Bu nesne için zaten sürdürülen bir indirme var!"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "first"
+msgstr "ilk"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "prev"
+msgstr "önceki"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "next"
+msgstr "sonraki"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "last"
+msgstr "son"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "All"
+msgstr "Hepsi"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Plugins"
+msgstr "Eklentiler"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Sort:"
+msgstr "Sırala:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Reverse"
+msgstr "Tersi"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Category:"
+msgstr "Katman:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Site:"
+msgstr "Yer:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Support.."
+msgstr "Destek..."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Official"
+msgstr "Resmi"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Testing"
+msgstr "Deneme"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Assets ZIP File"
+msgstr "Varlıkların ZIP Dizeci"
#: editor/plugins/camera_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
msgid "Preview"
msgstr "Önizleme"
@@ -3781,12 +3320,18 @@ msgid "Edit CanvasItem"
msgstr "CanvasItem Düzenle"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Change Anchors"
+#, fuzzy
+msgid "Anchors only"
+msgstr "Çapa"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#, fuzzy
+msgid "Change Anchors and Margins"
msgstr "Çapaları Değiştir"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom (%):"
-msgstr "YaklaÅŸ (%):"
+msgid "Change Anchors"
+msgstr "Çapaları Değiştir"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Paste Pose"
@@ -3840,60 +3385,78 @@ msgid "Pan Mode"
msgstr "Kaydırma Biçimi"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Lock the selected object in place (can't be moved)."
-msgstr "Seçilen nesneyi yerine kilitleyin (taşınamaz)."
+#, fuzzy
+msgid "Toggles snapping"
+msgstr "Kesme Noktası Aç/Kapat"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Unlock the selected object (can be moved)."
-msgstr "Seçilen nesnenin kilidini açın (taşınabilir)."
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Use Snap"
+msgstr "Yapışma Kullan"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Makes sure the object's children are not selectable."
-msgstr "Nesnenin çocuğunun seçilemez olduğundan kuşkusuz olur."
+#, fuzzy
+msgid "Snapping options"
+msgstr "Canlandırma Seçenekleri"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Restores the object's children's ability to be selected."
-msgstr "Nesnenin çocuğunun seçilebilme yeteneğini geri kazandırır."
+#, fuzzy
+msgid "Snap to grid"
+msgstr "Yapışma Biçimi:"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Edit"
-msgstr "Düzenle"
+msgid "Use Rotation Snap"
+msgstr "Döndürme Yapışması Kullan"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Use Snap"
-msgstr "Yapışma Kullan"
+#, fuzzy
+msgid "Configure Snap..."
+msgstr "Yapışmayı Yapılandır.."
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Show Grid"
-msgstr "Izgarayı Göster"
+msgid "Snap Relative"
+msgstr "Göreceli Yapış"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Rotation Snap"
-msgstr "Döndürme Yapışması Kullan"
+msgid "Use Pixel Snap"
+msgstr "Nokta Yapışması Kullan"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap Relative"
-msgstr "Göreceli Yapış"
+msgid "Smart snapping"
+msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Configure Snap.."
-msgstr "Yapışmayı Yapılandır.."
+#, fuzzy
+msgid "Snap to parent"
+msgstr "Ataya geniÅŸletin"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Pixel Snap"
-msgstr "Nokta Yapışması Kullan"
+msgid "Snap to node anchor"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to node sides"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to other nodes"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Lock the selected object in place (can't be moved)."
+msgstr "Seçilen nesneyi yerine kilitleyin (taşınamaz)."
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Unlock the selected object (can be moved)."
+msgstr "Seçilen nesnenin kilidini açın (taşınabilir)."
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Skeleton.."
-msgstr "Ä°skelet.."
+msgid "Makes sure the object's children are not selectable."
+msgstr "Nesnenin çocuğunun seçilemez olduğundan kuşkusuz olur."
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Restores the object's children's ability to be selected."
+msgstr "Nesnenin çocuğunun seçilebilme yeteneğini geri kazandırır."
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Make Bones"
@@ -3921,12 +3484,19 @@ msgid "View"
msgstr "Görüş"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Reset"
-msgstr "Yakınlaşmayı Sıfırla"
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Show Grid"
+msgstr "Izgarayı Göster"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#, fuzzy
+msgid "Show helpers"
+msgstr "Kemikleri Göster"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Set.."
-msgstr "Yakınlaşmayı Ayarla.."
+#, fuzzy
+msgid "Show rulers"
+msgstr "Kemikleri Göster"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Center Selection"
@@ -3937,8 +3507,9 @@ msgid "Frame Selection"
msgstr "Kafes Seçimi"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Anchor"
-msgstr "Çapa"
+#, fuzzy
+msgid "Layout"
+msgstr "Tasarımı Kaydet"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Insert Keys"
@@ -3961,12 +3532,21 @@ msgid "Clear Pose"
msgstr "DuruÅŸu Temizle"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Set a Value"
-msgstr "Bir DeÄŸer Ata"
+msgid "Drag pivot from mouse position"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#, fuzzy
+msgid "Set pivot at mouse position"
+msgstr "Eğri Çıkış Konumunu Ayarla"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Multiply grid step by 2"
+msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap (Pixels):"
-msgstr "Yapış (Noktalara):"
+msgid "Divide grid step by 2"
+msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Add %s"
@@ -3976,23 +3556,28 @@ msgstr "Ekle %s"
msgid "Adding %s..."
msgstr "Ekliyor %s.."
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Create Node"
msgstr "Düğüm Oluştur"
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Error instancing scene from %s"
msgstr "%s sahne örnekleme sorunu"
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "OK :("
msgstr "Tamam :("
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "No parent to instance a child at."
msgstr "Çocuğun örnek alacağı bir ata yok."
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "This operation requires a single selected node."
msgstr "Bu işlem, seçilmiş tek bir düğüm gerektirir."
@@ -4008,45 +3593,6 @@ msgstr ""
"Sürükle & bırak + Shift: Kardeş olarak düğüm ekle\n"
"Sürükle & bırak + Alt: Düğüm türünü değiştir"
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Create Poly"
-msgstr "Çoklu Oluşturun"
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly"
-msgstr "Çokluyu Düzenleyin"
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly (Remove Point)"
-msgstr "Çokluyu Düzenleyin (Noktayı Silin)"
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Create a new polygon from scratch."
-msgstr "Sıfırdan yeni bir çokgen oluşturun."
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-msgid ""
-"Edit existing polygon:\n"
-"LMB: Move Point.\n"
-"Ctrl+LMB: Split Segment.\n"
-"RMB: Erase Point."
-msgstr ""
-
#: editor/plugins/collision_polygon_editor_plugin.cpp
msgid "Create Poly3D"
msgstr "Çoklu3B Oluştur"
@@ -4056,14 +3602,6 @@ msgid "Set Handle"
msgstr "Tutamacı Ayarla"
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Creating Mesh Library"
-msgstr "Örüntü Betikevi Oluştur"
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Thumbnail.."
-msgstr "Küçük Bediz.."
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Remove item %d?"
msgstr "%d öğe kaldırılsın mı?"
@@ -4086,6 +3624,28 @@ msgid "Update from Scene"
msgstr "Sahneden Güncelle"
#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat0"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat1"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+#, fuzzy
+msgid "Ease in"
+msgstr "Açılma"
+
+#: editor/plugins/curve_editor_plugin.cpp
+#, fuzzy
+msgid "Ease out"
+msgstr "Kararma"
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Smoothstep"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
#, fuzzy
msgid "Modify Curve Point"
msgstr "Eğri Haritasını Değiştir"
@@ -4170,22 +3730,18 @@ msgid "Create Occluder Polygon"
msgstr "Engelleyici Çokgeni Oluştur"
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Edit existing polygon:"
msgstr "Var olan çokgeni düzenleyin:"
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "LMB: Move Point."
msgstr "LMB: Taşıma Noktası."
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Ctrl+LMB: Split Segment."
msgstr "Ctrl + LMB: Parçayı Böl."
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "RMB: Erase Point."
msgstr "RMB: Noktayı Sil."
@@ -4290,6 +3846,10 @@ msgid "Create Outline"
msgstr "Anahat OluÅŸtur"
#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Mesh"
+msgstr "Örüntü"
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Create Trimesh Static Body"
msgstr "Üçlü Örüntü Durağan Gövdesi Oluştur"
@@ -4417,14 +3977,83 @@ msgstr "Rastgele Ölçek:"
msgid "Populate"
msgstr "Doldur"
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake!"
+msgstr "PiÅŸir!"
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+#, fuzzy
+msgid "Bake the navigation mesh.\n"
+msgstr "Yönlendirici Örüntüsü Oluştur"
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+#, fuzzy
+msgid "Clear the navigation mesh."
+msgstr "Yönlendirici Örüntüsü Oluştur"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Setting up Configuration..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Calculating grid size..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Creating heightfield..."
+msgstr "Işık Sekağacı Oluşturuyor"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Marking walkable triangles..."
+msgstr "Çevirilebilir Dizeler.."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Constructing compact heightfield..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Eroding walkable area..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Partitioning..."
+msgstr "Uyarı"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Creating contours..."
+msgstr "Sekağaç Dokusu Oluşturuyor"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Creating polymesh..."
+msgstr "Anahat Örüntüsü Oluştur.."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Converting to native navigation mesh..."
+msgstr "Yönlendirici Örüntüsü Oluştur"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Navigation Mesh Generator Setup:"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Parsing Geometry..."
+msgstr "Uzambilgisini Ayrıştırıyor"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Done!"
+msgstr ""
+
#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Create Navigation Polygon"
msgstr "Yönlendirici Çokgeni Oluştur"
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Remove Poly And Point"
-msgstr "Çokluyu ve Noktayı Kaldır"
-
#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Clear Emission Mask"
msgstr "Yayma Örtecini Temizle"
@@ -4610,14 +4239,17 @@ msgid "Curve Point #"
msgstr "EÄŸrisel Nokta #"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve Point Position"
msgstr "Eğri Noktası Konumu Ayarla"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve In Position"
msgstr "EÄŸriyi Konumda Ayarla"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve Out Position"
msgstr "Eğri Çıkış Konumunu Ayarla"
@@ -4680,6 +4312,14 @@ msgid "Scale Polygon"
msgstr "Çokgeni Ölçekle"
#: editor/plugins/polygon_2d_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Edit"
+msgstr "Düzenle"
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Polygon->UV"
msgstr "Çokgen->UV"
@@ -4734,63 +4374,10 @@ msgstr "Kaynak Yükle"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/shader_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "Yapıştır"
-#: editor/plugins/rich_text_editor_plugin.cpp
-msgid "Parse BBCode"
-msgstr "BBCode'u Ayrıştır"
-
-#: editor/plugins/sample_editor_plugin.cpp
-msgid "Length:"
-msgstr "Uzunluk:"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Open Sample File(s)"
-msgstr "Örnek Dizeçleri Aç"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "ERROR: Couldn't load sample!"
-msgstr "SORUN: Örnek yüklenemedi!"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Add Sample"
-msgstr "Örnek Ekle"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Rename Sample"
-msgstr "Örneği Yeniden Addlandır"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Delete Sample"
-msgstr "Örneği Sil"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "16 Bits"
-msgstr "16 bit"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "8 Bits"
-msgstr "8 Bit"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Stereo"
-msgstr "Çiftli"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Mono"
-msgstr "Tekli"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Format"
-msgstr "Biçem"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Pitch"
-msgstr "Perde"
-
#: editor/plugins/script_editor_plugin.cpp
#, fuzzy
msgid "Clear Recent Files"
@@ -4882,6 +4469,10 @@ msgstr "Belgeleri Kapat"
msgid "Close All"
msgstr "Tümünü Kapat"
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+msgid "Run"
+msgstr "Çalıştır"
+
#: editor/plugins/script_editor_plugin.cpp
#, fuzzy
msgid "Toggle Scripts Panel"
@@ -4911,7 +4502,8 @@ msgstr "İçeri Adımla"
msgid "Break"
msgstr "Ara Ver"
-#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+#: editor/script_editor_debugger.cpp
msgid "Continue"
msgstr "Devam Et"
@@ -4925,18 +4517,6 @@ msgid "Debug with external editor"
msgstr "Düzenleyicide Aç"
#: editor/plugins/script_editor_plugin.cpp
-msgid "Window"
-msgstr "Pencere"
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Left"
-msgstr "Sola Taşı"
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Right"
-msgstr "Sağa Taşı"
-
-#: editor/plugins/script_editor_plugin.cpp
#, fuzzy
msgid "Open Godot online documentation"
msgstr "BaÅŸvuru belgelerinde arama yap."
@@ -5025,8 +4605,9 @@ msgid "Cut"
msgstr "Kes"
#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "Tıpkıla"
@@ -5292,10 +4873,6 @@ msgid "View Plane Transform."
msgstr "Düzlem Dönüşümünü Görüntüle."
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Scaling to %s%%."
-msgstr "Şuna %s%% Ölçeklendiriliyor."
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rotating %s degrees."
msgstr "%s Düzey Dönüyor."
@@ -5312,10 +4889,6 @@ msgid "Top View."
msgstr "Üstten Görünüm."
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Top"
-msgstr "Ãœst"
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rear View."
msgstr "Arkadan Görünüm."
@@ -5561,6 +5134,10 @@ msgid "Transform"
msgstr "Dönüşüm"
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Configure Snap.."
+msgstr "Yapışmayı Yapılandır.."
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Local Coords"
msgstr "Yerel Konaçlar"
@@ -5706,6 +5283,10 @@ msgid "Speed (FPS):"
msgstr "Hız (FPS):"
#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Loop"
+msgstr "Döngü"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Animation Frames"
msgstr "Canlandırma Çerçeveleri"
@@ -5718,12 +5299,14 @@ msgid "Insert Empty (After)"
msgstr "BoÅŸ Ekle (Sonra)"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Up"
-msgstr "Yukarı"
+#, fuzzy
+msgid "Move (Before)"
+msgstr "Düğümleri Kaldır"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Down"
-msgstr "Aşağı"
+#, fuzzy
+msgid "Move (After)"
+msgstr "Sola Taşı"
#: editor/plugins/style_box_editor_plugin.cpp
msgid "StyleBox Preview:"
@@ -5802,8 +5385,12 @@ msgid "Remove All"
msgstr "Kaldır"
#: editor/plugins/theme_editor_plugin.cpp
-msgid "Theme"
-msgstr "Kalıp"
+msgid "Edit theme.."
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Theme editing menu."
+msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
msgid "Add Class Items"
@@ -5887,6 +5474,10 @@ msgid "Style"
msgstr "Yoldam"
#: editor/plugins/theme_editor_plugin.cpp
+msgid "Font"
+msgstr "Yazı Tipi"
+
+#: editor/plugins/theme_editor_plugin.cpp
msgid "Color"
msgstr "Renk"
@@ -5938,8 +5529,9 @@ msgid "Mirror Y"
msgstr "Y'ye Aynala"
#: editor/plugins/tile_map_editor_plugin.cpp
-msgid "Bucket"
-msgstr "Kova"
+#, fuzzy
+msgid "Paint Tile"
+msgstr "TileMap'i Boya"
#: editor/plugins/tile_map_editor_plugin.cpp
msgid "Pick Tile"
@@ -6005,6 +5597,10 @@ msgid "Delete preset '%s'?"
msgstr "Seçili dizeçleri sil?"
#: editor/project_export.cpp
+msgid "Export templates for this platform are missing/corrupted: "
+msgstr ""
+
+#: editor/project_export.cpp
#, fuzzy
msgid "Presets"
msgstr "Ön ayar.."
@@ -6090,34 +5686,62 @@ msgid "Export templates for this platform are missing:"
msgstr ""
#: editor/project_export.cpp
+msgid "Export templates for this platform are missing/corrupted:"
+msgstr ""
+
+#: editor/project_export.cpp
#, fuzzy
msgid "Export With Debug"
msgstr "Döşenti Dizi Dışa Aktar"
#: editor/project_manager.cpp
-msgid "Invalid project path, the path must exist!"
-msgstr "Geçersiz tasarı yolu, yolun var olması gerekir!"
+#, fuzzy
+msgid "The path does not exist."
+msgstr "Dizeç yok."
#: editor/project_manager.cpp
#, fuzzy
-msgid "Invalid project path, project.godot must not exist."
-msgstr "Geçersiz tasarı yolu, engine.cfg var olmaması gerekir."
+msgid "Please choose a 'project.godot' file."
+msgstr "Lütfen tasarı dizininin dışına aktarın!"
#: editor/project_manager.cpp
-#, fuzzy
-msgid "Invalid project path, project.godot must exist."
-msgstr "Geçersiz tasarı yolu, engine.cfg var olması gerekir."
+msgid ""
+"Your project will be created in a non empty folder (you might want to create "
+"a new folder)."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Please choose a folder that does not contain a 'project.godot' file."
+msgstr ""
#: editor/project_manager.cpp
msgid "Imported Project"
msgstr "İçe Aktarılan Tasarı"
#: editor/project_manager.cpp
+msgid " "
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "It would be a good idea to name your project."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Invalid project path (changed anything?)."
msgstr "Geçersiz tasarı yolu (bir şey değişti mi?)."
#: editor/project_manager.cpp
#, fuzzy
+msgid "Couldn't get project.godot in project path."
+msgstr "engine.cfg tasarı yolunda oluşturulamadı."
+
+#: editor/project_manager.cpp
+#, fuzzy
+msgid "Couldn't edit project.godot in project path."
+msgstr "engine.cfg tasarı yolunda oluşturulamadı."
+
+#: editor/project_manager.cpp
+#, fuzzy
msgid "Couldn't create project.godot in project path."
msgstr "engine.cfg tasarı yolunda oluşturulamadı."
@@ -6126,38 +5750,49 @@ msgid "The following files failed extraction from package:"
msgstr "Aşağıdaki dizeçlerin, çıkından ayıklanma işlemi başarısız oldu:"
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Rename Project"
+msgstr "Adsız Tasarı"
+
+#: editor/project_manager.cpp
+#, fuzzy
+msgid "Couldn't get project.godot in the project path."
+msgstr "engine.cfg tasarı yolunda oluşturulamadı."
+
+#: editor/project_manager.cpp
+msgid "New Game Project"
+msgstr "Yeni Oyun Tasarısı"
+
+#: editor/project_manager.cpp
msgid "Import Existing Project"
msgstr "Var olan Tasarıyı İçe Aktar"
#: editor/project_manager.cpp
-msgid "Project Path (Must Exist):"
-msgstr "Tasarı Yolu (Var Olması Gerekir):"
+msgid "Create New Project"
+msgstr "Yeni Tasarı Oluştur"
+
+#: editor/project_manager.cpp
+msgid "Install Project:"
+msgstr "Tasarıyı Kur:"
#: editor/project_manager.cpp
msgid "Project Name:"
msgstr "Tasarı Adı:"
#: editor/project_manager.cpp
-msgid "Create New Project"
-msgstr "Yeni Tasarı Oluştur"
+#, fuzzy
+msgid "Create folder"
+msgstr "Dizin OluÅŸtur"
#: editor/project_manager.cpp
msgid "Project Path:"
msgstr "Tasarı Yolu:"
#: editor/project_manager.cpp
-msgid "Install Project:"
-msgstr "Tasarıyı Kur:"
-
-#: editor/project_manager.cpp
msgid "Browse"
msgstr "Gözat"
#: editor/project_manager.cpp
-msgid "New Game Project"
-msgstr "Yeni Oyun Tasarısı"
-
-#: editor/project_manager.cpp
msgid "That's a BINGO!"
msgstr "YaÅŸa BE!"
@@ -6166,6 +5801,11 @@ msgid "Unnamed Project"
msgstr "Adsız Tasarı"
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Can't open project"
+msgstr "Bağlanamadı."
+
+#: editor/project_manager.cpp
msgid "Are you sure to open more than one project?"
msgstr "Birden fazla tasarı açmakta kararlı mısınız?"
@@ -6197,6 +5837,12 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
+"Language changed.\n"
+"The UI will update next time the editor or project manager starts."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid ""
"You are about the scan %s folders for existing Godot projects. Do you "
"confirm?"
msgstr ""
@@ -6208,10 +5854,6 @@ msgid "Project List"
msgstr "Tasarı Dizelgesi"
#: editor/project_manager.cpp
-msgid "Run"
-msgstr "Çalıştır"
-
-#: editor/project_manager.cpp
msgid "Scan"
msgstr "Tara"
@@ -6234,6 +5876,11 @@ msgstr "Çık"
#: editor/project_manager.cpp
#, fuzzy
+msgid "Restart Now"
+msgstr "Yeniden BaÅŸlat (sn):"
+
+#: editor/project_manager.cpp
+#, fuzzy
msgid "Can't run project"
msgstr "Bağlanamadı."
@@ -6270,17 +5917,14 @@ msgid "Add Input Action Event"
msgstr "Giriş İşlem Olayı Ekle"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Meta+"
msgstr "Meta+"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Shift+"
msgstr "Shift+"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Alt+"
msgstr "Alt+"
@@ -6342,7 +5986,7 @@ msgstr "DeÄŸiÅŸtir"
msgid "Joypad Axis Index:"
msgstr "Oyunçubuğu Ekseni Dizini:"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Axis"
msgstr "Eksen"
@@ -6364,31 +6008,31 @@ msgstr "Giriş Eylemi Olayını Sil"
msgid "Add Event"
msgstr "BoÅŸ Ekle"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Device"
msgstr "Aygıt"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Button"
msgstr "Düğme"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Left Button."
msgstr "Sol Düğme."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Right Button."
msgstr "Sağ Düğme."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Middle Button."
msgstr "Orta Düğme."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Up."
msgstr "Tekerlek Yukarı."
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Down."
msgstr "Tekerlek Aşağı."
@@ -6398,7 +6042,7 @@ msgid "Add Global Property"
msgstr "Alıcı Özellik Ekle"
#: editor/project_settings_editor.cpp
-msgid "Select an setting item first!"
+msgid "Select a setting item first!"
msgstr ""
#: editor/project_settings_editor.cpp
@@ -6417,6 +6061,16 @@ msgid "Delete Item"
msgstr "GiriÅŸi Sil"
#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Can't contain '/' or ':'"
+msgstr "Ana makineye bağlanılamadı:"
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Already existing"
+msgstr "Sürdürmeyi Aç/Kapat"
+
+#: editor/project_settings_editor.cpp
msgid "Error saving settings."
msgstr "Ayarları kaydetme sorunu."
@@ -6458,6 +6112,15 @@ msgstr "Kaynak Yeniden Eşle Seçeneğini Kaldır"
#: editor/project_settings_editor.cpp
#, fuzzy
+msgid "Changed Locale Filter"
+msgstr "Karışım Süresini Değiştir"
+
+#: editor/project_settings_editor.cpp
+msgid "Changed Locale Filter Mode"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
msgid "Project Settings (project.godot)"
msgstr "Tasarı Ayarları (engine.cfg)"
@@ -6518,6 +6181,30 @@ msgid "Locale"
msgstr "Yerel"
#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Locales Filter"
+msgstr "Bediz Süzgeci:"
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Show all locales"
+msgstr "Kemikleri Göster"
+
+#: editor/project_settings_editor.cpp
+msgid "Show only selected locales"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Filter mode:"
+msgstr "Süzgeçler"
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Locales:"
+msgstr "Yerel"
+
+#: editor/project_settings_editor.cpp
msgid "AutoLoad"
msgstr "KendindenYükle"
@@ -6569,10 +6256,20 @@ msgstr "Yeni Betik"
#: editor/property_editor.cpp
#, fuzzy
+msgid "Make Unique"
+msgstr "Kemik Yap"
+
+#: editor/property_editor.cpp
+#, fuzzy
msgid "Show in File System"
msgstr "DizeçDüzeni"
#: editor/property_editor.cpp
+#, fuzzy
+msgid "Convert To %s"
+msgstr "Şuna Dönüştür.."
+
+#: editor/property_editor.cpp
msgid "Error loading file: Not a resource!"
msgstr "Dizeç yüklenirken sorun oluştu: Bir kaynak değil!"
@@ -6611,6 +6308,11 @@ msgid "Select Property"
msgstr "Nitelik Seç"
#: editor/property_selector.cpp
+#, fuzzy
+msgid "Select Virtual Method"
+msgstr "Yöntem Seç"
+
+#: editor/property_selector.cpp
msgid "Select Method"
msgstr "Yöntem Seç"
@@ -6638,26 +6340,6 @@ msgstr "Bütünsel Dönüşümü Tut"
msgid "Reparent"
msgstr "Yeniden Ata Yap"
-#: editor/resources_dock.cpp
-msgid "Create New Resource"
-msgstr "Yeni Kaynak OluÅŸtur"
-
-#: editor/resources_dock.cpp
-msgid "Open Resource"
-msgstr "Kaynak Aç"
-
-#: editor/resources_dock.cpp
-msgid "Save Resource"
-msgstr "Kaynağı Kaydet"
-
-#: editor/resources_dock.cpp
-msgid "Resource Tools"
-msgstr "Kaynak Araçları"
-
-#: editor/resources_dock.cpp
-msgid "Make Local"
-msgstr "YerelleÅŸtir"
-
#: editor/run_settings_dialog.cpp
msgid "Run Mode:"
msgstr "Çalışma Biçimi:"
@@ -6788,14 +6470,6 @@ msgid "Sub-Resources:"
msgstr "Kaynaklar:"
#: editor/scene_tree_dock.cpp
-msgid "Edit Groups"
-msgstr "Öbekleri Düzenle"
-
-#: editor/scene_tree_dock.cpp
-msgid "Edit Connections"
-msgstr "Bağlantıları Düzenle"
-
-#: editor/scene_tree_dock.cpp
msgid "Clear Inheritance"
msgstr "Kalıtı Temizle"
@@ -6984,6 +6658,15 @@ msgid "Invalid base path"
msgstr "Geçersiz üst yol"
#: editor/script_create_dialog.cpp
+msgid "Directory of the same name exists"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
+#, fuzzy
+msgid "File exists, will be reused"
+msgstr "Dizeç var. Üzerine Yazılsın mı?"
+
+#: editor/script_create_dialog.cpp
msgid "Invalid extension"
msgstr "Geçersiz uzantı"
@@ -7029,6 +6712,10 @@ msgid "Load existing script file"
msgstr "Var olan betiği yükle"
#: editor/script_create_dialog.cpp
+msgid "Language"
+msgstr "Dil"
+
+#: editor/script_create_dialog.cpp
#, fuzzy
msgid "Inherits"
msgstr "Kalıtçılar:"
@@ -7073,6 +6760,10 @@ msgid "Function:"
msgstr "Ä°ÅŸlev:"
#: editor/script_editor_debugger.cpp
+msgid "Pick one or more items from the list to display the graph."
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
msgid "Errors"
msgstr "Sorunlar"
@@ -7153,6 +6844,10 @@ msgid "Type"
msgstr "Tür"
#: editor/script_editor_debugger.cpp
+msgid "Format"
+msgstr "Biçem"
+
+#: editor/script_editor_debugger.cpp
msgid "Usage"
msgstr "Kullanım"
@@ -7228,13 +6923,31 @@ msgstr ""
msgid "Change Probe Extents"
msgstr "DeÅŸme GeniÅŸlemesini DeÄŸiÅŸtir"
+#: modules/gdnative/gd_native_library_editor.cpp
+#, fuzzy
+msgid "Library"
+msgstr "MeshLibrary .."
+
+#: modules/gdnative/gd_native_library_editor.cpp
+#, fuzzy
+msgid "Status"
+msgstr "Durum:"
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Libraries: "
+msgstr ""
+
+#: modules/gdnative/register_types.cpp
+msgid "GDNative"
+msgstr ""
+
#: modules/gdscript/gd_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Invalid type argument to convert(), use TYPE_* constants."
msgstr ""
"convert() için geçersiz türde değiştirgen, TYPE_* sabitlerini kullanın."
-#: modules/gdscript/gd_functions.cpp
+#: modules/gdscript/gd_functions.cpp modules/mono/glue/glue_header.h
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Not enough bytes for decoding bytes, or invalid format."
msgstr "Geçersiz biçem ya da kod çözmek için yetersiz byte sayısı."
@@ -7286,10 +6999,6 @@ msgid "GridMap Duplicate Selection"
msgstr "Seçimi İkile"
#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "GridMap Paint"
-msgstr ""
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
#, fuzzy
msgid "Snap View"
msgstr "Üstten Görünüm"
@@ -7393,13 +7102,8 @@ msgstr "Yapışma Ayarları"
msgid "Pick Distance:"
msgstr "Örnek:"
-#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
-msgid "Tiles"
-msgstr "Dizeç"
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "Areas"
+#: modules/mono/editor/mono_bottom_panel.cpp
+msgid "Builds"
msgstr ""
#: modules/visual_script/visual_script.cpp
@@ -7610,10 +7314,18 @@ msgid "Return"
msgstr "Döndür"
#: modules/visual_script/visual_script_editor.cpp
+msgid "Call"
+msgstr "Çağır"
+
+#: modules/visual_script/visual_script_editor.cpp
msgid "Get"
msgstr "Al"
#: modules/visual_script/visual_script_editor.cpp
+msgid "Script already has function '%s'"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
#, fuzzy
msgid "Change Input Value"
msgstr "Giriş Adını Değiştir"
@@ -8029,6 +7741,12 @@ msgstr ""
"AnimatedSprite3D 'nin çerçeveleri görüntülemek için bir SpriteFrames kaynağı "
"oluşturulmalı veya 'Çerçeveler' niteliğinde ayarlanmalıdır."
+#: scene/3d/vehicle_body.cpp
+msgid ""
+"VehicleWheel serves to provide a wheel system to a VehicleBody. Please use "
+"it as a child of a VehicleBody."
+msgstr ""
+
#: scene/gui/color_picker.cpp
#, fuzzy
msgid "Raw Mode"
@@ -8039,6 +7757,10 @@ msgid "Add current color as a preset"
msgstr ""
#: scene/gui/dialogs.cpp
+msgid "Cancel"
+msgstr "Vazgeç"
+
+#: scene/gui/dialogs.cpp
msgid "Alert!"
msgstr "Uyarı!"
@@ -8046,10 +7768,6 @@ msgstr "Uyarı!"
msgid "Please Confirm..."
msgstr "Lütfen Doğrulayın..."
-#: scene/gui/input_action.cpp
-msgid "Ctrl+"
-msgstr "Ctrl+"
-
#: scene/gui/popup.cpp
msgid ""
"Popups will hide by default unless you call popup() or any of the popup*() "
@@ -8085,6 +7803,624 @@ msgstr ""
"bir boyut elde edin. Ya da, onu bir RenderTarget yapın ve iç dokusunu "
"görüntülemesi için bir düğüme atayın."
+#: scene/resources/dynamic_font.cpp
+msgid "Error initializing FreeType."
+msgstr "FreeType başlatılırken sorun oluştu."
+
+#: scene/resources/dynamic_font.cpp
+msgid "Unknown font format."
+msgstr "Bilinmeyen yazı türü."
+
+#: scene/resources/dynamic_font.cpp
+msgid "Error loading font."
+msgstr "Yazı türü yüklerken sorun oluştu."
+
+#: scene/resources/dynamic_font.cpp
+msgid "Invalid font size."
+msgstr "Geçersiz yazı türü boyutu."
+
+#~ msgid "Filter:"
+#~ msgstr "Süzgeç:"
+
+#~ msgid "Theme"
+#~ msgstr "Kalıp"
+
+#~ msgid "Method List For '%s':"
+#~ msgstr "'%s' İçin Yöntem Dizelgesi:"
+
+#~ msgid "Arguments:"
+#~ msgstr "DeÄŸiÅŸtirgenler:"
+
+#~ msgid "Return:"
+#~ msgstr "Döndür:"
+
+#~ msgid "Added:"
+#~ msgstr "Eklenen:"
+
+#~ msgid "Removed:"
+#~ msgstr "Silinen:"
+
+#~ msgid "Error saving atlas:"
+#~ msgstr "Atlas kaydedilirken sorun oluÅŸtu:"
+
+#~ msgid "Could not save atlas subtexture:"
+#~ msgstr "Atlas alt dokusu kaydedilemedi:"
+
+#~ msgid "Exporting for %s"
+#~ msgstr "%s için Dışa Aktarım"
+
+#~ msgid "Setting Up.."
+#~ msgstr "Kurulum..."
+
+#~ msgid "Error loading scene."
+#~ msgstr "Sahne yüklenirken sorun oluştu."
+
+#~ msgid "Re-Import"
+#~ msgstr "Yeniden İçe Aktar"
+
+#~ msgid "Please wait for scan to complete."
+#~ msgstr "Tarama için bitmesini bekleyin."
+
+#~ msgid "Current scene must be saved to re-import."
+#~ msgstr "Yeniden içe aktarmak için şu anki sahneyi kaydet."
+
+#~ msgid "Save & Re-Import"
+#~ msgstr "Kaydet & Yeniden İçe Aktar"
+
+#~ msgid "Re-Importing"
+#~ msgstr "Yeniden-İçe Aktarım"
+
+#~ msgid "Re-Import Changed Resources"
+#~ msgstr "Değiştirilmiş Kaynakları Yeniden İçe Aktar"
+
+#~ msgid "Loading Export Templates"
+#~ msgstr "Dışa Aktarım Kalıpları Yükleniyor"
+
+#, fuzzy
+#~ msgid ""
+#~ "\n"
+#~ "Status: Needs Re-Import"
+#~ msgstr "Kaydet & Yeniden İçe Aktar"
+
+#~ msgid "Same source and destination files, doing nothing."
+#~ msgstr "Özdeş kaynak ve varış dizeçleri, hiçbir şey yapılmıyor."
+
+#~ msgid "Same source and destination paths, doing nothing."
+#~ msgstr "Özdeş kaynak ve varış yolları, hiçbir şey yapılmıyor."
+
+#~ msgid "Can't move directories to within themselves."
+#~ msgstr "Dizinleri kendi içlerine taşıyamazsınız."
+
+#, fuzzy
+#~ msgid "Error moving file:\n"
+#~ msgstr "Bediz yüklenirken sorun oluştu:"
+
+#~ msgid "Pick New Name and Location For:"
+#~ msgstr "Şunun için yeni ad ile konum seçin:"
+
+#~ msgid "No files selected!"
+#~ msgstr "Hiçbir Dizeç Seçilmedi!"
+
+#~ msgid "Info"
+#~ msgstr "Bilgi"
+
+#~ msgid "Re-Import.."
+#~ msgstr "Yeniden İçe Aktar.."
+
+#~ msgid "No bit masks to import!"
+#~ msgstr "Alınacak hiç bit örteci yok!"
+
+#~ msgid "Target path is empty."
+#~ msgstr "Amaçlanan dizeç yolu boş."
+
+#~ msgid "Target path must be a complete resource path."
+#~ msgstr "Amaçlanan yol, tam bir kaynak yolu olmalıdır."
+
+#~ msgid "Target path must exist."
+#~ msgstr "Amaçlanan dizeç yolu var olmalı."
+
+#~ msgid "Save path is empty!"
+#~ msgstr "Kayıt yolu boş!"
+
+#~ msgid "Import BitMasks"
+#~ msgstr "BitMasks İçe Aktar"
+
+#~ msgid "Source Texture(s):"
+#~ msgstr "Kaynak Doku(lar):"
+
+#~ msgid "Target Path:"
+#~ msgstr "Amaçlanan Dizeç Yolu :"
+
+#~ msgid "Accept"
+#~ msgstr "Kabul"
+
+#~ msgid "Bit Mask"
+#~ msgstr "Bit Örteci"
+
+#~ msgid "No source font file!"
+#~ msgstr "Kaynak yazı türü dizeci yok!"
+
+#~ msgid "No target font resource!"
+#~ msgstr "Amaçlanan yazı türü kaynağı yok!"
+
+#, fuzzy
+#~ msgid ""
+#~ "Invalid file extension.\n"
+#~ "Please use .font."
+#~ msgstr ""
+#~ "Geçersiz dizeç uzantısı.\n"
+#~ "Lütfen .fnt uzantısını kullanın."
+
+#~ msgid "Couldn't save font."
+#~ msgstr "Yazı türü kaydedilemedi."
+
+#~ msgid "Source Font:"
+#~ msgstr "Yazı Türü Kaynağı:"
+
+#~ msgid "Source Font Size:"
+#~ msgstr "Kaynak Yazı Türü Boyutu:"
+
+#~ msgid "Dest Resource:"
+#~ msgstr "Varış Kaynağı:"
+
+#~ msgid "The quick brown fox jumps over the lazy dog."
+#~ msgstr "Hızlı kahverengi tilki üşengeç köpeğin üstünden atlar."
+
+#~ msgid "Test:"
+#~ msgstr "Deneme:"
+
+#~ msgid "Options:"
+#~ msgstr "Seçenekler:"
+
+#~ msgid "Font Import"
+#~ msgstr "Yazı Türü İçe Aktar"
+
+#~ msgid ""
+#~ "This file is already a Godot font file, please supply a BMFont type file "
+#~ "instead."
+#~ msgstr ""
+#~ "Bu dizeç zaten bir Godot yazı türü dizecidir , lütfen bunun yerine bir "
+#~ "BMFont türü dizeci sağlayın."
+
+#~ msgid "Failed opening as BMFont file."
+#~ msgstr "BMFont dizeci olarak açma başarısız oldu."
+
+#~ msgid "Invalid font custom source."
+#~ msgstr "Geçersiz yazı türü özel kaynağı."
+
+#~ msgid "No meshes to import!"
+#~ msgstr "İçe aktarılacak örüntü yok!"
+
+#~ msgid "Single Mesh Import"
+#~ msgstr "Tekil Örüntü İçe Aktar"
+
+#~ msgid "Source Mesh(es):"
+#~ msgstr "Kaynak Örüntü(leri):"
+
+#~ msgid "Surface %d"
+#~ msgstr "Yüzey %d"
+
+#~ msgid "No samples to import!"
+#~ msgstr "Alınacak örnek yok!"
+
+#~ msgid "Import Audio Samples"
+#~ msgstr "Ses Örneklerini İçe Aktar"
+
+#~ msgid "Source Sample(s):"
+#~ msgstr "Kaynak Örnek(leri):"
+
+#~ msgid "Audio Sample"
+#~ msgstr "Ses Örneği"
+
+#~ msgid "New Clip"
+#~ msgstr "Yeni Parça"
+
+#~ msgid "Flags"
+#~ msgstr "Bayraklar"
+
+#~ msgid "Bake FPS:"
+#~ msgstr "FPS'i PiÅŸir:"
+
+#~ msgid "Optimizer"
+#~ msgstr "Ä°yileÅŸtirici"
+
+#~ msgid "Max Linear Error"
+#~ msgstr "En üst Doğrusal Sorun"
+
+#~ msgid "Max Angular Error"
+#~ msgstr "En üst Açısal Sorun"
+
+#~ msgid "Max Angle"
+#~ msgstr "En üst Açı"
+
+#~ msgid "Clips"
+#~ msgstr "Parçalar"
+
+#~ msgid "Start(s)"
+#~ msgstr "Başlangıç(lar)"
+
+#~ msgid "End(s)"
+#~ msgstr "Son(lar)"
+
+#~ msgid "Filters"
+#~ msgstr "Süzgeçler"
+
+#~ msgid "Source path is empty."
+#~ msgstr "Kaynak yol boÅŸ."
+
+#~ msgid "Couldn't load post-import script."
+#~ msgstr "İçe aktarma sonrası betik dizeci yüklenemedi."
+
+#~ msgid "Invalid/broken script for post-import."
+#~ msgstr "İçe aktarma sonrası için geçersiz/bozuk betik dizeci."
+
+#~ msgid "Error importing scene."
+#~ msgstr "İçe aktarırken sorun oluştu."
+
+#~ msgid "Import 3D Scene"
+#~ msgstr "3B Sahneyi İçe Aktar"
+
+#~ msgid "Source Scene:"
+#~ msgstr "Kaynak Sahne:"
+
+#~ msgid "Same as Target Scene"
+#~ msgstr "Hedef Sahne ile Aynı"
+
+#~ msgid "Shared"
+#~ msgstr "Paylaşılan"
+
+#~ msgid "Target Texture Folder:"
+#~ msgstr "Amaçlanan Doku Dizini:"
+
+#~ msgid "Post-Process Script:"
+#~ msgstr "İşlem Sonrası Betik Dizeci:"
+
+#~ msgid "Custom Root Node Type:"
+#~ msgstr "Özel Kök Düğüm Türü:"
+
+#~ msgid "Auto"
+#~ msgstr "KendiliÄŸinden"
+
+#~ msgid "Root Node Name:"
+#~ msgstr "Kök Düğüm adı:"
+
+#~ msgid "The Following Files are Missing:"
+#~ msgstr "Aşağıdaki Dizeçler Eksik:"
+
+#~ msgid "Import Anyway"
+#~ msgstr "Yine de İçe Aktar"
+
+#~ msgid "Import & Open"
+#~ msgstr "İçe Aktar & Aç"
+
+#~ msgid "Edited scene has not been saved, open imported scene anyway?"
+#~ msgstr ""
+#~ "Düzenlenen sahne kaydedilmedi, yine de içe aktarılan sahne açılsın mı?"
+
+#~ msgid "Import Image:"
+#~ msgstr "Bedizi İçe Aktar:"
+
+#~ msgid "Couldn't localize path: %s (already local)"
+#~ msgstr "Yol yerelleÅŸtirilemedi: %s (zaten yerel)"
+
+#~ msgid "3D Scene Animation"
+#~ msgstr "3B Sahne Canlandırması"
+
+#~ msgid "Uncompressed"
+#~ msgstr "Sıkıştırılmamış"
+
+#~ msgid "Compress Lossless (PNG)"
+#~ msgstr "Kayıpsız Sıkıştırma (PNG)"
+
+#~ msgid "Compress Lossy (WebP)"
+#~ msgstr "Kayıplı Sıkıştırma (WebP)"
+
+#~ msgid "Compress (VRAM)"
+#~ msgstr "Sıkıştır (VRAM)"
+
+#~ msgid "Texture Format"
+#~ msgstr "Doku Biçemi"
+
+#~ msgid "Texture Compression Quality (WebP):"
+#~ msgstr "Doku Sıkıştırma Niteliği (WebP):"
+
+#~ msgid "Texture Options"
+#~ msgstr "Doku Seçenekleri"
+
+#~ msgid "Please specify some files!"
+#~ msgstr "Lütfen bazı dizeçleri belirtin!"
+
+#~ msgid "At least one file needed for Atlas."
+#~ msgstr "Atlas için en az bir dizeç gerekli."
+
+#~ msgid "Error importing:"
+#~ msgstr "İçe aktarırken sorun:"
+
+#~ msgid "Only one file is required for large texture."
+#~ msgstr "Büyük doku için yalnızca bir dizeç gereklidir."
+
+#~ msgid "Max Texture Size:"
+#~ msgstr "En üst Doku Boyutu:"
+
+#~ msgid "Import Textures for Atlas (2D)"
+#~ msgstr "Dokuları Atlas(2B) için içe aktar"
+
+#~ msgid "Cell Size:"
+#~ msgstr "Odacık Boyutu:"
+
+#~ msgid "Large Texture"
+#~ msgstr "GeniÅŸ Doku"
+
+#~ msgid "Import Large Textures (2D)"
+#~ msgstr "Büyük Boyutlu(2D) Dokuları İçe Aktar"
+
+#~ msgid "Source Texture"
+#~ msgstr "Kaynak Doku"
+
+#~ msgid "Base Atlas Texture"
+#~ msgstr "Temel Atlas Doku"
+
+#~ msgid "Source Texture(s)"
+#~ msgstr "Kaynak Doku(lar)"
+
+#~ msgid "Import Textures for 2D"
+#~ msgstr "2B için Dokuları İçe Aktar"
+
+#~ msgid "Import Textures for 3D"
+#~ msgstr "3B için Dokuları İçe Aktar"
+
+#~ msgid "Import Textures"
+#~ msgstr "Dokuları İçe Aktar"
+
+#~ msgid "2D Texture"
+#~ msgstr "2B Doku"
+
+#~ msgid "3D Texture"
+#~ msgstr "3B Doku"
+
+#~ msgid "Atlas Texture"
+#~ msgstr "Atlas Doku"
+
+#~ msgid ""
+#~ "NOTICE: Importing 2D textures is not mandatory. Just copy png/jpg files "
+#~ "to the project."
+#~ msgstr ""
+#~ "UYARI: 2B dokuların içe aktarılması zorunlu değildir. Png / jpg "
+#~ "dizeçlerini tasarıya tıpkılamanız yeterlidir."
+
+#~ msgid "Crop empty space."
+#~ msgstr "Boş alanı kırp."
+
+#~ msgid "Texture"
+#~ msgstr "Doku"
+
+#~ msgid "Import Large Texture"
+#~ msgstr "Büyük Dokuyu İçe Aktar"
+
+#~ msgid "Load Source Image"
+#~ msgstr "Kaynak Bedizi Yükle"
+
+#~ msgid "Slicing"
+#~ msgstr "Dilimleme"
+
+#~ msgid "Saving"
+#~ msgstr "Kaydediyor"
+
+#~ msgid "Couldn't save large texture:"
+#~ msgstr "Büyük doku kaydedilemedi:"
+
+#~ msgid "Build Atlas For:"
+#~ msgstr "Atlası Şunun için Oluştur:"
+
+#~ msgid "Loading Image:"
+#~ msgstr "Bediz Yükleniyor:"
+
+#~ msgid "Couldn't load image:"
+#~ msgstr "Bediz yüklenemedi:"
+
+#~ msgid "Converting Images"
+#~ msgstr "Bedizleri Dönüştürüyor"
+
+#~ msgid "Cropping Images"
+#~ msgstr "Bedizleri Kırpıyor"
+
+#~ msgid "Blitting Images"
+#~ msgstr "Bedizleri Blitle"
+
+#~ msgid "Couldn't save atlas image:"
+#~ msgstr "Atlas bedizi kaydedilemedi:"
+
+#~ msgid "Couldn't save converted texture:"
+#~ msgstr "Dönüştürülmüş doku kaydedilemedi:"
+
+#~ msgid "Invalid source!"
+#~ msgstr "Geçersiz kaynak!"
+
+#~ msgid "Invalid translation source!"
+#~ msgstr "Geçersiz çeviri kaynağı!"
+
+#~ msgid "Column"
+#~ msgstr "Dikeç"
+
+#~ msgid "No items to import!"
+#~ msgstr "Alınacak öğe yok!"
+
+#~ msgid "No target path!"
+#~ msgstr "Amaçlanan yol yok!"
+
+#~ msgid "Import Translations"
+#~ msgstr "Çevirileri İçe Aktar"
+
+#~ msgid "Couldn't import!"
+#~ msgstr "Alınamadı!"
+
+#~ msgid "Import Translation"
+#~ msgstr "Çeviriyi İçe Aktar"
+
+#~ msgid "Source CSV:"
+#~ msgstr "Kaynak CSV:"
+
+#~ msgid "Ignore First Row"
+#~ msgstr "İlk Sırayı Yoksay"
+
+#~ msgid "Compress"
+#~ msgstr "Sıkıştır"
+
+#, fuzzy
+#~ msgid "Add to Project (project.godot)"
+#~ msgstr "Tasarıya Ekle (engine.cfg)"
+
+#~ msgid "Import Languages:"
+#~ msgstr "Dilleri İçe Aktar:"
+
+#~ msgid "Translation"
+#~ msgstr "Çeviri"
+
+#~ msgid "Parsing %d Triangles:"
+#~ msgstr "%d Üçgenlerini Ayrıştırma:"
+
+#~ msgid "Triangle #"
+#~ msgstr "Üçgen #"
+
+#~ msgid "Light Baker Setup:"
+#~ msgstr "Işık Pişirici Kurulumu:"
+
+#~ msgid "Fixing Lights"
+#~ msgstr "Işıkları Sabitliyor"
+
+#~ msgid "Making BVH"
+#~ msgstr "BVH Yapıyor"
+
+#~ msgid "Transfer to Lightmaps:"
+#~ msgstr "Işık Haritalarına Aktar:"
+
+#~ msgid "Allocating Texture #"
+#~ msgstr "Doku Paylaşımı #"
+
+#~ msgid "Baking Triangle #"
+#~ msgstr "Pişirme Üçgeni #"
+
+#~ msgid "Post-Processing Texture #"
+#~ msgstr "İşleme-Sonrası Dokusu #"
+
+#~ msgid "Reset the lightmap octree baking process (start over)."
+#~ msgstr ""
+#~ "Işık haritası sekağacı pişirme işlemini sıfırlayın (baştan başlayın)."
+
+#~ msgid "Zoom (%):"
+#~ msgstr "YaklaÅŸ (%):"
+
+#~ msgid "Skeleton.."
+#~ msgstr "Ä°skelet.."
+
+#~ msgid "Zoom Reset"
+#~ msgstr "Yakınlaşmayı Sıfırla"
+
+#~ msgid "Zoom Set.."
+#~ msgstr "Yakınlaşmayı Ayarla.."
+
+#~ msgid "Set a Value"
+#~ msgstr "Bir DeÄŸer Ata"
+
+#~ msgid "Snap (Pixels):"
+#~ msgstr "Yapış (Noktalara):"
+
+#~ msgid "Parse BBCode"
+#~ msgstr "BBCode'u Ayrıştır"
+
+#~ msgid "Length:"
+#~ msgstr "Uzunluk:"
+
+#~ msgid "Open Sample File(s)"
+#~ msgstr "Örnek Dizeçleri Aç"
+
+#~ msgid "ERROR: Couldn't load sample!"
+#~ msgstr "SORUN: Örnek yüklenemedi!"
+
+#~ msgid "Add Sample"
+#~ msgstr "Örnek Ekle"
+
+#~ msgid "Rename Sample"
+#~ msgstr "Örneği Yeniden Addlandır"
+
+#~ msgid "Delete Sample"
+#~ msgstr "Örneği Sil"
+
+#~ msgid "16 Bits"
+#~ msgstr "16 bit"
+
+#~ msgid "8 Bits"
+#~ msgstr "8 Bit"
+
+#~ msgid "Stereo"
+#~ msgstr "Çiftli"
+
+#~ msgid "Mono"
+#~ msgstr "Tekli"
+
+#~ msgid "Pitch"
+#~ msgstr "Perde"
+
+#~ msgid "Window"
+#~ msgstr "Pencere"
+
+#~ msgid "Move Right"
+#~ msgstr "Sağa Taşı"
+
+#~ msgid "Scaling to %s%%."
+#~ msgstr "Şuna %s%% Ölçeklendiriliyor."
+
+#~ msgid "Up"
+#~ msgstr "Yukarı"
+
+#~ msgid "Down"
+#~ msgstr "Aşağı"
+
+#~ msgid "Bucket"
+#~ msgstr "Kova"
+
+#~ msgid "Invalid project path, the path must exist!"
+#~ msgstr "Geçersiz tasarı yolu, yolun var olması gerekir!"
+
+#, fuzzy
+#~ msgid "Invalid project path, project.godot must not exist."
+#~ msgstr "Geçersiz tasarı yolu, engine.cfg var olmaması gerekir."
+
+#, fuzzy
+#~ msgid "Invalid project path, project.godot must exist."
+#~ msgstr "Geçersiz tasarı yolu, engine.cfg var olması gerekir."
+
+#~ msgid "Project Path (Must Exist):"
+#~ msgstr "Tasarı Yolu (Var Olması Gerekir):"
+
+#~ msgid "Create New Resource"
+#~ msgstr "Yeni Kaynak OluÅŸtur"
+
+#~ msgid "Open Resource"
+#~ msgstr "Kaynak Aç"
+
+#~ msgid "Save Resource"
+#~ msgstr "Kaynağı Kaydet"
+
+#~ msgid "Resource Tools"
+#~ msgstr "Kaynak Araçları"
+
+#~ msgid "Make Local"
+#~ msgstr "YerelleÅŸtir"
+
+#~ msgid "Edit Groups"
+#~ msgstr "Öbekleri Düzenle"
+
+#~ msgid "Edit Connections"
+#~ msgstr "Bağlantıları Düzenle"
+
+#, fuzzy
+#~ msgid "Tiles"
+#~ msgstr "Dizeç"
+
+#~ msgid "Ctrl+"
+#~ msgstr "Ctrl+"
+
#~ msgid "Close scene? (Unsaved changes will be lost)"
#~ msgstr "Sahneyi kapatsın mı? (Kaydedilmemiş değişiklikler yok olacak)"
@@ -8098,9 +8434,6 @@ msgstr ""
#~ msgid "Close Goto Prev. Scene"
#~ msgstr "Önc. Sahneye Git sekmesini Kapat"
-#~ msgid "Expand to Parent"
-#~ msgstr "Ataya geniÅŸletin"
-
#~ msgid "Del"
#~ msgstr "Sil"
@@ -8264,18 +8597,12 @@ msgstr ""
#~ msgid "Save Translatable Strings"
#~ msgstr "Çevirilebilir Metinleri Kaydet"
-#~ msgid "Translatable Strings.."
-#~ msgstr "Çevirilebilir Dizeler.."
-
#~ msgid "Install Export Templates"
#~ msgstr "Dışa Aktarım Kalıplarını Yükle"
#~ msgid "Edit Script Options"
#~ msgstr "Betik Seçeneklerini Düzenle"
-#~ msgid "Please export outside the project folder!"
-#~ msgstr "Lütfen tasarı dizininin dışına aktarın!"
-
#~ msgid "Error exporting project!"
#~ msgstr "Tasarı gönderilirken sorun oluştu!"
@@ -8334,18 +8661,12 @@ msgstr ""
#~ msgid "Include"
#~ msgstr "Katıştır"
-#~ msgid "Change Image Group"
-#~ msgstr "Bediz Öbeğini Değiştir"
-
#~ msgid "Group name can't be empty!"
#~ msgstr "Öbek adı boş olamaz!"
#~ msgid "Invalid character in group name!"
#~ msgstr "Öbek adında geçersiz damga!"
-#~ msgid "Group name already exists!"
-#~ msgstr "Öbek adı zaten var!"
-
#~ msgid "Add Image Group"
#~ msgstr "Bediz Öbeği Ekle"
@@ -8424,9 +8745,6 @@ msgstr ""
#~ msgid "Preview Atlas"
#~ msgstr "Atlası Önizle"
-#~ msgid "Image Filter:"
-#~ msgstr "Bediz Süzgeci:"
-
#~ msgid "Images:"
#~ msgstr "Bedizler:"
@@ -8493,9 +8811,6 @@ msgstr ""
#~ msgid "Lighting"
#~ msgstr "Aydınlatma"
-#~ msgid "Toggle Persisting"
-#~ msgstr "Sürdürmeyi Aç/Kapat"
-
#~ msgid "Global"
#~ msgstr "Bütünsel"
diff --git a/editor/translations/ur_PK.po b/editor/translations/ur_PK.po
index 41384a79da..3b624f4c8c 100644
--- a/editor/translations/ur_PK.po
+++ b/editor/translations/ur_PK.po
@@ -1,5 +1,6 @@
# Urdu (Pakistan) translation of the Godot Engine editor
-# Copyright (C) 2016-2017 Juan Linietsky, Ariel Manzur and the Godot community
+# Copyright (C) 2007-2017 Juan Linietsky, Ariel Manzur
+# Copyright (C) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)
# This file is distributed under the same license as the Godot source code.
#
# Muhammad Ali <ali@codeonion.com>, 2016.
@@ -192,10 +193,9 @@ msgid "Create %d NEW tracks and insert keys?"
msgstr ""
#: editor/animation_editor.cpp editor/create_dialog.cpp
-#: editor/editor_audio_buses.cpp
+#: editor/editor_audio_buses.cpp editor/plugins/abstract_polygon_2d_editor.cpp
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
#: editor/plugins/mesh_instance_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp editor/project_manager.cpp
#: editor/script_create_dialog.cpp
msgid "Create"
@@ -357,261 +357,6 @@ msgstr ""
msgid "Change Array Value"
msgstr ""
-#: editor/asset_library_editor_plugin.cpp
-msgid "Free"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_plugin_settings.cpp
-msgid "Version:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Contents:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "View Files"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_help.cpp editor/property_selector.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Description:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-#: editor/project_manager.cpp
-msgid "Install"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/call_dialog.cpp
-#: editor/connections_dialog.cpp editor/export_template_manager.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-#: editor/project_settings_editor.cpp editor/property_editor.cpp
-#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Close"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve hostname:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Connection error, please try again."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't connect."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't connect to host:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response from host:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Request failed, return code:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Req. Failed."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Request failed, too many redirects"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Redirect Loop."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Bad download hash, assuming file has been tampered with."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Expected:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Got:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Asset Download Error:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-msgid "Success!"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Fetching:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Resolving.."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Connecting.."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Requesting.."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Error making request"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Idle"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Retry"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Download Error"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Download for this asset is already in progress!"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "first"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "prev"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "next"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "last"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "All"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
-#: editor/settings_config_dialog.cpp
-msgid "Search:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/code_editor.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Search"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/project_manager.cpp
-msgid "Import"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Plugins"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Sort:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Reverse"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Category:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Site:"
-msgstr "سائٹ:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Support.."
-msgstr ".سپورٹ"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Official"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-msgid "Community"
-msgstr "کمیونٹی"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Testing"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Assets ZIP File"
-msgstr "Ø§Ø«Ø§Ø«Û Ú©ÛŒ زپ Ùائل"
-
-#: editor/call_dialog.cpp
-msgid "Method List For '%s':"
-msgstr ""
-
-#: editor/call_dialog.cpp modules/visual_script/visual_script_editor.cpp
-msgid "Call"
-msgstr ""
-
-#: editor/call_dialog.cpp
-msgid "Method List:"
-msgstr ""
-
-#: editor/call_dialog.cpp
-msgid "Arguments:"
-msgstr ""
-
-#: editor/call_dialog.cpp
-msgid "Return:"
-msgstr ""
-
#: editor/code_editor.cpp
msgid "Go to Line"
msgstr ""
@@ -648,6 +393,14 @@ msgstr ""
msgid "Selection Only"
msgstr ""
+#: editor/code_editor.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
+msgid "Search"
+msgstr ""
+
#: editor/code_editor.cpp editor/editor_help.cpp
msgid "Find"
msgstr ""
@@ -680,11 +433,11 @@ msgstr ""
msgid "Skip"
msgstr ""
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom In"
msgstr ""
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom Out"
msgstr ""
@@ -751,6 +504,20 @@ msgstr ""
msgid "Oneshot"
msgstr ""
+#: editor/connections_dialog.cpp editor/dependency_editor.cpp
+#: editor/export_template_manager.cpp
+#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Close"
+msgstr ""
+
#: editor/connections_dialog.cpp
msgid "Connect"
msgstr ""
@@ -776,7 +543,7 @@ msgstr ""
msgid "Disconnect"
msgstr ""
-#: editor/connections_dialog.cpp editor/node_dock.cpp
+#: editor/connections_dialog.cpp editor/editor_help.cpp editor/node_dock.cpp
msgid "Signals"
msgstr ""
@@ -793,12 +560,25 @@ msgstr ""
msgid "Recent:"
msgstr ""
+#: editor/create_dialog.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/quick_open.cpp editor/settings_config_dialog.cpp
+msgid "Search:"
+msgstr ""
+
#: editor/create_dialog.cpp editor/editor_help.cpp
#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/quick_open.cpp
msgid "Matches:"
msgstr ""
+#: editor/create_dialog.cpp editor/editor_help.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/property_selector.cpp
+#: editor/script_editor_debugger.cpp
+msgid "Description:"
+msgstr ""
+
#: editor/dependency_editor.cpp
msgid "Search Replacement For:"
msgstr ""
@@ -854,6 +634,10 @@ msgid "Owners Of:"
msgstr ""
#: editor/dependency_editor.cpp
+msgid "Remove selected files from the project? (no undo)"
+msgstr ""
+
+#: editor/dependency_editor.cpp
msgid ""
"The files being removed are required by other resources in order for them to "
"work.\n"
@@ -861,7 +645,7 @@ msgid ""
msgstr ""
#: editor/dependency_editor.cpp
-msgid "Remove selected files from the project? (no undo)"
+msgid "Cannot remove:\n"
msgstr ""
#: editor/dependency_editor.cpp
@@ -928,10 +712,6 @@ msgid "Godot Engine contributors"
msgstr ""
#: editor/editor_about.cpp
-msgid "Authors"
-msgstr ""
-
-#: editor/editor_about.cpp
msgid "Project Founders"
msgstr ""
@@ -948,6 +728,38 @@ msgid "Developers"
msgstr ""
#: editor/editor_about.cpp
+msgid "Authors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Platinum Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Gold Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Mini Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Gold Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Silver Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Bronze Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
msgid "License"
msgstr ""
@@ -988,6 +800,16 @@ msgid "Package Installed Successfully!"
msgstr ""
#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Success!"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/project_manager.cpp
+msgid "Install"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
msgid "Package Installer"
msgstr ""
@@ -1037,10 +859,6 @@ msgid "Audio Bus, Drag and Drop to rearrange."
msgstr ""
#: editor/editor_audio_buses.cpp
-msgid "Bus options"
-msgstr ""
-
-#: editor/editor_audio_buses.cpp
msgid "Solo"
msgstr ""
@@ -1052,12 +870,20 @@ msgstr ""
msgid "Bypass"
msgstr ""
+#: editor/editor_audio_buses.cpp
+msgid "Bus options"
+msgstr ""
+
#: editor/editor_audio_buses.cpp editor/plugins/tile_map_editor_plugin.cpp
#: editor/scene_tree_dock.cpp
msgid "Duplicate"
msgstr ""
#: editor/editor_audio_buses.cpp
+msgid "Reset Volume"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
msgid "Delete Effect"
msgstr ""
@@ -1078,6 +904,10 @@ msgid "Duplicate Audio Bus"
msgstr ""
#: editor/editor_audio_buses.cpp
+msgid "Reset Bus Volume"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
#, fuzzy
msgid "Move Audio Bus"
msgstr "ایکشن منتقل کریں"
@@ -1110,7 +940,8 @@ msgstr ""
msgid "Create a new Bus Layout."
msgstr ""
-#: editor/editor_audio_buses.cpp editor/script_create_dialog.cpp
+#: editor/editor_audio_buses.cpp editor/property_editor.cpp
+#: editor/script_create_dialog.cpp
msgid "Load"
msgstr ""
@@ -1202,7 +1033,7 @@ msgid "Rearrange Autoloads"
msgstr ""
#: editor/editor_autoload_settings.cpp editor/editor_file_dialog.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp scene/gui/file_dialog.cpp
+#: scene/gui/file_dialog.cpp
msgid "Path:"
msgstr ""
@@ -1210,9 +1041,7 @@ msgstr ""
msgid "Node Name:"
msgstr ""
-#: editor/editor_autoload_settings.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp editor/project_manager.cpp
+#: editor/editor_autoload_settings.cpp editor/project_manager.cpp
msgid "Name"
msgstr ""
@@ -1245,18 +1074,19 @@ msgid "Choose a Directory"
msgstr ""
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Create Folder"
msgstr ""
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: editor/editor_plugin_settings.cpp editor/plugins/theme_editor_plugin.cpp
-#: editor/project_export.cpp scene/gui/file_dialog.cpp
+#: editor/editor_plugin_settings.cpp editor/filesystem_dock.cpp
+#: editor/plugins/theme_editor_plugin.cpp editor/project_export.cpp
+#: scene/gui/file_dialog.cpp
msgid "Name:"
msgstr ""
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Could not create folder."
msgstr ""
@@ -1276,30 +1106,6 @@ msgstr ""
msgid "Template file not found:\n"
msgstr ""
-#: editor/editor_export.cpp
-msgid "Added:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Removed:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Error saving atlas:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Could not save atlas subtexture:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Exporting for %s"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Setting Up.."
-msgstr ""
-
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "File Exists, Overwrite?"
msgstr ""
@@ -1386,6 +1192,10 @@ msgstr "Ù¾Ø³Ù†Ø¯ÛŒØ¯Û Ø§ÙˆÙ¾Ø± منتقل کریں"
msgid "Move Favorite Down"
msgstr "Ù¾Ø³Ù†Ø¯ÛŒØ¯Û Ù†ÛŒÚ†Û’ منتقل کریں"
+#: editor/editor_file_dialog.cpp
+msgid "Go to parent folder"
+msgstr ""
+
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Directories & Files:"
msgstr ""
@@ -1400,10 +1210,6 @@ msgid "File:"
msgstr ""
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
-msgid "Filter:"
-msgstr ""
-
-#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Must use a valid extension."
msgstr ""
@@ -1428,6 +1234,10 @@ msgstr ""
msgid "Search Classes"
msgstr ""
+#: editor/editor_help.cpp editor/plugins/spatial_editor_plugin.cpp
+msgid "Top"
+msgstr ""
+
#: editor/editor_help.cpp editor/property_editor.cpp
msgid "Class:"
msgstr ""
@@ -1444,15 +1254,27 @@ msgstr ""
msgid "Brief Description:"
msgstr ""
+#: editor/editor_help.cpp
+msgid "Members"
+msgstr ""
+
#: editor/editor_help.cpp modules/visual_script/visual_script_editor.cpp
msgid "Members:"
msgstr ""
#: editor/editor_help.cpp
+msgid "Public Methods"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Public Methods:"
msgstr ""
#: editor/editor_help.cpp
+msgid "GUI Theme Items"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "GUI Theme Items:"
msgstr ""
@@ -1461,6 +1283,10 @@ msgid "Signals:"
msgstr ""
#: editor/editor_help.cpp
+msgid "Enumerations"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Enumerations:"
msgstr ""
@@ -1469,19 +1295,48 @@ msgid "enum "
msgstr ""
#: editor/editor_help.cpp
+msgid "Constants"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Constants:"
msgstr ""
#: editor/editor_help.cpp
#, fuzzy
+msgid "Description"
+msgstr "سب سکریپشن بنائیں"
+
+#: editor/editor_help.cpp
+msgid "Properties"
+msgstr ""
+
+#: editor/editor_help.cpp
+#, fuzzy
msgid "Property Description:"
msgstr "سب سکریپشن بنائیں"
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this property. Please help us by "
+"[color=$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+
+#: editor/editor_help.cpp
+msgid "Methods"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Method Description:"
msgstr ""
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this method. Please help us by [color="
+"$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Search Text"
msgstr ""
@@ -1490,24 +1345,21 @@ msgid "Output:"
msgstr ""
#: editor/editor_log.cpp editor/plugins/animation_tree_editor_plugin.cpp
-#: editor/plugins/rich_text_editor_plugin.cpp editor/property_editor.cpp
-#: editor/script_editor_debugger.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/property_editor.cpp editor/script_editor_debugger.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Clear"
msgstr ""
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Error saving resource!"
msgstr ""
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Save Resource As.."
msgstr ""
-#: editor/editor_node.cpp editor/export_template_manager.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "I see.."
msgstr ""
@@ -1524,6 +1376,26 @@ msgid "Error while saving."
msgstr ""
#: editor/editor_node.cpp
+msgid "Can't open '%s'."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Error while parsing '%s'."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Unexpected end of file '%s'."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Missing '%s' or its dependencies."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Error while loading '%s'."
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Saving Scene"
msgstr ""
@@ -1581,6 +1453,33 @@ msgid "Restored default layout to base settings."
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was imported, so it's not editable.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was instanced or inherited.\n"
+"Changes to it will not be kept when saving the current scene."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource was imported, so it's not editable. Change its settings in the "
+"import panel and then re-import."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This scene was imported, so changes to it will not be kept.\n"
+"Instancing it or inheriting will allow making changes to it.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Copy Params"
msgstr ""
@@ -1742,24 +1641,35 @@ msgid "Save changes the following scene(s) before opening Project Manager?"
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"This option is deprecated. Situations where refresh must be forced are now "
+"considered a bug. Please report."
+msgstr ""
+
+#: editor/editor_node.cpp
#, fuzzy
msgid "Pick a Main Scene"
msgstr "ایک مینو منظر چنیں"
#: editor/editor_node.cpp
-msgid "Unable to enable addon plugin at: '"
+msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr ""
#: editor/editor_node.cpp
-msgid "' parsing of config failed."
+msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/"
+msgid "Unable to load addon script from path: '%s'."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to load addon script from path: '"
+msgid ""
+"Unable to load addon script from path: '%s' Base type is not EditorPlugin."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Unable to load addon script from path: '%s' Script is not in tool mode."
msgstr ""
#: editor/editor_node.cpp
@@ -1769,7 +1679,7 @@ msgid ""
msgstr ""
#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/scene_tree_dock.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Ugh"
msgstr ""
@@ -1780,11 +1690,11 @@ msgid ""
msgstr ""
#: editor/editor_node.cpp
-msgid "Error loading scene."
+msgid "Scene '%s' has broken dependencies:"
msgstr ""
#: editor/editor_node.cpp
-msgid "Scene '%s' has broken dependencies:"
+msgid "Clear Recent Scenes"
msgstr ""
#: editor/editor_node.cpp
@@ -1820,7 +1730,7 @@ msgstr ""
msgid "Toggle distraction-free mode."
msgstr ""
-#: editor/editor_node.cpp editor/io_plugins/editor_scene_import_plugin.cpp
+#: editor/editor_node.cpp
msgid "Scene"
msgstr ""
@@ -2039,6 +1949,10 @@ msgstr ""
msgid "Issue Tracker"
msgstr ""
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+msgid "Community"
+msgstr "کمیونٹی"
+
#: editor/editor_node.cpp
msgid "About"
msgstr ""
@@ -2047,7 +1961,7 @@ msgstr ""
msgid "Play the project."
msgstr ""
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Play"
msgstr ""
@@ -2063,7 +1977,7 @@ msgstr ""
msgid "Stop the scene."
msgstr ""
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Stop"
msgstr ""
@@ -2136,6 +2050,15 @@ msgid "Object properties."
msgstr ""
#: editor/editor_node.cpp
+msgid "Changes may be lost!"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Import"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "FileSystem"
msgstr ""
@@ -2151,14 +2074,6 @@ msgstr ""
msgid "Don't Save"
msgstr ""
-#: editor/editor_node.cpp editor/editor_reimport_dialog.cpp
-msgid "Re-Import"
-msgstr ""
-
-#: editor/editor_node.cpp editor/editor_plugin_settings.cpp
-msgid "Update"
-msgstr ""
-
#: editor/editor_node.cpp
msgid "Import Templates From ZIP File"
msgstr ""
@@ -2220,11 +2135,28 @@ msgstr ""
msgid "Open the previous Editor"
msgstr ""
+#: editor/editor_plugin.cpp
+msgid "Creating Mesh Previews"
+msgstr ""
+
+#: editor/editor_plugin.cpp
+msgid "Thumbnail.."
+msgstr ""
+
#: editor/editor_plugin_settings.cpp
msgid "Installed Plugins:"
msgstr ""
#: editor/editor_plugin_settings.cpp
+msgid "Update"
+msgstr ""
+
+#: editor/editor_plugin_settings.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Version:"
+msgstr ""
+
+#: editor/editor_plugin_settings.cpp
msgid "Author:"
msgstr ""
@@ -2257,7 +2189,7 @@ msgid "Frame %"
msgstr ""
#: editor/editor_profiler.cpp
-msgid "Fixed Frame %"
+msgid "Physics Frame %"
msgstr ""
#: editor/editor_profiler.cpp editor/script_editor_debugger.cpp
@@ -2276,26 +2208,6 @@ msgstr ""
msgid "Frame #:"
msgstr ""
-#: editor/editor_reimport_dialog.cpp
-msgid "Please wait for scan to complete."
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Current scene must be saved to re-import."
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Save & Re-Import"
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Importing"
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Import Changed Resources"
-msgstr ""
-
#: editor/editor_run_native.cpp
msgid "Select device from the list"
msgstr ""
@@ -2405,10 +2317,6 @@ msgid "Importing:"
msgstr ""
#: editor/export_template_manager.cpp
-msgid "Loading Export Templates"
-msgstr ""
-
-#: editor/export_template_manager.cpp
msgid "Current Version:"
msgstr ""
@@ -2442,9 +2350,17 @@ msgid "Cannot navigate to '"
msgstr ""
#: editor/filesystem_dock.cpp
+msgid "View items as a grid of thumbnails"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "View items as a list"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
msgid ""
"\n"
-"Status: Needs Re-Import"
+"Status: Import of file failed. Please fix file and reimport manually."
msgstr ""
#: editor/filesystem_dock.cpp
@@ -2454,87 +2370,87 @@ msgid ""
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Same source and destination files, doing nothing."
+msgid "Cannot move/rename resources root."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Target file exists, can't overwrite. Delete first."
+msgid "Cannot move a folder into itself.\n"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Same source and destination paths, doing nothing."
+msgid "Error moving:\n"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Can't move directories to within themselves."
+msgid "Unable to update dependencies:\n"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Can't rename deps for:\n"
+msgid "No name provided"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Error moving file:\n"
+msgid "Provided name contains invalid characters"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Error moving dir:\n"
+msgid "No name provided."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Can't operate on '..'"
+msgid "Name contains invalid characters."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Pick New Name and Location For:"
+msgid "A file or folder with this name already exists."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "No files selected!"
+msgid "Renaming file:"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Expand all"
+msgid "Renaming folder:"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Collapse all"
+msgid "Expand all"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Show In File Manager"
+msgid "Collapse all"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Instance"
+msgid "Copy Path"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Edit Dependencies.."
+msgid "Rename.."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "View Owners.."
+msgid "Move To.."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Copy Path"
+msgid "New Folder.."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Rename or Move.."
+msgid "Show In File Manager"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Move To.."
+msgid "Instance"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Info"
+msgid "Edit Dependencies.."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Re-Import.."
+msgid "View Owners.."
msgstr ""
#: editor/filesystem_dock.cpp
@@ -2567,6 +2483,11 @@ msgstr ""
msgid "Move"
msgstr ""
+#: editor/filesystem_dock.cpp editor/plugins/animation_tree_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Rename"
+msgstr ""
+
#: editor/groups_editor.cpp
msgid "Add to Group"
msgstr ""
@@ -2580,6 +2501,10 @@ msgid "Import as Single Scene"
msgstr ""
#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
msgid "Import with Separate Materials"
msgstr ""
@@ -2592,6 +2517,18 @@ msgid "Import with Separate Objects+Materials"
msgstr ""
#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Materials+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Materials+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
msgid "Import as Multiple Scenes"
msgstr ""
@@ -2600,38 +2537,31 @@ msgid "Import as Multiple Scenes+Materials"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Import Scene"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Importing Scene.."
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Running Custom Script.."
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Couldn't load post-import script:"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Invalid/broken script for post-import (check console):"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Error running post-import script:"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Saving.."
msgstr ""
@@ -2659,579 +2589,54 @@ msgstr ""
msgid "Reimport"
msgstr ""
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "No bit masks to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path is empty."
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must be a complete resource path."
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must exist."
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Save path is empty!"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Import BitMasks"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s):"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Target Path:"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Accept"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Bit Mask"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No source font file!"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No target font resource!"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"Invalid file extension.\n"
-"Please use .font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Can't load/process source font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Couldn't save font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font Size:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Dest Resource:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "The quick brown fox jumps over the lazy dog."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Test:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Options:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Font Import"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"This file is already a Godot font file, please supply a BMFont type file "
-"instead."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Failed opening as BMFont file."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error initializing FreeType."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Unknown font format."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error loading font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Invalid font size."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Invalid font custom source."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/plugins/theme_editor_plugin.cpp
-msgid "Font"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "No meshes to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Single Mesh Import"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Source Mesh(es):"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/plugins/mesh_instance_editor_plugin.cpp
-msgid "Mesh"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Surface %d"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "No samples to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Import Audio Samples"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Source Sample(s):"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Audio Sample"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "New Clip"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Animation Options"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Flags"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Bake FPS:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Optimizer"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Linear Error"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angular Error"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angle"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Clips"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Start(s)"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "End(s)"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Loop"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Filters"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source path is empty."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't load post-import script."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Invalid/broken script for post-import."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Error importing scene."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import 3D Scene"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source Scene:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Same as Target Scene"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Shared"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Target Texture Folder:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Post-Process Script:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Custom Root Node Type:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Auto"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Root Node Name:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "The Following Files are Missing:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Anyway"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp scene/gui/dialogs.cpp
-msgid "Cancel"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import & Open"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Edited scene has not been saved, open imported scene anyway?"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Image:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Can't import a file over itself:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't localize path: %s (already local)"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "3D Scene Animation"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Uncompressed"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossless (PNG)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossy (WebP)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress (VRAM)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Format"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Compression Quality (WebP):"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Options"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Please specify some files!"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "At least one file needed for Atlas."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Error importing:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Only one file is required for large texture."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Max Texture Size:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for Atlas (2D)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cell Size:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Large Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Textures (2D)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture"
+#: editor/multi_node_edit.cpp
+msgid "MultiNode Set"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Base Atlas Texture"
+#: editor/node_dock.cpp
+msgid "Groups"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s)"
+#: editor/node_dock.cpp
+msgid "Select a Node to edit Signals and Groups."
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 2D"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create Poly"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 3D"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Insert Point"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "2D Texture"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly (Remove Point)"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "3D Texture"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Remove Poly And Point"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Atlas Texture"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create a new polygon from scratch."
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
+#: editor/plugins/abstract_polygon_2d_editor.cpp
msgid ""
-"NOTICE: Importing 2D textures is not mandatory. Just copy png/jpg files to "
-"the project."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Crop empty space."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Load Source Image"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Slicing"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Inserting"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Saving"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save large texture:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Build Atlas For:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Loading Image:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't load image:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Converting Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cropping Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Blitting Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save atlas image:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save converted texture:"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid source!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid translation source!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Column"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/script_create_dialog.cpp
-msgid "Language"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No items to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No target path!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translations"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Couldn't import!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translation"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Source CSV:"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Ignore First Row"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Compress"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Add to Project (project.godot)"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Languages:"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Translation"
-msgstr ""
-
-#: editor/multi_node_edit.cpp
-msgid "MultiNode Set"
-msgstr ""
-
-#: editor/node_dock.cpp
-msgid "Groups"
-msgstr ""
-
-#: editor/node_dock.cpp
-msgid "Select a Node to edit Signals and Groups."
+"Edit existing polygon:\n"
+"LMB: Move Point.\n"
+"Ctrl+LMB: Split Segment.\n"
+"RMB: Erase Point."
msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
@@ -3387,7 +2792,6 @@ msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
#: editor/script_create_dialog.cpp
msgid "Error!"
@@ -3497,10 +2901,6 @@ msgid "Delete Input"
msgstr ""
#: editor/plugins/animation_tree_editor_plugin.cpp
-msgid "Rename"
-msgstr ""
-
-#: editor/plugins/animation_tree_editor_plugin.cpp
msgid "Animation tree is valid."
msgstr ""
@@ -3556,64 +2956,181 @@ msgstr ""
msgid "Filters.."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing %d Triangles:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Free"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Triangle #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Contents:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Light Baker Setup:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "View Files"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing Geometry"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve hostname:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Fixing Lights"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Making BVH"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connection error, please try again."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Light Octree"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't connect."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Octree Texture"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't connect to host:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Transfer to Lightmaps:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response from host:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Allocating Texture #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Baking Triangle #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, return code:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Post-Processing Texture #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Req. Failed."
msgstr ""
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Bake!"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, too many redirects"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Redirect Loop."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Bad download hash, assuming file has been tampered with."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Expected:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Got:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed sha256 hash check"
msgstr ""
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Reset the lightmap octree baking process (start over)."
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Asset Download Error:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Fetching:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Resolving.."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connecting.."
msgstr ""
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Requesting.."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Error making request"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Idle"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Retry"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download Error"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download for this asset is already in progress!"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "first"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "prev"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "next"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "last"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "All"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Plugins"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Sort:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Reverse"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Category:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Site:"
+msgstr "سائٹ:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Support.."
+msgstr ".سپورٹ"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Official"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Testing"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Assets ZIP File"
+msgstr "Ø§Ø«Ø§Ø«Û Ú©ÛŒ زپ Ùائل"
+
#: editor/plugins/camera_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
msgid "Preview"
msgstr ""
@@ -3656,11 +3173,15 @@ msgid "Edit CanvasItem"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Change Anchors"
+msgid "Anchors only"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Change Anchors and Margins"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom (%):"
+msgid "Change Anchors"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3712,59 +3233,72 @@ msgid "Pan Mode"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Lock the selected object in place (can't be moved)."
+msgid "Toggles snapping"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Unlock the selected object (can be moved)."
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Use Snap"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Makes sure the object's children are not selectable."
+msgid "Snapping options"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Restores the object's children's ability to be selected."
+msgid "Snap to grid"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Edit"
+msgid "Use Rotation Snap"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Use Snap"
+msgid "Configure Snap..."
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Show Grid"
+msgid "Snap Relative"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Rotation Snap"
+msgid "Use Pixel Snap"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap Relative"
+msgid "Smart snapping"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Configure Snap.."
+msgid "Snap to parent"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Pixel Snap"
+msgid "Snap to node anchor"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Skeleton.."
+msgid "Snap to node sides"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to other nodes"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Lock the selected object in place (can't be moved)."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Unlock the selected object (can be moved)."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Makes sure the object's children are not selectable."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Restores the object's children's ability to be selected."
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3793,11 +3327,16 @@ msgid "View"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Reset"
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Show Grid"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Set.."
+msgid "Show helpers"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Show rulers"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3809,7 +3348,7 @@ msgid "Frame Selection"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Anchor"
+msgid "Layout"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3833,11 +3372,20 @@ msgid "Clear Pose"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Set a Value"
+msgid "Drag pivot from mouse position"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#, fuzzy
+msgid "Set pivot at mouse position"
+msgstr ".تمام کا انتخاب"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Multiply grid step by 2"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap (Pixels):"
+msgid "Divide grid step by 2"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3848,23 +3396,28 @@ msgstr ""
msgid "Adding %s..."
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Create Node"
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Error instancing scene from %s"
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "OK :("
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "No parent to instance a child at."
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "This operation requires a single selected node."
msgstr ""
@@ -3878,45 +3431,6 @@ msgid ""
"Drag & drop + Alt : Change node type"
msgstr ""
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Create Poly"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly (Remove Point)"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Create a new polygon from scratch."
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-msgid ""
-"Edit existing polygon:\n"
-"LMB: Move Point.\n"
-"Ctrl+LMB: Split Segment.\n"
-"RMB: Erase Point."
-msgstr ""
-
#: editor/plugins/collision_polygon_editor_plugin.cpp
msgid "Create Poly3D"
msgstr ""
@@ -3926,14 +3440,6 @@ msgid "Set Handle"
msgstr ""
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Creating Mesh Library"
-msgstr ""
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Thumbnail.."
-msgstr ""
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Remove item %d?"
msgstr ""
@@ -3956,6 +3462,27 @@ msgid "Update from Scene"
msgstr ""
#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat0"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat1"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+#, fuzzy
+msgid "Ease in"
+msgstr ".تمام کا انتخاب"
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Ease out"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Smoothstep"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
msgid "Modify Curve Point"
msgstr ""
@@ -4033,22 +3560,18 @@ msgid "Create Occluder Polygon"
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Edit existing polygon:"
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "LMB: Move Point."
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Ctrl+LMB: Split Segment."
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "RMB: Erase Point."
msgstr ""
@@ -4149,6 +3672,10 @@ msgid "Create Outline"
msgstr ""
#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Mesh"
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Create Trimesh Static Body"
msgstr ""
@@ -4276,12 +3803,72 @@ msgstr ""
msgid "Populate"
msgstr ""
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Create Navigation Polygon"
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake!"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake the navigation mesh.\n"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Clear the navigation mesh."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Setting up Configuration..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Calculating grid size..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating heightfield..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Marking walkable triangles..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Constructing compact heightfield..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Eroding walkable area..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Partitioning..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating contours..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating polymesh..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Converting to native navigation mesh..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Navigation Mesh Generator Setup:"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Parsing Geometry..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Done!"
msgstr ""
#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Remove Poly And Point"
+msgid "Create Navigation Polygon"
msgstr ""
#: editor/plugins/particles_2d_editor_plugin.cpp
@@ -4455,16 +4042,19 @@ msgid "Curve Point #"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve Point Position"
-msgstr ""
+msgstr ".تمام کا انتخاب"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve In Position"
-msgstr ""
+msgstr ".تمام کا انتخاب"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve Out Position"
-msgstr ""
+msgstr ".تمام کا انتخاب"
#: editor/plugins/path_editor_plugin.cpp
msgid "Split Path"
@@ -4524,6 +4114,14 @@ msgid "Scale Polygon"
msgstr ""
#: editor/plugins/polygon_2d_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Edit"
+msgstr ""
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Polygon->UV"
msgstr ""
@@ -4578,63 +4176,10 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/shader_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr ""
-#: editor/plugins/rich_text_editor_plugin.cpp
-msgid "Parse BBCode"
-msgstr ""
-
-#: editor/plugins/sample_editor_plugin.cpp
-msgid "Length:"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Open Sample File(s)"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "ERROR: Couldn't load sample!"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Add Sample"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Rename Sample"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Delete Sample"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "16 Bits"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "8 Bits"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Stereo"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Mono"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Format"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Pitch"
-msgstr ""
-
#: editor/plugins/script_editor_plugin.cpp
msgid "Clear Recent Files"
msgstr ""
@@ -4726,6 +4271,10 @@ msgstr ""
msgid "Close All"
msgstr ""
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+msgid "Run"
+msgstr ""
+
#: editor/plugins/script_editor_plugin.cpp
msgid "Toggle Scripts Panel"
msgstr ""
@@ -4754,7 +4303,8 @@ msgstr ""
msgid "Break"
msgstr ""
-#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+#: editor/script_editor_debugger.cpp
msgid "Continue"
msgstr ""
@@ -4767,18 +4317,6 @@ msgid "Debug with external editor"
msgstr ""
#: editor/plugins/script_editor_plugin.cpp
-msgid "Window"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Left"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Right"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
msgid "Open Godot online documentation"
msgstr ""
@@ -4860,8 +4398,9 @@ msgid "Cut"
msgstr ""
#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr ""
@@ -5124,10 +4663,6 @@ msgid "View Plane Transform."
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Scaling to %s%%."
-msgstr ""
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rotating %s degrees."
msgstr ""
@@ -5144,10 +4679,6 @@ msgid "Top View."
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Top"
-msgstr ""
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rear View."
msgstr ""
@@ -5378,6 +4909,10 @@ msgid "Transform"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Configure Snap.."
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Local Coords"
msgstr ""
@@ -5523,6 +5058,10 @@ msgid "Speed (FPS):"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Loop"
+msgstr ""
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Animation Frames"
msgstr ""
@@ -5535,12 +5074,14 @@ msgid "Insert Empty (After)"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Up"
-msgstr ""
+#, fuzzy
+msgid "Move (Before)"
+msgstr "ایکشن منتقل کریں"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Down"
-msgstr ""
+#, fuzzy
+msgid "Move (After)"
+msgstr "ایکشن منتقل کریں"
#: editor/plugins/style_box_editor_plugin.cpp
msgid "StyleBox Preview:"
@@ -5618,7 +5159,11 @@ msgid "Remove All"
msgstr ".تمام کا انتخاب"
#: editor/plugins/theme_editor_plugin.cpp
-msgid "Theme"
+msgid "Edit theme.."
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Theme editing menu."
msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
@@ -5703,6 +5248,10 @@ msgid "Style"
msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
+msgid "Font"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
msgid "Color"
msgstr ""
@@ -5752,7 +5301,7 @@ msgid "Mirror Y"
msgstr ""
#: editor/plugins/tile_map_editor_plugin.cpp
-msgid "Bucket"
+msgid "Paint Tile"
msgstr ""
#: editor/plugins/tile_map_editor_plugin.cpp
@@ -5816,6 +5365,10 @@ msgid "Delete preset '%s'?"
msgstr ""
#: editor/project_export.cpp
+msgid "Export templates for this platform are missing/corrupted: "
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Presets"
msgstr ""
@@ -5886,19 +5439,29 @@ msgid "Export templates for this platform are missing:"
msgstr ""
#: editor/project_export.cpp
+msgid "Export templates for this platform are missing/corrupted:"
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Export With Debug"
msgstr ""
#: editor/project_manager.cpp
-msgid "Invalid project path, the path must exist!"
+msgid "The path does not exist."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Please choose a 'project.godot' file."
msgstr ""
#: editor/project_manager.cpp
-msgid "Invalid project path, project.godot must not exist."
+msgid ""
+"Your project will be created in a non empty folder (you might want to create "
+"a new folder)."
msgstr ""
#: editor/project_manager.cpp
-msgid "Invalid project path, project.godot must exist."
+msgid "Please choose a folder that does not contain a 'project.godot' file."
msgstr ""
#: editor/project_manager.cpp
@@ -5906,10 +5469,26 @@ msgid "Imported Project"
msgstr ""
#: editor/project_manager.cpp
+msgid " "
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "It would be a good idea to name your project."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Invalid project path (changed anything?)."
msgstr ""
#: editor/project_manager.cpp
+msgid "Couldn't get project.godot in project path."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Couldn't edit project.godot in project path."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
msgstr ""
@@ -5918,15 +5497,20 @@ msgid "The following files failed extraction from package:"
msgstr ""
#: editor/project_manager.cpp
-msgid "Import Existing Project"
+#, fuzzy
+msgid "Rename Project"
+msgstr ".تمام کا انتخاب"
+
+#: editor/project_manager.cpp
+msgid "Couldn't get project.godot in the project path."
msgstr ""
#: editor/project_manager.cpp
-msgid "Project Path (Must Exist):"
+msgid "New Game Project"
msgstr ""
#: editor/project_manager.cpp
-msgid "Project Name:"
+msgid "Import Existing Project"
msgstr ""
#: editor/project_manager.cpp
@@ -5934,19 +5518,23 @@ msgid "Create New Project"
msgstr ""
#: editor/project_manager.cpp
-msgid "Project Path:"
+msgid "Install Project:"
msgstr ""
#: editor/project_manager.cpp
-msgid "Install Project:"
+msgid "Project Name:"
msgstr ""
#: editor/project_manager.cpp
-msgid "Browse"
+msgid "Create folder"
msgstr ""
#: editor/project_manager.cpp
-msgid "New Game Project"
+msgid "Project Path:"
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Browse"
msgstr ""
#: editor/project_manager.cpp
@@ -5958,6 +5546,10 @@ msgid "Unnamed Project"
msgstr ""
#: editor/project_manager.cpp
+msgid "Can't open project"
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Are you sure to open more than one project?"
msgstr ""
@@ -5984,16 +5576,18 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
-"You are about the scan %s folders for existing Godot projects. Do you "
-"confirm?"
+"Language changed.\n"
+"The UI will update next time the editor or project manager starts."
msgstr ""
#: editor/project_manager.cpp
-msgid "Project List"
+msgid ""
+"You are about the scan %s folders for existing Godot projects. Do you "
+"confirm?"
msgstr ""
#: editor/project_manager.cpp
-msgid "Run"
+msgid "Project List"
msgstr ""
#: editor/project_manager.cpp
@@ -6018,6 +5612,10 @@ msgid "Exit"
msgstr ""
#: editor/project_manager.cpp
+msgid "Restart Now"
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Can't run project"
msgstr ""
@@ -6054,17 +5652,14 @@ msgid "Add Input Action Event"
msgstr ""
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Meta+"
msgstr ""
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Shift+"
msgstr ""
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Alt+"
msgstr ""
@@ -6125,7 +5720,7 @@ msgstr ""
msgid "Joypad Axis Index:"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Axis"
msgstr ""
@@ -6145,31 +5740,31 @@ msgstr ""
msgid "Add Event"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Device"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Button"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Left Button."
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Right Button."
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Middle Button."
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Up."
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Down."
msgstr ""
@@ -6178,7 +5773,7 @@ msgid "Add Global Property"
msgstr ""
#: editor/project_settings_editor.cpp
-msgid "Select an setting item first!"
+msgid "Select a setting item first!"
msgstr ""
#: editor/project_settings_editor.cpp
@@ -6194,6 +5789,14 @@ msgid "Delete Item"
msgstr ""
#: editor/project_settings_editor.cpp
+msgid "Can't contain '/' or ':'"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Already existing"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "Error saving settings."
msgstr ""
@@ -6234,6 +5837,14 @@ msgid "Remove Resource Remap Option"
msgstr ""
#: editor/project_settings_editor.cpp
+msgid "Changed Locale Filter"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Changed Locale Filter Mode"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "Project Settings (project.godot)"
msgstr ""
@@ -6294,6 +5905,26 @@ msgid "Locale"
msgstr ""
#: editor/project_settings_editor.cpp
+msgid "Locales Filter"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Show all locales"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Show only selected locales"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Filter mode:"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Locales:"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "AutoLoad"
msgstr ""
@@ -6343,10 +5974,18 @@ msgid "New Script"
msgstr "سب سکریپشن بنائیں"
#: editor/property_editor.cpp
+msgid "Make Unique"
+msgstr ""
+
+#: editor/property_editor.cpp
msgid "Show in File System"
msgstr ""
#: editor/property_editor.cpp
+msgid "Convert To %s"
+msgstr ""
+
+#: editor/property_editor.cpp
msgid "Error loading file: Not a resource!"
msgstr ""
@@ -6383,6 +6022,10 @@ msgid "Select Property"
msgstr ""
#: editor/property_selector.cpp
+msgid "Select Virtual Method"
+msgstr ""
+
+#: editor/property_selector.cpp
msgid "Select Method"
msgstr ""
@@ -6410,26 +6053,6 @@ msgstr ""
msgid "Reparent"
msgstr ""
-#: editor/resources_dock.cpp
-msgid "Create New Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Open Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Save Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Resource Tools"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Make Local"
-msgstr ""
-
#: editor/run_settings_dialog.cpp
msgid "Run Mode:"
msgstr ""
@@ -6556,14 +6179,6 @@ msgid "Sub-Resources:"
msgstr ""
#: editor/scene_tree_dock.cpp
-msgid "Edit Groups"
-msgstr ""
-
-#: editor/scene_tree_dock.cpp
-msgid "Edit Connections"
-msgstr ""
-
-#: editor/scene_tree_dock.cpp
msgid "Clear Inheritance"
msgstr ""
@@ -6747,6 +6362,14 @@ msgid "Invalid base path"
msgstr ""
#: editor/script_create_dialog.cpp
+msgid "Directory of the same name exists"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
+msgid "File exists, will be reused"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
msgid "Invalid extension"
msgstr ""
@@ -6789,6 +6412,10 @@ msgid "Load existing script file"
msgstr "سب سکریپشن بنائیں"
#: editor/script_create_dialog.cpp
+msgid "Language"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
msgid "Inherits"
msgstr ""
@@ -6831,6 +6458,10 @@ msgid "Function:"
msgstr ""
#: editor/script_editor_debugger.cpp
+msgid "Pick one or more items from the list to display the graph."
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
msgid "Errors"
msgstr ""
@@ -6911,6 +6542,10 @@ msgid "Type"
msgstr ""
#: editor/script_editor_debugger.cpp
+msgid "Format"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
msgid "Usage"
msgstr ""
@@ -6987,13 +6622,29 @@ msgstr ""
msgid "Change Probe Extents"
msgstr ".نوٹÙئر Ú©Û’ اکسٹنٹ Ú©Ùˆ تبدیل کیجیۓ"
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Library"
+msgstr ""
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Status"
+msgstr ""
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Libraries: "
+msgstr ""
+
+#: modules/gdnative/register_types.cpp
+msgid "GDNative"
+msgstr ""
+
#: modules/gdscript/gd_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Invalid type argument to convert(), use TYPE_* constants."
msgstr ""
".استمال کیجۓ TYPE_* constants .Ú©Û’ لیے غلط Ûیں convert() دیے گئے ارگمنٹس."
-#: modules/gdscript/gd_functions.cpp
+#: modules/gdscript/gd_functions.cpp modules/mono/glue/glue_header.h
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Not enough bytes for decoding bytes, or invalid format."
msgstr "یا تو ڈیکوڈ کرنے Ú©Û’ لئے بائیٹس Ú©Ù… Ûیں یا پھر ناقص Ùارمیٹ Ú¾Û’."
@@ -7044,10 +6695,6 @@ msgid "GridMap Duplicate Selection"
msgstr ""
#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "GridMap Paint"
-msgstr ""
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Snap View"
msgstr ""
@@ -7139,12 +6786,8 @@ msgstr ""
msgid "Pick Distance:"
msgstr ""
-#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "Tiles"
-msgstr ""
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "Areas"
+#: modules/mono/editor/mono_bottom_panel.cpp
+msgid "Builds"
msgstr ""
#: modules/visual_script/visual_script.cpp
@@ -7336,10 +6979,18 @@ msgid "Return"
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
+msgid "Call"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
msgid "Get"
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
+msgid "Script already has function '%s'"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
msgid "Change Input Value"
msgstr ""
@@ -7695,6 +7346,12 @@ msgid ""
"order for AnimatedSprite3D to display frames."
msgstr ""
+#: scene/3d/vehicle_body.cpp
+msgid ""
+"VehicleWheel serves to provide a wheel system to a VehicleBody. Please use "
+"it as a child of a VehicleBody."
+msgstr ""
+
#: scene/gui/color_picker.cpp
msgid "Raw Mode"
msgstr ""
@@ -7704,15 +7361,15 @@ msgid "Add current color as a preset"
msgstr ""
#: scene/gui/dialogs.cpp
-msgid "Alert!"
+msgid "Cancel"
msgstr ""
#: scene/gui/dialogs.cpp
-msgid "Please Confirm..."
+msgid "Alert!"
msgstr ""
-#: scene/gui/input_action.cpp
-msgid "Ctrl+"
+#: scene/gui/dialogs.cpp
+msgid "Please Confirm..."
msgstr ""
#: scene/gui/popup.cpp
@@ -7743,5 +7400,21 @@ msgid ""
"texture to some node for display."
msgstr ""
+#: scene/resources/dynamic_font.cpp
+msgid "Error initializing FreeType."
+msgstr ""
+
+#: scene/resources/dynamic_font.cpp
+msgid "Unknown font format."
+msgstr ""
+
+#: scene/resources/dynamic_font.cpp
+msgid "Error loading font."
+msgstr ""
+
+#: scene/resources/dynamic_font.cpp
+msgid "Invalid font size."
+msgstr ""
+
#~ msgid "Samples"
#~ msgstr "نمونے"
diff --git a/editor/translations/zh_CN.po b/editor/translations/zh_CN.po
index f725bf6a5e..3a67defced 100644
--- a/editor/translations/zh_CN.po
+++ b/editor/translations/zh_CN.po
@@ -1,5 +1,6 @@
# Chinese (China) translation of the Godot Engine editor
-# Copyright (C) 2016-2017 Juan Linietsky, Ariel Manzur and the Godot community
+# Copyright (C) 2007-2017 Juan Linietsky, Ariel Manzur
+# Copyright (C) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)
# This file is distributed under the same license as the Godot source code.
#
# 纯æ´çš„å蛋 <tqj.zyy@gmail.com>, 2016.
@@ -10,6 +11,7 @@
# Geequlim <geequlim@gmail.com>, 2016-2017.
# Luo Jun <vipsbpig@gmail.com>, 2016.
# oberon-tonya <360119124@qq.com>, 2016.
+# sersoong <seraphim945@qq.com>, 2017.
# wanfang liu <wanfang.liu@gmail.com>, 2016.
# Youmu <konpaku.w@gmail.com>, 2017.
#
@@ -17,15 +19,16 @@ msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2017-07-08 15:27+0800\n"
-"Last-Translator: Geequlim <geequlim@gmail.com>\n"
-"Language-Team: 汉语 <geequlim@gmail.com>\n"
+"PO-Revision-Date: 2017-09-15 08:55+0000\n"
+"Last-Translator: sersoong <seraphim945@qq.com>\n"
+"Language-Team: Chinese (Simplified) <https://hosted.weblate.org/projects/"
+"godot-engine/godot/zh_Hans/>\n"
"Language: zh_CN\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
-"X-Generator: Gtranslator 2.91.7\n"
+"X-Generator: Weblate 2.17-dev\n"
#: editor/animation_editor.cpp
msgid "Disabled"
@@ -201,10 +204,9 @@ msgid "Create %d NEW tracks and insert keys?"
msgstr "创建%d个新轨é“并æ’入关键帧?"
#: editor/animation_editor.cpp editor/create_dialog.cpp
-#: editor/editor_audio_buses.cpp
+#: editor/editor_audio_buses.cpp editor/plugins/abstract_polygon_2d_editor.cpp
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
#: editor/plugins/mesh_instance_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp editor/project_manager.cpp
#: editor/script_create_dialog.cpp
msgid "Create"
@@ -366,261 +368,6 @@ msgstr "修改数组类型"
msgid "Change Array Value"
msgstr "修改数组值"
-#: editor/asset_library_editor_plugin.cpp
-msgid "Free"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_plugin_settings.cpp
-msgid "Version:"
-msgstr "版本:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Contents:"
-msgstr "内容:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "View Files"
-msgstr "查看文件"
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_help.cpp editor/property_selector.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Description:"
-msgstr "æè¿°:"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-#: editor/project_manager.cpp
-msgid "Install"
-msgstr "安装"
-
-#: editor/asset_library_editor_plugin.cpp editor/call_dialog.cpp
-#: editor/connections_dialog.cpp editor/export_template_manager.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-#: editor/project_settings_editor.cpp editor/property_editor.cpp
-#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Close"
-msgstr "关闭"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve hostname:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Connection error, please try again."
-msgstr "连接错误,请é‡è¯•ã€‚"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't connect."
-msgstr "无法连接。"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't connect to host:"
-msgstr "无法连接到æœåŠ¡å™¨:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response from host:"
-msgstr "æœåŠ¡å™¨æ— å“应:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response."
-msgstr "æ— å“应。"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Request failed, return code:"
-msgstr "请求失败,错误代ç :"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Req. Failed."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Request failed, too many redirects"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Redirect Loop."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed:"
-msgstr "失败:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Bad download hash, assuming file has been tampered with."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Expected:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Got:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Asset Download Error:"
-msgstr "资æºä¸‹è½½å‡ºé”™:"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-msgid "Success!"
-msgstr "完æˆï¼"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Fetching:"
-msgstr "获å–:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Resolving.."
-msgstr "解æžä¸­.."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Connecting.."
-msgstr "连接中.."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Requesting.."
-msgstr "正在请求.."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Error making request"
-msgstr "请求错误"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Idle"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Retry"
-msgstr "é‡è¯•"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Download Error"
-msgstr "下载错误"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Download for this asset is already in progress!"
-msgstr "此资æºæ–‡ä»¶æ­£åœ¨ä¸‹è½½ä¸­ï¼"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "first"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "prev"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "next"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "last"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "All"
-msgstr "全部"
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
-#: editor/settings_config_dialog.cpp
-msgid "Search:"
-msgstr "æœç´¢:"
-
-#: editor/asset_library_editor_plugin.cpp editor/code_editor.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Search"
-msgstr "æœç´¢"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/project_manager.cpp
-msgid "Import"
-msgstr "导入"
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Plugins"
-msgstr "æ’件"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Sort:"
-msgstr "排åº:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Reverse"
-msgstr "å选"
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Category:"
-msgstr "分类:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Site:"
-msgstr "站点:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Support.."
-msgstr "支æŒ.."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Official"
-msgstr "官方"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-msgid "Community"
-msgstr "社区"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Testing"
-msgstr "测试"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Assets ZIP File"
-msgstr "ZIP资æºåŒ…"
-
-#: editor/call_dialog.cpp
-msgid "Method List For '%s':"
-msgstr "'%s'的方法列表:"
-
-#: editor/call_dialog.cpp modules/visual_script/visual_script_editor.cpp
-msgid "Call"
-msgstr "调用到"
-
-#: editor/call_dialog.cpp
-msgid "Method List:"
-msgstr "方法列表:"
-
-#: editor/call_dialog.cpp
-msgid "Arguments:"
-msgstr "å‚æ•°:"
-
-#: editor/call_dialog.cpp
-msgid "Return:"
-msgstr "返回:"
-
#: editor/code_editor.cpp
msgid "Go to Line"
msgstr "转到行"
@@ -657,6 +404,14 @@ msgstr "全字匹é…"
msgid "Selection Only"
msgstr "仅选中"
+#: editor/code_editor.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
+msgid "Search"
+msgstr "æœç´¢"
+
#: editor/code_editor.cpp editor/editor_help.cpp
msgid "Find"
msgstr "查找"
@@ -689,11 +444,11 @@ msgstr "æ›´æ¢æ—¶æ示"
msgid "Skip"
msgstr "跳过"
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom In"
msgstr "放大"
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom Out"
msgstr "缩å°"
@@ -760,6 +515,20 @@ msgstr "延时"
msgid "Oneshot"
msgstr "å•æ¬¡"
+#: editor/connections_dialog.cpp editor/dependency_editor.cpp
+#: editor/export_template_manager.cpp
+#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Close"
+msgstr "关闭"
+
#: editor/connections_dialog.cpp
msgid "Connect"
msgstr "连接"
@@ -785,7 +554,7 @@ msgstr "连接事件。"
msgid "Disconnect"
msgstr "删除事件连接"
-#: editor/connections_dialog.cpp editor/node_dock.cpp
+#: editor/connections_dialog.cpp editor/editor_help.cpp editor/node_dock.cpp
msgid "Signals"
msgstr "ä¿¡å·"
@@ -802,12 +571,25 @@ msgstr "收è—:"
msgid "Recent:"
msgstr "最近文件:"
+#: editor/create_dialog.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/quick_open.cpp editor/settings_config_dialog.cpp
+msgid "Search:"
+msgstr "æœç´¢:"
+
#: editor/create_dialog.cpp editor/editor_help.cpp
#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/quick_open.cpp
msgid "Matches:"
msgstr "匹é…项:"
+#: editor/create_dialog.cpp editor/editor_help.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/property_selector.cpp
+#: editor/script_editor_debugger.cpp
+msgid "Description:"
+msgstr "æè¿°:"
+
#: editor/dependency_editor.cpp
msgid "Search Replacement For:"
msgstr "æœç´¢æ›¿æ¢:"
@@ -863,6 +645,10 @@ msgid "Owners Of:"
msgstr "拥有者:"
#: editor/dependency_editor.cpp
+msgid "Remove selected files from the project? (no undo)"
+msgstr "确定从项目中删除文件?(此æ“作无法撤销)"
+
+#: editor/dependency_editor.cpp
msgid ""
"The files being removed are required by other resources in order for them to "
"work.\n"
@@ -870,8 +656,9 @@ msgid ""
msgstr "è¦åˆ é™¤çš„文件被其他资æºæ‰€ä¾èµ–,ä»ç„¶è¦åˆ é™¤å—?(无法撤销)"
#: editor/dependency_editor.cpp
-msgid "Remove selected files from the project? (no undo)"
-msgstr "确定从项目中删除文件?(此æ“作无法撤销)"
+#, fuzzy
+msgid "Cannot remove:\n"
+msgstr "无法解æž."
#: editor/dependency_editor.cpp
msgid "Error loading:"
@@ -937,19 +724,12 @@ msgid "Godot Engine contributors"
msgstr "Godot引擎贡献者"
#: editor/editor_about.cpp
-#, fuzzy
-msgid "Authors"
-msgstr "作者:"
-
-#: editor/editor_about.cpp
-#, fuzzy
msgid "Project Founders"
-msgstr "项目管ç†å™¨"
+msgstr "项目创始人"
#: editor/editor_about.cpp
-#, fuzzy
msgid "Lead Developer"
-msgstr "å¼€å‘者"
+msgstr "主è¦å¼€å‘者"
#: editor/editor_about.cpp editor/project_manager.cpp
msgid "Project Manager"
@@ -960,118 +740,153 @@ msgid "Developers"
msgstr "å¼€å‘者"
#: editor/editor_about.cpp
-msgid "License"
+msgid "Authors"
+msgstr "作者"
+
+#: editor/editor_about.cpp
+msgid "Platinum Sponsors"
msgstr ""
#: editor/editor_about.cpp
-msgid "Thirdparty License"
+msgid "Gold Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Mini Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Gold Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Silver Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+#, fuzzy
+msgid "Bronze Donors"
+msgstr "æ‹·è´åˆ°ä¸‹ä¸€è¡Œ"
+
+#: editor/editor_about.cpp
+msgid "Donors"
msgstr ""
#: editor/editor_about.cpp
+msgid "License"
+msgstr "许å¯è¯"
+
+#: editor/editor_about.cpp
+msgid "Thirdparty License"
+msgstr "第三方许å¯è¯"
+
+#: editor/editor_about.cpp
msgid ""
"Godot Engine relies on a number of thirdparty free and open source "
"libraries, all compatible with the terms of its MIT license. The following "
"is an exhaustive list of all such thirdparty components with their "
"respective copyright statements and license terms."
msgstr ""
+"Godot引擎ä¾èµ–第三方开æºä»£ç åº“,全部符åˆMIT 许å¯è¯çš„æ¡æ¬¾ã€‚下é¢åˆ—出所有第三方组"
+"件相关的版æƒå£°æ˜Žå’Œè®¸å¯åè®®æ¡æ¬¾ã€‚"
#: editor/editor_about.cpp
-#, fuzzy
msgid "All Components"
-msgstr "内容:"
+msgstr "所有组件"
#: editor/editor_about.cpp
-#, fuzzy
msgid "Components"
-msgstr "内容:"
+msgstr "组件"
#: editor/editor_about.cpp
msgid "Licenses"
-msgstr ""
+msgstr "许å¯è¯"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Error opening package file, not in zip format."
-msgstr ""
+msgstr "打开压缩包出错,éžzipæ ¼å¼ã€‚"
#: editor/editor_asset_installer.cpp
-#, fuzzy
msgid "Uncompressing Assets"
-msgstr "ä¸åŽ‹ç¼©"
+msgstr "无压缩资æº"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package Installed Successfully!"
msgstr "软件包安装æˆåŠŸï¼"
#: editor/editor_asset_installer.cpp
-#, fuzzy
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Success!"
+msgstr "完æˆï¼"
+
+#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/project_manager.cpp
+msgid "Install"
+msgstr "安装"
+
+#: editor/editor_asset_installer.cpp
msgid "Package Installer"
-msgstr "软件包安装æˆåŠŸï¼"
+msgstr "程åºåŒ…安装程åº"
#: editor/editor_audio_buses.cpp
msgid "Speakers"
-msgstr ""
+msgstr "扬声器"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Add Effect"
-msgstr "添加事件"
+msgstr "添加效果"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Rename Audio Bus"
-msgstr "打开音频Bus布局"
+msgstr "é‡å‘½å音频总线(Audio Bus)"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Toggle Audio Bus Solo"
-msgstr "打开音频Bus布局"
+msgstr "切æ¢éŸ³é¢‘独å¥"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Toggle Audio Bus Mute"
-msgstr "打开音频Bus布局"
+msgstr "切æ¢éŸ³é¢‘é™éŸ³"
#: editor/editor_audio_buses.cpp
msgid "Toggle Audio Bus Bypass Effects"
-msgstr ""
+msgstr "切æ¢éŸ³é¢‘æ—通效果"
#: editor/editor_audio_buses.cpp
msgid "Select Audio Bus Send"
-msgstr ""
+msgstr "选择音频å‘é€æ€»çº¿"
#: editor/editor_audio_buses.cpp
msgid "Add Audio Bus Effect"
-msgstr ""
+msgstr "添加音频总线效果"
#: editor/editor_audio_buses.cpp
msgid "Move Bus Effect"
-msgstr ""
+msgstr "移动总线效果"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Delete Bus Effect"
-msgstr "删除选择的节点"
+msgstr "删除音频总线效果"
#: editor/editor_audio_buses.cpp
msgid "Audio Bus, Drag and Drop to rearrange."
-msgstr ""
-
-#: editor/editor_audio_buses.cpp
-#, fuzzy
-msgid "Bus options"
-msgstr "å­åœºæ™¯é€‰é¡¹"
+msgstr "音频总线,拖放é‡æ–°æŽ’列。"
#: editor/editor_audio_buses.cpp
msgid "Solo"
-msgstr ""
+msgstr "独å¥"
#: editor/editor_audio_buses.cpp
msgid "Mute"
-msgstr ""
+msgstr "é™éŸ³"
#: editor/editor_audio_buses.cpp
msgid "Bypass"
-msgstr ""
+msgstr "æ—通"
+
+#: editor/editor_audio_buses.cpp
+msgid "Bus options"
+msgstr "音频总线选项"
#: editor/editor_audio_buses.cpp editor/plugins/tile_map_editor_plugin.cpp
#: editor/scene_tree_dock.cpp
@@ -1080,32 +895,37 @@ msgstr "æ‹·è´"
#: editor/editor_audio_buses.cpp
#, fuzzy
+msgid "Reset Volume"
+msgstr "é‡ç½®ç¼©æ”¾"
+
+#: editor/editor_audio_buses.cpp
msgid "Delete Effect"
-msgstr "删除选择的节点"
+msgstr "删除效果"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Add Audio Bus"
-msgstr "添加Bus"
+msgstr "添加音频总线(Audio Bus)"
#: editor/editor_audio_buses.cpp
msgid "Master bus can't be deleted!"
-msgstr ""
+msgstr "ä¸èƒ½åˆ é™¤ä¸»éŸ³é¢‘总线!"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Delete Audio Bus"
-msgstr "删除布局"
+msgstr "删除音频总线"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Duplicate Audio Bus"
-msgstr "å¤åˆ¶åŠ¨ç”»"
+msgstr "å¤åˆ¶éŸ³é¢‘总线"
#: editor/editor_audio_buses.cpp
#, fuzzy
+msgid "Reset Bus Volume"
+msgstr "é‡ç½®ç¼©æ”¾"
+
+#: editor/editor_audio_buses.cpp
msgid "Move Audio Bus"
-msgstr "移动动作"
+msgstr "移动音频总线"
#: editor/editor_audio_buses.cpp
msgid "Save Audio Bus Layout As.."
@@ -1121,32 +941,28 @@ msgstr "打开音频Bus布局"
#: editor/editor_audio_buses.cpp
msgid "There is no 'res://default_bus_layout.tres' file."
-msgstr ""
+msgstr "ä¸å­˜åœ¨'res://default_bus_layout.tres'文件。"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Invalid file, not an audio bus layout."
-msgstr ""
-"文件扩展åä¸åˆæ³•\n"
-"请使用.font文件。"
+msgstr "无效文件,ä¸å­˜åœ¨éŸ³é¢‘总线布局。"
#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr "添加Bus"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Create a new Bus Layout."
-msgstr "创建资æº"
+msgstr "创建一个新的总线布局。"
-#: editor/editor_audio_buses.cpp editor/script_create_dialog.cpp
+#: editor/editor_audio_buses.cpp editor/property_editor.cpp
+#: editor/script_create_dialog.cpp
msgid "Load"
msgstr "加载"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Load an existing Bus Layout."
-msgstr "从ç£ç›˜ä¸­åŠ è½½èµ„æºå¹¶ç¼–辑。"
+msgstr "加载现有的总线布局。"
#: editor/editor_audio_buses.cpp
#: editor/plugins/animation_player_editor_plugin.cpp
@@ -1154,18 +970,16 @@ msgid "Save As"
msgstr "å¦å­˜ä¸º"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Save this Bus Layout to a file."
msgstr "将音频Bus布局ä¿å­˜ä¸º.."
#: editor/editor_audio_buses.cpp editor/import_dock.cpp
-#, fuzzy
msgid "Load Default"
-msgstr "默认"
+msgstr "加载默认"
#: editor/editor_audio_buses.cpp
msgid "Load the default Bus Layout."
-msgstr ""
+msgstr "加载默认总线布局。"
#: editor/editor_autoload_settings.cpp
msgid "Invalid name."
@@ -1209,7 +1023,7 @@ msgstr "Autoload '%s'已存在ï¼"
#: editor/editor_autoload_settings.cpp
msgid "Rename Autoload"
-msgstr "移除Autoload"
+msgstr "é‡å‘½å自动加载脚本"
#: editor/editor_autoload_settings.cpp
msgid "Toggle AutoLoad Globals"
@@ -1232,7 +1046,7 @@ msgid "Rearrange Autoloads"
msgstr "é‡æŽ’åºAutoload"
#: editor/editor_autoload_settings.cpp editor/editor_file_dialog.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp scene/gui/file_dialog.cpp
+#: scene/gui/file_dialog.cpp
msgid "Path:"
msgstr "路径:"
@@ -1240,9 +1054,7 @@ msgstr "路径:"
msgid "Node Name:"
msgstr "节点å称:"
-#: editor/editor_autoload_settings.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp editor/project_manager.cpp
+#: editor/editor_autoload_settings.cpp editor/project_manager.cpp
msgid "Name"
msgstr "å称"
@@ -1267,27 +1079,27 @@ msgid "Updating scene.."
msgstr "更新场景中.."
#: editor/editor_dir_dialog.cpp
-#, fuzzy
msgid "Please select a base directory first"
-msgstr "请先ä¿å­˜åœºæ™¯ã€‚"
+msgstr "请先选择一个目录"
#: editor/editor_dir_dialog.cpp
msgid "Choose a Directory"
msgstr "选择目录"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Create Folder"
msgstr "新建目录"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: editor/editor_plugin_settings.cpp editor/plugins/theme_editor_plugin.cpp
-#: editor/project_export.cpp scene/gui/file_dialog.cpp
+#: editor/editor_plugin_settings.cpp editor/filesystem_dock.cpp
+#: editor/plugins/theme_editor_plugin.cpp editor/project_export.cpp
+#: scene/gui/file_dialog.cpp
msgid "Name:"
msgstr "å称:"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Could not create folder."
msgstr "无法创建目录。"
@@ -1305,31 +1117,7 @@ msgstr "打包中"
#: editor/editor_export.cpp platform/javascript/export/export.cpp
msgid "Template file not found:\n"
-msgstr "找ä¸åˆ°æ¨¡æ¿æ–‡ä»¶:"
-
-#: editor/editor_export.cpp
-msgid "Added:"
-msgstr "已添加:"
-
-#: editor/editor_export.cpp
-msgid "Removed:"
-msgstr "已移除:"
-
-#: editor/editor_export.cpp
-msgid "Error saving atlas:"
-msgstr "ä¿å­˜è´´å›¾é›†å‡ºé”™:"
-
-#: editor/editor_export.cpp
-msgid "Could not save atlas subtexture:"
-msgstr "无法ä¿å­˜ç²¾çµé›†å­è´´å›¾:"
-
-#: editor/editor_export.cpp
-msgid "Exporting for %s"
-msgstr "正在导出 %s"
-
-#: editor/editor_export.cpp
-msgid "Setting Up.."
-msgstr "é…ç½®.."
+msgstr "找ä¸åˆ°æ¨¡æ¿æ–‡ä»¶:\n"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "File Exists, Overwrite?"
@@ -1415,6 +1203,11 @@ msgstr "å‘上移动收è—"
msgid "Move Favorite Down"
msgstr "å‘下移动收è—"
+#: editor/editor_file_dialog.cpp
+#, fuzzy
+msgid "Go to parent folder"
+msgstr "无法创建目录。"
+
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Directories & Files:"
msgstr "目录|文件:"
@@ -1429,10 +1222,6 @@ msgid "File:"
msgstr "文件:"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
-msgid "Filter:"
-msgstr "筛选:"
-
-#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Must use a valid extension."
msgstr "必须使用åˆæ³•çš„拓展å。"
@@ -1457,6 +1246,10 @@ msgstr "类型列表:"
msgid "Search Classes"
msgstr "æœç´¢ç±»åž‹"
+#: editor/editor_help.cpp editor/plugins/spatial_editor_plugin.cpp
+msgid "Top"
+msgstr "顶部"
+
#: editor/editor_help.cpp editor/property_editor.cpp
msgid "Class:"
msgstr "ç±»:"
@@ -1473,15 +1266,30 @@ msgstr "派生类:"
msgid "Brief Description:"
msgstr "简介:"
+#: editor/editor_help.cpp
+#, fuzzy
+msgid "Members"
+msgstr "æˆå‘˜ï¼š"
+
#: editor/editor_help.cpp modules/visual_script/visual_script_editor.cpp
msgid "Members:"
msgstr "æˆå‘˜ï¼š"
#: editor/editor_help.cpp
+#, fuzzy
+msgid "Public Methods"
+msgstr "公共方法:"
+
+#: editor/editor_help.cpp
msgid "Public Methods:"
msgstr "公共方法:"
#: editor/editor_help.cpp
+#, fuzzy
+msgid "GUI Theme Items"
+msgstr "GUI主题:"
+
+#: editor/editor_help.cpp
msgid "GUI Theme Items:"
msgstr "GUI主题:"
@@ -1491,53 +1299,85 @@ msgstr "事件:"
#: editor/editor_help.cpp
#, fuzzy
+msgid "Enumerations"
+msgstr "枚举:"
+
+#: editor/editor_help.cpp
msgid "Enumerations:"
-msgstr "动画"
+msgstr "枚举:"
#: editor/editor_help.cpp
msgid "enum "
-msgstr ""
+msgstr "枚举 "
+
+#: editor/editor_help.cpp
+#, fuzzy
+msgid "Constants"
+msgstr "常é‡:"
#: editor/editor_help.cpp
msgid "Constants:"
msgstr "常é‡:"
#: editor/editor_help.cpp
+#, fuzzy
+msgid "Description"
+msgstr "æè¿°:"
+
+#: editor/editor_help.cpp
+#, fuzzy
+msgid "Properties"
+msgstr "属性:"
+
+#: editor/editor_help.cpp
msgid "Property Description:"
msgstr "属性æ述:"
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this property. Please help us by "
+"[color=$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+
+#: editor/editor_help.cpp
+#, fuzzy
+msgid "Methods"
+msgstr "方法列表:"
+
+#: editor/editor_help.cpp
msgid "Method Description:"
msgstr "方法æè¿°:"
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this method. Please help us by [color="
+"$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Search Text"
msgstr "æœç´¢æ–‡æœ¬"
#: editor/editor_log.cpp
-#, fuzzy
msgid "Output:"
-msgstr " 输出:"
+msgstr "输出:"
#: editor/editor_log.cpp editor/plugins/animation_tree_editor_plugin.cpp
-#: editor/plugins/rich_text_editor_plugin.cpp editor/property_editor.cpp
-#: editor/script_editor_debugger.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/property_editor.cpp editor/script_editor_debugger.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Clear"
msgstr "清除"
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Error saving resource!"
msgstr "ä¿å­˜èµ„æºå‡ºé”™ï¼"
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Save Resource As.."
msgstr "资æºå¦å­˜ä¸º.."
-#: editor/editor_node.cpp editor/export_template_manager.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "I see.."
msgstr "好å§.."
@@ -1554,6 +1394,30 @@ msgid "Error while saving."
msgstr "ä¿å­˜å‡ºé”™ã€‚"
#: editor/editor_node.cpp
+#, fuzzy
+msgid "Can't open '%s'."
+msgstr "无法对'..'引用æ“作"
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Error while parsing '%s'."
+msgstr "ä¿å­˜å‡ºé”™ã€‚"
+
+#: editor/editor_node.cpp
+msgid "Unexpected end of file '%s'."
+msgstr ""
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Missing '%s' or its dependencies."
+msgstr "场景'%s'çš„ä¾èµ–已被破å:"
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Error while loading '%s'."
+msgstr "ä¿å­˜å‡ºé”™ã€‚"
+
+#: editor/editor_node.cpp
msgid "Saving Scene"
msgstr "正在ä¿å­˜åœºæ™¯"
@@ -1566,7 +1430,6 @@ msgid "Creating Thumbnail"
msgstr "创建缩略图"
#: editor/editor_node.cpp
-#, fuzzy
msgid "This operation can't be done without a tree root."
msgstr "æ­¤æ“作必须在打开一个场景åŽæ‰èƒ½æ‰§è¡Œã€‚"
@@ -1612,6 +1475,33 @@ msgid "Restored default layout to base settings."
msgstr "é‡ç½®ä¸ºé»˜è®¤å¸ƒå±€è®¾ç½®ã€‚"
#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was imported, so it's not editable.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was instanced or inherited.\n"
+"Changes to it will not be kept when saving the current scene."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource was imported, so it's not editable. Change its settings in the "
+"import panel and then re-import."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This scene was imported, so changes to it will not be kept.\n"
+"Instancing it or inheriting will allow making changes to it.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Copy Params"
msgstr "æ‹·è´å‚æ•°"
@@ -1633,7 +1523,7 @@ msgstr "使之内置"
#: editor/editor_node.cpp
msgid "Make Sub-Resources Unique"
-msgstr "使å­èµ„æºå”¯ä¸€åŒ–"
+msgstr "转æ¢ä¸ºç‹¬ç«‹å­èµ„æº"
#: editor/editor_node.cpp
msgid "Open in Help"
@@ -1695,13 +1585,12 @@ msgid "Quick Open Script.."
msgstr "快速打开脚本.."
#: editor/editor_node.cpp
-#, fuzzy
msgid "Save & Close"
-msgstr "ä¿å­˜æ–‡ä»¶"
+msgstr "ä¿å­˜å¹¶å…³é—­"
#: editor/editor_node.cpp
msgid "Save changes to '%s' before closing?"
-msgstr ""
+msgstr "在关闭å‰ä¿å­˜æ›´æ”¹åˆ° %s å—?"
#: editor/editor_node.cpp
msgid "Save Scene As.."
@@ -1725,16 +1614,15 @@ msgstr "æ­¤æ“作必须在打开一个场景åŽæ‰èƒ½æ‰§è¡Œã€‚"
#: editor/editor_node.cpp
msgid "Export Mesh Library"
-msgstr "导出MeshLibrary"
+msgstr "导出网格库(Mesh Library)"
#: editor/editor_node.cpp
msgid "Export Tile Set"
-msgstr "导出砖å—集"
+msgstr "导出砖å—集(Tile Set)"
#: editor/editor_node.cpp
-#, fuzzy
msgid "This operation can't be done without a selected node."
-msgstr "æ­¤æ“作必须在打开一个场景åŽæ‰èƒ½æ‰§è¡Œã€‚"
+msgstr "æ­¤æ“作必须先选择一个nodeæ‰èƒ½æ‰§è¡Œã€‚"
#: editor/editor_node.cpp
msgid "Current scene not saved. Open anyway?"
@@ -1765,21 +1653,25 @@ msgid "Exit the editor?"
msgstr "确定è¦é€€å‡ºç¼–辑器å—?"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Open Project Manager?"
-msgstr "项目管ç†å™¨"
+msgstr "打开项目管ç†å™¨ï¼Ÿ"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Save & Quit"
-msgstr "ä¿å­˜æ–‡ä»¶"
+msgstr "ä¿å­˜åŽé€€å‡º"
#: editor/editor_node.cpp
msgid "Save changes to the following scene(s) before quitting?"
-msgstr ""
+msgstr "以下场景在退出å‰ä¿å­˜æ›´æ”¹å—?"
#: editor/editor_node.cpp
msgid "Save changes the following scene(s) before opening Project Manager?"
+msgstr "在打开项目管ç†å™¨ä¹‹å‰ä¿å­˜æ›´æ”¹å—?"
+
+#: editor/editor_node.cpp
+msgid ""
+"This option is deprecated. Situations where refresh must be forced are now "
+"considered a bug. Please report."
msgstr ""
#: editor/editor_node.cpp
@@ -1787,20 +1679,30 @@ msgid "Pick a Main Scene"
msgstr "选择主场景"
#: editor/editor_node.cpp
-msgid "Unable to enable addon plugin at: '"
-msgstr ""
+#, fuzzy
+msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
+msgstr "无法å¯ç”¨æ’件: '"
#: editor/editor_node.cpp
-msgid "' parsing of config failed."
-msgstr ""
+#, fuzzy
+msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
+msgstr "在æ’件目录中没有找到脚本: 'res://addons/"
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/"
-msgstr ""
+#, fuzzy
+msgid "Unable to load addon script from path: '%s'."
+msgstr "无法从路径加载æ’件脚本: '"
#: editor/editor_node.cpp
-msgid "Unable to load addon script from path: '"
-msgstr ""
+#, fuzzy
+msgid ""
+"Unable to load addon script from path: '%s' Base type is not EditorPlugin."
+msgstr "无法从路径加载æ’件脚本: '"
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Unable to load addon script from path: '%s' Script is not in tool mode."
+msgstr "无法从路径加载æ’件脚本: '"
#: editor/editor_node.cpp
msgid ""
@@ -1808,12 +1710,12 @@ msgid ""
"To make changes to it, a new inherited scene can be created."
msgstr ""
"自动导入的场景'%s'无法修改。\n"
-"è¦è¿›è¡Œæ›´æ”¹ï¼Œå¯ä»¥åˆ›å»ºä¸€ä¸ªæ–°çš„场景继承自它。"
+"如è¦æ›´æ”¹ï¼Œè¯·åˆ›å»ºä¸€ä¸ªæ–°çš„备份场景。"
#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/scene_tree_dock.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Ugh"
-msgstr "é¢"
+msgstr "呃"
#: editor/editor_node.cpp
msgid ""
@@ -1823,14 +1725,15 @@ msgstr ""
"加载场景出错,场景必须放在项目目录下。请å°è¯•ä½¿ç”¨'导入'èœå•å¯¼å…¥æ­¤åœºæ™¯åŽå†è¯•ã€‚"
#: editor/editor_node.cpp
-msgid "Error loading scene."
-msgstr "加载场景出错。"
-
-#: editor/editor_node.cpp
msgid "Scene '%s' has broken dependencies:"
msgstr "场景'%s'çš„ä¾èµ–已被破å:"
#: editor/editor_node.cpp
+#, fuzzy
+msgid "Clear Recent Scenes"
+msgstr "清ç†å½“å‰æ–‡ä»¶"
+
+#: editor/editor_node.cpp
msgid "Save Layout"
msgstr "ä¿å­˜å¸ƒå±€"
@@ -1860,11 +1763,10 @@ msgid "Distraction Free Mode"
msgstr "无干扰模å¼"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Toggle distraction-free mode."
-msgstr "无干扰模å¼"
+msgstr "切æ¢æ— å¹²æ‰°æ¨¡å¼ã€‚"
-#: editor/editor_node.cpp editor/io_plugins/editor_scene_import_plugin.cpp
+#: editor/editor_node.cpp
msgid "Scene"
msgstr "场景"
@@ -2090,7 +1992,11 @@ msgstr "问答"
#: editor/editor_node.cpp
msgid "Issue Tracker"
-msgstr ""
+msgstr "问题跟踪器"
+
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+msgid "Community"
+msgstr "社区"
#: editor/editor_node.cpp
msgid "About"
@@ -2100,7 +2006,7 @@ msgstr "关于"
msgid "Play the project."
msgstr "è¿è¡Œæ­¤é¡¹ç›®ï¼ˆF5)。"
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Play"
msgstr "播放"
@@ -2116,7 +2022,7 @@ msgstr "æš‚åœè¿è¡Œåœºæ™¯"
msgid "Stop the scene."
msgstr "åœæ­¢è¿è¡Œåœºæ™¯ã€‚"
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Stop"
msgstr "åœæ­¢"
@@ -2189,6 +2095,16 @@ msgid "Object properties."
msgstr "对象属性。"
#: editor/editor_node.cpp
+#, fuzzy
+msgid "Changes may be lost!"
+msgstr "修改图片分组"
+
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Import"
+msgstr "导入"
+
+#: editor/editor_node.cpp
msgid "FileSystem"
msgstr "文件系统"
@@ -2202,15 +2118,7 @@ msgstr "输出"
#: editor/editor_node.cpp
msgid "Don't Save"
-msgstr ""
-
-#: editor/editor_node.cpp editor/editor_reimport_dialog.cpp
-msgid "Re-Import"
-msgstr "é‡æ–°å¯¼å…¥"
-
-#: editor/editor_node.cpp editor/editor_plugin_settings.cpp
-msgid "Update"
-msgstr "æ›´æ–°"
+msgstr "ä¸ä¿å­˜"
#: editor/editor_node.cpp
msgid "Import Templates From ZIP File"
@@ -2237,9 +2145,8 @@ msgid "Open & Run a Script"
msgstr "打开并è¿è¡Œè„šæœ¬"
#: editor/editor_node.cpp
-#, fuzzy
msgid "New Inherited"
-msgstr "从现有场景中创建.."
+msgstr "从现有场景中创建"
#: editor/editor_node.cpp
msgid "Load Errors"
@@ -2273,11 +2180,29 @@ msgstr "打开下一个编辑器"
msgid "Open the previous Editor"
msgstr "打开上一个编辑器"
+#: editor/editor_plugin.cpp
+#, fuzzy
+msgid "Creating Mesh Previews"
+msgstr "创建 Mesh(网格) 库"
+
+#: editor/editor_plugin.cpp
+msgid "Thumbnail.."
+msgstr "缩略图.."
+
#: editor/editor_plugin_settings.cpp
msgid "Installed Plugins:"
msgstr "已安装æ’件:"
#: editor/editor_plugin_settings.cpp
+msgid "Update"
+msgstr "æ›´æ–°"
+
+#: editor/editor_plugin_settings.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Version:"
+msgstr "版本:"
+
+#: editor/editor_plugin_settings.cpp
msgid "Author:"
msgstr "作者:"
@@ -2310,8 +2235,9 @@ msgid "Frame %"
msgstr "渲染速度"
#: editor/editor_profiler.cpp
-msgid "Fixed Frame %"
-msgstr "物ç†é€Ÿåº¦"
+#, fuzzy
+msgid "Physics Frame %"
+msgstr "固定帧速率 %"
#: editor/editor_profiler.cpp editor/script_editor_debugger.cpp
msgid "Time:"
@@ -2329,35 +2255,17 @@ msgstr "自身"
msgid "Frame #:"
msgstr "帧åºå·:"
-#: editor/editor_reimport_dialog.cpp
-msgid "Please wait for scan to complete."
-msgstr "扫æ中,请ç¨åŽ..."
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Current scene must be saved to re-import."
-msgstr "需è¦å…ˆä¿å­˜å½“å‰åœºæ™¯æ‰èƒ½é‡æ–°å¯¼å…¥ã€‚"
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Save & Re-Import"
-msgstr "ä¿å­˜å¹¶é‡æ–°å¯¼å…¥"
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Importing"
-msgstr "é‡æ–°å¯¼å…¥"
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Import Changed Resources"
-msgstr "é‡æ–°å¯¼å…¥æ”¹å˜çš„资æº"
-
#: editor/editor_run_native.cpp
msgid "Select device from the list"
-msgstr ""
+msgstr "从列表中选择设备"
#: editor/editor_run_native.cpp
msgid ""
"No runnable export preset found for this platform.\n"
"Please add a runnable preset in the export menu."
msgstr ""
+"没有这个平å°çš„导出é…置。\n"
+"请在导出èœå•ä¸­æ·»åŠ é…置。"
#: editor/editor_run_script.cpp
msgid "Write your logic in the _run() method."
@@ -2425,7 +2333,7 @@ msgstr "(当å‰)"
#: editor/export_template_manager.cpp
msgid "Remove template version '%s'?"
-msgstr "移除版本为 '%s' 的模æ¿"
+msgstr "移除版本为 '%s' 的模�"
#: editor/export_template_manager.cpp
msgid "Can't open export templates zip."
@@ -2447,7 +2355,7 @@ msgstr "模æ¿ä¸­æ²¡æœ‰æ‰¾åˆ°version.txt文件。"
#: editor/export_template_manager.cpp
msgid "Error creating path for templates:\n"
-msgstr "无法将模æ¿ä¿å­˜åˆ°ä»¥ä¸‹æ–‡ä»¶:"
+msgstr "无法将模æ¿ä¿å­˜åˆ°ä»¥ä¸‹æ–‡ä»¶:\n"
#: editor/export_template_manager.cpp
msgid "Extracting Export Templates"
@@ -2458,10 +2366,6 @@ msgid "Importing:"
msgstr "导入:"
#: editor/export_template_manager.cpp
-msgid "Loading Export Templates"
-msgstr "正在加载导出模æ¿"
-
-#: editor/export_template_manager.cpp
msgid "Current Version:"
msgstr "当å‰ç‰ˆæœ¬:"
@@ -2491,63 +2395,82 @@ msgstr "无法以å¯å†™æ–¹å¼æ‰“å¼€file_type_cache.cchï¼"
#: editor/filesystem_dock.cpp
msgid "Cannot navigate to '"
-msgstr "无法导航到 "
+msgstr "无法导航到 '"
+
+#: editor/filesystem_dock.cpp
+msgid "View items as a grid of thumbnails"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "View items as a list"
+msgstr ""
#: editor/filesystem_dock.cpp
-#, fuzzy
msgid ""
"\n"
-"Status: Needs Re-Import"
-msgstr "ä¿å­˜å¹¶é‡æ–°å¯¼å…¥"
+"Status: Import of file failed. Please fix file and reimport manually."
+msgstr ""
#: editor/filesystem_dock.cpp
-#, fuzzy
msgid ""
"\n"
"Source: "
-msgstr "æº:"
+msgstr ""
+"\n"
+"æº: "
#: editor/filesystem_dock.cpp
-msgid "Same source and destination files, doing nothing."
-msgstr "æºæ–‡ä»¶å’Œç›®æ ‡æ–‡ä»¶ç›¸åŒï¼Œæ“作忽略。"
+#, fuzzy
+msgid "Cannot move/rename resources root."
+msgstr "无法加载/处ç†æºå­—体。"
#: editor/filesystem_dock.cpp
-msgid "Target file exists, can't overwrite. Delete first."
-msgstr ""
+#, fuzzy
+msgid "Cannot move a folder into itself.\n"
+msgstr "ä¸å…许导入文件本身:"
+
+#: editor/filesystem_dock.cpp
+#, fuzzy
+msgid "Error moving:\n"
+msgstr "移动目录出错:\n"
#: editor/filesystem_dock.cpp
-msgid "Same source and destination paths, doing nothing."
-msgstr "æºè·¯å¾„和目标路径相åŒï¼Œæ“作忽略。"
+#, fuzzy
+msgid "Unable to update dependencies:\n"
+msgstr "场景'%s'çš„ä¾èµ–已被破å:"
#: editor/filesystem_dock.cpp
-msgid "Can't move directories to within themselves."
-msgstr "无法将目录移动到自身下。"
+msgid "No name provided"
+msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Can't rename deps for:\n"
+msgid "Provided name contains invalid characters"
msgstr ""
#: editor/filesystem_dock.cpp
#, fuzzy
-msgid "Error moving file:\n"
-msgstr "加载图片出错:"
+msgid "No name provided."
+msgstr "移动或é‡å‘½å.."
#: editor/filesystem_dock.cpp
#, fuzzy
-msgid "Error moving dir:\n"
-msgstr "导入出错:"
+msgid "Name contains invalid characters."
+msgstr "字符åˆæ³•:"
#: editor/filesystem_dock.cpp
-msgid "Can't operate on '..'"
-msgstr "无法对'..'引用æ“作"
+#, fuzzy
+msgid "A file or folder with this name already exists."
+msgstr "分组å称已存在ï¼"
#: editor/filesystem_dock.cpp
-msgid "Pick New Name and Location For:"
-msgstr "选择新å称和路径:"
+#, fuzzy
+msgid "Renaming file:"
+msgstr "é‡å‘½åå˜é‡"
#: editor/filesystem_dock.cpp
-msgid "No files selected!"
-msgstr "没有选中任何文件ï¼"
+#, fuzzy
+msgid "Renaming folder:"
+msgstr "é‡å‘½å节点"
#: editor/filesystem_dock.cpp
msgid "Expand all"
@@ -2558,40 +2481,38 @@ msgid "Collapse all"
msgstr "收起所有"
#: editor/filesystem_dock.cpp
-msgid "Show In File Manager"
-msgstr "在资æºç®¡ç†å™¨ä¸­æ‰“å¼€"
-
-#: editor/filesystem_dock.cpp
-msgid "Instance"
-msgstr "创建实例节点"
+msgid "Copy Path"
+msgstr "æ‹·è´è·¯å¾„"
#: editor/filesystem_dock.cpp
-msgid "Edit Dependencies.."
-msgstr "编辑ä¾èµ–.."
+#, fuzzy
+msgid "Rename.."
+msgstr "é‡å‘½å"
#: editor/filesystem_dock.cpp
-msgid "View Owners.."
-msgstr "查看所有者.."
+msgid "Move To.."
+msgstr "移动.."
#: editor/filesystem_dock.cpp
-msgid "Copy Path"
-msgstr "æ‹·è´è·¯å¾„"
+#, fuzzy
+msgid "New Folder.."
+msgstr "新建目录"
#: editor/filesystem_dock.cpp
-msgid "Rename or Move.."
-msgstr "移动或é‡å‘½å.."
+msgid "Show In File Manager"
+msgstr "在资æºç®¡ç†å™¨ä¸­æ‰“å¼€"
#: editor/filesystem_dock.cpp
-msgid "Move To.."
-msgstr "移动.."
+msgid "Instance"
+msgstr "创建实例节点"
#: editor/filesystem_dock.cpp
-msgid "Info"
-msgstr "ä¿¡æ¯"
+msgid "Edit Dependencies.."
+msgstr "编辑ä¾èµ–.."
#: editor/filesystem_dock.cpp
-msgid "Re-Import.."
-msgstr "é‡æ–°å¯¼å…¥.."
+msgid "View Owners.."
+msgstr "查看所有者.."
#: editor/filesystem_dock.cpp
msgid "Previous Directory"
@@ -2618,11 +2539,18 @@ msgid ""
"Scanning Files,\n"
"Please Wait.."
msgstr ""
+"扫æ文件,\n"
+"请ç¨å€™ã€‚"
#: editor/filesystem_dock.cpp
msgid "Move"
msgstr "移动"
+#: editor/filesystem_dock.cpp editor/plugins/animation_tree_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Rename"
+msgstr "é‡å‘½å"
+
#: editor/groups_editor.cpp
msgid "Add to Group"
msgstr "添加到分组"
@@ -2632,78 +2560,89 @@ msgid "Remove from Group"
msgstr "从分组中移除"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Import as Single Scene"
-msgstr "导入场景.."
+msgstr "导入为独立场景"
+
+#: editor/import/resource_importer_scene.cpp
+#, fuzzy
+msgid "Import with Separate Animations"
+msgstr "导入独立æè´¨"
#: editor/import/resource_importer_scene.cpp
msgid "Import with Separate Materials"
-msgstr ""
+msgstr "导入独立æè´¨"
#: editor/import/resource_importer_scene.cpp
msgid "Import with Separate Objects"
-msgstr ""
+msgstr "导入独立物体"
#: editor/import/resource_importer_scene.cpp
msgid "Import with Separate Objects+Materials"
-msgstr ""
+msgstr "导入独立物体 + æè´¨"
#: editor/import/resource_importer_scene.cpp
#, fuzzy
+msgid "Import with Separate Objects+Animations"
+msgstr "导入独立物体 + æè´¨"
+
+#: editor/import/resource_importer_scene.cpp
+#, fuzzy
+msgid "Import with Separate Materials+Animations"
+msgstr "导入独立æè´¨"
+
+#: editor/import/resource_importer_scene.cpp
+#, fuzzy
+msgid "Import with Separate Objects+Materials+Animations"
+msgstr "导入独立物体 + æè´¨"
+
+#: editor/import/resource_importer_scene.cpp
msgid "Import as Multiple Scenes"
-msgstr "导入3D场景"
+msgstr "导入多个场景"
#: editor/import/resource_importer_scene.cpp
msgid "Import as Multiple Scenes+Materials"
-msgstr ""
+msgstr "导入多个场景 + æè´¨"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Import Scene"
msgstr "导入场景"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Importing Scene.."
msgstr "导入场景.."
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Running Custom Script.."
msgstr "执行自定义脚本.."
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Couldn't load post-import script:"
msgstr "无法载入åŽå¯¼å…¥è„šæœ¬:"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Invalid/broken script for post-import (check console):"
msgstr "åŽå¤„ç†è„šæœ¬è¢«æŸå或ä¸åˆæ³•ï¼ˆæŸ¥çœ‹æŽ§åˆ¶å°ï¼‰:"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Error running post-import script:"
msgstr "åŽå¤„ç†è„šæœ¬è¿è¡Œå‘生错误:"
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Saving.."
msgstr "ä¿å­˜ä¸­..."
#: editor/import_dock.cpp
msgid "Set as Default for '%s'"
-msgstr ""
+msgstr "将默认设置为 '%s'"
#: editor/import_dock.cpp
msgid "Clear Default for '%s'"
-msgstr ""
+msgstr "清除默认'%s'"
#: editor/import_dock.cpp
msgid " Files"
-msgstr "文件"
+msgstr " 文件"
#: editor/import_dock.cpp
msgid "Import As:"
@@ -2717,574 +2656,6 @@ msgstr "预设.."
msgid "Reimport"
msgstr "é‡æ–°å¯¼å…¥"
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "No bit masks to import!"
-msgstr "没有è¦å¯¼å…¥çš„bit masksï¼"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path is empty."
-msgstr "目标路径为空。"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must be a complete resource path."
-msgstr "目标路径必须是一个完整的资æºæ–‡ä»¶è·¯å¾„。"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must exist."
-msgstr "目标路径必须存在。"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Save path is empty!"
-msgstr "ä¿å­˜è·¯å¾„为空ï¼"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Import BitMasks"
-msgstr "导入BitMask"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s):"
-msgstr "æºè´´å›¾:"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Target Path:"
-msgstr "目标路径:"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Accept"
-msgstr "接å—"
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Bit Mask"
-msgstr "ä½æŽ©ç ï¼ˆBitMask)"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No source font file!"
-msgstr "请设置æºå­—体文件ï¼"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No target font resource!"
-msgstr "请设置目标字体资æºï¼"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"Invalid file extension.\n"
-"Please use .font."
-msgstr ""
-"文件扩展åä¸åˆæ³•\n"
-"请使用.font文件。"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Can't load/process source font."
-msgstr "无法加载/处ç†æºå­—体。"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Couldn't save font."
-msgstr "无法ä¿å­˜å­—体。"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font:"
-msgstr "æºå­—体文件:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font Size:"
-msgstr "æºå­—体大å°:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Dest Resource:"
-msgstr "目标资æº:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "The quick brown fox jumps over the lazy dog."
-msgstr ""
-"The quick brown fox jumps over the lazy dog.\n"
-"我能åžä¸‹çŽ»ç’ƒè€Œä¸ä¼¤èº«ä½“。"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Test:"
-msgstr "测试:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Options:"
-msgstr "选项:"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Font Import"
-msgstr "导入字体"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"This file is already a Godot font file, please supply a BMFont type file "
-"instead."
-msgstr "此文件已ç»æ˜¯ä¸€ä¸ªGodot的字体文件,请æ供一个ä½å›¾å­—体(BMFont)文件。"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Failed opening as BMFont file."
-msgstr "打开ä½å›¾å­—体失败。"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error initializing FreeType."
-msgstr "åˆå§‹åŒ–FreeType出错。"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Unknown font format."
-msgstr "未知的字体格å¼ã€‚"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error loading font."
-msgstr "加载字体出错。"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Invalid font size."
-msgstr "字体大å°éžæ³•ã€‚"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Invalid font custom source."
-msgstr "自定义字体文件éžæ³•ã€‚"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/plugins/theme_editor_plugin.cpp
-msgid "Font"
-msgstr "字体"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "No meshes to import!"
-msgstr "没有è¦å¯¼å…¥çš„Meshï¼"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Single Mesh Import"
-msgstr "导入å•ä¸ªMesh"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Source Mesh(es):"
-msgstr "æºMesh:"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/plugins/mesh_instance_editor_plugin.cpp
-msgid "Mesh"
-msgstr "Mesh"
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Surface %d"
-msgstr "è¡¨é¢ %d"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "No samples to import!"
-msgstr "没有音效è¦å¯¼å…¥ï¼"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Import Audio Samples"
-msgstr "导入声音文件"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Source Sample(s):"
-msgstr "æºéŸ³æ•ˆæ–‡ä»¶:"
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Audio Sample"
-msgstr "音效"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "New Clip"
-msgstr "新片段"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Animation Options"
-msgstr "动画选项"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Flags"
-msgstr "标记"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Bake FPS:"
-msgstr "烘培FPS:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Optimizer"
-msgstr "优化"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Linear Error"
-msgstr "最大线性误差"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angular Error"
-msgstr "最大角度误差"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angle"
-msgstr "最大角度"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Clips"
-msgstr "片段"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Start(s)"
-msgstr "起点"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "End(s)"
-msgstr "终点"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Loop"
-msgstr "循环"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Filters"
-msgstr "筛选"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source path is empty."
-msgstr "æºè·¯å¾„为空。"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't load post-import script."
-msgstr "无法载入åŽå¯¼å…¥è„šæœ¬ã€‚"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Invalid/broken script for post-import."
-msgstr "åŽå¯¼å…¥è„šæœ¬è¢«æŸå或ä¸åˆæ³•ã€‚"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Error importing scene."
-msgstr "导入场景出错。"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import 3D Scene"
-msgstr "导入3D场景"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source Scene:"
-msgstr "æºåœºæ™¯:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Same as Target Scene"
-msgstr "与目标场景相åŒ"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Shared"
-msgstr "共享的"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Target Texture Folder:"
-msgstr "目标贴图目录:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Post-Process Script:"
-msgstr "åŽå¤„ç†è„šæœ¬:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Custom Root Node Type:"
-msgstr "自定义根节点类型:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Auto"
-msgstr "自动"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Root Node Name:"
-msgstr "节点å称:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "The Following Files are Missing:"
-msgstr "找ä¸åˆ°ä¸‹åˆ—文件:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Anyway"
-msgstr "ä»ç„¶å¯¼å…¥"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp scene/gui/dialogs.cpp
-msgid "Cancel"
-msgstr "å–消"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import & Open"
-msgstr "导入|打开"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Edited scene has not been saved, open imported scene anyway?"
-msgstr "正在编辑的场景尚未ä¿å­˜ï¼Œä»ç„¶è¦æ‰“开导入的场景å—?"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Image:"
-msgstr "导入图片:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Can't import a file over itself:"
-msgstr "ä¸å…许导入文件本身:"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't localize path: %s (already local)"
-msgstr "无法本地化路径:%s (å·²ç»æ˜¯æœ¬åœ°è·¯å¾„)"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "3D Scene Animation"
-msgstr "3D场景动画"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Uncompressed"
-msgstr "ä¸åŽ‹ç¼©"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossless (PNG)"
-msgstr "æ— æŸåŽ‹ç¼©ï¼ˆPNG)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossy (WebP)"
-msgstr "有æŸåŽ‹ç¼©ï¼ˆWebP)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress (VRAM)"
-msgstr "VRAM压缩"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Format"
-msgstr "纹ç†æ ¼å¼"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Compression Quality (WebP):"
-msgstr "高质é‡ï¼ˆWebP)压缩方å¼:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Options"
-msgstr "纹ç†é€‰é¡¹"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Please specify some files!"
-msgstr "请添加文件ï¼"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "At least one file needed for Atlas."
-msgstr "ç²¾çµé›†è‡³å°‘需è¦ä¸€ä¸ªæ–‡ä»¶ã€‚"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Error importing:"
-msgstr "导入出错:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Only one file is required for large texture."
-msgstr "大图导入仅支æŒä¸€ä¸ªè¾“入文件。"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Max Texture Size:"
-msgstr "最大纹ç†å°ºå¯¸:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for Atlas (2D)"
-msgstr "导入2Dç²¾çµé›†"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cell Size:"
-msgstr "å•å…ƒå°ºå¯¸:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Large Texture"
-msgstr "大图"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Textures (2D)"
-msgstr "导入2D大图"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture"
-msgstr "æºè´´å›¾"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Base Atlas Texture"
-msgstr "基础图集纹ç†"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s)"
-msgstr "æºè´´å›¾(s)"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 2D"
-msgstr "导入2D贴图"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 3D"
-msgstr "导入3D贴图"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures"
-msgstr "导入贴图"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "2D Texture"
-msgstr "2D贴图"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "3D Texture"
-msgstr "3D贴图"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Atlas Texture"
-msgstr "ç²¾çµå›¾é›†"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid ""
-"NOTICE: Importing 2D textures is not mandatory. Just copy png/jpg files to "
-"the project."
-msgstr ""
-"æ示:大多数2D贴图并ä¸éœ€è¦å¯¼å…¥æ“作,åªè¦å°†png/jpg文件放到项目目录下å³å¯ã€‚"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Crop empty space."
-msgstr "切除空白区域。"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture"
-msgstr "贴图"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Texture"
-msgstr "导入大图"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Load Source Image"
-msgstr "加载æºå›¾ç‰‡"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Slicing"
-msgstr "切片中"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Inserting"
-msgstr "æ’入中"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Saving"
-msgstr "正在ä¿å­˜æ–‡ä»¶"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save large texture:"
-msgstr "无法ä¿å­˜å¤§å›¾:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Build Atlas For:"
-msgstr "使用以下图片生æˆç²¾çµé›†:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Loading Image:"
-msgstr "加载图片中:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't load image:"
-msgstr "无法加载图片:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Converting Images"
-msgstr "正在转æ¢å›¾ç‰‡"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cropping Images"
-msgstr "剪è£å›¾ç‰‡"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Blitting Images"
-msgstr "Blitting 图片"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save atlas image:"
-msgstr "无法ä¿å­˜ç²¾çµé›†å›¾ç‰‡:"
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save converted texture:"
-msgstr "无法ä¿å­˜è½¬æ¢çš„贴图:"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid source!"
-msgstr "输入æºéžæ³•ï¼"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid translation source!"
-msgstr "æºè¯­è¨€æ–‡ä»¶éžæ³•ï¼"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Column"
-msgstr "列"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/script_create_dialog.cpp
-msgid "Language"
-msgstr "语言"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No items to import!"
-msgstr "没有è¦å¯¼å…¥çš„项目ï¼"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No target path!"
-msgstr "目标路径为空ï¼"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translations"
-msgstr "导入多ç§è¯­è¨€ç¿»è¯‘"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Couldn't import!"
-msgstr "无法导入ï¼"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translation"
-msgstr "导入语言翻译"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Source CSV:"
-msgstr "æºCSV文件:"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Ignore First Row"
-msgstr "忽略第一行"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Compress"
-msgstr "压缩"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Add to Project (project.godot)"
-msgstr "添加到项目 (project.godot)"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Languages:"
-msgstr "导入语言:"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Translation"
-msgstr "语言"
-
#: editor/multi_node_edit.cpp
msgid "MultiNode Set"
msgstr "多节点组"
@@ -3297,6 +2668,49 @@ msgstr "分组"
msgid "Select a Node to edit Signals and Groups."
msgstr "请选择一个节点æ¥è®¾ç½®ä¿¡å·æˆ–分组。"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create Poly"
+msgstr "创建多边形"
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly"
+msgstr "编辑多边形"
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#, fuzzy
+msgid "Insert Point"
+msgstr "æ’入中"
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly (Remove Point)"
+msgstr "编辑多边形(移除顶点)"
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Remove Poly And Point"
+msgstr "移除多边形åŠé¡¶ç‚¹"
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create a new polygon from scratch."
+msgstr "从头开始创建一个新的多边形。"
+
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid ""
+"Edit existing polygon:\n"
+"LMB: Move Point.\n"
+"Ctrl+LMB: Split Segment.\n"
+"RMB: Erase Point."
+msgstr ""
+"编辑多边形:\n"
+"LMB: 移动点。\n"
+"Ctrl + LMB: 分离片段。\n"
+"人民å¸ï¼š 擦除点。"
+
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Toggle Autoplay"
msgstr "切æ¢AutoPlay"
@@ -3315,7 +2729,7 @@ msgstr "é‡å‘½å动画:"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Delete Animation?"
-msgstr "删除动画"
+msgstr "是å¦åˆ é™¤åŠ¨ç”»ï¼Ÿ"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
@@ -3450,7 +2864,6 @@ msgstr "动画å称:"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
#: editor/script_create_dialog.cpp
msgid "Error!"
@@ -3478,9 +2891,8 @@ msgid "New name:"
msgstr "æ–°å称:"
#: editor/plugins/animation_tree_editor_plugin.cpp
-#, fuzzy
msgid "Edit Filters"
-msgstr "编辑节点筛选"
+msgstr "编辑筛选器"
#: editor/plugins/animation_tree_editor_plugin.cpp
#: editor/plugins/multimesh_editor_plugin.cpp
@@ -3561,10 +2973,6 @@ msgid "Delete Input"
msgstr "删除输入事件"
#: editor/plugins/animation_tree_editor_plugin.cpp
-msgid "Rename"
-msgstr "é‡å‘½å"
-
-#: editor/plugins/animation_tree_editor_plugin.cpp
msgid "Animation tree is valid."
msgstr "动画树å¯ç”¨ã€‚"
@@ -3620,64 +3028,181 @@ msgstr "编辑节点筛选"
msgid "Filters.."
msgstr "筛选.."
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing %d Triangles:"
-msgstr "正在解æžç¬¬%d个三角形:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Free"
+msgstr "释放"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Triangle #"
-msgstr "三角形 #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Contents:"
+msgstr "内容:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Light Baker Setup:"
-msgstr "建立烘培:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "View Files"
+msgstr "查看文件"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing Geometry"
-msgstr "解æžå¤šè¾¹å½¢ä¸­"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve hostname:"
+msgstr "无法解æžä¸»æœºå:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Fixing Lights"
-msgstr "修正光照"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve."
+msgstr "无法解æž."
-#: editor/plugins/baked_light_baker.cpp
-msgid "Making BVH"
-msgstr "制作BVH(动作骨骼)"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connection error, please try again."
+msgstr "连接错误,请é‡è¯•ã€‚"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Light Octree"
-msgstr "创建光的 Octree(å…«å‰æ ‘)"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't connect."
+msgstr "无法连接。"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Octree Texture"
-msgstr "创建 Octree (å…«å‰æ ‘) 纹ç†"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't connect to host:"
+msgstr "无法连接到æœåŠ¡å™¨:"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Transfer to Lightmaps:"
-msgstr "转移到光照贴图:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response from host:"
+msgstr "æœåŠ¡å™¨æ— å“应:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response."
+msgstr "æ— å“应。"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, return code:"
+msgstr "请求失败,错误代ç :"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Allocating Texture #"
-msgstr "分é…çº¹ç† #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Req. Failed."
+msgstr "请求失败."
-#: editor/plugins/baked_light_baker.cpp
-msgid "Baking Triangle #"
-msgstr "烘培三角形 #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, too many redirects"
+msgstr "请求失败,é‡å®šå‘次数过多"
-#: editor/plugins/baked_light_baker.cpp
-msgid "Post-Processing Texture #"
-msgstr "åŽåŠ å·¥çº¹ç† #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Redirect Loop."
+msgstr "循环é‡å®šå‘。"
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Bake!"
-msgstr "烘培ï¼"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed:"
+msgstr "失败:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Bad download hash, assuming file has been tampered with."
+msgstr "文件hash值错误,该文件å¯èƒ½è¢«ç¯¡æ”¹ã€‚"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Expected:"
+msgstr "预计:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Got:"
+msgstr "获得:"
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Reset the lightmap octree baking process (start over)."
-msgstr "é‡ç½®è´´å›¾çƒ˜ç„™è¿‡ç¨‹ (é‡æ–°å¼€å§‹ï¼‰ çš„ octree (å…«å‰æ ‘)。"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed sha256 hash check"
+msgstr "sha256哈希值校验失败"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Asset Download Error:"
+msgstr "资æºä¸‹è½½å‡ºé”™:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Fetching:"
+msgstr "获å–:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Resolving.."
+msgstr "解æžä¸­.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connecting.."
+msgstr "连接中.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Requesting.."
+msgstr "正在请求.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Error making request"
+msgstr "请求错误"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Idle"
+msgstr "空闲"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Retry"
+msgstr "é‡è¯•"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download Error"
+msgstr "下载错误"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download for this asset is already in progress!"
+msgstr "此资æºæ–‡ä»¶æ­£åœ¨ä¸‹è½½ä¸­ï¼"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "first"
+msgstr "首先"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "prev"
+msgstr "上一页"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "next"
+msgstr "下一页"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "last"
+msgstr "最åŽä¸€é¡µ"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "All"
+msgstr "全部"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Plugins"
+msgstr "æ’件"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Sort:"
+msgstr "排åº:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Reverse"
+msgstr "å选"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Category:"
+msgstr "分类:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Site:"
+msgstr "站点:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Support.."
+msgstr "支æŒ.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Official"
+msgstr "官方"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Testing"
+msgstr "测试"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Assets ZIP File"
+msgstr "ZIP资æºåŒ…"
#: editor/plugins/camera_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
msgid "Preview"
msgstr "预览"
@@ -3720,12 +3245,18 @@ msgid "Edit CanvasItem"
msgstr "编辑CanvasItem"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Change Anchors"
+#, fuzzy
+msgid "Anchors only"
+msgstr "锚点"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#, fuzzy
+msgid "Change Anchors and Margins"
msgstr "编辑锚点"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom (%):"
-msgstr "缩放(%):"
+msgid "Change Anchors"
+msgstr "编辑锚点"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Paste Pose"
@@ -3775,60 +3306,78 @@ msgid "Pan Mode"
msgstr "移动画布"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Lock the selected object in place (can't be moved)."
-msgstr "é”定选中对象的ä½ç½®ã€‚"
+#, fuzzy
+msgid "Toggles snapping"
+msgstr "设置断点"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Unlock the selected object (can be moved)."
-msgstr "解é”选中对象的ä½ç½®ã€‚"
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Use Snap"
+msgstr "使用å¸é™„"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Makes sure the object's children are not selectable."
-msgstr "ç¡®ä¿èŠ‚点的å­å­™æ— æ³•è¢«é€‰ä¸­ã€‚"
+#, fuzzy
+msgid "Snapping options"
+msgstr "动画选项"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Restores the object's children's ability to be selected."
-msgstr "æ¢å¤èŠ‚点的å­å­™èƒ½å¤Ÿè¢«é€‰ä¸­ã€‚"
+#, fuzzy
+msgid "Snap to grid"
+msgstr "å¸é™„模å¼:"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Edit"
-msgstr "编辑"
+msgid "Use Rotation Snap"
+msgstr "使用旋转å¸é™„"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Use Snap"
-msgstr "使用å¸é™„"
+#, fuzzy
+msgid "Configure Snap..."
+msgstr "设置å¸é™„.."
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Show Grid"
-msgstr "显示网格"
+msgid "Snap Relative"
+msgstr "相对å¸é™„"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Rotation Snap"
-msgstr "使用旋转å¸é™„"
+msgid "Use Pixel Snap"
+msgstr "使用åƒç´ å¸é™„"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap Relative"
-msgstr "相对å¸é™„"
+msgid "Smart snapping"
+msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Configure Snap.."
-msgstr "设置å¸é™„.."
+#, fuzzy
+msgid "Snap to parent"
+msgstr "展开父节点"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Pixel Snap"
-msgstr "使用åƒç´ å¸é™„"
+msgid "Snap to node anchor"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to node sides"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to other nodes"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Lock the selected object in place (can't be moved)."
+msgstr "é”定选中对象的ä½ç½®ã€‚"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Unlock the selected object (can be moved)."
+msgstr "解é”选中对象的ä½ç½®ã€‚"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Makes sure the object's children are not selectable."
+msgstr "ç¡®ä¿èŠ‚点的å­å­™æ— æ³•è¢«é€‰ä¸­ã€‚"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Skeleton.."
-msgstr "骨骼.."
+msgid "Restores the object's children's ability to be selected."
+msgstr "æ¢å¤èŠ‚点的å­å­™èƒ½å¤Ÿè¢«é€‰ä¸­ã€‚"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Make Bones"
@@ -3856,12 +3405,19 @@ msgid "View"
msgstr "视图"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Reset"
-msgstr "é‡ç½®ç¼©æ”¾"
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Show Grid"
+msgstr "显示网格"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#, fuzzy
+msgid "Show helpers"
+msgstr "显示骨骼"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Set.."
-msgstr "设置缩放.."
+#, fuzzy
+msgid "Show rulers"
+msgstr "显示骨骼"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Center Selection"
@@ -3872,8 +3428,9 @@ msgid "Frame Selection"
msgstr "最大化显示选中节点"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Anchor"
-msgstr "锚点"
+#, fuzzy
+msgid "Layout"
+msgstr "ä¿å­˜å¸ƒå±€"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Insert Keys"
@@ -3896,12 +3453,21 @@ msgid "Clear Pose"
msgstr "清除姿势"
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Set a Value"
-msgstr "设置值"
+msgid "Drag pivot from mouse position"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#, fuzzy
+msgid "Set pivot at mouse position"
+msgstr "设置曲线输出ä½ç½®ï¼ˆPos)"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Multiply grid step by 2"
+msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap (Pixels):"
-msgstr "å¸é™„(åƒç´ ï¼‰ï¼š"
+msgid "Divide grid step by 2"
+msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Add %s"
@@ -3911,23 +3477,28 @@ msgstr "添加(Add) %s"
msgid "Adding %s..."
msgstr "添加(Adding) %s..."
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Create Node"
msgstr "新节点"
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Error instancing scene from %s"
msgstr "从%s实例化场景出错"
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "OK :("
msgstr "好å§"
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "No parent to instance a child at."
msgstr "没有选中节点æ¥æ·»åŠ å®žä¾‹ã€‚"
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "This operation requires a single selected node."
msgstr "æ­¤æ“作åªèƒ½åº”用于å•ä¸ªé€‰ä¸­èŠ‚点。"
@@ -3943,45 +3514,6 @@ msgstr ""
"拖放+ Shift:将节点添加为兄弟节点\n"
"拖放+ Alt:更改节点类型"
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Create Poly"
-msgstr "创建多边形"
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly"
-msgstr "编辑多边形"
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly (Remove Point)"
-msgstr "编辑多边形(移除顶点)"
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Create a new polygon from scratch."
-msgstr "从头开始创建一个新的多边形。"
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-msgid ""
-"Edit existing polygon:\n"
-"LMB: Move Point.\n"
-"Ctrl+LMB: Split Segment.\n"
-"RMB: Erase Point."
-msgstr ""
-
#: editor/plugins/collision_polygon_editor_plugin.cpp
msgid "Create Poly3D"
msgstr "创建 Poly3D (多边型3D)"
@@ -3991,14 +3523,6 @@ msgid "Set Handle"
msgstr "设置处ç†ç¨‹åº"
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Creating Mesh Library"
-msgstr "创建 Mesh(网格) 库"
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Thumbnail.."
-msgstr "缩略图.."
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Remove item %d?"
msgstr "确定è¦ç§»é™¤é¡¹ç›®%då—?"
@@ -4021,19 +3545,38 @@ msgid "Update from Scene"
msgstr "从场景中更新"
#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat0"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat1"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
#, fuzzy
-msgid "Modify Curve Point"
-msgstr "修改曲线"
+msgid "Ease in"
+msgstr "缓入"
#: editor/plugins/curve_editor_plugin.cpp
#, fuzzy
+msgid "Ease out"
+msgstr "缓出"
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Smoothstep"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Modify Curve Point"
+msgstr "修改曲线点"
+
+#: editor/plugins/curve_editor_plugin.cpp
msgid "Modify Curve Tangent"
-msgstr "修改曲线图"
+msgstr "修改曲线切角"
#: editor/plugins/curve_editor_plugin.cpp
-#, fuzzy
msgid "Load Curve Preset"
-msgstr "加载预设"
+msgstr "加载曲线预设"
#: editor/plugins/curve_editor_plugin.cpp
msgid "Add point"
@@ -4044,31 +3587,28 @@ msgid "Remove point"
msgstr "移除顶点"
#: editor/plugins/curve_editor_plugin.cpp
-#, fuzzy
msgid "Left linear"
-msgstr "线性"
+msgstr "左线性"
#: editor/plugins/curve_editor_plugin.cpp
-#, fuzzy
msgid "Right linear"
-msgstr "å³è§†å›¾"
+msgstr "å³çº¿æ€§"
#: editor/plugins/curve_editor_plugin.cpp
msgid "Load preset"
msgstr "加载预设"
#: editor/plugins/curve_editor_plugin.cpp
-#, fuzzy
msgid "Remove Curve Point"
msgstr "移除路径顶点"
#: editor/plugins/curve_editor_plugin.cpp
msgid "Toggle Curve Linear Tangent"
-msgstr ""
+msgstr "切æ¢æ›²çº¿çº¿æ€§Tangent"
#: editor/plugins/curve_editor_plugin.cpp
msgid "Hold Shift to edit tangents individually"
-msgstr ""
+msgstr "æŒ‰ä½ Shift å¯å•ç‹¬ç¼–辑切线"
#: editor/plugins/gradient_editor_plugin.cpp
msgid "Add/Remove Color Ramp Point"
@@ -4096,28 +3636,26 @@ msgid ""
"No OccluderPolygon2D resource on this node.\n"
"Create and assign one?"
msgstr ""
+"在这个节点上没有 OccluderPolygon2D 资æºã€‚\n"
+"创建和分é…一个å—?"
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
msgid "Create Occluder Polygon"
msgstr "添加é®å…‰å¤šè¾¹å½¢"
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Edit existing polygon:"
msgstr "编辑已存在的多边形:"
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "LMB: Move Point."
msgstr "鼠标左键:移动点。"
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Ctrl+LMB: Split Segment."
msgstr "Ctrl+鼠标左键:分割视图å—。"
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "RMB: Erase Point."
msgstr "é¼ æ ‡å³é”®:移除点。"
@@ -4218,6 +3756,10 @@ msgid "Create Outline"
msgstr "创建轮廓(outlines)"
#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Mesh"
+msgstr "Mesh"
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Create Trimesh Static Body"
msgstr "创建三维é™æ€èº«ä½“(Body)"
@@ -4345,14 +3887,83 @@ msgstr "éšæœºç¼©æ”¾:"
msgid "Populate"
msgstr "å¡«å……"
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake!"
+msgstr "烘培ï¼"
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+#, fuzzy
+msgid "Bake the navigation mesh.\n"
+msgstr "创建导航Mesh(网格)"
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+#, fuzzy
+msgid "Clear the navigation mesh."
+msgstr "创建导航Mesh(网格)"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Setting up Configuration..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Calculating grid size..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Creating heightfield..."
+msgstr "创建光的 Octree(å…«å‰æ ‘)"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Marking walkable triangles..."
+msgstr "å¯ç¿»è¯‘字符串.."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Constructing compact heightfield..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Eroding walkable area..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Partitioning..."
+msgstr "警告"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Creating contours..."
+msgstr "创建 Octree (å…«å‰æ ‘) 纹ç†"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Creating polymesh..."
+msgstr "创建轮廓网格(Outline Mesh).."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Converting to native navigation mesh..."
+msgstr "创建导航Mesh(网格)"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Navigation Mesh Generator Setup:"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Parsing Geometry..."
+msgstr "解æžå¤šè¾¹å½¢ä¸­"
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Done!"
+msgstr ""
+
#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Create Navigation Polygon"
msgstr "创建导航多边形"
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Remove Poly And Point"
-msgstr "移除多边形åŠé¡¶ç‚¹"
-
#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Clear Emission Mask"
msgstr "清除Emission Mask(å‘å°„å±è”½ï¼‰"
@@ -4364,7 +3975,7 @@ msgstr "正在生æˆAABB"
#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Can only set point into a ParticlesMaterial process material"
-msgstr ""
+msgstr "å¯ä»¥è®¾ç½®ParticlesMaterial 点的æè´¨"
#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Error loading image:"
@@ -4380,7 +3991,7 @@ msgstr "设置Emission Mask(å‘å°„å±è”½ï¼‰"
#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Generate Visibility Rect"
-msgstr ""
+msgstr "生æˆå¯è§†åŒ–区域"
#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Load Emission Mask"
@@ -4388,9 +3999,8 @@ msgstr "加载Emission Mask(å‘å°„å±è”½ï¼‰"
#: editor/plugins/particles_2d_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp
-#, fuzzy
msgid "Particles"
-msgstr "顶点"
+msgstr "ç²’å­"
#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Generated Point Count:"
@@ -4399,19 +4009,19 @@ msgstr "生æˆé¡¶ç‚¹è®¡æ•°:"
#: editor/plugins/particles_2d_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp
msgid "Generation Time (sec):"
-msgstr "生æˆæ—¶é—´ï¼ˆç§’)"
+msgstr "生æˆæ—¶é—´ï¼ˆç§’):"
#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Emission Mask"
-msgstr ""
+msgstr "å‘å…‰é®ç½©ï¼ˆmask)"
#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Capture from Pixel"
-msgstr ""
+msgstr "从åƒç´ æ•æ‰"
#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Emission Colors"
-msgstr ""
+msgstr "å‘光颜色"
#: editor/plugins/particles_editor_plugin.cpp
msgid "Node does not contain geometry."
@@ -4471,11 +4081,11 @@ msgstr "体积"
#: editor/plugins/particles_editor_plugin.cpp
msgid "Emission Source: "
-msgstr "å‘å°„æºï¼š"
+msgstr "å‘å°„æºï¼š "
#: editor/plugins/particles_editor_plugin.cpp
msgid "Generate Visibility AABB"
-msgstr ""
+msgstr "生æˆå¯è§çš„AABB"
#: editor/plugins/path_2d_editor_plugin.cpp
msgid "Remove Point from Curve"
@@ -4525,14 +4135,17 @@ msgid "Curve Point #"
msgstr "曲线定点 #"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve Point Position"
msgstr "设置曲线顶点åæ ‡"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve In Position"
msgstr "设置的曲线输入ä½ç½®ï¼ˆPos)"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve Out Position"
msgstr "设置曲线输出ä½ç½®ï¼ˆPos)"
@@ -4593,6 +4206,14 @@ msgid "Scale Polygon"
msgstr "缩放多边形"
#: editor/plugins/polygon_2d_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Edit"
+msgstr "编辑"
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Polygon->UV"
msgstr "多边形->UV"
@@ -4647,63 +4268,10 @@ msgstr "加载资æº"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/shader_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "粘贴"
-#: editor/plugins/rich_text_editor_plugin.cpp
-msgid "Parse BBCode"
-msgstr "解æžBBCode"
-
-#: editor/plugins/sample_editor_plugin.cpp
-msgid "Length:"
-msgstr "长度:"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Open Sample File(s)"
-msgstr "打开声音文件"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "ERROR: Couldn't load sample!"
-msgstr "错误:无法加载音效ï¼"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Add Sample"
-msgstr "添加音效"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Rename Sample"
-msgstr "é‡å‘½å音效"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Delete Sample"
-msgstr "删除音效"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "16 Bits"
-msgstr "16ä½"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "8 Bits"
-msgstr "8ä½"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Stereo"
-msgstr "立体声"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Mono"
-msgstr "å•å£°é“"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Format"
-msgstr "æ ¼å¼"
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Pitch"
-msgstr "音调"
-
#: editor/plugins/script_editor_plugin.cpp
msgid "Clear Recent Files"
msgstr "清ç†å½“å‰æ–‡ä»¶"
@@ -4713,6 +4281,8 @@ msgid ""
"Close and save changes?\n"
"\""
msgstr ""
+"关闭并ä¿å­˜æ›´æ”¹å—?\n"
+"\""
#: editor/plugins/script_editor_plugin.cpp
msgid "Error while saving theme"
@@ -4740,7 +4310,7 @@ msgstr "主题å¦å­˜ä¸º.."
#: editor/plugins/script_editor_plugin.cpp
msgid " Class Reference"
-msgstr ""
+msgstr " 类引用"
#: editor/plugins/script_editor_plugin.cpp
msgid "Next script"
@@ -4794,10 +4364,13 @@ msgstr "关闭文档"
msgid "Close All"
msgstr "关闭全部"
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+msgid "Run"
+msgstr "è¿è¡Œ"
+
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Toggle Scripts Panel"
-msgstr "切æ¢æ”¶è—"
+msgstr "切æ¢è„šæœ¬é¢æ¿"
#: editor/plugins/script_editor_plugin.cpp
#: editor/plugins/script_text_editor.cpp
@@ -4823,7 +4396,8 @@ msgstr "å•æ­¥è¿›å…¥"
msgid "Break"
msgstr "跳过"
-#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+#: editor/script_editor_debugger.cpp
msgid "Continue"
msgstr "继续"
@@ -4832,25 +4406,12 @@ msgid "Keep Debugger Open"
msgstr "ä¿æŒè°ƒè¯•å™¨æ‰“å¼€"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Debug with external editor"
-msgstr "打开下一个编辑器"
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Window"
-msgstr "窗å£"
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Left"
-msgstr "å‘左移动"
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Right"
-msgstr "å‘å³ç§»åŠ¨"
+msgstr "使用外部编辑器进行调试"
#: editor/plugins/script_editor_plugin.cpp
msgid "Open Godot online documentation"
-msgstr ""
+msgstr "打开Godot在线文档"
#: editor/plugins/script_editor_plugin.cpp
msgid "Search the class hierarchy."
@@ -4903,7 +4464,7 @@ msgstr "内建脚本åªæœ‰åœ¨å…¶æ‰€å±žçš„节点读å–åŽæ‰èƒ½è¢«ä¿®æ”¹"
#: editor/plugins/script_text_editor.cpp
msgid "Only resources from filesystem can be dropped."
-msgstr ""
+msgstr "åªå¯ä»¥æ‹–入文件系统的资æºã€‚"
#: editor/plugins/script_text_editor.cpp
msgid "Pick Color"
@@ -4932,8 +4493,9 @@ msgid "Cut"
msgstr "剪切"
#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "å¤åˆ¶"
@@ -4952,9 +4514,8 @@ msgid "Move Down"
msgstr "å‘下移动"
#: editor/plugins/script_text_editor.cpp
-#, fuzzy
msgid "Delete Line"
-msgstr "删除顶点"
+msgstr "删除线"
#: editor/plugins/script_text_editor.cpp
msgid "Indent Left"
@@ -5197,10 +4758,6 @@ msgid "View Plane Transform."
msgstr "视图平é¢å˜æ¢ã€‚"
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Scaling to %s%%."
-msgstr "缩放到%s%%。"
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rotating %s degrees."
msgstr "旋转%s度。"
@@ -5217,10 +4774,6 @@ msgid "Top View."
msgstr "俯视图(Top View)。"
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Top"
-msgstr "顶部"
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rear View."
msgstr "åŽè§†å›¾ã€‚"
@@ -5262,7 +4815,7 @@ msgstr "æ’入动画键。"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Objects Drawn"
-msgstr ""
+msgstr "绘制的对象"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Material Changes"
@@ -5278,7 +4831,7 @@ msgstr "表é¢å˜æ›´"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Draw Calls"
-msgstr "Draw Calls"
+msgstr "绘制调用(Draw Calls)"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Vertices"
@@ -5302,60 +4855,57 @@ msgstr "显示过度绘制"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Display Unshaded"
-msgstr ""
+msgstr "显示无阴影"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "View Environment"
-msgstr ""
+msgstr "视图环境"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "View Gizmos"
msgstr "Gizmos(å¯è§†åŒ–调试工具)"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "View Information"
-msgstr ""
+msgstr "查看信æ¯"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Audio Listener"
msgstr "音频监å¬å™¨"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Doppler Enable"
-msgstr "å¯ç”¨"
+msgstr "å¯ç”¨å¤šæ™®å‹’效应"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Freelook Left"
-msgstr ""
+msgstr "自由视图 左"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Freelook Right"
-msgstr ""
+msgstr "自由视图 å³"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Freelook Forward"
-msgstr ""
+msgstr "自由视图 å‰"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Freelook Backwards"
-msgstr ""
+msgstr "自由视图 åŽ"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Freelook Up"
-msgstr ""
+msgstr "自由视图 上"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Freelook Down"
-msgstr ""
+msgstr "自由视图 下"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Freelook Speed Modifier"
-msgstr ""
+msgstr "自由视图速度调整"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "preview"
msgstr "预览"
@@ -5364,17 +4914,18 @@ msgid "XForm Dialog"
msgstr "XForm对è¯æ¡†"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Select Mode (Q)\n"
-msgstr "选择模å¼"
+msgstr "é€‰æ‹©æ¨¡å¼ (Q)\n"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid ""
"Drag: Rotate\n"
"Alt+Drag: Move\n"
"Alt+RMB: Depth list selection"
-msgstr "Alt+é¼ æ ‡å³é”®:显示鼠标点击ä½ç½®ä¸‹çš„所有节点列表"
+msgstr ""
+"鼠标拖拽:旋转\n"
+"Alt+拖拽:移动\n"
+"Alt+é¼ æ ‡å³é”®ï¼šæ˜¾ç¤ºåˆ—表"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Move Mode (W)"
@@ -5433,30 +4984,30 @@ msgid "Align Selection With View"
msgstr "选中项与视图对é½"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Tool Select"
-msgstr "选择"
+msgstr "选择工具"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Tool Move"
-msgstr "移动"
+msgstr "移动工具"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Tool Rotate"
-msgstr "Ctrl:旋转"
+msgstr "旋转工具"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Tool Scale"
-msgstr "缩放:"
+msgstr "缩放工具"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Transform"
msgstr "å˜æ¢"
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Configure Snap.."
+msgstr "设置å¸é™„.."
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Local Coords"
msgstr "本地åæ ‡"
@@ -5602,6 +5153,10 @@ msgid "Speed (FPS):"
msgstr "速度(FPS):"
#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Loop"
+msgstr "循环"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Animation Frames"
msgstr "动画帧"
@@ -5614,19 +5169,20 @@ msgid "Insert Empty (After)"
msgstr "æ’入空白帧(之åŽï¼‰"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Up"
-msgstr "å‘上"
+#, fuzzy
+msgid "Move (Before)"
+msgstr "移动节点"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Down"
-msgstr "å‘下"
+#, fuzzy
+msgid "Move (After)"
+msgstr "å‘左移动"
#: editor/plugins/style_box_editor_plugin.cpp
msgid "StyleBox Preview:"
msgstr "StyleBox预览:"
#: editor/plugins/texture_region_editor_plugin.cpp
-#, fuzzy
msgid "Set Region Rect"
msgstr "设置纹ç†åŒºåŸŸ"
@@ -5688,18 +5244,20 @@ msgid "Remove Item"
msgstr "移除项目"
#: editor/plugins/theme_editor_plugin.cpp
-#, fuzzy
msgid "Remove All Items"
msgstr "移除类项目"
#: editor/plugins/theme_editor_plugin.cpp
-#, fuzzy
msgid "Remove All"
-msgstr "移除"
+msgstr "移除全部"
#: editor/plugins/theme_editor_plugin.cpp
-msgid "Theme"
-msgstr "主题"
+msgid "Edit theme.."
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Theme editing menu."
+msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
msgid "Add Class Items"
@@ -5783,11 +5341,14 @@ msgid "Style"
msgstr "æ ·å¼"
#: editor/plugins/theme_editor_plugin.cpp
+msgid "Font"
+msgstr "字体"
+
+#: editor/plugins/theme_editor_plugin.cpp
msgid "Color"
msgstr "颜色"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Erase Selection"
msgstr "擦除选中"
@@ -5796,18 +5357,16 @@ msgid "Paint TileMap"
msgstr "绘制砖å—地图"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Line Draw"
-msgstr "线性"
+msgstr "线性绘制"
#: editor/plugins/tile_map_editor_plugin.cpp
msgid "Rectangle Paint"
-msgstr ""
+msgstr "绘制矩形"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Bucket Fill"
-msgstr "桶(Bucket)"
+msgstr "油漆桶填充"
#: editor/plugins/tile_map_editor_plugin.cpp
msgid "Erase TileMap"
@@ -5834,12 +5393,13 @@ msgid "Mirror Y"
msgstr "沿Y轴翻转"
#: editor/plugins/tile_map_editor_plugin.cpp
-msgid "Bucket"
-msgstr "桶(Bucket)"
+#, fuzzy
+msgid "Paint Tile"
+msgstr "绘制砖å—地图"
#: editor/plugins/tile_map_editor_plugin.cpp
msgid "Pick Tile"
-msgstr "选择砖å—"
+msgstr "选择砖å—(Tile)"
#: editor/plugins/tile_map_editor_plugin.cpp
msgid "Rotate 0 degrees"
@@ -5898,6 +5458,11 @@ msgid "Delete preset '%s'?"
msgstr "删除选中的 '%s'?"
#: editor/project_export.cpp
+#, fuzzy
+msgid "Export templates for this platform are missing/corrupted: "
+msgstr "没有下列平å°çš„导出模æ¿:"
+
+#: editor/project_export.cpp
msgid "Presets"
msgstr "预设"
@@ -5911,15 +5476,15 @@ msgstr "资æº"
#: editor/project_export.cpp
msgid "Export all resources in the project"
-msgstr "导出项目中的所有资æºã€‚"
+msgstr "导出项目中的所有资æº"
#: editor/project_export.cpp
msgid "Export selected scenes (and dependencies)"
-msgstr "导出选中的场景(包括其ä¾èµ–)。"
+msgstr "导出选中的场景(包括ä¾èµ–项)"
#: editor/project_export.cpp
msgid "Export selected resources (and dependencies)"
-msgstr "导出选中的资æºï¼ˆåŒ…括其ä¾èµ–资æºï¼‰ã€‚"
+msgstr "导出选中的资æºï¼ˆåŒ…括ä¾èµ–资æºï¼‰"
#: editor/project_export.cpp
msgid "Export Mode:"
@@ -5932,12 +5497,12 @@ msgstr "导出的资æº:"
#: editor/project_export.cpp
msgid ""
"Filters to export non-resource files (comma separated, e.g: *.json, *.txt)"
-msgstr "导出éžèµ„æºæ–‡ä»¶ç­›é€‰ï¼ˆä½¿ç”¨è‹±æ–‡é€—å·åˆ†éš”,如:*.json,*.txt):"
+msgstr "导出éžèµ„æºæ–‡ä»¶ç­›é€‰ï¼ˆä½¿ç”¨è‹±æ–‡é€—å·åˆ†éš”,如:*.json,*.txt)"
#: editor/project_export.cpp
msgid ""
"Filters to exclude files from project (comma separated, e.g: *.json, *.txt)"
-msgstr "排除导出的éžèµ„æºæ–‡ä»¶ç­›é€‰ï¼ˆä½¿ç”¨è‹±æ–‡é€—å·åˆ†éš”,如:*.json,*.txt):"
+msgstr "排除导出的éžèµ„æºæ–‡ä»¶ç­›é€‰ï¼ˆä½¿ç”¨è‹±æ–‡é€—å·åˆ†éš”,如:*.json,*.txt)"
#: editor/project_export.cpp
msgid "Patches"
@@ -5948,18 +5513,16 @@ msgid "Make Patch"
msgstr "制作Patch"
#: editor/project_export.cpp
-#, fuzzy
msgid "Features"
-msgstr "贴图"
+msgstr "功能"
#: editor/project_export.cpp
msgid "Custom (comma-separated):"
-msgstr ""
+msgstr "自定义 (以逗å·åˆ†éš”):"
#: editor/project_export.cpp
-#, fuzzy
msgid "Feature List:"
-msgstr "方法列表:"
+msgstr "功能列表:"
#: editor/project_export.cpp
msgid "Export PCK/Zip"
@@ -5970,30 +5533,61 @@ msgid "Export templates for this platform are missing:"
msgstr "没有下列平å°çš„导出模æ¿:"
#: editor/project_export.cpp
+#, fuzzy
+msgid "Export templates for this platform are missing/corrupted:"
+msgstr "没有下列平å°çš„导出模æ¿:"
+
+#: editor/project_export.cpp
msgid "Export With Debug"
msgstr "导出为调试"
#: editor/project_manager.cpp
-msgid "Invalid project path, the path must exist!"
-msgstr "项目目录ä¸å­˜åœ¨ï¼"
+#, fuzzy
+msgid "The path does not exist."
+msgstr "文件ä¸å­˜åœ¨ã€‚"
+
+#: editor/project_manager.cpp
+#, fuzzy
+msgid "Please choose a 'project.godot' file."
+msgstr "请导出到项目目录之外ï¼"
#: editor/project_manager.cpp
-msgid "Invalid project path, project.godot must not exist."
-msgstr "项目目录下ä¸èƒ½åŒ…å«project.godot文件。"
+msgid ""
+"Your project will be created in a non empty folder (you might want to create "
+"a new folder)."
+msgstr ""
#: editor/project_manager.cpp
-msgid "Invalid project path, project.godot must exist."
-msgstr "项目目录下必须包å«project.godot文件。"
+msgid "Please choose a folder that does not contain a 'project.godot' file."
+msgstr ""
#: editor/project_manager.cpp
msgid "Imported Project"
msgstr "已导入的项目"
#: editor/project_manager.cpp
+msgid " "
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "It would be a good idea to name your project."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Invalid project path (changed anything?)."
msgstr "项目路径éžæ³•ï¼ˆè¢«å¤–部修改?)。"
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Couldn't get project.godot in project path."
+msgstr "无法在项目目录下创建project.godot文件。"
+
+#: editor/project_manager.cpp
+#, fuzzy
+msgid "Couldn't edit project.godot in project path."
+msgstr "无法在项目目录下创建project.godot文件。"
+
+#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
msgstr "无法在项目目录下创建project.godot文件。"
@@ -6002,38 +5596,49 @@ msgid "The following files failed extraction from package:"
msgstr "æå–以下文件失败:"
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Rename Project"
+msgstr "未命å项目"
+
+#: editor/project_manager.cpp
+#, fuzzy
+msgid "Couldn't get project.godot in the project path."
+msgstr "无法在项目目录下创建project.godot文件。"
+
+#: editor/project_manager.cpp
+msgid "New Game Project"
+msgstr "新建游æˆé¡¹ç›®"
+
+#: editor/project_manager.cpp
msgid "Import Existing Project"
msgstr "导入现有项目"
#: editor/project_manager.cpp
-msgid "Project Path (Must Exist):"
-msgstr "项目目录(必须存在):"
+msgid "Create New Project"
+msgstr "新建项目"
+
+#: editor/project_manager.cpp
+msgid "Install Project:"
+msgstr "安装项目:"
#: editor/project_manager.cpp
msgid "Project Name:"
msgstr "项目å称:"
#: editor/project_manager.cpp
-msgid "Create New Project"
-msgstr "新建项目"
+#, fuzzy
+msgid "Create folder"
+msgstr "新建目录"
#: editor/project_manager.cpp
msgid "Project Path:"
msgstr "项目目录:"
#: editor/project_manager.cpp
-msgid "Install Project:"
-msgstr "安装项目:"
-
-#: editor/project_manager.cpp
msgid "Browse"
msgstr "æµè§ˆ"
#: editor/project_manager.cpp
-msgid "New Game Project"
-msgstr "新建游æˆé¡¹ç›®"
-
-#: editor/project_manager.cpp
msgid "That's a BINGO!"
msgstr "碉堡了ï¼"
@@ -6042,24 +5647,30 @@ msgid "Unnamed Project"
msgstr "未命å项目"
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Can't open project"
+msgstr "无法è¿è¡Œé¡¹ç›®"
+
+#: editor/project_manager.cpp
msgid "Are you sure to open more than one project?"
msgstr "您确定è¦æ‰“开多个项目å—?"
#: editor/project_manager.cpp
-#, fuzzy
msgid ""
"Can't run project: no main scene defined.\n"
"Please edit the project and set the main scene in \"Project Settings\" under "
"the \"Application\" category."
msgstr ""
"尚未定义主场景, 现在选择一个�\n"
-"你也å¯ä»¥ç¨åŽåœ¨é¡¹ç›®è®¾ç½®çš„application分类下修改。"
+"你也å¯ä»¥ç¨åŽåœ¨é¡¹ç›®è®¾ç½®çš„Application分类下修改。"
#: editor/project_manager.cpp
msgid ""
"Can't run project: Assets need to be imported.\n"
"Please edit the project to trigger the initial import."
msgstr ""
+"ä¸èƒ½è¿è¡Œé¡¹ç›®ï¼š 需è¦å¯¼å…¥èµ„æºæ–‡ä»¶ã€‚\n"
+"请编辑项目导入åˆå§‹åŒ–资æºã€‚"
#: editor/project_manager.cpp
msgid "Are you sure to run more than one project?"
@@ -6071,6 +5682,12 @@ msgstr "移除此项目(项目的文件ä¸å—å½±å“)"
#: editor/project_manager.cpp
msgid ""
+"Language changed.\n"
+"The UI will update next time the editor or project manager starts."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid ""
"You are about the scan %s folders for existing Godot projects. Do you "
"confirm?"
msgstr "您确认è¦æ‰«æ%s目录下现有的Godot项目å—?"
@@ -6080,10 +5697,6 @@ msgid "Project List"
msgstr "项目列表"
#: editor/project_manager.cpp
-msgid "Run"
-msgstr "è¿è¡Œ"
-
-#: editor/project_manager.cpp
msgid "Scan"
msgstr "扫æ"
@@ -6105,8 +5718,12 @@ msgstr "退出"
#: editor/project_manager.cpp
#, fuzzy
+msgid "Restart Now"
+msgstr "é‡æ–°å¼€å§‹ï¼ˆç§’):"
+
+#: editor/project_manager.cpp
msgid "Can't run project"
-msgstr "无法连接。"
+msgstr "无法è¿è¡Œé¡¹ç›®"
#: editor/project_settings_editor.cpp
msgid "Key "
@@ -6141,17 +5758,14 @@ msgid "Add Input Action Event"
msgstr "添加输入事件"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Meta+"
msgstr "Meta+"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Shift+"
msgstr "Shift+"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Alt+"
msgstr "Alt+"
@@ -6212,7 +5826,7 @@ msgstr "更改"
msgid "Joypad Axis Index:"
msgstr "手柄摇æ†åºå·:"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Axis"
msgstr "è½´"
@@ -6232,59 +5846,66 @@ msgstr "移除输入事件"
msgid "Add Event"
msgstr "添加事件"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Device"
msgstr "设备"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Button"
msgstr "按钮"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Left Button."
msgstr "左键。"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Right Button."
msgstr "å³é”®ã€‚"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Middle Button."
msgstr "中键(滚轮)。"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Up."
msgstr "滚轮å‘上滚动。"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Down."
msgstr "滚轮å‘下滚动。"
#: editor/project_settings_editor.cpp
-#, fuzzy
msgid "Add Global Property"
-msgstr "添加 Getter Property"
+msgstr "添加Getter属性"
#: editor/project_settings_editor.cpp
-msgid "Select an setting item first!"
-msgstr ""
+#, fuzzy
+msgid "Select a setting item first!"
+msgstr "首先选择一个设置项目 ï¼"
#: editor/project_settings_editor.cpp
-#, fuzzy
msgid "No property '"
-msgstr "属性:"
+msgstr "没有属性 '"
#: editor/project_settings_editor.cpp
-#, fuzzy
msgid "Setting '"
-msgstr "设置"
+msgstr "设置 '"
#: editor/project_settings_editor.cpp
-#, fuzzy
msgid "Delete Item"
msgstr "删除输入事件"
#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Can't contain '/' or ':'"
+msgstr "无法连接到æœåŠ¡å™¨:"
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Already existing"
+msgstr "动作%s已存在ï¼"
+
+#: editor/project_settings_editor.cpp
msgid "Error saving settings."
msgstr "ä¿å­˜è®¾ç½®å‡ºé”™ã€‚"
@@ -6294,7 +5915,7 @@ msgstr "ä¿å­˜è®¾ç½®æˆåŠŸã€‚"
#: editor/project_settings_editor.cpp
msgid "Override for Feature"
-msgstr ""
+msgstr "é‡å†™åŠŸèƒ½"
#: editor/project_settings_editor.cpp
msgid "Add Translation"
@@ -6325,6 +5946,15 @@ msgid "Remove Resource Remap Option"
msgstr "移除资æºé‡å®šå‘选项"
#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Changed Locale Filter"
+msgstr "更改混åˆæ—¶é—´"
+
+#: editor/project_settings_editor.cpp
+msgid "Changed Locale Filter Mode"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "Project Settings (project.godot)"
msgstr "项目设置(project.godot)"
@@ -6338,7 +5968,7 @@ msgstr "属性:"
#: editor/project_settings_editor.cpp
msgid "Override For.."
-msgstr ""
+msgstr "é‡å†™çš„......"
#: editor/project_settings_editor.cpp
msgid "Input Map"
@@ -6385,6 +6015,30 @@ msgid "Locale"
msgstr "地区"
#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Locales Filter"
+msgstr "纹ç†è¿‡æ»¤:"
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Show all locales"
+msgstr "显示骨骼"
+
+#: editor/project_settings_editor.cpp
+msgid "Show only selected locales"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Filter mode:"
+msgstr "筛选节点"
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Locales:"
+msgstr "地区"
+
+#: editor/project_settings_editor.cpp
msgid "AutoLoad"
msgstr "自动加载(AutoLoad)"
@@ -6425,7 +6079,6 @@ msgid "Assign"
msgstr "分é…(Assign)"
#: editor/property_editor.cpp
-#, fuzzy
msgid "Select Node"
msgstr "选择一个节点"
@@ -6434,17 +6087,26 @@ msgid "New Script"
msgstr "新建脚本"
#: editor/property_editor.cpp
+#, fuzzy
+msgid "Make Unique"
+msgstr "添加骨骼"
+
+#: editor/property_editor.cpp
msgid "Show in File System"
msgstr "在资æºç®¡ç†å™¨ä¸­å±•ç¤º"
#: editor/property_editor.cpp
+#, fuzzy
+msgid "Convert To %s"
+msgstr "转æ¢ä¸º.."
+
+#: editor/property_editor.cpp
msgid "Error loading file: Not a resource!"
msgstr "加载文件出错:ä¸æ˜¯èµ„æºæ–‡ä»¶ï¼"
#: editor/property_editor.cpp
-#, fuzzy
msgid "Selected node is not a Viewport!"
-msgstr "选择è¦å¯¼å…¥çš„节点"
+msgstr "选定的节点ä¸æ˜¯ä¸€ä¸ªViewport节点ï¼"
#: editor/property_editor.cpp
msgid "Pick a Node"
@@ -6475,6 +6137,11 @@ msgid "Select Property"
msgstr "选择属性"
#: editor/property_selector.cpp
+#, fuzzy
+msgid "Select Virtual Method"
+msgstr "选择方å¼"
+
+#: editor/property_selector.cpp
msgid "Select Method"
msgstr "选择方å¼"
@@ -6502,26 +6169,6 @@ msgstr "ä¿æŒå…¨å±€å˜æ¢"
msgid "Reparent"
msgstr "é‡è®¾çˆ¶èŠ‚点"
-#: editor/resources_dock.cpp
-msgid "Create New Resource"
-msgstr "创建资æº"
-
-#: editor/resources_dock.cpp
-msgid "Open Resource"
-msgstr "打开资æº"
-
-#: editor/resources_dock.cpp
-msgid "Save Resource"
-msgstr "ä¿å­˜èµ„æº"
-
-#: editor/resources_dock.cpp
-msgid "Resource Tools"
-msgstr "资æºå·¥å…·"
-
-#: editor/resources_dock.cpp
-msgid "Make Local"
-msgstr "使用本地"
-
#: editor/run_settings_dialog.cpp
msgid "Run Mode:"
msgstr "è¿è¡Œæ¨¡å¼:"
@@ -6648,14 +6295,6 @@ msgid "Sub-Resources:"
msgstr "å­èµ„æº:"
#: editor/scene_tree_dock.cpp
-msgid "Edit Groups"
-msgstr "编辑分组"
-
-#: editor/scene_tree_dock.cpp
-msgid "Edit Connections"
-msgstr "编辑事件连接"
-
-#: editor/scene_tree_dock.cpp
msgid "Clear Inheritance"
msgstr "清除继承"
@@ -6714,9 +6353,8 @@ msgid ""
msgstr "实例化场景文件为一个节点,如果没有根节点则创建一个继承自该文件的场景。"
#: editor/scene_tree_dock.cpp
-#, fuzzy
msgid "Filter nodes"
-msgstr "筛选"
+msgstr "筛选节点"
#: editor/scene_tree_dock.cpp
msgid "Attach a new or existing script for the selected node."
@@ -6751,6 +6389,8 @@ msgid ""
"Node has connection(s) and group(s)\n"
"Click to show signals dock."
msgstr ""
+"节点具有信å·è¿žæŽ¥å’Œç»„\n"
+"å•å‡»ä»¥æ˜¾ç¤ºä¿¡å·æŽ¥å£ã€‚"
#: editor/scene_tree_editor.cpp
msgid ""
@@ -6789,6 +6429,8 @@ msgid ""
"Children are not selectable.\n"
"Click to make selectable"
msgstr ""
+"å­èŠ‚点无法选择。\n"
+"å•å‡»ä½¿å…¶å¯é€‰"
#: editor/scene_tree_editor.cpp
msgid "Toggle Visibility"
@@ -6807,18 +6449,16 @@ msgid "Scene Tree (Nodes):"
msgstr "场景树:"
#: editor/scene_tree_editor.cpp
-#, fuzzy
msgid "Node Configuration Warning!"
-msgstr "节点é…置警告:"
+msgstr "节点é…置警告ï¼"
#: editor/scene_tree_editor.cpp
msgid "Select a Node"
msgstr "选择一个节点"
#: editor/script_create_dialog.cpp
-#, fuzzy
msgid "Error loading template '%s'"
-msgstr "加载图片出错:"
+msgstr "åŠ è½½æ¨¡æ¿ %s 时出错"
#: editor/script_create_dialog.cpp
msgid "Error - Could not create script in filesystem."
@@ -6845,6 +6485,15 @@ msgid "Invalid base path"
msgstr "父路径éžæ³•"
#: editor/script_create_dialog.cpp
+msgid "Directory of the same name exists"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
+#, fuzzy
+msgid "File exists, will be reused"
+msgstr "文件已存在,确定è¦è¦†ç›–它å—?"
+
+#: editor/script_create_dialog.cpp
msgid "Invalid extension"
msgstr "扩展åéžæ³•"
@@ -6885,6 +6534,10 @@ msgid "Load existing script file"
msgstr "加载现有脚本"
#: editor/script_create_dialog.cpp
+msgid "Language"
+msgstr "语言"
+
+#: editor/script_create_dialog.cpp
msgid "Inherits"
msgstr "继承自"
@@ -6925,6 +6578,10 @@ msgid "Function:"
msgstr "函数:"
#: editor/script_editor_debugger.cpp
+msgid "Pick one or more items from the list to display the graph."
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
msgid "Errors"
msgstr "错误"
@@ -7005,6 +6662,10 @@ msgid "Type"
msgstr "类型"
#: editor/script_editor_debugger.cpp
+msgid "Format"
+msgstr "æ ¼å¼"
+
+#: editor/script_editor_debugger.cpp
msgid "Usage"
msgstr "用é‡"
@@ -7038,7 +6699,7 @@ msgstr "设置光照åŠå¾„"
#: editor/spatial_editor_gizmos.cpp
msgid "Change AudioStreamPlayer3D Emission Angle"
-msgstr ""
+msgstr "æ”¹å˜ AudioStreamPlayer3D å‘射角"
#: editor/spatial_editor_gizmos.cpp
msgid "Change Camera FOV"
@@ -7080,12 +6741,30 @@ msgstr "修改粒å­AABB"
msgid "Change Probe Extents"
msgstr "更改探针(Probe)范围"
+#: modules/gdnative/gd_native_library_editor.cpp
+#, fuzzy
+msgid "Library"
+msgstr "MeshLibrary(网格库).."
+
+#: modules/gdnative/gd_native_library_editor.cpp
+#, fuzzy
+msgid "Status"
+msgstr "状æ€ï¼š"
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Libraries: "
+msgstr ""
+
+#: modules/gdnative/register_types.cpp
+msgid "GDNative"
+msgstr ""
+
#: modules/gdscript/gd_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Invalid type argument to convert(), use TYPE_* constants."
msgstr "convert函数å‚数类型éžæ³•ï¼Œè¯·ä¼ å…¥ä»¥â€œTYPE_â€æ‰“头的常é‡ã€‚"
-#: modules/gdscript/gd_functions.cpp
+#: modules/gdscript/gd_functions.cpp modules/mono/glue/glue_header.h
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Not enough bytes for decoding bytes, or invalid format."
msgstr "没有足够的字节æ¥è§£ç æˆ–æ ¼å¼ä¸æ­£ç¡®ã€‚"
@@ -7124,133 +6803,112 @@ msgstr "éžæ³•çš„字典实例(派生类éžæ³•ï¼‰"
#: modules/gdscript/gd_functions.cpp
msgid "Object can't provide a length."
-msgstr ""
+msgstr "对象ä¸èƒ½æ供长度。"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "GridMap Delete Selection"
-msgstr "删除选择的节点"
+msgstr "删除选择的栅格图"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "GridMap Duplicate Selection"
msgstr "å¤åˆ¶é€‰ä¸­é¡¹"
#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "GridMap Paint"
-msgstr ""
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Snap View"
-msgstr "Top视图"
+msgstr "æ•æ‰è§†å›¾"
#: modules/gridmap/grid_map_editor_plugin.cpp
+#, fuzzy
msgid "Prev Level (%sDown Wheel)"
-msgstr ""
+msgstr "上一级"
#: modules/gridmap/grid_map_editor_plugin.cpp
+#, fuzzy
msgid "Next Level (%sUp Wheel)"
-msgstr ""
+msgstr "下一级"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Clip Disabled"
-msgstr "å·²ç¦ç”¨"
+msgstr "ç¦ç”¨å‰ªè¾‘"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Clip Above"
-msgstr ""
+msgstr "上级剪辑"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Clip Below"
-msgstr ""
+msgstr "下级剪辑"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Edit X Axis"
-msgstr ""
+msgstr "编辑 X 轴"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Edit Y Axis"
-msgstr ""
+msgstr "编辑 Y 轴"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Edit Z Axis"
-msgstr ""
+msgstr "编辑 Z 轴"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Cursor Rotate X"
-msgstr "Ctrl:旋转"
+msgstr "光标沿X轴旋转"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Cursor Rotate Y"
-msgstr "Ctrl:旋转"
+msgstr "沿Y轴旋转"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Cursor Rotate Z"
-msgstr "Ctrl:旋转"
+msgstr "沿Z轴旋转"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Cursor Back Rotate X"
-msgstr ""
+msgstr "光标沿Xè½´å‘åŽæ—‹è½¬"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Cursor Back Rotate Y"
-msgstr ""
+msgstr "光标沿Yè½´å‘åŽæ—‹è½¬"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Cursor Back Rotate Z"
-msgstr ""
+msgstr "光标沿Zè½´å‘åŽæ—‹è½¬"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Cursor Clear Rotation"
-msgstr ""
+msgstr "光标清除旋转"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Create Area"
-msgstr "新建"
+msgstr "新建区域"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Create Exterior Connector"
-msgstr "新建项目"
+msgstr "创建外部连接器"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Erase Area"
-msgstr "擦除砖å—地图"
+msgstr "擦除区域"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Selection -> Duplicate"
-msgstr "仅选中"
+msgstr "选择->å¤åˆ¶"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Selection -> Clear"
-msgstr "仅选中"
+msgstr "选择->清空"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "GridMap Settings"
-msgstr "æ•æ‰(snap)设置"
+msgstr "栅格图设置"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Pick Distance:"
-msgstr "实例:"
+msgstr "拾å–è·ç¦»:"
-#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
-msgid "Tiles"
-msgstr "文件"
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "Areas"
+#: modules/mono/editor/mono_bottom_panel.cpp
+msgid "Builds"
msgstr ""
#: modules/visual_script/visual_script.cpp
@@ -7285,29 +6943,24 @@ msgid "Stack overflow with stack depth: "
msgstr "堆栈深度溢出: "
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Change Signal Arguments"
-msgstr "编辑事件å‚æ•°:"
+msgstr "编辑信å·å‚æ•°"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Change Argument Type"
-msgstr "修改数组类型"
+msgstr "修改å‚数类型"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Change Argument name"
-msgstr "更改输入å称"
+msgstr "更改å‚æ•°å称"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Set Variable Default Value"
msgstr "修改默认值"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Set Variable Type"
-msgstr "编辑å˜é‡:"
+msgstr "设置å˜é‡ç±»åž‹"
#: modules/visual_script/visual_script_editor.cpp
msgid "Functions:"
@@ -7358,14 +7011,12 @@ msgid "Add Node"
msgstr "添加节点"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Remove VisualScript Nodes"
-msgstr "移除无效键"
+msgstr "删除 VisualScript 节点"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Duplicate VisualScript Nodes"
-msgstr "å¤åˆ¶Graph Node节点"
+msgstr "å¤åˆ¶ VisualScript 节点"
#: modules/visual_script/visual_script_editor.cpp
msgid "Hold Meta to drop a Getter. Hold Shift to drop a generic signature."
@@ -7408,24 +7059,20 @@ msgid "Add Setter Property"
msgstr "添加 Setter Property"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Change Base Type"
-msgstr "更改类型"
+msgstr "更改基本类型"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Move Node(s)"
-msgstr "移除节点"
+msgstr "移动节点"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Remove VisualScript Node"
-msgstr "移除Graph Node节点"
+msgstr "删除 VisualScript 节点"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Connect Nodes"
-msgstr "连接到节点:"
+msgstr "连接节点"
#: modules/visual_script/visual_script_editor.cpp
msgid "Condition"
@@ -7452,46 +7099,48 @@ msgid "Return"
msgstr "返回节点(Return)"
#: modules/visual_script/visual_script_editor.cpp
+msgid "Call"
+msgstr "调用到"
+
+#: modules/visual_script/visual_script_editor.cpp
msgid "Get"
msgstr "获å–"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
+msgid "Script already has function '%s'"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
msgid "Change Input Value"
-msgstr "更改输入å称"
+msgstr "更改输入的值"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Can't copy the function node."
-msgstr "无法对'..'引用æ“作"
+msgstr "无法å¤åˆ¶å‡½æ•°èŠ‚点。"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Clipboard is empty!"
-msgstr "资æºå‰ªåˆ‡æ¿ä¸­æ— å†…容ï¼"
+msgstr "剪贴æ¿æ˜¯ç©ºçš„ ï¼"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Paste VisualScript Nodes"
-msgstr "粘贴节点"
+msgstr "粘贴 VisualScript 节点"
#: modules/visual_script/visual_script_editor.cpp
msgid "Remove Function"
msgstr "删除函数"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Edit Variable"
-msgstr "编辑å˜é‡:"
+msgstr "编辑å˜é‡"
#: modules/visual_script/visual_script_editor.cpp
msgid "Remove Variable"
msgstr "删除å˜é‡"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Edit Signal"
-msgstr "编辑事件:"
+msgstr "编辑信å·"
#: modules/visual_script/visual_script_editor.cpp
msgid "Remove Signal"
@@ -7703,7 +7352,7 @@ msgstr ""
msgid ""
"A material to process the particles is not assigned, so no behavior is "
"imprinted."
-msgstr ""
+msgstr "ç²’å­æ质没有指定,该行为无效。"
#: scene/2d/path_2d.cpp
msgid "PathFollow2D only works when set as a child of a Path2D node."
@@ -7715,6 +7364,9 @@ msgid ""
"by the physics engine when running.\n"
"Change the size in children collision shapes instead."
msgstr ""
+"è¿è¡Œæ—¶ï¼Œä¿®æ”¹RigidBody2D (character或rigid模å¼ï¼‰çš„尺寸,会修改物ç†å¼•æ“Žçš„大å°"
+"尺寸。\n"
+"修改å­èŠ‚点碰撞形状的大å°ä½œä¸ºä»£æ›¿ã€‚"
#: scene/2d/remote_transform_2d.cpp
msgid "Path property must point to a valid Node2D node to work."
@@ -7743,31 +7395,31 @@ msgstr "VisibilityEnable2D类型的节点用于场景的根节点æ‰èƒ½èŽ·å¾—最
#: scene/3d/arvr_nodes.cpp
msgid "ARVRCamera must have an ARVROrigin node as its parent"
-msgstr ""
+msgstr "ARVRCamera 必须处于 ARVROrigin 节点之下"
#: scene/3d/arvr_nodes.cpp
msgid "ARVRController must have an ARVROrigin node as its parent"
-msgstr ""
+msgstr "ARVRController 必须处于 ARVROrigin 节点之下"
#: scene/3d/arvr_nodes.cpp
msgid ""
"The controller id must not be 0 or this controller will not be bound to an "
"actual controller"
-msgstr ""
+msgstr "控制器 id å¿…é¡»ä¸ä¸º 0 或此控制器将ä¸ç»‘定到实际的控制器"
#: scene/3d/arvr_nodes.cpp
msgid "ARVRAnchor must have an ARVROrigin node as its parent"
-msgstr ""
+msgstr "ARVRAnchor 必须处于 ARVROrigin 节点之下"
#: scene/3d/arvr_nodes.cpp
msgid ""
"The anchor id must not be 0 or this anchor will not be bound to an actual "
"anchor"
-msgstr ""
+msgstr "锚 id å¿…é¡»ä¸æ˜¯ 0 或这个锚点将ä¸ç»‘定到实际的锚"
#: scene/3d/arvr_nodes.cpp
msgid "ARVROrigin requires an ARVRCamera child node"
-msgstr ""
+msgstr "ARVROrigin 必须拥有 ARVRCamera å­èŠ‚点"
#: scene/3d/collision_polygon.cpp
msgid ""
@@ -7813,7 +7465,7 @@ msgstr ""
#: scene/3d/particles.cpp
msgid ""
"Nothing is visible because meshes have not been assigned to draw passes."
-msgstr ""
+msgstr "ç²’å­ä¸å¯è§ï¼Œå› ä¸ºæ²¡æœ‰ç½‘æ ¼(meshes)指定到绘制通é“(draw passes)。"
#: scene/3d/physics_body.cpp
msgid ""
@@ -7821,6 +7473,9 @@ msgid ""
"the physics engine when running.\n"
"Change the size in children collision shapes instead."
msgstr ""
+"è¿è¡Œæ—¶ï¼Œä¿®æ”¹RigidBody(character或rigid模å¼ï¼‰çš„尺寸,会修改物ç†å¼•æ“Žçš„大å°å°º"
+"寸。\n"
+"修改å­èŠ‚点碰撞形状的大å°ä½œä¸ºä»£æ›¿ã€‚"
#: scene/3d/remote_transform.cpp
msgid "Path property must point to a valid Spatial node to work."
@@ -7839,16 +7494,25 @@ msgstr ""
"SpriteFrame资æºå¿…须是通过AnimatedSprite3D节点的Frames属性创建的,å¦åˆ™æ— æ³•æ˜¾ç¤º"
"动画帧。"
+#: scene/3d/vehicle_body.cpp
+msgid ""
+"VehicleWheel serves to provide a wheel system to a VehicleBody. Please use "
+"it as a child of a VehicleBody."
+msgstr ""
+
#: scene/gui/color_picker.cpp
-#, fuzzy
msgid "Raw Mode"
-msgstr "移动画布"
+msgstr "Raw 模å¼"
#: scene/gui/color_picker.cpp
msgid "Add current color as a preset"
msgstr "将当å‰é¢œè‰²æ·»åŠ ä¸ºé¢„设"
#: scene/gui/dialogs.cpp
+msgid "Cancel"
+msgstr "å–消"
+
+#: scene/gui/dialogs.cpp
msgid "Alert!"
msgstr "æ示ï¼"
@@ -7856,10 +7520,6 @@ msgstr "æ示ï¼"
msgid "Please Confirm..."
msgstr "请确认..."
-#: scene/gui/input_action.cpp
-msgid "Ctrl+"
-msgstr "Ctrl+"
-
#: scene/gui/popup.cpp
msgid ""
"Popups will hide by default unless you call popup() or any of the popup*() "
@@ -7883,7 +7543,7 @@ msgstr ""
msgid ""
"Default Environment as specified in Project Setings (Rendering -> Viewport -"
"> Default Environment) could not be loaded."
-msgstr ""
+msgstr "项目设置中的默认环境无法加载,详è§ï¼ˆæ¸²æŸ“->视图->默认环境) 。"
#: scene/main/viewport.cpp
msgid ""
@@ -7896,6 +7556,637 @@ msgstr ""
"使其æˆä¸ºå­æŽ§ä»¶çš„所以它å¯ä»¥æœ‰ä¸€ä¸ªå°ºå¯¸å¤§å°å€¼ã€‚å¦åˆ™è¯·è®¾ç½®ä¸ºRender target,并将其"
"内部纹ç†åˆ†é…给一些节点以显示。"
+#: scene/resources/dynamic_font.cpp
+msgid "Error initializing FreeType."
+msgstr "åˆå§‹åŒ–FreeType出错。"
+
+#: scene/resources/dynamic_font.cpp
+msgid "Unknown font format."
+msgstr "未知的字体格å¼ã€‚"
+
+#: scene/resources/dynamic_font.cpp
+msgid "Error loading font."
+msgstr "加载字体出错。"
+
+#: scene/resources/dynamic_font.cpp
+msgid "Invalid font size."
+msgstr "字体大å°éžæ³•ã€‚"
+
+#~ msgid "Filter:"
+#~ msgstr "筛选:"
+
+#~ msgid "' parsing of config failed."
+#~ msgstr "' 解æžé…置失败。"
+
+#~ msgid "Theme"
+#~ msgstr "主题"
+
+#~ msgid "Method List For '%s':"
+#~ msgstr "'%s'的方法列表:"
+
+#~ msgid "Arguments:"
+#~ msgstr "å‚æ•°:"
+
+#~ msgid "Return:"
+#~ msgstr "返回:"
+
+#~ msgid "Added:"
+#~ msgstr "已添加:"
+
+#~ msgid "Removed:"
+#~ msgstr "已移除:"
+
+#~ msgid "Error saving atlas:"
+#~ msgstr "ä¿å­˜è´´å›¾é›†å‡ºé”™:"
+
+#~ msgid "Could not save atlas subtexture:"
+#~ msgstr "无法ä¿å­˜ç²¾çµé›†å­è´´å›¾:"
+
+#~ msgid "Exporting for %s"
+#~ msgstr "正在导出 %s"
+
+#~ msgid "Setting Up.."
+#~ msgstr "é…ç½®.."
+
+#~ msgid "Error loading scene."
+#~ msgstr "加载场景出错。"
+
+#~ msgid "Re-Import"
+#~ msgstr "é‡æ–°å¯¼å…¥"
+
+#~ msgid "Please wait for scan to complete."
+#~ msgstr "扫æ中,请ç¨åŽ..."
+
+#~ msgid "Current scene must be saved to re-import."
+#~ msgstr "需è¦å…ˆä¿å­˜å½“å‰åœºæ™¯æ‰èƒ½é‡æ–°å¯¼å…¥ã€‚"
+
+#~ msgid "Save & Re-Import"
+#~ msgstr "ä¿å­˜å¹¶é‡æ–°å¯¼å…¥"
+
+#~ msgid "Re-Importing"
+#~ msgstr "é‡æ–°å¯¼å…¥"
+
+#~ msgid "Re-Import Changed Resources"
+#~ msgstr "é‡æ–°å¯¼å…¥æ”¹å˜çš„资æº"
+
+#~ msgid "Loading Export Templates"
+#~ msgstr "正在加载导出模æ¿"
+
+#~ msgid ""
+#~ "\n"
+#~ "Status: Needs Re-Import"
+#~ msgstr ""
+#~ "\n"
+#~ "状æ€ï¼š 需è¦é‡æ–°å¯¼å…¥"
+
+#~ msgid "Same source and destination files, doing nothing."
+#~ msgstr "æºæ–‡ä»¶å’Œç›®æ ‡æ–‡ä»¶ç›¸åŒï¼Œæ“作忽略。"
+
+#~ msgid "Target file exists, can't overwrite. Delete first."
+#~ msgstr "目标文件存在,无法覆盖。请先删除。"
+
+#~ msgid "Same source and destination paths, doing nothing."
+#~ msgstr "æºè·¯å¾„和目标路径相åŒï¼Œæ“作忽略。"
+
+#~ msgid "Can't move directories to within themselves."
+#~ msgstr "无法将目录移动到自身下。"
+
+#~ msgid "Can't rename deps for:\n"
+#~ msgstr "无法é‡å‘½ådeps:\n"
+
+#~ msgid "Error moving file:\n"
+#~ msgstr "移动文件时出错:\n"
+
+#~ msgid "Pick New Name and Location For:"
+#~ msgstr "选择新å称和路径:"
+
+#~ msgid "No files selected!"
+#~ msgstr "没有选中任何文件ï¼"
+
+#~ msgid "Info"
+#~ msgstr "ä¿¡æ¯"
+
+#~ msgid "Re-Import.."
+#~ msgstr "é‡æ–°å¯¼å…¥.."
+
+#~ msgid "No bit masks to import!"
+#~ msgstr "没有è¦å¯¼å…¥çš„bit masksï¼"
+
+#~ msgid "Target path is empty."
+#~ msgstr "目标路径为空。"
+
+#~ msgid "Target path must be a complete resource path."
+#~ msgstr "目标路径必须是一个完整的资æºæ–‡ä»¶è·¯å¾„。"
+
+#~ msgid "Target path must exist."
+#~ msgstr "目标路径必须存在。"
+
+#~ msgid "Save path is empty!"
+#~ msgstr "ä¿å­˜è·¯å¾„为空ï¼"
+
+#~ msgid "Import BitMasks"
+#~ msgstr "导入BitMask"
+
+#~ msgid "Source Texture(s):"
+#~ msgstr "æºè´´å›¾:"
+
+#~ msgid "Target Path:"
+#~ msgstr "目标路径:"
+
+#~ msgid "Accept"
+#~ msgstr "接å—"
+
+#~ msgid "Bit Mask"
+#~ msgstr "ä½æŽ©ç ï¼ˆBitMask)"
+
+#~ msgid "No source font file!"
+#~ msgstr "请设置æºå­—体文件ï¼"
+
+#~ msgid "No target font resource!"
+#~ msgstr "请设置目标字体资æºï¼"
+
+#~ msgid ""
+#~ "Invalid file extension.\n"
+#~ "Please use .font."
+#~ msgstr ""
+#~ "文件扩展åä¸åˆæ³•\n"
+#~ "请使用.font文件。"
+
+#~ msgid "Couldn't save font."
+#~ msgstr "无法ä¿å­˜å­—体。"
+
+#~ msgid "Source Font:"
+#~ msgstr "æºå­—体文件:"
+
+#~ msgid "Source Font Size:"
+#~ msgstr "æºå­—体大å°:"
+
+#~ msgid "Dest Resource:"
+#~ msgstr "目标资æº:"
+
+#~ msgid "The quick brown fox jumps over the lazy dog."
+#~ msgstr ""
+#~ "The quick brown fox jumps over the lazy dog.\n"
+#~ "我能åžä¸‹çŽ»ç’ƒè€Œä¸ä¼¤èº«ä½“。"
+
+#~ msgid "Test:"
+#~ msgstr "测试:"
+
+#~ msgid "Options:"
+#~ msgstr "选项:"
+
+#~ msgid "Font Import"
+#~ msgstr "导入字体"
+
+#~ msgid ""
+#~ "This file is already a Godot font file, please supply a BMFont type file "
+#~ "instead."
+#~ msgstr "此文件已ç»æ˜¯ä¸€ä¸ªGodot的字体文件,请æ供一个ä½å›¾å­—体(BMFont)文件。"
+
+#~ msgid "Failed opening as BMFont file."
+#~ msgstr "打开ä½å›¾å­—体失败。"
+
+#~ msgid "Invalid font custom source."
+#~ msgstr "自定义字体文件éžæ³•ã€‚"
+
+#~ msgid "No meshes to import!"
+#~ msgstr "没有è¦å¯¼å…¥çš„Meshï¼"
+
+#~ msgid "Single Mesh Import"
+#~ msgstr "导入å•ä¸ªMesh"
+
+#~ msgid "Source Mesh(es):"
+#~ msgstr "æºMesh:"
+
+#~ msgid "Surface %d"
+#~ msgstr "è¡¨é¢ %d"
+
+#~ msgid "No samples to import!"
+#~ msgstr "没有音效è¦å¯¼å…¥ï¼"
+
+#~ msgid "Import Audio Samples"
+#~ msgstr "导入声音文件"
+
+#~ msgid "Source Sample(s):"
+#~ msgstr "æºéŸ³æ•ˆæ–‡ä»¶:"
+
+#~ msgid "Audio Sample"
+#~ msgstr "音效"
+
+#~ msgid "New Clip"
+#~ msgstr "新片段"
+
+#~ msgid "Flags"
+#~ msgstr "标记"
+
+#~ msgid "Bake FPS:"
+#~ msgstr "烘培FPS:"
+
+#~ msgid "Optimizer"
+#~ msgstr "优化"
+
+#~ msgid "Max Linear Error"
+#~ msgstr "最大线性误差"
+
+#~ msgid "Max Angular Error"
+#~ msgstr "最大角度误差"
+
+#~ msgid "Max Angle"
+#~ msgstr "最大角度"
+
+#~ msgid "Clips"
+#~ msgstr "片段"
+
+#~ msgid "Start(s)"
+#~ msgstr "起点"
+
+#~ msgid "End(s)"
+#~ msgstr "终点"
+
+#~ msgid "Filters"
+#~ msgstr "筛选"
+
+#~ msgid "Source path is empty."
+#~ msgstr "æºè·¯å¾„为空。"
+
+#~ msgid "Couldn't load post-import script."
+#~ msgstr "无法载入åŽå¯¼å…¥è„šæœ¬ã€‚"
+
+#~ msgid "Invalid/broken script for post-import."
+#~ msgstr "åŽå¯¼å…¥è„šæœ¬è¢«æŸå或ä¸åˆæ³•ã€‚"
+
+#~ msgid "Error importing scene."
+#~ msgstr "导入场景出错。"
+
+#~ msgid "Import 3D Scene"
+#~ msgstr "导入3D场景"
+
+#~ msgid "Source Scene:"
+#~ msgstr "æºåœºæ™¯:"
+
+#~ msgid "Same as Target Scene"
+#~ msgstr "与目标场景相åŒ"
+
+#~ msgid "Shared"
+#~ msgstr "共享的"
+
+#~ msgid "Target Texture Folder:"
+#~ msgstr "目标贴图目录:"
+
+#~ msgid "Post-Process Script:"
+#~ msgstr "åŽå¤„ç†è„šæœ¬:"
+
+#~ msgid "Custom Root Node Type:"
+#~ msgstr "自定义根节点类型:"
+
+#~ msgid "Auto"
+#~ msgstr "自动"
+
+#~ msgid "Root Node Name:"
+#~ msgstr "节点å称:"
+
+#~ msgid "The Following Files are Missing:"
+#~ msgstr "找ä¸åˆ°ä¸‹åˆ—文件:"
+
+#~ msgid "Import Anyway"
+#~ msgstr "ä»ç„¶å¯¼å…¥"
+
+#~ msgid "Import & Open"
+#~ msgstr "导入|打开"
+
+#~ msgid "Edited scene has not been saved, open imported scene anyway?"
+#~ msgstr "正在编辑的场景尚未ä¿å­˜ï¼Œä»ç„¶è¦æ‰“开导入的场景å—?"
+
+#~ msgid "Import Image:"
+#~ msgstr "导入图片:"
+
+#~ msgid "Couldn't localize path: %s (already local)"
+#~ msgstr "无法本地化路径:%s (å·²ç»æ˜¯æœ¬åœ°è·¯å¾„)"
+
+#~ msgid "3D Scene Animation"
+#~ msgstr "3D场景动画"
+
+#~ msgid "Uncompressed"
+#~ msgstr "ä¸åŽ‹ç¼©"
+
+#~ msgid "Compress Lossless (PNG)"
+#~ msgstr "æ— æŸåŽ‹ç¼©ï¼ˆPNG)"
+
+#~ msgid "Compress Lossy (WebP)"
+#~ msgstr "有æŸåŽ‹ç¼©ï¼ˆWebP)"
+
+#~ msgid "Compress (VRAM)"
+#~ msgstr "VRAM压缩"
+
+#~ msgid "Texture Format"
+#~ msgstr "纹ç†æ ¼å¼"
+
+#~ msgid "Texture Compression Quality (WebP):"
+#~ msgstr "高质é‡ï¼ˆWebP)压缩方å¼:"
+
+#~ msgid "Texture Options"
+#~ msgstr "纹ç†é€‰é¡¹"
+
+#~ msgid "Please specify some files!"
+#~ msgstr "请添加文件ï¼"
+
+#~ msgid "At least one file needed for Atlas."
+#~ msgstr "ç²¾çµé›†è‡³å°‘需è¦ä¸€ä¸ªæ–‡ä»¶ã€‚"
+
+#~ msgid "Error importing:"
+#~ msgstr "导入出错:"
+
+#~ msgid "Only one file is required for large texture."
+#~ msgstr "大图导入仅支æŒä¸€ä¸ªè¾“入文件。"
+
+#~ msgid "Max Texture Size:"
+#~ msgstr "最大纹ç†å°ºå¯¸:"
+
+#~ msgid "Import Textures for Atlas (2D)"
+#~ msgstr "导入2Dç²¾çµé›†"
+
+#~ msgid "Cell Size:"
+#~ msgstr "å•å…ƒå°ºå¯¸:"
+
+#~ msgid "Large Texture"
+#~ msgstr "大图"
+
+#~ msgid "Import Large Textures (2D)"
+#~ msgstr "导入2D大图"
+
+#~ msgid "Source Texture"
+#~ msgstr "æºè´´å›¾"
+
+#~ msgid "Base Atlas Texture"
+#~ msgstr "基础图集纹ç†"
+
+#~ msgid "Source Texture(s)"
+#~ msgstr "æºè´´å›¾(s)"
+
+#~ msgid "Import Textures for 2D"
+#~ msgstr "导入2D贴图"
+
+#~ msgid "Import Textures for 3D"
+#~ msgstr "导入3D贴图"
+
+#~ msgid "Import Textures"
+#~ msgstr "导入贴图"
+
+#~ msgid "2D Texture"
+#~ msgstr "2D贴图"
+
+#~ msgid "3D Texture"
+#~ msgstr "3D贴图"
+
+#~ msgid "Atlas Texture"
+#~ msgstr "ç²¾çµå›¾é›†"
+
+#~ msgid ""
+#~ "NOTICE: Importing 2D textures is not mandatory. Just copy png/jpg files "
+#~ "to the project."
+#~ msgstr ""
+#~ "æ示:大多数2D贴图并ä¸éœ€è¦å¯¼å…¥æ“作,åªè¦å°†png/jpg文件放到项目目录下å³å¯ã€‚"
+
+#~ msgid "Crop empty space."
+#~ msgstr "切除空白区域。"
+
+#~ msgid "Texture"
+#~ msgstr "贴图"
+
+#~ msgid "Import Large Texture"
+#~ msgstr "导入大图"
+
+#~ msgid "Load Source Image"
+#~ msgstr "加载æºå›¾ç‰‡"
+
+#~ msgid "Slicing"
+#~ msgstr "切片中"
+
+#~ msgid "Saving"
+#~ msgstr "正在ä¿å­˜æ–‡ä»¶"
+
+#~ msgid "Couldn't save large texture:"
+#~ msgstr "无法ä¿å­˜å¤§å›¾:"
+
+#~ msgid "Build Atlas For:"
+#~ msgstr "使用以下图片生æˆç²¾çµé›†:"
+
+#~ msgid "Loading Image:"
+#~ msgstr "加载图片中:"
+
+#~ msgid "Couldn't load image:"
+#~ msgstr "无法加载图片:"
+
+#~ msgid "Converting Images"
+#~ msgstr "正在转æ¢å›¾ç‰‡"
+
+#~ msgid "Cropping Images"
+#~ msgstr "剪è£å›¾ç‰‡"
+
+#~ msgid "Blitting Images"
+#~ msgstr "Blitting 图片"
+
+#~ msgid "Couldn't save atlas image:"
+#~ msgstr "无法ä¿å­˜ç²¾çµé›†å›¾ç‰‡:"
+
+#~ msgid "Couldn't save converted texture:"
+#~ msgstr "无法ä¿å­˜è½¬æ¢çš„贴图:"
+
+#~ msgid "Invalid source!"
+#~ msgstr "输入æºéžæ³•ï¼"
+
+#~ msgid "Invalid translation source!"
+#~ msgstr "æºè¯­è¨€æ–‡ä»¶éžæ³•ï¼"
+
+#~ msgid "Column"
+#~ msgstr "列"
+
+#~ msgid "No items to import!"
+#~ msgstr "没有è¦å¯¼å…¥çš„项目ï¼"
+
+#~ msgid "No target path!"
+#~ msgstr "目标路径为空ï¼"
+
+#~ msgid "Import Translations"
+#~ msgstr "导入多ç§è¯­è¨€ç¿»è¯‘"
+
+#~ msgid "Couldn't import!"
+#~ msgstr "无法导入ï¼"
+
+#~ msgid "Import Translation"
+#~ msgstr "导入语言翻译"
+
+#~ msgid "Source CSV:"
+#~ msgstr "æºCSV文件:"
+
+#~ msgid "Ignore First Row"
+#~ msgstr "忽略第一行"
+
+#~ msgid "Compress"
+#~ msgstr "压缩"
+
+#~ msgid "Add to Project (project.godot)"
+#~ msgstr "添加到项目 (project.godot)"
+
+#~ msgid "Import Languages:"
+#~ msgstr "导入语言:"
+
+#~ msgid "Translation"
+#~ msgstr "语言"
+
+#~ msgid "Parsing %d Triangles:"
+#~ msgstr "正在解æžç¬¬%d个三角形:"
+
+#~ msgid "Triangle #"
+#~ msgstr "三角形 #"
+
+#~ msgid "Light Baker Setup:"
+#~ msgstr "建立烘培:"
+
+#~ msgid "Fixing Lights"
+#~ msgstr "修正光照"
+
+#~ msgid "Making BVH"
+#~ msgstr "制作BVH(动作骨骼)"
+
+#~ msgid "Transfer to Lightmaps:"
+#~ msgstr "转移到光照贴图:"
+
+#~ msgid "Allocating Texture #"
+#~ msgstr "分é…çº¹ç† #"
+
+#~ msgid "Baking Triangle #"
+#~ msgstr "烘培三角形 #"
+
+#~ msgid "Post-Processing Texture #"
+#~ msgstr "åŽåŠ å·¥çº¹ç† #"
+
+#~ msgid "Reset the lightmap octree baking process (start over)."
+#~ msgstr "é‡ç½®è´´å›¾çƒ˜ç„™è¿‡ç¨‹ (é‡æ–°å¼€å§‹ï¼‰ çš„ octree (å…«å‰æ ‘)。"
+
+#~ msgid "Zoom (%):"
+#~ msgstr "缩放(%):"
+
+#~ msgid "Skeleton.."
+#~ msgstr "骨骼.."
+
+#~ msgid "Zoom Reset"
+#~ msgstr "é‡ç½®ç¼©æ”¾"
+
+#~ msgid "Zoom Set.."
+#~ msgstr "设置缩放.."
+
+#~ msgid "Set a Value"
+#~ msgstr "设置值"
+
+#~ msgid "Snap (Pixels):"
+#~ msgstr "å¸é™„(åƒç´ ï¼‰ï¼š"
+
+#~ msgid "Parse BBCode"
+#~ msgstr "解æžBBCode"
+
+#~ msgid "Length:"
+#~ msgstr "长度:"
+
+#~ msgid "Open Sample File(s)"
+#~ msgstr "打开声音文件"
+
+#~ msgid "ERROR: Couldn't load sample!"
+#~ msgstr "错误:无法加载音效ï¼"
+
+#~ msgid "Add Sample"
+#~ msgstr "添加音效"
+
+#~ msgid "Rename Sample"
+#~ msgstr "é‡å‘½å音效"
+
+#~ msgid "Delete Sample"
+#~ msgstr "删除音效"
+
+#~ msgid "16 Bits"
+#~ msgstr "16ä½"
+
+#~ msgid "8 Bits"
+#~ msgstr "8ä½"
+
+#~ msgid "Stereo"
+#~ msgstr "立体声"
+
+#~ msgid "Mono"
+#~ msgstr "å•å£°é“"
+
+#~ msgid "Pitch"
+#~ msgstr "音调"
+
+#~ msgid "Window"
+#~ msgstr "窗å£"
+
+#~ msgid "Move Right"
+#~ msgstr "å‘å³ç§»åŠ¨"
+
+#~ msgid "Scaling to %s%%."
+#~ msgstr "缩放到%s%%。"
+
+#~ msgid "Up"
+#~ msgstr "å‘上"
+
+#~ msgid "Down"
+#~ msgstr "å‘下"
+
+#~ msgid "Bucket"
+#~ msgstr "桶(Bucket)"
+
+#~ msgid "Invalid project path, the path must exist!"
+#~ msgstr "项目目录ä¸å­˜åœ¨ï¼"
+
+#~ msgid "Invalid project path, project.godot must not exist."
+#~ msgstr "项目目录下ä¸èƒ½åŒ…å«project.godot文件。"
+
+#~ msgid "Invalid project path, project.godot must exist."
+#~ msgstr "项目目录下必须包å«project.godot文件。"
+
+#~ msgid "Project Path (Must Exist):"
+#~ msgstr "项目目录(必须存在):"
+
+#~ msgid "Create New Resource"
+#~ msgstr "创建资æº"
+
+#~ msgid "Open Resource"
+#~ msgstr "打开资æº"
+
+#~ msgid "Save Resource"
+#~ msgstr "ä¿å­˜èµ„æº"
+
+#~ msgid "Resource Tools"
+#~ msgstr "资æºå·¥å…·"
+
+#~ msgid "Make Local"
+#~ msgstr "使用本地"
+
+#~ msgid "Edit Groups"
+#~ msgstr "编辑分组"
+
+#~ msgid "Edit Connections"
+#~ msgstr "编辑事件连接"
+
+#~ msgid "GridMap Paint"
+#~ msgstr "绘制栅格图"
+
+#~ msgid "Tiles"
+#~ msgstr "ç –å—(Tiles)"
+
+#~ msgid "Areas"
+#~ msgstr "区域"
+
+#~ msgid "Ctrl+"
+#~ msgstr "Ctrl+"
+
+#~ msgid "Down Wheel)"
+#~ msgstr "下轮)"
+
+#~ msgid "Up Wheel)"
+#~ msgstr "上轮)"
+
#~ msgid "Close scene? (Unsaved changes will be lost)"
#~ msgstr "确定è¦å…³é—­åœºæ™¯å—?(未ä¿å­˜çš„修改将丢失)"
@@ -7909,9 +8200,6 @@ msgstr ""
#~ msgid "Close Goto Prev. Scene"
#~ msgstr "关闭并å‰å¾€ä¸Šä¸€ä¸ªåœºæ™¯"
-#~ msgid "Expand to Parent"
-#~ msgstr "展开父节点"
-
#~ msgid "Del"
#~ msgstr "删除"
@@ -8070,18 +8358,12 @@ msgstr ""
#~ msgid "Save Translatable Strings"
#~ msgstr "ä¿å­˜å¯ç¿»è¯‘字符串"
-#~ msgid "Translatable Strings.."
-#~ msgstr "å¯ç¿»è¯‘字符串.."
-
#~ msgid "Install Export Templates"
#~ msgstr "安装导出模æ¿"
#~ msgid "Edit Script Options"
#~ msgstr "脚本编辑器选项"
-#~ msgid "Please export outside the project folder!"
-#~ msgstr "请导出到项目目录之外ï¼"
-
#~ msgid "Error exporting project!"
#~ msgstr "导出项目出错ï¼"
@@ -8140,18 +8422,12 @@ msgstr ""
#~ msgid "Include"
#~ msgstr "包å«"
-#~ msgid "Change Image Group"
-#~ msgstr "修改图片分组"
-
#~ msgid "Group name can't be empty!"
#~ msgstr "分组å称ä¸èƒ½ä¸ºç©ºï¼"
#~ msgid "Invalid character in group name!"
#~ msgstr "分组å称中包å«éžæ³•å­—符ï¼"
-#~ msgid "Group name already exists!"
-#~ msgstr "分组å称已存在ï¼"
-
#~ msgid "Add Image Group"
#~ msgstr "添加图片分组"
@@ -8230,9 +8506,6 @@ msgstr ""
#~ msgid "Preview Atlas"
#~ msgstr "ç²¾çµé›†é¢„览"
-#~ msgid "Image Filter:"
-#~ msgstr "纹ç†è¿‡æ»¤:"
-
#~ msgid "Images:"
#~ msgstr "图片:"
diff --git a/editor/translations/zh_HK.po b/editor/translations/zh_HK.po
index ceb21d7b85..3828ea059c 100644
--- a/editor/translations/zh_HK.po
+++ b/editor/translations/zh_HK.po
@@ -1,5 +1,6 @@
# Chinese (Hong Kong) translation of the Godot Engine editor
-# Copyright (C) 2016-2017 Juan Linietsky, Ariel Manzur and the Godot community
+# Copyright (C) 2007-2017 Juan Linietsky, Ariel Manzur
+# Copyright (C) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)
# This file is distributed under the same license as the Godot source code.
#
# Wesley (zx-wt) <ZX_WT@ymail.com>, 2016-2017.
@@ -196,10 +197,9 @@ msgid "Create %d NEW tracks and insert keys?"
msgstr ""
#: editor/animation_editor.cpp editor/create_dialog.cpp
-#: editor/editor_audio_buses.cpp
+#: editor/editor_audio_buses.cpp editor/plugins/abstract_polygon_2d_editor.cpp
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
#: editor/plugins/mesh_instance_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp editor/project_manager.cpp
#: editor/script_create_dialog.cpp
msgid "Create"
@@ -361,265 +361,6 @@ msgstr ""
msgid "Change Array Value"
msgstr ""
-#: editor/asset_library_editor_plugin.cpp
-msgid "Free"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_plugin_settings.cpp
-msgid "Version:"
-msgstr "版本:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Contents:"
-msgstr "內容:"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "View Files"
-msgstr "檔案"
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_help.cpp editor/property_selector.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Description:"
-msgstr "æ述:"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-#: editor/project_manager.cpp
-msgid "Install"
-msgstr "安è£"
-
-#: editor/asset_library_editor_plugin.cpp editor/call_dialog.cpp
-#: editor/connections_dialog.cpp editor/export_template_manager.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-#: editor/project_settings_editor.cpp editor/property_editor.cpp
-#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Close"
-msgstr "關閉"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve hostname:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Connection error, please try again."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't connect."
-msgstr "ä¸èƒ½é€£æŽ¥ã€‚"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't connect to host:"
-msgstr "ä¸èƒ½é€£åˆ°ä¸»æ©Ÿï¼š"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response from host:"
-msgstr "主機沒有回應:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response."
-msgstr "沒有回應。"
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Request failed, return code:"
-msgstr "請求失敗,"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Req. Failed."
-msgstr "請求失敗。"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Request failed, too many redirects"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Redirect Loop."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed:"
-msgstr "失敗:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Bad download hash, assuming file has been tampered with."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Expected:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Got:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Asset Download Error:"
-msgstr "Asset下載出ç¾éŒ¯èª¤ï¼š"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-msgid "Success!"
-msgstr "æˆåŠŸï¼"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Fetching:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Resolving.."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Connecting.."
-msgstr "連到..."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Requesting.."
-msgstr "請求中..."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Error making request"
-msgstr "請求時出ç¾éŒ¯èª¤"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Idle"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Retry"
-msgstr "é‡è©¦"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Download Error"
-msgstr "下載出ç¾éŒ¯èª¤"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Download for this asset is already in progress!"
-msgstr "Asset已在下載中"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "first"
-msgstr "首é "
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "prev"
-msgstr "上一é "
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "next"
-msgstr "下一é "
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "last"
-msgstr "å°¾é "
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "All"
-msgstr "全部"
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
-#: editor/settings_config_dialog.cpp
-msgid "Search:"
-msgstr "æœå°‹ï¼š"
-
-#: editor/asset_library_editor_plugin.cpp editor/code_editor.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Search"
-msgstr "æœå°‹"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/project_manager.cpp
-msgid "Import"
-msgstr "å°Žå…¥"
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Plugins"
-msgstr "æ’件"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Sort:"
-msgstr "排åºï¼š"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Reverse"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Category:"
-msgstr "分類:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Site:"
-msgstr "地å€:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Support.."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Official"
-msgstr "官方"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-msgid "Community"
-msgstr "社群"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Testing"
-msgstr "測試"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Assets ZIP File"
-msgstr "Assets ZIP 檔"
-
-#: editor/call_dialog.cpp
-msgid "Method List For '%s':"
-msgstr ""
-
-#: editor/call_dialog.cpp modules/visual_script/visual_script_editor.cpp
-msgid "Call"
-msgstr ""
-
-#: editor/call_dialog.cpp
-msgid "Method List:"
-msgstr ""
-
-#: editor/call_dialog.cpp
-msgid "Arguments:"
-msgstr ""
-
-#: editor/call_dialog.cpp
-msgid "Return:"
-msgstr ""
-
#: editor/code_editor.cpp
msgid "Go to Line"
msgstr "跳到行"
@@ -656,6 +397,14 @@ msgstr "完整詞語"
msgid "Selection Only"
msgstr "åªé™é¸ä¸­"
+#: editor/code_editor.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
+msgid "Search"
+msgstr "æœå°‹"
+
#: editor/code_editor.cpp editor/editor_help.cpp
msgid "Find"
msgstr "查找"
@@ -688,11 +437,11 @@ msgstr ""
msgid "Skip"
msgstr "è·³éŽ"
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom In"
msgstr "放大"
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom Out"
msgstr "縮å°"
@@ -760,6 +509,20 @@ msgstr ""
msgid "Oneshot"
msgstr ""
+#: editor/connections_dialog.cpp editor/dependency_editor.cpp
+#: editor/export_template_manager.cpp
+#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Close"
+msgstr "關閉"
+
#: editor/connections_dialog.cpp
msgid "Connect"
msgstr "連到"
@@ -785,7 +548,7 @@ msgstr "連到..."
msgid "Disconnect"
msgstr "中斷"
-#: editor/connections_dialog.cpp editor/node_dock.cpp
+#: editor/connections_dialog.cpp editor/editor_help.cpp editor/node_dock.cpp
msgid "Signals"
msgstr "訊號"
@@ -802,12 +565,25 @@ msgstr "最愛:"
msgid "Recent:"
msgstr "最近:"
+#: editor/create_dialog.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/quick_open.cpp editor/settings_config_dialog.cpp
+msgid "Search:"
+msgstr "æœå°‹ï¼š"
+
#: editor/create_dialog.cpp editor/editor_help.cpp
#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/quick_open.cpp
msgid "Matches:"
msgstr "å»åˆï¼š"
+#: editor/create_dialog.cpp editor/editor_help.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/property_selector.cpp
+#: editor/script_editor_debugger.cpp
+msgid "Description:"
+msgstr "æ述:"
+
#: editor/dependency_editor.cpp
msgid "Search Replacement For:"
msgstr "æœå°‹å’Œæ›¿ä»£ç‚ºï¼š"
@@ -863,6 +639,10 @@ msgid "Owners Of:"
msgstr ""
#: editor/dependency_editor.cpp
+msgid "Remove selected files from the project? (no undo)"
+msgstr ""
+
+#: editor/dependency_editor.cpp
msgid ""
"The files being removed are required by other resources in order for them to "
"work.\n"
@@ -870,7 +650,7 @@ msgid ""
msgstr ""
#: editor/dependency_editor.cpp
-msgid "Remove selected files from the project? (no undo)"
+msgid "Cannot remove:\n"
msgstr ""
#: editor/dependency_editor.cpp
@@ -937,10 +717,6 @@ msgid "Godot Engine contributors"
msgstr ""
#: editor/editor_about.cpp
-msgid "Authors"
-msgstr ""
-
-#: editor/editor_about.cpp
#, fuzzy
msgid "Project Founders"
msgstr "專案設定"
@@ -959,6 +735,38 @@ msgid "Developers"
msgstr "開發者"
#: editor/editor_about.cpp
+msgid "Authors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Platinum Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Gold Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Mini Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Gold Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Silver Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Bronze Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
msgid "License"
msgstr ""
@@ -1002,6 +810,16 @@ msgid "Package Installed Successfully!"
msgstr ""
#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Success!"
+msgstr "æˆåŠŸï¼"
+
+#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/project_manager.cpp
+msgid "Install"
+msgstr "安è£"
+
+#: editor/editor_asset_installer.cpp
msgid "Package Installer"
msgstr ""
@@ -1052,11 +870,6 @@ msgid "Audio Bus, Drag and Drop to rearrange."
msgstr ""
#: editor/editor_audio_buses.cpp
-#, fuzzy
-msgid "Bus options"
-msgstr "é¸é …"
-
-#: editor/editor_audio_buses.cpp
msgid "Solo"
msgstr ""
@@ -1068,6 +881,11 @@ msgstr ""
msgid "Bypass"
msgstr ""
+#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Bus options"
+msgstr "é¸é …"
+
#: editor/editor_audio_buses.cpp editor/plugins/tile_map_editor_plugin.cpp
#: editor/scene_tree_dock.cpp
msgid "Duplicate"
@@ -1075,6 +893,11 @@ msgstr "複製"
#: editor/editor_audio_buses.cpp
#, fuzzy
+msgid "Reset Volume"
+msgstr "é‡è¨­ç¸®æ”¾æ¯”例"
+
+#: editor/editor_audio_buses.cpp
+#, fuzzy
msgid "Delete Effect"
msgstr "刪除é¸ä¸­æª”案"
@@ -1098,6 +921,11 @@ msgstr "複製"
#: editor/editor_audio_buses.cpp
#, fuzzy
+msgid "Reset Bus Volume"
+msgstr "é‡è¨­ç¸®æ”¾æ¯”例"
+
+#: editor/editor_audio_buses.cpp
+#, fuzzy
msgid "Move Audio Bus"
msgstr "移動"
@@ -1129,7 +957,8 @@ msgstr ""
msgid "Create a new Bus Layout."
msgstr ""
-#: editor/editor_audio_buses.cpp editor/script_create_dialog.cpp
+#: editor/editor_audio_buses.cpp editor/property_editor.cpp
+#: editor/script_create_dialog.cpp
msgid "Load"
msgstr ""
@@ -1233,7 +1062,7 @@ msgid "Rearrange Autoloads"
msgstr "é‡æ–°æŽ’例Autoloads"
#: editor/editor_autoload_settings.cpp editor/editor_file_dialog.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp scene/gui/file_dialog.cpp
+#: scene/gui/file_dialog.cpp
msgid "Path:"
msgstr "路徑:"
@@ -1241,9 +1070,7 @@ msgstr "路徑:"
msgid "Node Name:"
msgstr ""
-#: editor/editor_autoload_settings.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp editor/project_manager.cpp
+#: editor/editor_autoload_settings.cpp editor/project_manager.cpp
msgid "Name"
msgstr "å稱"
@@ -1277,18 +1104,19 @@ msgid "Choose a Directory"
msgstr "é¸æ“‡è³‡æ–™å¤¾"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Create Folder"
msgstr "新增資料夾"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: editor/editor_plugin_settings.cpp editor/plugins/theme_editor_plugin.cpp
-#: editor/project_export.cpp scene/gui/file_dialog.cpp
+#: editor/editor_plugin_settings.cpp editor/filesystem_dock.cpp
+#: editor/plugins/theme_editor_plugin.cpp editor/project_export.cpp
+#: scene/gui/file_dialog.cpp
msgid "Name:"
msgstr "å稱:"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Could not create folder."
msgstr "無法新增資料夾"
@@ -1308,30 +1136,6 @@ msgstr ""
msgid "Template file not found:\n"
msgstr ""
-#: editor/editor_export.cpp
-msgid "Added:"
-msgstr "已加入:"
-
-#: editor/editor_export.cpp
-msgid "Removed:"
-msgstr "已移除:"
-
-#: editor/editor_export.cpp
-msgid "Error saving atlas:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Could not save atlas subtexture:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Exporting for %s"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Setting Up.."
-msgstr ""
-
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "File Exists, Overwrite?"
msgstr "檔案已存在, è¦è¦†è“‹å—Ž?"
@@ -1417,6 +1221,11 @@ msgstr "上移最愛"
msgid "Move Favorite Down"
msgstr "下移最愛"
+#: editor/editor_file_dialog.cpp
+#, fuzzy
+msgid "Go to parent folder"
+msgstr "無法新增資料夾"
+
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Directories & Files:"
msgstr "資料夾和檔案:"
@@ -1431,10 +1240,6 @@ msgid "File:"
msgstr "檔案:"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
-msgid "Filter:"
-msgstr "篩é¸:"
-
-#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Must use a valid extension."
msgstr "請用有效的副檔å"
@@ -1460,6 +1265,10 @@ msgstr ""
msgid "Search Classes"
msgstr ""
+#: editor/editor_help.cpp editor/plugins/spatial_editor_plugin.cpp
+msgid "Top"
+msgstr ""
+
#: editor/editor_help.cpp editor/property_editor.cpp
msgid "Class:"
msgstr ""
@@ -1476,15 +1285,28 @@ msgstr ""
msgid "Brief Description:"
msgstr ""
+#: editor/editor_help.cpp
+msgid "Members"
+msgstr ""
+
#: editor/editor_help.cpp modules/visual_script/visual_script_editor.cpp
msgid "Members:"
msgstr ""
#: editor/editor_help.cpp
+#, fuzzy
+msgid "Public Methods"
+msgstr "é¸æ“‡æ¨¡å¼"
+
+#: editor/editor_help.cpp
msgid "Public Methods:"
msgstr ""
#: editor/editor_help.cpp
+msgid "GUI Theme Items"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "GUI Theme Items:"
msgstr ""
@@ -1494,6 +1316,11 @@ msgstr "訊號:"
#: editor/editor_help.cpp
#, fuzzy
+msgid "Enumerations"
+msgstr "翻譯:"
+
+#: editor/editor_help.cpp
+#, fuzzy
msgid "Enumerations:"
msgstr "翻譯:"
@@ -1502,18 +1329,49 @@ msgid "enum "
msgstr ""
#: editor/editor_help.cpp
+#, fuzzy
+msgid "Constants"
+msgstr "常數"
+
+#: editor/editor_help.cpp
msgid "Constants:"
msgstr ""
#: editor/editor_help.cpp
+#, fuzzy
+msgid "Description"
+msgstr "æ述:"
+
+#: editor/editor_help.cpp
+msgid "Properties"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Property Description:"
msgstr ""
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this property. Please help us by "
+"[color=$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+
+#: editor/editor_help.cpp
+#, fuzzy
+msgid "Methods"
+msgstr "é¸æ“‡æ¨¡å¼"
+
+#: editor/editor_help.cpp
msgid "Method Description:"
msgstr ""
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this method. Please help us by [color="
+"$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Search Text"
msgstr ""
@@ -1522,25 +1380,22 @@ msgid "Output:"
msgstr ""
#: editor/editor_log.cpp editor/plugins/animation_tree_editor_plugin.cpp
-#: editor/plugins/rich_text_editor_plugin.cpp editor/property_editor.cpp
-#: editor/script_editor_debugger.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/property_editor.cpp editor/script_editor_debugger.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Clear"
msgstr "清空"
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
#, fuzzy
msgid "Error saving resource!"
msgstr "儲存資æºæ™‚出ç¾éŒ¯èª¤ï¼"
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Save Resource As.."
msgstr "把資æºå¦å­˜ç‚º..."
-#: editor/editor_node.cpp editor/export_template_manager.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "I see.."
msgstr "如來如此"
@@ -1559,6 +1414,29 @@ msgid "Error while saving."
msgstr "儲存時出ç¾éŒ¯èª¤"
#: editor/editor_node.cpp
+#, fuzzy
+msgid "Can't open '%s'."
+msgstr "ä¸èƒ½é€£æŽ¥ã€‚"
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Error while parsing '%s'."
+msgstr "儲存時出ç¾éŒ¯èª¤"
+
+#: editor/editor_node.cpp
+msgid "Unexpected end of file '%s'."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Missing '%s' or its dependencies."
+msgstr ""
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Error while loading '%s'."
+msgstr "儲存時出ç¾éŒ¯èª¤"
+
+#: editor/editor_node.cpp
msgid "Saving Scene"
msgstr "場景儲存中"
@@ -1619,6 +1497,33 @@ msgid "Restored default layout to base settings."
msgstr "é‡è¨­é è¨­ä½ˆå±€ã€‚"
#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was imported, so it's not editable.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was instanced or inherited.\n"
+"Changes to it will not be kept when saving the current scene."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource was imported, so it's not editable. Change its settings in the "
+"import panel and then re-import."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This scene was imported, so changes to it will not be kept.\n"
+"Instancing it or inheriting will allow making changes to it.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+
+#: editor/editor_node.cpp
#, fuzzy
msgid "Copy Params"
msgstr "複製åƒæ•¸"
@@ -1785,23 +1690,35 @@ msgid "Save changes the following scene(s) before opening Project Manager?"
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"This option is deprecated. Situations where refresh must be forced are now "
+"considered a bug. Please report."
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Pick a Main Scene"
msgstr "é¸æ“‡ä¸»å ´æ™¯"
#: editor/editor_node.cpp
-msgid "Unable to enable addon plugin at: '"
+msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr ""
#: editor/editor_node.cpp
-msgid "' parsing of config failed."
+msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/"
+#, fuzzy
+msgid "Unable to load addon script from path: '%s'."
+msgstr "載入字形出ç¾éŒ¯èª¤"
+
+#: editor/editor_node.cpp
+msgid ""
+"Unable to load addon script from path: '%s' Base type is not EditorPlugin."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to load addon script from path: '"
+msgid "Unable to load addon script from path: '%s' Script is not in tool mode."
msgstr ""
#: editor/editor_node.cpp
@@ -1811,7 +1728,7 @@ msgid ""
msgstr ""
#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/scene_tree_dock.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Ugh"
msgstr ""
@@ -1822,14 +1739,15 @@ msgid ""
msgstr ""
#: editor/editor_node.cpp
-msgid "Error loading scene."
-msgstr "載入場景時出ç¾éŒ¯èª¤"
-
-#: editor/editor_node.cpp
msgid "Scene '%s' has broken dependencies:"
msgstr ""
#: editor/editor_node.cpp
+#, fuzzy
+msgid "Clear Recent Scenes"
+msgstr "關閉場景"
+
+#: editor/editor_node.cpp
msgid "Save Layout"
msgstr "儲存佈局"
@@ -1862,7 +1780,7 @@ msgstr ""
msgid "Toggle distraction-free mode."
msgstr ""
-#: editor/editor_node.cpp editor/io_plugins/editor_scene_import_plugin.cpp
+#: editor/editor_node.cpp
msgid "Scene"
msgstr "場景"
@@ -2085,6 +2003,10 @@ msgstr ""
msgid "Issue Tracker"
msgstr ""
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+msgid "Community"
+msgstr "社群"
+
#: editor/editor_node.cpp
msgid "About"
msgstr "關於"
@@ -2093,7 +2015,7 @@ msgstr "關於"
msgid "Play the project."
msgstr "é‹è¡Œå°ˆæ¡ˆ"
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Play"
msgstr "é‹è¡Œ"
@@ -2109,7 +2031,7 @@ msgstr "æš«åœå ´æ™¯"
msgid "Stop the scene."
msgstr "åœæ­¢é‹è¡Œå ´æ™¯"
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Stop"
msgstr "åœæ­¢"
@@ -2182,6 +2104,15 @@ msgid "Object properties."
msgstr ""
#: editor/editor_node.cpp
+msgid "Changes may be lost!"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Import"
+msgstr "å°Žå…¥"
+
+#: editor/editor_node.cpp
msgid "FileSystem"
msgstr ""
@@ -2197,14 +2128,6 @@ msgstr ""
msgid "Don't Save"
msgstr ""
-#: editor/editor_node.cpp editor/editor_reimport_dialog.cpp
-msgid "Re-Import"
-msgstr ""
-
-#: editor/editor_node.cpp editor/editor_plugin_settings.cpp
-msgid "Update"
-msgstr "æ›´æ–°"
-
#: editor/editor_node.cpp
msgid "Import Templates From ZIP File"
msgstr ""
@@ -2269,11 +2192,28 @@ msgstr "è¦é›¢é–‹ç·¨è¼¯å™¨å—Ž?"
msgid "Open the previous Editor"
msgstr ""
+#: editor/editor_plugin.cpp
+msgid "Creating Mesh Previews"
+msgstr ""
+
+#: editor/editor_plugin.cpp
+msgid "Thumbnail.."
+msgstr ""
+
#: editor/editor_plugin_settings.cpp
msgid "Installed Plugins:"
msgstr ""
#: editor/editor_plugin_settings.cpp
+msgid "Update"
+msgstr "æ›´æ–°"
+
+#: editor/editor_plugin_settings.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Version:"
+msgstr "版本:"
+
+#: editor/editor_plugin_settings.cpp
msgid "Author:"
msgstr ""
@@ -2306,7 +2246,7 @@ msgid "Frame %"
msgstr ""
#: editor/editor_profiler.cpp
-msgid "Fixed Frame %"
+msgid "Physics Frame %"
msgstr ""
#: editor/editor_profiler.cpp editor/script_editor_debugger.cpp
@@ -2325,26 +2265,6 @@ msgstr ""
msgid "Frame #:"
msgstr ""
-#: editor/editor_reimport_dialog.cpp
-msgid "Please wait for scan to complete."
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Current scene must be saved to re-import."
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Save & Re-Import"
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Importing"
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Import Changed Resources"
-msgstr ""
-
#: editor/editor_run_native.cpp
msgid "Select device from the list"
msgstr ""
@@ -2454,10 +2374,6 @@ msgid "Importing:"
msgstr "導入中:"
#: editor/export_template_manager.cpp
-msgid "Loading Export Templates"
-msgstr ""
-
-#: editor/export_template_manager.cpp
msgid "Current Version:"
msgstr ""
@@ -2493,9 +2409,17 @@ msgid "Cannot navigate to '"
msgstr ""
#: editor/filesystem_dock.cpp
+msgid "View items as a grid of thumbnails"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "View items as a list"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
msgid ""
"\n"
-"Status: Needs Re-Import"
+"Status: Import of file failed. Please fix file and reimport manually."
msgstr ""
#: editor/filesystem_dock.cpp
@@ -2506,45 +2430,50 @@ msgid ""
msgstr "來æº:"
#: editor/filesystem_dock.cpp
-msgid "Same source and destination files, doing nothing."
+msgid "Cannot move/rename resources root."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Target file exists, can't overwrite. Delete first."
+msgid "Cannot move a folder into itself.\n"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Same source and destination paths, doing nothing."
+#, fuzzy
+msgid "Error moving:\n"
+msgstr "載入錯誤:"
+
+#: editor/filesystem_dock.cpp
+msgid "Unable to update dependencies:\n"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Can't move directories to within themselves."
+msgid "No name provided"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Can't rename deps for:\n"
+msgid "Provided name contains invalid characters"
msgstr ""
#: editor/filesystem_dock.cpp
-#, fuzzy
-msgid "Error moving file:\n"
-msgstr "儲存TileSet時出ç¾éŒ¯èª¤ï¼"
+msgid "No name provided."
+msgstr ""
#: editor/filesystem_dock.cpp
#, fuzzy
-msgid "Error moving dir:\n"
-msgstr "載入錯誤:"
+msgid "Name contains invalid characters."
+msgstr "有效字符:"
#: editor/filesystem_dock.cpp
-msgid "Can't operate on '..'"
+msgid "A file or folder with this name already exists."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Pick New Name and Location For:"
-msgstr ""
+#, fuzzy
+msgid "Renaming file:"
+msgstr "儲存TileSet時出ç¾éŒ¯èª¤ï¼"
#: editor/filesystem_dock.cpp
-msgid "No files selected!"
+msgid "Renaming folder:"
msgstr ""
#: editor/filesystem_dock.cpp
@@ -2556,39 +2485,36 @@ msgid "Collapse all"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Show In File Manager"
-msgstr ""
-
-#: editor/filesystem_dock.cpp
-msgid "Instance"
-msgstr ""
+msgid "Copy Path"
+msgstr "複製路徑"
#: editor/filesystem_dock.cpp
-msgid "Edit Dependencies.."
+msgid "Rename.."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "View Owners.."
+msgid "Move To.."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Copy Path"
-msgstr "複製路徑"
+#, fuzzy
+msgid "New Folder.."
+msgstr "新增資料夾"
#: editor/filesystem_dock.cpp
-msgid "Rename or Move.."
+msgid "Show In File Manager"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Move To.."
+msgid "Instance"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Info"
+msgid "Edit Dependencies.."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Re-Import.."
+msgid "View Owners.."
msgstr ""
#: editor/filesystem_dock.cpp
@@ -2621,6 +2547,11 @@ msgstr ""
msgid "Move"
msgstr ""
+#: editor/filesystem_dock.cpp editor/plugins/animation_tree_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Rename"
+msgstr ""
+
#: editor/groups_editor.cpp
msgid "Add to Group"
msgstr ""
@@ -2635,6 +2566,10 @@ msgid "Import as Single Scene"
msgstr "更新場景"
#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
msgid "Import with Separate Materials"
msgstr ""
@@ -2647,6 +2582,18 @@ msgid "Import with Separate Objects+Materials"
msgstr ""
#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Materials+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Materials+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
msgid "Import as Multiple Scenes"
msgstr ""
@@ -2655,38 +2602,31 @@ msgid "Import as Multiple Scenes+Materials"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Import Scene"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Importing Scene.."
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Running Custom Script.."
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Couldn't load post-import script:"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Invalid/broken script for post-import (check console):"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Error running post-import script:"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Saving.."
msgstr ""
@@ -2717,579 +2657,54 @@ msgstr ""
msgid "Reimport"
msgstr "å°Žå…¥"
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "No bit masks to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path is empty."
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must be a complete resource path."
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must exist."
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Save path is empty!"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Import BitMasks"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s):"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Target Path:"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Accept"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Bit Mask"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No source font file!"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No target font resource!"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"Invalid file extension.\n"
-"Please use .font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Can't load/process source font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Couldn't save font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font Size:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Dest Resource:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "The quick brown fox jumps over the lazy dog."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Test:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Options:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Font Import"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"This file is already a Godot font file, please supply a BMFont type file "
-"instead."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Failed opening as BMFont file."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error initializing FreeType."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Unknown font format."
-msgstr "字形格å¼ä¸æ˜Ž"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error loading font."
-msgstr "載入字形出ç¾éŒ¯èª¤"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Invalid font size."
-msgstr "無效字型"
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Invalid font custom source."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/plugins/theme_editor_plugin.cpp
-msgid "Font"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "No meshes to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Single Mesh Import"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Source Mesh(es):"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/plugins/mesh_instance_editor_plugin.cpp
-msgid "Mesh"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Surface %d"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "No samples to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Import Audio Samples"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Source Sample(s):"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Audio Sample"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "New Clip"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Animation Options"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Flags"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Bake FPS:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Optimizer"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Linear Error"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angular Error"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angle"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Clips"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Start(s)"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "End(s)"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Loop"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Filters"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source path is empty."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't load post-import script."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Invalid/broken script for post-import."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Error importing scene."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import 3D Scene"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source Scene:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Same as Target Scene"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Shared"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Target Texture Folder:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Post-Process Script:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Custom Root Node Type:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Auto"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Root Node Name:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "The Following Files are Missing:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Anyway"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp scene/gui/dialogs.cpp
-msgid "Cancel"
-msgstr "å–消"
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import & Open"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Edited scene has not been saved, open imported scene anyway?"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Image:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Can't import a file over itself:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't localize path: %s (already local)"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "3D Scene Animation"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Uncompressed"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossless (PNG)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossy (WebP)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress (VRAM)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Format"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Compression Quality (WebP):"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Options"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Please specify some files!"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "At least one file needed for Atlas."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Error importing:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Only one file is required for large texture."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Max Texture Size:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for Atlas (2D)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cell Size:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Large Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Textures (2D)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture"
+#: editor/multi_node_edit.cpp
+msgid "MultiNode Set"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Base Atlas Texture"
+#: editor/node_dock.cpp
+msgid "Groups"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s)"
+#: editor/node_dock.cpp
+msgid "Select a Node to edit Signals and Groups."
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 2D"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create Poly"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 3D"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Insert Point"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "2D Texture"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly (Remove Point)"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "3D Texture"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Remove Poly And Point"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Atlas Texture"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create a new polygon from scratch."
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
+#: editor/plugins/abstract_polygon_2d_editor.cpp
msgid ""
-"NOTICE: Importing 2D textures is not mandatory. Just copy png/jpg files to "
-"the project."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Crop empty space."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Load Source Image"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Slicing"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Inserting"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Saving"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save large texture:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Build Atlas For:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Loading Image:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't load image:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Converting Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cropping Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Blitting Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save atlas image:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save converted texture:"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid source!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid translation source!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Column"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/script_create_dialog.cpp
-msgid "Language"
-msgstr "語言"
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No items to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No target path!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translations"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Couldn't import!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translation"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Source CSV:"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Ignore First Row"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Compress"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Add to Project (project.godot)"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Languages:"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Translation"
-msgstr ""
-
-#: editor/multi_node_edit.cpp
-msgid "MultiNode Set"
-msgstr ""
-
-#: editor/node_dock.cpp
-msgid "Groups"
-msgstr ""
-
-#: editor/node_dock.cpp
-msgid "Select a Node to edit Signals and Groups."
+"Edit existing polygon:\n"
+"LMB: Move Point.\n"
+"Ctrl+LMB: Split Segment.\n"
+"RMB: Erase Point."
msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
@@ -3445,7 +2860,6 @@ msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
#: editor/script_create_dialog.cpp
msgid "Error!"
@@ -3556,10 +2970,6 @@ msgid "Delete Input"
msgstr ""
#: editor/plugins/animation_tree_editor_plugin.cpp
-msgid "Rename"
-msgstr ""
-
-#: editor/plugins/animation_tree_editor_plugin.cpp
msgid "Animation tree is valid."
msgstr ""
@@ -3615,64 +3025,185 @@ msgstr ""
msgid "Filters.."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing %d Triangles:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Free"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Triangle #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Contents:"
+msgstr "內容:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "View Files"
+msgstr "檔案"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve hostname:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Light Baker Setup:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing Geometry"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connection error, please try again."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Fixing Lights"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't connect."
+msgstr "ä¸èƒ½é€£æŽ¥ã€‚"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't connect to host:"
+msgstr "ä¸èƒ½é€£åˆ°ä¸»æ©Ÿï¼š"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response from host:"
+msgstr "主機沒有回應:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response."
+msgstr "沒有回應。"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Request failed, return code:"
+msgstr "請求失敗,"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Req. Failed."
+msgstr "請求失敗。"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, too many redirects"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Making BVH"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Redirect Loop."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Light Octree"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed:"
+msgstr "失敗:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Bad download hash, assuming file has been tampered with."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Octree Texture"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Expected:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Transfer to Lightmaps:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Got:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Allocating Texture #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed sha256 hash check"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Baking Triangle #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Asset Download Error:"
+msgstr "Asset下載出ç¾éŒ¯èª¤ï¼š"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Fetching:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Post-Processing Texture #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Resolving.."
msgstr ""
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Bake!"
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Connecting.."
+msgstr "連到..."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Requesting.."
+msgstr "請求中..."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Error making request"
+msgstr "請求時出ç¾éŒ¯èª¤"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Idle"
msgstr ""
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Reset the lightmap octree baking process (start over)."
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Retry"
+msgstr "é‡è©¦"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download Error"
+msgstr "下載出ç¾éŒ¯èª¤"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download for this asset is already in progress!"
+msgstr "Asset已在下載中"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "first"
+msgstr "首é "
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "prev"
+msgstr "上一é "
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "next"
+msgstr "下一é "
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "last"
+msgstr "å°¾é "
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "All"
+msgstr "全部"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Plugins"
+msgstr "æ’件"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Sort:"
+msgstr "排åºï¼š"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Reverse"
msgstr ""
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Category:"
+msgstr "分類:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Site:"
+msgstr "地å€:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Support.."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Official"
+msgstr "官方"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Testing"
+msgstr "測試"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Assets ZIP File"
+msgstr "Assets ZIP 檔"
+
#: editor/plugins/camera_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
msgid "Preview"
msgstr ""
@@ -3715,11 +3246,15 @@ msgid "Edit CanvasItem"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Change Anchors"
+msgid "Anchors only"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom (%):"
+msgid "Change Anchors and Margins"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Change Anchors"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3770,59 +3305,72 @@ msgid "Pan Mode"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Lock the selected object in place (can't be moved)."
+msgid "Toggles snapping"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Unlock the selected object (can be moved)."
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Use Snap"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Makes sure the object's children are not selectable."
+msgid "Snapping options"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Restores the object's children's ability to be selected."
+msgid "Snap to grid"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Edit"
-msgstr "編輯"
+msgid "Use Rotation Snap"
+msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Use Snap"
+msgid "Configure Snap..."
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Show Grid"
+msgid "Snap Relative"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Rotation Snap"
+msgid "Use Pixel Snap"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap Relative"
+msgid "Smart snapping"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Configure Snap.."
+msgid "Snap to parent"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Pixel Snap"
+msgid "Snap to node anchor"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Skeleton.."
+msgid "Snap to node sides"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to other nodes"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Lock the selected object in place (can't be moved)."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Unlock the selected object (can be moved)."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Makes sure the object's children are not selectable."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Restores the object's children's ability to be selected."
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3851,11 +3399,16 @@ msgid "View"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Reset"
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Show Grid"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Set.."
+msgid "Show helpers"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Show rulers"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3867,8 +3420,9 @@ msgid "Frame Selection"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Anchor"
-msgstr ""
+#, fuzzy
+msgid "Layout"
+msgstr "儲存佈局"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Insert Keys"
@@ -3891,11 +3445,20 @@ msgid "Clear Pose"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Set a Value"
+msgid "Drag pivot from mouse position"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap (Pixels):"
+#, fuzzy
+msgid "Set pivot at mouse position"
+msgstr "åªé™é¸ä¸­"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Multiply grid step by 2"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Divide grid step by 2"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3906,23 +3469,28 @@ msgstr ""
msgid "Adding %s..."
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Create Node"
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Error instancing scene from %s"
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "OK :("
msgstr "OK :("
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "No parent to instance a child at."
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "This operation requires a single selected node."
msgstr ""
@@ -3936,45 +3504,6 @@ msgid ""
"Drag & drop + Alt : Change node type"
msgstr ""
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Create Poly"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly (Remove Point)"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Create a new polygon from scratch."
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-msgid ""
-"Edit existing polygon:\n"
-"LMB: Move Point.\n"
-"Ctrl+LMB: Split Segment.\n"
-"RMB: Erase Point."
-msgstr ""
-
#: editor/plugins/collision_polygon_editor_plugin.cpp
msgid "Create Poly3D"
msgstr ""
@@ -3984,14 +3513,6 @@ msgid "Set Handle"
msgstr ""
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Creating Mesh Library"
-msgstr ""
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Thumbnail.."
-msgstr ""
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Remove item %d?"
msgstr ""
@@ -4014,6 +3535,27 @@ msgid "Update from Scene"
msgstr ""
#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat0"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat1"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+#, fuzzy
+msgid "Ease in"
+msgstr "縮放selection"
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Ease out"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Smoothstep"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
msgid "Modify Curve Point"
msgstr ""
@@ -4093,22 +3635,18 @@ msgid "Create Occluder Polygon"
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Edit existing polygon:"
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "LMB: Move Point."
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Ctrl+LMB: Split Segment."
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "RMB: Erase Point."
msgstr ""
@@ -4209,6 +3747,10 @@ msgid "Create Outline"
msgstr ""
#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Mesh"
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Create Trimesh Static Body"
msgstr ""
@@ -4336,12 +3878,73 @@ msgstr ""
msgid "Populate"
msgstr ""
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Create Navigation Polygon"
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake!"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake the navigation mesh.\n"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Clear the navigation mesh."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Setting up Configuration..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Calculating grid size..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating heightfield..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Marking walkable triangles..."
+msgstr "儲存本地更改.."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Constructing compact heightfield..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Eroding walkable area..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Partitioning..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating contours..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating polymesh..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Converting to native navigation mesh..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Navigation Mesh Generator Setup:"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Parsing Geometry..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Done!"
msgstr ""
#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Remove Poly And Point"
+msgid "Create Navigation Polygon"
msgstr ""
#: editor/plugins/particles_2d_editor_plugin.cpp
@@ -4515,16 +4118,19 @@ msgid "Curve Point #"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve Point Position"
-msgstr ""
+msgstr "åªé™é¸ä¸­"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve In Position"
-msgstr ""
+msgstr "åªé™é¸ä¸­"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve Out Position"
-msgstr ""
+msgstr "åªé™é¸ä¸­"
#: editor/plugins/path_editor_plugin.cpp
msgid "Split Path"
@@ -4584,6 +4190,14 @@ msgid "Scale Polygon"
msgstr ""
#: editor/plugins/polygon_2d_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Edit"
+msgstr "編輯"
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Polygon->UV"
msgstr ""
@@ -4638,63 +4252,10 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/shader_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr "貼上"
-#: editor/plugins/rich_text_editor_plugin.cpp
-msgid "Parse BBCode"
-msgstr ""
-
-#: editor/plugins/sample_editor_plugin.cpp
-msgid "Length:"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Open Sample File(s)"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "ERROR: Couldn't load sample!"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Add Sample"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Rename Sample"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Delete Sample"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "16 Bits"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "8 Bits"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Stereo"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Mono"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Format"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Pitch"
-msgstr ""
-
#: editor/plugins/script_editor_plugin.cpp
msgid "Clear Recent Files"
msgstr ""
@@ -4787,6 +4348,10 @@ msgstr "關閉場景"
msgid "Close All"
msgstr "關閉"
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+msgid "Run"
+msgstr "é‹è¡Œ"
+
#: editor/plugins/script_editor_plugin.cpp
msgid "Toggle Scripts Panel"
msgstr ""
@@ -4815,7 +4380,8 @@ msgstr ""
msgid "Break"
msgstr ""
-#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+#: editor/script_editor_debugger.cpp
msgid "Continue"
msgstr ""
@@ -4829,18 +4395,6 @@ msgid "Debug with external editor"
msgstr "è¦é›¢é–‹ç·¨è¼¯å™¨å—Ž?"
#: editor/plugins/script_editor_plugin.cpp
-msgid "Window"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Left"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Right"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
msgid "Open Godot online documentation"
msgstr ""
@@ -4924,8 +4478,9 @@ msgid "Cut"
msgstr "剪下"
#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr "複製"
@@ -5191,10 +4746,6 @@ msgid "View Plane Transform."
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Scaling to %s%%."
-msgstr ""
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rotating %s degrees."
msgstr ""
@@ -5211,10 +4762,6 @@ msgid "Top View."
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Top"
-msgstr ""
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rear View."
msgstr ""
@@ -5451,6 +4998,10 @@ msgid "Transform"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Configure Snap.."
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Local Coords"
msgstr ""
@@ -5596,6 +5147,10 @@ msgid "Speed (FPS):"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Loop"
+msgstr ""
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Animation Frames"
msgstr ""
@@ -5608,11 +5163,12 @@ msgid "Insert Empty (After)"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Up"
-msgstr ""
+#, fuzzy
+msgid "Move (Before)"
+msgstr "移動模å¼"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Down"
+msgid "Move (After)"
msgstr ""
#: editor/plugins/style_box_editor_plugin.cpp
@@ -5691,7 +5247,11 @@ msgid "Remove All"
msgstr "移除"
#: editor/plugins/theme_editor_plugin.cpp
-msgid "Theme"
+msgid "Edit theme.."
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Theme editing menu."
msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
@@ -5776,6 +5336,10 @@ msgid "Style"
msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
+msgid "Font"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
msgid "Color"
msgstr ""
@@ -5826,7 +5390,7 @@ msgid "Mirror Y"
msgstr ""
#: editor/plugins/tile_map_editor_plugin.cpp
-msgid "Bucket"
+msgid "Paint Tile"
msgstr ""
#: editor/plugins/tile_map_editor_plugin.cpp
@@ -5893,6 +5457,10 @@ msgid "Delete preset '%s'?"
msgstr "è¦åˆªé™¤é¸ä¸­æª”案?"
#: editor/project_export.cpp
+msgid "Export templates for this platform are missing/corrupted: "
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Presets"
msgstr ""
@@ -5966,19 +5534,30 @@ msgid "Export templates for this platform are missing:"
msgstr ""
#: editor/project_export.cpp
+msgid "Export templates for this platform are missing/corrupted:"
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Export With Debug"
msgstr ""
#: editor/project_manager.cpp
-msgid "Invalid project path, the path must exist!"
+#, fuzzy
+msgid "The path does not exist."
+msgstr "檔案ä¸å­˜åœ¨."
+
+#: editor/project_manager.cpp
+msgid "Please choose a 'project.godot' file."
msgstr ""
#: editor/project_manager.cpp
-msgid "Invalid project path, project.godot must not exist."
+msgid ""
+"Your project will be created in a non empty folder (you might want to create "
+"a new folder)."
msgstr ""
#: editor/project_manager.cpp
-msgid "Invalid project path, project.godot must exist."
+msgid "Please choose a folder that does not contain a 'project.godot' file."
msgstr ""
#: editor/project_manager.cpp
@@ -5986,10 +5565,26 @@ msgid "Imported Project"
msgstr ""
#: editor/project_manager.cpp
+msgid " "
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "It would be a good idea to name your project."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Invalid project path (changed anything?)."
msgstr ""
#: editor/project_manager.cpp
+msgid "Couldn't get project.godot in project path."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Couldn't edit project.godot in project path."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
msgstr ""
@@ -5998,15 +5593,20 @@ msgid "The following files failed extraction from package:"
msgstr ""
#: editor/project_manager.cpp
-msgid "Import Existing Project"
+#, fuzzy
+msgid "Rename Project"
+msgstr "專案"
+
+#: editor/project_manager.cpp
+msgid "Couldn't get project.godot in the project path."
msgstr ""
#: editor/project_manager.cpp
-msgid "Project Path (Must Exist):"
+msgid "New Game Project"
msgstr ""
#: editor/project_manager.cpp
-msgid "Project Name:"
+msgid "Import Existing Project"
msgstr ""
#: editor/project_manager.cpp
@@ -6014,22 +5614,27 @@ msgid "Create New Project"
msgstr ""
#: editor/project_manager.cpp
-msgid "Project Path:"
+msgid "Install Project:"
msgstr ""
#: editor/project_manager.cpp
-msgid "Install Project:"
+msgid "Project Name:"
msgstr ""
#: editor/project_manager.cpp
-msgid "Browse"
-msgstr "ç€è¦½"
+#, fuzzy
+msgid "Create folder"
+msgstr "新增資料夾"
#: editor/project_manager.cpp
-msgid "New Game Project"
+msgid "Project Path:"
msgstr ""
#: editor/project_manager.cpp
+msgid "Browse"
+msgstr "ç€è¦½"
+
+#: editor/project_manager.cpp
msgid "That's a BINGO!"
msgstr ""
@@ -6038,6 +5643,11 @@ msgid "Unnamed Project"
msgstr ""
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Can't open project"
+msgstr "ä¸èƒ½é€£æŽ¥ã€‚"
+
+#: editor/project_manager.cpp
msgid "Are you sure to open more than one project?"
msgstr ""
@@ -6064,6 +5674,12 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
+"Language changed.\n"
+"The UI will update next time the editor or project manager starts."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid ""
"You are about the scan %s folders for existing Godot projects. Do you "
"confirm?"
msgstr ""
@@ -6073,10 +5689,6 @@ msgid "Project List"
msgstr ""
#: editor/project_manager.cpp
-msgid "Run"
-msgstr "é‹è¡Œ"
-
-#: editor/project_manager.cpp
msgid "Scan"
msgstr ""
@@ -6098,6 +5710,10 @@ msgid "Exit"
msgstr "離開"
#: editor/project_manager.cpp
+msgid "Restart Now"
+msgstr ""
+
+#: editor/project_manager.cpp
#, fuzzy
msgid "Can't run project"
msgstr "ä¸èƒ½é€£æŽ¥ã€‚"
@@ -6135,17 +5751,14 @@ msgid "Add Input Action Event"
msgstr ""
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Meta+"
msgstr "Meta+"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Shift+"
msgstr "Shift+"
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Alt+"
msgstr "Alt+"
@@ -6207,7 +5820,7 @@ msgstr "當改變時更新"
msgid "Joypad Axis Index:"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
#, fuzzy
msgid "Axis"
msgstr "中軸"
@@ -6228,31 +5841,31 @@ msgstr ""
msgid "Add Event"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Device"
msgstr "設備"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Button"
msgstr "按éµ"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Left Button."
msgstr "左𨫡"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Right Button."
msgstr "å³ð¨«¡"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Middle Button."
msgstr "中𨫡"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Up."
msgstr "上滾"
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Down."
msgstr "下滾"
@@ -6261,7 +5874,7 @@ msgid "Add Global Property"
msgstr ""
#: editor/project_settings_editor.cpp
-msgid "Select an setting item first!"
+msgid "Select a setting item first!"
msgstr ""
#: editor/project_settings_editor.cpp
@@ -6279,6 +5892,15 @@ msgid "Delete Item"
msgstr "刪除"
#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Can't contain '/' or ':'"
+msgstr "ä¸èƒ½é€£åˆ°ä¸»æ©Ÿï¼š"
+
+#: editor/project_settings_editor.cpp
+msgid "Already existing"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "Error saving settings."
msgstr ""
@@ -6319,6 +5941,14 @@ msgid "Remove Resource Remap Option"
msgstr ""
#: editor/project_settings_editor.cpp
+msgid "Changed Locale Filter"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Changed Locale Filter Mode"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "Project Settings (project.godot)"
msgstr ""
@@ -6379,6 +6009,27 @@ msgid "Locale"
msgstr ""
#: editor/project_settings_editor.cpp
+msgid "Locales Filter"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Show all locales"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Show only selected locales"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Filter mode:"
+msgstr "篩é¸:"
+
+#: editor/project_settings_editor.cpp
+msgid "Locales:"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "AutoLoad"
msgstr ""
@@ -6429,10 +6080,19 @@ msgid "New Script"
msgstr "下一個腳本"
#: editor/property_editor.cpp
+msgid "Make Unique"
+msgstr ""
+
+#: editor/property_editor.cpp
msgid "Show in File System"
msgstr ""
#: editor/property_editor.cpp
+#, fuzzy
+msgid "Convert To %s"
+msgstr "轉為..."
+
+#: editor/property_editor.cpp
msgid "Error loading file: Not a resource!"
msgstr ""
@@ -6472,6 +6132,11 @@ msgstr "é¸æ“‡æ¨¡å¼"
#: editor/property_selector.cpp
#, fuzzy
+msgid "Select Virtual Method"
+msgstr "é¸æ“‡æ¨¡å¼"
+
+#: editor/property_selector.cpp
+#, fuzzy
msgid "Select Method"
msgstr "é¸æ“‡æ¨¡å¼"
@@ -6499,26 +6164,6 @@ msgstr ""
msgid "Reparent"
msgstr ""
-#: editor/resources_dock.cpp
-msgid "Create New Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Open Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Save Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Resource Tools"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Make Local"
-msgstr ""
-
#: editor/run_settings_dialog.cpp
msgid "Run Mode:"
msgstr ""
@@ -6646,14 +6291,6 @@ msgid "Sub-Resources:"
msgstr "資æº"
#: editor/scene_tree_dock.cpp
-msgid "Edit Groups"
-msgstr ""
-
-#: editor/scene_tree_dock.cpp
-msgid "Edit Connections"
-msgstr ""
-
-#: editor/scene_tree_dock.cpp
msgid "Clear Inheritance"
msgstr ""
@@ -6842,6 +6479,15 @@ msgid "Invalid base path"
msgstr ""
#: editor/script_create_dialog.cpp
+msgid "Directory of the same name exists"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
+#, fuzzy
+msgid "File exists, will be reused"
+msgstr "檔案已存在, è¦è¦†è“‹å—Ž?"
+
+#: editor/script_create_dialog.cpp
msgid "Invalid extension"
msgstr "無效副檔å"
@@ -6886,6 +6532,10 @@ msgid "Load existing script file"
msgstr "下一個腳本"
#: editor/script_create_dialog.cpp
+msgid "Language"
+msgstr "語言"
+
+#: editor/script_create_dialog.cpp
msgid "Inherits"
msgstr ""
@@ -6929,6 +6579,10 @@ msgid "Function:"
msgstr ""
#: editor/script_editor_debugger.cpp
+msgid "Pick one or more items from the list to display the graph."
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
msgid "Errors"
msgstr "錯誤"
@@ -7010,6 +6664,10 @@ msgid "Type"
msgstr ""
#: editor/script_editor_debugger.cpp
+msgid "Format"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
msgid "Usage"
msgstr ""
@@ -7085,12 +6743,29 @@ msgstr ""
msgid "Change Probe Extents"
msgstr ""
+#: modules/gdnative/gd_native_library_editor.cpp
+#, fuzzy
+msgid "Library"
+msgstr "MeshLibrary.."
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Status"
+msgstr ""
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Libraries: "
+msgstr ""
+
+#: modules/gdnative/register_types.cpp
+msgid "GDNative"
+msgstr ""
+
#: modules/gdscript/gd_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Invalid type argument to convert(), use TYPE_* constants."
msgstr ""
-#: modules/gdscript/gd_functions.cpp
+#: modules/gdscript/gd_functions.cpp modules/mono/glue/glue_header.h
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Not enough bytes for decoding bytes, or invalid format."
msgstr ""
@@ -7142,10 +6817,6 @@ msgid "GridMap Duplicate Selection"
msgstr "複製 Selection"
#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "GridMap Paint"
-msgstr ""
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Snap View"
msgstr ""
@@ -7242,13 +6913,8 @@ msgstr "設定"
msgid "Pick Distance:"
msgstr ""
-#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
-msgid "Tiles"
-msgstr "檔案"
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "Areas"
+#: modules/mono/editor/mono_bottom_panel.cpp
+msgid "Builds"
msgstr ""
#: modules/visual_script/visual_script.cpp
@@ -7445,10 +7111,18 @@ msgid "Return"
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
+msgid "Call"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
msgid "Get"
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
+msgid "Script already has function '%s'"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
#, fuzzy
msgid "Change Input Value"
msgstr "動畫變化數值"
@@ -7814,6 +7488,12 @@ msgid ""
"order for AnimatedSprite3D to display frames."
msgstr ""
+#: scene/3d/vehicle_body.cpp
+msgid ""
+"VehicleWheel serves to provide a wheel system to a VehicleBody. Please use "
+"it as a child of a VehicleBody."
+msgstr ""
+
#: scene/gui/color_picker.cpp
msgid "Raw Mode"
msgstr ""
@@ -7823,6 +7503,10 @@ msgid "Add current color as a preset"
msgstr ""
#: scene/gui/dialogs.cpp
+msgid "Cancel"
+msgstr "å–消"
+
+#: scene/gui/dialogs.cpp
msgid "Alert!"
msgstr "警告!"
@@ -7830,10 +7514,6 @@ msgstr "警告!"
msgid "Please Confirm..."
msgstr "請確èª..."
-#: scene/gui/input_action.cpp
-msgid "Ctrl+"
-msgstr "Ctrl+"
-
#: scene/gui/popup.cpp
msgid ""
"Popups will hide by default unless you call popup() or any of the popup*() "
@@ -7862,6 +7542,41 @@ msgid ""
"texture to some node for display."
msgstr ""
+#: scene/resources/dynamic_font.cpp
+msgid "Error initializing FreeType."
+msgstr ""
+
+#: scene/resources/dynamic_font.cpp
+msgid "Unknown font format."
+msgstr "字形格å¼ä¸æ˜Ž"
+
+#: scene/resources/dynamic_font.cpp
+msgid "Error loading font."
+msgstr "載入字形出ç¾éŒ¯èª¤"
+
+#: scene/resources/dynamic_font.cpp
+msgid "Invalid font size."
+msgstr "無效字型"
+
+#~ msgid "Filter:"
+#~ msgstr "篩é¸:"
+
+#~ msgid "Added:"
+#~ msgstr "已加入:"
+
+#~ msgid "Removed:"
+#~ msgstr "已移除:"
+
+#~ msgid "Error loading scene."
+#~ msgstr "載入場景時出ç¾éŒ¯èª¤"
+
+#, fuzzy
+#~ msgid "Tiles"
+#~ msgstr "檔案"
+
+#~ msgid "Ctrl+"
+#~ msgstr "Ctrl+"
+
#~ msgid "Close scene? (Unsaved changes will be lost)"
#~ msgstr "è¦é—œé–‰å ´æ™¯å—Žï¼Ÿï¼ˆæœªå„²å­˜çš„更改將會消失)"
diff --git a/editor/translations/zh_TW.po b/editor/translations/zh_TW.po
index f845efea17..7a392613d2 100644
--- a/editor/translations/zh_TW.po
+++ b/editor/translations/zh_TW.po
@@ -1,5 +1,6 @@
# Chinese (Taiwan) translation of the Godot Engine editor
-# Copyright (C) 2016-2017 Juan Linietsky, Ariel Manzur and the Godot community
+# Copyright (C) 2007-2017 Juan Linietsky, Ariel Manzur
+# Copyright (C) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)
# This file is distributed under the same license as the Godot source code.
#
# Allen H <w84miracle@gmail.com>, 2017.
@@ -194,10 +195,9 @@ msgid "Create %d NEW tracks and insert keys?"
msgstr ""
#: editor/animation_editor.cpp editor/create_dialog.cpp
-#: editor/editor_audio_buses.cpp
+#: editor/editor_audio_buses.cpp editor/plugins/abstract_polygon_2d_editor.cpp
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
#: editor/plugins/mesh_instance_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp editor/project_manager.cpp
#: editor/script_create_dialog.cpp
msgid "Create"
@@ -359,265 +359,6 @@ msgstr ""
msgid "Change Array Value"
msgstr ""
-#: editor/asset_library_editor_plugin.cpp
-msgid "Free"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_plugin_settings.cpp
-msgid "Version:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Contents:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "View Files"
-msgstr "éŽæ¿¾æª”案.."
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_help.cpp editor/property_selector.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Description:"
-msgstr "æè¿°:"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-#: editor/project_manager.cpp
-msgid "Install"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/call_dialog.cpp
-#: editor/connections_dialog.cpp editor/export_template_manager.cpp
-#: editor/plugins/animation_player_editor_plugin.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-#: editor/project_settings_editor.cpp editor/property_editor.cpp
-#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Close"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve hostname:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't resolve."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Connection error, please try again."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Can't connect."
-msgstr "連接..."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Can't connect to host:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response from host:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "No response."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Request failed, return code:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Req. Failed."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Request failed, too many redirects"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Redirect Loop."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Bad download hash, assuming file has been tampered with."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Expected:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Got:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Failed sha256 hash check"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Asset Download Error:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_asset_installer.cpp
-msgid "Success!"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Fetching:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Resolving.."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Connecting.."
-msgstr "連接..."
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Requesting.."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-#, fuzzy
-msgid "Error making request"
-msgstr "載入場景時發生錯誤"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Idle"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Retry"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Download Error"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Download for this asset is already in progress!"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "first"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "prev"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "next"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "last"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "All"
-msgstr "全部"
-
-#: editor/asset_library_editor_plugin.cpp editor/create_dialog.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
-#: editor/settings_config_dialog.cpp
-msgid "Search:"
-msgstr "æœå°‹:"
-
-#: editor/asset_library_editor_plugin.cpp editor/code_editor.cpp
-#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Search"
-msgstr "æœå°‹"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/project_manager.cpp
-msgid "Import"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Plugins"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Sort:"
-msgstr "排åº:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Reverse"
-msgstr "å轉"
-
-#: editor/asset_library_editor_plugin.cpp editor/project_settings_editor.cpp
-msgid "Category:"
-msgstr "類別:"
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Site:"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Support.."
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Official"
-msgstr "官方"
-
-#: editor/asset_library_editor_plugin.cpp editor/editor_node.cpp
-msgid "Community"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Testing"
-msgstr ""
-
-#: editor/asset_library_editor_plugin.cpp
-msgid "Assets ZIP File"
-msgstr ""
-
-#: editor/call_dialog.cpp
-msgid "Method List For '%s':"
-msgstr ""
-
-#: editor/call_dialog.cpp modules/visual_script/visual_script_editor.cpp
-msgid "Call"
-msgstr ""
-
-#: editor/call_dialog.cpp
-msgid "Method List:"
-msgstr "方法:"
-
-#: editor/call_dialog.cpp
-msgid "Arguments:"
-msgstr "輸入åƒæ•¸"
-
-#: editor/call_dialog.cpp
-msgid "Return:"
-msgstr "回傳值:"
-
#: editor/code_editor.cpp
msgid "Go to Line"
msgstr "å‰å¾€ç¬¬...è¡Œ"
@@ -654,6 +395,14 @@ msgstr ""
msgid "Selection Only"
msgstr "僅é¸æ“‡å€åŸŸ"
+#: editor/code_editor.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_settings_editor.cpp
+msgid "Search"
+msgstr "æœå°‹"
+
#: editor/code_editor.cpp editor/editor_help.cpp
msgid "Find"
msgstr "尋找"
@@ -686,11 +435,11 @@ msgstr "æ¯æ¬¡å–代都è¦å…ˆè©¢å•æˆ‘"
msgid "Skip"
msgstr "è·³éŽ"
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom In"
msgstr "放大"
-#: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/code_editor.cpp
msgid "Zoom Out"
msgstr "縮å°"
@@ -758,6 +507,20 @@ msgstr "延é²"
msgid "Oneshot"
msgstr ""
+#: editor/connections_dialog.cpp editor/dependency_editor.cpp
+#: editor/export_template_manager.cpp
+#: editor/plugins/animation_player_editor_plugin.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/resource_preloader_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Close"
+msgstr ""
+
#: editor/connections_dialog.cpp
msgid "Connect"
msgstr ""
@@ -783,7 +546,7 @@ msgstr "連接..."
msgid "Disconnect"
msgstr "æ–·ç·š"
-#: editor/connections_dialog.cpp editor/node_dock.cpp
+#: editor/connections_dialog.cpp editor/editor_help.cpp editor/node_dock.cpp
msgid "Signals"
msgstr ""
@@ -800,12 +563,25 @@ msgstr "我的最愛:"
msgid "Recent:"
msgstr "最近存å–:"
+#: editor/create_dialog.cpp editor/editor_node.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/quick_open.cpp editor/settings_config_dialog.cpp
+msgid "Search:"
+msgstr "æœå°‹:"
+
#: editor/create_dialog.cpp editor/editor_help.cpp
#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/quick_open.cpp
msgid "Matches:"
msgstr "符åˆæ¢ä»¶:"
+#: editor/create_dialog.cpp editor/editor_help.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/property_selector.cpp
+#: editor/script_editor_debugger.cpp
+msgid "Description:"
+msgstr "æè¿°:"
+
#: editor/dependency_editor.cpp
msgid "Search Replacement For:"
msgstr ""
@@ -863,6 +639,10 @@ msgid "Owners Of:"
msgstr ""
#: editor/dependency_editor.cpp
+msgid "Remove selected files from the project? (no undo)"
+msgstr "此動作無法復原, 確定è¦å¾žå°ˆæ¡ˆä¸­åˆªé™¤æ‰€é¸çš„檔案?"
+
+#: editor/dependency_editor.cpp
msgid ""
"The files being removed are required by other resources in order for them to "
"work.\n"
@@ -872,8 +652,8 @@ msgstr ""
"此動作無法復原, 確定è¦åˆªé™¤å—Ž?"
#: editor/dependency_editor.cpp
-msgid "Remove selected files from the project? (no undo)"
-msgstr "此動作無法復原, 確定è¦å¾žå°ˆæ¡ˆä¸­åˆªé™¤æ‰€é¸çš„檔案?"
+msgid "Cannot remove:\n"
+msgstr ""
#: editor/dependency_editor.cpp
#, fuzzy
@@ -940,10 +720,6 @@ msgid "Godot Engine contributors"
msgstr ""
#: editor/editor_about.cpp
-msgid "Authors"
-msgstr ""
-
-#: editor/editor_about.cpp
#, fuzzy
msgid "Project Founders"
msgstr "專案設定"
@@ -961,6 +737,38 @@ msgid "Developers"
msgstr ""
#: editor/editor_about.cpp
+msgid "Authors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Platinum Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Gold Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Mini Sponsors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Gold Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Silver Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Bronze Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
+msgid "Donors"
+msgstr ""
+
+#: editor/editor_about.cpp
msgid "License"
msgstr ""
@@ -1002,6 +810,16 @@ msgid "Package Installed Successfully!"
msgstr ""
#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Success!"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp editor/project_manager.cpp
+msgid "Install"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
msgid "Package Installer"
msgstr ""
@@ -1050,11 +868,6 @@ msgid "Audio Bus, Drag and Drop to rearrange."
msgstr ""
#: editor/editor_audio_buses.cpp
-#, fuzzy
-msgid "Bus options"
-msgstr "除錯é¸é …"
-
-#: editor/editor_audio_buses.cpp
msgid "Solo"
msgstr ""
@@ -1066,6 +879,11 @@ msgstr ""
msgid "Bypass"
msgstr ""
+#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Bus options"
+msgstr "除錯é¸é …"
+
#: editor/editor_audio_buses.cpp editor/plugins/tile_map_editor_plugin.cpp
#: editor/scene_tree_dock.cpp
msgid "Duplicate"
@@ -1073,6 +891,11 @@ msgstr ""
#: editor/editor_audio_buses.cpp
#, fuzzy
+msgid "Reset Volume"
+msgstr "é‡è¨­ç¸®æ”¾å¤§å°"
+
+#: editor/editor_audio_buses.cpp
+#, fuzzy
msgid "Delete Effect"
msgstr "刪除"
@@ -1094,6 +917,11 @@ msgid "Duplicate Audio Bus"
msgstr "複製所é¸"
#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Reset Bus Volume"
+msgstr "é‡è¨­ç¸®æ”¾å¤§å°"
+
+#: editor/editor_audio_buses.cpp
msgid "Move Audio Bus"
msgstr ""
@@ -1125,7 +953,8 @@ msgstr ""
msgid "Create a new Bus Layout."
msgstr ""
-#: editor/editor_audio_buses.cpp editor/script_create_dialog.cpp
+#: editor/editor_audio_buses.cpp editor/property_editor.cpp
+#: editor/script_create_dialog.cpp
msgid "Load"
msgstr "載入"
@@ -1216,7 +1045,7 @@ msgid "Rearrange Autoloads"
msgstr ""
#: editor/editor_autoload_settings.cpp editor/editor_file_dialog.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp scene/gui/file_dialog.cpp
+#: scene/gui/file_dialog.cpp
msgid "Path:"
msgstr "路徑:"
@@ -1224,9 +1053,7 @@ msgstr "路徑:"
msgid "Node Name:"
msgstr "節點å稱:"
-#: editor/editor_autoload_settings.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp editor/project_manager.cpp
+#: editor/editor_autoload_settings.cpp editor/project_manager.cpp
msgid "Name"
msgstr "å稱"
@@ -1260,18 +1087,19 @@ msgid "Choose a Directory"
msgstr "é¸æ“‡è³‡æ–™å¤¾"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Create Folder"
msgstr "新增資料夾"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: editor/editor_plugin_settings.cpp editor/plugins/theme_editor_plugin.cpp
-#: editor/project_export.cpp scene/gui/file_dialog.cpp
+#: editor/editor_plugin_settings.cpp editor/filesystem_dock.cpp
+#: editor/plugins/theme_editor_plugin.cpp editor/project_export.cpp
+#: scene/gui/file_dialog.cpp
msgid "Name:"
msgstr "å稱:"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
-#: scene/gui/file_dialog.cpp
+#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
msgid "Could not create folder."
msgstr "無法新增資料夾"
@@ -1291,30 +1119,6 @@ msgstr ""
msgid "Template file not found:\n"
msgstr ""
-#: editor/editor_export.cpp
-msgid "Added:"
-msgstr "已新增:"
-
-#: editor/editor_export.cpp
-msgid "Removed:"
-msgstr "已刪除:"
-
-#: editor/editor_export.cpp
-msgid "Error saving atlas:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Could not save atlas subtexture:"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Exporting for %s"
-msgstr ""
-
-#: editor/editor_export.cpp
-msgid "Setting Up.."
-msgstr ""
-
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "File Exists, Overwrite?"
msgstr "檔案已經存在, è¦è¦†å¯«å—Ž?"
@@ -1399,6 +1203,11 @@ msgstr ""
msgid "Move Favorite Down"
msgstr ""
+#: editor/editor_file_dialog.cpp
+#, fuzzy
+msgid "Go to parent folder"
+msgstr "無法新增資料夾"
+
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Directories & Files:"
msgstr "資料夾 & 檔案:"
@@ -1413,10 +1222,6 @@ msgid "File:"
msgstr "檔案:"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
-msgid "Filter:"
-msgstr "éŽæ¿¾å™¨:"
-
-#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Must use a valid extension."
msgstr ""
@@ -1441,6 +1246,10 @@ msgstr ""
msgid "Search Classes"
msgstr ""
+#: editor/editor_help.cpp editor/plugins/spatial_editor_plugin.cpp
+msgid "Top"
+msgstr ""
+
#: editor/editor_help.cpp editor/property_editor.cpp
msgid "Class:"
msgstr ""
@@ -1457,15 +1266,27 @@ msgstr ""
msgid "Brief Description:"
msgstr ""
+#: editor/editor_help.cpp
+msgid "Members"
+msgstr ""
+
#: editor/editor_help.cpp modules/visual_script/visual_script_editor.cpp
msgid "Members:"
msgstr ""
#: editor/editor_help.cpp
+msgid "Public Methods"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Public Methods:"
msgstr ""
#: editor/editor_help.cpp
+msgid "GUI Theme Items"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "GUI Theme Items:"
msgstr ""
@@ -1474,6 +1295,10 @@ msgid "Signals:"
msgstr ""
#: editor/editor_help.cpp
+msgid "Enumerations"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Enumerations:"
msgstr ""
@@ -1482,18 +1307,48 @@ msgid "enum "
msgstr ""
#: editor/editor_help.cpp
+msgid "Constants"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Constants:"
msgstr ""
#: editor/editor_help.cpp
+#, fuzzy
+msgid "Description"
+msgstr "æè¿°:"
+
+#: editor/editor_help.cpp
+msgid "Properties"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Property Description:"
msgstr ""
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this property. Please help us by "
+"[color=$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+
+#: editor/editor_help.cpp
+#, fuzzy
+msgid "Methods"
+msgstr "方法:"
+
+#: editor/editor_help.cpp
msgid "Method Description:"
msgstr ""
#: editor/editor_help.cpp
+msgid ""
+"There is currently no description for this method. Please help us by [color="
+"$color][url=$url]contributing one[/url][/color]!"
+msgstr ""
+
+#: editor/editor_help.cpp
msgid "Search Text"
msgstr "æœå°‹è©žå½™"
@@ -1503,24 +1358,21 @@ msgid "Output:"
msgstr " 輸出:"
#: editor/editor_log.cpp editor/plugins/animation_tree_editor_plugin.cpp
-#: editor/plugins/rich_text_editor_plugin.cpp editor/property_editor.cpp
-#: editor/script_editor_debugger.cpp scene/gui/line_edit.cpp
-#: scene/gui/text_edit.cpp
+#: editor/property_editor.cpp editor/script_editor_debugger.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Clear"
msgstr "清除"
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Error saving resource!"
msgstr ""
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
-#: editor/resources_dock.cpp
msgid "Save Resource As.."
msgstr ""
-#: editor/editor_node.cpp editor/export_template_manager.cpp
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "I see.."
msgstr "我知é“了"
@@ -1537,6 +1389,29 @@ msgid "Error while saving."
msgstr ""
#: editor/editor_node.cpp
+#, fuzzy
+msgid "Can't open '%s'."
+msgstr "連接..."
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Error while parsing '%s'."
+msgstr "載入場景時發生錯誤"
+
+#: editor/editor_node.cpp
+msgid "Unexpected end of file '%s'."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Missing '%s' or its dependencies."
+msgstr ""
+
+#: editor/editor_node.cpp
+#, fuzzy
+msgid "Error while loading '%s'."
+msgstr "載入場景時發生錯誤"
+
+#: editor/editor_node.cpp
msgid "Saving Scene"
msgstr ""
@@ -1595,6 +1470,33 @@ msgid "Restored default layout to base settings."
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was imported, so it's not editable.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource belongs to a scene that was instanced or inherited.\n"
+"Changes to it will not be kept when saving the current scene."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This resource was imported, so it's not editable. Change its settings in the "
+"import panel and then re-import."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid ""
+"This scene was imported, so changes to it will not be kept.\n"
+"Instancing it or inheriting will allow making changes to it.\n"
+"Please read the documentation relevant to importing scenes to better "
+"understand this workflow."
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Copy Params"
msgstr "複製åƒæ•¸"
@@ -1757,23 +1659,34 @@ msgid "Save changes the following scene(s) before opening Project Manager?"
msgstr ""
#: editor/editor_node.cpp
+msgid ""
+"This option is deprecated. Situations where refresh must be forced are now "
+"considered a bug. Please report."
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "Pick a Main Scene"
msgstr "挑一個主è¦å ´æ™¯"
#: editor/editor_node.cpp
-msgid "Unable to enable addon plugin at: '"
+msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr ""
#: editor/editor_node.cpp
-msgid "' parsing of config failed."
+msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to find script field for addon plugin at: 'res://addons/"
+msgid "Unable to load addon script from path: '%s'."
msgstr ""
#: editor/editor_node.cpp
-msgid "Unable to load addon script from path: '"
+msgid ""
+"Unable to load addon script from path: '%s' Base type is not EditorPlugin."
+msgstr ""
+
+#: editor/editor_node.cpp
+msgid "Unable to load addon script from path: '%s' Script is not in tool mode."
msgstr ""
#: editor/editor_node.cpp
@@ -1783,7 +1696,7 @@ msgid ""
msgstr ""
#: editor/editor_node.cpp editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/scene_tree_dock.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Ugh"
msgstr "呃"
@@ -1794,14 +1707,15 @@ msgid ""
msgstr ""
#: editor/editor_node.cpp
-msgid "Error loading scene."
-msgstr "載入場景時發生錯誤"
-
-#: editor/editor_node.cpp
msgid "Scene '%s' has broken dependencies:"
msgstr ""
#: editor/editor_node.cpp
+#, fuzzy
+msgid "Clear Recent Scenes"
+msgstr "關閉場景"
+
+#: editor/editor_node.cpp
msgid "Save Layout"
msgstr ""
@@ -1834,7 +1748,7 @@ msgstr ""
msgid "Toggle distraction-free mode."
msgstr ""
-#: editor/editor_node.cpp editor/io_plugins/editor_scene_import_plugin.cpp
+#: editor/editor_node.cpp
#, fuzzy
msgid "Scene"
msgstr "場景"
@@ -2055,6 +1969,10 @@ msgstr ""
msgid "Issue Tracker"
msgstr ""
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+msgid "Community"
+msgstr ""
+
#: editor/editor_node.cpp
msgid "About"
msgstr ""
@@ -2063,7 +1981,7 @@ msgstr ""
msgid "Play the project."
msgstr "éŠçŽ©æ­¤å°ˆæ¡ˆ"
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Play"
msgstr "開始"
@@ -2079,7 +1997,7 @@ msgstr "æš«åœå ´æ™¯"
msgid "Stop the scene."
msgstr "åœæ­¢æ­¤å ´æ™¯"
-#: editor/editor_node.cpp editor/plugins/sample_library_editor_plugin.cpp
+#: editor/editor_node.cpp
msgid "Stop"
msgstr "åœæ­¢"
@@ -2152,6 +2070,15 @@ msgid "Object properties."
msgstr ""
#: editor/editor_node.cpp
+msgid "Changes may be lost!"
+msgstr ""
+
+#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Import"
+msgstr ""
+
+#: editor/editor_node.cpp
msgid "FileSystem"
msgstr ""
@@ -2167,14 +2094,6 @@ msgstr ""
msgid "Don't Save"
msgstr ""
-#: editor/editor_node.cpp editor/editor_reimport_dialog.cpp
-msgid "Re-Import"
-msgstr ""
-
-#: editor/editor_node.cpp editor/editor_plugin_settings.cpp
-msgid "Update"
-msgstr ""
-
#: editor/editor_node.cpp
msgid "Import Templates From ZIP File"
msgstr ""
@@ -2236,11 +2155,28 @@ msgstr "離開編輯器嗎?"
msgid "Open the previous Editor"
msgstr ""
+#: editor/editor_plugin.cpp
+msgid "Creating Mesh Previews"
+msgstr ""
+
+#: editor/editor_plugin.cpp
+msgid "Thumbnail.."
+msgstr ""
+
#: editor/editor_plugin_settings.cpp
msgid "Installed Plugins:"
msgstr ""
#: editor/editor_plugin_settings.cpp
+msgid "Update"
+msgstr ""
+
+#: editor/editor_plugin_settings.cpp
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Version:"
+msgstr ""
+
+#: editor/editor_plugin_settings.cpp
msgid "Author:"
msgstr ""
@@ -2273,7 +2209,7 @@ msgid "Frame %"
msgstr ""
#: editor/editor_profiler.cpp
-msgid "Fixed Frame %"
+msgid "Physics Frame %"
msgstr ""
#: editor/editor_profiler.cpp editor/script_editor_debugger.cpp
@@ -2292,26 +2228,6 @@ msgstr ""
msgid "Frame #:"
msgstr ""
-#: editor/editor_reimport_dialog.cpp
-msgid "Please wait for scan to complete."
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Current scene must be saved to re-import."
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Save & Re-Import"
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Importing"
-msgstr ""
-
-#: editor/editor_reimport_dialog.cpp
-msgid "Re-Import Changed Resources"
-msgstr ""
-
#: editor/editor_run_native.cpp
msgid "Select device from the list"
msgstr ""
@@ -2421,10 +2337,6 @@ msgid "Importing:"
msgstr ""
#: editor/export_template_manager.cpp
-msgid "Loading Export Templates"
-msgstr ""
-
-#: editor/export_template_manager.cpp
msgid "Current Version:"
msgstr ""
@@ -2457,81 +2369,78 @@ msgid "Cannot navigate to '"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid ""
-"\n"
-"Status: Needs Re-Import"
-msgstr ""
-
-#: editor/filesystem_dock.cpp
-msgid ""
-"\n"
-"Source: "
+msgid "View items as a grid of thumbnails"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Same source and destination files, doing nothing."
+msgid "View items as a list"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Target file exists, can't overwrite. Delete first."
+msgid ""
+"\n"
+"Status: Import of file failed. Please fix file and reimport manually."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Same source and destination paths, doing nothing."
+msgid ""
+"\n"
+"Source: "
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Can't move directories to within themselves."
+msgid "Cannot move/rename resources root."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Can't rename deps for:\n"
+msgid "Cannot move a folder into itself.\n"
msgstr ""
#: editor/filesystem_dock.cpp
#, fuzzy
-msgid "Error moving file:\n"
+msgid "Error moving:\n"
msgstr "載入時發生錯誤:"
#: editor/filesystem_dock.cpp
#, fuzzy
-msgid "Error moving dir:\n"
-msgstr "載入時發生錯誤:"
+msgid "Unable to update dependencies:\n"
+msgstr "場景缺少了æŸäº›è³‡æºä»¥è‡³æ–¼ç„¡æ³•è¼‰å…¥"
#: editor/filesystem_dock.cpp
-msgid "Can't operate on '..'"
+msgid "No name provided"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Pick New Name and Location For:"
+msgid "Provided name contains invalid characters"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "No files selected!"
+msgid "No name provided."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Expand all"
+msgid "Name contains invalid characters."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Collapse all"
+msgid "A file or folder with this name already exists."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Show In File Manager"
-msgstr ""
+#, fuzzy
+msgid "Renaming file:"
+msgstr "載入時發生錯誤:"
#: editor/filesystem_dock.cpp
-msgid "Instance"
+msgid "Renaming folder:"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Edit Dependencies.."
+msgid "Expand all"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "View Owners.."
+msgid "Collapse all"
msgstr ""
#: editor/filesystem_dock.cpp
@@ -2539,7 +2448,7 @@ msgid "Copy Path"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Rename or Move.."
+msgid "Rename.."
msgstr ""
#: editor/filesystem_dock.cpp
@@ -2547,11 +2456,24 @@ msgid "Move To.."
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Info"
+#, fuzzy
+msgid "New Folder.."
+msgstr "新增資料夾"
+
+#: editor/filesystem_dock.cpp
+msgid "Show In File Manager"
msgstr ""
#: editor/filesystem_dock.cpp
-msgid "Re-Import.."
+msgid "Instance"
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "Edit Dependencies.."
+msgstr ""
+
+#: editor/filesystem_dock.cpp
+msgid "View Owners.."
msgstr ""
#: editor/filesystem_dock.cpp
@@ -2584,6 +2506,11 @@ msgstr ""
msgid "Move"
msgstr ""
+#: editor/filesystem_dock.cpp editor/plugins/animation_tree_editor_plugin.cpp
+#: editor/project_manager.cpp
+msgid "Rename"
+msgstr ""
+
#: editor/groups_editor.cpp
msgid "Add to Group"
msgstr ""
@@ -2598,6 +2525,10 @@ msgid "Import as Single Scene"
msgstr "更新場景"
#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
msgid "Import with Separate Materials"
msgstr ""
@@ -2610,6 +2541,18 @@ msgid "Import with Separate Objects+Materials"
msgstr ""
#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Materials+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
+msgid "Import with Separate Objects+Materials+Animations"
+msgstr ""
+
+#: editor/import/resource_importer_scene.cpp
msgid "Import as Multiple Scenes"
msgstr ""
@@ -2618,38 +2561,31 @@ msgid "Import as Multiple Scenes+Materials"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Import Scene"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Importing Scene.."
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Running Custom Script.."
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Couldn't load post-import script:"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Invalid/broken script for post-import (check console):"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Error running post-import script:"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
msgid "Saving.."
msgstr ""
@@ -2677,579 +2613,54 @@ msgstr ""
msgid "Reimport"
msgstr ""
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "No bit masks to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path is empty."
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must be a complete resource path."
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Target path must exist."
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Save path is empty!"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Import BitMasks"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s):"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Target Path:"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Accept"
-msgstr ""
-
-#: editor/io_plugins/editor_bitmask_import_plugin.cpp
-msgid "Bit Mask"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No source font file!"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "No target font resource!"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"Invalid file extension.\n"
-"Please use .font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Can't load/process source font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Couldn't save font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Source Font Size:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Dest Resource:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "The quick brown fox jumps over the lazy dog."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Test:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Options:"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Font Import"
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid ""
-"This file is already a Godot font file, please supply a BMFont type file "
-"instead."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Failed opening as BMFont file."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error initializing FreeType."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Unknown font format."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Error loading font."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: scene/resources/dynamic_font.cpp
-msgid "Invalid font size."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-msgid "Invalid font custom source."
-msgstr ""
-
-#: editor/io_plugins/editor_font_import_plugin.cpp
-#: editor/plugins/theme_editor_plugin.cpp
-msgid "Font"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "No meshes to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Single Mesh Import"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Source Mesh(es):"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-#: editor/plugins/mesh_instance_editor_plugin.cpp
-msgid "Mesh"
-msgstr ""
-
-#: editor/io_plugins/editor_mesh_import_plugin.cpp
-msgid "Surface %d"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "No samples to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Import Audio Samples"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Source Sample(s):"
-msgstr ""
-
-#: editor/io_plugins/editor_sample_import_plugin.cpp
-msgid "Audio Sample"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "New Clip"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Animation Options"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Flags"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Bake FPS:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Optimizer"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Linear Error"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angular Error"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Max Angle"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Clips"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Start(s)"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "End(s)"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Loop"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Filters"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source path is empty."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't load post-import script."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Invalid/broken script for post-import."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Error importing scene."
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import 3D Scene"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Source Scene:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Same as Target Scene"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Shared"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Target Texture Folder:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Post-Process Script:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Custom Root Node Type:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Auto"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Root Node Name:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "The Following Files are Missing:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Anyway"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp scene/gui/dialogs.cpp
-msgid "Cancel"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import & Open"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Edited scene has not been saved, open imported scene anyway?"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Import Image:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Can't import a file over itself:"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "Couldn't localize path: %s (already local)"
-msgstr ""
-
-#: editor/io_plugins/editor_scene_import_plugin.cpp
-msgid "3D Scene Animation"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Uncompressed"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossless (PNG)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress Lossy (WebP)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Compress (VRAM)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Format"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Compression Quality (WebP):"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture Options"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Please specify some files!"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "At least one file needed for Atlas."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Error importing:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Only one file is required for large texture."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Max Texture Size:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for Atlas (2D)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cell Size:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Large Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Textures (2D)"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture"
+#: editor/multi_node_edit.cpp
+msgid "MultiNode Set"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Base Atlas Texture"
+#: editor/node_dock.cpp
+msgid "Groups"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Source Texture(s)"
+#: editor/node_dock.cpp
+msgid "Select a Node to edit Signals and Groups."
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 2D"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create Poly"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures for 3D"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Textures"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Insert Point"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "2D Texture"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/collision_polygon_editor_plugin.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Edit Poly (Remove Point)"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "3D Texture"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+msgid "Remove Poly And Point"
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Atlas Texture"
+#: editor/plugins/abstract_polygon_2d_editor.cpp
+#: editor/plugins/light_occluder_2d_editor_plugin.cpp
+msgid "Create a new polygon from scratch."
msgstr ""
-#: editor/io_plugins/editor_texture_import_plugin.cpp
+#: editor/plugins/abstract_polygon_2d_editor.cpp
msgid ""
-"NOTICE: Importing 2D textures is not mandatory. Just copy png/jpg files to "
-"the project."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Crop empty space."
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Import Large Texture"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Load Source Image"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Slicing"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Inserting"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Saving"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save large texture:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Build Atlas For:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Loading Image:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't load image:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Converting Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Cropping Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Blitting Images"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save atlas image:"
-msgstr ""
-
-#: editor/io_plugins/editor_texture_import_plugin.cpp
-msgid "Couldn't save converted texture:"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid source!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Invalid translation source!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Column"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-#: editor/script_create_dialog.cpp
-msgid "Language"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No items to import!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "No target path!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translations"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Couldn't import!"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Translation"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Source CSV:"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Ignore First Row"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Compress"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Add to Project (project.godot)"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Import Languages:"
-msgstr ""
-
-#: editor/io_plugins/editor_translation_import_plugin.cpp
-msgid "Translation"
-msgstr ""
-
-#: editor/multi_node_edit.cpp
-msgid "MultiNode Set"
-msgstr ""
-
-#: editor/node_dock.cpp
-msgid "Groups"
-msgstr ""
-
-#: editor/node_dock.cpp
-msgid "Select a Node to edit Signals and Groups."
+"Edit existing polygon:\n"
+"LMB: Move Point.\n"
+"Ctrl+LMB: Split Segment.\n"
+"RMB: Erase Point."
msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
@@ -3405,7 +2816,6 @@ msgstr ""
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/resource_preloader_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
#: editor/script_create_dialog.cpp
msgid "Error!"
@@ -3516,10 +2926,6 @@ msgid "Delete Input"
msgstr ""
#: editor/plugins/animation_tree_editor_plugin.cpp
-msgid "Rename"
-msgstr ""
-
-#: editor/plugins/animation_tree_editor_plugin.cpp
msgid "Animation tree is valid."
msgstr ""
@@ -3575,64 +2981,185 @@ msgstr ""
msgid "Filters.."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing %d Triangles:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Free"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Contents:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "View Files"
+msgstr "éŽæ¿¾æª”案.."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve hostname:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't resolve."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Connection error, please try again."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Can't connect."
+msgstr "連接..."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Can't connect to host:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response from host:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Triangle #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "No response."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Light Baker Setup:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, return code:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Parsing Geometry"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Req. Failed."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Fixing Lights"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Request failed, too many redirects"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Making BVH"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Redirect Loop."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Light Octree"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Creating Octree Texture"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Bad download hash, assuming file has been tampered with."
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Transfer to Lightmaps:"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Expected:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Allocating Texture #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Got:"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Baking Triangle #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Failed sha256 hash check"
msgstr ""
-#: editor/plugins/baked_light_baker.cpp
-msgid "Post-Processing Texture #"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Asset Download Error:"
msgstr ""
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Bake!"
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Fetching:"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Resolving.."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Connecting.."
+msgstr "連接..."
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Requesting.."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#, fuzzy
+msgid "Error making request"
+msgstr "載入場景時發生錯誤"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Idle"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Retry"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download Error"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Download for this asset is already in progress!"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "first"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "prev"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "next"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "last"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "All"
+msgstr "全部"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Plugins"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Sort:"
+msgstr "排åº:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Reverse"
+msgstr "å轉"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+#: editor/project_settings_editor.cpp
+msgid "Category:"
+msgstr "類別:"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Site:"
msgstr ""
-#: editor/plugins/baked_light_editor_plugin.cpp
-msgid "Reset the lightmap octree baking process (start over)."
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Support.."
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Official"
+msgstr "官方"
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Testing"
+msgstr ""
+
+#: editor/plugins/asset_library_editor_plugin.cpp
+msgid "Assets ZIP File"
msgstr ""
#: editor/plugins/camera_editor_plugin.cpp
-#: editor/plugins/sample_library_editor_plugin.cpp
msgid "Preview"
msgstr ""
@@ -3675,11 +3202,15 @@ msgid "Edit CanvasItem"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Change Anchors"
+msgid "Anchors only"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom (%):"
+msgid "Change Anchors and Margins"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Change Anchors"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3730,59 +3261,72 @@ msgid "Pan Mode"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Lock the selected object in place (can't be moved)."
+msgid "Toggles snapping"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Unlock the selected object (can be moved)."
+#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Use Snap"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Makes sure the object's children are not selectable."
+msgid "Snapping options"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Restores the object's children's ability to be selected."
+msgid "Snap to grid"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
-#: editor/project_settings_editor.cpp
-#: modules/visual_script/visual_script_editor.cpp
-msgid "Edit"
+msgid "Use Rotation Snap"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Use Snap"
+msgid "Configure Snap..."
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Show Grid"
+msgid "Snap Relative"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Rotation Snap"
+msgid "Use Pixel Snap"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap Relative"
+msgid "Smart snapping"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Configure Snap.."
+msgid "Snap to parent"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Use Pixel Snap"
+msgid "Snap to node anchor"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to node sides"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Snap to other nodes"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Lock the selected object in place (can't be moved)."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Unlock the selected object (can be moved)."
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Skeleton.."
+msgid "Makes sure the object's children are not selectable."
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Restores the object's children's ability to be selected."
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3811,11 +3355,16 @@ msgid "View"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Reset"
+#: editor/plugins/polygon_2d_editor_plugin.cpp
+msgid "Show Grid"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Zoom Set.."
+msgid "Show helpers"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Show rulers"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3827,7 +3376,7 @@ msgid "Frame Selection"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Anchor"
+msgid "Layout"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3851,11 +3400,20 @@ msgid "Clear Pose"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Set a Value"
+msgid "Drag pivot from mouse position"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-msgid "Snap (Pixels):"
+#, fuzzy
+msgid "Set pivot at mouse position"
+msgstr "移除"
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Multiply grid step by 2"
+msgstr ""
+
+#: editor/plugins/canvas_item_editor_plugin.cpp
+msgid "Divide grid step by 2"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
@@ -3866,23 +3424,28 @@ msgstr ""
msgid "Adding %s..."
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Create Node"
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "Error instancing scene from %s"
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "OK :("
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "No parent to instance a child at."
msgstr ""
-#: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp
+#: editor/plugins/canvas_item_editor_plugin.cpp
+#: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp
msgid "This operation requires a single selected node."
msgstr ""
@@ -3896,45 +3459,6 @@ msgid ""
"Drag & drop + Alt : Change node type"
msgstr ""
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Create Poly"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/collision_polygon_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-#: editor/plugins/path_2d_editor_plugin.cpp
-#: editor/plugins/polygon_2d_editor_plugin.cpp
-msgid "Edit Poly (Remove Point)"
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Create a new polygon from scratch."
-msgstr ""
-
-#: editor/plugins/collision_polygon_2d_editor_plugin.cpp
-msgid ""
-"Edit existing polygon:\n"
-"LMB: Move Point.\n"
-"Ctrl+LMB: Split Segment.\n"
-"RMB: Erase Point."
-msgstr ""
-
#: editor/plugins/collision_polygon_editor_plugin.cpp
msgid "Create Poly3D"
msgstr ""
@@ -3944,14 +3468,6 @@ msgid "Set Handle"
msgstr ""
#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Creating Mesh Library"
-msgstr ""
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
-msgid "Thumbnail.."
-msgstr ""
-
-#: editor/plugins/cube_grid_theme_editor_plugin.cpp
msgid "Remove item %d?"
msgstr ""
@@ -3974,6 +3490,27 @@ msgid "Update from Scene"
msgstr ""
#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat0"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Flat1"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+#, fuzzy
+msgid "Ease in"
+msgstr "所有的é¸æ“‡"
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Ease out"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
+msgid "Smoothstep"
+msgstr ""
+
+#: editor/plugins/curve_editor_plugin.cpp
msgid "Modify Curve Point"
msgstr ""
@@ -4052,22 +3589,18 @@ msgid "Create Occluder Polygon"
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Edit existing polygon:"
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "LMB: Move Point."
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "Ctrl+LMB: Split Segment."
msgstr ""
#: editor/plugins/light_occluder_2d_editor_plugin.cpp
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
msgid "RMB: Erase Point."
msgstr ""
@@ -4168,6 +3701,10 @@ msgid "Create Outline"
msgstr ""
#: editor/plugins/mesh_instance_editor_plugin.cpp
+msgid "Mesh"
+msgstr ""
+
+#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Create Trimesh Static Body"
msgstr ""
@@ -4295,12 +3832,73 @@ msgstr ""
msgid "Populate"
msgstr ""
-#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Create Navigation Polygon"
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake!"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Bake the navigation mesh.\n"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_editor_plugin.cpp
+msgid "Clear the navigation mesh."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Setting up Configuration..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Calculating grid size..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating heightfield..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+#, fuzzy
+msgid "Marking walkable triangles..."
+msgstr "正在儲存變更.."
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Constructing compact heightfield..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Eroding walkable area..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Partitioning..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating contours..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Creating polymesh..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Converting to native navigation mesh..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Navigation Mesh Generator Setup:"
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Parsing Geometry..."
+msgstr ""
+
+#: editor/plugins/navigation_mesh_generator.cpp
+msgid "Done!"
msgstr ""
#: editor/plugins/navigation_polygon_editor_plugin.cpp
-msgid "Remove Poly And Point"
+msgid "Create Navigation Polygon"
msgstr ""
#: editor/plugins/particles_2d_editor_plugin.cpp
@@ -4474,16 +4072,19 @@ msgid "Curve Point #"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve Point Position"
-msgstr ""
+msgstr "移除"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve In Position"
-msgstr ""
+msgstr "移除"
#: editor/plugins/path_editor_plugin.cpp
+#, fuzzy
msgid "Set Curve Out Position"
-msgstr ""
+msgstr "移除"
#: editor/plugins/path_editor_plugin.cpp
msgid "Split Path"
@@ -4542,6 +4143,14 @@ msgid "Scale Polygon"
msgstr ""
#: editor/plugins/polygon_2d_editor_plugin.cpp
+#: editor/plugins/script_text_editor.cpp
+#: editor/plugins/shader_editor_plugin.cpp editor/project_manager.cpp
+#: editor/project_settings_editor.cpp editor/property_editor.cpp
+#: modules/visual_script/visual_script_editor.cpp
+msgid "Edit"
+msgstr ""
+
+#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Polygon->UV"
msgstr ""
@@ -4596,63 +4205,10 @@ msgstr ""
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/shader_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Paste"
msgstr ""
-#: editor/plugins/rich_text_editor_plugin.cpp
-msgid "Parse BBCode"
-msgstr ""
-
-#: editor/plugins/sample_editor_plugin.cpp
-msgid "Length:"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Open Sample File(s)"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "ERROR: Couldn't load sample!"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Add Sample"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Rename Sample"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Delete Sample"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "16 Bits"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "8 Bits"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Stereo"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Mono"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-#: editor/script_editor_debugger.cpp
-msgid "Format"
-msgstr ""
-
-#: editor/plugins/sample_library_editor_plugin.cpp
-msgid "Pitch"
-msgstr ""
-
#: editor/plugins/script_editor_plugin.cpp
msgid "Clear Recent Files"
msgstr ""
@@ -4743,6 +4299,10 @@ msgstr ""
msgid "Close All"
msgstr ""
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+msgid "Run"
+msgstr ""
+
#: editor/plugins/script_editor_plugin.cpp
msgid "Toggle Scripts Panel"
msgstr ""
@@ -4771,7 +4331,8 @@ msgstr ""
msgid "Break"
msgstr ""
-#: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
+#: editor/script_editor_debugger.cpp
msgid "Continue"
msgstr ""
@@ -4785,18 +4346,6 @@ msgid "Debug with external editor"
msgstr "離開編輯器嗎?"
#: editor/plugins/script_editor_plugin.cpp
-msgid "Window"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Left"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
-msgid "Move Right"
-msgstr ""
-
-#: editor/plugins/script_editor_plugin.cpp
msgid "Open Godot online documentation"
msgstr ""
@@ -4879,8 +4428,9 @@ msgid "Cut"
msgstr ""
#: editor/plugins/script_text_editor.cpp
-#: editor/plugins/shader_editor_plugin.cpp editor/property_editor.cpp
-#: editor/resources_dock.cpp scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#: editor/plugins/shader_editor_plugin.cpp
+#: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp
+#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Copy"
msgstr ""
@@ -5146,10 +4696,6 @@ msgid "View Plane Transform."
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Scaling to %s%%."
-msgstr ""
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rotating %s degrees."
msgstr ""
@@ -5166,10 +4712,6 @@ msgid "Top View."
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
-msgid "Top"
-msgstr ""
-
-#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rear View."
msgstr ""
@@ -5402,6 +4944,10 @@ msgid "Transform"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
+msgid "Configure Snap.."
+msgstr ""
+
+#: editor/plugins/spatial_editor_plugin.cpp
msgid "Local Coords"
msgstr ""
@@ -5547,6 +5093,10 @@ msgid "Speed (FPS):"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Loop"
+msgstr ""
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Animation Frames"
msgstr ""
@@ -5559,11 +5109,11 @@ msgid "Insert Empty (After)"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Up"
+msgid "Move (Before)"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
-msgid "Down"
+msgid "Move (After)"
msgstr ""
#: editor/plugins/style_box_editor_plugin.cpp
@@ -5641,7 +5191,11 @@ msgid "Remove All"
msgstr "移除"
#: editor/plugins/theme_editor_plugin.cpp
-msgid "Theme"
+msgid "Edit theme.."
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
+msgid "Theme editing menu."
msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
@@ -5726,6 +5280,10 @@ msgid "Style"
msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
+msgid "Font"
+msgstr ""
+
+#: editor/plugins/theme_editor_plugin.cpp
msgid "Color"
msgstr ""
@@ -5776,7 +5334,7 @@ msgid "Mirror Y"
msgstr ""
#: editor/plugins/tile_map_editor_plugin.cpp
-msgid "Bucket"
+msgid "Paint Tile"
msgstr ""
#: editor/plugins/tile_map_editor_plugin.cpp
@@ -5840,6 +5398,10 @@ msgid "Delete preset '%s'?"
msgstr ""
#: editor/project_export.cpp
+msgid "Export templates for this platform are missing/corrupted: "
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Presets"
msgstr ""
@@ -5912,19 +5474,30 @@ msgid "Export templates for this platform are missing:"
msgstr ""
#: editor/project_export.cpp
+msgid "Export templates for this platform are missing/corrupted:"
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Export With Debug"
msgstr ""
#: editor/project_manager.cpp
-msgid "Invalid project path, the path must exist!"
+#, fuzzy
+msgid "The path does not exist."
+msgstr "檔案ä¸å­˜åœ¨"
+
+#: editor/project_manager.cpp
+msgid "Please choose a 'project.godot' file."
msgstr ""
#: editor/project_manager.cpp
-msgid "Invalid project path, project.godot must not exist."
+msgid ""
+"Your project will be created in a non empty folder (you might want to create "
+"a new folder)."
msgstr ""
#: editor/project_manager.cpp
-msgid "Invalid project path, project.godot must exist."
+msgid "Please choose a folder that does not contain a 'project.godot' file."
msgstr ""
#: editor/project_manager.cpp
@@ -5932,10 +5505,26 @@ msgid "Imported Project"
msgstr ""
#: editor/project_manager.cpp
+msgid " "
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "It would be a good idea to name your project."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Invalid project path (changed anything?)."
msgstr ""
#: editor/project_manager.cpp
+msgid "Couldn't get project.godot in project path."
+msgstr ""
+
+#: editor/project_manager.cpp
+msgid "Couldn't edit project.godot in project path."
+msgstr ""
+
+#: editor/project_manager.cpp
msgid "Couldn't create project.godot in project path."
msgstr ""
@@ -5944,15 +5533,20 @@ msgid "The following files failed extraction from package:"
msgstr ""
#: editor/project_manager.cpp
-msgid "Import Existing Project"
+#, fuzzy
+msgid "Rename Project"
+msgstr "專案設定"
+
+#: editor/project_manager.cpp
+msgid "Couldn't get project.godot in the project path."
msgstr ""
#: editor/project_manager.cpp
-msgid "Project Path (Must Exist):"
+msgid "New Game Project"
msgstr ""
#: editor/project_manager.cpp
-msgid "Project Name:"
+msgid "Import Existing Project"
msgstr ""
#: editor/project_manager.cpp
@@ -5960,19 +5554,24 @@ msgid "Create New Project"
msgstr ""
#: editor/project_manager.cpp
-msgid "Project Path:"
+msgid "Install Project:"
msgstr ""
#: editor/project_manager.cpp
-msgid "Install Project:"
+msgid "Project Name:"
msgstr ""
#: editor/project_manager.cpp
-msgid "Browse"
+#, fuzzy
+msgid "Create folder"
+msgstr "新增資料夾"
+
+#: editor/project_manager.cpp
+msgid "Project Path:"
msgstr ""
#: editor/project_manager.cpp
-msgid "New Game Project"
+msgid "Browse"
msgstr ""
#: editor/project_manager.cpp
@@ -5984,6 +5583,11 @@ msgid "Unnamed Project"
msgstr ""
#: editor/project_manager.cpp
+#, fuzzy
+msgid "Can't open project"
+msgstr "連接..."
+
+#: editor/project_manager.cpp
msgid "Are you sure to open more than one project?"
msgstr ""
@@ -6010,16 +5614,18 @@ msgstr ""
#: editor/project_manager.cpp
msgid ""
-"You are about the scan %s folders for existing Godot projects. Do you "
-"confirm?"
+"Language changed.\n"
+"The UI will update next time the editor or project manager starts."
msgstr ""
#: editor/project_manager.cpp
-msgid "Project List"
+msgid ""
+"You are about the scan %s folders for existing Godot projects. Do you "
+"confirm?"
msgstr ""
#: editor/project_manager.cpp
-msgid "Run"
+msgid "Project List"
msgstr ""
#: editor/project_manager.cpp
@@ -6043,6 +5649,10 @@ msgid "Exit"
msgstr ""
#: editor/project_manager.cpp
+msgid "Restart Now"
+msgstr ""
+
+#: editor/project_manager.cpp
#, fuzzy
msgid "Can't run project"
msgstr "連接..."
@@ -6080,17 +5690,14 @@ msgid "Add Input Action Event"
msgstr ""
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Meta+"
msgstr ""
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Shift+"
msgstr ""
#: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp
-#: scene/gui/input_action.cpp
msgid "Alt+"
msgstr ""
@@ -6151,7 +5758,7 @@ msgstr ""
msgid "Joypad Axis Index:"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Axis"
msgstr ""
@@ -6171,31 +5778,31 @@ msgstr ""
msgid "Add Event"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Device"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Button"
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Left Button."
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Right Button."
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Middle Button."
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Up."
msgstr ""
-#: editor/project_settings_editor.cpp scene/gui/input_action.cpp
+#: editor/project_settings_editor.cpp
msgid "Wheel Down."
msgstr ""
@@ -6204,7 +5811,7 @@ msgid "Add Global Property"
msgstr ""
#: editor/project_settings_editor.cpp
-msgid "Select an setting item first!"
+msgid "Select a setting item first!"
msgstr ""
#: editor/project_settings_editor.cpp
@@ -6221,6 +5828,14 @@ msgid "Delete Item"
msgstr "刪除"
#: editor/project_settings_editor.cpp
+msgid "Can't contain '/' or ':'"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Already existing"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "Error saving settings."
msgstr ""
@@ -6262,6 +5877,15 @@ msgstr ""
#: editor/project_settings_editor.cpp
#, fuzzy
+msgid "Changed Locale Filter"
+msgstr "變更é¡é ­å°ºå¯¸"
+
+#: editor/project_settings_editor.cpp
+msgid "Changed Locale Filter Mode"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
msgid "Project Settings (project.godot)"
msgstr "專案設定"
@@ -6322,6 +5946,27 @@ msgid "Locale"
msgstr ""
#: editor/project_settings_editor.cpp
+msgid "Locales Filter"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Show all locales"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+msgid "Show only selected locales"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
+#, fuzzy
+msgid "Filter mode:"
+msgstr "éŽæ¿¾æª”案.."
+
+#: editor/project_settings_editor.cpp
+msgid "Locales:"
+msgstr ""
+
+#: editor/project_settings_editor.cpp
msgid "AutoLoad"
msgstr ""
@@ -6370,10 +6015,19 @@ msgid "New Script"
msgstr ""
#: editor/property_editor.cpp
+msgid "Make Unique"
+msgstr ""
+
+#: editor/property_editor.cpp
msgid "Show in File System"
msgstr ""
#: editor/property_editor.cpp
+#, fuzzy
+msgid "Convert To %s"
+msgstr "轉æ›æˆ.."
+
+#: editor/property_editor.cpp
msgid "Error loading file: Not a resource!"
msgstr ""
@@ -6410,6 +6064,10 @@ msgid "Select Property"
msgstr ""
#: editor/property_selector.cpp
+msgid "Select Virtual Method"
+msgstr ""
+
+#: editor/property_selector.cpp
msgid "Select Method"
msgstr ""
@@ -6437,26 +6095,6 @@ msgstr ""
msgid "Reparent"
msgstr ""
-#: editor/resources_dock.cpp
-msgid "Create New Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Open Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Save Resource"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Resource Tools"
-msgstr ""
-
-#: editor/resources_dock.cpp
-msgid "Make Local"
-msgstr ""
-
#: editor/run_settings_dialog.cpp
msgid "Run Mode:"
msgstr ""
@@ -6583,14 +6221,6 @@ msgid "Sub-Resources:"
msgstr ""
#: editor/scene_tree_dock.cpp
-msgid "Edit Groups"
-msgstr ""
-
-#: editor/scene_tree_dock.cpp
-msgid "Edit Connections"
-msgstr ""
-
-#: editor/scene_tree_dock.cpp
msgid "Clear Inheritance"
msgstr ""
@@ -6775,6 +6405,15 @@ msgid "Invalid base path"
msgstr ""
#: editor/script_create_dialog.cpp
+msgid "Directory of the same name exists"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
+#, fuzzy
+msgid "File exists, will be reused"
+msgstr "檔案已經存在, è¦è¦†å¯«å—Ž?"
+
+#: editor/script_create_dialog.cpp
msgid "Invalid extension"
msgstr ""
@@ -6816,6 +6455,10 @@ msgid "Load existing script file"
msgstr ""
#: editor/script_create_dialog.cpp
+msgid "Language"
+msgstr ""
+
+#: editor/script_create_dialog.cpp
msgid "Inherits"
msgstr ""
@@ -6856,6 +6499,10 @@ msgid "Function:"
msgstr ""
#: editor/script_editor_debugger.cpp
+msgid "Pick one or more items from the list to display the graph."
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
msgid "Errors"
msgstr ""
@@ -6938,6 +6585,10 @@ msgid "Type"
msgstr "é¡žåž‹"
#: editor/script_editor_debugger.cpp
+msgid "Format"
+msgstr ""
+
+#: editor/script_editor_debugger.cpp
msgid "Usage"
msgstr "使用é‡"
@@ -7016,12 +6667,28 @@ msgstr ""
msgid "Change Probe Extents"
msgstr "變更框型範åœ"
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Library"
+msgstr ""
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Status"
+msgstr ""
+
+#: modules/gdnative/gd_native_library_editor.cpp
+msgid "Libraries: "
+msgstr ""
+
+#: modules/gdnative/register_types.cpp
+msgid "GDNative"
+msgstr ""
+
#: modules/gdscript/gd_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Invalid type argument to convert(), use TYPE_* constants."
msgstr ""
-#: modules/gdscript/gd_functions.cpp
+#: modules/gdscript/gd_functions.cpp modules/mono/glue/glue_header.h
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Not enough bytes for decoding bytes, or invalid format."
msgstr "解碼字節ä½å…ƒä¸è¶³ï¼Œæˆ–為無效格å¼ã€‚"
@@ -7078,10 +6745,6 @@ msgid "GridMap Duplicate Selection"
msgstr "複製所é¸"
#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "GridMap Paint"
-msgstr ""
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Snap View"
msgstr ""
@@ -7178,12 +6841,8 @@ msgstr "專案設定"
msgid "Pick Distance:"
msgstr ""
-#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "Tiles"
-msgstr ""
-
-#: modules/gridmap/grid_map_editor_plugin.cpp
-msgid "Areas"
+#: modules/mono/editor/mono_bottom_panel.cpp
+msgid "Builds"
msgstr ""
#: modules/visual_script/visual_script.cpp
@@ -7377,10 +7036,18 @@ msgid "Return"
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
+msgid "Call"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
msgid "Get"
msgstr ""
#: modules/visual_script/visual_script_editor.cpp
+msgid "Script already has function '%s'"
+msgstr ""
+
+#: modules/visual_script/visual_script_editor.cpp
msgid "Change Input Value"
msgstr ""
@@ -7740,6 +7407,12 @@ msgid ""
"order for AnimatedSprite3D to display frames."
msgstr ""
+#: scene/3d/vehicle_body.cpp
+msgid ""
+"VehicleWheel serves to provide a wheel system to a VehicleBody. Please use "
+"it as a child of a VehicleBody."
+msgstr ""
+
#: scene/gui/color_picker.cpp
msgid "Raw Mode"
msgstr ""
@@ -7749,6 +7422,10 @@ msgid "Add current color as a preset"
msgstr ""
#: scene/gui/dialogs.cpp
+msgid "Cancel"
+msgstr ""
+
+#: scene/gui/dialogs.cpp
msgid "Alert!"
msgstr ""
@@ -7756,10 +7433,6 @@ msgstr ""
msgid "Please Confirm..."
msgstr ""
-#: scene/gui/input_action.cpp
-msgid "Ctrl+"
-msgstr "Ctrl+"
-
#: scene/gui/popup.cpp
msgid ""
"Popups will hide by default unless you call popup() or any of the popup*() "
@@ -7788,6 +7461,40 @@ msgid ""
"texture to some node for display."
msgstr ""
+#: scene/resources/dynamic_font.cpp
+msgid "Error initializing FreeType."
+msgstr ""
+
+#: scene/resources/dynamic_font.cpp
+msgid "Unknown font format."
+msgstr ""
+
+#: scene/resources/dynamic_font.cpp
+msgid "Error loading font."
+msgstr ""
+
+#: scene/resources/dynamic_font.cpp
+msgid "Invalid font size."
+msgstr ""
+
+#~ msgid "Filter:"
+#~ msgstr "éŽæ¿¾å™¨:"
+
+#~ msgid "Arguments:"
+#~ msgstr "輸入åƒæ•¸"
+
+#~ msgid "Return:"
+#~ msgstr "回傳值:"
+
+#~ msgid "Added:"
+#~ msgstr "已新增:"
+
+#~ msgid "Removed:"
+#~ msgstr "已刪除:"
+
+#~ msgid "Ctrl+"
+#~ msgstr "Ctrl+"
+
#~ msgid "Close scene? (Unsaved changes will be lost)"
#~ msgstr "沒有儲存的變更都會éºå¤±, 確定è¦é—œé–‰?"
diff --git a/main/SCsub b/main/SCsub
index 1f97cd1be0..ae63b94864 100644
--- a/main/SCsub
+++ b/main/SCsub
@@ -16,7 +16,7 @@ def make_splash(target, source, env):
g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n")
g.write("#ifndef BOOT_SPLASH_H\n")
g.write("#define BOOT_SPLASH_H\n")
- g.write("static const Color boot_splash_bg_color = Color(1,1,1,1);\n")
+ g.write('static const Color boot_splash_bg_color = Color::html("#232323");\n')
g.write("static const unsigned char boot_splash_png[] = {\n")
for i in range(len(buf)):
g.write(byte_to_str(buf[i]) + ",\n")
diff --git a/main/input_default.cpp b/main/input_default.cpp
index 2940f432d5..7cc7521686 100644
--- a/main/input_default.cpp
+++ b/main/input_default.cpp
@@ -319,6 +319,15 @@ void InputDefault::parse_input_event(const Ref<InputEvent> &p_event) {
set_joy_axis(jm->get_device(), jm->get_axis(), jm->get_axis_value());
}
+ Ref<InputEventGesture> ge = p_event;
+
+ if (ge.is_valid()) {
+
+ if (main_loop) {
+ main_loop->input_event(ge);
+ }
+ }
+
if (!p_event->is_echo()) {
for (const Map<StringName, InputMap::Action>::Element *E = InputMap::get_singleton()->get_action_map().front(); E; E = E->next()) {
diff --git a/main/main.cpp b/main/main.cpp
index e06f423bfc..e74402d7dd 100644..100755
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -35,6 +35,7 @@
#include "message_queue.h"
#include "modules/register_module_types.h"
#include "os/os.h"
+#include "platform/register_platform_apis.h"
#include "project_settings.h"
#include "scene/register_scene_types.h"
#include "script_debugger_local.h"
@@ -45,7 +46,10 @@
#include "input_map.h"
#include "io/resource_loader.h"
#include "scene/main/scene_tree.h"
+#include "servers/arvr_server.h"
#include "servers/audio_server.h"
+#include "servers/physics_2d_server.h"
+#include "servers/physics_server.h"
#include "io/resource_loader.h"
#include "script_language.h"
@@ -82,6 +86,9 @@ static InputMap *input_map = NULL;
static bool _start_success = false;
static ScriptDebugger *script_debugger = NULL;
AudioServer *audio_server = NULL;
+ARVRServer *arvr_server = NULL;
+PhysicsServer *physics_server = NULL;
+Physics2DServer *physics_2d_server = NULL;
static MessageQueue *message_queue = NULL;
static Performance *performance = NULL;
@@ -118,6 +125,35 @@ static int fixed_fps = -1;
static OS::ProcessID allow_focus_steal_pid = 0;
+void initialize_physics() {
+
+ /// 3D Physics Server
+ physics_server = PhysicsServerManager::new_server(ProjectSettings::get_singleton()->get(PhysicsServerManager::setting_property_name));
+ if (!physics_server) {
+ // Physics server not found, Use the default physics
+ physics_server = PhysicsServerManager::new_default_server();
+ }
+ ERR_FAIL_COND(!physics_server);
+ physics_server->init();
+
+ /// 2D Physics server
+ physics_2d_server = Physics2DServerManager::new_server(ProjectSettings::get_singleton()->get(Physics2DServerManager::setting_property_name));
+ if (!physics_2d_server) {
+ // Physics server not found, Use the default physics
+ physics_2d_server = Physics2DServerManager::new_default_server();
+ }
+ ERR_FAIL_COND(!physics_2d_server);
+ physics_2d_server->init();
+}
+
+void finalize_physics() {
+ physics_server->finish();
+ memdelete(physics_server);
+
+ physics_2d_server->finish();
+ memdelete(physics_2d_server);
+}
+
static String unescape_cmdline(const String &p_str) {
return p_str.replace("%20", " ");
@@ -141,7 +177,7 @@ static String get_full_version_string() {
void Main::print_help(const char *p_binary) {
- print_line(String(_MKSTR(VERSION_NAME)) + " v" + get_full_version_string() + " - https://godotengine.org");
+ print_line(String(VERSION_NAME) + " v" + get_full_version_string() + " - https://godotengine.org");
OS::get_singleton()->print("(c) 2007-2017 Juan Linietsky, Ariel Manzur.\n");
OS::get_singleton()->print("(c) 2014-2017 Godot Engine contributors.\n");
OS::get_singleton()->print("\n");
@@ -162,6 +198,7 @@ void Main::print_help(const char *p_binary) {
#endif
OS::get_singleton()->print(" -l, --language <locale> Use a specific locale (<locale> being a two-letter code).\n");
OS::get_singleton()->print(" --path <directory> Path to a project (<directory> must contain a 'project.godot' file).\n");
+ OS::get_singleton()->print(" -u, --upwards Scan folders upwards for project.godot file.\n");
OS::get_singleton()->print(" --main-pack <file> Path to a pack (.pck) file to load.\n");
OS::get_singleton()->print(" --render-thread <mode> Render thread mode ('unsafe', 'safe', 'separate').\n");
OS::get_singleton()->print(" --remote-fs <address> Remote filesystem (<host/IP>[:<port>] address).\n");
@@ -253,11 +290,10 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
register_core_settings(); //here globals is present
- OS::get_singleton()->initialize_logger();
-
translation_server = memnew(TranslationServer);
performance = memnew(Performance);
- globals->add_singleton(ProjectSettings::Singleton("Performance", performance));
+ ClassDB::register_class<Performance>();
+ engine->add_singleton(Engine::Singleton("Performance", performance));
GLOBAL_DEF("debug/settings/crash_handler/message", String("Please include this when reporting the bug on https://github.com/godotengine/godot/issues"));
@@ -284,11 +320,10 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
I = args.front();
- video_mode = OS::get_singleton()->get_default_video_mode();
-
String video_driver = "";
String audio_driver = "";
String game_path = ".";
+ bool upwards = false;
String debug_mode;
String debug_host;
String main_pack;
@@ -390,6 +425,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
} else if (I->get() == "-m" || I->get() == "--maximized") { // force maximized window
init_maximized = true;
+ video_mode.maximized = true;
} else if (I->get() == "-w" || I->get() == "--windowed") { // force windowed window
init_windowed = true;
@@ -497,6 +533,8 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
OS::get_singleton()->print("Missing relative or absolute path, aborting.\n");
goto error;
}
+ } else if (I->get() == "-u" || I->get() == "--upwards") { // scan folders upwards
+ upwards = true;
} else if (I->get().ends_with("project.godot")) {
String path;
String file = I->get();
@@ -694,7 +732,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
#endif
- if (globals->setup(game_path, main_pack) != OK) {
+ if (globals->setup(game_path, main_pack, upwards) != OK) {
#ifdef TOOLS_ENABLED
editor = false;
@@ -705,10 +743,20 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
#endif
}
+ GLOBAL_DEF("logging/file_logging/enable_file_logging", true);
+ GLOBAL_DEF("logging/file_logging/log_path", "user://logs/log.txt");
+ GLOBAL_DEF("logging/file_logging/max_log_files", 10);
+ if (FileAccess::get_create_func(FileAccess::ACCESS_USERDATA) && GLOBAL_GET("logging/file_logging/enable_file_logging")) {
+ String base_path = GLOBAL_GET("logging/file_logging/log_path");
+ int max_files = GLOBAL_GET("logging/file_logging/max_log_files");
+ OS::get_singleton()->add_logger(memnew(RotatedFileLogger(base_path, max_files)));
+ }
+
if (editor) {
Engine::get_singleton()->set_editor_hint(true);
main_args.push_back("--editor");
init_maximized = true;
+ video_mode.maximized = true;
use_custom_res = false;
}
@@ -739,38 +787,41 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
//if (video_driver == "") // useless for now, so removing
// video_driver = GLOBAL_DEF("display/driver/name", Variant((const char *)OS::get_singleton()->get_video_driver_name(0)));
- if (!force_res && use_custom_res && globals->has_setting("display/window/size/width"))
- video_mode.width = globals->get("display/window/size/width");
- if (!force_res && use_custom_res && globals->has_setting("display/window/size/height"))
- video_mode.height = globals->get("display/window/size/height");
- if (!editor && ((globals->has_setting("display/window/dpi/allow_hidpi") && !globals->get("display/window/dpi/allow_hidpi")) || force_lowdpi)) {
- OS::get_singleton()->_allow_hidpi = false;
- }
- if (use_custom_res && globals->has_setting("display/window/size/fullscreen"))
- video_mode.fullscreen = globals->get("display/window/size/fullscreen");
- if (use_custom_res && globals->has_setting("display/window/size/resizable"))
- video_mode.resizable = globals->get("display/window/size/resizable");
- if (use_custom_res && globals->has_setting("display/window/size/borderless"))
- video_mode.borderless_window = globals->get("display/window/size/borderless");
-
- if (!force_res && use_custom_res && globals->has_setting("display/window/size/test_width") && globals->has_setting("display/window/size/test_height")) {
- int tw = globals->get("display/window/size/test_width");
- int th = globals->get("display/window/size/test_height");
- if (tw > 0 && th > 0) {
- video_mode.width = tw;
- video_mode.height = th;
+ GLOBAL_DEF("display/window/size/width", 1024);
+ GLOBAL_DEF("display/window/size/height", 600);
+ GLOBAL_DEF("display/window/size/resizable", true);
+ GLOBAL_DEF("display/window/size/borderless", false);
+ GLOBAL_DEF("display/window/size/fullscreen", false);
+ GLOBAL_DEF("display/window/size/test_width", 0);
+ GLOBAL_DEF("display/window/size/test_height", 0);
+
+ if (use_custom_res) {
+
+ if (!force_res) {
+ video_mode.width = GLOBAL_GET("display/window/size/width");
+ video_mode.height = GLOBAL_GET("display/window/size/height");
+
+ if (globals->has_setting("display/window/size/test_width") && globals->has_setting("display/window/size/test_height")) {
+ int tw = globals->get("display/window/size/test_width");
+ int th = globals->get("display/window/size/test_height");
+ if (tw > 0 && th > 0) {
+ video_mode.width = tw;
+ video_mode.height = th;
+ }
+ }
}
+
+ video_mode.resizable = GLOBAL_GET("display/window/size/resizable");
+ video_mode.borderless_window = GLOBAL_GET("display/window/size/borderless");
+ video_mode.fullscreen = GLOBAL_GET("display/window/size/fullscreen");
}
- GLOBAL_DEF("display/window/size/width", video_mode.width);
- GLOBAL_DEF("display/window/size/height", video_mode.height);
- GLOBAL_DEF("display/window/dpi/allow_hidpi", false);
- GLOBAL_DEF("display/window/size/fullscreen", video_mode.fullscreen);
- GLOBAL_DEF("display/window/size/resizable", video_mode.resizable);
- GLOBAL_DEF("display/window/size/borderless", video_mode.borderless_window);
- use_vsync = GLOBAL_DEF("display/window/vsync/use_vsync", use_vsync);
- GLOBAL_DEF("display/window/size/test_width", 0);
- GLOBAL_DEF("display/window/size/test_height", 0);
+ if (!force_lowdpi) {
+ OS::get_singleton()->_allow_hidpi = GLOBAL_DEF("display/window/dpi/allow_hidpi", false);
+ }
+
+ use_vsync = GLOBAL_DEF("display/window/vsync/use_vsync", true);
+
GLOBAL_DEF("rendering/quality/intended_usage/framebuffer_allocation", 2);
GLOBAL_DEF("rendering/quality/intended_usage/framebuffer_allocation.mobile", 3);
@@ -934,11 +985,14 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
OS::get_singleton()->set_window_position(init_custom_pos);
}
- //right moment to create and initialize the audio server
+ // right moment to create and initialize the audio server
audio_server = memnew(AudioServer);
audio_server->init();
+ // also init our arvr_server from here
+ arvr_server = memnew(ARVRServer);
+
OS::get_singleton()->set_use_vsync(use_vsync);
register_core_singletons();
@@ -1062,9 +1116,14 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
OS::get_singleton()->enable_for_stealing_focus(allow_focus_steal_pid);
}
- MAIN_PRINT("Main: Load Scripts, Modules, Drivers");
+ MAIN_PRINT("Main: Load Modules, Physics, Drivers, Scripts");
+ register_platform_apis();
register_module_types();
+
+ initialize_physics();
+ register_server_singletons();
+
register_driver_types();
ScriptServer::init_languages();
@@ -1340,7 +1399,7 @@ bool Main::start() {
String stretch_mode = GLOBAL_DEF("display/window/stretch/mode", "disabled");
String stretch_aspect = GLOBAL_DEF("display/window/stretch/aspect", "ignore");
Size2i stretch_size = Size2(GLOBAL_DEF("display/window/size/width", 0), GLOBAL_DEF("display/window/size/height", 0));
- int stretch_shrink = GLOBAL_DEF("display/window/stretch/shrink", 1);
+ real_t stretch_shrink = GLOBAL_DEF("display/window/stretch/shrink", 1.0f);
SceneTree::StretchMode sml_sm = SceneTree::STRETCH_MODE_DISABLED;
if (stretch_mode == "2d")
@@ -1623,7 +1682,7 @@ bool Main::iteration() {
while (time_accum > frame_slice) {
- uint64_t fixed_begin = OS::get_singleton()->get_ticks_usec();
+ uint64_t physics_begin = OS::get_singleton()->get_ticks_usec();
PhysicsServer::get_singleton()->sync();
PhysicsServer::get_singleton()->flush_queries();
@@ -1646,8 +1705,8 @@ bool Main::iteration() {
time_accum -= frame_slice;
message_queue->flush();
- physics_process_ticks = MAX(physics_process_ticks, OS::get_singleton()->get_ticks_usec() - fixed_begin); // keep the largest one for reference
- physics_process_max = MAX(OS::get_singleton()->get_ticks_usec() - fixed_begin, physics_process_max);
+ physics_process_ticks = MAX(physics_process_ticks, OS::get_singleton()->get_ticks_usec() - physics_begin); // keep the largest one for reference
+ physics_process_max = MAX(OS::get_singleton()->get_ticks_usec() - physics_begin, physics_process_max);
iters++;
Engine::get_singleton()->_physics_frames++;
}
@@ -1770,12 +1829,19 @@ void Main::cleanup() {
memdelete(audio_server);
}
+ if (arvr_server) {
+ // cleanup now before we pull the rug from underneath...
+ memdelete(arvr_server);
+ }
+
unregister_driver_types();
unregister_module_types();
+ unregister_platform_apis();
unregister_scene_types();
unregister_server_types();
OS::get_singleton()->finalize();
+ finalize_physics();
if (packed_data)
memdelete(packed_data);
diff --git a/main/performance.cpp b/main/performance.cpp
index 0f3383c4a8..39b42e803c 100644
--- a/main/performance.cpp
+++ b/main/performance.cpp
@@ -57,10 +57,10 @@ void Performance::_bind_methods() {
BIND_ENUM_CONSTANT(RENDER_SHADER_CHANGES_IN_FRAME);
BIND_ENUM_CONSTANT(RENDER_SURFACE_CHANGES_IN_FRAME);
BIND_ENUM_CONSTANT(RENDER_DRAW_CALLS_IN_FRAME);
- BIND_ENUM_CONSTANT(RENDER_USAGE_VIDEO_MEM_TOTAL);
BIND_ENUM_CONSTANT(RENDER_VIDEO_MEM_USED);
BIND_ENUM_CONSTANT(RENDER_TEXTURE_MEM_USED);
BIND_ENUM_CONSTANT(RENDER_VERTEX_MEM_USED);
+ BIND_ENUM_CONSTANT(RENDER_USAGE_VIDEO_MEM_TOTAL);
BIND_ENUM_CONSTANT(PHYSICS_2D_ACTIVE_OBJECTS);
BIND_ENUM_CONSTANT(PHYSICS_2D_COLLISION_PAIRS);
BIND_ENUM_CONSTANT(PHYSICS_2D_ISLAND_COUNT);
@@ -153,6 +153,44 @@ float Performance::get_monitor(Monitor p_monitor) const {
return 0;
}
+Performance::MonitorType Performance::get_monitor_type(Monitor p_monitor) const {
+ ERR_FAIL_INDEX_V(p_monitor, MONITOR_MAX, MONITOR_TYPE_QUANTITY);
+ // ugly
+ static const MonitorType types[MONITOR_MAX] = {
+
+ MONITOR_TYPE_QUANTITY,
+ MONITOR_TYPE_TIME,
+ MONITOR_TYPE_TIME,
+ MONITOR_TYPE_MEMORY,
+ MONITOR_TYPE_MEMORY,
+ MONITOR_TYPE_MEMORY,
+ MONITOR_TYPE_MEMORY,
+ MONITOR_TYPE_MEMORY,
+ MONITOR_TYPE_QUANTITY,
+ MONITOR_TYPE_QUANTITY,
+ MONITOR_TYPE_QUANTITY,
+ MONITOR_TYPE_QUANTITY,
+ MONITOR_TYPE_QUANTITY,
+ MONITOR_TYPE_QUANTITY,
+ MONITOR_TYPE_QUANTITY,
+ MONITOR_TYPE_QUANTITY,
+ MONITOR_TYPE_QUANTITY,
+ MONITOR_TYPE_MEMORY,
+ MONITOR_TYPE_MEMORY,
+ MONITOR_TYPE_MEMORY,
+ MONITOR_TYPE_MEMORY,
+ MONITOR_TYPE_QUANTITY,
+ MONITOR_TYPE_QUANTITY,
+ MONITOR_TYPE_QUANTITY,
+ MONITOR_TYPE_QUANTITY,
+ MONITOR_TYPE_QUANTITY,
+ MONITOR_TYPE_QUANTITY,
+
+ };
+
+ return types[p_monitor];
+}
+
void Performance::set_process_time(float p_pt) {
_process_time = p_pt;
diff --git a/main/performance.h b/main/performance.h
index 900e6434b7..21fbd7a1d2 100644
--- a/main/performance.h
+++ b/main/performance.h
@@ -79,9 +79,17 @@ public:
MONITOR_MAX
};
+ enum MonitorType {
+ MONITOR_TYPE_QUANTITY,
+ MONITOR_TYPE_MEMORY,
+ MONITOR_TYPE_TIME
+ };
+
float get_monitor(Monitor p_monitor) const;
String get_monitor_name(Monitor p_monitor) const;
+ MonitorType get_monitor_type(Monitor p_monitor) const;
+
void set_process_time(float p_pt);
void set_physics_process_time(float p_pt);
diff --git a/main/splash.png b/main/splash.png
index 894a7d7aba..34be46557f 100644
--- a/main/splash.png
+++ b/main/splash.png
Binary files differ
diff --git a/main/tests/test_gdscript.cpp b/main/tests/test_gdscript.cpp
index bcf4278bde..b41b5f6452 100644
--- a/main/tests/test_gdscript.cpp
+++ b/main/tests/test_gdscript.cpp
@@ -35,10 +35,10 @@
#ifdef GDSCRIPT_ENABLED
-#include "modules/gdscript/gd_compiler.h"
-#include "modules/gdscript/gd_parser.h"
-#include "modules/gdscript/gd_script.h"
-#include "modules/gdscript/gd_tokenizer.h"
+#include "modules/gdscript/gdscript.h"
+#include "modules/gdscript/gdscript_compiler.h"
+#include "modules/gdscript/gdscript_parser.h"
+#include "modules/gdscript/gdscript_tokenizer.h"
namespace TestGDScript {
@@ -52,7 +52,7 @@ static void _print_indent(int p_ident, const String &p_text) {
print_line(txt + p_text);
}
-static String _parser_extends(const GDParser::ClassNode *p_class) {
+static String _parser_extends(const GDScriptParser::ClassNode *p_class) {
String txt = "extends ";
if (String(p_class->extends_file) != "") {
@@ -72,29 +72,29 @@ static String _parser_extends(const GDParser::ClassNode *p_class) {
return txt;
}
-static String _parser_expr(const GDParser::Node *p_expr) {
+static String _parser_expr(const GDScriptParser::Node *p_expr) {
String txt;
switch (p_expr->type) {
- case GDParser::Node::TYPE_IDENTIFIER: {
+ case GDScriptParser::Node::TYPE_IDENTIFIER: {
- const GDParser::IdentifierNode *id_node = static_cast<const GDParser::IdentifierNode *>(p_expr);
+ const GDScriptParser::IdentifierNode *id_node = static_cast<const GDScriptParser::IdentifierNode *>(p_expr);
txt = id_node->name;
} break;
- case GDParser::Node::TYPE_CONSTANT: {
- const GDParser::ConstantNode *c_node = static_cast<const GDParser::ConstantNode *>(p_expr);
+ case GDScriptParser::Node::TYPE_CONSTANT: {
+ const GDScriptParser::ConstantNode *c_node = static_cast<const GDScriptParser::ConstantNode *>(p_expr);
if (c_node->value.get_type() == Variant::STRING)
txt = "\"" + String(c_node->value) + "\"";
else
txt = c_node->value;
} break;
- case GDParser::Node::TYPE_SELF: {
+ case GDScriptParser::Node::TYPE_SELF: {
txt = "self";
} break;
- case GDParser::Node::TYPE_ARRAY: {
- const GDParser::ArrayNode *arr_node = static_cast<const GDParser::ArrayNode *>(p_expr);
+ case GDScriptParser::Node::TYPE_ARRAY: {
+ const GDScriptParser::ArrayNode *arr_node = static_cast<const GDScriptParser::ArrayNode *>(p_expr);
txt += "[";
for (int i = 0; i < arr_node->elements.size(); i++) {
@@ -104,51 +104,51 @@ static String _parser_expr(const GDParser::Node *p_expr) {
}
txt += "]";
} break;
- case GDParser::Node::TYPE_DICTIONARY: {
- const GDParser::DictionaryNode *dict_node = static_cast<const GDParser::DictionaryNode *>(p_expr);
+ case GDScriptParser::Node::TYPE_DICTIONARY: {
+ const GDScriptParser::DictionaryNode *dict_node = static_cast<const GDScriptParser::DictionaryNode *>(p_expr);
txt += "{";
for (int i = 0; i < dict_node->elements.size(); i++) {
if (i > 0)
txt += ", ";
- const GDParser::DictionaryNode::Pair &p = dict_node->elements[i];
+ const GDScriptParser::DictionaryNode::Pair &p = dict_node->elements[i];
txt += _parser_expr(p.key);
txt += ":";
txt += _parser_expr(p.value);
}
txt += "}";
} break;
- case GDParser::Node::TYPE_OPERATOR: {
+ case GDScriptParser::Node::TYPE_OPERATOR: {
- const GDParser::OperatorNode *c_node = static_cast<const GDParser::OperatorNode *>(p_expr);
+ const GDScriptParser::OperatorNode *c_node = static_cast<const GDScriptParser::OperatorNode *>(p_expr);
switch (c_node->op) {
- case GDParser::OperatorNode::OP_PARENT_CALL:
+ case GDScriptParser::OperatorNode::OP_PARENT_CALL:
txt += ".";
- case GDParser::OperatorNode::OP_CALL: {
+ case GDScriptParser::OperatorNode::OP_CALL: {
ERR_FAIL_COND_V(c_node->arguments.size() < 1, "");
String func_name;
- const GDParser::Node *nfunc = c_node->arguments[0];
+ const GDScriptParser::Node *nfunc = c_node->arguments[0];
int arg_ofs = 0;
- if (nfunc->type == GDParser::Node::TYPE_BUILT_IN_FUNCTION) {
+ if (nfunc->type == GDScriptParser::Node::TYPE_BUILT_IN_FUNCTION) {
- const GDParser::BuiltInFunctionNode *bif_node = static_cast<const GDParser::BuiltInFunctionNode *>(nfunc);
- func_name = GDFunctions::get_func_name(bif_node->function);
+ const GDScriptParser::BuiltInFunctionNode *bif_node = static_cast<const GDScriptParser::BuiltInFunctionNode *>(nfunc);
+ func_name = GDScriptFunctions::get_func_name(bif_node->function);
arg_ofs = 1;
- } else if (nfunc->type == GDParser::Node::TYPE_TYPE) {
+ } else if (nfunc->type == GDScriptParser::Node::TYPE_TYPE) {
- const GDParser::TypeNode *t_node = static_cast<const GDParser::TypeNode *>(nfunc);
+ const GDScriptParser::TypeNode *t_node = static_cast<const GDScriptParser::TypeNode *>(nfunc);
func_name = Variant::get_type_name(t_node->vtype);
arg_ofs = 1;
} else {
ERR_FAIL_COND_V(c_node->arguments.size() < 2, "");
nfunc = c_node->arguments[1];
- ERR_FAIL_COND_V(nfunc->type != GDParser::Node::TYPE_IDENTIFIER, "");
+ ERR_FAIL_COND_V(nfunc->type != GDScriptParser::Node::TYPE_IDENTIFIER, "");
- if (c_node->arguments[0]->type != GDParser::Node::TYPE_SELF)
+ if (c_node->arguments[0]->type != GDScriptParser::Node::TYPE_SELF)
func_name = _parser_expr(c_node->arguments[0]) + ".";
func_name += _parser_expr(nfunc);
@@ -159,7 +159,7 @@ static String _parser_expr(const GDParser::Node *p_expr) {
for (int i = arg_ofs; i < c_node->arguments.size(); i++) {
- const GDParser::Node *arg = c_node->arguments[i];
+ const GDScriptParser::Node *arg = c_node->arguments[i];
if (i > arg_ofs)
txt += ", ";
txt += _parser_expr(arg);
@@ -168,7 +168,7 @@ static String _parser_expr(const GDParser::Node *p_expr) {
txt += ")";
} break;
- case GDParser::OperatorNode::OP_INDEX: {
+ case GDScriptParser::OperatorNode::OP_INDEX: {
ERR_FAIL_COND_V(c_node->arguments.size() != 2, "");
@@ -176,125 +176,125 @@ static String _parser_expr(const GDParser::Node *p_expr) {
txt = _parser_expr(c_node->arguments[0]) + "[" + _parser_expr(c_node->arguments[1]) + "]";
} break;
- case GDParser::OperatorNode::OP_INDEX_NAMED: {
+ case GDScriptParser::OperatorNode::OP_INDEX_NAMED: {
ERR_FAIL_COND_V(c_node->arguments.size() != 2, "");
txt = _parser_expr(c_node->arguments[0]) + "." + _parser_expr(c_node->arguments[1]);
} break;
- case GDParser::OperatorNode::OP_NEG: {
+ case GDScriptParser::OperatorNode::OP_NEG: {
txt = "-" + _parser_expr(c_node->arguments[0]);
} break;
- case GDParser::OperatorNode::OP_NOT: {
+ case GDScriptParser::OperatorNode::OP_NOT: {
txt = "not " + _parser_expr(c_node->arguments[0]);
} break;
- case GDParser::OperatorNode::OP_BIT_INVERT: {
+ case GDScriptParser::OperatorNode::OP_BIT_INVERT: {
txt = "~" + _parser_expr(c_node->arguments[0]);
} break;
- case GDParser::OperatorNode::OP_PREINC: {
+ case GDScriptParser::OperatorNode::OP_PREINC: {
} break;
- case GDParser::OperatorNode::OP_PREDEC: {
+ case GDScriptParser::OperatorNode::OP_PREDEC: {
} break;
- case GDParser::OperatorNode::OP_INC: {
+ case GDScriptParser::OperatorNode::OP_INC: {
} break;
- case GDParser::OperatorNode::OP_DEC: {
+ case GDScriptParser::OperatorNode::OP_DEC: {
} break;
- case GDParser::OperatorNode::OP_IN: {
+ case GDScriptParser::OperatorNode::OP_IN: {
txt = _parser_expr(c_node->arguments[0]) + " in " + _parser_expr(c_node->arguments[1]);
} break;
- case GDParser::OperatorNode::OP_EQUAL: {
+ case GDScriptParser::OperatorNode::OP_EQUAL: {
txt = _parser_expr(c_node->arguments[0]) + "==" + _parser_expr(c_node->arguments[1]);
} break;
- case GDParser::OperatorNode::OP_NOT_EQUAL: {
+ case GDScriptParser::OperatorNode::OP_NOT_EQUAL: {
txt = _parser_expr(c_node->arguments[0]) + "!=" + _parser_expr(c_node->arguments[1]);
} break;
- case GDParser::OperatorNode::OP_LESS: {
+ case GDScriptParser::OperatorNode::OP_LESS: {
txt = _parser_expr(c_node->arguments[0]) + "<" + _parser_expr(c_node->arguments[1]);
} break;
- case GDParser::OperatorNode::OP_LESS_EQUAL: {
+ case GDScriptParser::OperatorNode::OP_LESS_EQUAL: {
txt = _parser_expr(c_node->arguments[0]) + "<=" + _parser_expr(c_node->arguments[1]);
} break;
- case GDParser::OperatorNode::OP_GREATER: {
+ case GDScriptParser::OperatorNode::OP_GREATER: {
txt = _parser_expr(c_node->arguments[0]) + ">" + _parser_expr(c_node->arguments[1]);
} break;
- case GDParser::OperatorNode::OP_GREATER_EQUAL: {
+ case GDScriptParser::OperatorNode::OP_GREATER_EQUAL: {
txt = _parser_expr(c_node->arguments[0]) + ">=" + _parser_expr(c_node->arguments[1]);
} break;
- case GDParser::OperatorNode::OP_AND: {
+ case GDScriptParser::OperatorNode::OP_AND: {
txt = _parser_expr(c_node->arguments[0]) + " and " + _parser_expr(c_node->arguments[1]);
} break;
- case GDParser::OperatorNode::OP_OR: {
+ case GDScriptParser::OperatorNode::OP_OR: {
txt = _parser_expr(c_node->arguments[0]) + " or " + _parser_expr(c_node->arguments[1]);
} break;
- case GDParser::OperatorNode::OP_ADD: {
+ case GDScriptParser::OperatorNode::OP_ADD: {
txt = _parser_expr(c_node->arguments[0]) + "+" + _parser_expr(c_node->arguments[1]);
} break;
- case GDParser::OperatorNode::OP_SUB: {
+ case GDScriptParser::OperatorNode::OP_SUB: {
txt = _parser_expr(c_node->arguments[0]) + "-" + _parser_expr(c_node->arguments[1]);
} break;
- case GDParser::OperatorNode::OP_MUL: {
+ case GDScriptParser::OperatorNode::OP_MUL: {
txt = _parser_expr(c_node->arguments[0]) + "*" + _parser_expr(c_node->arguments[1]);
} break;
- case GDParser::OperatorNode::OP_DIV: {
+ case GDScriptParser::OperatorNode::OP_DIV: {
txt = _parser_expr(c_node->arguments[0]) + "/" + _parser_expr(c_node->arguments[1]);
} break;
- case GDParser::OperatorNode::OP_MOD: {
+ case GDScriptParser::OperatorNode::OP_MOD: {
txt = _parser_expr(c_node->arguments[0]) + "%" + _parser_expr(c_node->arguments[1]);
} break;
- case GDParser::OperatorNode::OP_SHIFT_LEFT: {
+ case GDScriptParser::OperatorNode::OP_SHIFT_LEFT: {
txt = _parser_expr(c_node->arguments[0]) + "<<" + _parser_expr(c_node->arguments[1]);
} break;
- case GDParser::OperatorNode::OP_SHIFT_RIGHT: {
+ case GDScriptParser::OperatorNode::OP_SHIFT_RIGHT: {
txt = _parser_expr(c_node->arguments[0]) + ">>" + _parser_expr(c_node->arguments[1]);
} break;
- case GDParser::OperatorNode::OP_ASSIGN: {
+ case GDScriptParser::OperatorNode::OP_ASSIGN: {
txt = _parser_expr(c_node->arguments[0]) + "=" + _parser_expr(c_node->arguments[1]);
} break;
- case GDParser::OperatorNode::OP_ASSIGN_ADD: {
+ case GDScriptParser::OperatorNode::OP_ASSIGN_ADD: {
txt = _parser_expr(c_node->arguments[0]) + "+=" + _parser_expr(c_node->arguments[1]);
} break;
- case GDParser::OperatorNode::OP_ASSIGN_SUB: {
+ case GDScriptParser::OperatorNode::OP_ASSIGN_SUB: {
txt = _parser_expr(c_node->arguments[0]) + "-=" + _parser_expr(c_node->arguments[1]);
} break;
- case GDParser::OperatorNode::OP_ASSIGN_MUL: {
+ case GDScriptParser::OperatorNode::OP_ASSIGN_MUL: {
txt = _parser_expr(c_node->arguments[0]) + "*=" + _parser_expr(c_node->arguments[1]);
} break;
- case GDParser::OperatorNode::OP_ASSIGN_DIV: {
+ case GDScriptParser::OperatorNode::OP_ASSIGN_DIV: {
txt = _parser_expr(c_node->arguments[0]) + "/=" + _parser_expr(c_node->arguments[1]);
} break;
- case GDParser::OperatorNode::OP_ASSIGN_MOD: {
+ case GDScriptParser::OperatorNode::OP_ASSIGN_MOD: {
txt = _parser_expr(c_node->arguments[0]) + "%=" + _parser_expr(c_node->arguments[1]);
} break;
- case GDParser::OperatorNode::OP_ASSIGN_SHIFT_LEFT: {
+ case GDScriptParser::OperatorNode::OP_ASSIGN_SHIFT_LEFT: {
txt = _parser_expr(c_node->arguments[0]) + "<<=" + _parser_expr(c_node->arguments[1]);
} break;
- case GDParser::OperatorNode::OP_ASSIGN_SHIFT_RIGHT: {
+ case GDScriptParser::OperatorNode::OP_ASSIGN_SHIFT_RIGHT: {
txt = _parser_expr(c_node->arguments[0]) + ">>=" + _parser_expr(c_node->arguments[1]);
} break;
- case GDParser::OperatorNode::OP_ASSIGN_BIT_AND: {
+ case GDScriptParser::OperatorNode::OP_ASSIGN_BIT_AND: {
txt = _parser_expr(c_node->arguments[0]) + "&=" + _parser_expr(c_node->arguments[1]);
} break;
- case GDParser::OperatorNode::OP_ASSIGN_BIT_OR: {
+ case GDScriptParser::OperatorNode::OP_ASSIGN_BIT_OR: {
txt = _parser_expr(c_node->arguments[0]) + "|=" + _parser_expr(c_node->arguments[1]);
} break;
- case GDParser::OperatorNode::OP_ASSIGN_BIT_XOR: {
+ case GDScriptParser::OperatorNode::OP_ASSIGN_BIT_XOR: {
txt = _parser_expr(c_node->arguments[0]) + "^=" + _parser_expr(c_node->arguments[1]);
} break;
- case GDParser::OperatorNode::OP_BIT_AND: {
+ case GDScriptParser::OperatorNode::OP_BIT_AND: {
txt = _parser_expr(c_node->arguments[0]) + "&" + _parser_expr(c_node->arguments[1]);
} break;
- case GDParser::OperatorNode::OP_BIT_OR: {
+ case GDScriptParser::OperatorNode::OP_BIT_OR: {
txt = _parser_expr(c_node->arguments[0]) + "|" + _parser_expr(c_node->arguments[1]);
} break;
- case GDParser::OperatorNode::OP_BIT_XOR: {
+ case GDScriptParser::OperatorNode::OP_BIT_XOR: {
txt = _parser_expr(c_node->arguments[0]) + "^" + _parser_expr(c_node->arguments[1]);
} break;
default: {}
}
} break;
- case GDParser::Node::TYPE_NEWLINE: {
+ case GDScriptParser::Node::TYPE_NEWLINE: {
//skippie
} break;
@@ -310,20 +310,20 @@ static String _parser_expr(const GDParser::Node *p_expr) {
//return "("+txt+")";
}
-static void _parser_show_block(const GDParser::BlockNode *p_block, int p_indent) {
+static void _parser_show_block(const GDScriptParser::BlockNode *p_block, int p_indent) {
for (int i = 0; i < p_block->statements.size(); i++) {
- const GDParser::Node *statement = p_block->statements[i];
+ const GDScriptParser::Node *statement = p_block->statements[i];
switch (statement->type) {
- case GDParser::Node::TYPE_CONTROL_FLOW: {
+ case GDScriptParser::Node::TYPE_CONTROL_FLOW: {
- const GDParser::ControlFlowNode *cf_node = static_cast<const GDParser::ControlFlowNode *>(statement);
+ const GDScriptParser::ControlFlowNode *cf_node = static_cast<const GDScriptParser::ControlFlowNode *>(statement);
switch (cf_node->cf_type) {
- case GDParser::ControlFlowNode::CF_IF: {
+ case GDScriptParser::ControlFlowNode::CF_IF: {
ERR_FAIL_COND(cf_node->arguments.size() != 1);
String txt;
@@ -339,7 +339,7 @@ static void _parser_show_block(const GDParser::BlockNode *p_block, int p_indent)
}
} break;
- case GDParser::ControlFlowNode::CF_FOR: {
+ case GDScriptParser::ControlFlowNode::CF_FOR: {
ERR_FAIL_COND(cf_node->arguments.size() != 2);
String txt;
txt += "for ";
@@ -352,7 +352,7 @@ static void _parser_show_block(const GDParser::BlockNode *p_block, int p_indent)
_parser_show_block(cf_node->body, p_indent + 1);
} break;
- case GDParser::ControlFlowNode::CF_WHILE: {
+ case GDScriptParser::ControlFlowNode::CF_WHILE: {
ERR_FAIL_COND(cf_node->arguments.size() != 1);
String txt;
@@ -364,18 +364,18 @@ static void _parser_show_block(const GDParser::BlockNode *p_block, int p_indent)
_parser_show_block(cf_node->body, p_indent + 1);
} break;
- case GDParser::ControlFlowNode::CF_SWITCH: {
+ case GDScriptParser::ControlFlowNode::CF_SWITCH: {
} break;
- case GDParser::ControlFlowNode::CF_CONTINUE: {
+ case GDScriptParser::ControlFlowNode::CF_CONTINUE: {
_print_indent(p_indent, "continue");
} break;
- case GDParser::ControlFlowNode::CF_BREAK: {
+ case GDScriptParser::ControlFlowNode::CF_BREAK: {
_print_indent(p_indent, "break");
} break;
- case GDParser::ControlFlowNode::CF_RETURN: {
+ case GDScriptParser::ControlFlowNode::CF_RETURN: {
if (cf_node->arguments.size())
_print_indent(p_indent, "return " + _parser_expr(cf_node->arguments[0]));
@@ -385,9 +385,9 @@ static void _parser_show_block(const GDParser::BlockNode *p_block, int p_indent)
}
} break;
- case GDParser::Node::TYPE_LOCAL_VAR: {
+ case GDScriptParser::Node::TYPE_LOCAL_VAR: {
- const GDParser::LocalVarNode *lv_node = static_cast<const GDParser::LocalVarNode *>(statement);
+ const GDScriptParser::LocalVarNode *lv_node = static_cast<const GDScriptParser::LocalVarNode *>(statement);
_print_indent(p_indent, "var " + String(lv_node->name));
} break;
default: {
@@ -398,7 +398,7 @@ static void _parser_show_block(const GDParser::BlockNode *p_block, int p_indent)
}
}
-static void _parser_show_function(const GDParser::FunctionNode *p_func, int p_indent, GDParser::BlockNode *p_initializer = NULL) {
+static void _parser_show_function(const GDScriptParser::FunctionNode *p_func, int p_indent, GDScriptParser::BlockNode *p_initializer = NULL) {
String txt;
if (p_func->_static)
@@ -434,7 +434,7 @@ static void _parser_show_function(const GDParser::FunctionNode *p_func, int p_in
_parser_show_block(p_func->body, p_indent + 1);
}
-static void _parser_show_class(const GDParser::ClassNode *p_class, int p_indent, const Vector<String> &p_code) {
+static void _parser_show_class(const GDScriptParser::ClassNode *p_class, int p_indent, const Vector<String> &p_code) {
if (p_indent == 0 && (String(p_class->extends_file) != "" || p_class->extends_class.size())) {
@@ -444,7 +444,7 @@ static void _parser_show_class(const GDParser::ClassNode *p_class, int p_indent,
for (int i = 0; i < p_class->subclasses.size(); i++) {
- const GDParser::ClassNode *subclass = p_class->subclasses[i];
+ const GDScriptParser::ClassNode *subclass = p_class->subclasses[i];
String line = "class " + subclass->name;
if (String(subclass->extends_file) != "" || subclass->extends_class.size())
line += " " + _parser_extends(subclass);
@@ -456,13 +456,13 @@ static void _parser_show_class(const GDParser::ClassNode *p_class, int p_indent,
for (int i = 0; i < p_class->constant_expressions.size(); i++) {
- const GDParser::ClassNode::Constant &constant = p_class->constant_expressions[i];
+ const GDScriptParser::ClassNode::Constant &constant = p_class->constant_expressions[i];
_print_indent(p_indent, "const " + String(constant.identifier) + "=" + _parser_expr(constant.expression));
}
for (int i = 0; i < p_class->variables.size(); i++) {
- const GDParser::ClassNode::Member &m = p_class->variables[i];
+ const GDScriptParser::ClassNode::Member &m = p_class->variables[i];
_print_indent(p_indent, "var " + String(m.identifier));
}
@@ -487,27 +487,27 @@ static void _parser_show_class(const GDParser::ClassNode *p_class, int p_indent,
print_line("\n");
}
-static String _disassemble_addr(const Ref<GDScript> &p_script, const GDFunction &func, int p_addr) {
+static String _disassemble_addr(const Ref<GDScript> &p_script, const GDScriptFunction &func, int p_addr) {
- int addr = p_addr & GDFunction::ADDR_MASK;
+ int addr = p_addr & GDScriptFunction::ADDR_MASK;
- switch (p_addr >> GDFunction::ADDR_BITS) {
+ switch (p_addr >> GDScriptFunction::ADDR_BITS) {
- case GDFunction::ADDR_TYPE_SELF: {
+ case GDScriptFunction::ADDR_TYPE_SELF: {
return "self";
} break;
- case GDFunction::ADDR_TYPE_CLASS: {
+ case GDScriptFunction::ADDR_TYPE_CLASS: {
return "class";
} break;
- case GDFunction::ADDR_TYPE_MEMBER: {
+ case GDScriptFunction::ADDR_TYPE_MEMBER: {
return "member(" + p_script->debug_get_member_by_index(addr) + ")";
} break;
- case GDFunction::ADDR_TYPE_CLASS_CONSTANT: {
+ case GDScriptFunction::ADDR_TYPE_CLASS_CONSTANT: {
return "class_const(" + func.get_global_name(addr) + ")";
} break;
- case GDFunction::ADDR_TYPE_LOCAL_CONSTANT: {
+ case GDScriptFunction::ADDR_TYPE_LOCAL_CONSTANT: {
Variant v = func.get_constant(addr);
String txt;
@@ -517,19 +517,19 @@ static String _disassemble_addr(const Ref<GDScript> &p_script, const GDFunction
txt = v;
return "const(" + txt + ")";
} break;
- case GDFunction::ADDR_TYPE_STACK: {
+ case GDScriptFunction::ADDR_TYPE_STACK: {
return "stack(" + itos(addr) + ")";
} break;
- case GDFunction::ADDR_TYPE_STACK_VARIABLE: {
+ case GDScriptFunction::ADDR_TYPE_STACK_VARIABLE: {
return "var_stack(" + itos(addr) + ")";
} break;
- case GDFunction::ADDR_TYPE_GLOBAL: {
+ case GDScriptFunction::ADDR_TYPE_GLOBAL: {
return "global(" + func.get_global_name(addr) + ")";
} break;
- case GDFunction::ADDR_TYPE_NIL: {
+ case GDScriptFunction::ADDR_TYPE_NIL: {
return "nil";
} break;
}
@@ -539,11 +539,11 @@ static String _disassemble_addr(const Ref<GDScript> &p_script, const GDFunction
static void _disassemble_class(const Ref<GDScript> &p_class, const Vector<String> &p_code) {
- const Map<StringName, GDFunction *> &mf = p_class->debug_get_member_functions();
+ const Map<StringName, GDScriptFunction *> &mf = p_class->debug_get_member_functions();
- for (const Map<StringName, GDFunction *>::Element *E = mf.front(); E; E = E->next()) {
+ for (const Map<StringName, GDScriptFunction *>::Element *E = mf.front(); E; E = E->next()) {
- const GDFunction &func = *E->get();
+ const GDScriptFunction &func = *E->get();
const int *code = func.get_code();
int codelen = func.get_code_size();
String defargs;
@@ -568,7 +568,7 @@ static void _disassemble_class(const Ref<GDScript> &p_class, const Vector<String
switch (code[ip]) {
- case GDFunction::OPCODE_OPERATOR: {
+ case GDScriptFunction::OPCODE_OPERATOR: {
int op = code[ip + 1];
txt += "op ";
@@ -583,7 +583,7 @@ static void _disassemble_class(const Ref<GDScript> &p_class, const Vector<String
incr += 5;
} break;
- case GDFunction::OPCODE_SET: {
+ case GDScriptFunction::OPCODE_SET: {
txt += "set ";
txt += DADDR(1);
@@ -594,7 +594,7 @@ static void _disassemble_class(const Ref<GDScript> &p_class, const Vector<String
incr += 4;
} break;
- case GDFunction::OPCODE_GET: {
+ case GDScriptFunction::OPCODE_GET: {
txt += " get ";
txt += DADDR(3);
@@ -606,7 +606,7 @@ static void _disassemble_class(const Ref<GDScript> &p_class, const Vector<String
incr += 4;
} break;
- case GDFunction::OPCODE_SET_NAMED: {
+ case GDScriptFunction::OPCODE_SET_NAMED: {
txt += " set_named ";
txt += DADDR(1);
@@ -617,7 +617,7 @@ static void _disassemble_class(const Ref<GDScript> &p_class, const Vector<String
incr += 4;
} break;
- case GDFunction::OPCODE_GET_NAMED: {
+ case GDScriptFunction::OPCODE_GET_NAMED: {
txt += " get_named ";
txt += DADDR(3);
@@ -629,7 +629,7 @@ static void _disassemble_class(const Ref<GDScript> &p_class, const Vector<String
incr += 4;
} break;
- case GDFunction::OPCODE_SET_MEMBER: {
+ case GDScriptFunction::OPCODE_SET_MEMBER: {
txt += " set_member ";
txt += "[\"";
@@ -639,7 +639,7 @@ static void _disassemble_class(const Ref<GDScript> &p_class, const Vector<String
incr += 3;
} break;
- case GDFunction::OPCODE_GET_MEMBER: {
+ case GDScriptFunction::OPCODE_GET_MEMBER: {
txt += " get_member ";
txt += DADDR(2);
@@ -650,7 +650,7 @@ static void _disassemble_class(const Ref<GDScript> &p_class, const Vector<String
incr += 3;
} break;
- case GDFunction::OPCODE_ASSIGN: {
+ case GDScriptFunction::OPCODE_ASSIGN: {
txt += " assign ";
txt += DADDR(1);
@@ -659,7 +659,7 @@ static void _disassemble_class(const Ref<GDScript> &p_class, const Vector<String
incr += 3;
} break;
- case GDFunction::OPCODE_ASSIGN_TRUE: {
+ case GDScriptFunction::OPCODE_ASSIGN_TRUE: {
txt += " assign ";
txt += DADDR(1);
@@ -667,7 +667,7 @@ static void _disassemble_class(const Ref<GDScript> &p_class, const Vector<String
incr += 2;
} break;
- case GDFunction::OPCODE_ASSIGN_FALSE: {
+ case GDScriptFunction::OPCODE_ASSIGN_FALSE: {
txt += " assign ";
txt += DADDR(1);
@@ -675,7 +675,7 @@ static void _disassemble_class(const Ref<GDScript> &p_class, const Vector<String
incr += 2;
} break;
- case GDFunction::OPCODE_CONSTRUCT: {
+ case GDScriptFunction::OPCODE_CONSTRUCT: {
Variant::Type t = Variant::Type(code[ip + 1]);
int argc = code[ip + 2];
@@ -696,7 +696,7 @@ static void _disassemble_class(const Ref<GDScript> &p_class, const Vector<String
incr = 4 + argc;
} break;
- case GDFunction::OPCODE_CONSTRUCT_ARRAY: {
+ case GDScriptFunction::OPCODE_CONSTRUCT_ARRAY: {
int argc = code[ip + 1];
txt += " make_array ";
@@ -714,7 +714,7 @@ static void _disassemble_class(const Ref<GDScript> &p_class, const Vector<String
incr += 3 + argc;
} break;
- case GDFunction::OPCODE_CONSTRUCT_DICTIONARY: {
+ case GDScriptFunction::OPCODE_CONSTRUCT_DICTIONARY: {
int argc = code[ip + 1];
txt += " make_dict ";
@@ -735,10 +735,10 @@ static void _disassemble_class(const Ref<GDScript> &p_class, const Vector<String
} break;
- case GDFunction::OPCODE_CALL:
- case GDFunction::OPCODE_CALL_RETURN: {
+ case GDScriptFunction::OPCODE_CALL:
+ case GDScriptFunction::OPCODE_CALL_RETURN: {
- bool ret = code[ip] == GDFunction::OPCODE_CALL_RETURN;
+ bool ret = code[ip] == GDScriptFunction::OPCODE_CALL_RETURN;
if (ret)
txt += " call-ret ";
@@ -764,14 +764,14 @@ static void _disassemble_class(const Ref<GDScript> &p_class, const Vector<String
incr = 5 + argc;
} break;
- case GDFunction::OPCODE_CALL_BUILT_IN: {
+ case GDScriptFunction::OPCODE_CALL_BUILT_IN: {
txt += " call-built-in ";
int argc = code[ip + 2];
txt += DADDR(3 + argc) + "=";
- txt += GDFunctions::get_func_name(GDFunctions::Function(code[ip + 1]));
+ txt += GDScriptFunctions::get_func_name(GDScriptFunctions::Function(code[ip + 1]));
txt += "(";
for (int i = 0; i < argc; i++) {
@@ -784,7 +784,7 @@ static void _disassemble_class(const Ref<GDScript> &p_class, const Vector<String
incr = 4 + argc;
} break;
- case GDFunction::OPCODE_CALL_SELF_BASE: {
+ case GDScriptFunction::OPCODE_CALL_SELF_BASE: {
txt += " call-self-base ";
@@ -804,13 +804,13 @@ static void _disassemble_class(const Ref<GDScript> &p_class, const Vector<String
incr = 4 + argc;
} break;
- case GDFunction::OPCODE_YIELD: {
+ case GDScriptFunction::OPCODE_YIELD: {
txt += " yield ";
incr = 1;
} break;
- case GDFunction::OPCODE_YIELD_SIGNAL: {
+ case GDScriptFunction::OPCODE_YIELD_SIGNAL: {
txt += " yield_signal ";
txt += DADDR(1);
@@ -818,13 +818,13 @@ static void _disassemble_class(const Ref<GDScript> &p_class, const Vector<String
txt += DADDR(2);
incr = 3;
} break;
- case GDFunction::OPCODE_YIELD_RESUME: {
+ case GDScriptFunction::OPCODE_YIELD_RESUME: {
txt += " yield resume: ";
txt += DADDR(1);
incr = 2;
} break;
- case GDFunction::OPCODE_JUMP: {
+ case GDScriptFunction::OPCODE_JUMP: {
txt += " jump ";
txt += itos(code[ip + 1]);
@@ -832,7 +832,7 @@ static void _disassemble_class(const Ref<GDScript> &p_class, const Vector<String
incr = 2;
} break;
- case GDFunction::OPCODE_JUMP_IF: {
+ case GDScriptFunction::OPCODE_JUMP_IF: {
txt += " jump-if ";
txt += DADDR(1);
@@ -841,7 +841,7 @@ static void _disassemble_class(const Ref<GDScript> &p_class, const Vector<String
incr = 3;
} break;
- case GDFunction::OPCODE_JUMP_IF_NOT: {
+ case GDScriptFunction::OPCODE_JUMP_IF_NOT: {
txt += " jump-if-not ";
txt += DADDR(1);
@@ -850,12 +850,12 @@ static void _disassemble_class(const Ref<GDScript> &p_class, const Vector<String
incr = 3;
} break;
- case GDFunction::OPCODE_JUMP_TO_DEF_ARGUMENT: {
+ case GDScriptFunction::OPCODE_JUMP_TO_DEF_ARGUMENT: {
txt += " jump-to-default-argument ";
incr = 1;
} break;
- case GDFunction::OPCODE_RETURN: {
+ case GDScriptFunction::OPCODE_RETURN: {
txt += " return ";
txt += DADDR(1);
@@ -863,19 +863,19 @@ static void _disassemble_class(const Ref<GDScript> &p_class, const Vector<String
incr = 2;
} break;
- case GDFunction::OPCODE_ITERATE_BEGIN: {
+ case GDScriptFunction::OPCODE_ITERATE_BEGIN: {
txt += " for-init " + DADDR(4) + " in " + DADDR(2) + " counter " + DADDR(1) + " end " + itos(code[ip + 3]);
incr += 5;
} break;
- case GDFunction::OPCODE_ITERATE: {
+ case GDScriptFunction::OPCODE_ITERATE: {
txt += " for-loop " + DADDR(4) + " in " + DADDR(2) + " counter " + DADDR(1) + " end " + itos(code[ip + 3]);
incr += 5;
} break;
- case GDFunction::OPCODE_LINE: {
+ case GDScriptFunction::OPCODE_LINE: {
int line = code[ip + 1] - 1;
if (line >= 0 && line < p_code.size())
@@ -884,12 +884,12 @@ static void _disassemble_class(const Ref<GDScript> &p_class, const Vector<String
txt = "";
incr += 2;
} break;
- case GDFunction::OPCODE_END: {
+ case GDScriptFunction::OPCODE_END: {
txt += " end";
incr += 1;
} break;
- case GDFunction::OPCODE_ASSERT: {
+ case GDScriptFunction::OPCODE_ASSERT: {
txt += " assert ";
txt += DADDR(1);
@@ -952,15 +952,15 @@ MainLoop *test(TestType p_type) {
if (p_type == TEST_TOKENIZER) {
- GDTokenizerText tk;
+ GDScriptTokenizerText tk;
tk.set_code(code);
int line = -1;
- while (tk.get_token() != GDTokenizer::TK_EOF) {
+ while (tk.get_token() != GDScriptTokenizer::TK_EOF) {
String text;
- if (tk.get_token() == GDTokenizer::TK_IDENTIFIER)
+ if (tk.get_token() == GDScriptTokenizer::TK_IDENTIFIER)
text = "'" + tk.get_token_identifier() + "' (identifier)";
- else if (tk.get_token() == GDTokenizer::TK_CONSTANT) {
+ else if (tk.get_token() == GDScriptTokenizer::TK_CONSTANT) {
Variant c = tk.get_token_constant();
if (c.get_type() == Variant::STRING)
text = "\"" + String(c) + "\"";
@@ -968,12 +968,12 @@ MainLoop *test(TestType p_type) {
text = c;
text = text + " (" + Variant::get_type_name(c.get_type()) + " constant)";
- } else if (tk.get_token() == GDTokenizer::TK_ERROR)
+ } else if (tk.get_token() == GDScriptTokenizer::TK_ERROR)
text = "ERROR: " + tk.get_token_error();
- else if (tk.get_token() == GDTokenizer::TK_NEWLINE)
+ else if (tk.get_token() == GDScriptTokenizer::TK_NEWLINE)
text = "newline (" + itos(tk.get_token_line()) + ") + indent: " + itos(tk.get_token_line_indent());
- else if (tk.get_token() == GDTokenizer::TK_BUILT_IN_FUNC)
- text = "'" + String(GDFunctions::get_func_name(tk.get_token_built_in_func())) + "' (built-in function)";
+ else if (tk.get_token() == GDScriptTokenizer::TK_BUILT_IN_FUNC)
+ text = "'" + String(GDScriptFunctions::get_func_name(tk.get_token_built_in_func())) + "' (built-in function)";
else
text = tk.get_token_name(tk.get_token());
@@ -995,7 +995,7 @@ MainLoop *test(TestType p_type) {
if (p_type == TEST_PARSER) {
- GDParser parser;
+ GDScriptParser parser;
Error err = parser.parse(code);
if (err) {
print_line("Parse Error:\n" + itos(parser.get_error_line()) + ":" + itos(parser.get_error_column()) + ":" + parser.get_error());
@@ -1003,16 +1003,16 @@ MainLoop *test(TestType p_type) {
return NULL;
}
- const GDParser::Node *root = parser.get_parse_tree();
- ERR_FAIL_COND_V(root->type != GDParser::Node::TYPE_CLASS, NULL);
- const GDParser::ClassNode *cnode = static_cast<const GDParser::ClassNode *>(root);
+ const GDScriptParser::Node *root = parser.get_parse_tree();
+ ERR_FAIL_COND_V(root->type != GDScriptParser::Node::TYPE_CLASS, NULL);
+ const GDScriptParser::ClassNode *cnode = static_cast<const GDScriptParser::ClassNode *>(root);
_parser_show_class(cnode, 0, lines);
}
if (p_type == TEST_COMPILER) {
- GDParser parser;
+ GDScriptParser parser;
Error err = parser.parse(code);
if (err) {
@@ -1023,7 +1023,7 @@ MainLoop *test(TestType p_type) {
GDScript *script = memnew(GDScript);
- GDCompiler gdc;
+ GDScriptCompiler gdc;
err = gdc.compile(&parser, script);
if (err) {
@@ -1046,7 +1046,7 @@ MainLoop *test(TestType p_type) {
} else if (p_type == TEST_BYTECODE) {
- Vector<uint8_t> buf = GDTokenizerBuffer::parse_code_string(code);
+ Vector<uint8_t> buf = GDScriptTokenizerBuffer::parse_code_string(code);
String dst = test.get_basename() + ".gdc";
FileAccess *fw = FileAccess::open(dst, FileAccess::WRITE);
fw->store_buffer(buf.ptr(), buf.size());
diff --git a/main/tests/test_physics.cpp b/main/tests/test_physics.cpp
index f149821928..1c50470544 100644
--- a/main/tests/test_physics.cpp
+++ b/main/tests/test_physics.cpp
@@ -299,7 +299,7 @@ public:
VisualServer *vs = VisualServer::get_singleton();
/* LIGHT */
- RID lightaux = vs->light_create(VisualServer::LIGHT_DIRECTIONAL);
+ RID lightaux = vs->directional_light_create();
scenario = vs->scenario_create();
vs->light_set_shadow(lightaux, true);
light = vs->instance_create2(lightaux, scenario);
diff --git a/main/tests/test_physics_2d.cpp b/main/tests/test_physics_2d.cpp
index a746973799..7d596fbda3 100644
--- a/main/tests/test_physics_2d.cpp
+++ b/main/tests/test_physics_2d.cpp
@@ -86,7 +86,7 @@ class TestPhysics2DMainLoop : public MainLoop {
body_shape_data[Physics2DServer::SHAPE_SEGMENT].image = vs->texture_create_from_image(image);
- RID segment_shape = ps->shape_create(Physics2DServer::SHAPE_SEGMENT);
+ RID segment_shape = ps->segment_shape_create();
Rect2 sg(Point2(-16, 0), Point2(16, 0));
ps->shape_set_data(segment_shape, sg);
@@ -113,7 +113,7 @@ class TestPhysics2DMainLoop : public MainLoop {
body_shape_data[Physics2DServer::SHAPE_CIRCLE].image = vs->texture_create_from_image(image);
- RID circle_shape = ps->shape_create(Physics2DServer::SHAPE_CIRCLE);
+ RID circle_shape = ps->circle_shape_create();
ps->shape_set_data(circle_shape, 16);
body_shape_data[Physics2DServer::SHAPE_CIRCLE].shape = circle_shape;
@@ -140,7 +140,7 @@ class TestPhysics2DMainLoop : public MainLoop {
body_shape_data[Physics2DServer::SHAPE_RECTANGLE].image = vs->texture_create_from_image(image);
- RID rectangle_shape = ps->shape_create(Physics2DServer::SHAPE_RECTANGLE);
+ RID rectangle_shape = ps->rectangle_shape_create();
ps->shape_set_data(rectangle_shape, Vector2(16, 16));
body_shape_data[Physics2DServer::SHAPE_RECTANGLE].shape = rectangle_shape;
@@ -168,7 +168,7 @@ class TestPhysics2DMainLoop : public MainLoop {
body_shape_data[Physics2DServer::SHAPE_CAPSULE].image = vs->texture_create_from_image(image);
- RID capsule_shape = ps->shape_create(Physics2DServer::SHAPE_CAPSULE);
+ RID capsule_shape = ps->capsule_shape_create();
ps->shape_set_data(capsule_shape, Vector2(16, 32));
body_shape_data[Physics2DServer::SHAPE_CAPSULE].shape = capsule_shape;
@@ -182,7 +182,7 @@ class TestPhysics2DMainLoop : public MainLoop {
body_shape_data[Physics2DServer::SHAPE_CONVEX_POLYGON].image = vs->texture_create_from_image(image);
- RID convex_polygon_shape = ps->shape_create(Physics2DServer::SHAPE_CONVEX_POLYGON);
+ RID convex_polygon_shape = ps->convex_polygon_shape_create();
PoolVector<Vector2> arr;
Point2 sb(32, 32);
@@ -277,10 +277,11 @@ protected:
arr.push_back(p_normal);
arr.push_back(p_d);
- RID plane = ps->shape_create(Physics2DServer::SHAPE_LINE);
+ RID plane = ps->line_shape_create();
ps->shape_set_data(plane, arr);
- RID plane_body = ps->body_create(Physics2DServer::BODY_MODE_STATIC);
+ RID plane_body = ps->body_create();
+ ps->body_set_mode(plane_body, Physics2DServer::BODY_MODE_STATIC);
ps->body_set_space(plane_body, space);
ps->body_add_shape(plane_body, plane);
}
@@ -290,9 +291,10 @@ protected:
Physics2DServer *ps = Physics2DServer::get_singleton();
VisualServer *vs = VisualServer::get_singleton();
- RID concave = ps->shape_create(Physics2DServer::SHAPE_CONCAVE_POLYGON);
+ RID concave = ps->concave_polygon_shape_create();
ps->shape_set_data(concave, p_points);
- RID body = ps->body_create(Physics2DServer::BODY_MODE_STATIC);
+ RID body = ps->body_create();
+ ps->body_set_mode(body, Physics2DServer::BODY_MODE_STATIC);
ps->body_set_space(body, space);
ps->body_add_shape(body, concave);
ps->body_set_state(body, Physics2DServer::BODY_STATE_TRANSFORM, p_xform);
diff --git a/main/tests/test_render.cpp b/main/tests/test_render.cpp
index 1f6217928d..cbf1a57855 100644
--- a/main/tests/test_render.cpp
+++ b/main/tests/test_render.cpp
@@ -180,7 +180,7 @@ public:
*/
RID lightaux;
- lightaux = vs->light_create(VisualServer::LIGHT_DIRECTIONAL);
+ lightaux = vs->directional_light_create();
//vs->light_set_color( lightaux, VisualServer::LIGHT_COLOR_AMBIENT, Color(0.0,0.0,0.0) );
vs->light_set_color(lightaux, Color(1.0, 1.0, 1.0));
//vs->light_set_shadow( lightaux, true );
@@ -191,7 +191,7 @@ public:
vs->instance_set_transform(light, lla);
- lightaux = vs->light_create(VisualServer::LIGHT_OMNI);
+ lightaux = vs->omni_light_create();
//vs->light_set_color( lightaux, VisualServer::LIGHT_COLOR_AMBIENT, Color(0.0,0.0,1.0) );
vs->light_set_color(lightaux, Color(1.0, 1.0, 0.0));
vs->light_set_param(lightaux, VisualServer::LIGHT_PARAM_RANGE, 4);
diff --git a/methods.py b/methods.py
index f1ef95f6fe..2be73f02d2 100644
--- a/methods.py
+++ b/methods.py
@@ -1149,24 +1149,28 @@ def build_gles3_headers(target, source, env):
build_legacygl_header(str(x), include="drivers/gles3/shader_gles3.h", class_suffix="GLES3", output_attribs=True)
-def update_version():
+def add_module_version_string(self,s):
+ self.module_version_string += "." + s
- rev = "custom_build"
+def update_version(module_version_string=""):
+
+ build_name = "custom_build"
+ if (os.getenv("BUILD_NAME") != None):
+ build_name = os.getenv("BUILD_NAME")
+ print("Using custom build name: " + build_name)
- if (os.getenv("BUILD_REVISION") != None):
- rev = os.getenv("BUILD_REVISION")
- print("Using custom revision: " + rev)
import version
f = open("core/version_generated.gen.h", "w")
- f.write("#define VERSION_SHORT_NAME " + str(version.short_name) + "\n")
- f.write("#define VERSION_NAME " + str(version.name) + "\n")
+ f.write("#define VERSION_SHORT_NAME \"" + str(version.short_name) + "\"\n")
+ 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_REVISION " + str(rev) + "\n")
- f.write("#define VERSION_STATUS " + str(version.status) + "\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")
import datetime
f.write("#define VERSION_YEAR " + str(datetime.datetime.now().year) + "\n")
f.close()
@@ -1289,21 +1293,15 @@ def detect_modules():
// modules.cpp - THIS FILE IS GENERATED, DO NOT EDIT!!!!!!!
#include "register_module_types.h"
-
""" + includes_cpp + """
void register_module_types() {
-
""" + register_cpp + """
-
}
void unregister_module_types() {
-
""" + unregister_cpp + """
-
}
-
"""
f = open("modules/register_module_types.gen.cpp", "w")
@@ -1360,6 +1358,10 @@ def win32_spawn(sh, escape, cmd, args, spawnenv):
return exit_code
"""
+def android_add_flat_dir(self, dir):
+ if (dir not in self.android_flat_dirs):
+ self.android_flat_dirs.append(dir)
+
def android_add_maven_repository(self, url):
if (url not in self.android_maven_repos):
self.android_maven_repos.append(url)
@@ -1684,6 +1686,17 @@ def find_visual_c_batch_file(env):
(host_platform, target_platform,req_target_platform) = get_host_target(env)
return find_batch_file(env, version, host_platform, target_platform)[0]
+def generate_cpp_hint_file(filename):
+ import os.path
+ if os.path.isfile(filename):
+ # Don't overwrite an existing hint file since the user may have customized it.
+ pass
+ else:
+ try:
+ fd = open(filename, "w")
+ fd.write("#define GDCLASS(m_class, m_inherits)\n")
+ except IOError:
+ print("Could not write cpp.hint file.")
def generate_vs_project(env, num_jobs):
batch_file = find_visual_c_batch_file(env)
@@ -1706,9 +1719,13 @@ def generate_vs_project(env, num_jobs):
env.AddToVSProject(env.servers_sources)
env.AddToVSProject(env.editor_sources)
- env['MSVSBUILDCOM'] = build_commandline('scons --directory=$(ProjectDir) platform=windows target=$(Configuration) tools=!tools! -j' + str(num_jobs))
- env['MSVSREBUILDCOM'] = build_commandline('scons --directory=$(ProjectDir) platform=windows target=$(Configuration) tools=!tools! vsproj=yes -j' + str(num_jobs))
- env['MSVSCLEANCOM'] = build_commandline('scons --directory=$(ProjectDir) --clean platform=windows target=$(Configuration) tools=!tools! -j' + str(num_jobs))
+ # windows allows us to have spaces in paths, so we need
+ # to double quote off the directory. However, the path ends
+ # in a backslash, so we need to remove this, lest it escape the
+ # last double quote off, confusing MSBuild
+ env['MSVSBUILDCOM'] = build_commandline('scons --directory="$(ProjectDir.TrimEnd(\'\\\'))" platform=windows progress=no target=$(Configuration) tools=!tools! -j' + str(num_jobs))
+ env['MSVSREBUILDCOM'] = build_commandline('scons --directory="$(ProjectDir.TrimEnd(\'\\\'))" platform=windows progress=no target=$(Configuration) tools=!tools! vsproj=yes -j' + str(num_jobs))
+ env['MSVSCLEANCOM'] = build_commandline('scons --directory="$(ProjectDir.TrimEnd(\'\\\'))" --clean platform=windows progress=no target=$(Configuration) tools=!tools! -j' + str(num_jobs))
# This version information (Win32, x64, Debug, Release, Release_Debug seems to be
# required for Visual Studio to understand that it needs to generate an NMAKE
diff --git a/misc/dist/docker/README.md b/misc/dist/docker/README.md
index 7f10b46ad8..71aac8a77c 100644
--- a/misc/dist/docker/README.md
+++ b/misc/dist/docker/README.md
@@ -1,40 +1,40 @@
-## A Docker image to build Linux, Windows and Android godot binaries.
-
-The main reason to write this, is to provide a simple way in all platforms to integrate external godot modules and build a custom version of godot.
-
-## usage
-1. Install docker on Linux or docker toolbox on Windows or Mac.
-2. Open a terminal on linux or "Docker Quickstart Terminal" on Windows or Mac.
-3. Run command:
- - Linux: `cd`
- - Windows: `cd /c/Users/YOUR_USERNAME`
- - Mac: `cd /Users/YOUR_USERNAME`
-4. Get godot source code: `git clone https://github.com/godotengine/godot.git`
-5. Run command: `cd godot/tools/docker`
-6. Run command: `docker build -t godot .`(In Linux run Docker commands with `sudo` or add your user to docker group before run the Docker commands). The godot docker image will be build after a while.
-7. Run command:
- - Linux: `docker run -it --name=godot-dev -v /home/YOUR_USERNAME/godot:/godot-dev/godot godot`
- - Windows: `docker run -it --name=godot-dev -v /c/Users/YOUR_USERNAME/godot:/godot-dev/godot godot`
- - Mac: `docker run -it --name=godot-dev -v /Users/YOUR_USERNAME/godot:/godot-dev/godot godot`
- You are in the godot-dev container and /godot-dev directory now.
-8. Run `./install-android-tools` to download and install all android development tools.
-9. Run command: `source ~/.bashrc`
-10. Run command: `cd godot`
-11. Run command: `scons p=android target=release` to test everything is ok. You can set platform to x11, windows, android, haiku and server.
-
-After use and exit, you can use this environment again by open terminal and type commands: `docker start godot-dev && docker attach godot-dev`.
-
-### Windows and Mac stuffs:
-
-- Speed up compilation:
- - Exit from container.
- - Run command: `docker-machine stop`
- - Open "Oracle VM VirtualBox".
- - In settings of default VM increase CPU cores and RAM to suitable values.
- - Run command: `docker-machine start`
- - Run command: `docker start godot-dev && docker attach godot-dev`
-
-- ssh to VM(can be useful sometimes):
- - `docker-machine ssh`
-
-Check docker and boot2docker projects for more details.
+## A Docker image to build Linux, Windows and Android godot binaries.
+
+The main reason to write this, is to provide a simple way in all platforms to integrate external godot modules and build a custom version of godot.
+
+## usage
+1. Install docker on Linux or docker toolbox on Windows or Mac.
+2. Open a terminal on linux or "Docker Quickstart Terminal" on Windows or Mac.
+3. Run command:
+ - Linux: `cd`
+ - Windows: `cd /c/Users/YOUR_USERNAME`
+ - Mac: `cd /Users/YOUR_USERNAME`
+4. Get godot source code: `git clone https://github.com/godotengine/godot.git`
+5. Run command: `cd godot/tools/docker`
+6. Run command: `docker build -t godot .`(In Linux run Docker commands with `sudo` or add your user to docker group before run the Docker commands). The godot docker image will be build after a while.
+7. Run command:
+ - Linux: `docker run -it --name=godot-dev -v /home/YOUR_USERNAME/godot:/godot-dev/godot godot`
+ - Windows: `docker run -it --name=godot-dev -v /c/Users/YOUR_USERNAME/godot:/godot-dev/godot godot`
+ - Mac: `docker run -it --name=godot-dev -v /Users/YOUR_USERNAME/godot:/godot-dev/godot godot`
+ You are in the godot-dev container and /godot-dev directory now.
+8. Run `./install-android-tools` to download and install all android development tools.
+9. Run command: `source ~/.bashrc`
+10. Run command: `cd godot`
+11. Run command: `scons p=android target=release` to test everything is ok. You can set platform to x11, windows, android, haiku and server.
+
+After use and exit, you can use this environment again by open terminal and type commands: `docker start godot-dev && docker attach godot-dev`.
+
+### Windows and Mac stuffs:
+
+- Speed up compilation:
+ - Exit from container.
+ - Run command: `docker-machine stop`
+ - Open "Oracle VM VirtualBox".
+ - In settings of default VM increase CPU cores and RAM to suitable values.
+ - Run command: `docker-machine start`
+ - Run command: `docker start godot-dev && docker attach godot-dev`
+
+- ssh to VM(can be useful sometimes):
+ - `docker-machine ssh`
+
+Check docker and boot2docker projects for more details.
diff --git a/misc/dist/html/default.html b/misc/dist/html/default.html
index 9fae34f97e..0f78fc640e 100644
--- a/misc/dist/html/default.html
+++ b/misc/dist/html/default.html
@@ -225,12 +225,11 @@ $GODOT_HEAD_INCLUDE
<script type="text/javascript" src="$GODOT_BASENAME.js"></script>
<script type="text/javascript">//<![CDATA[
- var game = new Engine;
+ var engine = new Engine;
(function() {
const BASENAME = '$GODOT_BASENAME';
- const MEMORY_SIZE = $GODOT_TOTAL_MEMORY;
const DEBUG_ENABLED = $GODOT_DEBUG_ENABLED;
const INDETERMINATE_STATUS_STEP_MS = 100;
@@ -246,8 +245,7 @@ $GODOT_HEAD_INCLUDE
var indeterminiateStatusAnimationId = 0;
setStatusMode('indeterminate');
- game.setCanvas(canvas);
- game.setAsmjsMemorySize(MEMORY_SIZE);
+ engine.setCanvas(canvas);
function setStatusMode(mode) {
@@ -302,7 +300,7 @@ $GODOT_HEAD_INCLUDE
});
};
- game.setProgressFunc((current, total) => {
+ engine.setProgressFunc((current, total) => {
if (total > 0) {
statusProgressInner.style.width = current/total * 100 + '%';
@@ -332,10 +330,6 @@ $GODOT_HEAD_INCLUDE
outputRoot.style.display = 'block';
function print(text) {
- if (arguments.length > 1) {
- text = Array.prototype.slice.call(arguments).join(" ");
- }
- if (text.length <= 0) return;
while (outputScroll.childElementCount >= OUTPUT_MSG_COUNT_MAX) {
outputScroll.firstChild.remove();
}
@@ -356,26 +350,31 @@ $GODOT_HEAD_INCLUDE
};
function printError(text) {
- print('**ERROR**' + ":", text);
+ if (!text.startsWith('**ERROR**: ')) {
+ text = '**ERROR**: ' + text;
+ }
+ print(text);
}
- game.setStdoutFunc(text => {
+ engine.setStdoutFunc(text => {
print(text);
console.log(text);
});
- game.setStderrFunc(text => {
+ engine.setStderrFunc(text => {
printError(text);
console.warn(text);
});
}
- game.start(BASENAME + '.pck').then(() => {
+ engine.startGame(BASENAME + '.pck').then(() => {
setStatusMode('hidden');
initializing = false;
}, err => {
- if (DEBUG_ENABLED)
+ if (DEBUG_ENABLED) {
printError(err.message);
+ console.warn(err);
+ }
setStatusNotice(err.message);
setStatusMode('notice');
initializing = false;
diff --git a/misc/dist/ios_xcode/godot.iphone.debug.fat b/misc/dist/ios_xcode/godot.iphone.debug.fat
deleted file mode 100755
index e69de29bb2..0000000000
--- a/misc/dist/ios_xcode/godot.iphone.debug.fat
+++ /dev/null
diff --git a/misc/dist/ios_xcode/godot.iphone.release.arm b/misc/dist/ios_xcode/godot.iphone.release.arm
deleted file mode 100755
index e69de29bb2..0000000000
--- a/misc/dist/ios_xcode/godot.iphone.release.arm
+++ /dev/null
diff --git a/misc/dist/ios_xcode/godot.iphone.release.arm64 b/misc/dist/ios_xcode/godot.iphone.release.arm64
deleted file mode 100755
index e69de29bb2..0000000000
--- a/misc/dist/ios_xcode/godot.iphone.release.arm64
+++ /dev/null
diff --git a/misc/dist/ios_xcode/godot.iphone.release.fat b/misc/dist/ios_xcode/godot.iphone.release.fat
deleted file mode 100755
index e69de29bb2..0000000000
--- a/misc/dist/ios_xcode/godot.iphone.release.fat
+++ /dev/null
diff --git a/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj b/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj
index 3f2db94193..ab15e35f63 100644
--- a/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj
+++ b/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj
@@ -8,8 +8,20 @@
/* Begin PBXBuildFile section */
1F1575721F582BE20003B888 /* dylibs in Resources */ = {isa = PBXBuildFile; fileRef = 1F1575711F582BE20003B888 /* dylibs */; };
+ 1FE926991FBBF85400F53A6F /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FE926961FBBF7D400F53A6F /* SystemConfiguration.framework */; };
+ 1FE9269A1FBBF85F00F53A6F /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FE926951FBBF7C400F53A6F /* Security.framework */; };
+ 1FE9269B1FBBF86200F53A6F /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FE926941FBBF7BD00F53A6F /* QuartzCore.framework */; };
+ 1FE9269C1FBBF86500F53A6F /* MediaPlayer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FE926931FBBF7AD00F53A6F /* MediaPlayer.framework */; };
+ 1FE9269D1FBBF86600F53A6F /* GameController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FE926921FBBF7A000F53A6F /* GameController.framework */; };
+ 1FE9269E1FBBF86900F53A6F /* CoreMotion.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FE926911FBBF79500F53A6F /* CoreMotion.framework */; };
+ 1FE9269F1FBBF86B00F53A6F /* CoreMedia.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FE926901FBBF78E00F53A6F /* CoreMedia.framework */; };
+ 1FE926A01FBBF86D00F53A6F /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FE9268E1FBBF77300F53A6F /* AudioToolbox.framework */; };
+ 1FE926A11FBBF86D00F53A6F /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FE9268F1FBBF77F00F53A6F /* CoreAudio.framework */; };
+ DEADBEEF2F582BE20003B888 /* $binary.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DEADBEEF1F582BE20003B888 /* $binary.a */; };
+ 1FF8DBB11FBA9DE1009DE660 /* dummy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1FF8DBB01FBA9DE1009DE660 /* dummy.cpp */; };
1FF4C1851F584E3F00A41E41 /* GameKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FF4C1841F584E3F00A41E41 /* GameKit.framework */; };
1FF4C1871F584E5600A41E41 /* StoreKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FF4C1861F584E5600A41E41 /* StoreKit.framework */; };
+ 1FF4C1871F584E7600A41E41 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FF4C1881F584E7600A41E41 /* StoreKit.framework */; };
D07CD43F1C5D573600B7FB28 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = D07CD4331C5D573600B7FB28 /* Default-568h@2x.png */; };
D07CD4411C5D573600B7FB28 /* Default-667h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = D07CD4351C5D573600B7FB28 /* Default-667h@2x.png */; };
D07CD4421C5D573600B7FB28 /* Default-Portrait-736h@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = D07CD4361C5D573600B7FB28 /* Default-Portrait-736h@3x.png */; };
@@ -26,14 +38,25 @@
D0BCFE4018AEBDA2004A7AAE /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0BCFE3F18AEBDA2004A7AAE /* OpenGLES.framework */; };
D0BCFE4618AEBDA2004A7AAE /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = D0BCFE4418AEBDA2004A7AAE /* InfoPlist.strings */; };
D0BCFE7818AEBFEB004A7AAE /* $binary.pck in Resources */ = {isa = PBXBuildFile; fileRef = D0BCFE7718AEBFEB004A7AAE /* $binary.pck */; };
- D0BCFE7A18AEC06A004A7AAE /* $binary.iphone in Resources */ = {isa = PBXBuildFile; fileRef = D0BCFE7918AEC06A004A7AAE /* $binary.iphone */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
- 1F1575711F582BE20003B888 /* dylibs */ = {isa = PBXFileReference; lastKnownFileType = folder; name = dylibs; path = dylibs; sourceTree = "<group>"; };
+ 1F1575711F582BE20003B888 /* dylibs */ = {isa = PBXFileReference; lastKnownFileType = folder; name = dylibs; path = "$binary/dylibs"; sourceTree = "<group>"; };
+ 1FE9268E1FBBF77300F53A6F /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; };
+ 1FE9268F1FBBF77F00F53A6F /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = System/Library/Frameworks/CoreAudio.framework; sourceTree = SDKROOT; };
+ 1FE926901FBBF78E00F53A6F /* CoreMedia.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMedia.framework; path = System/Library/Frameworks/CoreMedia.framework; sourceTree = SDKROOT; };
+ 1FE926911FBBF79500F53A6F /* CoreMotion.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMotion.framework; path = System/Library/Frameworks/CoreMotion.framework; sourceTree = SDKROOT; };
+ 1FE926921FBBF7A000F53A6F /* GameController.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameController.framework; path = System/Library/Frameworks/GameController.framework; sourceTree = SDKROOT; };
+ 1FE926931FBBF7AD00F53A6F /* MediaPlayer.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MediaPlayer.framework; path = System/Library/Frameworks/MediaPlayer.framework; sourceTree = SDKROOT; };
+ 1FE926941FBBF7BD00F53A6F /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
+ 1FE926951FBBF7C400F53A6F /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
+ 1FE926961FBBF7D400F53A6F /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
+ DEADBEEF1F582BE20003B888 /* $binary.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = godot; path = "$binary.a"; sourceTree = "<group>"; };
1FF4C1841F584E3F00A41E41 /* GameKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameKit.framework; path = System/Library/Frameworks/GameKit.framework; sourceTree = SDKROOT; };
1FF4C1861F584E5600A41E41 /* StoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreKit.framework; path = System/Library/Frameworks/StoreKit.framework; sourceTree = SDKROOT; };
+ 1FF4C1881F584E7600A41E41 /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; };
1FF4C1881F584E6300A41E41 /* $binary.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = $binary.entitlements; sourceTree = "<group>"; };
+ 1FF8DBB01FBA9DE1009DE660 /* dummy.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = dummy.cpp; sourceTree = "<group>"; };
D07CD4331C5D573600B7FB28 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = "<group>"; };
D07CD4351C5D573600B7FB28 /* Default-667h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-667h@2x.png"; sourceTree = "<group>"; };
D07CD4361C5D573600B7FB28 /* Default-Portrait-736h@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-Portrait-736h@3x.png"; sourceTree = "<group>"; };
@@ -51,24 +74,35 @@
D0BCFE3F18AEBDA2004A7AAE /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; };
D0BCFE4318AEBDA2004A7AAE /* $binary-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "$binary-Info.plist"; sourceTree = "<group>"; };
D0BCFE4518AEBDA2004A7AAE /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
- D0BCFE4918AEBDA2004A7AAE /* $binary-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "$binary-Prefix.pch"; sourceTree = "<group>"; };
- D0BCFE6118AEBDA3004A7AAE /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
D0BCFE7718AEBFEB004A7AAE /* $binary.pck */ = {isa = PBXFileReference; lastKnownFileType = file; path = $binary.pck; sourceTree = "<group>"; };
- D0BCFE7918AEC06A004A7AAE /* $binary.iphone */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.executable"; path = $binary.iphone; sourceTree = "<group>"; };
/* End PBXFileReference section */
+ $additional_pbx_files
+
/* Begin PBXFrameworksBuildPhase section */
D0BCFE3118AEBDA2004A7AAE /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
+ D0BCFE3A18AEBDA2004A7AAE /* CoreGraphics.framework in Frameworks */,
+ 1FE926991FBBF85400F53A6F /* SystemConfiguration.framework in Frameworks */,
+ 1FE9269A1FBBF85F00F53A6F /* Security.framework in Frameworks */,
+ 1FE9269B1FBBF86200F53A6F /* QuartzCore.framework in Frameworks */,
+ 1FE9269C1FBBF86500F53A6F /* MediaPlayer.framework in Frameworks */,
+ 1FE9269D1FBBF86600F53A6F /* GameController.framework in Frameworks */,
+ 1FE9269E1FBBF86900F53A6F /* CoreMotion.framework in Frameworks */,
+ 1FE9269F1FBBF86B00F53A6F /* CoreMedia.framework in Frameworks */,
+ 1FE926A11FBBF86D00F53A6F /* CoreAudio.framework in Frameworks */,
+ 1FE926A01FBBF86D00F53A6F /* AudioToolbox.framework in Frameworks */,
D0BCFE4018AEBDA2004A7AAE /* OpenGLES.framework in Frameworks */,
1FF4C1871F584E5600A41E41 /* StoreKit.framework in Frameworks */,
- D0BCFE3A18AEBDA2004A7AAE /* CoreGraphics.framework in Frameworks */,
+ 1FF4C1871F584E7600A41E41 /* AVFoundation.framework in Frameworks */,
D0BCFE3C18AEBDA2004A7AAE /* UIKit.framework in Frameworks */,
1FF4C1851F584E3F00A41E41 /* GameKit.framework in Frameworks */,
D0BCFE3E18AEBDA2004A7AAE /* GLKit.framework in Frameworks */,
D0BCFE3818AEBDA2004A7AAE /* Foundation.framework in Frameworks */,
+ DEADBEEF2F582BE20003B888 /* $binary.a */,
+ $additional_pbx_frameworks_build
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -79,11 +113,11 @@
isa = PBXGroup;
children = (
1F1575711F582BE20003B888 /* dylibs */,
- D0BCFE7918AEC06A004A7AAE /* $binary.iphone */,
D0BCFE7718AEBFEB004A7AAE /* $binary.pck */,
D0BCFE4118AEBDA2004A7AAE /* $binary */,
D0BCFE3618AEBDA2004A7AAE /* Frameworks */,
D0BCFE3518AEBDA2004A7AAE /* Products */,
+ $additional_pbx_resources_refs
);
sourceTree = "<group>";
};
@@ -98,14 +132,25 @@
D0BCFE3618AEBDA2004A7AAE /* Frameworks */ = {
isa = PBXGroup;
children = (
+ 1FE926961FBBF7D400F53A6F /* SystemConfiguration.framework */,
+ 1FE926951FBBF7C400F53A6F /* Security.framework */,
+ 1FE926941FBBF7BD00F53A6F /* QuartzCore.framework */,
+ 1FE926931FBBF7AD00F53A6F /* MediaPlayer.framework */,
+ 1FE926921FBBF7A000F53A6F /* GameController.framework */,
+ 1FE926911FBBF79500F53A6F /* CoreMotion.framework */,
+ 1FE926901FBBF78E00F53A6F /* CoreMedia.framework */,
+ 1FE9268F1FBBF77F00F53A6F /* CoreAudio.framework */,
+ 1FE9268E1FBBF77300F53A6F /* AudioToolbox.framework */,
1FF4C1861F584E5600A41E41 /* StoreKit.framework */,
1FF4C1841F584E3F00A41E41 /* GameKit.framework */,
+ 1FF4C1881F584E7600A41E41 /* AVFoundation.framework */,
D0BCFE3718AEBDA2004A7AAE /* Foundation.framework */,
D0BCFE3918AEBDA2004A7AAE /* CoreGraphics.framework */,
D0BCFE3B18AEBDA2004A7AAE /* UIKit.framework */,
D0BCFE3D18AEBDA2004A7AAE /* GLKit.framework */,
D0BCFE3F18AEBDA2004A7AAE /* OpenGLES.framework */,
- D0BCFE6118AEBDA3004A7AAE /* XCTest.framework */,
+ DEADBEEF1F582BE20003B888 /* $binary.a */,
+ $additional_pbx_frameworks_refs
);
name = Frameworks;
sourceTree = "<group>";
@@ -124,6 +169,7 @@
D07CD43C1C5D573600B7FB28 /* Default-Portrait-1366h@2x.png */,
D07CD44D1C5D589C00B7FB28 /* Images.xcassets */,
D0BCFE4218AEBDA2004A7AAE /* Supporting Files */,
+ 1FF8DBB01FBA9DE1009DE660 /* dummy.cpp */,
);
path = $binary;
sourceTree = "<group>";
@@ -133,7 +179,6 @@
children = (
D0BCFE4318AEBDA2004A7AAE /* $binary-Info.plist */,
D0BCFE4418AEBDA2004A7AAE /* InfoPlist.strings */,
- D0BCFE4918AEBDA2004A7AAE /* $binary-Prefix.pch */,
);
name = "Supporting Files";
sourceTree = "<group>";
@@ -218,7 +263,7 @@
D07CD4421C5D573600B7FB28 /* Default-Portrait-736h@3x.png in Resources */,
D07CD4481C5D573600B7FB28 /* Default-Portrait-1366h@2x.png in Resources */,
D0BCFE4618AEBDA2004A7AAE /* InfoPlist.strings in Resources */,
- D0BCFE7A18AEC06A004A7AAE /* $binary.iphone in Resources */,
+ $additional_pbx_resources_build
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -229,6 +274,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
+ 1FF8DBB11FBA9DE1009DE660 /* dummy.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -250,7 +296,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
- ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)";
+ ARCHS = "$godot_archs";
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
@@ -265,6 +311,8 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "$code_sign_identity_debug";
COPY_PHASE_STRIP = NO;
+ ENABLE_BITCODE = NO;
+ "FRAMEWORK_SEARCH_PATHS[arch=*]" = "$binary";
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0;
@@ -280,7 +328,7 @@
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
- ONLY_ACTIVE_ARCH = YES;
+ OTHER_LDFLAGS = "$linker_flags";
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
};
@@ -290,7 +338,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
- ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)";
+ ARCHS = "$godot_archs";
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
@@ -306,6 +354,8 @@
CODE_SIGN_IDENTITY = "$code_sign_identity_release";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "$code_sign_identity_release";
COPY_PHASE_STRIP = YES;
+ ENABLE_BITCODE = NO;
+ "FRAMEWORK_SEARCH_PATHS[arch=*]" = "$binary";
ENABLE_NS_ASSERTIONS = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
@@ -315,6 +365,7 @@
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
+ OTHER_LDFLAGS = "$linker_flags";
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
@@ -324,26 +375,23 @@
D0BCFE7218AEBDA3004A7AAE /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
- ARCHS = "$(ARCHS_STANDARD)";
+ ARCHS = "$godot_archs";
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = $binary/$binary.entitlements;
CODE_SIGN_IDENTITY = "$code_sign_identity_debug";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "$code_sign_identity_debug";
CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)";
DEVELOPMENT_TEAM = $team_id;
- GCC_PRECOMPILE_PREFIX_HEADER = YES;
- GCC_PREFIX_HEADER = "$binary/$binary-Prefix.pch";
INFOPLIST_FILE = "$binary/$binary-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
- "$(PROJECT_DIR)/dylibs",
);
PRODUCT_BUNDLE_IDENTIFIER = $identifier;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE = "$provisioning_profile_uuid_debug";
TARGETED_DEVICE_FAMILY = "1,2";
- VALID_ARCHS = "armv7 armv7s";
+ VALID_ARCHS = "armv7 armv7s arm64 i386 x86_64";
WRAPPER_EXTENSION = app;
};
name = Debug;
@@ -351,26 +399,23 @@
D0BCFE7318AEBDA3004A7AAE /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
- ARCHS = "$(ARCHS_STANDARD)";
+ ARCHS = "$godot_archs";
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = $binary/$binary.entitlements;
CODE_SIGN_IDENTITY = "$code_sign_identity_release";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "$code_sign_identity_release";
CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)";
DEVELOPMENT_TEAM = $team_id;
- GCC_PRECOMPILE_PREFIX_HEADER = YES;
- GCC_PREFIX_HEADER = "$binary/$binary-Prefix.pch";
INFOPLIST_FILE = "$binary/$binary-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
- "$(PROJECT_DIR)/dylibs",
);
PRODUCT_BUNDLE_IDENTIFIER = $identifier;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE = "$provisioning_profile_uuid_release";
TARGETED_DEVICE_FAMILY = "1,2";
- VALID_ARCHS = "armv7 armv7s";
+ VALID_ARCHS = "armv7 armv7s arm64 i386 x86_64";
WRAPPER_EXTENSION = app;
};
name = Release;
diff --git a/misc/dist/ios_xcode/godot_ios.xcodeproj/xcshareddata/xcschemes/godot_ios.xcscheme b/misc/dist/ios_xcode/godot_ios.xcodeproj/xcshareddata/xcschemes/godot_ios.xcscheme
index 3f0df5c437..b6beeb012f 100644
--- a/misc/dist/ios_xcode/godot_ios.xcodeproj/xcshareddata/xcschemes/godot_ios.xcscheme
+++ b/misc/dist/ios_xcode/godot_ios.xcodeproj/xcshareddata/xcschemes/godot_ios.xcscheme
@@ -23,7 +23,7 @@
</BuildActionEntries>
</BuildAction>
<TestAction
- buildConfiguration = "Development"
+ buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
@@ -42,7 +42,7 @@
</AdditionalOptions>
</TestAction>
<LaunchAction
- buildConfiguration = "Development"
+ buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
@@ -67,7 +67,7 @@
</AdditionalOptions>
</LaunchAction>
<ProfileAction
- buildConfiguration = "Development"
+ buildConfiguration = "Debug"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
@@ -84,10 +84,10 @@
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
- buildConfiguration = "Development">
+ buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
- buildConfiguration = "Development"
+ buildConfiguration = "Debug"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
diff --git a/misc/dist/ios_xcode/godot_ios/dummy.cpp b/misc/dist/ios_xcode/godot_ios/dummy.cpp
new file mode 100644
index 0000000000..78ec87fc10
--- /dev/null
+++ b/misc/dist/ios_xcode/godot_ios/dummy.cpp
@@ -0,0 +1 @@
+$cpp_code \ No newline at end of file
diff --git a/misc/dist/ios_xcode/godot_ios/dylibs/empty b/misc/dist/ios_xcode/godot_ios/dylibs/empty
new file mode 100644
index 0000000000..4b5614362b
--- /dev/null
+++ b/misc/dist/ios_xcode/godot_ios/dylibs/empty
@@ -0,0 +1 @@
+Dummy file to make dylibs folder exported \ No newline at end of file
diff --git a/misc/dist/ios_xcode/export_options.plist b/misc/dist/ios_xcode/godot_ios/export_options.plist
index 86d89a6e42..3878a4dbe6 100644
--- a/misc/dist/ios_xcode/export_options.plist
+++ b/misc/dist/ios_xcode/godot_ios/export_options.plist
@@ -4,7 +4,17 @@
<dict>
<key>method</key>
<string>$export_method</string>
+
<key>teamID</key>
<string>$team_id</string>
+
+ <key>provisioningProfiles</key>
+ <dict>
+ <key>$identifier</key>
+ <string>$provisioning_profile_uuid</string>
+ </dict>
+
+ <key>compileBitcode</key>
+ <false/>
</dict>
</plist> \ No newline at end of file
diff --git a/misc/dist/ios_xcode/godot_ios/godot_ios-Info.plist b/misc/dist/ios_xcode/godot_ios/godot_ios-Info.plist
index 1531a41bd0..70932c1943 100644
--- a/misc/dist/ios_xcode/godot_ios/godot_ios-Info.plist
+++ b/misc/dist/ios_xcode/godot_ios/godot_ios-Info.plist
@@ -7,7 +7,7 @@
<key>CFBundleDisplayName</key>
<string>$name</string>
<key>CFBundleExecutable</key>
- <string>$binary.iphone</string>
+ <string>$binary</string>
<key>CFBundleIcons</key>
<dict/>
<key>CFBundleIcons~ipad</key>
@@ -47,5 +47,6 @@
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
+ $additional_plist_content
</dict>
</plist>
diff --git a/misc/dist/ios_xcode/godot.iphone.debug.arm b/misc/dist/ios_xcode/libgodot.iphone.debug.fat.a
index e69de29bb2..e69de29bb2 100755..100644
--- a/misc/dist/ios_xcode/godot.iphone.debug.arm
+++ b/misc/dist/ios_xcode/libgodot.iphone.debug.fat.a
diff --git a/misc/dist/ios_xcode/godot.iphone.debug.arm64 b/misc/dist/ios_xcode/libgodot.iphone.release.fat.a
index e69de29bb2..e69de29bb2 100755..100644
--- a/misc/dist/ios_xcode/godot.iphone.debug.arm64
+++ b/misc/dist/ios_xcode/libgodot.iphone.release.fat.a
diff --git a/misc/dist/uwp_template/AppxManifest.xml b/misc/dist/uwp_template/AppxManifest.xml
index d5e653708c..cf26387f22 100644
--- a/misc/dist/uwp_template/AppxManifest.xml
+++ b/misc/dist/uwp_template/AppxManifest.xml
@@ -1,32 +1,32 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" IgnorableNamespaces="uap mp build" xmlns:build="http://schemas.microsoft.com/developer/appx/2015/build">
- <Identity Name="$identity_name$" Publisher="$publisher$" Version="$version_string$" ProcessorArchitecture="$architecture$" />
- <mp:PhoneIdentity PhoneProductId="$product_guid$" PhonePublisherId="$publisher_guid$" />
- <Properties>
- <DisplayName>$display_name$</DisplayName>
- <PublisherDisplayName>$publisher_display_name$</PublisherDisplayName>
- <Logo>Assets\StoreLogo.png</Logo>
- </Properties>
- <Dependencies>
- <TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.10240.0" MaxVersionTested="10.0.14393.0" />
- <PackageDependency Name="Microsoft.VCLibs.140.00" MinVersion="14.0.24123.0" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" />
- </Dependencies>
- <Resources>
- <Resource Language="EN-US" />
- </Resources>
- <Applications>
- <Application Id="App" Executable="godot.uwp.exe" EntryPoint="GodotUWP.App">
- <uap:VisualElements DisplayName="$display_name$" Square150x150Logo="Assets\Square150x150Logo.png" Square44x44Logo="Assets\Square44x44Logo.png" Description="$app_description$" BackgroundColor="$bg_color$">
- <uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png" Square310x310Logo="Assets\Square310x310Logo.png" Square71x71Logo="Assets\Square71x71Logo.png" ShortName="$short_name$">
- $name_on_tiles$
- </uap:DefaultTile>
- <uap:SplashScreen Image="Assets\SplashScreen.png" />
- $rotation_preference$
- </uap:VisualElements>
- </Application>
- </Applications>
- $capabilities_place$
- <build:Metadata>
- <build:Item Name="GodotEngine" Version="$godot_version$" />
- </build:Metadata>
+<?xml version="1.0" encoding="utf-8"?>
+<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" IgnorableNamespaces="uap mp build" xmlns:build="http://schemas.microsoft.com/developer/appx/2015/build">
+ <Identity Name="$identity_name$" Publisher="$publisher$" Version="$version_string$" ProcessorArchitecture="$architecture$" />
+ <mp:PhoneIdentity PhoneProductId="$product_guid$" PhonePublisherId="$publisher_guid$" />
+ <Properties>
+ <DisplayName>$display_name$</DisplayName>
+ <PublisherDisplayName>$publisher_display_name$</PublisherDisplayName>
+ <Logo>Assets\StoreLogo.png</Logo>
+ </Properties>
+ <Dependencies>
+ <TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.10240.0" MaxVersionTested="10.0.14393.0" />
+ <PackageDependency Name="Microsoft.VCLibs.140.00" MinVersion="14.0.24123.0" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" />
+ </Dependencies>
+ <Resources>
+ <Resource Language="EN-US" />
+ </Resources>
+ <Applications>
+ <Application Id="App" Executable="godot.uwp.exe" EntryPoint="GodotUWP.App">
+ <uap:VisualElements DisplayName="$display_name$" Square150x150Logo="Assets\Square150x150Logo.png" Square44x44Logo="Assets\Square44x44Logo.png" Description="$app_description$" BackgroundColor="$bg_color$">
+ <uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png" Square310x310Logo="Assets\Square310x310Logo.png" Square71x71Logo="Assets\Square71x71Logo.png" ShortName="$short_name$">
+ $name_on_tiles$
+ </uap:DefaultTile>
+ <uap:SplashScreen Image="Assets\SplashScreen.png" />
+ $rotation_preference$
+ </uap:VisualElements>
+ </Application>
+ </Applications>
+ $capabilities_place$
+ <build:Metadata>
+ <build:Item Name="GodotEngine" Version="$godot_version$" />
+ </build:Metadata>
</Package> \ No newline at end of file
diff --git a/misc/travis/android-tools-linux.sh b/misc/travis/android-tools-linux.sh
new file mode 100755
index 0000000000..04fb2eee21
--- /dev/null
+++ b/misc/travis/android-tools-linux.sh
@@ -0,0 +1,107 @@
+#!/bin/bash
+
+# SDK
+# https://dl.google.com/android/repository/sdk-tools-linux-3859397.zip
+# SHA-256 444e22ce8ca0f67353bda4b85175ed3731cae3ffa695ca18119cbacef1c1bea0
+# latest version available here: https://developer.android.com/studio/index.html
+
+# NDK
+# https://dl.google.com/android/repository/android-ndk-r15c-linux-x86_64.zip
+# SHA-1 0bf02d4e8b85fd770fd7b9b2cdec57f9441f27a2
+# latest version available here: https://developer.android.com/ndk/downloads/index.html
+
+BASH_RC=~/.bashrc
+GODOT_BUILD_TOOLS_PATH=./godot-dev/build-tools
+mkdir -p $GODOT_BUILD_TOOLS_PATH
+cd $GODOT_BUILD_TOOLS_PATH
+
+ANDROID_BASE_URL=http://dl.google.com/android/repository
+
+ANDROID_SDK_RELEASE=3859397
+ANDROID_SDK_DIR=android-sdk
+ANDROID_SDK_FILENAME=sdk-tools-linux-$ANDROID_SDK_RELEASE.zip
+ANDROID_SDK_URL=$ANDROID_BASE_URL/$ANDROID_SDK_FILENAME
+ANDROID_SDK_PATH=$GODOT_BUILD_TOOLS_PATH/$ANDROID_SDK_DIR
+ANDROID_SDK_SHA256=444e22ce8ca0f67353bda4b85175ed3731cae3ffa695ca18119cbacef1c1bea0
+
+ANDROID_NDK_RELEASE=r15c
+ANDROID_NDK_DIR=android-ndk
+ANDROID_NDK_FILENAME=android-ndk-$ANDROID_NDK_RELEASE-linux-x86_64.zip
+ANDROID_NDK_URL=$ANDROID_BASE_URL/$ANDROID_NDK_FILENAME
+ANDROID_NDK_PATH=$GODOT_BUILD_TOOLS_PATH/$ANDROID_NDK_DIR
+ANDROID_NDK_SHA1=0bf02d4e8b85fd770fd7b9b2cdec57f9441f27a2
+
+echo
+echo "Download and install Android development tools ..."
+echo
+
+if [ ! -e $ANDROID_SDK_FILENAME ]; then
+ echo "Downloading: Android SDK ..."
+ curl -L -O $ANDROID_SDK_URL
+else
+ echo $ANDROID_SDK_SHA1 $ANDROID_SDK_FILENAME > $ANDROID_SDK_FILENAME.sha1
+ if [ $(shasum -a 256 < $ANDROID_SDK_FILENAME | awk '{print $1;}') != $ANDROID_SDK_SHA1 ]; then
+ echo "Downloading: Android SDK ..."
+ curl -L -O $ANDROID_SDK_URL
+ fi
+fi
+
+if [ ! -d $ANDROID_SDK_DIR ]; then
+ echo "Extracting: Android SDK ..."
+ unzip -qq $ANDROID_SDK_FILENAME -d $ANDROID_SDK_DIR
+ echo
+fi
+
+if [ ! -e $ANDROID_NDK_FILENAME ]; then
+ echo "Downloading: Android NDK ..."
+ curl -L -O $ANDROID_NDK_URL
+else
+ echo $ANDROID_NDK_MD5 $ANDROID_NDK_FILENAME > $ANDROID_NDK_FILENAME.md5
+ if [ $(shasum -a 1 < $ANDROID_NDK_FILENAME | awk '{print $1;}') != $ANDROID_NDK_SHA1 ]; then
+ echo "Downloading: Android NDK ..."
+ curl -L -O $ANDROID_NDK_URL
+ fi
+fi
+
+if [ ! -d $ANDROID_NDK_DIR ]; then
+ echo "Extracting: Android NDK ..."
+ unzip -qq $ANDROID_NDK_FILENAME
+ mv android-ndk-$ANDROID_NDK_RELEASE $ANDROID_NDK_DIR
+ echo
+fi
+
+echo "Installing: Android Tools ..."
+#$ANDROID_SDK_DIR/tools/bin/sdkmanager --all
+yes | $ANDROID_SDK_DIR/tools/bin/sdkmanager --licenses > /dev/null
+$ANDROID_SDK_DIR/tools/bin/sdkmanager 'tools' > /dev/null
+$ANDROID_SDK_DIR/tools/bin/sdkmanager 'platform-tools' > /dev/null
+$ANDROID_SDK_DIR/tools/bin/sdkmanager 'build-tools;26.0.2' > /dev/null
+echo
+
+EXPORT_VAL="export ANDROID_HOME=$ANDROID_SDK_PATH"
+if ! grep -q "^$EXPORT_VAL" $BASH_RC; then
+ echo $EXPORT_VAL >> $BASH_RC
+fi
+#eval $EXPORT_VAL
+
+EXPORT_VAL="export ANDROID_NDK_ROOT=$ANDROID_NDK_PATH"
+if ! grep -q "^$EXPORT_VAL" $BASH_RC; then
+ echo $EXPORT_VAL >> $BASH_RC
+fi
+#eval $EXPORT_VAL
+
+EXPORT_VAL="export PATH=$PATH:$ANDROID_SDK_PATH/tools"
+if ! grep -q "^export PATH=.*$ANDROID_SDK_PATH/tools.*" $BASH_RC; then
+ echo $EXPORT_VAL >> $BASH_RC
+fi
+#eval $EXPORT_VAL
+
+EXPORT_VAL="export PATH=$PATH:$ANDROID_SDK_PATH/tools/bin"
+if ! grep -q "^export PATH=.*$ANDROID_SDK_PATH/tools/bin.*" $BASH_RC; then
+ echo $EXPORT_VAL >> $BASH_RC
+fi
+#eval $EXPORT_VAL
+
+echo
+echo "Done!"
+echo
diff --git a/misc/travis/android-tools-osx.sh b/misc/travis/android-tools-osx.sh
new file mode 100755
index 0000000000..96125a3a3f
--- /dev/null
+++ b/misc/travis/android-tools-osx.sh
@@ -0,0 +1,107 @@
+#!/bin/bash
+
+# SDK
+# https://dl.google.com/android/repository/sdk-tools-darwin-3859397.zip
+# SHA-256 4a81754a760fce88cba74d69c364b05b31c53d57b26f9f82355c61d5fe4b9df9
+# latest version available here: https://developer.android.com/studio/index.html
+
+# NDK
+# https://dl.google.com/android/repository/android-ndk-r15c-darwin-x86_64.zip
+# SHA-1 ea4b5d76475db84745aa8828000d009625fc1f98
+# latest version available here: https://developer.android.com/ndk/downloads/index.html
+
+BASH_RC=~/.bashrc
+GODOT_BUILD_TOOLS_PATH=./godot-dev/build-tools
+mkdir -p $GODOT_BUILD_TOOLS_PATH
+cd $GODOT_BUILD_TOOLS_PATH
+
+ANDROID_BASE_URL=http://dl.google.com/android/repository
+
+ANDROID_SDK_RELEASE=3859397
+ANDROID_SDK_DIR=android-sdk
+ANDROID_SDK_FILENAME=sdk-tools-darwin-$ANDROID_SDK_RELEASE.zip
+ANDROID_SDK_URL=$ANDROID_BASE_URL/$ANDROID_SDK_FILENAME
+ANDROID_SDK_PATH=$GODOT_BUILD_TOOLS_PATH/$ANDROID_SDK_DIR
+ANDROID_SDK_SHA256=4a81754a760fce88cba74d69c364b05b31c53d57b26f9f82355c61d5fe4b9df9
+
+ANDROID_NDK_RELEASE=r15c
+ANDROID_NDK_DIR=android-ndk
+ANDROID_NDK_FILENAME=android-ndk-$ANDROID_NDK_RELEASE-darwin-x86_64.zip
+ANDROID_NDK_URL=$ANDROID_BASE_URL/$ANDROID_NDK_FILENAME
+ANDROID_NDK_PATH=$GODOT_BUILD_TOOLS_PATH/$ANDROID_NDK_DIR
+ANDROID_NDK_SHA1=ea4b5d76475db84745aa8828000d009625fc1f98
+
+echo
+echo "Download and install Android development tools ..."
+echo
+
+if [ ! -e $ANDROID_SDK_FILENAME ]; then
+ echo "Downloading: Android SDK ..."
+ curl -L -O $ANDROID_SDK_URL
+else
+ echo $ANDROID_SDK_SHA1 $ANDROID_SDK_FILENAME > $ANDROID_SDK_FILENAME.sha1
+ if [ $(shasum -a 256 < $ANDROID_SDK_FILENAME | awk '{print $1;}') != $ANDROID_SDK_SHA1 ]; then
+ echo "Downloading: Android SDK ..."
+ curl -L -O $ANDROID_SDK_URL
+ fi
+fi
+
+if [ ! -d $ANDROID_SDK_DIR ]; then
+ echo "Extracting: Android SDK ..."
+ mkdir -p $ANDROID_SDK_DIR && tar -xf $ANDROID_SDK_FILENAME -C $ANDROID_SDK_DIR
+ echo
+fi
+
+if [ ! -e $ANDROID_NDK_FILENAME ]; then
+ echo "Downloading: Android NDK ..."
+ curl -L -O $ANDROID_NDK_URL
+else
+ echo $ANDROID_NDK_MD5 $ANDROID_NDK_FILENAME > $ANDROID_NDK_FILENAME.md5
+ if [ $(shasum -a 1 < $ANDROID_NDK_FILENAME | awk '{print $1;}') != $ANDROID_NDK_SHA1 ]; then
+ echo "Downloading: Android NDK ..."
+ curl -L -O $ANDROID_NDK_URL
+ fi
+fi
+
+if [ ! -d $ANDROID_NDK_DIR ]; then
+ echo "Extracting: Android NDK ..."
+ tar -xf $ANDROID_NDK_FILENAME
+ mv android-ndk-$ANDROID_NDK_RELEASE $ANDROID_NDK_DIR
+ echo
+fi
+
+echo "Installing: Android Tools ..."
+#$ANDROID_SDK_DIR/tools/bin/sdkmanager --all
+yes | $ANDROID_SDK_DIR/tools/bin/sdkmanager --licenses > /dev/null
+$ANDROID_SDK_DIR/tools/bin/sdkmanager 'tools' > /dev/null
+$ANDROID_SDK_DIR/tools/bin/sdkmanager 'platform-tools' > /dev/null
+$ANDROID_SDK_DIR/tools/bin/sdkmanager 'build-tools;26.0.2' > /dev/null
+echo
+
+EXPORT_VAL="export ANDROID_HOME=$ANDROID_SDK_PATH"
+if ! grep -q "^$EXPORT_VAL" $BASH_RC; then
+ echo $EXPORT_VAL >> $BASH_RC
+fi
+#eval $EXPORT_VAL
+
+EXPORT_VAL="export ANDROID_NDK_ROOT=$ANDROID_NDK_PATH"
+if ! grep -q "^$EXPORT_VAL" $BASH_RC; then
+ echo $EXPORT_VAL >> $BASH_RC
+fi
+#eval $EXPORT_VAL
+
+EXPORT_VAL="export PATH=$PATH:$ANDROID_SDK_PATH/tools"
+if ! grep -q "^export PATH=.*$ANDROID_SDK_PATH/tools.*" $BASH_RC; then
+ echo $EXPORT_VAL >> $BASH_RC
+fi
+#eval $EXPORT_VAL
+
+EXPORT_VAL="export PATH=$PATH:$ANDROID_SDK_PATH/tools/bin"
+if ! grep -q "^export PATH=.*$ANDROID_SDK_PATH/tools/bin.*" $BASH_RC; then
+ echo $EXPORT_VAL >> $BASH_RC
+fi
+#eval $EXPORT_VAL
+
+echo
+echo "Done!"
+echo
diff --git a/misc/travis/ccache-osx.sh b/misc/travis/ccache-osx.sh
new file mode 100755
index 0000000000..5ce7a80cbc
--- /dev/null
+++ b/misc/travis/ccache-osx.sh
@@ -0,0 +1,43 @@
+#!/bin/bash
+
+echo
+echo "Download and install ccache ..."
+echo
+
+echo "Downloading sources ..."
+curl -L -O https://www.samba.org/ftp/ccache/ccache-3.3.4.tar.gz # latest version available here: https://ccache.samba.org/download.html
+
+echo "Extracting to build directory ..."
+tar xzf ccache-3.3.4.tar.gz
+cd ccache-3.3.4
+
+echo "Compiling sources ..."
+./configure --prefix=/usr/local --with-bundled-zlib > /dev/null
+make
+
+echo "Installing ..."
+
+mkdir /usr/local/opt/ccache
+
+mkdir /usr/local/opt/ccache/bin
+cp ccache /usr/local/opt/ccache/bin
+ln -s /usr/local/opt/ccache/bin/ccache /usr/local/bin/ccache
+
+mkdir /usr/local/opt/ccache/libexec
+links=(
+ clang
+ clang++
+ cc
+ gcc gcc2 gcc3 gcc-3.3 gcc-4.0 gcc-4.2 gcc-4.3 gcc-4.4 gcc-4.5 gcc-4.6 gcc-4.7 gcc-4.8 gcc-4.9 gcc-5 gcc-6 gcc-7
+ c++ c++3 c++-3.3 c++-4.0 c++-4.2 c++-4.3 c++-4.4 c++-4.5 c++-4.6 c++-4.7 c++-4.8 c++-4.9 c++-5 c++-6 c++-7
+ g++ g++2 g++3 g++-3.3 g++-4.0 g++-4.2 g++-4.3 g++-4.4 g++-4.5 g++-4.6 g++-4.7 g++-4.8 g++-4.9 g++-5 g++-6 g++-7
+)
+for link in "${links[@]}"; do
+ ln -s ../bin/ccache /usr/local/opt/ccache/libexec/$link
+done
+#/usr/local/bin/ccache -M 2G
+cd $TRAVIS_BUILD_DIR
+
+echo
+echo "Done!"
+echo
diff --git a/misc/travis/scons-local-osx.sh b/misc/travis/scons-local-osx.sh
new file mode 100755
index 0000000000..d9d7d98b38
--- /dev/null
+++ b/misc/travis/scons-local-osx.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+
+echo
+echo "Download and install Scons local package ..."
+echo
+
+echo "Downloading sources ..."
+curl -L -O http://prdownloads.sourceforge.net/scons/scons-local-3.0.0.zip # latest version available here: http://scons.org/pages/download.html
+
+echo "Extracting to build directory ..."
+unzip -qq -n scons-local-3.0.0.zip -d $TRAVIS_BUILD_DIR/scons-local
+
+echo "Installing symlinks ..."
+ln -s $TRAVIS_BUILD_DIR/scons-local/scons.py /usr/local/bin/scons
+
+echo
+echo "Done!"
+echo
diff --git a/modules/SCsub b/modules/SCsub
index d1c0cdc05c..c1cf5a6c1a 100644
--- a/modules/SCsub
+++ b/modules/SCsub
@@ -9,7 +9,6 @@ Export('env_modules')
env.modules_sources = [
"register_module_types.gen.cpp",
]
-# env.add_source_files(env.modules_sources,"*.cpp")
Export('env')
for x in env.module_list:
diff --git a/modules/bullet/SCsub b/modules/bullet/SCsub
new file mode 100644
index 0000000000..7a37cca130
--- /dev/null
+++ b/modules/bullet/SCsub
@@ -0,0 +1,191 @@
+#!/usr/bin/env python
+
+Import('env')
+
+# build only version 2
+# Bullet 2.87
+bullet_src__2_x = [
+ # BulletCollision
+ "BulletCollision/BroadphaseCollision/btAxisSweep3.cpp"
+ , "BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp"
+ , "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp"
+ , "BulletCollision/BroadphaseCollision/btDbvt.cpp"
+ , "BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp"
+ , "BulletCollision/BroadphaseCollision/btDispatcher.cpp"
+ , "BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp"
+ , "BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp"
+ , "BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp"
+ , "BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp"
+ , "BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp"
+ , "BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp"
+ , "BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp"
+ , "BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp"
+ , "BulletCollision/CollisionDispatch/btCollisionDispatcherMt.cpp"
+ , "BulletCollision/CollisionDispatch/btCollisionObject.cpp"
+ , "BulletCollision/CollisionDispatch/btCollisionWorld.cpp"
+ , "BulletCollision/CollisionDispatch/btCollisionWorldImporter.cpp"
+ , "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp"
+ , "BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.cpp"
+ , "BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp"
+ , "BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp"
+ , "BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp"
+ , "BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp"
+ , "BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp"
+ , "BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp"
+ , "BulletCollision/CollisionDispatch/btGhostObject.cpp"
+ , "BulletCollision/CollisionDispatch/btHashedSimplePairCache.cpp"
+ , "BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp"
+ , "BulletCollision/CollisionDispatch/btManifoldResult.cpp"
+ , "BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp"
+ , "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp"
+ , "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp"
+ , "BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp"
+ , "BulletCollision/CollisionDispatch/btUnionFind.cpp"
+ , "BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp"
+ , "BulletCollision/CollisionShapes/btBoxShape.cpp"
+ , "BulletCollision/CollisionShapes/btBox2dShape.cpp"
+ , "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp"
+ , "BulletCollision/CollisionShapes/btCapsuleShape.cpp"
+ , "BulletCollision/CollisionShapes/btCollisionShape.cpp"
+ , "BulletCollision/CollisionShapes/btCompoundShape.cpp"
+ , "BulletCollision/CollisionShapes/btConcaveShape.cpp"
+ , "BulletCollision/CollisionShapes/btConeShape.cpp"
+ , "BulletCollision/CollisionShapes/btConvexHullShape.cpp"
+ , "BulletCollision/CollisionShapes/btConvexInternalShape.cpp"
+ , "BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp"
+ , "BulletCollision/CollisionShapes/btConvexPolyhedron.cpp"
+ , "BulletCollision/CollisionShapes/btConvexShape.cpp"
+ , "BulletCollision/CollisionShapes/btConvex2dShape.cpp"
+ , "BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp"
+ , "BulletCollision/CollisionShapes/btCylinderShape.cpp"
+ , "BulletCollision/CollisionShapes/btEmptyShape.cpp"
+ , "BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp"
+ , "BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp"
+ , "BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp"
+ , "BulletCollision/CollisionShapes/btMultiSphereShape.cpp"
+ , "BulletCollision/CollisionShapes/btOptimizedBvh.cpp"
+ , "BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp"
+ , "BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp"
+ , "BulletCollision/CollisionShapes/btShapeHull.cpp"
+ , "BulletCollision/CollisionShapes/btSphereShape.cpp"
+ , "BulletCollision/CollisionShapes/btStaticPlaneShape.cpp"
+ , "BulletCollision/CollisionShapes/btStridingMeshInterface.cpp"
+ , "BulletCollision/CollisionShapes/btTetrahedronShape.cpp"
+ , "BulletCollision/CollisionShapes/btTriangleBuffer.cpp"
+ , "BulletCollision/CollisionShapes/btTriangleCallback.cpp"
+ , "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp"
+ , "BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp"
+ , "BulletCollision/CollisionShapes/btTriangleMesh.cpp"
+ , "BulletCollision/CollisionShapes/btTriangleMeshShape.cpp"
+ , "BulletCollision/CollisionShapes/btUniformScalingShape.cpp"
+ , "BulletCollision/Gimpact/btContactProcessing.cpp"
+ , "BulletCollision/Gimpact/btGenericPoolAllocator.cpp"
+ , "BulletCollision/Gimpact/btGImpactBvh.cpp"
+ , "BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp"
+ , "BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp"
+ , "BulletCollision/Gimpact/btGImpactShape.cpp"
+ , "BulletCollision/Gimpact/btTriangleShapeEx.cpp"
+ , "BulletCollision/Gimpact/gim_box_set.cpp"
+ , "BulletCollision/Gimpact/gim_contact.cpp"
+ , "BulletCollision/Gimpact/gim_memory.cpp"
+ , "BulletCollision/Gimpact/gim_tri_collision.cpp"
+ , "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp"
+ , "BulletCollision/NarrowPhaseCollision/btConvexCast.cpp"
+ , "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp"
+ , "BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp"
+ , "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp"
+ , "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp"
+ , "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp"
+ , "BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp"
+ , "BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp"
+ , "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp"
+ , "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp"
+ , "BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp"
+
+ # BulletDynamics
+ , "BulletDynamics/Character/btKinematicCharacterController.cpp"
+ , "BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp"
+ , "BulletDynamics/ConstraintSolver/btContactConstraint.cpp"
+ , "BulletDynamics/ConstraintSolver/btFixedConstraint.cpp"
+ , "BulletDynamics/ConstraintSolver/btGearConstraint.cpp"
+ , "BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp"
+ , "BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp"
+ , "BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.cpp"
+ , "BulletDynamics/ConstraintSolver/btHinge2Constraint.cpp"
+ , "BulletDynamics/ConstraintSolver/btHingeConstraint.cpp"
+ , "BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp"
+ , "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp"
+ , "BulletDynamics/ConstraintSolver/btNNCGConstraintSolver.cpp"
+ , "BulletDynamics/ConstraintSolver/btSliderConstraint.cpp"
+ , "BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp"
+ , "BulletDynamics/ConstraintSolver/btTypedConstraint.cpp"
+ , "BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp"
+ , "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp"
+ , "BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.cpp"
+ , "BulletDynamics/Dynamics/btSimulationIslandManagerMt.cpp"
+ , "BulletDynamics/Dynamics/btRigidBody.cpp"
+ , "BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp"
+ #, "BulletDynamics/Dynamics/Bullet-C-API.cpp"
+ , "BulletDynamics/Vehicle/btRaycastVehicle.cpp"
+ , "BulletDynamics/Vehicle/btWheelInfo.cpp"
+ , "BulletDynamics/Featherstone/btMultiBody.cpp"
+ , "BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp"
+ , "BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.cpp"
+ , "BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.cpp"
+ , "BulletDynamics/Featherstone/btMultiBodyConstraint.cpp"
+ , "BulletDynamics/Featherstone/btMultiBodyPoint2Point.cpp"
+ , "BulletDynamics/Featherstone/btMultiBodyFixedConstraint.cpp"
+ , "BulletDynamics/Featherstone/btMultiBodySliderConstraint.cpp"
+ , "BulletDynamics/Featherstone/btMultiBodyJointMotor.cpp"
+ , "BulletDynamics/Featherstone/btMultiBodyGearConstraint.cpp"
+ , "BulletDynamics/MLCPSolvers/btDantzigLCP.cpp"
+ , "BulletDynamics/MLCPSolvers/btMLCPSolver.cpp"
+ , "BulletDynamics/MLCPSolvers/btLemkeAlgorithm.cpp"
+
+ # BulletInverseDynamics
+ , "BulletInverseDynamics/IDMath.cpp"
+ , "BulletInverseDynamics/MultiBodyTree.cpp"
+ , "BulletInverseDynamics/details/MultiBodyTreeInitCache.cpp"
+ , "BulletInverseDynamics/details/MultiBodyTreeImpl.cpp"
+
+ # BulletSoftBody
+ , "BulletSoftBody/btSoftBody.cpp"
+ , "BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp"
+ , "BulletSoftBody/btSoftBodyHelpers.cpp"
+ , "BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp"
+ , "BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp"
+ , "BulletSoftBody/btSoftRigidDynamicsWorld.cpp"
+ , "BulletSoftBody/btSoftMultiBodyDynamicsWorld.cpp"
+ , "BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp"
+ , "BulletSoftBody/btDefaultSoftBodySolver.cpp"
+
+ # clew
+ , "clew/clew.c"
+
+ # LinearMath
+ , "LinearMath/btAlignedAllocator.cpp"
+ , "LinearMath/btConvexHull.cpp"
+ , "LinearMath/btConvexHullComputer.cpp"
+ , "LinearMath/btGeometryUtil.cpp"
+ , "LinearMath/btPolarDecomposition.cpp"
+ , "LinearMath/btQuickprof.cpp"
+ , "LinearMath/btSerializer.cpp"
+ , "LinearMath/btSerializer64.cpp"
+ , "LinearMath/btThreads.cpp"
+ , "LinearMath/btVector3.cpp"
+ ]
+
+thirdparty_dir = "#thirdparty/bullet/"
+thirdparty_src = thirdparty_dir + "src/"
+
+bullet_sources = [thirdparty_src + file for file in bullet_src__2_x]
+
+# include headers
+env.Append(CPPPATH=[thirdparty_src])
+
+env.add_source_files(env.modules_sources, bullet_sources)
+
+# Godot source files
+env.add_source_files(env.modules_sources, "*.cpp")
+
+Export('env')
diff --git a/modules/bullet/SCsub_with_lib b/modules/bullet/SCsub_with_lib
new file mode 100644
index 0000000000..b362a686ff
--- /dev/null
+++ b/modules/bullet/SCsub_with_lib
@@ -0,0 +1,33 @@
+#!/usr/bin/env python
+
+Import('env')
+
+thirdparty_dir = "#thirdparty/bullet/"
+thirdparty_lib = thirdparty_dir + "Win64/lib/"
+
+bullet_libs = [
+ "Bullet2FileLoader",
+ "Bullet3Collision",
+ "Bullet3Common",
+ "Bullet3Dynamics",
+ "Bullet3Geometry",
+ "Bullet3OpenCL_clew",
+ "BulletCollision",
+ "BulletDynamics",
+ "BulletInverseDynamics",
+ "BulletSoftBody",
+ "LinearMath"
+ ]
+
+thirdparty_src = thirdparty_dir + "src/"
+# include headers
+env.Append(CPPPATH=[thirdparty_src])
+
+# lib
+env.Append(LIBPATH=[thirdparty_dir + "/Win64/lib/"])
+
+bullet_libs = [file+'.lib' for file in bullet_libs]
+# LIBS doesn't work in windows
+env.Append(LINKFLAGS=bullet_libs)
+
+env.add_source_files(env.modules_sources, "*.cpp")
diff --git a/modules/bullet/area_bullet.cpp b/modules/bullet/area_bullet.cpp
new file mode 100644
index 0000000000..54024b4f90
--- /dev/null
+++ b/modules/bullet/area_bullet.cpp
@@ -0,0 +1,284 @@
+/*************************************************************************/
+/* area_bullet.cpp */
+/* Author: AndreaCatania */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "area_bullet.h"
+#include "BulletCollision/CollisionDispatch/btGhostObject.h"
+#include "btBulletCollisionCommon.h"
+#include "bullet_types_converter.h"
+#include "bullet_utilities.h"
+#include "collision_object_bullet.h"
+#include "space_bullet.h"
+
+AreaBullet::AreaBullet()
+ : RigidCollisionObjectBullet(CollisionObjectBullet::TYPE_AREA),
+ monitorable(true),
+ isScratched(false),
+ spOv_mode(PhysicsServer::AREA_SPACE_OVERRIDE_DISABLED),
+ spOv_gravityPoint(false),
+ spOv_gravityPointDistanceScale(0),
+ spOv_gravityPointAttenuation(1),
+ spOv_gravityVec(0, -1, 0),
+ spOv_gravityMag(10),
+ spOv_linearDump(0.1),
+ spOv_angularDump(1),
+ spOv_priority(0) {
+
+ btGhost = bulletnew(btGhostObject);
+ btGhost->setCollisionShape(compoundShape);
+ setupBulletCollisionObject(btGhost);
+ /// Collision objects with a callback still have collision response with dynamic rigid bodies.
+ /// In order to use collision objects as trigger, you have to disable the collision response.
+ set_collision_enabled(false);
+
+ for (int i = 0; i < 5; ++i)
+ call_event_res_ptr[i] = &call_event_res[i];
+}
+
+AreaBullet::~AreaBullet() {
+ remove_all_overlapping_instantly();
+}
+
+void AreaBullet::dispatch_callbacks() {
+ if (!isScratched)
+ return;
+ isScratched = false;
+
+ // Reverse order because I've to remove EXIT objects
+ for (int i = overlappingObjects.size() - 1; 0 <= i; --i) {
+ OverlappingObjectData &otherObj = overlappingObjects[i];
+
+ switch (otherObj.state) {
+ case OVERLAP_STATE_ENTER:
+ otherObj.state = OVERLAP_STATE_INSIDE;
+ call_event(otherObj.object, PhysicsServer::AREA_BODY_ADDED);
+ otherObj.object->on_enter_area(this);
+ break;
+ case OVERLAP_STATE_EXIT:
+ call_event(otherObj.object, PhysicsServer::AREA_BODY_REMOVED);
+ otherObj.object->on_exit_area(this);
+ overlappingObjects.remove(i); // Remove after callback
+ break;
+ }
+ }
+}
+
+void AreaBullet::call_event(CollisionObjectBullet *p_otherObject, PhysicsServer::AreaBodyStatus p_status) {
+
+ InOutEventCallback &event = eventsCallbacks[static_cast<int>(p_otherObject->getType())];
+ Object *areaGodoObject = ObjectDB::get_instance(event.event_callback_id);
+
+ if (!areaGodoObject) {
+ event.event_callback_id = 0;
+ return;
+ }
+
+ call_event_res[0] = p_status;
+ call_event_res[1] = p_otherObject->get_self(); // Other body
+ call_event_res[2] = p_otherObject->get_instance_id(); // instance ID
+ call_event_res[3] = 0; // other_body_shape ID
+ call_event_res[4] = 0; // self_shape ID
+
+ Variant::CallError outResp;
+ areaGodoObject->call(event.event_callback_method, (const Variant **)call_event_res_ptr, 5, outResp);
+}
+
+void AreaBullet::scratch() {
+ if (isScratched)
+ return;
+ isScratched = true;
+}
+
+void AreaBullet::remove_all_overlapping_instantly() {
+ CollisionObjectBullet *supportObject;
+ for (int i = overlappingObjects.size() - 1; 0 <= i; --i) {
+ supportObject = overlappingObjects[i].object;
+ call_event(supportObject, PhysicsServer::AREA_BODY_REMOVED);
+ supportObject->on_exit_area(this);
+ }
+ overlappingObjects.clear();
+}
+
+void AreaBullet::remove_overlapping_instantly(CollisionObjectBullet *p_object) {
+ CollisionObjectBullet *supportObject;
+ for (int i = overlappingObjects.size() - 1; 0 <= i; --i) {
+ supportObject = overlappingObjects[i].object;
+ if (supportObject == p_object) {
+ call_event(supportObject, PhysicsServer::AREA_BODY_REMOVED);
+ supportObject->on_exit_area(this);
+ overlappingObjects.remove(i);
+ break;
+ }
+ }
+}
+
+int AreaBullet::find_overlapping_object(CollisionObjectBullet *p_colObj) {
+ const int size = overlappingObjects.size();
+ for (int i = 0; i < size; ++i) {
+ if (overlappingObjects[i].object == p_colObj) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+void AreaBullet::set_monitorable(bool p_monitorable) {
+ monitorable = p_monitorable;
+}
+
+bool AreaBullet::is_monitoring() const {
+ return get_godot_object_flags() & GOF_IS_MONITORING_AREA;
+}
+
+void AreaBullet::reload_body() {
+ if (space) {
+ space->remove_area(this);
+ space->add_area(this);
+ }
+}
+
+void AreaBullet::set_space(SpaceBullet *p_space) {
+ // Clear the old space if there is one
+ if (space) {
+ isScratched = false;
+
+ // Remove this object form the physics world
+ space->remove_area(this);
+ }
+
+ space = p_space;
+
+ if (space) {
+ space->add_area(this);
+ }
+}
+
+void AreaBullet::on_collision_filters_change() {
+ if (space) {
+ space->reload_collision_filters(this);
+ }
+}
+
+void AreaBullet::add_overlap(CollisionObjectBullet *p_otherObject) {
+ scratch();
+ overlappingObjects.push_back(OverlappingObjectData(p_otherObject, OVERLAP_STATE_ENTER));
+ p_otherObject->notify_new_overlap(this);
+}
+
+void AreaBullet::put_overlap_as_exit(int p_index) {
+ scratch();
+ overlappingObjects[p_index].state = OVERLAP_STATE_EXIT;
+}
+
+void AreaBullet::put_overlap_as_inside(int p_index) {
+ // This check is required to be sure this body was inside
+ if (OVERLAP_STATE_DIRTY == overlappingObjects[p_index].state) {
+ overlappingObjects[p_index].state = OVERLAP_STATE_INSIDE;
+ }
+}
+
+void AreaBullet::set_param(PhysicsServer::AreaParameter p_param, const Variant &p_value) {
+ switch (p_param) {
+ case PhysicsServer::AREA_PARAM_GRAVITY:
+ set_spOv_gravityMag(p_value);
+ break;
+ case PhysicsServer::AREA_PARAM_GRAVITY_VECTOR:
+ set_spOv_gravityVec(p_value);
+ break;
+ case PhysicsServer::AREA_PARAM_LINEAR_DAMP:
+ set_spOv_linearDump(p_value);
+ break;
+ case PhysicsServer::AREA_PARAM_ANGULAR_DAMP:
+ set_spOv_angularDump(p_value);
+ break;
+ case PhysicsServer::AREA_PARAM_PRIORITY:
+ set_spOv_priority(p_value);
+ break;
+ case PhysicsServer::AREA_PARAM_GRAVITY_IS_POINT:
+ set_spOv_gravityPoint(p_value);
+ break;
+ case PhysicsServer::AREA_PARAM_GRAVITY_DISTANCE_SCALE:
+ set_spOv_gravityPointDistanceScale(p_value);
+ break;
+ case PhysicsServer::AREA_PARAM_GRAVITY_POINT_ATTENUATION:
+ set_spOv_gravityPointAttenuation(p_value);
+ break;
+ default:
+ print_line("The Bullet areas dosn't suppot this param: " + itos(p_param));
+ }
+}
+
+Variant AreaBullet::get_param(PhysicsServer::AreaParameter p_param) const {
+ switch (p_param) {
+ case PhysicsServer::AREA_PARAM_GRAVITY:
+ return spOv_gravityMag;
+ case PhysicsServer::AREA_PARAM_GRAVITY_VECTOR:
+ return spOv_gravityVec;
+ case PhysicsServer::AREA_PARAM_LINEAR_DAMP:
+ return spOv_linearDump;
+ case PhysicsServer::AREA_PARAM_ANGULAR_DAMP:
+ return spOv_angularDump;
+ case PhysicsServer::AREA_PARAM_PRIORITY:
+ return spOv_priority;
+ case PhysicsServer::AREA_PARAM_GRAVITY_IS_POINT:
+ return spOv_gravityPoint;
+ case PhysicsServer::AREA_PARAM_GRAVITY_DISTANCE_SCALE:
+ return spOv_gravityPointDistanceScale;
+ case PhysicsServer::AREA_PARAM_GRAVITY_POINT_ATTENUATION:
+ return spOv_gravityPointAttenuation;
+ default:
+ print_line("The Bullet areas dosn't suppot this param: " + itos(p_param));
+ return Variant();
+ }
+}
+
+void AreaBullet::set_event_callback(Type p_callbackObjectType, ObjectID p_id, const StringName &p_method) {
+ InOutEventCallback &ev = eventsCallbacks[static_cast<int>(p_callbackObjectType)];
+ ev.event_callback_id = p_id;
+ ev.event_callback_method = p_method;
+
+ /// Set if monitoring
+ if (eventsCallbacks[0].event_callback_id || eventsCallbacks[1].event_callback_id) {
+ set_godot_object_flags(get_godot_object_flags() | GOF_IS_MONITORING_AREA);
+ } else {
+ set_godot_object_flags(get_godot_object_flags() & (~GOF_IS_MONITORING_AREA));
+ }
+}
+
+bool AreaBullet::has_event_callback(Type p_callbackObjectType) {
+ return eventsCallbacks[static_cast<int>(p_callbackObjectType)].event_callback_id;
+}
+
+void AreaBullet::on_enter_area(AreaBullet *p_area) {
+}
+
+void AreaBullet::on_exit_area(AreaBullet *p_area) {
+ CollisionObjectBullet::on_exit_area(p_area);
+}
diff --git a/modules/bullet/area_bullet.h b/modules/bullet/area_bullet.h
new file mode 100644
index 0000000000..f6e3b7e902
--- /dev/null
+++ b/modules/bullet/area_bullet.h
@@ -0,0 +1,169 @@
+/*************************************************************************/
+/* area_bullet.h */
+/* Author: AndreaCatania */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef AREABULLET_H
+#define AREABULLET_H
+
+#include "collision_object_bullet.h"
+#include "core/vector.h"
+#include "servers/physics_server.h"
+#include "space_bullet.h"
+
+class btGhostObject;
+
+class AreaBullet : public RigidCollisionObjectBullet {
+ friend void SpaceBullet::check_ghost_overlaps();
+
+public:
+ struct InOutEventCallback {
+ ObjectID event_callback_id;
+ StringName event_callback_method;
+
+ InOutEventCallback()
+ : event_callback_id(0) {}
+ };
+
+ enum OverlapState {
+ OVERLAP_STATE_DIRTY = 0, // Mark processed overlaps
+ OVERLAP_STATE_INSIDE, // Mark old overlap
+ OVERLAP_STATE_ENTER, // Mark just enter overlap
+ OVERLAP_STATE_EXIT // Mark ended overlaps
+ };
+
+ struct OverlappingObjectData {
+ CollisionObjectBullet *object;
+ OverlapState state;
+
+ OverlappingObjectData()
+ : object(NULL), state(OVERLAP_STATE_ENTER) {}
+ OverlappingObjectData(CollisionObjectBullet *p_object, OverlapState p_state)
+ : object(p_object), state(p_state) {}
+ OverlappingObjectData(const OverlappingObjectData &other) {
+ operator=(other);
+ }
+ void operator=(const OverlappingObjectData &other) {
+ object = other.object;
+ state = other.state;
+ }
+ };
+
+private:
+ // These are used by function callEvent. Instead to create this each call I create if one time.
+ Variant call_event_res[5];
+ Variant *call_event_res_ptr[5];
+
+ btGhostObject *btGhost;
+ Vector<OverlappingObjectData> overlappingObjects;
+ bool monitorable;
+
+ PhysicsServer::AreaSpaceOverrideMode spOv_mode;
+ bool spOv_gravityPoint;
+ real_t spOv_gravityPointDistanceScale;
+ real_t spOv_gravityPointAttenuation;
+ Vector3 spOv_gravityVec;
+ real_t spOv_gravityMag;
+ real_t spOv_linearDump;
+ real_t spOv_angularDump;
+ int spOv_priority;
+
+ bool isScratched;
+
+ InOutEventCallback eventsCallbacks[2];
+
+public:
+ AreaBullet();
+ ~AreaBullet();
+
+ _FORCE_INLINE_ btGhostObject *get_bt_ghost() const { return btGhost; }
+ int find_overlapping_object(CollisionObjectBullet *p_colObj);
+
+ void set_monitorable(bool p_monitorable);
+ _FORCE_INLINE_ bool is_monitorable() const { return monitorable; }
+
+ bool is_monitoring() const;
+
+ _FORCE_INLINE_ void set_spOv_mode(PhysicsServer::AreaSpaceOverrideMode p_mode) { spOv_mode = p_mode; }
+ _FORCE_INLINE_ PhysicsServer::AreaSpaceOverrideMode get_spOv_mode() { return spOv_mode; }
+
+ _FORCE_INLINE_ void set_spOv_gravityPoint(bool p_isGP) { spOv_gravityPoint = p_isGP; }
+ _FORCE_INLINE_ bool is_spOv_gravityPoint() { return spOv_gravityPoint; }
+
+ _FORCE_INLINE_ void set_spOv_gravityPointDistanceScale(real_t p_GPDS) { spOv_gravityPointDistanceScale = p_GPDS; }
+ _FORCE_INLINE_ real_t get_spOv_gravityPointDistanceScale() { return spOv_gravityPointDistanceScale; }
+
+ _FORCE_INLINE_ void set_spOv_gravityPointAttenuation(real_t p_GPA) { spOv_gravityPointAttenuation = p_GPA; }
+ _FORCE_INLINE_ real_t get_spOv_gravityPointAttenuation() { return spOv_gravityPointAttenuation; }
+
+ _FORCE_INLINE_ void set_spOv_gravityVec(Vector3 p_vec) { spOv_gravityVec = p_vec; }
+ _FORCE_INLINE_ const Vector3 &get_spOv_gravityVec() const { return spOv_gravityVec; }
+
+ _FORCE_INLINE_ void set_spOv_gravityMag(real_t p_gravityMag) { spOv_gravityMag = p_gravityMag; }
+ _FORCE_INLINE_ real_t get_spOv_gravityMag() { return spOv_gravityMag; }
+
+ _FORCE_INLINE_ void set_spOv_linearDump(real_t p_linearDump) { spOv_linearDump = p_linearDump; }
+ _FORCE_INLINE_ real_t get_spOv_linearDamp() { return spOv_linearDump; }
+
+ _FORCE_INLINE_ void set_spOv_angularDump(real_t p_angularDump) { spOv_angularDump = p_angularDump; }
+ _FORCE_INLINE_ real_t get_spOv_angularDamp() { return spOv_angularDump; }
+
+ _FORCE_INLINE_ void set_spOv_priority(int p_priority) { spOv_priority = p_priority; }
+ _FORCE_INLINE_ int get_spOv_priority() { return spOv_priority; }
+
+ virtual void reload_body();
+ virtual void set_space(SpaceBullet *p_space);
+
+ virtual void dispatch_callbacks();
+ void call_event(CollisionObjectBullet *p_otherObject, PhysicsServer::AreaBodyStatus p_status);
+ void set_on_state_change(ObjectID p_id, const StringName &p_method, const Variant &p_udata = Variant());
+ void scratch();
+
+ void remove_all_overlapping_instantly();
+ // Dispatch the callbacks and removes from overlapping list
+ void remove_overlapping_instantly(CollisionObjectBullet *p_object);
+
+ virtual void on_collision_filters_change();
+ virtual void on_collision_checker_start() {}
+
+ void add_overlap(CollisionObjectBullet *p_otherObject);
+ void put_overlap_as_exit(int p_index);
+ void put_overlap_as_inside(int p_index);
+
+ void set_param(PhysicsServer::AreaParameter p_param, const Variant &p_value);
+ Variant get_param(PhysicsServer::AreaParameter p_param) const;
+
+ void set_event_callback(Type p_callbackObjectType, ObjectID p_id, const StringName &p_method);
+ bool has_event_callback(Type p_callbackObjectType);
+
+ virtual void on_enter_area(AreaBullet *p_area);
+ virtual void on_exit_area(AreaBullet *p_area);
+};
+
+#endif
diff --git a/modules/bullet/btRayShape.cpp b/modules/bullet/btRayShape.cpp
new file mode 100644
index 0000000000..ac95faaac6
--- /dev/null
+++ b/modules/bullet/btRayShape.cpp
@@ -0,0 +1,94 @@
+/*************************************************************************/
+/* btRayShape.h */
+/* Author: AndreaCatania */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "btRayShape.h"
+#include "LinearMath/btAabbUtil2.h"
+#include "math/math_funcs.h"
+
+btRayShape::btRayShape(btScalar length)
+ : btConvexInternalShape(),
+ m_shapeAxis(0, 0, 1) {
+ m_shapeType = CUSTOM_CONVEX_SHAPE_TYPE;
+ setLength(length);
+}
+
+btRayShape::~btRayShape() {
+}
+
+void btRayShape::setLength(btScalar p_length) {
+
+ m_length = p_length;
+ reload_cache();
+}
+
+btVector3 btRayShape::localGetSupportingVertex(const btVector3 &vec) const {
+ return localGetSupportingVertexWithoutMargin(vec) + (m_shapeAxis * m_collisionMargin);
+}
+
+btVector3 btRayShape::localGetSupportingVertexWithoutMargin(const btVector3 &vec) const {
+ if (vec.z() > 0)
+ return m_shapeAxis * m_cacheScaledLength;
+ else
+ return btVector3(0, 0, 0);
+}
+
+void btRayShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3 *vectors, btVector3 *supportVerticesOut, int numVectors) const {
+ for (int i = 0; i < numVectors; ++i) {
+ supportVerticesOut[i] = localGetSupportingVertexWithoutMargin(vectors[i]);
+ }
+}
+
+void btRayShape::getAabb(const btTransform &t, btVector3 &aabbMin, btVector3 &aabbMax) const {
+#define MARGIN_BROADPHASE 0.1
+ btVector3 localAabbMin(0, 0, 0);
+ btVector3 localAabbMax(m_shapeAxis * m_length);
+ btTransformAabb(localAabbMin, localAabbMax, MARGIN_BROADPHASE, t, aabbMin, aabbMax);
+}
+
+void btRayShape::calculateLocalInertia(btScalar mass, btVector3 &inertia) const {
+ inertia.setZero();
+}
+
+int btRayShape::getNumPreferredPenetrationDirections() const {
+ return 0;
+}
+
+void btRayShape::getPreferredPenetrationDirection(int index, btVector3 &penetrationVector) const {
+ penetrationVector.setZero();
+}
+
+void btRayShape::reload_cache() {
+
+ m_cacheScaledLength = m_length * m_localScaling[2] + m_collisionMargin;
+
+ m_cacheSupportPoint.setIdentity();
+ m_cacheSupportPoint.setOrigin(m_shapeAxis * m_cacheScaledLength);
+}
diff --git a/modules/bullet/btRayShape.h b/modules/bullet/btRayShape.h
new file mode 100644
index 0000000000..1b63fb477c
--- /dev/null
+++ b/modules/bullet/btRayShape.h
@@ -0,0 +1,87 @@
+/*************************************************************************/
+/* btRayShape.h */
+/* Author: AndreaCatania */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 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. */
+/*************************************************************************/
+
+/// IMPORTANT The class name and filename was created by following Bullet writing rules for an easy (eventually ) porting to bullet
+/// This shape is a custom shape that is not present to Bullet physics engine
+#ifndef BTRAYSHAPE_H
+#define BTRAYSHAPE_H
+
+#include "BulletCollision/CollisionShapes/btConvexInternalShape.h"
+
+/// Ray shape around z axis
+ATTRIBUTE_ALIGNED16(class)
+btRayShape : public btConvexInternalShape {
+
+ btScalar m_length;
+ /// The default axis is the z
+ btVector3 m_shapeAxis;
+
+ btTransform m_cacheSupportPoint;
+ btScalar m_cacheScaledLength;
+
+public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ btRayShape(btScalar length);
+ virtual ~btRayShape();
+
+ void setLength(btScalar p_length);
+ btScalar getLength() const { return m_length; }
+
+ const btTransform &getSupportPoint() const { return m_cacheSupportPoint; }
+ const btScalar &getScaledLength() const { return m_cacheScaledLength; }
+
+ virtual btVector3 localGetSupportingVertex(const btVector3 &vec) const;
+#ifndef __SPU__
+ virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3 &vec) const;
+#endif //#ifndef __SPU__
+
+ virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3 *vectors, btVector3 *supportVerticesOut, int numVectors) const;
+
+ ///getAabb returns the axis aligned bounding box in the coordinate frame of the given transform t.
+ virtual void getAabb(const btTransform &t, btVector3 &aabbMin, btVector3 &aabbMax) const;
+
+#ifndef __SPU__
+ virtual void calculateLocalInertia(btScalar mass, btVector3 & inertia) const;
+
+ virtual const char *getName() const {
+ return "RayZ";
+ }
+#endif //__SPU__
+
+ virtual int getNumPreferredPenetrationDirections() const;
+ virtual void getPreferredPenetrationDirection(int index, btVector3 &penetrationVector) const;
+
+private:
+ void reload_cache();
+};
+
+#endif // BTRAYSHAPE_H
diff --git a/modules/bullet/bullet_physics_server.cpp b/modules/bullet/bullet_physics_server.cpp
new file mode 100644
index 0000000000..7f95d16ba6
--- /dev/null
+++ b/modules/bullet/bullet_physics_server.cpp
@@ -0,0 +1,1364 @@
+/*************************************************************************/
+/* bullet_physics_server.cpp */
+/* Author: AndreaCatania */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "bullet_physics_server.h"
+#include "LinearMath/btVector3.h"
+#include "bullet_utilities.h"
+#include "class_db.h"
+#include "cone_twist_joint_bullet.h"
+#include "core/error_macros.h"
+#include "core/ustring.h"
+#include "generic_6dof_joint_bullet.h"
+#include "hinge_joint_bullet.h"
+#include "pin_joint_bullet.h"
+#include "shape_bullet.h"
+#include "slider_joint_bullet.h"
+#include <assert.h>
+
+#define CreateThenReturnRID(owner, ridData) \
+ RID rid = owner.make_rid(ridData); \
+ ridData->set_self(rid); \
+ ridData->_set_physics_server(this); \
+ return rid;
+
+// <--------------- Joint creation asserts
+/// Assert the body is assigned to a space
+#define JointAssertSpace(body, bIndex, ret) \
+ if (!body->get_space()) { \
+ ERR_PRINTS("Before create a joint the Body" + String(bIndex) + " must be added to a space!"); \
+ return ret; \
+ }
+
+/// Assert the two bodies of joint are in the same space
+#define JointAssertSameSpace(bodyA, bodyB, ret) \
+ if (bodyA->get_space() != bodyB->get_space()) { \
+ ERR_PRINT("In order to create a joint the Body_A and Body_B must be in the same space!"); \
+ return RID(); \
+ }
+
+#define AddJointToSpace(body, joint, disableCollisionsBetweenLinkedBodies) \
+ body->get_space()->add_constraint(joint, disableCollisionsBetweenLinkedBodies);
+// <--------------- Joint creation asserts
+
+btEmptyShape *BulletPhysicsServer::emptyShape(ShapeBullet::create_shape_empty());
+
+btEmptyShape *BulletPhysicsServer::get_empty_shape() {
+ return emptyShape;
+}
+
+void BulletPhysicsServer::_bind_methods() {
+ //ClassDB::bind_method(D_METHOD("DoTest"), &BulletPhysicsServer::DoTest);
+}
+
+BulletPhysicsServer::BulletPhysicsServer()
+ : PhysicsServer(),
+ active(true),
+ active_spaces_count(0) {}
+
+BulletPhysicsServer::~BulletPhysicsServer() {}
+
+RID BulletPhysicsServer::shape_create(ShapeType p_shape) {
+ ShapeBullet *shape = NULL;
+
+ switch (p_shape) {
+ case SHAPE_PLANE: {
+
+ shape = bulletnew(PlaneShapeBullet);
+ } break;
+ case SHAPE_SPHERE: {
+
+ shape = bulletnew(SphereShapeBullet);
+ } break;
+ case SHAPE_BOX: {
+
+ shape = bulletnew(BoxShapeBullet);
+ } break;
+ case SHAPE_CAPSULE: {
+
+ shape = bulletnew(CapsuleShapeBullet);
+ } break;
+ case SHAPE_CONVEX_POLYGON: {
+
+ shape = bulletnew(ConvexPolygonShapeBullet);
+ } break;
+ case SHAPE_CONCAVE_POLYGON: {
+
+ shape = bulletnew(ConcavePolygonShapeBullet);
+ } break;
+ case SHAPE_HEIGHTMAP: {
+
+ shape = bulletnew(HeightMapShapeBullet);
+ } break;
+ case SHAPE_RAY: {
+ shape = bulletnew(RayShapeBullet);
+ } break;
+ case SHAPE_CUSTOM:
+ defaul:
+ ERR_FAIL_V(RID());
+ break;
+ }
+
+ CreateThenReturnRID(shape_owner, shape)
+}
+
+void BulletPhysicsServer::shape_set_data(RID p_shape, const Variant &p_data) {
+ ShapeBullet *shape = shape_owner.get(p_shape);
+ ERR_FAIL_COND(!shape);
+ shape->set_data(p_data);
+}
+
+void BulletPhysicsServer::shape_set_custom_solver_bias(RID p_shape, real_t p_bias) {
+ //WARN_PRINT("Bias not supported by Bullet physics engine");
+}
+
+PhysicsServer::ShapeType BulletPhysicsServer::shape_get_type(RID p_shape) const {
+ ShapeBullet *shape = shape_owner.get(p_shape);
+ ERR_FAIL_COND_V(!shape, PhysicsServer::SHAPE_CUSTOM);
+ return shape->get_type();
+}
+
+Variant BulletPhysicsServer::shape_get_data(RID p_shape) const {
+ ShapeBullet *shape = shape_owner.get(p_shape);
+ ERR_FAIL_COND_V(!shape, Variant());
+ return shape->get_data();
+}
+
+real_t BulletPhysicsServer::shape_get_custom_solver_bias(RID p_shape) const {
+ //WARN_PRINT("Bias not supported by Bullet physics engine");
+ return 0.;
+}
+
+RID BulletPhysicsServer::space_create() {
+ SpaceBullet *space = bulletnew(SpaceBullet(false));
+ CreateThenReturnRID(space_owner, space);
+}
+
+void BulletPhysicsServer::space_set_active(RID p_space, bool p_active) {
+
+ SpaceBullet *space = space_owner.get(p_space);
+ ERR_FAIL_COND(!space);
+
+ if (space_is_active(p_space) == p_active) {
+ return;
+ }
+
+ if (p_active) {
+ ++active_spaces_count;
+ active_spaces.push_back(space);
+ } else {
+ --active_spaces_count;
+ active_spaces.erase(space);
+ }
+}
+
+bool BulletPhysicsServer::space_is_active(RID p_space) const {
+ SpaceBullet *space = space_owner.get(p_space);
+ ERR_FAIL_COND_V(!space, false);
+
+ return -1 != active_spaces.find(space);
+}
+
+void BulletPhysicsServer::space_set_param(RID p_space, SpaceParameter p_param, real_t p_value) {
+ SpaceBullet *space = space_owner.get(p_space);
+ ERR_FAIL_COND(!space);
+ space->set_param(p_param, p_value);
+}
+
+real_t BulletPhysicsServer::space_get_param(RID p_space, SpaceParameter p_param) const {
+ SpaceBullet *space = space_owner.get(p_space);
+ ERR_FAIL_COND_V(!space, 0);
+ return space->get_param(p_param);
+}
+
+PhysicsDirectSpaceState *BulletPhysicsServer::space_get_direct_state(RID p_space) {
+ SpaceBullet *space = space_owner.get(p_space);
+ ERR_FAIL_COND_V(!space, NULL);
+
+ return space->get_direct_state();
+}
+
+void BulletPhysicsServer::space_set_debug_contacts(RID p_space, int p_max_contacts) {
+ SpaceBullet *space = space_owner.get(p_space);
+ ERR_FAIL_COND(!space);
+
+ space->set_debug_contacts(p_max_contacts);
+}
+
+Vector<Vector3> BulletPhysicsServer::space_get_contacts(RID p_space) const {
+ SpaceBullet *space = space_owner.get(p_space);
+ ERR_FAIL_COND_V(!space, Vector<Vector3>());
+
+ return space->get_debug_contacts();
+}
+
+int BulletPhysicsServer::space_get_contact_count(RID p_space) const {
+ SpaceBullet *space = space_owner.get(p_space);
+ ERR_FAIL_COND_V(!space, 0);
+
+ return space->get_debug_contact_count();
+}
+
+RID BulletPhysicsServer::area_create() {
+ AreaBullet *area = bulletnew(AreaBullet);
+ area->set_collision_layer(1);
+ area->set_collision_mask(1);
+ CreateThenReturnRID(area_owner, area)
+}
+
+void BulletPhysicsServer::area_set_space(RID p_area, RID p_space) {
+ AreaBullet *area = area_owner.get(p_area);
+ ERR_FAIL_COND(!area);
+ SpaceBullet *space = NULL;
+ if (p_space.is_valid()) {
+ space = space_owner.get(p_space);
+ ERR_FAIL_COND(!space);
+ }
+ area->set_space(space);
+}
+
+RID BulletPhysicsServer::area_get_space(RID p_area) const {
+ AreaBullet *area = area_owner.get(p_area);
+ return area->get_space()->get_self();
+}
+
+void BulletPhysicsServer::area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode) {
+ AreaBullet *area = area_owner.get(p_area);
+ ERR_FAIL_COND(!area)
+
+ area->set_spOv_mode(p_mode);
+}
+
+PhysicsServer::AreaSpaceOverrideMode BulletPhysicsServer::area_get_space_override_mode(RID p_area) const {
+ AreaBullet *area = area_owner.get(p_area);
+ ERR_FAIL_COND_V(!area, PhysicsServer::AREA_SPACE_OVERRIDE_DISABLED);
+
+ return area->get_spOv_mode();
+}
+
+void BulletPhysicsServer::area_add_shape(RID p_area, RID p_shape, const Transform &p_transform) {
+ AreaBullet *area = area_owner.get(p_area);
+ ERR_FAIL_COND(!area);
+
+ ShapeBullet *shape = shape_owner.get(p_shape);
+ ERR_FAIL_COND(!shape);
+
+ area->add_shape(shape, p_transform);
+}
+
+void BulletPhysicsServer::area_set_shape(RID p_area, int p_shape_idx, RID p_shape) {
+ AreaBullet *area = area_owner.get(p_area);
+ ERR_FAIL_COND(!area);
+
+ ShapeBullet *shape = shape_owner.get(p_shape);
+ ERR_FAIL_COND(!shape);
+
+ area->set_shape(p_shape_idx, shape);
+}
+
+void BulletPhysicsServer::area_set_shape_transform(RID p_area, int p_shape_idx, const Transform &p_transform) {
+ AreaBullet *area = area_owner.get(p_area);
+ ERR_FAIL_COND(!area);
+
+ area->set_shape_transform(p_shape_idx, p_transform);
+}
+
+int BulletPhysicsServer::area_get_shape_count(RID p_area) const {
+ AreaBullet *area = area_owner.get(p_area);
+ ERR_FAIL_COND_V(!area, 0);
+
+ return area->get_shape_count();
+}
+
+RID BulletPhysicsServer::area_get_shape(RID p_area, int p_shape_idx) const {
+ AreaBullet *area = area_owner.get(p_area);
+ ERR_FAIL_COND_V(!area, RID());
+
+ return area->get_shape(p_shape_idx)->get_self();
+}
+
+Transform BulletPhysicsServer::area_get_shape_transform(RID p_area, int p_shape_idx) const {
+ AreaBullet *area = area_owner.get(p_area);
+ ERR_FAIL_COND_V(!area, Transform());
+
+ return area->get_shape_transform(p_shape_idx);
+}
+
+void BulletPhysicsServer::area_remove_shape(RID p_area, int p_shape_idx) {
+ AreaBullet *area = area_owner.get(p_area);
+ ERR_FAIL_COND(!area);
+ return area->remove_shape(p_shape_idx);
+}
+
+void BulletPhysicsServer::area_clear_shapes(RID p_area) {
+ AreaBullet *area = area_owner.get(p_area);
+ ERR_FAIL_COND(!area);
+
+ for (int i = area->get_shape_count(); 0 < i; --i)
+ area->remove_shape(0);
+}
+
+void BulletPhysicsServer::area_set_shape_disabled(RID p_area, int p_shape_idx, bool p_disabled) {
+ AreaBullet *area = area_owner.get(p_area);
+ ERR_FAIL_COND(!area);
+
+ area->set_shape_disabled(p_shape_idx, p_disabled);
+}
+
+void BulletPhysicsServer::area_attach_object_instance_id(RID p_area, ObjectID p_ID) {
+ if (space_owner.owns(p_area)) {
+ return;
+ }
+ AreaBullet *area = area_owner.get(p_area);
+ ERR_FAIL_COND(!area);
+ area->set_instance_id(p_ID);
+}
+
+ObjectID BulletPhysicsServer::area_get_object_instance_id(RID p_area) const {
+ if (space_owner.owns(p_area)) {
+ return 0;
+ }
+ AreaBullet *area = area_owner.get(p_area);
+ ERR_FAIL_COND_V(!area, ObjectID());
+ return area->get_instance_id();
+}
+
+void BulletPhysicsServer::area_set_param(RID p_area, AreaParameter p_param, const Variant &p_value) {
+ if (space_owner.owns(p_area)) {
+ SpaceBullet *space = space_owner.get(p_area);
+ if (space) {
+ space->set_param(p_param, p_value);
+ }
+ } else {
+
+ AreaBullet *area = area_owner.get(p_area);
+ ERR_FAIL_COND(!area);
+
+ area->set_param(p_param, p_value);
+ }
+}
+
+Variant BulletPhysicsServer::area_get_param(RID p_area, AreaParameter p_param) const {
+ if (space_owner.owns(p_area)) {
+ SpaceBullet *space = space_owner.get(p_area);
+ return space->get_param(p_param);
+ } else {
+ AreaBullet *area = area_owner.get(p_area);
+ ERR_FAIL_COND_V(!area, Variant());
+
+ return area->get_param(p_param);
+ }
+}
+
+void BulletPhysicsServer::area_set_transform(RID p_area, const Transform &p_transform) {
+ AreaBullet *area = area_owner.get(p_area);
+ ERR_FAIL_COND(!area);
+ area->set_transform(p_transform);
+}
+
+Transform BulletPhysicsServer::area_get_transform(RID p_area) const {
+ AreaBullet *area = area_owner.get(p_area);
+ ERR_FAIL_COND_V(!area, Transform());
+ return area->get_transform();
+}
+
+void BulletPhysicsServer::area_set_collision_mask(RID p_area, uint32_t p_mask) {
+ AreaBullet *area = area_owner.get(p_area);
+ ERR_FAIL_COND(!area);
+ area->set_collision_mask(p_mask);
+}
+
+void BulletPhysicsServer::area_set_collision_layer(RID p_area, uint32_t p_layer) {
+ AreaBullet *area = area_owner.get(p_area);
+ ERR_FAIL_COND(!area);
+ area->set_collision_layer(p_layer);
+}
+
+void BulletPhysicsServer::area_set_monitorable(RID p_area, bool p_monitorable) {
+ AreaBullet *area = area_owner.get(p_area);
+ ERR_FAIL_COND(!area);
+
+ area->set_monitorable(p_monitorable);
+}
+
+void BulletPhysicsServer::area_set_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) {
+ AreaBullet *area = area_owner.get(p_area);
+ ERR_FAIL_COND(!area);
+
+ area->set_event_callback(CollisionObjectBullet::TYPE_RIGID_BODY, p_receiver ? p_receiver->get_instance_id() : 0, p_method);
+}
+
+void BulletPhysicsServer::area_set_area_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) {
+ AreaBullet *area = area_owner.get(p_area);
+ ERR_FAIL_COND(!area);
+
+ area->set_event_callback(CollisionObjectBullet::TYPE_AREA, p_receiver ? p_receiver->get_instance_id() : 0, p_method);
+}
+
+void BulletPhysicsServer::area_set_ray_pickable(RID p_area, bool p_enable) {
+ AreaBullet *area = area_owner.get(p_area);
+ ERR_FAIL_COND(!area);
+ area->set_ray_pickable(p_enable);
+}
+
+bool BulletPhysicsServer::area_is_ray_pickable(RID p_area) const {
+ AreaBullet *area = area_owner.get(p_area);
+ ERR_FAIL_COND_V(!area, false);
+ return area->is_ray_pickable();
+}
+
+RID BulletPhysicsServer::body_create(BodyMode p_mode, bool p_init_sleeping) {
+ RigidBodyBullet *body = bulletnew(RigidBodyBullet);
+ body->set_mode(p_mode);
+ body->set_collision_layer(1);
+ body->set_collision_mask(1);
+ if (p_init_sleeping)
+ body->set_state(BODY_STATE_SLEEPING, p_init_sleeping);
+ CreateThenReturnRID(rigid_body_owner, body);
+}
+
+void BulletPhysicsServer::body_set_space(RID p_body, RID p_space) {
+ RigidBodyBullet *body = rigid_body_owner.get(p_body);
+ ERR_FAIL_COND(!body);
+ SpaceBullet *space = NULL;
+
+ if (p_space.is_valid()) {
+ space = space_owner.get(p_space);
+ ERR_FAIL_COND(!space);
+ }
+
+ if (body->get_space() == space)
+ return; //pointles
+
+ body->set_space(space);
+}
+
+RID BulletPhysicsServer::body_get_space(RID p_body) const {
+ RigidBodyBullet *body = rigid_body_owner.get(p_body);
+ ERR_FAIL_COND_V(!body, RID());
+
+ SpaceBullet *space = body->get_space();
+ if (!space)
+ return RID();
+ return space->get_self();
+}
+
+void BulletPhysicsServer::body_set_mode(RID p_body, PhysicsServer::BodyMode p_mode) {
+ RigidBodyBullet *body = rigid_body_owner.get(p_body);
+ ERR_FAIL_COND(!body);
+ body->set_mode(p_mode);
+}
+
+PhysicsServer::BodyMode BulletPhysicsServer::body_get_mode(RID p_body) const {
+ RigidBodyBullet *body = rigid_body_owner.get(p_body);
+ ERR_FAIL_COND_V(!body, BODY_MODE_STATIC);
+ return body->get_mode();
+}
+
+void BulletPhysicsServer::body_add_shape(RID p_body, RID p_shape, const Transform &p_transform) {
+
+ RigidBodyBullet *body = rigid_body_owner.get(p_body);
+ ERR_FAIL_COND(!body);
+
+ ShapeBullet *shape = shape_owner.get(p_shape);
+ ERR_FAIL_COND(!shape);
+
+ body->add_shape(shape, p_transform);
+}
+
+void BulletPhysicsServer::body_set_shape(RID p_body, int p_shape_idx, RID p_shape) {
+ RigidBodyBullet *body = rigid_body_owner.get(p_body);
+ ERR_FAIL_COND(!body);
+
+ ShapeBullet *shape = shape_owner.get(p_shape);
+ ERR_FAIL_COND(!shape);
+
+ body->set_shape(p_shape_idx, shape);
+}
+
+void BulletPhysicsServer::body_set_shape_transform(RID p_body, int p_shape_idx, const Transform &p_transform) {
+ RigidBodyBullet *body = rigid_body_owner.get(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->set_shape_transform(p_shape_idx, p_transform);
+}
+
+int BulletPhysicsServer::body_get_shape_count(RID p_body) const {
+ RigidBodyBullet *body = rigid_body_owner.get(p_body);
+ ERR_FAIL_COND_V(!body, 0);
+ return body->get_shape_count();
+}
+
+RID BulletPhysicsServer::body_get_shape(RID p_body, int p_shape_idx) const {
+ RigidBodyBullet *body = rigid_body_owner.get(p_body);
+ ERR_FAIL_COND_V(!body, RID());
+
+ ShapeBullet *shape = body->get_shape(p_shape_idx);
+ ERR_FAIL_COND_V(!shape, RID());
+
+ return shape->get_self();
+}
+
+Transform BulletPhysicsServer::body_get_shape_transform(RID p_body, int p_shape_idx) const {
+ RigidBodyBullet *body = rigid_body_owner.get(p_body);
+ ERR_FAIL_COND_V(!body, Transform());
+ return body->get_shape_transform(p_shape_idx);
+}
+
+void BulletPhysicsServer::body_set_shape_disabled(RID p_body, int p_shape_idx, bool p_disabled) {
+ RigidBodyBullet *body = rigid_body_owner.get(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->set_shape_disabled(p_shape_idx, p_disabled);
+}
+
+void BulletPhysicsServer::body_remove_shape(RID p_body, int p_shape_idx) {
+ RigidBodyBullet *body = rigid_body_owner.get(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->remove_shape(p_shape_idx);
+}
+
+void BulletPhysicsServer::body_clear_shapes(RID p_body) {
+ RigidBodyBullet *body = rigid_body_owner.get(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->remove_all_shapes();
+}
+
+void BulletPhysicsServer::body_attach_object_instance_id(RID p_body, uint32_t p_ID) {
+ CollisionObjectBullet *body = get_collisin_object(p_body);
+ if (!body) {
+ body = soft_body_owner.get(p_body);
+ }
+ ERR_FAIL_COND(!body);
+
+ body->set_instance_id(p_ID);
+}
+
+uint32_t BulletPhysicsServer::body_get_object_instance_id(RID p_body) const {
+ CollisionObjectBullet *body = get_collisin_object(p_body);
+ ERR_FAIL_COND_V(!body, 0);
+
+ return body->get_instance_id();
+}
+
+void BulletPhysicsServer::body_set_enable_continuous_collision_detection(RID p_body, bool p_enable) {
+ RigidBodyBullet *body = rigid_body_owner.get(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->set_continuous_collision_detection(p_enable);
+}
+
+bool BulletPhysicsServer::body_is_continuous_collision_detection_enabled(RID p_body) const {
+ RigidBodyBullet *body = rigid_body_owner.get(p_body);
+ ERR_FAIL_COND_V(!body, false);
+
+ return body->is_continuous_collision_detection_enabled();
+}
+
+void BulletPhysicsServer::body_set_collision_layer(RID p_body, uint32_t p_layer) {
+ RigidBodyBullet *body = rigid_body_owner.get(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->set_collision_layer(p_layer);
+}
+
+uint32_t BulletPhysicsServer::body_get_collision_layer(RID p_body) const {
+ const RigidBodyBullet *body = rigid_body_owner.get(p_body);
+ ERR_FAIL_COND_V(!body, 0);
+
+ return body->get_collision_layer();
+}
+
+void BulletPhysicsServer::body_set_collision_mask(RID p_body, uint32_t p_mask) {
+ RigidBodyBullet *body = rigid_body_owner.get(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->set_collision_mask(p_mask);
+}
+
+uint32_t BulletPhysicsServer::body_get_collision_mask(RID p_body) const {
+ RigidBodyBullet *body = rigid_body_owner.get(p_body);
+ ERR_FAIL_COND_V(!body, 0);
+
+ return body->get_collision_mask();
+}
+
+void BulletPhysicsServer::body_set_user_flags(RID p_body, uint32_t p_flags) {
+ WARN_PRINT("This function si not currently supported by bullet and Godot");
+}
+
+uint32_t BulletPhysicsServer::body_get_user_flags(RID p_body) const {
+ WARN_PRINT("This function si not currently supported by bullet and Godot");
+ return 0;
+}
+
+void BulletPhysicsServer::body_set_param(RID p_body, BodyParameter p_param, float p_value) {
+ RigidBodyBullet *body = rigid_body_owner.get(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->set_param(p_param, p_value);
+}
+
+float BulletPhysicsServer::body_get_param(RID p_body, BodyParameter p_param) const {
+ RigidBodyBullet *body = rigid_body_owner.get(p_body);
+ ERR_FAIL_COND_V(!body, 0);
+
+ return body->get_param(p_param);
+}
+
+void BulletPhysicsServer::body_set_kinematic_safe_margin(RID p_body, real_t p_margin) {
+ RigidBodyBullet *body = rigid_body_owner.get(p_body);
+ ERR_FAIL_COND(!body);
+
+ if (body->get_kinematic_utilities()) {
+
+ body->get_kinematic_utilities()->setSafeMargin(p_margin);
+ }
+}
+
+real_t BulletPhysicsServer::body_get_kinematic_safe_margin(RID p_body) const {
+ RigidBodyBullet *body = rigid_body_owner.get(p_body);
+ ERR_FAIL_COND_V(!body, 0);
+
+ if (body->get_kinematic_utilities()) {
+
+ return body->get_kinematic_utilities()->safe_margin;
+ }
+
+ return 0;
+}
+
+void BulletPhysicsServer::body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) {
+ RigidBodyBullet *body = rigid_body_owner.get(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->set_state(p_state, p_variant);
+}
+
+Variant BulletPhysicsServer::body_get_state(RID p_body, BodyState p_state) const {
+ RigidBodyBullet *body = rigid_body_owner.get(p_body);
+ ERR_FAIL_COND_V(!body, Variant());
+
+ return body->get_state(p_state);
+}
+
+void BulletPhysicsServer::body_set_applied_force(RID p_body, const Vector3 &p_force) {
+ RigidBodyBullet *body = rigid_body_owner.get(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->set_applied_force(p_force);
+}
+
+Vector3 BulletPhysicsServer::body_get_applied_force(RID p_body) const {
+ RigidBodyBullet *body = rigid_body_owner.get(p_body);
+ ERR_FAIL_COND_V(!body, Vector3());
+ return body->get_applied_force();
+}
+
+void BulletPhysicsServer::body_set_applied_torque(RID p_body, const Vector3 &p_torque) {
+ RigidBodyBullet *body = rigid_body_owner.get(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->set_applied_torque(p_torque);
+}
+
+Vector3 BulletPhysicsServer::body_get_applied_torque(RID p_body) const {
+ RigidBodyBullet *body = rigid_body_owner.get(p_body);
+ ERR_FAIL_COND_V(!body, Vector3());
+
+ return body->get_applied_torque();
+}
+
+void BulletPhysicsServer::body_apply_impulse(RID p_body, const Vector3 &p_pos, const Vector3 &p_impulse) {
+ RigidBodyBullet *body = rigid_body_owner.get(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->apply_impulse(p_pos, p_impulse);
+}
+
+void BulletPhysicsServer::body_apply_torque_impulse(RID p_body, const Vector3 &p_impulse) {
+ RigidBodyBullet *body = rigid_body_owner.get(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->apply_torque_impulse(p_impulse);
+}
+
+void BulletPhysicsServer::body_set_axis_velocity(RID p_body, const Vector3 &p_axis_velocity) {
+ RigidBodyBullet *body = rigid_body_owner.get(p_body);
+ ERR_FAIL_COND(!body);
+
+ Vector3 v = body->get_linear_velocity();
+ Vector3 axis = p_axis_velocity.normalized();
+ v -= axis * axis.dot(v);
+ v += p_axis_velocity;
+ body->set_linear_velocity(v);
+}
+
+void BulletPhysicsServer::body_set_axis_lock(RID p_body, PhysicsServer::BodyAxisLock p_lock) {
+ RigidBodyBullet *body = rigid_body_owner.get(p_body);
+ ERR_FAIL_COND(!body);
+ body->set_axis_lock(p_lock);
+}
+
+PhysicsServer::BodyAxisLock BulletPhysicsServer::body_get_axis_lock(RID p_body) const {
+ const RigidBodyBullet *body = rigid_body_owner.get(p_body);
+ ERR_FAIL_COND_V(!body, BODY_AXIS_LOCK_DISABLED);
+ return body->get_axis_lock();
+}
+
+void BulletPhysicsServer::body_add_collision_exception(RID p_body, RID p_body_b) {
+ RigidBodyBullet *body = rigid_body_owner.get(p_body);
+ ERR_FAIL_COND(!body);
+
+ RigidBodyBullet *other_body = rigid_body_owner.get(p_body_b);
+ ERR_FAIL_COND(!other_body);
+
+ body->add_collision_exception(other_body);
+}
+
+void BulletPhysicsServer::body_remove_collision_exception(RID p_body, RID p_body_b) {
+ RigidBodyBullet *body = rigid_body_owner.get(p_body);
+ ERR_FAIL_COND(!body);
+
+ RigidBodyBullet *other_body = rigid_body_owner.get(p_body_b);
+ ERR_FAIL_COND(!other_body);
+
+ body->remove_collision_exception(other_body);
+}
+
+void BulletPhysicsServer::body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions) {
+ RigidBodyBullet *body = rigid_body_owner.get(p_body);
+ ERR_FAIL_COND(!body);
+ for (int i = 0; i < body->get_exceptions().size(); i++) {
+ p_exceptions->push_back(body->get_exceptions()[i]);
+ }
+}
+
+void BulletPhysicsServer::body_set_max_contacts_reported(RID p_body, int p_contacts) {
+ RigidBodyBullet *body = rigid_body_owner.get(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->set_max_collisions_detection(p_contacts);
+}
+
+int BulletPhysicsServer::body_get_max_contacts_reported(RID p_body) const {
+ RigidBodyBullet *body = rigid_body_owner.get(p_body);
+ ERR_FAIL_COND_V(!body, 0);
+
+ return body->get_max_collisions_detection();
+}
+
+void BulletPhysicsServer::body_set_contacts_reported_depth_threshold(RID p_body, float p_treshold) {
+ WARN_PRINT("Not supported by bullet and even Godot");
+}
+
+float BulletPhysicsServer::body_get_contacts_reported_depth_threshold(RID p_body) const {
+ WARN_PRINT("Not supported by bullet and even Godot");
+ return 0.;
+}
+
+void BulletPhysicsServer::body_set_omit_force_integration(RID p_body, bool p_omit) {
+ WARN_PRINT("Not supported by bullet");
+}
+
+bool BulletPhysicsServer::body_is_omitting_force_integration(RID p_body) const {
+ WARN_PRINT("Not supported by bullet");
+ return false;
+}
+
+void BulletPhysicsServer::body_set_force_integration_callback(RID p_body, Object *p_receiver, const StringName &p_method, const Variant &p_udata) {
+ RigidBodyBullet *body = rigid_body_owner.get(p_body);
+ ERR_FAIL_COND(!body);
+ body->set_force_integration_callback(p_receiver->get_instance_id(), p_method, p_udata);
+}
+
+void BulletPhysicsServer::body_set_ray_pickable(RID p_body, bool p_enable) {
+ RigidBodyBullet *body = rigid_body_owner.get(p_body);
+ ERR_FAIL_COND(!body);
+ body->set_ray_pickable(p_enable);
+}
+
+bool BulletPhysicsServer::body_is_ray_pickable(RID p_body) const {
+ RigidBodyBullet *body = rigid_body_owner.get(p_body);
+ ERR_FAIL_COND_V(!body, false);
+ return body->is_ray_pickable();
+}
+
+PhysicsDirectBodyState *BulletPhysicsServer::body_get_direct_state(RID p_body) {
+ RigidBodyBullet *body = rigid_body_owner.get(p_body);
+ ERR_FAIL_COND_V(!body, NULL);
+ return BulletPhysicsDirectBodyState::get_singleton(body);
+}
+
+bool BulletPhysicsServer::body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, MotionResult *r_result) {
+ RigidBodyBullet *body = rigid_body_owner.get(p_body);
+ ERR_FAIL_COND_V(!body, false);
+ ERR_FAIL_COND_V(!body->get_space(), false);
+
+ return body->get_space()->test_body_motion(body, p_from, p_motion, r_result);
+}
+
+RID BulletPhysicsServer::soft_body_create(bool p_init_sleeping) {
+ SoftBodyBullet *body = bulletnew(SoftBodyBullet);
+ body->set_collision_layer(1);
+ body->set_collision_mask(1);
+ if (p_init_sleeping)
+ body->set_activation_state(false);
+ CreateThenReturnRID(soft_body_owner, body);
+}
+
+void BulletPhysicsServer::soft_body_set_space(RID p_body, RID p_space) {
+ SoftBodyBullet *body = soft_body_owner.get(p_body);
+ ERR_FAIL_COND(!body);
+ SpaceBullet *space = NULL;
+
+ if (p_space.is_valid()) {
+ space = space_owner.get(p_space);
+ ERR_FAIL_COND(!space);
+ }
+
+ if (body->get_space() == space)
+ return; //pointles
+
+ body->set_space(space);
+}
+
+RID BulletPhysicsServer::soft_body_get_space(RID p_body) const {
+ SoftBodyBullet *body = soft_body_owner.get(p_body);
+ ERR_FAIL_COND_V(!body, RID());
+
+ SpaceBullet *space = body->get_space();
+ if (!space)
+ return RID();
+ return space->get_self();
+}
+
+void BulletPhysicsServer::soft_body_set_trimesh_body_shape(RID p_body, PoolVector<int> p_indices, PoolVector<Vector3> p_vertices, int p_triangles_num) {
+ SoftBodyBullet *body = soft_body_owner.get(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->set_trimesh_body_shape(p_indices, p_vertices, p_triangles_num);
+}
+
+void BulletPhysicsServer::soft_body_set_collision_layer(RID p_body, uint32_t p_layer) {
+ SoftBodyBullet *body = soft_body_owner.get(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->set_collision_layer(p_layer);
+}
+
+uint32_t BulletPhysicsServer::soft_body_get_collision_layer(RID p_body) const {
+ const SoftBodyBullet *body = soft_body_owner.get(p_body);
+ ERR_FAIL_COND_V(!body, 0);
+
+ return body->get_collision_layer();
+}
+
+void BulletPhysicsServer::soft_body_set_collision_mask(RID p_body, uint32_t p_mask) {
+ SoftBodyBullet *body = soft_body_owner.get(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->set_collision_mask(p_mask);
+}
+
+uint32_t BulletPhysicsServer::soft_body_get_collision_mask(RID p_body) const {
+ const SoftBodyBullet *body = soft_body_owner.get(p_body);
+ ERR_FAIL_COND_V(!body, 0);
+
+ return body->get_collision_mask();
+}
+
+void BulletPhysicsServer::soft_body_add_collision_exception(RID p_body, RID p_body_b) {
+ SoftBodyBullet *body = soft_body_owner.get(p_body);
+ ERR_FAIL_COND(!body);
+
+ CollisionObjectBullet *other_body = rigid_body_owner.get(p_body_b);
+ if (!other_body) {
+ other_body = soft_body_owner.get(p_body_b);
+ }
+ ERR_FAIL_COND(!other_body);
+
+ body->add_collision_exception(other_body);
+}
+
+void BulletPhysicsServer::soft_body_remove_collision_exception(RID p_body, RID p_body_b) {
+ SoftBodyBullet *body = soft_body_owner.get(p_body);
+ ERR_FAIL_COND(!body);
+
+ CollisionObjectBullet *other_body = rigid_body_owner.get(p_body_b);
+ if (!other_body) {
+ other_body = soft_body_owner.get(p_body_b);
+ }
+ ERR_FAIL_COND(!other_body);
+
+ body->remove_collision_exception(other_body);
+}
+
+void BulletPhysicsServer::soft_body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions) {
+ SoftBodyBullet *body = soft_body_owner.get(p_body);
+ ERR_FAIL_COND(!body);
+ for (int i = 0; i < body->get_exceptions().size(); i++) {
+ p_exceptions->push_back(body->get_exceptions()[i]);
+ }
+}
+
+void BulletPhysicsServer::soft_body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) {
+ print_line("TODO MUST BE IMPLEMENTED");
+}
+
+Variant BulletPhysicsServer::soft_body_get_state(RID p_body, BodyState p_state) const {
+ print_line("TODO MUST BE IMPLEMENTED");
+ return Variant();
+}
+
+void BulletPhysicsServer::soft_body_set_transform(RID p_body, const Transform &p_transform) {
+ SoftBodyBullet *body = soft_body_owner.get(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->set_transform(p_transform);
+}
+
+Transform BulletPhysicsServer::soft_body_get_transform(RID p_body) const {
+ const SoftBodyBullet *body = soft_body_owner.get(p_body);
+ ERR_FAIL_COND_V(!body, Transform());
+
+ return body->get_transform();
+}
+
+void BulletPhysicsServer::soft_body_set_ray_pickable(RID p_body, bool p_enable) {
+ SoftBodyBullet *body = soft_body_owner.get(p_body);
+ ERR_FAIL_COND(!body);
+ body->set_ray_pickable(p_enable);
+}
+
+bool BulletPhysicsServer::soft_body_is_ray_pickable(RID p_body) const {
+ SoftBodyBullet *body = soft_body_owner.get(p_body);
+ ERR_FAIL_COND_V(!body, false);
+ return body->is_ray_pickable();
+}
+
+PhysicsServer::JointType BulletPhysicsServer::joint_get_type(RID p_joint) const {
+ JointBullet *joint = joint_owner.get(p_joint);
+ ERR_FAIL_COND_V(!joint, JOINT_PIN);
+ return joint->get_type();
+}
+
+void BulletPhysicsServer::joint_set_solver_priority(RID p_joint, int p_priority) {
+ //WARN_PRINTS("Joint priority not supported by bullet");
+}
+
+int BulletPhysicsServer::joint_get_solver_priority(RID p_joint) const {
+ //WARN_PRINTS("Joint priority not supported by bullet");
+ return 0;
+}
+
+RID BulletPhysicsServer::joint_create_pin(RID p_body_A, const Vector3 &p_local_A, RID p_body_B, const Vector3 &p_local_B) {
+ RigidBodyBullet *body_A = rigid_body_owner.get(p_body_A);
+ ERR_FAIL_COND_V(!body_A, RID());
+
+ JointAssertSpace(body_A, "A", RID());
+
+ RigidBodyBullet *body_B = NULL;
+ if (p_body_B.is_valid()) {
+ body_B = rigid_body_owner.get(p_body_B);
+ JointAssertSpace(body_B, "B", RID());
+ JointAssertSameSpace(body_A, body_B, RID());
+ }
+
+ ERR_FAIL_COND_V(body_A == body_B, RID());
+
+ JointBullet *joint = bulletnew(PinJointBullet(body_A, p_local_A, body_B, p_local_B));
+ AddJointToSpace(body_A, joint, true);
+
+ CreateThenReturnRID(joint_owner, joint);
+}
+
+void BulletPhysicsServer::pin_joint_set_param(RID p_joint, PinJointParam p_param, float p_value) {
+ JointBullet *joint = joint_owner.get(p_joint);
+ ERR_FAIL_COND(!joint);
+ ERR_FAIL_COND(joint->get_type() != JOINT_PIN);
+ PinJointBullet *pin_joint = static_cast<PinJointBullet *>(joint);
+ pin_joint->set_param(p_param, p_value);
+}
+
+float BulletPhysicsServer::pin_joint_get_param(RID p_joint, PinJointParam p_param) const {
+ JointBullet *joint = joint_owner.get(p_joint);
+ ERR_FAIL_COND_V(!joint, 0);
+ ERR_FAIL_COND_V(joint->get_type() != JOINT_PIN, 0);
+ PinJointBullet *pin_joint = static_cast<PinJointBullet *>(joint);
+ return pin_joint->get_param(p_param);
+}
+
+void BulletPhysicsServer::pin_joint_set_local_a(RID p_joint, const Vector3 &p_A) {
+ JointBullet *joint = joint_owner.get(p_joint);
+ ERR_FAIL_COND(!joint);
+ ERR_FAIL_COND(joint->get_type() != JOINT_PIN);
+ PinJointBullet *pin_joint = static_cast<PinJointBullet *>(joint);
+ pin_joint->setPivotInA(p_A);
+}
+
+Vector3 BulletPhysicsServer::pin_joint_get_local_a(RID p_joint) const {
+ JointBullet *joint = joint_owner.get(p_joint);
+ ERR_FAIL_COND_V(!joint, Vector3());
+ ERR_FAIL_COND_V(joint->get_type() != JOINT_PIN, Vector3());
+ PinJointBullet *pin_joint = static_cast<PinJointBullet *>(joint);
+ return pin_joint->getPivotInA();
+}
+
+void BulletPhysicsServer::pin_joint_set_local_b(RID p_joint, const Vector3 &p_B) {
+ JointBullet *joint = joint_owner.get(p_joint);
+ ERR_FAIL_COND(!joint);
+ ERR_FAIL_COND(joint->get_type() != JOINT_PIN);
+ PinJointBullet *pin_joint = static_cast<PinJointBullet *>(joint);
+ pin_joint->setPivotInB(p_B);
+}
+
+Vector3 BulletPhysicsServer::pin_joint_get_local_b(RID p_joint) const {
+ JointBullet *joint = joint_owner.get(p_joint);
+ ERR_FAIL_COND_V(!joint, Vector3());
+ ERR_FAIL_COND_V(joint->get_type() != JOINT_PIN, Vector3());
+ PinJointBullet *pin_joint = static_cast<PinJointBullet *>(joint);
+ return pin_joint->getPivotInB();
+}
+
+RID BulletPhysicsServer::joint_create_hinge(RID p_body_A, const Transform &p_hinge_A, RID p_body_B, const Transform &p_hinge_B) {
+ RigidBodyBullet *body_A = rigid_body_owner.get(p_body_A);
+ ERR_FAIL_COND_V(!body_A, RID());
+ JointAssertSpace(body_A, "A", RID());
+
+ RigidBodyBullet *body_B = NULL;
+ if (p_body_B.is_valid()) {
+ body_B = rigid_body_owner.get(p_body_B);
+ JointAssertSpace(body_B, "B", RID());
+ JointAssertSameSpace(body_A, body_B, RID());
+ }
+
+ ERR_FAIL_COND_V(body_A == body_B, RID());
+
+ JointBullet *joint = bulletnew(HingeJointBullet(body_A, body_B, p_hinge_A, p_hinge_B));
+ AddJointToSpace(body_A, joint, true);
+
+ CreateThenReturnRID(joint_owner, joint);
+}
+
+RID BulletPhysicsServer::joint_create_hinge_simple(RID p_body_A, const Vector3 &p_pivot_A, const Vector3 &p_axis_A, RID p_body_B, const Vector3 &p_pivot_B, const Vector3 &p_axis_B) {
+ RigidBodyBullet *body_A = rigid_body_owner.get(p_body_A);
+ ERR_FAIL_COND_V(!body_A, RID());
+ JointAssertSpace(body_A, "A", RID());
+
+ RigidBodyBullet *body_B = NULL;
+ if (p_body_B.is_valid()) {
+ body_B = rigid_body_owner.get(p_body_B);
+ JointAssertSpace(body_B, "B", RID());
+ JointAssertSameSpace(body_A, body_B, RID());
+ }
+
+ ERR_FAIL_COND_V(body_A == body_B, RID());
+
+ JointBullet *joint = bulletnew(HingeJointBullet(body_A, body_B, p_pivot_A, p_pivot_B, p_axis_A, p_axis_B));
+ AddJointToSpace(body_A, joint, true);
+
+ CreateThenReturnRID(joint_owner, joint);
+}
+
+void BulletPhysicsServer::hinge_joint_set_param(RID p_joint, HingeJointParam p_param, float p_value) {
+ JointBullet *joint = joint_owner.get(p_joint);
+ ERR_FAIL_COND(!joint);
+ ERR_FAIL_COND(joint->get_type() != JOINT_HINGE);
+ HingeJointBullet *hinge_joint = static_cast<HingeJointBullet *>(joint);
+ hinge_joint->set_param(p_param, p_value);
+}
+
+float BulletPhysicsServer::hinge_joint_get_param(RID p_joint, HingeJointParam p_param) const {
+ JointBullet *joint = joint_owner.get(p_joint);
+ ERR_FAIL_COND_V(!joint, 0);
+ ERR_FAIL_COND_V(joint->get_type() != JOINT_HINGE, 0);
+ HingeJointBullet *hinge_joint = static_cast<HingeJointBullet *>(joint);
+ return hinge_joint->get_param(p_param);
+}
+
+void BulletPhysicsServer::hinge_joint_set_flag(RID p_joint, HingeJointFlag p_flag, bool p_value) {
+ JointBullet *joint = joint_owner.get(p_joint);
+ ERR_FAIL_COND(!joint);
+ ERR_FAIL_COND(joint->get_type() != JOINT_HINGE);
+ HingeJointBullet *hinge_joint = static_cast<HingeJointBullet *>(joint);
+ hinge_joint->set_flag(p_flag, p_value);
+}
+
+bool BulletPhysicsServer::hinge_joint_get_flag(RID p_joint, HingeJointFlag p_flag) const {
+ JointBullet *joint = joint_owner.get(p_joint);
+ ERR_FAIL_COND_V(!joint, false);
+ ERR_FAIL_COND_V(joint->get_type() != JOINT_HINGE, false);
+ HingeJointBullet *hinge_joint = static_cast<HingeJointBullet *>(joint);
+ return hinge_joint->get_flag(p_flag);
+}
+
+RID BulletPhysicsServer::joint_create_slider(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) {
+ RigidBodyBullet *body_A = rigid_body_owner.get(p_body_A);
+ ERR_FAIL_COND_V(!body_A, RID());
+ JointAssertSpace(body_A, "A", RID());
+
+ RigidBodyBullet *body_B = NULL;
+ if (p_body_B.is_valid()) {
+ body_B = rigid_body_owner.get(p_body_B);
+ JointAssertSpace(body_B, "B", RID());
+ JointAssertSameSpace(body_A, body_B, RID());
+ }
+
+ ERR_FAIL_COND_V(body_A == body_B, RID());
+
+ JointBullet *joint = bulletnew(SliderJointBullet(body_A, body_B, p_local_frame_A, p_local_frame_B));
+ AddJointToSpace(body_A, joint, true);
+
+ CreateThenReturnRID(joint_owner, joint);
+}
+
+void BulletPhysicsServer::slider_joint_set_param(RID p_joint, SliderJointParam p_param, float p_value) {
+ JointBullet *joint = joint_owner.get(p_joint);
+ ERR_FAIL_COND(!joint);
+ ERR_FAIL_COND(joint->get_type() != JOINT_SLIDER);
+ SliderJointBullet *slider_joint = static_cast<SliderJointBullet *>(joint);
+ slider_joint->set_param(p_param, p_value);
+}
+
+float BulletPhysicsServer::slider_joint_get_param(RID p_joint, SliderJointParam p_param) const {
+ JointBullet *joint = joint_owner.get(p_joint);
+ ERR_FAIL_COND_V(!joint, 0);
+ ERR_FAIL_COND_V(joint->get_type() != JOINT_SLIDER, 0);
+ SliderJointBullet *slider_joint = static_cast<SliderJointBullet *>(joint);
+ return slider_joint->get_param(p_param);
+}
+
+RID BulletPhysicsServer::joint_create_cone_twist(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) {
+ RigidBodyBullet *body_A = rigid_body_owner.get(p_body_A);
+ ERR_FAIL_COND_V(!body_A, RID());
+ JointAssertSpace(body_A, "A", RID());
+
+ RigidBodyBullet *body_B = NULL;
+ if (p_body_B.is_valid()) {
+ body_B = rigid_body_owner.get(p_body_B);
+ JointAssertSpace(body_B, "B", RID());
+ JointAssertSameSpace(body_A, body_B, RID());
+ }
+
+ JointBullet *joint = bulletnew(ConeTwistJointBullet(body_A, body_B, p_local_frame_A, p_local_frame_B));
+ AddJointToSpace(body_A, joint, true);
+
+ CreateThenReturnRID(joint_owner, joint);
+}
+
+void BulletPhysicsServer::cone_twist_joint_set_param(RID p_joint, ConeTwistJointParam p_param, float p_value) {
+ JointBullet *joint = joint_owner.get(p_joint);
+ ERR_FAIL_COND(!joint);
+ ERR_FAIL_COND(joint->get_type() != JOINT_CONE_TWIST);
+ ConeTwistJointBullet *coneTwist_joint = static_cast<ConeTwistJointBullet *>(joint);
+ coneTwist_joint->set_param(p_param, p_value);
+}
+
+float BulletPhysicsServer::cone_twist_joint_get_param(RID p_joint, ConeTwistJointParam p_param) const {
+ JointBullet *joint = joint_owner.get(p_joint);
+ ERR_FAIL_COND_V(!joint, 0.);
+ ERR_FAIL_COND_V(joint->get_type() != JOINT_CONE_TWIST, 0.);
+ ConeTwistJointBullet *coneTwist_joint = static_cast<ConeTwistJointBullet *>(joint);
+ return coneTwist_joint->get_param(p_param);
+}
+
+RID BulletPhysicsServer::joint_create_generic_6dof(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) {
+ RigidBodyBullet *body_A = rigid_body_owner.get(p_body_A);
+ ERR_FAIL_COND_V(!body_A, RID());
+ JointAssertSpace(body_A, "A", RID());
+
+ RigidBodyBullet *body_B = NULL;
+ if (p_body_B.is_valid()) {
+ body_B = rigid_body_owner.get(p_body_B);
+ JointAssertSpace(body_B, "B", RID());
+ JointAssertSameSpace(body_A, body_B, RID());
+ }
+
+ ERR_FAIL_COND_V(body_A == body_B, RID());
+
+ JointBullet *joint = bulletnew(Generic6DOFJointBullet(body_A, body_B, p_local_frame_A, p_local_frame_B, true));
+ AddJointToSpace(body_A, joint, true);
+
+ CreateThenReturnRID(joint_owner, joint);
+}
+
+void BulletPhysicsServer::generic_6dof_joint_set_param(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisParam p_param, float p_value) {
+ JointBullet *joint = joint_owner.get(p_joint);
+ ERR_FAIL_COND(!joint);
+ ERR_FAIL_COND(joint->get_type() != JOINT_6DOF);
+ Generic6DOFJointBullet *generic_6dof_joint = static_cast<Generic6DOFJointBullet *>(joint);
+ generic_6dof_joint->set_param(p_axis, p_param, p_value);
+}
+
+float BulletPhysicsServer::generic_6dof_joint_get_param(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisParam p_param) {
+ JointBullet *joint = joint_owner.get(p_joint);
+ ERR_FAIL_COND_V(!joint, 0);
+ ERR_FAIL_COND_V(joint->get_type() != JOINT_6DOF, 0);
+ Generic6DOFJointBullet *generic_6dof_joint = static_cast<Generic6DOFJointBullet *>(joint);
+ return generic_6dof_joint->get_param(p_axis, p_param);
+}
+
+void BulletPhysicsServer::generic_6dof_joint_set_flag(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisFlag p_flag, bool p_enable) {
+ JointBullet *joint = joint_owner.get(p_joint);
+ ERR_FAIL_COND(!joint);
+ ERR_FAIL_COND(joint->get_type() != JOINT_6DOF);
+ Generic6DOFJointBullet *generic_6dof_joint = static_cast<Generic6DOFJointBullet *>(joint);
+ generic_6dof_joint->set_flag(p_axis, p_flag, p_enable);
+}
+
+bool BulletPhysicsServer::generic_6dof_joint_get_flag(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisFlag p_flag) {
+ JointBullet *joint = joint_owner.get(p_joint);
+ ERR_FAIL_COND_V(!joint, false);
+ ERR_FAIL_COND_V(joint->get_type() != JOINT_6DOF, false);
+ Generic6DOFJointBullet *generic_6dof_joint = static_cast<Generic6DOFJointBullet *>(joint);
+ return generic_6dof_joint->get_flag(p_axis, p_flag);
+}
+
+void BulletPhysicsServer::free(RID p_rid) {
+ if (shape_owner.owns(p_rid)) {
+
+ ShapeBullet *shape = shape_owner.get(p_rid);
+
+ // Notify the shape is configured
+ for (Map<ShapeOwnerBullet *, int>::Element *element = shape->get_owners().front(); element; element = element->next()) {
+ static_cast<ShapeOwnerBullet *>(element->key())->remove_shape(shape);
+ }
+
+ shape_owner.free(p_rid);
+ bulletdelete(shape);
+ } else if (rigid_body_owner.owns(p_rid)) {
+
+ RigidBodyBullet *body = rigid_body_owner.get(p_rid);
+
+ body->set_space(NULL);
+
+ body->remove_all_shapes(true);
+
+ rigid_body_owner.free(p_rid);
+ bulletdelete(body);
+
+ } else if (soft_body_owner.owns(p_rid)) {
+
+ SoftBodyBullet *body = soft_body_owner.get(p_rid);
+
+ body->set_space(NULL);
+
+ soft_body_owner.free(p_rid);
+ bulletdelete(body);
+
+ } else if (area_owner.owns(p_rid)) {
+
+ AreaBullet *area = area_owner.get(p_rid);
+
+ area->set_space(NULL);
+
+ area->remove_all_shapes(true);
+
+ area_owner.free(p_rid);
+ bulletdelete(area);
+
+ } else if (joint_owner.owns(p_rid)) {
+
+ JointBullet *joint = joint_owner.get(p_rid);
+ joint->destroy_internal_constraint();
+ joint_owner.free(p_rid);
+ bulletdelete(joint);
+
+ } else if (space_owner.owns(p_rid)) {
+
+ SpaceBullet *space = space_owner.get(p_rid);
+
+ space->remove_all_collision_objects();
+
+ space_set_active(p_rid, false);
+ space_owner.free(p_rid);
+ bulletdelete(space);
+ } else {
+
+ ERR_EXPLAIN("Invalid ID");
+ ERR_FAIL();
+ }
+}
+
+void BulletPhysicsServer::init() {
+ BulletPhysicsDirectBodyState::initSingleton();
+}
+
+void BulletPhysicsServer::step(float p_deltaTime) {
+ if (!active)
+ return;
+
+ BulletPhysicsDirectBodyState::singleton_setDeltaTime(p_deltaTime);
+
+ for (int i = 0; i < active_spaces_count; ++i) {
+
+ active_spaces[i]->step(p_deltaTime);
+ }
+}
+
+void BulletPhysicsServer::sync() {
+}
+
+void BulletPhysicsServer::flush_queries() {
+}
+
+void BulletPhysicsServer::finish() {
+ BulletPhysicsDirectBodyState::destroySingleton();
+}
+
+int BulletPhysicsServer::get_process_info(ProcessInfo p_info) {
+ return 0;
+}
+
+CollisionObjectBullet *BulletPhysicsServer::get_collisin_object(RID p_object) const {
+ if (rigid_body_owner.owns(p_object)) {
+ return rigid_body_owner.getornull(p_object);
+ }
+ if (area_owner.owns(p_object)) {
+ return area_owner.getornull(p_object);
+ }
+ if (soft_body_owner.owns(p_object)) {
+ return soft_body_owner.getornull(p_object);
+ }
+ return NULL;
+}
+
+RigidCollisionObjectBullet *BulletPhysicsServer::get_rigid_collisin_object(RID p_object) const {
+ if (rigid_body_owner.owns(p_object)) {
+ return rigid_body_owner.getornull(p_object);
+ }
+ if (area_owner.owns(p_object)) {
+ return area_owner.getornull(p_object);
+ }
+ return NULL;
+}
diff --git a/modules/bullet/bullet_physics_server.h b/modules/bullet/bullet_physics_server.h
new file mode 100644
index 0000000000..ad8137ee2f
--- /dev/null
+++ b/modules/bullet/bullet_physics_server.h
@@ -0,0 +1,362 @@
+/*************************************************************************/
+/* bullet_physics_server.h */
+/* Author: AndreaCatania */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef BULLET_PHYSICS_SERVER_H
+#define BULLET_PHYSICS_SERVER_H
+
+#include "area_bullet.h"
+#include "joint_bullet.h"
+#include "rid.h"
+#include "rigid_body_bullet.h"
+#include "servers/physics_server.h"
+#include "shape_bullet.h"
+#include "soft_body_bullet.h"
+#include "space_bullet.h"
+
+class BulletPhysicsServer : public PhysicsServer {
+ GDCLASS(BulletPhysicsServer, PhysicsServer)
+
+ friend class BulletPhysicsDirectSpaceState;
+
+ bool active;
+ char active_spaces_count;
+ Vector<SpaceBullet *> active_spaces;
+
+ mutable RID_Owner<SpaceBullet> space_owner;
+ mutable RID_Owner<ShapeBullet> shape_owner;
+ mutable RID_Owner<AreaBullet> area_owner;
+ mutable RID_Owner<RigidBodyBullet> rigid_body_owner;
+ mutable RID_Owner<SoftBodyBullet> soft_body_owner;
+ mutable RID_Owner<JointBullet> joint_owner;
+
+private:
+ /// This is used when a collision shape is not active, so the bullet compound shapes index are always sync with godot index
+ static btEmptyShape *emptyShape;
+
+public:
+ static btEmptyShape *get_empty_shape();
+
+protected:
+ static void _bind_methods();
+
+public:
+ BulletPhysicsServer();
+ ~BulletPhysicsServer();
+
+ _FORCE_INLINE_ RID_Owner<SpaceBullet> *get_space_owner() {
+ return &space_owner;
+ }
+ _FORCE_INLINE_ RID_Owner<ShapeBullet> *get_shape_owner() {
+ return &shape_owner;
+ }
+ _FORCE_INLINE_ RID_Owner<AreaBullet> *get_area_owner() {
+ return &area_owner;
+ }
+ _FORCE_INLINE_ RID_Owner<RigidBodyBullet> *get_rigid_body_owner() {
+ return &rigid_body_owner;
+ }
+ _FORCE_INLINE_ RID_Owner<SoftBodyBullet> *get_soft_body_owner() {
+ return &soft_body_owner;
+ }
+ _FORCE_INLINE_ RID_Owner<JointBullet> *get_joint_owner() {
+ return &joint_owner;
+ }
+
+ /* SHAPE API */
+ virtual RID shape_create(ShapeType p_shape);
+ virtual void shape_set_data(RID p_shape, const Variant &p_data);
+ virtual ShapeType shape_get_type(RID p_shape) const;
+ virtual Variant shape_get_data(RID p_shape) const;
+
+ /// Not supported
+ virtual void shape_set_custom_solver_bias(RID p_shape, real_t p_bias);
+ /// Not supported
+ virtual real_t shape_get_custom_solver_bias(RID p_shape) const;
+
+ /* SPACE API */
+
+ virtual RID space_create();
+ virtual void space_set_active(RID p_space, bool p_active);
+ virtual bool space_is_active(RID p_space) const;
+
+ /// Not supported
+ virtual void space_set_param(RID p_space, SpaceParameter p_param, real_t p_value);
+ /// Not supported
+ virtual real_t space_get_param(RID p_space, SpaceParameter p_param) const;
+
+ virtual PhysicsDirectSpaceState *space_get_direct_state(RID p_space);
+
+ virtual void space_set_debug_contacts(RID p_space, int p_max_contacts);
+ virtual Vector<Vector3> space_get_contacts(RID p_space) const;
+ virtual int space_get_contact_count(RID p_space) const;
+
+ /* AREA API */
+
+ /// Bullet Physics Engine not support "Area", this must be handled by the game developer in another way.
+ /// Since godot Physics use the concept of area even to define the main world, the API area_set_param is used to set initial physics world information.
+ /// The API area_set_param is a bit hacky, and allow Godot to set some parameters on Bullet's world, a different use print a warning to console.
+ /// All other APIs returns a warning message if used
+
+ virtual RID area_create();
+
+ virtual void area_set_space(RID p_area, RID p_space);
+
+ virtual RID area_get_space(RID p_area) const;
+
+ virtual void area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode);
+ virtual AreaSpaceOverrideMode area_get_space_override_mode(RID p_area) const;
+
+ virtual void area_add_shape(RID p_area, RID p_shape, const Transform &p_transform = Transform());
+ virtual void area_set_shape(RID p_area, int p_shape_idx, RID p_shape);
+ virtual void area_set_shape_transform(RID p_area, int p_shape_idx, const Transform &p_transform);
+ virtual int area_get_shape_count(RID p_area) const;
+ virtual RID area_get_shape(RID p_area, int p_shape_idx) const;
+ virtual Transform area_get_shape_transform(RID p_area, int p_shape_idx) const;
+ virtual void area_remove_shape(RID p_area, int p_shape_idx);
+ virtual void area_clear_shapes(RID p_area);
+ virtual void area_set_shape_disabled(RID p_area, int p_shape_idx, bool p_disabled);
+ virtual void area_attach_object_instance_id(RID p_area, ObjectID p_ID);
+ virtual ObjectID area_get_object_instance_id(RID p_area) const;
+
+ /// If you pass as p_area the SpaceBullet you can set some parameters as specified below
+ /// AREA_PARAM_GRAVITY
+ /// AREA_PARAM_GRAVITY_VECTOR
+ /// Otherwise you can set area parameters
+ virtual void area_set_param(RID p_area, AreaParameter p_param, const Variant &p_value);
+ virtual Variant area_get_param(RID p_parea, AreaParameter p_param) const;
+
+ virtual void area_set_transform(RID p_area, const Transform &p_transform);
+ virtual Transform area_get_transform(RID p_area) const;
+
+ virtual void area_set_collision_mask(RID p_area, uint32_t p_mask);
+ virtual void area_set_collision_layer(RID p_area, uint32_t p_layer);
+
+ virtual void area_set_monitorable(RID p_area, bool p_monitorable);
+ virtual void area_set_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method);
+ virtual void area_set_area_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method);
+ virtual void area_set_ray_pickable(RID p_area, bool p_enable);
+ virtual bool area_is_ray_pickable(RID p_area) const;
+
+ /* RIGID BODY API */
+
+ virtual RID body_create(BodyMode p_mode = BODY_MODE_RIGID, bool p_init_sleeping = false);
+
+ virtual void body_set_space(RID p_body, RID p_space);
+ virtual RID body_get_space(RID p_body) const;
+
+ virtual void body_set_mode(RID p_body, BodyMode p_mode);
+ virtual BodyMode body_get_mode(RID p_body) const;
+
+ virtual void body_add_shape(RID p_body, RID p_shape, const Transform &p_transform = Transform());
+ // Not supported, Please remove and add new shape
+ virtual void body_set_shape(RID p_body, int p_shape_idx, RID p_shape);
+ virtual void body_set_shape_transform(RID p_body, int p_shape_idx, const Transform &p_transform);
+
+ virtual int body_get_shape_count(RID p_body) const;
+ virtual RID body_get_shape(RID p_body, int p_shape_idx) const;
+ virtual Transform body_get_shape_transform(RID p_body, int p_shape_idx) const;
+
+ virtual void body_set_shape_disabled(RID p_body, int p_shape_idx, bool p_disabled);
+
+ virtual void body_remove_shape(RID p_body, int p_shape_idx);
+ virtual void body_clear_shapes(RID p_body);
+
+ // Used for Rigid and Soft Bodies
+ virtual void body_attach_object_instance_id(RID p_body, uint32_t p_ID);
+ virtual uint32_t body_get_object_instance_id(RID p_body) const;
+
+ virtual void body_set_enable_continuous_collision_detection(RID p_body, bool p_enable);
+ virtual bool body_is_continuous_collision_detection_enabled(RID p_body) const;
+
+ virtual void body_set_collision_layer(RID p_body, uint32_t p_layer);
+ virtual uint32_t body_get_collision_layer(RID p_body) const;
+
+ virtual void body_set_collision_mask(RID p_body, uint32_t p_mask);
+ virtual uint32_t body_get_collision_mask(RID p_body) const;
+
+ /// This is not supported by physics server
+ virtual void body_set_user_flags(RID p_body, uint32_t p_flags);
+ /// This is not supported by physics server
+ virtual uint32_t body_get_user_flags(RID p_body) const;
+
+ virtual void body_set_param(RID p_body, BodyParameter p_param, float p_value);
+ virtual float body_get_param(RID p_body, BodyParameter p_param) const;
+
+ virtual void body_set_kinematic_safe_margin(RID p_body, real_t p_margin);
+ virtual real_t body_get_kinematic_safe_margin(RID p_body) const;
+
+ virtual void body_set_state(RID p_body, BodyState p_state, const Variant &p_variant);
+ virtual Variant body_get_state(RID p_body, BodyState p_state) const;
+
+ virtual void body_set_applied_force(RID p_body, const Vector3 &p_force);
+ virtual Vector3 body_get_applied_force(RID p_body) const;
+
+ virtual void body_set_applied_torque(RID p_body, const Vector3 &p_torque);
+ virtual Vector3 body_get_applied_torque(RID p_body) const;
+
+ virtual void body_apply_impulse(RID p_body, const Vector3 &p_pos, const Vector3 &p_impulse);
+ virtual void body_apply_torque_impulse(RID p_body, const Vector3 &p_impulse);
+ virtual void body_set_axis_velocity(RID p_body, const Vector3 &p_axis_velocity);
+
+ virtual void body_set_axis_lock(RID p_body, BodyAxisLock p_lock);
+ virtual BodyAxisLock body_get_axis_lock(RID p_body) const;
+
+ virtual void body_add_collision_exception(RID p_body, RID p_body_b);
+ virtual void body_remove_collision_exception(RID p_body, RID p_body_b);
+ virtual void body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions);
+
+ virtual void body_set_max_contacts_reported(RID p_body, int p_contacts);
+ virtual int body_get_max_contacts_reported(RID p_body) const;
+
+ virtual void body_set_contacts_reported_depth_threshold(RID p_body, float p_treshold);
+ virtual float body_get_contacts_reported_depth_threshold(RID p_body) const;
+
+ virtual void body_set_omit_force_integration(RID p_body, bool p_omit);
+ virtual bool body_is_omitting_force_integration(RID p_body) const;
+
+ virtual void body_set_force_integration_callback(RID p_body, Object *p_receiver, const StringName &p_method, const Variant &p_udata = Variant());
+
+ virtual void body_set_ray_pickable(RID p_body, bool p_enable);
+ virtual bool body_is_ray_pickable(RID p_body) const;
+
+ // this function only works on physics process, errors and returns null otherwise
+ virtual PhysicsDirectBodyState *body_get_direct_state(RID p_body);
+
+ virtual bool body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, MotionResult *r_result = NULL);
+
+ /* SOFT BODY API */
+
+ virtual RID soft_body_create(bool p_init_sleeping = false);
+
+ virtual void soft_body_set_space(RID p_body, RID p_space);
+ virtual RID soft_body_get_space(RID p_body) const;
+
+ virtual void soft_body_set_trimesh_body_shape(RID p_body, PoolVector<int> p_indices, PoolVector<Vector3> p_vertices, int p_triangles_num);
+
+ virtual void soft_body_set_collision_layer(RID p_body, uint32_t p_layer);
+ virtual uint32_t soft_body_get_collision_layer(RID p_body) const;
+
+ virtual void soft_body_set_collision_mask(RID p_body, uint32_t p_mask);
+ virtual uint32_t soft_body_get_collision_mask(RID p_body) const;
+
+ virtual void soft_body_add_collision_exception(RID p_body, RID p_body_b);
+ virtual void soft_body_remove_collision_exception(RID p_body, RID p_body_b);
+ virtual void soft_body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions);
+
+ virtual void soft_body_set_state(RID p_body, BodyState p_state, const Variant &p_variant);
+ virtual Variant soft_body_get_state(RID p_body, BodyState p_state) const;
+
+ virtual void soft_body_set_transform(RID p_body, const Transform &p_transform);
+ virtual Transform soft_body_get_transform(RID p_body) const;
+
+ virtual void soft_body_set_ray_pickable(RID p_body, bool p_enable);
+ virtual bool soft_body_is_ray_pickable(RID p_body) const;
+
+ /* JOINT API */
+
+ virtual JointType joint_get_type(RID p_joint) const;
+
+ virtual void joint_set_solver_priority(RID p_joint, int p_priority);
+ virtual int joint_get_solver_priority(RID p_joint) const;
+
+ virtual RID joint_create_pin(RID p_body_A, const Vector3 &p_local_A, RID p_body_B, const Vector3 &p_local_B);
+
+ virtual void pin_joint_set_param(RID p_joint, PinJointParam p_param, float p_value);
+ virtual float pin_joint_get_param(RID p_joint, PinJointParam p_param) const;
+
+ virtual void pin_joint_set_local_a(RID p_joint, const Vector3 &p_A);
+ virtual Vector3 pin_joint_get_local_a(RID p_joint) const;
+
+ virtual void pin_joint_set_local_b(RID p_joint, const Vector3 &p_B);
+ virtual Vector3 pin_joint_get_local_b(RID p_joint) const;
+
+ virtual RID joint_create_hinge(RID p_body_A, const Transform &p_frame_A, RID p_body_B, const Transform &p_frame_B);
+ virtual RID joint_create_hinge_simple(RID p_body_A, const Vector3 &p_pivot_A, const Vector3 &p_axis_A, RID p_body_B, const Vector3 &p_pivot_B, const Vector3 &p_axis_B);
+
+ virtual void hinge_joint_set_param(RID p_joint, HingeJointParam p_param, float p_value);
+ virtual float hinge_joint_get_param(RID p_joint, HingeJointParam p_param) const;
+
+ virtual void hinge_joint_set_flag(RID p_joint, HingeJointFlag p_flag, bool p_value);
+ virtual bool hinge_joint_get_flag(RID p_joint, HingeJointFlag p_flag) const;
+
+ /// Reference frame is A
+ virtual RID joint_create_slider(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B);
+
+ virtual void slider_joint_set_param(RID p_joint, SliderJointParam p_param, float p_value);
+ virtual float slider_joint_get_param(RID p_joint, SliderJointParam p_param) const;
+
+ /// Reference frame is A
+ virtual RID joint_create_cone_twist(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B);
+
+ virtual void cone_twist_joint_set_param(RID p_joint, ConeTwistJointParam p_param, float p_value);
+ virtual float cone_twist_joint_get_param(RID p_joint, ConeTwistJointParam p_param) const;
+
+ /// Reference frame is A
+ virtual RID joint_create_generic_6dof(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B);
+
+ virtual void generic_6dof_joint_set_param(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisParam p_param, float p_value);
+ virtual float generic_6dof_joint_get_param(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisParam p_param);
+
+ virtual void generic_6dof_joint_set_flag(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisFlag p_flag, bool p_enable);
+ virtual bool generic_6dof_joint_get_flag(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisFlag p_flag);
+
+ /* MISC */
+
+ virtual void free(RID p_rid);
+
+ virtual void set_active(bool p_active) {
+ active = p_active;
+ }
+
+ static bool singleton_isActive() {
+ return static_cast<BulletPhysicsServer *>(get_singleton())->active;
+ }
+
+ bool isActive() {
+ return active;
+ }
+
+ virtual void init();
+ virtual void step(float p_deltaTime);
+ virtual void sync();
+ virtual void flush_queries();
+ virtual void finish();
+
+ virtual int get_process_info(ProcessInfo p_info);
+
+ CollisionObjectBullet *get_collisin_object(RID p_object) const;
+ RigidCollisionObjectBullet *get_rigid_collisin_object(RID p_object) const;
+
+ /// Internal APIs
+public:
+};
+
+#endif
diff --git a/modules/bullet/bullet_types_converter.cpp b/modules/bullet/bullet_types_converter.cpp
new file mode 100644
index 0000000000..5010197a78
--- /dev/null
+++ b/modules/bullet/bullet_types_converter.cpp
@@ -0,0 +1,94 @@
+/*************************************************************************/
+/* bullet_types_converter.cpp */
+/* Author: AndreaCatania */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 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. */
+/*************************************************************************/
+
+#pragma once
+
+#include "bullet_types_converter.h"
+
+// ++ BULLET to GODOT ++++++++++
+void B_TO_G(btVector3 const &inVal, Vector3 &outVal) {
+ outVal[0] = inVal[0];
+ outVal[1] = inVal[1];
+ outVal[2] = inVal[2];
+}
+
+void INVERT_B_TO_G(btVector3 const &inVal, Vector3 &outVal) {
+ outVal[0] = inVal[0] != 0. ? 1. / inVal[0] : 0.;
+ outVal[1] = inVal[1] != 0. ? 1. / inVal[1] : 0.;
+ outVal[2] = inVal[2] != 0. ? 1. / inVal[2] : 0.;
+}
+
+void B_TO_G(btMatrix3x3 const &inVal, Basis &outVal) {
+ B_TO_G(inVal[0], outVal[0]);
+ B_TO_G(inVal[1], outVal[1]);
+ B_TO_G(inVal[2], outVal[2]);
+}
+
+void INVERT_B_TO_G(btMatrix3x3 const &inVal, Basis &outVal) {
+ INVERT_B_TO_G(inVal[0], outVal[0]);
+ INVERT_B_TO_G(inVal[1], outVal[1]);
+ INVERT_B_TO_G(inVal[2], outVal[2]);
+}
+
+void B_TO_G(btTransform const &inVal, Transform &outVal) {
+ B_TO_G(inVal.getBasis(), outVal.basis);
+ B_TO_G(inVal.getOrigin(), outVal.origin);
+}
+
+// ++ GODOT to BULLET ++++++++++
+void G_TO_B(Vector3 const &inVal, btVector3 &outVal) {
+ outVal[0] = inVal[0];
+ outVal[1] = inVal[1];
+ outVal[2] = inVal[2];
+}
+
+void INVERT_G_TO_B(Vector3 const &inVal, btVector3 &outVal) {
+ outVal[0] = inVal[0] != 0. ? 1. / inVal[0] : 0.;
+ outVal[1] = inVal[1] != 0. ? 1. / inVal[1] : 0.;
+ outVal[2] = inVal[2] != 0. ? 1. / inVal[2] : 0.;
+}
+
+void G_TO_B(Basis const &inVal, btMatrix3x3 &outVal) {
+ G_TO_B(inVal[0], outVal[0]);
+ G_TO_B(inVal[1], outVal[1]);
+ G_TO_B(inVal[2], outVal[2]);
+}
+
+void INVERT_G_TO_B(Basis const &inVal, btMatrix3x3 &outVal) {
+ INVERT_G_TO_B(inVal[0], outVal[0]);
+ INVERT_G_TO_B(inVal[1], outVal[1]);
+ INVERT_G_TO_B(inVal[2], outVal[2]);
+}
+
+void G_TO_B(Transform const &inVal, btTransform &outVal) {
+ G_TO_B(inVal.basis, outVal.getBasis());
+ G_TO_B(inVal.origin, outVal.getOrigin());
+}
diff --git a/modules/bullet/bullet_types_converter.h b/modules/bullet/bullet_types_converter.h
new file mode 100644
index 0000000000..ed6a349382
--- /dev/null
+++ b/modules/bullet/bullet_types_converter.h
@@ -0,0 +1,57 @@
+/*************************************************************************/
+/* bullet_types_converter.h */
+/* Author: AndreaCatania */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef BULLET_TYPES_CONVERTER_H
+#define BULLET_TYPES_CONVERTER_H
+
+#include "LinearMath/btMatrix3x3.h"
+#include "LinearMath/btTransform.h"
+#include "LinearMath/btVector3.h"
+#include "core/math/matrix3.h"
+#include "core/math/transform.h"
+#include "core/math/vector3.h"
+#include "core/typedefs.h"
+
+// Bullet to Godot
+extern void B_TO_G(btVector3 const &inVal, Vector3 &outVal);
+extern void INVERT_B_TO_G(btVector3 const &inVal, Vector3 &outVal);
+extern void B_TO_G(btMatrix3x3 const &inVal, Basis &outVal);
+extern void INVERT_B_TO_G(btMatrix3x3 const &inVal, Basis &outVal);
+extern void B_TO_G(btTransform const &inVal, Transform &outVal);
+
+// Godot TO Bullet
+extern void G_TO_B(Vector3 const &inVal, btVector3 &outVal);
+extern void INVERT_G_TO_B(Vector3 const &inVal, btVector3 &outVal);
+extern void G_TO_B(Basis const &inVal, btMatrix3x3 &outVal);
+extern void INVERT_G_TO_B(Basis const &inVal, btMatrix3x3 &outVal);
+extern void G_TO_B(Transform const &inVal, btTransform &outVal);
+
+#endif
diff --git a/modules/bullet/bullet_utilities.h b/modules/bullet/bullet_utilities.h
new file mode 100644
index 0000000000..45cde169b7
--- /dev/null
+++ b/modules/bullet/bullet_utilities.h
@@ -0,0 +1,44 @@
+/*************************************************************************/
+/* bullet_utilities.h */
+/* Author: AndreaCatania */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef BULLET_UTILITIES_H
+#define BULLET_UTILITIES_H
+
+#pragma once
+
+#define bulletnew(cl) \
+ new cl
+
+#define bulletdelete(cl) \
+ delete cl; \
+ cl = NULL;
+
+#endif
diff --git a/modules/bullet/collision_object_bullet.cpp b/modules/bullet/collision_object_bullet.cpp
new file mode 100644
index 0000000000..91a049b1f3
--- /dev/null
+++ b/modules/bullet/collision_object_bullet.cpp
@@ -0,0 +1,320 @@
+/*************************************************************************/
+/* collision_object_bullet.cpp */
+/* Author: AndreaCatania */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "collision_object_bullet.h"
+#include "area_bullet.h"
+#include "btBulletCollisionCommon.h"
+#include "bullet_physics_server.h"
+#include "bullet_types_converter.h"
+#include "bullet_utilities.h"
+#include "shape_bullet.h"
+#include "space_bullet.h"
+
+#define enableDynamicAabbTree true
+#define initialChildCapacity 1
+
+CollisionObjectBullet::ShapeWrapper::~ShapeWrapper() {}
+
+void CollisionObjectBullet::ShapeWrapper::set_transform(const Transform &p_transform) {
+ G_TO_B(p_transform, transform);
+}
+void CollisionObjectBullet::ShapeWrapper::set_transform(const btTransform &p_transform) {
+ transform = p_transform;
+}
+
+CollisionObjectBullet::CollisionObjectBullet(Type p_type)
+ : RIDBullet(), space(NULL), type(p_type), collisionsEnabled(true), m_isStatic(false), bt_collision_object(NULL), body_scale(1., 1., 1.) {}
+
+CollisionObjectBullet::~CollisionObjectBullet() {
+ // Remove all overlapping
+ for (int i = areasOverlapped.size() - 1; 0 <= i; --i) {
+ areasOverlapped[i]->remove_overlapping_instantly(this);
+ }
+ // not required
+ // areasOverlapped.clear();
+
+ destroyBulletCollisionObject();
+}
+
+bool equal(real_t first, real_t second) {
+ return Math::abs(first - second) <= 0.001f;
+}
+
+void CollisionObjectBullet::set_body_scale(const Vector3 &p_new_scale) {
+ if (!equal(p_new_scale[0], body_scale[0]) || !equal(p_new_scale[1], body_scale[1]) || !equal(p_new_scale[2], body_scale[2])) {
+ G_TO_B(p_new_scale, body_scale);
+ on_body_scale_changed();
+ }
+}
+
+void CollisionObjectBullet::on_body_scale_changed() {
+}
+
+void CollisionObjectBullet::destroyBulletCollisionObject() {
+ bulletdelete(bt_collision_object);
+}
+
+void CollisionObjectBullet::setupBulletCollisionObject(btCollisionObject *p_collisionObject) {
+ bt_collision_object = p_collisionObject;
+ bt_collision_object->setUserPointer(this);
+ bt_collision_object->setUserIndex(type);
+ // Force the enabling of collision and avoid problems
+ set_collision_enabled(collisionsEnabled);
+}
+
+void CollisionObjectBullet::add_collision_exception(const CollisionObjectBullet *p_ignoreCollisionObject) {
+ exceptions.insert(p_ignoreCollisionObject->get_self());
+ bt_collision_object->setIgnoreCollisionCheck(p_ignoreCollisionObject->bt_collision_object, true);
+ if (space)
+ space->get_broadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bt_collision_object->getBroadphaseHandle(), space->get_dispatcher());
+}
+
+void CollisionObjectBullet::remove_collision_exception(const CollisionObjectBullet *p_ignoreCollisionObject) {
+ exceptions.erase(p_ignoreCollisionObject->get_self());
+ bt_collision_object->setIgnoreCollisionCheck(p_ignoreCollisionObject->bt_collision_object, false);
+ if (space)
+ space->get_broadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bt_collision_object->getBroadphaseHandle(), space->get_dispatcher());
+}
+
+bool CollisionObjectBullet::has_collision_exception(const CollisionObjectBullet *p_otherCollisionObject) const {
+ return !bt_collision_object->checkCollideWith(p_otherCollisionObject->bt_collision_object);
+}
+
+void CollisionObjectBullet::set_collision_enabled(bool p_enabled) {
+ collisionsEnabled = p_enabled;
+ if (collisionsEnabled) {
+ bt_collision_object->setCollisionFlags(bt_collision_object->getCollisionFlags() & (~btCollisionObject::CF_NO_CONTACT_RESPONSE));
+ } else {
+ bt_collision_object->setCollisionFlags(bt_collision_object->getCollisionFlags() | btCollisionObject::CF_NO_CONTACT_RESPONSE);
+ }
+}
+
+bool CollisionObjectBullet::is_collisions_response_enabled() {
+ return collisionsEnabled;
+}
+
+void CollisionObjectBullet::notify_new_overlap(AreaBullet *p_area) {
+ areasOverlapped.push_back(p_area);
+}
+
+void CollisionObjectBullet::on_exit_area(AreaBullet *p_area) {
+ areasOverlapped.erase(p_area);
+}
+
+void CollisionObjectBullet::set_godot_object_flags(int flags) {
+ bt_collision_object->setUserIndex2(flags);
+}
+
+int CollisionObjectBullet::get_godot_object_flags() const {
+ return bt_collision_object->getUserIndex2();
+}
+
+void CollisionObjectBullet::set_transform(const Transform &p_global_transform) {
+
+ btTransform btTrans;
+ Basis decomposed_basis;
+
+ Vector3 decomposed_scale = p_global_transform.get_basis().rotref_posscale_decomposition(decomposed_basis);
+
+ G_TO_B(p_global_transform.get_origin(), btTrans.getOrigin());
+ G_TO_B(decomposed_basis, btTrans.getBasis());
+
+ set_body_scale(decomposed_scale);
+ set_transform__bullet(btTrans);
+}
+
+Transform CollisionObjectBullet::get_transform() const {
+ Transform t;
+ B_TO_G(get_transform__bullet(), t);
+ return t;
+}
+
+void CollisionObjectBullet::set_transform__bullet(const btTransform &p_global_transform) {
+ bt_collision_object->setWorldTransform(p_global_transform);
+}
+
+const btTransform &CollisionObjectBullet::get_transform__bullet() const {
+ return bt_collision_object->getWorldTransform();
+}
+
+RigidCollisionObjectBullet::RigidCollisionObjectBullet(Type p_type)
+ : CollisionObjectBullet(p_type), compoundShape(bulletnew(btCompoundShape(enableDynamicAabbTree, initialChildCapacity))) {
+}
+
+RigidCollisionObjectBullet::~RigidCollisionObjectBullet() {
+ remove_all_shapes(true);
+ bt_collision_object->setCollisionShape(NULL);
+ bulletdelete(compoundShape);
+}
+
+/* Not used
+void RigidCollisionObjectBullet::_internal_replaceShape(btCollisionShape *p_old_shape, btCollisionShape *p_new_shape) {
+ bool at_least_one_was_changed = false;
+ btTransform old_transf;
+ // Inverse because I need remove the shapes
+ // Fetch all shapes to be sure to remove all shapes
+ for (int i = compoundShape->getNumChildShapes() - 1; 0 <= i; --i) {
+ if (compoundShape->getChildShape(i) == p_old_shape) {
+
+ old_transf = compoundShape->getChildTransform(i);
+ compoundShape->removeChildShapeByIndex(i);
+ compoundShape->addChildShape(old_transf, p_new_shape);
+ at_least_one_was_changed = true;
+ }
+ }
+
+ if (at_least_one_was_changed) {
+ on_shapes_changed();
+ }
+}*/
+
+void RigidCollisionObjectBullet::add_shape(ShapeBullet *p_shape, const Transform &p_transform) {
+ shapes.push_back(ShapeWrapper(p_shape, p_transform, true));
+ p_shape->add_owner(this);
+ on_shapes_changed();
+}
+
+void RigidCollisionObjectBullet::set_shape(int p_index, ShapeBullet *p_shape) {
+ ShapeWrapper &shp = shapes[p_index];
+ shp.shape->remove_owner(this);
+ p_shape->add_owner(this);
+ shp.shape = p_shape;
+ on_shapes_changed();
+}
+
+void RigidCollisionObjectBullet::set_shape_transform(int p_index, const Transform &p_transform) {
+ ERR_FAIL_INDEX(p_index, get_shape_count());
+
+ shapes[p_index].set_transform(p_transform);
+ on_shapes_changed();
+}
+
+void RigidCollisionObjectBullet::remove_shape(ShapeBullet *p_shape) {
+ // Remove the shape, all the times it appears
+ // Reverse order required for delete.
+ for (int i = shapes.size() - 1; 0 <= i; --i) {
+ if (p_shape == shapes[i].shape) {
+ internal_shape_destroy(i);
+ shapes.remove(i);
+ }
+ }
+ on_shapes_changed();
+}
+
+void RigidCollisionObjectBullet::remove_shape(int p_index) {
+ ERR_FAIL_INDEX(p_index, get_shape_count());
+ internal_shape_destroy(p_index);
+ shapes.remove(p_index);
+ on_shapes_changed();
+}
+
+void RigidCollisionObjectBullet::remove_all_shapes(bool p_permanentlyFromThisBody) {
+ // Reverse order required for delete.
+ for (int i = shapes.size() - 1; 0 <= i; --i) {
+ internal_shape_destroy(i, p_permanentlyFromThisBody);
+ }
+ shapes.clear();
+ on_shapes_changed();
+}
+
+int RigidCollisionObjectBullet::get_shape_count() const {
+ return shapes.size();
+}
+
+ShapeBullet *RigidCollisionObjectBullet::get_shape(int p_index) const {
+ return shapes[p_index].shape;
+}
+
+btCollisionShape *RigidCollisionObjectBullet::get_bt_shape(int p_index) const {
+ return shapes[p_index].bt_shape;
+}
+
+Transform RigidCollisionObjectBullet::get_shape_transform(int p_index) const {
+ Transform trs;
+ B_TO_G(shapes[p_index].transform, trs);
+ return trs;
+}
+
+void RigidCollisionObjectBullet::on_shape_changed(const ShapeBullet *const p_shape) {
+ const int size = shapes.size();
+ for (int i = 0; i < size; ++i) {
+ if (shapes[i].shape == p_shape) {
+ bulletdelete(shapes[i].bt_shape);
+ }
+ }
+ on_shapes_changed();
+}
+
+void RigidCollisionObjectBullet::on_shapes_changed() {
+ int i;
+ // Remove all shapes, reverse order for performance reason (Array resize)
+ for (i = compoundShape->getNumChildShapes() - 1; 0 <= i; --i) {
+ compoundShape->removeChildShapeByIndex(i);
+ }
+
+ // Insert all shapes
+ ShapeWrapper *shpWrapper;
+ const int size = shapes.size();
+ for (i = 0; i < size; ++i) {
+ shpWrapper = &shapes[i];
+ if (!shpWrapper->bt_shape) {
+ shpWrapper->bt_shape = shpWrapper->shape->create_bt_shape();
+ }
+ if (shpWrapper->active) {
+ compoundShape->addChildShape(shpWrapper->transform, shpWrapper->bt_shape);
+ } else {
+ compoundShape->addChildShape(shpWrapper->transform, BulletPhysicsServer::get_empty_shape());
+ }
+ }
+
+ compoundShape->setLocalScaling(body_scale);
+ compoundShape->recalculateLocalAabb();
+}
+
+void RigidCollisionObjectBullet::set_shape_disabled(int p_index, bool p_disabled) {
+ shapes[p_index].active = !p_disabled;
+ on_shapes_changed();
+}
+
+bool RigidCollisionObjectBullet::is_shape_disabled(int p_index) {
+ return !shapes[p_index].active;
+}
+
+void RigidCollisionObjectBullet::on_body_scale_changed() {
+ CollisionObjectBullet::on_body_scale_changed();
+ on_shapes_changed();
+}
+
+void RigidCollisionObjectBullet::internal_shape_destroy(int p_index, bool p_permanentlyFromThisBody) {
+ ShapeWrapper &shp = shapes[p_index];
+ shp.shape->remove_owner(this, p_permanentlyFromThisBody);
+ bulletdelete(shp.bt_shape);
+}
diff --git a/modules/bullet/collision_object_bullet.h b/modules/bullet/collision_object_bullet.h
new file mode 100644
index 0000000000..153b8ea5bc
--- /dev/null
+++ b/modules/bullet/collision_object_bullet.h
@@ -0,0 +1,234 @@
+/*************************************************************************/
+/* collision_object_bullet.h */
+/* Author: AndreaCatania */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef COLLISION_OBJECT_BULLET_H
+#define COLLISION_OBJECT_BULLET_H
+
+#include "LinearMath/btTransform.h"
+#include "core/vset.h"
+#include "object.h"
+#include "shape_owner_bullet.h"
+#include "transform.h"
+#include "vector3.h"
+
+class AreaBullet;
+class ShapeBullet;
+class btCollisionObject;
+class btCompoundShape;
+class btCollisionShape;
+class SpaceBullet;
+
+class CollisionObjectBullet : public RIDBullet {
+public:
+ enum GodotObjectFlags {
+ GOF_IS_MONITORING_AREA = 1 << 0
+ // FLAG2 = 1 << 1,
+ // FLAG3 = 1 << 2,
+ // FLAG4 = 1 << 3,
+ // FLAG5 = 1 << 4,
+ // FLAG6 = 1 << 5
+ // etc..
+ };
+ enum Type {
+ TYPE_AREA = 0,
+ TYPE_RIGID_BODY,
+ TYPE_SOFT_BODY,
+ TYPE_KINEMATIC_GHOST_BODY
+ };
+
+ struct ShapeWrapper {
+ ShapeBullet *shape;
+ btCollisionShape *bt_shape;
+ btTransform transform;
+ bool active;
+
+ ShapeWrapper()
+ : shape(NULL), bt_shape(NULL), active(true) {}
+
+ ShapeWrapper(ShapeBullet *p_shape, const btTransform &p_transform, bool p_active)
+ : shape(p_shape), bt_shape(NULL), active(p_active) {
+ set_transform(p_transform);
+ }
+
+ ShapeWrapper(ShapeBullet *p_shape, const Transform &p_transform, bool p_active)
+ : shape(p_shape), bt_shape(NULL), active(p_active) {
+ set_transform(p_transform);
+ }
+ ~ShapeWrapper();
+
+ ShapeWrapper(const ShapeWrapper &otherShape) {
+ operator=(otherShape);
+ }
+
+ void operator=(const ShapeWrapper &otherShape) {
+ shape = otherShape.shape;
+ bt_shape = otherShape.bt_shape;
+ transform = otherShape.transform;
+ active = otherShape.active;
+ }
+
+ void set_transform(const Transform &p_transform);
+ void set_transform(const btTransform &p_transform);
+ };
+
+protected:
+ Type type;
+ ObjectID instance_id;
+ uint32_t collisionLayer;
+ uint32_t collisionMask;
+ bool collisionsEnabled;
+ bool m_isStatic;
+ bool ray_pickable;
+ btCollisionObject *bt_collision_object;
+ btVector3 body_scale;
+ SpaceBullet *space;
+
+ VSet<RID> exceptions;
+
+ /// This array is used to know all areas where this Object is overlapped in
+ /// New area is added when overlap with new area (AreaBullet::addOverlap), then is removed when it exit (CollisionObjectBullet::onExitArea)
+ /// This array is used mainly to know which area hold the pointer of this object
+ Vector<AreaBullet *> areasOverlapped;
+
+public:
+ CollisionObjectBullet(Type p_type);
+ virtual ~CollisionObjectBullet();
+
+ Type getType() { return type; }
+
+protected:
+ void destroyBulletCollisionObject();
+ void setupBulletCollisionObject(btCollisionObject *p_collisionObject);
+
+public:
+ _FORCE_INLINE_ btCollisionObject *get_bt_collision_object() { return bt_collision_object; }
+
+ _FORCE_INLINE_ void set_instance_id(const ObjectID &p_instance_id) { instance_id = p_instance_id; }
+ _FORCE_INLINE_ ObjectID get_instance_id() const { return instance_id; }
+
+ _FORCE_INLINE_ bool is_static() const { return m_isStatic; }
+
+ _FORCE_INLINE_ void set_ray_pickable(bool p_enable) { ray_pickable = p_enable; }
+ _FORCE_INLINE_ bool is_ray_pickable() const { return ray_pickable; }
+
+ void set_body_scale(const Vector3 &p_new_scale);
+ virtual void on_body_scale_changed();
+
+ void add_collision_exception(const CollisionObjectBullet *p_ignoreCollisionObject);
+ void remove_collision_exception(const CollisionObjectBullet *p_ignoreCollisionObject);
+ bool has_collision_exception(const CollisionObjectBullet *p_otherCollisionObject) const;
+ _FORCE_INLINE_ const VSet<RID> &get_exceptions() const { return exceptions; }
+
+ _FORCE_INLINE_ void set_collision_layer(uint32_t p_layer) {
+ collisionLayer = p_layer;
+ on_collision_filters_change();
+ }
+ _FORCE_INLINE_ uint32_t get_collision_layer() const { return collisionLayer; }
+
+ _FORCE_INLINE_ void set_collision_mask(uint32_t p_mask) {
+ collisionMask = p_mask;
+ on_collision_filters_change();
+ }
+ _FORCE_INLINE_ uint32_t get_collision_mask() const { return collisionMask; }
+
+ virtual void on_collision_filters_change() = 0;
+
+ _FORCE_INLINE_ bool test_collision_mask(CollisionObjectBullet *p_other) const {
+ return collisionLayer & p_other->collisionMask || p_other->collisionLayer & collisionMask;
+ }
+
+ virtual void reload_body() = 0;
+ virtual void set_space(SpaceBullet *p_space) = 0;
+ _FORCE_INLINE_ SpaceBullet *get_space() const { return space; }
+ /// This is an event that is called when a collision checker starts
+ virtual void on_collision_checker_start() = 0;
+
+ virtual void dispatch_callbacks() = 0;
+
+ void set_collision_enabled(bool p_enabled);
+ bool is_collisions_response_enabled();
+
+ void notify_new_overlap(AreaBullet *p_area);
+ virtual void on_enter_area(AreaBullet *p_area) = 0;
+ virtual void on_exit_area(AreaBullet *p_area);
+
+ /// GodotObjectFlags
+ void set_godot_object_flags(int flags);
+ int get_godot_object_flags() const;
+
+ void set_transform(const Transform &p_global_transform);
+ Transform get_transform() const;
+ virtual void set_transform__bullet(const btTransform &p_global_transform);
+ virtual const btTransform &get_transform__bullet() const;
+};
+
+class RigidCollisionObjectBullet : public CollisionObjectBullet, public ShapeOwnerBullet {
+protected:
+ /// This is required to combine some shapes together.
+ /// Since Godot allow to have multiple shapes for each body with custom relative location,
+ /// each body will attach the shapes using this class even if there is only one shape.
+ btCompoundShape *compoundShape;
+ Vector<ShapeWrapper> shapes;
+
+public:
+ RigidCollisionObjectBullet(Type p_type);
+ ~RigidCollisionObjectBullet();
+
+ _FORCE_INLINE_ const Vector<ShapeWrapper> &get_shapes_wrappers() const { return shapes; }
+
+ /// This is used to set new shape or replace existing
+ //virtual void _internal_replaceShape(btCollisionShape *p_old_shape, btCollisionShape *p_new_shape) = 0;
+ void add_shape(ShapeBullet *p_shape, const Transform &p_transform = Transform());
+ void set_shape(int p_index, ShapeBullet *p_shape);
+ void set_shape_transform(int p_index, const Transform &p_transform);
+ virtual void remove_shape(ShapeBullet *p_shape);
+ void remove_shape(int p_index);
+ void remove_all_shapes(bool p_permanentlyFromThisBody = false);
+
+ virtual void on_shape_changed(const ShapeBullet *const p_shape);
+ virtual void on_shapes_changed();
+
+ _FORCE_INLINE_ btCompoundShape *get_compound_shape() const { return compoundShape; }
+ int get_shape_count() const;
+ ShapeBullet *get_shape(int p_index) const;
+ btCollisionShape *get_bt_shape(int p_index) const;
+ Transform get_shape_transform(int p_index) const;
+
+ void set_shape_disabled(int p_index, bool p_disabled);
+ bool is_shape_disabled(int p_index);
+
+ virtual void on_body_scale_changed();
+
+private:
+ void internal_shape_destroy(int p_index, bool p_permanentlyFromThisBody = false);
+};
+
+#endif
diff --git a/modules/bullet/cone_twist_joint_bullet.cpp b/modules/bullet/cone_twist_joint_bullet.cpp
new file mode 100644
index 0000000000..f6ac40e001
--- /dev/null
+++ b/modules/bullet/cone_twist_joint_bullet.cpp
@@ -0,0 +1,111 @@
+/*************************************************************************/
+/* cone_twist_joint_bullet.cpp */
+/* Author: AndreaCatania */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "cone_twist_joint_bullet.h"
+#include "BulletDynamics/ConstraintSolver/btConeTwistConstraint.h"
+#include "bullet_types_converter.h"
+#include "bullet_utilities.h"
+#include "rigid_body_bullet.h"
+
+ConeTwistJointBullet::ConeTwistJointBullet(RigidBodyBullet *rbA, RigidBodyBullet *rbB, const Transform &rbAFrame, const Transform &rbBFrame)
+ : JointBullet() {
+ btTransform btFrameA;
+ G_TO_B(rbAFrame, btFrameA);
+ if (rbB) {
+ btTransform btFrameB;
+ G_TO_B(rbBFrame, btFrameB);
+ coneConstraint = bulletnew(btConeTwistConstraint(*rbA->get_bt_rigid_body(), *rbB->get_bt_rigid_body(), btFrameA, btFrameB));
+ } else {
+ coneConstraint = bulletnew(btConeTwistConstraint(*rbA->get_bt_rigid_body(), btFrameA));
+ }
+ setup(coneConstraint);
+}
+
+void ConeTwistJointBullet::set_angular_only(bool angularOnly) {
+ coneConstraint->setAngularOnly(angularOnly);
+}
+
+void ConeTwistJointBullet::set_limit(real_t _swingSpan1, real_t _swingSpan2, real_t _twistSpan, real_t _softness, real_t _biasFactor, real_t _relaxationFactor) {
+ coneConstraint->setLimit(_swingSpan1, _swingSpan2, _twistSpan, _softness, _biasFactor, _relaxationFactor);
+}
+
+int ConeTwistJointBullet::get_solve_twist_limit() {
+ return coneConstraint->getSolveTwistLimit();
+}
+
+int ConeTwistJointBullet::get_solve_swing_limit() {
+ return coneConstraint->getSolveSwingLimit();
+}
+
+real_t ConeTwistJointBullet::get_twist_limit_sign() {
+ return coneConstraint->getTwistLimitSign();
+}
+
+void ConeTwistJointBullet::set_param(PhysicsServer::ConeTwistJointParam p_param, real_t p_value) {
+ switch (p_param) {
+ case PhysicsServer::CONE_TWIST_JOINT_SWING_SPAN:
+ coneConstraint->setLimit(5, p_value);
+ coneConstraint->setLimit(4, p_value);
+ break;
+ case PhysicsServer::CONE_TWIST_JOINT_TWIST_SPAN:
+ coneConstraint->setLimit(3, p_value);
+ break;
+ case PhysicsServer::CONE_TWIST_JOINT_BIAS:
+ coneConstraint->setLimit(coneConstraint->getSwingSpan1(), coneConstraint->getSwingSpan2(), coneConstraint->getTwistSpan(), coneConstraint->getLimitSoftness(), p_value, coneConstraint->getRelaxationFactor());
+ break;
+ case PhysicsServer::CONE_TWIST_JOINT_SOFTNESS:
+ coneConstraint->setLimit(coneConstraint->getSwingSpan1(), coneConstraint->getSwingSpan2(), coneConstraint->getTwistSpan(), p_value, coneConstraint->getBiasFactor(), coneConstraint->getRelaxationFactor());
+ break;
+ case PhysicsServer::CONE_TWIST_JOINT_RELAXATION:
+ coneConstraint->setLimit(coneConstraint->getSwingSpan1(), coneConstraint->getSwingSpan2(), coneConstraint->getTwistSpan(), coneConstraint->getLimitSoftness(), coneConstraint->getBiasFactor(), p_value);
+ break;
+ default:
+ WARN_PRINT("This parameter is not supported by Bullet engine");
+ }
+}
+
+real_t ConeTwistJointBullet::get_param(PhysicsServer::ConeTwistJointParam p_param) const {
+ switch (p_param) {
+ case PhysicsServer::CONE_TWIST_JOINT_SWING_SPAN:
+ return coneConstraint->getSwingSpan1();
+ case PhysicsServer::CONE_TWIST_JOINT_TWIST_SPAN:
+ return coneConstraint->getTwistSpan();
+ case PhysicsServer::CONE_TWIST_JOINT_BIAS:
+ return coneConstraint->getBiasFactor();
+ case PhysicsServer::CONE_TWIST_JOINT_SOFTNESS:
+ return coneConstraint->getLimitSoftness();
+ case PhysicsServer::CONE_TWIST_JOINT_RELAXATION:
+ return coneConstraint->getRelaxationFactor();
+ default:
+ WARN_PRINT("This parameter is not supported by Bullet engine");
+ return 0;
+ }
+}
diff --git a/modules/bullet/cone_twist_joint_bullet.h b/modules/bullet/cone_twist_joint_bullet.h
new file mode 100644
index 0000000000..1ce5ef9826
--- /dev/null
+++ b/modules/bullet/cone_twist_joint_bullet.h
@@ -0,0 +1,58 @@
+/*************************************************************************/
+/* cone_twist_joint_bullet.h */
+/* Author: AndreaCatania */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef CONE_TWIST_JOINT_BULLET_H
+#define CONE_TWIST_JOINT_BULLET_H
+
+#include "joint_bullet.h"
+
+class RigidBodyBullet;
+
+class ConeTwistJointBullet : public JointBullet {
+ class btConeTwistConstraint *coneConstraint;
+
+public:
+ ConeTwistJointBullet(RigidBodyBullet *rbA, RigidBodyBullet *rbB, const Transform &rbAFrame, const Transform &rbBFrame);
+
+ virtual PhysicsServer::JointType get_type() const { return PhysicsServer::JOINT_CONE_TWIST; }
+
+ void set_angular_only(bool angularOnly);
+
+ void set_limit(real_t _swingSpan1, real_t _swingSpan2, real_t _twistSpan, real_t _softness = 0.8f, real_t _biasFactor = 0.3f, real_t _relaxationFactor = 1.0f);
+ int get_solve_twist_limit();
+
+ int get_solve_swing_limit();
+ real_t get_twist_limit_sign();
+
+ void set_param(PhysicsServer::ConeTwistJointParam p_param, real_t p_value);
+ real_t get_param(PhysicsServer::ConeTwistJointParam p_param) const;
+};
+#endif
diff --git a/modules/bullet/config.py b/modules/bullet/config.py
new file mode 100644
index 0000000000..0a31c2e503
--- /dev/null
+++ b/modules/bullet/config.py
@@ -0,0 +1,14 @@
+def can_build(platform):
+ return True
+
+def configure(env):
+ pass
+
+def get_doc_classes():
+ return [
+ "BulletPhysicsDirectBodyState",
+ "BulletPhysicsServer",
+ ]
+
+def get_doc_path():
+ return "doc_classes"
diff --git a/modules/bullet/constraint_bullet.cpp b/modules/bullet/constraint_bullet.cpp
new file mode 100644
index 0000000000..08fc36f274
--- /dev/null
+++ b/modules/bullet/constraint_bullet.cpp
@@ -0,0 +1,50 @@
+/*************************************************************************/
+/* constraint_bullet.cpp */
+/* Author: AndreaCatania */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "constraint_bullet.h"
+#include "collision_object_bullet.h"
+#include "space_bullet.h"
+
+ConstraintBullet::ConstraintBullet()
+ : space(NULL), constraint(NULL) {}
+
+void ConstraintBullet::setup(btTypedConstraint *p_constraint) {
+ constraint = p_constraint;
+ constraint->setUserConstraintPtr(this);
+}
+
+void ConstraintBullet::set_space(SpaceBullet *p_space) {
+ space = p_space;
+}
+
+void ConstraintBullet::destroy_internal_constraint() {
+ space->remove_constraint(this);
+}
diff --git a/modules/bullet/constraint_bullet.h b/modules/bullet/constraint_bullet.h
new file mode 100644
index 0000000000..b528ec6d7b
--- /dev/null
+++ b/modules/bullet/constraint_bullet.h
@@ -0,0 +1,64 @@
+/*************************************************************************/
+/* constraint_bullet.h */
+/* Author: AndreaCatania */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef CONSTRAINT_BULLET_H
+#define CONSTRAINT_BULLET_H
+
+#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
+#include "bullet_utilities.h"
+#include "rid_bullet.h"
+
+class RigidBodyBullet;
+class SpaceBullet;
+class btTypedConstraint;
+
+class ConstraintBullet : public RIDBullet {
+
+protected:
+ SpaceBullet *space;
+ btTypedConstraint *constraint;
+
+public:
+ ConstraintBullet();
+
+ virtual void setup(btTypedConstraint *p_constraint);
+ virtual void set_space(SpaceBullet *p_space);
+ virtual void destroy_internal_constraint();
+
+public:
+ virtual ~ConstraintBullet() {
+ bulletdelete(constraint);
+ constraint = NULL;
+ }
+
+ _FORCE_INLINE_ btTypedConstraint *get_bt_constraint() { return constraint; }
+};
+#endif
diff --git a/modules/bullet/doc_classes/BulletPhysicsDirectBodyState.xml b/modules/bullet/doc_classes/BulletPhysicsDirectBodyState.xml
new file mode 100644
index 0000000000..831b346942
--- /dev/null
+++ b/modules/bullet/doc_classes/BulletPhysicsDirectBodyState.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="BulletPhysicsDirectBodyState" inherits="PhysicsDirectBodyState" category="Core" version="3.0-alpha">
+ <brief_description>
+ </brief_description>
+ <description>
+ </description>
+ <tutorials>
+ </tutorials>
+ <demos>
+ </demos>
+ <methods>
+ </methods>
+ <constants>
+ </constants>
+</class>
diff --git a/doc/classes/PhysicsServerSW.xml b/modules/bullet/doc_classes/BulletPhysicsServer.xml
index 7bffc23258..4b5c2e6d83 100644
--- a/doc/classes/PhysicsServerSW.xml
+++ b/modules/bullet/doc_classes/BulletPhysicsServer.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="PhysicsServerSW" inherits="PhysicsServer" category="Core" version="3.0.alpha.custom_build">
+<class name="BulletPhysicsServer" inherits="PhysicsServer" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/modules/bullet/generic_6dof_joint_bullet.cpp b/modules/bullet/generic_6dof_joint_bullet.cpp
new file mode 100644
index 0000000000..647396c24c
--- /dev/null
+++ b/modules/bullet/generic_6dof_joint_bullet.cpp
@@ -0,0 +1,241 @@
+/*************************************************************************/
+/* generic_6dof_joint_bullet.cpp */
+/* Author: AndreaCatania */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "generic_6dof_joint_bullet.h"
+#include "BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h"
+#include "bullet_types_converter.h"
+#include "bullet_utilities.h"
+#include "rigid_body_bullet.h"
+
+Generic6DOFJointBullet::Generic6DOFJointBullet(RigidBodyBullet *rbA, RigidBodyBullet *rbB, const Transform &frameInA, const Transform &frameInB, bool useLinearReferenceFrameA)
+ : JointBullet() {
+
+ btTransform btFrameA;
+ G_TO_B(frameInA, btFrameA);
+
+ if (rbB) {
+ btTransform btFrameB;
+ G_TO_B(frameInB, btFrameB);
+
+ sixDOFConstraint = bulletnew(btGeneric6DofConstraint(*rbA->get_bt_rigid_body(), *rbB->get_bt_rigid_body(), btFrameA, btFrameB, useLinearReferenceFrameA));
+ } else {
+ sixDOFConstraint = bulletnew(btGeneric6DofConstraint(*rbA->get_bt_rigid_body(), btFrameA, useLinearReferenceFrameA));
+ }
+
+ setup(sixDOFConstraint);
+}
+
+Transform Generic6DOFJointBullet::getFrameOffsetA() const {
+ btTransform btTrs = sixDOFConstraint->getFrameOffsetA();
+ Transform gTrs;
+ B_TO_G(btTrs, gTrs);
+ return gTrs;
+}
+
+Transform Generic6DOFJointBullet::getFrameOffsetB() const {
+ btTransform btTrs = sixDOFConstraint->getFrameOffsetB();
+ Transform gTrs;
+ B_TO_G(btTrs, gTrs);
+ return gTrs;
+}
+
+Transform Generic6DOFJointBullet::getFrameOffsetA() {
+ btTransform btTrs = sixDOFConstraint->getFrameOffsetA();
+ Transform gTrs;
+ B_TO_G(btTrs, gTrs);
+ return gTrs;
+}
+
+Transform Generic6DOFJointBullet::getFrameOffsetB() {
+ btTransform btTrs = sixDOFConstraint->getFrameOffsetB();
+ Transform gTrs;
+ B_TO_G(btTrs, gTrs);
+ return gTrs;
+}
+
+void Generic6DOFJointBullet::set_linear_lower_limit(const Vector3 &linearLower) {
+ btVector3 btVec;
+ G_TO_B(linearLower, btVec);
+ sixDOFConstraint->setLinearLowerLimit(btVec);
+}
+
+void Generic6DOFJointBullet::set_linear_upper_limit(const Vector3 &linearUpper) {
+ btVector3 btVec;
+ G_TO_B(linearUpper, btVec);
+ sixDOFConstraint->setLinearUpperLimit(btVec);
+}
+
+void Generic6DOFJointBullet::set_angular_lower_limit(const Vector3 &angularLower) {
+ btVector3 btVec;
+ G_TO_B(angularLower, btVec);
+ sixDOFConstraint->setAngularLowerLimit(btVec);
+}
+
+void Generic6DOFJointBullet::set_angular_upper_limit(const Vector3 &angularUpper) {
+ btVector3 btVec;
+ G_TO_B(angularUpper, btVec);
+ sixDOFConstraint->setAngularUpperLimit(btVec);
+}
+
+void Generic6DOFJointBullet::set_param(Vector3::Axis p_axis, PhysicsServer::G6DOFJointAxisParam p_param, real_t p_value) {
+ ERR_FAIL_INDEX(p_axis, 3);
+ switch (p_param) {
+ case PhysicsServer::G6DOF_JOINT_LINEAR_LOWER_LIMIT:
+ sixDOFConstraint->getTranslationalLimitMotor()->m_lowerLimit[p_axis] = p_value;
+ break;
+ case PhysicsServer::G6DOF_JOINT_LINEAR_UPPER_LIMIT:
+ sixDOFConstraint->getTranslationalLimitMotor()->m_upperLimit[p_axis] = p_value;
+ break;
+ case PhysicsServer::G6DOF_JOINT_LINEAR_LIMIT_SOFTNESS:
+ sixDOFConstraint->getTranslationalLimitMotor()->m_limitSoftness = p_value;
+ break;
+ case PhysicsServer::G6DOF_JOINT_LINEAR_RESTITUTION:
+ sixDOFConstraint->getTranslationalLimitMotor()->m_restitution = p_value;
+ break;
+ case PhysicsServer::G6DOF_JOINT_LINEAR_DAMPING:
+ sixDOFConstraint->getTranslationalLimitMotor()->m_damping = p_value;
+ break;
+ case PhysicsServer::G6DOF_JOINT_ANGULAR_LOWER_LIMIT:
+ sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_loLimit = p_value;
+ break;
+ case PhysicsServer::G6DOF_JOINT_ANGULAR_UPPER_LIMIT:
+ sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_hiLimit = p_value;
+ break;
+ case PhysicsServer::G6DOF_JOINT_ANGULAR_LIMIT_SOFTNESS:
+ sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_limitSoftness = p_value;
+ break;
+ case PhysicsServer::G6DOF_JOINT_ANGULAR_DAMPING:
+ sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_damping = p_value;
+ break;
+ case PhysicsServer::G6DOF_JOINT_ANGULAR_RESTITUTION:
+ sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_bounce = p_value;
+ break;
+ case PhysicsServer::G6DOF_JOINT_ANGULAR_FORCE_LIMIT:
+ sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_maxLimitForce = p_value;
+ break;
+ case PhysicsServer::G6DOF_JOINT_ANGULAR_ERP:
+ sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_stopERP = p_value;
+ break;
+ case PhysicsServer::G6DOF_JOINT_ANGULAR_MOTOR_TARGET_VELOCITY:
+ sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_targetVelocity = p_value;
+ break;
+ case PhysicsServer::G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT:
+ sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_maxLimitForce = p_value;
+ break;
+ default:
+ WARN_PRINT("This parameter is not supported");
+ }
+}
+
+real_t Generic6DOFJointBullet::get_param(Vector3::Axis p_axis, PhysicsServer::G6DOFJointAxisParam p_param) const {
+ ERR_FAIL_INDEX_V(p_axis, 3, 0.);
+ switch (p_param) {
+ case PhysicsServer::G6DOF_JOINT_LINEAR_LOWER_LIMIT:
+ return sixDOFConstraint->getTranslationalLimitMotor()->m_lowerLimit[p_axis];
+ case PhysicsServer::G6DOF_JOINT_LINEAR_UPPER_LIMIT:
+ return sixDOFConstraint->getTranslationalLimitMotor()->m_upperLimit[p_axis];
+ case PhysicsServer::G6DOF_JOINT_LINEAR_LIMIT_SOFTNESS:
+ return sixDOFConstraint->getTranslationalLimitMotor()->m_limitSoftness;
+ case PhysicsServer::G6DOF_JOINT_LINEAR_RESTITUTION:
+ return sixDOFConstraint->getTranslationalLimitMotor()->m_restitution;
+ case PhysicsServer::G6DOF_JOINT_LINEAR_DAMPING:
+ return sixDOFConstraint->getTranslationalLimitMotor()->m_damping;
+ case PhysicsServer::G6DOF_JOINT_ANGULAR_LOWER_LIMIT:
+ return sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_loLimit;
+ case PhysicsServer::G6DOF_JOINT_ANGULAR_UPPER_LIMIT:
+ return sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_hiLimit;
+ case PhysicsServer::G6DOF_JOINT_ANGULAR_LIMIT_SOFTNESS:
+ return sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_limitSoftness;
+ case PhysicsServer::G6DOF_JOINT_ANGULAR_DAMPING:
+ return sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_damping;
+ case PhysicsServer::G6DOF_JOINT_ANGULAR_RESTITUTION:
+ return sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_bounce;
+ case PhysicsServer::G6DOF_JOINT_ANGULAR_FORCE_LIMIT:
+ return sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_maxLimitForce;
+ case PhysicsServer::G6DOF_JOINT_ANGULAR_ERP:
+ return sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_stopERP;
+ case PhysicsServer::G6DOF_JOINT_ANGULAR_MOTOR_TARGET_VELOCITY:
+ return sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_targetVelocity;
+ case PhysicsServer::G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT:
+ return sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_maxLimitForce;
+ default:
+ WARN_PRINT("This parameter is not supported");
+ return 0.;
+ }
+}
+
+void Generic6DOFJointBullet::set_flag(Vector3::Axis p_axis, PhysicsServer::G6DOFJointAxisFlag p_flag, bool p_value) {
+ ERR_FAIL_INDEX(p_axis, 3);
+ switch (p_flag) {
+ case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT:
+ if (p_value) {
+ if (!get_flag(p_axis, p_flag)) // avoid overwrite, if limited
+ sixDOFConstraint->setLimit(p_axis, 0, 0); // Limited
+ } else {
+ if (get_flag(p_axis, p_flag)) // avoid overwrite, if free
+ sixDOFConstraint->setLimit(p_axis, 0, -1); // Free
+ }
+ break;
+ case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT: {
+ int angularAxis = 3 + p_axis;
+ if (p_value) {
+ if (!get_flag(p_axis, p_flag)) // avoid overwrite, if Limited
+ sixDOFConstraint->setLimit(angularAxis, 0, 0); // Limited
+ } else {
+ if (get_flag(p_axis, p_flag)) // avoid overwrite, if free
+ sixDOFConstraint->setLimit(angularAxis, 0, -1); // Free
+ }
+ break;
+ }
+ case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_MOTOR:
+ //sixDOFConstraint->getTranslationalLimitMotor()->m_enableMotor[p_axis] = p_value;
+ sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_enableMotor = p_value;
+ break;
+ default:
+ WARN_PRINT("This flag is not supported by Bullet engine");
+ }
+}
+
+bool Generic6DOFJointBullet::get_flag(Vector3::Axis p_axis, PhysicsServer::G6DOFJointAxisFlag p_flag) const {
+ ERR_FAIL_INDEX_V(p_axis, 3, false);
+ switch (p_flag) {
+ case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT:
+ return sixDOFConstraint->getTranslationalLimitMotor()->isLimited(p_axis);
+ case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT:
+ return sixDOFConstraint->getRotationalLimitMotor(p_axis)->isLimited();
+ case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_MOTOR:
+ return //sixDOFConstraint->getTranslationalLimitMotor()->m_enableMotor[p_axis] &&
+ sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_enableMotor;
+ default:
+ WARN_PRINT("This flag is not supported by Bullet engine");
+ return false;
+ }
+}
diff --git a/modules/bullet/generic_6dof_joint_bullet.h b/modules/bullet/generic_6dof_joint_bullet.h
new file mode 100644
index 0000000000..0d47b823de
--- /dev/null
+++ b/modules/bullet/generic_6dof_joint_bullet.h
@@ -0,0 +1,65 @@
+/*************************************************************************/
+/* generic_6dof_joint_bullet.h */
+/* Author: AndreaCatania */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef GENERIC_6DOF_JOINT_BULLET_H
+#define GENERIC_6DOF_JOINT_BULLET_H
+
+#include "joint_bullet.h"
+
+class RigidBodyBullet;
+
+class Generic6DOFJointBullet : public JointBullet {
+ class btGeneric6DofConstraint *sixDOFConstraint;
+
+public:
+ Generic6DOFJointBullet(RigidBodyBullet *rbA, RigidBodyBullet *rbB, const Transform &frameInA, const Transform &frameInB, bool useLinearReferenceFrameA);
+
+ virtual PhysicsServer::JointType get_type() const { return PhysicsServer::JOINT_6DOF; }
+
+ Transform getFrameOffsetA() const;
+ Transform getFrameOffsetB() const;
+ Transform getFrameOffsetA();
+ Transform getFrameOffsetB();
+
+ void set_linear_lower_limit(const Vector3 &linearLower);
+ void set_linear_upper_limit(const Vector3 &linearUpper);
+
+ void set_angular_lower_limit(const Vector3 &angularLower);
+ void set_angular_upper_limit(const Vector3 &angularUpper);
+
+ void set_param(Vector3::Axis p_axis, PhysicsServer::G6DOFJointAxisParam p_param, real_t p_value);
+ real_t get_param(Vector3::Axis p_axis, PhysicsServer::G6DOFJointAxisParam p_param) const;
+
+ void set_flag(Vector3::Axis p_axis, PhysicsServer::G6DOFJointAxisFlag p_flag, bool p_value);
+ bool get_flag(Vector3::Axis p_axis, PhysicsServer::G6DOFJointAxisFlag p_flag) const;
+};
+
+#endif
diff --git a/modules/bullet/godot_collision_configuration.cpp b/modules/bullet/godot_collision_configuration.cpp
new file mode 100644
index 0000000000..4e4228cc48
--- /dev/null
+++ b/modules/bullet/godot_collision_configuration.cpp
@@ -0,0 +1,91 @@
+/*************************************************************************/
+/* godot_collision_configuration.cpp */
+/* Author: AndreaCatania */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "godot_collision_configuration.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h"
+#include "godot_ray_world_algorithm.h"
+
+GodotCollisionConfiguration::GodotCollisionConfiguration(const btDiscreteDynamicsWorld *world, const btDefaultCollisionConstructionInfo &constructionInfo)
+ : btDefaultCollisionConfiguration(constructionInfo) {
+
+ void *mem = NULL;
+
+ mem = btAlignedAlloc(sizeof(GodotRayWorldAlgorithm::CreateFunc), 16);
+ m_rayWorldCF = new (mem) GodotRayWorldAlgorithm::CreateFunc(world);
+
+ mem = btAlignedAlloc(sizeof(GodotRayWorldAlgorithm::SwappedCreateFunc), 16);
+ m_swappedRayWorldCF = new (mem) GodotRayWorldAlgorithm::SwappedCreateFunc(world);
+}
+
+GodotCollisionConfiguration::~GodotCollisionConfiguration() {
+ m_rayWorldCF->~btCollisionAlgorithmCreateFunc();
+ btAlignedFree(m_rayWorldCF);
+
+ m_swappedRayWorldCF->~btCollisionAlgorithmCreateFunc();
+ btAlignedFree(m_swappedRayWorldCF);
+}
+
+btCollisionAlgorithmCreateFunc *GodotCollisionConfiguration::getCollisionAlgorithmCreateFunc(int proxyType0, int proxyType1) {
+
+ if (CUSTOM_CONVEX_SHAPE_TYPE == proxyType0 && CUSTOM_CONVEX_SHAPE_TYPE == proxyType1) {
+
+ // This collision is not supported
+ return m_emptyCreateFunc;
+ } else if (CUSTOM_CONVEX_SHAPE_TYPE == proxyType0) {
+
+ return m_rayWorldCF;
+ } else if (CUSTOM_CONVEX_SHAPE_TYPE == proxyType1) {
+
+ return m_swappedRayWorldCF;
+ } else {
+
+ return btDefaultCollisionConfiguration::getCollisionAlgorithmCreateFunc(proxyType0, proxyType1);
+ }
+}
+
+btCollisionAlgorithmCreateFunc *GodotCollisionConfiguration::getClosestPointsAlgorithmCreateFunc(int proxyType0, int proxyType1) {
+
+ if (CUSTOM_CONVEX_SHAPE_TYPE == proxyType0 && CUSTOM_CONVEX_SHAPE_TYPE == proxyType1) {
+
+ // This collision is not supported
+ return m_emptyCreateFunc;
+ } else if (CUSTOM_CONVEX_SHAPE_TYPE == proxyType0) {
+
+ return m_rayWorldCF;
+ } else if (CUSTOM_CONVEX_SHAPE_TYPE == proxyType1) {
+
+ return m_swappedRayWorldCF;
+ } else {
+
+ return btDefaultCollisionConfiguration::getClosestPointsAlgorithmCreateFunc(proxyType0, proxyType1);
+ }
+}
diff --git a/modules/bullet/godot_collision_configuration.h b/modules/bullet/godot_collision_configuration.h
new file mode 100644
index 0000000000..ed99065f8c
--- /dev/null
+++ b/modules/bullet/godot_collision_configuration.h
@@ -0,0 +1,50 @@
+/*************************************************************************/
+/* godot_collision_configuration.h */
+/* Author: AndreaCatania */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef GODOT_COLLISION_CONFIGURATION_H
+#define GODOT_COLLISION_CONFIGURATION_H
+
+#include "BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h"
+
+class btDiscreteDynamicsWorld;
+
+class GodotCollisionConfiguration : public btDefaultCollisionConfiguration {
+ btCollisionAlgorithmCreateFunc *m_rayWorldCF;
+ btCollisionAlgorithmCreateFunc *m_swappedRayWorldCF;
+
+public:
+ GodotCollisionConfiguration(const btDiscreteDynamicsWorld *world, const btDefaultCollisionConstructionInfo &constructionInfo = btDefaultCollisionConstructionInfo());
+ virtual ~GodotCollisionConfiguration();
+
+ virtual btCollisionAlgorithmCreateFunc *getCollisionAlgorithmCreateFunc(int proxyType0, int proxyType1);
+ virtual btCollisionAlgorithmCreateFunc *getClosestPointsAlgorithmCreateFunc(int proxyType0, int proxyType1);
+};
+#endif
diff --git a/modules/bullet/godot_collision_dispatcher.cpp b/modules/bullet/godot_collision_dispatcher.cpp
new file mode 100644
index 0000000000..ea75e4eef4
--- /dev/null
+++ b/modules/bullet/godot_collision_dispatcher.cpp
@@ -0,0 +1,54 @@
+/*************************************************************************/
+/* godot_collision_dispatcher.cpp */
+/* Author: AndreaCatania */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "godot_collision_dispatcher.h"
+#include "collision_object_bullet.h"
+
+const int GodotCollisionDispatcher::CASTED_TYPE_AREA = static_cast<int>(CollisionObjectBullet::TYPE_AREA);
+
+GodotCollisionDispatcher::GodotCollisionDispatcher(btCollisionConfiguration *collisionConfiguration)
+ : btCollisionDispatcher(collisionConfiguration) {}
+
+bool GodotCollisionDispatcher::needsCollision(const btCollisionObject *body0, const btCollisionObject *body1) {
+ if (body0->getUserIndex() == CASTED_TYPE_AREA || body1->getUserIndex() == CASTED_TYPE_AREA) {
+ // Avoide area narrow phase
+ return false;
+ }
+ return btCollisionDispatcher::needsCollision(body0, body1);
+}
+
+bool GodotCollisionDispatcher::needsResponse(const btCollisionObject *body0, const btCollisionObject *body1) {
+ if (body0->getUserIndex() == CASTED_TYPE_AREA || body1->getUserIndex() == CASTED_TYPE_AREA) {
+ // Avoide area narrow phase
+ return false;
+ }
+ return btCollisionDispatcher::needsResponse(body0, body1);
+}
diff --git a/modules/bullet/godot_collision_dispatcher.h b/modules/bullet/godot_collision_dispatcher.h
new file mode 100644
index 0000000000..501b2078dd
--- /dev/null
+++ b/modules/bullet/godot_collision_dispatcher.h
@@ -0,0 +1,48 @@
+/*************************************************************************/
+/* godot_collision_dispatcher.h */
+/* Author: AndreaCatania */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef GODOT_COLLISION_DISPATCHER_H
+#define GODOT_COLLISION_DISPATCHER_H
+
+#include "int_types.h"
+#include <btBulletDynamicsCommon.h>
+
+/// This class is required to implement custom collision behaviour in the narrowphase
+class GodotCollisionDispatcher : public btCollisionDispatcher {
+private:
+ static const int CASTED_TYPE_AREA;
+
+public:
+ GodotCollisionDispatcher(btCollisionConfiguration *collisionConfiguration);
+ virtual bool needsCollision(const btCollisionObject *body0, const btCollisionObject *body1);
+ virtual bool needsResponse(const btCollisionObject *body0, const btCollisionObject *body1);
+};
+#endif
diff --git a/modules/bullet/godot_motion_state.h b/modules/bullet/godot_motion_state.h
new file mode 100644
index 0000000000..5111807394
--- /dev/null
+++ b/modules/bullet/godot_motion_state.h
@@ -0,0 +1,96 @@
+/*************************************************************************/
+/* godot_motion_state.h */
+/* Author: AndreaCatania */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef GODOT_MOTION_STATE_H
+#define GODOT_MOTION_STATE_H
+
+#include "LinearMath/btMotionState.h"
+#include "rigid_body_bullet.h"
+
+class RigidBodyBullet;
+
+// This clas is responsible to move kinematic actor
+// and sincronize rendering engine with Bullet
+/// DOC:
+/// http://www.bulletphysics.org/mediawiki-1.5.8/index.php/MotionStates#What.27s_a_MotionState.3F
+class GodotMotionState : public btMotionState {
+
+ /// This data is used to store the new world position for kinematic body
+ btTransform bodyKinematicWorldTransf;
+ /// This data is used to store last world position
+ btTransform bodyCurrentWorldTransform;
+
+ RigidBodyBullet *owner;
+
+public:
+ GodotMotionState(RigidBodyBullet *p_owner)
+ : bodyKinematicWorldTransf(btMatrix3x3(1., 0., 0., 0., 1., 0., 0., 0., 1.), btVector3(0., 0., 0.)),
+ bodyCurrentWorldTransform(btMatrix3x3(1., 0., 0., 0., 1., 0., 0., 0., 1.), btVector3(0., 0., 0.)),
+ owner(p_owner) {}
+
+ /// IMPORTANT DON'T USE THIS FUNCTION TO KNOW THE CURRENT BODY TRANSFORM
+ /// This class is used internally by Bullet
+ /// Use GodotMotionState::getCurrentWorldTransform to know current position
+ ///
+ /// This function is used by Bullet to get the position of object in the world
+ /// if the body is kinematic Bullet will move the object to this location
+ /// if the body is static Bullet doesn't move at all
+ virtual void getWorldTransform(btTransform &worldTrans) const {
+ worldTrans = bodyKinematicWorldTransf;
+ }
+
+ /// IMPORTANT: to move the body use: moveBody
+ /// IMPORTANT: DON'T CALL THIS FUNCTION, IT IS CALLED BY BULLET TO UPDATE RENDERING ENGINE
+ ///
+ /// This function is called each time by Bullet and set the current position of body
+ /// inside the physics world.
+ /// Don't allow Godot rendering scene takes world transform from this object because
+ /// the correct transform is set by Bullet only after the last step when there are sub steps
+ /// This function must update Godot transform rendering scene for this object.
+ virtual void setWorldTransform(const btTransform &worldTrans) {
+ bodyCurrentWorldTransform = worldTrans;
+
+ owner->scratch();
+ }
+
+public:
+ /// Use this function to move kinematic body
+ /// -- or set initial transfom before body creation.
+ void moveBody(const btTransform &newWorldTransform) {
+ bodyKinematicWorldTransf = newWorldTransform;
+ }
+
+ /// It returns the current body transform from last Bullet update
+ const btTransform &getCurrentWorldTransform() const {
+ return bodyCurrentWorldTransform;
+ }
+};
+#endif
diff --git a/modules/bullet/godot_ray_world_algorithm.cpp b/modules/bullet/godot_ray_world_algorithm.cpp
new file mode 100644
index 0000000000..98daf8398e
--- /dev/null
+++ b/modules/bullet/godot_ray_world_algorithm.cpp
@@ -0,0 +1,104 @@
+/*************************************************************************/
+/* godot_ray_world_algorithm.cpp */
+/* Author: AndreaCatania */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "godot_ray_world_algorithm.h"
+#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h"
+#include "btRayShape.h"
+#include "collision_object_bullet.h"
+
+GodotRayWorldAlgorithm::CreateFunc::CreateFunc(const btDiscreteDynamicsWorld *world)
+ : m_world(world) {}
+
+GodotRayWorldAlgorithm::SwappedCreateFunc::SwappedCreateFunc(const btDiscreteDynamicsWorld *world)
+ : m_world(world) {}
+
+GodotRayWorldAlgorithm::GodotRayWorldAlgorithm(const btDiscreteDynamicsWorld *world, btPersistentManifold *mf, const btCollisionAlgorithmConstructionInfo &ci, const btCollisionObjectWrapper *body0Wrap, const btCollisionObjectWrapper *body1Wrap, bool isSwapped)
+ : btActivatingCollisionAlgorithm(ci, body0Wrap, body1Wrap),
+ m_manifoldPtr(mf),
+ m_ownManifold(false),
+ m_world(world),
+ m_isSwapped(isSwapped) {}
+
+GodotRayWorldAlgorithm::~GodotRayWorldAlgorithm() {
+ if (m_ownManifold && m_manifoldPtr) {
+ m_dispatcher->releaseManifold(m_manifoldPtr);
+ }
+}
+
+void GodotRayWorldAlgorithm::processCollision(const btCollisionObjectWrapper *body0Wrap, const btCollisionObjectWrapper *body1Wrap, const btDispatcherInfo &dispatchInfo, btManifoldResult *resultOut) {
+
+ if (!m_manifoldPtr) {
+ if (m_isSwapped) {
+ m_manifoldPtr = m_dispatcher->getNewManifold(body1Wrap->getCollisionObject(), body0Wrap->getCollisionObject());
+ } else {
+ m_manifoldPtr = m_dispatcher->getNewManifold(body0Wrap->getCollisionObject(), body1Wrap->getCollisionObject());
+ }
+ m_ownManifold = true;
+ }
+ m_manifoldPtr->clearManifold();
+ resultOut->setPersistentManifold(m_manifoldPtr);
+
+ const btRayShape *ray_shape;
+ btTransform ray_transform;
+
+ const btCollisionObjectWrapper *other_co_wrapper;
+
+ if (m_isSwapped) {
+
+ ray_shape = static_cast<const btRayShape *>(body1Wrap->getCollisionShape());
+ ray_transform = body1Wrap->getWorldTransform();
+
+ other_co_wrapper = body0Wrap;
+ } else {
+
+ ray_shape = static_cast<const btRayShape *>(body0Wrap->getCollisionShape());
+ ray_transform = body0Wrap->getWorldTransform();
+
+ other_co_wrapper = body1Wrap;
+ }
+
+ btTransform to(ray_transform * ray_shape->getSupportPoint());
+
+ btCollisionWorld::ClosestRayResultCallback btResult(ray_transform.getOrigin(), to.getOrigin());
+
+ m_world->rayTestSingleInternal(ray_transform, to, other_co_wrapper, btResult);
+
+ if (btResult.hasHit()) {
+ btVector3 ray_normal(to.getOrigin() - ray_transform.getOrigin());
+ ray_normal.normalize();
+ ray_normal *= -1;
+ resultOut->addContactPoint(ray_normal, btResult.m_hitPointWorld, ray_shape->getScaledLength() * (btResult.m_closestHitFraction - 1));
+ }
+}
+
+btScalar GodotRayWorldAlgorithm::calculateTimeOfImpact(btCollisionObject *body0, btCollisionObject *body1, const btDispatcherInfo &dispatchInfo, btManifoldResult *resultOut) {
+ return 1;
+}
diff --git a/modules/bullet/godot_ray_world_algorithm.h b/modules/bullet/godot_ray_world_algorithm.h
new file mode 100644
index 0000000000..15c71b8d7d
--- /dev/null
+++ b/modules/bullet/godot_ray_world_algorithm.h
@@ -0,0 +1,83 @@
+/*************************************************************************/
+/* godot_ray_world_algorithm.h */
+/* Author: AndreaCatania */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef GODOT_RAY_WORLD_ALGORITHM_H
+#define GODOT_RAY_WORLD_ALGORITHM_H
+
+#include "BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+
+class btDiscreteDynamicsWorld;
+
+class GodotRayWorldAlgorithm : public btActivatingCollisionAlgorithm {
+
+ const btDiscreteDynamicsWorld *m_world;
+ btPersistentManifold *m_manifoldPtr;
+ bool m_ownManifold;
+ bool m_isSwapped;
+
+public:
+ GodotRayWorldAlgorithm(const btDiscreteDynamicsWorld *m_world, btPersistentManifold *mf, const btCollisionAlgorithmConstructionInfo &ci, const btCollisionObjectWrapper *body0Wrap, const btCollisionObjectWrapper *body1Wrap, bool isSwapped);
+ virtual ~GodotRayWorldAlgorithm();
+
+ virtual void processCollision(const btCollisionObjectWrapper *body0Wrap, const btCollisionObjectWrapper *body1Wrap, const btDispatcherInfo &dispatchInfo, btManifoldResult *resultOut);
+ virtual btScalar calculateTimeOfImpact(btCollisionObject *body0, btCollisionObject *body1, const btDispatcherInfo &dispatchInfo, btManifoldResult *resultOut);
+
+ virtual void getAllContactManifolds(btManifoldArray &manifoldArray) {
+ ///should we use m_ownManifold to avoid adding duplicates?
+ if (m_manifoldPtr && m_ownManifold)
+ manifoldArray.push_back(m_manifoldPtr);
+ }
+ struct CreateFunc : public btCollisionAlgorithmCreateFunc {
+
+ const btDiscreteDynamicsWorld *m_world;
+ CreateFunc(const btDiscreteDynamicsWorld *world);
+
+ virtual btCollisionAlgorithm *CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo &ci, const btCollisionObjectWrapper *body0Wrap, const btCollisionObjectWrapper *body1Wrap) {
+ void *mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(GodotRayWorldAlgorithm));
+ return new (mem) GodotRayWorldAlgorithm(m_world, ci.m_manifold, ci, body0Wrap, body1Wrap, false);
+ }
+ };
+
+ struct SwappedCreateFunc : public btCollisionAlgorithmCreateFunc {
+
+ const btDiscreteDynamicsWorld *m_world;
+ SwappedCreateFunc(const btDiscreteDynamicsWorld *world);
+
+ virtual btCollisionAlgorithm *CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo &ci, const btCollisionObjectWrapper *body0Wrap, const btCollisionObjectWrapper *body1Wrap) {
+ void *mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(GodotRayWorldAlgorithm));
+ return new (mem) GodotRayWorldAlgorithm(m_world, ci.m_manifold, ci, body0Wrap, body1Wrap, true);
+ }
+ };
+};
+
+#endif // GODOT_RAY_WORLD_ALGORITHM_H
diff --git a/modules/bullet/godot_result_callbacks.cpp b/modules/bullet/godot_result_callbacks.cpp
new file mode 100644
index 0000000000..cbf30c8a2e
--- /dev/null
+++ b/modules/bullet/godot_result_callbacks.cpp
@@ -0,0 +1,262 @@
+/*************************************************************************/
+/* godot_result_callbacks.cpp */
+/* Author: AndreaCatania */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "godot_result_callbacks.h"
+#include "bullet_types_converter.h"
+#include "collision_object_bullet.h"
+#include "rigid_body_bullet.h"
+
+bool GodotFilterCallback::test_collision_filters(uint32_t body0_collision_layer, uint32_t body0_collision_mask, uint32_t body1_collision_layer, uint32_t body1_collision_mask) {
+ return body0_collision_layer & body1_collision_mask || body1_collision_layer & body0_collision_mask;
+}
+
+bool GodotFilterCallback::needBroadphaseCollision(btBroadphaseProxy *proxy0, btBroadphaseProxy *proxy1) const {
+ return GodotFilterCallback::test_collision_filters(proxy0->m_collisionFilterGroup, proxy0->m_collisionFilterMask, proxy1->m_collisionFilterGroup, proxy1->m_collisionFilterMask);
+}
+
+bool GodotClosestRayResultCallback::needsCollision(btBroadphaseProxy *proxy0) const {
+ const bool needs = GodotFilterCallback::test_collision_filters(m_collisionFilterGroup, m_collisionFilterMask, proxy0->m_collisionFilterGroup, proxy0->m_collisionFilterMask);
+ if (needs) {
+ btCollisionObject *btObj = static_cast<btCollisionObject *>(proxy0->m_clientObject);
+ CollisionObjectBullet *gObj = static_cast<CollisionObjectBullet *>(btObj->getUserPointer());
+ if (m_pickRay && gObj->is_ray_pickable()) {
+ return true;
+ } else if (m_exclude->has(gObj->get_self())) {
+ return false;
+ }
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool GodotAllConvexResultCallback::needsCollision(btBroadphaseProxy *proxy0) const {
+ const bool needs = GodotFilterCallback::test_collision_filters(m_collisionFilterGroup, m_collisionFilterMask, proxy0->m_collisionFilterGroup, proxy0->m_collisionFilterMask);
+ if (needs) {
+ btCollisionObject *btObj = static_cast<btCollisionObject *>(proxy0->m_clientObject);
+ CollisionObjectBullet *gObj = static_cast<CollisionObjectBullet *>(btObj->getUserPointer());
+ if (m_exclude->has(gObj->get_self())) {
+ return false;
+ }
+ return true;
+ } else {
+ return false;
+ }
+}
+
+btScalar GodotAllConvexResultCallback::addSingleResult(btCollisionWorld::LocalConvexResult &convexResult, bool normalInWorldSpace) {
+ CollisionObjectBullet *gObj = static_cast<CollisionObjectBullet *>(convexResult.m_hitCollisionObject->getUserPointer());
+
+ PhysicsDirectSpaceState::ShapeResult &result = m_results[count];
+
+ result.shape = convexResult.m_localShapeInfo->m_triangleIndex; // "m_triangleIndex" Is a odd name but contains the compound shape ID
+ result.rid = gObj->get_self();
+ result.collider_id = gObj->get_instance_id();
+ result.collider = 0 == result.collider_id ? NULL : ObjectDB::get_instance(result.collider_id);
+
+ ++count;
+ return count < m_resultMax;
+}
+
+bool GodotKinClosestConvexResultCallback::needsCollision(btBroadphaseProxy *proxy0) const {
+ const bool needs = GodotFilterCallback::test_collision_filters(m_collisionFilterGroup, m_collisionFilterMask, proxy0->m_collisionFilterGroup, proxy0->m_collisionFilterMask);
+ if (needs) {
+ btCollisionObject *btObj = static_cast<btCollisionObject *>(proxy0->m_clientObject);
+ CollisionObjectBullet *gObj = static_cast<CollisionObjectBullet *>(btObj->getUserPointer());
+ if (gObj == m_self_object) {
+ return false;
+ } else {
+ if (m_ignore_areas && gObj->getType() == CollisionObjectBullet::TYPE_AREA) {
+ return false;
+ } else if (m_self_object->has_collision_exception(gObj)) {
+ return false;
+ }
+ }
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool GodotClosestConvexResultCallback::needsCollision(btBroadphaseProxy *proxy0) const {
+ const bool needs = GodotFilterCallback::test_collision_filters(m_collisionFilterGroup, m_collisionFilterMask, proxy0->m_collisionFilterGroup, proxy0->m_collisionFilterMask);
+ if (needs) {
+ btCollisionObject *btObj = static_cast<btCollisionObject *>(proxy0->m_clientObject);
+ CollisionObjectBullet *gObj = static_cast<CollisionObjectBullet *>(btObj->getUserPointer());
+ if (m_exclude->has(gObj->get_self())) {
+ return false;
+ }
+ return true;
+ } else {
+ return false;
+ }
+}
+
+btScalar GodotClosestConvexResultCallback::addSingleResult(btCollisionWorld::LocalConvexResult &convexResult, bool normalInWorldSpace) {
+ btScalar res = btCollisionWorld::ClosestConvexResultCallback::addSingleResult(convexResult, normalInWorldSpace);
+ m_shapeId = convexResult.m_localShapeInfo->m_triangleIndex; // "m_triangleIndex" Is a odd name but contains the compound shape ID
+ return res;
+}
+
+bool GodotAllContactResultCallback::needsCollision(btBroadphaseProxy *proxy0) const {
+ const bool needs = GodotFilterCallback::test_collision_filters(m_collisionFilterGroup, m_collisionFilterMask, proxy0->m_collisionFilterGroup, proxy0->m_collisionFilterMask);
+ if (needs) {
+ btCollisionObject *btObj = static_cast<btCollisionObject *>(proxy0->m_clientObject);
+ CollisionObjectBullet *gObj = static_cast<CollisionObjectBullet *>(btObj->getUserPointer());
+ if (m_exclude->has(gObj->get_self())) {
+ return false;
+ }
+ return true;
+ } else {
+ return false;
+ }
+}
+
+btScalar GodotAllContactResultCallback::addSingleResult(btManifoldPoint &cp, const btCollisionObjectWrapper *colObj0Wrap, int partId0, int index0, const btCollisionObjectWrapper *colObj1Wrap, int partId1, int index1) {
+
+ if (cp.getDistance() <= 0) {
+
+ PhysicsDirectSpaceState::ShapeResult &result = m_results[m_count];
+ // Penetrated
+
+ CollisionObjectBullet *colObj;
+ if (m_self_object == colObj0Wrap->getCollisionObject()) {
+ colObj = static_cast<CollisionObjectBullet *>(colObj1Wrap->getCollisionObject()->getUserPointer());
+ result.shape = cp.m_index1;
+ } else {
+ colObj = static_cast<CollisionObjectBullet *>(colObj0Wrap->getCollisionObject()->getUserPointer());
+ result.shape = cp.m_index0;
+ }
+
+ if (colObj)
+ result.collider_id = colObj->get_instance_id();
+ else
+ result.collider_id = 0;
+ result.collider = 0 == result.collider_id ? NULL : ObjectDB::get_instance(result.collider_id);
+ result.rid = colObj->get_self();
+ ++m_count;
+ }
+
+ return m_count < m_resultMax;
+}
+
+bool GodotContactPairContactResultCallback::needsCollision(btBroadphaseProxy *proxy0) const {
+ const bool needs = GodotFilterCallback::test_collision_filters(m_collisionFilterGroup, m_collisionFilterMask, proxy0->m_collisionFilterGroup, proxy0->m_collisionFilterMask);
+ if (needs) {
+ btCollisionObject *btObj = static_cast<btCollisionObject *>(proxy0->m_clientObject);
+ CollisionObjectBullet *gObj = static_cast<CollisionObjectBullet *>(btObj->getUserPointer());
+ if (m_exclude->has(gObj->get_self())) {
+ return false;
+ }
+ return true;
+ } else {
+ return false;
+ }
+}
+
+btScalar GodotContactPairContactResultCallback::addSingleResult(btManifoldPoint &cp, const btCollisionObjectWrapper *colObj0Wrap, int partId0, int index0, const btCollisionObjectWrapper *colObj1Wrap, int partId1, int index1) {
+
+ if (m_self_object == colObj0Wrap->getCollisionObject()) {
+ B_TO_G(cp.m_localPointA, m_results[m_count * 2 + 0]); // Local contact
+ B_TO_G(cp.m_localPointB, m_results[m_count * 2 + 1]);
+ } else {
+ B_TO_G(cp.m_localPointB, m_results[m_count * 2 + 0]); // Local contact
+ B_TO_G(cp.m_localPointA, m_results[m_count * 2 + 1]);
+ }
+
+ ++m_count;
+
+ return m_count < m_resultMax;
+}
+
+bool GodotRestInfoContactResultCallback::needsCollision(btBroadphaseProxy *proxy0) const {
+ const bool needs = GodotFilterCallback::test_collision_filters(m_collisionFilterGroup, m_collisionFilterMask, proxy0->m_collisionFilterGroup, proxy0->m_collisionFilterMask);
+ if (needs) {
+ btCollisionObject *btObj = static_cast<btCollisionObject *>(proxy0->m_clientObject);
+ CollisionObjectBullet *gObj = static_cast<CollisionObjectBullet *>(btObj->getUserPointer());
+ if (m_exclude->has(gObj->get_self())) {
+ return false;
+ }
+ return true;
+ } else {
+ return false;
+ }
+}
+
+btScalar GodotRestInfoContactResultCallback::addSingleResult(btManifoldPoint &cp, const btCollisionObjectWrapper *colObj0Wrap, int partId0, int index0, const btCollisionObjectWrapper *colObj1Wrap, int partId1, int index1) {
+
+ if (cp.getDistance() <= m_min_distance) {
+ m_min_distance = cp.getDistance();
+
+ CollisionObjectBullet *colObj;
+ if (m_self_object == colObj0Wrap->getCollisionObject()) {
+ colObj = static_cast<CollisionObjectBullet *>(colObj1Wrap->getCollisionObject()->getUserPointer());
+ m_result->shape = cp.m_index1;
+ B_TO_G(cp.getPositionWorldOnB(), m_result->point);
+ m_rest_info_bt_point = cp.getPositionWorldOnB();
+ m_rest_info_collision_object = colObj1Wrap->getCollisionObject();
+ } else {
+ colObj = static_cast<CollisionObjectBullet *>(colObj0Wrap->getCollisionObject()->getUserPointer());
+ m_result->shape = cp.m_index0;
+ B_TO_G(cp.m_normalWorldOnB * -1, m_result->normal);
+ m_rest_info_bt_point = cp.getPositionWorldOnA();
+ m_rest_info_collision_object = colObj0Wrap->getCollisionObject();
+ }
+
+ if (colObj)
+ m_result->collider_id = colObj->get_instance_id();
+ else
+ m_result->collider_id = 0;
+ m_result->rid = colObj->get_self();
+
+ m_collided = true;
+ }
+
+ return cp.getDistance();
+}
+
+void GodotDeepPenetrationContactResultCallback::addContactPoint(const btVector3 &normalOnBInWorld, const btVector3 &pointInWorldOnB, btScalar depth) {
+
+ if (depth < 0) {
+ // Has penetration
+ if (m_most_penetrated_distance > depth) {
+
+ bool isSwapped = m_manifoldPtr->getBody0() != m_body0Wrap->getCollisionObject();
+
+ m_most_penetrated_distance = depth;
+ m_pointCollisionObject = (isSwapped ? m_body0Wrap : m_body1Wrap)->getCollisionObject();
+ m_other_compound_shape_index = isSwapped ? m_index1 : m_index0;
+ m_pointNormalWorld = isSwapped ? normalOnBInWorld * -1 : normalOnBInWorld;
+ m_pointWorld = isSwapped ? (pointInWorldOnB + normalOnBInWorld * depth) : pointInWorldOnB;
+ m_penetration_distance = depth;
+ }
+ }
+}
diff --git a/modules/bullet/godot_result_callbacks.h b/modules/bullet/godot_result_callbacks.h
new file mode 100644
index 0000000000..ba5142676b
--- /dev/null
+++ b/modules/bullet/godot_result_callbacks.h
@@ -0,0 +1,179 @@
+/*************************************************************************/
+/* godot_result_callbacks.h */
+/* Author: AndreaCatania */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef GODOT_RESULT_CALLBACKS_H
+#define GODOT_RESULT_CALLBACKS_H
+
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "btBulletDynamicsCommon.h"
+#include "servers/physics_server.h"
+
+class RigidBodyBullet;
+
+/// This class is required to implement custom collision behaviour in the broadphase
+struct GodotFilterCallback : public btOverlapFilterCallback {
+ static bool test_collision_filters(uint32_t body0_collision_layer, uint32_t body0_collision_mask, uint32_t body1_collision_layer, uint32_t body1_collision_mask);
+
+ // return true when pairs need collision
+ virtual bool needBroadphaseCollision(btBroadphaseProxy *proxy0, btBroadphaseProxy *proxy1) const;
+};
+
+/// It performs an additional check allow exclusions.
+struct GodotClosestRayResultCallback : public btCollisionWorld::ClosestRayResultCallback {
+ const Set<RID> *m_exclude;
+ bool m_pickRay;
+
+public:
+ GodotClosestRayResultCallback(const btVector3 &rayFromWorld, const btVector3 &rayToWorld, const Set<RID> *p_exclude)
+ : btCollisionWorld::ClosestRayResultCallback(rayFromWorld, rayToWorld), m_exclude(p_exclude), m_pickRay(false) {}
+
+ virtual bool needsCollision(btBroadphaseProxy *proxy0) const;
+};
+
+// store all colliding object
+struct GodotAllConvexResultCallback : public btCollisionWorld::ConvexResultCallback {
+public:
+ PhysicsDirectSpaceState::ShapeResult *m_results;
+ int m_resultMax;
+ int count;
+ const Set<RID> *m_exclude;
+
+ GodotAllConvexResultCallback(PhysicsDirectSpaceState::ShapeResult *p_results, int p_resultMax, const Set<RID> *p_exclude)
+ : m_results(p_results), m_exclude(p_exclude), m_resultMax(p_resultMax), count(0) {}
+
+ virtual bool needsCollision(btBroadphaseProxy *proxy0) const;
+
+ virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult &convexResult, bool normalInWorldSpace);
+};
+
+struct GodotKinClosestConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback {
+public:
+ const RigidBodyBullet *m_self_object;
+ const bool m_ignore_areas;
+
+ GodotKinClosestConvexResultCallback(const btVector3 &convexFromWorld, const btVector3 &convexToWorld, const RigidBodyBullet *p_self_object, bool p_ignore_areas)
+ : btCollisionWorld::ClosestConvexResultCallback(convexFromWorld, convexToWorld), m_self_object(p_self_object), m_ignore_areas(p_ignore_areas) {}
+
+ virtual bool needsCollision(btBroadphaseProxy *proxy0) const;
+};
+
+struct GodotClosestConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback {
+public:
+ const Set<RID> *m_exclude;
+ int m_shapeId;
+
+ GodotClosestConvexResultCallback(const btVector3 &convexFromWorld, const btVector3 &convexToWorld, const Set<RID> *p_exclude)
+ : btCollisionWorld::ClosestConvexResultCallback(convexFromWorld, convexToWorld), m_exclude(p_exclude) {}
+
+ virtual bool needsCollision(btBroadphaseProxy *proxy0) const;
+
+ virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult &convexResult, bool normalInWorldSpace);
+};
+
+struct GodotAllContactResultCallback : public btCollisionWorld::ContactResultCallback {
+public:
+ const btCollisionObject *m_self_object;
+ PhysicsDirectSpaceState::ShapeResult *m_results;
+ int m_resultMax;
+ int m_count;
+ const Set<RID> *m_exclude;
+
+ GodotAllContactResultCallback(btCollisionObject *p_self_object, PhysicsDirectSpaceState::ShapeResult *p_results, int p_resultMax, const Set<RID> *p_exclude)
+ : m_self_object(p_self_object), m_results(p_results), m_exclude(p_exclude), m_resultMax(p_resultMax), m_count(0) {}
+
+ virtual bool needsCollision(btBroadphaseProxy *proxy0) const;
+
+ virtual btScalar addSingleResult(btManifoldPoint &cp, const btCollisionObjectWrapper *colObj0Wrap, int partId0, int index0, const btCollisionObjectWrapper *colObj1Wrap, int partId1, int index1);
+};
+
+/// Returns the list of contacts pairs in this order: Local contact, other body contact
+struct GodotContactPairContactResultCallback : public btCollisionWorld::ContactResultCallback {
+public:
+ const btCollisionObject *m_self_object;
+ Vector3 *m_results;
+ int m_resultMax;
+ int m_count;
+ const Set<RID> *m_exclude;
+
+ GodotContactPairContactResultCallback(btCollisionObject *p_self_object, Vector3 *p_results, int p_resultMax, const Set<RID> *p_exclude)
+ : m_self_object(p_self_object), m_results(p_results), m_exclude(p_exclude), m_resultMax(p_resultMax), m_count(0) {}
+
+ virtual bool needsCollision(btBroadphaseProxy *proxy0) const;
+
+ virtual btScalar addSingleResult(btManifoldPoint &cp, const btCollisionObjectWrapper *colObj0Wrap, int partId0, int index0, const btCollisionObjectWrapper *colObj1Wrap, int partId1, int index1);
+};
+
+struct GodotRestInfoContactResultCallback : public btCollisionWorld::ContactResultCallback {
+public:
+ const btCollisionObject *m_self_object;
+ PhysicsDirectSpaceState::ShapeRestInfo *m_result;
+ bool m_collided;
+ real_t m_min_distance;
+ const btCollisionObject *m_rest_info_collision_object;
+ btVector3 m_rest_info_bt_point;
+ const Set<RID> *m_exclude;
+
+ GodotRestInfoContactResultCallback(btCollisionObject *p_self_object, PhysicsDirectSpaceState::ShapeRestInfo *p_result, const Set<RID> *p_exclude)
+ : m_self_object(p_self_object), m_result(p_result), m_exclude(p_exclude), m_collided(false), m_min_distance(0) {}
+
+ virtual bool needsCollision(btBroadphaseProxy *proxy0) const;
+
+ virtual btScalar addSingleResult(btManifoldPoint &cp, const btCollisionObjectWrapper *colObj0Wrap, int partId0, int index0, const btCollisionObjectWrapper *colObj1Wrap, int partId1, int index1);
+};
+
+struct GodotDeepPenetrationContactResultCallback : public btManifoldResult {
+ btVector3 m_pointNormalWorld;
+ btVector3 m_pointWorld;
+ btScalar m_penetration_distance;
+ int m_other_compound_shape_index;
+ const btCollisionObject *m_pointCollisionObject;
+
+ btScalar m_most_penetrated_distance;
+
+ GodotDeepPenetrationContactResultCallback(const btCollisionObjectWrapper *body0Wrap, const btCollisionObjectWrapper *body1Wrap)
+ : btManifoldResult(body0Wrap, body1Wrap),
+ m_pointCollisionObject(NULL),
+ m_penetration_distance(0),
+ m_other_compound_shape_index(0),
+ m_most_penetrated_distance(1e20) {}
+
+ void reset() {
+ m_pointCollisionObject = NULL;
+ m_most_penetrated_distance = 1e20;
+ }
+
+ bool hasHit() {
+ return m_pointCollisionObject;
+ }
+
+ virtual void addContactPoint(const btVector3 &normalOnBInWorld, const btVector3 &pointInWorld, btScalar depth);
+};
+#endif // GODOT_RESULT_CALLBACKS_H
diff --git a/modules/bullet/hinge_joint_bullet.cpp b/modules/bullet/hinge_joint_bullet.cpp
new file mode 100644
index 0000000000..bb70babd99
--- /dev/null
+++ b/modules/bullet/hinge_joint_bullet.cpp
@@ -0,0 +1,163 @@
+/*************************************************************************/
+/* hinge_joint_bullet.cpp */
+/* Author: AndreaCatania */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "hinge_joint_bullet.h"
+#include "BulletDynamics/ConstraintSolver/btHingeConstraint.h"
+#include "bullet_types_converter.h"
+#include "bullet_utilities.h"
+#include "rigid_body_bullet.h"
+
+HingeJointBullet::HingeJointBullet(RigidBodyBullet *rbA, RigidBodyBullet *rbB, const Transform &frameA, const Transform &frameB)
+ : JointBullet() {
+ btTransform btFrameA;
+ G_TO_B(frameA, btFrameA);
+
+ if (rbB) {
+ btTransform btFrameB;
+ G_TO_B(frameB, btFrameB);
+
+ hingeConstraint = bulletnew(btHingeConstraint(*rbA->get_bt_rigid_body(), *rbB->get_bt_rigid_body(), btFrameA, btFrameB));
+ } else {
+
+ hingeConstraint = bulletnew(btHingeConstraint(*rbA->get_bt_rigid_body(), btFrameA));
+ }
+
+ setup(hingeConstraint);
+}
+
+HingeJointBullet::HingeJointBullet(RigidBodyBullet *rbA, RigidBodyBullet *rbB, const Vector3 &pivotInA, const Vector3 &pivotInB, const Vector3 &axisInA, const Vector3 &axisInB)
+ : JointBullet() {
+
+ btVector3 btPivotA;
+ btVector3 btAxisA;
+ G_TO_B(pivotInA, btPivotA);
+ G_TO_B(axisInA, btAxisA);
+
+ if (rbB) {
+ btVector3 btPivotB;
+ btVector3 btAxisB;
+ G_TO_B(pivotInB, btPivotB);
+ G_TO_B(axisInB, btAxisB);
+
+ hingeConstraint = bulletnew(btHingeConstraint(*rbA->get_bt_rigid_body(), *rbB->get_bt_rigid_body(), btPivotA, btPivotB, btAxisA, btAxisB));
+ } else {
+
+ hingeConstraint = bulletnew(btHingeConstraint(*rbA->get_bt_rigid_body(), btPivotA, btAxisA));
+ }
+
+ setup(hingeConstraint);
+}
+
+real_t HingeJointBullet::get_hinge_angle() {
+ return hingeConstraint->getHingeAngle();
+}
+
+void HingeJointBullet::set_param(PhysicsServer::HingeJointParam p_param, real_t p_value) {
+ switch (p_param) {
+ case PhysicsServer::HINGE_JOINT_BIAS:
+ if (0 < p_value) {
+ print_line("The Bullet Hinge Joint doesn't support bias, So it's always 0");
+ }
+ break;
+ case PhysicsServer::HINGE_JOINT_LIMIT_UPPER:
+ hingeConstraint->setLimit(hingeConstraint->getLowerLimit(), p_value, hingeConstraint->getLimitSoftness(), hingeConstraint->getLimitBiasFactor(), hingeConstraint->getLimitRelaxationFactor());
+ break;
+ case PhysicsServer::HINGE_JOINT_LIMIT_LOWER:
+ hingeConstraint->setLimit(p_value, hingeConstraint->getUpperLimit(), hingeConstraint->getLimitSoftness(), hingeConstraint->getLimitBiasFactor(), hingeConstraint->getLimitRelaxationFactor());
+ break;
+ case PhysicsServer::HINGE_JOINT_LIMIT_BIAS:
+ hingeConstraint->setLimit(hingeConstraint->getLowerLimit(), hingeConstraint->getUpperLimit(), hingeConstraint->getLimitSoftness(), p_value, hingeConstraint->getLimitRelaxationFactor());
+ break;
+ case PhysicsServer::HINGE_JOINT_LIMIT_SOFTNESS:
+ hingeConstraint->setLimit(hingeConstraint->getLowerLimit(), hingeConstraint->getUpperLimit(), p_value, hingeConstraint->getLimitBiasFactor(), hingeConstraint->getLimitRelaxationFactor());
+ break;
+ case PhysicsServer::HINGE_JOINT_LIMIT_RELAXATION:
+ hingeConstraint->setLimit(hingeConstraint->getLowerLimit(), hingeConstraint->getUpperLimit(), hingeConstraint->getLimitSoftness(), hingeConstraint->getLimitBiasFactor(), p_value);
+ break;
+ case PhysicsServer::HINGE_JOINT_MOTOR_TARGET_VELOCITY:
+ hingeConstraint->setMotorTargetVelocity(p_value);
+ break;
+ case PhysicsServer::HINGE_JOINT_MOTOR_MAX_IMPULSE:
+ hingeConstraint->setMaxMotorImpulse(p_value);
+ break;
+ default:
+ WARN_PRINTS("The Bullet Hinge Joint doesn't support this parameter: " + itos(p_param) + ", value: " + itos(p_value));
+ }
+}
+
+real_t HingeJointBullet::get_param(PhysicsServer::HingeJointParam p_param) const {
+ switch (p_param) {
+ case PhysicsServer::HINGE_JOINT_BIAS:
+ return 0;
+ break;
+ case PhysicsServer::HINGE_JOINT_LIMIT_UPPER:
+ return hingeConstraint->getUpperLimit();
+ case PhysicsServer::HINGE_JOINT_LIMIT_LOWER:
+ return hingeConstraint->getLowerLimit();
+ case PhysicsServer::HINGE_JOINT_LIMIT_BIAS:
+ return hingeConstraint->getLimitBiasFactor();
+ case PhysicsServer::HINGE_JOINT_LIMIT_SOFTNESS:
+ return hingeConstraint->getLimitSoftness();
+ case PhysicsServer::HINGE_JOINT_LIMIT_RELAXATION:
+ return hingeConstraint->getLimitRelaxationFactor();
+ case PhysicsServer::HINGE_JOINT_MOTOR_TARGET_VELOCITY:
+ return hingeConstraint->getMotorTargetVelocity();
+ case PhysicsServer::HINGE_JOINT_MOTOR_MAX_IMPULSE:
+ return hingeConstraint->getMaxMotorImpulse();
+ default:
+ WARN_PRINTS("The Bullet Hinge Joint doesn't support this parameter: " + itos(p_param));
+ return 0;
+ }
+}
+
+void HingeJointBullet::set_flag(PhysicsServer::HingeJointFlag p_flag, bool p_value) {
+ switch (p_flag) {
+ case PhysicsServer::HINGE_JOINT_FLAG_USE_LIMIT:
+ if (!p_value) {
+ hingeConstraint->setLimit(-Math_PI, Math_PI);
+ }
+ break;
+ case PhysicsServer::HINGE_JOINT_FLAG_ENABLE_MOTOR:
+ hingeConstraint->enableMotor(p_value);
+ break;
+ }
+}
+
+bool HingeJointBullet::get_flag(PhysicsServer::HingeJointFlag p_flag) const {
+ switch (p_flag) {
+ case PhysicsServer::HINGE_JOINT_FLAG_USE_LIMIT:
+ return true;
+ case PhysicsServer::HINGE_JOINT_FLAG_ENABLE_MOTOR:
+ return hingeConstraint->getEnableAngularMotor();
+ default:
+ return false;
+ }
+}
diff --git a/modules/bullet/hinge_joint_bullet.h b/modules/bullet/hinge_joint_bullet.h
new file mode 100644
index 0000000000..a78788a5e5
--- /dev/null
+++ b/modules/bullet/hinge_joint_bullet.h
@@ -0,0 +1,54 @@
+/*************************************************************************/
+/* hinge_joint_bullet.h */
+/* Author: AndreaCatania */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef HINGE_JOINT_BULLET_H
+#define HINGE_JOINT_BULLET_H
+
+#include "joint_bullet.h"
+
+class HingeJointBullet : public JointBullet {
+ class btHingeConstraint *hingeConstraint;
+
+public:
+ HingeJointBullet(RigidBodyBullet *rbA, RigidBodyBullet *rbB, const Transform &frameA, const Transform &frameB);
+ HingeJointBullet(RigidBodyBullet *rbA, RigidBodyBullet *rbB, const Vector3 &pivotInA, const Vector3 &pivotInB, const Vector3 &axisInA, const Vector3 &axisInB);
+
+ virtual PhysicsServer::JointType get_type() const { return PhysicsServer::JOINT_HINGE; }
+
+ real_t get_hinge_angle();
+
+ void set_param(PhysicsServer::HingeJointParam p_param, real_t p_value);
+ real_t get_param(PhysicsServer::HingeJointParam p_param) const;
+
+ void set_flag(PhysicsServer::HingeJointFlag p_flag, bool p_value);
+ bool get_flag(PhysicsServer::HingeJointFlag p_flag) const;
+};
+#endif
diff --git a/modules/bullet/joint_bullet.cpp b/modules/bullet/joint_bullet.cpp
new file mode 100644
index 0000000000..be544f89bf
--- /dev/null
+++ b/modules/bullet/joint_bullet.cpp
@@ -0,0 +1,38 @@
+/*************************************************************************/
+/* joint_bullet.cpp */
+/* Author: AndreaCatania */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "joint_bullet.h"
+#include "space_bullet.h"
+
+JointBullet::JointBullet()
+ : ConstraintBullet() {}
+
+JointBullet::~JointBullet() {}
diff --git a/modules/bullet/joint_bullet.h b/modules/bullet/joint_bullet.h
new file mode 100644
index 0000000000..d47e677502
--- /dev/null
+++ b/modules/bullet/joint_bullet.h
@@ -0,0 +1,49 @@
+/*************************************************************************/
+/* joint_bullet.h */
+/* Author: AndreaCatania */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef JOINT_BULLET_H
+#define JOINT_BULLET_H
+
+#include "constraint_bullet.h"
+#include "servers/physics_server.h"
+
+class RigidBodyBullet;
+class btTypedConstraint;
+
+class JointBullet : public ConstraintBullet {
+
+public:
+ JointBullet();
+ virtual ~JointBullet();
+
+ virtual PhysicsServer::JointType get_type() const = 0;
+};
+#endif
diff --git a/modules/bullet/pin_joint_bullet.cpp b/modules/bullet/pin_joint_bullet.cpp
new file mode 100644
index 0000000000..cd9e9a4557
--- /dev/null
+++ b/modules/bullet/pin_joint_bullet.cpp
@@ -0,0 +1,112 @@
+/*************************************************************************/
+/* pin_joint_bullet.cpp */
+/* Author: AndreaCatania */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "pin_joint_bullet.h"
+#include "BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h"
+#include "bullet_types_converter.h"
+#include "rigid_body_bullet.h"
+
+PinJointBullet::PinJointBullet(RigidBodyBullet *p_body_a, const Vector3 &p_pos_a, RigidBodyBullet *p_body_b, const Vector3 &p_pos_b)
+ : JointBullet() {
+ if (p_body_b) {
+
+ btVector3 btPivotA;
+ btVector3 btPivotB;
+ G_TO_B(p_pos_a, btPivotA);
+ G_TO_B(p_pos_b, btPivotB);
+ p2pConstraint = bulletnew(btPoint2PointConstraint(*p_body_a->get_bt_rigid_body(),
+ *p_body_b->get_bt_rigid_body(),
+ btPivotA,
+ btPivotB));
+ } else {
+ btVector3 btPivotA;
+ G_TO_B(p_pos_a, btPivotA);
+ p2pConstraint = bulletnew(btPoint2PointConstraint(*p_body_a->get_bt_rigid_body(), btPivotA));
+ }
+
+ setup(p2pConstraint);
+}
+
+PinJointBullet::~PinJointBullet() {}
+
+void PinJointBullet::set_param(PhysicsServer::PinJointParam p_param, real_t p_value) {
+ switch (p_param) {
+ case PhysicsServer::PIN_JOINT_BIAS:
+ p2pConstraint->m_setting.m_tau = p_value;
+ break;
+ case PhysicsServer::PIN_JOINT_DAMPING:
+ p2pConstraint->m_setting.m_damping = p_value;
+ break;
+ case PhysicsServer::PIN_JOINT_IMPULSE_CLAMP:
+ p2pConstraint->m_setting.m_impulseClamp = p_value;
+ break;
+ }
+}
+
+real_t PinJointBullet::get_param(PhysicsServer::PinJointParam p_param) const {
+ switch (p_param) {
+ case PhysicsServer::PIN_JOINT_BIAS:
+ return p2pConstraint->m_setting.m_tau;
+ case PhysicsServer::PIN_JOINT_DAMPING:
+ return p2pConstraint->m_setting.m_damping;
+ case PhysicsServer::PIN_JOINT_IMPULSE_CLAMP:
+ return p2pConstraint->m_setting.m_impulseClamp;
+ default:
+ WARN_PRINTS("This get parameter is not supported");
+ return 0;
+ }
+}
+
+void PinJointBullet::setPivotInA(const Vector3 &p_pos) {
+ btVector3 btVec;
+ G_TO_B(p_pos, btVec);
+ p2pConstraint->setPivotA(btVec);
+}
+
+void PinJointBullet::setPivotInB(const Vector3 &p_pos) {
+ btVector3 btVec;
+ G_TO_B(p_pos, btVec);
+ p2pConstraint->setPivotB(btVec);
+}
+
+Vector3 PinJointBullet::getPivotInA() {
+ btVector3 vec = p2pConstraint->getPivotInA();
+ Vector3 gVec;
+ B_TO_G(vec, gVec);
+ return gVec;
+}
+
+Vector3 PinJointBullet::getPivotInB() {
+ btVector3 vec = p2pConstraint->getPivotInB();
+ Vector3 gVec;
+ B_TO_G(vec, gVec);
+ return gVec;
+}
diff --git a/modules/bullet/pin_joint_bullet.h b/modules/bullet/pin_joint_bullet.h
new file mode 100644
index 0000000000..3a0906bf83
--- /dev/null
+++ b/modules/bullet/pin_joint_bullet.h
@@ -0,0 +1,57 @@
+/*************************************************************************/
+/* pin_joint_bullet.h */
+/* Author: AndreaCatania */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef PIN_JOINT_BULLET_H
+#define PIN_JOINT_BULLET_H
+
+#include "joint_bullet.h"
+
+class RigidBodyBullet;
+
+class PinJointBullet : public JointBullet {
+ class btPoint2PointConstraint *p2pConstraint;
+
+public:
+ PinJointBullet(RigidBodyBullet *p_body_a, const Vector3 &p_pos_a, RigidBodyBullet *p_body_b, const Vector3 &p_pos_b);
+ ~PinJointBullet();
+
+ virtual PhysicsServer::JointType get_type() const { return PhysicsServer::JOINT_PIN; }
+
+ void set_param(PhysicsServer::PinJointParam p_param, real_t p_value);
+ real_t get_param(PhysicsServer::PinJointParam p_param) const;
+
+ void setPivotInA(const Vector3 &p_pos);
+ void setPivotInB(const Vector3 &p_pos);
+
+ Vector3 getPivotInA();
+ Vector3 getPivotInB();
+};
+#endif
diff --git a/modules/bullet/register_types.cpp b/modules/bullet/register_types.cpp
new file mode 100644
index 0000000000..1e697e7443
--- /dev/null
+++ b/modules/bullet/register_types.cpp
@@ -0,0 +1,47 @@
+/*************************************************************************/
+/* register_types.cpp */
+/* Author: AndreaCatania */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "register_types.h"
+#include "bullet_physics_server.h"
+#include "class_db.h"
+
+PhysicsServer *_createBulletPhysicsCallback() {
+ return memnew(BulletPhysicsServer);
+}
+
+void register_bullet_types() {
+
+ PhysicsServerManager::register_server("Bullet", &_createBulletPhysicsCallback);
+ PhysicsServerManager::set_default_server("Bullet", 1);
+}
+
+void unregister_bullet_types() {
+}
diff --git a/modules/bullet/register_types.h b/modules/bullet/register_types.h
new file mode 100644
index 0000000000..ca0683fa3b
--- /dev/null
+++ b/modules/bullet/register_types.h
@@ -0,0 +1,37 @@
+/*************************************************************************/
+/* register_types.h */
+/* Author: AndreaCatania */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef REGISTER_BULLET_TYPES_H
+#define REGISTER_BULLET_TYPES_H
+
+void register_bullet_types();
+void unregister_bullet_types();
+#endif
diff --git a/modules/bullet/rid_bullet.h b/modules/bullet/rid_bullet.h
new file mode 100644
index 0000000000..da7517f246
--- /dev/null
+++ b/modules/bullet/rid_bullet.h
@@ -0,0 +1,50 @@
+/*************************************************************************/
+/* rid_bullet.h */
+/* Author: AndreaCatania */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef RID_BULLET_H
+#define RID_BULLET_H
+
+#include "core/rid.h"
+
+class BulletPhysicsServer;
+
+class RIDBullet : public RID_Data {
+ RID self;
+ BulletPhysicsServer *physicsServer;
+
+public:
+ _FORCE_INLINE_ void set_self(const RID &p_self) { self = p_self; }
+ _FORCE_INLINE_ RID get_self() const { return self; }
+
+ _FORCE_INLINE_ void _set_physics_server(BulletPhysicsServer *p_physicsServer) { physicsServer = p_physicsServer; }
+ _FORCE_INLINE_ BulletPhysicsServer *get_physics_server() const { return physicsServer; }
+};
+#endif
diff --git a/modules/bullet/rigid_body_bullet.cpp b/modules/bullet/rigid_body_bullet.cpp
new file mode 100644
index 0000000000..98ae82bc5f
--- /dev/null
+++ b/modules/bullet/rigid_body_bullet.cpp
@@ -0,0 +1,999 @@
+/*************************************************************************/
+/* body_bullet.cpp */
+/* Author: AndreaCatania */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "rigid_body_bullet.h"
+#include "BulletCollision/CollisionDispatch/btGhostObject.h"
+#include "BulletCollision/CollisionShapes/btConvexPointCloudShape.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "btBulletCollisionCommon.h"
+#include "btRayShape.h"
+#include "bullet_physics_server.h"
+#include "bullet_types_converter.h"
+#include "bullet_utilities.h"
+#include "godot_motion_state.h"
+#include "joint_bullet.h"
+#include <assert.h>
+
+BulletPhysicsDirectBodyState *BulletPhysicsDirectBodyState::singleton = NULL;
+
+Vector3 BulletPhysicsDirectBodyState::get_total_gravity() const {
+ Vector3 gVec;
+ B_TO_G(body->btBody->getGravity(), gVec);
+ return gVec;
+}
+
+float BulletPhysicsDirectBodyState::get_total_angular_damp() const {
+ return body->btBody->getAngularDamping();
+}
+
+float BulletPhysicsDirectBodyState::get_total_linear_damp() const {
+ return body->btBody->getLinearDamping();
+}
+
+Vector3 BulletPhysicsDirectBodyState::get_center_of_mass() const {
+ Vector3 gVec;
+ B_TO_G(body->btBody->getCenterOfMassPosition(), gVec);
+ return gVec;
+}
+
+Basis BulletPhysicsDirectBodyState::get_principal_inertia_axes() const {
+ return Basis();
+}
+
+float BulletPhysicsDirectBodyState::get_inverse_mass() const {
+ return body->btBody->getInvMass();
+}
+
+Vector3 BulletPhysicsDirectBodyState::get_inverse_inertia() const {
+ Vector3 gVec;
+ B_TO_G(body->btBody->getInvInertiaDiagLocal(), gVec);
+ return gVec;
+}
+
+Basis BulletPhysicsDirectBodyState::get_inverse_inertia_tensor() const {
+ Basis gInertia;
+ B_TO_G(body->btBody->getInvInertiaTensorWorld(), gInertia);
+ return gInertia;
+}
+
+void BulletPhysicsDirectBodyState::set_linear_velocity(const Vector3 &p_velocity) {
+ body->set_linear_velocity(p_velocity);
+}
+
+Vector3 BulletPhysicsDirectBodyState::get_linear_velocity() const {
+ return body->get_linear_velocity();
+}
+
+void BulletPhysicsDirectBodyState::set_angular_velocity(const Vector3 &p_velocity) {
+ body->set_angular_velocity(p_velocity);
+}
+
+Vector3 BulletPhysicsDirectBodyState::get_angular_velocity() const {
+ return body->get_angular_velocity();
+}
+
+void BulletPhysicsDirectBodyState::set_transform(const Transform &p_transform) {
+ body->set_transform(p_transform);
+}
+
+Transform BulletPhysicsDirectBodyState::get_transform() const {
+ return body->get_transform();
+}
+
+void BulletPhysicsDirectBodyState::add_force(const Vector3 &p_force, const Vector3 &p_pos) {
+ body->apply_force(p_force, p_pos);
+}
+
+void BulletPhysicsDirectBodyState::apply_impulse(const Vector3 &p_pos, const Vector3 &p_j) {
+ body->apply_impulse(p_pos, p_j);
+}
+
+void BulletPhysicsDirectBodyState::apply_torque_impulse(const Vector3 &p_j) {
+ body->apply_torque_impulse(p_j);
+}
+
+void BulletPhysicsDirectBodyState::set_sleep_state(bool p_enable) {
+ body->set_activation_state(p_enable);
+}
+
+bool BulletPhysicsDirectBodyState::is_sleeping() const {
+ return !body->is_active();
+}
+
+int BulletPhysicsDirectBodyState::get_contact_count() const {
+ return body->collisionsCount;
+}
+
+Vector3 BulletPhysicsDirectBodyState::get_contact_local_position(int p_contact_idx) const {
+ return body->collisions[p_contact_idx].hitLocalLocation;
+}
+
+Vector3 BulletPhysicsDirectBodyState::get_contact_local_normal(int p_contact_idx) const {
+ return body->collisions[p_contact_idx].hitNormal;
+}
+
+int BulletPhysicsDirectBodyState::get_contact_local_shape(int p_contact_idx) const {
+ return body->collisions[p_contact_idx].local_shape;
+}
+
+RID BulletPhysicsDirectBodyState::get_contact_collider(int p_contact_idx) const {
+ return body->collisions[p_contact_idx].otherObject->get_self();
+}
+
+Vector3 BulletPhysicsDirectBodyState::get_contact_collider_position(int p_contact_idx) const {
+ return body->collisions[p_contact_idx].hitWorldLocation;
+}
+
+ObjectID BulletPhysicsDirectBodyState::get_contact_collider_id(int p_contact_idx) const {
+ return body->collisions[p_contact_idx].otherObject->get_instance_id();
+}
+
+int BulletPhysicsDirectBodyState::get_contact_collider_shape(int p_contact_idx) const {
+ return body->collisions[p_contact_idx].other_object_shape;
+}
+
+Vector3 BulletPhysicsDirectBodyState::get_contact_collider_velocity_at_position(int p_contact_idx) const {
+ RigidBodyBullet::CollisionData &colDat = body->collisions[p_contact_idx];
+
+ btVector3 hitLocation;
+ G_TO_B(colDat.hitLocalLocation, hitLocation);
+
+ Vector3 velocityAtPoint;
+ B_TO_G(colDat.otherObject->get_bt_rigid_body()->getVelocityInLocalPoint(hitLocation), velocityAtPoint);
+
+ return velocityAtPoint;
+}
+
+PhysicsDirectSpaceState *BulletPhysicsDirectBodyState::get_space_state() {
+ return body->get_space()->get_direct_state();
+}
+
+RigidBodyBullet::KinematicUtilities::KinematicUtilities(RigidBodyBullet *p_owner)
+ : owner(p_owner),
+ safe_margin(0.001) {
+}
+
+RigidBodyBullet::KinematicUtilities::~KinematicUtilities() {
+ just_delete_shapes(shapes.size()); // don't need to resize
+}
+
+void RigidBodyBullet::KinematicUtilities::setSafeMargin(btScalar p_margin) {
+ safe_margin = p_margin;
+ copyAllOwnerShapes();
+}
+
+void RigidBodyBullet::KinematicUtilities::copyAllOwnerShapes() {
+ const Vector<CollisionObjectBullet::ShapeWrapper> &shapes_wrappers(owner->get_shapes_wrappers());
+ const int shapes_count = shapes_wrappers.size();
+
+ just_delete_shapes(shapes_count);
+
+ const CollisionObjectBullet::ShapeWrapper *shape_wrapper;
+
+ for (int i = shapes_count - 1; 0 <= i; --i) {
+ shape_wrapper = &shapes_wrappers[i];
+ if (!shape_wrapper->active) {
+ continue;
+ }
+ shapes[i].transform = shape_wrapper->transform;
+
+ btConvexShape *&kin_shape_ref = shapes[i].shape;
+
+ switch (shape_wrapper->shape->get_type()) {
+ case PhysicsServer::SHAPE_SPHERE: {
+ SphereShapeBullet *sphere = static_cast<SphereShapeBullet *>(shape_wrapper->shape);
+ kin_shape_ref = ShapeBullet::create_shape_sphere(sphere->get_radius() * owner->body_scale[0] + safe_margin);
+ break;
+ }
+ case PhysicsServer::SHAPE_BOX: {
+ BoxShapeBullet *box = static_cast<BoxShapeBullet *>(shape_wrapper->shape);
+ kin_shape_ref = ShapeBullet::create_shape_box((box->get_half_extents() * owner->body_scale) + btVector3(safe_margin, safe_margin, safe_margin));
+ break;
+ }
+ case PhysicsServer::SHAPE_CAPSULE: {
+ CapsuleShapeBullet *capsule = static_cast<CapsuleShapeBullet *>(shape_wrapper->shape);
+ kin_shape_ref = ShapeBullet::create_shape_capsule(capsule->get_radius() * owner->body_scale[0] + safe_margin, capsule->get_height() * owner->body_scale[1] + safe_margin);
+ break;
+ }
+ case PhysicsServer::SHAPE_CONVEX_POLYGON: {
+ ConvexPolygonShapeBullet *godot_convex = static_cast<ConvexPolygonShapeBullet *>(shape_wrapper->shape);
+ kin_shape_ref = ShapeBullet::create_shape_convex(godot_convex->vertices);
+ kin_shape_ref->setLocalScaling(owner->body_scale + btVector3(safe_margin, safe_margin, safe_margin));
+ break;
+ }
+ case PhysicsServer::SHAPE_RAY: {
+ RayShapeBullet *godot_ray = static_cast<RayShapeBullet *>(shape_wrapper->shape);
+ kin_shape_ref = ShapeBullet::create_shape_ray(godot_ray->length * owner->body_scale[1] + safe_margin);
+ break;
+ }
+ default:
+ WARN_PRINT("This shape is not supported to be kinematic!");
+ kin_shape_ref = NULL;
+ }
+ }
+}
+
+void RigidBodyBullet::KinematicUtilities::just_delete_shapes(int new_size) {
+ for (int i = shapes.size() - 1; 0 <= i; --i) {
+ if (shapes[i].shape) {
+ bulletdelete(shapes[i].shape);
+ }
+ }
+ shapes.resize(new_size);
+}
+
+RigidBodyBullet::RigidBodyBullet()
+ : RigidCollisionObjectBullet(CollisionObjectBullet::TYPE_RIGID_BODY),
+ kinematic_utilities(NULL),
+ gravity_scale(1),
+ mass(1),
+ linearDamp(0),
+ angularDamp(0),
+ can_sleep(true),
+ force_integration_callback(NULL),
+ isTransformChanged(false),
+ maxCollisionsDetection(0),
+ collisionsCount(0),
+ maxAreasWhereIam(10),
+ areaWhereIamCount(0),
+ countGravityPointSpaces(0),
+ isScratchedSpaceOverrideModificator(false) {
+
+ godotMotionState = bulletnew(GodotMotionState(this));
+
+ // Initial properties
+ const btVector3 localInertia(0, 0, 0);
+ btRigidBody::btRigidBodyConstructionInfo cInfo(mass, godotMotionState, compoundShape, localInertia);
+
+ btBody = bulletnew(btRigidBody(cInfo));
+ setupBulletCollisionObject(btBody);
+
+ set_mode(PhysicsServer::BODY_MODE_RIGID);
+ set_axis_lock(PhysicsServer::BODY_AXIS_LOCK_DISABLED);
+
+ areasWhereIam.resize(maxAreasWhereIam);
+ for (int i = areasWhereIam.size() - 1; 0 <= i; --i) {
+ areasWhereIam[i] = NULL;
+ }
+}
+
+RigidBodyBullet::~RigidBodyBullet() {
+ bulletdelete(godotMotionState);
+
+ if (force_integration_callback)
+ memdelete(force_integration_callback);
+
+ destroy_kinematic_utilities();
+}
+
+void RigidBodyBullet::init_kinematic_utilities() {
+ kinematic_utilities = memnew(KinematicUtilities(this));
+}
+
+void RigidBodyBullet::destroy_kinematic_utilities() {
+ if (kinematic_utilities) {
+ memdelete(kinematic_utilities);
+ kinematic_utilities = NULL;
+ }
+}
+
+void RigidBodyBullet::reload_body() {
+ if (space) {
+ space->remove_rigid_body(this);
+ space->add_rigid_body(this);
+ }
+}
+
+void RigidBodyBullet::set_space(SpaceBullet *p_space) {
+ // Clear the old space if there is one
+ if (space) {
+ isTransformChanged = false;
+
+ // Remove all eventual constraints
+ assert_no_constraints();
+
+ // Remove this object form the physics world
+ space->remove_rigid_body(this);
+ }
+
+ space = p_space;
+
+ if (space) {
+ space->add_rigid_body(this);
+ }
+}
+
+void RigidBodyBullet::dispatch_callbacks() {
+ /// The check isTransformChanged is necessary in order to call integrated forces only when the first transform is sent
+ if (btBody->isActive() && force_integration_callback && isTransformChanged) {
+
+ BulletPhysicsDirectBodyState *bodyDirect = BulletPhysicsDirectBodyState::get_singleton(this);
+
+ Variant variantBodyDirect = bodyDirect;
+
+ Object *obj = ObjectDB::get_instance(force_integration_callback->id);
+ if (!obj) {
+ // Remove integration callback
+ set_force_integration_callback(0, StringName());
+ } else {
+ const Variant *vp[2] = { &variantBodyDirect, &force_integration_callback->udata };
+
+ Variant::CallError responseCallError;
+ int argc = (force_integration_callback->udata.get_type() == Variant::NIL) ? 1 : 2;
+ obj->call(force_integration_callback->method, vp, argc, responseCallError);
+ }
+ }
+
+ if (isScratchedSpaceOverrideModificator || 0 < countGravityPointSpaces) {
+ isScratchedSpaceOverrideModificator = false;
+ reload_space_override_modificator();
+ }
+
+ /// Lock axis
+ btBody->setLinearVelocity(btBody->getLinearVelocity() * btBody->getLinearFactor());
+ btBody->setAngularVelocity(btBody->getAngularVelocity() * btBody->getAngularFactor());
+}
+
+void RigidBodyBullet::set_force_integration_callback(ObjectID p_id, const StringName &p_method, const Variant &p_udata) {
+
+ if (force_integration_callback) {
+ memdelete(force_integration_callback);
+ force_integration_callback = NULL;
+ }
+
+ if (p_id != 0) {
+ force_integration_callback = memnew(ForceIntegrationCallback);
+ force_integration_callback->id = p_id;
+ force_integration_callback->method = p_method;
+ force_integration_callback->udata = p_udata;
+ }
+}
+
+void RigidBodyBullet::scratch() {
+ isTransformChanged = true;
+}
+
+void RigidBodyBullet::scratch_space_override_modificator() {
+ isScratchedSpaceOverrideModificator = true;
+}
+
+void RigidBodyBullet::on_collision_filters_change() {
+ if (space) {
+ space->reload_collision_filters(this);
+ }
+}
+
+void RigidBodyBullet::on_collision_checker_start() {
+ collisionsCount = 0;
+}
+
+bool RigidBodyBullet::add_collision_object(RigidBodyBullet *p_otherObject, const Vector3 &p_hitWorldLocation, const Vector3 &p_hitLocalLocation, const Vector3 &p_hitNormal, int p_other_shape_index, int p_local_shape_index) {
+
+ if (collisionsCount >= maxCollisionsDetection) {
+ return false;
+ }
+
+ CollisionData &cd = collisions[collisionsCount];
+ cd.hitLocalLocation = p_hitLocalLocation;
+ cd.otherObject = p_otherObject;
+ cd.hitWorldLocation = p_hitWorldLocation;
+ cd.hitNormal = p_hitNormal;
+ cd.other_object_shape = p_other_shape_index;
+ cd.local_shape = p_local_shape_index;
+
+ ++collisionsCount;
+ return true;
+}
+
+void RigidBodyBullet::assert_no_constraints() {
+ if (btBody->getNumConstraintRefs()) {
+ WARN_PRINT("A body with a joints is destroyed. Please check the implementation in order to destroy the joint before the body.");
+ }
+ /*for(int i = btBody->getNumConstraintRefs()-1; 0<=i; --i){
+ btTypedConstraint* btConst = btBody->getConstraintRef(i);
+ JointBullet* joint = static_cast<JointBullet*>( btConst->getUserConstraintPtr() );
+ space->removeConstraint(joint);
+ }*/
+}
+
+void RigidBodyBullet::set_activation_state(bool p_active) {
+ if (p_active) {
+ btBody->setActivationState(ACTIVE_TAG);
+ } else {
+ btBody->setActivationState(WANTS_DEACTIVATION);
+ }
+}
+
+bool RigidBodyBullet::is_active() const {
+ return btBody->isActive();
+}
+
+void RigidBodyBullet::set_param(PhysicsServer::BodyParameter p_param, real_t p_value) {
+ switch (p_param) {
+ case PhysicsServer::BODY_PARAM_BOUNCE:
+ btBody->setRestitution(p_value);
+ break;
+ case PhysicsServer::BODY_PARAM_FRICTION:
+ btBody->setFriction(p_value);
+ break;
+ case PhysicsServer::BODY_PARAM_MASS: {
+ ERR_FAIL_COND(p_value < 0);
+ mass = p_value;
+ _internal_set_mass(p_value);
+ break;
+ }
+ case PhysicsServer::BODY_PARAM_LINEAR_DAMP:
+ linearDamp = p_value;
+ btBody->setDamping(linearDamp, angularDamp);
+ break;
+ case PhysicsServer::BODY_PARAM_ANGULAR_DAMP:
+ angularDamp = p_value;
+ btBody->setDamping(linearDamp, angularDamp);
+ break;
+ case PhysicsServer::BODY_PARAM_GRAVITY_SCALE:
+ gravity_scale = p_value;
+ /// The Bullet gravity will be is set by reload_space_override_modificator
+ scratch_space_override_modificator();
+ break;
+ default:
+ WARN_PRINTS("Parameter " + itos(p_param) + " not supported by bullet. Value: " + itos(p_value));
+ }
+}
+
+real_t RigidBodyBullet::get_param(PhysicsServer::BodyParameter p_param) const {
+ switch (p_param) {
+ case PhysicsServer::BODY_PARAM_BOUNCE:
+ return btBody->getRestitution();
+ case PhysicsServer::BODY_PARAM_FRICTION:
+ return btBody->getFriction();
+ case PhysicsServer::BODY_PARAM_MASS: {
+ const btScalar invMass = btBody->getInvMass();
+ return 0 == invMass ? 0 : 1 / invMass;
+ }
+ case PhysicsServer::BODY_PARAM_LINEAR_DAMP:
+ return linearDamp;
+ case PhysicsServer::BODY_PARAM_ANGULAR_DAMP:
+ return angularDamp;
+ case PhysicsServer::BODY_PARAM_GRAVITY_SCALE:
+ return gravity_scale;
+ default:
+ WARN_PRINTS("Parameter " + itos(p_param) + " not supported by bullet");
+ return 0;
+ }
+}
+
+void RigidBodyBullet::set_mode(PhysicsServer::BodyMode p_mode) {
+ // This is necessary to block force_integration untile next move
+ isTransformChanged = false;
+ destroy_kinematic_utilities();
+ // The mode change is relevant to its mass
+ switch (p_mode) {
+ case PhysicsServer::BODY_MODE_KINEMATIC:
+ mode = PhysicsServer::BODY_MODE_KINEMATIC;
+ set_axis_lock(axis_lock); // Reload axis lock
+ _internal_set_mass(0);
+ init_kinematic_utilities();
+ break;
+ case PhysicsServer::BODY_MODE_STATIC:
+ mode = PhysicsServer::BODY_MODE_STATIC;
+ set_axis_lock(axis_lock); // Reload axis lock
+ _internal_set_mass(0);
+ break;
+ case PhysicsServer::BODY_MODE_RIGID: {
+ mode = PhysicsServer::BODY_MODE_RIGID;
+ set_axis_lock(axis_lock); // Reload axis lock
+ _internal_set_mass(0 == mass ? 1 : mass);
+ break;
+ }
+ case PhysicsServer::BODY_MODE_CHARACTER: {
+ mode = PhysicsServer::BODY_MODE_CHARACTER;
+ set_axis_lock(axis_lock); // Reload axis lock
+ _internal_set_mass(0 == mass ? 1 : mass);
+ break;
+ }
+ }
+
+ btBody->setAngularVelocity(btVector3(0, 0, 0));
+ btBody->setLinearVelocity(btVector3(0, 0, 0));
+}
+PhysicsServer::BodyMode RigidBodyBullet::get_mode() const {
+ return mode;
+}
+
+void RigidBodyBullet::set_state(PhysicsServer::BodyState p_state, const Variant &p_variant) {
+
+ switch (p_state) {
+ case PhysicsServer::BODY_STATE_TRANSFORM:
+ set_transform(p_variant);
+ break;
+ case PhysicsServer::BODY_STATE_LINEAR_VELOCITY:
+ set_linear_velocity(p_variant);
+ break;
+ case PhysicsServer::BODY_STATE_ANGULAR_VELOCITY:
+ set_angular_velocity(p_variant);
+ break;
+ case PhysicsServer::BODY_STATE_SLEEPING:
+ set_activation_state(!bool(p_variant));
+ break;
+ case PhysicsServer::BODY_STATE_CAN_SLEEP:
+ can_sleep = bool(p_variant);
+ if (!can_sleep) {
+ // Can't sleep
+ btBody->forceActivationState(DISABLE_DEACTIVATION);
+ }
+ break;
+ }
+}
+
+Variant RigidBodyBullet::get_state(PhysicsServer::BodyState p_state) const {
+ switch (p_state) {
+ case PhysicsServer::BODY_STATE_TRANSFORM:
+ return get_transform();
+ case PhysicsServer::BODY_STATE_LINEAR_VELOCITY:
+ return get_linear_velocity();
+ case PhysicsServer::BODY_STATE_ANGULAR_VELOCITY:
+ return get_angular_velocity();
+ case PhysicsServer::BODY_STATE_SLEEPING:
+ return !is_active();
+ case PhysicsServer::BODY_STATE_CAN_SLEEP:
+ return can_sleep;
+ default:
+ WARN_PRINTS("This state " + itos(p_state) + " is not supported by Bullet");
+ return Variant();
+ }
+}
+
+void RigidBodyBullet::apply_central_impulse(const Vector3 &p_impulse) {
+ btVector3 btImpu;
+ G_TO_B(p_impulse, btImpu);
+ btBody->activate();
+ btBody->applyCentralImpulse(btImpu);
+}
+
+void RigidBodyBullet::apply_impulse(const Vector3 &p_pos, const Vector3 &p_impulse) {
+ btVector3 btImpu;
+ btVector3 btPos;
+ G_TO_B(p_impulse, btImpu);
+ G_TO_B(p_pos, btPos);
+ btBody->activate();
+ btBody->applyImpulse(btImpu, btPos);
+}
+
+void RigidBodyBullet::apply_torque_impulse(const Vector3 &p_impulse) {
+ btVector3 btImp;
+ G_TO_B(p_impulse, btImp);
+ btBody->activate();
+ btBody->applyTorqueImpulse(btImp);
+}
+
+void RigidBodyBullet::apply_force(const Vector3 &p_force, const Vector3 &p_pos) {
+ btVector3 btForce;
+ btVector3 btPos;
+ G_TO_B(p_force, btForce);
+ G_TO_B(p_pos, btPos);
+ btBody->activate();
+ btBody->applyForce(btForce, btPos);
+}
+
+void RigidBodyBullet::apply_central_force(const Vector3 &p_force) {
+ btVector3 btForce;
+ G_TO_B(p_force, btForce);
+ btBody->activate();
+ btBody->applyCentralForce(btForce);
+}
+
+void RigidBodyBullet::apply_torque(const Vector3 &p_torque) {
+ btVector3 btTorq;
+ G_TO_B(p_torque, btTorq);
+ btBody->activate();
+ btBody->applyTorque(btTorq);
+}
+
+void RigidBodyBullet::set_applied_force(const Vector3 &p_force) {
+ btVector3 btVec = btBody->getTotalTorque();
+
+ btBody->activate();
+
+ btBody->clearForces();
+ btBody->applyTorque(btVec);
+
+ G_TO_B(p_force, btVec);
+ btBody->applyCentralForce(btVec);
+}
+
+Vector3 RigidBodyBullet::get_applied_force() const {
+ Vector3 gTotForc;
+ B_TO_G(btBody->getTotalForce(), gTotForc);
+ return gTotForc;
+}
+
+void RigidBodyBullet::set_applied_torque(const Vector3 &p_torque) {
+ btVector3 btVec = btBody->getTotalForce();
+
+ btBody->activate();
+
+ btBody->clearForces();
+ btBody->applyCentralForce(btVec);
+
+ G_TO_B(p_torque, btVec);
+ btBody->applyTorque(btVec);
+}
+
+Vector3 RigidBodyBullet::get_applied_torque() const {
+ Vector3 gTotTorq;
+ B_TO_G(btBody->getTotalTorque(), gTotTorq);
+ return gTotTorq;
+}
+
+void RigidBodyBullet::set_axis_lock(PhysicsServer::BodyAxisLock p_lock) {
+ axis_lock = p_lock;
+
+ if (PhysicsServer::BODY_AXIS_LOCK_DISABLED == axis_lock) {
+ btBody->setLinearFactor(btVector3(1., 1., 1.));
+ btBody->setAngularFactor(btVector3(1., 1., 1.));
+ } else if (PhysicsServer::BODY_AXIS_LOCK_X == axis_lock) {
+ btBody->setLinearFactor(btVector3(0., 1., 1.));
+ btBody->setAngularFactor(btVector3(1., 0., 0.));
+ } else if (PhysicsServer::BODY_AXIS_LOCK_Y == axis_lock) {
+ btBody->setLinearFactor(btVector3(1., 0., 1.));
+ btBody->setAngularFactor(btVector3(0., 1., 0.));
+ } else if (PhysicsServer::BODY_AXIS_LOCK_Z == axis_lock) {
+ btBody->setLinearFactor(btVector3(1., 1., 0.));
+ btBody->setAngularFactor(btVector3(0., 0., 1.));
+ }
+
+ if (PhysicsServer::BODY_MODE_CHARACTER == mode) {
+ /// When character lock angular
+ btBody->setAngularFactor(btVector3(0., 0., 0.));
+ }
+}
+
+PhysicsServer::BodyAxisLock RigidBodyBullet::get_axis_lock() const {
+ btVector3 vec = btBody->getLinearFactor();
+ if (0. == vec.x()) {
+ return PhysicsServer::BODY_AXIS_LOCK_X;
+ } else if (0. == vec.y()) {
+ return PhysicsServer::BODY_AXIS_LOCK_Y;
+ } else if (0. == vec.z()) {
+ return PhysicsServer::BODY_AXIS_LOCK_Z;
+ } else {
+ return PhysicsServer::BODY_AXIS_LOCK_DISABLED;
+ }
+}
+
+void RigidBodyBullet::set_continuous_collision_detection(bool p_enable) {
+ if (p_enable) {
+ // This threshold enable CCD if the object moves more than
+ // 1 meter in one simulation frame
+ btBody->setCcdMotionThreshold(1);
+
+ /// Calculate using the rule writte below the CCD swept sphere radius
+ /// CCD works on an embedded sphere of radius, make sure this radius
+ /// is embedded inside the convex objects, preferably smaller:
+ /// for an object of dimentions 1 meter, try 0.2
+ btVector3 center;
+ btScalar radius;
+ btBody->getCollisionShape()->getBoundingSphere(center, radius);
+ btBody->setCcdSweptSphereRadius(radius * 0.2);
+ } else {
+ btBody->setCcdMotionThreshold(0.);
+ btBody->setCcdSweptSphereRadius(0.);
+ }
+}
+
+bool RigidBodyBullet::is_continuous_collision_detection_enabled() const {
+ return 0. != btBody->getCcdMotionThreshold();
+}
+
+void RigidBodyBullet::set_linear_velocity(const Vector3 &p_velocity) {
+ btVector3 btVec;
+ G_TO_B(p_velocity, btVec);
+ btBody->activate();
+ btBody->setLinearVelocity(btVec);
+}
+
+Vector3 RigidBodyBullet::get_linear_velocity() const {
+ Vector3 gVec;
+ B_TO_G(btBody->getLinearVelocity(), gVec);
+ return gVec;
+}
+
+void RigidBodyBullet::set_angular_velocity(const Vector3 &p_velocity) {
+ btVector3 btVec;
+ G_TO_B(p_velocity, btVec);
+ btBody->activate();
+ btBody->setAngularVelocity(btVec);
+}
+
+Vector3 RigidBodyBullet::get_angular_velocity() const {
+ Vector3 gVec;
+ B_TO_G(btBody->getAngularVelocity(), gVec);
+ return gVec;
+}
+
+void RigidBodyBullet::set_transform__bullet(const btTransform &p_global_transform) {
+ if (mode == PhysicsServer::BODY_MODE_KINEMATIC) {
+ // The kinematic use MotionState class
+ godotMotionState->moveBody(p_global_transform);
+ }
+ btBody->setWorldTransform(p_global_transform);
+}
+
+const btTransform &RigidBodyBullet::get_transform__bullet() const {
+ if (is_static()) {
+
+ return RigidCollisionObjectBullet::get_transform__bullet();
+ } else {
+
+ return godotMotionState->getCurrentWorldTransform();
+ }
+}
+
+void RigidBodyBullet::on_shapes_changed() {
+ RigidCollisionObjectBullet::on_shapes_changed();
+
+ const btScalar invMass = btBody->getInvMass();
+ const btScalar mass = invMass == 0 ? 0 : 1 / invMass;
+
+ btVector3 inertia;
+ btBody->getCollisionShape()->calculateLocalInertia(mass, inertia);
+ btBody->setMassProps(mass, inertia);
+ btBody->updateInertiaTensor();
+
+ reload_kinematic_shapes();
+
+ reload_body();
+}
+
+void RigidBodyBullet::on_enter_area(AreaBullet *p_area) {
+ /// Add this area to the array in an ordered way
+ ++areaWhereIamCount;
+ if (areaWhereIamCount >= maxAreasWhereIam) {
+ --areaWhereIamCount;
+ return;
+ }
+ for (int i = 0; i < areaWhereIamCount; ++i) {
+
+ if (NULL == areasWhereIam[i]) {
+ // This area has the highest priority
+ areasWhereIam[i] = p_area;
+ break;
+ } else {
+ if (areasWhereIam[i]->get_spOv_priority() > p_area->get_spOv_priority()) {
+ // The position was found, just shift all elements
+ for (int j = i; j < areaWhereIamCount; ++j) {
+ areasWhereIam[j + 1] = areasWhereIam[j];
+ }
+ areasWhereIam[i] = p_area;
+ break;
+ }
+ }
+ }
+ if (PhysicsServer::AREA_SPACE_OVERRIDE_DISABLED != p_area->get_spOv_mode()) {
+ scratch_space_override_modificator();
+ }
+
+ if (p_area->is_spOv_gravityPoint()) {
+ ++countGravityPointSpaces;
+ assert(0 < countGravityPointSpaces);
+ }
+}
+
+void RigidBodyBullet::on_exit_area(AreaBullet *p_area) {
+ RigidCollisionObjectBullet::on_exit_area(p_area);
+ /// Remove this area and keep the order
+ /// N.B. Since I don't want resize the array I can't use the "erase" function
+ bool wasTheAreaFound = false;
+ for (int i = 0; i < areaWhereIamCount; ++i) {
+ if (p_area == areasWhereIam[i]) {
+ // The area was fount, just shift down all elements
+ for (int j = i; j < areaWhereIamCount; ++j) {
+ areasWhereIam[j] = areasWhereIam[j + 1];
+ }
+ wasTheAreaFound = true;
+ break;
+ }
+ }
+ if (wasTheAreaFound) {
+ if (p_area->is_spOv_gravityPoint()) {
+ --countGravityPointSpaces;
+ assert(0 <= countGravityPointSpaces);
+ }
+
+ --areaWhereIamCount;
+ areasWhereIam[areaWhereIamCount] = NULL; // Even if this is not required, I clear the last element to be safe
+ if (PhysicsServer::AREA_SPACE_OVERRIDE_DISABLED != p_area->get_spOv_mode()) {
+ scratch_space_override_modificator();
+ }
+ }
+}
+
+void RigidBodyBullet::reload_space_override_modificator() {
+
+ Vector3 newGravity(space->get_gravity_direction() * space->get_gravity_magnitude());
+ real_t newLinearDamp(linearDamp);
+ real_t newAngularDamp(angularDamp);
+
+ AreaBullet *currentArea;
+ // Variable used to calculate new gravity for gravity point areas, it is pointed by currentGravity pointer
+ Vector3 support_gravity(0, 0, 0);
+
+ int countCombined(0);
+ for (int i = areaWhereIamCount - 1; 0 <= i; --i) {
+
+ currentArea = areasWhereIam[i];
+
+ if (PhysicsServer::AREA_SPACE_OVERRIDE_DISABLED == currentArea->get_spOv_mode()) {
+ continue;
+ }
+
+ /// Here is calculated the gravity
+ if (currentArea->is_spOv_gravityPoint()) {
+
+ /// It calculates the direction of new gravity
+ support_gravity = currentArea->get_transform().xform(currentArea->get_spOv_gravityVec()) - get_transform().get_origin();
+ real_t distanceMag = support_gravity.length();
+ // Normalized in this way to avoid the double call of function "length()"
+ if (distanceMag == 0) {
+ support_gravity.x = 0;
+ support_gravity.y = 0;
+ support_gravity.z = 0;
+ } else {
+ support_gravity.x /= distanceMag;
+ support_gravity.y /= distanceMag;
+ support_gravity.z /= distanceMag;
+ }
+
+ /// Here is calculated the final gravity
+ if (currentArea->get_spOv_gravityPointDistanceScale() > 0) {
+ // Scaled gravity by distance
+ support_gravity *= currentArea->get_spOv_gravityMag() / Math::pow(distanceMag * currentArea->get_spOv_gravityPointDistanceScale() + 1, 2);
+ } else {
+ // Unscaled gravity
+ support_gravity *= currentArea->get_spOv_gravityMag();
+ }
+ } else {
+ support_gravity = currentArea->get_spOv_gravityVec() * currentArea->get_spOv_gravityMag();
+ }
+
+ switch (currentArea->get_spOv_mode()) {
+ ///case PhysicsServer::AREA_SPACE_OVERRIDE_DISABLED:
+ /// This area does not affect gravity/damp. These are generally areas
+ /// that exist only to detect collisions, and objects entering or exiting them.
+ /// break;
+ case PhysicsServer::AREA_SPACE_OVERRIDE_COMBINE:
+ /// This area adds its gravity/damp values to whatever has been
+ /// calculated so far. This way, many overlapping areas can combine
+ /// their physics to make interesting
+ newGravity += support_gravity;
+ newLinearDamp += currentArea->get_spOv_linearDamp();
+ newAngularDamp += currentArea->get_spOv_angularDamp();
+ ++countCombined;
+ break;
+ case PhysicsServer::AREA_SPACE_OVERRIDE_COMBINE_REPLACE:
+ /// This area adds its gravity/damp values to whatever has been calculated
+ /// so far. Then stops taking into account the rest of the areas, even the
+ /// default one.
+ newGravity += support_gravity;
+ newLinearDamp += currentArea->get_spOv_linearDamp();
+ newAngularDamp += currentArea->get_spOv_angularDamp();
+ ++countCombined;
+ goto endAreasCycle;
+ case PhysicsServer::AREA_SPACE_OVERRIDE_REPLACE:
+ /// This area replaces any gravity/damp, even the default one, and
+ /// stops taking into account the rest of the areas.
+ newGravity = support_gravity;
+ newLinearDamp = currentArea->get_spOv_linearDamp();
+ newAngularDamp = currentArea->get_spOv_angularDamp();
+ countCombined = 1;
+ goto endAreasCycle;
+ case PhysicsServer::AREA_SPACE_OVERRIDE_REPLACE_COMBINE:
+ /// This area replaces any gravity/damp calculated so far, but keeps
+ /// calculating the rest of the areas, down to the default one.
+ newGravity = support_gravity;
+ newLinearDamp = currentArea->get_spOv_linearDamp();
+ newAngularDamp = currentArea->get_spOv_angularDamp();
+ countCombined = 1;
+ break;
+ }
+ }
+endAreasCycle:
+
+ if (1 < countCombined) {
+ newGravity /= countCombined;
+ newLinearDamp /= countCombined;
+ newAngularDamp /= countCombined;
+ }
+
+ btVector3 newBtGravity;
+ G_TO_B(newGravity * gravity_scale, newBtGravity);
+
+ btBody->setGravity(newBtGravity);
+ btBody->setDamping(newLinearDamp, newAngularDamp);
+}
+
+void RigidBodyBullet::reload_kinematic_shapes() {
+ if (!kinematic_utilities) {
+ return;
+ }
+ kinematic_utilities->copyAllOwnerShapes();
+}
+
+void RigidBodyBullet::_internal_set_mass(real_t p_mass) {
+
+ btVector3 localInertia(0, 0, 0);
+
+ int clearedCurrentFlags = btBody->getCollisionFlags();
+ clearedCurrentFlags &= ~(btCollisionObject::CF_KINEMATIC_OBJECT | btCollisionObject::CF_STATIC_OBJECT | btCollisionObject::CF_CHARACTER_OBJECT);
+
+ // Rigidbody is dynamic if and only if mass is non Zero, otherwise static
+ const bool isDynamic = p_mass != 0.f;
+ if (isDynamic) {
+
+ ERR_FAIL_COND(PhysicsServer::BODY_MODE_RIGID != mode && PhysicsServer::BODY_MODE_CHARACTER != mode);
+
+ m_isStatic = false;
+ compoundShape->calculateLocalInertia(p_mass, localInertia);
+
+ if (PhysicsServer::BODY_MODE_RIGID == mode) {
+
+ btBody->setCollisionFlags(clearedCurrentFlags); // Just set the flags without Kin and Static
+ } else {
+
+ btBody->setCollisionFlags(clearedCurrentFlags | btCollisionObject::CF_CHARACTER_OBJECT);
+ }
+
+ if (can_sleep) {
+ btBody->forceActivationState(ACTIVE_TAG); // ACTIVE_TAG 1
+ } else {
+ btBody->forceActivationState(DISABLE_DEACTIVATION); // DISABLE_DEACTIVATION 4
+ }
+ } else {
+
+ ERR_FAIL_COND(PhysicsServer::BODY_MODE_STATIC != mode && PhysicsServer::BODY_MODE_KINEMATIC != mode);
+
+ m_isStatic = true;
+ if (PhysicsServer::BODY_MODE_STATIC == mode) {
+
+ btBody->setCollisionFlags(clearedCurrentFlags | btCollisionObject::CF_STATIC_OBJECT);
+ } else {
+
+ btBody->setCollisionFlags(clearedCurrentFlags | btCollisionObject::CF_KINEMATIC_OBJECT);
+ set_transform__bullet(btBody->getWorldTransform()); // Set current Transform using kinematic method
+ }
+ btBody->forceActivationState(DISABLE_SIMULATION); // DISABLE_SIMULATION 5
+ }
+
+ btBody->setMassProps(p_mass, localInertia);
+ btBody->updateInertiaTensor();
+
+ reload_body();
+}
diff --git a/modules/bullet/rigid_body_bullet.h b/modules/bullet/rigid_body_bullet.h
new file mode 100644
index 0000000000..ab3c3e58b2
--- /dev/null
+++ b/modules/bullet/rigid_body_bullet.h
@@ -0,0 +1,302 @@
+/*************************************************************************/
+/* body_bullet.h */
+/* Author: AndreaCatania */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef BODYBULLET_H
+#define BODYBULLET_H
+
+#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
+#include "LinearMath/btTransform.h"
+#include "collision_object_bullet.h"
+#include "space_bullet.h"
+
+class AreaBullet;
+class SpaceBullet;
+class btRigidBody;
+class GodotMotionState;
+class BulletPhysicsDirectBodyState;
+
+/// This class could be used in multi thread with few changes but currently
+/// is setted to be only in one single thread.
+///
+/// In the system there is only one object at a time that manage all bodies and is
+/// created by BulletPhysicsServer and is held by the "singleton" variable of this class
+/// Each time something require it, the body must be setted again.
+class BulletPhysicsDirectBodyState : public PhysicsDirectBodyState {
+ GDCLASS(BulletPhysicsDirectBodyState, PhysicsDirectBodyState)
+
+ static BulletPhysicsDirectBodyState *singleton;
+
+public:
+ /// This class avoid the creation of more object of this class
+ static void initSingleton() {
+ if (!singleton) {
+ singleton = memnew(BulletPhysicsDirectBodyState);
+ }
+ }
+
+ static void destroySingleton() {
+ memdelete(singleton);
+ singleton = NULL;
+ }
+
+ static void singleton_setDeltaTime(real_t p_deltaTime) {
+ singleton->deltaTime = p_deltaTime;
+ }
+
+ static BulletPhysicsDirectBodyState *get_singleton(RigidBodyBullet *p_body) {
+ singleton->body = p_body;
+ return singleton;
+ }
+
+public:
+ RigidBodyBullet *body;
+ real_t deltaTime;
+
+private:
+ BulletPhysicsDirectBodyState() {}
+
+public:
+ virtual Vector3 get_total_gravity() const;
+ virtual float get_total_angular_damp() const;
+ virtual float get_total_linear_damp() const;
+
+ virtual Vector3 get_center_of_mass() const;
+ virtual Basis get_principal_inertia_axes() const;
+ // get the mass
+ virtual float get_inverse_mass() const;
+ // get density of this body space
+ virtual Vector3 get_inverse_inertia() const;
+ // get density of this body space
+ virtual Basis get_inverse_inertia_tensor() const;
+
+ virtual void set_linear_velocity(const Vector3 &p_velocity);
+ virtual Vector3 get_linear_velocity() const;
+
+ virtual void set_angular_velocity(const Vector3 &p_velocity);
+ virtual Vector3 get_angular_velocity() const;
+
+ virtual void set_transform(const Transform &p_transform);
+ virtual Transform get_transform() const;
+
+ virtual void add_force(const Vector3 &p_force, const Vector3 &p_pos);
+ virtual void apply_impulse(const Vector3 &p_pos, const Vector3 &p_j);
+ virtual void apply_torque_impulse(const Vector3 &p_j);
+
+ virtual void set_sleep_state(bool p_enable);
+ virtual bool is_sleeping() const;
+
+ virtual int get_contact_count() const;
+
+ virtual Vector3 get_contact_local_position(int p_contact_idx) const;
+ virtual Vector3 get_contact_local_normal(int p_contact_idx) const;
+ virtual int get_contact_local_shape(int p_contact_idx) const;
+
+ virtual RID get_contact_collider(int p_contact_idx) const;
+ virtual Vector3 get_contact_collider_position(int p_contact_idx) const;
+ virtual ObjectID get_contact_collider_id(int p_contact_idx) const;
+ virtual int get_contact_collider_shape(int p_contact_idx) const;
+ virtual Vector3 get_contact_collider_velocity_at_position(int p_contact_idx) const;
+
+ virtual real_t get_step() const { return deltaTime; }
+ virtual void integrate_forces() {
+ // Skip the execution of this function
+ }
+
+ virtual PhysicsDirectSpaceState *get_space_state();
+};
+
+class RigidBodyBullet : public RigidCollisionObjectBullet {
+
+public:
+ struct CollisionData {
+ RigidBodyBullet *otherObject;
+ int other_object_shape;
+ int local_shape;
+ Vector3 hitLocalLocation;
+ Vector3 hitWorldLocation;
+ Vector3 hitNormal;
+ };
+
+ struct ForceIntegrationCallback {
+ ObjectID id;
+ StringName method;
+ Variant udata;
+ };
+
+ /// Used to hold shapes
+ struct KinematicShape {
+ class btConvexShape *shape;
+ btTransform transform;
+
+ KinematicShape()
+ : shape(NULL) {}
+ const bool is_active() const { return shape; }
+ };
+
+ struct KinematicUtilities {
+ RigidBodyBullet *owner;
+ btScalar safe_margin;
+ Vector<KinematicShape> shapes;
+
+ KinematicUtilities(RigidBodyBullet *p_owner);
+ ~KinematicUtilities();
+
+ void setSafeMargin(btScalar p_margin);
+ /// Used to set the default shape to ghost
+ void copyAllOwnerShapes();
+
+ private:
+ void just_delete_shapes(int new_size);
+ };
+
+private:
+ friend class BulletPhysicsDirectBodyState;
+
+ // This is required only for Kinematic movement
+ KinematicUtilities *kinematic_utilities;
+
+ PhysicsServer::BodyMode mode;
+ PhysicsServer::BodyAxisLock axis_lock;
+ GodotMotionState *godotMotionState;
+ btRigidBody *btBody;
+ real_t mass;
+ real_t gravity_scale;
+ real_t linearDamp;
+ real_t angularDamp;
+ bool can_sleep;
+
+ Vector<CollisionData> collisions;
+ // these parameters are used to avoid vector resize
+ int maxCollisionsDetection;
+ int collisionsCount;
+
+ Vector<AreaBullet *> areasWhereIam;
+ // these parameters are used to avoid vector resize
+ int maxAreasWhereIam;
+ int areaWhereIamCount;
+ // Used to know if the area is used as gravity point
+ int countGravityPointSpaces;
+ bool isScratchedSpaceOverrideModificator;
+
+ bool isTransformChanged;
+
+ ForceIntegrationCallback *force_integration_callback;
+
+public:
+ RigidBodyBullet();
+ ~RigidBodyBullet();
+
+ void init_kinematic_utilities();
+ void destroy_kinematic_utilities();
+ _FORCE_INLINE_ class KinematicUtilities *get_kinematic_utilities() const { return kinematic_utilities; }
+
+ _FORCE_INLINE_ btRigidBody *get_bt_rigid_body() { return btBody; }
+
+ virtual void reload_body();
+ virtual void set_space(SpaceBullet *p_space);
+
+ virtual void dispatch_callbacks();
+ void set_force_integration_callback(ObjectID p_id, const StringName &p_method, const Variant &p_udata = Variant());
+ void scratch();
+ void scratch_space_override_modificator();
+
+ virtual void on_collision_filters_change();
+ virtual void on_collision_checker_start();
+ void set_max_collisions_detection(int p_maxCollisionsDetection) {
+ maxCollisionsDetection = p_maxCollisionsDetection;
+ collisions.resize(p_maxCollisionsDetection);
+ collisionsCount = 0;
+ }
+ int get_max_collisions_detection() {
+ return maxCollisionsDetection;
+ }
+
+ bool can_add_collision() { return collisionsCount < maxCollisionsDetection; }
+ bool add_collision_object(RigidBodyBullet *p_otherObject, const Vector3 &p_hitWorldLocation, const Vector3 &p_hitLocalLocation, const Vector3 &p_hitNormal, int p_other_shape_index, int p_local_shape_index);
+
+ void assert_no_constraints();
+
+ void set_activation_state(bool p_active);
+ bool is_active() const;
+
+ void set_param(PhysicsServer::BodyParameter p_param, real_t);
+ real_t get_param(PhysicsServer::BodyParameter p_param) const;
+
+ void set_mode(PhysicsServer::BodyMode p_mode);
+ PhysicsServer::BodyMode get_mode() const;
+
+ void set_state(PhysicsServer::BodyState p_state, const Variant &p_variant);
+ Variant get_state(PhysicsServer::BodyState p_state) const;
+
+ void apply_impulse(const Vector3 &p_pos, const Vector3 &p_impulse);
+ void apply_central_impulse(const Vector3 &p_force);
+ void apply_torque_impulse(const Vector3 &p_impulse);
+
+ void apply_force(const Vector3 &p_force, const Vector3 &p_pos);
+ void apply_central_force(const Vector3 &p_force);
+ void apply_torque(const Vector3 &p_force);
+
+ void set_applied_force(const Vector3 &p_force);
+ Vector3 get_applied_force() const;
+ void set_applied_torque(const Vector3 &p_torque);
+ Vector3 get_applied_torque() const;
+
+ void set_axis_lock(PhysicsServer::BodyAxisLock p_lock);
+ PhysicsServer::BodyAxisLock get_axis_lock() const;
+
+ /// Doc:
+ /// http://www.bulletphysics.org/mediawiki-1.5.8/index.php?title=Anti_tunneling_by_Motion_Clamping
+ void set_continuous_collision_detection(bool p_enable);
+ bool is_continuous_collision_detection_enabled() const;
+
+ void set_linear_velocity(const Vector3 &p_velocity);
+ Vector3 get_linear_velocity() const;
+
+ void set_angular_velocity(const Vector3 &p_velocity);
+ Vector3 get_angular_velocity() const;
+
+ virtual void set_transform__bullet(const btTransform &p_global_transform);
+ virtual const btTransform &get_transform__bullet() const;
+
+ virtual void on_shapes_changed();
+
+ virtual void on_enter_area(AreaBullet *p_area);
+ virtual void on_exit_area(AreaBullet *p_area);
+ void reload_space_override_modificator();
+
+ /// Kinematic
+ void reload_kinematic_shapes();
+
+private:
+ void _internal_set_mass(real_t p_mass);
+};
+
+#endif
diff --git a/modules/bullet/shape_bullet.cpp b/modules/bullet/shape_bullet.cpp
new file mode 100644
index 0000000000..49150484d9
--- /dev/null
+++ b/modules/bullet/shape_bullet.cpp
@@ -0,0 +1,435 @@
+/*************************************************************************/
+/* shape_bullet.cpp */
+/* Author: AndreaCatania */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "shape_bullet.h"
+#include "BulletCollision/CollisionShapes/btConvexPointCloudShape.h"
+#include "BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h"
+#include "btBulletCollisionCommon.h"
+#include "btRayShape.h"
+#include "bullet_physics_server.h"
+#include "bullet_types_converter.h"
+#include "bullet_utilities.h"
+#include "shape_owner_bullet.h"
+
+ShapeBullet::ShapeBullet() {}
+
+ShapeBullet::~ShapeBullet() {}
+
+btCollisionShape *ShapeBullet::prepare(btCollisionShape *p_btShape) const {
+ p_btShape->setUserPointer(const_cast<ShapeBullet *>(this));
+ return p_btShape;
+}
+
+void ShapeBullet::notifyShapeChanged() {
+ for (Map<ShapeOwnerBullet *, int>::Element *E = owners.front(); E; E = E->next()) {
+ static_cast<ShapeOwnerBullet *>(E->key())->on_shape_changed(this);
+ }
+}
+
+void ShapeBullet::add_owner(ShapeOwnerBullet *p_owner) {
+ Map<ShapeOwnerBullet *, int>::Element *E = owners.find(p_owner);
+ if (E) {
+ E->get()++;
+ } else {
+ owners[p_owner] = 1; // add new owner
+ }
+}
+
+void ShapeBullet::remove_owner(ShapeOwnerBullet *p_owner, bool p_permanentlyFromThisBody) {
+ Map<ShapeOwnerBullet *, int>::Element *E = owners.find(p_owner);
+ ERR_FAIL_COND(!E);
+ E->get()--;
+ if (p_permanentlyFromThisBody || 0 >= E->get()) {
+ owners.erase(E);
+ }
+}
+
+bool ShapeBullet::is_owner(ShapeOwnerBullet *p_owner) const {
+
+ return owners.has(p_owner);
+}
+
+const Map<ShapeOwnerBullet *, int> &ShapeBullet::get_owners() const {
+ return owners;
+}
+
+btEmptyShape *ShapeBullet::create_shape_empty() {
+ return bulletnew(btEmptyShape);
+}
+
+btStaticPlaneShape *ShapeBullet::create_shape_plane(const btVector3 &planeNormal, btScalar planeConstant) {
+ return bulletnew(btStaticPlaneShape(planeNormal, planeConstant));
+}
+
+btSphereShape *ShapeBullet::create_shape_sphere(btScalar radius) {
+ return bulletnew(btSphereShape(radius));
+}
+
+btBoxShape *ShapeBullet::create_shape_box(const btVector3 &boxHalfExtents) {
+ return bulletnew(btBoxShape(boxHalfExtents));
+}
+
+btCapsuleShapeZ *ShapeBullet::create_shape_capsule(btScalar radius, btScalar height) {
+ return bulletnew(btCapsuleShapeZ(radius, height));
+}
+
+btConvexPointCloudShape *ShapeBullet::create_shape_convex(btAlignedObjectArray<btVector3> &p_vertices, const btVector3 &p_local_scaling) {
+ return bulletnew(btConvexPointCloudShape(&p_vertices[0], p_vertices.size(), p_local_scaling));
+}
+
+btScaledBvhTriangleMeshShape *ShapeBullet::create_shape_concave(btBvhTriangleMeshShape *p_mesh_shape, const btVector3 &p_local_scaling) {
+ if (p_mesh_shape) {
+ return bulletnew(btScaledBvhTriangleMeshShape(p_mesh_shape, p_local_scaling));
+ } else {
+ return NULL;
+ }
+}
+
+btHeightfieldTerrainShape *ShapeBullet::create_shape_height_field(PoolVector<real_t> &p_heights, int p_width, int p_depth, real_t p_cell_size) {
+ const btScalar ignoredHeightScale(1);
+ const btScalar fieldHeight(500); // Meters
+ const int YAxis = 1; // 0=X, 1=Y, 2=Z
+ const bool flipQuadEdges = false;
+ const void *heightsPtr = p_heights.read().ptr();
+
+ return bulletnew(btHeightfieldTerrainShape(p_width, p_depth, heightsPtr, ignoredHeightScale, -fieldHeight, fieldHeight, YAxis, PHY_FLOAT, flipQuadEdges));
+}
+
+btRayShape *ShapeBullet::create_shape_ray(real_t p_length) {
+ return bulletnew(btRayShape(p_length));
+}
+
+/* PLANE */
+
+PlaneShapeBullet::PlaneShapeBullet()
+ : ShapeBullet() {}
+
+void PlaneShapeBullet::set_data(const Variant &p_data) {
+ setup(p_data);
+}
+
+Variant PlaneShapeBullet::get_data() const {
+ return plane;
+}
+
+PhysicsServer::ShapeType PlaneShapeBullet::get_type() const {
+ return PhysicsServer::SHAPE_PLANE;
+}
+
+void PlaneShapeBullet::setup(const Plane &p_plane) {
+ plane = p_plane;
+ notifyShapeChanged();
+}
+
+btCollisionShape *PlaneShapeBullet::create_bt_shape() {
+ btVector3 btPlaneNormal;
+ G_TO_B(plane.normal, btPlaneNormal);
+ return prepare(PlaneShapeBullet::create_shape_plane(btPlaneNormal, plane.d));
+}
+
+/* Sphere */
+
+SphereShapeBullet::SphereShapeBullet()
+ : ShapeBullet() {}
+
+void SphereShapeBullet::set_data(const Variant &p_data) {
+ setup(p_data);
+}
+
+Variant SphereShapeBullet::get_data() const {
+ return radius;
+}
+
+PhysicsServer::ShapeType SphereShapeBullet::get_type() const {
+ return PhysicsServer::SHAPE_SPHERE;
+}
+
+void SphereShapeBullet::setup(real_t p_radius) {
+ radius = p_radius;
+ notifyShapeChanged();
+}
+
+btCollisionShape *SphereShapeBullet::create_bt_shape() {
+ return prepare(ShapeBullet::create_shape_sphere(radius));
+}
+
+/* Box */
+BoxShapeBullet::BoxShapeBullet()
+ : ShapeBullet() {}
+
+void BoxShapeBullet::set_data(const Variant &p_data) {
+ setup(p_data);
+}
+
+Variant BoxShapeBullet::get_data() const {
+ Vector3 g_half_extents;
+ B_TO_G(half_extents, g_half_extents);
+ return g_half_extents;
+}
+
+PhysicsServer::ShapeType BoxShapeBullet::get_type() const {
+ return PhysicsServer::SHAPE_BOX;
+}
+
+void BoxShapeBullet::setup(const Vector3 &p_half_extents) {
+ G_TO_B(p_half_extents, half_extents);
+ notifyShapeChanged();
+}
+
+btCollisionShape *BoxShapeBullet::create_bt_shape() {
+ return prepare(ShapeBullet::create_shape_box(half_extents));
+}
+
+/* Capsule */
+
+CapsuleShapeBullet::CapsuleShapeBullet()
+ : ShapeBullet() {}
+
+void CapsuleShapeBullet::set_data(const Variant &p_data) {
+ Dictionary d = p_data;
+ ERR_FAIL_COND(!d.has("radius"));
+ ERR_FAIL_COND(!d.has("height"));
+ setup(d["height"], d["radius"]);
+}
+
+Variant CapsuleShapeBullet::get_data() const {
+ Dictionary d;
+ d["radius"] = radius;
+ d["height"] = height;
+ return d;
+}
+
+PhysicsServer::ShapeType CapsuleShapeBullet::get_type() const {
+ return PhysicsServer::SHAPE_CAPSULE;
+}
+
+void CapsuleShapeBullet::setup(real_t p_height, real_t p_radius) {
+ radius = p_radius;
+ height = p_height;
+ notifyShapeChanged();
+}
+
+btCollisionShape *CapsuleShapeBullet::create_bt_shape() {
+ return prepare(ShapeBullet::create_shape_capsule(radius, height));
+}
+
+/* Convex polygon */
+
+ConvexPolygonShapeBullet::ConvexPolygonShapeBullet()
+ : ShapeBullet() {}
+
+void ConvexPolygonShapeBullet::set_data(const Variant &p_data) {
+ setup(p_data);
+}
+
+void ConvexPolygonShapeBullet::get_vertices(Vector<Vector3> &out_vertices) {
+ const int n_of_vertices = vertices.size();
+ out_vertices.resize(n_of_vertices);
+ for (int i = n_of_vertices - 1; 0 <= i; --i) {
+ B_TO_G(vertices[i], out_vertices[i]);
+ }
+}
+
+Variant ConvexPolygonShapeBullet::get_data() const {
+ ConvexPolygonShapeBullet *variable_self = const_cast<ConvexPolygonShapeBullet *>(this);
+ Vector<Vector3> out_vertices;
+ variable_self->get_vertices(out_vertices);
+ return out_vertices;
+}
+
+PhysicsServer::ShapeType ConvexPolygonShapeBullet::get_type() const {
+ return PhysicsServer::SHAPE_CONVEX_POLYGON;
+}
+
+void ConvexPolygonShapeBullet::setup(const Vector<Vector3> &p_vertices) {
+ // Make a copy of verticies
+ const int n_of_vertices = p_vertices.size();
+ vertices.resize(n_of_vertices);
+ for (int i = n_of_vertices - 1; 0 <= i; --i) {
+ G_TO_B(p_vertices[i], vertices[i]);
+ }
+ notifyShapeChanged();
+}
+
+btCollisionShape *ConvexPolygonShapeBullet::create_bt_shape() {
+ return prepare(ShapeBullet::create_shape_convex(vertices));
+}
+
+/* Concave polygon */
+
+ConcavePolygonShapeBullet::ConcavePolygonShapeBullet()
+ : ShapeBullet(), meshShape(NULL) {}
+
+ConcavePolygonShapeBullet::~ConcavePolygonShapeBullet() {
+ if (meshShape) {
+ delete meshShape->getMeshInterface();
+ delete meshShape;
+ }
+ faces = PoolVector<Vector3>();
+}
+
+void ConcavePolygonShapeBullet::set_data(const Variant &p_data) {
+ setup(p_data);
+}
+
+Variant ConcavePolygonShapeBullet::get_data() const {
+ return faces;
+}
+
+PhysicsServer::ShapeType ConcavePolygonShapeBullet::get_type() const {
+ return PhysicsServer::SHAPE_CONCAVE_POLYGON;
+}
+
+void ConcavePolygonShapeBullet::setup(PoolVector<Vector3> p_faces) {
+ faces = p_faces;
+ if (meshShape) {
+ /// Clear previous created shape
+ delete meshShape->getMeshInterface();
+ bulletdelete(meshShape);
+ }
+ int src_face_count = faces.size();
+ if (0 < src_face_count) {
+
+ btTriangleMesh *shapeInterface = bulletnew(btTriangleMesh);
+
+ // It counts the faces and assert the array contains the correct number of vertices.
+ ERR_FAIL_COND(src_face_count % 3);
+ src_face_count /= 3;
+ PoolVector<Vector3>::Read r = p_faces.read();
+ const Vector3 *facesr = r.ptr();
+
+ btVector3 supVec_0;
+ btVector3 supVec_1;
+ btVector3 supVec_2;
+ for (int i = 0; i < src_face_count; ++i) {
+ G_TO_B(facesr[i * 3], supVec_0);
+ G_TO_B(facesr[i * 3 + 1], supVec_1);
+ G_TO_B(facesr[i * 3 + 2], supVec_2);
+
+ shapeInterface->addTriangle(supVec_0, supVec_1, supVec_2);
+ }
+
+ const bool useQuantizedAabbCompression = true;
+
+ meshShape = bulletnew(btBvhTriangleMeshShape(shapeInterface, useQuantizedAabbCompression));
+ } else {
+ meshShape = NULL;
+ ERR_PRINT("The faces count are 0, the mesh shape cannot be created");
+ }
+ notifyShapeChanged();
+}
+
+btCollisionShape *ConcavePolygonShapeBullet::create_bt_shape() {
+ btCollisionShape *cs = ShapeBullet::create_shape_concave(meshShape);
+ if (!cs) {
+ // This is necessary since if 0 faces the creation of concave return NULL
+ cs = ShapeBullet::create_shape_empty();
+ }
+ return prepare(cs);
+}
+
+/* Height map shape */
+
+HeightMapShapeBullet::HeightMapShapeBullet()
+ : ShapeBullet() {}
+
+void HeightMapShapeBullet::set_data(const Variant &p_data) {
+ ERR_FAIL_COND(p_data.get_type() != Variant::DICTIONARY);
+ Dictionary d = p_data;
+ ERR_FAIL_COND(!d.has("width"));
+ ERR_FAIL_COND(!d.has("depth"));
+ ERR_FAIL_COND(!d.has("cell_size"));
+ ERR_FAIL_COND(!d.has("heights"));
+
+ int l_width = d["width"];
+ int l_depth = d["depth"];
+ real_t l_cell_size = d["cell_size"];
+ PoolVector<real_t> l_heights = d["heights"];
+
+ ERR_FAIL_COND(l_width <= 0);
+ ERR_FAIL_COND(l_depth <= 0);
+ ERR_FAIL_COND(l_cell_size <= CMP_EPSILON);
+ ERR_FAIL_COND(l_heights.size() != (width * depth));
+ setup(heights, width, depth, cell_size);
+}
+
+Variant HeightMapShapeBullet::get_data() const {
+ ERR_FAIL_V(Variant());
+}
+
+PhysicsServer::ShapeType HeightMapShapeBullet::get_type() const {
+ return PhysicsServer::SHAPE_HEIGHTMAP;
+}
+
+void HeightMapShapeBullet::setup(PoolVector<real_t> &p_heights, int p_width, int p_depth, real_t p_cell_size) {
+ { // Copy
+ const int heights_size = p_heights.size();
+ heights.resize(heights_size);
+ PoolVector<real_t>::Read p_heights_r = p_heights.read();
+ PoolVector<real_t>::Write heights_w = heights.write();
+ for (int i = heights_size - 1; 0 <= i; --i) {
+ heights_w[i] = p_heights_r[i];
+ }
+ }
+ width = p_width;
+ depth = p_depth;
+ cell_size = p_cell_size;
+ notifyShapeChanged();
+}
+
+btCollisionShape *HeightMapShapeBullet::create_bt_shape() {
+ return prepare(ShapeBullet::create_shape_height_field(heights, width, depth, cell_size));
+}
+
+/* Ray shape */
+RayShapeBullet::RayShapeBullet()
+ : ShapeBullet(), length(1) {}
+
+void RayShapeBullet::set_data(const Variant &p_data) {
+ setup(p_data);
+}
+
+Variant RayShapeBullet::get_data() const {
+ return length;
+}
+
+PhysicsServer::ShapeType RayShapeBullet::get_type() const {
+ return PhysicsServer::SHAPE_RAY;
+}
+
+void RayShapeBullet::setup(real_t p_length) {
+ length = p_length;
+ notifyShapeChanged();
+}
+
+btCollisionShape *RayShapeBullet::create_bt_shape() {
+ return prepare(ShapeBullet::create_shape_ray(length));
+}
diff --git a/modules/bullet/shape_bullet.h b/modules/bullet/shape_bullet.h
new file mode 100644
index 0000000000..0a56fa1709
--- /dev/null
+++ b/modules/bullet/shape_bullet.h
@@ -0,0 +1,225 @@
+/*************************************************************************/
+/* shape_bullet.h */
+/* Author: AndreaCatania */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef SHAPE_BULLET_H
+#define SHAPE_BULLET_H
+
+#include "LinearMath/btAlignedObjectArray.h"
+#include "LinearMath/btScalar.h"
+#include "LinearMath/btVector3.h"
+#include "core/variant.h"
+#include "geometry.h"
+#include "rid_bullet.h"
+#include "servers/physics_server.h"
+
+class ShapeBullet;
+class btCollisionShape;
+class ShapeOwnerBullet;
+class btBvhTriangleMeshShape;
+
+class ShapeBullet : public RIDBullet {
+
+ Map<ShapeOwnerBullet *, int> owners;
+
+protected:
+ /// return self
+ btCollisionShape *prepare(btCollisionShape *p_btShape) const;
+ void notifyShapeChanged();
+
+public:
+ ShapeBullet();
+ virtual ~ShapeBullet();
+
+ virtual btCollisionShape *create_bt_shape() = 0;
+
+ void add_owner(ShapeOwnerBullet *p_owner);
+ void remove_owner(ShapeOwnerBullet *p_owner, bool p_permanentlyFromThisBody = false);
+ bool is_owner(ShapeOwnerBullet *p_owner) const;
+ const Map<ShapeOwnerBullet *, int> &get_owners() const;
+
+ /// Setup the shape
+ virtual void set_data(const Variant &p_data) = 0;
+ virtual Variant get_data() const = 0;
+
+ virtual PhysicsServer::ShapeType get_type() const = 0;
+
+public:
+ static class btEmptyShape *create_shape_empty();
+ static class btStaticPlaneShape *create_shape_plane(const btVector3 &planeNormal, btScalar planeConstant);
+ static class btSphereShape *create_shape_sphere(btScalar radius);
+ static class btBoxShape *create_shape_box(const btVector3 &boxHalfExtents);
+ static class btCapsuleShapeZ *create_shape_capsule(btScalar radius, btScalar height);
+ /// IMPORTANT: Remember to delete the shape interface by calling: delete my_shape->getMeshInterface();
+ static class btConvexPointCloudShape *create_shape_convex(btAlignedObjectArray<btVector3> &p_vertices, const btVector3 &p_local_scaling = btVector3(1, 1, 1));
+ static class btScaledBvhTriangleMeshShape *create_shape_concave(btBvhTriangleMeshShape *p_mesh_shape, const btVector3 &p_local_scaling = btVector3(1, 1, 1));
+ static class btHeightfieldTerrainShape *create_shape_height_field(PoolVector<real_t> &p_heights, int p_width, int p_depth, real_t p_cell_size);
+ static class btRayShape *create_shape_ray(real_t p_length);
+};
+
+class PlaneShapeBullet : public ShapeBullet {
+
+ Plane plane;
+
+public:
+ PlaneShapeBullet();
+
+ virtual void set_data(const Variant &p_data);
+ virtual Variant get_data() const;
+ virtual PhysicsServer::ShapeType get_type() const;
+ virtual btCollisionShape *create_bt_shape();
+
+private:
+ void setup(const Plane &p_plane);
+};
+
+class SphereShapeBullet : public ShapeBullet {
+
+ real_t radius;
+
+public:
+ SphereShapeBullet();
+
+ _FORCE_INLINE_ real_t get_radius() { return radius; }
+ virtual void set_data(const Variant &p_data);
+ virtual Variant get_data() const;
+ virtual PhysicsServer::ShapeType get_type() const;
+ virtual btCollisionShape *create_bt_shape();
+
+private:
+ void setup(real_t p_radius);
+};
+
+class BoxShapeBullet : public ShapeBullet {
+
+ btVector3 half_extents;
+
+public:
+ BoxShapeBullet();
+
+ _FORCE_INLINE_ const btVector3 &get_half_extents() { return half_extents; }
+ virtual void set_data(const Variant &p_data);
+ virtual Variant get_data() const;
+ virtual PhysicsServer::ShapeType get_type() const;
+ virtual btCollisionShape *create_bt_shape();
+
+private:
+ void setup(const Vector3 &p_half_extents);
+};
+
+class CapsuleShapeBullet : public ShapeBullet {
+
+ real_t height;
+ real_t radius;
+
+public:
+ CapsuleShapeBullet();
+
+ _FORCE_INLINE_ real_t get_height() { return height; }
+ _FORCE_INLINE_ real_t get_radius() { return radius; }
+ virtual void set_data(const Variant &p_data);
+ virtual Variant get_data() const;
+ virtual PhysicsServer::ShapeType get_type() const;
+ virtual btCollisionShape *create_bt_shape();
+
+private:
+ void setup(real_t p_height, real_t p_radius);
+};
+
+class ConvexPolygonShapeBullet : public ShapeBullet {
+
+public:
+ btAlignedObjectArray<btVector3> vertices;
+
+ ConvexPolygonShapeBullet();
+
+ virtual void set_data(const Variant &p_data);
+ void get_vertices(Vector<Vector3> &out_vertices);
+ virtual Variant get_data() const;
+ virtual PhysicsServer::ShapeType get_type() const;
+ virtual btCollisionShape *create_bt_shape();
+
+private:
+ void setup(const Vector<Vector3> &p_vertices);
+};
+
+class ConcavePolygonShapeBullet : public ShapeBullet {
+ class btBvhTriangleMeshShape *meshShape;
+
+public:
+ PoolVector<Vector3> faces;
+
+ ConcavePolygonShapeBullet();
+ virtual ~ConcavePolygonShapeBullet();
+
+ virtual void set_data(const Variant &p_data);
+ virtual Variant get_data() const;
+ virtual PhysicsServer::ShapeType get_type() const;
+ virtual btCollisionShape *create_bt_shape();
+
+private:
+ void setup(PoolVector<Vector3> p_faces);
+};
+
+class HeightMapShapeBullet : public ShapeBullet {
+
+public:
+ PoolVector<real_t> heights;
+ int width;
+ int depth;
+ real_t cell_size;
+
+ HeightMapShapeBullet();
+
+ virtual void set_data(const Variant &p_data);
+ virtual Variant get_data() const;
+ virtual PhysicsServer::ShapeType get_type() const;
+ virtual btCollisionShape *create_bt_shape();
+
+private:
+ void setup(PoolVector<real_t> &p_heights, int p_width, int p_depth, real_t p_cell_size);
+};
+
+class RayShapeBullet : public ShapeBullet {
+
+public:
+ real_t length;
+
+ RayShapeBullet();
+
+ virtual void set_data(const Variant &p_data);
+ virtual Variant get_data() const;
+ virtual PhysicsServer::ShapeType get_type() const;
+ virtual btCollisionShape *create_bt_shape();
+
+private:
+ void setup(real_t p_length);
+};
+#endif
diff --git a/modules/bullet/shape_owner_bullet.cpp b/modules/bullet/shape_owner_bullet.cpp
new file mode 100644
index 0000000000..04b2b01675
--- /dev/null
+++ b/modules/bullet/shape_owner_bullet.cpp
@@ -0,0 +1,32 @@
+/*************************************************************************/
+/* shape_owner_bullet.cpp */
+/* Author: AndreaCatania */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "shape_owner_bullet.h"
diff --git a/modules/bullet/shape_owner_bullet.h b/modules/bullet/shape_owner_bullet.h
new file mode 100644
index 0000000000..d2f3d321c7
--- /dev/null
+++ b/modules/bullet/shape_owner_bullet.h
@@ -0,0 +1,52 @@
+/*************************************************************************/
+/* shape_owner_bullet.h */
+/* Author: AndreaCatania */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef SHAPE_OWNER_BULLET_H
+#define SHAPE_OWNER_BULLET_H
+
+#include "rid_bullet.h"
+
+class ShapeBullet;
+class btCollisionShape;
+class CollisionObjectBullet;
+
+/// Each clas that want to use Shapes must inherit this class
+/// E.G. BodyShape is a child of this
+class ShapeOwnerBullet {
+public:
+ /// This is used to set new shape or replace existing
+ //virtual void _internal_replaceShape(btCollisionShape *p_old_shape, btCollisionShape *p_new_shape) = 0;
+ virtual void on_shape_changed(const ShapeBullet *const p_shape) = 0;
+ virtual void on_shapes_changed() = 0;
+ virtual void remove_shape(class ShapeBullet *p_shape) = 0;
+ virtual ~ShapeOwnerBullet() {}
+};
+#endif
diff --git a/modules/bullet/slider_joint_bullet.cpp b/modules/bullet/slider_joint_bullet.cpp
new file mode 100644
index 0000000000..2da65677f5
--- /dev/null
+++ b/modules/bullet/slider_joint_bullet.cpp
@@ -0,0 +1,385 @@
+/*************************************************************************/
+/* slider_joint_bullet.cpp */
+/* Author: AndreaCatania */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "slider_joint_bullet.h"
+#include "BulletDynamics/ConstraintSolver/btSliderConstraint.h"
+#include "bullet_types_converter.h"
+#include "bullet_utilities.h"
+#include "rigid_body_bullet.h"
+
+SliderJointBullet::SliderJointBullet(RigidBodyBullet *rbA, RigidBodyBullet *rbB, const Transform &frameInA, const Transform &frameInB)
+ : JointBullet() {
+ btTransform btFrameA;
+ G_TO_B(frameInA, btFrameA);
+ if (rbB) {
+ btTransform btFrameB;
+ G_TO_B(frameInB, btFrameB);
+ sliderConstraint = bulletnew(btSliderConstraint(*rbA->get_bt_rigid_body(), *rbB->get_bt_rigid_body(), btFrameA, btFrameB, true));
+
+ } else {
+ sliderConstraint = bulletnew(btSliderConstraint(*rbA->get_bt_rigid_body(), btFrameA, true));
+ }
+ setup(sliderConstraint);
+}
+
+const RigidBodyBullet *SliderJointBullet::getRigidBodyA() const {
+ return static_cast<RigidBodyBullet *>(sliderConstraint->getRigidBodyA().getUserPointer());
+}
+
+const RigidBodyBullet *SliderJointBullet::getRigidBodyB() const {
+ return static_cast<RigidBodyBullet *>(sliderConstraint->getRigidBodyB().getUserPointer());
+}
+
+const Transform SliderJointBullet::getCalculatedTransformA() const {
+ btTransform btTransform = sliderConstraint->getCalculatedTransformA();
+ Transform gTrans;
+ B_TO_G(btTransform, gTrans);
+ return gTrans;
+}
+
+const Transform SliderJointBullet::getCalculatedTransformB() const {
+ btTransform btTransform = sliderConstraint->getCalculatedTransformB();
+ Transform gTrans;
+ B_TO_G(btTransform, gTrans);
+ return gTrans;
+}
+
+const Transform SliderJointBullet::getFrameOffsetA() const {
+ btTransform btTransform = sliderConstraint->getFrameOffsetA();
+ Transform gTrans;
+ B_TO_G(btTransform, gTrans);
+ return gTrans;
+}
+
+const Transform SliderJointBullet::getFrameOffsetB() const {
+ btTransform btTransform = sliderConstraint->getFrameOffsetB();
+ Transform gTrans;
+ B_TO_G(btTransform, gTrans);
+ return gTrans;
+}
+
+Transform SliderJointBullet::getFrameOffsetA() {
+ btTransform btTransform = sliderConstraint->getFrameOffsetA();
+ Transform gTrans;
+ B_TO_G(btTransform, gTrans);
+ return gTrans;
+}
+
+Transform SliderJointBullet::getFrameOffsetB() {
+ btTransform btTransform = sliderConstraint->getFrameOffsetB();
+ Transform gTrans;
+ B_TO_G(btTransform, gTrans);
+ return gTrans;
+}
+
+real_t SliderJointBullet::getLowerLinLimit() const {
+ return sliderConstraint->getLowerLinLimit();
+}
+
+void SliderJointBullet::setLowerLinLimit(real_t lowerLimit) {
+ sliderConstraint->setLowerLinLimit(lowerLimit);
+}
+real_t SliderJointBullet::getUpperLinLimit() const {
+ return sliderConstraint->getUpperLinLimit();
+}
+
+void SliderJointBullet::setUpperLinLimit(real_t upperLimit) {
+ sliderConstraint->setUpperLinLimit(upperLimit);
+}
+
+real_t SliderJointBullet::getLowerAngLimit() const {
+ return sliderConstraint->getLowerAngLimit();
+}
+
+void SliderJointBullet::setLowerAngLimit(real_t lowerLimit) {
+ sliderConstraint->setLowerAngLimit(lowerLimit);
+}
+
+real_t SliderJointBullet::getUpperAngLimit() const {
+ return sliderConstraint->getUpperAngLimit();
+}
+
+void SliderJointBullet::setUpperAngLimit(real_t upperLimit) {
+ sliderConstraint->setUpperAngLimit(upperLimit);
+}
+
+real_t SliderJointBullet::getSoftnessDirLin() const {
+ return sliderConstraint->getSoftnessDirLin();
+}
+
+real_t SliderJointBullet::getRestitutionDirLin() const {
+ return sliderConstraint->getRestitutionDirLin();
+}
+
+real_t SliderJointBullet::getDampingDirLin() const {
+ return sliderConstraint->getDampingDirLin();
+}
+
+real_t SliderJointBullet::getSoftnessDirAng() const {
+ return sliderConstraint->getSoftnessDirAng();
+}
+
+real_t SliderJointBullet::getRestitutionDirAng() const {
+ return sliderConstraint->getRestitutionDirAng();
+}
+
+real_t SliderJointBullet::getDampingDirAng() const {
+ return sliderConstraint->getDampingDirAng();
+}
+
+real_t SliderJointBullet::getSoftnessLimLin() const {
+ return sliderConstraint->getSoftnessLimLin();
+}
+
+real_t SliderJointBullet::getRestitutionLimLin() const {
+ return sliderConstraint->getRestitutionLimLin();
+}
+
+real_t SliderJointBullet::getDampingLimLin() const {
+ return sliderConstraint->getDampingLimLin();
+}
+
+real_t SliderJointBullet::getSoftnessLimAng() const {
+ return sliderConstraint->getSoftnessLimAng();
+}
+
+real_t SliderJointBullet::getRestitutionLimAng() const {
+ return sliderConstraint->getRestitutionLimAng();
+}
+
+real_t SliderJointBullet::getDampingLimAng() const {
+ return sliderConstraint->getDampingLimAng();
+}
+
+real_t SliderJointBullet::getSoftnessOrthoLin() const {
+ return sliderConstraint->getSoftnessOrthoLin();
+}
+
+real_t SliderJointBullet::getRestitutionOrthoLin() const {
+ return sliderConstraint->getRestitutionOrthoLin();
+}
+
+real_t SliderJointBullet::getDampingOrthoLin() const {
+ return sliderConstraint->getDampingOrthoLin();
+}
+
+real_t SliderJointBullet::getSoftnessOrthoAng() const {
+ return sliderConstraint->getSoftnessOrthoAng();
+}
+
+real_t SliderJointBullet::getRestitutionOrthoAng() const {
+ return sliderConstraint->getRestitutionOrthoAng();
+}
+
+real_t SliderJointBullet::getDampingOrthoAng() const {
+ return sliderConstraint->getDampingOrthoAng();
+}
+
+void SliderJointBullet::setSoftnessDirLin(real_t softnessDirLin) {
+ sliderConstraint->setSoftnessDirLin(softnessDirLin);
+}
+
+void SliderJointBullet::setRestitutionDirLin(real_t restitutionDirLin) {
+ sliderConstraint->setRestitutionDirLin(restitutionDirLin);
+}
+
+void SliderJointBullet::setDampingDirLin(real_t dampingDirLin) {
+ sliderConstraint->setDampingDirLin(dampingDirLin);
+}
+
+void SliderJointBullet::setSoftnessDirAng(real_t softnessDirAng) {
+ sliderConstraint->setSoftnessDirAng(softnessDirAng);
+}
+
+void SliderJointBullet::setRestitutionDirAng(real_t restitutionDirAng) {
+ sliderConstraint->setRestitutionDirAng(restitutionDirAng);
+}
+
+void SliderJointBullet::setDampingDirAng(real_t dampingDirAng) {
+ sliderConstraint->setDampingDirAng(dampingDirAng);
+}
+
+void SliderJointBullet::setSoftnessLimLin(real_t softnessLimLin) {
+ sliderConstraint->setSoftnessLimLin(softnessLimLin);
+}
+
+void SliderJointBullet::setRestitutionLimLin(real_t restitutionLimLin) {
+ sliderConstraint->setRestitutionLimLin(restitutionLimLin);
+}
+
+void SliderJointBullet::setDampingLimLin(real_t dampingLimLin) {
+ sliderConstraint->setDampingLimLin(dampingLimLin);
+}
+
+void SliderJointBullet::setSoftnessLimAng(real_t softnessLimAng) {
+ sliderConstraint->setSoftnessLimAng(softnessLimAng);
+}
+
+void SliderJointBullet::setRestitutionLimAng(real_t restitutionLimAng) {
+ sliderConstraint->setRestitutionLimAng(restitutionLimAng);
+}
+
+void SliderJointBullet::setDampingLimAng(real_t dampingLimAng) {
+ sliderConstraint->setDampingLimAng(dampingLimAng);
+}
+
+void SliderJointBullet::setSoftnessOrthoLin(real_t softnessOrthoLin) {
+ sliderConstraint->setSoftnessOrthoLin(softnessOrthoLin);
+}
+
+void SliderJointBullet::setRestitutionOrthoLin(real_t restitutionOrthoLin) {
+ sliderConstraint->setRestitutionOrthoLin(restitutionOrthoLin);
+}
+
+void SliderJointBullet::setDampingOrthoLin(real_t dampingOrthoLin) {
+ sliderConstraint->setDampingOrthoLin(dampingOrthoLin);
+}
+
+void SliderJointBullet::setSoftnessOrthoAng(real_t softnessOrthoAng) {
+ sliderConstraint->setSoftnessOrthoAng(softnessOrthoAng);
+}
+
+void SliderJointBullet::setRestitutionOrthoAng(real_t restitutionOrthoAng) {
+ sliderConstraint->setRestitutionOrthoAng(restitutionOrthoAng);
+}
+
+void SliderJointBullet::setDampingOrthoAng(real_t dampingOrthoAng) {
+ sliderConstraint->setDampingOrthoAng(dampingOrthoAng);
+}
+
+void SliderJointBullet::setPoweredLinMotor(bool onOff) {
+ sliderConstraint->setPoweredLinMotor(onOff);
+}
+
+bool SliderJointBullet::getPoweredLinMotor() {
+ return sliderConstraint->getPoweredLinMotor();
+}
+
+void SliderJointBullet::setTargetLinMotorVelocity(real_t targetLinMotorVelocity) {
+ sliderConstraint->setTargetLinMotorVelocity(targetLinMotorVelocity);
+}
+
+real_t SliderJointBullet::getTargetLinMotorVelocity() {
+ return sliderConstraint->getTargetLinMotorVelocity();
+}
+
+void SliderJointBullet::setMaxLinMotorForce(real_t maxLinMotorForce) {
+ sliderConstraint->setMaxLinMotorForce(maxLinMotorForce);
+}
+
+real_t SliderJointBullet::getMaxLinMotorForce() {
+ return sliderConstraint->getMaxLinMotorForce();
+}
+
+void SliderJointBullet::setPoweredAngMotor(bool onOff) {
+ sliderConstraint->setPoweredAngMotor(onOff);
+}
+
+bool SliderJointBullet::getPoweredAngMotor() {
+ return sliderConstraint->getPoweredAngMotor();
+}
+
+void SliderJointBullet::setTargetAngMotorVelocity(real_t targetAngMotorVelocity) {
+ sliderConstraint->setTargetAngMotorVelocity(targetAngMotorVelocity);
+}
+
+real_t SliderJointBullet::getTargetAngMotorVelocity() {
+ return sliderConstraint->getTargetAngMotorVelocity();
+}
+
+void SliderJointBullet::setMaxAngMotorForce(real_t maxAngMotorForce) {
+ sliderConstraint->setMaxAngMotorForce(maxAngMotorForce);
+}
+
+real_t SliderJointBullet::getMaxAngMotorForce() {
+ return sliderConstraint->getMaxAngMotorForce();
+}
+
+real_t SliderJointBullet::getLinearPos() {
+ return sliderConstraint->getLinearPos();
+ ;
+}
+
+void SliderJointBullet::set_param(PhysicsServer::SliderJointParam p_param, real_t p_value) {
+ switch (p_param) {
+ case PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_UPPER: setUpperLinLimit(p_value); break;
+ case PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_LOWER: setLowerLinLimit(p_value); break;
+ case PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_SOFTNESS: setSoftnessLimLin(p_value); break;
+ case PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_RESTITUTION: setRestitutionLimLin(p_value); break;
+ case PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_DAMPING: setDampingLimLin(p_value); break;
+ case PhysicsServer::SLIDER_JOINT_LINEAR_MOTION_SOFTNESS: setSoftnessDirLin(p_value); break;
+ case PhysicsServer::SLIDER_JOINT_LINEAR_MOTION_RESTITUTION: setRestitutionDirLin(p_value); break;
+ case PhysicsServer::SLIDER_JOINT_LINEAR_MOTION_DAMPING: setDampingDirLin(p_value); break;
+ case PhysicsServer::SLIDER_JOINT_LINEAR_ORTHOGONAL_SOFTNESS: setSoftnessOrthoLin(p_value); break;
+ case PhysicsServer::SLIDER_JOINT_LINEAR_ORTHOGONAL_RESTITUTION: setRestitutionOrthoLin(p_value); break;
+ case PhysicsServer::SLIDER_JOINT_LINEAR_ORTHOGONAL_DAMPING: setDampingOrthoLin(p_value); break;
+ case PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_UPPER: setUpperAngLimit(p_value); break;
+ case PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_LOWER: setLowerAngLimit(p_value); break;
+ case PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS: setSoftnessLimAng(p_value); break;
+ case PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_RESTITUTION: setRestitutionLimAng(p_value); break;
+ case PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_DAMPING: setDampingLimAng(p_value); break;
+ case PhysicsServer::SLIDER_JOINT_ANGULAR_MOTION_SOFTNESS: setSoftnessDirAng(p_value); break;
+ case PhysicsServer::SLIDER_JOINT_ANGULAR_MOTION_RESTITUTION: setRestitutionDirAng(p_value); break;
+ case PhysicsServer::SLIDER_JOINT_ANGULAR_MOTION_DAMPING: setDampingDirAng(p_value); break;
+ case PhysicsServer::SLIDER_JOINT_ANGULAR_ORTHOGONAL_SOFTNESS: setSoftnessOrthoAng(p_value); break;
+ case PhysicsServer::SLIDER_JOINT_ANGULAR_ORTHOGONAL_RESTITUTION: setRestitutionOrthoAng(p_value); break;
+ case PhysicsServer::SLIDER_JOINT_ANGULAR_ORTHOGONAL_DAMPING: setDampingOrthoAng(p_value); break;
+ }
+}
+
+real_t SliderJointBullet::get_param(PhysicsServer::SliderJointParam p_param) const {
+ switch (p_param) {
+ case PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_UPPER: return getUpperLinLimit();
+ case PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_LOWER: return getLowerLinLimit();
+ case PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_SOFTNESS: return getSoftnessLimLin();
+ case PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_RESTITUTION: return getRestitutionLimLin();
+ case PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_DAMPING: return getDampingLimLin();
+ case PhysicsServer::SLIDER_JOINT_LINEAR_MOTION_SOFTNESS: return getSoftnessDirLin();
+ case PhysicsServer::SLIDER_JOINT_LINEAR_MOTION_RESTITUTION: return getRestitutionDirLin();
+ case PhysicsServer::SLIDER_JOINT_LINEAR_MOTION_DAMPING: return getDampingDirLin();
+ case PhysicsServer::SLIDER_JOINT_LINEAR_ORTHOGONAL_SOFTNESS: return getSoftnessOrthoLin();
+ case PhysicsServer::SLIDER_JOINT_LINEAR_ORTHOGONAL_RESTITUTION: return getRestitutionOrthoLin();
+ case PhysicsServer::SLIDER_JOINT_LINEAR_ORTHOGONAL_DAMPING: return getDampingOrthoLin();
+ case PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_UPPER: return getUpperAngLimit();
+ case PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_LOWER: return getLowerAngLimit();
+ case PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS: return getSoftnessLimAng();
+ case PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_RESTITUTION: return getRestitutionLimAng();
+ case PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_DAMPING: return getDampingLimAng();
+ case PhysicsServer::SLIDER_JOINT_ANGULAR_MOTION_SOFTNESS: return getSoftnessDirAng();
+ case PhysicsServer::SLIDER_JOINT_ANGULAR_MOTION_RESTITUTION: return getRestitutionDirAng();
+ case PhysicsServer::SLIDER_JOINT_ANGULAR_MOTION_DAMPING: return getDampingDirAng();
+ case PhysicsServer::SLIDER_JOINT_ANGULAR_ORTHOGONAL_SOFTNESS: return getSoftnessOrthoAng();
+ case PhysicsServer::SLIDER_JOINT_ANGULAR_ORTHOGONAL_RESTITUTION: return getRestitutionOrthoAng();
+ case PhysicsServer::SLIDER_JOINT_ANGULAR_ORTHOGONAL_DAMPING: return getDampingOrthoAng();
+ default:
+ return 0;
+ }
+}
diff --git a/modules/bullet/slider_joint_bullet.h b/modules/bullet/slider_joint_bullet.h
new file mode 100644
index 0000000000..d50c376ea6
--- /dev/null
+++ b/modules/bullet/slider_joint_bullet.h
@@ -0,0 +1,118 @@
+/*************************************************************************/
+/* slider_joint_bullet.h */
+/* Author: AndreaCatania */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef SLIDER_JOINT_BULLET_H
+#define SLIDER_JOINT_BULLET_H
+
+#include "joint_bullet.h"
+
+class RigidBodyBullet;
+
+class SliderJointBullet : public JointBullet {
+ class btSliderConstraint *sliderConstraint;
+
+public:
+ /// Reference frame is A
+ SliderJointBullet(RigidBodyBullet *rbA, RigidBodyBullet *rbB, const Transform &frameInA, const Transform &frameInB);
+
+ virtual PhysicsServer::JointType get_type() const { return PhysicsServer::JOINT_SLIDER; }
+
+ const RigidBodyBullet *getRigidBodyA() const;
+ const RigidBodyBullet *getRigidBodyB() const;
+ const Transform getCalculatedTransformA() const;
+ const Transform getCalculatedTransformB() const;
+ const Transform getFrameOffsetA() const;
+ const Transform getFrameOffsetB() const;
+ Transform getFrameOffsetA();
+ Transform getFrameOffsetB();
+ real_t getLowerLinLimit() const;
+ void setLowerLinLimit(real_t lowerLimit);
+ real_t getUpperLinLimit() const;
+ void setUpperLinLimit(real_t upperLimit);
+ real_t getLowerAngLimit() const;
+ void setLowerAngLimit(real_t lowerLimit);
+ real_t getUpperAngLimit() const;
+ void setUpperAngLimit(real_t upperLimit);
+
+ real_t getSoftnessDirLin() const;
+ real_t getRestitutionDirLin() const;
+ real_t getDampingDirLin() const;
+ real_t getSoftnessDirAng() const;
+ real_t getRestitutionDirAng() const;
+ real_t getDampingDirAng() const;
+ real_t getSoftnessLimLin() const;
+ real_t getRestitutionLimLin() const;
+ real_t getDampingLimLin() const;
+ real_t getSoftnessLimAng() const;
+ real_t getRestitutionLimAng() const;
+ real_t getDampingLimAng() const;
+ real_t getSoftnessOrthoLin() const;
+ real_t getRestitutionOrthoLin() const;
+ real_t getDampingOrthoLin() const;
+ real_t getSoftnessOrthoAng() const;
+ real_t getRestitutionOrthoAng() const;
+ real_t getDampingOrthoAng() const;
+ void setSoftnessDirLin(real_t softnessDirLin);
+ void setRestitutionDirLin(real_t restitutionDirLin);
+ void setDampingDirLin(real_t dampingDirLin);
+ void setSoftnessDirAng(real_t softnessDirAng);
+ void setRestitutionDirAng(real_t restitutionDirAng);
+ void setDampingDirAng(real_t dampingDirAng);
+ void setSoftnessLimLin(real_t softnessLimLin);
+ void setRestitutionLimLin(real_t restitutionLimLin);
+ void setDampingLimLin(real_t dampingLimLin);
+ void setSoftnessLimAng(real_t softnessLimAng);
+ void setRestitutionLimAng(real_t restitutionLimAng);
+ void setDampingLimAng(real_t dampingLimAng);
+ void setSoftnessOrthoLin(real_t softnessOrthoLin);
+ void setRestitutionOrthoLin(real_t restitutionOrthoLin);
+ void setDampingOrthoLin(real_t dampingOrthoLin);
+ void setSoftnessOrthoAng(real_t softnessOrthoAng);
+ void setRestitutionOrthoAng(real_t restitutionOrthoAng);
+ void setDampingOrthoAng(real_t dampingOrthoAng);
+ void setPoweredLinMotor(bool onOff);
+ bool getPoweredLinMotor();
+ void setTargetLinMotorVelocity(real_t targetLinMotorVelocity);
+ real_t getTargetLinMotorVelocity();
+ void setMaxLinMotorForce(real_t maxLinMotorForce);
+ real_t getMaxLinMotorForce();
+ void setPoweredAngMotor(bool onOff);
+ bool getPoweredAngMotor();
+ void setTargetAngMotorVelocity(real_t targetAngMotorVelocity);
+ real_t getTargetAngMotorVelocity();
+ void setMaxAngMotorForce(real_t maxAngMotorForce);
+ real_t getMaxAngMotorForce();
+ real_t getLinearPos();
+
+ void set_param(PhysicsServer::SliderJointParam p_param, real_t p_value);
+ real_t get_param(PhysicsServer::SliderJointParam p_param) const;
+};
+#endif
diff --git a/modules/bullet/soft_body_bullet.cpp b/modules/bullet/soft_body_bullet.cpp
new file mode 100644
index 0000000000..64ef7bfad2
--- /dev/null
+++ b/modules/bullet/soft_body_bullet.cpp
@@ -0,0 +1,303 @@
+/*************************************************************************/
+/* soft_body_bullet.cpp */
+/* Author: AndreaCatania */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "soft_body_bullet.h"
+#include "bullet_types_converter.h"
+#include "bullet_utilities.h"
+#include "space_bullet.h"
+
+#include "scene/3d/immediate_geometry.h"
+
+SoftBodyBullet::SoftBodyBullet()
+ : CollisionObjectBullet(CollisionObjectBullet::TYPE_SOFT_BODY), mass(1), simulation_precision(5), stiffness(0.5f), pressure_coefficient(50), damping_coefficient(0.005), drag_coefficient(0.005), bt_soft_body(NULL), soft_shape_type(SOFT_SHAPETYPE_NONE), isScratched(false), soft_body_shape_data(NULL) {
+
+ test_geometry = memnew(ImmediateGeometry);
+
+ red_mat = Ref<SpatialMaterial>(memnew(SpatialMaterial));
+ red_mat->set_flag(SpatialMaterial::FLAG_UNSHADED, true);
+ red_mat->set_line_width(20.0);
+ red_mat->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true);
+ red_mat->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
+ red_mat->set_flag(SpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true);
+ red_mat->set_albedo(Color(1, 0, 0, 1));
+ test_geometry->set_material_override(red_mat);
+
+ test_is_in_scene = false;
+}
+
+SoftBodyBullet::~SoftBodyBullet() {
+ bulletdelete(soft_body_shape_data);
+}
+
+void SoftBodyBullet::reload_body() {
+ if (space) {
+ space->remove_soft_body(this);
+ space->add_soft_body(this);
+ }
+}
+
+void SoftBodyBullet::set_space(SpaceBullet *p_space) {
+ if (space) {
+ isScratched = false;
+
+ // Remove this object from the physics world
+ space->remove_soft_body(this);
+ }
+
+ space = p_space;
+
+ if (space) {
+ space->add_soft_body(this);
+ }
+
+ reload_soft_body();
+}
+
+void SoftBodyBullet::dispatch_callbacks() {
+ if (!bt_soft_body) {
+ return;
+ }
+
+ if (!test_is_in_scene) {
+ test_is_in_scene = true;
+ SceneTree::get_singleton()->get_current_scene()->add_child(test_geometry);
+ }
+
+ test_geometry->clear();
+ test_geometry->begin(Mesh::PRIMITIVE_LINES, NULL);
+ bool first = true;
+ Vector3 pos;
+ for (int i = 0; i < bt_soft_body->m_nodes.size(); ++i) {
+ const btSoftBody::Node &n = bt_soft_body->m_nodes[i];
+ B_TO_G(n.m_x, pos);
+ test_geometry->add_vertex(pos);
+ if (!first) {
+ test_geometry->add_vertex(pos);
+ } else {
+ first = false;
+ }
+ }
+ test_geometry->end();
+}
+
+void SoftBodyBullet::on_collision_filters_change() {
+}
+
+void SoftBodyBullet::on_collision_checker_start() {
+}
+
+void SoftBodyBullet::on_enter_area(AreaBullet *p_area) {
+}
+
+void SoftBodyBullet::on_exit_area(AreaBullet *p_area) {
+}
+
+void SoftBodyBullet::set_trimesh_body_shape(PoolVector<int> p_indices, PoolVector<Vector3> p_vertices, int p_triangles_num) {
+
+ TrimeshSoftShapeData *shape_data = bulletnew(TrimeshSoftShapeData);
+ shape_data->m_triangles_indices = p_indices;
+ shape_data->m_vertices = p_vertices;
+ shape_data->m_triangles_num = p_triangles_num;
+
+ set_body_shape_data(shape_data, SOFT_SHAPE_TYPE_TRIMESH);
+ reload_soft_body();
+}
+
+void SoftBodyBullet::set_body_shape_data(SoftShapeData *p_soft_shape_data, SoftShapeType p_type) {
+ bulletdelete(soft_body_shape_data);
+ soft_body_shape_data = p_soft_shape_data;
+ soft_shape_type = p_type;
+}
+
+void SoftBodyBullet::set_transform(const Transform &p_transform) {
+ transform = p_transform;
+ if (bt_soft_body) {
+ // TODO the softbody set new transform considering the current transform as center of world
+ // like if it's local transform, so I must fix this by setting nwe transform considering the old
+ btTransform bt_trans;
+ G_TO_B(transform, bt_trans);
+ //bt_soft_body->transform(bt_trans);
+ }
+}
+
+const Transform &SoftBodyBullet::get_transform() const {
+ return transform;
+}
+
+void SoftBodyBullet::get_first_node_origin(btVector3 &p_out_origin) const {
+ if (bt_soft_body && bt_soft_body->m_nodes.size()) {
+ p_out_origin = bt_soft_body->m_nodes[0].m_x;
+ } else {
+ p_out_origin.setZero();
+ }
+}
+
+void SoftBodyBullet::set_activation_state(bool p_active) {
+ if (p_active) {
+ bt_soft_body->setActivationState(ACTIVE_TAG);
+ } else {
+ bt_soft_body->setActivationState(WANTS_DEACTIVATION);
+ }
+}
+
+void SoftBodyBullet::set_mass(real_t p_val) {
+ if (0 >= p_val) {
+ p_val = 1;
+ }
+ mass = p_val;
+ if (bt_soft_body) {
+ bt_soft_body->setTotalMass(mass);
+ }
+}
+
+void SoftBodyBullet::set_stiffness(real_t p_val) {
+ stiffness = p_val;
+ if (bt_soft_body) {
+ mat0->m_kAST = stiffness;
+ mat0->m_kLST = stiffness;
+ mat0->m_kVST = stiffness;
+ }
+}
+
+void SoftBodyBullet::set_simulation_precision(int p_val) {
+ simulation_precision = p_val;
+ if (bt_soft_body) {
+ bt_soft_body->m_cfg.piterations = simulation_precision;
+ }
+}
+
+void SoftBodyBullet::set_pressure_coefficient(real_t p_val) {
+ pressure_coefficient = p_val;
+ if (bt_soft_body) {
+ bt_soft_body->m_cfg.kPR = pressure_coefficient;
+ }
+}
+
+void SoftBodyBullet::set_damping_coefficient(real_t p_val) {
+ damping_coefficient = p_val;
+ if (bt_soft_body) {
+ bt_soft_body->m_cfg.kDP = damping_coefficient;
+ }
+}
+
+void SoftBodyBullet::set_drag_coefficient(real_t p_val) {
+ drag_coefficient = p_val;
+ if (bt_soft_body) {
+ bt_soft_body->m_cfg.kDG = drag_coefficient;
+ }
+}
+
+void SoftBodyBullet::reload_soft_body() {
+
+ destroy_soft_body();
+ create_soft_body();
+
+ if (bt_soft_body) {
+
+ // TODO the softbody set new transform considering the current transform as center of world
+ // like if it's local transform, so I must fix this by setting nwe transform considering the old
+ btTransform bt_trans;
+ G_TO_B(transform, bt_trans);
+ bt_soft_body->transform(bt_trans);
+
+ bt_soft_body->generateBendingConstraints(2, mat0);
+ mat0->m_kAST = stiffness;
+ mat0->m_kLST = stiffness;
+ mat0->m_kVST = stiffness;
+
+ bt_soft_body->m_cfg.piterations = simulation_precision;
+ bt_soft_body->m_cfg.kDP = damping_coefficient;
+ bt_soft_body->m_cfg.kDG = drag_coefficient;
+ bt_soft_body->m_cfg.kPR = pressure_coefficient;
+ bt_soft_body->setTotalMass(mass);
+ }
+ if (space) {
+ // TODO remove this please
+ space->add_soft_body(this);
+ }
+}
+
+void SoftBodyBullet::create_soft_body() {
+ if (!space || !soft_body_shape_data) {
+ return;
+ }
+ ERR_FAIL_COND(!space->is_using_soft_world());
+ switch (soft_shape_type) {
+ case SOFT_SHAPE_TYPE_TRIMESH: {
+ TrimeshSoftShapeData *trimesh_data = static_cast<TrimeshSoftShapeData *>(soft_body_shape_data);
+
+ Vector<int> indices;
+ Vector<btScalar> vertices;
+
+ int i;
+ const int indices_size = trimesh_data->m_triangles_indices.size();
+ const int vertices_size = trimesh_data->m_vertices.size();
+ indices.resize(indices_size);
+ vertices.resize(vertices_size * 3);
+
+ PoolVector<int>::Read i_r = trimesh_data->m_triangles_indices.read();
+ for (i = 0; i < indices_size; ++i) {
+ indices[i] = i_r[i];
+ }
+ i_r = PoolVector<int>::Read();
+
+ PoolVector<Vector3>::Read f_r = trimesh_data->m_vertices.read();
+ for (int j = i = 0; i < vertices_size; ++i, j += 3) {
+ vertices[j + 0] = f_r[i][0];
+ vertices[j + 1] = f_r[i][1];
+ vertices[j + 2] = f_r[i][2];
+ }
+ f_r = PoolVector<Vector3>::Read();
+
+ bt_soft_body = btSoftBodyHelpers::CreateFromTriMesh(*space->get_soft_body_world_info(), vertices.ptr(), indices.ptr(), trimesh_data->m_triangles_num);
+ } break;
+ default:
+ ERR_PRINT("Shape type not supported");
+ return;
+ }
+
+ setupBulletCollisionObject(bt_soft_body);
+ bt_soft_body->getCollisionShape()->setMargin(0.001f);
+ bt_soft_body->setCollisionFlags(bt_soft_body->getCollisionFlags() & (~(btCollisionObject::CF_KINEMATIC_OBJECT | btCollisionObject::CF_STATIC_OBJECT)));
+ mat0 = bt_soft_body->appendMaterial();
+}
+
+void SoftBodyBullet::destroy_soft_body() {
+ if (space) {
+ /// This step is required to assert that the body is not into the world during deletion
+ /// This step is required since to change the body shape the body must be re-created.
+ /// Here is handled the case when the body is assigned into a world and the body
+ /// shape is changed.
+ space->remove_soft_body(this);
+ }
+ destroyBulletCollisionObject();
+ bt_soft_body = NULL;
+}
diff --git a/modules/bullet/soft_body_bullet.h b/modules/bullet/soft_body_bullet.h
new file mode 100644
index 0000000000..9ee7cd76d3
--- /dev/null
+++ b/modules/bullet/soft_body_bullet.h
@@ -0,0 +1,136 @@
+/*************************************************************************/
+/* soft_body_bullet.h */
+/* Author: AndreaCatania */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef SOFT_BODY_BULLET_H
+#define SOFT_BODY_BULLET_H
+
+#ifdef None
+/// This is required to remove the macro None defined by x11 compiler because this word "None" is used internally by Bullet
+#undef None
+#define x11_None 0L
+#endif
+
+#include "BulletSoftBody/btSoftBodyHelpers.h"
+#include "collision_object_bullet.h"
+
+#ifdef x11_None
+/// This is required to re add the macro None defined by x11 compiler
+#undef x11_None
+#define None 0L
+#endif
+
+#include "scene/resources/material.h" // TODO remove thsi please
+
+struct SoftShapeData {};
+struct TrimeshSoftShapeData : public SoftShapeData {
+ PoolVector<int> m_triangles_indices;
+ PoolVector<Vector3> m_vertices;
+ int m_triangles_num;
+};
+
+class SoftBodyBullet : public CollisionObjectBullet {
+public:
+ enum SoftShapeType {
+ SOFT_SHAPETYPE_NONE = 0,
+ SOFT_SHAPE_TYPE_TRIMESH
+ };
+
+private:
+ btSoftBody *bt_soft_body;
+ btSoftBody::Material *mat0; // This is just a copy of pointer managed by btSoftBody
+ SoftShapeType soft_shape_type;
+ bool isScratched;
+
+ SoftShapeData *soft_body_shape_data;
+
+ Transform transform;
+ int simulation_precision;
+ real_t mass;
+ real_t stiffness; // [0,1]
+ real_t pressure_coefficient; // [-inf,+inf]
+ real_t damping_coefficient; // [0,1]
+ real_t drag_coefficient; // [0,1]
+
+ class ImmediateGeometry *test_geometry; // TODO remove this please
+ Ref<SpatialMaterial> red_mat; // TODO remove this please
+ bool test_is_in_scene; // TODO remove this please
+
+public:
+ SoftBodyBullet();
+ ~SoftBodyBullet();
+
+ virtual void reload_body();
+ virtual void set_space(SpaceBullet *p_space);
+
+ virtual void dispatch_callbacks();
+ virtual void on_collision_filters_change();
+ virtual void on_collision_checker_start();
+ virtual void on_enter_area(AreaBullet *p_area);
+ virtual void on_exit_area(AreaBullet *p_area);
+
+ _FORCE_INLINE_ btSoftBody *get_bt_soft_body() const { return bt_soft_body; }
+
+ void set_trimesh_body_shape(PoolVector<int> p_indices, PoolVector<Vector3> p_vertices, int p_triangles_num);
+ void set_body_shape_data(SoftShapeData *p_soft_shape_data, SoftShapeType p_type);
+
+ void set_transform(const Transform &p_transform);
+ /// This function doesn't return the exact COM transform.
+ /// It returns the origin only of first node (vertice) of current soft body
+ /// ---
+ /// The soft body doesn't have a fixed center of mass, but is a group of nodes (vertices)
+ /// that each has its own position in the world.
+ /// For this reason return the correct COM is not so simple and must be calculate
+ /// Check this to improve this function http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=8803
+ const Transform &get_transform() const;
+ void get_first_node_origin(btVector3 &p_out_origin) const;
+
+ void set_activation_state(bool p_active);
+
+ void set_mass(real_t p_val);
+ _FORCE_INLINE_ real_t get_mass() const { return mass; }
+ void set_stiffness(real_t p_val);
+ _FORCE_INLINE_ real_t get_stiffness() const { return stiffness; }
+ void set_simulation_precision(int p_val);
+ _FORCE_INLINE_ int get_simulation_precision() const { return simulation_precision; }
+ void set_pressure_coefficient(real_t p_val);
+ _FORCE_INLINE_ real_t get_pressure_coefficient() const { return pressure_coefficient; }
+ void set_damping_coefficient(real_t p_val);
+ _FORCE_INLINE_ real_t get_damping_coefficient() const { return damping_coefficient; }
+ void set_drag_coefficient(real_t p_val);
+ _FORCE_INLINE_ real_t get_drag_coefficient() const { return drag_coefficient; }
+
+private:
+ void reload_soft_body();
+ void create_soft_body();
+ void destroy_soft_body();
+};
+
+#endif // SOFT_BODY_BULLET_H
diff --git a/modules/bullet/space_bullet.cpp b/modules/bullet/space_bullet.cpp
new file mode 100644
index 0000000000..853906063b
--- /dev/null
+++ b/modules/bullet/space_bullet.cpp
@@ -0,0 +1,1139 @@
+/*************************************************************************/
+/* space_bullet.cpp */
+/* Author: AndreaCatania */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "space_bullet.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/CollisionDispatch/btGhostObject.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h"
+#include "BulletCollision/NarrowPhaseCollision/btPointCollector.h"
+#include "BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h"
+#include "BulletSoftBody/btSoftRigidDynamicsWorld.h"
+#include "btBulletDynamicsCommon.h"
+#include "bullet_physics_server.h"
+#include "bullet_types_converter.h"
+#include "bullet_utilities.h"
+#include "constraint_bullet.h"
+#include "godot_collision_configuration.h"
+#include "godot_collision_dispatcher.h"
+#include "rigid_body_bullet.h"
+#include "servers/physics_server.h"
+#include "soft_body_bullet.h"
+#include "ustring.h"
+#include <assert.h>
+
+BulletPhysicsDirectSpaceState::BulletPhysicsDirectSpaceState(SpaceBullet *p_space)
+ : PhysicsDirectSpaceState(), space(p_space) {}
+
+int BulletPhysicsDirectSpaceState::intersect_point(const Vector3 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_layer, uint32_t p_object_type_mask) {
+
+ if (p_result_max <= 0)
+ return 0;
+
+ btVector3 bt_point;
+ G_TO_B(p_point, bt_point);
+
+ btSphereShape sphere_point(0.f);
+ btCollisionObject collision_object_point;
+ collision_object_point.setCollisionShape(&sphere_point);
+ collision_object_point.setWorldTransform(btTransform(btQuaternion::getIdentity(), bt_point));
+
+ // Setup query
+ GodotAllContactResultCallback btResult(&collision_object_point, r_results, p_result_max, &p_exclude);
+ btResult.m_collisionFilterGroup = p_collision_layer;
+ btResult.m_collisionFilterMask = p_object_type_mask;
+ space->dynamicsWorld->contactTest(&collision_object_point, btResult);
+
+ // The results is already populated by GodotAllConvexResultCallback
+ return btResult.m_count;
+}
+
+bool BulletPhysicsDirectSpaceState::intersect_ray(const Vector3 &p_from, const Vector3 &p_to, RayResult &r_result, const Set<RID> &p_exclude, uint32_t p_collision_layer, uint32_t p_object_type_mask, bool p_pick_ray) {
+
+ btVector3 btVec_from;
+ btVector3 btVec_to;
+
+ G_TO_B(p_from, btVec_from);
+ G_TO_B(p_to, btVec_to);
+
+ // setup query
+ GodotClosestRayResultCallback btResult(btVec_from, btVec_to, &p_exclude);
+ btResult.m_collisionFilterGroup = p_collision_layer;
+ btResult.m_collisionFilterMask = p_object_type_mask;
+ btResult.m_pickRay = p_pick_ray;
+
+ space->dynamicsWorld->rayTest(btVec_from, btVec_to, btResult);
+ if (btResult.hasHit()) {
+ B_TO_G(btResult.m_hitPointWorld, r_result.position);
+ B_TO_G(btResult.m_hitNormalWorld.normalize(), r_result.normal);
+ CollisionObjectBullet *gObj = static_cast<CollisionObjectBullet *>(btResult.m_collisionObject->getUserPointer());
+ if (gObj) {
+ r_result.shape = 0;
+ r_result.rid = gObj->get_self();
+ r_result.collider_id = gObj->get_instance_id();
+ r_result.collider = 0 == r_result.collider_id ? NULL : ObjectDB::get_instance(r_result.collider_id);
+ } else {
+ WARN_PRINTS("The raycast performed has hit a collision object that is not part of Godot scene, please check it.");
+ }
+ return true;
+ } else {
+ return false;
+ }
+}
+
+int BulletPhysicsDirectSpaceState::intersect_shape(const RID &p_shape, const Transform &p_xform, float p_margin, ShapeResult *p_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_layer, uint32_t p_object_type_mask) {
+ if (p_result_max <= 0)
+ return 0;
+
+ ShapeBullet *shape = space->get_physics_server()->get_shape_owner()->get(p_shape);
+
+ btCollisionShape *btShape = shape->create_bt_shape();
+ if (!btShape->isConvex()) {
+ bulletdelete(btShape);
+ ERR_PRINTS("The shape is not a convex shape, then is not supported: shape type: " + itos(shape->get_type()));
+ return 0;
+ }
+ btConvexShape *btConvex = static_cast<btConvexShape *>(btShape);
+
+ btVector3 scale_with_margin;
+ G_TO_B(p_xform.basis.get_scale(), scale_with_margin);
+ btConvex->setLocalScaling(scale_with_margin);
+
+ btTransform bt_xform;
+ G_TO_B(p_xform, bt_xform);
+
+ btCollisionObject collision_object;
+ collision_object.setCollisionShape(btConvex);
+ collision_object.setWorldTransform(bt_xform);
+
+ GodotAllContactResultCallback btQuery(&collision_object, p_results, p_result_max, &p_exclude);
+ btQuery.m_collisionFilterGroup = p_collision_layer;
+ btQuery.m_collisionFilterMask = p_object_type_mask;
+ btQuery.m_closestDistanceThreshold = p_margin;
+ space->dynamicsWorld->contactTest(&collision_object, btQuery);
+
+ bulletdelete(btConvex);
+
+ return btQuery.m_count;
+}
+
+bool BulletPhysicsDirectSpaceState::cast_motion(const RID &p_shape, const Transform &p_xform, const Vector3 &p_motion, float p_margin, float &p_closest_safe, float &p_closest_unsafe, const Set<RID> &p_exclude, uint32_t p_collision_layer, uint32_t p_object_type_mask, ShapeRestInfo *r_info) {
+ ShapeBullet *shape = space->get_physics_server()->get_shape_owner()->get(p_shape);
+
+ btCollisionShape *btShape = shape->create_bt_shape();
+ if (!btShape->isConvex()) {
+ bulletdelete(btShape);
+ ERR_PRINTS("The shape is not a convex shape, then is not supported: shape type: " + itos(shape->get_type()));
+ return 0;
+ }
+ btConvexShape *bt_convex_shape = static_cast<btConvexShape *>(btShape);
+
+ btVector3 bt_motion;
+ G_TO_B(p_motion, bt_motion);
+
+ btVector3 scale_with_margin;
+ G_TO_B(p_xform.basis.get_scale() + Vector3(p_margin, p_margin, p_margin), scale_with_margin);
+ bt_convex_shape->setLocalScaling(scale_with_margin);
+
+ btTransform bt_xform_from;
+ G_TO_B(p_xform, bt_xform_from);
+
+ btTransform bt_xform_to(bt_xform_from);
+ bt_xform_to.getOrigin() += bt_motion;
+
+ GodotClosestConvexResultCallback btResult(bt_xform_from.getOrigin(), bt_xform_to.getOrigin(), &p_exclude);
+ btResult.m_collisionFilterGroup = p_collision_layer;
+ btResult.m_collisionFilterMask = p_object_type_mask;
+
+ space->dynamicsWorld->convexSweepTest(bt_convex_shape, bt_xform_from, bt_xform_to, btResult, 0.002);
+
+ if (btResult.hasHit()) {
+ p_closest_safe = p_closest_unsafe = btResult.m_closestHitFraction;
+ if (r_info) {
+ if (btCollisionObject::CO_RIGID_BODY == btResult.m_hitCollisionObject->getInternalType()) {
+ B_TO_G(static_cast<const btRigidBody *>(btResult.m_hitCollisionObject)->getVelocityInLocalPoint(btResult.m_hitPointWorld), r_info->linear_velocity);
+ }
+ CollisionObjectBullet *collision_object = static_cast<CollisionObjectBullet *>(btResult.m_hitCollisionObject->getUserPointer());
+ B_TO_G(btResult.m_hitPointWorld, r_info->point);
+ B_TO_G(btResult.m_hitNormalWorld, r_info->normal);
+ r_info->rid = collision_object->get_self();
+ r_info->collider_id = collision_object->get_instance_id();
+ r_info->shape = btResult.m_shapeId;
+ }
+ }
+
+ bulletdelete(bt_convex_shape);
+ return btResult.hasHit();
+}
+
+/// Returns the list of contacts pairs in this order: Local contact, other body contact
+bool BulletPhysicsDirectSpaceState::collide_shape(RID p_shape, const Transform &p_shape_xform, float p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude, uint32_t p_collision_layer, uint32_t p_object_type_mask) {
+ if (p_result_max <= 0)
+ return 0;
+
+ ShapeBullet *shape = space->get_physics_server()->get_shape_owner()->get(p_shape);
+
+ btCollisionShape *btShape = shape->create_bt_shape();
+ if (!btShape->isConvex()) {
+ bulletdelete(btShape);
+ ERR_PRINTS("The shape is not a convex shape, then is not supported: shape type: " + itos(shape->get_type()));
+ return 0;
+ }
+ btConvexShape *btConvex = static_cast<btConvexShape *>(btShape);
+
+ btVector3 scale_with_margin;
+ G_TO_B(p_shape_xform.basis.get_scale(), scale_with_margin);
+ btConvex->setLocalScaling(scale_with_margin);
+
+ btTransform bt_xform;
+ G_TO_B(p_shape_xform, bt_xform);
+
+ btCollisionObject collision_object;
+ collision_object.setCollisionShape(btConvex);
+ collision_object.setWorldTransform(bt_xform);
+
+ GodotContactPairContactResultCallback btQuery(&collision_object, r_results, p_result_max, &p_exclude);
+ btQuery.m_collisionFilterGroup = p_collision_layer;
+ btQuery.m_collisionFilterMask = p_object_type_mask;
+ btQuery.m_closestDistanceThreshold = p_margin;
+ space->dynamicsWorld->contactTest(&collision_object, btQuery);
+
+ r_result_count = btQuery.m_count;
+ bulletdelete(btConvex);
+
+ return btQuery.m_count;
+}
+
+bool BulletPhysicsDirectSpaceState::rest_info(RID p_shape, const Transform &p_shape_xform, float p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude, uint32_t p_collision_layer, uint32_t p_object_type_mask) {
+
+ ShapeBullet *shape = space->get_physics_server()->get_shape_owner()->get(p_shape);
+
+ btCollisionShape *btShape = shape->create_bt_shape();
+ if (!btShape->isConvex()) {
+ bulletdelete(btShape);
+ ERR_PRINTS("The shape is not a convex shape, then is not supported: shape type: " + itos(shape->get_type()));
+ return 0;
+ }
+ btConvexShape *btConvex = static_cast<btConvexShape *>(btShape);
+
+ btVector3 scale_with_margin;
+ G_TO_B(p_shape_xform.basis.get_scale() + Vector3(p_margin, p_margin, p_margin), scale_with_margin);
+ btConvex->setLocalScaling(scale_with_margin);
+
+ btTransform bt_xform;
+ G_TO_B(p_shape_xform, bt_xform);
+
+ btCollisionObject collision_object;
+ collision_object.setCollisionShape(btConvex);
+ collision_object.setWorldTransform(bt_xform);
+
+ GodotRestInfoContactResultCallback btQuery(&collision_object, r_info, &p_exclude);
+ btQuery.m_collisionFilterGroup = p_collision_layer;
+ btQuery.m_collisionFilterMask = p_object_type_mask;
+ btQuery.m_closestDistanceThreshold = p_margin;
+ space->dynamicsWorld->contactTest(&collision_object, btQuery);
+
+ bulletdelete(btConvex);
+
+ if (btQuery.m_collided) {
+ if (btCollisionObject::CO_RIGID_BODY == btQuery.m_rest_info_collision_object->getInternalType()) {
+ B_TO_G(static_cast<const btRigidBody *>(btQuery.m_rest_info_collision_object)->getVelocityInLocalPoint(btQuery.m_rest_info_bt_point), r_info->linear_velocity);
+ }
+ B_TO_G(btQuery.m_rest_info_bt_point, r_info->point);
+ }
+
+ return btQuery.m_collided;
+}
+
+Vector3 BulletPhysicsDirectSpaceState::get_closest_point_to_object_volume(RID p_object, const Vector3 p_point) const {
+
+ RigidCollisionObjectBullet *rigid_object = space->get_physics_server()->get_rigid_collisin_object(p_object);
+ ERR_FAIL_COND_V(!rigid_object, Vector3());
+
+ btVector3 out_closest_point(0, 0, 0);
+ btScalar out_distance = 1e20;
+
+ btVector3 bt_point;
+ G_TO_B(p_point, bt_point);
+
+ btSphereShape point_shape(0.);
+
+ btCollisionShape *shape;
+ btConvexShape *convex_shape;
+ btTransform child_transform;
+ btTransform body_transform(rigid_object->get_bt_collision_object()->getWorldTransform());
+
+ btGjkPairDetector::ClosestPointInput input;
+ input.m_transformA.getBasis().setIdentity();
+ input.m_transformA.setOrigin(bt_point);
+
+ bool shapes_found = false;
+
+ btCompoundShape *compound = rigid_object->get_compound_shape();
+ for (int i = compound->getNumChildShapes() - 1; 0 <= i; --i) {
+ shape = compound->getChildShape(i);
+ if (shape->isConvex()) {
+ child_transform = compound->getChildTransform(i);
+ convex_shape = static_cast<btConvexShape *>(shape);
+
+ input.m_transformB = body_transform * child_transform;
+
+ btPointCollector result;
+ btGjkPairDetector gjk_pair_detector(&point_shape, convex_shape, space->gjk_simplex_solver, space->gjk_epa_pen_solver);
+ gjk_pair_detector.getClosestPoints(input, result, 0);
+
+ if (out_distance > result.m_distance) {
+ out_distance = result.m_distance;
+ out_closest_point = result.m_pointInWorld;
+ }
+ }
+ shapes_found = true;
+ }
+
+ if (shapes_found) {
+
+ Vector3 out;
+ B_TO_G(out_closest_point, out);
+ return out;
+ } else {
+
+ // no shapes found, use distance to origin.
+ return rigid_object->get_transform().get_origin();
+ }
+}
+
+SpaceBullet::SpaceBullet(bool p_create_soft_world)
+ : broadphase(NULL),
+ dispatcher(NULL),
+ solver(NULL),
+ collisionConfiguration(NULL),
+ dynamicsWorld(NULL),
+ soft_body_world_info(NULL),
+ ghostPairCallback(NULL),
+ godotFilterCallback(NULL),
+ gravityDirection(0, -1, 0),
+ gravityMagnitude(10),
+ contactDebugCount(0) {
+
+ create_empty_world(p_create_soft_world);
+ direct_access = memnew(BulletPhysicsDirectSpaceState(this));
+}
+
+SpaceBullet::~SpaceBullet() {
+ memdelete(direct_access);
+ destroy_world();
+}
+
+void SpaceBullet::flush_queries() {
+ const btCollisionObjectArray &colObjArray = dynamicsWorld->getCollisionObjectArray();
+ for (int i = colObjArray.size() - 1; 0 <= i; --i) {
+ static_cast<CollisionObjectBullet *>(colObjArray[i]->getUserPointer())->dispatch_callbacks();
+ }
+}
+
+void SpaceBullet::step(real_t p_delta_time) {
+ dynamicsWorld->stepSimulation(p_delta_time, 0, 0);
+}
+
+void SpaceBullet::set_param(PhysicsServer::AreaParameter p_param, const Variant &p_value) {
+ assert(dynamicsWorld);
+
+ switch (p_param) {
+ case PhysicsServer::AREA_PARAM_GRAVITY:
+ gravityMagnitude = p_value;
+ update_gravity();
+ break;
+ case PhysicsServer::AREA_PARAM_GRAVITY_VECTOR:
+ gravityDirection = p_value;
+ update_gravity();
+ break;
+ case PhysicsServer::AREA_PARAM_LINEAR_DAMP:
+ case PhysicsServer::AREA_PARAM_ANGULAR_DAMP:
+ break; // No damp
+ case PhysicsServer::AREA_PARAM_PRIORITY:
+ // Priority is always 0, the lower
+ break;
+ case PhysicsServer::AREA_PARAM_GRAVITY_IS_POINT:
+ case PhysicsServer::AREA_PARAM_GRAVITY_DISTANCE_SCALE:
+ case PhysicsServer::AREA_PARAM_GRAVITY_POINT_ATTENUATION:
+ break;
+ default:
+ WARN_PRINTS("This set parameter (" + itos(p_param) + ") is ignored, the SpaceBullet doesn't support it.");
+ break;
+ }
+}
+
+Variant SpaceBullet::get_param(PhysicsServer::AreaParameter p_param) {
+ switch (p_param) {
+ case PhysicsServer::AREA_PARAM_GRAVITY:
+ return gravityMagnitude;
+ case PhysicsServer::AREA_PARAM_GRAVITY_VECTOR:
+ return gravityDirection;
+ case PhysicsServer::AREA_PARAM_LINEAR_DAMP:
+ case PhysicsServer::AREA_PARAM_ANGULAR_DAMP:
+ return 0; // No damp
+ case PhysicsServer::AREA_PARAM_PRIORITY:
+ return 0; // Priority is always 0, the lower
+ case PhysicsServer::AREA_PARAM_GRAVITY_IS_POINT:
+ return false;
+ case PhysicsServer::AREA_PARAM_GRAVITY_DISTANCE_SCALE:
+ return 0;
+ case PhysicsServer::AREA_PARAM_GRAVITY_POINT_ATTENUATION:
+ return 0;
+ default:
+ WARN_PRINTS("This get parameter (" + itos(p_param) + ") is ignored, the SpaceBullet doesn't support it.");
+ return Variant();
+ }
+}
+
+void SpaceBullet::set_param(PhysicsServer::SpaceParameter p_param, real_t p_value) {
+ switch (p_param) {
+ case PhysicsServer::SPACE_PARAM_CONTACT_RECYCLE_RADIUS:
+ case PhysicsServer::SPACE_PARAM_CONTACT_MAX_SEPARATION:
+ case PhysicsServer::SPACE_PARAM_BODY_MAX_ALLOWED_PENETRATION:
+ case PhysicsServer::SPACE_PARAM_BODY_LINEAR_VELOCITY_SLEEP_THRESHOLD:
+ case PhysicsServer::SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_THRESHOLD:
+ case PhysicsServer::SPACE_PARAM_BODY_TIME_TO_SLEEP:
+ case PhysicsServer::SPACE_PARAM_BODY_ANGULAR_VELOCITY_DAMP_RATIO:
+ case PhysicsServer::SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS:
+ default:
+ WARN_PRINTS("This set parameter (" + itos(p_param) + ") is ignored, the SpaceBullet doesn't support it.");
+ break;
+ }
+}
+
+real_t SpaceBullet::get_param(PhysicsServer::SpaceParameter p_param) {
+ switch (p_param) {
+ case PhysicsServer::SPACE_PARAM_CONTACT_RECYCLE_RADIUS:
+ case PhysicsServer::SPACE_PARAM_CONTACT_MAX_SEPARATION:
+ case PhysicsServer::SPACE_PARAM_BODY_MAX_ALLOWED_PENETRATION:
+ case PhysicsServer::SPACE_PARAM_BODY_LINEAR_VELOCITY_SLEEP_THRESHOLD:
+ case PhysicsServer::SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_THRESHOLD:
+ case PhysicsServer::SPACE_PARAM_BODY_TIME_TO_SLEEP:
+ case PhysicsServer::SPACE_PARAM_BODY_ANGULAR_VELOCITY_DAMP_RATIO:
+ case PhysicsServer::SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS:
+ default:
+ WARN_PRINTS("The SpaceBullet doesn't support this get parameter (" + itos(p_param) + "), 0 is returned.");
+ return 0.f;
+ }
+}
+
+void SpaceBullet::add_area(AreaBullet *p_area) {
+ areas.push_back(p_area);
+ dynamicsWorld->addCollisionObject(p_area->get_bt_ghost(), p_area->get_collision_layer(), p_area->get_collision_mask());
+}
+
+void SpaceBullet::remove_area(AreaBullet *p_area) {
+ areas.erase(p_area);
+ dynamicsWorld->removeCollisionObject(p_area->get_bt_ghost());
+}
+
+void SpaceBullet::reload_collision_filters(AreaBullet *p_area) {
+ // This is necessary to change collision filter
+ dynamicsWorld->removeCollisionObject(p_area->get_bt_ghost());
+ dynamicsWorld->addCollisionObject(p_area->get_bt_ghost(), p_area->get_collision_layer(), p_area->get_collision_mask());
+}
+
+void SpaceBullet::add_rigid_body(RigidBodyBullet *p_body) {
+ if (p_body->is_static()) {
+ dynamicsWorld->addCollisionObject(p_body->get_bt_rigid_body(), p_body->get_collision_layer(), p_body->get_collision_mask());
+ } else {
+ dynamicsWorld->addRigidBody(p_body->get_bt_rigid_body(), p_body->get_collision_layer(), p_body->get_collision_mask());
+ }
+}
+
+void SpaceBullet::remove_rigid_body(RigidBodyBullet *p_body) {
+ if (p_body->is_static()) {
+ dynamicsWorld->removeCollisionObject(p_body->get_bt_rigid_body());
+ } else {
+ dynamicsWorld->removeRigidBody(p_body->get_bt_rigid_body());
+ }
+}
+
+void SpaceBullet::reload_collision_filters(RigidBodyBullet *p_body) {
+ // This is necessary to change collision filter
+ remove_rigid_body(p_body);
+ add_rigid_body(p_body);
+}
+
+void SpaceBullet::add_soft_body(SoftBodyBullet *p_body) {
+ if (is_using_soft_world()) {
+ if (p_body->get_bt_soft_body()) {
+ static_cast<btSoftRigidDynamicsWorld *>(dynamicsWorld)->addSoftBody(p_body->get_bt_soft_body(), p_body->get_collision_layer(), p_body->get_collision_mask());
+ }
+ } else {
+ ERR_PRINT("This soft body can't be added to non soft world");
+ }
+}
+
+void SpaceBullet::remove_soft_body(SoftBodyBullet *p_body) {
+ if (is_using_soft_world()) {
+ if (p_body->get_bt_soft_body()) {
+ static_cast<btSoftRigidDynamicsWorld *>(dynamicsWorld)->removeSoftBody(p_body->get_bt_soft_body());
+ }
+ }
+}
+
+void SpaceBullet::reload_collision_filters(SoftBodyBullet *p_body) {
+ // This is necessary to change collision filter
+ remove_soft_body(p_body);
+ add_soft_body(p_body);
+}
+
+void SpaceBullet::add_constraint(ConstraintBullet *p_constraint, bool disableCollisionsBetweenLinkedBodies) {
+ p_constraint->set_space(this);
+ dynamicsWorld->addConstraint(p_constraint->get_bt_constraint(), disableCollisionsBetweenLinkedBodies);
+}
+
+void SpaceBullet::remove_constraint(ConstraintBullet *p_constraint) {
+ dynamicsWorld->removeConstraint(p_constraint->get_bt_constraint());
+}
+
+int SpaceBullet::get_num_collision_objects() const {
+ return dynamicsWorld->getNumCollisionObjects();
+}
+
+void SpaceBullet::remove_all_collision_objects() {
+ for (int i = dynamicsWorld->getNumCollisionObjects() - 1; 0 <= i; --i) {
+ btCollisionObject *btObj = dynamicsWorld->getCollisionObjectArray()[i];
+ CollisionObjectBullet *colObj = static_cast<CollisionObjectBullet *>(btObj->getUserPointer());
+ colObj->set_space(NULL);
+ }
+}
+
+void onBulletPreTickCallback(btDynamicsWorld *p_dynamicsWorld, btScalar timeStep) {
+ static_cast<SpaceBullet *>(p_dynamicsWorld->getWorldUserInfo())->flush_queries();
+}
+
+void onBulletTickCallback(btDynamicsWorld *p_dynamicsWorld, btScalar timeStep) {
+
+ // Notify all Collision objects the collision checker is started
+ const btCollisionObjectArray &colObjArray = p_dynamicsWorld->getCollisionObjectArray();
+ for (int i = colObjArray.size() - 1; 0 <= i; --i) {
+ CollisionObjectBullet *colObj = static_cast<CollisionObjectBullet *>(colObjArray[i]->getUserPointer());
+ assert(NULL != colObj);
+ colObj->on_collision_checker_start();
+ }
+
+ SpaceBullet *sb = static_cast<SpaceBullet *>(p_dynamicsWorld->getWorldUserInfo());
+ sb->check_ghost_overlaps();
+ sb->check_body_collision();
+}
+
+BulletPhysicsDirectSpaceState *SpaceBullet::get_direct_state() {
+ return direct_access;
+}
+
+btScalar calculateGodotCombinedRestitution(const btCollisionObject *body0, const btCollisionObject *body1) {
+ return MAX(body0->getRestitution(), body1->getRestitution());
+}
+
+void SpaceBullet::create_empty_world(bool p_create_soft_world) {
+
+ gjk_epa_pen_solver = bulletnew(btGjkEpaPenetrationDepthSolver);
+ gjk_simplex_solver = bulletnew(btVoronoiSimplexSolver);
+ gjk_simplex_solver->setEqualVertexThreshold(0.f);
+
+ void *world_mem;
+ if (p_create_soft_world) {
+ world_mem = malloc(sizeof(btSoftRigidDynamicsWorld));
+ } else {
+ world_mem = malloc(sizeof(btDiscreteDynamicsWorld));
+ }
+
+ if (p_create_soft_world) {
+ collisionConfiguration = bulletnew(btSoftBodyRigidBodyCollisionConfiguration);
+ } else {
+ collisionConfiguration = bulletnew(GodotCollisionConfiguration(static_cast<btDiscreteDynamicsWorld *>(world_mem)));
+ }
+
+ dispatcher = bulletnew(GodotCollisionDispatcher(collisionConfiguration));
+ broadphase = bulletnew(btDbvtBroadphase);
+ solver = bulletnew(btSequentialImpulseConstraintSolver);
+
+ if (p_create_soft_world) {
+ dynamicsWorld = new (world_mem) btSoftRigidDynamicsWorld(dispatcher, broadphase, solver, collisionConfiguration);
+ soft_body_world_info = bulletnew(btSoftBodyWorldInfo);
+ } else {
+ dynamicsWorld = new (world_mem) btDiscreteDynamicsWorld(dispatcher, broadphase, solver, collisionConfiguration);
+ }
+
+ ghostPairCallback = bulletnew(btGhostPairCallback);
+ godotFilterCallback = bulletnew(GodotFilterCallback);
+ gCalculateCombinedRestitutionCallback = &calculateGodotCombinedRestitution;
+
+ dynamicsWorld->setWorldUserInfo(this);
+
+ dynamicsWorld->setInternalTickCallback(onBulletPreTickCallback, this, true);
+ dynamicsWorld->setInternalTickCallback(onBulletTickCallback, this, false);
+ dynamicsWorld->getBroadphase()->getOverlappingPairCache()->setInternalGhostPairCallback(ghostPairCallback); // Setup ghost check
+ dynamicsWorld->getPairCache()->setOverlapFilterCallback(godotFilterCallback);
+
+ if (soft_body_world_info) {
+ soft_body_world_info->m_broadphase = broadphase;
+ soft_body_world_info->m_dispatcher = dispatcher;
+ soft_body_world_info->m_sparsesdf.Initialize();
+ }
+
+ update_gravity();
+}
+
+void SpaceBullet::destroy_world() {
+
+ /// The world elements (like: Collision Objects, Constraints, Shapes) are managed by godot
+
+ dynamicsWorld->getBroadphase()->getOverlappingPairCache()->setInternalGhostPairCallback(NULL);
+ dynamicsWorld->getPairCache()->setOverlapFilterCallback(NULL);
+
+ bulletdelete(ghostPairCallback);
+ bulletdelete(godotFilterCallback);
+
+ // Deallocate world
+ dynamicsWorld->~btDiscreteDynamicsWorld();
+ free(dynamicsWorld);
+ dynamicsWorld = NULL;
+
+ bulletdelete(solver);
+ bulletdelete(broadphase);
+ bulletdelete(dispatcher);
+ bulletdelete(collisionConfiguration);
+ bulletdelete(soft_body_world_info);
+ bulletdelete(gjk_simplex_solver);
+ bulletdelete(gjk_epa_pen_solver);
+}
+
+void SpaceBullet::check_ghost_overlaps() {
+
+ /// Algorith support variables
+ btConvexShape *other_body_shape;
+ btConvexShape *area_shape;
+ btGjkPairDetector::ClosestPointInput gjk_input;
+ AreaBullet *area;
+ RigidCollisionObjectBullet *otherObject;
+ int x(-1), i(-1), y(-1), z(-1), indexOverlap(-1);
+
+ /// For each areas
+ for (x = areas.size() - 1; 0 <= x; --x) {
+ area = areas[x];
+
+ if (!area->is_monitoring())
+ continue;
+
+ /// 1. Reset all states
+ for (i = area->overlappingObjects.size() - 1; 0 <= i; --i) {
+ AreaBullet::OverlappingObjectData &otherObj = area->overlappingObjects[i];
+ // This check prevent the overwrite of ENTER state
+ // if this function is called more times before dispatchCallbacks
+ if (otherObj.state != AreaBullet::OVERLAP_STATE_ENTER) {
+ otherObj.state = AreaBullet::OVERLAP_STATE_DIRTY;
+ }
+ }
+
+ /// 2. Check all overlapping objects using GJK
+
+ const btAlignedObjectArray<btCollisionObject *> ghostOverlaps = area->get_bt_ghost()->getOverlappingPairs();
+
+ // For each overlapping
+ for (i = ghostOverlaps.size() - 1; 0 <= i; --i) {
+
+ if (!(ghostOverlaps[i]->getUserIndex() == CollisionObjectBullet::TYPE_RIGID_BODY || ghostOverlaps[i]->getUserIndex() == CollisionObjectBullet::TYPE_AREA))
+ continue;
+
+ otherObject = static_cast<RigidCollisionObjectBullet *>(ghostOverlaps[i]->getUserPointer());
+
+ bool hasOverlap = false;
+
+ // For each area shape
+ for (y = area->get_compound_shape()->getNumChildShapes() - 1; 0 <= y; --y) {
+ if (!area->get_compound_shape()->getChildShape(y)->isConvex())
+ continue;
+
+ gjk_input.m_transformA = area->get_transform__bullet() * area->get_compound_shape()->getChildTransform(y);
+ area_shape = static_cast<btConvexShape *>(area->get_compound_shape()->getChildShape(y));
+
+ // For each other object shape
+ for (z = otherObject->get_compound_shape()->getNumChildShapes() - 1; 0 <= z; --z) {
+
+ if (!otherObject->get_compound_shape()->getChildShape(z)->isConvex())
+ continue;
+
+ other_body_shape = static_cast<btConvexShape *>(otherObject->get_compound_shape()->getChildShape(z));
+ gjk_input.m_transformB = otherObject->get_transform__bullet() * otherObject->get_compound_shape()->getChildTransform(z);
+
+ btPointCollector result;
+ btGjkPairDetector gjk_pair_detector(area_shape, other_body_shape, gjk_simplex_solver, gjk_epa_pen_solver);
+ gjk_pair_detector.getClosestPoints(gjk_input, result, 0);
+
+ if (0 >= result.m_distance) {
+ hasOverlap = true;
+ goto collision_found;
+ }
+ } // ~For each other object shape
+ } // ~For each area shape
+
+ collision_found:
+ if (!hasOverlap)
+ continue;
+
+ indexOverlap = area->find_overlapping_object(otherObject);
+ if (-1 == indexOverlap) {
+ // Not found
+ area->add_overlap(otherObject);
+ } else {
+ // Found
+ area->put_overlap_as_inside(indexOverlap);
+ }
+ }
+
+ /// 3. Remove not overlapping
+ for (i = area->overlappingObjects.size() - 1; 0 <= i; --i) {
+ // If the overlap has DIRTY state it means that it's no more overlapping
+ if (area->overlappingObjects[i].state == AreaBullet::OVERLAP_STATE_DIRTY) {
+ area->put_overlap_as_exit(i);
+ }
+ }
+ }
+}
+
+void SpaceBullet::check_body_collision() {
+#ifdef DEBUG_ENABLED
+ reset_debug_contact_count();
+#endif
+
+ const int numManifolds = dynamicsWorld->getDispatcher()->getNumManifolds();
+ for (int i = 0; i < numManifolds; ++i) {
+ btPersistentManifold *contactManifold = dynamicsWorld->getDispatcher()->getManifoldByIndexInternal(i);
+
+ // I know this static cast is a bit risky. But I'm checking its type just after it.
+ // This allow me to avoid a lot of other cast and checks
+ RigidBodyBullet *bodyA = static_cast<RigidBodyBullet *>(contactManifold->getBody0()->getUserPointer());
+ RigidBodyBullet *bodyB = static_cast<RigidBodyBullet *>(contactManifold->getBody1()->getUserPointer());
+
+ if (CollisionObjectBullet::TYPE_RIGID_BODY == bodyA->getType() && CollisionObjectBullet::TYPE_RIGID_BODY == bodyB->getType()) {
+ if (!bodyA->can_add_collision() && !bodyB->can_add_collision()) {
+ continue;
+ }
+
+ const int numContacts = contactManifold->getNumContacts();
+#define REPORT_ALL_CONTACTS 0
+#if REPORT_ALL_CONTACTS
+ for (int j = 0; j < numContacts; j++) {
+ btManifoldPoint &pt = contactManifold->getContactPoint(j);
+#else
+ // Since I don't need report all contacts for these objects, I'll report only the first
+ if (numContacts) {
+ btManifoldPoint &pt = contactManifold->getContactPoint(0);
+#endif
+ Vector3 collisionWorldPosition;
+ Vector3 collisionLocalPosition;
+ Vector3 normalOnB;
+ B_TO_G(pt.m_normalWorldOnB, normalOnB);
+
+ if (bodyA->can_add_collision()) {
+ B_TO_G(pt.getPositionWorldOnB(), collisionWorldPosition);
+ /// pt.m_localPointB Doesn't report the exact point in local space
+ B_TO_G(pt.getPositionWorldOnB() - contactManifold->getBody1()->getWorldTransform().getOrigin(), collisionLocalPosition);
+ bodyA->add_collision_object(bodyB, collisionWorldPosition, collisionLocalPosition, normalOnB, pt.m_index1, pt.m_index0);
+ }
+ if (bodyB->can_add_collision()) {
+ B_TO_G(pt.getPositionWorldOnA(), collisionWorldPosition);
+ /// pt.m_localPointA Doesn't report the exact point in local space
+ B_TO_G(pt.getPositionWorldOnA() - contactManifold->getBody0()->getWorldTransform().getOrigin(), collisionLocalPosition);
+ bodyB->add_collision_object(bodyA, collisionWorldPosition, collisionLocalPosition, normalOnB * -1, pt.m_index0, pt.m_index1);
+ }
+
+#ifdef DEBUG_ENABLED
+ if (is_debugging_contacts()) {
+ add_debug_contact(collisionWorldPosition);
+ }
+#endif
+ }
+ }
+ }
+}
+
+void SpaceBullet::update_gravity() {
+ btVector3 btGravity;
+ G_TO_B(gravityDirection * gravityMagnitude, btGravity);
+ //dynamicsWorld->setGravity(btGravity);
+ dynamicsWorld->setGravity(btVector3(0, 0, 0));
+ if (soft_body_world_info) {
+ soft_body_world_info->m_gravity = btGravity;
+ }
+}
+
+/// IMPORTANT: Please don't turn it ON this is not managed correctly!!
+/// I'm leaving this here just for future tests.
+/// Debug motion and normal vector drawing
+#define debug_test_motion 0
+#define PERFORM_INITIAL_UNSTACK 1
+
+#if debug_test_motion
+
+#include "scene/3d/immediate_geometry.h"
+
+static ImmediateGeometry *motionVec(NULL);
+static ImmediateGeometry *normalLine(NULL);
+static Ref<SpatialMaterial> red_mat;
+static Ref<SpatialMaterial> blue_mat;
+#endif
+
+#define IGNORE_AREAS_TRUE true
+bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_from, const Vector3 &p_motion, PhysicsServer::MotionResult *r_result) {
+
+#if debug_test_motion
+ /// Yes I know this is not good, but I've used it as fast debugging hack.
+ /// I'm leaving it here just for speedup the other eventual debugs
+ if (!normalLine) {
+ motionVec = memnew(ImmediateGeometry);
+ normalLine = memnew(ImmediateGeometry);
+ SceneTree::get_singleton()->get_current_scene()->add_child(motionVec);
+ SceneTree::get_singleton()->get_current_scene()->add_child(normalLine);
+
+ red_mat = Ref<SpatialMaterial>(memnew(SpatialMaterial));
+ red_mat->set_flag(SpatialMaterial::FLAG_UNSHADED, true);
+ red_mat->set_line_width(20.0);
+ red_mat->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true);
+ red_mat->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
+ red_mat->set_flag(SpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true);
+ red_mat->set_albedo(Color(1, 0, 0, 1));
+ motionVec->set_material_override(red_mat);
+
+ blue_mat = Ref<SpatialMaterial>(memnew(SpatialMaterial));
+ blue_mat->set_flag(SpatialMaterial::FLAG_UNSHADED, true);
+ blue_mat->set_line_width(20.0);
+ blue_mat->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true);
+ blue_mat->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
+ blue_mat->set_flag(SpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true);
+ blue_mat->set_albedo(Color(0, 0, 1, 1));
+ normalLine->set_material_override(blue_mat);
+ }
+#endif
+
+ ///// Release all generated manifolds
+ //{
+ // if(p_body->get_kinematic_utilities()){
+ // for(int i= p_body->get_kinematic_utilities()->m_generatedManifold.size()-1; 0<=i; --i){
+ // dispatcher->releaseManifold( p_body->get_kinematic_utilities()->m_generatedManifold[i] );
+ // }
+ // p_body->get_kinematic_utilities()->m_generatedManifold.clear();
+ // }
+ //}
+
+ btVector3 recover_initial_position(0, 0, 0);
+
+ btTransform body_safe_position;
+ G_TO_B(p_from, body_safe_position);
+
+ { /// Phase one - multi shapes depenetration using margin
+#if PERFORM_INITIAL_UNSTACK
+ if (recover_from_penetration(p_body, body_safe_position, recover_initial_position)) {
+
+ // Add recover position to "From" and "To" transforms
+ body_safe_position.getOrigin() += recover_initial_position;
+ }
+#endif
+ }
+
+ btVector3 recovered_motion;
+ G_TO_B(p_motion, recovered_motion);
+ const int shape_count(p_body->get_shape_count());
+
+ { /// phase two - sweep test, from a secure position without margin
+
+#if debug_test_motion
+ Vector3 sup_line;
+ B_TO_G(body_safe_position.getOrigin(), sup_line);
+ motionVec->clear();
+ motionVec->begin(Mesh::PRIMITIVE_LINES, NULL);
+ motionVec->add_vertex(sup_line);
+ motionVec->add_vertex(sup_line + p_motion * 10);
+ motionVec->end();
+#endif
+
+ for (int shIndex = 0; shIndex < shape_count; ++shIndex) {
+ if (p_body->is_shape_disabled(shIndex)) {
+ continue;
+ }
+
+ if (!p_body->get_bt_shape(shIndex)->isConvex()) {
+ // Skip no convex shape
+ continue;
+ }
+ btConvexShape *convex_shape_test(static_cast<btConvexShape *>(p_body->get_bt_shape(shIndex)));
+
+ btTransform shape_world_from;
+ G_TO_B(p_body->get_shape_transform(shIndex), shape_world_from);
+
+ // Add local shape transform
+ shape_world_from = body_safe_position * shape_world_from;
+
+ btTransform shape_world_to(shape_world_from);
+ shape_world_to.getOrigin() += recovered_motion;
+
+ GodotKinClosestConvexResultCallback btResult(shape_world_from.getOrigin(), shape_world_to.getOrigin(), p_body, IGNORE_AREAS_TRUE);
+ btResult.m_collisionFilterGroup = p_body->get_collision_layer();
+ btResult.m_collisionFilterMask = p_body->get_collision_mask();
+
+ dynamicsWorld->convexSweepTest(convex_shape_test, shape_world_from, shape_world_to, btResult, 0.002);
+
+ if (btResult.hasHit()) {
+ /// Since for each sweep test I fix the motion of new shapes in base the recover result,
+ /// if another shape will hit something it means that has a deepest penetration respect the previous shape
+ recovered_motion *= btResult.m_closestHitFraction;
+ }
+ }
+ }
+
+ bool hasPenetration = false;
+
+ { /// Phase three - Recover + contact test with margin
+
+ RecoverResult r_recover_result;
+
+ hasPenetration = recover_from_penetration(p_body, body_safe_position, recovered_motion, &r_recover_result);
+
+ if (r_result) {
+
+ B_TO_G(recovered_motion + recover_initial_position, r_result->motion);
+
+ if (hasPenetration) {
+ const btRigidBody *btRigid = static_cast<const btRigidBody *>(r_recover_result.other_collision_object);
+ CollisionObjectBullet *collisionObject = static_cast<CollisionObjectBullet *>(btRigid->getUserPointer());
+
+ r_result->remainder = p_motion - r_result->motion; // is the remaining movements
+ B_TO_G(r_recover_result.pointWorld, r_result->collision_point);
+ B_TO_G(r_recover_result.pointNormalWorld, r_result->collision_normal);
+ B_TO_G(btRigid->getVelocityInLocalPoint(r_recover_result.pointWorld - btRigid->getWorldTransform().getOrigin()), r_result->collider_velocity); // It calculates velocity at point and assign it using special function Bullet_to_Godot
+ r_result->collider = collisionObject->get_self();
+ r_result->collider_id = collisionObject->get_instance_id();
+ r_result->collider_shape = r_recover_result.other_compound_shape_index;
+ r_result->collision_local_shape = r_recover_result.local_shape_most_recovered;
+
+//{ /// Add manifold point to manage collisions
+// btPersistentManifold* manifold = dynamicsWorld->getDispatcher()->getNewManifold(p_body->getBtBody(), btRigid);
+// btManifoldPoint manifoldPoint(result_callabck.m_pointWorld, result_callabck.m_pointWorld, result_callabck.m_pointNormalWorld, result_callabck.m_penetration_distance);
+// manifoldPoint.m_index0 = r_result->collision_local_shape;
+// manifoldPoint.m_index1 = r_result->collider_shape;
+// manifold->addManifoldPoint(manifoldPoint);
+// p_body->get_kinematic_utilities()->m_generatedManifold.push_back(manifold);
+//}
+
+#if debug_test_motion
+ Vector3 sup_line2;
+ B_TO_G(recovered_motion, sup_line2);
+ //Vector3 sup_pos;
+ //B_TO_G( pt.getPositionWorldOnB(), sup_pos);
+ normalLine->clear();
+ normalLine->begin(Mesh::PRIMITIVE_LINES, NULL);
+ normalLine->add_vertex(r_result->collision_point);
+ normalLine->add_vertex(r_result->collision_point + r_result->collision_normal * 10);
+ normalLine->end();
+#endif
+
+ } else {
+ r_result->remainder = Vector3();
+ }
+ }
+ }
+
+ return hasPenetration;
+}
+
+struct RecoverPenetrationBroadPhaseCallback : public btBroadphaseAabbCallback {
+private:
+ const btCollisionObject *self_collision_object;
+ uint32_t collision_layer;
+ uint32_t collision_mask;
+
+public:
+ Vector<btCollisionObject *> result_collision_objects;
+
+public:
+ RecoverPenetrationBroadPhaseCallback(const btCollisionObject *p_self_collision_object, uint32_t p_collision_layer, uint32_t p_collision_mask)
+ : self_collision_object(p_self_collision_object),
+ collision_layer(p_collision_layer),
+ collision_mask(p_collision_mask) {}
+
+ virtual ~RecoverPenetrationBroadPhaseCallback() {}
+
+ virtual bool process(const btBroadphaseProxy *proxy) {
+
+ btCollisionObject *co = static_cast<btCollisionObject *>(proxy->m_clientObject);
+ if (co->getInternalType() <= btCollisionObject::CO_RIGID_BODY) {
+ if (self_collision_object != proxy->m_clientObject && GodotFilterCallback::test_collision_filters(collision_layer, collision_mask, proxy->m_collisionFilterGroup, proxy->m_collisionFilterMask)) {
+ result_collision_objects.push_back(co);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ void reset() {
+ result_collision_objects.empty();
+ }
+};
+
+bool SpaceBullet::recover_from_penetration(RigidBodyBullet *p_body, const btTransform &p_body_position, btVector3 &r_recover_position, RecoverResult *r_recover_result) {
+
+ RecoverPenetrationBroadPhaseCallback recover_broad_result(p_body->get_bt_collision_object(), p_body->get_collision_layer(), p_body->get_collision_mask());
+
+ btTransform body_shape_position;
+ btTransform body_shape_position_recovered;
+
+ // Broad phase support
+ btVector3 minAabb, maxAabb;
+
+ bool penetration = false;
+
+ // For each shape
+ for (int kinIndex = p_body->get_kinematic_utilities()->shapes.size() - 1; 0 <= kinIndex; --kinIndex) {
+
+ recover_broad_result.reset();
+
+ const RigidBodyBullet::KinematicShape &kin_shape(p_body->get_kinematic_utilities()->shapes[kinIndex]);
+ if (!kin_shape.is_active()) {
+ continue;
+ }
+
+ body_shape_position = p_body_position * kin_shape.transform;
+ body_shape_position_recovered = body_shape_position;
+ body_shape_position_recovered.getOrigin() += r_recover_position;
+
+ kin_shape.shape->getAabb(body_shape_position_recovered, minAabb, maxAabb);
+ dynamicsWorld->getBroadphase()->aabbTest(minAabb, maxAabb, recover_broad_result);
+
+ for (int i = recover_broad_result.result_collision_objects.size() - 1; 0 <= i; --i) {
+ btCollisionObject *otherObject = recover_broad_result.result_collision_objects[i];
+ if (!p_body->get_bt_collision_object()->checkCollideWith(otherObject) || !otherObject->checkCollideWith(p_body->get_bt_collision_object()))
+ continue;
+
+ if (otherObject->getCollisionShape()->isCompound()) {
+
+ // Each convex shape
+ btCompoundShape *cs = static_cast<btCompoundShape *>(otherObject->getCollisionShape());
+ for (int x = cs->getNumChildShapes() - 1; 0 <= x; --x) {
+
+ if (cs->getChildShape(x)->isConvex()) {
+ if (RFP_convex_convex_test(kin_shape.shape, static_cast<const btConvexShape *>(cs->getChildShape(x)), otherObject, x, body_shape_position, otherObject->getWorldTransform() * cs->getChildTransform(x), r_recover_position, r_recover_result)) {
+
+ penetration = true;
+ }
+ } else {
+ if (RFP_convex_world_test(kin_shape.shape, cs->getChildShape(x), p_body->get_bt_collision_object(), otherObject, kinIndex, x, body_shape_position, otherObject->getWorldTransform() * cs->getChildTransform(x), r_recover_position, r_recover_result)) {
+
+ penetration = true;
+ }
+ }
+ }
+ } else if (otherObject->getCollisionShape()->isConvex()) { /// Execute GJK test against object shape
+ if (RFP_convex_convex_test(kin_shape.shape, static_cast<const btConvexShape *>(otherObject->getCollisionShape()), otherObject, 0, body_shape_position, otherObject->getWorldTransform(), r_recover_position, r_recover_result)) {
+
+ penetration = true;
+ }
+ } else {
+ if (RFP_convex_world_test(kin_shape.shape, otherObject->getCollisionShape(), p_body->get_bt_collision_object(), otherObject, kinIndex, 0, body_shape_position, otherObject->getWorldTransform(), r_recover_position, r_recover_result)) {
+
+ penetration = true;
+ }
+ }
+ }
+ }
+
+ return penetration;
+}
+
+bool SpaceBullet::RFP_convex_convex_test(const btConvexShape *p_shapeA, const btConvexShape *p_shapeB, btCollisionObject *p_objectB, int p_shapeId_B, const btTransform &p_transformA, const btTransform &p_transformB, btVector3 &r_recover_position, RecoverResult *r_recover_result) {
+
+ // Initialize GJK input
+ btGjkPairDetector::ClosestPointInput gjk_input;
+ gjk_input.m_transformA = p_transformA;
+ gjk_input.m_transformA.getOrigin() += r_recover_position;
+ gjk_input.m_transformB = p_transformB;
+
+ // Perform GJK test
+ btPointCollector result;
+ btGjkPairDetector gjk_pair_detector(p_shapeA, p_shapeB, gjk_simplex_solver, gjk_epa_pen_solver);
+ gjk_pair_detector.getClosestPoints(gjk_input, result, 0);
+ if (0 > result.m_distance) {
+ // Has penetration
+ r_recover_position += result.m_normalOnBInWorld * (result.m_distance * -1);
+
+ if (r_recover_result) {
+
+ r_recover_result->hasPenetration = true;
+ r_recover_result->other_collision_object = p_objectB;
+ r_recover_result->other_compound_shape_index = p_shapeId_B;
+ r_recover_result->penetration_distance = result.m_distance;
+ r_recover_result->pointNormalWorld = result.m_normalOnBInWorld;
+ r_recover_result->pointWorld = result.m_pointInWorld;
+ }
+ return true;
+ }
+ return false;
+}
+
+bool SpaceBullet::RFP_convex_world_test(const btConvexShape *p_shapeA, const btCollisionShape *p_shapeB, btCollisionObject *p_objectA, btCollisionObject *p_objectB, int p_shapeId_A, int p_shapeId_B, const btTransform &p_transformA, const btTransform &p_transformB, btVector3 &r_recover_position, RecoverResult *r_recover_result) {
+
+ /// Contact test
+
+ btTransform p_recovered_transformA(p_transformA);
+ p_recovered_transformA.getOrigin() += r_recover_position;
+
+ btCollisionObjectWrapper obA(NULL, p_shapeA, p_objectA, p_recovered_transformA, -1, p_shapeId_A);
+ btCollisionObjectWrapper obB(NULL, p_shapeB, p_objectB, p_transformB, -1, p_shapeId_B);
+
+ btCollisionAlgorithm *algorithm = dispatcher->findAlgorithm(&obA, &obB, NULL, BT_CLOSEST_POINT_ALGORITHMS);
+ if (algorithm) {
+ GodotDeepPenetrationContactResultCallback contactPointResult(&obA, &obB);
+ //discrete collision detection query
+ algorithm->processCollision(&obA, &obB, dynamicsWorld->getDispatchInfo(), &contactPointResult);
+
+ algorithm->~btCollisionAlgorithm();
+ dispatcher->freeCollisionAlgorithm(algorithm);
+
+ if (contactPointResult.hasHit()) {
+ r_recover_position += contactPointResult.m_pointNormalWorld * (contactPointResult.m_penetration_distance * -1);
+
+ if (r_recover_result) {
+
+ r_recover_result->hasPenetration = true;
+ r_recover_result->other_collision_object = p_objectB;
+ r_recover_result->other_compound_shape_index = p_shapeId_B;
+ r_recover_result->penetration_distance = contactPointResult.m_penetration_distance;
+ r_recover_result->pointNormalWorld = contactPointResult.m_pointNormalWorld;
+ r_recover_result->pointWorld = contactPointResult.m_pointWorld;
+ }
+ return true;
+ }
+ }
+ return false;
+}
diff --git a/modules/bullet/space_bullet.h b/modules/bullet/space_bullet.h
new file mode 100644
index 0000000000..9acac9a7d6
--- /dev/null
+++ b/modules/bullet/space_bullet.h
@@ -0,0 +1,200 @@
+/*************************************************************************/
+/* space_bullet.h */
+/* Author: AndreaCatania */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef SPACE_BULLET_H
+#define SPACE_BULLET_H
+
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
+#include "LinearMath/btScalar.h"
+#include "LinearMath/btTransform.h"
+#include "LinearMath/btVector3.h"
+#include "core/variant.h"
+#include "core/vector.h"
+#include "godot_result_callbacks.h"
+#include "rid_bullet.h"
+#include "servers/physics_server.h"
+
+class AreaBullet;
+class btBroadphaseInterface;
+class btCollisionDispatcher;
+class btConstraintSolver;
+class btDefaultCollisionConfiguration;
+class btDynamicsWorld;
+class btDiscreteDynamicsWorld;
+class btEmptyShape;
+class btGhostPairCallback;
+class btSoftRigidDynamicsWorld;
+class btSoftBodyWorldInfo;
+class ConstraintBullet;
+class CollisionObjectBullet;
+class RigidBodyBullet;
+class SpaceBullet;
+class SoftBodyBullet;
+class btGjkEpaPenetrationDepthSolver;
+
+class BulletPhysicsDirectSpaceState : public PhysicsDirectSpaceState {
+ GDCLASS(BulletPhysicsDirectSpaceState, PhysicsDirectSpaceState)
+private:
+ SpaceBullet *space;
+
+public:
+ BulletPhysicsDirectSpaceState(SpaceBullet *p_space);
+
+ virtual int intersect_point(const Vector3 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, uint32_t p_object_type_mask = TYPE_MASK_COLLISION);
+ virtual bool intersect_ray(const Vector3 &p_from, const Vector3 &p_to, RayResult &r_result, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, uint32_t p_object_type_mask = TYPE_MASK_COLLISION, bool p_pick_ray = false);
+ virtual int intersect_shape(const RID &p_shape, const Transform &p_xform, float p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, uint32_t p_object_type_mask = TYPE_MASK_COLLISION);
+ virtual bool cast_motion(const RID &p_shape, const Transform &p_xform, const Vector3 &p_motion, float p_margin, float &p_closest_safe, float &p_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, uint32_t p_object_type_mask = TYPE_MASK_COLLISION, ShapeRestInfo *r_info = NULL);
+ /// Returns the list of contacts pairs in this order: Local contact, other body contact
+ virtual bool collide_shape(RID p_shape, const Transform &p_shape_xform, float p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, uint32_t p_object_type_mask = TYPE_MASK_COLLISION);
+ virtual bool rest_info(RID p_shape, const Transform &p_shape_xform, float p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, uint32_t p_object_type_mask = TYPE_MASK_COLLISION);
+ virtual Vector3 get_closest_point_to_object_volume(RID p_object, const Vector3 p_point) const;
+};
+
+class SpaceBullet : public RIDBullet {
+private:
+ friend class AreaBullet;
+ friend void onBulletTickCallback(btDynamicsWorld *world, btScalar timeStep);
+ friend class BulletPhysicsDirectSpaceState;
+
+ btBroadphaseInterface *broadphase;
+ btDefaultCollisionConfiguration *collisionConfiguration;
+ btCollisionDispatcher *dispatcher;
+ btConstraintSolver *solver;
+ btDiscreteDynamicsWorld *dynamicsWorld;
+ btGhostPairCallback *ghostPairCallback;
+ GodotFilterCallback *godotFilterCallback;
+ btSoftBodyWorldInfo *soft_body_world_info;
+
+ btGjkEpaPenetrationDepthSolver *gjk_epa_pen_solver;
+ btVoronoiSimplexSolver *gjk_simplex_solver;
+
+ BulletPhysicsDirectSpaceState *direct_access;
+ Vector3 gravityDirection;
+ real_t gravityMagnitude;
+
+ Vector<AreaBullet *> areas;
+
+ Vector<Vector3> contactDebug;
+ int contactDebugCount;
+
+public:
+ SpaceBullet(bool p_create_soft_world);
+ virtual ~SpaceBullet();
+
+ void flush_queries();
+ void step(real_t p_delta_time);
+
+ _FORCE_INLINE_ btBroadphaseInterface *get_broadphase() { return broadphase; }
+ _FORCE_INLINE_ btCollisionDispatcher *get_dispatcher() { return dispatcher; }
+ _FORCE_INLINE_ btSoftBodyWorldInfo *get_soft_body_world_info() { return soft_body_world_info; }
+ _FORCE_INLINE_ bool is_using_soft_world() { return soft_body_world_info; }
+
+ /// Used to set some parameters to Bullet world
+ /// @param p_param:
+ /// AREA_PARAM_GRAVITY to set the gravity magnitude of entire world
+ /// AREA_PARAM_GRAVITY_VECTOR to set the gravity direction of entire world
+ void set_param(PhysicsServer::AreaParameter p_param, const Variant &p_value);
+ /// Used to get some parameters to Bullet world
+ /// @param p_param:
+ /// AREA_PARAM_GRAVITY to get the gravity magnitude of entire world
+ /// AREA_PARAM_GRAVITY_VECTOR to get the gravity direction of entire world
+ Variant get_param(PhysicsServer::AreaParameter p_param);
+
+ void set_param(PhysicsServer::SpaceParameter p_param, real_t p_value);
+ real_t get_param(PhysicsServer::SpaceParameter p_param);
+
+ void add_area(AreaBullet *p_area);
+ void remove_area(AreaBullet *p_area);
+ void reload_collision_filters(AreaBullet *p_area);
+
+ void add_rigid_body(RigidBodyBullet *p_body);
+ void remove_rigid_body(RigidBodyBullet *p_body);
+ void reload_collision_filters(RigidBodyBullet *p_body);
+
+ void add_soft_body(SoftBodyBullet *p_body);
+ void remove_soft_body(SoftBodyBullet *p_body);
+ void reload_collision_filters(SoftBodyBullet *p_body);
+
+ void add_constraint(ConstraintBullet *p_constraint, bool disableCollisionsBetweenLinkedBodies = false);
+ void remove_constraint(ConstraintBullet *p_constraint);
+
+ int get_num_collision_objects() const;
+ void remove_all_collision_objects();
+
+ BulletPhysicsDirectSpaceState *get_direct_state();
+
+ void set_debug_contacts(int p_amount) { contactDebug.resize(p_amount); }
+ _FORCE_INLINE_ bool is_debugging_contacts() const { return !contactDebug.empty(); }
+ _FORCE_INLINE_ void reset_debug_contact_count() {
+ contactDebugCount = 0;
+ }
+ _FORCE_INLINE_ void add_debug_contact(const Vector3 &p_contact) {
+ if (contactDebugCount < contactDebug.size()) contactDebug[contactDebugCount++] = p_contact;
+ }
+ _FORCE_INLINE_ Vector<Vector3> get_debug_contacts() { return contactDebug; }
+ _FORCE_INLINE_ int get_debug_contact_count() { return contactDebugCount; }
+
+ const Vector3 &get_gravity_direction() const { return gravityDirection; }
+ real_t get_gravity_magnitude() const { return gravityMagnitude; }
+
+ void update_gravity();
+
+ bool test_body_motion(RigidBodyBullet *p_body, const Transform &p_from, const Vector3 &p_motion, PhysicsServer::MotionResult *r_result);
+
+private:
+ void create_empty_world(bool p_create_soft_world);
+ void destroy_world();
+ void check_ghost_overlaps();
+ void check_body_collision();
+
+ struct RecoverResult {
+ bool hasPenetration;
+ btVector3 pointNormalWorld;
+ btVector3 pointWorld;
+ btScalar penetration_distance; // Negative is penetration
+ int other_compound_shape_index;
+ const btCollisionObject *other_collision_object;
+ int local_shape_most_recovered;
+
+ RecoverResult()
+ : hasPenetration(false) {}
+ };
+
+ bool recover_from_penetration(RigidBodyBullet *p_body, const btTransform &p_from, btVector3 &r_recover_position, RecoverResult *r_recover_result = NULL);
+ /// This is an API that recover a kinematic object from penetration
+ /// This allow only Convex Convex test and it always use GJK algorithm, With this API we don't benefit of Bullet special accelerated functions
+ bool RFP_convex_convex_test(const btConvexShape *p_shapeA, const btConvexShape *p_shapeB, btCollisionObject *p_objectB, int p_shapeId_B, const btTransform &p_transformA, const btTransform &p_transformB, btVector3 &r_recover_position, RecoverResult *r_recover_result);
+ /// This is an API that recover a kinematic object from penetration
+ /// Using this we leave Bullet to select the best algorithm, For example GJK in case we have Convex Convex, or a Bullet accelerated algorithm
+ bool RFP_convex_world_test(const btConvexShape *p_shapeA, const btCollisionShape *p_shapeB, btCollisionObject *p_objectA, btCollisionObject *p_objectB, int p_shapeId_A, int p_shapeId_B, const btTransform &p_transformA, const btTransform &p_transformB, btVector3 &r_recover_position, RecoverResult *r_recover_result);
+};
+#endif
diff --git a/modules/dds/config.py b/modules/dds/config.py
index fb920482f5..5f133eba90 100644
--- a/modules/dds/config.py
+++ b/modules/dds/config.py
@@ -1,7 +1,5 @@
-
def can_build(platform):
return True
-
def configure(env):
pass
diff --git a/modules/enet/config.py b/modules/enet/config.py
index fb920482f5..8031fbb4b6 100644
--- a/modules/enet/config.py
+++ b/modules/enet/config.py
@@ -1,7 +1,13 @@
-
def can_build(platform):
return True
-
def configure(env):
pass
+
+def get_doc_classes():
+ return [
+ "NetworkedMultiplayerENet",
+ ]
+
+def get_doc_path():
+ return "doc_classes"
diff --git a/doc/classes/NetworkedMultiplayerENet.xml b/modules/enet/doc_classes/NetworkedMultiplayerENet.xml
index 02c919bd83..70ef6aef20 100644
--- a/doc/classes/NetworkedMultiplayerENet.xml
+++ b/modules/enet/doc_classes/NetworkedMultiplayerENet.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="NetworkedMultiplayerENet" inherits="NetworkedMultiplayerPeer" category="Core" version="3.0.alpha.custom_build">
+<class name="NetworkedMultiplayerENet" inherits="NetworkedMultiplayerPeer" category="Core" version="3.0-alpha">
<brief_description>
PacketPeer implementation using the ENet library.
</brief_description>
diff --git a/modules/enet/networked_multiplayer_enet.cpp b/modules/enet/networked_multiplayer_enet.cpp
index c50886ad3c..1e18ec0d18 100644
--- a/modules/enet/networked_multiplayer_enet.cpp
+++ b/modules/enet/networked_multiplayer_enet.cpp
@@ -505,7 +505,7 @@ uint32_t NetworkedMultiplayerENet::_gen_unique_id() const {
hash = hash_djb2_one_32(
(uint32_t)OS::get_singleton()->get_unix_time(), hash);
hash = hash_djb2_one_32(
- (uint32_t)OS::get_singleton()->get_data_dir().hash64(), hash);
+ (uint32_t)OS::get_singleton()->get_user_data_dir().hash64(), hash);
/*
hash = hash_djb2_one_32(
(uint32_t)OS::get_singleton()->get_unique_id().hash64(), hash );
diff --git a/modules/etc/config.py b/modules/etc/config.py
index 7dc2cb59c1..395fc1bb02 100644
--- a/modules/etc/config.py
+++ b/modules/etc/config.py
@@ -1,8 +1,6 @@
-
def can_build(platform):
return True
-
def configure(env):
# Tools only, disabled for non-tools
# TODO: Find a cleaner way to achieve that
diff --git a/modules/etc/image_etc.cpp b/modules/etc/image_etc.cpp
index dc7d23bbd7..941df41694 100644
--- a/modules/etc/image_etc.cpp
+++ b/modules/etc/image_etc.cpp
@@ -129,7 +129,7 @@ static void _compress_etc(Image *p_img, float p_lossy_quality, bool force_etc1_f
PoolVector<uint8_t>::Read r = img->get_data().read();
int target_size = Image::get_image_data_size(imgw, imgh, etc_format, p_img->has_mipmaps() ? -1 : 0);
- int mmc = p_img->has_mipmaps() ? Image::get_image_required_mipmaps(imgw, imgh, etc_format) : 0;
+ int mmc = 1 + (p_img->has_mipmaps() ? Image::get_image_required_mipmaps(imgw, imgh, etc_format) : 0);
PoolVector<uint8_t> dst_data;
dst_data.resize(target_size);
@@ -155,7 +155,7 @@ static void _compress_etc(Image *p_img, float p_lossy_quality, bool force_etc1_f
print_line("begin encoding, format: " + Image::get_format_name(etc_format));
uint64_t t = OS::get_singleton()->get_ticks_msec();
- for (int i = 0; i < mmc + 1; i++) {
+ for (int i = 0; i < mmc; i++) {
// convert source image to internal etc2comp format (which is equivalent to Image::FORMAT_RGBAF)
// NOTE: We can alternatively add a case to Image::convert to handle Image::FORMAT_RGBAF conversion.
int mipmap_ofs = 0, mipmap_size = 0, mipmap_w = 0, mipmap_h = 0;
@@ -163,9 +163,9 @@ static void _compress_etc(Image *p_img, float p_lossy_quality, bool force_etc1_f
const uint8_t *src = &r[mipmap_ofs];
Etc::ColorFloatRGBA *src_rgba_f = new Etc::ColorFloatRGBA[mipmap_w * mipmap_h];
- for (int i = 0; i < mipmap_w * mipmap_h; i++) {
- int si = i * 4; // RGBA8
- src_rgba_f[i] = Etc::ColorFloatRGBA::ConvertFromRGBA8(src[si], src[si + 1], src[si + 2], src[si + 3]);
+ for (int j = 0; j < mipmap_w * mipmap_h; j++) {
+ int si = j * 4; // RGBA8
+ src_rgba_f[j] = Etc::ColorFloatRGBA::ConvertFromRGBA8(src[si], src[si + 1], src[si + 2], src[si + 3]);
}
unsigned char *etc_data = NULL;
@@ -173,15 +173,17 @@ static void _compress_etc(Image *p_img, float p_lossy_quality, bool force_etc1_f
unsigned int extended_width = 0, extended_height = 0;
Etc::Encode((float *)src_rgba_f, mipmap_w, mipmap_h, etc2comp_etc_format, error_metric, effort, num_cpus, num_cpus, &etc_data, &etc_data_len, &extended_width, &extended_height, &encoding_time);
+ CRASH_COND(wofs + etc_data_len > target_size);
memcpy(&w[wofs], etc_data, etc_data_len);
wofs += etc_data_len;
delete[] etc_data;
delete[] src_rgba_f;
}
+
print_line("time encoding: " + rtos(OS::get_singleton()->get_ticks_msec() - t));
- p_img->create(imgw, imgh, mmc > 1 ? true : false, etc_format, dst_data);
+ p_img->create(imgw, imgh, p_img->has_mipmaps(), etc_format, dst_data);
}
static void _compress_etc1(Image *p_img, float p_lossy_quality) {
diff --git a/modules/freetype/config.py b/modules/freetype/config.py
index fb920482f5..5f133eba90 100644
--- a/modules/freetype/config.py
+++ b/modules/freetype/config.py
@@ -1,7 +1,5 @@
-
def can_build(platform):
return True
-
def configure(env):
pass
diff --git a/modules/gdnative/SCsub b/modules/gdnative/SCsub
index be0975b53c..485bf4b9df 100644
--- a/modules/gdnative/SCsub
+++ b/modules/gdnative/SCsub
@@ -12,35 +12,81 @@ gdn_env.add_source_files(env.modules_sources, "nativescript/*.cpp")
gdn_env.Append(CPPPATH=['#modules/gdnative/include/'])
+SConscript("arvr/SCsub")
+SConscript("pluginscript/SCsub")
+
def _spaced(e):
return e if e[-1] == '*' else e + ' '
def _build_gdnative_api_struct_header(api):
+ ext_wrappers = ''
+
+ for name in api['extensions']:
+ ext_wrappers += ' extern const godot_gdnative_ext_' + name + '_api_struct *_gdnative_wrapper_' + name + '_api_struct;'
+
+ ext_init = 'for (int i = 0; i < _gdnative_wrapper_api_struct->num_extensions; i++) { '
+ ext_init += 'switch (_gdnative_wrapper_api_struct->extensions[i]->type) {'
+
+ for name in api['extensions']:
+ ext_init += 'case GDNATIVE_EXT_' + api['extensions'][name]['type'] + ': '
+ ext_init += '_gdnative_wrapper_' + name + '_api_struct = (' + 'godot_gdnative_ext_' + name + '_api_struct *) _gdnative_wrapper_api_struct->extensions[i]; break;'
+
+ ext_init += '}'
+
out = [
'/* THIS FILE IS GENERATED DO NOT EDIT */',
'#ifndef GODOT_GDNATIVE_API_STRUCT_H',
'#define GODOT_GDNATIVE_API_STRUCT_H',
'',
'#include <gdnative/gdnative.h>',
+ '#include <arvr/godot_arvr.h>',
'#include <nativescript/godot_nativescript.h>',
+ '#include <pluginscript/godot_pluginscript.h>',
'',
- '#define GDNATIVE_API_INIT(options) do { extern const godot_gdnative_api_struct *_gdnative_wrapper_api_struct; _gdnative_wrapper_api_struct = options->api_struct; } while (0)',
+ '#define GDNATIVE_API_INIT(options) do { extern const godot_gdnative_api_struct *_gdnative_wrapper_api_struct;' + ext_wrappers + ' _gdnative_wrapper_api_struct = options->api_struct; ' + ext_init + ' } while (0)',
'',
'#ifdef __cplusplus',
'extern "C" {',
'#endif',
'',
- 'typedef struct godot_gdnative_api_struct {',
- '\tvoid *next;',
- '\tconst char *version;',
+ 'enum GDNATIVE_API_TYPES {',
+ '\tGDNATIVE_' + api['core']['type'] + ','
+ ]
+
+ for name in api['extensions']:
+ out += ['\tGDNATIVE_EXT_' + api['extensions'][name]['type'] + ',']
+
+ out += ['};', '']
+
+ for name in api['extensions']:
+ out += [
+ 'typedef struct godot_gdnative_ext_' + name + '_api_struct {',
+ '\tunsigned int type;',
+ '\tgodot_gdnative_api_version version;',
+ '\tconst godot_gdnative_api_struct *next;'
+ ]
+
+ for funcdef in api['extensions'][name]['api']:
+ args = ', '.join(['%s%s' % (_spaced(t), n) for t, n in funcdef['arguments']])
+ out.append('\t%s(*%s)(%s);' % (_spaced(funcdef['return_type']), funcdef['name'], args))
+
+ out += ['} godot_gdnative_ext_' + name + '_api_struct;', '']
+
+ out += [
+ 'typedef struct godot_gdnative_core_api_struct {',
+ '\tunsigned int type;',
+ '\tgodot_gdnative_api_version version;',
+ '\tconst godot_gdnative_api_struct *next;',
+ '\tunsigned int num_extensions;',
+ '\tconst godot_gdnative_api_struct **extensions;',
]
- for funcname, funcdef in api['api'].items():
+ for funcdef in api['core']['api']:
args = ', '.join(['%s%s' % (_spaced(t), n) for t, n in funcdef['arguments']])
- out.append('\t%s(*%s)(%s);' % (_spaced(funcdef['return_type']), funcname, args))
+ out.append('\t%s(*%s)(%s);' % (_spaced(funcdef['return_type']), funcdef['name'], args))
out += [
- '} godot_gdnative_api_struct;',
+ '} godot_gdnative_core_api_struct;',
'',
'#ifdef __cplusplus',
'}',
@@ -56,15 +102,40 @@ def _build_gdnative_api_struct_source(api):
'/* THIS FILE IS GENERATED DO NOT EDIT */',
'',
'#include <gdnative_api_struct.gen.h>',
- '',
- 'const char *_gdnative_api_version = "%s";' % api['version'],
- 'extern const godot_gdnative_api_struct api_struct = {',
+ ''
+ ]
+
+ for name in api['extensions']:
+ out += [
+ 'extern const godot_gdnative_ext_' + name + '_api_struct api_extension_' + name + '_struct = {',
+ '\tGDNATIVE_EXT_' + api['extensions'][name]['type'] + ',',
+ '\t{' + str(api['extensions'][name]['version']['major']) + ', ' + str(api['extensions'][name]['version']['minor']) + '},',
+ '\tNULL,'
+ ]
+
+ for funcdef in api['extensions'][name]['api']:
+ out.append('\t%s,' % funcdef['name'])
+
+ out += ['};\n']
+
+ out += ['', 'const godot_gdnative_api_struct *gdnative_extensions_pointers[] = {']
+
+ for name in api['extensions']:
+ out += ['\t(godot_gdnative_api_struct *)&api_extension_' + name + '_struct,']
+
+ out += ['};\n']
+
+ out += [
+ 'extern const godot_gdnative_core_api_struct api_struct = {',
+ '\tGDNATIVE_' + api['core']['type'] + ',',
+ '\t{' + str(api['core']['version']['major']) + ', ' + str(api['core']['version']['minor']) + '},',
'\tNULL,',
- '\t_gdnative_api_version,',
+ '\t' + str(len(api['extensions'])) + ',',
+ '\tgdnative_extensions_pointers,',
]
- for funcname in api['api'].keys():
- out.append('\t%s,' % funcname)
+ for funcdef in api['core']['api']:
+ out.append('\t%s,' % funcdef['name'])
out.append('};\n')
return '\n'.join(out)
@@ -74,8 +145,7 @@ def build_gdnative_api_struct(target, source, env):
from collections import OrderedDict
with open(source[0].path, 'r') as fd:
- # Keep the json ordered
- api = json.load(fd, object_pairs_hook=OrderedDict)
+ api = json.load(fd)
header, source = target
with open(header.path, 'w') as fd:
@@ -96,30 +166,50 @@ def _build_gdnative_wrapper_code(api):
'',
'#include <gdnative/gdnative.h>',
'#include <nativescript/godot_nativescript.h>',
+ '#include <pluginscript/godot_pluginscript.h>',
+ '#include <arvr/godot_arvr.h>',
'',
'#include <gdnative_api_struct.gen.h>',
'',
- 'godot_gdnative_api_struct *_gdnative_wrapper_api_struct = 0;',
- '',
'#ifdef __cplusplus',
'extern "C" {',
'#endif',
- ''
+ '',
+ 'godot_gdnative_core_api_struct *_gdnative_wrapper_api_struct = 0;',
]
- for funcname, funcdef in api['api'].items():
+ for name in api['extensions']:
+ out.append('godot_gdnative_ext_' + name + '_api_struct *_gdnative_wrapper_' + name + '_api_struct;')
+
+ out += ['']
+
+ for funcdef in api['core']['api']:
args = ', '.join(['%s%s' % (_spaced(t), n) for t, n in funcdef['arguments']])
- out.append('%s %s(%s) {' % (_spaced(funcdef['return_type']), funcname, args))
+ out.append('%s%s(%s) {' % (_spaced(funcdef['return_type']), funcdef['name'], args))
args = ', '.join(['%s' % n for t, n in funcdef['arguments']])
return_line = '\treturn ' if funcdef['return_type'] != 'void' else '\t'
- return_line += '_gdnative_wrapper_api_struct->' + funcname + '(' + args + ');'
+ return_line += '_gdnative_wrapper_api_struct->' + funcdef['name'] + '(' + args + ');'
out.append(return_line)
out.append('}')
out.append('')
+ for name in api['extensions']:
+ for funcdef in api['extensions'][name]['api']:
+ args = ', '.join(['%s%s' % (_spaced(t), n) for t, n in funcdef['arguments']])
+ out.append('%s%s(%s) {' % (_spaced(funcdef['return_type']), funcdef['name'], args))
+
+ args = ', '.join(['%s' % n for t, n in funcdef['arguments']])
+
+ return_line = '\treturn ' if funcdef['return_type'] != 'void' else '\t'
+ return_line += '_gdnative_wrapper_' + name + '_api_struct->' + funcdef['name'] + '(' + args + ');'
+
+ out.append(return_line)
+ out.append('}')
+ out.append('')
+
out += [
'#ifdef __cplusplus',
'}',
@@ -132,7 +222,6 @@ def _build_gdnative_wrapper_code(api):
def build_gdnative_wrapper_code(target, source, env):
import json
with open(source[0].path, 'r') as fd:
-#Keep the json ordered
api = json.load(fd)
wrapper_file = target[0]
@@ -143,7 +232,7 @@ def build_gdnative_wrapper_code(target, source, env):
if ARGUMENTS.get('gdnative_wrapper', False):
#build wrapper code
- gdn_env.Command('gdnative_wrapper_code.gen.cpp', 'gdnative_api.json', build_gdnative_wrapper_code)
+ gensource, = gdn_env.Command('gdnative_wrapper_code.gen.cpp', 'gdnative_api.json', build_gdnative_wrapper_code)
gd_wrapper_env = env.Clone()
gd_wrapper_env.Append(CPPPATH=['#modules/gdnative/include/'])
@@ -151,4 +240,4 @@ if ARGUMENTS.get('gdnative_wrapper', False):
# I think this doesn't work on MSVC yet...
gd_wrapper_env.Append(CCFLAGS=['-fPIC'])
- gd_wrapper_env.Library("#bin/gdnative_wrapper_code", ["#modules/gdnative/gdnative_wrapper_code.gen.cpp"])
+ gd_wrapper_env.Library("#bin/gdnative_wrapper_code", [gensource])
diff --git a/modules/gdnative/arvr/SCsub b/modules/gdnative/arvr/SCsub
new file mode 100644
index 0000000000..ecc5996108
--- /dev/null
+++ b/modules/gdnative/arvr/SCsub
@@ -0,0 +1,13 @@
+#!/usr/bin/env python
+
+import os
+import methods
+
+Import('env')
+Import('env_modules')
+
+env_arvr_gdnative = env_modules.Clone()
+
+env_arvr_gdnative.Append(CPPPATH=['#modules/gdnative/include/'])
+env_arvr_gdnative.add_source_files(env.modules_sources, '*.cpp')
+
diff --git a/modules/gdnative/arvr/arvr_interface_gdnative.cpp b/modules/gdnative/arvr/arvr_interface_gdnative.cpp
new file mode 100644
index 0000000000..02f2ee7424
--- /dev/null
+++ b/modules/gdnative/arvr/arvr_interface_gdnative.cpp
@@ -0,0 +1,398 @@
+/*************************************************************************/
+/* arvr_interface_gdnative.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "arvr_interface_gdnative.h"
+#include "main/input_default.h"
+#include "servers/arvr/arvr_positional_tracker.h"
+#include "servers/visual/visual_server_global.h"
+
+ARVRInterfaceGDNative::ARVRInterfaceGDNative() {
+ // testing
+ printf("Construct gdnative interface\n");
+
+ // we won't have our data pointer until our library gets set
+ data = NULL;
+
+ interface = NULL;
+}
+
+ARVRInterfaceGDNative::~ARVRInterfaceGDNative() {
+ printf("Destruct gdnative interface\n");
+
+ if (is_initialized()) {
+ uninitialize();
+ };
+
+ // cleanup after ourselves
+ cleanup();
+}
+
+void ARVRInterfaceGDNative::cleanup() {
+ if (interface != NULL) {
+ interface->destructor(data);
+ data = NULL;
+ interface = NULL;
+ }
+}
+
+void ARVRInterfaceGDNative::set_interface(const godot_arvr_interface_gdnative *p_interface) {
+ // this should only be called once, just being paranoid..
+ if (interface) {
+ cleanup();
+ }
+
+ // bind to our interface
+ interface = p_interface;
+
+ // Now we do our constructing...
+ data = interface->constructor((godot_object *)this);
+}
+
+StringName ARVRInterfaceGDNative::get_name() const {
+
+ ERR_FAIL_COND_V(interface == NULL, StringName());
+
+ godot_string result = interface->get_name(data);
+
+ StringName name = *(String *)&result;
+
+ godot_string_destroy(&result);
+
+ return name;
+}
+
+int ARVRInterfaceGDNative::get_capabilities() const {
+ int capabilities;
+
+ ERR_FAIL_COND_V(interface == NULL, 0); // 0 = None
+
+ capabilities = interface->get_capabilities(data);
+
+ return capabilities;
+}
+
+bool ARVRInterfaceGDNative::get_anchor_detection_is_enabled() const {
+ bool enabled;
+
+ ERR_FAIL_COND_V(interface == NULL, false);
+
+ enabled = interface->get_anchor_detection_is_enabled(data);
+
+ return enabled;
+}
+
+void ARVRInterfaceGDNative::set_anchor_detection_is_enabled(bool p_enable) {
+
+ ERR_FAIL_COND(interface == NULL);
+
+ interface->set_anchor_detection_is_enabled(data, p_enable);
+}
+
+bool ARVRInterfaceGDNative::is_stereo() {
+ bool stereo;
+
+ ERR_FAIL_COND_V(interface == NULL, false);
+
+ stereo = interface->is_stereo(data);
+
+ return stereo;
+}
+
+bool ARVRInterfaceGDNative::is_initialized() {
+ bool initialized;
+
+ ERR_FAIL_COND_V(interface == NULL, false);
+
+ initialized = interface->is_initialized(data);
+
+ return initialized;
+}
+
+bool ARVRInterfaceGDNative::initialize() {
+ bool initialized;
+
+ ERR_FAIL_COND_V(interface == NULL, false);
+
+ initialized = interface->initialize(data);
+
+ if (initialized) {
+ // if we successfully initialize our interface and we don't have a primary interface yet, this becomes our primary interface
+
+ ARVRServer *arvr_server = ARVRServer::get_singleton();
+ if ((arvr_server != NULL) && (arvr_server->get_primary_interface() == NULL)) {
+ arvr_server->set_primary_interface(this);
+ };
+ };
+
+ return initialized;
+}
+
+void ARVRInterfaceGDNative::uninitialize() {
+ ERR_FAIL_COND(interface == NULL);
+
+ ARVRServer *arvr_server = ARVRServer::get_singleton();
+ if (arvr_server != NULL) {
+ // Whatever happens, make sure this is no longer our primary interface
+ arvr_server->clear_primary_interface_if(this);
+ }
+
+ interface->uninitialize(data);
+}
+
+Size2 ARVRInterfaceGDNative::get_render_targetsize() {
+
+ ERR_FAIL_COND_V(interface == NULL, Size2());
+
+ godot_vector2 result = interface->get_render_targetsize(data);
+ Vector2 *vec = (Vector2 *)&result;
+
+ return *vec;
+}
+
+Transform ARVRInterfaceGDNative::get_transform_for_eye(ARVRInterface::Eyes p_eye, const Transform &p_cam_transform) {
+ Transform *ret;
+
+ ERR_FAIL_COND_V(interface == NULL, Transform());
+
+ godot_transform t = interface->get_transform_for_eye(data, (int)p_eye, (godot_transform *)&p_cam_transform);
+
+ ret = (Transform *)&t;
+
+ return *ret;
+}
+
+CameraMatrix ARVRInterfaceGDNative::get_projection_for_eye(ARVRInterface::Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far) {
+ CameraMatrix cm;
+
+ ERR_FAIL_COND_V(interface == NULL, CameraMatrix());
+
+ interface->fill_projection_for_eye(data, (godot_real *)cm.matrix, (godot_int)p_eye, p_aspect, p_z_near, p_z_far);
+
+ return cm;
+}
+
+void ARVRInterfaceGDNative::commit_for_eye(ARVRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect) {
+
+ ERR_FAIL_COND(interface == NULL);
+
+ interface->commit_for_eye(data, (godot_int)p_eye, (godot_rid *)&p_render_target, (godot_rect2 *)&p_screen_rect);
+}
+
+void ARVRInterfaceGDNative::process() {
+ ERR_FAIL_COND(interface == NULL);
+
+ interface->process(data);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////
+// some helper callbacks
+
+extern "C" {
+
+void GDAPI godot_arvr_register_interface(const godot_arvr_interface_gdnative *p_interface) {
+ Ref<ARVRInterfaceGDNative> new_interface;
+ new_interface.instance();
+ new_interface->set_interface((godot_arvr_interface_gdnative * const)p_interface);
+ ARVRServer::get_singleton()->add_interface(new_interface);
+}
+
+godot_real GDAPI godot_arvr_get_worldscale() {
+ ARVRServer *arvr_server = ARVRServer::get_singleton();
+ ERR_FAIL_NULL_V(arvr_server, 1.0);
+
+ return arvr_server->get_world_scale();
+}
+
+godot_transform GDAPI godot_arvr_get_reference_frame() {
+ godot_transform reference_frame;
+ Transform *reference_frame_ptr = (Transform *)&reference_frame;
+
+ ARVRServer *arvr_server = ARVRServer::get_singleton();
+ if (arvr_server != NULL) {
+ *reference_frame_ptr = arvr_server->get_reference_frame();
+ } else {
+ godot_transform_new_identity(&reference_frame);
+ }
+
+ return reference_frame;
+}
+
+void GDAPI godot_arvr_blit(godot_int p_eye, godot_rid *p_render_target, godot_rect2 *p_rect) {
+ // blits out our texture as is, handy for preview display of one of the eyes that is already rendered with lens distortion on an external HMD
+ ARVRInterface::Eyes eye = (ARVRInterface::Eyes)p_eye;
+ RID *render_target = (RID *)p_render_target;
+ Rect2 screen_rect = *(Rect2 *)p_rect;
+
+ if (eye == ARVRInterface::EYE_LEFT) {
+ screen_rect.size.x /= 2.0;
+ } else if (p_eye == ARVRInterface::EYE_RIGHT) {
+ screen_rect.size.x /= 2.0;
+ screen_rect.position.x += screen_rect.size.x;
+ }
+
+ VSG::rasterizer->set_current_render_target(RID());
+ VSG::rasterizer->blit_render_target_to_screen(*render_target, screen_rect, 0);
+}
+
+godot_int GDAPI godot_arvr_get_texid(godot_rid *p_render_target) {
+ // In order to send off our textures to display on our hardware we need the opengl texture ID instead of the render target RID
+ // This is a handy function to expose that.
+ RID *render_target = (RID *)p_render_target;
+
+ RID eye_texture = VSG::storage->render_target_get_texture(*render_target);
+ uint32_t texid = VS::get_singleton()->texture_get_texid(eye_texture);
+
+ return texid;
+}
+
+godot_int GDAPI godot_arvr_add_controller(char *p_device_name, godot_int p_hand, godot_bool p_tracks_orientation, godot_bool p_tracks_position) {
+ ARVRServer *arvr_server = ARVRServer::get_singleton();
+ ERR_FAIL_NULL_V(arvr_server, 0);
+
+ InputDefault *input = (InputDefault *)Input::get_singleton();
+ ERR_FAIL_NULL_V(input, 0);
+
+ ARVRPositionalTracker *new_tracker = memnew(ARVRPositionalTracker);
+ new_tracker->set_name(p_device_name);
+ new_tracker->set_type(ARVRServer::TRACKER_CONTROLLER);
+ if (p_hand == 1) {
+ new_tracker->set_hand(ARVRPositionalTracker::TRACKER_LEFT_HAND);
+ } else if (p_hand == 2) {
+ new_tracker->set_hand(ARVRPositionalTracker::TRACKER_RIGHT_HAND);
+ }
+
+ // also register as joystick...
+ int joyid = input->get_unused_joy_id();
+ if (joyid != -1) {
+ new_tracker->set_joy_id(joyid);
+ input->joy_connection_changed(joyid, true, p_device_name, "");
+ }
+
+ if (p_tracks_orientation) {
+ Basis orientation;
+ new_tracker->set_orientation(orientation);
+ }
+ if (p_tracks_position) {
+ Vector3 position;
+ new_tracker->set_position(position);
+ }
+
+ // add our tracker to our server and remember its pointer
+ arvr_server->add_tracker(new_tracker);
+
+ // note, this ID is only unique within controllers!
+ return new_tracker->get_tracker_id();
+}
+
+void GDAPI godot_arvr_remove_controller(godot_int p_controller_id) {
+ ARVRServer *arvr_server = ARVRServer::get_singleton();
+ ERR_FAIL_NULL(arvr_server);
+
+ InputDefault *input = (InputDefault *)Input::get_singleton();
+ ERR_FAIL_NULL(input);
+
+ ARVRPositionalTracker *remove_tracker = arvr_server->find_by_type_and_id(ARVRServer::TRACKER_CONTROLLER, p_controller_id);
+ if (remove_tracker != NULL) {
+ // unset our joystick if applicable
+ int joyid = remove_tracker->get_joy_id();
+ if (joyid != -1) {
+ input->joy_connection_changed(joyid, false, "", "");
+ remove_tracker->set_joy_id(-1);
+ }
+
+ // remove our tracker from our server
+ arvr_server->remove_tracker(remove_tracker);
+ memdelete(remove_tracker);
+ }
+}
+
+void GDAPI godot_arvr_set_controller_transform(godot_int p_controller_id, godot_transform *p_transform, godot_bool p_tracks_orientation, godot_bool p_tracks_position) {
+ ARVRServer *arvr_server = ARVRServer::get_singleton();
+ ERR_FAIL_NULL(arvr_server);
+
+ ARVRPositionalTracker *tracker = arvr_server->find_by_type_and_id(ARVRServer::TRACKER_CONTROLLER, p_controller_id);
+ if (tracker != NULL) {
+ Transform *transform = (Transform *)p_transform;
+ if (p_tracks_orientation) {
+ tracker->set_orientation(transform->basis);
+ }
+ if (p_tracks_position) {
+ tracker->set_position(transform->origin);
+ }
+ }
+}
+
+void GDAPI godot_arvr_set_controller_button(godot_int p_controller_id, godot_int p_button, godot_bool p_is_pressed) {
+ ARVRServer *arvr_server = ARVRServer::get_singleton();
+ ERR_FAIL_NULL(arvr_server);
+
+ InputDefault *input = (InputDefault *)Input::get_singleton();
+ ERR_FAIL_NULL(input);
+
+ ARVRPositionalTracker *tracker = arvr_server->find_by_type_and_id(ARVRServer::TRACKER_CONTROLLER, p_controller_id);
+ if (tracker != NULL) {
+ int joyid = tracker->get_joy_id();
+ if (joyid != -1) {
+ input->joy_button(joyid, p_button, p_is_pressed);
+ }
+ }
+}
+
+void GDAPI godot_arvr_set_controller_axis(godot_int p_controller_id, godot_int p_axis, godot_real p_value, godot_bool p_can_be_negative) {
+ ARVRServer *arvr_server = ARVRServer::get_singleton();
+ ERR_FAIL_NULL(arvr_server);
+
+ InputDefault *input = (InputDefault *)Input::get_singleton();
+ ERR_FAIL_NULL(input);
+
+ ARVRPositionalTracker *tracker = arvr_server->find_by_type_and_id(ARVRServer::TRACKER_CONTROLLER, p_controller_id);
+ if (tracker != NULL) {
+ int joyid = tracker->get_joy_id();
+ if (joyid != -1) {
+ InputDefault::JoyAxis jx;
+ jx.min = p_can_be_negative ? -1 : 0;
+ jx.value = p_value;
+ input->joy_axis(joyid, p_axis, jx);
+ }
+ }
+}
+
+godot_real GDAPI godot_arvr_get_controller_rumble(godot_int p_controller_id) {
+ ARVRServer *arvr_server = ARVRServer::get_singleton();
+ ERR_FAIL_NULL_V(arvr_server, 0.0);
+
+ ARVRPositionalTracker *tracker = arvr_server->find_by_type_and_id(ARVRServer::TRACKER_CONTROLLER, p_controller_id);
+ if (tracker != NULL) {
+ return tracker->get_rumble();
+ }
+
+ return 0.0;
+}
+}
diff --git a/modules/gdnative/arvr/arvr_interface_gdnative.h b/modules/gdnative/arvr/arvr_interface_gdnative.h
new file mode 100644
index 0000000000..96f7b580d5
--- /dev/null
+++ b/modules/gdnative/arvr/arvr_interface_gdnative.h
@@ -0,0 +1,86 @@
+/*************************************************************************/
+/* arvr_interface_gdnative.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef ARVR_INTERFACE_GDNATIVE_H
+#define ARVR_INTERFACE_GDNATIVE_H
+
+#include "modules/gdnative/gdnative.h"
+#include "servers/arvr/arvr_interface.h"
+
+/**
+ @authors Hinsbart & Karroffel & Mux213
+
+ This subclass of our AR/VR interface forms a bridge to GDNative.
+*/
+
+class ARVRInterfaceGDNative : public ARVRInterface {
+ GDCLASS(ARVRInterfaceGDNative, ARVRInterface)
+
+ void cleanup();
+
+protected:
+ const godot_arvr_interface_gdnative *interface;
+ void *data;
+
+public:
+ /** general interface information **/
+ ARVRInterfaceGDNative();
+ ~ARVRInterfaceGDNative();
+
+ void set_interface(const godot_arvr_interface_gdnative *p_interface);
+
+ virtual StringName get_name() const;
+ virtual int get_capabilities() const;
+
+ virtual bool is_initialized();
+ virtual bool initialize();
+ virtual void uninitialize();
+
+ /** specific to AR **/
+ virtual bool get_anchor_detection_is_enabled() const;
+ virtual void set_anchor_detection_is_enabled(bool p_enable);
+
+ /** rendering and internal **/
+ virtual Size2 get_render_targetsize();
+ virtual bool is_stereo();
+ virtual Transform get_transform_for_eye(ARVRInterface::Eyes p_eye, const Transform &p_cam_transform);
+
+ // we expose a PoolVector<float> version of this function to GDNative
+ PoolVector<float> _get_projection_for_eye(ARVRInterface::Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far);
+
+ // and a CameraMatrix version to ARVRServer
+ virtual CameraMatrix get_projection_for_eye(ARVRInterface::Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far);
+
+ virtual void commit_for_eye(ARVRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect);
+
+ virtual void process();
+};
+
+#endif // ARVR_INTERFACE_GDNATIVE_H
diff --git a/modules/gdnative/arvr/config.py b/modules/gdnative/arvr/config.py
new file mode 100644
index 0000000000..4d1bdfe4d1
--- /dev/null
+++ b/modules/gdnative/arvr/config.py
@@ -0,0 +1,5 @@
+def can_build(platform):
+ return True
+
+def configure(env):
+ pass
diff --git a/misc/dist/ios_xcode/godot_ios/main.m b/modules/gdnative/arvr/register_types.cpp
index bb63364d8f..139750a02d 100644
--- a/misc/dist/ios_xcode/godot_ios/main.m
+++ b/modules/gdnative/arvr/register_types.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* main.m */
+/* register_types.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,12 +28,12 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#import <UIKit/UIKit.h>
+#include "register_types.h"
+#include "arvr_interface_gdnative.h"
-#import "AppDelegate.h"
+void register_arvr_types() {
+ ClassDB::register_class<ARVRInterfaceGDNative>();
+}
-int main(int argc, char *argv[]) {
- @autoreleasepool {
- return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
- }
+void unregister_arvr_types() {
}
diff --git a/modules/gdnative/arvr/register_types.h b/modules/gdnative/arvr/register_types.h
new file mode 100644
index 0000000000..4918319926
--- /dev/null
+++ b/modules/gdnative/arvr/register_types.h
@@ -0,0 +1,32 @@
+/*************************************************************************/
+/* register_types.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 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. */
+/*************************************************************************/
+
+void register_arvr_types();
+void unregister_arvr_types();
diff --git a/modules/gdnative/config.py b/modules/gdnative/config.py
index 9f57b9bb74..68148c4d87 100644
--- a/modules/gdnative/config.py
+++ b/modules/gdnative/config.py
@@ -1,8 +1,17 @@
-
-
def can_build(platform):
return True
-
def configure(env):
env.use_ptrcall = True
+
+def get_doc_classes():
+ return [
+ "ARVRInterfaceGDNative",
+ "GDNative",
+ "GDNativeLibrary",
+ "NativeScript",
+ "PluginScript",
+ ]
+
+def get_doc_path():
+ return "doc_classes"
diff --git a/modules/gdnative/doc_classes/ARVRInterfaceGDNative.xml b/modules/gdnative/doc_classes/ARVRInterfaceGDNative.xml
new file mode 100644
index 0000000000..10957a3394
--- /dev/null
+++ b/modules/gdnative/doc_classes/ARVRInterfaceGDNative.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="ARVRInterfaceGDNative" inherits="ARVRInterface" category="Core" version="3.0-alpha">
+ <brief_description>
+ GDNative wrapper for an ARVR interface
+ </brief_description>
+ <description>
+ This is a wrapper class for GDNative implementations of the ARVR interface. To use a GDNative ARVR interface simply instantiate this object and set your GDNative library containing the ARVR interface implementation.
+ </description>
+ <tutorials>
+ </tutorials>
+ <demos>
+ </demos>
+ <methods>
+ </methods>
+ <constants>
+ </constants>
+</class>
diff --git a/doc/classes/GDNative.xml b/modules/gdnative/doc_classes/GDNative.xml
index ba813c4564..7a36d09aec 100644
--- a/doc/classes/GDNative.xml
+++ b/modules/gdnative/doc_classes/GDNative.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="GDNative" inherits="Reference" category="Core" version="3.0.alpha.custom_build">
+<class name="GDNative" inherits="Reference" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
@@ -12,11 +12,11 @@
<method name="call_native">
<return type="Variant">
</return>
- <argument index="0" name="procedure_name" type="String">
+ <argument index="0" name="calling_type" type="String">
</argument>
- <argument index="1" name="arguments" type="String">
+ <argument index="1" name="procedure_name" type="String">
</argument>
- <argument index="2" name="arg2" type="Array">
+ <argument index="2" name="arguments" type="Array">
</argument>
<description>
</description>
diff --git a/modules/gdnative/doc_classes/GDNativeLibrary.xml b/modules/gdnative/doc_classes/GDNativeLibrary.xml
new file mode 100644
index 0000000000..e271665fd4
--- /dev/null
+++ b/modules/gdnative/doc_classes/GDNativeLibrary.xml
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="GDNativeLibrary" inherits="Resource" category="Core" version="3.0-alpha">
+ <brief_description>
+ </brief_description>
+ <description>
+ </description>
+ <tutorials>
+ </tutorials>
+ <demos>
+ </demos>
+ <methods>
+ <method name="get_config_file">
+ <return type="ConfigFile">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_current_dependencies" qualifiers="const">
+ <return type="PoolStringArray">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_current_library_path" qualifiers="const">
+ <return type="String">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_symbol_prefix" qualifiers="const">
+ <return type="String">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="is_current_library_statically_linked" qualifiers="const">
+ <return type="bool">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="is_singleton" qualifiers="const">
+ <return type="bool">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="set_load_once">
+ <return type="void">
+ </return>
+ <argument index="0" name="load_once" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="set_singleton">
+ <return type="void">
+ </return>
+ <argument index="0" name="singleton" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="set_symbol_prefix">
+ <return type="void">
+ </return>
+ <argument index="0" name="symbol_prefix" type="String">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="should_load_once" qualifiers="const">
+ <return type="bool">
+ </return>
+ <description>
+ </description>
+ </method>
+ </methods>
+ <members>
+ <member name="load_once" type="bool" setter="set_load_once" getter="should_load_once">
+ </member>
+ <member name="singleton" type="bool" setter="set_singleton" getter="is_singleton">
+ </member>
+ <member name="symbol_prefix" type="String" setter="set_symbol_prefix" getter="get_symbol_prefix">
+ </member>
+ </members>
+ <constants>
+ </constants>
+</class>
diff --git a/doc/classes/NativeScript.xml b/modules/gdnative/doc_classes/NativeScript.xml
index b040cfd966..eb4e13f748 100644
--- a/doc/classes/NativeScript.xml
+++ b/modules/gdnative/doc_classes/NativeScript.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="NativeScript" inherits="Script" category="Core" version="3.0.alpha.custom_build">
+<class name="NativeScript" inherits="Script" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/VisualScriptSelf.xml b/modules/gdnative/doc_classes/PluginScript.xml
index a60f7eee03..a5ab422d3c 100644
--- a/doc/classes/VisualScriptSelf.xml
+++ b/modules/gdnative/doc_classes/PluginScript.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptSelf" inherits="VisualScriptNode" category="Core" version="3.0.alpha.custom_build">
+<class name="PluginScript" inherits="Script" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/modules/gdnative/gd_native_library_editor.cpp b/modules/gdnative/gd_native_library_editor.cpp
index c37b7f473d..fda5dcdcad 100644
--- a/modules/gdnative/gd_native_library_editor.cpp
+++ b/modules/gdnative/gd_native_library_editor.cpp
@@ -44,7 +44,7 @@ void GDNativeLibraryEditor::_find_gdnative_singletons(EditorFileSystemDirectory
}
Ref<GDNativeLibrary> lib = ResourceLoader::load(p_dir->get_file_path(i));
- if (lib.is_valid() && lib->is_singleton_gdnative()) {
+ if (lib.is_valid() && lib->is_singleton()) {
String path = p_dir->get_file_path(i);
TreeItem *ti = libraries->create_item(libraries->get_root());
ti->set_text(0, path.get_file());
diff --git a/modules/gdnative/gdnative.cpp b/modules/gdnative/gdnative.cpp
index 373b98dc8b..de118043ca 100644
--- a/modules/gdnative/gdnative.cpp
+++ b/modules/gdnative/gdnative.cpp
@@ -37,161 +37,55 @@
#include "scene/main/scene_tree.h"
-const String init_symbol = "godot_gdnative_init";
-const String terminate_symbol = "godot_gdnative_terminate";
+const String init_symbol = "gdnative_init";
+const String terminate_symbol = "gdnative_terminate";
+const String default_symbol_prefix = "godot_";
// Defined in gdnative_api_struct.gen.cpp
-extern const godot_gdnative_api_struct api_struct;
-
-String GDNativeLibrary::platform_names[NUM_PLATFORMS + 1] = {
- "X11_32bit",
- "X11_64bit",
- "Windows_32bit",
- "Windows_64bit",
- "OSX",
-
- "Android",
-
- "iOS_32bit",
- "iOS_64bit",
-
- "WebAssembly",
-
- ""
-};
-String GDNativeLibrary::platform_lib_ext[NUM_PLATFORMS + 1] = {
- "so",
- "so",
- "dll",
- "dll",
- "dylib",
-
- "so",
-
- "dylib",
- "dylib",
-
- "wasm",
-
- ""
-};
-
-GDNativeLibrary::Platform GDNativeLibrary::current_platform =
-#if defined(X11_ENABLED)
- (sizeof(void *) == 8 ? X11_64BIT : X11_32BIT);
-#elif defined(WINDOWS_ENABLED)
- (sizeof(void *) == 8 ? WINDOWS_64BIT : WINDOWS_32BIT);
-#elif defined(OSX_ENABLED)
- OSX;
-#elif defined(IPHONE_ENABLED)
- (sizeof(void *) == 8 ? IOS_64BIT : IOS_32BIT);
-#elif defined(ANDROID_ENABLED)
- ANDROID;
-#elif defined(JAVASCRIPT_ENABLED)
- WASM;
-#else
- NUM_PLATFORMS;
-#endif
-
-GDNativeLibrary::GDNativeLibrary()
- : library_paths(), singleton_gdnative(false) {
-}
-
-GDNativeLibrary::~GDNativeLibrary() {
-}
-
-void GDNativeLibrary::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_library_path", "platform", "path"), &GDNativeLibrary::set_library_path);
- ClassDB::bind_method(D_METHOD("get_library_path", "platform"), &GDNativeLibrary::get_library_path);
- ClassDB::bind_method(D_METHOD("get_active_library_path"), &GDNativeLibrary::get_active_library_path);
+extern const godot_gdnative_core_api_struct api_struct;
- ClassDB::bind_method(D_METHOD("is_singleton_gdnative"), &GDNativeLibrary::is_singleton_gdnative);
- ClassDB::bind_method(D_METHOD("set_singleton_gdnative", "singleton"), &GDNativeLibrary::set_singleton_gdnative);
+Map<String, Vector<Ref<GDNative> > > *GDNativeLibrary::loaded_libraries = NULL;
- ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "singleton_gdnative"), "set_singleton_gdnative", "is_singleton_gdnative");
-}
+GDNativeLibrary::GDNativeLibrary() {
+ config_file.instance();
-bool GDNativeLibrary::_set(const StringName &p_name, const Variant &p_value) {
- String name = p_name;
- if (name.begins_with("platform/")) {
- set_library_path(name.get_slice("/", 1), p_value);
- return true;
- }
- return false;
-}
+ symbol_prefix = default_symbol_prefix;
-bool GDNativeLibrary::_get(const StringName &p_name, Variant &r_ret) const {
- String name = p_name;
- if (name.begins_with("platform/")) {
- r_ret = get_library_path(name.get_slice("/", 1));
- return true;
+ if (GDNativeLibrary::loaded_libraries == NULL) {
+ GDNativeLibrary::loaded_libraries = memnew((Map<String, Vector<Ref<GDNative> > >));
}
- return false;
}
-void GDNativeLibrary::_get_property_list(List<PropertyInfo> *p_list) const {
- for (int i = 0; i < NUM_PLATFORMS; i++) {
- p_list->push_back(PropertyInfo(Variant::STRING,
- "platform/" + platform_names[i],
- PROPERTY_HINT_FILE,
- "*." + platform_lib_ext[i]));
- }
+GDNativeLibrary::~GDNativeLibrary() {
}
-void GDNativeLibrary::set_library_path(StringName p_platform, String p_path) {
- int i;
- for (i = 0; i <= NUM_PLATFORMS; i++) {
- if (i == NUM_PLATFORMS) break;
- if (platform_names[i] == p_platform) {
- break;
- }
- }
+void GDNativeLibrary::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("get_config_file"), &GDNativeLibrary::get_config_file);
- if (i == NUM_PLATFORMS) {
- ERR_EXPLAIN(String("No such platform: ") + p_platform);
- ERR_FAIL();
- }
+ ClassDB::bind_method(D_METHOD("get_current_library_path"), &GDNativeLibrary::get_current_library_path);
+ ClassDB::bind_method(D_METHOD("get_current_dependencies"), &GDNativeLibrary::get_current_dependencies);
- library_paths[i] = p_path;
-}
+ ClassDB::bind_method(D_METHOD("should_load_once"), &GDNativeLibrary::should_load_once);
+ ClassDB::bind_method(D_METHOD("is_singleton"), &GDNativeLibrary::is_singleton);
+ ClassDB::bind_method(D_METHOD("get_symbol_prefix"), &GDNativeLibrary::get_symbol_prefix);
-String GDNativeLibrary::get_library_path(StringName p_platform) const {
- int i;
- for (i = 0; i <= NUM_PLATFORMS; i++) {
- if (i == NUM_PLATFORMS) break;
- if (platform_names[i] == p_platform) {
- break;
- }
- }
-
- if (i == NUM_PLATFORMS) {
- ERR_EXPLAIN(String("No such platform: ") + p_platform);
- ERR_FAIL_V("");
- }
+ ClassDB::bind_method(D_METHOD("set_load_once", "load_once"), &GDNativeLibrary::set_load_once);
+ ClassDB::bind_method(D_METHOD("set_singleton", "singleton"), &GDNativeLibrary::set_singleton);
+ ClassDB::bind_method(D_METHOD("set_symbol_prefix", "symbol_prefix"), &GDNativeLibrary::set_symbol_prefix);
- return library_paths[i];
-}
-
-String GDNativeLibrary::get_active_library_path() const {
- if (GDNativeLibrary::current_platform != NUM_PLATFORMS) {
- return library_paths[GDNativeLibrary::current_platform];
- }
- return "";
+ ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "load_once"), "set_load_once", "should_load_once");
+ ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "singleton"), "set_singleton", "is_singleton");
+ ADD_PROPERTYNZ(PropertyInfo(Variant::STRING, "symbol_prefix"), "set_symbol_prefix", "get_symbol_prefix");
}
GDNative::GDNative() {
native_handle = NULL;
+ initialized = false;
}
GDNative::~GDNative() {
}
-extern "C" void _api_anchor();
-
-void GDNative::_compile_dummy_for_api() {
- _api_anchor();
-}
-
void GDNative::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_library", "library"), &GDNative::set_library);
ClassDB::bind_method(D_METHOD("get_library"), &GDNative::get_library);
@@ -199,10 +93,7 @@ void GDNative::_bind_methods() {
ClassDB::bind_method(D_METHOD("initialize"), &GDNative::initialize);
ClassDB::bind_method(D_METHOD("terminate"), &GDNative::terminate);
- // TODO(karroffel): get_native_(raw_)call_types binding?
-
- // TODO(karroffel): make this a varargs function?
- ClassDB::bind_method(D_METHOD("call_native", "procedure_name", "arguments"), &GDNative::call_native);
+ ClassDB::bind_method(D_METHOD("call_native", "calling_type", "procedure_name", "arguments"), &GDNative::call_native);
ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "library", PROPERTY_HINT_RESOURCE_TYPE, "GDNativeLibrary"), "set_library", "get_library");
}
@@ -217,32 +108,49 @@ Ref<GDNativeLibrary> GDNative::get_library() {
return library;
}
+extern "C" void _gdnative_report_version_mismatch(const godot_object *p_library, const char *p_ext, godot_gdnative_api_version p_want, godot_gdnative_api_version p_have);
+extern "C" void _gdnative_report_loading_error(const godot_object *p_library, const char *p_what);
+
bool GDNative::initialize() {
if (library.is_null()) {
ERR_PRINT("No library set, can't initialize GDNative object");
return false;
}
- String lib_path = library->get_active_library_path();
+ String lib_path = library->get_current_library_path();
if (lib_path.empty()) {
ERR_PRINT("No library set for this platform");
return false;
}
#ifdef IPHONE_ENABLED
- String path = lib_path.replace("res://", "dylibs/");
+ String path = "";
#else
String path = ProjectSettings::get_singleton()->globalize_path(lib_path);
#endif
+
+ if (library->should_load_once()) {
+ if (GDNativeLibrary::loaded_libraries->has(lib_path)) {
+ // already loaded. Don't load again.
+ // copy some of the stuff instead
+ this->native_handle = (*GDNativeLibrary::loaded_libraries)[lib_path][0]->native_handle;
+ initialized = true;
+ return true;
+ }
+ }
+
Error err = OS::get_singleton()->open_dynamic_library(path, native_handle);
if (err != OK) {
return false;
}
void *library_init;
- err = OS::get_singleton()->get_dynamic_library_symbol_handle(
- native_handle,
- init_symbol,
- library_init);
+
+ // we cheat here a little bit. you saw nothing
+ initialized = true;
+
+ err = get_symbol(library->get_symbol_prefix() + init_symbol, library_init, false);
+
+ initialized = false;
if (err || !library_init) {
OS::get_singleton()->close_dynamic_library(native_handle);
@@ -261,27 +169,50 @@ bool GDNative::initialize() {
options.core_api_hash = ClassDB::get_api_hash(ClassDB::API_CORE);
options.editor_api_hash = ClassDB::get_api_hash(ClassDB::API_EDITOR);
options.no_api_hash = ClassDB::get_api_hash(ClassDB::API_NONE);
+ options.report_version_mismatch = &_gdnative_report_version_mismatch;
+ options.report_loading_error = &_gdnative_report_loading_error;
options.gd_native_library = (godot_object *)(get_library().ptr());
options.active_library_path = (godot_string *)&path;
library_init_fpointer(&options);
+ initialized = true;
+
+ if (library->should_load_once() && !GDNativeLibrary::loaded_libraries->has(lib_path)) {
+ Vector<Ref<GDNative> > gdnatives;
+ gdnatives.resize(1);
+ gdnatives[0] = Ref<GDNative>(this);
+ GDNativeLibrary::loaded_libraries->insert(lib_path, gdnatives);
+ }
+
return true;
}
bool GDNative::terminate() {
- if (native_handle == NULL) {
+ if (!initialized) {
ERR_PRINT("No valid library handle, can't terminate GDNative object");
return false;
}
+ if (library->should_load_once()) {
+ Vector<Ref<GDNative> > *gdnatives = &(*GDNativeLibrary::loaded_libraries)[library->get_current_library_path()];
+ if (gdnatives->size() > 1) {
+ // there are other GDNative's still using this library, so we actually don't terminte
+ gdnatives->erase(Ref<GDNative>(this));
+ initialized = false;
+ return true;
+ } else if (gdnatives->size() == 1) {
+ // we're the last one, terminate!
+ gdnatives->clear();
+ // wew this looks scary, but all it does is remove the entry completely
+ GDNativeLibrary::loaded_libraries->erase(GDNativeLibrary::loaded_libraries->find(library->get_current_library_path()));
+ }
+ }
+
void *library_terminate;
- Error error = OS::get_singleton()->get_dynamic_library_symbol_handle(
- native_handle,
- terminate_symbol,
- library_terminate);
- if (error) {
+ Error error = get_symbol(library->get_symbol_prefix() + terminate_symbol, library_terminate);
+ if (error || !library_terminate) {
OS::get_singleton()->close_dynamic_library(native_handle);
native_handle = NULL;
return true;
@@ -290,13 +221,13 @@ bool GDNative::terminate() {
godot_gdnative_terminate_fn library_terminate_pointer;
library_terminate_pointer = (godot_gdnative_terminate_fn)library_terminate;
- // TODO(karroffel): remove this? Should be part of NativeScript, not
- // GDNative IMO
godot_gdnative_terminate_options options;
options.in_editor = Engine::get_singleton()->is_editor_hint();
library_terminate_pointer(&options);
+ initialized = false;
+
// GDNativeScriptLanguage::get_singleton()->initialized_libraries.erase(p_native_lib->path);
OS::get_singleton()->close_dynamic_library(native_handle);
@@ -306,17 +237,13 @@ bool GDNative::terminate() {
}
bool GDNative::is_initialized() {
- return (native_handle != NULL);
+ return initialized;
}
void GDNativeCallRegistry::register_native_call_type(StringName p_call_type, native_call_cb p_callback) {
native_calls.insert(p_call_type, p_callback);
}
-void GDNativeCallRegistry::register_native_raw_call_type(StringName p_raw_call_type, native_raw_call_cb p_callback) {
- native_raw_calls.insert(p_raw_call_type, p_callback);
-}
-
Vector<StringName> GDNativeCallRegistry::get_native_call_types() {
Vector<StringName> call_types;
call_types.resize(native_calls.size());
@@ -329,18 +256,6 @@ Vector<StringName> GDNativeCallRegistry::get_native_call_types() {
return call_types;
}
-Vector<StringName> GDNativeCallRegistry::get_native_raw_call_types() {
- Vector<StringName> call_types;
- call_types.resize(native_raw_calls.size());
-
- size_t idx = 0;
- for (Map<StringName, native_raw_call_cb>::Element *E = native_raw_calls.front(); E; E = E->next(), idx++) {
- call_types[idx] = E->key();
- }
-
- return call_types;
-}
-
Variant GDNative::call_native(StringName p_native_call_type, StringName p_procedure_name, Array p_arguments) {
Map<StringName, native_call_cb>::Element *E = GDNativeCallRegistry::singleton->native_calls.find(p_native_call_type);
@@ -349,20 +264,158 @@ Variant GDNative::call_native(StringName p_native_call_type, StringName p_proced
return Variant();
}
- String procedure_name = p_procedure_name;
- godot_variant result = E->get()(native_handle, (godot_string *)&procedure_name, (godot_array *)&p_arguments);
+ void *procedure_handle;
+
+ Error err = OS::get_singleton()->get_dynamic_library_symbol_handle(
+ native_handle,
+ p_procedure_name,
+ procedure_handle);
+
+ if (err != OK || procedure_handle == NULL) {
+ return Variant();
+ }
+
+ godot_variant result = E->get()(procedure_handle, (godot_array *)&p_arguments);
return *(Variant *)&result;
}
-void GDNative::call_native_raw(StringName p_raw_call_type, StringName p_procedure_name, void *data, int num_args, void **args, void *r_return) {
+Error GDNative::get_symbol(StringName p_procedure_name, void *&r_handle, bool p_optional) {
- Map<StringName, native_raw_call_cb>::Element *E = GDNativeCallRegistry::singleton->native_raw_calls.find(p_raw_call_type);
- if (!E) {
- ERR_PRINT((String("No handler for native raw call type \"" + p_raw_call_type) + "\" found").utf8().get_data());
- return;
+ if (!initialized) {
+ ERR_PRINT("No valid library handle, can't get symbol from GDNative object");
+ return ERR_CANT_OPEN;
}
- String procedure_name = p_procedure_name;
- E->get()(native_handle, (godot_string *)&procedure_name, data, num_args, args, r_return);
+ Error result = OS::get_singleton()->get_dynamic_library_symbol_handle(
+ native_handle,
+ p_procedure_name,
+ r_handle,
+ p_optional);
+
+ return result;
+}
+
+RES GDNativeLibraryResourceLoader::load(const String &p_path, const String &p_original_path, Error *r_error) {
+ Ref<GDNativeLibrary> lib;
+ lib.instance();
+
+ Ref<ConfigFile> config = lib->get_config_file();
+
+ Error err = config->load(p_path);
+
+ if (r_error) {
+ *r_error = err;
+ }
+
+ lib->set_singleton(config->get_value("general", "singleton", false));
+ lib->set_load_once(config->get_value("general", "load_once", true));
+ lib->set_symbol_prefix(config->get_value("general", "symbol_prefix", default_symbol_prefix));
+
+ String entry_lib_path;
+ {
+
+ List<String> entry_keys;
+ config->get_section_keys("entry", &entry_keys);
+
+ for (List<String>::Element *E = entry_keys.front(); E; E = E->next()) {
+ String key = E->get();
+
+ Vector<String> tags = key.split(".");
+
+ bool skip = false;
+ for (int i = 0; i < tags.size(); i++) {
+ bool has_feature = OS::get_singleton()->has_feature(tags[i]);
+
+ if (!has_feature) {
+ skip = true;
+ break;
+ }
+ }
+
+ if (skip) {
+ continue;
+ }
+
+ entry_lib_path = config->get_value("entry", key);
+ break;
+ }
+ }
+
+ Vector<String> dependency_paths;
+ {
+
+ List<String> dependency_keys;
+ config->get_section_keys("dependencies", &dependency_keys);
+
+ for (List<String>::Element *E = dependency_keys.front(); E; E = E->next()) {
+ String key = E->get();
+
+ Vector<String> tags = key.split(".");
+
+ bool skip = false;
+ for (int i = 0; i < tags.size(); i++) {
+ bool has_feature = OS::get_singleton()->has_feature(tags[i]);
+
+ if (!has_feature) {
+ skip = true;
+ break;
+ }
+ }
+
+ if (skip) {
+ continue;
+ }
+
+ dependency_paths = config->get_value("dependencies", key);
+ break;
+ }
+ }
+
+ lib->current_library_path = entry_lib_path;
+ lib->current_dependencies = dependency_paths;
+
+ return lib;
+}
+
+void GDNativeLibraryResourceLoader::get_recognized_extensions(List<String> *p_extensions) const {
+ p_extensions->push_back("gdnlib");
+}
+
+bool GDNativeLibraryResourceLoader::handles_type(const String &p_type) const {
+ return p_type == "GDNativeLibrary";
+}
+
+String GDNativeLibraryResourceLoader::get_resource_type(const String &p_path) const {
+ String el = p_path.get_extension().to_lower();
+ if (el == "gdnlib")
+ return "GDNativeLibrary";
+ return "";
+}
+
+Error GDNativeLibraryResourceSaver::save(const String &p_path, const RES &p_resource, uint32_t p_flags) {
+
+ Ref<GDNativeLibrary> lib = p_resource;
+
+ if (lib.is_null()) {
+ return ERR_INVALID_DATA;
+ }
+
+ Ref<ConfigFile> config = lib->get_config_file();
+
+ config->set_value("general", "singleton", lib->is_singleton());
+ config->set_value("general", "load_once", lib->should_load_once());
+ config->set_value("general", "symbol_prefix", lib->get_symbol_prefix());
+
+ return config->save(p_path);
+}
+
+bool GDNativeLibraryResourceSaver::recognize(const RES &p_resource) const {
+ return Object::cast_to<GDNativeLibrary>(*p_resource) != NULL;
+}
+
+void GDNativeLibraryResourceSaver::get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const {
+ if (Object::cast_to<GDNativeLibrary>(*p_resource) != NULL) {
+ p_extensions->push_back("gdnlib");
+ }
}
diff --git a/modules/gdnative/gdnative.h b/modules/gdnative/gdnative.h
index 7bbad842eb..bb260bdd1b 100644
--- a/modules/gdnative/gdnative.h
+++ b/modules/gdnative/gdnative.h
@@ -38,90 +38,82 @@
#include "gdnative/gdnative.h"
#include "gdnative_api_struct.gen.h"
-class GDNativeLibrary : public Resource {
- GDCLASS(GDNativeLibrary, Resource)
-
- enum Platform {
- X11_32BIT,
- X11_64BIT,
- WINDOWS_32BIT,
- WINDOWS_64BIT,
- // NOTE(karroffel): I heard OSX 32 bit is dead, so 64 only
- OSX,
-
- // Android .so files must be located in directories corresponding to Android ABI names:
- // https://developer.android.com/ndk/guides/abis.html
- // Android runtime will select the matching library depending on the device.
- // The value here must simply point to the .so name, for example:
- // "res://libmy_gdnative.so" or "libmy_gdnative.so",
- // while in the project the actual paths can be "lib/android/armeabi-v7a/libmy_gdnative.so",
- // "lib/android/arm64-v8a/libmy_gdnative.so".
- ANDROID,
+#include "io/config_file.h"
- IOS_32BIT,
- IOS_64BIT,
+class GDNativeLibraryResourceLoader;
+class GDNative;
- // TODO(karroffel): figure out how to deal with web stuff at all...
- WASM,
-
- // TODO(karroffel): does UWP have different libs??
- // UWP,
-
- NUM_PLATFORMS
-
- };
+class GDNativeLibrary : public Resource {
+ GDCLASS(GDNativeLibrary, Resource)
- static String platform_names[NUM_PLATFORMS + 1];
- static String platform_lib_ext[NUM_PLATFORMS + 1];
+ static Map<String, Vector<Ref<GDNative> > > *loaded_libraries;
- static Platform current_platform;
+ friend class GDNativeLibraryResourceLoader;
+ friend class GDNative;
- String library_paths[NUM_PLATFORMS];
+ Ref<ConfigFile> config_file;
- bool singleton_gdnative;
+ String current_library_path;
+ Vector<String> current_dependencies;
-protected:
- bool _set(const StringName &p_name, const Variant &p_value);
- bool _get(const StringName &p_name, Variant &r_ret) const;
- void _get_property_list(List<PropertyInfo> *p_list) const;
+ bool singleton;
+ bool load_once;
+ String symbol_prefix;
public:
GDNativeLibrary();
~GDNativeLibrary();
- static void _bind_methods();
+ _FORCE_INLINE_ Ref<ConfigFile> get_config_file() { return config_file; }
- void set_library_path(StringName p_platform, String p_path);
- String get_library_path(StringName p_platform) const;
+ // things that change per-platform
+ // so there are no setters for this
+ _FORCE_INLINE_ String get_current_library_path() const {
+ return current_library_path;
+ }
+ _FORCE_INLINE_ Vector<String> get_current_dependencies() const {
+ return current_dependencies;
+ }
- String get_active_library_path() const;
+ // things that are a property of the library itself, not platform specific
+ _FORCE_INLINE_ bool should_load_once() const {
+ return load_once;
+ }
+ _FORCE_INLINE_ bool is_singleton() const {
+ return singleton;
+ }
+ _FORCE_INLINE_ String get_symbol_prefix() const {
+ return symbol_prefix;
+ }
- _FORCE_INLINE_ bool is_singleton_gdnative() const { return singleton_gdnative; }
- _FORCE_INLINE_ void set_singleton_gdnative(bool p_singleton) { singleton_gdnative = p_singleton; }
-};
+ _FORCE_INLINE_ void set_load_once(bool p_load_once) {
+ load_once = p_load_once;
+ }
+ _FORCE_INLINE_ void set_singleton(bool p_singleton) {
+ singleton = p_singleton;
+ }
+ _FORCE_INLINE_ void set_symbol_prefix(String p_symbol_prefix) {
+ symbol_prefix = p_symbol_prefix;
+ }
-typedef godot_variant (*native_call_cb)(void *, godot_string *, godot_array *);
-typedef void (*native_raw_call_cb)(void *, godot_string *, void *, int, void **, void *);
+ static void _bind_methods();
+};
struct GDNativeCallRegistry {
static GDNativeCallRegistry *singleton;
- inline GDNativeCallRegistry *get_singleton() {
+ inline static GDNativeCallRegistry *get_singleton() {
return singleton;
}
inline GDNativeCallRegistry()
- : native_calls(),
- native_raw_calls() {}
+ : native_calls() {}
Map<StringName, native_call_cb> native_calls;
- Map<StringName, native_raw_call_cb> native_raw_calls;
void register_native_call_type(StringName p_call_type, native_call_cb p_callback);
- void register_native_raw_call_type(StringName p_raw_call_type, native_raw_call_cb p_callback);
Vector<StringName> get_native_call_types();
- Vector<StringName> get_native_raw_call_types();
};
class GDNative : public Reference {
@@ -129,10 +121,9 @@ class GDNative : public Reference {
Ref<GDNativeLibrary> library;
- // TODO(karroffel): different platforms? WASM????
void *native_handle;
- void _compile_dummy_for_api();
+ bool initialized;
public:
GDNative();
@@ -149,7 +140,23 @@ public:
bool terminate();
Variant call_native(StringName p_native_call_type, StringName p_procedure_name, Array p_arguments = Array());
- void call_native_raw(StringName p_raw_call_type, StringName p_procedure_name, void *data, int num_args, void **args, void *r_return);
+
+ Error get_symbol(StringName p_procedure_name, void *&r_handle, bool p_optional = true);
+};
+
+class GDNativeLibraryResourceLoader : public ResourceFormatLoader {
+public:
+ virtual RES load(const String &p_path, const String &p_original_path, Error *r_error);
+ virtual void get_recognized_extensions(List<String> *p_extensions) const;
+ virtual bool handles_type(const String &p_type) const;
+ virtual String get_resource_type(const String &p_path) const;
+};
+
+class GDNativeLibraryResourceSaver : public ResourceFormatSaver {
+public:
+ virtual Error save(const String &p_path, const RES &p_resource, uint32_t p_flags);
+ virtual bool recognize(const RES &p_resource) const;
+ virtual void get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const;
};
#endif // GDNATIVE_H
diff --git a/modules/gdnative/gdnative/aabb.cpp b/modules/gdnative/gdnative/aabb.cpp
new file mode 100644
index 0000000000..6c89bcdceb
--- /dev/null
+++ b/modules/gdnative/gdnative/aabb.cpp
@@ -0,0 +1,217 @@
+/*************************************************************************/
+/* aabb.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#include "gdnative/aabb.h"
+
+#include "core/math/aabb.h"
+#include "core/variant.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void GDAPI godot_aabb_new(godot_aabb *r_dest, const godot_vector3 *p_pos, const godot_vector3 *p_size) {
+ const Vector3 *pos = (const Vector3 *)p_pos;
+ const Vector3 *size = (const Vector3 *)p_size;
+ AABB *dest = (AABB *)r_dest;
+ *dest = AABB(*pos, *size);
+}
+
+godot_vector3 GDAPI godot_aabb_get_position(const godot_aabb *p_self) {
+ godot_vector3 raw_ret;
+ const AABB *self = (const AABB *)p_self;
+ Vector3 *ret = (Vector3 *)&raw_ret;
+ *ret = self->position;
+ return raw_ret;
+}
+
+void GDAPI godot_aabb_set_position(const godot_aabb *p_self, const godot_vector3 *p_v) {
+ AABB *self = (AABB *)p_self;
+ const Vector3 *v = (const Vector3 *)p_v;
+ self->position = *v;
+}
+
+godot_vector3 GDAPI godot_aabb_get_size(const godot_aabb *p_self) {
+ godot_vector3 raw_ret;
+ const AABB *self = (const AABB *)p_self;
+ Vector3 *ret = (Vector3 *)&raw_ret;
+ *ret = self->size;
+ return raw_ret;
+}
+
+void GDAPI godot_aabb_set_size(const godot_aabb *p_self, const godot_vector3 *p_v) {
+ AABB *self = (AABB *)p_self;
+ const Vector3 *v = (const Vector3 *)p_v;
+ self->size = *v;
+}
+
+godot_string GDAPI godot_aabb_as_string(const godot_aabb *p_self) {
+ godot_string ret;
+ const AABB *self = (const AABB *)p_self;
+ memnew_placement(&ret, String(*self));
+ return ret;
+}
+
+godot_real GDAPI godot_aabb_get_area(const godot_aabb *p_self) {
+ const AABB *self = (const AABB *)p_self;
+ return self->get_area();
+}
+
+godot_bool GDAPI godot_aabb_has_no_area(const godot_aabb *p_self) {
+ const AABB *self = (const AABB *)p_self;
+ return self->has_no_area();
+}
+
+godot_bool GDAPI godot_aabb_has_no_surface(const godot_aabb *p_self) {
+ const AABB *self = (const AABB *)p_self;
+ return self->has_no_surface();
+}
+
+godot_bool GDAPI godot_aabb_intersects(const godot_aabb *p_self, const godot_aabb *p_with) {
+ const AABB *self = (const AABB *)p_self;
+ const AABB *with = (const AABB *)p_with;
+ return self->intersects(*with);
+}
+
+godot_bool GDAPI godot_aabb_encloses(const godot_aabb *p_self, const godot_aabb *p_with) {
+ const AABB *self = (const AABB *)p_self;
+ const AABB *with = (const AABB *)p_with;
+ return self->encloses(*with);
+}
+
+godot_aabb GDAPI godot_aabb_merge(const godot_aabb *p_self, const godot_aabb *p_with) {
+ godot_aabb dest;
+ const AABB *self = (const AABB *)p_self;
+ const AABB *with = (const AABB *)p_with;
+ *((AABB *)&dest) = self->merge(*with);
+ return dest;
+}
+
+godot_aabb GDAPI godot_aabb_intersection(const godot_aabb *p_self, const godot_aabb *p_with) {
+ godot_aabb dest;
+ const AABB *self = (const AABB *)p_self;
+ const AABB *with = (const AABB *)p_with;
+ *((AABB *)&dest) = self->intersection(*with);
+ return dest;
+}
+
+godot_bool GDAPI godot_aabb_intersects_plane(const godot_aabb *p_self, const godot_plane *p_plane) {
+ const AABB *self = (const AABB *)p_self;
+ const Plane *plane = (const Plane *)p_plane;
+ return self->intersects_plane(*plane);
+}
+
+godot_bool GDAPI godot_aabb_intersects_segment(const godot_aabb *p_self, const godot_vector3 *p_from, const godot_vector3 *p_to) {
+ const AABB *self = (const AABB *)p_self;
+ const Vector3 *from = (const Vector3 *)p_from;
+ const Vector3 *to = (const Vector3 *)p_to;
+ return self->intersects_segment(*from, *to);
+}
+
+godot_bool GDAPI godot_aabb_has_point(const godot_aabb *p_self, const godot_vector3 *p_point) {
+ const AABB *self = (const AABB *)p_self;
+ const Vector3 *point = (const Vector3 *)p_point;
+ return self->has_point(*point);
+}
+
+godot_vector3 GDAPI godot_aabb_get_support(const godot_aabb *p_self, const godot_vector3 *p_dir) {
+ godot_vector3 dest;
+ const AABB *self = (const AABB *)p_self;
+ const Vector3 *dir = (const Vector3 *)p_dir;
+ *((Vector3 *)&dest) = self->get_support(*dir);
+ return dest;
+}
+
+godot_vector3 GDAPI godot_aabb_get_longest_axis(const godot_aabb *p_self) {
+ godot_vector3 dest;
+ const AABB *self = (const AABB *)p_self;
+ *((Vector3 *)&dest) = self->get_longest_axis();
+ return dest;
+}
+
+godot_int GDAPI godot_aabb_get_longest_axis_index(const godot_aabb *p_self) {
+ const AABB *self = (const AABB *)p_self;
+ return self->get_longest_axis_index();
+}
+
+godot_real GDAPI godot_aabb_get_longest_axis_size(const godot_aabb *p_self) {
+ const AABB *self = (const AABB *)p_self;
+ return self->get_longest_axis_size();
+}
+
+godot_vector3 GDAPI godot_aabb_get_shortest_axis(const godot_aabb *p_self) {
+ godot_vector3 dest;
+ const AABB *self = (const AABB *)p_self;
+ *((Vector3 *)&dest) = self->get_shortest_axis();
+ return dest;
+}
+
+godot_int GDAPI godot_aabb_get_shortest_axis_index(const godot_aabb *p_self) {
+ const AABB *self = (const AABB *)p_self;
+ return self->get_shortest_axis_index();
+}
+
+godot_real GDAPI godot_aabb_get_shortest_axis_size(const godot_aabb *p_self) {
+ const AABB *self = (const AABB *)p_self;
+ return self->get_shortest_axis_size();
+}
+
+godot_aabb GDAPI godot_aabb_expand(const godot_aabb *p_self, const godot_vector3 *p_to_point) {
+ godot_aabb dest;
+ const AABB *self = (const AABB *)p_self;
+ const Vector3 *to_point = (const Vector3 *)p_to_point;
+ *((AABB *)&dest) = self->expand(*to_point);
+ return dest;
+}
+
+godot_aabb GDAPI godot_aabb_grow(const godot_aabb *p_self, const godot_real p_by) {
+ godot_aabb dest;
+ const AABB *self = (const AABB *)p_self;
+
+ *((AABB *)&dest) = self->grow(p_by);
+ return dest;
+}
+
+godot_vector3 GDAPI godot_aabb_get_endpoint(const godot_aabb *p_self, const godot_int p_idx) {
+ godot_vector3 dest;
+ const AABB *self = (const AABB *)p_self;
+
+ *((Vector3 *)&dest) = self->get_endpoint(p_idx);
+ return dest;
+}
+
+godot_bool GDAPI godot_aabb_operator_equal(const godot_aabb *p_self, const godot_aabb *p_b) {
+ const AABB *self = (const AABB *)p_self;
+ const AABB *b = (const AABB *)p_b;
+ return *self == *b;
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/modules/gdnative/gdnative/array.cpp b/modules/gdnative/gdnative/array.cpp
index 51c023981f..8351c43574 100644
--- a/modules/gdnative/gdnative/array.cpp
+++ b/modules/gdnative/gdnative/array.cpp
@@ -41,9 +41,6 @@
extern "C" {
#endif
-void _array_api_anchor() {
-}
-
void GDAPI godot_array_new(godot_array *r_dest) {
Array *dest = (Array *)r_dest;
memnew_placement(dest, Array);
@@ -158,6 +155,11 @@ godot_variant GDAPI *godot_array_operator_index(godot_array *p_self, const godot
return (godot_variant *)&self->operator[](p_idx);
}
+const godot_variant GDAPI *godot_array_operator_index_const(const godot_array *p_self, const godot_int p_idx) {
+ const Array *self = (const Array *)p_self;
+ return (const godot_variant *)&self->operator[](p_idx);
+}
+
void GDAPI godot_array_append(godot_array *p_self, const godot_variant *p_value) {
Array *self = (Array *)p_self;
Variant *val = (Variant *)p_value;
@@ -300,6 +302,17 @@ void GDAPI godot_array_sort_custom(godot_array *p_self, godot_object *p_obj, con
self->sort_custom((Object *)p_obj, *func);
}
+godot_int GDAPI godot_array_bsearch(godot_array *p_self, const godot_variant *p_value, const godot_bool p_before) {
+ Array *self = (Array *)p_self;
+ return self->bsearch((const Variant *)p_value, p_before);
+}
+
+godot_int GDAPI godot_array_bsearch_custom(godot_array *p_self, const godot_variant *p_value, godot_object *p_obj, const godot_string *p_func, const godot_bool p_before) {
+ Array *self = (Array *)p_self;
+ const String *func = (const String *)p_func;
+ return self->bsearch_custom((const Variant *)p_value, (Object *)p_obj, *func, p_before);
+}
+
void GDAPI godot_array_destroy(godot_array *p_self) {
((Array *)p_self)->~Array();
}
diff --git a/modules/gdnative/gdnative/basis.cpp b/modules/gdnative/gdnative/basis.cpp
index b1327cdaef..39ca754dc7 100644
--- a/modules/gdnative/gdnative/basis.cpp
+++ b/modules/gdnative/gdnative/basis.cpp
@@ -36,8 +36,6 @@
extern "C" {
#endif
-void _basis_api_anchor() {}
-
void GDAPI godot_basis_new_with_rows(godot_basis *r_dest, const godot_vector3 *p_x_axis, const godot_vector3 *p_y_axis, const godot_vector3 *p_z_axis) {
const Vector3 *x_axis = (const Vector3 *)p_x_axis;
const Vector3 *y_axis = (const Vector3 *)p_y_axis;
@@ -172,7 +170,7 @@ void GDAPI godot_basis_new_with_euler_quat(godot_basis *r_dest, const godot_quat
}
// p_elements is a pointer to an array of 3 (!!) vector3
-void GDAPI godot_basis_get_elements(godot_basis *p_self, godot_vector3 *p_elements) {
+void GDAPI godot_basis_get_elements(const godot_basis *p_self, godot_vector3 *p_elements) {
const Basis *self = (const Basis *)p_self;
Vector3 *elements = (Vector3 *)p_elements;
elements[0] = self->elements[0];
diff --git a/modules/gdnative/gdnative/color.cpp b/modules/gdnative/gdnative/color.cpp
index 2a5c0887a1..281a4c416f 100644
--- a/modules/gdnative/gdnative/color.cpp
+++ b/modules/gdnative/gdnative/color.cpp
@@ -36,8 +36,6 @@
extern "C" {
#endif
-void _color_api_anchor() {}
-
void GDAPI godot_color_new_rgba(godot_color *r_dest, const godot_real p_r, const godot_real p_g, const godot_real p_b, const godot_real p_a) {
Color *dest = (Color *)r_dest;
diff --git a/modules/gdnative/gdnative/dictionary.cpp b/modules/gdnative/gdnative/dictionary.cpp
index ed98cdbb00..8363416946 100644
--- a/modules/gdnative/gdnative/dictionary.cpp
+++ b/modules/gdnative/gdnative/dictionary.cpp
@@ -38,8 +38,6 @@
extern "C" {
#endif
-void _dictionary_api_anchor() {}
-
void GDAPI godot_dictionary_new(godot_dictionary *r_dest) {
Dictionary *dest = (Dictionary *)r_dest;
memnew_placement(dest, Dictionary);
@@ -130,6 +128,12 @@ godot_variant GDAPI *godot_dictionary_operator_index(godot_dictionary *p_self, c
return (godot_variant *)&self->operator[](*key);
}
+const godot_variant GDAPI *godot_dictionary_operator_index_const(const godot_dictionary *p_self, const godot_variant *p_key) {
+ const Dictionary *self = (const Dictionary *)p_self;
+ const Variant *key = (const Variant *)p_key;
+ return (const godot_variant *)&self->operator[](*key);
+}
+
godot_variant GDAPI *godot_dictionary_next(const godot_dictionary *p_self, const godot_variant *p_key) {
Dictionary *self = (Dictionary *)p_self;
const Variant *key = (const Variant *)p_key;
diff --git a/modules/gdnative/gdnative/gdnative.cpp b/modules/gdnative/gdnative/gdnative.cpp
index cf1f6a4f16..92a88e354b 100644
--- a/modules/gdnative/gdnative/gdnative.cpp
+++ b/modules/gdnative/gdnative/gdnative.cpp
@@ -30,55 +30,18 @@
#include "gdnative/gdnative.h"
#include "class_db.h"
+#include "engine.h"
#include "error_macros.h"
#include "global_constants.h"
#include "os/os.h"
-#include "project_settings.h"
#include "variant.h"
+#include "modules/gdnative/gdnative.h"
+
#ifdef __cplusplus
extern "C" {
#endif
-extern "C" void _string_api_anchor();
-extern "C" void _vector2_api_anchor();
-extern "C" void _rect2_api_anchor();
-extern "C" void _vector3_api_anchor();
-extern "C" void _transform2d_api_anchor();
-extern "C" void _plane_api_anchor();
-extern "C" void _quat_api_anchor();
-extern "C" void _basis_api_anchor();
-extern "C" void _rect3_api_anchor();
-extern "C" void _transform_api_anchor();
-extern "C" void _color_api_anchor();
-extern "C" void _node_path_api_anchor();
-extern "C" void _rid_api_anchor();
-extern "C" void _dictionary_api_anchor();
-extern "C" void _array_api_anchor();
-extern "C" void _pool_arrays_api_anchor();
-extern "C" void _variant_api_anchor();
-
-void _api_anchor() {
-
- _string_api_anchor();
- _vector2_api_anchor();
- _rect2_api_anchor();
- _vector3_api_anchor();
- _transform2d_api_anchor();
- _plane_api_anchor();
- _quat_api_anchor();
- _rect3_api_anchor();
- _basis_api_anchor();
- _transform_api_anchor();
- _color_api_anchor();
- _node_path_api_anchor();
- _rid_api_anchor();
- _dictionary_api_anchor();
- _array_api_anchor();
- _pool_arrays_api_anchor();
- _variant_api_anchor();
-}
-
void GDAPI godot_object_destroy(godot_object *p_o) {
memdelete((Object *)p_o);
}
@@ -86,7 +49,7 @@ void GDAPI godot_object_destroy(godot_object *p_o) {
// Singleton API
godot_object GDAPI *godot_global_get_singleton(char *p_name) {
- return (godot_object *)ProjectSettings::get_singleton()->get_singleton_object(String(p_name));
+ return (godot_object *)Engine::get_singleton()->get_singleton_object(String(p_name));
} // result shouldn't be freed
void GDAPI *godot_get_stack_bottom() {
@@ -131,14 +94,6 @@ godot_variant GDAPI godot_method_bind_call(godot_method_bind *p_method_bind, god
return ret;
}
-// @Todo
-/*
-void GDAPI godot_method_bind_varcall(godot_method_bind *p_method_bind)
-{
-
-}
-*/
-
godot_class_constructor GDAPI godot_get_class_constructor(const char *p_classname) {
ClassDB::ClassInfo *class_info = ClassDB::classes.getptr(StringName(p_classname));
if (class_info)
@@ -160,6 +115,10 @@ godot_dictionary GDAPI godot_get_global_constants() {
}
// System functions
+void GDAPI godot_register_native_call_type(const char *p_call_type, native_call_cb p_callback) {
+ GDNativeCallRegistry::get_singleton()->register_native_call_type(StringName(p_call_type), p_callback);
+}
+
void GDAPI *godot_alloc(int p_bytes) {
return memalloc(p_bytes);
}
@@ -184,6 +143,32 @@ void GDAPI godot_print(const godot_string *p_message) {
print_line(*(String *)p_message);
}
+void _gdnative_report_version_mismatch(const godot_object *p_library, const char *p_ext, godot_gdnative_api_version p_want, godot_gdnative_api_version p_have) {
+ String message = "Error loading GDNative file ";
+ GDNativeLibrary *library = (GDNativeLibrary *)p_library;
+
+ message += library->get_current_library_path() + ": Extension \"" + p_ext + "\" can't be loaded.\n";
+
+ Dictionary versions;
+ versions["have_major"] = p_have.major;
+ versions["have_minor"] = p_have.minor;
+ versions["want_major"] = p_want.major;
+ versions["want_minor"] = p_want.minor;
+
+ message += String("Got version {have_major}.{have_minor} but needs {want_major}.{want_minor}!").format(versions);
+
+ _err_print_error("gdnative_init", library->get_current_library_path().utf8().ptr(), 0, message.utf8().ptr());
+}
+
+void _gdnative_report_loading_error(const godot_object *p_library, const char *p_what) {
+ String message = "Error loading GDNative file ";
+ GDNativeLibrary *library = (GDNativeLibrary *)p_library;
+
+ message += library->get_current_library_path() + ": " + p_what;
+
+ _err_print_error("gdnative_init", library->get_current_library_path().utf8().ptr(), 0, message.utf8().ptr());
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/modules/gdnative/gdnative/node_path.cpp b/modules/gdnative/gdnative/node_path.cpp
index 50fade5b94..2bd278e050 100644
--- a/modules/gdnative/gdnative/node_path.cpp
+++ b/modules/gdnative/gdnative/node_path.cpp
@@ -36,8 +36,6 @@
extern "C" {
#endif
-void _node_path_api_anchor() {}
-
void GDAPI godot_node_path_new(godot_node_path *r_dest, const godot_string *p_from) {
NodePath *dest = (NodePath *)r_dest;
const String *from = (const String *)p_from;
diff --git a/modules/gdnative/gdnative/plane.cpp b/modules/gdnative/gdnative/plane.cpp
index a5e05ffa6b..c92efb8d99 100644
--- a/modules/gdnative/gdnative/plane.cpp
+++ b/modules/gdnative/gdnative/plane.cpp
@@ -36,8 +36,6 @@
extern "C" {
#endif
-void _plane_api_anchor() {}
-
void GDAPI godot_plane_new_with_reals(godot_plane *r_dest, const godot_real p_a, const godot_real p_b, const godot_real p_c, const godot_real p_d) {
Plane *dest = (Plane *)r_dest;
diff --git a/modules/gdnative/gdnative/pool_arrays.cpp b/modules/gdnative/gdnative/pool_arrays.cpp
index 1393374da2..562cc344a9 100644
--- a/modules/gdnative/gdnative/pool_arrays.cpp
+++ b/modules/gdnative/gdnative/pool_arrays.cpp
@@ -41,9 +41,6 @@
extern "C" {
#endif
-void _pool_arrays_api_anchor() {
-}
-
#define memnew_placement_custom(m_placement, m_class, m_constr) _post_initialize(new (m_placement, sizeof(m_class), "") m_constr)
// byte
@@ -106,6 +103,16 @@ void GDAPI godot_pool_byte_array_resize(godot_pool_byte_array *p_self, const god
self->resize(p_size);
}
+godot_pool_byte_array_read_access GDAPI *godot_pool_byte_array_read(const godot_pool_byte_array *p_self) {
+ const PoolVector<uint8_t> *self = (const PoolVector<uint8_t> *)p_self;
+ return (godot_pool_byte_array_read_access *)memnew(PoolVector<uint8_t>::Read(self->read()));
+}
+
+godot_pool_byte_array_write_access GDAPI *godot_pool_byte_array_write(godot_pool_byte_array *p_self) {
+ PoolVector<uint8_t> *self = (PoolVector<uint8_t> *)p_self;
+ return (godot_pool_byte_array_write_access *)memnew(PoolVector<uint8_t>::Write(self->write()));
+}
+
void GDAPI godot_pool_byte_array_set(godot_pool_byte_array *p_self, const godot_int p_idx, const uint8_t p_data) {
PoolVector<uint8_t> *self = (PoolVector<uint8_t> *)p_self;
self->set(p_idx, p_data);
@@ -185,6 +192,16 @@ void GDAPI godot_pool_int_array_resize(godot_pool_int_array *p_self, const godot
self->resize(p_size);
}
+godot_pool_int_array_read_access GDAPI *godot_pool_int_array_read(const godot_pool_int_array *p_self) {
+ const PoolVector<godot_int> *self = (const PoolVector<godot_int> *)p_self;
+ return (godot_pool_int_array_read_access *)memnew(PoolVector<godot_int>::Read(self->read()));
+}
+
+godot_pool_int_array_write_access GDAPI *godot_pool_int_array_write(godot_pool_int_array *p_self) {
+ PoolVector<godot_int> *self = (PoolVector<godot_int> *)p_self;
+ return (godot_pool_int_array_write_access *)memnew(PoolVector<godot_int>::Write(self->write()));
+}
+
void GDAPI godot_pool_int_array_set(godot_pool_int_array *p_self, const godot_int p_idx, const godot_int p_data) {
PoolVector<godot_int> *self = (PoolVector<godot_int> *)p_self;
self->set(p_idx, p_data);
@@ -260,10 +277,20 @@ void GDAPI godot_pool_real_array_remove(godot_pool_real_array *p_self, const god
}
void GDAPI godot_pool_real_array_resize(godot_pool_real_array *p_self, const godot_int p_size) {
- PoolVector<godot_int> *self = (PoolVector<godot_int> *)p_self;
+ PoolVector<godot_real> *self = (PoolVector<godot_real> *)p_self;
self->resize(p_size);
}
+godot_pool_real_array_read_access GDAPI *godot_pool_real_array_read(const godot_pool_real_array *p_self) {
+ const PoolVector<godot_real> *self = (const PoolVector<godot_real> *)p_self;
+ return (godot_pool_real_array_read_access *)memnew(PoolVector<godot_real>::Read(self->read()));
+}
+
+godot_pool_int_array_write_access GDAPI *godot_pool_real_array_write(godot_pool_real_array *p_self) {
+ PoolVector<godot_real> *self = (PoolVector<godot_real> *)p_self;
+ return (godot_pool_real_array_write_access *)memnew(PoolVector<godot_real>::Write(self->write()));
+}
+
void GDAPI godot_pool_real_array_set(godot_pool_real_array *p_self, const godot_int p_idx, const godot_real p_data) {
PoolVector<godot_real> *self = (PoolVector<godot_real> *)p_self;
self->set(p_idx, p_data);
@@ -346,6 +373,16 @@ void GDAPI godot_pool_string_array_resize(godot_pool_string_array *p_self, const
self->resize(p_size);
}
+godot_pool_string_array_read_access GDAPI *godot_pool_string_array_read(const godot_pool_string_array *p_self) {
+ const PoolVector<String> *self = (const PoolVector<String> *)p_self;
+ return (godot_pool_string_array_read_access *)memnew(PoolVector<String>::Read(self->read()));
+}
+
+godot_pool_string_array_write_access GDAPI *godot_pool_string_array_write(godot_pool_string_array *p_self) {
+ PoolVector<String> *self = (PoolVector<String> *)p_self;
+ return (godot_pool_string_array_write_access *)memnew(PoolVector<String>::Write(self->write()));
+}
+
void GDAPI godot_pool_string_array_set(godot_pool_string_array *p_self, const godot_int p_idx, const godot_string *p_data) {
PoolVector<String> *self = (PoolVector<String> *)p_self;
String &s = *(String *)p_data;
@@ -433,6 +470,16 @@ void GDAPI godot_pool_vector2_array_resize(godot_pool_vector2_array *p_self, con
self->resize(p_size);
}
+godot_pool_vector2_array_read_access GDAPI *godot_pool_vector2_array_read(const godot_pool_vector2_array *p_self) {
+ const PoolVector<Vector2> *self = (const PoolVector<Vector2> *)p_self;
+ return (godot_pool_vector2_array_read_access *)memnew(PoolVector<Vector2>::Read(self->read()));
+}
+
+godot_pool_vector2_array_write_access GDAPI *godot_pool_vector2_array_write(godot_pool_vector2_array *p_self) {
+ PoolVector<Vector2> *self = (PoolVector<Vector2> *)p_self;
+ return (godot_pool_vector2_array_write_access *)memnew(PoolVector<Vector2>::Write(self->write()));
+}
+
void GDAPI godot_pool_vector2_array_set(godot_pool_vector2_array *p_self, const godot_int p_idx, const godot_vector2 *p_data) {
PoolVector<Vector2> *self = (PoolVector<Vector2> *)p_self;
Vector2 &s = *(Vector2 *)p_data;
@@ -519,6 +566,16 @@ void GDAPI godot_pool_vector3_array_resize(godot_pool_vector3_array *p_self, con
self->resize(p_size);
}
+godot_pool_vector3_array_read_access GDAPI *godot_pool_vector3_array_read(const godot_pool_vector3_array *p_self) {
+ const PoolVector<Vector3> *self = (const PoolVector<Vector3> *)p_self;
+ return (godot_pool_vector3_array_read_access *)memnew(PoolVector<Vector3>::Read(self->read()));
+}
+
+godot_pool_vector3_array_write_access GDAPI *godot_pool_vector3_array_write(godot_pool_vector3_array *p_self) {
+ PoolVector<Vector3> *self = (PoolVector<Vector3> *)p_self;
+ return (godot_pool_vector3_array_write_access *)memnew(PoolVector<Vector3>::Write(self->write()));
+}
+
void GDAPI godot_pool_vector3_array_set(godot_pool_vector3_array *p_self, const godot_int p_idx, const godot_vector3 *p_data) {
PoolVector<Vector3> *self = (PoolVector<Vector3> *)p_self;
Vector3 &s = *(Vector3 *)p_data;
@@ -605,6 +662,16 @@ void GDAPI godot_pool_color_array_resize(godot_pool_color_array *p_self, const g
self->resize(p_size);
}
+godot_pool_color_array_read_access GDAPI *godot_pool_color_array_read(const godot_pool_color_array *p_self) {
+ const PoolVector<Color> *self = (const PoolVector<Color> *)p_self;
+ return (godot_pool_color_array_read_access *)memnew(PoolVector<Color>::Read(self->read()));
+}
+
+godot_pool_color_array_write_access GDAPI *godot_pool_color_array_write(godot_pool_color_array *p_self) {
+ PoolVector<Color> *self = (PoolVector<Color> *)p_self;
+ return (godot_pool_color_array_write_access *)memnew(PoolVector<Color>::Write(self->write()));
+}
+
void GDAPI godot_pool_color_array_set(godot_pool_color_array *p_self, const godot_int p_idx, const godot_color *p_data) {
PoolVector<Color> *self = (PoolVector<Color> *)p_self;
Color &s = *(Color *)p_data;
@@ -628,6 +695,196 @@ void GDAPI godot_pool_color_array_destroy(godot_pool_color_array *p_self) {
((PoolVector<Color> *)p_self)->~PoolVector();
}
+//
+// read accessor functions
+//
+
+const uint8_t GDAPI *godot_pool_byte_array_read_access_ptr(const godot_pool_byte_array_read_access *p_read) {
+ const PoolVector<uint8_t>::Read *read = (const PoolVector<uint8_t>::Read *)p_read;
+ return read->ptr();
+}
+void GDAPI godot_pool_byte_array_read_access_operator_assign(godot_pool_byte_array_read_access *p_read, godot_pool_byte_array_read_access *p_other) {
+ PoolVector<uint8_t>::Read *read = (PoolVector<uint8_t>::Read *)p_read;
+ PoolVector<uint8_t>::Read *other = (PoolVector<uint8_t>::Read *)p_other;
+ read->operator=(*other);
+}
+void GDAPI godot_pool_byte_array_read_access_destroy(godot_pool_byte_array_read_access *p_read) {
+ memdelete((PoolVector<uint8_t>::Read *)p_read);
+}
+
+const godot_int GDAPI *godot_pool_int_array_read_access_ptr(const godot_pool_int_array_read_access *p_read) {
+ const PoolVector<godot_int>::Read *read = (const PoolVector<godot_int>::Read *)p_read;
+ return read->ptr();
+}
+void GDAPI godot_pool_int_array_read_access_operator_assign(godot_pool_int_array_read_access *p_read, godot_pool_int_array_read_access *p_other) {
+ PoolVector<godot_int>::Read *read = (PoolVector<godot_int>::Read *)p_read;
+ PoolVector<godot_int>::Read *other = (PoolVector<godot_int>::Read *)p_other;
+ read->operator=(*other);
+}
+void GDAPI godot_pool_int_array_read_access_destroy(godot_pool_int_array_read_access *p_read) {
+ memdelete((PoolVector<godot_int>::Read *)p_read);
+}
+
+const godot_real GDAPI *godot_pool_real_array_read_access_ptr(const godot_pool_real_array_read_access *p_read) {
+ const PoolVector<godot_real>::Read *read = (const PoolVector<godot_real>::Read *)p_read;
+ return read->ptr();
+}
+void GDAPI godot_pool_real_array_read_access_operator_assign(godot_pool_real_array_read_access *p_read, godot_pool_real_array_read_access *p_other) {
+ PoolVector<godot_real>::Read *read = (PoolVector<godot_real>::Read *)p_read;
+ PoolVector<godot_real>::Read *other = (PoolVector<godot_real>::Read *)p_other;
+ read->operator=(*other);
+}
+void GDAPI godot_pool_real_array_read_access_destroy(godot_pool_real_array_read_access *p_read) {
+ memdelete((PoolVector<godot_real>::Read *)p_read);
+}
+
+const godot_string GDAPI *godot_pool_string_array_read_access_ptr(const godot_pool_string_array_read_access *p_read) {
+ const PoolVector<String>::Read *read = (const PoolVector<String>::Read *)p_read;
+ return (const godot_string *)read->ptr();
+}
+void GDAPI godot_pool_string_array_read_access_operator_assign(godot_pool_string_array_read_access *p_read, godot_pool_string_array_read_access *p_other) {
+ PoolVector<String>::Read *read = (PoolVector<String>::Read *)p_read;
+ PoolVector<String>::Read *other = (PoolVector<String>::Read *)p_other;
+ read->operator=(*other);
+}
+void GDAPI godot_pool_string_array_read_access_destroy(godot_pool_string_array_read_access *p_read) {
+ memdelete((PoolVector<String>::Read *)p_read);
+}
+
+const godot_vector2 GDAPI *godot_pool_vector2_array_read_access_ptr(const godot_pool_vector2_array_read_access *p_read) {
+ const PoolVector<Vector2>::Read *read = (const PoolVector<Vector2>::Read *)p_read;
+ return (const godot_vector2 *)read->ptr();
+}
+void GDAPI godot_pool_vector2_array_read_access_operator_assign(godot_pool_vector2_array_read_access *p_read, godot_pool_vector2_array_read_access *p_other) {
+ PoolVector<Vector2>::Read *read = (PoolVector<Vector2>::Read *)p_read;
+ PoolVector<Vector2>::Read *other = (PoolVector<Vector2>::Read *)p_other;
+ read->operator=(*other);
+}
+void GDAPI godot_pool_vector2_array_read_access_destroy(godot_pool_vector2_array_read_access *p_read) {
+ memdelete((PoolVector<Vector2>::Read *)p_read);
+}
+
+const godot_vector3 GDAPI *godot_pool_vector3_array_read_access_ptr(const godot_pool_vector3_array_read_access *p_read) {
+ const PoolVector<Vector3>::Read *read = (const PoolVector<Vector3>::Read *)p_read;
+ return (const godot_vector3 *)read->ptr();
+}
+void GDAPI godot_pool_vector3_array_read_access_operator_assign(godot_pool_vector3_array_read_access *p_read, godot_pool_vector3_array_read_access *p_other) {
+ PoolVector<Vector3>::Read *read = (PoolVector<Vector3>::Read *)p_read;
+ PoolVector<Vector3>::Read *other = (PoolVector<Vector3>::Read *)p_other;
+ read->operator=(*other);
+}
+void GDAPI godot_pool_vector3_array_read_access_destroy(godot_pool_vector3_array_read_access *p_read) {
+ memdelete((PoolVector<Vector2>::Read *)p_read);
+}
+
+const godot_color GDAPI *godot_pool_color_array_read_access_ptr(const godot_pool_color_array_read_access *p_read) {
+ const PoolVector<Color>::Read *read = (const PoolVector<Color>::Read *)p_read;
+ return (const godot_color *)read->ptr();
+}
+void GDAPI godot_pool_color_array_read_access_operator_assign(godot_pool_color_array_read_access *p_read, godot_pool_color_array_read_access *p_other) {
+ PoolVector<Color>::Read *read = (PoolVector<Color>::Read *)p_read;
+ PoolVector<Color>::Read *other = (PoolVector<Color>::Read *)p_other;
+ read->operator=(*other);
+}
+void GDAPI godot_pool_color_array_read_access_destroy(godot_pool_color_array_read_access *p_read) {
+ memdelete((PoolVector<Color>::Read *)p_read);
+}
+
+//
+// write accessor functions
+//
+
+uint8_t GDAPI *godot_pool_byte_array_write_access_ptr(const godot_pool_byte_array_write_access *p_write) {
+ PoolVector<uint8_t>::Write *write = (PoolVector<uint8_t>::Write *)p_write;
+ return write->ptr();
+}
+void GDAPI godot_pool_byte_array_write_access_operator_assign(godot_pool_byte_array_write_access *p_write, godot_pool_byte_array_write_access *p_other) {
+ PoolVector<uint8_t>::Write *write = (PoolVector<uint8_t>::Write *)p_write;
+ PoolVector<uint8_t>::Write *other = (PoolVector<uint8_t>::Write *)p_other;
+ write->operator=(*other);
+}
+void GDAPI godot_pool_byte_array_write_access_destroy(godot_pool_byte_array_write_access *p_write) {
+ memdelete((PoolVector<uint8_t>::Write *)p_write);
+}
+
+godot_int GDAPI *godot_pool_int_array_write_access_ptr(const godot_pool_int_array_write_access *p_write) {
+ PoolVector<godot_int>::Write *write = (PoolVector<godot_int>::Write *)p_write;
+ return write->ptr();
+}
+void GDAPI godot_pool_int_array_write_access_operator_assign(godot_pool_int_array_write_access *p_write, godot_pool_int_array_write_access *p_other) {
+ PoolVector<godot_int>::Write *write = (PoolVector<godot_int>::Write *)p_write;
+ PoolVector<godot_int>::Write *other = (PoolVector<godot_int>::Write *)p_other;
+ write->operator=(*other);
+}
+void GDAPI godot_pool_int_array_write_access_destroy(godot_pool_int_array_write_access *p_write) {
+ memdelete((PoolVector<godot_int>::Write *)p_write);
+}
+
+godot_real GDAPI *godot_pool_real_array_write_access_ptr(const godot_pool_real_array_write_access *p_write) {
+ PoolVector<godot_real>::Write *write = (PoolVector<godot_real>::Write *)p_write;
+ return write->ptr();
+}
+void GDAPI godot_pool_real_array_write_access_operator_assign(godot_pool_real_array_write_access *p_write, godot_pool_real_array_write_access *p_other) {
+ PoolVector<godot_real>::Write *write = (PoolVector<godot_real>::Write *)p_write;
+ PoolVector<godot_real>::Write *other = (PoolVector<godot_real>::Write *)p_other;
+ write->operator=(*other);
+}
+void GDAPI godot_pool_real_array_write_access_destroy(godot_pool_real_array_write_access *p_write) {
+ memdelete((PoolVector<godot_real>::Write *)p_write);
+}
+
+godot_string GDAPI *godot_pool_string_array_write_access_ptr(const godot_pool_string_array_write_access *p_write) {
+ PoolVector<String>::Write *write = (PoolVector<String>::Write *)p_write;
+ return (godot_string *)write->ptr();
+}
+void GDAPI godot_pool_string_array_write_access_operator_assign(godot_pool_string_array_write_access *p_write, godot_pool_string_array_write_access *p_other) {
+ PoolVector<String>::Write *write = (PoolVector<String>::Write *)p_write;
+ PoolVector<String>::Write *other = (PoolVector<String>::Write *)p_other;
+ write->operator=(*other);
+}
+void GDAPI godot_pool_string_array_write_access_destroy(godot_pool_string_array_write_access *p_write) {
+ memdelete((PoolVector<String>::Write *)p_write);
+}
+
+godot_vector2 GDAPI *godot_pool_vector2_array_write_access_ptr(const godot_pool_vector2_array_write_access *p_write) {
+ PoolVector<Vector2>::Write *write = (PoolVector<Vector2>::Write *)p_write;
+ return (godot_vector2 *)write->ptr();
+}
+void GDAPI godot_pool_vector2_array_write_access_operator_assign(godot_pool_vector2_array_write_access *p_write, godot_pool_vector2_array_write_access *p_other) {
+ PoolVector<Vector2>::Write *write = (PoolVector<Vector2>::Write *)p_write;
+ PoolVector<Vector2>::Write *other = (PoolVector<Vector2>::Write *)p_other;
+ write->operator=(*other);
+}
+void GDAPI godot_pool_vector2_array_write_access_destroy(godot_pool_vector2_array_write_access *p_write) {
+ memdelete((PoolVector<Vector2>::Write *)p_write);
+}
+
+godot_vector3 GDAPI *godot_pool_vector3_array_write_access_ptr(const godot_pool_vector3_array_write_access *p_write) {
+ PoolVector<Vector3>::Write *write = (PoolVector<Vector3>::Write *)p_write;
+ return (godot_vector3 *)write->ptr();
+}
+void GDAPI godot_pool_vector3_array_write_access_operator_assign(godot_pool_vector3_array_write_access *p_write, godot_pool_vector3_array_write_access *p_other) {
+ PoolVector<Vector3>::Write *write = (PoolVector<Vector3>::Write *)p_write;
+ PoolVector<Vector3>::Write *other = (PoolVector<Vector3>::Write *)p_other;
+ write->operator=(*other);
+}
+void GDAPI godot_pool_vector3_array_write_access_destroy(godot_pool_vector3_array_write_access *p_write) {
+ memdelete((PoolVector<Vector3>::Write *)p_write);
+}
+
+godot_color GDAPI *godot_pool_color_array_write_access_ptr(const godot_pool_color_array_write_access *p_write) {
+ PoolVector<Color>::Write *write = (PoolVector<Color>::Write *)p_write;
+ return (godot_color *)write->ptr();
+}
+void GDAPI godot_pool_color_array_write_access_operator_assign(godot_pool_color_array_write_access *p_write, godot_pool_color_array_write_access *p_other) {
+ PoolVector<Color>::Write *write = (PoolVector<Color>::Write *)p_write;
+ PoolVector<Color>::Write *other = (PoolVector<Color>::Write *)p_other;
+ write->operator=(*other);
+}
+void GDAPI godot_pool_color_array_write_access_destroy(godot_pool_color_array_write_access *p_write) {
+ memdelete((PoolVector<Color>::Write *)p_write);
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/modules/gdnative/gdnative/quat.cpp b/modules/gdnative/gdnative/quat.cpp
index 7db7847da1..2d012c069f 100644
--- a/modules/gdnative/gdnative/quat.cpp
+++ b/modules/gdnative/gdnative/quat.cpp
@@ -36,8 +36,6 @@
extern "C" {
#endif
-void _quat_api_anchor() {}
-
void GDAPI godot_quat_new(godot_quat *r_dest, const godot_real p_x, const godot_real p_y, const godot_real p_z, const godot_real p_w) {
Quat *dest = (Quat *)r_dest;
diff --git a/modules/gdnative/gdnative/rect2.cpp b/modules/gdnative/gdnative/rect2.cpp
index ecd8cce9ca..b0b0e28138 100644
--- a/modules/gdnative/gdnative/rect2.cpp
+++ b/modules/gdnative/gdnative/rect2.cpp
@@ -36,8 +36,6 @@
extern "C" {
#endif
-void _rect2_api_anchor() {}
-
void GDAPI godot_rect2_new_with_position_and_size(godot_rect2 *r_dest, const godot_vector2 *p_pos, const godot_vector2 *p_size) {
const Vector2 *position = (const Vector2 *)p_pos;
const Vector2 *size = (const Vector2 *)p_size;
diff --git a/modules/gdnative/gdnative/rect3.cpp b/modules/gdnative/gdnative/rect3.cpp
deleted file mode 100644
index d34d964db9..0000000000
--- a/modules/gdnative/gdnative/rect3.cpp
+++ /dev/null
@@ -1,219 +0,0 @@
-/*************************************************************************/
-/* rect3.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#include "gdnative/rect3.h"
-
-#include "core/math/rect3.h"
-#include "core/variant.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-void _rect3_api_anchor() {}
-
-void GDAPI godot_rect3_new(godot_rect3 *r_dest, const godot_vector3 *p_pos, const godot_vector3 *p_size) {
- const Vector3 *pos = (const Vector3 *)p_pos;
- const Vector3 *size = (const Vector3 *)p_size;
- Rect3 *dest = (Rect3 *)r_dest;
- *dest = Rect3(*pos, *size);
-}
-
-godot_vector3 GDAPI godot_rect3_get_position(const godot_rect3 *p_self) {
- godot_vector3 raw_ret;
- const Rect3 *self = (const Rect3 *)p_self;
- Vector3 *ret = (Vector3 *)&raw_ret;
- *ret = self->position;
- return raw_ret;
-}
-
-void GDAPI godot_rect3_set_position(const godot_rect3 *p_self, const godot_vector3 *p_v) {
- Rect3 *self = (Rect3 *)p_self;
- const Vector3 *v = (const Vector3 *)p_v;
- self->position = *v;
-}
-
-godot_vector3 GDAPI godot_rect3_get_size(const godot_rect3 *p_self) {
- godot_vector3 raw_ret;
- const Rect3 *self = (const Rect3 *)p_self;
- Vector3 *ret = (Vector3 *)&raw_ret;
- *ret = self->size;
- return raw_ret;
-}
-
-void GDAPI godot_rect3_set_size(const godot_rect3 *p_self, const godot_vector3 *p_v) {
- Rect3 *self = (Rect3 *)p_self;
- const Vector3 *v = (const Vector3 *)p_v;
- self->size = *v;
-}
-
-godot_string GDAPI godot_rect3_as_string(const godot_rect3 *p_self) {
- godot_string ret;
- const Rect3 *self = (const Rect3 *)p_self;
- memnew_placement(&ret, String(*self));
- return ret;
-}
-
-godot_real GDAPI godot_rect3_get_area(const godot_rect3 *p_self) {
- const Rect3 *self = (const Rect3 *)p_self;
- return self->get_area();
-}
-
-godot_bool GDAPI godot_rect3_has_no_area(const godot_rect3 *p_self) {
- const Rect3 *self = (const Rect3 *)p_self;
- return self->has_no_area();
-}
-
-godot_bool GDAPI godot_rect3_has_no_surface(const godot_rect3 *p_self) {
- const Rect3 *self = (const Rect3 *)p_self;
- return self->has_no_surface();
-}
-
-godot_bool GDAPI godot_rect3_intersects(const godot_rect3 *p_self, const godot_rect3 *p_with) {
- const Rect3 *self = (const Rect3 *)p_self;
- const Rect3 *with = (const Rect3 *)p_with;
- return self->intersects(*with);
-}
-
-godot_bool GDAPI godot_rect3_encloses(const godot_rect3 *p_self, const godot_rect3 *p_with) {
- const Rect3 *self = (const Rect3 *)p_self;
- const Rect3 *with = (const Rect3 *)p_with;
- return self->encloses(*with);
-}
-
-godot_rect3 GDAPI godot_rect3_merge(const godot_rect3 *p_self, const godot_rect3 *p_with) {
- godot_rect3 dest;
- const Rect3 *self = (const Rect3 *)p_self;
- const Rect3 *with = (const Rect3 *)p_with;
- *((Rect3 *)&dest) = self->merge(*with);
- return dest;
-}
-
-godot_rect3 GDAPI godot_rect3_intersection(const godot_rect3 *p_self, const godot_rect3 *p_with) {
- godot_rect3 dest;
- const Rect3 *self = (const Rect3 *)p_self;
- const Rect3 *with = (const Rect3 *)p_with;
- *((Rect3 *)&dest) = self->intersection(*with);
- return dest;
-}
-
-godot_bool GDAPI godot_rect3_intersects_plane(const godot_rect3 *p_self, const godot_plane *p_plane) {
- const Rect3 *self = (const Rect3 *)p_self;
- const Plane *plane = (const Plane *)p_plane;
- return self->intersects_plane(*plane);
-}
-
-godot_bool GDAPI godot_rect3_intersects_segment(const godot_rect3 *p_self, const godot_vector3 *p_from, const godot_vector3 *p_to) {
- const Rect3 *self = (const Rect3 *)p_self;
- const Vector3 *from = (const Vector3 *)p_from;
- const Vector3 *to = (const Vector3 *)p_to;
- return self->intersects_segment(*from, *to);
-}
-
-godot_bool GDAPI godot_rect3_has_point(const godot_rect3 *p_self, const godot_vector3 *p_point) {
- const Rect3 *self = (const Rect3 *)p_self;
- const Vector3 *point = (const Vector3 *)p_point;
- return self->has_point(*point);
-}
-
-godot_vector3 GDAPI godot_rect3_get_support(const godot_rect3 *p_self, const godot_vector3 *p_dir) {
- godot_vector3 dest;
- const Rect3 *self = (const Rect3 *)p_self;
- const Vector3 *dir = (const Vector3 *)p_dir;
- *((Vector3 *)&dest) = self->get_support(*dir);
- return dest;
-}
-
-godot_vector3 GDAPI godot_rect3_get_longest_axis(const godot_rect3 *p_self) {
- godot_vector3 dest;
- const Rect3 *self = (const Rect3 *)p_self;
- *((Vector3 *)&dest) = self->get_longest_axis();
- return dest;
-}
-
-godot_int GDAPI godot_rect3_get_longest_axis_index(const godot_rect3 *p_self) {
- const Rect3 *self = (const Rect3 *)p_self;
- return self->get_longest_axis_index();
-}
-
-godot_real GDAPI godot_rect3_get_longest_axis_size(const godot_rect3 *p_self) {
- const Rect3 *self = (const Rect3 *)p_self;
- return self->get_longest_axis_size();
-}
-
-godot_vector3 GDAPI godot_rect3_get_shortest_axis(const godot_rect3 *p_self) {
- godot_vector3 dest;
- const Rect3 *self = (const Rect3 *)p_self;
- *((Vector3 *)&dest) = self->get_shortest_axis();
- return dest;
-}
-
-godot_int GDAPI godot_rect3_get_shortest_axis_index(const godot_rect3 *p_self) {
- const Rect3 *self = (const Rect3 *)p_self;
- return self->get_shortest_axis_index();
-}
-
-godot_real GDAPI godot_rect3_get_shortest_axis_size(const godot_rect3 *p_self) {
- const Rect3 *self = (const Rect3 *)p_self;
- return self->get_shortest_axis_size();
-}
-
-godot_rect3 GDAPI godot_rect3_expand(const godot_rect3 *p_self, const godot_vector3 *p_to_point) {
- godot_rect3 dest;
- const Rect3 *self = (const Rect3 *)p_self;
- const Vector3 *to_point = (const Vector3 *)p_to_point;
- *((Rect3 *)&dest) = self->expand(*to_point);
- return dest;
-}
-
-godot_rect3 GDAPI godot_rect3_grow(const godot_rect3 *p_self, const godot_real p_by) {
- godot_rect3 dest;
- const Rect3 *self = (const Rect3 *)p_self;
-
- *((Rect3 *)&dest) = self->grow(p_by);
- return dest;
-}
-
-godot_vector3 GDAPI godot_rect3_get_endpoint(const godot_rect3 *p_self, const godot_int p_idx) {
- godot_vector3 dest;
- const Rect3 *self = (const Rect3 *)p_self;
-
- *((Vector3 *)&dest) = self->get_endpoint(p_idx);
- return dest;
-}
-
-godot_bool GDAPI godot_rect3_operator_equal(const godot_rect3 *p_self, const godot_rect3 *p_b) {
- const Rect3 *self = (const Rect3 *)p_self;
- const Rect3 *b = (const Rect3 *)p_b;
- return *self == *b;
-}
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/modules/gdnative/gdnative/rid.cpp b/modules/gdnative/gdnative/rid.cpp
index f05c39906c..c6e8d82494 100644
--- a/modules/gdnative/gdnative/rid.cpp
+++ b/modules/gdnative/gdnative/rid.cpp
@@ -37,8 +37,6 @@
extern "C" {
#endif
-void _rid_api_anchor() {}
-
void GDAPI godot_rid_new(godot_rid *r_dest) {
RID *dest = (RID *)r_dest;
memnew_placement(dest, RID);
diff --git a/modules/gdnative/gdnative/string.cpp b/modules/gdnative/gdnative/string.cpp
index 9b715ce36a..67a037736c 100644
--- a/modules/gdnative/gdnative/string.cpp
+++ b/modules/gdnative/gdnative/string.cpp
@@ -29,9 +29,9 @@
/*************************************************************************/
#include "gdnative/string.h"
+#include "core/string_db.h"
+#include "core/ustring.h"
#include "core/variant.h"
-#include "string_db.h"
-#include "ustring.h"
#include <string.h>
@@ -39,9 +39,6 @@
extern "C" {
#endif
-void _string_api_anchor() {
-}
-
void GDAPI godot_string_new(godot_string *r_dest) {
String *dest = (String *)r_dest;
memnew_placement(dest, String);
@@ -65,11 +62,20 @@ void GDAPI godot_string_new_unicode_data(godot_string *r_dest, const wchar_t *p_
void GDAPI godot_string_get_data(const godot_string *p_self, char *p_dest, int *p_size) {
String *self = (String *)p_self;
- if (p_size != NULL) {
- *p_size = self->utf8().length();
- }
- if (p_dest != NULL) {
- memcpy(p_dest, self->utf8().get_data(), *p_size);
+
+ if (p_size) {
+ // we have a length pointer, that means we either want to know
+ // the length or want to write *p_size bytes into a buffer
+
+ CharString utf8_string = self->utf8();
+
+ int len = utf8_string.length();
+
+ if (p_dest) {
+ memcpy(p_dest, utf8_string.get_data(), *p_size);
+ } else {
+ *p_size = len;
+ }
}
}
@@ -78,9 +84,9 @@ wchar_t GDAPI *godot_string_operator_index(godot_string *p_self, const godot_int
return &(self->operator[](p_idx));
}
-const char GDAPI *godot_string_c_str(const godot_string *p_self) {
+wchar_t GDAPI godot_string_operator_index_const(const godot_string *p_self, const godot_int p_idx) {
const String *self = (const String *)p_self;
- return self->utf8().get_data();
+ return self->operator[](p_idx);
}
const wchar_t GDAPI *godot_string_unicode_str(const godot_string *p_self) {
diff --git a/modules/gdnative/gdnative/string_name.cpp b/modules/gdnative/gdnative/string_name.cpp
new file mode 100644
index 0000000000..5c79e0acbd
--- /dev/null
+++ b/modules/gdnative/gdnative/string_name.cpp
@@ -0,0 +1,88 @@
+/*************************************************************************/
+/* string_name.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#include "gdnative/string_name.h"
+
+#include "core/string_db.h"
+#include "core/ustring.h"
+
+#include <string.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void GDAPI godot_string_name_new(godot_string_name *r_dest, const godot_string *p_name) {
+ StringName *dest = (StringName *)r_dest;
+ const String *name = (const String *)p_name;
+ memnew_placement(dest, StringName(*name));
+}
+
+void GDAPI godot_string_name_new_data(godot_string_name *r_dest, const char *p_name) {
+ StringName *dest = (StringName *)r_dest;
+ memnew_placement(dest, StringName(p_name));
+}
+
+godot_string GDAPI godot_string_name_get_name(const godot_string_name *p_self) {
+ godot_string ret;
+ const StringName *self = (const StringName *)p_self;
+ memnew_placement(&ret, String(*self));
+ return ret;
+}
+
+uint32_t GDAPI godot_string_name_get_hash(const godot_string_name *p_self) {
+ const StringName *self = (const StringName *)p_self;
+ return self->hash();
+}
+
+const void GDAPI *godot_string_name_get_data_unique_pointer(const godot_string_name *p_self) {
+ const StringName *self = (const StringName *)p_self;
+ return self->data_unique_pointer();
+}
+
+godot_bool GDAPI godot_string_name_operator_equal(const godot_string_name *p_self, const godot_string_name *p_other) {
+ const StringName *self = (const StringName *)p_self;
+ const StringName *other = (const StringName *)p_other;
+ return self == other;
+}
+
+godot_bool GDAPI godot_string_name_operator_less(const godot_string_name *p_self, const godot_string_name *p_other) {
+ const StringName *self = (const StringName *)p_self;
+ const StringName *other = (const StringName *)p_other;
+ return self < other;
+}
+
+void GDAPI godot_string_name_destroy(godot_string_name *p_self) {
+ StringName *self = (StringName *)p_self;
+ self->~StringName();
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/modules/gdnative/gdnative/transform.cpp b/modules/gdnative/gdnative/transform.cpp
index d7a3e78d3f..b07fcffcb6 100644
--- a/modules/gdnative/gdnative/transform.cpp
+++ b/modules/gdnative/gdnative/transform.cpp
@@ -36,8 +36,6 @@
extern "C" {
#endif
-void _transform_api_anchor() {}
-
void GDAPI godot_transform_new_with_axis_origin(godot_transform *r_dest, const godot_vector3 *p_x_axis, const godot_vector3 *p_y_axis, const godot_vector3 *p_z_axis, const godot_vector3 *p_origin) {
const Vector3 *x_axis = (const Vector3 *)p_x_axis;
const Vector3 *y_axis = (const Vector3 *)p_y_axis;
@@ -200,20 +198,20 @@ godot_vector3 GDAPI godot_transform_xform_inv_vector3(const godot_transform *p_s
return raw_dest;
}
-godot_rect3 GDAPI godot_transform_xform_rect3(const godot_transform *p_self, const godot_rect3 *p_v) {
- godot_rect3 raw_dest;
- Rect3 *dest = (Rect3 *)&raw_dest;
+godot_aabb GDAPI godot_transform_xform_aabb(const godot_transform *p_self, const godot_aabb *p_v) {
+ godot_aabb raw_dest;
+ AABB *dest = (AABB *)&raw_dest;
const Transform *self = (const Transform *)p_self;
- const Rect3 *v = (const Rect3 *)p_v;
+ const AABB *v = (const AABB *)p_v;
*dest = self->xform(*v);
return raw_dest;
}
-godot_rect3 GDAPI godot_transform_xform_inv_rect3(const godot_transform *p_self, const godot_rect3 *p_v) {
- godot_rect3 raw_dest;
- Rect3 *dest = (Rect3 *)&raw_dest;
+godot_aabb GDAPI godot_transform_xform_inv_aabb(const godot_transform *p_self, const godot_aabb *p_v) {
+ godot_aabb raw_dest;
+ AABB *dest = (AABB *)&raw_dest;
const Transform *self = (const Transform *)p_self;
- const Rect3 *v = (const Rect3 *)p_v;
+ const AABB *v = (const AABB *)p_v;
*dest = self->xform_inv(*v);
return raw_dest;
}
diff --git a/modules/gdnative/gdnative/transform2d.cpp b/modules/gdnative/gdnative/transform2d.cpp
index dcb54f7a53..0a6334516b 100644
--- a/modules/gdnative/gdnative/transform2d.cpp
+++ b/modules/gdnative/gdnative/transform2d.cpp
@@ -36,8 +36,6 @@
extern "C" {
#endif
-void _transform2d_api_anchor() {}
-
void GDAPI godot_transform2d_new(godot_transform2d *r_dest, const godot_real p_rot, const godot_vector2 *p_pos) {
const Vector2 *pos = (const Vector2 *)p_pos;
Transform2D *dest = (Transform2D *)r_dest;
diff --git a/modules/gdnative/gdnative/variant.cpp b/modules/gdnative/gdnative/variant.cpp
index 9ba4166c1d..6483d19d74 100644
--- a/modules/gdnative/gdnative/variant.cpp
+++ b/modules/gdnative/gdnative/variant.cpp
@@ -36,8 +36,6 @@
extern "C" {
#endif
-void _variant_api_anchor() {}
-
#define memnew_placement_custom(m_placement, m_class, m_constr) _post_initialize(new (m_placement, sizeof(m_class), "") m_constr)
// Constructors
@@ -120,10 +118,10 @@ void GDAPI godot_variant_new_quat(godot_variant *r_dest, const godot_quat *p_qua
memnew_placement_custom(dest, Variant, Variant(*quat));
}
-void GDAPI godot_variant_new_rect3(godot_variant *r_dest, const godot_rect3 *p_rect3) {
+void GDAPI godot_variant_new_aabb(godot_variant *r_dest, const godot_aabb *p_aabb) {
Variant *dest = (Variant *)r_dest;
- Rect3 *rect3 = (Rect3 *)p_rect3;
- memnew_placement_custom(dest, Variant, Variant(*rect3));
+ AABB *aabb = (AABB *)p_aabb;
+ memnew_placement_custom(dest, Variant, Variant(*aabb));
}
void GDAPI godot_variant_new_basis(godot_variant *r_dest, const godot_basis *p_basis) {
@@ -306,10 +304,10 @@ godot_quat GDAPI godot_variant_as_quat(const godot_variant *p_self) {
return raw_dest;
}
-godot_rect3 GDAPI godot_variant_as_rect3(const godot_variant *p_self) {
- godot_rect3 raw_dest;
+godot_aabb GDAPI godot_variant_as_aabb(const godot_variant *p_self) {
+ godot_aabb raw_dest;
const Variant *self = (const Variant *)p_self;
- Rect3 *dest = (Rect3 *)&raw_dest;
+ AABB *dest = (AABB *)&raw_dest;
*dest = *self;
return raw_dest;
}
diff --git a/modules/gdnative/gdnative/vector2.cpp b/modules/gdnative/gdnative/vector2.cpp
index 67f858997f..7a5b29e0c4 100644
--- a/modules/gdnative/gdnative/vector2.cpp
+++ b/modules/gdnative/gdnative/vector2.cpp
@@ -36,8 +36,6 @@
extern "C" {
#endif
-void _vector2_api_anchor() {}
-
void GDAPI godot_vector2_new(godot_vector2 *r_dest, const godot_real p_x, const godot_real p_y) {
Vector2 *dest = (Vector2 *)r_dest;
diff --git a/modules/gdnative/gdnative/vector3.cpp b/modules/gdnative/gdnative/vector3.cpp
index c85a3f1c08..11ffb3320b 100644
--- a/modules/gdnative/gdnative/vector3.cpp
+++ b/modules/gdnative/gdnative/vector3.cpp
@@ -36,8 +36,6 @@
extern "C" {
#endif
-void _vector3_api_anchor() {}
-
void GDAPI godot_vector3_new(godot_vector3 *r_dest, const godot_real p_x, const godot_real p_y, const godot_real p_z) {
Vector3 *dest = (Vector3 *)r_dest;
diff --git a/modules/gdnative/gdnative_api.json b/modules/gdnative/gdnative_api.json
index 8b6593c9c3..0438a196cf 100644
--- a/modules/gdnative/gdnative_api.json
+++ b/modules/gdnative/gdnative_api.json
@@ -1,4511 +1,5812 @@
{
- "version": "1.0.0",
- "api": {
- "godot_color_new_rgba": {
- "return_type": "void",
- "arguments": [
- ["godot_color *", "r_dest"],
- ["const godot_real", "p_r"],
- ["const godot_real", "p_g"],
- ["const godot_real", "p_b"],
- ["const godot_real", "p_a"]
- ]
- },
- "godot_color_new_rgb": {
- "return_type": "void",
- "arguments": [
- ["godot_color *", "r_dest"],
- ["const godot_real", "p_r"],
- ["const godot_real", "p_g"],
- ["const godot_real", "p_b"]
- ]
- },
- "godot_color_get_r": {
- "return_type": "godot_real",
- "arguments": [
- ["const godot_color *", "p_self"]
- ]
- },
- "godot_color_set_r": {
- "return_type": "void",
- "arguments": [
- ["godot_color *", "p_self"],
- ["const godot_real", "r"]
- ]
- },
- "godot_color_get_g": {
- "return_type": "godot_real",
- "arguments": [
- ["const godot_color *", "p_self"]
- ]
- },
- "godot_color_set_g": {
- "return_type": "void",
- "arguments": [
- ["godot_color *", "p_self"],
- ["const godot_real", "g"]
- ]
- },
- "godot_color_get_b": {
- "return_type": "godot_real",
- "arguments": [
- ["const godot_color *", "p_self"]
- ]
- },
- "godot_color_set_b": {
- "return_type": "void",
- "arguments": [
- ["godot_color *", "p_self"],
- ["const godot_real", "b"]
- ]
- },
- "godot_color_get_a": {
- "return_type": "godot_real",
- "arguments": [
- ["const godot_color *", "p_self"]
- ]
- },
- "godot_color_set_a": {
- "return_type": "void",
- "arguments": [
- ["godot_color *", "p_self"],
- ["const godot_real", "a"]
- ]
- },
- "godot_color_get_h": {
- "return_type": "godot_real",
- "arguments": [
- ["const godot_color *", "p_self"]
- ]
- },
- "godot_color_get_s": {
- "return_type": "godot_real",
- "arguments": [
- ["const godot_color *", "p_self"]
- ]
- },
- "godot_color_get_v": {
- "return_type": "godot_real",
- "arguments": [
- ["const godot_color *", "p_self"]
- ]
- },
- "godot_color_as_string": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_color *", "p_self"]
- ]
- },
- "godot_color_to_rgba32": {
- "return_type": "godot_int",
- "arguments": [
- ["const godot_color *", "p_self"]
- ]
- },
- "godot_color_to_argb32": {
- "return_type": "godot_int",
- "arguments": [
- ["const godot_color *", "p_self"]
- ]
- },
- "godot_color_gray": {
- "return_type": "godot_real",
- "arguments": [
- ["const godot_color *", "p_self"]
- ]
- },
- "godot_color_inverted": {
- "return_type": "godot_color",
- "arguments": [
- ["const godot_color *", "p_self"]
- ]
- },
- "godot_color_contrasted": {
- "return_type": "godot_color",
- "arguments": [
- ["const godot_color *", "p_self"]
- ]
- },
- "godot_color_linear_interpolate": {
- "return_type": "godot_color",
- "arguments": [
- ["const godot_color *", "p_self"],
- ["const godot_color *", "p_b"],
- ["const godot_real", "p_t"]
- ]
- },
- "godot_color_blend": {
- "return_type": "godot_color",
- "arguments": [
- ["const godot_color *", "p_self"],
- ["const godot_color *", "p_over"]
- ]
- },
- "godot_color_to_html": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_color *", "p_self"],
- ["const godot_bool", "p_with_alpha"]
- ]
- },
- "godot_color_operator_equal": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_color *", "p_self"],
- ["const godot_color *", "p_b"]
- ]
- },
- "godot_color_operator_less": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_color *", "p_self"],
- ["const godot_color *", "p_b"]
- ]
- },
- "godot_vector2_new": {
- "return_type": "void",
- "arguments": [
- ["godot_vector2 *", "r_dest"],
- ["const godot_real", "p_x"],
- ["const godot_real", "p_y"]
- ]
- },
- "godot_vector2_as_string": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_vector2 *", "p_self"]
- ]
- },
- "godot_vector2_normalized": {
- "return_type": "godot_vector2",
- "arguments": [
- ["const godot_vector2 *", "p_self"]
- ]
- },
- "godot_vector2_length": {
- "return_type": "godot_real",
- "arguments": [
- ["const godot_vector2 *", "p_self"]
- ]
- },
- "godot_vector2_angle": {
- "return_type": "godot_real",
- "arguments": [
- ["const godot_vector2 *", "p_self"]
- ]
- },
- "godot_vector2_length_squared": {
- "return_type": "godot_real",
- "arguments": [
- ["const godot_vector2 *", "p_self"]
- ]
- },
- "godot_vector2_is_normalized": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_vector2 *", "p_self"]
- ]
- },
- "godot_vector2_distance_to": {
- "return_type": "godot_real",
- "arguments": [
- ["const godot_vector2 *", "p_self"],
- ["const godot_vector2 *", "p_to"]
- ]
- },
- "godot_vector2_distance_squared_to": {
- "return_type": "godot_real",
- "arguments": [
- ["const godot_vector2 *", "p_self"],
- ["const godot_vector2 *", "p_to"]
- ]
- },
- "godot_vector2_angle_to": {
- "return_type": "godot_real",
- "arguments": [
- ["const godot_vector2 *", "p_self"],
- ["const godot_vector2 *", "p_to"]
- ]
- },
- "godot_vector2_angle_to_point": {
- "return_type": "godot_real",
- "arguments": [
- ["const godot_vector2 *", "p_self"],
- ["const godot_vector2 *", "p_to"]
- ]
- },
- "godot_vector2_linear_interpolate": {
- "return_type": "godot_vector2",
- "arguments": [
- ["const godot_vector2 *", "p_self"],
- ["const godot_vector2 *", "p_b"],
- ["const godot_real", "p_t"]
- ]
- },
- "godot_vector2_cubic_interpolate": {
- "return_type": "godot_vector2",
- "arguments": [
- ["const godot_vector2 *", "p_self"],
- ["const godot_vector2 *", "p_b"],
- ["const godot_vector2 *", "p_pre_a"],
- ["const godot_vector2 *", "p_post_b"],
- ["const godot_real", "p_t"]
- ]
- },
- "godot_vector2_rotated": {
- "return_type": "godot_vector2",
- "arguments": [
- ["const godot_vector2 *", "p_self"],
- ["const godot_real", "p_phi"]
- ]
- },
- "godot_vector2_tangent": {
- "return_type": "godot_vector2",
- "arguments": [
- ["const godot_vector2 *", "p_self"]
- ]
- },
- "godot_vector2_floor": {
- "return_type": "godot_vector2",
- "arguments": [
- ["const godot_vector2 *", "p_self"]
- ]
- },
- "godot_vector2_snapped": {
- "return_type": "godot_vector2",
- "arguments": [
- ["const godot_vector2 *", "p_self"],
- ["const godot_vector2 *", "p_by"]
- ]
- },
- "godot_vector2_aspect": {
- "return_type": "godot_real",
- "arguments": [
- ["const godot_vector2 *", "p_self"]
- ]
- },
- "godot_vector2_dot": {
- "return_type": "godot_real",
- "arguments": [
- ["const godot_vector2 *", "p_self"],
- ["const godot_vector2 *", "p_with"]
- ]
- },
- "godot_vector2_slide": {
- "return_type": "godot_vector2",
- "arguments": [
- ["const godot_vector2 *", "p_self"],
- ["const godot_vector2 *", "p_n"]
- ]
- },
- "godot_vector2_bounce": {
- "return_type": "godot_vector2",
- "arguments": [
- ["const godot_vector2 *", "p_self"],
- ["const godot_vector2 *", "p_n"]
- ]
- },
- "godot_vector2_reflect": {
- "return_type": "godot_vector2",
- "arguments": [
- ["const godot_vector2 *", "p_self"],
- ["const godot_vector2 *", "p_n"]
- ]
- },
- "godot_vector2_abs": {
- "return_type": "godot_vector2",
- "arguments": [
- ["const godot_vector2 *", "p_self"]
- ]
- },
- "godot_vector2_clamped": {
- "return_type": "godot_vector2",
- "arguments": [
- ["const godot_vector2 *", "p_self"],
- ["const godot_real", "p_length"]
- ]
- },
- "godot_vector2_operator_add": {
- "return_type": "godot_vector2",
- "arguments": [
- ["const godot_vector2 *", "p_self"],
- ["const godot_vector2 *", "p_b"]
- ]
- },
- "godot_vector2_operator_substract": {
- "return_type": "godot_vector2",
- "arguments": [
- ["const godot_vector2 *", "p_self"],
- ["const godot_vector2 *", "p_b"]
- ]
- },
- "godot_vector2_operator_multiply_vector": {
- "return_type": "godot_vector2",
- "arguments": [
- ["const godot_vector2 *", "p_self"],
- ["const godot_vector2 *", "p_b"]
- ]
- },
- "godot_vector2_operator_multiply_scalar": {
- "return_type": "godot_vector2",
- "arguments": [
- ["const godot_vector2 *", "p_self"],
- ["const godot_real", "p_b"]
- ]
- },
- "godot_vector2_operator_divide_vector": {
- "return_type": "godot_vector2",
- "arguments": [
- ["const godot_vector2 *", "p_self"],
- ["const godot_vector2 *", "p_b"]
- ]
- },
- "godot_vector2_operator_divide_scalar": {
- "return_type": "godot_vector2",
- "arguments": [
- ["const godot_vector2 *", "p_self"],
- ["const godot_real", "p_b"]
- ]
- },
- "godot_vector2_operator_equal": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_vector2 *", "p_self"],
- ["const godot_vector2 *", "p_b"]
- ]
- },
- "godot_vector2_operator_less": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_vector2 *", "p_self"],
- ["const godot_vector2 *", "p_b"]
- ]
- },
- "godot_vector2_operator_neg": {
- "return_type": "godot_vector2",
- "arguments": [
- ["const godot_vector2 *", "p_self"]
- ]
- },
- "godot_vector2_set_x": {
- "return_type": "void",
- "arguments": [
- ["godot_vector2 *", "p_self"],
- ["const godot_real", "p_x"]
- ]
- },
- "godot_vector2_set_y": {
- "return_type": "void",
- "arguments": [
- ["godot_vector2 *", "p_self"],
- ["const godot_real", "p_y"]
- ]
- },
- "godot_vector2_get_x": {
- "return_type": "godot_real",
- "arguments": [
- ["const godot_vector2 *", "p_self"]
- ]
- },
- "godot_vector2_get_y": {
- "return_type": "godot_real",
- "arguments": [
- ["const godot_vector2 *", "p_self"]
- ]
- },
- "godot_quat_new": {
- "return_type": "void",
- "arguments": [
- ["godot_quat *", "r_dest"],
- ["const godot_real", "p_x"],
- ["const godot_real", "p_y"],
- ["const godot_real", "p_z"],
- ["const godot_real", "p_w"]
- ]
- },
- "godot_quat_new_with_axis_angle": {
- "return_type": "void",
- "arguments": [
- ["godot_quat *", "r_dest"],
- ["const godot_vector3 *", "p_axis"],
- ["const godot_real", "p_angle"]
- ]
- },
- "godot_quat_get_x": {
- "return_type": "godot_real",
- "arguments": [
- ["const godot_quat *", "p_self"]
- ]
- },
- "godot_quat_set_x": {
- "return_type": "void",
- "arguments": [
- ["godot_quat *", "p_self"],
- ["const godot_real", "val"]
- ]
- },
- "godot_quat_get_y": {
- "return_type": "godot_real",
- "arguments": [
- ["const godot_quat *", "p_self"]
- ]
- },
- "godot_quat_set_y": {
- "return_type": "void",
- "arguments": [
- ["godot_quat *", "p_self"],
- ["const godot_real", "val"]
- ]
- },
- "godot_quat_get_z": {
- "return_type": "godot_real",
- "arguments": [
- ["const godot_quat *", "p_self"]
- ]
- },
- "godot_quat_set_z": {
- "return_type": "void",
- "arguments": [
- ["godot_quat *", "p_self"],
- ["const godot_real", "val"]
- ]
- },
- "godot_quat_get_w": {
- "return_type": "godot_real",
- "arguments": [
- ["const godot_quat *", "p_self"]
- ]
- },
- "godot_quat_set_w": {
- "return_type": "void",
- "arguments": [
- ["godot_quat *", "p_self"],
- ["const godot_real", "val"]
- ]
- },
- "godot_quat_as_string": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_quat *", "p_self"]
- ]
- },
- "godot_quat_length": {
- "return_type": "godot_real",
- "arguments": [
- ["const godot_quat *", "p_self"]
- ]
- },
- "godot_quat_length_squared": {
- "return_type": "godot_real",
- "arguments": [
- ["const godot_quat *", "p_self"]
- ]
- },
- "godot_quat_normalized": {
- "return_type": "godot_quat",
- "arguments": [
- ["const godot_quat *", "p_self"]
- ]
- },
- "godot_quat_is_normalized": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_quat *", "p_self"]
- ]
- },
- "godot_quat_inverse": {
- "return_type": "godot_quat",
- "arguments": [
- ["const godot_quat *", "p_self"]
- ]
- },
- "godot_quat_dot": {
- "return_type": "godot_real",
- "arguments": [
- ["const godot_quat *", "p_self"],
- ["const godot_quat *", "p_b"]
- ]
- },
- "godot_quat_xform": {
- "return_type": "godot_vector3",
- "arguments": [
- ["const godot_quat *", "p_self"],
- ["const godot_vector3 *", "p_v"]
- ]
- },
- "godot_quat_slerp": {
- "return_type": "godot_quat",
- "arguments": [
- ["const godot_quat *", "p_self"],
- ["const godot_quat *", "p_b"],
- ["const godot_real", "p_t"]
- ]
- },
- "godot_quat_slerpni": {
- "return_type": "godot_quat",
- "arguments": [
- ["const godot_quat *", "p_self"],
- ["const godot_quat *", "p_b"],
- ["const godot_real", "p_t"]
- ]
- },
- "godot_quat_cubic_slerp": {
- "return_type": "godot_quat",
- "arguments": [
- ["const godot_quat *", "p_self"],
- ["const godot_quat *", "p_b"],
- ["const godot_quat *", "p_pre_a"],
- ["const godot_quat *", "p_post_b"],
- ["const godot_real", "p_t"]
- ]
- },
- "godot_quat_operator_multiply": {
- "return_type": "godot_quat",
- "arguments": [
- ["const godot_quat *", "p_self"],
- ["const godot_real", "p_b"]
- ]
- },
- "godot_quat_operator_add": {
- "return_type": "godot_quat",
- "arguments": [
- ["const godot_quat *", "p_self"],
- ["const godot_quat *", "p_b"]
- ]
- },
- "godot_quat_operator_substract": {
- "return_type": "godot_quat",
- "arguments": [
- ["const godot_quat *", "p_self"],
- ["const godot_quat *", "p_b"]
- ]
- },
- "godot_quat_operator_divide": {
- "return_type": "godot_quat",
- "arguments": [
- ["const godot_quat *", "p_self"],
- ["const godot_real", "p_b"]
- ]
- },
- "godot_quat_operator_equal": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_quat *", "p_self"],
- ["const godot_quat *", "p_b"]
- ]
- },
- "godot_quat_operator_neg": {
- "return_type": "godot_quat",
- "arguments": [
- ["const godot_quat *", "p_self"]
- ]
- },
- "godot_basis_new_with_rows": {
- "return_type": "void",
- "arguments": [
- ["godot_basis *", "r_dest"],
- ["const godot_vector3 *", "p_x_axis"],
- ["const godot_vector3 *", "p_y_axis"],
- ["const godot_vector3 *", "p_z_axis"]
- ]
- },
- "godot_basis_new_with_axis_and_angle": {
- "return_type": "void",
- "arguments": [
- ["godot_basis *", "r_dest"],
- ["const godot_vector3 *", "p_axis"],
- ["const godot_real", "p_phi"]
- ]
- },
- "godot_basis_new_with_euler": {
- "return_type": "void",
- "arguments": [
- ["godot_basis *", "r_dest"],
- ["const godot_vector3 *", "p_euler"]
- ]
- },
- "godot_basis_as_string": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_basis *", "p_self"]
- ]
- },
- "godot_basis_inverse": {
- "return_type": "godot_basis",
- "arguments": [
- ["const godot_basis *", "p_self"]
- ]
- },
- "godot_basis_transposed": {
- "return_type": "godot_basis",
- "arguments": [
- ["const godot_basis *", "p_self"]
- ]
- },
- "godot_basis_orthonormalized": {
- "return_type": "godot_basis",
- "arguments": [
- ["const godot_basis *", "p_self"]
- ]
- },
- "godot_basis_determinant": {
- "return_type": "godot_real",
- "arguments": [
- ["const godot_basis *", "p_self"]
- ]
- },
- "godot_basis_rotated": {
- "return_type": "godot_basis",
- "arguments": [
- ["const godot_basis *", "p_self"],
- ["const godot_vector3 *", "p_axis"],
- ["const godot_real", "p_phi"]
- ]
- },
- "godot_basis_scaled": {
- "return_type": "godot_basis",
- "arguments": [
- ["const godot_basis *", "p_self"],
- ["const godot_vector3 *", "p_scale"]
- ]
- },
- "godot_basis_get_scale": {
- "return_type": "godot_vector3",
- "arguments": [
- ["const godot_basis *", "p_self"]
- ]
- },
- "godot_basis_get_euler": {
- "return_type": "godot_vector3",
- "arguments": [
- ["const godot_basis *", "p_self"]
- ]
- },
- "godot_basis_tdotx": {
- "return_type": "godot_real",
- "arguments": [
- ["const godot_basis *", "p_self"],
- ["const godot_vector3 *", "p_with"]
- ]
- },
- "godot_basis_tdoty": {
- "return_type": "godot_real",
- "arguments": [
- ["const godot_basis *", "p_self"],
- ["const godot_vector3 *", "p_with"]
- ]
- },
- "godot_basis_tdotz": {
- "return_type": "godot_real",
- "arguments": [
- ["const godot_basis *", "p_self"],
- ["const godot_vector3 *", "p_with"]
- ]
- },
- "godot_basis_xform": {
- "return_type": "godot_vector3",
- "arguments": [
- ["const godot_basis *", "p_self"],
- ["const godot_vector3 *", "p_v"]
- ]
- },
- "godot_basis_xform_inv": {
- "return_type": "godot_vector3",
- "arguments": [
- ["const godot_basis *", "p_self"],
- ["const godot_vector3 *", "p_v"]
- ]
- },
- "godot_basis_get_orthogonal_index": {
- "return_type": "godot_int",
- "arguments": [
- ["const godot_basis *", "p_self"]
- ]
- },
- "godot_basis_new": {
- "return_type": "void",
- "arguments": [
- ["godot_basis *", "r_dest"]
- ]
- },
- "godot_basis_new_with_euler_quat": {
- "return_type": "void",
- "arguments": [
- ["godot_basis *", "r_dest"],
- ["const godot_quat *", "p_euler"]
- ]
- },
- "godot_basis_get_elements": {
- "return_type": "void",
- "arguments": [
- ["godot_basis *", "p_self"],
- ["godot_vector3 *", "p_elements"]
- ]
- },
- "godot_basis_get_axis": {
- "return_type": "godot_vector3",
- "arguments": [
- ["const godot_basis *", "p_self"],
- ["const godot_int", "p_axis"]
- ]
- },
- "godot_basis_set_axis": {
- "return_type": "void",
- "arguments": [
- ["godot_basis *", "p_self"],
- ["const godot_int", "p_axis"],
- ["const godot_vector3 *", "p_value"]
- ]
- },
- "godot_basis_get_row": {
- "return_type": "godot_vector3",
- "arguments": [
- ["const godot_basis *", "p_self"],
- ["const godot_int", "p_row"]
- ]
- },
- "godot_basis_set_row": {
- "return_type": "void",
- "arguments": [
- ["godot_basis *", "p_self"],
- ["const godot_int", "p_row"],
- ["const godot_vector3 *", "p_value"]
- ]
- },
- "godot_basis_operator_equal": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_basis *", "p_self"],
- ["const godot_basis *", "p_b"]
- ]
- },
- "godot_basis_operator_add": {
- "return_type": "godot_basis",
- "arguments": [
- ["const godot_basis *", "p_self"],
- ["const godot_basis *", "p_b"]
- ]
- },
- "godot_basis_operator_substract": {
- "return_type": "godot_basis",
- "arguments": [
- ["const godot_basis *", "p_self"],
- ["const godot_basis *", "p_b"]
- ]
- },
- "godot_basis_operator_multiply_vector": {
- "return_type": "godot_basis",
- "arguments": [
- ["const godot_basis *", "p_self"],
- ["const godot_basis *", "p_b"]
- ]
- },
- "godot_basis_operator_multiply_scalar": {
- "return_type": "godot_basis",
- "arguments": [
- ["const godot_basis *", "p_self"],
- ["const godot_real", "p_b"]
- ]
- },
- "godot_vector3_new": {
- "return_type": "void",
- "arguments": [
- ["godot_vector3 *", "r_dest"],
- ["const godot_real", "p_x"],
- ["const godot_real", "p_y"],
- ["const godot_real", "p_z"]
- ]
- },
- "godot_vector3_as_string": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_vector3 *", "p_self"]
- ]
- },
- "godot_vector3_min_axis": {
- "return_type": "godot_int",
- "arguments": [
- ["const godot_vector3 *", "p_self"]
- ]
- },
- "godot_vector3_max_axis": {
- "return_type": "godot_int",
- "arguments": [
- ["const godot_vector3 *", "p_self"]
- ]
- },
- "godot_vector3_length": {
- "return_type": "godot_real",
- "arguments": [
- ["const godot_vector3 *", "p_self"]
- ]
- },
- "godot_vector3_length_squared": {
- "return_type": "godot_real",
- "arguments": [
- ["const godot_vector3 *", "p_self"]
- ]
- },
- "godot_vector3_is_normalized": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_vector3 *", "p_self"]
- ]
- },
- "godot_vector3_normalized": {
- "return_type": "godot_vector3",
- "arguments": [
- ["const godot_vector3 *", "p_self"]
- ]
- },
- "godot_vector3_inverse": {
- "return_type": "godot_vector3",
- "arguments": [
- ["const godot_vector3 *", "p_self"]
- ]
- },
- "godot_vector3_snapped": {
- "return_type": "godot_vector3",
- "arguments": [
- ["const godot_vector3 *", "p_self"],
- ["const godot_vector3 *", "p_by"]
- ]
- },
- "godot_vector3_rotated": {
- "return_type": "godot_vector3",
- "arguments": [
- ["const godot_vector3 *", "p_self"],
- ["const godot_vector3 *", "p_axis"],
- ["const godot_real", "p_phi"]
- ]
- },
- "godot_vector3_linear_interpolate": {
- "return_type": "godot_vector3",
- "arguments": [
- ["const godot_vector3 *", "p_self"],
- ["const godot_vector3 *", "p_b"],
- ["const godot_real", "p_t"]
- ]
- },
- "godot_vector3_cubic_interpolate": {
- "return_type": "godot_vector3",
- "arguments": [
- ["const godot_vector3 *", "p_self"],
- ["const godot_vector3 *", "p_b"],
- ["const godot_vector3 *", "p_pre_a"],
- ["const godot_vector3 *", "p_post_b"],
- ["const godot_real", "p_t"]
- ]
- },
- "godot_vector3_dot": {
- "return_type": "godot_real",
- "arguments": [
- ["const godot_vector3 *", "p_self"],
- ["const godot_vector3 *", "p_b"]
- ]
- },
- "godot_vector3_cross": {
- "return_type": "godot_vector3",
- "arguments": [
- ["const godot_vector3 *", "p_self"],
- ["const godot_vector3 *", "p_b"]
- ]
- },
- "godot_vector3_outer": {
- "return_type": "godot_basis",
- "arguments": [
- ["const godot_vector3 *", "p_self"],
- ["const godot_vector3 *", "p_b"]
- ]
- },
- "godot_vector3_to_diagonal_matrix": {
- "return_type": "godot_basis",
- "arguments": [
- ["const godot_vector3 *", "p_self"]
- ]
- },
- "godot_vector3_abs": {
- "return_type": "godot_vector3",
- "arguments": [
- ["const godot_vector3 *", "p_self"]
- ]
- },
- "godot_vector3_floor": {
- "return_type": "godot_vector3",
- "arguments": [
- ["const godot_vector3 *", "p_self"]
- ]
- },
- "godot_vector3_ceil": {
- "return_type": "godot_vector3",
- "arguments": [
- ["const godot_vector3 *", "p_self"]
- ]
- },
- "godot_vector3_distance_to": {
- "return_type": "godot_real",
- "arguments": [
- ["const godot_vector3 *", "p_self"],
- ["const godot_vector3 *", "p_b"]
- ]
- },
- "godot_vector3_distance_squared_to": {
- "return_type": "godot_real",
- "arguments": [
- ["const godot_vector3 *", "p_self"],
- ["const godot_vector3 *", "p_b"]
- ]
- },
- "godot_vector3_angle_to": {
- "return_type": "godot_real",
- "arguments": [
- ["const godot_vector3 *", "p_self"],
- ["const godot_vector3 *", "p_to"]
- ]
- },
- "godot_vector3_slide": {
- "return_type": "godot_vector3",
- "arguments": [
- ["const godot_vector3 *", "p_self"],
- ["const godot_vector3 *", "p_n"]
- ]
- },
- "godot_vector3_bounce": {
- "return_type": "godot_vector3",
- "arguments": [
- ["const godot_vector3 *", "p_self"],
- ["const godot_vector3 *", "p_n"]
- ]
- },
- "godot_vector3_reflect": {
- "return_type": "godot_vector3",
- "arguments": [
- ["const godot_vector3 *", "p_self"],
- ["const godot_vector3 *", "p_n"]
- ]
- },
- "godot_vector3_operator_add": {
- "return_type": "godot_vector3",
- "arguments": [
- ["const godot_vector3 *", "p_self"],
- ["const godot_vector3 *", "p_b"]
- ]
- },
- "godot_vector3_operator_substract": {
- "return_type": "godot_vector3",
- "arguments": [
- ["const godot_vector3 *", "p_self"],
- ["const godot_vector3 *", "p_b"]
- ]
- },
- "godot_vector3_operator_multiply_vector": {
- "return_type": "godot_vector3",
- "arguments": [
- ["const godot_vector3 *", "p_self"],
- ["const godot_vector3 *", "p_b"]
- ]
- },
- "godot_vector3_operator_multiply_scalar": {
- "return_type": "godot_vector3",
- "arguments": [
- ["const godot_vector3 *", "p_self"],
- ["const godot_real", "p_b"]
- ]
- },
- "godot_vector3_operator_divide_vector": {
- "return_type": "godot_vector3",
- "arguments": [
- ["const godot_vector3 *", "p_self"],
- ["const godot_vector3 *", "p_b"]
- ]
- },
- "godot_vector3_operator_divide_scalar": {
- "return_type": "godot_vector3",
- "arguments": [
- ["const godot_vector3 *", "p_self"],
- ["const godot_real", "p_b"]
- ]
- },
- "godot_vector3_operator_equal": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_vector3 *", "p_self"],
- ["const godot_vector3 *", "p_b"]
- ]
- },
- "godot_vector3_operator_less": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_vector3 *", "p_self"],
- ["const godot_vector3 *", "p_b"]
- ]
- },
- "godot_vector3_operator_neg": {
- "return_type": "godot_vector3",
- "arguments": [
- ["const godot_vector3 *", "p_self"]
- ]
- },
- "godot_vector3_set_axis": {
- "return_type": "void",
- "arguments": [
- ["godot_vector3 *", "p_self"],
- ["const godot_vector3_axis", "p_axis"],
- ["const godot_real", "p_val"]
- ]
- },
- "godot_vector3_get_axis": {
- "return_type": "godot_real",
- "arguments": [
- ["const godot_vector3 *", "p_self"],
- ["const godot_vector3_axis", "p_axis"]
- ]
- },
- "godot_pool_byte_array_new": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_byte_array *", "r_dest"]
- ]
- },
- "godot_pool_byte_array_new_copy": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_byte_array *", "r_dest"],
- ["const godot_pool_byte_array *", "p_src"]
- ]
- },
- "godot_pool_byte_array_new_with_array": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_byte_array *", "r_dest"],
- ["const godot_array *", "p_a"]
- ]
- },
- "godot_pool_byte_array_append": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_byte_array *", "p_self"],
- ["const uint8_t", "p_data"]
- ]
- },
- "godot_pool_byte_array_append_array": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_byte_array *", "p_self"],
- ["const godot_pool_byte_array *", "p_array"]
- ]
- },
- "godot_pool_byte_array_insert": {
- "return_type": "godot_error",
- "arguments": [
- ["godot_pool_byte_array *", "p_self"],
- ["const godot_int", "p_idx"],
- ["const uint8_t", "p_data"]
- ]
- },
- "godot_pool_byte_array_invert": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_byte_array *", "p_self"]
- ]
- },
- "godot_pool_byte_array_push_back": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_byte_array *", "p_self"],
- ["const uint8_t", "p_data"]
- ]
- },
- "godot_pool_byte_array_remove": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_byte_array *", "p_self"],
- ["const godot_int", "p_idx"]
- ]
- },
- "godot_pool_byte_array_resize": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_byte_array *", "p_self"],
- ["const godot_int", "p_size"]
- ]
- },
- "godot_pool_byte_array_set": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_byte_array *", "p_self"],
- ["const godot_int", "p_idx"],
- ["const uint8_t", "p_data"]
- ]
- },
- "godot_pool_byte_array_get": {
- "return_type": "uint8_t",
- "arguments": [
- ["const godot_pool_byte_array *", "p_self"],
- ["const godot_int", "p_idx"]
- ]
- },
- "godot_pool_byte_array_size": {
- "return_type": "godot_int",
- "arguments": [
- ["const godot_pool_byte_array *", "p_self"]
- ]
- },
- "godot_pool_byte_array_destroy": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_byte_array *", "p_self"]
- ]
- },
- "godot_pool_int_array_new": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_int_array *", "r_dest"]
- ]
- },
- "godot_pool_int_array_new_copy": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_int_array *", "r_dest"],
- ["const godot_pool_int_array *", "p_src"]
- ]
- },
- "godot_pool_int_array_new_with_array": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_int_array *", "r_dest"],
- ["const godot_array *", "p_a"]
- ]
- },
- "godot_pool_int_array_append": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_int_array *", "p_self"],
- ["const godot_int", "p_data"]
- ]
- },
- "godot_pool_int_array_append_array": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_int_array *", "p_self"],
- ["const godot_pool_int_array *", "p_array"]
- ]
- },
- "godot_pool_int_array_insert": {
- "return_type": "godot_error",
- "arguments": [
- ["godot_pool_int_array *", "p_self"],
- ["const godot_int", "p_idx"],
- ["const godot_int", "p_data"]
- ]
- },
- "godot_pool_int_array_invert": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_int_array *", "p_self"]
- ]
- },
- "godot_pool_int_array_push_back": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_int_array *", "p_self"],
- ["const godot_int", "p_data"]
- ]
- },
- "godot_pool_int_array_remove": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_int_array *", "p_self"],
- ["const godot_int", "p_idx"]
- ]
- },
- "godot_pool_int_array_resize": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_int_array *", "p_self"],
- ["const godot_int", "p_size"]
- ]
- },
- "godot_pool_int_array_set": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_int_array *", "p_self"],
- ["const godot_int", "p_idx"],
- ["const godot_int", "p_data"]
- ]
- },
- "godot_pool_int_array_get": {
- "return_type": "godot_int",
- "arguments": [
- ["const godot_pool_int_array *", "p_self"],
- ["const godot_int", "p_idx"]
- ]
- },
- "godot_pool_int_array_size": {
- "return_type": "godot_int",
- "arguments": [
- ["const godot_pool_int_array *", "p_self"]
- ]
- },
- "godot_pool_int_array_destroy": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_int_array *", "p_self"]
- ]
- },
- "godot_pool_real_array_new": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_real_array *", "r_dest"]
- ]
- },
- "godot_pool_real_array_new_copy": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_real_array *", "r_dest"],
- ["const godot_pool_real_array *", "p_src"]
- ]
- },
- "godot_pool_real_array_new_with_array": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_real_array *", "r_dest"],
- ["const godot_array *", "p_a"]
- ]
- },
- "godot_pool_real_array_append": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_real_array *", "p_self"],
- ["const godot_real", "p_data"]
- ]
- },
- "godot_pool_real_array_append_array": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_real_array *", "p_self"],
- ["const godot_pool_real_array *", "p_array"]
- ]
- },
- "godot_pool_real_array_insert": {
- "return_type": "godot_error",
- "arguments": [
- ["godot_pool_real_array *", "p_self"],
- ["const godot_int", "p_idx"],
- ["const godot_real", "p_data"]
- ]
- },
- "godot_pool_real_array_invert": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_real_array *", "p_self"]
- ]
- },
- "godot_pool_real_array_push_back": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_real_array *", "p_self"],
- ["const godot_real", "p_data"]
- ]
- },
- "godot_pool_real_array_remove": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_real_array *", "p_self"],
- ["const godot_int", "p_idx"]
- ]
- },
- "godot_pool_real_array_resize": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_real_array *", "p_self"],
- ["const godot_int", "p_size"]
- ]
- },
- "godot_pool_real_array_set": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_real_array *", "p_self"],
- ["const godot_int", "p_idx"],
- ["const godot_real", "p_data"]
- ]
- },
- "godot_pool_real_array_get": {
- "return_type": "godot_real",
- "arguments": [
- ["const godot_pool_real_array *", "p_self"],
- ["const godot_int", "p_idx"]
- ]
- },
- "godot_pool_real_array_size": {
- "return_type": "godot_int",
- "arguments": [
- ["const godot_pool_real_array *", "p_self"]
- ]
- },
- "godot_pool_real_array_destroy": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_real_array *", "p_self"]
- ]
- },
- "godot_pool_string_array_new": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_string_array *", "r_dest"]
- ]
- },
- "godot_pool_string_array_new_copy": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_string_array *", "r_dest"],
- ["const godot_pool_string_array *", "p_src"]
- ]
- },
- "godot_pool_string_array_new_with_array": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_string_array *", "r_dest"],
- ["const godot_array *", "p_a"]
- ]
- },
- "godot_pool_string_array_append": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_string_array *", "p_self"],
- ["const godot_string *", "p_data"]
- ]
- },
- "godot_pool_string_array_append_array": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_string_array *", "p_self"],
- ["const godot_pool_string_array *", "p_array"]
- ]
- },
- "godot_pool_string_array_insert": {
- "return_type": "godot_error",
- "arguments": [
- ["godot_pool_string_array *", "p_self"],
- ["const godot_int", "p_idx"],
- ["const godot_string *", "p_data"]
- ]
- },
- "godot_pool_string_array_invert": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_string_array *", "p_self"]
- ]
- },
- "godot_pool_string_array_push_back": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_string_array *", "p_self"],
- ["const godot_string *", "p_data"]
- ]
- },
- "godot_pool_string_array_remove": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_string_array *", "p_self"],
- ["const godot_int", "p_idx"]
- ]
- },
- "godot_pool_string_array_resize": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_string_array *", "p_self"],
- ["const godot_int", "p_size"]
- ]
- },
- "godot_pool_string_array_set": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_string_array *", "p_self"],
- ["const godot_int", "p_idx"],
- ["const godot_string *", "p_data"]
- ]
- },
- "godot_pool_string_array_get": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_pool_string_array *", "p_self"],
- ["const godot_int", "p_idx"]
- ]
- },
- "godot_pool_string_array_size": {
- "return_type": "godot_int",
- "arguments": [
- ["const godot_pool_string_array *", "p_self"]
- ]
- },
- "godot_pool_string_array_destroy": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_string_array *", "p_self"]
- ]
- },
- "godot_pool_vector2_array_new": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_vector2_array *", "r_dest"]
- ]
- },
- "godot_pool_vector2_array_new_copy": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_vector2_array *", "r_dest"],
- ["const godot_pool_vector2_array *", "p_src"]
- ]
- },
- "godot_pool_vector2_array_new_with_array": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_vector2_array *", "r_dest"],
- ["const godot_array *", "p_a"]
- ]
- },
- "godot_pool_vector2_array_append": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_vector2_array *", "p_self"],
- ["const godot_vector2 *", "p_data"]
- ]
- },
- "godot_pool_vector2_array_append_array": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_vector2_array *", "p_self"],
- ["const godot_pool_vector2_array *", "p_array"]
- ]
- },
- "godot_pool_vector2_array_insert": {
- "return_type": "godot_error",
- "arguments": [
- ["godot_pool_vector2_array *", "p_self"],
- ["const godot_int", "p_idx"],
- ["const godot_vector2 *", "p_data"]
- ]
- },
- "godot_pool_vector2_array_invert": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_vector2_array *", "p_self"]
- ]
- },
- "godot_pool_vector2_array_push_back": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_vector2_array *", "p_self"],
- ["const godot_vector2 *", "p_data"]
- ]
- },
- "godot_pool_vector2_array_remove": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_vector2_array *", "p_self"],
- ["const godot_int", "p_idx"]
- ]
- },
- "godot_pool_vector2_array_resize": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_vector2_array *", "p_self"],
- ["const godot_int", "p_size"]
- ]
- },
- "godot_pool_vector2_array_set": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_vector2_array *", "p_self"],
- ["const godot_int", "p_idx"],
- ["const godot_vector2 *", "p_data"]
- ]
- },
- "godot_pool_vector2_array_get": {
- "return_type": "godot_vector2",
- "arguments": [
- ["const godot_pool_vector2_array *", "p_self"],
- ["const godot_int", "p_idx"]
- ]
- },
- "godot_pool_vector2_array_size": {
- "return_type": "godot_int",
- "arguments": [
- ["const godot_pool_vector2_array *", "p_self"]
- ]
- },
- "godot_pool_vector2_array_destroy": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_vector2_array *", "p_self"]
- ]
- },
- "godot_pool_vector3_array_new": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_vector3_array *", "r_dest"]
- ]
- },
- "godot_pool_vector3_array_new_copy": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_vector3_array *", "r_dest"],
- ["const godot_pool_vector3_array *", "p_src"]
- ]
- },
- "godot_pool_vector3_array_new_with_array": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_vector3_array *", "r_dest"],
- ["const godot_array *", "p_a"]
- ]
- },
- "godot_pool_vector3_array_append": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_vector3_array *", "p_self"],
- ["const godot_vector3 *", "p_data"]
- ]
- },
- "godot_pool_vector3_array_append_array": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_vector3_array *", "p_self"],
- ["const godot_pool_vector3_array *", "p_array"]
- ]
- },
- "godot_pool_vector3_array_insert": {
- "return_type": "godot_error",
- "arguments": [
- ["godot_pool_vector3_array *", "p_self"],
- ["const godot_int", "p_idx"],
- ["const godot_vector3 *", "p_data"]
- ]
- },
- "godot_pool_vector3_array_invert": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_vector3_array *", "p_self"]
- ]
- },
- "godot_pool_vector3_array_push_back": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_vector3_array *", "p_self"],
- ["const godot_vector3 *", "p_data"]
- ]
- },
- "godot_pool_vector3_array_remove": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_vector3_array *", "p_self"],
- ["const godot_int", "p_idx"]
- ]
- },
- "godot_pool_vector3_array_resize": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_vector3_array *", "p_self"],
- ["const godot_int", "p_size"]
- ]
- },
- "godot_pool_vector3_array_set": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_vector3_array *", "p_self"],
- ["const godot_int", "p_idx"],
- ["const godot_vector3 *", "p_data"]
- ]
- },
- "godot_pool_vector3_array_get": {
- "return_type": "godot_vector3",
- "arguments": [
- ["const godot_pool_vector3_array *", "p_self"],
- ["const godot_int", "p_idx"]
- ]
- },
- "godot_pool_vector3_array_size": {
- "return_type": "godot_int",
- "arguments": [
- ["const godot_pool_vector3_array *", "p_self"]
- ]
- },
- "godot_pool_vector3_array_destroy": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_vector3_array *", "p_self"]
- ]
- },
- "godot_pool_color_array_new": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_color_array *", "r_dest"]
- ]
- },
- "godot_pool_color_array_new_copy": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_color_array *", "r_dest"],
- ["const godot_pool_color_array *", "p_src"]
- ]
- },
- "godot_pool_color_array_new_with_array": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_color_array *", "r_dest"],
- ["const godot_array *", "p_a"]
- ]
- },
- "godot_pool_color_array_append": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_color_array *", "p_self"],
- ["const godot_color *", "p_data"]
- ]
- },
- "godot_pool_color_array_append_array": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_color_array *", "p_self"],
- ["const godot_pool_color_array *", "p_array"]
- ]
- },
- "godot_pool_color_array_insert": {
- "return_type": "godot_error",
- "arguments": [
- ["godot_pool_color_array *", "p_self"],
- ["const godot_int", "p_idx"],
- ["const godot_color *", "p_data"]
- ]
- },
- "godot_pool_color_array_invert": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_color_array *", "p_self"]
- ]
- },
- "godot_pool_color_array_push_back": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_color_array *", "p_self"],
- ["const godot_color *", "p_data"]
- ]
- },
- "godot_pool_color_array_remove": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_color_array *", "p_self"],
- ["const godot_int", "p_idx"]
- ]
- },
- "godot_pool_color_array_resize": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_color_array *", "p_self"],
- ["const godot_int", "p_size"]
- ]
- },
- "godot_pool_color_array_set": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_color_array *", "p_self"],
- ["const godot_int", "p_idx"],
- ["const godot_color *", "p_data"]
- ]
- },
- "godot_pool_color_array_get": {
- "return_type": "godot_color",
- "arguments": [
- ["const godot_pool_color_array *", "p_self"],
- ["const godot_int", "p_idx"]
- ]
- },
- "godot_pool_color_array_size": {
- "return_type": "godot_int",
- "arguments": [
- ["const godot_pool_color_array *", "p_self"]
- ]
- },
- "godot_pool_color_array_destroy": {
- "return_type": "void",
- "arguments": [
- ["godot_pool_color_array *", "p_self"]
- ]
- },
- "godot_array_new": {
- "return_type": "void",
- "arguments": [
- ["godot_array *", "r_dest"]
- ]
- },
- "godot_array_new_copy": {
- "return_type": "void",
- "arguments": [
- ["godot_array *", "r_dest"],
- ["const godot_array *", "p_src"]
- ]
- },
- "godot_array_new_pool_color_array": {
- "return_type": "void",
- "arguments": [
- ["godot_array *", "r_dest"],
- ["const godot_pool_color_array *", "p_pca"]
- ]
- },
- "godot_array_new_pool_vector3_array": {
- "return_type": "void",
- "arguments": [
- ["godot_array *", "r_dest"],
- ["const godot_pool_vector3_array *", "p_pv3a"]
- ]
- },
- "godot_array_new_pool_vector2_array": {
- "return_type": "void",
- "arguments": [
- ["godot_array *", "r_dest"],
- ["const godot_pool_vector2_array *", "p_pv2a"]
- ]
- },
- "godot_array_new_pool_string_array": {
- "return_type": "void",
- "arguments": [
- ["godot_array *", "r_dest"],
- ["const godot_pool_string_array *", "p_psa"]
- ]
- },
- "godot_array_new_pool_real_array": {
- "return_type": "void",
- "arguments": [
- ["godot_array *", "r_dest"],
- ["const godot_pool_real_array *", "p_pra"]
- ]
- },
- "godot_array_new_pool_int_array": {
- "return_type": "void",
- "arguments": [
- ["godot_array *", "r_dest"],
- ["const godot_pool_int_array *", "p_pia"]
- ]
- },
- "godot_array_new_pool_byte_array": {
- "return_type": "void",
- "arguments": [
- ["godot_array *", "r_dest"],
- ["const godot_pool_byte_array *", "p_pba"]
- ]
- },
- "godot_array_set": {
- "return_type": "void",
- "arguments": [
- ["godot_array *", "p_self"],
- ["const godot_int", "p_idx"],
- ["const godot_variant *", "p_value"]
- ]
- },
- "godot_array_get": {
- "return_type": "godot_variant",
- "arguments": [
- ["const godot_array *", "p_self"],
- ["const godot_int", "p_idx"]
- ]
- },
- "godot_array_operator_index": {
- "return_type": "godot_variant *",
- "arguments": [
- ["godot_array *", "p_self"],
- ["const godot_int", "p_idx"]
- ]
- },
- "godot_array_append": {
- "return_type": "void",
- "arguments": [
- ["godot_array *", "p_self"],
- ["const godot_variant *", "p_value"]
- ]
- },
- "godot_array_clear": {
- "return_type": "void",
- "arguments": [
- ["godot_array *", "p_self"]
- ]
- },
- "godot_array_count": {
- "return_type": "godot_int",
- "arguments": [
- ["const godot_array *", "p_self"],
- ["const godot_variant *", "p_value"]
- ]
- },
- "godot_array_empty": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_array *", "p_self"]
- ]
- },
- "godot_array_erase": {
- "return_type": "void",
- "arguments": [
- ["godot_array *", "p_self"],
- ["const godot_variant *", "p_value"]
- ]
- },
- "godot_array_front": {
- "return_type": "godot_variant",
- "arguments": [
- ["const godot_array *", "p_self"]
- ]
- },
- "godot_array_back": {
- "return_type": "godot_variant",
- "arguments": [
- ["const godot_array *", "p_self"]
- ]
- },
- "godot_array_find": {
- "return_type": "godot_int",
- "arguments": [
- ["const godot_array *", "p_self"],
- ["const godot_variant *", "p_what"],
- ["const godot_int", "p_from"]
- ]
- },
- "godot_array_find_last": {
- "return_type": "godot_int",
- "arguments": [
- ["const godot_array *", "p_self"],
- ["const godot_variant *", "p_what"]
- ]
- },
- "godot_array_has": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_array *", "p_self"],
- ["const godot_variant *", "p_value"]
- ]
- },
- "godot_array_hash": {
- "return_type": "godot_int",
- "arguments": [
- ["const godot_array *", "p_self"]
- ]
- },
- "godot_array_insert": {
- "return_type": "void",
- "arguments": [
- ["godot_array *", "p_self"],
- ["const godot_int", "p_pos"],
- ["const godot_variant *", "p_value"]
- ]
- },
- "godot_array_invert": {
- "return_type": "void",
- "arguments": [
- ["godot_array *", "p_self"]
- ]
- },
- "godot_array_pop_back": {
- "return_type": "godot_variant",
- "arguments": [
- ["godot_array *", "p_self"]
- ]
- },
- "godot_array_pop_front": {
- "return_type": "godot_variant",
- "arguments": [
- ["godot_array *", "p_self"]
- ]
- },
- "godot_array_push_back": {
- "return_type": "void",
- "arguments": [
- ["godot_array *", "p_self"],
- ["const godot_variant *", "p_value"]
- ]
- },
- "godot_array_push_front": {
- "return_type": "void",
- "arguments": [
- ["godot_array *", "p_self"],
- ["const godot_variant *", "p_value"]
- ]
- },
- "godot_array_remove": {
- "return_type": "void",
- "arguments": [
- ["godot_array *", "p_self"],
- ["const godot_int", "p_idx"]
- ]
- },
- "godot_array_resize": {
- "return_type": "void",
- "arguments": [
- ["godot_array *", "p_self"],
- ["const godot_int", "p_size"]
- ]
- },
- "godot_array_rfind": {
- "return_type": "godot_int",
- "arguments": [
- ["const godot_array *", "p_self"],
- ["const godot_variant *", "p_what"],
- ["const godot_int", "p_from"]
- ]
- },
- "godot_array_size": {
- "return_type": "godot_int",
- "arguments": [
- ["const godot_array *", "p_self"]
- ]
- },
- "godot_array_sort": {
- "return_type": "void",
- "arguments": [
- ["godot_array *", "p_self"]
- ]
- },
- "godot_array_sort_custom": {
- "return_type": "void",
- "arguments": [
- ["godot_array *", "p_self"],
- ["godot_object *", "p_obj"],
- ["const godot_string *", "p_func"]
- ]
- },
- "godot_array_destroy": {
- "return_type": "void",
- "arguments": [
- ["godot_array *", "p_self"]
- ]
- },
- "godot_dictionary_new": {
- "return_type": "void",
- "arguments": [
- ["godot_dictionary *", "r_dest"]
- ]
- },
- "godot_dictionary_new_copy": {
- "return_type": "void",
- "arguments": [
- ["godot_dictionary *", "r_dest"],
- ["const godot_dictionary *", "p_src"]
- ]
- },
- "godot_dictionary_destroy": {
- "return_type": "void",
- "arguments": [
- ["godot_dictionary *", "p_self"]
- ]
- },
- "godot_dictionary_size": {
- "return_type": "godot_int",
- "arguments": [
- ["const godot_dictionary *", "p_self"]
- ]
- },
- "godot_dictionary_empty": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_dictionary *", "p_self"]
- ]
- },
- "godot_dictionary_clear": {
- "return_type": "void",
- "arguments": [
- ["godot_dictionary *", "p_self"]
- ]
- },
- "godot_dictionary_has": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_dictionary *", "p_self"],
- ["const godot_variant *", "p_key"]
- ]
- },
- "godot_dictionary_has_all": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_dictionary *", "p_self"],
- ["const godot_array *", "p_keys"]
- ]
- },
- "godot_dictionary_erase": {
- "return_type": "void",
- "arguments": [
- ["godot_dictionary *", "p_self"],
- ["const godot_variant *", "p_key"]
- ]
- },
- "godot_dictionary_hash": {
- "return_type": "godot_int",
- "arguments": [
- ["const godot_dictionary *", "p_self"]
- ]
- },
- "godot_dictionary_keys": {
- "return_type": "godot_array",
- "arguments": [
- ["const godot_dictionary *", "p_self"]
- ]
- },
- "godot_dictionary_values": {
- "return_type": "godot_array",
- "arguments": [
- ["const godot_dictionary *", "p_self"]
- ]
- },
- "godot_dictionary_get": {
- "return_type": "godot_variant",
- "arguments": [
- ["const godot_dictionary *", "p_self"],
- ["const godot_variant *", "p_key"]
- ]
- },
- "godot_dictionary_set": {
- "return_type": "void",
- "arguments": [
- ["godot_dictionary *", "p_self"],
- ["const godot_variant *", "p_key"],
- ["const godot_variant *", "p_value"]
- ]
- },
- "godot_dictionary_operator_index": {
- "return_type": "godot_variant *",
- "arguments": [
- ["godot_dictionary *", "p_self"],
- ["const godot_variant *", "p_key"]
- ]
- },
- "godot_dictionary_next": {
- "return_type": "godot_variant *",
- "arguments": [
- ["const godot_dictionary *", "p_self"],
- ["const godot_variant *", "p_key"]
- ]
- },
- "godot_dictionary_operator_equal": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_dictionary *", "p_self"],
- ["const godot_dictionary *", "p_b"]
- ]
- },
- "godot_dictionary_to_json": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_dictionary *", "p_self"]
- ]
- },
- "godot_node_path_new": {
- "return_type": "void",
- "arguments": [
- ["godot_node_path *", "r_dest"],
- ["const godot_string *", "p_from"]
- ]
- },
- "godot_node_path_new_copy": {
- "return_type": "void",
- "arguments": [
- ["godot_node_path *", "r_dest"],
- ["const godot_node_path *", "p_src"]
- ]
- },
- "godot_node_path_destroy": {
- "return_type": "void",
- "arguments": [
- ["godot_node_path *", "p_self"]
- ]
- },
- "godot_node_path_as_string": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_node_path *", "p_self"]
- ]
- },
- "godot_node_path_is_absolute": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_node_path *", "p_self"]
- ]
- },
- "godot_node_path_get_name_count": {
- "return_type": "godot_int",
- "arguments": [
- ["const godot_node_path *", "p_self"]
- ]
- },
- "godot_node_path_get_name": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_node_path *", "p_self"],
- ["const godot_int", "p_idx"]
- ]
- },
- "godot_node_path_get_subname_count": {
- "return_type": "godot_int",
- "arguments": [
- ["const godot_node_path *", "p_self"]
- ]
- },
- "godot_node_path_get_subname": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_node_path *", "p_self"],
- ["const godot_int", "p_idx"]
- ]
- },
- "godot_node_path_get_property": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_node_path *", "p_self"]
- ]
- },
- "godot_node_path_is_empty": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_node_path *", "p_self"]
- ]
- },
- "godot_node_path_operator_equal": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_node_path *", "p_self"],
- ["const godot_node_path *", "p_b"]
- ]
- },
- "godot_plane_new_with_reals": {
- "return_type": "void",
- "arguments": [
- ["godot_plane *", "r_dest"],
- ["const godot_real", "p_a"],
- ["const godot_real", "p_b"],
- ["const godot_real", "p_c"],
- ["const godot_real", "p_d"]
- ]
- },
- "godot_plane_new_with_vectors": {
- "return_type": "void",
- "arguments": [
- ["godot_plane *", "r_dest"],
- ["const godot_vector3 *", "p_v1"],
- ["const godot_vector3 *", "p_v2"],
- ["const godot_vector3 *", "p_v3"]
- ]
- },
- "godot_plane_new_with_normal": {
- "return_type": "void",
- "arguments": [
- ["godot_plane *", "r_dest"],
- ["const godot_vector3 *", "p_normal"],
- ["const godot_real", "p_d"]
- ]
- },
- "godot_plane_as_string": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_plane *", "p_self"]
- ]
- },
- "godot_plane_normalized": {
- "return_type": "godot_plane",
- "arguments": [
- ["const godot_plane *", "p_self"]
- ]
- },
- "godot_plane_center": {
- "return_type": "godot_vector3",
- "arguments": [
- ["const godot_plane *", "p_self"]
- ]
- },
- "godot_plane_get_any_point": {
- "return_type": "godot_vector3",
- "arguments": [
- ["const godot_plane *", "p_self"]
- ]
- },
- "godot_plane_is_point_over": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_plane *", "p_self"],
- ["const godot_vector3 *", "p_point"]
- ]
- },
- "godot_plane_distance_to": {
- "return_type": "godot_real",
- "arguments": [
- ["const godot_plane *", "p_self"],
- ["const godot_vector3 *", "p_point"]
- ]
- },
- "godot_plane_has_point": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_plane *", "p_self"],
- ["const godot_vector3 *", "p_point"],
- ["const godot_real", "p_epsilon"]
- ]
- },
- "godot_plane_project": {
- "return_type": "godot_vector3",
- "arguments": [
- ["const godot_plane *", "p_self"],
- ["const godot_vector3 *", "p_point"]
- ]
- },
- "godot_plane_intersect_3": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_plane *", "p_self"],
- ["godot_vector3 *", "r_dest"],
- ["const godot_plane *", "p_b"],
- ["const godot_plane *", "p_c"]
- ]
- },
- "godot_plane_intersects_ray": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_plane *", "p_self"],
- ["godot_vector3 *", "r_dest"],
- ["const godot_vector3 *", "p_from"],
- ["const godot_vector3 *", "p_dir"]
- ]
- },
- "godot_plane_intersects_segment": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_plane *", "p_self"],
- ["godot_vector3 *", "r_dest"],
- ["const godot_vector3 *", "p_begin"],
- ["const godot_vector3 *", "p_end"]
- ]
- },
- "godot_plane_operator_neg": {
- "return_type": "godot_plane",
- "arguments": [
- ["const godot_plane *", "p_self"]
- ]
- },
- "godot_plane_operator_equal": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_plane *", "p_self"],
- ["const godot_plane *", "p_b"]
- ]
- },
- "godot_plane_set_normal": {
- "return_type": "void",
- "arguments": [
- ["godot_plane *", "p_self"],
- ["const godot_vector3 *", "p_normal"]
- ]
- },
- "godot_plane_get_normal": {
- "return_type": "godot_vector3",
- "arguments": [
- ["const godot_plane *", "p_self"]
- ]
- },
- "godot_plane_get_d": {
- "return_type": "godot_real",
- "arguments": [
- ["const godot_plane *", "p_self"]
- ]
- },
- "godot_plane_set_d": {
- "return_type": "void",
- "arguments": [
- ["godot_plane *", "p_self"],
- ["const godot_real", "p_d"]
- ]
- },
- "godot_rect2_new_with_position_and_size": {
- "return_type": "void",
- "arguments": [
- ["godot_rect2 *", "r_dest"],
- ["const godot_vector2 *", "p_pos"],
- ["const godot_vector2 *", "p_size"]
- ]
- },
- "godot_rect2_new": {
- "return_type": "void",
- "arguments": [
- ["godot_rect2 *", "r_dest"],
- ["const godot_real", "p_x"],
- ["const godot_real", "p_y"],
- ["const godot_real", "p_width"],
- ["const godot_real", "p_height"]
- ]
- },
- "godot_rect2_as_string": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_rect2 *", "p_self"]
- ]
- },
- "godot_rect2_get_area": {
- "return_type": "godot_real",
- "arguments": [
- ["const godot_rect2 *", "p_self"]
- ]
- },
- "godot_rect2_intersects": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_rect2 *", "p_self"],
- ["const godot_rect2 *", "p_b"]
- ]
- },
- "godot_rect2_encloses": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_rect2 *", "p_self"],
- ["const godot_rect2 *", "p_b"]
- ]
- },
- "godot_rect2_has_no_area": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_rect2 *", "p_self"]
- ]
- },
- "godot_rect2_clip": {
- "return_type": "godot_rect2",
- "arguments": [
- ["const godot_rect2 *", "p_self"],
- ["const godot_rect2 *", "p_b"]
- ]
- },
- "godot_rect2_merge": {
- "return_type": "godot_rect2",
- "arguments": [
- ["const godot_rect2 *", "p_self"],
- ["const godot_rect2 *", "p_b"]
- ]
- },
- "godot_rect2_has_point": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_rect2 *", "p_self"],
- ["const godot_vector2 *", "p_point"]
- ]
- },
- "godot_rect2_grow": {
- "return_type": "godot_rect2",
- "arguments": [
- ["const godot_rect2 *", "p_self"],
- ["const godot_real", "p_by"]
- ]
- },
- "godot_rect2_expand": {
- "return_type": "godot_rect2",
- "arguments": [
- ["const godot_rect2 *", "p_self"],
- ["const godot_vector2 *", "p_to"]
- ]
- },
- "godot_rect2_operator_equal": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_rect2 *", "p_self"],
- ["const godot_rect2 *", "p_b"]
- ]
- },
- "godot_rect2_get_position": {
- "return_type": "godot_vector2",
- "arguments": [
- ["const godot_rect2 *", "p_self"]
- ]
- },
- "godot_rect2_get_size": {
- "return_type": "godot_vector2",
- "arguments": [
- ["const godot_rect2 *", "p_self"]
- ]
- },
- "godot_rect2_set_position": {
- "return_type": "void",
- "arguments": [
- ["godot_rect2 *", "p_self"],
- ["const godot_vector2 *", "p_pos"]
- ]
- },
- "godot_rect2_set_size": {
- "return_type": "void",
- "arguments": [
- ["godot_rect2 *", "p_self"],
- ["const godot_vector2 *", "p_size"]
- ]
- },
- "godot_rect3_new": {
- "return_type": "void",
- "arguments": [
- ["godot_rect3 *", "r_dest"],
- ["const godot_vector3 *", "p_pos"],
- ["const godot_vector3 *", "p_size"]
- ]
- },
- "godot_rect3_get_position": {
- "return_type": "godot_vector3",
- "arguments": [
- ["const godot_rect3 *", "p_self"]
- ]
- },
- "godot_rect3_set_position": {
- "return_type": "void",
- "arguments": [
- ["const godot_rect3 *", "p_self"],
- ["const godot_vector3 *", "p_v"]
- ]
- },
- "godot_rect3_get_size": {
- "return_type": "godot_vector3",
- "arguments": [
- ["const godot_rect3 *", "p_self"]
- ]
- },
- "godot_rect3_set_size": {
- "return_type": "void",
- "arguments": [
- ["const godot_rect3 *", "p_self"],
- ["const godot_vector3 *", "p_v"]
- ]
- },
- "godot_rect3_as_string": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_rect3 *", "p_self"]
- ]
- },
- "godot_rect3_get_area": {
- "return_type": "godot_real",
- "arguments": [
- ["const godot_rect3 *", "p_self"]
- ]
- },
- "godot_rect3_has_no_area": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_rect3 *", "p_self"]
- ]
- },
- "godot_rect3_has_no_surface": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_rect3 *", "p_self"]
- ]
- },
- "godot_rect3_intersects": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_rect3 *", "p_self"],
- ["const godot_rect3 *", "p_with"]
- ]
- },
- "godot_rect3_encloses": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_rect3 *", "p_self"],
- ["const godot_rect3 *", "p_with"]
- ]
- },
- "godot_rect3_merge": {
- "return_type": "godot_rect3",
- "arguments": [
- ["const godot_rect3 *", "p_self"],
- ["const godot_rect3 *", "p_with"]
- ]
- },
- "godot_rect3_intersection": {
- "return_type": "godot_rect3",
- "arguments": [
- ["const godot_rect3 *", "p_self"],
- ["const godot_rect3 *", "p_with"]
- ]
- },
- "godot_rect3_intersects_plane": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_rect3 *", "p_self"],
- ["const godot_plane *", "p_plane"]
- ]
- },
- "godot_rect3_intersects_segment": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_rect3 *", "p_self"],
- ["const godot_vector3 *", "p_from"],
- ["const godot_vector3 *", "p_to"]
- ]
- },
- "godot_rect3_has_point": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_rect3 *", "p_self"],
- ["const godot_vector3 *", "p_point"]
- ]
- },
- "godot_rect3_get_support": {
- "return_type": "godot_vector3",
- "arguments": [
- ["const godot_rect3 *", "p_self"],
- ["const godot_vector3 *", "p_dir"]
- ]
- },
- "godot_rect3_get_longest_axis": {
- "return_type": "godot_vector3",
- "arguments": [
- ["const godot_rect3 *", "p_self"]
- ]
- },
- "godot_rect3_get_longest_axis_index": {
- "return_type": "godot_int",
- "arguments": [
- ["const godot_rect3 *", "p_self"]
- ]
- },
- "godot_rect3_get_longest_axis_size": {
- "return_type": "godot_real",
- "arguments": [
- ["const godot_rect3 *", "p_self"]
- ]
- },
- "godot_rect3_get_shortest_axis": {
- "return_type": "godot_vector3",
- "arguments": [
- ["const godot_rect3 *", "p_self"]
- ]
- },
- "godot_rect3_get_shortest_axis_index": {
- "return_type": "godot_int",
- "arguments": [
- ["const godot_rect3 *", "p_self"]
- ]
- },
- "godot_rect3_get_shortest_axis_size": {
- "return_type": "godot_real",
- "arguments": [
- ["const godot_rect3 *", "p_self"]
- ]
- },
- "godot_rect3_expand": {
- "return_type": "godot_rect3",
- "arguments": [
- ["const godot_rect3 *", "p_self"],
- ["const godot_vector3 *", "p_to_point"]
- ]
- },
- "godot_rect3_grow": {
- "return_type": "godot_rect3",
- "arguments": [
- ["const godot_rect3 *", "p_self"],
- ["const godot_real", "p_by"]
- ]
- },
- "godot_rect3_get_endpoint": {
- "return_type": "godot_vector3",
- "arguments": [
- ["const godot_rect3 *", "p_self"],
- ["const godot_int", "p_idx"]
- ]
- },
- "godot_rect3_operator_equal": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_rect3 *", "p_self"],
- ["const godot_rect3 *", "p_b"]
- ]
- },
- "godot_rid_new": {
- "return_type": "void",
- "arguments": [
- ["godot_rid *", "r_dest"]
- ]
- },
- "godot_rid_get_id": {
- "return_type": "godot_int",
- "arguments": [
- ["const godot_rid *", "p_self"]
- ]
- },
- "godot_rid_new_with_resource": {
- "return_type": "void",
- "arguments": [
- ["godot_rid *", "r_dest"],
- ["const godot_object *", "p_from"]
- ]
- },
- "godot_rid_operator_equal": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_rid *", "p_self"],
- ["const godot_rid *", "p_b"]
- ]
- },
- "godot_rid_operator_less": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_rid *", "p_self"],
- ["const godot_rid *", "p_b"]
- ]
- },
- "godot_transform_new_with_axis_origin": {
- "return_type": "void",
- "arguments": [
- ["godot_transform *", "r_dest"],
- ["const godot_vector3 *", "p_x_axis"],
- ["const godot_vector3 *", "p_y_axis"],
- ["const godot_vector3 *", "p_z_axis"],
- ["const godot_vector3 *", "p_origin"]
- ]
- },
- "godot_transform_new": {
- "return_type": "void",
- "arguments": [
- ["godot_transform *", "r_dest"],
- ["const godot_basis *", "p_basis"],
- ["const godot_vector3 *", "p_origin"]
- ]
- },
- "godot_transform_get_basis": {
- "return_type": "godot_basis",
- "arguments": [
- ["const godot_transform *", "p_self"]
- ]
- },
- "godot_transform_set_basis": {
- "return_type": "void",
- "arguments": [
- ["godot_transform *", "p_self"],
- ["godot_basis *", "p_v"]
- ]
- },
- "godot_transform_get_origin": {
- "return_type": "godot_vector3",
- "arguments": [
- ["const godot_transform *", "p_self"]
- ]
- },
- "godot_transform_set_origin": {
- "return_type": "void",
- "arguments": [
- ["godot_transform *", "p_self"],
- ["godot_vector3 *", "p_v"]
- ]
- },
- "godot_transform_as_string": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_transform *", "p_self"]
- ]
- },
- "godot_transform_inverse": {
- "return_type": "godot_transform",
- "arguments": [
- ["const godot_transform *", "p_self"]
- ]
- },
- "godot_transform_affine_inverse": {
- "return_type": "godot_transform",
- "arguments": [
- ["const godot_transform *", "p_self"]
- ]
- },
- "godot_transform_orthonormalized": {
- "return_type": "godot_transform",
- "arguments": [
- ["const godot_transform *", "p_self"]
- ]
- },
- "godot_transform_rotated": {
- "return_type": "godot_transform",
- "arguments": [
- ["const godot_transform *", "p_self"],
- ["const godot_vector3 *", "p_axis"],
- ["const godot_real", "p_phi"]
- ]
- },
- "godot_transform_scaled": {
- "return_type": "godot_transform",
- "arguments": [
- ["const godot_transform *", "p_self"],
- ["const godot_vector3 *", "p_scale"]
- ]
- },
- "godot_transform_translated": {
- "return_type": "godot_transform",
- "arguments": [
- ["const godot_transform *", "p_self"],
- ["const godot_vector3 *", "p_ofs"]
- ]
- },
- "godot_transform_looking_at": {
- "return_type": "godot_transform",
- "arguments": [
- ["const godot_transform *", "p_self"],
- ["const godot_vector3 *", "p_target"],
- ["const godot_vector3 *", "p_up"]
- ]
- },
- "godot_transform_xform_plane": {
- "return_type": "godot_plane",
- "arguments": [
- ["const godot_transform *", "p_self"],
- ["const godot_plane *", "p_v"]
- ]
- },
- "godot_transform_xform_inv_plane": {
- "return_type": "godot_plane",
- "arguments": [
- ["const godot_transform *", "p_self"],
- ["const godot_plane *", "p_v"]
- ]
- },
- "godot_transform_new_identity": {
- "return_type": "void",
- "arguments": [
- ["godot_transform *", "r_dest"]
- ]
- },
- "godot_transform_operator_equal": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_transform *", "p_self"],
- ["const godot_transform *", "p_b"]
- ]
- },
- "godot_transform_operator_multiply": {
- "return_type": "godot_transform",
- "arguments": [
- ["const godot_transform *", "p_self"],
- ["const godot_transform *", "p_b"]
- ]
- },
- "godot_transform_xform_vector3": {
- "return_type": "godot_vector3",
- "arguments": [
- ["const godot_transform *", "p_self"],
- ["const godot_vector3 *", "p_v"]
- ]
- },
- "godot_transform_xform_inv_vector3": {
- "return_type": "godot_vector3",
- "arguments": [
- ["const godot_transform *", "p_self"],
- ["const godot_vector3 *", "p_v"]
- ]
- },
- "godot_transform_xform_rect3": {
- "return_type": "godot_rect3",
- "arguments": [
- ["const godot_transform *", "p_self"],
- ["const godot_rect3 *", "p_v"]
- ]
- },
- "godot_transform_xform_inv_rect3": {
- "return_type": "godot_rect3",
- "arguments": [
- ["const godot_transform *", "p_self"],
- ["const godot_rect3 *", "p_v"]
- ]
- },
- "godot_transform2d_new": {
- "return_type": "void",
- "arguments": [
- ["godot_transform2d *", "r_dest"],
- ["const godot_real", "p_rot"],
- ["const godot_vector2 *", "p_pos"]
- ]
- },
- "godot_transform2d_new_axis_origin": {
- "return_type": "void",
- "arguments": [
- ["godot_transform2d *", "r_dest"],
- ["const godot_vector2 *", "p_x_axis"],
- ["const godot_vector2 *", "p_y_axis"],
- ["const godot_vector2 *", "p_origin"]
- ]
- },
- "godot_transform2d_as_string": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_transform2d *", "p_self"]
- ]
- },
- "godot_transform2d_inverse": {
- "return_type": "godot_transform2d",
- "arguments": [
- ["const godot_transform2d *", "p_self"]
- ]
- },
- "godot_transform2d_affine_inverse": {
- "return_type": "godot_transform2d",
- "arguments": [
- ["const godot_transform2d *", "p_self"]
- ]
- },
- "godot_transform2d_get_rotation": {
- "return_type": "godot_real",
- "arguments": [
- ["const godot_transform2d *", "p_self"]
- ]
- },
- "godot_transform2d_get_origin": {
- "return_type": "godot_vector2",
- "arguments": [
- ["const godot_transform2d *", "p_self"]
- ]
- },
- "godot_transform2d_get_scale": {
- "return_type": "godot_vector2",
- "arguments": [
- ["const godot_transform2d *", "p_self"]
- ]
- },
- "godot_transform2d_orthonormalized": {
- "return_type": "godot_transform2d",
- "arguments": [
- ["const godot_transform2d *", "p_self"]
- ]
- },
- "godot_transform2d_rotated": {
- "return_type": "godot_transform2d",
- "arguments": [
- ["const godot_transform2d *", "p_self"],
- ["const godot_real", "p_phi"]
- ]
- },
- "godot_transform2d_scaled": {
- "return_type": "godot_transform2d",
- "arguments": [
- ["const godot_transform2d *", "p_self"],
- ["const godot_vector2 *", "p_scale"]
- ]
- },
- "godot_transform2d_translated": {
- "return_type": "godot_transform2d",
- "arguments": [
- ["const godot_transform2d *", "p_self"],
- ["const godot_vector2 *", "p_offset"]
- ]
- },
- "godot_transform2d_xform_vector2": {
- "return_type": "godot_vector2",
- "arguments": [
- ["const godot_transform2d *", "p_self"],
- ["const godot_vector2 *", "p_v"]
- ]
- },
- "godot_transform2d_xform_inv_vector2": {
- "return_type": "godot_vector2",
- "arguments": [
- ["const godot_transform2d *", "p_self"],
- ["const godot_vector2 *", "p_v"]
- ]
- },
- "godot_transform2d_basis_xform_vector2": {
- "return_type": "godot_vector2",
- "arguments": [
- ["const godot_transform2d *", "p_self"],
- ["const godot_vector2 *", "p_v"]
- ]
- },
- "godot_transform2d_basis_xform_inv_vector2": {
- "return_type": "godot_vector2",
- "arguments": [
- ["const godot_transform2d *", "p_self"],
- ["const godot_vector2 *", "p_v"]
- ]
- },
- "godot_transform2d_interpolate_with": {
- "return_type": "godot_transform2d",
- "arguments": [
- ["const godot_transform2d *", "p_self"],
- ["const godot_transform2d *", "p_m"],
- ["const godot_real", "p_c"]
- ]
- },
- "godot_transform2d_operator_equal": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_transform2d *", "p_self"],
- ["const godot_transform2d *", "p_b"]
- ]
- },
- "godot_transform2d_operator_multiply": {
- "return_type": "godot_transform2d",
- "arguments": [
- ["const godot_transform2d *", "p_self"],
- ["const godot_transform2d *", "p_b"]
- ]
- },
- "godot_transform2d_new_identity": {
- "return_type": "void",
- "arguments": [
- ["godot_transform2d *", "r_dest"]
- ]
- },
- "godot_transform2d_xform_rect2": {
- "return_type": "godot_rect2",
- "arguments": [
- ["const godot_transform2d *", "p_self"],
- ["const godot_rect2 *", "p_v"]
- ]
- },
- "godot_transform2d_xform_inv_rect2": {
- "return_type": "godot_rect2",
- "arguments": [
- ["const godot_transform2d *", "p_self"],
- ["const godot_rect2 *", "p_v"]
- ]
- },
- "godot_variant_get_type": {
- "return_type": "godot_variant_type",
- "arguments": [
- ["const godot_variant *", "p_v"]
- ]
- },
- "godot_variant_new_copy": {
- "return_type": "void",
- "arguments": [
- ["godot_variant *", "r_dest"],
- ["const godot_variant *", "p_src"]
- ]
- },
- "godot_variant_new_nil": {
- "return_type": "void",
- "arguments": [
- ["godot_variant *", "r_dest"]
- ]
- },
- "godot_variant_new_bool": {
- "return_type": "void",
- "arguments": [
- ["godot_variant *", "p_v"],
- ["const godot_bool", "p_b"]
- ]
- },
- "godot_variant_new_uint": {
- "return_type": "void",
- "arguments": [
- ["godot_variant *", "r_dest"],
- ["const uint64_t", "p_i"]
- ]
- },
- "godot_variant_new_int": {
- "return_type": "void",
- "arguments": [
- ["godot_variant *", "r_dest"],
- ["const int64_t", "p_i"]
- ]
- },
- "godot_variant_new_real": {
- "return_type": "void",
- "arguments": [
- ["godot_variant *", "r_dest"],
- ["const double", "p_r"]
- ]
- },
- "godot_variant_new_string": {
- "return_type": "void",
- "arguments": [
- ["godot_variant *", "r_dest"],
- ["const godot_string *", "p_s"]
- ]
- },
- "godot_variant_new_vector2": {
- "return_type": "void",
- "arguments": [
- ["godot_variant *", "r_dest"],
- ["const godot_vector2 *", "p_v2"]
- ]
- },
- "godot_variant_new_rect2": {
- "return_type": "void",
- "arguments": [
- ["godot_variant *", "r_dest"],
- ["const godot_rect2 *", "p_rect2"]
- ]
- },
- "godot_variant_new_vector3": {
- "return_type": "void",
- "arguments": [
- ["godot_variant *", "r_dest"],
- ["const godot_vector3 *", "p_v3"]
- ]
- },
- "godot_variant_new_transform2d": {
- "return_type": "void",
- "arguments": [
- ["godot_variant *", "r_dest"],
- ["const godot_transform2d *", "p_t2d"]
- ]
- },
- "godot_variant_new_plane": {
- "return_type": "void",
- "arguments": [
- ["godot_variant *", "r_dest"],
- ["const godot_plane *", "p_plane"]
- ]
- },
- "godot_variant_new_quat": {
- "return_type": "void",
- "arguments": [
- ["godot_variant *", "r_dest"],
- ["const godot_quat *", "p_quat"]
- ]
- },
- "godot_variant_new_rect3": {
- "return_type": "void",
- "arguments": [
- ["godot_variant *", "r_dest"],
- ["const godot_rect3 *", "p_rect3"]
- ]
- },
- "godot_variant_new_basis": {
- "return_type": "void",
- "arguments": [
- ["godot_variant *", "r_dest"],
- ["const godot_basis *", "p_basis"]
- ]
- },
- "godot_variant_new_transform": {
- "return_type": "void",
- "arguments": [
- ["godot_variant *", "r_dest"],
- ["const godot_transform *", "p_trans"]
- ]
- },
- "godot_variant_new_color": {
- "return_type": "void",
- "arguments": [
- ["godot_variant *", "r_dest"],
- ["const godot_color *", "p_color"]
- ]
- },
- "godot_variant_new_node_path": {
- "return_type": "void",
- "arguments": [
- ["godot_variant *", "r_dest"],
- ["const godot_node_path *", "p_np"]
- ]
- },
- "godot_variant_new_rid": {
- "return_type": "void",
- "arguments": [
- ["godot_variant *", "r_dest"],
- ["const godot_rid *", "p_rid"]
- ]
- },
- "godot_variant_new_object": {
- "return_type": "void",
- "arguments": [
- ["godot_variant *", "r_dest"],
- ["const godot_object *", "p_obj"]
- ]
- },
- "godot_variant_new_dictionary": {
- "return_type": "void",
- "arguments": [
- ["godot_variant *", "r_dest"],
- ["const godot_dictionary *", "p_dict"]
- ]
- },
- "godot_variant_new_array": {
- "return_type": "void",
- "arguments": [
- ["godot_variant *", "r_dest"],
- ["const godot_array *", "p_arr"]
- ]
- },
- "godot_variant_new_pool_byte_array": {
- "return_type": "void",
- "arguments": [
- ["godot_variant *", "r_dest"],
- ["const godot_pool_byte_array *", "p_pba"]
- ]
- },
- "godot_variant_new_pool_int_array": {
- "return_type": "void",
- "arguments": [
- ["godot_variant *", "r_dest"],
- ["const godot_pool_int_array *", "p_pia"]
- ]
- },
- "godot_variant_new_pool_real_array": {
- "return_type": "void",
- "arguments": [
- ["godot_variant *", "r_dest"],
- ["const godot_pool_real_array *", "p_pra"]
- ]
- },
- "godot_variant_new_pool_string_array": {
- "return_type": "void",
- "arguments": [
- ["godot_variant *", "r_dest"],
- ["const godot_pool_string_array *", "p_psa"]
- ]
- },
- "godot_variant_new_pool_vector2_array": {
- "return_type": "void",
- "arguments": [
- ["godot_variant *", "r_dest"],
- ["const godot_pool_vector2_array *", "p_pv2a"]
- ]
- },
- "godot_variant_new_pool_vector3_array": {
- "return_type": "void",
- "arguments": [
- ["godot_variant *", "r_dest"],
- ["const godot_pool_vector3_array *", "p_pv3a"]
- ]
- },
- "godot_variant_new_pool_color_array": {
- "return_type": "void",
- "arguments": [
- ["godot_variant *", "r_dest"],
- ["const godot_pool_color_array *", "p_pca"]
- ]
- },
- "godot_variant_as_bool": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_variant *", "p_self"]
- ]
- },
- "godot_variant_as_uint": {
- "return_type": "uint64_t",
- "arguments": [
- ["const godot_variant *", "p_self"]
- ]
- },
- "godot_variant_as_int": {
- "return_type": "int64_t",
- "arguments": [
- ["const godot_variant *", "p_self"]
- ]
- },
- "godot_variant_as_real": {
- "return_type": "double",
- "arguments": [
- ["const godot_variant *", "p_self"]
- ]
- },
- "godot_variant_as_string": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_variant *", "p_self"]
- ]
- },
- "godot_variant_as_vector2": {
- "return_type": "godot_vector2",
- "arguments": [
- ["const godot_variant *", "p_self"]
- ]
- },
- "godot_variant_as_rect2": {
- "return_type": "godot_rect2",
- "arguments": [
- ["const godot_variant *", "p_self"]
- ]
- },
- "godot_variant_as_vector3": {
- "return_type": "godot_vector3",
- "arguments": [
- ["const godot_variant *", "p_self"]
- ]
- },
- "godot_variant_as_transform2d": {
- "return_type": "godot_transform2d",
- "arguments": [
- ["const godot_variant *", "p_self"]
- ]
- },
- "godot_variant_as_plane": {
- "return_type": "godot_plane",
- "arguments": [
- ["const godot_variant *", "p_self"]
- ]
- },
- "godot_variant_as_quat": {
- "return_type": "godot_quat",
- "arguments": [
- ["const godot_variant *", "p_self"]
- ]
- },
- "godot_variant_as_rect3": {
- "return_type": "godot_rect3",
- "arguments": [
- ["const godot_variant *", "p_self"]
- ]
- },
- "godot_variant_as_basis": {
- "return_type": "godot_basis",
- "arguments": [
- ["const godot_variant *", "p_self"]
- ]
- },
- "godot_variant_as_transform": {
- "return_type": "godot_transform",
- "arguments": [
- ["const godot_variant *", "p_self"]
- ]
- },
- "godot_variant_as_color": {
- "return_type": "godot_color",
- "arguments": [
- ["const godot_variant *", "p_self"]
- ]
- },
- "godot_variant_as_node_path": {
- "return_type": "godot_node_path",
- "arguments": [
- ["const godot_variant *", "p_self"]
- ]
- },
- "godot_variant_as_rid": {
- "return_type": "godot_rid",
- "arguments": [
- ["const godot_variant *", "p_self"]
- ]
- },
- "godot_variant_as_object": {
- "return_type": "godot_object *",
- "arguments": [
- ["const godot_variant *", "p_self"]
- ]
- },
- "godot_variant_as_dictionary": {
- "return_type": "godot_dictionary",
- "arguments": [
- ["const godot_variant *", "p_self"]
- ]
- },
- "godot_variant_as_array": {
- "return_type": "godot_array",
- "arguments": [
- ["const godot_variant *", "p_self"]
- ]
- },
- "godot_variant_as_pool_byte_array": {
- "return_type": "godot_pool_byte_array",
- "arguments": [
- ["const godot_variant *", "p_self"]
- ]
- },
- "godot_variant_as_pool_int_array": {
- "return_type": "godot_pool_int_array",
- "arguments": [
- ["const godot_variant *", "p_self"]
- ]
- },
- "godot_variant_as_pool_real_array": {
- "return_type": "godot_pool_real_array",
- "arguments": [
- ["const godot_variant *", "p_self"]
- ]
- },
- "godot_variant_as_pool_string_array": {
- "return_type": "godot_pool_string_array",
- "arguments": [
- ["const godot_variant *", "p_self"]
- ]
- },
- "godot_variant_as_pool_vector2_array": {
- "return_type": "godot_pool_vector2_array",
- "arguments": [
- ["const godot_variant *", "p_self"]
- ]
- },
- "godot_variant_as_pool_vector3_array": {
- "return_type": "godot_pool_vector3_array",
- "arguments": [
- ["const godot_variant *", "p_self"]
- ]
- },
- "godot_variant_as_pool_color_array": {
- "return_type": "godot_pool_color_array",
- "arguments": [
- ["const godot_variant *", "p_self"]
- ]
- },
- "godot_variant_call": {
- "return_type": "godot_variant",
- "arguments": [
- ["godot_variant *", "p_self"],
- ["const godot_string *", "p_method"],
- ["const godot_variant **", "p_args"],
- ["const godot_int", "p_argcount"],
- ["godot_variant_call_error *", "r_error"]
- ]
- },
- "godot_variant_has_method": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_variant *", "p_self"],
- ["const godot_string *", "p_method"]
- ]
- },
- "godot_variant_operator_equal": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_variant *", "p_self"],
- ["const godot_variant *", "p_other"]
- ]
- },
- "godot_variant_operator_less": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_variant *", "p_self"],
- ["const godot_variant *", "p_other"]
- ]
- },
- "godot_variant_hash_compare": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_variant *", "p_self"],
- ["const godot_variant *", "p_other"]
- ]
- },
- "godot_variant_booleanize": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_variant *", "p_self"]
- ]
- },
- "godot_variant_destroy": {
- "return_type": "void",
- "arguments": [
- ["godot_variant *", "p_self"]
- ]
- },
- "godot_string_new": {
- "return_type": "void",
- "arguments": [
- ["godot_string *", "r_dest"]
- ]
- },
- "godot_string_new_copy": {
- "return_type": "void",
- "arguments": [
- ["godot_string *", "r_dest"],
- ["const godot_string *", "p_src"]
- ]
- },
- "godot_string_new_data": {
- "return_type": "void",
- "arguments": [
- ["godot_string *", "r_dest"],
- ["const char *", "p_contents"],
- ["const int", "p_size"]
- ]
- },
- "godot_string_new_unicode_data": {
- "return_type": "void",
- "arguments": [
- ["godot_string *", "r_dest"],
- ["const wchar_t *", "p_contents"],
- ["const int", "p_size"]
- ]
- },
- "godot_string_get_data": {
- "return_type": "void",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["char *", "p_dest"],
- ["int *", "p_size"]
- ]
- },
- "godot_string_operator_index": {
- "return_type": "wchar_t *",
- "arguments": [
- ["godot_string *", "p_self"],
- ["const godot_int", "p_idx"]
- ]
- },
- "godot_string_c_str": {
- "return_type": "const char *",
- "arguments": [
- ["const godot_string *", "p_self"]
- ]
- },
- "godot_string_unicode_str": {
- "return_type": "const wchar_t *",
- "arguments": [
- ["const godot_string *", "p_self"]
- ]
- },
- "godot_string_operator_equal": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["const godot_string *", "p_b"]
- ]
- },
- "godot_string_operator_less": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["const godot_string *", "p_b"]
- ]
- },
- "godot_string_operator_plus": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["const godot_string *", "p_b"]
- ]
- },
- "godot_string_length": {
- "return_type": "godot_int",
- "arguments": [
- ["const godot_string *", "p_self"]
- ]
- },
- "godot_string_begins_with": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["const godot_string *", "p_string"]
- ]
- },
- "godot_string_begins_with_char_array": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["const char *", "p_char_array"]
- ]
- },
- "godot_string_bigrams": {
- "return_type": "godot_array",
- "arguments": [
- ["const godot_string *", "p_self"]
- ]
- },
- "godot_string_chr": {
- "return_type": "godot_string",
- "arguments": [
- ["wchar_t", "p_character"]
- ]
- },
- "godot_string_ends_with": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["const godot_string *", "p_string"]
- ]
- },
- "godot_string_find": {
- "return_type": "godot_int",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["godot_string", "p_what"]
- ]
- },
- "godot_string_find_from": {
- "return_type": "godot_int",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["godot_string", "p_what"],
- ["godot_int", "p_from"]
- ]
- },
- "godot_string_findmk": {
- "return_type": "godot_int",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["const godot_array *", "p_keys"]
- ]
- },
- "godot_string_findmk_from": {
- "return_type": "godot_int",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["const godot_array *", "p_keys"],
- ["godot_int", "p_from"]
- ]
- },
- "godot_string_findmk_from_in_place": {
- "return_type": "godot_int",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["const godot_array *", "p_keys"],
- ["godot_int", "p_from"],
- ["godot_int *", "r_key"]
- ]
- },
- "godot_string_findn": {
- "return_type": "godot_int",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["godot_string", "p_what"]
- ]
- },
- "godot_string_findn_from": {
- "return_type": "godot_int",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["godot_string", "p_what"],
- ["godot_int", "p_from"]
- ]
- },
- "godot_string_find_last": {
- "return_type": "godot_int",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["godot_string", "p_what"]
- ]
- },
- "godot_string_format": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["const godot_variant *", "p_values"]
- ]
- },
- "godot_string_format_with_custom_placeholder": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["const godot_variant *", "p_values"],
- ["const char *", "p_placeholder"]
- ]
- },
- "godot_string_hex_encode_buffer": {
- "return_type": "godot_string",
- "arguments": [
- ["const uint8_t *", "p_buffer"],
- ["godot_int", "p_len"]
- ]
- },
- "godot_string_hex_to_int": {
- "return_type": "godot_int",
- "arguments": [
- ["const godot_string *", "p_self"]
- ]
- },
- "godot_string_hex_to_int_without_prefix": {
- "return_type": "godot_int",
- "arguments": [
- ["const godot_string *", "p_self"]
- ]
- },
- "godot_string_insert": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["godot_int", "p_at_pos"],
- ["godot_string", "p_string"]
- ]
- },
- "godot_string_is_numeric": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_string *", "p_self"]
- ]
- },
- "godot_string_is_subsequence_of": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["const godot_string *", "p_string"]
- ]
- },
- "godot_string_is_subsequence_ofi": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["const godot_string *", "p_string"]
- ]
- },
- "godot_string_lpad": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["godot_int", "p_min_length"]
- ]
- },
- "godot_string_lpad_with_custom_character": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["godot_int", "p_min_length"],
- ["const godot_string *", "p_character"]
- ]
- },
- "godot_string_match": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["const godot_string *", "p_wildcard"]
- ]
- },
- "godot_string_matchn": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["const godot_string *", "p_wildcard"]
- ]
- },
- "godot_string_md5": {
- "return_type": "godot_string",
- "arguments": [
- ["const uint8_t *", "p_md5"]
- ]
- },
- "godot_string_num": {
- "return_type": "godot_string",
- "arguments": [
- ["double", "p_num"]
- ]
- },
- "godot_string_num_int64": {
- "return_type": "godot_string",
- "arguments": [
- ["int64_t", "p_num"],
- ["godot_int", "p_base"]
- ]
- },
- "godot_string_num_int64_capitalized": {
- "return_type": "godot_string",
- "arguments": [
- ["int64_t", "p_num"],
- ["godot_int", "p_base"],
- ["godot_bool", "p_capitalize_hex"]
- ]
- },
- "godot_string_num_real": {
- "return_type": "godot_string",
- "arguments": [
- ["double", "p_num"]
- ]
- },
- "godot_string_num_scientific": {
- "return_type": "godot_string",
- "arguments": [
- ["double", "p_num"]
- ]
- },
- "godot_string_num_with_decimals": {
- "return_type": "godot_string",
- "arguments": [
- ["double", "p_num"],
- ["godot_int", "p_decimals"]
- ]
- },
- "godot_string_pad_decimals": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["godot_int", "p_digits"]
- ]
- },
- "godot_string_pad_zeros": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["godot_int", "p_digits"]
- ]
- },
- "godot_string_replace_first": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["godot_string", "p_key"],
- ["godot_string", "p_with"]
- ]
- },
- "godot_string_replace": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["godot_string", "p_key"],
- ["godot_string", "p_with"]
- ]
- },
- "godot_string_replacen": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["godot_string", "p_key"],
- ["godot_string", "p_with"]
- ]
- },
- "godot_string_rfind": {
- "return_type": "godot_int",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["godot_string", "p_what"]
- ]
- },
- "godot_string_rfindn": {
- "return_type": "godot_int",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["godot_string", "p_what"]
- ]
- },
- "godot_string_rfind_from": {
- "return_type": "godot_int",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["godot_string", "p_what"],
- ["godot_int", "p_from"]
- ]
- },
- "godot_string_rfindn_from": {
- "return_type": "godot_int",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["godot_string", "p_what"],
- ["godot_int", "p_from"]
- ]
- },
- "godot_string_rpad": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["godot_int", "p_min_length"]
- ]
- },
- "godot_string_rpad_with_custom_character": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["godot_int", "p_min_length"],
- ["const godot_string *", "p_character"]
- ]
- },
- "godot_string_similarity": {
- "return_type": "godot_real",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["const godot_string *", "p_string"]
- ]
- },
- "godot_string_sprintf": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["const godot_array *", "p_values"],
- ["godot_bool *", "p_error"]
- ]
- },
- "godot_string_substr": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["godot_int", "p_from"],
- ["godot_int", "p_chars"]
- ]
- },
- "godot_string_to_double": {
- "return_type": "double",
- "arguments": [
- ["const godot_string *", "p_self"]
- ]
- },
- "godot_string_to_float": {
- "return_type": "godot_real",
- "arguments": [
- ["const godot_string *", "p_self"]
- ]
- },
- "godot_string_to_int": {
- "return_type": "godot_int",
- "arguments": [
- ["const godot_string *", "p_self"]
- ]
- },
- "godot_string_camelcase_to_underscore": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_string *", "p_self"]
- ]
- },
- "godot_string_camelcase_to_underscore_lowercased": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_string *", "p_self"]
- ]
- },
- "godot_string_capitalize": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_string *", "p_self"]
- ]
- },
- "godot_string_char_to_double": {
- "return_type": "double",
- "arguments": [
- ["const char *", "p_what"]
- ]
- },
- "godot_string_char_to_int": {
- "return_type": "godot_int",
- "arguments": [
- ["const char *", "p_what"]
- ]
- },
- "godot_string_wchar_to_int": {
- "return_type": "int64_t",
- "arguments": [
- ["const wchar_t *", "p_str"]
- ]
- },
- "godot_string_char_to_int_with_len": {
- "return_type": "godot_int",
- "arguments": [
- ["const char *", "p_what"],
- ["godot_int", "p_len"]
- ]
- },
- "godot_string_char_to_int64_with_len": {
- "return_type": "int64_t",
- "arguments": [
- ["const wchar_t *", "p_str"],
- ["int", "p_len"]
- ]
- },
- "godot_string_hex_to_int64": {
- "return_type": "int64_t",
- "arguments": [
- ["const godot_string *", "p_self"]
- ]
- },
- "godot_string_hex_to_int64_with_prefix": {
- "return_type": "int64_t",
- "arguments": [
- ["const godot_string *", "p_self"]
- ]
- },
- "godot_string_to_int64": {
- "return_type": "int64_t",
- "arguments": [
- ["const godot_string *", "p_self"]
- ]
- },
- "godot_string_unicode_char_to_double": {
- "return_type": "double",
- "arguments": [
- ["const wchar_t *", "p_str"],
- ["const wchar_t **", "r_end"]
- ]
- },
- "godot_string_get_slice_count": {
- "return_type": "godot_int",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["godot_string", "p_splitter"]
- ]
- },
- "godot_string_get_slice": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["godot_string", "p_splitter"],
- ["godot_int", "p_slice"]
- ]
- },
- "godot_string_get_slicec": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["wchar_t", "p_splitter"],
- ["godot_int", "p_slice"]
- ]
- },
- "godot_string_split": {
- "return_type": "godot_array",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["const godot_string *", "p_splitter"]
- ]
- },
- "godot_string_split_allow_empty": {
- "return_type": "godot_array",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["const godot_string *", "p_splitter"]
- ]
- },
- "godot_string_split_floats": {
- "return_type": "godot_array",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["const godot_string *", "p_splitter"]
- ]
- },
- "godot_string_split_floats_allows_empty": {
- "return_type": "godot_array",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["const godot_string *", "p_splitter"]
- ]
- },
- "godot_string_split_floats_mk": {
- "return_type": "godot_array",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["const godot_array *", "p_splitters"]
- ]
- },
- "godot_string_split_floats_mk_allows_empty": {
- "return_type": "godot_array",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["const godot_array *", "p_splitters"]
- ]
- },
- "godot_string_split_ints": {
- "return_type": "godot_array",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["const godot_string *", "p_splitter"]
- ]
- },
- "godot_string_split_ints_allows_empty": {
- "return_type": "godot_array",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["const godot_string *", "p_splitter"]
- ]
- },
- "godot_string_split_ints_mk": {
- "return_type": "godot_array",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["const godot_array *", "p_splitters"]
- ]
- },
- "godot_string_split_ints_mk_allows_empty": {
- "return_type": "godot_array",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["const godot_array *", "p_splitters"]
- ]
- },
- "godot_string_split_spaces": {
- "return_type": "godot_array",
- "arguments": [
- ["const godot_string *", "p_self"]
- ]
- },
- "godot_string_char_lowercase": {
- "return_type": "wchar_t",
- "arguments": [
- ["wchar_t", "p_char"]
- ]
- },
- "godot_string_char_uppercase": {
- "return_type": "wchar_t",
- "arguments": [
- ["wchar_t", "p_char"]
- ]
- },
- "godot_string_to_lower": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_string *", "p_self"]
- ]
- },
- "godot_string_to_upper": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_string *", "p_self"]
- ]
- },
- "godot_string_get_basename": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_string *", "p_self"]
- ]
- },
- "godot_string_get_extension": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_string *", "p_self"]
- ]
- },
- "godot_string_left": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["godot_int", "p_pos"]
- ]
- },
- "godot_string_ord_at": {
- "return_type": "wchar_t",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["godot_int", "p_idx"]
- ]
- },
- "godot_string_plus_file": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["const godot_string *", "p_file"]
- ]
- },
- "godot_string_right": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["godot_int", "p_pos"]
- ]
- },
- "godot_string_strip_edges": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["godot_bool", "p_left"],
- ["godot_bool", "p_right"]
- ]
- },
- "godot_string_strip_escapes": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_string *", "p_self"]
- ]
- },
- "godot_string_erase": {
- "return_type": "void",
- "arguments": [
- ["godot_string *", "p_self"],
- ["godot_int", "p_pos"],
- ["godot_int", "p_chars"]
- ]
- },
- "godot_string_ascii": {
- "return_type": "void",
- "arguments": [
- ["godot_string *", "p_self"],
- ["char *", "result"]
- ]
- },
- "godot_string_ascii_extended": {
- "return_type": "void",
- "arguments": [
- ["godot_string *", "p_self"],
- ["char *", "result"]
- ]
- },
- "godot_string_utf8": {
- "return_type": "void",
- "arguments": [
- ["godot_string *", "p_self"],
- ["char *", "result"]
- ]
- },
- "godot_string_parse_utf8": {
- "return_type": "godot_bool",
- "arguments": [
- ["godot_string *", "p_self"],
- ["const char *", "p_utf8"]
- ]
- },
- "godot_string_parse_utf8_with_len": {
- "return_type": "godot_bool",
- "arguments": [
- ["godot_string *", "p_self"],
- ["const char *", "p_utf8"],
- ["godot_int", "p_len"]
- ]
- },
- "godot_string_chars_to_utf8": {
- "return_type": "godot_string",
- "arguments": [
- ["const char *", "p_utf8"]
- ]
- },
- "godot_string_chars_to_utf8_with_len": {
- "return_type": "godot_string",
- "arguments": [
- ["const char *", "p_utf8"],
- ["godot_int", "p_len"]
- ]
- },
- "godot_string_hash": {
- "return_type": "uint32_t",
- "arguments": [
- ["const godot_string *", "p_self"]
- ]
- },
- "godot_string_hash64": {
- "return_type": "uint64_t",
- "arguments": [
- ["const godot_string *", "p_self"]
- ]
- },
- "godot_string_hash_chars": {
- "return_type": "uint32_t",
- "arguments": [
- ["const char *", "p_cstr"]
- ]
- },
- "godot_string_hash_chars_with_len": {
- "return_type": "uint32_t",
- "arguments": [
- ["const char *", "p_cstr"],
- ["godot_int", "p_len"]
- ]
- },
- "godot_string_hash_utf8_chars": {
- "return_type": "uint32_t",
- "arguments": [
- ["const wchar_t *", "p_str"]
- ]
- },
- "godot_string_hash_utf8_chars_with_len": {
- "return_type": "uint32_t",
- "arguments": [
- ["const wchar_t *", "p_str"],
- ["godot_int", "p_len"]
- ]
- },
- "godot_string_md5_buffer": {
- "return_type": "godot_pool_byte_array",
- "arguments": [
- ["const godot_string *", "p_self"]
- ]
- },
- "godot_string_md5_text": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_string *", "p_self"]
- ]
- },
- "godot_string_sha256_buffer": {
- "return_type": "godot_pool_byte_array",
- "arguments": [
- ["const godot_string *", "p_self"]
- ]
- },
- "godot_string_sha256_text": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_string *", "p_self"]
- ]
- },
- "godot_string_empty": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_string *", "p_self"]
- ]
- },
- "godot_string_get_base_dir": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_string *", "p_self"]
- ]
- },
- "godot_string_get_file": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_string *", "p_self"]
- ]
- },
- "godot_string_humanize_size": {
- "return_type": "godot_string",
- "arguments": [
- ["size_t", "p_size"]
- ]
- },
- "godot_string_is_abs_path": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_string *", "p_self"]
- ]
- },
- "godot_string_is_rel_path": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_string *", "p_self"]
- ]
- },
- "godot_string_is_resource_file": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_string *", "p_self"]
- ]
- },
- "godot_string_path_to": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["const godot_string *", "p_path"]
- ]
- },
- "godot_string_path_to_file": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["const godot_string *", "p_path"]
- ]
- },
- "godot_string_simplify_path": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_string *", "p_self"]
- ]
- },
- "godot_string_c_escape": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_string *", "p_self"]
- ]
- },
- "godot_string_c_escape_multiline": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_string *", "p_self"]
- ]
- },
- "godot_string_c_unescape": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_string *", "p_self"]
- ]
- },
- "godot_string_http_escape": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_string *", "p_self"]
- ]
- },
- "godot_string_http_unescape": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_string *", "p_self"]
- ]
- },
- "godot_string_json_escape": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_string *", "p_self"]
- ]
- },
- "godot_string_word_wrap": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["godot_int", "p_chars_per_line"]
- ]
- },
- "godot_string_xml_escape": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_string *", "p_self"]
- ]
- },
- "godot_string_xml_escape_with_quotes": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_string *", "p_self"]
- ]
- },
- "godot_string_xml_unescape": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_string *", "p_self"]
- ]
- },
- "godot_string_percent_decode": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_string *", "p_self"]
- ]
- },
- "godot_string_percent_encode": {
- "return_type": "godot_string",
- "arguments": [
- ["const godot_string *", "p_self"]
- ]
- },
- "godot_string_is_valid_float": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_string *", "p_self"]
- ]
- },
- "godot_string_is_valid_hex_number": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_string *", "p_self"],
- ["godot_bool", "p_with_prefix"]
- ]
- },
- "godot_string_is_valid_html_color": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_string *", "p_self"]
- ]
- },
- "godot_string_is_valid_identifier": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_string *", "p_self"]
- ]
- },
- "godot_string_is_valid_integer": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_string *", "p_self"]
- ]
- },
- "godot_string_is_valid_ip_address": {
- "return_type": "godot_bool",
- "arguments": [
- ["const godot_string *", "p_self"]
- ]
- },
- "godot_string_destroy": {
- "return_type": "void",
- "arguments": [
- ["godot_string *", "p_self"]
- ]
- },
- "godot_object_destroy": {
- "return_type": "void",
- "arguments": [
- ["godot_object *", "p_o"]
- ]
- },
- "godot_global_get_singleton": {
- "return_type": "godot_object *",
- "arguments": [
- ["char *", "p_name"]
- ]
- },
- "godot_method_bind_get_method": {
- "return_type": "godot_method_bind *",
- "arguments": [
- ["const char *", "p_classname"],
- ["const char *", "p_methodname"]
- ]
- },
- "godot_method_bind_ptrcall": {
- "return_type": "void",
- "arguments": [
- ["godot_method_bind *", "p_method_bind"],
- ["godot_object *", "p_instance"],
- ["const void **", "p_args"],
- ["void *", "p_ret"]
- ]
- },
- "godot_method_bind_call": {
- "return_type": "godot_variant",
- "arguments": [
- ["godot_method_bind *", "p_method_bind"],
- ["godot_object *", "p_instance"],
- ["const godot_variant **", "p_args"],
- ["const int", "p_arg_count"],
- ["godot_variant_call_error *", "p_call_error"]
- ]
- },
- "godot_get_class_constructor": {
- "return_type": "godot_class_constructor",
- "arguments": [
- ["const char *", "p_classname"]
- ]
- },
- "godot_alloc": {
- "return_type": "void *",
- "arguments": [
- ["int", "p_bytes"]
- ]
- },
- "godot_realloc": {
- "return_type": "void *",
- "arguments": [
- ["void *", "p_ptr"],
- ["int", "p_bytes"]
- ]
- },
- "godot_free": {
- "return_type": "void",
- "arguments": [
- ["void *", "p_ptr"]
- ]
- },
- "godot_print_error": {
- "return_type": "void",
- "arguments": [
- ["const char *", "p_description"],
- ["const char *", "p_function"],
- ["const char *", "p_file"],
- ["int", "p_line"]
- ]
- },
- "godot_print_warning": {
- "return_type": "void",
- "arguments": [
- ["const char *", "p_description"],
- ["const char *", "p_function"],
- ["const char *", "p_file"],
- ["int", "p_line"]
- ]
- },
- "godot_print": {
- "return_type": "void",
- "arguments": [
- ["const godot_string *", "p_message"]
- ]
- },
- "godot_nativescript_register_class": {
- "return_type": "void",
- "arguments": [
- ["void *", "p_gdnative_handle"],
- ["const char *", "p_name"],
- ["const char *", "p_base"],
- ["godot_instance_create_func", "p_create_func"],
- ["godot_instance_destroy_func", "p_destroy_func"]
- ]
- },
- "godot_nativescript_register_tool_class": {
- "return_type": "void",
- "arguments": [
- ["void *", "p_gdnative_handle"],
- ["const char *", "p_name"],
- ["const char *", "p_base"],
- ["godot_instance_create_func", "p_create_func"],
- ["godot_instance_destroy_func", "p_destroy_func"]
- ]
- },
- "godot_nativescript_register_method": {
- "return_type": "void",
- "arguments": [
- ["void *", "p_gdnative_handle"],
- ["const char *", "p_name"],
- ["const char *", "p_function_name"],
- ["godot_method_attributes", "p_attr"],
- ["godot_instance_method", "p_method"]
- ]
- },
- "godot_nativescript_register_property": {
- "return_type": "void",
- "arguments": [
- ["void *", "p_gdnative_handle"],
- ["const char *", "p_name"],
- ["const char *", "p_path"],
- ["godot_property_attributes *", "p_attr"],
- ["godot_property_set_func", "p_set_func"],
- ["godot_property_get_func", "p_get_func"]
- ]
- },
- "godot_nativescript_register_signal": {
- "return_type": "void",
- "arguments": [
- ["void *", "p_gdnative_handle"],
- ["const char *", "p_name"],
- ["const godot_signal *", "p_signal"]
- ]
- },
- "godot_nativescript_get_userdata": {
- "return_type": "void *",
- "arguments": [
- ["godot_object *", "p_instance"]
+ "core": {
+ "type": "CORE",
+ "version": {
+ "major": 1,
+ "minor": 0
+ },
+ "api": [
+ {
+ "name": "godot_color_new_rgba",
+ "return_type": "void",
+ "arguments": [
+ ["godot_color *", "r_dest"],
+ ["const godot_real", "p_r"],
+ ["const godot_real", "p_g"],
+ ["const godot_real", "p_b"],
+ ["const godot_real", "p_a"]
+ ]
+ },
+ {
+ "name": "godot_color_new_rgb",
+ "return_type": "void",
+ "arguments": [
+ ["godot_color *", "r_dest"],
+ ["const godot_real", "p_r"],
+ ["const godot_real", "p_g"],
+ ["const godot_real", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_color_get_r",
+ "return_type": "godot_real",
+ "arguments": [
+ ["const godot_color *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_color_set_r",
+ "return_type": "void",
+ "arguments": [
+ ["godot_color *", "p_self"],
+ ["const godot_real", "r"]
+ ]
+ },
+ {
+ "name": "godot_color_get_g",
+ "return_type": "godot_real",
+ "arguments": [
+ ["const godot_color *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_color_set_g",
+ "return_type": "void",
+ "arguments": [
+ ["godot_color *", "p_self"],
+ ["const godot_real", "g"]
+ ]
+ },
+ {
+ "name": "godot_color_get_b",
+ "return_type": "godot_real",
+ "arguments": [
+ ["const godot_color *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_color_set_b",
+ "return_type": "void",
+ "arguments": [
+ ["godot_color *", "p_self"],
+ ["const godot_real", "b"]
+ ]
+ },
+ {
+ "name": "godot_color_get_a",
+ "return_type": "godot_real",
+ "arguments": [
+ ["const godot_color *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_color_set_a",
+ "return_type": "void",
+ "arguments": [
+ ["godot_color *", "p_self"],
+ ["const godot_real", "a"]
+ ]
+ },
+ {
+ "name": "godot_color_get_h",
+ "return_type": "godot_real",
+ "arguments": [
+ ["const godot_color *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_color_get_s",
+ "return_type": "godot_real",
+ "arguments": [
+ ["const godot_color *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_color_get_v",
+ "return_type": "godot_real",
+ "arguments": [
+ ["const godot_color *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_color_as_string",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_color *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_color_to_rgba32",
+ "return_type": "godot_int",
+ "arguments": [
+ ["const godot_color *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_color_to_argb32",
+ "return_type": "godot_int",
+ "arguments": [
+ ["const godot_color *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_color_gray",
+ "return_type": "godot_real",
+ "arguments": [
+ ["const godot_color *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_color_inverted",
+ "return_type": "godot_color",
+ "arguments": [
+ ["const godot_color *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_color_contrasted",
+ "return_type": "godot_color",
+ "arguments": [
+ ["const godot_color *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_color_linear_interpolate",
+ "return_type": "godot_color",
+ "arguments": [
+ ["const godot_color *", "p_self"],
+ ["const godot_color *", "p_b"],
+ ["const godot_real", "p_t"]
+ ]
+ },
+ {
+ "name": "godot_color_blend",
+ "return_type": "godot_color",
+ "arguments": [
+ ["const godot_color *", "p_self"],
+ ["const godot_color *", "p_over"]
+ ]
+ },
+ {
+ "name": "godot_color_to_html",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_color *", "p_self"],
+ ["const godot_bool", "p_with_alpha"]
+ ]
+ },
+ {
+ "name": "godot_color_operator_equal",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_color *", "p_self"],
+ ["const godot_color *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_color_operator_less",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_color *", "p_self"],
+ ["const godot_color *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_vector2_new",
+ "return_type": "void",
+ "arguments": [
+ ["godot_vector2 *", "r_dest"],
+ ["const godot_real", "p_x"],
+ ["const godot_real", "p_y"]
+ ]
+ },
+ {
+ "name": "godot_vector2_as_string",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_vector2 *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_vector2_normalized",
+ "return_type": "godot_vector2",
+ "arguments": [
+ ["const godot_vector2 *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_vector2_length",
+ "return_type": "godot_real",
+ "arguments": [
+ ["const godot_vector2 *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_vector2_angle",
+ "return_type": "godot_real",
+ "arguments": [
+ ["const godot_vector2 *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_vector2_length_squared",
+ "return_type": "godot_real",
+ "arguments": [
+ ["const godot_vector2 *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_vector2_is_normalized",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_vector2 *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_vector2_distance_to",
+ "return_type": "godot_real",
+ "arguments": [
+ ["const godot_vector2 *", "p_self"],
+ ["const godot_vector2 *", "p_to"]
+ ]
+ },
+ {
+ "name": "godot_vector2_distance_squared_to",
+ "return_type": "godot_real",
+ "arguments": [
+ ["const godot_vector2 *", "p_self"],
+ ["const godot_vector2 *", "p_to"]
+ ]
+ },
+ {
+ "name": "godot_vector2_angle_to",
+ "return_type": "godot_real",
+ "arguments": [
+ ["const godot_vector2 *", "p_self"],
+ ["const godot_vector2 *", "p_to"]
+ ]
+ },
+ {
+ "name": "godot_vector2_angle_to_point",
+ "return_type": "godot_real",
+ "arguments": [
+ ["const godot_vector2 *", "p_self"],
+ ["const godot_vector2 *", "p_to"]
+ ]
+ },
+ {
+ "name": "godot_vector2_linear_interpolate",
+ "return_type": "godot_vector2",
+ "arguments": [
+ ["const godot_vector2 *", "p_self"],
+ ["const godot_vector2 *", "p_b"],
+ ["const godot_real", "p_t"]
+ ]
+ },
+ {
+ "name": "godot_vector2_cubic_interpolate",
+ "return_type": "godot_vector2",
+ "arguments": [
+ ["const godot_vector2 *", "p_self"],
+ ["const godot_vector2 *", "p_b"],
+ ["const godot_vector2 *", "p_pre_a"],
+ ["const godot_vector2 *", "p_post_b"],
+ ["const godot_real", "p_t"]
+ ]
+ },
+ {
+ "name": "godot_vector2_rotated",
+ "return_type": "godot_vector2",
+ "arguments": [
+ ["const godot_vector2 *", "p_self"],
+ ["const godot_real", "p_phi"]
+ ]
+ },
+ {
+ "name": "godot_vector2_tangent",
+ "return_type": "godot_vector2",
+ "arguments": [
+ ["const godot_vector2 *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_vector2_floor",
+ "return_type": "godot_vector2",
+ "arguments": [
+ ["const godot_vector2 *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_vector2_snapped",
+ "return_type": "godot_vector2",
+ "arguments": [
+ ["const godot_vector2 *", "p_self"],
+ ["const godot_vector2 *", "p_by"]
+ ]
+ },
+ {
+ "name": "godot_vector2_aspect",
+ "return_type": "godot_real",
+ "arguments": [
+ ["const godot_vector2 *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_vector2_dot",
+ "return_type": "godot_real",
+ "arguments": [
+ ["const godot_vector2 *", "p_self"],
+ ["const godot_vector2 *", "p_with"]
+ ]
+ },
+ {
+ "name": "godot_vector2_slide",
+ "return_type": "godot_vector2",
+ "arguments": [
+ ["const godot_vector2 *", "p_self"],
+ ["const godot_vector2 *", "p_n"]
+ ]
+ },
+ {
+ "name": "godot_vector2_bounce",
+ "return_type": "godot_vector2",
+ "arguments": [
+ ["const godot_vector2 *", "p_self"],
+ ["const godot_vector2 *", "p_n"]
+ ]
+ },
+ {
+ "name": "godot_vector2_reflect",
+ "return_type": "godot_vector2",
+ "arguments": [
+ ["const godot_vector2 *", "p_self"],
+ ["const godot_vector2 *", "p_n"]
+ ]
+ },
+ {
+ "name": "godot_vector2_abs",
+ "return_type": "godot_vector2",
+ "arguments": [
+ ["const godot_vector2 *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_vector2_clamped",
+ "return_type": "godot_vector2",
+ "arguments": [
+ ["const godot_vector2 *", "p_self"],
+ ["const godot_real", "p_length"]
+ ]
+ },
+ {
+ "name": "godot_vector2_operator_add",
+ "return_type": "godot_vector2",
+ "arguments": [
+ ["const godot_vector2 *", "p_self"],
+ ["const godot_vector2 *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_vector2_operator_substract",
+ "return_type": "godot_vector2",
+ "arguments": [
+ ["const godot_vector2 *", "p_self"],
+ ["const godot_vector2 *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_vector2_operator_multiply_vector",
+ "return_type": "godot_vector2",
+ "arguments": [
+ ["const godot_vector2 *", "p_self"],
+ ["const godot_vector2 *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_vector2_operator_multiply_scalar",
+ "return_type": "godot_vector2",
+ "arguments": [
+ ["const godot_vector2 *", "p_self"],
+ ["const godot_real", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_vector2_operator_divide_vector",
+ "return_type": "godot_vector2",
+ "arguments": [
+ ["const godot_vector2 *", "p_self"],
+ ["const godot_vector2 *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_vector2_operator_divide_scalar",
+ "return_type": "godot_vector2",
+ "arguments": [
+ ["const godot_vector2 *", "p_self"],
+ ["const godot_real", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_vector2_operator_equal",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_vector2 *", "p_self"],
+ ["const godot_vector2 *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_vector2_operator_less",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_vector2 *", "p_self"],
+ ["const godot_vector2 *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_vector2_operator_neg",
+ "return_type": "godot_vector2",
+ "arguments": [
+ ["const godot_vector2 *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_vector2_set_x",
+ "return_type": "void",
+ "arguments": [
+ ["godot_vector2 *", "p_self"],
+ ["const godot_real", "p_x"]
+ ]
+ },
+ {
+ "name": "godot_vector2_set_y",
+ "return_type": "void",
+ "arguments": [
+ ["godot_vector2 *", "p_self"],
+ ["const godot_real", "p_y"]
+ ]
+ },
+ {
+ "name": "godot_vector2_get_x",
+ "return_type": "godot_real",
+ "arguments": [
+ ["const godot_vector2 *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_vector2_get_y",
+ "return_type": "godot_real",
+ "arguments": [
+ ["const godot_vector2 *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_quat_new",
+ "return_type": "void",
+ "arguments": [
+ ["godot_quat *", "r_dest"],
+ ["const godot_real", "p_x"],
+ ["const godot_real", "p_y"],
+ ["const godot_real", "p_z"],
+ ["const godot_real", "p_w"]
+ ]
+ },
+ {
+ "name": "godot_quat_new_with_axis_angle",
+ "return_type": "void",
+ "arguments": [
+ ["godot_quat *", "r_dest"],
+ ["const godot_vector3 *", "p_axis"],
+ ["const godot_real", "p_angle"]
+ ]
+ },
+ {
+ "name": "godot_quat_get_x",
+ "return_type": "godot_real",
+ "arguments": [
+ ["const godot_quat *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_quat_set_x",
+ "return_type": "void",
+ "arguments": [
+ ["godot_quat *", "p_self"],
+ ["const godot_real", "val"]
+ ]
+ },
+ {
+ "name": "godot_quat_get_y",
+ "return_type": "godot_real",
+ "arguments": [
+ ["const godot_quat *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_quat_set_y",
+ "return_type": "void",
+ "arguments": [
+ ["godot_quat *", "p_self"],
+ ["const godot_real", "val"]
+ ]
+ },
+ {
+ "name": "godot_quat_get_z",
+ "return_type": "godot_real",
+ "arguments": [
+ ["const godot_quat *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_quat_set_z",
+ "return_type": "void",
+ "arguments": [
+ ["godot_quat *", "p_self"],
+ ["const godot_real", "val"]
+ ]
+ },
+ {
+ "name": "godot_quat_get_w",
+ "return_type": "godot_real",
+ "arguments": [
+ ["const godot_quat *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_quat_set_w",
+ "return_type": "void",
+ "arguments": [
+ ["godot_quat *", "p_self"],
+ ["const godot_real", "val"]
+ ]
+ },
+ {
+ "name": "godot_quat_as_string",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_quat *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_quat_length",
+ "return_type": "godot_real",
+ "arguments": [
+ ["const godot_quat *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_quat_length_squared",
+ "return_type": "godot_real",
+ "arguments": [
+ ["const godot_quat *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_quat_normalized",
+ "return_type": "godot_quat",
+ "arguments": [
+ ["const godot_quat *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_quat_is_normalized",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_quat *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_quat_inverse",
+ "return_type": "godot_quat",
+ "arguments": [
+ ["const godot_quat *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_quat_dot",
+ "return_type": "godot_real",
+ "arguments": [
+ ["const godot_quat *", "p_self"],
+ ["const godot_quat *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_quat_xform",
+ "return_type": "godot_vector3",
+ "arguments": [
+ ["const godot_quat *", "p_self"],
+ ["const godot_vector3 *", "p_v"]
+ ]
+ },
+ {
+ "name": "godot_quat_slerp",
+ "return_type": "godot_quat",
+ "arguments": [
+ ["const godot_quat *", "p_self"],
+ ["const godot_quat *", "p_b"],
+ ["const godot_real", "p_t"]
+ ]
+ },
+ {
+ "name": "godot_quat_slerpni",
+ "return_type": "godot_quat",
+ "arguments": [
+ ["const godot_quat *", "p_self"],
+ ["const godot_quat *", "p_b"],
+ ["const godot_real", "p_t"]
+ ]
+ },
+ {
+ "name": "godot_quat_cubic_slerp",
+ "return_type": "godot_quat",
+ "arguments": [
+ ["const godot_quat *", "p_self"],
+ ["const godot_quat *", "p_b"],
+ ["const godot_quat *", "p_pre_a"],
+ ["const godot_quat *", "p_post_b"],
+ ["const godot_real", "p_t"]
+ ]
+ },
+ {
+ "name": "godot_quat_operator_multiply",
+ "return_type": "godot_quat",
+ "arguments": [
+ ["const godot_quat *", "p_self"],
+ ["const godot_real", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_quat_operator_add",
+ "return_type": "godot_quat",
+ "arguments": [
+ ["const godot_quat *", "p_self"],
+ ["const godot_quat *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_quat_operator_substract",
+ "return_type": "godot_quat",
+ "arguments": [
+ ["const godot_quat *", "p_self"],
+ ["const godot_quat *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_quat_operator_divide",
+ "return_type": "godot_quat",
+ "arguments": [
+ ["const godot_quat *", "p_self"],
+ ["const godot_real", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_quat_operator_equal",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_quat *", "p_self"],
+ ["const godot_quat *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_quat_operator_neg",
+ "return_type": "godot_quat",
+ "arguments": [
+ ["const godot_quat *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_basis_new_with_rows",
+ "return_type": "void",
+ "arguments": [
+ ["godot_basis *", "r_dest"],
+ ["const godot_vector3 *", "p_x_axis"],
+ ["const godot_vector3 *", "p_y_axis"],
+ ["const godot_vector3 *", "p_z_axis"]
+ ]
+ },
+ {
+ "name": "godot_basis_new_with_axis_and_angle",
+ "return_type": "void",
+ "arguments": [
+ ["godot_basis *", "r_dest"],
+ ["const godot_vector3 *", "p_axis"],
+ ["const godot_real", "p_phi"]
+ ]
+ },
+ {
+ "name": "godot_basis_new_with_euler",
+ "return_type": "void",
+ "arguments": [
+ ["godot_basis *", "r_dest"],
+ ["const godot_vector3 *", "p_euler"]
+ ]
+ },
+ {
+ "name": "godot_basis_as_string",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_basis *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_basis_inverse",
+ "return_type": "godot_basis",
+ "arguments": [
+ ["const godot_basis *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_basis_transposed",
+ "return_type": "godot_basis",
+ "arguments": [
+ ["const godot_basis *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_basis_orthonormalized",
+ "return_type": "godot_basis",
+ "arguments": [
+ ["const godot_basis *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_basis_determinant",
+ "return_type": "godot_real",
+ "arguments": [
+ ["const godot_basis *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_basis_rotated",
+ "return_type": "godot_basis",
+ "arguments": [
+ ["const godot_basis *", "p_self"],
+ ["const godot_vector3 *", "p_axis"],
+ ["const godot_real", "p_phi"]
+ ]
+ },
+ {
+ "name": "godot_basis_scaled",
+ "return_type": "godot_basis",
+ "arguments": [
+ ["const godot_basis *", "p_self"],
+ ["const godot_vector3 *", "p_scale"]
+ ]
+ },
+ {
+ "name": "godot_basis_get_scale",
+ "return_type": "godot_vector3",
+ "arguments": [
+ ["const godot_basis *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_basis_get_euler",
+ "return_type": "godot_vector3",
+ "arguments": [
+ ["const godot_basis *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_basis_tdotx",
+ "return_type": "godot_real",
+ "arguments": [
+ ["const godot_basis *", "p_self"],
+ ["const godot_vector3 *", "p_with"]
+ ]
+ },
+ {
+ "name": "godot_basis_tdoty",
+ "return_type": "godot_real",
+ "arguments": [
+ ["const godot_basis *", "p_self"],
+ ["const godot_vector3 *", "p_with"]
+ ]
+ },
+ {
+ "name": "godot_basis_tdotz",
+ "return_type": "godot_real",
+ "arguments": [
+ ["const godot_basis *", "p_self"],
+ ["const godot_vector3 *", "p_with"]
+ ]
+ },
+ {
+ "name": "godot_basis_xform",
+ "return_type": "godot_vector3",
+ "arguments": [
+ ["const godot_basis *", "p_self"],
+ ["const godot_vector3 *", "p_v"]
+ ]
+ },
+ {
+ "name": "godot_basis_xform_inv",
+ "return_type": "godot_vector3",
+ "arguments": [
+ ["const godot_basis *", "p_self"],
+ ["const godot_vector3 *", "p_v"]
+ ]
+ },
+ {
+ "name": "godot_basis_get_orthogonal_index",
+ "return_type": "godot_int",
+ "arguments": [
+ ["const godot_basis *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_basis_new",
+ "return_type": "void",
+ "arguments": [
+ ["godot_basis *", "r_dest"]
+ ]
+ },
+ {
+ "name": "godot_basis_new_with_euler_quat",
+ "return_type": "void",
+ "arguments": [
+ ["godot_basis *", "r_dest"],
+ ["const godot_quat *", "p_euler"]
+ ]
+ },
+ {
+ "name": "godot_basis_get_elements",
+ "return_type": "void",
+ "arguments": [
+ ["const godot_basis *", "p_self"],
+ ["godot_vector3 *", "p_elements"]
+ ]
+ },
+ {
+ "name": "godot_basis_get_axis",
+ "return_type": "godot_vector3",
+ "arguments": [
+ ["const godot_basis *", "p_self"],
+ ["const godot_int", "p_axis"]
+ ]
+ },
+ {
+ "name": "godot_basis_set_axis",
+ "return_type": "void",
+ "arguments": [
+ ["godot_basis *", "p_self"],
+ ["const godot_int", "p_axis"],
+ ["const godot_vector3 *", "p_value"]
+ ]
+ },
+ {
+ "name": "godot_basis_get_row",
+ "return_type": "godot_vector3",
+ "arguments": [
+ ["const godot_basis *", "p_self"],
+ ["const godot_int", "p_row"]
+ ]
+ },
+ {
+ "name": "godot_basis_set_row",
+ "return_type": "void",
+ "arguments": [
+ ["godot_basis *", "p_self"],
+ ["const godot_int", "p_row"],
+ ["const godot_vector3 *", "p_value"]
+ ]
+ },
+ {
+ "name": "godot_basis_operator_equal",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_basis *", "p_self"],
+ ["const godot_basis *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_basis_operator_add",
+ "return_type": "godot_basis",
+ "arguments": [
+ ["const godot_basis *", "p_self"],
+ ["const godot_basis *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_basis_operator_substract",
+ "return_type": "godot_basis",
+ "arguments": [
+ ["const godot_basis *", "p_self"],
+ ["const godot_basis *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_basis_operator_multiply_vector",
+ "return_type": "godot_basis",
+ "arguments": [
+ ["const godot_basis *", "p_self"],
+ ["const godot_basis *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_basis_operator_multiply_scalar",
+ "return_type": "godot_basis",
+ "arguments": [
+ ["const godot_basis *", "p_self"],
+ ["const godot_real", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_vector3_new",
+ "return_type": "void",
+ "arguments": [
+ ["godot_vector3 *", "r_dest"],
+ ["const godot_real", "p_x"],
+ ["const godot_real", "p_y"],
+ ["const godot_real", "p_z"]
+ ]
+ },
+ {
+ "name": "godot_vector3_as_string",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_vector3 *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_vector3_min_axis",
+ "return_type": "godot_int",
+ "arguments": [
+ ["const godot_vector3 *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_vector3_max_axis",
+ "return_type": "godot_int",
+ "arguments": [
+ ["const godot_vector3 *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_vector3_length",
+ "return_type": "godot_real",
+ "arguments": [
+ ["const godot_vector3 *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_vector3_length_squared",
+ "return_type": "godot_real",
+ "arguments": [
+ ["const godot_vector3 *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_vector3_is_normalized",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_vector3 *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_vector3_normalized",
+ "return_type": "godot_vector3",
+ "arguments": [
+ ["const godot_vector3 *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_vector3_inverse",
+ "return_type": "godot_vector3",
+ "arguments": [
+ ["const godot_vector3 *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_vector3_snapped",
+ "return_type": "godot_vector3",
+ "arguments": [
+ ["const godot_vector3 *", "p_self"],
+ ["const godot_vector3 *", "p_by"]
+ ]
+ },
+ {
+ "name": "godot_vector3_rotated",
+ "return_type": "godot_vector3",
+ "arguments": [
+ ["const godot_vector3 *", "p_self"],
+ ["const godot_vector3 *", "p_axis"],
+ ["const godot_real", "p_phi"]
+ ]
+ },
+ {
+ "name": "godot_vector3_linear_interpolate",
+ "return_type": "godot_vector3",
+ "arguments": [
+ ["const godot_vector3 *", "p_self"],
+ ["const godot_vector3 *", "p_b"],
+ ["const godot_real", "p_t"]
+ ]
+ },
+ {
+ "name": "godot_vector3_cubic_interpolate",
+ "return_type": "godot_vector3",
+ "arguments": [
+ ["const godot_vector3 *", "p_self"],
+ ["const godot_vector3 *", "p_b"],
+ ["const godot_vector3 *", "p_pre_a"],
+ ["const godot_vector3 *", "p_post_b"],
+ ["const godot_real", "p_t"]
+ ]
+ },
+ {
+ "name": "godot_vector3_dot",
+ "return_type": "godot_real",
+ "arguments": [
+ ["const godot_vector3 *", "p_self"],
+ ["const godot_vector3 *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_vector3_cross",
+ "return_type": "godot_vector3",
+ "arguments": [
+ ["const godot_vector3 *", "p_self"],
+ ["const godot_vector3 *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_vector3_outer",
+ "return_type": "godot_basis",
+ "arguments": [
+ ["const godot_vector3 *", "p_self"],
+ ["const godot_vector3 *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_vector3_to_diagonal_matrix",
+ "return_type": "godot_basis",
+ "arguments": [
+ ["const godot_vector3 *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_vector3_abs",
+ "return_type": "godot_vector3",
+ "arguments": [
+ ["const godot_vector3 *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_vector3_floor",
+ "return_type": "godot_vector3",
+ "arguments": [
+ ["const godot_vector3 *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_vector3_ceil",
+ "return_type": "godot_vector3",
+ "arguments": [
+ ["const godot_vector3 *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_vector3_distance_to",
+ "return_type": "godot_real",
+ "arguments": [
+ ["const godot_vector3 *", "p_self"],
+ ["const godot_vector3 *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_vector3_distance_squared_to",
+ "return_type": "godot_real",
+ "arguments": [
+ ["const godot_vector3 *", "p_self"],
+ ["const godot_vector3 *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_vector3_angle_to",
+ "return_type": "godot_real",
+ "arguments": [
+ ["const godot_vector3 *", "p_self"],
+ ["const godot_vector3 *", "p_to"]
+ ]
+ },
+ {
+ "name": "godot_vector3_slide",
+ "return_type": "godot_vector3",
+ "arguments": [
+ ["const godot_vector3 *", "p_self"],
+ ["const godot_vector3 *", "p_n"]
+ ]
+ },
+ {
+ "name": "godot_vector3_bounce",
+ "return_type": "godot_vector3",
+ "arguments": [
+ ["const godot_vector3 *", "p_self"],
+ ["const godot_vector3 *", "p_n"]
+ ]
+ },
+ {
+ "name": "godot_vector3_reflect",
+ "return_type": "godot_vector3",
+ "arguments": [
+ ["const godot_vector3 *", "p_self"],
+ ["const godot_vector3 *", "p_n"]
+ ]
+ },
+ {
+ "name": "godot_vector3_operator_add",
+ "return_type": "godot_vector3",
+ "arguments": [
+ ["const godot_vector3 *", "p_self"],
+ ["const godot_vector3 *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_vector3_operator_substract",
+ "return_type": "godot_vector3",
+ "arguments": [
+ ["const godot_vector3 *", "p_self"],
+ ["const godot_vector3 *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_vector3_operator_multiply_vector",
+ "return_type": "godot_vector3",
+ "arguments": [
+ ["const godot_vector3 *", "p_self"],
+ ["const godot_vector3 *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_vector3_operator_multiply_scalar",
+ "return_type": "godot_vector3",
+ "arguments": [
+ ["const godot_vector3 *", "p_self"],
+ ["const godot_real", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_vector3_operator_divide_vector",
+ "return_type": "godot_vector3",
+ "arguments": [
+ ["const godot_vector3 *", "p_self"],
+ ["const godot_vector3 *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_vector3_operator_divide_scalar",
+ "return_type": "godot_vector3",
+ "arguments": [
+ ["const godot_vector3 *", "p_self"],
+ ["const godot_real", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_vector3_operator_equal",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_vector3 *", "p_self"],
+ ["const godot_vector3 *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_vector3_operator_less",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_vector3 *", "p_self"],
+ ["const godot_vector3 *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_vector3_operator_neg",
+ "return_type": "godot_vector3",
+ "arguments": [
+ ["const godot_vector3 *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_vector3_set_axis",
+ "return_type": "void",
+ "arguments": [
+ ["godot_vector3 *", "p_self"],
+ ["const godot_vector3_axis", "p_axis"],
+ ["const godot_real", "p_val"]
+ ]
+ },
+ {
+ "name": "godot_vector3_get_axis",
+ "return_type": "godot_real",
+ "arguments": [
+ ["const godot_vector3 *", "p_self"],
+ ["const godot_vector3_axis", "p_axis"]
+ ]
+ },
+ {
+ "name": "godot_pool_byte_array_new",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_byte_array *", "r_dest"]
+ ]
+ },
+ {
+ "name": "godot_pool_byte_array_new_copy",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_byte_array *", "r_dest"],
+ ["const godot_pool_byte_array *", "p_src"]
+ ]
+ },
+ {
+ "name": "godot_pool_byte_array_new_with_array",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_byte_array *", "r_dest"],
+ ["const godot_array *", "p_a"]
+ ]
+ },
+ {
+ "name": "godot_pool_byte_array_append",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_byte_array *", "p_self"],
+ ["const uint8_t", "p_data"]
+ ]
+ },
+ {
+ "name": "godot_pool_byte_array_append_array",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_byte_array *", "p_self"],
+ ["const godot_pool_byte_array *", "p_array"]
+ ]
+ },
+ {
+ "name": "godot_pool_byte_array_insert",
+ "return_type": "godot_error",
+ "arguments": [
+ ["godot_pool_byte_array *", "p_self"],
+ ["const godot_int", "p_idx"],
+ ["const uint8_t", "p_data"]
+ ]
+ },
+ {
+ "name": "godot_pool_byte_array_invert",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_byte_array *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_pool_byte_array_push_back",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_byte_array *", "p_self"],
+ ["const uint8_t", "p_data"]
+ ]
+ },
+ {
+ "name": "godot_pool_byte_array_remove",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_byte_array *", "p_self"],
+ ["const godot_int", "p_idx"]
+ ]
+ },
+ {
+ "name": "godot_pool_byte_array_resize",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_byte_array *", "p_self"],
+ ["const godot_int", "p_size"]
+ ]
+ },
+ {
+ "name": "godot_pool_byte_array_read",
+ "return_type": "godot_pool_byte_array_read_access *",
+ "arguments": [
+ ["const godot_pool_byte_array *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_pool_byte_array_write",
+ "return_type": "godot_pool_byte_array_write_access *",
+ "arguments": [
+ ["godot_pool_byte_array *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_pool_byte_array_set",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_byte_array *", "p_self"],
+ ["const godot_int", "p_idx"],
+ ["const uint8_t", "p_data"]
+ ]
+ },
+ {
+ "name": "godot_pool_byte_array_get",
+ "return_type": "uint8_t",
+ "arguments": [
+ ["const godot_pool_byte_array *", "p_self"],
+ ["const godot_int", "p_idx"]
+ ]
+ },
+ {
+ "name": "godot_pool_byte_array_size",
+ "return_type": "godot_int",
+ "arguments": [
+ ["const godot_pool_byte_array *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_pool_byte_array_destroy",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_byte_array *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_pool_int_array_new",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_int_array *", "r_dest"]
+ ]
+ },
+ {
+ "name": "godot_pool_int_array_new_copy",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_int_array *", "r_dest"],
+ ["const godot_pool_int_array *", "p_src"]
+ ]
+ },
+ {
+ "name": "godot_pool_int_array_new_with_array",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_int_array *", "r_dest"],
+ ["const godot_array *", "p_a"]
+ ]
+ },
+ {
+ "name": "godot_pool_int_array_append",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_int_array *", "p_self"],
+ ["const godot_int", "p_data"]
+ ]
+ },
+ {
+ "name": "godot_pool_int_array_append_array",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_int_array *", "p_self"],
+ ["const godot_pool_int_array *", "p_array"]
+ ]
+ },
+ {
+ "name": "godot_pool_int_array_insert",
+ "return_type": "godot_error",
+ "arguments": [
+ ["godot_pool_int_array *", "p_self"],
+ ["const godot_int", "p_idx"],
+ ["const godot_int", "p_data"]
+ ]
+ },
+ {
+ "name": "godot_pool_int_array_invert",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_int_array *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_pool_int_array_push_back",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_int_array *", "p_self"],
+ ["const godot_int", "p_data"]
+ ]
+ },
+ {
+ "name": "godot_pool_int_array_remove",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_int_array *", "p_self"],
+ ["const godot_int", "p_idx"]
+ ]
+ },
+ {
+ "name": "godot_pool_int_array_resize",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_int_array *", "p_self"],
+ ["const godot_int", "p_size"]
+ ]
+ },
+ {
+ "name": "godot_pool_int_array_read",
+ "return_type": "godot_pool_int_array_read_access *",
+ "arguments": [
+ ["const godot_pool_int_array *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_pool_int_array_write",
+ "return_type": "godot_pool_int_array_write_access *",
+ "arguments": [
+ ["godot_pool_int_array *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_pool_int_array_set",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_int_array *", "p_self"],
+ ["const godot_int", "p_idx"],
+ ["const godot_int", "p_data"]
+ ]
+ },
+ {
+ "name": "godot_pool_int_array_get",
+ "return_type": "godot_int",
+ "arguments": [
+ ["const godot_pool_int_array *", "p_self"],
+ ["const godot_int", "p_idx"]
+ ]
+ },
+ {
+ "name": "godot_pool_int_array_size",
+ "return_type": "godot_int",
+ "arguments": [
+ ["const godot_pool_int_array *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_pool_int_array_destroy",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_int_array *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_pool_real_array_new",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_real_array *", "r_dest"]
+ ]
+ },
+ {
+ "name": "godot_pool_real_array_new_copy",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_real_array *", "r_dest"],
+ ["const godot_pool_real_array *", "p_src"]
+ ]
+ },
+ {
+ "name": "godot_pool_real_array_new_with_array",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_real_array *", "r_dest"],
+ ["const godot_array *", "p_a"]
+ ]
+ },
+ {
+ "name": "godot_pool_real_array_append",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_real_array *", "p_self"],
+ ["const godot_real", "p_data"]
+ ]
+ },
+ {
+ "name": "godot_pool_real_array_append_array",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_real_array *", "p_self"],
+ ["const godot_pool_real_array *", "p_array"]
+ ]
+ },
+ {
+ "name": "godot_pool_real_array_insert",
+ "return_type": "godot_error",
+ "arguments": [
+ ["godot_pool_real_array *", "p_self"],
+ ["const godot_int", "p_idx"],
+ ["const godot_real", "p_data"]
+ ]
+ },
+ {
+ "name": "godot_pool_real_array_invert",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_real_array *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_pool_real_array_push_back",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_real_array *", "p_self"],
+ ["const godot_real", "p_data"]
+ ]
+ },
+ {
+ "name": "godot_pool_real_array_remove",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_real_array *", "p_self"],
+ ["const godot_int", "p_idx"]
+ ]
+ },
+ {
+ "name": "godot_pool_real_array_resize",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_real_array *", "p_self"],
+ ["const godot_int", "p_size"]
+ ]
+ },
+ {
+ "name": "godot_pool_real_array_read",
+ "return_type": "godot_pool_real_array_read_access *",
+ "arguments": [
+ ["const godot_pool_real_array *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_pool_real_array_write",
+ "return_type": "godot_pool_real_array_write_access *",
+ "arguments": [
+ ["godot_pool_real_array *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_pool_real_array_set",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_real_array *", "p_self"],
+ ["const godot_int", "p_idx"],
+ ["const godot_real", "p_data"]
+ ]
+ },
+ {
+ "name": "godot_pool_real_array_get",
+ "return_type": "godot_real",
+ "arguments": [
+ ["const godot_pool_real_array *", "p_self"],
+ ["const godot_int", "p_idx"]
+ ]
+ },
+ {
+ "name": "godot_pool_real_array_size",
+ "return_type": "godot_int",
+ "arguments": [
+ ["const godot_pool_real_array *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_pool_real_array_destroy",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_real_array *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_pool_string_array_new",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_string_array *", "r_dest"]
+ ]
+ },
+ {
+ "name": "godot_pool_string_array_new_copy",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_string_array *", "r_dest"],
+ ["const godot_pool_string_array *", "p_src"]
+ ]
+ },
+ {
+ "name": "godot_pool_string_array_new_with_array",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_string_array *", "r_dest"],
+ ["const godot_array *", "p_a"]
+ ]
+ },
+ {
+ "name": "godot_pool_string_array_append",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_string_array *", "p_self"],
+ ["const godot_string *", "p_data"]
+ ]
+ },
+ {
+ "name": "godot_pool_string_array_append_array",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_string_array *", "p_self"],
+ ["const godot_pool_string_array *", "p_array"]
+ ]
+ },
+ {
+ "name": "godot_pool_string_array_insert",
+ "return_type": "godot_error",
+ "arguments": [
+ ["godot_pool_string_array *", "p_self"],
+ ["const godot_int", "p_idx"],
+ ["const godot_string *", "p_data"]
+ ]
+ },
+ {
+ "name": "godot_pool_string_array_invert",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_string_array *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_pool_string_array_push_back",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_string_array *", "p_self"],
+ ["const godot_string *", "p_data"]
+ ]
+ },
+ {
+ "name": "godot_pool_string_array_remove",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_string_array *", "p_self"],
+ ["const godot_int", "p_idx"]
+ ]
+ },
+ {
+ "name": "godot_pool_string_array_resize",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_string_array *", "p_self"],
+ ["const godot_int", "p_size"]
+ ]
+ },
+ {
+ "name": "godot_pool_string_array_read",
+ "return_type": "godot_pool_string_array_read_access *",
+ "arguments": [
+ ["const godot_pool_string_array *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_pool_string_array_write",
+ "return_type": "godot_pool_string_array_write_access *",
+ "arguments": [
+ ["godot_pool_string_array *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_pool_string_array_set",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_string_array *", "p_self"],
+ ["const godot_int", "p_idx"],
+ ["const godot_string *", "p_data"]
+ ]
+ },
+ {
+ "name": "godot_pool_string_array_get",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_pool_string_array *", "p_self"],
+ ["const godot_int", "p_idx"]
+ ]
+ },
+ {
+ "name": "godot_pool_string_array_size",
+ "return_type": "godot_int",
+ "arguments": [
+ ["const godot_pool_string_array *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_pool_string_array_destroy",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_string_array *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_pool_vector2_array_new",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_vector2_array *", "r_dest"]
+ ]
+ },
+ {
+ "name": "godot_pool_vector2_array_new_copy",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_vector2_array *", "r_dest"],
+ ["const godot_pool_vector2_array *", "p_src"]
+ ]
+ },
+ {
+ "name": "godot_pool_vector2_array_new_with_array",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_vector2_array *", "r_dest"],
+ ["const godot_array *", "p_a"]
+ ]
+ },
+ {
+ "name": "godot_pool_vector2_array_append",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_vector2_array *", "p_self"],
+ ["const godot_vector2 *", "p_data"]
+ ]
+ },
+ {
+ "name": "godot_pool_vector2_array_append_array",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_vector2_array *", "p_self"],
+ ["const godot_pool_vector2_array *", "p_array"]
+ ]
+ },
+ {
+ "name": "godot_pool_vector2_array_insert",
+ "return_type": "godot_error",
+ "arguments": [
+ ["godot_pool_vector2_array *", "p_self"],
+ ["const godot_int", "p_idx"],
+ ["const godot_vector2 *", "p_data"]
+ ]
+ },
+ {
+ "name": "godot_pool_vector2_array_invert",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_vector2_array *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_pool_vector2_array_push_back",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_vector2_array *", "p_self"],
+ ["const godot_vector2 *", "p_data"]
+ ]
+ },
+ {
+ "name": "godot_pool_vector2_array_remove",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_vector2_array *", "p_self"],
+ ["const godot_int", "p_idx"]
+ ]
+ },
+ {
+ "name": "godot_pool_vector2_array_resize",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_vector2_array *", "p_self"],
+ ["const godot_int", "p_size"]
+ ]
+ },
+ {
+ "name": "godot_pool_vector2_array_read",
+ "return_type": "godot_pool_vector2_array_read_access *",
+ "arguments": [
+ ["const godot_pool_vector2_array *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_pool_vector2_array_write",
+ "return_type": "godot_pool_vector2_array_write_access *",
+ "arguments": [
+ ["godot_pool_vector2_array *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_pool_vector2_array_set",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_vector2_array *", "p_self"],
+ ["const godot_int", "p_idx"],
+ ["const godot_vector2 *", "p_data"]
+ ]
+ },
+ {
+ "name": "godot_pool_vector2_array_get",
+ "return_type": "godot_vector2",
+ "arguments": [
+ ["const godot_pool_vector2_array *", "p_self"],
+ ["const godot_int", "p_idx"]
+ ]
+ },
+ {
+ "name": "godot_pool_vector2_array_size",
+ "return_type": "godot_int",
+ "arguments": [
+ ["const godot_pool_vector2_array *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_pool_vector2_array_destroy",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_vector2_array *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_pool_vector3_array_new",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_vector3_array *", "r_dest"]
+ ]
+ },
+ {
+ "name": "godot_pool_vector3_array_new_copy",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_vector3_array *", "r_dest"],
+ ["const godot_pool_vector3_array *", "p_src"]
+ ]
+ },
+ {
+ "name": "godot_pool_vector3_array_new_with_array",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_vector3_array *", "r_dest"],
+ ["const godot_array *", "p_a"]
+ ]
+ },
+ {
+ "name": "godot_pool_vector3_array_append",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_vector3_array *", "p_self"],
+ ["const godot_vector3 *", "p_data"]
+ ]
+ },
+ {
+ "name": "godot_pool_vector3_array_append_array",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_vector3_array *", "p_self"],
+ ["const godot_pool_vector3_array *", "p_array"]
+ ]
+ },
+ {
+ "name": "godot_pool_vector3_array_insert",
+ "return_type": "godot_error",
+ "arguments": [
+ ["godot_pool_vector3_array *", "p_self"],
+ ["const godot_int", "p_idx"],
+ ["const godot_vector3 *", "p_data"]
+ ]
+ },
+ {
+ "name": "godot_pool_vector3_array_invert",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_vector3_array *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_pool_vector3_array_push_back",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_vector3_array *", "p_self"],
+ ["const godot_vector3 *", "p_data"]
+ ]
+ },
+ {
+ "name": "godot_pool_vector3_array_remove",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_vector3_array *", "p_self"],
+ ["const godot_int", "p_idx"]
+ ]
+ },
+ {
+ "name": "godot_pool_vector3_array_resize",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_vector3_array *", "p_self"],
+ ["const godot_int", "p_size"]
+ ]
+ },
+ {
+ "name": "godot_pool_vector3_array_read",
+ "return_type": "godot_pool_vector3_array_read_access *",
+ "arguments": [
+ ["const godot_pool_vector3_array *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_pool_vector3_array_write",
+ "return_type": "godot_pool_vector3_array_write_access *",
+ "arguments": [
+ ["godot_pool_vector3_array *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_pool_vector3_array_set",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_vector3_array *", "p_self"],
+ ["const godot_int", "p_idx"],
+ ["const godot_vector3 *", "p_data"]
+ ]
+ },
+ {
+ "name": "godot_pool_vector3_array_get",
+ "return_type": "godot_vector3",
+ "arguments": [
+ ["const godot_pool_vector3_array *", "p_self"],
+ ["const godot_int", "p_idx"]
+ ]
+ },
+ {
+ "name": "godot_pool_vector3_array_size",
+ "return_type": "godot_int",
+ "arguments": [
+ ["const godot_pool_vector3_array *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_pool_vector3_array_destroy",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_vector3_array *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_pool_color_array_new",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_color_array *", "r_dest"]
+ ]
+ },
+ {
+ "name": "godot_pool_color_array_new_copy",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_color_array *", "r_dest"],
+ ["const godot_pool_color_array *", "p_src"]
+ ]
+ },
+ {
+ "name": "godot_pool_color_array_new_with_array",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_color_array *", "r_dest"],
+ ["const godot_array *", "p_a"]
+ ]
+ },
+ {
+ "name": "godot_pool_color_array_append",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_color_array *", "p_self"],
+ ["const godot_color *", "p_data"]
+ ]
+ },
+ {
+ "name": "godot_pool_color_array_append_array",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_color_array *", "p_self"],
+ ["const godot_pool_color_array *", "p_array"]
+ ]
+ },
+ {
+ "name": "godot_pool_color_array_insert",
+ "return_type": "godot_error",
+ "arguments": [
+ ["godot_pool_color_array *", "p_self"],
+ ["const godot_int", "p_idx"],
+ ["const godot_color *", "p_data"]
+ ]
+ },
+ {
+ "name": "godot_pool_color_array_invert",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_color_array *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_pool_color_array_push_back",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_color_array *", "p_self"],
+ ["const godot_color *", "p_data"]
+ ]
+ },
+ {
+ "name": "godot_pool_color_array_remove",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_color_array *", "p_self"],
+ ["const godot_int", "p_idx"]
+ ]
+ },
+ {
+ "name": "godot_pool_color_array_resize",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_color_array *", "p_self"],
+ ["const godot_int", "p_size"]
+ ]
+ },
+ {
+ "name": "godot_pool_color_array_read",
+ "return_type": "godot_pool_color_array_read_access *",
+ "arguments": [
+ ["const godot_pool_color_array *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_pool_color_array_write",
+ "return_type": "godot_pool_color_array_write_access *",
+ "arguments": [
+ ["godot_pool_color_array *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_pool_color_array_set",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_color_array *", "p_self"],
+ ["const godot_int", "p_idx"],
+ ["const godot_color *", "p_data"]
+ ]
+ },
+ {
+ "name": "godot_pool_color_array_get",
+ "return_type": "godot_color",
+ "arguments": [
+ ["const godot_pool_color_array *", "p_self"],
+ ["const godot_int", "p_idx"]
+ ]
+ },
+ {
+ "name": "godot_pool_color_array_size",
+ "return_type": "godot_int",
+ "arguments": [
+ ["const godot_pool_color_array *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_pool_color_array_destroy",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_color_array *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_pool_byte_array_read_access_ptr",
+ "return_type": "const uint8_t *",
+ "arguments": [
+ ["const godot_pool_byte_array_read_access *", "p_read"]
+ ]
+ },
+ {
+ "name": "godot_pool_byte_array_read_access_operator_assign",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_byte_array_read_access *", "p_read"],
+ ["godot_pool_byte_array_read_access *", "p_other"]
+ ]
+ },
+ {
+ "name": "godot_pool_byte_array_read_access_destroy",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_byte_array_read_access *", "p_read"]
+ ]
+ },
+ {
+ "name": "godot_pool_int_array_read_access_ptr",
+ "return_type": "const godot_int *",
+ "arguments": [
+ ["const godot_pool_int_array_read_access *", "p_read"]
+ ]
+ },
+ {
+ "name": "godot_pool_int_array_read_access_operator_assign",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_int_array_read_access *", "p_read"],
+ ["godot_pool_int_array_read_access *", "p_other"]
+ ]
+ },
+ {
+ "name": "godot_pool_int_array_read_access_destroy",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_int_array_read_access *", "p_read"]
+ ]
+ },
+ {
+ "name": "godot_pool_real_array_read_access_ptr",
+ "return_type": "const godot_real *",
+ "arguments": [
+ ["const godot_pool_real_array_read_access *", "p_read"]
+ ]
+ },
+ {
+ "name": "godot_pool_real_array_read_access_operator_assign",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_real_array_read_access *", "p_read"],
+ ["godot_pool_real_array_read_access *", "p_other"]
+ ]
+ },
+ {
+ "name": "godot_pool_real_array_read_access_destroy",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_real_array_read_access *", "p_read"]
+ ]
+ },
+ {
+ "name": "godot_pool_string_array_read_access_ptr",
+ "return_type": "const godot_string *",
+ "arguments": [
+ ["const godot_pool_string_array_read_access *", "p_read"]
+ ]
+ },
+ {
+ "name": "godot_pool_string_array_read_access_operator_assign",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_string_array_read_access *", "p_read"],
+ ["godot_pool_string_array_read_access *", "p_other"]
+ ]
+ },
+ {
+ "name": "godot_pool_string_array_read_access_destroy",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_string_array_read_access *", "p_read"]
+ ]
+ },
+ {
+ "name": "godot_pool_vector2_array_read_access_ptr",
+ "return_type": "const godot_vector2 *",
+ "arguments": [
+ ["const godot_pool_vector2_array_read_access *", "p_read"]
+ ]
+ },
+ {
+ "name": "godot_pool_vector2_array_read_access_operator_assign",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_vector2_array_read_access *", "p_read"],
+ ["godot_pool_vector2_array_read_access *", "p_other"]
+ ]
+ },
+ {
+ "name": "godot_pool_vector2_array_read_access_destroy",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_vector2_array_read_access *", "p_read"]
+ ]
+ },
+ {
+ "name": "godot_pool_vector3_array_read_access_ptr",
+ "return_type": "const godot_vector3 *",
+ "arguments": [
+ ["const godot_pool_vector3_array_read_access *", "p_read"]
+ ]
+ },
+ {
+ "name": "godot_pool_vector3_array_read_access_operator_assign",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_vector3_array_read_access *", "p_read"],
+ ["godot_pool_vector3_array_read_access *", "p_other"]
+ ]
+ },
+ {
+ "name": "godot_pool_vector3_array_read_access_destroy",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_vector3_array_read_access *", "p_read"]
+ ]
+ },
+ {
+ "name": "godot_pool_color_array_read_access_ptr",
+ "return_type": "const godot_color *",
+ "arguments": [
+ ["const godot_pool_color_array_read_access *", "p_read"]
+ ]
+ },
+ {
+ "name": "godot_pool_color_array_read_access_operator_assign",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_color_array_read_access *", "p_read"],
+ ["godot_pool_color_array_read_access *", "p_other"]
+ ]
+ },
+ {
+ "name": "godot_pool_color_array_read_access_destroy",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_color_array_read_access *", "p_read"]
+ ]
+ },
+ {
+ "name": "godot_pool_byte_array_write_access_ptr",
+ "return_type": "uint8_t *",
+ "arguments": [
+ ["const godot_pool_byte_array_write_access *", "p_write"]
+ ]
+ },
+ {
+ "name": "godot_pool_byte_array_write_access_operator_assign",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_byte_array_write_access *", "p_write"],
+ ["godot_pool_byte_array_write_access *", "p_other"]
+ ]
+ },
+ {
+ "name": "godot_pool_byte_array_write_access_destroy",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_byte_array_write_access *", "p_write"]
+ ]
+ },
+ {
+ "name": "godot_pool_int_array_write_access_ptr",
+ "return_type": "godot_int *",
+ "arguments": [
+ ["const godot_pool_int_array_write_access *", "p_write"]
+ ]
+ },
+ {
+ "name": "godot_pool_int_array_write_access_operator_assign",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_int_array_write_access *", "p_write"],
+ ["godot_pool_int_array_write_access *", "p_other"]
+ ]
+ },
+ {
+ "name": "godot_pool_int_array_write_access_destroy",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_int_array_write_access *", "p_write"]
+ ]
+ },
+ {
+ "name": "godot_pool_real_array_write_access_ptr",
+ "return_type": "godot_real *",
+ "arguments": [
+ ["const godot_pool_real_array_write_access *", "p_write"]
+ ]
+ },
+ {
+ "name": "godot_pool_real_array_write_access_operator_assign",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_real_array_write_access *", "p_write"],
+ ["godot_pool_real_array_write_access *", "p_other"]
+ ]
+ },
+ {
+ "name": "godot_pool_real_array_write_access_destroy",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_real_array_write_access *", "p_write"]
+ ]
+ },
+ {
+ "name": "godot_pool_string_array_write_access_ptr",
+ "return_type": "godot_string *",
+ "arguments": [
+ ["const godot_pool_string_array_write_access *", "p_write"]
+ ]
+ },
+ {
+ "name": "godot_pool_string_array_write_access_operator_assign",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_string_array_write_access *", "p_write"],
+ ["godot_pool_string_array_write_access *", "p_other"]
+ ]
+ },
+ {
+ "name": "godot_pool_string_array_write_access_destroy",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_string_array_write_access *", "p_write"]
+ ]
+ },
+ {
+ "name": "godot_pool_vector2_array_write_access_ptr",
+ "return_type": "godot_vector2 *",
+ "arguments": [
+ ["const godot_pool_vector2_array_write_access *", "p_write"]
+ ]
+ },
+ {
+ "name": "godot_pool_vector2_array_write_access_operator_assign",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_vector2_array_write_access *", "p_write"],
+ ["godot_pool_vector2_array_write_access *", "p_other"]
+ ]
+ },
+ {
+ "name": "godot_pool_vector2_array_write_access_destroy",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_vector2_array_write_access *", "p_write"]
+ ]
+ },
+ {
+ "name": "godot_pool_vector3_array_write_access_ptr",
+ "return_type": "godot_vector3 *",
+ "arguments": [
+ ["const godot_pool_vector3_array_write_access *", "p_write"]
+ ]
+ },
+ {
+ "name": "godot_pool_vector3_array_write_access_operator_assign",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_vector3_array_write_access *", "p_write"],
+ ["godot_pool_vector3_array_write_access *", "p_other"]
+ ]
+ },
+ {
+ "name": "godot_pool_vector3_array_write_access_destroy",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_vector3_array_write_access *", "p_write"]
+ ]
+ },
+ {
+ "name": "godot_pool_color_array_write_access_ptr",
+ "return_type": "godot_color *",
+ "arguments": [
+ ["const godot_pool_color_array_write_access *", "p_write"]
+ ]
+ },
+ {
+ "name": "godot_pool_color_array_write_access_operator_assign",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_color_array_write_access *", "p_write"],
+ ["godot_pool_color_array_write_access *", "p_other"]
+ ]
+ },
+ {
+ "name": "godot_pool_color_array_write_access_destroy",
+ "return_type": "void",
+ "arguments": [
+ ["godot_pool_color_array_write_access *", "p_write"]
+ ]
+ },
+ {
+ "name": "godot_array_new",
+ "return_type": "void",
+ "arguments": [
+ ["godot_array *", "r_dest"]
+ ]
+ },
+ {
+ "name": "godot_array_new_copy",
+ "return_type": "void",
+ "arguments": [
+ ["godot_array *", "r_dest"],
+ ["const godot_array *", "p_src"]
+ ]
+ },
+ {
+ "name": "godot_array_new_pool_color_array",
+ "return_type": "void",
+ "arguments": [
+ ["godot_array *", "r_dest"],
+ ["const godot_pool_color_array *", "p_pca"]
+ ]
+ },
+ {
+ "name": "godot_array_new_pool_vector3_array",
+ "return_type": "void",
+ "arguments": [
+ ["godot_array *", "r_dest"],
+ ["const godot_pool_vector3_array *", "p_pv3a"]
+ ]
+ },
+ {
+ "name": "godot_array_new_pool_vector2_array",
+ "return_type": "void",
+ "arguments": [
+ ["godot_array *", "r_dest"],
+ ["const godot_pool_vector2_array *", "p_pv2a"]
+ ]
+ },
+ {
+ "name": "godot_array_new_pool_string_array",
+ "return_type": "void",
+ "arguments": [
+ ["godot_array *", "r_dest"],
+ ["const godot_pool_string_array *", "p_psa"]
+ ]
+ },
+ {
+ "name": "godot_array_new_pool_real_array",
+ "return_type": "void",
+ "arguments": [
+ ["godot_array *", "r_dest"],
+ ["const godot_pool_real_array *", "p_pra"]
+ ]
+ },
+ {
+ "name": "godot_array_new_pool_int_array",
+ "return_type": "void",
+ "arguments": [
+ ["godot_array *", "r_dest"],
+ ["const godot_pool_int_array *", "p_pia"]
+ ]
+ },
+ {
+ "name": "godot_array_new_pool_byte_array",
+ "return_type": "void",
+ "arguments": [
+ ["godot_array *", "r_dest"],
+ ["const godot_pool_byte_array *", "p_pba"]
+ ]
+ },
+ {
+ "name": "godot_array_set",
+ "return_type": "void",
+ "arguments": [
+ ["godot_array *", "p_self"],
+ ["const godot_int", "p_idx"],
+ ["const godot_variant *", "p_value"]
+ ]
+ },
+ {
+ "name": "godot_array_get",
+ "return_type": "godot_variant",
+ "arguments": [
+ ["const godot_array *", "p_self"],
+ ["const godot_int", "p_idx"]
+ ]
+ },
+ {
+ "name": "godot_array_operator_index",
+ "return_type": "godot_variant *",
+ "arguments": [
+ ["godot_array *", "p_self"],
+ ["const godot_int", "p_idx"]
+ ]
+ },
+ {
+ "name": "godot_array_operator_index_const",
+ "return_type": "const godot_variant *",
+ "arguments": [
+ ["const godot_array *", "p_self"],
+ ["const godot_int", "p_idx"]
+ ]
+ },
+ {
+ "name": "godot_array_append",
+ "return_type": "void",
+ "arguments": [
+ ["godot_array *", "p_self"],
+ ["const godot_variant *", "p_value"]
+ ]
+ },
+ {
+ "name": "godot_array_clear",
+ "return_type": "void",
+ "arguments": [
+ ["godot_array *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_array_count",
+ "return_type": "godot_int",
+ "arguments": [
+ ["const godot_array *", "p_self"],
+ ["const godot_variant *", "p_value"]
+ ]
+ },
+ {
+ "name": "godot_array_empty",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_array *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_array_erase",
+ "return_type": "void",
+ "arguments": [
+ ["godot_array *", "p_self"],
+ ["const godot_variant *", "p_value"]
+ ]
+ },
+ {
+ "name": "godot_array_front",
+ "return_type": "godot_variant",
+ "arguments": [
+ ["const godot_array *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_array_back",
+ "return_type": "godot_variant",
+ "arguments": [
+ ["const godot_array *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_array_find",
+ "return_type": "godot_int",
+ "arguments": [
+ ["const godot_array *", "p_self"],
+ ["const godot_variant *", "p_what"],
+ ["const godot_int", "p_from"]
+ ]
+ },
+ {
+ "name": "godot_array_find_last",
+ "return_type": "godot_int",
+ "arguments": [
+ ["const godot_array *", "p_self"],
+ ["const godot_variant *", "p_what"]
+ ]
+ },
+ {
+ "name": "godot_array_has",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_array *", "p_self"],
+ ["const godot_variant *", "p_value"]
+ ]
+ },
+ {
+ "name": "godot_array_hash",
+ "return_type": "godot_int",
+ "arguments": [
+ ["const godot_array *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_array_insert",
+ "return_type": "void",
+ "arguments": [
+ ["godot_array *", "p_self"],
+ ["const godot_int", "p_pos"],
+ ["const godot_variant *", "p_value"]
+ ]
+ },
+ {
+ "name": "godot_array_invert",
+ "return_type": "void",
+ "arguments": [
+ ["godot_array *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_array_pop_back",
+ "return_type": "godot_variant",
+ "arguments": [
+ ["godot_array *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_array_pop_front",
+ "return_type": "godot_variant",
+ "arguments": [
+ ["godot_array *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_array_push_back",
+ "return_type": "void",
+ "arguments": [
+ ["godot_array *", "p_self"],
+ ["const godot_variant *", "p_value"]
+ ]
+ },
+ {
+ "name": "godot_array_push_front",
+ "return_type": "void",
+ "arguments": [
+ ["godot_array *", "p_self"],
+ ["const godot_variant *", "p_value"]
+ ]
+ },
+ {
+ "name": "godot_array_remove",
+ "return_type": "void",
+ "arguments": [
+ ["godot_array *", "p_self"],
+ ["const godot_int", "p_idx"]
+ ]
+ },
+ {
+ "name": "godot_array_resize",
+ "return_type": "void",
+ "arguments": [
+ ["godot_array *", "p_self"],
+ ["const godot_int", "p_size"]
+ ]
+ },
+ {
+ "name": "godot_array_rfind",
+ "return_type": "godot_int",
+ "arguments": [
+ ["const godot_array *", "p_self"],
+ ["const godot_variant *", "p_what"],
+ ["const godot_int", "p_from"]
+ ]
+ },
+ {
+ "name": "godot_array_size",
+ "return_type": "godot_int",
+ "arguments": [
+ ["const godot_array *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_array_sort",
+ "return_type": "void",
+ "arguments": [
+ ["godot_array *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_array_sort_custom",
+ "return_type": "void",
+ "arguments": [
+ ["godot_array *", "p_self"],
+ ["godot_object *", "p_obj"],
+ ["const godot_string *", "p_func"]
+ ]
+ },
+ {
+ "name": "godot_array_bsearch",
+ "return_type": "godot_int",
+ "arguments": [
+ ["godot_array *", "p_self"],
+ ["const godot_variant *", "p_value"],
+ ["const godot_bool", "p_before"]
+ ]
+ },
+ {
+ "name": "godot_array_bsearch_custom",
+ "return_type": "godot_int",
+ "arguments": [
+ ["godot_array *", "p_self"],
+ ["const godot_variant *", "p_value"],
+ ["godot_object *", "p_obj"],
+ ["const godot_string *", "p_func"],
+ ["const godot_bool", "p_before"]
+ ]
+ },
+ {
+ "name": "godot_array_destroy",
+ "return_type": "void",
+ "arguments": [
+ ["godot_array *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_dictionary_new",
+ "return_type": "void",
+ "arguments": [
+ ["godot_dictionary *", "r_dest"]
+ ]
+ },
+ {
+ "name": "godot_dictionary_new_copy",
+ "return_type": "void",
+ "arguments": [
+ ["godot_dictionary *", "r_dest"],
+ ["const godot_dictionary *", "p_src"]
+ ]
+ },
+ {
+ "name": "godot_dictionary_destroy",
+ "return_type": "void",
+ "arguments": [
+ ["godot_dictionary *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_dictionary_size",
+ "return_type": "godot_int",
+ "arguments": [
+ ["const godot_dictionary *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_dictionary_empty",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_dictionary *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_dictionary_clear",
+ "return_type": "void",
+ "arguments": [
+ ["godot_dictionary *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_dictionary_has",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_dictionary *", "p_self"],
+ ["const godot_variant *", "p_key"]
+ ]
+ },
+ {
+ "name": "godot_dictionary_has_all",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_dictionary *", "p_self"],
+ ["const godot_array *", "p_keys"]
+ ]
+ },
+ {
+ "name": "godot_dictionary_erase",
+ "return_type": "void",
+ "arguments": [
+ ["godot_dictionary *", "p_self"],
+ ["const godot_variant *", "p_key"]
+ ]
+ },
+ {
+ "name": "godot_dictionary_hash",
+ "return_type": "godot_int",
+ "arguments": [
+ ["const godot_dictionary *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_dictionary_keys",
+ "return_type": "godot_array",
+ "arguments": [
+ ["const godot_dictionary *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_dictionary_values",
+ "return_type": "godot_array",
+ "arguments": [
+ ["const godot_dictionary *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_dictionary_get",
+ "return_type": "godot_variant",
+ "arguments": [
+ ["const godot_dictionary *", "p_self"],
+ ["const godot_variant *", "p_key"]
+ ]
+ },
+ {
+ "name": "godot_dictionary_set",
+ "return_type": "void",
+ "arguments": [
+ ["godot_dictionary *", "p_self"],
+ ["const godot_variant *", "p_key"],
+ ["const godot_variant *", "p_value"]
+ ]
+ },
+ {
+ "name": "godot_dictionary_operator_index",
+ "return_type": "godot_variant *",
+ "arguments": [
+ ["godot_dictionary *", "p_self"],
+ ["const godot_variant *", "p_key"]
+ ]
+ },
+ {
+ "name": "godot_dictionary_operator_index_const",
+ "return_type": "const godot_variant *",
+ "arguments": [
+ ["const godot_dictionary *", "p_self"],
+ ["const godot_variant *", "p_key"]
+ ]
+ },
+ {
+ "name": "godot_dictionary_next",
+ "return_type": "godot_variant *",
+ "arguments": [
+ ["const godot_dictionary *", "p_self"],
+ ["const godot_variant *", "p_key"]
+ ]
+ },
+ {
+ "name": "godot_dictionary_operator_equal",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_dictionary *", "p_self"],
+ ["const godot_dictionary *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_dictionary_to_json",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_dictionary *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_node_path_new",
+ "return_type": "void",
+ "arguments": [
+ ["godot_node_path *", "r_dest"],
+ ["const godot_string *", "p_from"]
+ ]
+ },
+ {
+ "name": "godot_node_path_new_copy",
+ "return_type": "void",
+ "arguments": [
+ ["godot_node_path *", "r_dest"],
+ ["const godot_node_path *", "p_src"]
+ ]
+ },
+ {
+ "name": "godot_node_path_destroy",
+ "return_type": "void",
+ "arguments": [
+ ["godot_node_path *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_node_path_as_string",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_node_path *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_node_path_is_absolute",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_node_path *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_node_path_get_name_count",
+ "return_type": "godot_int",
+ "arguments": [
+ ["const godot_node_path *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_node_path_get_name",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_node_path *", "p_self"],
+ ["const godot_int", "p_idx"]
+ ]
+ },
+ {
+ "name": "godot_node_path_get_subname_count",
+ "return_type": "godot_int",
+ "arguments": [
+ ["const godot_node_path *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_node_path_get_subname",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_node_path *", "p_self"],
+ ["const godot_int", "p_idx"]
+ ]
+ },
+ {
+ "name": "godot_node_path_get_property",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_node_path *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_node_path_is_empty",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_node_path *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_node_path_operator_equal",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_node_path *", "p_self"],
+ ["const godot_node_path *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_plane_new_with_reals",
+ "return_type": "void",
+ "arguments": [
+ ["godot_plane *", "r_dest"],
+ ["const godot_real", "p_a"],
+ ["const godot_real", "p_b"],
+ ["const godot_real", "p_c"],
+ ["const godot_real", "p_d"]
+ ]
+ },
+ {
+ "name": "godot_plane_new_with_vectors",
+ "return_type": "void",
+ "arguments": [
+ ["godot_plane *", "r_dest"],
+ ["const godot_vector3 *", "p_v1"],
+ ["const godot_vector3 *", "p_v2"],
+ ["const godot_vector3 *", "p_v3"]
+ ]
+ },
+ {
+ "name": "godot_plane_new_with_normal",
+ "return_type": "void",
+ "arguments": [
+ ["godot_plane *", "r_dest"],
+ ["const godot_vector3 *", "p_normal"],
+ ["const godot_real", "p_d"]
+ ]
+ },
+ {
+ "name": "godot_plane_as_string",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_plane *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_plane_normalized",
+ "return_type": "godot_plane",
+ "arguments": [
+ ["const godot_plane *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_plane_center",
+ "return_type": "godot_vector3",
+ "arguments": [
+ ["const godot_plane *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_plane_get_any_point",
+ "return_type": "godot_vector3",
+ "arguments": [
+ ["const godot_plane *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_plane_is_point_over",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_plane *", "p_self"],
+ ["const godot_vector3 *", "p_point"]
+ ]
+ },
+ {
+ "name": "godot_plane_distance_to",
+ "return_type": "godot_real",
+ "arguments": [
+ ["const godot_plane *", "p_self"],
+ ["const godot_vector3 *", "p_point"]
+ ]
+ },
+ {
+ "name": "godot_plane_has_point",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_plane *", "p_self"],
+ ["const godot_vector3 *", "p_point"],
+ ["const godot_real", "p_epsilon"]
+ ]
+ },
+ {
+ "name": "godot_plane_project",
+ "return_type": "godot_vector3",
+ "arguments": [
+ ["const godot_plane *", "p_self"],
+ ["const godot_vector3 *", "p_point"]
+ ]
+ },
+ {
+ "name": "godot_plane_intersect_3",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_plane *", "p_self"],
+ ["godot_vector3 *", "r_dest"],
+ ["const godot_plane *", "p_b"],
+ ["const godot_plane *", "p_c"]
+ ]
+ },
+ {
+ "name": "godot_plane_intersects_ray",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_plane *", "p_self"],
+ ["godot_vector3 *", "r_dest"],
+ ["const godot_vector3 *", "p_from"],
+ ["const godot_vector3 *", "p_dir"]
+ ]
+ },
+ {
+ "name": "godot_plane_intersects_segment",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_plane *", "p_self"],
+ ["godot_vector3 *", "r_dest"],
+ ["const godot_vector3 *", "p_begin"],
+ ["const godot_vector3 *", "p_end"]
+ ]
+ },
+ {
+ "name": "godot_plane_operator_neg",
+ "return_type": "godot_plane",
+ "arguments": [
+ ["const godot_plane *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_plane_operator_equal",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_plane *", "p_self"],
+ ["const godot_plane *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_plane_set_normal",
+ "return_type": "void",
+ "arguments": [
+ ["godot_plane *", "p_self"],
+ ["const godot_vector3 *", "p_normal"]
+ ]
+ },
+ {
+ "name": "godot_plane_get_normal",
+ "return_type": "godot_vector3",
+ "arguments": [
+ ["const godot_plane *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_plane_get_d",
+ "return_type": "godot_real",
+ "arguments": [
+ ["const godot_plane *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_plane_set_d",
+ "return_type": "void",
+ "arguments": [
+ ["godot_plane *", "p_self"],
+ ["const godot_real", "p_d"]
+ ]
+ },
+ {
+ "name": "godot_rect2_new_with_position_and_size",
+ "return_type": "void",
+ "arguments": [
+ ["godot_rect2 *", "r_dest"],
+ ["const godot_vector2 *", "p_pos"],
+ ["const godot_vector2 *", "p_size"]
+ ]
+ },
+ {
+ "name": "godot_rect2_new",
+ "return_type": "void",
+ "arguments": [
+ ["godot_rect2 *", "r_dest"],
+ ["const godot_real", "p_x"],
+ ["const godot_real", "p_y"],
+ ["const godot_real", "p_width"],
+ ["const godot_real", "p_height"]
+ ]
+ },
+ {
+ "name": "godot_rect2_as_string",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_rect2 *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_rect2_get_area",
+ "return_type": "godot_real",
+ "arguments": [
+ ["const godot_rect2 *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_rect2_intersects",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_rect2 *", "p_self"],
+ ["const godot_rect2 *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_rect2_encloses",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_rect2 *", "p_self"],
+ ["const godot_rect2 *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_rect2_has_no_area",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_rect2 *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_rect2_clip",
+ "return_type": "godot_rect2",
+ "arguments": [
+ ["const godot_rect2 *", "p_self"],
+ ["const godot_rect2 *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_rect2_merge",
+ "return_type": "godot_rect2",
+ "arguments": [
+ ["const godot_rect2 *", "p_self"],
+ ["const godot_rect2 *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_rect2_has_point",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_rect2 *", "p_self"],
+ ["const godot_vector2 *", "p_point"]
+ ]
+ },
+ {
+ "name": "godot_rect2_grow",
+ "return_type": "godot_rect2",
+ "arguments": [
+ ["const godot_rect2 *", "p_self"],
+ ["const godot_real", "p_by"]
+ ]
+ },
+ {
+ "name": "godot_rect2_expand",
+ "return_type": "godot_rect2",
+ "arguments": [
+ ["const godot_rect2 *", "p_self"],
+ ["const godot_vector2 *", "p_to"]
+ ]
+ },
+ {
+ "name": "godot_rect2_operator_equal",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_rect2 *", "p_self"],
+ ["const godot_rect2 *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_rect2_get_position",
+ "return_type": "godot_vector2",
+ "arguments": [
+ ["const godot_rect2 *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_rect2_get_size",
+ "return_type": "godot_vector2",
+ "arguments": [
+ ["const godot_rect2 *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_rect2_set_position",
+ "return_type": "void",
+ "arguments": [
+ ["godot_rect2 *", "p_self"],
+ ["const godot_vector2 *", "p_pos"]
+ ]
+ },
+ {
+ "name": "godot_rect2_set_size",
+ "return_type": "void",
+ "arguments": [
+ ["godot_rect2 *", "p_self"],
+ ["const godot_vector2 *", "p_size"]
+ ]
+ },
+ {
+ "name": "godot_aabb_new",
+ "return_type": "void",
+ "arguments": [
+ ["godot_aabb *", "r_dest"],
+ ["const godot_vector3 *", "p_pos"],
+ ["const godot_vector3 *", "p_size"]
+ ]
+ },
+ {
+ "name": "godot_aabb_get_position",
+ "return_type": "godot_vector3",
+ "arguments": [
+ ["const godot_aabb *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_aabb_set_position",
+ "return_type": "void",
+ "arguments": [
+ ["const godot_aabb *", "p_self"],
+ ["const godot_vector3 *", "p_v"]
+ ]
+ },
+ {
+ "name": "godot_aabb_get_size",
+ "return_type": "godot_vector3",
+ "arguments": [
+ ["const godot_aabb *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_aabb_set_size",
+ "return_type": "void",
+ "arguments": [
+ ["const godot_aabb *", "p_self"],
+ ["const godot_vector3 *", "p_v"]
+ ]
+ },
+ {
+ "name": "godot_aabb_as_string",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_aabb *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_aabb_get_area",
+ "return_type": "godot_real",
+ "arguments": [
+ ["const godot_aabb *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_aabb_has_no_area",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_aabb *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_aabb_has_no_surface",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_aabb *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_aabb_intersects",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_aabb *", "p_self"],
+ ["const godot_aabb *", "p_with"]
+ ]
+ },
+ {
+ "name": "godot_aabb_encloses",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_aabb *", "p_self"],
+ ["const godot_aabb *", "p_with"]
+ ]
+ },
+ {
+ "name": "godot_aabb_merge",
+ "return_type": "godot_aabb",
+ "arguments": [
+ ["const godot_aabb *", "p_self"],
+ ["const godot_aabb *", "p_with"]
+ ]
+ },
+ {
+ "name": "godot_aabb_intersection",
+ "return_type": "godot_aabb",
+ "arguments": [
+ ["const godot_aabb *", "p_self"],
+ ["const godot_aabb *", "p_with"]
+ ]
+ },
+ {
+ "name": "godot_aabb_intersects_plane",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_aabb *", "p_self"],
+ ["const godot_plane *", "p_plane"]
+ ]
+ },
+ {
+ "name": "godot_aabb_intersects_segment",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_aabb *", "p_self"],
+ ["const godot_vector3 *", "p_from"],
+ ["const godot_vector3 *", "p_to"]
+ ]
+ },
+ {
+ "name": "godot_aabb_has_point",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_aabb *", "p_self"],
+ ["const godot_vector3 *", "p_point"]
+ ]
+ },
+ {
+ "name": "godot_aabb_get_support",
+ "return_type": "godot_vector3",
+ "arguments": [
+ ["const godot_aabb *", "p_self"],
+ ["const godot_vector3 *", "p_dir"]
+ ]
+ },
+ {
+ "name": "godot_aabb_get_longest_axis",
+ "return_type": "godot_vector3",
+ "arguments": [
+ ["const godot_aabb *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_aabb_get_longest_axis_index",
+ "return_type": "godot_int",
+ "arguments": [
+ ["const godot_aabb *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_aabb_get_longest_axis_size",
+ "return_type": "godot_real",
+ "arguments": [
+ ["const godot_aabb *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_aabb_get_shortest_axis",
+ "return_type": "godot_vector3",
+ "arguments": [
+ ["const godot_aabb *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_aabb_get_shortest_axis_index",
+ "return_type": "godot_int",
+ "arguments": [
+ ["const godot_aabb *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_aabb_get_shortest_axis_size",
+ "return_type": "godot_real",
+ "arguments": [
+ ["const godot_aabb *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_aabb_expand",
+ "return_type": "godot_aabb",
+ "arguments": [
+ ["const godot_aabb *", "p_self"],
+ ["const godot_vector3 *", "p_to_point"]
+ ]
+ },
+ {
+ "name": "godot_aabb_grow",
+ "return_type": "godot_aabb",
+ "arguments": [
+ ["const godot_aabb *", "p_self"],
+ ["const godot_real", "p_by"]
+ ]
+ },
+ {
+ "name": "godot_aabb_get_endpoint",
+ "return_type": "godot_vector3",
+ "arguments": [
+ ["const godot_aabb *", "p_self"],
+ ["const godot_int", "p_idx"]
+ ]
+ },
+ {
+ "name": "godot_aabb_operator_equal",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_aabb *", "p_self"],
+ ["const godot_aabb *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_rid_new",
+ "return_type": "void",
+ "arguments": [
+ ["godot_rid *", "r_dest"]
+ ]
+ },
+ {
+ "name": "godot_rid_get_id",
+ "return_type": "godot_int",
+ "arguments": [
+ ["const godot_rid *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_rid_new_with_resource",
+ "return_type": "void",
+ "arguments": [
+ ["godot_rid *", "r_dest"],
+ ["const godot_object *", "p_from"]
+ ]
+ },
+ {
+ "name": "godot_rid_operator_equal",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_rid *", "p_self"],
+ ["const godot_rid *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_rid_operator_less",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_rid *", "p_self"],
+ ["const godot_rid *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_transform_new_with_axis_origin",
+ "return_type": "void",
+ "arguments": [
+ ["godot_transform *", "r_dest"],
+ ["const godot_vector3 *", "p_x_axis"],
+ ["const godot_vector3 *", "p_y_axis"],
+ ["const godot_vector3 *", "p_z_axis"],
+ ["const godot_vector3 *", "p_origin"]
+ ]
+ },
+ {
+ "name": "godot_transform_new",
+ "return_type": "void",
+ "arguments": [
+ ["godot_transform *", "r_dest"],
+ ["const godot_basis *", "p_basis"],
+ ["const godot_vector3 *", "p_origin"]
+ ]
+ },
+ {
+ "name": "godot_transform_get_basis",
+ "return_type": "godot_basis",
+ "arguments": [
+ ["const godot_transform *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_transform_set_basis",
+ "return_type": "void",
+ "arguments": [
+ ["godot_transform *", "p_self"],
+ ["godot_basis *", "p_v"]
+ ]
+ },
+ {
+ "name": "godot_transform_get_origin",
+ "return_type": "godot_vector3",
+ "arguments": [
+ ["const godot_transform *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_transform_set_origin",
+ "return_type": "void",
+ "arguments": [
+ ["godot_transform *", "p_self"],
+ ["godot_vector3 *", "p_v"]
+ ]
+ },
+ {
+ "name": "godot_transform_as_string",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_transform *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_transform_inverse",
+ "return_type": "godot_transform",
+ "arguments": [
+ ["const godot_transform *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_transform_affine_inverse",
+ "return_type": "godot_transform",
+ "arguments": [
+ ["const godot_transform *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_transform_orthonormalized",
+ "return_type": "godot_transform",
+ "arguments": [
+ ["const godot_transform *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_transform_rotated",
+ "return_type": "godot_transform",
+ "arguments": [
+ ["const godot_transform *", "p_self"],
+ ["const godot_vector3 *", "p_axis"],
+ ["const godot_real", "p_phi"]
+ ]
+ },
+ {
+ "name": "godot_transform_scaled",
+ "return_type": "godot_transform",
+ "arguments": [
+ ["const godot_transform *", "p_self"],
+ ["const godot_vector3 *", "p_scale"]
+ ]
+ },
+ {
+ "name": "godot_transform_translated",
+ "return_type": "godot_transform",
+ "arguments": [
+ ["const godot_transform *", "p_self"],
+ ["const godot_vector3 *", "p_ofs"]
+ ]
+ },
+ {
+ "name": "godot_transform_looking_at",
+ "return_type": "godot_transform",
+ "arguments": [
+ ["const godot_transform *", "p_self"],
+ ["const godot_vector3 *", "p_target"],
+ ["const godot_vector3 *", "p_up"]
+ ]
+ },
+ {
+ "name": "godot_transform_xform_plane",
+ "return_type": "godot_plane",
+ "arguments": [
+ ["const godot_transform *", "p_self"],
+ ["const godot_plane *", "p_v"]
+ ]
+ },
+ {
+ "name": "godot_transform_xform_inv_plane",
+ "return_type": "godot_plane",
+ "arguments": [
+ ["const godot_transform *", "p_self"],
+ ["const godot_plane *", "p_v"]
+ ]
+ },
+ {
+ "name": "godot_transform_new_identity",
+ "return_type": "void",
+ "arguments": [
+ ["godot_transform *", "r_dest"]
+ ]
+ },
+ {
+ "name": "godot_transform_operator_equal",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_transform *", "p_self"],
+ ["const godot_transform *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_transform_operator_multiply",
+ "return_type": "godot_transform",
+ "arguments": [
+ ["const godot_transform *", "p_self"],
+ ["const godot_transform *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_transform_xform_vector3",
+ "return_type": "godot_vector3",
+ "arguments": [
+ ["const godot_transform *", "p_self"],
+ ["const godot_vector3 *", "p_v"]
+ ]
+ },
+ {
+ "name": "godot_transform_xform_inv_vector3",
+ "return_type": "godot_vector3",
+ "arguments": [
+ ["const godot_transform *", "p_self"],
+ ["const godot_vector3 *", "p_v"]
+ ]
+ },
+ {
+ "name": "godot_transform_xform_aabb",
+ "return_type": "godot_aabb",
+ "arguments": [
+ ["const godot_transform *", "p_self"],
+ ["const godot_aabb *", "p_v"]
+ ]
+ },
+ {
+ "name": "godot_transform_xform_inv_aabb",
+ "return_type": "godot_aabb",
+ "arguments": [
+ ["const godot_transform *", "p_self"],
+ ["const godot_aabb *", "p_v"]
+ ]
+ },
+ {
+ "name": "godot_transform2d_new",
+ "return_type": "void",
+ "arguments": [
+ ["godot_transform2d *", "r_dest"],
+ ["const godot_real", "p_rot"],
+ ["const godot_vector2 *", "p_pos"]
+ ]
+ },
+ {
+ "name": "godot_transform2d_new_axis_origin",
+ "return_type": "void",
+ "arguments": [
+ ["godot_transform2d *", "r_dest"],
+ ["const godot_vector2 *", "p_x_axis"],
+ ["const godot_vector2 *", "p_y_axis"],
+ ["const godot_vector2 *", "p_origin"]
+ ]
+ },
+ {
+ "name": "godot_transform2d_as_string",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_transform2d *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_transform2d_inverse",
+ "return_type": "godot_transform2d",
+ "arguments": [
+ ["const godot_transform2d *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_transform2d_affine_inverse",
+ "return_type": "godot_transform2d",
+ "arguments": [
+ ["const godot_transform2d *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_transform2d_get_rotation",
+ "return_type": "godot_real",
+ "arguments": [
+ ["const godot_transform2d *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_transform2d_get_origin",
+ "return_type": "godot_vector2",
+ "arguments": [
+ ["const godot_transform2d *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_transform2d_get_scale",
+ "return_type": "godot_vector2",
+ "arguments": [
+ ["const godot_transform2d *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_transform2d_orthonormalized",
+ "return_type": "godot_transform2d",
+ "arguments": [
+ ["const godot_transform2d *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_transform2d_rotated",
+ "return_type": "godot_transform2d",
+ "arguments": [
+ ["const godot_transform2d *", "p_self"],
+ ["const godot_real", "p_phi"]
+ ]
+ },
+ {
+ "name": "godot_transform2d_scaled",
+ "return_type": "godot_transform2d",
+ "arguments": [
+ ["const godot_transform2d *", "p_self"],
+ ["const godot_vector2 *", "p_scale"]
+ ]
+ },
+ {
+ "name": "godot_transform2d_translated",
+ "return_type": "godot_transform2d",
+ "arguments": [
+ ["const godot_transform2d *", "p_self"],
+ ["const godot_vector2 *", "p_offset"]
+ ]
+ },
+ {
+ "name": "godot_transform2d_xform_vector2",
+ "return_type": "godot_vector2",
+ "arguments": [
+ ["const godot_transform2d *", "p_self"],
+ ["const godot_vector2 *", "p_v"]
+ ]
+ },
+ {
+ "name": "godot_transform2d_xform_inv_vector2",
+ "return_type": "godot_vector2",
+ "arguments": [
+ ["const godot_transform2d *", "p_self"],
+ ["const godot_vector2 *", "p_v"]
+ ]
+ },
+ {
+ "name": "godot_transform2d_basis_xform_vector2",
+ "return_type": "godot_vector2",
+ "arguments": [
+ ["const godot_transform2d *", "p_self"],
+ ["const godot_vector2 *", "p_v"]
+ ]
+ },
+ {
+ "name": "godot_transform2d_basis_xform_inv_vector2",
+ "return_type": "godot_vector2",
+ "arguments": [
+ ["const godot_transform2d *", "p_self"],
+ ["const godot_vector2 *", "p_v"]
+ ]
+ },
+ {
+ "name": "godot_transform2d_interpolate_with",
+ "return_type": "godot_transform2d",
+ "arguments": [
+ ["const godot_transform2d *", "p_self"],
+ ["const godot_transform2d *", "p_m"],
+ ["const godot_real", "p_c"]
+ ]
+ },
+ {
+ "name": "godot_transform2d_operator_equal",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_transform2d *", "p_self"],
+ ["const godot_transform2d *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_transform2d_operator_multiply",
+ "return_type": "godot_transform2d",
+ "arguments": [
+ ["const godot_transform2d *", "p_self"],
+ ["const godot_transform2d *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_transform2d_new_identity",
+ "return_type": "void",
+ "arguments": [
+ ["godot_transform2d *", "r_dest"]
+ ]
+ },
+ {
+ "name": "godot_transform2d_xform_rect2",
+ "return_type": "godot_rect2",
+ "arguments": [
+ ["const godot_transform2d *", "p_self"],
+ ["const godot_rect2 *", "p_v"]
+ ]
+ },
+ {
+ "name": "godot_transform2d_xform_inv_rect2",
+ "return_type": "godot_rect2",
+ "arguments": [
+ ["const godot_transform2d *", "p_self"],
+ ["const godot_rect2 *", "p_v"]
+ ]
+ },
+ {
+ "name": "godot_variant_get_type",
+ "return_type": "godot_variant_type",
+ "arguments": [
+ ["const godot_variant *", "p_v"]
+ ]
+ },
+ {
+ "name": "godot_variant_new_copy",
+ "return_type": "void",
+ "arguments": [
+ ["godot_variant *", "r_dest"],
+ ["const godot_variant *", "p_src"]
+ ]
+ },
+ {
+ "name": "godot_variant_new_nil",
+ "return_type": "void",
+ "arguments": [
+ ["godot_variant *", "r_dest"]
+ ]
+ },
+ {
+ "name": "godot_variant_new_bool",
+ "return_type": "void",
+ "arguments": [
+ ["godot_variant *", "p_v"],
+ ["const godot_bool", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_variant_new_uint",
+ "return_type": "void",
+ "arguments": [
+ ["godot_variant *", "r_dest"],
+ ["const uint64_t", "p_i"]
+ ]
+ },
+ {
+ "name": "godot_variant_new_int",
+ "return_type": "void",
+ "arguments": [
+ ["godot_variant *", "r_dest"],
+ ["const int64_t", "p_i"]
+ ]
+ },
+ {
+ "name": "godot_variant_new_real",
+ "return_type": "void",
+ "arguments": [
+ ["godot_variant *", "r_dest"],
+ ["const double", "p_r"]
+ ]
+ },
+ {
+ "name": "godot_variant_new_string",
+ "return_type": "void",
+ "arguments": [
+ ["godot_variant *", "r_dest"],
+ ["const godot_string *", "p_s"]
+ ]
+ },
+ {
+ "name": "godot_variant_new_vector2",
+ "return_type": "void",
+ "arguments": [
+ ["godot_variant *", "r_dest"],
+ ["const godot_vector2 *", "p_v2"]
+ ]
+ },
+ {
+ "name": "godot_variant_new_rect2",
+ "return_type": "void",
+ "arguments": [
+ ["godot_variant *", "r_dest"],
+ ["const godot_rect2 *", "p_rect2"]
+ ]
+ },
+ {
+ "name": "godot_variant_new_vector3",
+ "return_type": "void",
+ "arguments": [
+ ["godot_variant *", "r_dest"],
+ ["const godot_vector3 *", "p_v3"]
+ ]
+ },
+ {
+ "name": "godot_variant_new_transform2d",
+ "return_type": "void",
+ "arguments": [
+ ["godot_variant *", "r_dest"],
+ ["const godot_transform2d *", "p_t2d"]
+ ]
+ },
+ {
+ "name": "godot_variant_new_plane",
+ "return_type": "void",
+ "arguments": [
+ ["godot_variant *", "r_dest"],
+ ["const godot_plane *", "p_plane"]
+ ]
+ },
+ {
+ "name": "godot_variant_new_quat",
+ "return_type": "void",
+ "arguments": [
+ ["godot_variant *", "r_dest"],
+ ["const godot_quat *", "p_quat"]
+ ]
+ },
+ {
+ "name": "godot_variant_new_aabb",
+ "return_type": "void",
+ "arguments": [
+ ["godot_variant *", "r_dest"],
+ ["const godot_aabb *", "p_aabb"]
+ ]
+ },
+ {
+ "name": "godot_variant_new_basis",
+ "return_type": "void",
+ "arguments": [
+ ["godot_variant *", "r_dest"],
+ ["const godot_basis *", "p_basis"]
+ ]
+ },
+ {
+ "name": "godot_variant_new_transform",
+ "return_type": "void",
+ "arguments": [
+ ["godot_variant *", "r_dest"],
+ ["const godot_transform *", "p_trans"]
+ ]
+ },
+ {
+ "name": "godot_variant_new_color",
+ "return_type": "void",
+ "arguments": [
+ ["godot_variant *", "r_dest"],
+ ["const godot_color *", "p_color"]
+ ]
+ },
+ {
+ "name": "godot_variant_new_node_path",
+ "return_type": "void",
+ "arguments": [
+ ["godot_variant *", "r_dest"],
+ ["const godot_node_path *", "p_np"]
+ ]
+ },
+ {
+ "name": "godot_variant_new_rid",
+ "return_type": "void",
+ "arguments": [
+ ["godot_variant *", "r_dest"],
+ ["const godot_rid *", "p_rid"]
+ ]
+ },
+ {
+ "name": "godot_variant_new_object",
+ "return_type": "void",
+ "arguments": [
+ ["godot_variant *", "r_dest"],
+ ["const godot_object *", "p_obj"]
+ ]
+ },
+ {
+ "name": "godot_variant_new_dictionary",
+ "return_type": "void",
+ "arguments": [
+ ["godot_variant *", "r_dest"],
+ ["const godot_dictionary *", "p_dict"]
+ ]
+ },
+ {
+ "name": "godot_variant_new_array",
+ "return_type": "void",
+ "arguments": [
+ ["godot_variant *", "r_dest"],
+ ["const godot_array *", "p_arr"]
+ ]
+ },
+ {
+ "name": "godot_variant_new_pool_byte_array",
+ "return_type": "void",
+ "arguments": [
+ ["godot_variant *", "r_dest"],
+ ["const godot_pool_byte_array *", "p_pba"]
+ ]
+ },
+ {
+ "name": "godot_variant_new_pool_int_array",
+ "return_type": "void",
+ "arguments": [
+ ["godot_variant *", "r_dest"],
+ ["const godot_pool_int_array *", "p_pia"]
+ ]
+ },
+ {
+ "name": "godot_variant_new_pool_real_array",
+ "return_type": "void",
+ "arguments": [
+ ["godot_variant *", "r_dest"],
+ ["const godot_pool_real_array *", "p_pra"]
+ ]
+ },
+ {
+ "name": "godot_variant_new_pool_string_array",
+ "return_type": "void",
+ "arguments": [
+ ["godot_variant *", "r_dest"],
+ ["const godot_pool_string_array *", "p_psa"]
+ ]
+ },
+ {
+ "name": "godot_variant_new_pool_vector2_array",
+ "return_type": "void",
+ "arguments": [
+ ["godot_variant *", "r_dest"],
+ ["const godot_pool_vector2_array *", "p_pv2a"]
+ ]
+ },
+ {
+ "name": "godot_variant_new_pool_vector3_array",
+ "return_type": "void",
+ "arguments": [
+ ["godot_variant *", "r_dest"],
+ ["const godot_pool_vector3_array *", "p_pv3a"]
+ ]
+ },
+ {
+ "name": "godot_variant_new_pool_color_array",
+ "return_type": "void",
+ "arguments": [
+ ["godot_variant *", "r_dest"],
+ ["const godot_pool_color_array *", "p_pca"]
+ ]
+ },
+ {
+ "name": "godot_variant_as_bool",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_variant *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_variant_as_uint",
+ "return_type": "uint64_t",
+ "arguments": [
+ ["const godot_variant *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_variant_as_int",
+ "return_type": "int64_t",
+ "arguments": [
+ ["const godot_variant *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_variant_as_real",
+ "return_type": "double",
+ "arguments": [
+ ["const godot_variant *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_variant_as_string",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_variant *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_variant_as_vector2",
+ "return_type": "godot_vector2",
+ "arguments": [
+ ["const godot_variant *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_variant_as_rect2",
+ "return_type": "godot_rect2",
+ "arguments": [
+ ["const godot_variant *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_variant_as_vector3",
+ "return_type": "godot_vector3",
+ "arguments": [
+ ["const godot_variant *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_variant_as_transform2d",
+ "return_type": "godot_transform2d",
+ "arguments": [
+ ["const godot_variant *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_variant_as_plane",
+ "return_type": "godot_plane",
+ "arguments": [
+ ["const godot_variant *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_variant_as_quat",
+ "return_type": "godot_quat",
+ "arguments": [
+ ["const godot_variant *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_variant_as_aabb",
+ "return_type": "godot_aabb",
+ "arguments": [
+ ["const godot_variant *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_variant_as_basis",
+ "return_type": "godot_basis",
+ "arguments": [
+ ["const godot_variant *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_variant_as_transform",
+ "return_type": "godot_transform",
+ "arguments": [
+ ["const godot_variant *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_variant_as_color",
+ "return_type": "godot_color",
+ "arguments": [
+ ["const godot_variant *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_variant_as_node_path",
+ "return_type": "godot_node_path",
+ "arguments": [
+ ["const godot_variant *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_variant_as_rid",
+ "return_type": "godot_rid",
+ "arguments": [
+ ["const godot_variant *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_variant_as_object",
+ "return_type": "godot_object *",
+ "arguments": [
+ ["const godot_variant *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_variant_as_dictionary",
+ "return_type": "godot_dictionary",
+ "arguments": [
+ ["const godot_variant *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_variant_as_array",
+ "return_type": "godot_array",
+ "arguments": [
+ ["const godot_variant *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_variant_as_pool_byte_array",
+ "return_type": "godot_pool_byte_array",
+ "arguments": [
+ ["const godot_variant *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_variant_as_pool_int_array",
+ "return_type": "godot_pool_int_array",
+ "arguments": [
+ ["const godot_variant *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_variant_as_pool_real_array",
+ "return_type": "godot_pool_real_array",
+ "arguments": [
+ ["const godot_variant *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_variant_as_pool_string_array",
+ "return_type": "godot_pool_string_array",
+ "arguments": [
+ ["const godot_variant *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_variant_as_pool_vector2_array",
+ "return_type": "godot_pool_vector2_array",
+ "arguments": [
+ ["const godot_variant *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_variant_as_pool_vector3_array",
+ "return_type": "godot_pool_vector3_array",
+ "arguments": [
+ ["const godot_variant *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_variant_as_pool_color_array",
+ "return_type": "godot_pool_color_array",
+ "arguments": [
+ ["const godot_variant *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_variant_call",
+ "return_type": "godot_variant",
+ "arguments": [
+ ["godot_variant *", "p_self"],
+ ["const godot_string *", "p_method"],
+ ["const godot_variant **", "p_args"],
+ ["const godot_int", "p_argcount"],
+ ["godot_variant_call_error *", "r_error"]
+ ]
+ },
+ {
+ "name": "godot_variant_has_method",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_variant *", "p_self"],
+ ["const godot_string *", "p_method"]
+ ]
+ },
+ {
+ "name": "godot_variant_operator_equal",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_variant *", "p_self"],
+ ["const godot_variant *", "p_other"]
+ ]
+ },
+ {
+ "name": "godot_variant_operator_less",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_variant *", "p_self"],
+ ["const godot_variant *", "p_other"]
+ ]
+ },
+ {
+ "name": "godot_variant_hash_compare",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_variant *", "p_self"],
+ ["const godot_variant *", "p_other"]
+ ]
+ },
+ {
+ "name": "godot_variant_booleanize",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_variant *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_variant_destroy",
+ "return_type": "void",
+ "arguments": [
+ ["godot_variant *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_string_new",
+ "return_type": "void",
+ "arguments": [
+ ["godot_string *", "r_dest"]
+ ]
+ },
+ {
+ "name": "godot_string_new_copy",
+ "return_type": "void",
+ "arguments": [
+ ["godot_string *", "r_dest"],
+ ["const godot_string *", "p_src"]
+ ]
+ },
+ {
+ "name": "godot_string_new_data",
+ "return_type": "void",
+ "arguments": [
+ ["godot_string *", "r_dest"],
+ ["const char *", "p_contents"],
+ ["const int", "p_size"]
+ ]
+ },
+ {
+ "name": "godot_string_new_unicode_data",
+ "return_type": "void",
+ "arguments": [
+ ["godot_string *", "r_dest"],
+ ["const wchar_t *", "p_contents"],
+ ["const int", "p_size"]
+ ]
+ },
+ {
+ "name": "godot_string_get_data",
+ "return_type": "void",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["char *", "p_dest"],
+ ["int *", "p_size"]
+ ]
+ },
+ {
+ "name": "godot_string_operator_index",
+ "return_type": "wchar_t *",
+ "arguments": [
+ ["godot_string *", "p_self"],
+ ["const godot_int", "p_idx"]
+ ]
+ },
+ {
+ "name": "godot_string_operator_index_const",
+ "return_type": "wchar_t",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["const godot_int", "p_idx"]
+ ]
+ },
+ {
+ "name": "godot_string_unicode_str",
+ "return_type": "const wchar_t *",
+ "arguments": [
+ ["const godot_string *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_string_operator_equal",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["const godot_string *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_string_operator_less",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["const godot_string *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_string_operator_plus",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["const godot_string *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_string_length",
+ "return_type": "godot_int",
+ "arguments": [
+ ["const godot_string *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_string_begins_with",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["const godot_string *", "p_string"]
+ ]
+ },
+ {
+ "name": "godot_string_begins_with_char_array",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["const char *", "p_char_array"]
+ ]
+ },
+ {
+ "name": "godot_string_bigrams",
+ "return_type": "godot_array",
+ "arguments": [
+ ["const godot_string *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_string_chr",
+ "return_type": "godot_string",
+ "arguments": [
+ ["wchar_t", "p_character"]
+ ]
+ },
+ {
+ "name": "godot_string_ends_with",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["const godot_string *", "p_string"]
+ ]
+ },
+ {
+ "name": "godot_string_find",
+ "return_type": "godot_int",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["godot_string", "p_what"]
+ ]
+ },
+ {
+ "name": "godot_string_find_from",
+ "return_type": "godot_int",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["godot_string", "p_what"],
+ ["godot_int", "p_from"]
+ ]
+ },
+ {
+ "name": "godot_string_findmk",
+ "return_type": "godot_int",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["const godot_array *", "p_keys"]
+ ]
+ },
+ {
+ "name": "godot_string_findmk_from",
+ "return_type": "godot_int",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["const godot_array *", "p_keys"],
+ ["godot_int", "p_from"]
+ ]
+ },
+ {
+ "name": "godot_string_findmk_from_in_place",
+ "return_type": "godot_int",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["const godot_array *", "p_keys"],
+ ["godot_int", "p_from"],
+ ["godot_int *", "r_key"]
+ ]
+ },
+ {
+ "name": "godot_string_findn",
+ "return_type": "godot_int",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["godot_string", "p_what"]
+ ]
+ },
+ {
+ "name": "godot_string_findn_from",
+ "return_type": "godot_int",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["godot_string", "p_what"],
+ ["godot_int", "p_from"]
+ ]
+ },
+ {
+ "name": "godot_string_find_last",
+ "return_type": "godot_int",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["godot_string", "p_what"]
+ ]
+ },
+ {
+ "name": "godot_string_format",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["const godot_variant *", "p_values"]
+ ]
+ },
+ {
+ "name": "godot_string_format_with_custom_placeholder",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["const godot_variant *", "p_values"],
+ ["const char *", "p_placeholder"]
+ ]
+ },
+ {
+ "name": "godot_string_hex_encode_buffer",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const uint8_t *", "p_buffer"],
+ ["godot_int", "p_len"]
+ ]
+ },
+ {
+ "name": "godot_string_hex_to_int",
+ "return_type": "godot_int",
+ "arguments": [
+ ["const godot_string *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_string_hex_to_int_without_prefix",
+ "return_type": "godot_int",
+ "arguments": [
+ ["const godot_string *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_string_insert",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["godot_int", "p_at_pos"],
+ ["godot_string", "p_string"]
+ ]
+ },
+ {
+ "name": "godot_string_is_numeric",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_string *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_string_is_subsequence_of",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["const godot_string *", "p_string"]
+ ]
+ },
+ {
+ "name": "godot_string_is_subsequence_ofi",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["const godot_string *", "p_string"]
+ ]
+ },
+ {
+ "name": "godot_string_lpad",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["godot_int", "p_min_length"]
+ ]
+ },
+ {
+ "name": "godot_string_lpad_with_custom_character",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["godot_int", "p_min_length"],
+ ["const godot_string *", "p_character"]
+ ]
+ },
+ {
+ "name": "godot_string_match",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["const godot_string *", "p_wildcard"]
+ ]
+ },
+ {
+ "name": "godot_string_matchn",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["const godot_string *", "p_wildcard"]
+ ]
+ },
+ {
+ "name": "godot_string_md5",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const uint8_t *", "p_md5"]
+ ]
+ },
+ {
+ "name": "godot_string_num",
+ "return_type": "godot_string",
+ "arguments": [
+ ["double", "p_num"]
+ ]
+ },
+ {
+ "name": "godot_string_num_int64",
+ "return_type": "godot_string",
+ "arguments": [
+ ["int64_t", "p_num"],
+ ["godot_int", "p_base"]
+ ]
+ },
+ {
+ "name": "godot_string_num_int64_capitalized",
+ "return_type": "godot_string",
+ "arguments": [
+ ["int64_t", "p_num"],
+ ["godot_int", "p_base"],
+ ["godot_bool", "p_capitalize_hex"]
+ ]
+ },
+ {
+ "name": "godot_string_num_real",
+ "return_type": "godot_string",
+ "arguments": [
+ ["double", "p_num"]
+ ]
+ },
+ {
+ "name": "godot_string_num_scientific",
+ "return_type": "godot_string",
+ "arguments": [
+ ["double", "p_num"]
+ ]
+ },
+ {
+ "name": "godot_string_num_with_decimals",
+ "return_type": "godot_string",
+ "arguments": [
+ ["double", "p_num"],
+ ["godot_int", "p_decimals"]
+ ]
+ },
+ {
+ "name": "godot_string_pad_decimals",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["godot_int", "p_digits"]
+ ]
+ },
+ {
+ "name": "godot_string_pad_zeros",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["godot_int", "p_digits"]
+ ]
+ },
+ {
+ "name": "godot_string_replace_first",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["godot_string", "p_key"],
+ ["godot_string", "p_with"]
+ ]
+ },
+ {
+ "name": "godot_string_replace",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["godot_string", "p_key"],
+ ["godot_string", "p_with"]
+ ]
+ },
+ {
+ "name": "godot_string_replacen",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["godot_string", "p_key"],
+ ["godot_string", "p_with"]
+ ]
+ },
+ {
+ "name": "godot_string_rfind",
+ "return_type": "godot_int",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["godot_string", "p_what"]
+ ]
+ },
+ {
+ "name": "godot_string_rfindn",
+ "return_type": "godot_int",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["godot_string", "p_what"]
+ ]
+ },
+ {
+ "name": "godot_string_rfind_from",
+ "return_type": "godot_int",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["godot_string", "p_what"],
+ ["godot_int", "p_from"]
+ ]
+ },
+ {
+ "name": "godot_string_rfindn_from",
+ "return_type": "godot_int",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["godot_string", "p_what"],
+ ["godot_int", "p_from"]
+ ]
+ },
+ {
+ "name": "godot_string_rpad",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["godot_int", "p_min_length"]
+ ]
+ },
+ {
+ "name": "godot_string_rpad_with_custom_character",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["godot_int", "p_min_length"],
+ ["const godot_string *", "p_character"]
+ ]
+ },
+ {
+ "name": "godot_string_similarity",
+ "return_type": "godot_real",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["const godot_string *", "p_string"]
+ ]
+ },
+ {
+ "name": "godot_string_sprintf",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["const godot_array *", "p_values"],
+ ["godot_bool *", "p_error"]
+ ]
+ },
+ {
+ "name": "godot_string_substr",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["godot_int", "p_from"],
+ ["godot_int", "p_chars"]
+ ]
+ },
+ {
+ "name": "godot_string_to_double",
+ "return_type": "double",
+ "arguments": [
+ ["const godot_string *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_string_to_float",
+ "return_type": "godot_real",
+ "arguments": [
+ ["const godot_string *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_string_to_int",
+ "return_type": "godot_int",
+ "arguments": [
+ ["const godot_string *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_string_camelcase_to_underscore",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_string *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_string_camelcase_to_underscore_lowercased",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_string *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_string_capitalize",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_string *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_string_char_to_double",
+ "return_type": "double",
+ "arguments": [
+ ["const char *", "p_what"]
+ ]
+ },
+ {
+ "name": "godot_string_char_to_int",
+ "return_type": "godot_int",
+ "arguments": [
+ ["const char *", "p_what"]
+ ]
+ },
+ {
+ "name": "godot_string_wchar_to_int",
+ "return_type": "int64_t",
+ "arguments": [
+ ["const wchar_t *", "p_str"]
+ ]
+ },
+ {
+ "name": "godot_string_char_to_int_with_len",
+ "return_type": "godot_int",
+ "arguments": [
+ ["const char *", "p_what"],
+ ["godot_int", "p_len"]
+ ]
+ },
+ {
+ "name": "godot_string_char_to_int64_with_len",
+ "return_type": "int64_t",
+ "arguments": [
+ ["const wchar_t *", "p_str"],
+ ["int", "p_len"]
+ ]
+ },
+ {
+ "name": "godot_string_hex_to_int64",
+ "return_type": "int64_t",
+ "arguments": [
+ ["const godot_string *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_string_hex_to_int64_with_prefix",
+ "return_type": "int64_t",
+ "arguments": [
+ ["const godot_string *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_string_to_int64",
+ "return_type": "int64_t",
+ "arguments": [
+ ["const godot_string *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_string_unicode_char_to_double",
+ "return_type": "double",
+ "arguments": [
+ ["const wchar_t *", "p_str"],
+ ["const wchar_t **", "r_end"]
+ ]
+ },
+ {
+ "name": "godot_string_get_slice_count",
+ "return_type": "godot_int",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["godot_string", "p_splitter"]
+ ]
+ },
+ {
+ "name": "godot_string_get_slice",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["godot_string", "p_splitter"],
+ ["godot_int", "p_slice"]
+ ]
+ },
+ {
+ "name": "godot_string_get_slicec",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["wchar_t", "p_splitter"],
+ ["godot_int", "p_slice"]
+ ]
+ },
+ {
+ "name": "godot_string_split",
+ "return_type": "godot_array",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["const godot_string *", "p_splitter"]
+ ]
+ },
+ {
+ "name": "godot_string_split_allow_empty",
+ "return_type": "godot_array",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["const godot_string *", "p_splitter"]
+ ]
+ },
+ {
+ "name": "godot_string_split_floats",
+ "return_type": "godot_array",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["const godot_string *", "p_splitter"]
+ ]
+ },
+ {
+ "name": "godot_string_split_floats_allows_empty",
+ "return_type": "godot_array",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["const godot_string *", "p_splitter"]
+ ]
+ },
+ {
+ "name": "godot_string_split_floats_mk",
+ "return_type": "godot_array",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["const godot_array *", "p_splitters"]
+ ]
+ },
+ {
+ "name": "godot_string_split_floats_mk_allows_empty",
+ "return_type": "godot_array",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["const godot_array *", "p_splitters"]
+ ]
+ },
+ {
+ "name": "godot_string_split_ints",
+ "return_type": "godot_array",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["const godot_string *", "p_splitter"]
+ ]
+ },
+ {
+ "name": "godot_string_split_ints_allows_empty",
+ "return_type": "godot_array",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["const godot_string *", "p_splitter"]
+ ]
+ },
+ {
+ "name": "godot_string_split_ints_mk",
+ "return_type": "godot_array",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["const godot_array *", "p_splitters"]
+ ]
+ },
+ {
+ "name": "godot_string_split_ints_mk_allows_empty",
+ "return_type": "godot_array",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["const godot_array *", "p_splitters"]
+ ]
+ },
+ {
+ "name": "godot_string_split_spaces",
+ "return_type": "godot_array",
+ "arguments": [
+ ["const godot_string *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_string_char_lowercase",
+ "return_type": "wchar_t",
+ "arguments": [
+ ["wchar_t", "p_char"]
+ ]
+ },
+ {
+ "name": "godot_string_char_uppercase",
+ "return_type": "wchar_t",
+ "arguments": [
+ ["wchar_t", "p_char"]
+ ]
+ },
+ {
+ "name": "godot_string_to_lower",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_string *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_string_to_upper",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_string *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_string_get_basename",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_string *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_string_get_extension",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_string *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_string_left",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["godot_int", "p_pos"]
+ ]
+ },
+ {
+ "name": "godot_string_ord_at",
+ "return_type": "wchar_t",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["godot_int", "p_idx"]
+ ]
+ },
+ {
+ "name": "godot_string_plus_file",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["const godot_string *", "p_file"]
+ ]
+ },
+ {
+ "name": "godot_string_right",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["godot_int", "p_pos"]
+ ]
+ },
+ {
+ "name": "godot_string_strip_edges",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["godot_bool", "p_left"],
+ ["godot_bool", "p_right"]
+ ]
+ },
+ {
+ "name": "godot_string_strip_escapes",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_string *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_string_erase",
+ "return_type": "void",
+ "arguments": [
+ ["godot_string *", "p_self"],
+ ["godot_int", "p_pos"],
+ ["godot_int", "p_chars"]
+ ]
+ },
+ {
+ "name": "godot_string_ascii",
+ "return_type": "void",
+ "arguments": [
+ ["godot_string *", "p_self"],
+ ["char *", "result"]
+ ]
+ },
+ {
+ "name": "godot_string_ascii_extended",
+ "return_type": "void",
+ "arguments": [
+ ["godot_string *", "p_self"],
+ ["char *", "result"]
+ ]
+ },
+ {
+ "name": "godot_string_utf8",
+ "return_type": "void",
+ "arguments": [
+ ["godot_string *", "p_self"],
+ ["char *", "result"]
+ ]
+ },
+ {
+ "name": "godot_string_parse_utf8",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["godot_string *", "p_self"],
+ ["const char *", "p_utf8"]
+ ]
+ },
+ {
+ "name": "godot_string_parse_utf8_with_len",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["godot_string *", "p_self"],
+ ["const char *", "p_utf8"],
+ ["godot_int", "p_len"]
+ ]
+ },
+ {
+ "name": "godot_string_chars_to_utf8",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const char *", "p_utf8"]
+ ]
+ },
+ {
+ "name": "godot_string_chars_to_utf8_with_len",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const char *", "p_utf8"],
+ ["godot_int", "p_len"]
+ ]
+ },
+ {
+ "name": "godot_string_hash",
+ "return_type": "uint32_t",
+ "arguments": [
+ ["const godot_string *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_string_hash64",
+ "return_type": "uint64_t",
+ "arguments": [
+ ["const godot_string *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_string_hash_chars",
+ "return_type": "uint32_t",
+ "arguments": [
+ ["const char *", "p_cstr"]
+ ]
+ },
+ {
+ "name": "godot_string_hash_chars_with_len",
+ "return_type": "uint32_t",
+ "arguments": [
+ ["const char *", "p_cstr"],
+ ["godot_int", "p_len"]
+ ]
+ },
+ {
+ "name": "godot_string_hash_utf8_chars",
+ "return_type": "uint32_t",
+ "arguments": [
+ ["const wchar_t *", "p_str"]
+ ]
+ },
+ {
+ "name": "godot_string_hash_utf8_chars_with_len",
+ "return_type": "uint32_t",
+ "arguments": [
+ ["const wchar_t *", "p_str"],
+ ["godot_int", "p_len"]
+ ]
+ },
+ {
+ "name": "godot_string_md5_buffer",
+ "return_type": "godot_pool_byte_array",
+ "arguments": [
+ ["const godot_string *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_string_md5_text",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_string *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_string_sha256_buffer",
+ "return_type": "godot_pool_byte_array",
+ "arguments": [
+ ["const godot_string *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_string_sha256_text",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_string *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_string_empty",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_string *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_string_get_base_dir",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_string *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_string_get_file",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_string *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_string_humanize_size",
+ "return_type": "godot_string",
+ "arguments": [
+ ["size_t", "p_size"]
+ ]
+ },
+ {
+ "name": "godot_string_is_abs_path",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_string *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_string_is_rel_path",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_string *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_string_is_resource_file",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_string *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_string_path_to",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["const godot_string *", "p_path"]
+ ]
+ },
+ {
+ "name": "godot_string_path_to_file",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["const godot_string *", "p_path"]
+ ]
+ },
+ {
+ "name": "godot_string_simplify_path",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_string *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_string_c_escape",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_string *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_string_c_escape_multiline",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_string *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_string_c_unescape",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_string *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_string_http_escape",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_string *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_string_http_unescape",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_string *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_string_json_escape",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_string *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_string_word_wrap",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["godot_int", "p_chars_per_line"]
+ ]
+ },
+ {
+ "name": "godot_string_xml_escape",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_string *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_string_xml_escape_with_quotes",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_string *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_string_xml_unescape",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_string *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_string_percent_decode",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_string *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_string_percent_encode",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_string *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_string_is_valid_float",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_string *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_string_is_valid_hex_number",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["godot_bool", "p_with_prefix"]
+ ]
+ },
+ {
+ "name": "godot_string_is_valid_html_color",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_string *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_string_is_valid_identifier",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_string *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_string_is_valid_integer",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_string *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_string_is_valid_ip_address",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_string *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_string_destroy",
+ "return_type": "void",
+ "arguments": [
+ ["godot_string *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_string_name_new",
+ "return_type": "void",
+ "arguments": [
+ ["godot_string_name *", "r_dest"],
+ ["const godot_string *", "p_name"]
+ ]
+ },
+ {
+ "name": "godot_string_name_new_data",
+ "return_type": "void",
+ "arguments": [
+ ["godot_string_name *", "r_dest"],
+ ["const char *", "p_name"]
+ ]
+ },
+ {
+ "name": "godot_string_name_get_name",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_string_name *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_string_name_get_hash",
+ "return_type": "uint32_t",
+ "arguments": [
+ ["const godot_string_name *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_string_name_get_data_unique_pointer",
+ "return_type": "const void *",
+ "arguments": [
+ ["const godot_string_name *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_string_name_operator_equal",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_string_name *", "p_self"],
+ ["const godot_string_name *", "p_other"]
+ ]
+ },
+ {
+ "name": "godot_string_name_operator_less",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_string_name *", "p_self"],
+ ["const godot_string_name *", "p_other"]
+ ]
+ },
+ {
+ "name": "godot_string_name_destroy",
+ "return_type": "void",
+ "arguments": [
+ ["godot_string_name *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_object_destroy",
+ "return_type": "void",
+ "arguments": [
+ ["godot_object *", "p_o"]
+ ]
+ },
+ {
+ "name": "godot_global_get_singleton",
+ "return_type": "godot_object *",
+ "arguments": [
+ ["char *", "p_name"]
+ ]
+ },
+ {
+ "name": "godot_method_bind_get_method",
+ "return_type": "godot_method_bind *",
+ "arguments": [
+ ["const char *", "p_classname"],
+ ["const char *", "p_methodname"]
+ ]
+ },
+ {
+ "name": "godot_method_bind_ptrcall",
+ "return_type": "void",
+ "arguments": [
+ ["godot_method_bind *", "p_method_bind"],
+ ["godot_object *", "p_instance"],
+ ["const void **", "p_args"],
+ ["void *", "p_ret"]
+ ]
+ },
+ {
+ "name": "godot_method_bind_call",
+ "return_type": "godot_variant",
+ "arguments": [
+ ["godot_method_bind *", "p_method_bind"],
+ ["godot_object *", "p_instance"],
+ ["const godot_variant **", "p_args"],
+ ["const int", "p_arg_count"],
+ ["godot_variant_call_error *", "p_call_error"]
+ ]
+ },
+ {
+ "name": "godot_get_class_constructor",
+ "return_type": "godot_class_constructor",
+ "arguments": [
+ ["const char *", "p_classname"]
+ ]
+ },
+ {
+ "name": "godot_register_native_call_type",
+ "return_type": "void",
+ "arguments": [
+ ["const char *", "call_type"],
+ ["native_call_cb", "p_callback"]
+ ]
+ },
+ {
+ "name": "godot_alloc",
+ "return_type": "void *",
+ "arguments": [
+ ["int", "p_bytes"]
+ ]
+ },
+ {
+ "name": "godot_realloc",
+ "return_type": "void *",
+ "arguments": [
+ ["void *", "p_ptr"],
+ ["int", "p_bytes"]
+ ]
+ },
+ {
+ "name": "godot_free",
+ "return_type": "void",
+ "arguments": [
+ ["void *", "p_ptr"]
+ ]
+ },
+ {
+ "name": "godot_print_error",
+ "return_type": "void",
+ "arguments": [
+ ["const char *", "p_description"],
+ ["const char *", "p_function"],
+ ["const char *", "p_file"],
+ ["int", "p_line"]
+ ]
+ },
+ {
+ "name": "godot_print_warning",
+ "return_type": "void",
+ "arguments": [
+ ["const char *", "p_description"],
+ ["const char *", "p_function"],
+ ["const char *", "p_file"],
+ ["int", "p_line"]
+ ]
+ },
+ {
+ "name": "godot_print",
+ "return_type": "void",
+ "arguments": [
+ ["const godot_string *", "p_message"]
+ ]
+ }
+ ]
+ },
+ "extensions": {
+ "nativescript": {
+ "type": "NATIVESCRIPT",
+ "version": {
+ "major": 1,
+ "minor": 0
+ },
+ "api": [
+ {
+ "name": "godot_nativescript_register_class",
+ "return_type": "void",
+ "arguments": [
+ ["void *", "p_gdnative_handle"],
+ ["const char *", "p_name"],
+ ["const char *", "p_base"],
+ ["godot_instance_create_func", "p_create_func"],
+ ["godot_instance_destroy_func", "p_destroy_func"]
+ ]
+ },
+ {
+ "name": "godot_nativescript_register_tool_class",
+ "return_type": "void",
+ "arguments": [
+ ["void *", "p_gdnative_handle"],
+ ["const char *", "p_name"],
+ ["const char *", "p_base"],
+ ["godot_instance_create_func", "p_create_func"],
+ ["godot_instance_destroy_func", "p_destroy_func"]
+ ]
+ },
+ {
+ "name": "godot_nativescript_register_method",
+ "return_type": "void",
+ "arguments": [
+ ["void *", "p_gdnative_handle"],
+ ["const char *", "p_name"],
+ ["const char *", "p_function_name"],
+ ["godot_method_attributes", "p_attr"],
+ ["godot_instance_method", "p_method"]
+ ]
+ },
+ {
+ "name": "godot_nativescript_register_property",
+ "return_type": "void",
+ "arguments": [
+ ["void *", "p_gdnative_handle"],
+ ["const char *", "p_name"],
+ ["const char *", "p_path"],
+ ["godot_property_attributes *", "p_attr"],
+ ["godot_property_set_func", "p_set_func"],
+ ["godot_property_get_func", "p_get_func"]
+ ]
+ },
+ {
+ "name": "godot_nativescript_register_signal",
+ "return_type": "void",
+ "arguments": [
+ ["void *", "p_gdnative_handle"],
+ ["const char *", "p_name"],
+ ["const godot_signal *", "p_signal"]
+ ]
+ },
+ {
+ "name": "godot_nativescript_get_userdata",
+ "return_type": "void *",
+ "arguments": [
+ ["godot_object *", "p_instance"]
+ ]
+ }
+ ]
+ },
+ "pluginscript": {
+ "type": "PLUGINSCRIPT",
+ "version": {
+ "major": 1,
+ "minor": 0
+ },
+ "api": [
+ {
+ "name": "godot_pluginscript_register_language",
+ "return_type": "void",
+ "arguments": [
+ ["const godot_pluginscript_language_desc *", "language_desc"]
+ ]
+ }
+ ]
+ },
+ "arvr": {
+ "type": "ARVR",
+ "version": {
+ "major": 1,
+ "minor": 0
+ },
+ "api": [
+ {
+ "name": "godot_arvr_register_interface",
+ "return_type": "void",
+ "arguments": [
+ ["const godot_arvr_interface_gdnative *", "p_interface"]
+ ]
+ },
+ {
+ "name": "godot_arvr_get_worldscale",
+ "return_type": "godot_real",
+ "arguments": []
+ },
+ {
+ "name": "godot_arvr_get_reference_frame",
+ "return_type": "godot_transform",
+ "arguments": []
+ },
+ {
+ "name": "godot_arvr_blit",
+ "return_type": "void",
+ "arguments": [
+ ["int", "p_eye"],
+ ["godot_rid *", "p_render_target"],
+ ["godot_rect2 *", "p_screen_rect"]
+ ]
+ },
+ {
+ "name": "godot_arvr_get_texid",
+ "return_type": "godot_int",
+ "arguments": [
+ ["godot_rid *", "p_render_target"]
+ ]
+ },
+ {
+ "name": "godot_arvr_add_controller",
+ "return_type": "godot_int",
+ "arguments": [
+ ["char *", "p_device_name"],
+ ["godot_int", "p_hand"],
+ ["godot_bool", "p_tracks_orientation"],
+ ["godot_bool", "p_tracks_position"]
+ ]
+ },
+ {
+ "name": "godot_arvr_remove_controller",
+ "return_type": "void",
+ "arguments": [
+ ["godot_int", "p_controller_id"]
+ ]
+ },
+ {
+ "name": "godot_arvr_set_controller_transform",
+ "return_type": "void",
+ "arguments": [
+ ["godot_int", "p_controller_id"],
+ ["godot_transform *", "p_transform"],
+ ["godot_bool", "p_tracks_orientation"],
+ ["godot_bool", "p_tracks_position"]
+ ]
+ },
+ {
+ "name": "godot_arvr_set_controller_button",
+ "return_type": "void",
+ "arguments": [
+ ["godot_int", "p_controller_id"],
+ ["godot_int", "p_button"],
+ ["godot_bool", "p_is_pressed"]
+ ]
+ },
+ {
+ "name": "godot_arvr_set_controller_axis",
+ "return_type": "void",
+ "arguments": [
+ ["godot_int", "p_controller_id"],
+ ["godot_int", "p_exis"],
+ ["godot_real", "p_value"],
+ ["godot_bool", "p_can_be_negative"]
+ ]
+ },
+ {
+ "name": "godot_arvr_get_controller_rumble",
+ "return_type": "godot_real",
+ "arguments": [
+ ["godot_int", "p_controller_id"]
+ ]
+ }
]
}
}
diff --git a/modules/gdnative/include/arvr/godot_arvr.h b/modules/gdnative/include/arvr/godot_arvr.h
new file mode 100644
index 0000000000..be13ac954b
--- /dev/null
+++ b/modules/gdnative/include/arvr/godot_arvr.h
@@ -0,0 +1,79 @@
+/*************************************************************************/
+/* godot_arvr.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#ifndef GODOT_NATIVEARVR_H
+#define GODOT_NATIVEARVR_H
+
+#include <gdnative/gdnative.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+ void *(*constructor)(godot_object *);
+ void (*destructor)(void *);
+ godot_string (*get_name)(const void *);
+ godot_int (*get_capabilities)(const void *);
+ godot_bool (*get_anchor_detection_is_enabled)(const void *);
+ void (*set_anchor_detection_is_enabled)(void *, godot_bool);
+ godot_bool (*is_stereo)(const void *);
+ godot_bool (*is_initialized)(const void *);
+ godot_bool (*initialize)(void *);
+ void (*uninitialize)(void *);
+ godot_vector2 (*get_render_targetsize)(const void *);
+ godot_transform (*get_transform_for_eye)(void *, godot_int, godot_transform *);
+ void (*fill_projection_for_eye)(void *, godot_real *, godot_int, godot_real, godot_real, godot_real);
+ void (*commit_for_eye)(void *, godot_int, godot_rid *, godot_rect2 *);
+ void (*process)(void *);
+} godot_arvr_interface_gdnative;
+
+void GDAPI godot_arvr_register_interface(const godot_arvr_interface_gdnative *p_interface);
+
+// helper functions to access ARVRServer data
+godot_real GDAPI godot_arvr_get_worldscale();
+godot_transform GDAPI godot_arvr_get_reference_frame();
+
+// helper functions for rendering
+void GDAPI godot_arvr_blit(godot_int p_eye, godot_rid *p_render_target, godot_rect2 *p_rect);
+godot_int GDAPI godot_arvr_get_texid(godot_rid *p_render_target);
+
+// helper functions for updating ARVR controllers
+godot_int GDAPI godot_arvr_add_controller(char *p_device_name, godot_int p_hand, godot_bool p_tracks_orientation, godot_bool p_tracks_position);
+void GDAPI godot_arvr_remove_controller(godot_int p_controller_id);
+void GDAPI godot_arvr_set_controller_transform(godot_int p_controller_id, godot_transform *p_transform, godot_bool p_tracks_orientation, godot_bool p_tracks_position);
+void GDAPI godot_arvr_set_controller_button(godot_int p_controller_id, godot_int p_button, godot_bool p_is_pressed);
+void GDAPI godot_arvr_set_controller_axis(godot_int p_controller_id, godot_int p_axis, godot_real p_value, godot_bool p_can_be_negative);
+godot_real GDAPI godot_arvr_get_controller_rumble(godot_int p_controller_id);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !GODOT_NATIVEARVR_H */
diff --git a/modules/gdnative/include/gdnative/aabb.h b/modules/gdnative/include/gdnative/aabb.h
new file mode 100644
index 0000000000..34339fa242
--- /dev/null
+++ b/modules/gdnative/include/gdnative/aabb.h
@@ -0,0 +1,117 @@
+/*************************************************************************/
+/* aabb.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#ifndef GODOT_AABB_H
+#define GODOT_AABB_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+#define GODOT_AABB_SIZE 24
+
+#ifndef GODOT_CORE_API_GODOT_AABB_TYPE_DEFINED
+#define GODOT_CORE_API_GODOT_AABB_TYPE_DEFINED
+typedef struct {
+ uint8_t _dont_touch_that[GODOT_AABB_SIZE];
+} godot_aabb;
+#endif
+
+// reduce extern "C" nesting for VS2013
+#ifdef __cplusplus
+}
+#endif
+
+#include <gdnative/gdnative.h>
+#include <gdnative/plane.h>
+#include <gdnative/vector3.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void GDAPI godot_aabb_new(godot_aabb *r_dest, const godot_vector3 *p_pos, const godot_vector3 *p_size);
+
+godot_vector3 GDAPI godot_aabb_get_position(const godot_aabb *p_self);
+void GDAPI godot_aabb_set_position(const godot_aabb *p_self, const godot_vector3 *p_v);
+
+godot_vector3 GDAPI godot_aabb_get_size(const godot_aabb *p_self);
+void GDAPI godot_aabb_set_size(const godot_aabb *p_self, const godot_vector3 *p_v);
+
+godot_string GDAPI godot_aabb_as_string(const godot_aabb *p_self);
+
+godot_real GDAPI godot_aabb_get_area(const godot_aabb *p_self);
+
+godot_bool GDAPI godot_aabb_has_no_area(const godot_aabb *p_self);
+
+godot_bool GDAPI godot_aabb_has_no_surface(const godot_aabb *p_self);
+
+godot_bool GDAPI godot_aabb_intersects(const godot_aabb *p_self, const godot_aabb *p_with);
+
+godot_bool GDAPI godot_aabb_encloses(const godot_aabb *p_self, const godot_aabb *p_with);
+
+godot_aabb GDAPI godot_aabb_merge(const godot_aabb *p_self, const godot_aabb *p_with);
+
+godot_aabb GDAPI godot_aabb_intersection(const godot_aabb *p_self, const godot_aabb *p_with);
+
+godot_bool GDAPI godot_aabb_intersects_plane(const godot_aabb *p_self, const godot_plane *p_plane);
+
+godot_bool GDAPI godot_aabb_intersects_segment(const godot_aabb *p_self, const godot_vector3 *p_from, const godot_vector3 *p_to);
+
+godot_bool GDAPI godot_aabb_has_point(const godot_aabb *p_self, const godot_vector3 *p_point);
+
+godot_vector3 GDAPI godot_aabb_get_support(const godot_aabb *p_self, const godot_vector3 *p_dir);
+
+godot_vector3 GDAPI godot_aabb_get_longest_axis(const godot_aabb *p_self);
+
+godot_int GDAPI godot_aabb_get_longest_axis_index(const godot_aabb *p_self);
+
+godot_real GDAPI godot_aabb_get_longest_axis_size(const godot_aabb *p_self);
+
+godot_vector3 GDAPI godot_aabb_get_shortest_axis(const godot_aabb *p_self);
+
+godot_int GDAPI godot_aabb_get_shortest_axis_index(const godot_aabb *p_self);
+
+godot_real GDAPI godot_aabb_get_shortest_axis_size(const godot_aabb *p_self);
+
+godot_aabb GDAPI godot_aabb_expand(const godot_aabb *p_self, const godot_vector3 *p_to_point);
+
+godot_aabb GDAPI godot_aabb_grow(const godot_aabb *p_self, const godot_real p_by);
+
+godot_vector3 GDAPI godot_aabb_get_endpoint(const godot_aabb *p_self, const godot_int p_idx);
+
+godot_bool GDAPI godot_aabb_operator_equal(const godot_aabb *p_self, const godot_aabb *p_b);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // GODOT_AABB_H
diff --git a/modules/gdnative/include/gdnative/array.h b/modules/gdnative/include/gdnative/array.h
index edab028cba..484ffd10ba 100644
--- a/modules/gdnative/include/gdnative/array.h
+++ b/modules/gdnative/include/gdnative/array.h
@@ -46,11 +46,20 @@ typedef struct {
} godot_array;
#endif
+// reduce extern "C" nesting for VS2013
+#ifdef __cplusplus
+}
+#endif
+
#include <gdnative/pool_arrays.h>
#include <gdnative/variant.h>
#include <gdnative/gdnative.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
void GDAPI godot_array_new(godot_array *r_dest);
void GDAPI godot_array_new_copy(godot_array *r_dest, const godot_array *p_src);
void GDAPI godot_array_new_pool_color_array(godot_array *r_dest, const godot_pool_color_array *p_pca);
@@ -67,6 +76,8 @@ godot_variant GDAPI godot_array_get(const godot_array *p_self, const godot_int p
godot_variant GDAPI *godot_array_operator_index(godot_array *p_self, const godot_int p_idx);
+const godot_variant GDAPI *godot_array_operator_index_const(const godot_array *p_self, const godot_int p_idx);
+
void GDAPI godot_array_append(godot_array *p_self, const godot_variant *p_value);
void GDAPI godot_array_clear(godot_array *p_self);
@@ -113,6 +124,10 @@ void GDAPI godot_array_sort(godot_array *p_self);
void GDAPI godot_array_sort_custom(godot_array *p_self, godot_object *p_obj, const godot_string *p_func);
+godot_int GDAPI godot_array_bsearch(godot_array *p_self, const godot_variant *p_value, const godot_bool p_before);
+
+godot_int GDAPI godot_array_bsearch_custom(godot_array *p_self, const godot_variant *p_value, godot_object *p_obj, const godot_string *p_func, const godot_bool p_before);
+
void GDAPI godot_array_destroy(godot_array *p_self);
#ifdef __cplusplus
diff --git a/modules/gdnative/include/gdnative/basis.h b/modules/gdnative/include/gdnative/basis.h
index 8ff6a6f541..49ca765a01 100644
--- a/modules/gdnative/include/gdnative/basis.h
+++ b/modules/gdnative/include/gdnative/basis.h
@@ -45,10 +45,19 @@ typedef struct {
} godot_basis;
#endif
+// reduce extern "C" nesting for VS2013
+#ifdef __cplusplus
+}
+#endif
+
#include <gdnative/gdnative.h>
#include <gdnative/quat.h>
#include <gdnative/vector3.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
void GDAPI godot_basis_new_with_rows(godot_basis *r_dest, const godot_vector3 *p_x_axis, const godot_vector3 *p_y_axis, const godot_vector3 *p_z_axis);
void GDAPI godot_basis_new_with_axis_and_angle(godot_basis *r_dest, const godot_vector3 *p_axis, const godot_real p_phi);
void GDAPI godot_basis_new_with_euler(godot_basis *r_dest, const godot_vector3 *p_euler);
@@ -88,7 +97,7 @@ void GDAPI godot_basis_new(godot_basis *r_dest);
void GDAPI godot_basis_new_with_euler_quat(godot_basis *r_dest, const godot_quat *p_euler);
// p_elements is a pointer to an array of 3 (!!) vector3
-void GDAPI godot_basis_get_elements(godot_basis *p_self, godot_vector3 *p_elements);
+void GDAPI godot_basis_get_elements(const godot_basis *p_self, godot_vector3 *p_elements);
godot_vector3 GDAPI godot_basis_get_axis(const godot_basis *p_self, const godot_int p_axis);
diff --git a/modules/gdnative/include/gdnative/color.h b/modules/gdnative/include/gdnative/color.h
index 14265466b9..857e86a738 100644
--- a/modules/gdnative/include/gdnative/color.h
+++ b/modules/gdnative/include/gdnative/color.h
@@ -45,9 +45,18 @@ typedef struct {
} godot_color;
#endif
+// reduce extern "C" nesting for VS2013
+#ifdef __cplusplus
+}
+#endif
+
#include <gdnative/gdnative.h>
#include <gdnative/string.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
void GDAPI godot_color_new_rgba(godot_color *r_dest, const godot_real p_r, const godot_real p_g, const godot_real p_b, const godot_real p_a);
void GDAPI godot_color_new_rgb(godot_color *r_dest, const godot_real p_r, const godot_real p_g, const godot_real p_b);
diff --git a/modules/gdnative/include/gdnative/dictionary.h b/modules/gdnative/include/gdnative/dictionary.h
index c85c3f3830..6d1f436921 100644
--- a/modules/gdnative/include/gdnative/dictionary.h
+++ b/modules/gdnative/include/gdnative/dictionary.h
@@ -45,10 +45,19 @@ typedef struct {
} godot_dictionary;
#endif
+// reduce extern "C" nesting for VS2013
+#ifdef __cplusplus
+}
+#endif
+
#include <gdnative/array.h>
#include <gdnative/gdnative.h>
#include <gdnative/variant.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
void GDAPI godot_dictionary_new(godot_dictionary *r_dest);
void GDAPI godot_dictionary_new_copy(godot_dictionary *r_dest, const godot_dictionary *p_src);
void GDAPI godot_dictionary_destroy(godot_dictionary *p_self);
@@ -76,6 +85,8 @@ void GDAPI godot_dictionary_set(godot_dictionary *p_self, const godot_variant *p
godot_variant GDAPI *godot_dictionary_operator_index(godot_dictionary *p_self, const godot_variant *p_key);
+const godot_variant GDAPI *godot_dictionary_operator_index_const(const godot_dictionary *p_self, const godot_variant *p_key);
+
godot_variant GDAPI *godot_dictionary_next(const godot_dictionary *p_self, const godot_variant *p_key);
godot_bool GDAPI godot_dictionary_operator_equal(const godot_dictionary *p_self, const godot_dictionary *p_b);
diff --git a/modules/gdnative/include/gdnative/gdnative.h b/modules/gdnative/include/gdnative/gdnative.h
index 008968a5e5..6e69d43469 100644
--- a/modules/gdnative/include/gdnative/gdnative.h
+++ b/modules/gdnative/include/gdnative/gdnative.h
@@ -47,7 +47,7 @@ extern "C" {
#define GDAPI GDCALLINGCONV
#endif
#else
-#define GDCALLINGCONV __attribute__((sysv_abi, visibility("default")))
+#define GDCALLINGCONV __attribute__((sysv_abi))
#define GDAPI GDCALLINGCONV
#endif
@@ -141,6 +141,10 @@ typedef void godot_object;
#include <gdnative/string.h>
+/////// String name
+
+#include <gdnative/string_name.h>
+
////// Vector2
#include <gdnative/vector2.h>
@@ -165,9 +169,9 @@ typedef void godot_object;
#include <gdnative/quat.h>
-/////// Rect3
+/////// AABB
-#include <gdnative/rect3.h>
+#include <gdnative/aabb.h>
/////// Basis
@@ -225,15 +229,30 @@ void GDAPI godot_method_bind_ptrcall(godot_method_bind *p_method_bind, godot_obj
godot_variant GDAPI godot_method_bind_call(godot_method_bind *p_method_bind, godot_object *p_instance, const godot_variant **p_args, const int p_arg_count, godot_variant_call_error *p_call_error);
////// Script API
-struct godot_gdnative_api_struct; // Forward declaration
+typedef struct godot_gdnative_api_version {
+ unsigned int major;
+ unsigned int minor;
+} godot_gdnative_api_version;
+
+typedef struct godot_gdnative_api_struct godot_gdnative_api_struct;
+
+struct godot_gdnative_api_struct {
+ unsigned int type;
+ godot_gdnative_api_version version;
+ const godot_gdnative_api_struct *next;
+};
+
+#define GDNATIVE_VERSION_COMPATIBLE(want, have) (want.major == have.major && want.minor <= have.minor)
typedef struct {
godot_bool in_editor;
uint64_t core_api_hash;
uint64_t editor_api_hash;
uint64_t no_api_hash;
+ void (*report_version_mismatch)(const godot_object *p_library, const char *p_what, godot_gdnative_api_version p_want, godot_gdnative_api_version p_have);
+ void (*report_loading_error)(const godot_object *p_library, const char *p_what);
godot_object *gd_native_library; // pointer to GDNativeLibrary that is being initialized
- const struct godot_gdnative_api_struct *api_struct;
+ const struct godot_gdnative_core_api_struct *api_struct;
const godot_string *active_library_path;
} godot_gdnative_init_options;
@@ -251,10 +270,13 @@ godot_dictionary GDAPI godot_get_global_constants();
////// GDNative procedure types
typedef void (*godot_gdnative_init_fn)(godot_gdnative_init_options *);
typedef void (*godot_gdnative_terminate_fn)(godot_gdnative_terminate_options *);
-typedef godot_variant (*godot_gdnative_procedure_fn)(void *, godot_array *);
+typedef godot_variant (*godot_gdnative_procedure_fn)(godot_array *);
////// System Functions
+typedef godot_variant (*native_call_cb)(void *, godot_array *);
+void GDAPI godot_register_native_call_type(const char *p_call_type, native_call_cb p_callback);
+
//using these will help Godot track how much memory is in use in debug mode
void GDAPI *godot_alloc(int p_bytes);
void GDAPI *godot_realloc(void *p_ptr, int p_bytes);
diff --git a/modules/gdnative/include/gdnative/node_path.h b/modules/gdnative/include/gdnative/node_path.h
index 0cfdbc1127..42446175d8 100644
--- a/modules/gdnative/include/gdnative/node_path.h
+++ b/modules/gdnative/include/gdnative/node_path.h
@@ -45,9 +45,18 @@ typedef struct {
} godot_node_path;
#endif
+// reduce extern "C" nesting for VS2013
+#ifdef __cplusplus
+}
+#endif
+
#include <gdnative/gdnative.h>
#include <gdnative/string.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
void GDAPI godot_node_path_new(godot_node_path *r_dest, const godot_string *p_from);
void GDAPI godot_node_path_new_copy(godot_node_path *r_dest, const godot_node_path *p_src);
void GDAPI godot_node_path_destroy(godot_node_path *p_self);
diff --git a/modules/gdnative/include/gdnative/plane.h b/modules/gdnative/include/gdnative/plane.h
index 6a8915e08b..dddd172122 100644
--- a/modules/gdnative/include/gdnative/plane.h
+++ b/modules/gdnative/include/gdnative/plane.h
@@ -45,9 +45,18 @@ typedef struct {
} godot_plane;
#endif
+// reduce extern "C" nesting for VS2013
+#ifdef __cplusplus
+}
+#endif
+
#include <gdnative/gdnative.h>
#include <gdnative/vector3.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
void GDAPI godot_plane_new_with_reals(godot_plane *r_dest, const godot_real p_a, const godot_real p_b, const godot_real p_c, const godot_real p_d);
void GDAPI godot_plane_new_with_vectors(godot_plane *r_dest, const godot_vector3 *p_v1, const godot_vector3 *p_v2, const godot_vector3 *p_v3);
void GDAPI godot_plane_new_with_normal(godot_plane *r_dest, const godot_vector3 *p_normal, const godot_real p_d);
diff --git a/modules/gdnative/include/gdnative/pool_arrays.h b/modules/gdnative/include/gdnative/pool_arrays.h
index cb1095ee8c..81500c9186 100644
--- a/modules/gdnative/include/gdnative/pool_arrays.h
+++ b/modules/gdnative/include/gdnative/pool_arrays.h
@@ -36,6 +36,38 @@ extern "C" {
#include <stdint.h>
+/////// Read Access
+
+#define GODOT_POOL_ARRAY_READ_ACCESS_SIZE 1
+
+typedef struct {
+ uint8_t _dont_touch_that[GODOT_POOL_ARRAY_READ_ACCESS_SIZE];
+} godot_pool_array_read_access;
+
+typedef godot_pool_array_read_access godot_pool_byte_array_read_access;
+typedef godot_pool_array_read_access godot_pool_int_array_read_access;
+typedef godot_pool_array_read_access godot_pool_real_array_read_access;
+typedef godot_pool_array_read_access godot_pool_string_array_read_access;
+typedef godot_pool_array_read_access godot_pool_vector2_array_read_access;
+typedef godot_pool_array_read_access godot_pool_vector3_array_read_access;
+typedef godot_pool_array_read_access godot_pool_color_array_read_access;
+
+/////// Write Access
+
+#define GODOT_POOL_ARRAY_WRITE_ACCESS_SIZE 1
+
+typedef struct {
+ uint8_t _dont_touch_that[GODOT_POOL_ARRAY_WRITE_ACCESS_SIZE];
+} godot_pool_array_write_access;
+
+typedef godot_pool_array_write_access godot_pool_byte_array_write_access;
+typedef godot_pool_array_write_access godot_pool_int_array_write_access;
+typedef godot_pool_array_write_access godot_pool_real_array_write_access;
+typedef godot_pool_array_write_access godot_pool_string_array_write_access;
+typedef godot_pool_array_write_access godot_pool_vector2_array_write_access;
+typedef godot_pool_array_write_access godot_pool_vector3_array_write_access;
+typedef godot_pool_array_write_access godot_pool_color_array_write_access;
+
/////// PoolByteArray
#define GODOT_POOL_BYTE_ARRAY_SIZE sizeof(void *)
@@ -113,6 +145,11 @@ typedef struct {
} godot_pool_color_array;
#endif
+// reduce extern "C" nesting for VS2013
+#ifdef __cplusplus
+}
+#endif
+
#include <gdnative/array.h>
#include <gdnative/color.h>
#include <gdnative/vector2.h>
@@ -120,6 +157,10 @@ typedef struct {
#include <gdnative/gdnative.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
// byte
void GDAPI godot_pool_byte_array_new(godot_pool_byte_array *r_dest);
@@ -140,6 +181,10 @@ void GDAPI godot_pool_byte_array_remove(godot_pool_byte_array *p_self, const god
void GDAPI godot_pool_byte_array_resize(godot_pool_byte_array *p_self, const godot_int p_size);
+godot_pool_byte_array_read_access GDAPI *godot_pool_byte_array_read(const godot_pool_byte_array *p_self);
+
+godot_pool_byte_array_write_access GDAPI *godot_pool_byte_array_write(godot_pool_byte_array *p_self);
+
void GDAPI godot_pool_byte_array_set(godot_pool_byte_array *p_self, const godot_int p_idx, const uint8_t p_data);
uint8_t GDAPI godot_pool_byte_array_get(const godot_pool_byte_array *p_self, const godot_int p_idx);
@@ -167,6 +212,10 @@ void GDAPI godot_pool_int_array_remove(godot_pool_int_array *p_self, const godot
void GDAPI godot_pool_int_array_resize(godot_pool_int_array *p_self, const godot_int p_size);
+godot_pool_int_array_read_access GDAPI *godot_pool_int_array_read(const godot_pool_int_array *p_self);
+
+godot_pool_int_array_write_access GDAPI *godot_pool_int_array_write(godot_pool_int_array *p_self);
+
void GDAPI godot_pool_int_array_set(godot_pool_int_array *p_self, const godot_int p_idx, const godot_int p_data);
godot_int GDAPI godot_pool_int_array_get(const godot_pool_int_array *p_self, const godot_int p_idx);
@@ -194,6 +243,10 @@ void GDAPI godot_pool_real_array_remove(godot_pool_real_array *p_self, const god
void GDAPI godot_pool_real_array_resize(godot_pool_real_array *p_self, const godot_int p_size);
+godot_pool_real_array_read_access GDAPI *godot_pool_real_array_read(const godot_pool_real_array *p_self);
+
+godot_pool_real_array_write_access GDAPI *godot_pool_real_array_write(godot_pool_real_array *p_self);
+
void GDAPI godot_pool_real_array_set(godot_pool_real_array *p_self, const godot_int p_idx, const godot_real p_data);
godot_real GDAPI godot_pool_real_array_get(const godot_pool_real_array *p_self, const godot_int p_idx);
@@ -221,6 +274,10 @@ void GDAPI godot_pool_string_array_remove(godot_pool_string_array *p_self, const
void GDAPI godot_pool_string_array_resize(godot_pool_string_array *p_self, const godot_int p_size);
+godot_pool_string_array_read_access GDAPI *godot_pool_string_array_read(const godot_pool_string_array *p_self);
+
+godot_pool_string_array_write_access GDAPI *godot_pool_string_array_write(godot_pool_string_array *p_self);
+
void GDAPI godot_pool_string_array_set(godot_pool_string_array *p_self, const godot_int p_idx, const godot_string *p_data);
godot_string GDAPI godot_pool_string_array_get(const godot_pool_string_array *p_self, const godot_int p_idx);
@@ -248,6 +305,10 @@ void GDAPI godot_pool_vector2_array_remove(godot_pool_vector2_array *p_self, con
void GDAPI godot_pool_vector2_array_resize(godot_pool_vector2_array *p_self, const godot_int p_size);
+godot_pool_vector2_array_read_access GDAPI *godot_pool_vector2_array_read(const godot_pool_vector2_array *p_self);
+
+godot_pool_vector2_array_write_access GDAPI *godot_pool_vector2_array_write(godot_pool_vector2_array *p_self);
+
void GDAPI godot_pool_vector2_array_set(godot_pool_vector2_array *p_self, const godot_int p_idx, const godot_vector2 *p_data);
godot_vector2 GDAPI godot_pool_vector2_array_get(const godot_pool_vector2_array *p_self, const godot_int p_idx);
@@ -275,6 +336,10 @@ void GDAPI godot_pool_vector3_array_remove(godot_pool_vector3_array *p_self, con
void GDAPI godot_pool_vector3_array_resize(godot_pool_vector3_array *p_self, const godot_int p_size);
+godot_pool_vector3_array_read_access GDAPI *godot_pool_vector3_array_read(const godot_pool_vector3_array *p_self);
+
+godot_pool_vector3_array_write_access GDAPI *godot_pool_vector3_array_write(godot_pool_vector3_array *p_self);
+
void GDAPI godot_pool_vector3_array_set(godot_pool_vector3_array *p_self, const godot_int p_idx, const godot_vector3 *p_data);
godot_vector3 GDAPI godot_pool_vector3_array_get(const godot_pool_vector3_array *p_self, const godot_int p_idx);
@@ -302,6 +367,10 @@ void GDAPI godot_pool_color_array_remove(godot_pool_color_array *p_self, const g
void GDAPI godot_pool_color_array_resize(godot_pool_color_array *p_self, const godot_int p_size);
+godot_pool_color_array_read_access GDAPI *godot_pool_color_array_read(const godot_pool_color_array *p_self);
+
+godot_pool_color_array_write_access GDAPI *godot_pool_color_array_write(godot_pool_color_array *p_self);
+
void GDAPI godot_pool_color_array_set(godot_pool_color_array *p_self, const godot_int p_idx, const godot_color *p_data);
godot_color GDAPI godot_pool_color_array_get(const godot_pool_color_array *p_self, const godot_int p_idx);
@@ -309,6 +378,70 @@ godot_int GDAPI godot_pool_color_array_size(const godot_pool_color_array *p_self
void GDAPI godot_pool_color_array_destroy(godot_pool_color_array *p_self);
+//
+// read accessor functions
+//
+
+const uint8_t GDAPI *godot_pool_byte_array_read_access_ptr(const godot_pool_byte_array_read_access *p_read);
+void GDAPI godot_pool_byte_array_read_access_operator_assign(godot_pool_byte_array_read_access *p_read, godot_pool_byte_array_read_access *p_other);
+void GDAPI godot_pool_byte_array_read_access_destroy(godot_pool_byte_array_read_access *p_read);
+
+const godot_int GDAPI *godot_pool_int_array_read_access_ptr(const godot_pool_int_array_read_access *p_read);
+void GDAPI godot_pool_int_array_read_access_operator_assign(godot_pool_int_array_read_access *p_read, godot_pool_int_array_read_access *p_other);
+void GDAPI godot_pool_int_array_read_access_destroy(godot_pool_int_array_read_access *p_read);
+
+const godot_real GDAPI *godot_pool_real_array_read_access_ptr(const godot_pool_real_array_read_access *p_read);
+void GDAPI godot_pool_real_array_read_access_operator_assign(godot_pool_real_array_read_access *p_read, godot_pool_real_array_read_access *p_other);
+void GDAPI godot_pool_real_array_read_access_destroy(godot_pool_real_array_read_access *p_read);
+
+const godot_string GDAPI *godot_pool_string_array_read_access_ptr(const godot_pool_string_array_read_access *p_read);
+void GDAPI godot_pool_string_array_read_access_operator_assign(godot_pool_string_array_read_access *p_read, godot_pool_string_array_read_access *p_other);
+void GDAPI godot_pool_string_array_read_access_destroy(godot_pool_string_array_read_access *p_read);
+
+const godot_vector2 GDAPI *godot_pool_vector2_array_read_access_ptr(const godot_pool_vector2_array_read_access *p_read);
+void GDAPI godot_pool_vector2_array_read_access_operator_assign(godot_pool_vector2_array_read_access *p_read, godot_pool_vector2_array_read_access *p_other);
+void GDAPI godot_pool_vector2_array_read_access_destroy(godot_pool_vector2_array_read_access *p_read);
+
+const godot_vector3 GDAPI *godot_pool_vector3_array_read_access_ptr(const godot_pool_vector3_array_read_access *p_read);
+void GDAPI godot_pool_vector3_array_read_access_operator_assign(godot_pool_vector3_array_read_access *p_read, godot_pool_vector3_array_read_access *p_other);
+void GDAPI godot_pool_vector3_array_read_access_destroy(godot_pool_vector3_array_read_access *p_read);
+
+const godot_color GDAPI *godot_pool_color_array_read_access_ptr(const godot_pool_color_array_read_access *p_read);
+void GDAPI godot_pool_color_array_read_access_operator_assign(godot_pool_color_array_read_access *p_read, godot_pool_color_array_read_access *p_other);
+void GDAPI godot_pool_color_array_read_access_destroy(godot_pool_color_array_read_access *p_read);
+
+//
+// write accessor functions
+//
+
+uint8_t GDAPI *godot_pool_byte_array_write_access_ptr(const godot_pool_byte_array_write_access *p_write);
+void GDAPI godot_pool_byte_array_write_access_operator_assign(godot_pool_byte_array_write_access *p_write, godot_pool_byte_array_write_access *p_other);
+void GDAPI godot_pool_byte_array_write_access_destroy(godot_pool_byte_array_write_access *p_write);
+
+godot_int GDAPI *godot_pool_int_array_write_access_ptr(const godot_pool_int_array_write_access *p_write);
+void GDAPI godot_pool_int_array_write_access_operator_assign(godot_pool_int_array_write_access *p_write, godot_pool_int_array_write_access *p_other);
+void GDAPI godot_pool_int_array_write_access_destroy(godot_pool_int_array_write_access *p_write);
+
+godot_real GDAPI *godot_pool_real_array_write_access_ptr(const godot_pool_real_array_write_access *p_write);
+void GDAPI godot_pool_real_array_write_access_operator_assign(godot_pool_real_array_write_access *p_write, godot_pool_real_array_write_access *p_other);
+void GDAPI godot_pool_real_array_write_access_destroy(godot_pool_real_array_write_access *p_write);
+
+godot_string GDAPI *godot_pool_string_array_write_access_ptr(const godot_pool_string_array_write_access *p_write);
+void GDAPI godot_pool_string_array_write_access_operator_assign(godot_pool_string_array_write_access *p_write, godot_pool_string_array_write_access *p_other);
+void GDAPI godot_pool_string_array_write_access_destroy(godot_pool_string_array_write_access *p_write);
+
+godot_vector2 GDAPI *godot_pool_vector2_array_write_access_ptr(const godot_pool_vector2_array_write_access *p_write);
+void GDAPI godot_pool_vector2_array_write_access_operator_assign(godot_pool_vector2_array_write_access *p_write, godot_pool_vector2_array_write_access *p_other);
+void GDAPI godot_pool_vector2_array_write_access_destroy(godot_pool_vector2_array_write_access *p_write);
+
+godot_vector3 GDAPI *godot_pool_vector3_array_write_access_ptr(const godot_pool_vector3_array_write_access *p_write);
+void GDAPI godot_pool_vector3_array_write_access_operator_assign(godot_pool_vector3_array_write_access *p_write, godot_pool_vector3_array_write_access *p_other);
+void GDAPI godot_pool_vector3_array_write_access_destroy(godot_pool_vector3_array_write_access *p_write);
+
+godot_color GDAPI *godot_pool_color_array_write_access_ptr(const godot_pool_color_array_write_access *p_write);
+void GDAPI godot_pool_color_array_write_access_operator_assign(godot_pool_color_array_write_access *p_write, godot_pool_color_array_write_access *p_other);
+void GDAPI godot_pool_color_array_write_access_destroy(godot_pool_color_array_write_access *p_write);
+
#ifdef __cplusplus
}
#endif
diff --git a/modules/gdnative/include/gdnative/quat.h b/modules/gdnative/include/gdnative/quat.h
index 4ffb96eb26..acae6e3e90 100644
--- a/modules/gdnative/include/gdnative/quat.h
+++ b/modules/gdnative/include/gdnative/quat.h
@@ -45,9 +45,18 @@ typedef struct {
} godot_quat;
#endif
+// reduce extern "C" nesting for VS2013
+#ifdef __cplusplus
+}
+#endif
+
#include <gdnative/gdnative.h>
#include <gdnative/vector3.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
void GDAPI godot_quat_new(godot_quat *r_dest, const godot_real p_x, const godot_real p_y, const godot_real p_z, const godot_real p_w);
void GDAPI godot_quat_new_with_axis_angle(godot_quat *r_dest, const godot_vector3 *p_axis, const godot_real p_angle);
diff --git a/modules/gdnative/include/gdnative/rect2.h b/modules/gdnative/include/gdnative/rect2.h
index 9e6cf60342..1c66443d4f 100644
--- a/modules/gdnative/include/gdnative/rect2.h
+++ b/modules/gdnative/include/gdnative/rect2.h
@@ -43,9 +43,18 @@ typedef struct godot_rect2 {
} godot_rect2;
#endif
+// reduce extern "C" nesting for VS2013
+#ifdef __cplusplus
+}
+#endif
+
#include <gdnative/gdnative.h>
#include <gdnative/vector2.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
void GDAPI godot_rect2_new_with_position_and_size(godot_rect2 *r_dest, const godot_vector2 *p_pos, const godot_vector2 *p_size);
void GDAPI godot_rect2_new(godot_rect2 *r_dest, const godot_real p_x, const godot_real p_y, const godot_real p_width, const godot_real p_height);
diff --git a/modules/gdnative/include/gdnative/rect3.h b/modules/gdnative/include/gdnative/rect3.h
deleted file mode 100644
index f94b6fea25..0000000000
--- a/modules/gdnative/include/gdnative/rect3.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/*************************************************************************/
-/* rect3.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#ifndef GODOT_RECT3_H
-#define GODOT_RECT3_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stdint.h>
-
-#define GODOT_RECT3_SIZE 24
-
-#ifndef GODOT_CORE_API_GODOT_RECT3_TYPE_DEFINED
-#define GODOT_CORE_API_GODOT_RECT3_TYPE_DEFINED
-typedef struct {
- uint8_t _dont_touch_that[GODOT_RECT3_SIZE];
-} godot_rect3;
-#endif
-
-#include <gdnative/gdnative.h>
-#include <gdnative/plane.h>
-#include <gdnative/vector3.h>
-
-void GDAPI godot_rect3_new(godot_rect3 *r_dest, const godot_vector3 *p_pos, const godot_vector3 *p_size);
-
-godot_vector3 GDAPI godot_rect3_get_position(const godot_rect3 *p_self);
-void GDAPI godot_rect3_set_position(const godot_rect3 *p_self, const godot_vector3 *p_v);
-
-godot_vector3 GDAPI godot_rect3_get_size(const godot_rect3 *p_self);
-void GDAPI godot_rect3_set_size(const godot_rect3 *p_self, const godot_vector3 *p_v);
-
-godot_string GDAPI godot_rect3_as_string(const godot_rect3 *p_self);
-
-godot_real GDAPI godot_rect3_get_area(const godot_rect3 *p_self);
-
-godot_bool GDAPI godot_rect3_has_no_area(const godot_rect3 *p_self);
-
-godot_bool GDAPI godot_rect3_has_no_surface(const godot_rect3 *p_self);
-
-godot_bool GDAPI godot_rect3_intersects(const godot_rect3 *p_self, const godot_rect3 *p_with);
-
-godot_bool GDAPI godot_rect3_encloses(const godot_rect3 *p_self, const godot_rect3 *p_with);
-
-godot_rect3 GDAPI godot_rect3_merge(const godot_rect3 *p_self, const godot_rect3 *p_with);
-
-godot_rect3 GDAPI godot_rect3_intersection(const godot_rect3 *p_self, const godot_rect3 *p_with);
-
-godot_bool GDAPI godot_rect3_intersects_plane(const godot_rect3 *p_self, const godot_plane *p_plane);
-
-godot_bool GDAPI godot_rect3_intersects_segment(const godot_rect3 *p_self, const godot_vector3 *p_from, const godot_vector3 *p_to);
-
-godot_bool GDAPI godot_rect3_has_point(const godot_rect3 *p_self, const godot_vector3 *p_point);
-
-godot_vector3 GDAPI godot_rect3_get_support(const godot_rect3 *p_self, const godot_vector3 *p_dir);
-
-godot_vector3 GDAPI godot_rect3_get_longest_axis(const godot_rect3 *p_self);
-
-godot_int GDAPI godot_rect3_get_longest_axis_index(const godot_rect3 *p_self);
-
-godot_real GDAPI godot_rect3_get_longest_axis_size(const godot_rect3 *p_self);
-
-godot_vector3 GDAPI godot_rect3_get_shortest_axis(const godot_rect3 *p_self);
-
-godot_int GDAPI godot_rect3_get_shortest_axis_index(const godot_rect3 *p_self);
-
-godot_real GDAPI godot_rect3_get_shortest_axis_size(const godot_rect3 *p_self);
-
-godot_rect3 GDAPI godot_rect3_expand(const godot_rect3 *p_self, const godot_vector3 *p_to_point);
-
-godot_rect3 GDAPI godot_rect3_grow(const godot_rect3 *p_self, const godot_real p_by);
-
-godot_vector3 GDAPI godot_rect3_get_endpoint(const godot_rect3 *p_self, const godot_int p_idx);
-
-godot_bool GDAPI godot_rect3_operator_equal(const godot_rect3 *p_self, const godot_rect3 *p_b);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // GODOT_RECT3_H
diff --git a/modules/gdnative/include/gdnative/rid.h b/modules/gdnative/include/gdnative/rid.h
index d9b5336fc9..caa1bb967e 100644
--- a/modules/gdnative/include/gdnative/rid.h
+++ b/modules/gdnative/include/gdnative/rid.h
@@ -45,8 +45,17 @@ typedef struct {
} godot_rid;
#endif
+// reduce extern "C" nesting for VS2013
+#ifdef __cplusplus
+}
+#endif
+
#include <gdnative/gdnative.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
void GDAPI godot_rid_new(godot_rid *r_dest);
godot_int GDAPI godot_rid_get_id(const godot_rid *p_self);
diff --git a/modules/gdnative/include/gdnative/string.h b/modules/gdnative/include/gdnative/string.h
index aca23a81d8..10358ceade 100644
--- a/modules/gdnative/include/gdnative/string.h
+++ b/modules/gdnative/include/gdnative/string.h
@@ -46,9 +46,19 @@ typedef struct {
} godot_string;
#endif
+// reduce extern "C" nesting for VS2013
+#ifdef __cplusplus
+}
+#endif
+
+#include <gdnative/array.h>
#include <gdnative/gdnative.h>
#include <gdnative/variant.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
void GDAPI godot_string_new(godot_string *r_dest);
void GDAPI godot_string_new_copy(godot_string *r_dest, const godot_string *p_src);
void GDAPI godot_string_new_data(godot_string *r_dest, const char *p_contents, const int p_size);
@@ -57,7 +67,7 @@ void GDAPI godot_string_new_unicode_data(godot_string *r_dest, const wchar_t *p_
void GDAPI godot_string_get_data(const godot_string *p_self, char *p_dest, int *p_size);
wchar_t GDAPI *godot_string_operator_index(godot_string *p_self, const godot_int p_idx);
-const char GDAPI *godot_string_c_str(const godot_string *p_self);
+wchar_t GDAPI godot_string_operator_index_const(const godot_string *p_self, const godot_int p_idx);
const wchar_t GDAPI *godot_string_unicode_str(const godot_string *p_self);
godot_bool GDAPI godot_string_operator_equal(const godot_string *p_self, const godot_string *p_b);
diff --git a/modules/gdnative/include/gdnative/string_name.h b/modules/gdnative/include/gdnative/string_name.h
new file mode 100644
index 0000000000..ee9f603d20
--- /dev/null
+++ b/modules/gdnative/include/gdnative/string_name.h
@@ -0,0 +1,77 @@
+/*************************************************************************/
+/* string_name.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#ifndef GODOT_STRING_NAME_H
+#define GODOT_STRING_NAME_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <wchar.h>
+
+#define GODOT_STRING_NAME_SIZE sizeof(void *)
+
+#ifndef GODOT_CORE_API_GODOT_STRING_NAME_TYPE_DEFINED
+#define GODOT_CORE_API_GODOT_STRING_NAME_TYPE_DEFINED
+typedef struct {
+ uint8_t _dont_touch_that[GODOT_STRING_NAME_SIZE];
+} godot_string_name;
+#endif
+
+// reduce extern "C" nesting for VS2013
+#ifdef __cplusplus
+}
+#endif
+
+#include <gdnative/gdnative.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void GDAPI godot_string_name_new(godot_string_name *r_dest, const godot_string *p_name);
+void GDAPI godot_string_name_new_data(godot_string_name *r_dest, const char *p_name);
+
+godot_string GDAPI godot_string_name_get_name(const godot_string_name *p_self);
+
+uint32_t GDAPI godot_string_name_get_hash(const godot_string_name *p_self);
+const void GDAPI *godot_string_name_get_data_unique_pointer(const godot_string_name *p_self);
+
+godot_bool GDAPI godot_string_name_operator_equal(const godot_string_name *p_self, const godot_string_name *p_other);
+godot_bool GDAPI godot_string_name_operator_less(const godot_string_name *p_self, const godot_string_name *p_other);
+
+void GDAPI godot_string_name_destroy(godot_string_name *p_self);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // GODOT_STRING_NAME_H
diff --git a/modules/gdnative/include/gdnative/transform.h b/modules/gdnative/include/gdnative/transform.h
index 656afae129..3b5c189bdf 100644
--- a/modules/gdnative/include/gdnative/transform.h
+++ b/modules/gdnative/include/gdnative/transform.h
@@ -45,11 +45,20 @@ typedef struct {
} godot_transform;
#endif
+// reduce extern "C" nesting for VS2013
+#ifdef __cplusplus
+}
+#endif
+
#include <gdnative/basis.h>
#include <gdnative/gdnative.h>
#include <gdnative/variant.h>
#include <gdnative/vector3.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
void GDAPI godot_transform_new_with_axis_origin(godot_transform *r_dest, const godot_vector3 *p_x_axis, const godot_vector3 *p_y_axis, const godot_vector3 *p_z_axis, const godot_vector3 *p_origin);
void GDAPI godot_transform_new(godot_transform *r_dest, const godot_basis *p_basis, const godot_vector3 *p_origin);
@@ -89,9 +98,9 @@ godot_vector3 GDAPI godot_transform_xform_vector3(const godot_transform *p_self,
godot_vector3 GDAPI godot_transform_xform_inv_vector3(const godot_transform *p_self, const godot_vector3 *p_v);
-godot_rect3 GDAPI godot_transform_xform_rect3(const godot_transform *p_self, const godot_rect3 *p_v);
+godot_aabb GDAPI godot_transform_xform_aabb(const godot_transform *p_self, const godot_aabb *p_v);
-godot_rect3 GDAPI godot_transform_xform_inv_rect3(const godot_transform *p_self, const godot_rect3 *p_v);
+godot_aabb GDAPI godot_transform_xform_inv_aabb(const godot_transform *p_self, const godot_aabb *p_v);
#ifdef __cplusplus
}
diff --git a/modules/gdnative/include/gdnative/transform2d.h b/modules/gdnative/include/gdnative/transform2d.h
index a945868b17..c68bd2963f 100644
--- a/modules/gdnative/include/gdnative/transform2d.h
+++ b/modules/gdnative/include/gdnative/transform2d.h
@@ -45,10 +45,19 @@ typedef struct {
} godot_transform2d;
#endif
+// reduce extern "C" nesting for VS2013
+#ifdef __cplusplus
+}
+#endif
+
#include <gdnative/gdnative.h>
#include <gdnative/variant.h>
#include <gdnative/vector2.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
void GDAPI godot_transform2d_new(godot_transform2d *r_dest, const godot_real p_rot, const godot_vector2 *p_pos);
void GDAPI godot_transform2d_new_axis_origin(godot_transform2d *r_dest, const godot_vector2 *p_x_axis, const godot_vector2 *p_y_axis, const godot_vector2 *p_origin);
diff --git a/modules/gdnative/include/gdnative/variant.h b/modules/gdnative/include/gdnative/variant.h
index 7b804c1eaf..06cafcfa63 100644
--- a/modules/gdnative/include/gdnative/variant.h
+++ b/modules/gdnative/include/gdnative/variant.h
@@ -62,7 +62,7 @@ typedef enum godot_variant_type {
GODOT_VARIANT_TYPE_TRANSFORM2D,
GODOT_VARIANT_TYPE_PLANE,
GODOT_VARIANT_TYPE_QUAT, // 10
- GODOT_VARIANT_TYPE_RECT3,
+ GODOT_VARIANT_TYPE_AABB,
GODOT_VARIANT_TYPE_BASIS,
GODOT_VARIANT_TYPE_TRANSFORM,
@@ -99,6 +99,12 @@ typedef struct godot_variant_call_error {
godot_variant_type expected;
} godot_variant_call_error;
+// reduce extern "C" nesting for VS2013
+#ifdef __cplusplus
+}
+#endif
+
+#include <gdnative/aabb.h>
#include <gdnative/array.h>
#include <gdnative/basis.h>
#include <gdnative/color.h>
@@ -108,7 +114,6 @@ typedef struct godot_variant_call_error {
#include <gdnative/pool_arrays.h>
#include <gdnative/quat.h>
#include <gdnative/rect2.h>
-#include <gdnative/rect3.h>
#include <gdnative/rid.h>
#include <gdnative/string.h>
#include <gdnative/transform.h>
@@ -119,6 +124,10 @@ typedef struct godot_variant_call_error {
#include <gdnative/gdnative.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
godot_variant_type GDAPI godot_variant_get_type(const godot_variant *p_v);
void GDAPI godot_variant_new_copy(godot_variant *r_dest, const godot_variant *p_src);
@@ -136,7 +145,7 @@ void GDAPI godot_variant_new_vector3(godot_variant *r_dest, const godot_vector3
void GDAPI godot_variant_new_transform2d(godot_variant *r_dest, const godot_transform2d *p_t2d);
void GDAPI godot_variant_new_plane(godot_variant *r_dest, const godot_plane *p_plane);
void GDAPI godot_variant_new_quat(godot_variant *r_dest, const godot_quat *p_quat);
-void GDAPI godot_variant_new_rect3(godot_variant *r_dest, const godot_rect3 *p_rect3);
+void GDAPI godot_variant_new_aabb(godot_variant *r_dest, const godot_aabb *p_aabb);
void GDAPI godot_variant_new_basis(godot_variant *r_dest, const godot_basis *p_basis);
void GDAPI godot_variant_new_transform(godot_variant *r_dest, const godot_transform *p_trans);
void GDAPI godot_variant_new_color(godot_variant *r_dest, const godot_color *p_color);
@@ -164,7 +173,7 @@ godot_vector3 GDAPI godot_variant_as_vector3(const godot_variant *p_self);
godot_transform2d GDAPI godot_variant_as_transform2d(const godot_variant *p_self);
godot_plane GDAPI godot_variant_as_plane(const godot_variant *p_self);
godot_quat GDAPI godot_variant_as_quat(const godot_variant *p_self);
-godot_rect3 GDAPI godot_variant_as_rect3(const godot_variant *p_self);
+godot_aabb GDAPI godot_variant_as_aabb(const godot_variant *p_self);
godot_basis GDAPI godot_variant_as_basis(const godot_variant *p_self);
godot_transform GDAPI godot_variant_as_transform(const godot_variant *p_self);
godot_color GDAPI godot_variant_as_color(const godot_variant *p_self);
diff --git a/modules/gdnative/include/gdnative/vector2.h b/modules/gdnative/include/gdnative/vector2.h
index 0af4abae27..07105abaf2 100644
--- a/modules/gdnative/include/gdnative/vector2.h
+++ b/modules/gdnative/include/gdnative/vector2.h
@@ -45,8 +45,17 @@ typedef struct {
} godot_vector2;
#endif
+// reduce extern "C" nesting for VS2013
+#ifdef __cplusplus
+}
+#endif
+
#include <gdnative/gdnative.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
void GDAPI godot_vector2_new(godot_vector2 *r_dest, const godot_real p_x, const godot_real p_y);
godot_string GDAPI godot_vector2_as_string(const godot_vector2 *p_self);
diff --git a/modules/gdnative/include/gdnative/vector3.h b/modules/gdnative/include/gdnative/vector3.h
index a27d516ec5..3ed23778ec 100644
--- a/modules/gdnative/include/gdnative/vector3.h
+++ b/modules/gdnative/include/gdnative/vector3.h
@@ -45,9 +45,18 @@ typedef struct {
} godot_vector3;
#endif
+// reduce extern "C" nesting for VS2013
+#ifdef __cplusplus
+}
+#endif
+
#include <gdnative/basis.h>
#include <gdnative/gdnative.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
typedef enum {
GODOT_VECTOR3_AXIS_X,
GODOT_VECTOR3_AXIS_Y,
diff --git a/modules/gdnative/include/pluginscript/godot_pluginscript.h b/modules/gdnative/include/pluginscript/godot_pluginscript.h
new file mode 100644
index 0000000000..d1c210529c
--- /dev/null
+++ b/modules/gdnative/include/pluginscript/godot_pluginscript.h
@@ -0,0 +1,171 @@
+/*************************************************************************/
+/* godot_nativescript.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#ifndef GODOT_PLUGINSCRIPT_H
+#define GODOT_PLUGINSCRIPT_H
+
+#include <gdnative/gdnative.h>
+#include <nativescript/godot_nativescript.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void godot_pluginscript_instance_data;
+typedef void godot_pluginscript_script_data;
+typedef void godot_pluginscript_language_data;
+
+// --- Instance ---
+
+// TODO: use godot_string_name for faster lookup ?
+typedef struct {
+ godot_pluginscript_instance_data *(*init)(godot_pluginscript_script_data *p_data, godot_object *p_owner);
+ void (*finish)(godot_pluginscript_instance_data *p_data);
+
+ godot_bool (*set_prop)(godot_pluginscript_instance_data *p_data, const godot_string *p_name, const godot_variant *p_value);
+ godot_bool (*get_prop)(godot_pluginscript_instance_data *p_data, const godot_string *p_name, godot_variant *r_ret);
+
+ godot_variant (*call_method)(godot_pluginscript_instance_data *p_data,
+ const godot_string_name *p_method, const godot_variant **p_args,
+ int p_argcount, godot_variant_call_error *r_error);
+
+ void (*notification)(godot_pluginscript_instance_data *p_data, int p_notification);
+ // TODO: could this rpc mode stuff be moved to the godot_pluginscript_script_manifest ?
+ godot_method_rpc_mode (*get_rpc_mode)(godot_pluginscript_instance_data *p_data, const godot_string *p_method);
+ godot_method_rpc_mode (*get_rset_mode)(godot_pluginscript_instance_data *p_data, const godot_string *p_variable);
+
+ //this is used by script languages that keep a reference counter of their own
+ //you can make make Ref<> not die when it reaches zero, so deleting the reference
+ //depends entirely from the script.
+ // Note: You can set thoses function pointer to NULL if not needed.
+ void (*refcount_incremented)(godot_pluginscript_instance_data *p_data);
+ bool (*refcount_decremented)(godot_pluginscript_instance_data *p_data); // return true if it can die
+} godot_pluginscript_instance_desc;
+
+// --- Script ---
+
+typedef struct {
+ godot_pluginscript_script_data *data;
+ godot_string_name name;
+ godot_bool is_tool;
+ godot_string_name base;
+
+ // Member lines format: {<string>: <int>}
+ godot_dictionary member_lines;
+ // Method info dictionary format
+ // {
+ // name: <string>
+ // args: [<dict:property>]
+ // default_args: [<variant>]
+ // return: <dict:property>
+ // flags: <int>
+ // rpc_mode: <int:godot_method_rpc_mode>
+ // }
+ godot_array methods;
+ // Same format than for methods
+ godot_array signals;
+ // Property info dictionary format
+ // {
+ // name: <string>
+ // type: <int:godot_variant_type>
+ // hint: <int:godot_property_hint>
+ // hint_string: <string>
+ // usage: <int:godot_property_usage_flags>
+ // default_value: <variant>
+ // rset_mode: <int:godot_method_rpc_mode>
+ // }
+ godot_array properties;
+} godot_pluginscript_script_manifest;
+
+typedef struct {
+ godot_pluginscript_script_manifest (*init)(godot_pluginscript_language_data *p_data, const godot_string *p_path, const godot_string *p_source, godot_error *r_error);
+ void (*finish)(godot_pluginscript_script_data *p_data);
+ godot_pluginscript_instance_desc instance_desc;
+} godot_pluginscript_script_desc;
+
+// --- Language ---
+
+typedef struct {
+ godot_string_name signature;
+ godot_int call_count;
+ godot_int total_time; // In microseconds
+ godot_int self_time; // In microseconds
+} godot_pluginscript_profiling_data;
+
+typedef struct {
+ const char *name;
+ const char *type;
+ const char *extension;
+ const char **recognized_extensions; // NULL terminated array
+ godot_pluginscript_language_data *(*init)();
+ void (*finish)(godot_pluginscript_language_data *p_data);
+ const char **reserved_words; // NULL terminated array
+ const char **comment_delimiters; // NULL terminated array
+ const char **string_delimiters; // NULL terminated array
+ godot_bool has_named_classes;
+ godot_bool supports_builtin_mode;
+
+ godot_string (*get_template_source_code)(godot_pluginscript_language_data *p_data, const godot_string *p_class_name, const godot_string *p_base_class_name);
+ godot_bool (*validate)(godot_pluginscript_language_data *p_data, const godot_string *p_script, int *r_line_error, int *r_col_error, godot_string *r_test_error, const godot_string *p_path, godot_pool_string_array *r_functions);
+ int (*find_function)(godot_pluginscript_language_data *p_data, const godot_string *p_function, const godot_string *p_code); // Can be NULL
+ godot_string (*make_function)(godot_pluginscript_language_data *p_data, const godot_string *p_class, const godot_string *p_name, const godot_pool_string_array *p_args);
+ godot_error (*complete_code)(godot_pluginscript_language_data *p_data, const godot_string *p_code, const godot_string *p_base_path, godot_object *p_owner, godot_array *r_options, godot_bool *r_force, godot_string *r_call_hint);
+ void (*auto_indent_code)(godot_pluginscript_language_data *p_data, godot_string *p_code, int p_from_line, int p_to_line);
+
+ void (*add_global_constant)(godot_pluginscript_language_data *p_data, const godot_string *p_variable, const godot_variant *p_value);
+ godot_string (*debug_get_error)(godot_pluginscript_language_data *p_data);
+ int (*debug_get_stack_level_count)(godot_pluginscript_language_data *p_data);
+ int (*debug_get_stack_level_line)(godot_pluginscript_language_data *p_data, int p_level);
+ godot_string (*debug_get_stack_level_function)(godot_pluginscript_language_data *p_data, int p_level);
+ godot_string (*debug_get_stack_level_source)(godot_pluginscript_language_data *p_data, int p_level);
+ void (*debug_get_stack_level_locals)(godot_pluginscript_language_data *p_data, int p_level, godot_pool_string_array *p_locals, godot_array *p_values, int p_max_subitems, int p_max_depth);
+ void (*debug_get_stack_level_members)(godot_pluginscript_language_data *p_data, int p_level, godot_pool_string_array *p_members, godot_array *p_values, int p_max_subitems, int p_max_depth);
+ void (*debug_get_globals)(godot_pluginscript_language_data *p_data, godot_pool_string_array *p_locals, godot_array *p_values, int p_max_subitems, int p_max_depth);
+ godot_string (*debug_parse_stack_level_expression)(godot_pluginscript_language_data *p_data, int p_level, const godot_string *p_expression, int p_max_subitems, int p_max_depth);
+
+ // TODO: could this stuff be moved to the godot_pluginscript_language_desc ?
+ void (*get_public_functions)(godot_pluginscript_language_data *p_data, godot_array *r_functions);
+ void (*get_public_constants)(godot_pluginscript_language_data *p_data, godot_dictionary *r_constants);
+
+ void (*profiling_start)(godot_pluginscript_language_data *p_data);
+ void (*profiling_stop)(godot_pluginscript_language_data *p_data);
+ int (*profiling_get_accumulated_data)(godot_pluginscript_language_data *p_data, godot_pluginscript_profiling_data *r_info, int p_info_max);
+ int (*profiling_get_frame_data)(godot_pluginscript_language_data *p_data, godot_pluginscript_profiling_data *r_info, int p_info_max);
+ void (*profiling_frame)(godot_pluginscript_language_data *p_data);
+
+ godot_pluginscript_script_desc script_desc;
+} godot_pluginscript_language_desc;
+
+void GDAPI godot_pluginscript_register_language(const godot_pluginscript_language_desc *language_desc);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // GODOT_PLUGINSCRIPT_H
diff --git a/modules/gdnative/nativescript/SCsub b/modules/gdnative/nativescript/SCsub
index 178afec64a..ee3b9c351d 100644
--- a/modules/gdnative/nativescript/SCsub
+++ b/modules/gdnative/nativescript/SCsub
@@ -4,7 +4,6 @@ Import('env')
mod_env = env.Clone()
mod_env.add_source_files(env.modules_sources, "*.cpp")
-mod_env.Append(CPPPATH='#modules/gdnative')
mod_env.Append(CPPFLAGS=['-DGDAPI_BUILT_IN'])
if "platform" in env and env["platform"] in ["x11", "iphone"]:
diff --git a/modules/gdnative/nativescript/api_generator.cpp b/modules/gdnative/nativescript/api_generator.cpp
index fdd5a2ea19..f9d699fb59 100644
--- a/modules/gdnative/nativescript/api_generator.cpp
+++ b/modules/gdnative/nativescript/api_generator.cpp
@@ -31,10 +31,10 @@
#ifdef TOOLS_ENABLED
-#include "class_db.h"
+#include "core/class_db.h"
+#include "core/engine.h"
#include "core/global_constants.h"
#include "core/pair.h"
-#include "core/project_settings.h"
#include "os/file_access.h"
// helper stuff
@@ -80,6 +80,7 @@ struct PropertyAPI {
String getter;
String setter;
String type;
+ int index;
};
struct ConstantAPI {
@@ -176,7 +177,7 @@ List<ClassAPI> generate_c_api_classes() {
if (name.begins_with("_")) {
name.remove(0);
}
- class_api.is_singleton = ProjectSettings::get_singleton()->has_singleton(name);
+ class_api.is_singleton = Engine::get_singleton()->has_singleton(name);
}
class_api.is_instanciable = !class_api.is_singleton && ClassDB::can_instance(class_name);
@@ -259,6 +260,8 @@ List<ClassAPI> generate_c_api_classes() {
property_api.type = get_type_name(p->get());
}
+ property_api.index = ClassDB::get_property_index(class_name, p->get().name);
+
if (!property_api.setter.empty() || !property_api.getter.empty()) {
class_api.properties.push_back(property_api);
}
@@ -395,7 +398,8 @@ static List<String> generate_c_api_json(const List<ClassAPI> &p_api) {
source.push_back("\t\t\t\t\"name\": \"" + e->get().name + "\",\n");
source.push_back("\t\t\t\t\"type\": \"" + e->get().type + "\",\n");
source.push_back("\t\t\t\t\"getter\": \"" + e->get().getter + "\",\n");
- source.push_back("\t\t\t\t\"setter\": \"" + e->get().setter + "\"\n");
+ source.push_back("\t\t\t\t\"setter\": \"" + e->get().setter + "\",\n");
+ source.push_back(String("\t\t\t\t\"index\": ") + itos(e->get().index) + "\n");
source.push_back(String("\t\t\t}") + (e->next() ? "," : "") + "\n");
}
source.push_back("\t\t],\n");
diff --git a/modules/gdnative/nativescript/api_generator.h b/modules/gdnative/nativescript/api_generator.h
index 56c2d786e6..a8e2eaf0bf 100644
--- a/modules/gdnative/nativescript/api_generator.h
+++ b/modules/gdnative/nativescript/api_generator.h
@@ -30,8 +30,8 @@
#ifndef API_GENERATOR_H
#define API_GENERATOR_H
+#include "core/typedefs.h"
#include "core/ustring.h"
-#include "typedefs.h"
Error generate_c_api(const String &p_path);
diff --git a/modules/gdnative/nativescript/nativescript.cpp b/modules/gdnative/nativescript/nativescript.cpp
index b9bd65af53..c2c7c27f25 100644
--- a/modules/gdnative/nativescript/nativescript.cpp
+++ b/modules/gdnative/nativescript/nativescript.cpp
@@ -31,15 +31,17 @@
#include "gdnative/gdnative.h"
-#include "global_constants.h"
+#include "core/global_constants.h"
+#include "core/project_settings.h"
#include "io/file_access_encrypted.h"
#include "os/file_access.h"
#include "os/os.h"
-#include "project_settings.h"
#include "scene/main/scene_tree.h"
#include "scene/resources/scene_format_text.h"
+#include <stdlib.h>
+
#ifndef NO_THREADS
#include "os/thread.h"
#endif
@@ -52,7 +54,11 @@
#include "editor/editor_node.h"
#endif
-////// Script stuff
+//
+//
+// Script stuff
+//
+//
void NativeScript::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_class_name", "class_name"), &NativeScript::set_class_name);
@@ -108,7 +114,7 @@ void NativeScript::set_library(Ref<GDNativeLibrary> p_library) {
return;
}
library = p_library;
- lib_path = library->get_active_library_path();
+ lib_path = library->get_current_library_path();
#ifndef NO_THREADS
if (Thread::get_caller_id() != Thread::get_main_id()) {
@@ -137,7 +143,6 @@ bool NativeScript::can_instance() const {
#endif
}
-// TODO(karroffel): implement this
Ref<Script> NativeScript::get_base_script() const {
NativeScriptDesc *script_data = get_script_desc();
@@ -271,10 +276,6 @@ bool NativeScript::is_tool() const {
return false;
}
-String NativeScript::get_node_type() const {
- return ""; // NOTE(karroffel): uhm?
-}
-
ScriptLanguage *NativeScript::get_language() const {
return NativeScriptLanguage::get_singleton();
}
@@ -419,7 +420,6 @@ Variant NativeScript::_new(const Variant **p_args, int p_argcount, Variant::Call
}
}
-// TODO(karroffel): implement this
NativeScript::NativeScript() {
library = Ref<GDNative>();
lib_path = "";
@@ -429,7 +429,6 @@ NativeScript::NativeScript() {
#endif
}
-// TODO(karroffel): implement this
NativeScript::~NativeScript() {
NSL->unregister_script(this);
@@ -438,7 +437,11 @@ NativeScript::~NativeScript() {
#endif
}
-////// ScriptInstance stuff
+//
+//
+// ScriptInstance stuff
+//
+//
#define GET_SCRIPT_DESC() script->get_script_desc()
@@ -696,7 +699,6 @@ NativeScriptInstance::RPCMode NativeScriptInstance::get_rpc_mode(const StringNam
return RPC_MODE_DISABLED;
}
-// TODO(karroffel): implement this
NativeScriptInstance::RPCMode NativeScriptInstance::get_rset_mode(const StringName &p_variable) const {
NativeScriptDesc *script_data = GET_SCRIPT_DESC();
@@ -779,15 +781,14 @@ NativeScriptInstance::~NativeScriptInstance() {
}
}
-////// ScriptingLanguage stuff
+//
+//
+// ScriptingLanguage stuff
+//
+//
NativeScriptLanguage *NativeScriptLanguage::singleton;
-extern "C" void _native_script_hook();
-void NativeScriptLanguage::_hacky_api_anchor() {
- _native_script_hook();
-}
-
void NativeScriptLanguage::_unload_stuff() {
for (Map<String, Map<StringName, NativeScriptDesc> >::Element *L = library_classes.front(); L; L = L->next()) {
for (Map<StringName, NativeScriptDesc>::Element *C = L->get().front(); C; C = C->next()) {
@@ -824,9 +825,7 @@ NativeScriptLanguage::NativeScriptLanguage() {
#endif
}
-// TODO(karroffel): implement this
NativeScriptLanguage::~NativeScriptLanguage() {
- // _unload_stuff(); // NOTE(karroffel): This gets called in ::finish()
for (Map<String, Ref<GDNative> >::Element *L = NSL->library_gdnatives.front(); L; L = L->next()) {
@@ -852,7 +851,6 @@ void _add_reload_node() {
#endif
}
-// TODO(karroffel): implement this
void NativeScriptLanguage::init() {
#if defined(TOOLS_ENABLED) && defined(DEBUG_METHODS_ENABLED)
@@ -865,6 +863,7 @@ void NativeScriptLanguage::init() {
if (generate_c_api(E->next()->get()) != OK) {
ERR_PRINT("Failed to generate C API\n");
}
+ exit(0);
}
#endif
@@ -891,11 +890,9 @@ void NativeScriptLanguage::get_comment_delimiters(List<String> *p_delimiters) co
void NativeScriptLanguage::get_string_delimiters(List<String> *p_delimiters) const {
}
-// TODO(karroffel): implement this
Ref<Script> NativeScriptLanguage::get_template(const String &p_class_name, const String &p_base_class_name) const {
NativeScript *s = memnew(NativeScript);
s->set_class_name(p_class_name);
- // TODO(karroffel): use p_base_class_name
return Ref<NativeScript>(s);
}
bool NativeScriptLanguage::validate(const String &p_script, int &r_line_error, int &r_col_error, String &r_test_error, const String &p_path, List<String> *r_functions) const {
@@ -909,6 +906,9 @@ Script *NativeScriptLanguage::create_script() const {
bool NativeScriptLanguage::has_named_classes() const {
return true;
}
+bool NativeScriptLanguage::supports_builtin_mode() const {
+ return true;
+}
int NativeScriptLanguage::find_function(const String &p_function, const String &p_code) const {
return -1;
}
@@ -990,7 +990,7 @@ void NativeScriptLanguage::init_library(const Ref<GDNativeLibrary> &lib) {
MutexLock lock(mutex);
#endif
// See if this library was "registered" already.
- const String &lib_path = lib->get_active_library_path();
+ const String &lib_path = lib->get_current_library_path();
ERR_EXPLAIN(lib->get_name() + " does not have a library for the current platform");
ERR_FAIL_COND(lib_path.length() == 0);
Map<String, Ref<GDNative> >::Element *E = library_gdnatives.find(lib_path);
@@ -1000,7 +1000,7 @@ void NativeScriptLanguage::init_library(const Ref<GDNativeLibrary> &lib) {
gdn.instance();
gdn->set_library(lib);
- // TODO(karroffel): check the return value?
+ // TODO check the return value?
gdn->initialize();
library_gdnatives.insert(lib_path, gdn);
@@ -1010,17 +1010,15 @@ void NativeScriptLanguage::init_library(const Ref<GDNativeLibrary> &lib) {
if (!library_script_users.has(lib_path))
library_script_users.insert(lib_path, Set<NativeScript *>());
- void *args[1] = {
- (void *)&lib_path
- };
+ void *proc_ptr;
+
+ Error err = gdn->get_symbol(lib->get_symbol_prefix() + _init_call_name, proc_ptr);
- // here the library registers all the classes and stuff.
- gdn->call_native_raw(_init_call_type,
- _init_call_name,
- NULL,
- 1,
- args,
- NULL);
+ if (err != OK) {
+ ERR_PRINT(String("No " + _init_call_name + " in \"" + lib_path + "\" found").utf8().get_data());
+ } else {
+ ((void (*)(godot_string *))proc_ptr)((godot_string *)&lib_path);
+ }
} else {
// already initialized. Nice.
}
@@ -1053,13 +1051,13 @@ void NativeScriptLanguage::call_libraries_cb(const StringName &name) {
// library_gdnatives is modified only from the main thread, so it's safe not to use mutex here
for (Map<String, Ref<GDNative> >::Element *L = library_gdnatives.front(); L; L = L->next()) {
if (L->get()->is_initialized()) {
- L->get()->call_native_raw(
- _noarg_call_type,
- name,
- NULL,
- 0,
- NULL,
- NULL);
+
+ void *proc_ptr;
+ Error err = L->get()->get_symbol(L->get()->get_library()->get_symbol_prefix() + name, proc_ptr);
+
+ if (!err) {
+ ((void (*)())proc_ptr)();
+ }
}
}
}
@@ -1142,12 +1140,14 @@ void NativeReloadNode::_notification(int p_what) {
};
// here the library registers all the classes and stuff.
- L->get()->call_native_raw(NSL->_init_call_type,
- NSL->_init_call_name,
- NULL,
- 1,
- args,
- NULL);
+
+ void *proc_ptr;
+ Error err = L->get()->get_symbol(L->get()->get_library()->get_symbol_prefix() + "nativescript_init", proc_ptr);
+ if (err != OK) {
+ ERR_PRINT(String("No godot_nativescript_init in \"" + L->key() + "\" found").utf8().get_data());
+ } else {
+ ((void (*)(void *))proc_ptr)((void *)&L->key());
+ }
for (Map<String, Set<NativeScript *> >::Element *U = NSL->library_script_users.front(); U; U = U->next()) {
for (Set<NativeScript *>::Element *S = U->get().front(); S; S = S->next()) {
diff --git a/modules/gdnative/nativescript/nativescript.h b/modules/gdnative/nativescript/nativescript.h
index bc7e850d3e..f0f14e2f30 100644
--- a/modules/gdnative/nativescript/nativescript.h
+++ b/modules/gdnative/nativescript/nativescript.h
@@ -30,14 +30,14 @@
#ifndef NATIVE_SCRIPT_H
#define NATIVE_SCRIPT_H
+#include "core/resource.h"
+#include "core/script_language.h"
+#include "core/self_list.h"
#include "io/resource_loader.h"
#include "io/resource_saver.h"
#include "ordered_hash_map.h"
#include "os/thread_safe.h"
-#include "resource.h"
#include "scene/main/node.h"
-#include "script_language.h"
-#include "self_list.h"
#include "modules/gdnative/gdnative.h"
#include <nativescript/godot_nativescript.h>
@@ -142,8 +142,6 @@ public:
virtual bool is_tool() const;
- virtual String get_node_type() const;
-
virtual ScriptLanguage *get_language() const;
virtual bool has_script_signal(const StringName &p_signal) const;
@@ -231,15 +229,15 @@ public:
Map<String, Set<NativeScript *> > library_script_users;
const StringName _init_call_type = "nativescript_init";
- const StringName _init_call_name = "godot_nativescript_init";
+ const StringName _init_call_name = "nativescript_init";
const StringName _noarg_call_type = "nativescript_no_arg";
- const StringName _frame_call_name = "godot_nativescript_frame";
+ const StringName _frame_call_name = "nativescript_frame";
#ifndef NO_THREADS
- const StringName _thread_enter_call_name = "godot_nativescript_thread_enter";
- const StringName _thread_exit_call_name = "godot_nativescript_thread_exit";
+ const StringName _thread_enter_call_name = "nativescript_thread_enter";
+ const StringName _thread_exit_call_name = "nativescript_thread_exit";
#endif
NativeScriptLanguage();
@@ -271,6 +269,7 @@ public:
virtual bool validate(const String &p_script, int &r_line_error, int &r_col_error, String &r_test_error, const String &p_path, List<String> *r_functions) const;
virtual Script *create_script() const;
virtual bool has_named_classes() const;
+ virtual bool supports_builtin_mode() const;
virtual int find_function(const String &p_function, const String &p_code) const;
virtual String make_function(const String &p_class, const String &p_name, const PoolStringArray &p_args) const;
virtual void auto_indent_code(String &p_code, int p_from_line, int p_to_line) const;
diff --git a/modules/gdnative/nativescript/register_types.cpp b/modules/gdnative/nativescript/register_types.cpp
index b846710ab8..d734bba810 100644
--- a/modules/gdnative/nativescript/register_types.cpp
+++ b/modules/gdnative/nativescript/register_types.cpp
@@ -38,53 +38,6 @@
NativeScriptLanguage *native_script_language;
-typedef void (*native_script_init_fn)(void *);
-
-void init_call_cb(void *p_handle, godot_string *p_proc_name, void *p_data, int p_num_args, void **args, void *r_ret) {
- if (p_handle == NULL) {
- ERR_PRINT("No valid library handle, can't call nativescript init procedure");
- return;
- }
-
- void *library_proc;
- Error err = OS::get_singleton()->get_dynamic_library_symbol_handle(
- p_handle,
- *(String *)p_proc_name,
- library_proc,
- true); // we print our own message
- if (err != OK) {
- ERR_PRINT((String("GDNative procedure \"" + *(String *)p_proc_name) + "\" does not exists and can't be called").utf8().get_data());
- return;
- }
-
- native_script_init_fn fn = (native_script_init_fn)library_proc;
-
- fn(args[0]);
-}
-
-typedef void (*native_script_empty_callback)();
-
-void noarg_call_cb(void *p_handle, godot_string *p_proc_name, void *p_data, int p_num_args, void **args, void *r_ret) {
- if (p_handle == NULL) {
- ERR_PRINT("No valid library handle, can't call nativescript callback");
- return;
- }
-
- void *library_proc;
- Error err = OS::get_singleton()->get_dynamic_library_symbol_handle(
- p_handle,
- *(String *)p_proc_name,
- library_proc,
- true);
- if (err != OK) {
- // it's fine if thread callbacks are not present in the library.
- return;
- }
-
- native_script_empty_callback fn = (native_script_empty_callback)library_proc;
- fn();
-}
-
ResourceFormatLoaderNativeScript *resource_loader_gdns = NULL;
ResourceFormatSaverNativeScript *resource_saver_gdns = NULL;
@@ -95,9 +48,6 @@ void register_nativescript_types() {
ScriptServer::register_language(native_script_language);
- GDNativeCallRegistry::singleton->register_native_raw_call_type(native_script_language->_init_call_type, init_call_cb);
- GDNativeCallRegistry::singleton->register_native_raw_call_type(native_script_language->_noarg_call_type, noarg_call_cb);
-
resource_saver_gdns = memnew(ResourceFormatSaverNativeScript);
ResourceSaver::add_resource_format_saver(resource_saver_gdns);
diff --git a/modules/gdnative/pluginscript/SCsub b/modules/gdnative/pluginscript/SCsub
new file mode 100644
index 0000000000..2031a4236b
--- /dev/null
+++ b/modules/gdnative/pluginscript/SCsub
@@ -0,0 +1,9 @@
+#!/usr/bin/env python
+
+Import('env')
+Import('env_modules')
+
+env_pluginscript = env_modules.Clone()
+
+env_pluginscript.Append(CPPPATH=['#modules/gdnative/include/'])
+env_pluginscript.add_source_files(env.modules_sources, '*.cpp')
diff --git a/modules/gdnative/pluginscript/pluginscript_instance.cpp b/modules/gdnative/pluginscript/pluginscript_instance.cpp
new file mode 100644
index 0000000000..8f01350826
--- /dev/null
+++ b/modules/gdnative/pluginscript/pluginscript_instance.cpp
@@ -0,0 +1,181 @@
+/*************************************************************************/
+/* pluginscript_instance.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 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. */
+/*************************************************************************/
+
+// Godot imports
+#include "core/os/os.h"
+#include "core/variant.h"
+// PluginScript imports
+#include "pluginscript_instance.h"
+#include "pluginscript_language.h"
+#include "pluginscript_script.h"
+
+bool PluginScriptInstance::set(const StringName &p_name, const Variant &p_value) {
+ String name = String(p_name);
+ return _desc->set_prop(_data, (const godot_string *)&name, (const godot_variant *)&p_value);
+}
+
+bool PluginScriptInstance::get(const StringName &p_name, Variant &r_ret) const {
+ String name = String(p_name);
+ return _desc->get_prop(_data, (const godot_string *)&name, (godot_variant *)&r_ret);
+}
+
+Ref<Script> PluginScriptInstance::get_script() const {
+ return _script;
+}
+
+ScriptLanguage *PluginScriptInstance::get_language() {
+ return _script->get_language();
+}
+
+Variant::Type PluginScriptInstance::get_property_type(const StringName &p_name, bool *r_is_valid) const {
+ if (!_script->has_property(p_name)) {
+ if (r_is_valid) {
+ *r_is_valid = false;
+ }
+ return Variant::NIL;
+ }
+ if (r_is_valid) {
+ *r_is_valid = true;
+ }
+ return _script->get_property_info(p_name).type;
+}
+
+void PluginScriptInstance::get_property_list(List<PropertyInfo> *p_properties) const {
+ _script->get_script_property_list(p_properties);
+}
+
+void PluginScriptInstance::get_method_list(List<MethodInfo> *p_list) const {
+ _script->get_script_method_list(p_list);
+}
+
+bool PluginScriptInstance::has_method(const StringName &p_method) const {
+ return _script->has_method(p_method);
+}
+
+Variant PluginScriptInstance::call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error) {
+ // TODO: optimize when calling a Godot method from Godot to avoid param conversion ?
+ godot_variant ret = _desc->call_method(
+ _data, (godot_string_name *)&p_method, (const godot_variant **)p_args,
+ p_argcount, (godot_variant_call_error *)&r_error);
+ Variant *var_ret = (Variant *)&ret;
+ return *var_ret;
+}
+
+#if 0 // TODO: Don't rely on default implementations provided by ScriptInstance ?
+void PluginScriptInstance::call_multilevel(const StringName& p_method,const Variant** p_args,int p_argcount) {
+
+#if 0
+ PluginScript *sptr=script.ptr();
+ Variant::CallError ce;
+
+ while(sptr) {
+ Map<StringName,GDFunction*>::Element *E = sptr->member_functions.find(p_method);
+ if (E) {
+ E->get()->call(this,p_args,p_argcount,ce);
+ }
+ sptr = sptr->_base;
+ }
+#endif
+
+}
+
+#if 0
+void PluginScriptInstance::_ml_call_reversed(PluginScript *sptr,const StringName& p_method,const Variant** p_args,int p_argcount) {
+
+ if (sptr->_base)
+ _ml_call_reversed(sptr->_base,p_method,p_args,p_argcount);
+
+ Variant::CallError ce;
+
+ Map<StringName,GDFunction*>::Element *E = sptr->member_functions.find(p_method);
+ if (E) {
+ E->get()->call(this,p_args,p_argcount,ce);
+ }
+
+}
+#endif
+
+
+void PluginScriptInstance::call_multilevel_reversed(const StringName& p_method,const Variant** p_args,int p_argcount) {
+
+#if 0
+ if (script.ptr()) {
+ _ml_call_reversed(script.ptr(),p_method,p_args,p_argcount);
+ }
+#endif
+}
+#endif // Multilevel stuff
+
+void PluginScriptInstance::notification(int p_notification) {
+ _desc->notification(_data, p_notification);
+}
+
+ScriptInstance::RPCMode PluginScriptInstance::get_rpc_mode(const StringName &p_method) const {
+ return _script->get_rpc_mode(p_method);
+}
+
+ScriptInstance::RPCMode PluginScriptInstance::get_rset_mode(const StringName &p_variable) const {
+ return _script->get_rset_mode(p_variable);
+}
+
+void PluginScriptInstance::refcount_incremented() {
+ if (_desc->refcount_decremented) {
+ _desc->refcount_incremented(_data);
+ }
+}
+
+bool PluginScriptInstance::refcount_decremented() {
+ // Return true if it can die
+ if (_desc->refcount_decremented) {
+ return _desc->refcount_decremented(_data);
+ }
+ return true;
+}
+
+PluginScriptInstance::PluginScriptInstance() {
+}
+
+bool PluginScriptInstance::init(PluginScript *p_script, Object *p_owner) {
+ _owner = p_owner;
+ _owner_variant = Variant(p_owner);
+ _script = Ref<PluginScript>(p_script);
+ _desc = &p_script->_desc->instance_desc;
+ _data = _desc->init(p_script->_data, (godot_object *)p_owner);
+ ERR_FAIL_COND_V(_data == NULL, false);
+ p_owner->set_script_instance(this);
+ return true;
+}
+
+PluginScriptInstance::~PluginScriptInstance() {
+ _desc->finish(_data);
+ _script->_language->lock();
+ _script->_instances.erase(_owner);
+ _script->_language->unlock();
+}
diff --git a/modules/gdnative/pluginscript/pluginscript_instance.h b/modules/gdnative/pluginscript/pluginscript_instance.h
new file mode 100644
index 0000000000..68696b4417
--- /dev/null
+++ b/modules/gdnative/pluginscript/pluginscript_instance.h
@@ -0,0 +1,90 @@
+/*************************************************************************/
+/* pluginscript_instance.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef PLUGINSCRIPT_INSTANCE_H
+#define PLUGINSCRIPT_INSTANCE_H
+
+// Godot imports
+#include "core/script_language.h"
+// PluginScript imports
+#include <pluginscript/godot_pluginscript.h>
+
+class PluginScript;
+
+class PluginScriptInstance : public ScriptInstance {
+ friend class PluginScript;
+
+private:
+ Ref<PluginScript> _script;
+ Object *_owner;
+ Variant _owner_variant;
+ godot_pluginscript_instance_data *_data;
+ const godot_pluginscript_instance_desc *_desc;
+
+public:
+ _FORCE_INLINE_ Object *get_owner() { return _owner; }
+
+ virtual bool set(const StringName &p_name, const Variant &p_value);
+ virtual bool get(const StringName &p_name, Variant &r_ret) const;
+ virtual void get_property_list(List<PropertyInfo> *p_properties) const;
+ virtual Variant::Type get_property_type(const StringName &p_name, bool *r_is_valid = NULL) const;
+
+ virtual void get_method_list(List<MethodInfo> *p_list) const;
+ virtual bool has_method(const StringName &p_method) const;
+
+ virtual Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error);
+#if 0
+ // Rely on default implementations provided by ScriptInstance for the moment.
+ // Note that multilevel call could be removed in 3.0 release, so stay tunned
+ // (see https://godotengine.org/qa/9244/can-override-the-_ready-and-_process-functions-child-classes)
+ virtual void call_multilevel(const StringName& p_method,const Variant** p_args,int p_argcount);
+ virtual void call_multilevel_reversed(const StringName& p_method,const Variant** p_args,int p_argcount);
+#endif
+
+ virtual void notification(int p_notification);
+
+ virtual Ref<Script> get_script() const;
+
+ virtual ScriptLanguage *get_language();
+
+ void set_path(const String &p_path);
+
+ virtual RPCMode get_rpc_mode(const StringName &p_method) const;
+ virtual RPCMode get_rset_mode(const StringName &p_variable) const;
+
+ virtual void refcount_incremented();
+ virtual bool refcount_decremented();
+
+ PluginScriptInstance();
+ bool init(PluginScript *p_script, Object *p_owner);
+ virtual ~PluginScriptInstance();
+};
+
+#endif // PLUGINSCRIPT_INSTANCE_H
diff --git a/modules/gdnative/pluginscript/pluginscript_language.cpp b/modules/gdnative/pluginscript/pluginscript_language.cpp
new file mode 100644
index 0000000000..40feb5ae43
--- /dev/null
+++ b/modules/gdnative/pluginscript/pluginscript_language.cpp
@@ -0,0 +1,435 @@
+/*************************************************************************/
+/* pluginscript_language.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 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. */
+/*************************************************************************/
+
+// Godot imports
+#include "core/os/file_access.h"
+#include "core/os/os.h"
+#include "core/project_settings.h"
+// PluginScript imports
+#include "pluginscript_language.h"
+#include "pluginscript_script.h"
+
+String PluginScriptLanguage::get_name() const {
+ return String(_desc.name);
+}
+
+void PluginScriptLanguage::init() {
+ _data = _desc.init();
+}
+
+String PluginScriptLanguage::get_type() const {
+ return String(_desc.type);
+}
+
+String PluginScriptLanguage::get_extension() const {
+ return String(_desc.extension);
+}
+
+Error PluginScriptLanguage::execute_file(const String &p_path) {
+ // TODO: pretty sure this method is totally deprecated and should be removed...
+ return OK;
+}
+
+void PluginScriptLanguage::finish() {
+ _desc.finish(_data);
+}
+
+/* EDITOR FUNCTIONS */
+
+void PluginScriptLanguage::get_reserved_words(List<String> *p_words) const {
+ if (_desc.reserved_words) {
+ const char **w = _desc.reserved_words;
+ while (*w) {
+ p_words->push_back(*w);
+ w++;
+ }
+ }
+}
+
+void PluginScriptLanguage::get_comment_delimiters(List<String> *p_delimiters) const {
+ if (_desc.comment_delimiters) {
+ const char **w = _desc.comment_delimiters;
+ while (*w) {
+ p_delimiters->push_back(*w);
+ w++;
+ }
+ }
+}
+
+void PluginScriptLanguage::get_string_delimiters(List<String> *p_delimiters) const {
+ if (_desc.string_delimiters) {
+ const char **w = _desc.string_delimiters;
+ while (*w) {
+ p_delimiters->push_back(*w);
+ w++;
+ }
+ }
+}
+
+Ref<Script> PluginScriptLanguage::get_template(const String &p_class_name, const String &p_base_class_name) const {
+ Script *ns = create_script();
+ Ref<Script> script = Ref<Script>(ns);
+ if (_desc.get_template_source_code) {
+ godot_string src = _desc.get_template_source_code(_data, (godot_string *)&p_class_name, (godot_string *)&p_base_class_name);
+ script->set_source_code(*(String *)&src);
+ }
+ return script;
+}
+
+bool PluginScriptLanguage::validate(const String &p_script, int &r_line_error, int &r_col_error, String &r_test_error, const String &p_path, List<String> *r_functions) const {
+ PoolStringArray functions;
+ if (_desc.validate) {
+ bool ret = _desc.validate(
+ _data,
+ (godot_string *)&p_script,
+ &r_line_error,
+ &r_col_error,
+ (godot_string *)&r_test_error,
+ (godot_string *)&p_path,
+ (godot_pool_string_array *)&functions);
+ for (int i = 0; i < functions.size(); i++) {
+ r_functions->push_back(functions[i]);
+ }
+ return ret;
+ }
+ return true;
+}
+
+Script *PluginScriptLanguage::create_script() const {
+ PluginScript *script = memnew(PluginScript());
+ // I'm hurting kittens doing this I guess...
+ script->init(const_cast<PluginScriptLanguage *>(this));
+ return script;
+}
+
+bool PluginScriptLanguage::has_named_classes() const {
+ return _desc.has_named_classes;
+}
+
+bool PluginScriptLanguage::supports_builtin_mode() const {
+ return _desc.supports_builtin_mode;
+}
+
+int PluginScriptLanguage::find_function(const String &p_function, const String &p_code) const {
+ if (_desc.find_function) {
+ return _desc.find_function(_data, (godot_string *)&p_function, (godot_string *)&p_code);
+ }
+ return -1;
+}
+
+String PluginScriptLanguage::make_function(const String &p_class, const String &p_name, const PoolStringArray &p_args) const {
+ if (_desc.make_function) {
+ godot_string tmp = _desc.make_function(_data, (godot_string *)&p_class, (godot_string *)&p_name, (godot_pool_string_array *)&p_args);
+ String ret = *(String *)&tmp;
+ godot_string_destroy(&tmp);
+ return ret;
+ }
+ return String();
+}
+
+Error PluginScriptLanguage::complete_code(const String &p_code, const String &p_base_path, Object *p_owner, List<String> *r_options, bool &r_force, String &r_call_hint) {
+ if (_desc.complete_code) {
+ Array options;
+ godot_error tmp = _desc.complete_code(
+ _data,
+ (godot_string *)&p_code,
+ (godot_string *)&p_base_path,
+ (godot_object *)p_owner,
+ (godot_array *)&options,
+ &r_force,
+ (godot_string *)&r_call_hint);
+ for (int i = 0; i < options.size(); i++) {
+ r_options->push_back(String(options[i]));
+ }
+ Error err = *(Error *)tmp;
+ return err;
+ }
+ return ERR_UNAVAILABLE;
+}
+
+void PluginScriptLanguage::auto_indent_code(String &p_code, int p_from_line, int p_to_line) const {
+ if (_desc.auto_indent_code) {
+ _desc.auto_indent_code(_data, (godot_string *)&p_code, p_from_line, p_to_line);
+ }
+ return;
+}
+
+void PluginScriptLanguage::add_global_constant(const StringName &p_variable, const Variant &p_value) {
+ const String variable = String(p_variable);
+ _desc.add_global_constant(_data, (godot_string *)&variable, (godot_variant *)&p_value);
+}
+
+/* LOADER FUNCTIONS */
+
+void PluginScriptLanguage::get_recognized_extensions(List<String> *p_extensions) const {
+ for (int i = 0; _desc.recognized_extensions[i]; ++i) {
+ p_extensions->push_back(String(_desc.recognized_extensions[i]));
+ }
+}
+
+void PluginScriptLanguage::get_public_functions(List<MethodInfo> *p_functions) const {
+ // TODO: provid this statically in `godot_pluginscript_language_desc` ?
+ if (_desc.get_public_functions) {
+ Array functions;
+ _desc.get_public_functions(_data, (godot_array *)&functions);
+ for (int i = 0; i < functions.size(); i++) {
+ MethodInfo mi = MethodInfo::from_dict(functions[i]);
+ p_functions->push_back(mi);
+ }
+ }
+}
+
+void PluginScriptLanguage::get_public_constants(List<Pair<String, Variant> > *p_constants) const {
+ // TODO: provid this statically in `godot_pluginscript_language_desc` ?
+ if (_desc.get_public_constants) {
+ Dictionary constants;
+ _desc.get_public_constants(_data, (godot_dictionary *)&constants);
+ for (const Variant *key = constants.next(); key; key = constants.next(key)) {
+ Variant value = constants[key];
+ p_constants->push_back(Pair<String, Variant>(*key, value));
+ }
+ }
+}
+
+void PluginScriptLanguage::profiling_start() {
+#ifdef DEBUG_ENABLED
+ if (_desc.profiling_start) {
+ lock();
+ _desc.profiling_start(_data);
+ unlock();
+ }
+#endif
+}
+
+void PluginScriptLanguage::profiling_stop() {
+#ifdef DEBUG_ENABLED
+ if (_desc.profiling_stop) {
+ lock();
+ _desc.profiling_stop(_data);
+ unlock();
+ }
+#endif
+}
+
+int PluginScriptLanguage::profiling_get_accumulated_data(ProfilingInfo *p_info_arr, int p_info_max) {
+ int info_count = 0;
+#ifdef DEBUG_ENABLED
+ if (_desc.profiling_get_accumulated_data) {
+ godot_pluginscript_profiling_data *info = (godot_pluginscript_profiling_data *)memalloc(
+ sizeof(godot_pluginscript_profiling_data) * p_info_max);
+ info_count = _desc.profiling_get_accumulated_data(_data, info, p_info_max);
+ for (int i = 0; i < info_count; ++i) {
+ p_info_arr[i].signature = *(StringName *)&info[i].signature;
+ p_info_arr[i].call_count = info[i].call_count;
+ p_info_arr[i].total_time = info[i].total_time;
+ p_info_arr[i].self_time = info[i].self_time;
+ godot_string_name_destroy(&info[i].signature);
+ }
+ }
+#endif
+ return info_count;
+}
+
+int PluginScriptLanguage::profiling_get_frame_data(ProfilingInfo *p_info_arr, int p_info_max) {
+ int info_count = 0;
+#ifdef DEBUG_ENABLED
+ if (_desc.profiling_get_frame_data) {
+ godot_pluginscript_profiling_data *info = (godot_pluginscript_profiling_data *)memalloc(
+ sizeof(godot_pluginscript_profiling_data) * p_info_max);
+ info_count = _desc.profiling_get_frame_data(_data, info, p_info_max);
+ for (int i = 0; i < info_count; ++i) {
+ p_info_arr[i].signature = *(StringName *)&info[i].signature;
+ p_info_arr[i].call_count = info[i].call_count;
+ p_info_arr[i].total_time = info[i].total_time;
+ p_info_arr[i].self_time = info[i].self_time;
+ godot_string_name_destroy(&info[i].signature);
+ }
+ }
+#endif
+ return info_count;
+}
+
+void PluginScriptLanguage::frame() {
+#ifdef DEBUG_ENABLED
+ if (_desc.profiling_frame) {
+ _desc.profiling_frame(_data);
+ }
+#endif
+}
+
+/* DEBUGGER FUNCTIONS */
+
+String PluginScriptLanguage::debug_get_error() const {
+ if (_desc.debug_get_error) {
+ godot_string tmp = _desc.debug_get_error(_data);
+ String ret = *(String *)&tmp;
+ godot_string_destroy(&tmp);
+ return ret;
+ }
+ return String("Nothing");
+}
+
+int PluginScriptLanguage::debug_get_stack_level_count() const {
+ if (_desc.debug_get_stack_level_count) {
+ return _desc.debug_get_stack_level_count(_data);
+ }
+ return 1;
+}
+
+int PluginScriptLanguage::debug_get_stack_level_line(int p_level) const {
+ if (_desc.debug_get_stack_level_line) {
+ return _desc.debug_get_stack_level_line(_data, p_level);
+ }
+ return 1;
+}
+
+String PluginScriptLanguage::debug_get_stack_level_function(int p_level) const {
+ if (_desc.debug_get_stack_level_function) {
+ godot_string tmp = _desc.debug_get_stack_level_function(_data, p_level);
+ String ret = *(String *)&tmp;
+ godot_string_destroy(&tmp);
+ return ret;
+ }
+ return String("Nothing");
+}
+
+String PluginScriptLanguage::debug_get_stack_level_source(int p_level) const {
+ if (_desc.debug_get_stack_level_source) {
+ godot_string tmp = _desc.debug_get_stack_level_source(_data, p_level);
+ String ret = *(String *)&tmp;
+ godot_string_destroy(&tmp);
+ return ret;
+ }
+ return String("Nothing");
+}
+
+void PluginScriptLanguage::debug_get_stack_level_locals(int p_level, List<String> *p_locals, List<Variant> *p_values, int p_max_subitems, int p_max_depth) {
+ if (_desc.debug_get_stack_level_locals) {
+ PoolStringArray locals;
+ Array values;
+ _desc.debug_get_stack_level_locals(_data, p_level, (godot_pool_string_array *)&locals, (godot_array *)&values, p_max_subitems, p_max_depth);
+ for (int i = 0; i < locals.size(); i++) {
+ p_locals->push_back(locals[i]);
+ }
+ for (int i = 0; i < values.size(); i++) {
+ p_values->push_back(values[i]);
+ }
+ }
+}
+
+void PluginScriptLanguage::debug_get_stack_level_members(int p_level, List<String> *p_members, List<Variant> *p_values, int p_max_subitems, int p_max_depth) {
+ if (_desc.debug_get_stack_level_members) {
+ PoolStringArray members;
+ Array values;
+ _desc.debug_get_stack_level_members(_data, p_level, (godot_pool_string_array *)&members, (godot_array *)&values, p_max_subitems, p_max_depth);
+ for (int i = 0; i < members.size(); i++) {
+ p_members->push_back(members[i]);
+ }
+ for (int i = 0; i < values.size(); i++) {
+ p_values->push_back(values[i]);
+ }
+ }
+}
+
+void PluginScriptLanguage::debug_get_globals(List<String> *p_locals, List<Variant> *p_values, int p_max_subitems, int p_max_depth) {
+ if (_desc.debug_get_globals) {
+ PoolStringArray locals;
+ Array values;
+ _desc.debug_get_globals(_data, (godot_pool_string_array *)&locals, (godot_array *)&values, p_max_subitems, p_max_depth);
+ for (int i = 0; i < locals.size(); i++) {
+ p_locals->push_back(locals[i]);
+ }
+ for (int i = 0; i < values.size(); i++) {
+ p_values->push_back(values[i]);
+ }
+ }
+}
+
+String PluginScriptLanguage::debug_parse_stack_level_expression(int p_level, const String &p_expression, int p_max_subitems, int p_max_depth) {
+ if (_desc.debug_parse_stack_level_expression) {
+ godot_string tmp = _desc.debug_parse_stack_level_expression(_data, p_level, (godot_string *)&p_expression, p_max_subitems, p_max_depth);
+ String ret = *(String *)&tmp;
+ godot_string_destroy(&tmp);
+ return ret;
+ }
+ return String("Nothing");
+}
+
+void PluginScriptLanguage::reload_all_scripts() {
+ // TODO
+}
+
+void PluginScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_soft_reload) {
+#ifdef DEBUG_ENABLED
+ lock();
+ // TODO
+ unlock();
+#endif
+}
+
+void PluginScriptLanguage::lock() {
+#ifndef NO_THREADS
+ if (_lock) {
+ _lock->lock();
+ }
+#endif
+}
+
+void PluginScriptLanguage::unlock() {
+#ifndef NO_THREADS
+ if (_lock) {
+ _lock->unlock();
+ }
+#endif
+}
+
+PluginScriptLanguage::PluginScriptLanguage(const godot_pluginscript_language_desc *desc)
+ : _desc(*desc) {
+ _resource_loader = memnew(ResourceFormatLoaderPluginScript(this));
+ _resource_saver = memnew(ResourceFormatSaverPluginScript(this));
+
+// TODO: totally remove _lock attribute if NO_THREADS is set
+#ifdef NO_THREADS
+ _lock = NULL;
+#else
+ _lock = Mutex::create();
+#endif
+}
+
+PluginScriptLanguage::~PluginScriptLanguage() {
+ memdelete(_resource_loader);
+ memdelete(_resource_saver);
+#ifndef NO_THREADS
+ if (_lock) {
+ memdelete(_lock);
+ _lock = NULL;
+ }
+#endif
+}
diff --git a/modules/gdnative/pluginscript/pluginscript_language.h b/modules/gdnative/pluginscript/pluginscript_language.h
new file mode 100644
index 0000000000..79b95ff4e6
--- /dev/null
+++ b/modules/gdnative/pluginscript/pluginscript_language.h
@@ -0,0 +1,132 @@
+/*************************************************************************/
+/* pluginscript_language.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef PLUGINSCRIPT_LANGUAGE_H
+#define PLUGINSCRIPT_LANGUAGE_H
+
+// Godot imports
+#include "core/io/resource_loader.h"
+#include "core/io/resource_saver.h"
+#include "core/map.h"
+#include "core/script_language.h"
+#include "core/self_list.h"
+// PluginScript imports
+#include "pluginscript_loader.h"
+#include <pluginscript/godot_pluginscript.h>
+
+class PluginScript;
+class PluginScriptInstance;
+
+class PluginScriptLanguage : public ScriptLanguage {
+ friend class PluginScript;
+ friend class PluginScriptInstance;
+
+ ResourceFormatLoaderPluginScript *_resource_loader;
+ ResourceFormatSaverPluginScript *_resource_saver;
+ const godot_pluginscript_language_desc _desc;
+ godot_pluginscript_language_data *_data;
+
+ Mutex *_lock;
+ SelfList<PluginScript>::List _script_list;
+
+public:
+ virtual String get_name() const;
+
+ _FORCE_INLINE_ ResourceFormatLoaderPluginScript *get_resource_loader() { return _resource_loader; };
+ _FORCE_INLINE_ ResourceFormatSaverPluginScript *get_resource_saver() { return _resource_saver; };
+
+ /* LANGUAGE FUNCTIONS */
+ virtual void init();
+ virtual String get_type() const;
+ virtual String get_extension() const;
+ virtual Error execute_file(const String &p_path);
+ virtual void finish();
+
+ /* EDITOR FUNCTIONS */
+ virtual void get_reserved_words(List<String> *p_words) const;
+ virtual void get_comment_delimiters(List<String> *p_delimiters) const;
+ virtual void get_string_delimiters(List<String> *p_delimiters) const;
+ virtual Ref<Script> get_template(const String &p_class_name, const String &p_base_class_name) const;
+ virtual bool validate(const String &p_script, int &r_line_error, int &r_col_error, String &r_test_error, const String &p_path = "", List<String> *r_functions = NULL) const;
+ virtual Script *create_script() const;
+ virtual bool has_named_classes() const;
+ virtual bool supports_builtin_mode() const;
+ virtual bool can_inherit_from_file() { return true; }
+ virtual int find_function(const String &p_function, const String &p_code) const;
+ virtual String make_function(const String &p_class, const String &p_name, const PoolStringArray &p_args) const;
+ virtual Error complete_code(const String &p_code, const String &p_base_path, Object *p_owner, List<String> *r_options, bool &r_force, String &r_call_hint);
+ virtual void auto_indent_code(String &p_code, int p_from_line, int p_to_line) const;
+ virtual void add_global_constant(const StringName &p_variable, const Variant &p_value);
+
+ /* MULTITHREAD FUNCTIONS */
+
+ //some VMs need to be notified of thread creation/exiting to allocate a stack
+ // void thread_enter() {}
+ // void thread_exit() {}
+
+ /* DEBUGGER FUNCTIONS */
+
+ virtual String debug_get_error() const;
+ virtual int debug_get_stack_level_count() const;
+ virtual int debug_get_stack_level_line(int p_level) const;
+ virtual String debug_get_stack_level_function(int p_level) const;
+ virtual String debug_get_stack_level_source(int p_level) const;
+ virtual void debug_get_stack_level_locals(int p_level, List<String> *p_locals, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1);
+ virtual void debug_get_stack_level_members(int p_level, List<String> *p_members, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1);
+ virtual void debug_get_globals(List<String> *p_locals, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1);
+ virtual String debug_parse_stack_level_expression(int p_level, const String &p_expression, int p_max_subitems = -1, int p_max_depth = -1);
+
+ // virtual Vector<StackInfo> debug_get_current_stack_info() { return Vector<StackInfo>(); }
+
+ virtual void reload_all_scripts();
+ virtual void reload_tool_script(const Ref<Script> &p_script, bool p_soft_reload);
+
+ /* LOADER FUNCTIONS */
+
+ virtual void get_recognized_extensions(List<String> *p_extensions) const;
+ virtual void get_public_functions(List<MethodInfo> *p_functions) const;
+ virtual void get_public_constants(List<Pair<String, Variant> > *p_constants) const;
+
+ virtual void profiling_start();
+ virtual void profiling_stop();
+
+ virtual int profiling_get_accumulated_data(ProfilingInfo *p_info_arr, int p_info_max);
+ virtual int profiling_get_frame_data(ProfilingInfo *p_info_arr, int p_info_max);
+
+ virtual void frame();
+
+ void lock();
+ void unlock();
+
+ PluginScriptLanguage(const godot_pluginscript_language_desc *desc);
+ virtual ~PluginScriptLanguage();
+};
+
+#endif // PLUGINSCRIPT_LANGUAGE_H
diff --git a/modules/gdnative/pluginscript/pluginscript_loader.cpp b/modules/gdnative/pluginscript/pluginscript_loader.cpp
new file mode 100644
index 0000000000..3648e1a5b4
--- /dev/null
+++ b/modules/gdnative/pluginscript/pluginscript_loader.cpp
@@ -0,0 +1,113 @@
+/*************************************************************************/
+/* pluginscript_loader.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 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. */
+/*************************************************************************/
+
+// Godot imports
+#include "os/file_access.h"
+// Pythonscript imports
+#include "pluginscript_language.h"
+#include "pluginscript_loader.h"
+#include "pluginscript_script.h"
+
+ResourceFormatLoaderPluginScript::ResourceFormatLoaderPluginScript(PluginScriptLanguage *language) {
+ _language = language;
+}
+
+RES ResourceFormatLoaderPluginScript::load(const String &p_path, const String &p_original_path, Error *r_error) {
+ if (r_error)
+ *r_error = ERR_FILE_CANT_OPEN;
+
+ PluginScript *script = memnew(PluginScript);
+ script->init(_language);
+
+ Ref<PluginScript> scriptres(script);
+
+ Error err = script->load_source_code(p_path);
+ ERR_FAIL_COND_V(err != OK, RES());
+
+ script->set_path(p_original_path);
+
+ script->reload();
+
+ if (r_error)
+ *r_error = OK;
+
+ return scriptres;
+}
+
+void ResourceFormatLoaderPluginScript::get_recognized_extensions(List<String> *p_extensions) const {
+ p_extensions->push_back(_language->get_extension());
+}
+
+bool ResourceFormatLoaderPluginScript::handles_type(const String &p_type) const {
+ return p_type == "Script" || p_type == _language->get_type();
+}
+
+String ResourceFormatLoaderPluginScript::get_resource_type(const String &p_path) const {
+ String el = p_path.get_extension().to_lower();
+ if (el == _language->get_extension())
+ return _language->get_type();
+ return "";
+}
+
+ResourceFormatSaverPluginScript::ResourceFormatSaverPluginScript(PluginScriptLanguage *language) {
+ _language = language;
+}
+
+Error ResourceFormatSaverPluginScript::save(const String &p_path, const RES &p_resource, uint32_t p_flags) {
+ Ref<PluginScript> sqscr = p_resource;
+ ERR_FAIL_COND_V(sqscr.is_null(), ERR_INVALID_PARAMETER);
+
+ String source = sqscr->get_source_code();
+
+ Error err;
+ FileAccess *file = FileAccess::open(p_path, FileAccess::WRITE, &err);
+ ERR_FAIL_COND_V(err, err);
+
+ file->store_string(source);
+ if (file->get_error() != OK && file->get_error() != ERR_FILE_EOF) {
+ memdelete(file);
+ return ERR_CANT_CREATE;
+ }
+ file->close();
+ memdelete(file);
+ return OK;
+}
+
+void ResourceFormatSaverPluginScript::get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const {
+
+ if (Object::cast_to<PluginScript>(*p_resource)) {
+ p_extensions->push_back(_language->get_extension());
+ }
+}
+
+bool ResourceFormatSaverPluginScript::recognize(const RES &p_resource) const {
+
+ return Object::cast_to<PluginScript>(*p_resource) != NULL;
+}
diff --git a/modules/gdnative/pluginscript/pluginscript_loader.h b/modules/gdnative/pluginscript/pluginscript_loader.h
new file mode 100644
index 0000000000..b85e7725a1
--- /dev/null
+++ b/modules/gdnative/pluginscript/pluginscript_loader.h
@@ -0,0 +1,62 @@
+/*************************************************************************/
+/* pluginscript_loader.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef PYTHONSCRIPT_PY_LOADER_H
+#define PYTHONSCRIPT_PY_LOADER_H
+
+// Godot imports
+#include "core/script_language.h"
+#include "io/resource_loader.h"
+#include "io/resource_saver.h"
+
+class PluginScriptLanguage;
+
+class ResourceFormatLoaderPluginScript : public ResourceFormatLoader {
+ PluginScriptLanguage *_language;
+
+public:
+ ResourceFormatLoaderPluginScript(PluginScriptLanguage *language);
+ virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = NULL);
+ virtual void get_recognized_extensions(List<String> *p_extensions) const;
+ virtual bool handles_type(const String &p_type) const;
+ virtual String get_resource_type(const String &p_path) const;
+};
+
+class ResourceFormatSaverPluginScript : public ResourceFormatSaver {
+ PluginScriptLanguage *_language;
+
+public:
+ ResourceFormatSaverPluginScript(PluginScriptLanguage *language);
+ virtual Error save(const String &p_path, const RES &p_resource, uint32_t p_flags = 0);
+ virtual void get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const;
+ virtual bool recognize(const RES &p_resource) const;
+};
+
+#endif // PYTHONSCRIPT_PY_LOADER_H
diff --git a/modules/gdnative/pluginscript/pluginscript_script.cpp b/modules/gdnative/pluginscript/pluginscript_script.cpp
new file mode 100644
index 0000000000..4169b07f63
--- /dev/null
+++ b/modules/gdnative/pluginscript/pluginscript_script.cpp
@@ -0,0 +1,449 @@
+/*************************************************************************/
+/* pluginscript_script.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 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. */
+/*************************************************************************/
+
+// Godot imports
+#include "core/os/file_access.h"
+// PluginScript imports
+#include "pluginscript_instance.h"
+#include "pluginscript_script.h"
+
+#if DEBUG_ENABLED
+#define __ASSERT_SCRIPT_REASON "Cannot retrieve pluginscript class for this script, is you code correct ?"
+#define ASSERT_SCRIPT_VALID() \
+ { \
+ ERR_EXPLAIN(__ASSERT_SCRIPT_REASON); \
+ ERR_FAIL_COND(!can_instance()) \
+ }
+#define ASSERT_SCRIPT_VALID_V(ret) \
+ { \
+ ERR_EXPLAIN(__ASSERT_SCRIPT_REASON); \
+ ERR_FAIL_COND_V(!can_instance(), ret) \
+ }
+#else
+#define ASSERT_SCRIPT_VALID()
+#define ASSERT_SCRIPT_VALID_V(ret)
+#endif
+
+void PluginScript::_bind_methods() {
+}
+
+#ifdef TOOLS_ENABLED
+
+void PluginScript::_placeholder_erased(PlaceHolderScriptInstance *p_placeholder) {
+ placeholders.erase(p_placeholder);
+}
+
+#endif
+
+bool PluginScript::can_instance() const {
+ bool can = _valid || (!_tool && !ScriptServer::is_scripting_enabled());
+ return can;
+}
+
+Ref<Script> PluginScript::get_base_script() const {
+ if (_ref_base_parent.is_valid()) {
+ return Ref<PluginScript>(_ref_base_parent);
+ } else {
+ return Ref<Script>();
+ }
+}
+
+StringName PluginScript::get_instance_base_type() const {
+ if (_native_parent)
+ return _native_parent;
+ if (_ref_base_parent.is_valid())
+ return _ref_base_parent->get_instance_base_type();
+ return StringName();
+}
+
+void PluginScript::update_exports() {
+// TODO
+#ifdef TOOLS_ENABLED
+#if 0
+ ASSERT_SCRIPT_VALID();
+ if (/*changed &&*/ placeholders.size()) { //hm :(
+
+ //update placeholders if any
+ Map<StringName, Variant> propdefvalues;
+ List<PropertyInfo> propinfos;
+ const String *props = (const String *)pybind_get_prop_list(_py_exposed_class);
+ for (int i = 0; props[i] != ""; ++i) {
+ const String propname = props[i];
+ pybind_get_prop_default_value(_py_exposed_class, propname.c_str(), (godot_variant *)&propdefvalues[propname]);
+ pybind_prop_info raw_info;
+ pybind_get_prop_info(_py_exposed_class, propname.c_str(), &raw_info);
+ PropertyInfo info;
+ info.type = (Variant::Type)raw_info.type;
+ info.name = propname;
+ info.hint = (PropertyHint)raw_info.hint;
+ info.hint_string = *(String *)&raw_info.hint_string;
+ info.usage = raw_info.usage;
+ propinfos.push_back(info);
+ }
+ for (Set<PlaceHolderScriptInstance *>::Element *E = placeholders.front(); E; E = E->next()) {
+ E->get()->update(propinfos, propdefvalues);
+ }
+ }
+#endif
+#endif
+}
+
+// TODO: rename p_this "p_owner" ?
+ScriptInstance *PluginScript::instance_create(Object *p_this) {
+ ASSERT_SCRIPT_VALID_V(NULL);
+ // TODO check script validity ?
+ if (!_tool && !ScriptServer::is_scripting_enabled()) {
+#ifdef TOOLS_ENABLED
+ // Instance a fake script for editing the values
+ PlaceHolderScriptInstance *si = memnew(PlaceHolderScriptInstance(get_language(), Ref<Script>(this), p_this));
+ placeholders.insert(si);
+ update_exports();
+ return si;
+#else
+ return NULL;
+#endif
+ }
+
+ PluginScript *top = this;
+ // TODO: can be optimized by storing a PluginScript::_base_parent direct pointer
+ while (top->_ref_base_parent.is_valid())
+ top = top->_ref_base_parent.ptr();
+ if (top->_native_parent) {
+ if (!ClassDB::is_parent_class(p_this->get_class_name(), top->_native_parent)) {
+ String msg = "Script inherits from native type '" + String(top->_native_parent) + "', so it can't be instanced in object of type: '" + p_this->get_class() + "'";
+ // TODO: implement PluginscriptLanguage::debug_break_parse
+ // if (ScriptDebugger::get_singleton()) {
+ // _language->debug_break_parse(get_path(), 0, msg);
+ // }
+ ERR_EXPLAIN(msg);
+ ERR_FAIL_V(NULL);
+ }
+ }
+
+ PluginScriptInstance *instance = memnew(PluginScriptInstance());
+ const bool success = instance->init(this, p_this);
+ if (success) {
+ _language->lock();
+ _instances.insert(instance->get_owner());
+ _language->unlock();
+ return instance;
+ } else {
+ memdelete(instance);
+ ERR_FAIL_V(NULL);
+ }
+}
+
+bool PluginScript::instance_has(const Object *p_this) const {
+ _language->lock();
+ bool hasit = _instances.has((Object *)p_this);
+ _language->unlock();
+ return hasit;
+}
+
+bool PluginScript::has_source_code() const {
+ bool has = _source != "";
+ return has;
+}
+
+String PluginScript::get_source_code() const {
+ return _source;
+}
+
+void PluginScript::set_source_code(const String &p_code) {
+ if (_source == p_code)
+ return;
+ _source = p_code;
+}
+
+Error PluginScript::reload(bool p_keep_state) {
+ _language->lock();
+ ERR_FAIL_COND_V(!p_keep_state && _instances.size(), ERR_ALREADY_IN_USE);
+ _language->unlock();
+
+ _valid = false;
+ String basedir = _path;
+
+ if (basedir == "")
+ basedir = get_path();
+
+ if (basedir != "")
+ basedir = basedir.get_base_dir();
+
+ if (_data) {
+ _desc->finish(_data);
+ }
+
+ Error err;
+ godot_pluginscript_script_manifest manifest = _desc->init(
+ _language->_data,
+ (godot_string *)&_path,
+ (godot_string *)&_source,
+ (godot_error *)&err);
+ if (err) {
+ // TODO: GDscript uses `ScriptDebugger` here to jump into the parsing error
+ return err;
+ }
+ _valid = true;
+ // Use the manifest to configure this script object
+ _data = manifest.data;
+ _name = *(StringName *)&manifest.name;
+ _tool = manifest.is_tool;
+ // Base name is either another PluginScript or a regular class accessible
+ // through ClassDB
+ StringName *base_name = (StringName *)&manifest.base;
+ for (SelfList<PluginScript> *e = _language->_script_list.first(); e != NULL; e = e->next()) {
+ if (e->self()->_name == *base_name) {
+ // Found you, base is a PluginScript !
+ _ref_base_parent = Ref<PluginScript>(e->self());
+ break;
+ }
+ }
+ if (!_ref_base_parent.is_valid()) {
+ // Base is a native ClassDB
+ if (!ClassDB::class_exists(*base_name)) {
+ ERR_EXPLAIN("Unknown script '" + String(_name) + "' parent '" + String(*base_name) + "'.");
+ ERR_FAIL_V(ERR_PARSE_ERROR);
+ }
+ _native_parent = *base_name;
+ }
+
+ Dictionary *members = (Dictionary *)&manifest.member_lines;
+ for (const Variant *key = members->next(); key != NULL; key = members->next(key)) {
+ _member_lines[*key] = (*members)[key];
+ }
+ Array *methods = (Array *)&manifest.methods;
+ for (int i = 0; i < methods->size(); ++i) {
+ Dictionary v = (*methods)[i];
+ MethodInfo mi = MethodInfo::from_dict(v);
+ _methods_info[mi.name] = mi;
+ // rpc_mode is passed as an optional field and is not part of MethodInfo
+ Variant var = v["rpc_mode"];
+ if (var == Variant()) {
+ _methods_rpc_mode[mi.name] = ScriptInstance::RPC_MODE_DISABLED;
+ } else {
+ _methods_rpc_mode[mi.name] = ScriptInstance::RPCMode(int(var));
+ }
+ }
+ Array *signals = (Array *)&manifest.signals;
+ for (int i = 0; i < signals->size(); ++i) {
+ Variant v = (*signals)[i];
+ MethodInfo mi = MethodInfo::from_dict(v);
+ _signals_info[mi.name] = mi;
+ }
+ Array *properties = (Array *)&manifest.properties;
+ for (int i = 0; i < properties->size(); ++i) {
+ Dictionary v = (*properties)[i];
+ PropertyInfo pi = PropertyInfo::from_dict(v);
+ _properties_info[pi.name] = pi;
+ _properties_default_values[pi.name] = v["default_value"];
+ // rset_mode is passed as an optional field and is not part of PropertyInfo
+ Variant var = v["rset_mode"];
+ if (var == Variant()) {
+ _methods_rpc_mode[pi.name] = ScriptInstance::RPC_MODE_DISABLED;
+ } else {
+ _methods_rpc_mode[pi.name] = ScriptInstance::RPCMode(int(var));
+ }
+ }
+ // Manifest's attributes must be explicitly freed
+ godot_string_name_destroy(&manifest.name);
+ godot_string_name_destroy(&manifest.base);
+ godot_dictionary_destroy(&manifest.member_lines);
+ godot_array_destroy(&manifest.methods);
+ godot_array_destroy(&manifest.signals);
+ godot_array_destroy(&manifest.properties);
+
+#ifdef TOOLS_ENABLED
+/*for (Set<PlaceHolderScriptInstance*>::Element *E=placeholders.front();E;E=E->next()) {
+
+ _update_placeholder(E->get());
+ }*/
+#endif
+ return OK;
+}
+
+void PluginScript::get_script_method_list(List<MethodInfo> *r_methods) const {
+ ASSERT_SCRIPT_VALID();
+ for (Map<StringName, MethodInfo>::Element *e = _methods_info.front(); e != NULL; e = e->next()) {
+ r_methods->push_back(e->get());
+ }
+}
+
+void PluginScript::get_script_property_list(List<PropertyInfo> *r_properties) const {
+ ASSERT_SCRIPT_VALID();
+ for (Map<StringName, PropertyInfo>::Element *e = _properties_info.front(); e != NULL; e = e->next()) {
+ r_properties->push_back(e->get());
+ }
+}
+
+bool PluginScript::has_method(const StringName &p_method) const {
+ ASSERT_SCRIPT_VALID_V(false);
+ return _methods_info.has(p_method);
+}
+
+MethodInfo PluginScript::get_method_info(const StringName &p_method) const {
+ ASSERT_SCRIPT_VALID_V(MethodInfo());
+ const Map<StringName, MethodInfo>::Element *e = _methods_info.find(p_method);
+ if (e != NULL) {
+ return e->get();
+ } else {
+ return MethodInfo();
+ }
+}
+
+bool PluginScript::has_property(const StringName &p_method) const {
+ ASSERT_SCRIPT_VALID_V(false);
+ return _properties_info.has(p_method);
+}
+
+PropertyInfo PluginScript::get_property_info(const StringName &p_property) const {
+ ASSERT_SCRIPT_VALID_V(PropertyInfo());
+ const Map<StringName, PropertyInfo>::Element *e = _properties_info.find(p_property);
+ if (e != NULL) {
+ return e->get();
+ } else {
+ return PropertyInfo();
+ }
+}
+
+bool PluginScript::get_property_default_value(const StringName &p_property, Variant &r_value) const {
+ ASSERT_SCRIPT_VALID_V(false);
+#ifdef TOOLS_ENABLED
+ const Map<StringName, Variant>::Element *e = _properties_default_values.find(p_property);
+ if (e != NULL) {
+ r_value = e->get();
+ return true;
+ } else {
+ return false;
+ }
+#endif
+ return false;
+}
+
+ScriptLanguage *PluginScript::get_language() const {
+ return _language;
+}
+
+Error PluginScript::load_source_code(const String &p_path) {
+
+ PoolVector<uint8_t> sourcef;
+ Error err;
+ FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err);
+ if (err) {
+ ERR_FAIL_COND_V(err, err);
+ }
+
+ int len = f->get_len();
+ sourcef.resize(len + 1);
+ PoolVector<uint8_t>::Write w = sourcef.write();
+ int r = f->get_buffer(w.ptr(), len);
+ f->close();
+ memdelete(f);
+ ERR_FAIL_COND_V(r != len, ERR_CANT_OPEN);
+ w[len] = 0;
+
+ String s;
+ if (s.parse_utf8((const char *)w.ptr())) {
+ ERR_EXPLAIN("Script '" + p_path + "' contains invalid unicode (utf-8), so it was not loaded. Please ensure that scripts are saved in valid utf-8 unicode.");
+ ERR_FAIL_V(ERR_INVALID_DATA);
+ }
+
+ _source = s;
+#ifdef TOOLS_ENABLED
+// source_changed_cache=true;
+#endif
+ _path = p_path;
+ return OK;
+}
+
+bool PluginScript::has_script_signal(const StringName &p_signal) const {
+ ASSERT_SCRIPT_VALID_V(false);
+ return _signals_info.has(p_signal);
+}
+
+void PluginScript::get_script_signal_list(List<MethodInfo> *r_signals) const {
+ ASSERT_SCRIPT_VALID();
+ for (Map<StringName, MethodInfo>::Element *e = _signals_info.front(); e != NULL; e = e->next()) {
+ r_signals->push_back(e->get());
+ }
+}
+
+int PluginScript::get_member_line(const StringName &p_member) const {
+#ifdef TOOLS_ENABLED
+ if (_member_lines.has(p_member))
+ return _member_lines[p_member];
+ else
+#endif
+ return -1;
+}
+
+ScriptInstance::RPCMode PluginScript::get_rpc_mode(const StringName &p_method) const {
+ ASSERT_SCRIPT_VALID_V(ScriptInstance::RPC_MODE_DISABLED);
+ const Map<StringName, ScriptInstance::RPCMode>::Element *e = _methods_rpc_mode.find(p_method);
+ if (e != NULL) {
+ return e->get();
+ } else {
+ return ScriptInstance::RPC_MODE_DISABLED;
+ }
+}
+
+ScriptInstance::RPCMode PluginScript::get_rset_mode(const StringName &p_variable) const {
+ ASSERT_SCRIPT_VALID_V(ScriptInstance::RPC_MODE_DISABLED);
+ const Map<StringName, ScriptInstance::RPCMode>::Element *e = _variables_rset_mode.find(p_variable);
+ if (e != NULL) {
+ return e->get();
+ } else {
+ return ScriptInstance::RPC_MODE_DISABLED;
+ }
+}
+
+PluginScript::PluginScript()
+ : _data(NULL), _tool(false), _valid(false), _script_list(this) {
+}
+
+void PluginScript::init(PluginScriptLanguage *language) {
+ _desc = &language->_desc.script_desc;
+ _language = language;
+
+#ifdef DEBUG_ENABLED
+ _language->lock();
+ _language->_script_list.add(&_script_list);
+ _language->unlock();
+#endif
+}
+
+PluginScript::~PluginScript() {
+ _desc->finish(_data);
+
+#ifdef DEBUG_ENABLED
+ _language->lock();
+ _language->_script_list.remove(&_script_list);
+ _language->unlock();
+#endif
+}
diff --git a/modules/gdnative/pluginscript/pluginscript_script.h b/modules/gdnative/pluginscript/pluginscript_script.h
new file mode 100644
index 0000000000..5600bca5ef
--- /dev/null
+++ b/modules/gdnative/pluginscript/pluginscript_script.h
@@ -0,0 +1,127 @@
+/*************************************************************************/
+/* pluginscript_script.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef PLUGINSCRIPT_SCRIPT_H
+#define PLUGINSCRIPT_SCRIPT_H
+
+// Godot imports
+#include "core/script_language.h"
+// PluginScript imports
+#include "pluginscript_language.h"
+#include <pluginscript/godot_pluginscript.h>
+
+class PyInstance;
+
+class PluginScript : public Script {
+
+ GDCLASS(PluginScript, Script);
+
+ friend class PluginScriptInstance;
+ friend class PluginScriptLanguage;
+
+private:
+ godot_pluginscript_script_data *_data;
+ const godot_pluginscript_script_desc *_desc;
+ PluginScriptLanguage *_language;
+ bool _tool;
+ bool _valid;
+
+ Ref<PluginScript> _ref_base_parent;
+ StringName _native_parent;
+ SelfList<PluginScript> _script_list;
+
+ Map<StringName, int> _member_lines;
+ Map<StringName, Variant> _properties_default_values;
+ Map<StringName, PropertyInfo> _properties_info;
+ Map<StringName, MethodInfo> _signals_info;
+ Map<StringName, MethodInfo> _methods_info;
+ Map<StringName, ScriptInstance::RPCMode> _variables_rset_mode;
+ Map<StringName, ScriptInstance::RPCMode> _methods_rpc_mode;
+
+ Set<Object *> _instances;
+ //exported members
+ String _source;
+ String _path;
+ StringName _name;
+
+protected:
+ static void _bind_methods();
+
+#ifdef TOOLS_ENABLED
+ Set<PlaceHolderScriptInstance *> placeholders;
+ //void _update_placeholder(PlaceHolderScriptInstance *p_placeholder);
+ virtual void _placeholder_erased(PlaceHolderScriptInstance *p_placeholder);
+#endif
+public:
+ virtual bool can_instance() const;
+
+ virtual Ref<Script> get_base_script() const; //for script inheritance
+
+ virtual StringName get_instance_base_type() const; // this may not work in all scripts, will return empty if so
+ virtual ScriptInstance *instance_create(Object *p_this);
+ virtual bool instance_has(const Object *p_this) const;
+
+ virtual bool has_source_code() const;
+ virtual String get_source_code() const;
+ virtual void set_source_code(const String &p_code);
+ virtual Error reload(bool p_keep_state = false);
+ // TODO: load_source_code only allow utf-8 file, should handle bytecode as well ?
+ virtual Error load_source_code(const String &p_path);
+
+ virtual bool has_method(const StringName &p_method) const;
+ virtual MethodInfo get_method_info(const StringName &p_method) const;
+
+ bool has_property(const StringName &p_method) const;
+ PropertyInfo get_property_info(const StringName &p_property) const;
+
+ bool is_tool() const { return _tool; }
+
+ virtual ScriptLanguage *get_language() const;
+
+ virtual bool has_script_signal(const StringName &p_signal) const;
+ virtual void get_script_signal_list(List<MethodInfo> *r_signals) const;
+
+ virtual bool get_property_default_value(const StringName &p_property, Variant &r_value) const;
+
+ virtual void update_exports();
+ virtual void get_script_method_list(List<MethodInfo> *r_methods) const;
+ virtual void get_script_property_list(List<PropertyInfo> *r_propertieslist) const;
+
+ virtual int get_member_line(const StringName &p_member) const;
+
+ ScriptInstance::RPCMode get_rpc_mode(const StringName &p_method) const;
+ ScriptInstance::RPCMode get_rset_mode(const StringName &p_variable) const;
+
+ PluginScript();
+ void init(PluginScriptLanguage *language);
+ virtual ~PluginScript();
+};
+
+#endif // PLUGINSCRIPT_SCRIPT_H
diff --git a/modules/gdnative/pluginscript/register_types.cpp b/modules/gdnative/pluginscript/register_types.cpp
new file mode 100644
index 0000000000..5829d08dff
--- /dev/null
+++ b/modules/gdnative/pluginscript/register_types.cpp
@@ -0,0 +1,118 @@
+/*************************************************************************/
+/* register_types.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#include "register_types.h"
+
+#include "core/project_settings.h"
+#include "io/resource_loader.h"
+#include "io/resource_saver.h"
+#include "os/dir_access.h"
+#include "os/os.h"
+#include "scene/main/scene_tree.h"
+
+#include "pluginscript_language.h"
+#include "pluginscript_script.h"
+#include <pluginscript/godot_pluginscript.h>
+
+static List<PluginScriptLanguage *> pluginscript_languages;
+
+static Error _check_language_desc(const godot_pluginscript_language_desc *desc) {
+ ERR_FAIL_COND_V(!desc->name || desc->name == String(), ERR_BUG);
+ ERR_FAIL_COND_V(!desc->type || desc->type == String(), ERR_BUG);
+ ERR_FAIL_COND_V(!desc->extension || desc->extension == String(), ERR_BUG);
+ ERR_FAIL_COND_V(!desc->recognized_extensions || !desc->recognized_extensions[0], ERR_BUG);
+ ERR_FAIL_COND_V(!desc->init, ERR_BUG);
+ ERR_FAIL_COND_V(!desc->finish, ERR_BUG);
+
+ // desc->reserved_words is not mandatory
+ // desc->comment_delimiters is not mandatory
+ // desc->string_delimiters is not mandatory
+
+ // desc->get_template_source_code is not mandatory
+ // desc->validate is not mandatory
+
+ // desc->get_template_source_code is not mandatory
+ // desc->validate is not mandatory
+ // desc->find_function is not mandatory
+ // desc->make_function is not mandatory
+ // desc->complete_code is not mandatory
+ // desc->auto_indent_code is not mandatory
+ // desc->add_global_constant is not mandatory
+ // desc->debug_get_error is not mandatory
+ // desc->debug_get_stack_level_count is not mandatory
+ // desc->debug_get_stack_level_line is not mandatory
+ // desc->debug_get_stack_level_function is not mandatory
+ // desc->debug_get_stack_level_source is not mandatory
+ // desc->debug_get_stack_level_locals is not mandatory
+ // desc->debug_get_stack_level_members is not mandatory
+ // desc->debug_get_globals is not mandatory
+ // desc->debug_parse_stack_level_expression is not mandatory
+ // desc->profiling_start is not mandatory
+ // desc->profiling_stop is not mandatory
+ // desc->profiling_get_accumulated_data is not mandatory
+ // desc->profiling_get_frame_data is not mandatory
+ // desc->frame is not mandatory
+
+ ERR_FAIL_COND_V(!desc->script_desc.init, ERR_BUG);
+ ERR_FAIL_COND_V(!desc->script_desc.finish, ERR_BUG);
+
+ ERR_FAIL_COND_V(!desc->script_desc.instance_desc.init, ERR_BUG);
+ ERR_FAIL_COND_V(!desc->script_desc.instance_desc.finish, ERR_BUG);
+ ERR_FAIL_COND_V(!desc->script_desc.instance_desc.set_prop, ERR_BUG);
+ ERR_FAIL_COND_V(!desc->script_desc.instance_desc.get_prop, ERR_BUG);
+ ERR_FAIL_COND_V(!desc->script_desc.instance_desc.call_method, ERR_BUG);
+ ERR_FAIL_COND_V(!desc->script_desc.instance_desc.notification, ERR_BUG);
+ // desc->script_desc.instance_desc.refcount_incremented is not mandatory
+ // desc->script_desc.instance_desc.refcount_decremented is not mandatory
+ return OK;
+}
+
+void GDAPI godot_pluginscript_register_language(const godot_pluginscript_language_desc *language_desc) {
+ Error ret = _check_language_desc(language_desc);
+ if (ret) {
+ ERR_FAIL();
+ }
+ PluginScriptLanguage *language = memnew(PluginScriptLanguage(language_desc));
+ ScriptServer::register_language(language);
+ ResourceLoader::add_resource_format_loader(language->get_resource_loader());
+ ResourceSaver::add_resource_format_saver(language->get_resource_saver());
+ pluginscript_languages.push_back(language);
+}
+
+void register_pluginscript_types() {
+ ClassDB::register_class<PluginScript>();
+}
+
+void unregister_pluginscript_types() {
+ for (List<PluginScriptLanguage *>::Element *e = pluginscript_languages.front(); e; e = e->next()) {
+ PluginScriptLanguage *language = e->get();
+ ScriptServer::unregister_language(language);
+ memdelete(language);
+ }
+}
diff --git a/modules/gdnative/pluginscript/register_types.h b/modules/gdnative/pluginscript/register_types.h
new file mode 100644
index 0000000000..70bbb16c62
--- /dev/null
+++ b/modules/gdnative/pluginscript/register_types.h
@@ -0,0 +1,31 @@
+/*************************************************************************/
+/* register_types.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 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. */
+/*************************************************************************/
+void register_pluginscript_types();
+void unregister_pluginscript_types();
diff --git a/modules/gdnative/register_types.cpp b/modules/gdnative/register_types.cpp
index 997c342045..34099bf528 100644
--- a/modules/gdnative/register_types.cpp
+++ b/modules/gdnative/register_types.cpp
@@ -35,7 +35,9 @@
#include "io/resource_loader.h"
#include "io/resource_saver.h"
+#include "arvr/register_types.h"
#include "nativescript/register_types.h"
+#include "pluginscript/register_types.h"
#include "core/engine.h"
#include "core/os/os.h"
@@ -46,7 +48,7 @@
#include "gd_native_library_editor.h"
// Class used to discover singleton gdnative files
-void actual_discoverer_handler();
+static void actual_discoverer_handler();
class GDNativeSingletonDiscover : public Object {
// GDCLASS(GDNativeSingletonDiscover, Object)
@@ -64,7 +66,7 @@ class GDNativeSingletonDiscover : public Object {
}
};
-Set<String> get_gdnative_singletons(EditorFileSystemDirectory *p_dir) {
+static Set<String> get_gdnative_singletons(EditorFileSystemDirectory *p_dir) {
Set<String> file_paths;
@@ -79,7 +81,7 @@ Set<String> get_gdnative_singletons(EditorFileSystemDirectory *p_dir) {
}
Ref<GDNativeLibrary> lib = ResourceLoader::load(p_dir->get_file_path(i));
- if (lib.is_valid() && lib->is_singleton_gdnative()) {
+ if (lib.is_valid() && lib->is_singleton()) {
file_paths.insert(p_dir->get_file_path(i));
}
}
@@ -96,7 +98,7 @@ Set<String> get_gdnative_singletons(EditorFileSystemDirectory *p_dir) {
return file_paths;
}
-void actual_discoverer_handler() {
+static void actual_discoverer_handler() {
EditorFileSystemDirectory *dir = EditorFileSystem::get_singleton()->get_filesystem();
Set<String> file_paths = get_gdnative_singletons(dir);
@@ -113,100 +115,197 @@ void actual_discoverer_handler() {
ProjectSettings::get_singleton()->save();
}
-GDNativeSingletonDiscover *discoverer = NULL;
+static GDNativeSingletonDiscover *discoverer = NULL;
-static void editor_init_callback() {
+class GDNativeExportPlugin : public EditorExportPlugin {
- GDNativeLibraryEditor *library_editor = memnew(GDNativeLibraryEditor);
- library_editor->set_name(TTR("GDNative"));
- ProjectSettingsEditor::get_singleton()->get_tabs()->add_child(library_editor);
+protected:
+ virtual void _export_file(const String &p_path, const String &p_type, const Set<String> &p_features);
+};
- discoverer = memnew(GDNativeSingletonDiscover);
- EditorFileSystem::get_singleton()->connect("filesystem_changed", discoverer, "get_class");
-}
+struct LibrarySymbol {
+ char *name;
+ bool is_required;
+};
-#endif
+void GDNativeExportPlugin::_export_file(const String &p_path, const String &p_type, const Set<String> &p_features) {
+ if (p_type != "GDNativeLibrary") {
+ return;
+ }
-godot_variant cb_standard_varcall(void *handle, godot_string *p_procedure, godot_array *p_args) {
- if (handle == NULL) {
- ERR_PRINT("No valid library handle, can't call standard varcall procedure");
- godot_variant ret;
- godot_variant_new_nil(&ret);
- return ret;
+ Ref<GDNativeLibrary> lib = ResourceLoader::load(p_path);
+
+ if (lib.is_null()) {
+ return;
}
- void *library_proc;
- Error err = OS::get_singleton()->get_dynamic_library_symbol_handle(
- handle,
- *(String *)p_procedure,
- library_proc,
- true); // we roll our own message
- if (err != OK) {
- ERR_PRINT((String("GDNative procedure \"" + *(String *)p_procedure) + "\" does not exists and can't be called").utf8().get_data());
- godot_variant ret;
- godot_variant_new_nil(&ret);
- return ret;
+ Ref<ConfigFile> config = lib->get_config_file();
+
+ {
+
+ List<String> entry_keys;
+ config->get_section_keys("entry", &entry_keys);
+
+ for (List<String>::Element *E = entry_keys.front(); E; E = E->next()) {
+ String key = E->get();
+
+ Vector<String> tags = key.split(".");
+
+ bool skip = false;
+ for (int i = 0; i < tags.size(); i++) {
+ bool has_feature = p_features.has(tags[i]);
+
+ if (!has_feature) {
+ skip = true;
+ break;
+ }
+ }
+
+ if (skip) {
+ continue;
+ }
+
+ String entry_lib_path = config->get_value("entry", key);
+ add_shared_object(entry_lib_path, tags);
+ }
}
- godot_gdnative_procedure_fn proc;
- proc = (godot_gdnative_procedure_fn)library_proc;
+ {
+ List<String> dependency_keys;
+ config->get_section_keys("dependencies", &dependency_keys);
- return proc(NULL, p_args);
-}
+ for (List<String>::Element *E = dependency_keys.front(); E; E = E->next()) {
+ String key = E->get();
-void cb_singleton_call(
- void *p_handle,
- godot_string *p_proc_name,
- void *p_data,
- int p_num_args,
- void **p_args,
- void *r_return) {
- if (p_handle == NULL) {
- ERR_PRINT("No valid library handle, can't call singleton procedure");
- return;
+ Vector<String> tags = key.split(".");
+
+ bool skip = false;
+ for (int i = 0; i < tags.size(); i++) {
+ bool has_feature = p_features.has(tags[i]);
+
+ if (!has_feature) {
+ skip = true;
+ break;
+ }
+ }
+
+ if (skip) {
+ continue;
+ }
+
+ Vector<String> dependency_paths = config->get_value("dependencies", key);
+ for (int i = 0; i < dependency_paths.size(); i++) {
+ add_shared_object(dependency_paths[i], tags);
+ }
+ }
}
- void *singleton_proc;
- Error err = OS::get_singleton()->get_dynamic_library_symbol_handle(
- p_handle,
- *(String *)p_proc_name,
- singleton_proc);
+ if (p_features.has("iOS")) {
+ // Register symbols in the "fake" dynamic lookup table, because dlsym does not work well on iOS.
+ LibrarySymbol expected_symbols[] = {
+ { "gdnative_init", true },
+ { "gdnative_terminate", false },
+ { "nativescript_init", false },
+ { "nativescript_frame", false },
+ { "nativescript_thread_enter", false },
+ { "nativescript_thread_exit", false },
+ { "gdnative_singleton", false }
+ };
+ String declare_pattern = "extern \"C\" void $name(void)$weak;\n";
+ String additional_code = "extern void register_dynamic_symbol(char *name, void *address);\n"
+ "extern void add_ios_init_callback(void (*cb)());\n";
+ String linker_flags = "";
+ for (int i = 0; i < sizeof(expected_symbols) / sizeof(expected_symbols[0]); ++i) {
+ String full_name = lib->get_symbol_prefix() + expected_symbols[i].name;
+ String code = declare_pattern.replace("$name", full_name);
+ code = code.replace("$weak", expected_symbols[i].is_required ? "" : " __attribute__((weak))");
+ additional_code += code;
+
+ if (!expected_symbols[i].is_required) {
+ if (linker_flags.length() > 0) {
+ linker_flags += " ";
+ }
+ linker_flags += "-Wl,-U,_" + full_name;
+ }
+ }
- if (err != OK) {
- return;
+ additional_code += String("void $prefixinit() {\n").replace("$prefix", lib->get_symbol_prefix());
+ String register_pattern = " if (&$name) register_dynamic_symbol((char *)\"$name\", (void *)$name);\n";
+ for (int i = 0; i < sizeof(expected_symbols) / sizeof(expected_symbols[0]); ++i) {
+ String full_name = lib->get_symbol_prefix() + expected_symbols[i].name;
+ additional_code += register_pattern.replace("$name", full_name);
+ }
+ additional_code += "}\n";
+ additional_code += String("struct $prefixstruct {$prefixstruct() {add_ios_init_callback($prefixinit);}};\n").replace("$prefix", lib->get_symbol_prefix());
+ additional_code += String("$prefixstruct $prefixstruct_instance;\n").replace("$prefix", lib->get_symbol_prefix());
+
+ add_ios_cpp_code(additional_code);
+ add_ios_linker_flags(linker_flags);
}
+}
+
+static void editor_init_callback() {
+
+ GDNativeLibraryEditor *library_editor = memnew(GDNativeLibraryEditor);
+ library_editor->set_name(TTR("GDNative"));
+ ProjectSettingsEditor::get_singleton()->get_tabs()->add_child(library_editor);
+
+ discoverer = memnew(GDNativeSingletonDiscover);
+ EditorFileSystem::get_singleton()->connect("filesystem_changed", discoverer, "get_class");
- void (*singleton_procedure_ptr)() = (void (*)())singleton_proc;
- singleton_procedure_ptr();
+ Ref<GDNativeExportPlugin> export_plugin;
+ export_plugin.instance();
+
+ EditorExport::get_singleton()->add_export_plugin(export_plugin);
+}
+
+#endif
+
+static godot_variant cb_standard_varcall(void *p_procedure_handle, godot_array *p_args) {
+
+ godot_gdnative_procedure_fn proc;
+ proc = (godot_gdnative_procedure_fn)p_procedure_handle;
+
+ return proc(p_args);
}
GDNativeCallRegistry *GDNativeCallRegistry::singleton;
Vector<Ref<GDNative> > singleton_gdnatives;
+GDNativeLibraryResourceLoader *resource_loader_gdnlib = NULL;
+GDNativeLibraryResourceSaver *resource_saver_gdnlib = NULL;
+
void register_gdnative_types() {
#ifdef TOOLS_ENABLED
- if (Engine::get_singleton()->is_editor_hint()) {
- EditorNode::add_init_callback(editor_init_callback);
- }
+ EditorNode::add_init_callback(editor_init_callback);
#endif
ClassDB::register_class<GDNativeLibrary>();
ClassDB::register_class<GDNative>();
+ resource_loader_gdnlib = memnew(GDNativeLibraryResourceLoader);
+ resource_saver_gdnlib = memnew(GDNativeLibraryResourceSaver);
+
+ ResourceLoader::add_resource_format_loader(resource_loader_gdnlib);
+ ResourceSaver::add_resource_format_saver(resource_saver_gdnlib);
+
GDNativeCallRegistry::singleton = memnew(GDNativeCallRegistry);
GDNativeCallRegistry::singleton->register_native_call_type("standard_varcall", cb_standard_varcall);
- GDNativeCallRegistry::singleton->register_native_raw_call_type("gdnative_singleton_call", cb_singleton_call);
-
+ register_arvr_types();
register_nativescript_types();
+ register_pluginscript_types();
// run singletons
- Array singletons = ProjectSettings::get_singleton()->get("gdnative/singletons");
+ Array singletons = Array();
+ if (ProjectSettings::get_singleton()->has_setting("gdnative/singletons")) {
+ singletons = ProjectSettings::get_singleton()->get("gdnative/singletons");
+ }
singleton_gdnatives.resize(singletons.size());
@@ -223,13 +322,16 @@ void register_gdnative_types() {
continue;
}
- singleton_gdnatives[i]->call_native_raw(
- "gdnative_singleton_call",
- "godot_gdnative_singleton",
- NULL,
- 0,
- NULL,
- NULL);
+ void *proc_ptr;
+ Error err = singleton_gdnatives[i]->get_symbol(
+ lib->get_symbol_prefix() + "gdnative_singleton",
+ proc_ptr);
+
+ if (err != OK) {
+ ERR_PRINT((String("No godot_gdnative_singleton in \"" + singleton_gdnatives[i]->get_library()->get_current_library_path()) + "\" found").utf8().get_data());
+ } else {
+ ((void (*)())proc_ptr)();
+ }
}
}
@@ -247,8 +349,11 @@ void unregister_gdnative_types() {
singleton_gdnatives[i]->terminate();
}
+ singleton_gdnatives.clear();
+ unregister_pluginscript_types();
unregister_nativescript_types();
+ unregister_arvr_types();
memdelete(GDNativeCallRegistry::singleton);
@@ -258,6 +363,9 @@ void unregister_gdnative_types() {
}
#endif
+ memdelete(resource_loader_gdnlib);
+ memdelete(resource_saver_gdnlib);
+
// This is for printing out the sizes of the core types
/*
@@ -270,7 +378,7 @@ void unregister_gdnative_types() {
print_line(String("poolarray:\t") + itos(sizeof(PoolByteArray)));
print_line(String("quat:\t") + itos(sizeof(Quat)));
print_line(String("rect2:\t") + itos(sizeof(Rect2)));
- print_line(String("rect3:\t") + itos(sizeof(Rect3)));
+ print_line(String("aabb:\t") + itos(sizeof(AABB)));
print_line(String("rid:\t") + itos(sizeof(RID)));
print_line(String("string:\t") + itos(sizeof(String)));
print_line(String("transform:\t") + itos(sizeof(Transform)));
diff --git a/modules/gdscript/config.py b/modules/gdscript/config.py
index 5698a37295..6496b59d75 100644
--- a/modules/gdscript/config.py
+++ b/modules/gdscript/config.py
@@ -1,8 +1,15 @@
-
-
def can_build(platform):
return True
-
def configure(env):
pass
+
+def get_doc_classes():
+ return [
+ "GDScript",
+ "GDScriptFunctionState",
+ "GDScriptNativeClass",
+ ]
+
+def get_doc_path():
+ return "doc_classes"
diff --git a/doc/classes/GDScript.xml b/modules/gdscript/doc_classes/GDScript.xml
index 2faa0ff968..13d45aa520 100644
--- a/doc/classes/GDScript.xml
+++ b/modules/gdscript/doc_classes/GDScript.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="GDScript" inherits="Script" category="Core" version="3.0.alpha.custom_build">
+<class name="GDScript" inherits="Script" category="Core" version="3.0-alpha">
<brief_description>
A script implemented in the GDScript programming language.
</brief_description>
diff --git a/doc/classes/GDFunctionState.xml b/modules/gdscript/doc_classes/GDScriptFunctionState.xml
index 801ca718e7..2df4e7c217 100644
--- a/doc/classes/GDFunctionState.xml
+++ b/modules/gdscript/doc_classes/GDScriptFunctionState.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="GDFunctionState" inherits="Reference" category="Core" version="3.0.alpha.custom_build">
+<class name="GDScriptFunctionState" inherits="Reference" category="Core" version="3.0-alpha">
<brief_description>
State of a function call after yielding.
</brief_description>
@@ -18,7 +18,7 @@
</argument>
<description>
Check whether the function call may be resumed. This is not the case if the function state was already resumed.
- If [code]extended_check[/code] is enabled, it also checks if the associated script and object still exist. The extended check is done in debug mode as part of [method GDFunctionState.resume], but you can use this if you know you may be trying to resume without knowing for sure the object and/or script have survived up to that point.
+ If [code]extended_check[/code] is enabled, it also checks if the associated script and object still exist. The extended check is done in debug mode as part of [method GDScriptFunctionState.resume], but you can use this if you know you may be trying to resume without knowing for sure the object and/or script have survived up to that point.
</description>
</method>
<method name="resume">
diff --git a/doc/classes/GDNativeClass.xml b/modules/gdscript/doc_classes/GDScriptNativeClass.xml
index 5a3f353720..4514a78469 100644
--- a/doc/classes/GDNativeClass.xml
+++ b/modules/gdscript/doc_classes/GDScriptNativeClass.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="GDNativeClass" inherits="Reference" category="Core" version="3.0.alpha.custom_build">
+<class name="GDScriptNativeClass" inherits="Reference" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/modules/gdscript/gd_script.cpp b/modules/gdscript/gdscript.cpp
index cf6529d5ae..41a810ff00 100644
--- a/modules/gdscript/gd_script.cpp
+++ b/modules/gdscript/gdscript.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* gd_script.cpp */
+/* gdscript.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -27,9 +27,10 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "gd_script.h"
+#include "gdscript.h"
-#include "gd_compiler.h"
+#include "engine.h"
+#include "gdscript_compiler.h"
#include "global_constants.h"
#include "io/file_access_encrypted.h"
#include "os/file_access.h"
@@ -38,12 +39,12 @@
///////////////////////////
-GDNativeClass::GDNativeClass(const StringName &p_name) {
+GDScriptNativeClass::GDScriptNativeClass(const StringName &p_name) {
name = p_name;
}
-bool GDNativeClass::_get(const StringName &p_name, Variant &r_ret) const {
+bool GDScriptNativeClass::_get(const StringName &p_name, Variant &r_ret) const {
bool ok;
int v = ClassDB::get_integer_constant(name, p_name, &ok);
@@ -56,12 +57,12 @@ bool GDNativeClass::_get(const StringName &p_name, Variant &r_ret) const {
}
}
-void GDNativeClass::_bind_methods() {
+void GDScriptNativeClass::_bind_methods() {
- ClassDB::bind_method(D_METHOD("new"), &GDNativeClass::_new);
+ ClassDB::bind_method(D_METHOD("new"), &GDScriptNativeClass::_new);
}
-Variant GDNativeClass::_new() {
+Variant GDScriptNativeClass::_new() {
Object *o = instance();
if (!o) {
@@ -77,16 +78,16 @@ Variant GDNativeClass::_new() {
}
}
-Object *GDNativeClass::instance() {
+Object *GDScriptNativeClass::instance() {
return ClassDB::instance(name);
}
-GDInstance *GDScript::_create_instance(const Variant **p_args, int p_argcount, Object *p_owner, bool p_isref, Variant::CallError &r_error) {
+GDScriptInstance *GDScript::_create_instance(const Variant **p_args, int p_argcount, Object *p_owner, bool p_isref, Variant::CallError &r_error) {
/* STEP 1, CREATE */
- GDInstance *instance = memnew(GDInstance);
+ GDScriptInstance *instance = memnew(GDScriptInstance);
instance->base_ref = p_isref;
instance->members.resize(member_indices.size());
instance->script = Ref<GDScript>(this);
@@ -99,7 +100,7 @@ GDInstance *GDScript::_create_instance(const Variant **p_args, int p_argcount, O
#endif
instance->owner->set_script_instance(instance);
-/* STEP 2, INITIALIZE AND CONSRTUCT */
+ /* STEP 2, INITIALIZE AND CONSRTUCT */
#ifndef NO_THREADS
GDScriptLanguage::singleton->lock->lock();
@@ -162,7 +163,7 @@ Variant GDScript::_new(const Variant **p_args, int p_argcount, Variant::CallErro
ref = REF(r);
}
- GDInstance *instance = _create_instance(p_args, p_argcount, owner, r != NULL, r_error);
+ GDScriptInstance *instance = _create_instance(p_args, p_argcount, owner, r != NULL, r_error);
if (!instance) {
if (ref.is_null()) {
memdelete(owner); //no owner, sorry
@@ -217,7 +218,7 @@ void GDScript::_placeholder_erased(PlaceHolderScriptInstance *p_placeholder) {
void GDScript::get_script_method_list(List<MethodInfo> *p_list) const {
- for (const Map<StringName, GDFunction *>::Element *E = member_functions.front(); E; E = E->next()) {
+ for (const Map<StringName, GDScriptFunction *>::Element *E = member_functions.front(); E; E = E->next()) {
MethodInfo mi;
mi.name = E->key();
for (int i = 0; i < E->get()->get_argument_count(); i++) {
@@ -271,7 +272,7 @@ bool GDScript::has_method(const StringName &p_method) const {
MethodInfo GDScript::get_method_info(const StringName &p_method) const {
- const Map<StringName, GDFunction *>::Element *E = member_functions.find(p_method);
+ const Map<StringName, GDScriptFunction *>::Element *E = member_functions.find(p_method);
if (!E)
return MethodInfo();
@@ -419,15 +420,15 @@ bool GDScript::_update_exports() {
if (basedir != "")
basedir = basedir.get_base_dir();
- GDParser parser;
+ GDScriptParser parser;
Error err = parser.parse(source, basedir, true, path);
if (err == OK) {
- const GDParser::Node *root = parser.get_parse_tree();
- ERR_FAIL_COND_V(root->type != GDParser::Node::TYPE_CLASS, false);
+ const GDScriptParser::Node *root = parser.get_parse_tree();
+ ERR_FAIL_COND_V(root->type != GDScriptParser::Node::TYPE_CLASS, false);
- const GDParser::ClassNode *c = static_cast<const GDParser::ClassNode *>(root);
+ const GDScriptParser::ClassNode *c = static_cast<const GDScriptParser::ClassNode *>(root);
if (base_cache.is_valid()) {
base_cache->inheriters_cache.erase(get_instance_id());
@@ -571,7 +572,7 @@ Error GDScript::reload(bool p_keep_state) {
}
valid = false;
- GDParser parser;
+ GDScriptParser parser;
Error err = parser.parse(source, basedir, false, path);
if (err) {
if (ScriptDebugger::get_singleton()) {
@@ -583,7 +584,7 @@ Error GDScript::reload(bool p_keep_state) {
bool can_run = ScriptServer::is_scripting_enabled() || parser.is_tool_script();
- GDCompiler compiler;
+ GDScriptCompiler compiler;
err = compiler.compile(&parser, this, p_keep_state);
if (err) {
@@ -609,14 +610,26 @@ Error GDScript::reload(bool p_keep_state) {
return OK;
}
-String GDScript::get_node_type() const {
+ScriptLanguage *GDScript::get_language() const {
- return ""; // ?
+ return GDScriptLanguage::get_singleton();
}
-ScriptLanguage *GDScript::get_language() const {
+void GDScript::get_constants(Map<StringName, Variant> *p_constants) {
- return GDScriptLanguage::get_singleton();
+ if (p_constants) {
+ for (Map<StringName, Variant>::Element *E = constants.front(); E; E = E->next()) {
+ (*p_constants)[E->key()] = E->value();
+ }
+ }
+}
+
+void GDScript::get_members(Set<StringName> *p_members) {
+ if (p_members) {
+ for (Set<StringName>::Element *E = members.front(); E; E = E->next()) {
+ p_members->insert(E->get());
+ }
+ }
}
Variant GDScript::call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error) {
@@ -624,7 +637,7 @@ Variant GDScript::call(const StringName &p_method, const Variant **p_args, int p
GDScript *top = this;
while (top) {
- Map<StringName, GDFunction *>::Element *E = top->member_functions.find(p_method);
+ Map<StringName, GDScriptFunction *>::Element *E = top->member_functions.find(p_method);
if (E) {
if (!E->get()->is_static()) {
@@ -703,7 +716,7 @@ void GDScript::_bind_methods() {
Vector<uint8_t> GDScript::get_as_byte_code() const {
- GDTokenizerBuffer tokenizer;
+ GDScriptTokenizerBuffer tokenizer;
return tokenizer.parse_code_string(source);
};
@@ -743,14 +756,14 @@ Error GDScript::load_byte_code(const String &p_path) {
basedir = basedir.get_base_dir();
valid = false;
- GDParser parser;
+ GDScriptParser parser;
Error err = parser.parse_bytecode(bytecode, basedir, get_path());
if (err) {
_err_print_error("GDScript::load_byte_code", path.empty() ? "built-in" : (const char *)path.utf8().get_data(), parser.get_error_line(), ("Parse Error: " + parser.get_error()).utf8().get_data(), ERR_HANDLER_SCRIPT);
ERR_FAIL_V(ERR_PARSE_ERROR);
}
- GDCompiler compiler;
+ GDScriptCompiler compiler;
err = compiler.compile(&parser, this);
if (err) {
@@ -803,7 +816,7 @@ Error GDScript::load_source_code(const String &p_path) {
return OK;
}
-const Map<StringName, GDFunction *> &GDScript::debug_get_member_functions() const {
+const Map<StringName, GDScriptFunction *> &GDScript::debug_get_member_functions() const {
return member_functions;
}
@@ -890,7 +903,7 @@ GDScript::GDScript()
}
GDScript::~GDScript() {
- for (Map<StringName, GDFunction *>::Element *E = member_functions.front(); E; E = E->next()) {
+ for (Map<StringName, GDScriptFunction *>::Element *E = member_functions.front(); E; E = E->next()) {
memdelete(E->get());
}
@@ -914,7 +927,7 @@ GDScript::~GDScript() {
// INSTANCE //
//////////////////////////////
-bool GDInstance::set(const StringName &p_name, const Variant &p_value) {
+bool GDScriptInstance::set(const StringName &p_name, const Variant &p_value) {
//member
{
@@ -936,7 +949,7 @@ bool GDInstance::set(const StringName &p_name, const Variant &p_value) {
GDScript *sptr = script.ptr();
while (sptr) {
- Map<StringName, GDFunction *>::Element *E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._set);
+ Map<StringName, GDScriptFunction *>::Element *E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._set);
if (E) {
Variant name = p_name;
@@ -953,7 +966,7 @@ bool GDInstance::set(const StringName &p_name, const Variant &p_value) {
return false;
}
-bool GDInstance::get(const StringName &p_name, Variant &r_ret) const {
+bool GDScriptInstance::get(const StringName &p_name, Variant &r_ret) const {
const GDScript *sptr = script.ptr();
while (sptr) {
@@ -963,7 +976,7 @@ bool GDInstance::get(const StringName &p_name, Variant &r_ret) const {
if (E) {
if (E->get().getter) {
Variant::CallError err;
- r_ret = const_cast<GDInstance *>(this)->call(E->get().getter, NULL, 0, err);
+ r_ret = const_cast<GDScriptInstance *>(this)->call(E->get().getter, NULL, 0, err);
if (err.error == Variant::CallError::CALL_OK) {
return true;
}
@@ -987,14 +1000,14 @@ bool GDInstance::get(const StringName &p_name, Variant &r_ret) const {
}
{
- const Map<StringName, GDFunction *>::Element *E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._get);
+ const Map<StringName, GDScriptFunction *>::Element *E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._get);
if (E) {
Variant name = p_name;
const Variant *args[1] = { &name };
Variant::CallError err;
- Variant ret = const_cast<GDFunction *>(E->get())->call(const_cast<GDInstance *>(this), (const Variant **)args, 1, err);
+ Variant ret = const_cast<GDScriptFunction *>(E->get())->call(const_cast<GDScriptInstance *>(this), (const Variant **)args, 1, err);
if (err.error == Variant::CallError::CALL_OK && ret.get_type() != Variant::NIL) {
r_ret = ret;
return true;
@@ -1007,7 +1020,7 @@ bool GDInstance::get(const StringName &p_name, Variant &r_ret) const {
return false;
}
-Variant::Type GDInstance::get_property_type(const StringName &p_name, bool *r_is_valid) const {
+Variant::Type GDScriptInstance::get_property_type(const StringName &p_name, bool *r_is_valid) const {
const GDScript *sptr = script.ptr();
while (sptr) {
@@ -1025,7 +1038,7 @@ Variant::Type GDInstance::get_property_type(const StringName &p_name, bool *r_is
return Variant::NIL;
}
-void GDInstance::get_property_list(List<PropertyInfo> *p_properties) const {
+void GDScriptInstance::get_property_list(List<PropertyInfo> *p_properties) const {
// exported members, not doen yet!
const GDScript *sptr = script.ptr();
@@ -1033,11 +1046,11 @@ void GDInstance::get_property_list(List<PropertyInfo> *p_properties) const {
while (sptr) {
- const Map<StringName, GDFunction *>::Element *E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._get_property_list);
+ const Map<StringName, GDScriptFunction *>::Element *E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._get_property_list);
if (E) {
Variant::CallError err;
- Variant ret = const_cast<GDFunction *>(E->get())->call(const_cast<GDInstance *>(this), NULL, 0, err);
+ Variant ret = const_cast<GDScriptFunction *>(E->get())->call(const_cast<GDScriptInstance *>(this), NULL, 0, err);
if (err.error == Variant::CallError::CALL_OK) {
if (ret.get_type() != Variant::ARRAY) {
@@ -1096,12 +1109,12 @@ void GDInstance::get_property_list(List<PropertyInfo> *p_properties) const {
}
}
-void GDInstance::get_method_list(List<MethodInfo> *p_list) const {
+void GDScriptInstance::get_method_list(List<MethodInfo> *p_list) const {
const GDScript *sptr = script.ptr();
while (sptr) {
- for (Map<StringName, GDFunction *>::Element *E = sptr->member_functions.front(); E; E = E->next()) {
+ for (Map<StringName, GDScriptFunction *>::Element *E = sptr->member_functions.front(); E; E = E->next()) {
MethodInfo mi;
mi.name = E->key();
@@ -1114,11 +1127,11 @@ void GDInstance::get_method_list(List<MethodInfo> *p_list) const {
}
}
-bool GDInstance::has_method(const StringName &p_method) const {
+bool GDScriptInstance::has_method(const StringName &p_method) const {
const GDScript *sptr = script.ptr();
while (sptr) {
- const Map<StringName, GDFunction *>::Element *E = sptr->member_functions.find(p_method);
+ const Map<StringName, GDScriptFunction *>::Element *E = sptr->member_functions.find(p_method);
if (E)
return true;
sptr = sptr->_base;
@@ -1126,13 +1139,13 @@ bool GDInstance::has_method(const StringName &p_method) const {
return false;
}
-Variant GDInstance::call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error) {
+Variant GDScriptInstance::call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error) {
//printf("calling %ls:%i method %ls\n", script->get_path().c_str(), -1, String(p_method).c_str());
GDScript *sptr = script.ptr();
while (sptr) {
- Map<StringName, GDFunction *>::Element *E = sptr->member_functions.find(p_method);
+ Map<StringName, GDScriptFunction *>::Element *E = sptr->member_functions.find(p_method);
if (E) {
return E->get()->call(this, p_args, p_argcount, r_error);
}
@@ -1142,13 +1155,13 @@ Variant GDInstance::call(const StringName &p_method, const Variant **p_args, int
return Variant();
}
-void GDInstance::call_multilevel(const StringName &p_method, const Variant **p_args, int p_argcount) {
+void GDScriptInstance::call_multilevel(const StringName &p_method, const Variant **p_args, int p_argcount) {
GDScript *sptr = script.ptr();
Variant::CallError ce;
while (sptr) {
- Map<StringName, GDFunction *>::Element *E = sptr->member_functions.find(p_method);
+ Map<StringName, GDScriptFunction *>::Element *E = sptr->member_functions.find(p_method);
if (E) {
E->get()->call(this, p_args, p_argcount, ce);
}
@@ -1156,27 +1169,27 @@ void GDInstance::call_multilevel(const StringName &p_method, const Variant **p_a
}
}
-void GDInstance::_ml_call_reversed(GDScript *sptr, const StringName &p_method, const Variant **p_args, int p_argcount) {
+void GDScriptInstance::_ml_call_reversed(GDScript *sptr, const StringName &p_method, const Variant **p_args, int p_argcount) {
if (sptr->_base)
_ml_call_reversed(sptr->_base, p_method, p_args, p_argcount);
Variant::CallError ce;
- Map<StringName, GDFunction *>::Element *E = sptr->member_functions.find(p_method);
+ Map<StringName, GDScriptFunction *>::Element *E = sptr->member_functions.find(p_method);
if (E) {
E->get()->call(this, p_args, p_argcount, ce);
}
}
-void GDInstance::call_multilevel_reversed(const StringName &p_method, const Variant **p_args, int p_argcount) {
+void GDScriptInstance::call_multilevel_reversed(const StringName &p_method, const Variant **p_args, int p_argcount) {
if (script.ptr()) {
_ml_call_reversed(script.ptr(), p_method, p_args, p_argcount);
}
}
-void GDInstance::notification(int p_notification) {
+void GDScriptInstance::notification(int p_notification) {
//notification is not virtual, it gets called at ALL levels just like in C.
Variant value = p_notification;
@@ -1184,7 +1197,7 @@ void GDInstance::notification(int p_notification) {
GDScript *sptr = script.ptr();
while (sptr) {
- Map<StringName, GDFunction *>::Element *E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._notification);
+ Map<StringName, GDScriptFunction *>::Element *E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._notification);
if (E) {
Variant::CallError err;
E->get()->call(this, args, 1, err);
@@ -1196,22 +1209,22 @@ void GDInstance::notification(int p_notification) {
}
}
-Ref<Script> GDInstance::get_script() const {
+Ref<Script> GDScriptInstance::get_script() const {
return script;
}
-ScriptLanguage *GDInstance::get_language() {
+ScriptLanguage *GDScriptInstance::get_language() {
return GDScriptLanguage::get_singleton();
}
-GDInstance::RPCMode GDInstance::get_rpc_mode(const StringName &p_method) const {
+GDScriptInstance::RPCMode GDScriptInstance::get_rpc_mode(const StringName &p_method) const {
const GDScript *cscript = script.ptr();
while (cscript) {
- const Map<StringName, GDFunction *>::Element *E = cscript->member_functions.find(p_method);
+ const Map<StringName, GDScriptFunction *>::Element *E = cscript->member_functions.find(p_method);
if (E) {
if (E->get()->get_rpc_mode() != RPC_MODE_DISABLED) {
@@ -1224,7 +1237,7 @@ GDInstance::RPCMode GDInstance::get_rpc_mode(const StringName &p_method) const {
return RPC_MODE_DISABLED;
}
-GDInstance::RPCMode GDInstance::get_rset_mode(const StringName &p_variable) const {
+GDScriptInstance::RPCMode GDScriptInstance::get_rset_mode(const StringName &p_variable) const {
const GDScript *cscript = script.ptr();
@@ -1242,7 +1255,7 @@ GDInstance::RPCMode GDInstance::get_rset_mode(const StringName &p_variable) cons
return RPC_MODE_DISABLED;
}
-void GDInstance::reload_members() {
+void GDScriptInstance::reload_members() {
#ifdef DEBUG_ENABLED
@@ -1273,12 +1286,12 @@ void GDInstance::reload_members() {
#endif
}
-GDInstance::GDInstance() {
+GDScriptInstance::GDScriptInstance() {
owner = NULL;
base_ref = false;
}
-GDInstance::~GDInstance() {
+GDScriptInstance::~GDScriptInstance() {
if (script.is_valid() && owner) {
#ifndef NO_THREADS
GDScriptLanguage::singleton->lock->lock();
@@ -1329,6 +1342,7 @@ void GDScriptLanguage::init() {
}
_add_global(StaticCString::create("PI"), Math_PI);
+ _add_global(StaticCString::create("TAU"), Math_TAU);
_add_global(StaticCString::create("INF"), Math_INF);
_add_global(StaticCString::create("NAN"), Math_NAN);
@@ -1345,15 +1359,15 @@ void GDScriptLanguage::init() {
if (globals.has(n))
continue;
- Ref<GDNativeClass> nc = memnew(GDNativeClass(E->get()));
+ Ref<GDScriptNativeClass> nc = memnew(GDScriptNativeClass(E->get()));
_add_global(n, nc);
}
//populate singletons
- List<ProjectSettings::Singleton> singletons;
- ProjectSettings::get_singleton()->get_singletons(&singletons);
- for (List<ProjectSettings::Singleton>::Element *E = singletons.front(); E; E = E->next()) {
+ List<Engine::Singleton> singletons;
+ Engine::get_singleton()->get_singletons(&singletons);
+ for (List<Engine::Singleton>::Element *E = singletons.front(); E; E = E->next()) {
_add_global(E->get().name, E->get().ptr);
}
@@ -1382,7 +1396,7 @@ void GDScriptLanguage::profiling_start() {
lock->lock();
}
- SelfList<GDFunction> *elem = function_list.first();
+ SelfList<GDScriptFunction> *elem = function_list.first();
while (elem) {
elem->self()->profile.call_count = 0;
elem->self()->profile.self_time = 0;
@@ -1427,7 +1441,7 @@ int GDScriptLanguage::profiling_get_accumulated_data(ProfilingInfo *p_info_arr,
lock->lock();
}
- SelfList<GDFunction> *elem = function_list.first();
+ SelfList<GDScriptFunction> *elem = function_list.first();
while (elem) {
if (current >= p_info_max)
break;
@@ -1457,7 +1471,7 @@ int GDScriptLanguage::profiling_get_frame_data(ProfilingInfo *p_info_arr, int p_
lock->lock();
}
- SelfList<GDFunction> *elem = function_list.first();
+ SelfList<GDScriptFunction> *elem = function_list.first();
while (elem) {
if (current >= p_info_max)
break;
@@ -1602,17 +1616,18 @@ void GDScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_so
Object *obj = E->get()->placeholders.front()->get()->get_owner();
//save instance info
- List<Pair<StringName, Variant> > state;
if (obj->get_script_instance()) {
+ map.insert(obj->get_instance_id(), List<Pair<StringName, Variant> >());
+ List<Pair<StringName, Variant> > &state = map[obj->get_instance_id()];
obj->get_script_instance()->get_property_state(state);
- map[obj->get_instance_id()] = state;
obj->set_script(RefPtr());
} else {
// no instance found. Let's remove it so we don't loop forever
E->get()->placeholders.erase(E->get()->placeholders.front()->get());
}
}
+
#endif
for (Map<ObjectID, List<Pair<StringName, Variant> > >::Element *F = E->get()->pending_reload_state.front(); F; F = F->next()) {
@@ -1670,7 +1685,7 @@ void GDScriptLanguage::frame() {
lock->lock();
}
- SelfList<GDFunction> *elem = function_list.first();
+ SelfList<GDScriptFunction> *elem = function_list.first();
while (elem) {
elem->self()->profile.last_frame_call_count = elem->self()->profile.frame_call_count;
elem->self()->profile.last_frame_self_time = elem->self()->profile.frame_self_time;
@@ -1705,6 +1720,7 @@ void GDScriptLanguage::get_reserved_words(List<String> *p_words) const {
"bool",
"null",
"PI",
+ "TAU",
"INF",
"NAN",
"self",
@@ -1754,8 +1770,8 @@ void GDScriptLanguage::get_reserved_words(List<String> *p_words) const {
w++;
}
- for (int i = 0; i < GDFunctions::FUNC_MAX; i++) {
- p_words->push_back(GDFunctions::get_func_name(GDFunctions::Function(i)));
+ for (int i = 0; i < GDScriptFunctions::FUNC_MAX; i++) {
+ p_words->push_back(GDScriptFunctions::get_func_name(GDScriptFunctions::Function(i)));
}
}
diff --git a/modules/gdscript/gd_script.h b/modules/gdscript/gdscript.h
index 5e1a8b19ac..6e5d59ad0e 100644
--- a/modules/gdscript/gd_script.h
+++ b/modules/gdscript/gdscript.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* gd_script.h */
+/* gdscript.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -27,16 +27,17 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef GD_SCRIPT_H
-#define GD_SCRIPT_H
+#ifndef GDSCRIPT_H
+#define GDSCRIPT_H
-#include "gd_function.h"
+#include "gdscript_function.h"
#include "io/resource_loader.h"
#include "io/resource_saver.h"
#include "script_language.h"
-class GDNativeClass : public Reference {
- GDCLASS(GDNativeClass, Reference);
+class GDScriptNativeClass : public Reference {
+
+ GDCLASS(GDScriptNativeClass, Reference);
StringName name;
@@ -48,7 +49,7 @@ public:
_FORCE_INLINE_ const StringName &get_name() const { return name; }
Variant _new();
Object *instance();
- GDNativeClass(const StringName &p_name);
+ GDScriptNativeClass(const StringName &p_name);
};
class GDScript : public Script {
@@ -64,21 +65,21 @@ class GDScript : public Script {
ScriptInstance::RPCMode rpc_mode;
};
- friend class GDInstance;
- friend class GDFunction;
- friend class GDCompiler;
- friend class GDFunctions;
+ friend class GDScriptInstance;
+ friend class GDScriptFunction;
+ friend class GDScriptCompiler;
+ friend class GDScriptFunctions;
friend class GDScriptLanguage;
Variant _static_ref; //used for static call
- Ref<GDNativeClass> native;
+ Ref<GDScriptNativeClass> native;
Ref<GDScript> base;
GDScript *_base; //fast pointer access
GDScript *_owner; //for subclasses
Set<StringName> members; //members are just indices to the instanced script.
Map<StringName, Variant> constants;
- Map<StringName, GDFunction *> member_functions;
+ Map<StringName, GDScriptFunction *> member_functions;
Map<StringName, MemberInfo> member_indices; //members are just indices to the instanced script.
Map<StringName, Ref<GDScript> > subclasses;
Map<StringName, Vector<StringName> > _signals;
@@ -99,7 +100,7 @@ class GDScript : public Script {
#endif
Map<StringName, PropertyInfo> member_info;
- GDFunction *initializer; //direct pointer to _init , faster to locate
+ GDScriptFunction *initializer; //direct pointer to _init , faster to locate
int subclass_count;
Set<Object *> instances;
@@ -109,7 +110,7 @@ class GDScript : public Script {
String name;
SelfList<GDScript> script_list;
- GDInstance *_create_instance(const Variant **p_args, int p_argcount, Object *p_owner, bool p_isref, Variant::CallError &r_error);
+ GDScriptInstance *_create_instance(const Variant **p_args, int p_argcount, Object *p_owner, bool p_isref, Variant::CallError &r_error);
void _set_subclass_path(Ref<GDScript> &p_sc, const String &p_path);
@@ -143,8 +144,8 @@ public:
const Map<StringName, Ref<GDScript> > &get_subclasses() const { return subclasses; }
const Map<StringName, Variant> &get_constants() const { return constants; }
const Set<StringName> &get_members() const { return members; }
- const Map<StringName, GDFunction *> &get_member_functions() const { return member_functions; }
- const Ref<GDNativeClass> &get_native() const { return native; }
+ const Map<StringName, GDScriptFunction *> &get_member_functions() const { return member_functions; }
+ const Ref<GDScriptNativeClass> &get_native() const { return native; }
virtual bool has_script_signal(const StringName &p_signal) const;
virtual void get_script_signal_list(List<MethodInfo> *r_signals) const;
@@ -153,7 +154,7 @@ public:
Ref<GDScript> get_base() const;
const Map<StringName, MemberInfo> &debug_get_member_indices() const { return member_indices; }
- const Map<StringName, GDFunction *> &debug_get_member_functions() const; //this is debug only
+ const Map<StringName, GDScriptFunction *> &debug_get_member_functions() const; //this is debug only
StringName debug_get_member_by_index(int p_idx) const;
Variant _new(const Variant **p_args, int p_argcount, Variant::CallError &r_error);
@@ -172,7 +173,6 @@ public:
virtual Error reload(bool p_keep_state = false);
- virtual String get_node_type() const;
void set_script_path(const String &p_path) { path = p_path; } //because subclasses need a path too...
Error load_source_code(const String &p_path);
Error load_byte_code(const String &p_path);
@@ -198,15 +198,18 @@ public:
return -1;
}
+ virtual void get_constants(Map<StringName, Variant> *p_constants);
+ virtual void get_members(Set<StringName> *p_members);
+
GDScript();
~GDScript();
};
-class GDInstance : public ScriptInstance {
+class GDScriptInstance : public ScriptInstance {
friend class GDScript;
- friend class GDFunction;
- friend class GDFunctions;
- friend class GDCompiler;
+ friend class GDScriptFunction;
+ friend class GDScriptFunctions;
+ friend class GDScriptCompiler;
Object *owner;
Ref<GDScript> script;
@@ -219,7 +222,7 @@ class GDInstance : public ScriptInstance {
void _ml_call_reversed(GDScript *sptr, const StringName &p_method, const Variant **p_args, int p_argcount);
public:
- _FORCE_INLINE_ Object *get_owner() { return owner; }
+ virtual Object *get_owner() { return owner; }
virtual bool set(const StringName &p_name, const Variant &p_value);
virtual bool get(const StringName &p_name, Variant &r_ret) const;
@@ -247,8 +250,8 @@ public:
virtual RPCMode get_rpc_mode(const StringName &p_method) const;
virtual RPCMode get_rset_mode(const StringName &p_variable) const;
- GDInstance();
- ~GDInstance();
+ GDScriptInstance();
+ ~GDScriptInstance();
};
class GDScriptLanguage : public ScriptLanguage {
@@ -262,8 +265,8 @@ class GDScriptLanguage : public ScriptLanguage {
struct CallLevel {
Variant *stack;
- GDFunction *function;
- GDInstance *instance;
+ GDScriptFunction *function;
+ GDScriptInstance *instance;
int *ip;
int *line;
};
@@ -277,16 +280,16 @@ class GDScriptLanguage : public ScriptLanguage {
void _add_global(const StringName &p_name, const Variant &p_value);
- friend class GDInstance;
+ friend class GDScriptInstance;
Mutex *lock;
friend class GDScript;
SelfList<GDScript>::List script_list;
- friend class GDFunction;
+ friend class GDScriptFunction;
- SelfList<GDFunction>::List function_list;
+ SelfList<GDScriptFunction>::List function_list;
bool profiling;
uint64_t script_frame_time;
@@ -296,7 +299,7 @@ public:
bool debug_break(const String &p_error, bool p_allow_continue = true);
bool debug_break_parse(const String &p_file, int p_line, const String &p_error);
- _FORCE_INLINE_ void enter_function(GDInstance *p_instance, GDFunction *p_function, Variant *p_stack, int *p_ip, int *p_line) {
+ _FORCE_INLINE_ void enter_function(GDScriptInstance *p_instance, GDScriptFunction *p_function, Variant *p_stack, int *p_ip, int *p_line) {
if (Thread::get_main_id() != Thread::get_caller_id())
return; //no support for other threads than main for now
@@ -386,6 +389,7 @@ public:
virtual bool validate(const String &p_script, int &r_line_error, int &r_col_error, String &r_test_error, const String &p_path = "", List<String> *r_functions = NULL) const;
virtual Script *create_script() const;
virtual bool has_named_classes() const;
+ virtual bool supports_builtin_mode() const;
virtual bool can_inherit_from_file() { return true; }
virtual int find_function(const String &p_function, const String &p_code) const;
virtual String make_function(const String &p_class, const String &p_name, const PoolStringArray &p_args) const;
@@ -406,7 +410,8 @@ public:
virtual String debug_get_stack_level_source(int p_level) const;
virtual void debug_get_stack_level_locals(int p_level, List<String> *p_locals, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1);
virtual void debug_get_stack_level_members(int p_level, List<String> *p_members, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1);
- virtual void debug_get_globals(List<String> *p_locals, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1);
+ virtual ScriptInstance *debug_get_stack_level_instance(int p_level);
+ virtual void debug_get_globals(List<String> *p_globals, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1);
virtual String debug_parse_stack_level_expression(int p_level, const String &p_expression, int p_max_subitems = -1, int p_max_depth = -1);
virtual void reload_all_scripts();
@@ -446,4 +451,4 @@ public:
virtual bool recognize(const RES &p_resource) const;
};
-#endif // GD_SCRIPT_H
+#endif // GDSCRIPT_H
diff --git a/modules/gdscript/gd_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp
index 7036a708e5..4cd6472b7f 100644
--- a/modules/gdscript/gd_compiler.cpp
+++ b/modules/gdscript/gdscript_compiler.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* gd_compiler.cpp */
+/* gdscript_compiler.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -27,10 +27,11 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "gd_compiler.h"
-#include "gd_script.h"
+#include "gdscript_compiler.h"
-bool GDCompiler::_is_class_member_property(CodeGen &codegen, const StringName &p_name) {
+#include "gdscript.h"
+
+bool GDScriptCompiler::_is_class_member_property(CodeGen &codegen, const StringName &p_name) {
if (!codegen.function_node || codegen.function_node->_static)
return false;
@@ -38,10 +39,10 @@ bool GDCompiler::_is_class_member_property(CodeGen &codegen, const StringName &p
return _is_class_member_property(codegen.script, p_name);
}
-bool GDCompiler::_is_class_member_property(GDScript *owner, const StringName &p_name) {
+bool GDScriptCompiler::_is_class_member_property(GDScript *owner, const StringName &p_name) {
GDScript *scr = owner;
- GDNativeClass *nc = NULL;
+ GDScriptNativeClass *nc = NULL;
while (scr) {
if (scr->native.is_valid())
@@ -54,7 +55,7 @@ bool GDCompiler::_is_class_member_property(GDScript *owner, const StringName &p_
return ClassDB::has_property(nc->get_name(), p_name);
}
-void GDCompiler::_set_error(const String &p_error, const GDParser::Node *p_node) {
+void GDScriptCompiler::_set_error(const String &p_error, const GDScriptParser::Node *p_node) {
if (error != "")
return;
@@ -69,7 +70,7 @@ void GDCompiler::_set_error(const String &p_error, const GDParser::Node *p_node)
}
}
-bool GDCompiler::_create_unary_operator(CodeGen &codegen, const GDParser::OperatorNode *on, Variant::Operator op, int p_stack_level) {
+bool GDScriptCompiler::_create_unary_operator(CodeGen &codegen, const GDScriptParser::OperatorNode *on, Variant::Operator op, int p_stack_level) {
ERR_FAIL_COND_V(on->arguments.size() != 1, false);
@@ -77,29 +78,29 @@ bool GDCompiler::_create_unary_operator(CodeGen &codegen, const GDParser::Operat
if (src_address_a < 0)
return false;
- codegen.opcodes.push_back(GDFunction::OPCODE_OPERATOR); // perform operator
+ codegen.opcodes.push_back(GDScriptFunction::OPCODE_OPERATOR); // perform operator
codegen.opcodes.push_back(op); //which operator
codegen.opcodes.push_back(src_address_a); // argument 1
codegen.opcodes.push_back(src_address_a); // argument 2 (repeated)
- //codegen.opcodes.push_back(GDFunction::ADDR_TYPE_NIL); // argument 2 (unary only takes one parameter)
+ //codegen.opcodes.push_back(GDScriptFunction::ADDR_TYPE_NIL); // argument 2 (unary only takes one parameter)
return true;
}
-bool GDCompiler::_create_binary_operator(CodeGen &codegen, const GDParser::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) {
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);
if (src_address_a < 0)
return false;
- if (src_address_a & GDFunction::ADDR_TYPE_STACK << GDFunction::ADDR_BITS)
+ if (src_address_a & GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS)
p_stack_level++; //uses stack for return, increase stack
int src_address_b = _parse_expression(codegen, on->arguments[1], p_stack_level, false, p_initializer);
if (src_address_b < 0)
return false;
- codegen.opcodes.push_back(GDFunction::OPCODE_OPERATOR); // perform operator
+ codegen.opcodes.push_back(GDScriptFunction::OPCODE_OPERATOR); // perform operator
codegen.opcodes.push_back(op); //which operator
codegen.opcodes.push_back(src_address_a); // argument 1
codegen.opcodes.push_back(src_address_b); // argument 2 (unary only takes one parameter)
@@ -107,14 +108,14 @@ bool GDCompiler::_create_binary_operator(CodeGen &codegen, const GDParser::Opera
}
/*
-int GDCompiler::_parse_subexpression(CodeGen& codegen,const GDParser::Node *p_expression) {
+int GDScriptCompiler::_parse_subexpression(CodeGen& codegen,const GDScriptParser::Node *p_expression) {
int ret = _parse_expression(codegen,p_expression);
if (ret<0)
return ret;
- if (ret&(GDFunction::ADDR_TYPE_STACK<<GDFunction::ADDR_BITS)) {
+ if (ret&(GDScriptFunction::ADDR_TYPE_STACK<<GDScriptFunction::ADDR_BITS)) {
codegen.stack_level++;
codegen.check_max_stack_level();
//stack was used, keep value
@@ -124,24 +125,24 @@ int GDCompiler::_parse_subexpression(CodeGen& codegen,const GDParser::Node *p_ex
}
*/
-int GDCompiler::_parse_assign_right_expression(CodeGen &codegen, const GDParser::OperatorNode *p_expression, int p_stack_level) {
+int GDScriptCompiler::_parse_assign_right_expression(CodeGen &codegen, const GDScriptParser::OperatorNode *p_expression, int p_stack_level) {
Variant::Operator var_op = Variant::OP_MAX;
switch (p_expression->op) {
- case GDParser::OperatorNode::OP_ASSIGN_ADD: var_op = Variant::OP_ADD; break;
- case GDParser::OperatorNode::OP_ASSIGN_SUB: var_op = Variant::OP_SUBTRACT; break;
- case GDParser::OperatorNode::OP_ASSIGN_MUL: var_op = Variant::OP_MULTIPLY; break;
- case GDParser::OperatorNode::OP_ASSIGN_DIV: var_op = Variant::OP_DIVIDE; break;
- case GDParser::OperatorNode::OP_ASSIGN_MOD: var_op = Variant::OP_MODULE; break;
- case GDParser::OperatorNode::OP_ASSIGN_SHIFT_LEFT: var_op = Variant::OP_SHIFT_LEFT; break;
- case GDParser::OperatorNode::OP_ASSIGN_SHIFT_RIGHT: var_op = Variant::OP_SHIFT_RIGHT; break;
- case GDParser::OperatorNode::OP_ASSIGN_BIT_AND: var_op = Variant::OP_BIT_AND; break;
- case GDParser::OperatorNode::OP_ASSIGN_BIT_OR: var_op = Variant::OP_BIT_OR; break;
- case GDParser::OperatorNode::OP_ASSIGN_BIT_XOR: var_op = Variant::OP_BIT_XOR; break;
- case GDParser::OperatorNode::OP_INIT_ASSIGN:
- case GDParser::OperatorNode::OP_ASSIGN: {
+ case GDScriptParser::OperatorNode::OP_ASSIGN_ADD: var_op = Variant::OP_ADD; break;
+ case GDScriptParser::OperatorNode::OP_ASSIGN_SUB: var_op = Variant::OP_SUBTRACT; break;
+ case GDScriptParser::OperatorNode::OP_ASSIGN_MUL: var_op = Variant::OP_MULTIPLY; break;
+ case GDScriptParser::OperatorNode::OP_ASSIGN_DIV: var_op = Variant::OP_DIVIDE; break;
+ case GDScriptParser::OperatorNode::OP_ASSIGN_MOD: var_op = Variant::OP_MODULE; break;
+ case GDScriptParser::OperatorNode::OP_ASSIGN_SHIFT_LEFT: var_op = Variant::OP_SHIFT_LEFT; break;
+ case GDScriptParser::OperatorNode::OP_ASSIGN_SHIFT_RIGHT: var_op = Variant::OP_SHIFT_RIGHT; break;
+ case GDScriptParser::OperatorNode::OP_ASSIGN_BIT_AND: var_op = Variant::OP_BIT_AND; break;
+ case GDScriptParser::OperatorNode::OP_ASSIGN_BIT_OR: var_op = Variant::OP_BIT_OR; break;
+ case GDScriptParser::OperatorNode::OP_ASSIGN_BIT_XOR: var_op = Variant::OP_BIT_XOR; break;
+ case GDScriptParser::OperatorNode::OP_INIT_ASSIGN:
+ case GDScriptParser::OperatorNode::OP_ASSIGN: {
//none
} break;
@@ -151,7 +152,7 @@ int GDCompiler::_parse_assign_right_expression(CodeGen &codegen, const GDParser:
}
}
- bool initializer = p_expression->op == GDParser::OperatorNode::OP_INIT_ASSIGN;
+ bool initializer = p_expression->op == GDScriptParser::OperatorNode::OP_INIT_ASSIGN;
if (var_op == Variant::OP_MAX) {
@@ -161,32 +162,32 @@ int GDCompiler::_parse_assign_right_expression(CodeGen &codegen, const GDParser:
if (!_create_binary_operator(codegen, p_expression, var_op, p_stack_level, initializer))
return -1;
- int dst_addr = (p_stack_level) | (GDFunction::ADDR_TYPE_STACK << GDFunction::ADDR_BITS);
+ int dst_addr = (p_stack_level) | (GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS);
codegen.opcodes.push_back(dst_addr); // append the stack level as destination address of the opcode
codegen.alloc_stack(p_stack_level);
return dst_addr;
}
-int GDCompiler::_parse_expression(CodeGen &codegen, const GDParser::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) {
switch (p_expression->type) {
//should parse variable declaration and adjust stack accordingly...
- case GDParser::Node::TYPE_IDENTIFIER: {
+ case GDScriptParser::Node::TYPE_IDENTIFIER: {
//return identifier
//wait, identifier could be a local variable or something else... careful here, must reference properly
//as stack may be more interesting to work with
//This could be made much simpler by just indexing "self", but done this way (with custom self-addressing modes) increases peformance a lot.
- const GDParser::IdentifierNode *in = static_cast<const GDParser::IdentifierNode *>(p_expression);
+ const GDScriptParser::IdentifierNode *in = static_cast<const GDScriptParser::IdentifierNode *>(p_expression);
StringName identifier = in->name;
if (_is_class_member_property(codegen, identifier)) {
//get property
- codegen.opcodes.push_back(GDFunction::OPCODE_GET_MEMBER); // perform operator
+ codegen.opcodes.push_back(GDScriptFunction::OPCODE_GET_MEMBER); // perform operator
codegen.opcodes.push_back(codegen.get_name_map_pos(identifier)); // argument 2 (unary only takes one parameter)
- int dst_addr = (p_stack_level) | (GDFunction::ADDR_TYPE_STACK << GDFunction::ADDR_BITS);
+ int dst_addr = (p_stack_level) | (GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS);
codegen.opcodes.push_back(dst_addr); // append the stack level as destination address of the opcode
codegen.alloc_stack(p_stack_level);
return dst_addr;
@@ -196,7 +197,7 @@ int GDCompiler::_parse_expression(CodeGen &codegen, const GDParser::Node *p_expr
if (!p_initializer && codegen.stack_identifiers.has(identifier)) {
int pos = codegen.stack_identifiers[identifier];
- return pos | (GDFunction::ADDR_TYPE_STACK_VARIABLE << GDFunction::ADDR_BITS);
+ return pos | (GDScriptFunction::ADDR_TYPE_STACK_VARIABLE << GDScriptFunction::ADDR_BITS);
}
//TRY MEMBERS!
if (!codegen.function_node || !codegen.function_node->_static) {
@@ -206,7 +207,7 @@ int GDCompiler::_parse_expression(CodeGen &codegen, const GDParser::Node *p_expr
if (codegen.script->member_indices.has(identifier)) {
int idx = codegen.script->member_indices[identifier].index;
- return idx | (GDFunction::ADDR_TYPE_MEMBER << GDFunction::ADDR_BITS); //argument (stack root)
+ return idx | (GDScriptFunction::ADDR_TYPE_MEMBER << GDScriptFunction::ADDR_BITS); //argument (stack root)
}
}
@@ -216,14 +217,14 @@ int GDCompiler::_parse_expression(CodeGen &codegen, const GDParser::Node *p_expr
while (owner) {
GDScript *scr = owner;
- GDNativeClass *nc = NULL;
+ GDScriptNativeClass *nc = NULL;
while (scr) {
if (scr->constants.has(identifier)) {
//int idx=scr->constants[identifier];
int idx = codegen.get_name_map_pos(identifier);
- return idx | (GDFunction::ADDR_TYPE_CLASS_CONSTANT << GDFunction::ADDR_BITS); //argument (stack root)
+ return idx | (GDScriptFunction::ADDR_TYPE_CLASS_CONSTANT << GDScriptFunction::ADDR_BITS); //argument (stack root)
}
if (scr->native.is_valid())
nc = scr->native.ptr();
@@ -249,7 +250,7 @@ int GDCompiler::_parse_expression(CodeGen &codegen, const GDParser::Node *p_expr
idx = codegen.constant_map[key];
}
- return idx | (GDFunction::ADDR_TYPE_LOCAL_CONSTANT << GDFunction::ADDR_BITS); //make it a local constant (faster access)
+ return idx | (GDScriptFunction::ADDR_TYPE_LOCAL_CONSTANT << GDScriptFunction::ADDR_BITS); //make it a local constant (faster access)
}
}
@@ -261,14 +262,14 @@ int GDCompiler::_parse_expression(CodeGen &codegen, const GDParser::Node *p_expr
if (codegen.script->subclasses.has(identifier)) {
//same with a subclass, make it a local constant.
int idx = codegen.get_constant_pos(codegen.script->subclasses[identifier]);
- return idx|(GDFunction::ADDR_TYPE_LOCAL_CONSTANT<<GDFunction::ADDR_BITS); //make it a local constant (faster access)
+ return idx|(GDScriptFunction::ADDR_TYPE_LOCAL_CONSTANT<<GDScriptFunction::ADDR_BITS); //make it a local constant (faster access)
}*/
if (GDScriptLanguage::get_singleton()->get_global_map().has(identifier)) {
int idx = GDScriptLanguage::get_singleton()->get_global_map()[identifier];
- return idx | (GDFunction::ADDR_TYPE_GLOBAL << GDFunction::ADDR_BITS); //argument (stack root)
+ return idx | (GDScriptFunction::ADDR_TYPE_GLOBAL << GDScriptFunction::ADDR_BITS); //argument (stack root)
}
//not found, error
@@ -278,9 +279,9 @@ int GDCompiler::_parse_expression(CodeGen &codegen, const GDParser::Node *p_expr
return -1;
} break;
- case GDParser::Node::TYPE_CONSTANT: {
+ case GDScriptParser::Node::TYPE_CONSTANT: {
//return constant
- const GDParser::ConstantNode *cn = static_cast<const GDParser::ConstantNode *>(p_expression);
+ const GDScriptParser::ConstantNode *cn = static_cast<const GDScriptParser::ConstantNode *>(p_expression);
int idx;
@@ -293,20 +294,20 @@ int GDCompiler::_parse_expression(CodeGen &codegen, const GDParser::Node *p_expr
idx = codegen.constant_map[cn->value];
}
- return idx | (GDFunction::ADDR_TYPE_LOCAL_CONSTANT << GDFunction::ADDR_BITS); //argument (stack root)
+ return idx | (GDScriptFunction::ADDR_TYPE_LOCAL_CONSTANT << GDScriptFunction::ADDR_BITS); //argument (stack root)
} break;
- case GDParser::Node::TYPE_SELF: {
+ case GDScriptParser::Node::TYPE_SELF: {
//return constant
if (codegen.function_node && codegen.function_node->_static) {
_set_error("'self' not present in static function!", p_expression);
return -1;
}
- return (GDFunction::ADDR_TYPE_SELF << GDFunction::ADDR_BITS);
+ return (GDScriptFunction::ADDR_TYPE_SELF << GDScriptFunction::ADDR_BITS);
} break;
- case GDParser::Node::TYPE_ARRAY: {
+ case GDScriptParser::Node::TYPE_ARRAY: {
- const GDParser::ArrayNode *an = static_cast<const GDParser::ArrayNode *>(p_expression);
+ const GDScriptParser::ArrayNode *an = static_cast<const GDScriptParser::ArrayNode *>(p_expression);
Vector<int> values;
int slevel = p_stack_level;
@@ -316,7 +317,7 @@ int GDCompiler::_parse_expression(CodeGen &codegen, const GDParser::Node *p_expr
int ret = _parse_expression(codegen, an->elements[i], slevel);
if (ret < 0)
return ret;
- if (ret & GDFunction::ADDR_TYPE_STACK << GDFunction::ADDR_BITS) {
+ if (ret & GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS) {
slevel++;
codegen.alloc_stack(slevel);
}
@@ -324,20 +325,20 @@ int GDCompiler::_parse_expression(CodeGen &codegen, const GDParser::Node *p_expr
values.push_back(ret);
}
- codegen.opcodes.push_back(GDFunction::OPCODE_CONSTRUCT_ARRAY);
+ codegen.opcodes.push_back(GDScriptFunction::OPCODE_CONSTRUCT_ARRAY);
codegen.opcodes.push_back(values.size());
for (int i = 0; i < values.size(); i++)
codegen.opcodes.push_back(values[i]);
- int dst_addr = (p_stack_level) | (GDFunction::ADDR_TYPE_STACK << GDFunction::ADDR_BITS);
+ int dst_addr = (p_stack_level) | (GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS);
codegen.opcodes.push_back(dst_addr); // append the stack level as destination address of the opcode
codegen.alloc_stack(p_stack_level);
return dst_addr;
} break;
- case GDParser::Node::TYPE_DICTIONARY: {
+ case GDScriptParser::Node::TYPE_DICTIONARY: {
- const GDParser::DictionaryNode *dn = static_cast<const GDParser::DictionaryNode *>(p_expression);
+ const GDScriptParser::DictionaryNode *dn = static_cast<const GDScriptParser::DictionaryNode *>(p_expression);
Vector<int> values;
int slevel = p_stack_level;
@@ -347,7 +348,7 @@ int GDCompiler::_parse_expression(CodeGen &codegen, const GDParser::Node *p_expr
int ret = _parse_expression(codegen, dn->elements[i].key, slevel);
if (ret < 0)
return ret;
- if (ret & GDFunction::ADDR_TYPE_STACK << GDFunction::ADDR_BITS) {
+ if (ret & GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS) {
slevel++;
codegen.alloc_stack(slevel);
}
@@ -357,7 +358,7 @@ int GDCompiler::_parse_expression(CodeGen &codegen, const GDParser::Node *p_expr
ret = _parse_expression(codegen, dn->elements[i].value, slevel);
if (ret < 0)
return ret;
- if (ret & GDFunction::ADDR_TYPE_STACK << GDFunction::ADDR_BITS) {
+ if (ret & GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS) {
slevel++;
codegen.alloc_stack(slevel);
}
@@ -365,29 +366,29 @@ int GDCompiler::_parse_expression(CodeGen &codegen, const GDParser::Node *p_expr
values.push_back(ret);
}
- codegen.opcodes.push_back(GDFunction::OPCODE_CONSTRUCT_DICTIONARY);
+ codegen.opcodes.push_back(GDScriptFunction::OPCODE_CONSTRUCT_DICTIONARY);
codegen.opcodes.push_back(dn->elements.size());
for (int i = 0; i < values.size(); i++)
codegen.opcodes.push_back(values[i]);
- int dst_addr = (p_stack_level) | (GDFunction::ADDR_TYPE_STACK << GDFunction::ADDR_BITS);
+ int dst_addr = (p_stack_level) | (GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS);
codegen.opcodes.push_back(dst_addr); // append the stack level as destination address of the opcode
codegen.alloc_stack(p_stack_level);
return dst_addr;
} break;
- case GDParser::Node::TYPE_OPERATOR: {
+ case GDScriptParser::Node::TYPE_OPERATOR: {
//hell breaks loose
- const GDParser::OperatorNode *on = static_cast<const GDParser::OperatorNode *>(p_expression);
+ const GDScriptParser::OperatorNode *on = static_cast<const GDScriptParser::OperatorNode *>(p_expression);
switch (on->op) {
//call/constructor operator
- case GDParser::OperatorNode::OP_PARENT_CALL: {
+ case GDScriptParser::OperatorNode::OP_PARENT_CALL: {
ERR_FAIL_COND_V(on->arguments.size() < 1, -1);
- const GDParser::IdentifierNode *in = (const GDParser::IdentifierNode *)on->arguments[0];
+ const GDScriptParser::IdentifierNode *in = (const GDScriptParser::IdentifierNode *)on->arguments[0];
Vector<int> arguments;
int slevel = p_stack_level;
@@ -396,7 +397,7 @@ int GDCompiler::_parse_expression(CodeGen &codegen, const GDParser::Node *p_expr
int ret = _parse_expression(codegen, on->arguments[i], slevel);
if (ret < 0)
return ret;
- if (ret & GDFunction::ADDR_TYPE_STACK << GDFunction::ADDR_BITS) {
+ if (ret & GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS) {
slevel++;
codegen.alloc_stack(slevel);
}
@@ -404,7 +405,7 @@ int GDCompiler::_parse_expression(CodeGen &codegen, const GDParser::Node *p_expr
}
//push call bytecode
- codegen.opcodes.push_back(GDFunction::OPCODE_CALL_SELF_BASE); // basic type constructor
+ codegen.opcodes.push_back(GDScriptFunction::OPCODE_CALL_SELF_BASE); // basic type constructor
codegen.opcodes.push_back(codegen.get_name_map_pos(in->name)); //instance
codegen.opcodes.push_back(arguments.size()); //argument count
@@ -413,13 +414,13 @@ int GDCompiler::_parse_expression(CodeGen &codegen, const GDParser::Node *p_expr
codegen.opcodes.push_back(arguments[i]); //arguments
} break;
- case GDParser::OperatorNode::OP_CALL: {
+ case GDScriptParser::OperatorNode::OP_CALL: {
- if (on->arguments[0]->type == GDParser::Node::TYPE_TYPE) {
+ if (on->arguments[0]->type == GDScriptParser::Node::TYPE_TYPE) {
//construct a basic type
ERR_FAIL_COND_V(on->arguments.size() < 1, -1);
- const GDParser::TypeNode *tn = (const GDParser::TypeNode *)on->arguments[0];
+ const GDScriptParser::TypeNode *tn = (const GDScriptParser::TypeNode *)on->arguments[0];
int vtype = tn->vtype;
Vector<int> arguments;
@@ -429,7 +430,7 @@ int GDCompiler::_parse_expression(CodeGen &codegen, const GDParser::Node *p_expr
int ret = _parse_expression(codegen, on->arguments[i], slevel);
if (ret < 0)
return ret;
- if (ret & GDFunction::ADDR_TYPE_STACK << GDFunction::ADDR_BITS) {
+ if (ret & GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS) {
slevel++;
codegen.alloc_stack(slevel);
}
@@ -437,14 +438,14 @@ int GDCompiler::_parse_expression(CodeGen &codegen, const GDParser::Node *p_expr
}
//push call bytecode
- codegen.opcodes.push_back(GDFunction::OPCODE_CONSTRUCT); // basic type constructor
+ codegen.opcodes.push_back(GDScriptFunction::OPCODE_CONSTRUCT); // basic type constructor
codegen.opcodes.push_back(vtype); //instance
codegen.opcodes.push_back(arguments.size()); //argument count
codegen.alloc_call(arguments.size());
for (int i = 0; i < arguments.size(); i++)
codegen.opcodes.push_back(arguments[i]); //arguments
- } else if (on->arguments[0]->type == GDParser::Node::TYPE_BUILT_IN_FUNCTION) {
+ } else if (on->arguments[0]->type == GDScriptParser::Node::TYPE_BUILT_IN_FUNCTION) {
//built in function
ERR_FAIL_COND_V(on->arguments.size() < 1, -1);
@@ -457,7 +458,7 @@ int GDCompiler::_parse_expression(CodeGen &codegen, const GDParser::Node *p_expr
if (ret < 0)
return ret;
- if (ret & GDFunction::ADDR_TYPE_STACK << GDFunction::ADDR_BITS) {
+ if (ret & GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS) {
slevel++;
codegen.alloc_stack(slevel);
}
@@ -465,8 +466,8 @@ int GDCompiler::_parse_expression(CodeGen &codegen, const GDParser::Node *p_expr
arguments.push_back(ret);
}
- codegen.opcodes.push_back(GDFunction::OPCODE_CALL_BUILT_IN);
- codegen.opcodes.push_back(static_cast<const GDParser::BuiltInFunctionNode *>(on->arguments[0])->function);
+ codegen.opcodes.push_back(GDScriptFunction::OPCODE_CALL_BUILT_IN);
+ codegen.opcodes.push_back(static_cast<const GDScriptParser::BuiltInFunctionNode *>(on->arguments[0])->function);
codegen.opcodes.push_back(on->arguments.size() - 1);
codegen.alloc_call(on->arguments.size() - 1);
for (int i = 0; i < arguments.size(); i++)
@@ -476,9 +477,9 @@ int GDCompiler::_parse_expression(CodeGen &codegen, const GDParser::Node *p_expr
//regular function
ERR_FAIL_COND_V(on->arguments.size() < 2, -1);
- const GDParser::Node *instance = on->arguments[0];
+ const GDScriptParser::Node *instance = on->arguments[0];
- if (instance->type == GDParser::Node::TYPE_SELF) {
+ if (instance->type == GDScriptParser::Node::TYPE_SELF) {
//room for optimization
}
@@ -489,16 +490,16 @@ int GDCompiler::_parse_expression(CodeGen &codegen, const GDParser::Node *p_expr
int ret;
- if (i == 0 && on->arguments[i]->type == GDParser::Node::TYPE_SELF && codegen.function_node && codegen.function_node->_static) {
+ if (i == 0 && on->arguments[i]->type == GDScriptParser::Node::TYPE_SELF && codegen.function_node && codegen.function_node->_static) {
//static call to self
- ret = (GDFunction::ADDR_TYPE_CLASS << GDFunction::ADDR_BITS);
+ ret = (GDScriptFunction::ADDR_TYPE_CLASS << GDScriptFunction::ADDR_BITS);
} else if (i == 1) {
- if (on->arguments[i]->type != GDParser::Node::TYPE_IDENTIFIER) {
+ if (on->arguments[i]->type != GDScriptParser::Node::TYPE_IDENTIFIER) {
_set_error("Attempt to call a non-identifier.", on);
return -1;
}
- GDParser::IdentifierNode *id = static_cast<GDParser::IdentifierNode *>(on->arguments[i]);
+ GDScriptParser::IdentifierNode *id = static_cast<GDScriptParser::IdentifierNode *>(on->arguments[i]);
ret = codegen.get_name_map_pos(id->name);
} else {
@@ -506,7 +507,7 @@ int GDCompiler::_parse_expression(CodeGen &codegen, const GDParser::Node *p_expr
ret = _parse_expression(codegen, on->arguments[i], slevel);
if (ret < 0)
return ret;
- if (ret & GDFunction::ADDR_TYPE_STACK << GDFunction::ADDR_BITS) {
+ if (ret & GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS) {
slevel++;
codegen.alloc_stack(slevel);
}
@@ -514,14 +515,14 @@ int GDCompiler::_parse_expression(CodeGen &codegen, const GDParser::Node *p_expr
arguments.push_back(ret);
}
- codegen.opcodes.push_back(p_root ? GDFunction::OPCODE_CALL : GDFunction::OPCODE_CALL_RETURN); // perform operator
+ codegen.opcodes.push_back(p_root ? GDScriptFunction::OPCODE_CALL : GDScriptFunction::OPCODE_CALL_RETURN); // perform operator
codegen.opcodes.push_back(on->arguments.size() - 2);
codegen.alloc_call(on->arguments.size() - 2);
for (int i = 0; i < arguments.size(); i++)
codegen.opcodes.push_back(arguments[i]);
}
} break;
- case GDParser::OperatorNode::OP_YIELD: {
+ case GDScriptParser::OperatorNode::OP_YIELD: {
ERR_FAIL_COND_V(on->arguments.size() && on->arguments.size() != 2, -1);
@@ -532,7 +533,7 @@ int GDCompiler::_parse_expression(CodeGen &codegen, const GDParser::Node *p_expr
int ret = _parse_expression(codegen, on->arguments[i], slevel);
if (ret < 0)
return ret;
- if (ret & (GDFunction::ADDR_TYPE_STACK << GDFunction::ADDR_BITS)) {
+ if (ret & (GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS)) {
slevel++;
codegen.alloc_stack(slevel);
}
@@ -540,22 +541,22 @@ int GDCompiler::_parse_expression(CodeGen &codegen, const GDParser::Node *p_expr
}
//push call bytecode
- codegen.opcodes.push_back(arguments.size() == 0 ? GDFunction::OPCODE_YIELD : GDFunction::OPCODE_YIELD_SIGNAL); // basic type constructor
+ codegen.opcodes.push_back(arguments.size() == 0 ? GDScriptFunction::OPCODE_YIELD : GDScriptFunction::OPCODE_YIELD_SIGNAL); // basic type constructor
for (int i = 0; i < arguments.size(); i++)
codegen.opcodes.push_back(arguments[i]); //arguments
- codegen.opcodes.push_back(GDFunction::OPCODE_YIELD_RESUME);
+ codegen.opcodes.push_back(GDScriptFunction::OPCODE_YIELD_RESUME);
//next will be where to place the result :)
} break;
//indexing operator
- case GDParser::OperatorNode::OP_INDEX:
- case GDParser::OperatorNode::OP_INDEX_NAMED: {
+ case GDScriptParser::OperatorNode::OP_INDEX:
+ case GDScriptParser::OperatorNode::OP_INDEX_NAMED: {
ERR_FAIL_COND_V(on->arguments.size() != 2, -1);
int slevel = p_stack_level;
- bool named = (on->op == GDParser::OperatorNode::OP_INDEX_NAMED);
+ bool named = (on->op == GDScriptParser::OperatorNode::OP_INDEX_NAMED);
int from = _parse_expression(codegen, on->arguments[0], slevel);
if (from < 0)
@@ -563,14 +564,14 @@ int GDCompiler::_parse_expression(CodeGen &codegen, const GDParser::Node *p_expr
int index;
if (named) {
- if (on->arguments[0]->type == GDParser::Node::TYPE_SELF && codegen.script && codegen.function_node && !codegen.function_node->_static) {
+ if (on->arguments[0]->type == GDScriptParser::Node::TYPE_SELF && codegen.script && codegen.function_node && !codegen.function_node->_static) {
- GDParser::IdentifierNode *identifier = static_cast<GDParser::IdentifierNode *>(on->arguments[1]);
+ GDScriptParser::IdentifierNode *identifier = static_cast<GDScriptParser::IdentifierNode *>(on->arguments[1]);
const Map<StringName, GDScript::MemberInfo>::Element *MI = codegen.script->member_indices.find(identifier->name);
#ifdef DEBUG_ENABLED
if (MI && MI->get().getter == codegen.function_node->name) {
- String n = static_cast<GDParser::IdentifierNode *>(on->arguments[1])->name;
+ String n = static_cast<GDScriptParser::IdentifierNode *>(on->arguments[1])->name;
_set_error("Must use '" + n + "' instead of 'self." + n + "' in getter.", on);
return -1;
}
@@ -578,23 +579,23 @@ int GDCompiler::_parse_expression(CodeGen &codegen, const GDParser::Node *p_expr
if (MI && MI->get().getter == "") {
// Faster than indexing self (as if no self. had been used)
- return (MI->get().index) | (GDFunction::ADDR_TYPE_MEMBER << GDFunction::ADDR_BITS);
+ return (MI->get().index) | (GDScriptFunction::ADDR_TYPE_MEMBER << GDScriptFunction::ADDR_BITS);
}
}
- index = codegen.get_name_map_pos(static_cast<GDParser::IdentifierNode *>(on->arguments[1])->name);
+ index = codegen.get_name_map_pos(static_cast<GDScriptParser::IdentifierNode *>(on->arguments[1])->name);
} else {
- if (on->arguments[1]->type == GDParser::Node::TYPE_CONSTANT && static_cast<const GDParser::ConstantNode *>(on->arguments[1])->value.get_type() == Variant::STRING) {
+ if (on->arguments[1]->type == GDScriptParser::Node::TYPE_CONSTANT && static_cast<const GDScriptParser::ConstantNode *>(on->arguments[1])->value.get_type() == Variant::STRING) {
//also, somehow, named (speed up anyway)
- StringName name = static_cast<const GDParser::ConstantNode *>(on->arguments[1])->value;
+ StringName name = static_cast<const GDScriptParser::ConstantNode *>(on->arguments[1])->value;
index = codegen.get_name_map_pos(name);
named = true;
} else {
//regular indexing
- if (from & GDFunction::ADDR_TYPE_STACK << GDFunction::ADDR_BITS) {
+ if (from & GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS) {
slevel++;
codegen.alloc_stack(slevel);
}
@@ -605,19 +606,19 @@ int GDCompiler::_parse_expression(CodeGen &codegen, const GDParser::Node *p_expr
}
}
- codegen.opcodes.push_back(named ? GDFunction::OPCODE_GET_NAMED : GDFunction::OPCODE_GET); // perform operator
+ codegen.opcodes.push_back(named ? GDScriptFunction::OPCODE_GET_NAMED : GDScriptFunction::OPCODE_GET); // perform operator
codegen.opcodes.push_back(from); // argument 1
codegen.opcodes.push_back(index); // argument 2 (unary only takes one parameter)
} break;
- case GDParser::OperatorNode::OP_AND: {
+ case GDScriptParser::OperatorNode::OP_AND: {
// AND operator with early out on failure
int res = _parse_expression(codegen, on->arguments[0], p_stack_level);
if (res < 0)
return res;
- codegen.opcodes.push_back(GDFunction::OPCODE_JUMP_IF_NOT);
+ codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP_IF_NOT);
codegen.opcodes.push_back(res);
int jump_fail_pos = codegen.opcodes.size();
codegen.opcodes.push_back(0);
@@ -626,31 +627,31 @@ int GDCompiler::_parse_expression(CodeGen &codegen, const GDParser::Node *p_expr
if (res < 0)
return res;
- codegen.opcodes.push_back(GDFunction::OPCODE_JUMP_IF_NOT);
+ codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP_IF_NOT);
codegen.opcodes.push_back(res);
int jump_fail_pos2 = codegen.opcodes.size();
codegen.opcodes.push_back(0);
codegen.alloc_stack(p_stack_level); //it will be used..
- codegen.opcodes.push_back(GDFunction::OPCODE_ASSIGN_TRUE);
- codegen.opcodes.push_back(p_stack_level | GDFunction::ADDR_TYPE_STACK << GDFunction::ADDR_BITS);
- codegen.opcodes.push_back(GDFunction::OPCODE_JUMP);
+ codegen.opcodes.push_back(GDScriptFunction::OPCODE_ASSIGN_TRUE);
+ codegen.opcodes.push_back(p_stack_level | GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS);
+ codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP);
codegen.opcodes.push_back(codegen.opcodes.size() + 3);
codegen.opcodes[jump_fail_pos] = codegen.opcodes.size();
codegen.opcodes[jump_fail_pos2] = codegen.opcodes.size();
- codegen.opcodes.push_back(GDFunction::OPCODE_ASSIGN_FALSE);
- codegen.opcodes.push_back(p_stack_level | GDFunction::ADDR_TYPE_STACK << GDFunction::ADDR_BITS);
- return p_stack_level | GDFunction::ADDR_TYPE_STACK << GDFunction::ADDR_BITS;
+ codegen.opcodes.push_back(GDScriptFunction::OPCODE_ASSIGN_FALSE);
+ codegen.opcodes.push_back(p_stack_level | GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS);
+ return p_stack_level | GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS;
} break;
- case GDParser::OperatorNode::OP_OR: {
+ case GDScriptParser::OperatorNode::OP_OR: {
// OR operator with early out on success
int res = _parse_expression(codegen, on->arguments[0], p_stack_level);
if (res < 0)
return res;
- codegen.opcodes.push_back(GDFunction::OPCODE_JUMP_IF);
+ codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP_IF);
codegen.opcodes.push_back(res);
int jump_success_pos = codegen.opcodes.size();
codegen.opcodes.push_back(0);
@@ -659,32 +660,32 @@ int GDCompiler::_parse_expression(CodeGen &codegen, const GDParser::Node *p_expr
if (res < 0)
return res;
- codegen.opcodes.push_back(GDFunction::OPCODE_JUMP_IF);
+ codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP_IF);
codegen.opcodes.push_back(res);
int jump_success_pos2 = codegen.opcodes.size();
codegen.opcodes.push_back(0);
codegen.alloc_stack(p_stack_level); //it will be used..
- codegen.opcodes.push_back(GDFunction::OPCODE_ASSIGN_FALSE);
- codegen.opcodes.push_back(p_stack_level | GDFunction::ADDR_TYPE_STACK << GDFunction::ADDR_BITS);
- codegen.opcodes.push_back(GDFunction::OPCODE_JUMP);
+ codegen.opcodes.push_back(GDScriptFunction::OPCODE_ASSIGN_FALSE);
+ codegen.opcodes.push_back(p_stack_level | GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS);
+ codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP);
codegen.opcodes.push_back(codegen.opcodes.size() + 3);
codegen.opcodes[jump_success_pos] = codegen.opcodes.size();
codegen.opcodes[jump_success_pos2] = codegen.opcodes.size();
- codegen.opcodes.push_back(GDFunction::OPCODE_ASSIGN_TRUE);
- codegen.opcodes.push_back(p_stack_level | GDFunction::ADDR_TYPE_STACK << GDFunction::ADDR_BITS);
- return p_stack_level | GDFunction::ADDR_TYPE_STACK << GDFunction::ADDR_BITS;
+ codegen.opcodes.push_back(GDScriptFunction::OPCODE_ASSIGN_TRUE);
+ codegen.opcodes.push_back(p_stack_level | GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS);
+ return p_stack_level | GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS;
} break;
// ternary operators
- case GDParser::OperatorNode::OP_TERNARY_IF: {
+ case GDScriptParser::OperatorNode::OP_TERNARY_IF: {
// x IF a ELSE y operator with early out on failure
int res = _parse_expression(codegen, on->arguments[0], p_stack_level);
if (res < 0)
return res;
- codegen.opcodes.push_back(GDFunction::OPCODE_JUMP_IF_NOT);
+ codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP_IF_NOT);
codegen.opcodes.push_back(res);
int jump_fail_pos = codegen.opcodes.size();
codegen.opcodes.push_back(0);
@@ -694,10 +695,10 @@ int GDCompiler::_parse_expression(CodeGen &codegen, const GDParser::Node *p_expr
return res;
codegen.alloc_stack(p_stack_level); //it will be used..
- codegen.opcodes.push_back(GDFunction::OPCODE_ASSIGN);
- codegen.opcodes.push_back(p_stack_level | GDFunction::ADDR_TYPE_STACK << GDFunction::ADDR_BITS);
+ codegen.opcodes.push_back(GDScriptFunction::OPCODE_ASSIGN);
+ codegen.opcodes.push_back(p_stack_level | GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS);
codegen.opcodes.push_back(res);
- codegen.opcodes.push_back(GDFunction::OPCODE_JUMP);
+ codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP);
int jump_past_pos = codegen.opcodes.size();
codegen.opcodes.push_back(0);
@@ -706,116 +707,116 @@ int GDCompiler::_parse_expression(CodeGen &codegen, const GDParser::Node *p_expr
if (res < 0)
return res;
- codegen.opcodes.push_back(GDFunction::OPCODE_ASSIGN);
- codegen.opcodes.push_back(p_stack_level | GDFunction::ADDR_TYPE_STACK << GDFunction::ADDR_BITS);
+ codegen.opcodes.push_back(GDScriptFunction::OPCODE_ASSIGN);
+ codegen.opcodes.push_back(p_stack_level | GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS);
codegen.opcodes.push_back(res);
codegen.opcodes[jump_past_pos] = codegen.opcodes.size();
- return p_stack_level | GDFunction::ADDR_TYPE_STACK << GDFunction::ADDR_BITS;
+ return p_stack_level | GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS;
} break;
//unary operators
- case GDParser::OperatorNode::OP_NEG: {
+ case GDScriptParser::OperatorNode::OP_NEG: {
if (!_create_unary_operator(codegen, on, Variant::OP_NEGATE, p_stack_level)) return -1;
} break;
- case GDParser::OperatorNode::OP_NOT: {
+ case GDScriptParser::OperatorNode::OP_NOT: {
if (!_create_unary_operator(codegen, on, Variant::OP_NOT, p_stack_level)) return -1;
} break;
- case GDParser::OperatorNode::OP_BIT_INVERT: {
+ case GDScriptParser::OperatorNode::OP_BIT_INVERT: {
if (!_create_unary_operator(codegen, on, Variant::OP_BIT_NEGATE, p_stack_level)) return -1;
} break;
- case GDParser::OperatorNode::OP_PREINC: {
+ case GDScriptParser::OperatorNode::OP_PREINC: {
} break; //?
- case GDParser::OperatorNode::OP_PREDEC: {
+ case GDScriptParser::OperatorNode::OP_PREDEC: {
} break;
- case GDParser::OperatorNode::OP_INC: {
+ case GDScriptParser::OperatorNode::OP_INC: {
} break;
- case GDParser::OperatorNode::OP_DEC: {
+ case GDScriptParser::OperatorNode::OP_DEC: {
} break;
//binary operators (in precedence order)
- case GDParser::OperatorNode::OP_IN: {
+ case GDScriptParser::OperatorNode::OP_IN: {
if (!_create_binary_operator(codegen, on, Variant::OP_IN, p_stack_level)) return -1;
} break;
- case GDParser::OperatorNode::OP_EQUAL: {
+ case GDScriptParser::OperatorNode::OP_EQUAL: {
if (!_create_binary_operator(codegen, on, Variant::OP_EQUAL, p_stack_level)) return -1;
} break;
- case GDParser::OperatorNode::OP_NOT_EQUAL: {
+ case GDScriptParser::OperatorNode::OP_NOT_EQUAL: {
if (!_create_binary_operator(codegen, on, Variant::OP_NOT_EQUAL, p_stack_level)) return -1;
} break;
- case GDParser::OperatorNode::OP_LESS: {
+ case GDScriptParser::OperatorNode::OP_LESS: {
if (!_create_binary_operator(codegen, on, Variant::OP_LESS, p_stack_level)) return -1;
} break;
- case GDParser::OperatorNode::OP_LESS_EQUAL: {
+ case GDScriptParser::OperatorNode::OP_LESS_EQUAL: {
if (!_create_binary_operator(codegen, on, Variant::OP_LESS_EQUAL, p_stack_level)) return -1;
} break;
- case GDParser::OperatorNode::OP_GREATER: {
+ case GDScriptParser::OperatorNode::OP_GREATER: {
if (!_create_binary_operator(codegen, on, Variant::OP_GREATER, p_stack_level)) return -1;
} break;
- case GDParser::OperatorNode::OP_GREATER_EQUAL: {
+ case GDScriptParser::OperatorNode::OP_GREATER_EQUAL: {
if (!_create_binary_operator(codegen, on, Variant::OP_GREATER_EQUAL, p_stack_level)) return -1;
} break;
- case GDParser::OperatorNode::OP_ADD: {
+ case GDScriptParser::OperatorNode::OP_ADD: {
if (!_create_binary_operator(codegen, on, Variant::OP_ADD, p_stack_level)) return -1;
} break;
- case GDParser::OperatorNode::OP_SUB: {
+ case GDScriptParser::OperatorNode::OP_SUB: {
if (!_create_binary_operator(codegen, on, Variant::OP_SUBTRACT, p_stack_level)) return -1;
} break;
- case GDParser::OperatorNode::OP_MUL: {
+ case GDScriptParser::OperatorNode::OP_MUL: {
if (!_create_binary_operator(codegen, on, Variant::OP_MULTIPLY, p_stack_level)) return -1;
} break;
- case GDParser::OperatorNode::OP_DIV: {
+ case GDScriptParser::OperatorNode::OP_DIV: {
if (!_create_binary_operator(codegen, on, Variant::OP_DIVIDE, p_stack_level)) return -1;
} break;
- case GDParser::OperatorNode::OP_MOD: {
+ case GDScriptParser::OperatorNode::OP_MOD: {
if (!_create_binary_operator(codegen, on, Variant::OP_MODULE, p_stack_level)) return -1;
} break;
- //case GDParser::OperatorNode::OP_SHIFT_LEFT: { if (!_create_binary_operator(codegen,on,Variant::OP_SHIFT_LEFT,p_stack_level)) return -1;} break;
- //case GDParser::OperatorNode::OP_SHIFT_RIGHT: { if (!_create_binary_operator(codegen,on,Variant::OP_SHIFT_RIGHT,p_stack_level)) return -1;} break;
- case GDParser::OperatorNode::OP_BIT_AND: {
+ //case GDScriptParser::OperatorNode::OP_SHIFT_LEFT: { if (!_create_binary_operator(codegen,on,Variant::OP_SHIFT_LEFT,p_stack_level)) return -1;} break;
+ //case GDScriptParser::OperatorNode::OP_SHIFT_RIGHT: { if (!_create_binary_operator(codegen,on,Variant::OP_SHIFT_RIGHT,p_stack_level)) return -1;} break;
+ case GDScriptParser::OperatorNode::OP_BIT_AND: {
if (!_create_binary_operator(codegen, on, Variant::OP_BIT_AND, p_stack_level)) return -1;
} break;
- case GDParser::OperatorNode::OP_BIT_OR: {
+ case GDScriptParser::OperatorNode::OP_BIT_OR: {
if (!_create_binary_operator(codegen, on, Variant::OP_BIT_OR, p_stack_level)) return -1;
} break;
- case GDParser::OperatorNode::OP_BIT_XOR: {
+ case GDScriptParser::OperatorNode::OP_BIT_XOR: {
if (!_create_binary_operator(codegen, on, Variant::OP_BIT_XOR, p_stack_level)) return -1;
} break;
//shift
- case GDParser::OperatorNode::OP_SHIFT_LEFT: {
+ case GDScriptParser::OperatorNode::OP_SHIFT_LEFT: {
if (!_create_binary_operator(codegen, on, Variant::OP_SHIFT_LEFT, p_stack_level)) return -1;
} break;
- case GDParser::OperatorNode::OP_SHIFT_RIGHT: {
+ case GDScriptParser::OperatorNode::OP_SHIFT_RIGHT: {
if (!_create_binary_operator(codegen, on, Variant::OP_SHIFT_RIGHT, p_stack_level)) return -1;
} break;
//assignment operators
- case GDParser::OperatorNode::OP_ASSIGN_ADD:
- case GDParser::OperatorNode::OP_ASSIGN_SUB:
- case GDParser::OperatorNode::OP_ASSIGN_MUL:
- case GDParser::OperatorNode::OP_ASSIGN_DIV:
- case GDParser::OperatorNode::OP_ASSIGN_MOD:
- case GDParser::OperatorNode::OP_ASSIGN_SHIFT_LEFT:
- case GDParser::OperatorNode::OP_ASSIGN_SHIFT_RIGHT:
- case GDParser::OperatorNode::OP_ASSIGN_BIT_AND:
- case GDParser::OperatorNode::OP_ASSIGN_BIT_OR:
- case GDParser::OperatorNode::OP_ASSIGN_BIT_XOR:
- case GDParser::OperatorNode::OP_INIT_ASSIGN:
- case GDParser::OperatorNode::OP_ASSIGN: {
+ case GDScriptParser::OperatorNode::OP_ASSIGN_ADD:
+ case GDScriptParser::OperatorNode::OP_ASSIGN_SUB:
+ case GDScriptParser::OperatorNode::OP_ASSIGN_MUL:
+ case GDScriptParser::OperatorNode::OP_ASSIGN_DIV:
+ case GDScriptParser::OperatorNode::OP_ASSIGN_MOD:
+ case GDScriptParser::OperatorNode::OP_ASSIGN_SHIFT_LEFT:
+ case GDScriptParser::OperatorNode::OP_ASSIGN_SHIFT_RIGHT:
+ case GDScriptParser::OperatorNode::OP_ASSIGN_BIT_AND:
+ case GDScriptParser::OperatorNode::OP_ASSIGN_BIT_OR:
+ case GDScriptParser::OperatorNode::OP_ASSIGN_BIT_XOR:
+ case GDScriptParser::OperatorNode::OP_INIT_ASSIGN:
+ case GDScriptParser::OperatorNode::OP_ASSIGN: {
ERR_FAIL_COND_V(on->arguments.size() != 2, -1);
- if (on->arguments[0]->type == GDParser::Node::TYPE_OPERATOR && (static_cast<GDParser::OperatorNode *>(on->arguments[0])->op == GDParser::OperatorNode::OP_INDEX || static_cast<GDParser::OperatorNode *>(on->arguments[0])->op == GDParser::OperatorNode::OP_INDEX_NAMED)) {
+ if (on->arguments[0]->type == GDScriptParser::Node::TYPE_OPERATOR && (static_cast<GDScriptParser::OperatorNode *>(on->arguments[0])->op == GDScriptParser::OperatorNode::OP_INDEX || static_cast<GDScriptParser::OperatorNode *>(on->arguments[0])->op == GDScriptParser::OperatorNode::OP_INDEX_NAMED)) {
//SET (chained) MODE!!
#ifdef DEBUG_ENABLED
- if (static_cast<GDParser::OperatorNode *>(on->arguments[0])->op == GDParser::OperatorNode::OP_INDEX_NAMED) {
- const GDParser::OperatorNode *inon = static_cast<GDParser::OperatorNode *>(on->arguments[0]);
+ if (static_cast<GDScriptParser::OperatorNode *>(on->arguments[0])->op == GDScriptParser::OperatorNode::OP_INDEX_NAMED) {
+ const GDScriptParser::OperatorNode *inon = static_cast<GDScriptParser::OperatorNode *>(on->arguments[0]);
- if (inon->arguments[0]->type == GDParser::Node::TYPE_SELF && codegen.script && codegen.function_node && !codegen.function_node->_static) {
+ if (inon->arguments[0]->type == GDScriptParser::Node::TYPE_SELF && codegen.script && codegen.function_node && !codegen.function_node->_static) {
- const Map<StringName, GDScript::MemberInfo>::Element *MI = codegen.script->member_indices.find(static_cast<GDParser::IdentifierNode *>(inon->arguments[1])->name);
+ const Map<StringName, GDScript::MemberInfo>::Element *MI = codegen.script->member_indices.find(static_cast<GDScriptParser::IdentifierNode *>(inon->arguments[1])->name);
if (MI && MI->get().setter == codegen.function_node->name) {
- String n = static_cast<GDParser::IdentifierNode *>(inon->arguments[1])->name;
+ String n = static_cast<GDScriptParser::IdentifierNode *>(inon->arguments[1])->name;
_set_error("Must use '" + n + "' instead of 'self." + n + "' in setter.", inon);
return -1;
}
@@ -825,34 +826,34 @@ int GDCompiler::_parse_expression(CodeGen &codegen, const GDParser::Node *p_expr
int slevel = p_stack_level;
- GDParser::OperatorNode *op = static_cast<GDParser::OperatorNode *>(on->arguments[0]);
+ GDScriptParser::OperatorNode *op = static_cast<GDScriptParser::OperatorNode *>(on->arguments[0]);
/* Find chain of sets */
StringName assign_property;
- List<GDParser::OperatorNode *> chain;
+ List<GDScriptParser::OperatorNode *> chain;
{
//create get/set chain
- GDParser::OperatorNode *n = op;
+ GDScriptParser::OperatorNode *n = op;
while (true) {
chain.push_back(n);
- if (n->arguments[0]->type != GDParser::Node::TYPE_OPERATOR) {
+ if (n->arguments[0]->type != GDScriptParser::Node::TYPE_OPERATOR) {
//check for a built-in property
- if (n->arguments[0]->type == GDParser::Node::TYPE_IDENTIFIER) {
+ if (n->arguments[0]->type == GDScriptParser::Node::TYPE_IDENTIFIER) {
- GDParser::IdentifierNode *identifier = static_cast<GDParser::IdentifierNode *>(n->arguments[0]);
+ GDScriptParser::IdentifierNode *identifier = static_cast<GDScriptParser::IdentifierNode *>(n->arguments[0]);
if (_is_class_member_property(codegen, identifier->name)) {
assign_property = identifier->name;
}
}
break;
}
- n = static_cast<GDParser::OperatorNode *>(n->arguments[0]);
- if (n->op != GDParser::OperatorNode::OP_INDEX && n->op != GDParser::OperatorNode::OP_INDEX_NAMED)
+ n = static_cast<GDScriptParser::OperatorNode *>(n->arguments[0]);
+ if (n->op != GDScriptParser::OperatorNode::OP_INDEX && n->op != GDScriptParser::OperatorNode::OP_INDEX_NAMED)
break;
}
}
@@ -867,7 +868,7 @@ int GDCompiler::_parse_expression(CodeGen &codegen, const GDParser::Node *p_expr
//print_line("retval: "+itos(retval));
- if (retval & GDFunction::ADDR_TYPE_STACK << GDFunction::ADDR_BITS) {
+ if (retval & GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS) {
slevel++;
codegen.alloc_stack(slevel);
}
@@ -881,30 +882,30 @@ int GDCompiler::_parse_expression(CodeGen &codegen, const GDParser::Node *p_expr
// in Node2D
setchain.push_back(prev_pos);
setchain.push_back(codegen.get_name_map_pos(assign_property));
- setchain.push_back(GDFunction::OPCODE_SET_MEMBER);
+ setchain.push_back(GDScriptFunction::OPCODE_SET_MEMBER);
}
- for (List<GDParser::OperatorNode *>::Element *E = chain.back(); E; E = E->prev()) {
+ for (List<GDScriptParser::OperatorNode *>::Element *E = chain.back(); E; E = E->prev()) {
if (E == chain.front()) //ignore first
break;
- bool named = E->get()->op == GDParser::OperatorNode::OP_INDEX_NAMED;
+ bool named = E->get()->op == GDScriptParser::OperatorNode::OP_INDEX_NAMED;
int key_idx;
if (named) {
- key_idx = codegen.get_name_map_pos(static_cast<const GDParser::IdentifierNode *>(E->get()->arguments[1])->name);
+ key_idx = codegen.get_name_map_pos(static_cast<const GDScriptParser::IdentifierNode *>(E->get()->arguments[1])->name);
//printf("named key %x\n",key_idx);
} else {
- if (prev_pos & (GDFunction::ADDR_TYPE_STACK << GDFunction::ADDR_BITS)) {
+ if (prev_pos & (GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS)) {
slevel++;
codegen.alloc_stack(slevel);
}
- GDParser::Node *key = E->get()->arguments[1];
+ GDScriptParser::Node *key = E->get()->arguments[1];
key_idx = _parse_expression(codegen, key, slevel);
//printf("expr key %x\n",key_idx);
@@ -914,12 +915,12 @@ int GDCompiler::_parse_expression(CodeGen &codegen, const GDParser::Node *p_expr
if (key_idx < 0) //error
return key_idx;
- codegen.opcodes.push_back(named ? GDFunction::OPCODE_GET_NAMED : GDFunction::OPCODE_GET);
+ codegen.opcodes.push_back(named ? GDScriptFunction::OPCODE_GET_NAMED : GDScriptFunction::OPCODE_GET);
codegen.opcodes.push_back(prev_pos);
codegen.opcodes.push_back(key_idx);
slevel++;
codegen.alloc_stack(slevel);
- int dst_pos = (GDFunction::ADDR_TYPE_STACK << GDFunction::ADDR_BITS) | slevel;
+ int dst_pos = (GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS) | slevel;
codegen.opcodes.push_back(dst_pos);
@@ -928,7 +929,7 @@ int GDCompiler::_parse_expression(CodeGen &codegen, const GDParser::Node *p_expr
setchain.push_back(dst_pos);
setchain.push_back(key_idx);
setchain.push_back(prev_pos);
- setchain.push_back(named ? GDFunction::OPCODE_SET_NAMED : GDFunction::OPCODE_SET);
+ setchain.push_back(named ? GDScriptFunction::OPCODE_SET_NAMED : GDScriptFunction::OPCODE_SET);
prev_pos = dst_pos;
}
@@ -938,9 +939,9 @@ int GDCompiler::_parse_expression(CodeGen &codegen, const GDParser::Node *p_expr
int set_index;
bool named = false;
- if (static_cast<const GDParser::OperatorNode *>(op)->op == GDParser::OperatorNode::OP_INDEX_NAMED) {
+ if (static_cast<const GDScriptParser::OperatorNode *>(op)->op == GDScriptParser::OperatorNode::OP_INDEX_NAMED) {
- set_index = codegen.get_name_map_pos(static_cast<const GDParser::IdentifierNode *>(op->arguments[1])->name);
+ set_index = codegen.get_name_map_pos(static_cast<const GDScriptParser::IdentifierNode *>(op->arguments[1])->name);
named = true;
} else {
@@ -951,7 +952,7 @@ int GDCompiler::_parse_expression(CodeGen &codegen, const GDParser::Node *p_expr
if (set_index < 0) //error
return set_index;
- if (set_index & GDFunction::ADDR_TYPE_STACK << GDFunction::ADDR_BITS) {
+ if (set_index & GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS) {
slevel++;
codegen.alloc_stack(slevel);
}
@@ -960,7 +961,7 @@ int GDCompiler::_parse_expression(CodeGen &codegen, const GDParser::Node *p_expr
if (set_value < 0) //error
return set_value;
- codegen.opcodes.push_back(named ? GDFunction::OPCODE_SET_NAMED : GDFunction::OPCODE_SET);
+ codegen.opcodes.push_back(named ? GDScriptFunction::OPCODE_SET_NAMED : GDScriptFunction::OPCODE_SET);
codegen.opcodes.push_back(prev_pos);
codegen.opcodes.push_back(set_index);
codegen.opcodes.push_back(set_value);
@@ -972,7 +973,7 @@ int GDCompiler::_parse_expression(CodeGen &codegen, const GDParser::Node *p_expr
return retval;
- } else if (on->arguments[0]->type == GDParser::Node::TYPE_IDENTIFIER && _is_class_member_property(codegen, static_cast<GDParser::IdentifierNode *>(on->arguments[0])->name)) {
+ } else if (on->arguments[0]->type == GDScriptParser::Node::TYPE_IDENTIFIER && _is_class_member_property(codegen, static_cast<GDScriptParser::IdentifierNode *>(on->arguments[0])->name)) {
//assignment to member property
int slevel = p_stack_level;
@@ -981,24 +982,24 @@ int GDCompiler::_parse_expression(CodeGen &codegen, const GDParser::Node *p_expr
if (src_address < 0)
return -1;
- StringName name = static_cast<GDParser::IdentifierNode *>(on->arguments[0])->name;
+ StringName name = static_cast<GDScriptParser::IdentifierNode *>(on->arguments[0])->name;
- codegen.opcodes.push_back(GDFunction::OPCODE_SET_MEMBER);
+ codegen.opcodes.push_back(GDScriptFunction::OPCODE_SET_MEMBER);
codegen.opcodes.push_back(codegen.get_name_map_pos(name));
codegen.opcodes.push_back(src_address);
- return GDFunction::ADDR_TYPE_NIL << GDFunction::ADDR_BITS;
+ return GDScriptFunction::ADDR_TYPE_NIL << GDScriptFunction::ADDR_BITS;
} else {
//REGULAR ASSIGNMENT MODE!!
int slevel = p_stack_level;
- int dst_address_a = _parse_expression(codegen, on->arguments[0], slevel, false, on->op == GDParser::OperatorNode::OP_INIT_ASSIGN);
+ int dst_address_a = _parse_expression(codegen, on->arguments[0], slevel, false, on->op == GDScriptParser::OperatorNode::OP_INIT_ASSIGN);
if (dst_address_a < 0)
return -1;
- if (dst_address_a & GDFunction::ADDR_TYPE_STACK << GDFunction::ADDR_BITS) {
+ if (dst_address_a & GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS) {
slevel++;
codegen.alloc_stack(slevel);
}
@@ -1007,14 +1008,14 @@ int GDCompiler::_parse_expression(CodeGen &codegen, const GDParser::Node *p_expr
if (src_address_b < 0)
return -1;
- codegen.opcodes.push_back(GDFunction::OPCODE_ASSIGN); // perform operator
+ codegen.opcodes.push_back(GDScriptFunction::OPCODE_ASSIGN); // perform operator
codegen.opcodes.push_back(dst_address_a); // argument 1
codegen.opcodes.push_back(src_address_b); // argument 2 (unary only takes one parameter)
return dst_address_a; //if anything, returns wathever was assigned or correct stack position
}
} break;
- case GDParser::OperatorNode::OP_IS: {
+ case GDScriptParser::OperatorNode::OP_IS: {
ERR_FAIL_COND_V(on->arguments.size() != 2, false);
@@ -1024,14 +1025,14 @@ int GDCompiler::_parse_expression(CodeGen &codegen, const GDParser::Node *p_expr
if (src_address_a < 0)
return -1;
- if (src_address_a & GDFunction::ADDR_TYPE_STACK << GDFunction::ADDR_BITS)
+ if (src_address_a & GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS)
slevel++; //uses stack for return, increase stack
int src_address_b = _parse_expression(codegen, on->arguments[1], slevel);
if (src_address_b < 0)
return -1;
- codegen.opcodes.push_back(GDFunction::OPCODE_EXTENDS_TEST); // perform operator
+ codegen.opcodes.push_back(GDScriptFunction::OPCODE_EXTENDS_TEST); // perform operator
codegen.opcodes.push_back(src_address_a); // argument 1
codegen.opcodes.push_back(src_address_b); // argument 2 (unary only takes one parameter)
@@ -1044,7 +1045,7 @@ int GDCompiler::_parse_expression(CodeGen &codegen, const GDParser::Node *p_expr
} break;
}
- int dst_addr = (p_stack_level) | (GDFunction::ADDR_TYPE_STACK << GDFunction::ADDR_BITS);
+ int dst_addr = (p_stack_level) | (GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS);
codegen.opcodes.push_back(dst_addr); // append the stack level as destination address of the opcode
codegen.alloc_stack(p_stack_level);
return dst_addr;
@@ -1060,7 +1061,7 @@ int GDCompiler::_parse_expression(CodeGen &codegen, const GDParser::Node *p_expr
ERR_FAIL_V(-1); //unreachable code
}
-Error GDCompiler::_parse_block(CodeGen &codegen, const GDParser::BlockNode *p_block, int p_stack_level, int p_break_addr, int p_continue_addr) {
+Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::BlockNode *p_block, int p_stack_level, int p_break_addr, int p_continue_addr) {
codegen.push_stack_identifiers();
int new_identifiers = 0;
@@ -1068,28 +1069,28 @@ Error GDCompiler::_parse_block(CodeGen &codegen, const GDParser::BlockNode *p_bl
for (int i = 0; i < p_block->statements.size(); i++) {
- const GDParser::Node *s = p_block->statements[i];
+ const GDScriptParser::Node *s = p_block->statements[i];
switch (s->type) {
- case GDParser::Node::TYPE_NEWLINE: {
+ case GDScriptParser::Node::TYPE_NEWLINE: {
#ifdef DEBUG_ENABLED
- const GDParser::NewLineNode *nl = static_cast<const GDParser::NewLineNode *>(s);
- codegen.opcodes.push_back(GDFunction::OPCODE_LINE);
+ const GDScriptParser::NewLineNode *nl = static_cast<const GDScriptParser::NewLineNode *>(s);
+ codegen.opcodes.push_back(GDScriptFunction::OPCODE_LINE);
codegen.opcodes.push_back(nl->line);
codegen.current_line = nl->line;
#endif
} break;
- case GDParser::Node::TYPE_CONTROL_FLOW: {
+ case GDScriptParser::Node::TYPE_CONTROL_FLOW: {
// try subblocks
- const GDParser::ControlFlowNode *cf = static_cast<const GDParser::ControlFlowNode *>(s);
+ const GDScriptParser::ControlFlowNode *cf = static_cast<const GDScriptParser::ControlFlowNode *>(s);
switch (cf->cf_type) {
- case GDParser::ControlFlowNode::CF_MATCH: {
- GDParser::MatchNode *match = cf->match;
+ case GDScriptParser::ControlFlowNode::CF_MATCH: {
+ GDScriptParser::MatchNode *match = cf->match;
- GDParser::IdentifierNode *id = memnew(GDParser::IdentifierNode);
+ GDScriptParser::IdentifierNode *id = memnew(GDScriptParser::IdentifierNode);
id->name = "#match_value";
// var #match_value
@@ -1098,8 +1099,8 @@ Error GDCompiler::_parse_block(CodeGen &codegen, const GDParser::BlockNode *p_bl
codegen.alloc_stack(p_stack_level);
new_identifiers++;
- GDParser::OperatorNode *op = memnew(GDParser::OperatorNode);
- op->op = GDParser::OperatorNode::OP_ASSIGN;
+ GDScriptParser::OperatorNode *op = memnew(GDScriptParser::OperatorNode);
+ op->op = GDScriptParser::OperatorNode::OP_ASSIGN;
op->arguments.push_back(id);
op->arguments.push_back(match->val_to_match);
@@ -1109,14 +1110,14 @@ Error GDCompiler::_parse_block(CodeGen &codegen, const GDParser::BlockNode *p_bl
}
// break address
- codegen.opcodes.push_back(GDFunction::OPCODE_JUMP);
+ codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP);
codegen.opcodes.push_back(codegen.opcodes.size() + 3);
int break_addr = codegen.opcodes.size();
- codegen.opcodes.push_back(GDFunction::OPCODE_JUMP);
+ codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP);
codegen.opcodes.push_back(0); // break addr
for (int j = 0; j < match->compiled_pattern_branches.size(); j++) {
- GDParser::MatchNode::CompiledPatternBranch branch = match->compiled_pattern_branches[j];
+ GDScriptParser::MatchNode::CompiledPatternBranch branch = match->compiled_pattern_branches[j];
// jump over continue
// jump unconditionally
@@ -1127,11 +1128,11 @@ Error GDCompiler::_parse_block(CodeGen &codegen, const GDParser::BlockNode *p_bl
return ERR_PARSE_ERROR;
}
- codegen.opcodes.push_back(GDFunction::OPCODE_JUMP_IF);
+ codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP_IF);
codegen.opcodes.push_back(ret);
codegen.opcodes.push_back(codegen.opcodes.size() + 3);
int continue_addr = codegen.opcodes.size();
- codegen.opcodes.push_back(GDFunction::OPCODE_JUMP);
+ codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP);
codegen.opcodes.push_back(0);
Error err = _parse_block(codegen, branch.body, p_stack_level, p_break_addr, continue_addr);
@@ -1139,7 +1140,7 @@ Error GDCompiler::_parse_block(CodeGen &codegen, const GDParser::BlockNode *p_bl
return ERR_PARSE_ERROR;
}
- codegen.opcodes.push_back(GDFunction::OPCODE_JUMP);
+ codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP);
codegen.opcodes.push_back(break_addr);
codegen.opcodes[continue_addr + 1] = codegen.opcodes.size();
@@ -1149,10 +1150,10 @@ Error GDCompiler::_parse_block(CodeGen &codegen, const GDParser::BlockNode *p_bl
} break;
- case GDParser::ControlFlowNode::CF_IF: {
+ case GDScriptParser::ControlFlowNode::CF_IF: {
#ifdef DEBUG_ENABLED
- codegen.opcodes.push_back(GDFunction::OPCODE_LINE);
+ codegen.opcodes.push_back(GDScriptFunction::OPCODE_LINE);
codegen.opcodes.push_back(cf->line);
codegen.current_line = cf->line;
#endif
@@ -1160,7 +1161,7 @@ Error GDCompiler::_parse_block(CodeGen &codegen, const GDParser::BlockNode *p_bl
if (ret < 0)
return ERR_PARSE_ERROR;
- codegen.opcodes.push_back(GDFunction::OPCODE_JUMP_IF_NOT);
+ codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP_IF_NOT);
codegen.opcodes.push_back(ret);
int else_addr = codegen.opcodes.size();
codegen.opcodes.push_back(0); //temporary
@@ -1171,7 +1172,7 @@ Error GDCompiler::_parse_block(CodeGen &codegen, const GDParser::BlockNode *p_bl
if (cf->body_else) {
- codegen.opcodes.push_back(GDFunction::OPCODE_JUMP);
+ codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP);
int end_addr = codegen.opcodes.size();
codegen.opcodes.push_back(0);
codegen.opcodes[else_addr] = codegen.opcodes.size();
@@ -1187,42 +1188,42 @@ Error GDCompiler::_parse_block(CodeGen &codegen, const GDParser::BlockNode *p_bl
}
} break;
- case GDParser::ControlFlowNode::CF_FOR: {
+ case GDScriptParser::ControlFlowNode::CF_FOR: {
int slevel = p_stack_level;
int iter_stack_pos = slevel;
- int iterator_pos = (slevel++) | (GDFunction::ADDR_TYPE_STACK << GDFunction::ADDR_BITS);
- int counter_pos = (slevel++) | (GDFunction::ADDR_TYPE_STACK << GDFunction::ADDR_BITS);
- int container_pos = (slevel++) | (GDFunction::ADDR_TYPE_STACK << GDFunction::ADDR_BITS);
+ int iterator_pos = (slevel++) | (GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS);
+ int counter_pos = (slevel++) | (GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS);
+ int container_pos = (slevel++) | (GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS);
codegen.alloc_stack(slevel);
codegen.push_stack_identifiers();
- codegen.add_stack_identifier(static_cast<const GDParser::IdentifierNode *>(cf->arguments[0])->name, iter_stack_pos);
+ codegen.add_stack_identifier(static_cast<const GDScriptParser::IdentifierNode *>(cf->arguments[0])->name, iter_stack_pos);
int ret = _parse_expression(codegen, cf->arguments[1], slevel, false);
if (ret < 0)
return ERR_COMPILATION_FAILED;
//assign container
- codegen.opcodes.push_back(GDFunction::OPCODE_ASSIGN);
+ codegen.opcodes.push_back(GDScriptFunction::OPCODE_ASSIGN);
codegen.opcodes.push_back(container_pos);
codegen.opcodes.push_back(ret);
//begin loop
- codegen.opcodes.push_back(GDFunction::OPCODE_ITERATE_BEGIN);
+ codegen.opcodes.push_back(GDScriptFunction::OPCODE_ITERATE_BEGIN);
codegen.opcodes.push_back(counter_pos);
codegen.opcodes.push_back(container_pos);
codegen.opcodes.push_back(codegen.opcodes.size() + 4);
codegen.opcodes.push_back(iterator_pos);
- codegen.opcodes.push_back(GDFunction::OPCODE_JUMP); //skip code for next
+ codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP); //skip code for next
codegen.opcodes.push_back(codegen.opcodes.size() + 8);
//break loop
int break_pos = codegen.opcodes.size();
- codegen.opcodes.push_back(GDFunction::OPCODE_JUMP); //skip code for next
+ codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP); //skip code for next
codegen.opcodes.push_back(0); //skip code for next
//next loop
int continue_pos = codegen.opcodes.size();
- codegen.opcodes.push_back(GDFunction::OPCODE_ITERATE);
+ codegen.opcodes.push_back(GDScriptFunction::OPCODE_ITERATE);
codegen.opcodes.push_back(counter_pos);
codegen.opcodes.push_back(container_pos);
codegen.opcodes.push_back(break_pos);
@@ -1232,52 +1233,52 @@ Error GDCompiler::_parse_block(CodeGen &codegen, const GDParser::BlockNode *p_bl
if (err)
return err;
- codegen.opcodes.push_back(GDFunction::OPCODE_JUMP);
+ codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP);
codegen.opcodes.push_back(continue_pos);
codegen.opcodes[break_pos + 1] = codegen.opcodes.size();
codegen.pop_stack_identifiers();
} break;
- case GDParser::ControlFlowNode::CF_WHILE: {
+ case GDScriptParser::ControlFlowNode::CF_WHILE: {
- codegen.opcodes.push_back(GDFunction::OPCODE_JUMP);
+ codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP);
codegen.opcodes.push_back(codegen.opcodes.size() + 3);
int break_addr = codegen.opcodes.size();
- codegen.opcodes.push_back(GDFunction::OPCODE_JUMP);
+ codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP);
codegen.opcodes.push_back(0);
int continue_addr = codegen.opcodes.size();
int ret = _parse_expression(codegen, cf->arguments[0], p_stack_level, false);
if (ret < 0)
return ERR_PARSE_ERROR;
- codegen.opcodes.push_back(GDFunction::OPCODE_JUMP_IF_NOT);
+ codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP_IF_NOT);
codegen.opcodes.push_back(ret);
codegen.opcodes.push_back(break_addr);
Error err = _parse_block(codegen, cf->body, p_stack_level, break_addr, continue_addr);
if (err)
return err;
- codegen.opcodes.push_back(GDFunction::OPCODE_JUMP);
+ codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP);
codegen.opcodes.push_back(continue_addr);
codegen.opcodes[break_addr + 1] = codegen.opcodes.size();
} break;
- case GDParser::ControlFlowNode::CF_SWITCH: {
+ case GDScriptParser::ControlFlowNode::CF_SWITCH: {
} break;
- case GDParser::ControlFlowNode::CF_BREAK: {
+ case GDScriptParser::ControlFlowNode::CF_BREAK: {
if (p_break_addr < 0) {
_set_error("'break'' not within loop", cf);
return ERR_COMPILATION_FAILED;
}
- codegen.opcodes.push_back(GDFunction::OPCODE_JUMP);
+ codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP);
codegen.opcodes.push_back(p_break_addr);
} break;
- case GDParser::ControlFlowNode::CF_CONTINUE: {
+ case GDScriptParser::ControlFlowNode::CF_CONTINUE: {
if (p_continue_addr < 0) {
@@ -1285,11 +1286,11 @@ Error GDCompiler::_parse_block(CodeGen &codegen, const GDParser::BlockNode *p_bl
return ERR_COMPILATION_FAILED;
}
- codegen.opcodes.push_back(GDFunction::OPCODE_JUMP);
+ codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP);
codegen.opcodes.push_back(p_continue_addr);
} break;
- case GDParser::ControlFlowNode::CF_RETURN: {
+ case GDScriptParser::ControlFlowNode::CF_RETURN: {
int ret;
@@ -1301,38 +1302,38 @@ Error GDCompiler::_parse_block(CodeGen &codegen, const GDParser::BlockNode *p_bl
} else {
- ret = GDFunction::ADDR_TYPE_NIL << GDFunction::ADDR_BITS;
+ ret = GDScriptFunction::ADDR_TYPE_NIL << GDScriptFunction::ADDR_BITS;
}
- codegen.opcodes.push_back(GDFunction::OPCODE_RETURN);
+ codegen.opcodes.push_back(GDScriptFunction::OPCODE_RETURN);
codegen.opcodes.push_back(ret);
} break;
}
} break;
- case GDParser::Node::TYPE_ASSERT: {
+ case GDScriptParser::Node::TYPE_ASSERT: {
#ifdef DEBUG_ENABLED
// try subblocks
- const GDParser::AssertNode *as = static_cast<const GDParser::AssertNode *>(s);
+ const GDScriptParser::AssertNode *as = static_cast<const GDScriptParser::AssertNode *>(s);
int ret = _parse_expression(codegen, as->condition, p_stack_level, false);
if (ret < 0)
return ERR_PARSE_ERROR;
- codegen.opcodes.push_back(GDFunction::OPCODE_ASSERT);
+ codegen.opcodes.push_back(GDScriptFunction::OPCODE_ASSERT);
codegen.opcodes.push_back(ret);
#endif
} break;
- case GDParser::Node::TYPE_BREAKPOINT: {
+ case GDScriptParser::Node::TYPE_BREAKPOINT: {
#ifdef DEBUG_ENABLED
// try subblocks
- codegen.opcodes.push_back(GDFunction::OPCODE_BREAKPOINT);
+ codegen.opcodes.push_back(GDScriptFunction::OPCODE_BREAKPOINT);
#endif
} break;
- case GDParser::Node::TYPE_LOCAL_VAR: {
+ case GDScriptParser::Node::TYPE_LOCAL_VAR: {
- const GDParser::LocalVarNode *lv = static_cast<const GDParser::LocalVarNode *>(s);
+ const GDScriptParser::LocalVarNode *lv = static_cast<const GDScriptParser::LocalVarNode *>(s);
if (_is_class_member_property(codegen, lv->name)) {
_set_error("Name for local variable '" + String(lv->name) + "' can't shadow class property of the same name.", lv);
@@ -1356,7 +1357,7 @@ Error GDCompiler::_parse_block(CodeGen &codegen, const GDParser::BlockNode *p_bl
return OK;
}
-Error GDCompiler::_parse_function(GDScript *p_script, const GDParser::ClassNode *p_class, const GDParser::FunctionNode *p_func, bool p_for_ready) {
+Error GDScriptCompiler::_parse_function(GDScript *p_script, const GDScriptParser::ClassNode *p_class, const GDScriptParser::FunctionNode *p_func, bool p_for_ready) {
Vector<int> bytecode;
CodeGen codegen;
@@ -1397,10 +1398,10 @@ Error GDCompiler::_parse_function(GDScript *p_script, const GDParser::ClassNode
if (!p_func && p_class->extends_used && p_script->native.is_null()) {
//call implicit parent constructor
- codegen.opcodes.push_back(GDFunction::OPCODE_CALL_SELF_BASE);
+ codegen.opcodes.push_back(GDScriptFunction::OPCODE_CALL_SELF_BASE);
codegen.opcodes.push_back(codegen.get_name_map_pos("_init"));
codegen.opcodes.push_back(0);
- codegen.opcodes.push_back((GDFunction::ADDR_TYPE_STACK << GDFunction::ADDR_BITS) | 0);
+ codegen.opcodes.push_back((GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS) | 0);
}
Error err = _parse_block(codegen, p_class->initializer, stack_level);
if (err)
@@ -1426,7 +1427,7 @@ Error GDCompiler::_parse_function(GDScript *p_script, const GDParser::ClassNode
if (p_func->default_values.size()) {
- codegen.opcodes.push_back(GDFunction::OPCODE_JUMP_TO_DEF_ARGUMENT);
+ codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP_TO_DEF_ARGUMENT);
defarg_addr.push_back(codegen.opcodes.size());
for (int i = 0; i < p_func->default_values.size(); i++) {
@@ -1449,15 +1450,15 @@ Error GDCompiler::_parse_function(GDScript *p_script, const GDParser::ClassNode
func_name = "_init";
}
- codegen.opcodes.push_back(GDFunction::OPCODE_END);
+ codegen.opcodes.push_back(GDScriptFunction::OPCODE_END);
/*
if (String(p_func->name)=="") { //initializer func
gdfunc = &p_script->initializer;
*/
//} else { //regular func
- p_script->member_functions[func_name] = memnew(GDFunction);
- GDFunction *gdfunc = p_script->member_functions[func_name];
+ p_script->member_functions[func_name] = memnew(GDScriptFunction);
+ GDScriptFunction *gdfunc = p_script->member_functions[func_name];
//}
if (p_func) {
@@ -1579,7 +1580,7 @@ Error GDCompiler::_parse_function(GDScript *p_script, const GDParser::ClassNode
return OK;
}
-Error GDCompiler::_parse_class(GDScript *p_script, GDScript *p_owner, const GDParser::ClassNode *p_class, bool p_keep_state) {
+Error GDScriptCompiler::_parse_class(GDScript *p_script, GDScript *p_owner, const GDScriptParser::ClassNode *p_class, bool p_keep_state) {
Map<StringName, Ref<GDScript> > old_subclasses;
@@ -1587,12 +1588,12 @@ Error GDCompiler::_parse_class(GDScript *p_script, GDScript *p_owner, const GDPa
old_subclasses = p_script->subclasses;
}
- p_script->native = Ref<GDNativeClass>();
+ p_script->native = Ref<GDScriptNativeClass>();
p_script->base = Ref<GDScript>();
p_script->_base = NULL;
p_script->members.clear();
p_script->constants.clear();
- for (Map<StringName, GDFunction *>::Element *E = p_script->member_functions.front(); E; E = E->next()) {
+ for (Map<StringName, GDScriptFunction *>::Element *E = p_script->member_functions.front(); E; E = E->next()) {
memdelete(E->get());
}
p_script->member_functions.clear();
@@ -1606,7 +1607,7 @@ Error GDCompiler::_parse_class(GDScript *p_script, GDScript *p_owner, const GDPa
p_script->tool = p_class->tool;
p_script->name = p_class->name;
- Ref<GDNativeClass> native;
+ Ref<GDScriptNativeClass> native;
if (p_class->extends_used) {
//do inheritance
@@ -1685,21 +1686,44 @@ Error GDCompiler::_parse_class(GDScript *p_script, GDScript *p_owner, const GDPa
base_class = p->subclasses[base];
break;
}
+
+ if (p->constants.has(base)) {
+
+ base_class = p->constants[base];
+ if (base_class.is_null()) {
+ _set_error("Constant is not a class: " + base, p_class);
+ return ERR_SCRIPT_FAILED;
+ }
+ break;
+ }
+
p = p->_owner;
}
if (base_class.is_valid()) {
+ String ident = base;
+
for (int i = 1; i < p_class->extends_class.size(); i++) {
String subclass = p_class->extends_class[i];
+ ident += ("." + subclass);
+
if (base_class->subclasses.has(subclass)) {
base_class = base_class->subclasses[subclass];
+ } else if (base_class->constants.has(subclass)) {
+
+ Ref<GDScript> new_base_class = base_class->constants[subclass];
+ if (new_base_class.is_null()) {
+ _set_error("Constant is not a class: " + ident, p_class);
+ return ERR_SCRIPT_FAILED;
+ }
+ base_class = new_base_class;
} else {
- _set_error("Could not find subclass: " + subclass, p_class);
+ _set_error("Could not find subclass: " + ident, p_class);
return ERR_FILE_NOT_FOUND;
}
}
@@ -1801,14 +1825,14 @@ Error GDCompiler::_parse_class(GDScript *p_script, GDScript *p_owner, const GDPa
for (int i = 0; i < p_class->constant_expressions.size(); i++) {
StringName name = p_class->constant_expressions[i].identifier;
- ERR_CONTINUE(p_class->constant_expressions[i].expression->type != GDParser::Node::TYPE_CONSTANT);
+ ERR_CONTINUE(p_class->constant_expressions[i].expression->type != GDScriptParser::Node::TYPE_CONSTANT);
if (_is_class_member_property(p_script, name)) {
_set_error("Member '" + name + "' already exists as a class property.", p_class);
return ERR_ALREADY_EXISTS;
}
- GDParser::ConstantNode *constant = static_cast<GDParser::ConstantNode *>(p_class->constant_expressions[i].expression);
+ GDScriptParser::ConstantNode *constant = static_cast<GDScriptParser::ConstantNode *>(p_class->constant_expressions[i].expression);
p_script->constants.insert(name, constant->value);
//p_script->constants[constant->value].make_const();
@@ -1917,7 +1941,7 @@ Error GDCompiler::_parse_class(GDScript *p_script, GDScript *p_owner, const GDPa
for (int i = 0; i < p_class->variables.size(); i++) {
if (p_class->variables[i].setter) {
- const Map<StringName, GDFunction *>::Element *E = p_script->get_member_functions().find(p_class->variables[i].setter);
+ const Map<StringName, GDScriptFunction *>::Element *E = p_script->get_member_functions().find(p_class->variables[i].setter);
if (!E) {
_set_error("Setter function '" + String(p_class->variables[i].setter) + "' not found in class.", NULL);
err_line = p_class->variables[i].line;
@@ -1934,7 +1958,7 @@ Error GDCompiler::_parse_class(GDScript *p_script, GDScript *p_owner, const GDPa
}
}
if (p_class->variables[i].getter) {
- const Map<StringName, GDFunction *>::Element *E = p_script->get_member_functions().find(p_class->variables[i].getter);
+ const Map<StringName, GDScriptFunction *>::Element *E = p_script->get_member_functions().find(p_class->variables[i].getter);
if (!E) {
_set_error("Getter function '" + String(p_class->variables[i].getter) + "' not found in class.", NULL);
err_line = p_class->variables[i].line;
@@ -1970,7 +1994,7 @@ Error GDCompiler::_parse_class(GDScript *p_script, GDScript *p_owner, const GDPa
//re-create as an instance
p_script->placeholders.erase(psi); //remove placeholder
- GDInstance *instance = memnew(GDInstance);
+ GDScriptInstance *instance = memnew(GDScriptInstance);
instance->base_ref = Object::cast_to<Reference>(E->get());
instance->members.resize(p_script->member_indices.size());
instance->script = Ref<GDScript>(p_script);
@@ -1994,7 +2018,7 @@ Error GDCompiler::_parse_class(GDScript *p_script, GDScript *p_owner, const GDPa
#endif
} else {
- GDInstance *gi = static_cast<GDInstance *>(si);
+ GDScriptInstance *gi = static_cast<GDScriptInstance *>(si);
gi->reload_members();
}
@@ -2007,18 +2031,18 @@ Error GDCompiler::_parse_class(GDScript *p_script, GDScript *p_owner, const GDPa
return OK;
}
-Error GDCompiler::compile(const GDParser *p_parser, GDScript *p_script, bool p_keep_state) {
+Error GDScriptCompiler::compile(const GDScriptParser *p_parser, GDScript *p_script, bool p_keep_state) {
err_line = -1;
err_column = -1;
error = "";
parser = p_parser;
- const GDParser::Node *root = parser->get_parse_tree();
- ERR_FAIL_COND_V(root->type != GDParser::Node::TYPE_CLASS, ERR_INVALID_DATA);
+ const GDScriptParser::Node *root = parser->get_parse_tree();
+ ERR_FAIL_COND_V(root->type != GDScriptParser::Node::TYPE_CLASS, ERR_INVALID_DATA);
source = p_script->get_path();
- Error err = _parse_class(p_script, NULL, static_cast<const GDParser::ClassNode *>(root), p_keep_state);
+ Error err = _parse_class(p_script, NULL, static_cast<const GDScriptParser::ClassNode *>(root), p_keep_state);
if (err)
return err;
@@ -2026,18 +2050,18 @@ Error GDCompiler::compile(const GDParser *p_parser, GDScript *p_script, bool p_k
return OK;
}
-String GDCompiler::get_error() const {
+String GDScriptCompiler::get_error() const {
return error;
}
-int GDCompiler::get_error_line() const {
+int GDScriptCompiler::get_error_line() const {
return err_line;
}
-int GDCompiler::get_error_column() const {
+int GDScriptCompiler::get_error_column() const {
return err_column;
}
-GDCompiler::GDCompiler() {
+GDScriptCompiler::GDScriptCompiler() {
}
diff --git a/modules/gdscript/gd_compiler.h b/modules/gdscript/gdscript_compiler.h
index ac713ae75b..6e0457ba30 100644
--- a/modules/gdscript/gd_compiler.h
+++ b/modules/gdscript/gdscript_compiler.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* gd_compiler.h */
+/* gdscript_compiler.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -27,26 +27,26 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef GD_COMPILER_H
-#define GD_COMPILER_H
+#ifndef GDSCRIPT_COMPILER_H
+#define GDSCRIPT_COMPILER_H
-#include "gd_parser.h"
-#include "gd_script.h"
+#include "gdscript.h"
+#include "gdscript_parser.h"
-class GDCompiler {
+class GDScriptCompiler {
- const GDParser *parser;
+ const GDScriptParser *parser;
struct CodeGen {
GDScript *script;
- const GDParser::ClassNode *class_node;
- const GDParser::FunctionNode *function_node;
+ const GDScriptParser::ClassNode *class_node;
+ const GDScriptParser::FunctionNode *function_node;
bool debug_stack;
List<Map<StringName, int> > stack_id_stack;
Map<StringName, int> stack_identifiers;
- List<GDFunction::StackDebug> stack_debug;
+ List<GDScriptFunction::StackDebug> stack_debug;
List<Map<StringName, int> > block_identifier_stack;
Map<StringName, int> block_identifiers;
@@ -54,7 +54,7 @@ class GDCompiler {
stack_identifiers[p_id] = p_stackpos;
if (debug_stack) {
block_identifiers[p_id] = p_stackpos;
- GDFunction::StackDebug sd;
+ GDScriptFunction::StackDebug sd;
sd.added = true;
sd.line = current_line;
sd.identifier = p_id;
@@ -79,7 +79,7 @@ class GDCompiler {
if (debug_stack) {
for (Map<StringName, int>::Element *E = block_identifiers.front(); E; E = E->next()) {
- GDFunction::StackDebug sd;
+ GDScriptFunction::StackDebug sd;
sd.added = false;
sd.identifier = E->key();
sd.line = current_line;
@@ -129,29 +129,29 @@ class GDCompiler {
bool _is_class_member_property(CodeGen &codegen, const StringName &p_name);
bool _is_class_member_property(GDScript *owner, const StringName &p_name);
- void _set_error(const String &p_error, const GDParser::Node *p_node);
+ void _set_error(const String &p_error, const GDScriptParser::Node *p_node);
- bool _create_unary_operator(CodeGen &codegen, const GDParser::OperatorNode *on, Variant::Operator op, int p_stack_level);
- bool _create_binary_operator(CodeGen &codegen, const GDParser::OperatorNode *on, Variant::Operator op, int p_stack_level, bool p_initializer = false);
+ 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);
- int _parse_assign_right_expression(CodeGen &codegen, const GDParser::OperatorNode *p_expression, int p_stack_level);
- int _parse_expression(CodeGen &codegen, const GDParser::Node *p_expression, int p_stack_level, bool p_root = false, bool p_initializer = false);
- Error _parse_block(CodeGen &codegen, const GDParser::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 GDParser::ClassNode *p_class, const GDParser::FunctionNode *p_func, bool p_for_ready = false);
- Error _parse_class(GDScript *p_script, GDScript *p_owner, const GDParser::ClassNode *p_class, bool p_keep_state);
+ 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);
+ 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(GDScript *p_script, GDScript *p_owner, const GDScriptParser::ClassNode *p_class, bool p_keep_state);
int err_line;
int err_column;
StringName source;
String error;
public:
- Error compile(const GDParser *p_parser, GDScript *p_script, bool p_keep_state = false);
+ Error compile(const GDScriptParser *p_parser, GDScript *p_script, bool p_keep_state = false);
String get_error() const;
int get_error_line() const;
int get_error_column() const;
- GDCompiler();
+ GDScriptCompiler();
};
-#endif // COMPILER_H
+#endif // GDSCRIPT_COMPILER_H
diff --git a/modules/gdscript/gd_editor.cpp b/modules/gdscript/gdscript_editor.cpp
index b0408917a4..5a76acea6e 100644
--- a/modules/gdscript/gd_editor.cpp
+++ b/modules/gdscript/gdscript_editor.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* gd_editor.cpp */
+/* gdscript_editor.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -27,13 +27,13 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "gd_script.h"
+#include "gdscript.h"
#include "editor/editor_settings.h"
-#include "gd_compiler.h"
+#include "gdscript_compiler.h"
#include "global_constants.h"
#include "os/file_access.h"
-#include "project_settings.h"
+#include "core/engine.h"
#ifdef TOOLS_ENABLED
#include "editor/editor_file_system.h"
@@ -61,7 +61,11 @@ Ref<Script> GDScriptLanguage::get_template(const String &p_class_name, const Str
"func _ready():\n" +
"%TS%# Called every time the node is added to the scene.\n" +
"%TS%# Initialization here\n" +
- "%TS%pass\n";
+ "%TS%pass\n\n" +
+ "#func _process(delta):\n" +
+ "#%TS%# Called every frame. Delta is time since last frame.\n" +
+ "#%TS%# Update game logic here.\n" +
+ "#%TS%pass\n";
_template = _template.replace("%BASE%", p_base_class_name);
_template = _template.replace("%TS%", _get_indentation());
@@ -88,7 +92,7 @@ void GDScriptLanguage::make_template(const String &p_class_name, const String &p
bool GDScriptLanguage::validate(const String &p_script, int &r_line_error, int &r_col_error, String &r_test_error, const String &p_path, List<String> *r_functions) const {
- GDParser parser;
+ GDScriptParser parser;
Error err = parser.parse(p_script, p_path.get_base_dir(), true, p_path);
if (err) {
@@ -98,10 +102,10 @@ bool GDScriptLanguage::validate(const String &p_script, int &r_line_error, int &
return false;
} else {
- const GDParser::Node *root = parser.get_parse_tree();
- ERR_FAIL_COND_V(root->type != GDParser::Node::TYPE_CLASS, false);
+ const GDScriptParser::Node *root = parser.get_parse_tree();
+ ERR_FAIL_COND_V(root->type != GDScriptParser::Node::TYPE_CLASS, false);
- const GDParser::ClassNode *cl = static_cast<const GDParser::ClassNode *>(root);
+ const GDScriptParser::ClassNode *cl = static_cast<const GDScriptParser::ClassNode *>(root);
Map<int, String> funcs;
for (int i = 0; i < cl->functions.size(); i++) {
@@ -127,18 +131,23 @@ bool GDScriptLanguage::has_named_classes() const {
return false;
}
+bool GDScriptLanguage::supports_builtin_mode() const {
+
+ return true;
+}
+
int GDScriptLanguage::find_function(const String &p_function, const String &p_code) const {
- GDTokenizerText tokenizer;
+ GDScriptTokenizerText tokenizer;
tokenizer.set_code(p_code);
int indent = 0;
- while (tokenizer.get_token() != GDTokenizer::TK_EOF && tokenizer.get_token() != GDTokenizer::TK_ERROR) {
+ while (tokenizer.get_token() != GDScriptTokenizer::TK_EOF && tokenizer.get_token() != GDScriptTokenizer::TK_ERROR) {
- if (tokenizer.get_token() == GDTokenizer::TK_NEWLINE) {
+ if (tokenizer.get_token() == GDScriptTokenizer::TK_NEWLINE) {
indent = tokenizer.get_token_line_indent();
}
- //print_line("TOKEN: "+String(GDTokenizer::get_token_name(tokenizer.get_token())));
- if (indent == 0 && tokenizer.get_token() == GDTokenizer::TK_PR_FUNCTION && tokenizer.get_token(1) == GDTokenizer::TK_IDENTIFIER) {
+ //print_line("TOKEN: "+String(GDScriptTokenizer::get_token_name(tokenizer.get_token())));
+ if (indent == 0 && tokenizer.get_token() == GDScriptTokenizer::TK_PR_FUNCTION && tokenizer.get_token(1) == GDScriptTokenizer::TK_IDENTIFIER) {
String identifier = tokenizer.get_token_identifier(1);
if (identifier == p_function) {
@@ -146,7 +155,7 @@ int GDScriptLanguage::find_function(const String &p_function, const String &p_co
}
}
tokenizer.advance();
- //print_line("NEXT: "+String(GDTokenizer::get_token_name(tokenizer.get_token())));
+ //print_line("NEXT: "+String(GDScriptTokenizer::get_token_name(tokenizer.get_token())));
}
return -1;
}
@@ -236,7 +245,7 @@ void GDScriptLanguage::debug_get_stack_level_locals(int p_level, List<String> *p
ERR_FAIL_INDEX(p_level, _debug_call_stack_pos);
int l = _debug_call_stack_pos - p_level - 1;
- GDFunction *f = _call_stack[l].function;
+ GDScriptFunction *f = _call_stack[l].function;
List<Pair<StringName, int> > locals;
@@ -255,7 +264,7 @@ void GDScriptLanguage::debug_get_stack_level_members(int p_level, List<String> *
ERR_FAIL_INDEX(p_level, _debug_call_stack_pos);
int l = _debug_call_stack_pos - p_level - 1;
- GDInstance *instance = _call_stack[l].instance;
+ GDScriptInstance *instance = _call_stack[l].instance;
if (!instance)
return;
@@ -271,10 +280,62 @@ void GDScriptLanguage::debug_get_stack_level_members(int p_level, List<String> *
p_values->push_back(instance->debug_get_member_by_index(E->get().index));
}
}
-void GDScriptLanguage::debug_get_globals(List<String> *p_locals, List<Variant> *p_values, int p_max_subitems, int p_max_depth) {
- //no globals are really reachable in gdscript
+ScriptInstance *GDScriptLanguage::debug_get_stack_level_instance(int p_level) {
+
+ ERR_FAIL_COND_V(_debug_parse_err_line >= 0, NULL);
+ ERR_FAIL_INDEX_V(p_level, _debug_call_stack_pos, NULL);
+
+ int l = _debug_call_stack_pos - p_level - 1;
+ ScriptInstance *instance = _call_stack[l].instance;
+
+ return instance;
+}
+
+void GDScriptLanguage::debug_get_globals(List<String> *p_globals, List<Variant> *p_values, int p_max_subitems, int p_max_depth) {
+
+ const Map<StringName, int> &name_idx = GDScriptLanguage::get_singleton()->get_global_map();
+ const Variant *globals = GDScriptLanguage::get_singleton()->get_global_array();
+
+ List<Pair<String, Variant> > cinfo;
+ get_public_constants(&cinfo);
+
+ for (const Map<StringName, int>::Element *E = name_idx.front(); E; E = E->next()) {
+
+ if (ClassDB::class_exists(E->key()) || Engine::get_singleton()->has_singleton(E->key()))
+ continue;
+
+ bool is_script_constant = false;
+ for (List<Pair<String, Variant> >::Element *CE = cinfo.front(); CE; CE = CE->next()) {
+ if (CE->get().first == E->key()) {
+ is_script_constant = true;
+ break;
+ }
+ }
+ if (is_script_constant)
+ continue;
+
+ const Variant &var = globals[E->value()];
+ if (Object *obj = var) {
+ if (Object::cast_to<GDScriptNativeClass>(obj))
+ continue;
+ }
+
+ bool skip = false;
+ for (int i = 0; i < GlobalConstants::get_global_constant_count(); i++) {
+ if (E->key() == GlobalConstants::get_global_constant_name(i)) {
+ skip = true;
+ break;
+ }
+ }
+ if (skip)
+ continue;
+
+ p_globals->push_back(E->key());
+ p_values->push_back(var);
+ }
}
+
String GDScriptLanguage::debug_parse_stack_level_expression(int p_level, const String &p_expression, int p_max_subitems, int p_max_depth) {
if (_debug_parse_err_line >= 0)
@@ -289,9 +350,9 @@ void GDScriptLanguage::get_recognized_extensions(List<String> *p_extensions) con
void GDScriptLanguage::get_public_functions(List<MethodInfo> *p_functions) const {
- for (int i = 0; i < GDFunctions::FUNC_MAX; i++) {
+ for (int i = 0; i < GDScriptFunctions::FUNC_MAX; i++) {
- p_functions->push_back(GDFunctions::get_info(GDFunctions::Function(i)));
+ p_functions->push_back(GDScriptFunctions::get_info(GDScriptFunctions::Function(i)));
}
//not really "functions", but..
@@ -309,7 +370,7 @@ void GDScriptLanguage::get_public_functions(List<MethodInfo> *p_functions) const
mi.arguments.push_back(PropertyInfo(Variant::STRING, "signal"));
mi.default_arguments.push_back(Variant::NIL);
mi.default_arguments.push_back(Variant::STRING);
- mi.return_val = PropertyInfo(Variant::OBJECT, "", PROPERTY_HINT_RESOURCE_TYPE, "GDFunctionState");
+ mi.return_val = PropertyInfo(Variant::OBJECT, "", PROPERTY_HINT_RESOURCE_TYPE, "GDScriptFunctionState");
p_functions->push_back(mi);
}
{
@@ -328,6 +389,11 @@ void GDScriptLanguage::get_public_constants(List<Pair<String, Variant> > *p_cons
pi.second = Math_PI;
p_constants->push_back(pi);
+ Pair<String, Variant> tau;
+ tau.first = "TAU";
+ tau.second = Math_TAU;
+ p_constants->push_back(tau);
+
Pair<String, Variant> infinity;
infinity.first = "INF";
infinity.second = Math_INF;
@@ -351,14 +417,14 @@ String GDScriptLanguage::make_function(const String &p_class, const String &p_na
}
s += " ";
}
- s += "):\n\tpass # replace with function body\n";
+ s += "):\n" + _get_indentation() + "pass # replace with function body\n";
return s;
}
#if defined(DEBUG_METHODS_ENABLED) && defined(TOOLS_ENABLED)
-struct GDCompletionIdentifier {
+struct GDScriptCompletionIdentifier {
String enumeration;
StringName obj_type;
@@ -367,17 +433,17 @@ struct GDCompletionIdentifier {
Variant value; //im case there is a value, also return it
};
-static GDCompletionIdentifier _get_type_from_variant(const Variant &p_variant, bool p_allow_gdnative_class = false) {
+static GDScriptCompletionIdentifier _get_type_from_variant(const Variant &p_variant, bool p_allow_gdnative_class = false) {
- GDCompletionIdentifier t;
+ GDScriptCompletionIdentifier t;
t.type = p_variant.get_type();
t.value = p_variant;
if (p_variant.get_type() == Variant::OBJECT) {
Object *obj = p_variant;
if (obj) {
- if (p_allow_gdnative_class && Object::cast_to<GDNativeClass>(obj)) {
- t.obj_type = Object::cast_to<GDNativeClass>(obj)->get_name();
+ if (p_allow_gdnative_class && Object::cast_to<GDScriptNativeClass>(obj)) {
+ t.obj_type = Object::cast_to<GDScriptNativeClass>(obj)->get_name();
t.value = Variant();
} else {
@@ -388,9 +454,9 @@ static GDCompletionIdentifier _get_type_from_variant(const Variant &p_variant, b
return t;
}
-static GDCompletionIdentifier _get_type_from_pinfo(const PropertyInfo &p_info) {
+static GDScriptCompletionIdentifier _get_type_from_pinfo(const PropertyInfo &p_info) {
- GDCompletionIdentifier t;
+ GDScriptCompletionIdentifier t;
t.type = p_info.type;
if (p_info.hint == PROPERTY_HINT_RESOURCE_TYPE) {
t.obj_type = p_info.hint_string;
@@ -398,23 +464,23 @@ static GDCompletionIdentifier _get_type_from_pinfo(const PropertyInfo &p_info) {
return t;
}
-struct GDCompletionContext {
+struct GDScriptCompletionContext {
- const GDParser::ClassNode *_class;
- const GDParser::FunctionNode *function;
- const GDParser::BlockNode *block;
+ const GDScriptParser::ClassNode *_class;
+ const GDScriptParser::FunctionNode *function;
+ const GDScriptParser::BlockNode *block;
Object *base;
String base_path;
};
-static Ref<Reference> _get_parent_class(GDCompletionContext &context) {
+static Ref<Reference> _get_parent_class(GDScriptCompletionContext &context) {
if (context._class->extends_used) {
//do inheritance
String path = context._class->extends_file;
Ref<GDScript> script;
- Ref<GDNativeClass> native;
+ Ref<GDScriptNativeClass> native;
if (path != "") {
//path (and optionally subclasses)
@@ -484,17 +550,17 @@ static Ref<Reference> _get_parent_class(GDCompletionContext &context) {
return Ref<Reference>();
}
-static GDCompletionIdentifier _get_native_class(GDCompletionContext &context) {
+static GDScriptCompletionIdentifier _get_native_class(GDScriptCompletionContext &context) {
//eeh...
- GDCompletionIdentifier id;
+ GDScriptCompletionIdentifier id;
id.type = Variant::NIL;
REF pc = _get_parent_class(context);
if (!pc.is_valid()) {
return id;
}
- Ref<GDNativeClass> nc = pc;
+ Ref<GDScriptNativeClass> nc = pc;
Ref<GDScript> s = pc;
if (s.is_null() && nc.is_null()) {
@@ -515,28 +581,28 @@ static GDCompletionIdentifier _get_native_class(GDCompletionContext &context) {
return id;
}
-static bool _guess_identifier_type(GDCompletionContext &context, int p_line, const StringName &p_identifier, GDCompletionIdentifier &r_type, bool p_for_indexing);
+static bool _guess_identifier_type(GDScriptCompletionContext &context, int p_line, const StringName &p_identifier, GDScriptCompletionIdentifier &r_type, bool p_for_indexing);
-static bool _guess_expression_type(GDCompletionContext &context, const GDParser::Node *p_node, int p_line, GDCompletionIdentifier &r_type, bool p_for_indexing = false) {
+static bool _guess_expression_type(GDScriptCompletionContext &context, const GDScriptParser::Node *p_node, int p_line, GDScriptCompletionIdentifier &r_type, bool p_for_indexing = false) {
- if (p_node->type == GDParser::Node::TYPE_CONSTANT) {
+ if (p_node->type == GDScriptParser::Node::TYPE_CONSTANT) {
- const GDParser::ConstantNode *cn = static_cast<const GDParser::ConstantNode *>(p_node);
+ const GDScriptParser::ConstantNode *cn = static_cast<const GDScriptParser::ConstantNode *>(p_node);
r_type = _get_type_from_variant(cn->value);
return true;
- } else if (p_node->type == GDParser::Node::TYPE_DICTIONARY) {
+ } else if (p_node->type == GDScriptParser::Node::TYPE_DICTIONARY) {
r_type.type = Variant::DICTIONARY;
//what the heck, fill it anyway
- const GDParser::DictionaryNode *an = static_cast<const GDParser::DictionaryNode *>(p_node);
+ const GDScriptParser::DictionaryNode *an = static_cast<const GDScriptParser::DictionaryNode *>(p_node);
Dictionary d;
for (int i = 0; i < an->elements.size(); i++) {
- GDCompletionIdentifier k;
+ GDScriptCompletionIdentifier k;
if (_guess_expression_type(context, an->elements[i].key, p_line, k) && k.value.get_type() != Variant::NIL) {
- GDCompletionIdentifier v;
+ GDScriptCompletionIdentifier v;
if (_guess_expression_type(context, an->elements[i].value, p_line, v)) {
d[k.value] = v.value;
}
@@ -544,15 +610,15 @@ static bool _guess_expression_type(GDCompletionContext &context, const GDParser:
}
r_type.value = d;
return true;
- } else if (p_node->type == GDParser::Node::TYPE_ARRAY) {
+ } else if (p_node->type == GDScriptParser::Node::TYPE_ARRAY) {
r_type.type = Variant::ARRAY;
//what the heck, fill it anyway
- const GDParser::ArrayNode *an = static_cast<const GDParser::ArrayNode *>(p_node);
+ const GDScriptParser::ArrayNode *an = static_cast<const GDScriptParser::ArrayNode *>(p_node);
Array arr;
arr.resize(an->elements.size());
for (int i = 0; i < an->elements.size(); i++) {
- GDCompletionIdentifier ci;
+ GDScriptCompletionIdentifier ci;
if (_guess_expression_type(context, an->elements[i], p_line, ci)) {
arr[i] = ci.value;
}
@@ -560,44 +626,44 @@ static bool _guess_expression_type(GDCompletionContext &context, const GDParser:
r_type.value = arr;
return true;
- } else if (p_node->type == GDParser::Node::TYPE_BUILT_IN_FUNCTION) {
+ } else if (p_node->type == GDScriptParser::Node::TYPE_BUILT_IN_FUNCTION) {
- MethodInfo mi = GDFunctions::get_info(static_cast<const GDParser::BuiltInFunctionNode *>(p_node)->function);
+ MethodInfo mi = GDScriptFunctions::get_info(static_cast<const GDScriptParser::BuiltInFunctionNode *>(p_node)->function);
r_type = _get_type_from_pinfo(mi.return_val);
return true;
- } else if (p_node->type == GDParser::Node::TYPE_IDENTIFIER) {
+ } else if (p_node->type == GDScriptParser::Node::TYPE_IDENTIFIER) {
- return _guess_identifier_type(context, p_line - 1, static_cast<const GDParser::IdentifierNode *>(p_node)->name, r_type, p_for_indexing);
- } else if (p_node->type == GDParser::Node::TYPE_SELF) {
+ return _guess_identifier_type(context, p_line - 1, static_cast<const GDScriptParser::IdentifierNode *>(p_node)->name, r_type, p_for_indexing);
+ } else if (p_node->type == GDScriptParser::Node::TYPE_SELF) {
//eeh...
r_type = _get_native_class(context);
return r_type.type != Variant::NIL;
- } else if (p_node->type == GDParser::Node::TYPE_OPERATOR) {
+ } else if (p_node->type == GDScriptParser::Node::TYPE_OPERATOR) {
- const GDParser::OperatorNode *op = static_cast<const GDParser::OperatorNode *>(p_node);
- if (op->op == GDParser::OperatorNode::OP_CALL) {
+ const GDScriptParser::OperatorNode *op = static_cast<const GDScriptParser::OperatorNode *>(p_node);
+ if (op->op == GDScriptParser::OperatorNode::OP_CALL) {
- if (op->arguments[0]->type == GDParser::Node::TYPE_TYPE) {
+ if (op->arguments[0]->type == GDScriptParser::Node::TYPE_TYPE) {
- const GDParser::TypeNode *tn = static_cast<const GDParser::TypeNode *>(op->arguments[0]);
+ const GDScriptParser::TypeNode *tn = static_cast<const GDScriptParser::TypeNode *>(op->arguments[0]);
r_type.type = tn->vtype;
return true;
- } else if (op->arguments[0]->type == GDParser::Node::TYPE_BUILT_IN_FUNCTION) {
+ } else if (op->arguments[0]->type == GDScriptParser::Node::TYPE_BUILT_IN_FUNCTION) {
- const GDParser::BuiltInFunctionNode *bin = static_cast<const GDParser::BuiltInFunctionNode *>(op->arguments[0]);
+ const GDScriptParser::BuiltInFunctionNode *bin = static_cast<const GDScriptParser::BuiltInFunctionNode *>(op->arguments[0]);
return _guess_expression_type(context, bin, p_line, r_type);
- } else if (op->arguments.size() > 1 && op->arguments[1]->type == GDParser::Node::TYPE_IDENTIFIER) {
+ } else if (op->arguments.size() > 1 && op->arguments[1]->type == GDScriptParser::Node::TYPE_IDENTIFIER) {
- StringName id = static_cast<const GDParser::IdentifierNode *>(op->arguments[1])->name;
+ StringName id = static_cast<const GDScriptParser::IdentifierNode *>(op->arguments[1])->name;
- if (op->arguments[0]->type == GDParser::Node::TYPE_IDENTIFIER && String(id) == "new") {
+ if (op->arguments[0]->type == GDScriptParser::Node::TYPE_IDENTIFIER && String(id) == "new") {
//shortcut
- StringName identifier = static_cast<const GDParser::IdentifierNode *>(op->arguments[0])->name;
+ StringName identifier = static_cast<const GDScriptParser::IdentifierNode *>(op->arguments[0])->name;
if (ClassDB::class_exists(identifier)) {
r_type.type = Variant::OBJECT;
@@ -607,7 +673,7 @@ static bool _guess_expression_type(GDCompletionContext &context, const GDParser:
}
}
- GDCompletionIdentifier base;
+ GDScriptCompletionIdentifier base;
if (!_guess_expression_type(context, op->arguments[0], p_line, base))
return false;
@@ -616,8 +682,8 @@ static bool _guess_expression_type(GDCompletionContext &context, const GDParser:
if (id.operator String() == "new" && base.value.get_type() == Variant::OBJECT) {
Object *obj = base.value;
- if (obj && Object::cast_to<GDNativeClass>(obj)) {
- GDNativeClass *gdnc = Object::cast_to<GDNativeClass>(obj);
+ if (obj && Object::cast_to<GDScriptNativeClass>(obj)) {
+ GDScriptNativeClass *gdnc = Object::cast_to<GDScriptNativeClass>(obj);
r_type.type = Variant::OBJECT;
r_type.value = Variant();
r_type.obj_type = gdnc->get_name();
@@ -648,7 +714,7 @@ static bool _guess_expression_type(GDCompletionContext &context, const GDParser:
bool all_valid = true;
Vector<Variant> args;
for (int i = 2; i < op->arguments.size(); i++) {
- GDCompletionIdentifier arg;
+ GDScriptCompletionIdentifier arg;
if (_guess_expression_type(context, op->arguments[i], p_line, arg)) {
if (arg.value.get_type() != Variant::NIL && arg.value.get_type() != Variant::OBJECT) { // calling with object seems dangerous, i don' t know
@@ -771,15 +837,15 @@ static bool _guess_expression_type(GDCompletionContext &context, const GDParser:
}
}
}
- } else if (op->op == GDParser::OperatorNode::OP_INDEX || op->op == GDParser::OperatorNode::OP_INDEX_NAMED) {
+ } else if (op->op == GDScriptParser::OperatorNode::OP_INDEX || op->op == GDScriptParser::OperatorNode::OP_INDEX_NAMED) {
- GDCompletionIdentifier p1;
- GDCompletionIdentifier p2;
+ GDScriptCompletionIdentifier p1;
+ GDScriptCompletionIdentifier p2;
- if (op->op == GDParser::OperatorNode::OP_INDEX_NAMED) {
+ if (op->op == GDScriptParser::OperatorNode::OP_INDEX_NAMED) {
- if (op->arguments[1]->type == GDParser::Node::TYPE_IDENTIFIER) {
- String id = static_cast<const GDParser::IdentifierNode *>(op->arguments[1])->name;
+ if (op->arguments[1]->type == GDScriptParser::Node::TYPE_IDENTIFIER) {
+ String id = static_cast<const GDScriptParser::IdentifierNode *>(op->arguments[1])->name;
p2.type = Variant::STRING;
p2.value = id;
}
@@ -793,9 +859,9 @@ static bool _guess_expression_type(GDCompletionContext &context, const GDParser:
}
}
- if (op->arguments[0]->type == GDParser::Node::TYPE_ARRAY) {
+ if (op->arguments[0]->type == GDScriptParser::Node::TYPE_ARRAY) {
- const GDParser::ArrayNode *an = static_cast<const GDParser::ArrayNode *>(op->arguments[0]);
+ const GDScriptParser::ArrayNode *an = static_cast<const GDScriptParser::ArrayNode *>(op->arguments[0]);
if (p2.value.is_num()) {
int index = p2.value;
if (index < 0 || index >= an->elements.size())
@@ -803,16 +869,16 @@ static bool _guess_expression_type(GDCompletionContext &context, const GDParser:
return _guess_expression_type(context, an->elements[index], p_line, r_type);
}
- } else if (op->arguments[0]->type == GDParser::Node::TYPE_DICTIONARY) {
+ } else if (op->arguments[0]->type == GDScriptParser::Node::TYPE_DICTIONARY) {
- const GDParser::DictionaryNode *dn = static_cast<const GDParser::DictionaryNode *>(op->arguments[0]);
+ const GDScriptParser::DictionaryNode *dn = static_cast<const GDScriptParser::DictionaryNode *>(op->arguments[0]);
if (p2.value.get_type() == Variant::NIL)
return false;
for (int i = 0; i < dn->elements.size(); i++) {
- GDCompletionIdentifier k;
+ GDScriptCompletionIdentifier k;
if (!_guess_expression_type(context, dn->elements[i].key, p_line, k)) {
@@ -844,9 +910,9 @@ static bool _guess_expression_type(GDCompletionContext &context, const GDParser:
StringName base_type = p1.obj_type;
- if (p1.obj_type == "GDNativeClass") {
+ if (p1.obj_type == "GDScriptNativeClass") {
//native enum
- Ref<GDNativeClass> gdn = p1.value;
+ Ref<GDScriptNativeClass> gdn = p1.value;
if (gdn.is_valid()) {
base_type = gdn->get_name();
@@ -907,24 +973,24 @@ static bool _guess_expression_type(GDCompletionContext &context, const GDParser:
Variant::Operator vop = Variant::OP_MAX;
switch (op->op) {
- case GDParser::OperatorNode::OP_ADD: vop = Variant::OP_ADD; break;
- case GDParser::OperatorNode::OP_SUB: vop = Variant::OP_SUBTRACT; break;
- case GDParser::OperatorNode::OP_MUL: vop = Variant::OP_MULTIPLY; break;
- case GDParser::OperatorNode::OP_DIV: vop = Variant::OP_DIVIDE; break;
- case GDParser::OperatorNode::OP_MOD: vop = Variant::OP_MODULE; break;
- case GDParser::OperatorNode::OP_SHIFT_LEFT: vop = Variant::OP_SHIFT_LEFT; break;
- case GDParser::OperatorNode::OP_SHIFT_RIGHT: vop = Variant::OP_SHIFT_RIGHT; break;
- case GDParser::OperatorNode::OP_BIT_AND: vop = Variant::OP_BIT_AND; break;
- case GDParser::OperatorNode::OP_BIT_OR: vop = Variant::OP_BIT_OR; break;
- case GDParser::OperatorNode::OP_BIT_XOR: vop = Variant::OP_BIT_XOR; break;
+ case GDScriptParser::OperatorNode::OP_ADD: vop = Variant::OP_ADD; break;
+ case GDScriptParser::OperatorNode::OP_SUB: vop = Variant::OP_SUBTRACT; break;
+ case GDScriptParser::OperatorNode::OP_MUL: vop = Variant::OP_MULTIPLY; break;
+ case GDScriptParser::OperatorNode::OP_DIV: vop = Variant::OP_DIVIDE; break;
+ case GDScriptParser::OperatorNode::OP_MOD: vop = Variant::OP_MODULE; break;
+ case GDScriptParser::OperatorNode::OP_SHIFT_LEFT: vop = Variant::OP_SHIFT_LEFT; break;
+ case GDScriptParser::OperatorNode::OP_SHIFT_RIGHT: vop = Variant::OP_SHIFT_RIGHT; break;
+ case GDScriptParser::OperatorNode::OP_BIT_AND: vop = Variant::OP_BIT_AND; break;
+ case GDScriptParser::OperatorNode::OP_BIT_OR: vop = Variant::OP_BIT_OR; break;
+ case GDScriptParser::OperatorNode::OP_BIT_XOR: vop = Variant::OP_BIT_XOR; break;
default: {}
}
if (vop == Variant::OP_MAX)
return false;
- GDCompletionIdentifier p1;
- GDCompletionIdentifier p2;
+ GDScriptCompletionIdentifier p1;
+ GDScriptCompletionIdentifier p2;
if (op->arguments[0]) {
if (!_guess_expression_type(context, op->arguments[0], p_line, p1)) {
@@ -971,15 +1037,15 @@ static bool _guess_expression_type(GDCompletionContext &context, const GDParser:
return false;
}
-static bool _guess_identifier_type_in_block(GDCompletionContext &context, int p_line, const StringName &p_identifier, GDCompletionIdentifier &r_type) {
+static bool _guess_identifier_type_in_block(GDScriptCompletionContext &context, int p_line, const StringName &p_identifier, GDScriptCompletionIdentifier &r_type) {
- if (context.block->if_condition && context.block->if_condition->type == GDParser::Node::TYPE_OPERATOR && static_cast<const GDParser::OperatorNode *>(context.block->if_condition)->op == GDParser::OperatorNode::OP_IS) {
+ if (context.block->if_condition && context.block->if_condition->type == GDScriptParser::Node::TYPE_OPERATOR && static_cast<const GDScriptParser::OperatorNode *>(context.block->if_condition)->op == GDScriptParser::OperatorNode::OP_IS) {
//is used, check if identifier is in there! this helps resolve in blocks that are (if (identifier is value)): which are very common..
//super dirty hack, but very useful
//credit: Zylann
//TODO: this could be hacked to detect ANDed conditions too..
- const GDParser::OperatorNode *op = static_cast<const GDParser::OperatorNode *>(context.block->if_condition);
- if (op->arguments[0]->type == GDParser::Node::TYPE_IDENTIFIER && static_cast<const GDParser::IdentifierNode *>(op->arguments[0])->name == p_identifier) {
+ const GDScriptParser::OperatorNode *op = static_cast<const GDScriptParser::OperatorNode *>(context.block->if_condition);
+ if (op->arguments[0]->type == GDScriptParser::Node::TYPE_IDENTIFIER && static_cast<const GDScriptParser::IdentifierNode *>(op->arguments[0])->name == p_identifier) {
//bingo
if (_guess_expression_type(context, op->arguments[1], op->line, r_type)) {
return true;
@@ -987,7 +1053,7 @@ static bool _guess_identifier_type_in_block(GDCompletionContext &context, int p_
}
}
- GDCompletionIdentifier gdi = _get_native_class(context);
+ GDScriptCompletionIdentifier gdi = _get_native_class(context);
if (gdi.obj_type != StringName()) {
bool valid;
Variant::Type t = ClassDB::get_property_type(gdi.obj_type, p_identifier, &valid);
@@ -1013,7 +1079,7 @@ static bool _guess_identifier_type_in_block(GDCompletionContext &context, int p_
}
}
- const GDParser::Node *last_assign = NULL;
+ const GDScriptParser::Node *last_assign = NULL;
int last_assign_line = -1;
for (int i = 0; i < context.block->statements.size(); i++) {
@@ -1021,9 +1087,9 @@ static bool _guess_identifier_type_in_block(GDCompletionContext &context, int p_
if (context.block->statements[i]->line > p_line)
continue;
- if (context.block->statements[i]->type == GDParser::BlockNode::TYPE_LOCAL_VAR) {
+ if (context.block->statements[i]->type == GDScriptParser::BlockNode::TYPE_LOCAL_VAR) {
- const GDParser::LocalVarNode *lv = static_cast<const GDParser::LocalVarNode *>(context.block->statements[i]);
+ const GDScriptParser::LocalVarNode *lv = static_cast<const GDScriptParser::LocalVarNode *>(context.block->statements[i]);
if (lv->assign && lv->name == p_identifier) {
@@ -1032,13 +1098,13 @@ static bool _guess_identifier_type_in_block(GDCompletionContext &context, int p_
}
}
- if (context.block->statements[i]->type == GDParser::BlockNode::TYPE_OPERATOR) {
- const GDParser::OperatorNode *op = static_cast<const GDParser::OperatorNode *>(context.block->statements[i]);
- if (op->op == GDParser::OperatorNode::OP_ASSIGN) {
+ if (context.block->statements[i]->type == GDScriptParser::BlockNode::TYPE_OPERATOR) {
+ const GDScriptParser::OperatorNode *op = static_cast<const GDScriptParser::OperatorNode *>(context.block->statements[i]);
+ if (op->op == GDScriptParser::OperatorNode::OP_ASSIGN) {
- if (op->arguments.size() && op->arguments[0]->type == GDParser::Node::TYPE_IDENTIFIER) {
+ if (op->arguments.size() && op->arguments[0]->type == GDScriptParser::Node::TYPE_IDENTIFIER) {
- const GDParser::IdentifierNode *id = static_cast<const GDParser::IdentifierNode *>(op->arguments[0]);
+ const GDScriptParser::IdentifierNode *id = static_cast<const GDScriptParser::IdentifierNode *>(op->arguments[0]);
if (id->name == p_identifier) {
@@ -1051,7 +1117,7 @@ static bool _guess_identifier_type_in_block(GDCompletionContext &context, int p_
}
//use the last assignment, (then backwards?)
- if (last_assign) {
+ if (last_assign && last_assign_line != p_line) {
return _guess_expression_type(context, last_assign, last_assign_line, r_type);
}
@@ -1059,9 +1125,9 @@ static bool _guess_identifier_type_in_block(GDCompletionContext &context, int p_
return false;
}
-static bool _guess_identifier_from_assignment_in_function(GDCompletionContext &context, int p_src_line, const StringName &p_identifier, const StringName &p_function, GDCompletionIdentifier &r_type) {
+static bool _guess_identifier_from_assignment_in_function(GDScriptCompletionContext &context, int p_src_line, const StringName &p_identifier, const StringName &p_function, GDScriptCompletionIdentifier &r_type) {
- const GDParser::FunctionNode *func = NULL;
+ const GDScriptParser::FunctionNode *func = NULL;
for (int i = 0; i < context._class->functions.size(); i++) {
if (context._class->functions[i]->name == p_function) {
func = context._class->functions[i];
@@ -1078,13 +1144,13 @@ static bool _guess_identifier_from_assignment_in_function(GDCompletionContext &c
break;
}
- if (func->body->statements[i]->type == GDParser::BlockNode::TYPE_OPERATOR) {
- const GDParser::OperatorNode *op = static_cast<const GDParser::OperatorNode *>(func->body->statements[i]);
- if (op->op == GDParser::OperatorNode::OP_ASSIGN) {
+ if (func->body->statements[i]->type == GDScriptParser::BlockNode::TYPE_OPERATOR) {
+ const GDScriptParser::OperatorNode *op = static_cast<const GDScriptParser::OperatorNode *>(func->body->statements[i]);
+ if (op->op == GDScriptParser::OperatorNode::OP_ASSIGN) {
- if (op->arguments.size() && op->arguments[0]->type == GDParser::Node::TYPE_IDENTIFIER) {
+ if (op->arguments.size() && op->arguments[0]->type == GDScriptParser::Node::TYPE_IDENTIFIER) {
- const GDParser::IdentifierNode *id = static_cast<const GDParser::IdentifierNode *>(op->arguments[0]);
+ const GDScriptParser::IdentifierNode *id = static_cast<const GDScriptParser::IdentifierNode *>(op->arguments[0]);
if (id->name == p_identifier) {
@@ -1098,15 +1164,15 @@ static bool _guess_identifier_from_assignment_in_function(GDCompletionContext &c
return false;
}
-static bool _guess_identifier_type(GDCompletionContext &context, int p_line, const StringName &p_identifier, GDCompletionIdentifier &r_type, bool p_for_indexing) {
+static bool _guess_identifier_type(GDScriptCompletionContext &context, int p_line, const StringName &p_identifier, GDScriptCompletionIdentifier &r_type, bool p_for_indexing) {
//go to block first
- const GDParser::BlockNode *block = context.block;
+ const GDScriptParser::BlockNode *block = context.block;
while (block) {
- GDCompletionContext c = context;
+ GDScriptCompletionContext c = context;
c.block = block;
if (_guess_identifier_type_in_block(c, p_line, p_identifier, r_type)) {
@@ -1130,7 +1196,7 @@ static bool _guess_identifier_type(GDCompletionContext &context, int p_line, con
}
if (argindex != -1) {
- GDCompletionIdentifier id = _get_native_class(context);
+ GDScriptCompletionIdentifier id = _get_native_class(context);
if (id.type == Variant::OBJECT && id.obj_type != StringName()) {
//this kinda sucks but meh
@@ -1168,8 +1234,8 @@ static bool _guess_identifier_type(GDCompletionContext &context, int p_line, con
if (context._class->constant_expressions[i].identifier == p_identifier) {
- ERR_FAIL_COND_V(context._class->constant_expressions[i].expression->type != GDParser::Node::TYPE_CONSTANT, false);
- r_type = _get_type_from_variant(static_cast<const GDParser::ConstantNode *>(context._class->constant_expressions[i].expression)->value);
+ ERR_FAIL_COND_V(context._class->constant_expressions[i].expression->type != GDScriptParser::Node::TYPE_CONSTANT, false);
+ r_type = _get_type_from_variant(static_cast<const GDScriptParser::ConstantNode *>(context._class->constant_expressions[i].expression)->value);
return true;
}
}
@@ -1185,6 +1251,8 @@ static bool _guess_identifier_type(GDCompletionContext &context, int p_line, con
r_type = _get_type_from_pinfo(context._class->variables[i]._export);
return true;
} else if (context._class->variables[i].expression) {
+ if (p_line <= context._class->variables[i].line)
+ return false;
bool rtype = _guess_expression_type(context, context._class->variables[i].expression, context._class->variables[i].line, r_type);
if (rtype && r_type.type != Variant::NIL)
@@ -1259,7 +1327,7 @@ static bool _guess_identifier_type(GDCompletionContext &context, int p_line, con
return false;
}
-static void _find_identifiers_in_block(GDCompletionContext &context, int p_line, bool p_only_functions, Set<String> &result) {
+static void _find_identifiers_in_block(GDScriptCompletionContext &context, int p_line, bool p_only_functions, Set<String> &result) {
if (p_only_functions)
return;
@@ -1269,15 +1337,15 @@ static void _find_identifiers_in_block(GDCompletionContext &context, int p_line,
if (context.block->statements[i]->line > p_line)
continue;
- if (context.block->statements[i]->type == GDParser::BlockNode::TYPE_LOCAL_VAR) {
+ if (context.block->statements[i]->type == GDScriptParser::BlockNode::TYPE_LOCAL_VAR) {
- const GDParser::LocalVarNode *lv = static_cast<const GDParser::LocalVarNode *>(context.block->statements[i]);
+ const GDScriptParser::LocalVarNode *lv = static_cast<const GDScriptParser::LocalVarNode *>(context.block->statements[i]);
result.insert(lv->name.operator String());
}
}
}
-static void _find_identifiers_in_class(GDCompletionContext &context, bool p_static, bool p_only_functions, Set<String> &result) {
+static void _find_identifiers_in_class(GDScriptCompletionContext &context, bool p_static, bool p_only_functions, Set<String> &result) {
if (!p_static && !p_only_functions) {
@@ -1320,7 +1388,7 @@ static void _find_identifiers_in_class(GDCompletionContext &context, bool p_stat
while (true) {
Ref<GDScript> script = base;
- Ref<GDNativeClass> nc = base;
+ Ref<GDScriptNativeClass> nc = base;
if (script.is_valid()) {
if (!p_static && !p_only_functions) {
@@ -1335,7 +1403,7 @@ static void _find_identifiers_in_class(GDCompletionContext &context, bool p_stat
}
}
- for (const Map<StringName, GDFunction *>::Element *E = script->get_member_functions().front(); E; E = E->next()) {
+ for (const Map<StringName, GDScriptFunction *>::Element *E = script->get_member_functions().front(); E; E = E->next()) {
if (!p_static || E->get()->is_static()) {
if (E->get()->get_argument_count())
result.insert(E->key().operator String() + "(");
@@ -1394,13 +1462,13 @@ static void _find_identifiers_in_class(GDCompletionContext &context, bool p_stat
}
}
-static void _find_identifiers(GDCompletionContext &context, int p_line, bool p_only_functions, Set<String> &result) {
+static void _find_identifiers(GDScriptCompletionContext &context, int p_line, bool p_only_functions, Set<String> &result) {
- const GDParser::BlockNode *block = context.block;
+ const GDScriptParser::BlockNode *block = context.block;
if (context.function) {
- const GDParser::FunctionNode *f = context.function;
+ const GDScriptParser::FunctionNode *f = context.function;
for (int i = 0; i < f->arguments.size(); i++) {
result.insert(f->arguments[i].operator String());
@@ -1409,19 +1477,19 @@ static void _find_identifiers(GDCompletionContext &context, int p_line, bool p_o
while (block) {
- GDCompletionContext c = context;
+ GDScriptCompletionContext c = context;
c.block = block;
_find_identifiers_in_block(c, p_line, p_only_functions, result);
block = block->parent_block;
}
- const GDParser::ClassNode *clss = context._class;
+ const GDScriptParser::ClassNode *clss = context._class;
bool _static = context.function && context.function->_static;
while (clss) {
- GDCompletionContext c = context;
+ GDScriptCompletionContext c = context;
c._class = clss;
c.block = NULL;
c.function = NULL;
@@ -1429,9 +1497,9 @@ static void _find_identifiers(GDCompletionContext &context, int p_line, bool p_o
clss = clss->owner;
}
- for (int i = 0; i < GDFunctions::FUNC_MAX; i++) {
+ for (int i = 0; i < GDScriptFunctions::FUNC_MAX; i++) {
- result.insert(GDFunctions::get_func_name(GDFunctions::Function(i)));
+ result.insert(GDScriptFunctions::get_func_name(GDScriptFunctions::Function(i)));
}
static const char *_type_names[Variant::VARIANT_MAX] = {
@@ -1485,7 +1553,7 @@ static String _get_visual_datatype(const PropertyInfo &p_info, bool p_isarg = tr
return Variant::get_type_name(p_info.type);
}
-static void _make_function_hint(const GDParser::FunctionNode *p_func, int p_argidx, String &arghint) {
+static void _make_function_hint(const GDScriptParser::FunctionNode *p_func, int p_argidx, String &arghint) {
arghint = "func " + p_func->name + "(";
for (int i = 0; i < p_func->arguments.size(); i++) {
@@ -1505,11 +1573,11 @@ static void _make_function_hint(const GDParser::FunctionNode *p_func, int p_argi
if (defidx >= 0 && defidx < p_func->default_values.size()) {
- if (p_func->default_values[defidx]->type == GDParser::Node::TYPE_OPERATOR) {
+ if (p_func->default_values[defidx]->type == GDScriptParser::Node::TYPE_OPERATOR) {
- const GDParser::OperatorNode *op = static_cast<const GDParser::OperatorNode *>(p_func->default_values[defidx]);
- if (op->op == GDParser::OperatorNode::OP_ASSIGN) {
- const GDParser::ConstantNode *cn = static_cast<const GDParser::ConstantNode *>(op->arguments[1]);
+ const GDScriptParser::OperatorNode *op = static_cast<const GDScriptParser::OperatorNode *>(p_func->default_values[defidx]);
+ if (op->op == GDScriptParser::OperatorNode::OP_ASSIGN) {
+ const GDScriptParser::ConstantNode *cn = static_cast<const GDScriptParser::ConstantNode *>(op->arguments[1]);
arghint += "=" + cn->value.get_construct_string();
}
} else {
@@ -1537,7 +1605,7 @@ void get_directory_contents(EditorFileSystemDirectory *p_dir, Set<String> &r_lis
}
}
-static void _find_type_arguments(GDCompletionContext &context, const GDParser::Node *p_node, int p_line, const StringName &p_method, const GDCompletionIdentifier &id, int p_argidx, Set<String> &result, bool &r_forced, String &arghint) {
+static void _find_type_arguments(GDScriptCompletionContext &context, const GDScriptParser::Node *p_node, int p_line, const StringName &p_method, const GDScriptCompletionIdentifier &id, int p_argidx, Set<String> &result, bool &r_forced, String &arghint) {
//print_line("find type arguments?");
if (id.type == Variant::OBJECT && id.obj_type != StringName()) {
@@ -1556,7 +1624,7 @@ static void _find_type_arguments(GDCompletionContext &context, const GDParser::N
if (scr) {
while (scr) {
- for (const Map<StringName, GDFunction *>::Element *E = scr->get_member_functions().front(); E; E = E->next()) {
+ for (const Map<StringName, GDScriptFunction *>::Element *E = scr->get_member_functions().front(); E; E = E->next()) {
if (E->get()->is_static() && p_method == E->get()->get_name()) {
arghint = "static func " + String(p_method) + "(";
for (int i = 0; i < E->get()->get_argument_count(); i++) {
@@ -1613,7 +1681,7 @@ static void _find_type_arguments(GDCompletionContext &context, const GDParser::N
if (code != "") {
//if there is code, parse it. This way is slower but updates in real-time
- GDParser p;
+ GDScriptParser p;
//Error parse(const String& p_code, const String& p_base_path="", bool p_just_validate=false,const String& p_self_path="",bool p_for_completion=false);
Error err = p.parse(scr->get_source_code(), scr->get_path().get_base_dir(), true, "", false);
@@ -1621,13 +1689,13 @@ static void _find_type_arguments(GDCompletionContext &context, const GDParser::N
if (err == OK) {
//print_line("checking the functions...");
//only if ok, otherwise use what is cached on the script
- //GDParser::ClassNode *base = p.
- const GDParser::Node *root = p.get_parse_tree();
- ERR_FAIL_COND(root->type != GDParser::Node::TYPE_CLASS);
+ //GDScriptParser::ClassNode *base = p.
+ const GDScriptParser::Node *root = p.get_parse_tree();
+ ERR_FAIL_COND(root->type != GDScriptParser::Node::TYPE_CLASS);
- const GDParser::ClassNode *cl = static_cast<const GDParser::ClassNode *>(root);
+ const GDScriptParser::ClassNode *cl = static_cast<const GDScriptParser::ClassNode *>(root);
- const GDParser::FunctionNode *func = NULL;
+ const GDScriptParser::FunctionNode *func = NULL;
bool st = false;
for (int i = 0; i < cl->functions.size(); i++) {
@@ -1665,10 +1733,10 @@ static void _find_type_arguments(GDCompletionContext &context, const GDParser::N
int defidx = deffrom - i;
- if (defidx >= 0 && defidx < func->default_values.size() && func->default_values[defidx]->type == GDParser::Node::TYPE_OPERATOR) {
- const GDParser::OperatorNode *op = static_cast<const GDParser::OperatorNode *>(func->default_values[defidx]);
- if (op->op == GDParser::OperatorNode::OP_ASSIGN) {
- const GDParser::ConstantNode *cn = static_cast<const GDParser::ConstantNode *>(op->arguments[1]);
+ if (defidx >= 0 && defidx < func->default_values.size() && func->default_values[defidx]->type == GDScriptParser::Node::TYPE_OPERATOR) {
+ const GDScriptParser::OperatorNode *op = static_cast<const GDScriptParser::OperatorNode *>(func->default_values[defidx]);
+ if (op->op == GDScriptParser::OperatorNode::OP_ASSIGN) {
+ const GDScriptParser::ConstantNode *cn = static_cast<const GDScriptParser::ConstantNode *>(op->arguments[1]);
arghint += "=" + cn->value.get_construct_string();
}
}
@@ -1689,7 +1757,7 @@ static void _find_type_arguments(GDCompletionContext &context, const GDParser::N
if (code == "") {
- for (const Map<StringName, GDFunction *>::Element *E = scr->get_member_functions().front(); E; E = E->next()) {
+ for (const Map<StringName, GDScriptFunction *>::Element *E = scr->get_member_functions().front(); E; E = E->next()) {
if (p_method == E->get()->get_name()) {
arghint = "func " + String(p_method) + "(";
for (int i = 0; i < E->get()->get_argument_count(); i++) {
@@ -1727,7 +1795,7 @@ static void _find_type_arguments(GDCompletionContext &context, const GDParser::N
}
} else {
-//regular method
+ //regular method
#if defined(DEBUG_METHODS_ENABLED) && defined(TOOLS_ENABLED)
if (p_argidx < m->get_argument_count()) {
@@ -1798,8 +1866,8 @@ static void _find_type_arguments(GDCompletionContext &context, const GDParser::N
}
/*if (p_argidx==2) {
- ERR_FAIL_COND(p_node->type!=GDParser::Node::TYPE_OPERATOR);
- const GDParser::OperatorNode *op=static_cast<const GDParser::OperatorNode *>(p_node);
+ ERR_FAIL_COND(p_node->type!=GDScriptParser::Node::TYPE_OPERATOR);
+ const GDScriptParser::OperatorNode *op=static_cast<const GDScriptParser::OperatorNode *>(p_node);
if (op->arguments.size()>)
}*/
@@ -1874,30 +1942,30 @@ static void _find_type_arguments(GDCompletionContext &context, const GDParser::N
}
}
-static void _find_call_arguments(GDCompletionContext &context, const GDParser::Node *p_node, int p_line, int p_argidx, Set<String> &result, bool &r_forced, String &arghint) {
+static void _find_call_arguments(GDScriptCompletionContext &context, const GDScriptParser::Node *p_node, int p_line, int p_argidx, Set<String> &result, bool &r_forced, String &arghint) {
- if (!p_node || p_node->type != GDParser::Node::TYPE_OPERATOR) {
+ if (!p_node || p_node->type != GDScriptParser::Node::TYPE_OPERATOR) {
return;
}
- const GDParser::OperatorNode *op = static_cast<const GDParser::OperatorNode *>(p_node);
+ const GDScriptParser::OperatorNode *op = static_cast<const GDScriptParser::OperatorNode *>(p_node);
- if (op->op != GDParser::OperatorNode::OP_CALL) {
+ if (op->op != GDScriptParser::OperatorNode::OP_CALL) {
return;
}
- if (op->arguments[0]->type == GDParser::Node::TYPE_BUILT_IN_FUNCTION) {
+ if (op->arguments[0]->type == GDScriptParser::Node::TYPE_BUILT_IN_FUNCTION) {
//complete built-in function
- const GDParser::BuiltInFunctionNode *fn = static_cast<const GDParser::BuiltInFunctionNode *>(op->arguments[0]);
- MethodInfo mi = GDFunctions::get_info(fn->function);
+ const GDScriptParser::BuiltInFunctionNode *fn = static_cast<const GDScriptParser::BuiltInFunctionNode *>(op->arguments[0]);
+ MethodInfo mi = GDScriptFunctions::get_info(fn->function);
if (mi.name == "load" && bool(EditorSettings::get_singleton()->get("text_editor/completion/complete_file_paths"))) {
get_directory_contents(EditorFileSystem::get_singleton()->get_filesystem(), result);
}
- arghint = _get_visual_datatype(mi.return_val, false) + " " + GDFunctions::get_func_name(fn->function) + String("(");
+ arghint = _get_visual_datatype(mi.return_val, false) + " " + GDScriptFunctions::get_func_name(fn->function) + String("(");
for (int i = 0; i < mi.arguments.size(); i++) {
if (i > 0)
arghint += ", ";
@@ -1915,9 +1983,9 @@ static void _find_call_arguments(GDCompletionContext &context, const GDParser::N
arghint += " ";
arghint += ")";
- } else if (op->arguments[0]->type == GDParser::Node::TYPE_TYPE) {
+ } else if (op->arguments[0]->type == GDScriptParser::Node::TYPE_TYPE) {
//complete constructor
- const GDParser::TypeNode *tn = static_cast<const GDParser::TypeNode *>(op->arguments[0]);
+ const GDScriptParser::TypeNode *tn = static_cast<const GDScriptParser::TypeNode *>(op->arguments[0]);
List<MethodInfo> mil;
Variant::get_constructor_list(tn->vtype, &mil);
@@ -1948,11 +2016,11 @@ static void _find_call_arguments(GDCompletionContext &context, const GDParser::N
arghint += ")";
}
- } else if (op->arguments.size() >= 2 && op->arguments[1]->type == GDParser::Node::TYPE_IDENTIFIER) {
+ } else if (op->arguments.size() >= 2 && op->arguments[1]->type == GDScriptParser::Node::TYPE_IDENTIFIER) {
//make sure identifier exists...
- const GDParser::IdentifierNode *id = static_cast<const GDParser::IdentifierNode *>(op->arguments[1]);
- if (op->arguments[0]->type == GDParser::Node::TYPE_SELF) {
+ const GDScriptParser::IdentifierNode *id = static_cast<const GDScriptParser::IdentifierNode *>(op->arguments[1]);
+ if (op->arguments[0]->type == GDScriptParser::Node::TYPE_SELF) {
//self, look up
for (int i = 0; i < context._class->static_functions.size(); i++) {
@@ -1977,10 +2045,10 @@ static void _find_call_arguments(GDCompletionContext &context, const GDParser::N
while (true) {
Ref<GDScript> script = base;
- Ref<GDNativeClass> nc = base;
+ Ref<GDScriptNativeClass> nc = base;
if (script.is_valid()) {
- for (const Map<StringName, GDFunction *>::Element *E = script->get_member_functions().front(); E; E = E->next()) {
+ for (const Map<StringName, GDScriptFunction *>::Element *E = script->get_member_functions().front(); E; E = E->next()) {
if (E->key() == id->name) {
@@ -2022,7 +2090,7 @@ static void _find_call_arguments(GDCompletionContext &context, const GDParser::N
if (!(context.function && context.function->_static)) {
- GDCompletionIdentifier ci;
+ GDScriptCompletionIdentifier ci;
ci.type = Variant::OBJECT;
ci.obj_type = nc->get_name();
if (!context._class->owner)
@@ -2047,7 +2115,7 @@ static void _find_call_arguments(GDCompletionContext &context, const GDParser::N
} else {
//indexed lookup
- GDCompletionIdentifier ci;
+ GDScriptCompletionIdentifier ci;
if (_guess_expression_type(context, op->arguments[0], p_line, ci)) {
_find_type_arguments(context, p_node, p_line, id->name, ci, p_argidx, result, r_forced, arghint);
@@ -2059,13 +2127,13 @@ static void _find_call_arguments(GDCompletionContext &context, const GDParser::N
Error GDScriptLanguage::complete_code(const String &p_code, const String &p_base_path, Object *p_owner, List<String> *r_options, bool &r_forced, String &r_call_hint) {
- GDParser p;
+ GDScriptParser p;
p.parse(p_code, p_base_path, false, "", true);
bool isfunction = false;
Set<String> options;
r_forced = false;
- GDCompletionContext context;
+ GDScriptCompletionContext context;
context._class = p.get_completion_class();
context.block = p.get_completion_block();
context.function = p.get_completion_function();
@@ -2074,9 +2142,9 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_base
switch (p.get_completion_type()) {
- case GDParser::COMPLETION_NONE: {
+ case GDScriptParser::COMPLETION_NONE: {
} break;
- case GDParser::COMPLETION_BUILT_IN_TYPE_CONSTANT: {
+ case GDScriptParser::COMPLETION_BUILT_IN_TYPE_CONSTANT: {
List<StringName> constants;
Variant::get_numeric_constants_for_type(p.get_completion_built_in_constant(), &constants);
for (List<StringName>::Element *E = constants.front(); E; E = E->next()) {
@@ -2084,16 +2152,16 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_base
}
} break;
- case GDParser::COMPLETION_FUNCTION:
+ case GDScriptParser::COMPLETION_FUNCTION:
isfunction = true;
- case GDParser::COMPLETION_IDENTIFIER: {
+ case GDScriptParser::COMPLETION_IDENTIFIER: {
_find_identifiers(context, p.get_completion_line(), isfunction, options);
} break;
- case GDParser::COMPLETION_PARENT_FUNCTION: {
+ case GDScriptParser::COMPLETION_PARENT_FUNCTION: {
} break;
- case GDParser::COMPLETION_GET_NODE: {
+ case GDScriptParser::COMPLETION_GET_NODE: {
if (p_owner) {
List<String> opts;
@@ -2102,9 +2170,9 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_base
for (List<String>::Element *E = opts.front(); E; E = E->next()) {
String opt = E->get().strip_edges();
- if (opt.begins_with("\"") && opt.ends_with("\"")) {
+ if (opt.is_quoted()) {
r_forced = true;
- String idopt = opt.substr(1, opt.length() - 2);
+ String idopt = opt.unquote();
if (idopt.replace("/", "_").is_valid_identifier()) {
options.insert(idopt);
} else {
@@ -2114,20 +2182,20 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_base
}
}
} break;
- case GDParser::COMPLETION_METHOD:
+ case GDScriptParser::COMPLETION_METHOD:
isfunction = true;
- case GDParser::COMPLETION_INDEX: {
+ case GDScriptParser::COMPLETION_INDEX: {
- const GDParser::Node *node = p.get_completion_node();
- if (node->type != GDParser::Node::TYPE_OPERATOR)
+ const GDScriptParser::Node *node = p.get_completion_node();
+ if (node->type != GDScriptParser::Node::TYPE_OPERATOR)
break;
- GDCompletionIdentifier t;
- if (_guess_expression_type(context, static_cast<const GDParser::OperatorNode *>(node)->arguments[0], p.get_completion_line(), t, true)) {
+ GDScriptCompletionIdentifier t;
+ if (_guess_expression_type(context, static_cast<const GDScriptParser::OperatorNode *>(node)->arguments[0], p.get_completion_line(), t, true)) {
- if (t.type == Variant::OBJECT && t.obj_type == "GDNativeClass") {
+ if (t.type == Variant::OBJECT && t.obj_type == "GDScriptNativeClass") {
//native enum
- Ref<GDNativeClass> gdn = t.value;
+ Ref<GDScriptNativeClass> gdn = t.value;
if (gdn.is_valid()) {
StringName cn = gdn->get_name();
List<String> cnames;
@@ -2163,7 +2231,7 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_base
options.insert(E->key());
}
}
- for (const Map<StringName, GDFunction *>::Element *E = scr->get_member_functions().front(); E; E = E->next()) {
+ for (const Map<StringName, GDScriptFunction *>::Element *E = scr->get_member_functions().front(); E; E = E->next()) {
if (E->get()->is_static())
options.insert(E->key());
}
@@ -2194,17 +2262,17 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_base
if (code != "") {
//if there is code, parse it. This way is slower but updates in real-time
- GDParser p;
+ GDScriptParser p;
Error err = p.parse(scr->get_source_code(), scr->get_path().get_base_dir(), true, "", false);
if (err == OK) {
//only if ok, otherwise use what is cached on the script
- //GDParser::ClassNode *base = p.
- const GDParser::Node *root = p.get_parse_tree();
- ERR_FAIL_COND_V(root->type != GDParser::Node::TYPE_CLASS, ERR_PARSE_ERROR);
+ //GDScriptParser::ClassNode *base = p.
+ const GDScriptParser::Node *root = p.get_parse_tree();
+ ERR_FAIL_COND_V(root->type != GDScriptParser::Node::TYPE_CLASS, ERR_PARSE_ERROR);
- const GDParser::ClassNode *cl = static_cast<const GDParser::ClassNode *>(root);
+ const GDScriptParser::ClassNode *cl = static_cast<const GDScriptParser::ClassNode *>(root);
for (int i = 0; i < cl->functions.size(); i++) {
@@ -2246,7 +2314,7 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_base
options.insert(E->key());
}
}
- for (const Map<StringName, GDFunction *>::Element *E = scr->get_member_functions().front(); E; E = E->next()) {
+ for (const Map<StringName, GDScriptFunction *>::Element *E = scr->get_member_functions().front(); E; E = E->next()) {
if (E->get()->get_argument_count())
options.insert(String(E->key()) + "()");
else
@@ -2325,13 +2393,13 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_base
}
} break;
- case GDParser::COMPLETION_CALL_ARGUMENTS: {
+ case GDScriptParser::COMPLETION_CALL_ARGUMENTS: {
_find_call_arguments(context, p.get_completion_node(), p.get_completion_line(), p.get_completion_argument_index(), options, r_forced, r_call_hint);
} break;
- case GDParser::COMPLETION_VIRTUAL_FUNC: {
+ case GDScriptParser::COMPLETION_VIRTUAL_FUNC: {
- GDCompletionIdentifier cid = _get_native_class(context);
+ GDScriptCompletionIdentifier cid = _get_native_class(context);
if (cid.obj_type != StringName()) {
List<MethodInfo> vm;
@@ -2360,11 +2428,11 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_base
}
}
} break;
- case GDParser::COMPLETION_YIELD: {
+ case GDScriptParser::COMPLETION_YIELD: {
- const GDParser::Node *node = p.get_completion_node();
+ const GDScriptParser::Node *node = p.get_completion_node();
- GDCompletionIdentifier t;
+ GDScriptCompletionIdentifier t;
if (!_guess_expression_type(context, node, p.get_completion_line(), t))
break;
@@ -2379,15 +2447,15 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_base
}
} break;
- case GDParser::COMPLETION_RESOURCE_PATH: {
+ case GDScriptParser::COMPLETION_RESOURCE_PATH: {
if (EditorSettings::get_singleton()->get("text_editor/completion/complete_file_paths"))
get_directory_contents(EditorFileSystem::get_singleton()->get_filesystem(), options);
} break;
- case GDParser::COMPLETION_ASSIGN: {
+ case GDScriptParser::COMPLETION_ASSIGN: {
#if defined(DEBUG_METHODS_ENABLED) && defined(TOOLS_ENABLED)
- GDCompletionIdentifier ci;
+ GDScriptCompletionIdentifier ci;
if (_guess_expression_type(context, p.get_completion_node(), p.get_completion_line(), ci)) {
String enumeration = ci.enumeration;
@@ -2540,8 +2608,8 @@ Error GDScriptLanguage::lookup_code(const String &p_code, const String &p_symbol
}
}
- for (int i = 0; i < GDFunctions::FUNC_MAX; i++) {
- if (GDFunctions::get_func_name(GDFunctions::Function(i)) == p_symbol) {
+ for (int i = 0; i < GDScriptFunctions::FUNC_MAX; i++) {
+ if (GDScriptFunctions::get_func_name(GDScriptFunctions::Function(i)) == p_symbol) {
r_result.type = ScriptLanguage::LookupResult::RESULT_CLASS_METHOD;
r_result.class_name = "@GDScript";
r_result.class_member = p_symbol;
@@ -2549,13 +2617,13 @@ Error GDScriptLanguage::lookup_code(const String &p_code, const String &p_symbol
}
}
- GDParser p;
+ GDScriptParser p;
p.parse(p_code, p_base_path, false, "", true);
- if (p.get_completion_type() == GDParser::COMPLETION_NONE)
+ if (p.get_completion_type() == GDScriptParser::COMPLETION_NONE)
return ERR_CANT_RESOLVE;
- GDCompletionContext context;
+ GDScriptCompletionContext context;
context._class = p.get_completion_class();
context.block = p.get_completion_block();
@@ -2566,10 +2634,10 @@ Error GDScriptLanguage::lookup_code(const String &p_code, const String &p_symbol
switch (p.get_completion_type()) {
- case GDParser::COMPLETION_GET_NODE:
- case GDParser::COMPLETION_NONE: {
+ case GDScriptParser::COMPLETION_GET_NODE:
+ case GDScriptParser::COMPLETION_NONE: {
} break;
- case GDParser::COMPLETION_BUILT_IN_TYPE_CONSTANT: {
+ case GDScriptParser::COMPLETION_BUILT_IN_TYPE_CONSTANT: {
r_result.type = ScriptLanguage::LookupResult::RESULT_CLASS_CONSTANT;
r_result.class_name = Variant::get_type_name(p.get_completion_built_in_constant());
@@ -2577,7 +2645,7 @@ Error GDScriptLanguage::lookup_code(const String &p_code, const String &p_symbol
return OK;
} break;
- case GDParser::COMPLETION_FUNCTION: {
+ case GDScriptParser::COMPLETION_FUNCTION: {
if (context._class && context._class->functions.size()) {
for (int i = 0; i < context._class->functions.size(); i++) {
@@ -2602,7 +2670,7 @@ Error GDScriptLanguage::lookup_code(const String &p_code, const String &p_symbol
parent = parent->get_base();
}
- GDCompletionIdentifier identifier = _get_native_class(context);
+ GDScriptCompletionIdentifier identifier = _get_native_class(context);
print_line("identifier: " + String(identifier.obj_type));
if (ClassDB::has_method(identifier.obj_type, p_symbol)) {
@@ -2614,7 +2682,7 @@ Error GDScriptLanguage::lookup_code(const String &p_code, const String &p_symbol
}
} break;
- case GDParser::COMPLETION_IDENTIFIER: {
+ case GDScriptParser::COMPLETION_IDENTIFIER: {
//check if a function
if (p.get_completion_identifier_is_function()) {
@@ -2641,7 +2709,7 @@ Error GDScriptLanguage::lookup_code(const String &p_code, const String &p_symbol
parent = parent->get_base();
}
- GDCompletionIdentifier identifier = _get_native_class(context);
+ GDScriptCompletionIdentifier identifier = _get_native_class(context);
if (ClassDB::has_method(identifier.obj_type, p_symbol)) {
@@ -2652,7 +2720,7 @@ Error GDScriptLanguage::lookup_code(const String &p_code, const String &p_symbol
}
} else {
- GDCompletionIdentifier gdi = _get_native_class(context);
+ GDScriptCompletionIdentifier gdi = _get_native_class(context);
if (gdi.obj_type != StringName()) {
bool valid;
Variant::Type t = ClassDB::get_property_type(gdi.obj_type, p_symbol, &valid);
@@ -2664,7 +2732,7 @@ Error GDScriptLanguage::lookup_code(const String &p_code, const String &p_symbol
}
}
- const GDParser::BlockNode *block = context.block;
+ const GDScriptParser::BlockNode *block = context.block;
//search in blocks going up (local var?)
while (block) {
@@ -2673,9 +2741,9 @@ Error GDScriptLanguage::lookup_code(const String &p_code, const String &p_symbol
if (block->statements[i]->line > p.get_completion_line())
continue;
- if (block->statements[i]->type == GDParser::BlockNode::TYPE_LOCAL_VAR) {
+ if (block->statements[i]->type == GDScriptParser::BlockNode::TYPE_LOCAL_VAR) {
- const GDParser::LocalVarNode *lv = static_cast<const GDParser::LocalVarNode *>(block->statements[i]);
+ const GDScriptParser::LocalVarNode *lv = static_cast<const GDScriptParser::LocalVarNode *>(block->statements[i]);
if (lv->assign && lv->name == p_symbol) {
@@ -2760,53 +2828,53 @@ Error GDScriptLanguage::lookup_code(const String &p_code, const String &p_symbol
}
//global
- for (Map<StringName, int>::Element *E = GDScriptLanguage::get_singleton()->get_global_map().front(); E; E = E->next()) {
- if (E->key() == p_symbol) {
-
- Variant value = GDScriptLanguage::get_singleton()->get_global_array()[E->get()];
- if (value.get_type() == Variant::OBJECT) {
- Object *obj = value;
- if (obj) {
-
- if (Object::cast_to<GDNativeClass>(obj)) {
- r_result.type = ScriptLanguage::LookupResult::RESULT_CLASS;
- r_result.class_name = Object::cast_to<GDNativeClass>(obj)->get_name();
-
- } else {
- r_result.type = ScriptLanguage::LookupResult::RESULT_CLASS;
- r_result.class_name = obj->get_class();
- }
- return OK;
+ Map<StringName, int> classes = GDScriptLanguage::get_singleton()->get_global_map();
+ if (classes.has(p_symbol)) {
+ Variant value = GDScriptLanguage::get_singleton()->get_global_array()[classes[p_symbol]];
+ if (value.get_type() == Variant::OBJECT) {
+ Object *obj = value;
+ if (obj) {
+ if (Object::cast_to<GDScriptNativeClass>(obj)) {
+ r_result.type = ScriptLanguage::LookupResult::RESULT_CLASS;
+ r_result.class_name = Object::cast_to<GDScriptNativeClass>(obj)->get_name();
+ } else {
+ r_result.type = ScriptLanguage::LookupResult::RESULT_CLASS;
+ r_result.class_name = obj->get_class();
}
- } else {
- r_result.type = ScriptLanguage::LookupResult::RESULT_CLASS_CONSTANT;
- r_result.class_name = "@Global Scope";
- r_result.class_member = p_symbol;
+ // proxy class remove the underscore.
+ if (r_result.class_name.begins_with("_")) {
+ r_result.class_name = r_result.class_name.right(1);
+ }
return OK;
}
+ } else {
+ r_result.type = ScriptLanguage::LookupResult::RESULT_CLASS_CONSTANT;
+ r_result.class_name = "@GlobalScope";
+ r_result.class_member = p_symbol;
+ return OK;
}
}
}
} break;
- case GDParser::COMPLETION_PARENT_FUNCTION: {
+ case GDScriptParser::COMPLETION_PARENT_FUNCTION: {
} break;
- case GDParser::COMPLETION_METHOD:
+ case GDScriptParser::COMPLETION_METHOD:
isfunction = true;
- case GDParser::COMPLETION_INDEX: {
+ case GDScriptParser::COMPLETION_INDEX: {
- const GDParser::Node *node = p.get_completion_node();
- if (node->type != GDParser::Node::TYPE_OPERATOR)
+ const GDScriptParser::Node *node = p.get_completion_node();
+ if (node->type != GDScriptParser::Node::TYPE_OPERATOR)
break;
- GDCompletionIdentifier t;
- if (_guess_expression_type(context, static_cast<const GDParser::OperatorNode *>(node)->arguments[0], p.get_completion_line(), t)) {
+ GDScriptCompletionIdentifier t;
+ if (_guess_expression_type(context, static_cast<const GDScriptParser::OperatorNode *>(node)->arguments[0], p.get_completion_line(), t)) {
- if (t.type == Variant::OBJECT && t.obj_type == "GDNativeClass") {
+ if (t.type == Variant::OBJECT && t.obj_type == "GDScriptNativeClass") {
//native enum
- Ref<GDNativeClass> gdn = t.value;
+ Ref<GDScriptNativeClass> gdn = t.value;
if (gdn.is_valid()) {
r_result.type = ScriptLanguage::LookupResult::RESULT_CLASS_CONSTANT;
r_result.class_name = gdn->get_name();
@@ -2898,13 +2966,13 @@ Error GDScriptLanguage::lookup_code(const String &p_code, const String &p_symbol
}
} break;
- case GDParser::COMPLETION_CALL_ARGUMENTS: {
+ case GDScriptParser::COMPLETION_CALL_ARGUMENTS: {
return ERR_CANT_RESOLVE;
} break;
- case GDParser::COMPLETION_VIRTUAL_FUNC: {
+ case GDScriptParser::COMPLETION_VIRTUAL_FUNC: {
- GDCompletionIdentifier cid = _get_native_class(context);
+ GDScriptCompletionIdentifier cid = _get_native_class(context);
if (cid.obj_type != StringName()) {
List<MethodInfo> vm;
@@ -2921,7 +2989,7 @@ Error GDScriptLanguage::lookup_code(const String &p_code, const String &p_symbol
}
}
} break;
- case GDParser::COMPLETION_YIELD: {
+ case GDScriptParser::COMPLETION_YIELD: {
return ERR_CANT_RESOLVE;
diff --git a/modules/gdscript/gd_function.cpp b/modules/gdscript/gdscript_function.cpp
index ce503b62f2..765a76fec4 100644
--- a/modules/gdscript/gd_function.cpp
+++ b/modules/gdscript/gdscript_function.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* gd_function.cpp */
+/* gdscript_function.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -27,13 +27,13 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "gd_function.h"
+#include "gdscript_function.h"
-#include "gd_functions.h"
-#include "gd_script.h"
+#include "gdscript.h"
+#include "gdscript_functions.h"
#include "os/os.h"
-Variant *GDFunction::_get_variant(int p_address, GDInstance *p_instance, GDScript *p_script, Variant &self, Variant *p_stack, String &r_error) const {
+Variant *GDScriptFunction::_get_variant(int p_address, GDScriptInstance *p_instance, GDScript *p_script, Variant &self, Variant *p_stack, String &r_error) const {
int address = p_address & ADDR_MASK;
@@ -85,7 +85,7 @@ Variant *GDFunction::_get_variant(int p_address, GDInstance *p_instance, GDScrip
o = o->_owner;
}
- ERR_EXPLAIN("GDCompiler bug..");
+ ERR_EXPLAIN("GDScriptCompiler bug..");
ERR_FAIL_V(NULL);
} break;
case ADDR_TYPE_LOCAL_CONSTANT: {
@@ -117,7 +117,7 @@ Variant *GDFunction::_get_variant(int p_address, GDInstance *p_instance, GDScrip
return NULL;
}
-String GDFunction::_get_call_error(const Variant::CallError &p_err, const String &p_where, const Variant **argptrs) const {
+String GDScriptFunction::_get_call_error(const Variant::CallError &p_err, const String &p_where, const Variant **argptrs) const {
String err_text;
@@ -170,7 +170,7 @@ static String _get_var_type(const Variant *p_type) {
return basestr;
}
-#if defined(__GNUC__) && !defined(__clang__)
+#if defined(__GNUC__)
#define OPCODES_TABLE \
static const void *switch_table_ops[] = { \
&&OPCODE_OPERATOR, \
@@ -231,7 +231,7 @@ static String _get_var_type(const Variant *p_type) {
#define OPCODE_OUT break
#endif
-Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_argcount, Variant::CallError &r_err, CallState *p_state) {
+Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_args, int p_argcount, Variant::CallError &r_err, CallState *p_state) {
OPCODES_TABLE;
@@ -427,8 +427,9 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
*dst = ret;
#endif
ip += 5;
- DISPATCH_OPCODE;
}
+ DISPATCH_OPCODE;
+
OPCODE(OPCODE_EXTENDS_TEST) {
CHECK_SPACE(4);
@@ -478,7 +479,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
} else {
- GDNativeClass *nc = Object::cast_to<GDNativeClass>(obj_B);
+ GDScriptNativeClass *nc = Object::cast_to<GDScriptNativeClass>(obj_B);
#ifdef DEBUG_ENABLED
if (!nc) {
@@ -492,8 +493,9 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
*dst = extends_ok;
ip += 4;
- DISPATCH_OPCODE;
}
+ DISPATCH_OPCODE;
+
OPCODE(OPCODE_SET) {
CHECK_SPACE(3);
@@ -518,8 +520,9 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
}
#endif
ip += 4;
- DISPATCH_OPCODE;
}
+ DISPATCH_OPCODE;
+
OPCODE(OPCODE_GET) {
CHECK_SPACE(3);
@@ -550,8 +553,9 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
*dst = ret;
#endif
ip += 4;
- DISPATCH_OPCODE;
}
+ DISPATCH_OPCODE;
+
OPCODE(OPCODE_SET_NAMED) {
CHECK_SPACE(3);
@@ -575,8 +579,9 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
}
#endif
ip += 4;
- DISPATCH_OPCODE;
}
+ DISPATCH_OPCODE;
+
OPCODE(OPCODE_GET_NAMED) {
CHECK_SPACE(4);
@@ -609,8 +614,9 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
*dst = ret;
#endif
ip += 4;
- DISPATCH_OPCODE;
}
+ DISPATCH_OPCODE;
+
OPCODE(OPCODE_SET_MEMBER) {
CHECK_SPACE(3);
@@ -631,8 +637,9 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
}
#endif
ip += 3;
- DISPATCH_OPCODE;
}
+ DISPATCH_OPCODE;
+
OPCODE(OPCODE_GET_MEMBER) {
CHECK_SPACE(3);
@@ -649,8 +656,9 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
}
#endif
ip += 3;
- DISPATCH_OPCODE;
}
+ DISPATCH_OPCODE;
+
OPCODE(OPCODE_ASSIGN) {
CHECK_SPACE(3);
@@ -660,8 +668,9 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
*dst = *src;
ip += 3;
- DISPATCH_OPCODE;
}
+ DISPATCH_OPCODE;
+
OPCODE(OPCODE_ASSIGN_TRUE) {
CHECK_SPACE(2);
@@ -670,8 +679,9 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
*dst = true;
ip += 2;
- DISPATCH_OPCODE;
}
+ DISPATCH_OPCODE;
+
OPCODE(OPCODE_ASSIGN_FALSE) {
CHECK_SPACE(2);
@@ -680,8 +690,9 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
*dst = false;
ip += 2;
- DISPATCH_OPCODE;
}
+ DISPATCH_OPCODE;
+
OPCODE(OPCODE_CONSTRUCT) {
CHECK_SPACE(2);
@@ -708,8 +719,9 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
ip += 4 + argc;
//construct a basic type
- DISPATCH_OPCODE;
}
+ DISPATCH_OPCODE;
+
OPCODE(OPCODE_CONSTRUCT_ARRAY) {
CHECK_SPACE(1);
@@ -728,8 +740,9 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
*dst = array;
ip += 3 + argc;
- DISPATCH_OPCODE;
}
+ DISPATCH_OPCODE;
+
OPCODE(OPCODE_CONSTRUCT_DICTIONARY) {
CHECK_SPACE(1);
@@ -750,8 +763,9 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
*dst = dict;
ip += 3 + argc * 2;
- DISPATCH_OPCODE;
}
+ DISPATCH_OPCODE;
+
OPCODE(OPCODE_CALL_RETURN)
OPCODE(OPCODE_CALL) {
@@ -830,13 +844,14 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
//_call_func(NULL,base,*methodname,ip,argc,p_instance,stack);
ip += argc + 1;
- DISPATCH_OPCODE;
}
+ DISPATCH_OPCODE;
+
OPCODE(OPCODE_CALL_BUILT_IN) {
CHECK_SPACE(4);
- GDFunctions::Function func = GDFunctions::Function(_code_ptr[ip + 1]);
+ GDScriptFunctions::Function func = GDScriptFunctions::Function(_code_ptr[ip + 1]);
int argc = _code_ptr[ip + 2];
GD_ERR_BREAK(argc < 0);
@@ -853,12 +868,12 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
Variant::CallError err;
- GDFunctions::call(func, (const Variant **)argptrs, argc, *dst, err);
+ GDScriptFunctions::call(func, (const Variant **)argptrs, argc, *dst, err);
#ifdef DEBUG_ENABLED
if (err.error != Variant::CallError::CALL_OK) {
- String methodstr = GDFunctions::get_func_name(func);
+ String methodstr = GDScriptFunctions::get_func_name(func);
if (dst->get_type() == Variant::STRING) {
//call provided error string
err_text = "Error calling built-in function '" + methodstr + "': " + String(*dst);
@@ -869,12 +884,14 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
}
#endif
ip += argc + 1;
- DISPATCH_OPCODE;
}
+ DISPATCH_OPCODE;
+
OPCODE(OPCODE_CALL_SELF) {
OPCODE_BREAK;
}
+
OPCODE(OPCODE_CALL_SELF_BASE) {
CHECK_SPACE(2);
@@ -904,7 +921,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
const GDScript *gds = _script;
- const Map<StringName, GDFunction *>::Element *E = NULL;
+ const Map<StringName, GDScriptFunction *>::Element *E = NULL;
while (gds->base.ptr()) {
gds = gds->base.ptr();
E = gds->member_functions.find(*methodname);
@@ -948,8 +965,9 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
}
ip += 4 + argc;
- DISPATCH_OPCODE;
}
+ DISPATCH_OPCODE;
+
OPCODE(OPCODE_YIELD)
OPCODE(OPCODE_YIELD_SIGNAL) {
@@ -961,7 +979,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
CHECK_SPACE(2);
}
- Ref<GDFunctionState> gdfs = memnew(GDFunctionState);
+ Ref<GDScriptFunctionState> gdfs = memnew(GDScriptFunctionState);
gdfs->function = this;
gdfs->state.stack.resize(alloca_size);
@@ -1032,6 +1050,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
exit_ok = true;
OPCODE_BREAK;
}
+
OPCODE(OPCODE_YIELD_RESUME) {
CHECK_SPACE(2);
@@ -1044,8 +1063,9 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
GET_VARIANT_PTR(result, 1);
*result = p_state->result;
ip += 2;
- DISPATCH_OPCODE;
}
+ DISPATCH_OPCODE;
+
OPCODE(OPCODE_JUMP) {
CHECK_SPACE(2);
@@ -1053,8 +1073,9 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
GD_ERR_BREAK(to < 0 || to > _code_size);
ip = to;
- DISPATCH_OPCODE;
}
+ DISPATCH_OPCODE;
+
OPCODE(OPCODE_JUMP_IF) {
CHECK_SPACE(3);
@@ -1067,11 +1088,12 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
int to = _code_ptr[ip + 2];
GD_ERR_BREAK(to < 0 || to > _code_size);
ip = to;
- DISPATCH_OPCODE;
+ } else {
+ ip += 3;
}
- ip += 3;
- DISPATCH_OPCODE;
}
+ DISPATCH_OPCODE;
+
OPCODE(OPCODE_JUMP_IF_NOT) {
CHECK_SPACE(3);
@@ -1084,17 +1106,19 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
int to = _code_ptr[ip + 2];
GD_ERR_BREAK(to < 0 || to > _code_size);
ip = to;
- DISPATCH_OPCODE;
+ } else {
+ ip += 3;
}
- ip += 3;
- DISPATCH_OPCODE;
}
+ DISPATCH_OPCODE;
+
OPCODE(OPCODE_JUMP_TO_DEF_ARGUMENT) {
CHECK_SPACE(2);
ip = _default_arg_ptr[defarg];
- DISPATCH_OPCODE;
}
+ DISPATCH_OPCODE;
+
OPCODE(OPCODE_RETURN) {
CHECK_SPACE(2);
@@ -1103,6 +1127,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
exit_ok = true;
OPCODE_BREAK;
}
+
OPCODE(OPCODE_ITERATE_BEGIN) {
CHECK_SPACE(8); //space for this a regular iterate
@@ -1121,20 +1146,21 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
int jumpto = _code_ptr[ip + 3];
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
ip = jumpto;
- DISPATCH_OPCODE;
- }
- GET_VARIANT_PTR(iterator, 4);
+ } else {
+ GET_VARIANT_PTR(iterator, 4);
- *iterator = container->iter_get(*counter, valid);
+ *iterator = container->iter_get(*counter, valid);
#ifdef DEBUG_ENABLED
- if (!valid) {
- err_text = "Unable to obtain iterator object of type " + Variant::get_type_name(container->get_type()) + "'.";
- OPCODE_BREAK;
- }
+ if (!valid) {
+ err_text = "Unable to obtain iterator object of type " + Variant::get_type_name(container->get_type()) + "'.";
+ OPCODE_BREAK;
+ }
#endif
- ip += 5; //skip regular iterate which is always next
- DISPATCH_OPCODE;
+ ip += 5; //skip regular iterate which is always next
+ }
}
+ DISPATCH_OPCODE;
+
OPCODE(OPCODE_ITERATE) {
CHECK_SPACE(4);
@@ -1153,20 +1179,21 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
int jumpto = _code_ptr[ip + 3];
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
ip = jumpto;
- DISPATCH_OPCODE;
- }
- GET_VARIANT_PTR(iterator, 4);
+ } else {
+ GET_VARIANT_PTR(iterator, 4);
- *iterator = container->iter_get(*counter, valid);
+ *iterator = container->iter_get(*counter, valid);
#ifdef DEBUG_ENABLED
- if (!valid) {
- err_text = "Unable to obtain iterator object of type " + Variant::get_type_name(container->get_type()) + "' (but was obtained on first iteration?).";
- OPCODE_BREAK;
- }
+ if (!valid) {
+ err_text = "Unable to obtain iterator object of type " + Variant::get_type_name(container->get_type()) + "' (but was obtained on first iteration?).";
+ OPCODE_BREAK;
+ }
#endif
- ip += 5; //loop again
- DISPATCH_OPCODE;
+ ip += 5; //loop again
+ }
}
+ DISPATCH_OPCODE;
+
OPCODE(OPCODE_ASSERT) {
CHECK_SPACE(2);
GET_VARIANT_PTR(test, 1);
@@ -1182,8 +1209,9 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
#endif
ip += 2;
- DISPATCH_OPCODE;
}
+ DISPATCH_OPCODE;
+
OPCODE(OPCODE_BREAKPOINT) {
#ifdef DEBUG_ENABLED
if (ScriptDebugger::get_singleton()) {
@@ -1191,8 +1219,9 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
}
#endif
ip += 1;
- DISPATCH_OPCODE;
}
+ DISPATCH_OPCODE;
+
OPCODE(OPCODE_LINE) {
CHECK_SPACE(2);
@@ -1220,8 +1249,9 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
ScriptDebugger::get_singleton()->line_poll();
}
- DISPATCH_OPCODE;
}
+ DISPATCH_OPCODE;
+
OPCODE(OPCODE_END) {
exit_ok = true;
@@ -1291,43 +1321,43 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
return retvalue;
}
-const int *GDFunction::get_code() const {
+const int *GDScriptFunction::get_code() const {
return _code_ptr;
}
-int GDFunction::get_code_size() const {
+int GDScriptFunction::get_code_size() const {
return _code_size;
}
-Variant GDFunction::get_constant(int p_idx) const {
+Variant GDScriptFunction::get_constant(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx, constants.size(), "<errconst>");
return constants[p_idx];
}
-StringName GDFunction::get_global_name(int p_idx) const {
+StringName GDScriptFunction::get_global_name(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx, global_names.size(), "<errgname>");
return global_names[p_idx];
}
-int GDFunction::get_default_argument_count() const {
+int GDScriptFunction::get_default_argument_count() const {
return default_arguments.size();
}
-int GDFunction::get_default_argument_addr(int p_idx) const {
+int GDScriptFunction::get_default_argument_addr(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx, default_arguments.size(), -1);
return default_arguments[p_idx];
}
-StringName GDFunction::get_name() const {
+StringName GDScriptFunction::get_name() const {
return name;
}
-int GDFunction::get_max_stack_size() const {
+int GDScriptFunction::get_max_stack_size() const {
return _stack_size;
}
@@ -1350,7 +1380,7 @@ struct _GDFKCS {
}
};
-void GDFunction::debug_get_stack_member_state(int p_line, List<Pair<StringName, int> > *r_stackvars) const {
+void GDScriptFunction::debug_get_stack_member_state(int p_line, List<Pair<StringName, int> > *r_stackvars) const {
int oc = 0;
Map<StringName, _GDFKC> sdmap;
@@ -1402,7 +1432,7 @@ void GDFunction::debug_get_stack_member_state(int p_line, List<Pair<StringName,
}
}
-GDFunction::GDFunction()
+GDScriptFunction::GDScriptFunction()
: function_list(this) {
_stack_size = 0;
@@ -1434,7 +1464,7 @@ GDFunction::GDFunction()
#endif
}
-GDFunction::~GDFunction() {
+GDScriptFunction::~GDScriptFunction() {
#ifdef DEBUG_ENABLED
if (GDScriptLanguage::get_singleton()->lock) {
GDScriptLanguage::get_singleton()->lock->lock();
@@ -1449,7 +1479,7 @@ GDFunction::~GDFunction() {
/////////////////////
-Variant GDFunctionState::_signal_callback(const Variant **p_args, int p_argcount, Variant::CallError &r_error) {
+Variant GDScriptFunctionState::_signal_callback(const Variant **p_args, int p_argcount, Variant::CallError &r_error) {
#ifdef DEBUG_ENABLED
if (state.instance_id && !ObjectDB::get_instance(state.instance_id)) {
@@ -1484,7 +1514,7 @@ Variant GDFunctionState::_signal_callback(const Variant **p_args, int p_argcount
arg = extra_args;
}
- Ref<GDFunctionState> self = *p_args[p_argcount - 1];
+ Ref<GDScriptFunctionState> self = *p_args[p_argcount - 1];
if (self.is_null()) {
r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
@@ -1498,10 +1528,10 @@ Variant GDFunctionState::_signal_callback(const Variant **p_args, int p_argcount
bool completed = true;
- // If the return value is a GDFunctionState reference,
+ // If the return value is a GDScriptFunctionState reference,
// then the function did yield again after resuming.
if (ret.is_ref()) {
- GDFunctionState *gdfs = Object::cast_to<GDFunctionState>(ret);
+ GDScriptFunctionState *gdfs = Object::cast_to<GDScriptFunctionState>(ret);
if (gdfs && gdfs->function == function)
completed = false;
}
@@ -1516,7 +1546,7 @@ Variant GDFunctionState::_signal_callback(const Variant **p_args, int p_argcount
return ret;
}
-bool GDFunctionState::is_valid(bool p_extended_check) const {
+bool GDScriptFunctionState::is_valid(bool p_extended_check) const {
if (function == NULL)
return false;
@@ -1533,7 +1563,7 @@ bool GDFunctionState::is_valid(bool p_extended_check) const {
return true;
}
-Variant GDFunctionState::resume(const Variant &p_arg) {
+Variant GDScriptFunctionState::resume(const Variant &p_arg) {
ERR_FAIL_COND_V(!function, Variant());
#ifdef DEBUG_ENABLED
@@ -1554,10 +1584,10 @@ Variant GDFunctionState::resume(const Variant &p_arg) {
bool completed = true;
- // If the return value is a GDFunctionState reference,
+ // If the return value is a GDScriptFunctionState reference,
// then the function did yield again after resuming.
if (ret.is_ref()) {
- GDFunctionState *gdfs = Object::cast_to<GDFunctionState>(ret);
+ GDScriptFunctionState *gdfs = Object::cast_to<GDScriptFunctionState>(ret);
if (gdfs && gdfs->function == function)
completed = false;
}
@@ -1572,21 +1602,21 @@ Variant GDFunctionState::resume(const Variant &p_arg) {
return ret;
}
-void GDFunctionState::_bind_methods() {
+void GDScriptFunctionState::_bind_methods() {
- ClassDB::bind_method(D_METHOD("resume", "arg"), &GDFunctionState::resume, DEFVAL(Variant()));
- ClassDB::bind_method(D_METHOD("is_valid", "extended_check"), &GDFunctionState::is_valid, DEFVAL(false));
- ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "_signal_callback", &GDFunctionState::_signal_callback, MethodInfo("_signal_callback"));
+ ClassDB::bind_method(D_METHOD("resume", "arg"), &GDScriptFunctionState::resume, DEFVAL(Variant()));
+ ClassDB::bind_method(D_METHOD("is_valid", "extended_check"), &GDScriptFunctionState::is_valid, DEFVAL(false));
+ ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "_signal_callback", &GDScriptFunctionState::_signal_callback, MethodInfo("_signal_callback"));
ADD_SIGNAL(MethodInfo("completed", PropertyInfo(Variant::NIL, "result", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT)));
}
-GDFunctionState::GDFunctionState() {
+GDScriptFunctionState::GDScriptFunctionState() {
function = NULL;
}
-GDFunctionState::~GDFunctionState() {
+GDScriptFunctionState::~GDScriptFunctionState() {
if (function != NULL) {
//never called, deinitialize stack
diff --git a/modules/gdscript/gd_function.h b/modules/gdscript/gdscript_function.h
index bf5ff5f8da..03fd5d52dc 100644
--- a/modules/gdscript/gd_function.h
+++ b/modules/gdscript/gdscript_function.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* gd_function.h */
+/* gdscript_function.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -27,8 +27,8 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef GD_FUNCTION_H
-#define GD_FUNCTION_H
+#ifndef GDSCRIPT_FUNCTION_H
+#define GDSCRIPT_FUNCTION_H
#include "os/thread.h"
#include "pair.h"
@@ -38,10 +38,10 @@
#include "string_db.h"
#include "variant.h"
-class GDInstance;
+class GDScriptInstance;
class GDScript;
-class GDFunction {
+class GDScriptFunction {
public:
enum Opcode {
OPCODE_OPERATOR,
@@ -111,7 +111,7 @@ public:
};
private:
- friend class GDCompiler;
+ friend class GDScriptCompiler;
StringName source;
@@ -145,12 +145,12 @@ private:
List<StackDebug> stack_debug;
- _FORCE_INLINE_ Variant *_get_variant(int p_address, GDInstance *p_instance, GDScript *p_script, Variant &self, Variant *p_stack, String &r_error) const;
+ _FORCE_INLINE_ Variant *_get_variant(int p_address, GDScriptInstance *p_instance, GDScript *p_script, Variant &self, Variant *p_stack, String &r_error) const;
_FORCE_INLINE_ String _get_call_error(const Variant::CallError &p_err, const String &p_where, const Variant **argptrs) const;
friend class GDScriptLanguage;
- SelfList<GDFunction> function_list;
+ SelfList<GDScriptFunction> function_list;
#ifdef DEBUG_ENABLED
CharString func_cname;
const char *_func_cname;
@@ -176,7 +176,7 @@ public:
ObjectID instance_id; //by debug only
ObjectID script_id;
- GDInstance *instance;
+ GDScriptInstance *instance;
Vector<uint8_t> stack;
int stack_size;
Variant self;
@@ -219,19 +219,19 @@ public:
return default_arguments[p_idx];
}
- Variant call(GDInstance *p_instance, const Variant **p_args, int p_argcount, Variant::CallError &r_err, CallState *p_state = NULL);
+ Variant call(GDScriptInstance *p_instance, const Variant **p_args, int p_argcount, Variant::CallError &r_err, CallState *p_state = NULL);
_FORCE_INLINE_ ScriptInstance::RPCMode get_rpc_mode() const { return rpc_mode; }
- GDFunction();
- ~GDFunction();
+ GDScriptFunction();
+ ~GDScriptFunction();
};
-class GDFunctionState : public Reference {
+class GDScriptFunctionState : public Reference {
- GDCLASS(GDFunctionState, Reference);
- friend class GDFunction;
- GDFunction *function;
- GDFunction::CallState state;
+ GDCLASS(GDScriptFunctionState, Reference);
+ friend class GDScriptFunction;
+ GDScriptFunction *function;
+ GDScriptFunction::CallState state;
Variant _signal_callback(const Variant **p_args, int p_argcount, Variant::CallError &r_error);
protected:
@@ -240,8 +240,8 @@ protected:
public:
bool is_valid(bool p_extended_check = false) const;
Variant resume(const Variant &p_arg = Variant());
- GDFunctionState();
- ~GDFunctionState();
+ GDScriptFunctionState();
+ ~GDScriptFunctionState();
};
-#endif // GD_FUNCTION_H
+#endif // GDSCRIPT_FUNCTION_H
diff --git a/modules/gdscript/gd_functions.cpp b/modules/gdscript/gdscript_functions.cpp
index 34d01c6beb..ca0a9582a7 100644
--- a/modules/gdscript/gd_functions.cpp
+++ b/modules/gdscript/gdscript_functions.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* gd_functions.cpp */
+/* gdscript_functions.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -27,10 +27,11 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "gd_functions.h"
+#include "gdscript_functions.h"
+
#include "class_db.h"
#include "func_ref.h"
-#include "gd_script.h"
+#include "gdscript.h"
#include "io/json.h"
#include "io/marshalls.h"
#include "math_funcs.h"
@@ -38,7 +39,7 @@
#include "reference.h"
#include "variant_parser.h"
-const char *GDFunctions::get_func_name(Function p_func) {
+const char *GDScriptFunctions::get_func_name(Function p_func) {
ERR_FAIL_INDEX_V(p_func, FUNC_MAX, "");
@@ -83,6 +84,10 @@ const char *GDFunctions::get_func_name(Function p_func) {
"rad2deg",
"linear2db",
"db2linear",
+ "polar2cartesian",
+ "cartesian2polar",
+ "wrapi",
+ "wrapf",
"max",
"min",
"clamp",
@@ -121,7 +126,7 @@ const char *GDFunctions::get_func_name(Function p_func) {
return _names[p_func];
}
-void GDFunctions::call(Function p_func, const Variant **p_args, int p_arg_count, Variant &r_ret, Variant::CallError &r_error) {
+void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_count, Variant &r_ret, Variant::CallError &r_error) {
r_error.error = Variant::CallError::CALL_OK;
#ifdef DEBUG_ENABLED
@@ -405,6 +410,30 @@ void GDFunctions::call(Function p_func, const Variant **p_args, int p_arg_count,
VALIDATE_ARG_NUM(0);
r_ret = Math::db2linear((double)*p_args[0]);
} break;
+ case MATH_POLAR2CARTESIAN: {
+ VALIDATE_ARG_COUNT(2);
+ VALIDATE_ARG_NUM(0);
+ VALIDATE_ARG_NUM(1);
+ double r = *p_args[0];
+ double th = *p_args[1];
+ r_ret = Vector2(r * Math::cos(th), r * Math::sin(th));
+ } break;
+ case MATH_CARTESIAN2POLAR: {
+ VALIDATE_ARG_COUNT(2);
+ VALIDATE_ARG_NUM(0);
+ VALIDATE_ARG_NUM(1);
+ double x = *p_args[0];
+ double y = *p_args[1];
+ r_ret = Vector2(Math::sqrt(x * x + y * y), Math::atan2(y, x));
+ } break;
+ case MATH_WRAP: {
+ VALIDATE_ARG_COUNT(3);
+ r_ret = Math::wrapi((int64_t)*p_args[0], (int64_t)*p_args[1], (int64_t)*p_args[2]);
+ } break;
+ case MATH_WRAPF: {
+ VALIDATE_ARG_COUNT(3);
+ r_ret = Math::wrapf((double)*p_args[0], (double)*p_args[1], (double)*p_args[2]);
+ } break;
case LOGIC_MAX: {
VALIDATE_ARG_COUNT(2);
if (p_args[0]->get_type() == Variant::INT && p_args[1]->get_type() == Variant::INT) {
@@ -631,7 +660,7 @@ void GDFunctions::call(Function p_func, const Variant **p_args, int p_arg_count,
}
//str+="\n";
- OS::get_singleton()->printerr("%s\n", str.utf8().get_data());
+ print_error(str);
r_ret = Variant();
} break;
@@ -889,7 +918,7 @@ void GDFunctions::call(Function p_func, const Variant **p_args, int p_arg_count,
return;
} else {
- GDInstance *ins = static_cast<GDInstance *>(obj->get_script_instance());
+ GDScriptInstance *ins = static_cast<GDScriptInstance *>(obj->get_script_instance());
Ref<GDScript> base = ins->get_script();
if (base.is_null()) {
@@ -1020,7 +1049,7 @@ void GDFunctions::call(Function p_func, const Variant **p_args, int p_arg_count,
r_ret = gdscr->_new(NULL, 0, r_error);
- GDInstance *ins = static_cast<GDInstance *>(static_cast<Object *>(r_ret)->get_script_instance());
+ GDScriptInstance *ins = static_cast<GDScriptInstance *>(static_cast<Object *>(r_ret)->get_script_instance());
Ref<GDScript> gd_ref = ins->get_script();
for (Map<StringName, GDScript::MemberInfo>::Element *E = gd_ref->member_indices.front(); E; E = E->next()) {
@@ -1244,7 +1273,7 @@ void GDFunctions::call(Function p_func, const Variant **p_args, int p_arg_count,
}
}
-bool GDFunctions::is_deterministic(Function p_func) {
+bool GDScriptFunctions::is_deterministic(Function p_func) {
//man i couldn't have chosen a worse function name,
//way too controversial..
@@ -1285,6 +1314,10 @@ bool GDFunctions::is_deterministic(Function p_func) {
case MATH_RAD2DEG:
case MATH_LINEAR2DB:
case MATH_DB2LINEAR:
+ case MATH_POLAR2CARTESIAN:
+ case MATH_CARTESIAN2POLAR:
+ case MATH_WRAP:
+ case MATH_WRAPF:
case LOGIC_MAX:
case LOGIC_MIN:
case LOGIC_CLAMP:
@@ -1305,7 +1338,7 @@ bool GDFunctions::is_deterministic(Function p_func) {
return false;
}
-MethodInfo GDFunctions::get_info(Function p_func) {
+MethodInfo GDScriptFunctions::get_info(Function p_func) {
#ifdef TOOLS_ENABLED
//using a switch, so the compiler generates a jumptable
@@ -1513,6 +1546,26 @@ MethodInfo GDFunctions::get_info(Function p_func) {
mi.return_val.type = Variant::REAL;
return mi;
} break;
+ case MATH_POLAR2CARTESIAN: {
+ MethodInfo mi("polar2cartesian", PropertyInfo(Variant::REAL, "r"), PropertyInfo(Variant::REAL, "th"));
+ mi.return_val.type = Variant::VECTOR2;
+ return mi;
+ } break;
+ case MATH_CARTESIAN2POLAR: {
+ MethodInfo mi("cartesian2polar", PropertyInfo(Variant::REAL, "x"), PropertyInfo(Variant::REAL, "y"));
+ mi.return_val.type = Variant::VECTOR2;
+ return mi;
+ } break;
+ case MATH_WRAP: {
+ MethodInfo mi("wrapi", PropertyInfo(Variant::INT, "value"), PropertyInfo(Variant::INT, "min"), PropertyInfo(Variant::INT, "max"));
+ mi.return_val.type = Variant::INT;
+ return mi;
+ } break;
+ case MATH_WRAPF: {
+ MethodInfo mi("wrapf", PropertyInfo(Variant::REAL, "value"), PropertyInfo(Variant::REAL, "min"), PropertyInfo(Variant::REAL, "max"));
+ mi.return_val.type = Variant::REAL;
+ return mi;
+ } break;
case LOGIC_MAX: {
MethodInfo mi("max", PropertyInfo(Variant::REAL, "a"), PropertyInfo(Variant::REAL, "b"));
mi.return_val.type = Variant::REAL;
diff --git a/modules/gdscript/gd_functions.h b/modules/gdscript/gdscript_functions.h
index a568c8f1cf..d1c5815cec 100644
--- a/modules/gdscript/gd_functions.h
+++ b/modules/gdscript/gdscript_functions.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* gd_functions.h */
+/* gdscript_functions.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -27,12 +27,12 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef GD_FUNCTIONS_H
-#define GD_FUNCTIONS_H
+#ifndef GDSCRIPT_FUNCTIONS_H
+#define GDSCRIPT_FUNCTIONS_H
#include "variant.h"
-class GDFunctions {
+class GDScriptFunctions {
public:
enum Function {
MATH_SIN,
@@ -75,6 +75,10 @@ public:
MATH_RAD2DEG,
MATH_LINEAR2DB,
MATH_DB2LINEAR,
+ MATH_POLAR2CARTESIAN,
+ MATH_CARTESIAN2POLAR,
+ MATH_WRAP,
+ MATH_WRAPF,
LOGIC_MAX,
LOGIC_MIN,
LOGIC_CLAMP,
@@ -118,4 +122,4 @@ public:
static MethodInfo get_info(Function p_func);
};
-#endif // GD_FUNCTIONS_H
+#endif // GDSCRIPT_FUNCTIONS_H
diff --git a/modules/gdscript/gd_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index 36aaa1f807..bee9ef1998 100644
--- a/modules/gdscript/gd_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* gd_parser.cpp */
+/* gdscript_parser.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -27,15 +27,16 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "gd_parser.h"
-#include "gd_script.h"
+#include "gdscript_parser.h"
+
+#include "gdscript.h"
#include "io/resource_loader.h"
#include "os/file_access.h"
#include "print_string.h"
#include "script_language.h"
template <class T>
-T *GDParser::alloc_node() {
+T *GDScriptParser::alloc_node() {
T *t = memnew(T);
@@ -50,21 +51,21 @@ T *GDParser::alloc_node() {
return t;
}
-bool GDParser::_end_statement() {
+bool GDScriptParser::_end_statement() {
- if (tokenizer->get_token() == GDTokenizer::TK_SEMICOLON) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_SEMICOLON) {
tokenizer->advance();
return true; //handle next
- } else if (tokenizer->get_token() == GDTokenizer::TK_NEWLINE || tokenizer->get_token() == GDTokenizer::TK_EOF) {
+ } else if (tokenizer->get_token() == GDScriptTokenizer::TK_NEWLINE || tokenizer->get_token() == GDScriptTokenizer::TK_EOF) {
return true; //will be handled properly
}
return false;
}
-bool GDParser::_enter_indent_block(BlockNode *p_block) {
+bool GDScriptParser::_enter_indent_block(BlockNode *p_block) {
- if (tokenizer->get_token() != GDTokenizer::TK_COLON) {
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_COLON) {
// report location at the previous token (on the previous line)
int error_line = tokenizer->get_token_line(-1);
int error_column = tokenizer->get_token_column(-1);
@@ -73,7 +74,7 @@ bool GDParser::_enter_indent_block(BlockNode *p_block) {
}
tokenizer->advance();
- if (tokenizer->get_token() != GDTokenizer::TK_NEWLINE) {
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_NEWLINE) {
// be more python-like
int current = tab_level.back()->get();
@@ -85,10 +86,10 @@ bool GDParser::_enter_indent_block(BlockNode *p_block) {
while (true) {
- if (tokenizer->get_token() != GDTokenizer::TK_NEWLINE) {
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_NEWLINE) {
return false; //wtf
- } else if (tokenizer->get_token(1) != GDTokenizer::TK_NEWLINE) {
+ } else if (tokenizer->get_token(1) != GDScriptTokenizer::TK_NEWLINE) {
int indent = tokenizer->get_token_line_indent();
int current = tab_level.back()->get();
@@ -113,9 +114,9 @@ bool GDParser::_enter_indent_block(BlockNode *p_block) {
}
}
-bool GDParser::_parse_arguments(Node *p_parent, Vector<Node *> &p_args, bool p_static, bool p_can_codecomplete) {
+bool GDScriptParser::_parse_arguments(Node *p_parent, Vector<Node *> &p_args, bool p_static, bool p_can_codecomplete) {
- if (tokenizer->get_token() == GDTokenizer::TK_PARENTHESIS_CLOSE) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
tokenizer->advance();
} else {
@@ -124,10 +125,10 @@ bool GDParser::_parse_arguments(Node *p_parent, Vector<Node *> &p_args, bool p_s
while (true) {
- if (tokenizer->get_token() == GDTokenizer::TK_CURSOR) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_CURSOR) {
_make_completable_call(argidx);
completion_node = p_parent;
- } else if (tokenizer->get_token() == GDTokenizer::TK_CONSTANT && tokenizer->get_token_constant().get_type() == Variant::STRING && tokenizer->get_token(1) == GDTokenizer::TK_CURSOR) {
+ } else if (tokenizer->get_token() == GDScriptTokenizer::TK_CONSTANT && tokenizer->get_token_constant().get_type() == Variant::STRING && tokenizer->get_token(1) == GDScriptTokenizer::TK_CURSOR) {
//completing a string argument..
completion_cursor = tokenizer->get_token_constant();
@@ -143,13 +144,13 @@ bool GDParser::_parse_arguments(Node *p_parent, Vector<Node *> &p_args, bool p_s
p_args.push_back(arg);
- if (tokenizer->get_token() == GDTokenizer::TK_PARENTHESIS_CLOSE) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
tokenizer->advance();
break;
- } else if (tokenizer->get_token() == GDTokenizer::TK_COMMA) {
+ } else if (tokenizer->get_token() == GDScriptTokenizer::TK_COMMA) {
- if (tokenizer->get_token(1) == GDTokenizer::TK_PARENTHESIS_CLOSE) {
+ if (tokenizer->get_token(1) == GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
_set_error("Expression expected");
return false;
@@ -169,7 +170,7 @@ bool GDParser::_parse_arguments(Node *p_parent, Vector<Node *> &p_args, bool p_s
return true;
}
-void GDParser::_make_completable_call(int p_arg) {
+void GDScriptParser::_make_completable_call(int p_arg) {
completion_cursor = StringName();
completion_type = COMPLETION_CALL_ARGUMENTS;
@@ -182,14 +183,14 @@ void GDParser::_make_completable_call(int p_arg) {
tokenizer->advance();
}
-bool GDParser::_get_completable_identifier(CompletionType p_type, StringName &identifier) {
+bool GDScriptParser::_get_completable_identifier(CompletionType p_type, StringName &identifier) {
identifier = StringName();
if (tokenizer->is_token_literal()) {
identifier = tokenizer->get_token_literal();
tokenizer->advance();
}
- if (tokenizer->get_token() == GDTokenizer::TK_CURSOR) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_CURSOR) {
completion_cursor = identifier;
completion_type = p_type;
@@ -206,7 +207,7 @@ bool GDParser::_get_completable_identifier(CompletionType p_type, StringName &id
tokenizer->advance();
}
- if (tokenizer->get_token() == GDTokenizer::TK_PARENTHESIS_OPEN) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_OPEN) {
completion_ident_is_call = true;
}
return true;
@@ -215,7 +216,7 @@ bool GDParser::_get_completable_identifier(CompletionType p_type, StringName &id
return false;
}
-GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool p_allow_assign, bool p_parsing_constant) {
+GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_static, bool p_allow_assign, bool p_parsing_constant) {
//Vector<Node*> expressions;
//Vector<OperatorNode::Operator> operators;
@@ -234,12 +235,12 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool
if (parenthesis > 0) {
//remove empty space (only allowed if inside parenthesis
- while (tokenizer->get_token() == GDTokenizer::TK_NEWLINE) {
+ while (tokenizer->get_token() == GDScriptTokenizer::TK_NEWLINE) {
tokenizer->advance();
}
}
- if (tokenizer->get_token() == GDTokenizer::TK_PARENTHESIS_OPEN) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_OPEN) {
//subexpression ()
tokenizer->advance();
parenthesis++;
@@ -248,7 +249,7 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool
if (!subexpr)
return NULL;
- if (tokenizer->get_token() != GDTokenizer::TK_PARENTHESIS_CLOSE) {
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
_set_error("Expected ')' in expression");
return NULL;
@@ -256,7 +257,7 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool
tokenizer->advance();
expr = subexpr;
- } else if (tokenizer->get_token() == GDTokenizer::TK_DOLLAR) {
+ } else if (tokenizer->get_token() == GDScriptTokenizer::TK_DOLLAR) {
tokenizer->advance();
String path;
@@ -267,7 +268,7 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool
while (!done) {
switch (tokenizer->get_token()) {
- case GDTokenizer::TK_CURSOR: {
+ case GDScriptTokenizer::TK_CURSOR: {
completion_cursor = StringName();
completion_type = COMPLETION_GET_NODE;
completion_class = current_class;
@@ -279,7 +280,7 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool
completion_found = true;
tokenizer->advance();
} break;
- case GDTokenizer::TK_CONSTANT: {
+ case GDScriptTokenizer::TK_CONSTANT: {
if (!need_identifier) {
done = true;
@@ -296,7 +297,7 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool
need_identifier = false;
} break;
- case GDTokenizer::TK_OP_DIV: {
+ case GDScriptTokenizer::TK_OP_DIV: {
if (need_identifier) {
done = true;
@@ -344,49 +345,56 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool
expr = op;
- } else if (tokenizer->get_token() == GDTokenizer::TK_CURSOR) {
+ } else if (tokenizer->get_token() == GDScriptTokenizer::TK_CURSOR) {
tokenizer->advance();
continue; //no point in cursor in the middle of expression
- } else if (tokenizer->get_token() == GDTokenizer::TK_CONSTANT) {
+ } else if (tokenizer->get_token() == GDScriptTokenizer::TK_CONSTANT) {
//constant defined by tokenizer
ConstantNode *constant = alloc_node<ConstantNode>();
constant->value = tokenizer->get_token_constant();
tokenizer->advance();
expr = constant;
- } else if (tokenizer->get_token() == GDTokenizer::TK_CONST_PI) {
+ } else if (tokenizer->get_token() == GDScriptTokenizer::TK_CONST_PI) {
//constant defined by tokenizer
ConstantNode *constant = alloc_node<ConstantNode>();
constant->value = Math_PI;
tokenizer->advance();
expr = constant;
- } else if (tokenizer->get_token() == GDTokenizer::TK_CONST_INF) {
+ } else if (tokenizer->get_token() == GDScriptTokenizer::TK_CONST_TAU) {
+
+ //constant defined by tokenizer
+ ConstantNode *constant = alloc_node<ConstantNode>();
+ constant->value = Math_TAU;
+ tokenizer->advance();
+ expr = constant;
+ } else if (tokenizer->get_token() == GDScriptTokenizer::TK_CONST_INF) {
//constant defined by tokenizer
ConstantNode *constant = alloc_node<ConstantNode>();
constant->value = Math_INF;
tokenizer->advance();
expr = constant;
- } else if (tokenizer->get_token() == GDTokenizer::TK_CONST_NAN) {
+ } else if (tokenizer->get_token() == GDScriptTokenizer::TK_CONST_NAN) {
//constant defined by tokenizer
ConstantNode *constant = alloc_node<ConstantNode>();
constant->value = Math_NAN;
tokenizer->advance();
expr = constant;
- } else if (tokenizer->get_token() == GDTokenizer::TK_PR_PRELOAD) {
+ } else if (tokenizer->get_token() == GDScriptTokenizer::TK_PR_PRELOAD) {
//constant defined by tokenizer
tokenizer->advance();
- if (tokenizer->get_token() != GDTokenizer::TK_PARENTHESIS_OPEN) {
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_OPEN) {
_set_error("Expected '(' after 'preload'");
return NULL;
}
tokenizer->advance();
- if (tokenizer->get_token() == GDTokenizer::TK_CURSOR) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_CURSOR) {
completion_cursor = StringName();
completion_node = p_parent;
completion_type = COMPLETION_RESOURCE_PATH;
@@ -466,7 +474,7 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool
}
}
- if (tokenizer->get_token() != GDTokenizer::TK_PARENTHESIS_CLOSE) {
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
_set_error("Expected ')' after 'preload' path");
return NULL;
}
@@ -476,12 +484,12 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool
constant->value = res;
expr = constant;
- } else if (tokenizer->get_token() == GDTokenizer::TK_PR_YIELD) {
+ } else if (tokenizer->get_token() == GDScriptTokenizer::TK_PR_YIELD) {
//constant defined by tokenizer
tokenizer->advance();
- if (tokenizer->get_token() != GDTokenizer::TK_PARENTHESIS_OPEN) {
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_OPEN) {
_set_error("Expected '(' after 'yield'");
return NULL;
}
@@ -491,11 +499,11 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool
OperatorNode *yield = alloc_node<OperatorNode>();
yield->op = OperatorNode::OP_YIELD;
- while (tokenizer->get_token() == GDTokenizer::TK_NEWLINE) {
+ while (tokenizer->get_token() == GDScriptTokenizer::TK_NEWLINE) {
tokenizer->advance();
}
- if (tokenizer->get_token() == GDTokenizer::TK_PARENTHESIS_CLOSE) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
expr = yield;
tokenizer->advance();
} else {
@@ -507,14 +515,14 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool
return NULL;
yield->arguments.push_back(object);
- if (tokenizer->get_token() != GDTokenizer::TK_COMMA) {
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_COMMA) {
_set_error("Expected ',' after first argument of 'yield'");
return NULL;
}
tokenizer->advance();
- if (tokenizer->get_token() == GDTokenizer::TK_CURSOR) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_CURSOR) {
completion_cursor = StringName();
completion_node = object;
@@ -533,7 +541,7 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool
return NULL;
yield->arguments.push_back(signal);
- if (tokenizer->get_token() != GDTokenizer::TK_PARENTHESIS_CLOSE) {
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
_set_error("Expected ')' after second argument of 'yield'");
return NULL;
}
@@ -545,7 +553,7 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool
expr = yield;
}
- } else if (tokenizer->get_token() == GDTokenizer::TK_SELF) {
+ } else if (tokenizer->get_token() == GDScriptTokenizer::TK_SELF) {
if (p_static) {
_set_error("'self'' not allowed in static function or constant expression");
@@ -555,7 +563,7 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool
SelfNode *self = alloc_node<SelfNode>();
tokenizer->advance();
expr = self;
- } else if (tokenizer->get_token() == GDTokenizer::TK_BUILT_IN_TYPE && tokenizer->get_token(1) == GDTokenizer::TK_PERIOD) {
+ } else if (tokenizer->get_token() == GDScriptTokenizer::TK_BUILT_IN_TYPE && tokenizer->get_token(1) == GDScriptTokenizer::TK_PERIOD) {
Variant::Type bi_type = tokenizer->get_token_type();
tokenizer->advance(2);
@@ -582,20 +590,20 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool
cn->value = Variant::get_numeric_constant_value(bi_type, identifier);
expr = cn;
- } else if (tokenizer->get_token(1) == GDTokenizer::TK_PARENTHESIS_OPEN && tokenizer->is_token_literal()) {
+ } else if (tokenizer->get_token(1) == GDScriptTokenizer::TK_PARENTHESIS_OPEN && tokenizer->is_token_literal()) {
// We check with is_token_literal, as this allows us to use match/sync/etc. as a name
//function or constructor
OperatorNode *op = alloc_node<OperatorNode>();
op->op = OperatorNode::OP_CALL;
- if (tokenizer->get_token() == GDTokenizer::TK_BUILT_IN_TYPE) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_BUILT_IN_TYPE) {
TypeNode *tn = alloc_node<TypeNode>();
tn->vtype = tokenizer->get_token_type();
op->arguments.push_back(tn);
tokenizer->advance(2);
- } else if (tokenizer->get_token() == GDTokenizer::TK_BUILT_IN_FUNC) {
+ } else if (tokenizer->get_token() == GDScriptTokenizer::TK_BUILT_IN_FUNC) {
BuiltInFunctionNode *bn = alloc_node<BuiltInFunctionNode>();
bn->function = tokenizer->get_token_built_in_func();
@@ -616,7 +624,7 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool
tokenizer->advance(1);
}
- if (tokenizer->get_token() == GDTokenizer::TK_CURSOR) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_CURSOR) {
_make_completable_call(0);
completion_node = op;
}
@@ -661,7 +669,7 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool
expr = id;
}
- } else if (tokenizer->get_token() == GDTokenizer::TK_OP_ADD || tokenizer->get_token() == GDTokenizer::TK_OP_SUB || tokenizer->get_token() == GDTokenizer::TK_OP_NOT || tokenizer->get_token() == GDTokenizer::TK_OP_BIT_INVERT) {
+ } else if (tokenizer->get_token() == GDScriptTokenizer::TK_OP_ADD || tokenizer->get_token() == GDScriptTokenizer::TK_OP_SUB || tokenizer->get_token() == GDScriptTokenizer::TK_OP_NOT || tokenizer->get_token() == GDScriptTokenizer::TK_OP_BIT_INVERT) {
//single prefix operators like !expr +expr -expr ++expr --expr
alloc_node<OperatorNode>();
@@ -669,16 +677,16 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool
e.is_op = true;
switch (tokenizer->get_token()) {
- case GDTokenizer::TK_OP_ADD: e.op = OperatorNode::OP_POS; break;
- case GDTokenizer::TK_OP_SUB: e.op = OperatorNode::OP_NEG; break;
- case GDTokenizer::TK_OP_NOT: e.op = OperatorNode::OP_NOT; break;
- case GDTokenizer::TK_OP_BIT_INVERT: e.op = OperatorNode::OP_BIT_INVERT; break;
+ case GDScriptTokenizer::TK_OP_ADD: e.op = OperatorNode::OP_POS; break;
+ case GDScriptTokenizer::TK_OP_SUB: e.op = OperatorNode::OP_NEG; break;
+ case GDScriptTokenizer::TK_OP_NOT: e.op = OperatorNode::OP_NOT; break;
+ case GDScriptTokenizer::TK_OP_BIT_INVERT: e.op = OperatorNode::OP_BIT_INVERT; break;
default: {}
}
tokenizer->advance();
- if (e.op != OperatorNode::OP_NOT && tokenizer->get_token() == GDTokenizer::TK_OP_NOT) {
+ if (e.op != OperatorNode::OP_NOT && tokenizer->get_token() == GDScriptTokenizer::TK_OP_NOT) {
_set_error("Misplaced 'not'.");
return NULL;
}
@@ -693,7 +701,7 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool
op->arguments.push_back(subexpr);
expr=op;*/
- } else if (tokenizer->get_token() == GDTokenizer::TK_BRACKET_OPEN) {
+ } else if (tokenizer->get_token() == GDScriptTokenizer::TK_BRACKET_OPEN) {
// array
tokenizer->advance();
@@ -702,18 +710,18 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool
while (true) {
- if (tokenizer->get_token() == GDTokenizer::TK_EOF) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_EOF) {
_set_error("Unterminated array");
return NULL;
- } else if (tokenizer->get_token() == GDTokenizer::TK_BRACKET_CLOSE) {
+ } else if (tokenizer->get_token() == GDScriptTokenizer::TK_BRACKET_CLOSE) {
tokenizer->advance();
break;
- } else if (tokenizer->get_token() == GDTokenizer::TK_NEWLINE) {
+ } else if (tokenizer->get_token() == GDScriptTokenizer::TK_NEWLINE) {
tokenizer->advance(); //ignore newline
- } else if (tokenizer->get_token() == GDTokenizer::TK_COMMA) {
+ } else if (tokenizer->get_token() == GDScriptTokenizer::TK_COMMA) {
if (!expecting_comma) {
_set_error("expression or ']' expected");
return NULL;
@@ -736,7 +744,7 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool
}
expr = arr;
- } else if (tokenizer->get_token() == GDTokenizer::TK_CURLY_BRACKET_OPEN) {
+ } else if (tokenizer->get_token() == GDScriptTokenizer::TK_CURLY_BRACKET_OPEN) {
// array
tokenizer->advance();
@@ -758,12 +766,12 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool
while (true) {
- if (tokenizer->get_token() == GDTokenizer::TK_EOF) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_EOF) {
_set_error("Unterminated dictionary");
return NULL;
- } else if (tokenizer->get_token() == GDTokenizer::TK_CURLY_BRACKET_CLOSE) {
+ } else if (tokenizer->get_token() == GDScriptTokenizer::TK_CURLY_BRACKET_CLOSE) {
if (expecting == DICT_EXPECT_COLON) {
_set_error("':' expected");
@@ -775,10 +783,10 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool
}
tokenizer->advance();
break;
- } else if (tokenizer->get_token() == GDTokenizer::TK_NEWLINE) {
+ } else if (tokenizer->get_token() == GDScriptTokenizer::TK_NEWLINE) {
tokenizer->advance(); //ignore newline
- } else if (tokenizer->get_token() == GDTokenizer::TK_COMMA) {
+ } else if (tokenizer->get_token() == GDScriptTokenizer::TK_COMMA) {
if (expecting == DICT_EXPECT_KEY) {
_set_error("key or '}' expected");
@@ -796,7 +804,7 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool
expecting = DICT_EXPECT_KEY;
tokenizer->advance(); //ignore newline
- } else if (tokenizer->get_token() == GDTokenizer::TK_COLON) {
+ } else if (tokenizer->get_token() == GDScriptTokenizer::TK_COLON) {
if (expecting == DICT_EXPECT_KEY) {
_set_error("key or '}' expected");
@@ -826,7 +834,7 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool
if (expecting == DICT_EXPECT_KEY) {
- if (tokenizer->is_token_literal() && tokenizer->get_token(1) == GDTokenizer::TK_OP_ASSIGN) {
+ if (tokenizer->is_token_literal() && tokenizer->get_token(1) == GDScriptTokenizer::TK_OP_ASSIGN) {
// We check with is_token_literal, as this allows us to use match/sync/etc. as a name
//lua style identifier, easier to write
ConstantNode *cn = alloc_node<ConstantNode>();
@@ -849,8 +857,8 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool
return NULL;
expecting = DICT_EXPECT_COMMA;
- if (key->type == GDParser::Node::TYPE_CONSTANT) {
- Variant const &keyName = static_cast<const GDParser::ConstantNode *>(key)->value;
+ if (key->type == GDScriptParser::Node::TYPE_CONSTANT) {
+ Variant const &keyName = static_cast<const GDScriptParser::ConstantNode *>(key)->value;
if (keys.has(keyName)) {
_set_error("Duplicate key found in Dictionary literal");
@@ -870,7 +878,7 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool
expr = dict;
- } else if (tokenizer->get_token() == GDTokenizer::TK_PERIOD && (tokenizer->is_token_literal(1) || tokenizer->get_token(1) == GDTokenizer::TK_CURSOR) && tokenizer->get_token(2) == GDTokenizer::TK_PARENTHESIS_OPEN) {
+ } else if (tokenizer->get_token() == GDScriptTokenizer::TK_PERIOD && (tokenizer->is_token_literal(1) || tokenizer->get_token(1) == GDScriptTokenizer::TK_CURSOR) && tokenizer->get_token(2) == GDScriptTokenizer::TK_PARENTHESIS_OPEN) {
// We check with is_token_literal, as this allows us to use match/sync/etc. as a name
// parent call
@@ -907,7 +915,7 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool
}
if (!expr) {
- ERR_EXPLAIN("GDParser bug, couldn't figure out what expression is..");
+ ERR_EXPLAIN("GDScriptParser bug, couldn't figure out what expression is..");
ERR_FAIL_COND_V(!expr, NULL);
}
@@ -919,15 +927,15 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool
//expressions can be indexed any number of times
- if (tokenizer->get_token() == GDTokenizer::TK_PERIOD) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_PERIOD) {
//indexing using "."
- if (tokenizer->get_token(1) != GDTokenizer::TK_CURSOR && !tokenizer->is_token_literal(1)) {
+ if (tokenizer->get_token(1) != GDScriptTokenizer::TK_CURSOR && !tokenizer->is_token_literal(1)) {
// We check with is_token_literal, as this allows us to use match/sync/etc. as a name
_set_error("Expected identifier as member");
return NULL;
- } else if (tokenizer->get_token(2) == GDTokenizer::TK_PARENTHESIS_OPEN) {
+ } else if (tokenizer->get_token(2) == GDScriptTokenizer::TK_PARENTHESIS_OPEN) {
//call!!
OperatorNode *op = alloc_node<OperatorNode>();
op->op = OperatorNode::OP_CALL;
@@ -935,10 +943,10 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool
tokenizer->advance();
IdentifierNode *id = alloc_node<IdentifierNode>();
- if (tokenizer->get_token() == GDTokenizer::TK_BUILT_IN_FUNC) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_BUILT_IN_FUNC) {
//small hack so built in funcs don't obfuscate methods
- id->name = GDFunctions::get_func_name(tokenizer->get_token_built_in_func());
+ id->name = GDScriptFunctions::get_func_name(tokenizer->get_token_built_in_func());
tokenizer->advance();
} else {
@@ -955,7 +963,7 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool
op->arguments.push_back(id); // call func
//get arguments
tokenizer->advance(1);
- if (tokenizer->get_token() == GDTokenizer::TK_CURSOR) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_CURSOR) {
_make_completable_call(0);
completion_node = op;
}
@@ -990,7 +998,7 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool
expr = op;
}
- } else if (tokenizer->get_token() == GDTokenizer::TK_BRACKET_OPEN) {
+ } else if (tokenizer->get_token() == GDScriptTokenizer::TK_BRACKET_OPEN) {
//indexing using "[]"
OperatorNode *op = alloc_node<OperatorNode>();
op->op = OperatorNode::OP_INDEX;
@@ -1002,7 +1010,7 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool
return NULL;
}
- if (tokenizer->get_token() != GDTokenizer::TK_BRACKET_CLOSE) {
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_BRACKET_CLOSE) {
_set_error("Expected ']'");
return NULL;
}
@@ -1022,7 +1030,7 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool
if (parenthesis > 0) {
//remove empty space (only allowed if inside parenthesis
- while (tokenizer->get_token() == GDTokenizer::TK_NEWLINE) {
+ while (tokenizer->get_token() == GDScriptTokenizer::TK_NEWLINE) {
tokenizer->advance();
}
}
@@ -1047,29 +1055,29 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool
switch (tokenizer->get_token()) { //see operator
- case GDTokenizer::TK_OP_IN: op = OperatorNode::OP_IN; break;
- case GDTokenizer::TK_OP_EQUAL: op = OperatorNode::OP_EQUAL; break;
- case GDTokenizer::TK_OP_NOT_EQUAL: op = OperatorNode::OP_NOT_EQUAL; break;
- case GDTokenizer::TK_OP_LESS: op = OperatorNode::OP_LESS; break;
- case GDTokenizer::TK_OP_LESS_EQUAL: op = OperatorNode::OP_LESS_EQUAL; break;
- case GDTokenizer::TK_OP_GREATER: op = OperatorNode::OP_GREATER; break;
- case GDTokenizer::TK_OP_GREATER_EQUAL: op = OperatorNode::OP_GREATER_EQUAL; break;
- case GDTokenizer::TK_OP_AND: op = OperatorNode::OP_AND; break;
- case GDTokenizer::TK_OP_OR: op = OperatorNode::OP_OR; break;
- case GDTokenizer::TK_OP_ADD: op = OperatorNode::OP_ADD; break;
- case GDTokenizer::TK_OP_SUB: op = OperatorNode::OP_SUB; break;
- case GDTokenizer::TK_OP_MUL: op = OperatorNode::OP_MUL; break;
- case GDTokenizer::TK_OP_DIV: op = OperatorNode::OP_DIV; break;
- case GDTokenizer::TK_OP_MOD:
+ case GDScriptTokenizer::TK_OP_IN: op = OperatorNode::OP_IN; break;
+ case GDScriptTokenizer::TK_OP_EQUAL: op = OperatorNode::OP_EQUAL; break;
+ case GDScriptTokenizer::TK_OP_NOT_EQUAL: op = OperatorNode::OP_NOT_EQUAL; break;
+ case GDScriptTokenizer::TK_OP_LESS: op = OperatorNode::OP_LESS; break;
+ case GDScriptTokenizer::TK_OP_LESS_EQUAL: op = OperatorNode::OP_LESS_EQUAL; break;
+ case GDScriptTokenizer::TK_OP_GREATER: op = OperatorNode::OP_GREATER; break;
+ case GDScriptTokenizer::TK_OP_GREATER_EQUAL: op = OperatorNode::OP_GREATER_EQUAL; break;
+ case GDScriptTokenizer::TK_OP_AND: op = OperatorNode::OP_AND; break;
+ case GDScriptTokenizer::TK_OP_OR: op = OperatorNode::OP_OR; break;
+ case GDScriptTokenizer::TK_OP_ADD: op = OperatorNode::OP_ADD; break;
+ case GDScriptTokenizer::TK_OP_SUB: op = OperatorNode::OP_SUB; break;
+ case GDScriptTokenizer::TK_OP_MUL: op = OperatorNode::OP_MUL; break;
+ case GDScriptTokenizer::TK_OP_DIV: op = OperatorNode::OP_DIV; break;
+ case GDScriptTokenizer::TK_OP_MOD:
op = OperatorNode::OP_MOD;
break;
- //case GDTokenizer::TK_OP_NEG: op=OperatorNode::OP_NEG ; break;
- case GDTokenizer::TK_OP_SHIFT_LEFT: op = OperatorNode::OP_SHIFT_LEFT; break;
- case GDTokenizer::TK_OP_SHIFT_RIGHT: op = OperatorNode::OP_SHIFT_RIGHT; break;
- case GDTokenizer::TK_OP_ASSIGN: {
+ //case GDScriptTokenizer::TK_OP_NEG: op=OperatorNode::OP_NEG ; break;
+ case GDScriptTokenizer::TK_OP_SHIFT_LEFT: op = OperatorNode::OP_SHIFT_LEFT; break;
+ case GDScriptTokenizer::TK_OP_SHIFT_RIGHT: op = OperatorNode::OP_SHIFT_RIGHT; break;
+ case GDScriptTokenizer::TK_OP_ASSIGN: {
_VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN;
- if (tokenizer->get_token(1) == GDTokenizer::TK_CURSOR) {
+ if (tokenizer->get_token(1) == GDScriptTokenizer::TK_CURSOR) {
//code complete assignment
completion_type = COMPLETION_ASSIGN;
completion_node = expr;
@@ -1082,22 +1090,22 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool
}
} break;
- case GDTokenizer::TK_OP_ASSIGN_ADD: _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_ADD; break;
- case GDTokenizer::TK_OP_ASSIGN_SUB: _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_SUB; break;
- case GDTokenizer::TK_OP_ASSIGN_MUL: _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_MUL; break;
- case GDTokenizer::TK_OP_ASSIGN_DIV: _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_DIV; break;
- case GDTokenizer::TK_OP_ASSIGN_MOD: _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_MOD; break;
- case GDTokenizer::TK_OP_ASSIGN_SHIFT_LEFT: _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_SHIFT_LEFT; break;
- case GDTokenizer::TK_OP_ASSIGN_SHIFT_RIGHT: _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_SHIFT_RIGHT; break;
- case GDTokenizer::TK_OP_ASSIGN_BIT_AND: _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_BIT_AND; break;
- case GDTokenizer::TK_OP_ASSIGN_BIT_OR: _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_BIT_OR; break;
- case GDTokenizer::TK_OP_ASSIGN_BIT_XOR: _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_BIT_XOR; break;
- case GDTokenizer::TK_OP_BIT_AND: op = OperatorNode::OP_BIT_AND; break;
- case GDTokenizer::TK_OP_BIT_OR: op = OperatorNode::OP_BIT_OR; break;
- case GDTokenizer::TK_OP_BIT_XOR: op = OperatorNode::OP_BIT_XOR; break;
- case GDTokenizer::TK_PR_IS: op = OperatorNode::OP_IS; break;
- case GDTokenizer::TK_CF_IF: op = OperatorNode::OP_TERNARY_IF; break;
- case GDTokenizer::TK_CF_ELSE: op = OperatorNode::OP_TERNARY_ELSE; break;
+ case GDScriptTokenizer::TK_OP_ASSIGN_ADD: _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_ADD; break;
+ case GDScriptTokenizer::TK_OP_ASSIGN_SUB: _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_SUB; break;
+ case GDScriptTokenizer::TK_OP_ASSIGN_MUL: _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_MUL; break;
+ case GDScriptTokenizer::TK_OP_ASSIGN_DIV: _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_DIV; break;
+ case GDScriptTokenizer::TK_OP_ASSIGN_MOD: _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_MOD; break;
+ case GDScriptTokenizer::TK_OP_ASSIGN_SHIFT_LEFT: _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_SHIFT_LEFT; break;
+ case GDScriptTokenizer::TK_OP_ASSIGN_SHIFT_RIGHT: _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_SHIFT_RIGHT; break;
+ case GDScriptTokenizer::TK_OP_ASSIGN_BIT_AND: _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_BIT_AND; break;
+ case GDScriptTokenizer::TK_OP_ASSIGN_BIT_OR: _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_BIT_OR; break;
+ case GDScriptTokenizer::TK_OP_ASSIGN_BIT_XOR: _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_BIT_XOR; break;
+ case GDScriptTokenizer::TK_OP_BIT_AND: op = OperatorNode::OP_BIT_AND; break;
+ case GDScriptTokenizer::TK_OP_BIT_OR: op = OperatorNode::OP_BIT_OR; break;
+ case GDScriptTokenizer::TK_OP_BIT_XOR: op = OperatorNode::OP_BIT_XOR; break;
+ case GDScriptTokenizer::TK_PR_IS: op = OperatorNode::OP_IS; break;
+ case GDScriptTokenizer::TK_CF_IF: op = OperatorNode::OP_TERNARY_IF; break;
+ case GDScriptTokenizer::TK_CF_ELSE: op = OperatorNode::OP_TERNARY_ELSE; break;
default: valid = false; break;
}
@@ -1205,7 +1213,7 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool
case OperatorNode::OP_ASSIGN_BIT_XOR: priority = 15; break;
default: {
- _set_error("GDParser bug, invalid operator in expression: " + itos(expression[i].op));
+ _set_error("GDScriptParser bug, invalid operator in expression: " + itos(expression[i].op));
return NULL;
}
}
@@ -1351,7 +1359,7 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool
return expression[0].node;
}
-GDParser::Node *GDParser::_reduce_expression(Node *p_node, bool p_to_const) {
+GDScriptParser::Node *GDScriptParser::_reduce_expression(Node *p_node, bool p_to_const) {
switch (p_node->type) {
@@ -1448,7 +1456,7 @@ GDParser::Node *GDParser::_reduce_expression(Node *p_node, bool p_to_const) {
} else if (op->op == OperatorNode::OP_CALL) {
//can reduce base type constructors
- if ((op->arguments[0]->type == Node::TYPE_TYPE || (op->arguments[0]->type == Node::TYPE_BUILT_IN_FUNCTION && GDFunctions::is_deterministic(static_cast<BuiltInFunctionNode *>(op->arguments[0])->function))) && last_not_constant == 0) {
+ if ((op->arguments[0]->type == Node::TYPE_TYPE || (op->arguments[0]->type == Node::TYPE_BUILT_IN_FUNCTION && GDScriptFunctions::is_deterministic(static_cast<BuiltInFunctionNode *>(op->arguments[0])->function))) && last_not_constant == 0) {
//native type constructor or intrinsic function
const Variant **vptr = NULL;
@@ -1473,8 +1481,8 @@ GDParser::Node *GDParser::_reduce_expression(Node *p_node, bool p_to_const) {
v = Variant::construct(tn->vtype, vptr, ptrs.size(), ce);
} else {
- GDFunctions::Function func = static_cast<BuiltInFunctionNode *>(op->arguments[0])->function;
- GDFunctions::call(func, vptr, ptrs.size(), v, ce);
+ GDScriptFunctions::Function func = static_cast<BuiltInFunctionNode *>(op->arguments[0])->function;
+ GDScriptFunctions::call(func, vptr, ptrs.size(), v, ce);
}
if (ce.error != Variant::CallError::CALL_OK) {
@@ -1485,8 +1493,8 @@ GDParser::Node *GDParser::_reduce_expression(Node *p_node, bool p_to_const) {
errwhere = "'" + Variant::get_type_name(tn->vtype) + "'' constructor";
} else {
- GDFunctions::Function func = static_cast<BuiltInFunctionNode *>(op->arguments[0])->function;
- errwhere = String("'") + GDFunctions::get_func_name(func) + "'' intrinsic function";
+ GDScriptFunctions::Function func = static_cast<BuiltInFunctionNode *>(op->arguments[0])->function;
+ errwhere = String("'") + GDScriptFunctions::get_func_name(func) + "'' intrinsic function";
}
switch (ce.error) {
@@ -1736,7 +1744,7 @@ GDParser::Node *GDParser::_reduce_expression(Node *p_node, bool p_to_const) {
}
}
-GDParser::Node *GDParser::_parse_and_reduce_expression(Node *p_parent, bool p_static, bool p_reduce_const, bool p_allow_assign) {
+GDScriptParser::Node *GDScriptParser::_parse_and_reduce_expression(Node *p_parent, bool p_static, bool p_reduce_const, bool p_allow_assign) {
Node *expr = _parse_expression(p_parent, p_static, p_allow_assign, p_reduce_const);
if (!expr || error_set)
@@ -1747,58 +1755,58 @@ GDParser::Node *GDParser::_parse_and_reduce_expression(Node *p_parent, bool p_st
return expr;
}
-bool GDParser::_recover_from_completion() {
+bool GDScriptParser::_recover_from_completion() {
if (!completion_found) {
return false; //can't recover if no completion
}
//skip stuff until newline
- while (tokenizer->get_token() != GDTokenizer::TK_NEWLINE && tokenizer->get_token() != GDTokenizer::TK_EOF && tokenizer->get_token() != GDTokenizer::TK_ERROR) {
+ while (tokenizer->get_token() != GDScriptTokenizer::TK_NEWLINE && tokenizer->get_token() != GDScriptTokenizer::TK_EOF && tokenizer->get_token() != GDScriptTokenizer::TK_ERROR) {
tokenizer->advance();
}
completion_found = false;
error_set = false;
- if (tokenizer->get_token() == GDTokenizer::TK_ERROR) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_ERROR) {
error_set = true;
}
return true;
}
-GDParser::PatternNode *GDParser::_parse_pattern(bool p_static) {
+GDScriptParser::PatternNode *GDScriptParser::_parse_pattern(bool p_static) {
PatternNode *pattern = alloc_node<PatternNode>();
- GDTokenizer::Token token = tokenizer->get_token();
+ GDScriptTokenizer::Token token = tokenizer->get_token();
if (error_set)
return NULL;
- if (token == GDTokenizer::TK_EOF) {
+ if (token == GDScriptTokenizer::TK_EOF) {
return NULL;
}
switch (token) {
// array
- case GDTokenizer::TK_BRACKET_OPEN: {
+ case GDScriptTokenizer::TK_BRACKET_OPEN: {
tokenizer->advance();
- pattern->pt_type = GDParser::PatternNode::PT_ARRAY;
+ pattern->pt_type = GDScriptParser::PatternNode::PT_ARRAY;
while (true) {
- if (tokenizer->get_token() == GDTokenizer::TK_BRACKET_CLOSE) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_BRACKET_CLOSE) {
tokenizer->advance();
break;
}
- if (tokenizer->get_token() == GDTokenizer::TK_PERIOD && tokenizer->get_token(1) == GDTokenizer::TK_PERIOD) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_PERIOD && tokenizer->get_token(1) == GDScriptTokenizer::TK_PERIOD) {
// match everything
tokenizer->advance(2);
PatternNode *sub_pattern = alloc_node<PatternNode>();
- sub_pattern->pt_type = GDParser::PatternNode::PT_IGNORE_REST;
+ sub_pattern->pt_type = GDScriptParser::PatternNode::PT_IGNORE_REST;
pattern->array.push_back(sub_pattern);
- if (tokenizer->get_token() == GDTokenizer::TK_COMMA && tokenizer->get_token(1) == GDTokenizer::TK_BRACKET_CLOSE) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_COMMA && tokenizer->get_token(1) == GDScriptTokenizer::TK_BRACKET_CLOSE) {
tokenizer->advance(2);
break;
- } else if (tokenizer->get_token() == GDTokenizer::TK_BRACKET_CLOSE) {
+ } else if (tokenizer->get_token() == GDScriptTokenizer::TK_BRACKET_CLOSE) {
tokenizer->advance(1);
break;
} else {
@@ -1814,10 +1822,10 @@ GDParser::PatternNode *GDParser::_parse_pattern(bool p_static) {
pattern->array.push_back(sub_pattern);
- if (tokenizer->get_token() == GDTokenizer::TK_COMMA) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_COMMA) {
tokenizer->advance();
continue;
- } else if (tokenizer->get_token() == GDTokenizer::TK_BRACKET_CLOSE) {
+ } else if (tokenizer->get_token() == GDScriptTokenizer::TK_BRACKET_CLOSE) {
tokenizer->advance();
break;
} else {
@@ -1827,33 +1835,33 @@ GDParser::PatternNode *GDParser::_parse_pattern(bool p_static) {
}
} break;
// bind
- case GDTokenizer::TK_PR_VAR: {
+ case GDScriptTokenizer::TK_PR_VAR: {
tokenizer->advance();
- pattern->pt_type = GDParser::PatternNode::PT_BIND;
+ pattern->pt_type = GDScriptParser::PatternNode::PT_BIND;
pattern->bind = tokenizer->get_token_identifier();
tokenizer->advance();
} break;
// dictionary
- case GDTokenizer::TK_CURLY_BRACKET_OPEN: {
+ case GDScriptTokenizer::TK_CURLY_BRACKET_OPEN: {
tokenizer->advance();
- pattern->pt_type = GDParser::PatternNode::PT_DICTIONARY;
+ pattern->pt_type = GDScriptParser::PatternNode::PT_DICTIONARY;
while (true) {
- if (tokenizer->get_token() == GDTokenizer::TK_CURLY_BRACKET_CLOSE) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_CURLY_BRACKET_CLOSE) {
tokenizer->advance();
break;
}
- if (tokenizer->get_token() == GDTokenizer::TK_PERIOD && tokenizer->get_token(1) == GDTokenizer::TK_PERIOD) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_PERIOD && tokenizer->get_token(1) == GDScriptTokenizer::TK_PERIOD) {
// match everything
tokenizer->advance(2);
PatternNode *sub_pattern = alloc_node<PatternNode>();
sub_pattern->pt_type = PatternNode::PT_IGNORE_REST;
pattern->array.push_back(sub_pattern);
- if (tokenizer->get_token() == GDTokenizer::TK_COMMA && tokenizer->get_token(1) == GDTokenizer::TK_CURLY_BRACKET_CLOSE) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_COMMA && tokenizer->get_token(1) == GDScriptTokenizer::TK_CURLY_BRACKET_CLOSE) {
tokenizer->advance(2);
break;
- } else if (tokenizer->get_token() == GDTokenizer::TK_CURLY_BRACKET_CLOSE) {
+ } else if (tokenizer->get_token() == GDScriptTokenizer::TK_CURLY_BRACKET_CLOSE) {
tokenizer->advance(1);
break;
} else {
@@ -1868,12 +1876,12 @@ GDParser::PatternNode *GDParser::_parse_pattern(bool p_static) {
return NULL;
}
- if (key->type != GDParser::Node::TYPE_CONSTANT) {
+ if (key->type != GDScriptParser::Node::TYPE_CONSTANT) {
_set_error("Not a constant expression as key");
return NULL;
}
- if (tokenizer->get_token() == GDTokenizer::TK_COLON) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_COLON) {
tokenizer->advance();
PatternNode *value = _parse_pattern(p_static);
@@ -1887,10 +1895,10 @@ GDParser::PatternNode *GDParser::_parse_pattern(bool p_static) {
pattern->dictionary.insert(static_cast<ConstantNode *>(key), NULL);
}
- if (tokenizer->get_token() == GDTokenizer::TK_COMMA) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_COMMA) {
tokenizer->advance();
continue;
- } else if (tokenizer->get_token() == GDTokenizer::TK_CURLY_BRACKET_CLOSE) {
+ } else if (tokenizer->get_token() == GDScriptTokenizer::TK_CURLY_BRACKET_CLOSE) {
tokenizer->advance();
break;
} else {
@@ -1899,14 +1907,15 @@ GDParser::PatternNode *GDParser::_parse_pattern(bool p_static) {
}
}
} break;
- case GDTokenizer::TK_WILDCARD: {
+ case GDScriptTokenizer::TK_WILDCARD: {
tokenizer->advance();
pattern->pt_type = PatternNode::PT_WILDCARD;
} break;
// all the constants like strings and numbers
default: {
Node *value = _parse_and_reduce_expression(pattern, p_static);
- if (error_set) {
+ if (!value) {
+ _set_error("Expect constant expression or variables in a pattern");
return NULL;
}
@@ -1942,15 +1951,15 @@ GDParser::PatternNode *GDParser::_parse_pattern(bool p_static) {
return pattern;
}
-void GDParser::_parse_pattern_block(BlockNode *p_block, Vector<PatternBranchNode *> &p_branches, bool p_static) {
+void GDScriptParser::_parse_pattern_block(BlockNode *p_block, Vector<PatternBranchNode *> &p_branches, bool p_static) {
int indent_level = tab_level.back()->get();
while (true) {
- while (tokenizer->get_token() == GDTokenizer::TK_NEWLINE && _parse_newline())
+ while (tokenizer->get_token() == GDScriptTokenizer::TK_NEWLINE && _parse_newline())
;
- // GDTokenizer::Token token = tokenizer->get_token();
+ // GDScriptTokenizer::Token token = tokenizer->get_token();
if (error_set)
return;
@@ -1969,7 +1978,7 @@ void GDParser::_parse_pattern_block(BlockNode *p_block, Vector<PatternBranchNode
return;
}
- while (tokenizer->get_token() == GDTokenizer::TK_COMMA) {
+ while (tokenizer->get_token() == GDScriptTokenizer::TK_COMMA) {
tokenizer->advance();
branch->patterns.push_back(_parse_pattern(p_static));
if (!branch->patterns[branch->patterns.size() - 1]) {
@@ -1995,13 +2004,13 @@ void GDParser::_parse_pattern_block(BlockNode *p_block, Vector<PatternBranchNode
}
}
-void GDParser::_generate_pattern(PatternNode *p_pattern, Node *p_node_to_match, Node *&p_resulting_node, Map<StringName, Node *> &p_bindings) {
+void GDScriptParser::_generate_pattern(PatternNode *p_pattern, Node *p_node_to_match, Node *&p_resulting_node, Map<StringName, Node *> &p_bindings) {
switch (p_pattern->pt_type) {
case PatternNode::PT_CONSTANT: {
// typecheck
BuiltInFunctionNode *typeof_node = alloc_node<BuiltInFunctionNode>();
- typeof_node->function = GDFunctions::TYPE_OF;
+ typeof_node->function = GDScriptFunctions::TYPE_OF;
OperatorNode *typeof_match_value = alloc_node<OperatorNode>();
typeof_match_value->op = OperatorNode::OP_CALL;
@@ -2056,7 +2065,7 @@ void GDParser::_generate_pattern(PatternNode *p_pattern, Node *p_node_to_match,
{
// typecheck
BuiltInFunctionNode *typeof_node = alloc_node<BuiltInFunctionNode>();
- typeof_node->function = GDFunctions::TYPE_OF;
+ typeof_node->function = GDScriptFunctions::TYPE_OF;
OperatorNode *typeof_match_value = alloc_node<OperatorNode>();
typeof_match_value->op = OperatorNode::OP_CALL;
@@ -2135,7 +2144,7 @@ void GDParser::_generate_pattern(PatternNode *p_pattern, Node *p_node_to_match,
{
// typecheck
BuiltInFunctionNode *typeof_node = alloc_node<BuiltInFunctionNode>();
- typeof_node->function = GDFunctions::TYPE_OF;
+ typeof_node->function = GDScriptFunctions::TYPE_OF;
OperatorNode *typeof_match_value = alloc_node<OperatorNode>();
typeof_match_value->op = OperatorNode::OP_CALL;
@@ -2233,7 +2242,7 @@ void GDParser::_generate_pattern(PatternNode *p_pattern, Node *p_node_to_match,
}
}
-void GDParser::_transform_match_statment(BlockNode *p_block, MatchNode *p_match_statement) {
+void GDScriptParser::_transform_match_statment(BlockNode *p_block, MatchNode *p_match_statement) {
IdentifierNode *id = alloc_node<IdentifierNode>();
id->name = "#match_value";
@@ -2297,7 +2306,7 @@ void GDParser::_transform_match_statment(BlockNode *p_block, MatchNode *p_match_
}
}
-void GDParser::_parse_block(BlockNode *p_block, bool p_static) {
+void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) {
int indent_level = tab_level.back()->get();
@@ -2320,7 +2329,7 @@ void GDParser::_parse_block(BlockNode *p_block, bool p_static) {
}
is_first_line = false;
- GDTokenizer::Token token = tokenizer->get_token();
+ GDScriptTokenizer::Token token = tokenizer->get_token();
if (error_set)
return;
@@ -2339,15 +2348,15 @@ void GDParser::_parse_block(BlockNode *p_block, bool p_static) {
switch (token) {
- case GDTokenizer::TK_EOF:
+ case GDScriptTokenizer::TK_EOF:
p_block->end_line = tokenizer->get_token_line();
- case GDTokenizer::TK_ERROR: {
+ case GDScriptTokenizer::TK_ERROR: {
return; //go back
//end of file!
} break;
- case GDTokenizer::TK_NEWLINE: {
+ case GDScriptTokenizer::TK_NEWLINE: {
if (!_parse_newline()) {
if (!error_set) {
@@ -2362,19 +2371,19 @@ void GDParser::_parse_block(BlockNode *p_block, bool p_static) {
p_block->statements.push_back(nl);
} break;
- case GDTokenizer::TK_CF_PASS: {
- if (tokenizer->get_token(1) != GDTokenizer::TK_SEMICOLON && tokenizer->get_token(1) != GDTokenizer::TK_NEWLINE && tokenizer->get_token(1) != GDTokenizer::TK_EOF) {
+ case GDScriptTokenizer::TK_CF_PASS: {
+ if (tokenizer->get_token(1) != GDScriptTokenizer::TK_SEMICOLON && tokenizer->get_token(1) != GDScriptTokenizer::TK_NEWLINE && tokenizer->get_token(1) != GDScriptTokenizer::TK_EOF) {
_set_error("Expected ';' or <NewLine>.");
return;
}
tokenizer->advance();
- if (tokenizer->get_token() == GDTokenizer::TK_SEMICOLON) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_SEMICOLON) {
// Ignore semicolon after 'pass'
tokenizer->advance();
}
} break;
- case GDTokenizer::TK_PR_VAR: {
+ case GDScriptTokenizer::TK_PR_VAR: {
//variale declaration and (eventual) initialization
tokenizer->advance();
@@ -2413,7 +2422,7 @@ void GDParser::_parse_block(BlockNode *p_block, bool p_static) {
Node *assigned = NULL;
- if (tokenizer->get_token() == GDTokenizer::TK_OP_ASSIGN) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_OP_ASSIGN) {
tokenizer->advance();
Node *subexpr = _parse_and_reduce_expression(p_block, p_static);
@@ -2451,7 +2460,7 @@ void GDParser::_parse_block(BlockNode *p_block, bool p_static) {
}
} break;
- case GDTokenizer::TK_CF_IF: {
+ case GDScriptTokenizer::TK_CF_IF: {
tokenizer->advance();
@@ -2490,7 +2499,7 @@ void GDParser::_parse_block(BlockNode *p_block, bool p_static) {
while (true) {
- while (tokenizer->get_token() == GDTokenizer::TK_NEWLINE && _parse_newline())
+ while (tokenizer->get_token() == GDScriptTokenizer::TK_NEWLINE && _parse_newline())
;
if (tab_level.back()->get() < indent_level) { //not at current indent level
@@ -2498,7 +2507,7 @@ void GDParser::_parse_block(BlockNode *p_block, bool p_static) {
return;
}
- if (tokenizer->get_token() == GDTokenizer::TK_CF_ELIF) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_CF_ELIF) {
if (tab_level.back()->get() > indent_level) {
@@ -2544,7 +2553,7 @@ void GDParser::_parse_block(BlockNode *p_block, bool p_static) {
if (error_set)
return;
- } else if (tokenizer->get_token() == GDTokenizer::TK_CF_ELSE) {
+ } else if (tokenizer->get_token() == GDScriptTokenizer::TK_CF_ELSE) {
if (tab_level.back()->get() > indent_level) {
_set_error("Invalid indent");
@@ -2574,7 +2583,7 @@ void GDParser::_parse_block(BlockNode *p_block, bool p_static) {
}
} break;
- case GDTokenizer::TK_CF_WHILE: {
+ case GDScriptTokenizer::TK_CF_WHILE: {
tokenizer->advance();
Node *condition = _parse_and_reduce_expression(p_block, p_static);
@@ -2607,7 +2616,7 @@ void GDParser::_parse_block(BlockNode *p_block, bool p_static) {
return;
p_block->statements.push_back(cf_while);
} break;
- case GDTokenizer::TK_CF_FOR: {
+ case GDScriptTokenizer::TK_CF_FOR: {
tokenizer->advance();
@@ -2621,7 +2630,7 @@ void GDParser::_parse_block(BlockNode *p_block, bool p_static) {
tokenizer->advance();
- if (tokenizer->get_token() != GDTokenizer::TK_OP_IN) {
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_OP_IN) {
_set_error("'in' expected after identifier");
return;
}
@@ -2639,7 +2648,7 @@ void GDParser::_parse_block(BlockNode *p_block, bool p_static) {
if (container->type == Node::TYPE_OPERATOR) {
OperatorNode *op = static_cast<OperatorNode *>(container);
- if (op->op == OperatorNode::OP_CALL && op->arguments[0]->type == Node::TYPE_BUILT_IN_FUNCTION && static_cast<BuiltInFunctionNode *>(op->arguments[0])->function == GDFunctions::GEN_RANGE) {
+ if (op->op == OperatorNode::OP_CALL && op->arguments[0]->type == Node::TYPE_BUILT_IN_FUNCTION && static_cast<BuiltInFunctionNode *>(op->arguments[0])->function == GDScriptFunctions::GEN_RANGE) {
//iterating a range, so see if range() can be optimized without allocating memory, by replacing it by vectors (which can work as iterable too!)
Vector<Node *> args;
@@ -2725,7 +2734,7 @@ void GDParser::_parse_block(BlockNode *p_block, bool p_static) {
return;
p_block->statements.push_back(cf_for);
} break;
- case GDTokenizer::TK_CF_CONTINUE: {
+ case GDScriptTokenizer::TK_CF_CONTINUE: {
tokenizer->advance();
ControlFlowNode *cf_continue = alloc_node<ControlFlowNode>();
@@ -2736,7 +2745,7 @@ void GDParser::_parse_block(BlockNode *p_block, bool p_static) {
return;
}
} break;
- case GDTokenizer::TK_CF_BREAK: {
+ case GDScriptTokenizer::TK_CF_BREAK: {
tokenizer->advance();
ControlFlowNode *cf_break = alloc_node<ControlFlowNode>();
@@ -2747,13 +2756,13 @@ void GDParser::_parse_block(BlockNode *p_block, bool p_static) {
return;
}
} break;
- case GDTokenizer::TK_CF_RETURN: {
+ case GDScriptTokenizer::TK_CF_RETURN: {
tokenizer->advance();
ControlFlowNode *cf_return = alloc_node<ControlFlowNode>();
cf_return->cf_type = ControlFlowNode::CF_RETURN;
- if (tokenizer->get_token() == GDTokenizer::TK_SEMICOLON || tokenizer->get_token() == GDTokenizer::TK_NEWLINE || tokenizer->get_token() == GDTokenizer::TK_EOF) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_SEMICOLON || tokenizer->get_token() == GDScriptTokenizer::TK_NEWLINE || tokenizer->get_token() == GDScriptTokenizer::TK_EOF) {
//expect end of statement
p_block->statements.push_back(cf_return);
if (!_end_statement()) {
@@ -2777,7 +2786,7 @@ void GDParser::_parse_block(BlockNode *p_block, bool p_static) {
}
} break;
- case GDTokenizer::TK_CF_MATCH: {
+ case GDScriptTokenizer::TK_CF_MATCH: {
tokenizer->advance();
@@ -2817,7 +2826,7 @@ void GDParser::_parse_block(BlockNode *p_block, bool p_static) {
_end_statement();
} break;
- case GDTokenizer::TK_PR_ASSERT: {
+ case GDScriptTokenizer::TK_PR_ASSERT: {
tokenizer->advance();
Node *condition = _parse_and_reduce_expression(p_block, p_static);
@@ -2836,7 +2845,7 @@ void GDParser::_parse_block(BlockNode *p_block, bool p_static) {
return;
}
} break;
- case GDTokenizer::TK_PR_BREAKPOINT: {
+ case GDScriptTokenizer::TK_PR_BREAKPOINT: {
tokenizer->advance();
BreakpointNode *bn = alloc_node<BreakpointNode>();
@@ -2864,9 +2873,9 @@ void GDParser::_parse_block(BlockNode *p_block, bool p_static) {
} break;
/*
- case GDTokenizer::TK_CF_LOCAL: {
+ case GDScriptTokenizer::TK_CF_LOCAL: {
- if (tokenizer->get_token(1)!=GDTokenizer::TK_SEMICOLON && tokenizer->get_token(1)!=GDTokenizer::TK_NEWLINE ) {
+ if (tokenizer->get_token(1)!=GDScriptTokenizer::TK_SEMICOLON && tokenizer->get_token(1)!=GDScriptTokenizer::TK_NEWLINE ) {
_set_error("Expected ';' or <NewLine>.");
}
@@ -2877,9 +2886,9 @@ void GDParser::_parse_block(BlockNode *p_block, bool p_static) {
}
}
-bool GDParser::_parse_newline() {
+bool GDScriptParser::_parse_newline() {
- if (tokenizer->get_token(1) != GDTokenizer::TK_EOF && tokenizer->get_token(1) != GDTokenizer::TK_NEWLINE) {
+ if (tokenizer->get_token(1) != GDScriptTokenizer::TK_EOF && tokenizer->get_token(1) != GDScriptTokenizer::TK_NEWLINE) {
int indent = tokenizer->get_token_line_indent();
int current_indent = tab_level.back()->get();
@@ -2918,7 +2927,7 @@ bool GDParser::_parse_newline() {
return true;
}
-void GDParser::_parse_extends(ClassNode *p_class) {
+void GDScriptParser::_parse_extends(ClassNode *p_class) {
if (p_class->extends_used) {
@@ -2936,14 +2945,14 @@ void GDParser::_parse_extends(ClassNode *p_class) {
tokenizer->advance();
- if (tokenizer->get_token() == GDTokenizer::TK_BUILT_IN_TYPE && tokenizer->get_token_type() == Variant::OBJECT) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_BUILT_IN_TYPE && tokenizer->get_token_type() == Variant::OBJECT) {
p_class->extends_class.push_back(Variant::get_type_name(Variant::OBJECT));
tokenizer->advance();
return;
}
// see if inheritance happens from a file
- if (tokenizer->get_token() == GDTokenizer::TK_CONSTANT) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_CONSTANT) {
Variant constant = tokenizer->get_token_constant();
if (constant.get_type() != Variant::STRING) {
@@ -2955,35 +2964,54 @@ void GDParser::_parse_extends(ClassNode *p_class) {
p_class->extends_file = constant;
tokenizer->advance();
- if (tokenizer->get_token() != GDTokenizer::TK_PERIOD) {
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_PERIOD) {
return;
} else
tokenizer->advance();
}
while (true) {
- if (tokenizer->get_token() != GDTokenizer::TK_IDENTIFIER) {
- _set_error("Invalid 'extends' syntax, expected string constant (path) and/or identifier (parent class).");
- return;
- }
+ switch (tokenizer->get_token()) {
+
+ case GDScriptTokenizer::TK_IDENTIFIER: {
- StringName identifier = tokenizer->get_token_identifier();
- p_class->extends_class.push_back(identifier);
+ StringName identifier = tokenizer->get_token_identifier();
+ p_class->extends_class.push_back(identifier);
+ }
+ break;
+
+ case GDScriptTokenizer::TK_PERIOD:
+ break;
+
+ default: {
+
+ _set_error("Invalid 'extends' syntax, expected string constant (path) and/or identifier (parent class).");
+ return;
+ }
+ }
tokenizer->advance(1);
- if (tokenizer->get_token() != GDTokenizer::TK_PERIOD)
- return;
+
+ switch (tokenizer->get_token()) {
+
+ case GDScriptTokenizer::TK_IDENTIFIER:
+ case GDScriptTokenizer::TK_PERIOD:
+ continue;
+
+ default:
+ return;
+ }
}
}
-void GDParser::_parse_class(ClassNode *p_class) {
+void GDScriptParser::_parse_class(ClassNode *p_class) {
int indent_level = tab_level.back()->get();
while (true) {
- GDTokenizer::Token token = tokenizer->get_token();
+ GDScriptTokenizer::Token token = tokenizer->get_token();
if (error_set)
return;
@@ -2994,13 +3022,13 @@ void GDParser::_parse_class(ClassNode *p_class) {
switch (token) {
- case GDTokenizer::TK_EOF:
+ case GDScriptTokenizer::TK_EOF:
p_class->end_line = tokenizer->get_token_line();
- case GDTokenizer::TK_ERROR: {
+ case GDScriptTokenizer::TK_ERROR: {
return; //go back
//end of file!
} break;
- case GDTokenizer::TK_NEWLINE: {
+ case GDScriptTokenizer::TK_NEWLINE: {
if (!_parse_newline()) {
if (!error_set) {
p_class->end_line = tokenizer->get_token_line();
@@ -3008,7 +3036,7 @@ void GDParser::_parse_class(ClassNode *p_class) {
return;
}
} break;
- case GDTokenizer::TK_PR_EXTENDS: {
+ case GDScriptTokenizer::TK_PR_EXTENDS: {
_parse_extends(p_class);
if (error_set)
@@ -3019,7 +3047,7 @@ void GDParser::_parse_class(ClassNode *p_class) {
}
} break;
- case GDTokenizer::TK_PR_TOOL: {
+ case GDScriptTokenizer::TK_PR_TOOL: {
if (p_class->tool) {
@@ -3031,13 +3059,13 @@ void GDParser::_parse_class(ClassNode *p_class) {
tokenizer->advance();
} break;
- case GDTokenizer::TK_PR_CLASS: {
+ case GDScriptTokenizer::TK_PR_CLASS: {
//class inside class :D
StringName name;
StringName extends;
- if (tokenizer->get_token(1) != GDTokenizer::TK_IDENTIFIER) {
+ if (tokenizer->get_token(1) != GDScriptTokenizer::TK_IDENTIFIER) {
_set_error("'class' syntax: 'class <Name>:' or 'class <Name> extends <BaseClass>:'");
return;
@@ -3055,7 +3083,7 @@ void GDParser::_parse_class(ClassNode *p_class) {
p_class->subclasses.push_back(newclass);
- if (tokenizer->get_token() == GDTokenizer::TK_PR_EXTENDS) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_PR_EXTENDS) {
_parse_extends(newclass);
if (error_set)
@@ -3073,26 +3101,26 @@ void GDParser::_parse_class(ClassNode *p_class) {
} break;
/* this is for functions....
- case GDTokenizer::TK_CF_PASS: {
+ case GDScriptTokenizer::TK_CF_PASS: {
tokenizer->advance(1);
} break;
*/
- case GDTokenizer::TK_PR_STATIC: {
+ case GDScriptTokenizer::TK_PR_STATIC: {
tokenizer->advance();
- if (tokenizer->get_token() != GDTokenizer::TK_PR_FUNCTION) {
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_PR_FUNCTION) {
_set_error("Expected 'func'.");
return;
}
}; //fallthrough to function
- case GDTokenizer::TK_PR_FUNCTION: {
+ case GDScriptTokenizer::TK_PR_FUNCTION: {
bool _static = false;
pending_newline = -1;
- if (tokenizer->get_token(-1) == GDTokenizer::TK_PR_STATIC) {
+ if (tokenizer->get_token(-1) == GDScriptTokenizer::TK_PR_STATIC) {
_static = true;
}
@@ -3120,7 +3148,7 @@ void GDParser::_parse_class(ClassNode *p_class) {
}
}
- if (tokenizer->get_token() != GDTokenizer::TK_PARENTHESIS_OPEN) {
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_OPEN) {
_set_error("Expected '(' after identifier (syntax: 'func <identifier>([arguments]):' ).");
return;
@@ -3133,17 +3161,17 @@ void GDParser::_parse_class(ClassNode *p_class) {
int fnline = tokenizer->get_token_line();
- if (tokenizer->get_token() != GDTokenizer::TK_PARENTHESIS_CLOSE) {
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
//has arguments
bool defaulting = false;
while (true) {
- if (tokenizer->get_token() == GDTokenizer::TK_NEWLINE) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_NEWLINE) {
tokenizer->advance();
continue;
}
- if (tokenizer->get_token() == GDTokenizer::TK_PR_VAR) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_PR_VAR) {
tokenizer->advance(); //var before the identifier is allowed
}
@@ -3159,7 +3187,7 @@ void GDParser::_parse_class(ClassNode *p_class) {
tokenizer->advance();
- if (defaulting && tokenizer->get_token() != GDTokenizer::TK_OP_ASSIGN) {
+ if (defaulting && tokenizer->get_token() != GDScriptTokenizer::TK_OP_ASSIGN) {
_set_error("Default parameter expected.");
return;
@@ -3167,7 +3195,7 @@ void GDParser::_parse_class(ClassNode *p_class) {
//tokenizer->advance();
- if (tokenizer->get_token() == GDTokenizer::TK_OP_ASSIGN) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_OP_ASSIGN) {
defaulting = true;
tokenizer->advance(1);
Node *defval = _parse_and_reduce_expression(p_class, _static);
@@ -3191,14 +3219,14 @@ void GDParser::_parse_class(ClassNode *p_class) {
default_values.push_back(on);
}
- while (tokenizer->get_token() == GDTokenizer::TK_NEWLINE) {
+ while (tokenizer->get_token() == GDScriptTokenizer::TK_NEWLINE) {
tokenizer->advance();
}
- if (tokenizer->get_token() == GDTokenizer::TK_COMMA) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_COMMA) {
tokenizer->advance();
continue;
- } else if (tokenizer->get_token() != GDTokenizer::TK_PARENTHESIS_CLOSE) {
+ } else if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
_set_error("Expected ',' or ')'.");
return;
@@ -3225,14 +3253,14 @@ void GDParser::_parse_class(ClassNode *p_class) {
id->name = "_init";
cparent->arguments.push_back(id);
- if (tokenizer->get_token() == GDTokenizer::TK_PERIOD) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_PERIOD) {
tokenizer->advance();
- if (tokenizer->get_token() != GDTokenizer::TK_PARENTHESIS_OPEN) {
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_OPEN) {
_set_error("expected '(' for parent constructor arguments.");
}
tokenizer->advance();
- if (tokenizer->get_token() != GDTokenizer::TK_PARENTHESIS_CLOSE) {
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
//has arguments
parenthesis++;
while (true) {
@@ -3240,10 +3268,10 @@ void GDParser::_parse_class(ClassNode *p_class) {
Node *arg = _parse_and_reduce_expression(p_class, _static);
cparent->arguments.push_back(arg);
- if (tokenizer->get_token() == GDTokenizer::TK_COMMA) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_COMMA) {
tokenizer->advance();
continue;
- } else if (tokenizer->get_token() != GDTokenizer::TK_PARENTHESIS_CLOSE) {
+ } else if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
_set_error("Expected ',' or ')'.");
return;
@@ -3258,7 +3286,7 @@ void GDParser::_parse_class(ClassNode *p_class) {
}
} else {
- if (tokenizer->get_token() == GDTokenizer::TK_PERIOD) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_PERIOD) {
_set_error("Parent constructor call found for a class without inheritance.");
return;
@@ -3295,7 +3323,7 @@ void GDParser::_parse_class(ClassNode *p_class) {
//arguments
} break;
- case GDTokenizer::TK_PR_SIGNAL: {
+ case GDScriptTokenizer::TK_PR_SIGNAL: {
tokenizer->advance();
if (!tokenizer->is_token_literal()) {
@@ -3307,15 +3335,15 @@ void GDParser::_parse_class(ClassNode *p_class) {
sig.name = tokenizer->get_token_identifier();
tokenizer->advance();
- if (tokenizer->get_token() == GDTokenizer::TK_PARENTHESIS_OPEN) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_OPEN) {
tokenizer->advance();
while (true) {
- if (tokenizer->get_token() == GDTokenizer::TK_NEWLINE) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_NEWLINE) {
tokenizer->advance();
continue;
}
- if (tokenizer->get_token() == GDTokenizer::TK_PARENTHESIS_CLOSE) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
tokenizer->advance();
break;
}
@@ -3328,13 +3356,13 @@ void GDParser::_parse_class(ClassNode *p_class) {
sig.arguments.push_back(tokenizer->get_token_identifier());
tokenizer->advance();
- while (tokenizer->get_token() == GDTokenizer::TK_NEWLINE) {
+ while (tokenizer->get_token() == GDScriptTokenizer::TK_NEWLINE) {
tokenizer->advance();
}
- if (tokenizer->get_token() == GDTokenizer::TK_COMMA) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_COMMA) {
tokenizer->advance();
- } else if (tokenizer->get_token() != GDTokenizer::TK_PARENTHESIS_CLOSE) {
+ } else if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
_set_error("Expected ',' or ')' after signal parameter identifier.");
return;
}
@@ -3348,14 +3376,14 @@ void GDParser::_parse_class(ClassNode *p_class) {
return;
}
} break;
- case GDTokenizer::TK_PR_EXPORT: {
+ case GDScriptTokenizer::TK_PR_EXPORT: {
tokenizer->advance();
- if (tokenizer->get_token() == GDTokenizer::TK_PARENTHESIS_OPEN) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_OPEN) {
tokenizer->advance();
- if (tokenizer->get_token() == GDTokenizer::TK_BUILT_IN_TYPE) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_BUILT_IN_TYPE) {
Variant::Type type = tokenizer->get_token_type();
if (type == Variant::NIL) {
@@ -3368,17 +3396,17 @@ void GDParser::_parse_class(ClassNode *p_class) {
String hint_prefix = "";
- if (type == Variant::ARRAY && tokenizer->get_token() == GDTokenizer::TK_COMMA) {
+ if (type == Variant::ARRAY && tokenizer->get_token() == GDScriptTokenizer::TK_COMMA) {
tokenizer->advance();
- while (tokenizer->get_token() == GDTokenizer::TK_BUILT_IN_TYPE) {
+ while (tokenizer->get_token() == GDScriptTokenizer::TK_BUILT_IN_TYPE) {
type = tokenizer->get_token_type();
tokenizer->advance();
if (type == Variant::ARRAY) {
hint_prefix += itos(Variant::ARRAY) + ":";
- if (tokenizer->get_token() == GDTokenizer::TK_COMMA) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_COMMA) {
tokenizer->advance();
}
} else {
@@ -3388,7 +3416,7 @@ void GDParser::_parse_class(ClassNode *p_class) {
}
}
- if (tokenizer->get_token() == GDTokenizer::TK_COMMA) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_COMMA) {
// hint expected next!
tokenizer->advance();
@@ -3396,15 +3424,15 @@ void GDParser::_parse_class(ClassNode *p_class) {
case Variant::INT: {
- if (tokenizer->get_token() == GDTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "FLAGS") {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "FLAGS") {
//current_export.hint=PROPERTY_HINT_ALL_FLAGS;
tokenizer->advance();
- if (tokenizer->get_token() == GDTokenizer::TK_PARENTHESIS_CLOSE) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
break;
}
- if (tokenizer->get_token() != GDTokenizer::TK_COMMA) {
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_COMMA) {
_set_error("Expected ')' or ',' in bit flags hint.");
return;
}
@@ -3415,7 +3443,7 @@ void GDParser::_parse_class(ClassNode *p_class) {
bool first = true;
while (true) {
- if (tokenizer->get_token() != GDTokenizer::TK_CONSTANT || tokenizer->get_token_constant().get_type() != Variant::STRING) {
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_CONSTANT || tokenizer->get_token_constant().get_type() != Variant::STRING) {
current_export = PropertyInfo();
_set_error("Expected a string constant in named bit flags hint.");
return;
@@ -3430,10 +3458,10 @@ void GDParser::_parse_class(ClassNode *p_class) {
current_export.hint_string += c.xml_escape();
tokenizer->advance();
- if (tokenizer->get_token() == GDTokenizer::TK_PARENTHESIS_CLOSE)
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_CLOSE)
break;
- if (tokenizer->get_token() != GDTokenizer::TK_COMMA) {
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_COMMA) {
current_export = PropertyInfo();
_set_error("Expected ')' or ',' in named bit flags hint.");
return;
@@ -3444,13 +3472,13 @@ void GDParser::_parse_class(ClassNode *p_class) {
break;
}
- if (tokenizer->get_token() == GDTokenizer::TK_CONSTANT && tokenizer->get_token_constant().get_type() == Variant::STRING) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_CONSTANT && tokenizer->get_token_constant().get_type() == Variant::STRING) {
//enumeration
current_export.hint = PROPERTY_HINT_ENUM;
bool first = true;
while (true) {
- if (tokenizer->get_token() != GDTokenizer::TK_CONSTANT || tokenizer->get_token_constant().get_type() != Variant::STRING) {
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_CONSTANT || tokenizer->get_token_constant().get_type() != Variant::STRING) {
current_export = PropertyInfo();
_set_error("Expected a string constant in enumeration hint.");
@@ -3466,10 +3494,10 @@ void GDParser::_parse_class(ClassNode *p_class) {
current_export.hint_string += c.xml_escape();
tokenizer->advance();
- if (tokenizer->get_token() == GDTokenizer::TK_PARENTHESIS_CLOSE)
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_CLOSE)
break;
- if (tokenizer->get_token() != GDTokenizer::TK_COMMA) {
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_COMMA) {
current_export = PropertyInfo();
_set_error("Expected ')' or ',' in enumeration hint.");
return;
@@ -3484,10 +3512,10 @@ void GDParser::_parse_class(ClassNode *p_class) {
}; //fallthrough to use the same
case Variant::REAL: {
- if (tokenizer->get_token() == GDTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "EASE") {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "EASE") {
current_export.hint = PROPERTY_HINT_EXP_EASING;
tokenizer->advance();
- if (tokenizer->get_token() != GDTokenizer::TK_PARENTHESIS_CLOSE) {
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
_set_error("Expected ')' in hint.");
return;
}
@@ -3495,14 +3523,14 @@ void GDParser::_parse_class(ClassNode *p_class) {
}
// range
- if (tokenizer->get_token() == GDTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "EXP") {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "EXP") {
current_export.hint = PROPERTY_HINT_EXP_RANGE;
tokenizer->advance();
- if (tokenizer->get_token() == GDTokenizer::TK_PARENTHESIS_CLOSE)
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_CLOSE)
break;
- else if (tokenizer->get_token() != GDTokenizer::TK_COMMA) {
+ else if (tokenizer->get_token() != GDScriptTokenizer::TK_COMMA) {
_set_error("Expected ')' or ',' in exponential range hint.");
return;
}
@@ -3512,11 +3540,11 @@ void GDParser::_parse_class(ClassNode *p_class) {
float sign = 1.0;
- if (tokenizer->get_token() == GDTokenizer::TK_OP_SUB) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_OP_SUB) {
sign = -1;
tokenizer->advance();
}
- if (tokenizer->get_token() != GDTokenizer::TK_CONSTANT || !tokenizer->get_token_constant().is_num()) {
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_CONSTANT || !tokenizer->get_token_constant().is_num()) {
current_export = PropertyInfo();
_set_error("Expected a range in numeric hint.");
@@ -3526,12 +3554,12 @@ void GDParser::_parse_class(ClassNode *p_class) {
current_export.hint_string = rtos(sign * double(tokenizer->get_token_constant()));
tokenizer->advance();
- if (tokenizer->get_token() == GDTokenizer::TK_PARENTHESIS_CLOSE) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
current_export.hint_string = "0," + current_export.hint_string;
break;
}
- if (tokenizer->get_token() != GDTokenizer::TK_COMMA) {
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_COMMA) {
current_export = PropertyInfo();
_set_error("Expected ',' or ')' in numeric range hint.");
@@ -3541,12 +3569,12 @@ void GDParser::_parse_class(ClassNode *p_class) {
tokenizer->advance();
sign = 1.0;
- if (tokenizer->get_token() == GDTokenizer::TK_OP_SUB) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_OP_SUB) {
sign = -1;
tokenizer->advance();
}
- if (tokenizer->get_token() != GDTokenizer::TK_CONSTANT || !tokenizer->get_token_constant().is_num()) {
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_CONSTANT || !tokenizer->get_token_constant().is_num()) {
current_export = PropertyInfo();
_set_error("Expected a number as upper bound in numeric range hint.");
@@ -3556,10 +3584,10 @@ void GDParser::_parse_class(ClassNode *p_class) {
current_export.hint_string += "," + rtos(sign * double(tokenizer->get_token_constant()));
tokenizer->advance();
- if (tokenizer->get_token() == GDTokenizer::TK_PARENTHESIS_CLOSE)
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_CLOSE)
break;
- if (tokenizer->get_token() != GDTokenizer::TK_COMMA) {
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_COMMA) {
current_export = PropertyInfo();
_set_error("Expected ',' or ')' in numeric range hint.");
@@ -3568,12 +3596,12 @@ void GDParser::_parse_class(ClassNode *p_class) {
tokenizer->advance();
sign = 1.0;
- if (tokenizer->get_token() == GDTokenizer::TK_OP_SUB) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_OP_SUB) {
sign = -1;
tokenizer->advance();
}
- if (tokenizer->get_token() != GDTokenizer::TK_CONSTANT || !tokenizer->get_token_constant().is_num()) {
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_CONSTANT || !tokenizer->get_token_constant().is_num()) {
current_export = PropertyInfo();
_set_error("Expected a number as step in numeric range hint.");
@@ -3586,13 +3614,13 @@ void GDParser::_parse_class(ClassNode *p_class) {
} break;
case Variant::STRING: {
- if (tokenizer->get_token() == GDTokenizer::TK_CONSTANT && tokenizer->get_token_constant().get_type() == Variant::STRING) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_CONSTANT && tokenizer->get_token_constant().get_type() == Variant::STRING) {
//enumeration
current_export.hint = PROPERTY_HINT_ENUM;
bool first = true;
while (true) {
- if (tokenizer->get_token() != GDTokenizer::TK_CONSTANT || tokenizer->get_token_constant().get_type() != Variant::STRING) {
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_CONSTANT || tokenizer->get_token_constant().get_type() != Variant::STRING) {
current_export = PropertyInfo();
_set_error("Expected a string constant in enumeration hint.");
@@ -3607,10 +3635,10 @@ void GDParser::_parse_class(ClassNode *p_class) {
current_export.hint_string += c.xml_escape();
tokenizer->advance();
- if (tokenizer->get_token() == GDTokenizer::TK_PARENTHESIS_CLOSE)
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_CLOSE)
break;
- if (tokenizer->get_token() != GDTokenizer::TK_COMMA) {
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_COMMA) {
current_export = PropertyInfo();
_set_error("Expected ')' or ',' in enumeration hint.");
return;
@@ -3621,17 +3649,17 @@ void GDParser::_parse_class(ClassNode *p_class) {
break;
}
- if (tokenizer->get_token() == GDTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "DIR") {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "DIR") {
tokenizer->advance();
- if (tokenizer->get_token() == GDTokenizer::TK_PARENTHESIS_CLOSE)
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_CLOSE)
current_export.hint = PROPERTY_HINT_DIR;
- else if (tokenizer->get_token() == GDTokenizer::TK_COMMA) {
+ else if (tokenizer->get_token() == GDScriptTokenizer::TK_COMMA) {
tokenizer->advance();
- if (tokenizer->get_token() != GDTokenizer::TK_IDENTIFIER || !(tokenizer->get_token_identifier() == "GLOBAL")) {
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_IDENTIFIER || !(tokenizer->get_token_identifier() == "GLOBAL")) {
_set_error("Expected 'GLOBAL' after comma in directory hint.");
return;
}
@@ -3642,7 +3670,7 @@ void GDParser::_parse_class(ClassNode *p_class) {
current_export.hint = PROPERTY_HINT_GLOBAL_DIR;
tokenizer->advance();
- if (tokenizer->get_token() != GDTokenizer::TK_PARENTHESIS_CLOSE) {
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
_set_error("Expected ')' in hint.");
return;
}
@@ -3653,16 +3681,16 @@ void GDParser::_parse_class(ClassNode *p_class) {
break;
}
- if (tokenizer->get_token() == GDTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "FILE") {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "FILE") {
current_export.hint = PROPERTY_HINT_FILE;
tokenizer->advance();
- if (tokenizer->get_token() == GDTokenizer::TK_COMMA) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_COMMA) {
tokenizer->advance();
- if (tokenizer->get_token() == GDTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "GLOBAL") {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "GLOBAL") {
if (!p_class->tool) {
_set_error("Global filesystem hints may only be used in tool scripts.");
@@ -3671,9 +3699,9 @@ void GDParser::_parse_class(ClassNode *p_class) {
current_export.hint = PROPERTY_HINT_GLOBAL_FILE;
tokenizer->advance();
- if (tokenizer->get_token() == GDTokenizer::TK_PARENTHESIS_CLOSE)
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_CLOSE)
break;
- else if (tokenizer->get_token() == GDTokenizer::TK_COMMA)
+ else if (tokenizer->get_token() == GDScriptTokenizer::TK_COMMA)
tokenizer->advance();
else {
_set_error("Expected ')' or ',' in hint.");
@@ -3681,7 +3709,7 @@ void GDParser::_parse_class(ClassNode *p_class) {
}
}
- if (tokenizer->get_token() != GDTokenizer::TK_CONSTANT || tokenizer->get_token_constant().get_type() != Variant::STRING) {
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_CONSTANT || tokenizer->get_token_constant().get_type() != Variant::STRING) {
if (current_export.hint == PROPERTY_HINT_GLOBAL_FILE)
_set_error("Expected string constant with filter");
@@ -3693,18 +3721,18 @@ void GDParser::_parse_class(ClassNode *p_class) {
tokenizer->advance();
}
- if (tokenizer->get_token() != GDTokenizer::TK_PARENTHESIS_CLOSE) {
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
_set_error("Expected ')' in hint.");
return;
}
break;
}
- if (tokenizer->get_token() == GDTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "MULTILINE") {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "MULTILINE") {
current_export.hint = PROPERTY_HINT_MULTILINE_TEXT;
tokenizer->advance();
- if (tokenizer->get_token() != GDTokenizer::TK_PARENTHESIS_CLOSE) {
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
_set_error("Expected ')' in hint.");
return;
}
@@ -3713,7 +3741,7 @@ void GDParser::_parse_class(ClassNode *p_class) {
} break;
case Variant::COLOR: {
- if (tokenizer->get_token() != GDTokenizer::TK_IDENTIFIER) {
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_IDENTIFIER) {
current_export = PropertyInfo();
_set_error("Color type hint expects RGB or RGBA as hints");
@@ -3749,25 +3777,85 @@ void GDParser::_parse_class(ClassNode *p_class) {
current_export.hint = PROPERTY_HINT_NONE;
}
- } else if (tokenizer->get_token() == GDTokenizer::TK_IDENTIFIER) {
+ } else {
- String identifier = tokenizer->get_token_identifier();
- if (!ClassDB::is_parent_class(identifier, "Resource")) {
+ parenthesis++;
+ Node *subexpr = _parse_and_reduce_expression(p_class, true, true);
+ if (!subexpr) {
+ if (_recover_from_completion()) {
+ break;
+ }
+ return;
+ }
+ parenthesis--;
+ if (subexpr->type != Node::TYPE_CONSTANT) {
current_export = PropertyInfo();
- _set_error("Export hint not a type or resource.");
+ _set_error("Expected a constant expression.");
}
- current_export.type = Variant::OBJECT;
- current_export.hint = PROPERTY_HINT_RESOURCE_TYPE;
- current_export.usage |= PROPERTY_USAGE_SCRIPT_VARIABLE;
+ Variant constant = static_cast<ConstantNode *>(subexpr)->value;
- current_export.hint_string = identifier;
+ if (constant.get_type() == Variant::OBJECT) {
+ GDScriptNativeClass *native_class = Object::cast_to<GDScriptNativeClass>(constant);
- tokenizer->advance();
+ if (native_class && ClassDB::is_parent_class(native_class->get_name(), "Resource")) {
+ current_export.type = Variant::OBJECT;
+ current_export.hint = PROPERTY_HINT_RESOURCE_TYPE;
+ current_export.usage |= PROPERTY_USAGE_SCRIPT_VARIABLE;
+
+ current_export.hint_string = native_class->get_name();
+
+ } else {
+ current_export = PropertyInfo();
+ _set_error("Export hint not a resource type.");
+ }
+ } else if (constant.get_type() == Variant::DICTIONARY) {
+ // Enumeration
+ bool is_flags = false;
+
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_COMMA) {
+ tokenizer->advance();
+
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "FLAGS") {
+ is_flags = true;
+ tokenizer->advance();
+ } else {
+ current_export = PropertyInfo();
+ _set_error("Expected 'FLAGS' after comma.");
+ }
+ }
+
+ current_export.type = Variant::INT;
+ current_export.hint = is_flags ? PROPERTY_HINT_FLAGS : PROPERTY_HINT_ENUM;
+ Dictionary enum_values = constant;
+
+ List<Variant> keys;
+ enum_values.get_key_list(&keys);
+
+ bool first = true;
+ for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
+ if (enum_values[E->get()].get_type() == Variant::INT) {
+ if (!first)
+ current_export.hint_string += ",";
+ else
+ first = false;
+
+ current_export.hint_string += E->get().operator String().camelcase_to_underscore(true).capitalize().xml_escape();
+ if (!is_flags) {
+ current_export.hint_string += ":";
+ current_export.hint_string += enum_values[E->get()].operator String().xml_escape();
+ }
+ }
+ }
+ } else {
+ current_export = PropertyInfo();
+ _set_error("Expected type for export.");
+ return;
+ }
}
- if (tokenizer->get_token() != GDTokenizer::TK_PARENTHESIS_CLOSE) {
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
current_export = PropertyInfo();
_set_error("Expected ')' or ',' after export hint.");
@@ -3777,7 +3865,7 @@ void GDParser::_parse_class(ClassNode *p_class) {
tokenizer->advance();
}
- if (tokenizer->get_token() != GDTokenizer::TK_PR_VAR && tokenizer->get_token() != GDTokenizer::TK_PR_ONREADY && tokenizer->get_token() != GDTokenizer::TK_PR_REMOTE && tokenizer->get_token() != GDTokenizer::TK_PR_MASTER && tokenizer->get_token() != GDTokenizer::TK_PR_SLAVE && tokenizer->get_token() != GDTokenizer::TK_PR_SYNC) {
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_PR_VAR && tokenizer->get_token() != GDScriptTokenizer::TK_PR_ONREADY && tokenizer->get_token() != GDScriptTokenizer::TK_PR_REMOTE && tokenizer->get_token() != GDScriptTokenizer::TK_PR_MASTER && tokenizer->get_token() != GDScriptTokenizer::TK_PR_SLAVE && tokenizer->get_token() != GDScriptTokenizer::TK_PR_SYNC) {
current_export = PropertyInfo();
_set_error("Expected 'var', 'onready', 'remote', 'master', 'slave' or 'sync'.");
@@ -3786,29 +3874,29 @@ void GDParser::_parse_class(ClassNode *p_class) {
continue;
} break;
- case GDTokenizer::TK_PR_ONREADY: {
+ case GDScriptTokenizer::TK_PR_ONREADY: {
//may be fallthrough from export, ignore if so
tokenizer->advance();
- if (tokenizer->get_token() != GDTokenizer::TK_PR_VAR) {
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_PR_VAR) {
_set_error("Expected 'var'.");
return;
}
continue;
} break;
- case GDTokenizer::TK_PR_REMOTE: {
+ case GDScriptTokenizer::TK_PR_REMOTE: {
//may be fallthrough from export, ignore if so
tokenizer->advance();
if (current_export.type) {
- if (tokenizer->get_token() != GDTokenizer::TK_PR_VAR) {
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_PR_VAR) {
_set_error("Expected 'var'.");
return;
}
} else {
- if (tokenizer->get_token() != GDTokenizer::TK_PR_VAR && tokenizer->get_token() != GDTokenizer::TK_PR_FUNCTION) {
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_PR_VAR && tokenizer->get_token() != GDScriptTokenizer::TK_PR_FUNCTION) {
_set_error("Expected 'var' or 'func'.");
return;
}
@@ -3817,18 +3905,18 @@ void GDParser::_parse_class(ClassNode *p_class) {
continue;
} break;
- case GDTokenizer::TK_PR_MASTER: {
+ case GDScriptTokenizer::TK_PR_MASTER: {
//may be fallthrough from export, ignore if so
tokenizer->advance();
if (current_export.type) {
- if (tokenizer->get_token() != GDTokenizer::TK_PR_VAR) {
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_PR_VAR) {
_set_error("Expected 'var'.");
return;
}
} else {
- if (tokenizer->get_token() != GDTokenizer::TK_PR_VAR && tokenizer->get_token() != GDTokenizer::TK_PR_FUNCTION) {
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_PR_VAR && tokenizer->get_token() != GDScriptTokenizer::TK_PR_FUNCTION) {
_set_error("Expected 'var' or 'func'.");
return;
}
@@ -3837,18 +3925,18 @@ void GDParser::_parse_class(ClassNode *p_class) {
rpc_mode = ScriptInstance::RPC_MODE_MASTER;
continue;
} break;
- case GDTokenizer::TK_PR_SLAVE: {
+ case GDScriptTokenizer::TK_PR_SLAVE: {
//may be fallthrough from export, ignore if so
tokenizer->advance();
if (current_export.type) {
- if (tokenizer->get_token() != GDTokenizer::TK_PR_VAR) {
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_PR_VAR) {
_set_error("Expected 'var'.");
return;
}
} else {
- if (tokenizer->get_token() != GDTokenizer::TK_PR_VAR && tokenizer->get_token() != GDTokenizer::TK_PR_FUNCTION) {
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_PR_VAR && tokenizer->get_token() != GDScriptTokenizer::TK_PR_FUNCTION) {
_set_error("Expected 'var' or 'func'.");
return;
}
@@ -3857,11 +3945,11 @@ void GDParser::_parse_class(ClassNode *p_class) {
rpc_mode = ScriptInstance::RPC_MODE_SLAVE;
continue;
} break;
- case GDTokenizer::TK_PR_SYNC: {
+ case GDScriptTokenizer::TK_PR_SYNC: {
//may be fallthrough from export, ignore if so
tokenizer->advance();
- if (tokenizer->get_token() != GDTokenizer::TK_PR_VAR && tokenizer->get_token() != GDTokenizer::TK_PR_FUNCTION) {
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_PR_VAR && tokenizer->get_token() != GDScriptTokenizer::TK_PR_FUNCTION) {
if (current_export.type)
_set_error("Expected 'var'.");
else
@@ -3872,17 +3960,17 @@ void GDParser::_parse_class(ClassNode *p_class) {
rpc_mode = ScriptInstance::RPC_MODE_SYNC;
continue;
} break;
- case GDTokenizer::TK_PR_VAR: {
+ case GDScriptTokenizer::TK_PR_VAR: {
//variale declaration and (eventual) initialization
ClassNode::Member member;
- bool autoexport = tokenizer->get_token(-1) == GDTokenizer::TK_PR_EXPORT;
+ bool autoexport = tokenizer->get_token(-1) == GDScriptTokenizer::TK_PR_EXPORT;
if (current_export.type != Variant::NIL) {
member._export = current_export;
current_export = PropertyInfo();
}
- bool onready = tokenizer->get_token(-1) == GDTokenizer::TK_PR_ONREADY;
+ bool onready = tokenizer->get_token(-1) == GDScriptTokenizer::TK_PR_ONREADY;
tokenizer->advance();
if (!tokenizer->is_token_literal(0, true)) {
@@ -3901,7 +3989,7 @@ void GDParser::_parse_class(ClassNode *p_class) {
rpc_mode = ScriptInstance::RPC_MODE_DISABLED;
- if (tokenizer->get_token() == GDTokenizer::TK_OP_ASSIGN) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_OP_ASSIGN) {
#ifdef DEBUG_ENABLED
int line = tokenizer->get_token_line();
@@ -4009,11 +4097,11 @@ void GDParser::_parse_class(ClassNode *p_class) {
}
}
- if (tokenizer->get_token() == GDTokenizer::TK_PR_SETGET) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_PR_SETGET) {
tokenizer->advance();
- if (tokenizer->get_token() != GDTokenizer::TK_COMMA) {
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_COMMA) {
//just comma means using only getter
if (!tokenizer->is_token_literal()) {
_set_error("Expected identifier for setter function after 'setget'.");
@@ -4024,7 +4112,7 @@ void GDParser::_parse_class(ClassNode *p_class) {
tokenizer->advance();
}
- if (tokenizer->get_token() == GDTokenizer::TK_COMMA) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_COMMA) {
//there is a getter
tokenizer->advance();
@@ -4044,7 +4132,7 @@ void GDParser::_parse_class(ClassNode *p_class) {
return;
}
} break;
- case GDTokenizer::TK_PR_CONST: {
+ case GDScriptTokenizer::TK_PR_CONST: {
//variale declaration and (eventual) initialization
ClassNode::Constant constant;
@@ -4059,7 +4147,7 @@ void GDParser::_parse_class(ClassNode *p_class) {
constant.identifier = tokenizer->get_token_literal();
tokenizer->advance();
- if (tokenizer->get_token() != GDTokenizer::TK_OP_ASSIGN) {
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_OP_ASSIGN) {
_set_error("Constant expects assignment.");
return;
}
@@ -4087,7 +4175,7 @@ void GDParser::_parse_class(ClassNode *p_class) {
}
} break;
- case GDTokenizer::TK_PR_ENUM: {
+ case GDScriptTokenizer::TK_PR_ENUM: {
//mutiple constant declarations..
int last_assign = -1; // Incremented by 1 right before the assingment.
@@ -4099,26 +4187,26 @@ void GDParser::_parse_class(ClassNode *p_class) {
enum_name = tokenizer->get_token_literal();
tokenizer->advance();
}
- if (tokenizer->get_token() != GDTokenizer::TK_CURLY_BRACKET_OPEN) {
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_CURLY_BRACKET_OPEN) {
_set_error("Expected '{' in enum declaration");
return;
}
tokenizer->advance();
while (true) {
- if (tokenizer->get_token() == GDTokenizer::TK_NEWLINE) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_NEWLINE) {
tokenizer->advance(); // Ignore newlines
- } else if (tokenizer->get_token() == GDTokenizer::TK_CURLY_BRACKET_CLOSE) {
+ } else if (tokenizer->get_token() == GDScriptTokenizer::TK_CURLY_BRACKET_CLOSE) {
tokenizer->advance();
break; // End of enum
} else if (!tokenizer->is_token_literal(0, true)) {
- if (tokenizer->get_token() == GDTokenizer::TK_EOF) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_EOF) {
_set_error("Unexpected end of file.");
} else {
- _set_error(String("Unexpected ") + GDTokenizer::get_token_name(tokenizer->get_token()) + ", expected identifier");
+ _set_error(String("Unexpected ") + GDScriptTokenizer::get_token_name(tokenizer->get_token()) + ", expected identifier");
}
return;
@@ -4129,7 +4217,7 @@ void GDParser::_parse_class(ClassNode *p_class) {
tokenizer->advance();
- if (tokenizer->get_token() == GDTokenizer::TK_OP_ASSIGN) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_OP_ASSIGN) {
tokenizer->advance();
Node *subexpr = _parse_and_reduce_expression(p_class, true, true);
@@ -4161,7 +4249,7 @@ void GDParser::_parse_class(ClassNode *p_class) {
constant.expression = cn;
}
- if (tokenizer->get_token() == GDTokenizer::TK_COMMA) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_COMMA) {
tokenizer->advance();
}
@@ -4190,7 +4278,7 @@ void GDParser::_parse_class(ClassNode *p_class) {
} break;
- case GDTokenizer::TK_CONSTANT: {
+ case GDScriptTokenizer::TK_CONSTANT: {
if (tokenizer->get_token_constant().get_type() == Variant::STRING) {
tokenizer->advance();
// Ignore
@@ -4210,7 +4298,7 @@ void GDParser::_parse_class(ClassNode *p_class) {
}
}
-void GDParser::_set_error(const String &p_error, int p_line, int p_column) {
+void GDScriptParser::_set_error(const String &p_error, int p_line, int p_column) {
if (error_set)
return; //allow no further errors
@@ -4221,21 +4309,21 @@ void GDParser::_set_error(const String &p_error, int p_line, int p_column) {
error_set = true;
}
-String GDParser::get_error() const {
+String GDScriptParser::get_error() const {
return error;
}
-int GDParser::get_error_line() const {
+int GDScriptParser::get_error_line() const {
return error_line;
}
-int GDParser::get_error_column() const {
+int GDScriptParser::get_error_column() const {
return error_column;
}
-Error GDParser::_parse(const String &p_base_path) {
+Error GDScriptParser::_parse(const String &p_base_path) {
base_path = p_base_path;
@@ -4251,7 +4339,7 @@ Error GDParser::_parse(const String &p_base_path) {
_parse_class(main_class);
- if (tokenizer->get_token() == GDTokenizer::TK_ERROR) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_ERROR) {
error_set = false;
_set_error("Parse Error: " + tokenizer->get_token_error());
}
@@ -4263,7 +4351,7 @@ Error GDParser::_parse(const String &p_base_path) {
return OK;
}
-Error GDParser::parse_bytecode(const Vector<uint8_t> &p_bytecode, const String &p_base_path, const String &p_self_path) {
+Error GDScriptParser::parse_bytecode(const Vector<uint8_t> &p_bytecode, const String &p_base_path, const String &p_self_path) {
for_completion = false;
validating = false;
@@ -4278,7 +4366,7 @@ Error GDParser::parse_bytecode(const Vector<uint8_t> &p_bytecode, const String &
current_function = NULL;
self_path = p_self_path;
- GDTokenizerBuffer *tb = memnew(GDTokenizerBuffer);
+ GDScriptTokenizerBuffer *tb = memnew(GDScriptTokenizerBuffer);
tb->set_code_buffer(p_bytecode);
tokenizer = tb;
Error ret = _parse(p_base_path);
@@ -4287,7 +4375,7 @@ Error GDParser::parse_bytecode(const Vector<uint8_t> &p_bytecode, const String &
return ret;
}
-Error GDParser::parse(const String &p_code, const String &p_base_path, bool p_just_validate, const String &p_self_path, bool p_for_completion) {
+Error GDScriptParser::parse(const String &p_code, const String &p_base_path, bool p_just_validate, const String &p_self_path, bool p_for_completion) {
completion_type = COMPLETION_NONE;
completion_node = NULL;
@@ -4301,7 +4389,7 @@ Error GDParser::parse(const String &p_code, const String &p_base_path, bool p_ju
current_function = NULL;
self_path = p_self_path;
- GDTokenizerText *tt = memnew(GDTokenizerText);
+ GDScriptTokenizerText *tt = memnew(GDScriptTokenizerText);
tt->set_code(p_code);
validating = p_just_validate;
@@ -4313,17 +4401,17 @@ Error GDParser::parse(const String &p_code, const String &p_base_path, bool p_ju
return ret;
}
-bool GDParser::is_tool_script() const {
+bool GDScriptParser::is_tool_script() const {
return (head && head->type == Node::TYPE_CLASS && static_cast<const ClassNode *>(head)->tool);
}
-const GDParser::Node *GDParser::get_parse_tree() const {
+const GDScriptParser::Node *GDScriptParser::get_parse_tree() const {
return head;
}
-void GDParser::clear() {
+void GDScriptParser::clear() {
while (list) {
@@ -4361,57 +4449,57 @@ void GDParser::clear() {
error = "";
}
-GDParser::CompletionType GDParser::get_completion_type() {
+GDScriptParser::CompletionType GDScriptParser::get_completion_type() {
return completion_type;
}
-StringName GDParser::get_completion_cursor() {
+StringName GDScriptParser::get_completion_cursor() {
return completion_cursor;
}
-int GDParser::get_completion_line() {
+int GDScriptParser::get_completion_line() {
return completion_line;
}
-Variant::Type GDParser::get_completion_built_in_constant() {
+Variant::Type GDScriptParser::get_completion_built_in_constant() {
return completion_built_in_constant;
}
-GDParser::Node *GDParser::get_completion_node() {
+GDScriptParser::Node *GDScriptParser::get_completion_node() {
return completion_node;
}
-GDParser::BlockNode *GDParser::get_completion_block() {
+GDScriptParser::BlockNode *GDScriptParser::get_completion_block() {
return completion_block;
}
-GDParser::ClassNode *GDParser::get_completion_class() {
+GDScriptParser::ClassNode *GDScriptParser::get_completion_class() {
return completion_class;
}
-GDParser::FunctionNode *GDParser::get_completion_function() {
+GDScriptParser::FunctionNode *GDScriptParser::get_completion_function() {
return completion_function;
}
-int GDParser::get_completion_argument_index() {
+int GDScriptParser::get_completion_argument_index() {
return completion_argument;
}
-int GDParser::get_completion_identifier_is_function() {
+int GDScriptParser::get_completion_identifier_is_function() {
return completion_ident_is_call;
}
-GDParser::GDParser() {
+GDScriptParser::GDScriptParser() {
head = NULL;
list = NULL;
@@ -4420,7 +4508,7 @@ GDParser::GDParser() {
clear();
}
-GDParser::~GDParser() {
+GDScriptParser::~GDScriptParser() {
clear();
}
diff --git a/modules/gdscript/gd_parser.h b/modules/gdscript/gdscript_parser.h
index 7e88fd9746..3c9c5ea02c 100644
--- a/modules/gdscript/gd_parser.h
+++ b/modules/gdscript/gdscript_parser.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* gd_parser.h */
+/* gdscript_parser.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -27,16 +27,16 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef GD_PARSER_H
-#define GD_PARSER_H
+#ifndef GDSCRIPT_PARSER_H
+#define GDSCRIPT_PARSER_H
-#include "gd_functions.h"
-#include "gd_tokenizer.h"
+#include "gdscript_functions.h"
+#include "gdscript_tokenizer.h"
#include "map.h"
#include "object.h"
#include "script_language.h"
-class GDParser {
+class GDScriptParser {
public:
struct Node {
@@ -166,7 +166,7 @@ public:
TypeNode() { type = TYPE_TYPE; }
};
struct BuiltInFunctionNode : public Node {
- GDFunctions::Function function;
+ GDScriptFunctions::Function function;
BuiltInFunctionNode() { type = TYPE_BUILT_IN_FUNCTION; }
};
@@ -448,7 +448,7 @@ public:
};
private:
- GDTokenizer *tokenizer;
+ GDScriptTokenizer *tokenizer;
Node *head;
Node *list;
@@ -540,8 +540,8 @@ public:
int get_completion_identifier_is_function();
void clear();
- GDParser();
- ~GDParser();
+ GDScriptParser();
+ ~GDScriptParser();
};
-#endif // PARSER_H
+#endif // GDSCRIPT_PARSER_H
diff --git a/modules/gdscript/gd_tokenizer.cpp b/modules/gdscript/gdscript_tokenizer.cpp
index 5f85158232..e3a0af8ee6 100644
--- a/modules/gdscript/gd_tokenizer.cpp
+++ b/modules/gdscript/gdscript_tokenizer.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* gd_tokenizer.cpp */
+/* gdscript_tokenizer.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -27,14 +27,14 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "gd_tokenizer.h"
+#include "gdscript_tokenizer.h"
-#include "gd_functions.h"
+#include "gdscript_functions.h"
#include "io/marshalls.h"
#include "map.h"
#include "print_string.h"
-const char *GDTokenizer::token_names[TK_MAX] = {
+const char *GDScriptTokenizer::token_names[TK_MAX] = {
"Empty",
"Identifier",
"Constant",
@@ -123,6 +123,7 @@ const char *GDTokenizer::token_names[TK_MAX] = {
"'$'",
"'\\n'",
"PI",
+ "TAU",
"_",
"INF",
"NAN",
@@ -147,7 +148,7 @@ static const _bit _type_list[] = {
{ Variant::RECT2, "Rect2" },
{ Variant::TRANSFORM2D, "Transform2D" },
{ Variant::VECTOR3, "Vector3" },
- { Variant::RECT3, "Rect3" },
+ { Variant::AABB, "AABB" },
{ Variant::PLANE, "Plane" },
{ Variant::QUAT, "Quat" },
{ Variant::BASIS, "Basis" },
@@ -169,67 +170,68 @@ static const _bit _type_list[] = {
};
struct _kws {
- GDTokenizer::Token token;
+ GDScriptTokenizer::Token token;
const char *text;
};
static const _kws _keyword_list[] = {
//ops
- { GDTokenizer::TK_OP_IN, "in" },
- { GDTokenizer::TK_OP_NOT, "not" },
- { GDTokenizer::TK_OP_OR, "or" },
- { GDTokenizer::TK_OP_AND, "and" },
+ { GDScriptTokenizer::TK_OP_IN, "in" },
+ { GDScriptTokenizer::TK_OP_NOT, "not" },
+ { GDScriptTokenizer::TK_OP_OR, "or" },
+ { GDScriptTokenizer::TK_OP_AND, "and" },
//func
- { GDTokenizer::TK_PR_FUNCTION, "func" },
- { GDTokenizer::TK_PR_CLASS, "class" },
- { GDTokenizer::TK_PR_EXTENDS, "extends" },
- { GDTokenizer::TK_PR_IS, "is" },
- { GDTokenizer::TK_PR_ONREADY, "onready" },
- { GDTokenizer::TK_PR_TOOL, "tool" },
- { GDTokenizer::TK_PR_STATIC, "static" },
- { GDTokenizer::TK_PR_EXPORT, "export" },
- { GDTokenizer::TK_PR_SETGET, "setget" },
- { GDTokenizer::TK_PR_VAR, "var" },
- { GDTokenizer::TK_PR_PRELOAD, "preload" },
- { GDTokenizer::TK_PR_ASSERT, "assert" },
- { GDTokenizer::TK_PR_YIELD, "yield" },
- { GDTokenizer::TK_PR_SIGNAL, "signal" },
- { GDTokenizer::TK_PR_BREAKPOINT, "breakpoint" },
- { GDTokenizer::TK_PR_REMOTE, "remote" },
- { GDTokenizer::TK_PR_MASTER, "master" },
- { GDTokenizer::TK_PR_SLAVE, "slave" },
- { GDTokenizer::TK_PR_SYNC, "sync" },
- { GDTokenizer::TK_PR_CONST, "const" },
- { GDTokenizer::TK_PR_ENUM, "enum" },
+ { GDScriptTokenizer::TK_PR_FUNCTION, "func" },
+ { GDScriptTokenizer::TK_PR_CLASS, "class" },
+ { GDScriptTokenizer::TK_PR_EXTENDS, "extends" },
+ { GDScriptTokenizer::TK_PR_IS, "is" },
+ { GDScriptTokenizer::TK_PR_ONREADY, "onready" },
+ { GDScriptTokenizer::TK_PR_TOOL, "tool" },
+ { GDScriptTokenizer::TK_PR_STATIC, "static" },
+ { GDScriptTokenizer::TK_PR_EXPORT, "export" },
+ { GDScriptTokenizer::TK_PR_SETGET, "setget" },
+ { GDScriptTokenizer::TK_PR_VAR, "var" },
+ { GDScriptTokenizer::TK_PR_PRELOAD, "preload" },
+ { GDScriptTokenizer::TK_PR_ASSERT, "assert" },
+ { GDScriptTokenizer::TK_PR_YIELD, "yield" },
+ { GDScriptTokenizer::TK_PR_SIGNAL, "signal" },
+ { GDScriptTokenizer::TK_PR_BREAKPOINT, "breakpoint" },
+ { GDScriptTokenizer::TK_PR_REMOTE, "remote" },
+ { GDScriptTokenizer::TK_PR_MASTER, "master" },
+ { GDScriptTokenizer::TK_PR_SLAVE, "slave" },
+ { GDScriptTokenizer::TK_PR_SYNC, "sync" },
+ { GDScriptTokenizer::TK_PR_CONST, "const" },
+ { GDScriptTokenizer::TK_PR_ENUM, "enum" },
//controlflow
- { GDTokenizer::TK_CF_IF, "if" },
- { GDTokenizer::TK_CF_ELIF, "elif" },
- { GDTokenizer::TK_CF_ELSE, "else" },
- { GDTokenizer::TK_CF_FOR, "for" },
- { GDTokenizer::TK_CF_WHILE, "while" },
- { GDTokenizer::TK_CF_DO, "do" },
- { GDTokenizer::TK_CF_SWITCH, "switch" },
- { GDTokenizer::TK_CF_CASE, "case" },
- { GDTokenizer::TK_CF_BREAK, "break" },
- { GDTokenizer::TK_CF_CONTINUE, "continue" },
- { GDTokenizer::TK_CF_RETURN, "return" },
- { GDTokenizer::TK_CF_MATCH, "match" },
- { GDTokenizer::TK_CF_PASS, "pass" },
- { GDTokenizer::TK_SELF, "self" },
- { GDTokenizer::TK_CONST_PI, "PI" },
- { GDTokenizer::TK_WILDCARD, "_" },
- { GDTokenizer::TK_CONST_INF, "INF" },
- { GDTokenizer::TK_CONST_NAN, "NAN" },
- { GDTokenizer::TK_ERROR, NULL }
+ { GDScriptTokenizer::TK_CF_IF, "if" },
+ { GDScriptTokenizer::TK_CF_ELIF, "elif" },
+ { GDScriptTokenizer::TK_CF_ELSE, "else" },
+ { GDScriptTokenizer::TK_CF_FOR, "for" },
+ { GDScriptTokenizer::TK_CF_WHILE, "while" },
+ { GDScriptTokenizer::TK_CF_DO, "do" },
+ { GDScriptTokenizer::TK_CF_SWITCH, "switch" },
+ { GDScriptTokenizer::TK_CF_CASE, "case" },
+ { GDScriptTokenizer::TK_CF_BREAK, "break" },
+ { GDScriptTokenizer::TK_CF_CONTINUE, "continue" },
+ { GDScriptTokenizer::TK_CF_RETURN, "return" },
+ { GDScriptTokenizer::TK_CF_MATCH, "match" },
+ { GDScriptTokenizer::TK_CF_PASS, "pass" },
+ { GDScriptTokenizer::TK_SELF, "self" },
+ { GDScriptTokenizer::TK_CONST_PI, "PI" },
+ { GDScriptTokenizer::TK_CONST_TAU, "TAU" },
+ { GDScriptTokenizer::TK_WILDCARD, "_" },
+ { GDScriptTokenizer::TK_CONST_INF, "INF" },
+ { GDScriptTokenizer::TK_CONST_NAN, "NAN" },
+ { GDScriptTokenizer::TK_ERROR, NULL }
};
-const char *GDTokenizer::get_token_name(Token p_token) {
+const char *GDScriptTokenizer::get_token_name(Token p_token) {
ERR_FAIL_INDEX_V(p_token, TK_MAX, "<error>");
return token_names[p_token];
}
-bool GDTokenizer::is_token_literal(int p_offset, bool variable_safe) const {
+bool GDScriptTokenizer::is_token_literal(int p_offset, bool variable_safe) const {
switch (get_token(p_offset)) {
// Can always be literal:
case TK_IDENTIFIER:
@@ -251,9 +253,9 @@ bool GDTokenizer::is_token_literal(int p_offset, bool variable_safe) const {
case TK_BUILT_IN_FUNC:
case TK_OP_IN:
- //case TK_OP_NOT:
- //case TK_OP_OR:
- //case TK_OP_AND:
+ //case TK_OP_NOT:
+ //case TK_OP_OR:
+ //case TK_OP_AND:
case TK_PR_CLASS:
case TK_PR_CONST:
@@ -280,6 +282,7 @@ bool GDTokenizer::is_token_literal(int p_offset, bool variable_safe) const {
case TK_CF_PASS:
case TK_SELF:
case TK_CONST_PI:
+ case TK_CONST_TAU:
case TK_WILDCARD:
case TK_CONST_INF:
case TK_CONST_NAN:
@@ -300,7 +303,7 @@ bool GDTokenizer::is_token_literal(int p_offset, bool variable_safe) const {
}
}
-StringName GDTokenizer::get_token_literal(int p_offset) const {
+StringName GDScriptTokenizer::get_token_literal(int p_offset) const {
Token token = get_token(p_offset);
switch (token) {
case TK_IDENTIFIER:
@@ -317,7 +320,7 @@ StringName GDTokenizer::get_token_literal(int p_offset) const {
}
} break; // Shouldn't get here, stuff happens
case TK_BUILT_IN_FUNC:
- return GDFunctions::get_func_name(get_token_built_in_func(p_offset));
+ return GDScriptFunctions::get_func_name(get_token_built_in_func(p_offset));
case TK_CONSTANT: {
const Variant value = get_token_constant(p_offset);
@@ -362,7 +365,7 @@ static bool _is_hex(CharType c) {
return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
}
-void GDTokenizerText::_make_token(Token p_type) {
+void GDScriptTokenizerText::_make_token(Token p_type) {
TokenData &tk = tk_rb[tk_rb_pos];
@@ -372,7 +375,7 @@ void GDTokenizerText::_make_token(Token p_type) {
tk_rb_pos = (tk_rb_pos + 1) % TK_RB_SIZE;
}
-void GDTokenizerText::_make_identifier(const StringName &p_identifier) {
+void GDScriptTokenizerText::_make_identifier(const StringName &p_identifier) {
TokenData &tk = tk_rb[tk_rb_pos];
@@ -384,7 +387,7 @@ void GDTokenizerText::_make_identifier(const StringName &p_identifier) {
tk_rb_pos = (tk_rb_pos + 1) % TK_RB_SIZE;
}
-void GDTokenizerText::_make_built_in_func(GDFunctions::Function p_func) {
+void GDScriptTokenizerText::_make_built_in_func(GDScriptFunctions::Function p_func) {
TokenData &tk = tk_rb[tk_rb_pos];
@@ -395,7 +398,7 @@ void GDTokenizerText::_make_built_in_func(GDFunctions::Function p_func) {
tk_rb_pos = (tk_rb_pos + 1) % TK_RB_SIZE;
}
-void GDTokenizerText::_make_constant(const Variant &p_constant) {
+void GDScriptTokenizerText::_make_constant(const Variant &p_constant) {
TokenData &tk = tk_rb[tk_rb_pos];
@@ -407,7 +410,7 @@ void GDTokenizerText::_make_constant(const Variant &p_constant) {
tk_rb_pos = (tk_rb_pos + 1) % TK_RB_SIZE;
}
-void GDTokenizerText::_make_type(const Variant::Type &p_type) {
+void GDScriptTokenizerText::_make_type(const Variant::Type &p_type) {
TokenData &tk = tk_rb[tk_rb_pos];
@@ -419,7 +422,7 @@ void GDTokenizerText::_make_type(const Variant::Type &p_type) {
tk_rb_pos = (tk_rb_pos + 1) % TK_RB_SIZE;
}
-void GDTokenizerText::_make_error(const String &p_error) {
+void GDScriptTokenizerText::_make_error(const String &p_error) {
error_flag = true;
last_error = p_error;
@@ -432,7 +435,7 @@ void GDTokenizerText::_make_error(const String &p_error) {
tk_rb_pos = (tk_rb_pos + 1) % TK_RB_SIZE;
}
-void GDTokenizerText::_make_newline(int p_spaces) {
+void GDScriptTokenizerText::_make_newline(int p_spaces) {
TokenData &tk = tk_rb[tk_rb_pos];
tk.type = TK_NEWLINE;
@@ -442,7 +445,7 @@ void GDTokenizerText::_make_newline(int p_spaces) {
tk_rb_pos = (tk_rb_pos + 1) % TK_RB_SIZE;
}
-void GDTokenizerText::_advance() {
+void GDScriptTokenizerText::_advance() {
if (error_flag) {
//parser broke
@@ -882,6 +885,9 @@ void GDTokenizerText::_advance() {
return;
}
sign_found = true;
+ } else if (GETCHAR(i) == '_') {
+ i++;
+ continue; // Included for readability, shouldn't be a part of the string
} else
break;
@@ -894,7 +900,7 @@ void GDTokenizerText::_advance() {
return;
}
- INCPOS(str.length());
+ INCPOS(i);
if (hexa_found) {
int64_t val = str.hex_to_int64();
_make_constant(val);
@@ -960,11 +966,11 @@ void GDTokenizerText::_advance() {
//built in func?
- for (int i = 0; i < GDFunctions::FUNC_MAX; i++) {
+ for (int i = 0; i < GDScriptFunctions::FUNC_MAX; i++) {
- if (str == GDFunctions::get_func_name(GDFunctions::Function(i))) {
+ if (str == GDScriptFunctions::get_func_name(GDScriptFunctions::Function(i))) {
- _make_built_in_func(GDFunctions::Function(i));
+ _make_built_in_func(GDScriptFunctions::Function(i));
found = true;
break;
}
@@ -1010,7 +1016,7 @@ void GDTokenizerText::_advance() {
}
}
-void GDTokenizerText::set_code(const String &p_code) {
+void GDScriptTokenizerText::set_code(const String &p_code) {
code = p_code;
len = p_code.length();
@@ -1029,7 +1035,7 @@ void GDTokenizerText::set_code(const String &p_code) {
_advance();
}
-GDTokenizerText::Token GDTokenizerText::get_token(int p_offset) const {
+GDScriptTokenizerText::Token GDScriptTokenizerText::get_token(int p_offset) const {
ERR_FAIL_COND_V(p_offset <= -MAX_LOOKAHEAD, TK_ERROR);
ERR_FAIL_COND_V(p_offset >= MAX_LOOKAHEAD, TK_ERROR);
@@ -1037,7 +1043,7 @@ GDTokenizerText::Token GDTokenizerText::get_token(int p_offset) const {
return tk_rb[ofs].type;
}
-int GDTokenizerText::get_token_line(int p_offset) const {
+int GDScriptTokenizerText::get_token_line(int p_offset) const {
ERR_FAIL_COND_V(p_offset <= -MAX_LOOKAHEAD, -1);
ERR_FAIL_COND_V(p_offset >= MAX_LOOKAHEAD, -1);
@@ -1045,7 +1051,7 @@ int GDTokenizerText::get_token_line(int p_offset) const {
return tk_rb[ofs].line;
}
-int GDTokenizerText::get_token_column(int p_offset) const {
+int GDScriptTokenizerText::get_token_column(int p_offset) const {
ERR_FAIL_COND_V(p_offset <= -MAX_LOOKAHEAD, -1);
ERR_FAIL_COND_V(p_offset >= MAX_LOOKAHEAD, -1);
@@ -1053,7 +1059,7 @@ int GDTokenizerText::get_token_column(int p_offset) const {
return tk_rb[ofs].col;
}
-const Variant &GDTokenizerText::get_token_constant(int p_offset) const {
+const Variant &GDScriptTokenizerText::get_token_constant(int p_offset) const {
ERR_FAIL_COND_V(p_offset <= -MAX_LOOKAHEAD, tk_rb[0].constant);
ERR_FAIL_COND_V(p_offset >= MAX_LOOKAHEAD, tk_rb[0].constant);
@@ -1062,7 +1068,7 @@ const Variant &GDTokenizerText::get_token_constant(int p_offset) const {
return tk_rb[ofs].constant;
}
-StringName GDTokenizerText::get_token_identifier(int p_offset) const {
+StringName GDScriptTokenizerText::get_token_identifier(int p_offset) const {
ERR_FAIL_COND_V(p_offset <= -MAX_LOOKAHEAD, StringName());
ERR_FAIL_COND_V(p_offset >= MAX_LOOKAHEAD, StringName());
@@ -1072,17 +1078,17 @@ StringName GDTokenizerText::get_token_identifier(int p_offset) const {
return tk_rb[ofs].identifier;
}
-GDFunctions::Function GDTokenizerText::get_token_built_in_func(int p_offset) const {
+GDScriptFunctions::Function GDScriptTokenizerText::get_token_built_in_func(int p_offset) const {
- ERR_FAIL_COND_V(p_offset <= -MAX_LOOKAHEAD, GDFunctions::FUNC_MAX);
- ERR_FAIL_COND_V(p_offset >= MAX_LOOKAHEAD, GDFunctions::FUNC_MAX);
+ ERR_FAIL_COND_V(p_offset <= -MAX_LOOKAHEAD, GDScriptFunctions::FUNC_MAX);
+ ERR_FAIL_COND_V(p_offset >= MAX_LOOKAHEAD, GDScriptFunctions::FUNC_MAX);
int ofs = (TK_RB_SIZE + tk_rb_pos + p_offset - MAX_LOOKAHEAD - 1) % TK_RB_SIZE;
- ERR_FAIL_COND_V(tk_rb[ofs].type != TK_BUILT_IN_FUNC, GDFunctions::FUNC_MAX);
+ ERR_FAIL_COND_V(tk_rb[ofs].type != TK_BUILT_IN_FUNC, GDScriptFunctions::FUNC_MAX);
return tk_rb[ofs].func;
}
-Variant::Type GDTokenizerText::get_token_type(int p_offset) const {
+Variant::Type GDScriptTokenizerText::get_token_type(int p_offset) const {
ERR_FAIL_COND_V(p_offset <= -MAX_LOOKAHEAD, Variant::NIL);
ERR_FAIL_COND_V(p_offset >= MAX_LOOKAHEAD, Variant::NIL);
@@ -1092,7 +1098,7 @@ Variant::Type GDTokenizerText::get_token_type(int p_offset) const {
return tk_rb[ofs].vtype;
}
-int GDTokenizerText::get_token_line_indent(int p_offset) const {
+int GDScriptTokenizerText::get_token_line_indent(int p_offset) const {
ERR_FAIL_COND_V(p_offset <= -MAX_LOOKAHEAD, 0);
ERR_FAIL_COND_V(p_offset >= MAX_LOOKAHEAD, 0);
@@ -1102,7 +1108,7 @@ int GDTokenizerText::get_token_line_indent(int p_offset) const {
return tk_rb[ofs].constant;
}
-String GDTokenizerText::get_token_error(int p_offset) const {
+String GDScriptTokenizerText::get_token_error(int p_offset) const {
ERR_FAIL_COND_V(p_offset <= -MAX_LOOKAHEAD, String());
ERR_FAIL_COND_V(p_offset >= MAX_LOOKAHEAD, String());
@@ -1112,18 +1118,18 @@ String GDTokenizerText::get_token_error(int p_offset) const {
return tk_rb[ofs].constant;
}
-void GDTokenizerText::advance(int p_amount) {
+void GDScriptTokenizerText::advance(int p_amount) {
ERR_FAIL_COND(p_amount <= 0);
for (int i = 0; i < p_amount; i++)
_advance();
}
-//////////////////////////////////////////////////////////////////////////////////////////////////////
+ //////////////////////////////////////////////////////////////////////////////////////////////////////
#define BYTECODE_VERSION 12
-Error GDTokenizerBuffer::set_code_buffer(const Vector<uint8_t> &p_buffer) {
+Error GDScriptTokenizerBuffer::set_code_buffer(const Vector<uint8_t> &p_buffer) {
const uint8_t *buf = p_buffer.ptr();
int total_len = p_buffer.size();
@@ -1211,7 +1217,7 @@ Error GDTokenizerBuffer::set_code_buffer(const Vector<uint8_t> &p_buffer) {
return OK;
}
-Vector<uint8_t> GDTokenizerBuffer::parse_code_string(const String &p_code) {
+Vector<uint8_t> GDScriptTokenizerBuffer::parse_code_string(const String &p_code) {
Vector<uint8_t> buf;
@@ -1220,7 +1226,7 @@ Vector<uint8_t> GDTokenizerBuffer::parse_code_string(const String &p_code) {
Map<uint32_t, int> line_map;
Vector<uint32_t> token_array;
- GDTokenizerText tt;
+ GDScriptTokenizerText tt;
tt.set_code(p_code);
int line = -1;
@@ -1369,17 +1375,17 @@ Vector<uint8_t> GDTokenizerBuffer::parse_code_string(const String &p_code) {
return buf;
}
-GDTokenizerBuffer::Token GDTokenizerBuffer::get_token(int p_offset) const {
+GDScriptTokenizerBuffer::Token GDScriptTokenizerBuffer::get_token(int p_offset) const {
int offset = token + p_offset;
if (offset < 0 || offset >= tokens.size())
return TK_EOF;
- return GDTokenizerBuffer::Token(tokens[offset] & TOKEN_MASK);
+ return GDScriptTokenizerBuffer::Token(tokens[offset] & TOKEN_MASK);
}
-StringName GDTokenizerBuffer::get_token_identifier(int p_offset) const {
+StringName GDScriptTokenizerBuffer::get_token_identifier(int p_offset) const {
int offset = token + p_offset;
@@ -1390,14 +1396,14 @@ StringName GDTokenizerBuffer::get_token_identifier(int p_offset) const {
return identifiers[identifier];
}
-GDFunctions::Function GDTokenizerBuffer::get_token_built_in_func(int p_offset) const {
+GDScriptFunctions::Function GDScriptTokenizerBuffer::get_token_built_in_func(int p_offset) const {
int offset = token + p_offset;
- ERR_FAIL_INDEX_V(offset, tokens.size(), GDFunctions::FUNC_MAX);
- return GDFunctions::Function(tokens[offset] >> TOKEN_BITS);
+ ERR_FAIL_INDEX_V(offset, tokens.size(), GDScriptFunctions::FUNC_MAX);
+ return GDScriptFunctions::Function(tokens[offset] >> TOKEN_BITS);
}
-Variant::Type GDTokenizerBuffer::get_token_type(int p_offset) const {
+Variant::Type GDScriptTokenizerBuffer::get_token_type(int p_offset) const {
int offset = token + p_offset;
ERR_FAIL_INDEX_V(offset, tokens.size(), Variant::NIL);
@@ -1405,7 +1411,7 @@ Variant::Type GDTokenizerBuffer::get_token_type(int p_offset) const {
return Variant::Type(tokens[offset] >> TOKEN_BITS);
}
-int GDTokenizerBuffer::get_token_line(int p_offset) const {
+int GDScriptTokenizerBuffer::get_token_line(int p_offset) const {
int offset = token + p_offset;
int pos = lines.find_nearest(offset);
@@ -1418,7 +1424,7 @@ int GDTokenizerBuffer::get_token_line(int p_offset) const {
uint32_t l = lines.getv(pos);
return l & TOKEN_LINE_MASK;
}
-int GDTokenizerBuffer::get_token_column(int p_offset) const {
+int GDScriptTokenizerBuffer::get_token_column(int p_offset) const {
int offset = token + p_offset;
int pos = lines.find_nearest(offset);
@@ -1430,13 +1436,13 @@ int GDTokenizerBuffer::get_token_column(int p_offset) const {
uint32_t l = lines.getv(pos);
return l >> TOKEN_LINE_BITS;
}
-int GDTokenizerBuffer::get_token_line_indent(int p_offset) const {
+int GDScriptTokenizerBuffer::get_token_line_indent(int p_offset) const {
int offset = token + p_offset;
ERR_FAIL_INDEX_V(offset, tokens.size(), 0);
return tokens[offset] >> TOKEN_BITS;
}
-const Variant &GDTokenizerBuffer::get_token_constant(int p_offset) const {
+const Variant &GDScriptTokenizerBuffer::get_token_constant(int p_offset) const {
int offset = token + p_offset;
ERR_FAIL_INDEX_V(offset, tokens.size(), nil);
@@ -1444,17 +1450,17 @@ const Variant &GDTokenizerBuffer::get_token_constant(int p_offset) const {
ERR_FAIL_INDEX_V(constant, (uint32_t)constants.size(), nil);
return constants[constant];
}
-String GDTokenizerBuffer::get_token_error(int p_offset) const {
+String GDScriptTokenizerBuffer::get_token_error(int p_offset) const {
ERR_FAIL_V(String());
}
-void GDTokenizerBuffer::advance(int p_amount) {
+void GDScriptTokenizerBuffer::advance(int p_amount) {
ERR_FAIL_INDEX(p_amount + token, tokens.size());
token += p_amount;
}
-GDTokenizerBuffer::GDTokenizerBuffer() {
+GDScriptTokenizerBuffer::GDScriptTokenizerBuffer() {
token = 0;
}
diff --git a/modules/gdscript/gd_tokenizer.h b/modules/gdscript/gdscript_tokenizer.h
index c935ce45a1..d19367177b 100644
--- a/modules/gdscript/gd_tokenizer.h
+++ b/modules/gdscript/gdscript_tokenizer.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* gd_tokenizer.h */
+/* gdscript_tokenizer.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -27,16 +27,16 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef GD_TOKENIZER_H
-#define GD_TOKENIZER_H
+#ifndef GDSCRIPT_TOKENIZER_H
+#define GDSCRIPT_TOKENIZER_H
-#include "gd_functions.h"
+#include "gdscript_functions.h"
#include "string_db.h"
#include "ustring.h"
#include "variant.h"
#include "vmap.h"
-class GDTokenizer {
+class GDScriptTokenizer {
public:
enum Token {
@@ -128,6 +128,7 @@ public:
TK_DOLLAR,
TK_NEWLINE,
TK_CONST_PI,
+ TK_CONST_TAU,
TK_WILDCARD,
TK_CONST_INF,
TK_CONST_NAN,
@@ -155,7 +156,7 @@ public:
virtual const Variant &get_token_constant(int p_offset = 0) const = 0;
virtual Token get_token(int p_offset = 0) const = 0;
virtual StringName get_token_identifier(int p_offset = 0) const = 0;
- virtual GDFunctions::Function get_token_built_in_func(int p_offset = 0) const = 0;
+ virtual GDScriptFunctions::Function get_token_built_in_func(int p_offset = 0) const = 0;
virtual Variant::Type get_token_type(int p_offset = 0) const = 0;
virtual int get_token_line(int p_offset = 0) const = 0;
virtual int get_token_column(int p_offset = 0) const = 0;
@@ -163,10 +164,10 @@ public:
virtual String get_token_error(int p_offset = 0) const = 0;
virtual void advance(int p_amount = 1) = 0;
- virtual ~GDTokenizer(){};
+ virtual ~GDScriptTokenizer(){};
};
-class GDTokenizerText : public GDTokenizer {
+class GDScriptTokenizerText : public GDScriptTokenizer {
enum {
MAX_LOOKAHEAD = 4,
@@ -180,7 +181,7 @@ class GDTokenizerText : public GDTokenizer {
Variant constant; //for constant types
union {
Variant::Type vtype; //for type types
- GDFunctions::Function func; //function for built in functions
+ GDScriptFunctions::Function func; //function for built in functions
};
int line, col;
TokenData() {
@@ -193,7 +194,7 @@ class GDTokenizerText : public GDTokenizer {
void _make_token(Token p_type);
void _make_newline(int p_spaces = 0);
void _make_identifier(const StringName &p_identifier);
- void _make_built_in_func(GDFunctions::Function p_func);
+ void _make_built_in_func(GDScriptFunctions::Function p_func);
void _make_constant(const Variant &p_constant);
void _make_type(const Variant::Type &p_type);
void _make_error(const String &p_error);
@@ -215,7 +216,7 @@ public:
void set_code(const String &p_code);
virtual Token get_token(int p_offset = 0) const;
virtual StringName get_token_identifier(int p_offset = 0) const;
- virtual GDFunctions::Function get_token_built_in_func(int p_offset = 0) const;
+ virtual GDScriptFunctions::Function get_token_built_in_func(int p_offset = 0) const;
virtual Variant::Type get_token_type(int p_offset = 0) const;
virtual int get_token_line(int p_offset = 0) const;
virtual int get_token_column(int p_offset = 0) const;
@@ -225,7 +226,7 @@ public:
virtual void advance(int p_amount = 1);
};
-class GDTokenizerBuffer : public GDTokenizer {
+class GDScriptTokenizerBuffer : public GDScriptTokenizer {
enum {
@@ -248,7 +249,7 @@ public:
static Vector<uint8_t> parse_code_string(const String &p_code);
virtual Token get_token(int p_offset = 0) const;
virtual StringName get_token_identifier(int p_offset = 0) const;
- virtual GDFunctions::Function get_token_built_in_func(int p_offset = 0) const;
+ virtual GDScriptFunctions::Function get_token_built_in_func(int p_offset = 0) const;
virtual Variant::Type get_token_type(int p_offset = 0) const;
virtual int get_token_line(int p_offset = 0) const;
virtual int get_token_column(int p_offset = 0) const;
@@ -256,7 +257,7 @@ public:
virtual const Variant &get_token_constant(int p_offset = 0) const;
virtual String get_token_error(int p_offset = 0) const;
virtual void advance(int p_amount = 1);
- GDTokenizerBuffer();
+ GDScriptTokenizerBuffer();
};
-#endif // TOKENIZER_H
+#endif // GDSCRIPT_TOKENIZER_H
diff --git a/modules/gdscript/register_types.cpp b/modules/gdscript/register_types.cpp
index 036274c8f2..1e007ddb0f 100644
--- a/modules/gdscript/register_types.cpp
+++ b/modules/gdscript/register_types.cpp
@@ -29,7 +29,7 @@
/*************************************************************************/
#include "register_types.h"
-#include "gd_script.h"
+#include "gdscript.h"
#include "io/file_access_encrypted.h"
#include "io/resource_loader.h"
#include "os/file_access.h"
@@ -41,10 +41,9 @@ ResourceFormatSaverGDScript *resource_saver_gd = NULL;
void register_gdscript_types() {
ClassDB::register_class<GDScript>();
- ClassDB::register_virtual_class<GDFunctionState>();
+ ClassDB::register_virtual_class<GDScriptFunctionState>();
script_language_gd = memnew(GDScriptLanguage);
- //script_language_gd->init();
ScriptServer::register_language(script_language_gd);
resource_loader_gd = memnew(ResourceFormatLoaderGDScript);
ResourceLoader::add_resource_format_loader(resource_loader_gd);
diff --git a/modules/gridmap/config.py b/modules/gridmap/config.py
index b3dbb9f46a..a93f4edb81 100644
--- a/modules/gridmap/config.py
+++ b/modules/gridmap/config.py
@@ -1,14 +1,13 @@
-
-
def can_build(platform):
return True
-
def configure(env):
pass
def get_doc_classes():
- return ["GridMap"]
+ return [
+ "GridMap",
+ ]
def get_doc_path():
- return "doc_classes"
+ return "doc_classes"
diff --git a/modules/gridmap/doc_classes/GridMap.xml b/modules/gridmap/doc_classes/GridMap.xml
index 3676570ec1..ee8ecfff66 100644
--- a/modules/gridmap/doc_classes/GridMap.xml
+++ b/modules/gridmap/doc_classes/GridMap.xml
@@ -1,8 +1,13 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="GridMap" inherits="Spatial" category="Core" version="3.0.alpha.custom_build">
+<class name="GridMap" inherits="Spatial" category="Core" version="3.0-alpha">
<brief_description>
+ Node for 3D tile-based maps.
</brief_description>
<description>
+ GridMap lets you place meshes on a grid interactively. It works both from the editor and can help you create in-game level editors.
+ GridMaps use a [MeshLibrary] which contain a list of tiles: meshes with materials plus optional collisions and extra elements.
+ A GridMap contains a collection of cells. Each grid cell refers to a [MeshLibrary] item. All cells in the map have the same dimensions.
+ A GridMap is split into a sparse collection of octants for efficient rendering and physics processing. Every octant has the same dimensions and can contain several cells.
</description>
<tutorials>
</tutorials>
@@ -13,6 +18,7 @@
<return type="void">
</return>
<description>
+ Clear all cells.
</description>
</method>
<method name="get_cell_item" qualifiers="const">
@@ -25,6 +31,7 @@
<argument index="2" name="z" type="int">
</argument>
<description>
+ The [MeshLibrary] item index located at the grid-based X, Y and Z coordinates. If the cell is empty, [INVALID_CELL_ITEM] will be returned.
</description>
</method>
<method name="get_cell_item_orientation" qualifiers="const">
@@ -37,48 +44,75 @@
<argument index="2" name="z" type="int">
</argument>
<description>
+ The orientation of the cell at the grid-based X, Y and Z coordinates. -1 is retuned if the cell is empty.
</description>
</method>
<method name="get_cell_size" qualifiers="const">
<return type="Vector3">
</return>
<description>
+ The dimensions of the grid's cells.
</description>
</method>
<method name="get_center_x" qualifiers="const">
<return type="bool">
</return>
<description>
+ Returns whether or not grid items are centered on the X axis.
</description>
</method>
<method name="get_center_y" qualifiers="const">
<return type="bool">
</return>
<description>
+ Returns whether or not grid items are centered on the Y axis.
</description>
</method>
<method name="get_center_z" qualifiers="const">
<return type="bool">
</return>
<description>
+ Returns whether or not grid items are centered on the Z axis.
</description>
</method>
<method name="get_meshes">
<return type="Array">
</return>
<description>
+ Array of [Transform] and [Mesh] references corresponding to the non empty cells in the grid. The transforms are specified in world space.
</description>
</method>
<method name="get_octant_size" qualifiers="const">
<return type="int">
</return>
<description>
+ The size of each octant measured in number of cells. This applies to all three axis.
</description>
</method>
<method name="get_theme" qualifiers="const">
<return type="MeshLibrary">
</return>
<description>
+ The assigned [MeshLibrary].
+ </description>
+ </method>
+ <method name="get_used_cells" qualifiers="const">
+ <return type="Array">
+ </return>
+ <description>
+ Array of [Vector3] with the non empty cell coordinates in the grid map.
+ </description>
+ </method>
+ <method name="map_to_world" qualifiers="const">
+ <return type="Vector3">
+ </return>
+ <argument index="0" name="x" type="int">
+ </argument>
+ <argument index="1" name="y" type="int">
+ </argument>
+ <argument index="2" name="z" type="int">
+ </argument>
+ <description>
</description>
</method>
<method name="resource_changed">
@@ -103,6 +137,9 @@
<argument index="4" name="orientation" type="int" default="0">
</argument>
<description>
+ Set the mesh index for the cell referenced by its grid-based X, Y and Z coordinates.
+ A negative item index will clear the cell.
+ Optionally, the item's orientation can be passed.
</description>
</method>
<method name="set_cell_size">
@@ -111,6 +148,7 @@
<argument index="0" name="size" type="Vector3">
</argument>
<description>
+ Sets the height, width and depth of the grid's cells.
</description>
</method>
<method name="set_center_x">
@@ -119,6 +157,7 @@
<argument index="0" name="enable" type="bool">
</argument>
<description>
+ Set grid items to be centered on the X axis. By default it is enabled.
</description>
</method>
<method name="set_center_y">
@@ -127,6 +166,7 @@
<argument index="0" name="enable" type="bool">
</argument>
<description>
+ Set grid items to be centered on the Y axis. By default it is enabled.
</description>
</method>
<method name="set_center_z">
@@ -135,6 +175,7 @@
<argument index="0" name="enable" type="bool">
</argument>
<description>
+ Set grid items to be centered on the Z axis. By default it is enabled.
</description>
</method>
<method name="set_clip">
@@ -157,6 +198,7 @@
<argument index="0" name="size" type="int">
</argument>
<description>
+ Sets the size for each octant measured in number of cells. This applies to all three axis.
</description>
</method>
<method name="set_theme">
@@ -165,11 +207,21 @@
<argument index="0" name="theme" type="MeshLibrary">
</argument>
<description>
+ Sets the collection of meshes for the map.
+ </description>
+ </method>
+ <method name="world_to_map" qualifiers="const">
+ <return type="Vector3">
+ </return>
+ <argument index="0" name="pos" type="Vector3">
+ </argument>
+ <description>
</description>
</method>
</methods>
<constants>
<constant name="INVALID_CELL_ITEM" value="-1" enum="">
+ Invalid cell item that can be used in [method set_cell_item] to clear cells (or represent an empty cell in [method get_cell_item]).
</constant>
</constants>
</class>
diff --git a/modules/gridmap/grid_map.cpp b/modules/gridmap/grid_map.cpp
index 4e8b67e4e8..b3a1947647 100644
--- a/modules/gridmap/grid_map.cpp
+++ b/modules/gridmap/grid_map.cpp
@@ -333,6 +333,23 @@ int GridMap::get_cell_item_orientation(int p_x, int p_y, int p_z) const {
return cell_map[key].rot;
}
+Vector3 GridMap::world_to_map(const Vector3 &p_world_pos) const {
+ Vector3 map_pos = p_world_pos / cell_size;
+ map_pos.x = floor(map_pos.x);
+ map_pos.y = floor(map_pos.y);
+ map_pos.z = floor(map_pos.z);
+ return map_pos;
+}
+
+Vector3 GridMap::map_to_world(int p_x, int p_y, int p_z) const {
+ Vector3 offset = _get_offset();
+ Vector3 world_pos(
+ p_x * cell_size.x + offset.x,
+ p_y * cell_size.y + offset.y,
+ p_z * cell_size.z + offset.z);
+ return world_pos;
+}
+
void GridMap::_octant_transform(const OctantKey &p_key) {
ERR_FAIL_COND(!octant_map.has(p_key));
@@ -407,7 +424,7 @@ bool GridMap::_octant_update(const OctantKey &p_key) {
//print_line("OCTANT, CELLS: "+itos(ii.cells.size()));
Vector3 cellpos = Vector3(E->get().x, E->get().y, E->get().z);
- Vector3 ofs(cell_size.x * 0.5 * int(center_x), cell_size.y * 0.5 * int(center_y), cell_size.z * 0.5 * int(center_z));
+ Vector3 ofs = _get_offset();
Transform xform;
@@ -730,7 +747,6 @@ void GridMap::_update_octants_callback() {
}
while (to_delete.front()) {
- memdelete(octant_map[to_delete.front()->get()]);
octant_map.erase(to_delete.front()->get());
to_delete.pop_back();
}
@@ -754,6 +770,9 @@ void GridMap::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_cell_item", "x", "y", "z"), &GridMap::get_cell_item);
ClassDB::bind_method(D_METHOD("get_cell_item_orientation", "x", "y", "z"), &GridMap::get_cell_item_orientation);
+ ClassDB::bind_method(D_METHOD("world_to_map", "pos"), &GridMap::world_to_map);
+ ClassDB::bind_method(D_METHOD("map_to_world", "x", "y", "z"), &GridMap::map_to_world);
+
//ClassDB::bind_method(D_METHOD("_recreate_octants"),&GridMap::_recreate_octants);
ClassDB::bind_method(D_METHOD("_update_octants_callback"), &GridMap::_update_octants_callback);
ClassDB::bind_method(D_METHOD("resource_changed", "resource"), &GridMap::resource_changed);
@@ -801,7 +820,7 @@ void GridMap::set_clip(bool p_enabled, bool p_clip_above, int p_floor, Vector3::
void GridMap::set_cell_scale(float p_scale) {
cell_scale = p_scale;
- _queue_octants_dirty();
+ _recreate_octant_data();
}
float GridMap::get_cell_scale() const {
@@ -827,7 +846,7 @@ Array GridMap::get_meshes() {
if (theme.is_null())
return Array();
- Vector3 ofs(cell_size.x * 0.5 * int(center_x), cell_size.y * 0.5 * int(center_y), cell_size.z * 0.5 * int(center_z));
+ Vector3 ofs = _get_offset();
Array meshes;
for (Map<IndexKey, Cell>::Element *E = cell_map.front(); E; E = E->next()) {
@@ -857,6 +876,13 @@ Array GridMap::get_meshes() {
return meshes;
}
+Vector3 GridMap::_get_offset() const {
+ return Vector3(
+ cell_size.x * 0.5 * int(center_x),
+ cell_size.y * 0.5 * int(center_y),
+ cell_size.z * 0.5 * int(center_z));
+}
+
GridMap::GridMap() {
cell_size = Vector3(2, 2, 2);
diff --git a/modules/gridmap/grid_map.h b/modules/gridmap/grid_map.h
index 296956ff5d..5bfdf1dac3 100644
--- a/modules/gridmap/grid_map.h
+++ b/modules/gridmap/grid_map.h
@@ -184,6 +184,8 @@ class GridMap : public Spatial {
void _clear_internal();
+ Vector3 _get_offset() const;
+
protected:
bool _set(const StringName &p_name, const Variant &p_value);
bool _get(const StringName &p_name, Variant &r_ret) const;
@@ -218,6 +220,9 @@ public:
int get_cell_item(int p_x, int p_y, int p_z) const;
int get_cell_item_orientation(int p_x, int p_y, int p_z) const;
+ Vector3 world_to_map(const Vector3 &p_pos) const;
+ Vector3 map_to_world(int p_x, int p_y, int p_z) const;
+
void set_clip(bool p_enabled, bool p_clip_above = true, int p_floor = 0, Vector3::Axis p_axis = Vector3::AXIS_X);
void set_cell_scale(float p_scale);
diff --git a/modules/gridmap/grid_map_editor_plugin.cpp b/modules/gridmap/grid_map_editor_plugin.cpp
index f6a76ad2a1..3a5d0fd3fc 100644
--- a/modules/gridmap/grid_map_editor_plugin.cpp
+++ b/modules/gridmap/grid_map_editor_plugin.cpp
@@ -28,8 +28,10 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "grid_map_editor_plugin.h"
+#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/plugins/spatial_editor_plugin.h"
+#include "os/input.h"
#include "scene/3d/camera.h"
#include "geometry.h"
@@ -56,6 +58,14 @@ void GridMapEditor::_menu_option(int p_option) {
switch (p_option) {
+ case MENU_OPTION_PREV_LEVEL: {
+ floor->set_value(floor->get_value() - 1);
+ } break;
+
+ case MENU_OPTION_NEXT_LEVEL: {
+ floor->set_value(floor->get_value() + 1);
+ } break;
+
case MENU_OPTION_CONFIGURE: {
} break;
@@ -94,6 +104,7 @@ void GridMapEditor::_menu_option(int p_option) {
} break;
case MENU_OPTION_CURSOR_ROTATE_Y: {
+
Basis r;
if (input_action == INPUT_DUPLICATE) {
@@ -109,6 +120,7 @@ void GridMapEditor::_menu_option(int p_option) {
_update_cursor_transform();
} break;
case MENU_OPTION_CURSOR_ROTATE_X: {
+
Basis r;
if (input_action == INPUT_DUPLICATE) {
@@ -125,6 +137,7 @@ void GridMapEditor::_menu_option(int p_option) {
_update_cursor_transform();
} break;
case MENU_OPTION_CURSOR_ROTATE_Z: {
+
Basis r;
if (input_action == INPUT_DUPLICATE) {
@@ -141,6 +154,7 @@ void GridMapEditor::_menu_option(int p_option) {
_update_cursor_transform();
} break;
case MENU_OPTION_CURSOR_BACK_ROTATE_Y: {
+
Basis r;
r.set_orthogonal_index(cursor_rot);
r.rotate(Vector3(0, 1, 0), Math_PI / 2.0);
@@ -148,6 +162,7 @@ void GridMapEditor::_menu_option(int p_option) {
_update_cursor_transform();
} break;
case MENU_OPTION_CURSOR_BACK_ROTATE_X: {
+
Basis r;
r.set_orthogonal_index(cursor_rot);
r.rotate(Vector3(1, 0, 0), Math_PI / 2.0);
@@ -155,6 +170,7 @@ void GridMapEditor::_menu_option(int p_option) {
_update_cursor_transform();
} break;
case MENU_OPTION_CURSOR_BACK_ROTATE_Z: {
+
Basis r;
r.set_orthogonal_index(cursor_rot);
r.rotate(Vector3(0, 0, 1), Math_PI / 2.0);
@@ -184,6 +200,9 @@ void GridMapEditor::_menu_option(int p_option) {
if (last_mouseover == Vector3(-1, -1, -1)) //nono mouseovering anythin
break;
+ last_mouseover = selection.begin;
+ VS::get_singleton()->instance_set_transform(grid_instance[edit_axis], Transform(Basis(), grid_ofs));
+
input_action = INPUT_DUPLICATE;
selection.click = last_mouseover;
selection.current = last_mouseover;
@@ -198,7 +217,7 @@ void GridMapEditor::_menu_option(int p_option) {
} break;
case MENU_OPTION_GRIDMAP_SETTINGS: {
- settings_dialog->popup_centered(settings_vbc->get_combined_minimum_size() + Size2(50, 50));
+ settings_dialog->popup_centered(settings_vbc->get_combined_minimum_size() + Size2(50, 50) * EDSCALE);
} break;
}
}
@@ -551,12 +570,11 @@ bool GridMapEditor::forward_spatial_input_event(Camera *p_camera, const Ref<Inpu
input_action = INPUT_NONE;
_update_duplicate_indicator();
- } else {
+ } else if (mb->get_shift()) {
input_action = INPUT_ERASE;
set_items.clear();
- }
- else
- return false;
+ } else
+ return false;
return do_input_action(p_camera, Point2(mb->get_position().x, mb->get_position().y), true);
} else {
@@ -605,6 +623,16 @@ bool GridMapEditor::forward_spatial_input_event(Camera *p_camera, const Ref<Inpu
return do_input_action(p_camera, mm->get_position(), false);
}
+ Ref<InputEventPanGesture> pan_gesture = p_event;
+ if (pan_gesture.is_valid()) {
+
+ if (pan_gesture->get_command() || pan_gesture->get_shift()) {
+ const real_t delta = pan_gesture->get_delta().y;
+ floor->set_value(floor->get_value() + SGN(delta));
+ return true;
+ }
+ }
+
return false;
}
@@ -829,70 +857,77 @@ void GridMapEditor::update_grid() {
void GridMapEditor::_notification(int p_what) {
- if (p_what == NOTIFICATION_ENTER_TREE) {
+ switch (p_what) {
- theme_pallete->connect("item_selected", this, "_item_selected_cbk");
- for (int i = 0; i < 3; i++) {
-
- grid[i] = VS::get_singleton()->mesh_create();
- grid_instance[i] = VS::get_singleton()->instance_create2(grid[i], get_tree()->get_root()->get_world()->get_scenario());
- selection_level_instance[i] = VisualServer::get_singleton()->instance_create2(selection_level_mesh[i], get_tree()->get_root()->get_world()->get_scenario());
- }
+ case NOTIFICATION_ENTER_TREE: {
+ theme_pallete->connect("item_selected", this, "_item_selected_cbk");
+ for (int i = 0; i < 3; i++) {
- selection_instance = VisualServer::get_singleton()->instance_create2(selection_mesh, get_tree()->get_root()->get_world()->get_scenario());
- duplicate_instance = VisualServer::get_singleton()->instance_create2(duplicate_mesh, get_tree()->get_root()->get_world()->get_scenario());
+ grid[i] = VS::get_singleton()->mesh_create();
+ grid_instance[i] = VS::get_singleton()->instance_create2(grid[i], get_tree()->get_root()->get_world()->get_scenario());
+ selection_level_instance[i] = VisualServer::get_singleton()->instance_create2(selection_level_mesh[i], get_tree()->get_root()->get_world()->get_scenario());
+ }
- _update_selection_transform();
- _update_duplicate_indicator();
+ selection_instance = VisualServer::get_singleton()->instance_create2(selection_mesh, get_tree()->get_root()->get_world()->get_scenario());
+ duplicate_instance = VisualServer::get_singleton()->instance_create2(duplicate_mesh, get_tree()->get_root()->get_world()->get_scenario());
- } else if (p_what == NOTIFICATION_EXIT_TREE) {
+ _update_selection_transform();
+ _update_duplicate_indicator();
+ } break;
- for (int i = 0; i < 3; i++) {
+ case NOTIFICATION_EXIT_TREE: {
+ for (int i = 0; i < 3; i++) {
- VS::get_singleton()->free(grid_instance[i]);
- VS::get_singleton()->free(grid[i]);
- grid_instance[i] = RID();
- grid[i] = RID();
- VisualServer::get_singleton()->free(selection_level_instance[i]);
- }
+ VS::get_singleton()->free(grid_instance[i]);
+ VS::get_singleton()->free(grid[i]);
+ grid_instance[i] = RID();
+ grid[i] = RID();
+ VisualServer::get_singleton()->free(selection_level_instance[i]);
+ }
- VisualServer::get_singleton()->free(selection_instance);
- VisualServer::get_singleton()->free(duplicate_instance);
- selection_instance = RID();
- duplicate_instance = RID();
+ VisualServer::get_singleton()->free(selection_instance);
+ VisualServer::get_singleton()->free(duplicate_instance);
+ selection_instance = RID();
+ duplicate_instance = RID();
+ } break;
- } else if (p_what == NOTIFICATION_PROCESS) {
- if (!node) {
- return;
- }
+ case NOTIFICATION_PROCESS: {
+ if (!node) {
+ return;
+ }
- Transform xf = node->get_global_transform();
+ Transform xf = node->get_global_transform();
- if (xf != grid_xform) {
- for (int i = 0; i < 3; i++) {
+ if (xf != grid_xform) {
+ for (int i = 0; i < 3; i++) {
- VS::get_singleton()->instance_set_transform(grid_instance[i], xf * edit_grid_xform);
+ VS::get_singleton()->instance_set_transform(grid_instance[i], xf * edit_grid_xform);
+ }
+ grid_xform = xf;
}
- grid_xform = xf;
- }
- Ref<MeshLibrary> cgmt = node->get_theme();
- if (cgmt.operator->() != last_theme)
- update_pallete();
+ Ref<MeshLibrary> cgmt = node->get_theme();
+ if (cgmt.operator->() != last_theme)
+ update_pallete();
- if (lock_view) {
+ if (lock_view) {
- EditorNode *editor = Object::cast_to<EditorNode>(get_tree()->get_root()->get_child(0));
+ EditorNode *editor = Object::cast_to<EditorNode>(get_tree()->get_root()->get_child(0));
- Plane p;
- p.normal[edit_axis] = 1.0;
- p.d = edit_floor[edit_axis] * node->get_cell_size()[edit_axis];
- p = node->get_transform().xform(p); // plane to snap
+ Plane p;
+ p.normal[edit_axis] = 1.0;
+ p.d = edit_floor[edit_axis] * node->get_cell_size()[edit_axis];
+ p = node->get_transform().xform(p); // plane to snap
- SpatialEditorPlugin *sep = Object::cast_to<SpatialEditorPlugin>(editor->get_editor_plugin_screen());
- if (sep)
- sep->snap_cursor_to_plane(p);
- //editor->get_editor_plugin_screen()->call("snap_cursor_to_plane",p);
- }
+ SpatialEditorPlugin *sep = Object::cast_to<SpatialEditorPlugin>(editor->get_editor_plugin_screen());
+ if (sep)
+ sep->snap_cursor_to_plane(p);
+ //editor->get_editor_plugin_screen()->call("snap_cursor_to_plane",p);
+ }
+ } break;
+
+ case NOTIFICATION_THEME_CHANGED: {
+ options->set_icon(get_icon("GridMap", "EditorIcons"));
+ } break;
}
}
@@ -954,20 +989,38 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) {
int mw = EDITOR_DEF("editors/grid_map/palette_min_width", 230);
Control *ec = memnew(Control);
- ec->set_custom_minimum_size(Size2(mw, 0));
+ ec->set_custom_minimum_size(Size2(mw, 0) * EDSCALE);
add_child(ec);
spatial_editor_hb = memnew(HBoxContainer);
+ spatial_editor_hb->set_h_size_flags(SIZE_EXPAND_FILL);
+ spatial_editor_hb->set_alignment(BoxContainer::ALIGN_END);
SpatialEditor::get_singleton()->add_control_to_menu_panel(spatial_editor_hb);
+
+ Label *fl = memnew(Label);
+ fl->set_text(TTR("Floor:"));
+ spatial_editor_hb->add_child(fl);
+
+ floor = memnew(SpinBox);
+ floor->set_min(-32767);
+ floor->set_max(32767);
+ floor->set_step(1);
+ floor->get_line_edit()->add_constant_override("minimum_spaces", 16);
+
+ spatial_editor_hb->add_child(floor);
+ floor->connect("value_changed", this, "_floor_changed");
+
+ spatial_editor_hb->add_child(memnew(VSeparator));
+
options = memnew(MenuButton);
spatial_editor_hb->add_child(options);
spatial_editor_hb->hide();
- options->set_text("Grid");
+ options->set_text(TTR("Grid Map"));
options->get_popup()->add_check_item(TTR("Snap View"), MENU_OPTION_LOCK_VIEW);
options->get_popup()->add_separator();
- options->get_popup()->add_item(vformat(TTR("Prev Level (%sDown Wheel)"), keycode_get_string(KEY_MASK_CMD)), MENU_OPTION_PREV_LEVEL);
- options->get_popup()->add_item(vformat(TTR("Next Level (%sUp Wheel)"), keycode_get_string(KEY_MASK_CMD)), MENU_OPTION_NEXT_LEVEL);
+ options->get_popup()->add_item(TTR("Previous Floor"), MENU_OPTION_PREV_LEVEL, KEY_Q);
+ options->get_popup()->add_item(TTR("Next Floor"), MENU_OPTION_NEXT_LEVEL, KEY_E);
options->get_popup()->add_separator();
options->get_popup()->add_check_item(TTR("Clip Disabled"), MENU_OPTION_CLIP_DISABLED);
options->get_popup()->set_item_checked(options->get_popup()->get_item_index(MENU_OPTION_CLIP_DISABLED), true);
@@ -993,8 +1046,8 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) {
options->get_popup()->add_item(TTR("Create Exterior Connector"), MENU_OPTION_SELECTION_MAKE_EXTERIOR_CONNECTOR);
options->get_popup()->add_item(TTR("Erase Area"), MENU_OPTION_REMOVE_AREA);
options->get_popup()->add_separator();
- options->get_popup()->add_item(TTR("Selection -> Duplicate"), MENU_OPTION_SELECTION_DUPLICATE, KEY_MASK_SHIFT + KEY_INSERT);
- options->get_popup()->add_item(TTR("Selection -> Clear"), MENU_OPTION_SELECTION_CLEAR, KEY_MASK_SHIFT + KEY_DELETE);
+ options->get_popup()->add_item(TTR("Duplicate Selection"), MENU_OPTION_SELECTION_DUPLICATE, KEY_MASK_SHIFT + KEY_C);
+ options->get_popup()->add_item(TTR("Clear Selection"), MENU_OPTION_SELECTION_CLEAR, KEY_MASK_SHIFT + KEY_X);
options->get_popup()->add_separator();
options->get_popup()->add_item(TTR("Settings"), MENU_OPTION_GRIDMAP_SETTINGS);
@@ -1003,7 +1056,7 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) {
settings_dialog->set_title(TTR("GridMap Settings"));
add_child(settings_dialog);
settings_vbc = memnew(VBoxContainer);
- settings_vbc->set_custom_minimum_size(Size2(200, 0));
+ settings_vbc->set_custom_minimum_size(Size2(200, 0) * EDSCALE);
settings_dialog->add_child(settings_vbc);
settings_pick_distance = memnew(SpinBox);
@@ -1042,20 +1095,6 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) {
add_child(theme_pallete);
theme_pallete->set_v_size_flags(SIZE_EXPAND_FILL);
- spatial_editor_hb->add_child(memnew(VSeparator));
- Label *fl = memnew(Label);
- fl->set_text(" Floor: ");
- spatial_editor_hb->add_child(fl);
-
- floor = memnew(SpinBox);
- floor->set_min(-32767);
- floor->set_max(32767);
- floor->set_step(1);
- floor->get_line_edit()->add_constant_override("minimum_spaces", 16);
-
- spatial_editor_hb->add_child(floor);
- floor->connect("value_changed", this, "_floor_changed");
-
edit_axis = Vector3::AXIS_Y;
edit_floor[0] = -1;
edit_floor[1] = -1;
@@ -1108,7 +1147,7 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) {
for (int i = 0; i < 12; i++) {
- Rect3 base(Vector3(0, 0, 0), Vector3(1, 1, 1));
+ AABB base(Vector3(0, 0, 0), Vector3(1, 1, 1));
Vector3 a, b;
base.get_edge(i, a, b);
lines.push_back(a);
@@ -1250,7 +1289,9 @@ GridMapEditorPlugin::GridMapEditorPlugin(EditorNode *p_node) {
gridmap_editor = memnew(GridMapEditor(editor));
SpatialEditor::get_singleton()->get_palette_split()->add_child(gridmap_editor);
- SpatialEditor::get_singleton()->get_palette_split()->move_child(gridmap_editor, 0);
+ // TODO: make this configurable, so the user can choose were to put this, it makes more sense
+ // on the right, but some people might find it strange.
+ SpatialEditor::get_singleton()->get_palette_split()->move_child(gridmap_editor, 1);
gridmap_editor->hide();
}
diff --git a/modules/hdr/config.py b/modules/hdr/config.py
index fb920482f5..5f133eba90 100644
--- a/modules/hdr/config.py
+++ b/modules/hdr/config.py
@@ -1,7 +1,5 @@
-
def can_build(platform):
return True
-
def configure(env):
pass
diff --git a/modules/hdr/image_loader_hdr.cpp b/modules/hdr/image_loader_hdr.cpp
index 92d88207b3..08ac624504 100644
--- a/modules/hdr/image_loader_hdr.cpp
+++ b/modules/hdr/image_loader_hdr.cpp
@@ -38,7 +38,6 @@ Error ImageLoaderHDR::load_image(Ref<Image> p_image, FileAccess *f, bool p_force
String header = f->get_token();
- print_line("HEADER: " + header);
ERR_FAIL_COND_V(header != "#?RADIANCE" && header != "#?RGBE", ERR_FILE_UNRECOGNIZED);
while (true) {
@@ -64,8 +63,6 @@ Error ImageLoaderHDR::load_image(Ref<Image> p_image, FileAccess *f, bool p_force
int width = f->get_line().to_int();
- print_line("HDR w: " + itos(width) + " h:" + itos(height));
-
PoolVector<uint8_t> imgdata;
imgdata.resize(height * width * sizeof(uint32_t));
@@ -102,7 +99,6 @@ Error ImageLoaderHDR::load_image(Ref<Image> p_image, FileAccess *f, bool p_force
len <<= 8;
len |= f->get_8();
- print_line("line: " + itos(len));
if (len != width) {
ERR_EXPLAIN("invalid decoded scanline length, corrupt HDR");
ERR_FAIL_V(ERR_FILE_CORRUPT);
diff --git a/modules/jpg/config.py b/modules/jpg/config.py
index fb920482f5..5f133eba90 100644
--- a/modules/jpg/config.py
+++ b/modules/jpg/config.py
@@ -1,7 +1,5 @@
-
def can_build(platform):
return True
-
def configure(env):
pass
diff --git a/modules/mobile_vr/config.py b/modules/mobile_vr/config.py
index cf96c66125..4e1155f0c6 100644
--- a/modules/mobile_vr/config.py
+++ b/modules/mobile_vr/config.py
@@ -1,12 +1,14 @@
def can_build(platform):
- # should probably change this to only be true on iOS and Android
- return True
+ # should probably change this to only be true on iOS and Android
+ return True
def configure(env):
- pass
+ pass
def get_doc_classes():
- return ["MobileVRInterface"]
+ return [
+ "MobileVRInterface",
+ ]
def get_doc_path():
- return "doc_classes"
+ return "doc_classes"
diff --git a/modules/mobile_vr/doc_classes/MobileVRInterface.xml b/modules/mobile_vr/doc_classes/MobileVRInterface.xml
index c945a99a9a..c99934aea9 100644
--- a/modules/mobile_vr/doc_classes/MobileVRInterface.xml
+++ b/modules/mobile_vr/doc_classes/MobileVRInterface.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="MobileVRInterface" inherits="ARVRInterface" category="Core" version="3.0.alpha.custom_build">
+<class name="MobileVRInterface" inherits="ARVRInterface" category="Core" version="3.0-alpha">
<brief_description>
Generic mobile VR implementation
</brief_description>
diff --git a/modules/mobile_vr/mobile_interface.cpp b/modules/mobile_vr/mobile_interface.cpp
index eb87bb2cf0..3a0b83d534 100644
--- a/modules/mobile_vr/mobile_interface.cpp
+++ b/modules/mobile_vr/mobile_interface.cpp
@@ -122,6 +122,7 @@ void MobileVRInterface::set_position_from_sensors() {
Vector3 north(0.0, 0.0, 1.0); // North is Z positive
// make copies of our inputs
+ bool has_grav = false;
Vector3 acc = input->get_accelerometer();
Vector3 gyro = input->get_gyroscope();
Vector3 grav = input->get_gravity();
@@ -143,25 +144,17 @@ void MobileVRInterface::set_position_from_sensors() {
// what a stable gravity vector is
grav = acc;
if (grav.length() > 0.1) {
- has_gyro = true;
+ has_grav = true;
};
} else {
- has_gyro = true;
+ has_grav = true;
};
bool has_magneto = magneto.length() > 0.1;
- bool has_grav = grav.length() > 0.1;
-
-#ifdef ANDROID_ENABLED
- ///@TODO needs testing, i don't have a gyro, potentially can be removed depending on what comes out of issue #8101
- // On Android x and z axis seem inverted
- gyro.x = -gyro.x;
- gyro.z = -gyro.z;
- grav.x = -grav.x;
- grav.z = -grav.z;
- magneto.x = -magneto.x;
- magneto.z = -magneto.z;
-#endif
+ if (gyro.length() > 0.1) {
+ /* this can return to 0.0 if the user doesn't move the phone, so once on, it's on */
+ has_gyro = true;
+ };
if (has_gyro) {
// start with applying our gyro (do NOT smooth our gyro!)
@@ -330,7 +323,7 @@ void MobileVRInterface::uninitialize() {
};
};
-Size2 MobileVRInterface::get_recommended_render_targetsize() {
+Size2 MobileVRInterface::get_render_targetsize() {
_THREAD_SAFE_METHOD_
// we use half our window size
diff --git a/modules/mobile_vr/mobile_interface.h b/modules/mobile_vr/mobile_interface.h
index 6a5e01c163..b652edc1c6 100644
--- a/modules/mobile_vr/mobile_interface.h
+++ b/modules/mobile_vr/mobile_interface.h
@@ -90,7 +90,7 @@ private:
///@TODO a few support functions for trackers, most are math related and should likely be moved elsewhere
float floor_decimals(float p_value, float p_decimals) {
- float power_of_10 = pow(10.0, p_decimals);
+ float power_of_10 = pow(10.0f, p_decimals);
return floor(p_value * power_of_10) / power_of_10;
};
@@ -137,7 +137,7 @@ public:
virtual bool initialize();
virtual void uninitialize();
- virtual Size2 get_recommended_render_targetsize();
+ virtual Size2 get_render_targetsize();
virtual bool is_stereo();
virtual Transform get_transform_for_eye(ARVRInterface::Eyes p_eye, const Transform &p_cam_transform);
virtual CameraMatrix get_projection_for_eye(ARVRInterface::Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far);
diff --git a/modules/mono/SCsub b/modules/mono/SCsub
index 0af2056c5c..18a20ecac4 100644
--- a/modules/mono/SCsub
+++ b/modules/mono/SCsub
@@ -2,9 +2,10 @@
Import('env')
+from compat import byte_to_str
def make_cs_files_header(src, dst):
- with open(dst, 'wb') as header:
+ with open(dst, 'w') as header:
header.write('/* This is an automatically generated file; DO NOT EDIT! OK THX */\n')
header.write('#ifndef _CS_FILES_DATA_H\n')
header.write('#define _CS_FILES_DATA_H\n\n')
@@ -26,7 +27,7 @@ def make_cs_files_header(src, dst):
for i, buf_idx in enumerate(range(len(buf))):
if i > 0:
header.write(', ')
- header.write(str(ord(buf[buf_idx])))
+ header.write(byte_to_str(buf[buf_idx]))
inserted_files += '\tr_files.insert(\"' + file + '\", ' \
'CompressedFile(_cs_' + name + '_compressed_size, ' \
'_cs_' + name + '_uncompressed_size, ' \
@@ -52,68 +53,155 @@ if env['tools']:
vars = Variables()
vars.Add(BoolVariable('mono_glue', 'Build with the mono glue sources', True))
+vars.Add(BoolVariable('xbuild_fallback', 'If MSBuild is not found, fallback to xbuild', False))
vars.Update(env)
# Glue sources
if env['mono_glue']:
env.add_source_files(env.modules_sources, 'glue/*.cpp')
else:
- env.Append(CPPDEFINES = [ 'MONO_GLUE_DISABLED' ])
+ env.Append(CPPDEFINES=['MONO_GLUE_DISABLED'])
if ARGUMENTS.get('yolo_copy', False):
- env.Append(CPPDEFINES = [ 'YOLO_COPY' ])
+ env.Append(CPPDEFINES=['YOLO_COPY'])
+
# Build GodotSharpTools solution
+
import os
-import subprocess
-import mono_reg_utils as monoreg
+
+
+def find_msbuild_unix(filename):
+ import os.path
+ import sys
+
+ hint_dirs = ['/opt/novell/mono/bin']
+ if sys.platform == "darwin":
+ hint_dirs = ['/Library/Frameworks/Mono.framework/Versions/Current/bin'] + hint_dirs
+
+ for hint_dir in hint_dirs:
+ hint_path = os.path.join(hint_dir, filename)
+ if os.path.isfile(hint_path):
+ return hint_path
+ elif os.path.isfile(hint_path + ".exe"):
+ return hint_path + ".exe"
+
+ for hint_dir in os.environ["PATH"].split(os.pathsep):
+ hint_dir = hint_dir.strip('"')
+ hint_path = os.path.join(hint_dir, filename)
+ if os.path.isfile(hint_path) and os.access(hint_path, os.X_OK):
+ return hint_path
+ if os.path.isfile(hint_path + ".exe") and os.access(hint_path + ".exe", os.X_OK):
+ return hint_path + ".exe"
+
+ return None
+
+
+def find_msbuild_windows():
+ import mono_reg_utils as monoreg
+
+ bits = env['bits']
+
+ if bits == '32':
+ if os.getenv('MONO32_PREFIX'):
+ mono_root = os.getenv('MONO32_PREFIX')
+ else:
+ mono_root = monoreg.find_mono_root_dir(bits)
+ else:
+ if os.getenv('MONO64_PREFIX'):
+ mono_root = os.getenv('MONO64_PREFIX')
+ else:
+ mono_root = monoreg.find_mono_root_dir(bits)
+
+ if not mono_root:
+ raise RuntimeError('Cannot find mono root directory')
+
+ msbuild_tools_path = monoreg.find_msbuild_tools_path_reg()
+
+ if msbuild_tools_path:
+ return (os.path.join(msbuild_tools_path, 'MSBuild.exe'), os.path.join(mono_root, 'lib', 'mono', '4.5'))
+ else:
+ msbuild_mono = os.path.join(mono_root, 'bin', 'msbuild.bat')
+
+ if os.path.isfile(msbuild_mono):
+ return (msbuild_mono, '')
+
+ return None
def mono_build_solution(source, target, env):
+ import subprocess
+ import mono_reg_utils as monoreg
+ from shutil import copyfile
+
+ framework_path_override = ''
+
if os.name == 'nt':
- msbuild_tools_path = monoreg.find_msbuild_tools_path_reg()
- if not msbuild_tools_path:
- raise RuntimeError('Cannot find MSBuild Tools Path in the registry')
- msbuild_path = os.path.join(msbuild_tools_path, 'MSBuild.exe')
+ msbuild_info = find_msbuild_windows()
+ if msbuild_info is None:
+ raise RuntimeError('Cannot find MSBuild executable')
+ msbuild_path = msbuild_info[0]
+ framework_path_override = msbuild_info[1]
else:
- msbuild_path = 'msbuild'
+ msbuild_path = find_msbuild_unix('msbuild')
+ if msbuild_path is None:
+ xbuild_fallback = env['xbuild_fallback']
+
+ if xbuild_fallback and os.name == 'nt':
+ print("Option 'xbuild_fallback' not supported on Windows")
+ xbuild_fallback = False
+
+ if xbuild_fallback:
+ print('Cannot find MSBuild executable, trying with xbuild')
+ print('Warning: xbuild is deprecated')
+
+ msbuild_path = find_msbuild_unix('xbuild')
+
+ if msbuild_path is None:
+ raise RuntimeError('Cannot find xbuild executable')
+ else:
+ raise RuntimeError('Cannot find MSBuild executable')
+
+ print('MSBuild path: ' + msbuild_path)
- output_path = os.path.abspath(os.path.join(str(target[0]), os.pardir))
+ build_config = 'Release'
msbuild_args = [
msbuild_path,
os.path.abspath(str(source[0])),
- '/p:Configuration=Release',
- '/p:OutputPath=' + output_path
+ '/p:Configuration=' + build_config,
]
+ if framework_path_override:
+ msbuild_args += ['/p:FrameworkPathOverride=' + framework_path_override]
+
msbuild_env = os.environ.copy()
# Needed when running from Developer Command Prompt for VS
if 'PLATFORM' in msbuild_env:
del msbuild_env['PLATFORM']
- msbuild_alt_paths = [ 'xbuild' ]
-
- while True:
- try:
- subprocess.check_call(msbuild_args, env = msbuild_env)
- break
- except subprocess.CalledProcessError:
- raise RuntimeError('GodotSharpTools build failed')
- except OSError:
- if os.name != 'nt':
- if not msbuild_alt_paths:
- raise RuntimeError('Could not find commands msbuild or xbuild')
- # Try xbuild
- msbuild_args[0] = msbuild_alt_paths.pop(0)
- else:
- raise RuntimeError('Could not find command MSBuild.exe')
+ try:
+ subprocess.check_call(msbuild_args, env=msbuild_env)
+ except subprocess.CalledProcessError:
+ raise RuntimeError('GodotSharpTools build failed')
+
+ src_dir = os.path.abspath(os.path.join(str(source[0]), os.pardir, 'bin', build_config))
+ dst_dir = os.path.abspath(os.path.join(str(target[0]), os.pardir))
+
+ if not os.path.isdir(dst_dir):
+ if os.path.exists(dst_dir):
+ raise RuntimeError('Target directory is a file')
+ os.makedirs(dst_dir)
+
+ asm_file = 'GodotSharpTools.dll'
+
+ copyfile(os.path.join(src_dir, asm_file), os.path.join(dst_dir, asm_file))
mono_sln_builder = Builder(action = mono_build_solution)
-env.Append(BUILDERS = { 'MonoBuildSolution' : mono_sln_builder })
+env.Append(BUILDERS={'MonoBuildSolution': mono_sln_builder})
env.MonoBuildSolution(
os.path.join(Dir('#bin').abspath, 'GodotSharpTools.dll'),
'editor/GodotSharpTools/GodotSharpTools.sln'
diff --git a/modules/mono/config.py b/modules/mono/config.py
index 9de199bb5a..b4e6433256 100644
--- a/modules/mono/config.py
+++ b/modules/mono/config.py
@@ -2,7 +2,6 @@
import imp
import os
import sys
-from shutil import copyfile
from SCons.Script import BoolVariable, Environment, Variables
@@ -16,8 +15,7 @@ def find_file_in_dir(directory, files, prefix='', extension=''):
for curfile in files:
if os.path.isfile(os.path.join(directory, prefix + curfile + extension)):
return curfile
-
- return None
+ return ''
def can_build(platform):
@@ -31,13 +29,32 @@ def is_enabled():
return False
+def copy_file_no_replace(src_dir, dst_dir, name):
+ from shutil import copyfile
+
+ src_path = os.path.join(src_dir, name)
+ dst_path = os.path.join(dst_dir, name)
+ need_copy = True
+
+ if not os.path.isdir(dst_dir):
+ os.mkdir(dst_dir)
+ elif os.path.exists(dst_path):
+ need_copy = False
+
+ if need_copy:
+ copyfile(src_path, dst_path)
+
+
def configure(env):
env.use_ptrcall = True
+ env.add_module_version_string("mono")
envvars = Variables()
envvars.Add(BoolVariable('mono_static', 'Statically link mono', False))
envvars.Update(env)
+ bits = env['bits']
+
mono_static = env['mono_static']
mono_lib_names = ['mono-2.0-sgen', 'monosgen-2.0']
@@ -46,18 +63,18 @@ def configure(env):
if mono_static:
raise RuntimeError('mono-static: Not supported on Windows')
- if env['bits'] == '32':
+ if bits == '32':
if os.getenv('MONO32_PREFIX'):
mono_root = os.getenv('MONO32_PREFIX')
elif os.name == 'nt':
- mono_root = monoreg.find_mono_root_dir()
+ mono_root = monoreg.find_mono_root_dir(bits)
else:
if os.getenv('MONO64_PREFIX'):
mono_root = os.getenv('MONO64_PREFIX')
elif os.name == 'nt':
- mono_root = monoreg.find_mono_root_dir()
+ mono_root = monoreg.find_mono_root_dir(bits)
- if mono_root is None:
+ if not mono_root:
raise RuntimeError('Mono installation directory not found')
mono_lib_path = os.path.join(mono_root, 'lib')
@@ -67,7 +84,7 @@ def configure(env):
mono_lib_name = find_file_in_dir(mono_lib_path, mono_lib_names, extension='.lib')
- if mono_lib_name is None:
+ if not mono_lib_name:
raise RuntimeError('Could not find mono library in: ' + mono_lib_path)
if os.getenv('VCINSTALLDIR'):
@@ -79,28 +96,23 @@ def configure(env):
mono_dll_name = find_file_in_dir(mono_bin_path, mono_lib_names, extension='.dll')
- mono_dll_src = os.path.join(mono_bin_path, mono_dll_name + '.dll')
- mono_dll_dst = os.path.join('bin', mono_dll_name + '.dll')
- copy_mono_dll = True
+ if not mono_dll_name:
+ raise RuntimeError('Could not find mono shared library in: ' + mono_bin_path)
- if not os.path.isdir('bin'):
- os.mkdir('bin')
- elif os.path.exists(mono_dll_dst):
- copy_mono_dll = False
-
- if copy_mono_dll:
- copyfile(mono_dll_src, mono_dll_dst)
+ copy_file_no_replace(mono_bin_path, 'bin', mono_dll_name + '.dll')
else:
- mono_root = None
+ sharedlib_ext = '.dylib' if sys.platform == 'darwin' else '.so'
+
+ mono_root = ''
- if env['bits'] == '32':
+ if bits == '32':
if os.getenv('MONO32_PREFIX'):
mono_root = os.getenv('MONO32_PREFIX')
else:
if os.getenv('MONO64_PREFIX'):
mono_root = os.getenv('MONO64_PREFIX')
- if mono_root is not None:
+ if mono_root:
mono_lib_path = os.path.join(mono_root, 'lib')
env.Append(LIBPATH=mono_lib_path)
@@ -108,7 +120,7 @@ def configure(env):
mono_lib = find_file_in_dir(mono_lib_path, mono_lib_names, prefix='lib', extension='.a')
- if mono_lib is None:
+ if not mono_lib:
raise RuntimeError('Could not find mono library in: ' + mono_lib_path)
env.Append(CPPFLAGS=['-D_REENTRANT'])
@@ -125,18 +137,51 @@ def configure(env):
else:
env.Append(LIBS=[mono_lib])
- env.Append(LIBS=['m', 'rt', 'dl', 'pthread'])
+ if sys.platform == "darwin":
+ env.Append(LIBS=['iconv', 'pthread'])
+ elif sys.platform == "linux" or sys.platform == "linux2":
+ env.Append(LIBS=['m', 'rt', 'dl', 'pthread'])
+
+ if not mono_static:
+ mono_so_name = find_file_in_dir(mono_lib_path, mono_lib_names, prefix='lib', extension=sharedlib_ext)
+
+ if not mono_so_name:
+ raise RuntimeError('Could not find mono shared library in: ' + mono_lib_path)
+
+ copy_file_no_replace(mono_lib_path, 'bin', 'lib' + mono_so_name + sharedlib_ext)
else:
if mono_static:
raise RuntimeError('mono-static: Not supported with pkg-config. Specify a mono prefix manually')
- env.ParseConfig('pkg-config mono-2 --cflags --libs')
+ env.ParseConfig('pkg-config monosgen-2 --cflags --libs')
+
+ mono_lib_path = ''
+ mono_so_name = ''
+
+ tmpenv = Environment()
+ tmpenv.ParseConfig('pkg-config monosgen-2 --libs-only-L')
+
+ for hint_dir in tmpenv['LIBPATH']:
+ name_found = find_file_in_dir(hint_dir, mono_lib_names, prefix='lib', extension=sharedlib_ext)
+ if name_found:
+ mono_lib_path = hint_dir
+ mono_so_name = name_found
+ break
+
+ if not mono_so_name:
+ raise RuntimeError('Could not find mono shared library in: ' + str(tmpenv['LIBPATH']))
+
+ copy_file_no_replace(mono_lib_path, 'bin', 'lib' + mono_so_name + sharedlib_ext)
env.Append(LINKFLAGS='-rdynamic')
def get_doc_classes():
- return ["@C#", "CSharpScript", "GodotSharp"]
+ return [
+ "@C#",
+ "CSharpScript",
+ "GodotSharp",
+ ]
def get_doc_path():
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp
index 7de90dfbc3..dfa5e720ae 100644
--- a/modules/mono/csharp_script.cpp
+++ b/modules/mono/csharp_script.cpp
@@ -41,6 +41,7 @@
#include "editor/csharp_project.h"
#include "editor/editor_node.h"
#include "editor/godotsharp_editor.h"
+#include "utils/string_utils.h"
#endif
#include "godotsharp_dirs.h"
@@ -48,8 +49,9 @@
#include "mono_gd/gd_mono_marshal.h"
#include "signal_awaiter_utils.h"
-#define CACHED_STRING_NAME(m_var) (CSharpLanguage::get_singleton()->string_names.m_var)
+#define CACHED_STRING_NAME(m_var) (CSharpLanguage::get_singleton()->get_string_names().m_var)
+#ifdef TOOLS_ENABLED
static bool _create_project_solution_if_needed() {
String sln_path = GodotSharpDirs::get_project_sln_path();
@@ -64,6 +66,7 @@ static bool _create_project_solution_if_needed() {
return true;
}
+#endif
CSharpLanguage *CSharpLanguage::singleton = NULL;
@@ -119,6 +122,9 @@ void CSharpLanguage::init() {
void CSharpLanguage::finish() {
+ // Release gchandle bindings before finalizing mono runtime
+ gchandle_bindings.clear();
+
if (gdmono) {
memdelete(gdmono);
gdmono = NULL;
@@ -274,17 +280,40 @@ Ref<Script> CSharpLanguage::get_template(const String &p_class_name, const Strin
" // Initialization here\n"
" \n"
" }\n"
+ "\n"
+ "// public override void _Process(float delta)\n"
+ "// {\n"
+ "// // Called every frame. Delta is time since last frame.\n"
+ "// // Update game logic here.\n"
+ "// \n"
+ "// }\n"
"}\n";
- script_template = script_template.replace("%BASE_CLASS_NAME%", p_base_class_name).replace("%CLASS_NAME%", p_class_name);
+ script_template = script_template.replace("%BASE_CLASS_NAME%", p_base_class_name)
+ .replace("%CLASS_NAME%", p_class_name);
Ref<CSharpScript> script;
script.instance();
script->set_source_code(script_template);
+ script->set_name(p_class_name);
return script;
}
+bool CSharpLanguage::is_using_templates() {
+
+ return true;
+}
+
+void CSharpLanguage::make_template(const String &p_class_name, const String &p_base_class_name, Ref<Script> &p_script) {
+
+ String src = p_script->get_source_code();
+ src = src.replace("%BASE%", p_base_class_name)
+ .replace("%CLASS%", p_class_name)
+ .replace("%TS%", _get_indentation());
+ p_script->set_source_code(src);
+}
+
Script *CSharpLanguage::create_script() const {
return memnew(CSharpScript);
@@ -292,23 +321,115 @@ Script *CSharpLanguage::create_script() const {
bool CSharpLanguage::has_named_classes() const {
- return true;
+ return false;
}
-String CSharpLanguage::make_function(const String &p_class, const String &p_name, const PoolStringArray &p_args) const {
+bool CSharpLanguage::supports_builtin_mode() const {
+ return false;
+}
+
+static String variant_type_to_managed_name(const String &p_var_type_name) {
+
+ if (p_var_type_name.empty())
+ return "object";
+
+ if (!ClassDB::class_exists(p_var_type_name)) {
+ Variant::Type var_types[] = {
+ Variant::BOOL,
+ Variant::INT,
+ Variant::REAL,
+ Variant::STRING,
+ Variant::VECTOR2,
+ Variant::RECT2,
+ Variant::VECTOR3,
+ Variant::TRANSFORM2D,
+ Variant::PLANE,
+ Variant::QUAT,
+ Variant::AABB,
+ Variant::BASIS,
+ Variant::TRANSFORM,
+ Variant::COLOR,
+ Variant::NODE_PATH,
+ Variant::_RID
+ };
+
+ for (int i = 0; i < sizeof(var_types) / sizeof(Variant::Type); i++) {
+ if (p_var_type_name == Variant::get_type_name(var_types[i]))
+ return p_var_type_name;
+ }
+
+ if (p_var_type_name == "String")
+ return "string"; // I prefer this one >:[
+
+ // TODO these will be rewritten later into custom containers
+
+ if (p_var_type_name == "Array")
+ return "object[]";
+
+ if (p_var_type_name == "Dictionary")
+ return "Dictionary<object, object>";
+
+ if (p_var_type_name == "PoolByteArray")
+ return "byte[]";
+ if (p_var_type_name == "PoolIntArray")
+ return "int[]";
+ if (p_var_type_name == "PoolRealArray")
+ return "float[]";
+ if (p_var_type_name == "PoolStringArray")
+ return "string[]";
+ if (p_var_type_name == "PoolVector2Array")
+ return "Vector2[]";
+ if (p_var_type_name == "PoolVector3Array")
+ return "Vector3[]";
+ if (p_var_type_name == "PoolColorArray")
+ return "Color[]";
+
+ return "object";
+ }
+
+ return p_var_type_name;
+}
+
+String CSharpLanguage::make_function(const String &p_class, const String &p_name, const PoolStringArray &p_args) const {
+#ifdef TOOLS_ENABLED
// FIXME
- // Due to Godot's API limitation this just appends the function to the end of the file
- // Another limitation is that the parameter types are not specified, so we must use System.Object
+ // - Due to Godot's API limitation this just appends the function to the end of the file
+ // - Use fully qualified name if there is ambiguity
String s = "private void " + p_name + "(";
for (int i = 0; i < p_args.size(); i++) {
+ const String &arg = p_args[i];
+
if (i > 0)
s += ", ";
- s += "object " + p_args[i];
+
+ s += variant_type_to_managed_name(arg.get_slice(":", 1)) + " " + escape_csharp_keyword(arg.get_slice(":", 0));
}
s += ")\n{\n // Replace with function body\n}\n";
return s;
+#else
+ return String();
+#endif
+}
+
+String CSharpLanguage::_get_indentation() const {
+#ifdef TOOLS_ENABLED
+ if (Engine::get_singleton()->is_editor_hint()) {
+ bool use_space_indentation = EDITOR_DEF("text_editor/indent/type", 0);
+
+ if (use_space_indentation) {
+ int indent_size = EDITOR_DEF("text_editor/indent/size", 4);
+
+ String space_indent = "";
+ for (int i = 0; i < indent_size; i++) {
+ space_indent += " ";
+ }
+ return space_indent;
+ }
+ }
+#endif
+ return "\t";
}
void CSharpLanguage::frame() {
@@ -392,6 +513,7 @@ void CSharpLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_soft
(void)p_script; // UNUSED
#ifdef TOOLS_ENABLED
+ MonoReloadNode::get_singleton()->restart_reload_timer();
reload_assemblies_if_needed(p_soft_reload);
#endif
}
@@ -403,13 +525,17 @@ void CSharpLanguage::reload_assemblies_if_needed(bool p_soft_reload) {
GDMonoAssembly *proj_assembly = gdmono->get_project_assembly();
+ String name = ProjectSettings::get_singleton()->get("application/config/name");
+ if (name.empty()) {
+ name = "UnnamedProject";
+ }
+
if (proj_assembly) {
String proj_asm_path = proj_assembly->get_path();
if (!FileAccess::exists(proj_assembly->get_path())) {
// Maybe it wasn't loaded from the default path, so check this as well
- String proj_asm_name = ProjectSettings::get_singleton()->get("application/config/name");
- proj_asm_path = GodotSharpDirs::get_res_temp_assemblies_dir().plus_file(proj_asm_name);
+ proj_asm_path = GodotSharpDirs::get_res_temp_assemblies_dir().plus_file(name);
if (!FileAccess::exists(proj_asm_path))
return; // No assembly to load
}
@@ -417,8 +543,7 @@ void CSharpLanguage::reload_assemblies_if_needed(bool p_soft_reload) {
if (FileAccess::get_modified_time(proj_asm_path) <= proj_assembly->get_modified_time())
return; // Already up to date
} else {
- String proj_asm_name = ProjectSettings::get_singleton()->get("application/config/name");
- if (!FileAccess::exists(GodotSharpDirs::get_res_temp_assemblies_dir().plus_file(proj_asm_name)))
+ if (!FileAccess::exists(GodotSharpDirs::get_res_temp_assemblies_dir().plus_file(name)))
return; // No assembly to load
}
}
@@ -536,6 +661,9 @@ void CSharpLanguage::reload_assemblies_if_needed(bool p_soft_reload) {
//if instance states were saved, set them!
}
+
+ if (Engine::get_singleton()->is_editor_hint())
+ EditorNode::get_singleton()->get_property_editor()->update_tree();
}
#endif
@@ -654,6 +782,13 @@ void *CSharpLanguage::alloc_instance_binding_data(Object *p_object) {
StringName type_name = p_object->get_class_name();
+ // ¯\_(ツ)_/¯
+ const ClassDB::ClassInfo *classinfo = ClassDB::classes.getptr(type_name);
+ while (classinfo && !classinfo->exposed)
+ classinfo = classinfo->inherits_ptr;
+ ERR_FAIL_NULL_V(classinfo, NULL);
+ type_name = classinfo->name;
+
GDMonoClass *type_class = GDMonoUtils::type_get_proxy_class(type_name);
ERR_FAIL_NULL_V(type_class, NULL);
@@ -695,6 +830,14 @@ void *CSharpLanguage::alloc_instance_binding_data(Object *p_object) {
void CSharpLanguage::free_instance_binding_data(void *p_data) {
+ if (GDMono::get_singleton() == NULL) {
+#ifdef DEBUG_ENABLED
+ CRASH_COND(!gchandle_bindings.empty());
+#endif
+ // Mono runtime finalized, all the gchandle bindings were already released
+ return;
+ }
+
#ifndef NO_THREADS
script_bind_lock->lock();
#endif
@@ -782,7 +925,7 @@ bool CSharpInstance::set(const StringName &p_name, const Variant &p_value) {
if (method) {
MonoObject *ret = method->invoke(mono_object, args);
- if (ret && UNBOX_BOOLEAN(ret))
+ if (ret && GDMonoMarshal::unbox<MonoBoolean>(ret) == true)
return true;
}
@@ -896,46 +1039,6 @@ Variant CSharpInstance::call(const StringName &p_method, const Variant **p_args,
} else {
return Variant();
}
- } else if (p_method == CACHED_STRING_NAME(_awaited_signal_callback)) {
- // shitty hack..
- // TODO move to its own function, thx
-
- if (p_argcount < 1) {
- r_error.error = Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
- r_error.argument = 1;
- return Variant();
- }
-
- Ref<SignalAwaiterHandle> awaiter = *p_args[p_argcount - 1];
-
- if (awaiter.is_null()) {
- r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_error.argument = p_argcount - 1;
- r_error.expected = Variant::OBJECT;
- return Variant();
- }
-
- awaiter->set_completed(true);
-
- int extra_argc = p_argcount - 1;
- MonoArray *extra_args = mono_array_new(SCRIPTS_DOMAIN, CACHED_CLASS_RAW(MonoObject), extra_argc);
-
- for (int i = 0; i < extra_argc; i++) {
- MonoObject *boxed = GDMonoMarshal::variant_to_mono_object(*p_args[i]);
- mono_array_set(extra_args, MonoObject *, i, boxed);
- }
-
- GDMonoUtils::GodotObject__AwaitedSignalCallback thunk = CACHED_METHOD_THUNK(GodotObject, _AwaitedSignalCallback);
-
- MonoObject *ex = NULL;
- thunk(mono_object, &extra_args, awaiter->get_target(), &ex);
-
- if (ex) {
- mono_print_unhandled_exception(ex);
- ERR_FAIL_V(Variant());
- }
-
- return Variant();
}
top = top->get_parent_class();
@@ -1232,8 +1335,11 @@ bool CSharpScript::_update_exports() {
for (int i = 0; i < fields.size(); i++) {
GDMonoField *field = fields[i];
- if (field->is_static() || field->get_visibility() != GDMono::PUBLIC)
+ if (field->is_static()) {
+ if (field->has_attribute(CACHED_CLASS(ExportAttribute)))
+ ERR_PRINTS("Cannot export field because it is static: " + top->get_full_name() + "." + field->get_name());
continue;
+ }
String name = field->get_name();
StringName cname = name;
@@ -1241,17 +1347,39 @@ bool CSharpScript::_update_exports() {
if (member_info.has(cname))
continue;
- Variant::Type type = GDMonoMarshal::managed_to_variant_type(field->get_type());
+ ManagedType field_type = field->get_type();
+ Variant::Type type = GDMonoMarshal::managed_to_variant_type(field_type);
if (field->has_attribute(CACHED_CLASS(ExportAttribute))) {
+ // Field has Export attribute
MonoObject *attr = field->get_attribute(CACHED_CLASS(ExportAttribute));
- // Field has Export attribute
- int hint = CACHED_FIELD(ExportAttribute, hint)->get_int_value(attr);
- String hint_string = CACHED_FIELD(ExportAttribute, hint_string)->get_string_value(attr);
- int usage = CACHED_FIELD(ExportAttribute, usage)->get_int_value(attr);
+ PropertyHint hint;
+ String hint_string;
+
+ if (type == Variant::NIL) {
+ ERR_PRINTS("Unknown type of exported field: " + top->get_full_name() + "." + field->get_name());
+ continue;
+ } else if (type == Variant::INT && field_type.type_encoding == MONO_TYPE_VALUETYPE && mono_class_is_enum(field_type.type_class->get_raw())) {
+ type = Variant::INT;
+ hint = PROPERTY_HINT_ENUM;
+
+ Vector<MonoClassField *> fields = field_type.type_class->get_enum_fields();
+
+ for (int i = 0; i < fields.size(); i++) {
+ if (i > 0)
+ hint_string += ",";
+ hint_string += mono_field_get_name(fields[i]);
+ }
+ } else if (type == Variant::OBJECT && CACHED_CLASS(GodotReference)->is_assignable_from(field_type.type_class)) {
+ hint = PROPERTY_HINT_RESOURCE_TYPE;
+ hint_string = NATIVE_GDMONOCLASS_NAME(field_type.type_class);
+ } else {
+ hint = PropertyHint(CACHED_FIELD(ExportAttribute, hint)->get_int_value(attr));
+ hint_string = CACHED_FIELD(ExportAttribute, hint_string)->get_string_value(attr);
+ }
- PropertyInfo prop_info = PropertyInfo(type, name, PropertyHint(hint), hint_string, PropertyUsageFlags(usage));
+ PropertyInfo prop_info = PropertyInfo(type, name, hint, hint_string, PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SCRIPT_VARIABLE);
member_info[cname] = prop_info;
exported_members_cache.push_back(prop_info);
@@ -1327,6 +1455,34 @@ void CSharpScript::_resource_path_changed() {
}
}
+bool CSharpScript::_get(const StringName &p_name, Variant &r_ret) const {
+
+ if (p_name == CSharpLanguage::singleton->string_names._script_source) {
+
+ r_ret = get_source_code();
+ return true;
+ }
+
+ return false;
+}
+
+bool CSharpScript::_set(const StringName &p_name, const Variant &p_value) {
+
+ if (p_name == CSharpLanguage::singleton->string_names._script_source) {
+
+ set_source_code(p_value);
+ reload();
+ return true;
+ }
+
+ return false;
+}
+
+void CSharpScript::_get_property_list(List<PropertyInfo> *p_properties) const {
+
+ p_properties->push_back(PropertyInfo(Variant::STRING, CSharpLanguage::singleton->string_names._script_source, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
+}
+
void CSharpScript::_bind_methods() {
ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "new", &CSharpScript::_new, MethodInfo(Variant::OBJECT, "new"));
@@ -1385,12 +1541,15 @@ bool CSharpScript::can_instance() const {
#ifdef TOOLS_ENABLED
if (Engine::get_singleton()->is_editor_hint()) {
- if (_create_project_solution_if_needed()) {
- CSharpProject::add_item(GodotSharpDirs::get_project_csproj_path(),
- "Compile",
- ProjectSettings::get_singleton()->globalize_path(get_path()));
- } else {
- ERR_PRINTS("Cannot add " + get_path() + " to the C# project because it could not be created.");
+
+ if (get_path().find("::") == -1) { // Ignore if built-in script. Can happen if the file is deleted...
+ if (_create_project_solution_if_needed()) {
+ CSharpProject::add_item(GodotSharpDirs::get_project_csproj_path(),
+ "Compile",
+ ProjectSettings::get_singleton()->globalize_path(get_path()));
+ } else {
+ ERR_PRINTS("Cannot add " + get_path() + " to the C# project because it could not be created.");
+ }
}
}
#endif
@@ -1640,11 +1799,6 @@ Error CSharpScript::reload(bool p_keep_state) {
return ERR_FILE_MISSING_DEPENDENCIES;
}
-String CSharpScript::get_node_type() const {
-
- return ""; // ?
-}
-
ScriptLanguage *CSharpScript::get_language() const {
return CSharpLanguage::get_singleton();
@@ -1672,16 +1826,6 @@ void CSharpScript::update_exports() {
#ifdef TOOLS_ENABLED
_update_exports();
-
- if (placeholders.size()) {
- Map<StringName, Variant> values;
- List<PropertyInfo> propnames;
- _update_exports_values(values, propnames);
-
- for (Set<PlaceHolderScriptInstance *>::Element *E = placeholders.front(); E; E = E->next()) {
- E->get()->update(propnames, values);
- }
- }
#endif
}
@@ -1908,9 +2052,10 @@ bool ResourceFormatSaverCSharpScript::recognize(const RES &p_resource) const {
CSharpLanguage::StringNameCache::StringNameCache() {
- _awaited_signal_callback = StaticCString::create("_AwaitedSignalCallback");
+ _signal_callback = StaticCString::create("_signal_callback");
_set = StaticCString::create("_set");
_get = StaticCString::create("_get");
_notification = StaticCString::create("_notification");
+ _script_source = StaticCString::create("script/source");
dotctor = StaticCString::create(".ctor");
}
diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h
index 3fcc3bdf04..255665b495 100644
--- a/modules/mono/csharp_script.h
+++ b/modules/mono/csharp_script.h
@@ -116,6 +116,9 @@ protected:
Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error);
virtual void _resource_path_changed();
+ bool _get(const StringName &p_name, Variant &r_ret) const;
+ bool _set(const StringName &p_name, const Variant &p_value);
+ void _get_property_list(List<PropertyInfo> *p_properties) const;
public:
virtual bool can_instance() const;
@@ -138,7 +141,6 @@ public:
virtual bool is_tool() const { return tool; }
virtual Ref<Script> get_base_script() const;
- virtual String get_node_type() const;
virtual ScriptLanguage *get_language() const;
/* TODO */ virtual void get_script_method_list(List<MethodInfo> *p_list) const {}
@@ -225,23 +227,26 @@ class CSharpLanguage : public ScriptLanguage {
struct StringNameCache {
- StringName _awaited_signal_callback;
+ StringName _signal_callback;
StringName _set;
StringName _get;
StringName _notification;
+ StringName _script_source;
StringName dotctor; // .ctor
StringNameCache();
};
- StringNameCache string_names;
-
int lang_idx;
public:
+ StringNameCache string_names;
+
_FORCE_INLINE_ int get_language_index() { return lang_idx; }
void set_language_index(int p_idx);
+ _FORCE_INLINE_ const StringNameCache &get_string_names() { return string_names; }
+
_FORCE_INLINE_ static CSharpLanguage *get_singleton() { return singleton; }
bool debug_break(const String &p_error, bool p_allow_continue = true);
@@ -265,12 +270,16 @@ public:
virtual void get_comment_delimiters(List<String> *p_delimiters) const;
virtual void get_string_delimiters(List<String> *p_delimiters) const;
virtual Ref<Script> get_template(const String &p_class_name, const String &p_base_class_name) const;
+ virtual bool is_using_templates();
+ virtual void make_template(const String &p_class_name, const String &p_base_class_name, Ref<Script> &p_script);
/* TODO */ virtual bool validate(const String &p_script, int &r_line_error, int &r_col_error, String &r_test_error, const String &p_path, List<String> *r_functions) const { return true; }
virtual Script *create_script() const;
virtual bool has_named_classes() const;
+ virtual bool supports_builtin_mode() const;
/* TODO? */ virtual int find_function(const String &p_function, const String &p_code) const { return -1; }
virtual String make_function(const String &p_class, const String &p_name, const PoolStringArray &p_args) const;
/* TODO? */ Error complete_code(const String &p_code, const String &p_base_path, Object *p_owner, List<String> *r_options, String &r_call_hint) { return ERR_UNAVAILABLE; }
+ virtual String _get_indentation() const;
/* TODO? */ virtual void auto_indent_code(String &p_code, int p_from_line, int p_to_line) const {}
/* TODO */ virtual void add_global_constant(const StringName &p_variable, const Variant &p_value) {}
diff --git a/modules/mono/doc_classes/@C#.xml b/modules/mono/doc_classes/@C#.xml
index 487ba9835f..5d27b32200 100644
--- a/modules/mono/doc_classes/@C#.xml
+++ b/modules/mono/doc_classes/@C#.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="@C#" category="Core" version="3.0.alpha.custom_build">
+<class name="@C#" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/modules/mono/doc_classes/CSharpScript.xml b/modules/mono/doc_classes/CSharpScript.xml
index 5f21c9774d..ccc24b832c 100644
--- a/modules/mono/doc_classes/CSharpScript.xml
+++ b/modules/mono/doc_classes/CSharpScript.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="CSharpScript" inherits="Script" category="Core" version="3.0.alpha.custom_build">
+<class name="CSharpScript" inherits="Script" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/modules/mono/doc_classes/GodotSharp.xml b/modules/mono/doc_classes/GodotSharp.xml
index e7e06ddd8f..9edbd18fc1 100644
--- a/modules/mono/doc_classes/GodotSharp.xml
+++ b/modules/mono/doc_classes/GodotSharp.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="GodotSharp" inherits="Object" category="Core" version="3.0.alpha.custom_build">
+<class name="GodotSharp" inherits="Object" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/modules/mono/editor/GodotSharpTools/Build/BuildSystem.cs b/modules/mono/editor/GodotSharpTools/Build/BuildSystem.cs
index 5544233eb7..04da0600cc 100644
--- a/modules/mono/editor/GodotSharpTools/Build/BuildSystem.cs
+++ b/modules/mono/editor/GodotSharpTools/Build/BuildSystem.cs
@@ -4,6 +4,7 @@ using System.Collections.Specialized;
using System.Diagnostics;
using System.IO;
using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
using System.Security;
using Microsoft.Build.Framework;
@@ -12,22 +13,27 @@ namespace GodotSharpTools.Build
public class BuildInstance : IDisposable
{
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static void godot_icall_BuildInstance_ExitCallback(string solution, string config, int exitCode);
+ private extern static void godot_icall_BuildInstance_ExitCallback(string solution, string config, int exitCode);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static string godot_icall_BuildInstance_get_MSBuildPath();
+ private extern static void godot_icall_BuildInstance_get_MSBuildInfo(ref string msbuildPath, ref string frameworkPath);
- private static string MSBuildPath
+ private struct MSBuildInfo
{
- get
- {
- string ret = godot_icall_BuildInstance_get_MSBuildPath();
+ public string path;
+ public string frameworkPathOverride;
+ }
- if (ret == null)
- throw new FileNotFoundException("Cannot find the MSBuild executable.");
+ private static MSBuildInfo GetMSBuildInfo()
+ {
+ MSBuildInfo msbuildInfo = new MSBuildInfo();
- return ret;
- }
+ godot_icall_BuildInstance_get_MSBuildInfo(ref msbuildInfo.path, ref msbuildInfo.frameworkPathOverride);
+
+ if (msbuildInfo.path == null)
+ throw new FileNotFoundException("Cannot find the MSBuild executable.");
+
+ return msbuildInfo;
}
private string solution;
@@ -48,9 +54,19 @@ namespace GodotSharpTools.Build
public bool Build(string loggerAssemblyPath, string loggerOutputDir, string[] customProperties = null)
{
- string compilerArgs = BuildArguments(loggerAssemblyPath, loggerOutputDir, customProperties);
+ MSBuildInfo msbuildInfo = GetMSBuildInfo();
+
+ List<string> customPropertiesList = new List<string>();
+
+ if (customProperties != null)
+ customPropertiesList.AddRange(customProperties);
+
+ if (msbuildInfo.frameworkPathOverride != null)
+ customPropertiesList.Add("FrameworkPathOverride=" + msbuildInfo.frameworkPathOverride);
- ProcessStartInfo startInfo = new ProcessStartInfo(MSBuildPath, compilerArgs);
+ string compilerArgs = BuildArguments(loggerAssemblyPath, loggerOutputDir, customPropertiesList);
+
+ ProcessStartInfo startInfo = new ProcessStartInfo(msbuildInfo.path, compilerArgs);
// No console output, thanks
startInfo.RedirectStandardOutput = true;
@@ -82,9 +98,19 @@ namespace GodotSharpTools.Build
if (process != null)
throw new InvalidOperationException("Already in use");
- string compilerArgs = BuildArguments(loggerAssemblyPath, loggerOutputDir, customProperties);
+ MSBuildInfo msbuildInfo = GetMSBuildInfo();
+
+ List<string> customPropertiesList = new List<string>();
+
+ if (customProperties != null)
+ customPropertiesList.AddRange(customProperties);
+
+ if (msbuildInfo.frameworkPathOverride.Length > 0)
+ customPropertiesList.Add("FrameworkPathOverride=" + msbuildInfo.frameworkPathOverride);
- ProcessStartInfo startInfo = new ProcessStartInfo("msbuild", compilerArgs);
+ string compilerArgs = BuildArguments(loggerAssemblyPath, loggerOutputDir, customPropertiesList);
+
+ ProcessStartInfo startInfo = new ProcessStartInfo(msbuildInfo.path, compilerArgs);
// No console output, thanks
startInfo.RedirectStandardOutput = true;
@@ -101,10 +127,13 @@ namespace GodotSharpTools.Build
process.Start();
+ process.BeginOutputReadLine();
+ process.BeginErrorReadLine();
+
return true;
}
- private string BuildArguments(string loggerAssemblyPath, string loggerOutputDir, string[] customProperties)
+ private string BuildArguments(string loggerAssemblyPath, string loggerOutputDir, List<string> customProperties)
{
string arguments = string.Format(@"""{0}"" /v:normal /t:Build ""/p:{1}"" ""/l:{2},{3};{4}""",
solution,
@@ -114,12 +143,9 @@ namespace GodotSharpTools.Build
loggerOutputDir
);
- if (customProperties != null)
+ foreach (string customProperty in customProperties)
{
- foreach (string customProperty in customProperties)
- {
- arguments += " /p:" + customProperty;
- }
+ arguments += " \"/p:" + customProperty + "\"";
}
return arguments;
diff --git a/modules/mono/editor/GodotSharpTools/GodotSharpTools.sln b/modules/mono/editor/GodotSharpTools/GodotSharpTools.sln
index 7eabcdff5d..5f7d0e8a39 100644
--- a/modules/mono/editor/GodotSharpTools/GodotSharpTools.sln
+++ b/modules/mono/editor/GodotSharpTools/GodotSharpTools.sln
@@ -1,17 +1,17 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 2012
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GodotSharpTools", "GodotSharpTools.csproj", "{A8CDAD94-C6D4-4B19-A7E7-76C53CC92984}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {A8CDAD94-C6D4-4B19-A7E7-76C53CC92984}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {A8CDAD94-C6D4-4B19-A7E7-76C53CC92984}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {A8CDAD94-C6D4-4B19-A7E7-76C53CC92984}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {A8CDAD94-C6D4-4B19-A7E7-76C53CC92984}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
-EndGlobal
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2012
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GodotSharpTools", "GodotSharpTools.csproj", "{A8CDAD94-C6D4-4B19-A7E7-76C53CC92984}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {A8CDAD94-C6D4-4B19-A7E7-76C53CC92984}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A8CDAD94-C6D4-4B19-A7E7-76C53CC92984}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A8CDAD94-C6D4-4B19-A7E7-76C53CC92984}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A8CDAD94-C6D4-4B19-A7E7-76C53CC92984}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+EndGlobal
diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp
index 123f00ea10..59a2b73dbc 100644
--- a/modules/mono/editor/bindings_generator.cpp
+++ b/modules/mono/editor/bindings_generator.cpp
@@ -31,12 +31,12 @@
#ifdef DEBUG_METHODS_ENABLED
+#include "engine.h"
#include "global_constants.h"
#include "io/compression.h"
#include "os/dir_access.h"
#include "os/file_access.h"
#include "os/os.h"
-#include "project_settings.h"
#include "ucaps.h"
#include "../glue/cs_compressed.gen.h"
@@ -108,42 +108,6 @@ const char *BindingsGenerator::TypeInterface::DEFAULT_VARARG_C_IN = "\t%0 %1_in
bool BindingsGenerator::verbose_output = false;
-static bool is_csharp_keyword(const String &p_name) {
-
- // Reserved keywords
-
- return p_name == "abstract" || p_name == "as" || p_name == "base" || p_name == "bool" ||
- p_name == "break" || p_name == "byte" || p_name == "case" || p_name == "catch" ||
- p_name == "char" || p_name == "checked" || p_name == "class" || p_name == "const" ||
- p_name == "continue" || p_name == "decimal" || p_name == "default" || p_name == "delegate" ||
- p_name == "do" || p_name == "double" || p_name == "else" || p_name == "enum" ||
- p_name == "event" || p_name == "explicit" || p_name == "extern" || p_name == "false" ||
- p_name == "finally" || p_name == "fixed" || p_name == "float" || p_name == "for" ||
- p_name == "forech" || p_name == "goto" || p_name == "if" || p_name == "implicit" ||
- p_name == "in" || p_name == "int" || p_name == "interface" || p_name == "internal" ||
- p_name == "is" || p_name == "lock" || p_name == "long" || p_name == "namespace" ||
- p_name == "new" || p_name == "null" || p_name == "object" || p_name == "operator" ||
- p_name == "out" || p_name == "override" || p_name == "params" || p_name == "private" ||
- p_name == "protected" || p_name == "public" || p_name == "readonly" || p_name == "ref" ||
- p_name == "return" || p_name == "sbyte" || p_name == "sealed" || p_name == "short" ||
- p_name == "sizeof" || p_name == "stackalloc" || p_name == "static" || p_name == "string" ||
- p_name == "struct" || p_name == "switch" || p_name == "this" || p_name == "throw" ||
- p_name == "true" || p_name == "try" || p_name == "typeof" || p_name == "uint" || p_name == "ulong" ||
- p_name == "unchecked" || p_name == "unsafe" || p_name == "ushort" || p_name == "using" ||
- p_name == "virtual" || p_name == "volatile" || p_name == "void" || p_name == "while";
-}
-
-static bool is_singleton_black_listed(const String &p_type) {
-
- return p_type == "IP_Unix" || p_type == "InputDefault" || p_type == "AudioServerSW" || p_type == "PhysicsServerSW" ||
- p_type == "Physics2DServerSW" || p_type == "SpatialSoundServerSW" || p_type == "SpatialSound2DServerSW";
-}
-
-inline static String escape_csharp_keyword(const String &p_name) {
-
- return is_csharp_keyword(p_name) ? "@" + p_name : p_name;
-}
-
static String snake_to_pascal_case(const String &p_identifier) {
String ret;
@@ -247,9 +211,6 @@ void BindingsGenerator::_generate_header_icalls() {
void BindingsGenerator::_generate_method_icalls(const TypeInterface &p_itype) {
- if (p_itype.base_name.length() && obj_types[p_itype.base_name].is_singleton && is_singleton_black_listed(p_itype.name))
- return;
-
for (const List<MethodInterface>::Element *E = p_itype.methods.front(); E; E = E->next()) {
const MethodInterface &imethod = E->get();
@@ -359,9 +320,9 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_output_dir, bo
int global_constants_count = GlobalConstants::get_global_constant_count();
if (global_constants_count > 0) {
- Map<String, DocData::ClassDoc>::Element *match = EditorHelp::get_doc_data()->class_list.find("@Global Scope");
+ Map<String, DocData::ClassDoc>::Element *match = EditorHelp::get_doc_data()->class_list.find("@GlobalScope");
- ERR_EXPLAIN("Could not find `@Global Scope` in DocData");
+ ERR_EXPLAIN("Could not find `@GlobalScope` in DocData");
ERR_FAIL_COND_V(!match, ERR_BUG);
const DocData::ClassDoc &global_scope_doc = match->value();
@@ -477,6 +438,9 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_output_dir, bo
return sln_error;
}
+ if (verbose_output)
+ OS::get_singleton()->print("The solution and C# project for the Core API was generated successfully\n");
+
return OK;
}
@@ -569,6 +533,9 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_output_dir,
return sln_error;
}
+ if (verbose_output)
+ OS::get_singleton()->print("The solution and C# project for the Editor API was generated successfully\n");
+
return OK;
}
@@ -576,13 +543,8 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_output_dir,
// e.g.: warning CS0108: 'SpriteBase3D.FLAG_MAX' hides inherited member 'GeometryInstance.FLAG_MAX'. Use the new keyword if hiding was intended.
Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const String &p_output_file) {
- int method_bind_count = 0;
-
bool is_derived_type = itype.base_name.length();
- if (is_derived_type && obj_types[itype.base_name].is_singleton && is_singleton_black_listed(itype.name))
- return ERR_SKIP;
-
List<InternalCall> &custom_icalls = itype.api_type == ClassDB::API_EDITOR ? editor_custom_icalls : core_custom_icalls;
if (verbose_output)
@@ -590,51 +552,51 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
String ctor_method(ICALL_PREFIX + itype.proxy_name + "_Ctor");
- List<String> cs_file;
+ List<String> output;
- cs_file.push_back("using System;\n"); // IntPtr
+ output.push_back("using System;\n"); // IntPtr
if (itype.requires_collections)
- cs_file.push_back("using System.Collections.Generic;\n"); // Dictionary
+ output.push_back("using System.Collections.Generic;\n"); // Dictionary
- cs_file.push_back("\nnamespace " BINDINGS_NAMESPACE "\n" OPEN_BLOCK);
+ output.push_back("\nnamespace " BINDINGS_NAMESPACE "\n" OPEN_BLOCK);
const DocData::ClassDoc *class_doc = itype.class_doc;
if (class_doc && class_doc->description.size()) {
- cs_file.push_back(INDENT1 "/// <summary>\n");
+ output.push_back(INDENT1 "/// <summary>\n");
Vector<String> description_lines = class_doc->description.split("\n");
for (int i = 0; i < description_lines.size(); i++) {
if (description_lines[i].size()) {
- cs_file.push_back(INDENT1 "/// ");
- cs_file.push_back(description_lines[i].strip_edges().xml_escape());
- cs_file.push_back("\n");
+ output.push_back(INDENT1 "/// ");
+ output.push_back(description_lines[i].strip_edges().xml_escape());
+ output.push_back("\n");
}
}
- cs_file.push_back(INDENT1 "/// </summary>\n");
+ output.push_back(INDENT1 "/// </summary>\n");
}
- cs_file.push_back(INDENT1 "public ");
- cs_file.push_back(itype.is_singleton ? "static class " : "class ");
- cs_file.push_back(itype.proxy_name);
+ output.push_back(INDENT1 "public ");
+ output.push_back(itype.is_singleton ? "static class " : "class ");
+ output.push_back(itype.proxy_name);
if (itype.is_singleton || !itype.is_object_type) {
- cs_file.push_back("\n");
+ output.push_back("\n");
} else if (!is_derived_type) {
- cs_file.push_back(" : IDisposable\n");
+ output.push_back(" : IDisposable\n");
} else if (obj_types.has(itype.base_name)) {
- cs_file.push_back(" : ");
- cs_file.push_back(obj_types[itype.base_name].proxy_name);
- cs_file.push_back("\n");
+ output.push_back(" : ");
+ output.push_back(obj_types[itype.base_name].proxy_name);
+ output.push_back("\n");
} else {
- ERR_PRINTS("Base type ' " + itype.base_name + "' does not exist");
+ ERR_PRINTS("Base type '" + itype.base_name + "' does not exist, for class " + itype.name);
return ERR_INVALID_DATA;
}
- cs_file.push_back(INDENT1 "{");
+ output.push_back(INDENT1 "{");
if (class_doc) {
@@ -644,270 +606,165 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
const DocData::ConstantDoc &const_doc = class_doc->constants[i];
if (const_doc.description.size()) {
- cs_file.push_back(MEMBER_BEGIN "/// <summary>\n");
+ output.push_back(MEMBER_BEGIN "/// <summary>\n");
Vector<String> description_lines = const_doc.description.split("\n");
for (int i = 0; i < description_lines.size(); i++) {
if (description_lines[i].size()) {
- cs_file.push_back(INDENT2 "/// ");
- cs_file.push_back(description_lines[i].strip_edges().xml_escape());
- cs_file.push_back("\n");
+ output.push_back(INDENT2 "/// ");
+ output.push_back(description_lines[i].strip_edges().xml_escape());
+ output.push_back("\n");
}
}
- cs_file.push_back(INDENT2 "/// </summary>");
+ output.push_back(INDENT2 "/// </summary>");
}
- cs_file.push_back(MEMBER_BEGIN "public const int ");
- cs_file.push_back(const_doc.name);
- cs_file.push_back(" = ");
- cs_file.push_back(const_doc.value);
- cs_file.push_back(";");
+ output.push_back(MEMBER_BEGIN "public const int ");
+ output.push_back(const_doc.name);
+ output.push_back(" = ");
+ output.push_back(const_doc.value);
+ output.push_back(";");
}
if (class_doc->constants.size())
- cs_file.push_back("\n");
+ output.push_back("\n");
// Add properties
- const Vector<DocData::PropertyDoc> &properties = itype.class_doc->properties;
+ const Vector<DocData::PropertyDoc> &properties = class_doc->properties;
for (int i = 0; i < properties.size(); i++) {
const DocData::PropertyDoc &prop_doc = properties[i];
-
- const MethodInterface *setter = itype.find_method_by_name(prop_doc.setter);
-
- // Search it in base types too
- const TypeInterface *current_type = &itype;
- while (!setter && current_type->base_name.length()) {
- Map<String, TypeInterface>::Element *base_match = obj_types.find(current_type->base_name);
- ERR_FAIL_NULL_V(base_match, ERR_BUG);
- current_type = &base_match->get();
- setter = current_type->find_method_by_name(prop_doc.setter);
- }
-
- const MethodInterface *getter = itype.find_method_by_name(prop_doc.getter);
-
- // Search it in base types too
- current_type = &itype;
- while (!getter && current_type->base_name.length()) {
- Map<String, TypeInterface>::Element *base_match = obj_types.find(current_type->base_name);
- ERR_FAIL_NULL_V(base_match, ERR_BUG);
- current_type = &base_match->get();
- getter = current_type->find_method_by_name(prop_doc.getter);
- }
-
- ERR_FAIL_COND_V(!setter && !getter, ERR_BUG);
-
- bool is_valid = false;
- int prop_index = ClassDB::get_property_index(itype.name, prop_doc.name, &is_valid);
- ERR_FAIL_COND_V(!is_valid, ERR_BUG);
-
- if (setter) {
- int setter_argc = prop_index != -1 ? 2 : 1;
- ERR_FAIL_COND_V(setter->arguments.size() != setter_argc, ERR_BUG);
- }
-
- if (getter) {
- int getter_argc = prop_index != -1 ? 1 : 0;
- ERR_FAIL_COND_V(getter->arguments.size() != getter_argc, ERR_BUG);
- }
-
- if (getter && setter) {
- ERR_FAIL_COND_V(getter->return_type != setter->arguments.back()->get().type, ERR_BUG);
- }
-
- // Let's not trust PropertyDoc::type
- String proptype_name = getter ? getter->return_type : setter->arguments.back()->get().type;
-
- const TypeInterface *prop_itype = _get_type_by_name_or_null(proptype_name);
- if (!prop_itype) {
- // Try with underscore prefix
- prop_itype = _get_type_by_name_or_null("_" + proptype_name);
+ Error prop_err = _generate_cs_property(itype, prop_doc, output);
+ if (prop_err != OK) {
+ ERR_EXPLAIN("Failed to generate property '" + prop_doc.name + "' for class '" + itype.name + "'");
+ ERR_FAIL_V(prop_err);
}
-
- ERR_FAIL_NULL_V(prop_itype, ERR_BUG);
-
- String prop_proxy_name = escape_csharp_keyword(snake_to_pascal_case(prop_doc.name));
-
- // Prevent property and enclosing type from sharing the same name
- if (prop_proxy_name == itype.proxy_name) {
- if (verbose_output) {
- WARN_PRINTS("Name of property `" + prop_proxy_name + "` is ambiguous with the name of its class `" +
- itype.proxy_name + "`. Renaming property to `" + prop_proxy_name + "_`");
- }
-
- prop_proxy_name += "_";
- }
-
- if (prop_doc.description.size()) {
- cs_file.push_back(MEMBER_BEGIN "/// <summary>\n");
-
- Vector<String> description_lines = prop_doc.description.split("\n");
-
- for (int i = 0; i < description_lines.size(); i++) {
- if (description_lines[i].size()) {
- cs_file.push_back(INDENT2 "/// ");
- cs_file.push_back(description_lines[i].strip_edges().xml_escape());
- cs_file.push_back("\n");
- }
- }
-
- cs_file.push_back(INDENT2 "/// </summary>");
- }
-
- cs_file.push_back(MEMBER_BEGIN "public ");
-
- if (itype.is_singleton)
- cs_file.push_back("static ");
-
- cs_file.push_back(prop_itype->cs_type);
- cs_file.push_back(" ");
- cs_file.push_back(prop_proxy_name.replace("/", "__"));
- cs_file.push_back("\n" INDENT2 OPEN_BLOCK);
-
- if (getter) {
- cs_file.push_back(INDENT3 "get\n" OPEN_BLOCK_L3);
- cs_file.push_back("return ");
- cs_file.push_back(getter->proxy_name + "(");
- if (prop_index != -1)
- cs_file.push_back(itos(prop_index));
- cs_file.push_back(");\n" CLOSE_BLOCK_L3);
- }
-
- if (setter) {
- cs_file.push_back(INDENT3 "set\n" OPEN_BLOCK_L3);
- cs_file.push_back(setter->proxy_name + "(");
- if (prop_index != -1)
- cs_file.push_back(itos(prop_index) + ", ");
- cs_file.push_back("value);\n" CLOSE_BLOCK_L3);
- }
-
- cs_file.push_back(CLOSE_BLOCK_L2);
}
if (class_doc->properties.size())
- cs_file.push_back("\n");
+ output.push_back("\n");
}
if (!itype.is_object_type) {
- cs_file.push_back(MEMBER_BEGIN "private const string " BINDINGS_NATIVE_NAME_FIELD " = \"" + itype.name + "\";\n");
- cs_file.push_back(MEMBER_BEGIN "private bool disposed = false;\n");
- cs_file.push_back(MEMBER_BEGIN "internal IntPtr " BINDINGS_PTR_FIELD ";\n");
+ output.push_back(MEMBER_BEGIN "private const string " BINDINGS_NATIVE_NAME_FIELD " = \"" + itype.name + "\";\n");
+ output.push_back(MEMBER_BEGIN "private bool disposed = false;\n");
+ output.push_back(MEMBER_BEGIN "internal IntPtr " BINDINGS_PTR_FIELD ";\n");
- cs_file.push_back(MEMBER_BEGIN "internal static IntPtr " CS_SMETHOD_GETINSTANCE "(");
- cs_file.push_back(itype.proxy_name);
- cs_file.push_back(" instance)\n" OPEN_BLOCK_L2 "return instance == null ? IntPtr.Zero : instance." BINDINGS_PTR_FIELD ";\n" CLOSE_BLOCK_L2);
+ output.push_back(MEMBER_BEGIN "internal static IntPtr " CS_SMETHOD_GETINSTANCE "(");
+ output.push_back(itype.proxy_name);
+ output.push_back(" instance)\n" OPEN_BLOCK_L2 "return instance == null ? IntPtr.Zero : instance." BINDINGS_PTR_FIELD ";\n" CLOSE_BLOCK_L2);
// Add Destructor
- cs_file.push_back(MEMBER_BEGIN "~");
- cs_file.push_back(itype.proxy_name);
- cs_file.push_back("()\n" OPEN_BLOCK_L2 "Dispose(false);\n" CLOSE_BLOCK_L2);
+ output.push_back(MEMBER_BEGIN "~");
+ output.push_back(itype.proxy_name);
+ output.push_back("()\n" OPEN_BLOCK_L2 "Dispose(false);\n" CLOSE_BLOCK_L2);
// Add the Dispose from IDisposable
- cs_file.push_back(MEMBER_BEGIN "public void Dispose()\n" OPEN_BLOCK_L2 "Dispose(true);\n" INDENT3 "GC.SuppressFinalize(this);\n" CLOSE_BLOCK_L2);
+ output.push_back(MEMBER_BEGIN "public void Dispose()\n" OPEN_BLOCK_L2 "Dispose(true);\n" INDENT3 "GC.SuppressFinalize(this);\n" CLOSE_BLOCK_L2);
// Add the virtual Dispose
- cs_file.push_back(MEMBER_BEGIN "public virtual void Dispose(bool disposing)\n" OPEN_BLOCK_L2
- "if (disposed) return;\n" INDENT3
- "if (" BINDINGS_PTR_FIELD " != IntPtr.Zero)\n" OPEN_BLOCK_L3 "NativeCalls.godot_icall_");
- cs_file.push_back(itype.proxy_name);
- cs_file.push_back("_Dtor(" BINDINGS_PTR_FIELD ");\n" INDENT5 BINDINGS_PTR_FIELD " = IntPtr.Zero;\n" CLOSE_BLOCK_L3 INDENT3
- "GC.SuppressFinalize(this);\n" INDENT3 "disposed = true;\n" CLOSE_BLOCK_L2);
-
- cs_file.push_back(MEMBER_BEGIN "internal ");
- cs_file.push_back(itype.proxy_name);
- cs_file.push_back("(IntPtr " BINDINGS_PTR_FIELD ")\n" OPEN_BLOCK_L2 "this." BINDINGS_PTR_FIELD " = " BINDINGS_PTR_FIELD ";\n" CLOSE_BLOCK_L2);
-
- cs_file.push_back(MEMBER_BEGIN "public bool HasValidHandle()\n" OPEN_BLOCK_L2
- "return " BINDINGS_PTR_FIELD " == IntPtr.Zero;\n" CLOSE_BLOCK_L2);
+ output.push_back(MEMBER_BEGIN "public virtual void Dispose(bool disposing)\n" OPEN_BLOCK_L2
+ "if (disposed) return;\n" INDENT3
+ "if (" BINDINGS_PTR_FIELD " != IntPtr.Zero)\n" OPEN_BLOCK_L3 "NativeCalls.godot_icall_");
+ output.push_back(itype.proxy_name);
+ output.push_back("_Dtor(" BINDINGS_PTR_FIELD ");\n" INDENT5 BINDINGS_PTR_FIELD " = IntPtr.Zero;\n" CLOSE_BLOCK_L3 INDENT3
+ "GC.SuppressFinalize(this);\n" INDENT3 "disposed = true;\n" CLOSE_BLOCK_L2);
+
+ output.push_back(MEMBER_BEGIN "internal ");
+ output.push_back(itype.proxy_name);
+ output.push_back("(IntPtr " BINDINGS_PTR_FIELD ")\n" OPEN_BLOCK_L2 "this." BINDINGS_PTR_FIELD " = " BINDINGS_PTR_FIELD ";\n" CLOSE_BLOCK_L2);
+
+ output.push_back(MEMBER_BEGIN "public IntPtr NativeInstance\n" OPEN_BLOCK_L2
+ "get { return " BINDINGS_PTR_FIELD "; }\n" CLOSE_BLOCK_L2);
} else if (itype.is_singleton) {
// Add the type name and the singleton pointer as static fields
- cs_file.push_back(MEMBER_BEGIN "private const string " BINDINGS_NATIVE_NAME_FIELD " = \"");
- cs_file.push_back(itype.name);
- cs_file.push_back("\";\n");
+ output.push_back(MEMBER_BEGIN "private const string " BINDINGS_NATIVE_NAME_FIELD " = \"");
+ output.push_back(itype.name);
+ output.push_back("\";\n");
- cs_file.push_back(INDENT2 "internal static IntPtr " BINDINGS_PTR_FIELD " = ");
- cs_file.push_back(itype.api_type == ClassDB::API_EDITOR ? CS_CLASS_NATIVECALLS_EDITOR : CS_CLASS_NATIVECALLS);
- cs_file.push_back("." ICALL_PREFIX);
- cs_file.push_back(itype.name);
- cs_file.push_back(SINGLETON_ICALL_SUFFIX "();\n");
+ output.push_back(INDENT2 "internal static IntPtr " BINDINGS_PTR_FIELD " = ");
+ output.push_back(itype.api_type == ClassDB::API_EDITOR ? CS_CLASS_NATIVECALLS_EDITOR : CS_CLASS_NATIVECALLS);
+ output.push_back("." ICALL_PREFIX);
+ output.push_back(itype.name);
+ output.push_back(SINGLETON_ICALL_SUFFIX "();\n");
} else {
// Add member fields
- cs_file.push_back(MEMBER_BEGIN "private const string " BINDINGS_NATIVE_NAME_FIELD " = \"");
- cs_file.push_back(itype.name);
- cs_file.push_back("\";\n");
+ output.push_back(MEMBER_BEGIN "private const string " BINDINGS_NATIVE_NAME_FIELD " = \"");
+ output.push_back(itype.name);
+ output.push_back("\";\n");
// Only the base class stores the pointer to the native object
// This pointer is expected to be and must be of type Object*
if (!is_derived_type) {
- cs_file.push_back(MEMBER_BEGIN "private bool disposed = false;\n");
- cs_file.push_back(INDENT2 "internal IntPtr " BINDINGS_PTR_FIELD ";\n");
- cs_file.push_back(INDENT2 "internal bool " CS_FIELD_MEMORYOWN ";\n");
+ output.push_back(MEMBER_BEGIN "private bool disposed = false;\n");
+ output.push_back(INDENT2 "internal IntPtr " BINDINGS_PTR_FIELD ";\n");
+ output.push_back(INDENT2 "internal bool " CS_FIELD_MEMORYOWN ";\n");
}
// Add default constructor
if (itype.is_instantiable) {
- cs_file.push_back(MEMBER_BEGIN "public ");
- cs_file.push_back(itype.proxy_name);
- cs_file.push_back("() : this(");
- cs_file.push_back(itype.memory_own ? "true" : "false");
+ output.push_back(MEMBER_BEGIN "public ");
+ output.push_back(itype.proxy_name);
+ output.push_back("() : this(");
+ output.push_back(itype.memory_own ? "true" : "false");
// The default constructor may also be called by the engine when instancing existing native objects
// The engine will initialize the pointer field of the managed side before calling the constructor
// This is why we only allocate a new native object from the constructor if the pointer field is not set
- cs_file.push_back(")\n" OPEN_BLOCK_L2 "if (" BINDINGS_PTR_FIELD " == IntPtr.Zero)\n" INDENT4 BINDINGS_PTR_FIELD " = ");
- cs_file.push_back(itype.api_type == ClassDB::API_EDITOR ? CS_CLASS_NATIVECALLS_EDITOR : CS_CLASS_NATIVECALLS);
- cs_file.push_back("." + ctor_method);
- cs_file.push_back("(this);\n" CLOSE_BLOCK_L2);
+ output.push_back(")\n" OPEN_BLOCK_L2 "if (" BINDINGS_PTR_FIELD " == IntPtr.Zero)\n" INDENT4 BINDINGS_PTR_FIELD " = ");
+ output.push_back(itype.api_type == ClassDB::API_EDITOR ? CS_CLASS_NATIVECALLS_EDITOR : CS_CLASS_NATIVECALLS);
+ output.push_back("." + ctor_method);
+ output.push_back("(this);\n" CLOSE_BLOCK_L2);
} else {
// Hide the constructor
- cs_file.push_back(MEMBER_BEGIN "internal ");
- cs_file.push_back(itype.proxy_name);
- cs_file.push_back("() {}\n");
+ output.push_back(MEMBER_BEGIN "internal ");
+ output.push_back(itype.proxy_name);
+ output.push_back("() {}\n");
}
// Add.. em.. trick constructor. Sort of.
- cs_file.push_back(MEMBER_BEGIN "internal ");
- cs_file.push_back(itype.proxy_name);
+ output.push_back(MEMBER_BEGIN "internal ");
+ output.push_back(itype.proxy_name);
if (is_derived_type) {
- cs_file.push_back("(bool " CS_FIELD_MEMORYOWN ") : base(" CS_FIELD_MEMORYOWN ") {}\n");
+ output.push_back("(bool " CS_FIELD_MEMORYOWN ") : base(" CS_FIELD_MEMORYOWN ") {}\n");
} else {
- cs_file.push_back("(bool " CS_FIELD_MEMORYOWN ")\n" OPEN_BLOCK_L2
- "this." CS_FIELD_MEMORYOWN " = " CS_FIELD_MEMORYOWN ";\n" CLOSE_BLOCK_L2);
+ output.push_back("(bool " CS_FIELD_MEMORYOWN ")\n" OPEN_BLOCK_L2
+ "this." CS_FIELD_MEMORYOWN " = " CS_FIELD_MEMORYOWN ";\n" CLOSE_BLOCK_L2);
}
// Add methods
if (!is_derived_type) {
- cs_file.push_back(MEMBER_BEGIN "public bool HasValidHandle()\n" OPEN_BLOCK_L2
- "return " BINDINGS_PTR_FIELD " == IntPtr.Zero;\n" CLOSE_BLOCK_L2);
+ output.push_back(MEMBER_BEGIN "public IntPtr NativeInstance\n" OPEN_BLOCK_L2
+ "get { return " BINDINGS_PTR_FIELD "; }\n" CLOSE_BLOCK_L2);
- cs_file.push_back(MEMBER_BEGIN "internal static IntPtr " CS_SMETHOD_GETINSTANCE "(Object instance)\n" OPEN_BLOCK_L2
- "return instance == null ? IntPtr.Zero : instance." BINDINGS_PTR_FIELD ";\n" CLOSE_BLOCK_L2);
+ output.push_back(MEMBER_BEGIN "internal static IntPtr " CS_SMETHOD_GETINSTANCE "(Object instance)\n" OPEN_BLOCK_L2
+ "return instance == null ? IntPtr.Zero : instance." BINDINGS_PTR_FIELD ";\n" CLOSE_BLOCK_L2);
}
if (!is_derived_type) {
// Add destructor
- cs_file.push_back(MEMBER_BEGIN "~");
- cs_file.push_back(itype.proxy_name);
- cs_file.push_back("()\n" OPEN_BLOCK_L2 "Dispose(false);\n" CLOSE_BLOCK_L2);
+ output.push_back(MEMBER_BEGIN "~");
+ output.push_back(itype.proxy_name);
+ output.push_back("()\n" OPEN_BLOCK_L2 "Dispose(false);\n" CLOSE_BLOCK_L2);
// Add the Dispose from IDisposable
- cs_file.push_back(MEMBER_BEGIN "public void Dispose()\n" OPEN_BLOCK_L2 "Dispose(true);\n" INDENT3 "GC.SuppressFinalize(this);\n" CLOSE_BLOCK_L2);
+ output.push_back(MEMBER_BEGIN "public void Dispose()\n" OPEN_BLOCK_L2 "Dispose(true);\n" INDENT3 "GC.SuppressFinalize(this);\n" CLOSE_BLOCK_L2);
// Add the virtual Dispose
- cs_file.push_back(MEMBER_BEGIN "public virtual void Dispose(bool disposing)\n" OPEN_BLOCK_L2
- "if (disposed) return;\n" INDENT3
- "if (" BINDINGS_PTR_FIELD " != IntPtr.Zero)\n" OPEN_BLOCK_L3
- "if (" CS_FIELD_MEMORYOWN ")\n" OPEN_BLOCK_L4 CS_FIELD_MEMORYOWN
- " = false;\n" INDENT5 CS_CLASS_NATIVECALLS "." ICALL_OBJECT_DTOR
- "(" BINDINGS_PTR_FIELD ");\n" INDENT5 BINDINGS_PTR_FIELD
- " = IntPtr.Zero;\n" CLOSE_BLOCK_L4 CLOSE_BLOCK_L3 INDENT3
- "GC.SuppressFinalize(this);\n" INDENT3 "disposed = true;\n" CLOSE_BLOCK_L2);
+ output.push_back(MEMBER_BEGIN "public virtual void Dispose(bool disposing)\n" OPEN_BLOCK_L2
+ "if (disposed) return;\n" INDENT3
+ "if (" BINDINGS_PTR_FIELD " != IntPtr.Zero)\n" OPEN_BLOCK_L3
+ "if (" CS_FIELD_MEMORYOWN ")\n" OPEN_BLOCK_L4 CS_FIELD_MEMORYOWN
+ " = false;\n" INDENT5 CS_CLASS_NATIVECALLS "." ICALL_OBJECT_DTOR
+ "(" BINDINGS_PTR_FIELD ");\n" INDENT5 BINDINGS_PTR_FIELD
+ " = IntPtr.Zero;\n" CLOSE_BLOCK_L4 CLOSE_BLOCK_L3 INDENT3
+ "GC.SuppressFinalize(this);\n" INDENT3 "disposed = true;\n" CLOSE_BLOCK_L2);
Map<String, TypeInterface>::Element *array_itype = builtin_types.find("Array");
@@ -916,419 +773,390 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
return ERR_BUG;
}
- cs_file.push_back(MEMBER_BEGIN "private void _AwaitedSignalCallback(");
- cs_file.push_back(array_itype->get().cs_type);
- cs_file.push_back(" args, SignalAwaiter awaiter)\n" OPEN_BLOCK_L2 "awaiter.SignalCallback(args);\n" CLOSE_BLOCK_L2);
-
Map<String, TypeInterface>::Element *object_itype = obj_types.find("Object");
if (!object_itype) {
- ERR_PRINT("BUG: Array type interface not found!");
+ ERR_PRINT("BUG: Object type interface not found!");
return ERR_BUG;
}
- cs_file.push_back(MEMBER_BEGIN "public " CS_CLASS_SIGNALAWAITER " ToSignal(");
- cs_file.push_back(object_itype->get().cs_type);
- cs_file.push_back(" source, string signal)\n" OPEN_BLOCK_L2
- "return new " CS_CLASS_SIGNALAWAITER "(source, signal, this);\n" CLOSE_BLOCK_L2);
+ output.push_back(MEMBER_BEGIN "public " CS_CLASS_SIGNALAWAITER " ToSignal(");
+ output.push_back(object_itype->get().cs_type);
+ output.push_back(" source, string signal)\n" OPEN_BLOCK_L2
+ "return new " CS_CLASS_SIGNALAWAITER "(source, signal, this);\n" CLOSE_BLOCK_L2);
}
}
Map<String, String>::Element *extra_member = extra_members.find(itype.name);
if (extra_member)
- cs_file.push_back(extra_member->get());
+ output.push_back(extra_member->get());
+ int method_bind_count = 0;
for (const List<MethodInterface>::Element *E = itype.methods.front(); E; E = E->next()) {
const MethodInterface &imethod = E->get();
+ Error method_err = _generate_cs_method(itype, imethod, method_bind_count, output);
+ if (method_err != OK) {
+ ERR_EXPLAIN("Failed to generate method '" + imethod.name + "' for class '" + itype.name + "'");
+ ERR_FAIL_V(method_err);
+ }
+ }
- const TypeInterface *return_type = _get_type_by_name_or_placeholder(imethod.return_type);
+ if (itype.is_singleton) {
+ InternalCall singleton_icall = InternalCall(itype.api_type, ICALL_PREFIX + itype.name + SINGLETON_ICALL_SUFFIX, "IntPtr");
- String method_bind_field = "method_bind_" + itos(method_bind_count);
+ if (!find_icall_by_name(singleton_icall.name, custom_icalls))
+ custom_icalls.push_back(singleton_icall);
+ }
- String icall_params = method_bind_field + ", " + sformat(itype.cs_in, "this");
- String arguments_sig;
- String cs_in_statements;
+ if (itype.is_instantiable) {
+ InternalCall ctor_icall = InternalCall(itype.api_type, ctor_method, "IntPtr", itype.proxy_name + " obj");
- List<String> default_args_doc;
+ if (!find_icall_by_name(ctor_icall.name, custom_icalls))
+ custom_icalls.push_back(ctor_icall);
+ }
- // Retrieve information from the arguments
- for (const List<ArgumentInterface>::Element *F = imethod.arguments.front(); F; F = F->next()) {
- const ArgumentInterface &iarg = F->get();
- const TypeInterface *arg_type = _get_type_by_name_or_placeholder(iarg.type);
+ output.push_back(INDENT1 CLOSE_BLOCK CLOSE_BLOCK);
- // Add the current arguments to the signature
- // If the argument has a default value which is not a constant, we will make it Nullable
- {
- if (F != imethod.arguments.front())
- arguments_sig += ", ";
+ return _save_file(p_output_file, output);
+}
- if (iarg.def_param_mode == ArgumentInterface::NULLABLE_VAL)
- arguments_sig += "Nullable<";
+Error BindingsGenerator::_generate_cs_property(const BindingsGenerator::TypeInterface &p_itype, const DocData::PropertyDoc &p_prop_doc, List<String> &p_output) {
- arguments_sig += arg_type->cs_type;
+ const MethodInterface *setter = p_itype.find_method_by_name(p_prop_doc.setter);
- if (iarg.def_param_mode == ArgumentInterface::NULLABLE_VAL)
- arguments_sig += "> ";
- else
- arguments_sig += " ";
+ // Search it in base types too
+ const TypeInterface *current_type = &p_itype;
+ while (!setter && current_type->base_name.length()) {
+ Map<String, TypeInterface>::Element *base_match = obj_types.find(current_type->base_name);
+ ERR_FAIL_NULL_V(base_match, ERR_BUG);
+ current_type = &base_match->get();
+ setter = current_type->find_method_by_name(p_prop_doc.setter);
+ }
- arguments_sig += iarg.name;
+ const MethodInterface *getter = p_itype.find_method_by_name(p_prop_doc.getter);
- if (iarg.default_argument.size()) {
- if (iarg.def_param_mode != ArgumentInterface::CONSTANT)
- arguments_sig += " = null";
- else
- arguments_sig += " = " + sformat(iarg.default_argument, arg_type->cs_type);
- }
- }
+ // Search it in base types too
+ current_type = &p_itype;
+ while (!getter && current_type->base_name.length()) {
+ Map<String, TypeInterface>::Element *base_match = obj_types.find(current_type->base_name);
+ ERR_FAIL_NULL_V(base_match, ERR_BUG);
+ current_type = &base_match->get();
+ getter = current_type->find_method_by_name(p_prop_doc.getter);
+ }
- icall_params += ", ";
+ ERR_FAIL_COND_V(!setter && !getter, ERR_BUG);
- if (iarg.default_argument.size() && iarg.def_param_mode != ArgumentInterface::CONSTANT) {
- // The default value of an argument must be constant. Otherwise we make it Nullable and do the following:
- // Type arg_in = arg.HasValue ? arg.Value : <non-const default value>;
- String arg_in = iarg.name;
- arg_in += "_in";
+ bool is_valid = false;
+ int prop_index = ClassDB::get_property_index(p_itype.name, p_prop_doc.name, &is_valid);
+ ERR_FAIL_COND_V(!is_valid, ERR_BUG);
- cs_in_statements += arg_type->cs_type;
- cs_in_statements += " ";
- cs_in_statements += arg_in;
- cs_in_statements += " = ";
- cs_in_statements += iarg.name;
+ if (setter) {
+ int setter_argc = prop_index != -1 ? 2 : 1;
+ ERR_FAIL_COND_V(setter->arguments.size() != setter_argc, ERR_BUG);
+ }
- if (iarg.def_param_mode == ArgumentInterface::NULLABLE_VAL)
- cs_in_statements += ".HasValue ? ";
- else
- cs_in_statements += " != null ? ";
+ if (getter) {
+ int getter_argc = prop_index != -1 ? 1 : 0;
+ ERR_FAIL_COND_V(getter->arguments.size() != getter_argc, ERR_BUG);
+ }
- cs_in_statements += iarg.name;
+ if (getter && setter) {
+ ERR_FAIL_COND_V(getter->return_type != setter->arguments.back()->get().type, ERR_BUG);
+ }
- if (iarg.def_param_mode == ArgumentInterface::NULLABLE_VAL)
- cs_in_statements += ".Value : ";
- else
- cs_in_statements += " : ";
+ // Let's not trust PropertyDoc::type
+ String proptype_name = getter ? getter->return_type : setter->arguments.back()->get().type;
- String def_arg = sformat(iarg.default_argument, arg_type->cs_type);
+ const TypeInterface *prop_itype = _get_type_by_name_or_null(proptype_name);
+ if (!prop_itype) {
+ // Try with underscore prefix
+ prop_itype = _get_type_by_name_or_null("_" + proptype_name);
+ }
- cs_in_statements += def_arg;
- cs_in_statements += ";\n" INDENT3;
+ ERR_FAIL_NULL_V(prop_itype, ERR_BUG);
- icall_params += arg_type->cs_in.empty() ? arg_in : sformat(arg_type->cs_in, arg_in);
+ String prop_proxy_name = escape_csharp_keyword(snake_to_pascal_case(p_prop_doc.name));
- default_args_doc.push_back(INDENT2 "/// <param name=\"" + iarg.name + "\">If the param is null, then the default value is " + def_arg + "</param>\n");
- } else {
- icall_params += arg_type->cs_in.empty() ? iarg.name : sformat(arg_type->cs_in, iarg.name);
- }
+ // Prevent property and enclosing type from sharing the same name
+ if (prop_proxy_name == p_itype.proxy_name) {
+ if (verbose_output) {
+ WARN_PRINTS("Name of property `" + prop_proxy_name + "` is ambiguous with the name of its class `" +
+ p_itype.proxy_name + "`. Renaming property to `" + prop_proxy_name + "_`");
}
- // Generate method
- {
- if (!imethod.is_virtual && !imethod.requires_object_call) {
- cs_file.push_back(MEMBER_BEGIN "private ");
- cs_file.push_back(itype.is_singleton ? "static IntPtr " : "IntPtr ");
- cs_file.push_back(method_bind_field + " = " CS_CLASS_NATIVECALLS "." ICALL_GET_METHODBIND "(" BINDINGS_NATIVE_NAME_FIELD ", \"");
- cs_file.push_back(imethod.name);
- cs_file.push_back("\");\n");
- }
+ prop_proxy_name += "_";
+ }
- if (imethod.method_doc && imethod.method_doc->description.size()) {
- cs_file.push_back(MEMBER_BEGIN "/// <summary>\n");
+ if (p_prop_doc.description.size()) {
+ p_output.push_back(MEMBER_BEGIN "/// <summary>\n");
- Vector<String> description_lines = imethod.method_doc->description.split("\n");
+ Vector<String> description_lines = p_prop_doc.description.split("\n");
- for (int i = 0; i < description_lines.size(); i++) {
- if (description_lines[i].size()) {
- cs_file.push_back(INDENT2 "/// ");
- cs_file.push_back(description_lines[i].strip_edges().xml_escape());
- cs_file.push_back("\n");
- }
- }
+ for (int i = 0; i < description_lines.size(); i++) {
+ if (description_lines[i].size()) {
+ p_output.push_back(INDENT2 "/// ");
+ p_output.push_back(description_lines[i].strip_edges().xml_escape());
+ p_output.push_back("\n");
+ }
+ }
- for (List<String>::Element *E = default_args_doc.front(); E; E = E->next()) {
- cs_file.push_back(E->get().xml_escape());
- }
+ p_output.push_back(INDENT2 "/// </summary>");
+ }
- cs_file.push_back(INDENT2 "/// </summary>");
- }
+ p_output.push_back(MEMBER_BEGIN "public ");
- if (!imethod.is_internal) {
- cs_file.push_back(MEMBER_BEGIN "[GodotMethod(\"");
- cs_file.push_back(imethod.name);
- cs_file.push_back("\")]");
- }
+ if (p_itype.is_singleton)
+ p_output.push_back("static ");
- cs_file.push_back(MEMBER_BEGIN);
- cs_file.push_back(imethod.is_internal ? "internal " : "public ");
+ p_output.push_back(prop_itype->cs_type);
+ p_output.push_back(" ");
+ p_output.push_back(prop_proxy_name.replace("/", "__"));
+ p_output.push_back("\n" INDENT2 OPEN_BLOCK);
- if (itype.is_singleton) {
- cs_file.push_back("static ");
- } else if (imethod.is_virtual) {
- cs_file.push_back("virtual ");
- }
+ if (getter) {
+ p_output.push_back(INDENT3 "get\n" OPEN_BLOCK_L3);
+ p_output.push_back("return ");
+ p_output.push_back(getter->proxy_name + "(");
+ if (prop_index != -1)
+ p_output.push_back(itos(prop_index));
+ p_output.push_back(");\n" CLOSE_BLOCK_L3);
+ }
- cs_file.push_back(return_type->cs_type + " ");
- cs_file.push_back(imethod.proxy_name + "(");
- cs_file.push_back(arguments_sig + ")\n" OPEN_BLOCK_L2);
+ if (setter) {
+ p_output.push_back(INDENT3 "set\n" OPEN_BLOCK_L3);
+ p_output.push_back(setter->proxy_name + "(");
+ if (prop_index != -1)
+ p_output.push_back(itos(prop_index) + ", ");
+ p_output.push_back("value);\n" CLOSE_BLOCK_L3);
+ }
- if (imethod.is_virtual) {
- // Godot virtual method must be overridden, therefore we return a default value by default.
+ p_output.push_back(CLOSE_BLOCK_L2);
- if (return_type->name == "void") {
- cs_file.push_back("return;\n" CLOSE_BLOCK_L2);
- } else {
- cs_file.push_back("return default(");
- cs_file.push_back(return_type->cs_type);
- cs_file.push_back(");\n" CLOSE_BLOCK_L2);
- }
+ return OK;
+}
- continue;
- }
+Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterface &p_itype, const BindingsGenerator::MethodInterface &p_imethod, int &p_method_bind_count, List<String> &p_output) {
- if (imethod.requires_object_call) {
- // Fallback to Godot's object.Call(string, params)
+ const TypeInterface *return_type = _get_type_by_name_or_placeholder(p_imethod.return_type);
- cs_file.push_back(CS_METHOD_CALL "(\"");
- cs_file.push_back(imethod.name);
- cs_file.push_back("\"");
+ String method_bind_field = "method_bind_" + itos(p_method_bind_count);
- for (const List<ArgumentInterface>::Element *F = imethod.arguments.front(); F; F = F->next()) {
- cs_file.push_back(", ");
- cs_file.push_back(F->get().name);
- }
+ String icall_params = method_bind_field + ", " + sformat(p_itype.cs_in, "this");
+ String arguments_sig;
+ String cs_in_statements;
- cs_file.push_back(");\n" CLOSE_BLOCK_L2);
+ List<String> default_args_doc;
- continue;
- }
+ // Retrieve information from the arguments
+ for (const List<ArgumentInterface>::Element *F = p_imethod.arguments.front(); F; F = F->next()) {
+ const ArgumentInterface &iarg = F->get();
+ const TypeInterface *arg_type = _get_type_by_name_or_placeholder(iarg.type);
- const Map<const MethodInterface *, const InternalCall *>::Element *match = method_icalls_map.find(&E->get());
- ERR_FAIL_NULL_V(match, ERR_BUG);
+ // Add the current arguments to the signature
+ // If the argument has a default value which is not a constant, we will make it Nullable
+ {
+ if (F != p_imethod.arguments.front())
+ arguments_sig += ", ";
- const InternalCall *im_icall = match->value();
+ if (iarg.def_param_mode == ArgumentInterface::NULLABLE_VAL)
+ arguments_sig += "Nullable<";
- String im_call = im_icall->editor_only ? CS_CLASS_NATIVECALLS_EDITOR : CS_CLASS_NATIVECALLS;
- im_call += "." + im_icall->name + "(" + icall_params + ");\n";
+ arguments_sig += arg_type->cs_type;
- if (imethod.arguments.size())
- cs_file.push_back(cs_in_statements);
+ if (iarg.def_param_mode == ArgumentInterface::NULLABLE_VAL)
+ arguments_sig += "> ";
+ else
+ arguments_sig += " ";
- if (return_type->name == "void") {
- cs_file.push_back(im_call);
- } else if (return_type->cs_out.empty()) {
- cs_file.push_back("return " + im_call);
- } else {
- cs_file.push_back(return_type->im_type_out);
- cs_file.push_back(" " LOCAL_RET " = ");
- cs_file.push_back(im_call);
- cs_file.push_back(INDENT3);
- cs_file.push_back(sformat(return_type->cs_out, LOCAL_RET) + "\n");
- }
+ arguments_sig += iarg.name;
- cs_file.push_back(CLOSE_BLOCK_L2);
+ if (iarg.default_argument.size()) {
+ if (iarg.def_param_mode != ArgumentInterface::CONSTANT)
+ arguments_sig += " = null";
+ else
+ arguments_sig += " = " + sformat(iarg.default_argument, arg_type->cs_type);
+ }
}
- method_bind_count++;
- }
+ icall_params += ", ";
- if (itype.is_singleton) {
- InternalCall singleton_icall = InternalCall(itype.api_type, ICALL_PREFIX + itype.name + SINGLETON_ICALL_SUFFIX, "IntPtr");
+ if (iarg.default_argument.size() && iarg.def_param_mode != ArgumentInterface::CONSTANT) {
+ // The default value of an argument must be constant. Otherwise we make it Nullable and do the following:
+ // Type arg_in = arg.HasValue ? arg.Value : <non-const default value>;
+ String arg_in = iarg.name;
+ arg_in += "_in";
- if (!find_icall_by_name(singleton_icall.name, custom_icalls))
- custom_icalls.push_back(singleton_icall);
- }
+ cs_in_statements += arg_type->cs_type;
+ cs_in_statements += " ";
+ cs_in_statements += arg_in;
+ cs_in_statements += " = ";
+ cs_in_statements += iarg.name;
- if (itype.is_instantiable) {
- InternalCall ctor_icall = InternalCall(itype.api_type, ctor_method, "IntPtr", itype.proxy_name + " obj");
+ if (iarg.def_param_mode == ArgumentInterface::NULLABLE_VAL)
+ cs_in_statements += ".HasValue ? ";
+ else
+ cs_in_statements += " != null ? ";
- if (!find_icall_by_name(ctor_icall.name, custom_icalls))
- custom_icalls.push_back(ctor_icall);
- }
+ cs_in_statements += iarg.name;
- cs_file.push_back(INDENT1 CLOSE_BLOCK CLOSE_BLOCK);
+ if (iarg.def_param_mode == ArgumentInterface::NULLABLE_VAL)
+ cs_in_statements += ".Value : ";
+ else
+ cs_in_statements += " : ";
- return _save_file(p_output_file, cs_file);
-}
+ String def_arg = sformat(iarg.default_argument, arg_type->cs_type);
-Error BindingsGenerator::generate_glue(const String &p_output_dir) {
+ cs_in_statements += def_arg;
+ cs_in_statements += ";\n" INDENT3;
- verbose_output = true;
+ icall_params += arg_type->cs_in.empty() ? arg_in : sformat(arg_type->cs_in, arg_in);
- bool dir_exists = DirAccess::exists(p_output_dir);
- ERR_EXPLAIN("The output directory does not exist.");
- ERR_FAIL_COND_V(!dir_exists, ERR_FILE_BAD_PATH);
+ default_args_doc.push_back(INDENT2 "/// <param name=\"" + iarg.name + "\">If the param is null, then the default value is " + def_arg + "</param>\n");
+ } else {
+ icall_params += arg_type->cs_in.empty() ? iarg.name : sformat(arg_type->cs_in, iarg.name);
+ }
+ }
- List<String> cpp_file;
+ // Generate method
+ {
+ if (!p_imethod.is_virtual && !p_imethod.requires_object_call) {
+ p_output.push_back(MEMBER_BEGIN "private ");
+ p_output.push_back(p_itype.is_singleton ? "static IntPtr " : "IntPtr ");
+ p_output.push_back(method_bind_field + " = " CS_CLASS_NATIVECALLS "." ICALL_GET_METHODBIND "(" BINDINGS_NATIVE_NAME_FIELD ", \"");
+ p_output.push_back(p_imethod.name);
+ p_output.push_back("\");\n");
+ }
- cpp_file.push_back("#include \"" GLUE_HEADER_FILE "\"\n"
- "\n");
+ if (p_imethod.method_doc && p_imethod.method_doc->description.size()) {
+ p_output.push_back(MEMBER_BEGIN "/// <summary>\n");
- List<const InternalCall *> generated_icall_funcs;
+ Vector<String> description_lines = p_imethod.method_doc->description.split("\n");
- for (Map<String, TypeInterface>::Element *type_elem = obj_types.front(); type_elem; type_elem = type_elem->next()) {
- const TypeInterface &itype = type_elem->get();
+ for (int i = 0; i < description_lines.size(); i++) {
+ if (description_lines[i].size()) {
+ p_output.push_back(INDENT2 "/// ");
+ p_output.push_back(description_lines[i].strip_edges().xml_escape());
+ p_output.push_back("\n");
+ }
+ }
- if (itype.base_name.length() && obj_types[itype.base_name].is_singleton && is_singleton_black_listed(itype.name))
- continue;
+ for (List<String>::Element *E = default_args_doc.front(); E; E = E->next()) {
+ p_output.push_back(E->get().xml_escape());
+ }
- List<InternalCall> &custom_icalls = itype.api_type == ClassDB::API_EDITOR ? editor_custom_icalls : core_custom_icalls;
+ p_output.push_back(INDENT2 "/// </summary>");
+ }
- OS::get_singleton()->print(String("Generating " + itype.name + "...\n").utf8());
+ if (!p_imethod.is_internal) {
+ p_output.push_back(MEMBER_BEGIN "[GodotMethod(\"");
+ p_output.push_back(p_imethod.name);
+ p_output.push_back("\")]");
+ }
- String ctor_method(ICALL_PREFIX + itype.proxy_name + "_Ctor");
+ p_output.push_back(MEMBER_BEGIN);
+ p_output.push_back(p_imethod.is_internal ? "internal " : "public ");
- for (const List<MethodInterface>::Element *E = itype.methods.front(); E; E = E->next()) {
- const MethodInterface &imethod = E->get();
+ if (p_itype.is_singleton) {
+ p_output.push_back("static ");
+ } else if (p_imethod.is_virtual) {
+ p_output.push_back("virtual ");
+ }
- if (imethod.is_virtual)
- continue;
+ p_output.push_back(return_type->cs_type + " ");
+ p_output.push_back(p_imethod.proxy_name + "(");
+ p_output.push_back(arguments_sig + ")\n" OPEN_BLOCK_L2);
- bool ret_void = imethod.return_type == "void";
+ if (p_imethod.is_virtual) {
+ // Godot virtual method must be overridden, therefore we return a default value by default.
- const TypeInterface *return_type = _get_type_by_name_or_placeholder(imethod.return_type);
+ if (return_type->name == "void") {
+ p_output.push_back("return;\n" CLOSE_BLOCK_L2);
+ } else {
+ p_output.push_back("return default(");
+ p_output.push_back(return_type->cs_type);
+ p_output.push_back(");\n" CLOSE_BLOCK_L2);
+ }
- String argc_str = itos(imethod.arguments.size());
+ return OK; // Won't increment method bind count
+ }
- String c_func_sig = "MethodBind* " CS_PARAM_METHODBIND ", " + itype.c_type_in + " " CS_PARAM_INSTANCE;
- String c_in_statements;
- String c_args_var_content;
+ if (p_imethod.requires_object_call) {
+ // Fallback to Godot's object.Call(string, params)
- // Get arguments information
- int i = 0;
- for (const List<ArgumentInterface>::Element *F = imethod.arguments.front(); F; F = F->next()) {
- const ArgumentInterface &iarg = F->get();
- const TypeInterface *arg_type = _get_type_by_name_or_placeholder(iarg.type);
+ p_output.push_back(CS_METHOD_CALL "(\"");
+ p_output.push_back(p_imethod.name);
+ p_output.push_back("\"");
- String c_param_name = "arg" + itos(i + 1);
+ for (const List<ArgumentInterface>::Element *F = p_imethod.arguments.front(); F; F = F->next()) {
+ p_output.push_back(", ");
+ p_output.push_back(F->get().name);
+ }
- if (imethod.is_vararg) {
- if (i < imethod.arguments.size() - 1) {
- c_in_statements += sformat(arg_type->c_in.size() ? arg_type->c_in : TypeInterface::DEFAULT_VARARG_C_IN, "Variant", c_param_name);
- c_in_statements += "\t" C_LOCAL_PTRCALL_ARGS ".set(0, ";
- c_in_statements += sformat("&%s_in", c_param_name);
- c_in_statements += ");\n";
- }
- } else {
- if (i > 0)
- c_args_var_content += ", ";
- if (arg_type->c_in.size())
- c_in_statements += sformat(arg_type->c_in, arg_type->c_type, c_param_name);
- c_args_var_content += sformat(arg_type->c_arg_in, c_param_name);
- }
+ p_output.push_back(");\n" CLOSE_BLOCK_L2);
- c_func_sig += ", ";
- c_func_sig += arg_type->c_type_in;
- c_func_sig += " ";
- c_func_sig += c_param_name;
+ return OK; // Won't increment method bind count
+ }
- i++;
- }
+ const Map<const MethodInterface *, const InternalCall *>::Element *match = method_icalls_map.find(&p_imethod);
+ ERR_FAIL_NULL_V(match, ERR_BUG);
- const Map<const MethodInterface *, const InternalCall *>::Element *match = method_icalls_map.find(&E->get());
- ERR_FAIL_NULL_V(match, ERR_BUG);
+ const InternalCall *im_icall = match->value();
- const InternalCall *im_icall = match->value();
- String icall_method = im_icall->name;
+ String im_call = im_icall->editor_only ? CS_CLASS_NATIVECALLS_EDITOR : CS_CLASS_NATIVECALLS;
+ im_call += "." + im_icall->name + "(" + icall_params + ");\n";
- if (!generated_icall_funcs.find(im_icall)) {
- generated_icall_funcs.push_back(im_icall);
+ if (p_imethod.arguments.size())
+ p_output.push_back(cs_in_statements);
- if (im_icall->editor_only)
- cpp_file.push_back("#ifdef TOOLS_ENABLED\n");
+ if (return_type->name == "void") {
+ p_output.push_back(im_call);
+ } else if (return_type->cs_out.empty()) {
+ p_output.push_back("return " + im_call);
+ } else {
+ p_output.push_back(return_type->im_type_out);
+ p_output.push_back(" " LOCAL_RET " = ");
+ p_output.push_back(im_call);
+ p_output.push_back(INDENT3);
+ p_output.push_back(sformat(return_type->cs_out, LOCAL_RET) + "\n");
+ }
- // Generate icall function
+ p_output.push_back(CLOSE_BLOCK_L2);
+ }
- cpp_file.push_back(ret_void ? "void " : return_type->c_type_out + " ");
- cpp_file.push_back(icall_method);
- cpp_file.push_back("(");
- cpp_file.push_back(c_func_sig);
- cpp_file.push_back(") " OPEN_BLOCK);
+ p_method_bind_count++;
+ return OK;
+}
- String fail_ret = ret_void ? "" : ", " + (return_type->c_type_out.ends_with("*") ? "NULL" : return_type->c_type_out + "()");
+Error BindingsGenerator::generate_glue(const String &p_output_dir) {
- if (!ret_void) {
- String ptrcall_return_type;
- String initialization;
+ verbose_output = true;
- if (return_type->is_object_type) {
- ptrcall_return_type = return_type->is_reference ? "Ref<Reference>" : return_type->c_type;
- initialization = return_type->is_reference ? "" : " = NULL";
- } else {
- ptrcall_return_type = return_type->c_type;
- }
+ bool dir_exists = DirAccess::exists(p_output_dir);
+ ERR_EXPLAIN("The output directory does not exist.");
+ ERR_FAIL_COND_V(!dir_exists, ERR_FILE_BAD_PATH);
- cpp_file.push_back("\t" + ptrcall_return_type);
- cpp_file.push_back(" " LOCAL_RET);
- cpp_file.push_back(initialization + ";\n");
- cpp_file.push_back("\tERR_FAIL_NULL_V(" CS_PARAM_INSTANCE);
- cpp_file.push_back(fail_ret);
- cpp_file.push_back(");\n");
- } else {
- cpp_file.push_back("\tERR_FAIL_NULL(" CS_PARAM_INSTANCE ");\n");
- }
+ List<String> output;
- if (imethod.arguments.size()) {
- if (imethod.is_vararg) {
- String err_fail_macro = ret_void ? "ERR_FAIL_COND" : "ERR_FAIL_COND_V";
- String vararg_arg = "arg" + argc_str;
- String real_argc_str = itos(imethod.arguments.size() - 1); // Arguments count without vararg
-
- cpp_file.push_back("\tVector<Variant> varargs;\n"
- "\tint vararg_length = mono_array_length(");
- cpp_file.push_back(vararg_arg);
- cpp_file.push_back(");\n\tint total_length = ");
- cpp_file.push_back(real_argc_str);
- cpp_file.push_back(" + vararg_length;\n\t");
- cpp_file.push_back(err_fail_macro);
- cpp_file.push_back("(varargs.resize(vararg_length) != OK");
- cpp_file.push_back(fail_ret);
- cpp_file.push_back(");\n\tVector<Variant*> " C_LOCAL_PTRCALL_ARGS ";\n\t");
- cpp_file.push_back(err_fail_macro);
- cpp_file.push_back("(call_args.resize(total_length) != OK");
- cpp_file.push_back(fail_ret);
- cpp_file.push_back(");\n");
- cpp_file.push_back(c_in_statements);
- cpp_file.push_back("\tfor (int i = 0; i < vararg_length; i++) " OPEN_BLOCK
- "\t\tMonoObject* elem = mono_array_get(");
- cpp_file.push_back(vararg_arg);
- cpp_file.push_back(", MonoObject*, i);\n"
- "\t\tvarargs.set(i, GDMonoMarshal::mono_object_to_variant(elem));\n"
- "\t\t" C_LOCAL_PTRCALL_ARGS ".set(");
- cpp_file.push_back(real_argc_str);
- cpp_file.push_back(" + i, &varargs[i]);\n\t" CLOSE_BLOCK);
- } else {
- cpp_file.push_back(c_in_statements);
- cpp_file.push_back("\tconst void* " C_LOCAL_PTRCALL_ARGS "[");
- cpp_file.push_back(argc_str + "] = { ");
- cpp_file.push_back(c_args_var_content + " };\n");
- }
- }
+ output.push_back("#include \"" GLUE_HEADER_FILE "\"\n"
+ "\n");
- if (imethod.is_vararg) {
- cpp_file.push_back("\tVariant::CallError vcall_error;\n\t");
+ generated_icall_funcs.clear();
- if (!ret_void)
- cpp_file.push_back(LOCAL_RET " = ");
+ for (Map<String, TypeInterface>::Element *type_elem = obj_types.front(); type_elem; type_elem = type_elem->next()) {
+ const TypeInterface &itype = type_elem->get();
- cpp_file.push_back(CS_PARAM_METHODBIND "->call(" CS_PARAM_INSTANCE ", ");
- cpp_file.push_back(imethod.arguments.size() ? "(const Variant**)" C_LOCAL_PTRCALL_ARGS ".ptr()" : "NULL");
- cpp_file.push_back(", total_length, vcall_error);\n");
- } else {
- cpp_file.push_back("\t" CS_PARAM_METHODBIND "->ptrcall(" CS_PARAM_INSTANCE ", ");
- cpp_file.push_back(imethod.arguments.size() ? C_LOCAL_PTRCALL_ARGS ", " : "NULL, ");
- cpp_file.push_back(!ret_void ? "&" LOCAL_RET ");\n" : "NULL);\n");
- }
+ List<InternalCall> &custom_icalls = itype.api_type == ClassDB::API_EDITOR ? editor_custom_icalls : core_custom_icalls;
- if (!ret_void) {
- if (return_type->c_out.empty())
- cpp_file.push_back("\treturn " LOCAL_RET ";\n");
- else
- cpp_file.push_back(sformat(return_type->c_out, return_type->c_type_out, LOCAL_RET, return_type->name));
- }
+ OS::get_singleton()->print(String("Generating " + itype.name + "...\n").utf8());
- cpp_file.push_back(CLOSE_BLOCK "\n");
+ String ctor_method(ICALL_PREFIX + itype.proxy_name + "_Ctor");
- if (im_icall->editor_only)
- cpp_file.push_back("#endif // TOOLS_ENABLED\n");
+ for (const List<MethodInterface>::Element *E = itype.methods.front(); E; E = E->next()) {
+ const MethodInterface &imethod = E->get();
+ Error method_err = _generate_glue_method(itype, imethod, output);
+ if (method_err != OK) {
+ ERR_EXPLAIN("Failed to generate method '" + imethod.name + "' for class '" + itype.name + "'");
+ ERR_FAIL_V(method_err);
}
}
@@ -1339,11 +1167,11 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) {
if (!find_icall_by_name(singleton_icall.name, custom_icalls))
custom_icalls.push_back(singleton_icall);
- cpp_file.push_back("Object* ");
- cpp_file.push_back(singleton_icall_name);
- cpp_file.push_back("() " OPEN_BLOCK "\treturn ProjectSettings::get_singleton()->get_singleton_object(\"");
- cpp_file.push_back(itype.proxy_name);
- cpp_file.push_back("\");\n" CLOSE_BLOCK "\n");
+ output.push_back("Object* ");
+ output.push_back(singleton_icall_name);
+ output.push_back("() " OPEN_BLOCK "\treturn Engine::get_singleton()->get_singleton_object(\"");
+ output.push_back(itype.proxy_name);
+ output.push_back("\");\n" CLOSE_BLOCK "\n");
}
if (itype.is_instantiable) {
@@ -1352,36 +1180,36 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) {
if (!find_icall_by_name(ctor_icall.name, custom_icalls))
custom_icalls.push_back(ctor_icall);
- cpp_file.push_back("Object* ");
- cpp_file.push_back(ctor_method);
- cpp_file.push_back("(MonoObject* obj) " OPEN_BLOCK
- "\t" C_MACRO_OBJECT_CONSTRUCT "(instance, \"");
- cpp_file.push_back(itype.name);
- cpp_file.push_back("\");\n"
- "\t" C_METHOD_TIE_MANAGED_TO_UNMANAGED "(obj, instance);\n"
- "\treturn instance;\n" CLOSE_BLOCK "\n");
+ output.push_back("Object* ");
+ output.push_back(ctor_method);
+ output.push_back("(MonoObject* obj) " OPEN_BLOCK
+ "\t" C_MACRO_OBJECT_CONSTRUCT "(instance, \"");
+ output.push_back(itype.name);
+ output.push_back("\");\n"
+ "\t" C_METHOD_TIE_MANAGED_TO_UNMANAGED "(obj, instance);\n"
+ "\treturn instance;\n" CLOSE_BLOCK "\n");
}
}
- cpp_file.push_back("namespace GodotSharpBindings\n" OPEN_BLOCK);
- cpp_file.push_back("uint64_t get_core_api_hash() { return ");
- cpp_file.push_back(itos(GDMono::get_singleton()->get_api_core_hash()) + "; }\n");
- cpp_file.push_back("#ifdef TOOLS_ENABLED\n"
- "uint64_t get_editor_api_hash() { return ");
- cpp_file.push_back(itos(GDMono::get_singleton()->get_api_editor_hash()) +
- "; }\n#endif // TOOLS_ENABLED\n");
- cpp_file.push_back("void register_generated_icalls() " OPEN_BLOCK);
-
-#define ADD_INTERNAL_CALL_REGISTRATION(m_icall) \
- { \
- cpp_file.push_back("\tmono_add_internal_call("); \
- cpp_file.push_back("\"" BINDINGS_NAMESPACE "."); \
- cpp_file.push_back(m_icall.editor_only ? CS_CLASS_NATIVECALLS_EDITOR : CS_CLASS_NATIVECALLS); \
- cpp_file.push_back("::"); \
- cpp_file.push_back(m_icall.name); \
- cpp_file.push_back("\", (void*)"); \
- cpp_file.push_back(m_icall.name); \
- cpp_file.push_back(");\n"); \
+ output.push_back("namespace GodotSharpBindings\n" OPEN_BLOCK);
+ output.push_back("uint64_t get_core_api_hash() { return ");
+ output.push_back(itos(GDMono::get_singleton()->get_api_core_hash()) + "; }\n");
+ output.push_back("#ifdef TOOLS_ENABLED\n"
+ "uint64_t get_editor_api_hash() { return ");
+ output.push_back(itos(GDMono::get_singleton()->get_api_editor_hash()) +
+ "; }\n#endif // TOOLS_ENABLED\n");
+ output.push_back("void register_generated_icalls() " OPEN_BLOCK);
+
+#define ADD_INTERNAL_CALL_REGISTRATION(m_icall) \
+ { \
+ output.push_back("\tmono_add_internal_call("); \
+ output.push_back("\"" BINDINGS_NAMESPACE "."); \
+ output.push_back(m_icall.editor_only ? CS_CLASS_NATIVECALLS_EDITOR : CS_CLASS_NATIVECALLS); \
+ output.push_back("::"); \
+ output.push_back(m_icall.name); \
+ output.push_back("\", (void*)"); \
+ output.push_back(m_icall.name); \
+ output.push_back(");\n"); \
}
bool tools_sequence = false;
@@ -1390,11 +1218,11 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) {
if (tools_sequence) {
if (!E->get().editor_only) {
tools_sequence = false;
- cpp_file.push_back("#endif\n");
+ output.push_back("#endif\n");
}
} else {
if (E->get().editor_only) {
- cpp_file.push_back("#ifdef TOOLS_ENABLED\n");
+ output.push_back("#ifdef TOOLS_ENABLED\n");
tools_sequence = true;
}
}
@@ -1404,24 +1232,23 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) {
if (tools_sequence) {
tools_sequence = false;
- cpp_file.push_back("#endif\n");
+ output.push_back("#endif\n");
}
- cpp_file.push_back("#ifdef TOOLS_ENABLED\n");
+ output.push_back("#ifdef TOOLS_ENABLED\n");
for (const List<InternalCall>::Element *E = editor_custom_icalls.front(); E; E = E->next())
ADD_INTERNAL_CALL_REGISTRATION(E->get());
- cpp_file.push_back("#endif // TOOLS_ENABLED\n");
+ output.push_back("#endif // TOOLS_ENABLED\n");
for (const List<InternalCall>::Element *E = method_icalls.front(); E; E = E->next()) {
-
if (tools_sequence) {
if (!E->get().editor_only) {
tools_sequence = false;
- cpp_file.push_back("#endif\n");
+ output.push_back("#endif\n");
}
} else {
if (E->get().editor_only) {
- cpp_file.push_back("#ifdef TOOLS_ENABLED\n");
+ output.push_back("#ifdef TOOLS_ENABLED\n");
tools_sequence = true;
}
}
@@ -1431,20 +1258,27 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) {
if (tools_sequence) {
tools_sequence = false;
- cpp_file.push_back("#endif\n");
+ output.push_back("#endif\n");
}
#undef ADD_INTERNAL_CALL_REGISTRATION
- cpp_file.push_back(CLOSE_BLOCK "}\n");
+ output.push_back(CLOSE_BLOCK "}\n");
+
+ Error save_err = _save_file(path_join(p_output_dir, "mono_glue.gen.cpp"), output);
+ if (save_err != OK)
+ return save_err;
- return _save_file(path_join(p_output_dir, "mono_glue.gen.cpp"), cpp_file);
+ OS::get_singleton()->print("Mono glue generated successfully\n");
+
+ return OK;
}
Error BindingsGenerator::_save_file(const String &p_path, const List<String> &p_content) {
FileAccessRef file = FileAccess::open(p_path, FileAccess::WRITE);
+ ERR_EXPLAIN("Cannot open file: " + p_path);
ERR_FAIL_COND_V(!file, ERR_FILE_CANT_WRITE);
for (const List<String>::Element *E = p_content.front(); E; E = E->next()) {
@@ -1456,6 +1290,163 @@ Error BindingsGenerator::_save_file(const String &p_path, const List<String> &p_
return OK;
}
+Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInterface &p_itype, const BindingsGenerator::MethodInterface &p_imethod, List<String> &p_output) {
+
+ if (p_imethod.is_virtual)
+ return OK; // Ignore
+
+ bool ret_void = p_imethod.return_type == "void";
+
+ const TypeInterface *return_type = _get_type_by_name_or_placeholder(p_imethod.return_type);
+
+ String argc_str = itos(p_imethod.arguments.size());
+
+ String c_func_sig = "MethodBind* " CS_PARAM_METHODBIND ", " + p_itype.c_type_in + " " CS_PARAM_INSTANCE;
+ String c_in_statements;
+ String c_args_var_content;
+
+ // Get arguments information
+ int i = 0;
+ for (const List<ArgumentInterface>::Element *F = p_imethod.arguments.front(); F; F = F->next()) {
+ const ArgumentInterface &iarg = F->get();
+ const TypeInterface *arg_type = _get_type_by_name_or_placeholder(iarg.type);
+
+ String c_param_name = "arg" + itos(i + 1);
+
+ if (p_imethod.is_vararg) {
+ if (i < p_imethod.arguments.size() - 1) {
+ c_in_statements += sformat(arg_type->c_in.size() ? arg_type->c_in : TypeInterface::DEFAULT_VARARG_C_IN, "Variant", c_param_name);
+ c_in_statements += "\t" C_LOCAL_PTRCALL_ARGS ".set(0, ";
+ c_in_statements += sformat("&%s_in", c_param_name);
+ c_in_statements += ");\n";
+ }
+ } else {
+ if (i > 0)
+ c_args_var_content += ", ";
+ if (arg_type->c_in.size())
+ c_in_statements += sformat(arg_type->c_in, arg_type->c_type, c_param_name);
+ c_args_var_content += sformat(arg_type->c_arg_in, c_param_name);
+ }
+
+ c_func_sig += ", ";
+ c_func_sig += arg_type->c_type_in;
+ c_func_sig += " ";
+ c_func_sig += c_param_name;
+
+ i++;
+ }
+
+ const Map<const MethodInterface *, const InternalCall *>::Element *match = method_icalls_map.find(&p_imethod);
+ ERR_FAIL_NULL_V(match, ERR_BUG);
+
+ const InternalCall *im_icall = match->value();
+ String icall_method = im_icall->name;
+
+ if (!generated_icall_funcs.find(im_icall)) {
+ generated_icall_funcs.push_back(im_icall);
+
+ if (im_icall->editor_only)
+ p_output.push_back("#ifdef TOOLS_ENABLED\n");
+
+ // Generate icall function
+
+ p_output.push_back(ret_void ? "void " : return_type->c_type_out + " ");
+ p_output.push_back(icall_method);
+ p_output.push_back("(");
+ p_output.push_back(c_func_sig);
+ p_output.push_back(") " OPEN_BLOCK);
+
+ String fail_ret = ret_void ? "" : ", " + (return_type->c_type_out.ends_with("*") ? "NULL" : return_type->c_type_out + "()");
+
+ if (!ret_void) {
+ String ptrcall_return_type;
+ String initialization;
+
+ if (return_type->is_object_type) {
+ ptrcall_return_type = return_type->is_reference ? "Ref<Reference>" : return_type->c_type;
+ initialization = return_type->is_reference ? "" : " = NULL";
+ } else {
+ ptrcall_return_type = return_type->c_type;
+ }
+
+ p_output.push_back("\t" + ptrcall_return_type);
+ p_output.push_back(" " LOCAL_RET);
+ p_output.push_back(initialization + ";\n");
+ p_output.push_back("\tERR_FAIL_NULL_V(" CS_PARAM_INSTANCE);
+ p_output.push_back(fail_ret);
+ p_output.push_back(");\n");
+ } else {
+ p_output.push_back("\tERR_FAIL_NULL(" CS_PARAM_INSTANCE ");\n");
+ }
+
+ if (p_imethod.arguments.size()) {
+ if (p_imethod.is_vararg) {
+ String err_fail_macro = ret_void ? "ERR_FAIL_COND" : "ERR_FAIL_COND_V";
+ String vararg_arg = "arg" + argc_str;
+ String real_argc_str = itos(p_imethod.arguments.size() - 1); // Arguments count without vararg
+
+ p_output.push_back("\tVector<Variant> varargs;\n"
+ "\tint vararg_length = mono_array_length(");
+ p_output.push_back(vararg_arg);
+ p_output.push_back(");\n\tint total_length = ");
+ p_output.push_back(real_argc_str);
+ p_output.push_back(" + vararg_length;\n\t");
+ p_output.push_back(err_fail_macro);
+ p_output.push_back("(varargs.resize(vararg_length) != OK");
+ p_output.push_back(fail_ret);
+ p_output.push_back(");\n\tVector<Variant*> " C_LOCAL_PTRCALL_ARGS ";\n\t");
+ p_output.push_back(err_fail_macro);
+ p_output.push_back("(call_args.resize(total_length) != OK");
+ p_output.push_back(fail_ret);
+ p_output.push_back(");\n");
+ p_output.push_back(c_in_statements);
+ p_output.push_back("\tfor (int i = 0; i < vararg_length; i++) " OPEN_BLOCK
+ "\t\tMonoObject* elem = mono_array_get(");
+ p_output.push_back(vararg_arg);
+ p_output.push_back(", MonoObject*, i);\n"
+ "\t\tvarargs.set(i, GDMonoMarshal::mono_object_to_variant(elem));\n"
+ "\t\t" C_LOCAL_PTRCALL_ARGS ".set(");
+ p_output.push_back(real_argc_str);
+ p_output.push_back(" + i, &varargs[i]);\n\t" CLOSE_BLOCK);
+ } else {
+ p_output.push_back(c_in_statements);
+ p_output.push_back("\tconst void* " C_LOCAL_PTRCALL_ARGS "[");
+ p_output.push_back(argc_str + "] = { ");
+ p_output.push_back(c_args_var_content + " };\n");
+ }
+ }
+
+ if (p_imethod.is_vararg) {
+ p_output.push_back("\tVariant::CallError vcall_error;\n\t");
+
+ if (!ret_void)
+ p_output.push_back(LOCAL_RET " = ");
+
+ p_output.push_back(CS_PARAM_METHODBIND "->call(" CS_PARAM_INSTANCE ", ");
+ p_output.push_back(p_imethod.arguments.size() ? "(const Variant**)" C_LOCAL_PTRCALL_ARGS ".ptr()" : "NULL");
+ p_output.push_back(", total_length, vcall_error);\n");
+ } else {
+ p_output.push_back("\t" CS_PARAM_METHODBIND "->ptrcall(" CS_PARAM_INSTANCE ", ");
+ p_output.push_back(p_imethod.arguments.size() ? C_LOCAL_PTRCALL_ARGS ", " : "NULL, ");
+ p_output.push_back(!ret_void ? "&" LOCAL_RET ");\n" : "NULL);\n");
+ }
+
+ if (!ret_void) {
+ if (return_type->c_out.empty())
+ p_output.push_back("\treturn " LOCAL_RET ";\n");
+ else
+ p_output.push_back(sformat(return_type->c_out, return_type->c_type_out, LOCAL_RET, return_type->name));
+ }
+
+ p_output.push_back(CLOSE_BLOCK "\n");
+
+ if (im_icall->editor_only)
+ p_output.push_back("#endif // TOOLS_ENABLED\n");
+ }
+
+ return OK;
+}
+
const BindingsGenerator::TypeInterface *BindingsGenerator::_get_type_by_name_or_null(const String &p_name) {
const Map<String, TypeInterface>::Element *match = builtin_types.find(p_name);
@@ -1514,11 +1505,18 @@ void BindingsGenerator::_populate_object_type_interfaces() {
TypeInterface itype = TypeInterface::create_object_type(type_cname, api_type);
itype.base_name = ClassDB::get_parent_class(type_cname);
- itype.is_singleton = ProjectSettings::get_singleton()->has_singleton(itype.proxy_name);
+ itype.is_singleton = Engine::get_singleton()->has_singleton(itype.proxy_name);
itype.is_instantiable = ClassDB::can_instance(type_cname) && !itype.is_singleton;
itype.is_reference = ClassDB::is_parent_class(type_cname, refclass_name);
itype.memory_own = itype.is_reference;
+ if (!ClassDB::is_class_exposed(type_cname)) {
+ if (verbose_output)
+ WARN_PRINTS("Ignoring type " + String(type_cname) + " because it's not exposed");
+ class_list.pop_front();
+ continue;
+ }
+
itype.c_out = "\treturn ";
itype.c_out += C_METHOD_UNMANAGED_GET_MANAGED;
itype.c_out += itype.is_reference ? "(%1.ptr());\n" : "(%1);\n";
@@ -1578,9 +1576,11 @@ void BindingsGenerator::_populate_object_type_interfaces() {
// which could actually will return something differnet.
// Let's put this to notify us if that ever happens.
if (itype.name != "Object" || imethod.name != "free") {
- WARN_PRINTS("Notification: New unexpected virtual non-overridable method found.\n"
- "We only expected Object.free, but found " +
- itype.name + "." + imethod.name);
+ if (verbose_output) {
+ WARN_PRINTS("Notification: New unexpected virtual non-overridable method found.\n"
+ "We only expected Object.free, but found " +
+ itype.name + "." + imethod.name);
+ }
}
} else {
ERR_PRINTS("Missing MethodBind for non-virtual method: " + itype.name + "." + imethod.name);
@@ -1721,7 +1721,7 @@ void BindingsGenerator::_default_argument_from_variant(const Variant &p_val, Arg
r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL;
break;
case Variant::PLANE:
- case Variant::RECT3:
+ case Variant::AABB:
case Variant::COLOR:
r_iarg.default_argument = "new Color(1, 1, 1, 1)";
r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL;
@@ -1793,7 +1793,7 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
INSERT_STRUCT_TYPE(Basis, "real_t*")
INSERT_STRUCT_TYPE(Quat, "real_t*")
INSERT_STRUCT_TYPE(Transform, "real_t*")
- INSERT_STRUCT_TYPE(Rect3, "real_t*")
+ INSERT_STRUCT_TYPE(AABB, "real_t*")
INSERT_STRUCT_TYPE(Color, "real_t*")
INSERT_STRUCT_TYPE(Plane, "real_t*")
@@ -2086,7 +2086,8 @@ BindingsGenerator::BindingsGenerator() {
void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args) {
- int options_count = 3;
+ const int NUM_OPTIONS = 3;
+ int options_left = NUM_OPTIONS;
String mono_glue_option = "--generate-mono-glue";
String cs_core_api_option = "--generate-cs-core-api";
@@ -2096,33 +2097,35 @@ void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args)
const List<String>::Element *elem = p_cmdline_args.front();
- while (elem && options_count) {
+ while (elem && options_left) {
if (elem->get() == mono_glue_option) {
const List<String>::Element *path_elem = elem->next();
if (path_elem) {
- get_singleton().generate_glue(path_elem->get());
+ if (get_singleton().generate_glue(path_elem->get()) != OK)
+ ERR_PRINT("Mono glue generation failed");
elem = elem->next();
} else {
ERR_PRINTS("--generate-mono-glue: No output directory specified");
}
- --options_count;
+ --options_left;
} else if (elem->get() == cs_core_api_option) {
const List<String>::Element *path_elem = elem->next();
if (path_elem) {
- get_singleton().generate_cs_core_project(path_elem->get());
+ if (get_singleton().generate_cs_core_project(path_elem->get()) != OK)
+ ERR_PRINT("Generation of solution and C# project for the Core API failed");
elem = elem->next();
} else {
ERR_PRINTS(cs_core_api_option + ": No output directory specified");
}
- --options_count;
+ --options_left;
} else if (elem->get() == cs_editor_api_option) {
@@ -2130,7 +2133,8 @@ void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args)
if (path_elem) {
if (path_elem->next()) {
- get_singleton().generate_cs_editor_project(path_elem->get(), path_elem->next()->get());
+ if (get_singleton().generate_cs_editor_project(path_elem->get(), path_elem->next()->get()) != OK)
+ ERR_PRINT("Generation of solution and C# project for the Editor API failed");
elem = path_elem->next();
} else {
ERR_PRINTS(cs_editor_api_option + ": No hint path for the Core API dll specified");
@@ -2139,13 +2143,16 @@ void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args)
ERR_PRINTS(cs_editor_api_option + ": No output directory specified");
}
- --options_count;
+ --options_left;
}
elem = elem->next();
}
verbose_output = false;
+
+ if (options_left != NUM_OPTIONS)
+ exit(0);
}
#endif
diff --git a/modules/mono/editor/bindings_generator.h b/modules/mono/editor/bindings_generator.h
index 437a566556..dfa3aa9911 100644
--- a/modules/mono/editor/bindings_generator.h
+++ b/modules/mono/editor/bindings_generator.h
@@ -368,6 +368,8 @@ class BindingsGenerator {
List<InternalCall> method_icalls;
Map<const MethodInterface *, const InternalCall *> method_icalls_map;
+ List<const InternalCall *> generated_icall_funcs;
+
List<InternalCall> core_custom_icalls;
List<InternalCall> editor_custom_icalls;
@@ -404,6 +406,11 @@ class BindingsGenerator {
Error _generate_cs_type(const TypeInterface &itype, const String &p_output_file);
+ Error _generate_cs_property(const TypeInterface &p_itype, const DocData::PropertyDoc &p_prop_doc, List<String> &p_output);
+ Error _generate_cs_method(const TypeInterface &p_itype, const MethodInterface &p_imethod, int &p_method_bind_count, List<String> &p_output);
+
+ Error _generate_glue_method(const TypeInterface &p_itype, const MethodInterface &p_imethod, List<String> &p_output);
+
Error _save_file(const String &path, const List<String> &content);
BindingsGenerator();
diff --git a/modules/mono/editor/godotsharp_builds.cpp b/modules/mono/editor/godotsharp_builds.cpp
index 1bad8a3f85..b88d34fc33 100644
--- a/modules/mono/editor/godotsharp_builds.cpp
+++ b/modules/mono/editor/godotsharp_builds.cpp
@@ -32,6 +32,7 @@
#include "main/main.h"
#include "../godotsharp_dirs.h"
+#include "../mono_gd/gd_mono.h"
#include "../mono_gd/gd_mono_class.h"
#include "../mono_gd/gd_mono_marshal.h"
#include "../utils/path_utils.h"
@@ -52,6 +53,10 @@ String _find_build_engine_on_unix(const String &p_name) {
if (ret.length())
return ret;
+ String ret_fallback = path_which(p_name + ".exe");
+ if (ret_fallback.length())
+ return ret_fallback;
+
const char *locations[] = {
#ifdef OSX_ENABLED
"/Library/Frameworks/Mono.framework/Versions/Current/bin/",
@@ -60,10 +65,10 @@ String _find_build_engine_on_unix(const String &p_name) {
};
for (int i = 0; i < sizeof(locations) / sizeof(const char *); i++) {
- String location = locations[i];
+ String hint_path = locations[i] + p_name;
- if (FileAccess::exists(location + p_name)) {
- return location;
+ if (FileAccess::exists(hint_path)) {
+ return hint_path;
}
}
@@ -71,7 +76,7 @@ String _find_build_engine_on_unix(const String &p_name) {
}
#endif
-MonoString *godot_icall_BuildInstance_get_MSBuildPath() {
+void godot_icall_BuildInstance_get_MSBuildInfo(MonoString **r_msbuild_path, MonoString **r_framework_path) {
GodotSharpBuilds::BuildTool build_tool = GodotSharpBuilds::BuildTool(int(EditorSettings::get_singleton()->get("mono/builds/build_tool")));
@@ -84,11 +89,23 @@ MonoString *godot_icall_BuildInstance_get_MSBuildPath() {
if (!msbuild_tools_path.ends_with("\\"))
msbuild_tools_path += "\\";
- return GDMonoMarshal::mono_string_from_godot(msbuild_tools_path + "MSBuild.exe");
+ // FrameworkPathOverride
+ const MonoRegInfo &mono_reg_info = GDMono::get_singleton()->get_mono_reg_info();
+ if (mono_reg_info.assembly_dir.length()) {
+ *r_msbuild_path = GDMonoMarshal::mono_string_from_godot(msbuild_tools_path + "MSBuild.exe");
+
+ String framework_path = path_join(mono_reg_info.assembly_dir, "mono", "4.5");
+ *r_framework_path = GDMonoMarshal::mono_string_from_godot(framework_path);
+ } else {
+ ERR_PRINT("Cannot find Mono's assemblies directory in the registry");
+ }
+
+ return;
}
- OS::get_singleton()->print("Cannot find System's MSBuild. Trying with Mono's...\n");
- }
+ if (OS::get_singleton()->is_stdout_verbose())
+ OS::get_singleton()->print("Cannot find System's MSBuild. Trying with Mono's...\n");
+ } // fall through
case GodotSharpBuilds::MSBUILD_MONO: {
String msbuild_path = GDMono::get_singleton()->get_mono_reg_info().bin_dir.plus_file("msbuild.bat");
@@ -96,17 +113,10 @@ MonoString *godot_icall_BuildInstance_get_MSBuildPath() {
WARN_PRINTS("Cannot find msbuild ('mono/builds/build_tool'). Tried with path: " + msbuild_path);
}
- return GDMonoMarshal::mono_string_from_godot(msbuild_path);
- }
- case GodotSharpBuilds::XBUILD: {
- String xbuild_path = GDMono::get_singleton()->get_mono_reg_info().bin_dir.plus_file("xbuild.bat");
+ *r_msbuild_path = GDMonoMarshal::mono_string_from_godot(msbuild_path);
- if (!FileAccess::exists(xbuild_path)) {
- WARN_PRINTS("Cannot find xbuild ('mono/builds/build_tool'). Tried with path: " + xbuild_path);
- }
-
- return GDMonoMarshal::mono_string_from_godot(xbuild_path);
- }
+ return;
+ } break;
default:
ERR_EXPLAIN("You don't deserve to live");
CRASH_NOW();
@@ -118,25 +128,28 @@ MonoString *godot_icall_BuildInstance_get_MSBuildPath() {
if (build_tool != GodotSharpBuilds::XBUILD) {
if (msbuild_path.empty()) {
WARN_PRINT("Cannot find msbuild ('mono/builds/build_tool').");
- return NULL;
+ return;
}
} else {
if (xbuild_path.empty()) {
WARN_PRINT("Cannot find xbuild ('mono/builds/build_tool').");
- return NULL;
+ return;
}
}
- return GDMonoMarshal::mono_string_from_godot(build_tool != GodotSharpBuilds::XBUILD ? msbuild_path : xbuild_path);
+ *r_msbuild_path = GDMonoMarshal::mono_string_from_godot(build_tool != GodotSharpBuilds::XBUILD ? msbuild_path : xbuild_path);
+
+ return;
#else
- return NULL;
+ ERR_PRINT("Not implemented on this platform");
+ return;
#endif
}
void GodotSharpBuilds::_register_internal_calls() {
mono_add_internal_call("GodotSharpTools.Build.BuildSystem::godot_icall_BuildInstance_ExitCallback", (void *)godot_icall_BuildInstance_ExitCallback);
- mono_add_internal_call("GodotSharpTools.Build.BuildInstance::godot_icall_BuildInstance_get_MSBuildPath", (void *)godot_icall_BuildInstance_get_MSBuildPath);
+ mono_add_internal_call("GodotSharpTools.Build.BuildInstance::godot_icall_BuildInstance_get_MSBuildInfo", (void *)godot_icall_BuildInstance_get_MSBuildInfo);
}
void GodotSharpBuilds::show_build_error_dialog(const String &p_message) {
@@ -269,7 +282,7 @@ bool GodotSharpBuilds::make_api_sln(GodotSharpBuilds::APIType p_api_type) {
return true;
}
-bool godotsharp_build_callback() {
+bool GodotSharpBuilds::build_project_blocking() {
if (!FileAccess::exists(GodotSharpDirs::get_project_sln_path()))
return true; // No solution to build
@@ -348,14 +361,25 @@ GodotSharpBuilds::GodotSharpBuilds() {
singleton = this;
- EditorNode::get_singleton()->add_build_callback(&godotsharp_build_callback);
+ EditorNode::get_singleton()->add_build_callback(&GodotSharpBuilds::build_project_blocking);
// Build tool settings
EditorSettings *ed_settings = EditorSettings::get_singleton();
- if (!ed_settings->has_setting("mono/builds/build_tool")) {
- ed_settings->set_setting("mono/builds/build_tool", MSBUILD);
- }
- ed_settings->add_property_hint(PropertyInfo(Variant::INT, "mono/builds/build_tool", PROPERTY_HINT_ENUM, "MSBuild (System),MSBuild (Mono),xbuild"));
+
+#ifdef WINDOWS_ENABLED
+ // TODO: Default to MSBUILD_MONO if its csc.exe issue is fixed in the installed mono version
+ EDITOR_DEF("mono/builds/build_tool", MSBUILD);
+#else
+ EDITOR_DEF("mono/builds/build_tool", MSBUILD_MONO);
+#endif
+
+ ed_settings->add_property_hint(PropertyInfo(Variant::INT, "mono/builds/build_tool", PROPERTY_HINT_ENUM,
+#ifdef WINDOWS_ENABLED
+ "MSBuild (Mono),MSBuild (System)"
+#else
+ "MSBuild (Mono),xbuild (Deprecated)"
+#endif
+ ));
}
GodotSharpBuilds::~GodotSharpBuilds() {
@@ -395,10 +419,11 @@ void GodotSharpBuilds::BuildProcess::start(bool p_blocking) {
}
if (!exited) {
- ERR_PRINT("BuildProcess::start called, but process still running");
exited = true;
- build_tab->on_build_exec_failed("!exited");
- return;
+ String message = "Tried to start build process, but it is already running";
+ build_tab->on_build_exec_failed(message);
+ ERR_EXPLAIN(message);
+ ERR_FAIL();
}
exited = false;
@@ -410,10 +435,12 @@ void GodotSharpBuilds::BuildProcess::start(bool p_blocking) {
if (d->file_exists(issues_file)) {
Error err = d->remove(issues_file);
if (err != OK) {
- ERR_PRINTS("Cannot remove file: " + logs_dir.plus_file(issues_file));
exited = true;
- build_tab->on_build_exec_failed("Cannot remove file: " + issues_file);
- return;
+ String file_path = ProjectSettings::get_singleton()->localize_path(logs_dir).plus_file(issues_file);
+ String message = "Cannot remove issues file: " + file_path;
+ build_tab->on_build_exec_failed(message);
+ ERR_EXPLAIN(message);
+ ERR_FAIL();
}
}
@@ -434,7 +461,9 @@ void GodotSharpBuilds::BuildProcess::start(bool p_blocking) {
if (ex) {
exited = true;
- build_tab->on_build_exec_failed("The build constructor threw an exception.\n" + GDMonoUtils::get_exception_name_and_message(ex));
+ String message = "The build constructor threw an exception.\n" + GDMonoUtils::get_exception_name_and_message(ex);
+ build_tab->on_build_exec_failed(message);
+ ERR_EXPLAIN(message);
ERR_FAIL();
}
@@ -452,7 +481,9 @@ void GodotSharpBuilds::BuildProcess::start(bool p_blocking) {
if (ex) {
exited = true;
- build_tab->on_build_exec_failed("The build method threw an exception.\n" + GDMonoUtils::get_exception_name_and_message(ex));
+ String message = "The build method threw an exception.\n" + GDMonoUtils::get_exception_name_and_message(ex);
+ build_tab->on_build_exec_failed(message);
+ ERR_EXPLAIN(message);
ERR_FAIL();
}
diff --git a/modules/mono/editor/godotsharp_builds.h b/modules/mono/editor/godotsharp_builds.h
index 6d5fa3b44a..7d2f38a774 100644
--- a/modules/mono/editor/godotsharp_builds.h
+++ b/modules/mono/editor/godotsharp_builds.h
@@ -67,9 +67,12 @@ public:
};
enum BuildTool {
- MSBUILD,
MSBUILD_MONO,
- XBUILD
+#ifdef WINDOWS_ENABLED
+ MSBUILD
+#else
+ XBUILD // Deprecated
+#endif
};
_FORCE_INLINE_ static GodotSharpBuilds *get_singleton() { return singleton; }
@@ -89,6 +92,8 @@ public:
static bool make_api_sln(APIType p_api_type);
+ static bool build_project_blocking();
+
GodotSharpBuilds();
~GodotSharpBuilds();
};
diff --git a/modules/mono/editor/godotsharp_editor.cpp b/modules/mono/editor/godotsharp_editor.cpp
index 30e7653256..1bc1e8a515 100644
--- a/modules/mono/editor/godotsharp_editor.cpp
+++ b/modules/mono/editor/godotsharp_editor.cpp
@@ -46,21 +46,6 @@
#include "../utils/mono_reg_utils.h"
#endif
-class MonoReloadNode : public Node {
- GDCLASS(MonoReloadNode, Node)
-
-protected:
- void _notification(int p_what) {
- switch (p_what) {
- case MainLoop::NOTIFICATION_WM_FOCUS_IN: {
- CSharpLanguage::get_singleton()->reload_assemblies_if_needed(true);
- } break;
- default: {
- } break;
- };
- }
-};
-
GodotSharpEditor *GodotSharpEditor::singleton = NULL;
bool GodotSharpEditor::_create_project_solution() {
@@ -71,6 +56,10 @@ bool GodotSharpEditor::_create_project_solution() {
String path = OS::get_singleton()->get_resource_dir();
String name = ProjectSettings::get_singleton()->get("application/config/name");
+ if (name.empty()) {
+ name = "UnnamedProject";
+ }
+
String guid = CSharpProject::generate_game_project(path, name);
if (guid.length()) {
@@ -182,11 +171,6 @@ Error GodotSharpEditor::open_in_external_editor(const Ref<Script> &p_script, int
String script_path = ProjectSettings::get_singleton()->globalize_path(p_script->get_path());
monodevel_instance->execute(script_path);
} break;
- case EDITOR_VISUAL_STUDIO:
- // TODO
- // devenv <PathToSolutionFolder>
- // devenv /edit <PathToCsFile> /command "edit.goto <Line>"
- // HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\SxS\VS7
default:
return ERR_UNAVAILABLE;
}
@@ -237,10 +221,8 @@ GodotSharpEditor::GodotSharpEditor(EditorNode *p_editor) {
// External editor settings
EditorSettings *ed_settings = EditorSettings::get_singleton();
- if (!ed_settings->has_setting("mono/editor/external_editor")) {
- ed_settings->set_setting("mono/editor/external_editor", EDITOR_NONE);
- }
- ed_settings->add_property_hint(PropertyInfo(Variant::INT, "mono/editor/external_editor", PROPERTY_HINT_ENUM, "None,MonoDevelop,Visual Studio,Visual Studio Code"));
+ EDITOR_DEF("mono/editor/external_editor", EDITOR_NONE);
+ ed_settings->add_property_hint(PropertyInfo(Variant::INT, "mono/editor/external_editor", PROPERTY_HINT_ENUM, "None,MonoDevelop,Visual Studio Code"));
}
GodotSharpEditor::~GodotSharpEditor() {
@@ -254,3 +236,49 @@ GodotSharpEditor::~GodotSharpEditor() {
monodevel_instance = NULL;
}
}
+
+MonoReloadNode *MonoReloadNode::singleton = NULL;
+
+void MonoReloadNode::_reload_timer_timeout() {
+
+ CSharpLanguage::get_singleton()->reload_assemblies_if_needed(false);
+}
+
+void MonoReloadNode::restart_reload_timer() {
+
+ reload_timer->stop();
+ reload_timer->start();
+}
+
+void MonoReloadNode::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("_reload_timer_timeout"), &MonoReloadNode::_reload_timer_timeout);
+}
+
+void MonoReloadNode::_notification(int p_what) {
+ switch (p_what) {
+ case MainLoop::NOTIFICATION_WM_FOCUS_IN: {
+ restart_reload_timer();
+ CSharpLanguage::get_singleton()->reload_assemblies_if_needed(true);
+ } break;
+ default: {
+ } break;
+ };
+}
+
+MonoReloadNode::MonoReloadNode() {
+
+ singleton = this;
+
+ reload_timer = memnew(Timer);
+ add_child(reload_timer);
+ reload_timer->set_one_shot(false);
+ reload_timer->set_wait_time(EDITOR_DEF("mono/assembly_watch_interval_sec", 0.5));
+ reload_timer->connect("timeout", this, "_reload_timer_timeout");
+ reload_timer->start();
+}
+
+MonoReloadNode::~MonoReloadNode() {
+
+ singleton = NULL;
+}
diff --git a/modules/mono/editor/godotsharp_editor.h b/modules/mono/editor/godotsharp_editor.h
index 1ecb8c7a94..0f2c163582 100644
--- a/modules/mono/editor/godotsharp_editor.h
+++ b/modules/mono/editor/godotsharp_editor.h
@@ -69,7 +69,6 @@ public:
enum ExternalEditor {
EDITOR_NONE,
EDITOR_MONODEVELOP,
- EDITOR_VISUAL_STUDIO,
EDITOR_CODE,
};
@@ -84,4 +83,27 @@ public:
~GodotSharpEditor();
};
+class MonoReloadNode : public Node {
+ GDCLASS(MonoReloadNode, Node)
+
+ Timer *reload_timer;
+
+ void _reload_timer_timeout();
+
+ static MonoReloadNode *singleton;
+
+protected:
+ static void _bind_methods();
+
+ void _notification(int p_what);
+
+public:
+ _FORCE_INLINE_ static MonoReloadNode *get_singleton() { return singleton; }
+
+ void restart_reload_timer();
+
+ MonoReloadNode();
+ ~MonoReloadNode();
+};
+
#endif // GODOTSHARP_EDITOR_H
diff --git a/modules/mono/editor/mono_bottom_panel.cpp b/modules/mono/editor/mono_bottom_panel.cpp
index 07109eaac7..31dc09856a 100644
--- a/modules/mono/editor/mono_bottom_panel.cpp
+++ b/modules/mono/editor/mono_bottom_panel.cpp
@@ -139,6 +139,14 @@ void MonoBottomPanel::_errors_toggled(bool p_pressed) {
build_tab->_update_issues_list();
}
+void MonoBottomPanel::_build_project_pressed() {
+
+ GodotSharpBuilds::get_singleton()->build_project_blocking();
+
+ MonoReloadNode::get_singleton()->restart_reload_timer();
+ CSharpLanguage::get_singleton()->reload_assemblies_if_needed(true);
+}
+
void MonoBottomPanel::_notification(int p_what) {
switch (p_what) {
@@ -153,6 +161,7 @@ void MonoBottomPanel::_notification(int p_what) {
void MonoBottomPanel::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("_build_project_pressed"), &MonoBottomPanel::_build_project_pressed);
ClassDB::bind_method(D_METHOD("_warnings_toggled", "pressed"), &MonoBottomPanel::_warnings_toggled);
ClassDB::bind_method(D_METHOD("_errors_toggled", "pressed"), &MonoBottomPanel::_errors_toggled);
ClassDB::bind_method(D_METHOD("_build_tab_item_selected", "idx"), &MonoBottomPanel::_build_tab_item_selected);
@@ -187,6 +196,12 @@ MonoBottomPanel::MonoBottomPanel(EditorNode *p_editor) {
toolbar_hbc->set_h_size_flags(SIZE_EXPAND_FILL);
panel_builds_tab->add_child(toolbar_hbc);
+ ToolButton *build_project_btn = memnew(ToolButton);
+ build_project_btn->set_text("Build Project");
+ build_project_btn->set_focus_mode(FOCUS_NONE);
+ build_project_btn->connect("pressed", this, "_build_project_pressed");
+ toolbar_hbc->add_child(build_project_btn);
+
toolbar_hbc->add_spacer();
warnings_btn = memnew(ToolButton);
@@ -280,7 +295,11 @@ void MonoBuildTab::_update_issues_list() {
String tooltip;
tooltip += String("Message: ") + issue.message;
- tooltip += String("\nCode: ") + issue.code;
+
+ if (issue.code.length()) {
+ tooltip += String("\nCode: ") + issue.code;
+ }
+
tooltip += String("\nType: ") + (issue.warning ? "warning" : "error");
String text;
@@ -356,23 +375,21 @@ void MonoBuildTab::on_build_exit(BuildResult result) {
MonoBottomPanel::get_singleton()->raise_build_tab(this);
}
-void MonoBuildTab::on_build_exec_failed(const String &p_cause, const String &p_detailed) {
+void MonoBuildTab::on_build_exec_failed(const String &p_cause) {
build_exited = true;
build_result = RESULT_ERROR;
issues_list->clear();
- String tooltip;
+ BuildIssue issue;
+ issue.message = p_cause;
+ issue.warning = false;
- tooltip += "Message: " + (p_detailed.length() ? p_detailed : p_cause);
- tooltip += "\nType: error";
+ error_count += 1;
+ issues.push_back(issue);
- int line_break_idx = p_cause.find("\n");
- issues_list->add_item(line_break_idx == -1 ? p_cause : p_cause.substr(0, line_break_idx),
- get_icon("Error", "EditorIcons"));
- int index = issues_list->get_item_count() - 1;
- issues_list->set_item_tooltip(index, tooltip);
+ _update_issues_list();
MonoBottomPanel::get_singleton()->raise_build_tab(this);
}
diff --git a/modules/mono/editor/mono_bottom_panel.h b/modules/mono/editor/mono_bottom_panel.h
index 909fa4b385..5cc4aa3240 100644
--- a/modules/mono/editor/mono_bottom_panel.h
+++ b/modules/mono/editor/mono_bottom_panel.h
@@ -61,6 +61,8 @@ class MonoBottomPanel : public VBoxContainer {
void _warnings_toggled(bool p_pressed);
void _errors_toggled(bool p_pressed);
+ void _build_project_pressed();
+
static MonoBottomPanel *singleton;
protected:
@@ -134,7 +136,7 @@ public:
void on_build_start();
void on_build_exit(BuildResult result);
- void on_build_exec_failed(const String &p_cause, const String &p_detailed = String());
+ void on_build_exec_failed(const String &p_cause);
void restart_build();
void stop_build();
diff --git a/modules/mono/glue/cs_files/Rect3.cs b/modules/mono/glue/cs_files/AABB.cs
index 0d25de1ec6..6ee3bbe53a 100644
--- a/modules/mono/glue/cs_files/Rect3.cs
+++ b/modules/mono/glue/cs_files/AABB.cs
@@ -1,477 +1,477 @@
-using System;
-
-// file: core/math/rect3.h
-// commit: 7ad14e7a3e6f87ddc450f7e34621eb5200808451
-// file: core/math/rect3.cpp
-// commit: bd282ff43f23fe845f29a3e25c8efc01bd65ffb0
-// file: core/variant_call.cpp
-// commit: 5ad9be4c24e9d7dc5672fdc42cea896622fe5685
-
-namespace Godot
-{
- public struct Rect3 : IEquatable<Rect3>
- {
- private Vector3 position;
- private Vector3 size;
-
- public Vector3 Position
- {
- get
- {
- return position;
- }
- }
-
- public Vector3 Size
- {
- get
- {
- return size;
- }
- }
-
- public Vector3 End
- {
- get
- {
- return position + size;
- }
- }
-
- public bool encloses(Rect3 with)
- {
- Vector3 src_min = position;
- Vector3 src_max = position + size;
- Vector3 dst_min = with.position;
- Vector3 dst_max = with.position + with.size;
-
- return ((src_min.x <= dst_min.x) &&
- (src_max.x > dst_max.x) &&
- (src_min.y <= dst_min.y) &&
- (src_max.y > dst_max.y) &&
- (src_min.z <= dst_min.z) &&
- (src_max.z > dst_max.z));
- }
-
- public Rect3 expand(Vector3 to_point)
- {
- Vector3 begin = position;
- Vector3 end = position + size;
-
- if (to_point.x < begin.x)
- begin.x = to_point.x;
- if (to_point.y < begin.y)
- begin.y = to_point.y;
- if (to_point.z < begin.z)
- begin.z = to_point.z;
-
- if (to_point.x > end.x)
- end.x = to_point.x;
- if (to_point.y > end.y)
- end.y = to_point.y;
- if (to_point.z > end.z)
- end.z = to_point.z;
-
- return new Rect3(begin, end - begin);
- }
-
- public float get_area()
- {
- return size.x * size.y * size.z;
- }
-
- public Vector3 get_endpoint(int idx)
- {
- switch (idx)
- {
- case 0:
- return new Vector3(position.x, position.y, position.z);
- case 1:
- return new Vector3(position.x, position.y, position.z + size.z);
- case 2:
- return new Vector3(position.x, position.y + size.y, position.z);
- case 3:
- return new Vector3(position.x, position.y + size.y, position.z + size.z);
- case 4:
- return new Vector3(position.x + size.x, position.y, position.z);
- case 5:
- return new Vector3(position.x + size.x, position.y, position.z + size.z);
- case 6:
- return new Vector3(position.x + size.x, position.y + size.y, position.z);
- case 7:
- return new Vector3(position.x + size.x, position.y + size.y, position.z + size.z);
- default:
- throw new ArgumentOutOfRangeException(nameof(idx), String.Format("Index is {0}, but a value from 0 to 7 is expected.", idx));
- }
- }
-
- public Vector3 get_longest_axis()
- {
- Vector3 axis = new Vector3(1f, 0f, 0f);
- float max_size = size.x;
-
- if (size.y > max_size)
- {
- axis = new Vector3(0f, 1f, 0f);
- max_size = size.y;
- }
-
- if (size.z > max_size)
- {
- axis = new Vector3(0f, 0f, 1f);
- max_size = size.z;
- }
-
- return axis;
- }
-
- public Vector3.Axis get_longest_axis_index()
- {
- Vector3.Axis axis = Vector3.Axis.X;
- float max_size = size.x;
-
- if (size.y > max_size)
- {
- axis = Vector3.Axis.Y;
- max_size = size.y;
- }
-
- if (size.z > max_size)
- {
- axis = Vector3.Axis.Z;
- max_size = size.z;
- }
-
- return axis;
- }
-
- public float get_longest_axis_size()
- {
- float max_size = size.x;
-
- if (size.y > max_size)
- max_size = size.y;
-
- if (size.z > max_size)
- max_size = size.z;
-
- return max_size;
- }
-
- public Vector3 get_shortest_axis()
- {
- Vector3 axis = new Vector3(1f, 0f, 0f);
- float max_size = size.x;
-
- if (size.y < max_size)
- {
- axis = new Vector3(0f, 1f, 0f);
- max_size = size.y;
- }
-
- if (size.z < max_size)
- {
- axis = new Vector3(0f, 0f, 1f);
- max_size = size.z;
- }
-
- return axis;
- }
-
- public Vector3.Axis get_shortest_axis_index()
- {
- Vector3.Axis axis = Vector3.Axis.X;
- float max_size = size.x;
-
- if (size.y < max_size)
- {
- axis = Vector3.Axis.Y;
- max_size = size.y;
- }
-
- if (size.z < max_size)
- {
- axis = Vector3.Axis.Z;
- max_size = size.z;
- }
-
- return axis;
- }
-
- public float get_shortest_axis_size()
- {
- float max_size = size.x;
-
- if (size.y < max_size)
- max_size = size.y;
-
- if (size.z < max_size)
- max_size = size.z;
-
- return max_size;
- }
-
- public Vector3 get_support(Vector3 dir)
- {
- Vector3 half_extents = size * 0.5f;
- Vector3 ofs = position + half_extents;
-
- return ofs + new Vector3(
- (dir.x > 0f) ? -half_extents.x : half_extents.x,
- (dir.y > 0f) ? -half_extents.y : half_extents.y,
- (dir.z > 0f) ? -half_extents.z : half_extents.z);
- }
-
- public Rect3 grow(float by)
- {
- Rect3 res = this;
-
- res.position.x -= by;
- res.position.y -= by;
- res.position.z -= by;
- res.size.x += 2.0f * by;
- res.size.y += 2.0f * by;
- res.size.z += 2.0f * by;
-
- return res;
- }
-
- public bool has_no_area()
- {
- return size.x <= 0f || size.y <= 0f || size.z <= 0f;
- }
-
- public bool has_no_surface()
- {
- return size.x <= 0f && size.y <= 0f && size.z <= 0f;
- }
-
- public bool has_point(Vector3 point)
- {
- if (point.x < position.x)
- return false;
- if (point.y < position.y)
- return false;
- if (point.z < position.z)
- return false;
- if (point.x > position.x + size.x)
- return false;
- if (point.y > position.y + size.y)
- return false;
- if (point.z > position.z + size.z)
- return false;
-
- return true;
- }
-
- public Rect3 intersection(Rect3 with)
- {
- Vector3 src_min = position;
- Vector3 src_max = position + size;
- Vector3 dst_min = with.position;
- Vector3 dst_max = with.position + with.size;
-
- Vector3 min, max;
-
- if (src_min.x > dst_max.x || src_max.x < dst_min.x)
- {
- return new Rect3();
- }
- else
- {
- min.x = (src_min.x > dst_min.x) ? src_min.x : dst_min.x;
- max.x = (src_max.x < dst_max.x) ? src_max.x : dst_max.x;
- }
-
- if (src_min.y > dst_max.y || src_max.y < dst_min.y)
- {
- return new Rect3();
- }
- else
- {
- min.y = (src_min.y > dst_min.y) ? src_min.y : dst_min.y;
- max.y = (src_max.y < dst_max.y) ? src_max.y : dst_max.y;
- }
-
- if (src_min.z > dst_max.z || src_max.z < dst_min.z)
- {
- return new Rect3();
- }
- else
- {
- min.z = (src_min.z > dst_min.z) ? src_min.z : dst_min.z;
- max.z = (src_max.z < dst_max.z) ? src_max.z : dst_max.z;
- }
-
- return new Rect3(min, max - min);
- }
-
- public bool intersects(Rect3 with)
- {
- if (position.x >= (with.position.x + with.size.x))
- return false;
- if ((position.x + size.x) <= with.position.x)
- return false;
- if (position.y >= (with.position.y + with.size.y))
- return false;
- if ((position.y + size.y) <= with.position.y)
- return false;
- if (position.z >= (with.position.z + with.size.z))
- return false;
- if ((position.z + size.z) <= with.position.z)
- return false;
-
- return true;
- }
-
- public bool intersects_plane(Plane plane)
- {
- Vector3[] points =
- {
- new Vector3(position.x, position.y, position.z),
- new Vector3(position.x, position.y, position.z + size.z),
- new Vector3(position.x, position.y + size.y, position.z),
- new Vector3(position.x, position.y + size.y, position.z + size.z),
- new Vector3(position.x + size.x, position.y, position.z),
- new Vector3(position.x + size.x, position.y, position.z + size.z),
- new Vector3(position.x + size.x, position.y + size.y, position.z),
- new Vector3(position.x + size.x, position.y + size.y, position.z + size.z),
- };
-
- bool over = false;
- bool under = false;
-
- for (int i = 0; i < 8; i++)
- {
- if (plane.distance_to(points[i]) > 0)
- over = true;
- else
- under = true;
- }
-
- return under && over;
- }
-
- public bool intersects_segment(Vector3 from, Vector3 to)
- {
- float min = 0f;
- float max = 1f;
-
- for (int i = 0; i < 3; i++)
- {
- float seg_from = from[i];
- float seg_to = to[i];
- float box_begin = position[i];
- float box_end = box_begin + size[i];
- float cmin, cmax;
-
- if (seg_from < seg_to)
- {
- if (seg_from > box_end || seg_to < box_begin)
- return false;
-
- float length = seg_to - seg_from;
- cmin = seg_from < box_begin ? (box_begin - seg_from) / length : 0f;
- cmax = seg_to > box_end ? (box_end - seg_from) / length : 1f;
- }
- else
- {
- if (seg_to > box_end || seg_from < box_begin)
- return false;
-
- float length = seg_to - seg_from;
- cmin = seg_from > box_end ? (box_end - seg_from) / length : 0f;
- cmax = seg_to < box_begin ? (box_begin - seg_from) / length : 1f;
- }
-
- if (cmin > min)
- {
- min = cmin;
- }
-
- if (cmax < max)
- max = cmax;
- if (max < min)
- return false;
- }
-
- return true;
- }
-
- public Rect3 merge(Rect3 with)
- {
- Vector3 beg_1 = position;
- Vector3 beg_2 = with.position;
- Vector3 end_1 = new Vector3(size.x, size.y, size.z) + beg_1;
- Vector3 end_2 = new Vector3(with.size.x, with.size.y, with.size.z) + beg_2;
-
- Vector3 min = new Vector3(
- (beg_1.x < beg_2.x) ? beg_1.x : beg_2.x,
- (beg_1.y < beg_2.y) ? beg_1.y : beg_2.y,
- (beg_1.z < beg_2.z) ? beg_1.z : beg_2.z
- );
-
- Vector3 max = new Vector3(
- (end_1.x > end_2.x) ? end_1.x : end_2.x,
- (end_1.y > end_2.y) ? end_1.y : end_2.y,
- (end_1.z > end_2.z) ? end_1.z : end_2.z
- );
-
- return new Rect3(min, max - min);
- }
-
- public Rect3(Vector3 position, Vector3 size)
- {
- this.position = position;
- this.size = size;
- }
-
- public static bool operator ==(Rect3 left, Rect3 right)
- {
- return left.Equals(right);
- }
-
- public static bool operator !=(Rect3 left, Rect3 right)
- {
- return !left.Equals(right);
- }
-
- public override bool Equals(object obj)
- {
- if (obj is Rect3)
- {
- return Equals((Rect3)obj);
- }
-
- return false;
- }
-
- public bool Equals(Rect3 other)
- {
- return position == other.position && size == other.size;
- }
-
- public override int GetHashCode()
- {
- return position.GetHashCode() ^ size.GetHashCode();
- }
-
- public override string ToString()
- {
- return String.Format("{0} - {1}", new object[]
- {
- this.position.ToString(),
- this.size.ToString()
- });
- }
-
- public string ToString(string format)
- {
- return String.Format("{0} - {1}", new object[]
- {
- this.position.ToString(format),
- this.size.ToString(format)
- });
- }
- }
-}
+using System;
+
+// file: core/math/aabb.h
+// commit: 7ad14e7a3e6f87ddc450f7e34621eb5200808451
+// file: core/math/aabb.cpp
+// commit: bd282ff43f23fe845f29a3e25c8efc01bd65ffb0
+// file: core/variant_call.cpp
+// commit: 5ad9be4c24e9d7dc5672fdc42cea896622fe5685
+
+namespace Godot
+{
+ public struct AABB : IEquatable<AABB>
+ {
+ private Vector3 position;
+ private Vector3 size;
+
+ public Vector3 Position
+ {
+ get
+ {
+ return position;
+ }
+ }
+
+ public Vector3 Size
+ {
+ get
+ {
+ return size;
+ }
+ }
+
+ public Vector3 End
+ {
+ get
+ {
+ return position + size;
+ }
+ }
+
+ public bool encloses(AABB with)
+ {
+ Vector3 src_min = position;
+ Vector3 src_max = position + size;
+ Vector3 dst_min = with.position;
+ Vector3 dst_max = with.position + with.size;
+
+ return ((src_min.x <= dst_min.x) &&
+ (src_max.x > dst_max.x) &&
+ (src_min.y <= dst_min.y) &&
+ (src_max.y > dst_max.y) &&
+ (src_min.z <= dst_min.z) &&
+ (src_max.z > dst_max.z));
+ }
+
+ public AABB expand(Vector3 to_point)
+ {
+ Vector3 begin = position;
+ Vector3 end = position + size;
+
+ if (to_point.x < begin.x)
+ begin.x = to_point.x;
+ if (to_point.y < begin.y)
+ begin.y = to_point.y;
+ if (to_point.z < begin.z)
+ begin.z = to_point.z;
+
+ if (to_point.x > end.x)
+ end.x = to_point.x;
+ if (to_point.y > end.y)
+ end.y = to_point.y;
+ if (to_point.z > end.z)
+ end.z = to_point.z;
+
+ return new AABB(begin, end - begin);
+ }
+
+ public float get_area()
+ {
+ return size.x * size.y * size.z;
+ }
+
+ public Vector3 get_endpoint(int idx)
+ {
+ switch (idx)
+ {
+ case 0:
+ return new Vector3(position.x, position.y, position.z);
+ case 1:
+ return new Vector3(position.x, position.y, position.z + size.z);
+ case 2:
+ return new Vector3(position.x, position.y + size.y, position.z);
+ case 3:
+ return new Vector3(position.x, position.y + size.y, position.z + size.z);
+ case 4:
+ return new Vector3(position.x + size.x, position.y, position.z);
+ case 5:
+ return new Vector3(position.x + size.x, position.y, position.z + size.z);
+ case 6:
+ return new Vector3(position.x + size.x, position.y + size.y, position.z);
+ case 7:
+ return new Vector3(position.x + size.x, position.y + size.y, position.z + size.z);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(idx), String.Format("Index is {0}, but a value from 0 to 7 is expected.", idx));
+ }
+ }
+
+ public Vector3 get_longest_axis()
+ {
+ Vector3 axis = new Vector3(1f, 0f, 0f);
+ float max_size = size.x;
+
+ if (size.y > max_size)
+ {
+ axis = new Vector3(0f, 1f, 0f);
+ max_size = size.y;
+ }
+
+ if (size.z > max_size)
+ {
+ axis = new Vector3(0f, 0f, 1f);
+ max_size = size.z;
+ }
+
+ return axis;
+ }
+
+ public Vector3.Axis get_longest_axis_index()
+ {
+ Vector3.Axis axis = Vector3.Axis.X;
+ float max_size = size.x;
+
+ if (size.y > max_size)
+ {
+ axis = Vector3.Axis.Y;
+ max_size = size.y;
+ }
+
+ if (size.z > max_size)
+ {
+ axis = Vector3.Axis.Z;
+ max_size = size.z;
+ }
+
+ return axis;
+ }
+
+ public float get_longest_axis_size()
+ {
+ float max_size = size.x;
+
+ if (size.y > max_size)
+ max_size = size.y;
+
+ if (size.z > max_size)
+ max_size = size.z;
+
+ return max_size;
+ }
+
+ public Vector3 get_shortest_axis()
+ {
+ Vector3 axis = new Vector3(1f, 0f, 0f);
+ float max_size = size.x;
+
+ if (size.y < max_size)
+ {
+ axis = new Vector3(0f, 1f, 0f);
+ max_size = size.y;
+ }
+
+ if (size.z < max_size)
+ {
+ axis = new Vector3(0f, 0f, 1f);
+ max_size = size.z;
+ }
+
+ return axis;
+ }
+
+ public Vector3.Axis get_shortest_axis_index()
+ {
+ Vector3.Axis axis = Vector3.Axis.X;
+ float max_size = size.x;
+
+ if (size.y < max_size)
+ {
+ axis = Vector3.Axis.Y;
+ max_size = size.y;
+ }
+
+ if (size.z < max_size)
+ {
+ axis = Vector3.Axis.Z;
+ max_size = size.z;
+ }
+
+ return axis;
+ }
+
+ public float get_shortest_axis_size()
+ {
+ float max_size = size.x;
+
+ if (size.y < max_size)
+ max_size = size.y;
+
+ if (size.z < max_size)
+ max_size = size.z;
+
+ return max_size;
+ }
+
+ public Vector3 get_support(Vector3 dir)
+ {
+ Vector3 half_extents = size * 0.5f;
+ Vector3 ofs = position + half_extents;
+
+ return ofs + new Vector3(
+ (dir.x > 0f) ? -half_extents.x : half_extents.x,
+ (dir.y > 0f) ? -half_extents.y : half_extents.y,
+ (dir.z > 0f) ? -half_extents.z : half_extents.z);
+ }
+
+ public AABB grow(float by)
+ {
+ AABB res = this;
+
+ res.position.x -= by;
+ res.position.y -= by;
+ res.position.z -= by;
+ res.size.x += 2.0f * by;
+ res.size.y += 2.0f * by;
+ res.size.z += 2.0f * by;
+
+ return res;
+ }
+
+ public bool has_no_area()
+ {
+ return size.x <= 0f || size.y <= 0f || size.z <= 0f;
+ }
+
+ public bool has_no_surface()
+ {
+ return size.x <= 0f && size.y <= 0f && size.z <= 0f;
+ }
+
+ public bool has_point(Vector3 point)
+ {
+ if (point.x < position.x)
+ return false;
+ if (point.y < position.y)
+ return false;
+ if (point.z < position.z)
+ return false;
+ if (point.x > position.x + size.x)
+ return false;
+ if (point.y > position.y + size.y)
+ return false;
+ if (point.z > position.z + size.z)
+ return false;
+
+ return true;
+ }
+
+ public AABB intersection(AABB with)
+ {
+ Vector3 src_min = position;
+ Vector3 src_max = position + size;
+ Vector3 dst_min = with.position;
+ Vector3 dst_max = with.position + with.size;
+
+ Vector3 min, max;
+
+ if (src_min.x > dst_max.x || src_max.x < dst_min.x)
+ {
+ return new AABB();
+ }
+ else
+ {
+ min.x = (src_min.x > dst_min.x) ? src_min.x : dst_min.x;
+ max.x = (src_max.x < dst_max.x) ? src_max.x : dst_max.x;
+ }
+
+ if (src_min.y > dst_max.y || src_max.y < dst_min.y)
+ {
+ return new AABB();
+ }
+ else
+ {
+ min.y = (src_min.y > dst_min.y) ? src_min.y : dst_min.y;
+ max.y = (src_max.y < dst_max.y) ? src_max.y : dst_max.y;
+ }
+
+ if (src_min.z > dst_max.z || src_max.z < dst_min.z)
+ {
+ return new AABB();
+ }
+ else
+ {
+ min.z = (src_min.z > dst_min.z) ? src_min.z : dst_min.z;
+ max.z = (src_max.z < dst_max.z) ? src_max.z : dst_max.z;
+ }
+
+ return new AABB(min, max - min);
+ }
+
+ public bool intersects(AABB with)
+ {
+ if (position.x >= (with.position.x + with.size.x))
+ return false;
+ if ((position.x + size.x) <= with.position.x)
+ return false;
+ if (position.y >= (with.position.y + with.size.y))
+ return false;
+ if ((position.y + size.y) <= with.position.y)
+ return false;
+ if (position.z >= (with.position.z + with.size.z))
+ return false;
+ if ((position.z + size.z) <= with.position.z)
+ return false;
+
+ return true;
+ }
+
+ public bool intersects_plane(Plane plane)
+ {
+ Vector3[] points =
+ {
+ new Vector3(position.x, position.y, position.z),
+ new Vector3(position.x, position.y, position.z + size.z),
+ new Vector3(position.x, position.y + size.y, position.z),
+ new Vector3(position.x, position.y + size.y, position.z + size.z),
+ new Vector3(position.x + size.x, position.y, position.z),
+ new Vector3(position.x + size.x, position.y, position.z + size.z),
+ new Vector3(position.x + size.x, position.y + size.y, position.z),
+ new Vector3(position.x + size.x, position.y + size.y, position.z + size.z),
+ };
+
+ bool over = false;
+ bool under = false;
+
+ for (int i = 0; i < 8; i++)
+ {
+ if (plane.distance_to(points[i]) > 0)
+ over = true;
+ else
+ under = true;
+ }
+
+ return under && over;
+ }
+
+ public bool intersects_segment(Vector3 from, Vector3 to)
+ {
+ float min = 0f;
+ float max = 1f;
+
+ for (int i = 0; i < 3; i++)
+ {
+ float seg_from = from[i];
+ float seg_to = to[i];
+ float box_begin = position[i];
+ float box_end = box_begin + size[i];
+ float cmin, cmax;
+
+ if (seg_from < seg_to)
+ {
+ if (seg_from > box_end || seg_to < box_begin)
+ return false;
+
+ float length = seg_to - seg_from;
+ cmin = seg_from < box_begin ? (box_begin - seg_from) / length : 0f;
+ cmax = seg_to > box_end ? (box_end - seg_from) / length : 1f;
+ }
+ else
+ {
+ if (seg_to > box_end || seg_from < box_begin)
+ return false;
+
+ float length = seg_to - seg_from;
+ cmin = seg_from > box_end ? (box_end - seg_from) / length : 0f;
+ cmax = seg_to < box_begin ? (box_begin - seg_from) / length : 1f;
+ }
+
+ if (cmin > min)
+ {
+ min = cmin;
+ }
+
+ if (cmax < max)
+ max = cmax;
+ if (max < min)
+ return false;
+ }
+
+ return true;
+ }
+
+ public AABB merge(AABB with)
+ {
+ Vector3 beg_1 = position;
+ Vector3 beg_2 = with.position;
+ Vector3 end_1 = new Vector3(size.x, size.y, size.z) + beg_1;
+ Vector3 end_2 = new Vector3(with.size.x, with.size.y, with.size.z) + beg_2;
+
+ Vector3 min = new Vector3(
+ (beg_1.x < beg_2.x) ? beg_1.x : beg_2.x,
+ (beg_1.y < beg_2.y) ? beg_1.y : beg_2.y,
+ (beg_1.z < beg_2.z) ? beg_1.z : beg_2.z
+ );
+
+ Vector3 max = new Vector3(
+ (end_1.x > end_2.x) ? end_1.x : end_2.x,
+ (end_1.y > end_2.y) ? end_1.y : end_2.y,
+ (end_1.z > end_2.z) ? end_1.z : end_2.z
+ );
+
+ return new AABB(min, max - min);
+ }
+
+ public AABB(Vector3 position, Vector3 size)
+ {
+ this.position = position;
+ this.size = size;
+ }
+
+ public static bool operator ==(AABB left, AABB right)
+ {
+ return left.Equals(right);
+ }
+
+ public static bool operator !=(AABB left, AABB right)
+ {
+ return !left.Equals(right);
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (obj is AABB)
+ {
+ return Equals((AABB)obj);
+ }
+
+ return false;
+ }
+
+ public bool Equals(AABB other)
+ {
+ return position == other.position && size == other.size;
+ }
+
+ public override int GetHashCode()
+ {
+ return position.GetHashCode() ^ size.GetHashCode();
+ }
+
+ public override string ToString()
+ {
+ return String.Format("{0} - {1}", new object[]
+ {
+ this.position.ToString(),
+ this.size.ToString()
+ });
+ }
+
+ public string ToString(string format)
+ {
+ return String.Format("{0} - {1}", new object[]
+ {
+ this.position.ToString(format),
+ this.size.ToString(format)
+ });
+ }
+ }
+}
diff --git a/modules/mono/glue/cs_files/Basis.cs b/modules/mono/glue/cs_files/Basis.cs
index 6a73ebd554..c50e783349 100644
--- a/modules/mono/glue/cs_files/Basis.cs
+++ b/modules/mono/glue/cs_files/Basis.cs
@@ -160,26 +160,29 @@ namespace Godot
Basis m = this.orthonormalized();
Vector3 euler;
+ euler.z = 0.0f;
- euler.y = Mathf.asin(m.x[2]);
+ float mxy = m.y[2];
- if (euler.y < Mathf.PI * 0.5f)
+
+ if (mxy < 1.0f)
{
- if (euler.y > -Mathf.PI * 0.5f)
+ if (mxy > -1.0f)
{
- euler.x = Mathf.atan2(-m.y[2], m.z[2]);
- euler.z = Mathf.atan2(-m.x[1], m.x[0]);
+ euler.x = Mathf.asin(-mxy);
+ euler.y = Mathf.atan2(m.x[2], m.z[2]);
+ euler.z = Mathf.atan2(m.y[0], m.y[1]);
}
else
{
- euler.z = 0.0f;
- euler.x = euler.z - Mathf.atan2(m.y[0], m.y[1]);
+ euler.x = Mathf.PI * 0.5f;
+ euler.y = -Mathf.atan2(-m.x[1], m.x[0]);
}
}
else
{
- euler.z = 0f;
- euler.x = Mathf.atan2(m.x[1], m.y[1]) - euler.z;
+ euler.x = -Mathf.PI * 0.5f;
+ euler.y = -Mathf.atan2(m.x[1], m.x[0]);
}
return euler;
@@ -273,7 +276,7 @@ namespace Godot
public Basis rotated(Vector3 axis, float phi)
{
- return this * new Basis(axis, phi);
+ return new Basis(axis, phi) * this;
}
public Basis scaled(Vector3 scale)
@@ -281,13 +284,13 @@ namespace Godot
Basis m = this;
m[0, 0] *= scale.x;
- m[1, 0] *= scale.x;
- m[2, 0] *= scale.x;
- m[0, 1] *= scale.y;
+ m[0, 1] *= scale.x;
+ m[0, 2] *= scale.x;
+ m[1, 0] *= scale.y;
m[1, 1] *= scale.y;
- m[2, 1] *= scale.y;
- m[0, 2] *= scale.z;
- m[1, 2] *= scale.z;
+ m[1, 2] *= scale.y;
+ m[2, 0] *= scale.z;
+ m[2, 1] *= scale.z;
m[2, 2] *= scale.z;
return m;
@@ -347,6 +350,48 @@ namespace Godot
);
}
+ public Quat Quat() {
+ float trace = x[0] + y[1] + z[2];
+
+ if (trace > 0.0f) {
+ float s = Mathf.sqrt(trace + 1.0f) * 2f;
+ float inv_s = 1f / s;
+ return new Quat(
+ (z[1] - y[2]) * inv_s,
+ (x[2] - z[0]) * inv_s,
+ (y[0] - x[1]) * inv_s,
+ s * 0.25f
+ );
+ } else if (x[0] > y[1] && x[0] > z[2]) {
+ float s = Mathf.sqrt(x[0] - y[1] - z[2] + 1.0f) * 2f;
+ float inv_s = 1f / s;
+ return new Quat(
+ s * 0.25f,
+ (x[1] + y[0]) * inv_s,
+ (x[2] + z[0]) * inv_s,
+ (z[1] - y[2]) * inv_s
+ );
+ } else if (y[1] > z[2]) {
+ float s = Mathf.sqrt(-x[0] + y[1] - z[2] + 1.0f) * 2f;
+ float inv_s = 1f / s;
+ return new Quat(
+ (x[1] + y[0]) * inv_s,
+ s * 0.25f,
+ (y[2] + z[1]) * inv_s,
+ (x[2] - z[0]) * inv_s
+ );
+ } else {
+ float s = Mathf.sqrt(-x[0] - y[1] + z[2] + 1.0f) * 2f;
+ float inv_s = 1f / s;
+ return new Quat(
+ (x[2] + z[0]) * inv_s,
+ (y[2] + z[1]) * inv_s,
+ s * 0.25f,
+ (y[0] - x[1]) * inv_s
+ );
+ }
+ }
+
public Basis(Quat quat)
{
float s = 2.0f / quat.length_squared();
diff --git a/modules/mono/glue/cs_files/Color.cs b/modules/mono/glue/cs_files/Color.cs
index df88a46832..0a00f83d47 100644
--- a/modules/mono/glue/cs_files/Color.cs
+++ b/modules/mono/glue/cs_files/Color.cs
@@ -1,590 +1,590 @@
-using System;
-
-namespace Godot
-{
- public struct Color : IEquatable<Color>
- {
- public float r;
- public float g;
- public float b;
- public float a;
-
- public int r8
- {
- get
- {
- return (int)(r * 255.0f);
- }
- }
-
- public int g8
- {
- get
- {
- return (int)(g * 255.0f);
- }
- }
-
- public int b8
- {
- get
- {
- return (int)(b * 255.0f);
- }
- }
-
- public int a8
- {
- get
- {
- return (int)(a * 255.0f);
- }
- }
-
- public float h
- {
- get
- {
- float max = Mathf.max(r, Mathf.max(g, b));
- float min = Mathf.min(r, Mathf.min(g, b));
-
- float delta = max - min;
-
- if (delta == 0)
- return 0;
-
- float h;
-
- if (r == max)
- h = (g - b) / delta; // Between yellow & magenta
- else if (g == max)
- h = 2 + (b - r) / delta; // Between cyan & yellow
- else
- h = 4 + (r - g) / delta; // Between magenta & cyan
-
- h /= 6.0f;
-
- if (h < 0)
- h += 1.0f;
-
- return h;
- }
- set
- {
- this = from_hsv(value, s, v);
- }
- }
-
- public float s
- {
- get
- {
- float max = Mathf.max(r, Mathf.max(g, b));
- float min = Mathf.min(r, Mathf.min(g, b));
-
- float delta = max - min;
-
- return max != 0 ? delta / max : 0;
- }
- set
- {
- this = from_hsv(h, value, v);
- }
- }
-
- public float v
- {
- get
- {
- return Mathf.max(r, Mathf.max(g, b));
- }
- set
- {
- this = from_hsv(h, s, value);
- }
- }
-
- private static readonly Color black = new Color(0f, 0f, 0f, 1.0f);
-
- public Color Black
- {
- get
- {
- return black;
- }
- }
-
- public float this [int index]
- {
- get
- {
- switch (index)
- {
- case 0:
- return r;
- case 1:
- return g;
- case 2:
- return b;
- case 3:
- return a;
- default:
- throw new IndexOutOfRangeException();
- }
- }
- set
- {
- switch (index)
- {
- case 0:
- r = value;
- return;
- case 1:
- g = value;
- return;
- case 2:
- b = value;
- return;
- case 3:
- a = value;
- return;
- default:
- throw new IndexOutOfRangeException();
- }
- }
- }
-
- public static void to_hsv(Color color, out float hue, out float saturation, out float value)
- {
- int max = Mathf.max(color.r8, Mathf.max(color.g8, color.b8));
- int min = Mathf.min(color.r8, Mathf.min(color.g8, color.b8));
-
- float delta = max - min;
-
- if (delta == 0)
- {
- hue = 0;
- }
- else
- {
- if (color.r == max)
- hue = (color.g - color.b) / delta; // Between yellow & magenta
- else if (color.g == max)
- hue = 2 + (color.b - color.r) / delta; // Between cyan & yellow
- else
- hue = 4 + (color.r - color.g) / delta; // Between magenta & cyan
-
- hue /= 6.0f;
-
- if (hue < 0)
- hue += 1.0f;
- }
-
- saturation = (max == 0) ? 0 : 1f - (1f * min / max);
- value = max / 255f;
- }
-
- public static Color from_hsv(float hue, float saturation, float value, float alpha = 1.0f)
- {
- if (saturation == 0)
- {
- // acp_hromatic (grey)
- return new Color(value, value, value, alpha);
- }
-
- int i;
- float f, p, q, t;
-
- hue *= 6.0f;
- hue %= 6f;
- i = (int)hue;
-
- f = hue - i;
- p = value * (1 - saturation);
- q = value * (1 - saturation * f);
- t = value * (1 - saturation * (1 - f));
-
- switch (i)
- {
- case 0: // Red is the dominant color
- return new Color(value, t, p, alpha);
- case 1: // Green is the dominant color
- return new Color(q, value, p, alpha);
- case 2:
- return new Color(p, value, t, alpha);
- case 3: // Blue is the dominant color
- return new Color(p, q, value, alpha);
- case 4:
- return new Color(t, p, value, alpha);
- default: // (5) Red is the dominant color
- return new Color(value, p, q, alpha);
- }
- }
-
- public Color blend(Color over)
- {
- Color res;
-
- float sa = 1.0f - over.a;
- res.a = a * sa + over.a;
-
- if (res.a == 0)
- {
- return new Color(0, 0, 0, 0);
- }
- else
- {
- res.r = (r * a * sa + over.r * over.a) / res.a;
- res.g = (g * a * sa + over.g * over.a) / res.a;
- res.b = (b * a * sa + over.b * over.a) / res.a;
- }
-
- return res;
- }
-
- public Color contrasted()
- {
- return new Color(
- (r + 0.5f) % 1.0f,
- (g + 0.5f) % 1.0f,
- (b + 0.5f) % 1.0f
- );
- }
-
- public float gray()
- {
- return (r + g + b) / 3.0f;
- }
-
- public Color inverted()
- {
- return new Color(
- 1.0f - r,
- 1.0f - g,
- 1.0f - b
- );
- }
-
- public Color linear_interpolate(Color b, float t)
- {
- Color res = this;
-
- res.r += (t * (b.r - this.r));
- res.g += (t * (b.g - this.g));
- res.b += (t * (b.b - this.b));
- res.a += (t * (b.a - this.a));
-
- return res;
- }
-
- public int to_32()
- {
- int c = (byte)(a * 255);
- c <<= 8;
- c |= (byte)(r * 255);
- c <<= 8;
- c |= (byte)(g * 255);
- c <<= 8;
- c |= (byte)(b * 255);
-
- return c;
- }
-
- public int to_ARGB32()
- {
- int c = (byte)(a * 255);
- c <<= 8;
- c |= (byte)(r * 255);
- c <<= 8;
- c |= (byte)(g * 255);
- c <<= 8;
- c |= (byte)(b * 255);
-
- return c;
- }
-
- public string to_html(bool include_alpha = true)
- {
- String txt = string.Empty;
-
- txt += _to_hex(r);
- txt += _to_hex(g);
- txt += _to_hex(b);
-
- if (include_alpha)
- txt = _to_hex(a) + txt;
-
- return txt;
- }
-
- public Color(float r, float g, float b, float a = 1.0f)
- {
- this.r = r;
- this.g = g;
- this.b = b;
- this.a = a;
- }
-
- public Color(int rgba)
- {
- this.a = (rgba & 0xFF) / 255.0f;
- rgba >>= 8;
- this.b = (rgba & 0xFF) / 255.0f;
- rgba >>= 8;
- this.g = (rgba & 0xFF) / 255.0f;
- rgba >>= 8;
- this.r = (rgba & 0xFF) / 255.0f;
- }
-
- private static float _parse_col(string str, int ofs)
- {
- int ig = 0;
-
- for (int i = 0; i < 2; i++)
- {
- int c = str[i + ofs];
- int v = 0;
-
- if (c >= '0' && c <= '9')
- {
- v = c - '0';
- }
- else if (c >= 'a' && c <= 'f')
- {
- v = c - 'a';
- v += 10;
- }
- else if (c >= 'A' && c <= 'F')
- {
- v = c - 'A';
- v += 10;
- }
- else
- {
- return -1;
- }
-
- if (i == 0)
- ig += v * 16;
- else
- ig += v;
- }
-
- return ig;
- }
-
- private String _to_hex(float val)
- {
- int v = (int)Mathf.clamp(val * 255.0f, 0, 255);
-
- string ret = string.Empty;
-
- for (int i = 0; i < 2; i++)
- {
- char[] c = { (char)0, (char)0 };
- int lv = v & 0xF;
-
- if (lv < 10)
- c[0] = (char)('0' + lv);
- else
- c[0] = (char)('a' + lv - 10);
-
- v >>= 4;
- ret = c + ret;
- }
-
- return ret;
- }
-
- internal static bool html_is_valid(string color)
- {
- if (color.Length == 0)
- return false;
-
- if (color[0] == '#')
- color = color.Substring(1, color.Length - 1);
-
- bool alpha = false;
-
- if (color.Length == 8)
- alpha = true;
- else if (color.Length == 6)
- alpha = false;
- else
- return false;
-
- if (alpha)
- {
- if ((int)_parse_col(color, 0) < 0)
- return false;
- }
-
- int from = alpha ? 2 : 0;
-
- if ((int)_parse_col(color, from + 0) < 0)
- return false;
- if ((int)_parse_col(color, from + 2) < 0)
- return false;
- if ((int)_parse_col(color, from + 4) < 0)
- return false;
-
- return true;
- }
-
- public static Color Color8(byte r8, byte g8, byte b8, byte a8)
- {
- return new Color((float)r8 / 255f, (float)g8 / 255f, (float)b8 / 255f, (float)a8 / 255f);
- }
-
- public Color(string rgba)
- {
- if (rgba.Length == 0)
- {
- r = 0f;
- g = 0f;
- b = 0f;
- a = 1.0f;
- return;
- }
-
- if (rgba[0] == '#')
- rgba = rgba.Substring(1);
-
- bool alpha = false;
-
- if (rgba.Length == 8)
- {
- alpha = true;
- }
- else if (rgba.Length == 6)
- {
- alpha = false;
- }
- else
- {
- throw new ArgumentOutOfRangeException("Invalid color code. Length is " + rgba.Length + " but a length of 6 or 8 is expected: " + rgba);
- }
-
- if (alpha)
- {
- a = _parse_col(rgba, 0);
-
- if (a < 0)
- throw new ArgumentOutOfRangeException("Invalid color code. Alpha is " + a + " but zero or greater is expected: " + rgba);
- }
- else
- {
- a = 1.0f;
- }
-
- int from = alpha ? 2 : 0;
-
- r = _parse_col(rgba, from + 0);
-
- if (r < 0)
- throw new ArgumentOutOfRangeException("Invalid color code. Red is " + r + " but zero or greater is expected: " + rgba);
-
- g = _parse_col(rgba, from + 2);
-
- if (g < 0)
- throw new ArgumentOutOfRangeException("Invalid color code. Green is " + g + " but zero or greater is expected: " + rgba);
-
- b = _parse_col(rgba, from + 4);
-
- if (b < 0)
- throw new ArgumentOutOfRangeException("Invalid color code. Blue is " + b + " but zero or greater is expected: " + rgba);
- }
-
- public static bool operator ==(Color left, Color right)
- {
- return left.Equals(right);
- }
-
- public static bool operator !=(Color left, Color right)
- {
- return !left.Equals(right);
- }
-
- public static bool operator <(Color left, Color right)
- {
- if (left.r == right.r)
- {
- if (left.g == right.g)
- {
- if (left.b == right.b)
- return (left.a < right.a);
- else
- return (left.b < right.b);
- }
- else
- {
- return left.g < right.g;
- }
- }
-
- return left.r < right.r;
- }
-
- public static bool operator >(Color left, Color right)
- {
- if (left.r == right.r)
- {
- if (left.g == right.g)
- {
- if (left.b == right.b)
- return (left.a > right.a);
- else
- return (left.b > right.b);
- }
- else
- {
- return left.g > right.g;
- }
- }
-
- return left.r > right.r;
- }
-
- public override bool Equals(object obj)
- {
- if (obj is Color)
- {
- return Equals((Color)obj);
- }
-
- return false;
- }
-
- public bool Equals(Color other)
- {
- return r == other.r && g == other.g && b == other.b && a == other.a;
- }
-
- public override int GetHashCode()
- {
- return r.GetHashCode() ^ g.GetHashCode() ^ b.GetHashCode() ^ a.GetHashCode();
- }
-
- public override string ToString()
- {
- return String.Format("{0},{1},{2},{3}", new object[]
- {
- this.r.ToString(),
- this.g.ToString(),
- this.b.ToString(),
- this.a.ToString()
- });
- }
-
- public string ToString(string format)
- {
- return String.Format("{0},{1},{2},{3}", new object[]
- {
- this.r.ToString(format),
- this.g.ToString(format),
- this.b.ToString(format),
- this.a.ToString(format)
- });
- }
- }
-}
+using System;
+
+namespace Godot
+{
+ public struct Color : IEquatable<Color>
+ {
+ public float r;
+ public float g;
+ public float b;
+ public float a;
+
+ public int r8
+ {
+ get
+ {
+ return (int)(r * 255.0f);
+ }
+ }
+
+ public int g8
+ {
+ get
+ {
+ return (int)(g * 255.0f);
+ }
+ }
+
+ public int b8
+ {
+ get
+ {
+ return (int)(b * 255.0f);
+ }
+ }
+
+ public int a8
+ {
+ get
+ {
+ return (int)(a * 255.0f);
+ }
+ }
+
+ public float h
+ {
+ get
+ {
+ float max = Mathf.max(r, Mathf.max(g, b));
+ float min = Mathf.min(r, Mathf.min(g, b));
+
+ float delta = max - min;
+
+ if (delta == 0)
+ return 0;
+
+ float h;
+
+ if (r == max)
+ h = (g - b) / delta; // Between yellow & magenta
+ else if (g == max)
+ h = 2 + (b - r) / delta; // Between cyan & yellow
+ else
+ h = 4 + (r - g) / delta; // Between magenta & cyan
+
+ h /= 6.0f;
+
+ if (h < 0)
+ h += 1.0f;
+
+ return h;
+ }
+ set
+ {
+ this = from_hsv(value, s, v);
+ }
+ }
+
+ public float s
+ {
+ get
+ {
+ float max = Mathf.max(r, Mathf.max(g, b));
+ float min = Mathf.min(r, Mathf.min(g, b));
+
+ float delta = max - min;
+
+ return max != 0 ? delta / max : 0;
+ }
+ set
+ {
+ this = from_hsv(h, value, v);
+ }
+ }
+
+ public float v
+ {
+ get
+ {
+ return Mathf.max(r, Mathf.max(g, b));
+ }
+ set
+ {
+ this = from_hsv(h, s, value);
+ }
+ }
+
+ private static readonly Color black = new Color(0f, 0f, 0f, 1.0f);
+
+ public Color Black
+ {
+ get
+ {
+ return black;
+ }
+ }
+
+ public float this [int index]
+ {
+ get
+ {
+ switch (index)
+ {
+ case 0:
+ return r;
+ case 1:
+ return g;
+ case 2:
+ return b;
+ case 3:
+ return a;
+ default:
+ throw new IndexOutOfRangeException();
+ }
+ }
+ set
+ {
+ switch (index)
+ {
+ case 0:
+ r = value;
+ return;
+ case 1:
+ g = value;
+ return;
+ case 2:
+ b = value;
+ return;
+ case 3:
+ a = value;
+ return;
+ default:
+ throw new IndexOutOfRangeException();
+ }
+ }
+ }
+
+ public static void to_hsv(Color color, out float hue, out float saturation, out float value)
+ {
+ int max = Mathf.max(color.r8, Mathf.max(color.g8, color.b8));
+ int min = Mathf.min(color.r8, Mathf.min(color.g8, color.b8));
+
+ float delta = max - min;
+
+ if (delta == 0)
+ {
+ hue = 0;
+ }
+ else
+ {
+ if (color.r == max)
+ hue = (color.g - color.b) / delta; // Between yellow & magenta
+ else if (color.g == max)
+ hue = 2 + (color.b - color.r) / delta; // Between cyan & yellow
+ else
+ hue = 4 + (color.r - color.g) / delta; // Between magenta & cyan
+
+ hue /= 6.0f;
+
+ if (hue < 0)
+ hue += 1.0f;
+ }
+
+ saturation = (max == 0) ? 0 : 1f - (1f * min / max);
+ value = max / 255f;
+ }
+
+ public static Color from_hsv(float hue, float saturation, float value, float alpha = 1.0f)
+ {
+ if (saturation == 0)
+ {
+ // acp_hromatic (grey)
+ return new Color(value, value, value, alpha);
+ }
+
+ int i;
+ float f, p, q, t;
+
+ hue *= 6.0f;
+ hue %= 6f;
+ i = (int)hue;
+
+ f = hue - i;
+ p = value * (1 - saturation);
+ q = value * (1 - saturation * f);
+ t = value * (1 - saturation * (1 - f));
+
+ switch (i)
+ {
+ case 0: // Red is the dominant color
+ return new Color(value, t, p, alpha);
+ case 1: // Green is the dominant color
+ return new Color(q, value, p, alpha);
+ case 2:
+ return new Color(p, value, t, alpha);
+ case 3: // Blue is the dominant color
+ return new Color(p, q, value, alpha);
+ case 4:
+ return new Color(t, p, value, alpha);
+ default: // (5) Red is the dominant color
+ return new Color(value, p, q, alpha);
+ }
+ }
+
+ public Color blend(Color over)
+ {
+ Color res;
+
+ float sa = 1.0f - over.a;
+ res.a = a * sa + over.a;
+
+ if (res.a == 0)
+ {
+ return new Color(0, 0, 0, 0);
+ }
+ else
+ {
+ res.r = (r * a * sa + over.r * over.a) / res.a;
+ res.g = (g * a * sa + over.g * over.a) / res.a;
+ res.b = (b * a * sa + over.b * over.a) / res.a;
+ }
+
+ return res;
+ }
+
+ public Color contrasted()
+ {
+ return new Color(
+ (r + 0.5f) % 1.0f,
+ (g + 0.5f) % 1.0f,
+ (b + 0.5f) % 1.0f
+ );
+ }
+
+ public float gray()
+ {
+ return (r + g + b) / 3.0f;
+ }
+
+ public Color inverted()
+ {
+ return new Color(
+ 1.0f - r,
+ 1.0f - g,
+ 1.0f - b
+ );
+ }
+
+ public Color linear_interpolate(Color b, float t)
+ {
+ Color res = this;
+
+ res.r += (t * (b.r - this.r));
+ res.g += (t * (b.g - this.g));
+ res.b += (t * (b.b - this.b));
+ res.a += (t * (b.a - this.a));
+
+ return res;
+ }
+
+ public int to_32()
+ {
+ int c = (byte)(a * 255);
+ c <<= 8;
+ c |= (byte)(r * 255);
+ c <<= 8;
+ c |= (byte)(g * 255);
+ c <<= 8;
+ c |= (byte)(b * 255);
+
+ return c;
+ }
+
+ public int to_ARGB32()
+ {
+ int c = (byte)(a * 255);
+ c <<= 8;
+ c |= (byte)(r * 255);
+ c <<= 8;
+ c |= (byte)(g * 255);
+ c <<= 8;
+ c |= (byte)(b * 255);
+
+ return c;
+ }
+
+ public string to_html(bool include_alpha = true)
+ {
+ String txt = string.Empty;
+
+ txt += _to_hex(r);
+ txt += _to_hex(g);
+ txt += _to_hex(b);
+
+ if (include_alpha)
+ txt = _to_hex(a) + txt;
+
+ return txt;
+ }
+
+ public Color(float r, float g, float b, float a = 1.0f)
+ {
+ this.r = r;
+ this.g = g;
+ this.b = b;
+ this.a = a;
+ }
+
+ public Color(int rgba)
+ {
+ this.a = (rgba & 0xFF) / 255.0f;
+ rgba >>= 8;
+ this.b = (rgba & 0xFF) / 255.0f;
+ rgba >>= 8;
+ this.g = (rgba & 0xFF) / 255.0f;
+ rgba >>= 8;
+ this.r = (rgba & 0xFF) / 255.0f;
+ }
+
+ private static float _parse_col(string str, int ofs)
+ {
+ int ig = 0;
+
+ for (int i = 0; i < 2; i++)
+ {
+ int c = str[i + ofs];
+ int v = 0;
+
+ if (c >= '0' && c <= '9')
+ {
+ v = c - '0';
+ }
+ else if (c >= 'a' && c <= 'f')
+ {
+ v = c - 'a';
+ v += 10;
+ }
+ else if (c >= 'A' && c <= 'F')
+ {
+ v = c - 'A';
+ v += 10;
+ }
+ else
+ {
+ return -1;
+ }
+
+ if (i == 0)
+ ig += v * 16;
+ else
+ ig += v;
+ }
+
+ return ig;
+ }
+
+ private String _to_hex(float val)
+ {
+ int v = (int)Mathf.clamp(val * 255.0f, 0, 255);
+
+ string ret = string.Empty;
+
+ for (int i = 0; i < 2; i++)
+ {
+ char[] c = { (char)0, (char)0 };
+ int lv = v & 0xF;
+
+ if (lv < 10)
+ c[0] = (char)('0' + lv);
+ else
+ c[0] = (char)('a' + lv - 10);
+
+ v >>= 4;
+ ret = c + ret;
+ }
+
+ return ret;
+ }
+
+ internal static bool html_is_valid(string color)
+ {
+ if (color.Length == 0)
+ return false;
+
+ if (color[0] == '#')
+ color = color.Substring(1, color.Length - 1);
+
+ bool alpha = false;
+
+ if (color.Length == 8)
+ alpha = true;
+ else if (color.Length == 6)
+ alpha = false;
+ else
+ return false;
+
+ if (alpha)
+ {
+ if ((int)_parse_col(color, 0) < 0)
+ return false;
+ }
+
+ int from = alpha ? 2 : 0;
+
+ if ((int)_parse_col(color, from + 0) < 0)
+ return false;
+ if ((int)_parse_col(color, from + 2) < 0)
+ return false;
+ if ((int)_parse_col(color, from + 4) < 0)
+ return false;
+
+ return true;
+ }
+
+ public static Color Color8(byte r8, byte g8, byte b8, byte a8)
+ {
+ return new Color((float)r8 / 255f, (float)g8 / 255f, (float)b8 / 255f, (float)a8 / 255f);
+ }
+
+ public Color(string rgba)
+ {
+ if (rgba.Length == 0)
+ {
+ r = 0f;
+ g = 0f;
+ b = 0f;
+ a = 1.0f;
+ return;
+ }
+
+ if (rgba[0] == '#')
+ rgba = rgba.Substring(1);
+
+ bool alpha = false;
+
+ if (rgba.Length == 8)
+ {
+ alpha = true;
+ }
+ else if (rgba.Length == 6)
+ {
+ alpha = false;
+ }
+ else
+ {
+ throw new ArgumentOutOfRangeException("Invalid color code. Length is " + rgba.Length + " but a length of 6 or 8 is expected: " + rgba);
+ }
+
+ if (alpha)
+ {
+ a = _parse_col(rgba, 0);
+
+ if (a < 0)
+ throw new ArgumentOutOfRangeException("Invalid color code. Alpha is " + a + " but zero or greater is expected: " + rgba);
+ }
+ else
+ {
+ a = 1.0f;
+ }
+
+ int from = alpha ? 2 : 0;
+
+ r = _parse_col(rgba, from + 0);
+
+ if (r < 0)
+ throw new ArgumentOutOfRangeException("Invalid color code. Red is " + r + " but zero or greater is expected: " + rgba);
+
+ g = _parse_col(rgba, from + 2);
+
+ if (g < 0)
+ throw new ArgumentOutOfRangeException("Invalid color code. Green is " + g + " but zero or greater is expected: " + rgba);
+
+ b = _parse_col(rgba, from + 4);
+
+ if (b < 0)
+ throw new ArgumentOutOfRangeException("Invalid color code. Blue is " + b + " but zero or greater is expected: " + rgba);
+ }
+
+ public static bool operator ==(Color left, Color right)
+ {
+ return left.Equals(right);
+ }
+
+ public static bool operator !=(Color left, Color right)
+ {
+ return !left.Equals(right);
+ }
+
+ public static bool operator <(Color left, Color right)
+ {
+ if (left.r == right.r)
+ {
+ if (left.g == right.g)
+ {
+ if (left.b == right.b)
+ return (left.a < right.a);
+ else
+ return (left.b < right.b);
+ }
+ else
+ {
+ return left.g < right.g;
+ }
+ }
+
+ return left.r < right.r;
+ }
+
+ public static bool operator >(Color left, Color right)
+ {
+ if (left.r == right.r)
+ {
+ if (left.g == right.g)
+ {
+ if (left.b == right.b)
+ return (left.a > right.a);
+ else
+ return (left.b > right.b);
+ }
+ else
+ {
+ return left.g > right.g;
+ }
+ }
+
+ return left.r > right.r;
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (obj is Color)
+ {
+ return Equals((Color)obj);
+ }
+
+ return false;
+ }
+
+ public bool Equals(Color other)
+ {
+ return r == other.r && g == other.g && b == other.b && a == other.a;
+ }
+
+ public override int GetHashCode()
+ {
+ return r.GetHashCode() ^ g.GetHashCode() ^ b.GetHashCode() ^ a.GetHashCode();
+ }
+
+ public override string ToString()
+ {
+ return String.Format("{0},{1},{2},{3}", new object[]
+ {
+ this.r.ToString(),
+ this.g.ToString(),
+ this.b.ToString(),
+ this.a.ToString()
+ });
+ }
+
+ public string ToString(string format)
+ {
+ return String.Format("{0},{1},{2},{3}", new object[]
+ {
+ this.r.ToString(format),
+ this.g.ToString(format),
+ this.b.ToString(format),
+ this.a.ToString(format)
+ });
+ }
+ }
+}
diff --git a/modules/mono/glue/cs_files/ExportAttribute.cs b/modules/mono/glue/cs_files/ExportAttribute.cs
index af3f603d6d..dce9cc59a0 100644
--- a/modules/mono/glue/cs_files/ExportAttribute.cs
+++ b/modules/mono/glue/cs_files/ExportAttribute.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
namespace Godot
{
@@ -7,13 +7,11 @@ namespace Godot
{
private int hint;
private string hint_string;
- private int usage;
- public ExportAttribute(int hint = GD.PROPERTY_HINT_NONE, string hint_string = "", int usage = GD.PROPERTY_USAGE_DEFAULT)
+ public ExportAttribute(int hint = GD.PROPERTY_HINT_NONE, string hint_string = "")
{
this.hint = hint;
this.hint_string = hint_string;
- this.usage = usage;
}
}
}
diff --git a/modules/mono/glue/cs_files/MarshalUtils.cs b/modules/mono/glue/cs_files/MarshalUtils.cs
index 5d40111339..2bdfb95c51 100644
--- a/modules/mono/glue/cs_files/MarshalUtils.cs
+++ b/modules/mono/glue/cs_files/MarshalUtils.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
namespace Godot
diff --git a/modules/mono/glue/cs_files/Mathf.cs b/modules/mono/glue/cs_files/Mathf.cs
index cb0eb1acdd..37e6e5bbe3 100644
--- a/modules/mono/glue/cs_files/Mathf.cs
+++ b/modules/mono/glue/cs_files/Mathf.cs
@@ -35,6 +35,11 @@ namespace Godot
return (float)Math.Atan2(x, y);
}
+ public static Vector2 cartesian2polar(float x, float y)
+ {
+ return new Vector2(sqrt(x * x + y * y), atan2(y, x));
+ }
+
public static float ceil(float s)
{
return (float)Math.Ceiling(s);
@@ -176,6 +181,11 @@ namespace Godot
return val;
}
+ public static Vector2 polar2cartesian(float r, float th)
+ {
+ return new Vector2(r * cos(th), r * sin(th));
+ }
+
public static float pow(float x, float y)
{
return (float)Math.Pow(x, y);
diff --git a/modules/mono/glue/cs_files/Plane.cs b/modules/mono/glue/cs_files/Plane.cs
index ada6e465ac..37f70aca1e 100644
--- a/modules/mono/glue/cs_files/Plane.cs
+++ b/modules/mono/glue/cs_files/Plane.cs
@@ -1,209 +1,209 @@
-using System;
-
-namespace Godot
-{
- public struct Plane : IEquatable<Plane>
- {
- Vector3 normal;
-
- public float x
- {
- get
- {
- return normal.x;
- }
- set
- {
- normal.x = value;
- }
- }
-
- public float y
- {
- get
- {
- return normal.y;
- }
- set
- {
- normal.y = value;
- }
- }
-
- public float z
- {
- get
- {
- return normal.z;
- }
- set
- {
- normal.z = value;
- }
- }
-
- float d;
-
- public Vector3 Center
- {
- get
- {
- return normal * d;
- }
- }
-
- public float distance_to(Vector3 point)
- {
- return normal.dot(point) - d;
- }
-
- public Vector3 get_any_point()
- {
- return normal * d;
- }
-
- public bool has_point(Vector3 point, float epsilon = Mathf.Epsilon)
- {
- float dist = normal.dot(point) - d;
- return Mathf.abs(dist) <= epsilon;
- }
-
- public Vector3 intersect_3(Plane b, Plane c)
- {
- float denom = normal.cross(b.normal).dot(c.normal);
-
- if (Mathf.abs(denom) <= Mathf.Epsilon)
- return new Vector3();
-
- Vector3 result = (b.normal.cross(c.normal) * this.d) +
- (c.normal.cross(normal) * b.d) +
- (normal.cross(b.normal) * c.d);
-
- return result / denom;
- }
-
- public Vector3 intersect_ray(Vector3 from, Vector3 dir)
- {
- float den = normal.dot(dir);
-
- if (Mathf.abs(den) <= Mathf.Epsilon)
- return new Vector3();
-
- float dist = (normal.dot(from) - d) / den;
-
- // This is a ray, before the emiting pos (from) does not exist
- if (dist > Mathf.Epsilon)
- return new Vector3();
-
- return from + dir * -dist;
- }
-
- public Vector3 intersect_segment(Vector3 begin, Vector3 end)
- {
- Vector3 segment = begin - end;
- float den = normal.dot(segment);
-
- if (Mathf.abs(den) <= Mathf.Epsilon)
- return new Vector3();
-
- float dist = (normal.dot(begin) - d) / den;
-
- if (dist < -Mathf.Epsilon || dist > (1.0f + Mathf.Epsilon))
- return new Vector3();
-
- return begin + segment * -dist;
- }
-
- public bool is_point_over(Vector3 point)
- {
- return normal.dot(point) > d;
- }
-
- public Plane normalized()
- {
- float len = normal.length();
-
- if (len == 0)
- return new Plane(0, 0, 0, 0);
-
- return new Plane(normal / len, d / len);
- }
-
- public Vector3 project(Vector3 point)
- {
- return point - normal * distance_to(point);
- }
-
- public Plane(float a, float b, float c, float d)
- {
- normal = new Vector3(a, b, c);
- this.d = d;
- }
-
- public Plane(Vector3 normal, float d)
- {
- this.normal = normal;
- this.d = d;
- }
-
- public Plane(Vector3 v1, Vector3 v2, Vector3 v3)
- {
- normal = (v1 - v3).cross(v1 - v2);
- normal.normalize();
- d = normal.dot(v1);
- }
-
- public static Plane operator -(Plane plane)
- {
- return new Plane(-plane.normal, -plane.d);
- }
-
- public static bool operator ==(Plane left, Plane right)
- {
- return left.Equals(right);
- }
-
- public static bool operator !=(Plane left, Plane right)
- {
- return !left.Equals(right);
- }
-
- public override bool Equals(object obj)
- {
- if (obj is Plane)
- {
- return Equals((Plane)obj);
- }
-
- return false;
- }
-
- public bool Equals(Plane other)
- {
- return normal == other.normal && d == other.d;
- }
-
- public override int GetHashCode()
- {
- return normal.GetHashCode() ^ d.GetHashCode();
- }
-
- public override string ToString()
- {
- return String.Format("({0}, {1})", new object[]
- {
- this.normal.ToString(),
- this.d.ToString()
- });
- }
-
- public string ToString(string format)
- {
- return String.Format("({0}, {1})", new object[]
- {
- this.normal.ToString(format),
- this.d.ToString(format)
- });
- }
- }
-}
+using System;
+
+namespace Godot
+{
+ public struct Plane : IEquatable<Plane>
+ {
+ Vector3 normal;
+
+ public float x
+ {
+ get
+ {
+ return normal.x;
+ }
+ set
+ {
+ normal.x = value;
+ }
+ }
+
+ public float y
+ {
+ get
+ {
+ return normal.y;
+ }
+ set
+ {
+ normal.y = value;
+ }
+ }
+
+ public float z
+ {
+ get
+ {
+ return normal.z;
+ }
+ set
+ {
+ normal.z = value;
+ }
+ }
+
+ float d;
+
+ public Vector3 Center
+ {
+ get
+ {
+ return normal * d;
+ }
+ }
+
+ public float distance_to(Vector3 point)
+ {
+ return normal.dot(point) - d;
+ }
+
+ public Vector3 get_any_point()
+ {
+ return normal * d;
+ }
+
+ public bool has_point(Vector3 point, float epsilon = Mathf.Epsilon)
+ {
+ float dist = normal.dot(point) - d;
+ return Mathf.abs(dist) <= epsilon;
+ }
+
+ public Vector3 intersect_3(Plane b, Plane c)
+ {
+ float denom = normal.cross(b.normal).dot(c.normal);
+
+ if (Mathf.abs(denom) <= Mathf.Epsilon)
+ return new Vector3();
+
+ Vector3 result = (b.normal.cross(c.normal) * this.d) +
+ (c.normal.cross(normal) * b.d) +
+ (normal.cross(b.normal) * c.d);
+
+ return result / denom;
+ }
+
+ public Vector3 intersect_ray(Vector3 from, Vector3 dir)
+ {
+ float den = normal.dot(dir);
+
+ if (Mathf.abs(den) <= Mathf.Epsilon)
+ return new Vector3();
+
+ float dist = (normal.dot(from) - d) / den;
+
+ // This is a ray, before the emiting pos (from) does not exist
+ if (dist > Mathf.Epsilon)
+ return new Vector3();
+
+ return from + dir * -dist;
+ }
+
+ public Vector3 intersect_segment(Vector3 begin, Vector3 end)
+ {
+ Vector3 segment = begin - end;
+ float den = normal.dot(segment);
+
+ if (Mathf.abs(den) <= Mathf.Epsilon)
+ return new Vector3();
+
+ float dist = (normal.dot(begin) - d) / den;
+
+ if (dist < -Mathf.Epsilon || dist > (1.0f + Mathf.Epsilon))
+ return new Vector3();
+
+ return begin + segment * -dist;
+ }
+
+ public bool is_point_over(Vector3 point)
+ {
+ return normal.dot(point) > d;
+ }
+
+ public Plane normalized()
+ {
+ float len = normal.length();
+
+ if (len == 0)
+ return new Plane(0, 0, 0, 0);
+
+ return new Plane(normal / len, d / len);
+ }
+
+ public Vector3 project(Vector3 point)
+ {
+ return point - normal * distance_to(point);
+ }
+
+ public Plane(float a, float b, float c, float d)
+ {
+ normal = new Vector3(a, b, c);
+ this.d = d;
+ }
+
+ public Plane(Vector3 normal, float d)
+ {
+ this.normal = normal;
+ this.d = d;
+ }
+
+ public Plane(Vector3 v1, Vector3 v2, Vector3 v3)
+ {
+ normal = (v1 - v3).cross(v1 - v2);
+ normal.normalize();
+ d = normal.dot(v1);
+ }
+
+ public static Plane operator -(Plane plane)
+ {
+ return new Plane(-plane.normal, -plane.d);
+ }
+
+ public static bool operator ==(Plane left, Plane right)
+ {
+ return left.Equals(right);
+ }
+
+ public static bool operator !=(Plane left, Plane right)
+ {
+ return !left.Equals(right);
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (obj is Plane)
+ {
+ return Equals((Plane)obj);
+ }
+
+ return false;
+ }
+
+ public bool Equals(Plane other)
+ {
+ return normal == other.normal && d == other.d;
+ }
+
+ public override int GetHashCode()
+ {
+ return normal.GetHashCode() ^ d.GetHashCode();
+ }
+
+ public override string ToString()
+ {
+ return String.Format("({0}, {1})", new object[]
+ {
+ this.normal.ToString(),
+ this.d.ToString()
+ });
+ }
+
+ public string ToString(string format)
+ {
+ return String.Format("({0}, {1})", new object[]
+ {
+ this.normal.ToString(format),
+ this.d.ToString(format)
+ });
+ }
+ }
+}
diff --git a/modules/mono/glue/cs_files/Quat.cs b/modules/mono/glue/cs_files/Quat.cs
index 6345239f47..9b4b7fb297 100644
--- a/modules/mono/glue/cs_files/Quat.cs
+++ b/modules/mono/glue/cs_files/Quat.cs
@@ -201,12 +201,12 @@ namespace Godot
}
else
{
- float s = Mathf.sin(-angle * 0.5f) / d;
+ float s = Mathf.sin(angle * 0.5f) / d;
x = axis.x * s;
y = axis.y * s;
z = axis.z * s;
- w = Mathf.cos(-angle * 0.5f);
+ w = Mathf.cos(angle * 0.5f);
}
}
diff --git a/modules/mono/glue/cs_files/ToolAttribute.cs b/modules/mono/glue/cs_files/ToolAttribute.cs
index 0275982c7f..d8601b5b32 100644
--- a/modules/mono/glue/cs_files/ToolAttribute.cs
+++ b/modules/mono/glue/cs_files/ToolAttribute.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
namespace Godot
{
diff --git a/modules/mono/glue/cs_files/Transform.cs b/modules/mono/glue/cs_files/Transform.cs
index 2010f0b3af..74271e758b 100644
--- a/modules/mono/glue/cs_files/Transform.cs
+++ b/modules/mono/glue/cs_files/Transform.cs
@@ -35,7 +35,7 @@ namespace Godot
public Transform rotated(Vector3 axis, float phi)
{
- return this * new Transform(new Basis(axis, phi), new Vector3());
+ return new Transform(new Basis(axis, phi), new Vector3()) * this;
}
public Transform scaled(Vector3 scale)
@@ -104,6 +104,12 @@ namespace Godot
this.origin = origin;
}
+ public Transform(Quat quat, Vector3 origin)
+ {
+ this.basis = new Basis(quat);
+ this.origin = origin;
+ }
+
public Transform(Basis basis, Vector3 origin)
{
this.basis = basis;
diff --git a/modules/mono/glue/glue_header.h b/modules/mono/glue/glue_header.h
index 0751a0160f..75a4eb2b40 100644
--- a/modules/mono/glue/glue_header.h
+++ b/modules/mono/glue/glue_header.h
@@ -35,10 +35,10 @@
#include "bind/core_bind.h"
#include "class_db.h"
+#include "engine.h"
#include "io/marshalls.h"
#include "object.h"
#include "os/os.h"
-#include "project_settings.h"
#include "reference.h"
#include "variant_parser.h"
diff --git a/modules/mono/godotsharp_dirs.cpp b/modules/mono/godotsharp_dirs.cpp
index 0a2010e99d..a0c2508b0d 100644
--- a/modules/mono/godotsharp_dirs.cpp
+++ b/modules/mono/godotsharp_dirs.cpp
@@ -33,6 +33,7 @@
#ifdef TOOLS_ENABLED
#include "editor/editor_settings.h"
+#include "os/dir_access.h"
#include "project_settings.h"
#include "version.h"
#endif
@@ -56,22 +57,24 @@ String _get_expected_build_config() {
String _get_mono_user_dir() {
#ifdef TOOLS_ENABLED
if (EditorSettings::get_singleton()) {
- return EditorSettings::get_singleton()->get_settings_path().plus_file("mono");
+ return EditorSettings::get_singleton()->get_data_dir().plus_file("mono");
} else {
String settings_path;
- if (OS::get_singleton()->has_environment("APPDATA")) {
- String app_data = OS::get_singleton()->get_environment("APPDATA").replace("\\", "/");
- settings_path = app_data.plus_file(String(_MKSTR(VERSION_SHORT_NAME)).capitalize());
- } else if (OS::get_singleton()->has_environment("HOME")) {
- String home = OS::get_singleton()->get_environment("HOME");
- settings_path = home.plus_file("." + String(_MKSTR(VERSION_SHORT_NAME)).to_lower());
+ String exe_dir = OS::get_singleton()->get_executable_path().get_base_dir();
+ DirAccessRef d = DirAccess::create_for_path(exe_dir);
+
+ if (d->file_exists("._sc_") || d->file_exists("_sc_")) {
+ // contain yourself
+ settings_path = exe_dir.plus_file("editor_data");
+ } else {
+ settings_path = OS::get_singleton()->get_data_path().plus_file(OS::get_singleton()->get_godot_dir_name());
}
return settings_path.plus_file("mono");
}
#else
- return OS::get_singleton()->get_data_dir().plus_file("mono");
+ return OS::get_singleton()->get_user_data_dir().plus_file("mono");
#endif
}
@@ -113,7 +116,14 @@ private:
#ifdef TOOLS_ENABLED
mono_solutions_dir = mono_user_dir.plus_file("solutions");
build_logs_dir = mono_user_dir.plus_file("build_logs");
- String base_path = String("res://") + ProjectSettings::get_singleton()->get("application/config/name");
+
+ String name = ProjectSettings::get_singleton()->get("application/config/name");
+ if (name.empty()) {
+ name = "UnnamedProject";
+ }
+
+ String base_path = String("res://") + name;
+
sln_filepath = ProjectSettings::get_singleton()->globalize_path(base_path + ".sln");
csproj_filepath = ProjectSettings::get_singleton()->globalize_path(base_path + ".csproj");
#endif
diff --git a/modules/mono/mono_gc_handle.cpp b/modules/mono/mono_gc_handle.cpp
index d3ad968135..e10e06df0e 100644
--- a/modules/mono/mono_gc_handle.cpp
+++ b/modules/mono/mono_gc_handle.cpp
@@ -59,6 +59,10 @@ Ref<MonoGCHandle> MonoGCHandle::create_weak(MonoObject *p_object) {
void MonoGCHandle::release() {
+#ifdef DEBUG_ENABLED
+ CRASH_COND(GDMono::get_singleton() == NULL);
+#endif
+
if (!released && GDMono::get_singleton()->is_runtime_initialized()) {
mono_gchandle_free(handle);
released = true;
diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp
index 2c88832998..c997b0f000 100644
--- a/modules/mono/mono_gd/gd_mono.cpp
+++ b/modules/mono/mono_gd/gd_mono.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "gd_mono.h"
+#include <mono/metadata/exception.h>
#include <mono/metadata/mono-config.h>
#include <mono/metadata/mono-debug.h>
#include <mono/metadata/mono-gc.h>
@@ -47,6 +48,15 @@
#include "../editor/godotsharp_editor.h"
#endif
+void gdmono_unhandled_exception_hook(MonoObject *exc, void *user_data) {
+
+ (void)user_data; // UNUSED
+
+ ERR_PRINT(GDMonoUtils::get_exception_name_and_message(exc).utf8());
+ mono_print_unhandled_exception(exc);
+ abort();
+}
+
#ifdef MONO_PRINT_HANDLER_ENABLED
void gdmono_MonoPrintCallback(const char *string, mono_bool is_stdout) {
@@ -132,7 +142,7 @@ void GDMono::initialize() {
ERR_FAIL_NULL(Engine::get_singleton());
- OS::get_singleton()->print("Initializing mono...\n");
+ OS::get_singleton()->print("Mono: Initializing module...\n");
#ifdef DEBUG_METHODS_ENABLED
_initialize_and_check_api_hashes();
@@ -214,7 +224,9 @@ void GDMono::initialize() {
// The following assemblies are not required at initialization
_load_all_script_assemblies();
- OS::get_singleton()->print("Mono: EVERYTHING OK\n");
+ mono_install_unhandled_exception_hook(gdmono_unhandled_exception_hook, NULL);
+
+ OS::get_singleton()->print("Mono: ALL IS GOOD\n");
}
#ifndef MONO_GLUE_DISABLED
@@ -285,7 +297,8 @@ bool GDMono::_load_assembly(const String &p_name, GDMonoAssembly **r_assembly) {
MonoAssembly *assembly = mono_assembly_load_full(aname, NULL, &status, false);
mono_assembly_name_free(aname);
- ERR_FAIL_NULL_V(assembly, false);
+ if (!assembly)
+ return false;
uint32_t domain_id = mono_domain_get_id(mono_domain_get());
@@ -356,9 +369,12 @@ bool GDMono::_load_project_assembly() {
if (project_assembly)
return true;
- String project_assembly_name = ProjectSettings::get_singleton()->get("application/config/name");
+ String name = ProjectSettings::get_singleton()->get("application/config/name");
+ if (name.empty()) {
+ name = "UnnamedProject";
+ }
- bool success = _load_assembly(project_assembly_name, &project_assembly);
+ bool success = _load_assembly(name, &project_assembly);
if (success)
mono_assembly_set_main(project_assembly->get_assembly());
@@ -609,6 +625,8 @@ GDMono::~GDMono() {
if (gdmono_log)
memdelete(gdmono_log);
+
+ singleton = NULL;
}
_GodotSharp *_GodotSharp::singleton = NULL;
@@ -687,7 +705,7 @@ bool _GodotSharp::is_domain_loaded() {
void _GodotSharp::queue_dispose(Object *p_object) {
- if (Thread::get_main_id() == Thread::get_caller_id() && !GDMono::get_singleton()->is_finalizing_scripts_domain()) {
+ if (GDMonoUtils::is_main_thread() && !GDMono::get_singleton()->is_finalizing_scripts_domain()) {
_dispose_object(p_object);
} else {
#ifndef NO_THREADS
@@ -704,7 +722,7 @@ void _GodotSharp::queue_dispose(Object *p_object) {
void _GodotSharp::queue_dispose(NodePath *p_node_path) {
- if (Thread::get_main_id() == Thread::get_caller_id() && !GDMono::get_singleton()->is_finalizing_scripts_domain()) {
+ if (GDMonoUtils::is_main_thread() && !GDMono::get_singleton()->is_finalizing_scripts_domain()) {
memdelete(p_node_path);
} else {
#ifndef NO_THREADS
@@ -721,7 +739,7 @@ void _GodotSharp::queue_dispose(NodePath *p_node_path) {
void _GodotSharp::queue_dispose(RID *p_rid) {
- if (Thread::get_main_id() == Thread::get_caller_id() && !GDMono::get_singleton()->is_finalizing_scripts_domain()) {
+ if (GDMonoUtils::is_main_thread() && !GDMono::get_singleton()->is_finalizing_scripts_domain()) {
memdelete(p_rid);
} else {
#ifndef NO_THREADS
diff --git a/modules/mono/mono_gd/gd_mono_assembly.cpp b/modules/mono/mono_gd/gd_mono_assembly.cpp
index a623b34b68..7dc7043eec 100644
--- a/modules/mono/mono_gd/gd_mono_assembly.cpp
+++ b/modules/mono/mono_gd/gd_mono_assembly.cpp
@@ -52,12 +52,12 @@ MonoAssembly *GDMonoAssembly::_search_hook(MonoAssemblyName *aname, void *user_d
if (no_search)
return NULL;
- no_search = true; // Avoid the recursion madness
-
GDMonoAssembly **loaded_asm = GDMono::get_singleton()->get_loaded_assembly(has_extension ? name.get_basename() : name);
if (loaded_asm)
return (*loaded_asm)->get_assembly();
+ no_search = true; // Avoid the recursion madness
+
String path;
MonoAssembly *res = NULL;
@@ -95,7 +95,9 @@ MonoAssembly *GDMonoAssembly::_preload_hook(MonoAssemblyName *aname, char **asse
(void)user_data; // UNUSED
if (search_dirs.empty()) {
+#ifdef TOOLS_DOMAIN
search_dirs.push_back(GodotSharpDirs::get_res_temp_assemblies_dir());
+#endif
search_dirs.push_back(GodotSharpDirs::get_res_assemblies_dir());
search_dirs.push_back(OS::get_singleton()->get_resource_dir());
search_dirs.push_back(OS::get_singleton()->get_executable_path().get_base_dir());
@@ -105,10 +107,11 @@ MonoAssembly *GDMonoAssembly::_preload_hook(MonoAssemblyName *aname, char **asse
search_dirs.push_back(String(rootdir).plus_file("mono").plus_file("4.5"));
}
- while (assemblies_path) {
- if (*assemblies_path)
+ if (assemblies_path) {
+ while (*assemblies_path) {
search_dirs.push_back(*assemblies_path);
- ++assemblies_path;
+ ++assemblies_path;
+ }
}
}
diff --git a/modules/mono/mono_gd/gd_mono_class.cpp b/modules/mono/mono_gd/gd_mono_class.cpp
index 0134ace5d7..77ba0ee90e 100644
--- a/modules/mono/mono_gd/gd_mono_class.cpp
+++ b/modules/mono/mono_gd/gd_mono_class.cpp
@@ -43,6 +43,14 @@ bool GDMonoClass::is_assignable_from(GDMonoClass *p_from) const {
return mono_class_is_assignable_from(mono_class, p_from->mono_class);
}
+String GDMonoClass::get_full_name() const {
+
+ String res = namespace_name;
+ if (res.length())
+ res += ".";
+ return res + class_name;
+}
+
GDMonoClass *GDMonoClass::get_parent_class() {
if (assembly) {
@@ -56,6 +64,30 @@ GDMonoClass *GDMonoClass::get_parent_class() {
return NULL;
}
+#ifdef TOOLS_ENABLED
+Vector<MonoClassField *> GDMonoClass::get_enum_fields() {
+
+ bool class_is_enum = mono_class_is_enum(mono_class);
+ ERR_FAIL_COND_V(!class_is_enum, Vector<MonoClassField *>());
+
+ Vector<MonoClassField *> enum_fields;
+
+ void *iter = NULL;
+ MonoClassField *raw_field = NULL;
+ while ((raw_field = mono_class_get_fields(get_raw(), &iter)) != NULL) {
+ uint32_t field_flags = mono_field_get_flags(raw_field);
+
+ // Enums have an instance field named value__ which holds the value of the enum.
+ // Enum constants are static, so we will use this to ignore the value__ field.
+ if (field_flags & MONO_FIELD_ATTR_PUBLIC && field_flags & MONO_FIELD_ATTR_STATIC) {
+ enum_fields.push_back(raw_field);
+ }
+ }
+
+ return enum_fields;
+}
+#endif
+
bool GDMonoClass::has_method(const StringName &p_name) {
return get_method(p_name) != NULL;
diff --git a/modules/mono/mono_gd/gd_mono_class.h b/modules/mono/mono_gd/gd_mono_class.h
index 1e72553879..ef1ca425a7 100644
--- a/modules/mono/mono_gd/gd_mono_class.h
+++ b/modules/mono/mono_gd/gd_mono_class.h
@@ -98,8 +98,14 @@ public:
_FORCE_INLINE_ MonoClass *get_raw() const { return mono_class; }
_FORCE_INLINE_ const GDMonoAssembly *get_assembly() const { return assembly; }
+ String get_full_name() const;
+
GDMonoClass *get_parent_class();
+#ifdef TOOLS_ENABLED
+ Vector<MonoClassField *> get_enum_fields();
+#endif
+
bool has_method(const StringName &p_name);
bool has_attribute(GDMonoClass *p_attr_class);
diff --git a/modules/mono/mono_gd/gd_mono_field.cpp b/modules/mono/mono_gd/gd_mono_field.cpp
index 0c64380e31..eb34f9dd3f 100644
--- a/modules/mono/mono_gd/gd_mono_field.cpp
+++ b/modules/mono/mono_gd/gd_mono_field.cpp
@@ -41,7 +41,7 @@ void GDMonoField::set_value_raw(MonoObject *p_object, void *p_ptr) {
void GDMonoField::set_value(MonoObject *p_object, const Variant &p_value) {
#define SET_FROM_STRUCT_AND_BREAK(m_type) \
{ \
- const m_type &val = p_value.operator m_type(); \
+ const m_type &val = p_value.operator ::m_type(); \
MARSHALLED_OUT(m_type, val, raw); \
mono_field_set_value(p_object, mono_field, raw); \
break; \
@@ -51,6 +51,7 @@ void GDMonoField::set_value(MonoObject *p_object, const Variant &p_value) {
{ \
m_type val = p_value.operator m_type(); \
mono_field_set_value(p_object, mono_field, &val); \
+ break; \
}
#define SET_FROM_ARRAY_AND_BREAK(m_type) \
@@ -128,8 +129,8 @@ void GDMonoField::set_value(MonoObject *p_object, const Variant &p_value) {
if (tclass == CACHED_CLASS(Transform))
SET_FROM_STRUCT_AND_BREAK(Transform);
- if (tclass == CACHED_CLASS(Rect3))
- SET_FROM_STRUCT_AND_BREAK(Rect3);
+ if (tclass == CACHED_CLASS(AABB))
+ SET_FROM_STRUCT_AND_BREAK(AABB);
if (tclass == CACHED_CLASS(Color))
SET_FROM_STRUCT_AND_BREAK(Color);
@@ -137,6 +138,9 @@ void GDMonoField::set_value(MonoObject *p_object, const Variant &p_value) {
if (tclass == CACHED_CLASS(Plane))
SET_FROM_STRUCT_AND_BREAK(Plane);
+ if (mono_class_is_enum(tclass->get_raw()))
+ SET_FROM_PRIMITIVE(signed int);
+
ERR_EXPLAIN(String() + "Attempted to set the value of a field of unmarshallable type: " + tclass->get_name());
ERR_FAIL();
} break;
@@ -179,19 +183,19 @@ void GDMonoField::set_value(MonoObject *p_object, const Variant &p_value) {
// GodotObject
if (CACHED_CLASS(GodotObject)->is_assignable_from(type_class)) {
MonoObject *managed = GDMonoUtils::unmanaged_get_managed(p_value.operator Object *());
- mono_field_set_value(p_object, mono_field, &managed);
+ mono_field_set_value(p_object, mono_field, managed);
break;
}
if (CACHED_CLASS(NodePath) == type_class) {
MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator NodePath());
- mono_field_set_value(p_object, mono_field, &managed);
+ mono_field_set_value(p_object, mono_field, managed);
break;
}
if (CACHED_CLASS(RID) == type_class) {
MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator RID());
- mono_field_set_value(p_object, mono_field, &managed);
+ mono_field_set_value(p_object, mono_field, managed);
break;
}
@@ -200,8 +204,6 @@ void GDMonoField::set_value(MonoObject *p_object, const Variant &p_value) {
} break;
case MONO_TYPE_OBJECT: {
- GDMonoClass *type_class = type.type_class;
-
// Variant
switch (p_value.get_type()) {
case Variant::BOOL: {
@@ -227,17 +229,17 @@ void GDMonoField::set_value(MonoObject *p_object, const Variant &p_value) {
case Variant::TRANSFORM2D: SET_FROM_STRUCT_AND_BREAK(Transform2D);
case Variant::PLANE: SET_FROM_STRUCT_AND_BREAK(Plane);
case Variant::QUAT: SET_FROM_STRUCT_AND_BREAK(Quat);
- case Variant::RECT3: SET_FROM_STRUCT_AND_BREAK(Rect3);
+ case Variant::AABB: SET_FROM_STRUCT_AND_BREAK(AABB);
case Variant::BASIS: SET_FROM_STRUCT_AND_BREAK(Basis);
case Variant::TRANSFORM: SET_FROM_STRUCT_AND_BREAK(Transform);
case Variant::COLOR: SET_FROM_STRUCT_AND_BREAK(Color);
case Variant::NODE_PATH: {
MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator NodePath());
- mono_field_set_value(p_object, mono_field, &managed);
+ mono_field_set_value(p_object, mono_field, managed);
} break;
case Variant::_RID: {
MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator RID());
- mono_field_set_value(p_object, mono_field, &managed);
+ mono_field_set_value(p_object, mono_field, managed);
} break;
case Variant::OBJECT: {
MonoObject *managed = GDMonoUtils::unmanaged_get_managed(p_value.operator Object *());
@@ -246,7 +248,7 @@ void GDMonoField::set_value(MonoObject *p_object, const Variant &p_value) {
}
case Variant::DICTIONARY: {
MonoObject *managed = GDMonoMarshal::Dictionary_to_mono_object(p_value.operator Dictionary());
- mono_field_set_value(p_object, mono_field, &managed);
+ mono_field_set_value(p_object, mono_field, managed);
} break;
case Variant::ARRAY: SET_FROM_ARRAY_AND_BREAK(Array);
case Variant::POOL_BYTE_ARRAY: SET_FROM_ARRAY_AND_BREAK(PoolByteArray);
@@ -264,7 +266,7 @@ void GDMonoField::set_value(MonoObject *p_object, const Variant &p_value) {
case MONO_TYPE_GENERICINST: {
if (CACHED_RAW_MONO_CLASS(Dictionary) == type.type_class->get_raw()) {
MonoObject *managed = GDMonoMarshal::Dictionary_to_mono_object(p_value.operator Dictionary());
- mono_field_set_value(p_object, mono_field, &managed);
+ mono_field_set_value(p_object, mono_field, managed);
break;
}
} break;
@@ -279,11 +281,11 @@ void GDMonoField::set_value(MonoObject *p_object, const Variant &p_value) {
}
bool GDMonoField::get_bool_value(MonoObject *p_object) {
- return UNBOX_BOOLEAN(get_value(p_object));
+ return (bool)GDMonoMarshal::unbox<MonoBoolean>(get_value(p_object));
}
int GDMonoField::get_int_value(MonoObject *p_object) {
- return UNBOX_INT32(get_value(p_object));
+ return GDMonoMarshal::unbox<int32_t>(get_value(p_object));
}
String GDMonoField::get_string_value(MonoObject *p_object) {
diff --git a/modules/mono/mono_gd/gd_mono_marshal.cpp b/modules/mono/mono_gd/gd_mono_marshal.cpp
index b5419952de..8bc2bb5096 100644
--- a/modules/mono/mono_gd/gd_mono_marshal.cpp
+++ b/modules/mono/mono_gd/gd_mono_marshal.cpp
@@ -36,16 +36,16 @@ namespace GDMonoMarshal {
#define RETURN_BOXED_STRUCT(m_t, m_var_in) \
{ \
- const m_t &m_in = m_var_in->operator m_t(); \
+ const m_t &m_in = m_var_in->operator ::m_t(); \
MARSHALLED_OUT(m_t, m_in, raw); \
return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(m_t), raw); \
}
-#define RETURN_UNBOXED_STRUCT(m_t, m_var_in) \
- { \
- float *raw = UNBOX_FLOAT_PTR(m_var_in); \
- MARSHALLED_IN(m_t, raw, ret); \
- return ret; \
+#define RETURN_UNBOXED_STRUCT(m_t, m_var_in) \
+ { \
+ float *raw = (float *)mono_object_unbox(m_var_in); \
+ MARSHALLED_IN(m_t, raw, ret); \
+ return ret; \
}
Variant::Type managed_to_variant_type(const ManagedType &p_type) {
@@ -104,14 +104,17 @@ Variant::Type managed_to_variant_type(const ManagedType &p_type) {
if (tclass == CACHED_CLASS(Transform))
return Variant::TRANSFORM;
- if (tclass == CACHED_CLASS(Rect3))
- return Variant::RECT3;
+ if (tclass == CACHED_CLASS(AABB))
+ return Variant::AABB;
if (tclass == CACHED_CLASS(Color))
return Variant::COLOR;
if (tclass == CACHED_CLASS(Plane))
return Variant::PLANE;
+
+ if (mono_class_is_enum(tclass->get_raw()))
+ return Variant::INT;
} break;
case MONO_TYPE_ARRAY:
@@ -165,9 +168,12 @@ Variant::Type managed_to_variant_type(const ManagedType &p_type) {
return Variant::DICTIONARY;
}
} break;
+
+ default: {
+ } break;
}
- // No error, the caller will decide what to do in this case
+ // Unknown
return Variant::NIL;
}
@@ -291,14 +297,19 @@ MonoObject *variant_to_mono_object(const Variant *p_var, const ManagedType &p_ty
if (tclass == CACHED_CLASS(Transform))
RETURN_BOXED_STRUCT(Transform, p_var);
- if (tclass == CACHED_CLASS(Rect3))
- RETURN_BOXED_STRUCT(Rect3, p_var);
+ if (tclass == CACHED_CLASS(AABB))
+ RETURN_BOXED_STRUCT(AABB, p_var);
if (tclass == CACHED_CLASS(Color))
RETURN_BOXED_STRUCT(Color, p_var);
if (tclass == CACHED_CLASS(Plane))
RETURN_BOXED_STRUCT(Plane, p_var);
+
+ if (mono_class_is_enum(tclass->get_raw())) {
+ int val = p_var->operator signed int();
+ return BOX_ENUM(tclass->get_raw(), val);
+ }
} break;
case MONO_TYPE_ARRAY:
@@ -383,8 +394,8 @@ MonoObject *variant_to_mono_object(const Variant *p_var, const ManagedType &p_ty
RETURN_BOXED_STRUCT(Plane, p_var);
case Variant::QUAT:
RETURN_BOXED_STRUCT(Quat, p_var);
- case Variant::RECT3:
- RETURN_BOXED_STRUCT(Rect3, p_var);
+ case Variant::AABB:
+ RETURN_BOXED_STRUCT(AABB, p_var);
case Variant::BASIS:
RETURN_BOXED_STRUCT(Basis, p_var);
case Variant::TRANSFORM:
@@ -453,30 +464,30 @@ Variant mono_object_to_variant(MonoObject *p_obj) {
Variant mono_object_to_variant(MonoObject *p_obj, const ManagedType &p_type) {
switch (p_type.type_encoding) {
case MONO_TYPE_BOOLEAN:
- return (bool)UNBOX_BOOLEAN(p_obj);
+ return (bool)unbox<MonoBoolean>(p_obj);
case MONO_TYPE_I1:
- return UNBOX_INT8(p_obj);
+ return unbox<int8_t>(p_obj);
case MONO_TYPE_I2:
- return UNBOX_INT16(p_obj);
+ return unbox<int16_t>(p_obj);
case MONO_TYPE_I4:
- return UNBOX_INT32(p_obj);
+ return unbox<int32_t>(p_obj);
case MONO_TYPE_I8:
- return UNBOX_INT64(p_obj);
+ return unbox<int64_t>(p_obj);
case MONO_TYPE_U1:
- return UNBOX_UINT8(p_obj);
+ return unbox<uint8_t>(p_obj);
case MONO_TYPE_U2:
- return UNBOX_UINT16(p_obj);
+ return unbox<uint16_t>(p_obj);
case MONO_TYPE_U4:
- return UNBOX_UINT32(p_obj);
+ return unbox<uint32_t>(p_obj);
case MONO_TYPE_U8:
- return UNBOX_UINT64(p_obj);
+ return unbox<uint64_t>(p_obj);
case MONO_TYPE_R4:
- return UNBOX_FLOAT(p_obj);
+ return unbox<float>(p_obj);
case MONO_TYPE_R8:
- return UNBOX_DOUBLE(p_obj);
+ return unbox<double>(p_obj);
case MONO_TYPE_STRING: {
String str = mono_string_to_godot((MonoString *)p_obj);
@@ -507,14 +518,17 @@ Variant mono_object_to_variant(MonoObject *p_obj, const ManagedType &p_type) {
if (tclass == CACHED_CLASS(Transform))
RETURN_UNBOXED_STRUCT(Transform, p_obj);
- if (tclass == CACHED_CLASS(Rect3))
- RETURN_UNBOXED_STRUCT(Rect3, p_obj);
+ if (tclass == CACHED_CLASS(AABB))
+ RETURN_UNBOXED_STRUCT(AABB, p_obj);
if (tclass == CACHED_CLASS(Color))
RETURN_UNBOXED_STRUCT(Color, p_obj);
if (tclass == CACHED_CLASS(Plane))
RETURN_UNBOXED_STRUCT(Plane, p_obj);
+
+ if (mono_class_is_enum(tclass->get_raw()))
+ return unbox<int32_t>(p_obj);
} break;
case MONO_TYPE_ARRAY:
@@ -554,29 +568,18 @@ Variant mono_object_to_variant(MonoObject *p_obj, const ManagedType &p_type) {
// GodotObject
if (CACHED_CLASS(GodotObject)->is_assignable_from(type_class)) {
- GDMonoField *ptr_field = CACHED_FIELD(GodotObject, ptr);
-
- ERR_FAIL_NULL_V(ptr_field, Variant());
-
- void *ptr_to_unmanaged = UNBOX_PTR(ptr_field->get_value(p_obj));
-
- if (!ptr_to_unmanaged) // IntPtr.Zero
- return Variant();
-
- Object *object_ptr = static_cast<Object *>(ptr_to_unmanaged);
-
- if (!object_ptr)
- return Variant();
-
- return object_ptr;
+ Object *ptr = unbox<Object *>(CACHED_FIELD(GodotObject, ptr)->get_value(p_obj));
+ return ptr ? Variant(ptr) : Variant();
}
if (CACHED_CLASS(NodePath) == type_class) {
- return UNBOX_PTR(CACHED_FIELD(NodePath, ptr)->get_value(p_obj));
+ NodePath *ptr = unbox<NodePath *>(CACHED_FIELD(NodePath, ptr)->get_value(p_obj));
+ return ptr ? Variant(*ptr) : Variant();
}
if (CACHED_CLASS(RID) == type_class) {
- return UNBOX_PTR(CACHED_FIELD(RID, ptr)->get_value(p_obj));
+ RID *ptr = unbox<RID *>(CACHED_FIELD(RID, ptr)->get_value(p_obj));
+ return ptr ? Variant(*ptr) : Variant();
}
} break;
@@ -597,7 +600,7 @@ MonoArray *Array_to_mono_array(const Array &p_array) {
for (int i = 0; i < p_array.size(); i++) {
MonoObject *boxed = variant_to_mono_object(p_array[i]);
- mono_array_set(ret, MonoObject *, i, boxed);
+ mono_array_setref(ret, i, boxed);
}
return ret;
@@ -716,9 +719,9 @@ MonoArray *PoolColorArray_to_mono_array(const PoolColorArray &p_array) {
real_t *raw = (real_t *)mono_array_addr_with_size(ret, sizeof(real_t) * 4, i);
const Color &elem = p_array[i];
raw[0] = elem.r;
- raw[4] = elem.g;
- raw[8] = elem.b;
- raw[12] = elem.a;
+ raw[1] = elem.g;
+ raw[2] = elem.b;
+ raw[3] = elem.a;
#endif
}
@@ -730,7 +733,7 @@ PoolColorArray mono_array_to_PoolColorArray(MonoArray *p_array) {
int length = mono_array_length(p_array);
for (int i = 0; i < length; i++) {
- real_t *raw_elem = mono_array_get(p_array, real_t *, i);
+ real_t *raw_elem = (real_t *)mono_array_addr_with_size(p_array, sizeof(real_t) * 4, i);
MARSHALLED_IN(Color, raw_elem, elem);
ret.push_back(elem);
}
@@ -748,7 +751,7 @@ MonoArray *PoolVector2Array_to_mono_array(const PoolVector2Array &p_array) {
real_t *raw = (real_t *)mono_array_addr_with_size(ret, sizeof(real_t) * 2, i);
const Vector2 &elem = p_array[i];
raw[0] = elem.x;
- raw[4] = elem.y;
+ raw[1] = elem.y;
#endif
}
@@ -760,7 +763,7 @@ PoolVector2Array mono_array_to_PoolVector2Array(MonoArray *p_array) {
int length = mono_array_length(p_array);
for (int i = 0; i < length; i++) {
- real_t *raw_elem = mono_array_get(p_array, real_t *, i);
+ real_t *raw_elem = (real_t *)mono_array_addr_with_size(p_array, sizeof(real_t) * 2, i);
MARSHALLED_IN(Vector2, raw_elem, elem);
ret.push_back(elem);
}
@@ -778,8 +781,8 @@ MonoArray *PoolVector3Array_to_mono_array(const PoolVector3Array &p_array) {
real_t *raw = (real_t *)mono_array_addr_with_size(ret, sizeof(real_t) * 3, i);
const Vector3 &elem = p_array[i];
raw[0] = elem.x;
- raw[4] = elem.y;
- raw[8] = elem.z;
+ raw[1] = elem.y;
+ raw[2] = elem.z;
#endif
}
@@ -791,7 +794,7 @@ PoolVector3Array mono_array_to_PoolVector3Array(MonoArray *p_array) {
int length = mono_array_length(p_array);
for (int i = 0; i < length; i++) {
- real_t *raw_elem = mono_array_get(p_array, real_t *, i);
+ real_t *raw_elem = (real_t *)mono_array_addr_with_size(p_array, sizeof(real_t) * 3, i);
MARSHALLED_IN(Vector3, raw_elem, elem);
ret.push_back(elem);
}
diff --git a/modules/mono/mono_gd/gd_mono_marshal.h b/modules/mono/mono_gd/gd_mono_marshal.h
index 5fbafa0acb..443e947fb5 100644
--- a/modules/mono/mono_gd/gd_mono_marshal.h
+++ b/modules/mono/mono_gd/gd_mono_marshal.h
@@ -36,21 +36,10 @@
namespace GDMonoMarshal {
-#define UNBOX_CHAR_PTR(x) (char *)mono_object_unbox(x)
-#define UNBOX_FLOAT_PTR(x) (float *)mono_object_unbox(x)
-
-#define UNBOX_DOUBLE(x) *(double *)mono_object_unbox(x)
-#define UNBOX_FLOAT(x) *(float *)mono_object_unbox(x)
-#define UNBOX_INT64(x) *(int64_t *)mono_object_unbox(x)
-#define UNBOX_INT32(x) *(int32_t *)mono_object_unbox(x)
-#define UNBOX_INT16(x) *(int16_t *)mono_object_unbox(x)
-#define UNBOX_INT8(x) *(int8_t *)mono_object_unbox(x)
-#define UNBOX_UINT64(x) *(uint64_t *)mono_object_unbox(x)
-#define UNBOX_UINT32(x) *(uint32_t *)mono_object_unbox(x)
-#define UNBOX_UINT16(x) *(uint16_t *)mono_object_unbox(x)
-#define UNBOX_UINT8(x) *(uint8_t *)mono_object_unbox(x)
-#define UNBOX_BOOLEAN(x) *(MonoBoolean *)mono_object_unbox(x)
-#define UNBOX_PTR(x) mono_object_unbox(x)
+template <typename T>
+T unbox(MonoObject *p_obj) {
+ return *(T *)mono_object_unbox(p_obj);
+}
#define BOX_DOUBLE(x) mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(double), &x)
#define BOX_FLOAT(x) mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(float), &x)
@@ -64,6 +53,7 @@ namespace GDMonoMarshal {
#define BOX_UINT8(x) mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(uint8_t), &x)
#define BOX_BOOLEAN(x) mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(bool), &x)
#define BOX_PTR(x) mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(IntPtr), x)
+#define BOX_ENUM(m_enum_class, x) mono_value_box(mono_domain_get(), m_enum_class, &x)
Variant::Type managed_to_variant_type(const ManagedType &p_type);
@@ -207,10 +197,10 @@ Dictionary mono_object_to_Dictionary(MonoObject *p_dict);
Basis(m_in[0], m_in[1], m_in[2], m_in[3], m_in[4], m_in[5], m_in[6], m_in[7], m_in[8]), \
Vector3(m_in[9], m_in[10], m_in[11]));
-// Rect3
+// AABB
-#define MARSHALLED_OUT_Rect3(m_in, m_out) real_t m_out[6] = { m_in.position.x, m_in.position.y, m_in.position.z, m_in.size.x, m_in.size.y, m_in.size.z };
-#define MARSHALLED_IN_Rect3(m_in, m_out) Rect3 m_out(Vector3(m_in[0], m_in[1], m_in[2]), Vector3(m_in[3], m_in[4], m_in[5]));
+#define MARSHALLED_OUT_AABB(m_in, m_out) real_t m_out[6] = { m_in.position.x, m_in.position.y, m_in.position.z, m_in.size.x, m_in.size.y, m_in.size.z };
+#define MARSHALLED_IN_AABB(m_in, m_out) AABB m_out(Vector3(m_in[0], m_in[1], m_in[2]), Vector3(m_in[3], m_in[4], m_in[5]));
// Color
@@ -224,6 +214,6 @@ Dictionary mono_object_to_Dictionary(MonoObject *p_dict);
#endif
-} // GDMonoMarshal
+} // namespace GDMonoMarshal
#endif // GDMONOMARSHAL_H
diff --git a/modules/mono/mono_gd/gd_mono_method.cpp b/modules/mono/mono_gd/gd_mono_method.cpp
index 6468e0d3d9..eb97d62900 100644
--- a/modules/mono/mono_gd/gd_mono_method.cpp
+++ b/modules/mono/mono_gd/gd_mono_method.cpp
@@ -83,9 +83,32 @@ MonoObject *GDMonoMethod::invoke(MonoObject *p_object, const Variant **p_params,
mono_array_set(params, MonoObject *, i, boxed_param);
}
- return mono_runtime_invoke_array(mono_method, p_object, params, r_exc);
+ MonoObject *exc = NULL;
+ MonoObject *ret = mono_runtime_invoke_array(mono_method, p_object, params, &exc);
+
+ if (exc) {
+ if (r_exc) {
+ *r_exc = exc;
+ } else {
+ ERR_PRINT(GDMonoUtils::get_exception_name_and_message(exc).utf8());
+ mono_print_unhandled_exception(exc);
+ }
+ }
+
+ return ret;
} else {
- mono_runtime_invoke(mono_method, p_object, NULL, r_exc);
+ MonoObject *exc = NULL;
+ mono_runtime_invoke(mono_method, p_object, NULL, &exc);
+
+ if (exc) {
+ if (r_exc) {
+ *r_exc = exc;
+ } else {
+ ERR_PRINT(GDMonoUtils::get_exception_name_and_message(exc).utf8());
+ mono_print_unhandled_exception(exc);
+ }
+ }
+
return NULL;
}
}
@@ -96,7 +119,19 @@ MonoObject *GDMonoMethod::invoke(MonoObject *p_object, MonoObject **r_exc) {
}
MonoObject *GDMonoMethod::invoke_raw(MonoObject *p_object, void **p_params, MonoObject **r_exc) {
- return mono_runtime_invoke(mono_method, p_object, p_params, r_exc);
+ MonoObject *exc = NULL;
+ MonoObject *ret = mono_runtime_invoke(mono_method, p_object, p_params, &exc);
+
+ if (exc) {
+ if (r_exc) {
+ *r_exc = exc;
+ } else {
+ ERR_PRINT(GDMonoUtils::get_exception_name_and_message(exc).utf8());
+ mono_print_unhandled_exception(exc);
+ }
+ }
+
+ return ret;
}
bool GDMonoMethod::has_attribute(GDMonoClass *p_attr_class) {
diff --git a/modules/mono/mono_gd/gd_mono_utils.cpp b/modules/mono/mono_gd/gd_mono_utils.cpp
index 5deca8e64d..1cccd0ad9d 100644
--- a/modules/mono/mono_gd/gd_mono_utils.cpp
+++ b/modules/mono/mono_gd/gd_mono_utils.cpp
@@ -80,12 +80,13 @@ void MonoCache::clear_members() {
class_Basis = NULL;
class_Quat = NULL;
class_Transform = NULL;
- class_Rect3 = NULL;
+ class_AABB = NULL;
class_Color = NULL;
class_Plane = NULL;
class_NodePath = NULL;
class_RID = NULL;
class_GodotObject = NULL;
+ class_GodotReference = NULL;
class_Node = NULL;
class_Control = NULL;
class_Spatial = NULL;
@@ -95,7 +96,6 @@ void MonoCache::clear_members() {
class_ExportAttribute = NULL;
field_ExportAttribute_hint = NULL;
field_ExportAttribute_hint_string = NULL;
- field_ExportAttribute_usage = NULL;
class_ToolAttribute = NULL;
class_RemoteAttribute = NULL;
class_SyncAttribute = NULL;
@@ -111,7 +111,7 @@ void MonoCache::clear_members() {
methodthunk_MarshalUtils_DictionaryToArrays = NULL;
methodthunk_MarshalUtils_ArraysToDictionary = NULL;
- methodthunk_GodotObject__AwaitedSignalCallback = NULL;
+ methodthunk_SignalAwaiter_SignalCallback = NULL;
methodthunk_SignalAwaiter_FailureCallback = NULL;
methodthunk_GodotTaskScheduler_Activate = NULL;
@@ -147,12 +147,13 @@ void update_godot_api_cache() {
CACHE_CLASS_AND_CHECK(Basis, GODOT_API_CLASS(Basis));
CACHE_CLASS_AND_CHECK(Quat, GODOT_API_CLASS(Quat));
CACHE_CLASS_AND_CHECK(Transform, GODOT_API_CLASS(Transform));
- CACHE_CLASS_AND_CHECK(Rect3, GODOT_API_CLASS(Rect3));
+ CACHE_CLASS_AND_CHECK(AABB, GODOT_API_CLASS(AABB));
CACHE_CLASS_AND_CHECK(Color, GODOT_API_CLASS(Color));
CACHE_CLASS_AND_CHECK(Plane, GODOT_API_CLASS(Plane));
CACHE_CLASS_AND_CHECK(NodePath, GODOT_API_CLASS(NodePath));
CACHE_CLASS_AND_CHECK(RID, GODOT_API_CLASS(NodePath));
CACHE_CLASS_AND_CHECK(GodotObject, GODOT_API_CLASS(Object));
+ CACHE_CLASS_AND_CHECK(GodotReference, GODOT_API_CLASS(Reference));
CACHE_CLASS_AND_CHECK(Node, GODOT_API_CLASS(Node));
CACHE_CLASS_AND_CHECK(Control, GODOT_API_CLASS(Control));
CACHE_CLASS_AND_CHECK(Spatial, GODOT_API_CLASS(Spatial));
@@ -163,7 +164,6 @@ void update_godot_api_cache() {
CACHE_CLASS_AND_CHECK(ExportAttribute, GODOT_API_CLASS(ExportAttribute));
CACHE_FIELD_AND_CHECK(ExportAttribute, hint, CACHED_CLASS(ExportAttribute)->get_field("hint"));
CACHE_FIELD_AND_CHECK(ExportAttribute, hint_string, CACHED_CLASS(ExportAttribute)->get_field("hint_string"));
- CACHE_FIELD_AND_CHECK(ExportAttribute, usage, CACHED_CLASS(ExportAttribute)->get_field("usage"));
CACHE_CLASS_AND_CHECK(ToolAttribute, GODOT_API_CLASS(ToolAttribute));
CACHE_CLASS_AND_CHECK(RemoteAttribute, GODOT_API_CLASS(RemoteAttribute));
CACHE_CLASS_AND_CHECK(SyncAttribute, GODOT_API_CLASS(SyncAttribute));
@@ -178,7 +178,7 @@ void update_godot_api_cache() {
CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, DictionaryToArrays, (MarshalUtils_DictToArrays)CACHED_CLASS(MarshalUtils)->get_method("DictionaryToArrays", 3)->get_thunk());
CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, ArraysToDictionary, (MarshalUtils_ArraysToDict)CACHED_CLASS(MarshalUtils)->get_method("ArraysToDictionary", 2)->get_thunk());
- CACHE_METHOD_THUNK_AND_CHECK(GodotObject, _AwaitedSignalCallback, (GodotObject__AwaitedSignalCallback)CACHED_CLASS(GodotObject)->get_method("_AwaitedSignalCallback", 2)->get_thunk());
+ CACHE_METHOD_THUNK_AND_CHECK(SignalAwaiter, SignalCallback, (SignalAwaiter_SignalCallback)GODOT_API_CLASS(SignalAwaiter)->get_method("SignalCallback", 1)->get_thunk());
CACHE_METHOD_THUNK_AND_CHECK(SignalAwaiter, FailureCallback, (SignalAwaiter_FailureCallback)GODOT_API_CLASS(SignalAwaiter)->get_method("FailureCallback", 0)->get_thunk());
CACHE_METHOD_THUNK_AND_CHECK(GodotTaskScheduler, Activate, (GodotTaskScheduler_Activate)GODOT_API_CLASS(GodotTaskScheduler)->get_method("Activate", 0)->get_thunk());
@@ -364,4 +364,4 @@ String get_exception_name_and_message(MonoObject *p_ex) {
return res;
}
-}
+} // namespace GDMonoUtils
diff --git a/modules/mono/mono_gd/gd_mono_utils.h b/modules/mono/mono_gd/gd_mono_utils.h
index f97f048aa9..c38f8c5af5 100644
--- a/modules/mono/mono_gd/gd_mono_utils.h
+++ b/modules/mono/mono_gd/gd_mono_utils.h
@@ -42,7 +42,7 @@ namespace GDMonoUtils {
typedef MonoObject *(*MarshalUtils_DictToArrays)(MonoObject *, MonoArray **, MonoArray **, MonoObject **);
typedef MonoObject *(*MarshalUtils_ArraysToDict)(MonoArray *, MonoArray *, MonoObject **);
-typedef MonoObject *(*GodotObject__AwaitedSignalCallback)(MonoObject *, MonoArray **, MonoObject *, MonoObject **);
+typedef MonoObject *(*SignalAwaiter_SignalCallback)(MonoObject *, MonoArray **, MonoObject **);
typedef MonoObject *(*SignalAwaiter_FailureCallback)(MonoObject *, MonoObject **);
typedef MonoObject *(*GodotTaskScheduler_Activate)(MonoObject *, MonoObject **);
@@ -82,12 +82,13 @@ struct MonoCache {
GDMonoClass *class_Basis;
GDMonoClass *class_Quat;
GDMonoClass *class_Transform;
- GDMonoClass *class_Rect3;
+ GDMonoClass *class_AABB;
GDMonoClass *class_Color;
GDMonoClass *class_Plane;
GDMonoClass *class_NodePath;
GDMonoClass *class_RID;
GDMonoClass *class_GodotObject;
+ GDMonoClass *class_GodotReference;
GDMonoClass *class_Node;
GDMonoClass *class_Control;
GDMonoClass *class_Spatial;
@@ -97,7 +98,6 @@ struct MonoCache {
GDMonoClass *class_ExportAttribute;
GDMonoField *field_ExportAttribute_hint;
GDMonoField *field_ExportAttribute_hint_string;
- GDMonoField *field_ExportAttribute_usage;
GDMonoClass *class_ToolAttribute;
GDMonoClass *class_RemoteAttribute;
GDMonoClass *class_SyncAttribute;
@@ -113,7 +113,7 @@ struct MonoCache {
MarshalUtils_DictToArrays methodthunk_MarshalUtils_DictionaryToArrays;
MarshalUtils_ArraysToDict methodthunk_MarshalUtils_ArraysToDictionary;
- GodotObject__AwaitedSignalCallback methodthunk_GodotObject__AwaitedSignalCallback;
+ SignalAwaiter_SignalCallback methodthunk_SignalAwaiter_SignalCallback;
SignalAwaiter_FailureCallback methodthunk_SignalAwaiter_FailureCallback;
GodotTaskScheduler_Activate methodthunk_GodotTaskScheduler_Activate;
@@ -149,6 +149,10 @@ void attach_current_thread();
void detach_current_thread();
MonoThread *get_current_thread();
+_FORCE_INLINE_ bool is_main_thread() {
+ return mono_domain_get() != NULL && mono_thread_get_main() == mono_thread_current();
+}
+
GDMonoClass *get_object_class(MonoObject *p_object);
GDMonoClass *type_get_proxy_class(const StringName &p_type);
GDMonoClass *get_class_native_base(GDMonoClass *p_class);
@@ -162,9 +166,9 @@ MonoDomain *create_domain(const String &p_friendly_name);
String get_exception_name_and_message(MonoObject *p_ex);
-} // GDMonoUtils
+} // namespace GDMonoUtils
-#define NATIVE_GDMONOCLASS_NAME(m_class) (GDMonoMarshal::mono_string_to_godot((MonoString *)m_class->get_field("nativeName")->get_value(NULL)))
+#define NATIVE_GDMONOCLASS_NAME(m_class) (GDMonoMarshal::mono_string_to_godot((MonoString *)m_class->get_field(BINDINGS_NATIVE_NAME_FIELD)->get_value(NULL)))
#define CACHED_CLASS(m_class) (GDMonoUtils::mono_cache.class_##m_class)
#define CACHED_CLASS_RAW(m_class) (GDMonoUtils::mono_cache.class_##m_class->get_raw())
diff --git a/modules/mono/mono_reg_utils.py b/modules/mono/mono_reg_utils.py
index e9988625f5..8ddddb3a24 100644
--- a/modules/mono/mono_reg_utils.py
+++ b/modules/mono/mono_reg_utils.py
@@ -1,4 +1,7 @@
import os
+import platform
+
+from compat import decode_utf8
if os.name == 'nt':
import sys
@@ -11,8 +14,7 @@ if os.name == 'nt':
def _reg_open_key(key, subkey):
try:
return winreg.OpenKey(key, subkey)
- except (WindowsError, EnvironmentError) as e:
- import platform
+ except (WindowsError, OSError):
if platform.architecture()[0] == '32bit':
bitness_sam = winreg.KEY_WOW64_64KEY
else:
@@ -20,39 +22,93 @@ def _reg_open_key(key, subkey):
return winreg.OpenKey(key, subkey, 0, winreg.KEY_READ | bitness_sam)
-def _find_mono_in_reg(subkey):
+def _reg_open_key_bits(key, subkey, bits):
+ sam = winreg.KEY_READ
+
+ if platform.architecture()[0] == '32bit':
+ if bits == '64':
+ # Force 32bit process to search in 64bit registry
+ sam |= winreg.KEY_WOW64_64KEY
+ else:
+ if bits == '32':
+ # Force 64bit process to search in 32bit registry
+ sam |= winreg.KEY_WOW64_32KEY
+
+ return winreg.OpenKey(key, subkey, 0, sam)
+
+
+def _find_mono_in_reg(subkey, bits):
try:
- with _reg_open_key(winreg.HKEY_LOCAL_MACHINE, subkey) as hKey:
+ with _reg_open_key_bits(winreg.HKEY_LOCAL_MACHINE, subkey, bits) as hKey:
value, regtype = winreg.QueryValueEx(hKey, 'SdkInstallRoot')
return value
- except (WindowsError, EnvironmentError) as e:
+ except (WindowsError, OSError):
return None
-def _find_mono_in_reg_old(subkey):
+
+def _find_mono_in_reg_old(subkey, bits):
try:
- with _reg_open_key(winreg.HKEY_LOCAL_MACHINE, subkey) as hKey:
+ with _reg_open_key_bits(winreg.HKEY_LOCAL_MACHINE, subkey, bits) as hKey:
default_clr, regtype = winreg.QueryValueEx(hKey, 'DefaultCLR')
if default_clr:
- return _find_mono_in_reg(subkey + '\\' + default_clr)
+ return _find_mono_in_reg(subkey + '\\' + default_clr, bits)
return None
except (WindowsError, EnvironmentError):
return None
-def find_mono_root_dir():
- dir = _find_mono_in_reg(r'SOFTWARE\Mono')
- if dir:
- return dir
- dir = _find_mono_in_reg_old(r'SOFTWARE\Novell\Mono')
- if dir:
- return dir
- return None
+def find_mono_root_dir(bits):
+ root_dir = _find_mono_in_reg(r'SOFTWARE\Mono', bits)
+ if root_dir is not None:
+ return root_dir
+ root_dir = _find_mono_in_reg_old(r'SOFTWARE\Novell\Mono', bits)
+ if root_dir is not None:
+ return root_dir
+ return ''
def find_msbuild_tools_path_reg():
+ import subprocess
+
+ vswhere = os.getenv('PROGRAMFILES(X86)')
+ if not vswhere:
+ vswhere = os.getenv('PROGRAMFILES')
+ vswhere += r'\Microsoft Visual Studio\Installer\vswhere.exe'
+
+ vswhere_args = ['-latest', '-requires', 'Microsoft.Component.MSBuild']
+
try:
- with _reg_open_key(winreg.HKEY_LOCAL_MACHINE, r'SOFTWARE\Microsoft\MSBuild\ToolsVersions\4.0') as hKey:
+ lines = subprocess.check_output([vswhere] + vswhere_args).splitlines()
+
+ for line in lines:
+ parts = decode_utf8(line).split(':', 1)
+
+ if len(parts) < 2 or parts[0] != 'installationPath':
+ continue
+
+ val = parts[1].strip()
+
+ if not val:
+ raise ValueError('Value of `installationPath` entry is empty')
+
+ return os.path.join(val, "MSBuild\\15.0\\Bin")
+
+ raise ValueError('Cannot find `installationPath` entry')
+ except ValueError as e:
+ print('Error reading output from vswhere: ' + e.message)
+ except WindowsError:
+ pass # Fine, vswhere not found
+ except (subprocess.CalledProcessError, OSError):
+ pass
+
+ # Try to find 14.0 in the Registry
+
+ try:
+ subkey = r'SOFTWARE\Microsoft\MSBuild\ToolsVersions\14.0'
+ with _reg_open_key(winreg.HKEY_LOCAL_MACHINE, subkey) as hKey:
value, regtype = winreg.QueryValueEx(hKey, 'MSBuildToolsPath')
return value
- except (WindowsError, EnvironmentError) as e:
- return None
+ except (WindowsError, OSError):
+ return ''
+
+ return ''
diff --git a/modules/mono/register_types.cpp b/modules/mono/register_types.cpp
index 2a84f0d1a6..217460a439 100644
--- a/modules/mono/register_types.cpp
+++ b/modules/mono/register_types.cpp
@@ -29,7 +29,7 @@
/*************************************************************************/
#include "register_types.h"
-#include "project_settings.h"
+#include "engine.h"
#include "csharp_script.h"
@@ -44,7 +44,8 @@ void register_mono_types() {
_godotsharp = memnew(_GodotSharp);
- ProjectSettings::get_singleton()->add_singleton(ProjectSettings::Singleton("GodotSharp", _GodotSharp::get_singleton()));
+ ClassDB::register_class<_GodotSharp>();
+ Engine::get_singleton()->add_singleton(Engine::Singleton("GodotSharp", _GodotSharp::get_singleton()));
script_language_cs = memnew(CSharpLanguage);
script_language_cs->set_language_index(ScriptServer::get_language_count());
diff --git a/modules/mono/signal_awaiter_utils.cpp b/modules/mono/signal_awaiter_utils.cpp
index 012dd119b1..7e99df29a1 100644
--- a/modules/mono/signal_awaiter_utils.cpp
+++ b/modules/mono/signal_awaiter_utils.cpp
@@ -29,6 +29,9 @@
/*************************************************************************/
#include "signal_awaiter_utils.h"
+#include "csharp_script.h"
+#include "mono_gd/gd_mono_class.h"
+#include "mono_gd/gd_mono_marshal.h"
#include "mono_gd/gd_mono_utils.h"
namespace SignalAwaiterUtils {
@@ -40,13 +43,20 @@ Error connect_signal_awaiter(Object *p_source, const String &p_signal, Object *p
uint32_t awaiter_handle = MonoGCHandle::make_strong_handle(p_awaiter);
Ref<SignalAwaiterHandle> sa_con = memnew(SignalAwaiterHandle(awaiter_handle));
+#ifdef DEBUG_ENABLED
+ sa_con->set_connection_target(p_target);
+#endif
+
Vector<Variant> binds;
binds.push_back(sa_con);
- Error err = p_source->connect(p_signal, p_target, "_AwaitedSignalCallback", binds, Object::CONNECT_ONESHOT);
+
+ Error err = p_source->connect(p_signal, sa_con.ptr(),
+ CSharpLanguage::get_singleton()->get_string_names()._signal_callback,
+ binds, Object::CONNECT_ONESHOT);
if (err != OK) {
- // set it as completed to prevent it from calling the failure callback when deleted
- // the awaiter will be aware of the failure by checking the returned error
+ // Set it as completed to prevent it from calling the failure callback when released.
+ // The awaiter will be aware of the failure by checking the returned error.
sa_con->set_completed(true);
}
@@ -54,11 +64,68 @@ Error connect_signal_awaiter(Object *p_source, const String &p_signal, Object *p
}
}
-SignalAwaiterHandle::SignalAwaiterHandle(uint32_t p_handle)
- : MonoGCHandle(p_handle) {
+Variant SignalAwaiterHandle::_signal_callback(const Variant **p_args, int p_argcount, Variant::CallError &r_error) {
+
+#ifdef DEBUG_ENABLED
+ if (conn_target_id && !ObjectDB::get_instance(conn_target_id)) {
+ ERR_EXPLAIN("Resumed after await, but class instance is gone");
+ ERR_FAIL_V(Variant());
+ }
+#endif
+
+ if (p_argcount < 1) {
+ r_error.error = Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_error.argument = 1;
+ return Variant();
+ }
+
+ Ref<SignalAwaiterHandle> self = *p_args[p_argcount - 1];
+
+ if (self.is_null()) {
+ r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument = p_argcount - 1;
+ r_error.expected = Variant::OBJECT;
+ return Variant();
+ }
+
+ set_completed(true);
+
+ int signal_argc = p_argcount - 1;
+ MonoArray *signal_args = mono_array_new(SCRIPTS_DOMAIN, CACHED_CLASS_RAW(MonoObject), signal_argc);
+
+ for (int i = 0; i < signal_argc; i++) {
+ MonoObject *boxed = GDMonoMarshal::variant_to_mono_object(*p_args[i]);
+ mono_array_set(signal_args, MonoObject *, i, boxed);
+ }
+
+ GDMonoUtils::SignalAwaiter_SignalCallback thunk = CACHED_METHOD_THUNK(SignalAwaiter, SignalCallback);
+
+ MonoObject *ex = NULL;
+ thunk(get_target(), &signal_args, &ex);
+
+ if (ex) {
+ mono_print_unhandled_exception(ex);
+ ERR_FAIL_V(Variant());
+ }
+
+ return Variant();
+}
+
+void SignalAwaiterHandle::_bind_methods() {
+
+ ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "_signal_callback", &SignalAwaiterHandle::_signal_callback, MethodInfo("_signal_callback"));
+}
+
+SignalAwaiterHandle::SignalAwaiterHandle(uint32_t p_managed_handle)
+ : MonoGCHandle(p_managed_handle) {
+
+#ifdef DEBUG_ENABLED
+ conn_target_id = 0;
+#endif
}
SignalAwaiterHandle::~SignalAwaiterHandle() {
+
if (!completed) {
GDMonoUtils::SignalAwaiter_FailureCallback thunk = CACHED_METHOD_THUNK(SignalAwaiter, FailureCallback);
diff --git a/modules/mono/signal_awaiter_utils.h b/modules/mono/signal_awaiter_utils.h
index 422ed4754f..0d615b5826 100644
--- a/modules/mono/signal_awaiter_utils.h
+++ b/modules/mono/signal_awaiter_utils.h
@@ -40,13 +40,30 @@ Error connect_signal_awaiter(Object *p_source, const String &p_signal, Object *p
class SignalAwaiterHandle : public MonoGCHandle {
+ GDCLASS(SignalAwaiterHandle, MonoGCHandle)
+
bool completed;
+#ifdef DEBUG_ENABLED
+ ObjectID conn_target_id;
+#endif
+
+ Variant _signal_callback(const Variant **p_args, int p_argcount, Variant::CallError &r_error);
+
+protected:
+ static void _bind_methods();
+
public:
_FORCE_INLINE_ bool is_completed() { return completed; }
_FORCE_INLINE_ void set_completed(bool p_completed) { completed = p_completed; }
- SignalAwaiterHandle(uint32_t p_handle);
+#ifdef DEBUG_ENABLED
+ _FORCE_INLINE_ void set_connection_target(Object *p_target) {
+ conn_target_id = p_target->get_instance_id();
+ }
+#endif
+
+ SignalAwaiterHandle(uint32_t p_managed_handle);
~SignalAwaiterHandle();
};
diff --git a/modules/mono/utils/path_utils.cpp b/modules/mono/utils/path_utils.cpp
index c8581f6122..105c2c981e 100644
--- a/modules/mono/utils/path_utils.cpp
+++ b/modules/mono/utils/path_utils.cpp
@@ -56,9 +56,6 @@ String path_which(const String &p_name) {
for (int i = 0; i < env_path.size(); i++) {
String p = path_join(env_path[i], p_name);
- if (FileAccess::exists(p))
- return p;
-
#ifdef WINDOWS_ENABLED
for (int j = 0; j < exts.size(); j++) {
String p2 = p + exts[j];
@@ -66,6 +63,9 @@ String path_which(const String &p_name) {
if (FileAccess::exists(p2))
return p2;
}
+#else
+ if (FileAccess::exists(p))
+ return p;
#endif
}
diff --git a/modules/mono/utils/string_utils.cpp b/modules/mono/utils/string_utils.cpp
index de1a60dbd1..f26663ea11 100644
--- a/modules/mono/utils/string_utils.cpp
+++ b/modules/mono/utils/string_utils.cpp
@@ -126,3 +126,32 @@ String sformat(const String &p_text, const Variant &p1, const Variant &p2, const
return new_string;
}
+
+bool is_csharp_keyword(const String &p_name) {
+
+ // Reserved keywords
+
+ return p_name == "abstract" || p_name == "as" || p_name == "base" || p_name == "bool" ||
+ p_name == "break" || p_name == "byte" || p_name == "case" || p_name == "catch" ||
+ p_name == "char" || p_name == "checked" || p_name == "class" || p_name == "const" ||
+ p_name == "continue" || p_name == "decimal" || p_name == "default" || p_name == "delegate" ||
+ p_name == "do" || p_name == "double" || p_name == "else" || p_name == "enum" ||
+ p_name == "event" || p_name == "explicit" || p_name == "extern" || p_name == "false" ||
+ p_name == "finally" || p_name == "fixed" || p_name == "float" || p_name == "for" ||
+ p_name == "forech" || p_name == "goto" || p_name == "if" || p_name == "implicit" ||
+ p_name == "in" || p_name == "int" || p_name == "interface" || p_name == "internal" ||
+ p_name == "is" || p_name == "lock" || p_name == "long" || p_name == "namespace" ||
+ p_name == "new" || p_name == "null" || p_name == "object" || p_name == "operator" ||
+ p_name == "out" || p_name == "override" || p_name == "params" || p_name == "private" ||
+ p_name == "protected" || p_name == "public" || p_name == "readonly" || p_name == "ref" ||
+ p_name == "return" || p_name == "sbyte" || p_name == "sealed" || p_name == "short" ||
+ p_name == "sizeof" || p_name == "stackalloc" || p_name == "static" || p_name == "string" ||
+ p_name == "struct" || p_name == "switch" || p_name == "this" || p_name == "throw" ||
+ p_name == "true" || p_name == "try" || p_name == "typeof" || p_name == "uint" || p_name == "ulong" ||
+ p_name == "unchecked" || p_name == "unsafe" || p_name == "ushort" || p_name == "using" ||
+ p_name == "virtual" || p_name == "volatile" || p_name == "void" || p_name == "while";
+}
+
+String escape_csharp_keyword(const String &p_name) {
+ return is_csharp_keyword(p_name) ? "@" + p_name : p_name;
+}
diff --git a/modules/mono/utils/string_utils.h b/modules/mono/utils/string_utils.h
index 2f2c3c2d89..a0d66ebdc3 100644
--- a/modules/mono/utils/string_utils.h
+++ b/modules/mono/utils/string_utils.h
@@ -35,4 +35,10 @@
String sformat(const String &p_text, const Variant &p1 = Variant(), const Variant &p2 = Variant(), const Variant &p3 = Variant(), const Variant &p4 = Variant(), const Variant &p5 = Variant());
+#ifdef TOOLS_ENABLED
+bool is_csharp_keyword(const String &p_name);
+
+String escape_csharp_keyword(const String &p_name);
+#endif
+
#endif // STRING_FORMAT_H
diff --git a/modules/ogg/config.py b/modules/ogg/config.py
index ef5daca05c..5f133eba90 100644
--- a/modules/ogg/config.py
+++ b/modules/ogg/config.py
@@ -1,8 +1,5 @@
-
def can_build(platform):
-# return True
- return False
-
+ return True
def configure(env):
pass
diff --git a/modules/openssl/config.py b/modules/openssl/config.py
index fb920482f5..5f133eba90 100644
--- a/modules/openssl/config.py
+++ b/modules/openssl/config.py
@@ -1,7 +1,5 @@
-
def can_build(platform):
return True
-
def configure(env):
pass
diff --git a/modules/openssl/stream_peer_openssl.cpp b/modules/openssl/stream_peer_openssl.cpp
index c19bdc4214..6d1d5485f3 100644
--- a/modules/openssl/stream_peer_openssl.cpp
+++ b/modules/openssl/stream_peer_openssl.cpp
@@ -30,7 +30,7 @@
#include "stream_peer_openssl.h"
// Compatibility with OpenSSL 1.1.0.
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
#define BIO_set_num(b, n)
#else
#define BIO_set_num(b, n) ((b)->num = (n))
@@ -269,7 +269,7 @@ int StreamPeerOpenSSL::_bio_puts(BIO *b, const char *str) {
return _bio_write(b, str, strlen(str));
}
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
BIO_METHOD *StreamPeerOpenSSL::_bio_method = NULL;
BIO_METHOD *StreamPeerOpenSSL::_get_bio_method() {
@@ -568,7 +568,7 @@ void StreamPeerOpenSSL::initialize_ssl() {
load_certs_func = _load_certs;
_create = _create_func;
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
CRYPTO_malloc_init(); // Initialize malloc, free, etc for OpenSSL's use
#endif
SSL_library_init(); // Initialize OpenSSL's SSL libraries
diff --git a/modules/openssl/stream_peer_openssl.h b/modules/openssl/stream_peer_openssl.h
index 535114058d..ad09564447 100644
--- a/modules/openssl/stream_peer_openssl.h
+++ b/modules/openssl/stream_peer_openssl.h
@@ -53,7 +53,7 @@ private:
static int _bio_gets(BIO *b, char *buf, int len);
static int _bio_puts(BIO *b, const char *str);
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
static BIO_METHOD *_bio_method;
#else
static BIO_METHOD _bio_method;
diff --git a/modules/opus/SCsub b/modules/opus/SCsub
index fee06bd267..6f643ef08c 100644
--- a/modules/opus/SCsub
+++ b/modules/opus/SCsub
@@ -3,6 +3,9 @@
Import('env')
Import('env_modules')
+
+stub = True
+
env_opus = env_modules.Clone()
# Thirdparty source files
@@ -212,5 +215,9 @@ if env['builtin_opus']:
if env['builtin_libogg']:
env_opus.Append(CPPPATH=["#thirdparty/libogg"])
-# Module files
-env_opus.add_source_files(env.modules_sources, "*.cpp")
+if not stub:
+ # Module files
+ env_opus.add_source_files(env.modules_sources, "*.cpp")
+else:
+ # Module files
+ env_opus.add_source_files(env.modules_sources, "stub/register_types.cpp")
diff --git a/modules/opus/audio_stream_opus.cpp b/modules/opus/audio_stream_opus.cpp
index c7748b9b21..06eab4c94d 100644
--- a/modules/opus/audio_stream_opus.cpp
+++ b/modules/opus/audio_stream_opus.cpp
@@ -267,7 +267,7 @@ void AudioStreamPlaybackOpus::seek(float p_time) {
frames_mixed = osrate * p_time;
}
-int AudioStreamPlaybackOpus::mix(int16_t *p_bufer, int p_frames) {
+int AudioStreamPlaybackOpus::mix(int16_t *p_buffer, int p_frames) {
if (!playing)
return 0;
@@ -281,7 +281,7 @@ int AudioStreamPlaybackOpus::mix(int16_t *p_bufer, int p_frames) {
break;
}
- int ret = op_read(opus_file, (opus_int16 *)p_bufer, todo * stream_channels, &current_section);
+ int ret = op_read(opus_file, (opus_int16 *)p_buffer, todo * stream_channels, &current_section);
if (ret < 0) {
playing = false;
ERR_EXPLAIN("Error reading Opus File: " + file);
@@ -325,7 +325,7 @@ int AudioStreamPlaybackOpus::mix(int16_t *p_bufer, int p_frames) {
frames_mixed += ret;
- p_bufer += ret * stream_channels;
+ p_buffer += ret * stream_channels;
p_frames -= ret;
}
diff --git a/modules/opus/audio_stream_opus.h b/modules/opus/audio_stream_opus.h
index 7b7740a804..f8d8f585cf 100644
--- a/modules/opus/audio_stream_opus.h
+++ b/modules/opus/audio_stream_opus.h
@@ -107,7 +107,7 @@ public:
virtual int get_minimum_buffer_size() const;
- virtual int mix(int16_t *p_bufer, int p_frames);
+ virtual int mix(int16_t *p_buffer, int p_frames);
AudioStreamPlaybackOpus();
~AudioStreamPlaybackOpus();
diff --git a/modules/opus/config.py b/modules/opus/config.py
index ef5daca05c..60f8d838d6 100644
--- a/modules/opus/config.py
+++ b/modules/opus/config.py
@@ -1,8 +1,13 @@
-
def can_build(platform):
-# return True
- return False
-
+ return True
def configure(env):
pass
+
+def get_doc_classes():
+ return [
+ "AudioStreamOpus",
+ ]
+
+def get_doc_path():
+ return "doc_classes"
diff --git a/modules/opus/stub/register_types.cpp b/modules/opus/stub/register_types.cpp
new file mode 100644
index 0000000000..c5ae3e274e
--- /dev/null
+++ b/modules/opus/stub/register_types.cpp
@@ -0,0 +1,36 @@
+/*************************************************************************/
+/* register_types.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#include "register_types.h"
+
+// Dummy module as libvorbis is needed by other modules (theora ...)
+
+void register_opus_types() {}
+
+void unregister_opus_types() {}
diff --git a/modules/opus/stub/register_types.h b/modules/opus/stub/register_types.h
new file mode 100644
index 0000000000..4517dc5df7
--- /dev/null
+++ b/modules/opus/stub/register_types.h
@@ -0,0 +1,31 @@
+/*************************************************************************/
+/* register_types.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 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. */
+/*************************************************************************/
+void register_opus_types();
+void unregister_opus_types();
diff --git a/modules/pbm/config.py b/modules/pbm/config.py
index fb920482f5..5f133eba90 100644
--- a/modules/pbm/config.py
+++ b/modules/pbm/config.py
@@ -1,7 +1,5 @@
-
def can_build(platform):
return True
-
def configure(env):
pass
diff --git a/modules/pvr/config.py b/modules/pvr/config.py
index fb920482f5..5f133eba90 100644
--- a/modules/pvr/config.py
+++ b/modules/pvr/config.py
@@ -1,7 +1,5 @@
-
def can_build(platform):
return True
-
def configure(env):
pass
diff --git a/modules/recast/config.py b/modules/recast/config.py
index d42f07b2a9..fc074cf661 100644
--- a/modules/recast/config.py
+++ b/modules/recast/config.py
@@ -1,7 +1,5 @@
-
def can_build(platform):
return platform != "android"
-
def configure(env):
pass
diff --git a/modules/regex/SCsub b/modules/regex/SCsub
index 2bab144a28..18b4051afe 100644
--- a/modules/regex/SCsub
+++ b/modules/regex/SCsub
@@ -8,7 +8,7 @@ env_regex.Append(CPPFLAGS=["-DPCRE2_CODE_UNIT_WIDTH=0"])
env_regex.add_source_files(env.modules_sources, "*.cpp")
if env['builtin_pcre2']:
- jit_blacklist = ['javascript']
+ jit_blacklist = ['javascript', 'uwp']
thirdparty_dir = '#thirdparty/pcre2/src/'
thirdparty_flags = ['-DPCRE2_STATIC', '-DHAVE_CONFIG_H']
if 'platform' in env and env['platform'] not in jit_blacklist:
diff --git a/modules/regex/config.py b/modules/regex/config.py
index 5347cfd243..cb2da26738 100644
--- a/modules/regex/config.py
+++ b/modules/regex/config.py
@@ -1,9 +1,14 @@
-#!/usr/bin/env python
-
-
def can_build(platform):
return True
-
def configure(env):
pass
+
+def get_doc_classes():
+ return [
+ "RegEx",
+ "RegExMatch",
+ ]
+
+def get_doc_path():
+ return "doc_classes"
diff --git a/modules/regex/doc_classes/RegEx.xml b/modules/regex/doc_classes/RegEx.xml
new file mode 100644
index 0000000000..4cf272fe8c
--- /dev/null
+++ b/modules/regex/doc_classes/RegEx.xml
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="RegEx" inherits="Reference" category="Core" version="3.0-alpha">
+ <brief_description>
+ Class for searching text for patterns using regular expressions.
+ </brief_description>
+ <description>
+ Regular Expression (or regex) is a compact programming language that can be used to recognise strings that follow a specific pattern, such as URLs, email addresses, complete sentences, etc. For instance, a regex of [code]ab[0-9][/code] would find any string that is [code]ab[/code] followed by any number from [code]0[/code] to [code]9[/code]. For a more in-depth look, you can easily find various tutorials and detailed explainations on the Internet.
+ To begin, the RegEx object needs to be compiled with the search pattern using [method compile] before it can be used.
+ [codeblock]
+ var regex = RegEx.new()
+ regex.compile("\\w-(\\d+)")
+ [/codeblock]
+ The search pattern must be escaped first for gdscript before it is escaped for the expression. For example, [code]compile("\\d+")[/code] would be read by RegEx as [code]\d+[/code]. Similarly, [code]compile("\"(?:\\\\.|[^\"])*\"")[/code] would be read as [code]"(?:\\.|[^"])*"[/code]
+ Using [method search] you can find the pattern within the given text. If a pattern is found, [RegExMatch] is returned and you can retrieve details of the results using fuctions such as [method RegExMatch.get_string] and [method RegExMatch.get_start].
+ [codeblock]
+ var regex = RegEx.new()
+ regex.compile("\\w-(\\d+)")
+ var result = regex.search("abc n-0123")
+ if result:
+ print(result.get_string()) # Would print n-0123
+ [/codeblock]
+ The results of capturing groups [code]()[/code] can be retrieved by passing the group number to the various functions in [RegExMatch]. Group 0 is the default and would always refer to the entire pattern. In the above example, calling [code]result.get_string(1)[/code] would give you [code]0123[/code].
+ This version of RegEx also supports named capturing groups, and the names can be used to retrieve the results. If two or more groups have the same name, the name would only refer to the first one with a match.
+ [codeblock]
+ var regex = RegEx.new()
+ regex.compile("d(?&lt;digit&gt;[0-9]+)|x(?&lt;digit&gt;[0-9a-f]+)")
+ var result = regex.search("the number is x2f")
+ if result:
+ print(result.get_string("digit")) # Would print 2f
+ [/codeblock]
+ If you need to process multiple results, [method search_all] generates a list of all non-overlapping results. This can be combined with a for-loop for convenience.
+ [codeblock]
+ for result in regex.search_all("d01, d03, d0c, x3f and x42"):
+ print(result.get_string("digit"))
+ # Would print 01 03 3f 42
+ # Note that d0c would not match
+ [/codeblock]
+ </description>
+ <tutorials>
+ </tutorials>
+ <demos>
+ </demos>
+ <methods>
+ <method name="clear">
+ <return type="void">
+ </return>
+ <description>
+ This method resets the state of the object, as it was freshly created. Namely, it unassigns the regular expression of this object.
+ </description>
+ </method>
+ <method name="compile">
+ <return type="int" enum="Error">
+ </return>
+ <argument index="0" name="pattern" type="String">
+ </argument>
+ <description>
+ Compiles and assign the search pattern to use. Returns OK if the compilation is successful. If an error is encountered the details are printed to STDOUT and FAILED is returned.
+ </description>
+ </method>
+ <method name="get_group_count" qualifiers="const">
+ <return type="int">
+ </return>
+ <description>
+ Returns the number of capturing groups in compiled pattern.
+ </description>
+ </method>
+ <method name="get_names" qualifiers="const">
+ <return type="Array">
+ </return>
+ <description>
+ Returns an array of names of named capturing groups in the compiled pattern. They are ordered by appearance.
+ </description>
+ </method>
+ <method name="get_pattern" qualifiers="const">
+ <return type="String">
+ </return>
+ <description>
+ Returns the original search pattern that was compiled.
+ </description>
+ </method>
+ <method name="is_valid" qualifiers="const">
+ <return type="bool">
+ </return>
+ <description>
+ Returns whether this object has a valid search pattern assigned.
+ </description>
+ </method>
+ <method name="search" qualifiers="const">
+ <return type="RegExMatch">
+ </return>
+ <argument index="0" name="subject" type="String">
+ </argument>
+ <argument index="1" name="offset" type="int" default="0">
+ </argument>
+ <argument index="2" name="end" type="int" default="-1">
+ </argument>
+ <description>
+ Searches the text for the compiled pattern. Returns a [RegExMatch] container of the first matching result if found, otherwise null. The region to search within can be specified without modifying where the start and end anchor would be.
+ </description>
+ </method>
+ <method name="search_all" qualifiers="const">
+ <return type="Array">
+ </return>
+ <argument index="0" name="subject" type="String">
+ </argument>
+ <argument index="1" name="offset" type="int" default="0">
+ </argument>
+ <argument index="2" name="end" type="int" default="-1">
+ </argument>
+ <description>
+ Searches the text for the compiled pattern. Returns an array of [RegExMatch] containers for each non-overlapping result. If no results were found an empty array is returned instead. The region to search within can be specified without modifying where the start and end anchor would be.
+ </description>
+ </method>
+ <method name="sub" qualifiers="const">
+ <return type="String">
+ </return>
+ <argument index="0" name="subject" type="String">
+ </argument>
+ <argument index="1" name="replacement" type="String">
+ </argument>
+ <argument index="2" name="all" type="bool" default="false">
+ </argument>
+ <argument index="3" name="offset" type="int" default="0">
+ </argument>
+ <argument index="4" name="end" type="int" default="-1">
+ </argument>
+ <description>
+ Searches the text for the compiled pattern and replaces it with the specified string. Escapes and backreferences such as [code]\1[/code] and [code]\g&lt;name&gt;[/code] expanded and resolved. By default only the first instance is replaced but it can be changed for all instances (global replacement). The region to search within can be specified without modifying where the start and end anchor would be.
+ </description>
+ </method>
+ </methods>
+ <constants>
+ </constants>
+</class>
diff --git a/modules/regex/doc_classes/RegExMatch.xml b/modules/regex/doc_classes/RegExMatch.xml
new file mode 100644
index 0000000000..8c6951fea2
--- /dev/null
+++ b/modules/regex/doc_classes/RegExMatch.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="RegExMatch" inherits="Reference" category="Core" version="3.0-alpha">
+ <brief_description>
+ Contains the results of a regex search.
+ </brief_description>
+ <description>
+ Contains the results of a single regex match returned by [method RegEx.search] and [method RegEx.search_all]. It can be used to find the position and range of the match and its capturing groups, and it can extract its sub-string for you.
+ </description>
+ <tutorials>
+ </tutorials>
+ <demos>
+ </demos>
+ <methods>
+ <method name="get_end" qualifiers="const">
+ <return type="int">
+ </return>
+ <argument index="0" name="name" type="Variant" default="0">
+ </argument>
+ <description>
+ Returns the end position of the match within the source string. The end position of capturing groups can be retrieved by providing its group number as an integer or its string name (if it's a named group). The default value of 0 refers to the whole pattern.
+ Returns -1 if the group did not match or doesn't exist.
+ </description>
+ </method>
+ <method name="get_group_count" qualifiers="const">
+ <return type="int">
+ </return>
+ <description>
+ Returns the number of capturing groups.
+ </description>
+ </method>
+ <method name="get_names" qualifiers="const">
+ <return type="Dictionary">
+ </return>
+ <description>
+ Returns a dictionary of named groups and its corresponding group number. Only groups with that were matched are included. If multiple groups have the same name, that name would refer to the first matching one.
+ </description>
+ </method>
+ <method name="get_start" qualifiers="const">
+ <return type="int">
+ </return>
+ <argument index="0" name="name" type="Variant" default="0">
+ </argument>
+ <description>
+ Returns the starting position of the match within the source string. The starting position of capturing groups can be retrieved by providing its group number as an integer or its string name (if it's a named group). The default value of 0 refers to the whole pattern.
+ Returns -1 if the group did not match or doesn't exist.
+ </description>
+ </method>
+ <method name="get_string" qualifiers="const">
+ <return type="String">
+ </return>
+ <argument index="0" name="name" type="Variant" default="0">
+ </argument>
+ <description>
+ Returns the substring of the match from the source string. Capturing groups can be retrieved by providing its group number as an integer or its string name (if it's a named group). The default value of 0 refers to the whole pattern.
+ Returns an empty string if the group did not match or doesn't exist.
+ </description>
+ </method>
+ <method name="get_strings" qualifiers="const">
+ <return type="Array">
+ </return>
+ <description>
+ Returns an [Array] of the match and its capturing groups.
+ </description>
+ </method>
+ <method name="get_subject" qualifiers="const">
+ <return type="String">
+ </return>
+ <description>
+ Returns the source string used with the search pattern to find this matching result.
+ </description>
+ </method>
+ </methods>
+ <constants>
+ </constants>
+</class>
diff --git a/modules/regex/regex.cpp b/modules/regex/regex.cpp
index 00e8ce0f54..daadfcc659 100644
--- a/modules/regex/regex.cpp
+++ b/modules/regex/regex.cpp
@@ -324,6 +324,21 @@ Ref<RegExMatch> RegEx::search(const String &p_subject, int p_offset, int p_end)
return result;
}
+Array RegEx::search_all(const String &p_subject, int p_offset, int p_end) const {
+
+ int last_end = -1;
+ Array result;
+ Ref<RegExMatch> match = search(p_subject, p_offset, p_end);
+ while (match.is_valid()) {
+ if (last_end == match->get_end(0))
+ break;
+ result.push_back(match);
+ last_end = match->get_end(0);
+ match = search(p_subject, match->get_end(0), p_end);
+ }
+ return result;
+}
+
String RegEx::sub(const String &p_subject, const String &p_replacement, bool p_all, int p_offset, int p_end) const {
ERR_FAIL_COND_V(!is_valid(), String());
@@ -489,6 +504,7 @@ void RegEx::_bind_methods() {
ClassDB::bind_method(D_METHOD("clear"), &RegEx::clear);
ClassDB::bind_method(D_METHOD("compile", "pattern"), &RegEx::compile);
ClassDB::bind_method(D_METHOD("search", "subject", "offset", "end"), &RegEx::search, DEFVAL(0), DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("search_all", "subject", "offset", "end"), &RegEx::search_all, DEFVAL(0), DEFVAL(-1));
ClassDB::bind_method(D_METHOD("sub", "subject", "replacement", "all", "offset", "end"), &RegEx::sub, DEFVAL(false), DEFVAL(0), DEFVAL(-1));
ClassDB::bind_method(D_METHOD("is_valid"), &RegEx::is_valid);
ClassDB::bind_method(D_METHOD("get_pattern"), &RegEx::get_pattern);
diff --git a/modules/regex/regex.h b/modules/regex/regex.h
index bfa9c84042..21387222f2 100644
--- a/modules/regex/regex.h
+++ b/modules/regex/regex.h
@@ -88,6 +88,7 @@ public:
void _init(const String &p_pattern = "");
Ref<RegExMatch> search(const String &p_subject, int p_offset = 0, int p_end = -1) const;
+ Array search_all(const String &p_subject, int p_offset = 0, int p_end = -1) const;
String sub(const String &p_subject, const String &p_replacement, bool p_all = false, int p_offset = 0, int p_end = -1) const;
bool is_valid() const;
diff --git a/modules/squish/config.py b/modules/squish/config.py
index 9b7729bda4..97c95999c8 100644
--- a/modules/squish/config.py
+++ b/modules/squish/config.py
@@ -1,8 +1,6 @@
-
def can_build(platform):
return True
-
def configure(env):
# Tools only, disabled for non-tools
# TODO: Find a cleaner way to achieve that
diff --git a/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp b/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp
index 27ea310780..5c252bda86 100644
--- a/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp
+++ b/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp
@@ -129,7 +129,6 @@ AudioStreamPlaybackOGGVorbis::~AudioStreamPlaybackOGGVorbis() {
Ref<AudioStreamPlayback> AudioStreamOGGVorbis::instance_playback() {
Ref<AudioStreamPlaybackOGGVorbis> ovs;
- printf("instance at %p, data %p\n", this, data);
ERR_FAIL_COND_V(data == NULL, ovs);
@@ -208,8 +207,6 @@ void AudioStreamOGGVorbis::set_data(const PoolVector<uint8_t> &p_data) {
break;
}
}
-
- printf("create at %p, data %p\n", this, data);
}
PoolVector<uint8_t> AudioStreamOGGVorbis::get_data() const {
diff --git a/modules/stb_vorbis/config.py b/modules/stb_vorbis/config.py
index fb920482f5..defe8d0c94 100644
--- a/modules/stb_vorbis/config.py
+++ b/modules/stb_vorbis/config.py
@@ -1,7 +1,14 @@
-
def can_build(platform):
return True
-
def configure(env):
pass
+
+def get_doc_classes():
+ return [
+ "AudioStreamOGGVorbis",
+ "ResourceImporterOGGVorbis",
+ ]
+
+def get_doc_path():
+ return "doc_classes"
diff --git a/doc/classes/AudioStreamOGGVorbis.xml b/modules/stb_vorbis/doc_classes/AudioStreamOGGVorbis.xml
index 679438b66b..ee6c28c36a 100644
--- a/doc/classes/AudioStreamOGGVorbis.xml
+++ b/modules/stb_vorbis/doc_classes/AudioStreamOGGVorbis.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AudioStreamOGGVorbis" inherits="AudioStream" category="Core" version="3.0.alpha.custom_build">
+<class name="AudioStreamOGGVorbis" inherits="AudioStream" category="Core" version="3.0-alpha">
<brief_description>
OGG Vorbis audio stream driver.
</brief_description>
diff --git a/doc/classes/ResourceImporterOGGVorbis.xml b/modules/stb_vorbis/doc_classes/ResourceImporterOGGVorbis.xml
index eef626cee7..ce16632d6e 100644
--- a/doc/classes/ResourceImporterOGGVorbis.xml
+++ b/modules/stb_vorbis/doc_classes/ResourceImporterOGGVorbis.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ResourceImporterOGGVorbis" inherits="ResourceImporter" category="Core" version="3.0.alpha.custom_build">
+<class name="ResourceImporterOGGVorbis" inherits="ResourceImporter" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/modules/svg/config.py b/modules/svg/config.py
index fb920482f5..5f133eba90 100644
--- a/modules/svg/config.py
+++ b/modules/svg/config.py
@@ -1,7 +1,5 @@
-
def can_build(platform):
return True
-
def configure(env):
pass
diff --git a/modules/tga/config.py b/modules/tga/config.py
index fb920482f5..5f133eba90 100644
--- a/modules/tga/config.py
+++ b/modules/tga/config.py
@@ -1,7 +1,5 @@
-
def can_build(platform):
return True
-
def configure(env):
pass
diff --git a/modules/theora/config.py b/modules/theora/config.py
index 8eefe81288..34d34f8be2 100644
--- a/modules/theora/config.py
+++ b/modules/theora/config.py
@@ -1,8 +1,14 @@
-
def can_build(platform):
-# return True
- return False
-
+ return True
def configure(env):
pass
+
+def get_doc_classes():
+ return [
+ "ResourceImporterTheora",
+ "VideoStreamTheora",
+ ]
+
+def get_doc_path():
+ return "doc_classes"
diff --git a/doc/classes/VisualScriptWhile.xml b/modules/theora/doc_classes/ResourceImporterTheora.xml
index b49678582e..497c938826 100644
--- a/doc/classes/VisualScriptWhile.xml
+++ b/modules/theora/doc_classes/ResourceImporterTheora.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptWhile" inherits="VisualScriptNode" category="Core" version="3.0.alpha.custom_build">
+<class name="ResourceImporterTheora" inherits="ResourceImporter" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/modules/theora/doc_classes/VideoStreamTheora.xml b/modules/theora/doc_classes/VideoStreamTheora.xml
new file mode 100644
index 0000000000..8f155b786f
--- /dev/null
+++ b/modules/theora/doc_classes/VideoStreamTheora.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="VideoStreamTheora" inherits="VideoStream" category="Core" version="3.0-alpha">
+ <brief_description>
+ </brief_description>
+ <description>
+ </description>
+ <tutorials>
+ </tutorials>
+ <demos>
+ </demos>
+ <methods>
+ <method name="get_file">
+ <return type="String">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="set_file">
+ <return type="void">
+ </return>
+ <argument index="0" name="file" type="String">
+ </argument>
+ <description>
+ </description>
+ </method>
+ </methods>
+ <members>
+ <member name="file" type="String" setter="set_file" getter="get_file">
+ </member>
+ </members>
+ <constants>
+ </constants>
+</class>
diff --git a/modules/theora/register_types.cpp b/modules/theora/register_types.cpp
index ae6961b3da..c51b87b8fc 100644
--- a/modules/theora/register_types.cpp
+++ b/modules/theora/register_types.cpp
@@ -28,19 +28,18 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "register_types.h"
-
+#include "resource_importer_theora.h"
#include "video_stream_theora.h"
-static ResourceFormatLoaderVideoStreamTheora *theora_stream_loader = NULL;
-
void register_theora_types() {
- theora_stream_loader = memnew(ResourceFormatLoaderVideoStreamTheora);
- ResourceLoader::add_resource_format_loader(theora_stream_loader);
+#ifdef TOOLS_ENABLED
+ Ref<ResourceImporterTheora> theora_import;
+ theora_import.instance();
+ ResourceFormatImporter::get_singleton()->add_importer(theora_import);
+#endif
ClassDB::register_class<VideoStreamTheora>();
}
void unregister_theora_types() {
-
- memdelete(theora_stream_loader);
}
diff --git a/modules/theora/resource_importer_theora.cpp b/modules/theora/resource_importer_theora.cpp
new file mode 100644
index 0000000000..c25c0e7427
--- /dev/null
+++ b/modules/theora/resource_importer_theora.cpp
@@ -0,0 +1,89 @@
+/*************************************************************************/
+/* resource_importer_theora.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#include "resource_importer_theora.h"
+
+#include "io/resource_saver.h"
+#include "os/file_access.h"
+#include "scene/resources/texture.h"
+
+String ResourceImporterTheora::get_importer_name() const {
+
+ return "Theora";
+}
+
+String ResourceImporterTheora::get_visible_name() const {
+
+ return "Theora";
+}
+void ResourceImporterTheora::get_recognized_extensions(List<String> *p_extensions) const {
+
+ p_extensions->push_back("ogv");
+ p_extensions->push_back("ogm");
+}
+
+String ResourceImporterTheora::get_save_extension() const {
+ return "ogvstr";
+}
+
+String ResourceImporterTheora::get_resource_type() const {
+
+ return "VideoStreamTheora";
+}
+
+bool ResourceImporterTheora::get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const {
+
+ return true;
+}
+
+int ResourceImporterTheora::get_preset_count() const {
+ return 0;
+}
+String ResourceImporterTheora::get_preset_name(int p_idx) const {
+
+ return String();
+}
+
+void ResourceImporterTheora::get_import_options(List<ImportOption> *r_options, int p_preset) const {
+
+ r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "loop"), true));
+}
+
+Error ResourceImporterTheora::import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files) {
+
+ VideoStreamTheora *stream = memnew(VideoStreamTheora);
+ stream->set_file(p_source_file);
+
+ Ref<VideoStreamTheora> ogv_stream = Ref<VideoStreamTheora>(stream);
+
+ return ResourceSaver::save(p_save_path + ".ogvstr", ogv_stream);
+}
+
+ResourceImporterTheora::ResourceImporterTheora() {
+}
diff --git a/modules/theora/resource_importer_theora.h b/modules/theora/resource_importer_theora.h
new file mode 100644
index 0000000000..8bf0ad38c4
--- /dev/null
+++ b/modules/theora/resource_importer_theora.h
@@ -0,0 +1,57 @@
+/*************************************************************************/
+/* resource_importer_theora.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#ifndef RESOURCEIMPORTEROGGTHEORA_H
+#define RESOURCEIMPORTEROGGTHEORA_H
+
+#include "video_stream_theora.h"
+
+#include "core/io/resource_import.h"
+
+class ResourceImporterTheora : public ResourceImporter {
+ GDCLASS(ResourceImporterTheora, ResourceImporter)
+public:
+ virtual String get_importer_name() const;
+ virtual String get_visible_name() const;
+ virtual void get_recognized_extensions(List<String> *p_extensions) const;
+ virtual String get_save_extension() const;
+ virtual String get_resource_type() const;
+
+ virtual int get_preset_count() const;
+ virtual String get_preset_name(int p_idx) const;
+
+ virtual void get_import_options(List<ImportOption> *r_options, int p_preset = 0) const;
+ virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const;
+
+ virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = NULL);
+
+ ResourceImporterTheora();
+};
+
+#endif // RESOURCEIMPORTEROGGTHEORA_H
diff --git a/modules/theora/video_stream_theora.cpp b/modules/theora/video_stream_theora.cpp
index c75bec31df..bc8ca23d60 100644
--- a/modules/theora/video_stream_theora.cpp
+++ b/modules/theora/video_stream_theora.cpp
@@ -406,20 +406,19 @@ void VideoStreamPlaybackTheora::update(float p_delta) {
ogg_packet op;
bool no_theora = false;
+ bool buffer_full = false;
- while (vorbis_p) {
+ while (vorbis_p && !audio_done && !buffer_full) {
int ret;
float **pcm;
- bool buffer_full = false;
-
/* if there's pending, decoded audio, grab it */
ret = vorbis_synthesis_pcmout(&vd, &pcm);
if (ret > 0) {
const int AUXBUF_LEN = 4096;
int to_read = ret;
- int16_t aux_buffer[AUXBUF_LEN];
+ float aux_buffer[AUXBUF_LEN];
while (to_read) {
@@ -429,11 +428,7 @@ void VideoStreamPlaybackTheora::update(float p_delta) {
for (int j = 0; j < m; j++) {
for (int i = 0; i < vi.channels; i++) {
-
- int val = Math::fast_ftoi(pcm[i][j] * 32767.f);
- if (val > 32767) val = 32767;
- if (val < -32768) val = -32768;
- aux_buffer[count++] = val;
+ aux_buffer[count++] = pcm[i][j];
}
}
@@ -602,10 +597,9 @@ bool VideoStreamPlaybackTheora::is_playing() const {
void VideoStreamPlaybackTheora::set_paused(bool p_paused) {
paused = p_paused;
- //pau = !p_paused;
};
-bool VideoStreamPlaybackTheora::is_paused(bool p_paused) const {
+bool VideoStreamPlaybackTheora::is_paused() const {
return paused;
};
@@ -733,32 +727,10 @@ VideoStreamPlaybackTheora::~VideoStreamPlaybackTheora() {
memdelete(file);
};
-RES ResourceFormatLoaderVideoStreamTheora::load(const String &p_path, const String &p_original_path, Error *r_error) {
- if (r_error)
- *r_error = ERR_FILE_CANT_OPEN;
-
- VideoStreamTheora *stream = memnew(VideoStreamTheora);
- stream->set_file(p_path);
-
- if (r_error)
- *r_error = OK;
-
- return Ref<VideoStreamTheora>(stream);
-}
+void VideoStreamTheora::_bind_methods() {
-void ResourceFormatLoaderVideoStreamTheora::get_recognized_extensions(List<String> *p_extensions) const {
+ ClassDB::bind_method(D_METHOD("set_file", "file"), &VideoStreamTheora::set_file);
+ ClassDB::bind_method(D_METHOD("get_file"), &VideoStreamTheora::get_file);
- p_extensions->push_back("ogm");
- p_extensions->push_back("ogv");
-}
-bool ResourceFormatLoaderVideoStreamTheora::handles_type(const String &p_type) const {
- return (p_type == "VideoStream" || p_type == "VideoStreamTheora");
-}
-
-String ResourceFormatLoaderVideoStreamTheora::get_resource_type(const String &p_path) const {
-
- String exl = p_path.get_extension().to_lower();
- if (exl == "ogm" || exl == "ogv")
- return "VideoStreamTheora";
- return "";
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "file", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_file", "get_file");
}
diff --git a/modules/theora/video_stream_theora.h b/modules/theora/video_stream_theora.h
index 484a1a7fb9..ec0e5aa34a 100644
--- a/modules/theora/video_stream_theora.h
+++ b/modules/theora/video_stream_theora.h
@@ -36,6 +36,7 @@
#include "os/thread.h"
#include "ring_buffer.h"
#include "scene/resources/video_stream.h"
+#include "servers/audio_server.h"
#include <theora/theoradec.h>
#include <vorbis/codec.h>
@@ -129,7 +130,7 @@ public:
virtual bool is_playing() const;
virtual void set_paused(bool p_paused);
- virtual bool is_paused(bool p_paused) const;
+ virtual bool is_paused() const;
virtual void set_loop(bool p_enable);
virtual bool has_loop() const;
@@ -161,10 +162,14 @@ public:
class VideoStreamTheora : public VideoStream {
GDCLASS(VideoStreamTheora, VideoStream);
+ RES_BASE_EXTENSION("ogvstr");
String file;
int audio_track;
+protected:
+ static void _bind_methods();
+
public:
Ref<VideoStreamPlayback> instance_playback() {
Ref<VideoStreamPlaybackTheora> pb = memnew(VideoStreamPlaybackTheora);
@@ -174,17 +179,10 @@ public:
}
void set_file(const String &p_file) { file = p_file; }
+ String get_file() { return file; }
void set_audio_track(int p_track) { audio_track = p_track; }
VideoStreamTheora() { audio_track = 0; }
};
-class ResourceFormatLoaderVideoStreamTheora : public ResourceFormatLoader {
-public:
- virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = NULL);
- virtual void get_recognized_extensions(List<String> *p_extensions) const;
- virtual bool handles_type(const String &p_type) const;
- virtual String get_resource_type(const String &p_path) const;
-};
-
#endif
diff --git a/modules/tinyexr/config.py b/modules/tinyexr/config.py
index 3e16fd725e..e12bb398ce 100644
--- a/modules/tinyexr/config.py
+++ b/modules/tinyexr/config.py
@@ -1,8 +1,6 @@
-
def can_build(platform):
return True
-
def configure(env):
# Tools only, disabled for non-tools
# TODO: Find a cleaner way to achieve that
diff --git a/modules/visual_script/config.py b/modules/visual_script/config.py
index 5698a37295..6b1ce41014 100644
--- a/modules/visual_script/config.py
+++ b/modules/visual_script/config.py
@@ -1,8 +1,57 @@
-
-
def can_build(platform):
return True
-
def configure(env):
pass
+
+def get_doc_classes():
+ return [
+ "VisualScriptBasicTypeConstant",
+ "VisualScriptBuiltinFunc",
+ "VisualScriptClassConstant",
+ "VisualScriptComment",
+ "VisualScriptCondition",
+ "VisualScriptConstant",
+ "VisualScriptConstructor",
+ "VisualScriptCustomNode",
+ "VisualScriptDeconstruct",
+ "VisualScriptEditor",
+ "VisualScriptEmitSignal",
+ "VisualScriptEngineSingleton",
+ "VisualScriptExpression",
+ "VisualScriptFunctionCall",
+ "VisualScriptFunctionState",
+ "VisualScriptFunction",
+ "VisualScriptGlobalConstant",
+ "VisualScriptIndexGet",
+ "VisualScriptIndexSet",
+ "VisualScriptInputAction",
+ "VisualScriptIterator",
+ "VisualScriptLocalVarSet",
+ "VisualScriptLocalVar",
+ "VisualScriptMathConstant",
+ "VisualScriptNode",
+ "VisualScriptOperator",
+ "VisualScriptPreload",
+ "VisualScriptPropertyGet",
+ "VisualScriptPropertySet",
+ "VisualScriptResourcePath",
+ "VisualScriptReturn",
+ "VisualScriptSceneNode",
+ "VisualScriptSceneTree",
+ "VisualScriptSelect",
+ "VisualScriptSelf",
+ "VisualScriptSequence",
+ "VisualScriptSubCall",
+ "VisualScriptSwitch",
+ "VisualScriptTypeCast",
+ "VisualScriptVariableGet",
+ "VisualScriptVariableSet",
+ "VisualScriptWhile",
+ "VisualScript",
+ "VisualScriptYieldSignal",
+ "VisualScriptYield",
+ ]
+
+def get_doc_path():
+ return "doc_classes"
diff --git a/doc/classes/VisualScript.xml b/modules/visual_script/doc_classes/VisualScript.xml
index e44547cd8f..80b1ed86d7 100644
--- a/doc/classes/VisualScript.xml
+++ b/modules/visual_script/doc_classes/VisualScript.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScript" inherits="Script" category="Core" version="3.0.alpha.custom_build">
+<class name="VisualScript" inherits="Script" category="Core" version="3.0-alpha">
<brief_description>
A script implemented in the Visual Script programming environment.
</brief_description>
<description>
- A script implemented in the Visual Script programming environment. The script exends the functionality of all objects that instance it.
+ A script implemented in the Visual Script programming environment. The script extends the functionality of all objects that instance it.
[method Object.set_script] extends an existing object, if that object's class matches one of the script's base classes.
You are most likely to use this class via the Visual Script editor or when writing plugins for it.
</description>
diff --git a/doc/classes/VisualScriptBasicTypeConstant.xml b/modules/visual_script/doc_classes/VisualScriptBasicTypeConstant.xml
index cc09815481..6c028e5f28 100644
--- a/doc/classes/VisualScriptBasicTypeConstant.xml
+++ b/modules/visual_script/doc_classes/VisualScriptBasicTypeConstant.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptBasicTypeConstant" inherits="VisualScriptNode" category="Core" version="3.0.alpha.custom_build">
+<class name="VisualScriptBasicTypeConstant" inherits="VisualScriptNode" category="Core" version="3.0-alpha">
<brief_description>
A Visual Script node representing a constant from the base types.
</brief_description>
diff --git a/doc/classes/VisualScriptBuiltinFunc.xml b/modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml
index f48f5a5308..c45c8d2b64 100644
--- a/doc/classes/VisualScriptBuiltinFunc.xml
+++ b/modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptBuiltinFunc" inherits="VisualScriptNode" category="Core" version="3.0.alpha.custom_build">
+<class name="VisualScriptBuiltinFunc" inherits="VisualScriptNode" category="Core" version="3.0-alpha">
<brief_description>
A Visual Script node used to call built-in functions.
</brief_description>
@@ -114,97 +114,111 @@
<constant name="MATH_LERP" value="26">
Return a number linearly interpolated between the first two inputs, based on the third input. Uses the formula [code]a + (a - b) * t[/code].
</constant>
- <constant name="MATH_DECTIME" value="27">
+ <constant name="MATH_INVERSE_LERP" value="27">
+ </constant>
+ <constant name="MATH_RANGE_LERP" value="28">
+ </constant>
+ <constant name="MATH_DECTIME" value="29">
Return the result of 'value' decreased by 'step' * 'amount'.
</constant>
- <constant name="MATH_RANDOMIZE" value="28">
+ <constant name="MATH_RANDOMIZE" value="30">
Randomize the seed (or the internal state) of the random number generator. Current implementation reseeds using a number based on time.
</constant>
- <constant name="MATH_RAND" value="29">
+ <constant name="MATH_RAND" value="31">
Return a random 32 bits integer value. To obtain a random value between 0 to N (where N is smaller than 2^32 - 1), you can use it with the remainder function.
</constant>
- <constant name="MATH_RANDF" value="30">
+ <constant name="MATH_RANDF" value="32">
Return a random floating-point value between 0 and 1. To obtain a random value between 0 to N, you can use it with multiplication.
</constant>
- <constant name="MATH_RANDOM" value="31">
+ <constant name="MATH_RANDOM" value="33">
Return a random floating-point value between the two inputs.
</constant>
- <constant name="MATH_SEED" value="32">
+ <constant name="MATH_SEED" value="34">
Set the seed for the random number generator.
</constant>
- <constant name="MATH_RANDSEED" value="33">
+ <constant name="MATH_RANDSEED" value="35">
Return a random value from the given seed, along with the new seed.
</constant>
- <constant name="MATH_DEG2RAD" value="34">
+ <constant name="MATH_DEG2RAD" value="36">
Convert the input from degrees to radians.
</constant>
- <constant name="MATH_RAD2DEG" value="35">
+ <constant name="MATH_RAD2DEG" value="37">
Convert the input from radians to degrees.
</constant>
- <constant name="MATH_LINEAR2DB" value="36">
+ <constant name="MATH_LINEAR2DB" value="38">
Convert the input from linear volume to decibel volume.
</constant>
- <constant name="MATH_DB2LINEAR" value="37">
+ <constant name="MATH_DB2LINEAR" value="39">
Convert the input from decibel volume to linear volume.
</constant>
- <constant name="LOGIC_MAX" value="38">
+ <constant name="MATH_POLAR2CARTESIAN" value="40">
+ Converts a 2D point expressed in the polar coordinate system (a distance from the origin [code]r[/code] and an angle [code]th[/code]) to the cartesian coordinate system (x and y axis).
+ </constant>
+ <constant name="MATH_CARTESIAN2POLAR" value="41">
+ Converts a 2D point expressed in the cartesian coordinate system (x and y axis) to the polar coordinate system (a distance from the origin and an angle).
+ </constant>
+ <constant name="MATH_WRAP" value="42">
+ </constant>
+ <constant name="MATH_WRAPF" value="43">
+ </constant>
+ <constant name="LOGIC_MAX" value="44">
Return the greater of the two numbers, also known as their maximum.
</constant>
- <constant name="LOGIC_MIN" value="39">
+ <constant name="LOGIC_MIN" value="45">
Return the lesser of the two numbers, also known as their minimum.
</constant>
- <constant name="LOGIC_CLAMP" value="40">
+ <constant name="LOGIC_CLAMP" value="46">
Return the input clamped inside the given range, ensuring the result is never outside it. Equivalent to `min(max(input, range_low), range_high)`
</constant>
- <constant name="LOGIC_NEAREST_PO2" value="41">
+ <constant name="LOGIC_NEAREST_PO2" value="46">
Return the nearest power of 2 to the input.
</constant>
- <constant name="OBJ_WEAKREF" value="42">
+ <constant name="OBJ_WEAKREF" value="47">
Create a [WeakRef] from the input.
</constant>
- <constant name="FUNC_FUNCREF" value="43">
+ <constant name="FUNC_FUNCREF" value="48">
Create a [FuncRef] from the input.
</constant>
- <constant name="TYPE_CONVERT" value="44">
+ <constant name="TYPE_CONVERT" value="49">
Convert between types.
</constant>
- <constant name="TYPE_OF" value="45">
+ <constant name="TYPE_OF" value="50">
Return the type of the input as an integer. Check [enum Variant.Type] for the integers that might be returned.
</constant>
- <constant name="TYPE_EXISTS" value="46">
+ <constant name="TYPE_EXISTS" value="51">
Checks if a type is registered in the [ClassDB].
</constant>
- <constant name="TEXT_CHAR" value="47">
+ <constant name="TEXT_CHAR" value="52">
Return a character with the given ascii value.
</constant>
- <constant name="TEXT_STR" value="48">
+ <constant name="TEXT_STR" value="53">
Convert the input to a string.
</constant>
- <constant name="TEXT_PRINT" value="49">
+ <constant name="TEXT_PRINT" value="54">
Print the given string to the output window.
</constant>
- <constant name="TEXT_PRINTERR" value="50">
+ <constant name="TEXT_PRINTERR" value="55">
Print the given string to the standard error output.
</constant>
- <constant name="TEXT_PRINTRAW" value="51">
+ <constant name="TEXT_PRINTRAW" value="56">
Print the given string to the standard output, without adding a newline.
</constant>
- <constant name="VAR_TO_STR" value="52">
+ <constant name="VAR_TO_STR" value="57">
Serialize a [Variant] to a string.
</constant>
- <constant name="STR_TO_VAR" value="53">
+ <constant name="STR_TO_VAR" value="58">
Deserialize a [Variant] from a string serialized using [VAR_TO_STR].
</constant>
- <constant name="VAR_TO_BYTES" value="54">
+ <constant name="VAR_TO_BYTES" value="59">
Serialize a [Variant] to a [PoolByteArray].
</constant>
- <constant name="BYTES_TO_VAR" value="55">
+ <constant name="BYTES_TO_VAR" value="60">
Deserialize a [Variant] from a [PoolByteArray] serialized using [VAR_TO_BYTES].
</constant>
- <constant name="COLORN" value="56">
+ <constant name="COLORN" value="61">
Return the [Color] with the given name and alpha ranging from 0 to 1. Note: names are defined in color_names.inc.
</constant>
- <constant name="FUNC_MAX" value="57">
+ <constant name="FUNC_MAX" value="62">
The maximum value the [member function] property can have.
</constant>
</constants>
diff --git a/doc/classes/VisualScriptClassConstant.xml b/modules/visual_script/doc_classes/VisualScriptClassConstant.xml
index 70e7de5dd9..e6498e92ad 100644
--- a/doc/classes/VisualScriptClassConstant.xml
+++ b/modules/visual_script/doc_classes/VisualScriptClassConstant.xml
@@ -1,10 +1,14 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptClassConstant" inherits="VisualScriptNode" category="Core" version="3.0.alpha.custom_build">
+<class name="VisualScriptClassConstant" inherits="VisualScriptNode" category="Core" version="3.0-alpha">
<brief_description>
- A Visual Script node representing a constant from a class.
+ Gets a constant from a given class.
</brief_description>
<description>
- A Visual Script node representing a constant from the classes, such as [@GlobalScope.TYPE_INT].
+ This node returns a constant from a given class, such as [@GlobalScope.TYPE_INT]. See the given class' documentation for available constants.
+ [b]Input Ports:[/b]
+ none
+ [b]Output Ports:[/b]
+ - Data (variant): [code]value[/code]
</description>
<tutorials>
</tutorials>
@@ -42,10 +46,10 @@
</methods>
<members>
<member name="base_type" type="String" setter="set_base_type" getter="get_base_type">
- The type to get the constant from.
+ The constant's parent class.
</member>
<member name="constant" type="String" setter="set_class_constant" getter="get_class_constant">
- The name of the constant to return.
+ The constant to return. See the given class for its available constants.
</member>
</members>
<constants>
diff --git a/doc/classes/VisualScriptComment.xml b/modules/visual_script/doc_classes/VisualScriptComment.xml
index da65998e78..ea4545f8ef 100644
--- a/doc/classes/VisualScriptComment.xml
+++ b/modules/visual_script/doc_classes/VisualScriptComment.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptComment" inherits="VisualScriptNode" category="Core" version="3.0.alpha.custom_build">
+<class name="VisualScriptComment" inherits="VisualScriptNode" category="Core" version="3.0-alpha">
<brief_description>
- A Visual Script node used to store information for the developer.
+ A Visual Script node used to annotate the script.
</brief_description>
<description>
- A Visual Script node used to display text, so that code is more readable and better documented.
+ A Visual Script node used to display annotations in the script, so that code may be documented.
Comment nodes can be resized so they encompass a group of nodes.
</description>
<tutorials>
@@ -60,10 +60,10 @@
The text inside the comment node.
</member>
<member name="size" type="Vector2" setter="set_size" getter="get_size">
- The size (in pixels) of the comment node.
+ The comment node's size (in pixels).
</member>
<member name="title" type="String" setter="set_title" getter="get_title">
- The title of the comment node.
+ The comment node's title.
</member>
</members>
<constants>
diff --git a/modules/visual_script/doc_classes/VisualScriptCondition.xml b/modules/visual_script/doc_classes/VisualScriptCondition.xml
new file mode 100644
index 0000000000..2a30c604a5
--- /dev/null
+++ b/modules/visual_script/doc_classes/VisualScriptCondition.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="VisualScriptCondition" inherits="VisualScriptNode" category="Core" version="3.0-alpha">
+ <brief_description>
+ A Visual Script node which branches the flow.
+ </brief_description>
+ <description>
+ A Visual Script node that checks a [bool] input port. If [code]true[/code] it will exit via the “true†sequence port. If [code]false[/code] it will exit via the "false" sequence port. After exiting either, it exits via the “done†port. Sequence ports may be left disconnected.
+ [b]Input Ports:[/b]
+ - Sequence: [code]if (cond) is[/code]
+ - Data (boolean): [code]cond[/code]
+ [b]Output Ports:[/b]
+ - Sequence: [code]true[/code]
+ - Sequence: [code]false[/code]
+ - Sequence: [code]done[/code]
+ </description>
+ <tutorials>
+ </tutorials>
+ <demos>
+ </demos>
+ <methods>
+ </methods>
+ <constants>
+ </constants>
+</class>
diff --git a/doc/classes/VisualScriptConstant.xml b/modules/visual_script/doc_classes/VisualScriptConstant.xml
index 508087a928..51c6d19238 100644
--- a/doc/classes/VisualScriptConstant.xml
+++ b/modules/visual_script/doc_classes/VisualScriptConstant.xml
@@ -1,10 +1,14 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptConstant" inherits="VisualScriptNode" category="Core" version="3.0.alpha.custom_build">
+<class name="VisualScriptConstant" inherits="VisualScriptNode" category="Core" version="3.0-alpha">
<brief_description>
- A Visual Script node which returns a constant value.
+ Gets a contant's value.
</brief_description>
<description>
- A Visual Script node which returns the specified constant value.
+ This node returns a constant's value.
+ [b]Input Ports:[/b]
+ none
+ [b]Output Ports:[/b]
+ - Data (variant): [code]get[/code]
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/VisualScriptConstructor.xml b/modules/visual_script/doc_classes/VisualScriptConstructor.xml
index 3b1fc5e385..91df52e893 100644
--- a/doc/classes/VisualScriptConstructor.xml
+++ b/modules/visual_script/doc_classes/VisualScriptConstructor.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptConstructor" inherits="VisualScriptNode" category="Core" version="3.0.alpha.custom_build">
+<class name="VisualScriptConstructor" inherits="VisualScriptNode" category="Core" version="3.0-alpha">
<brief_description>
A Visual Script node which calls a base type constructor.
</brief_description>
diff --git a/doc/classes/VisualScriptCustomNode.xml b/modules/visual_script/doc_classes/VisualScriptCustomNode.xml
index e321c8854a..38c325cfb7 100644
--- a/doc/classes/VisualScriptCustomNode.xml
+++ b/modules/visual_script/doc_classes/VisualScriptCustomNode.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptCustomNode" inherits="VisualScriptNode" category="Core" version="3.0.alpha.custom_build">
+<class name="VisualScriptCustomNode" inherits="VisualScriptNode" category="Core" version="3.0-alpha">
<brief_description>
A scripted Visual Script node.
</brief_description>
diff --git a/doc/classes/VisualScriptDeconstruct.xml b/modules/visual_script/doc_classes/VisualScriptDeconstruct.xml
index cd7d79ae56..cbed3ba22c 100644
--- a/doc/classes/VisualScriptDeconstruct.xml
+++ b/modules/visual_script/doc_classes/VisualScriptDeconstruct.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptDeconstruct" inherits="VisualScriptNode" category="Core" version="3.0.alpha.custom_build">
+<class name="VisualScriptDeconstruct" inherits="VisualScriptNode" category="Core" version="3.0-alpha">
<brief_description>
A Visual Script node which deconstructs a base type instance into its parts.
</brief_description>
diff --git a/modules/visual_script/doc_classes/VisualScriptEditor.xml b/modules/visual_script/doc_classes/VisualScriptEditor.xml
new file mode 100644
index 0000000000..70d52b2bd7
--- /dev/null
+++ b/modules/visual_script/doc_classes/VisualScriptEditor.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="VisualScriptEditor" inherits="Object" category="Core" version="3.0.alpha.custom_build">
+ <brief_description>
+ </brief_description>
+ <description>
+ </description>
+ <tutorials>
+ </tutorials>
+ <demos>
+ </demos>
+ <methods>
+ <method name="add_custom_node">
+ <return type="void">
+ </return>
+ <argument index="0" name="name" type="String">
+ </argument>
+ <argument index="1" name="category" type="String">
+ </argument>
+ <argument index="2" name="script" type="Script">
+ </argument>
+ <description>
+ Add a custom Visual Script node to the editor. It'll be placed under "Custom Nodes" with the [code]category[/code] as the parameter.
+ </description>
+ </method>
+ <method name="remove_custom_node">
+ <return type="void">
+ </return>
+ <argument index="0" name="name" type="String">
+ </argument>
+ <argument index="1" name="category" type="String">
+ </argument>
+ <description>
+ Remove a custom Visual Script node from the editor. Custom nodes already placed on scripts won't be removed.
+ </description>
+ </method>
+ </methods>
+ <signals>
+ <signal name="custom_nodes_updated">
+ <description>
+ Emitted when a custom Visual Script node is added or removed.
+ </description>
+ </signal>
+ </signals>
+ <constants>
+ </constants>
+</class>
diff --git a/doc/classes/VisualScriptEmitSignal.xml b/modules/visual_script/doc_classes/VisualScriptEmitSignal.xml
index 844b5a40ec..669276f0d0 100644
--- a/doc/classes/VisualScriptEmitSignal.xml
+++ b/modules/visual_script/doc_classes/VisualScriptEmitSignal.xml
@@ -1,10 +1,14 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptEmitSignal" inherits="VisualScriptNode" category="Core" version="3.0.alpha.custom_build">
+<class name="VisualScriptEmitSignal" inherits="VisualScriptNode" category="Core" version="3.0-alpha">
<brief_description>
- A Visual Script node which emits a specified signal.
+ Emits a specified signal.
</brief_description>
<description>
- A Visual Script node which emits a specified signal when it is executed.
+ Emits a specified signal when it is executed.
+ [b]Input Ports:[/b]
+ - Sequence: [code]emit[/code]
+ [b]Output Ports:[/b]
+ - Sequence
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/VisualScriptEngineSingleton.xml b/modules/visual_script/doc_classes/VisualScriptEngineSingleton.xml
index 6606f10f11..6703ff4eda 100644
--- a/doc/classes/VisualScriptEngineSingleton.xml
+++ b/modules/visual_script/doc_classes/VisualScriptEngineSingleton.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptEngineSingleton" inherits="VisualScriptNode" category="Core" version="3.0.alpha.custom_build">
+<class name="VisualScriptEngineSingleton" inherits="VisualScriptNode" category="Core" version="3.0-alpha">
<brief_description>
A Visual Script node returning a singleton from [@GlobalScope]
</brief_description>
diff --git a/doc/classes/VisualScriptExpression.xml b/modules/visual_script/doc_classes/VisualScriptExpression.xml
index 1ca943a8a8..fb3b6ef19d 100644
--- a/doc/classes/VisualScriptExpression.xml
+++ b/modules/visual_script/doc_classes/VisualScriptExpression.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptExpression" inherits="VisualScriptNode" category="Core" version="3.0.alpha.custom_build">
+<class name="VisualScriptExpression" inherits="VisualScriptNode" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/VisualScriptFunction.xml b/modules/visual_script/doc_classes/VisualScriptFunction.xml
index 946231eaad..d77169679b 100644
--- a/doc/classes/VisualScriptFunction.xml
+++ b/modules/visual_script/doc_classes/VisualScriptFunction.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptFunction" inherits="VisualScriptNode" category="Core" version="3.0.alpha.custom_build">
+<class name="VisualScriptFunction" inherits="VisualScriptNode" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/VisualScriptFunctionCall.xml b/modules/visual_script/doc_classes/VisualScriptFunctionCall.xml
index 36c808afce..7a0a7c9f55 100644
--- a/doc/classes/VisualScriptFunctionCall.xml
+++ b/modules/visual_script/doc_classes/VisualScriptFunctionCall.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptFunctionCall" inherits="VisualScriptNode" category="Core" version="3.0.alpha.custom_build">
+<class name="VisualScriptFunctionCall" inherits="VisualScriptNode" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/VisualScriptFunctionState.xml b/modules/visual_script/doc_classes/VisualScriptFunctionState.xml
index d5c06682ef..9b30f62236 100644
--- a/doc/classes/VisualScriptFunctionState.xml
+++ b/modules/visual_script/doc_classes/VisualScriptFunctionState.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptFunctionState" inherits="Reference" category="Core" version="3.0.alpha.custom_build">
+<class name="VisualScriptFunctionState" inherits="Reference" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/VisualScriptGlobalConstant.xml b/modules/visual_script/doc_classes/VisualScriptGlobalConstant.xml
index 52bf8c2821..961244fe88 100644
--- a/doc/classes/VisualScriptGlobalConstant.xml
+++ b/modules/visual_script/doc_classes/VisualScriptGlobalConstant.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptGlobalConstant" inherits="VisualScriptNode" category="Core" version="3.0.alpha.custom_build">
+<class name="VisualScriptGlobalConstant" inherits="VisualScriptNode" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/VisualScriptIndexGet.xml b/modules/visual_script/doc_classes/VisualScriptIndexGet.xml
index c0226b6677..c5229f7678 100644
--- a/doc/classes/VisualScriptIndexGet.xml
+++ b/modules/visual_script/doc_classes/VisualScriptIndexGet.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptIndexGet" inherits="VisualScriptNode" category="Core" version="3.0.alpha.custom_build">
+<class name="VisualScriptIndexGet" inherits="VisualScriptNode" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/VisualScriptIndexSet.xml b/modules/visual_script/doc_classes/VisualScriptIndexSet.xml
index 440b4801b4..27646b4a5f 100644
--- a/doc/classes/VisualScriptIndexSet.xml
+++ b/modules/visual_script/doc_classes/VisualScriptIndexSet.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptIndexSet" inherits="VisualScriptNode" category="Core" version="3.0.alpha.custom_build">
+<class name="VisualScriptIndexSet" inherits="VisualScriptNode" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/VisualScriptInputAction.xml b/modules/visual_script/doc_classes/VisualScriptInputAction.xml
index b555a0228b..7f6d13264e 100644
--- a/doc/classes/VisualScriptInputAction.xml
+++ b/modules/visual_script/doc_classes/VisualScriptInputAction.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptInputAction" inherits="VisualScriptNode" category="Core" version="3.0.alpha.custom_build">
+<class name="VisualScriptInputAction" inherits="VisualScriptNode" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/modules/visual_script/doc_classes/VisualScriptIterator.xml b/modules/visual_script/doc_classes/VisualScriptIterator.xml
new file mode 100644
index 0000000000..fc905d6c39
--- /dev/null
+++ b/modules/visual_script/doc_classes/VisualScriptIterator.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="VisualScriptIterator" inherits="VisualScriptNode" category="Core" version="3.0-alpha">
+ <brief_description>
+ Steps through items in a given input.
+ </brief_description>
+ <description>
+ This node steps through each item in a given input. Input can be any sequence data type, such as an [Array] or [String]. When each item has been processed, execution passed out the [code]exit[/code] Sequence port.
+ [b]Input Ports:[/b]
+ - Sequence: [code]for (elem) in (input)[/code]
+ - Data (variant): [code]input[/code]
+ [b]Output Ports:[/b]
+ - Sequence: [code]each[/code]
+ - Sequence: [code]exit[/code]
+ - Data (variant): [code]elem[/code]
+ </description>
+ <tutorials>
+ </tutorials>
+ <demos>
+ </demos>
+ <methods>
+ </methods>
+ <constants>
+ </constants>
+</class>
diff --git a/doc/classes/VisualScriptLocalVar.xml b/modules/visual_script/doc_classes/VisualScriptLocalVar.xml
index 7db550d5fe..ff77dfac0d 100644
--- a/doc/classes/VisualScriptLocalVar.xml
+++ b/modules/visual_script/doc_classes/VisualScriptLocalVar.xml
@@ -1,8 +1,14 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptLocalVar" inherits="VisualScriptNode" category="Core" version="3.0.alpha.custom_build">
+<class name="VisualScriptLocalVar" inherits="VisualScriptNode" category="Core" version="3.0-alpha">
<brief_description>
+ Gets a local variable's value.
</brief_description>
<description>
+ Returns a local variable's value. "Var Name" must be supplied, with an optional type.
+ [b]Input Ports:[/b]
+ none
+ [b]Output Ports:[/b]
+ - Data (variant): [code]get[/code]
</description>
<tutorials>
</tutorials>
@@ -40,8 +46,10 @@
</methods>
<members>
<member name="type" type="int" setter="set_var_type" getter="get_var_type" enum="Variant.Type">
+ The local variable's type.
</member>
<member name="var_name" type="String" setter="set_var_name" getter="get_var_name">
+ The local variable's name.
</member>
</members>
<constants>
diff --git a/doc/classes/VisualScriptLocalVarSet.xml b/modules/visual_script/doc_classes/VisualScriptLocalVarSet.xml
index 6e69f13383..07b01d4576 100644
--- a/doc/classes/VisualScriptLocalVarSet.xml
+++ b/modules/visual_script/doc_classes/VisualScriptLocalVarSet.xml
@@ -1,8 +1,16 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptLocalVarSet" inherits="VisualScriptNode" category="Core" version="3.0.alpha.custom_build">
+<class name="VisualScriptLocalVarSet" inherits="VisualScriptNode" category="Core" version="3.0-alpha">
<brief_description>
+ Changes a local variable's value.
</brief_description>
<description>
+ Changes a local variable's value to the given input. The new value is also provided on an output Data port.
+ [b]Input Ports:[/b]
+ - Sequence
+ - Data (variant): [code]set[/code]
+ [b]Output Ports:[/b]
+ - Sequence
+ - Data (variant): [code]get[/code]
</description>
<tutorials>
</tutorials>
@@ -40,8 +48,10 @@
</methods>
<members>
<member name="type" type="int" setter="set_var_type" getter="get_var_type" enum="Variant.Type">
+ The local variable's type.
</member>
<member name="var_name" type="String" setter="set_var_name" getter="get_var_name">
+ The local variable's name.
</member>
</members>
<constants>
diff --git a/doc/classes/VisualScriptMathConstant.xml b/modules/visual_script/doc_classes/VisualScriptMathConstant.xml
index 1ef7d71e10..817bcb5ce2 100644
--- a/doc/classes/VisualScriptMathConstant.xml
+++ b/modules/visual_script/doc_classes/VisualScriptMathConstant.xml
@@ -1,8 +1,14 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptMathConstant" inherits="VisualScriptNode" category="Core" version="3.0.alpha.custom_build">
+<class name="VisualScriptMathConstant" inherits="VisualScriptNode" category="Core" version="3.0-alpha">
<brief_description>
+ Commonly used mathematical constants.
</brief_description>
<description>
+ Provides common math constants, such as Pi or Euler's constant, on an output Data port.
+ [b]Input Ports:[/b]
+ none
+ [b]Output Ports:[/b]
+ - Data (variant): [code]get[/code]
</description>
<tutorials>
</tutorials>
@@ -26,24 +32,33 @@
</methods>
<members>
<member name="constant" type="int" setter="set_math_constant" getter="get_math_constant" enum="VisualScriptMathConstant.MathConstant">
+ The math constant.
</member>
</members>
<constants>
<constant name="MATH_CONSTANT_ONE" value="0">
+ Unity: [code]1[/code]
</constant>
<constant name="MATH_CONSTANT_PI" value="1">
+ Pi: [code]3.141593[/code]
</constant>
- <constant name="MATH_CONSTANT_2PI" value="2">
+ <constant name="MATH_CONSTANT_HALF_PI" value="2">
+ Pi divided by two: [code]1.570796[/code]
</constant>
- <constant name="MATH_CONSTANT_HALF_PI" value="3">
+ <constant name="MATH_CONSTANT_TAU" value="3">
+ Tau: [code]6.283185[/code]
</constant>
<constant name="MATH_CONSTANT_E" value="4">
+ Natural log: [code]2.718282[/code]
</constant>
<constant name="MATH_CONSTANT_SQRT2" value="5">
+ Square root of two: [code]1.414214[/code]
</constant>
<constant name="MATH_CONSTANT_INF" value="6">
+ Infinity: [code]inf[/code]
</constant>
<constant name="MATH_CONSTANT_NAN" value="7">
+ Not a number: [code]nan[/code]
</constant>
<constant name="MATH_CONSTANT_MAX" value="8">
</constant>
diff --git a/doc/classes/VisualScriptNode.xml b/modules/visual_script/doc_classes/VisualScriptNode.xml
index 74ec9bdc2e..f6f2867172 100644
--- a/doc/classes/VisualScriptNode.xml
+++ b/modules/visual_script/doc_classes/VisualScriptNode.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptNode" inherits="Resource" category="Core" version="3.0.alpha.custom_build">
+<class name="VisualScriptNode" inherits="Resource" category="Core" version="3.0-alpha">
<brief_description>
A node which is part of a [VisualScript].
</brief_description>
diff --git a/doc/classes/VisualScriptOperator.xml b/modules/visual_script/doc_classes/VisualScriptOperator.xml
index 82951c9e0c..bf4032c09c 100644
--- a/doc/classes/VisualScriptOperator.xml
+++ b/modules/visual_script/doc_classes/VisualScriptOperator.xml
@@ -1,8 +1,13 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptOperator" inherits="VisualScriptNode" category="Core" version="3.0.alpha.custom_build">
+<class name="VisualScriptOperator" inherits="VisualScriptNode" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
+ [b]Input Ports:[/b]
+ - Data (variant): [code]A[/code]
+ - Data (variant): [code]B[/code]
+ [b]Output Ports:[/b]
+ - Data (variant): [code]result[/code]
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/VisualScriptPreload.xml b/modules/visual_script/doc_classes/VisualScriptPreload.xml
index b68bf5546b..4a71e23809 100644
--- a/doc/classes/VisualScriptPreload.xml
+++ b/modules/visual_script/doc_classes/VisualScriptPreload.xml
@@ -1,8 +1,14 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptPreload" inherits="VisualScriptNode" category="Core" version="3.0.alpha.custom_build">
+<class name="VisualScriptPreload" inherits="VisualScriptNode" category="Core" version="3.0-alpha">
<brief_description>
+ Creates a new [Resource] or loads one from the filesystem.
</brief_description>
<description>
+ Creates a new [Resource] or loads one from the filesystem.
+ [b]Input Ports:[/b]
+ none
+ [b]Output Ports:[/b]
+ - Data (object): [code]res[/code]
</description>
<tutorials>
</tutorials>
@@ -26,6 +32,7 @@
</methods>
<members>
<member name="resource" type="Resource" setter="set_preload" getter="get_preload">
+ The [Resource] to load.
</member>
</members>
<constants>
diff --git a/doc/classes/VisualScriptPropertyGet.xml b/modules/visual_script/doc_classes/VisualScriptPropertyGet.xml
index c790a59b0c..eb5c52f4be 100644
--- a/doc/classes/VisualScriptPropertyGet.xml
+++ b/modules/visual_script/doc_classes/VisualScriptPropertyGet.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptPropertyGet" inherits="VisualScriptNode" category="Core" version="3.0.alpha.custom_build">
+<class name="VisualScriptPropertyGet" inherits="VisualScriptNode" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/VisualScriptPropertySet.xml b/modules/visual_script/doc_classes/VisualScriptPropertySet.xml
index 88d47a7463..794caa2518 100644
--- a/doc/classes/VisualScriptPropertySet.xml
+++ b/modules/visual_script/doc_classes/VisualScriptPropertySet.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptPropertySet" inherits="VisualScriptNode" category="Core" version="3.0.alpha.custom_build">
+<class name="VisualScriptPropertySet" inherits="VisualScriptNode" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/VisualScriptResourcePath.xml b/modules/visual_script/doc_classes/VisualScriptResourcePath.xml
index e4b881b659..274a852c3e 100644
--- a/doc/classes/VisualScriptResourcePath.xml
+++ b/modules/visual_script/doc_classes/VisualScriptResourcePath.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptResourcePath" inherits="VisualScriptNode" category="Core" version="3.0.alpha.custom_build">
+<class name="VisualScriptResourcePath" inherits="VisualScriptNode" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/VisualScriptReturn.xml b/modules/visual_script/doc_classes/VisualScriptReturn.xml
index 55c53e17a0..4ac586a02c 100644
--- a/doc/classes/VisualScriptReturn.xml
+++ b/modules/visual_script/doc_classes/VisualScriptReturn.xml
@@ -1,8 +1,15 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptReturn" inherits="VisualScriptNode" category="Core" version="3.0.alpha.custom_build">
+<class name="VisualScriptReturn" inherits="VisualScriptNode" category="Core" version="3.0-alpha">
<brief_description>
+ Exits a function and returns an optional value.
</brief_description>
<description>
+ Ends the execution of a function and returns control to the calling function. Optionally, it can return a [Variant] value.
+ [b]Input Ports:[/b]
+ - Sequence
+ - Data (variant): [code]result[/code] (optional)
+ [b]Output Ports:[/b]
+ none
</description>
<tutorials>
</tutorials>
@@ -40,8 +47,10 @@
</methods>
<members>
<member name="return_enabled" type="bool" setter="set_enable_return_value" getter="is_return_value_enabled">
+ If [code]true[/code] the [code]return[/code] input port is available.
</member>
<member name="return_type" type="int" setter="set_return_type" getter="get_return_type" enum="Variant.Type">
+ The return value's data type.
</member>
</members>
<constants>
diff --git a/doc/classes/VisualScriptSceneNode.xml b/modules/visual_script/doc_classes/VisualScriptSceneNode.xml
index 90a8f132c0..e8fdb69c6a 100644
--- a/doc/classes/VisualScriptSceneNode.xml
+++ b/modules/visual_script/doc_classes/VisualScriptSceneNode.xml
@@ -1,8 +1,14 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptSceneNode" inherits="VisualScriptNode" category="Core" version="3.0.alpha.custom_build">
+<class name="VisualScriptSceneNode" inherits="VisualScriptNode" category="Core" version="3.0-alpha">
<brief_description>
+ Node reference.
</brief_description>
<description>
+ A direct reference to a node.
+ [b]Input Ports:[/b]
+ none
+ [b]Output Ports:[/b]
+ - Data: [code]node[/code] (obj)
</description>
<tutorials>
</tutorials>
@@ -26,6 +32,7 @@
</methods>
<members>
<member name="node_path" type="NodePath" setter="set_node_path" getter="get_node_path">
+ The node's path in the scene tree.
</member>
</members>
<constants>
diff --git a/doc/classes/VisualScriptSceneTree.xml b/modules/visual_script/doc_classes/VisualScriptSceneTree.xml
index 55e27460ab..e74c330623 100644
--- a/doc/classes/VisualScriptSceneTree.xml
+++ b/modules/visual_script/doc_classes/VisualScriptSceneTree.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptSceneTree" inherits="VisualScriptNode" category="Core" version="3.0.alpha.custom_build">
+<class name="VisualScriptSceneTree" inherits="VisualScriptNode" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/VisualScriptSelect.xml b/modules/visual_script/doc_classes/VisualScriptSelect.xml
index 855da76e6c..6a62e364f3 100644
--- a/doc/classes/VisualScriptSelect.xml
+++ b/modules/visual_script/doc_classes/VisualScriptSelect.xml
@@ -1,8 +1,16 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptSelect" inherits="VisualScriptNode" category="Core" version="3.0.alpha.custom_build">
+<class name="VisualScriptSelect" inherits="VisualScriptNode" category="Core" version="3.0-alpha">
<brief_description>
+ Chooses between two input values.
</brief_description>
<description>
+ Chooses between two input values based on a Boolean condition.
+ [b]Input Ports:[/b]
+ - Data (boolean): [code]cond[/code]
+ - Data (variant): [code]a[/code]
+ - Data (variant): [code]b[/code]
+ [b]Output Ports:[/b]
+ - Data (variant): [code]out[/code]
</description>
<tutorials>
</tutorials>
@@ -26,6 +34,7 @@
</methods>
<members>
<member name="type" type="int" setter="set_typed" getter="get_typed" enum="Variant.Type">
+ The input variables' type.
</member>
</members>
<constants>
diff --git a/modules/visual_script/doc_classes/VisualScriptSelf.xml b/modules/visual_script/doc_classes/VisualScriptSelf.xml
new file mode 100644
index 0000000000..f39a02bf84
--- /dev/null
+++ b/modules/visual_script/doc_classes/VisualScriptSelf.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="VisualScriptSelf" inherits="VisualScriptNode" category="Core" version="3.0-alpha">
+ <brief_description>
+ Outputs a reference to the current instance.
+ </brief_description>
+ <description>
+ Provides a reference to the node running the visual script.
+ [b]Input Ports:[/b]
+ none
+ [b]Output Ports:[/b]
+ - Data (object): [code]instance[/code]
+ </description>
+ <tutorials>
+ </tutorials>
+ <demos>
+ </demos>
+ <methods>
+ </methods>
+ <constants>
+ </constants>
+</class>
diff --git a/doc/classes/VisualScriptSequence.xml b/modules/visual_script/doc_classes/VisualScriptSequence.xml
index a60c9e782b..51238070d5 100644
--- a/doc/classes/VisualScriptSequence.xml
+++ b/modules/visual_script/doc_classes/VisualScriptSequence.xml
@@ -1,8 +1,16 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptSequence" inherits="VisualScriptNode" category="Core" version="3.0.alpha.custom_build">
+<class name="VisualScriptSequence" inherits="VisualScriptNode" category="Core" version="3.0-alpha">
<brief_description>
+ Executes a series of Sequence ports.
</brief_description>
<description>
+ Steps through a series of one or more output Sequence ports. The [code]current[/code] data port outputs the currently executing item.
+ [b]Input Ports:[/b]
+ - Sequence: [code]in order[/code]
+ [b]Output Ports:[/b]
+ - Sequence: [code]1[/code]
+ - Sequence: [code]2 - n[/code] (optional)
+ - Data (int): [code]current[/code]
</description>
<tutorials>
</tutorials>
@@ -26,6 +34,7 @@
</methods>
<members>
<member name="steps" type="int" setter="set_steps" getter="get_steps">
+ The number of steps in the sequence.
</member>
</members>
<constants>
diff --git a/doc/classes/VisualScriptSubCall.xml b/modules/visual_script/doc_classes/VisualScriptSubCall.xml
index 297ec96781..381095f49b 100644
--- a/doc/classes/VisualScriptSubCall.xml
+++ b/modules/visual_script/doc_classes/VisualScriptSubCall.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptSubCall" inherits="VisualScriptNode" category="Core" version="3.0.alpha.custom_build">
+<class name="VisualScriptSubCall" inherits="VisualScriptNode" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/modules/visual_script/doc_classes/VisualScriptSwitch.xml b/modules/visual_script/doc_classes/VisualScriptSwitch.xml
new file mode 100644
index 0000000000..3c8a79f686
--- /dev/null
+++ b/modules/visual_script/doc_classes/VisualScriptSwitch.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="VisualScriptSwitch" inherits="VisualScriptNode" category="Core" version="3.0-alpha">
+ <brief_description>
+ Branches program flow based on a given input's value.
+ </brief_description>
+ <description>
+ Branches the flow based on an input's value. Use "Case Count" in the Inspector to set the number of branches and each comparison's optional type.
+ [b]Input Ports:[/b]
+ - Sequence: [code]'input' is[/code]
+ - Data (variant): [code]=[/code]
+ - Data (variant): [code]=[/code] (optional)
+ - Data (variant): [code]input[/code]
+ [b]Output Ports:[/b]
+ - Sequence
+ - Sequence (optional)
+ - Sequence: [code]done[/code]
+ </description>
+ <tutorials>
+ </tutorials>
+ <demos>
+ </demos>
+ <methods>
+ </methods>
+ <constants>
+ </constants>
+</class>
diff --git a/doc/classes/VisualScriptTypeCast.xml b/modules/visual_script/doc_classes/VisualScriptTypeCast.xml
index 3008426900..417c0a5159 100644
--- a/doc/classes/VisualScriptTypeCast.xml
+++ b/modules/visual_script/doc_classes/VisualScriptTypeCast.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptTypeCast" inherits="VisualScriptNode" category="Core" version="3.0.alpha.custom_build">
+<class name="VisualScriptTypeCast" inherits="VisualScriptNode" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/VisualScriptVariableGet.xml b/modules/visual_script/doc_classes/VisualScriptVariableGet.xml
index 8411933756..1cad4480a6 100644
--- a/doc/classes/VisualScriptVariableGet.xml
+++ b/modules/visual_script/doc_classes/VisualScriptVariableGet.xml
@@ -1,8 +1,14 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptVariableGet" inherits="VisualScriptNode" category="Core" version="3.0.alpha.custom_build">
+<class name="VisualScriptVariableGet" inherits="VisualScriptNode" category="Core" version="3.0-alpha">
<brief_description>
+ Gets a variable's value.
</brief_description>
<description>
+ Returns a variable's value. "Var Name" must be supplied, with an optional type.
+ [b]Input Ports:[/b]
+ none
+ [b]Output Ports:[/b]
+ - Data (variant): [code]value[/code]
</description>
<tutorials>
</tutorials>
@@ -26,6 +32,7 @@
</methods>
<members>
<member name="var_name" type="String" setter="set_variable" getter="get_variable">
+ The variable's name.
</member>
</members>
<constants>
diff --git a/doc/classes/VisualScriptVariableSet.xml b/modules/visual_script/doc_classes/VisualScriptVariableSet.xml
index fbe0f8e275..fa3befa21d 100644
--- a/doc/classes/VisualScriptVariableSet.xml
+++ b/modules/visual_script/doc_classes/VisualScriptVariableSet.xml
@@ -1,8 +1,15 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptVariableSet" inherits="VisualScriptNode" category="Core" version="3.0.alpha.custom_build">
+<class name="VisualScriptVariableSet" inherits="VisualScriptNode" category="Core" version="3.0-alpha">
<brief_description>
+ Changes a variable's value.
</brief_description>
<description>
+ Changes a variable's value to the given input.
+ [b]Input Ports:[/b]
+ - Sequence
+ - Data (variant): [code]set[/code]
+ [b]Output Ports:[/b]
+ - Sequence
</description>
<tutorials>
</tutorials>
@@ -26,6 +33,7 @@
</methods>
<members>
<member name="var_name" type="String" setter="set_variable" getter="get_variable">
+ The variable's name.
</member>
</members>
<constants>
diff --git a/modules/visual_script/doc_classes/VisualScriptWhile.xml b/modules/visual_script/doc_classes/VisualScriptWhile.xml
new file mode 100644
index 0000000000..f948660997
--- /dev/null
+++ b/modules/visual_script/doc_classes/VisualScriptWhile.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="VisualScriptWhile" inherits="VisualScriptNode" category="Core" version="3.0-alpha">
+ <brief_description>
+ Conditional loop.
+ </brief_description>
+ <description>
+ Loops while a condition is [code]true[/code]. Execution continues out the [code]exit[/code] Sequence port when the loop terminates.
+ [b]Input Ports:[/b]
+ - Sequence: [code]while(cond)[/code]
+ - Data (bool): [code]cond[/code]
+ [b]Output Ports:[/b]
+ - Sequence: [code]repeat[/code]
+ - Sequence: [code]exit[/code]
+ </description>
+ <tutorials>
+ </tutorials>
+ <demos>
+ </demos>
+ <methods>
+ </methods>
+ <constants>
+ </constants>
+</class>
diff --git a/doc/classes/VisualScriptYield.xml b/modules/visual_script/doc_classes/VisualScriptYield.xml
index b8938daa67..5474ee8b78 100644
--- a/doc/classes/VisualScriptYield.xml
+++ b/modules/visual_script/doc_classes/VisualScriptYield.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptYield" inherits="VisualScriptNode" category="Core" version="3.0.alpha.custom_build">
+<class name="VisualScriptYield" inherits="VisualScriptNode" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
@@ -47,7 +47,7 @@
<constants>
<constant name="YIELD_FRAME" value="1">
</constant>
- <constant name="YIELD_FIXED_FRAME" value="2">
+ <constant name="YIELD_PHYSICS_FRAME" value="2">
</constant>
<constant name="YIELD_WAIT" value="3">
</constant>
diff --git a/doc/classes/VisualScriptYieldSignal.xml b/modules/visual_script/doc_classes/VisualScriptYieldSignal.xml
index f4202edf2b..a3b6982075 100644
--- a/doc/classes/VisualScriptYieldSignal.xml
+++ b/modules/visual_script/doc_classes/VisualScriptYieldSignal.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptYieldSignal" inherits="VisualScriptNode" category="Core" version="3.0.alpha.custom_build">
+<class name="VisualScriptYieldSignal" inherits="VisualScriptNode" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/modules/visual_script/register_types.cpp b/modules/visual_script/register_types.cpp
index c50ba17c35..b6ce10381d 100644
--- a/modules/visual_script/register_types.cpp
+++ b/modules/visual_script/register_types.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "register_types.h"
+#include "core/engine.h"
#include "io/resource_loader.h"
#include "visual_script.h"
#include "visual_script_builtin_funcs.h"
@@ -40,6 +41,9 @@
#include "visual_script_yield_nodes.h"
VisualScriptLanguage *visual_script_language = NULL;
+#ifdef TOOLS_ENABLED
+static _VisualScriptEditor *vs_editor_singleton = NULL;
+#endif
void register_visual_script_types() {
@@ -107,6 +111,10 @@ void register_visual_script_types() {
register_visual_script_expression_node();
#ifdef TOOLS_ENABLED
+ ClassDB::register_class<_VisualScriptEditor>();
+ vs_editor_singleton = memnew(_VisualScriptEditor);
+ Engine::get_singleton()->add_singleton(Engine::Singleton("VisualScriptEditor", _VisualScriptEditor::get_singleton()));
+
VisualScriptEditor::register_editor();
#endif
}
@@ -119,6 +127,9 @@ void unregister_visual_script_types() {
#ifdef TOOLS_ENABLED
VisualScriptEditor::free_clipboard();
+ if (vs_editor_singleton) {
+ memdelete(vs_editor_singleton);
+ }
#endif
if (visual_script_language)
memdelete(visual_script_language);
diff --git a/modules/visual_script/visual_script.cpp b/modules/visual_script/visual_script.cpp
index 48145495e4..0834bc81d9 100644
--- a/modules/visual_script/visual_script.cpp
+++ b/modules/visual_script/visual_script.cpp
@@ -974,11 +974,6 @@ bool VisualScript::is_tool() const {
return false;
}
-String VisualScript::get_node_type() const {
-
- return String();
-}
-
ScriptLanguage *VisualScript::get_language() const {
return VisualScriptLanguage::singleton;
@@ -2412,6 +2407,10 @@ bool VisualScriptLanguage::has_named_classes() const {
return false;
}
+bool VisualScriptLanguage::supports_builtin_mode() const {
+
+ return true;
+}
int VisualScriptLanguage::find_function(const String &p_function, const String &p_code) const {
return -1;
@@ -2645,6 +2644,11 @@ void VisualScriptLanguage::add_register_func(const String &p_name, VisualScriptN
register_funcs[p_name] = p_func;
}
+void VisualScriptLanguage::remove_register_func(const String &p_name) {
+ ERR_FAIL_COND(!register_funcs.has(p_name));
+ register_funcs.erase(p_name);
+}
+
Ref<VisualScriptNode> VisualScriptLanguage::create_node_from_name(const String &p_name) {
ERR_FAIL_COND_V(!register_funcs.has(p_name), Ref<VisualScriptNode>());
diff --git a/modules/visual_script/visual_script.h b/modules/visual_script/visual_script.h
index 4ae50ee829..3e31876941 100644
--- a/modules/visual_script/visual_script.h
+++ b/modules/visual_script/visual_script.h
@@ -339,8 +339,6 @@ public:
virtual bool is_tool() const;
- virtual String get_node_type() const;
-
virtual ScriptLanguage *get_language() const;
virtual bool has_script_signal(const StringName &p_signal) const;
@@ -569,6 +567,7 @@ public:
virtual bool validate(const String &p_script, int &r_line_error, int &r_col_error, String &r_test_error, const String &p_path = "", List<String> *r_functions = NULL) const;
virtual Script *create_script() const;
virtual bool has_named_classes() const;
+ virtual bool supports_builtin_mode() const;
virtual int find_function(const String &p_function, const String &p_code) const;
virtual String make_function(const String &p_class, const String &p_name, const PoolStringArray &p_args) const;
virtual void auto_indent_code(String &p_code, int p_from_line, int p_to_line) const;
@@ -601,6 +600,7 @@ public:
virtual int profiling_get_frame_data(ProfilingInfo *p_info_arr, int p_info_max);
void add_register_func(const String &p_name, VisualScriptNodeRegisterFunc p_func);
+ void remove_register_func(const String &p_name);
Ref<VisualScriptNode> create_node_from_name(const String &p_name);
void get_registered_node_names(List<String> *r_names);
diff --git a/modules/visual_script/visual_script_builtin_funcs.cpp b/modules/visual_script/visual_script_builtin_funcs.cpp
index 972be5f5a4..32f7519125 100644
--- a/modules/visual_script/visual_script_builtin_funcs.cpp
+++ b/modules/visual_script/visual_script_builtin_funcs.cpp
@@ -65,6 +65,8 @@ const char *VisualScriptBuiltinFunc::func_name[VisualScriptBuiltinFunc::FUNC_MAX
"decimals",
"stepify",
"lerp",
+ "inverse_lerp",
+ "range_lerp",
"dectime",
"randomize",
"randi",
@@ -76,6 +78,10 @@ const char *VisualScriptBuiltinFunc::func_name[VisualScriptBuiltinFunc::FUNC_MAX
"rad2deg",
"linear2db",
"db2linear",
+ "polar2cartesian",
+ "cartesian2polar",
+ "wrapi",
+ "wrapf",
"max",
"min",
"clamp",
@@ -187,6 +193,8 @@ int VisualScriptBuiltinFunc::get_func_argument_count(BuiltinFunc p_func) {
case MATH_EASE:
case MATH_STEPIFY:
case MATH_RANDOM:
+ case MATH_POLAR2CARTESIAN:
+ case MATH_CARTESIAN2POLAR:
case LOGIC_MAX:
case LOGIC_MIN:
case FUNC_FUNCREF:
@@ -194,9 +202,14 @@ int VisualScriptBuiltinFunc::get_func_argument_count(BuiltinFunc p_func) {
case COLORN:
return 2;
case MATH_LERP:
+ case MATH_INVERSE_LERP:
case MATH_DECTIME:
+ case MATH_WRAP:
+ case MATH_WRAPF:
case LOGIC_CLAMP:
return 3;
+ case MATH_RANGE_LERP:
+ return 5;
case FUNC_MAX: {
}
}
@@ -297,7 +310,26 @@ PropertyInfo VisualScriptBuiltinFunc::get_input_value_port_info(int p_idx) const
return PropertyInfo(Variant::REAL, "to");
else
return PropertyInfo(Variant::REAL, "weight");
-
+ } break;
+ case MATH_INVERSE_LERP: {
+ if (p_idx == 0)
+ return PropertyInfo(Variant::REAL, "from");
+ else if (p_idx == 1)
+ return PropertyInfo(Variant::REAL, "to");
+ else
+ return PropertyInfo(Variant::REAL, "value");
+ } break;
+ case MATH_RANGE_LERP: {
+ if (p_idx == 0)
+ return PropertyInfo(Variant::REAL, "value");
+ else if (p_idx == 1)
+ return PropertyInfo(Variant::REAL, "istart");
+ else if (p_idx == 2)
+ return PropertyInfo(Variant::REAL, "istop");
+ else if (p_idx == 3)
+ return PropertyInfo(Variant::REAL, "ostart");
+ else
+ return PropertyInfo(Variant::REAL, "ostop");
} break;
case MATH_DECTIME: {
if (p_idx == 0)
@@ -340,6 +372,34 @@ PropertyInfo VisualScriptBuiltinFunc::get_input_value_port_info(int p_idx) const
case MATH_DB2LINEAR: {
return PropertyInfo(Variant::REAL, "db");
} break;
+ case MATH_POLAR2CARTESIAN: {
+ if (p_idx == 0)
+ return PropertyInfo(Variant::REAL, "r");
+ else
+ return PropertyInfo(Variant::REAL, "th");
+ } break;
+ case MATH_CARTESIAN2POLAR: {
+ if (p_idx == 0)
+ return PropertyInfo(Variant::REAL, "x");
+ else
+ return PropertyInfo(Variant::REAL, "y");
+ } break;
+ case MATH_WRAP: {
+ if (p_idx == 0)
+ return PropertyInfo(Variant::INT, "value");
+ else if (p_idx == 1)
+ return PropertyInfo(Variant::INT, "min");
+ else
+ return PropertyInfo(Variant::INT, "max");
+ } break;
+ case MATH_WRAPF: {
+ if (p_idx == 0)
+ return PropertyInfo(Variant::REAL, "value");
+ else if (p_idx == 1)
+ return PropertyInfo(Variant::REAL, "min");
+ else
+ return PropertyInfo(Variant::REAL, "max");
+ } break;
case LOGIC_MAX: {
if (p_idx == 0)
return PropertyInfo(Variant::REAL, "a");
@@ -495,6 +555,8 @@ PropertyInfo VisualScriptBuiltinFunc::get_output_value_port_info(int p_idx) cons
} break;
case MATH_STEPIFY:
case MATH_LERP:
+ case MATH_INVERSE_LERP:
+ case MATH_RANGE_LERP:
case MATH_DECTIME: {
t = Variant::REAL;
@@ -523,9 +585,17 @@ PropertyInfo VisualScriptBuiltinFunc::get_output_value_port_info(int p_idx) cons
case MATH_DEG2RAD:
case MATH_RAD2DEG:
case MATH_LINEAR2DB:
+ case MATH_WRAPF:
case MATH_DB2LINEAR: {
t = Variant::REAL;
} break;
+ case MATH_POLAR2CARTESIAN:
+ case MATH_CARTESIAN2POLAR: {
+ t = Variant::VECTOR2;
+ } break;
+ case MATH_WRAP: {
+ t = Variant::INT;
+ } break;
case LOGIC_MAX:
case LOGIC_MIN:
case LOGIC_CLAMP: {
@@ -795,6 +865,22 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func, const Variant **p_in
VALIDATE_ARG_NUM(2);
*r_return = Math::lerp((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]);
} break;
+ case VisualScriptBuiltinFunc::MATH_INVERSE_LERP: {
+
+ VALIDATE_ARG_NUM(0);
+ VALIDATE_ARG_NUM(1);
+ VALIDATE_ARG_NUM(2);
+ *r_return = Math::inverse_lerp((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]);
+ } break;
+ case VisualScriptBuiltinFunc::MATH_RANGE_LERP: {
+
+ VALIDATE_ARG_NUM(0);
+ VALIDATE_ARG_NUM(1);
+ VALIDATE_ARG_NUM(2);
+ VALIDATE_ARG_NUM(3);
+ VALIDATE_ARG_NUM(4);
+ *r_return = Math::range_lerp((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2], (double)*p_inputs[3], (double)*p_inputs[4]);
+ } break;
case VisualScriptBuiltinFunc::MATH_DECTIME: {
VALIDATE_ARG_NUM(0);
@@ -856,6 +942,32 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func, const Variant **p_in
VALIDATE_ARG_NUM(0);
*r_return = Math::db2linear((double)*p_inputs[0]);
} break;
+ case VisualScriptBuiltinFunc::MATH_POLAR2CARTESIAN: {
+ VALIDATE_ARG_NUM(0);
+ VALIDATE_ARG_NUM(1);
+ double r = *p_inputs[0];
+ double th = *p_inputs[1];
+ *r_return = Vector2(r * Math::cos(th), r * Math::sin(th));
+ } break;
+ case VisualScriptBuiltinFunc::MATH_CARTESIAN2POLAR: {
+ VALIDATE_ARG_NUM(0);
+ VALIDATE_ARG_NUM(1);
+ double x = *p_inputs[0];
+ double y = *p_inputs[1];
+ *r_return = Vector2(Math::sqrt(x * x + y * y), Math::atan2(y, x));
+ } break;
+ case VisualScriptBuiltinFunc::MATH_WRAP: {
+ VALIDATE_ARG_NUM(0);
+ VALIDATE_ARG_NUM(1);
+ VALIDATE_ARG_NUM(2);
+ *r_return = Math::wrapi((int64_t)*p_inputs[0], (int64_t)*p_inputs[1], (int64_t)*p_inputs[2]);
+ } break;
+ case VisualScriptBuiltinFunc::MATH_WRAPF: {
+ VALIDATE_ARG_NUM(0);
+ VALIDATE_ARG_NUM(1);
+ VALIDATE_ARG_NUM(2);
+ *r_return = Math::wrapf((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]);
+ } break;
case VisualScriptBuiltinFunc::LOGIC_MAX: {
if (p_inputs[0]->get_type() == Variant::INT && p_inputs[1]->get_type() == Variant::INT) {
@@ -1031,7 +1143,7 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func, const Variant **p_in
String str = *p_inputs[0];
//str+="\n";
- OS::get_singleton()->printerr("%s\n", str.utf8().get_data());
+ print_error(str);
} break;
case VisualScriptBuiltinFunc::TEXT_PRINTRAW: {
@@ -1203,6 +1315,8 @@ void VisualScriptBuiltinFunc::_bind_methods() {
BIND_ENUM_CONSTANT(MATH_DECIMALS);
BIND_ENUM_CONSTANT(MATH_STEPIFY);
BIND_ENUM_CONSTANT(MATH_LERP);
+ BIND_ENUM_CONSTANT(MATH_INVERSE_LERP);
+ BIND_ENUM_CONSTANT(MATH_RANGE_LERP);
BIND_ENUM_CONSTANT(MATH_DECTIME);
BIND_ENUM_CONSTANT(MATH_RANDOMIZE);
BIND_ENUM_CONSTANT(MATH_RAND);
@@ -1214,6 +1328,10 @@ void VisualScriptBuiltinFunc::_bind_methods() {
BIND_ENUM_CONSTANT(MATH_RAD2DEG);
BIND_ENUM_CONSTANT(MATH_LINEAR2DB);
BIND_ENUM_CONSTANT(MATH_DB2LINEAR);
+ BIND_ENUM_CONSTANT(MATH_POLAR2CARTESIAN);
+ BIND_ENUM_CONSTANT(MATH_CARTESIAN2POLAR);
+ BIND_ENUM_CONSTANT(MATH_WRAP);
+ BIND_ENUM_CONSTANT(MATH_WRAPF);
BIND_ENUM_CONSTANT(LOGIC_MAX);
BIND_ENUM_CONSTANT(LOGIC_MIN);
BIND_ENUM_CONSTANT(LOGIC_CLAMP);
@@ -1236,6 +1354,11 @@ void VisualScriptBuiltinFunc::_bind_methods() {
BIND_ENUM_CONSTANT(FUNC_MAX);
}
+VisualScriptBuiltinFunc::VisualScriptBuiltinFunc(VisualScriptBuiltinFunc::BuiltinFunc func) {
+
+ this->func = func;
+}
+
VisualScriptBuiltinFunc::VisualScriptBuiltinFunc() {
func = MATH_SIN;
@@ -1244,9 +1367,7 @@ VisualScriptBuiltinFunc::VisualScriptBuiltinFunc() {
template <VisualScriptBuiltinFunc::BuiltinFunc func>
static Ref<VisualScriptNode> create_builtin_func_node(const String &p_name) {
- Ref<VisualScriptBuiltinFunc> node;
- node.instance();
- node->set_func(func);
+ Ref<VisualScriptBuiltinFunc> node = memnew(VisualScriptBuiltinFunc(func));
return node;
}
@@ -1282,6 +1403,8 @@ void register_visual_script_builtin_func_node() {
VisualScriptLanguage::singleton->add_register_func("functions/built_in/decimals", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_DECIMALS>);
VisualScriptLanguage::singleton->add_register_func("functions/built_in/stepify", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_STEPIFY>);
VisualScriptLanguage::singleton->add_register_func("functions/built_in/lerp", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_LERP>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/inverse_lerp", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_INVERSE_LERP>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/range_lerp", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_RANGE_LERP>);
VisualScriptLanguage::singleton->add_register_func("functions/built_in/dectime", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_DECTIME>);
VisualScriptLanguage::singleton->add_register_func("functions/built_in/randomize", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_RANDOMIZE>);
VisualScriptLanguage::singleton->add_register_func("functions/built_in/rand", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_RAND>);
@@ -1294,6 +1417,10 @@ void register_visual_script_builtin_func_node() {
VisualScriptLanguage::singleton->add_register_func("functions/built_in/rad2deg", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_RAD2DEG>);
VisualScriptLanguage::singleton->add_register_func("functions/built_in/linear2db", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_LINEAR2DB>);
VisualScriptLanguage::singleton->add_register_func("functions/built_in/db2linear", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_DB2LINEAR>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/polar2cartesian", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_POLAR2CARTESIAN>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/cartesian2polar", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_CARTESIAN2POLAR>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/wrapi", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_WRAP>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/wrapf", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_WRAPF>);
VisualScriptLanguage::singleton->add_register_func("functions/built_in/max", create_builtin_func_node<VisualScriptBuiltinFunc::LOGIC_MAX>);
VisualScriptLanguage::singleton->add_register_func("functions/built_in/min", create_builtin_func_node<VisualScriptBuiltinFunc::LOGIC_MIN>);
diff --git a/modules/visual_script/visual_script_builtin_funcs.h b/modules/visual_script/visual_script_builtin_funcs.h
index 97ab307039..54dc997b38 100644
--- a/modules/visual_script/visual_script_builtin_funcs.h
+++ b/modules/visual_script/visual_script_builtin_funcs.h
@@ -64,6 +64,8 @@ public:
MATH_DECIMALS,
MATH_STEPIFY,
MATH_LERP,
+ MATH_INVERSE_LERP,
+ MATH_RANGE_LERP,
MATH_DECTIME,
MATH_RANDOMIZE,
MATH_RAND,
@@ -75,6 +77,10 @@ public:
MATH_RAD2DEG,
MATH_LINEAR2DB,
MATH_DB2LINEAR,
+ MATH_POLAR2CARTESIAN,
+ MATH_CARTESIAN2POLAR,
+ MATH_WRAP,
+ MATH_WRAPF,
LOGIC_MAX,
LOGIC_MIN,
LOGIC_CLAMP,
@@ -130,6 +136,7 @@ public:
virtual VisualScriptNodeInstance *instance(VisualScriptInstance *p_instance);
+ VisualScriptBuiltinFunc(VisualScriptBuiltinFunc::BuiltinFunc func);
VisualScriptBuiltinFunc();
};
diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp
index 2b43088a7a..2318149ca5 100644
--- a/modules/visual_script/visual_script_editor.cpp
+++ b/modules/visual_script/visual_script_editor.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "visual_script_editor.h"
+#include "core/script_language.h"
#include "editor/editor_node.h"
#include "editor/editor_resource_preview.h"
#include "os/input.h"
@@ -348,7 +349,7 @@ static Color _color_from_type(Variant::Type p_type, bool dark_theme = true) {
case Variant::TRANSFORM2D: color = Color::html("#c4ec69"); break;
case Variant::PLANE: color = Color::html("#f77070"); break;
case Variant::QUAT: color = Color::html("#ec69a3"); break;
- case Variant::RECT3: color = Color::html("#ee7991"); break;
+ case Variant::AABB: color = Color::html("#ee7991"); break;
case Variant::BASIS: color = Color::html("#e3ec69"); break;
case Variant::TRANSFORM: color = Color::html("#f6a86e"); break;
@@ -385,7 +386,7 @@ static Color _color_from_type(Variant::Type p_type, bool dark_theme = true) {
case Variant::TRANSFORM2D: color = Color::html("#96ce1a"); break;
case Variant::PLANE: color = Color::html("#f77070"); break;
case Variant::QUAT: color = Color::html("#ec69a3"); break;
- case Variant::RECT3: color = Color::html("#ee7991"); break;
+ case Variant::AABB: color = Color::html("#ee7991"); break;
case Variant::BASIS: color = Color::html("#b2bb19"); break;
case Variant::TRANSFORM: color = Color::html("#f49047"); break;
@@ -809,7 +810,7 @@ void VisualScriptEditor::_update_members() {
ti->set_text(0, E->get());
Variant var = script->get_variable_default_value(E->get());
- ti->set_suffix(0, "=" + String(var));
+ ti->set_suffix(0, "= " + String(var));
ti->set_icon(0, type_icons[script->get_variable_info(E->get()).type]);
ti->set_selectable(0, true);
@@ -2764,6 +2765,23 @@ void VisualScriptEditor::_default_value_edited(Node *p_button, int p_id, int p_i
default_value_edit->set_position(Object::cast_to<Control>(p_button)->get_global_position() + Vector2(0, Object::cast_to<Control>(p_button)->get_size().y));
default_value_edit->set_size(Size2(1, 1));
+
+ if (pinfo.type == Variant::NODE_PATH) {
+
+ Node *edited_scene = get_tree()->get_edited_scene_root();
+ Node *script_node = _find_script_node(edited_scene, edited_scene, script);
+
+ if (script_node) {
+ //pick a node relative to the script, IF the script exists
+ pinfo.hint = PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE;
+ pinfo.hint_string = script_node->get_path();
+ } else {
+ //pick a path relative to edited scene
+ pinfo.hint = PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE;
+ pinfo.hint_string = get_tree()->get_edited_scene_root()->get_path();
+ }
+ }
+
if (default_value_edit->edit(NULL, pinfo.name, pinfo.type, existing, pinfo.hint, pinfo.hint_string)) {
if (pinfo.hint == PROPERTY_HINT_MULTILINE_TEXT)
default_value_edit->popup_centered_ratio();
@@ -3241,6 +3259,8 @@ void VisualScriptEditor::_bind_methods() {
ClassDB::bind_method("_member_rmb_selected", &VisualScriptEditor::_member_rmb_selected);
ClassDB::bind_method("_member_option", &VisualScriptEditor::_member_option);
+
+ ClassDB::bind_method("_update_available_nodes", &VisualScriptEditor::_update_available_nodes);
}
VisualScriptEditor::VisualScriptEditor() {
@@ -3425,6 +3445,8 @@ VisualScriptEditor::VisualScriptEditor() {
members->connect("item_rmb_selected", this, "_member_rmb_selected");
members->set_allow_rmb_select(true);
member_popup->connect("id_pressed", this, "_member_option");
+
+ _VisualScriptEditor::get_singleton()->connect("custom_nodes_updated", this, "_update_available_nodes");
}
VisualScriptEditor::~VisualScriptEditor() {
@@ -3468,4 +3490,42 @@ void VisualScriptEditor::register_editor() {
EditorNode::add_plugin_init_callback(register_editor_callback);
}
+Ref<VisualScriptNode> _VisualScriptEditor::create_node_custom(const String &p_name) {
+
+ Ref<VisualScriptCustomNode> node;
+ node.instance();
+ node->set_script(singleton->custom_nodes[p_name]);
+ return node;
+}
+
+_VisualScriptEditor *_VisualScriptEditor::singleton = NULL;
+Map<String, RefPtr> _VisualScriptEditor::custom_nodes;
+
+_VisualScriptEditor::_VisualScriptEditor() {
+ singleton = this;
+}
+
+_VisualScriptEditor::~_VisualScriptEditor() {
+ custom_nodes.clear();
+}
+
+void _VisualScriptEditor::add_custom_node(const String &p_name, const String &p_category, const Ref<Script> &p_script) {
+ String node_name = "custom/" + p_category + "/" + p_name;
+ custom_nodes.insert(node_name, p_script.get_ref_ptr());
+ VisualScriptLanguage::singleton->add_register_func(node_name, &_VisualScriptEditor::create_node_custom);
+ emit_signal("custom_nodes_updated");
+}
+
+void _VisualScriptEditor::remove_custom_node(const String &p_name, const String &p_category) {
+ String node_name = "custom/" + p_category + "/" + p_name;
+ custom_nodes.erase(node_name);
+ VisualScriptLanguage::singleton->remove_register_func(node_name);
+ emit_signal("custom_nodes_updated");
+}
+
+void _VisualScriptEditor::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("add_custom_node", "name", "category", "script"), &_VisualScriptEditor::add_custom_node);
+ ClassDB::bind_method(D_METHOD("remove_custom_node", "name", "category"), &_VisualScriptEditor::remove_custom_node);
+ ADD_SIGNAL(MethodInfo("custom_nodes_updated"));
+}
#endif
diff --git a/modules/visual_script/visual_script_editor.h b/modules/visual_script/visual_script_editor.h
index db54d10300..3d037e82ea 100644
--- a/modules/visual_script/visual_script_editor.h
+++ b/modules/visual_script/visual_script_editor.h
@@ -278,6 +278,29 @@ public:
VisualScriptEditor();
~VisualScriptEditor();
};
+
+// Singleton
+class _VisualScriptEditor : public Object {
+ GDCLASS(_VisualScriptEditor, Object);
+
+ friend class VisualScriptLanguage;
+
+protected:
+ static void _bind_methods();
+ static _VisualScriptEditor *singleton;
+
+ static Map<String, RefPtr> custom_nodes;
+ static Ref<VisualScriptNode> create_node_custom(const String &p_name);
+
+public:
+ static _VisualScriptEditor *get_singleton() { return singleton; }
+
+ void add_custom_node(const String &p_name, const String &p_category, const Ref<Script> &p_script);
+ void remove_custom_node(const String &p_name, const String &p_category);
+
+ _VisualScriptEditor();
+ ~_VisualScriptEditor();
+};
#endif
#endif // VISUALSCRIPT_EDITOR_H
diff --git a/modules/visual_script/visual_script_expression.cpp b/modules/visual_script/visual_script_expression.cpp
index 897e910f20..07dca4b904 100644
--- a/modules/visual_script/visual_script_expression.cpp
+++ b/modules/visual_script/visual_script_expression.cpp
@@ -564,6 +564,9 @@ Error VisualScriptExpression::_get_token(Token &r_token) {
} else if (id == "PI") {
r_token.type = TK_CONSTANT;
r_token.value = Math_PI;
+ } else if (id == "TAU") {
+ r_token.type = TK_CONSTANT;
+ r_token.value = Math_TAU;
} else if (id == "INF") {
r_token.type = TK_CONSTANT;
r_token.value = Math_INF;
diff --git a/modules/visual_script/visual_script_func_nodes.cpp b/modules/visual_script/visual_script_func_nodes.cpp
index 8d73de9889..cbe4438cdf 100644
--- a/modules/visual_script/visual_script_func_nodes.cpp
+++ b/modules/visual_script/visual_script_func_nodes.cpp
@@ -29,9 +29,9 @@
/*************************************************************************/
#include "visual_script_func_nodes.h"
+#include "engine.h"
#include "io/resource_loader.h"
#include "os/os.h"
-#include "project_settings.h"
#include "scene/main/node.h"
#include "scene/main/scene_tree.h"
#include "visual_script_nodes.h"
@@ -344,7 +344,7 @@ void VisualScriptFunctionCall::set_singleton(const StringName &p_type) {
return;
singleton = p_type;
- Object *obj = ProjectSettings::get_singleton()->get_singleton_object(singleton);
+ Object *obj = Engine::get_singleton()->get_singleton_object(singleton);
if (obj) {
base_type = obj->get_class();
}
@@ -380,7 +380,7 @@ void VisualScriptFunctionCall::_update_method_cache() {
} else if (call_mode == CALL_MODE_SINGLETON) {
- Object *obj = ProjectSettings::get_singleton()->get_singleton_object(singleton);
+ Object *obj = Engine::get_singleton()->get_singleton_object(singleton);
if (obj) {
type = obj->get_class();
script = obj->get_script();
@@ -565,11 +565,11 @@ void VisualScriptFunctionCall::_validate_property(PropertyInfo &property) const
if (call_mode != CALL_MODE_SINGLETON) {
property.usage = 0;
} else {
- List<ProjectSettings::Singleton> names;
- ProjectSettings::get_singleton()->get_singletons(&names);
+ List<Engine::Singleton> names;
+ Engine::get_singleton()->get_singletons(&names);
property.hint = PROPERTY_HINT_ENUM;
String sl;
- for (List<ProjectSettings::Singleton>::Element *E = names.front(); E; E = E->next()) {
+ for (List<Engine::Singleton>::Element *E = names.front(); E; E = E->next()) {
if (sl != String())
sl += ",";
sl += E->get().name;
@@ -603,7 +603,7 @@ void VisualScriptFunctionCall::_validate_property(PropertyInfo &property) const
property.hint_string = itos(get_visual_script()->get_instance_id());
} else if (call_mode == CALL_MODE_SINGLETON) {
- Object *obj = ProjectSettings::get_singleton()->get_singleton_object(singleton);
+ Object *obj = Engine::get_singleton()->get_singleton_object(singleton);
if (obj) {
property.hint = PROPERTY_HINT_METHOD_OF_INSTANCE;
property.hint_string = itos(obj->get_instance_id());
@@ -858,6 +858,8 @@ public:
if (call_mode == VisualScriptFunctionCall::CALL_MODE_INSTANCE) {
if (returns >= 2) {
*p_outputs[1] = v.call(function, p_inputs + 1, input_args, r_error);
+ } else if (returns == 1) {
+ v.call(function, p_inputs + 1, input_args, r_error);
} else {
r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD;
r_error_str = "Invalid returns count for call_mode == CALL_MODE_INSTANCE";
@@ -877,7 +879,7 @@ public:
} break;
case VisualScriptFunctionCall::CALL_MODE_SINGLETON: {
- Object *object = ProjectSettings::get_singleton()->get_singleton_object(singleton);
+ Object *object = Engine::get_singleton()->get_singleton_object(singleton);
if (!object) {
r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD;
r_error_str = "Invalid singleton name: '" + String(singleton) + "'";
diff --git a/modules/visual_script/visual_script_nodes.cpp b/modules/visual_script/visual_script_nodes.cpp
index 5a34fc3cd9..05ff629d1b 100644
--- a/modules/visual_script/visual_script_nodes.cpp
+++ b/modules/visual_script/visual_script_nodes.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "visual_script_nodes.h"
+#include "engine.h"
#include "global_constants.h"
#include "os/input.h"
#include "os/os.h"
@@ -532,6 +533,7 @@ String VisualScriptOperator::get_text() const {
L"A or B", //OP_OR,
L"A xor B", //OP_XOR,
L"not A", //OP_NOT,
+ L"A in B", //OP_IN,
};
return op_names[op];
@@ -1775,8 +1777,8 @@ VisualScriptBasicTypeConstant::VisualScriptBasicTypeConstant() {
const char *VisualScriptMathConstant::const_name[MATH_CONSTANT_MAX] = {
"One",
"PI",
- "PIx2",
"PI/2",
+ "TAU",
"E",
"Sqrt2",
"INF",
@@ -1786,8 +1788,8 @@ const char *VisualScriptMathConstant::const_name[MATH_CONSTANT_MAX] = {
double VisualScriptMathConstant::const_value[MATH_CONSTANT_MAX] = {
1.0,
Math_PI,
- Math_PI * 2,
Math_PI * 0.5,
+ Math_TAU,
2.71828182845904523536,
Math::sqrt(2.0),
Math_INF,
@@ -1885,8 +1887,8 @@ void VisualScriptMathConstant::_bind_methods() {
BIND_ENUM_CONSTANT(MATH_CONSTANT_ONE);
BIND_ENUM_CONSTANT(MATH_CONSTANT_PI);
- BIND_ENUM_CONSTANT(MATH_CONSTANT_2PI);
BIND_ENUM_CONSTANT(MATH_CONSTANT_HALF_PI);
+ BIND_ENUM_CONSTANT(MATH_CONSTANT_TAU);
BIND_ENUM_CONSTANT(MATH_CONSTANT_E);
BIND_ENUM_CONSTANT(MATH_CONSTANT_SQRT2);
BIND_ENUM_CONSTANT(MATH_CONSTANT_INF);
@@ -1975,13 +1977,13 @@ public:
VisualScriptNodeInstance *VisualScriptEngineSingleton::instance(VisualScriptInstance *p_instance) {
VisualScriptNodeInstanceEngineSingleton *instance = memnew(VisualScriptNodeInstanceEngineSingleton);
- instance->singleton = ProjectSettings::get_singleton()->get_singleton_object(singleton);
+ instance->singleton = Engine::get_singleton()->get_singleton_object(singleton);
return instance;
}
VisualScriptEngineSingleton::TypeGuess VisualScriptEngineSingleton::guess_output_type(TypeGuess *p_inputs, int p_output) const {
- Object *obj = ProjectSettings::get_singleton()->get_singleton_object(singleton);
+ Object *obj = Engine::get_singleton()->get_singleton_object(singleton);
TypeGuess tg;
tg.type = Variant::OBJECT;
if (obj) {
@@ -1999,11 +2001,11 @@ void VisualScriptEngineSingleton::_bind_methods() {
String cc;
- List<ProjectSettings::Singleton> singletons;
+ List<Engine::Singleton> singletons;
- ProjectSettings::get_singleton()->get_singletons(&singletons);
+ Engine::get_singleton()->get_singletons(&singletons);
- for (List<ProjectSettings::Singleton>::Element *E = singletons.front(); E; E = E->next()) {
+ for (List<Engine::Singleton>::Element *E = singletons.front(); E; E = E->next()) {
if (E->get().name == "VS" || E->get().name == "PS" || E->get().name == "PS2D" || E->get().name == "AS" || E->get().name == "TS" || E->get().name == "SS" || E->get().name == "SS2D")
continue; //skip these, too simple named
diff --git a/modules/visual_script/visual_script_nodes.h b/modules/visual_script/visual_script_nodes.h
index 421409b265..6648f57e7b 100644
--- a/modules/visual_script/visual_script_nodes.h
+++ b/modules/visual_script/visual_script_nodes.h
@@ -474,8 +474,8 @@ public:
enum MathConstant {
MATH_CONSTANT_ONE,
MATH_CONSTANT_PI,
- MATH_CONSTANT_2PI,
MATH_CONSTANT_HALF_PI,
+ MATH_CONSTANT_TAU,
MATH_CONSTANT_E,
MATH_CONSTANT_SQRT2,
MATH_CONSTANT_INF,
diff --git a/modules/visual_script/visual_script_yield_nodes.cpp b/modules/visual_script/visual_script_yield_nodes.cpp
index bc033418ba..3c9076246d 100644
--- a/modules/visual_script/visual_script_yield_nodes.cpp
+++ b/modules/visual_script/visual_script_yield_nodes.cpp
@@ -82,7 +82,7 @@ String VisualScriptYield::get_text() const {
switch (yield_mode) {
case YIELD_RETURN: return ""; break;
case YIELD_FRAME: return "Next Frame"; break;
- case YIELD_PHYSICS_FRAME: return "Next Fixed Frame"; break;
+ case YIELD_PHYSICS_FRAME: return "Next Physics Frame"; break;
case YIELD_WAIT: return rtos(wait_time) + " sec(s)"; break;
}
@@ -186,7 +186,7 @@ void VisualScriptYield::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_wait_time", "sec"), &VisualScriptYield::set_wait_time);
ClassDB::bind_method(D_METHOD("get_wait_time"), &VisualScriptYield::get_wait_time);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Frame,FixedFrame,Time", PROPERTY_USAGE_NOEDITOR), "set_yield_mode", "get_yield_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Frame,Physics Frame,Time", PROPERTY_USAGE_NOEDITOR), "set_yield_mode", "get_yield_mode");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "wait_time"), "set_wait_time", "get_wait_time");
BIND_ENUM_CONSTANT(YIELD_FRAME);
diff --git a/modules/vorbis/SCsub b/modules/vorbis/SCsub
index 9d2d0feb92..55a112585b 100644
--- a/modules/vorbis/SCsub
+++ b/modules/vorbis/SCsub
@@ -5,6 +5,8 @@ Import('env_modules')
env_vorbis = env_modules.Clone()
+stub = True
+
# Thirdparty source files
if env['builtin_libvorbis']:
thirdparty_dir = "#thirdparty/libvorbis/"
@@ -45,5 +47,9 @@ if env['builtin_libvorbis']:
if env['builtin_libogg']:
env_vorbis.Append(CPPPATH=["#thirdparty/libogg"])
-# Godot source files
-env_vorbis.add_source_files(env.modules_sources, "*.cpp")
+if not stub:
+ # Module files
+ env_vorbis.add_source_files(env.modules_sources, "*.cpp")
+else:
+ # Module files
+ env_vorbis.add_source_files(env.modules_sources, "stub/register_types.cpp")
diff --git a/modules/vorbis/audio_stream_ogg_vorbis.cpp b/modules/vorbis/audio_stream_ogg_vorbis.cpp
index 0afb889199..9fb6fa8197 100644
--- a/modules/vorbis/audio_stream_ogg_vorbis.cpp
+++ b/modules/vorbis/audio_stream_ogg_vorbis.cpp
@@ -92,7 +92,7 @@ long AudioStreamPlaybackOGGVorbis::_ov_tell_func(void *_f) {
return fa->get_position();
}
-int AudioStreamPlaybackOGGVorbis::mix(int16_t *p_bufer, int p_frames) {
+int AudioStreamPlaybackOGGVorbis::mix(int16_t *p_buffer, int p_frames) {
if (!playing)
return 0;
@@ -106,12 +106,10 @@ int AudioStreamPlaybackOGGVorbis::mix(int16_t *p_bufer, int p_frames) {
break;
}
-//printf("to mix %i - mix me %i bytes\n",to_mix,to_mix*stream_channels*sizeof(int16_t));
-
#ifdef BIG_ENDIAN_ENABLED
- long ret = ov_read(&vf, (char *)p_bufer, todo * stream_channels * sizeof(int16_t), 1, 2, 1, &current_section);
+ long ret = ov_read(&vf, (char *)p_buffer, todo * stream_channels * sizeof(int16_t), 1, 2, 1, &current_section);
#else
- long ret = ov_read(&vf, (char *)p_bufer, todo * stream_channels * sizeof(int16_t), 0, 2, 1, &current_section);
+ long ret = ov_read(&vf, (char *)p_buffer, todo * stream_channels * sizeof(int16_t), 0, 2, 1, &current_section);
#endif
if (ret < 0) {
@@ -162,7 +160,7 @@ int AudioStreamPlaybackOGGVorbis::mix(int16_t *p_bufer, int p_frames) {
frames_mixed += ret;
- p_bufer += ret * stream_channels;
+ p_buffer += ret * stream_channels;
p_frames -= ret;
}
@@ -359,7 +357,7 @@ void AudioStreamPlaybackOGGVorbis::set_paused(bool p_paused) {
paused = p_paused;
}
-bool AudioStreamPlaybackOGGVorbis::is_paused(bool p_paused) const {
+bool AudioStreamPlaybackOGGVorbis::is_paused() const {
return paused;
}
diff --git a/modules/vorbis/audio_stream_ogg_vorbis.h b/modules/vorbis/audio_stream_ogg_vorbis.h
index 929b2651e9..5000d03fd4 100644
--- a/modules/vorbis/audio_stream_ogg_vorbis.h
+++ b/modules/vorbis/audio_stream_ogg_vorbis.h
@@ -85,7 +85,7 @@ public:
virtual void set_loop_restart_time(float p_time) { loop_restart_time = p_time; }
virtual void set_paused(bool p_paused);
- virtual bool is_paused(bool p_paused) const;
+ virtual bool is_paused() const;
virtual void set_loop(bool p_enable);
virtual bool has_loop() const;
@@ -103,7 +103,7 @@ public:
virtual int get_mix_rate() const { return stream_srate; }
virtual int get_minimum_buffer_size() const { return 0; }
- virtual int mix(int16_t *p_bufer, int p_frames);
+ virtual int mix(int16_t *p_buffer, int p_frames);
AudioStreamPlaybackOGGVorbis();
~AudioStreamPlaybackOGGVorbis();
diff --git a/modules/vorbis/config.py b/modules/vorbis/config.py
index ef5daca05c..5f133eba90 100644
--- a/modules/vorbis/config.py
+++ b/modules/vorbis/config.py
@@ -1,8 +1,5 @@
-
def can_build(platform):
-# return True
- return False
-
+ return True
def configure(env):
pass
diff --git a/modules/vorbis/stub/register_types.cpp b/modules/vorbis/stub/register_types.cpp
new file mode 100644
index 0000000000..b93d890436
--- /dev/null
+++ b/modules/vorbis/stub/register_types.cpp
@@ -0,0 +1,36 @@
+/*************************************************************************/
+/* register_types.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#include "register_types.h"
+
+// Dummy module as libvorbis is needed by other modules (theora ...)
+
+void register_vorbis_types() {}
+
+void unregister_vorbis_types() {}
diff --git a/modules/vorbis/stub/register_types.h b/modules/vorbis/stub/register_types.h
new file mode 100644
index 0000000000..e7cde7a66c
--- /dev/null
+++ b/modules/vorbis/stub/register_types.h
@@ -0,0 +1,31 @@
+/*************************************************************************/
+/* register_types.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 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. */
+/*************************************************************************/
+void register_vorbis_types();
+void unregister_vorbis_types();
diff --git a/modules/webm/config.py b/modules/webm/config.py
index ef5daca05c..dcae4447d5 100644
--- a/modules/webm/config.py
+++ b/modules/webm/config.py
@@ -1,8 +1,14 @@
-
def can_build(platform):
-# return True
- return False
-
+ return platform != 'iphone'
def configure(env):
pass
+
+def get_doc_classes():
+ return [
+ "ResourceImporterWebm",
+ "VideoStreamWebm",
+ ]
+
+def get_doc_path():
+ return "doc_classes"
diff --git a/doc/classes/VisualScriptSwitch.xml b/modules/webm/doc_classes/ResourceImporterWebm.xml
index 95ed737372..dcba351e37 100644
--- a/doc/classes/VisualScriptSwitch.xml
+++ b/modules/webm/doc_classes/ResourceImporterWebm.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptSwitch" inherits="VisualScriptNode" category="Core" version="3.0.alpha.custom_build">
+<class name="ResourceImporterWebm" inherits="ResourceImporter" category="Core" version="3.0-alpha">
<brief_description>
</brief_description>
<description>
diff --git a/modules/webm/doc_classes/VideoStreamWebm.xml b/modules/webm/doc_classes/VideoStreamWebm.xml
new file mode 100644
index 0000000000..9a430f6b0d
--- /dev/null
+++ b/modules/webm/doc_classes/VideoStreamWebm.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="VideoStreamWebm" inherits="VideoStream" category="Core" version="3.0-alpha">
+ <brief_description>
+ </brief_description>
+ <description>
+ </description>
+ <tutorials>
+ </tutorials>
+ <demos>
+ </demos>
+ <methods>
+ <method name="get_file">
+ <return type="String">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="set_file">
+ <return type="void">
+ </return>
+ <argument index="0" name="file" type="String">
+ </argument>
+ <description>
+ </description>
+ </method>
+ </methods>
+ <members>
+ <member name="file" type="String" setter="set_file" getter="get_file">
+ </member>
+ </members>
+ <constants>
+ </constants>
+</class>
diff --git a/modules/webm/libvpx/SCsub b/modules/webm/libvpx/SCsub
index fd8d762a5e..73ba17d184 100644
--- a/modules/webm/libvpx/SCsub
+++ b/modules/webm/libvpx/SCsub
@@ -298,7 +298,7 @@ if webm_cpu_x86:
if not yasm_found:
webm_cpu_x86 = False
- print "YASM is necessary for WebM SIMD optimizations."
+ print("YASM is necessary for WebM SIMD optimizations.")
webm_simd_optimizations = False
@@ -345,7 +345,7 @@ if webm_cpu_arm:
webm_simd_optimizations = True
if webm_simd_optimizations == False:
- print "WebM SIMD optimizations are disabled. Check if your CPU architecture, CPU bits or platform are supported!"
+ print("WebM SIMD optimizations are disabled. Check if your CPU architecture, CPU bits or platform are supported!")
env_libvpx.add_source_files(env.modules_sources, libvpx_sources)
diff --git a/modules/webm/register_types.cpp b/modules/webm/register_types.cpp
index 892d1b8420..669c9997f1 100644
--- a/modules/webm/register_types.cpp
+++ b/modules/webm/register_types.cpp
@@ -28,19 +28,18 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "register_types.h"
-
+#include "resource_importer_webm.h"
#include "video_stream_webm.h"
-static ResourceFormatLoaderVideoStreamWebm *webm_stream_loader = NULL;
-
void register_webm_types() {
- webm_stream_loader = memnew(ResourceFormatLoaderVideoStreamWebm);
- ResourceLoader::add_resource_format_loader(webm_stream_loader);
+#ifdef TOOLS_ENABLED
+ Ref<ResourceImporterWebm> webm_import;
+ webm_import.instance();
+ ResourceFormatImporter::get_singleton()->add_importer(webm_import);
+#endif
ClassDB::register_class<VideoStreamWebm>();
}
void unregister_webm_types() {
-
- memdelete(webm_stream_loader);
}
diff --git a/modules/webm/resource_importer_webm.cpp b/modules/webm/resource_importer_webm.cpp
new file mode 100644
index 0000000000..5db3d4df2e
--- /dev/null
+++ b/modules/webm/resource_importer_webm.cpp
@@ -0,0 +1,95 @@
+/*************************************************************************/
+/* resource_importer_webm.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#include "resource_importer_webm.h"
+
+#include "io/resource_saver.h"
+#include "os/file_access.h"
+#include "scene/resources/texture.h"
+#include "video_stream_webm.h"
+
+String ResourceImporterWebm::get_importer_name() const {
+
+ return "Webm";
+}
+
+String ResourceImporterWebm::get_visible_name() const {
+
+ return "Webm";
+}
+void ResourceImporterWebm::get_recognized_extensions(List<String> *p_extensions) const {
+
+ p_extensions->push_back("webm");
+}
+
+String ResourceImporterWebm::get_save_extension() const {
+ return "webmstr";
+}
+
+String ResourceImporterWebm::get_resource_type() const {
+
+ return "VideoStreamWebm";
+}
+
+bool ResourceImporterWebm::get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const {
+
+ return true;
+}
+
+int ResourceImporterWebm::get_preset_count() const {
+ return 0;
+}
+String ResourceImporterWebm::get_preset_name(int p_idx) const {
+
+ return String();
+}
+
+void ResourceImporterWebm::get_import_options(List<ImportOption> *r_options, int p_preset) const {
+
+ r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "loop"), true));
+}
+
+Error ResourceImporterWebm::import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files) {
+
+ FileAccess *f = FileAccess::open(p_source_file, FileAccess::READ);
+ if (!f) {
+ ERR_FAIL_COND_V(!f, ERR_CANT_OPEN);
+ }
+ memdelete(f);
+
+ VideoStreamWebm *stream = memnew(VideoStreamWebm);
+ stream->set_file(p_source_file);
+
+ Ref<VideoStreamWebm> webm_stream = Ref<VideoStreamWebm>(stream);
+
+ return ResourceSaver::save(p_save_path + ".webmstr", webm_stream);
+}
+
+ResourceImporterWebm::ResourceImporterWebm() {
+}
diff --git a/modules/webm/resource_importer_webm.h b/modules/webm/resource_importer_webm.h
new file mode 100644
index 0000000000..4cedd1598d
--- /dev/null
+++ b/modules/webm/resource_importer_webm.h
@@ -0,0 +1,55 @@
+/*************************************************************************/
+/* resource_importer_webm.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#ifndef RESOURCEIMPORTERWEBM_H
+#define RESOURCEIMPORTERWEBM_H
+
+#include "io/resource_import.h"
+
+class ResourceImporterWebm : public ResourceImporter {
+ GDCLASS(ResourceImporterWebm, ResourceImporter)
+public:
+ virtual String get_importer_name() const;
+ virtual String get_visible_name() const;
+ virtual void get_recognized_extensions(List<String> *p_extensions) const;
+ virtual String get_save_extension() const;
+ virtual String get_resource_type() const;
+
+ virtual int get_preset_count() const;
+ virtual String get_preset_name(int p_idx) const;
+
+ virtual void get_import_options(List<ImportOption> *r_options, int p_preset = 0) const;
+ virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const;
+
+ virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = NULL);
+
+ ResourceImporterWebm();
+};
+
+#endif // RESOURCEIMPORTERWEBM_H
diff --git a/modules/webm/video_stream_webm.cpp b/modules/webm/video_stream_webm.cpp
index 2ec6b27471..0fc9df5b58 100644
--- a/modules/webm/video_stream_webm.cpp
+++ b/modules/webm/video_stream_webm.cpp
@@ -35,10 +35,13 @@
#include "mkvparser/mkvparser.h"
#include "os/file_access.h"
+#include "os/os.h"
#include "project_settings.h"
#include "thirdparty/misc/yuv2rgb.h"
+#include "servers/audio_server.h"
+
#include <string.h>
class MkvReader : public mkvparser::IMkvReader {
@@ -47,6 +50,8 @@ public:
MkvReader(const String &p_file) {
file = FileAccess::open(p_file, FileAccess::READ);
+
+ ERR_EXPLAIN("Failed loading resource: '" + p_file + "';");
ERR_FAIL_COND(!file);
}
~MkvReader() {
@@ -113,14 +118,14 @@ bool VideoStreamPlaybackWebm::open_file(const String &p_file) {
webm = memnew(WebMDemuxer(new MkvReader(file_name), 0, audio_track));
if (webm->isOpen()) {
- video = memnew(VPXDecoder(*webm, 8)); //TODO: Detect CPU threads
+ video = memnew(VPXDecoder(*webm, OS::get_singleton()->get_processor_count()));
if (video->isOpen()) {
audio = memnew(OpusVorbisDecoder(*webm));
if (audio->isOpen()) {
audio_frame = memnew(WebMFrame);
- pcm = (int16_t *)memalloc(sizeof(int16_t) * audio->getBufferSamples() * webm->getChannels());
+ pcm = (float *)memalloc(sizeof(float) * audio->getBufferSamples() * webm->getChannels());
} else {
memdelete(audio);
@@ -183,7 +188,7 @@ void VideoStreamPlaybackWebm::set_paused(bool p_paused) {
paused = p_paused;
}
-bool VideoStreamPlaybackWebm::is_paused(bool p_paused) const {
+bool VideoStreamPlaybackWebm::is_paused() const {
return paused;
}
@@ -222,11 +227,18 @@ Ref<Texture> VideoStreamPlaybackWebm::get_texture() {
return texture;
}
+
void VideoStreamPlaybackWebm::update(float p_delta) {
if ((!playing || paused) || !video)
return;
+ time += p_delta;
+
+ if (time < video_pos) {
+ return;
+ }
+
bool audio_buffer_full = false;
if (samples_offset > -1) {
@@ -245,13 +257,15 @@ void VideoStreamPlaybackWebm::update(float p_delta) {
}
const bool hasAudio = (audio && mix_callback);
- while ((hasAudio && (!audio_buffer_full || !has_enough_video_frames())) || (!hasAudio && video_frames_pos == 0)) {
+ while ((hasAudio && !audio_buffer_full && !has_enough_video_frames()) ||
+ (!hasAudio && video_frames_pos == 0)) {
- if (hasAudio && !audio_buffer_full && audio_frame->isValid() && audio->getPCMS16(*audio_frame, pcm, num_decoded_samples) && num_decoded_samples > 0) {
+ if (hasAudio && !audio_buffer_full && audio_frame->isValid() &&
+ audio->getPCMF(*audio_frame, pcm, num_decoded_samples) && num_decoded_samples > 0) {
const int mixed = mix_callback(mix_udata, pcm, num_decoded_samples);
- if (mixed != num_decoded_samples) {
+ if (mixed != num_decoded_samples) {
samples_offset = mixed;
audio_buffer_full = true;
}
@@ -273,72 +287,61 @@ void VideoStreamPlaybackWebm::update(float p_delta) {
++video_frames_pos;
};
- const double video_delay = video->getFramesDelay() * video_frame_delay;
-
- bool want_this_frame = false;
- while (video_frames_pos > 0 && !want_this_frame) {
+ bool video_frame_done = false;
+ while (video_frames_pos > 0 && !video_frame_done) {
WebMFrame *video_frame = video_frames[0];
- if (video_frame->time <= time + video_delay) {
- if (video->decode(*video_frame)) {
+ // It seems VPXDecoder::decode has to be executed even though we might skip this frame
+ if (video->decode(*video_frame)) {
- VPXDecoder::IMAGE_ERROR err;
- VPXDecoder::Image image;
+ VPXDecoder::IMAGE_ERROR err;
+ VPXDecoder::Image image;
- while ((err = video->getImage(image)) != VPXDecoder::NO_FRAME) {
+ if (should_process(*video_frame)) {
- want_this_frame = (time - video_frame->time <= video_frame_delay);
+ if ((err = video->getImage(image)) != VPXDecoder::NO_FRAME) {
- if (want_this_frame) {
+ if (err == VPXDecoder::NO_ERROR && image.w == webm->getWidth() && image.h == webm->getHeight()) {
- if (err == VPXDecoder::NO_ERROR && image.w == webm->getWidth() && image.h == webm->getHeight()) {
+ PoolVector<uint8_t>::Write w = frame_data.write();
+ bool converted = false;
- PoolVector<uint8_t>::Write w = frame_data.write();
- bool converted = false;
+ if (image.chromaShiftW == 1 && image.chromaShiftH == 1) {
- if (image.chromaShiftW == 1 && image.chromaShiftH == 1) {
+ yuv420_2_rgb8888(w.ptr(), image.planes[0], image.planes[2], image.planes[1], image.w, image.h, image.linesize[0], image.linesize[1], image.w << 2, 0);
+ // libyuv::I420ToARGB(image.planes[0], image.linesize[0], image.planes[2], image.linesize[2], image.planes[1], image.linesize[1], w.ptr(), image.w << 2, image.w, image.h);
+ converted = true;
+ } else if (image.chromaShiftW == 1 && image.chromaShiftH == 0) {
- yuv420_2_rgb8888(w.ptr(), image.planes[0], image.planes[2], image.planes[1], image.w, image.h, image.linesize[0], image.linesize[1], image.w << 2, 0);
- // libyuv::I420ToARGB(image.planes[0], image.linesize[0], image.planes[2], image.linesize[2], image.planes[1], image.linesize[1], w.ptr(), image.w << 2, image.w, image.h);
- converted = true;
- } else if (image.chromaShiftW == 1 && image.chromaShiftH == 0) {
+ yuv422_2_rgb8888(w.ptr(), image.planes[0], image.planes[2], image.planes[1], image.w, image.h, image.linesize[0], image.linesize[1], image.w << 2, 0);
+ // libyuv::I422ToARGB(image.planes[0], image.linesize[0], image.planes[2], image.linesize[2], image.planes[1], image.linesize[1], w.ptr(), image.w << 2, image.w, image.h);
+ converted = true;
+ } else if (image.chromaShiftW == 0 && image.chromaShiftH == 0) {
- yuv422_2_rgb8888(w.ptr(), image.planes[0], image.planes[2], image.planes[1], image.w, image.h, image.linesize[0], image.linesize[1], image.w << 2, 0);
- // libyuv::I422ToARGB(image.planes[0], image.linesize[0], image.planes[2], image.linesize[2], image.planes[1], image.linesize[1], w.ptr(), image.w << 2, image.w, image.h);
- converted = true;
- } else if (image.chromaShiftW == 0 && image.chromaShiftH == 0) {
+ yuv444_2_rgb8888(w.ptr(), image.planes[0], image.planes[2], image.planes[1], image.w, image.h, image.linesize[0], image.linesize[1], image.w << 2, 0);
+ // libyuv::I444ToARGB(image.planes[0], image.linesize[0], image.planes[2], image.linesize[2], image.planes[1], image.linesize[1], w.ptr(), image.w << 2, image.w, image.h);
+ converted = true;
+ } else if (image.chromaShiftW == 2 && image.chromaShiftH == 0) {
- yuv444_2_rgb8888(w.ptr(), image.planes[0], image.planes[2], image.planes[1], image.w, image.h, image.linesize[0], image.linesize[1], image.w << 2, 0);
- // libyuv::I444ToARGB(image.planes[0], image.linesize[0], image.planes[2], image.linesize[2], image.planes[1], image.linesize[1], w.ptr(), image.w << 2, image.w, image.h);
- converted = true;
- } else if (image.chromaShiftW == 2 && image.chromaShiftH == 0) {
-
- // libyuv::I411ToARGB(image.planes[0], image.linesize[0], image.planes[2], image.linesize[2], image.planes[1], image.linesize[1], w.ptr(), image.w << 2, image.w, image.h);
- // converted = true;
- }
-
- if (converted)
- texture->set_data(Image(image.w, image.h, 0, Image::FORMAT_RGBA8, frame_data)); //Zero copy send to visual server
+ // libyuv::I411ToARGB(image.planes[0], image.linesize[0], image.planes[2], image.linesize[2], image.planes[1], image.linesize[1], w.ptr(), image.w << 2, image.w, image.h);
+ // converted = true;
}
- break;
+ if (converted) {
+ Ref<Image> img = memnew(Image(image.w, image.h, 0, Image::FORMAT_RGBA8, frame_data));
+ texture->set_data(img); //Zero copy send to visual server
+ video_frame_done = true;
+ }
}
}
}
-
- video_frame_delay = video_frame->time - video_pos;
- video_pos = video_frame->time;
-
- memmove(video_frames, video_frames + 1, (--video_frames_pos) * sizeof(void *));
- video_frames[video_frames_pos] = video_frame;
- } else {
-
- break;
}
- }
- time += p_delta;
+ video_pos = video_frame->time;
+ memmove(video_frames, video_frames + 1, (--video_frames_pos) * sizeof(void *));
+ video_frames[video_frames_pos] = video_frame;
+ }
if (video_frames_pos == 0 && webm->isEOS())
stop();
@@ -372,6 +375,11 @@ inline bool VideoStreamPlaybackWebm::has_enough_video_frames() const {
return false;
}
+bool VideoStreamPlaybackWebm::should_process(WebMFrame &video_frame) {
+ const double audio_delay = AudioServer::get_singleton()->get_output_delay();
+ return video_frame.time >= time + audio_delay + delay_compensation;
+}
+
void VideoStreamPlaybackWebm::delete_pointers() {
if (pcm)
@@ -395,34 +403,6 @@ void VideoStreamPlaybackWebm::delete_pointers() {
/**/
-RES ResourceFormatLoaderVideoStreamWebm::load(const String &p_path, const String &p_original_path, Error *r_error) {
-
- Ref<VideoStreamWebm> stream = memnew(VideoStreamWebm);
- stream->set_file(p_path);
- if (r_error)
- *r_error = OK;
- return stream;
-}
-
-void ResourceFormatLoaderVideoStreamWebm::get_recognized_extensions(List<String> *p_extensions) const {
-
- p_extensions->push_back("webm");
-}
-bool ResourceFormatLoaderVideoStreamWebm::handles_type(const String &p_type) const {
-
- return (p_type == "VideoStream" || p_type == "VideoStreamWebm");
-}
-
-String ResourceFormatLoaderVideoStreamWebm::get_resource_type(const String &p_path) const {
-
- const String exl = p_path.get_extension().to_lower();
- if (exl == "webm")
- return "VideoStreamWebm";
- return "";
-}
-
-/**/
-
VideoStreamWebm::VideoStreamWebm()
: audio_track(0) {}
@@ -439,6 +419,19 @@ void VideoStreamWebm::set_file(const String &p_file) {
file = p_file;
}
+String VideoStreamWebm::get_file() {
+
+ return file;
+}
+
+void VideoStreamWebm::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("set_file", "file"), &VideoStreamWebm::set_file);
+ ClassDB::bind_method(D_METHOD("get_file"), &VideoStreamWebm::get_file);
+
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "file", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_file", "get_file");
+}
+
void VideoStreamWebm::set_audio_track(int p_track) {
audio_track = p_track;
diff --git a/modules/webm/video_stream_webm.h b/modules/webm/video_stream_webm.h
index fc0720967a..f7dd16a38f 100644
--- a/modules/webm/video_stream_webm.h
+++ b/modules/webm/video_stream_webm.h
@@ -60,7 +60,7 @@ class VideoStreamPlaybackWebm : public VideoStreamPlayback {
PoolVector<uint8_t> frame_data;
Ref<ImageTexture> texture;
- int16_t *pcm;
+ float *pcm;
public:
VideoStreamPlaybackWebm();
@@ -74,7 +74,7 @@ public:
virtual bool is_playing() const;
virtual void set_paused(bool p_paused);
- virtual bool is_paused(bool p_paused) const;
+ virtual bool is_paused() const;
virtual void set_loop(bool p_enable);
virtual bool has_loop() const;
@@ -95,6 +95,7 @@ public:
private:
inline bool has_enough_video_frames() const;
+ bool should_process(WebMFrame &video_frame);
void delete_pointers();
};
@@ -103,27 +104,21 @@ private:
class VideoStreamWebm : public VideoStream {
- GDCLASS(VideoStreamWebm, VideoStream)
+ GDCLASS(VideoStreamWebm, VideoStream);
+ RES_BASE_EXTENSION("webmstr");
String file;
int audio_track;
+protected:
+ static void _bind_methods();
+
public:
VideoStreamWebm();
virtual Ref<VideoStreamPlayback> instance_playback();
virtual void set_file(const String &p_file);
+ String get_file();
virtual void set_audio_track(int p_track);
};
-
-/**/
-
-class ResourceFormatLoaderVideoStreamWebm : public ResourceFormatLoader {
-
-public:
- virtual RES load(const String &p_path, const String &p_original_path, Error *r_error);
- virtual void get_recognized_extensions(List<String> *p_extensions) const;
- virtual bool handles_type(const String &p_type) const;
- virtual String get_resource_type(const String &p_path) const;
-};
diff --git a/modules/webp/config.py b/modules/webp/config.py
index fb920482f5..5f133eba90 100644
--- a/modules/webp/config.py
+++ b/modules/webp/config.py
@@ -1,7 +1,5 @@
-
def can_build(platform):
return True
-
def configure(env):
pass
diff --git a/platform/SCsub b/platform/SCsub
new file mode 100644
index 0000000000..4ef23ab053
--- /dev/null
+++ b/platform/SCsub
@@ -0,0 +1,30 @@
+#!/usr/bin/env python
+
+from compat import open_utf8
+
+Import('env')
+platform_sources = []
+
+# Register platform-exclusive APIs
+reg_apis_inc = '#include "register_platform_apis.h"\n'
+reg_apis = 'void register_platform_apis() {\n'
+unreg_apis = 'void unregister_platform_apis() {\n'
+for platform in env.platform_apis:
+ platform_dir = env.Dir(platform)
+ platform_sources.append(platform_dir.File('api/api.cpp'))
+ reg_apis += '\tregister_' + platform + '_api();\n'
+ unreg_apis += '\tunregister_' + platform + '_api();\n'
+ reg_apis_inc += '#include "' + platform + '/api/api.h"\n'
+reg_apis_inc += '\n'
+reg_apis += '}\n\n'
+unreg_apis += '}\n'
+f = open_utf8('register_platform_apis.gen.cpp', 'w')
+f.write(reg_apis_inc)
+f.write(reg_apis)
+f.write(unreg_apis)
+f.close()
+platform_sources.append('register_platform_apis.gen.cpp')
+
+env.Prepend(LIBS=env.Library('platform', platform_sources))
+
+Export('env')
diff --git a/platform/android/SCsub b/platform/android/SCsub
index e9a370869f..7fa0262359 100644
--- a/platform/android/SCsub
+++ b/platform/android/SCsub
@@ -46,8 +46,18 @@ gradle_baseout = open_utf8(abspath + "/java/build.gradle", "w")
gradle_text = gradle_basein.read()
-
+gradle_maven_flat_text = ""
+if len(env.android_flat_dirs) > 0:
+ gradle_maven_flat_text += "flatDir {\n"
+ gradle_maven_flat_text += "\tdirs "
+ for x in env.android_flat_dirs:
+ gradle_maven_flat_text += "'" + x + "',"
+
+ gradle_maven_flat_text = gradle_maven_flat_text[:-1]
+ gradle_maven_flat_text += "\n\t}\n"
+
gradle_maven_repos_text = ""
+gradle_maven_repos_text += gradle_maven_flat_text
if len(env.android_maven_repos) > 0:
gradle_maven_repos_text += ""
diff --git a/platform/android/build.gradle.template b/platform/android/build.gradle.template
index 1df56ce621..11c49fbb50 100644
--- a/platform/android/build.gradle.template
+++ b/platform/android/build.gradle.template
@@ -1,6 +1,7 @@
buildscript {
repositories {
jcenter()
+ $$GRADLE_REPOSITORY_URLS$$
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.3'
@@ -30,7 +31,7 @@ android {
disable 'MissingTranslation'
}
- compileSdkVersion 23
+ compileSdkVersion 24
buildToolsVersion "26.0.1"
useLibrary 'org.apache.http.legacy'
@@ -54,11 +55,11 @@ android {
]
res.srcDirs = [
'res'
- $$GRADLE_RES_DIRS$$
+ $$GRADLE_RES_DIRS$$
]
aidl.srcDirs = [
'aidl'
- $$GRADLE_AIDL_DIRS$$
+ $$GRADLE_AIDL_DIRS$$
]
assets.srcDirs = [
'assets'
diff --git a/platform/android/detect.py b/platform/android/detect.py
index 13fc4ee810..bc67f6e6dc 100644
--- a/platform/android/detect.py
+++ b/platform/android/detect.py
@@ -2,6 +2,7 @@ import os
import sys
import string
import platform
+from distutils.version import LooseVersion
def is_active():
@@ -25,7 +26,7 @@ def get_opts():
('ndk_platform', 'Target platform (android-<api>, e.g. "android-18")', "android-18"),
EnumVariable('android_arch', 'Target architecture', "armv7", ('armv7', 'armv6', 'arm64v8', 'x86')),
BoolVariable('android_neon', 'Enable NEON support (armv7 only)', True),
- BoolVariable('android_stl', 'Enable Android STL support (for modules)', False),
+ BoolVariable('android_stl', 'Enable Android STL support (for modules)', True)
]
@@ -172,20 +173,39 @@ def configure(env):
# For Clang to find NDK tools in preference of those system-wide
env.PrependENVPath('PATH', tools_path)
- env['CC'] = compiler_path + '/clang'
- env['CXX'] = compiler_path + '/clang++'
+ ccache_path = os.environ.get("CCACHE")
+ if ccache_path == None:
+ env['CC'] = compiler_path + '/clang'
+ env['CXX'] = compiler_path + '/clang++'
+ else:
+ # there aren't any ccache wrappers available for Android,
+ # to enable caching we need to prepend the path to the ccache binary
+ env['CC'] = ccache_path + ' ' + compiler_path + '/clang'
+ env['CXX'] = ccache_path + ' ' + compiler_path + '/clang++'
env['AR'] = tools_path + "/ar"
env['RANLIB'] = tools_path + "/ranlib"
env['AS'] = tools_path + "/as"
- sysroot = env["ANDROID_NDK_ROOT"] + "/platforms/" + env['ndk_platform'] + "/" + env['ARCH']
common_opts = ['-fno-integrated-as', '-gcc-toolchain', gcc_toolchain_path]
+ lib_sysroot = env["ANDROID_NDK_ROOT"] + "/platforms/" + env['ndk_platform'] + "/" + env['ARCH']
+
## Compile flags
- env.Append(CPPFLAGS=["-isystem", sysroot + "/usr/include"])
+ ndk_version = get_ndk_version(env["ANDROID_NDK_ROOT"])
+ if ndk_version != None and LooseVersion(ndk_version) >= LooseVersion("15.0.4075724"):
+ print("Using NDK unified headers")
+ sysroot = env["ANDROID_NDK_ROOT"] + "/sysroot"
+ env.Append(CPPFLAGS=["-isystem", sysroot + "/usr/include"])
+ env.Append(CPPFLAGS=["-isystem", sysroot + "/usr/include/" + abi_subpath])
+ # For unified headers this define has to be set manually
+ env.Append(CPPFLAGS=["-D__ANDROID_API__=" + str(int(env['ndk_platform'].split("-")[1]))])
+ else:
+ print("Using NDK deprecated headers")
+ env.Append(CPPFLAGS=["-isystem", lib_sysroot + "/usr/include"])
+
env.Append(CPPFLAGS='-fpic -ffunction-sections -funwind-tables -fstack-protector-strong -fvisibility=hidden -fno-strict-aliasing'.split())
- env.Append(CPPFLAGS='-DNO_STATVFS -DGLES2_ENABLED'.split())
+ env.Append(CPPFLAGS='-DNO_STATVFS -DGLES_ENABLED'.split())
env['neon_enabled'] = False
if env['android_arch'] == 'x86':
@@ -224,7 +244,7 @@ def configure(env):
## Link flags
- env['LINKFLAGS'] = ['-shared', '--sysroot=' + sysroot, '-Wl,--warn-shared-textrel']
+ env['LINKFLAGS'] = ['-shared', '--sysroot=' + lib_sysroot, '-Wl,--warn-shared-textrel']
if env["android_arch"] == "armv7":
env.Append(LINKFLAGS='-Wl,--fix-cortex-a8'.split())
env.Append(LINKFLAGS='-Wl,--no-undefined -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now'.split())
@@ -248,3 +268,18 @@ def configure(env):
if (env["android_arch"] == "armv6" or env["android_arch"] == "armv7"):
env.Append(CFLAGS=["-DOPUS_ARM_OPT"])
env.opus_fixed_point = "yes"
+
+# Return NDK version string in source.properties (adapted from the Chromium project).
+def get_ndk_version(path):
+ if path == None:
+ return None
+ prop_file_path = os.path.join(path, "source.properties")
+ try:
+ with open(prop_file_path) as prop_file:
+ for line in prop_file:
+ key_value = map(lambda x: string.strip(x), line.split("="))
+ if key_value[0] == "Pkg.Revision":
+ return key_value[1]
+ except:
+ print("Could not read source prop file '%s'" % prop_file_path)
+ return None
diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp
index 9fe1f291d6..e1ff12c5ac 100644
--- a/platform/android/export/export.cpp
+++ b/platform/android/export/export.cpp
@@ -267,7 +267,6 @@ class EditorExportAndroid : public EditorExportPlatform {
if (different) {
- print_line("DIFFERENT!");
Vector<Device> ndevices;
for (int i = 0; i < ldevices.size(); i++) {
@@ -371,7 +370,7 @@ class EditorExportAndroid : public EditorExportPlatform {
}
if (aname == "") {
- aname = _MKSTR(VERSION_NAME);
+ aname = VERSION_NAME;
}
return aname;
@@ -946,16 +945,17 @@ public:
public:
virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) {
- int api = p_preset->get("graphics/api");
+ // Reenable when a GLES 2.0 backend is readded
+ /*int api = p_preset->get("graphics/api");
if (api == 0)
r_features->push_back("etc");
- else
- r_features->push_back("etc2");
+ else*/
+ r_features->push_back("etc2");
}
virtual void get_export_options(List<ExportOption> *r_options) {
- r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "graphics/api", PROPERTY_HINT_ENUM, "OpenGL ES 2.0,OpenGL ES 3.0"), 1));
+ /*r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "graphics/api", PROPERTY_HINT_ENUM, "OpenGL ES 2.0,OpenGL ES 3.0"), 1));*/
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "graphics/32_bits_framebuffer"), true));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "one_click_deploy/clear_previous_install"), true));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_package/debug", PROPERTY_HINT_GLOBAL_FILE, "apk"), ""));
@@ -1067,7 +1067,7 @@ public:
if (use_reverse)
p_debug_flags |= DEBUG_FLAG_REMOTE_DEBUG_LOCALHOST;
- String export_to = EditorSettings::get_singleton()->get_settings_path() + "/tmp/tmpexport.apk";
+ String export_to = EditorSettings::get_singleton()->get_cache_dir().plus_file("tmpexport.apk");
Error err = export_project(p_preset, true, export_to, p_debug_flags);
if (err) {
device_lock->unlock();
@@ -1292,7 +1292,7 @@ public:
zlib_filefunc_def io2 = io;
FileAccess *dst_f = NULL;
io2.opaque = &dst_f;
- String unaligned_path = EditorSettings::get_singleton()->get_settings_path() + "/tmp/tmpexport-unaligned.apk";
+ String unaligned_path = EditorSettings::get_singleton()->get_cache_dir().plus_file("tmpexport-unaligned.apk");
zipFile unaligned_apk = zipOpen2(unaligned_path.utf8().get_data(), APPEND_STATUS_CREATE, NULL, &io2);
bool export_x86 = p_preset->get("architecture/x86");
diff --git a/platform/android/globals/global_defaults.cpp b/platform/android/globals/global_defaults.cpp
index c73b578154..0e1c17e9c8 100644
--- a/platform/android/globals/global_defaults.cpp
+++ b/platform/android/globals/global_defaults.cpp
@@ -31,12 +31,4 @@
#include "project_settings.h"
void register_android_global_defaults() {
-
- /* GLOBAL_DEF("rasterizer.Android/use_fragment_lighting",false);
- GLOBAL_DEF("rasterizer.Android/fp16_framebuffer",false);
- GLOBAL_DEF("display.Android/driver","GLES2");
- //GLOBAL_DEF("rasterizer.Android/trilinear_mipmap_filter",false);
-
- ProjectSettings::get_singleton()->set_custom_property_info("display.Android/driver",PropertyInfo(Variant::STRING,"display.Android/driver",PROPERTY_HINT_ENUM,"GLES2"));
- */
}
diff --git a/platform/android/godot_android.cpp b/platform/android/godot_android.cpp
index 8235683496..f9bcbadc24 100644
--- a/platform/android/godot_android.cpp
+++ b/platform/android/godot_android.cpp
@@ -29,23 +29,23 @@
/*************************************************************************/
#ifdef ANDROID_NATIVE_ACTIVITY
-#include <errno.h>
-#include <jni.h>
-
-#include <EGL/egl.h>
-#include <GLES2/gl2.h>
-
+#include "engine.h"
#include "file_access_android.h"
#include "main/main.h"
#include "os_android.h"
#include "project_settings.h"
+
+#include <EGL/egl.h>
#include <android/log.h>
#include <android/sensor.h>
#include <android/window.h>
#include <android_native_app_glue.h>
+#include <errno.h>
+#include <jni.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+
#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "godot", __VA_ARGS__))
#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "godot", __VA_ARGS__))
@@ -669,6 +669,14 @@ static void engine_handle_cmd(struct android_app *app, int32_t cmd) {
ASensorEventQueue_setEventRate(engine->sensorEventQueue,
engine->accelerometerSensor, (1000L / 60) * 1000);
}
+ // start monitoring gravity
+ if (engine->gravitySensor != NULL) {
+ ASensorEventQueue_enableSensor(engine->sensorEventQueue,
+ engine->gravitySensor);
+ // We'd like to get 60 events per second (in us).
+ ASensorEventQueue_setEventRate(engine->sensorEventQueue,
+ engine->gravitySensor, (1000L / 60) * 1000);
+ }
// Also start monitoring the magnetometer.
if (engine->magnetometerSensor != NULL) {
ASensorEventQueue_enableSensor(engine->sensorEventQueue,
@@ -694,6 +702,10 @@ static void engine_handle_cmd(struct android_app *app, int32_t cmd) {
ASensorEventQueue_disableSensor(engine->sensorEventQueue,
engine->accelerometerSensor);
}
+ if (engine->gravitySensor != NULL) {
+ ASensorEventQueue_disableSensor(engine->sensorEventQueue,
+ engine->gravitySensor);
+ }
if (engine->magnetometerSensor != NULL) {
ASensorEventQueue_disableSensor(engine->sensorEventQueue,
engine->magnetometerSensor);
@@ -729,6 +741,8 @@ void android_main(struct android_app *app) {
engine.sensorManager = ASensorManager_getInstance();
engine.accelerometerSensor = ASensorManager_getDefaultSensor(engine.sensorManager,
ASENSOR_TYPE_ACCELEROMETER);
+ engine.gravitySensor = ASensorManager_getDefaultSensor(engine.sensorManager,
+ ASENSOR_TYPE_GRAVITY);
engine.magnetometerSensor = ASensorManager_getDefaultSensor(engine.sensorManager,
ASENSOR_TYPE_MAGNETIC_FIELD);
engine.gyroscopeSensor = ASensorManager_getDefaultSensor(engine.sensorManager,
@@ -828,7 +842,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_Godot_registerSingleton(JNIEnv
s->set_instance(env->NewGlobalRef(p_object));
jni_singletons[singname] = s;
- ProjectSettings::get_singleton()->add_singleton(ProjectSettings::Singleton(singname, s));
+ Engine::get_singleton()->add_singleton(Engine::Singleton(singname, s));
}
static Variant::Type get_jni_type(const String &p_type) {
diff --git a/platform/android/java/gradlew.bat b/platform/android/java/gradlew.bat
index aec99730b4..8a0b282aa6 100644
--- a/platform/android/java/gradlew.bat
+++ b/platform/android/java/gradlew.bat
@@ -1,90 +1,90 @@
-@if "%DEBUG%" == "" @echo off
-@rem ##########################################################################
-@rem
-@rem Gradle startup script for Windows
-@rem
-@rem ##########################################################################
-
-@rem Set local scope for the variables with windows NT shell
-if "%OS%"=="Windows_NT" setlocal
-
-@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-set DEFAULT_JVM_OPTS=
-
-set DIRNAME=%~dp0
-if "%DIRNAME%" == "" set DIRNAME=.
-set APP_BASE_NAME=%~n0
-set APP_HOME=%DIRNAME%
-
-@rem Find java.exe
-if defined JAVA_HOME goto findJavaFromJavaHome
-
-set JAVA_EXE=java.exe
-%JAVA_EXE% -version >NUL 2>&1
-if "%ERRORLEVEL%" == "0" goto init
-
-echo.
-echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
-
-goto fail
-
-:findJavaFromJavaHome
-set JAVA_HOME=%JAVA_HOME:"=%
-set JAVA_EXE=%JAVA_HOME%/bin/java.exe
-
-if exist "%JAVA_EXE%" goto init
-
-echo.
-echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
-
-goto fail
-
-:init
-@rem Get command-line arguments, handling Windowz variants
-
-if not "%OS%" == "Windows_NT" goto win9xME_args
-if "%@eval[2+2]" == "4" goto 4NT_args
-
-:win9xME_args
-@rem Slurp the command line arguments.
-set CMD_LINE_ARGS=
-set _SKIP=2
-
-:win9xME_args_slurp
-if "x%~1" == "x" goto execute
-
-set CMD_LINE_ARGS=%*
-goto execute
-
-:4NT_args
-@rem Get arguments from the 4NT Shell from JP Software
-set CMD_LINE_ARGS=%$
-
-:execute
-@rem Setup the command line
-
-set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
-
-@rem Execute Gradle
-"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
-
-:end
-@rem End local scope for the variables with windows NT shell
-if "%ERRORLEVEL%"=="0" goto mainEnd
-
-:fail
-rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
-rem the _cmd.exe /c_ return code!
-if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
-exit /b 1
-
-:mainEnd
-if "%OS%"=="Windows_NT" endlocal
-
-:omega
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/platform/android/java/src/org/godotengine/godot/Godot.java b/platform/android/java/src/org/godotengine/godot/Godot.java
index 053dfa631a..41dcba5c2c 100644
--- a/platform/android/java/src/org/godotengine/godot/Godot.java
+++ b/platform/android/java/src/org/godotengine/godot/Godot.java
@@ -191,6 +191,7 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
protected void onMainPause() {}
protected void onMainResume() {}
protected void onMainDestroy() {}
+ protected boolean onMainBackPressed() { return false; }
protected void onGLDrawFrame(GL10 gl) {}
protected void onGLSurfaceChanged(GL10 gl, int width, int height) {} // singletons will always miss first onGLSurfaceChanged call
@@ -218,6 +219,7 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
private SensorManager mSensorManager;
private Sensor mAccelerometer;
+ private Sensor mGravity;
private Sensor mMagnetometer;
private Sensor mGyroscope;
@@ -434,6 +436,8 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_GAME);
+ mGravity = mSensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY);
+ mSensorManager.registerListener(this, mGravity, SensorManager.SENSOR_DELAY_GAME);
mMagnetometer = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
mSensorManager.registerListener(this, mMagnetometer, SensorManager.SENSOR_DELAY_GAME);
mGyroscope = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
@@ -666,6 +670,7 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
}
});
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_GAME);
+ mSensorManager.registerListener(this, mGravity, SensorManager.SENSOR_DELAY_GAME);
mSensorManager.registerListener(this, mMagnetometer, SensorManager.SENSOR_DELAY_GAME);
mSensorManager.registerListener(this, mGyroscope, SensorManager.SENSOR_DELAY_GAME);
@@ -733,13 +738,16 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
@Override
public void run() {
if (typeOfSensor == Sensor.TYPE_ACCELEROMETER) {
- GodotLib.accelerometer(x,y,z);
+ GodotLib.accelerometer(-x,y,-z);
+ }
+ if (typeOfSensor == Sensor.TYPE_GRAVITY) {
+ GodotLib.gravity(-x,y,-z);
}
if (typeOfSensor == Sensor.TYPE_MAGNETIC_FIELD) {
- GodotLib.magnetometer(x,y,z);
+ GodotLib.magnetometer(-x,y,-z);
}
if (typeOfSensor == Sensor.TYPE_GYROSCOPE) {
- GodotLib.gyroscope(x,y,z);
+ GodotLib.gyroscope(x,-y,z);
}
}
});
@@ -767,9 +775,16 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
*/
@Override public void onBackPressed() {
+ boolean shouldQuit = true;
+
+ for(int i=0;i<singleton_count;i++) {
+ if (singletons[i].onMainBackPressed()) {
+ shouldQuit = false;
+ }
+ }
System.out.printf("** BACK REQUEST!\n");
- if (mView != null) {
+ if (shouldQuit && mView != null) {
mView.queueEvent(new Runnable() {
@Override
public void run() {
diff --git a/platform/android/java/src/org/godotengine/godot/GodotLib.java b/platform/android/java/src/org/godotengine/godot/GodotLib.java
index e0ed4cd38c..6b84ad6555 100644
--- a/platform/android/java/src/org/godotengine/godot/GodotLib.java
+++ b/platform/android/java/src/org/godotengine/godot/GodotLib.java
@@ -53,6 +53,7 @@ public class GodotLib {
public static native void step();
public static native void touch(int what,int pointer,int howmany, int[] arr);
public static native void accelerometer(float x, float y, float z);
+ public static native void gravity(float x, float y, float z);
public static native void magnetometer(float x, float y, float z);
public static native void gyroscope(float x, float y, float z);
public static native void key(int p_scancode, int p_unicode_char, boolean p_pressed);
diff --git a/platform/android/java/src/org/godotengine/godot/GodotView.java b/platform/android/java/src/org/godotengine/godot/GodotView.java
index 3c2ad7cc59..b807b952d4 100644
--- a/platform/android/java/src/org/godotengine/godot/GodotView.java
+++ b/platform/android/java/src/org/godotengine/godot/GodotView.java
@@ -285,13 +285,7 @@ public class GodotView extends GLSurfaceView implements InputDeviceListener {
@Override public boolean onKeyDown(final int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
- queueEvent(new Runnable() {
- @Override
- public void run() {
- GodotLib.back();
- }
- });
-
+ activity.onBackPressed();
// press 'back' button should not terminate program
//normal handle 'back' event in game logic
return true;
diff --git a/platform/android/java/src/org/godotengine/godot/input/GodotTextInputWrapper.java b/platform/android/java/src/org/godotengine/godot/input/GodotTextInputWrapper.java
index 04669a3b0c..ac424ab9f8 100644
--- a/platform/android/java/src/org/godotengine/godot/input/GodotTextInputWrapper.java
+++ b/platform/android/java/src/org/godotengine/godot/input/GodotTextInputWrapper.java
@@ -88,79 +88,48 @@ public class GodotTextInputWrapper implements TextWatcher, OnEditorActionListene
public void beforeTextChanged(final CharSequence pCharSequence, final int start, final int count, final int after) {
//Log.d(TAG, "beforeTextChanged(" + pCharSequence + ")start: " + start + ",count: " + count + ",after: " + after);
- for (int i=0;i<count;i++){
- mView.queueEvent(new Runnable() {
- @Override
- public void run() {
+ mView.queueEvent(new Runnable() {
+ @Override
+ public void run() {
+ for (int i = 0; i < count; ++i) {
GodotLib.key(KeyEvent.KEYCODE_DEL, 0, true);
GodotLib.key(KeyEvent.KEYCODE_DEL, 0, false);
}
- });
- }
+ }
+ });
}
@Override
public void onTextChanged(final CharSequence pCharSequence, final int start, final int before, final int count) {
//Log.d(TAG, "onTextChanged(" + pCharSequence + ")start: " + start + ",count: " + count + ",before: " + before);
- for (int i=start;i<start+count;i++){
- final int ch = pCharSequence.charAt(i);
- mView.queueEvent(new Runnable() {
- @Override
- public void run() {
+ mView.queueEvent(new Runnable() {
+ @Override
+ public void run() {
+ for (int i = start; i < start + count; ++i) {
+ final int ch = pCharSequence.charAt(i);
GodotLib.key(0, ch, true);
GodotLib.key(0, ch, false);
}
- });
- }
-
+ }
+ });
}
@Override
public boolean onEditorAction(final TextView pTextView, final int pActionID, final KeyEvent pKeyEvent) {
if (this.mEdit == pTextView && this.isFullScreenEdit()) {
- // user press the action button, delete all old text and insert new text
- for (int i = this.mOriginText.length(); i > 0; i--) {
- mView.queueEvent(new Runnable() {
- @Override
- public void run() {
- GodotLib.key(KeyEvent.KEYCODE_DEL, 0, true);
- GodotLib.key(KeyEvent.KEYCODE_DEL, 0, false);
- }
- });
+ final String characters = pKeyEvent.getCharacters();
- /*
- if (BuildConfig.DEBUG) {
- Log.d(TAG, "deleteBackward");
- }
- */
- }
- String text = pTextView.getText().toString();
-
- /* If user input nothing, translate "\n" to engine. */
- if (text.compareTo("") == 0) {
- text = "\n";
- }
-
- if ('\n' != text.charAt(text.length() - 1)) {
- text += '\n';
- }
-
- for(int i = 0; i < text.length(); i++) {
- final int ch = text.codePointAt(i);
- mView.queueEvent(new Runnable() {
- @Override
- public void run() {
+ mView.queueEvent(new Runnable() {
+ @Override
+ public void run() {
+ for (int i = 0; i < characters.length(); i++) {
+ final int ch = characters.codePointAt(i);
GodotLib.key(0, ch, true);
GodotLib.key(0, ch, false);
}
- });
- }
- /*
- if (BuildConfig.DEBUG) {
- Log.d(TAG, "insertText(" + insertText + ")");
- }
- */
+ }
+ });
}
if (pActionID == EditorInfo.IME_ACTION_DONE) {
diff --git a/platform/android/java_glue.cpp b/platform/android/java_glue.cpp
index 6819a7e20f..40dfe6d909 100644
--- a/platform/android/java_glue.cpp
+++ b/platform/android/java_glue.cpp
@@ -34,6 +34,7 @@
#include "audio_driver_jandroid.h"
#include "core/os/keyboard.h"
#include "dir_access_jandroid.h"
+#include "engine.h"
#include "file_access_android.h"
#include "file_access_jandroid.h"
#include "java_class_wrapper.h"
@@ -602,30 +603,18 @@ struct TST {
TST tst;
-struct JAndroidPointerEvent {
-
- Vector<OS_Android::TouchPos> points;
- int pointer;
- int what;
-};
-
-static List<JAndroidPointerEvent> pointer_events;
-static List<Ref<InputEvent> > key_events;
-static List<OS_Android::JoypadEvent> joy_events;
static bool initialized = false;
static int step = 0;
static bool resized = false;
static bool resized_reload = false;
-static bool go_back_request = false;
static Size2 new_size;
static Vector3 accelerometer;
+static Vector3 gravity;
static Vector3 magnetometer;
static Vector3 gyroscope;
static HashMap<String, JNISingleton *> jni_singletons;
static jobject godot_io;
-static Vector<int> joy_device_ids;
-
typedef void (*GFXInitFunc)(void *ud, bool gl2);
static jmethodID _on_video_init = 0;
@@ -658,7 +647,7 @@ static int _open_uri(const String &p_uri) {
return env->CallIntMethod(godot_io, _openURI, jStr);
}
-static String _get_data_dir() {
+static String _get_user_data_dir() {
JNIEnv *env = ThreadAndroid::get_env();
jstring s = (jstring)env->CallObjectMethod(godot_io, _getDataDir);
@@ -836,7 +825,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *en
AudioDriverAndroid::setup(gob);
}
- os_android = new OS_Android(_gfx_init_func, env, _open_uri, _get_data_dir, _get_locale, _get_model, _get_screen_dpi, _show_vk, _hide_vk, _get_vk_height, _set_screen_orient, _get_unique_id, _get_system_dir, _play_video, _is_video_playing, _pause_video, _stop_video, _set_keep_screen_on, _alert, p_use_apk_expansion);
+ os_android = new OS_Android(_gfx_init_func, env, _open_uri, _get_user_data_dir, _get_locale, _get_model, _get_screen_dpi, _show_vk, _hide_vk, _get_vk_height, _set_screen_orient, _get_unique_id, _get_system_dir, _play_video, _is_video_playing, _pause_video, _stop_video, _set_keep_screen_on, _alert, p_use_apk_expansion);
os_android->set_need_reload_hooks(p_need_reload_hook);
char wd[500];
@@ -965,7 +954,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setup(JNIEnv *env, jo
__android_log_print(ANDROID_LOG_INFO, "godot", "*****SETUP OK");
java_class_wrapper = memnew(JavaClassWrapper(_godot_instance));
- ProjectSettings::get_singleton()->add_singleton(ProjectSettings::Singleton("JavaClassWrapper", java_class_wrapper));
+ Engine::get_singleton()->add_singleton(Engine::Singleton("JavaClassWrapper", java_class_wrapper));
_initialize_java_modules();
}
@@ -998,7 +987,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_newcontext(JNIEnv *en
}
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_back(JNIEnv *env, jobject obj) {
- go_back_request = true;
+ os_android->main_loop_request_go_back();
}
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_step(JNIEnv *env, jobject obj) {
@@ -1023,38 +1012,10 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_step(JNIEnv *env, job
//__android_log_print(ANDROID_LOG_INFO,"godot","**STEP EVENT! - %p-%i\n",env,Thread::get_caller_id());
- while (pointer_events.size()) {
-
- JAndroidPointerEvent jpe = pointer_events.front()->get();
- os_android->process_touch(jpe.what, jpe.pointer, jpe.points);
-
- pointer_events.pop_front();
- }
-
- while (key_events.size()) {
-
- Ref<InputEvent> event = key_events.front()->get();
- os_android->process_event(event);
-
- key_events.pop_front();
- };
-
- while (joy_events.size()) {
-
- OS_Android::JoypadEvent event = joy_events.front()->get();
- os_android->process_joy_event(event);
-
- joy_events.pop_front();
- }
-
- if (go_back_request) {
-
- os_android->main_loop_request_go_back();
- go_back_request = false;
- }
-
os_android->process_accelerometer(accelerometer);
+ os_android->process_gravity(gravity);
+
os_android->process_magnetometer(magnetometer);
os_android->process_gyroscope(gyroscope);
@@ -1083,12 +1044,8 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_touch(JNIEnv *env, jo
points.push_back(tp);
}
- JAndroidPointerEvent jpe;
- jpe.pointer = pointer;
- jpe.points = points;
- jpe.what = ev;
+ os_android->process_touch(ev, pointer, points);
- pointer_events.push_back(jpe);
/*
if (os_android)
os_android->process_touch(ev,pointer,points);
@@ -1358,7 +1315,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joybutton(JNIEnv *env
jevent.index = p_button;
jevent.pressed = p_pressed;
- joy_events.push_back(jevent);
+ os_android->process_joy_event(jevent);
}
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyaxis(JNIEnv *env, jobject obj, jint p_device, jint p_axis, jfloat p_value) {
@@ -1369,7 +1326,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyaxis(JNIEnv *env,
jevent.index = p_axis;
jevent.value = p_value;
- joy_events.push_back(jevent);
+ os_android->process_joy_event(jevent);
}
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyhat(JNIEnv *env, jobject obj, jint p_device, jint p_hat_x, jint p_hat_y) {
@@ -1390,7 +1347,8 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyhat(JNIEnv *env, j
hat |= InputDefault::HAT_MASK_DOWN;
}
jevent.hat = hat;
- joy_events.push_back(jevent);
+
+ os_android->process_joy_event(jevent);
}
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyconnectionchanged(JNIEnv *env, jobject obj, jint p_device, jboolean p_connected, jstring p_name) {
@@ -1403,6 +1361,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyconnectionchanged(
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_key(JNIEnv *env, jobject obj, jint p_scancode, jint p_unicode_char, jboolean p_pressed) {
Ref<InputEventKey> ievent;
+ ievent.instance();
int val = p_unicode_char;
int scancode = android_get_keysym(p_scancode);
ievent->set_scancode(scancode);
@@ -1421,16 +1380,20 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_key(JNIEnv *env, jobj
ievent->set_unicode(KEY_ENTER);
} else if (p_scancode == 4) {
- go_back_request = true;
+ os_android->main_loop_request_go_back();
}
- key_events.push_back(ievent);
+ os_android->process_event(ievent);
}
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_accelerometer(JNIEnv *env, jobject obj, jfloat x, jfloat y, jfloat z) {
accelerometer = Vector3(x, y, z);
}
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_gravity(JNIEnv *env, jobject obj, jfloat x, jfloat y, jfloat z) {
+ gravity = Vector3(x, y, z);
+}
+
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_magnetometer(JNIEnv *env, jobject obj, jfloat x, jfloat y, jfloat z) {
magnetometer = Vector3(x, y, z);
}
@@ -1464,7 +1427,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_singleton(JNIEnv *env
s->set_instance(env->NewGlobalRef(p_object));
jni_singletons[singname] = s;
- ProjectSettings::get_singleton()->add_singleton(ProjectSettings::Singleton(singname, s));
+ Engine::get_singleton()->add_singleton(Engine::Singleton(singname, s));
ProjectSettings::get_singleton()->set(singname, s);
}
diff --git a/platform/android/java_glue.h b/platform/android/java_glue.h
index 0aa2489813..4790c65617 100644
--- a/platform/android/java_glue.h
+++ b/platform/android/java_glue.h
@@ -50,6 +50,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyhat(JNIEnv *env, j
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyconnectionchanged(JNIEnv *env, jobject obj, jint p_device, jboolean p_connected, jstring p_name);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_audio(JNIEnv *env, jobject obj);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_accelerometer(JNIEnv *env, jobject obj, jfloat x, jfloat y, jfloat z);
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_gravity(JNIEnv *env, jobject obj, jfloat x, jfloat y, jfloat z);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_magnetometer(JNIEnv *env, jobject obj, jfloat x, jfloat y, jfloat z);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_gyroscope(JNIEnv *env, jobject obj, jfloat x, jfloat y, jfloat z);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_focusin(JNIEnv *env, jobject obj);
diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp
index 473a093077..b575f15559 100644
--- a/platform/android/os_android.cpp
+++ b/platform/android/os_android.cpp
@@ -65,12 +65,6 @@ const char *OS_Android::get_video_driver_name(int p_driver) const {
return "GLES2";
}
-
-OS::VideoMode OS_Android::get_default_video_mode() const {
-
- return OS::VideoMode();
-}
-
int OS_Android::get_audio_driver_count() const {
return 1;
@@ -120,13 +114,6 @@ void OS_Android::initialize_core() {
#endif
}
-void OS_Android::initialize_logger() {
- Vector<Logger *> loggers;
- loggers.push_back(memnew(AndroidLogger));
- loggers.push_back(memnew(RotatedFileLogger("user://logs/log.txt")));
- _set_logger(memnew(CompositeLogger(loggers)));
-}
-
void OS_Android::set_opengl_extensions(const char *p_gl_extensions) {
ERR_FAIL_COND(!p_gl_extensions);
@@ -155,11 +142,6 @@ void OS_Android::initialize(const VideoMode &p_desired, int p_video_driver, int
AudioDriverManager::initialize(p_audio_driver);
- physics_server = memnew(PhysicsServerSW);
- physics_server->init();
- physics_2d_server = Physics2DServerWrapMT::init_server<Physics2DServerSW>();
- physics_2d_server->init();
-
input = memnew(InputDefault);
input->set_fallback_mapping("Default Android Gamepad");
@@ -499,6 +481,11 @@ void OS_Android::process_accelerometer(const Vector3 &p_accelerometer) {
input->set_accelerometer(p_accelerometer);
}
+void OS_Android::process_gravity(const Vector3 &p_gravity) {
+
+ input->set_gravity(p_gravity);
+}
+
void OS_Android::process_magnetometer(const Vector3 &p_magnetometer) {
input->set_magnetometer(p_magnetometer);
@@ -616,13 +603,13 @@ void OS_Android::set_need_reload_hooks(bool p_needs_them) {
use_reload_hooks = p_needs_them;
}
-String OS_Android::get_data_dir() const {
+String OS_Android::get_user_data_dir() const {
if (data_dir_cache != String())
return data_dir_cache;
- if (get_data_dir_func) {
- String data_dir = get_data_dir_func();
+ if (get_user_data_dir_func) {
+ String data_dir = get_user_data_dir_func();
//store current dir
char real_current_dir_name[2048];
@@ -645,7 +632,6 @@ String OS_Android::get_data_dir() const {
}
return ".";
- //return ProjectSettings::get_singleton()->get_singleton_object("GodotOS")->call("get_data_dir");
}
void OS_Android::set_screen_orientation(ScreenOrientation p_orientation) {
@@ -710,10 +696,27 @@ String OS_Android::get_joy_guid(int p_device) const {
}
bool OS_Android::_check_internal_feature_support(const String &p_feature) {
- return p_feature == "mobile" || p_feature == "etc" || p_feature == "etc2"; //TODO support etc2 only if GLES3 driver is selected
+ if (p_feature == "mobile" || p_feature == "etc" || p_feature == "etc2") {
+ //TODO support etc2 only if GLES3 driver is selected
+ return true;
+ }
+#if defined(__aarch64__)
+ if (p_feature == "arm64-v8a") {
+ return true;
+ }
+#elif defined(__ARM_ARCH_7A__)
+ if (p_feature == "armeabi-v7a" || p_feature == "armeabi") {
+ return true;
+ }
+#elif defined(__arm__)
+ if (p_feature == "armeabi") {
+ return true;
+ }
+#endif
+ return false;
}
-OS_Android::OS_Android(GFXInitFunc p_gfx_init_func, void *p_gfx_init_ud, OpenURIFunc p_open_uri_func, GetDataDirFunc p_get_data_dir_func, GetLocaleFunc p_get_locale_func, GetModelFunc p_get_model_func, GetScreenDPIFunc p_get_screen_dpi_func, ShowVirtualKeyboardFunc p_show_vk, HideVirtualKeyboardFunc p_hide_vk, VirtualKeyboardHeightFunc p_vk_height_func, SetScreenOrientationFunc p_screen_orient, GetUniqueIDFunc p_get_unique_id, GetSystemDirFunc p_get_sdir_func, VideoPlayFunc p_video_play_func, VideoIsPlayingFunc p_video_is_playing_func, VideoPauseFunc p_video_pause_func, VideoStopFunc p_video_stop_func, SetKeepScreenOnFunc p_set_keep_screen_on_func, AlertFunc p_alert_func, bool p_use_apk_expansion) {
+OS_Android::OS_Android(GFXInitFunc p_gfx_init_func, void *p_gfx_init_ud, OpenURIFunc p_open_uri_func, GetUserDataDirFunc p_get_user_data_dir_func, GetLocaleFunc p_get_locale_func, GetModelFunc p_get_model_func, GetScreenDPIFunc p_get_screen_dpi_func, ShowVirtualKeyboardFunc p_show_vk, HideVirtualKeyboardFunc p_hide_vk, VirtualKeyboardHeightFunc p_vk_height_func, SetScreenOrientationFunc p_screen_orient, GetUniqueIDFunc p_get_unique_id, GetSystemDirFunc p_get_sdir_func, VideoPlayFunc p_video_play_func, VideoIsPlayingFunc p_video_is_playing_func, VideoPauseFunc p_video_pause_func, VideoStopFunc p_video_stop_func, SetKeepScreenOnFunc p_set_keep_screen_on_func, AlertFunc p_alert_func, bool p_use_apk_expansion) {
use_apk_expansion = p_use_apk_expansion;
default_videomode.width = 800;
@@ -729,7 +732,7 @@ OS_Android::OS_Android(GFXInitFunc p_gfx_init_func, void *p_gfx_init_ud, OpenURI
use_gl2 = false;
open_uri_func = p_open_uri_func;
- get_data_dir_func = p_get_data_dir_func;
+ get_user_data_dir_func = p_get_user_data_dir_func;
get_locale_func = p_get_locale_func;
get_model_func = p_get_model_func;
get_screen_dpi_func = p_get_screen_dpi_func;
@@ -750,7 +753,9 @@ OS_Android::OS_Android(GFXInitFunc p_gfx_init_func, void *p_gfx_init_ud, OpenURI
alert_func = p_alert_func;
use_reload_hooks = false;
- _set_logger(memnew(AndroidLogger));
+ Vector<Logger *> loggers;
+ loggers.push_back(memnew(AndroidLogger));
+ _set_logger(memnew(CompositeLogger(loggers)));
}
OS_Android::~OS_Android() {
diff --git a/platform/android/os_android.h b/platform/android/os_android.h
index 0c78c198a8..3b7f55096e 100644
--- a/platform/android/os_android.h
+++ b/platform/android/os_android.h
@@ -38,9 +38,6 @@
#include "os/main_loop.h"
//#include "power_android.h"
#include "servers/audio_server.h"
-#include "servers/physics/physics_server_sw.h"
-#include "servers/physics_2d/physics_2d_server_sw.h"
-#include "servers/physics_2d/physics_2d_server_wrap_mt.h"
#include "servers/visual/rasterizer.h"
#ifdef ANDROID_NATIVE_ACTIVITY
@@ -51,7 +48,7 @@
typedef void (*GFXInitFunc)(void *ud, bool gl2);
typedef int (*OpenURIFunc)(const String &);
-typedef String (*GetDataDirFunc)();
+typedef String (*GetUserDataDirFunc)();
typedef String (*GetLocaleFunc)();
typedef String (*GetModelFunc)();
typedef int (*GetScreenDPIFunc)();
@@ -106,8 +103,6 @@ private:
bool use_16bits_fbo;
VisualServer *visual_server;
- PhysicsServer *physics_server;
- Physics2DServer *physics_2d_server;
mutable String data_dir_cache;
@@ -121,7 +116,7 @@ private:
MainLoop *main_loop;
OpenURIFunc open_uri_func;
- GetDataDirFunc get_data_dir_func;
+ GetUserDataDirFunc get_user_data_dir_func;
GetLocaleFunc get_locale_func;
GetModelFunc get_model_func;
GetScreenDPIFunc get_screen_dpi_func;
@@ -146,12 +141,9 @@ public:
virtual int get_video_driver_count() const;
virtual const char *get_video_driver_name(int p_driver) const;
- virtual VideoMode get_default_video_mode() const;
-
virtual int get_audio_driver_count() const;
virtual const char *get_audio_driver_name(int p_driver) const;
- virtual void initialize_logger();
virtual void initialize_core();
virtual void initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver);
@@ -215,7 +207,7 @@ public:
virtual void set_screen_orientation(ScreenOrientation p_orientation);
virtual Error shell_open(String p_uri);
- virtual String get_data_dir() const;
+ virtual String get_user_data_dir() const;
virtual String get_resource_dir() const;
virtual String get_locale() const;
virtual String get_model_name() const;
@@ -226,6 +218,7 @@ public:
virtual String get_system_dir(SystemDir p_dir) const;
void process_accelerometer(const Vector3 &p_accelerometer);
+ void process_gravity(const Vector3 &p_gravity);
void process_magnetometer(const Vector3 &p_magnetometer);
void process_gyroscope(const Vector3 &p_gyroscope);
void process_touch(int p_what, int p_pointer, const Vector<TouchPos> &p_points);
@@ -243,7 +236,7 @@ public:
void joy_connection_changed(int p_device, bool p_connected, String p_name);
virtual bool _check_internal_feature_support(const String &p_feature);
- OS_Android(GFXInitFunc p_gfx_init_func, void *p_gfx_init_ud, OpenURIFunc p_open_uri_func, GetDataDirFunc p_get_data_dir_func, GetLocaleFunc p_get_locale_func, GetModelFunc p_get_model_func, GetScreenDPIFunc p_get_screen_dpi_func, ShowVirtualKeyboardFunc p_show_vk, HideVirtualKeyboardFunc p_hide_vk, VirtualKeyboardHeightFunc p_vk_height_func, SetScreenOrientationFunc p_screen_orient, GetUniqueIDFunc p_get_unique_id, GetSystemDirFunc p_get_sdir_func, VideoPlayFunc p_video_play_func, VideoIsPlayingFunc p_video_is_playing_func, VideoPauseFunc p_video_pause_func, VideoStopFunc p_video_stop_func, SetKeepScreenOnFunc p_set_keep_screen_on_func, AlertFunc p_alert_func, bool p_use_apk_expansion);
+ OS_Android(GFXInitFunc p_gfx_init_func, void *p_gfx_init_ud, OpenURIFunc p_open_uri_func, GetUserDataDirFunc p_get_user_data_dir_func, GetLocaleFunc p_get_locale_func, GetModelFunc p_get_model_func, GetScreenDPIFunc p_get_screen_dpi_func, ShowVirtualKeyboardFunc p_show_vk, HideVirtualKeyboardFunc p_hide_vk, VirtualKeyboardHeightFunc p_vk_height_func, SetScreenOrientationFunc p_screen_orient, GetUniqueIDFunc p_get_unique_id, GetSystemDirFunc p_get_sdir_func, VideoPlayFunc p_video_play_func, VideoIsPlayingFunc p_video_is_playing_func, VideoPauseFunc p_video_pause_func, VideoStopFunc p_video_stop_func, SetKeepScreenOnFunc p_set_keep_screen_on_func, AlertFunc p_alert_func, bool p_use_apk_expansion);
~OS_Android();
};
diff --git a/platform/android/platform_config.h b/platform/android/platform_config.h
index b1c3f027f3..b1f51c9256 100644
--- a/platform/android/platform_config.h
+++ b/platform/android/platform_config.h
@@ -28,3 +28,4 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include <alloca.h>
+#include <malloc.h>
diff --git a/platform/haiku/context_gl_haiku.cpp b/platform/haiku/context_gl_haiku.cpp
index 2b943df5ba..80d0bd78d5 100644
--- a/platform/haiku/context_gl_haiku.cpp
+++ b/platform/haiku/context_gl_haiku.cpp
@@ -29,7 +29,7 @@
/*************************************************************************/
#include "context_gl_haiku.h"
-#if defined(OPENGL_ENABLED) || defined(LEGACYGL_ENABLED)
+#if defined(OPENGL_ENABLED)
ContextGL_Haiku::ContextGL_Haiku(HaikuDirectWindow *p_window) {
window = p_window;
diff --git a/platform/haiku/context_gl_haiku.h b/platform/haiku/context_gl_haiku.h
index 40daf43ab9..a9a13a2b7f 100644
--- a/platform/haiku/context_gl_haiku.h
+++ b/platform/haiku/context_gl_haiku.h
@@ -30,7 +30,7 @@
#ifndef CONTEXT_GL_HAIKU_H
#define CONTEXT_GL_HAIKU_H
-#if defined(OPENGL_ENABLED) || defined(LEGACYGL_ENABLED)
+#if defined(OPENGL_ENABLED)
#include "drivers/gl_context/context_gl.h"
diff --git a/platform/haiku/detect.py b/platform/haiku/detect.py
index 50f9783dd2..7c62654ef6 100644
--- a/platform/haiku/detect.py
+++ b/platform/haiku/detect.py
@@ -67,7 +67,7 @@ def configure(env):
## Flags
env.Append(CPPPATH=['#platform/haiku'])
- env.Append(CPPFLAGS=['-DUNIX_ENABLED', '-DOPENGL_ENABLED', '-DGLES2_ENABLED', '-DGLES_OVER_GL'])
+ env.Append(CPPFLAGS=['-DUNIX_ENABLED', '-DOPENGL_ENABLED', '-DGLES_ENABLED', '-DGLES_OVER_GL'])
env.Append(CPPFLAGS=['-DMEDIA_KIT_ENABLED'])
# env.Append(CCFLAGS=['-DFREETYPE_ENABLED'])
env.Append(CPPFLAGS=['-DPTHREAD_NO_RENAME']) # TODO: enable when we have pthread_setname_np
diff --git a/platform/haiku/os_haiku.cpp b/platform/haiku/os_haiku.cpp
index 9f2f88bb4e..ef5a065107 100644
--- a/platform/haiku/os_haiku.cpp
+++ b/platform/haiku/os_haiku.cpp
@@ -76,11 +76,7 @@ int OS_Haiku::get_video_driver_count() const {
}
const char *OS_Haiku::get_video_driver_name(int p_driver) const {
- return "GLES2";
-}
-
-OS::VideoMode OS_Haiku::get_default_video_mode() const {
- return OS::VideoMode(800, 600, false);
+ return "GLES3";
}
void OS_Haiku::initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) {
@@ -105,12 +101,14 @@ void OS_Haiku::initialize(const VideoMode &p_desired, int p_video_driver, int p_
window->SetFlags(flags);
}
-#if defined(OPENGL_ENABLED) || defined(LEGACYGL_ENABLED)
+#if defined(OPENGL_ENABLED)
context_gl = memnew(ContextGL_Haiku(window));
context_gl->initialize();
context_gl->make_current();
- rasterizer = memnew(RasterizerGLES2);
+ /* Port to GLES 3 rasterizer */
+ //rasterizer = memnew(RasterizerGLES2);
+
#endif
visual_server = memnew(VisualServerRaster(rasterizer));
@@ -130,13 +128,6 @@ void OS_Haiku::initialize(const VideoMode &p_desired, int p_video_driver, int p_
window->Show();
visual_server->init();
- physics_server = memnew(PhysicsServerSW);
- physics_server->init();
- physics_2d_server = memnew(Physics2DServerSW);
- // TODO: enable multithreaded PS
- //physics_2d_server = Physics2DServerWrapMT::init_server<Physics2DServerSW>();
- physics_2d_server->init();
-
AudioDriverManager::initialize(p_audio_driver);
power_manager = memnew(PowerHaiku);
@@ -153,15 +144,9 @@ void OS_Haiku::finalize() {
memdelete(visual_server);
memdelete(rasterizer);
- physics_server->finish();
- memdelete(physics_server);
-
- physics_2d_server->finish();
- memdelete(physics_2d_server);
-
memdelete(input);
-#if defined(OPENGL_ENABLED) || defined(LEGACYGL_ENABLED)
+#if defined(OPENGL_ENABLED)
memdelete(context_gl);
#endif
}
@@ -331,3 +316,36 @@ bool OS_Haiku::_check_internal_feature_support(const String &p_feature) {
return p_feature == "pc" || p_feature == "s3tc";
}
+
+String OS_Haiku::get_config_path() const {
+
+ if (has_environment("XDG_CONFIG_HOME")) {
+ return get_environment("XDG_CONFIG_HOME");
+ } else if (has_environment("HOME")) {
+ return get_environment("HOME").plus_file(".config");
+ } else {
+ return ".";
+ }
+}
+
+String OS_Haiku::get_data_path() const {
+
+ if (has_environment("XDG_DATA_HOME")) {
+ return get_environment("XDG_DATA_HOME");
+ } else if (has_environment("HOME")) {
+ return get_environment("HOME").plus_file(".local/share");
+ } else {
+ return get_config_path();
+ }
+}
+
+String OS_Haiku::get_cache_path() const {
+
+ if (has_environment("XDG_CACHE_HOME")) {
+ return get_environment("XDG_CACHE_HOME");
+ } else if (has_environment("HOME")) {
+ return get_environment("HOME").plus_file(".cache");
+ } else {
+ return get_config_path();
+ }
+}
diff --git a/platform/haiku/os_haiku.h b/platform/haiku/os_haiku.h
index d2fafb9129..4ee54fb48d 100644
--- a/platform/haiku/os_haiku.h
+++ b/platform/haiku/os_haiku.h
@@ -38,8 +38,6 @@
#include "main/input_default.h"
#include "power_haiku.h"
#include "servers/audio_server.h"
-#include "servers/physics_2d/physics_2d_server_sw.h"
-#include "servers/physics_server.h"
#include "servers/visual/rasterizer.h"
#include "servers/visual_server.h"
@@ -52,15 +50,13 @@ private:
Rasterizer *rasterizer;
VisualServer *visual_server;
VideoMode current_video_mode;
- PhysicsServer *physics_server;
- Physics2DServer *physics_2d_server;
PowerHaiku *power_manager;
#ifdef MEDIA_KIT_ENABLED
AudioDriverMediaKit driver_media_kit;
#endif
-#if defined(OPENGL_ENABLED) || defined(LEGACYGL_ENABLED)
+#if defined(OPENGL_ENABLED)
ContextGL_Haiku *context_gl;
#endif
@@ -69,7 +65,6 @@ private:
protected:
virtual int get_video_driver_count() const;
virtual const char *get_video_driver_name(int p_driver) const;
- virtual VideoMode get_default_video_mode() const;
virtual void initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver);
virtual void finalize();
@@ -122,6 +117,10 @@ public:
virtual int get_power_percent_left();
virtual bool _check_internal_feature_support(const String &p_feature);
+
+ virtual String get_config_path() const;
+ virtual String get_data_path() const;
+ virtual String get_cache_path() const;
};
#endif
diff --git a/platform/iphone/SCsub b/platform/iphone/SCsub
index 61798c5f87..550dfdd7d6 100644
--- a/platform/iphone/SCsub
+++ b/platform/iphone/SCsub
@@ -3,7 +3,7 @@
Import('env')
iphone_lib = [
-
+ 'godot_iphone.cpp',
'os_iphone.cpp',
'sem_iphone.cpp',
'gl_view.mm',
@@ -17,10 +17,10 @@ iphone_lib = [
]
env_ios = env.Clone()
+ios_lib = env_ios.Library('iphone', iphone_lib)
-obj = env_ios.Object('godot_iphone.cpp')
+def combine_libs(target=None, source=None, env=None):
+ lib_path = target[0].srcnode().abspath
+ env.Execute('$IPHONEPATH/usr/bin/libtool -static -o "' + lib_path + '" ' + ' '.join([('"' + lib.srcnode().abspath + '"') for lib in source]))
-prog = None
-prog = env_ios.Program('#bin/godot', [obj] + iphone_lib)
-action = "$IPHONEPATH/usr/bin/dsymutil " + File(prog)[0].path + " -o " + File(prog)[0].path + ".dSYM"
-env.AddPostAction(prog, action)
+combine_command = env_ios.Command('#bin/libgodot' + env_ios['LIBSUFFIX'], [ios_lib] + env_ios['LIBS'], combine_libs)
diff --git a/platform/iphone/app_delegate.mm b/platform/iphone/app_delegate.mm
index da6ceacdac..8f2893e69e 100644
--- a/platform/iphone/app_delegate.mm
+++ b/platform/iphone/app_delegate.mm
@@ -81,7 +81,7 @@ void _set_keep_screen_on(bool p_enabled) {
extern int gargc;
extern char **gargv;
-extern int iphone_main(int, int, int, char **);
+extern int iphone_main(int, int, int, char **, String);
extern void iphone_finish();
CMMotionManager *motionManager;
@@ -393,15 +393,6 @@ static int frame_count = 0;
};
++frame_count;
- NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
- NSUserDomainMask, YES);
- NSString *documentsDirectory = [paths objectAtIndex:0];
- // NSString *documentsDirectory = [[[NSFileManager defaultManager]
- // URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask]
- // lastObject];
- OSIPhone::get_singleton()->set_data_dir(
- String::utf8([documentsDirectory UTF8String]));
-
NSString *locale_code = [[NSLocale currentLocale] localeIdentifier];
OSIPhone::get_singleton()->set_locale(
String::utf8([locale_code UTF8String]));
@@ -604,7 +595,11 @@ static int frame_count = 0;
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES,
GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
- int err = iphone_main(backingWidth, backingHeight, gargc, gargv);
+ NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
+ NSUserDomainMask, YES);
+ NSString *documentsDirectory = [paths objectAtIndex:0];
+
+ int err = iphone_main(backingWidth, backingHeight, gargc, gargv, String::utf8([documentsDirectory UTF8String]));
if (err != 0) {
// bail, things did not go very well for us, should probably output a message on screen with our error code...
exit(0);
@@ -643,6 +638,9 @@ static int frame_count = 0;
mainViewController = view_controller;
+ // prevent to stop music in another background app
+ [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:nil];
+
#ifdef MODULE_GAME_ANALYTICS_ENABLED
printf("********************* didFinishLaunchingWithOptions\n");
if (!ProjectSettings::get_singleton()->has("mobileapptracker/advertiser_id")) {
diff --git a/platform/iphone/detect.py b/platform/iphone/detect.py
index 00d8a59f74..25674c2b47 100644
--- a/platform/iphone/detect.py
+++ b/platform/iphone/detect.py
@@ -47,8 +47,8 @@ def configure(env):
if (env["target"].startswith("release")):
env.Append(CPPFLAGS=['-DNDEBUG', '-DNS_BLOCK_ASSERTIONS=1'])
- env.Append(CPPFLAGS=['-O2', '-flto', '-ftree-vectorize', '-fomit-frame-pointer', '-ffast-math', '-funsafe-math-optimizations'])
- env.Append(LINKFLAGS=['-O2', '-flto'])
+ env.Append(CPPFLAGS=['-O2', '-ftree-vectorize', '-fomit-frame-pointer', '-ffast-math', '-funsafe-math-optimizations'])
+ env.Append(LINKFLAGS=['-O2'])
if env["target"] == "release_debug":
env.Append(CPPFLAGS=['-DDEBUG_ENABLED'])
@@ -56,11 +56,18 @@ def configure(env):
elif (env["target"] == "debug"):
env.Append(CPPFLAGS=['-D_DEBUG', '-DDEBUG=1', '-gdwarf-2', '-O0', '-DDEBUG_ENABLED', '-DDEBUG_MEMORY_ENABLED'])
+ if (env["use_lto"]):
+ env.Append(CPPFLAGS=['-flto'])
+ env.Append(LINKFLAGS=['-flto'])
+
## Architecture
+ if env["ios_sim"] and not ("arch" in env):
+ env["arch"] = "x86"
- if env["ios_sim"] or env["arch"] == "x86": # i386, simulator
- env["arch"] = "x86"
+ if env["arch"] == "x86": # i386, simulator
env["bits"] = "32"
+ elif env["arch"] == "x86_64":
+ env["bits"] = "64"
elif (env["arch"] == "arm" or env["arch"] == "arm32" or env["arch"] == "armv7" or env["bits"] == "32"): # arm
env["arch"] = "arm"
env["bits"] = "32"
@@ -72,18 +79,30 @@ def configure(env):
env['ENV']['PATH'] = env['IPHONEPATH'] + "/Developer/usr/bin/:" + env['ENV']['PATH']
- env['CC'] = '$IPHONEPATH/usr/bin/${ios_triple}clang'
- env['CXX'] = '$IPHONEPATH/usr/bin/${ios_triple}clang++'
- env['AR'] = '$IPHONEPATH/usr/bin/${ios_triple}ar'
- env['RANLIB'] = '$IPHONEPATH/usr/bin/${ios_triple}ranlib'
- env['S_compiler'] = '$IPHONEPATH/Developer/usr/bin/gcc'
+ compiler_path = '$IPHONEPATH/usr/bin/${ios_triple}'
+ s_compiler_path = '$IPHONEPATH/Developer/usr/bin/'
+
+ ccache_path = os.environ.get("CCACHE")
+ if ccache_path == None:
+ env['CC'] = compiler_path + 'clang'
+ env['CXX'] = compiler_path + 'clang++'
+ env['S_compiler'] = s_compiler_path + 'gcc'
+ else:
+ # there aren't any ccache wrappers available for iOS,
+ # to enable caching we need to prepend the path to the ccache binary
+ env['CC'] = ccache_path + ' ' + compiler_path + 'clang'
+ env['CXX'] = ccache_path + ' ' + compiler_path + 'clang++'
+ env['S_compiler'] = ccache_path + ' ' + s_compiler_path + 'gcc'
+ env['AR'] = compiler_path + 'ar'
+ env['RANLIB'] = compiler_path + 'ranlib'
## Compile flags
- if (env["arch"] == "x86"):
+ if (env["arch"] == "x86" or env["arch"] == "x86_64"):
env['IPHONEPLATFORM'] = 'iPhoneSimulator'
- env['ENV']['MACOSX_DEPLOYMENT_TARGET'] = '10.6'
- env.Append(CCFLAGS='-arch i386 -fobjc-abi-version=2 -fobjc-legacy-dispatch -fmessage-length=0 -fpascal-strings -fblocks -fasm-blocks -D__IPHONE_OS_VERSION_MIN_REQUIRED=40100 -isysroot $IPHONESDK -mios-simulator-version-min=4.3 -DCUSTOM_MATRIX_TRANSFORM_H=\\\"build/iphone/matrix4_iphone.h\\\" -DCUSTOM_VECTOR3_TRANSFORM_H=\\\"build/iphone/vector3_iphone.h\\\"'.split())
+ env['ENV']['MACOSX_DEPLOYMENT_TARGET'] = '10.9'
+ arch_flag = "i386" if env["arch"] == "x86" else env["arch"]
+ env.Append(CCFLAGS=('-arch ' + arch_flag + ' -fobjc-abi-version=2 -fobjc-legacy-dispatch -fmessage-length=0 -fpascal-strings -fblocks -fasm-blocks -isysroot $IPHONESDK -mios-simulator-version-min=9.0 -DCUSTOM_MATRIX_TRANSFORM_H=\\\"build/iphone/matrix4_iphone.h\\\" -DCUSTOM_VECTOR3_TRANSFORM_H=\\\"build/iphone/vector3_iphone.h\\\"').split())
elif (env["arch"] == "arm"):
env.Append(CCFLAGS='-fno-objc-arc -arch armv7 -fmessage-length=0 -fno-strict-aliasing -fdiagnostics-print-source-range-info -fdiagnostics-show-category=id -fdiagnostics-parseable-fixits -fpascal-strings -fblocks -isysroot $IPHONESDK -fvisibility=hidden -mthumb "-DIBOutlet=__attribute__((iboutlet))" "-DIBOutletCollection(ClassName)=__attribute__((iboutletcollection(ClassName)))" "-DIBAction=void)__attribute__((ibaction)" -miphoneos-version-min=9.0 -MMD -MT dependencies'.split())
elif (env["arch"] == "arm64"):
@@ -98,8 +117,9 @@ def configure(env):
## Link flags
- if (env["arch"] == "x86"):
- env.Append(LINKFLAGS=['-arch', 'i386', '-mios-simulator-version-min=4.3',
+ if (env["arch"] == "x86" or env["arch"] == "x86_64"):
+ arch_flag = "i386" if env["arch"] == "x86" else env["arch"]
+ env.Append(LINKFLAGS=['-arch', arch_flag, '-mios-simulator-version-min=9.0',
'-isysroot', '$IPHONESDK',
'-Xlinker',
'-objc_abi_version',
@@ -148,7 +168,7 @@ def configure(env):
env['ENV']['CODESIGN_ALLOCATE'] = '/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/codesign_allocate'
env.Append(CPPPATH=['#platform/iphone'])
- env.Append(CPPFLAGS=['-DIPHONE_ENABLED', '-DUNIX_ENABLED', '-DGLES2_ENABLED', '-DMPC_FIXED_POINT', '-DCOREAUDIO_ENABLED'])
+ env.Append(CPPFLAGS=['-DIPHONE_ENABLED', '-DUNIX_ENABLED', '-DGLES_ENABLED', '-DMPC_FIXED_POINT', '-DCOREAUDIO_ENABLED'])
# TODO: Move that to opus module's config
if 'module_opus_enabled' in env and env['module_opus_enabled']:
diff --git a/platform/iphone/export/export.cpp b/platform/iphone/export/export.cpp
index c91781ce1d..6aa1ed9f8d 100644
--- a/platform/iphone/export/export.cpp
+++ b/platform/iphone/export/export.cpp
@@ -56,11 +56,48 @@ class EditorExportPlatformIOS : public EditorExportPlatform {
static Error _walk_dir_recursive(DirAccess *p_da, FileHandler p_handler, void *p_userdata);
static Error _codesign(String p_file, void *p_userdata);
- void _fix_config_file(const Ref<EditorExportPreset> &p_preset, Vector<uint8_t> &pfile, const String &p_name, const String &p_binary, bool p_debug);
- static Error _export_dylibs(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total);
+ struct IOSConfigData {
+ String pkg_name;
+ String binary_name;
+ String plist_content;
+ String architectures;
+ String linker_flags;
+ String cpp_code;
+ };
+
+ struct ExportArchitecture {
+ String name;
+ bool is_default;
+
+ ExportArchitecture()
+ : name(""), is_default(false) {
+ }
+
+ ExportArchitecture(String p_name, bool p_is_default) {
+ name = p_name;
+ is_default = p_is_default;
+ }
+ };
+
+ struct IOSExportAsset {
+ String exported_path;
+ bool is_framework; // framework is anything linked to the binary, otherwise it's a resource
+ };
+
+ String _get_additional_plist_content();
+ String _get_linker_flags();
+ String _get_cpp_code();
+ void _fix_config_file(const Ref<EditorExportPreset> &p_preset, Vector<uint8_t> &pfile, const IOSConfigData &p_config, bool p_debug);
Error _export_loading_screens(const Ref<EditorExportPreset> &p_preset, const String &p_dest_dir);
Error _export_icons(const Ref<EditorExportPreset> &p_preset, const String &p_iconset_dir);
+ Vector<ExportArchitecture> _get_supported_architectures();
+ Vector<String> _get_preset_architectures(const Ref<EditorExportPreset> &p_preset);
+
+ void _add_assets_to_project(Vector<uint8_t> &p_project_data, const Vector<IOSExportAsset> &p_additional_assets);
+ Error _export_additional_assets(const String &p_out_dir, const Vector<String> &p_assets, bool p_is_framework, Vector<IOSExportAsset> &r_exported_assets);
+ Error _export_additional_assets(const String &p_out_dir, const Vector<SharedObject> &p_libraries, Vector<IOSExportAsset> &r_exported_assets);
+
protected:
virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features);
virtual void get_export_options(List<ExportOption> *r_options);
@@ -96,6 +133,17 @@ void EditorExportPlatformIOS::get_preset_features(const Ref<EditorExportPreset>
if (p_preset->get("texture_format/etc2")) {
r_features->push_back("etc2");
}
+ Vector<String> architectures = _get_preset_architectures(p_preset);
+ for (int i = 0; i < architectures.size(); ++i) {
+ r_features->push_back(architectures[i]);
+ }
+}
+
+Vector<EditorExportPlatformIOS::ExportArchitecture> EditorExportPlatformIOS::_get_supported_architectures() {
+ Vector<ExportArchitecture> archs;
+ archs.push_back(ExportArchitecture("armv7", true));
+ archs.push_back(ExportArchitecture("arm64", true));
+ return archs;
}
void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options) {
@@ -120,7 +168,6 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options)
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/short_version"), "1.0"));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/version"), "1.0"));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/copyright"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "application/bits_mode", PROPERTY_HINT_ENUM, "Fat (32 & 64 bits),64 bits,32 bits"), 1));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "required_icons/iphone_120x120", PROPERTY_HINT_FILE, "png"), "")); // Home screen on iPhone/iPod Touch with retina display
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "required_icons/ipad_76x76", PROPERTY_HINT_FILE, "png"), "")); // Home screen on iPad
@@ -145,10 +192,13 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options)
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/etc"), false));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/etc2"), true));
- /* probably need some more info */
+ Vector<ExportArchitecture> architectures = _get_supported_architectures();
+ for (int i = 0; i < architectures.size(); ++i) {
+ r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "architectures/" + architectures[i].name), architectures[i].is_default));
+ }
}
-void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_preset, Vector<uint8_t> &pfile, const String &p_name, const String &p_binary, bool p_debug) {
+void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_preset, Vector<uint8_t> &pfile, const IOSConfigData &p_config, bool p_debug) {
static const String export_method_string[] = {
"app-store",
"development",
@@ -158,13 +208,12 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_
String str;
String strnew;
str.parse_utf8((const char *)pfile.ptr(), pfile.size());
- print_line(str);
Vector<String> lines = str.split("\n");
for (int i = 0; i < lines.size(); i++) {
if (lines[i].find("$binary") != -1) {
- strnew += lines[i].replace("$binary", p_binary) + "\n";
+ strnew += lines[i].replace("$binary", p_config.binary_name) + "\n";
} else if (lines[i].find("$name") != -1) {
- strnew += lines[i].replace("$name", p_name) + "\n";
+ strnew += lines[i].replace("$name", p_config.pkg_name) + "\n";
} else if (lines[i].find("$info") != -1) {
strnew += lines[i].replace("$info", p_preset->get("application/info")) + "\n";
} else if (lines[i].find("$identifier") != -1) {
@@ -186,10 +235,21 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_
strnew += lines[i].replace("$provisioning_profile_uuid_release", p_preset->get("application/provisioning_profile_uuid_release")) + "\n";
} else if (lines[i].find("$provisioning_profile_uuid_debug") != -1) {
strnew += lines[i].replace("$provisioning_profile_uuid_debug", p_preset->get("application/provisioning_profile_uuid_debug")) + "\n";
+ } else if (lines[i].find("$provisioning_profile_uuid") != -1) {
+ String uuid = p_debug ? p_preset->get("application/provisioning_profile_uuid_debug") : p_preset->get("application/provisioning_profile_uuid_release");
+ strnew += lines[i].replace("$provisioning_profile_uuid", uuid) + "\n";
} else if (lines[i].find("$code_sign_identity_debug") != -1) {
strnew += lines[i].replace("$code_sign_identity_debug", p_preset->get("application/code_sign_identity_debug")) + "\n";
} else if (lines[i].find("$code_sign_identity_release") != -1) {
strnew += lines[i].replace("$code_sign_identity_release", p_preset->get("application/code_sign_identity_release")) + "\n";
+ } else if (lines[i].find("$additional_plist_content") != -1) {
+ strnew += lines[i].replace("$additional_plist_content", p_config.plist_content) + "\n";
+ } else if (lines[i].find("$godot_archs") != -1) {
+ strnew += lines[i].replace("$godot_archs", p_config.architectures) + "\n";
+ } else if (lines[i].find("$linker_flags") != -1) {
+ strnew += lines[i].replace("$linker_flags", p_config.linker_flags) + "\n";
+ } else if (lines[i].find("$cpp_code") != -1) {
+ strnew += lines[i].replace("$cpp_code", p_config.cpp_code) + "\n";
} else {
strnew += lines[i] + "\n";
}
@@ -204,27 +264,37 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_
}
}
-Error EditorExportPlatformIOS::_export_dylibs(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total) {
- if (!p_path.ends_with(".dylib")) return OK;
- const String &dest_dir = *(String *)p_userdata;
- String rel_path = p_path.replace_first("res://", "dylibs/");
- DirAccess *dest_dir_access = DirAccess::open(dest_dir);
- ERR_FAIL_COND_V(!dest_dir_access, ERR_CANT_OPEN);
-
- String base_dir = rel_path.get_base_dir();
- Error make_dir_err = OK;
- if (!dest_dir_access->dir_exists(base_dir)) {
- make_dir_err = dest_dir_access->make_dir_recursive(base_dir);
- }
- if (make_dir_err != OK) {
- memdelete(dest_dir_access);
- return make_dir_err;
+String EditorExportPlatformIOS::_get_additional_plist_content() {
+ Vector<Ref<EditorExportPlugin> > export_plugins = EditorExport::get_singleton()->get_export_plugins();
+ String result;
+ for (int i = 0; i < export_plugins.size(); ++i) {
+ result += export_plugins[i]->get_ios_plist_content();
}
+ return result;
+}
- Error copy_err = dest_dir_access->copy(p_path, dest_dir + rel_path);
- memdelete(dest_dir_access);
+String EditorExportPlatformIOS::_get_linker_flags() {
+ Vector<Ref<EditorExportPlugin> > export_plugins = EditorExport::get_singleton()->get_export_plugins();
+ String result;
+ for (int i = 0; i < export_plugins.size(); ++i) {
+ String flags = export_plugins[i]->get_ios_linker_flags();
+ if (flags.length() == 0) continue;
+ if (result.length() > 0) {
+ result += ' ';
+ }
+ result += flags;
+ }
+ // the flags will be enclosed in quotes, so need to escape them
+ return result.replace("\"", "\\\"");
+}
- return copy_err;
+String EditorExportPlatformIOS::_get_cpp_code() {
+ Vector<Ref<EditorExportPlugin> > export_plugins = EditorExport::get_singleton()->get_export_plugins();
+ String result;
+ for (int i = 0; i < export_plugins.size(); ++i) {
+ result += export_plugins[i]->get_ios_cpp_code();
+ }
+ return result;
}
struct IconInfo {
@@ -397,12 +467,212 @@ Error EditorExportPlatformIOS::_codesign(String p_file, void *p_userdata) {
codesign_args.push_back("-s");
codesign_args.push_back(data->preset->get(data->debug ? "application/code_sign_identity_debug" : "application/code_sign_identity_release"));
codesign_args.push_back(p_file);
- return OS::get_singleton()->execute("/usr/bin/codesign", codesign_args, true);
+ return OS::get_singleton()->execute("codesign", codesign_args, true);
}
return OK;
}
+struct PbxId {
+private:
+ static char _hex_char(uint8_t four_bits) {
+ if (four_bits < 10) {
+ return ('0' + four_bits);
+ }
+ return 'A' + (four_bits - 10);
+ }
+
+ static String _hex_pad(uint32_t num) {
+ Vector<char> ret;
+ ret.resize(sizeof(num) * 2);
+ for (int i = 0; i < sizeof(num) * 2; ++i) {
+ uint8_t four_bits = (num >> (sizeof(num) * 8 - (i + 1) * 4)) & 0xF;
+ ret[i] = _hex_char(four_bits);
+ }
+ return String::utf8(ret.ptr(), ret.size());
+ }
+
+public:
+ uint32_t high_bits;
+ uint32_t mid_bits;
+ uint32_t low_bits;
+
+ String str() const {
+ return _hex_pad(high_bits) + _hex_pad(mid_bits) + _hex_pad(low_bits);
+ }
+
+ PbxId &operator++() {
+ low_bits++;
+ if (!low_bits) {
+ mid_bits++;
+ if (!mid_bits) {
+ high_bits++;
+ }
+ }
+
+ return *this;
+ }
+};
+
+struct ExportLibsData {
+ Vector<String> lib_paths;
+ String dest_dir;
+};
+
+void EditorExportPlatformIOS::_add_assets_to_project(Vector<uint8_t> &p_project_data, const Vector<IOSExportAsset> &p_additional_assets) {
+ Vector<Ref<EditorExportPlugin> > export_plugins = EditorExport::get_singleton()->get_export_plugins();
+ Vector<String> frameworks;
+ for (int i = 0; i < export_plugins.size(); ++i) {
+ Vector<String> plugin_frameworks = export_plugins[i]->get_ios_frameworks();
+ for (int j = 0; j < plugin_frameworks.size(); ++j) {
+ frameworks.push_back(plugin_frameworks[j]);
+ }
+ }
+
+ // that is just a random number, we just need Godot IDs not to clash with
+ // existing IDs in the project.
+ PbxId current_id = { 0x58938401, 0, 0 };
+ String pbx_files;
+ String pbx_frameworks_build;
+ String pbx_frameworks_refs;
+ String pbx_resources_build;
+ String pbx_resources_refs;
+
+ const String file_info_format = String("$build_id = {isa = PBXBuildFile; fileRef = $ref_id; };\n") +
+ "$ref_id = {isa = PBXFileReference; lastKnownFileType = $file_type; name = $name; path = \"$file_path\"; sourceTree = \"<group>\"; };\n";
+ for (int i = 0; i < p_additional_assets.size(); ++i) {
+ String build_id = (++current_id).str();
+ String ref_id = (++current_id).str();
+ const IOSExportAsset &asset = p_additional_assets[i];
+
+ String type;
+ if (asset.exported_path.ends_with(".framework")) {
+ type = "wrapper.framework";
+ } else if (asset.exported_path.ends_with(".dylib")) {
+ type = "compiled.mach-o.dylib";
+ } else if (asset.exported_path.ends_with(".a")) {
+ type = "archive.ar";
+ } else {
+ type = "file";
+ }
+
+ String &pbx_build = asset.is_framework ? pbx_frameworks_build : pbx_resources_build;
+ String &pbx_refs = asset.is_framework ? pbx_frameworks_refs : pbx_resources_refs;
+
+ if (pbx_build.length() > 0) {
+ pbx_build += ",\n";
+ pbx_refs += ",\n";
+ }
+ pbx_build += build_id;
+ pbx_refs += ref_id;
+
+ Dictionary format_dict;
+ format_dict["build_id"] = build_id;
+ format_dict["ref_id"] = ref_id;
+ format_dict["name"] = asset.exported_path.get_file();
+ format_dict["file_path"] = asset.exported_path;
+ format_dict["file_type"] = type;
+ pbx_files += file_info_format.format(format_dict, "$_");
+ }
+
+ String str = String::utf8((const char *)p_project_data.ptr(), p_project_data.size());
+ str = str.replace("$additional_pbx_files", pbx_files);
+ str = str.replace("$additional_pbx_frameworks_build", pbx_frameworks_build);
+ str = str.replace("$additional_pbx_frameworks_refs", pbx_frameworks_refs);
+ str = str.replace("$additional_pbx_resources_build", pbx_resources_build);
+ str = str.replace("$additional_pbx_resources_refs", pbx_resources_refs);
+
+ CharString cs = str.utf8();
+ p_project_data.resize(cs.size() - 1);
+ for (int i = 0; i < cs.size() - 1; i++) {
+ p_project_data[i] = cs[i];
+ }
+}
+
+Error EditorExportPlatformIOS::_export_additional_assets(const String &p_out_dir, const Vector<String> &p_assets, bool p_is_framework, Vector<IOSExportAsset> &r_exported_assets) {
+ DirAccess *filesystem_da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ ERR_FAIL_COND_V(!filesystem_da, ERR_CANT_CREATE);
+ for (int f_idx = 0; f_idx < p_assets.size(); ++f_idx) {
+ String asset = p_assets[f_idx];
+ if (!asset.begins_with("res://")) {
+ // either SDK-builtin or already a part of the export template
+ IOSExportAsset exported_asset = { asset, p_is_framework };
+ r_exported_assets.push_back(exported_asset);
+ } else {
+ DirAccess *da = DirAccess::create_for_path(asset);
+ if (!da) {
+ memdelete(filesystem_da);
+ ERR_FAIL_COND_V(!da, ERR_CANT_CREATE);
+ }
+ bool file_exists = da->file_exists(asset);
+ bool dir_exists = da->dir_exists(asset);
+ if (!file_exists && !dir_exists) {
+ memdelete(da);
+ memdelete(filesystem_da);
+ return ERR_FILE_NOT_FOUND;
+ }
+ String additional_dir = p_is_framework && asset.ends_with(".dylib") ? "/dylibs/" : "/";
+ String destination_dir = p_out_dir + additional_dir + asset.get_base_dir().replace("res://", "");
+ if (!filesystem_da->dir_exists(destination_dir)) {
+ Error make_dir_err = filesystem_da->make_dir_recursive(destination_dir);
+ if (make_dir_err) {
+ memdelete(da);
+ memdelete(filesystem_da);
+ return make_dir_err;
+ }
+ }
+
+ String destination = destination_dir + "/" + asset.get_file();
+ Error err = dir_exists ? da->copy_dir(asset, destination) : da->copy(asset, destination);
+ memdelete(da);
+ if (err) {
+ memdelete(filesystem_da);
+ return err;
+ }
+ IOSExportAsset exported_asset = { destination, p_is_framework };
+ r_exported_assets.push_back(exported_asset);
+ }
+ }
+ memdelete(filesystem_da);
+
+ return OK;
+}
+
+Error EditorExportPlatformIOS::_export_additional_assets(const String &p_out_dir, const Vector<SharedObject> &p_libraries, Vector<IOSExportAsset> &r_exported_assets) {
+ Vector<Ref<EditorExportPlugin> > export_plugins = EditorExport::get_singleton()->get_export_plugins();
+ for (int i = 0; i < export_plugins.size(); i++) {
+ Vector<String> frameworks = export_plugins[i]->get_ios_frameworks();
+ Error err = _export_additional_assets(p_out_dir, frameworks, true, r_exported_assets);
+ ERR_FAIL_COND_V(err, err);
+ Vector<String> ios_bundle_files = export_plugins[i]->get_ios_bundle_files();
+ err = _export_additional_assets(p_out_dir, ios_bundle_files, false, r_exported_assets);
+ ERR_FAIL_COND_V(err, err);
+ }
+
+ Vector<String> library_paths;
+ for (int i = 0; i < p_libraries.size(); ++i) {
+ library_paths.push_back(p_libraries[i].path);
+ }
+ Error err = _export_additional_assets(p_out_dir, library_paths, true, r_exported_assets);
+ ERR_FAIL_COND_V(err, err);
+
+ return OK;
+}
+
+Vector<String> EditorExportPlatformIOS::_get_preset_architectures(const Ref<EditorExportPreset> &p_preset) {
+ Vector<ExportArchitecture> all_archs = _get_supported_architectures();
+ Vector<String> enabled_archs;
+ for (int i = 0; i < all_archs.size(); ++i) {
+ bool is_enabled = p_preset->get("architectures/" + all_archs[i].name);
+ if (is_enabled) {
+ enabled_archs.push_back(all_archs[i].name);
+ }
+ }
+ return enabled_archs;
+}
+
Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
+ ExportNotifier notifier(*this, p_preset, p_debug, p_path, p_flags);
+
String src_pkg_name;
String dest_dir = p_path.get_base_dir() + "/";
String binary_name = p_path.get_file().get_basename();
@@ -427,26 +697,43 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
}
}
- FileAccess *src_f = NULL;
- zlib_filefunc_def io = zipio_create_io_from_file(&src_f);
+ DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ if (da) {
+ String current_dir = da->get_current_dir();
- ep.step("Creating app", 0);
+ // remove leftovers from last export so they don't interfere
+ // in case some files are no longer needed
+ if (da->change_dir(dest_dir + binary_name + ".xcodeproj") == OK) {
+ da->erase_contents_recursive();
+ }
+ if (da->change_dir(dest_dir + binary_name) == OK) {
+ da->erase_contents_recursive();
+ }
- unzFile src_pkg_zip = unzOpen2(src_pkg_name.utf8().get_data(), &io);
- if (!src_pkg_zip) {
+ da->change_dir(current_dir);
- EditorNode::add_io_error("Could not find template app to export:\n" + src_pkg_name);
- return ERR_FILE_NOT_FOUND;
+ if (!da->dir_exists(dest_dir + binary_name)) {
+ Error err = da->make_dir(dest_dir + binary_name);
+ if (err) {
+ memdelete(da);
+ return err;
+ }
+ }
+ memdelete(da);
}
- ERR_FAIL_COND_V(!src_pkg_zip, ERR_CANT_OPEN);
- int ret = unzGoToFirstFile(src_pkg_zip);
+ ep.step("Making .pck", 0);
+ String pack_path = dest_dir + binary_name + ".pck";
+ Vector<SharedObject> libraries;
+ Error err = save_pack(p_preset, pack_path, &libraries);
+ if (err)
+ return err;
- String binary_to_use = "godot.iphone." + String(p_debug ? "debug" : "release") + ".";
- int bits_mode = p_preset->get("application/bits_mode");
- binary_to_use += String(bits_mode == 0 ? "fat" : bits_mode == 1 ? "arm64" : "armv7");
+ ep.step("Extracting and configuring Xcode project", 1);
- print_line("binary: " + binary_to_use);
+ String library_to_use = "libgodot.iphone." + String(p_debug ? "debug" : "release") + ".fat.a";
+
+ print_line("static library: " + library_to_use);
String pkg_name;
if (p_preset->get("application/name") != "")
pkg_name = p_preset->get("application/name"); // app_name
@@ -455,22 +742,41 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
else
pkg_name = "Unnamed";
- DirAccess *tmp_app_path = DirAccess::create_for_path(dest_dir);
- ERR_FAIL_COND_V(!tmp_app_path, ERR_CANT_CREATE)
-
- /* Now process our template */
- bool found_binary = false;
+ bool found_library = false;
int total_size = 0;
+ const String project_file = "godot_ios.xcodeproj/project.pbxproj";
Set<String> files_to_parse;
files_to_parse.insert("godot_ios/godot_ios-Info.plist");
- files_to_parse.insert("godot_ios.xcodeproj/project.pbxproj");
- files_to_parse.insert("export_options.plist");
+ files_to_parse.insert(project_file);
+ files_to_parse.insert("godot_ios/export_options.plist");
+ files_to_parse.insert("godot_ios/dummy.cpp");
files_to_parse.insert("godot_ios.xcodeproj/project.xcworkspace/contents.xcworkspacedata");
files_to_parse.insert("godot_ios.xcodeproj/xcshareddata/xcschemes/godot_ios.xcscheme");
- print_line("Unzipping...");
+ IOSConfigData config_data = {
+ pkg_name,
+ binary_name,
+ _get_additional_plist_content(),
+ String(" ").join(_get_preset_architectures(p_preset)),
+ _get_linker_flags(),
+ _get_cpp_code()
+ };
+
+ DirAccess *tmp_app_path = DirAccess::create_for_path(dest_dir);
+ ERR_FAIL_COND_V(!tmp_app_path, ERR_CANT_CREATE)
+ print_line("Unzipping...");
+ FileAccess *src_f = NULL;
+ zlib_filefunc_def io = zipio_create_io_from_file(&src_f);
+ unzFile src_pkg_zip = unzOpen2(src_pkg_name.utf8().get_data(), &io);
+ if (!src_pkg_zip) {
+ EditorNode::add_io_error("Could not open export template (not a zip file?):\n" + src_pkg_name);
+ return ERR_CANT_OPEN;
+ }
+ ERR_FAIL_COND_V(!src_pkg_zip, ERR_CANT_OPEN);
+ int ret = unzGoToFirstFile(src_pkg_zip);
+ Vector<uint8_t> project_file_data;
while (ret == UNZ_OK) {
bool is_execute = false;
@@ -496,15 +802,18 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
if (files_to_parse.has(file)) {
print_line(String("parse ") + file);
- _fix_config_file(p_preset, data, pkg_name, binary_name, p_debug);
- } else if (file.begins_with("godot.iphone")) {
- if (file != binary_to_use) {
+ _fix_config_file(p_preset, data, config_data, p_debug);
+ } else if (file.begins_with("libgodot.iphone")) {
+ if (file != library_to_use) {
ret = unzGoToNextFile(src_pkg_zip);
continue; //ignore!
}
- found_binary = true;
+ found_library = true;
is_execute = true;
- file = "godot_ios.iphone";
+ file = "godot_ios.a";
+ }
+ if (file == project_file) {
+ project_file_data = data;
}
///@TODO need to parse logo files
@@ -557,16 +866,16 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
/* we're done with our source zip */
unzClose(src_pkg_zip);
- if (!found_binary) {
- ERR_PRINTS("Requested template binary '" + binary_to_use + "' not found. It might be missing from your template archive.");
+ if (!found_library) {
+ ERR_PRINTS("Requested template library '" + library_to_use + "' not found. It might be missing from your template archive.");
memdelete(tmp_app_path);
return ERR_FILE_NOT_FOUND;
}
String iconset_dir = dest_dir + binary_name + "/Images.xcassets/AppIcon.appiconset/";
- Error err = OK;
+ err = OK;
if (!tmp_app_path->dir_exists(iconset_dir)) {
- Error err = tmp_app_path->make_dir_recursive(iconset_dir);
+ err = tmp_app_path->make_dir_recursive(iconset_dir);
}
memdelete(tmp_app_path);
if (err)
@@ -580,19 +889,30 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
if (err)
return err;
- ep.step("Making .pck", 1);
-
- String pack_path = dest_dir + binary_name + ".pck";
- err = save_pack(p_preset, pack_path);
- if (err)
- return err;
-
- err = export_project_files(p_preset, _export_dylibs, &dest_dir);
- if (err)
- return err;
+ print_line("Exporting additional assets");
+ Vector<IOSExportAsset> assets;
+ _export_additional_assets(dest_dir + binary_name, libraries, assets);
+ _add_assets_to_project(project_file_data, assets);
+ String project_file_name = dest_dir + binary_name + ".xcodeproj/project.pbxproj";
+ FileAccess *f = FileAccess::open(project_file_name, FileAccess::WRITE);
+ if (!f) {
+ ERR_PRINTS("Can't write '" + project_file_name + "'.");
+ return ERR_CANT_CREATE;
+ };
+ f->store_buffer(project_file_data.ptr(), project_file_data.size());
+ f->close();
+ memdelete(f);
#ifdef OSX_ENABLED
- ep.step("Making .xcarchive", 2);
+ ep.step("Code-signing dylibs", 2);
+ DirAccess *dylibs_dir = DirAccess::open(dest_dir + binary_name + "/dylibs");
+ ERR_FAIL_COND_V(!dylibs_dir, ERR_CANT_OPEN);
+ CodesignData codesign_data(p_preset, p_debug);
+ err = _walk_dir_recursive(dylibs_dir, _codesign, &codesign_data);
+ memdelete(dylibs_dir);
+ ERR_FAIL_COND_V(err, err);
+
+ ep.step("Making .xcarchive", 3);
String archive_path = p_path.get_basename() + ".xcarchive";
List<String> archive_args;
archive_args.push_back("-project");
@@ -608,15 +928,7 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
archive_args.push_back("archive");
archive_args.push_back("-archivePath");
archive_args.push_back(archive_path);
- err = OS::get_singleton()->execute("/usr/bin/xcodebuild", archive_args, true);
- ERR_FAIL_COND_V(err, err);
-
- ep.step("Code-signing dylibs", 3);
- DirAccess *dylibs_dir = DirAccess::open(archive_path + "/Products/Applications/" + binary_name + ".app/dylibs");
- ERR_FAIL_COND_V(!dylibs_dir, ERR_CANT_OPEN);
- CodesignData codesign_data(p_preset, p_debug);
- err = _walk_dir_recursive(dylibs_dir, _codesign, &codesign_data);
- memdelete(dylibs_dir);
+ err = OS::get_singleton()->execute("xcodebuild", archive_args, true);
ERR_FAIL_COND_V(err, err);
ep.step("Making .ipa", 4);
@@ -625,13 +937,14 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
export_args.push_back("-archivePath");
export_args.push_back(archive_path);
export_args.push_back("-exportOptionsPlist");
- export_args.push_back(dest_dir + "export_options.plist");
+ export_args.push_back(dest_dir + binary_name + "/export_options.plist");
+ export_args.push_back("-allowProvisioningUpdates");
export_args.push_back("-exportPath");
export_args.push_back(dest_dir);
- err = OS::get_singleton()->execute("/usr/bin/xcodebuild", export_args, true);
+ err = OS::get_singleton()->execute("xcodebuild", export_args, true);
ERR_FAIL_COND_V(err, err);
#else
- print_line(".ipa can only be built on macOS. Leaving XCode project without building the package.");
+ print_line(".ipa can only be built on macOS. Leaving Xcode project without building the package.");
#endif
return OK;
diff --git a/platform/iphone/game_center.h b/platform/iphone/game_center.h
index c0a7830fe9..21f40fa362 100644
--- a/platform/iphone/game_center.h
+++ b/platform/iphone/game_center.h
@@ -43,11 +43,13 @@ class GameCenter : public Object {
List<Variant> pending_events;
- bool connected;
+ bool authenticated;
+
+ void return_connect_error(const char *p_error_description);
public:
- Error connect();
- bool is_connected();
+ void connect();
+ bool is_authenticated();
Error post_score(Variant p_score);
Error award_achievement(Variant p_params);
@@ -55,6 +57,7 @@ public:
void request_achievements();
void request_achievement_descriptions();
Error show_game_center(Variant p_params);
+ Error request_identity_verification_signature();
void game_center_closed();
diff --git a/platform/iphone/game_center.mm b/platform/iphone/game_center.mm
index 821ef2a3ab..d2104ae765 100644
--- a/platform/iphone/game_center.mm
+++ b/platform/iphone/game_center.mm
@@ -49,8 +49,7 @@ extern "C" {
GameCenter *GameCenter::instance = NULL;
void GameCenter::_bind_methods() {
- ClassDB::bind_method(D_METHOD("connect"), &GameCenter::connect);
- ClassDB::bind_method(D_METHOD("is_connected"), &GameCenter::is_connected);
+ ClassDB::bind_method(D_METHOD("is_authenticated"), &GameCenter::is_authenticated);
ClassDB::bind_method(D_METHOD("post_score"), &GameCenter::post_score);
ClassDB::bind_method(D_METHOD("award_achievement"), &GameCenter::award_achievement);
@@ -58,24 +57,41 @@ void GameCenter::_bind_methods() {
ClassDB::bind_method(D_METHOD("request_achievements"), &GameCenter::request_achievements);
ClassDB::bind_method(D_METHOD("request_achievement_descriptions"), &GameCenter::request_achievement_descriptions);
ClassDB::bind_method(D_METHOD("show_game_center"), &GameCenter::show_game_center);
+ ClassDB::bind_method(D_METHOD("request_identity_verification_signature"), &GameCenter::request_identity_verification_signature);
ClassDB::bind_method(D_METHOD("get_pending_event_count"), &GameCenter::get_pending_event_count);
ClassDB::bind_method(D_METHOD("pop_pending_event"), &GameCenter::pop_pending_event);
};
-Error GameCenter::connect() {
+void GameCenter::return_connect_error(const char *p_error_description) {
+ authenticated = false;
+ Dictionary ret;
+ ret["type"] = "authentication";
+ ret["result"] = "error";
+ ret["error_code"] = 0;
+ ret["error_description"] = p_error_description;
+ pending_events.push_back(ret);
+}
+
+void GameCenter::connect() {
//if this class isn't available, game center isn't implemented
if ((NSClassFromString(@"GKLocalPlayer")) == nil) {
- GameCenter::get_singleton()->connected = false;
- return ERR_UNAVAILABLE;
+ return_connect_error("GameCenter not available");
+ return;
}
GKLocalPlayer *player = [GKLocalPlayer localPlayer];
- ERR_FAIL_COND_V(![player respondsToSelector:@selector(authenticateHandler)], ERR_UNAVAILABLE);
+ if (![player respondsToSelector:@selector(authenticateHandler)]) {
+ return_connect_error("GameCenter doesn't respond to 'authenticateHandler'");
+ return;
+ }
ViewController *root_controller = (ViewController *)((AppDelegate *)[[UIApplication sharedApplication] delegate]).window.rootViewController;
- ERR_FAIL_COND_V(!root_controller, FAILED);
+ if (!root_controller) {
+ return_connect_error("Window doesn't have root ViewController");
+ return;
+ }
// This handler is called several times. First when the view needs to be shown, then again
// after the view is cancelled or the user logs in. Or if the user's already logged in, it's
@@ -89,24 +105,22 @@ Error GameCenter::connect() {
ret["type"] = "authentication";
if (player.isAuthenticated) {
ret["result"] = "ok";
- ret["player_id"] = player.playerID;
- GameCenter::get_singleton()->connected = true;
+ ret["player_id"] = [player.playerID UTF8String];
+ GameCenter::get_singleton()->authenticated = true;
} else {
ret["result"] = "error";
- ret["error_code"] = error.code;
+ ret["error_code"] = (int64_t)error.code;
ret["error_description"] = [error.localizedDescription UTF8String];
- GameCenter::get_singleton()->connected = false;
+ GameCenter::get_singleton()->authenticated = false;
};
pending_events.push_back(ret);
};
});
-
- return OK;
};
-bool GameCenter::is_connected() {
- return connected;
+bool GameCenter::is_authenticated() {
+ return authenticated;
};
Error GameCenter::post_score(Variant p_score) {
@@ -117,7 +131,7 @@ Error GameCenter::post_score(Variant p_score) {
String category = params["category"];
NSString *cat_str = [[[NSString alloc] initWithUTF8String:category.utf8().get_data()] autorelease];
- GKScore *reporter = [[[GKScore alloc] initWithCategory:cat_str] autorelease];
+ GKScore *reporter = [[[GKScore alloc] initWithLeaderboardIdentifier:cat_str] autorelease];
reporter.value = score;
ERR_FAIL_COND_V([GKScore respondsToSelector:@selector(reportScores)], ERR_UNAVAILABLE);
@@ -131,7 +145,7 @@ Error GameCenter::post_score(Variant p_score) {
ret["result"] = "ok";
} else {
ret["result"] = "error";
- ret["error_code"] = error.code;
+ ret["error_code"] = (int64_t)error.code;
ret["error_description"] = [error.localizedDescription UTF8String];
};
@@ -169,7 +183,7 @@ Error GameCenter::award_achievement(Variant p_params) {
ret["result"] = "ok";
} else {
ret["result"] = "error";
- ret["error_code"] = error.code;
+ ret["error_code"] = (int64_t)error.code;
};
pending_events.push_back(ret);
@@ -227,7 +241,7 @@ void GameCenter::request_achievement_descriptions() {
} else {
ret["result"] = "error";
- ret["error_code"] = error.code;
+ ret["error_code"] = (int64_t)error.code;
};
pending_events.push_back(ret);
@@ -259,7 +273,7 @@ void GameCenter::request_achievements() {
} else {
ret["result"] = "error";
- ret["error_code"] = error.code;
+ ret["error_code"] = (int64_t)error.code;
};
pending_events.push_back(ret);
@@ -275,7 +289,7 @@ void GameCenter::reset_achievements() {
ret["result"] = "ok";
} else {
ret["result"] = "error";
- ret["error_code"] = error.code;
+ ret["error_code"] = (int64_t)error.code;
};
pending_events.push_back(ret);
@@ -326,6 +340,34 @@ Error GameCenter::show_game_center(Variant p_params) {
return OK;
};
+Error GameCenter::request_identity_verification_signature() {
+
+ ERR_FAIL_COND_V(!is_authenticated(), ERR_UNAUTHORIZED);
+
+ GKLocalPlayer *player = [GKLocalPlayer localPlayer];
+ [player generateIdentityVerificationSignatureWithCompletionHandler:^(NSURL *publicKeyUrl, NSData *signature, NSData *salt, uint64_t timestamp, NSError *error) {
+
+ Dictionary ret;
+ ret["type"] = "identity_verification_signature";
+ if (error == nil) {
+ ret["result"] = "ok";
+ ret["public_key_url"] = [publicKeyUrl.absoluteString UTF8String];
+ ret["signature"] = [[signature base64EncodedStringWithOptions:0] UTF8String];
+ ret["salt"] = [[salt base64EncodedStringWithOptions:0] UTF8String];
+ ret["timestamp"] = timestamp;
+ ret["player_id"] = [player.playerID UTF8String];
+ } else {
+ ret["result"] = "error";
+ ret["error_code"] = (int64_t)error.code;
+ ret["error_description"] = [error.localizedDescription UTF8String];
+ };
+
+ pending_events.push_back(ret);
+ }];
+
+ return OK;
+};
+
void GameCenter::game_center_closed() {
Dictionary ret;
@@ -354,7 +396,7 @@ GameCenter *GameCenter::get_singleton() {
GameCenter::GameCenter() {
ERR_FAIL_COND(instance != NULL);
instance = this;
- connected = false;
+ authenticated = false;
};
GameCenter::~GameCenter(){};
diff --git a/platform/iphone/globals/global_defaults.cpp b/platform/iphone/globals/global_defaults.cpp
index 4bdc716d6e..b81e6def3b 100644
--- a/platform/iphone/globals/global_defaults.cpp
+++ b/platform/iphone/globals/global_defaults.cpp
@@ -31,11 +31,4 @@
#include "project_settings.h"
void register_iphone_global_defaults() {
-
- /*GLOBAL_DEF("rasterizer.iOS/use_fragment_lighting",false);
- GLOBAL_DEF("rasterizer.iOS/fp16_framebuffer",false);
- GLOBAL_DEF("display.iOS/driver","GLES2");
- ProjectSettings::get_singleton()->set_custom_property_info("display.iOS/driver",PropertyInfo(Variant::STRING,"display.iOS/driver",PROPERTY_HINT_ENUM,"GLES1,GLES2"));
- GLOBAL_DEF("display.iOS/use_cadisplaylink",true);
- */
}
diff --git a/platform/iphone/godot_iphone.cpp b/platform/iphone/godot_iphone.cpp
index 8c6d6d8da4..7d21d35e18 100644
--- a/platform/iphone/godot_iphone.cpp
+++ b/platform/iphone/godot_iphone.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "main/main.h"
#include "os_iphone.h"
+#include "ustring.h"
#include <stdio.h>
#include <string.h>
@@ -41,9 +42,9 @@ int add_path(int p_argc, char **p_args);
int add_cmdline(int p_argc, char **p_args);
};
-int iphone_main(int, int, int, char **);
+int iphone_main(int, int, int, char **, String);
-int iphone_main(int width, int height, int argc, char **argv) {
+int iphone_main(int width, int height, int argc, char **argv, String data_dir) {
int len = strlen(argv[0]);
@@ -63,7 +64,7 @@ int iphone_main(int width, int height, int argc, char **argv) {
char cwd[512];
getcwd(cwd, sizeof(cwd));
printf("cwd %s\n", cwd);
- os = new OSIPhone(width, height);
+ os = new OSIPhone(width, height, data_dir);
char *fargv[64];
for (int i = 0; i < argc; i++) {
diff --git a/platform/iphone/in_app_store.mm b/platform/iphone/in_app_store.mm
index 9efd4b9891..25f4e1e166 100644
--- a/platform/iphone/in_app_store.mm
+++ b/platform/iphone/in_app_store.mm
@@ -92,6 +92,7 @@ void InAppStore::_bind_methods() {
PoolRealArray prices;
PoolStringArray ids;
PoolStringArray localized_prices;
+ PoolStringArray currency_codes;
for (int i = 0; i < [products count]; i++) {
@@ -105,12 +106,14 @@ void InAppStore::_bind_methods() {
prices.push_back([product.price doubleValue]);
ids.push_back(String::utf8([product.productIdentifier UTF8String]));
localized_prices.push_back(String::utf8([product.localizedPrice UTF8String]));
+ currency_codes.push_back(String::utf8([[[product priceLocale] objectForKey:NSLocaleCurrencyCode] UTF8String]));
};
ret["titles"] = titles;
ret["descriptions"] = descriptions;
ret["prices"] = prices;
ret["ids"] = ids;
ret["localized_prices"] = localized_prices;
+ ret["currency_codes"] = currency_codes;
PoolStringArray invalid_ids;
diff --git a/platform/iphone/os_iphone.cpp b/platform/iphone/os_iphone.cpp
index 219e93facf..fbe3bd310d 100644
--- a/platform/iphone/os_iphone.cpp
+++ b/platform/iphone/os_iphone.cpp
@@ -46,6 +46,7 @@
#include "sem_iphone.h"
#include "ios.h"
+#include <dlfcn.h>
int OSIPhone::get_video_driver_count() const {
@@ -54,7 +55,7 @@ int OSIPhone::get_video_driver_count() const {
const char *OSIPhone::get_video_driver_name(int p_driver) const {
- return "GLES2";
+ return "GLES3";
};
OSIPhone *OSIPhone::get_singleton() {
@@ -62,11 +63,6 @@ OSIPhone *OSIPhone::get_singleton() {
return (OSIPhone *)OS::get_singleton();
};
-OS::VideoMode OSIPhone::get_default_video_mode() const {
-
- return video_mode;
-};
-
uint8_t OSIPhone::get_orientations() const {
return supported_orientations;
@@ -97,14 +93,9 @@ void OSIPhone::initialize_core() {
OS_Unix::initialize_core();
SemaphoreIphone::make_default();
-};
-void OSIPhone::initialize_logger() {
- Vector<Logger *> loggers;
- loggers.push_back(memnew(SyslogLogger));
- loggers.push_back(memnew(RotatedFileLogger("user://logs/log.txt")));
- _set_logger(memnew(CompositeLogger(loggers)));
-}
+ set_data_dir(data_dir);
+};
void OSIPhone::initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) {
@@ -134,40 +125,33 @@ void OSIPhone::initialize(const VideoMode &p_desired, int p_video_driver, int p_
AudioDriverManager::add_driver(&audio_driver);
AudioDriverManager::initialize(p_audio_driver);
- // init physics servers
- physics_server = memnew(PhysicsServerSW);
- physics_server->init();
- //physics_2d_server = memnew( Physics2DServerSW );
- physics_2d_server = Physics2DServerWrapMT::init_server<Physics2DServerSW>();
- physics_2d_server->init();
-
input = memnew(InputDefault);
/*
#ifdef IOS_SCORELOOP_ENABLED
scoreloop = memnew(ScoreloopIOS);
- ProjectSettings::get_singleton()->add_singleton(ProjectSettings::Singleton("Scoreloop", scoreloop));
+ Engine::get_singleton()->add_singleton(Engine::Singleton("Scoreloop", scoreloop));
scoreloop->connect();
#endif
*/
#ifdef GAME_CENTER_ENABLED
game_center = memnew(GameCenter);
- ProjectSettings::get_singleton()->add_singleton(ProjectSettings::Singleton("GameCenter", game_center));
+ Engine::get_singleton()->add_singleton(Engine::Singleton("GameCenter", game_center));
game_center->connect();
#endif
#ifdef STOREKIT_ENABLED
store_kit = memnew(InAppStore);
- ProjectSettings::get_singleton()->add_singleton(ProjectSettings::Singleton("InAppStore", store_kit));
+ Engine::get_singleton()->add_singleton(Engine::Singleton("InAppStore", store_kit));
#endif
#ifdef ICLOUD_ENABLED
icloud = memnew(ICloud);
- ProjectSettings::get_singleton()->add_singleton(ProjectSettings::Singleton("ICloud", icloud));
+ Engine::get_singleton()->add_singleton(Engine::Singleton("ICloud", icloud));
//icloud->connect();
#endif
- ProjectSettings::get_singleton()->add_singleton(ProjectSettings::Singleton("iOS", memnew(iOS)));
+ Engine::get_singleton()->add_singleton(Engine::Singleton("iOS", memnew(iOS)));
};
MainLoop *OSIPhone::get_main_loop() const {
@@ -380,12 +364,6 @@ void OSIPhone::finalize() {
memdelete(visual_server);
// memdelete(rasterizer);
- physics_server->finish();
- memdelete(physics_server);
-
- physics_2d_server->finish();
- memdelete(physics_2d_server);
-
memdelete(input);
};
@@ -416,6 +394,37 @@ void OSIPhone::alert(const String &p_alert, const String &p_title) {
iOS::alert(utf8_alert.get_data(), utf8_title.get_data());
}
+Error OSIPhone::open_dynamic_library(const String p_path, void *&p_library_handle) {
+ if (p_path.length() == 0) {
+ p_library_handle = RTLD_SELF;
+ return OK;
+ }
+ return OS_Unix::open_dynamic_library(p_path, p_library_handle);
+}
+
+Error OSIPhone::close_dynamic_library(void *p_library_handle) {
+ if (p_library_handle == RTLD_SELF) {
+ return OK;
+ }
+ return OS_Unix::close_dynamic_library(p_library_handle);
+}
+
+HashMap<String, void *> OSIPhone::dynamic_symbol_lookup_table;
+void register_dynamic_symbol(char *name, void *address) {
+ OSIPhone::dynamic_symbol_lookup_table[String(name)] = address;
+}
+
+Error OSIPhone::get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional) {
+ if (p_library_handle == RTLD_SELF) {
+ void **ptr = OSIPhone::dynamic_symbol_lookup_table.getptr(p_name);
+ if (ptr) {
+ p_symbol_handle = *ptr;
+ return OK;
+ }
+ }
+ return OS_Unix::get_dynamic_library_symbol_handle(p_library_handle, p_name, p_symbol_handle, p_optional);
+}
+
void OSIPhone::set_video_mode(const VideoMode &p_video_mode, int p_screen) {
video_mode = p_video_mode;
@@ -484,7 +493,7 @@ void OSIPhone::set_cursor_shape(CursorShape p_shape){
};
-String OSIPhone::get_data_dir() const {
+String OSIPhone::get_user_data_dir() const {
return data_dir;
};
@@ -523,7 +532,7 @@ Error OSIPhone::native_video_play(String p_path, float p_volume, String p_audio_
FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
bool exists = f && f->is_open();
- String tempFile = get_data_dir();
+ String tempFile = get_user_data_dir();
if (!exists)
return FAILED;
@@ -535,7 +544,7 @@ Error OSIPhone::native_video_play(String p_path, float p_volume, String p_audio_
p_path = p_path.replace("res:/", ProjectSettings::get_singleton()->get_resource_path());
}
} else if (p_path.begins_with("user://"))
- p_path = p_path.replace("user:/", get_data_dir());
+ p_path = p_path.replace("user:/", get_user_data_dir());
memdelete(f);
@@ -572,7 +581,36 @@ bool OSIPhone::_check_internal_feature_support(const String &p_feature) {
return p_feature == "mobile" || p_feature == "etc" || p_feature == "pvrtc" || p_feature == "etc2";
}
-OSIPhone::OSIPhone(int width, int height) {
+// Initialization order between compilation units is not guaranteed,
+// so we use this as a hack to ensure certain code is called before
+// everything else, but after all units are initialized.
+typedef void (*init_callback)();
+static init_callback *ios_init_callbacks = NULL;
+static int ios_init_callbacks_count = 0;
+static int ios_init_callbacks_capacity = 0;
+
+void add_ios_init_callback(init_callback cb) {
+ if (ios_init_callbacks_count == ios_init_callbacks_capacity) {
+ void *new_ptr = realloc(ios_init_callbacks, sizeof(cb) * 32);
+ if (new_ptr) {
+ ios_init_callbacks = (init_callback *)(new_ptr);
+ ios_init_callbacks_capacity += 32;
+ }
+ }
+ if (ios_init_callbacks_capacity > ios_init_callbacks_count) {
+ ios_init_callbacks[ios_init_callbacks_count] = cb;
+ ++ios_init_callbacks_count;
+ }
+}
+
+OSIPhone::OSIPhone(int width, int height, String p_data_dir) {
+ for (int i = 0; i < ios_init_callbacks_count; ++i) {
+ ios_init_callbacks[i]();
+ }
+ free(ios_init_callbacks);
+ ios_init_callbacks = NULL;
+ ios_init_callbacks_count = 0;
+ ios_init_callbacks_capacity = 0;
main_loop = NULL;
visual_server = NULL;
@@ -586,7 +624,17 @@ OSIPhone::OSIPhone(int width, int height) {
event_count = 0;
virtual_keyboard_height = 0;
- _set_logger(memnew(SyslogLogger));
+ // can't call set_data_dir from here, since it requires DirAccess
+ // which is initialized in initialize_core
+ data_dir = p_data_dir;
+
+ Vector<Logger *> loggers;
+ loggers.push_back(memnew(SyslogLogger));
+#ifdef DEBUG_ENABLED
+ // it seems iOS app's stdout/stderr is only obtainable if you launch it from Xcode
+ loggers.push_back(memnew(StdLogger));
+#endif
+ _set_logger(memnew(CompositeLogger(loggers)));
};
OSIPhone::~OSIPhone() {
diff --git a/platform/iphone/os_iphone.h b/platform/iphone/os_iphone.h
index cf2396e87b..1ef673765a 100644
--- a/platform/iphone/os_iphone.h
+++ b/platform/iphone/os_iphone.h
@@ -41,9 +41,6 @@
#include "in_app_store.h"
#include "main/input_default.h"
#include "servers/audio_server.h"
-#include "servers/physics/physics_server_sw.h"
-#include "servers/physics_2d/physics_2d_server_sw.h"
-#include "servers/physics_2d/physics_2d_server_wrap_mt.h"
#include "servers/visual/rasterizer.h"
#include "servers/visual_server.h"
@@ -63,11 +60,12 @@ private:
MAX_EVENTS = 64,
};
+ static HashMap<String, void *> dynamic_symbol_lookup_table;
+ friend void register_dynamic_symbol(char *name, void *address);
+
uint8_t supported_orientations;
VisualServer *visual_server;
- PhysicsServer *physics_server;
- Physics2DServer *physics_2d_server;
AudioDriverCoreAudio audio_driver;
@@ -88,9 +86,6 @@ private:
virtual int get_video_driver_count() const;
virtual const char *get_video_driver_name(int p_driver) const;
- virtual VideoMode get_default_video_mode() const;
-
- virtual void initialize_logger();
virtual void initialize_core();
virtual void initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver);
@@ -160,6 +155,10 @@ public:
virtual void alert(const String &p_alert, const String &p_title = "ALERT!");
+ virtual Error open_dynamic_library(const String p_path, void *&p_library_handle);
+ virtual Error close_dynamic_library(void *p_library_handle);
+ virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional = false);
+
virtual void set_video_mode(const VideoMode &p_video_mode, int p_screen = 0);
virtual VideoMode get_video_mode(int p_screen = 0) const;
virtual void get_fullscreen_mode_list(List<VideoMode> *p_list, int p_screen = 0) const;
@@ -185,7 +184,7 @@ public:
Error shell_open(String p_uri);
- String get_data_dir() const;
+ String get_user_data_dir() const;
void set_locale(String p_locale);
String get_locale() const;
@@ -201,7 +200,7 @@ public:
virtual void native_video_stop();
virtual bool _check_internal_feature_support(const String &p_feature);
- OSIPhone(int width, int height);
+ OSIPhone(int width, int height, String p_data_dir);
~OSIPhone();
};
diff --git a/platform/iphone/platform_config.h b/platform/iphone/platform_config.h
index 54de66082e..7ff6e7a9a9 100644
--- a/platform/iphone/platform_config.h
+++ b/platform/iphone/platform_config.h
@@ -28,7 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include <alloca.h>
-// #define GLES2_INCLUDE_H <ES2/gl.h>
+
#define GLES3_INCLUDE_H <ES3/gl.h>
#define PLATFORM_REFCOUNT
diff --git a/platform/javascript/SCsub b/platform/javascript/SCsub
index f01d9367d2..8d505a5829 100644
--- a/platform/javascript/SCsub
+++ b/platform/javascript/SCsub
@@ -6,8 +6,8 @@ javascript_files = [
"os_javascript.cpp",
"audio_driver_javascript.cpp",
"javascript_main.cpp",
- "audio_server_javascript.cpp",
"power_javascript.cpp",
+ "http_client_javascript.cpp",
"javascript_eval.cpp",
]
@@ -19,33 +19,23 @@ javascript_objects = []
for x in javascript_files:
javascript_objects.append(env_javascript.Object(x))
-env.Append(LINKFLAGS=["-s", "EXPORTED_FUNCTIONS=\"['_main','_audio_server_mix_function','_main_after_fs_sync','_send_notification']\""])
+env.Append(LINKFLAGS=["-s", "EXPORTED_FUNCTIONS=\"['_main','_main_after_fs_sync','_send_notification']\""])
-# output file name without file extension
-basename = "godot" + env["PROGSUFFIX"]
target_dir = env.Dir("#bin")
+build = env.Program(['#bin/godot', target_dir.File('godot' + env['PROGSUFFIX'] + '.wasm')], javascript_objects, PROGSUFFIX=env['PROGSUFFIX'] + '.js');
-zip_dir = target_dir.Dir('.javascript_zip')
-zip_files = env.InstallAs(zip_dir.File('godot.html'), '#misc/dist/html/default.html')
-
-implicit_targets = []
-if env['wasm']:
- wasm = target_dir.File(basename + '.wasm')
- implicit_targets.append(wasm)
- zip_files.append(InstallAs(zip_dir.File('godot.wasm'), wasm))
- prejs = env.File('pre_wasm.js')
-else:
- asmjs_files = [target_dir.File(basename + '.asm.js'), target_dir.File(basename + '.js.mem')]
- implicit_targets.extend(asmjs_files)
- zip_files.append(InstallAs([zip_dir.File('godot.asm.js'), zip_dir.File('godot.mem')], asmjs_files))
- prejs = env.File('pre_asmjs.js')
-
-js = env.Program(['#bin/godot'] + implicit_targets, javascript_objects, PROGSUFFIX=env['PROGSUFFIX'] + '.js')[0];
-zip_files.append(InstallAs(zip_dir.File('godot.js'), js))
+js_libraries = []
+js_libraries.append(env.File('http_request.js'))
+for lib in js_libraries:
+ env.Append(LINKFLAGS=['--js-library', lib.path])
+env.Depends(build, js_libraries)
+prejs = env.File('pre.js')
postjs = env.File('engine.js')
-env.Depends(js, [prejs, postjs])
env.Append(LINKFLAGS=['--pre-js', prejs.path])
env.Append(LINKFLAGS=['--post-js', postjs.path])
+env.Depends(build, [prejs, postjs])
+zip_dir = target_dir.Dir('.javascript_zip')
+zip_files = env.InstallAs([zip_dir.File('godot.js'), zip_dir.File('godot.wasm'), zip_dir.File('godot.html')], build + ['#misc/dist/html/default.html'])
Zip('#bin/godot', zip_files, ZIPSUFFIX=env['PROGSUFFIX'] + env['ZIPSUFFIX'], ZIPROOT=zip_dir, ZIPCOMSTR="Archving $SOURCES as $TARGET")
diff --git a/platform/javascript/api/api.cpp b/platform/javascript/api/api.cpp
new file mode 100644
index 0000000000..f2b2ca40bf
--- /dev/null
+++ b/platform/javascript/api/api.cpp
@@ -0,0 +1,73 @@
+/*************************************************************************/
+/* api.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#include "api.h"
+#include "engine.h"
+#include "javascript_eval.h"
+
+static JavaScript *javascript_eval;
+
+void register_javascript_api() {
+
+ ClassDB::register_virtual_class<JavaScript>();
+ javascript_eval = memnew(JavaScript);
+ Engine::get_singleton()->add_singleton(Engine::Singleton("JavaScript", javascript_eval));
+}
+
+void unregister_javascript_api() {
+
+ memdelete(javascript_eval);
+}
+
+JavaScript *JavaScript::singleton = NULL;
+
+JavaScript *JavaScript::get_singleton() {
+
+ return singleton;
+}
+
+JavaScript::JavaScript() {
+
+ ERR_FAIL_COND(singleton != NULL);
+ singleton = this;
+}
+
+JavaScript::~JavaScript() {}
+
+void JavaScript::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("eval", "code", "use_global_execution_context"), &JavaScript::eval, DEFVAL(false));
+}
+
+#if !defined(JAVASCRIPT_ENABLED) || !defined(JAVASCRIPT_EVAL_ENABLED)
+Variant JavaScript::eval(const String &p_code, bool p_use_global_exec_context) {
+
+ return Variant();
+}
+#endif
diff --git a/platform/javascript/api/api.h b/platform/javascript/api/api.h
new file mode 100644
index 0000000000..53cd9239fc
--- /dev/null
+++ b/platform/javascript/api/api.h
@@ -0,0 +1,31 @@
+/*************************************************************************/
+/* api.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 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. */
+/*************************************************************************/
+void register_javascript_api();
+void unregister_javascript_api();
diff --git a/platform/javascript/javascript_eval.h b/platform/javascript/api/javascript_eval.h
index ed7cf383da..4d0b0b21ff 100644
--- a/platform/javascript/javascript_eval.h
+++ b/platform/javascript/api/javascript_eval.h
@@ -27,8 +27,6 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifdef JAVASCRIPT_EVAL_ENABLED
-
#ifndef JAVASCRIPT_EVAL_H
#define JAVASCRIPT_EVAL_H
@@ -52,4 +50,3 @@ public:
};
#endif // JAVASCRIPT_EVAL_H
-#endif // JAVASCRIPT_EVAL_ENABLED
diff --git a/platform/javascript/audio_driver_javascript.cpp b/platform/javascript/audio_driver_javascript.cpp
index 4c0e5fd966..9633472cd2 100644
--- a/platform/javascript/audio_driver_javascript.cpp
+++ b/platform/javascript/audio_driver_javascript.cpp
@@ -29,31 +29,86 @@
/*************************************************************************/
#include "audio_driver_javascript.h"
-#include <string.h>
+#include <emscripten.h>
-#define MAX_NUMBER_INTERFACES 3
-#define MAX_NUMBER_OUTPUT_DEVICES 6
-
-/* Structure for passing information to callback function */
-
-//AudioDriverJavaScript* AudioDriverJavaScript::s_ad=NULL;
+AudioDriverJavaScript *AudioDriverJavaScript::singleton_js = NULL;
const char *AudioDriverJavaScript::get_name() const {
return "JavaScript";
}
+extern "C" EMSCRIPTEN_KEEPALIVE void js_audio_driver_mix_function(int p_frames) {
+
+ //print_line("MIXI! "+itos(p_frames));
+ AudioDriverJavaScript::singleton_js->mix_to_js(p_frames);
+}
+
+void AudioDriverJavaScript::mix_to_js(int p_frames) {
+
+ int todo = p_frames;
+ int offset = 0;
+
+ while (todo) {
+
+ int tomix = MIN(todo, INTERNAL_BUFFER_SIZE);
+
+ audio_server_process(p_frames, stream_buffer);
+ for (int i = 0; i < tomix * internal_buffer_channels; i++) {
+ internal_buffer[i] = float(stream_buffer[i] >> 16) / 32768.0;
+ }
+
+ /* clang-format off */
+ EM_ASM_ARGS({
+ var data = HEAPF32.subarray($0 / 4, $0 / 4 + $2 * 2);
+
+ for (var channel = 0; channel < _as_output_buffer.numberOfChannels; channel++) {
+ var outputData = _as_output_buffer.getChannelData(channel);
+ // Loop through samples
+ for (var sample = 0; sample < $2; sample++) {
+ // make output equal to the same as the input
+ outputData[sample + $1] = data[sample * 2 + channel];
+ }
+ }
+ }, internal_buffer, offset, tomix);
+ /* clang-format on */
+
+ todo -= tomix;
+ offset += tomix;
+ }
+}
+
Error AudioDriverJavaScript::init() {
return OK;
}
void AudioDriverJavaScript::start() {
+
+ internal_buffer = memnew_arr(float, INTERNAL_BUFFER_SIZE *internal_buffer_channels);
+ stream_buffer = memnew_arr(int32_t, INTERNAL_BUFFER_SIZE * 4); //max 4 channels
+
+ /* clang-format off */
+ mix_rate = EM_ASM_INT({
+ _as_audioctx = new (window.AudioContext || window.webkitAudioContext);
+ _as_script_node = _as_audioctx.createScriptProcessor($0, 0, $1);
+ _as_script_node.connect(_as_audioctx.destination);
+ console.log(_as_script_node.bufferSize);
+ var jsAudioDriverMixFunction = cwrap('js_audio_driver_mix_function', null, ['number']);
+
+ _as_script_node.onaudioprocess = function(audioProcessingEvent) {
+ // The output buffer contains the samples that will be modified and played
+ _as_output_buffer = audioProcessingEvent.outputBuffer;
+ jsAudioDriverMixFunction([_as_output_buffer.getChannelData(0).length]);
+ };
+ return _as_audioctx.sampleRate;
+ }, INTERNAL_BUFFER_SIZE, internal_buffer_channels);
+ /* clang-format on */
}
int AudioDriverJavaScript::get_mix_rate() const {
- return 44100;
+ return mix_rate;
}
AudioDriver::SpeakerMode AudioDriverJavaScript::get_speaker_mode() const {
@@ -63,7 +118,7 @@ AudioDriver::SpeakerMode AudioDriverJavaScript::get_speaker_mode() const {
void AudioDriverJavaScript::lock() {
- /*
+ /*no locking, as threads are not supported
if (active && mutex)
mutex->lock();
*/
@@ -71,7 +126,7 @@ void AudioDriverJavaScript::lock() {
void AudioDriverJavaScript::unlock() {
- /*
+ /*no locking, as threads are not supported
if (active && mutex)
mutex->unlock();
*/
@@ -81,4 +136,8 @@ void AudioDriverJavaScript::finish() {
}
AudioDriverJavaScript::AudioDriverJavaScript() {
+
+ internal_buffer_channels = 2;
+ mix_rate = DEFAULT_MIX_RATE;
+ singleton_js = this;
}
diff --git a/platform/javascript/audio_driver_javascript.h b/platform/javascript/audio_driver_javascript.h
index c5cebe800f..b265c4e030 100644
--- a/platform/javascript/audio_driver_javascript.h
+++ b/platform/javascript/audio_driver_javascript.h
@@ -32,10 +32,21 @@
#include "servers/audio_server.h"
-#include "os/mutex.h"
-
class AudioDriverJavaScript : public AudioDriver {
+
+ enum {
+ INTERNAL_BUFFER_SIZE = 4096,
+ };
+
+ int mix_rate;
+ float *internal_buffer;
+ int internal_buffer_channels;
+ int32_t *stream_buffer;
+
public:
+ void mix_to_js(int p_frames);
+ static AudioDriverJavaScript *singleton_js;
+
virtual const char *get_name() const;
virtual Error init();
diff --git a/platform/javascript/audio_server_javascript.cpp b/platform/javascript/audio_server_javascript.cpp
deleted file mode 100644
index ab9f66ce5b..0000000000
--- a/platform/javascript/audio_server_javascript.cpp
+++ /dev/null
@@ -1,853 +0,0 @@
-/*************************************************************************/
-/* audio_server_javascript.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#include "audio_server_javascript.h"
-
-// FIXME: Needs to be ported to the new AudioServer API in 3.0
-#if 0
-#include "emscripten.h"
-
-AudioMixer *AudioServerJavascript::get_mixer() {
-
- return NULL;
-}
-
-void AudioServerJavascript::audio_mixer_chunk_callback(int p_frames){
-
-
-}
-
-
-RID AudioServerJavascript::sample_create(SampleFormat p_format, bool p_stereo, int p_length) {
-
- Sample *sample = memnew( Sample );
- sample->format=p_format;
- sample->stereo=p_stereo;
- sample->length=p_length;
- sample->loop_begin=0;
- sample->loop_end=p_length;
- sample->loop_format=SAMPLE_LOOP_NONE;
- sample->mix_rate=44100;
- sample->index=-1;
-
- return sample_owner.make_rid(sample);
-
-}
-
-void AudioServerJavascript::sample_set_description(RID p_sample, const String& p_description){
-
-
-}
-String AudioServerJavascript::sample_get_description(RID p_sample) const{
-
- return String();
-}
-
-AudioServerJavascript::SampleFormat AudioServerJavascript::sample_get_format(RID p_sample) const{
-
- return SAMPLE_FORMAT_PCM8;
-}
-bool AudioServerJavascript::sample_is_stereo(RID p_sample) const{
-
- const Sample *sample = sample_owner.get(p_sample);
- ERR_FAIL_COND_V(!sample,false);
- return sample->stereo;
-
-}
-int AudioServerJavascript::sample_get_length(RID p_sample) const{
- const Sample *sample = sample_owner.get(p_sample);
- ERR_FAIL_COND_V(!sample,0);
- return sample->length;
-}
-const void* AudioServerJavascript::sample_get_data_ptr(RID p_sample) const{
-
- return NULL;
-}
-
-void AudioServerJavascript::sample_set_data(RID p_sample, const PoolVector<uint8_t>& p_buffer){
-
- Sample *sample = sample_owner.get(p_sample);
- ERR_FAIL_COND(!sample);
- int chans = sample->stereo?2:1;
-
- Vector<float> buffer;
- buffer.resize(sample->length*chans);
- PoolVector<uint8_t>::Read r=p_buffer.read();
- if (sample->format==SAMPLE_FORMAT_PCM8) {
- const int8_t*ptr = (const int8_t*)r.ptr();
- for(int i=0;i<sample->length*chans;i++) {
- buffer[i]=ptr[i]/128.0;
- }
- } else if (sample->format==SAMPLE_FORMAT_PCM16){
- const int16_t*ptr = (const int16_t*)r.ptr();
- for(int i=0;i<sample->length*chans;i++) {
- buffer[i]=ptr[i]/32768.0;
- }
- } else {
- ERR_EXPLAIN("Unsupported for now");
- ERR_FAIL();
- }
-
- sample->tmp_data=buffer;
-
-
-
-}
-PoolVector<uint8_t> AudioServerJavascript::sample_get_data(RID p_sample) const{
-
-
- return PoolVector<uint8_t>();
-}
-
-void AudioServerJavascript::sample_set_mix_rate(RID p_sample,int p_rate){
- Sample *sample = sample_owner.get(p_sample);
- ERR_FAIL_COND(!sample);
- sample->mix_rate=p_rate;
-
-}
-
-int AudioServerJavascript::sample_get_mix_rate(RID p_sample) const{
- const Sample *sample = sample_owner.get(p_sample);
- ERR_FAIL_COND_V(!sample,0);
- return sample->mix_rate;
-}
-
-
-void AudioServerJavascript::sample_set_loop_format(RID p_sample,SampleLoopFormat p_format){
-
- Sample *sample = sample_owner.get(p_sample);
- ERR_FAIL_COND(!sample);
- sample->loop_format=p_format;
-
-}
-
-AudioServerJavascript::SampleLoopFormat AudioServerJavascript::sample_get_loop_format(RID p_sample) const {
-
- const Sample *sample = sample_owner.get(p_sample);
- ERR_FAIL_COND_V(!sample,SAMPLE_LOOP_NONE);
- return sample->loop_format;
-}
-
-void AudioServerJavascript::sample_set_loop_begin(RID p_sample,int p_pos){
-
- Sample *sample = sample_owner.get(p_sample);
- ERR_FAIL_COND(!sample);
- sample->loop_begin=p_pos;
-
-}
-int AudioServerJavascript::sample_get_loop_begin(RID p_sample) const{
-
- const Sample *sample = sample_owner.get(p_sample);
- ERR_FAIL_COND_V(!sample,0);
- return sample->loop_begin;
-}
-
-void AudioServerJavascript::sample_set_loop_end(RID p_sample,int p_pos){
-
- Sample *sample = sample_owner.get(p_sample);
- ERR_FAIL_COND(!sample);
- sample->loop_end=p_pos;
-
-}
-int AudioServerJavascript::sample_get_loop_end(RID p_sample) const{
-
- const Sample *sample = sample_owner.get(p_sample);
- ERR_FAIL_COND_V(!sample,0);
- return sample->loop_end;
-}
-
-
-/* VOICE API */
-
-RID AudioServerJavascript::voice_create(){
-
- Voice *voice = memnew( Voice );
-
- voice->index=voice_base;
- voice->volume=1.0;
- voice->pan=0.0;
- voice->pan_depth=.0;
- voice->pan_height=0.0;
- voice->chorus=0;
- voice->reverb_type=REVERB_SMALL;
- voice->reverb=0;
- voice->mix_rate=-1;
- voice->positional=false;
- voice->active=false;
-
- /* clang-format off */
- EM_ASM_( {
- _as_voices[$0] = null;
- _as_voice_gain[$0] = _as_audioctx.createGain();
- _as_voice_pan[$0] = _as_audioctx.createStereoPanner();
- _as_voice_gain[$0].connect(_as_voice_pan[$0]);
- _as_voice_pan[$0].connect(_as_audioctx.destination);
- }, voice_base);
- /* clang-format on */
-
- voice_base++;
-
- return voice_owner.make_rid( voice );
-}
-
-void AudioServerJavascript::voice_play(RID p_voice, RID p_sample){
-
- Voice* voice=voice_owner.get(p_voice);
- ERR_FAIL_COND(!voice);
- Sample *sample=sample_owner.get(p_sample);
- ERR_FAIL_COND(!sample);
-
- // due to how webaudio works, sample cration is deferred until used
- // sorry! WebAudio absolutely sucks
-
-
- if (sample->index==-1) {
- //create sample if not created
- ERR_FAIL_COND(sample->tmp_data.size()==0);
- sample->index=sample_base;
- /* clang-format off */
- EM_ASM_({
- _as_samples[$0] = _as_audioctx.createBuffer($1, $2, $3);
- }, sample_base, sample->stereo ? 2 : 1, sample->length, sample->mix_rate);
- /* clang-format on */
-
- sample_base++;
- int chans = sample->stereo?2:1;
-
-
- for(int i=0;i<chans;i++) {
- /* clang-format off */
- EM_ASM_({
- _as_edited_buffer = _as_samples[$0].getChannelData($1);
- }, sample->index, i);
- /* clang-format on */
-
- for(int j=0;j<sample->length;j++) {
- /* clang-format off */
- EM_ASM_({
- _as_edited_buffer[$0] = $1;
- }, j, sample->tmp_data[j * chans + i]);
- /* clang-format on */
- }
- }
-
- sample->tmp_data.clear();
- }
-
-
- voice->sample_mix_rate=sample->mix_rate;
- if (voice->mix_rate==-1) {
- voice->mix_rate=voice->sample_mix_rate;
- }
-
- float freq_diff = Math::log(float(voice->mix_rate)/float(voice->sample_mix_rate))/Math::log(2.0);
- int detune = int(freq_diff*1200.0);
-
- /* clang-format off */
- EM_ASM_({
- if (_as_voices[$0] !== null) {
- _as_voices[$0].stop(); //stop and byebye
- }
- _as_voices[$0] = _as_audioctx.createBufferSource();
- _as_voices[$0].connect(_as_voice_gain[$0]);
- _as_voices[$0].buffer = _as_samples[$1];
- _as_voices[$0].loopStart.value = $1;
- _as_voices[$0].loopEnd.value = $2;
- _as_voices[$0].loop.value = $3;
- _as_voices[$0].detune.value = $6;
- _as_voice_pan[$0].pan.value = $4;
- _as_voice_gain[$0].gain.value = $5;
- _as_voices[$0].start();
- _as_voices[$0].onended = function() {
- _as_voices[$0].disconnect(_as_voice_gain[$0]);
- _as_voices[$0] = null;
- }
- }, voice->index, sample->index, sample->mix_rate * sample->loop_begin, sample->mix_rate * sample->loop_end, sample->loop_format != SAMPLE_LOOP_NONE, voice->pan, voice->volume * fx_volume_scale, detune);
- /* clang-format on */
-
- voice->active=true;
-}
-
-void AudioServerJavascript::voice_set_volume(RID p_voice, float p_volume){
-
- Voice* voice=voice_owner.get(p_voice);
- ERR_FAIL_COND(!voice);
-
- voice->volume=p_volume;
-
- if (voice->active) {
- /* clang-format off */
- EM_ASM_({
- _as_voice_gain[$0].gain.value = $1;
- }, voice->index, voice->volume * fx_volume_scale);
- /* clang-format on */
- }
-
-}
-void AudioServerJavascript::voice_set_pan(RID p_voice, float p_pan, float p_depth,float height){
-
- Voice* voice=voice_owner.get(p_voice);
- ERR_FAIL_COND(!voice);
-
- voice->pan=p_pan;
- voice->pan_depth=p_depth;
- voice->pan_height=height;
-
- if (voice->active) {
- /* clang-format off */
- EM_ASM_({
- _as_voice_pan[$0].pan.value = $1;
- }, voice->index, voice->pan);
- /* clang-format on */
- }
-}
-void AudioServerJavascript::voice_set_filter(RID p_voice, FilterType p_type, float p_cutoff, float p_resonance, float p_gain){
-
-}
-void AudioServerJavascript::voice_set_chorus(RID p_voice, float p_chorus ){
-
-}
-void AudioServerJavascript::voice_set_reverb(RID p_voice, ReverbRoomType p_room_type, float p_reverb){
-
-}
-void AudioServerJavascript::voice_set_mix_rate(RID p_voice, int p_mix_rate){
-
- Voice* voice=voice_owner.get(p_voice);
- ERR_FAIL_COND(!voice);
-
- voice->mix_rate=p_mix_rate;
-
- if (voice->active) {
-
- float freq_diff = Math::log(float(voice->mix_rate)/float(voice->sample_mix_rate))/Math::log(2.0);
- int detune = int(freq_diff*1200.0);
- /* clang-format off */
- EM_ASM_({
- _as_voices[$0].detune.value = $1;
- }, voice->index, detune);
- /* clang-format on */
- }
-}
-void AudioServerJavascript::voice_set_positional(RID p_voice, bool p_positional){
-
-}
-
-float AudioServerJavascript::voice_get_volume(RID p_voice) const{
-
- Voice* voice=voice_owner.get(p_voice);
- ERR_FAIL_COND_V(!voice,0);
-
- return voice->volume;
-}
-float AudioServerJavascript::voice_get_pan(RID p_voice) const{
-
- Voice* voice=voice_owner.get(p_voice);
- ERR_FAIL_COND_V(!voice,0);
-
- return voice->pan;
-}
-float AudioServerJavascript::voice_get_pan_depth(RID p_voice) const{
- Voice* voice=voice_owner.get(p_voice);
- ERR_FAIL_COND_V(!voice,0);
-
- return voice->pan_depth;
-}
-float AudioServerJavascript::voice_get_pan_height(RID p_voice) const{
-
- Voice* voice=voice_owner.get(p_voice);
- ERR_FAIL_COND_V(!voice,0);
-
- return voice->pan_height;
-}
-AudioServerJavascript::FilterType AudioServerJavascript::voice_get_filter_type(RID p_voice) const{
-
- return FILTER_NONE;
-}
-float AudioServerJavascript::voice_get_filter_cutoff(RID p_voice) const{
-
- return 0;
-}
-float AudioServerJavascript::voice_get_filter_resonance(RID p_voice) const{
-
- return 0;
-}
-float AudioServerJavascript::voice_get_chorus(RID p_voice) const{
-
- return 0;
-}
-AudioServerJavascript::ReverbRoomType AudioServerJavascript::voice_get_reverb_type(RID p_voice) const{
-
- return REVERB_SMALL;
-}
-float AudioServerJavascript::voice_get_reverb(RID p_voice) const{
-
- return 0;
-}
-
-int AudioServerJavascript::voice_get_mix_rate(RID p_voice) const{
-
- return 44100;
-}
-
-bool AudioServerJavascript::voice_is_positional(RID p_voice) const{
-
- return false;
-}
-
-void AudioServerJavascript::voice_stop(RID p_voice){
-
- Voice* voice=voice_owner.get(p_voice);
- ERR_FAIL_COND(!voice);
-
- if (voice->active) {
- /* clang-format off */
- EM_ASM_({
- if (_as_voices[$0] !== null) {
- _as_voices[$0].stop();
- _as_voices[$0].disconnect(_as_voice_gain[$0]);
- _as_voices[$0] = null;
- }
- }, voice->index);
- /* clang-format on */
-
- voice->active=false;
- }
-
-
-}
-bool AudioServerJavascript::voice_is_active(RID p_voice) const{
- Voice* voice=voice_owner.get(p_voice);
- ERR_FAIL_COND_V(!voice,false);
-
- return voice->active;
-}
-
-/* STREAM API */
-
-RID AudioServerJavascript::audio_stream_create(AudioStream *p_stream) {
-
-
- Stream *s = memnew(Stream);
- s->audio_stream=p_stream;
- s->event_stream=NULL;
- s->active=false;
- s->E=NULL;
- s->volume_scale=1.0;
- p_stream->set_mix_rate(webaudio_mix_rate);
-
- return stream_owner.make_rid(s);
-}
-
-RID AudioServerJavascript::event_stream_create(EventStream *p_stream) {
-
-
- Stream *s = memnew(Stream);
- s->audio_stream=NULL;
- s->event_stream=p_stream;
- s->active=false;
- s->E=NULL;
- s->volume_scale=1.0;
- //p_stream->set_mix_rate(AudioDriverJavascript::get_singleton()->get_mix_rate());
-
- return stream_owner.make_rid(s);
-
-
-}
-
-
-void AudioServerJavascript::stream_set_active(RID p_stream, bool p_active) {
-
-
- Stream *s = stream_owner.get(p_stream);
- ERR_FAIL_COND(!s);
-
- if (s->active==p_active)
- return;
-
- s->active=p_active;
- if (p_active)
- s->E=active_audio_streams.push_back(s);
- else {
- active_audio_streams.erase(s->E);
- s->E=NULL;
- }
-}
-
-bool AudioServerJavascript::stream_is_active(RID p_stream) const {
-
- Stream *s = stream_owner.get(p_stream);
- ERR_FAIL_COND_V(!s,false);
- return s->active;
-}
-
-void AudioServerJavascript::stream_set_volume_scale(RID p_stream, float p_scale) {
-
- Stream *s = stream_owner.get(p_stream);
- ERR_FAIL_COND(!s);
- s->volume_scale=p_scale;
-
-}
-
-float AudioServerJavascript::stream_set_volume_scale(RID p_stream) const {
-
- Stream *s = stream_owner.get(p_stream);
- ERR_FAIL_COND_V(!s,0);
- return s->volume_scale;
-
-}
-
-
-/* Audio Physics API */
-
-void AudioServerJavascript::free(RID p_id){
-
- if (voice_owner.owns(p_id)) {
- Voice* voice=voice_owner.get(p_id);
- ERR_FAIL_COND(!voice);
-
- if (voice->active) {
- /* clang-format off */
- EM_ASM_({
- if (_as_voices[$0] !== null) {
- _as_voices[$0].stop();
- _as_voices[$0].disconnect(_as_voice_gain[$0]);
- }
- }, voice->index);
- /* clang-format on */
- }
-
- /* clang-format off */
- EM_ASM_({
- delete _as_voices[$0];
- _as_voice_gain[$0].disconnect(_as_voice_pan[$0]);
- delete _as_voice_gain[$0];
- _as_voice_pan[$0].disconnect(_as_audioctx.destination);
- delete _as_voice_pan[$0];
- }, voice->index);
- /* clang-format on */
-
- voice_owner.free(p_id);
- memdelete(voice);
-
- } else if (sample_owner.owns(p_id)) {
-
- Sample *sample = sample_owner.get(p_id);
- ERR_FAIL_COND(!sample);
-
- /* clang-format off */
- EM_ASM_({
- delete _as_samples[$0];
- }, sample->index);
- /* clang-format on */
-
- sample_owner.free(p_id);
- memdelete(sample);
-
- } else if (stream_owner.owns(p_id)) {
-
-
- Stream *s=stream_owner.get(p_id);
-
- if (s->active) {
- stream_set_active(p_id,false);
- }
-
- memdelete(s);
- stream_owner.free(p_id);
- }
-}
-
-extern "C" {
-
-
-void audio_server_mix_function(int p_frames) {
-
- //print_line("MIXI! "+itos(p_frames));
- static_cast<AudioServerJavascript*>(AudioServerJavascript::get_singleton())->mix_to_js(p_frames);
-}
-
-}
-
-void AudioServerJavascript::mix_to_js(int p_frames) {
-
-
- //process in chunks to make sure to never process more than INTERNAL_BUFFER_SIZE
- int todo=p_frames;
- int offset=0;
-
- while(todo) {
-
- int tomix=MIN(todo,INTERNAL_BUFFER_SIZE);
- driver_process_chunk(tomix);
-
- /* clang-format off */
- EM_ASM_({
- var data = HEAPF32.subarray($0 / 4, $0 / 4 + $2 * 2);
-
- for (var channel = 0; channel < _as_output_buffer.numberOfChannels; channel++) {
- var outputData = _as_output_buffer.getChannelData(channel);
- // Loop through samples
- for (var sample = 0; sample < $2; sample++) {
- // make output equal to the same as the input
- outputData[sample + $1] = data[sample * 2 + channel];
- }
- }
- }, internal_buffer, offset, tomix);
- /* clang-format on */
-
- todo-=tomix;
- offset+=tomix;
- }
-}
-
-void AudioServerJavascript::init(){
-
- /*
- // clang-format off
- EM_ASM(
- console.log('server is ' + audio_server);
- );
- // clang-format on
- */
-
-
- //int latency = GLOBAL_DEF("javascript/audio_latency",16384);
-
- internal_buffer_channels=2;
- internal_buffer = memnew_arr(float,INTERNAL_BUFFER_SIZE*internal_buffer_channels);
- stream_buffer = memnew_arr(int32_t,INTERNAL_BUFFER_SIZE*4); //max 4 channels
-
- stream_volume=0.3;
-
- int buffer_latency=16384;
-
- /* clang-format off */
- EM_ASM_( {
- _as_script_node = _as_audioctx.createScriptProcessor($0, 0, 2);
- _as_script_node.connect(_as_audioctx.destination);
- console.log(_as_script_node.bufferSize);
-
- _as_script_node.onaudioprocess = function(audioProcessingEvent) {
- // The output buffer contains the samples that will be modified and played
- _as_output_buffer = audioProcessingEvent.outputBuffer;
- audio_server_mix_function(_as_output_buffer.getChannelData(0).length);
- }
- }, buffer_latency);
- /* clang-format on */
-
-
-}
-
-void AudioServerJavascript::finish(){
-
-}
-void AudioServerJavascript::update(){
-
- for(List<Stream*>::Element *E=active_audio_streams.front();E;) { //stream might be removed durnig this callback
-
- List<Stream*>::Element *N=E->next();
-
- if (E->get()->audio_stream)
- E->get()->audio_stream->update();
-
- E=N;
- }
-}
-
-/* MISC config */
-
-void AudioServerJavascript::lock(){
-
-}
-void AudioServerJavascript::unlock(){
-
-}
-int AudioServerJavascript::get_default_channel_count() const{
-
- return 1;
-}
-int AudioServerJavascript::get_default_mix_rate() const{
-
- return 44100;
-}
-
-void AudioServerJavascript::set_stream_global_volume_scale(float p_volume){
-
- stream_volume_scale=p_volume;
-}
-void AudioServerJavascript::set_fx_global_volume_scale(float p_volume){
-
- fx_volume_scale=p_volume;
-}
-void AudioServerJavascript::set_event_voice_global_volume_scale(float p_volume){
-
-}
-
-float AudioServerJavascript::get_stream_global_volume_scale() const{
- return 1;
-}
-float AudioServerJavascript::get_fx_global_volume_scale() const{
-
- return 1;
-}
-float AudioServerJavascript::get_event_voice_global_volume_scale() const{
-
- return 1;
-}
-
-uint32_t AudioServerJavascript::read_output_peak() const{
-
- return 0;
-}
-
-AudioServerJavascript *AudioServerJavascript::singleton=NULL;
-
-AudioServer *AudioServerJavascript::get_singleton() {
- return singleton;
-}
-
-double AudioServerJavascript::get_mix_time() const{
-
- return 0;
-}
-double AudioServerJavascript::get_output_delay() const {
-
- return 0;
-}
-
-
-void AudioServerJavascript::driver_process_chunk(int p_frames) {
-
-
-
- int samples=p_frames*internal_buffer_channels;
-
- for(int i=0;i<samples;i++) {
- internal_buffer[i]=0;
- }
-
-
- for(List<Stream*>::Element *E=active_audio_streams.front();E;E=E->next()) {
-
- ERR_CONTINUE(!E->get()->active); // bug?
-
-
- AudioStream *as=E->get()->audio_stream;
- if (!as)
- continue;
-
- int channels=as->get_channel_count();
- if (channels==0)
- continue; // does not want mix
- if (!as->mix(stream_buffer,p_frames))
- continue; //nothing was mixed!!
-
- int32_t stream_vol_scale=(stream_volume*stream_volume_scale*E->get()->volume_scale)*(1<<STREAM_SCALE_BITS);
-
-#define STRSCALE(m_val) ((((m_val >> STREAM_SCALE_BITS) * stream_vol_scale) >> 8) / 8388608.0)
- switch(channels) {
- case 1: {
-
- for(int i=0;i<p_frames;i++) {
-
- internal_buffer[(i<<1)+0]+=STRSCALE(stream_buffer[i]);
- internal_buffer[(i<<1)+1]+=STRSCALE(stream_buffer[i]);
- }
- } break;
- case 2: {
-
- for(int i=0;i<p_frames*2;i++) {
-
- internal_buffer[i]+=STRSCALE(stream_buffer[i]);
- }
- } break;
- case 4: {
-
- for(int i=0;i<p_frames;i++) {
-
- internal_buffer[(i<<2)+0]+=STRSCALE((stream_buffer[(i<<2)+0]+stream_buffer[(i<<2)+2])>>1);
- internal_buffer[(i<<2)+1]+=STRSCALE((stream_buffer[(i<<2)+1]+stream_buffer[(i<<2)+3])>>1);
- }
- } break;
-
-
- }
-
-#undef STRSCALE
- }
-}
-
-
-/*void AudioServerSW::driver_process(int p_frames,int32_t *p_buffer) {
-
-
- _output_delay=p_frames/double(AudioDriverSW::get_singleton()->get_mix_rate());
- //process in chunks to make sure to never process more than INTERNAL_BUFFER_SIZE
- int todo=p_frames;
- while(todo) {
-
- int tomix=MIN(todo,INTERNAL_BUFFER_SIZE);
- driver_process_chunk(tomix,p_buffer);
- p_buffer+=tomix;
- todo-=tomix;
- }
-
-
-}*/
-
-AudioServerJavascript::AudioServerJavascript() {
-
- singleton=this;
- sample_base=1;
- voice_base=1;
- /* clang-format off */
- EM_ASM(
- _as_samples = {};
- _as_voices = {};
- _as_voice_pan = {};
- _as_voice_gain = {};
-
- _as_audioctx = new (window.AudioContext || window.webkitAudioContext)();
-
- audio_server_mix_function = Module.cwrap('audio_server_mix_function', 'void', ['number']);
- );
- /* clang-format on */
-
- /* clang-format off */
- webaudio_mix_rate = EM_ASM_INT_V(
- return _as_audioctx.sampleRate;
- );
- /* clang-format on */
- print_line("WEBAUDIO MIX RATE: "+itos(webaudio_mix_rate));
- event_voice_scale=1.0;
- fx_volume_scale=1.0;
- stream_volume_scale=1.0;
-
-}
-#endif
diff --git a/platform/javascript/audio_server_javascript.h b/platform/javascript/audio_server_javascript.h
deleted file mode 100644
index 0773459f56..0000000000
--- a/platform/javascript/audio_server_javascript.h
+++ /dev/null
@@ -1,229 +0,0 @@
-/*************************************************************************/
-/* audio_server_javascript.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#ifndef AUDIO_SERVER_JAVASCRIPT_H
-#define AUDIO_SERVER_JAVASCRIPT_H
-
-// FIXME: Needs to be ported to the new AudioServer API in 3.0
-#if 0
-#include "servers/audio_server.h"
-
-class AudioServerJavascript : public AudioServer {
-
- GDCLASS(AudioServerJavascript,AudioServer);
-
- enum {
- INTERNAL_BUFFER_SIZE=4096,
- STREAM_SCALE_BITS=12
-
- };
-
- AudioMixer *get_mixer();
- void audio_mixer_chunk_callback(int p_frames);
-
- struct Sample {
- SampleFormat format;
- SampleLoopFormat loop_format;
- int loop_begin;
- int loop_end;
- int length;
- int index;
- int mix_rate;
- bool stereo;
-
- Vector<float> tmp_data;
- };
-
- mutable RID_Owner<Sample> sample_owner;
- int sample_base;
-
- struct Voice {
- int index;
- float volume;
- float pan;
- float pan_depth;
- float pan_height;
-
- float chorus;
- ReverbRoomType reverb_type;
- float reverb;
-
- int mix_rate;
- int sample_mix_rate;
- bool positional;
-
- bool active;
-
- };
-
- mutable RID_Owner<Voice> voice_owner;
-
- int voice_base;
-
- struct Stream {
- bool active;
- List<Stream*>::Element *E;
- AudioStream *audio_stream;
- EventStream *event_stream;
- float volume_scale;
- };
-
- List<Stream*> active_audio_streams;
-
- //List<Stream*> event_streams;
-
- float * internal_buffer;
- int internal_buffer_channels;
- int32_t * stream_buffer;
-
- mutable RID_Owner<Stream> stream_owner;
-
- float stream_volume;
- float stream_volume_scale;
-
- float event_voice_scale;
- float fx_volume_scale;
-
-
- void driver_process_chunk(int p_frames);
-
- int webaudio_mix_rate;
-
-
- static AudioServerJavascript *singleton;
-public:
-
- void mix_to_js(int p_frames);
- /* SAMPLE API */
-
- virtual RID sample_create(SampleFormat p_format, bool p_stereo, int p_length);
-
- virtual void sample_set_description(RID p_sample, const String& p_description);
- virtual String sample_get_description(RID p_sample) const;
-
- virtual SampleFormat sample_get_format(RID p_sample) const;
- virtual bool sample_is_stereo(RID p_sample) const;
- virtual int sample_get_length(RID p_sample) const;
- virtual const void* sample_get_data_ptr(RID p_sample) const;
-
-
- virtual void sample_set_data(RID p_sample, const PoolVector<uint8_t>& p_buffer);
- virtual PoolVector<uint8_t> sample_get_data(RID p_sample) const;
-
- virtual void sample_set_mix_rate(RID p_sample,int p_rate);
- virtual int sample_get_mix_rate(RID p_sample) const;
-
- virtual void sample_set_loop_format(RID p_sample,SampleLoopFormat p_format);
- virtual SampleLoopFormat sample_get_loop_format(RID p_sample) const;
-
- virtual void sample_set_loop_begin(RID p_sample,int p_pos);
- virtual int sample_get_loop_begin(RID p_sample) const;
-
- virtual void sample_set_loop_end(RID p_sample,int p_pos);
- virtual int sample_get_loop_end(RID p_sample) const;
-
-
- /* VOICE API */
-
- virtual RID voice_create();
-
- virtual void voice_play(RID p_voice, RID p_sample);
-
- virtual void voice_set_volume(RID p_voice, float p_volume);
- virtual void voice_set_pan(RID p_voice, float p_pan, float p_depth=0,float height=0); //pan and depth go from -1 to 1
- virtual void voice_set_filter(RID p_voice, FilterType p_type, float p_cutoff, float p_resonance, float p_gain=0);
- virtual void voice_set_chorus(RID p_voice, float p_chorus );
- virtual void voice_set_reverb(RID p_voice, ReverbRoomType p_room_type, float p_reverb);
- virtual void voice_set_mix_rate(RID p_voice, int p_mix_rate);
- virtual void voice_set_positional(RID p_voice, bool p_positional);
-
- virtual float voice_get_volume(RID p_voice) const;
- virtual float voice_get_pan(RID p_voice) const; //pan and depth go from -1 to 1
- virtual float voice_get_pan_depth(RID p_voice) const; //pan and depth go from -1 to 1
- virtual float voice_get_pan_height(RID p_voice) const; //pan and depth go from -1 to 1
- virtual FilterType voice_get_filter_type(RID p_voice) const;
- virtual float voice_get_filter_cutoff(RID p_voice) const;
- virtual float voice_get_filter_resonance(RID p_voice) const;
- virtual float voice_get_chorus(RID p_voice) const;
- virtual ReverbRoomType voice_get_reverb_type(RID p_voice) const;
- virtual float voice_get_reverb(RID p_voice) const;
-
- virtual int voice_get_mix_rate(RID p_voice) const;
- virtual bool voice_is_positional(RID p_voice) const;
-
- virtual void voice_stop(RID p_voice);
- virtual bool voice_is_active(RID p_voice) const;
-
- /* STREAM API */
-
- virtual RID audio_stream_create(AudioStream *p_stream);
- virtual RID event_stream_create(EventStream *p_stream);
-
- virtual void stream_set_active(RID p_stream, bool p_active);
- virtual bool stream_is_active(RID p_stream) const;
-
- virtual void stream_set_volume_scale(RID p_stream, float p_scale);
- virtual float stream_set_volume_scale(RID p_stream) const;
-
- /* Audio Physics API */
-
- virtual void free(RID p_id);
-
- virtual void init();
- virtual void finish();
- virtual void update();
-
- /* MISC config */
-
- virtual void lock();
- virtual void unlock();
- virtual int get_default_channel_count() const;
- virtual int get_default_mix_rate() const;
-
- virtual void set_stream_global_volume_scale(float p_volume);
- virtual void set_fx_global_volume_scale(float p_volume);
- virtual void set_event_voice_global_volume_scale(float p_volume);
-
- virtual float get_stream_global_volume_scale() const;
- virtual float get_fx_global_volume_scale() const;
- virtual float get_event_voice_global_volume_scale() const;
-
- virtual uint32_t read_output_peak() const;
-
- static AudioServer *get_singleton();
-
- virtual double get_mix_time() const; //useful for video -> audio sync
- virtual double get_output_delay() const;
-
-
- AudioServerJavascript();
-};
-
-#endif // AUDIO_SERVER_JAVASCRIPT_H
-#endif
diff --git a/platform/javascript/detect.py b/platform/javascript/detect.py
index cc29ad8956..8472c3ccab 100644
--- a/platform/javascript/detect.py
+++ b/platform/javascript/detect.py
@@ -13,13 +13,12 @@ def get_name():
def can_build():
- return ("EMSCRIPTEN_ROOT" in os.environ)
+ return ("EMSCRIPTEN_ROOT" in os.environ or "EMSCRIPTEN" in os.environ)
def get_opts():
from SCons.Variables import BoolVariable
return [
- BoolVariable('wasm', 'Compile to WebAssembly', False),
BoolVariable('javascript_eval', 'Enable JavaScript eval interface', True),
]
@@ -66,7 +65,10 @@ def configure(env):
## Compiler configuration
env['ENV'] = os.environ
- env.PrependENVPath('PATH', os.environ['EMSCRIPTEN_ROOT'])
+ if ("EMSCRIPTEN_ROOT" in os.environ):
+ env.PrependENVPath('PATH', os.environ['EMSCRIPTEN_ROOT'])
+ elif ("EMSCRIPTEN" in os.environ):
+ env.PrependENVPath('PATH', os.environ['EMSCRIPTEN'])
env['CC'] = 'emcc'
env['CXX'] = 'em++'
env['LINK'] = 'emcc'
@@ -100,20 +102,13 @@ def configure(env):
## Link flags
- env.Append(LINKFLAGS=['-s', 'EXTRA_EXPORTED_RUNTIME_METHODS="[\'FS\']"'])
+ env.Append(LINKFLAGS=['-s', 'BINARYEN=1'])
+ env.Append(LINKFLAGS=['-s', 'ALLOW_MEMORY_GROWTH=1'])
env.Append(LINKFLAGS=['-s', 'USE_WEBGL2=1'])
+ env.Append(LINKFLAGS=['-s', 'EXTRA_EXPORTED_RUNTIME_METHODS="[\'FS\']"'])
- if env['wasm']:
- env.Append(LINKFLAGS=['-s', 'BINARYEN=1'])
- # In contrast to asm.js, enabling memory growth on WebAssembly has no
- # major performance impact, and causes only a negligible increase in
- # memory size.
- env.Append(LINKFLAGS=['-s', 'ALLOW_MEMORY_GROWTH=1'])
- env.extra_suffix = '.webassembly' + env.extra_suffix
- else:
- env.Append(LINKFLAGS=['-s', 'ASM_JS=1'])
- env.Append(LINKFLAGS=['--separate-asm'])
- env.Append(LINKFLAGS=['--memory-init-file', '1'])
+ env.Append(LINKFLAGS=['-s', 'INVOKE_RUN=0'])
+ env.Append(LINKFLAGS=['-s', 'NO_EXIT_RUNTIME=1'])
# TODO: Move that to opus module's config
if 'module_opus_enabled' in env and env['module_opus_enabled']:
diff --git a/platform/javascript/engine.js b/platform/javascript/engine.js
index 99d1c20bbd..dc4bdc7efb 100644
--- a/platform/javascript/engine.js
+++ b/platform/javascript/engine.js
@@ -5,7 +5,6 @@
(function() {
var engine = Engine;
- var USING_WASM = engine.USING_WASM;
var DOWNLOAD_ATTEMPTS_MAX = 4;
var basePath = null;
@@ -32,87 +31,101 @@
this.rtenv = null;
- var gameInitPromise = null;
+ var initPromise = null;
var unloadAfterInit = true;
- var memorySize = 268435456;
+ var preloadedFiles = [];
+
+ var resizeCanvasOnStart = true;
var progressFunc = null;
- var pckProgressTracker = {};
+ var preloadProgressTracker = {};
var lastProgress = { loaded: 0, total: 0 };
var canvas = null;
+ var executableName = null;
+ var locale = null;
var stdout = null;
var stderr = null;
- this.initGame = function(mainPack) {
-
- if (!gameInitPromise) {
+ this.init = function(newBasePath) {
- if (mainPack === undefined) {
- if (basePath !== null) {
- mainPack = basePath + '.pck';
- } else {
- return Promise.reject(new Error("No main pack to load specified"));
- }
- }
- if (basePath === null)
- basePath = getBasePath(mainPack);
-
- gameInitPromise = Engine.initEngine().then(
+ if (!initPromise) {
+ initPromise = Engine.load(newBasePath).then(
instantiate.bind(this)
);
- var gameLoadPromise = loadPromise(mainPack, pckProgressTracker).then(function(xhr) { return xhr.response; });
- gameInitPromise = Promise.all([gameLoadPromise, gameInitPromise]).then(function(values) {
- // resolve with pck
- return new Uint8Array(values[0]);
- });
- if (unloadAfterInit)
- gameInitPromise.then(Engine.unloadEngine);
requestAnimationFrame(animateProgress);
+ if (unloadAfterInit)
+ initPromise.then(Engine.unloadEngine);
}
- return gameInitPromise;
+ return initPromise;
};
- function instantiate(initializer) {
+ function instantiate(wasmBuf) {
- var rtenvOpts = {
- noInitialRun: true,
- thisProgram: getBaseName(basePath),
+ var rtenvProps = {
engine: this,
+ ENV: {},
};
if (typeof stdout === 'function')
- rtenvOpts.print = stdout;
+ rtenvProps.print = stdout;
if (typeof stderr === 'function')
- rtenvOpts.printErr = stderr;
- if (typeof WebAssembly === 'object' && initializer instanceof ArrayBuffer) {
- rtenvOpts.instantiateWasm = function(imports, onSuccess) {
- WebAssembly.instantiate(initializer, imports).then(function(result) {
- onSuccess(result.instance);
- });
- return {};
- };
- } else if (initializer.asm && initializer.mem) {
- rtenvOpts.asm = initializer.asm;
- rtenvOpts.memoryInitializerRequest = initializer.mem;
- rtenvOpts.TOTAL_MEMORY = memorySize;
- } else {
- throw new Error("Invalid initializer");
- }
+ rtenvProps.printErr = stderr;
+ rtenvProps.instantiateWasm = function(imports, onSuccess) {
+ WebAssembly.instantiate(wasmBuf, imports).then(function(result) {
+ onSuccess(result.instance);
+ });
+ return {};
+ };
return new Promise(function(resolve, reject) {
- rtenvOpts.onRuntimeInitialized = resolve;
- rtenvOpts.onAbort = reject;
- rtenvOpts.engine.rtenv = Engine.RuntimeEnvironment(rtenvOpts);
+ rtenvProps.onRuntimeInitialized = resolve;
+ rtenvProps.onAbort = reject;
+ rtenvProps.engine.rtenv = Engine.RuntimeEnvironment(rtenvProps);
});
}
- this.start = function(mainPack) {
+ this.preloadFile = function(pathOrBuffer, bufferFilename) {
+
+ if (pathOrBuffer instanceof ArrayBuffer) {
+ pathOrBuffer = new Uint8Array(pathOrBuffer);
+ } else if (ArrayBuffer.isView(pathOrBuffer)) {
+ pathOrBuffer = new Uint8Array(pathOrBuffer.buffer);
+ }
+ if (pathOrBuffer instanceof Uint8Array) {
+ preloadedFiles.push({
+ name: bufferFilename,
+ buffer: pathOrBuffer
+ });
+ return Promise.resolve();
+ } else if (typeof pathOrBuffer === 'string') {
+ return loadPromise(pathOrBuffer, preloadProgressTracker).then(function(xhr) {
+ preloadedFiles.push({
+ name: pathOrBuffer,
+ buffer: xhr.response
+ });
+ });
+ } else {
+ throw Promise.reject("Invalid object for preloading");
+ }
+ };
+
+ this.start = function() {
+
+ return this.init().then(
+ Function.prototype.apply.bind(synchronousStart, this, arguments)
+ );
+ };
+
+ this.startGame = function(mainPack) {
- return this.initGame(mainPack).then(synchronousStart.bind(this));
+ executableName = getBaseName(mainPack);
+ return Promise.all([this.init(getBasePath(mainPack)), this.preloadFile(mainPack)]).then(
+ Function.prototype.apply.bind(synchronousStart, this, [])
+ );
};
- function synchronousStart(pckView) {
- // TODO don't expect canvas when runninng as cli tool
+ function synchronousStart() {
+
if (canvas instanceof HTMLCanvasElement) {
this.rtenv.canvas = canvas;
} else {
@@ -147,15 +160,33 @@
ev.preventDefault();
}, false);
- this.rtenv.FS.createDataFile('/', this.rtenv.thisProgram + '.pck', pckView, true, true, true);
- gameInitPromise = null;
- this.rtenv.callMain();
+ if (locale) {
+ this.rtenv.locale = locale;
+ } else {
+ this.rtenv.locale = navigator.languages ? navigator.languages[0] : navigator.language;
+ }
+ this.rtenv.locale = this.rtenv.locale.split('.')[0];
+ this.rtenv.resizeCanvasOnStart = resizeCanvasOnStart;
+
+ this.rtenv.thisProgram = executableName || getBaseName(basePath);
+
+ preloadedFiles.forEach(function(file) {
+ this.rtenv.FS.createDataFile('/', file.name, new Uint8Array(file.buffer), true, true, true);
+ }, this);
+
+ preloadedFiles = null;
+ initPromise = null;
+ this.rtenv.callMain(arguments);
}
this.setProgressFunc = function(func) {
progressFunc = func;
};
+ this.setResizeCanvasOnStart = function(enabled) {
+ resizeCanvasOnStart = enabled;
+ };
+
function animateProgress() {
var loaded = 0;
@@ -163,7 +194,7 @@
var totalIsValid = true;
var progressIsFinal = true;
- [loadingFiles, pckProgressTracker].forEach(function(tracker) {
+ [loadingFiles, preloadProgressTracker].forEach(function(tracker) {
Object.keys(tracker).forEach(function(file) {
if (!tracker[file].final)
progressIsFinal = false;
@@ -190,14 +221,20 @@
canvas = elem;
};
- this.setAsmjsMemorySize = function(size) {
- memorySize = size;
+ this.setExecutableName = function(newName) {
+
+ executableName = newName;
+ };
+
+ this.setLocale = function(newLocale) {
+
+ locale = newLocale;
};
this.setUnloadAfterInit = function(enabled) {
- if (enabled && !unloadAfterInit && gameInitPromise) {
- gameInitPromise.then(Engine.unloadEngine);
+ if (enabled && !unloadAfterInit && initPromise) {
+ initPromise.then(Engine.unloadEngine);
}
unloadAfterInit = enabled;
};
@@ -232,26 +269,16 @@
Engine.RuntimeEnvironment = engine.RuntimeEnvironment;
- Engine.initEngine = function(newBasePath) {
+ Engine.load = function(newBasePath) {
if (newBasePath !== undefined) basePath = getBasePath(newBasePath);
if (engineLoadPromise === null) {
- if (USING_WASM) {
- if (typeof WebAssembly !== 'object')
- return Promise.reject(new Error("Browser doesn't support WebAssembly"));
- // TODO cache/retrieve module to/from idb
- engineLoadPromise = loadPromise(basePath + '.wasm').then(function(xhr) {
- return xhr.response;
- });
- } else {
- var asmjsPromise = loadPromise(basePath + '.asm.js').then(function(xhr) {
- return asmjsModulePromise(xhr.response);
- });
- var memPromise = loadPromise(basePath + '.mem');
- engineLoadPromise = Promise.all([asmjsPromise, memPromise]).then(function(values) {
- return { asm: values[0], mem: values[1] };
- });
- }
+ if (typeof WebAssembly !== 'object')
+ return Promise.reject(new Error("Browser doesn't support WebAssembly"));
+ // TODO cache/retrieve module to/from idb
+ engineLoadPromise = loadPromise(basePath + '.wasm').then(function(xhr) {
+ return xhr.response;
+ });
engineLoadPromise = engineLoadPromise.catch(function(err) {
engineLoadPromise = null;
throw err;
@@ -260,34 +287,7 @@
return engineLoadPromise;
};
- function asmjsModulePromise(module) {
- var elem = document.createElement('script');
- var script = new Blob([
- 'Engine.asm = (function() { var Module = {};',
- module,
- 'return Module.asm; })();'
- ]);
- var url = URL.createObjectURL(script);
- elem.src = url;
- return new Promise(function(resolve, reject) {
- elem.addEventListener('load', function() {
- URL.revokeObjectURL(url);
- var asm = Engine.asm;
- Engine.asm = undefined;
- setTimeout(function() {
- // delay to reclaim compilation memory
- resolve(asm);
- }, 1);
- });
- elem.addEventListener('error', function() {
- URL.revokeObjectURL(url);
- reject("asm.js faiilure");
- });
- document.body.appendChild(elem);
- });
- }
-
- Engine.unloadEngine = function() {
+ Engine.unload = function() {
engineLoadPromise = null;
};
@@ -306,7 +306,7 @@
if (!file.endsWith('.js')) {
xhr.responseType = 'arraybuffer';
}
- ['loadstart', 'progress', 'load', 'error', 'timeout', 'abort'].forEach(function(ev) {
+ ['loadstart', 'progress', 'load', 'error', 'abort'].forEach(function(ev) {
xhr.addEventListener(ev, onXHREvent.bind(xhr, resolve, reject, file, tracker));
});
xhr.send();
@@ -321,7 +321,7 @@
this.abort();
return;
} else {
- loadXHR(resolve, reject, file);
+ setTimeout(loadXHR.bind(null, resolve, reject, file, tracker), 1000);
}
}
@@ -348,12 +348,11 @@
break;
case 'error':
- case 'timeout':
if (++tracker[file].attempts >= DOWNLOAD_ATTEMPTS_MAX) {
tracker[file].final = true;
reject(new Error("Failed loading file '" + file + "'"));
} else {
- loadXHR(resolve, reject, file);
+ setTimeout(loadXHR.bind(null, resolve, reject, file, tracker), 1000);
}
break;
diff --git a/platform/javascript/export/export.cpp b/platform/javascript/export/export.cpp
index 4a97bf4c32..05b0fb3fbc 100644
--- a/platform/javascript/export/export.cpp
+++ b/platform/javascript/export/export.cpp
@@ -30,13 +30,12 @@
#include "editor/editor_node.h"
#include "editor_export.h"
#include "io/zip_io.h"
+#include "main/splash.gen.h"
#include "platform/javascript/logo.gen.h"
#include "platform/javascript/run_icon.gen.h"
#define EXPORT_TEMPLATE_WEBASSEMBLY_RELEASE "webassembly_release.zip"
#define EXPORT_TEMPLATE_WEBASSEMBLY_DEBUG "webassembly_debug.zip"
-#define EXPORT_TEMPLATE_ASMJS_RELEASE "javascript_release.zip"
-#define EXPORT_TEMPLATE_ASMJS_DEBUG "javascript_debug.zip"
class EditorExportPlatformJavaScript : public EditorExportPlatform {
@@ -47,18 +46,11 @@ class EditorExportPlatformJavaScript : public EditorExportPlatform {
bool runnable_when_last_polled;
void _fix_html(Vector<uint8_t> &p_html, const Ref<EditorExportPreset> &p_preset, const String &p_name, bool p_debug);
- void _fix_fsloader_js(Vector<uint8_t> &p_js, const String &p_pack_name, uint64_t p_pack_size);
public:
- enum Target {
- TARGET_WEBASSEMBLY,
- TARGET_ASMJS
- };
-
virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features);
virtual void get_export_options(List<ExportOption> *r_options);
- virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const;
virtual String get_name() const;
virtual String get_os_name() const;
@@ -90,17 +82,9 @@ void EditorExportPlatformJavaScript::_fix_html(Vector<uint8_t> &p_html, const Re
String str_export;
Vector<String> lines = str_template.split("\n");
- int memory_mb;
- if (p_preset->get("options/target").operator int() != TARGET_ASMJS)
- // WebAssembly allows memory growth, so start with a reasonable default
- memory_mb = 1 << 4;
- else
- memory_mb = 1 << (p_preset->get("options/memory_size").operator int() + 5);
-
for (int i = 0; i < lines.size(); i++) {
String current_line = lines[i];
- current_line = current_line.replace("$GODOT_TOTAL_MEMORY", itos(memory_mb * 1024 * 1024));
current_line = current_line.replace("$GODOT_BASENAME", p_name);
current_line = current_line.replace("$GODOT_HEAD_INCLUDE", p_preset->get("html/head_include"));
current_line = current_line.replace("$GODOT_DEBUG_ENABLED", p_debug ? "true" : "false");
@@ -129,24 +113,15 @@ void EditorExportPlatformJavaScript::get_preset_features(const Ref<EditorExportP
void EditorExportPlatformJavaScript::get_export_options(List<ExportOption> *r_options) {
- r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "options/target", PROPERTY_HINT_ENUM, "WebAssembly,asm.js"), TARGET_WEBASSEMBLY));
- r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "options/memory_size", PROPERTY_HINT_ENUM, "32 MB,64 MB,128 MB,256 MB,512 MB,1 GB"), 3));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/s3tc"), false));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/etc"), true));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/etc2"), false));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "html/custom_html_shell", PROPERTY_HINT_GLOBAL_FILE, "html"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "html/head_include", PROPERTY_HINT_MULTILINE_TEXT), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/release", PROPERTY_HINT_GLOBAL_FILE, "zip"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/debug", PROPERTY_HINT_GLOBAL_FILE, "zip"), ""));
}
-bool EditorExportPlatformJavaScript::get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const {
-
- if (p_option == "options/memory_size") {
- return p_options["options/target"].operator int() == TARGET_ASMJS;
- }
- return true;
-}
-
String EditorExportPlatformJavaScript::get_name() const {
return "HTML5";
@@ -166,17 +141,10 @@ bool EditorExportPlatformJavaScript::can_export(const Ref<EditorExportPreset> &p
r_missing_templates = false;
- if (p_preset->get("options/target").operator int() == TARGET_WEBASSEMBLY) {
- if (find_export_template(EXPORT_TEMPLATE_WEBASSEMBLY_RELEASE) == String())
- r_missing_templates = true;
- else if (find_export_template(EXPORT_TEMPLATE_WEBASSEMBLY_DEBUG) == String())
- r_missing_templates = true;
- } else {
- if (find_export_template(EXPORT_TEMPLATE_ASMJS_RELEASE) == String())
- r_missing_templates = true;
- else if (find_export_template(EXPORT_TEMPLATE_ASMJS_DEBUG) == String())
- r_missing_templates = true;
- }
+ if (find_export_template(EXPORT_TEMPLATE_WEBASSEMBLY_RELEASE) == String())
+ r_missing_templates = true;
+ else if (find_export_template(EXPORT_TEMPLATE_WEBASSEMBLY_DEBUG) == String())
+ r_missing_templates = true;
return !r_missing_templates;
}
@@ -187,9 +155,11 @@ String EditorExportPlatformJavaScript::get_binary_extension() const {
}
Error EditorExportPlatformJavaScript::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
+ ExportNotifier notifier(*this, p_preset, p_debug, p_path, p_flags);
String custom_debug = p_preset->get("custom_template/debug");
String custom_release = p_preset->get("custom_template/release");
+ String custom_html = p_preset->get("html/custom_html_shell");
String template_path = p_debug ? custom_debug : custom_release;
@@ -197,17 +167,10 @@ Error EditorExportPlatformJavaScript::export_project(const Ref<EditorExportPrese
if (template_path == String()) {
- if (p_preset->get("options/target").operator int() == TARGET_WEBASSEMBLY) {
- if (p_debug)
- template_path = find_export_template(EXPORT_TEMPLATE_WEBASSEMBLY_DEBUG);
- else
- template_path = find_export_template(EXPORT_TEMPLATE_WEBASSEMBLY_RELEASE);
- } else {
- if (p_debug)
- template_path = find_export_template(EXPORT_TEMPLATE_ASMJS_DEBUG);
- else
- template_path = find_export_template(EXPORT_TEMPLATE_ASMJS_RELEASE);
- }
+ if (p_debug)
+ template_path = find_export_template(EXPORT_TEMPLATE_WEBASSEMBLY_DEBUG);
+ else
+ template_path = find_export_template(EXPORT_TEMPLATE_WEBASSEMBLY_RELEASE);
}
if (template_path != String() && !FileAccess::exists(template_path)) {
@@ -222,14 +185,6 @@ Error EditorExportPlatformJavaScript::export_project(const Ref<EditorExportPrese
return error;
}
- FileAccess *f = FileAccess::open(pck_path, FileAccess::READ);
- if (!f) {
- EditorNode::get_singleton()->show_warning(TTR("Could not read file:\n") + pck_path);
- return ERR_FILE_CANT_READ;
- }
- size_t pack_size = f->get_len();
- memdelete(f);
-
FileAccess *src_f = NULL;
zlib_filefunc_def io = zipio_create_io_from_file(&src_f);
unzFile pkg = unzOpen2(template_path.utf8().get_data(), &io);
@@ -240,13 +195,17 @@ Error EditorExportPlatformJavaScript::export_project(const Ref<EditorExportPrese
return ERR_FILE_NOT_FOUND;
}
- int ret = unzGoToFirstFile(pkg);
- while (ret == UNZ_OK) {
+ if (unzGoToFirstFile(pkg) != UNZ_OK) {
+ EditorNode::get_singleton()->show_warning(TTR("Invalid export template:\n") + template_path);
+ unzClose(pkg);
+ return ERR_FILE_CORRUPT;
+ }
+ do {
//get filename
unz_file_info info;
char fname[16384];
- ret = unzGetCurrentFileInfo(pkg, &info, fname, 16384, NULL, 0, NULL, 0);
+ unzGetCurrentFileInfo(pkg, &info, fname, 16384, NULL, 0, NULL, 0);
String file = fname;
@@ -262,20 +221,18 @@ Error EditorExportPlatformJavaScript::export_project(const Ref<EditorExportPrese
if (file == "godot.html") {
+ if (!custom_html.empty()) {
+ continue;
+ }
_fix_html(data, p_preset, p_path.get_file().get_basename(), p_debug);
file = p_path.get_file();
+
} else if (file == "godot.js") {
file = p_path.get_file().get_basename() + ".js";
} else if (file == "godot.wasm") {
file = p_path.get_file().get_basename() + ".wasm";
- } else if (file == "godot.asm.js") {
-
- file = p_path.get_file().get_basename() + ".asm.js";
- } else if (file == "godot.mem") {
-
- file = p_path.get_file().get_basename() + ".mem";
}
String dst = p_path.get_base_dir().plus_file(file);
@@ -288,9 +245,50 @@ Error EditorExportPlatformJavaScript::export_project(const Ref<EditorExportPrese
f->store_buffer(data.ptr(), data.size());
memdelete(f);
- ret = unzGoToNextFile(pkg);
+ } while (unzGoToNextFile(pkg) == UNZ_OK);
+ unzClose(pkg);
+
+ if (!custom_html.empty()) {
+
+ FileAccess *f = FileAccess::open(custom_html, FileAccess::READ);
+ if (!f) {
+ EditorNode::get_singleton()->show_warning(TTR("Could not read custom HTML shell:\n") + custom_html);
+ return ERR_FILE_CANT_READ;
+ }
+ Vector<uint8_t> buf;
+ buf.resize(f->get_len());
+ f->get_buffer(buf.ptr(), buf.size());
+ memdelete(f);
+ _fix_html(buf, p_preset, p_path.get_file().get_basename(), p_debug);
+
+ f = FileAccess::open(p_path, FileAccess::WRITE);
+ if (!f) {
+ EditorNode::get_singleton()->show_warning(TTR("Could not write file:\n") + p_path);
+ return ERR_FILE_CANT_WRITE;
+ }
+ f->store_buffer(buf.ptr(), buf.size());
+ memdelete(f);
}
+ Ref<Image> splash;
+ String splash_path = GLOBAL_GET("application/boot_splash/image");
+ splash_path = splash_path.strip_edges();
+ if (!splash_path.empty()) {
+ splash.instance();
+ Error err = splash->load(splash_path);
+ if (err) {
+ EditorNode::get_singleton()->show_warning(TTR("Could not read boot splash image file:\n") + splash_path + "\nUsing default boot splash image");
+ splash.unref();
+ }
+ }
+ if (splash.is_null()) {
+ splash = Ref<Image>(memnew(Image(boot_splash_png)));
+ }
+ String png_path = p_path.get_base_dir().plus_file(p_path.get_file().get_basename() + ".png");
+ if (splash->save_png(png_path) != OK) {
+ EditorNode::get_singleton()->show_warning(TTR("Could not write file:\n") + png_path);
+ return ERR_FILE_CANT_WRITE;
+ }
return OK;
}
@@ -319,7 +317,7 @@ int EditorExportPlatformJavaScript::get_device_count() const {
Error EditorExportPlatformJavaScript::run(const Ref<EditorExportPreset> &p_preset, int p_device, int p_debug_flags) {
- String path = EditorSettings::get_singleton()->get_settings_path() + "/tmp/tmp_export.html";
+ String path = EditorSettings::get_singleton()->get_cache_dir().plus_file("tmp_export.html");
Error err = export_project(p_preset, true, path, p_debug_flags);
if (err) {
return err;
diff --git a/platform/javascript/http_client.h.inc b/platform/javascript/http_client.h.inc
new file mode 100644
index 0000000000..9e4edf7848
--- /dev/null
+++ b/platform/javascript/http_client.h.inc
@@ -0,0 +1,48 @@
+/*************************************************************************/
+/* http_client.h.inc */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 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. */
+/*************************************************************************/
+
+// HTTPClient's additional private members in the javascript platform
+
+Error prepare_request(Method p_method, const String &p_url, const Vector<String> &p_headers);
+
+int xhr_id;
+int read_limit;
+int response_read_offset;
+Status status;
+
+String host;
+int port;
+bool use_tls;
+String username;
+String password;
+
+int polled_response_code;
+String polled_response_header;
+PoolByteArray polled_response;
diff --git a/platform/javascript/http_client_javascript.cpp b/platform/javascript/http_client_javascript.cpp
new file mode 100644
index 0000000000..0b105dcb40
--- /dev/null
+++ b/platform/javascript/http_client_javascript.cpp
@@ -0,0 +1,282 @@
+/*************************************************************************/
+/* http_client_javascript.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#include "http_request.h"
+#include "io/http_client.h"
+
+Error HTTPClient::connect_to_host(const String &p_host, int p_port, bool p_ssl, bool p_verify_host) {
+
+ close();
+ if (p_ssl && !p_verify_host) {
+ WARN_PRINT("Disabling HTTPClient's host verification is not supported for the HTML5 platform, host will be verified");
+ }
+
+ host = p_host;
+ if (host.begins_with("http://")) {
+ host.replace_first("http://", "");
+ } else if (host.begins_with("https://")) {
+ host.replace_first("https://", "");
+ }
+
+ status = host.is_valid_ip_address() ? STATUS_CONNECTING : STATUS_RESOLVING;
+ port = p_port;
+ use_tls = p_ssl;
+ return OK;
+}
+
+void HTTPClient::set_connection(const Ref<StreamPeer> &p_connection) {
+
+ ERR_EXPLAIN("Accessing an HTTPClient's StreamPeer is not supported for the HTML5 platform");
+ ERR_FAIL();
+}
+
+Ref<StreamPeer> HTTPClient::get_connection() const {
+
+ ERR_EXPLAIN("Accessing an HTTPClient's StreamPeer is not supported for the HTML5 platform");
+ ERR_FAIL_V(REF());
+}
+
+Error HTTPClient::prepare_request(Method p_method, const String &p_url, const Vector<String> &p_headers) {
+
+ ERR_FAIL_INDEX_V(p_method, METHOD_MAX, ERR_INVALID_PARAMETER);
+ ERR_FAIL_COND_V(status != STATUS_CONNECTED, ERR_INVALID_PARAMETER);
+ ERR_FAIL_COND_V(host.empty(), ERR_UNCONFIGURED);
+ ERR_FAIL_COND_V(port < 0, ERR_UNCONFIGURED);
+
+ static const char *_methods[HTTPClient::METHOD_MAX] = {
+ "GET",
+ "HEAD",
+ "POST",
+ "PUT",
+ "DELETE",
+ "OPTIONS",
+ "TRACE",
+ "CONNECT"
+ };
+
+ String url = (use_tls ? "https://" : "http://") + host + ":" + itos(port) + "/" + p_url;
+ godot_xhr_reset(xhr_id);
+ godot_xhr_open(xhr_id, _methods[p_method], url.utf8().get_data(),
+ username.empty() ? NULL : username.utf8().get_data(),
+ password.empty() ? NULL : password.utf8().get_data());
+
+ for (int i = 0; i < p_headers.size(); i++) {
+ int header_separator = p_headers[i].find(": ");
+ ERR_FAIL_COND_V(header_separator < 0, ERR_INVALID_PARAMETER);
+ godot_xhr_set_request_header(xhr_id,
+ p_headers[i].left(header_separator).utf8().get_data(),
+ p_headers[i].right(header_separator + 2).utf8().get_data());
+ }
+ response_read_offset = 0;
+ status = STATUS_REQUESTING;
+ return OK;
+}
+
+Error HTTPClient::request_raw(Method p_method, const String &p_url, const Vector<String> &p_headers, const PoolVector<uint8_t> &p_body) {
+
+ Error err = prepare_request(p_method, p_url, p_headers);
+ if (err != OK)
+ return err;
+ PoolByteArray::Read read = p_body.read();
+ godot_xhr_send_data(xhr_id, read.ptr(), p_body.size());
+ return OK;
+}
+
+Error HTTPClient::request(Method p_method, const String &p_url, const Vector<String> &p_headers, const String &p_body) {
+
+ Error err = prepare_request(p_method, p_url, p_headers);
+ if (err != OK)
+ return err;
+ godot_xhr_send_string(xhr_id, p_body.utf8().get_data());
+ return OK;
+}
+
+void HTTPClient::close() {
+
+ host = "";
+ port = -1;
+ use_tls = false;
+ status = STATUS_DISCONNECTED;
+ polled_response.resize(0);
+ polled_response_code = 0;
+ polled_response_header = String();
+ godot_xhr_reset(xhr_id);
+}
+
+HTTPClient::Status HTTPClient::get_status() const {
+
+ return status;
+}
+
+bool HTTPClient::has_response() const {
+
+ return !polled_response_header.empty();
+}
+
+bool HTTPClient::is_response_chunked() const {
+
+ // TODO evaluate using moz-chunked-arraybuffer, fetch & ReadableStream
+ return false;
+}
+
+int HTTPClient::get_response_code() const {
+
+ return polled_response_code;
+}
+
+Error HTTPClient::get_response_headers(List<String> *r_response) {
+
+ if (!polled_response_header.size())
+ return ERR_INVALID_PARAMETER;
+
+ Vector<String> header_lines = polled_response_header.split("\r\n", false);
+ for (int i = 0; i < header_lines.size(); ++i) {
+ r_response->push_back(header_lines[i]);
+ }
+ polled_response_header = String();
+ return OK;
+}
+
+int HTTPClient::get_response_body_length() const {
+
+ return polled_response.size();
+}
+
+PoolByteArray HTTPClient::read_response_body_chunk() {
+
+ ERR_FAIL_COND_V(status != STATUS_BODY, PoolByteArray());
+
+ int to_read = MIN(read_limit, polled_response.size() - response_read_offset);
+ PoolByteArray chunk;
+ chunk.resize(to_read);
+ PoolByteArray::Write write = chunk.write();
+ PoolByteArray::Read read = polled_response.read();
+ memcpy(write.ptr(), read.ptr() + response_read_offset, to_read);
+ write = PoolByteArray::Write();
+ read = PoolByteArray::Read();
+ response_read_offset += to_read;
+
+ if (response_read_offset == polled_response.size()) {
+ status = STATUS_CONNECTED;
+ polled_response.resize(0);
+ polled_response_code = 0;
+ polled_response_header = String();
+ godot_xhr_reset(xhr_id);
+ }
+
+ return chunk;
+}
+
+void HTTPClient::set_blocking_mode(bool p_enable) {
+
+ ERR_EXPLAIN("HTTPClient blocking mode is not supported for the HTML5 platform");
+ ERR_FAIL_COND(p_enable);
+}
+
+bool HTTPClient::is_blocking_mode_enabled() const {
+
+ return false;
+}
+
+void HTTPClient::set_read_chunk_size(int p_size) {
+
+ read_limit = p_size;
+}
+
+Error HTTPClient::poll() {
+
+ switch (status) {
+
+ case STATUS_DISCONNECTED:
+ return ERR_UNCONFIGURED;
+
+ case STATUS_RESOLVING:
+ status = STATUS_CONNECTING;
+ return OK;
+
+ case STATUS_CONNECTING:
+ status = STATUS_CONNECTED;
+ return OK;
+
+ case STATUS_CONNECTED:
+ case STATUS_BODY:
+ return OK;
+
+ case STATUS_CONNECTION_ERROR:
+ return ERR_CONNECTION_ERROR;
+
+ case STATUS_REQUESTING:
+ polled_response_code = godot_xhr_get_status(xhr_id);
+ int response_length = godot_xhr_get_response_length(xhr_id);
+ if (response_length == 0) {
+ godot_xhr_ready_state_t ready_state = godot_xhr_get_ready_state(xhr_id);
+ if (ready_state == XHR_READY_STATE_HEADERS_RECEIVED || ready_state == XHR_READY_STATE_LOADING) {
+ return OK;
+ } else {
+ status = STATUS_CONNECTION_ERROR;
+ return ERR_CONNECTION_ERROR;
+ }
+ }
+
+ status = STATUS_BODY;
+
+ PoolByteArray bytes;
+ int len = godot_xhr_get_response_headers_length(xhr_id);
+ bytes.resize(len);
+ PoolByteArray::Write write = bytes.write();
+ godot_xhr_get_response_headers(xhr_id, reinterpret_cast<char *>(write.ptr()), len);
+ write = PoolByteArray::Write();
+
+ PoolByteArray::Read read = bytes.read();
+ polled_response_header = String::utf8(reinterpret_cast<const char *>(read.ptr()));
+ read = PoolByteArray::Read();
+
+ polled_response.resize(response_length);
+ write = polled_response.write();
+ godot_xhr_get_response(xhr_id, write.ptr(), response_length);
+ write = PoolByteArray::Write();
+ break;
+ }
+ return OK;
+}
+
+HTTPClient::HTTPClient() {
+
+ xhr_id = godot_xhr_new();
+ read_limit = 4096;
+ status = STATUS_DISCONNECTED;
+ port = -1;
+ use_tls = false;
+ polled_response_code = 0;
+}
+
+HTTPClient::~HTTPClient() {
+
+ godot_xhr_free(xhr_id);
+}
diff --git a/platform/javascript/http_request.h b/platform/javascript/http_request.h
new file mode 100644
index 0000000000..06d9239004
--- /dev/null
+++ b/platform/javascript/http_request.h
@@ -0,0 +1,74 @@
+/*************************************************************************/
+/* http_request.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#ifndef HTTP_REQUEST_H
+#define HTTP_REQUEST_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "stddef.h"
+
+typedef enum {
+ XHR_READY_STATE_UNSENT = 0,
+ XHR_READY_STATE_OPENED = 1,
+ XHR_READY_STATE_HEADERS_RECEIVED = 2,
+ XHR_READY_STATE_LOADING = 3,
+ XHR_READY_STATE_DONE = 4,
+} godot_xhr_ready_state_t;
+
+extern int godot_xhr_new();
+extern void godot_xhr_reset(int p_xhr_id);
+extern bool godot_xhr_free(int p_xhr_id);
+
+extern int godot_xhr_open(int p_xhr_id, const char *p_method, const char *p_url, const char *p_user = NULL, const char *p_password = NULL);
+
+extern void godot_xhr_set_request_header(int p_xhr_id, const char *p_header, const char *p_value);
+
+extern void godot_xhr_send_null(int p_xhr_id);
+extern void godot_xhr_send_string(int p_xhr_id, const char *p_data);
+extern void godot_xhr_send_data(int p_xhr_id, const void *p_data, int p_len);
+extern void godot_xhr_abort(int p_xhr_id);
+
+/* this is an HTTPClient::ResponseCode, not ::Status */
+extern int godot_xhr_get_status(int p_xhr_id);
+extern godot_xhr_ready_state_t godot_xhr_get_ready_state(int p_xhr_id);
+
+extern int godot_xhr_get_response_headers_length(int p_xhr_id);
+extern void godot_xhr_get_response_headers(int p_xhr_id, char *r_dst, int p_len);
+
+extern int godot_xhr_get_response_length(int p_xhr_id);
+extern void godot_xhr_get_response(int p_xhr_id, void *r_dst, int p_len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HTTP_REQUEST_H */
diff --git a/platform/javascript/http_request.js b/platform/javascript/http_request.js
new file mode 100644
index 0000000000..f30240b41b
--- /dev/null
+++ b/platform/javascript/http_request.js
@@ -0,0 +1,145 @@
+/*************************************************************************/
+/* http_request.js */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* */
+/* 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. */
+/*************************************************************************/
+var GodotHTTPRequest = {
+
+ $GodotHTTPRequest: {
+
+ requests: [],
+
+ getUnusedRequestId: function() {
+ var idMax = GodotHTTPRequest.requests.length;
+ for (var potentialId = 0; potentialId < idMax; ++potentialId) {
+ if (GodotHTTPRequest.requests[potentialId] instanceof XMLHttpRequest) {
+ continue;
+ }
+ return potentialId;
+ }
+ GodotHTTPRequest.requests.push(null)
+ return idMax;
+ },
+
+ setupRequest: function(xhr) {
+ xhr.responseType = 'arraybuffer';
+ },
+ },
+
+ godot_xhr_new: function() {
+ var newId = GodotHTTPRequest.getUnusedRequestId();
+ GodotHTTPRequest.requests[newId] = new XMLHttpRequest;
+ GodotHTTPRequest.setupRequest(GodotHTTPRequest.requests[newId]);
+ return newId;
+ },
+
+ godot_xhr_reset: function(xhrId) {
+ GodotHTTPRequest.requests[xhrId] = new XMLHttpRequest;
+ GodotHTTPRequest.setupRequest(GodotHTTPRequest.requests[xhrId]);
+ },
+
+ godot_xhr_free: function(xhrId) {
+ GodotHTTPRequest.requests[xhrId].abort();
+ GodotHTTPRequest.requests[xhrId] = null;
+ },
+
+ godot_xhr_open: function(xhrId, method, url, user, password) {
+ user = user > 0 ? UTF8ToString(user) : null;
+ password = password > 0 ? UTF8ToString(password) : null;
+ GodotHTTPRequest.requests[xhrId].open(UTF8ToString(method), UTF8ToString(url), true, user, password);
+ },
+
+ godot_xhr_set_request_header: function(xhrId, header, value) {
+ GodotHTTPRequest.requests[xhrId].setRequestHeader(UTF8ToString(header), UTF8ToString(value));
+ },
+
+ godot_xhr_send_null: function(xhrId) {
+ GodotHTTPRequest.requests[xhrId].send();
+ },
+
+ godot_xhr_send_string: function(xhrId, strPtr) {
+ if (!strPtr) {
+ Module.printErr("Failed to send string per XHR: null pointer");
+ return;
+ }
+ GodotHTTPRequest.requests[xhrId].send(UTF8ToString(strPtr));
+ },
+
+ godot_xhr_send_data: function(xhrId, ptr, len) {
+ if (!ptr) {
+ Module.printErr("Failed to send data per XHR: null pointer");
+ return;
+ }
+ if (len < 0) {
+ Module.printErr("Failed to send data per XHR: buffer length less than 0");
+ return;
+ }
+ GodotHTTPRequest.requests[xhrId].send(HEAPU8.subarray(ptr, ptr + len));
+ },
+
+ godot_xhr_abort: function(xhrId) {
+ GodotHTTPRequest.requests[xhrId].abort();
+ },
+
+ godot_xhr_get_status: function(xhrId) {
+ return GodotHTTPRequest.requests[xhrId].status;
+ },
+
+ godot_xhr_get_ready_state: function(xhrId) {
+ return GodotHTTPRequest.requests[xhrId].readyState;
+ },
+
+ godot_xhr_get_response_headers_length: function(xhrId) {
+ var headers = GodotHTTPRequest.requests[xhrId].getAllResponseHeaders();
+ return headers === null ? 0 : lengthBytesUTF8(headers);
+ },
+
+ godot_xhr_get_response_headers: function(xhrId, dst, len) {
+ var str = GodotHTTPRequest.requests[xhrId].getAllResponseHeaders();
+ if (str === null)
+ return;
+ var buf = new Uint8Array(len + 1);
+ stringToUTF8Array(str, buf, 0, buf.length);
+ buf = buf.subarray(0, -1);
+ HEAPU8.set(buf, dst);
+ },
+
+ godot_xhr_get_response_length: function(xhrId) {
+ var body = GodotHTTPRequest.requests[xhrId].response;
+ return body === null ? 0 : body.byteLength;
+ },
+
+ godot_xhr_get_response: function(xhrId, dst, len) {
+ var buf = GodotHTTPRequest.requests[xhrId].response;
+ if (buf === null)
+ return;
+ buf = new Uint8Array(buf).subarray(0, len);
+ HEAPU8.set(buf, dst);
+ },
+};
+
+autoAddDeps(GodotHTTPRequest, "$GodotHTTPRequest");
+mergeInto(LibraryManager.library, GodotHTTPRequest);
diff --git a/platform/javascript/javascript_eval.cpp b/platform/javascript/javascript_eval.cpp
index 74f8d80a76..a755dcb5c4 100644
--- a/platform/javascript/javascript_eval.cpp
+++ b/platform/javascript/javascript_eval.cpp
@@ -29,34 +29,44 @@
/*************************************************************************/
#ifdef JAVASCRIPT_EVAL_ENABLED
-#include "javascript_eval.h"
+#include "api/javascript_eval.h"
#include "emscripten.h"
-JavaScript *JavaScript::singleton = NULL;
+extern "C" EMSCRIPTEN_KEEPALIVE uint8_t *resize_poolbytearray_and_open_write(PoolByteArray *p_arr, PoolByteArray::Write *r_write, int p_len) {
-JavaScript *JavaScript::get_singleton() {
-
- return singleton;
+ p_arr->resize(p_len);
+ *r_write = p_arr->write();
+ return r_write->ptr();
}
Variant JavaScript::eval(const String &p_code, bool p_use_global_exec_context) {
union {
- int i;
+ bool b;
double d;
char *s;
} js_data[4];
+
+ PoolByteArray arr;
+ PoolByteArray::Write arr_write;
+
/* clang-format off */
Variant::Type return_type = static_cast<Variant::Type>(EM_ASM_INT({
+ const CODE = $0;
+ const USE_GLOBAL_EXEC_CONTEXT = $1;
+ const PTR = $2;
+ const ELEM_LEN = $3;
+ const BYTEARRAY_PTR = $4;
+ const BYTEARRAY_WRITE_PTR = $5;
var eval_ret;
try {
- if ($3) { // p_use_global_exec_context
+ if (USE_GLOBAL_EXEC_CONTEXT) {
// indirect eval call grants global execution context
var global_eval = eval;
- eval_ret = global_eval(UTF8ToString($2));
+ eval_ret = global_eval(UTF8ToString(CODE));
} else {
- eval_ret = eval(UTF8ToString($2));
+ eval_ret = eval(UTF8ToString(CODE));
}
} catch (e) {
Module.printErr(e);
@@ -66,16 +76,11 @@ Variant JavaScript::eval(const String &p_code, bool p_use_global_exec_context) {
switch (typeof eval_ret) {
case 'boolean':
- // bitwise op yields 32-bit int
- setValue($0, eval_ret|0, 'i32');
+ setValue(PTR, eval_ret, 'i32');
return 1; // BOOL
case 'number':
- if ((eval_ret|0)===eval_ret) {
- setValue($0, eval_ret|0, 'i32');
- return 2; // INT
- }
- setValue($0, eval_ret, 'double');
+ setValue(PTR, eval_ret, 'double');
return 3; // REAL
case 'string':
@@ -85,7 +90,7 @@ Variant JavaScript::eval(const String &p_code, bool p_use_global_exec_context) {
if (array_ptr===0) {
throw new Error('String allocation failed (probably out of memory)');
}
- setValue($0, array_ptr|0 , '*');
+ setValue(PTR, array_ptr , '*');
stringToUTF8(eval_ret, array_ptr, array_len);
return 4; // STRING
} catch (e) {
@@ -102,41 +107,50 @@ Variant JavaScript::eval(const String &p_code, bool p_use_global_exec_context) {
break;
}
- else if (typeof eval_ret.x==='number' && typeof eval_ret.y==='number') {
- setValue($0, eval_ret.x, 'double');
- setValue($0+$1, eval_ret.y, 'double');
+ if (ArrayBuffer.isView(eval_ret) && !(eval_ret instanceof Uint8Array)) {
+ eval_ret = new Uint8Array(eval_ret.buffer);
+ }
+ else if (eval_ret instanceof ArrayBuffer) {
+ eval_ret = new Uint8Array(eval_ret);
+ }
+ if (eval_ret instanceof Uint8Array) {
+ var bytes_ptr = ccall('resize_poolbytearray_and_open_write', 'number', ['number', 'number' ,'number'], [BYTEARRAY_PTR, BYTEARRAY_WRITE_PTR, eval_ret.length]);
+ HEAPU8.set(eval_ret, bytes_ptr);
+ return 20; // POOL_BYTE_ARRAY
+ }
+
+ if (typeof eval_ret.x==='number' && typeof eval_ret.y==='number') {
+ setValue(PTR, eval_ret.x, 'double');
+ setValue(PTR + ELEM_LEN, eval_ret.y, 'double');
if (typeof eval_ret.z==='number') {
- setValue($0+$1*2, eval_ret.z, 'double');
+ setValue(PTR + ELEM_LEN*2, eval_ret.z, 'double');
return 7; // VECTOR3
}
else if (typeof eval_ret.width==='number' && typeof eval_ret.height==='number') {
- setValue($0+$1*2, eval_ret.width, 'double');
- setValue($0+$1*3, eval_ret.height, 'double');
+ setValue(PTR + ELEM_LEN*2, eval_ret.width, 'double');
+ setValue(PTR + ELEM_LEN*3, eval_ret.height, 'double');
return 6; // RECT2
}
return 5; // VECTOR2
}
- else if (typeof eval_ret.r==='number' && typeof eval_ret.g==='number' && typeof eval_ret.b==='number') {
- // assume 8-bit rgb components since we're on the web
- setValue($0, eval_ret.r, 'double');
- setValue($0+$1, eval_ret.g, 'double');
- setValue($0+$1*2, eval_ret.b, 'double');
- setValue($0+$1*3, typeof eval_ret.a==='number' ? eval_ret.a : 1, 'double');
+ if (typeof eval_ret.r === 'number' && typeof eval_ret.g === 'number' && typeof eval_ret.b === 'number') {
+ setValue(PTR, eval_ret.r, 'double');
+ setValue(PTR + ELEM_LEN, eval_ret.g, 'double');
+ setValue(PTR + ELEM_LEN*2, eval_ret.b, 'double');
+ setValue(PTR + ELEM_LEN*3, typeof eval_ret.a === 'number' ? eval_ret.a : 1, 'double');
return 14; // COLOR
}
break;
}
return 0; // NIL
- }, js_data, sizeof *js_data, p_code.utf8().get_data(), p_use_global_exec_context));
+ }, p_code.utf8().get_data(), p_use_global_exec_context, js_data, sizeof *js_data, &arr, &arr_write));
/* clang-format on */
switch (return_type) {
case Variant::BOOL:
- return !!js_data->i;
- case Variant::INT:
- return js_data->i;
+ return js_data->b;
case Variant::REAL:
return js_data->d;
case Variant::STRING: {
@@ -153,23 +167,12 @@ Variant JavaScript::eval(const String &p_code, bool p_use_global_exec_context) {
case Variant::RECT2:
return Rect2(js_data[0].d, js_data[1].d, js_data[2].d, js_data[3].d);
case Variant::COLOR:
- return Color(js_data[0].d / 255., js_data[1].d / 255., js_data[2].d / 255., js_data[3].d);
+ return Color(js_data[0].d, js_data[1].d, js_data[2].d, js_data[3].d);
+ case Variant::POOL_BYTE_ARRAY:
+ arr_write = PoolByteArray::Write();
+ return arr;
}
return Variant();
}
-void JavaScript::_bind_methods() {
-
- ClassDB::bind_method(D_METHOD("eval", "code", "use_global_execution_context"), &JavaScript::eval, false);
-}
-
-JavaScript::JavaScript() {
-
- ERR_FAIL_COND(singleton != NULL);
- singleton = this;
-}
-
-JavaScript::~JavaScript() {
-}
-
#endif // JAVASCRIPT_EVAL_ENABLED
diff --git a/platform/javascript/javascript_main.cpp b/platform/javascript/javascript_main.cpp
index ed4f416cfd..5c5d608524 100644
--- a/platform/javascript/javascript_main.cpp
+++ b/platform/javascript/javascript_main.cpp
@@ -61,7 +61,6 @@ int main(int argc, char *argv[]) {
// run the 'main_after_fs_sync' function
/* clang-format off */
EM_ASM(
- Module.noExitRuntime = true;
FS.mkdir('/userfs');
FS.mount(IDBFS, {}, '/userfs');
FS.syncfs(true, function(err) {
diff --git a/platform/javascript/os_javascript.cpp b/platform/javascript/os_javascript.cpp
index f6446e77da..d5c675d9e0 100644
--- a/platform/javascript/os_javascript.cpp
+++ b/platform/javascript/os_javascript.cpp
@@ -29,8 +29,8 @@
/*************************************************************************/
#include "os_javascript.h"
+#include "core/engine.h"
#include "core/io/file_access_buffered_fa.h"
-#include "core/project_settings.h"
#include "dom_keys.h"
#include "drivers/gles3/rasterizer_gles3.h"
#include "drivers/unix/dir_access_unix.h"
@@ -64,11 +64,6 @@ const char *OS_JavaScript::get_video_driver_name(int p_driver) const {
return "GLES3";
}
-OS::VideoMode OS_JavaScript::get_default_video_mode() const {
-
- return OS::VideoMode();
-}
-
int OS_JavaScript::get_audio_driver_count() const {
return 1;
@@ -85,10 +80,6 @@ void OS_JavaScript::initialize_core() {
FileAccess::make_default<FileAccessBufferedFA<FileAccessUnix> >(FileAccess::ACCESS_RESOURCES);
}
-void OS_JavaScript::initialize_logger() {
- _set_logger(memnew(StdLogger));
-}
-
void OS_JavaScript::set_opengl_extensions(const char *p_gl_extensions) {
ERR_FAIL_COND(!p_gl_extensions);
@@ -171,14 +162,15 @@ static EM_BOOL _mousebutton_callback(int event_type, const EmscriptenMouseEvent
}
int mask = _input->get_mouse_button_mask();
+ int button_flag = 1 << (ev->get_button_index() - 1);
if (ev->is_pressed()) {
// since the event is consumed, focus manually
if (!is_canvas_focused()) {
focus_canvas();
}
- mask |= ev->get_button_index();
- } else if (mask & ev->get_button_index()) {
- mask &= ~ev->get_button_index();
+ mask |= button_flag;
+ } else if (mask & button_flag) {
+ mask &= ~button_flag;
} else {
// release event, but press was outside the canvas, so ignore
return false;
@@ -442,25 +434,23 @@ void OS_JavaScript::initialize(const VideoMode &p_desired, int p_video_driver, i
video_mode = p_desired;
// can't fulfil fullscreen request due to browser security
video_mode.fullscreen = false;
- set_window_size(Size2(p_desired.width, p_desired.height));
+ /* clang-format off */
+ bool resize_canvas_on_start = EM_ASM_INT_V(
+ return Module.resizeCanvasOnStart;
+ );
+ /* clang-format on */
+ if (resize_canvas_on_start) {
+ set_window_size(Size2(video_mode.width, video_mode.height));
+ } else {
+ Size2 canvas_size = get_window_size();
+ video_mode.width = canvas_size.width;
+ video_mode.height = canvas_size.height;
+ }
- // find locale, emscripten only sets "C"
char locale_ptr[16];
/* clang-format off */
- EM_ASM_({
- var locale = "";
- if (Module.locale) {
- // best case: server-side script reads Accept-Language early and
- // defines the locale to be read here
- locale = Module.locale;
- } else {
- // no luck, use what the JS engine can tell us
- // if this turns out not compatible enough, add tests for
- // browserLanguage, systemLanguage and userLanguage
- locale = navigator.languages ? navigator.languages[0] : navigator.language;
- }
- locale = locale.split('.')[0];
- stringToUTF8(locale, $0, 16);
+ EM_ASM_ARGS({
+ stringToUTF8(Module.locale, $0, 16);
}, locale_ptr);
/* clang-format on */
setenv("LANG", locale_ptr, true);
@@ -480,11 +470,6 @@ void OS_JavaScript::initialize(const VideoMode &p_desired, int p_video_driver, i
print_line("Init Physicsserver");
- physics_server = memnew(PhysicsServerSW);
- physics_server->init();
- physics_2d_server = memnew(Physics2DServerSW);
- physics_2d_server->init();
-
input = memnew(InputDefault);
_input = input;
@@ -521,11 +506,6 @@ void OS_JavaScript::initialize(const VideoMode &p_desired, int p_video_driver, i
#undef SET_EM_CALLBACK
#undef EM_CHECK
-#ifdef JAVASCRIPT_EVAL_ENABLED
- javascript_eval = memnew(JavaScript);
- ProjectSettings::get_singleton()->add_singleton(ProjectSettings::Singleton("JavaScript", javascript_eval));
-#endif
-
visual_server->init();
}
@@ -898,14 +878,13 @@ String OS_JavaScript::get_resource_dir() const {
return "/"; //javascript has it's own filesystem for resources inside the APK
}
-String OS_JavaScript::get_data_dir() const {
+String OS_JavaScript::get_user_data_dir() const {
/*
- if (get_data_dir_func)
- return get_data_dir_func();
+ if (get_user_data_dir_func)
+ return get_user_data_dir_func();
*/
return "/userfs";
- //return ProjectSettings::get_singleton()->get_singleton_object("GodotOS")->call("get_data_dir");
};
String OS_JavaScript::get_executable_path() const {
@@ -1003,7 +982,7 @@ bool OS_JavaScript::is_userfs_persistent() const {
return idbfs_available;
}
-OS_JavaScript::OS_JavaScript(const char *p_execpath, GetDataDirFunc p_get_data_dir_func) {
+OS_JavaScript::OS_JavaScript(const char *p_execpath, GetUserDataDirFunc p_get_user_data_dir_func) {
set_cmdline(p_execpath, get_cmdline_args());
main_loop = NULL;
gl_extensions = NULL;
@@ -1011,7 +990,7 @@ OS_JavaScript::OS_JavaScript(const char *p_execpath, GetDataDirFunc p_get_data_d
soft_fs_enabled = false;
canvas_size_adjustment_requested = false;
- get_data_dir_func = p_get_data_dir_func;
+ get_user_data_dir_func = p_get_user_data_dir_func;
FileAccessUnix::close_notification_func = _close_notification_funcs;
idbfs_available = false;
diff --git a/platform/javascript/os_javascript.h b/platform/javascript/os_javascript.h
index 1c939d3fd5..a95b069d03 100644
--- a/platform/javascript/os_javascript.h
+++ b/platform/javascript/os_javascript.h
@@ -31,21 +31,17 @@
#define OS_JAVASCRIPT_H
#include "audio_driver_javascript.h"
-#include "audio_server_javascript.h"
#include "drivers/unix/os_unix.h"
-#include "javascript_eval.h"
#include "main/input_default.h"
#include "os/input.h"
#include "os/main_loop.h"
#include "power_javascript.h"
#include "servers/audio_server.h"
-#include "servers/physics/physics_server_sw.h"
-#include "servers/physics_2d/physics_2d_server_sw.h"
#include "servers/visual/rasterizer.h"
#include <emscripten/html5.h>
-typedef String (*GetDataDirFunc)();
+typedef String (*GetUserDataDirFunc)();
class OS_JavaScript : public OS_Unix {
@@ -54,8 +50,6 @@ class OS_JavaScript : public OS_Unix {
int64_t last_sync_time;
VisualServer *visual_server;
- PhysicsServer *physics_server;
- Physics2DServer *physics_2d_server;
AudioDriverJavaScript audio_driver_javascript;
const char *gl_extensions;
@@ -68,14 +62,10 @@ class OS_JavaScript : public OS_Unix {
CursorShape cursor_shape;
MainLoop *main_loop;
- GetDataDirFunc get_data_dir_func;
+ GetUserDataDirFunc get_user_data_dir_func;
PowerJavascript *power_manager;
-#ifdef JAVASCRIPT_EVAL_ENABLED
- JavaScript *javascript_eval;
-#endif
-
static void _close_notification_funcs(const String &p_file, int p_flags);
void process_joypads();
@@ -88,12 +78,9 @@ public:
virtual int get_video_driver_count() const;
virtual const char *get_video_driver_name(int p_driver) const;
- virtual VideoMode get_default_video_mode() const;
-
virtual int get_audio_driver_count() const;
virtual const char *get_audio_driver_name(int p_driver) const;
- virtual void initialize_logger();
virtual void initialize_core();
virtual void initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver);
@@ -153,7 +140,7 @@ public:
void set_opengl_extensions(const char *p_gl_extensions);
virtual Error shell_open(String p_uri);
- virtual String get_data_dir() const;
+ virtual String get_user_data_dir() const;
String get_executable_path() const;
virtual String get_resource_dir() const;
@@ -172,7 +159,7 @@ public:
void set_idbfs_available(bool p_idbfs_available);
- OS_JavaScript(const char *p_execpath, GetDataDirFunc p_get_data_dir_func);
+ OS_JavaScript(const char *p_execpath, GetUserDataDirFunc p_get_user_data_dir_func);
~OS_JavaScript();
};
diff --git a/platform/javascript/pre_wasm.js b/platform/javascript/pre.js
index be4383c8c9..311aa44fda 100644
--- a/platform/javascript/pre_wasm.js
+++ b/platform/javascript/pre.js
@@ -1,3 +1,2 @@
var Engine = {
- USING_WASM: true,
RuntimeEnvironment: function(Module) {
diff --git a/platform/javascript/pre_asmjs.js b/platform/javascript/pre_asmjs.js
deleted file mode 100644
index 3c497721b6..0000000000
--- a/platform/javascript/pre_asmjs.js
+++ /dev/null
@@ -1,3 +0,0 @@
-var Engine = {
- USING_WASM: false,
- RuntimeEnvironment: function(Module) {
diff --git a/platform/osx/crash_handler_osx.mm b/platform/osx/crash_handler_osx.mm
index 2ed88db309..5635fe0187 100644
--- a/platform/osx/crash_handler_osx.mm
+++ b/platform/osx/crash_handler_osx.mm
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "main/main.h"
#include "os_osx.h"
+#include "project_settings.h"
#include <string.h>
#include <unistd.h>
diff --git a/platform/osx/detect.py b/platform/osx/detect.py
index 31032659b6..ff7cf2ad2f 100644
--- a/platform/osx/detect.py
+++ b/platform/osx/detect.py
@@ -84,8 +84,15 @@ def configure(env):
else: # 64-bit, default
basecmd = root + "/target/bin/x86_64-apple-" + env["osxcross_sdk"] + "-"
- env['CC'] = basecmd + "cc"
- env['CXX'] = basecmd + "c++"
+ ccache_path = os.environ.get("CCACHE")
+ if ccache_path == None:
+ env['CC'] = basecmd + "cc"
+ env['CXX'] = basecmd + "c++"
+ else:
+ # there aren't any ccache wrappers available for OS X cross-compile,
+ # to enable caching we need to prepend the path to the ccache binary
+ env['CC'] = ccache_path + ' ' + basecmd + "cc"
+ env['CXX'] = ccache_path + ' ' + basecmd + "c++"
env['AR'] = basecmd + "ar"
env['RANLIB'] = basecmd + "ranlib"
env['AS'] = basecmd + "as"
@@ -103,7 +110,7 @@ def configure(env):
## Flags
env.Append(CPPPATH=['#platform/osx'])
- env.Append(CPPFLAGS=['-DOSX_ENABLED', '-DUNIX_ENABLED', '-DGLES2_ENABLED', '-DAPPLE_STYLE_KEYS', '-DCOREAUDIO_ENABLED'])
+ env.Append(CPPFLAGS=['-DOSX_ENABLED', '-DUNIX_ENABLED', '-DGLES_ENABLED', '-DAPPLE_STYLE_KEYS', '-DCOREAUDIO_ENABLED'])
env.Append(LINKFLAGS=['-framework', 'Cocoa', '-framework', 'Carbon', '-framework', 'OpenGL', '-framework', 'AGL', '-framework', 'AudioUnit', '-framework', 'CoreAudio', '-lz', '-framework', 'IOKit', '-framework', 'ForceFeedback'])
env.Append(LIBS=['pthread'])
diff --git a/platform/osx/export/export.cpp b/platform/osx/export/export.cpp
index 0fd21d62ee..689b79b826 100644
--- a/platform/osx/export/export.cpp
+++ b/platform/osx/export/export.cpp
@@ -53,9 +53,16 @@ class EditorExportPlatformOSX : public EditorExportPlatform {
void _fix_plist(const Ref<EditorExportPreset> &p_preset, Vector<uint8_t> &plist, const String &p_binary);
void _make_icon(const Ref<Image> &p_icon, Vector<uint8_t> &p_data);
-#ifdef OSX_ENABLED
+
Error _code_sign(const Ref<EditorExportPreset> &p_preset, const String &p_path);
Error _create_dmg(const String &p_dmg_path, const String &p_pkg_name, const String &p_app_path_name);
+
+#ifdef OSX_ENABLED
+ bool use_codesign() const { return true; }
+ bool use_dmg() const { return true; }
+#else
+ bool use_codesign() const { return false; }
+ bool use_dmg() const { return false; }
#endif
protected:
@@ -67,11 +74,7 @@ public:
virtual String get_os_name() const { return "OSX"; }
virtual Ref<Texture> get_logo() const { return logo; }
-#ifdef OSX_ENABLED
- virtual String get_binary_extension() const { return "dmg"; }
-#else
- virtual String get_binary_extension() const { return "zip"; }
-#endif
+ virtual String get_binary_extension() const { return use_dmg() ? "dmg" : "zip"; }
virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0);
virtual bool can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const;
@@ -157,7 +160,7 @@ void EditorExportPlatformOSX::_make_icon(const Ref<Image> &p_icon, Vector<uint8_
copy->convert(Image::FORMAT_RGBA8);
copy->resize(size, size);
it->create_from_image(copy);
- String path = EditorSettings::get_singleton()->get_settings_path() + "/tmp/icon.png";
+ String path = EditorSettings::get_singleton()->get_cache_dir().plus_file("icon.png");
ResourceSaver::save(path, it);
FileAccess *f = FileAccess::open(path, FileAccess::READ);
@@ -220,7 +223,6 @@ void EditorExportPlatformOSX::_fix_plist(const Ref<EditorExportPreset> &p_preset
}
}
-#ifdef OSX_ENABLED
/**
If we're running the OSX version of the Godot editor we'll:
- export our application bundle to a temporary folder
@@ -230,6 +232,7 @@ void EditorExportPlatformOSX::_fix_plist(const Ref<EditorExportPreset> &p_preset
Error EditorExportPlatformOSX::_code_sign(const Ref<EditorExportPreset> &p_preset, const String &p_path) {
List<String> args;
+
if (p_preset->get("codesign/entitlements") != "") {
/* this should point to our entitlements.plist file that sandboxes our application, I don't know if this should also be placed in our app bundle */
args.push_back("-entitlements");
@@ -239,14 +242,25 @@ Error EditorExportPlatformOSX::_code_sign(const Ref<EditorExportPreset> &p_prese
args.push_back(p_preset->get("codesign/identity"));
args.push_back("-v"); /* provide some more feedback */
args.push_back(p_path);
- Error err = OS::get_singleton()->execute("/usr/bin/codesign", args, true);
- ERR_FAIL_COND_V(err, err);
+
+ String str;
+ Error err = OS::get_singleton()->execute("codesign", args, true, NULL, &str, NULL, true);
+ ERR_FAIL_COND_V(err != OK, err);
+
+ print_line("codesign: " + str);
+ if (str.find("no identity found") != -1) {
+ EditorNode::add_io_error("codesign: no identity found");
+ return FAILED;
+ }
return OK;
}
Error EditorExportPlatformOSX::_create_dmg(const String &p_dmg_path, const String &p_pkg_name, const String &p_app_path_name) {
List<String> args;
+
+ OS::get_singleton()->move_to_trash(p_dmg_path);
+
args.push_back("create");
args.push_back(p_dmg_path);
args.push_back("-volname");
@@ -255,13 +269,26 @@ Error EditorExportPlatformOSX::_create_dmg(const String &p_dmg_path, const Strin
args.push_back("HFS+");
args.push_back("-srcfolder");
args.push_back(p_app_path_name);
- Error err = OS::get_singleton()->execute("/usr/bin/hdiutil", args, true);
- ERR_FAIL_COND_V(err, err);
+
+ String str;
+ Error err = OS::get_singleton()->execute("hdiutil", args, true, NULL, &str, NULL, true);
+ ERR_FAIL_COND_V(err != OK, err);
+
+ print_line("hdiutil returned: " + str);
+ if (str.find("create failed") != -1) {
+ if (str.find("File exists") != -1) {
+ EditorNode::add_io_error("hdiutil: create failed - file exists");
+ } else {
+ EditorNode::add_io_error("hdiutil: create failed");
+ }
+ return FAILED;
+ }
return OK;
}
Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
+ ExportNotifier notifier(*this, p_preset, p_debug, p_path, p_flags);
String src_pkg_name;
@@ -309,28 +336,45 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
else
pkg_name = "Unnamed";
- // We're on OSX so we can export to DMG, but first we create our application bundle
- String tmp_app_path_name = p_path.get_base_dir() + "/" + pkg_name + ".app";
- print_line("Exporting to " + tmp_app_path_name);
- DirAccess *tmp_app_path = DirAccess::create_for_path(tmp_app_path_name);
- ERR_FAIL_COND_V(!tmp_app_path, ERR_CANT_CREATE)
+ Error err = OK;
+ String tmp_app_path_name = "";
+ zlib_filefunc_def io2 = io;
+ FileAccess *dst_f = NULL;
+ io2.opaque = &dst_f;
+ zipFile dst_pkg_zip = NULL;
+
+ if (use_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);
+ if (!tmp_app_path) {
+ err = ERR_CANT_CREATE;
+ }
- ///@TODO We should delete the existing application bundle especially if we attempt to code sign it, but what is a safe way to do this? Maybe call system function so it moves to trash?
- // tmp_app_path->erase_contents_recursive();
+ // Create our folder structure or rely on unzip?
+ if (err == OK) {
+ print_line("Creating " + tmp_app_path_name + "/Contents/MacOS");
+ err = tmp_app_path->make_dir_recursive(tmp_app_path_name + "/Contents/MacOS");
+ }
- // Create our folder structure or rely on unzip?
- print_line("Creating " + tmp_app_path_name + "/Contents/MacOS");
- Error dir_err = tmp_app_path->make_dir_recursive(tmp_app_path_name + "/Contents/MacOS");
- ERR_FAIL_COND_V(dir_err, ERR_CANT_CREATE)
- print_line("Creating " + tmp_app_path_name + "/Contents/Resources");
- dir_err = tmp_app_path->make_dir_recursive(tmp_app_path_name + "/Contents/Resources");
- ERR_FAIL_COND_V(dir_err, ERR_CANT_CREATE)
+ if (err == OK) {
+ print_line("Creating " + tmp_app_path_name + "/Contents/Resources");
+ err = tmp_app_path->make_dir_recursive(tmp_app_path_name + "/Contents/Resources");
+ }
+ } else {
+ // Open our destination zip file
+ dst_pkg_zip = zipOpen2(p_path.utf8().get_data(), APPEND_STATUS_CREATE, NULL, &io2);
+ if (!dst_pkg_zip) {
+ err = ERR_CANT_CREATE;
+ }
+ }
- /* Now process our template */
+ // Now process our template
bool found_binary = false;
int total_size = 0;
- while (ret == UNZ_OK) {
+ while (ret == UNZ_OK && err == OK) {
bool is_execute = false;
//get filename
@@ -392,287 +436,152 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
print_line("ADDING: " + file + " size: " + itos(data.size()));
total_size += data.size();
- /* write it into our application bundle */
- file = tmp_app_path_name + "/" + file;
-
- /* write the file, need to add chmod */
- FileAccess *f = FileAccess::open(file, FileAccess::WRITE);
- ERR_FAIL_COND_V(!f, ERR_CANT_CREATE)
- f->store_buffer(data.ptr(), data.size());
- f->close();
- memdelete(f);
-
- if (is_execute) {
- // we need execute rights on this file
- chmod(file.utf8().get_data(), 0755);
+ if (use_dmg()) {
+ // write it into our application bundle
+ file = tmp_app_path_name + "/" + 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
+ f->_chmod(file, 0755);
+ }
+ memdelete(f);
+ } else {
+ err = ERR_CANT_CREATE;
+ }
} else {
- // seems to already be set correctly
- // chmod(file.utf8().get_data(), 0644);
+ // add it to our zip file
+ file = pkg_name + ".app/" + file;
+
+ zip_fileinfo fi;
+ fi.tmz_date.tm_hour = info.tmu_date.tm_hour;
+ fi.tmz_date.tm_min = info.tmu_date.tm_min;
+ fi.tmz_date.tm_sec = info.tmu_date.tm_sec;
+ fi.tmz_date.tm_mon = info.tmu_date.tm_mon;
+ fi.tmz_date.tm_mday = info.tmu_date.tm_mday;
+ fi.tmz_date.tm_year = info.tmu_date.tm_year;
+ fi.dosDate = info.dosDate;
+ fi.internal_fa = info.internal_fa;
+ fi.external_fa = info.external_fa;
+
+ int zerr = zipOpenNewFileInZip(dst_pkg_zip,
+ file.utf8().get_data(),
+ &fi,
+ NULL,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ Z_DEFLATED,
+ Z_DEFAULT_COMPRESSION);
+
+ print_line("OPEN ERR: " + itos(zerr));
+ zerr = zipWriteInFileInZip(dst_pkg_zip, data.ptr(), data.size());
+ print_line("WRITE ERR: " + itos(zerr));
+ zipCloseFileInZip(dst_pkg_zip);
}
}
ret = unzGoToNextFile(src_pkg_zip);
}
- /* we're done with our source zip */
+ // we're done with our source zip
unzClose(src_pkg_zip);
if (!found_binary) {
ERR_PRINTS("Requested template binary '" + binary_to_use + "' not found. It might be missing from your template archive.");
- unzClose(src_pkg_zip);
- return ERR_FILE_NOT_FOUND;
- }
-
- ep.step("Making PKG", 1);
-
- String pack_path = tmp_app_path_name + "/Contents/Resources/" + pkg_name + ".pck";
- Error err = save_pack(p_preset, pack_path);
- // chmod(pack_path.utf8().get_data(), 0644);
-
- if (err) {
- return err;
+ err = ERR_FILE_NOT_FOUND;
}
- /* see if we can code sign our new package */
- if (p_preset->get("codesign/identity") != "") {
- ep.step("Code signing bundle", 2);
+ if (err == OK) {
+ ep.step("Making PKG", 1);
- /* the order in which we code sign is important, this is a bit of a shame or we could do this in our loop that extracts the files from our ZIP */
+ if (use_dmg()) {
+ String pack_path = tmp_app_path_name + "/Contents/Resources/" + pkg_name + ".pck";
+ err = save_pack(p_preset, pack_path);
- // start with our application
- err = _code_sign(p_preset, tmp_app_path_name + "/Contents/MacOS/" + pkg_name);
- ERR_FAIL_COND_V(err, err);
+ // see if we can code sign our new package
+ String identity = p_preset->get("codesign/identity");
+ if (err == OK && identity != "") {
+ ep.step("Code signing bundle", 2);
- ///@TODO we should check the contents of /Contents/Frameworks for frameworks to sign
+ // the order in which we code sign is important, this is a bit of a shame or we could do this in our loop that extracts the files from our ZIP
- // we should probably loop through all resources and sign them?
- err = _code_sign(p_preset, tmp_app_path_name + "/Contents/Resources/icon.icns");
- ERR_FAIL_COND_V(err, err);
- err = _code_sign(p_preset, pack_path);
- ERR_FAIL_COND_V(err, err);
- err = _code_sign(p_preset, tmp_app_path_name + "/Contents/Info.plist");
- ERR_FAIL_COND_V(err, err);
- }
+ // start with our application
+ err = _code_sign(p_preset, tmp_app_path_name + "/Contents/MacOS/" + pkg_name);
- /* and finally create a DMG */
- ep.step("Making DMG", 3);
- err = _create_dmg(p_path, pkg_name, tmp_app_path_name);
- ERR_FAIL_COND_V(err, err);
-
- return OK;
-}
-
-#else
-
-/**
- When exporting for OSX from any other platform we don't have access to code signing or creating DMGs so we'll wrap the bundle into a zip file.
-
- Should probably find a nicer way to have just one export method instead of duplicating the method like this but I would the code got very
- messy with switches inside of it.
-**/
-Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
-
- String src_pkg_name;
-
- EditorProgress ep("export", "Exporting for OSX", 104);
-
- if (p_debug)
- src_pkg_name = p_preset->get("custom_package/debug");
- else
- src_pkg_name = p_preset->get("custom_package/release");
-
- if (src_pkg_name == "") {
- String err;
- src_pkg_name = find_export_template("osx.zip", &err);
- if (src_pkg_name == "") {
- EditorNode::add_io_error(err);
- return ERR_FILE_NOT_FOUND;
- }
- }
-
- FileAccess *src_f = NULL;
- zlib_filefunc_def io = zipio_create_io_from_file(&src_f);
-
- ep.step("Creating app", 0);
-
- unzFile src_pkg_zip = unzOpen2(src_pkg_name.utf8().get_data(), &io);
- if (!src_pkg_zip) {
-
- EditorNode::add_io_error("Could not find template app to export:\n" + src_pkg_name);
- return ERR_FILE_NOT_FOUND;
- }
-
- ERR_FAIL_COND_V(!src_pkg_zip, ERR_CANT_OPEN);
- int ret = unzGoToFirstFile(src_pkg_zip);
-
- String binary_to_use = "godot_osx_" + String(p_debug ? "debug" : "release") + ".";
- int bits_mode = p_preset->get("application/bits_mode");
- binary_to_use += String(bits_mode == 0 ? "fat" : bits_mode == 1 ? "64" : "32");
-
- print_line("binary: " + binary_to_use);
- String pkg_name;
- if (p_preset->get("application/name") != "")
- pkg_name = p_preset->get("application/name"); // app_name
- else if (String(ProjectSettings::get_singleton()->get("application/config/name")) != "")
- pkg_name = String(ProjectSettings::get_singleton()->get("application/config/name"));
- else
- pkg_name = "Unnamed";
-
- /* Open our destination zip file */
- zlib_filefunc_def io2 = io;
- FileAccess *dst_f = NULL;
- io2.opaque = &dst_f;
- zipFile dst_pkg_zip = zipOpen2(p_path.utf8().get_data(), APPEND_STATUS_CREATE, NULL, &io2);
-
- bool found_binary = false;
-
- while (ret == UNZ_OK) {
-
- //get filename
- unz_file_info info;
- char fname[16384];
- ret = unzGetCurrentFileInfo(src_pkg_zip, &info, fname, 16384, NULL, 0, NULL, 0);
-
- String file = fname;
-
- print_line("READ: " + file);
- Vector<uint8_t> data;
- data.resize(info.uncompressed_size);
-
- //read
- unzOpenCurrentFile(src_pkg_zip);
- unzReadCurrentFile(src_pkg_zip, data.ptr(), data.size());
- unzCloseCurrentFile(src_pkg_zip);
-
- //write
+ ///@TODO we should check the contents of /Contents/Frameworks for frameworks to sign
+ }
- file = file.replace_first("osx_template.app/", "");
+ if (err == OK && identity != "") {
+ // we should probably loop through all resources and sign them?
+ err = _code_sign(p_preset, tmp_app_path_name + "/Contents/Resources/icon.icns");
+ }
- if (file == "Contents/Info.plist") {
- print_line("parse plist");
- _fix_plist(p_preset, data, pkg_name);
- }
+ if (err == OK && identity != "") {
+ err = _code_sign(p_preset, pack_path);
+ }
- if (file.begins_with("Contents/MacOS/godot_")) {
- if (file != "Contents/MacOS/" + binary_to_use) {
- ret = unzGoToNextFile(src_pkg_zip);
- continue; //ignore!
+ if (err == OK && identity != "") {
+ err = _code_sign(p_preset, tmp_app_path_name + "/Contents/Info.plist");
}
- found_binary = true;
- file = "Contents/MacOS/" + pkg_name;
- }
- if (file == "Contents/Resources/icon.icns") {
- //see if there is an icon
- String iconpath;
- if (p_preset->get("application/icon") != "")
- iconpath = p_preset->get("application/icon");
- else
- iconpath = ProjectSettings::get_singleton()->get("application/config/icon");
- print_line("icon? " + iconpath);
- if (iconpath != "") {
- Ref<Image> icon;
- icon.instance();
- icon->load(iconpath);
- if (!icon->empty()) {
- print_line("loaded?");
- _make_icon(icon, data);
- }
+ // and finally create a DMG
+ if (err == OK) {
+ ep.step("Making DMG", 3);
+ err = _create_dmg(p_path, pkg_name, tmp_app_path_name);
}
- //bleh?
- }
- if (data.size() > 0) {
- print_line("ADDING: " + file + " size: " + itos(data.size()));
+ // Clean up temporary .app dir
+ OS::get_singleton()->move_to_trash(tmp_app_path_name);
+ } else {
- /* add it to our zip file */
- file = pkg_name + ".app/" + file;
-
- zip_fileinfo fi;
- fi.tmz_date.tm_hour = info.tmu_date.tm_hour;
- fi.tmz_date.tm_min = info.tmu_date.tm_min;
- fi.tmz_date.tm_sec = info.tmu_date.tm_sec;
- fi.tmz_date.tm_mon = info.tmu_date.tm_mon;
- fi.tmz_date.tm_mday = info.tmu_date.tm_mday;
- fi.tmz_date.tm_year = info.tmu_date.tm_year;
- fi.dosDate = info.dosDate;
- fi.internal_fa = info.internal_fa;
- fi.external_fa = info.external_fa;
-
- int err = zipOpenNewFileInZip(dst_pkg_zip,
- file.utf8().get_data(),
- &fi,
- NULL,
- 0,
- NULL,
- 0,
- NULL,
- Z_DEFLATED,
- Z_DEFAULT_COMPRESSION);
-
- print_line("OPEN ERR: " + itos(err));
- err = zipWriteInFileInZip(dst_pkg_zip, data.ptr(), data.size());
- print_line("WRITE ERR: " + itos(err));
- zipCloseFileInZip(dst_pkg_zip);
+ String pack_path = EditorSettings::get_singleton()->get_cache_dir().plus_file(pkg_name + ".pck");
+ Error err = save_pack(p_preset, pack_path);
+
+ if (err == OK) {
+ zipOpenNewFileInZip(dst_pkg_zip,
+ (pkg_name + ".app/Contents/Resources/" + pkg_name + ".pck").utf8().get_data(),
+ NULL,
+ NULL,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ Z_DEFLATED,
+ Z_DEFAULT_COMPRESSION);
+
+ FileAccess *pf = FileAccess::open(pack_path, FileAccess::READ);
+ if (pf) {
+ const int BSIZE = 16384;
+ uint8_t buf[BSIZE];
+
+ while (true) {
+
+ int r = pf->get_buffer(buf, BSIZE);
+ if (r <= 0)
+ break;
+ zipWriteInFileInZip(dst_pkg_zip, buf, r);
+ }
+ zipCloseFileInZip(dst_pkg_zip);
+ memdelete(pf);
+ } else {
+ err = ERR_CANT_OPEN;
+ }
+ }
}
-
- ret = unzGoToNextFile(src_pkg_zip);
}
- if (!found_binary) {
- ERR_PRINTS("Requested template binary '" + binary_to_use + "' not found. It might be missing from your template archive.");
+ if (dst_pkg_zip) {
zipClose(dst_pkg_zip, NULL);
- unzClose(src_pkg_zip);
- return ERR_FILE_NOT_FOUND;
}
- ep.step("Making PKG", 1);
-
- String pack_path = EditorSettings::get_singleton()->get_settings_path() + "/tmp/" + pkg_name + ".pck";
- Error err = save_pack(p_preset, pack_path);
-
- if (err) {
- zipClose(dst_pkg_zip, NULL);
- unzClose(src_pkg_zip);
- return err;
- }
-
- {
- //write datapack
-
- zipOpenNewFileInZip(dst_pkg_zip,
- (pkg_name + ".app/Contents/Resources/" + pkg_name + ".pck").utf8().get_data(),
- NULL,
- NULL,
- 0,
- NULL,
- 0,
- NULL,
- Z_DEFLATED,
- Z_DEFAULT_COMPRESSION);
-
- FileAccess *pf = FileAccess::open(pack_path, FileAccess::READ);
- ERR_FAIL_COND_V(!pf, ERR_CANT_OPEN);
- const int BSIZE = 16384;
- uint8_t buf[BSIZE];
-
- while (true) {
-
- int r = pf->get_buffer(buf, BSIZE);
- if (r <= 0)
- break;
- zipWriteInFileInZip(dst_pkg_zip, buf, r);
- }
- zipCloseFileInZip(dst_pkg_zip);
- memdelete(pf);
- }
-
- zipClose(dst_pkg_zip, NULL);
- unzClose(src_pkg_zip);
-
return OK;
}
-#endif
bool EditorExportPlatformOSX::can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const {
diff --git a/platform/osx/os_osx.h b/platform/osx/os_osx.h
index eb8c0566b4..9a740a7bea 100644
--- a/platform/osx/os_osx.h
+++ b/platform/osx/os_osx.h
@@ -38,9 +38,6 @@
#include "os/input.h"
#include "power_osx.h"
#include "servers/audio_server.h"
-#include "servers/physics_2d/physics_2d_server_sw.h"
-#include "servers/physics_2d/physics_2d_server_wrap_mt.h"
-#include "servers/physics_server.h"
#include "servers/visual/rasterizer.h"
#include "servers/visual/visual_server_wrap_mt.h"
#include "servers/visual_server.h"
@@ -62,9 +59,6 @@ public:
List<String> args;
MainLoop *main_loop;
- PhysicsServer *physics_server;
- Physics2DServer *physics_2d_server;
-
IP_Unix *ip_unix;
AudioDriverCoreAudio audio_driver;
@@ -112,22 +106,21 @@ public:
CrashHandler crash_handler;
float _mouse_scale(float p_scale) {
- if (display_scale > 1.0)
+ if (_display_scale() > 1.0)
return p_scale;
else
return 1.0;
}
- void _update_window();
+ float _display_scale() const;
+ float _display_scale(id screen) const;
- float display_scale;
+ void _update_window();
protected:
virtual int get_video_driver_count() const;
virtual const char *get_video_driver_name(int p_driver) const;
- virtual VideoMode get_default_video_mode() const;
- virtual void initialize_logger();
virtual void initialize_core();
virtual void initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver);
virtual void finalize();
@@ -160,6 +153,11 @@ public:
virtual MainLoop *get_main_loop() const;
+ virtual String get_config_path() const;
+ virtual String get_data_path() const;
+ virtual String get_cache_path() const;
+ virtual String get_godot_dir_name() const;
+
virtual String get_system_dir(SystemDir p_dir) const;
virtual bool can_draw() const;
@@ -218,6 +216,9 @@ public:
virtual bool _check_internal_feature_support(const String &p_feature);
+ virtual void set_use_vsync(bool p_enable);
+ virtual bool is_vsync_enabled() const;
+
void run();
void set_mouse_mode(MouseMode p_mode);
@@ -229,6 +230,12 @@ public:
virtual Error move_to_trash(const String &p_path);
OS_OSX();
+
+private:
+ Point2 get_native_screen_position(int p_screen) const;
+ Point2 get_native_window_position() const;
+ void set_native_window_position(const Point2 &p_position);
+ Point2 get_screens_origin() const;
};
#endif
diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm
index 8323aa84a8..781e8de1ab 100644
--- a/platform/osx/os_osx.mm
+++ b/platform/osx/os_osx.mm
@@ -35,8 +35,8 @@
#include "os/keyboard.h"
#include "print_string.h"
#include "sem_osx.h"
-#include "servers/physics/physics_server_sw.h"
#include "servers/visual/visual_server_raster.h"
+#include "version_generated.gen.h"
#include <Carbon/Carbon.h>
#import <Cocoa/Cocoa.h>
@@ -85,6 +85,15 @@ static int prev_mouse_y = 0;
static int button_mask = 0;
static bool mouse_down_control = false;
+static Vector2 get_mouse_pos(NSEvent *event) {
+
+ const NSRect contentRect = [OS_OSX::singleton->window_view frame];
+ const NSPoint p = [event locationInWindow];
+ mouse_x = p.x * OS_OSX::singleton->_mouse_scale([[event window] backingScaleFactor]);
+ mouse_y = (contentRect.size.height - p.y) * OS_OSX::singleton->_mouse_scale([[event window] backingScaleFactor]);
+ return Vector2(mouse_x, mouse_y);
+}
+
@interface GodotApplication : NSApplication
@end
@@ -180,13 +189,13 @@ static bool mouse_down_control = false;
if (newBackingScaleFactor != oldBackingScaleFactor) {
//Set new display scale and window size
- OS_OSX::singleton->display_scale = newBackingScaleFactor;
+ float newDisplayScale = OS_OSX::singleton->is_hidpi_allowed() ? newBackingScaleFactor : 1.0;
const NSRect contentRect = [OS_OSX::singleton->window_view frame];
const NSRect fbRect = contentRect; //convertRectToBacking(contentRect);
- OS_OSX::singleton->window_size.width = fbRect.size.width * OS_OSX::singleton->display_scale;
- OS_OSX::singleton->window_size.height = fbRect.size.height * OS_OSX::singleton->display_scale;
+ OS_OSX::singleton->window_size.width = fbRect.size.width * newDisplayScale;
+ OS_OSX::singleton->window_size.height = fbRect.size.height * newDisplayScale;
//Update context
if (OS_OSX::singleton->main_loop) {
@@ -206,8 +215,9 @@ static bool mouse_down_control = false;
const NSRect contentRect = [OS_OSX::singleton->window_view frame];
const NSRect fbRect = contentRect; //convertRectToBacking(contentRect);
- OS_OSX::singleton->window_size.width = fbRect.size.width * OS_OSX::singleton->display_scale;
- OS_OSX::singleton->window_size.height = fbRect.size.height * OS_OSX::singleton->display_scale;
+ float displayScale = OS_OSX::singleton->_display_scale();
+ OS_OSX::singleton->window_size.width = fbRect.size.width * displayScale;
+ OS_OSX::singleton->window_size.height = fbRect.size.height * displayScale;
if (OS_OSX::singleton->main_loop) {
Main::force_redraw();
@@ -352,7 +362,8 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
- (NSRect)firstRectForCharacterRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange {
const NSRect contentRect = [OS_OSX::singleton->window_view frame];
- NSRect pointInWindowRect = NSMakeRect(OS_OSX::singleton->im_position.x / OS_OSX::singleton->display_scale, contentRect.size.height - (OS_OSX::singleton->im_position.y / OS_OSX::singleton->display_scale) - 1, 0, 0);
+ float displayScale = OS_OSX::singleton->_display_scale();
+ NSRect pointInWindowRect = NSMakeRect(OS_OSX::singleton->im_position.x / displayScale, contentRect.size.height - (OS_OSX::singleton->im_position.y / displayScale) - 1, 0, 0);
NSPoint pointOnScreen = [[OS_OSX::singleton->window_view window] convertRectToScreen:pointInWindowRect].origin;
return NSMakeRect(pointOnScreen.x, pointOnScreen.y, 0, 0);
@@ -506,12 +517,9 @@ static void _mouseDownEvent(NSEvent *event, int index, int mask, bool pressed) {
mm->set_button_mask(button_mask);
prev_mouse_x = mouse_x;
prev_mouse_y = mouse_y;
- const NSRect contentRect = [OS_OSX::singleton->window_view frame];
- const NSPoint p = [event locationInWindow];
- mouse_x = p.x * OS_OSX::singleton->_mouse_scale([[event window] backingScaleFactor]);
- mouse_y = (contentRect.size.height - p.y) * OS_OSX::singleton->_mouse_scale([[event window] backingScaleFactor]);
- mm->set_position(Vector2(mouse_x, mouse_y));
- mm->set_global_position(Vector2(mouse_x, mouse_y));
+ const Vector2 pos = get_mouse_pos(event);
+ mm->set_position(pos);
+ mm->set_global_position(pos);
Vector2 relativeMotion = Vector2();
relativeMotion.x = [event deltaX] * OS_OSX::singleton->_mouse_scale([[event window] backingScaleFactor]);
relativeMotion.y = [event deltaY] * OS_OSX::singleton->_mouse_scale([[event window] backingScaleFactor]);
@@ -573,6 +581,15 @@ static void _mouseDownEvent(NSEvent *event, int index, int mask, bool pressed) {
OS_OSX::singleton->input->set_mouse_in_window(true);
}
+- (void)magnifyWithEvent:(NSEvent *)event {
+ Ref<InputEventMagnifyGesture> ev;
+ ev.instance();
+ get_key_modifier_state([event modifierFlags], ev);
+ ev->set_position(get_mouse_pos(event));
+ ev->set_factor([event magnification] + 1.0);
+ OS_OSX::singleton->push_input(ev);
+}
+
- (void)viewDidChangeBackingProperties {
// nothing left to do here
}
@@ -836,6 +853,18 @@ inline void sendScrollEvent(int button, double factor, int modifierFlags) {
OS_OSX::singleton->push_input(sc);
}
+inline void sendPanEvent(double dx, double dy, int modifierFlags) {
+
+ Ref<InputEventPanGesture> pg;
+ pg.instance();
+
+ get_key_modifier_state(modifierFlags, pg);
+ Vector2 mouse_pos = Vector2(mouse_x, mouse_y);
+ pg->set_position(mouse_pos);
+ pg->set_delta(Vector2(-dx, -dy));
+ OS_OSX::singleton->push_input(pg);
+}
+
- (void)scrollWheel:(NSEvent *)event {
double deltaX, deltaY;
@@ -854,11 +883,16 @@ inline void sendScrollEvent(int button, double factor, int modifierFlags) {
deltaX = [event deltaX];
deltaY = [event deltaY];
}
- if (fabs(deltaX)) {
- sendScrollEvent(0 > deltaX ? BUTTON_WHEEL_RIGHT : BUTTON_WHEEL_LEFT, fabs(deltaX * 0.3), [event modifierFlags]);
- }
- if (fabs(deltaY)) {
- sendScrollEvent(0 < deltaY ? BUTTON_WHEEL_UP : BUTTON_WHEEL_DOWN, fabs(deltaY * 0.3), [event modifierFlags]);
+
+ if ([event phase] != NSEventPhaseNone || [event momentumPhase] != NSEventPhaseNone) {
+ sendPanEvent(deltaX, deltaY, [event modifierFlags]);
+ } else {
+ if (fabs(deltaX)) {
+ sendScrollEvent(0 > deltaX ? BUTTON_WHEEL_RIGHT : BUTTON_WHEEL_LEFT, fabs(deltaX * 0.3), [event modifierFlags]);
+ }
+ if (fabs(deltaY)) {
+ sendScrollEvent(0 < deltaY ? BUTTON_WHEEL_UP : BUTTON_WHEEL_DOWN, fabs(deltaY * 0.3), [event modifierFlags]);
+ }
}
}
@@ -895,17 +929,7 @@ int OS_OSX::get_video_driver_count() const {
const char *OS_OSX::get_video_driver_name(int p_driver) const {
- return "GLES2";
-}
-
-OS::VideoMode OS_OSX::get_default_video_mode() const {
-
- VideoMode vm;
- vm.width = 1024;
- vm.height = 600;
- vm.fullscreen = false;
- vm.resizable = true;
- return vm;
+ return "GLES3";
}
void OS_OSX::initialize_core() {
@@ -922,10 +946,15 @@ void OS_OSX::initialize_core() {
}
static bool keyboard_layout_dirty = true;
-static void keyboardLayoutChanged(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) {
+static void keyboard_layout_changed(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef user_info) {
keyboard_layout_dirty = true;
}
+static bool displays_arrangement_dirty = true;
+static void displays_arrangement_changed(CGDirectDisplayID display_id, CGDisplayChangeSummaryFlags flags, void *user_info) {
+ displays_arrangement_dirty = true;
+}
+
void OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) {
/*** OSX INITIALIZATION ***/
@@ -933,21 +962,16 @@ void OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_au
/*** OSX INITIALIZATION ***/
keyboard_layout_dirty = true;
+ displays_arrangement_dirty = true;
// Register to be notified on keyboard layout changes
CFNotificationCenterAddObserver(CFNotificationCenterGetDistributedCenter(),
- NULL, keyboardLayoutChanged,
+ NULL, keyboard_layout_changed,
kTISNotifySelectedKeyboardInputSourceChanged, NULL,
CFNotificationSuspensionBehaviorDeliverImmediately);
- if (is_hidpi_allowed() && [[NSScreen mainScreen] respondsToSelector:@selector(backingScaleFactor)]) {
- for (NSScreen *screen in [NSScreen screens]) {
- float s = [screen backingScaleFactor];
- if (s > display_scale) {
- display_scale = s;
- }
- }
- }
+ // Register to be notified on displays arrangement changes
+ CGDisplayRegisterReconfigurationCallback(displays_arrangement_changed, NULL);
window_delegate = [[GodotWindowDelegate alloc] init];
@@ -972,10 +996,19 @@ void OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_au
window_view = [[GodotContentView alloc] init];
- window_size.width = p_desired.width * display_scale;
- window_size.height = p_desired.height * display_scale;
+ float displayScale = 1.0;
+ if (is_hidpi_allowed()) {
+ // note that mainScreen is not screen #0 but the one with the keyboard focus.
+ NSScreen *screen = [NSScreen mainScreen];
+ if ([screen respondsToSelector:@selector(backingScaleFactor)]) {
+ displayScale = fmax(displayScale, [screen backingScaleFactor]);
+ }
+ }
+
+ window_size.width = p_desired.width * displayScale;
+ window_size.height = p_desired.height * displayScale;
- if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6 && display_scale > 1) {
+ if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6 && displayScale > 1.0) {
[window_view setWantsBestResolutionOpenGLSurface:YES];
//if (current_videomode.resizable)
[window_object setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
@@ -1066,8 +1099,6 @@ void OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_au
zoomed = true;
/*** END OSX INITIALIZATION ***/
- /*** END OSX INITIALIZATION ***/
- /*** END OSX INITIALIZATION ***/
bool use_gl2 = p_video_driver != 1;
@@ -1077,32 +1108,21 @@ void OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_au
RasterizerGLES3::register_config();
RasterizerGLES3::make_current();
- //rasterizer = instance_RasterizerGLES2();
- //visual_server = memnew( VisualServerRaster(rasterizer) );
-
visual_server = memnew(VisualServerRaster);
if (get_render_thread_mode() != RENDER_THREAD_UNSAFE) {
visual_server = memnew(VisualServerWrapMT(visual_server, get_render_thread_mode() == RENDER_SEPARATE_THREAD));
}
visual_server->init();
- // visual_server->cursor_set_visible(false, 0);
AudioDriverManager::initialize(p_audio_driver);
- //
- physics_server = memnew(PhysicsServerSW);
- physics_server->init();
- //physics_2d_server = memnew( Physics2DServerSW );
- physics_2d_server = Physics2DServerWrapMT::init_server<Physics2DServerSW>();
- physics_2d_server->init();
-
input = memnew(InputDefault);
joypad_osx = memnew(JoypadOSX);
power_manager = memnew(power_osx);
- _ensure_data_dir();
+ _ensure_user_data_dir();
restore_rect = Rect2(get_window_position(), get_window_size());
}
@@ -1110,6 +1130,8 @@ void OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_au
void OS_OSX::finalize() {
CFNotificationCenterRemoveObserver(CFNotificationCenterGetDistributedCenter(), NULL, kTISNotifySelectedKeyboardInputSourceChanged, NULL);
+ CGDisplayRemoveReconfigurationCallback(displays_arrangement_changed, NULL);
+
delete_main_loop();
memdelete(joypad_osx);
@@ -1118,12 +1140,6 @@ void OS_OSX::finalize() {
visual_server->finish();
memdelete(visual_server);
//memdelete(rasterizer);
-
- physics_server->finish();
- memdelete(physics_server);
-
- physics_2d_server->finish();
- memdelete(physics_2d_server);
}
void OS_OSX::set_main_loop(MainLoop *p_main_loop) {
@@ -1201,13 +1217,6 @@ public:
typedef UnixTerminalLogger OSXTerminalLogger;
#endif
-void OS_OSX::initialize_logger() {
- Vector<Logger *> loggers;
- loggers.push_back(memnew(OSXTerminalLogger));
- loggers.push_back(memnew(RotatedFileLogger("user://logs/log.txt")));
- _set_logger(memnew(CompositeLogger(loggers)));
-}
-
void OS_OSX::alert(const String &p_alert, const String &p_title) {
// Set OS X-compliant variables
NSAlert *window = [[NSAlert alloc] init];
@@ -1274,7 +1283,8 @@ void OS_OSX::warp_mouse_position(const Point2 &p_to) {
//local point in window coords
const NSRect contentRect = [window_view frame];
- NSRect pointInWindowRect = NSMakeRect(p_to.x / display_scale, contentRect.size.height - (p_to.y / display_scale) - 1, 0, 0);
+ float displayScale = _display_scale();
+ NSRect pointInWindowRect = NSMakeRect(p_to.x / displayScale, contentRect.size.height - (p_to.y / displayScale) - 1, 0, 0);
NSPoint pointOnScreen = [[window_view window] convertRectToScreen:pointInWindowRect].origin;
//point in scren coords
@@ -1348,6 +1358,43 @@ MainLoop *OS_OSX::get_main_loop() const {
return main_loop;
}
+String OS_OSX::get_config_path() const {
+
+ if (has_environment("XDG_CONFIG_HOME")) {
+ return get_environment("XDG_CONFIG_HOME");
+ } else if (has_environment("HOME")) {
+ return get_environment("HOME").plus_file("Library/Application Support");
+ } else {
+ return ".";
+ }
+}
+
+String OS_OSX::get_data_path() const {
+
+ if (has_environment("XDG_DATA_HOME")) {
+ return get_environment("XDG_DATA_HOME");
+ } else {
+ return get_config_path();
+ }
+}
+
+String OS_OSX::get_cache_path() const {
+
+ if (has_environment("XDG_CACHE_HOME")) {
+ return get_environment("XDG_CACHE_HOME");
+ } else if (has_environment("HOME")) {
+ return get_environment("HOME").plus_file("Library/Caches");
+ } else {
+ return get_config_path();
+ }
+}
+
+// Get properly capitalized engine name for system paths
+String OS_OSX::get_godot_dir_name() const {
+
+ return String(VERSION_SHORT_NAME).capitalize();
+}
+
String OS_OSX::get_system_dir(SystemDir p_dir) const {
NSSearchPathDirectory id = 0;
@@ -1475,17 +1522,43 @@ int OS_OSX::get_screen_count() const {
return [screenArray count];
};
+// Returns the native top-left screen coordinate of the smallest rectangle
+// that encompasses all screens. Needed in get_screen_position(),
+// get_window_position, and set_window_position()
+// to convert between OS X native screen coordinates and the ones expected by Godot
+Point2 OS_OSX::get_screens_origin() const {
+ static Point2 origin;
+
+ if (displays_arrangement_dirty) {
+ origin = Point2();
+
+ for (int i = 0; i < get_screen_count(); i++) {
+ Point2 position = get_native_screen_position(i);
+ if (position.x < origin.x) {
+ origin.x = position.x;
+ }
+ if (position.y > origin.y) {
+ origin.y = position.y;
+ }
+ }
+
+ displays_arrangement_dirty = false;
+ }
+
+ return origin;
+}
+
+static int get_screen_index(NSScreen *screen) {
+ const NSUInteger index = [[NSScreen screens] indexOfObject:screen];
+ return index == NSNotFound ? 0 : index;
+}
+
int OS_OSX::get_current_screen() const {
- Vector2 wpos = get_window_position();
-
- int count = get_screen_count();
- for (int i = 0; i < count; i++) {
- Point2 pos = get_screen_position(i);
- Size2 size = get_screen_size(i);
- if ((wpos.x >= pos.x && wpos.x < pos.x + size.width) && (wpos.y >= pos.y && wpos.y < pos.y + size.height))
- return i;
+ if (window_object) {
+ return get_screen_index([window_object screen]);
+ } else {
+ return get_screen_index([NSScreen mainScreen]);
}
- return 0;
};
void OS_OSX::set_current_screen(int p_screen) {
@@ -1493,26 +1566,30 @@ void OS_OSX::set_current_screen(int p_screen) {
set_window_position(wpos + get_screen_position(p_screen));
};
-Point2 OS_OSX::get_screen_position(int p_screen) const {
+Point2 OS_OSX::get_native_screen_position(int p_screen) const {
if (p_screen == -1) {
p_screen = get_current_screen();
}
NSArray *screenArray = [NSScreen screens];
if (p_screen < [screenArray count]) {
- float displayScale = 1.0;
-
- if (display_scale > 1.0 && [[screenArray objectAtIndex:p_screen] respondsToSelector:@selector(backingScaleFactor)]) {
- displayScale = [[screenArray objectAtIndex:p_screen] backingScaleFactor];
- }
-
+ float display_scale = _display_scale([screenArray objectAtIndex:p_screen]);
NSRect nsrect = [[screenArray objectAtIndex:p_screen] frame];
- return Point2(nsrect.origin.x, nsrect.origin.y) * displayScale;
+ // Return the top-left corner of the screen, for OS X the y starts at the bottom
+ return Point2(nsrect.origin.x, nsrect.origin.y + nsrect.size.height) * display_scale;
}
return Point2();
}
+Point2 OS_OSX::get_screen_position(int p_screen) const {
+ Point2 position = get_native_screen_position(p_screen) - get_screens_origin();
+ // OS X native y-coordinate relative to get_screens_origin() is negative,
+ // Godot expects a positive value
+ position.y *= -1;
+ return position;
+}
+
int OS_OSX::get_screen_dpi(int p_screen) const {
if (p_screen == -1) {
p_screen = get_current_screen();
@@ -1520,12 +1597,7 @@ int OS_OSX::get_screen_dpi(int p_screen) const {
NSArray *screenArray = [NSScreen screens];
if (p_screen < [screenArray count]) {
- float displayScale = 1.0;
-
- if (display_scale > 1.0 && [[screenArray objectAtIndex:p_screen] respondsToSelector:@selector(backingScaleFactor)]) {
- displayScale = [[screenArray objectAtIndex:p_screen] backingScaleFactor];
- }
-
+ float displayScale = _display_scale([screenArray objectAtIndex:p_screen]);
NSDictionary *description = [[screenArray objectAtIndex:p_screen] deviceDescription];
NSSize displayPixelSize = [[description objectForKey:NSDeviceSize] sizeValue];
CGSize displayPhysicalSize = CGDisplayScreenSize(
@@ -1544,12 +1616,7 @@ Size2 OS_OSX::get_screen_size(int p_screen) const {
NSArray *screenArray = [NSScreen screens];
if (p_screen < [screenArray count]) {
- float displayScale = 1.0;
-
- if (display_scale > 1.0 && [[screenArray objectAtIndex:p_screen] respondsToSelector:@selector(backingScaleFactor)]) {
- displayScale = [[screenArray objectAtIndex:p_screen] backingScaleFactor];
- }
-
+ float displayScale = _display_scale([screenArray objectAtIndex:p_screen]);
// Note: Use frame to get the whole screen size
NSRect nsrect = [[screenArray objectAtIndex:p_screen] frame];
return Size2(nsrect.size.width, nsrect.size.height) * displayScale;
@@ -1583,27 +1650,66 @@ void OS_OSX::_update_window() {
}
}
-Point2 OS_OSX::get_window_position() const {
+float OS_OSX::_display_scale() const {
+ if (window_object) {
+ return _display_scale([window_object screen]);
+ } else {
+ return _display_scale([NSScreen mainScreen]);
+ }
+}
- Size2 wp([window_object frame].origin.x, [window_object frame].origin.y);
- wp *= display_scale;
- return wp;
+float OS_OSX::_display_scale(id screen) const {
+ if (is_hidpi_allowed()) {
+ if ([screen respondsToSelector:@selector(backingScaleFactor)]) {
+ return fmax(1.0, [screen backingScaleFactor]);
+ }
+ } else {
+ return 1.0;
+ }
+}
+
+Point2 OS_OSX::get_native_window_position() const {
+
+ NSRect nsrect = [window_object frame];
+ Point2 pos;
+ float display_scale = _display_scale();
+
+ // Return the position of the top-left corner, for OS X the y starts at the bottom
+ pos.x = nsrect.origin.x * display_scale;
+ pos.y = (nsrect.origin.y + nsrect.size.height) * display_scale;
+
+ return pos;
};
-void OS_OSX::set_window_position(const Point2 &p_position) {
+Point2 OS_OSX::get_window_position() const {
+ Point2 position = get_native_window_position() - get_screens_origin();
+ // OS X native y-coordinate relative to get_screens_origin() is negative,
+ // Godot expects a positive value
+ position.y *= -1;
+ return position;
+}
+
+void OS_OSX::set_native_window_position(const Point2 &p_position) {
- Size2 scr = get_screen_size();
NSPoint pos;
+ float displayScale = _display_scale();
- pos.x = p_position.x / display_scale;
- // For OS X the y starts at the bottom
- pos.y = (scr.height - p_position.y) / display_scale;
+ pos.x = p_position.x / displayScale;
+ pos.y = p_position.y / displayScale;
[window_object setFrameTopLeftPoint:pos];
_update_window();
};
+void OS_OSX::set_window_position(const Point2 &p_position) {
+ Point2 position = p_position;
+ // OS X native y-coordinate relative to get_screens_origin() is negative,
+ // Godot passes a positive value
+ position.y *= -1;
+ set_native_window_position(get_screens_origin() + position);
+};
+
Size2 OS_OSX::get_window_size() const {
return window_size;
@@ -1825,6 +1931,8 @@ OS::LatinKeyboardVariant OS_OSX::get_latin_keyboard_variant() const {
layout = LATIN_KEYBOARD_DVORAK;
} else if ([test isEqualToString:@"xvlcwk"]) {
layout = LATIN_KEYBOARD_NEO;
+ } else if ([test isEqualToString:@"qwfpgj"]) {
+ layout = LATIN_KEYBOARD_COLEMAK;
}
[test release];
@@ -1947,6 +2055,23 @@ Error OS_OSX::move_to_trash(const String &p_path) {
return OK;
}
+void OS_OSX::set_use_vsync(bool p_enable) {
+ CGLContextObj ctx = CGLGetCurrentContext();
+ if (ctx) {
+ GLint swapInterval = p_enable ? 1 : 0;
+ CGLSetParameter(ctx, kCGLCPSwapInterval, &swapInterval);
+ }
+}
+
+bool OS_OSX::is_vsync_enabled() const {
+ GLint swapInterval = 0;
+ CGLContextObj ctx = CGLGetCurrentContext();
+ if (ctx) {
+ CGLGetParameter(ctx, kCGLCPSwapInterval, &swapInterval);
+ }
+ return swapInterval ? true : false;
+}
+
OS_OSX *OS_OSX::singleton = NULL;
OS_OSX::OS_OSX() {
@@ -2039,9 +2164,10 @@ OS_OSX::OS_OSX() {
minimized = false;
window_size = Vector2(1024, 600);
zoomed = false;
- display_scale = 1.0;
- _set_logger(memnew(OSXTerminalLogger));
+ Vector<Logger *> loggers;
+ loggers.push_back(memnew(OSXTerminalLogger));
+ _set_logger(memnew(CompositeLogger(loggers)));
}
bool OS_OSX::_check_internal_feature_support(const String &p_feature) {
diff --git a/platform/register_platform_apis.h b/platform/register_platform_apis.h
new file mode 100644
index 0000000000..37f98f6cd3
--- /dev/null
+++ b/platform/register_platform_apis.h
@@ -0,0 +1,36 @@
+/*************************************************************************/
+/* register_platform_apis.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#ifndef REGISTER_APIS_H
+#define REGISTER_APIS_H
+
+void register_platform_apis();
+void unregister_platform_apis();
+
+#endif
diff --git a/platform/server/detect.py b/platform/server/detect.py
index 04b38f280d..ffec2af933 100644
--- a/platform/server/detect.py
+++ b/platform/server/detect.py
@@ -12,6 +12,9 @@ def get_name():
def can_build():
+ # Doesn't build against Godot 3.0 for now, disable to avoid confusing users
+ return False
+
if (os.name != "posix" or sys.platform == "darwin"):
return False
diff --git a/platform/server/os_server.cpp b/platform/server/os_server.cpp
index 300c5cffcc..5b852af738 100644
--- a/platform/server/os_server.cpp
+++ b/platform/server/os_server.cpp
@@ -31,7 +31,6 @@
//#include "servers/visual/rasterizer_dummy.h"
#include "os_server.h"
#include "print_string.h"
-#include "servers/physics/physics_server_sw.h"
#include <stdio.h>
#include <stdlib.h>
@@ -47,10 +46,6 @@ const char *OS_Server::get_video_driver_name(int p_driver) const {
return "Dummy";
}
-OS::VideoMode OS_Server::get_default_video_mode() const {
-
- return OS::VideoMode(800, 600, false);
-}
void OS_Server::initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) {
@@ -75,15 +70,10 @@ void OS_Server::initialize(const VideoMode &p_desired, int p_video_driver, int p
ERR_FAIL_COND(!visual_server);
visual_server->init();
- //
- physics_server = memnew(PhysicsServerSW);
- physics_server->init();
- physics_2d_server = memnew(Physics2DServerSW);
- physics_2d_server->init();
input = memnew(InputDefault);
- _ensure_data_dir();
+ _ensure_user_data_dir();
}
void OS_Server::finalize() {
@@ -111,12 +101,6 @@ void OS_Server::finalize() {
memdelete(visual_server);
//memdelete(rasterizer);
- physics_server->finish();
- memdelete(physics_server);
-
- physics_2d_server->finish();
- memdelete(physics_2d_server);
-
memdelete(input);
args.clear();
diff --git a/platform/server/os_server.h b/platform/server/os_server.h
index ba12f649be..03f7c2a6c8 100644
--- a/platform/server/os_server.h
+++ b/platform/server/os_server.h
@@ -35,8 +35,6 @@
#include "drivers/unix/os_unix.h"
#include "main/input_default.h"
#include "servers/audio_server.h"
-#include "servers/physics_2d/physics_2d_server_sw.h"
-#include "servers/physics_server.h"
#include "servers/visual/rasterizer.h"
#include "servers/visual_server.h"
@@ -56,9 +54,6 @@ class OS_Server : public OS_Unix {
bool grab;
- PhysicsServer *physics_server;
- Physics2DServer *physics_2d_server;
-
virtual void delete_main_loop();
IP_Unix *ip_unix;
@@ -71,7 +66,6 @@ class OS_Server : public OS_Unix {
protected:
virtual int get_video_driver_count() const;
virtual const char *get_video_driver_name(int p_driver) const;
- virtual VideoMode get_default_video_mode() const;
virtual void initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver);
virtual void finalize();
diff --git a/platform/uwp/SCsub b/platform/uwp/SCsub
index 7ee5aa2ac3..bbd329a7e5 100644
--- a/platform/uwp/SCsub
+++ b/platform/uwp/SCsub
@@ -8,6 +8,7 @@ files = [
'#platform/windows/packet_peer_udp_winsock.cpp',
'#platform/windows/stream_peer_winsock.cpp',
'#platform/windows/key_mapping_win.cpp',
+ '#platform/windows/windows_terminal_logger.cpp',
'joypad_uwp.cpp',
'power_uwp.cpp',
'gl_context_egl.cpp',
diff --git a/platform/uwp/app.h b/platform/uwp/app.h
index e079fa9c9d..b812512a98 100644
--- a/platform/uwp/app.h
+++ b/platform/uwp/app.h
@@ -33,6 +33,7 @@
#include <wrl.h>
+// ANGLE doesn't provide a specific lib for GLES3, so we keep using GLES2
#include "GLES2/gl2.h"
#include "os_uwp.h"
diff --git a/platform/uwp/detect.py b/platform/uwp/detect.py
index af53f97446..7cc8afff06 100644
--- a/platform/uwp/detect.py
+++ b/platform/uwp/detect.py
@@ -84,7 +84,7 @@ def configure(env):
## Architecture
arch = ""
- if os.getenv('Platform') == "ARM":
+ if str(os.getenv('Platform')).lower() == "arm":
print("Compiled program architecture will be an ARM executable. (forcing bits=32).")
@@ -136,7 +136,7 @@ def configure(env):
env.Append(CPPPATH=['#platform/uwp', '#drivers/windows'])
env.Append(CCFLAGS=['/DUWP_ENABLED', '/DWINDOWS_ENABLED', '/DTYPED_METHOD_BIND'])
- env.Append(CCFLAGS=['/DGLES2_ENABLED', '/DGL_GLEXT_PROTOTYPES', '/DEGL_EGLEXT_PROTOTYPES', '/DANGLE_ENABLED'])
+ env.Append(CCFLAGS=['/DGLES_ENABLED', '/DGL_GLEXT_PROTOTYPES', '/DEGL_EGLEXT_PROTOTYPES', '/DANGLE_ENABLED'])
winver = "0x0602" # Windows 8 is the minimum target for UWP build
env.Append(CCFLAGS=['/DWINVER=%s' % winver, '/D_WIN32_WINNT=%s' % winver])
diff --git a/platform/uwp/export/export.cpp b/platform/uwp/export/export.cpp
index d66bcaa91c..120df9bc3f 100644
--- a/platform/uwp/export/export.cpp
+++ b/platform/uwp/export/export.cpp
@@ -456,8 +456,8 @@ void AppxPackager::init(FileAccess *p_fa) {
package = p_fa;
central_dir_offset = 0;
end_of_central_dir_offset = 0;
- tmp_blockmap_file_path = EditorSettings::get_singleton()->get_settings_path() + "/tmp/tmpblockmap.xml";
- tmp_content_types_file_path = EditorSettings::get_singleton()->get_settings_path() + "/tmp/tmpcontenttypes.xml";
+ tmp_blockmap_file_path = EditorSettings::get_singleton()->get_cache_dir().plus_file("tmpblockmap.xml");
+ tmp_content_types_file_path = EditorSettings::get_singleton()->get_cache_dir().plus_file("tmpcontenttypes.xml");
}
void AppxPackager::add_file(String p_file_name, const uint8_t *p_buffer, size_t p_len, int p_file_no, int p_total_files, bool p_compress) {
@@ -886,7 +886,7 @@ class EditorExportUWP : public EditorExportPlatform {
if (!image) return data;
- String tmp_path = EditorSettings::get_singleton()->get_settings_path().plus_file("tmp/uwp_tmp_logo.png");
+ String tmp_path = EditorSettings::get_singleton()->get_cache_dir().plus_file("uwp_tmp_logo.png");
Error err = image->get_data()->save_png(tmp_path);
diff --git a/platform/uwp/gl_context_egl.cpp b/platform/uwp/gl_context_egl.cpp
index ed3db65cdf..dafe5d5e25 100644
--- a/platform/uwp/gl_context_egl.cpp
+++ b/platform/uwp/gl_context_egl.cpp
@@ -101,26 +101,25 @@ Error ContextEGL::initialize() {
try {
- const EGLint displayAttributes[] =
- {
- /*EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
- EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, 9,
- EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, 3,
- EGL_NONE,*/
- // These are the default display attributes, used to request ANGLE's D3D11 renderer.
- // eglInitialize will only succeed with these attributes if the hardware supports D3D11 Feature Level 10_0+.
- EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
-
- // EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER is an optimization that can have large performance benefits on mobile devices.
- // Its syntax is subject to change, though. Please update your Visual Studio templates if you experience compilation issues with it.
- //EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, EGL_TRUE,
-
- // EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE is an option that enables ANGLE to automatically call
- // the IDXGIDevice3::Trim method on behalf of the application when it gets suspended.
- // Calling IDXGIDevice3::Trim when an application is suspended is a Windows Store application certification requirement.
- EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_TRUE,
- EGL_NONE,
- };
+ const EGLint displayAttributes[] = {
+ /*EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
+ EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, 9,
+ EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, 3,
+ EGL_NONE,*/
+ // These are the default display attributes, used to request ANGLE's D3D11 renderer.
+ // eglInitialize will only succeed with these attributes if the hardware supports D3D11 Feature Level 10_0+.
+ EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
+
+ // EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER is an optimization that can have large performance benefits on mobile devices.
+ // Its syntax is subject to change, though. Please update your Visual Studio templates if you experience compilation issues with it.
+ //EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, EGL_TRUE,
+
+ // EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE is an option that enables ANGLE to automatically call
+ // the IDXGIDevice3::Trim method on behalf of the application when it gets suspended.
+ // Calling IDXGIDevice3::Trim when an application is suspended is a Windows Store application certification requirement.
+ EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_TRUE,
+ EGL_NONE,
+ };
PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT = reinterpret_cast<PFNEGLGETPLATFORMDISPLAYEXTPROC>(eglGetProcAddress("eglGetPlatformDisplayEXT"));
diff --git a/platform/uwp/os_uwp.cpp b/platform/uwp/os_uwp.cpp
index 031c714514..1655caf04b 100644
--- a/platform/uwp/os_uwp.cpp
+++ b/platform/uwp/os_uwp.cpp
@@ -28,6 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "os_uwp.h"
+
#include "drivers/gles3/rasterizer_gles3.h"
#include "drivers/unix/ip_unix.h"
#include "drivers/windows/dir_access_windows.h"
@@ -69,12 +70,7 @@ int OSUWP::get_video_driver_count() const {
}
const char *OSUWP::get_video_driver_name(int p_driver) const {
- return "GLES2";
-}
-
-OS::VideoMode OSUWP::get_default_video_mode() const {
-
- return video_mode;
+ return "GLES3";
}
Size2 OSUWP::get_window_size() const {
@@ -183,13 +179,6 @@ void OSUWP::initialize_core() {
cursor_shape = CURSOR_ARROW;
}
-void OSUWP::initialize_logger() {
- Vector<Logger *> loggers;
- loggers.push_back(memnew(WindowsTerminalLogger));
- loggers.push_back(memnew(RotatedFileLogger("user://logs/log.txt")));
- _set_logger(memnew(CompositeLogger(loggers)));
-}
-
bool OSUWP::can_draw() const {
return !minimized;
@@ -262,13 +251,6 @@ void OSUWP::initialize(const VideoMode &p_desired, int p_video_driver, int p_aud
}
*/
- //
- physics_server = memnew(PhysicsServerSW);
- physics_server->init();
-
- physics_2d_server = memnew(Physics2DServerSW);
- physics_2d_server->init();
-
visual_server->init();
input = memnew(InputDefault);
@@ -308,7 +290,7 @@ void OSUWP::initialize(const VideoMode &p_desired, int p_video_driver, int p_aud
ref new TypedEventHandler<Gyrometer ^, GyrometerReadingChangedEventArgs ^>(managed_object, &ManagedType::on_gyroscope_reading_changed);
}
- _ensure_data_dir();
+ _ensure_user_data_dir();
if (is_keep_screen_on())
display_request->RequestActive();
@@ -367,12 +349,6 @@ void OSUWP::finalize() {
memdelete(input);
- physics_server->finish();
- memdelete(physics_server);
-
- physics_2d_server->finish();
- memdelete(physics_2d_server);
-
joypad = nullptr;
}
@@ -674,7 +650,7 @@ void OSUWP::set_cursor_shape(CursorShape p_shape) {
cursor_shape = p_shape;
}
-Error OSUWP::execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, String *r_pipe, int *r_exitcode) {
+Error OSUWP::execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, String *r_pipe, int *r_exitcode, bool read_stderr) {
return FAILED;
};
@@ -797,7 +773,7 @@ MainLoop *OSUWP::get_main_loop() const {
return main_loop;
}
-String OSUWP::get_data_dir() const {
+String OSUWP::get_user_data_dir() const {
Windows::Storage::StorageFolder ^ data_folder = Windows::Storage::ApplicationData::Current->LocalFolder;
@@ -849,7 +825,9 @@ OSUWP::OSUWP() {
AudioDriverManager::add_driver(&audio_driver);
- _set_logger(memnew(WindowsTerminalLogger));
+ Vector<Logger *> loggers;
+ loggers.push_back(memnew(WindowsTerminalLogger));
+ _set_logger(memnew(CompositeLogger(loggers)));
}
OSUWP::~OSUWP() {
diff --git a/platform/uwp/os_uwp.h b/platform/uwp/os_uwp.h
index df38faa8e1..8d69cd53fd 100644
--- a/platform/uwp/os_uwp.h
+++ b/platform/uwp/os_uwp.h
@@ -40,8 +40,6 @@
#include "os/os.h"
#include "power_uwp.h"
#include "servers/audio_server.h"
-#include "servers/physics/physics_server_sw.h"
-#include "servers/physics_2d/physics_2d_server_sw.h"
#include "servers/visual/rasterizer.h"
#include "servers/visual_server.h"
@@ -94,8 +92,6 @@ private:
int old_x, old_y;
Point2i center;
VisualServer *visual_server;
- PhysicsServer *physics_server;
- Physics2DServer *physics_2d_server;
int pressrc;
ContextEGL *gl_context;
@@ -158,12 +154,9 @@ protected:
virtual int get_video_driver_count() const;
virtual const char *get_video_driver_name(int p_driver) const;
- virtual VideoMode get_default_video_mode() const;
-
virtual int get_audio_driver_count() const;
virtual const char *get_audio_driver_name(int p_driver) const;
- virtual void initialize_logger();
virtual void initialize_core();
virtual void initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver);
@@ -215,7 +208,7 @@ public:
virtual void delay_usec(uint32_t p_usec) const;
virtual uint64_t get_ticks_usec() const;
- virtual Error execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id = NULL, String *r_pipe = NULL, int *r_exitcode = NULL);
+ virtual Error execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id = NULL, String *r_pipe = NULL, int *r_exitcode = NULL, bool read_stderr = false);
virtual Error kill(const ProcessID &p_pid);
virtual bool has_environment(const String &p_var) const;
@@ -232,7 +225,7 @@ public:
virtual String get_locale() const;
virtual void move_window_to_foreground();
- virtual String get_data_dir() const;
+ virtual String get_user_data_dir() const;
virtual bool _check_internal_feature_support(const String &p_feature);
diff --git a/platform/windows/context_gl_win.cpp b/platform/windows/context_gl_win.cpp
index 8640f27699..81aa18dd23 100644
--- a/platform/windows/context_gl_win.cpp
+++ b/platform/windows/context_gl_win.cpp
@@ -27,25 +27,12 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#if defined(OPENGL_ENABLED) || defined(LEGACYGL_ENABLED) || defined(GLES2_ENABLED)
-
-//
-// C++ Implementation: context_gl_x11
-//
-// Description:
-//
-//
+#if defined(OPENGL_ENABLED) || defined(GLES_ENABLED)
+
// Author: Juan Linietsky <reduzio@gmail.com>, (C) 2008
-//
-// Copyright: See COPYING file that comes with this distribution
-//
-//
#include "context_gl_win.h"
-//#include "drivers/opengl/glwrapper.h"
-//#include "ctxgl_procaddr.h"
-
#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
#define WGL_CONTEXT_FLAGS_ARB 0x2094
@@ -165,7 +152,7 @@ Error ContextGL_Win::initialize() {
WGL_CONTEXT_MAJOR_VERSION_ARB, 3, //we want a 3.3 context
WGL_CONTEXT_MINOR_VERSION_ARB, 3,
//and it shall be forward compatible so that we can only use up to date functionality
- WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB | _WGL_CONTEXT_DEBUG_BIT_ARB,
+ WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB /*| _WGL_CONTEXT_DEBUG_BIT_ARB*/,
0
}; //zero indicates the end of the array
diff --git a/platform/windows/context_gl_win.h b/platform/windows/context_gl_win.h
index 912d4d0133..5a280b0d08 100644
--- a/platform/windows/context_gl_win.h
+++ b/platform/windows/context_gl_win.h
@@ -27,18 +27,9 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#if defined(OPENGL_ENABLED) || defined(LEGACYGL_ENABLED) || defined(GLES2_ENABLED)
-//
-// C++ Interface: context_gl_x11
-//
-// Description:
-//
-//
+#if defined(OPENGL_ENABLED) || defined(GLES_ENABLED)
+
// Author: Juan Linietsky <reduzio@gmail.com>, (C) 2008
-//
-// Copyright: See COPYING file that comes with this distribution
-//
-//
#ifndef CONTEXT_GL_WIN_H
#define CONTEXT_GL_WIN_H
diff --git a/platform/windows/crash_handler_win.cpp b/platform/windows/crash_handler_win.cpp
index 2f5ee7956e..feea3911b2 100644
--- a/platform/windows/crash_handler_win.cpp
+++ b/platform/windows/crash_handler_win.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "main/main.h"
#include "os_windows.h"
+#include "project_settings.h"
#ifdef CRASH_HANDLER_EXCEPTION
diff --git a/platform/windows/detect.py b/platform/windows/detect.py
index 031b397988..fbb02c9d1b 100644
--- a/platform/windows/detect.py
+++ b/platform/windows/detect.py
@@ -44,7 +44,6 @@ def can_build():
if (os.system(mingw64 + test) == 0 or os.system(mingw32 + test) == 0):
return True
- print("Could not detect MinGW. Ensure its binaries are in your PATH or that MINGW32_PREFIX or MINGW64_PREFIX are properly defined.")
return False
@@ -65,7 +64,6 @@ def get_opts():
return [
('mingw_prefix_32', 'MinGW prefix (Win32)', mingw32),
('mingw_prefix_64', 'MinGW prefix (Win64)', mingw64),
- BoolVariable('use_lto', 'Use link time optimization (when using MingW)', False),
EnumVariable('debug_symbols', 'Add debug symbols to release version', 'yes', ('yes', 'no', 'full')),
]
@@ -265,10 +263,7 @@ def configure(env):
if env['use_lto']:
env.Append(CCFLAGS=['-flto'])
- if not env['use_llvm'] and env.GetOption("num_jobs") > 1:
- env.Append(LINKFLAGS=['-flto=' + str(env.GetOption("num_jobs"))])
- else:
- env.Append(LINKFLAGS=['-flto'])
+ env.Append(LINKFLAGS=['-flto=' + str(env.GetOption("num_jobs"))])
## Compile flags
diff --git a/platform/windows/godot_res.rc b/platform/windows/godot_res.rc
index b86869d316..c535a749c0 100644
--- a/platform/windows/godot_res.rc
+++ b/platform/windows/godot_res.rc
@@ -23,13 +23,13 @@ BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "Godot Engine"
- VALUE "FileDescription", _MKSTR(VERSION_NAME) " Editor"
+ VALUE "FileDescription", VERSION_NAME " Editor"
VALUE "FileVersion", _MKSTR(VERSION_MAJOR) "." _MKSTR(VERSION_MINOR) "." _MKSTR(VERSION_PATCH)
- VALUE "ProductName", _MKSTR(VERSION_NAME)
+ VALUE "ProductName", VERSION_NAME
VALUE "Licence", "MIT"
VALUE "LegalCopyright", "Copyright (c) 2007-" _MKSTR(VERSION_YEAR) " Juan Linietsky, Ariel Manzur"
- VALUE "Info", "http://www.godotengine.org"
- VALUE "ProductVersion", _MKSTR(VERSION_MAJOR) "." _MKSTR(VERSION_MINOR) PATCH_STRING "." _MKSTR(VERSION_REVISION)
+ VALUE "Info", "https://godotengine.org"
+ VALUE "ProductVersion", _MKSTR(VERSION_MAJOR) "." _MKSTR(VERSION_MINOR) PATCH_STRING "." VERSION_BUILD
END
END
BLOCK "VarFileInfo"
diff --git a/platform/windows/key_mapping_win.cpp b/platform/windows/key_mapping_win.cpp
index 57f8e965de..76bb5d5723 100644
--- a/platform/windows/key_mapping_win.cpp
+++ b/platform/windows/key_mapping_win.cpp
@@ -50,7 +50,7 @@ static _WinTranslatePair _vk_to_keycode[] = {
{ KEY_CONTROL, VK_CONTROL }, //(0x11)
- { KEY_MENU, VK_MENU }, //(0x12)
+ { KEY_ALT, VK_MENU }, //(0x12)
{ KEY_PAUSE, VK_PAUSE }, //(0x13)
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index bee8c90ad3..c189b3b744 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -42,12 +42,12 @@
#include "lang_table.h"
#include "main/main.h"
#include "packet_peer_udp_winsock.h"
-#include "project_settings.h"
#include "servers/audio_server.h"
#include "servers/visual/visual_server_raster.h"
#include "servers/visual/visual_server_wrap_mt.h"
#include "stream_peer_winsock.h"
#include "tcp_server_winsock.h"
+#include "version_generated.gen.h"
#include "windows_terminal_logger.h"
#include <process.h>
@@ -144,12 +144,7 @@ int OS_Windows::get_video_driver_count() const {
}
const char *OS_Windows::get_video_driver_name(int p_driver) const {
- return "GLES2";
-}
-
-OS::VideoMode OS_Windows::get_default_video_mode() const {
-
- return VideoMode(1024, 600, false);
+ return "GLES3";
}
int OS_Windows::get_audio_driver_count() const {
@@ -206,13 +201,6 @@ void OS_Windows::initialize_core() {
cursor_shape = CURSOR_ARROW;
}
-void OS_Windows::initialize_logger() {
- Vector<Logger *> loggers;
- loggers.push_back(memnew(WindowsTerminalLogger));
- loggers.push_back(memnew(RotatedFileLogger("user://logs/log.txt")));
- _set_logger(memnew(CompositeLogger(loggers)));
-}
-
bool OS_Windows::can_draw() const {
return !minimized;
@@ -1056,12 +1044,6 @@ void OS_Windows::initialize(const VideoMode &p_desired, int p_video_driver, int
visual_server = memnew(VisualServerWrapMT(visual_server, get_render_thread_mode() == RENDER_SEPARATE_THREAD));
}
- physics_server = memnew(PhysicsServerSW);
- physics_server->init();
-
- physics_2d_server = Physics2DServerWrapMT::init_server<Physics2DServerSW>();
- physics_2d_server->init();
-
if (!is_no_window_mode_enabled()) {
ShowWindow(hWnd, SW_SHOW); // Show The Window
SetForegroundWindow(hWnd); // Slightly Higher Priority
@@ -1100,7 +1082,7 @@ void OS_Windows::initialize(const VideoMode &p_desired, int p_video_driver, int
//RegisterTouchWindow(hWnd, 0); // Windows 7
- _ensure_data_dir();
+ _ensure_user_data_dir();
DragAcceptFiles(hWnd, true);
@@ -1223,12 +1205,6 @@ void OS_Windows::finalize() {
memdelete(debugger_connection_console);
}
*/
-
- physics_server->finish();
- memdelete(physics_server);
-
- physics_2d_server->finish();
- memdelete(physics_2d_server);
}
void OS_Windows::finalize_core() {
@@ -1812,7 +1788,7 @@ void OS_Windows::set_cursor_shape(CursorShape p_shape) {
cursor_shape = p_shape;
}
-Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, String *r_pipe, int *r_exitcode) {
+Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, String *r_pipe, int *r_exitcode, bool read_stderr) {
if (p_blocking && r_pipe) {
@@ -2147,6 +2123,43 @@ MainLoop *OS_Windows::get_main_loop() const {
return main_loop;
}
+String OS_Windows::get_config_path() const {
+
+ if (has_environment("XDG_CONFIG_HOME")) { // unlikely, but after all why not?
+ return get_environment("XDG_CONFIG_HOME");
+ } else if (has_environment("APPDATA")) {
+ return get_environment("APPDATA");
+ } else {
+ return ".";
+ }
+}
+
+String OS_Windows::get_data_path() const {
+
+ if (has_environment("XDG_DATA_HOME")) {
+ return get_environment("XDG_DATA_HOME");
+ } else {
+ return get_config_path();
+ }
+}
+
+String OS_Windows::get_cache_path() const {
+
+ if (has_environment("XDG_CACHE_HOME")) {
+ return get_environment("XDG_CACHE_HOME");
+ } else if (has_environment("TEMP")) {
+ return get_environment("TEMP");
+ } else {
+ return get_config_path();
+ }
+}
+
+// Get properly capitalized engine name for system paths
+String OS_Windows::get_godot_dir_name() const {
+
+ return String(VERSION_SHORT_NAME).capitalize();
+}
+
String OS_Windows::get_system_dir(SystemDir p_dir) const {
int id;
@@ -2183,18 +2196,17 @@ String OS_Windows::get_system_dir(SystemDir p_dir) const {
ERR_FAIL_COND_V(res != S_OK, String());
return String(szPath);
}
-String OS_Windows::get_data_dir() const {
- String an = get_safe_application_name();
- if (an != "") {
+String OS_Windows::get_user_data_dir() const {
- if (has_environment("APPDATA")) {
+ String appname = get_safe_application_name();
+ if (appname != "") {
- bool use_godot = ProjectSettings::get_singleton()->get("application/config/use_shared_user_dir");
- if (!use_godot)
- return (OS::get_singleton()->get_environment("APPDATA") + "/" + an).replace("\\", "/");
- else
- return (OS::get_singleton()->get_environment("APPDATA") + "/Godot/app_userdata/" + an).replace("\\", "/");
+ bool use_godot_dir = ProjectSettings::get_singleton()->get("application/config/use_shared_user_dir");
+ if (use_godot_dir) {
+ return get_data_path().plus_file(get_godot_dir_name()).plus_file("app_userdata").plus_file(appname).replace("\\", "/");
+ } else {
+ return get_data_path().plus_file(appname).replace("\\", "/");
}
}
@@ -2305,7 +2317,9 @@ OS_Windows::OS_Windows(HINSTANCE _hInstance) {
AudioDriverManager::add_driver(&driver_xaudio2);
#endif
- _set_logger(memnew(WindowsTerminalLogger));
+ Vector<Logger *> loggers;
+ loggers.push_back(memnew(WindowsTerminalLogger));
+ _set_logger(memnew(CompositeLogger(loggers)));
}
OS_Windows::~OS_Windows() {
diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h
index 9560bc61ca..4367297262 100644
--- a/platform/windows/os_windows.h
+++ b/platform/windows/os_windows.h
@@ -29,8 +29,8 @@
/*************************************************************************/
#ifndef OS_WINDOWS_H
#define OS_WINDOWS_H
-
#include "context_gl_win.h"
+#include "core/project_settings.h"
#include "crash_handler_win.h"
#include "drivers/rtaudio/audio_driver_rtaudio.h"
#include "drivers/wasapi/audio_driver_wasapi.h"
@@ -38,7 +38,6 @@
#include "os/os.h"
#include "power_windows.h"
#include "servers/audio_server.h"
-#include "servers/physics/physics_server_sw.h"
#include "servers/visual/rasterizer.h"
#include "servers/visual_server.h"
#ifdef XAUDIO2_ENABLED
@@ -47,8 +46,6 @@
#include "drivers/unix/ip_unix.h"
#include "key_mapping_win.h"
#include "main/input_default.h"
-#include "servers/physics_2d/physics_2d_server_sw.h"
-#include "servers/physics_2d/physics_2d_server_wrap_mt.h"
#include <fcntl.h>
#include <io.h>
@@ -90,8 +87,6 @@ class OS_Windows : public OS {
ContextGL_Win *gl_context;
#endif
VisualServer *visual_server;
- PhysicsServer *physics_server;
- Physics2DServer *physics_2d_server;
int pressrc;
HDC hDC; // Private GDI Device Context
HINSTANCE hInstance; // Holds The Instance Of The Application
@@ -147,12 +142,9 @@ protected:
virtual int get_video_driver_count() const;
virtual const char *get_video_driver_name(int p_driver) const;
- virtual VideoMode get_default_video_mode() const;
-
virtual int get_audio_driver_count() const;
virtual const char *get_audio_driver_name(int p_driver) const;
- virtual void initialize_logger();
virtual void initialize_core();
virtual void initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver);
@@ -240,7 +232,7 @@ public:
virtual void delay_usec(uint32_t p_usec) const;
virtual uint64_t get_ticks_usec() const;
- virtual Error execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id = NULL, String *r_pipe = NULL, int *r_exitcode = NULL);
+ virtual Error execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id = NULL, String *r_pipe = NULL, int *r_exitcode = NULL, bool read_stderr = false);
virtual Error kill(const ProcessID &p_pid);
virtual int get_process_id() const;
@@ -260,8 +252,14 @@ public:
virtual void enable_for_stealing_focus(ProcessID pid);
virtual void move_window_to_foreground();
- virtual String get_data_dir() const;
+
+ virtual String get_config_path() const;
+ virtual String get_data_path() const;
+ virtual String get_cache_path() const;
+ virtual String get_godot_dir_name() const;
+
virtual String get_system_dir(SystemDir p_dir) const;
+ virtual String get_user_data_dir() const;
virtual void release_rendering_thread();
virtual void make_rendering_thread();
diff --git a/platform/x11/context_gl_x11.cpp b/platform/x11/context_gl_x11.cpp
index 0cc9734119..4f9d4a84b9 100644
--- a/platform/x11/context_gl_x11.cpp
+++ b/platform/x11/context_gl_x11.cpp
@@ -30,7 +30,7 @@
#include "context_gl_x11.h"
#ifdef X11_ENABLED
-#if defined(OPENGL_ENABLED) || defined(LEGACYGL_ENABLED)
+#if defined(OPENGL_ENABLED)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
diff --git a/platform/x11/context_gl_x11.h b/platform/x11/context_gl_x11.h
index ba01b51d59..c37bac5e9b 100644
--- a/platform/x11/context_gl_x11.h
+++ b/platform/x11/context_gl_x11.h
@@ -35,7 +35,7 @@
*/
#ifdef X11_ENABLED
-#if defined(OPENGL_ENABLED) || defined(LEGACYGL_ENABLED)
+#if defined(OPENGL_ENABLED)
#include "drivers/gl_context/context_gl.h"
#include "os/os.h"
diff --git a/platform/x11/crash_handler_x11.cpp b/platform/x11/crash_handler_x11.cpp
index 3c54d5cbc2..005a7459f9 100644
--- a/platform/x11/crash_handler_x11.cpp
+++ b/platform/x11/crash_handler_x11.cpp
@@ -33,6 +33,7 @@
#include "main/main.h"
#include "os_x11.h"
+#include "project_settings.h"
#ifdef CRASH_HANDLER_ENABLED
#include <cxxabi.h>
diff --git a/platform/x11/detect.py b/platform/x11/detect.py
index 1f7f67fe10..3d07851c4f 100644
--- a/platform/x11/detect.py
+++ b/platform/x11/detect.py
@@ -52,7 +52,6 @@ def get_opts():
BoolVariable('use_static_cpp', 'Link stdc++ statically', False),
BoolVariable('use_sanitizer', 'Use LLVM compiler address sanitizer', False),
BoolVariable('use_leak_sanitizer', 'Use LLVM compiler memory leaks sanitizer (implies use_sanitizer)', False),
- BoolVariable('use_lto', 'Use link time optimization', False),
BoolVariable('pulseaudio', 'Detect & use pulseaudio', True),
BoolVariable('udev', 'Use udev for gamepad connection callbacks', False),
EnumVariable('debug_symbols', 'Add debug symbols to release version', 'yes', ('yes', 'no', 'full')),
@@ -101,6 +100,10 @@ def configure(env):
## Compiler configuration
+ if 'CXX' in env and 'clang' in env['CXX']:
+ # Convenience check to enforce the use_llvm overrides when CXX is clang(++)
+ env['use_llvm'] = True
+
if env['use_llvm']:
if ('clang++' not in env['CXX']):
env["CC"] = "clang"
@@ -233,12 +236,15 @@ def configure(env):
env.ParseConfig('pkg-config zlib --cflags --libs')
env.Append(CPPPATH=['#platform/x11'])
- env.Append(CPPFLAGS=['-DX11_ENABLED', '-DUNIX_ENABLED', '-DOPENGL_ENABLED', '-DGLES2_ENABLED', '-DGLES_OVER_GL'])
+ env.Append(CPPFLAGS=['-DX11_ENABLED', '-DUNIX_ENABLED', '-DOPENGL_ENABLED', '-DGLES_ENABLED', '-DGLES_OVER_GL'])
env.Append(LIBS=['GL', 'pthread'])
if (platform.system() == "Linux"):
env.Append(LIBS=['dl'])
+ if (platform.system().find("BSD") >= 0):
+ env.Append(LIBS=['execinfo'])
+
## Cross-compilation
if (is64 and env["bits"] == "32"):
diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp
index 041666a594..d1aa129e77 100644
--- a/platform/x11/os_x11.cpp
+++ b/platform/x11/os_x11.cpp
@@ -32,10 +32,13 @@
#include "errno.h"
#include "key_mapping_x11.h"
#include "print_string.h"
-#include "servers/physics/physics_server_sw.h"
#include "servers/visual/visual_server_raster.h"
#include "servers/visual/visual_server_wrap_mt.h"
+
+#ifdef HAVE_MNTENT
#include <mntent.h>
+#endif
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -79,10 +82,6 @@ const char *OS_X11::get_video_driver_name(int p_driver) const {
return "GLES3";
}
-OS::VideoMode OS_X11::get_default_video_mode() const {
- return OS::VideoMode(1024, 600, false);
-}
-
int OS_X11::get_audio_driver_count() const {
return AudioDriverManager::get_driver_count();
}
@@ -235,7 +234,7 @@ void OS_X11::initialize(const VideoMode &p_desired, int p_video_driver, int p_au
// maybe contextgl wants to be in charge of creating the window
//print_line("def videomode "+itos(current_videomode.width)+","+itos(current_videomode.height));
-#if defined(OPENGL_ENABLED) || defined(LEGACYGL_ENABLED)
+#if defined(OPENGL_ENABLED)
context_gl = memnew(ContextGL_X11(x11_display, x11_window, current_videomode, true));
context_gl->initialize();
@@ -251,41 +250,13 @@ void OS_X11::initialize(const VideoMode &p_desired, int p_video_driver, int p_au
visual_server = memnew(VisualServerWrapMT(visual_server, get_render_thread_mode() == RENDER_SEPARATE_THREAD));
}
-
- // borderless fullscreen window mode
- if (current_videomode.fullscreen) {
- // set bypass compositor hint
- Atom bypass_compositor = XInternAtom(x11_display, "_NET_WM_BYPASS_COMPOSITOR", False);
- unsigned long compositing_disable_on = 1;
- XChangeProperty(x11_display, x11_window, bypass_compositor, XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&compositing_disable_on, 1);
-
- // needed for lxde/openbox, possibly others
- Hints hints;
- Atom property;
- hints.flags = 2;
- hints.decorations = 0;
- property = XInternAtom(x11_display, "_MOTIF_WM_HINTS", True);
- XChangeProperty(x11_display, x11_window, property, property, 32, PropModeReplace, (unsigned char *)&hints, 5);
- XMapRaised(x11_display, x11_window);
- XWindowAttributes xwa;
- XGetWindowAttributes(x11_display, DefaultRootWindow(x11_display), &xwa);
- XMoveResizeWindow(x11_display, x11_window, 0, 0, xwa.width, xwa.height);
-
- // code for netwm-compliants
- XEvent xev;
- Atom wm_state = XInternAtom(x11_display, "_NET_WM_STATE", False);
- Atom fullscreen = XInternAtom(x11_display, "_NET_WM_STATE_FULLSCREEN", False);
-
- memset(&xev, 0, sizeof(xev));
- xev.type = ClientMessage;
- xev.xclient.window = x11_window;
- xev.xclient.message_type = wm_state;
- xev.xclient.format = 32;
- xev.xclient.data.l[0] = 1;
- xev.xclient.data.l[1] = fullscreen;
- xev.xclient.data.l[2] = 0;
-
- XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureNotifyMask, &xev);
+ if (current_videomode.maximized) {
+ current_videomode.maximized = false;
+ set_window_maximized(true);
+ // borderless fullscreen window mode
+ } else if (current_videomode.fullscreen) {
+ current_videomode.fullscreen = false;
+ set_window_fullscreen(true);
} else if (current_videomode.borderless_window) {
Hints hints;
Atom property;
@@ -458,12 +429,6 @@ void OS_X11::initialize(const VideoMode &p_desired, int p_video_driver, int p_au
requested = None;
visual_server->init();
- //
- physics_server = memnew(PhysicsServerSW);
- physics_server->init();
- //physics_2d_server = memnew( Physics2DServerSW );
- physics_2d_server = Physics2DServerWrapMT::init_server<Physics2DServerSW>();
- physics_2d_server->init();
input = memnew(InputDefault);
@@ -471,11 +436,20 @@ void OS_X11::initialize(const VideoMode &p_desired, int p_video_driver, int p_au
#ifdef JOYDEV_ENABLED
joypad = memnew(JoypadLinux(input));
#endif
- _ensure_data_dir();
+ _ensure_user_data_dir();
power_manager = memnew(PowerX11);
+
+ XEvent xevent;
+ while (XCheckIfEvent(x11_display, &xevent, _check_window_events, NULL)) {
+ _window_changed(&xevent);
+ }
}
+int OS_X11::_check_window_events(Display *display, XEvent *event, char *arg) {
+ if (event->type == ConfigureNotify) return 1;
+ return 0;
+}
void OS_X11::xim_destroy_callback(::XIM im, ::XPointer client_data,
::XPointer call_data) {
@@ -519,12 +493,6 @@ void OS_X11::finalize() {
memdelete(visual_server);
//memdelete(rasterizer);
- physics_server->finish();
- memdelete(physics_server);
-
- physics_2d_server->finish();
- memdelete(physics_2d_server);
-
memdelete(power_manager);
if (xrandr_handle)
@@ -533,7 +501,7 @@ void OS_X11::finalize() {
XUnmapWindow(x11_display, x11_window);
XDestroyWindow(x11_display, x11_window);
-#if defined(OPENGL_ENABLED) || defined(LEGACYGL_ENABLED)
+#if defined(OPENGL_ENABLED)
memdelete(context_gl);
#endif
for (int i = 0; i < CURSOR_MAX; i++) {
@@ -661,6 +629,9 @@ void OS_X11::get_fullscreen_mode_list(List<VideoMode> *p_list, int p_screen) con
}
void OS_X11::set_wm_fullscreen(bool p_enabled) {
+ if (current_videomode.fullscreen == p_enabled)
+ return;
+
if (p_enabled && !is_window_resizable()) {
// Set the window as resizable to prevent window managers to ignore the fullscreen state flag.
XSizeHints *xsh;
@@ -984,6 +955,9 @@ bool OS_X11::is_window_minimized() const {
}
void OS_X11::set_window_maximized(bool p_enabled) {
+ if (is_window_maximized() == p_enabled)
+ return;
+
// Using EWMH -- Extended Window Manager Hints
XEvent xev;
Atom wm_state = XInternAtom(x11_display, "_NET_WM_STATE", False);
@@ -1430,6 +1404,20 @@ static Atom pick_target_from_atoms(Display *p_disp, Atom p_t1, Atom p_t2, Atom p
return None;
}
+void OS_X11::_window_changed(XEvent *event) {
+
+ if (xic) {
+ // Not portable.
+ set_ime_position(Point2(0, 1));
+ }
+ if ((event->xconfigure.width == current_videomode.width) &&
+ (event->xconfigure.height == current_videomode.height))
+ return;
+
+ current_videomode.width = event->xconfigure.width;
+ current_videomode.height = event->xconfigure.height;
+}
+
void OS_X11::process_xevents() {
//printf("checking events %i\n", XPending(x11_display));
@@ -1511,18 +1499,7 @@ void OS_X11::process_xevents() {
break;
case ConfigureNotify:
- if (xic) {
- // Not portable.
- set_ime_position(Point2(0, 1));
- }
- /* call resizeGLScene only if our window-size changed */
-
- if ((event.xconfigure.width == current_videomode.width) &&
- (event.xconfigure.height == current_videomode.height))
- break;
-
- current_videomode.width = event.xconfigure.width;
- current_videomode.height = event.xconfigure.height;
+ _window_changed(&event);
break;
case ButtonPress:
case ButtonRelease: {
@@ -1939,7 +1916,7 @@ Error OS_X11::shell_open(String p_uri) {
Error ok;
List<String> args;
args.push_back(p_uri);
- ok = execute("/usr/bin/xdg-open", args, false);
+ ok = execute("xdg-open", args, false);
if (ok == OK)
return OK;
ok = execute("gnome-open", args, false);
@@ -1954,6 +1931,39 @@ bool OS_X11::_check_internal_feature_support(const String &p_feature) {
return p_feature == "pc" || p_feature == "s3tc";
}
+String OS_X11::get_config_path() const {
+
+ if (has_environment("XDG_CONFIG_HOME")) {
+ return get_environment("XDG_CONFIG_HOME");
+ } else if (has_environment("HOME")) {
+ return get_environment("HOME").plus_file(".config");
+ } else {
+ return ".";
+ }
+}
+
+String OS_X11::get_data_path() const {
+
+ if (has_environment("XDG_DATA_HOME")) {
+ return get_environment("XDG_DATA_HOME");
+ } else if (has_environment("HOME")) {
+ return get_environment("HOME").plus_file(".local/share");
+ } else {
+ return get_config_path();
+ }
+}
+
+String OS_X11::get_cache_path() const {
+
+ if (has_environment("XDG_CACHE_HOME")) {
+ return get_environment("XDG_CACHE_HOME");
+ } else if (has_environment("HOME")) {
+ return get_environment("HOME").plus_file(".cache");
+ } else {
+ return get_config_path();
+ }
+}
+
String OS_X11::get_system_dir(SystemDir p_dir) const {
String xdgparam;
@@ -2003,7 +2013,7 @@ String OS_X11::get_system_dir(SystemDir p_dir) const {
String pipe;
List<String> arg;
arg.push_back(xdgparam);
- Error err = const_cast<OS_X11 *>(this)->execute("/usr/bin/xdg-user-dir", arg, true, NULL, &pipe);
+ Error err = const_cast<OS_X11 *>(this)->execute("xdg-user-dir", arg, true, NULL, &pipe);
if (err != OK)
return ".";
return pipe.strip_edges();
@@ -2053,7 +2063,7 @@ void OS_X11::alert(const String &p_alert, const String &p_title) {
args.push_back(p_title);
args.push_back(p_alert);
- execute("/usr/bin/xmessage", args, true);
+ execute("xmessage", args, true);
}
void OS_X11::set_icon(const Ref<Image> &p_icon) {
@@ -2182,6 +2192,7 @@ static String get_mountpoint(const String &p_path) {
return "";
}
+#ifdef HAVE_MNTENT
dev_t dev = s.st_dev;
FILE *fd = setmntent("/proc/mounts", "r");
if (!fd) {
@@ -2199,6 +2210,7 @@ static String get_mountpoint(const String &p_path) {
}
endmntent(fd);
+#endif
return "";
}
@@ -2236,17 +2248,49 @@ Error OS_X11::move_to_trash(const String &p_path) {
List<String> args;
args.push_back("-p");
args.push_back(trashcan);
- Error err = execute("/bin/mkdir", args, true);
+ Error err = execute("mkdir", args, true);
if (err == OK) {
List<String> args2;
args2.push_back(p_path);
args2.push_back(trashcan);
- err = execute("/bin/mv", args2, true);
+ err = execute("mv", args2, true);
}
return err;
}
+OS::LatinKeyboardVariant OS_X11::get_latin_keyboard_variant() const {
+
+ XkbDescRec *xkbdesc = XkbAllocKeyboard();
+ ERR_FAIL_COND_V(!xkbdesc, LATIN_KEYBOARD_QWERTY);
+
+ XkbGetNames(x11_display, XkbSymbolsNameMask, xkbdesc);
+ ERR_FAIL_COND_V(!xkbdesc->names, LATIN_KEYBOARD_QWERTY);
+ ERR_FAIL_COND_V(!xkbdesc->names->symbols, LATIN_KEYBOARD_QWERTY);
+
+ char *layout = XGetAtomName(x11_display, xkbdesc->names->symbols);
+ ERR_FAIL_COND_V(!layout, LATIN_KEYBOARD_QWERTY);
+
+ Vector<String> info = String(layout).split("+");
+ ERR_FAIL_INDEX_V(1, info.size(), LATIN_KEYBOARD_QWERTY);
+
+ if (info[1].find("colemak") != -1) {
+ return LATIN_KEYBOARD_COLEMAK;
+ } else if (info[1].find("qwertz") != -1) {
+ return LATIN_KEYBOARD_QWERTZ;
+ } else if (info[1].find("azerty") != -1) {
+ return LATIN_KEYBOARD_AZERTY;
+ } else if (info[1].find("qzerty") != -1) {
+ return LATIN_KEYBOARD_QZERTY;
+ } else if (info[1].find("dvorak") != -1) {
+ return LATIN_KEYBOARD_DVORAK;
+ } else if (info[1].find("neo") != -1) {
+ return LATIN_KEYBOARD_NEO;
+ }
+
+ return LATIN_KEYBOARD_QWERTY;
+}
+
OS_X11::OS_X11() {
#ifdef PULSEAUDIO_ENABLED
diff --git a/platform/x11/os_x11.h b/platform/x11/os_x11.h
index 0d5c272ed4..a74e6ee5f3 100644
--- a/platform/x11/os_x11.h
+++ b/platform/x11/os_x11.h
@@ -42,9 +42,6 @@
#include "main/input_default.h"
#include "power_x11.h"
#include "servers/audio_server.h"
-#include "servers/physics_2d/physics_2d_server_sw.h"
-#include "servers/physics_2d/physics_2d_server_wrap_mt.h"
-#include "servers/physics_server.h"
#include "servers/visual/rasterizer.h"
#include <X11/Xcursor/Xcursor.h>
@@ -94,7 +91,7 @@ class OS_X11 : public OS_Unix {
int xdnd_version;
-#if defined(OPENGL_ENABLED) || defined(LEGACYGL_ENABLED)
+#if defined(OPENGL_ENABLED)
ContextGL_X11 *context_gl;
#endif
//Rasterizer *rasterizer;
@@ -121,10 +118,8 @@ class OS_X11 : public OS_Unix {
uint64_t last_click_ms;
uint32_t last_button_state;
- PhysicsServer *physics_server;
unsigned int get_mouse_button_state(unsigned int p_x11_state);
void get_key_modifier_state(unsigned int p_x11_state, Ref<InputEventWithModifiers> state);
- Physics2DServer *physics_2d_server;
MouseMode mouse_mode;
Point2i center;
@@ -182,7 +177,6 @@ class OS_X11 : public OS_Unix {
protected:
virtual int get_video_driver_count() const;
virtual const char *get_video_driver_name(int p_driver) const;
- virtual VideoMode get_default_video_mode() const;
virtual int get_audio_driver_count() const;
virtual const char *get_audio_driver_name(int p_driver) const;
@@ -193,6 +187,9 @@ protected:
virtual void set_main_loop(MainLoop *p_main_loop);
+ void _window_changed(XEvent *xevent);
+ static int _check_window_events(Display *display, XEvent *xevent, char *arg);
+
public:
virtual String get_name();
@@ -219,6 +216,10 @@ public:
virtual void make_rendering_thread();
virtual void swap_buffers();
+ virtual String get_config_path() const;
+ virtual String get_data_path() const;
+ virtual String get_cache_path() const;
+
virtual String get_system_dir(SystemDir p_dir) const;
virtual Error shell_open(String p_uri);
@@ -275,6 +276,8 @@ public:
virtual Error move_to_trash(const String &p_path);
+ virtual LatinKeyboardVariant get_latin_keyboard_variant() const;
+
OS_X11();
};
diff --git a/scene/2d/animated_sprite.cpp b/scene/2d/animated_sprite.cpp
index c2edb173d7..4865858b7d 100644
--- a/scene/2d/animated_sprite.cpp
+++ b/scene/2d/animated_sprite.cpp
@@ -247,16 +247,16 @@ SpriteFrames::SpriteFrames() {
add_animation(SceneStringNames::get_singleton()->_default);
}
-void AnimatedSprite::edit_set_pivot(const Point2 &p_pivot) {
+void AnimatedSprite::_edit_set_pivot(const Point2 &p_pivot) {
set_offset(p_pivot);
}
-Point2 AnimatedSprite::edit_get_pivot() const {
+Point2 AnimatedSprite::_edit_get_pivot() const {
return get_offset();
}
-bool AnimatedSprite::edit_has_pivot() const {
+bool AnimatedSprite::_edit_use_pivot() const {
return true;
}
@@ -298,10 +298,8 @@ void AnimatedSprite::_validate_property(PropertyInfo &property) const {
property.hint = PROPERTY_HINT_SPRITE_FRAME;
- if (frames->has_animation(animation)) {
+ if (frames->has_animation(animation) && frames->get_frame_count(animation) > 1) {
property.hint_string = "0," + itos(frames->get_frame_count(animation) - 1) + ",1";
- } else {
- property.hint_string = "0,0,0";
}
}
}
@@ -511,17 +509,17 @@ bool AnimatedSprite::is_flipped_v() const {
return vflip;
}
-Rect2 AnimatedSprite::get_item_rect() const {
+Rect2 AnimatedSprite::_edit_get_rect() const {
if (!frames.is_valid() || !frames->has_animation(animation) || frame < 0 || frame >= frames->get_frame_count(animation)) {
- return Node2D::get_item_rect();
+ return Node2D::_edit_get_rect();
}
Ref<Texture> t;
if (animation)
t = frames->get_frame(animation, frame);
if (t.is_null())
- return Node2D::get_item_rect();
+ return Node2D::_edit_get_rect();
Size2i s = t->get_size();
Point2 ofs = offset;
diff --git a/scene/2d/animated_sprite.h b/scene/2d/animated_sprite.h
index 6c660d0381..a8d0db021a 100644
--- a/scene/2d/animated_sprite.h
+++ b/scene/2d/animated_sprite.h
@@ -149,9 +149,9 @@ protected:
virtual void _validate_property(PropertyInfo &property) const;
public:
- virtual void edit_set_pivot(const Point2 &p_pivot);
- virtual Point2 edit_get_pivot() const;
- virtual bool edit_has_pivot() const;
+ virtual void _edit_set_pivot(const Point2 &p_pivot);
+ virtual Point2 _edit_get_pivot() const;
+ virtual bool _edit_use_pivot() const;
void set_sprite_frames(const Ref<SpriteFrames> &p_frames);
Ref<SpriteFrames> get_sprite_frames() const;
@@ -181,7 +181,7 @@ public:
void set_modulate(const Color &p_color);
Color get_modulate() const;
- virtual Rect2 get_item_rect() const;
+ virtual Rect2 _edit_get_rect() const;
virtual String get_configuration_warning() const;
AnimatedSprite();
diff --git a/scene/2d/back_buffer_copy.cpp b/scene/2d/back_buffer_copy.cpp
index 2858ddaad5..e4f52a227a 100644
--- a/scene/2d/back_buffer_copy.cpp
+++ b/scene/2d/back_buffer_copy.cpp
@@ -49,7 +49,7 @@ void BackBufferCopy::_update_copy_mode() {
}
}
-Rect2 BackBufferCopy::get_item_rect() const {
+Rect2 BackBufferCopy::_edit_get_rect() const {
return rect;
}
diff --git a/scene/2d/back_buffer_copy.h b/scene/2d/back_buffer_copy.h
index 2424dd7b19..cfd632d755 100644
--- a/scene/2d/back_buffer_copy.h
+++ b/scene/2d/back_buffer_copy.h
@@ -52,14 +52,14 @@ protected:
static void _bind_methods();
public:
+ Rect2 _edit_get_rect() const;
+
void set_rect(const Rect2 &p_rect);
Rect2 get_rect() const;
void set_copy_mode(CopyMode p_mode);
CopyMode get_copy_mode() const;
- Rect2 get_item_rect() const;
-
BackBufferCopy();
~BackBufferCopy();
};
diff --git a/scene/2d/camera_2d.cpp b/scene/2d/camera_2d.cpp
index 4fcd6893b8..3164344d15 100644
--- a/scene/2d/camera_2d.cpp
+++ b/scene/2d/camera_2d.cpp
@@ -52,7 +52,11 @@ void Camera2D::_update_scroll() {
if (viewport) {
viewport->set_canvas_transform(xform);
}
- get_tree()->call_group_flags(SceneTree::GROUP_CALL_REALTIME, group_name, "_camera_moved", xform);
+
+ Size2 screen_size = viewport->get_visible_rect().size;
+ Point2 screen_offset = (anchor_mode == ANCHOR_MODE_DRAG_CENTER ? (screen_size * 0.5) : Point2());
+
+ get_tree()->call_group_flags(SceneTree::GROUP_CALL_REALTIME, group_name, "_camera_moved", xform, screen_offset);
};
}
@@ -735,8 +739,8 @@ void Camera2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "editor_draw_limits"), "set_limit_drawing_enabled", "is_limit_drawing_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "editor_draw_drag_margin"), "set_margin_drawing_enabled", "is_margin_drawing_enabled");
- BIND_ENUM_CONSTANT(ANCHOR_MODE_DRAG_CENTER);
BIND_ENUM_CONSTANT(ANCHOR_MODE_FIXED_TOP_LEFT);
+ BIND_ENUM_CONSTANT(ANCHOR_MODE_DRAG_CENTER);
}
Camera2D::Camera2D() {
diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp
index d9bb6576d9..66abe1baa8 100644
--- a/scene/2d/canvas_item.cpp
+++ b/scene/2d/canvas_item.cpp
@@ -178,6 +178,12 @@ CanvasItemMaterial::LightMode CanvasItemMaterial::get_light_mode() const {
void CanvasItemMaterial::_validate_property(PropertyInfo &property) const {
}
+RID CanvasItemMaterial::get_shader_rid() const {
+
+ ERR_FAIL_COND_V(!shader_map.has(current_key), RID());
+ return shader_map[current_key].shader;
+}
+
void CanvasItemMaterial::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_blend_mode", "blend_mode"), &CanvasItemMaterial::set_blend_mode);
@@ -300,22 +306,7 @@ void CanvasItem::hide() {
_change_notify("visible");
}
-Variant CanvasItem::edit_get_state() const {
-
- return Variant();
-}
-void CanvasItem::edit_set_state(const Variant &p_state) {
-}
-
-void CanvasItem::edit_set_rect(const Rect2 &p_edit_rect) {
-
- //used by editors, implement at will
-}
-
-void CanvasItem::edit_rotate(float p_rot) {
-}
-
-Size2 CanvasItem::edit_get_minimum_size() const {
+Size2 CanvasItem::_edit_get_minimum_size() const {
return Size2(-1, -1); //no limit
}
@@ -935,15 +926,22 @@ 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);
-
- 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_rect", "rect"), &CanvasItem::edit_set_rect);
- ClassDB::bind_method(D_METHOD("edit_rotate", "degrees"), &CanvasItem::edit_rotate);
-
- ClassDB::bind_method(D_METHOD("get_item_rect"), &CanvasItem::get_item_rect);
- ClassDB::bind_method(D_METHOD("get_item_and_children_rect"), &CanvasItem::get_item_and_children_rect);
- //ClassDB::bind_method(D_METHOD("get_transform"),&CanvasItem::get_transform);
+ 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_use_position"), &CanvasItem::_edit_use_position);
+ ClassDB::bind_method(D_METHOD("_edit_set_rect", "rect"), &CanvasItem::_edit_set_rect);
+ ClassDB::bind_method(D_METHOD("_edit_get_rect"), &CanvasItem::_edit_get_rect);
+ ClassDB::bind_method(D_METHOD("_edit_use_rect"), &CanvasItem::_edit_use_rect);
+ ClassDB::bind_method(D_METHOD("_edit_get_item_and_children_rect"), &CanvasItem::_edit_get_item_and_children_rect);
+ ClassDB::bind_method(D_METHOD("_edit_set_rotation", "degrees"), &CanvasItem::_edit_set_rotation);
+ ClassDB::bind_method(D_METHOD("_edit_get_rotation"), &CanvasItem::_edit_get_rotation);
+ ClassDB::bind_method(D_METHOD("_edit_use_rotation"), &CanvasItem::_edit_use_rotation);
+ ClassDB::bind_method(D_METHOD("_edit_set_pivot", "pivot"), &CanvasItem::_edit_set_pivot);
+ 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("get_canvas_item"), &CanvasItem::get_canvas_item);
@@ -1045,11 +1043,11 @@ void CanvasItem::_bind_methods() {
BIND_ENUM_CONSTANT(BLEND_MODE_MUL);
BIND_ENUM_CONSTANT(BLEND_MODE_PREMULT_ALPHA);
+ BIND_CONSTANT(NOTIFICATION_TRANSFORM_CHANGED);
BIND_CONSTANT(NOTIFICATION_DRAW);
BIND_CONSTANT(NOTIFICATION_VISIBILITY_CHANGED);
BIND_CONSTANT(NOTIFICATION_ENTER_CANVAS);
BIND_CONSTANT(NOTIFICATION_EXIT_CANVAS);
- BIND_CONSTANT(NOTIFICATION_TRANSFORM_CHANGED);
}
Transform2D CanvasItem::get_canvas_transform() const {
@@ -1113,14 +1111,14 @@ int CanvasItem::get_canvas_layer() const {
return 0;
}
-Rect2 CanvasItem::get_item_and_children_rect() const {
+Rect2 CanvasItem::_edit_get_item_and_children_rect() const {
- Rect2 rect = get_item_rect();
+ Rect2 rect = _edit_get_rect();
for (int i = 0; i < get_child_count(); i++) {
CanvasItem *c = Object::cast_to<CanvasItem>(get_child(i));
if (c) {
- Rect2 sir = c->get_transform().xform(c->get_item_and_children_rect());
+ Rect2 sir = c->get_transform().xform(c->_edit_get_item_and_children_rect());
rect = rect.merge(sir);
}
}
diff --git a/scene/2d/canvas_item.h b/scene/2d/canvas_item.h
index 1afbd150a2..c877a94755 100644
--- a/scene/2d/canvas_item.h
+++ b/scene/2d/canvas_item.h
@@ -121,6 +121,8 @@ public:
static void finish_shaders();
static void flush_changes();
+ RID get_shader_rid() const;
+
CanvasItemMaterial();
virtual ~CanvasItemMaterial();
};
@@ -214,11 +216,31 @@ public:
/* EDITOR */
- virtual Variant edit_get_state() const;
- virtual void edit_set_state(const Variant &p_state);
- virtual void edit_set_rect(const Rect2 &p_edit_rect);
- virtual void edit_rotate(float p_rot);
- virtual Size2 edit_get_minimum_size() const;
+ virtual void _edit_set_state(const Dictionary &p_state){};
+ virtual Dictionary _edit_get_state() const { return Dictionary(); };
+
+ // Used to move/select the node
+ virtual void _edit_set_position(const Point2 &p_position){};
+ virtual Point2 _edit_get_position() const { return Point2(); };
+ virtual bool _edit_use_position() const { return false; };
+
+ // Used to resize/move/select the node
+ virtual void _edit_set_rect(const Rect2 &p_rect){};
+ virtual Rect2 _edit_get_rect() const { return Rect2(-32, -32, 64, 64); };
+ Rect2 _edit_get_item_and_children_rect() const;
+ virtual bool _edit_use_rect() const { return false; };
+
+ // Used to rotate the node
+ virtual void _edit_set_rotation(float p_rotation){};
+ virtual float _edit_get_rotation() const { return 0.0; };
+ virtual bool _edit_use_rotation() const { return false; };
+
+ // Used to set a pivot
+ virtual void _edit_set_pivot(const Point2 &p_pivot){};
+ virtual Point2 _edit_get_pivot() const { return Point2(); };
+ virtual bool _edit_use_pivot() const { return false; };
+
+ virtual Size2 _edit_get_minimum_size() const;
/* VISIBILITY */
@@ -248,7 +270,7 @@ public:
void draw_circle(const Point2 &p_pos, float p_radius, const Color &p_color);
void draw_texture(const Ref<Texture> &p_texture, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1, 1), const Ref<Texture> &p_normal_map = Ref<Texture>());
void draw_texture_rect(const Ref<Texture> &p_texture, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>());
- void draw_texture_rect_region(const Ref<Texture> &p_texture, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>(), bool p_clip_uv = true);
+ void draw_texture_rect_region(const Ref<Texture> &p_texture, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>(), bool p_clip_uv = false);
void draw_style_box(const Ref<StyleBox> &p_style_box, const Rect2 &p_rect);
void draw_primitive(const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, Ref<Texture> p_texture = Ref<Texture>(), float p_width = 1, const Ref<Texture> &p_normal_map = Ref<Texture>());
void draw_polygon(const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), Ref<Texture> p_texture = Ref<Texture>(), const Ref<Texture> &p_normal_map = Ref<Texture>(), bool p_antialiased = false);
@@ -270,14 +292,11 @@ public:
CanvasItem *get_parent_item() const;
- virtual Rect2 get_item_rect() const = 0;
virtual Transform2D get_transform() const = 0;
virtual Transform2D get_global_transform() const;
virtual Transform2D get_global_transform_with_canvas() const;
- Rect2 get_item_and_children_rect() const;
-
CanvasItem *get_toplevel() const;
_FORCE_INLINE_ RID get_canvas_item() const { return canvas_item; }
diff --git a/scene/2d/collision_polygon_2d.cpp b/scene/2d/collision_polygon_2d.cpp
index a840744c78..92855299ae 100644
--- a/scene/2d/collision_polygon_2d.cpp
+++ b/scene/2d/collision_polygon_2d.cpp
@@ -243,7 +243,7 @@ CollisionPolygon2D::BuildMode CollisionPolygon2D::get_build_mode() const {
return build_mode;
}
-Rect2 CollisionPolygon2D::get_item_rect() const {
+Rect2 CollisionPolygon2D::_edit_get_rect() const {
return aabb;
}
diff --git a/scene/2d/collision_polygon_2d.h b/scene/2d/collision_polygon_2d.h
index c9ec860e36..2fb08a4599 100644
--- a/scene/2d/collision_polygon_2d.h
+++ b/scene/2d/collision_polygon_2d.h
@@ -69,7 +69,7 @@ public:
void set_polygon(const Vector<Point2> &p_polygon);
Vector<Point2> get_polygon() const;
- virtual Rect2 get_item_rect() const;
+ virtual Rect2 _edit_get_rect() const;
virtual String get_configuration_warning() const;
diff --git a/scene/2d/collision_shape_2d.cpp b/scene/2d/collision_shape_2d.cpp
index 0758f4a9bf..f7cb5473e3 100644
--- a/scene/2d/collision_shape_2d.cpp
+++ b/scene/2d/collision_shape_2d.cpp
@@ -158,7 +158,7 @@ Ref<Shape2D> CollisionShape2D::get_shape() const {
return shape;
}
-Rect2 CollisionShape2D::get_item_rect() const {
+Rect2 CollisionShape2D::_edit_get_rect() const {
return rect;
}
diff --git a/scene/2d/collision_shape_2d.h b/scene/2d/collision_shape_2d.h
index 04203a75b4..4745c659c8 100644
--- a/scene/2d/collision_shape_2d.h
+++ b/scene/2d/collision_shape_2d.h
@@ -51,9 +51,10 @@ protected:
static void _bind_methods();
public:
+ virtual Rect2 _edit_get_rect() const;
+
void set_shape(const Ref<Shape2D> &p_shape);
Ref<Shape2D> get_shape() const;
- virtual Rect2 get_item_rect() const;
void set_disabled(bool p_disabled);
bool is_disabled() const;
diff --git a/scene/2d/joints_2d.cpp b/scene/2d/joints_2d.cpp
index 69bad1623f..b98cdcc365 100644
--- a/scene/2d/joints_2d.cpp
+++ b/scene/2d/joints_2d.cpp
@@ -33,19 +33,49 @@
#include "physics_body_2d.h"
#include "servers/physics_2d_server.h"
-void Joint2D::_update_joint() {
-
- if (!is_inside_tree())
- return;
+void Joint2D::_update_joint(bool p_only_free) {
if (joint.is_valid()) {
+ if (ba.is_valid() && bb.is_valid())
+ Physics2DServer::get_singleton()->body_remove_collision_exception(ba, bb);
+
Physics2DServer::get_singleton()->free(joint);
+ joint = RID();
+ ba = RID();
+ bb = RID();
}
- joint = RID();
+ if (p_only_free || !is_inside_tree())
+ return;
+
+ Node *node_a = has_node(get_node_a()) ? get_node(get_node_a()) : (Node *)NULL;
+ Node *node_b = has_node(get_node_b()) ? get_node(get_node_b()) : (Node *)NULL;
+
+ if (!node_a || !node_b)
+ return;
+
+ PhysicsBody2D *body_a = Object::cast_to<PhysicsBody2D>(node_a);
+ PhysicsBody2D *body_b = Object::cast_to<PhysicsBody2D>(node_b);
+
+ if (!body_a || !body_b)
+ return;
+
+ if (!body_a) {
+ SWAP(body_a, body_b);
+ }
+
+ joint = _configure_joint(body_a, body_b);
+
+ if (!joint.is_valid())
+ return;
- joint = _configure_joint();
Physics2DServer::get_singleton()->get_singleton()->joint_set_param(joint, Physics2DServer::JOINT_PARAM_BIAS, bias);
+
+ ba = body_a->get_rid();
+ bb = body_b->get_rid();
+
+ if (exclude_from_collision)
+ Physics2DServer::get_singleton()->body_add_collision_exception(body_a->get_rid(), body_b->get_rid());
}
void Joint2D::set_node_a(const NodePath &p_node_a) {
@@ -83,9 +113,7 @@ void Joint2D::_notification(int p_what) {
} break;
case NOTIFICATION_EXIT_TREE: {
if (joint.is_valid()) {
-
- Physics2DServer::get_singleton()->free(joint);
- joint = RID();
+ _update_joint(true);
}
} break;
}
@@ -164,29 +192,8 @@ void PinJoint2D::_notification(int p_what) {
}
}
-RID PinJoint2D::_configure_joint() {
-
- Node *node_a = has_node(get_node_a()) ? get_node(get_node_a()) : (Node *)NULL;
- Node *node_b = has_node(get_node_b()) ? get_node(get_node_b()) : (Node *)NULL;
-
- if (!node_a && !node_b)
- return RID();
+RID PinJoint2D::_configure_joint(PhysicsBody2D *body_a, PhysicsBody2D *body_b) {
- PhysicsBody2D *body_a = Object::cast_to<PhysicsBody2D>(node_a);
- PhysicsBody2D *body_b = Object::cast_to<PhysicsBody2D>(node_b);
-
- if (!body_a && !body_b)
- return RID();
-
- if (!body_a) {
- SWAP(body_a, body_b);
- } else if (body_b) {
- //add a collision exception between both
- if (get_exclude_nodes_from_collision())
- Physics2DServer::get_singleton()->body_add_collision_exception(body_a->get_rid(), body_b->get_rid());
- else
- Physics2DServer::get_singleton()->body_remove_collision_exception(body_a->get_rid(), body_b->get_rid());
- }
RID pj = Physics2DServer::get_singleton()->pin_joint_create(get_global_transform().get_origin(), body_a->get_rid(), body_b ? body_b->get_rid() : RID());
Physics2DServer::get_singleton()->pin_joint_set_param(pj, Physics2DServer::PIN_JOINT_SOFTNESS, softness);
return pj;
@@ -241,24 +248,7 @@ void GrooveJoint2D::_notification(int p_what) {
}
}
-RID GrooveJoint2D::_configure_joint() {
-
- Node *node_a = has_node(get_node_a()) ? get_node(get_node_a()) : (Node *)NULL;
- Node *node_b = has_node(get_node_b()) ? get_node(get_node_b()) : (Node *)NULL;
-
- if (!node_a || !node_b)
- return RID();
-
- PhysicsBody2D *body_a = Object::cast_to<PhysicsBody2D>(node_a);
- PhysicsBody2D *body_b = Object::cast_to<PhysicsBody2D>(node_b);
-
- if (!body_a || !body_b)
- return RID();
-
- if (get_exclude_nodes_from_collision())
- Physics2DServer::get_singleton()->body_add_collision_exception(body_a->get_rid(), body_b->get_rid());
- else
- Physics2DServer::get_singleton()->body_remove_collision_exception(body_a->get_rid(), body_b->get_rid());
+RID GrooveJoint2D::_configure_joint(PhysicsBody2D *body_a, PhysicsBody2D *body_b) {
Transform2D gt = get_global_transform();
Vector2 groove_A1 = gt.get_origin();
@@ -330,24 +320,7 @@ void DampedSpringJoint2D::_notification(int p_what) {
}
}
-RID DampedSpringJoint2D::_configure_joint() {
-
- Node *node_a = has_node(get_node_a()) ? get_node(get_node_a()) : (Node *)NULL;
- Node *node_b = has_node(get_node_b()) ? get_node(get_node_b()) : (Node *)NULL;
-
- if (!node_a || !node_b)
- return RID();
-
- PhysicsBody2D *body_a = Object::cast_to<PhysicsBody2D>(node_a);
- PhysicsBody2D *body_b = Object::cast_to<PhysicsBody2D>(node_b);
-
- if (!body_a || !body_b)
- return RID();
-
- if (get_exclude_nodes_from_collision())
- Physics2DServer::get_singleton()->body_add_collision_exception(body_a->get_rid(), body_b->get_rid());
- else
- Physics2DServer::get_singleton()->body_remove_collision_exception(body_a->get_rid(), body_b->get_rid());
+RID DampedSpringJoint2D::_configure_joint(PhysicsBody2D *body_a, PhysicsBody2D *body_b) {
Transform2D gt = get_global_transform();
Vector2 anchor_A = gt.get_origin();
diff --git a/scene/2d/joints_2d.h b/scene/2d/joints_2d.h
index 685299abc6..a6292be51c 100644
--- a/scene/2d/joints_2d.h
+++ b/scene/2d/joints_2d.h
@@ -32,11 +32,14 @@
#include "node_2d.h"
+class PhysicsBody2D;
+
class Joint2D : public Node2D {
GDCLASS(Joint2D, Node2D);
RID joint;
+ RID ba, bb;
NodePath a;
NodePath b;
@@ -45,10 +48,10 @@ class Joint2D : public Node2D {
bool exclude_from_collision;
protected:
- void _update_joint();
+ void _update_joint(bool p_only_free = false);
void _notification(int p_what);
- virtual RID _configure_joint() = 0;
+ virtual RID _configure_joint(PhysicsBody2D *body_a, PhysicsBody2D *body_b) = 0;
static void _bind_methods();
@@ -77,7 +80,7 @@ class PinJoint2D : public Joint2D {
protected:
void _notification(int p_what);
- virtual RID _configure_joint();
+ virtual RID _configure_joint(PhysicsBody2D *body_a, PhysicsBody2D *body_b);
static void _bind_methods();
public:
@@ -96,7 +99,7 @@ class GrooveJoint2D : public Joint2D {
protected:
void _notification(int p_what);
- virtual RID _configure_joint();
+ virtual RID _configure_joint(PhysicsBody2D *body_a, PhysicsBody2D *body_b);
static void _bind_methods();
public:
@@ -120,7 +123,7 @@ class DampedSpringJoint2D : public Joint2D {
protected:
void _notification(int p_what);
- virtual RID _configure_joint();
+ virtual RID _configure_joint(PhysicsBody2D *body_a, PhysicsBody2D *body_b);
static void _bind_methods();
public:
diff --git a/scene/2d/light_2d.cpp b/scene/2d/light_2d.cpp
index 516acefe2a..d2b987e037 100644
--- a/scene/2d/light_2d.cpp
+++ b/scene/2d/light_2d.cpp
@@ -32,21 +32,21 @@
#include "engine.h"
#include "servers/visual_server.h"
-void Light2D::edit_set_pivot(const Point2 &p_pivot) {
+void Light2D::_edit_set_pivot(const Point2 &p_pivot) {
set_texture_offset(p_pivot);
}
-Point2 Light2D::edit_get_pivot() const {
+Point2 Light2D::_edit_get_pivot() const {
return get_texture_offset();
}
-bool Light2D::edit_has_pivot() const {
+bool Light2D::_edit_use_pivot() const {
return true;
}
-Rect2 Light2D::get_item_rect() const {
+Rect2 Light2D::_edit_get_rect() const {
if (texture.is_null())
return Rect2(0, 0, 1, 1);
diff --git a/scene/2d/light_2d.h b/scene/2d/light_2d.h
index f6bc943adb..9b9da8379f 100644
--- a/scene/2d/light_2d.h
+++ b/scene/2d/light_2d.h
@@ -84,9 +84,10 @@ protected:
static void _bind_methods();
public:
- virtual void edit_set_pivot(const Point2 &p_pivot);
- virtual Point2 edit_get_pivot() const;
- virtual bool edit_has_pivot() const;
+ virtual void _edit_set_pivot(const Point2 &p_pivot);
+ virtual Point2 _edit_get_pivot() const;
+ virtual bool _edit_use_pivot() const;
+ virtual Rect2 _edit_get_rect() const;
void set_enabled(bool p_enabled);
bool is_enabled() const;
@@ -151,8 +152,6 @@ public:
void set_shadow_smooth(float p_amount);
float get_shadow_smooth() const;
- virtual Rect2 get_item_rect() const;
-
String get_configuration_warning() const;
Light2D();
diff --git a/scene/2d/navigation_polygon.cpp b/scene/2d/navigation_polygon.cpp
index 352ec3b300..c53241e985 100644
--- a/scene/2d/navigation_polygon.cpp
+++ b/scene/2d/navigation_polygon.cpp
@@ -329,7 +329,7 @@ void NavigationPolygonInstance::_notification(int p_what) {
break;
}
- c = Object::cast_to<Node2D>(get_parent());
+ c = Object::cast_to<Node2D>(c->get_parent());
}
} break;
@@ -452,7 +452,7 @@ String NavigationPolygonInstance::get_configuration_warning() const {
return String();
}
- c = Object::cast_to<Node2D>(get_parent());
+ c = Object::cast_to<Node2D>(c->get_parent());
}
return TTR("NavigationPolygonInstance must be a child or grandchild to a Navigation2D node. It only provides navigation data.");
diff --git a/scene/2d/node_2d.cpp b/scene/2d/node_2d.cpp
index e62b59dd4d..45f780e50e 100644
--- a/scene/2d/node_2d.cpp
+++ b/scene/2d/node_2d.cpp
@@ -34,45 +34,39 @@
#include "scene/main/viewport.h"
#include "servers/visual_server.h"
-void Node2D::edit_set_pivot(const Point2 &p_pivot) {
-}
-
-Point2 Node2D::edit_get_pivot() const {
-
- return Point2();
-}
-bool Node2D::edit_has_pivot() const {
+Dictionary Node2D::_edit_get_state() const {
- return false;
-}
-
-Variant Node2D::edit_get_state() const {
-
- Array state;
- state.push_back(get_position());
- state.push_back(get_rotation());
- state.push_back(get_scale());
+ Dictionary state;
+ state["position"] = get_position();
+ state["rotation"] = get_rotation();
+ state["scale"] = get_scale();
return state;
}
-void Node2D::edit_set_state(const Variant &p_state) {
+void Node2D::_edit_set_state(const Dictionary &p_state) {
- Array state = p_state;
- ERR_FAIL_COND(state.size() != 3);
+ Dictionary state = p_state;
+ pos = state["position"];
+ angle = state["rotation"];
+ _scale = state["scale"];
- pos = state[0];
- angle = state[1];
- _scale = state[2];
_update_transform();
_change_notify("rotation");
- _change_notify("rotation_deg");
+ _change_notify("rotation_degrees");
_change_notify("scale");
_change_notify("position");
}
-void Node2D::edit_set_rect(const Rect2 &p_edit_rect) {
+void Node2D::_edit_set_position(const Point2 &p_position) {
+ pos = p_position;
+}
- Rect2 r = get_item_rect();
+Point2 Node2D::_edit_get_position() const {
+ return pos;
+}
+
+void Node2D::_edit_set_rect(const Rect2 &p_edit_rect) {
+ Rect2 r = _edit_get_rect();
Vector2 zero_offset;
if (r.size.x != 0)
@@ -101,12 +95,23 @@ void Node2D::edit_set_rect(const Rect2 &p_edit_rect) {
_change_notify("position");
}
-void Node2D::edit_rotate(float p_rot) {
+bool Node2D::_edit_use_rect() const {
+ return true;
+}
- angle += p_rot;
+void Node2D::_edit_set_rotation(float p_rotation) {
+ angle = p_rotation;
_update_transform();
_change_notify("rotation");
- _change_notify("rotation_deg");
+ _change_notify("rotation_degrees");
+}
+
+float Node2D::_edit_get_rotation() const {
+ return angle;
+}
+
+bool Node2D::_edit_use_rotation() const {
+ return true;
}
void Node2D::_update_xform_values() {
@@ -147,22 +152,14 @@ void Node2D::set_rotation(float p_radians) {
angle = p_radians;
_update_transform();
_change_notify("rotation");
- _change_notify("rotation_deg");
+ _change_notify("rotation_degrees");
}
-void Node2D::set_rotation_in_degrees(float p_degrees) {
+void Node2D::set_rotation_degrees(float p_degrees) {
set_rotation(Math::deg2rad(p_degrees));
}
-// Kept for compatibility after rename to set_rotd.
-// Could be removed after a couple releases.
-void Node2D::_set_rotd(float p_degrees) {
-
- WARN_PRINT("Deprecated method Node2D._set_rotd(): This method was renamed to set_rotd. Please adapt your code accordingly, as the old method will be obsoleted.");
- set_rotation_in_degrees(p_degrees);
-}
-
void Node2D::set_scale(const Size2 &p_scale) {
if (_xform_dirty)
@@ -182,23 +179,19 @@ Point2 Node2D::get_position() const {
((Node2D *)this)->_update_xform_values();
return pos;
}
+
float Node2D::get_rotation() const {
if (_xform_dirty)
((Node2D *)this)->_update_xform_values();
return angle;
}
-float Node2D::get_rotation_in_degrees() const {
+
+float Node2D::get_rotation_degrees() const {
return Math::rad2deg(get_rotation());
}
-// Kept for compatibility after rename to get_rotd.
-// Could be removed after a couple releases.
-float Node2D::_get_rotd() const {
- WARN_PRINT("Deprecated method Node2D._get_rotd(): This method was renamed to get_rotd. Please adapt your code accordingly, as the old method will be obsoleted.");
- return get_rotation_in_degrees();
-}
Size2 Node2D::get_scale() const {
if (_xform_dirty)
((Node2D *)this)->_update_xform_values();
@@ -217,17 +210,6 @@ Transform2D Node2D::get_transform() const {
return _mat;
}
-Rect2 Node2D::get_item_rect() const {
-
- if (get_script_instance()) {
- Variant::CallError err;
- Rect2 r = get_script_instance()->call("_get_item_rect", NULL, 0, err);
- if (err.error == Variant::CallError::CALL_OK)
- return r;
- }
- return Rect2(Point2(-32, -32), Size2(64, 64));
-}
-
void Node2D::rotate(float p_radians) {
set_rotation(get_rotation() + p_radians);
@@ -299,12 +281,12 @@ void Node2D::set_global_rotation(float p_radians) {
}
}
-float Node2D::get_global_rotation_in_degrees() const {
+float Node2D::get_global_rotation_degrees() const {
return Math::rad2deg(get_global_rotation());
}
-void Node2D::set_global_rotation_in_degrees(float p_degrees) {
+void Node2D::set_global_rotation_degrees(float p_degrees) {
set_global_rotation(Math::deg2rad(p_degrees));
}
@@ -410,18 +392,14 @@ Point2 Node2D::to_global(Point2 p_local) const {
void Node2D::_bind_methods() {
- // TODO: Obsolete those two methods (old name) properly (GH-4397)
- ClassDB::bind_method(D_METHOD("_get_rotd"), &Node2D::_get_rotd);
- ClassDB::bind_method(D_METHOD("_set_rotd", "degrees"), &Node2D::_set_rotd);
-
ClassDB::bind_method(D_METHOD("set_position", "position"), &Node2D::set_position);
ClassDB::bind_method(D_METHOD("set_rotation", "radians"), &Node2D::set_rotation);
- ClassDB::bind_method(D_METHOD("set_rotation_in_degrees", "degrees"), &Node2D::set_rotation_in_degrees);
+ ClassDB::bind_method(D_METHOD("set_rotation_degrees", "degrees"), &Node2D::set_rotation_degrees);
ClassDB::bind_method(D_METHOD("set_scale", "scale"), &Node2D::set_scale);
ClassDB::bind_method(D_METHOD("get_position"), &Node2D::get_position);
ClassDB::bind_method(D_METHOD("get_rotation"), &Node2D::get_rotation);
- ClassDB::bind_method(D_METHOD("get_rotation_in_degrees"), &Node2D::get_rotation_in_degrees);
+ ClassDB::bind_method(D_METHOD("get_rotation_degrees"), &Node2D::get_rotation_degrees);
ClassDB::bind_method(D_METHOD("get_scale"), &Node2D::get_scale);
ClassDB::bind_method(D_METHOD("rotate", "radians"), &Node2D::rotate);
@@ -435,8 +413,8 @@ void Node2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_global_position"), &Node2D::get_global_position);
ClassDB::bind_method(D_METHOD("set_global_rotation", "radians"), &Node2D::set_global_rotation);
ClassDB::bind_method(D_METHOD("get_global_rotation"), &Node2D::get_global_rotation);
- ClassDB::bind_method(D_METHOD("set_global_rotation_in_degrees", "degrees"), &Node2D::set_global_rotation_in_degrees);
- ClassDB::bind_method(D_METHOD("get_global_rotation_in_degrees"), &Node2D::get_global_rotation_in_degrees);
+ ClassDB::bind_method(D_METHOD("set_global_rotation_degrees", "degrees"), &Node2D::set_global_rotation_degrees);
+ ClassDB::bind_method(D_METHOD("get_global_rotation_degrees"), &Node2D::get_global_rotation_degrees);
ClassDB::bind_method(D_METHOD("set_global_scale", "scale"), &Node2D::set_global_scale);
ClassDB::bind_method(D_METHOD("get_global_scale"), &Node2D::get_global_scale);
@@ -455,20 +433,18 @@ void Node2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_z_as_relative", "enable"), &Node2D::set_z_as_relative);
ClassDB::bind_method(D_METHOD("is_z_relative"), &Node2D::is_z_relative);
- ClassDB::bind_method(D_METHOD("edit_set_pivot", "pivot"), &Node2D::edit_set_pivot);
-
ClassDB::bind_method(D_METHOD("get_relative_transform_to_parent", "parent"), &Node2D::get_relative_transform_to_parent);
ADD_GROUP("Transform", "");
ADD_PROPERTYNZ(PropertyInfo(Variant::VECTOR2, "position"), "set_position", "get_position");
ADD_PROPERTYNZ(PropertyInfo(Variant::REAL, "rotation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_rotation", "get_rotation");
- ADD_PROPERTYNZ(PropertyInfo(Variant::REAL, "rotation_deg", PROPERTY_HINT_RANGE, "-1440,1440,0.1", PROPERTY_USAGE_EDITOR), "set_rotation_in_degrees", "get_rotation_in_degrees");
+ ADD_PROPERTYNZ(PropertyInfo(Variant::REAL, "rotation_degrees", PROPERTY_HINT_RANGE, "-1440,1440,0.1", PROPERTY_USAGE_EDITOR), "set_rotation_degrees", "get_rotation_degrees");
ADD_PROPERTYNO(PropertyInfo(Variant::VECTOR2, "scale"), "set_scale", "get_scale");
ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "transform", PROPERTY_HINT_NONE, "", 0), "set_transform", "get_transform");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "global_position", PROPERTY_HINT_NONE, "", 0), "set_global_position", "get_global_position");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "global_rotation", PROPERTY_HINT_NONE, "", 0), "set_global_rotation", "get_global_rotation");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "global_rotation_deg", PROPERTY_HINT_NONE, "", 0), "set_global_rotation_in_degrees", "get_global_rotation_in_degrees");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "global_rotation_degrees", PROPERTY_HINT_NONE, "", 0), "set_global_rotation_degrees", "get_global_rotation_degrees");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "global_scale", PROPERTY_HINT_NONE, "", 0), "set_global_scale", "get_global_scale");
ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "global_transform", PROPERTY_HINT_NONE, "", 0), "set_global_transform", "get_global_transform");
diff --git a/scene/2d/node_2d.h b/scene/2d/node_2d.h
index 19aafc81ff..e1e07f2895 100644
--- a/scene/2d/node_2d.h
+++ b/scene/2d/node_2d.h
@@ -48,10 +48,6 @@ class Node2D : public CanvasItem {
void _update_transform();
- // Deprecated, should be removed in a future version.
- void _set_rotd(float p_degrees);
- float _get_rotd() const;
-
void _update_xform_values();
protected:
@@ -60,17 +56,20 @@ protected:
static void _bind_methods();
public:
- virtual Variant edit_get_state() const;
- virtual void edit_set_state(const Variant &p_state);
- virtual void edit_set_rect(const Rect2 &p_edit_rect);
- virtual void edit_rotate(float p_rot);
- virtual void edit_set_pivot(const Point2 &p_pivot);
- virtual Point2 edit_get_pivot() const;
- virtual bool edit_has_pivot() const;
+ virtual Dictionary _edit_get_state() const;
+ virtual void _edit_set_state(const Dictionary &p_state);
+
+ virtual void _edit_set_position(const Point2 &p_position);
+ virtual Point2 _edit_get_position() const;
+ virtual void _edit_set_rect(const Rect2 &p_edit_rect);
+ virtual bool _edit_use_rect() const;
+ virtual void _edit_set_rotation(float p_rotation);
+ virtual float _edit_get_rotation() const;
+ virtual bool _edit_use_rotation() const;
void set_position(const Point2 &p_pos);
void set_rotation(float p_radians);
- void set_rotation_in_degrees(float p_degrees);
+ void set_rotation_degrees(float p_degrees);
void set_scale(const Size2 &p_scale);
void rotate(float p_radians);
@@ -82,20 +81,19 @@ public:
Point2 get_position() const;
float get_rotation() const;
- float get_rotation_in_degrees() const;
+ float get_rotation_degrees() const;
Size2 get_scale() const;
Point2 get_global_position() const;
float get_global_rotation() const;
- float get_global_rotation_in_degrees() const;
+ float get_global_rotation_degrees() const;
Size2 get_global_scale() const;
- virtual Rect2 get_item_rect() const;
void set_transform(const Transform2D &p_transform);
void set_global_transform(const Transform2D &p_transform);
void set_global_position(const Point2 &p_pos);
void set_global_rotation(float p_radians);
- void set_global_rotation_in_degrees(float p_degrees);
+ void set_global_rotation_degrees(float p_degrees);
void set_global_scale(const Size2 &p_scale);
void set_z(int p_z);
diff --git a/scene/2d/parallax_background.cpp b/scene/2d/parallax_background.cpp
index 0ddcb7b51b..b9012e37b2 100644
--- a/scene/2d/parallax_background.cpp
+++ b/scene/2d/parallax_background.cpp
@@ -47,10 +47,12 @@ void ParallaxBackground::_notification(int p_what) {
}
}
-void ParallaxBackground::_camera_moved(const Transform2D &p_transform) {
+void ParallaxBackground::_camera_moved(const Transform2D &p_transform, const Point2 &p_screen_offset) {
+
+ screen_offset = p_screen_offset;
- set_scroll_offset(p_transform.get_origin());
set_scroll_scale(p_transform.get_scale().dot(Vector2(0.5, 0.5)));
+ set_scroll_offset(p_transform.get_origin());
}
void ParallaxBackground::set_scroll_scale(float p_scale) {
@@ -106,9 +108,9 @@ void ParallaxBackground::_update_scroll() {
continue;
if (ignore_camera_zoom)
- l->set_base_offset_and_scale(ofs, 1.0);
+ l->set_base_offset_and_scale(ofs, 1.0, screen_offset);
else
- l->set_base_offset_and_scale(ofs, scale);
+ l->set_base_offset_and_scale(ofs, scale, screen_offset);
}
}
diff --git a/scene/2d/parallax_background.h b/scene/2d/parallax_background.h
index 0dad1daeab..e37ec0db99 100644
--- a/scene/2d/parallax_background.h
+++ b/scene/2d/parallax_background.h
@@ -42,6 +42,7 @@ class ParallaxBackground : public CanvasLayer {
float scale;
Point2 base_offset;
Point2 base_scale;
+ Point2 screen_offset;
String group_name;
Point2 limit_begin;
Point2 limit_end;
@@ -51,7 +52,7 @@ class ParallaxBackground : public CanvasLayer {
void _update_scroll();
protected:
- void _camera_moved(const Transform2D &p_transform);
+ void _camera_moved(const Transform2D &p_transform, const Point2 &p_screen_offset);
void _notification(int p_what);
static void _bind_methods();
diff --git a/scene/2d/parallax_layer.cpp b/scene/2d/parallax_layer.cpp
index 8fe651cb5f..4a69841975 100644
--- a/scene/2d/parallax_layer.cpp
+++ b/scene/2d/parallax_layer.cpp
@@ -40,7 +40,7 @@ void ParallaxLayer::set_motion_scale(const Size2 &p_scale) {
if (pb && is_inside_tree()) {
Vector2 ofs = pb->get_final_offset();
float scale = pb->get_scroll_scale();
- set_base_offset_and_scale(ofs, scale);
+ set_base_offset_and_scale(ofs, scale, screen_offset);
}
}
@@ -57,7 +57,7 @@ void ParallaxLayer::set_motion_offset(const Size2 &p_offset) {
if (pb && is_inside_tree()) {
Vector2 ofs = pb->get_final_offset();
float scale = pb->get_scroll_scale();
- set_base_offset_and_scale(ofs, scale);
+ set_base_offset_and_scale(ofs, scale, screen_offset);
}
}
@@ -106,26 +106,28 @@ void ParallaxLayer::_notification(int p_what) {
}
}
-void ParallaxLayer::set_base_offset_and_scale(const Point2 &p_offset, float p_scale) {
+void ParallaxLayer::set_base_offset_and_scale(const Point2 &p_offset, float p_scale, const Point2 &p_screen_offset) {
+ screen_offset = p_screen_offset;
if (!is_inside_tree())
return;
if (Engine::get_singleton()->is_editor_hint())
return;
- Point2 new_ofs = ((orig_offset + p_offset) * motion_scale) * p_scale + motion_offset;
+
+ Point2 new_ofs = (screen_offset + (p_offset - screen_offset) * motion_scale) + motion_offset * p_scale + orig_offset * p_scale;
+
+ Vector2 mirror = Vector2(1, 1);
if (mirroring.x) {
- double den = mirroring.x * p_scale;
- new_ofs.x -= den * ceil(new_ofs.x / den);
+ mirror.x = -1;
}
if (mirroring.y) {
- double den = mirroring.y * p_scale;
- new_ofs.y -= den * ceil(new_ofs.y / den);
+ mirror.y = -1;
}
set_position(new_ofs);
- set_scale(Vector2(1, 1) * p_scale);
+ set_scale(mirror * p_scale * orig_scale);
}
String ParallaxLayer::get_configuration_warning() const {
diff --git a/scene/2d/parallax_layer.h b/scene/2d/parallax_layer.h
index 95ca27c41a..6feb1fad67 100644
--- a/scene/2d/parallax_layer.h
+++ b/scene/2d/parallax_layer.h
@@ -43,6 +43,8 @@ class ParallaxLayer : public Node2D {
Vector2 mirroring;
void _update_mirroring();
+ Point2 screen_offset;
+
protected:
void _notification(int p_what);
static void _bind_methods();
@@ -57,7 +59,7 @@ public:
void set_mirroring(const Size2 &p_mirroring);
Size2 get_mirroring() const;
- void set_base_offset_and_scale(const Point2 &p_offset, float p_scale);
+ void set_base_offset_and_scale(const Point2 &p_offset, float p_scale, const Point2 &p_screen_offset);
virtual String get_configuration_warning() const;
ParallaxLayer();
diff --git a/scene/2d/particles_2d.cpp b/scene/2d/particles_2d.cpp
index c146ac08c2..aee5d89150 100644
--- a/scene/2d/particles_2d.cpp
+++ b/scene/2d/particles_2d.cpp
@@ -77,7 +77,7 @@ void Particles2D::set_randomness_ratio(float p_ratio) {
void Particles2D::set_visibility_rect(const Rect2 &p_aabb) {
visibility_rect = p_aabb;
- Rect3 aabb;
+ AABB aabb;
aabb.position.x = p_aabb.position.x;
aabb.position.y = p_aabb.position.y;
aabb.size.x = p_aabb.size.x;
@@ -223,7 +223,7 @@ String Particles2D::get_configuration_warning() const {
Rect2 Particles2D::capture_rect() const {
- Rect3 aabb = VS::get_singleton()->particles_get_current_aabb(particles);
+ AABB aabb = VS::get_singleton()->particles_get_current_aabb(particles);
Rect2 r;
r.position.x = aabb.position.x;
r.position.y = aabb.position.y;
@@ -378,7 +378,7 @@ void Particles2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "fixed_fps", PROPERTY_HINT_RANGE, "0,1000,1"), "set_fixed_fps", "get_fixed_fps");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fract_delta"), "set_fractional_delta", "get_fractional_delta");
ADD_GROUP("Drawing", "");
- ADD_PROPERTY(PropertyInfo(Variant::RECT3, "visibility_rect"), "set_visibility_rect", "get_visibility_rect");
+ ADD_PROPERTY(PropertyInfo(Variant::AABB, "visibility_rect"), "set_visibility_rect", "get_visibility_rect");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "local_coords"), "set_use_local_coordinates", "get_use_local_coordinates");
ADD_PROPERTY(PropertyInfo(Variant::INT, "draw_order", PROPERTY_HINT_ENUM, "Index,Lifetime"), "set_draw_order", "get_draw_order");
ADD_GROUP("Process Material", "process_");
diff --git a/scene/2d/path_2d.cpp b/scene/2d/path_2d.cpp
index 8413be1ca9..55c055e34f 100644
--- a/scene/2d/path_2d.cpp
+++ b/scene/2d/path_2d.cpp
@@ -107,28 +107,39 @@ void PathFollow2D::_update_transform() {
if (!c.is_valid())
return;
+ if (delta_offset == 0) {
+ return;
+ }
+
float o = offset;
if (loop)
o = Math::fposmod(o, c->get_baked_length());
Vector2 pos = c->interpolate_baked(o, cubic);
+ Vector2 offset = Vector2(h_offset, v_offset);
+
+ Transform2D t = get_transform();
+ t.set_origin(pos);
+
if (rotate) {
- Vector2 n = (c->interpolate_baked(o + lookahead, cubic) - pos).normalized();
- Vector2 t = -n.tangent();
- pos += n * h_offset;
- pos += t * v_offset;
+ Vector2 t_prev = (pos - c->interpolate_baked(o - delta_offset, cubic)).normalized();
+ Vector2 t_cur = (c->interpolate_baked(o + delta_offset, cubic) - pos).normalized();
+
+ float dot = t_prev.dot(t_cur);
+ float angle = Math::acos(CLAMP(dot, -1, 1));
+
+ t.rotate(angle);
- set_rotation(t.angle());
+ t.translate(offset);
} else {
- pos.x += h_offset;
- pos.y += v_offset;
+ t.set_origin(t.get_origin() + offset);
}
- set_position(pos);
+ set_transform(t);
}
void PathFollow2D::_notification(int p_what) {
@@ -176,8 +187,6 @@ bool PathFollow2D::_set(const StringName &p_name, const Variant &p_value) {
set_cubic_interpolation(p_value);
} else if (String(p_name) == "loop") {
set_loop(p_value);
- } else if (String(p_name) == "lookahead") {
- set_lookahead(p_value);
} else
return false;
@@ -200,8 +209,6 @@ bool PathFollow2D::_get(const StringName &p_name, Variant &r_ret) const {
r_ret = cubic;
} else if (String(p_name) == "loop") {
r_ret = loop;
- } else if (String(p_name) == "lookahead") {
- r_ret = lookahead;
} else
return false;
@@ -219,7 +226,6 @@ void PathFollow2D::_get_property_list(List<PropertyInfo> *p_list) const {
p_list->push_back(PropertyInfo(Variant::BOOL, "rotate"));
p_list->push_back(PropertyInfo(Variant::BOOL, "cubic_interp"));
p_list->push_back(PropertyInfo(Variant::BOOL, "loop"));
- p_list->push_back(PropertyInfo(Variant::REAL, "lookahead", PROPERTY_HINT_RANGE, "0.001,1024.0,0.001"));
}
String PathFollow2D::get_configuration_warning() const {
@@ -259,7 +265,7 @@ void PathFollow2D::_bind_methods() {
}
void PathFollow2D::set_offset(float p_offset) {
-
+ delta_offset = p_offset - offset;
offset = p_offset;
if (path)
_update_transform();
@@ -310,16 +316,6 @@ float PathFollow2D::get_unit_offset() const {
return 0;
}
-void PathFollow2D::set_lookahead(float p_lookahead) {
-
- lookahead = p_lookahead;
-}
-
-float PathFollow2D::get_lookahead() const {
-
- return lookahead;
-}
-
void PathFollow2D::set_rotate(bool p_rotate) {
rotate = p_rotate;
@@ -344,11 +340,11 @@ bool PathFollow2D::has_loop() const {
PathFollow2D::PathFollow2D() {
offset = 0;
+ delta_offset = 0;
h_offset = 0;
v_offset = 0;
path = NULL;
rotate = true;
cubic = true;
loop = true;
- lookahead = 4;
}
diff --git a/scene/2d/path_2d.h b/scene/2d/path_2d.h
index 88a0abdea9..f5ba3a3d32 100644
--- a/scene/2d/path_2d.h
+++ b/scene/2d/path_2d.h
@@ -60,9 +60,9 @@ public:
private:
Path2D *path;
real_t offset;
+ real_t delta_offset; // change in offset since last _update_transform
real_t h_offset;
real_t v_offset;
- real_t lookahead;
bool cubic;
bool loop;
bool rotate;
@@ -90,9 +90,6 @@ public:
void set_unit_offset(float p_unit_offset);
float get_unit_offset() const;
- void set_lookahead(float p_lookahead);
- float get_lookahead() const;
-
void set_loop(bool p_loop);
bool has_loop() const;
diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp
index d3b37ae903..1f6127e6eb 100644
--- a/scene/2d/physics_body_2d.cpp
+++ b/scene/2d/physics_body_2d.cpp
@@ -133,8 +133,9 @@ bool PhysicsBody2D::get_collision_layer_bit(int p_bit) const {
}
PhysicsBody2D::PhysicsBody2D(Physics2DServer::BodyMode p_mode)
- : CollisionObject2D(Physics2DServer::get_singleton()->body_create(p_mode), false) {
+ : CollisionObject2D(Physics2DServer::get_singleton()->body_create(), false) {
+ Physics2DServer::get_singleton()->body_set_mode(get_rid(), p_mode);
collision_layer = 1;
collision_mask = 1;
set_pickable(false);
@@ -910,10 +911,10 @@ void RigidBody2D::_bind_methods() {
ADD_SIGNAL(MethodInfo("body_exited", PropertyInfo(Variant::OBJECT, "body")));
ADD_SIGNAL(MethodInfo("sleeping_state_changed"));
- BIND_ENUM_CONSTANT(MODE_STATIC);
- BIND_ENUM_CONSTANT(MODE_KINEMATIC);
BIND_ENUM_CONSTANT(MODE_RIGID);
+ BIND_ENUM_CONSTANT(MODE_STATIC);
BIND_ENUM_CONSTANT(MODE_CHARACTER);
+ BIND_ENUM_CONSTANT(MODE_KINEMATIC);
BIND_ENUM_CONSTANT(CCD_MODE_DISABLED);
BIND_ENUM_CONSTANT(CCD_MODE_CAST_RAY);
@@ -1027,7 +1028,10 @@ Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const
on_floor = true;
floor_velocity = collision.collider_vel;
- if (collision.travel.length() < 1 && ABS((lv.x - floor_velocity.x)) < p_slope_stop_min_velocity) {
+ Vector2 rel_v = lv - floor_velocity;
+ Vector2 hv = rel_v - p_floor_direction * p_floor_direction.dot(rel_v);
+
+ if (collision.travel.length() < 1 && hv.length() < p_slope_stop_min_velocity) {
Transform2D gt = get_global_transform();
gt.elements[2] -= collision.travel;
set_global_transform(gt);
diff --git a/scene/2d/polygon_2d.cpp b/scene/2d/polygon_2d.cpp
index 197c74352e..3f2ad19e51 100644
--- a/scene/2d/polygon_2d.cpp
+++ b/scene/2d/polygon_2d.cpp
@@ -29,7 +29,7 @@
/*************************************************************************/
#include "polygon_2d.h"
-Rect2 Polygon2D::get_item_rect() const {
+Rect2 Polygon2D::_edit_get_rect() const {
if (rect_cache_dirty) {
int l = polygon.size();
@@ -49,16 +49,16 @@ Rect2 Polygon2D::get_item_rect() const {
return item_rect;
}
-void Polygon2D::edit_set_pivot(const Point2 &p_pivot) {
+void Polygon2D::_edit_set_pivot(const Point2 &p_pivot) {
set_offset(p_pivot);
}
-Point2 Polygon2D::edit_get_pivot() const {
+Point2 Polygon2D::_edit_get_pivot() const {
return get_offset();
}
-bool Polygon2D::edit_has_pivot() const {
+bool Polygon2D::_edit_use_pivot() const {
return true;
}
@@ -264,11 +264,11 @@ float Polygon2D::get_texture_rotation() const {
return tex_rot;
}
-void Polygon2D::_set_texture_rotationd(float p_rot) {
+void Polygon2D::set_texture_rotation_degrees(float p_rot) {
set_texture_rotation(Math::deg2rad(p_rot));
}
-float Polygon2D::_get_texture_rotationd() const {
+float Polygon2D::get_texture_rotation_degrees() const {
return Math::rad2deg(get_texture_rotation());
}
@@ -348,8 +348,8 @@ void Polygon2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_texture_rotation", "texture_rotation"), &Polygon2D::set_texture_rotation);
ClassDB::bind_method(D_METHOD("get_texture_rotation"), &Polygon2D::get_texture_rotation);
- ClassDB::bind_method(D_METHOD("_set_texture_rotationd", "texture_rotation"), &Polygon2D::_set_texture_rotationd);
- ClassDB::bind_method(D_METHOD("_get_texture_rotationd"), &Polygon2D::_get_texture_rotationd);
+ ClassDB::bind_method(D_METHOD("set_texture_rotation_degrees", "texture_rotation"), &Polygon2D::set_texture_rotation_degrees);
+ ClassDB::bind_method(D_METHOD("get_texture_rotation_degrees"), &Polygon2D::get_texture_rotation_degrees);
ClassDB::bind_method(D_METHOD("set_texture_scale", "texture_scale"), &Polygon2D::set_texture_scale);
ClassDB::bind_method(D_METHOD("get_texture_scale"), &Polygon2D::get_texture_scale);
@@ -377,7 +377,7 @@ void Polygon2D::_bind_methods() {
ADD_GROUP("Texture", "texture_");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "texture_offset"), "set_texture_offset", "get_texture_offset");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "texture_scale"), "set_texture_scale", "get_texture_scale");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "texture_rotation", PROPERTY_HINT_RANGE, "-1440,1440,0.1"), "_set_texture_rotationd", "_get_texture_rotationd");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "texture_rotation", PROPERTY_HINT_RANGE, "-1440,1440,0.1"), "set_texture_rotation_degrees", "get_texture_rotation_degrees");
ADD_GROUP("Invert", "invert_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "invert_enable"), "set_invert", "get_invert");
diff --git a/scene/2d/polygon_2d.h b/scene/2d/polygon_2d.h
index 20c3324a50..d09e22f5ff 100644
--- a/scene/2d/polygon_2d.h
+++ b/scene/2d/polygon_2d.h
@@ -53,9 +53,6 @@ class Polygon2D : public Node2D {
mutable bool rect_cache_dirty;
mutable Rect2 item_rect;
- void _set_texture_rotationd(float p_rot);
- float _get_texture_rotationd() const;
-
protected:
void _notification(int p_what);
static void _bind_methods();
@@ -82,6 +79,9 @@ public:
void set_texture_rotation(float p_rot);
float get_texture_rotation() const;
+ void set_texture_rotation_degrees(float p_rot);
+ float get_texture_rotation_degrees() const;
+
void set_texture_scale(const Size2 &p_scale);
Size2 get_texture_scale() const;
@@ -99,11 +99,11 @@ public:
//editor stuff
- virtual void edit_set_pivot(const Point2 &p_pivot);
- virtual Point2 edit_get_pivot() const;
- virtual bool edit_has_pivot() const;
+ virtual void _edit_set_pivot(const Point2 &p_pivot);
+ virtual Point2 _edit_get_pivot() const;
+ virtual bool _edit_use_pivot() const;
- virtual Rect2 get_item_rect() const;
+ virtual Rect2 _edit_get_rect() const;
Polygon2D();
};
diff --git a/scene/2d/position_2d.cpp b/scene/2d/position_2d.cpp
index cde665d422..1e729bc179 100644
--- a/scene/2d/position_2d.cpp
+++ b/scene/2d/position_2d.cpp
@@ -38,7 +38,7 @@ void Position2D::_draw_cross() {
draw_line(Point2(0, -10), Point2(0, +10), Color(0.5, 1, 0.5));
}
-Rect2 Position2D::get_item_rect() const {
+Rect2 Position2D::_edit_get_rect() const {
return Rect2(Point2(-10, -10), Size2(20, 20));
}
diff --git a/scene/2d/position_2d.h b/scene/2d/position_2d.h
index af54fb919a..5961e447df 100644
--- a/scene/2d/position_2d.h
+++ b/scene/2d/position_2d.h
@@ -42,7 +42,7 @@ protected:
void _notification(int p_what);
public:
- virtual Rect2 get_item_rect() const;
+ virtual Rect2 _edit_get_rect() const;
Position2D();
};
diff --git a/scene/2d/ray_cast_2d.cpp b/scene/2d/ray_cast_2d.cpp
index b272da46f8..ff23b3183b 100644
--- a/scene/2d/ray_cast_2d.cpp
+++ b/scene/2d/ray_cast_2d.cpp
@@ -46,14 +46,14 @@ Vector2 RayCast2D::get_cast_to() const {
return cast_to;
}
-void RayCast2D::set_collision_layer(uint32_t p_layer) {
+void RayCast2D::set_collision_mask(uint32_t p_mask) {
- collision_layer = p_layer;
+ collision_mask = p_mask;
}
-uint32_t RayCast2D::get_collision_layer() const {
+uint32_t RayCast2D::get_collision_mask() const {
- return collision_layer;
+ return collision_mask;
}
void RayCast2D::set_type_mask(uint32_t p_mask) {
@@ -61,6 +61,21 @@ void RayCast2D::set_type_mask(uint32_t p_mask) {
type_mask = p_mask;
}
+void RayCast2D::set_collision_mask_bit(int p_bit, bool p_value) {
+
+ uint32_t mask = get_collision_mask();
+ if (p_value)
+ mask |= 1 << p_bit;
+ else
+ mask &= ~(1 << p_bit);
+ set_collision_mask(mask);
+}
+
+bool RayCast2D::get_collision_mask_bit(int p_bit) const {
+
+ return get_collision_mask() & (1 << p_bit);
+}
+
uint32_t RayCast2D::get_type_mask() const {
return type_mask;
@@ -203,7 +218,7 @@ void RayCast2D::_update_raycast_state() {
Physics2DDirectSpaceState::RayResult rr;
- if (dss->intersect_ray(gt.get_origin(), gt.xform(to), rr, exclude, collision_layer, type_mask)) {
+ if (dss->intersect_ray(gt.get_origin(), gt.xform(to), rr, exclude, collision_mask, type_mask)) {
collided = true;
against = rr.collider_id;
@@ -276,8 +291,11 @@ void RayCast2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("clear_exceptions"), &RayCast2D::clear_exceptions);
- ClassDB::bind_method(D_METHOD("set_collision_layer", "layer"), &RayCast2D::set_collision_layer);
- ClassDB::bind_method(D_METHOD("get_collision_layer"), &RayCast2D::get_collision_layer);
+ ClassDB::bind_method(D_METHOD("set_collision_mask", "mask"), &RayCast2D::set_collision_mask);
+ ClassDB::bind_method(D_METHOD("get_collision_mask"), &RayCast2D::get_collision_mask);
+
+ ClassDB::bind_method(D_METHOD("set_collision_mask_bit", "bit", "value"), &RayCast2D::set_collision_mask_bit);
+ ClassDB::bind_method(D_METHOD("get_collision_mask_bit", "bit"), &RayCast2D::get_collision_mask_bit);
ClassDB::bind_method(D_METHOD("set_type_mask", "mask"), &RayCast2D::set_type_mask);
ClassDB::bind_method(D_METHOD("get_type_mask"), &RayCast2D::get_type_mask);
@@ -288,7 +306,7 @@ void RayCast2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "exclude_parent"), "set_exclude_parent_body", "get_exclude_parent_body");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "cast_to"), "set_cast_to", "get_cast_to");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_layer", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_collision_layer", "get_collision_layer");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_collision_mask", "get_collision_mask");
ADD_PROPERTY(PropertyInfo(Variant::INT, "type_mask", PROPERTY_HINT_FLAGS, "Static,Kinematic,Rigid,Character,Area"), "set_type_mask", "get_type_mask");
}
@@ -298,7 +316,7 @@ RayCast2D::RayCast2D() {
against = 0;
collided = false;
against_shape = 0;
- collision_layer = 1;
+ collision_mask = 1;
type_mask = Physics2DDirectSpaceState::TYPE_MASK_COLLISION;
cast_to = Vector2(0, 50);
exclude_parent_body = true;
diff --git a/scene/2d/ray_cast_2d.h b/scene/2d/ray_cast_2d.h
index 338de814d2..c13ddfdc58 100644
--- a/scene/2d/ray_cast_2d.h
+++ b/scene/2d/ray_cast_2d.h
@@ -43,7 +43,7 @@ class RayCast2D : public Node2D {
Vector2 collision_point;
Vector2 collision_normal;
Set<RID> exclude;
- uint32_t collision_layer;
+ uint32_t collision_mask;
uint32_t type_mask;
bool exclude_parent_body;
@@ -61,8 +61,11 @@ public:
void set_cast_to(const Vector2 &p_point);
Vector2 get_cast_to() const;
- void set_collision_layer(uint32_t p_layer);
- uint32_t get_collision_layer() const;
+ void set_collision_mask(uint32_t p_mask);
+ uint32_t get_collision_mask() const;
+
+ void set_collision_mask_bit(int p_bit, bool p_value);
+ bool get_collision_mask_bit(int p_bit) const;
void set_type_mask(uint32_t p_mask);
uint32_t get_type_mask() const;
diff --git a/scene/2d/screen_button.cpp b/scene/2d/screen_button.cpp
index bf7c5a3ba4..d5fcda90d5 100644
--- a/scene/2d/screen_button.cpp
+++ b/scene/2d/screen_button.cpp
@@ -133,7 +133,7 @@ void TouchScreenButton::_notification(int p_what) {
return;
if (shape.is_valid()) {
Color draw_col = get_tree()->get_debug_collisions_color();
- Vector2 pos = shape_centered ? get_item_rect().size * 0.5f : Vector2();
+ Vector2 pos = shape_centered ? _edit_get_rect().size * 0.5f : Vector2();
draw_set_transform_matrix(get_canvas_transform().translated(pos));
shape->draw(get_canvas_item(), draw_col);
}
@@ -251,7 +251,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 = get_item_rect();
+ Rect2 item_rect = _edit_get_rect();
bool touched = false;
bool check_rect = true;
@@ -322,13 +322,13 @@ void TouchScreenButton::_release(bool p_exiting_tree) {
}
}
-Rect2 TouchScreenButton::get_item_rect() const {
+Rect2 TouchScreenButton::_edit_get_rect() const {
if (texture.is_null())
return Rect2(0, 0, 1, 1);
/*
if (texture.is_null())
- return CanvasItem::get_item_rect();
+ return CanvasItem::_edit_get_rect();
*/
return Rect2(Size2(), texture->get_size());
diff --git a/scene/2d/screen_button.h b/scene/2d/screen_button.h
index 7647070b26..2e674c20b4 100644
--- a/scene/2d/screen_button.h
+++ b/scene/2d/screen_button.h
@@ -102,7 +102,7 @@ public:
bool is_pressed() const;
- Rect2 get_item_rect() const;
+ Rect2 _edit_get_rect() const;
TouchScreenButton();
};
diff --git a/scene/2d/sprite.cpp b/scene/2d/sprite.cpp
index c53faab5f9..df2265aae9 100644
--- a/scene/2d/sprite.cpp
+++ b/scene/2d/sprite.cpp
@@ -33,16 +33,16 @@
#include "scene/main/viewport.h"
#include "scene/scene_string_names.h"
-void Sprite::edit_set_pivot(const Point2 &p_pivot) {
+void Sprite::_edit_set_pivot(const Point2 &p_pivot) {
set_offset(p_pivot);
}
-Point2 Sprite::edit_get_pivot() const {
+Point2 Sprite::_edit_get_pivot() const {
return get_offset();
}
-bool Sprite::edit_has_pivot() const {
+bool Sprite::_edit_use_pivot() const {
return true;
}
@@ -257,13 +257,13 @@ int Sprite::get_hframes() const {
return hframes;
}
-Rect2 Sprite::get_item_rect() const {
+Rect2 Sprite::_edit_get_rect() const {
if (texture.is_null())
return Rect2(0, 0, 1, 1);
/*
if (texture.is_null())
- return CanvasItem::get_item_rect();
+ return CanvasItem::_edit_get_rect();
*/
Size2i s;
@@ -368,224 +368,3 @@ Sprite::Sprite() {
vframes = 1;
hframes = 1;
}
-
-//////////////////////////// VPSPRITE
-///
-///
-///
-
-#if 0
-void ViewportSprite::edit_set_pivot(const Point2& p_pivot) {
-
- set_offset(p_pivot);
-}
-
-Point2 ViewportSprite::edit_get_pivot() const {
-
- return get_offset();
-}
-bool ViewportSprite::edit_has_pivot() const {
-
- return true;
-}
-
-void ViewportSprite::_notification(int p_what) {
-
- switch(p_what) {
-
- case NOTIFICATION_ENTER_TREE: {
-
- if (!viewport_path.is_empty()) {
-
- Node *n = get_node(viewport_path);
- ERR_FAIL_COND(!n);
- Viewport *vp=Object::cast_to<Viewport>(n);
- ERR_FAIL_COND(!vp);
-
- Ref<RenderTargetTexture> rtt = vp->get_render_target_texture();
- texture=rtt;
- texture->connect("changed",this,"update");
- item_rect_changed();
- }
- } break;
- case NOTIFICATION_EXIT_TREE: {
-
- if (texture.is_valid()) {
-
- texture->disconnect("changed",this,"update");
- texture=Ref<Texture>();
- }
- } break;
- case NOTIFICATION_DRAW: {
-
- if (texture.is_null())
- return;
-
- RID ci = get_canvas_item();
-
- /*
- texture->draw(ci,Point2());
- break;
- */
-
- Size2i s;
- Rect2i src_rect;
-
- s = texture->get_size();
-
- src_rect.size=s;
-
- Point2 ofs=offset;
- if (centered)
- ofs-=s/2;
-
- if (OS::get_singleton()->get_use_pixel_snap()) {
- ofs=ofs.floor();
- }
- Rect2 dst_rect(ofs,s);
- texture->draw_rect_region(ci,dst_rect,src_rect,modulate);
-
- } break;
- }
-}
-
-void ViewportSprite::set_viewport_path(const NodePath& p_viewport) {
-
- viewport_path=p_viewport;
- update();
- if (!is_inside_tree())
- return;
-
- if (texture.is_valid()) {
- texture->disconnect("changed",this,"update");
- texture=Ref<Texture>();
- }
-
- if (viewport_path.is_empty())
- return;
-
-
- Node *n = get_node(viewport_path);
- ERR_FAIL_COND(!n);
- Viewport *vp=Object::cast_to<Viewport>(n);
- ERR_FAIL_COND(!vp);
-
- Ref<RenderTargetTexture> rtt = vp->get_render_target_texture();
- texture=rtt;
-
- if (texture.is_valid()) {
- texture->connect("changed",this,"update");
- }
-
- item_rect_changed();
-
-}
-
-NodePath ViewportSprite::get_viewport_path() const {
-
- return viewport_path;
-}
-
-void ViewportSprite::set_centered(bool p_center) {
-
- centered=p_center;
- update();
- item_rect_changed();
-}
-
-bool ViewportSprite::is_centered() const {
-
- return centered;
-}
-
-void ViewportSprite::set_offset(const Point2& p_offset) {
-
- offset=p_offset;
- update();
- item_rect_changed();
-}
-Point2 ViewportSprite::get_offset() const {
-
- return offset;
-}
-void ViewportSprite::set_modulate(const Color& p_color) {
-
- modulate=p_color;
- update();
-}
-
-Color ViewportSprite::get_modulate() const{
-
- return modulate;
-}
-
-
-Rect2 ViewportSprite::get_item_rect() const {
-
- if (texture.is_null())
- return Rect2(0,0,1,1);
- /*
- if (texture.is_null())
- return CanvasItem::get_item_rect();
- */
-
- Size2i s;
-
- s = texture->get_size();
- Point2 ofs=offset;
- if (centered)
- ofs-=s/2;
-
- if (s==Size2(0,0))
- s=Size2(1,1);
-
- return Rect2(ofs,s);
-}
-
-String ViewportSprite::get_configuration_warning() const {
-
- if (!has_node(viewport_path) || !Object::cast_to<Viewport>(get_node(viewport_path))) {
- return TTR("Path property must point to a valid Viewport node to work. Such Viewport must be set to 'render target' mode.");
- } else {
-
- Node *n = get_node(viewport_path);
- if (n) {
- Viewport *vp = Object::cast_to<Viewport>(n);
- if (!vp->is_set_as_render_target()) {
-
- return TTR("The Viewport set in the path property must be set as 'render target' in order for this sprite to work.");
- }
- }
- }
-
- return String();
-
-}
-
-void ViewportSprite::_bind_methods() {
-
- ClassDB::bind_method(D_METHOD("set_viewport_path","path"),&ViewportSprite::set_viewport_path);
- ClassDB::bind_method(D_METHOD("get_viewport_path"),&ViewportSprite::get_viewport_path);
-
- ClassDB::bind_method(D_METHOD("set_centered","centered"),&ViewportSprite::set_centered);
- ClassDB::bind_method(D_METHOD("is_centered"),&ViewportSprite::is_centered);
-
- ClassDB::bind_method(D_METHOD("set_offset","offset"),&ViewportSprite::set_offset);
- ClassDB::bind_method(D_METHOD("get_offset"),&ViewportSprite::get_offset);
-
- ClassDB::bind_method(D_METHOD("set_modulate","modulate"),&ViewportSprite::set_modulate);
- ClassDB::bind_method(D_METHOD("get_modulate"),&ViewportSprite::get_modulate);
-
- ADD_PROPERTYNZ( PropertyInfo( Variant::NODE_PATH, "viewport"), "set_viewport_path","get_viewport_path");
- ADD_PROPERTYNO( PropertyInfo( Variant::BOOL, "centered"), "set_centered","is_centered");
- ADD_PROPERTYNZ( PropertyInfo( Variant::VECTOR2, "offset"), "set_offset","get_offset");
- ADD_PROPERTYNO( PropertyInfo( Variant::COLOR, "modulate"), "set_modulate","get_modulate");
-
-}
-
-ViewportSprite::ViewportSprite() {
-
- centered=true;
- modulate=Color(1,1,1,1);
-}
-#endif
diff --git a/scene/2d/sprite.h b/scene/2d/sprite.h
index 64d30325f2..1bef73c0a5 100644
--- a/scene/2d/sprite.h
+++ b/scene/2d/sprite.h
@@ -62,9 +62,10 @@ protected:
virtual void _validate_property(PropertyInfo &property) const;
public:
- virtual void edit_set_pivot(const Point2 &p_pivot);
- virtual Point2 edit_get_pivot() const;
- virtual bool edit_has_pivot() const;
+ virtual void _edit_set_pivot(const Point2 &p_pivot);
+ virtual Point2 _edit_get_pivot() const;
+ virtual bool _edit_use_pivot() const;
+ virtual Rect2 _edit_get_rect() const;
void set_texture(const Ref<Texture> &p_texture);
Ref<Texture> get_texture() const;
@@ -102,53 +103,7 @@ public:
void set_hframes(int p_amount);
int get_hframes() const;
- virtual Rect2 get_item_rect() const;
-
Sprite();
};
-#if 0
-class ViewportSprite : public Node2D {
-
- GDCLASS( ViewportSprite, Node2D );
-
- Ref<Texture> texture;
- NodePath viewport_path;
-
- bool centered;
- Point2 offset;
- Color modulate;
-
-protected:
-
- void _notification(int p_what);
-
- static void _bind_methods();
-
-public:
-
- virtual void edit_set_pivot(const Point2& p_pivot);
- virtual Point2 edit_get_pivot() const;
- virtual bool edit_has_pivot() const;
-
- void set_viewport_path(const NodePath& p_viewport);
- NodePath get_viewport_path() const;
-
- void set_centered(bool p_center);
- bool is_centered() const;
-
- void set_offset(const Point2& p_offset);
- Point2 get_offset() const;
-
- void set_modulate(const Color& p_color);
- Color get_modulate() const;
-
- virtual Rect2 get_item_rect() const;
-
- virtual String get_configuration_warning() const;
-
- ViewportSprite();
-};
-
-#endif
#endif // SPRITE_H
diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp
index 4286d88ab1..f067b5a187 100644
--- a/scene/2d/tile_map.cpp
+++ b/scene/2d/tile_map.cpp
@@ -448,21 +448,20 @@ void TileMap::_update_dirty_quadrants() {
if (r == Rect2()) {
tex->draw_rect(canvas_item, rect, false, modulate, c.transpose, normal_map);
} else {
- tex->draw_rect_region(canvas_item, rect, r, modulate, c.transpose, normal_map);
+ tex->draw_rect_region(canvas_item, rect, r, modulate, c.transpose, normal_map, clip_uv);
}
Vector<TileSet::ShapeData> shapes = tile_set->tile_get_shapes(c.id);
for (int i = 0; i < shapes.size(); i++) {
-
Ref<Shape2D> shape = shapes[i].shape;
if (shape.is_valid()) {
Transform2D xform;
xform.set_origin(offset.floor());
- _fix_cell_transform(xform, c, center_ofs, s);
+ Vector2 shape_ofs = tile_set->tile_get_shape_offset(c.id, i);
- xform *= shapes[i].shape_transform;
+ _fix_cell_transform(xform, c, shape_ofs + center_ofs, s);
if (debug_canvas_item.is_valid()) {
vs->canvas_item_add_set_transform(debug_canvas_item, xform);
@@ -587,7 +586,9 @@ Map<TileMap::PosKey, TileMap::Quadrant>::Element *TileMap::_create_quadrant(cons
xform.set_origin(q.pos);
//q.canvas_item = VisualServer::get_singleton()->canvas_item_create();
- q.body = Physics2DServer::get_singleton()->body_create(use_kinematic ? Physics2DServer::BODY_MODE_KINEMATIC : Physics2DServer::BODY_MODE_STATIC);
+ q.body = Physics2DServer::get_singleton()->body_create();
+ Physics2DServer::get_singleton()->body_set_mode(q.body, use_kinematic ? Physics2DServer::BODY_MODE_KINEMATIC : Physics2DServer::BODY_MODE_STATIC);
+
Physics2DServer::get_singleton()->body_attach_object_instance_id(q.body, get_instance_id());
Physics2DServer::get_singleton()->body_set_collision_layer(q.body, collision_layer);
Physics2DServer::get_singleton()->body_set_collision_mask(q.body, collision_mask);
@@ -882,7 +883,7 @@ PoolVector<int> TileMap::_get_tile_data() const {
return data;
}
-Rect2 TileMap::get_item_rect() const {
+Rect2 TileMap::_edit_get_rect() const {
const_cast<TileMap *>(this)->_update_dirty_quadrants();
return rect_cache;
@@ -1234,6 +1235,21 @@ void TileMap::set_light_mask(int p_light_mask) {
}
}
+void TileMap::set_clip_uv(bool p_enable) {
+
+ if (clip_uv == p_enable)
+ return;
+
+ _clear_quadrants();
+ clip_uv = p_enable;
+ _recreate_quadrants();
+}
+
+bool TileMap::get_clip_uv() const {
+
+ return clip_uv;
+}
+
void TileMap::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_tileset", "tileset"), &TileMap::set_tileset);
@@ -1266,6 +1282,9 @@ void TileMap::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_center_y", "enable"), &TileMap::set_center_y);
ClassDB::bind_method(D_METHOD("get_center_y"), &TileMap::get_center_y);
+ ClassDB::bind_method(D_METHOD("set_clip_uv", "enable"), &TileMap::set_clip_uv);
+ ClassDB::bind_method(D_METHOD("get_clip_uv"), &TileMap::get_clip_uv);
+
ClassDB::bind_method(D_METHOD("set_y_sort_mode", "enable"), &TileMap::set_y_sort_mode);
ClassDB::bind_method(D_METHOD("is_y_sort_mode_enabled"), &TileMap::is_y_sort_mode_enabled);
@@ -1327,6 +1346,7 @@ void TileMap::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "cell_half_offset", PROPERTY_HINT_ENUM, "Offset X,Offset Y,Disabled"), "set_half_offset", "get_half_offset");
ADD_PROPERTY(PropertyInfo(Variant::INT, "cell_tile_origin", PROPERTY_HINT_ENUM, "Top Left,Center,Bottom Left"), "set_tile_origin", "get_tile_origin");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "cell_y_sort"), "set_y_sort_mode", "is_y_sort_mode_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "cell_clip_uv"), "set_clip_uv", "get_clip_uv");
ADD_GROUP("Collision", "collision_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collision_use_kinematic", PROPERTY_HINT_NONE, ""), "set_collision_use_kinematic", "get_collision_use_kinematic");
@@ -1377,6 +1397,7 @@ TileMap::TileMap() {
navigation = NULL;
y_sort_mode = false;
occluder_light_mask = 1;
+ clip_uv = false;
fp_adjust = 0.00001;
tile_origin = TILE_ORIGIN_TOP_LEFT;
diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h
index c9d14e09d1..9e14ec838a 100644
--- a/scene/2d/tile_map.h
+++ b/scene/2d/tile_map.h
@@ -161,6 +161,7 @@ private:
bool used_size_cache_dirty;
bool quadrant_order_dirty;
bool y_sort_mode;
+ bool clip_uv;
float fp_adjust;
float friction;
float bounce;
@@ -228,7 +229,7 @@ public:
void set_cellv(const Vector2 &p_pos, int p_tile, bool p_flip_x = false, bool p_flip_y = false, bool p_transpose = false);
int get_cellv(const Vector2 &p_pos) const;
- Rect2 get_item_rect() const;
+ Rect2 _edit_get_rect() const;
void set_collision_layer(uint32_t p_layer);
uint32_t get_collision_layer() const;
@@ -285,6 +286,9 @@ public:
virtual void set_use_parent_material(bool p_use_parent_material);
+ void set_clip_uv(bool p_enable);
+ bool get_clip_uv() const;
+
void clear();
TileMap();
diff --git a/scene/2d/visibility_notifier_2d.cpp b/scene/2d/visibility_notifier_2d.cpp
index ca7b6aa0e4..298bc2649e 100644
--- a/scene/2d/visibility_notifier_2d.cpp
+++ b/scene/2d/visibility_notifier_2d.cpp
@@ -83,7 +83,7 @@ void VisibilityNotifier2D::set_rect(const Rect2 &p_rect) {
_change_notify("rect");
}
-Rect2 VisibilityNotifier2D::get_item_rect() const {
+Rect2 VisibilityNotifier2D::_edit_get_rect() const {
return rect;
}
@@ -341,12 +341,12 @@ void VisibilityEnabler2D::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "process_parent"), "set_enabler", "is_enabler_enabled", ENABLER_PARENT_PROCESS);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "physics_process_parent"), "set_enabler", "is_enabler_enabled", ENABLER_PARENT_PHYSICS_PROCESS);
- BIND_ENUM_CONSTANT(ENABLER_FREEZE_BODIES);
BIND_ENUM_CONSTANT(ENABLER_PAUSE_ANIMATIONS);
+ BIND_ENUM_CONSTANT(ENABLER_FREEZE_BODIES);
BIND_ENUM_CONSTANT(ENABLER_PAUSE_PARTICLES);
- BIND_ENUM_CONSTANT(ENABLER_PAUSE_ANIMATED_SPRITES);
BIND_ENUM_CONSTANT(ENABLER_PARENT_PROCESS);
BIND_ENUM_CONSTANT(ENABLER_PARENT_PHYSICS_PROCESS);
+ BIND_ENUM_CONSTANT(ENABLER_PAUSE_ANIMATED_SPRITES);
BIND_ENUM_CONSTANT(ENABLER_MAX);
}
diff --git a/scene/2d/visibility_notifier_2d.h b/scene/2d/visibility_notifier_2d.h
index ee5152978b..6e06833912 100644
--- a/scene/2d/visibility_notifier_2d.h
+++ b/scene/2d/visibility_notifier_2d.h
@@ -54,13 +54,13 @@ protected:
static void _bind_methods();
public:
+ virtual Rect2 _edit_get_rect() const;
+
void set_rect(const Rect2 &p_rect);
Rect2 get_rect() const;
bool is_on_screen() const;
- virtual Rect2 get_item_rect() const;
-
VisibilityNotifier2D();
};
diff --git a/scene/3d/SCsub b/scene/3d/SCsub
index 72739b527e..4008f4f196 100644
--- a/scene/3d/SCsub
+++ b/scene/3d/SCsub
@@ -7,6 +7,9 @@ if env['disable_3d']:
env.scene_sources.append("3d/spatial.cpp")
env.scene_sources.append("3d/skeleton.cpp")
+ env.scene_sources.append("3d/particles.cpp")
+ env.scene_sources.append("3d/visual_instance.cpp")
+ env.scene_sources.append("3d/scenario_fx.cpp")
else:
env.add_source_files(env.scene_sources, "*.cpp")
diff --git a/scene/3d/arvr_nodes.cpp b/scene/3d/arvr_nodes.cpp
index c6b6c02129..e1e0b9b1ce 100644
--- a/scene/3d/arvr_nodes.cpp
+++ b/scene/3d/arvr_nodes.cpp
@@ -204,7 +204,7 @@ void ARVRController::_notification(int p_what) {
int mask = 1;
// check button states
for (int i = 0; i < 16; i++) {
- bool was_pressed = (button_states && mask) == mask;
+ bool was_pressed = (button_states & mask) == mask;
bool is_pressed = Input::get_singleton()->is_joy_button_pressed(joy_id, i);
if (!was_pressed && is_pressed) {
@@ -231,7 +231,7 @@ void ARVRController::_notification(int p_what) {
void ARVRController::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_controller_id", "controller_id"), &ARVRController::set_controller_id);
ClassDB::bind_method(D_METHOD("get_controller_id"), &ARVRController::get_controller_id);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "controller_id"), "set_controller_id", "get_controller_id");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "controller_id", PROPERTY_HINT_RANGE, "1,32,1"), "set_controller_id", "get_controller_id");
ClassDB::bind_method(D_METHOD("get_controller_name"), &ARVRController::get_controller_name);
// passthroughs to information about our related joystick
@@ -242,6 +242,10 @@ void ARVRController::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_is_active"), &ARVRController::get_is_active);
ClassDB::bind_method(D_METHOD("get_hand"), &ARVRController::get_hand);
+ ClassDB::bind_method(D_METHOD("get_rumble"), &ARVRController::get_rumble);
+ ClassDB::bind_method(D_METHOD("set_rumble", "rumble"), &ARVRController::set_rumble);
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "rumble", PROPERTY_HINT_RANGE, "0.0,1.0,0.01"), "set_rumble", "get_rumble");
+
ADD_SIGNAL(MethodInfo("button_pressed", PropertyInfo(Variant::INT, "button")));
ADD_SIGNAL(MethodInfo("button_release", PropertyInfo(Variant::INT, "button")));
};
@@ -299,6 +303,30 @@ float ARVRController::get_joystick_axis(int p_axis) const {
return Input::get_singleton()->get_joy_axis(joy_id, p_axis);
};
+real_t ARVRController::get_rumble() const {
+ // get our ARVRServer
+ ARVRServer *arvr_server = ARVRServer::get_singleton();
+ ERR_FAIL_NULL_V(arvr_server, 0.0);
+
+ ARVRPositionalTracker *tracker = arvr_server->find_by_type_and_id(ARVRServer::TRACKER_CONTROLLER, controller_id);
+ if (tracker == NULL) {
+ return 0.0;
+ };
+
+ return tracker->get_rumble();
+};
+
+void ARVRController::set_rumble(real_t p_rumble) {
+ // get our ARVRServer
+ ARVRServer *arvr_server = ARVRServer::get_singleton();
+ ERR_FAIL_NULL(arvr_server);
+
+ ARVRPositionalTracker *tracker = arvr_server->find_by_type_and_id(ARVRServer::TRACKER_CONTROLLER, controller_id);
+ if (tracker != NULL) {
+ tracker->set_rumble(p_rumble);
+ };
+};
+
bool ARVRController::get_is_active() const {
return is_active;
};
@@ -336,6 +364,7 @@ String ARVRController::get_configuration_warning() const {
ARVRController::ARVRController() {
controller_id = 0;
is_active = true;
+ button_states = 0;
};
ARVRController::~ARVRController(){
diff --git a/scene/3d/arvr_nodes.h b/scene/3d/arvr_nodes.h
index e0ccfab58b..6e940351f2 100644
--- a/scene/3d/arvr_nodes.h
+++ b/scene/3d/arvr_nodes.h
@@ -89,6 +89,9 @@ public:
int is_button_pressed(int p_button) const;
float get_joystick_axis(int p_axis) const;
+ real_t get_rumble() const;
+ void set_rumble(real_t p_rumble);
+
bool get_is_active() const;
ARVRPositionalTracker::TrackerHand get_hand() const;
diff --git a/scene/3d/audio_stream_player_3d.cpp b/scene/3d/audio_stream_player_3d.cpp
index 3c92814c87..ad1a15f363 100644
--- a/scene/3d/audio_stream_player_3d.cpp
+++ b/scene/3d/audio_stream_player_3d.cpp
@@ -869,7 +869,7 @@ void AudioStreamPlayer3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::REAL, "attenuation_filter_cutoff_hz", PROPERTY_HINT_RANGE, "50,50000,1"), "set_attenuation_filter_cutoff_hz", "get_attenuation_filter_cutoff_hz");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "attenuation_filter_db", PROPERTY_HINT_RANGE, "-80,0,0.1"), "set_attenuation_filter_db", "get_attenuation_filter_db");
ADD_GROUP("Doppler", "doppler_");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "doppler_tracking", PROPERTY_HINT_ENUM, "Disabled,Idle,Fixed"), "set_doppler_tracking", "get_doppler_tracking");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "doppler_tracking", PROPERTY_HINT_ENUM, "Disabled,Idle,Physics"), "set_doppler_tracking", "get_doppler_tracking");
BIND_ENUM_CONSTANT(ATTENUATION_INVERSE_DISTANCE);
BIND_ENUM_CONSTANT(ATTENUATION_INVERSE_SQUARE_DISTANCE);
diff --git a/scene/3d/camera.cpp b/scene/3d/camera.cpp
index 7baf9a9deb..8c7d0c23c3 100644
--- a/scene/3d/camera.cpp
+++ b/scene/3d/camera.cpp
@@ -175,7 +175,7 @@ void Camera::_get_property_list(List<PropertyInfo> *p_list) const {
p_list->push_back(PropertyInfo(Variant::OBJECT, "environment", PROPERTY_HINT_RESOURCE_TYPE, "Environment"));
p_list->push_back(PropertyInfo(Variant::REAL, "h_offset"));
p_list->push_back(PropertyInfo(Variant::REAL, "v_offset"));
- p_list->push_back(PropertyInfo(Variant::INT, "doppler/tracking", PROPERTY_HINT_ENUM, "Disabled,Idle,Fixed"));
+ p_list->push_back(PropertyInfo(Variant::INT, "doppler/tracking", PROPERTY_HINT_ENUM, "Disabled,Idle,Physics"));
}
void Camera::_update_camera() {
diff --git a/scene/3d/collision_polygon.cpp b/scene/3d/collision_polygon.cpp
index 382cbb8f38..a6d812efec 100644
--- a/scene/3d/collision_polygon.cpp
+++ b/scene/3d/collision_polygon.cpp
@@ -117,7 +117,7 @@ Vector<Point2> CollisionPolygon::get_polygon() const {
return polygon;
}
-Rect3 CollisionPolygon::get_item_rect() const {
+AABB CollisionPolygon::get_item_rect() const {
return aabb;
}
@@ -176,7 +176,7 @@ void CollisionPolygon::_bind_methods() {
CollisionPolygon::CollisionPolygon() {
- aabb = Rect3(Vector3(-1, -1, -1), Vector3(2, 2, 2));
+ aabb = AABB(Vector3(-1, -1, -1), Vector3(2, 2, 2));
depth = 1.0;
set_notify_local_transform(true);
parent = NULL;
diff --git a/scene/3d/collision_polygon.h b/scene/3d/collision_polygon.h
index dbed1d7154..14d8c3aba6 100644
--- a/scene/3d/collision_polygon.h
+++ b/scene/3d/collision_polygon.h
@@ -40,7 +40,7 @@ class CollisionPolygon : public Spatial {
protected:
float depth;
- Rect3 aabb;
+ AABB aabb;
Vector<Point2> polygon;
uint32_t owner_id;
@@ -64,7 +64,7 @@ public:
void set_disabled(bool p_disabled);
bool is_disabled() const;
- virtual Rect3 get_item_rect() const;
+ virtual AABB get_item_rect() const;
String get_configuration_warning() const;
diff --git a/scene/3d/gi_probe.cpp b/scene/3d/gi_probe.cpp
index 9d55a82824..05d5d52d28 100644
--- a/scene/3d/gi_probe.cpp
+++ b/scene/3d/gi_probe.cpp
@@ -31,12 +31,12 @@
#include "mesh_instance.h"
-void GIProbeData::set_bounds(const Rect3 &p_bounds) {
+void GIProbeData::set_bounds(const AABB &p_bounds) {
VS::get_singleton()->gi_probe_set_bounds(probe, p_bounds);
}
-Rect3 GIProbeData::get_bounds() const {
+AABB GIProbeData::get_bounds() const {
return VS::get_singleton()->gi_probe_get_bounds(probe);
}
@@ -180,7 +180,7 @@ void GIProbeData::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_compress", "compress"), &GIProbeData::set_compress);
ClassDB::bind_method(D_METHOD("is_compressed"), &GIProbeData::is_compressed);
- ADD_PROPERTY(PropertyInfo(Variant::RECT3, "bounds", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_bounds", "get_bounds");
+ ADD_PROPERTY(PropertyInfo(Variant::AABB, "bounds", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_bounds", "get_bounds");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "cell_size", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_cell_size", "get_cell_size");
ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM, "to_cell_xform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_to_cell_xform", "get_to_cell_xform");
@@ -410,7 +410,7 @@ static bool planeBoxOverlap(Vector3 normal, float d, Vector3 maxbox) {
rad = fa * boxhalfsize.x + fb * boxhalfsize.z; \
if (min > rad || max < -rad) return false;
-/*======================== Z-tests ========================*/
+ /*======================== Z-tests ========================*/
#define AXISTEST_Z12(a, b, fa, fb) \
p1 = a * v1.x - b * v1.y; \
@@ -542,7 +542,7 @@ static _FORCE_INLINE_ Vector2 get_uv(const Vector3 &p_pos, const Vector3 *p_vtx,
return p_uv[0] * u + p_uv[1] * v + p_uv[2] * w;
}
-void GIProbe::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, const Vector3 *p_vtx, const Vector2 *p_uv, const Baker::MaterialCache &p_material, const Rect3 &p_aabb, Baker *p_baker) {
+void GIProbe::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, const Vector3 *p_vtx, const Vector2 *p_uv, const Baker::MaterialCache &p_material, const AABB &p_aabb, Baker *p_baker) {
if (p_level == p_baker->cell_subdiv - 1) {
//plot the face by guessing it's albedo and emission value
@@ -702,7 +702,7 @@ void GIProbe::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, cons
int half = (1 << (p_baker->cell_subdiv - 1)) >> (p_level + 1);
for (int i = 0; i < 8; i++) {
- Rect3 aabb = p_aabb;
+ AABB aabb = p_aabb;
aabb.size *= 0.5;
int nx = p_x;
@@ -726,7 +726,7 @@ void GIProbe::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, cons
continue;
{
- Rect3 test_aabb = aabb;
+ AABB test_aabb = aabb;
//test_aabb.grow_by(test_aabb.get_longest_axis_size()*0.05); //grow a bit to avoid numerical error in real-time
Vector3 qsize = test_aabb.size * 0.5; //quarter size, for fast aabb test
@@ -891,7 +891,7 @@ void GIProbe::_fixup_plot(int p_idx, int p_level, int p_x, int p_y, int p_z, Bak
}
}
-Vector<Color> GIProbe::_get_bake_texture(Ref<Image> p_image, const Color &p_color) {
+Vector<Color> GIProbe::_get_bake_texture(Ref<Image> p_image, const Color &p_color_mul, const Color &p_color_add) {
Vector<Color> ret;
@@ -899,7 +899,7 @@ Vector<Color> GIProbe::_get_bake_texture(Ref<Image> p_image, const Color &p_colo
ret.resize(bake_texture_size * bake_texture_size);
for (int i = 0; i < bake_texture_size * bake_texture_size; i++) {
- ret[i] = p_color;
+ ret[i] = p_color_add;
}
return ret;
@@ -919,9 +919,10 @@ Vector<Color> GIProbe::_get_bake_texture(Ref<Image> p_image, const Color &p_colo
for (int i = 0; i < bake_texture_size * bake_texture_size; i++) {
Color c;
- c.r = (r[i * 4 + 0] / 255.0) * p_color.r;
- c.g = (r[i * 4 + 1] / 255.0) * p_color.g;
- c.b = (r[i * 4 + 2] / 255.0) * p_color.b;
+ c.r = (r[i * 4 + 0] / 255.0) * p_color_mul.r + p_color_add.r;
+ c.g = (r[i * 4 + 1] / 255.0) * p_color_mul.g + p_color_add.g;
+ c.b = (r[i * 4 + 2] / 255.0) * p_color_mul.b + p_color_add.b;
+
c.a = r[i * 4 + 3] / 255.0;
ret[i] = c;
@@ -951,17 +952,15 @@ GIProbe::Baker::MaterialCache GIProbe::_get_material_cache(Ref<Material> p_mater
if (albedo_tex.is_valid()) {
img_albedo = albedo_tex->get_data();
+ mc.albedo = _get_bake_texture(img_albedo, mat->get_albedo(), Color(0, 0, 0)); // albedo texture, color is multiplicative
} else {
+ mc.albedo = _get_bake_texture(img_albedo, Color(1, 1, 1), mat->get_albedo()); // no albedo texture, color is additive
}
- mc.albedo = _get_bake_texture(img_albedo, mat->get_albedo());
-
- Ref<ImageTexture> emission_tex = mat->get_texture(SpatialMaterial::TEXTURE_EMISSION);
+ Ref<Texture> emission_tex = mat->get_texture(SpatialMaterial::TEXTURE_EMISSION);
Color emission_col = mat->get_emission();
- emission_col.r *= mat->get_emission_energy();
- emission_col.g *= mat->get_emission_energy();
- emission_col.b *= mat->get_emission_energy();
+ float emission_energy = mat->get_emission_energy();
Ref<Image> img_emission;
@@ -970,13 +969,17 @@ GIProbe::Baker::MaterialCache GIProbe::_get_material_cache(Ref<Material> p_mater
img_emission = emission_tex->get_data();
}
- mc.emission = _get_bake_texture(img_emission, emission_col);
+ if (mat->get_emission_operator() == SpatialMaterial::EMISSION_OP_ADD) {
+ mc.emission = _get_bake_texture(img_emission, Color(1, 1, 1) * emission_energy, emission_col * emission_energy);
+ } else {
+ mc.emission = _get_bake_texture(img_emission, emission_col * emission_energy, Color(0, 0, 0));
+ }
} else {
Ref<Image> empty;
- mc.albedo = _get_bake_texture(empty, Color(0.7, 0.7, 0.7));
- mc.emission = _get_bake_texture(empty, Color(0, 0, 0));
+ mc.albedo = _get_bake_texture(empty, Color(0, 0, 0), Color(1, 1, 1));
+ mc.emission = _get_bake_texture(empty, Color(0, 0, 0), Color(0, 0, 0));
}
p_baker->material_cache[p_material] = mc;
@@ -1080,11 +1083,11 @@ void GIProbe::_find_meshes(Node *p_at_node, Baker *p_baker) {
Ref<Mesh> mesh = mi->get_mesh();
if (mesh.is_valid()) {
- Rect3 aabb = mesh->get_aabb();
+ AABB aabb = mesh->get_aabb();
Transform xf = get_global_transform().affine_inverse() * mi->get_global_transform();
- if (Rect3(-extents, extents * 2).intersects(xf.xform(aabb))) {
+ if (AABB(-extents, extents * 2).intersects(xf.xform(aabb))) {
Baker::PlotMesh pm;
pm.local_xform = xf;
pm.mesh = mesh;
@@ -1110,11 +1113,11 @@ void GIProbe::_find_meshes(Node *p_at_node, Baker *p_baker) {
if (!mesh.is_valid())
continue;
- Rect3 aabb = mesh->get_aabb();
+ AABB aabb = mesh->get_aabb();
Transform xf = get_global_transform().affine_inverse() * (s->get_global_transform() * mxf);
- if (Rect3(-extents, extents * 2).intersects(xf.xform(aabb))) {
+ if (AABB(-extents, extents * 2).intersects(xf.xform(aabb))) {
Baker::PlotMesh pm;
pm.local_xform = xf;
pm.mesh = mesh;
@@ -1134,6 +1137,10 @@ void GIProbe::_find_meshes(Node *p_at_node, Baker *p_baker) {
}
}
+GIProbe::BakeBeginFunc GIProbe::bake_begin_function = NULL;
+GIProbe::BakeStepFunc GIProbe::bake_step_function = NULL;
+GIProbe::BakeEndFunc GIProbe::bake_end_function = NULL;
+
void GIProbe::bake(Node *p_from_node, bool p_create_visual_debug) {
Baker baker;
@@ -1144,7 +1151,7 @@ void GIProbe::bake(Node *p_from_node, bool p_create_visual_debug) {
baker.bake_cells.resize(1);
//find out the actual real bounds, power of 2, which gets the highest subdivision
- baker.po2_bounds = Rect3(-extents, extents * 2.0);
+ baker.po2_bounds = AABB(-extents, extents * 2.0);
int longest_axis = baker.po2_bounds.get_longest_axis_index();
baker.axis_cell_size[longest_axis] = (1 << (baker.cell_subdiv - 1));
baker.leaf_voxel_count = 0;
@@ -1177,14 +1184,25 @@ void GIProbe::bake(Node *p_from_node, bool p_create_visual_debug) {
_find_meshes(p_from_node ? p_from_node : get_parent(), &baker);
+ if (bake_begin_function) {
+ bake_begin_function(baker.mesh_list.size() + 1);
+ }
+
int pmc = 0;
for (List<Baker::PlotMesh>::Element *E = baker.mesh_list.front(); E; E = E->next()) {
- print_line("plotting mesh " + itos(pmc++) + "/" + itos(baker.mesh_list.size()));
+ if (bake_step_function) {
+ bake_step_function(pmc, RTR("Plotting Meshes") + " " + itos(pmc) + "/" + itos(baker.mesh_list.size()));
+ }
+
+ pmc++;
_plot_mesh(E->get().local_xform, E->get().mesh, &baker, E->get().instance_materials, E->get().override_material);
}
+ if (bake_step_function) {
+ bake_step_function(pmc++, RTR("Finishing Plot"));
+ }
_fixup_plot(0, 0, 0, 0, 0, &baker);
@@ -1268,7 +1286,7 @@ void GIProbe::bake(Node *p_from_node, bool p_create_visual_debug) {
Ref<GIProbeData> probe_data;
probe_data.instance();
- probe_data->set_bounds(Rect3(-extents, extents * 2.0));
+ probe_data->set_bounds(AABB(-extents, extents * 2.0));
probe_data->set_cell_size(baker.po2_bounds.size[longest_axis] / baker.axis_cell_size[longest_axis]);
probe_data->set_dynamic_data(data);
probe_data->set_dynamic_range(dynamic_range);
@@ -1282,9 +1300,13 @@ void GIProbe::bake(Node *p_from_node, bool p_create_visual_debug) {
set_probe_data(probe_data);
}
+
+ if (bake_end_function) {
+ bake_end_function();
+ }
}
-void GIProbe::_debug_mesh(int p_idx, int p_level, const Rect3 &p_aabb, Ref<MultiMesh> &p_multimesh, int &idx, Baker *p_baker) {
+void GIProbe::_debug_mesh(int p_idx, int p_level, const AABB &p_aabb, Ref<MultiMesh> &p_multimesh, int &idx, Baker *p_baker) {
if (p_level == p_baker->cell_subdiv - 1) {
@@ -1306,7 +1328,7 @@ void GIProbe::_debug_mesh(int p_idx, int p_level, const Rect3 &p_aabb, Ref<Multi
if (p_baker->bake_cells[p_idx].childs[i] == Baker::CHILD_EMPTY)
continue;
- Rect3 aabb = p_aabb;
+ AABB aabb = p_aabb;
aabb.size *= 0.5;
if (i & 1)
@@ -1418,9 +1440,9 @@ void GIProbe::_debug_bake() {
bake(NULL, true);
}
-Rect3 GIProbe::get_aabb() const {
+AABB GIProbe::get_aabb() const {
- return Rect3(-extents, extents * 2);
+ return AABB(-extents, extents * 2);
}
PoolVector<Face3> GIProbe::get_faces(uint32_t p_usage_flags) const {
@@ -1478,6 +1500,7 @@ void GIProbe::_bind_methods() {
BIND_ENUM_CONSTANT(SUBDIV_64);
BIND_ENUM_CONSTANT(SUBDIV_128);
BIND_ENUM_CONSTANT(SUBDIV_256);
+ BIND_ENUM_CONSTANT(SUBDIV_512);
BIND_ENUM_CONSTANT(SUBDIV_MAX);
}
diff --git a/scene/3d/gi_probe.h b/scene/3d/gi_probe.h
index 5a06984a47..324ff8e917 100644
--- a/scene/3d/gi_probe.h
+++ b/scene/3d/gi_probe.h
@@ -43,8 +43,8 @@ protected:
static void _bind_methods();
public:
- void set_bounds(const Rect3 &p_bounds);
- Rect3 get_bounds() const;
+ void set_bounds(const AABB &p_bounds);
+ AABB get_bounds() const;
void set_cell_size(float p_size);
float get_cell_size() const;
@@ -95,6 +95,10 @@ public:
};
+ typedef void (*BakeBeginFunc)(int);
+ typedef void (*BakeStepFunc)(int, const String &);
+ typedef void (*BakeEndFunc)();
+
private:
//stuff used for bake
struct Baker {
@@ -142,7 +146,7 @@ private:
MaterialCache _get_material_cache(Ref<Material> p_material);
int leaf_voxel_count;
- Rect3 po2_bounds;
+ AABB po2_bounds;
int axis_cell_size[3];
struct PlotMesh {
@@ -174,14 +178,14 @@ private:
int color_scan_cell_width;
int bake_texture_size;
- Vector<Color> _get_bake_texture(Ref<Image> p_image, const Color &p_color);
+ Vector<Color> _get_bake_texture(Ref<Image> p_image, const Color &p_color_mul, const Color &p_color_add);
Baker::MaterialCache _get_material_cache(Ref<Material> p_material, Baker *p_baker);
- void _plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, const Vector3 *p_vtx, const Vector2 *p_uv, const Baker::MaterialCache &p_material, const Rect3 &p_aabb, Baker *p_baker);
+ void _plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, const Vector3 *p_vtx, const Vector2 *p_uv, const Baker::MaterialCache &p_material, const AABB &p_aabb, Baker *p_baker);
void _plot_mesh(const Transform &p_xform, Ref<Mesh> &p_mesh, Baker *p_baker, const Vector<Ref<Material> > &p_materials, const Ref<Material> &p_override_material);
void _find_meshes(Node *p_at_node, Baker *p_baker);
void _fixup_plot(int p_idx, int p_level, int p_x, int p_y, int p_z, Baker *p_baker);
- void _debug_mesh(int p_idx, int p_level, const Rect3 &p_aabb, Ref<MultiMesh> &p_multimesh, int &idx, Baker *p_baker);
+ void _debug_mesh(int p_idx, int p_level, const AABB &p_aabb, Ref<MultiMesh> &p_multimesh, int &idx, Baker *p_baker);
void _create_debug_mesh(Baker *p_baker);
void _debug_bake();
@@ -190,6 +194,10 @@ protected:
static void _bind_methods();
public:
+ static BakeBeginFunc bake_begin_function;
+ static BakeStepFunc bake_step_function;
+ static BakeEndFunc bake_end_function;
+
void set_probe_data(const Ref<GIProbeData> &p_data);
Ref<GIProbeData> get_probe_data() const;
@@ -222,7 +230,7 @@ public:
void bake(Node *p_from_node = NULL, bool p_create_visual_debug = false);
- virtual Rect3 get_aabb() const;
+ virtual AABB get_aabb() const;
virtual PoolVector<Face3> get_faces(uint32_t p_usage_flags) const;
GIProbe();
diff --git a/scene/3d/immediate_geometry.cpp b/scene/3d/immediate_geometry.cpp
index 11f7efe066..092ed8f0b2 100644
--- a/scene/3d/immediate_geometry.cpp
+++ b/scene/3d/immediate_geometry.cpp
@@ -85,7 +85,7 @@ void ImmediateGeometry::clear() {
cached_textures.clear();
}
-Rect3 ImmediateGeometry::get_aabb() const {
+AABB ImmediateGeometry::get_aabb() const {
return aabb;
}
diff --git a/scene/3d/immediate_geometry.h b/scene/3d/immediate_geometry.h
index 93ef726c6d..1ff4e05e82 100644
--- a/scene/3d/immediate_geometry.h
+++ b/scene/3d/immediate_geometry.h
@@ -42,7 +42,7 @@ class ImmediateGeometry : public GeometryInstance {
// in VisualServer from becoming invalid if the texture is no longer used
List<Ref<Texture> > cached_textures;
bool empty;
- Rect3 aabb;
+ AABB aabb;
protected:
static void _bind_methods();
@@ -62,7 +62,7 @@ public:
void add_sphere(int p_lats, int p_lons, float p_radius, bool p_add_uv = true);
- virtual Rect3 get_aabb() const;
+ virtual AABB get_aabb() const;
virtual PoolVector<Face3> get_faces(uint32_t p_usage_flags) const;
ImmediateGeometry();
diff --git a/scene/3d/light.cpp b/scene/3d/light.cpp
index b7cd9bd2dc..126c07f0be 100644
--- a/scene/3d/light.cpp
+++ b/scene/3d/light.cpp
@@ -117,24 +117,24 @@ bool Light::get_shadow_reverse_cull_face() const {
return reverse_cull;
}
-Rect3 Light::get_aabb() const {
+AABB Light::get_aabb() const {
if (type == VisualServer::LIGHT_DIRECTIONAL) {
- return Rect3(Vector3(-1, -1, -1), Vector3(2, 2, 2));
+ return AABB(Vector3(-1, -1, -1), Vector3(2, 2, 2));
} else if (type == VisualServer::LIGHT_OMNI) {
- return Rect3(Vector3(-1, -1, -1) * param[PARAM_RANGE], Vector3(2, 2, 2) * param[PARAM_RANGE]);
+ return AABB(Vector3(-1, -1, -1) * param[PARAM_RANGE], Vector3(2, 2, 2) * param[PARAM_RANGE]);
} else if (type == VisualServer::LIGHT_SPOT) {
float len = param[PARAM_RANGE];
float size = Math::tan(Math::deg2rad(param[PARAM_SPOT_ANGLE])) * len;
- return Rect3(Vector3(-size, -size, -len), Vector3(size * 2, size * 2, len));
+ return AABB(Vector3(-size, -size, -len), Vector3(size * 2, size * 2, len));
}
- return Rect3();
+ return AABB();
}
PoolVector<Face3> Light::get_faces(uint32_t p_usage_flags) const {
@@ -222,6 +222,7 @@ void Light::_bind_methods() {
ADD_GROUP("Light", "light_");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "light_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_color", "get_color");
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "light_energy", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_param", "get_param", PARAM_ENERGY);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL, "light_indirect_energy", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_param", "get_param", PARAM_INDIRECT_ENERGY);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "light_negative"), "set_negative", "is_negative");
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "light_specular", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param", "get_param", PARAM_SPECULAR);
ADD_PROPERTY(PropertyInfo(Variant::INT, "light_cull_mask", PROPERTY_HINT_LAYERS_3D_RENDER), "set_cull_mask", "get_cull_mask");
@@ -236,6 +237,7 @@ void Light::_bind_methods() {
ADD_GROUP("", "");
BIND_ENUM_CONSTANT(PARAM_ENERGY);
+ BIND_ENUM_CONSTANT(PARAM_INDIRECT_ENERGY);
BIND_ENUM_CONSTANT(PARAM_SPECULAR);
BIND_ENUM_CONSTANT(PARAM_RANGE);
BIND_ENUM_CONSTANT(PARAM_ATTENUATION);
@@ -248,14 +250,20 @@ void Light::_bind_methods() {
BIND_ENUM_CONSTANT(PARAM_SHADOW_SPLIT_3_OFFSET);
BIND_ENUM_CONSTANT(PARAM_SHADOW_NORMAL_BIAS);
BIND_ENUM_CONSTANT(PARAM_SHADOW_BIAS);
-
+ BIND_ENUM_CONSTANT(PARAM_SHADOW_BIAS_SPLIT_SCALE);
BIND_ENUM_CONSTANT(PARAM_MAX);
}
Light::Light(VisualServer::LightType p_type) {
type = p_type;
- light = VisualServer::get_singleton()->light_create(p_type);
+ switch (p_type) {
+ case VS::LIGHT_DIRECTIONAL: light = VisualServer::get_singleton()->directional_light_create(); break;
+ case VS::LIGHT_OMNI: light = VisualServer::get_singleton()->omni_light_create(); break;
+ case VS::LIGHT_SPOT: light = VisualServer::get_singleton()->spot_light_create(); break;
+ default: {};
+ }
+
VS::get_singleton()->instance_set_base(get_instance(), light);
reverse_cull = false;
@@ -267,6 +275,7 @@ Light::Light(VisualServer::LightType p_type) {
set_cull_mask(0xFFFFFFFF);
set_param(PARAM_ENERGY, 1);
+ set_param(PARAM_INDIRECT_ENERGY, 1);
set_param(PARAM_SPECULAR, 0.5);
set_param(PARAM_RANGE, 5);
set_param(PARAM_ATTENUATION, 1);
@@ -369,12 +378,6 @@ DirectionalLight::DirectionalLight()
set_shadow_depth_range(SHADOW_DEPTH_RANGE_STABLE);
blend_splits = false;
-
-#ifdef TOOLS_ENABLED
- if (Engine::get_singleton()->is_editor_hint())
- // Create light with a default natural "sun" orientation in editor, instead of looking horizontally on X
- set_rotation_in_degrees(Vector3(-50, 25, 30));
-#endif
}
void OmniLight::set_shadow_mode(ShadowMode p_mode) {
diff --git a/scene/3d/light.h b/scene/3d/light.h
index 2f3ac8a5e7..8514b429ec 100644
--- a/scene/3d/light.h
+++ b/scene/3d/light.h
@@ -46,6 +46,7 @@ class Light : public VisualInstance {
public:
enum Param {
PARAM_ENERGY = VS::LIGHT_PARAM_ENERGY,
+ PARAM_INDIRECT_ENERGY = VS::LIGHT_PARAM_INDIRECT_ENERGY,
PARAM_SPECULAR = VS::LIGHT_PARAM_SPECULAR,
PARAM_RANGE = VS::LIGHT_PARAM_RANGE,
PARAM_ATTENUATION = VS::LIGHT_PARAM_ATTENUATION,
@@ -113,7 +114,7 @@ public:
void set_shadow_reverse_cull_face(bool p_enable);
bool get_shadow_reverse_cull_face() const;
- virtual Rect3 get_aabb() const;
+ virtual AABB get_aabb() const;
virtual PoolVector<Face3> get_faces(uint32_t p_usage_flags) const;
Light();
diff --git a/scene/3d/mesh_instance.cpp b/scene/3d/mesh_instance.cpp
index c8215971c4..1e52ccc6e0 100644
--- a/scene/3d/mesh_instance.cpp
+++ b/scene/3d/mesh_instance.cpp
@@ -165,12 +165,12 @@ NodePath MeshInstance::get_skeleton_path() {
return skeleton_path;
}
-Rect3 MeshInstance::get_aabb() const {
+AABB MeshInstance::get_aabb() const {
if (!mesh.is_null())
return mesh->get_aabb();
- return Rect3();
+ return AABB();
}
PoolVector<Face3> MeshInstance::get_faces(uint32_t p_usage_flags) const {
diff --git a/scene/3d/mesh_instance.h b/scene/3d/mesh_instance.h
index 8e8c12a592..970a10aaf3 100644
--- a/scene/3d/mesh_instance.h
+++ b/scene/3d/mesh_instance.h
@@ -85,7 +85,7 @@ public:
void create_debug_tangents();
- virtual Rect3 get_aabb() const;
+ virtual AABB get_aabb() const;
virtual PoolVector<Face3> get_faces(uint32_t p_usage_flags) const;
MeshInstance();
diff --git a/scene/3d/multimesh_instance.cpp b/scene/3d/multimesh_instance.cpp
index f90489f1f0..ce7b97be7f 100644
--- a/scene/3d/multimesh_instance.cpp
+++ b/scene/3d/multimesh_instance.cpp
@@ -55,10 +55,10 @@ PoolVector<Face3> MultiMeshInstance::get_faces(uint32_t p_usage_flags) const {
return PoolVector<Face3>();
}
-Rect3 MultiMeshInstance::get_aabb() const {
+AABB MultiMeshInstance::get_aabb() const {
if (multimesh.is_null())
- return Rect3();
+ return AABB();
else
return multimesh->get_aabb();
}
diff --git a/scene/3d/multimesh_instance.h b/scene/3d/multimesh_instance.h
index cd0e7b463c..9b2b1ff9a7 100644
--- a/scene/3d/multimesh_instance.h
+++ b/scene/3d/multimesh_instance.h
@@ -52,7 +52,7 @@ public:
void set_multimesh(const Ref<MultiMesh> &p_multimesh);
Ref<MultiMesh> get_multimesh() const;
- virtual Rect3 get_aabb() const;
+ virtual AABB get_aabb() const;
MultiMeshInstance();
~MultiMeshInstance();
diff --git a/scene/3d/particles.cpp b/scene/3d/particles.cpp
index 80c706898d..2a032f5d96 100644
--- a/scene/3d/particles.cpp
+++ b/scene/3d/particles.cpp
@@ -31,9 +31,9 @@
#include "scene/resources/surface_tool.h"
#include "servers/visual_server.h"
-Rect3 Particles::get_aabb() const {
+AABB Particles::get_aabb() const {
- return Rect3();
+ return AABB();
}
PoolVector<Face3> Particles::get_faces(uint32_t p_usage_flags) const {
@@ -82,7 +82,7 @@ void Particles::set_randomness_ratio(float p_ratio) {
randomness_ratio = p_ratio;
VS::get_singleton()->particles_set_randomness_ratio(particles, randomness_ratio);
}
-void Particles::set_visibility_aabb(const Rect3 &p_aabb) {
+void Particles::set_visibility_aabb(const AABB &p_aabb) {
visibility_aabb = p_aabb;
VS::get_singleton()->particles_set_custom_aabb(particles, visibility_aabb);
@@ -140,7 +140,7 @@ float Particles::get_randomness_ratio() const {
return randomness_ratio;
}
-Rect3 Particles::get_visibility_aabb() const {
+AABB Particles::get_visibility_aabb() const {
return visibility_aabb;
}
@@ -252,7 +252,7 @@ void Particles::restart() {
VisualServer::get_singleton()->particles_restart(particles);
}
-Rect3 Particles::capture_aabb() const {
+AABB Particles::capture_aabb() const {
return VS::get_singleton()->particles_get_current_aabb(particles);
}
@@ -335,7 +335,7 @@ void Particles::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "fixed_fps", PROPERTY_HINT_RANGE, "0,1000,1"), "set_fixed_fps", "get_fixed_fps");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fract_delta"), "set_fractional_delta", "get_fractional_delta");
ADD_GROUP("Drawing", "");
- ADD_PROPERTY(PropertyInfo(Variant::RECT3, "visibility_aabb"), "set_visibility_aabb", "get_visibility_aabb");
+ ADD_PROPERTY(PropertyInfo(Variant::AABB, "visibility_aabb"), "set_visibility_aabb", "get_visibility_aabb");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "local_coords"), "set_use_local_coordinates", "get_use_local_coordinates");
ADD_PROPERTY(PropertyInfo(Variant::INT, "draw_order", PROPERTY_HINT_ENUM, "Index,Lifetime,View Depth"), "set_draw_order", "get_draw_order");
ADD_GROUP("Process Material", "");
@@ -367,7 +367,7 @@ Particles::Particles() {
set_pre_process_time(0);
set_explosiveness_ratio(0);
set_randomness_ratio(0);
- set_visibility_aabb(Rect3(Vector3(-4, -4, -4), Vector3(8, 8, 8)));
+ set_visibility_aabb(AABB(Vector3(-4, -4, -4), Vector3(8, 8, 8)));
set_use_local_coordinates(true);
set_draw_passes(1);
set_draw_order(DRAW_ORDER_INDEX);
@@ -462,8 +462,6 @@ void ParticlesMaterial::finish_shaders() {
void ParticlesMaterial::_update_shader() {
- print_line("updating shader");
-
dirty_materials.remove(&element);
MaterialKey mk = _compute_key();
@@ -587,298 +585,300 @@ void ParticlesMaterial::_update_shader() {
//need a random function
code += "\n\n";
code += "float rand_from_seed(inout uint seed) {\n";
- code += " int k;\n";
- code += " int s = int(seed);\n";
- code += " if (s == 0)\n";
+ code += " int k;\n";
+ code += " int s = int(seed);\n";
+ code += " if (s == 0)\n";
code += " s = 305420679;\n";
- code += " k = s / 127773;\n";
- code += " s = 16807 * (s - k * 127773) - 2836 * k;\n";
- code += " if (s < 0)\n";
- code += " s += 2147483647;\n";
- code += " seed = uint(s);\n";
- code += " return float(seed % uint(65536))/65535.0;\n";
+ code += " k = s / 127773;\n";
+ code += " s = 16807 * (s - k * 127773) - 2836 * k;\n";
+ code += " if (s < 0)\n";
+ code += " s += 2147483647;\n";
+ code += " seed = uint(s);\n";
+ code += " return float(seed % uint(65536))/65535.0;\n";
code += "}\n";
+ code += "\n";
+
//improve seed quality
code += "uint hash(uint x) {\n";
- code += " x = ((x >> uint(16)) ^ x) * uint(73244475);\n";
- code += " x = ((x >> uint(16)) ^ x) * uint(73244475);\n";
- code += " x = (x >> uint(16)) ^ x;\n";
- code += " return x;\n";
+ code += " x = ((x >> uint(16)) ^ x) * uint(73244475);\n";
+ code += " x = ((x >> uint(16)) ^ x) * uint(73244475);\n";
+ code += " x = (x >> uint(16)) ^ x;\n";
+ code += " return x;\n";
code += "}\n";
- code += "void vertex() {\n\n";
code += "\n";
- code += " uint base_number=NUMBER/uint(trail_divisor);\n";
- code += " uint alt_seed=hash(base_number+uint(1)+RANDOM_SEED);\n";
- code += " float angle_rand=rand_from_seed(alt_seed);\n";
- code += " float scale_rand=rand_from_seed(alt_seed);\n";
- code += " float hue_rot_rand=rand_from_seed(alt_seed);\n";
- code += " float anim_offset_rand=rand_from_seed(alt_seed);\n";
- code += "\n";
- code += "\n";
- code += "\n";
+ code += "void vertex() {\n";
+ code += " uint base_number = NUMBER/uint(trail_divisor);\n";
+ code += " uint alt_seed = hash(base_number+uint(1)+RANDOM_SEED);\n";
+ code += " float angle_rand = rand_from_seed(alt_seed);\n";
+ code += " float scale_rand = rand_from_seed(alt_seed);\n";
+ code += " float hue_rot_rand = rand_from_seed(alt_seed);\n";
+ code += " float anim_offset_rand = rand_from_seed(alt_seed);\n";
code += "\n";
+
if (emission_shape >= EMISSION_SHAPE_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";
+ 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";
}
- code += " if (RESTART) {\n";
+ code += " if (RESTART) {\n";
if (tex_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid())
- code += " float tex_linear_velocity = textureLod(linear_velocity_texture,vec2(0.0,0.0),0.0).r;\n";
+ code += " float tex_linear_velocity = textureLod(linear_velocity_texture,vec2(0.0,0.0),0.0).r;\n";
else
- code += " float tex_linear_velocity = 0.0;\n";
+ code += " float tex_linear_velocity = 0.0;\n";
if (tex_parameters[PARAM_ANGLE].is_valid())
- code += " float tex_angle = textureLod(angle_texture,vec2(0.0,0.0),0.0).r;\n";
+ code += " float tex_angle = textureLod(angle_texture,vec2(0.0,0.0),0.0).r;\n";
else
- code += " float tex_angle = 0.0;\n";
+ code += " float tex_angle = 0.0;\n";
if (tex_parameters[PARAM_ANIM_OFFSET].is_valid())
- code += " float tex_anim_offset = textureLod(anim_offset_texture,vec2(0.0,0.0),0.0).r;\n";
+ code += " float tex_anim_offset = textureLod(anim_offset_texture,vec2(0.0,0.0),0.0).r;\n";
else
- code += " float tex_anim_offset = 0.0;\n";
+ code += " float tex_anim_offset = 0.0;\n";
if (flags[FLAG_DISABLE_Z]) {
- code += " float angle1 = (rand_from_seed(alt_seed)*2.0-1.0)*spread/180.0*3.1416;\n";
- code += " vec3 rot=vec3( cos(angle1), sin(angle1),0.0 );\n";
- code += " VELOCITY=(rot*initial_linear_velocity+rot*initial_linear_velocity_random*rand_from_seed(alt_seed));\n";
+ code += " float angle1 = (rand_from_seed(alt_seed)*2.0-1.0)*spread/180.0*3.1416;\n";
+ code += " vec3 rot = vec3( cos(angle1), sin(angle1),0.0 );\n";
+ code += " VELOCITY = rot*initial_linear_velocity*mix(1.0, rand_from_seed(alt_seed), initial_linear_velocity_random);\n";
} else {
//initiate velocity spread in 3D
- code += " float angle1 = rand_from_seed(alt_seed)*spread*3.1416;\n";
- code += " float angle2 = rand_from_seed(alt_seed)*20.0*3.1416; // make it more random like\n";
- code += " vec3 rot_xz=vec3( sin(angle1), 0.0, cos(angle1) );\n";
- code += " vec3 rot = vec3( cos(angle2)*rot_xz.x,sin(angle2)*rot_xz.x, rot_xz.z);\n";
- code += " VELOCITY=(rot*initial_linear_velocity+rot*initial_linear_velocity_random*rand_from_seed(alt_seed));\n";
+ code += " float angle1 = rand_from_seed(alt_seed)*spread*3.1416;\n";
+ code += " float angle2 = rand_from_seed(alt_seed)*20.0*3.1416; // make it more random like\n";
+ code += " vec3 rot_xz = vec3( sin(angle1), 0.0, cos(angle1) );\n";
+ code += " vec3 rot = vec3( cos(angle2)*rot_xz.x,sin(angle2)*rot_xz.x, rot_xz.z);\n";
+ code += " VELOCITY = rot*initial_linear_velocity*mix(1.0, rand_from_seed(alt_seed), initial_linear_velocity_random);\n";
}
- code += " float base_angle=(initial_angle+tex_angle)*mix(1.0,angle_rand,initial_angle_random);\n";
- code += " CUSTOM.x=base_angle*3.1416/180.0;\n"; //angle
- code += " CUSTOM.y=0.0;\n"; //phase
- code += " CUSTOM.z=(anim_offset+tex_anim_offset)*mix(1.0,anim_offset_rand,anim_offset_random);\n"; //animation offset (0-1)
+ code += " float base_angle = (initial_angle+tex_angle)*mix(1.0,angle_rand,initial_angle_random);\n";
+ code += " CUSTOM.x = base_angle*3.1416/180.0;\n"; //angle
+ code += " CUSTOM.y = 0.0;\n"; //phase
+ code += " CUSTOM.z = (anim_offset+tex_anim_offset)*mix(1.0,anim_offset_rand,anim_offset_random);\n"; //animation offset (0-1)
switch (emission_shape) {
case EMISSION_SHAPE_POINT: {
//do none
} break;
case EMISSION_SHAPE_SPHERE: {
- code += " TRANSFORM[3].xyz = normalize(vec3(rand_from_seed(alt_seed) * 2.0 - 1.0, rand_from_seed(alt_seed) * 2.0-1.0, rand_from_seed(alt_seed) * 2.0-1.0 ))*emission_sphere_radius;\n";
+ code += " TRANSFORM[3].xyz = normalize(vec3(rand_from_seed(alt_seed) * 2.0 - 1.0, rand_from_seed(alt_seed) * 2.0-1.0, rand_from_seed(alt_seed) * 2.0-1.0 ))*emission_sphere_radius;\n";
} break;
case EMISSION_SHAPE_BOX: {
- code += " TRANSFORM[3].xyz = vec3(rand_from_seed(alt_seed) * 2.0 - 1.0, rand_from_seed(alt_seed) * 2.0-1.0, rand_from_seed(alt_seed) * 2.0-1.0)*emission_box_extents;\n";
+ code += " TRANSFORM[3].xyz = vec3(rand_from_seed(alt_seed) * 2.0 - 1.0, rand_from_seed(alt_seed) * 2.0-1.0, rand_from_seed(alt_seed) * 2.0-1.0)*emission_box_extents;\n";
} break;
case EMISSION_SHAPE_POINTS:
case EMISSION_SHAPE_DIRECTED_POINTS: {
- code += " TRANSFORM[3].xyz = texelFetch(emission_texture_points, emission_tex_ofs,0).xyz;\n";
+ code += " TRANSFORM[3].xyz = texelFetch(emission_texture_points, emission_tex_ofs,0).xyz;\n";
if (emission_shape == EMISSION_SHAPE_DIRECTED_POINTS) {
if (flags[FLAG_DISABLE_Z]) {
- code += " mat2 rotm;";
- code += " rotm[0]=texelFetch(emission_texture_normal, emission_tex_ofs,0).xy;\n";
- code += " rotm[1]=rotm[0].yx * vec2(1.0,-1.0);\n";
- code += " VELOCITY.xy = rotm * VELOCITY.xy;\n";
+ code += " mat2 rotm;";
+ code += " rotm[0] = texelFetch(emission_texture_normal, emission_tex_ofs,0).xy;\n";
+ code += " rotm[1] = rotm[0].yx * vec2(1.0,-1.0);\n";
+ code += " VELOCITY.xy = rotm * VELOCITY.xy;\n";
} else {
- code += " vec3 normal = texelFetch(emission_texture_normal, emission_tex_ofs,0).xyz;\n";
- code += " vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0, 1.0, 0.0);\n";
- code += " vec3 tangent = normalize(cross(v0, normal));\n";
- code += " vec3 bitangent = normalize(cross(tangent, normal));\n";
- code += " VELOCITY = mat3(tangent,bitangent,normal) * VELOCITY;\n";
+ code += " vec3 normal = texelFetch(emission_texture_normal, emission_tex_ofs,0).xyz;\n";
+ code += " vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0, 1.0, 0.0);\n";
+ code += " vec3 tangent = normalize(cross(v0, normal));\n";
+ code += " vec3 bitangent = normalize(cross(tangent, normal));\n";
+ code += " VELOCITY = mat3(tangent,bitangent,normal) * VELOCITY;\n";
}
}
} break;
}
- code += " VELOCITY = (EMISSION_TRANSFORM * vec4(VELOCITY,0.0)).xyz;\n";
- code += " TRANSFORM = EMISSION_TRANSFORM * TRANSFORM;\n";
+ code += " VELOCITY = (EMISSION_TRANSFORM * vec4(VELOCITY,0.0)).xyz;\n";
+ code += " TRANSFORM = EMISSION_TRANSFORM * TRANSFORM;\n";
if (flags[FLAG_DISABLE_Z]) {
- code += " VELOCITY.z=0.0;\n";
- code += " TRANSFORM[3].z=0.0;\n";
+ code += " VELOCITY.z = 0.0;\n";
+ code += " TRANSFORM[3].z = 0.0;\n";
}
- code += " } else {\n";
+ code += " } else {\n";
- code += " CUSTOM.y+=DELTA/LIFETIME;\n";
+ code += " CUSTOM.y += DELTA/LIFETIME;\n";
if (tex_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid())
- code += " float tex_linear_velocity = textureLod(linear_velocity_texture,vec2(CUSTOM.y,0.0),0.0).r;\n";
+ code += " float tex_linear_velocity = textureLod(linear_velocity_texture,vec2(CUSTOM.y,0.0),0.0).r;\n";
else
- code += " float tex_linear_velocity = 0.0;\n";
+ code += " float tex_linear_velocity = 0.0;\n";
if (tex_parameters[PARAM_ORBIT_VELOCITY].is_valid())
- code += " float tex_orbit_velocity = textureLod(orbit_velocity_texture,vec2(CUSTOM.y,0.0),0.0).r;\n";
+ code += " float tex_orbit_velocity = textureLod(orbit_velocity_texture,vec2(CUSTOM.y,0.0),0.0).r;\n";
else
- code += " float tex_orbit_velocity = 0.0;\n";
+ code += " float tex_orbit_velocity = 0.0;\n";
if (tex_parameters[PARAM_ANGULAR_VELOCITY].is_valid())
- code += " float tex_angular_velocity = textureLod(angular_velocity_texture,vec2(CUSTOM.y,0.0),0.0).r;\n";
+ code += " float tex_angular_velocity = textureLod(angular_velocity_texture,vec2(CUSTOM.y,0.0),0.0).r;\n";
else
- code += " float tex_angular_velocity = 0.0;\n";
+ code += " float tex_angular_velocity = 0.0;\n";
if (tex_parameters[PARAM_LINEAR_ACCEL].is_valid())
- code += " float tex_linear_accel = textureLod(linear_accel_texture,vec2(CUSTOM.y,0.0),0.0).r;\n";
+ code += " float tex_linear_accel = textureLod(linear_accel_texture,vec2(CUSTOM.y,0.0),0.0).r;\n";
else
- code += " float tex_linear_accel = 0.0;\n";
+ code += " float tex_linear_accel = 0.0;\n";
if (tex_parameters[PARAM_RADIAL_ACCEL].is_valid())
- code += " float tex_radial_accel = textureLod(radial_accel_texture,vec2(CUSTOM.y,0.0),0.0).r;\n";
+ code += " float tex_radial_accel = textureLod(radial_accel_texture,vec2(CUSTOM.y,0.0),0.0).r;\n";
else
- code += " float tex_radial_accel = 0.0;\n";
+ code += " float tex_radial_accel = 0.0;\n";
if (tex_parameters[PARAM_TANGENTIAL_ACCEL].is_valid())
- code += " float tex_tangent_accel = textureLod(tangent_accel_texture,vec2(CUSTOM.y,0.0),0.0).r;\n";
+ code += " float tex_tangent_accel = textureLod(tangent_accel_texture,vec2(CUSTOM.y,0.0),0.0).r;\n";
else
- code += " float tex_tangent_accel = 0.0;\n";
+ code += " float tex_tangent_accel = 0.0;\n";
if (tex_parameters[PARAM_DAMPING].is_valid())
- code += " float tex_damping = textureLod(damping_texture,vec2(CUSTOM.y,0.0),0.0).r;\n";
+ code += " float tex_damping = textureLod(damping_texture,vec2(CUSTOM.y,0.0),0.0).r;\n";
else
- code += " float tex_damping = 0.0;\n";
+ code += " float tex_damping = 0.0;\n";
if (tex_parameters[PARAM_ANGLE].is_valid())
- code += " float tex_angle = textureLod(angle_texture,vec2(CUSTOM.y,0.0),0.0).r;\n";
+ code += " float tex_angle = textureLod(angle_texture,vec2(CUSTOM.y,0.0),0.0).r;\n";
else
- code += " float tex_angle = 0.0;\n";
+ code += " float tex_angle = 0.0;\n";
if (tex_parameters[PARAM_ANIM_SPEED].is_valid())
- code += " float tex_anim_speed = textureLod(anim_speed_texture,vec2(CUSTOM.y,0.0),0.0).r;\n";
+ code += " float tex_anim_speed = textureLod(anim_speed_texture,vec2(CUSTOM.y,0.0),0.0).r;\n";
else
- code += " float tex_anim_speed = 0.0;\n";
+ code += " float tex_anim_speed = 0.0;\n";
if (tex_parameters[PARAM_ANIM_OFFSET].is_valid())
- code += " float tex_anim_offset = textureLod(anim_offset_texture,vec2(CUSTOM.y,0.0),0.0).r;\n";
+ code += " float tex_anim_offset = textureLod(anim_offset_texture,vec2(CUSTOM.y,0.0),0.0).r;\n";
else
- code += " float tex_anim_offset = 0.0;\n";
+ code += " float tex_anim_offset = 0.0;\n";
- code += " vec3 force = gravity; \n";
- code += " vec3 pos = TRANSFORM[3].xyz; \n";
+ code += " vec3 force = gravity; \n";
+ code += " vec3 pos = TRANSFORM[3].xyz; \n";
if (flags[FLAG_DISABLE_Z]) {
- code += " pos.z=0.0; \n";
+ code += " pos.z = 0.0; \n";
}
- code += " //apply linear acceleration\n";
- code += " force+= length(VELOCITY) > 0.0 ? normalize(VELOCITY) * (linear_accel+tex_linear_accel)*mix(1.0,rand_from_seed(alt_seed),linear_accel_random) : vec3(0.0);\n";
- code += " //apply radial acceleration\n";
- code += " vec3 org = vec3(0.0);\n";
- code += " // if (!p_system->local_coordinates)\n";
- code += " //org=p_transform.origin;\n";
- code += " vec3 diff = pos-org;\n";
- code += " force+=length(diff) > 0.0 ? normalize(diff) * (radial_accel+tex_radial_accel)*mix(1.0,rand_from_seed(alt_seed),radial_accel_random) : vec3(0.0);\n";
- code += " //apply tangential acceleration;\n";
+ code += " //apply linear acceleration\n";
+ code += " force += length(VELOCITY) > 0.0 ? normalize(VELOCITY) * (linear_accel+tex_linear_accel)*mix(1.0,rand_from_seed(alt_seed),linear_accel_random) : vec3(0.0);\n";
+ code += " //apply radial acceleration\n";
+ code += " vec3 org = vec3(0.0);\n";
+ code += " vec3 diff = pos-org;\n";
+ code += " force += length(diff) > 0.0 ? normalize(diff) * (radial_accel+tex_radial_accel)*mix(1.0,rand_from_seed(alt_seed),radial_accel_random) : vec3(0.0);\n";
+ code += " //apply tangential acceleration;\n";
if (flags[FLAG_DISABLE_Z]) {
- code += " force+=length(diff.yx) > 0.0 ? vec3(normalize(diff.yx * vec2(-1.0,1.0)),0.0) * ((tangent_accel+tex_tangent_accel)*mix(1.0,rand_from_seed(alt_seed),radial_accel_random)) : vec3(0.0);\n";
+ code += " force += length(diff.yx) > 0.0 ? vec3(normalize(diff.yx * vec2(-1.0,1.0)),0.0) * ((tangent_accel+tex_tangent_accel)*mix(1.0,rand_from_seed(alt_seed),tangent_accel_random)) : vec3(0.0);\n";
} else {
- code += " vec3 crossDiff = cross(normalize(diff),normalize(gravity));\n";
- code += " force+=length(crossDiff) > 0.0 ? normalize(crossDiff) * ((tangent_accel+tex_tangent_accel)*mix(1.0,rand_from_seed(alt_seed),radial_accel_random)) : vec3(0.0);\n";
+ code += " vec3 crossDiff = cross(normalize(diff),normalize(gravity));\n";
+ code += " force += length(crossDiff) > 0.0 ? normalize(crossDiff) * ((tangent_accel+tex_tangent_accel)*mix(1.0,rand_from_seed(alt_seed),tangent_accel_random)) : vec3(0.0);\n";
}
- code += " //apply attractor forces\n";
- code += " VELOCITY+=force * DELTA;\n";
+ code += " //apply attractor forces\n";
+ code += " VELOCITY += force * DELTA;\n";
if (tex_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) {
- code += " VELOCITY=normalize(VELOCITY)*tex_linear_velocity;\n";
+ code += " VELOCITY = normalize(VELOCITY)*tex_linear_velocity;\n";
}
- code += " if (damping+tex_damping>0.0) {\n";
- code += " \n";
- code += " float v = length(VELOCITY);\n";
- code += " float damp = (damping+tex_damping)*mix(1.0,rand_from_seed(alt_seed),damping_random);\n";
- code += " v -= damp * DELTA;\n";
- code += " if (v<0.0) {\n";
- code += " VELOCITY=vec3(0.0);\n";
- code += " } else {\n";
- code += " VELOCITY=normalize(VELOCITY) * v;\n";
- code += " }\n";
- code += " }\n";
- code += " float base_angle=(initial_angle+tex_angle)*mix(1.0,angle_rand,initial_angle_random);\n";
- code += " base_angle+=CUSTOM.y*LIFETIME*(angular_velocity+tex_angular_velocity)*mix(1.0,rand_from_seed(alt_seed)*2.0-1.0,angular_velocity_random);\n";
- code += " CUSTOM.x=base_angle*3.1416/180.0;\n"; //angle
- code += " CUSTOM.z=(anim_offset+tex_anim_offset)*mix(1.0,anim_offset_rand,anim_offset_random)+CUSTOM.y*(anim_speed+tex_anim_speed)*mix(1.0,rand_from_seed(alt_seed),anim_speed_random);\n"; //angle
+ code += " if (damping + tex_damping > 0.0) {\n";
+ code += " \n";
+ code += " float v = length(VELOCITY);\n";
+ code += " float damp = (damping+tex_damping)*mix(1.0,rand_from_seed(alt_seed),damping_random);\n";
+ code += " v -= damp * DELTA;\n";
+ code += " if (v < 0.0) {\n";
+ code += " VELOCITY = vec3(0.0);\n";
+ code += " } else {\n";
+ code += " VELOCITY = normalize(VELOCITY) * v;\n";
+ code += " }\n";
+ code += " }\n";
+ code += " float base_angle = (initial_angle+tex_angle)*mix(1.0,angle_rand,initial_angle_random);\n";
+ code += " base_angle += CUSTOM.y*LIFETIME*(angular_velocity+tex_angular_velocity)*mix(1.0,rand_from_seed(alt_seed)*2.0-1.0,angular_velocity_random);\n";
+ code += " CUSTOM.x = base_angle*3.1416/180.0;\n"; //angle
+ code += " CUSTOM.z = (anim_offset+tex_anim_offset)*mix(1.0,anim_offset_rand,anim_offset_random)+CUSTOM.y*(anim_speed+tex_anim_speed)*mix(1.0,rand_from_seed(alt_seed),anim_speed_random);\n"; //angle
if (flags[FLAG_ANIM_LOOP]) {
- code += " CUSTOM.z=mod(CUSTOM.z,1.0);\n"; //loop
+ code += " CUSTOM.z = mod(CUSTOM.z,1.0);\n"; //loop
} else {
- code += " CUSTOM.z=clamp(CUSTOM.z,0.0,1.0);\n"; //0 to 1 only
+ code += " CUSTOM.z = clamp(CUSTOM.z,0.0,1.0);\n"; //0 to 1 only
}
- code += " }\n";
+ code += " }\n";
//apply color
//apply hue rotation
if (tex_parameters[PARAM_SCALE].is_valid())
- code += " float tex_scale = textureLod(scale_texture,vec2(CUSTOM.y,0.0),0.0).r;\n";
+ code += " float tex_scale = textureLod(scale_texture,vec2(CUSTOM.y,0.0),0.0).r;\n";
else
- code += " float tex_scale = 1.0;\n";
+ code += " float tex_scale = 1.0;\n";
if (tex_parameters[PARAM_HUE_VARIATION].is_valid())
- code += " float tex_hue_variation = textureLod(hue_variation_texture,vec2(CUSTOM.y,0.0),0.0).r;\n";
+ code += " float tex_hue_variation = textureLod(hue_variation_texture,vec2(CUSTOM.y,0.0),0.0).r;\n";
else
- code += " float tex_hue_variation = 0.0;\n";
-
- code += " float hue_rot_angle = (hue_variation+tex_hue_variation)*3.1416*2.0*mix(1.0,hue_rot_rand*2.0-1.0,hue_variation_random);\n";
- code += " float hue_rot_c = cos(hue_rot_angle);\n";
- code += " float hue_rot_s = sin(hue_rot_angle);\n";
- code += " mat4 hue_rot_mat = mat4( vec4(0.299, 0.587, 0.114, 0.0),\n";
- code += " vec4(0.299, 0.587, 0.114, 0.0),\n";
- code += " vec4(0.299, 0.587, 0.114, 0.0),\n";
- code += " vec4(0.000, 0.000, 0.000, 1.0)) +\n";
- code += " \n";
- code += " mat4( vec4(0.701, -0.587, -0.114, 0.0),\n";
- code += " vec4(-0.299, 0.413, -0.114, 0.0),\n";
- code += " vec4(-0.300, -0.588, 0.886, 0.0),\n";
- code += " vec4(0.000, 0.000, 0.000, 0.0)) * hue_rot_c +\n";
- code += "\n";
- code += " mat4( vec4(0.168, 0.330, -0.497, 0.0),\n";
- code += " vec4(-0.328, 0.035, 0.292, 0.0),\n";
- code += " vec4(1.250, -1.050, -0.203, 0.0),\n";
- code += " vec4(0.000, 0.000, 0.000, 0.0)) * hue_rot_s;\n";
+ code += " float tex_hue_variation = 0.0;\n";
+
+ code += " float hue_rot_angle = (hue_variation+tex_hue_variation)*3.1416*2.0*mix(1.0,hue_rot_rand*2.0-1.0,hue_variation_random);\n";
+ code += " float hue_rot_c = cos(hue_rot_angle);\n";
+ code += " float hue_rot_s = sin(hue_rot_angle);\n";
+ code += " mat4 hue_rot_mat = mat4( vec4(0.299, 0.587, 0.114, 0.0),\n";
+ code += " vec4(0.299, 0.587, 0.114, 0.0),\n";
+ code += " vec4(0.299, 0.587, 0.114, 0.0),\n";
+ code += " vec4(0.000, 0.000, 0.000, 1.0)) +\n";
+ code += " mat4( vec4(0.701, -0.587, -0.114, 0.0),\n";
+ code += " vec4(-0.299, 0.413, -0.114, 0.0),\n";
+ code += " vec4(-0.300, -0.588, 0.886, 0.0),\n";
+ code += " vec4(0.000, 0.000, 0.000, 0.0)) * hue_rot_c +\n";
+ code += " mat4( vec4(0.168, 0.330, -0.497, 0.0),\n";
+ code += " vec4(-0.328, 0.035, 0.292, 0.0),\n";
+ code += " vec4(1.250, -1.050, -0.203, 0.0),\n";
+ code += " vec4(0.000, 0.000, 0.000, 0.0)) * hue_rot_s;\n";
if (color_ramp.is_valid()) {
- code += " COLOR = textureLod(color_ramp,vec2(CUSTOM.y,0.0),0.0) * hue_rot_mat;\n";
+ code += " COLOR = textureLod(color_ramp,vec2(CUSTOM.y,0.0),0.0) * hue_rot_mat;\n";
} else {
- code += " COLOR = color_value * hue_rot_mat;\n";
+ code += " COLOR = color_value * hue_rot_mat;\n";
}
if (emission_color_texture.is_valid() && emission_shape >= EMISSION_SHAPE_POINTS) {
- code += " COLOR*= texelFetch(emission_texture_color,emission_tex_ofs,0);\n";
+ code += " COLOR*= texelFetch(emission_texture_color,emission_tex_ofs,0);\n";
}
if (trail_color_modifier.is_valid()) {
- code += "if (trail_divisor>1) { COLOR*=textureLod(trail_color_modifier,vec2(float(int(NUMBER)%trail_divisor)/float(trail_divisor-1),0.0),0.0); }\n";
+ code += " if (trail_divisor > 1) { COLOR *= textureLod(trail_color_modifier,vec2(float(int(NUMBER)%trail_divisor)/float(trail_divisor-1),0.0),0.0); }\n";
}
code += "\n";
if (flags[FLAG_DISABLE_Z]) {
- code += " TRANSFORM[0]=vec4(cos(CUSTOM.x),-sin(CUSTOM.x),0.0,0.0);\n";
- code += " TRANSFORM[1]=vec4(sin(CUSTOM.x),cos(CUSTOM.x),0.0,0.0);\n";
- code += " TRANSFORM[2]=vec4(0.0,0.0,1.0,0.0);\n";
+ if (flags[FLAG_ALIGN_Y_TO_VELOCITY]) {
+ code += " if (length(VELOCITY) > 0.0) { TRANSFORM[1].xyz = normalize(VELOCITY); } else { TRANSFORM[1].xyz = normalize(TRANSFORM[1].xyz); }\n";
+ code += " TRANSFORM[0].xyz = normalize(cross(TRANSFORM[1].xyz,TRANSFORM[2].xyz));\n";
+ code += " TRANSFORM[2] = vec4(0.0,0.0,1.0,0.0);\n";
+ } else {
+ code += " TRANSFORM[0] = vec4(cos(CUSTOM.x),-sin(CUSTOM.x),0.0,0.0);\n";
+ code += " TRANSFORM[1] = vec4(sin(CUSTOM.x),cos(CUSTOM.x),0.0,0.0);\n";
+ code += " TRANSFORM[2] = vec4(0.0,0.0,1.0,0.0);\n";
+ }
} else {
//orient particle Y towards velocity
if (flags[FLAG_ALIGN_Y_TO_VELOCITY]) {
- code += " if (length(VELOCITY)>0.0) {TRANSFORM[1].xyz=normalize(VELOCITY);} else {TRANSFORM[1].xyz=normalize(TRANSFORM[1].xyz);}\n";
- code += " if (TRANSFORM[1].xyz==normalize(TRANSFORM[0].xyz)) {\n";
- code += "\tTRANSFORM[0].xyz=normalize(cross(normalize(TRANSFORM[1].xyz),normalize(TRANSFORM[2].xyz)));\n";
- code += "\tTRANSFORM[2].xyz=normalize(cross(normalize(TRANSFORM[0].xyz),normalize(TRANSFORM[1].xyz)));\n";
- code += " } else {\n";
- code += "\tTRANSFORM[2].xyz=normalize(cross(normalize(TRANSFORM[0].xyz),normalize(TRANSFORM[1].xyz)));\n";
- code += "\tTRANSFORM[0].xyz=normalize(cross(normalize(TRANSFORM[1].xyz),normalize(TRANSFORM[2].xyz)));\n";
- code += " }\n";
+ code += " if (length(VELOCITY) > 0.0) { TRANSFORM[1].xyz = normalize(VELOCITY); } else { TRANSFORM[1].xyz = normalize(TRANSFORM[1].xyz); }\n";
+ code += " if (TRANSFORM[1].xyz == normalize(TRANSFORM[0].xyz)) {\n";
+ code += " TRANSFORM[0].xyz = normalize(cross(normalize(TRANSFORM[1].xyz),normalize(TRANSFORM[2].xyz)));\n";
+ code += " TRANSFORM[2].xyz = normalize(cross(normalize(TRANSFORM[0].xyz),normalize(TRANSFORM[1].xyz)));\n";
+ code += " } else {\n";
+ code += " TRANSFORM[2].xyz = normalize(cross(normalize(TRANSFORM[0].xyz),normalize(TRANSFORM[1].xyz)));\n";
+ code += " TRANSFORM[0].xyz = normalize(cross(normalize(TRANSFORM[1].xyz),normalize(TRANSFORM[2].xyz)));\n";
+ code += " }\n";
} else {
- code += "\tTRANSFORM[0].xyz=normalize(TRANSFORM[0].xyz);\n";
- code += "\tTRANSFORM[1].xyz=normalize(TRANSFORM[1].xyz);\n";
- code += "\tTRANSFORM[2].xyz=normalize(TRANSFORM[2].xyz);\n";
+ code += " TRANSFORM[0].xyz = normalize(TRANSFORM[0].xyz);\n";
+ code += " TRANSFORM[1].xyz = normalize(TRANSFORM[1].xyz);\n";
+ code += " TRANSFORM[2].xyz = normalize(TRANSFORM[2].xyz);\n";
}
//turn particle by rotation in Y
if (flags[FLAG_ROTATE_Y]) {
- code += "\tTRANSFORM = TRANSFORM * mat4( vec4(cos(CUSTOM.x),0.0,-sin(CUSTOM.x),0.0), vec4(0.0,1.0,0.0,0.0),vec4(sin(CUSTOM.x),0.0,cos(CUSTOM.x),0.0),vec4(0.0,0.0,0.0,1.0));\n";
+ code += " TRANSFORM = TRANSFORM * mat4( vec4(cos(CUSTOM.x),0.0,-sin(CUSTOM.x),0.0), vec4(0.0,1.0,0.0,0.0),vec4(sin(CUSTOM.x),0.0,cos(CUSTOM.x),0.0),vec4(0.0,0.0,0.0,1.0));\n";
}
}
//scale by scale
- code += " float base_scale=mix(scale*tex_scale,1.0,scale_random*scale_rand);\n";
+ code += " float base_scale = mix(scale*tex_scale,1.0,scale_random*scale_rand);\n";
if (trail_size_modifier.is_valid()) {
- code += "if (trail_divisor>1) { base_scale*=textureLod(trail_size_modifier,vec2(float(int(NUMBER)%trail_divisor)/float(trail_divisor-1),0.0),0.0).r; } \n";
+ code += " if (trail_divisor > 1) { base_scale *= textureLod(trail_size_modifier,vec2(float(int(NUMBER)%trail_divisor)/float(trail_divisor-1),0.0),0.0).r; } \n";
}
- code += " TRANSFORM[0].xyz*=base_scale;\n";
- code += " TRANSFORM[1].xyz*=base_scale;\n";
- code += " TRANSFORM[2].xyz*=base_scale;\n";
+ code += " TRANSFORM[0].xyz *= base_scale;\n";
+ code += " TRANSFORM[1].xyz *= base_scale;\n";
+ code += " TRANSFORM[2].xyz *= base_scale;\n";
if (flags[FLAG_DISABLE_Z]) {
- code += " VELOCITY.z=0.0;\n";
- code += " TRANSFORM[3].z=0.0;\n";
+ code += " VELOCITY.z = 0.0;\n";
+ code += " TRANSFORM[3].z = 0.0;\n";
}
code += "}\n";
code += "\n";
@@ -913,9 +913,7 @@ void ParticlesMaterial::_queue_shader_change() {
if (material_mutex)
material_mutex->lock();
- print_line("queuing change");
if (!element.in_list()) {
- print_line("not in list, adding");
dirty_materials.add(&element);
}
@@ -1329,6 +1327,12 @@ Vector3 ParticlesMaterial::get_gravity() const {
return gravity;
}
+RID ParticlesMaterial::get_shader_rid() const {
+
+ ERR_FAIL_COND_V(!shader_map.has(current_key), RID());
+ return shader_map[current_key].shader;
+}
+
void ParticlesMaterial::_validate_property(PropertyInfo &property) const {
if (property.name == "color" && color_ramp.is_valid()) {
diff --git a/scene/3d/particles.h b/scene/3d/particles.h
index 2c109d6ec8..30080360bb 100644
--- a/scene/3d/particles.h
+++ b/scene/3d/particles.h
@@ -65,7 +65,7 @@ private:
float explosiveness_ratio;
float randomness_ratio;
float speed_scale;
- Rect3 visibility_aabb;
+ AABB visibility_aabb;
bool local_coords;
int fixed_fps;
bool fractional_delta;
@@ -82,7 +82,7 @@ protected:
virtual void _validate_property(PropertyInfo &property) const;
public:
- Rect3 get_aabb() const;
+ AABB get_aabb() const;
PoolVector<Face3> get_faces(uint32_t p_usage_flags) const;
void set_emitting(bool p_emitting);
@@ -92,7 +92,7 @@ public:
void set_pre_process_time(float p_time);
void set_explosiveness_ratio(float p_ratio);
void set_randomness_ratio(float p_ratio);
- void set_visibility_aabb(const Rect3 &p_aabb);
+ void set_visibility_aabb(const AABB &p_aabb);
void set_use_local_coordinates(bool p_enable);
void set_process_material(const Ref<Material> &p_material);
void set_speed_scale(float p_scale);
@@ -104,7 +104,7 @@ public:
float get_pre_process_time() const;
float get_explosiveness_ratio() const;
float get_randomness_ratio() const;
- Rect3 get_visibility_aabb() const;
+ AABB get_visibility_aabb() const;
bool get_use_local_coordinates() const;
Ref<Material> get_process_material() const;
float get_speed_scale() const;
@@ -128,7 +128,7 @@ public:
void restart();
- Rect3 capture_aabb() const;
+ AABB capture_aabb() const;
Particles();
~Particles();
};
@@ -388,6 +388,8 @@ public:
static void finish_shaders();
static void flush_changes();
+ RID get_shader_rid() const;
+
ParticlesMaterial();
~ParticlesMaterial();
};
diff --git a/scene/3d/path.cpp b/scene/3d/path.cpp
index 60245fe6ce..65f20210e1 100644
--- a/scene/3d/path.cpp
+++ b/scene/3d/path.cpp
@@ -85,9 +85,15 @@ void PathFollow::_update_transform() {
if (!c.is_valid())
return;
+ if (delta_offset == 0) {
+ return;
+ }
+
float o = offset;
- if (loop)
+
+ if (loop) {
o = Math::fposmod(o, c->get_baked_length());
+ }
Vector3 pos = c->interpolate_baked(o, cubic);
Transform t = get_transform();
@@ -101,14 +107,14 @@ void PathFollow::_update_transform() {
// see C. Dougan, The Parallel Transport Frame, Game Programming Gems 2 for example
// for a discussion about why not Frenet frame.
- Vector3 t_prev = pos - c->interpolate_baked(o - lookahead, cubic);
- Vector3 t_cur = c->interpolate_baked(o + lookahead, cubic) - pos;
+ Vector3 t_prev = (pos - c->interpolate_baked(o - delta_offset, cubic)).normalized();
+ Vector3 t_cur = (c->interpolate_baked(o + delta_offset, cubic) - pos).normalized();
Vector3 axis = t_prev.cross(t_cur);
- float dot = t_prev.normalized().dot(t_cur.normalized());
+ float dot = t_prev.dot(t_cur);
float angle = Math::acos(CLAMP(dot, -1, 1));
- if (axis.length() > CMP_EPSILON && angle > CMP_EPSILON) {
+ if (likely(Math::abs(angle) > CMP_EPSILON)) {
if (rotation_mode == ROTATION_Y) {
// assuming we're referring to global Y-axis. is this correct?
axis.x = 0;
@@ -116,27 +122,31 @@ void PathFollow::_update_transform() {
} else if (rotation_mode == ROTATION_XY) {
axis.z = 0;
} else if (rotation_mode == ROTATION_XYZ) {
- // all components are OK
+ // all components are allowed
}
- t.rotate_basis(axis.normalized(), angle);
+ if (likely(axis.length() > CMP_EPSILON)) {
+ t.rotate_basis(axis.normalized(), angle);
+ }
}
// do the additional tilting
float tilt_angle = c->interpolate_baked_tilt(o);
- Vector3 tilt_axis = t_cur; // is this correct??
+ Vector3 tilt_axis = t_cur; // not sure what tilt is supposed to do, is this correct??
- if (tilt_axis.length() > CMP_EPSILON && tilt_angle > CMP_EPSILON) {
+ if (likely(Math::abs(tilt_angle) > CMP_EPSILON)) {
if (rotation_mode == ROTATION_Y) {
tilt_axis.x = 0;
tilt_axis.z = 0;
} else if (rotation_mode == ROTATION_XY) {
tilt_axis.z = 0;
} else if (rotation_mode == ROTATION_XYZ) {
- // all components are OK
+ // all components are allowed
}
- t.rotate_basis(tilt_axis.normalized(), tilt_angle);
+ if (likely(tilt_axis.length() > CMP_EPSILON)) {
+ t.rotate_basis(tilt_axis.normalized(), tilt_angle);
+ }
}
t.translate(pos_offset);
@@ -195,8 +205,6 @@ bool PathFollow::_set(const StringName &p_name, const Variant &p_value) {
set_cubic_interpolation(p_value);
} else if (String(p_name) == "loop") {
set_loop(p_value);
- } else if (String(p_name) == "lookahead") {
- set_lookahead(p_value);
} else
return false;
@@ -219,8 +227,6 @@ bool PathFollow::_get(const StringName &p_name, Variant &r_ret) const {
r_ret = cubic;
} else if (String(p_name) == "loop") {
r_ret = loop;
- } else if (String(p_name) == "lookahead") {
- r_ret = lookahead;
} else
return false;
@@ -238,7 +244,6 @@ void PathFollow::_get_property_list(List<PropertyInfo> *p_list) const {
p_list->push_back(PropertyInfo(Variant::INT, "rotation_mode", PROPERTY_HINT_ENUM, "None,Y,XY,XYZ"));
p_list->push_back(PropertyInfo(Variant::BOOL, "cubic_interp"));
p_list->push_back(PropertyInfo(Variant::BOOL, "loop"));
- p_list->push_back(PropertyInfo(Variant::REAL, "lookahead", PROPERTY_HINT_RANGE, "0.001,1024.0,0.001"));
}
void PathFollow::_bind_methods() {
@@ -271,8 +276,9 @@ void PathFollow::_bind_methods() {
}
void PathFollow::set_offset(float p_offset) {
-
+ delta_offset = p_offset - offset;
offset = p_offset;
+
if (path)
_update_transform();
_change_notify("offset");
@@ -322,16 +328,6 @@ float PathFollow::get_unit_offset() const {
return 0;
}
-void PathFollow::set_lookahead(float p_lookahead) {
-
- lookahead = p_lookahead;
-}
-
-float PathFollow::get_lookahead() const {
-
- return lookahead;
-}
-
void PathFollow::set_rotation_mode(RotationMode p_rotation_mode) {
rotation_mode = p_rotation_mode;
@@ -356,11 +352,11 @@ bool PathFollow::has_loop() const {
PathFollow::PathFollow() {
offset = 0;
+ delta_offset = 0;
h_offset = 0;
v_offset = 0;
path = NULL;
rotation_mode = ROTATION_XYZ;
cubic = true;
loop = true;
- lookahead = 0.1;
}
diff --git a/scene/3d/path.h b/scene/3d/path.h
index 0f9a169f72..52760e0c75 100644
--- a/scene/3d/path.h
+++ b/scene/3d/path.h
@@ -67,10 +67,10 @@ public:
private:
Path *path;
+ real_t delta_offset; // change in offset since last _update_transform
real_t offset;
real_t h_offset;
real_t v_offset;
- real_t lookahead;
bool cubic;
bool loop;
RotationMode rotation_mode;
@@ -98,9 +98,6 @@ public:
void set_unit_offset(float p_unit_offset);
float get_unit_offset() const;
- void set_lookahead(float p_lookahead);
- float get_lookahead() const;
-
void set_loop(bool p_loop);
bool has_loop() const;
diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp
index d7fdf94d40..4e06b272e2 100644
--- a/scene/3d/physics_body.cpp
+++ b/scene/3d/physics_body.cpp
@@ -870,10 +870,10 @@ void RigidBody::_bind_methods() {
ADD_SIGNAL(MethodInfo("body_exited", PropertyInfo(Variant::OBJECT, "body")));
ADD_SIGNAL(MethodInfo("sleeping_state_changed"));
- BIND_ENUM_CONSTANT(MODE_STATIC);
- BIND_ENUM_CONSTANT(MODE_KINEMATIC);
BIND_ENUM_CONSTANT(MODE_RIGID);
+ BIND_ENUM_CONSTANT(MODE_STATIC);
BIND_ENUM_CONSTANT(MODE_CHARACTER);
+ BIND_ENUM_CONSTANT(MODE_KINEMATIC);
BIND_ENUM_CONSTANT(AXIS_LOCK_DISABLED);
BIND_ENUM_CONSTANT(AXIS_LOCK_X);
@@ -938,7 +938,7 @@ bool KinematicBody::move_and_collide(const Vector3 &p_motion, Collision &r_colli
Transform gt = get_global_transform();
PhysicsServer::MotionResult result;
- bool colliding = PhysicsServer::get_singleton()->body_test_motion(get_rid(), gt, p_motion, margin, &result);
+ bool colliding = PhysicsServer::get_singleton()->body_test_motion(get_rid(), gt, p_motion, &result);
if (colliding) {
r_collision.collider_metadata = result.collider_metadata;
@@ -988,12 +988,15 @@ Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Ve
on_floor = true;
floor_velocity = collision.collider_vel;
- /*if (collision.travel.length() < 0.01 && ABS((lv.x - floor_velocity.x)) < p_slope_stop_min_velocity) {
+ Vector3 rel_v = lv - floor_velocity;
+ Vector3 hv = rel_v - p_floor_direction * p_floor_direction.dot(rel_v);
+
+ if (collision.travel.length() < 0.05 && hv.length() < p_slope_stop_min_velocity) {
Transform gt = get_global_transform();
- gt.elements[2] -= collision.travel;
+ gt.origin -= collision.travel;
set_global_transform(gt);
- return Vector3();
- }*/
+ return floor_velocity - p_floor_direction * p_floor_direction.dot(floor_velocity);
+ }
} else if (collision.normal.dot(-p_floor_direction) >= Math::cos(p_floor_max_angle)) { //ceiling
on_ceiling = true;
} else {
@@ -1041,12 +1044,13 @@ bool KinematicBody::test_move(const Transform &p_from, const Vector3 &p_motion)
ERR_FAIL_COND_V(!is_inside_tree(), false);
- return PhysicsServer::get_singleton()->body_test_motion(get_rid(), p_from, p_motion, margin);
+ return PhysicsServer::get_singleton()->body_test_motion(get_rid(), p_from, p_motion);
}
void KinematicBody::set_safe_margin(float p_margin) {
margin = p_margin;
+ PhysicsServer::get_singleton()->body_set_kinematic_safe_margin(get_rid(), margin);
}
float KinematicBody::get_safe_margin() const {
diff --git a/scene/3d/physics_joint.cpp b/scene/3d/physics_joint.cpp
index aa127ab79f..1d779d31fe 100644
--- a/scene/3d/physics_joint.cpp
+++ b/scene/3d/physics_joint.cpp
@@ -32,13 +32,8 @@
void Joint::_update_joint(bool p_only_free) {
if (joint.is_valid()) {
- if (ba.is_valid() && bb.is_valid()) {
-
- if (exclude_from_collision)
- PhysicsServer::get_singleton()->body_add_collision_exception(ba, bb);
- else
- PhysicsServer::get_singleton()->body_remove_collision_exception(ba, bb);
- }
+ if (ba.is_valid() && bb.is_valid())
+ PhysicsServer::get_singleton()->body_remove_collision_exception(ba, bb);
PhysicsServer::get_singleton()->free(joint);
joint = RID();
@@ -52,33 +47,31 @@ void Joint::_update_joint(bool p_only_free) {
Node *node_a = has_node(get_node_a()) ? get_node(get_node_a()) : (Node *)NULL;
Node *node_b = has_node(get_node_b()) ? get_node(get_node_b()) : (Node *)NULL;
- if (!node_a && !node_b)
+ if (!node_a || !node_b)
return;
PhysicsBody *body_a = Object::cast_to<PhysicsBody>(node_a);
PhysicsBody *body_b = Object::cast_to<PhysicsBody>(node_b);
- if (!body_a && !body_b)
+ if (!body_a || !body_b)
return;
if (!body_a) {
SWAP(body_a, body_b);
- } else if (body_b) {
- //add a collision exception between both
- PhysicsServer::get_singleton()->body_add_collision_exception(body_a->get_rid(), body_b->get_rid());
}
joint = _configure_joint(body_a, body_b);
- if (joint.is_valid())
- PhysicsServer::get_singleton()->joint_set_solver_priority(joint, solver_priority);
+ if (!joint.is_valid())
+ return;
+
+ PhysicsServer::get_singleton()->joint_set_solver_priority(joint, solver_priority);
- if (body_b && joint.is_valid()) {
+ ba = body_a->get_rid();
+ bb = body_b->get_rid();
- ba = body_a->get_rid();
- bb = body_b->get_rid();
+ if (exclude_from_collision)
PhysicsServer::get_singleton()->body_add_collision_exception(body_a->get_rid(), body_b->get_rid());
- }
}
void Joint::set_node_a(const NodePath &p_node_a) {
@@ -129,8 +122,6 @@ void Joint::_notification(int p_what) {
case NOTIFICATION_EXIT_TREE: {
if (joint.is_valid()) {
_update_joint(true);
- //PhysicsServer::get_singleton()->free(joint);
- joint = RID();
}
} break;
}
diff --git a/scene/3d/portal.cpp b/scene/3d/portal.cpp
index 6c14f7dbc9..4fde29aab9 100644
--- a/scene/3d/portal.cpp
+++ b/scene/3d/portal.cpp
@@ -98,7 +98,7 @@ void Portal::_get_property_list(List<PropertyInfo> *p_list) const {
p_list->push_back(PropertyInfo(Variant::REAL, "connect_range", PROPERTY_HINT_RANGE, "0.1,4096,0.01"));
}
-Rect3 Portal::get_aabb() const {
+AABB Portal::get_aabb() const {
return aabb;
}
diff --git a/scene/3d/portal.h b/scene/3d/portal.h
index 6de3df8553..4ea208a718 100644
--- a/scene/3d/portal.h
+++ b/scene/3d/portal.h
@@ -53,7 +53,7 @@ class Portal : public VisualInstance {
Color disabled_color;
float connect_range;
- Rect3 aabb;
+ AABB aabb;
protected:
bool _set(const StringName &p_name, const Variant &p_value);
@@ -63,7 +63,7 @@ protected:
static void _bind_methods();
public:
- virtual Rect3 get_aabb() const;
+ virtual AABB get_aabb() const;
virtual PoolVector<Face3> get_faces(uint32_t p_usage_flags) const;
void set_enabled(bool p_enabled);
diff --git a/scene/3d/ray_cast.cpp b/scene/3d/ray_cast.cpp
index df6764ee1a..9f61cc64ea 100644
--- a/scene/3d/ray_cast.cpp
+++ b/scene/3d/ray_cast.cpp
@@ -48,14 +48,14 @@ Vector3 RayCast::get_cast_to() const {
return cast_to;
}
-void RayCast::set_collision_layer(uint32_t p_layer) {
+void RayCast::set_collision_mask(uint32_t p_mask) {
- collision_layer = p_layer;
+ collision_mask = p_mask;
}
-uint32_t RayCast::get_collision_layer() const {
+uint32_t RayCast::get_collision_mask() const {
- return collision_layer;
+ return collision_mask;
}
void RayCast::set_type_mask(uint32_t p_mask) {
@@ -63,6 +63,21 @@ void RayCast::set_type_mask(uint32_t p_mask) {
type_mask = p_mask;
}
+void RayCast::set_collision_mask_bit(int p_bit, bool p_value) {
+
+ uint32_t mask = get_collision_mask();
+ if (p_value)
+ mask |= 1 << p_bit;
+ else
+ mask &= ~(1 << p_bit);
+ set_collision_mask(mask);
+}
+
+bool RayCast::get_collision_mask_bit(int p_bit) const {
+
+ return get_collision_mask() & (1 << p_bit);
+}
+
uint32_t RayCast::get_type_mask() const {
return type_mask;
@@ -172,7 +187,7 @@ void RayCast::_update_raycast_state() {
PhysicsDirectSpaceState::RayResult rr;
- if (dss->intersect_ray(gt.get_origin(), gt.xform(to), rr, exclude, collision_layer, type_mask)) {
+ if (dss->intersect_ray(gt.get_origin(), gt.xform(to), rr, exclude, collision_mask, type_mask)) {
collided = true;
against = rr.collider_id;
@@ -245,15 +260,18 @@ void RayCast::_bind_methods() {
ClassDB::bind_method(D_METHOD("clear_exceptions"), &RayCast::clear_exceptions);
- ClassDB::bind_method(D_METHOD("set_collision_layer", "layer"), &RayCast::set_collision_layer);
- ClassDB::bind_method(D_METHOD("get_collision_layer"), &RayCast::get_collision_layer);
+ ClassDB::bind_method(D_METHOD("set_collision_mask", "mask"), &RayCast::set_collision_mask);
+ ClassDB::bind_method(D_METHOD("get_collision_mask"), &RayCast::get_collision_mask);
+
+ ClassDB::bind_method(D_METHOD("set_collision_mask_bit", "bit", "value"), &RayCast::set_collision_mask_bit);
+ ClassDB::bind_method(D_METHOD("get_collision_mask_bit", "bit"), &RayCast::get_collision_mask_bit);
ClassDB::bind_method(D_METHOD("set_type_mask", "mask"), &RayCast::set_type_mask);
ClassDB::bind_method(D_METHOD("get_type_mask"), &RayCast::get_type_mask);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "cast_to"), "set_cast_to", "get_cast_to");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_layer", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_layer", "get_collision_layer");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask");
ADD_PROPERTY(PropertyInfo(Variant::INT, "type_mask", PROPERTY_HINT_FLAGS, "Static,Kinematic,Rigid,Character,Area"), "set_type_mask", "get_type_mask");
}
@@ -325,7 +343,7 @@ RayCast::RayCast() {
against = 0;
collided = false;
against_shape = 0;
- collision_layer = 1;
+ collision_mask = 1;
type_mask = PhysicsDirectSpaceState::TYPE_MASK_COLLISION;
cast_to = Vector3(0, -1, 0);
debug_shape = NULL;
diff --git a/scene/3d/ray_cast.h b/scene/3d/ray_cast.h
index fd566cd343..cac1596264 100644
--- a/scene/3d/ray_cast.h
+++ b/scene/3d/ray_cast.h
@@ -47,7 +47,7 @@ class RayCast : public Spatial {
Set<RID> exclude;
- uint32_t collision_layer;
+ uint32_t collision_mask;
uint32_t type_mask;
Node *debug_shape;
@@ -69,8 +69,11 @@ public:
void set_cast_to(const Vector3 &p_point);
Vector3 get_cast_to() const;
- void set_collision_layer(uint32_t p_layer);
- uint32_t get_collision_layer() const;
+ void set_collision_mask(uint32_t p_mask);
+ uint32_t get_collision_mask() const;
+
+ void set_collision_mask_bit(int p_bit, bool p_value);
+ bool get_collision_mask_bit(int p_bit) const;
void set_type_mask(uint32_t p_mask);
uint32_t get_type_mask() const;
diff --git a/scene/3d/reflection_probe.cpp b/scene/3d/reflection_probe.cpp
index 46b105cd21..0e575ec152 100644
--- a/scene/3d/reflection_probe.cpp
+++ b/scene/3d/reflection_probe.cpp
@@ -178,9 +178,9 @@ ReflectionProbe::UpdateMode ReflectionProbe::get_update_mode() const {
return update_mode;
}
-Rect3 ReflectionProbe::get_aabb() const {
+AABB ReflectionProbe::get_aabb() const {
- Rect3 aabb;
+ AABB aabb;
aabb.position = -origin_offset;
aabb.size = origin_offset + extents;
return aabb;
diff --git a/scene/3d/reflection_probe.h b/scene/3d/reflection_probe.h
index 7c328a8f16..26f17fdcf9 100644
--- a/scene/3d/reflection_probe.h
+++ b/scene/3d/reflection_probe.h
@@ -101,7 +101,7 @@ public:
void set_update_mode(UpdateMode p_mode);
UpdateMode get_update_mode() const;
- virtual Rect3 get_aabb() const;
+ virtual AABB get_aabb() const;
virtual PoolVector<Face3> get_faces(uint32_t p_usage_flags) const;
ReflectionProbe();
diff --git a/scene/3d/room_instance.cpp b/scene/3d/room_instance.cpp
index 439b6bfdf8..47a7b8bfb9 100644
--- a/scene/3d/room_instance.cpp
+++ b/scene/3d/room_instance.cpp
@@ -66,12 +66,12 @@ void Room::_notification(int p_what) {
}
}
-Rect3 Room::get_aabb() const {
+AABB Room::get_aabb() const {
if (room.is_null())
- return Rect3();
+ return AABB();
- return Rect3();
+ return AABB();
}
PoolVector<Face3> Room::get_faces(uint32_t p_usage_flags) const {
diff --git a/scene/3d/room_instance.h b/scene/3d/room_instance.h
index b9a64b6670..3069ea2eba 100644
--- a/scene/3d/room_instance.h
+++ b/scene/3d/room_instance.h
@@ -71,7 +71,7 @@ public:
NOTIFICATION_AREA_CHANGED = 60
};
- virtual Rect3 get_aabb() const;
+ virtual AABB get_aabb() const;
virtual PoolVector<Face3> get_faces(uint32_t p_usage_flags) const;
void set_room(const Ref<RoomBounds> &p_room);
diff --git a/scene/3d/spatial.cpp b/scene/3d/spatial.cpp
index 0dfd80ca90..588aa2881a 100644
--- a/scene/3d/spatial.cpp
+++ b/scene/3d/spatial.cpp
@@ -233,7 +233,7 @@ void Spatial::set_transform(const Transform &p_transform) {
data.dirty |= DIRTY_VECTORS;
_change_notify("translation");
_change_notify("rotation");
- _change_notify("rotation_deg");
+ _change_notify("rotation_degrees");
_change_notify("scale");
_propagate_transform_changed(this);
if (data.notify_local_transform) {
@@ -327,17 +327,11 @@ void Spatial::set_rotation(const Vector3 &p_euler_rad) {
}
}
-void Spatial::set_rotation_in_degrees(const Vector3 &p_euler_deg) {
+void Spatial::set_rotation_degrees(const Vector3 &p_euler_deg) {
set_rotation(p_euler_deg * Math_PI / 180.0);
}
-void Spatial::_set_rotation_deg(const Vector3 &p_euler_deg) {
-
- WARN_PRINT("Deprecated method Spatial._set_rotation_deg(): This method was renamed to set_rotation_deg. Please adapt your code accordingly, as the old method will be obsoleted.");
- set_rotation_in_degrees(p_euler_deg);
-}
-
void Spatial::set_scale(const Vector3 &p_scale) {
if (data.dirty & DIRTY_VECTORS) {
@@ -370,19 +364,11 @@ Vector3 Spatial::get_rotation() const {
return data.rotation;
}
-Vector3 Spatial::get_rotation_in_degrees() const {
+Vector3 Spatial::get_rotation_degrees() const {
return get_rotation() * 180.0 / Math_PI;
}
-// Kept for compatibility after rename to set_rotd.
-// Could be removed after a couple releases.
-Vector3 Spatial::_get_rotation_deg() const {
-
- WARN_PRINT("Deprecated method Spatial._get_rotation_deg(): This method was renamed to get_rotation_deg. Please adapt your code accordingly, as the old method will be obsoleted.");
- return get_rotation_in_degrees();
-}
-
Vector3 Spatial::get_scale() const {
if (data.dirty & DIRTY_VECTORS) {
@@ -691,10 +677,10 @@ void Spatial::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_transform"), &Spatial::get_transform);
ClassDB::bind_method(D_METHOD("set_translation", "translation"), &Spatial::set_translation);
ClassDB::bind_method(D_METHOD("get_translation"), &Spatial::get_translation);
- ClassDB::bind_method(D_METHOD("set_rotation", "rotation_rad"), &Spatial::set_rotation);
+ ClassDB::bind_method(D_METHOD("set_rotation", "radians"), &Spatial::set_rotation);
ClassDB::bind_method(D_METHOD("get_rotation"), &Spatial::get_rotation);
- ClassDB::bind_method(D_METHOD("set_rotation_deg", "rotation_deg"), &Spatial::set_rotation_in_degrees);
- ClassDB::bind_method(D_METHOD("get_rotation_deg"), &Spatial::get_rotation_in_degrees);
+ ClassDB::bind_method(D_METHOD("set_rotation_degrees", "degrees"), &Spatial::set_rotation_degrees);
+ ClassDB::bind_method(D_METHOD("get_rotation_degrees"), &Spatial::get_rotation_degrees);
ClassDB::bind_method(D_METHOD("set_scale", "scale"), &Spatial::set_scale);
ClassDB::bind_method(D_METHOD("get_scale"), &Spatial::get_scale);
ClassDB::bind_method(D_METHOD("set_global_transform", "global"), &Spatial::set_global_transform);
@@ -705,10 +691,6 @@ void Spatial::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_set_as_toplevel"), &Spatial::is_set_as_toplevel);
ClassDB::bind_method(D_METHOD("get_world"), &Spatial::get_world);
- // TODO: Obsolete those two methods (old name) properly (GH-4397)
- ClassDB::bind_method(D_METHOD("_set_rotation_deg", "rotation_deg"), &Spatial::_set_rotation_deg);
- ClassDB::bind_method(D_METHOD("_get_rotation_deg"), &Spatial::_get_rotation_deg);
-
#ifdef TOOLS_ENABLED
ClassDB::bind_method(D_METHOD("_update_gizmo"), &Spatial::_update_gizmo);
#endif
@@ -764,7 +746,7 @@ void Spatial::_bind_methods() {
ADD_PROPERTYNZ(PropertyInfo(Variant::TRANSFORM, "transform", PROPERTY_HINT_NONE, ""), "set_transform", "get_transform");
ADD_PROPERTYNZ(PropertyInfo(Variant::TRANSFORM, "global_transform", PROPERTY_HINT_NONE, "", 0), "set_global_transform", "get_global_transform");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "translation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_translation", "get_translation");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "rotation_deg", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_rotation_deg", "get_rotation_deg");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "rotation_degrees", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_rotation_degrees", "get_rotation_degrees");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "rotation", PROPERTY_HINT_NONE, "", 0), "set_rotation", "get_rotation");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "scale", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_scale", "get_scale");
ADD_GROUP("Visibility", "");
diff --git a/scene/3d/spatial.h b/scene/3d/spatial.h
index b912d1f906..8f53b4a066 100644
--- a/scene/3d/spatial.h
+++ b/scene/3d/spatial.h
@@ -106,10 +106,6 @@ class Spatial : public Node {
void _notify_dirty();
void _propagate_transform_changed(Spatial *p_origin);
- // Deprecated, should be removed in a future version.
- void _set_rotation_deg(const Vector3 &p_euler_deg);
- Vector3 _get_rotation_deg() const;
-
void _propagate_visibility_changed();
protected:
@@ -136,12 +132,12 @@ public:
void set_translation(const Vector3 &p_translation);
void set_rotation(const Vector3 &p_euler_rad);
- void set_rotation_in_degrees(const Vector3 &p_euler_deg);
+ void set_rotation_degrees(const Vector3 &p_euler_deg);
void set_scale(const Vector3 &p_scale);
Vector3 get_translation() const;
Vector3 get_rotation() const;
- Vector3 get_rotation_in_degrees() const;
+ Vector3 get_rotation_degrees() const;
Vector3 get_scale() const;
void set_transform(const Transform &p_transform);
diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp
index 49a3205f21..18ebc22c8b 100644
--- a/scene/3d/sprite_3d.cpp
+++ b/scene/3d/sprite_3d.cpp
@@ -188,7 +188,7 @@ void SpriteBase3D::_queue_update() {
call_deferred(SceneStringNames::get_singleton()->_im_update);
}
-Rect3 SpriteBase3D::get_aabb() const {
+AABB SpriteBase3D::get_aabb() const {
return aabb;
}
@@ -407,7 +407,7 @@ void Sprite3D::_draw() {
}
}
- Rect3 aabb;
+ AABB aabb;
for (int i = 0; i < 4; i++) {
VS::get_singleton()->immediate_normal(immediate, normal);
@@ -698,7 +698,7 @@ void AnimatedSprite3D::_draw() {
}
}
- Rect3 aabb;
+ AABB aabb;
for (int i = 0; i < 4; i++) {
VS::get_singleton()->immediate_normal(immediate, normal);
diff --git a/scene/3d/sprite_3d.h b/scene/3d/sprite_3d.h
index 1165392cb2..d18553a504 100644
--- a/scene/3d/sprite_3d.h
+++ b/scene/3d/sprite_3d.h
@@ -71,7 +71,7 @@ private:
Vector3::Axis axis;
float pixel_size;
- Rect3 aabb;
+ AABB aabb;
RID immediate;
@@ -87,7 +87,7 @@ protected:
void _notification(int p_what);
static void _bind_methods();
virtual void _draw() = 0;
- _FORCE_INLINE_ void set_aabb(const Rect3 &p_aabb) { aabb = p_aabb; }
+ _FORCE_INLINE_ void set_aabb(const AABB &p_aabb) { aabb = p_aabb; }
_FORCE_INLINE_ RID &get_immediate() { return immediate; }
void _queue_update();
@@ -130,7 +130,7 @@ public:
virtual Rect2 get_item_rect() const = 0;
- virtual Rect3 get_aabb() const;
+ virtual AABB get_aabb() const;
virtual PoolVector<Face3> get_faces(uint32_t p_usage_flags) const;
SpriteBase3D();
diff --git a/scene/3d/visibility_notifier.cpp b/scene/3d/visibility_notifier.cpp
index d3203bacec..47144c4b78 100644
--- a/scene/3d/visibility_notifier.cpp
+++ b/scene/3d/visibility_notifier.cpp
@@ -60,7 +60,7 @@ void VisibilityNotifier::_exit_camera(Camera *p_camera) {
}
}
-void VisibilityNotifier::set_aabb(const Rect3 &p_aabb) {
+void VisibilityNotifier::set_aabb(const AABB &p_aabb) {
if (aabb == p_aabb)
return;
@@ -74,7 +74,7 @@ void VisibilityNotifier::set_aabb(const Rect3 &p_aabb) {
update_gizmo();
}
-Rect3 VisibilityNotifier::get_aabb() const {
+AABB VisibilityNotifier::get_aabb() const {
return aabb;
}
@@ -108,7 +108,7 @@ void VisibilityNotifier::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_aabb"), &VisibilityNotifier::get_aabb);
ClassDB::bind_method(D_METHOD("is_on_screen"), &VisibilityNotifier::is_on_screen);
- ADD_PROPERTY(PropertyInfo(Variant::RECT3, "aabb"), "set_aabb", "get_aabb");
+ ADD_PROPERTY(PropertyInfo(Variant::AABB, "aabb"), "set_aabb", "get_aabb");
ADD_SIGNAL(MethodInfo("camera_entered", PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Camera")));
ADD_SIGNAL(MethodInfo("camera_exited", PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Camera")));
@@ -118,7 +118,7 @@ void VisibilityNotifier::_bind_methods() {
VisibilityNotifier::VisibilityNotifier() {
- aabb = Rect3(Vector3(-1, -1, -1), Vector3(2, 2, 2));
+ aabb = AABB(Vector3(-1, -1, -1), Vector3(2, 2, 2));
set_notify_transform(true);
}
@@ -252,8 +252,8 @@ void VisibilityEnabler::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "pause_animations"), "set_enabler", "is_enabler_enabled", ENABLER_PAUSE_ANIMATIONS);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "freeze_bodies"), "set_enabler", "is_enabler_enabled", ENABLER_FREEZE_BODIES);
- BIND_ENUM_CONSTANT(ENABLER_FREEZE_BODIES);
BIND_ENUM_CONSTANT(ENABLER_PAUSE_ANIMATIONS);
+ BIND_ENUM_CONSTANT(ENABLER_FREEZE_BODIES);
BIND_ENUM_CONSTANT(ENABLER_MAX);
}
diff --git a/scene/3d/visibility_notifier.h b/scene/3d/visibility_notifier.h
index 0b83e0534e..fc06cf5aec 100644
--- a/scene/3d/visibility_notifier.h
+++ b/scene/3d/visibility_notifier.h
@@ -39,7 +39,7 @@ class VisibilityNotifier : public Spatial {
Set<Camera *> cameras;
- Rect3 aabb;
+ AABB aabb;
protected:
virtual void _screen_enter() {}
@@ -53,8 +53,8 @@ protected:
void _exit_camera(Camera *p_camera);
public:
- void set_aabb(const Rect3 &p_aabb);
- Rect3 get_aabb() const;
+ void set_aabb(const AABB &p_aabb);
+ AABB get_aabb() const;
bool is_on_screen() const;
VisibilityNotifier();
diff --git a/scene/3d/visual_instance.cpp b/scene/3d/visual_instance.cpp
index fa35d982eb..b92e7ead04 100644
--- a/scene/3d/visual_instance.cpp
+++ b/scene/3d/visual_instance.cpp
@@ -33,7 +33,7 @@
#include "servers/visual_server.h"
#include "skeleton.h"
-Rect3 VisualInstance::get_transformed_aabb() const {
+AABB VisualInstance::get_transformed_aabb() const {
return get_global_transform().xform(get_aabb());
}
diff --git a/scene/3d/visual_instance.h b/scene/3d/visual_instance.h
index c405236d2c..5827f1e1fb 100644
--- a/scene/3d/visual_instance.h
+++ b/scene/3d/visual_instance.h
@@ -62,10 +62,10 @@ public:
};
RID get_instance() const;
- virtual Rect3 get_aabb() const = 0;
+ virtual AABB get_aabb() const = 0;
virtual PoolVector<Face3> get_faces(uint32_t p_usage_flags) const = 0;
- virtual Rect3 get_transformed_aabb() const; // helper
+ virtual AABB get_transformed_aabb() const; // helper
void set_base(const RID &p_base);
diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp
index a38bee1b43..6be3ff88d9 100644
--- a/scene/animation/animation_player.cpp
+++ b/scene/animation/animation_player.cpp
@@ -202,7 +202,6 @@ void AnimationPlayer::_notification(int p_what) {
if (!Engine::get_singleton()->is_editor_hint() && animation_set.has(autoplay)) {
play(autoplay);
- set_autoplay(""); //this line is the fix for autoplay issues with animatio
_animation_process(0);
}
} break;
@@ -405,6 +404,10 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float
if (a->value_track_get_update_mode(i) == Animation::UPDATE_CONTINUOUS || (p_delta == 0 && a->value_track_get_update_mode(i) == Animation::UPDATE_DISCRETE)) { //delta == 0 means seek
Variant value = a->value_track_interpolate(i, p_time);
+
+ if (value == Variant())
+ continue;
+
//thanks to trigger mode, this should be solved now..
/*
if (p_delta==0 && value.get_type()==Variant::STRING)
@@ -434,7 +437,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float
pa->object->set(pa->prop, value, &valid); //you are not speshul
#ifdef DEBUG_ENABLED
if (!valid) {
- ERR_PRINTS("Failed setting track value '" + String(pa->owner->path) + "'. Check if property exists or the type of key is valid");
+ ERR_PRINTS("Failed setting track value '" + String(pa->owner->path) + "'. Check if property exists or the type of key is valid. Animation '" + a->get_name() + "' at node '" + get_path() + "'.");
}
#endif
@@ -442,7 +445,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float
case SP_NODE2D_POS: {
#ifdef DEBUG_ENABLED
if (value.get_type() != Variant::VECTOR2) {
- ERR_PRINTS("Position key at time " + rtos(p_time) + " in Animation Track '" + String(pa->owner->path) + "' not of type Vector2()");
+ ERR_PRINTS("Position key at time " + rtos(p_time) + " in Animation Track '" + String(pa->owner->path) + "' not of type Vector2(). Animation '" + a->get_name() + "' at node '" + get_path() + "'.");
}
#endif
static_cast<Node2D *>(pa->object)->set_position(value);
@@ -450,7 +453,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float
case SP_NODE2D_ROT: {
#ifdef DEBUG_ENABLED
if (value.is_num()) {
- ERR_PRINTS("Rotation key at time " + rtos(p_time) + " in Animation Track '" + String(pa->owner->path) + "' not numerical");
+ ERR_PRINTS("Rotation key at time " + rtos(p_time) + " in Animation Track '" + String(pa->owner->path) + "' not numerical. Animation '" + a->get_name() + "' at node '" + get_path() + "'.");
}
#endif
@@ -459,7 +462,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float
case SP_NODE2D_SCALE: {
#ifdef DEBUG_ENABLED
if (value.get_type() != Variant::VECTOR2) {
- ERR_PRINTS("Scale key at time " + rtos(p_time) + " in Animation Track '" + String(pa->owner->path) + "' not of type Vector2()");
+ ERR_PRINTS("Scale key at time " + rtos(p_time) + " in Animation Track '" + String(pa->owner->path) + "' not of type Vector2()." + a->get_name() + "' at node '" + get_path() + "'.");
}
#endif
@@ -529,12 +532,12 @@ void AnimationPlayer::_animation_process_data(PlaybackData &cd, float p_delta, f
if (&cd == &playback.current) {
- if (!backwards && cd.pos < len && next_pos == len /*&& playback.blend.empty()*/) {
+ if (!backwards && cd.pos <= len && next_pos == len /*&& playback.blend.empty()*/) {
//playback finished
end_notify = true;
}
- if (backwards && cd.pos > 0 && next_pos == 0 /*&& playback.blend.empty()*/) {
+ if (backwards && cd.pos >= 0 && next_pos == 0 /*&& playback.blend.empty()*/) {
//playback finished
end_notify = true;
}
@@ -542,7 +545,14 @@ void AnimationPlayer::_animation_process_data(PlaybackData &cd, float p_delta, f
} else {
- next_pos = Math::fposmod(next_pos, len);
+ float looped_next_pos = Math::fposmod(next_pos, len);
+ if (looped_next_pos == 0 && next_pos != 0) {
+ // Loop multiples of the length to it, rather than 0
+ // so state at time=length is previewable in the editor
+ next_pos = len;
+ } else {
+ next_pos = looped_next_pos;
+ }
}
cd.pos = next_pos;
@@ -615,7 +625,7 @@ void AnimationPlayer::_animation_update_transforms() {
pa->object->set(pa->prop, pa->value_accum, &valid); //you are not speshul
#ifdef DEBUG_ENABLED
if (!valid) {
- ERR_PRINTS("Failed setting key at time " + rtos(playback.current.pos) + " in Animation '" + get_current_animation() + "', Track '" + String(pa->owner->path) + "'. Check if property exists or the type of key is right for the property");
+ ERR_PRINTS("Failed setting key at time " + rtos(playback.current.pos) + " in Animation '" + get_current_animation() + "' at Node '" + get_path() + "', Track '" + String(pa->owner->path) + "'. Check if property exists or the type of key is right for the property");
}
#endif
@@ -623,7 +633,7 @@ void AnimationPlayer::_animation_update_transforms() {
case SP_NODE2D_POS: {
#ifdef DEBUG_ENABLED
if (pa->value_accum.get_type() != Variant::VECTOR2) {
- ERR_PRINTS("Position key at time " + rtos(playback.current.pos) + " in Animation '" + get_current_animation() + "', Track '" + String(pa->owner->path) + "' not of type Vector2()");
+ ERR_PRINTS("Position key at time " + rtos(playback.current.pos) + " in Animation '" + get_current_animation() + "' at Node '" + get_path() + "', Track '" + String(pa->owner->path) + "' not of type Vector2()");
}
#endif
static_cast<Node2D *>(pa->object)->set_position(pa->value_accum);
@@ -631,7 +641,7 @@ void AnimationPlayer::_animation_update_transforms() {
case SP_NODE2D_ROT: {
#ifdef DEBUG_ENABLED
if (pa->value_accum.is_num()) {
- ERR_PRINTS("Rotation key at time " + rtos(playback.current.pos) + " in Animation '" + get_current_animation() + "', Track '" + String(pa->owner->path) + "' not numerical");
+ ERR_PRINTS("Rotation key at time " + rtos(playback.current.pos) + " in Animation '" + get_current_animation() + "' at Node '" + get_path() + "', Track '" + String(pa->owner->path) + "' not numerical");
}
#endif
@@ -640,7 +650,7 @@ void AnimationPlayer::_animation_update_transforms() {
case SP_NODE2D_SCALE: {
#ifdef DEBUG_ENABLED
if (pa->value_accum.get_type() != Variant::VECTOR2) {
- ERR_PRINTS("Scale key at time " + rtos(playback.current.pos) + " in Animation '" + get_current_animation() + "', Track '" + String(pa->owner->path) + "' not of type Vector2()");
+ ERR_PRINTS("Scale key at time " + rtos(playback.current.pos) + " in Animation '" + get_current_animation() + "' at Node '" + get_path() + "', Track '" + String(pa->owner->path) + "' not of type Vector2()");
}
#endif
@@ -1254,7 +1264,7 @@ void AnimationPlayer::_bind_methods() {
ClassDB::bind_method(D_METHOD("advance", "delta"), &AnimationPlayer::advance);
ADD_GROUP("Playback Options", "playback_");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "playback_process_mode", PROPERTY_HINT_ENUM, "Fixed,Idle"), "set_animation_process_mode", "get_animation_process_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "playback_process_mode", PROPERTY_HINT_ENUM, "Physics,Idle"), "set_animation_process_mode", "get_animation_process_mode");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "playback_default_blend_time", PROPERTY_HINT_RANGE, "0,4096,0.01"), "set_default_blend_time", "get_default_blend_time");
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "root_node"), "set_root", "get_root");
diff --git a/scene/animation/animation_tree_player.cpp b/scene/animation/animation_tree_player.cpp
index d564671bcf..ad5329c94b 100644
--- a/scene/animation/animation_tree_player.cpp
+++ b/scene/animation/animation_tree_player.cpp
@@ -1796,7 +1796,7 @@ void AnimationTreePlayer::_bind_methods() {
ClassDB::bind_method(D_METHOD("recompute_caches"), &AnimationTreePlayer::recompute_caches);
ADD_GROUP("Playback", "playback_");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "playback_process_mode", PROPERTY_HINT_ENUM, "Fixed,Idle"), "set_animation_process_mode", "get_animation_process_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "playback_process_mode", PROPERTY_HINT_ENUM, "Physics,Idle"), "set_animation_process_mode", "get_animation_process_mode");
BIND_ENUM_CONSTANT(NODE_OUTPUT);
BIND_ENUM_CONSTANT(NODE_ANIMATION);
diff --git a/scene/animation/tween.cpp b/scene/animation/tween.cpp
index fb327191b9..40d06dc756 100644
--- a/scene/animation/tween.cpp
+++ b/scene/animation/tween.cpp
@@ -222,7 +222,7 @@ void Tween::_bind_methods() {
ADD_SIGNAL(MethodInfo("tween_step", PropertyInfo(Variant::OBJECT, "object"), PropertyInfo(Variant::STRING, "key"), PropertyInfo(Variant::REAL, "elapsed"), PropertyInfo(Variant::OBJECT, "value")));
ADD_SIGNAL(MethodInfo("tween_completed", PropertyInfo(Variant::OBJECT, "object"), PropertyInfo(Variant::STRING, "key")));
- ADD_PROPERTY(PropertyInfo(Variant::INT, "playback_process_mode", PROPERTY_HINT_ENUM, "Fixed,Idle"), "set_tween_process_mode", "get_tween_process_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "playback_process_mode", PROPERTY_HINT_ENUM, "Physics,Idle"), "set_tween_process_mode", "get_tween_process_mode");
BIND_ENUM_CONSTANT(TWEEN_PROCESS_PHYSICS);
BIND_ENUM_CONSTANT(TWEEN_PROCESS_IDLE);
@@ -416,10 +416,10 @@ Variant Tween::_run_equation(InterpolateData &p_data) {
result = r;
} break;
- case Variant::RECT3: {
- Rect3 i = initial_val;
- Rect3 d = delta_val;
- Rect3 r;
+ case Variant::AABB: {
+ AABB i = initial_val;
+ AABB d = delta_val;
+ AABB r;
APPLY_EQUATION(position.x);
APPLY_EQUATION(position.y);
@@ -956,10 +956,10 @@ bool Tween::_calc_delta_val(const Variant &p_initial_val, const Variant &p_final
case Variant::QUAT:
delta_val = final_val.operator Quat() - initial_val.operator Quat();
break;
- case Variant::RECT3: {
- Rect3 i = initial_val;
- Rect3 f = final_val;
- delta_val = Rect3(f.position - i.position, f.size - i.size);
+ case Variant::AABB: {
+ AABB i = initial_val;
+ AABB f = final_val;
+ delta_val = AABB(f.position - i.position, f.size - i.size);
} break;
case Variant::TRANSFORM: {
Transform i = initial_val;
diff --git a/scene/audio/audio_player.cpp b/scene/audio/audio_player.cpp
index 058b162e83..08b01c6a4c 100644
--- a/scene/audio/audio_player.cpp
+++ b/scene/audio/audio_player.cpp
@@ -31,20 +31,7 @@
#include "engine.h"
-void AudioStreamPlayer::_mix_audio() {
-
- if (!stream_playback.is_valid()) {
- return;
- }
-
- if (!active) {
- return;
- }
-
- if (setseek >= 0.0) {
- stream_playback->start(setseek);
- setseek = -1.0; //reset seek
- }
+void AudioStreamPlayer::_mix_internal(bool p_fadeout) {
int bus_index = AudioServer::get_singleton()->thread_find_bus_index(bus);
@@ -52,19 +39,24 @@ void AudioStreamPlayer::_mix_audio() {
AudioFrame *buffer = mix_buffer.ptr();
int buffer_size = mix_buffer.size();
+ if (p_fadeout) {
+ buffer_size = MIN(buffer_size, 16); //short fadeout ramp
+ }
+
//mix
stream_playback->mix(buffer, 1.0, buffer_size);
//multiply volume interpolating to avoid clicks if this changes
+ float target_volume = p_fadeout ? -80.0 : volume_db;
float vol = Math::db2linear(mix_volume_db);
- float vol_inc = (Math::db2linear(volume_db) - vol) / float(buffer_size);
+ float vol_inc = (Math::db2linear(target_volume) - vol) / float(buffer_size);
for (int i = 0; i < buffer_size; i++) {
buffer[i] *= vol;
vol += vol_inc;
}
//set volume for next mix
- mix_volume_db = volume_db;
+ mix_volume_db = target_volume;
AudioFrame *targets[4] = { NULL, NULL, NULL, NULL };
@@ -95,6 +87,30 @@ void AudioStreamPlayer::_mix_audio() {
}
}
+void AudioStreamPlayer::_mix_audio() {
+
+ if (!stream_playback.is_valid()) {
+ return;
+ }
+
+ if (!active) {
+ return;
+ }
+
+ if (setseek >= 0.0) {
+ if (stream_playback->is_playing()) {
+
+ //fade out to avoid pops
+ _mix_internal(true);
+ }
+ stream_playback->start(setseek);
+ setseek = -1.0; //reset seek
+ mix_volume_db = volume_db; //reset ramp
+ }
+
+ _mix_internal(false);
+}
+
void AudioStreamPlayer::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE) {
@@ -163,7 +179,7 @@ float AudioStreamPlayer::get_volume_db() const {
void AudioStreamPlayer::play(float p_from_pos) {
if (stream_playback.is_valid()) {
- mix_volume_db = volume_db; //reset volume ramp
+ //mix_volume_db = volume_db; do not reset volume ramp here, can cause clicks
setseek = p_from_pos;
active = true;
set_process_internal(true);
diff --git a/scene/audio/audio_player.h b/scene/audio/audio_player.h
index 4bfc44730d..6e9d623433 100644
--- a/scene/audio/audio_player.h
+++ b/scene/audio/audio_player.h
@@ -59,6 +59,7 @@ private:
MixTarget mix_target;
+ void _mix_internal(bool p_fadeout);
void _mix_audio();
static void _mix_audios(void *self) { reinterpret_cast<AudioStreamPlayer *>(self)->_mix_audio(); }
diff --git a/scene/gui/check_button.cpp b/scene/gui/check_button.cpp
index e68159e27f..77fdedd5e5 100644
--- a/scene/gui/check_button.cpp
+++ b/scene/gui/check_button.cpp
@@ -32,6 +32,23 @@
#include "print_string.h"
#include "servers/visual_server.h"
+Size2 CheckButton::get_minimum_size() const {
+
+ Size2 minsize = Button::get_minimum_size();
+
+ Ref<Texture> on = Control::get_icon("on");
+ Ref<Texture> off = Control::get_icon("off");
+ Size2 tex_size = Size2(0, 0);
+ if (!on.is_null())
+ tex_size = Size2(on->get_width(), on->get_height());
+ if (!off.is_null())
+ tex_size = Size2(MAX(tex_size.width, off->get_width()), MAX(tex_size.height, off->get_height()));
+ minsize += Size2(tex_size.width + get_constant("hseparation"), 0);
+ minsize.height = MAX(minsize.height, tex_size.height);
+
+ return get_stylebox("normal")->get_minimum_size() + minsize;
+}
+
void CheckButton::_notification(int p_what) {
if (p_what == NOTIFICATION_DRAW) {
@@ -41,9 +58,11 @@ void CheckButton::_notification(int p_what) {
Ref<Texture> on = Control::get_icon("on");
Ref<Texture> off = Control::get_icon("off");
+ Ref<StyleBox> sb = get_stylebox("normal");
+ Size2 sb_ofs = Size2(sb->get_margin(MARGIN_RIGHT), sb->get_margin(MARGIN_TOP));
Vector2 ofs;
- ofs.x = get_size().width - on->get_width();
- ofs.y = int((get_size().height - on->get_height()) / 2);
+ ofs.x = get_minimum_size().width - (on->get_width() + sb_ofs.width);
+ ofs.y = sb_ofs.height;
if (is_pressed())
on->draw(ci, ofs);
diff --git a/scene/gui/check_button.h b/scene/gui/check_button.h
index af3b80fe04..eb68943fe7 100644
--- a/scene/gui/check_button.h
+++ b/scene/gui/check_button.h
@@ -39,6 +39,7 @@ class CheckButton : public Button {
GDCLASS(CheckButton, Button);
protected:
+ virtual Size2 get_minimum_size() const;
void _notification(int p_what);
public:
diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp
index e58cbe373b..dbd7c1bbc0 100644
--- a/scene/gui/color_picker.cpp
+++ b/scene/gui/color_picker.cpp
@@ -40,12 +40,15 @@ void ColorPicker::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_THEME_CHANGED: {
//sample->set_texture(get_icon("color_sample"));
+ btn_pick->set_icon(get_icon("screen_picker", "ColorPicker"));
+ bt_add_preset->set_icon(get_icon("add_preset"));
_update_controls();
} break;
case NOTIFICATION_ENTER_TREE: {
btn_pick->set_icon(get_icon("screen_picker", "ColorPicker"));
+ bt_add_preset->set_icon(get_icon("add_preset"));
_update_color();
} break;
@@ -601,7 +604,6 @@ ColorPicker::ColorPicker()
preset->connect("draw", this, "_update_presets");
bt_add_preset = memnew(Button);
- bt_add_preset->set_icon(get_icon("add_preset"));
bt_add_preset->set_tooltip(TTR("Add current color as a preset"));
bt_add_preset->connect("pressed", this, "_add_preset_pressed");
bbc->add_child(bt_add_preset);
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index 91c5263bf5..adca78d1d4 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -45,7 +45,7 @@
#endif
#include <stdio.h>
-Variant Control::edit_get_state() const {
+Dictionary Control::_edit_get_state() const {
Dictionary s;
s["rect"] = get_rect();
@@ -59,22 +59,78 @@ Variant Control::edit_get_state() const {
s["anchors"] = anchors;
return s;
}
-void Control::edit_set_state(const Variant &p_state) {
+void Control::_edit_set_state(const Dictionary &p_state) {
- Dictionary s = p_state;
+ Dictionary state = p_state;
- Rect2 state = s["rect"];
- set_position(state.position);
- set_size(state.size);
- set_rotation(s["rotation"]);
- set_scale(s["scale"]);
- Array anchors = s["anchors"];
+ Rect2 rect = state["rect"];
+ set_position(rect.position);
+ set_size(rect.size);
+ set_rotation(state["rotation"]);
+ set_scale(state["scale"]);
+ Array anchors = state["anchors"];
set_anchor(MARGIN_LEFT, anchors[0]);
set_anchor(MARGIN_TOP, anchors[1]);
set_anchor(MARGIN_RIGHT, anchors[2]);
set_anchor(MARGIN_BOTTOM, anchors[3]);
}
+void Control::_edit_set_position(const Point2 &p_position) {
+ set_position(p_position);
+};
+
+Point2 Control::_edit_get_position() const {
+ return get_position();
+};
+
+void Control::_edit_set_rect(const Rect2 &p_edit_rect) {
+
+ Transform2D xform = _get_internal_transform();
+
+ Vector2 new_pos = xform.basis_xform(p_edit_rect.position);
+
+ Vector2 pos = get_position() + new_pos;
+
+ Rect2 new_rect = get_rect();
+ new_rect.position = pos.snapped(Vector2(1, 1));
+ new_rect.size = p_edit_rect.size.snapped(Vector2(1, 1));
+
+ set_position(new_rect.position);
+ set_size(new_rect.size);
+}
+
+Rect2 Control::_edit_get_rect() const {
+ return Rect2(Point2(), get_size());
+}
+
+bool Control::_edit_use_rect() const {
+ return true;
+}
+
+void Control::_edit_set_rotation(float p_rotation) {
+ set_rotation(p_rotation);
+}
+
+float Control::_edit_get_rotation() const {
+ return get_rotation();
+}
+
+bool Control::_edit_use_rotation() const {
+ return true;
+}
+
+void Control::_edit_set_pivot(const Point2 &p_pivot) {
+ set_pivot_offset(p_pivot);
+}
+
+Point2 Control::_edit_get_pivot() const {
+ return get_pivot_offset();
+}
+
+bool Control::_edit_use_pivot() const {
+ return true;
+}
+
void Control::set_custom_minimum_size(const Size2 &p_custom) {
if (p_custom == data.custom_minimum_size)
@@ -96,7 +152,7 @@ Size2 Control::get_combined_minimum_size() const {
return minsize;
}
-Size2 Control::edit_get_minimum_size() const {
+Size2 Control::_edit_get_minimum_size() const {
return get_combined_minimum_size();
}
@@ -110,23 +166,6 @@ Transform2D Control::_get_internal_transform() const {
return offset.affine_inverse() * (rot_scale * offset);
}
-void Control::edit_set_rect(const Rect2 &p_edit_rect) {
-
- Transform2D xform = _get_internal_transform();
-
- // xform[2] += get_position();
-
- Vector2 new_pos = xform.basis_xform(p_edit_rect.position);
-
- Vector2 pos = get_position() + new_pos;
-
- Rect2 new_rect = get_rect();
- new_rect.position = pos.snapped(Vector2(1, 1));
- new_rect.size = p_edit_rect.size.snapped(Vector2(1, 1));
-
- set_position(new_rect.position);
- set_size(new_rect.size);
-}
bool Control::_set(const StringName &p_name, const Variant &p_value) {
@@ -1210,7 +1249,7 @@ Size2 Control::get_parent_area_size() const {
if (data.parent_canvas_item) {
- parent_size = data.parent_canvas_item->get_item_rect().size;
+ parent_size = data.parent_canvas_item->_edit_get_rect().size;
} else {
parent_size = get_viewport()->get_visible_rect().size;
@@ -1289,7 +1328,7 @@ float Control::_get_parent_range(int p_idx) const {
}
if (data.parent_canvas_item) {
- return data.parent_canvas_item->get_item_rect().size[p_idx & 1];
+ return data.parent_canvas_item->_edit_get_rect().size[p_idx & 1];
} else {
return get_viewport()->get_visible_rect().size[p_idx & 1];
}
@@ -1751,11 +1790,6 @@ Rect2 Control::get_rect() const {
return Rect2(get_position(), get_size());
}
-Rect2 Control::get_item_rect() const {
-
- return Rect2(Point2(), get_size());
-}
-
void Control::add_icon_override(const StringName &p_name, const Ref<Texture> &p_icon) {
ERR_FAIL_COND(p_icon.is_null());
@@ -1847,6 +1881,25 @@ Control *Control::find_next_valid_focus() const {
while (true) {
+ // If the focus property is manually overwritten, attempt to use it.
+
+ if (!data.focus_next.is_empty()) {
+ Node *n = get_node(data.focus_next);
+ if (n) {
+ from = Object::cast_to<Control>(n);
+
+ if (!from) {
+
+ ERR_EXPLAIN("Next focus node is not a control: " + n->get_name());
+ ERR_FAIL_V(NULL);
+ }
+ } else {
+ return NULL;
+ }
+ if (from->is_visible() && from->get_focus_mode() != FOCUS_NONE)
+ return from;
+ }
+
// find next child
Control *next_child = NULL;
@@ -1926,6 +1979,25 @@ Control *Control::find_prev_valid_focus() const {
while (true) {
+ // If the focus property is manually overwritten, attempt to use it.
+
+ if (!data.focus_prev.is_empty()) {
+ Node *n = get_node(data.focus_prev);
+ if (n) {
+ from = Object::cast_to<Control>(n);
+
+ if (!from) {
+
+ ERR_EXPLAIN("Prev focus node is not a control: " + n->get_name());
+ ERR_FAIL_V(NULL);
+ }
+ } else {
+ return NULL;
+ }
+ if (from->is_visible() && from->get_focus_mode() != FOCUS_NONE)
+ return from;
+ }
+
// find prev child
Control *prev_child = NULL;
@@ -2157,6 +2229,26 @@ NodePath Control::get_focus_neighbour(Margin p_margin) const {
return data.focus_neighbour[p_margin];
}
+void Control::set_focus_next(const NodePath &p_next) {
+
+ data.focus_next = p_next;
+}
+
+NodePath Control::get_focus_next() const {
+
+ return data.focus_next;
+}
+
+void Control::set_focus_previous(const NodePath &p_prev) {
+
+ data.focus_prev = p_prev;
+}
+
+NodePath Control::get_focus_previous() const {
+
+ return data.focus_prev;
+}
+
#define MAX_NEIGHBOUR_SEARCH_COUNT 512
Control *Control::_get_focus_neighbour(Margin p_margin, int p_count) {
@@ -2172,7 +2264,7 @@ Control *Control::_get_focus_neighbour(Margin p_margin, int p_count) {
if (!c) {
- ERR_EXPLAIN("Next focus node is not a control: " + n->get_name());
+ ERR_EXPLAIN("Neighbour focus node is not a control: " + n->get_name());
ERR_FAIL_V(NULL);
}
} else {
@@ -2196,7 +2288,7 @@ Control *Control::_get_focus_neighbour(Margin p_margin, int p_count) {
Point2 points[4];
Transform2D xform = get_global_transform();
- Rect2 rect = get_item_rect();
+ Rect2 rect = _edit_get_rect();
points[0] = xform.xform(rect.position);
points[1] = xform.xform(rect.position + Point2(rect.size.x, 0));
@@ -2255,7 +2347,7 @@ void Control::_window_find_focus_neighbour(const Vector2 &p_dir, Node *p_at, con
Point2 points[4];
Transform2D xform = c->get_global_transform();
- Rect2 rect = c->get_item_rect();
+ Rect2 rect = c->_edit_get_rect();
points[0] = xform.xform(rect.position);
points[1] = xform.xform(rect.position + Point2(rect.size.x, 0));
@@ -2416,24 +2508,14 @@ float Control::get_rotation() const {
return data.rotation;
}
-void Control::set_rotation_deg(float p_degrees) {
+void Control::set_rotation_degrees(float p_degrees) {
set_rotation(Math::deg2rad(p_degrees));
}
-float Control::get_rotation_deg() const {
+float Control::get_rotation_degrees() const {
return Math::rad2deg(get_rotation());
}
-// Kept for compatibility after rename to {s,g}et_rotation_deg.
-// Could be removed after a couple releases.
-void Control::_set_rotation_deg(float p_degrees) {
- WARN_PRINT("Deprecated method Control._set_rotation_deg(): This method was renamed to set_rotation_deg. Please adapt your code accordingly, as the old method will be obsoleted.");
- set_rotation_deg(p_degrees);
-}
-float Control::_get_rotation_deg() const {
- WARN_PRINT("Deprecated method Control._get_rotation_deg(): This method was renamed to get_rotation_deg. Please adapt your code accordingly, as the old method will be obsoleted.");
- return get_rotation_deg();
-}
//needed to update the control if the font changes..
void Control::_ref_font(Ref<Font> p_sc) {
@@ -2606,9 +2688,7 @@ void Control::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_custom_minimum_size", "size"), &Control::set_custom_minimum_size);
ClassDB::bind_method(D_METHOD("set_global_position", "position"), &Control::set_global_position);
ClassDB::bind_method(D_METHOD("set_rotation", "radians"), &Control::set_rotation);
- ClassDB::bind_method(D_METHOD("set_rotation_deg", "degrees"), &Control::set_rotation_deg);
- // TODO: Obsolete this method (old name) properly (GH-4397)
- ClassDB::bind_method(D_METHOD("_set_rotation_deg", "degrees"), &Control::_set_rotation_deg);
+ ClassDB::bind_method(D_METHOD("set_rotation_degrees", "degrees"), &Control::set_rotation_degrees);
ClassDB::bind_method(D_METHOD("set_scale", "scale"), &Control::set_scale);
ClassDB::bind_method(D_METHOD("set_pivot_offset", "pivot_offset"), &Control::set_pivot_offset);
ClassDB::bind_method(D_METHOD("get_margin", "margin"), &Control::get_margin);
@@ -2617,9 +2697,7 @@ void Control::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_position"), &Control::get_position);
ClassDB::bind_method(D_METHOD("get_size"), &Control::get_size);
ClassDB::bind_method(D_METHOD("get_rotation"), &Control::get_rotation);
- ClassDB::bind_method(D_METHOD("get_rotation_deg"), &Control::get_rotation_deg);
- // TODO: Obsolete this method (old name) properly (GH-4397)
- ClassDB::bind_method(D_METHOD("_get_rotation_deg"), &Control::_get_rotation_deg);
+ ClassDB::bind_method(D_METHOD("get_rotation_degrees"), &Control::get_rotation_degrees);
ClassDB::bind_method(D_METHOD("get_scale"), &Control::get_scale);
ClassDB::bind_method(D_METHOD("get_pivot_offset"), &Control::get_pivot_offset);
ClassDB::bind_method(D_METHOD("get_custom_minimum_size"), &Control::get_custom_minimum_size);
@@ -2691,6 +2769,12 @@ void Control::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_focus_neighbour", "margin", "neighbour"), &Control::set_focus_neighbour);
ClassDB::bind_method(D_METHOD("get_focus_neighbour", "margin"), &Control::get_focus_neighbour);
+ ClassDB::bind_method(D_METHOD("set_focus_next", "next"), &Control::set_focus_next);
+ ClassDB::bind_method(D_METHOD("get_focus_next"), &Control::get_focus_next);
+
+ ClassDB::bind_method(D_METHOD("set_focus_previous", "previous"), &Control::set_focus_previous);
+ ClassDB::bind_method(D_METHOD("get_focus_previous"), &Control::get_focus_previous);
+
ClassDB::bind_method(D_METHOD("force_drag", "data", "preview"), &Control::force_drag);
ClassDB::bind_method(D_METHOD("set_mouse_filter", "filter"), &Control::set_mouse_filter);
@@ -2738,7 +2822,7 @@ void Control::_bind_methods() {
ADD_PROPERTYNZ(PropertyInfo(Variant::VECTOR2, "rect_position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_position", "get_position");
ADD_PROPERTYNZ(PropertyInfo(Variant::VECTOR2, "rect_size", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_size", "get_size");
ADD_PROPERTYNZ(PropertyInfo(Variant::VECTOR2, "rect_min_size"), "set_custom_minimum_size", "get_custom_minimum_size");
- ADD_PROPERTYNZ(PropertyInfo(Variant::REAL, "rect_rotation", PROPERTY_HINT_RANGE, "-1080,1080,0.01"), "set_rotation_deg", "get_rotation_deg");
+ ADD_PROPERTYNZ(PropertyInfo(Variant::REAL, "rect_rotation", PROPERTY_HINT_RANGE, "-1080,1080,0.01"), "set_rotation_degrees", "get_rotation_degrees");
ADD_PROPERTYNO(PropertyInfo(Variant::VECTOR2, "rect_scale"), "set_scale", "get_scale");
ADD_PROPERTYNO(PropertyInfo(Variant::VECTOR2, "rect_pivot_offset"), "set_pivot_offset", "get_pivot_offset");
ADD_PROPERTYNO(PropertyInfo(Variant::BOOL, "rect_clip_content"), "set_clip_contents", "is_clipping_contents");
@@ -2751,6 +2835,8 @@ void Control::_bind_methods() {
ADD_PROPERTYINZ(PropertyInfo(Variant::NODE_PATH, "focus_neighbour_top"), "set_focus_neighbour", "get_focus_neighbour", MARGIN_TOP);
ADD_PROPERTYINZ(PropertyInfo(Variant::NODE_PATH, "focus_neighbour_right"), "set_focus_neighbour", "get_focus_neighbour", MARGIN_RIGHT);
ADD_PROPERTYINZ(PropertyInfo(Variant::NODE_PATH, "focus_neighbour_bottom"), "set_focus_neighbour", "get_focus_neighbour", MARGIN_BOTTOM);
+ ADD_PROPERTYNZ(PropertyInfo(Variant::NODE_PATH, "focus_next"), "set_focus_next", "get_focus_next");
+ ADD_PROPERTYNZ(PropertyInfo(Variant::NODE_PATH, "focus_previous"), "set_focus_previous", "get_focus_previous");
ADD_GROUP("Mouse", "mouse_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "mouse_filter", PROPERTY_HINT_ENUM, "Stop,Pass,Ignore"), "set_mouse_filter", "get_mouse_filter");
@@ -2811,12 +2897,12 @@ void Control::_bind_methods() {
BIND_ENUM_CONSTANT(PRESET_WIDE);
BIND_ENUM_CONSTANT(PRESET_MODE_MINSIZE);
- BIND_ENUM_CONSTANT(PRESET_MODE_KEEP_HEIGHT);
BIND_ENUM_CONSTANT(PRESET_MODE_KEEP_WIDTH);
+ BIND_ENUM_CONSTANT(PRESET_MODE_KEEP_HEIGHT);
BIND_ENUM_CONSTANT(PRESET_MODE_KEEP_SIZE);
- BIND_ENUM_CONSTANT(SIZE_EXPAND);
BIND_ENUM_CONSTANT(SIZE_FILL);
+ BIND_ENUM_CONSTANT(SIZE_EXPAND);
BIND_ENUM_CONSTANT(SIZE_EXPAND_FILL);
BIND_ENUM_CONSTANT(SIZE_SHRINK_CENTER);
BIND_ENUM_CONSTANT(SIZE_SHRINK_END);
diff --git a/scene/gui/control.h b/scene/gui/control.h
index 5b146b4454..92d1c969fc 100644
--- a/scene/gui/control.h
+++ b/scene/gui/control.h
@@ -191,6 +191,8 @@ private:
ObjectID modal_prev_focus_owner;
NodePath focus_neighbour[4];
+ NodePath focus_next;
+ NodePath focus_prev;
HashMap<StringName, Ref<Texture>, StringNameHasher> icon_override;
HashMap<StringName, Ref<Shader>, StringNameHasher> shader_override;
@@ -226,10 +228,6 @@ private:
void _size_changed();
String _get_tooltip() const;
- // Deprecated, should be removed in a future version.
- void _set_rotation_deg(float p_degrees);
- float _get_rotation_deg() const;
-
void _ref_font(Ref<Font> p_sc);
void _unref_font(Ref<Font> p_sc);
void _font_changed();
@@ -273,10 +271,25 @@ public:
};
- virtual Variant edit_get_state() const;
- virtual void edit_set_state(const Variant &p_state);
- virtual void edit_set_rect(const Rect2 &p_edit_rect);
- virtual Size2 edit_get_minimum_size() const;
+ virtual Dictionary _edit_get_state() const;
+ virtual void _edit_set_state(const Dictionary &p_state);
+
+ virtual void _edit_set_position(const Point2 &p_position);
+ virtual Point2 _edit_get_position() const;
+
+ virtual void _edit_set_rect(const Rect2 &p_edit_rect);
+ virtual Rect2 _edit_get_rect() const;
+ virtual bool _edit_use_rect() const;
+
+ virtual void _edit_set_rotation(float p_rotation);
+ virtual float _edit_get_rotation() const;
+ virtual bool _edit_use_rotation() const;
+
+ virtual void _edit_set_pivot(const Point2 &p_pivot);
+ virtual Point2 _edit_get_pivot() const;
+ virtual bool _edit_use_pivot() const;
+
+ virtual Size2 _edit_get_minimum_size() const;
void accept_event();
@@ -332,9 +345,9 @@ public:
Rect2 get_window_rect() const; ///< use with care, as it blocks waiting for the visual server
void set_rotation(float p_radians);
- void set_rotation_deg(float p_degrees);
+ void set_rotation_degrees(float p_degrees);
float get_rotation() const;
- float get_rotation_deg() const;
+ float get_rotation_degrees() const;
void set_h_grow_direction(GrowDirection p_direction);
GrowDirection get_h_grow_direction() const;
@@ -378,6 +391,11 @@ public:
void set_focus_neighbour(Margin p_margin, const NodePath &p_neighbour);
NodePath get_focus_neighbour(Margin p_margin) const;
+ void set_focus_next(const NodePath &p_next);
+ NodePath get_focus_next() const;
+ void set_focus_previous(const NodePath &p_prev);
+ NodePath get_focus_previous() const;
+
Control *get_focus_owner() const;
void set_mouse_filter(MouseFilter p_filter);
@@ -424,7 +442,6 @@ public:
CursorShape get_default_cursor_shape() const;
virtual CursorShape get_cursor_shape(const Point2 &p_pos = Point2i()) const;
- virtual Rect2 get_item_rect() const;
virtual Transform2D get_transform() const;
bool is_toplevel_control() const;
diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp
index 320dad9301..6aba535572 100644
--- a/scene/gui/file_dialog.cpp
+++ b/scene/gui/file_dialog.cpp
@@ -115,7 +115,9 @@ Vector<String> FileDialog::get_selected_files() const {
void FileDialog::update_dir() {
dir->set_text(dir_access->get_current_dir());
- drives->select(dir_access->get_current_drive());
+ if (drives->is_visible()) {
+ drives->select(dir_access->get_current_drive());
+ }
}
void FileDialog::_dir_entered(String p_dir) {
@@ -321,6 +323,9 @@ void FileDialog::update_file_list() {
while ((item = dir_access->get_next(&isdir)) != "") {
+ if (item == ".")
+ continue;
+
ishidden = dir_access->current_is_hidden();
if (show_hidden || !ishidden) {
@@ -342,7 +347,7 @@ void FileDialog::update_file_list() {
while (!dirs.empty()) {
String &dir_name = dirs.front()->get();
TreeItem *ti = tree->create_item(root);
- ti->set_text(0, dir_name + "/");
+ ti->set_text(0, dir_name);
ti->set_icon(0, folder);
Dictionary d;
@@ -667,7 +672,6 @@ void FileDialog::_update_drives() {
drives->show();
for (int i = 0; i < dir_access->get_drive_count(); i++) {
- String d = dir_access->get_drive(i);
drives->add_item(dir_access->get_drive(i));
}
@@ -758,38 +762,42 @@ FileDialog::FileDialog() {
mode = MODE_SAVE_FILE;
set_title(RTR("Save a File"));
+ HBoxContainer *hbc = memnew(HBoxContainer);
+ hbc->add_child(memnew(Label(RTR("Path:"))));
dir = memnew(LineEdit);
- HBoxContainer *pathhb = memnew(HBoxContainer);
- pathhb->add_child(dir);
+ hbc->add_child(dir);
dir->set_h_size_flags(SIZE_EXPAND_FILL);
refresh = memnew(ToolButton);
refresh->connect("pressed", this, "_update_file_list");
- pathhb->add_child(refresh);
+ hbc->add_child(refresh);
drives = memnew(OptionButton);
- pathhb->add_child(drives);
+ hbc->add_child(drives);
drives->connect("item_selected", this, "_select_drive");
makedir = memnew(Button);
makedir->set_text(RTR("Create Folder"));
makedir->connect("pressed", this, "_make_dir");
- pathhb->add_child(makedir);
-
- vbc->add_margin_child(RTR("Path:"), pathhb);
+ hbc->add_child(makedir);
+ vbc->add_child(hbc);
tree = memnew(Tree);
tree->set_hide_root(true);
vbc->add_margin_child(RTR("Directories & Files:"), tree, true);
+ hbc = memnew(HBoxContainer);
+ hbc->add_child(memnew(Label(RTR("File:"))));
file = memnew(LineEdit);
- //add_child(file);
- vbc->add_margin_child(RTR("File:"), file);
-
+ file->set_stretch_ratio(4);
+ file->set_h_size_flags(SIZE_EXPAND_FILL);
+ hbc->add_child(file);
filter = memnew(OptionButton);
- //add_child(filter);
- vbc->add_margin_child(RTR("Filter:"), filter);
+ filter->set_stretch_ratio(3);
+ filter->set_h_size_flags(SIZE_EXPAND_FILL);
filter->set_clip_text(true); //too many extensions overflow it
+ hbc->add_child(filter);
+ vbc->add_child(hbc);
dir_access = DirAccess::create(DirAccess::ACCESS_RESOURCES);
access = ACCESS_RESOURCES;
diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp
index 0d3cccc2b5..da52fb39e0 100644
--- a/scene/gui/graph_edit.cpp
+++ b/scene/gui/graph_edit.cpp
@@ -284,7 +284,6 @@ void GraphEdit::_notification(int p_what) {
zoom_reset->set_icon(get_icon("reset"));
zoom_plus->set_icon(get_icon("more"));
snap_button->set_icon(get_icon("snap"));
- //zoom_icon->set_texture( get_icon("Zoom", "EditorIcons"));
}
if (p_what == NOTIFICATION_DRAW) {
@@ -965,6 +964,19 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) {
emit_signal("delete_nodes_request");
accept_event();
}
+
+ Ref<InputEventMagnifyGesture> magnify_gesture = p_ev;
+ if (magnify_gesture.is_valid()) {
+
+ set_zoom_custom(zoom * magnify_gesture->get_factor(), magnify_gesture->get_position());
+ }
+
+ Ref<InputEventPanGesture> pan_gesture = p_ev;
+ if (pan_gesture.is_valid()) {
+
+ h_scroll->set_value(h_scroll->get_value() + h_scroll->get_page() * pan_gesture->get_delta().x / 8);
+ v_scroll->set_value(v_scroll->get_value() + v_scroll->get_page() * pan_gesture->get_delta().y / 8);
+ }
}
void GraphEdit::clear_connections() {
@@ -976,6 +988,11 @@ void GraphEdit::clear_connections() {
void GraphEdit::set_zoom(float p_zoom) {
+ set_zoom_custom(p_zoom, get_size() / 2);
+}
+
+void GraphEdit::set_zoom_custom(float p_zoom, const Vector2 &p_center) {
+
p_zoom = CLAMP(p_zoom, MIN_ZOOM, MAX_ZOOM);
if (zoom == p_zoom)
return;
@@ -983,7 +1000,7 @@ void GraphEdit::set_zoom(float p_zoom) {
zoom_minus->set_disabled(zoom == MIN_ZOOM);
zoom_plus->set_disabled(zoom == MAX_ZOOM);
- Vector2 sbofs = (Vector2(h_scroll->get_value(), v_scroll->get_value()) + get_size() / 2) / zoom;
+ Vector2 sbofs = (Vector2(h_scroll->get_value(), v_scroll->get_value()) + p_center) / zoom;
zoom = p_zoom;
top_layer->update();
@@ -993,7 +1010,7 @@ void GraphEdit::set_zoom(float p_zoom) {
if (is_visible_in_tree()) {
- Vector2 ofs = sbofs * zoom - get_size() / 2;
+ Vector2 ofs = sbofs * zoom - p_center;
h_scroll->set_value(ofs.x);
v_scroll->set_value(ofs.y);
}
diff --git a/scene/gui/graph_edit.h b/scene/gui/graph_edit.h
index 4656b50133..e8e530848d 100644
--- a/scene/gui/graph_edit.h
+++ b/scene/gui/graph_edit.h
@@ -179,6 +179,7 @@ public:
bool is_valid_connection_type(int p_type, int p_with_type) const;
void set_zoom(float p_zoom);
+ void set_zoom_custom(float p_zoom, const Vector2 &p_center);
float get_zoom() const;
GraphEditFilter *get_top_layer() const { return top_layer; }
diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp
index a034c7224f..51ab49e643 100644
--- a/scene/gui/item_list.cpp
+++ b/scene/gui/item_list.cpp
@@ -489,7 +489,7 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) {
if (mb->get_button_index() == BUTTON_RIGHT) {
- emit_signal("item_rmb_selected", i, pos);
+ emit_signal("item_rmb_selected", i, get_local_mouse_position());
}
} else {
@@ -500,7 +500,7 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) {
if (items[i].selected && mb->get_button_index() == BUTTON_RIGHT) {
- emit_signal("item_rmb_selected", i, pos);
+ emit_signal("item_rmb_selected", i, get_local_mouse_position());
} else {
bool selected = !items[i].selected;
@@ -515,7 +515,7 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) {
if (mb->get_button_index() == BUTTON_RIGHT) {
- emit_signal("item_rmb_selected", i, pos);
+ emit_signal("item_rmb_selected", i, get_local_mouse_position());
} else if (/*select_mode==SELECT_SINGLE &&*/ mb->is_doubleclick()) {
emit_signal("item_activated", i);
@@ -525,6 +525,11 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) {
return;
}
+ if (mb->get_button_index() == BUTTON_RIGHT) {
+ emit_signal("rmb_clicked", mb->get_position());
+
+ return;
+ }
}
if (mb.is_valid() && mb->get_button_index() == BUTTON_WHEEL_UP && mb->is_pressed()) {
@@ -708,6 +713,12 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) {
}
}
}
+
+ Ref<InputEventPanGesture> pan_gesture = p_event;
+ if (pan_gesture.is_valid()) {
+
+ scroll_bar->set_value(scroll_bar->get_value() + scroll_bar->get_page() * pan_gesture->get_delta().y / 8);
+ }
}
void ItemList::ensure_current_is_visible() {
@@ -754,7 +765,7 @@ void ItemList::_notification(int p_what) {
int width = size.width - bg->get_minimum_size().width;
if (scroll_bar->is_visible()) {
- width -= mw + bg->get_margin(MARGIN_RIGHT);
+ width -= mw;
}
draw_style_box(bg, Rect2(Point2(), size));
@@ -1107,7 +1118,7 @@ void ItemList::_notification(int p_what) {
}
for (int i = 0; i < separators.size(); i++) {
- draw_line(Vector2(bg->get_margin(MARGIN_LEFT), base_ofs.y + separators[i]), Vector2(size.width - bg->get_margin(MARGIN_RIGHT), base_ofs.y + separators[i]), guide_color);
+ draw_line(Vector2(bg->get_margin(MARGIN_LEFT), base_ofs.y + separators[i]), Vector2(width, base_ofs.y + separators[i]), guide_color);
}
}
}
@@ -1397,6 +1408,7 @@ void ItemList::_bind_methods() {
ADD_SIGNAL(MethodInfo("item_rmb_selected", PropertyInfo(Variant::INT, "index"), PropertyInfo(Variant::VECTOR2, "at_position")));
ADD_SIGNAL(MethodInfo("multi_selected", PropertyInfo(Variant::INT, "index"), PropertyInfo(Variant::BOOL, "selected")));
ADD_SIGNAL(MethodInfo("item_activated", PropertyInfo(Variant::INT, "index")));
+ ADD_SIGNAL(MethodInfo("rmb_clicked", PropertyInfo(Variant::VECTOR2, "at_position")));
GLOBAL_DEF("gui/timers/incremental_search_max_interval_msec", 2000);
}
diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp
index ed8eff436c..f7bf1cd9ea 100644
--- a/scene/gui/line_edit.cpp
+++ b/scene/gui/line_edit.cpp
@@ -48,7 +48,7 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
if (b.is_valid()) {
- if (b->is_pressed() && b->get_button_index() == BUTTON_RIGHT) {
+ if (b->is_pressed() && b->get_button_index() == BUTTON_RIGHT && context_menu_enabled) {
menu->set_position(get_global_transform().xform(get_local_mouse_position()));
menu->set_size(Vector2(1, 1));
menu->popup();
@@ -161,13 +161,14 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
} break;
- case (KEY_Z): { // Simple One level undo
-
+ case (KEY_Z): { // undo / redo
if (editable) {
-
- undo();
+ if (k->get_shift()) {
+ redo();
+ } else {
+ undo();
+ }
}
-
} break;
case (KEY_U): { // Delete from start to cursor
@@ -175,7 +176,6 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
if (editable) {
selection_clear();
- undo_text = text;
text = text.substr(cursor_pos, text.length() - cursor_pos);
Ref<Font> font = get_font("font");
@@ -205,7 +205,6 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
if (editable) {
selection_clear();
- undo_text = text;
text = text.substr(0, cursor_pos);
_text_changed();
}
@@ -245,7 +244,6 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
break;
if (selection.enabled) {
- undo_text = text;
selection_delete();
break;
}
@@ -276,7 +274,6 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
set_cursor_position(cc);
} else {
- undo_text = text;
delete_char();
}
@@ -382,7 +379,6 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
}
if (selection.enabled) {
- undo_text = text;
selection_delete();
break;
}
@@ -417,7 +413,6 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
delete_text(cursor_pos, cc);
} else {
- undo_text = text;
set_cursor_position(cursor_pos + 1);
delete_char();
}
@@ -778,7 +773,6 @@ void LineEdit::copy_text() {
void LineEdit::cut_text() {
if (selection.enabled) {
- undo_text = text;
OS::get_singleton()->set_clipboard(text.substr(selection.begin, selection.end - selection.begin));
selection_delete();
}
@@ -798,23 +792,33 @@ void LineEdit::paste_text() {
}
void LineEdit::undo() {
-
- int old_cursor_pos = cursor_pos;
- text = undo_text;
-
- Ref<Font> font = get_font("font");
-
- cached_width = 0;
- for (int i = 0; i < text.length(); i++)
- cached_width += font->get_char_size(text[i]).width;
-
- if (old_cursor_pos > text.length()) {
- set_cursor_position(text.length());
- } else {
- set_cursor_position(old_cursor_pos);
+ if (undo_stack_pos == NULL) {
+ if (undo_stack.size() <= 1) {
+ return;
+ }
+ undo_stack_pos = undo_stack.back();
+ } else if (undo_stack_pos == undo_stack.front()) {
+ return;
}
+ undo_stack_pos = undo_stack_pos->prev();
+ TextOperation op = undo_stack_pos->get();
+ text = op.text;
+ set_cursor_position(op.cursor_pos);
+ _emit_text_change();
+}
- _text_changed();
+void LineEdit::redo() {
+ if (undo_stack_pos == NULL) {
+ return;
+ }
+ if (undo_stack_pos == undo_stack.back()) {
+ return;
+ }
+ undo_stack_pos = undo_stack_pos->next();
+ TextOperation op = undo_stack_pos->get();
+ text = op.text;
+ set_cursor_position(op.cursor_pos);
+ _emit_text_change();
}
void LineEdit::shift_selection_check_pre(bool p_shift) {
@@ -947,8 +951,6 @@ void LineEdit::delete_char() {
void LineEdit::delete_text(int p_from_column, int p_to_column) {
- undo_text = text;
-
if (text.size() > 0) {
Ref<Font> font = get_font("font");
if (font != NULL) {
@@ -1036,9 +1038,11 @@ void LineEdit::set_cursor_position(int p_pos) {
Ref<StyleBox> style = get_stylebox("normal");
Ref<Font> font = get_font("font");
- if (cursor_pos < window_pos) {
+ if (cursor_pos <= window_pos) {
/* Adjust window if cursor goes too much to the left */
- set_window_pos(cursor_pos);
+ if (window_pos > 0)
+ set_window_pos(window_pos - 1);
+
} else if (cursor_pos > window_pos) {
/* Adjust window if cursor goes too much to the right */
int window_width = get_size().width - style->get_minimum_size().width;
@@ -1086,8 +1090,6 @@ void LineEdit::append_at_cursor(String p_text) {
if ((max_length <= 0) || (text.length() + p_text.length() <= max_length)) {
- undo_text = text;
-
Ref<Font> font = get_font("font");
if (font != NULL) {
for (int i = 0; i < p_text.length(); i++)
@@ -1105,6 +1107,7 @@ void LineEdit::append_at_cursor(String p_text) {
void LineEdit::clear_internal() {
+ _clear_undo_stack();
cached_width = 0;
cursor_pos = 0;
window_pos = 0;
@@ -1275,9 +1278,22 @@ void LineEdit::menu_option(int p_option) {
undo();
}
} break;
+ case MENU_REDO: {
+ if (editable) {
+ redo();
+ }
+ }
}
}
+void LineEdit::set_context_menu_enabled(bool p_enable) {
+ context_menu_enabled = p_enable;
+}
+
+bool LineEdit::is_context_menu_enabled() {
+ return context_menu_enabled;
+}
+
PopupMenu *LineEdit::get_menu() const {
return menu;
}
@@ -1293,6 +1309,7 @@ void LineEdit::set_expand_to_text_length(bool p_enabled) {
expand_to_text_length = p_enabled;
minimum_size_changed();
+ set_window_pos(0);
}
bool LineEdit::get_expand_to_text_length() const {
@@ -1312,10 +1329,43 @@ void LineEdit::_text_changed() {
if (expand_to_text_length)
minimum_size_changed();
+ _emit_text_change();
+ _clear_redo();
+}
+
+void LineEdit::_emit_text_change() {
emit_signal("text_changed", text);
_change_notify("text");
}
+void LineEdit::_clear_redo() {
+ _create_undo_state();
+ if (undo_stack_pos == NULL) {
+ return;
+ }
+
+ undo_stack_pos = undo_stack_pos->next();
+ while (undo_stack_pos) {
+ List<TextOperation>::Element *elem = undo_stack_pos;
+ undo_stack_pos = undo_stack_pos->next();
+ undo_stack.erase(elem);
+ }
+ _create_undo_state();
+}
+
+void LineEdit::_clear_undo_stack() {
+ undo_stack.clear();
+ undo_stack_pos = NULL;
+ _create_undo_state();
+}
+
+void LineEdit::_create_undo_state() {
+ TextOperation op;
+ op.text = text;
+ op.cursor_pos = cursor_pos;
+ undo_stack.push_back(op);
+}
+
void LineEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("_toggle_draw_caret"), &LineEdit::_toggle_draw_caret);
@@ -1354,6 +1404,8 @@ void LineEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("select", "from", "to"), &LineEdit::select, DEFVAL(0), DEFVAL(-1));
ClassDB::bind_method(D_METHOD("menu_option", "option"), &LineEdit::menu_option);
ClassDB::bind_method(D_METHOD("get_menu"), &LineEdit::get_menu);
+ ClassDB::bind_method(D_METHOD("set_context_menu_enabled", "enable"), &LineEdit::set_context_menu_enabled);
+ ClassDB::bind_method(D_METHOD("is_context_menu_enabled"), &LineEdit::is_context_menu_enabled);
ADD_SIGNAL(MethodInfo("text_changed", PropertyInfo(Variant::STRING, "text")));
ADD_SIGNAL(MethodInfo("text_entered", PropertyInfo(Variant::STRING, "text")));
@@ -1369,6 +1421,7 @@ void LineEdit::_bind_methods() {
BIND_ENUM_CONSTANT(MENU_CLEAR);
BIND_ENUM_CONSTANT(MENU_SELECT_ALL);
BIND_ENUM_CONSTANT(MENU_UNDO);
+ BIND_ENUM_CONSTANT(MENU_REDO);
BIND_ENUM_CONSTANT(MENU_MAX);
ADD_PROPERTYNZ(PropertyInfo(Variant::STRING, "text"), "set_text", "get_text");
@@ -1376,7 +1429,7 @@ void LineEdit::_bind_methods() {
ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "max_length"), "set_max_length", "get_max_length");
ADD_PROPERTYNO(PropertyInfo(Variant::BOOL, "editable"), "set_editable", "is_editable");
ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "secret"), "set_secret", "is_secret");
- ADD_PROPERTYNO(PropertyInfo(Variant::BOOL, "expand_to_len"), "set_expand_to_text_length", "get_expand_to_text_length");
+ ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "expand_to_text_length"), "set_expand_to_text_length", "get_expand_to_text_length");
ADD_PROPERTY(PropertyInfo(Variant::INT, "focus_mode", PROPERTY_HINT_ENUM, "None,Click,All"), "set_focus_mode", "get_focus_mode");
ADD_GROUP("Placeholder", "placeholder_");
ADD_PROPERTYNZ(PropertyInfo(Variant::STRING, "placeholder_text"), "set_placeholder", "get_placeholder");
@@ -1384,10 +1437,13 @@ void LineEdit::_bind_methods() {
ADD_GROUP("Caret", "caret_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret_blink"), "cursor_set_blink_enabled", "cursor_get_blink_enabled");
ADD_PROPERTYNZ(PropertyInfo(Variant::REAL, "caret_blink_speed", PROPERTY_HINT_RANGE, "0.1,10,0.1"), "cursor_set_blink_speed", "cursor_get_blink_speed");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "context_menu_enabled"), "set_context_menu_enabled", "is_context_menu_enabled");
}
LineEdit::LineEdit() {
+ undo_stack_pos = NULL;
+ _create_undo_state();
align = ALIGN_LEFT;
cached_width = 0;
cursor_pos = 0;
@@ -1411,6 +1467,7 @@ LineEdit::LineEdit() {
caret_blink_timer->connect("timeout", this, "_toggle_draw_caret");
cursor_set_blink_enabled(false);
+ context_menu_enabled = true;
menu = memnew(PopupMenu);
add_child(menu);
menu->add_item(TTR("Cut"), MENU_CUT, KEY_MASK_CMD | KEY_X);
@@ -1421,6 +1478,7 @@ LineEdit::LineEdit() {
menu->add_item(TTR("Clear"), MENU_CLEAR);
menu->add_separator();
menu->add_item(TTR("Undo"), MENU_UNDO, KEY_MASK_CMD | KEY_Z);
+ menu->add_item(TTR("Redo"), MENU_REDO, KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_Z);
menu->connect("id_pressed", this, "menu_option");
expand_to_text_length = false;
}
diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h
index 661f9b60b9..c3a299c2f5 100644
--- a/scene/gui/line_edit.h
+++ b/scene/gui/line_edit.h
@@ -56,6 +56,7 @@ public:
MENU_CLEAR,
MENU_SELECT_ALL,
MENU_UNDO,
+ MENU_REDO,
MENU_MAX
};
@@ -73,6 +74,7 @@ private:
String ime_text;
Point2 ime_selection;
+ bool context_menu_enabled;
PopupMenu *menu;
int cursor_pos;
@@ -92,10 +94,22 @@ private:
bool drag_attempt;
} selection;
+ struct TextOperation {
+ int cursor_pos;
+ String text;
+ };
+ List<TextOperation> undo_stack;
+ List<TextOperation>::Element *undo_stack_pos;
+
+ void _clear_undo_stack();
+ void _clear_redo();
+ void _create_undo_state();
+
Timer *caret_blink_timer;
static void _ime_text_callback(void *p_self, String p_text, Point2 p_selection);
void _text_changed();
+ void _emit_text_change();
bool expand_to_text_length;
bool caret_blink_enabled;
@@ -137,6 +151,8 @@ public:
virtual void drop_data(const Point2 &p_point, const Variant &p_data);
void menu_option(int p_option);
+ void set_context_menu_enabled(bool p_enable);
+ bool is_context_menu_enabled();
PopupMenu *get_menu() const;
void select_all();
@@ -166,6 +182,7 @@ public:
void cut_text();
void paste_text();
void undo();
+ void redo();
void set_editable(bool p_editable);
bool is_editable() const;
diff --git a/scene/gui/patch_9_rect.cpp b/scene/gui/nine_patch_rect.cpp
index 92c34dd3f9..c02d80bba8 100644
--- a/scene/gui/patch_9_rect.cpp
+++ b/scene/gui/nine_patch_rect.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* patch_9_rect.cpp */
+/* nine_patch_rect.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -27,7 +27,7 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "patch_9_rect.h"
+#include "nine_patch_rect.h"
#include "servers/visual_server.h"
diff --git a/scene/gui/patch_9_rect.h b/scene/gui/nine_patch_rect.h
index 808b7a1f5d..809daf9db3 100644
--- a/scene/gui/patch_9_rect.h
+++ b/scene/gui/nine_patch_rect.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* patch_9_rect.h */
+/* nine_patch_rect.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -27,8 +27,8 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef PATCH_9_FRAME_H
-#define PATCH_9_FRAME_H
+#ifndef NINE_PATCH_RECT_H
+#define NINE_PATCH_RECT_H
#include "scene/gui/control.h"
/**
@@ -81,4 +81,4 @@ public:
};
VARIANT_ENUM_CAST(NinePatchRect::AxisStretchMode)
-#endif // PATCH_9_FRAME_H
+#endif // NINE_PATCH_RECT_H
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index c2ce2a633e..124c268c8a 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -354,7 +354,7 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int &
cw = font->get_char_size(c[i], c[i + 1]).x;
draw_rect(Rect2(p_ofs.x + pofs, p_ofs.y + y, cw, lh), selection_bg);
if (visible)
- font->draw_char(ci, p_ofs + Point2(align_ofs + pofs, y + lh - (fh - ascent)), c[i], c[i + 1], selection_fg);
+ font->draw_char(ci, p_ofs + Point2(align_ofs + pofs, y + lh - (fh - ascent)), c[i], c[i + 1], override_selected_font_color ? selection_fg : color);
} else {
if (visible)
@@ -526,6 +526,9 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int &
nonblank_line_count += _process_line(frame, p_ofs + offset + draw_ofs + Vector2(0, yofs), ly, table->columns[column].width, i, PROCESS_DRAW, cfont, ccolor);
} else if (p_mode == PROCESS_POINTER) {
_process_line(frame, p_ofs + offset + draw_ofs + Vector2(0, yofs), ly, table->columns[column].width, i, PROCESS_POINTER, cfont, ccolor, p_click_pos, r_click_item, r_click_char, r_outside);
+ if (r_click_item && *r_click_item) {
+ RETURN; // exit early
+ }
}
}
@@ -814,6 +817,16 @@ void RichTextLabel::_gui_input(Ref<InputEvent> p_event) {
}
}
+ Ref<InputEventPanGesture> pan_gesture = p_event;
+ if (pan_gesture.is_valid()) {
+
+ if (scroll_active)
+
+ vscroll->set_value(vscroll->get_value() + vscroll->get_page() * pan_gesture->get_delta().y * 0.5 / 8);
+
+ return;
+ }
+
Ref<InputEventKey> k = p_event;
if (k.is_valid()) {
@@ -874,11 +887,13 @@ void RichTextLabel::_gui_input(Ref<InputEvent> p_event) {
if (main->first_invalid_line < main->lines.size())
return;
+ int line = 0;
+ Item *item = NULL;
+ bool outside;
+ _find_click(main, m->get_position(), &item, &line, &outside);
+
if (selection.click) {
- int line = 0;
- Item *item = NULL;
- _find_click(main, m->get_position(), &item, &line);
if (!item)
return; // do not update
@@ -909,6 +924,22 @@ void RichTextLabel::_gui_input(Ref<InputEvent> p_event) {
selection.active = true;
update();
}
+
+ Variant meta;
+ if (item && !outside && _find_meta(item, &meta)) {
+ if (meta_hovering != item) {
+ if (meta_hovering) {
+ emit_signal("meta_hover_ended", current_meta);
+ }
+ meta_hovering = static_cast<ItemMeta *>(item);
+ current_meta = meta;
+ emit_signal("meta_hover_started", meta);
+ }
+ } else if (meta_hovering) {
+ emit_signal("meta_hover_ended", current_meta);
+ meta_hovering = NULL;
+ current_meta = false;
+ }
}
}
@@ -1195,8 +1226,9 @@ void RichTextLabel::add_newline() {
return;
ItemNewline *item = memnew(ItemNewline);
item->line = current_frame->lines.size();
- current_frame->lines.resize(current_frame->lines.size() + 1);
_add_item(item, false);
+ current_frame->lines.resize(current_frame->lines.size() + 1);
+ _invalidate_current_line(current_frame);
}
bool RichTextLabel::remove_line(const int p_line) {
@@ -1376,6 +1408,16 @@ bool RichTextLabel::is_meta_underlined() const {
return underline_meta;
}
+void RichTextLabel::set_override_selected_font_color(bool p_override_selected_font_color) {
+
+ override_selected_font_color = p_override_selected_font_color;
+}
+
+bool RichTextLabel::is_overriding_selected_font_color() const {
+
+ return override_selected_font_color;
+}
+
void RichTextLabel::set_offset(int p_pixel) {
vscroll->set_value(p_pixel);
@@ -1906,6 +1948,9 @@ void RichTextLabel::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_meta_underline", "enable"), &RichTextLabel::set_meta_underline);
ClassDB::bind_method(D_METHOD("is_meta_underlined"), &RichTextLabel::is_meta_underlined);
+ ClassDB::bind_method(D_METHOD("set_override_selected_font_color", "override"), &RichTextLabel::set_override_selected_font_color);
+ ClassDB::bind_method(D_METHOD("is_overriding_selected_font_color"), &RichTextLabel::is_overriding_selected_font_color);
+
ClassDB::bind_method(D_METHOD("set_scroll_active", "active"), &RichTextLabel::set_scroll_active);
ClassDB::bind_method(D_METHOD("is_scroll_active"), &RichTextLabel::is_scroll_active);
@@ -1948,8 +1993,11 @@ void RichTextLabel::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "visible_characters", PROPERTY_HINT_RANGE, "-1,128000,1"), "set_visible_characters", "get_visible_characters");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "percent_visible", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_percent_visible", "get_percent_visible");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "override_selected_font_color"), "set_override_selected_font_color", "is_overriding_selected_font_color");
ADD_SIGNAL(MethodInfo("meta_clicked", PropertyInfo(Variant::NIL, "meta", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT)));
+ ADD_SIGNAL(MethodInfo("meta_hover_started", PropertyInfo(Variant::NIL, "meta", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT)));
+ ADD_SIGNAL(MethodInfo("meta_hover_ended", PropertyInfo(Variant::NIL, "meta", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT)));
BIND_ENUM_CONSTANT(ALIGN_LEFT);
BIND_ENUM_CONSTANT(ALIGN_CENTER);
@@ -1970,6 +2018,7 @@ void RichTextLabel::_bind_methods() {
BIND_ENUM_CONSTANT(ITEM_ALIGN);
BIND_ENUM_CONSTANT(ITEM_INDENT);
BIND_ENUM_CONSTANT(ITEM_LIST);
+ BIND_ENUM_CONSTANT(ITEM_TABLE);
BIND_ENUM_CONSTANT(ITEM_META);
}
@@ -2003,6 +2052,7 @@ RichTextLabel::RichTextLabel() {
tab_size = 4;
default_align = ALIGN_LEFT;
underline_meta = true;
+ override_selected_font_color = false;
scroll_visible = false;
scroll_follow = false;
diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h
index 24c1e5eb59..1096e3f650 100644
--- a/scene/gui/rich_text_label.h
+++ b/scene/gui/rich_text_label.h
@@ -221,9 +221,13 @@ private:
int tab_size;
bool underline_meta;
+ bool override_selected_font_color;
Align default_align;
+ ItemMeta *meta_hovering;
+ Variant current_meta;
+
void _invalidate_current_line(ItemFrame *p_frame);
void _validate_line_caches(ItemFrame *p_frame);
@@ -313,6 +317,9 @@ public:
void set_meta_underline(bool p_underline);
bool is_meta_underlined() const;
+ void set_override_selected_font_color(bool p_override_selected_font_color);
+ bool is_overriding_selected_font_color() const;
+
void set_scroll_active(bool p_active);
bool is_scroll_active() const;
diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp
index 1ad1e3f638..a71a1c5f92 100644
--- a/scene/gui/scroll_container.cpp
+++ b/scene/gui/scroll_container.cpp
@@ -180,6 +180,17 @@ void ScrollContainer::_gui_input(const Ref<InputEvent> &p_gui_input) {
time_since_motion = 0;
}
}
+
+ Ref<InputEventPanGesture> pan_gesture = p_gui_input;
+ if (pan_gesture.is_valid()) {
+
+ if (h_scroll->is_visible_in_tree()) {
+ h_scroll->set_value(h_scroll->get_value() + h_scroll->get_page() * pan_gesture->get_delta().x / 8);
+ }
+ if (v_scroll->is_visible_in_tree()) {
+ v_scroll->set_value(v_scroll->get_value() + v_scroll->get_page() * pan_gesture->get_delta().y / 8);
+ }
+ }
}
void ScrollContainer::_update_scrollbar_position() {
@@ -347,12 +358,11 @@ void ScrollContainer::update_scrollbars() {
} else {
v_scroll->show();
+ v_scroll->set_max(min.height);
+ v_scroll->set_page(size.height - hmin.height);
scroll.y = v_scroll->get_value();
}
- v_scroll->set_max(min.height);
- v_scroll->set_page(size.height - hmin.height);
-
if (!scroll_h || min.width <= size.width - vmin.width) {
h_scroll->hide();
diff --git a/scene/gui/separator.cpp b/scene/gui/separator.cpp
index 3db234f7cc..55d837458a 100644
--- a/scene/gui/separator.cpp
+++ b/scene/gui/separator.cpp
@@ -32,7 +32,11 @@
Size2 Separator::get_minimum_size() const {
Size2 ms(3, 3);
- ms[orientation] = get_constant("separation");
+ if (orientation == VERTICAL) {
+ ms.x = get_constant("separation");
+ } else { // HORIZONTAL
+ ms.y = get_constant("separation");
+ }
return ms;
}
diff --git a/scene/gui/slider.cpp b/scene/gui/slider.cpp
index 116e0ac354..e88742a3e3 100644
--- a/scene/gui/slider.cpp
+++ b/scene/gui/slider.cpp
@@ -157,6 +157,12 @@ void Slider::_notification(int p_what) {
mouse_inside = false;
update();
} break;
+ case NOTIFICATION_VISIBILITY_CHANGED: // fallthrough
+ case NOTIFICATION_EXIT_TREE: {
+
+ mouse_inside = false;
+ grab.active = false;
+ } break;
case NOTIFICATION_DRAW: {
RID ci = get_canvas_item();
Size2i size = get_size();
diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp
index 6e50614e8f..581034ddee 100644
--- a/scene/gui/tab_container.cpp
+++ b/scene/gui/tab_container.cpp
@@ -90,19 +90,28 @@ void TabContainer::_gui_input(const Ref<InputEvent> &p_event) {
return;
}
+ // Do not activate tabs when tabs is empty
+ if (get_tab_count() == 0)
+ return;
+
Vector<Control *> tabs = _get_tabs();
// Handle navigation buttons.
if (buttons_visible_cache) {
+ int popup_ofs = 0;
+ if (popup) {
+ popup_ofs = menu->get_width();
+ }
+
Ref<Texture> increment = get_icon("increment");
Ref<Texture> decrement = get_icon("decrement");
- if (pos.x > size.width - increment->get_width()) {
+ if (pos.x > size.width - increment->get_width() - popup_ofs) {
if (last_tab_cache < tabs.size() - 1) {
first_tab_cache += 1;
update();
}
return;
- } else if (pos.x > size.width - increment->get_width() - decrement->get_width()) {
+ } else if (pos.x > size.width - increment->get_width() - decrement->get_width() - popup_ofs) {
if (first_tab_cache > 0) {
first_tab_cache -= 1;
update();
@@ -293,6 +302,8 @@ void TabContainer::_notification(int p_what) {
}
int TabContainer::_get_tab_width(int p_index) const {
+
+ ERR_FAIL_INDEX_V(p_index, get_tab_count(), 0);
Control *control = Object::cast_to<Control>(_get_tabs()[p_index]);
if (!control || control->is_set_as_toplevel())
return 0;
@@ -664,6 +675,7 @@ void TabContainer::_bind_methods() {
TabContainer::TabContainer() {
first_tab_cache = 0;
+ last_tab_cache = 0;
buttons_visible_cache = false;
tabs_ofs_cache = 0;
current = 0;
diff --git a/scene/gui/tabs.cpp b/scene/gui/tabs.cpp
index 085f6de6b8..1fb0f84223 100644
--- a/scene/gui/tabs.cpp
+++ b/scene/gui/tabs.cpp
@@ -142,91 +142,107 @@ void Tabs::_gui_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> mb = p_event;
- if (rb_pressing && mb.is_valid() &&
- !mb->is_pressed() &&
- mb->get_button_index() == BUTTON_LEFT) {
+ if (mb.is_valid()) {
- if (rb_hover != -1) {
- //pressed
- emit_signal("right_button_pressed", rb_hover);
+ if (mb->is_pressed() && mb->get_button_index() == BUTTON_WHEEL_UP && !mb->get_command()) {
+
+ if (scrolling_enabled && buttons_visible) {
+ if (offset > 0) {
+ offset--;
+ update();
+ }
+ }
}
- rb_pressing = false;
- update();
- }
+ if (mb->is_pressed() && mb->get_button_index() == BUTTON_WHEEL_DOWN && !mb->get_command()) {
+ if (scrolling_enabled && buttons_visible) {
+ if (missing_right) {
+ offset++;
+ update();
+ }
+ }
+ }
- if (cb_pressing && mb.is_valid() &&
- !mb->is_pressed() &&
- mb->get_button_index() == BUTTON_LEFT) {
+ if (rb_pressing && !mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
- if (cb_hover != -1) {
- //pressed
- emit_signal("tab_close", cb_hover);
+ if (rb_hover != -1) {
+ //pressed
+ emit_signal("right_button_pressed", rb_hover);
+ }
+
+ rb_pressing = false;
+ update();
}
- cb_pressing = false;
- update();
- }
+ if (cb_pressing && !mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
- if (mb.is_valid() &&
- mb->is_pressed() &&
- mb->get_button_index() == BUTTON_LEFT) {
+ if (cb_hover != -1) {
+ //pressed
+ emit_signal("tab_close", cb_hover);
+ }
- // clicks
- Point2 pos(mb->get_position().x, mb->get_position().y);
+ cb_pressing = false;
+ update();
+ }
- if (buttons_visible) {
+ if (mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
- Ref<Texture> incr = get_icon("increment");
- Ref<Texture> decr = get_icon("decrement");
+ // clicks
+ Point2 pos(mb->get_position().x, mb->get_position().y);
- int limit = get_size().width - incr->get_width() - decr->get_width();
+ if (buttons_visible) {
- if (pos.x > limit + decr->get_width()) {
- if (missing_right) {
- offset++;
- update();
- }
- return;
- } else if (pos.x > limit) {
- if (offset > 0) {
- offset--;
- update();
+ Ref<Texture> incr = get_icon("increment");
+ Ref<Texture> decr = get_icon("decrement");
+
+ int limit = get_size().width - incr->get_width() - decr->get_width();
+
+ if (pos.x > limit + decr->get_width()) {
+ if (missing_right) {
+ offset++;
+ update();
+ }
+ return;
+ } else if (pos.x > limit) {
+ if (offset > 0) {
+ offset--;
+ update();
+ }
+ return;
}
- return;
}
- }
- int found = -1;
- for (int i = 0; i < tabs.size(); i++) {
+ int found = -1;
+ for (int i = 0; i < tabs.size(); i++) {
- if (i < offset)
- continue;
+ if (i < offset)
+ continue;
- if (tabs[i].rb_rect.has_point(pos)) {
- rb_pressing = true;
- update();
- return;
- }
+ if (tabs[i].rb_rect.has_point(pos)) {
+ rb_pressing = true;
+ update();
+ return;
+ }
- if (tabs[i].cb_rect.has_point(pos)) {
- cb_pressing = true;
- update();
- return;
- }
+ if (tabs[i].cb_rect.has_point(pos)) {
+ cb_pressing = true;
+ update();
+ return;
+ }
- if (pos.x >= tabs[i].ofs_cache && pos.x < tabs[i].ofs_cache + tabs[i].size_cache) {
- if (!tabs[i].disabled) {
- found = i;
+ if (pos.x >= tabs[i].ofs_cache && pos.x < tabs[i].ofs_cache + tabs[i].size_cache) {
+ if (!tabs[i].disabled) {
+ found = i;
+ }
+ break;
}
- break;
}
- }
- if (found != -1) {
+ if (found != -1) {
- set_current_tab(found);
- emit_signal("tab_clicked", found);
+ set_current_tab(found);
+ emit_signal("tab_clicked", found);
+ }
}
}
}
@@ -440,6 +456,14 @@ int Tabs::get_hovered_tab() const {
return hover;
}
+int Tabs::get_tab_offset() const {
+ return offset;
+}
+
+bool Tabs::get_offset_buttons_visible() const {
+ return buttons_visible;
+}
+
void Tabs::set_tab_title(int p_tab, const String &p_title) {
ERR_FAIL_INDEX(p_tab, tabs.size());
@@ -484,6 +508,7 @@ void Tabs::set_tab_right_button(int p_tab, const Ref<Texture> &p_right_button) {
ERR_FAIL_INDEX(p_tab, tabs.size());
tabs[p_tab].right_button = p_right_button;
+ _update_cache();
update();
minimum_size_changed();
}
@@ -783,6 +808,14 @@ void Tabs::set_min_width(int p_width) {
min_width = p_width;
}
+void Tabs::set_scrolling_enabled(bool p_enabled) {
+ scrolling_enabled = p_enabled;
+}
+
+bool Tabs::get_scrolling_enabled() const {
+ return scrolling_enabled;
+}
+
void Tabs::_bind_methods() {
ClassDB::bind_method(D_METHOD("_gui_input"), &Tabs::_gui_input);
@@ -799,11 +832,15 @@ void Tabs::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_tab", "title", "icon"), &Tabs::add_tab, DEFVAL(""), DEFVAL(Ref<Texture>()));
ClassDB::bind_method(D_METHOD("set_tab_align", "align"), &Tabs::set_tab_align);
ClassDB::bind_method(D_METHOD("get_tab_align"), &Tabs::get_tab_align);
+ ClassDB::bind_method(D_METHOD("get_tab_offset"), &Tabs::get_tab_offset);
+ ClassDB::bind_method(D_METHOD("get_offset_buttons_visible"), &Tabs::get_offset_buttons_visible);
ClassDB::bind_method(D_METHOD("ensure_tab_visible", "idx"), &Tabs::ensure_tab_visible);
ClassDB::bind_method(D_METHOD("get_tab_rect", "tab_idx"), &Tabs::get_tab_rect);
ClassDB::bind_method(D_METHOD("move_tab", "from", "to"), &Tabs::move_tab);
ClassDB::bind_method(D_METHOD("set_tab_close_display_policy", "policy"), &Tabs::set_tab_close_display_policy);
ClassDB::bind_method(D_METHOD("get_tab_close_display_policy"), &Tabs::get_tab_close_display_policy);
+ ClassDB::bind_method(D_METHOD("set_scrolling_enabled", "enabled"), &Tabs::set_scrolling_enabled);
+ ClassDB::bind_method(D_METHOD("get_scrolling_enabled"), &Tabs::get_scrolling_enabled);
ADD_SIGNAL(MethodInfo("tab_changed", PropertyInfo(Variant::INT, "tab")));
ADD_SIGNAL(MethodInfo("right_button_pressed", PropertyInfo(Variant::INT, "tab")));
@@ -814,15 +851,16 @@ void Tabs::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "current_tab", PROPERTY_HINT_RANGE, "-1,4096,1", PROPERTY_USAGE_EDITOR), "set_current_tab", "get_current_tab");
ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "tab_close_display_policy", PROPERTY_HINT_ENUM, "Show Never,Show Active Only,Show Always"), "set_tab_close_display_policy", "get_tab_close_display_policy");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "scrolling_enabled"), "set_scrolling_enabled", "get_scrolling_enabled");
BIND_ENUM_CONSTANT(ALIGN_LEFT);
BIND_ENUM_CONSTANT(ALIGN_CENTER);
BIND_ENUM_CONSTANT(ALIGN_RIGHT);
BIND_ENUM_CONSTANT(ALIGN_MAX);
+ BIND_ENUM_CONSTANT(CLOSE_BUTTON_SHOW_NEVER);
BIND_ENUM_CONSTANT(CLOSE_BUTTON_SHOW_ACTIVE_ONLY);
BIND_ENUM_CONSTANT(CLOSE_BUTTON_SHOW_ALWAYS);
- BIND_ENUM_CONSTANT(CLOSE_BUTTON_SHOW_NEVER);
BIND_ENUM_CONSTANT(CLOSE_BUTTON_MAX);
}
@@ -841,4 +879,5 @@ Tabs::Tabs() {
max_drawn_tab = 0;
min_width = 0;
+ scrolling_enabled = true;
}
diff --git a/scene/gui/tabs.h b/scene/gui/tabs.h
index 73fa40bbb8..4eb6be3435 100644
--- a/scene/gui/tabs.h
+++ b/scene/gui/tabs.h
@@ -88,6 +88,7 @@ private:
int hover; // hovered tab
int min_width;
+ bool scrolling_enabled;
int get_tab_width(int p_idx) const;
void _ensure_no_over_offset();
@@ -131,10 +132,16 @@ public:
int get_current_tab() const;
int get_hovered_tab() const;
+ int get_tab_offset() const;
+ bool get_offset_buttons_visible() const;
+
void remove_tab(int p_idx);
void clear_tabs();
+ void set_scrolling_enabled(bool p_enabled);
+ bool get_scrolling_enabled() const;
+
void ensure_tab_visible(int p_idx);
void set_min_width(int p_width);
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index d14d3ef947..69dc7b21fe 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -274,6 +274,7 @@ void TextEdit::Text::insert(int p_at, const String &p_text) {
Line line;
line.marked = false;
line.breakpoint = false;
+ line.hidden = false;
line.width_cache = -1;
line.data = p_text;
text.insert(p_at, line);
@@ -297,9 +298,11 @@ void TextEdit::_update_scrollbars() {
int hscroll_rows = ((hmin.height - 1) / get_row_height()) + 1;
int visible_rows = get_visible_rows();
- int total_rows = text.size();
+ int num_rows = MAX(visible_rows, num_lines_from(CLAMP(cursor.line_ofs, 0, text.size() - 1), MIN(visible_rows, text.size() - 1 - cursor.line_ofs)));
+
+ int total_rows = (is_hiding_enabled() ? get_total_unhidden_rows() : text.size());
if (scroll_past_end_of_file_enabled) {
- total_rows += get_visible_rows() - 1;
+ total_rows += visible_rows - 1;
}
int vscroll_pixels = v_scroll->get_combined_minimum_size().width;
@@ -313,6 +316,10 @@ void TextEdit::_update_scrollbars() {
total_width += cache.breakpoint_gutter_width;
}
+ if (draw_fold_gutter) {
+ total_width += cache.fold_gutter_width;
+ }
+
bool use_hscroll = true;
bool use_vscroll = true;
@@ -347,12 +354,11 @@ void TextEdit::_update_scrollbars() {
v_scroll->set_step(1);
}
- if (fabs(v_scroll->get_value() - (double)cursor.line_ofs) >= 1) {
- v_scroll->set_value(cursor.line_ofs);
- }
-
+ update_line_scroll_pos();
} else {
cursor.line_ofs = 0;
+ line_scroll_pos = 0;
+ v_scroll->set_value(0);
v_scroll->hide();
}
@@ -376,24 +382,116 @@ void TextEdit::_update_scrollbars() {
void TextEdit::_click_selection_held() {
if (Input::get_singleton()->is_mouse_button_pressed(BUTTON_LEFT) && selection.selecting_mode != Selection::MODE_NONE) {
+ switch (selection.selecting_mode) {
+ case Selection::MODE_POINTER: {
+ _update_selection_mode_pointer();
+ } break;
+ case Selection::MODE_WORD: {
+ _update_selection_mode_word();
+ } break;
+ case Selection::MODE_LINE: {
+ _update_selection_mode_line();
+ } break;
+ default: {
+ break;
+ }
+ }
+ } else {
+ click_select_held->stop();
+ }
+}
- Point2 mp = Input::get_singleton()->get_mouse_position() - get_global_position();
+void TextEdit::_update_selection_mode_pointer() {
+ Point2 mp = Input::get_singleton()->get_mouse_position() - get_global_position();
- int row, col;
- _get_mouse_pos(Point2i(mp.x, mp.y), row, col);
+ int row, col;
+ _get_mouse_pos(Point2i(mp.x, mp.y), row, col);
- select(selection.selecting_line, selection.selecting_column, row, col);
+ select(selection.selecting_line, selection.selecting_column, row, col);
- cursor_set_line(row);
- cursor_set_column(col);
- update();
+ cursor_set_line(row);
+ cursor_set_column(col);
+ update();
+
+ click_select_held->start();
+}
+
+void TextEdit::_update_selection_mode_word() {
+ Point2 mp = Input::get_singleton()->get_mouse_position() - get_global_position();
- click_select_held->start();
+ int row, col;
+ _get_mouse_pos(Point2i(mp.x, mp.y), row, col);
+
+ String line = text[row];
+ int beg = CLAMP(col, 0, line.length());
+ // if its the first selection and on whitespace make sure we grab the word instead..
+ if (!selection.active) {
+ while (beg > 0 && line[beg] <= 32) {
+ beg--;
+ }
+ }
+ int end = beg;
+ bool symbol = beg < line.length() && _is_symbol(line[beg]);
+
+ // get the word end and begin points
+ while (beg > 0 && line[beg - 1] > 32 && (symbol == _is_symbol(line[beg - 1]))) {
+ beg--;
+ }
+ while (end < line.length() && line[end + 1] > 32 && (symbol == _is_symbol(line[end + 1]))) {
+ end++;
+ }
+ if (end < line.length()) {
+ end += 1;
+ }
+ // inital selection
+ if (!selection.active) {
+ select(row, beg, row, end);
+ selection.selecting_column = beg;
+ selection.selected_word_beg = beg;
+ selection.selected_word_end = end;
+ selection.selected_word_origin = beg;
+ cursor_set_column(selection.to_column);
} else {
+ if ((col <= selection.selected_word_origin && row == selection.selecting_line) || row < selection.selecting_line) {
+ selection.selecting_column = selection.selected_word_end;
+ select(row, beg, selection.selecting_line, selection.selected_word_end);
+ cursor_set_column(selection.from_column);
+ } else {
+ selection.selecting_column = selection.selected_word_beg;
+ select(selection.selecting_line, selection.selected_word_beg, row, end);
+ cursor_set_column(selection.to_column);
+ }
+ }
+ cursor_set_line(row);
- click_select_held->stop();
+ update();
+ click_select_held->start();
+}
+
+void TextEdit::_update_selection_mode_line() {
+ Point2 mp = Input::get_singleton()->get_mouse_position() - get_global_position();
+
+ int row, col;
+ _get_mouse_pos(Point2i(mp.x, mp.y), row, col);
+
+ col = 0;
+ if (row < selection.selecting_line) {
+ // cursor is above us
+ cursor_set_line(row - 1);
+ selection.selecting_column = text[selection.selecting_line].length();
+ } else {
+ // cursor is below us
+ cursor_set_line(row + 1);
+ selection.selecting_column = 0;
+ col = text[row].length();
}
+ cursor_set_column(0);
+
+ select(selection.selecting_line, selection.selecting_column, row, col);
+ update();
+
+ click_select_held->start();
}
void TextEdit::_notification(int p_what) {
@@ -459,6 +557,13 @@ void TextEdit::_notification(int p_what) {
cache.breakpoint_gutter_width = 0;
}
+ if (draw_fold_gutter) {
+ fold_gutter_width = (get_row_height() * 55) / 100;
+ cache.fold_gutter_width = fold_gutter_width;
+ } else {
+ cache.fold_gutter_width = 0;
+ }
+
int line_number_char_count = 0;
{
@@ -481,7 +586,7 @@ void TextEdit::_notification(int p_what) {
RID ci = get_canvas_item();
VisualServer::get_singleton()->canvas_item_set_clip(get_canvas_item(), true);
- int xmargin_beg = cache.style_normal->get_margin(MARGIN_LEFT) + cache.line_number_w + cache.breakpoint_gutter_width;
+ int xmargin_beg = cache.style_normal->get_margin(MARGIN_LEFT) + cache.line_number_w + cache.breakpoint_gutter_width + cache.fold_gutter_width;
int xmargin_end = cache.size.width - cache.style_normal->get_margin(MARGIN_RIGHT);
//let's do it easy for now:
cache.style_normal->draw(ci, Rect2(Point2(), cache.size));
@@ -688,10 +793,22 @@ void TextEdit::_notification(int p_what) {
String highlighted_text = get_selection_text();
String line_num_padding = line_numbers_zero_padded ? "0" : " ";
+ update_line_scroll_pos();
+ int line = cursor.line_ofs - 1;
for (int i = 0; i < visible_rows; i++) {
- int line = i + cursor.line_ofs;
+ line++;
+
+ if (line < 0 || line >= (int)text.size())
+ continue;
+
+ while (is_line_hidden(line)) {
+ line++;
+ if (line < 0 || line >= (int)text.size()) {
+ break;
+ }
+ }
if (line < 0 || line >= (int)text.size())
continue;
@@ -702,7 +819,7 @@ void TextEdit::_notification(int p_what) {
int char_ofs = 0;
int ofs_y = (i * get_row_height() + cache.line_spacing / 2);
if (smooth_scroll_enabled) {
- ofs_y -= (v_scroll->get_value() - cursor.line_ofs) * get_row_height();
+ ofs_y -= (v_scroll->get_value() - get_line_scroll_pos()) * get_row_height();
}
bool prev_is_char = false;
@@ -732,8 +849,17 @@ void TextEdit::_notification(int p_what) {
VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg, ofs_y, xmargin_end - xmargin_beg, get_row_height()), cache.mark_color);
}
- if (line == cursor.line) {
- VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(0, ofs_y, xmargin_end, get_row_height()), cache.current_line_color);
+ if (str.length() == 0) {
+ // draw line background if empty as we won't loop at at all
+ if (line == cursor.line && highlight_current_line) {
+ VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(0, ofs_y, xmargin_end, get_row_height()), cache.current_line_color);
+ }
+
+ // give visual indication of empty selected line
+ if (selection.active && line >= selection.from_line && line <= selection.to_line) {
+ int char_w = cache.font->get_char_size(' ').width;
+ VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg, ofs_y, char_w, get_row_height()), cache.selection_color);
+ }
}
if (text.is_breakpoint(line) && !draw_breakpoint_gutter) {
@@ -756,6 +882,21 @@ void TextEdit::_notification(int p_what) {
}
}
+ // draw fold markers
+ if (draw_fold_gutter) {
+ int horizontal_gap = (cache.fold_gutter_width * 30) / 100;
+ int gutter_left = cache.style_normal->get_margin(MARGIN_LEFT) + cache.breakpoint_gutter_width + cache.line_number_w;
+ if (is_folded(line)) {
+ int xofs = horizontal_gap - (cache.can_fold_icon->get_width()) / 2;
+ int yofs = (get_row_height() - cache.folded_icon->get_height()) / 2;
+ cache.folded_icon->draw(ci, Point2(gutter_left + xofs, ofs_y + yofs), Color(0.8f, 0.8f, 0.8f, 0.8f));
+ } else if (can_fold(line)) {
+ int xofs = -cache.can_fold_icon->get_width() / 2 - horizontal_gap + 3;
+ int yofs = (get_row_height() - cache.can_fold_icon->get_height()) / 2;
+ cache.can_fold_icon->draw(ci, Point2(gutter_left + xofs, ofs_y + yofs), Color(0.8f, 0.8f, 0.8f, 0.8f));
+ }
+ }
+
if (cache.line_number_w) {
String fc = String::num(line + 1);
while (fc.length() < line_number_char_count) {
@@ -764,6 +905,7 @@ void TextEdit::_notification(int p_what) {
cache.font->draw(ci, Point2(cache.style_normal->get_margin(MARGIN_LEFT) + cache.breakpoint_gutter_width, ofs_y + cache.font->get_ascent()), fc, cache.line_number_color);
}
+ //loop through charcters in one line
for (int j = 0; j < str.length(); j++) {
//look for keyword
@@ -792,17 +934,18 @@ void TextEdit::_notification(int p_what) {
is_hex_notation = false;
}
- // check for dot or 'x' for hex notation in floating point number
- if ((str[j] == '.' || str[j] == 'x') && !in_word && prev_is_number && !is_number) {
+ // check for dot or underscore or 'x' for hex notation in floating point number
+ if ((str[j] == '.' || str[j] == 'x' || str[j] == '_') && !in_word && prev_is_number && !is_number) {
is_number = true;
is_symbol = false;
+ is_char = false;
if (str[j] == 'x' && str[j - 1] == '0') {
is_hex_notation = true;
}
}
- if (!in_word && _is_char(str[j])) {
+ if (!in_word && _is_char(str[j]) && !is_number) {
in_word = true;
}
@@ -952,10 +1095,25 @@ void TextEdit::_notification(int p_what) {
}
}
+ //current line highlighting
bool in_selection = (selection.active && line >= selection.from_line && line <= selection.to_line && (line > selection.from_line || j >= selection.from_column) && (line < selection.to_line || j < selection.to_column));
+ if (line == cursor.line && highlight_current_line) {
+ // if its the first char draw behind line numbers
+ if (j == 0) {
+ VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(0, ofs_y, (char_ofs + char_margin), get_row_height()), cache.current_line_color);
+ }
+ // if its the last char draw to end of the line
+ if (j == str.length() - 1) {
+ VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(char_ofs + char_margin + char_w, ofs_y, xmargin_end - (char_ofs + char_margin + char_w), get_row_height()), cache.current_line_color);
+ }
+ // actual text
+ if (!in_selection) {
+ VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2i(char_ofs + char_margin, ofs_y), Size2i(char_w, get_row_height())), cache.current_line_color);
+ }
+ }
+
if (in_selection) {
- //inside selection!
VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2i(char_ofs + char_margin, ofs_y), Size2i(char_w, get_row_height())), cache.selection_color);
}
@@ -998,7 +1156,7 @@ void TextEdit::_notification(int p_what) {
if (brace_open_mismatch)
color = cache.brace_mismatch_color;
- cache.font->draw_char(ci, Point2i(char_ofs + char_margin, ofs_y + ascent), '_', str[j + 1], in_selection ? cache.font_selected_color : color);
+ cache.font->draw_char(ci, Point2i(char_ofs + char_margin, ofs_y + ascent), '_', str[j + 1], in_selection && override_selected_font_color ? cache.font_selected_color : color);
}
if (
@@ -1007,7 +1165,7 @@ void TextEdit::_notification(int p_what) {
if (brace_close_mismatch)
color = cache.brace_mismatch_color;
- cache.font->draw_char(ci, Point2i(char_ofs + char_margin, ofs_y + ascent), '_', str[j + 1], in_selection ? cache.font_selected_color : color);
+ cache.font->draw_char(ci, Point2i(char_ofs + char_margin, ofs_y + ascent), '_', str[j + 1], in_selection && override_selected_font_color ? cache.font_selected_color : color);
}
}
@@ -1066,18 +1224,24 @@ void TextEdit::_notification(int p_what) {
}
if (str[j] >= 32) {
- int w = cache.font->draw_char(ci, Point2i(char_ofs + char_margin, ofs_y + ascent), str[j], str[j + 1], in_selection ? cache.font_selected_color : color);
+ int w = cache.font->draw_char(ci, Point2i(char_ofs + char_margin, ofs_y + ascent), str[j], str[j + 1], in_selection && override_selected_font_color ? cache.font_selected_color : color);
if (underlined) {
- draw_rect(Rect2(char_ofs + char_margin, ofs_y + ascent + 2, w, 1), in_selection ? cache.font_selected_color : color);
+ draw_rect(Rect2(char_ofs + char_margin, ofs_y + ascent + 2, w, 1), in_selection && override_selected_font_color ? cache.font_selected_color : color);
}
}
else if (draw_tabs && str[j] == '\t') {
int yofs = (get_row_height() - cache.tab_icon->get_height()) / 2;
- cache.tab_icon->draw(ci, Point2(char_ofs + char_margin, ofs_y + yofs), in_selection ? cache.font_selected_color : color);
+ cache.tab_icon->draw(ci, Point2(char_ofs + char_margin, ofs_y + yofs), in_selection && override_selected_font_color ? cache.font_selected_color : color);
}
char_ofs += char_w;
+
+ if (j == str.length() - 1 && is_folded(line)) {
+ int yofs = (get_row_height() - cache.folded_eol_icon->get_height()) / 2;
+ int xofs = cache.folded_eol_icon->get_width() / 2;
+ cache.folded_eol_icon->draw(ci, Point2(char_ofs + char_margin + xofs, ofs_y + yofs), Color(1, 1, 1, 1));
+ }
}
if (cursor.column == str.length() && cursor.line == line && (char_ofs + char_margin) >= xmargin_beg) {
@@ -1420,6 +1584,12 @@ void TextEdit::backspace_at_cursor() {
int prev_line = cursor.column ? cursor.line : cursor.line - 1;
int prev_column = cursor.column ? (cursor.column - 1) : (text[cursor.line - 1].length());
+
+ if (is_line_hidden(cursor.line))
+ set_line_as_hidden(prev_line, true);
+ if (is_line_set_as_breakpoint(cursor.line))
+ set_line_as_breakpoint(prev_line, true);
+
if (auto_brace_completion_enabled &&
cursor.column > 0 &&
_is_pair_left_symbol(text[cursor.line][cursor.column - 1])) {
@@ -1459,7 +1629,7 @@ void TextEdit::backspace_at_cursor() {
}
}
- cursor_set_line(prev_line);
+ cursor_set_line(prev_line, true, true);
cursor_set_column(prev_column);
}
@@ -1533,10 +1703,18 @@ void TextEdit::_get_mouse_pos(const Point2i &p_mouse, int &r_row, int &r_col) co
float rows = p_mouse.y;
rows -= cache.style_normal->get_margin(MARGIN_TOP);
rows /= get_row_height();
- int row = cursor.line_ofs + (rows + (v_scroll->get_value() - cursor.line_ofs));
+ int lsp = get_line_scroll_pos(true);
+ int row = cursor.line_ofs + (rows + (v_scroll->get_value() - lsp));
+
+ if (is_hiding_enabled()) {
+ // row will be offset by the hidden rows
+ int f_ofs = num_lines_from(CLAMP(cursor.line_ofs, 0, text.size() - 1), MIN(rows + 1, text.size() - cursor.line_ofs)) - 1;
+ row = cursor.line_ofs + (f_ofs + (v_scroll->get_value() - lsp));
+ row = CLAMP(row, 0, text.size() - num_lines_from(text.size() - 1, -1));
+ }
if (row < 0)
- row = 0;
+ row = 0; //todo
int col = 0;
@@ -1546,7 +1724,7 @@ void TextEdit::_get_mouse_pos(const Point2i &p_mouse, int &r_row, int &r_col) co
col = text[row].size();
} else {
- col = p_mouse.x - (cache.style_normal->get_margin(MARGIN_LEFT) + cache.line_number_w + cache.breakpoint_gutter_width);
+ col = p_mouse.x - (cache.style_normal->get_margin(MARGIN_LEFT) + cache.line_number_w + cache.breakpoint_gutter_width + cache.fold_gutter_width);
col += cursor.x_ofs;
col = get_char_pos_for(col, get_line(row));
}
@@ -1599,43 +1777,10 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
if (mb->is_pressed()) {
if (mb->get_button_index() == BUTTON_WHEEL_UP && !mb->get_command()) {
- if (scrolling) {
- target_v_scroll = (target_v_scroll - (3 * mb->get_factor()));
- } else {
- target_v_scroll = (v_scroll->get_value() - (3 * mb->get_factor()));
- }
-
- if (smooth_scroll_enabled) {
- if (target_v_scroll <= 0) {
- target_v_scroll = 0;
- }
- scrolling = true;
- set_physics_process(true);
- } else {
- v_scroll->set_value(target_v_scroll);
- }
+ _scroll_up(3 * mb->get_factor());
}
if (mb->get_button_index() == BUTTON_WHEEL_DOWN && !mb->get_command()) {
- if (scrolling) {
- target_v_scroll = (target_v_scroll + (3 * mb->get_factor()));
- } else {
- target_v_scroll = (v_scroll->get_value() + (3 * mb->get_factor()));
- }
-
- if (smooth_scroll_enabled) {
- int max_v_scroll = get_line_count() - 1;
- if (!scroll_past_end_of_file_enabled) {
- max_v_scroll -= get_visible_rows() - 1;
- }
-
- if (target_v_scroll > max_v_scroll) {
- target_v_scroll = max_v_scroll;
- }
- scrolling = true;
- set_physics_process(true);
- } else {
- v_scroll->set_value(target_v_scroll);
- }
+ _scroll_down(3 * mb->get_factor());
}
if (mb->get_button_index() == BUTTON_WHEEL_LEFT) {
h_scroll->set_value(h_scroll->get_value() - (100 * mb->get_factor()));
@@ -1648,6 +1793,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
_reset_caret_blink_timer();
int row, col;
+ update_line_scroll_pos();
_get_mouse_pos(Point2i(mb->get_position().x, mb->get_position().y), row, col);
if (mb->get_command() && highlighted_word != String()) {
@@ -1666,10 +1812,35 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
}
}
+ // toggle fold on gutter click if can
+ if (draw_fold_gutter) {
+
+ int left_margin = cache.style_normal->get_margin(MARGIN_LEFT);
+ int gutter_left = left_margin + cache.breakpoint_gutter_width + cache.line_number_w;
+ if (mb->get_position().x > gutter_left - 6 && mb->get_position().x <= gutter_left + cache.fold_gutter_width - 3) {
+ if (is_folded(row)) {
+ unfold_line(row);
+ } else if (can_fold(row)) {
+ fold_line(row);
+ }
+ return;
+ }
+ }
+
+ // unfold on folded icon click
+ if (is_folded(row)) {
+ int line_width = text.get_line_width(row);
+ line_width += cache.style_normal->get_margin(MARGIN_LEFT) + cache.line_number_w + cache.breakpoint_gutter_width + cache.fold_gutter_width - cursor.x_ofs;
+ if (mb->get_position().x > line_width - 3 && mb->get_position().x <= line_width + cache.folded_eol_icon->get_width() + 3) {
+ unfold_line(row);
+ return;
+ }
+ }
+
int prev_col = cursor.column;
int prev_line = cursor.line;
- cursor_set_line(row);
+ cursor_set_line(row, true, false);
cursor_set_column(col);
if (mb->get_shift() && (cursor.column != prev_col || cursor.line != prev_line)) {
@@ -1734,36 +1905,15 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
if (!mb->is_doubleclick() && (OS::get_singleton()->get_ticks_msec() - last_dblclk) < 600 && cursor.line == prev_line) {
//tripleclick select line
- select(cursor.line, 0, cursor.line, text[cursor.line].length());
- selection.selecting_column = 0;
+ selection.selecting_mode = Selection::MODE_LINE;
+ _update_selection_mode_line();
last_dblclk = 0;
} else if (mb->is_doubleclick() && text[cursor.line].length()) {
//doubleclick select world
- String s = text[cursor.line];
- int beg = CLAMP(cursor.column, 0, s.length());
- int end = beg;
-
- if (s[beg] > 32 || beg == s.length()) {
-
- bool symbol = beg < s.length() && _is_symbol(s[beg]); //not sure if right but most editors behave like this
-
- while (beg > 0 && s[beg - 1] > 32 && (symbol == _is_symbol(s[beg - 1]))) {
- beg--;
- }
- while (end < s.length() && s[end + 1] > 32 && (symbol == _is_symbol(s[end + 1]))) {
- end++;
- }
-
- if (end < s.length())
- end += 1;
-
- select(cursor.line, beg, cursor.line, end);
-
- selection.selecting_column = beg;
- }
-
+ selection.selecting_mode = Selection::MODE_WORD;
+ _update_selection_mode_word();
last_dblclk = OS::get_singleton()->get_ticks_msec();
}
@@ -1787,6 +1937,19 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
}
}
+ const Ref<InputEventPanGesture> pan_gesture = p_gui_input;
+ if (pan_gesture.is_valid()) {
+
+ const real_t delta = pan_gesture->get_delta().y;
+ if (delta < 0) {
+ _scroll_up(-delta);
+ } else {
+ _scroll_down(delta);
+ }
+ h_scroll->set_value(h_scroll->get_value() + pan_gesture->get_delta().x * 100);
+ return;
+ }
+
Ref<InputEventMouseMotion> mm = p_gui_input;
if (mm.is_valid()) {
@@ -1808,21 +1971,21 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
}
if (mm->get_button_mask() & BUTTON_MASK_LEFT && get_viewport()->gui_get_drag_data() == Variant()) { //ignore if dragging
+ _reset_caret_blink_timer();
- if (selection.selecting_mode != Selection::MODE_NONE) {
-
- _reset_caret_blink_timer();
-
- int row, col;
- _get_mouse_pos(mm->get_position(), row, col);
-
- select(selection.selecting_line, selection.selecting_column, row, col);
-
- cursor_set_line(row);
- cursor_set_column(col);
- update();
-
- click_select_held->start();
+ switch (selection.selecting_mode) {
+ case Selection::MODE_POINTER: {
+ _update_selection_mode_pointer();
+ } break;
+ case Selection::MODE_WORD: {
+ _update_selection_mode_word();
+ } break;
+ case Selection::MODE_LINE: {
+ _update_selection_mode_line();
+ } break;
+ default: {
+ break;
+ }
}
}
}
@@ -1929,17 +2092,6 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
return;
}
- if (k->get_scancode() == KEY_DOWN) {
-
- if (completion_index < completion_options.size() - 1) {
- completion_index++;
- completion_current = completion_options[completion_index];
- update();
- }
- accept_event();
- return;
- }
-
if (k->get_scancode() == KEY_KP_ENTER || k->get_scancode() == KEY_ENTER || k->get_scancode() == KEY_TAB) {
_confirm_completion();
@@ -2093,7 +2245,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
selection.active = false;
update();
_remove_text(selection.from_line, selection.from_column, selection.to_line, selection.to_column);
- cursor_set_line(selection.from_line);
+ cursor_set_line(selection.from_line, true, false);
cursor_set_column(selection.from_column);
update();
}
@@ -2143,6 +2295,9 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
}
}
+ if (is_folded(cursor.line))
+ unfold_line(cursor.line);
+
bool brace_indent = false;
// no need to indent if we are going upwards.
@@ -2163,7 +2318,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
}
}
}
-
+ begin_complex_operation();
bool first_line = false;
if (k->get_command()) {
if (k->get_shift()) {
@@ -2179,8 +2334,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
}
}
- _insert_text_at_cursor(ins);
- _push_current_op();
+ insert_text_at_cursor(ins);
if (first_line) {
cursor_set_line(0);
@@ -2188,7 +2342,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
cursor_set_line(cursor.line - 1);
cursor_set_column(text[cursor.line].length());
}
-
+ end_complex_operation();
} break;
case KEY_ESCAPE: {
if (completion_hint != "") {
@@ -2294,6 +2448,8 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
cursor_set_column(column);
} else {
+ if (cursor.line > 0 && is_line_hidden(cursor.line - 1))
+ unfold_line(cursor.line - 1);
backspace_at_cursor();
}
@@ -2352,7 +2508,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
} else if (cursor.column == 0) {
if (cursor.line > 0) {
- cursor_set_line(cursor.line - 1);
+ cursor_set_line(cursor.line - num_lines_from(CLAMP(cursor.line - 1, 0, text.size() - 1), -1));
cursor_set_column(text[cursor.line].length());
}
} else {
@@ -2415,7 +2571,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
} else if (cursor.column == text[cursor.line].length()) {
if (cursor.line < text.size() - 1) {
- cursor_set_line(cursor.line + 1);
+ cursor_set_line(cursor_get_line() + num_lines_from(CLAMP(cursor.line + 1, 0, text.size() - 1), 1), true, false);
cursor_set_column(0);
}
} else {
@@ -2456,7 +2612,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
cursor_set_line(0);
else
#endif
- cursor_set_line(cursor_get_line() - 1);
+ cursor_set_line(cursor_get_line() - num_lines_from(CLAMP(cursor.line - 1, 0, text.size() - 1), -1));
if (k->get_shift())
_post_shift_selection();
@@ -2490,10 +2646,10 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
}
if (k->get_command())
- cursor_set_line(text.size() - 1);
+ cursor_set_line(text.size() - 1, true, false);
else
#endif
- cursor_set_line(cursor_get_line() + 1);
+ cursor_set_line(cursor_get_line() + num_lines_from(CLAMP(cursor.line + 1, 0, text.size() - 1), 1), true, false);
if (k->get_shift())
_post_shift_selection();
@@ -2640,7 +2796,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
if (k->get_shift())
_pre_shift_selection();
- cursor_set_line(text.size() - 1);
+ cursor_set_line(text.size() - 1, true, false);
if (k->get_shift())
_post_shift_selection();
@@ -2655,7 +2811,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
_pre_shift_selection();
if (k->get_command())
- cursor_set_line(text.size() - 1);
+ cursor_set_line(text.size() - 1, true, false);
cursor_set_column(text[cursor.line].length());
if (k->get_shift())
@@ -2680,7 +2836,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
if (k->get_shift())
_pre_shift_selection();
- cursor_set_line(cursor_get_line() - get_visible_rows());
+ cursor_set_line(cursor_get_line() - num_lines_from(cursor.line, -get_visible_rows()), true, false);
if (k->get_shift())
_post_shift_selection();
@@ -2701,7 +2857,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
if (k->get_shift())
_pre_shift_selection();
- cursor_set_line(cursor_get_line() + get_visible_rows());
+ cursor_set_line(cursor_get_line() + num_lines_from(cursor.line, get_visible_rows()), true, false);
if (k->get_shift())
_post_shift_selection();
@@ -2823,19 +2979,19 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
if (scancode_handled)
accept_event();
/*
- if (!scancode_handled && !k->get_command() && !k->get_alt()) {
+ if (!scancode_handled && !k->get_command() && !k->get_alt()) {
if (k->get_unicode()>=32) {
- if (readonly)
+ if (readonly)
break;
- accept_event();
+ accept_event();
} else {
- break;
+ break;
+ }
}
- }
*/
if (k->get_scancode() == KEY_INSERT) {
set_insert_mode(!insert_mode);
@@ -2887,6 +3043,50 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
}
}
+void TextEdit::_scroll_up(real_t p_delta) {
+
+ if (scrolling) {
+ target_v_scroll = (target_v_scroll - p_delta);
+ } else {
+ target_v_scroll = (v_scroll->get_value() - p_delta);
+ }
+
+ if (smooth_scroll_enabled) {
+ if (target_v_scroll <= 0) {
+ target_v_scroll = 0;
+ }
+ scrolling = true;
+ set_physics_process(true);
+ } else {
+ v_scroll->set_value(target_v_scroll);
+ }
+}
+
+void TextEdit::_scroll_down(real_t p_delta) {
+
+ if (scrolling) {
+ target_v_scroll = (target_v_scroll + p_delta);
+ } else {
+ target_v_scroll = (v_scroll->get_value() + p_delta);
+ }
+
+ if (smooth_scroll_enabled) {
+ int max_v_scroll = get_total_unhidden_rows();
+ if (!scroll_past_end_of_file_enabled) {
+ max_v_scroll -= get_visible_rows();
+ max_v_scroll = CLAMP(max_v_scroll, 0, get_total_unhidden_rows());
+ }
+
+ if (target_v_scroll > max_v_scroll) {
+ target_v_scroll = max_v_scroll;
+ }
+ scrolling = true;
+ set_physics_process(true);
+ } else {
+ v_scroll->set_value(target_v_scroll);
+ }
+}
+
void TextEdit::_pre_shift_selection() {
if (!selection.active || selection.selecting_mode == Selection::MODE_NONE) {
@@ -2919,8 +3119,9 @@ void TextEdit::_scroll_lines_up() {
}
// adjust the cursor
- if (cursor_get_line() >= (get_visible_rows() + get_v_scroll()) && !selection.active) {
- cursor_set_line((get_visible_rows() + get_v_scroll()) - 1, false);
+ int num_lines = num_lines_from(CLAMP(cursor.line_ofs, 0, text.size() - 1), get_visible_rows()) - 1;
+ if (cursor.line >= cursor.line_ofs + num_lines && !selection.active) {
+ cursor_set_line(cursor.line_ofs + num_lines, false, false);
}
}
@@ -2928,9 +3129,10 @@ void TextEdit::_scroll_lines_down() {
scrolling = false;
// calculate the maximum vertical scroll position
- int max_v_scroll = get_line_count() - 1;
+ int max_v_scroll = get_total_unhidden_rows();
if (!scroll_past_end_of_file_enabled) {
- max_v_scroll -= get_visible_rows() - 1;
+ max_v_scroll -= get_visible_rows();
+ max_v_scroll = CLAMP(max_v_scroll, 0, get_total_unhidden_rows());
}
// adjust the vertical scroll
@@ -2939,8 +3141,8 @@ void TextEdit::_scroll_lines_down() {
}
// adjust the cursor
- if ((cursor_get_line()) <= get_v_scroll() - 1 && !selection.active) {
- cursor_set_line(get_v_scroll(), false);
+ if (cursor.line <= cursor.line_ofs - 1 && !selection.active) {
+ cursor_set_line(cursor.line_ofs, false, false);
}
}
@@ -2985,6 +3187,15 @@ void TextEdit::_base_insert_text(int p_line, int p_char, const String &p_text, i
}
}
+ // if we are just making a new empty line, reset breakpoints and hidden status
+ if (p_char == 0 && p_text.replace("\r", "") == "\n") {
+
+ text.set_breakpoint(p_line + 1, text.is_breakpoint(p_line));
+ text.set_hidden(p_line + 1, text.is_hidden(p_line));
+ text.set_breakpoint(p_line, false);
+ text.set_hidden(p_line, false);
+ }
+
r_end_line = p_line + substrings.size() - 1;
r_end_column = text[r_end_line].length() - postinsert_text.length();
@@ -3183,6 +3394,7 @@ Size2 TextEdit::get_minimum_size() const {
return cache.style_normal->get_minimum_size();
}
+
int TextEdit::get_visible_rows() const {
int total = cache.size.height;
@@ -3190,31 +3402,81 @@ int TextEdit::get_visible_rows() const {
total /= get_row_height();
return total;
}
+
+int TextEdit::get_total_unhidden_rows() const {
+ if (!is_hiding_enabled())
+ return text.size();
+
+ int total_unhidden = 0;
+ for (int i = 0; i < text.size(); i++) {
+ if (!text.is_hidden(i))
+ total_unhidden++;
+ }
+ return total_unhidden;
+}
+
+double TextEdit::get_line_scroll_pos(bool p_recalculate) const {
+
+ if (!is_hiding_enabled())
+ return cursor.line_ofs;
+ if (!p_recalculate)
+ return line_scroll_pos;
+
+ // count num unhidden lines to the cursor line ofs
+ double new_line_scroll_pos = 0;
+ int to = CLAMP(cursor.line_ofs, 0, text.size() - 1);
+ for (int i = 0; i < to; i++) {
+ if (!text.is_hidden(i))
+ new_line_scroll_pos++;
+ }
+ return new_line_scroll_pos;
+}
+
+void TextEdit::update_line_scroll_pos() {
+
+ if (!is_hiding_enabled()) {
+ line_scroll_pos = cursor.line_ofs;
+ return;
+ }
+
+ // count num unhidden lines to the cursor line ofs
+ double new_line_scroll_pos = 0;
+ int to = CLAMP(cursor.line_ofs, 0, text.size() - 1);
+ for (int i = 0; i < to; i++) {
+ if (!text.is_hidden(i))
+ new_line_scroll_pos++;
+ }
+ line_scroll_pos = new_line_scroll_pos;
+}
+
void TextEdit::adjust_viewport_to_cursor() {
scrolling = false;
- if (cursor.line_ofs > cursor.line)
+ if (cursor.line_ofs > cursor.line) {
cursor.line_ofs = cursor.line;
+ }
- int visible_width = cache.size.width - cache.style_normal->get_minimum_size().width - cache.line_number_w - cache.breakpoint_gutter_width;
+ int visible_width = cache.size.width - cache.style_normal->get_minimum_size().width - cache.line_number_w - cache.breakpoint_gutter_width - cache.fold_gutter_width;
if (v_scroll->is_visible_in_tree())
visible_width -= v_scroll->get_combined_minimum_size().width;
visible_width -= 20; // give it a little more space
- //printf("rowofs %i, visrows %i, cursor.line %i\n",cursor.line_ofs,get_visible_rows(),cursor.line);
-
int visible_rows = get_visible_rows();
if (h_scroll->is_visible_in_tree())
visible_rows -= ((h_scroll->get_combined_minimum_size().height - 1) / get_row_height());
+ int num_rows = num_lines_from(CLAMP(cursor.line_ofs, 0, text.size() - 1), MIN(visible_rows, text.size() - 1 - cursor.line_ofs));
- if (cursor.line >= (cursor.line_ofs + visible_rows))
- cursor.line_ofs = cursor.line - visible_rows;
- if (cursor.line < cursor.line_ofs)
+ // if the cursor is off the screen
+ if (cursor.line >= (cursor.line_ofs + MAX(num_rows, visible_rows))) {
+ cursor.line_ofs = cursor.line - (num_lines_from(CLAMP(cursor.line, 0, text.size() - 1), -visible_rows) - 1);
+ }
+ if (cursor.line < cursor.line_ofs) {
cursor.line_ofs = cursor.line;
+ }
- if (cursor.line_ofs + visible_rows > text.size() && !scroll_past_end_of_file_enabled) {
- cursor.line_ofs = text.size() - visible_rows;
- v_scroll->set_value(text.size() - visible_rows);
+ // fixes deleting lines from moving the line ofs in a bad way
+ if (!scroll_past_end_of_file_enabled && get_total_unhidden_rows() > visible_rows && num_rows < visible_rows) {
+ cursor.line_ofs = text.size() - 1 - (num_lines_from(text.size() - 1, -visible_rows) - 1);
}
int cursor_x = get_column_x_offset(cursor.column, text[cursor.line]);
@@ -3225,13 +3487,18 @@ void TextEdit::adjust_viewport_to_cursor() {
if (cursor_x < cursor.x_ofs)
cursor.x_ofs = cursor_x;
+ update_line_scroll_pos();
+ if (get_line_scroll_pos() == 0)
+ v_scroll->set_value(0);
+ else
+ v_scroll->set_value(get_line_scroll_pos() + 1);
update();
/*
- get_range()->set_max(text.size());
+ get_range()->set_max(text.size());
- get_range()->set_page(get_visible_rows());
+ get_range()->set_page(get_visible_rows());
- get_range()->set((int)cursor.line_ofs);
+ get_range()->set((int)cursor.line_ofs);
*/
}
@@ -3241,7 +3508,10 @@ void TextEdit::center_viewport_to_cursor() {
if (cursor.line_ofs > cursor.line)
cursor.line_ofs = cursor.line;
- int visible_width = cache.size.width - cache.style_normal->get_minimum_size().width - cache.line_number_w - cache.breakpoint_gutter_width;
+ if (is_line_hidden(cursor.line))
+ unfold_line(cursor.line);
+
+ int visible_width = cache.size.width - cache.style_normal->get_minimum_size().width - cache.line_number_w - cache.breakpoint_gutter_width - cache.fold_gutter_width;
if (v_scroll->is_visible_in_tree())
visible_width -= v_scroll->get_combined_minimum_size().width;
visible_width -= 20; // give it a little more space
@@ -3250,9 +3520,8 @@ void TextEdit::center_viewport_to_cursor() {
if (h_scroll->is_visible_in_tree())
visible_rows -= ((h_scroll->get_combined_minimum_size().height - 1) / get_row_height());
- int max_ofs = text.size() - (scroll_past_end_of_file_enabled ? 1 : visible_rows);
- cursor.line_ofs = CLAMP(cursor.line - (visible_rows / 2), 0, max_ofs);
-
+ int max_ofs = text.size() - (scroll_past_end_of_file_enabled ? 1 : num_lines_from(text.size() - 1, -visible_rows));
+ cursor.line_ofs = CLAMP(cursor.line - num_lines_from(cursor.line - visible_rows / 2, -visible_rows / 2), 0, max_ofs);
int cursor_x = get_column_x_offset(cursor.column, text[cursor.line]);
if (cursor_x > (cursor.x_ofs + visible_width))
@@ -3261,6 +3530,9 @@ void TextEdit::center_viewport_to_cursor() {
if (cursor_x < cursor.x_ofs)
cursor.x_ofs = cursor_x;
+ update_line_scroll_pos();
+ v_scroll->set_value(get_line_scroll_pos());
+
update();
}
@@ -3285,7 +3557,7 @@ void TextEdit::cursor_set_column(int p_col, bool p_adjust_viewport) {
}
}
-void TextEdit::cursor_set_line(int p_row, bool p_adjust_viewport) {
+void TextEdit::cursor_set_line(int p_row, bool p_adjust_viewport, bool p_can_be_hidden) {
if (setting_row)
return;
@@ -3297,6 +3569,21 @@ void TextEdit::cursor_set_line(int p_row, bool p_adjust_viewport) {
if (p_row >= (int)text.size())
p_row = (int)text.size() - 1;
+ if (!p_can_be_hidden) {
+ if (is_line_hidden(CLAMP(p_row, 0, text.size() - 1))) {
+ int move_down = num_lines_from(p_row, 1) - 1;
+ if (p_row + move_down <= text.size() - 1 && !is_line_hidden(p_row + move_down)) {
+ p_row += move_down;
+ } else {
+ int move_up = num_lines_from(p_row, -1) - 1;
+ if (p_row - move_up > 0 && !is_line_hidden(p_row - move_up)) {
+ p_row -= move_up;
+ } else {
+ WARN_PRINTS(("Cursor set to hidden line " + itos(p_row) + " and there are no nonhidden lines."));
+ }
+ }
+ }
+ }
cursor.line = p_row;
cursor.column = get_char_pos_for(cursor.last_fit_x, get_line(cursor.line));
@@ -3366,8 +3653,11 @@ void TextEdit::_scroll_moved(double p_to_val) {
if (h_scroll->is_visible_in_tree())
cursor.x_ofs = h_scroll->get_value();
- if (v_scroll->is_visible_in_tree())
- cursor.line_ofs = v_scroll->get_value();
+ if (v_scroll->is_visible_in_tree()) {
+ double val = v_scroll->get_value();
+ cursor.line_ofs = num_lines_from(0, (int)floor(val)) - 1;
+ line_scroll_pos = (int)floor(val);
+ }
update();
}
@@ -3456,10 +3746,43 @@ Control::CursorShape TextEdit::get_cursor_shape(const Point2 &p_pos) const {
if (highlighted_word != String())
return CURSOR_POINTING_HAND;
- int gutter = cache.style_normal->get_margin(MARGIN_LEFT) + cache.line_number_w + cache.breakpoint_gutter_width;
- if ((completion_active && completion_rect.has_point(p_pos)) || p_pos.x < gutter) {
+ int gutter = cache.style_normal->get_margin(MARGIN_LEFT) + cache.line_number_w + cache.breakpoint_gutter_width + cache.fold_gutter_width;
+ if ((completion_active && completion_rect.has_point(p_pos))) {
return CURSOR_ARROW;
}
+ if (p_pos.x < gutter) {
+
+ int row, col;
+ _get_mouse_pos(p_pos, row, col);
+ int left_margin = cache.style_normal->get_margin(MARGIN_LEFT);
+
+ // breakpoint icon
+ if (draw_breakpoint_gutter && p_pos.x > left_margin && p_pos.x <= left_margin + cache.breakpoint_gutter_width + 3) {
+ return CURSOR_POINTING_HAND;
+ }
+
+ // fold icon
+ int gutter_left = left_margin + cache.breakpoint_gutter_width + cache.line_number_w;
+ if (draw_fold_gutter && p_pos.x > gutter_left - 6 && p_pos.x <= gutter_left + cache.fold_gutter_width - 3) {
+ if (is_folded(row) || can_fold(row))
+ return CURSOR_POINTING_HAND;
+ else
+ return CURSOR_ARROW;
+ }
+ return CURSOR_ARROW;
+ } else {
+ int row, col;
+ _get_mouse_pos(p_pos, row, col);
+ // eol fold icon
+ if (is_folded(row)) {
+ int line_width = text.get_line_width(row);
+ line_width += cache.style_normal->get_margin(MARGIN_LEFT) + cache.line_number_w + cache.breakpoint_gutter_width + cache.fold_gutter_width - cursor.x_ofs;
+ if (p_pos.x > line_width - 3 && p_pos.x <= line_width + cache.folded_eol_icon->get_width() + 3) {
+ return CURSOR_POINTING_HAND;
+ }
+ }
+ }
+
return CURSOR_IBEAM;
}
@@ -3473,6 +3796,7 @@ void TextEdit::set_text(String p_text) {
cursor.line = 0;
cursor.x_ofs = 0;
cursor.line_ofs = 0;
+ line_scroll_pos = 0;
cursor.last_fit_x = 0;
cursor_set_line(0);
cursor_set_column(0);
@@ -3558,6 +3882,7 @@ void TextEdit::_clear() {
cursor.line = 0;
cursor.x_ofs = 0;
cursor.line_ofs = 0;
+ line_scroll_pos = 0;
cursor.last_fit_x = 0;
}
@@ -3573,6 +3898,11 @@ void TextEdit::set_readonly(bool p_readonly) {
readonly = p_readonly;
}
+bool TextEdit::is_readonly() const {
+
+ return readonly;
+}
+
void TextEdit::set_wrap(bool p_wrap) {
wrap = p_wrap;
@@ -3631,6 +3961,9 @@ void TextEdit::_update_caches() {
cache.line_spacing = get_constant("line_spacing");
cache.row_height = cache.font->get_height() + cache.line_spacing;
cache.tab_icon = get_icon("tab");
+ cache.folded_icon = get_icon("GuiTreeArrowRight", "EditorIcons");
+ cache.can_fold_icon = get_icon("GuiTreeArrowDown", "EditorIcons");
+ cache.folded_eol_icon = get_icon("GuiEllipsis", "EditorIcons");
text.set_font(cache.font);
}
@@ -3805,7 +4138,12 @@ void TextEdit::select(int p_from_line, int p_from_column, int p_to_line, int p_t
update();
}
-
+void TextEdit::swap_lines(int line1, int line2) {
+ String tmp = get_line(line1);
+ String tmp2 = get_line(line2);
+ set_line(line2, tmp);
+ set_line(line1, tmp2);
+}
bool TextEdit::is_selection_active() const {
return selection.active;
@@ -4072,6 +4410,198 @@ void TextEdit::get_breakpoints(List<int> *p_breakpoints) const {
}
}
+void TextEdit::set_line_as_hidden(int p_line, bool p_hidden) {
+
+ ERR_FAIL_INDEX(p_line, text.size());
+ if (is_hiding_enabled() || !p_hidden)
+ text.set_hidden(p_line, p_hidden);
+ update();
+}
+
+bool TextEdit::is_line_hidden(int p_line) const {
+
+ ERR_FAIL_INDEX_V(p_line, text.size(), false);
+ return text.is_hidden(p_line);
+}
+
+void TextEdit::fold_all_lines() {
+
+ for (int i = 0; i < text.size(); i++) {
+ fold_line(i);
+ }
+ _update_scrollbars();
+ update();
+}
+
+void TextEdit::unhide_all_lines() {
+
+ for (int i = 0; i < text.size(); i++) {
+ text.set_hidden(i, false);
+ }
+ _update_scrollbars();
+ update();
+}
+
+int TextEdit::num_lines_from(int p_line_from, int unhidden_amount) const {
+
+ // returns the number of hidden and unhidden lines from p_line_from to p_line_from + amount of visible lines
+ ERR_FAIL_INDEX_V(p_line_from, text.size(), ABS(unhidden_amount));
+
+ if (!is_hiding_enabled())
+ return unhidden_amount;
+ int num_visible = 0;
+ int num_total = 0;
+ if (unhidden_amount >= 0) {
+ for (int i = p_line_from; i < text.size(); i++) {
+ num_total++;
+ if (!is_line_hidden(i))
+ num_visible++;
+ if (num_visible >= unhidden_amount)
+ break;
+ }
+ } else {
+ unhidden_amount = ABS(unhidden_amount);
+ for (int i = p_line_from; i >= 0; i--) {
+ num_total++;
+ if (!is_line_hidden(i))
+ num_visible++;
+ if (num_visible >= unhidden_amount)
+ break;
+ }
+ }
+ return num_total;
+}
+
+int TextEdit::get_whitespace_level(int p_line) const {
+
+ ERR_FAIL_INDEX_V(p_line, text.size(), 0);
+
+ // counts number of tabs and spaces before line starts
+ int whitespace_count = 0;
+ int line_length = text[p_line].size();
+ for (int i = 0; i < line_length - 1; i++) {
+ if (text[p_line][i] == '\t') {
+ whitespace_count++;
+ } else if (text[p_line][i] == ' ') {
+ whitespace_count++;
+ } else if (text[p_line][i] == '#') {
+ break;
+ } else {
+ break;
+ }
+ }
+ return whitespace_count;
+}
+
+bool TextEdit::can_fold(int p_line) const {
+
+ ERR_FAIL_INDEX_V(p_line, text.size(), false);
+ if (!is_hiding_enabled())
+ return false;
+ if (p_line + 1 >= text.size())
+ return false;
+ if (text[p_line].size() == 0)
+ return false;
+ if (is_folded(p_line))
+ return false;
+ if (is_line_hidden(p_line))
+ return false;
+
+ int start_indent = get_whitespace_level(p_line);
+
+ for (int i = p_line + 1; i < text.size(); i++) {
+ if (text[i].size() == 0)
+ continue;
+ int next_indent = get_whitespace_level(i);
+ if (next_indent > start_indent)
+ return true;
+ else
+ return false;
+ }
+
+ return false;
+}
+
+bool TextEdit::is_folded(int p_line) const {
+
+ ERR_FAIL_INDEX_V(p_line, text.size(), false);
+ if (p_line + 1 >= text.size() - 1)
+ return false;
+ if (!is_line_hidden(p_line) && is_line_hidden(p_line + 1))
+ return true;
+ return false;
+}
+
+void TextEdit::fold_line(int p_line) {
+
+ ERR_FAIL_INDEX(p_line, text.size());
+ if (!is_hiding_enabled())
+ return;
+ if (!can_fold(p_line))
+ return;
+
+ // hide lines below this one
+ int start_indent = get_whitespace_level(p_line);
+ for (int i = p_line + 1; i < text.size(); i++) {
+ int cur_indent = get_whitespace_level(i);
+ if (text[i].size() == 0 || cur_indent > start_indent) {
+ set_line_as_hidden(i, true);
+ } else {
+ // exclude trailing empty lines
+ for (int trail_i = i - 1; trail_i > p_line; trail_i--) {
+ if (text[trail_i].size() == 0)
+ set_line_as_hidden(trail_i, false);
+ else
+ break;
+ }
+ break;
+ }
+ }
+
+ // fix selection
+ if (is_selection_active()) {
+ if (is_line_hidden(selection.from_line) && is_line_hidden(selection.to_line)) {
+ deselect();
+ } else if (is_line_hidden(selection.from_line)) {
+ select(p_line, 9999, selection.to_line, selection.to_column);
+ } else if (is_line_hidden(selection.to_line)) {
+ select(selection.from_line, selection.from_column, p_line, 9999);
+ }
+ }
+
+ // reset cursor
+ if (is_line_hidden(cursor.line)) {
+ cursor_set_line(p_line, false, false);
+ cursor_set_column(get_line(p_line).length(), false);
+ }
+ _update_scrollbars();
+ update();
+}
+
+void TextEdit::unfold_line(int p_line) {
+
+ ERR_FAIL_INDEX(p_line, text.size());
+
+ if (!is_folded(p_line) && !is_line_hidden(p_line))
+ return;
+ int fold_start = p_line;
+ for (fold_start = p_line; fold_start > 0; fold_start--) {
+ if (is_folded(fold_start))
+ break;
+ }
+ fold_start = is_folded(fold_start) ? fold_start : p_line;
+
+ for (int i = fold_start + 1; i < text.size(); i++) {
+ if (is_line_hidden(i)) {
+ set_line_as_hidden(i, false);
+ } else {
+ break;
+ }
+ }
+ _update_scrollbars();
+ update();
+}
+
int TextEdit::get_line_count() const {
return text.size();
@@ -4256,6 +4786,13 @@ bool TextEdit::is_drawing_tabs() const {
return draw_tabs;
}
+void TextEdit::set_override_selected_font_color(bool p_override_selected_font_color) {
+ override_selected_font_color = p_override_selected_font_color;
+}
+bool TextEdit::is_overriding_selected_font_color() const {
+ return override_selected_font_color;
+}
+
void TextEdit::set_insert_mode(bool p_enabled) {
insert_mode = p_enabled;
update();
@@ -4287,8 +4824,18 @@ int TextEdit::get_v_scroll() const {
}
void TextEdit::set_v_scroll(int p_scroll) {
+ if (p_scroll < 0) {
+ p_scroll = 0;
+ }
+ if (!scroll_past_end_of_file_enabled) {
+ if (p_scroll + get_visible_rows() > get_total_unhidden_rows()) {
+ int num_rows = num_lines_from(CLAMP(p_scroll, 0, text.size() - 1), MIN(get_visible_rows(), text.size() - 1 - p_scroll));
+ p_scroll = text.size() - num_rows;
+ }
+ }
v_scroll->set_value(p_scroll);
- cursor.line_ofs = p_scroll;
+ cursor.line_ofs = num_lines_from(0, p_scroll);
+ line_scroll_pos = p_scroll;
}
int TextEdit::get_h_scroll() const {
@@ -4449,7 +4996,13 @@ void TextEdit::_update_completion_candidates() {
completion_index = 0;
completion_base = s;
Vector<float> sim_cache;
+ bool single_quote = s.begins_with("'");
+
for (int i = 0; i < completion_strings.size(); i++) {
+ if (single_quote && completion_strings[i].is_quoted()) {
+ completion_strings[i] = completion_strings[i].unquote().quote("'");
+ }
+
if (s == completion_strings[i]) {
// A perfect match, stop completion
_cancel_completion();
@@ -4644,7 +5197,7 @@ void TextEdit::set_line(int line, String new_text) {
void TextEdit::insert_at(const String &p_text, int at) {
cursor_set_column(0);
- cursor_set_line(at);
+ cursor_set_line(at, false, true);
_insert_text(at, 0, p_text + "\n");
}
@@ -4692,6 +5245,44 @@ int TextEdit::get_breakpoint_gutter_width() const {
return cache.breakpoint_gutter_width;
}
+void TextEdit::set_draw_fold_gutter(bool p_draw) {
+ draw_fold_gutter = p_draw;
+ update();
+}
+
+bool TextEdit::is_drawing_fold_gutter() const {
+ return draw_fold_gutter;
+}
+
+void TextEdit::set_fold_gutter_width(int p_gutter_width) {
+ fold_gutter_width = p_gutter_width;
+ update();
+}
+
+int TextEdit::get_fold_gutter_width() const {
+ return cache.fold_gutter_width;
+}
+
+void TextEdit::set_hiding_enabled(int p_enabled) {
+ if (!p_enabled)
+ unhide_all_lines();
+ hiding_enabled = p_enabled;
+ update();
+}
+
+int TextEdit::is_hiding_enabled() const {
+ return hiding_enabled;
+}
+
+void TextEdit::set_highlight_current_line(bool p_enabled) {
+ highlight_current_line = p_enabled;
+ update();
+}
+
+bool TextEdit::is_highlight_current_line_enabled() const {
+ return highlight_current_line;
+}
+
bool TextEdit::is_text_field() const {
return true;
@@ -4741,6 +5332,10 @@ void TextEdit::set_context_menu_enabled(bool p_enable) {
context_menu_enabled = p_enable;
}
+bool TextEdit::is_context_menu_enabled() {
+ return context_menu_enabled;
+}
+
PopupMenu *TextEdit::get_menu() const {
return menu;
}
@@ -4761,8 +5356,8 @@ void TextEdit::_bind_methods() {
BIND_ENUM_CONSTANT(SEARCH_BACKWARDS);
/*
- ClassDB::bind_method(D_METHOD("delete_char"),&TextEdit::delete_char);
- ClassDB::bind_method(D_METHOD("delete_line"),&TextEdit::delete_line);
+ ClassDB::bind_method(D_METHOD("delete_char"),&TextEdit::delete_char);
+ ClassDB::bind_method(D_METHOD("delete_line"),&TextEdit::delete_line);
*/
ClassDB::bind_method(D_METHOD("set_text", "text"), &TextEdit::set_text);
@@ -4773,7 +5368,7 @@ void TextEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_line", "line"), &TextEdit::get_line);
ClassDB::bind_method(D_METHOD("cursor_set_column", "column", "adjust_viewport"), &TextEdit::cursor_set_column, DEFVAL(true));
- ClassDB::bind_method(D_METHOD("cursor_set_line", "line", "adjust_viewport"), &TextEdit::cursor_set_line, DEFVAL(true));
+ ClassDB::bind_method(D_METHOD("cursor_set_line", "line", "adjust_viewport", "can_be_hidden"), &TextEdit::cursor_set_line, DEFVAL(true), DEFVAL(true));
ClassDB::bind_method(D_METHOD("cursor_get_column"), &TextEdit::cursor_get_column);
ClassDB::bind_method(D_METHOD("cursor_get_line"), &TextEdit::cursor_get_line);
@@ -4785,8 +5380,12 @@ void TextEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("cursor_is_block_mode"), &TextEdit::cursor_is_block_mode);
ClassDB::bind_method(D_METHOD("set_readonly", "enable"), &TextEdit::set_readonly);
+ ClassDB::bind_method(D_METHOD("is_readonly"), &TextEdit::is_readonly);
+
ClassDB::bind_method(D_METHOD("set_wrap", "enable"), &TextEdit::set_wrap);
ClassDB::bind_method(D_METHOD("set_max_chars", "amount"), &TextEdit::set_max_chars);
+ ClassDB::bind_method(D_METHOD("set_context_menu_enabled", "enable"), &TextEdit::set_context_menu_enabled);
+ ClassDB::bind_method(D_METHOD("is_context_menu_enabled"), &TextEdit::is_context_menu_enabled);
ClassDB::bind_method(D_METHOD("cut"), &TextEdit::cut);
ClassDB::bind_method(D_METHOD("copy"), &TextEdit::copy);
@@ -4810,12 +5409,29 @@ void TextEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_show_line_numbers", "enable"), &TextEdit::set_show_line_numbers);
ClassDB::bind_method(D_METHOD("is_show_line_numbers_enabled"), &TextEdit::is_show_line_numbers_enabled);
+ ClassDB::bind_method(D_METHOD("set_hiding_enabled", "enable"), &TextEdit::set_hiding_enabled);
+ ClassDB::bind_method(D_METHOD("is_hiding_enabled"), &TextEdit::is_hiding_enabled);
+ ClassDB::bind_method(D_METHOD("set_line_as_hidden", "line", "enable"), &TextEdit::set_line_as_hidden);
+ ClassDB::bind_method(D_METHOD("is_line_hidden"), &TextEdit::is_line_hidden);
+ ClassDB::bind_method(D_METHOD("fold_all_lines"), &TextEdit::fold_all_lines);
+ ClassDB::bind_method(D_METHOD("unhide_all_lines"), &TextEdit::unhide_all_lines);
+ ClassDB::bind_method(D_METHOD("fold_line", "line"), &TextEdit::fold_line);
+ ClassDB::bind_method(D_METHOD("unfold_line", "line"), &TextEdit::unfold_line);
+ ClassDB::bind_method(D_METHOD("can_fold", "line"), &TextEdit::can_fold);
+ ClassDB::bind_method(D_METHOD("is_folded", "line"), &TextEdit::is_folded);
+
ClassDB::bind_method(D_METHOD("set_highlight_all_occurrences", "enable"), &TextEdit::set_highlight_all_occurrences);
ClassDB::bind_method(D_METHOD("is_highlight_all_occurrences_enabled"), &TextEdit::is_highlight_all_occurrences_enabled);
+ ClassDB::bind_method(D_METHOD("set_override_selected_font_color", "override"), &TextEdit::set_override_selected_font_color);
+ ClassDB::bind_method(D_METHOD("is_overriding_selected_font_color"), &TextEdit::is_overriding_selected_font_color);
+
ClassDB::bind_method(D_METHOD("set_syntax_coloring", "enable"), &TextEdit::set_syntax_coloring);
ClassDB::bind_method(D_METHOD("is_syntax_coloring_enabled"), &TextEdit::is_syntax_coloring_enabled);
+ ClassDB::bind_method(D_METHOD("set_highlight_current_line", "enabled"), &TextEdit::set_highlight_current_line);
+ ClassDB::bind_method(D_METHOD("is_highlight_current_line_enabled"), &TextEdit::is_highlight_current_line_enabled);
+
ClassDB::bind_method(D_METHOD("set_smooth_scroll_enable", "enable"), &TextEdit::set_smooth_scroll_enabled);
ClassDB::bind_method(D_METHOD("is_smooth_scroll_enabled"), &TextEdit::is_smooth_scroll_enabled);
ClassDB::bind_method(D_METHOD("set_v_scroll_speed", "speed"), &TextEdit::set_v_scroll_speed);
@@ -4827,11 +5443,17 @@ void TextEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("menu_option", "option"), &TextEdit::menu_option);
ClassDB::bind_method(D_METHOD("get_menu"), &TextEdit::get_menu);
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "text", PROPERTY_HINT_MULTILINE_TEXT), "set_text", "get_text");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "readonly"), "set_readonly", "is_readonly");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "highlight_current_line"), "set_highlight_current_line", "is_highlight_current_line_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "syntax_highlighting"), "set_syntax_coloring", "is_syntax_coloring_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_line_numbers"), "set_show_line_numbers", "is_show_line_numbers_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "highlight_all_occurrences"), "set_highlight_all_occurrences", "is_highlight_all_occurrences_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "override_selected_font_color"), "set_override_selected_font_color", "is_overriding_selected_font_color");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "context_menu_enabled"), "set_context_menu_enabled", "is_context_menu_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "smooth_scrolling"), "set_smooth_scroll_enable", "is_smooth_scroll_enabled");
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_GROUP("Caret", "caret_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret_block_mode"), "cursor_set_block_mode", "cursor_is_block_mode");
@@ -4860,6 +5482,7 @@ TextEdit::TextEdit() {
readonly = false;
setting_row = false;
draw_tabs = false;
+ override_selected_font_color = false;
draw_caret = true;
max_chars = 0;
clear();
@@ -4872,6 +5495,8 @@ TextEdit::TextEdit() {
cache.line_number_w = 1;
cache.breakpoint_gutter_width = 0;
breakpoint_gutter_width = 0;
+ cache.fold_gutter_width = 0;
+ fold_gutter_width = 0;
indent_size = 4;
text.set_indent_size(indent_size);
@@ -4941,11 +5566,14 @@ TextEdit::TextEdit() {
line_length_guideline = false;
line_length_guideline_col = 80;
draw_breakpoint_gutter = false;
+ draw_fold_gutter = false;
+ hiding_enabled = false;
next_operation_is_complex = false;
scroll_past_end_of_file_enabled = false;
auto_brace_completion_enabled = false;
brace_matching_enabled = false;
highlight_all_occurrences = false;
+ highlight_current_line = false;
indent_using_spaces = false;
space_indent = " ";
auto_indent = false;
diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h
index 7e61c4e8b1..bb9ca87d06 100644
--- a/scene/gui/text_edit.h
+++ b/scene/gui/text_edit.h
@@ -51,11 +51,14 @@ class TextEdit : public Control {
MODE_NONE,
MODE_SHIFT,
- MODE_POINTER
+ MODE_POINTER,
+ MODE_WORD,
+ MODE_LINE
};
Mode selecting_mode;
int selecting_line, selecting_column;
+ int selected_word_beg, selected_word_end, selected_word_origin;
bool selecting_text;
bool active;
@@ -70,6 +73,9 @@ class TextEdit : public Control {
struct Cache {
Ref<Texture> tab_icon;
+ Ref<Texture> can_fold_icon;
+ Ref<Texture> folded_icon;
+ Ref<Texture> folded_eol_icon;
Ref<StyleBox> style_normal;
Ref<StyleBox> style_focus;
Ref<Font> font;
@@ -102,6 +108,7 @@ class TextEdit : public Control {
int line_spacing;
int line_number_w;
int breakpoint_gutter_width;
+ int fold_gutter_width;
Size2 size;
} cache;
@@ -133,6 +140,7 @@ class TextEdit : public Control {
int width_cache : 24;
bool marked : 1;
bool breakpoint : 1;
+ bool hidden : 1;
Map<int, ColorRegionInfo> region_info;
String data;
};
@@ -157,6 +165,8 @@ class TextEdit : public Control {
bool is_marked(int p_line) const { return text[p_line].marked; }
void set_breakpoint(int p_line, bool p_breakpoint) { text[p_line].breakpoint = p_breakpoint; }
bool is_breakpoint(int p_line) const { return text[p_line].breakpoint; }
+ void set_hidden(int p_line, bool p_hidden) { text[p_line].hidden = p_hidden; }
+ bool is_hidden(int p_line) const { return text[p_line].hidden; }
void insert(int p_at, const String &p_text);
void remove(int p_at);
int size() const { return text.size(); }
@@ -238,6 +248,7 @@ class TextEdit : public Control {
bool setting_row;
bool wrap;
bool draw_tabs;
+ bool override_selected_font_color;
bool cursor_changed_dirty;
bool text_changed_dirty;
bool undo_enabled;
@@ -247,11 +258,15 @@ class TextEdit : public Control {
int line_length_guideline_col;
bool draw_breakpoint_gutter;
int breakpoint_gutter_width;
+ bool draw_fold_gutter;
+ int fold_gutter_width;
+ bool hiding_enabled;
bool highlight_all_occurrences;
bool scroll_past_end_of_file_enabled;
bool auto_brace_completion_enabled;
bool brace_matching_enabled;
+ bool highlight_current_line;
bool auto_indent;
bool cut_copy_line;
bool insert_mode;
@@ -288,9 +303,14 @@ class TextEdit : public Control {
int search_result_line;
int search_result_col;
+ double line_scroll_pos;
+
bool context_menu_enabled;
int get_visible_rows() const;
+ int get_total_unhidden_rows() const;
+ double get_line_scroll_pos(bool p_recalculate = false) const;
+ void update_line_scroll_pos();
int get_char_count();
@@ -298,11 +318,19 @@ class TextEdit : public Control {
int get_column_x_offset(int p_char, String p_str);
void adjust_viewport_to_cursor();
+ double get_scroll_line_diff() const;
void _scroll_moved(double);
void _update_scrollbars();
void _v_scroll_input();
void _click_selection_held();
+ void _update_selection_mode_pointer();
+ void _update_selection_mode_word();
+ void _update_selection_mode_line();
+
+ void _scroll_up(real_t p_delta);
+ void _scroll_down(real_t p_delta);
+
void _pre_shift_selection();
void _post_shift_selection();
@@ -396,6 +424,18 @@ public:
void set_line_as_breakpoint(int p_line, bool p_breakpoint);
bool is_line_set_as_breakpoint(int p_line) const;
void get_breakpoints(List<int> *p_breakpoints) const;
+
+ void set_line_as_hidden(int p_line, bool p_hidden);
+ bool is_line_hidden(int p_line) const;
+ void fold_all_lines();
+ void unhide_all_lines();
+ int num_lines_from(int p_line_from, int unhidden_amount) const;
+ int get_whitespace_level(int p_line) const;
+ bool can_fold(int p_line) const;
+ bool is_folded(int p_line) const;
+ void fold_line(int p_line);
+ void unfold_line(int p_line);
+
String get_text();
String get_line(int line) const;
void set_line(int line, String new_text);
@@ -424,7 +464,7 @@ public:
void center_viewport_to_cursor();
void cursor_set_column(int p_col, bool p_adjust_viewport = true);
- void cursor_set_line(int p_row, bool p_adjust_viewport = true);
+ void cursor_set_line(int p_row, bool p_adjust_viewport = true, bool p_can_be_hidden = true);
int cursor_get_column() const;
int cursor_get_line() const;
@@ -439,6 +479,7 @@ public:
bool cursor_is_block_mode() const;
void set_readonly(bool p_readonly);
+ bool is_readonly() const;
void set_max_chars(int p_max_chars);
void set_wrap(bool p_wrap);
@@ -454,6 +495,7 @@ public:
void select_all();
void select(int p_from_line, int p_from_column, int p_to_line, int p_to_column);
void deselect();
+ void swap_lines(int line1, int line2);
void set_search_text(const String &p_search_text);
void set_search_flags(uint32_t p_flags);
@@ -482,6 +524,8 @@ public:
void set_indent_size(const int p_size);
void set_draw_tabs(bool p_draw);
bool is_drawing_tabs() const;
+ void set_override_selected_font_color(bool p_override_selected_font_color);
+ bool is_overriding_selected_font_color() const;
void set_insert_mode(bool p_enabled);
bool is_insert_mode() const;
@@ -511,6 +555,9 @@ public:
void set_show_line_numbers(bool p_show);
bool is_show_line_numbers_enabled() const;
+ void set_highlight_current_line(bool p_enabled);
+ bool is_highlight_current_line_enabled() const;
+
void set_line_numbers_zero_padded(bool p_zero_padded);
void set_show_line_length_guideline(bool p_show);
@@ -522,6 +569,15 @@ public:
void set_breakpoint_gutter_width(int p_gutter_width);
int get_breakpoint_gutter_width() const;
+ void set_draw_fold_gutter(bool p_draw);
+ bool is_drawing_fold_gutter() const;
+
+ void set_fold_gutter_width(int p_gutter_width);
+ int get_fold_gutter_width() const;
+
+ void set_hiding_enabled(int p_enabled);
+ int is_hiding_enabled() const;
+
void set_tooltip_request_func(Object *p_obj, const StringName &p_function, const Variant &p_udata);
void set_completion(bool p_enabled, const Vector<String> &p_prefixes);
@@ -533,6 +589,8 @@ public:
bool is_selecting_identifiers_on_hover_enabled() const;
void set_context_menu_enabled(bool p_enable);
+ bool is_context_menu_enabled();
+
PopupMenu *get_menu() const;
String get_text_for_completion();
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index 178a1c272b..9213296c55 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -28,6 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "tree.h"
+#include <limits.h>
#include "os/input.h"
#include "os/keyboard.h"
@@ -47,18 +48,21 @@ void TreeItem::move_to_top() {
}
void TreeItem::move_to_bottom() {
-
if (!parent || !next)
return;
- while (next) {
+ TreeItem *prev = get_prev();
+ TreeItem *last = next;
+ while (last->next)
+ last = last->next;
- if (parent->childs == this)
- parent->childs = next;
- TreeItem *n = next;
- next = n->next;
- n->next = this;
+ if (prev) {
+ prev->next = next;
+ } else {
+ parent->childs = next;
}
+ last->next = this;
+ next = NULL;
}
Size2 TreeItem::Cell::get_icon_size() const {
@@ -151,8 +155,17 @@ void TreeItem::set_text(int p_column, String p_text) {
if (cells[p_column].mode == TreeItem::CELL_MODE_RANGE || cells[p_column].mode == TreeItem::CELL_MODE_RANGE_EXPRESSION) {
- cells[p_column].min = 0;
- cells[p_column].max = p_text.get_slice_count(",");
+ Vector<String> strings = p_text.split(",");
+ cells[p_column].min = INT_MAX;
+ cells[p_column].max = INT_MIN;
+ for (int i = 0; i < strings.size(); i++) {
+ int value = i;
+ if (!strings[i].get_slicec(':', 1).empty()) {
+ value = strings[i].get_slicec(':', 1).to_int();
+ }
+ cells[p_column].min = MIN(cells[p_column].min, value);
+ cells[p_column].max = MAX(cells[p_column].max, value);
+ }
cells[p_column].step = 0;
}
_changed_notify(p_column);
@@ -1123,7 +1136,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
if (p_item->cells[i].selected && select_mode != SELECT_ROW) {
- Rect2i r(item_rect.position, item_rect.size);
+ Rect2i r(cell_rect.position, cell_rect.size);
if (p_item->cells[i].text.size() > 0) {
float icon_width = p_item->cells[i].get_icon_size().width;
r.position.x += icon_width;
@@ -1228,8 +1241,18 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
int option = (int)p_item->cells[i].val;
- String s = p_item->cells[i].text;
- s = s.get_slicec(',', option);
+ String s = RTR("(Other)");
+ Vector<String> strings = p_item->cells[i].text.split(",");
+ for (int i = 0; i < strings.size(); i++) {
+ int value = i;
+ if (!strings[i].get_slicec(':', 1).empty()) {
+ value = strings[i].get_slicec(':', 1).to_int();
+ }
+ if (option == value) {
+ s = strings[i].get_slicec(':', 0);
+ break;
+ }
+ }
if (p_item->cells[i].suffix != String())
s += " " + p_item->cells[i].suffix;
@@ -1773,7 +1796,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool
for (int i = 0; i < c.text.get_slice_count(","); i++) {
String s = c.text.get_slicec(',', i);
- popup_menu->add_item(s, i);
+ popup_menu->add_item(s.get_slicec(':', 0), s.get_slicec(':', 1).empty() ? i : s.get_slicec(':', 1).to_int());
}
popup_menu->set_size(Size2(col_width, 0));
@@ -2589,6 +2612,12 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
} break;
}
}
+
+ Ref<InputEventPanGesture> pan_gesture = p_event;
+ if (pan_gesture.is_valid()) {
+
+ v_scroll->set_value(v_scroll->get_value() + v_scroll->get_page() * pan_gesture->get_delta().y / 8);
+ }
}
bool Tree::edit_selected() {
@@ -2631,7 +2660,7 @@ bool Tree::edit_selected() {
for (int i = 0; i < c.text.get_slice_count(","); i++) {
String s = c.text.get_slicec(',', i);
- popup_menu->add_item(s, i);
+ popup_menu->add_item(s.get_slicec(':', 0), s.get_slicec(':', 1).empty() ? i : s.get_slicec(':', 1).to_int());
}
popup_menu->set_size(Size2(rect.size.width, 0));
@@ -3329,6 +3358,26 @@ Point2 Tree::get_scroll() const {
return ofs;
}
+void Tree::scroll_to_item(TreeItem *p_item) {
+
+ if (!is_visible_in_tree()) {
+
+ // hack to work around crash in get_item_rect() if Tree is not in tree.
+ return;
+ }
+
+ // make sure the scrollbar min and max are up to date with latest changes.
+ update_scrollbars();
+
+ const Rect2 r = get_item_rect(p_item);
+
+ if (r.position.y < v_scroll->get_value()) {
+ v_scroll->set_value(r.position.y);
+ } else if (r.position.y + r.size.y + 2 * cache.vseparation > v_scroll->get_value() + get_size().y) {
+ v_scroll->set_value(r.position.y + r.size.y + 2 * cache.vseparation - get_size().y);
+ }
+}
+
TreeItem *Tree::_search_item_text(TreeItem *p_at, const String &p_find, int *r_col, bool p_selectable, bool p_backwards) {
while (p_at) {
diff --git a/scene/gui/tree.h b/scene/gui/tree.h
index 2ee91a8b73..64d6016942 100644
--- a/scene/gui/tree.h
+++ b/scene/gui/tree.h
@@ -570,6 +570,7 @@ public:
TreeItem *search_item_text(const String &p_find, int *r_col = NULL, bool p_selectable = false);
Point2 get_scroll() const;
+ void scroll_to_item(TreeItem *p_item);
void set_cursor_can_exit_tree(bool p_enable);
bool can_cursor_exit_tree() const;
diff --git a/scene/gui/video_player.cpp b/scene/gui/video_player.cpp
index 190ccd50d5..1b6bd30b58 100644
--- a/scene/gui/video_player.cpp
+++ b/scene/gui/video_player.cpp
@@ -42,44 +42,127 @@ void VideoPlayer::sp_set_mix_rate(int p_rate) {
server_mix_rate = p_rate;
}
-bool VideoPlayer::sp_mix(int32_t *p_buffer, int p_frames) {
-
- if (resampler.is_ready()) {
+bool VideoPlayer::mix(AudioFrame *p_buffer, int p_frames) {
+
+ // Check the amount resampler can really handle.
+ // If it cannot, wait "wait_resampler_phase_limit" times.
+ // This mechanism contributes to smoother pause/unpause operation.
+ if (p_frames <= resampler.get_num_of_ready_frames() ||
+ wait_resampler_limit <= wait_resampler) {
+ wait_resampler = 0;
return resampler.mix(p_buffer, p_frames);
}
-
+ wait_resampler++;
return false;
}
-int VideoPlayer::_audio_mix_callback(void *p_udata, const int16_t *p_data, int p_frames) {
+// Called from main thread (eg VideoStreamPlaybackWebm::update)
+int VideoPlayer::_audio_mix_callback(void *p_udata, const float *p_data, int p_frames) {
VideoPlayer *vp = (VideoPlayer *)p_udata;
- int todo = MIN(vp->resampler.get_todo(), p_frames);
+ int todo = MIN(vp->resampler.get_writer_space(), p_frames);
- int16_t *wb = vp->resampler.get_write_buffer();
+ float *wb = vp->resampler.get_write_buffer();
int c = vp->resampler.get_channel_count();
for (int i = 0; i < todo * c; i++) {
wb[i] = p_data[i];
}
vp->resampler.write(todo);
+
return todo;
}
+// Called from audio thread
+void VideoPlayer::_mix_audio() {
+
+ if (!stream.is_valid()) {
+ return;
+ }
+ if (!playback.is_valid() || !playback->is_playing() || playback->is_paused()) {
+ return;
+ }
+
+ AudioFrame *buffer = mix_buffer.ptr();
+ int buffer_size = mix_buffer.size();
+
+ // Resample
+ if (!mix(buffer, buffer_size))
+ return;
+
+ AudioFrame vol = AudioFrame(volume, volume);
+
+ // Copy to server's audio buffer
+ switch (AudioServer::get_singleton()->get_speaker_mode()) {
+
+ case AudioServer::SPEAKER_MODE_STEREO: {
+ AudioFrame *target = AudioServer::get_singleton()->thread_get_channel_mix_buffer(bus_index, 0);
+
+ for (int j = 0; j < buffer_size; j++) {
+
+ target[j] += buffer[j] * vol;
+ }
+
+ } break;
+ case AudioServer::SPEAKER_SURROUND_51: {
+
+ AudioFrame *targets[2] = {
+ AudioServer::get_singleton()->thread_get_channel_mix_buffer(bus_index, 1),
+ AudioServer::get_singleton()->thread_get_channel_mix_buffer(bus_index, 2),
+ };
+
+ for (int j = 0; j < buffer_size; j++) {
+
+ AudioFrame frame = buffer[j] * vol;
+ targets[0][j] = frame;
+ targets[1][j] = frame;
+ }
+ } break;
+ case AudioServer::SPEAKER_SURROUND_71: {
+
+ AudioFrame *targets[3] = {
+ AudioServer::get_singleton()->thread_get_channel_mix_buffer(bus_index, 1),
+ AudioServer::get_singleton()->thread_get_channel_mix_buffer(bus_index, 2),
+ AudioServer::get_singleton()->thread_get_channel_mix_buffer(bus_index, 3)
+ };
+
+ for (int j = 0; j < buffer_size; j++) {
+
+ AudioFrame frame = buffer[j] * vol;
+ targets[0][j] += frame;
+ targets[1][j] += frame;
+ targets[2][j] += frame;
+ }
+
+ } break;
+ }
+}
+
void VideoPlayer::_notification(int p_notification) {
switch (p_notification) {
case NOTIFICATION_ENTER_TREE: {
+ AudioServer::get_singleton()->add_callback(_mix_audios, this);
+
if (stream.is_valid() && autoplay && !Engine::get_singleton()->is_editor_hint()) {
play();
}
+
+ } break;
+
+ case NOTIFICATION_EXIT_TREE: {
+
+ AudioServer::get_singleton()->remove_callback(_mix_audios, this);
+
} break;
case NOTIFICATION_INTERNAL_PROCESS: {
+ bus_index = AudioServer::get_singleton()->thread_find_bus_index(bus);
+
if (stream.is_null())
return;
if (paused)
@@ -87,10 +170,11 @@ void VideoPlayer::_notification(int p_notification) {
if (!playback->is_playing())
return;
- double audio_time = USEC_TO_SEC(OS::get_singleton()->get_ticks_usec()); //AudioServer::get_singleton()->get_mix_time();
+ double audio_time = USEC_TO_SEC(OS::get_singleton()->get_ticks_usec());
double delta = last_audio_time == 0 ? 0 : audio_time - last_audio_time;
last_audio_time = audio_time;
+
if (delta == 0)
return;
@@ -135,6 +219,9 @@ bool VideoPlayer::has_expand() const {
void VideoPlayer::set_stream(const Ref<VideoStream> &p_stream) {
stop();
+ AudioServer::get_singleton()->lock();
+ mix_buffer.resize(AudioServer::get_singleton()->thread_get_mix_buffer_size());
+ AudioServer::get_singleton()->unlock();
stream = p_stream;
if (stream.is_valid()) {
@@ -309,6 +396,40 @@ bool VideoPlayer::has_autoplay() const {
return autoplay;
};
+void VideoPlayer::set_bus(const StringName &p_bus) {
+
+ //if audio is active, must lock this
+ AudioServer::get_singleton()->lock();
+ bus = p_bus;
+ AudioServer::get_singleton()->unlock();
+}
+
+StringName VideoPlayer::get_bus() const {
+
+ for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) {
+ if (AudioServer::get_singleton()->get_bus_name(i) == bus) {
+ return bus;
+ }
+ }
+ return "Master";
+}
+
+void VideoPlayer::_validate_property(PropertyInfo &property) const {
+
+ if (property.name == "bus") {
+
+ String options;
+ for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) {
+ if (i > 0)
+ options += ",";
+ String name = AudioServer::get_singleton()->get_bus_name(i);
+ options += name;
+ }
+
+ property.hint_string = options;
+ }
+}
+
void VideoPlayer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_stream", "stream"), &VideoPlayer::set_stream);
@@ -345,6 +466,9 @@ void VideoPlayer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_buffering_msec", "msec"), &VideoPlayer::set_buffering_msec);
ClassDB::bind_method(D_METHOD("get_buffering_msec"), &VideoPlayer::get_buffering_msec);
+ ClassDB::bind_method(D_METHOD("set_bus", "bus"), &VideoPlayer::set_bus);
+ ClassDB::bind_method(D_METHOD("get_bus"), &VideoPlayer::get_bus);
+
ClassDB::bind_method(D_METHOD("get_video_texture"), &VideoPlayer::get_video_texture);
ADD_PROPERTY(PropertyInfo(Variant::INT, "audio_track", PROPERTY_HINT_RANGE, "0,128,1"), "set_audio_track", "get_audio_track");
@@ -354,6 +478,7 @@ void VideoPlayer::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "autoplay"), "set_autoplay", "has_autoplay");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "paused"), "set_paused", "is_paused");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "expand"), "set_expand", "has_expand");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "bus", PROPERTY_HINT_ENUM, ""), "set_bus", "get_bus");
}
VideoPlayer::VideoPlayer() {
@@ -372,6 +497,9 @@ VideoPlayer::VideoPlayer() {
// internal_stream.player=this;
// stream_rid=AudioServer::get_singleton()->audio_stream_create(&internal_stream);
last_audio_time = 0;
+
+ wait_resampler = 0;
+ wait_resampler_limit = 2;
};
VideoPlayer::~VideoPlayer() {
diff --git a/scene/gui/video_player.h b/scene/gui/video_player.h
index f04e90365f..74e2f14e58 100644
--- a/scene/gui/video_player.h
+++ b/scene/gui/video_player.h
@@ -33,17 +33,24 @@
#include "scene/gui/control.h"
#include "scene/resources/video_stream.h"
#include "servers/audio/audio_rb_resampler.h"
+#include "servers/audio_server.h"
class VideoPlayer : public Control {
GDCLASS(VideoPlayer, Control);
+ struct Output {
+
+ AudioFrame vol;
+ int bus_index;
+ Viewport *viewport; //pointer only used for reference to previous mix
+ };
Ref<VideoStreamPlayback> playback;
Ref<VideoStream> stream;
int sp_get_channel_count() const;
void sp_set_mix_rate(int p_rate); //notify the stream of the mix rate
- bool sp_mix(int32_t *p_buffer, int p_frames);
+ bool mix(AudioFrame *p_buffer, int p_frames);
RID stream_rid;
@@ -51,6 +58,8 @@ class VideoPlayer : public Control {
Ref<Image> last_frame;
AudioRBResampler resampler;
+ Vector<AudioFrame> mix_buffer;
+ int wait_resampler, wait_resampler_limit;
bool paused;
bool autoplay;
@@ -61,12 +70,18 @@ class VideoPlayer : public Control {
int buffering_ms;
int server_mix_rate;
int audio_track;
+ int bus_index;
+
+ StringName bus;
- static int _audio_mix_callback(void *p_udata, const int16_t *p_data, int p_frames);
+ void _mix_audio();
+ static int _audio_mix_callback(void *p_udata, const float *p_data, int p_frames);
+ static void _mix_audios(void *self) { reinterpret_cast<VideoPlayer *>(self)->_mix_audio(); }
protected:
static void _bind_methods();
void _notification(int p_notification);
+ void _validate_property(PropertyInfo &property) const;
public:
Size2 get_minimum_size() const;
@@ -104,6 +119,9 @@ public:
void set_buffering_msec(int p_msec);
int get_buffering_msec() const;
+ void set_bus(const StringName &p_bus);
+ StringName get_bus() const;
+
VideoPlayer();
~VideoPlayer();
};
diff --git a/scene/gui/viewport_container.cpp b/scene/gui/viewport_container.cpp
index c321b873fd..9244d8de2f 100644
--- a/scene/gui/viewport_container.cpp
+++ b/scene/gui/viewport_container.cpp
@@ -62,6 +62,34 @@ bool ViewportContainer::is_stretch_enabled() const {
return stretch;
}
+void ViewportContainer::set_stretch_shrink(int p_shrink) {
+
+ ERR_FAIL_COND(p_shrink < 1);
+ if (shrink == p_shrink)
+ return;
+
+ shrink = p_shrink;
+
+ if (!stretch)
+ return;
+
+ for (int i = 0; i < get_child_count(); i++) {
+
+ Viewport *c = Object::cast_to<Viewport>(get_child(i));
+ if (!c)
+ continue;
+
+ c->set_size(get_size() / shrink);
+ }
+
+ update();
+}
+
+int ViewportContainer::get_stretch_shrink() const {
+
+ return shrink;
+}
+
void ViewportContainer::_notification(int p_what) {
if (p_what == NOTIFICATION_RESIZED) {
@@ -75,7 +103,7 @@ void ViewportContainer::_notification(int p_what) {
if (!c)
continue;
- c->set_size(get_size());
+ c->set_size(get_size() / shrink);
}
}
@@ -115,10 +143,15 @@ void ViewportContainer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_stretch", "enable"), &ViewportContainer::set_stretch);
ClassDB::bind_method(D_METHOD("is_stretch_enabled"), &ViewportContainer::is_stretch_enabled);
+ ClassDB::bind_method(D_METHOD("set_stretch_shrink", "amount"), &ViewportContainer::set_stretch_shrink);
+ ClassDB::bind_method(D_METHOD("get_stretch_shrink"), &ViewportContainer::get_stretch_shrink);
+
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "stretch"), "set_stretch", "is_stretch_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "stretch_shrink"), "set_stretch_shrink", "get_stretch_shrink");
}
ViewportContainer::ViewportContainer() {
stretch = false;
+ shrink = 1;
}
diff --git a/scene/gui/viewport_container.h b/scene/gui/viewport_container.h
index 630523b5fb..ebf5869ed9 100644
--- a/scene/gui/viewport_container.h
+++ b/scene/gui/viewport_container.h
@@ -37,6 +37,7 @@ class ViewportContainer : public Container {
GDCLASS(ViewportContainer, Container);
bool stretch;
+ int shrink;
protected:
void _notification(int p_what);
@@ -46,6 +47,9 @@ public:
void set_stretch(bool p_enable);
bool is_stretch_enabled() const;
+ void set_stretch_shrink(int p_shrink);
+ int get_stretch_shrink() const;
+
virtual Size2 get_minimum_size() const;
ViewportContainer();
diff --git a/scene/main/canvas_layer.cpp b/scene/main/canvas_layer.cpp
index ce8714e574..5a3814ef35 100644
--- a/scene/main/canvas_layer.cpp
+++ b/scene/main/canvas_layer.cpp
@@ -105,30 +105,16 @@ real_t CanvasLayer::get_rotation() const {
return rot;
}
-void CanvasLayer::set_rotationd(real_t p_degrees) {
+void CanvasLayer::set_rotation_degrees(real_t p_degrees) {
set_rotation(Math::deg2rad(p_degrees));
}
-real_t CanvasLayer::get_rotationd() const {
+real_t CanvasLayer::get_rotation_degrees() const {
return Math::rad2deg(get_rotation());
}
-// Kept for compatibility after rename to {s,g}et_rotationd.
-// Could be removed after a couple releases.
-void CanvasLayer::_set_rotationd(real_t p_degrees) {
-
- WARN_PRINT("Deprecated method CanvasLayer._set_rotationd(): This method was renamed to set_rotationd. Please adapt your code accordingly, as the old method will be obsoleted.");
- set_rotationd(p_degrees);
-}
-
-real_t CanvasLayer::_get_rotationd() const {
-
- WARN_PRINT("Deprecated method CanvasLayer._get_rotationd(): This method was renamed to get_rotationd. Please adapt your code accordingly, as the old method will be obsoleted.");
- return get_rotationd();
-}
-
void CanvasLayer::set_scale(const Vector2 &p_scale) {
if (locrotscale_dirty)
@@ -252,12 +238,8 @@ void CanvasLayer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_rotation", "radians"), &CanvasLayer::set_rotation);
ClassDB::bind_method(D_METHOD("get_rotation"), &CanvasLayer::get_rotation);
- ClassDB::bind_method(D_METHOD("set_rotationd", "degrees"), &CanvasLayer::set_rotationd);
- ClassDB::bind_method(D_METHOD("get_rotationd"), &CanvasLayer::get_rotationd);
-
- // TODO: Obsolete those two methods (old name) properly (GH-4397)
- ClassDB::bind_method(D_METHOD("_set_rotationd", "degrees"), &CanvasLayer::_set_rotationd);
- ClassDB::bind_method(D_METHOD("_get_rotationd"), &CanvasLayer::_get_rotationd);
+ ClassDB::bind_method(D_METHOD("set_rotation_degrees", "degrees"), &CanvasLayer::set_rotation_degrees);
+ ClassDB::bind_method(D_METHOD("get_rotation_degrees"), &CanvasLayer::get_rotation_degrees);
ClassDB::bind_method(D_METHOD("set_scale", "scale"), &CanvasLayer::set_scale);
ClassDB::bind_method(D_METHOD("get_scale"), &CanvasLayer::get_scale);
@@ -271,7 +253,7 @@ void CanvasLayer::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "layer", PROPERTY_HINT_RANGE, "-128,128,1"), "set_layer", "get_layer");
//ADD_PROPERTY( PropertyInfo(Variant::MATRIX32,"transform",PROPERTY_HINT_RANGE),"set_transform","get_transform") ;
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "offset"), "set_offset", "get_offset");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "rotation"), "set_rotationd", "get_rotationd");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "rotation"), "set_rotation_degrees", "get_rotation_degrees");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "scale"), "set_scale", "get_scale");
}
diff --git a/scene/main/canvas_layer.h b/scene/main/canvas_layer.h
index fbee87f487..db2c8e1273 100644
--- a/scene/main/canvas_layer.h
+++ b/scene/main/canvas_layer.h
@@ -54,10 +54,6 @@ class CanvasLayer : public Node {
int sort_index;
- // Deprecated, should be removed in a future version.
- void _set_rotationd(real_t p_degrees);
- real_t _get_rotationd() const;
-
void _update_xform();
void _update_locrotscale();
@@ -78,8 +74,8 @@ public:
void set_rotation(real_t p_radians);
real_t get_rotation() const;
- void set_rotationd(real_t p_degrees);
- real_t get_rotationd() const;
+ void set_rotation_degrees(real_t p_degrees);
+ real_t get_rotation_degrees() const;
void set_scale(const Size2 &p_scale);
Size2 get_scale() const;
diff --git a/scene/main/http_request.cpp b/scene/main/http_request.cpp
index 1e1e4f2d5f..672e893f1b 100644
--- a/scene/main/http_request.cpp
+++ b/scene/main/http_request.cpp
@@ -579,6 +579,7 @@ HTTPRequest::HTTPRequest() {
client.instance();
use_threads = false;
thread_done = false;
+ downloaded = 0;
body_size_limit = -1;
file = NULL;
status = HTTPClient::STATUS_DISCONNECTED;
diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index c2a31b4a8b..01e11962ff 100755
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -212,6 +212,8 @@ void Node::_propagate_enter_tree() {
emit_signal(SceneStringNames::get_singleton()->tree_entered);
+ data.tree->node_added(this);
+
data.blocked++;
//block while adding children
@@ -2065,7 +2067,7 @@ int Node::get_position_in_parent() const {
return data.pos;
}
-Node *Node::_duplicate(int p_flags) const {
+Node *Node::_duplicate(int p_flags, Map<const Node *, Node *> *r_duplimap) const {
Node *node = NULL;
@@ -2082,7 +2084,12 @@ Node *Node::_duplicate(int p_flags) const {
Ref<PackedScene> res = ResourceLoader::load(get_filename());
ERR_FAIL_COND_V(res.is_null(), NULL);
- node = res->instance();
+ PackedScene::GenEditState ges = PackedScene::GEN_EDIT_STATE_DISABLED;
+#ifdef TOOLS_ENABLED
+ if (p_flags & DUPLICATE_FROM_EDITOR)
+ ges = PackedScene::GEN_EDIT_STATE_INSTANCE;
+#endif
+ node = res->instance(ges);
ERR_FAIL_COND_V(!node, NULL);
instanced = true;
@@ -2097,10 +2104,6 @@ Node *Node::_duplicate(int p_flags) const {
ERR_FAIL_COND_V(!node, NULL);
}
- if (get_filename() != "") { //an instance
- node->set_filename(get_filename());
- }
-
List<PropertyInfo> plist;
get_property_list(&plist);
@@ -2136,18 +2139,25 @@ Node *Node::_duplicate(int p_flags) const {
node->set_name(get_name());
+#ifdef TOOLS_ENABLED
+ if ((p_flags & DUPLICATE_FROM_EDITOR) && r_duplimap)
+ r_duplimap->insert(this, node);
+#endif
+
if (p_flags & DUPLICATE_GROUPS) {
List<GroupInfo> gi;
get_groups(&gi);
for (List<GroupInfo>::Element *E = gi.front(); E; E = E->next()) {
+#ifdef TOOLS_ENABLED
+ if ((p_flags & DUPLICATE_FROM_EDITOR) && !E->get().persistent)
+ continue;
+#endif
+
node->add_to_group(E->get().name, E->get().persistent);
}
}
- if (p_flags & DUPLICATE_SIGNALS)
- _duplicate_signals(this, node);
-
for (int i = 0; i < get_child_count(); i++) {
if (get_child(i)->data.parent_owned)
@@ -2155,7 +2165,7 @@ Node *Node::_duplicate(int p_flags) const {
if (instanced && get_child(i)->data.owner == this)
continue; //part of instance
- Node *dup = get_child(i)->duplicate(p_flags);
+ Node *dup = get_child(i)->_duplicate(p_flags, r_duplimap);
if (!dup) {
memdelete(node);
@@ -2179,6 +2189,20 @@ Node *Node::duplicate(int p_flags) const {
return dupe;
}
+#ifdef TOOLS_ENABLED
+Node *Node::duplicate_from_editor(Map<const Node *, Node *> &r_duplimap) const {
+
+ Node *dupe = _duplicate(DUPLICATE_SIGNALS | DUPLICATE_GROUPS | DUPLICATE_SCRIPTS | DUPLICATE_USE_INSTANCING | DUPLICATE_FROM_EDITOR, &r_duplimap);
+
+ // Duplication of signals must happen after all the node descendants have been copied,
+ // because re-targeting of connections from some descendant to another is not possible
+ // if the emitter node comes later in tree order than the receiver
+ _duplicate_signals(this, dupe);
+
+ return dupe;
+}
+#endif
+
void Node::_duplicate_and_reown(Node *p_new_parent, const Map<Node *, Node *> &p_reown_map) const {
if (get_owner() != get_parent()->get_owner())
@@ -2249,6 +2273,9 @@ void Node::_duplicate_and_reown(Node *p_new_parent, const Map<Node *, Node *> &p
}
}
+// Duplication of signals must happen after all the node descendants have been copied,
+// because re-targeting of connections from some descendant to another is not possible
+// if the emitter node comes later in tree order than the receiver
void Node::_duplicate_signals(const Node *p_original, Node *p_copy) const {
if (this != p_original && (get_owner() != p_original && get_owner() != p_original->get_owner()))
@@ -2271,8 +2298,14 @@ void Node::_duplicate_signals(const Node *p_original, Node *p_copy) const {
NodePath ptarget = p_original->get_path_to(target);
Node *copytarget = p_copy->get_node(ptarget);
+ // Cannot find a path to the duplicate target, so it seems it's not part
+ // of the duplicated and not yet parented hierarchy, so at least try to connect
+ // to the same target as the original
+ if (!copytarget)
+ copytarget = target;
+
if (copy && copytarget) {
- copy->connect(E->get().signal, copytarget, E->get().method, E->get().binds, CONNECT_PERSIST);
+ copy->connect(E->get().signal, copytarget, E->get().method, E->get().binds, E->get().flags);
}
}
}
@@ -2317,6 +2350,9 @@ Node *Node::duplicate_and_reown(const Map<Node *, Node *> &p_reown_map) const {
get_child(i)->_duplicate_and_reown(node, p_reown_map);
}
+ // Duplication of signals must happen after all the node descendants have been copied,
+ // because re-targeting of connections from some descendant to another is not possible
+ // if the emitter node comes later in tree order than the receiver
_duplicate_signals(this, node);
return node;
}
@@ -2420,7 +2456,9 @@ void Node::_replace_connections_target(Node *p_new_target) {
if (c.flags & CONNECT_PERSIST) {
c.source->disconnect(c.signal, this, c.method);
- ERR_CONTINUE(!p_new_target->has_method(c.method));
+ bool valid = p_new_target->has_method(c.method) || p_new_target->get_script().is_null() || Ref<Script>(p_new_target->get_script())->has_method(c.method);
+ ERR_EXPLAIN("Attempt to connect signal \'" + c.source->get_class() + "." + c.signal + "\' to nonexistent method \'" + c.target->get_class() + "." + c.method + "\'");
+ ERR_CONTINUE(!valid);
c.source->connect(c.signal, p_new_target, c.method, c.binds, c.flags);
}
}
@@ -2801,12 +2839,12 @@ void Node::_bind_methods() {
BIND_CONSTANT(NOTIFICATION_EXIT_TREE);
BIND_CONSTANT(NOTIFICATION_MOVED_IN_PARENT);
BIND_CONSTANT(NOTIFICATION_READY);
+ BIND_CONSTANT(NOTIFICATION_PAUSED);
+ BIND_CONSTANT(NOTIFICATION_UNPAUSED);
BIND_CONSTANT(NOTIFICATION_PHYSICS_PROCESS);
BIND_CONSTANT(NOTIFICATION_PROCESS);
BIND_CONSTANT(NOTIFICATION_PARENTED);
BIND_CONSTANT(NOTIFICATION_UNPARENTED);
- BIND_CONSTANT(NOTIFICATION_PAUSED);
- BIND_CONSTANT(NOTIFICATION_UNPAUSED);
BIND_CONSTANT(NOTIFICATION_INSTANCED);
BIND_CONSTANT(NOTIFICATION_DRAG_BEGIN);
BIND_CONSTANT(NOTIFICATION_DRAG_END);
diff --git a/scene/main/node.h b/scene/main/node.h
index c43e96063f..bd0b18c87a 100644
--- a/scene/main/node.h
+++ b/scene/main/node.h
@@ -58,7 +58,10 @@ public:
DUPLICATE_SIGNALS = 1,
DUPLICATE_GROUPS = 2,
DUPLICATE_SCRIPTS = 4,
- DUPLICATE_USE_INSTANCING = 8
+ DUPLICATE_USE_INSTANCING = 8,
+#ifdef TOOLS_ENABLED
+ DUPLICATE_FROM_EDITOR = 16,
+#endif
};
enum RPCMode {
@@ -169,7 +172,7 @@ private:
void _duplicate_signals(const Node *p_original, Node *p_copy) const;
void _duplicate_and_reown(Node *p_new_parent, const Map<Node *, Node *> &p_reown_map) const;
- Node *_duplicate(int p_flags) const;
+ Node *_duplicate(int p_flags, Map<const Node *, Node *> *r_duplimap = NULL) const;
Array _get_children() const;
Array _get_groups() const;
@@ -326,6 +329,9 @@ public:
Node *duplicate(int p_flags = DUPLICATE_GROUPS | DUPLICATE_SIGNALS | DUPLICATE_SCRIPTS) const;
Node *duplicate_and_reown(const Map<Node *, Node *> &p_reown_map) const;
+#ifdef TOOLS_ENABLED
+ Node *duplicate_from_editor(Map<const Node *, Node *> &r_duplimap) const;
+#endif
//Node *clone_tree() const;
diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp
index 7a28e2a6f8..d4be683a2b 100644
--- a/scene/main/scene_tree.cpp
+++ b/scene/main/scene_tree.cpp
@@ -85,6 +85,11 @@ void SceneTree::tree_changed() {
emit_signal(tree_changed_name);
}
+void SceneTree::node_added(Node *p_node) {
+
+ emit_signal(node_added_name, p_node);
+}
+
void SceneTree::node_removed(Node *p_node) {
if (current_scene == p_node) {
@@ -1172,7 +1177,7 @@ void SceneTree::_update_root_rect() {
}
}
-void SceneTree::set_screen_stretch(StretchMode p_mode, StretchAspect p_aspect, const Size2 p_minsize, int p_shrink) {
+void SceneTree::set_screen_stretch(StretchMode p_mode, StretchAspect p_aspect, const Size2 p_minsize, real_t p_shrink) {
stretch_mode = p_mode;
stretch_aspect = p_aspect;
@@ -2189,6 +2194,7 @@ void SceneTree::_bind_methods() {
ClassDB::bind_method(D_METHOD("_server_disconnected"), &SceneTree::_server_disconnected);
ADD_SIGNAL(MethodInfo("tree_changed"));
+ ADD_SIGNAL(MethodInfo("node_added", PropertyInfo(Variant::OBJECT, "node")));
ADD_SIGNAL(MethodInfo("node_removed", PropertyInfo(Variant::OBJECT, "node")));
ADD_SIGNAL(MethodInfo("screen_resized"));
ADD_SIGNAL(MethodInfo("node_configuration_warning_changed", PropertyInfo(Variant::OBJECT, "node")));
@@ -2260,6 +2266,7 @@ SceneTree::SceneTree() {
root = NULL;
current_frame = 0;
tree_changed_name = "tree_changed";
+ node_added_name = "node_added";
node_removed_name = "node_removed";
ugc_locked = false;
call_lock = 0;
diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h
index f3e689adab..bc3efdc42f 100644
--- a/scene/main/scene_tree.h
+++ b/scene/main/scene_tree.h
@@ -124,6 +124,7 @@ private:
bool input_handled;
Size2 last_screen_size;
StringName tree_changed_name;
+ StringName node_added_name;
StringName node_removed_name;
int64_t current_frame;
@@ -147,7 +148,7 @@ private:
StretchMode stretch_mode;
StretchAspect stretch_aspect;
Size2i stretch_min;
- int stretch_shrink;
+ real_t stretch_shrink;
void _update_root_rect();
@@ -233,6 +234,7 @@ private:
void _rpc(Node *p_from, int p_to, bool p_unreliable, bool p_set, const StringName &p_name, const Variant **p_arg, int p_argcount);
void tree_changed();
+ void node_added(Node *p_node);
void node_removed(Node *p_node);
Group *add_to_group(const StringName &p_group, Node *p_node);
@@ -415,7 +417,7 @@ public:
void get_nodes_in_group(const StringName &p_group, List<Node *> *p_list);
bool has_group(const StringName &p_identifier) const;
- void set_screen_stretch(StretchMode p_mode, StretchAspect p_aspect, const Size2 p_minsize, int p_shrink = 1);
+ void set_screen_stretch(StretchMode p_mode, StretchAspect p_aspect, const Size2 p_minsize, real_t p_shrink = 1);
//void change_scene(const String& p_path);
//Node *get_loaded_scene();
diff --git a/scene/main/timer.cpp b/scene/main/timer.cpp
index 23854b5f59..e0c6f93f25 100755
--- a/scene/main/timer.cpp
+++ b/scene/main/timer.cpp
@@ -199,7 +199,7 @@ void Timer::_bind_methods() {
ADD_SIGNAL(MethodInfo("timeout"));
- ADD_PROPERTY(PropertyInfo(Variant::INT, "process_mode", PROPERTY_HINT_ENUM, "Fixed,Idle"), "set_timer_process_mode", "get_timer_process_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "process_mode", PROPERTY_HINT_ENUM, "Physics,Idle"), "set_timer_process_mode", "get_timer_process_mode");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "wait_time", PROPERTY_HINT_EXP_RANGE, "0.01,4096,0.01"), "set_wait_time", "get_wait_time");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "one_shot"), "set_one_shot", "is_one_shot");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "autostart"), "set_autostart", "has_autostart");
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index 37a393b55b..1f539041fd 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -2013,6 +2013,30 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
}
}
+ Ref<InputEventGesture> gesture_event = p_event;
+ if (gesture_event.is_valid()) {
+
+ Size2 pos = gesture_event->get_position();
+
+ Control *over = _gui_find_control(pos);
+ if (over) {
+
+ if (over->can_process()) {
+
+ gesture_event = gesture_event->xformed_by(Transform2D()); //make a copy
+ if (over == gui.mouse_focus) {
+ pos = gui.focus_inv_xform.xform(pos);
+ } else {
+ pos = over->get_global_transform_with_canvas().affine_inverse().xform(pos);
+ }
+ gesture_event->set_position(pos);
+ _gui_call_input(over, gesture_event);
+ }
+ get_tree()->set_input_as_handled();
+ return;
+ }
+ }
+
Ref<InputEventScreenDrag> drag_event = p_event;
if (drag_event.is_valid()) {
@@ -2371,8 +2395,13 @@ void Viewport::input(const Ref<InputEvent> &p_event) {
ERR_FAIL_COND(!is_inside_tree());
- get_tree()->_call_input_pause(input_group, "_input", p_event); //not a bug, must happen before GUI, order is _input -> gui input -> _unhandled input
- _gui_input_event(p_event);
+ if (!get_tree()->is_input_handled()) {
+ get_tree()->_call_input_pause(input_group, "_input", p_event); //not a bug, must happen before GUI, order is _input -> gui input -> _unhandled input
+ }
+
+ if (!get_tree()->is_input_handled()) {
+ _gui_input_event(p_event);
+ }
//get_tree()->call_group(SceneTree::GROUP_CALL_REVERSE|SceneTree::GROUP_CALL_REALTIME|SceneTree::GROUP_CALL_MULIILEVEL,gui_input_group,"_gui_input",p_event); //special one for GUI, as controls use their own process check
}
@@ -2711,7 +2740,7 @@ void Viewport::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "debug_draw", PROPERTY_HINT_ENUM, "Disabled,Unshaded,Overdraw,Wireframe"), "set_debug_draw", "get_debug_draw");
ADD_GROUP("Render Target", "render_target_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "render_target_v_flip"), "set_vflip", "get_vflip");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "render_target_clear_mode", PROPERTY_HINT_ENUM, "Always,Never,NextFrame"), "set_clear_mode", "get_clear_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "render_target_clear_mode", PROPERTY_HINT_ENUM, "Always,Never,Next Frame"), "set_clear_mode", "get_clear_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "render_target_update_mode", PROPERTY_HINT_ENUM, "Disabled,Once,When Visible,Always"), "set_update_mode", "get_update_mode");
ADD_GROUP("Audio Listener", "audio_listener_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "audio_listener_enable_2d"), "set_as_audio_listener_2d", "is_audio_listener_2d");
diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp
index a85a0fb9f7..c99bc3c9ef 100644
--- a/scene/register_scene_types.cpp
+++ b/scene/register_scene_types.cpp
@@ -83,10 +83,10 @@
#include "scene/gui/link_button.h"
#include "scene/gui/margin_container.h"
#include "scene/gui/menu_button.h"
+#include "scene/gui/nine_patch_rect.h"
#include "scene/gui/option_button.h"
#include "scene/gui/panel.h"
#include "scene/gui/panel_container.h"
-#include "scene/gui/patch_9_rect.h"
#include "scene/gui/popup_menu.h"
#include "scene/gui/progress_bar.h"
#include "scene/gui/reference_rect.h"
@@ -152,6 +152,10 @@
#include "scene/resources/world_2d.h"
#include "scene/scene_string_names.h"
+#include "scene/3d/particles.h"
+#include "scene/3d/scenario_fx.h"
+#include "scene/3d/spatial.h"
+
#ifndef _3D_DISABLED
#include "scene/3d/area.h"
#include "scene/3d/arvr_nodes.h"
@@ -169,7 +173,6 @@
#include "scene/3d/multimesh_instance.h"
#include "scene/3d/navigation.h"
#include "scene/3d/navigation_mesh.h"
-#include "scene/3d/particles.h"
#include "scene/3d/path.h"
#include "scene/3d/physics_body.h"
#include "scene/3d/physics_joint.h"
@@ -180,9 +183,7 @@
#include "scene/3d/reflection_probe.h"
#include "scene/3d/remote_transform.h"
#include "scene/3d/room_instance.h"
-#include "scene/3d/scenario_fx.h"
#include "scene/3d/skeleton.h"
-#include "scene/3d/spatial.h"
#include "scene/3d/sprite_3d.h"
#include "scene/3d/vehicle_body.h"
#include "scene/3d/visibility_notifier.h"
@@ -266,9 +267,11 @@ void register_scene_types() {
ClassDB::register_class<Control>();
ClassDB::register_class<Button>();
ClassDB::register_class<Label>();
+ ClassDB::register_class<ScrollBar>();
ClassDB::register_class<HScrollBar>();
ClassDB::register_class<VScrollBar>();
ClassDB::register_class<ProgressBar>();
+ ClassDB::register_class<Slider>();
ClassDB::register_class<HSlider>();
ClassDB::register_class<VSlider>();
ClassDB::register_class<Popup>();
@@ -352,6 +355,7 @@ void register_scene_types() {
#ifndef _3D_DISABLED
ClassDB::register_class<BoneAttachment>();
ClassDB::register_virtual_class<VisualInstance>();
+ ClassDB::register_virtual_class<GeometryInstance>();
ClassDB::register_class<Camera>();
ClassDB::register_class<Listener>();
ClassDB::register_class<ARVRCamera>();
@@ -361,6 +365,7 @@ void register_scene_types() {
ClassDB::register_class<InterpolatedCamera>();
ClassDB::register_class<MeshInstance>();
ClassDB::register_class<ImmediateGeometry>();
+ ClassDB::register_virtual_class<SpriteBase3D>();
ClassDB::register_class<Sprite3D>();
ClassDB::register_class<AnimatedSprite3D>();
ClassDB::register_virtual_class<Light>();
@@ -380,6 +385,7 @@ void register_scene_types() {
OS::get_singleton()->yield(); //may take time to init
ClassDB::register_virtual_class<CollisionObject>();
+ ClassDB::register_virtual_class<PhysicsBody>();
ClassDB::register_class<StaticBody>();
ClassDB::register_class<RigidBody>();
ClassDB::register_class<KinematicCollision>();
@@ -494,6 +500,7 @@ void register_scene_types() {
OS::get_singleton()->yield(); //may take time to init
+ ClassDB::register_virtual_class<Shape>();
ClassDB::register_class<RayShape>();
ClassDB::register_class<SphereShape>();
ClassDB::register_class<BoxShape>();
@@ -531,9 +538,11 @@ void register_scene_types() {
ClassDB::register_class<DynamicFontData>();
ClassDB::register_class<DynamicFont>();
+ ClassDB::register_virtual_class<StyleBox>();
ClassDB::register_class<StyleBoxEmpty>();
ClassDB::register_class<StyleBoxTexture>();
ClassDB::register_class<StyleBoxFlat>();
+ ClassDB::register_class<StyleBoxLine>();
ClassDB::register_class<Theme>();
ClassDB::register_class<PolygonPathFinder>();
@@ -544,7 +553,9 @@ void register_scene_types() {
ClassDB::register_class<AudioStreamPlayer>();
ClassDB::register_class<AudioStreamPlayer2D>();
+#ifndef _3D_DISABLED
ClassDB::register_class<AudioStreamPlayer3D>();
+#endif
ClassDB::register_virtual_class<VideoStream>();
ClassDB::register_class<AudioStreamSample>();
diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp
index 8dcc8d4e14..8192074c17 100644
--- a/scene/resources/animation.cpp
+++ b/scene/resources/animation.cpp
@@ -1125,14 +1125,14 @@ Variant Animation::_cubic_interpolate(const Variant &p_pre_a, const Variant &p_a
return a.cubic_slerp(b, pa, pb, p_c);
} break;
- case Variant::RECT3: {
+ case Variant::AABB: {
- Rect3 a = p_a;
- Rect3 b = p_b;
- Rect3 pa = p_pre_a;
- Rect3 pb = p_post_b;
+ AABB a = p_a;
+ AABB b = p_b;
+ AABB pa = p_pre_a;
+ AABB pb = p_post_b;
- return Rect3(
+ return AABB(
a.position.cubic_interpolate(b.position, pa.position, pb.position, p_c),
a.size.cubic_interpolate(b.size, pa.size, pb.size, p_c));
} break;
@@ -1171,9 +1171,7 @@ T Animation::_interpolate(const Vector<TKey<T> > &p_keys, float p_time, Interpol
ERR_FAIL_COND_V(idx == -2, T());
- if (p_ok)
- *p_ok = true;
-
+ bool result = true;
int next = 0;
float c = 0;
// prepare for all cases of interpolation
@@ -1243,10 +1241,19 @@ T Animation::_interpolate(const Vector<TKey<T> > &p_keys, float p_time, Interpol
} else if (idx < 0) {
- idx = next = 0;
+ // only allow extending first key to anim start if looping
+ if (loop)
+ idx = next = 0;
+ else
+ result = false;
}
}
+ if (p_ok)
+ *p_ok = result;
+ if (!result)
+ return T();
+
float tr = p_keys[idx].transition;
if (tr == 0 || idx == next) {
@@ -1298,7 +1305,7 @@ Error Animation::transform_track_interpolate(int p_track, float p_time, Vector3
TransformKey tk = _interpolate(tt->transforms, p_time, tt->interpolation, tt->loop_wrap, &ok);
- if (!ok) // ??
+ if (!ok)
return ERR_UNAVAILABLE;
if (r_loc)
diff --git a/scene/resources/audio_stream_sample.cpp b/scene/resources/audio_stream_sample.cpp
index 1fd84a860e..f81f460521 100644
--- a/scene/resources/audio_stream_sample.cpp
+++ b/scene/resources/audio_stream_sample.cpp
@@ -31,17 +31,23 @@
void AudioStreamPlaybackSample::start(float p_from_pos) {
- for (int i = 0; i < 2; i++) {
- ima_adpcm[i].step_index = 0;
- ima_adpcm[i].predictor = 0;
- ima_adpcm[i].loop_step_index = 0;
- ima_adpcm[i].loop_predictor = 0;
- ima_adpcm[i].last_nibble = -1;
- ima_adpcm[i].loop_pos = 0x7FFFFFFF;
- ima_adpcm[i].window_ofs = 0;
+ if (base->format == AudioStreamSample::FORMAT_IMA_ADPCM) {
+ //no seeking in IMA_ADPCM
+ for (int i = 0; i < 2; i++) {
+ ima_adpcm[i].step_index = 0;
+ ima_adpcm[i].predictor = 0;
+ ima_adpcm[i].loop_step_index = 0;
+ ima_adpcm[i].loop_predictor = 0;
+ ima_adpcm[i].last_nibble = -1;
+ ima_adpcm[i].loop_pos = 0x7FFFFFFF;
+ ima_adpcm[i].window_ofs = 0;
+ }
+
+ offset = 0;
+ } else {
+ seek(p_from_pos);
}
- seek(p_from_pos);
sign = 1;
active = true;
}
@@ -373,6 +379,14 @@ void AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, in
dst_buff += target;
}
+
+ if (todo) {
+ //bit was missing from mix
+ int todo_ofs = p_frames - todo;
+ for (int i = todo_ofs; i < p_frames; i++) {
+ p_buffer[i] = AudioFrame(0, 0);
+ }
+ }
}
float AudioStreamPlaybackSample::get_length() const {
@@ -486,7 +500,8 @@ PoolVector<uint8_t> AudioStreamSample::get_data() const {
{
PoolVector<uint8_t>::Write w = pv.write();
- copymem(w.ptr(), data, data_bytes);
+ uint8_t *dataptr = (uint8_t *)data;
+ copymem(w.ptr(), dataptr + DATA_PAD, data_bytes);
}
}
diff --git a/scene/resources/box_shape.cpp b/scene/resources/box_shape.cpp
index bbc85ce0f6..4b9843f3f5 100644
--- a/scene/resources/box_shape.cpp
+++ b/scene/resources/box_shape.cpp
@@ -33,7 +33,7 @@
Vector<Vector3> BoxShape::_gen_debug_mesh_lines() {
Vector<Vector3> lines;
- Rect3 aabb;
+ AABB aabb;
aabb.position = -get_extents();
aabb.size = aabb.position * -2;
diff --git a/scene/resources/capsule_shape_2d.cpp b/scene/resources/capsule_shape_2d.cpp
index 56a09bc3bf..912150b939 100644
--- a/scene/resources/capsule_shape_2d.cpp
+++ b/scene/resources/capsule_shape_2d.cpp
@@ -98,7 +98,7 @@ void CapsuleShape2D::_bind_methods() {
}
CapsuleShape2D::CapsuleShape2D()
- : Shape2D(Physics2DServer::get_singleton()->shape_create(Physics2DServer::SHAPE_CAPSULE)) {
+ : Shape2D(Physics2DServer::get_singleton()->capsule_shape_create()) {
radius = 10;
height = 20;
diff --git a/scene/resources/circle_shape_2d.cpp b/scene/resources/circle_shape_2d.cpp
index ecfc98ea60..287bde4bfb 100644
--- a/scene/resources/circle_shape_2d.cpp
+++ b/scene/resources/circle_shape_2d.cpp
@@ -77,7 +77,7 @@ void CircleShape2D::draw(const RID &p_to_rid, const Color &p_color) {
}
CircleShape2D::CircleShape2D()
- : Shape2D(Physics2DServer::get_singleton()->shape_create(Physics2DServer::SHAPE_CIRCLE)) {
+ : Shape2D(Physics2DServer::get_singleton()->circle_shape_create()) {
radius = 10;
_update_shape();
diff --git a/scene/resources/concave_polygon_shape_2d.cpp b/scene/resources/concave_polygon_shape_2d.cpp
index 7f4abf7ae0..bb91e33ec2 100644
--- a/scene/resources/concave_polygon_shape_2d.cpp
+++ b/scene/resources/concave_polygon_shape_2d.cpp
@@ -85,5 +85,5 @@ void ConcavePolygonShape2D::_bind_methods() {
}
ConcavePolygonShape2D::ConcavePolygonShape2D()
- : Shape2D(Physics2DServer::get_singleton()->shape_create(Physics2DServer::SHAPE_CONCAVE_POLYGON)) {
+ : Shape2D(Physics2DServer::get_singleton()->concave_polygon_shape_create()) {
}
diff --git a/scene/resources/convex_polygon_shape_2d.cpp b/scene/resources/convex_polygon_shape_2d.cpp
index 7588909d90..a76b6a7cf4 100644
--- a/scene/resources/convex_polygon_shape_2d.cpp
+++ b/scene/resources/convex_polygon_shape_2d.cpp
@@ -87,7 +87,7 @@ Rect2 ConvexPolygonShape2D::get_rect() const {
}
ConvexPolygonShape2D::ConvexPolygonShape2D()
- : Shape2D(Physics2DServer::get_singleton()->shape_create(Physics2DServer::SHAPE_CONVEX_POLYGON)) {
+ : Shape2D(Physics2DServer::get_singleton()->convex_polygon_shape_create()) {
int pcount = 3;
for (int i = 0; i < pcount; i++)
diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp
index 923639bc79..cd28c9d203 100644
--- a/scene/resources/default_theme/default_theme.cpp
+++ b/scene/resources/default_theme/default_theme.cpp
@@ -512,6 +512,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
// HSlider
theme->set_stylebox("slider", "HSlider", make_stylebox(hslider_bg_png, 4, 4, 4, 4));
+ theme->set_stylebox("grabber_area", "HSlider", make_stylebox(hslider_bg_png, 4, 4, 4, 4));
theme->set_stylebox("grabber_highlight", "HSlider", make_stylebox(hslider_grabber_hl_png, 6, 6, 6, 6));
theme->set_stylebox("grabber_disabled", "HSlider", make_stylebox(hslider_grabber_disabled_png, 6, 6, 6, 6));
theme->set_stylebox("focus", "HSlider", focus);
@@ -524,6 +525,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
// VSlider
theme->set_stylebox("slider", "VSlider", make_stylebox(vslider_bg_png, 4, 4, 4, 4));
+ theme->set_stylebox("grabber_area", "VSlider", make_stylebox(vslider_bg_png, 4, 4, 4, 4));
theme->set_stylebox("grabber_highlight", "VSlider", make_stylebox(vslider_grabber_hl_png, 6, 6, 6, 6));
theme->set_stylebox("grabber_disabled", "VSlider", make_stylebox(vslider_grabber_disabled_png, 6, 6, 6, 6));
theme->set_stylebox("focus", "VSlider", focus);
@@ -834,39 +836,6 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_constant("autohide", "HSplitContainer", 1 * scale);
theme->set_constant("autohide", "VSplitContainer", 1 * scale);
- // HButtonArray
- theme->set_stylebox("normal", "HButtonArray", sb_button_normal);
- theme->set_stylebox("selected", "HButtonArray", sb_button_pressed);
- theme->set_stylebox("hover", "HButtonArray", sb_button_hover);
-
- theme->set_font("font", "HButtonArray", default_font);
- theme->set_font("font_selected", "HButtonArray", default_font);
-
- theme->set_color("font_color", "HButtonArray", control_font_color_low);
- theme->set_color("font_color_selected", "HButtonArray", control_font_color_hover);
-
- theme->set_constant("icon_separator", "HButtonArray", 2 * scale);
- theme->set_constant("button_separator", "HButtonArray", 4 * scale);
-
- theme->set_stylebox("focus", "HButtonArray", focus);
-
- // VButtonArray
-
- theme->set_stylebox("normal", "VButtonArray", sb_button_normal);
- theme->set_stylebox("selected", "VButtonArray", sb_button_pressed);
- theme->set_stylebox("hover", "VButtonArray", sb_button_hover);
-
- theme->set_font("font", "VButtonArray", default_font);
- theme->set_font("font_selected", "VButtonArray", default_font);
-
- theme->set_color("font_color", "VButtonArray", control_font_color_low);
- theme->set_color("font_color_selected", "VButtonArray", control_font_color_hover);
-
- theme->set_constant("icon_separator", "VButtonArray", 2 * scale);
- theme->set_constant("button_separator", "VButtonArray", 4 * scale);
-
- theme->set_stylebox("focus", "VButtonArray", focus);
-
// ReferenceRect
Ref<StyleBoxTexture> ttnc = make_stylebox(full_panel_bg_png, 8, 8, 8, 8);
@@ -882,7 +851,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_icon("minus", "GraphEdit", make_icon(icon_zoom_less_png));
theme->set_icon("reset", "GraphEdit", make_icon(icon_zoom_reset_png));
theme->set_icon("more", "GraphEdit", make_icon(icon_zoom_more_png));
- theme->set_icon("SnapGrid", "GraphEdit", make_icon(icon_snap_grid_png));
+ theme->set_icon("snap", "GraphEdit", make_icon(icon_snap_grid_png));
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));
diff --git a/scene/resources/dynamic_font.cpp b/scene/resources/dynamic_font.cpp
index 1ee76a4216..48c6add586 100644
--- a/scene/resources/dynamic_font.cpp
+++ b/scene/resources/dynamic_font.cpp
@@ -571,7 +571,7 @@ void DynamicFontAtSize::_update_char(CharType p_char) {
wr[ofs + 0] = 255; //grayscale as 1
wr[ofs + 1] = slot->bitmap.buffer[i * slot->bitmap.pitch + j];
break;
- // TODO: FT_PIXEL_MODE_LCD, FT_PIXEL_MODE_BGRA
+ // TODO: FT_PIXEL_MODE_LCD, FT_PIXEL_MODE_BGRA
default:
ERR_EXPLAIN("Font uses unsupported pixel format: " + itos(slot->bitmap.pixel_mode));
ERR_FAIL();
diff --git a/scene/resources/dynamic_font_stb.cpp b/scene/resources/dynamic_font_stb.cpp
index 91263fb125..4aa47cb664 100644
--- a/scene/resources/dynamic_font_stb.cpp
+++ b/scene/resources/dynamic_font_stb.cpp
@@ -333,8 +333,7 @@ void DynamicFontAtSize::_update_char(CharType p_char) {
//blit to image and texture
{
-
- Image img(tex.texture_size, tex.texture_size, 0, Image::FORMAT_LA8, tex.imgdata);
+ Ref<Image> img = memnew(Image(tex.texture_size, tex.texture_size, 0, Image::FORMAT_LA8, tex.imgdata));
if (tex.texture.is_null()) {
tex.texture.instance();
@@ -518,7 +517,7 @@ bool ResourceFormatLoaderDynamicFont::handles_type(const String &p_type) const {
String ResourceFormatLoaderDynamicFont::get_resource_type(const String &p_path) const {
- String el = p_path.extension().to_lower();
+ String el = p_path.get_extension().to_lower();
if (el == "ttf")
return "DynamicFontData";
return "";
diff --git a/scene/resources/environment.cpp b/scene/resources/environment.cpp
index 4c6fa7c8a1..fe59450f2e 100644
--- a/scene/resources/environment.cpp
+++ b/scene/resources/environment.cpp
@@ -377,7 +377,7 @@ bool Environment::is_ssr_rough() const {
void Environment::set_ssao_enabled(bool p_enable) {
ssao_enabled = p_enable;
- VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_color, ssao_blur);
+ VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_color, VS::EnvironmentSSAOQuality(ssao_quality), VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness);
_change_notify();
}
@@ -389,7 +389,7 @@ bool Environment::is_ssao_enabled() const {
void Environment::set_ssao_radius(float p_radius) {
ssao_radius = p_radius;
- VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_color, ssao_blur);
+ VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_color, VS::EnvironmentSSAOQuality(ssao_quality), VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness);
}
float Environment::get_ssao_radius() const {
@@ -399,7 +399,7 @@ float Environment::get_ssao_radius() const {
void Environment::set_ssao_intensity(float p_intensity) {
ssao_intensity = p_intensity;
- VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_color, ssao_blur);
+ VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_color, VS::EnvironmentSSAOQuality(ssao_quality), VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness);
}
float Environment::get_ssao_intensity() const {
@@ -410,7 +410,7 @@ float Environment::get_ssao_intensity() const {
void Environment::set_ssao_radius2(float p_radius) {
ssao_radius2 = p_radius;
- VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_color, ssao_blur);
+ VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_color, VS::EnvironmentSSAOQuality(ssao_quality), VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness);
}
float Environment::get_ssao_radius2() const {
@@ -420,7 +420,7 @@ float Environment::get_ssao_radius2() const {
void Environment::set_ssao_intensity2(float p_intensity) {
ssao_intensity2 = p_intensity;
- VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_color, ssao_blur);
+ VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_color, VS::EnvironmentSSAOQuality(ssao_quality), VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness);
}
float Environment::get_ssao_intensity2() const {
@@ -430,7 +430,7 @@ float Environment::get_ssao_intensity2() const {
void Environment::set_ssao_bias(float p_bias) {
ssao_bias = p_bias;
- VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_color, ssao_blur);
+ VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_color, VS::EnvironmentSSAOQuality(ssao_quality), VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness);
}
float Environment::get_ssao_bias() const {
@@ -440,7 +440,7 @@ float Environment::get_ssao_bias() const {
void Environment::set_ssao_direct_light_affect(float p_direct_light_affect) {
ssao_direct_light_affect = p_direct_light_affect;
- VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_color, ssao_blur);
+ VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_color, VS::EnvironmentSSAOQuality(ssao_quality), VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness);
}
float Environment::get_ssao_direct_light_affect() const {
@@ -450,7 +450,7 @@ float Environment::get_ssao_direct_light_affect() const {
void Environment::set_ssao_color(const Color &p_color) {
ssao_color = p_color;
- VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_color, ssao_blur);
+ VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_color, VS::EnvironmentSSAOQuality(ssao_quality), VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness);
}
Color Environment::get_ssao_color() const {
@@ -458,16 +458,38 @@ Color Environment::get_ssao_color() const {
return ssao_color;
}
-void Environment::set_ssao_blur(bool p_enable) {
+void Environment::set_ssao_blur(SSAOBlur p_blur) {
- ssao_blur = p_enable;
- VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_color, ssao_blur);
+ ssao_blur = p_blur;
+ VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_color, VS::EnvironmentSSAOQuality(ssao_quality), VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness);
}
-bool Environment::is_ssao_blur_enabled() const {
+Environment::SSAOBlur Environment::get_ssao_blur() const {
return ssao_blur;
}
+void Environment::set_ssao_quality(SSAOQuality p_quality) {
+
+ ssao_quality = p_quality;
+ VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_color, VS::EnvironmentSSAOQuality(ssao_quality), VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness);
+}
+
+Environment::SSAOQuality Environment::get_ssao_quality() const {
+
+ return ssao_quality;
+}
+
+void Environment::set_ssao_edge_sharpness(float p_edge_sharpness) {
+
+ ssao_edge_sharpness = p_edge_sharpness;
+ VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_color, VS::EnvironmentSSAOQuality(ssao_quality), VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness);
+}
+
+float Environment::get_ssao_edge_sharpness() const {
+
+ return ssao_edge_sharpness;
+}
+
void Environment::set_glow_enabled(bool p_enabled) {
glow_enabled = p_enabled;
@@ -988,8 +1010,14 @@ void Environment::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_ssao_color", "color"), &Environment::set_ssao_color);
ClassDB::bind_method(D_METHOD("get_ssao_color"), &Environment::get_ssao_color);
- ClassDB::bind_method(D_METHOD("set_ssao_blur", "enabled"), &Environment::set_ssao_blur);
- ClassDB::bind_method(D_METHOD("is_ssao_blur_enabled"), &Environment::is_ssao_blur_enabled);
+ ClassDB::bind_method(D_METHOD("set_ssao_blur", "mode"), &Environment::set_ssao_blur);
+ ClassDB::bind_method(D_METHOD("get_ssao_blur"), &Environment::get_ssao_blur);
+
+ ClassDB::bind_method(D_METHOD("set_ssao_quality", "quality"), &Environment::set_ssao_quality);
+ ClassDB::bind_method(D_METHOD("get_ssao_quality"), &Environment::get_ssao_quality);
+
+ ClassDB::bind_method(D_METHOD("set_ssao_edge_sharpness", "edge_sharpness"), &Environment::set_ssao_edge_sharpness);
+ ClassDB::bind_method(D_METHOD("get_ssao_edge_sharpness"), &Environment::get_ssao_edge_sharpness);
ADD_GROUP("SSAO", "ssao_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ssao_enabled"), "set_ssao_enabled", "is_ssao_enabled");
@@ -1000,7 +1028,9 @@ void Environment::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::REAL, "ssao_bias", PROPERTY_HINT_RANGE, "0.001,8,0.001"), "set_ssao_bias", "get_ssao_bias");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "ssao_light_affect", PROPERTY_HINT_RANGE, "0.00,1,0.01"), "set_ssao_direct_light_affect", "get_ssao_direct_light_affect");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "ssao_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_ssao_color", "get_ssao_color");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ssao_blur"), "set_ssao_blur", "is_ssao_blur_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "ssao_quality", PROPERTY_HINT_ENUM, "Low,Medium,High"), "set_ssao_quality", "get_ssao_quality");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "ssao_blur", PROPERTY_HINT_ENUM, "Disabled,1x1,2x2,3x3"), "set_ssao_blur", "get_ssao_blur");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "ssao_edge_sharpness", PROPERTY_HINT_RANGE, "0,32,0.01"), "set_ssao_edge_sharpness", "get_ssao_edge_sharpness");
ClassDB::bind_method(D_METHOD("set_dof_blur_far_enabled", "enabled"), &Environment::set_dof_blur_far_enabled);
ClassDB::bind_method(D_METHOD("is_dof_blur_far_enabled"), &Environment::is_dof_blur_far_enabled);
@@ -1134,6 +1164,15 @@ void Environment::_bind_methods() {
BIND_ENUM_CONSTANT(DOF_BLUR_QUALITY_LOW);
BIND_ENUM_CONSTANT(DOF_BLUR_QUALITY_MEDIUM);
BIND_ENUM_CONSTANT(DOF_BLUR_QUALITY_HIGH);
+
+ BIND_ENUM_CONSTANT(SSAO_BLUR_DISABLED);
+ BIND_ENUM_CONSTANT(SSAO_BLUR_1x1);
+ BIND_ENUM_CONSTANT(SSAO_BLUR_2x2);
+ BIND_ENUM_CONSTANT(SSAO_BLUR_3x3);
+
+ BIND_ENUM_CONSTANT(SSAO_QUALITY_LOW);
+ BIND_ENUM_CONSTANT(SSAO_QUALITY_MEDIUM);
+ BIND_ENUM_CONSTANT(SSAO_QUALITY_HIGH);
}
Environment::Environment() {
@@ -1145,7 +1184,8 @@ Environment::Environment() {
bg_energy = 1.0;
bg_canvas_max_layer = 0;
ambient_energy = 1.0;
- ambient_sky_contribution = 1.0;
+ //ambient_sky_contribution = 1.0;
+ set_ambient_light_sky_contribution(1.0);
tone_mapper = TONE_MAPPER_LINEAR;
tonemap_exposure = 1.0;
@@ -1179,7 +1219,9 @@ Environment::Environment() {
ssao_intensity2 = 1;
ssao_bias = 0.01;
ssao_direct_light_affect = false;
- ssao_blur = true;
+ ssao_blur = SSAO_BLUR_3x3;
+ set_ssao_edge_sharpness(4);
+ set_ssao_quality(SSAO_QUALITY_LOW);
glow_enabled = false;
glow_levels = (1 << 2) | (1 << 4);
diff --git a/scene/resources/environment.h b/scene/resources/environment.h
index 5909846074..418949a6ad 100644
--- a/scene/resources/environment.h
+++ b/scene/resources/environment.h
@@ -71,6 +71,19 @@ public:
DOF_BLUR_QUALITY_HIGH,
};
+ enum SSAOBlur {
+ SSAO_BLUR_DISABLED,
+ SSAO_BLUR_1x1,
+ SSAO_BLUR_2x2,
+ SSAO_BLUR_3x3
+ };
+
+ enum SSAOQuality {
+ SSAO_QUALITY_LOW,
+ SSAO_QUALITY_MEDIUM,
+ SSAO_QUALITY_HIGH
+ };
+
private:
RID environment;
@@ -114,7 +127,9 @@ private:
float ssao_bias;
float ssao_direct_light_affect;
Color ssao_color;
- bool ssao_blur;
+ SSAOBlur ssao_blur;
+ float ssao_edge_sharpness;
+ SSAOQuality ssao_quality;
bool glow_enabled;
int glow_levels;
@@ -261,8 +276,14 @@ public:
void set_ssao_color(const Color &p_color);
Color get_ssao_color() const;
- void set_ssao_blur(bool p_enable);
- bool is_ssao_blur_enabled() const;
+ void set_ssao_blur(SSAOBlur p_blur);
+ SSAOBlur get_ssao_blur() const;
+
+ void set_ssao_quality(SSAOQuality p_quality);
+ SSAOQuality get_ssao_quality() const;
+
+ void set_ssao_edge_sharpness(float p_edge_sharpness);
+ float get_ssao_edge_sharpness() const;
void set_glow_enabled(bool p_enabled);
bool is_glow_enabled() const;
@@ -370,5 +391,7 @@ VARIANT_ENUM_CAST(Environment::BGMode)
VARIANT_ENUM_CAST(Environment::ToneMapper)
VARIANT_ENUM_CAST(Environment::GlowBlendMode)
VARIANT_ENUM_CAST(Environment::DOFBlurQuality)
+VARIANT_ENUM_CAST(Environment::SSAOQuality)
+VARIANT_ENUM_CAST(Environment::SSAOBlur)
#endif // ENVIRONMENT_H
diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp
index 2936df7a51..286840656b 100644
--- a/scene/resources/material.cpp
+++ b/scene/resources/material.cpp
@@ -723,7 +723,11 @@ void SpatialMaterial::_update_shader() {
} else {
code += "\tvec3 emission_tex = texture(texture_emission,base_uv).rgb;\n";
}
- code += "\tEMISSION = (emission.rgb+emission_tex)*emission_energy;\n";
+ if (emission_op == EMISSION_OP_ADD) {
+ code += "\tEMISSION = (emission.rgb+emission_tex)*emission_energy;\n";
+ } else {
+ code += "\tEMISSION = (emission.rgb*emission_tex)*emission_energy;\n";
+ }
}
if (features[FEATURE_REFRACTION] && !flags[FLAG_UV1_USE_TRIPLANAR]) { //refraction not supported with triplanar
@@ -1242,6 +1246,15 @@ Ref<Texture> SpatialMaterial::get_texture(TextureParam p_param) const {
return textures[p_param];
}
+Ref<Texture> SpatialMaterial::get_texture_by_name(StringName p_name) const {
+ for (int i = 0; i < (int)SpatialMaterial::TEXTURE_MAX; i++) {
+ TextureParam param = TextureParam(i);
+ if (p_name == shader_names->texture_names[param])
+ return textures[param];
+ }
+ return Ref<Texture>();
+}
+
void SpatialMaterial::_validate_feature(const String &text, Feature feature, PropertyInfo &property) const {
if (property.name.begins_with(text) && property.name != text + "_enabled" && !features[feature]) {
property.usage = 0;
@@ -1269,7 +1282,7 @@ void SpatialMaterial::_validate_property(PropertyInfo &property) const {
property.usage = 0;
}
- if (property.name == "proximity_fade_distacne" && !proximity_fade_enabled) {
+ if (property.name == "proximity_fade_distance" && !proximity_fade_enabled) {
property.usage = 0;
}
@@ -1626,6 +1639,19 @@ float SpatialMaterial::get_distance_fade_min_distance() const {
return distance_fade_min_distance;
}
+void SpatialMaterial::set_emission_operator(EmissionOperator p_op) {
+
+ if (emission_op == p_op)
+ return;
+ emission_op = p_op;
+ _queue_shader_change();
+}
+
+SpatialMaterial::EmissionOperator SpatialMaterial::get_emission_operator() const {
+
+ return emission_op;
+}
+
RID SpatialMaterial::get_shader_rid() const {
ERR_FAIL_COND_V(!shader_map.has(current_key), RID());
@@ -1760,6 +1786,9 @@ void SpatialMaterial::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_grow", "amount"), &SpatialMaterial::set_grow);
ClassDB::bind_method(D_METHOD("get_grow"), &SpatialMaterial::get_grow);
+ ClassDB::bind_method(D_METHOD("set_emission_operator", "operator"), &SpatialMaterial::set_emission_operator);
+ ClassDB::bind_method(D_METHOD("get_emission_operator"), &SpatialMaterial::get_emission_operator);
+
ClassDB::bind_method(D_METHOD("set_ao_light_affect", "amount"), &SpatialMaterial::set_ao_light_affect);
ClassDB::bind_method(D_METHOD("get_ao_light_affect"), &SpatialMaterial::get_ao_light_affect);
@@ -1845,6 +1874,7 @@ void SpatialMaterial::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "emission_enabled"), "set_feature", "get_feature", FEATURE_EMISSION);
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "emission", PROPERTY_HINT_COLOR_NO_ALPHA), "set_emission", "get_emission");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "emission_energy", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_emission_energy", "get_emission_energy");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "emission_operator", PROPERTY_HINT_ENUM, "Add,Multiply"), "set_emission_operator", "get_emission_operator");
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "emission_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_EMISSION);
ADD_GROUP("NormalMap", "normal_");
@@ -2013,6 +2043,9 @@ void SpatialMaterial::_bind_methods() {
BIND_ENUM_CONSTANT(TEXTURE_CHANNEL_BLUE);
BIND_ENUM_CONSTANT(TEXTURE_CHANNEL_ALPHA);
BIND_ENUM_CONSTANT(TEXTURE_CHANNEL_GRAYSCALE);
+
+ BIND_ENUM_CONSTANT(EMISSION_OP_ADD);
+ BIND_ENUM_CONSTANT(EMISSION_OP_MULTIPLY);
}
SpatialMaterial::SpatialMaterial()
@@ -2048,6 +2081,7 @@ SpatialMaterial::SpatialMaterial()
set_particles_anim_v_frames(1);
set_particles_anim_loop(false);
set_alpha_scissor_threshold(0.98);
+ emission_op = EMISSION_OP_ADD;
proximity_fade_enabled = false;
distance_fade_enabled = false;
diff --git a/scene/resources/material.h b/scene/resources/material.h
index c0e007ac5f..877d4dfd41 100644
--- a/scene/resources/material.h
+++ b/scene/resources/material.h
@@ -215,6 +215,11 @@ public:
TEXTURE_CHANNEL_GRAYSCALE
};
+ enum EmissionOperator {
+ EMISSION_OP_ADD,
+ EMISSION_OP_MULTIPLY
+ };
+
private:
union MaterialKey {
@@ -234,6 +239,7 @@ private:
uint64_t grow : 1;
uint64_t proximity_fade : 1;
uint64_t distance_fade : 1;
+ uint64_t emission_op : 1;
};
uint64_t key;
@@ -278,6 +284,7 @@ private:
mk.grow = grow_enabled;
mk.proximity_fade = proximity_fade_enabled;
mk.distance_fade = distance_fade_enabled;
+ mk.emission_op = emission_op;
return mk;
}
@@ -394,6 +401,7 @@ private:
SpecularMode specular_mode;
DiffuseMode diffuse_mode;
BillboardMode billboard_mode;
+ EmissionOperator emission_op;
TextureChannel metallic_texture_channel;
TextureChannel roughness_texture_channel;
@@ -510,6 +518,8 @@ public:
void set_texture(TextureParam p_param, const Ref<Texture> &p_texture);
Ref<Texture> get_texture(TextureParam p_param) const;
+ // Used only for shader material conversion
+ Ref<Texture> get_texture_by_name(StringName p_name) const;
void set_feature(Feature p_feature, bool p_enabled);
bool get_feature(Feature p_feature) const;
@@ -569,6 +579,9 @@ public:
void set_distance_fade_min_distance(float p_distance);
float get_distance_fade_min_distance() const;
+ void set_emission_operator(EmissionOperator p_op);
+ EmissionOperator get_emission_operator() const;
+
void set_metallic_texture_channel(TextureChannel p_channel);
TextureChannel get_metallic_texture_channel() const;
void set_roughness_texture_channel(TextureChannel p_channel);
@@ -601,6 +614,7 @@ VARIANT_ENUM_CAST(SpatialMaterial::DiffuseMode)
VARIANT_ENUM_CAST(SpatialMaterial::SpecularMode)
VARIANT_ENUM_CAST(SpatialMaterial::BillboardMode)
VARIANT_ENUM_CAST(SpatialMaterial::TextureChannel)
+VARIANT_ENUM_CAST(SpatialMaterial::EmissionOperator)
//////////////////////
diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp
index db5d87d703..0a886c25b1 100644
--- a/scene/resources/mesh.cpp
+++ b/scene/resources/mesh.cpp
@@ -574,7 +574,6 @@ bool ArrayMesh::_set(const StringName &p_name, const Variant &p_value) {
ERR_FAIL_COND_V(!d.has("format"), false);
uint32_t format = d["format"];
- ERR_FAIL_COND_V(!d.has("primitive"), false);
uint32_t primitive = d["primitive"];
ERR_FAIL_COND_V(!d.has("vertex_count"), false);
@@ -595,11 +594,11 @@ bool ArrayMesh::_set(const StringName &p_name, const Variant &p_value) {
}
ERR_FAIL_COND_V(!d.has("aabb"), false);
- Rect3 aabb = d["aabb"];
+ AABB aabb = d["aabb"];
- Vector<Rect3> bone_aabb;
- if (d.has("bone_aabb")) {
- Array baabb = d["bone_aabb"];
+ Vector<AABB> bone_aabb;
+ if (d.has("skeleton_aabb")) {
+ Array baabb = d["skeleton_aabb"];
bone_aabb.resize(baabb.size());
for (int i = 0; i < baabb.size(); i++) {
@@ -677,7 +676,7 @@ bool ArrayMesh::_get(const StringName &p_name, Variant &r_ret) const {
d["format"] = VS::get_singleton()->mesh_surface_get_format(mesh, idx);
d["aabb"] = VS::get_singleton()->mesh_surface_get_aabb(mesh, idx);
- Vector<Rect3> skel_aabb = VS::get_singleton()->mesh_surface_get_skeleton_aabb(mesh, idx);
+ Vector<AABB> skel_aabb = VS::get_singleton()->mesh_surface_get_skeleton_aabb(mesh, idx);
Array arr;
for (int i = 0; i < skel_aabb.size(); i++) {
arr[i] = skel_aabb[i];
@@ -726,13 +725,13 @@ void ArrayMesh::_get_property_list(List<PropertyInfo> *p_list) const {
}
}
- p_list->push_back(PropertyInfo(Variant::RECT3, "custom_aabb/custom_aabb"));
+ p_list->push_back(PropertyInfo(Variant::AABB, "custom_aabb/custom_aabb"));
}
void ArrayMesh::_recompute_aabb() {
// regenerate AABB
- aabb = Rect3();
+ aabb = AABB();
for (int i = 0; i < surfaces.size(); i++) {
@@ -743,7 +742,7 @@ void ArrayMesh::_recompute_aabb() {
}
}
-void ArrayMesh::add_surface(uint32_t p_format, PrimitiveType p_primitive, const PoolVector<uint8_t> &p_array, int p_vertex_count, const PoolVector<uint8_t> &p_index_array, int p_index_count, const Rect3 &p_aabb, const Vector<PoolVector<uint8_t> > &p_blend_shapes, const Vector<Rect3> &p_bone_aabbs) {
+void ArrayMesh::add_surface(uint32_t p_format, PrimitiveType p_primitive, const PoolVector<uint8_t> &p_array, int p_vertex_count, const PoolVector<uint8_t> &p_index_array, int p_index_count, const AABB &p_aabb, const Vector<PoolVector<uint8_t> > &p_blend_shapes, const Vector<AABB> &p_bone_aabbs) {
Surface s;
s.aabb = p_aabb;
@@ -773,7 +772,7 @@ void ArrayMesh::add_surface_from_arrays(PrimitiveType p_primitive, const Array &
const Vector3 *vtx = r.ptr();
// check AABB
- Rect3 aabb;
+ AABB aabb;
for (int i = 0; i < len; i++) {
if (i == 0)
@@ -921,7 +920,13 @@ String ArrayMesh::surface_get_name(int p_idx) const {
return surfaces[p_idx].name;
}
-void ArrayMesh::surface_set_custom_aabb(int p_idx, const Rect3 &p_aabb) {
+void ArrayMesh::surface_update_region(int p_surface, int p_offset, const PoolVector<uint8_t> &p_data) {
+
+ ERR_FAIL_INDEX(p_surface, surfaces.size());
+ VS::get_singleton()->mesh_surface_update_region(mesh, p_surface, p_offset, p_data);
+}
+
+void ArrayMesh::surface_set_custom_aabb(int p_idx, const AABB &p_aabb) {
ERR_FAIL_INDEX(p_idx, surfaces.size());
surfaces[p_idx].aabb = p_aabb;
@@ -937,7 +942,7 @@ Ref<Material> ArrayMesh::surface_get_material(int p_idx) const {
void ArrayMesh::add_surface_from_mesh_data(const Geometry::MeshData &p_mesh_data) {
VisualServer::get_singleton()->mesh_add_surface_from_mesh_data(mesh, p_mesh_data);
- Rect3 aabb;
+ AABB aabb;
for (int i = 0; i < p_mesh_data.vertices.size(); i++) {
if (i == 0)
@@ -965,18 +970,18 @@ RID ArrayMesh::get_rid() const {
return mesh;
}
-Rect3 ArrayMesh::get_aabb() const {
+AABB ArrayMesh::get_aabb() const {
return aabb;
}
-void ArrayMesh::set_custom_aabb(const Rect3 &p_custom) {
+void ArrayMesh::set_custom_aabb(const AABB &p_custom) {
custom_aabb = p_custom;
VS::get_singleton()->mesh_set_custom_aabb(mesh, custom_aabb);
}
-Rect3 ArrayMesh::get_custom_aabb() const {
+AABB ArrayMesh::get_custom_aabb() const {
return custom_aabb;
}
@@ -1042,6 +1047,7 @@ void ArrayMesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_surface_from_arrays", "primitive", "arrays", "blend_shapes", "compress_flags"), &ArrayMesh::add_surface_from_arrays, DEFVAL(Array()), DEFVAL(ARRAY_COMPRESS_DEFAULT));
ClassDB::bind_method(D_METHOD("get_surface_count"), &ArrayMesh::get_surface_count);
ClassDB::bind_method(D_METHOD("surface_remove", "surf_idx"), &ArrayMesh::surface_remove);
+ ClassDB::bind_method(D_METHOD("surface_update_region", "surf_idx", "offset", "data"), &ArrayMesh::surface_update_region);
ClassDB::bind_method(D_METHOD("surface_get_array_len", "surf_idx"), &ArrayMesh::surface_get_array_len);
ClassDB::bind_method(D_METHOD("surface_get_array_index_len", "surf_idx"), &ArrayMesh::surface_get_array_index_len);
ClassDB::bind_method(D_METHOD("surface_get_format", "surf_idx"), &ArrayMesh::surface_get_format);
@@ -1090,6 +1096,16 @@ void ArrayMesh::_bind_methods() {
BIND_ENUM_CONSTANT(ARRAY_FORMAT_INDEX);
}
+void ArrayMesh::reload_from_file() {
+ VisualServer::get_singleton()->mesh_clear(mesh);
+ surfaces.clear();
+ clear_blend_shapes();
+
+ Resource::reload_from_file();
+
+ _change_notify();
+}
+
ArrayMesh::ArrayMesh() {
mesh = VisualServer::get_singleton()->mesh_create();
diff --git a/scene/resources/mesh.h b/scene/resources/mesh.h
index f4edb258b6..b85a6a84af 100644
--- a/scene/resources/mesh.h
+++ b/scene/resources/mesh.h
@@ -95,6 +95,7 @@ public:
ARRAY_FLAG_USE_2D_VERTICES = ARRAY_COMPRESS_INDEX << 1,
ARRAY_FLAG_USE_16_BIT_BONES = ARRAY_COMPRESS_INDEX << 2,
+ ARRAY_FLAG_USE_DYNAMIC_UPDATE = ARRAY_COMPRESS_INDEX << 3,
ARRAY_COMPRESS_DEFAULT = ARRAY_COMPRESS_VERTEX | ARRAY_COMPRESS_NORMAL | ARRAY_COMPRESS_TANGENT | ARRAY_COMPRESS_COLOR | ARRAY_COMPRESS_TEX_UV | ARRAY_COMPRESS_TEX_UV2 | ARRAY_COMPRESS_WEIGHTS
@@ -135,7 +136,7 @@ public:
Ref<Mesh> create_outline(float p_margin) const;
- virtual Rect3 get_aabb() const = 0;
+ virtual AABB get_aabb() const = 0;
Mesh();
};
@@ -148,16 +149,16 @@ class ArrayMesh : public Mesh {
private:
struct Surface {
String name;
- Rect3 aabb;
+ AABB aabb;
Ref<Material> material;
bool is_2d;
};
Vector<Surface> surfaces;
RID mesh;
- Rect3 aabb;
+ AABB aabb;
BlendShapeMode blend_shape_mode;
Vector<StringName> blend_shapes;
- Rect3 custom_aabb;
+ AABB custom_aabb;
void _recompute_aabb();
@@ -172,7 +173,7 @@ protected:
public:
void add_surface_from_arrays(PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes = Array(), uint32_t p_flags = ARRAY_COMPRESS_DEFAULT);
- void add_surface(uint32_t p_format, PrimitiveType p_primitive, const PoolVector<uint8_t> &p_array, int p_vertex_count, const PoolVector<uint8_t> &p_index_array, int p_index_count, const Rect3 &p_aabb, const Vector<PoolVector<uint8_t> > &p_blend_shapes = Vector<PoolVector<uint8_t> >(), const Vector<Rect3> &p_bone_aabbs = Vector<Rect3>());
+ void add_surface(uint32_t p_format, PrimitiveType p_primitive, const PoolVector<uint8_t> &p_array, int p_vertex_count, const PoolVector<uint8_t> &p_index_array, int p_index_count, const AABB &p_aabb, const Vector<PoolVector<uint8_t> > &p_blend_shapes = Vector<PoolVector<uint8_t> >(), const Vector<AABB> &p_bone_aabbs = Vector<AABB>());
Array surface_get_arrays(int p_surface) const;
Array surface_get_blend_shape_arrays(int p_surface) const;
@@ -185,10 +186,12 @@ public:
void set_blend_shape_mode(BlendShapeMode p_mode);
BlendShapeMode get_blend_shape_mode() const;
+ void surface_update_region(int p_surface, int p_offset, const PoolVector<uint8_t> &p_data);
+
int get_surface_count() const;
void surface_remove(int p_idx);
- void surface_set_custom_aabb(int p_idx, const Rect3 &p_aabb); //only recognized by driver
+ void surface_set_custom_aabb(int p_idx, const AABB &p_aabb); //only recognized by driver
int surface_get_array_len(int p_idx) const;
int surface_get_array_index_len(int p_idx) const;
@@ -204,15 +207,17 @@ public:
void add_surface_from_mesh_data(const Geometry::MeshData &p_mesh_data);
- void set_custom_aabb(const Rect3 &p_custom);
- Rect3 get_custom_aabb() const;
+ void set_custom_aabb(const AABB &p_custom);
+ AABB get_custom_aabb() const;
- Rect3 get_aabb() const;
+ AABB get_aabb() const;
virtual RID get_rid() const;
void center_geometry();
void regen_normalmaps();
+ virtual void reload_from_file();
+
ArrayMesh();
~ArrayMesh();
diff --git a/scene/resources/multimesh.cpp b/scene/resources/multimesh.cpp
index 15f1e15542..ee6efa6e85 100644
--- a/scene/resources/multimesh.cpp
+++ b/scene/resources/multimesh.cpp
@@ -155,7 +155,7 @@ Color MultiMesh::get_instance_color(int p_instance) const {
return VisualServer::get_singleton()->multimesh_instance_get_color(multimesh, p_instance);
}
-Rect3 MultiMesh::get_aabb() const {
+AABB MultiMesh::get_aabb() const {
return VisualServer::get_singleton()->multimesh_get_aabb(multimesh);
}
diff --git a/scene/resources/multimesh.h b/scene/resources/multimesh.h
index 7ca66b0b46..0a5310f641 100644
--- a/scene/resources/multimesh.h
+++ b/scene/resources/multimesh.h
@@ -84,7 +84,7 @@ public:
void set_instance_color(int p_instance, const Color &p_color);
Color get_instance_color(int p_instance) const;
- virtual Rect3 get_aabb() const;
+ virtual AABB get_aabb() const;
virtual RID get_rid() const;
diff --git a/scene/resources/primitive_meshes.cpp b/scene/resources/primitive_meshes.cpp
index ba356d89b1..3b80db291c 100644
--- a/scene/resources/primitive_meshes.cpp
+++ b/scene/resources/primitive_meshes.cpp
@@ -42,7 +42,7 @@ void PrimitiveMesh::_update() const {
PoolVector<Vector3> points = arr[VS::ARRAY_VERTEX];
- aabb = Rect3();
+ aabb = AABB();
int pc = points.size();
ERR_FAIL_COND(pc == 0);
@@ -141,7 +141,7 @@ StringName PrimitiveMesh::get_blend_shape_name(int p_index) const {
return StringName();
}
-Rect3 PrimitiveMesh::get_aabb() const {
+AABB PrimitiveMesh::get_aabb() const {
if (pending_request) {
_update();
}
@@ -1299,14 +1299,16 @@ void QuadMesh::_create_mesh_array(Array &p_arr) const {
tangents.resize(4 * 4);
uvs.resize(4);
- for (int i = 0; i < 4; i++) {
+ Vector2 _size = Vector2(size.x / 2.0f, size.y / 2.0f);
- static const Vector3 quad_faces[4] = {
- Vector3(-1, -1, 0),
- Vector3(-1, 1, 0),
- Vector3(1, 1, 0),
- Vector3(1, -1, 0),
- };
+ Vector3 quad_faces[4] = {
+ Vector3(-_size.x, -_size.y, 0),
+ Vector3(-_size.x, _size.y, 0),
+ Vector3(_size.x, _size.y, 0),
+ Vector3(_size.x, -_size.y, 0),
+ };
+
+ for (int i = 0; i < 4; i++) {
faces.set(i, quad_faces[i]);
normals.set(i, Vector3(0, 0, 1));
@@ -1325,18 +1327,30 @@ void QuadMesh::_create_mesh_array(Array &p_arr) const {
uvs.set(i, quad_uv[i]);
}
- p_arr[ARRAY_VERTEX] = faces;
- p_arr[ARRAY_NORMAL] = normals;
- p_arr[ARRAY_TANGENT] = tangents;
- p_arr[ARRAY_TEX_UV] = uvs;
+ p_arr[VS::ARRAY_VERTEX] = faces;
+ p_arr[VS::ARRAY_NORMAL] = normals;
+ p_arr[VS::ARRAY_TANGENT] = tangents;
+ p_arr[VS::ARRAY_TEX_UV] = uvs;
};
void QuadMesh::_bind_methods() {
- // nothing here yet...
+ ClassDB::bind_method(D_METHOD("set_size", "size"), &QuadMesh::set_size);
+ ClassDB::bind_method(D_METHOD("get_size"), &QuadMesh::get_size);
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "size"), "set_size", "get_size");
}
QuadMesh::QuadMesh() {
primitive_type = PRIMITIVE_TRIANGLE_FAN;
+ size = Size2(1.0, 1.0);
+}
+
+void QuadMesh::set_size(const Size2 &p_size) {
+ size = p_size;
+ _request_update();
+}
+
+Size2 QuadMesh::get_size() const {
+ return size;
}
/**
diff --git a/scene/resources/primitive_meshes.h b/scene/resources/primitive_meshes.h
index 38a5695883..b38c247827 100644
--- a/scene/resources/primitive_meshes.h
+++ b/scene/resources/primitive_meshes.h
@@ -47,7 +47,7 @@ class PrimitiveMesh : public Mesh {
private:
RID mesh;
- mutable Rect3 aabb;
+ mutable AABB aabb;
Ref<Material> material;
@@ -73,7 +73,7 @@ public:
virtual Ref<Material> surface_get_material(int p_idx) const;
virtual int get_blend_shape_count() const;
virtual StringName get_blend_shape_name(int p_index) const;
- virtual Rect3 get_aabb() const;
+ virtual AABB get_aabb() const;
virtual RID get_rid() const;
void set_material(const Ref<Material> &p_material);
@@ -263,7 +263,7 @@ class QuadMesh : public PrimitiveMesh {
GDCLASS(QuadMesh, PrimitiveMesh)
private:
- // nothing? really? Maybe add size some day atleast... :)
+ Size2 size;
protected:
static void _bind_methods();
@@ -271,6 +271,9 @@ protected:
public:
QuadMesh();
+
+ void set_size(const Size2 &p_size);
+ Size2 get_size() const;
};
/**
diff --git a/scene/resources/rectangle_shape_2d.cpp b/scene/resources/rectangle_shape_2d.cpp
index 507dbce861..69dbb76744 100644
--- a/scene/resources/rectangle_shape_2d.cpp
+++ b/scene/resources/rectangle_shape_2d.cpp
@@ -67,7 +67,7 @@ void RectangleShape2D::_bind_methods() {
}
RectangleShape2D::RectangleShape2D()
- : Shape2D(Physics2DServer::get_singleton()->shape_create(Physics2DServer::SHAPE_RECTANGLE)) {
+ : Shape2D(Physics2DServer::get_singleton()->rectangle_shape_create()) {
extents = Vector2(10, 10);
_update_shape();
diff --git a/scene/resources/scene_format_text.cpp b/scene/resources/scene_format_text.cpp
index f0304bfaa5..fe23fbf6b3 100644
--- a/scene/resources/scene_format_text.cpp
+++ b/scene/resources/scene_format_text.cpp
@@ -33,7 +33,7 @@
#include "project_settings.h"
#include "version.h"
-//version 2: changed names for basis, rect3, poolvectors, etc.
+//version 2: changed names for basis, aabb, poolvectors, etc.
#define FORMAT_VERSION 2
#include "os/dir_access.h"
diff --git a/scene/resources/segment_shape_2d.cpp b/scene/resources/segment_shape_2d.cpp
index 1171db5c02..7c7ec0d112 100644
--- a/scene/resources/segment_shape_2d.cpp
+++ b/scene/resources/segment_shape_2d.cpp
@@ -87,7 +87,7 @@ void SegmentShape2D::_bind_methods() {
}
SegmentShape2D::SegmentShape2D()
- : Shape2D(Physics2DServer::get_singleton()->shape_create(Physics2DServer::SHAPE_SEGMENT)) {
+ : Shape2D(Physics2DServer::get_singleton()->segment_shape_create()) {
a = Vector2();
b = Vector2(0, 10);
@@ -146,7 +146,7 @@ real_t RayShape2D::get_length() const {
}
RayShape2D::RayShape2D()
- : Shape2D(Physics2DServer::get_singleton()->shape_create(Physics2DServer::SHAPE_RAY)) {
+ : Shape2D(Physics2DServer::get_singleton()->ray_shape_create()) {
length = 20;
_update_shape();
diff --git a/scene/resources/shader.cpp b/scene/resources/shader.cpp
index ec41630258..66df7dfda8 100644
--- a/scene/resources/shader.cpp
+++ b/scene/resources/shader.cpp
@@ -43,8 +43,6 @@ void Shader::set_code(const String &p_code) {
String type = ShaderLanguage::get_shader_type(p_code);
- print_line("mode: " + type);
-
if (type == "canvas_item") {
mode = MODE_CANVAS_ITEM;
} else if (type == "particles") {
diff --git a/scene/resources/shape_line_2d.cpp b/scene/resources/shape_line_2d.cpp
index 4dcc5ac981..d046ce876c 100644
--- a/scene/resources/shape_line_2d.cpp
+++ b/scene/resources/shape_line_2d.cpp
@@ -96,7 +96,7 @@ void LineShape2D::_bind_methods() {
}
LineShape2D::LineShape2D()
- : Shape2D(Physics2DServer::get_singleton()->shape_create(Physics2DServer::SHAPE_LINE)) {
+ : Shape2D(Physics2DServer::get_singleton()->line_shape_create()) {
normal = Vector2(0, -1);
d = 0;
diff --git a/scene/resources/style_box.cpp b/scene/resources/style_box.cpp
index b8a0a7864e..f4a9abc1ea 100644
--- a/scene/resources/style_box.cpp
+++ b/scene/resources/style_box.cpp
@@ -765,7 +765,7 @@ void StyleBoxFlat::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_border_blend", "blend"), &StyleBoxFlat::set_border_blend);
ClassDB::bind_method(D_METHOD("get_border_blend"), &StyleBoxFlat::get_border_blend);
- ClassDB::bind_method(D_METHOD("set_corner_radius_individual", "radius_top_left", "radius_top_right", "radius_botton_right", "radius_bottom_left"), &StyleBoxFlat::set_corner_radius_individual);
+ ClassDB::bind_method(D_METHOD("set_corner_radius_individual", "radius_top_left", "radius_top_right", "radius_bottom_right", "radius_bottom_left"), &StyleBoxFlat::set_corner_radius_individual);
ClassDB::bind_method(D_METHOD("set_corner_radius_all", "radius"), &StyleBoxFlat::set_corner_radius_all);
ClassDB::bind_method(D_METHOD("set_corner_radius", "corner", "radius"), &StyleBoxFlat::set_corner_radius);
diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp
index c202fad1a4..162edd0d1c 100644
--- a/scene/resources/texture.cpp
+++ b/scene/resources/texture.cpp
@@ -78,11 +78,11 @@ void Texture::_bind_methods() {
BIND_ENUM_CONSTANT(FLAG_MIPMAPS);
BIND_ENUM_CONSTANT(FLAG_REPEAT);
BIND_ENUM_CONSTANT(FLAG_FILTER);
- BIND_ENUM_CONSTANT(FLAG_VIDEO_SURFACE);
BIND_ENUM_CONSTANT(FLAGS_DEFAULT);
BIND_ENUM_CONSTANT(FLAG_ANISOTROPIC_FILTER);
BIND_ENUM_CONSTANT(FLAG_CONVERT_TO_LINEAR);
BIND_ENUM_CONSTANT(FLAG_MIRRORED_REPEAT);
+ BIND_ENUM_CONSTANT(FLAG_VIDEO_SURFACE);
}
Texture::Texture() {
@@ -866,6 +866,18 @@ Rect2 AtlasTexture::get_margin() const {
return margin;
}
+void AtlasTexture::set_filter_clip(const bool p_enable) {
+
+ filter_clip = p_enable;
+ emit_changed();
+ _change_notify("filter_clip");
+}
+
+bool AtlasTexture::has_filter_clip() const {
+
+ return filter_clip;
+}
+
void AtlasTexture::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_atlas", "atlas"), &AtlasTexture::set_atlas);
@@ -877,9 +889,13 @@ void AtlasTexture::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_margin", "margin"), &AtlasTexture::set_margin);
ClassDB::bind_method(D_METHOD("get_margin"), &AtlasTexture::get_margin);
+ ClassDB::bind_method(D_METHOD("set_filter_clip", "enable"), &AtlasTexture::set_filter_clip);
+ ClassDB::bind_method(D_METHOD("has_filter_clip"), &AtlasTexture::has_filter_clip);
+
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "atlas", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_atlas", "get_atlas");
ADD_PROPERTY(PropertyInfo(Variant::RECT2, "region"), "set_region", "get_region");
ADD_PROPERTY(PropertyInfo(Variant::RECT2, "margin"), "set_margin", "get_margin");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "filter_clip"), "set_filter_clip", "has_filter_clip");
}
void AtlasTexture::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose, const Ref<Texture> &p_normal_map) const {
@@ -898,7 +914,7 @@ void AtlasTexture::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_m
}
RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID();
- VS::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, Rect2(p_pos + margin.position, rc.size), atlas->get_rid(), rc, p_modulate, p_transpose, normal_rid);
+ VS::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, Rect2(p_pos + margin.position, rc.size), atlas->get_rid(), rc, p_modulate, p_transpose, normal_rid, filter_clip);
}
void AtlasTexture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose, const Ref<Texture> &p_normal_map) const {
@@ -920,7 +936,7 @@ void AtlasTexture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile
Rect2 dr(p_rect.position + margin.position * scale, rc.size * scale);
RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID();
- VS::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, dr, atlas->get_rid(), rc, p_modulate, p_transpose, normal_rid);
+ VS::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, dr, atlas->get_rid(), rc, p_modulate, p_transpose, normal_rid, filter_clip);
}
void AtlasTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, const Ref<Texture> &p_normal_map, bool p_clip_uv) const {
@@ -951,7 +967,7 @@ void AtlasTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, cons
Rect2 dr(p_rect.position + ofs * scale, src_c.size * scale);
RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID();
- VS::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, dr, atlas->get_rid(), src_c, p_modulate, p_transpose, normal_rid, p_clip_uv);
+ VS::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, dr, atlas->get_rid(), src_c, p_modulate, p_transpose, normal_rid, filter_clip);
}
bool AtlasTexture::get_rect_region(const Rect2 &p_rect, const Rect2 &p_src_rect, Rect2 &r_rect, Rect2 &r_src_rect) const {
@@ -987,6 +1003,7 @@ bool AtlasTexture::get_rect_region(const Rect2 &p_rect, const Rect2 &p_src_rect,
}
AtlasTexture::AtlasTexture() {
+ filter_clip = false;
}
//////////////////////////////////////////
@@ -1324,10 +1341,8 @@ void CubeMap::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_width"), &CubeMap::get_width);
ClassDB::bind_method(D_METHOD("get_height"), &CubeMap::get_height);
- //ClassDB::bind_method(D_METHOD("get_rid"),&CubeMap::get_rid);
ClassDB::bind_method(D_METHOD("set_flags", "flags"), &CubeMap::set_flags);
ClassDB::bind_method(D_METHOD("get_flags"), &CubeMap::get_flags);
-
ClassDB::bind_method(D_METHOD("set_side", "side", "image"), &CubeMap::set_side);
ClassDB::bind_method(D_METHOD("get_side", "side"), &CubeMap::get_side);
ClassDB::bind_method(D_METHOD("set_storage", "mode"), &CubeMap::set_storage);
@@ -1335,6 +1350,9 @@ void CubeMap::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_lossy_storage_quality", "quality"), &CubeMap::set_lossy_storage_quality);
ClassDB::bind_method(D_METHOD("get_lossy_storage_quality"), &CubeMap::get_lossy_storage_quality);
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "storage_mode", PROPERTY_HINT_ENUM, "Raw,Lossy Compressed,Lossless Compressed"), "set_storage", "get_storage");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "lossy_storage_quality"), "set_lossy_storage_quality", "get_lossy_storage_quality");
+
BIND_ENUM_CONSTANT(STORAGE_RAW);
BIND_ENUM_CONSTANT(STORAGE_COMPRESS_LOSSY);
BIND_ENUM_CONSTANT(STORAGE_COMPRESS_LOSSLESS);
diff --git a/scene/resources/texture.h b/scene/resources/texture.h
index 207436e4a7..ee54156647 100644
--- a/scene/resources/texture.h
+++ b/scene/resources/texture.h
@@ -237,6 +237,7 @@ protected:
Ref<Texture> atlas;
Rect2 region;
Rect2 margin;
+ bool filter_clip;
static void _bind_methods();
@@ -259,6 +260,9 @@ public:
void set_margin(const Rect2 &p_margin);
Rect2 get_margin() const;
+ void set_filter_clip(const bool p_enable);
+ bool has_filter_clip() const;
+
virtual void draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>()) const;
virtual void draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>()) const;
virtual void draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>(), bool p_clip_uv = true) const;
diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp
index 50e8c28c22..29ac7852bf 100644
--- a/scene/resources/tile_set.cpp
+++ b/scene/resources/tile_set.cpp
@@ -57,11 +57,9 @@ bool TileSet::_set(const StringName &p_name, const Variant &p_value) {
tile_set_region(id, p_value);
else if (what == "shape")
tile_set_shape(id, 0, p_value);
- else if (what == "shape_offset") {
- Transform2D xform = tile_get_shape_transform(id, 0);
- xform.set_origin(p_value);
- tile_set_shape_transform(id, 0, xform);
- } else if (what == "shape_transform")
+ else if (what == "shape_offset")
+ tile_set_shape_offset(id, 0, p_value);
+ else if (what == "shape_transform")
tile_set_shape_transform(id, 0, p_value);
else if (what == "shape_one_way")
tile_set_shape_one_way(id, 0, p_value);
@@ -110,7 +108,7 @@ bool TileSet::_get(const StringName &p_name, Variant &r_ret) const {
else if (what == "shape")
r_ret = tile_get_shape(id, 0);
else if (what == "shape_offset")
- r_ret = tile_get_shape_transform(id, 0).get_origin();
+ r_ret = tile_get_shape_offset(id, 0);
else if (what == "shape_transform")
r_ret = tile_get_shape_transform(id, 0);
else if (what == "shape_one_way")
@@ -313,6 +311,16 @@ Transform2D TileSet::tile_get_shape_transform(int p_id, int p_shape_id) const {
return Transform2D();
}
+void TileSet::tile_set_shape_offset(int p_id, int p_shape_id, const Vector2 &p_offset) {
+ Transform2D transform = tile_get_shape_transform(p_id, p_shape_id);
+ transform.set_origin(p_offset);
+ tile_set_shape_transform(p_id, p_shape_id, transform);
+}
+
+Vector2 TileSet::tile_get_shape_offset(int p_id, int p_shape_id) const {
+ return tile_get_shape_transform(p_id, p_shape_id).get_origin();
+}
+
void TileSet::tile_set_shape_one_way(int p_id, int p_shape_id, const bool p_one_way) {
ERR_FAIL_COND(!tile_map.has(p_id));
diff --git a/scene/resources/tile_set.h b/scene/resources/tile_set.h
index fe782ff987..3ef3f00cef 100644
--- a/scene/resources/tile_set.h
+++ b/scene/resources/tile_set.h
@@ -108,6 +108,9 @@ public:
void tile_set_shape_transform(int p_id, int p_shape_id, const Transform2D &p_offset);
Transform2D tile_get_shape_transform(int p_id, int p_shape_id) const;
+ void tile_set_shape_offset(int p_id, int p_shape_id, const Vector2 &p_offset);
+ Vector2 tile_get_shape_offset(int p_id, int p_shape_id) const;
+
void tile_set_shape_one_way(int p_id, int p_shape_id, bool p_one_way);
bool tile_get_shape_one_way(int p_id, int p_shape_id) const;
diff --git a/scene/resources/video_stream.h b/scene/resources/video_stream.h
index 0f07233185..fbe52909e7 100644
--- a/scene/resources/video_stream.h
+++ b/scene/resources/video_stream.h
@@ -40,7 +40,7 @@ protected:
static void _bind_methods();
public:
- typedef int (*AudioMixCallback)(void *p_udata, const int16_t *p_data, int p_frames);
+ typedef int (*AudioMixCallback)(void *p_udata, const float *p_data, int p_frames);
virtual void stop() = 0;
virtual void play() = 0;
@@ -48,7 +48,7 @@ public:
virtual bool is_playing() const = 0;
virtual void set_paused(bool p_paused) = 0;
- virtual bool is_paused(bool p_paused) const = 0;
+ virtual bool is_paused() const = 0;
virtual void set_loop(bool p_enable) = 0;
virtual bool has_loop() const = 0;
@@ -60,7 +60,7 @@ public:
virtual void set_audio_track(int p_idx) = 0;
- //virtual int mix(int16_t* p_bufer,int p_frames)=0;
+ //virtual int mix(int16_t* p_buffer,int p_frames)=0;
virtual Ref<Texture> get_texture() = 0;
virtual void update(float p_delta) = 0;
diff --git a/scene/resources/world.cpp b/scene/resources/world.cpp
index af159975ca..86b32a5cdd 100644
--- a/scene/resources/world.cpp
+++ b/scene/resources/world.cpp
@@ -41,7 +41,7 @@ struct SpatialIndexer {
struct NotifierData {
- Rect3 aabb;
+ AABB aabb;
OctreeElementID id;
};
@@ -63,7 +63,7 @@ struct SpatialIndexer {
uint64_t pass;
uint64_t last_frame;
- void _notifier_add(VisibilityNotifier *p_notifier, const Rect3 &p_rect) {
+ void _notifier_add(VisibilityNotifier *p_notifier, const AABB &p_rect) {
ERR_FAIL_COND(notifiers.has(p_notifier));
notifiers[p_notifier].aabb = p_rect;
@@ -71,7 +71,7 @@ struct SpatialIndexer {
changed = true;
}
- void _notifier_update(VisibilityNotifier *p_notifier, const Rect3 &p_rect) {
+ void _notifier_update(VisibilityNotifier *p_notifier, const AABB &p_rect) {
Map<VisibilityNotifier *, NotifierData>::Element *E = notifiers.find(p_notifier);
ERR_FAIL_COND(!E);
@@ -229,14 +229,14 @@ void World::_remove_camera(Camera *p_camera) {
#endif
}
-void World::_register_notifier(VisibilityNotifier *p_notifier, const Rect3 &p_rect) {
+void World::_register_notifier(VisibilityNotifier *p_notifier, const AABB &p_rect) {
#ifndef _3D_DISABLED
indexer->_notifier_add(p_notifier, p_rect);
#endif
}
-void World::_update_notifier(VisibilityNotifier *p_notifier, const Rect3 &p_rect) {
+void World::_update_notifier(VisibilityNotifier *p_notifier, const AABB &p_rect) {
#ifndef _3D_DISABLED
indexer->_notifier_update(p_notifier, p_rect);
diff --git a/scene/resources/world.h b/scene/resources/world.h
index 767d1b5b6e..e0f1de1fd0 100644
--- a/scene/resources/world.h
+++ b/scene/resources/world.h
@@ -60,8 +60,8 @@ protected:
void _update_camera(Camera *p_camera);
void _remove_camera(Camera *p_camera);
- void _register_notifier(VisibilityNotifier *p_notifier, const Rect3 &p_rect);
- void _update_notifier(VisibilityNotifier *p_notifier, const Rect3 &p_rect);
+ void _register_notifier(VisibilityNotifier *p_notifier, const AABB &p_rect);
+ void _update_notifier(VisibilityNotifier *p_notifier, const AABB &p_rect);
void _remove_notifier(VisibilityNotifier *p_notifier);
friend class Viewport;
void _update(uint64_t p_frame);
diff --git a/scene/scene_string_names.cpp b/scene/scene_string_names.cpp
index d9770ec3f3..52b8e35d5e 100644
--- a/scene/scene_string_names.cpp
+++ b/scene/scene_string_names.cpp
@@ -143,7 +143,7 @@ SceneStringNames::SceneStringNames() {
v_offset = StaticCString::create("v_offset");
transform_pos = StaticCString::create("position");
- transform_rot = StaticCString::create("rotation_deg");
+ transform_rot = StaticCString::create("rotation_degrees");
transform_scale = StaticCString::create("scale");
_update_remote = StaticCString::create("_update_remote");
diff --git a/servers/arvr/arvr_interface.cpp b/servers/arvr/arvr_interface.cpp
index 55707def7c..458459a843 100644
--- a/servers/arvr/arvr_interface.cpp
+++ b/servers/arvr/arvr_interface.cpp
@@ -43,7 +43,7 @@ void ARVRInterface::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_tracking_status"), &ARVRInterface::get_tracking_status);
- ClassDB::bind_method(D_METHOD("get_recommended_render_targetsize"), &ARVRInterface::get_recommended_render_targetsize);
+ ClassDB::bind_method(D_METHOD("get_render_targetsize"), &ARVRInterface::get_render_targetsize);
ClassDB::bind_method(D_METHOD("is_stereo"), &ARVRInterface::is_stereo);
ADD_GROUP("Interface", "interface_");
diff --git a/servers/arvr/arvr_interface.h b/servers/arvr/arvr_interface.h
index 880f6e4595..1599c1a64f 100644
--- a/servers/arvr/arvr_interface.h
+++ b/servers/arvr/arvr_interface.h
@@ -103,7 +103,7 @@ public:
/** rendering and internal **/
- virtual Size2 get_recommended_render_targetsize() = 0; /* returns the recommended render target size per eye for this device */
+ virtual Size2 get_render_targetsize() = 0; /* returns the recommended render target size per eye for this device */
virtual bool is_stereo() = 0; /* returns true if this interface requires stereo rendering (for VR HMDs) or mono rendering (for mobile AR) */
virtual Transform get_transform_for_eye(ARVRInterface::Eyes p_eye, const Transform &p_cam_transform) = 0; /* get each eyes camera transform, also implement EYE_MONO */
virtual CameraMatrix get_projection_for_eye(ARVRInterface::Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far) = 0; /* get each eyes projection matrix */
diff --git a/servers/arvr/arvr_positional_tracker.cpp b/servers/arvr/arvr_positional_tracker.cpp
index 4ecd7a3898..fc0270615c 100644
--- a/servers/arvr/arvr_positional_tracker.cpp
+++ b/servers/arvr/arvr_positional_tracker.cpp
@@ -52,6 +52,11 @@ void ARVRPositionalTracker::_bind_methods() {
ClassDB::bind_method(D_METHOD("_set_joy_id", "joy_id"), &ARVRPositionalTracker::set_joy_id);
ClassDB::bind_method(D_METHOD("_set_orientation", "orientation"), &ARVRPositionalTracker::set_orientation);
ClassDB::bind_method(D_METHOD("_set_rw_position", "rw_position"), &ARVRPositionalTracker::set_rw_position);
+
+ ClassDB::bind_method(D_METHOD("get_rumble"), &ARVRPositionalTracker::get_rumble);
+ ClassDB::bind_method(D_METHOD("set_rumble", "rumble"), &ARVRPositionalTracker::set_rumble);
+
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "rumble"), "set_rumble", "get_rumble");
};
void ARVRPositionalTracker::set_type(ARVRServer::TrackerType p_type) {
@@ -170,6 +175,18 @@ Transform ARVRPositionalTracker::get_transform(bool p_adjust_by_reference_frame)
return new_transform;
};
+real_t ARVRPositionalTracker::get_rumble() const {
+ return rumble;
+};
+
+void ARVRPositionalTracker::set_rumble(real_t p_rumble) {
+ if (p_rumble > 0.0) {
+ rumble = p_rumble;
+ } else {
+ rumble = 0.0;
+ };
+};
+
ARVRPositionalTracker::ARVRPositionalTracker() {
type = ARVRServer::TRACKER_UNKNOWN;
name = "Unknown";
@@ -178,6 +195,7 @@ ARVRPositionalTracker::ARVRPositionalTracker() {
tracks_orientation = false;
tracks_position = false;
hand = TRACKER_HAND_UNKNOWN;
+ rumble = 0.0;
};
ARVRPositionalTracker::~ARVRPositionalTracker(){
diff --git a/servers/arvr/arvr_positional_tracker.h b/servers/arvr/arvr_positional_tracker.h
index ff0c150f89..e450328a22 100644
--- a/servers/arvr/arvr_positional_tracker.h
+++ b/servers/arvr/arvr_positional_tracker.h
@@ -65,6 +65,7 @@ private:
bool tracks_position; // do we track position?
Vector3 rw_position; // our position "in the real world, so without world_scale applied"
TrackerHand hand; // if known, the hand this tracker is held in
+ real_t rumble; // rumble strength, 0.0 is off, 1.0 is maximum, note that we only record here, arvr_interface is responsible for execution
protected:
static void _bind_methods();
@@ -87,6 +88,8 @@ public:
Vector3 get_rw_position() const;
ARVRPositionalTracker::TrackerHand get_hand() const;
void set_hand(const ARVRPositionalTracker::TrackerHand p_hand);
+ real_t get_rumble() const;
+ void set_rumble(real_t p_rumble);
Transform get_transform(bool p_adjust_by_reference_frame) const;
diff --git a/servers/arvr/arvr_script_interface.cpp b/servers/arvr/arvr_script_interface.cpp
deleted file mode 100644
index 2755605a14..0000000000
--- a/servers/arvr/arvr_script_interface.cpp
+++ /dev/null
@@ -1,136 +0,0 @@
-#include "arvr_script_interface.h"
-
-ARVRScriptInterface::ARVRScriptInterface() {
- // testing
- printf("Construct script interface");
-}
-
-ARVRScriptInterface::~ARVRScriptInterface() {
- if (is_initialized()) {
- uninitialize();
- };
-
- // testing
- printf("Destruct script interface");
-}
-
-StringName ARVRScriptInterface::get_name() const {
- if (get_script_instance() && get_script_instance()->has_method("get_name")) {
- return get_script_instance()->call("get_name");
- } else {
- // just return something for now
- return "ARVR Script interface";
- }
-}
-
-int ARVRScriptInterface::get_capabilities() const {
- ERR_FAIL_COND_V(!(get_script_instance() && get_script_instance()->has_method("get_capabilities")), ARVRInterface::ARVR_NONE);
- return get_script_instance()->call("get_capabilities");
-};
-
-ARVRInterface::Tracking_status ARVRScriptInterface::get_tracking_status() const {
- ERR_FAIL_COND_V(!(get_script_instance() && get_script_instance()->has_method("get_tracking_status")), ARVRInterface::ARVR_NOT_TRACKING);
- int status = get_script_instance()->call("get_tracking_status");
- return (ARVRInterface::Tracking_status)status;
-}
-
-bool ARVRScriptInterface::get_anchor_detection_is_enabled() const {
- ERR_FAIL_COND_V(!(get_script_instance() && get_script_instance()->has_method("get_anchor_detection_is_enabled")), false);
- return get_script_instance()->call("get_anchor_detection_is_enabled");
-};
-
-void ARVRScriptInterface::set_anchor_detection_is_enabled(bool p_enable) {
- ERR_FAIL_COND(!(get_script_instance() && get_script_instance()->has_method("set_anchor_detection_is_enabled")));
- get_script_instance()->call("set_anchor_detection_is_enabled");
-};
-
-bool ARVRScriptInterface::is_stereo() {
- ERR_FAIL_COND_V(!(get_script_instance() && get_script_instance()->has_method("is_stereo")), false);
- return get_script_instance()->call("is_stereo");
-}
-
-bool ARVRScriptInterface::is_initialized() {
- ERR_FAIL_COND_V(!(get_script_instance() && get_script_instance()->has_method("is_initialized")), false);
- return get_script_instance()->call("is_initialized");
-}
-
-bool ARVRScriptInterface::initialize() {
- ERR_FAIL_COND_V(!(get_script_instance() && get_script_instance()->has_method("initialize")), false);
- return get_script_instance()->call("initialize");
-}
-
-void ARVRScriptInterface::uninitialize() {
- ARVRServer *arvr_server = ARVRServer::get_singleton();
- if (arvr_server != NULL) {
- // Whatever happens, make sure this is no longer our primary interface
- arvr_server->clear_primary_interface_if(this);
- }
-
- ERR_FAIL_COND(!(get_script_instance() && get_script_instance()->has_method("uninitialize")));
- get_script_instance()->call("uninitialize");
-}
-
-Size2 ARVRScriptInterface::get_recommended_render_targetsize() {
- ERR_FAIL_COND_V(!(get_script_instance() && get_script_instance()->has_method("get_recommended_render_targetsize")), Size2());
- return get_script_instance()->call("get_recommended_render_targetsize");
-}
-
-Transform ARVRScriptInterface::get_transform_for_eye(Eyes p_eye, const Transform &p_cam_transform) {
- ERR_FAIL_COND_V(!(get_script_instance() && get_script_instance()->has_method("get_transform_for_eye")), Transform());
- return get_script_instance()->call("get_transform_for_eye", p_eye, p_cam_transform);
-}
-
-// Suggestion from Reduz, as we can't return a CameraMatrix, return a PoolVector with our 16 floats
-PoolVector<float> ARVRScriptInterface::_get_projection_for_eye(Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far) {
- ERR_FAIL_COND_V(!(get_script_instance() && get_script_instance()->has_method("_get_projection_for_eye")), PoolVector<float>());
- return get_script_instance()->call("_get_projection_for_eye", p_eye, p_aspect, p_z_near, p_z_far);
-}
-
-CameraMatrix ARVRScriptInterface::get_projection_for_eye(Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far) {
- CameraMatrix cm;
- int i = 0;
- int j = 0;
-
- PoolVector<float> cm_as_floats = _get_projection_for_eye(p_eye, p_aspect, p_z_near, p_z_far);
-
- for (int k = 0; k < cm_as_floats.size() && i < 4; k++) {
- cm.matrix[i][j] = cm_as_floats[k];
- j++;
- if (j == 4) {
- j = 0;
- i++;
- };
- };
-
- return cm;
-}
-
-void ARVRScriptInterface::commit_for_eye(ARVRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect) {
- ERR_FAIL_COND(!(get_script_instance() && get_script_instance()->has_method("commit_for_eye")));
- get_script_instance()->call("commit_for_eye");
-}
-
-void ARVRScriptInterface::process() {
- ERR_FAIL_COND(!(get_script_instance() && get_script_instance()->has_method("process")));
- get_script_instance()->call("process");
-}
-
-void ARVRScriptInterface::_bind_methods() {
- ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::INT, "get_capabilities"));
-
- ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::BOOL, "is_initialized"));
- ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::BOOL, "initialize"));
- ClassDB::add_virtual_method(get_class_static(), MethodInfo("uninitialize"));
-
- ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::INT, "get_tracking_status"));
-
- ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::BOOL, "get_anchor_detection_is_enabled"));
- ClassDB::add_virtual_method(get_class_static(), MethodInfo("set_anchor_detection_is_enabled", PropertyInfo(Variant::BOOL, "enabled")));
-
- ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::BOOL, "is_stereo"));
- ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::VECTOR2, "get_recommended_render_targetsize"));
- ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::TRANSFORM, "get_transform_for_eye", PropertyInfo(Variant::INT, "eye"), PropertyInfo(Variant::TRANSFORM, "cam_transform")));
- ClassDB::add_virtual_method(get_class_static(), MethodInfo("_get_projection_for_eye"));
- ClassDB::add_virtual_method(get_class_static(), MethodInfo("commit_for_eye", PropertyInfo(Variant::INT, "eye"), PropertyInfo(Variant::_RID, "render_target")));
- ClassDB::add_virtual_method(get_class_static(), MethodInfo("process"));
-}
diff --git a/servers/arvr/arvr_script_interface.h b/servers/arvr/arvr_script_interface.h
deleted file mode 100644
index b1393b4fdb..0000000000
--- a/servers/arvr/arvr_script_interface.h
+++ /dev/null
@@ -1,52 +0,0 @@
-#ifndef SCRIPT_INTERFACE_H
-#define SCRIPT_INTERFACE_H
-
-#include "arvr_interface.h"
-
-/**
- @authors Hinsbart & Karroffel
-
- This subclass of our AR/VR interface forms a bridge to GDNative.
-*/
-
-class ARVRScriptInterface : public ARVRInterface {
- GDCLASS(ARVRScriptInterface, ARVRInterface);
-
-protected:
- static void _bind_methods();
-
-public:
- /** general interface information **/
- ARVRScriptInterface();
- ~ARVRScriptInterface();
-
- virtual StringName get_name() const;
- virtual int get_capabilities() const;
-
- virtual bool is_initialized();
- virtual bool initialize();
- virtual void uninitialize();
-
- ARVRInterface::Tracking_status get_tracking_status() const; /* get the status of our current tracking */
-
- /** specific to AR **/
- virtual bool get_anchor_detection_is_enabled() const;
- virtual void set_anchor_detection_is_enabled(bool p_enable);
-
- /** rendering and internal **/
- virtual Size2 get_recommended_render_targetsize();
- virtual bool is_stereo();
- virtual Transform get_transform_for_eye(ARVRInterface::Eyes p_eye, const Transform &p_cam_transform);
-
- // we expose a PoolVector<float> version of this function to GDNative
- PoolVector<float> _get_projection_for_eye(Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far);
-
- // and a CameraMatrix version to ARVRServer
- virtual CameraMatrix get_projection_for_eye(ARVRInterface::Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far);
-
- virtual void commit_for_eye(ARVRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect);
-
- virtual void process();
-};
-
-#endif // SCRIPT_INTERFACE_H
diff --git a/servers/arvr_server.cpp b/servers/arvr_server.cpp
index aa879f8aed..1e73d6753c 100644
--- a/servers/arvr_server.cpp
+++ b/servers/arvr_server.cpp
@@ -49,20 +49,18 @@ void ARVRServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_interface_count"), &ARVRServer::get_interface_count);
ClassDB::bind_method(D_METHOD("get_interface", "idx"), &ARVRServer::get_interface);
+ ClassDB::bind_method(D_METHOD("get_interfaces"), &ARVRServer::get_interfaces);
ClassDB::bind_method(D_METHOD("find_interface", "name"), &ARVRServer::find_interface);
ClassDB::bind_method(D_METHOD("get_tracker_count"), &ARVRServer::get_tracker_count);
ClassDB::bind_method(D_METHOD("get_tracker", "idx"), &ARVRServer::get_tracker);
- ClassDB::bind_method(D_METHOD("set_primary_interface"), &ARVRServer::set_primary_interface);
-
- ClassDB::bind_method(D_METHOD("add_interface"), &ARVRServer::add_interface);
- ClassDB::bind_method(D_METHOD("remove_interface"), &ARVRServer::remove_interface);
+ ClassDB::bind_method(D_METHOD("set_primary_interface", "interface"), &ARVRServer::set_primary_interface);
BIND_ENUM_CONSTANT(TRACKER_CONTROLLER);
BIND_ENUM_CONSTANT(TRACKER_BASESTATION);
BIND_ENUM_CONSTANT(TRACKER_ANCHOR);
- BIND_ENUM_CONSTANT(TRACKER_UNKNOWN);
BIND_ENUM_CONSTANT(TRACKER_ANY_KNOWN);
+ BIND_ENUM_CONSTANT(TRACKER_UNKNOWN);
BIND_ENUM_CONSTANT(TRACKER_ANY);
ADD_SIGNAL(MethodInfo("interface_added", PropertyInfo(Variant::STRING, "name")));
@@ -138,7 +136,7 @@ void ARVRServer::add_interface(const Ref<ARVRInterface> &p_interface) {
};
};
- print_line("Registered interface " + p_interface->get_name());
+ print_line("ARVR: Registered interface: " + p_interface->get_name());
interfaces.push_back(p_interface);
emit_signal("interface_added", p_interface->get_name());
@@ -191,6 +189,21 @@ Ref<ARVRInterface> ARVRServer::find_interface(const String &p_name) const {
return interfaces[idx];
};
+Array ARVRServer::get_interfaces() const {
+ Array ret;
+
+ for (int i = 0; i < interfaces.size(); i++) {
+ Dictionary iface_info;
+
+ iface_info["id"] = i;
+ iface_info["name"] = interfaces[i]->get_name();
+
+ ret.push_back(iface_info);
+ };
+
+ return ret;
+};
+
/*
A little extra info on the tracker ids, these are unique per tracker type so we get soem consistency in recognising our trackers, specifically controllers.
diff --git a/servers/arvr_server.h b/servers/arvr_server.h
index 948895cb27..9b84ee2e99 100644
--- a/servers/arvr_server.h
+++ b/servers/arvr_server.h
@@ -137,6 +137,7 @@ public:
int get_interface_count() const;
Ref<ARVRInterface> get_interface(int p_index) const;
Ref<ARVRInterface> find_interface(const String &p_name) const;
+ Array get_interfaces() const;
/*
note, more then one interface can technically be active, especially on mobile, but only one interface is used for
diff --git a/servers/audio/audio_rb_resampler.cpp b/servers/audio/audio_rb_resampler.cpp
index 113e356612..b0b94a1f49 100644
--- a/servers/audio/audio_rb_resampler.cpp
+++ b/servers/audio/audio_rb_resampler.cpp
@@ -28,6 +28,9 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "audio_rb_resampler.h"
+#include "core/math/math_funcs.h"
+#include "os/os.h"
+#include "servers/audio_server.h"
int AudioRBResampler::get_channel_count() const {
@@ -37,8 +40,11 @@ int AudioRBResampler::get_channel_count() const {
return channels;
}
+// Linear interpolation based sample rate convertion (low quality)
+// Note that AudioStreamPlaybackResampled::mix has better algorithm,
+// but it wasn't obvious to integrate that with VideoPlayer
template <int C>
-uint32_t AudioRBResampler::_resample(int32_t *p_dest, int p_todo, int32_t p_increment) {
+uint32_t AudioRBResampler::_resample(AudioFrame *p_dest, int p_todo, int32_t p_increment) {
uint32_t read = offset & MIX_FRAC_MASK;
@@ -47,186 +53,128 @@ uint32_t AudioRBResampler::_resample(int32_t *p_dest, int p_todo, int32_t p_incr
offset = (offset + p_increment) & (((1 << (rb_bits + MIX_FRAC_BITS)) - 1));
read += p_increment;
uint32_t pos = offset >> MIX_FRAC_BITS;
- uint32_t frac = offset & MIX_FRAC_MASK;
-#ifndef FAST_AUDIO
+ float frac = float(offset & MIX_FRAC_MASK) / float(MIX_FRAC_LEN);
ERR_FAIL_COND_V(pos >= rb_len, 0);
-#endif
uint32_t pos_next = (pos + 1) & rb_mask;
- //printf("rb pos %i\n",pos);
// since this is a template with a known compile time value (C), conditionals go away when compiling.
if (C == 1) {
- int32_t v0 = rb[pos];
- int32_t v0n = rb[pos_next];
-#ifndef FAST_AUDIO
- v0 += (v0n - v0) * (int32_t)frac >> MIX_FRAC_BITS;
-#endif
- v0 <<= 16;
- p_dest[i] = v0;
+ float v0 = rb[pos];
+ float v0n = rb[pos_next];
+ v0 += (v0n - v0) * frac;
+ p_dest[i] = AudioFrame(v0, v0);
}
+
if (C == 2) {
- int32_t v0 = rb[(pos << 1) + 0];
- int32_t v1 = rb[(pos << 1) + 1];
- int32_t v0n = rb[(pos_next << 1) + 0];
- int32_t v1n = rb[(pos_next << 1) + 1];
-
-#ifndef FAST_AUDIO
- v0 += (v0n - v0) * (int32_t)frac >> MIX_FRAC_BITS;
- v1 += (v1n - v1) * (int32_t)frac >> MIX_FRAC_BITS;
-#endif
- v0 <<= 16;
- v1 <<= 16;
- p_dest[(i << 1) + 0] = v0;
- p_dest[(i << 1) + 1] = v1;
+ float v0 = rb[(pos << 1) + 0];
+ float v1 = rb[(pos << 1) + 1];
+ float v0n = rb[(pos_next << 1) + 0];
+ float v1n = rb[(pos_next << 1) + 1];
+
+ v0 += (v0n - v0) * frac;
+ v1 += (v1n - v1) * frac;
+ p_dest[i] = AudioFrame(v0, v1);
}
+ // For now, channels higher than stereo are almost ignored
if (C == 4) {
- int32_t v0 = rb[(pos << 2) + 0];
- int32_t v1 = rb[(pos << 2) + 1];
- int32_t v2 = rb[(pos << 2) + 2];
- int32_t v3 = rb[(pos << 2) + 3];
- int32_t v0n = rb[(pos_next << 2) + 0];
- int32_t v1n = rb[(pos_next << 2) + 1];
- int32_t v2n = rb[(pos_next << 2) + 2];
- int32_t v3n = rb[(pos_next << 2) + 3];
-
-#ifndef FAST_AUDIO
- v0 += (v0n - v0) * (int32_t)frac >> MIX_FRAC_BITS;
- v1 += (v1n - v1) * (int32_t)frac >> MIX_FRAC_BITS;
- v2 += (v2n - v2) * (int32_t)frac >> MIX_FRAC_BITS;
- v3 += (v3n - v3) * (int32_t)frac >> MIX_FRAC_BITS;
-#endif
- v0 <<= 16;
- v1 <<= 16;
- v2 <<= 16;
- v3 <<= 16;
- p_dest[(i << 2) + 0] = v0;
- p_dest[(i << 2) + 1] = v1;
- p_dest[(i << 2) + 2] = v2;
- p_dest[(i << 2) + 3] = v3;
+ float v0 = rb[(pos << 2) + 0];
+ float v1 = rb[(pos << 2) + 1];
+ float v2 = rb[(pos << 2) + 2];
+ float v3 = rb[(pos << 2) + 3];
+ float v0n = rb[(pos_next << 2) + 0];
+ float v1n = rb[(pos_next << 2) + 1];
+ float v2n = rb[(pos_next << 2) + 2];
+ float v3n = rb[(pos_next << 2) + 3];
+
+ v0 += (v0n - v0) * frac;
+ v1 += (v1n - v1) * frac;
+ v2 += (v2n - v2) * frac;
+ v3 += (v3n - v3) * frac;
+ p_dest[i] = AudioFrame(v0, v1);
}
if (C == 6) {
- int32_t v0 = rb[(pos * 6) + 0];
- int32_t v1 = rb[(pos * 6) + 1];
- int32_t v2 = rb[(pos * 6) + 2];
- int32_t v3 = rb[(pos * 6) + 3];
- int32_t v4 = rb[(pos * 6) + 4];
- int32_t v5 = rb[(pos * 6) + 5];
- int32_t v0n = rb[(pos_next * 6) + 0];
- int32_t v1n = rb[(pos_next * 6) + 1];
- int32_t v2n = rb[(pos_next * 6) + 2];
- int32_t v3n = rb[(pos_next * 6) + 3];
- int32_t v4n = rb[(pos_next * 6) + 4];
- int32_t v5n = rb[(pos_next * 6) + 5];
-
-#ifndef FAST_AUDIO
- v0 += (v0n - v0) * (int32_t)frac >> MIX_FRAC_BITS;
- v1 += (v1n - v1) * (int32_t)frac >> MIX_FRAC_BITS;
- v2 += (v2n - v2) * (int32_t)frac >> MIX_FRAC_BITS;
- v3 += (v3n - v3) * (int32_t)frac >> MIX_FRAC_BITS;
- v4 += (v4n - v4) * (int32_t)frac >> MIX_FRAC_BITS;
- v5 += (v5n - v5) * (int32_t)frac >> MIX_FRAC_BITS;
-#endif
- v0 <<= 16;
- v1 <<= 16;
- v2 <<= 16;
- v3 <<= 16;
- v4 <<= 16;
- v5 <<= 16;
- p_dest[(i * 6) + 0] = v0;
- p_dest[(i * 6) + 1] = v1;
- p_dest[(i * 6) + 2] = v2;
- p_dest[(i * 6) + 3] = v3;
- p_dest[(i * 6) + 4] = v4;
- p_dest[(i * 6) + 5] = v5;
+ float v0 = rb[(pos * 6) + 0];
+ float v1 = rb[(pos * 6) + 1];
+ float v2 = rb[(pos * 6) + 2];
+ float v3 = rb[(pos * 6) + 3];
+ float v4 = rb[(pos * 6) + 4];
+ float v5 = rb[(pos * 6) + 5];
+ float v0n = rb[(pos_next * 6) + 0];
+ float v1n = rb[(pos_next * 6) + 1];
+ float v2n = rb[(pos_next * 6) + 2];
+ float v3n = rb[(pos_next * 6) + 3];
+ float v4n = rb[(pos_next * 6) + 4];
+ float v5n = rb[(pos_next * 6) + 5];
+
+ p_dest[i] = AudioFrame(v0, v1);
}
}
- return read >> MIX_FRAC_BITS; //rb_read_pos=offset>>MIX_FRAC_BITS;
+ return read >> MIX_FRAC_BITS; //rb_read_pos = offset >> MIX_FRAC_BITS;
}
-bool AudioRBResampler::mix(int32_t *p_dest, int p_frames) {
+bool AudioRBResampler::mix(AudioFrame *p_dest, int p_frames) {
if (!rb)
return false;
- int write_pos_cache = rb_write_pos;
-
int32_t increment = (src_mix_rate * MIX_FRAC_LEN) / target_mix_rate;
-
- int rb_todo;
-
- if (write_pos_cache == rb_read_pos) {
- return false; //out of buffer
-
- } else if (rb_read_pos < write_pos_cache) {
-
- rb_todo = write_pos_cache - rb_read_pos; //-1?
- } else {
-
- rb_todo = (rb_len - rb_read_pos) + write_pos_cache; //-1?
- }
-
- int todo = MIN(((int64_t(rb_todo) << MIX_FRAC_BITS) / increment) + 1, p_frames);
+ int read_space = get_reader_space();
+ int target_todo = MIN(get_num_of_ready_frames(), p_frames);
{
-
- int read = 0;
+ int src_read = 0;
switch (channels) {
- case 1: read = _resample<1>(p_dest, todo, increment); break;
- case 2: read = _resample<2>(p_dest, todo, increment); break;
- case 4: read = _resample<4>(p_dest, todo, increment); break;
- case 6: read = _resample<6>(p_dest, todo, increment); break;
+ case 1: src_read = _resample<1>(p_dest, target_todo, increment); break;
+ case 2: src_read = _resample<2>(p_dest, target_todo, increment); break;
+ case 4: src_read = _resample<4>(p_dest, target_todo, increment); break;
+ case 6: src_read = _resample<6>(p_dest, target_todo, increment); break;
}
- //end of stream, fadeout
- int remaining = p_frames - todo;
- if (remaining && todo > 0) {
-
- //print_line("fadeout");
- for (uint32_t c = 0; c < channels; c++) {
+ if (src_read > read_space)
+ src_read = read_space;
- for (int i = 0; i < todo; i++) {
+ rb_read_pos = (rb_read_pos + src_read) & rb_mask;
- int32_t samp = p_dest[i * channels + c] >> 8;
- uint32_t mul = (todo - i) * 256 / todo;
- //print_line("mul: "+itos(i)+" "+itos(mul));
- p_dest[i * channels + c] = samp * mul;
- }
+ // Create fadeout effect for the end of stream (note that it can be because of slow writer)
+ if (p_frames - target_todo > 0) {
+ for (int i = 0; i < target_todo; i++) {
+ p_dest[i] = p_dest[i] * float(target_todo - i) / float(target_todo);
}
}
- //zero out what remains there to avoid glitches
- for (uint32_t i = todo * channels; i < int(p_frames) * channels; i++) {
-
- p_dest[i] = 0;
+ // Fill zeros (silence) for the rest of frames
+ for (uint32_t i = target_todo; i < p_frames; i++) {
+ p_dest[i] = AudioFrame(0, 0);
}
-
- if (read > rb_todo)
- read = rb_todo;
-
- rb_read_pos = (rb_read_pos + read) & rb_mask;
}
return true;
}
+int AudioRBResampler::get_num_of_ready_frames() {
+ if (!is_ready())
+ return 0;
+ int32_t increment = (src_mix_rate * MIX_FRAC_LEN) / target_mix_rate;
+ int read_space = get_reader_space();
+ return (int64_t(read_space) << MIX_FRAC_BITS) / increment;
+}
+
Error AudioRBResampler::setup(int p_channels, int p_src_mix_rate, int p_target_mix_rate, int p_buffer_msec, int p_minbuff_needed) {
ERR_FAIL_COND_V(p_channels != 1 && p_channels != 2 && p_channels != 4 && p_channels != 6, ERR_INVALID_PARAMETER);
- //float buffering_sec = int(GLOBAL_DEF("audio/stream_buffering_ms",500))/1000.0;
int desired_rb_bits = nearest_shift(MAX((p_buffer_msec / 1000.0) * p_src_mix_rate, p_minbuff_needed));
bool recreate = !rb;
if (rb && (uint32_t(desired_rb_bits) != rb_bits || channels != uint32_t(p_channels))) {
- //recreate
memdelete_arr(rb);
memdelete_arr(read_buf);
@@ -239,8 +187,8 @@ Error AudioRBResampler::setup(int p_channels, int p_src_mix_rate, int p_target_m
rb_bits = desired_rb_bits;
rb_len = (1 << rb_bits);
rb_mask = rb_len - 1;
- rb = memnew_arr(int16_t, rb_len * p_channels);
- read_buf = memnew_arr(int16_t, rb_len * p_channels);
+ rb = memnew_arr(float, rb_len *p_channels);
+ read_buf = memnew_arr(float, rb_len *p_channels);
}
src_mix_rate = p_src_mix_rate;
diff --git a/servers/audio/audio_rb_resampler.h b/servers/audio/audio_rb_resampler.h
index bc1f924ab5..08c7a5a668 100644
--- a/servers/audio/audio_rb_resampler.h
+++ b/servers/audio/audio_rb_resampler.h
@@ -31,6 +31,7 @@
#define AUDIO_RB_RESAMPLER_H
#include "os/memory.h"
+#include "servers/audio_server.h"
#include "typedefs.h"
struct AudioRBResampler {
@@ -53,11 +54,11 @@ struct AudioRBResampler {
MIX_FRAC_MASK = MIX_FRAC_LEN - 1,
};
- int16_t *read_buf;
- int16_t *rb;
+ float *read_buf;
+ float *rb;
template <int C>
- uint32_t _resample(int32_t *p_dest, int p_todo, int32_t p_increment);
+ uint32_t _resample(AudioFrame *p_dest, int p_todo, int32_t p_increment);
public:
_FORCE_INLINE_ void flush() {
@@ -71,33 +72,48 @@ public:
}
_FORCE_INLINE_ int get_total() const {
-
return rb_len - 1;
}
- _FORCE_INLINE_ int get_todo() const { //return amount of frames to mix
-
- int todo;
- int read_pos_cache = rb_read_pos;
+ _FORCE_INLINE_ int get_writer_space() const {
+ int space, r, w;
- if (read_pos_cache == rb_write_pos) {
- todo = rb_len - 1;
- } else if (read_pos_cache > rb_write_pos) {
+ r = rb_read_pos;
+ w = rb_write_pos;
- todo = read_pos_cache - rb_write_pos - 1;
+ if (r == w) {
+ space = rb_len - 1;
+ } else if (w < r) {
+ space = r - w - 1;
} else {
+ space = (rb_len - r) + w - 1;
+ }
+
+ return space;
+ }
+
+ _FORCE_INLINE_ int get_reader_space() const {
+ int space, r, w;
- todo = (rb_len - rb_write_pos) + read_pos_cache - 1;
+ r = rb_read_pos;
+ w = rb_write_pos;
+
+ if (r == w) {
+ space = 0;
+ } else if (w < r) {
+ space = rb_len - r + w;
+ } else {
+ space = w - r;
}
- return todo;
+ return space;
}
_FORCE_INLINE_ bool has_data() const {
return rb && rb_read_pos != rb_write_pos;
}
- _FORCE_INLINE_ int16_t *get_write_buffer() { return read_buf; }
+ _FORCE_INLINE_ float *get_write_buffer() { return read_buf; }
_FORCE_INLINE_ void write(uint32_t p_frames) {
ERR_FAIL_COND(p_frames >= rb_len);
@@ -151,7 +167,8 @@ public:
Error setup(int p_channels, int p_src_mix_rate, int p_target_mix_rate, int p_buffer_msec, int p_minbuff_needed = -1);
void clear();
- bool mix(int32_t *p_dest, int p_frames);
+ bool mix(AudioFrame *p_dest, int p_frames);
+ int get_num_of_ready_frames();
AudioRBResampler();
~AudioRBResampler();
diff --git a/servers/audio/audio_stream.cpp b/servers/audio/audio_stream.cpp
index 0e3d5824d9..d7b2c2c5e0 100644
--- a/servers/audio/audio_stream.cpp
+++ b/servers/audio/audio_stream.cpp
@@ -191,12 +191,12 @@ void AudioStreamPlaybackRandomPitch::seek(float p_time) {
}
}
-void AudioStreamPlaybackRandomPitch::mix(AudioFrame *p_bufer, float p_rate_scale, int p_frames) {
+void AudioStreamPlaybackRandomPitch::mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) {
if (playing.is_valid()) {
- playing->mix(p_bufer, p_rate_scale * pitch_scale, p_frames);
+ playing->mix(p_buffer, p_rate_scale * pitch_scale, p_frames);
} else {
for (int i = 0; i < p_frames; i++) {
- p_bufer[i] = AudioFrame(0, 0);
+ p_buffer[i] = AudioFrame(0, 0);
}
}
}
diff --git a/servers/audio/audio_stream.h b/servers/audio/audio_stream.h
index 3324597b41..dc931502b4 100644
--- a/servers/audio/audio_stream.h
+++ b/servers/audio/audio_stream.h
@@ -48,7 +48,7 @@ public:
virtual float get_playback_position() const = 0;
virtual void seek(float p_time) = 0;
- virtual void mix(AudioFrame *p_bufer, float p_rate_scale, int p_frames) = 0;
+ virtual void mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) = 0;
virtual float get_length() const = 0; //if supported, otherwise return 0
};
@@ -70,7 +70,7 @@ class AudioStreamPlaybackResampled : public AudioStreamPlayback {
protected:
void _begin_resample();
- virtual void _mix_internal(AudioFrame *p_bufer, int p_frames) = 0;
+ virtual void _mix_internal(AudioFrame *p_buffer, int p_frames) = 0;
virtual float get_stream_sampling_rate() = 0;
public:
@@ -136,7 +136,7 @@ public:
virtual float get_playback_position() const;
virtual void seek(float p_time);
- virtual void mix(AudioFrame *p_bufer, float p_rate_scale, int p_frames);
+ virtual void mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames);
virtual float get_length() const; //if supported, otherwise return 0
diff --git a/servers/audio/effects/audio_effect_filter.cpp b/servers/audio/effects/audio_effect_filter.cpp
index 019494c74a..95354230c6 100644
--- a/servers/audio/effects/audio_effect_filter.cpp
+++ b/servers/audio/effects/audio_effect_filter.cpp
@@ -158,7 +158,7 @@ void AudioEffectFilter::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::REAL, "cutoff_hz", PROPERTY_HINT_RANGE, "1,40000,0.1"), "set_cutoff", "get_cutoff");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "resonance", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_resonance", "get_resonance");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "gain", PROPERTY_HINT_RANGE, "0,4,0.01"), "set_gain", "get_gain");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "dB", PROPERTY_HINT_ENUM, "6db,12db,18db,24db"), "set_db", "get_db");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "db", PROPERTY_HINT_ENUM, "6 dB,12 dB,18 dB,24 dB"), "set_db", "get_db");
BIND_ENUM_CONSTANT(FILTER_6DB);
BIND_ENUM_CONSTANT(FILTER_12DB);
diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp
index 18b7014595..6a10d7539d 100644
--- a/servers/audio_server.cpp
+++ b/servers/audio_server.cpp
@@ -226,7 +226,7 @@ void AudioServer::_driver_process(int p_frames, int32_t *p_buffer) {
static int total = 0;
ticks = OS::get_singleton()->get_ticks_msec();
- if ((ticks - first_ticks) > 10 * 1000) {
+ if ((ticks - first_ticks) > 10 * 1000 && count > 0) {
print_line("Audio Driver " + String(AudioDriver::get_singleton()->get_name()) + " average latency: " + itos(total / count) + "ms (frame=" + itos(p_frames) + ")");
first_ticks = ticks;
total = 0;
@@ -876,6 +876,8 @@ void AudioServer::init() {
#ifdef TOOLS_ENABLED
set_edited(false); //avoid editors from thinking this was edited
#endif
+
+ GLOBAL_DEF("audio/video_delay_compensation_ms", 0);
}
void AudioServer::load_default_bus_layout() {
diff --git a/servers/physics/body_pair_sw.cpp b/servers/physics/body_pair_sw.cpp
index a289b4b0ca..ef54eb58cf 100644
--- a/servers/physics/body_pair_sw.cpp
+++ b/servers/physics/body_pair_sw.cpp
@@ -46,6 +46,7 @@
//#define ALLOWED_PENETRATION 0.01
#define RELAXATION_TIMESTEPS 3
#define MIN_VELOCITY 0.0001
+#define MAX_BIAS_ROTATION (Math_PI / 8)
void BodyPairSW::_contact_added_callback(const Vector3 &p_point_A, const Vector3 &p_point_B, void *p_userdata) {
@@ -71,6 +72,7 @@ void BodyPairSW::contact_added_callback(const Vector3 &p_point_A, const Vector3
contact.acc_normal_impulse = 0;
contact.acc_bias_impulse = 0;
+ contact.acc_bias_impulse_center_of_mass = 0;
contact.acc_tangent_impulse = Vector3();
contact.local_A = local_A;
contact.local_B = local_B;
@@ -82,12 +84,12 @@ void BodyPairSW::contact_added_callback(const Vector3 &p_point_A, const Vector3
for (int i = 0; i < contact_count; i++) {
Contact &c = contacts[i];
- if (
- c.local_A.distance_squared_to(local_A) < (contact_recycle_radius * contact_recycle_radius) &&
+ if (c.local_A.distance_squared_to(local_A) < (contact_recycle_radius * contact_recycle_radius) &&
c.local_B.distance_squared_to(local_B) < (contact_recycle_radius * contact_recycle_radius)) {
contact.acc_normal_impulse = c.acc_normal_impulse;
contact.acc_bias_impulse = c.acc_bias_impulse;
+ contact.acc_bias_impulse_center_of_mass = c.acc_bias_impulse_center_of_mass;
contact.acc_tangent_impulse = c.acc_tangent_impulse;
new_index = i;
break;
@@ -325,9 +327,7 @@ bool BodyPairSW::setup(real_t p_step) {
A->apply_impulse(c.rA + A->get_center_of_mass(), -j_vec);
B->apply_impulse(c.rB + B->get_center_of_mass(), j_vec);
c.acc_bias_impulse = 0;
- Vector3 jb_vec = c.normal * c.acc_bias_impulse;
- A->apply_bias_impulse(c.rA + A->get_center_of_mass(), -jb_vec);
- B->apply_bias_impulse(c.rB + B->get_center_of_mass(), jb_vec);
+ c.acc_bias_impulse_center_of_mass = 0;
c.bounce = MAX(A->get_bounce(), B->get_bounce());
if (c.bounce) {
@@ -356,7 +356,7 @@ void BodyPairSW::solve(real_t p_step) {
c.active = false; //try to deactivate, will activate itself if still needed
- //bias impule
+ //bias impulse
Vector3 crbA = A->get_biased_angular_velocity().cross(c.rA);
Vector3 crbB = B->get_biased_angular_velocity().cross(c.rB);
@@ -372,8 +372,26 @@ void BodyPairSW::solve(real_t p_step) {
Vector3 jb = c.normal * (c.acc_bias_impulse - jbnOld);
- A->apply_bias_impulse(c.rA + A->get_center_of_mass(), -jb);
- B->apply_bias_impulse(c.rB + B->get_center_of_mass(), jb);
+ A->apply_bias_impulse(c.rA + A->get_center_of_mass(), -jb, MAX_BIAS_ROTATION / p_step);
+ B->apply_bias_impulse(c.rB + B->get_center_of_mass(), jb, MAX_BIAS_ROTATION / p_step);
+
+ crbA = A->get_biased_angular_velocity().cross(c.rA);
+ crbB = B->get_biased_angular_velocity().cross(c.rB);
+ dbv = B->get_biased_linear_velocity() + crbB - A->get_biased_linear_velocity() - crbA;
+
+ vbn = dbv.dot(c.normal);
+
+ if (Math::abs(-vbn + c.bias) > MIN_VELOCITY) {
+
+ real_t jbn_com = (-vbn + c.bias) / (A->get_inv_mass() + B->get_inv_mass());
+ real_t jbnOld_com = c.acc_bias_impulse_center_of_mass;
+ c.acc_bias_impulse_center_of_mass = MAX(jbnOld_com + jbn_com, 0.0f);
+
+ Vector3 jb_com = c.normal * (c.acc_bias_impulse_center_of_mass - jbnOld_com);
+
+ A->apply_bias_impulse(A->get_center_of_mass(), -jb_com, 0.0f);
+ B->apply_bias_impulse(B->get_center_of_mass(), jb_com, 0.0f);
+ }
c.active = true;
}
@@ -382,7 +400,7 @@ void BodyPairSW::solve(real_t p_step) {
Vector3 crB = B->get_angular_velocity().cross(c.rB);
Vector3 dv = B->get_linear_velocity() + crB - A->get_linear_velocity() - crA;
- //normal impule
+ //normal impulse
real_t vn = dv.dot(c.normal);
if (Math::abs(vn) > MIN_VELOCITY) {
@@ -399,7 +417,7 @@ void BodyPairSW::solve(real_t p_step) {
c.active = true;
}
- //friction impule
+ //friction impulse
real_t friction = A->get_friction() * B->get_friction();
diff --git a/servers/physics/body_pair_sw.h b/servers/physics/body_pair_sw.h
index f09c977950..74fda60998 100644
--- a/servers/physics/body_pair_sw.h
+++ b/servers/physics/body_pair_sw.h
@@ -59,6 +59,7 @@ class BodyPairSW : public ConstraintSW {
real_t acc_normal_impulse; // accumulated normal impulse (Pn)
Vector3 acc_tangent_impulse; // accumulated tangent impulse (Pt)
real_t acc_bias_impulse; // accumulated normal impulse for position bias (Pnb)
+ real_t acc_bias_impulse_center_of_mass; // accumulated normal impulse for position bias applied to com
real_t mass_normal;
real_t bias;
real_t bounce;
diff --git a/servers/physics/body_sw.cpp b/servers/physics/body_sw.cpp
index 46a5192e52..f8cd6ca858 100644
--- a/servers/physics/body_sw.cpp
+++ b/servers/physics/body_sw.cpp
@@ -45,8 +45,9 @@ void BodySW::_update_transform_dependant() {
// update inertia tensor
Basis tb = principal_inertia_axes;
Basis tbt = tb.transposed();
- tb.scale(_inv_inertia);
- _inv_inertia_tensor = tb * tbt;
+ Basis diag;
+ diag.scale(_inv_inertia);
+ _inv_inertia_tensor = tb * diag * tbt;
}
void BodySW::update_inertias() {
@@ -735,6 +736,10 @@ void BodySW::set_force_integration_callback(ObjectID p_id, const StringName &p_m
}
}
+void BodySW::set_kinematic_margin(real_t p_margin) {
+ kinematic_safe_margin = p_margin;
+}
+
BodySW::BodySW()
: CollisionObjectSW(TYPE_BODY), active_list(this), inertia_update_list(this), direct_state_query_list(this) {
@@ -742,6 +747,7 @@ BodySW::BodySW()
active = true;
mass = 1;
+ kinematic_safe_margin = 0.01;
//_inv_inertia=Transform();
_inv_mass = 1;
bounce = 0;
diff --git a/servers/physics/body_sw.h b/servers/physics/body_sw.h
index 782bf14a4b..738d99c764 100644
--- a/servers/physics/body_sw.h
+++ b/servers/physics/body_sw.h
@@ -55,6 +55,7 @@ class BodySW : public CollisionObjectSW {
PhysicsServer::BodyAxisLock axis_lock;
+ real_t kinematic_safe_margin;
real_t _inv_mass;
Vector3 _inv_inertia; // Relative to the principal axes of inertia
@@ -149,6 +150,9 @@ class BodySW : public CollisionObjectSW {
public:
void set_force_integration_callback(ObjectID p_id, const StringName &p_method, const Variant &p_udata = Variant());
+ void set_kinematic_margin(real_t p_margin);
+ _FORCE_INLINE_ real_t get_kinematic_margin() { return kinematic_safe_margin; }
+
_FORCE_INLINE_ void add_area(AreaSW *p_area) {
int index = areas.find(AreaCMP(p_area));
if (index > -1) {
@@ -223,10 +227,16 @@ public:
angular_velocity += _inv_inertia_tensor.xform(p_j);
}
- _FORCE_INLINE_ void apply_bias_impulse(const Vector3 &p_pos, const Vector3 &p_j) {
+ _FORCE_INLINE_ void apply_bias_impulse(const Vector3 &p_pos, const Vector3 &p_j, real_t p_max_delta_av = -1.0) {
biased_linear_velocity += p_j * _inv_mass;
- biased_angular_velocity += _inv_inertia_tensor.xform((p_pos - center_of_mass).cross(p_j));
+ if (p_max_delta_av != 0.0) {
+ Vector3 delta_av = _inv_inertia_tensor.xform((p_pos - center_of_mass).cross(p_j));
+ if (p_max_delta_av > 0 && delta_av.length() > p_max_delta_av) {
+ delta_av = delta_av.normalized() * p_max_delta_av;
+ }
+ biased_angular_velocity += delta_av;
+ }
}
_FORCE_INLINE_ void apply_bias_torque_impulse(const Vector3 &p_j) {
diff --git a/servers/physics/broad_phase_basic.cpp b/servers/physics/broad_phase_basic.cpp
index c6565ac2e9..e4eae09c61 100644
--- a/servers/physics/broad_phase_basic.cpp
+++ b/servers/physics/broad_phase_basic.cpp
@@ -46,7 +46,7 @@ BroadPhaseSW::ID BroadPhaseBasic::create(CollisionObjectSW *p_object, int p_subi
return current;
}
-void BroadPhaseBasic::move(ID p_id, const Rect3 &p_aabb) {
+void BroadPhaseBasic::move(ID p_id, const AABB &p_aabb) {
Map<ID, Element>::Element *E = element_map.find(p_id);
ERR_FAIL_COND(!E);
@@ -109,7 +109,7 @@ int BroadPhaseBasic::cull_point(const Vector3 &p_point, CollisionObjectSW **p_re
for (Map<ID, Element>::Element *E = element_map.front(); E; E = E->next()) {
- const Rect3 aabb = E->get().aabb;
+ const AABB aabb = E->get().aabb;
if (aabb.has_point(p_point)) {
p_results[rc] = E->get().owner;
@@ -129,7 +129,7 @@ int BroadPhaseBasic::cull_segment(const Vector3 &p_from, const Vector3 &p_to, Co
for (Map<ID, Element>::Element *E = element_map.front(); E; E = E->next()) {
- const Rect3 aabb = E->get().aabb;
+ const AABB aabb = E->get().aabb;
if (aabb.intersects_segment(p_from, p_to)) {
p_results[rc] = E->get().owner;
@@ -142,13 +142,13 @@ int BroadPhaseBasic::cull_segment(const Vector3 &p_from, const Vector3 &p_to, Co
return rc;
}
-int BroadPhaseBasic::cull_aabb(const Rect3 &p_aabb, CollisionObjectSW **p_results, int p_max_results, int *p_result_indices) {
+int BroadPhaseBasic::cull_aabb(const AABB &p_aabb, CollisionObjectSW **p_results, int p_max_results, int *p_result_indices) {
int rc = 0;
for (Map<ID, Element>::Element *E = element_map.front(); E; E = E->next()) {
- const Rect3 aabb = E->get().aabb;
+ const AABB aabb = E->get().aabb;
if (aabb.intersects(p_aabb)) {
p_results[rc] = E->get().owner;
diff --git a/servers/physics/broad_phase_basic.h b/servers/physics/broad_phase_basic.h
index 5c124c1792..ee683ed840 100644
--- a/servers/physics/broad_phase_basic.h
+++ b/servers/physics/broad_phase_basic.h
@@ -39,7 +39,7 @@ class BroadPhaseBasic : public BroadPhaseSW {
CollisionObjectSW *owner;
bool _static;
- Rect3 aabb;
+ AABB aabb;
int subindex;
};
@@ -83,7 +83,7 @@ class BroadPhaseBasic : public BroadPhaseSW {
public:
// 0 is an invalid ID
virtual ID create(CollisionObjectSW *p_object, int p_subindex = 0);
- virtual void move(ID p_id, const Rect3 &p_aabb);
+ virtual void move(ID p_id, const AABB &p_aabb);
virtual void set_static(ID p_id, bool p_static);
virtual void remove(ID p_id);
@@ -93,7 +93,7 @@ public:
virtual int cull_point(const Vector3 &p_point, CollisionObjectSW **p_results, int p_max_results, int *p_result_indices = NULL);
virtual int cull_segment(const Vector3 &p_from, const Vector3 &p_to, CollisionObjectSW **p_results, int p_max_results, int *p_result_indices = NULL);
- virtual int cull_aabb(const Rect3 &p_aabb, CollisionObjectSW **p_results, int p_max_results, int *p_result_indices = NULL);
+ virtual int cull_aabb(const AABB &p_aabb, CollisionObjectSW **p_results, int p_max_results, int *p_result_indices = NULL);
virtual void set_pair_callback(PairCallback p_pair_callback, void *p_userdata);
virtual void set_unpair_callback(UnpairCallback p_unpair_callback, void *p_userdata);
diff --git a/servers/physics/broad_phase_octree.cpp b/servers/physics/broad_phase_octree.cpp
index e7111d9580..3b18a270f0 100644
--- a/servers/physics/broad_phase_octree.cpp
+++ b/servers/physics/broad_phase_octree.cpp
@@ -32,11 +32,11 @@
BroadPhaseSW::ID BroadPhaseOctree::create(CollisionObjectSW *p_object, int p_subindex) {
- ID oid = octree.create(p_object, Rect3(), p_subindex, false, 1 << p_object->get_type(), 0);
+ ID oid = octree.create(p_object, AABB(), p_subindex, false, 1 << p_object->get_type(), 0);
return oid;
}
-void BroadPhaseOctree::move(ID p_id, const Rect3 &p_aabb) {
+void BroadPhaseOctree::move(ID p_id, const AABB &p_aabb) {
octree.move(p_id, p_aabb);
}
@@ -76,7 +76,7 @@ int BroadPhaseOctree::cull_segment(const Vector3 &p_from, const Vector3 &p_to, C
return octree.cull_segment(p_from, p_to, p_results, p_max_results, p_result_indices);
}
-int BroadPhaseOctree::cull_aabb(const Rect3 &p_aabb, CollisionObjectSW **p_results, int p_max_results, int *p_result_indices) {
+int BroadPhaseOctree::cull_aabb(const AABB &p_aabb, CollisionObjectSW **p_results, int p_max_results, int *p_result_indices) {
return octree.cull_aabb(p_aabb, p_results, p_max_results, p_result_indices);
}
diff --git a/servers/physics/broad_phase_octree.h b/servers/physics/broad_phase_octree.h
index d28f2da13f..f894d6ca5a 100644
--- a/servers/physics/broad_phase_octree.h
+++ b/servers/physics/broad_phase_octree.h
@@ -48,7 +48,7 @@ class BroadPhaseOctree : public BroadPhaseSW {
public:
// 0 is an invalid ID
virtual ID create(CollisionObjectSW *p_object, int p_subindex = 0);
- virtual void move(ID p_id, const Rect3 &p_aabb);
+ virtual void move(ID p_id, const AABB &p_aabb);
virtual void set_static(ID p_id, bool p_static);
virtual void remove(ID p_id);
@@ -58,7 +58,7 @@ public:
virtual int cull_point(const Vector3 &p_point, CollisionObjectSW **p_results, int p_max_results, int *p_result_indices = NULL);
virtual int cull_segment(const Vector3 &p_from, const Vector3 &p_to, CollisionObjectSW **p_results, int p_max_results, int *p_result_indices = NULL);
- virtual int cull_aabb(const Rect3 &p_aabb, CollisionObjectSW **p_results, int p_max_results, int *p_result_indices = NULL);
+ virtual int cull_aabb(const AABB &p_aabb, CollisionObjectSW **p_results, int p_max_results, int *p_result_indices = NULL);
virtual void set_pair_callback(PairCallback p_pair_callback, void *p_userdata);
virtual void set_unpair_callback(UnpairCallback p_unpair_callback, void *p_userdata);
diff --git a/servers/physics/broad_phase_sw.h b/servers/physics/broad_phase_sw.h
index 2b5ed629fe..5ad3f9a261 100644
--- a/servers/physics/broad_phase_sw.h
+++ b/servers/physics/broad_phase_sw.h
@@ -30,8 +30,8 @@
#ifndef BROAD_PHASE_SW_H
#define BROAD_PHASE_SW_H
+#include "aabb.h"
#include "math_funcs.h"
-#include "rect3.h"
class CollisionObjectSW;
@@ -49,7 +49,7 @@ public:
// 0 is an invalid ID
virtual ID create(CollisionObjectSW *p_object_, int p_subindex = 0) = 0;
- virtual void move(ID p_id, const Rect3 &p_aabb) = 0;
+ virtual void move(ID p_id, const AABB &p_aabb) = 0;
virtual void set_static(ID p_id, bool p_static) = 0;
virtual void remove(ID p_id) = 0;
@@ -59,7 +59,7 @@ public:
virtual int cull_point(const Vector3 &p_point, CollisionObjectSW **p_results, int p_max_results, int *p_result_indices = NULL) = 0;
virtual int cull_segment(const Vector3 &p_from, const Vector3 &p_to, CollisionObjectSW **p_results, int p_max_results, int *p_result_indices = NULL) = 0;
- virtual int cull_aabb(const Rect3 &p_aabb, CollisionObjectSW **p_results, int p_max_results, int *p_result_indices = NULL) = 0;
+ virtual int cull_aabb(const AABB &p_aabb, CollisionObjectSW **p_results, int p_max_results, int *p_result_indices = NULL) = 0;
virtual void set_pair_callback(PairCallback p_pair_callback, void *p_userdata) = 0;
virtual void set_unpair_callback(UnpairCallback p_unpair_callback, void *p_userdata) = 0;
diff --git a/servers/physics/collision_object_sw.cpp b/servers/physics/collision_object_sw.cpp
index 3af8b542fa..126f8141ff 100644
--- a/servers/physics/collision_object_sw.cpp
+++ b/servers/physics/collision_object_sw.cpp
@@ -149,7 +149,7 @@ void CollisionObjectSW::_update_shapes() {
}
//not quite correct, should compute the next matrix..
- Rect3 shape_aabb = s.shape->get_aabb();
+ AABB shape_aabb = s.shape->get_aabb();
Transform xform = transform * s.xform;
shape_aabb = xform.xform(shape_aabb);
s.aabb_cache = shape_aabb;
@@ -176,10 +176,10 @@ void CollisionObjectSW::_update_shapes_with_motion(const Vector3 &p_motion) {
}
//not quite correct, should compute the next matrix..
- Rect3 shape_aabb = s.shape->get_aabb();
+ AABB shape_aabb = s.shape->get_aabb();
Transform xform = transform * s.xform;
shape_aabb = xform.xform(shape_aabb);
- shape_aabb = shape_aabb.merge(Rect3(shape_aabb.position + p_motion, shape_aabb.size)); //use motion
+ shape_aabb = shape_aabb.merge(AABB(shape_aabb.position + p_motion, shape_aabb.size)); //use motion
s.aabb_cache = shape_aabb;
space->get_broadphase()->move(s.bpid, shape_aabb);
diff --git a/servers/physics/collision_object_sw.h b/servers/physics/collision_object_sw.h
index 67a8a44944..254947060b 100644
--- a/servers/physics/collision_object_sw.h
+++ b/servers/physics/collision_object_sw.h
@@ -61,7 +61,7 @@ private:
Transform xform;
Transform xform_inv;
BroadPhaseSW::ID bpid;
- Rect3 aabb_cache; //for rayqueries
+ AABB aabb_cache; //for rayqueries
real_t area_cache;
ShapeSW *shape;
bool disabled;
@@ -123,7 +123,7 @@ public:
_FORCE_INLINE_ ShapeSW *get_shape(int p_index) const { return shapes[p_index].shape; }
_FORCE_INLINE_ const Transform &get_shape_transform(int p_index) const { return shapes[p_index].xform; }
_FORCE_INLINE_ const Transform &get_shape_inv_transform(int p_index) const { return shapes[p_index].xform_inv; }
- _FORCE_INLINE_ const Rect3 &get_shape_aabb(int p_index) const { return shapes[p_index].aabb_cache; }
+ _FORCE_INLINE_ const AABB &get_shape_aabb(int p_index) const { return shapes[p_index].aabb_cache; }
_FORCE_INLINE_ const real_t get_shape_area(int p_index) const { return shapes[p_index].area_cache; }
_FORCE_INLINE_ Transform get_transform() const { return transform; }
diff --git a/servers/physics/collision_solver_sw.cpp b/servers/physics/collision_solver_sw.cpp
index 7bef208237..a9431dc6d8 100644
--- a/servers/physics/collision_solver_sw.cpp
+++ b/servers/physics/collision_solver_sw.cpp
@@ -152,7 +152,7 @@ bool CollisionSolverSW::solve_concave(const ShapeSW *p_shape_A, const Transform
//quickly compute a local AABB
- Rect3 local_aabb;
+ AABB local_aabb;
for (int i = 0; i < 3; i++) {
Vector3 axis(p_transform_B.basis.get_axis(i));
@@ -291,7 +291,7 @@ bool CollisionSolverSW::solve_distance_plane(const ShapeSW *p_shape_A, const Tra
return collided;
}
-bool CollisionSolverSW::solve_distance(const ShapeSW *p_shape_A, const Transform &p_transform_A, const ShapeSW *p_shape_B, const Transform &p_transform_B, Vector3 &r_point_A, Vector3 &r_point_B, const Rect3 &p_concave_hint, Vector3 *r_sep_axis) {
+bool CollisionSolverSW::solve_distance(const ShapeSW *p_shape_A, const Transform &p_transform_A, const ShapeSW *p_shape_B, const Transform &p_transform_B, Vector3 &r_point_A, Vector3 &r_point_B, const AABB &p_concave_hint, Vector3 *r_sep_axis) {
if (p_shape_A->is_concave())
return false;
@@ -328,14 +328,14 @@ bool CollisionSolverSW::solve_distance(const ShapeSW *p_shape_A, const Transform
//quickly compute a local AABB
- bool use_cc_hint = p_concave_hint != Rect3();
- Rect3 cc_hint_aabb;
+ bool use_cc_hint = p_concave_hint != AABB();
+ AABB cc_hint_aabb;
if (use_cc_hint) {
cc_hint_aabb = p_concave_hint;
cc_hint_aabb.position -= p_transform_B.origin;
}
- Rect3 local_aabb;
+ AABB local_aabb;
for (int i = 0; i < 3; i++) {
Vector3 axis(p_transform_B.basis.get_axis(i));
diff --git a/servers/physics/collision_solver_sw.h b/servers/physics/collision_solver_sw.h
index 1e38b1b54e..a40b665ff0 100644
--- a/servers/physics/collision_solver_sw.h
+++ b/servers/physics/collision_solver_sw.h
@@ -46,7 +46,7 @@ private:
public:
static bool solve_static(const ShapeSW *p_shape_A, const Transform &p_transform_A, const ShapeSW *p_shape_B, const Transform &p_transform_B, CallbackResult p_result_callback, void *p_userdata, Vector3 *r_sep_axis = NULL, real_t p_margin_A = 0, real_t p_margin_B = 0);
- static bool solve_distance(const ShapeSW *p_shape_A, const Transform &p_transform_A, const ShapeSW *p_shape_B, const Transform &p_transform_B, Vector3 &r_point_A, Vector3 &r_point_B, const Rect3 &p_concave_hint, Vector3 *r_sep_axis = NULL);
+ static bool solve_distance(const ShapeSW *p_shape_A, const Transform &p_transform_A, const ShapeSW *p_shape_B, const Transform &p_transform_B, Vector3 &r_point_A, Vector3 &r_point_B, const AABB &p_concave_hint, Vector3 *r_sep_axis = NULL);
};
#endif // COLLISION_SOLVER__SW_H
diff --git a/servers/physics/joints/generic_6dof_joint_sw.cpp b/servers/physics/joints/generic_6dof_joint_sw.cpp
index 70cc549e2d..1e323be36c 100644
--- a/servers/physics/joints/generic_6dof_joint_sw.cpp
+++ b/servers/physics/joints/generic_6dof_joint_sw.cpp
@@ -219,9 +219,9 @@ Generic6DOFJointSW::Generic6DOFJointSW(BodySW *rbA, BodySW *rbB, const Transform
}
void Generic6DOFJointSW::calculateAngleInfo() {
- Basis relative_frame = m_calculatedTransformA.basis.inverse() * m_calculatedTransformB.basis;
+ Basis relative_frame = m_calculatedTransformB.basis.inverse() * m_calculatedTransformA.basis;
- m_calculatedAxisAngleDiff = relative_frame.get_euler();
+ m_calculatedAxisAngleDiff = relative_frame.get_euler_xyz();
// in euler angle mode we do not actually constrain the angular velocity
// along the axes axis[0] and axis[2] (although we do use axis[1]) :
diff --git a/servers/physics/joints/pin_joint_sw.h b/servers/physics/joints/pin_joint_sw.h
index ee9272ce06..f6c11c49b0 100644
--- a/servers/physics/joints/pin_joint_sw.h
+++ b/servers/physics/joints/pin_joint_sw.h
@@ -86,8 +86,8 @@ public:
void set_pos_a(const Vector3 &p_pos) { m_pivotInA = p_pos; }
void set_pos_b(const Vector3 &p_pos) { m_pivotInB = p_pos; }
- Vector3 get_position_a() { return m_pivotInB; }
- Vector3 get_position_b() { return m_pivotInA; }
+ Vector3 get_position_a() { return m_pivotInA; }
+ Vector3 get_position_b() { return m_pivotInB; }
PinJointSW(BodySW *p_body_a, const Vector3 &p_pos_a, BodySW *p_body_b, const Vector3 &p_pos_b);
~PinJointSW();
diff --git a/servers/physics/physics_server_sw.cpp b/servers/physics/physics_server_sw.cpp
index 1553c3c8e6..ce63d84617 100644
--- a/servers/physics/physics_server_sw.cpp
+++ b/servers/physics/physics_server_sw.cpp
@@ -233,14 +233,7 @@ void PhysicsServerSW::area_set_space(RID p_area, RID p_space) {
if (area->get_space() == space)
return; //pointless
- for (Set<ConstraintSW *>::Element *E = area->get_constraints().front(); E; E = E->next()) {
- RID self = E->get()->get_self();
- if (!self.is_valid())
- continue;
- free(self);
- }
area->clear_constraints();
-
area->set_space(space);
};
@@ -494,14 +487,7 @@ void PhysicsServerSW::body_set_space(RID p_body, RID p_space) {
if (body->get_space() == space)
return; //pointless
- for (Map<ConstraintSW *, int>::Element *E = body->get_constraint_map().front(); E; E = E->next()) {
- RID self = E->key()->get_self();
- if (!self.is_valid())
- continue;
- free(self);
- }
body->clear_constraint_map();
-
body->set_space(space);
};
@@ -709,6 +695,19 @@ real_t PhysicsServerSW::body_get_param(RID p_body, BodyParameter p_param) const
return body->get_param(p_param);
};
+void PhysicsServerSW::body_set_kinematic_safe_margin(RID p_body, real_t p_margin) {
+ BodySW *body = body_owner.get(p_body);
+ ERR_FAIL_COND(!body);
+ body->set_kinematic_margin(p_margin);
+}
+
+real_t PhysicsServerSW::body_get_kinematic_safe_margin(RID p_body) const {
+ BodySW *body = body_owner.get(p_body);
+ ERR_FAIL_COND_V(!body, 0);
+
+ return body->get_kinematic_margin();
+}
+
void PhysicsServerSW::body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) {
BodySW *body = body_owner.get(p_body);
@@ -902,7 +901,7 @@ bool PhysicsServerSW::body_is_ray_pickable(RID p_body) const {
return body->is_ray_pickable();
}
-bool PhysicsServerSW::body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, float p_margin, MotionResult *r_result) {
+bool PhysicsServerSW::body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, MotionResult *r_result) {
BodySW *body = body_owner.get(p_body);
ERR_FAIL_COND_V(!body, false);
@@ -911,7 +910,22 @@ bool PhysicsServerSW::body_test_motion(RID p_body, const Transform &p_from, cons
_update_shapes();
- return body->get_space()->test_body_motion(body, p_from, p_motion, p_margin, r_result);
+ return body->get_space()->test_body_motion(body, p_from, p_motion, body->get_kinematic_margin(), r_result);
+}
+
+PhysicsDirectBodyState *PhysicsServerSW::body_get_direct_state(RID p_body) {
+
+ BodySW *body = body_owner.get(p_body);
+ ERR_FAIL_COND_V(!body, NULL);
+
+ if (!doing_sync || body->get_space()->is_locked()) {
+
+ ERR_EXPLAIN("Body state is inaccessible right now, wait for iteration or physics process notification.");
+ ERR_FAIL_V(NULL);
+ }
+
+ direct_state->body = body;
+ return direct_state;
}
/* JOINT API */
diff --git a/servers/physics/physics_server_sw.h b/servers/physics/physics_server_sw.h
index aea3e150b0..fa754a1c8f 100644
--- a/servers/physics/physics_server_sw.h
+++ b/servers/physics/physics_server_sw.h
@@ -187,6 +187,9 @@ public:
virtual void body_set_param(RID p_body, BodyParameter p_param, real_t p_value);
virtual real_t body_get_param(RID p_body, BodyParameter p_param) const;
+ virtual void body_set_kinematic_safe_margin(RID p_body, real_t p_margin);
+ virtual real_t body_get_kinematic_safe_margin(RID p_body) const;
+
virtual void body_set_state(RID p_body, BodyState p_state, const Variant &p_variant);
virtual Variant body_get_state(RID p_body, BodyState p_state) const;
@@ -221,7 +224,10 @@ public:
virtual void body_set_ray_pickable(RID p_body, bool p_enable);
virtual bool body_is_ray_pickable(RID p_body) const;
- virtual bool body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, float p_margin = 0.001, MotionResult *r_result = NULL);
+ virtual bool body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, MotionResult *r_result = NULL);
+
+ // this function only works on physics process, errors and returns null otherwise
+ virtual PhysicsDirectBodyState *body_get_direct_state(RID p_body);
/* JOINT API */
diff --git a/servers/physics/shape_sw.cpp b/servers/physics/shape_sw.cpp
index 6dafaac115..b204ff7a33 100644
--- a/servers/physics/shape_sw.cpp
+++ b/servers/physics/shape_sw.cpp
@@ -37,7 +37,7 @@
#define _EDGE_IS_VALID_SUPPORT_THRESHOLD 0.0002
#define _FACE_IS_VALID_SUPPORT_THRESHOLD 0.9998
-void ShapeSW::configure(const Rect3 &p_aabb) {
+void ShapeSW::configure(const AABB &p_aabb) {
aabb = p_aabb;
configured = true;
for (Map<ShapeOwnerSW *, int>::Element *E = owners.front(); E; E = E->next()) {
@@ -141,7 +141,7 @@ Vector3 PlaneShapeSW::get_moment_of_inertia(real_t p_mass) const {
void PlaneShapeSW::_setup(const Plane &p_plane) {
plane = p_plane;
- configure(Rect3(Vector3(-1e4, -1e4, -1e4), Vector3(1e4 * 2, 1e4 * 2, 1e4 * 2)));
+ configure(AABB(Vector3(-1e4, -1e4, -1e4), Vector3(1e4 * 2, 1e4 * 2, 1e4 * 2)));
}
void PlaneShapeSW::set_data(const Variant &p_data) {
@@ -223,7 +223,7 @@ Vector3 RayShapeSW::get_moment_of_inertia(real_t p_mass) const {
void RayShapeSW::_setup(real_t p_length) {
length = p_length;
- configure(Rect3(Vector3(0, 0, 0), Vector3(0.1, 0.1, length)));
+ configure(AABB(Vector3(0, 0, 0), Vector3(0.1, 0.1, length)));
}
void RayShapeSW::set_data(const Variant &p_data) {
@@ -299,7 +299,7 @@ Vector3 SphereShapeSW::get_moment_of_inertia(real_t p_mass) const {
void SphereShapeSW::_setup(real_t p_radius) {
radius = p_radius;
- configure(Rect3(Vector3(-radius, -radius, -radius), Vector3(radius * 2.0, radius * 2.0, radius * 2.0)));
+ configure(AABB(Vector3(-radius, -radius, -radius), Vector3(radius * 2.0, radius * 2.0, radius * 2.0)));
}
void SphereShapeSW::set_data(const Variant &p_data) {
@@ -430,7 +430,7 @@ void BoxShapeSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_sup
bool BoxShapeSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const {
- Rect3 aabb(-half_extents, half_extents * 2.0);
+ AABB aabb(-half_extents, half_extents * 2.0);
return aabb.intersects_segment(p_begin, p_end, &r_result, &r_normal);
}
@@ -504,7 +504,7 @@ void BoxShapeSW::_setup(const Vector3 &p_half_extents) {
half_extents = p_half_extents.abs();
- configure(Rect3(-half_extents, half_extents * 2));
+ configure(AABB(-half_extents, half_extents * 2));
}
void BoxShapeSW::set_data(const Variant &p_data) {
@@ -684,7 +684,7 @@ void CapsuleShapeSW::_setup(real_t p_height, real_t p_radius) {
height = p_height;
radius = p_radius;
- configure(Rect3(Vector3(-radius, -radius, -height * 0.5 - radius), Vector3(radius * 2, radius * 2, height + radius * 2.0)));
+ configure(AABB(Vector3(-radius, -radius, -height * 0.5 - radius), Vector3(radius * 2, radius * 2, height + radius * 2.0)));
}
void CapsuleShapeSW::set_data(const Variant &p_data) {
@@ -957,7 +957,7 @@ void ConvexPolygonShapeSW::_setup(const Vector<Vector3> &p_vertices) {
if (err != OK)
ERR_PRINT("Failed to build QuickHull");
- Rect3 _aabb;
+ AABB _aabb;
for (int i = 0; i < mesh.vertices.size(); i++) {
@@ -1102,7 +1102,7 @@ Vector3 FaceShapeSW::get_moment_of_inertia(real_t p_mass) const {
FaceShapeSW::FaceShapeSW() {
- configure(Rect3());
+ configure(AABB());
}
PoolVector<Vector3> ConcavePolygonShapeSW::get_faces() const {
@@ -1300,13 +1300,13 @@ void ConcavePolygonShapeSW::_cull(int p_idx, _CullParams *p_params) const {
}
}
-void ConcavePolygonShapeSW::cull(const Rect3 &p_local_aabb, Callback p_callback, void *p_userdata) const {
+void ConcavePolygonShapeSW::cull(const AABB &p_local_aabb, Callback p_callback, void *p_userdata) const {
// make matrix local to concave
if (faces.size() == 0)
return;
- Rect3 local_aabb = p_local_aabb;
+ AABB local_aabb = p_local_aabb;
// unlock data
PoolVector<Face>::Read fr = faces.read();
@@ -1341,7 +1341,7 @@ Vector3 ConcavePolygonShapeSW::get_moment_of_inertia(real_t p_mass) const {
struct _VolumeSW_BVH_Element {
- Rect3 aabb;
+ AABB aabb;
Vector3 center;
int face_index;
};
@@ -1372,7 +1372,7 @@ struct _VolumeSW_BVH_CompareZ {
struct _VolumeSW_BVH {
- Rect3 aabb;
+ AABB aabb;
_VolumeSW_BVH *left;
_VolumeSW_BVH *right;
@@ -1396,7 +1396,7 @@ _VolumeSW_BVH *_volume_sw_build_bvh(_VolumeSW_BVH_Element *p_elements, int p_siz
bvh->face_index = -1;
}
- Rect3 aabb;
+ AABB aabb;
for (int i = 0; i < p_size; i++) {
if (i == 0)
@@ -1467,7 +1467,7 @@ void ConcavePolygonShapeSW::_setup(PoolVector<Vector3> p_faces) {
int src_face_count = p_faces.size();
if (src_face_count == 0) {
- configure(Rect3());
+ configure(AABB());
return;
}
ERR_FAIL_COND(src_face_count % 3);
@@ -1491,7 +1491,7 @@ void ConcavePolygonShapeSW::_setup(PoolVector<Vector3> p_faces) {
PoolVector<Vector3>::Write vw = vertices.write();
Vector3 *verticesw = vw.ptr();
- Rect3 _aabb;
+ AABB _aabb;
for (int i = 0; i < src_face_count; i++) {
@@ -1588,7 +1588,7 @@ Vector3 HeightMapShapeSW::get_closest_point_to(const Vector3 &p_point) const {
return Vector3();
}
-void HeightMapShapeSW::cull(const Rect3 &p_local_aabb, Callback p_callback, void *p_userdata) const {
+void HeightMapShapeSW::cull(const AABB &p_local_aabb, Callback p_callback, void *p_userdata) const {
}
Vector3 HeightMapShapeSW::get_moment_of_inertia(real_t p_mass) const {
@@ -1611,7 +1611,7 @@ void HeightMapShapeSW::_setup(PoolVector<real_t> p_heights, int p_width, int p_d
PoolVector<real_t>::Read r = heights.read();
- Rect3 aabb;
+ AABB aabb;
for (int i = 0; i < depth; i++) {
diff --git a/servers/physics/shape_sw.h b/servers/physics/shape_sw.h
index 151b84c054..48832affc9 100644
--- a/servers/physics/shape_sw.h
+++ b/servers/physics/shape_sw.h
@@ -58,14 +58,14 @@ public:
class ShapeSW : public RID_Data {
RID self;
- Rect3 aabb;
+ AABB aabb;
bool configured;
real_t custom_bias;
Map<ShapeOwnerSW *, int> owners;
protected:
- void configure(const Rect3 &p_aabb);
+ void configure(const AABB &p_aabb);
public:
enum {
@@ -79,7 +79,7 @@ public:
virtual PhysicsServer::ShapeType get_type() const = 0;
- _FORCE_INLINE_ Rect3 get_aabb() const { return aabb; }
+ _FORCE_INLINE_ AABB get_aabb() const { return aabb; }
_FORCE_INLINE_ bool is_configured() const { return configured; }
virtual bool is_concave() const { return false; }
@@ -114,7 +114,7 @@ public:
typedef void (*Callback)(void *p_userdata, ShapeSW *p_convex);
virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const { r_amount = 0; }
- virtual void cull(const Rect3 &p_local_aabb, Callback p_callback, void *p_userdata) const = 0;
+ virtual void cull(const AABB &p_local_aabb, Callback p_callback, void *p_userdata) const = 0;
ConcaveShapeSW() {}
};
@@ -299,7 +299,7 @@ struct ConcavePolygonShapeSW : public ConcaveShapeSW {
struct BVH {
- Rect3 aabb;
+ AABB aabb;
int left;
int right;
@@ -310,7 +310,7 @@ struct ConcavePolygonShapeSW : public ConcaveShapeSW {
struct _CullParams {
- Rect3 aabb;
+ AABB aabb;
Callback callback;
void *userdata;
const Face *faces;
@@ -353,7 +353,7 @@ public:
virtual bool intersect_point(const Vector3 &p_point) const;
virtual Vector3 get_closest_point_to(const Vector3 &p_point) const;
- virtual void cull(const Rect3 &p_local_aabb, Callback p_callback, void *p_userdata) const;
+ virtual void cull(const AABB &p_local_aabb, Callback p_callback, void *p_userdata) const;
virtual Vector3 get_moment_of_inertia(real_t p_mass) const;
@@ -389,7 +389,7 @@ public:
virtual bool intersect_point(const Vector3 &p_point) const;
virtual Vector3 get_closest_point_to(const Vector3 &p_point) const;
- virtual void cull(const Rect3 &p_local_aabb, Callback p_callback, void *p_userdata) const;
+ virtual void cull(const AABB &p_local_aabb, Callback p_callback, void *p_userdata) const;
virtual Vector3 get_moment_of_inertia(real_t p_mass) const;
@@ -462,7 +462,7 @@ struct MotionShapeSW : public ShapeSW {
virtual void set_data(const Variant &p_data) {}
virtual Variant get_data() const { return Variant(); }
- MotionShapeSW() { configure(Rect3()); }
+ MotionShapeSW() { configure(AABB()); }
};
struct _ShapeTestConvexBSPSW {
diff --git a/servers/physics/space_sw.cpp b/servers/physics/space_sw.cpp
index 17e2df6c9e..a6426b7ee0 100644
--- a/servers/physics/space_sw.cpp
+++ b/servers/physics/space_sw.cpp
@@ -33,9 +33,9 @@
#include "physics_server_sw.h"
#include "project_settings.h"
-_FORCE_INLINE_ static bool _match_object_type_query(CollisionObjectSW *p_object, uint32_t p_collision_layer, uint32_t p_type_mask) {
+_FORCE_INLINE_ static bool _match_object_type_query(CollisionObjectSW *p_object, uint32_t p_collision_mask, uint32_t p_type_mask) {
- if ((p_object->get_collision_layer() & p_collision_layer) == 0)
+ if ((p_object->get_collision_layer() & p_collision_mask) == 0)
return false;
if (p_object->get_type() == CollisionObjectSW::TYPE_AREA)
@@ -46,7 +46,7 @@ _FORCE_INLINE_ static bool _match_object_type_query(CollisionObjectSW *p_object,
return (1 << body->get_mode()) & p_type_mask;
}
-int PhysicsDirectSpaceStateSW::intersect_point(const Vector3 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_layer, uint32_t p_object_type_mask) {
+int PhysicsDirectSpaceStateSW::intersect_point(const Vector3 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, uint32_t p_object_type_mask) {
ERR_FAIL_COND_V(space->locked, false);
int amount = space->broadphase->cull_point(p_point, space->intersection_query_results, SpaceSW::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results);
@@ -59,7 +59,7 @@ int PhysicsDirectSpaceStateSW::intersect_point(const Vector3 &p_point, ShapeResu
if (cc >= p_result_max)
break;
- if (!_match_object_type_query(space->intersection_query_results[i], p_collision_layer, p_object_type_mask))
+ if (!_match_object_type_query(space->intersection_query_results[i], p_collision_mask, p_object_type_mask))
continue;
//area can't be picked by ray (default)
@@ -90,7 +90,7 @@ int PhysicsDirectSpaceStateSW::intersect_point(const Vector3 &p_point, ShapeResu
return cc;
}
-bool PhysicsDirectSpaceStateSW::intersect_ray(const Vector3 &p_from, const Vector3 &p_to, RayResult &r_result, const Set<RID> &p_exclude, uint32_t p_collision_layer, uint32_t p_object_type_mask, bool p_pick_ray) {
+bool PhysicsDirectSpaceStateSW::intersect_ray(const Vector3 &p_from, const Vector3 &p_to, RayResult &r_result, const Set<RID> &p_exclude, uint32_t p_collision_mask, uint32_t p_object_type_mask, bool p_pick_ray) {
ERR_FAIL_COND_V(space->locked, false);
@@ -112,7 +112,7 @@ bool PhysicsDirectSpaceStateSW::intersect_ray(const Vector3 &p_from, const Vecto
for (int i = 0; i < amount; i++) {
- if (!_match_object_type_query(space->intersection_query_results[i], p_collision_layer, p_object_type_mask))
+ if (!_match_object_type_query(space->intersection_query_results[i], p_collision_mask, p_object_type_mask))
continue;
if (p_pick_ray && !(static_cast<CollisionObjectSW *>(space->intersection_query_results[i])->is_ray_pickable()))
@@ -168,7 +168,7 @@ bool PhysicsDirectSpaceStateSW::intersect_ray(const Vector3 &p_from, const Vecto
return true;
}
-int PhysicsDirectSpaceStateSW::intersect_shape(const RID &p_shape, const Transform &p_xform, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_layer, uint32_t p_object_type_mask) {
+int PhysicsDirectSpaceStateSW::intersect_shape(const RID &p_shape, const Transform &p_xform, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, uint32_t p_object_type_mask) {
if (p_result_max <= 0)
return 0;
@@ -176,7 +176,7 @@ int PhysicsDirectSpaceStateSW::intersect_shape(const RID &p_shape, const Transfo
ShapeSW *shape = static_cast<PhysicsServerSW *>(PhysicsServer::get_singleton())->shape_owner.get(p_shape);
ERR_FAIL_COND_V(!shape, 0);
- Rect3 aabb = p_xform.xform(shape->get_aabb());
+ AABB aabb = p_xform.xform(shape->get_aabb());
int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, SpaceSW::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results);
@@ -189,7 +189,7 @@ int PhysicsDirectSpaceStateSW::intersect_shape(const RID &p_shape, const Transfo
if (cc >= p_result_max)
break;
- if (!_match_object_type_query(space->intersection_query_results[i], p_collision_layer, p_object_type_mask))
+ if (!_match_object_type_query(space->intersection_query_results[i], p_collision_mask, p_object_type_mask))
continue;
//area can't be picked by ray (default)
@@ -219,13 +219,13 @@ int PhysicsDirectSpaceStateSW::intersect_shape(const RID &p_shape, const Transfo
return cc;
}
-bool PhysicsDirectSpaceStateSW::cast_motion(const RID &p_shape, const Transform &p_xform, const Vector3 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude, uint32_t p_collision_layer, uint32_t p_object_type_mask, ShapeRestInfo *r_info) {
+bool PhysicsDirectSpaceStateSW::cast_motion(const RID &p_shape, const Transform &p_xform, const Vector3 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude, uint32_t p_collision_mask, uint32_t p_object_type_mask, ShapeRestInfo *r_info) {
ShapeSW *shape = static_cast<PhysicsServerSW *>(PhysicsServer::get_singleton())->shape_owner.get(p_shape);
ERR_FAIL_COND_V(!shape, false);
- Rect3 aabb = p_xform.xform(shape->get_aabb());
- aabb = aabb.merge(Rect3(aabb.position + p_motion, aabb.size)); //motion
+ AABB aabb = p_xform.xform(shape->get_aabb());
+ aabb = aabb.merge(AABB(aabb.position + p_motion, aabb.size)); //motion
aabb = aabb.grow(p_margin);
/*
@@ -249,7 +249,7 @@ bool PhysicsDirectSpaceStateSW::cast_motion(const RID &p_shape, const Transform
for (int i = 0; i < amount; i++) {
- if (!_match_object_type_query(space->intersection_query_results[i], p_collision_layer, p_object_type_mask))
+ if (!_match_object_type_query(space->intersection_query_results[i], p_collision_mask, p_object_type_mask))
continue;
if (p_exclude.has(space->intersection_query_results[i]->get_self()))
@@ -333,7 +333,7 @@ bool PhysicsDirectSpaceStateSW::cast_motion(const RID &p_shape, const Transform
return true;
}
-bool PhysicsDirectSpaceStateSW::collide_shape(RID p_shape, const Transform &p_shape_xform, real_t p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude, uint32_t p_collision_layer, uint32_t p_object_type_mask) {
+bool PhysicsDirectSpaceStateSW::collide_shape(RID p_shape, const Transform &p_shape_xform, real_t p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude, uint32_t p_collision_mask, uint32_t p_object_type_mask) {
if (p_result_max <= 0)
return 0;
@@ -341,7 +341,7 @@ bool PhysicsDirectSpaceStateSW::collide_shape(RID p_shape, const Transform &p_sh
ShapeSW *shape = static_cast<PhysicsServerSW *>(PhysicsServer::get_singleton())->shape_owner.get(p_shape);
ERR_FAIL_COND_V(!shape, 0);
- Rect3 aabb = p_shape_xform.xform(shape->get_aabb());
+ AABB aabb = p_shape_xform.xform(shape->get_aabb());
aabb = aabb.grow(p_margin);
int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, SpaceSW::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results);
@@ -363,7 +363,7 @@ bool PhysicsDirectSpaceStateSW::collide_shape(RID p_shape, const Transform &p_sh
for (int i = 0; i < amount; i++) {
- if (!_match_object_type_query(space->intersection_query_results[i], p_collision_layer, p_object_type_mask))
+ if (!_match_object_type_query(space->intersection_query_results[i], p_collision_mask, p_object_type_mask))
continue;
const CollisionObjectSW *col_obj = space->intersection_query_results[i];
@@ -412,12 +412,12 @@ static void _rest_cbk_result(const Vector3 &p_point_A, const Vector3 &p_point_B,
rd->best_object = rd->object;
rd->best_shape = rd->shape;
}
-bool PhysicsDirectSpaceStateSW::rest_info(RID p_shape, const Transform &p_shape_xform, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude, uint32_t p_collision_layer, uint32_t p_object_type_mask) {
+bool PhysicsDirectSpaceStateSW::rest_info(RID p_shape, const Transform &p_shape_xform, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude, uint32_t p_collision_mask, uint32_t p_object_type_mask) {
ShapeSW *shape = static_cast<PhysicsServerSW *>(PhysicsServer::get_singleton())->shape_owner.get(p_shape);
ERR_FAIL_COND_V(!shape, 0);
- Rect3 aabb = p_shape_xform.xform(shape->get_aabb());
+ AABB aabb = p_shape_xform.xform(shape->get_aabb());
aabb = aabb.grow(p_margin);
int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, SpaceSW::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results);
@@ -429,7 +429,7 @@ bool PhysicsDirectSpaceStateSW::rest_info(RID p_shape, const Transform &p_shape_
for (int i = 0; i < amount; i++) {
- if (!_match_object_type_query(space->intersection_query_results[i], p_collision_layer, p_object_type_mask))
+ if (!_match_object_type_query(space->intersection_query_results[i], p_collision_mask, p_object_type_mask))
continue;
const CollisionObjectSW *col_obj = space->intersection_query_results[i];
@@ -514,7 +514,7 @@ PhysicsDirectSpaceStateSW::PhysicsDirectSpaceStateSW() {
////////////////////////////////////////////////////////////////////////////////////////////////////////////
-int SpaceSW::_cull_aabb_for_body(BodySW *p_body, const Rect3 &p_aabb) {
+int SpaceSW::_cull_aabb_for_body(BodySW *p_body, const AABB &p_aabb) {
int amount = broadphase->cull_aabb(p_aabb, intersection_query_results, INTERSECTION_QUERY_MAX, intersection_query_subindex_results);
@@ -561,7 +561,7 @@ bool SpaceSW::test_body_motion(BodySW *p_body, const Transform &p_from, const Ve
r_result->collider_id = 0;
r_result->collider_shape = 0;
}
- Rect3 body_aabb;
+ AABB body_aabb;
for (int i = 0; i < p_body->get_shape_count(); i++) {
@@ -648,7 +648,7 @@ bool SpaceSW::test_body_motion(BodySW *p_body, const Transform &p_from, const Ve
{
// STEP 2 ATTEMPT MOTION
- Rect3 motion_aabb = body_aabb;
+ AABB motion_aabb = body_aabb;
motion_aabb.position += p_motion;
motion_aabb = motion_aabb.merge(body_aabb);
@@ -956,15 +956,15 @@ void SpaceSW::call_queries() {
while (state_query_list.first()) {
BodySW *b = state_query_list.first()->self();
- b->call_queries();
state_query_list.remove(state_query_list.first());
+ b->call_queries();
}
while (monitor_query_list.first()) {
AreaSW *a = monitor_query_list.first()->self();
- a->call_queries();
monitor_query_list.remove(monitor_query_list.first());
+ a->call_queries();
}
}
diff --git a/servers/physics/space_sw.h b/servers/physics/space_sw.h
index 56f4d2f10d..fd7e6d16a9 100644
--- a/servers/physics/space_sw.h
+++ b/servers/physics/space_sw.h
@@ -47,12 +47,12 @@ class PhysicsDirectSpaceStateSW : public PhysicsDirectSpaceState {
public:
SpaceSW *space;
- virtual int intersect_point(const Vector3 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, uint32_t p_object_type_mask = TYPE_MASK_COLLISION);
- virtual bool intersect_ray(const Vector3 &p_from, const Vector3 &p_to, RayResult &r_result, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, uint32_t p_object_type_mask = TYPE_MASK_COLLISION, bool p_pick_ray = false);
- virtual int intersect_shape(const RID &p_shape, const Transform &p_xform, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, uint32_t p_object_type_mask = TYPE_MASK_COLLISION);
- virtual bool cast_motion(const RID &p_shape, const Transform &p_xform, const Vector3 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, uint32_t p_object_type_mask = TYPE_MASK_COLLISION, ShapeRestInfo *r_info = NULL);
- virtual bool collide_shape(RID p_shape, const Transform &p_shape_xform, real_t p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, uint32_t p_object_type_mask = TYPE_MASK_COLLISION);
- virtual bool rest_info(RID p_shape, const Transform &p_shape_xform, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, uint32_t p_object_type_mask = TYPE_MASK_COLLISION);
+ virtual int intersect_point(const Vector3 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, uint32_t p_object_type_mask = TYPE_MASK_COLLISION);
+ virtual bool intersect_ray(const Vector3 &p_from, const Vector3 &p_to, RayResult &r_result, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, uint32_t p_object_type_mask = TYPE_MASK_COLLISION, bool p_pick_ray = false);
+ virtual int intersect_shape(const RID &p_shape, const Transform &p_xform, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, uint32_t p_object_type_mask = TYPE_MASK_COLLISION);
+ virtual bool cast_motion(const RID &p_shape, const Transform &p_xform, const Vector3 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, uint32_t p_object_type_mask = TYPE_MASK_COLLISION, ShapeRestInfo *r_info = NULL);
+ virtual bool collide_shape(RID p_shape, const Transform &p_shape_xform, real_t p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, uint32_t p_object_type_mask = TYPE_MASK_COLLISION);
+ virtual bool rest_info(RID p_shape, const Transform &p_shape_xform, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, uint32_t p_object_type_mask = TYPE_MASK_COLLISION);
virtual Vector3 get_closest_point_to_object_volume(RID p_object, const Vector3 p_point) const;
PhysicsDirectSpaceStateSW();
@@ -122,7 +122,7 @@ private:
friend class PhysicsDirectSpaceStateSW;
- int _cull_aabb_for_body(BodySW *p_body, const Rect3 &p_aabb);
+ int _cull_aabb_for_body(BodySW *p_body, const AABB &p_aabb);
public:
_FORCE_INLINE_ void set_self(const RID &p_self) { self = p_self; }
diff --git a/servers/physics_2d/collision_object_2d_sw.h b/servers/physics_2d/collision_object_2d_sw.h
index db1270633f..627ba8ea15 100644
--- a/servers/physics_2d/collision_object_2d_sw.h
+++ b/servers/physics_2d/collision_object_2d_sw.h
@@ -110,21 +110,48 @@ public:
void set_shape_metadata(int p_index, const Variant &p_metadata);
_FORCE_INLINE_ int get_shape_count() const { return shapes.size(); }
- _FORCE_INLINE_ Shape2DSW *get_shape(int p_index) const { return shapes[p_index].shape; }
- _FORCE_INLINE_ const Transform2D &get_shape_transform(int p_index) const { return shapes[p_index].xform; }
- _FORCE_INLINE_ const Transform2D &get_shape_inv_transform(int p_index) const { return shapes[p_index].xform_inv; }
- _FORCE_INLINE_ const Rect2 &get_shape_aabb(int p_index) const { return shapes[p_index].aabb_cache; }
- _FORCE_INLINE_ const Variant &get_shape_metadata(int p_index) const { return shapes[p_index].metadata; }
+ _FORCE_INLINE_ Shape2DSW *get_shape(int p_index) const {
+ ERR_FAIL_INDEX_V(p_index, shapes.size(), NULL);
+ return shapes[p_index].shape;
+ }
+ _FORCE_INLINE_ const Transform2D &get_shape_transform(int p_index) const {
+ ERR_FAIL_INDEX_V(p_index, shapes.size(), Transform2D());
+ return shapes[p_index].xform;
+ }
+ _FORCE_INLINE_ const Transform2D &get_shape_inv_transform(int p_index) const {
+ ERR_FAIL_INDEX_V(p_index, shapes.size(), Transform2D());
+ return shapes[p_index].xform_inv;
+ }
+ _FORCE_INLINE_ const Rect2 &get_shape_aabb(int p_index) const {
+ ERR_FAIL_INDEX_V(p_index, shapes.size(), Rect2());
+ return shapes[p_index].aabb_cache;
+ }
+ _FORCE_INLINE_ const Variant &get_shape_metadata(int p_index) const {
+ ERR_FAIL_INDEX_V(p_index, shapes.size(), Variant());
+ return shapes[p_index].metadata;
+ }
_FORCE_INLINE_ Transform2D get_transform() const { return transform; }
_FORCE_INLINE_ Transform2D get_inv_transform() const { return inv_transform; }
_FORCE_INLINE_ Space2DSW *get_space() const { return space; }
- _FORCE_INLINE_ void set_shape_as_disabled(int p_idx, bool p_disabled) { shapes[p_idx].disabled = p_disabled; }
- _FORCE_INLINE_ bool is_shape_set_as_disabled(int p_idx) const { return shapes[p_idx].disabled; }
+ _FORCE_INLINE_ void set_shape_as_disabled(int p_idx, bool p_disabled) {
+ ERR_FAIL_INDEX(p_idx, shapes.size());
+ shapes[p_idx].disabled = p_disabled;
+ }
+ _FORCE_INLINE_ bool is_shape_set_as_disabled(int p_idx) const {
+ ERR_FAIL_INDEX_V(p_idx, shapes.size(), false);
+ return shapes[p_idx].disabled;
+ }
- _FORCE_INLINE_ void set_shape_as_one_way_collision(int p_idx, bool p_one_way_collision) { shapes[p_idx].one_way_collision = p_one_way_collision; }
- _FORCE_INLINE_ bool is_shape_set_as_one_way_collision(int p_idx) const { return shapes[p_idx].one_way_collision; }
+ _FORCE_INLINE_ void set_shape_as_one_way_collision(int p_idx, bool p_one_way_collision) {
+ ERR_FAIL_INDEX(p_idx, shapes.size());
+ shapes[p_idx].one_way_collision = p_one_way_collision;
+ }
+ _FORCE_INLINE_ bool is_shape_set_as_one_way_collision(int p_idx) const {
+ ERR_FAIL_INDEX_V(p_idx, shapes.size(), false);
+ return shapes[p_idx].one_way_collision;
+ }
void set_collision_mask(uint32_t p_mask) { collision_mask = p_mask; }
_FORCE_INLINE_ uint32_t get_collision_mask() const { return collision_mask; }
diff --git a/servers/physics_2d/physics_2d_server_sw.cpp b/servers/physics_2d/physics_2d_server_sw.cpp
index 2b7505169a..475a3fe3b3 100644
--- a/servers/physics_2d/physics_2d_server_sw.cpp
+++ b/servers/physics_2d/physics_2d_server_sw.cpp
@@ -35,7 +35,7 @@
#include "project_settings.h"
#include "script_language.h"
-RID Physics2DServerSW::shape_create(ShapeType p_shape) {
+RID Physics2DServerSW::_shape_create(ShapeType p_shape) {
Shape2DSW *shape = NULL;
switch (p_shape) {
@@ -83,7 +83,42 @@ RID Physics2DServerSW::shape_create(ShapeType p_shape) {
shape->set_self(id);
return id;
-};
+}
+
+RID Physics2DServerSW::line_shape_create() {
+
+ return _shape_create(SHAPE_LINE);
+}
+
+RID Physics2DServerSW::ray_shape_create() {
+
+ return _shape_create(SHAPE_RAY);
+}
+RID Physics2DServerSW::segment_shape_create() {
+
+ return _shape_create(SHAPE_SEGMENT);
+}
+RID Physics2DServerSW::circle_shape_create() {
+
+ return _shape_create(SHAPE_CIRCLE);
+}
+RID Physics2DServerSW::rectangle_shape_create() {
+
+ return _shape_create(SHAPE_RECTANGLE);
+}
+RID Physics2DServerSW::capsule_shape_create() {
+
+ return _shape_create(SHAPE_CAPSULE);
+}
+
+RID Physics2DServerSW::convex_polygon_shape_create() {
+
+ return _shape_create(SHAPE_CONVEX_POLYGON);
+}
+RID Physics2DServerSW::concave_polygon_shape_create() {
+
+ return _shape_create(SHAPE_CONCAVE_POLYGON);
+}
void Physics2DServerSW::shape_set_data(RID p_shape, const Variant &p_data) {
@@ -299,14 +334,7 @@ void Physics2DServerSW::area_set_space(RID p_area, RID p_space) {
if (area->get_space() == space)
return; //pointless
- for (Set<Constraint2DSW *>::Element *E = area->get_constraints().front(); E; E = E->next()) {
- RID self = E->get()->get_self();
- if (!self.is_valid())
- continue;
- free(self);
- }
area->clear_constraints();
-
area->set_space(space);
};
@@ -526,17 +554,13 @@ void Physics2DServerSW::area_set_area_monitor_callback(RID p_area, Object *p_rec
/* BODY API */
-RID Physics2DServerSW::body_create(BodyMode p_mode, bool p_init_sleeping) {
+RID Physics2DServerSW::body_create() {
Body2DSW *body = memnew(Body2DSW);
- if (p_mode != BODY_MODE_RIGID)
- body->set_mode(p_mode);
- if (p_init_sleeping)
- body->set_state(BODY_STATE_SLEEPING, p_init_sleeping);
RID rid = body_owner.make_rid(body);
body->set_self(rid);
return rid;
-};
+}
void Physics2DServerSW::body_set_space(RID p_body, RID p_space) {
@@ -551,14 +575,7 @@ void Physics2DServerSW::body_set_space(RID p_body, RID p_space) {
if (body->get_space() == space)
return; //pointless
- for (Map<Constraint2DSW *, int>::Element *E = body->get_constraint_map().front(); E; E = E->next()) {
- RID self = E->key()->get_self();
- if (!self.is_valid())
- continue;
- free(self);
- }
body->clear_constraint_map();
-
body->set_space(space);
};
@@ -954,6 +971,21 @@ bool Physics2DServerSW::body_test_motion(RID p_body, const Transform2D &p_from,
return body->get_space()->test_body_motion(body, p_from, p_motion, p_margin, r_result);
}
+Physics2DDirectBodyState *Physics2DServerSW::body_get_direct_state(RID p_body) {
+
+ Body2DSW *body = body_owner.get(p_body);
+ ERR_FAIL_COND_V(!body, NULL);
+
+ if ((using_threads && !doing_sync) || body->get_space()->is_locked()) {
+
+ ERR_EXPLAIN("Body state is inaccessible right now, wait for iteration or physics process notification.");
+ ERR_FAIL_V(NULL);
+ }
+
+ direct_state->body = body;
+ return direct_state;
+}
+
/* JOINT API */
void Physics2DServerSW::joint_set_param(RID p_joint, JointParam p_param, real_t p_value) {
diff --git a/servers/physics_2d/physics_2d_server_sw.h b/servers/physics_2d/physics_2d_server_sw.h
index 0ebd43be53..171a0b7a81 100644
--- a/servers/physics_2d/physics_2d_server_sw.h
+++ b/servers/physics_2d/physics_2d_server_sw.h
@@ -67,6 +67,9 @@ class Physics2DServerSW : public Physics2DServer {
static Physics2DServerSW *singletonsw;
//void _clear_query(Query2DSW *p_query);
+
+ RID _shape_create(ShapeType p_shape);
+
public:
struct CollCbkData {
@@ -78,9 +81,17 @@ public:
Vector2 *ptr;
};
+ virtual RID line_shape_create();
+ virtual RID ray_shape_create();
+ virtual RID segment_shape_create();
+ virtual RID circle_shape_create();
+ virtual RID rectangle_shape_create();
+ virtual RID capsule_shape_create();
+ virtual RID convex_polygon_shape_create();
+ virtual RID concave_polygon_shape_create();
+
static void _shape_col_cbk(const Vector2 &p_point_A, const Vector2 &p_point_B, void *p_userdata);
- virtual RID shape_create(ShapeType p_shape);
virtual void shape_set_data(RID p_shape, const Variant &p_data);
virtual void shape_set_custom_solver_bias(RID p_shape, real_t p_bias);
@@ -149,7 +160,7 @@ public:
/* BODY API */
// create a body of a given type
- virtual RID body_create(BodyMode p_mode = BODY_MODE_RIGID, bool p_init_sleeping = false);
+ virtual RID body_create();
virtual void body_set_space(RID p_body, RID p_space);
virtual RID body_get_space(RID p_body) const;
@@ -222,6 +233,9 @@ public:
virtual bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin = 0.001, MotionResult *r_result = NULL);
+ // this function only works on physics process, errors and returns null otherwise
+ virtual Physics2DDirectBodyState *body_get_direct_state(RID p_body);
+
/* JOINT API */
virtual void joint_set_param(RID p_joint, JointParam p_param, real_t p_value);
diff --git a/servers/physics_2d/physics_2d_server_wrap_mt.cpp b/servers/physics_2d/physics_2d_server_wrap_mt.cpp
index f8f3b620d4..f92ed18de2 100644
--- a/servers/physics_2d/physics_2d_server_wrap_mt.cpp
+++ b/servers/physics_2d/physics_2d_server_wrap_mt.cpp
@@ -130,19 +130,23 @@ void Physics2DServerWrapMT::finish() {
Thread::wait_to_finish(thread);
memdelete(thread);
- /*
- shape_free_cached_ids();
- area_free_cached_ids();
- body_free_cached_ids();
- pin_joint_free_cached_ids();
- groove_joint_free_cached_ids();
- damped_string_free_cached_ids();
-*/
thread = NULL;
} else {
physics_2d_server->finish();
}
+ line_shape_free_cached_ids();
+ ray_shape_free_cached_ids();
+ segment_shape_free_cached_ids();
+ circle_shape_free_cached_ids();
+ rectangle_shape_free_cached_ids();
+ convex_polygon_shape_free_cached_ids();
+ concave_polygon_shape_free_cached_ids();
+
+ space_free_cached_ids();
+ area_free_cached_ids();
+ body_free_cached_ids();
+
if (step_sem)
memdelete(step_sem);
}
@@ -158,12 +162,7 @@ Physics2DServerWrapMT::Physics2DServerWrapMT(Physics2DServer *p_contained, bool
step_thread_up = false;
alloc_mutex = Mutex::create();
- shape_pool_max_size = GLOBAL_GET("memory/limits/multithreaded_server/rid_pool_prealloc");
- area_pool_max_size = GLOBAL_GET("memory/limits/multithreaded_server/rid_pool_prealloc");
- body_pool_max_size = GLOBAL_GET("memory/limits/multithreaded_server/rid_pool_prealloc");
- pin_joint_pool_max_size = GLOBAL_GET("memory/limits/multithreaded_server/rid_pool_prealloc");
- groove_joint_pool_max_size = GLOBAL_GET("memory/limits/multithreaded_server/rid_pool_prealloc");
- damped_spring_joint_pool_max_size = GLOBAL_GET("memory/limits/multithreaded_server/rid_pool_prealloc");
+ pool_max_size = GLOBAL_GET("memory/limits/multithreaded_server/rid_pool_prealloc");
if (!p_create_thread) {
server_thread = Thread::get_caller_id();
diff --git a/servers/physics_2d/physics_2d_server_wrap_mt.h b/servers/physics_2d/physics_2d_server_wrap_mt.h
index 5bec2f7cbd..cbc316cb7a 100644
--- a/servers/physics_2d/physics_2d_server_wrap_mt.h
+++ b/servers/physics_2d/physics_2d_server_wrap_mt.h
@@ -64,21 +64,10 @@ class Physics2DServerWrapMT : public Physics2DServer {
void thread_exit();
- Mutex *alloc_mutex;
bool first_frame;
- int shape_pool_max_size;
- List<RID> shape_id_pool;
- int area_pool_max_size;
- List<RID> area_id_pool;
- int body_pool_max_size;
- List<RID> body_id_pool;
- int pin_joint_pool_max_size;
- List<RID> pin_joint_id_pool;
- int groove_joint_pool_max_size;
- List<RID> groove_joint_id_pool;
- int damped_spring_joint_pool_max_size;
- List<RID> damped_spring_joint_id_pool;
+ Mutex *alloc_mutex;
+ int pool_max_size;
public:
#define ServerName Physics2DServer
@@ -87,7 +76,15 @@ public:
#include "servers/server_wrap_mt_common.h"
//FUNC1RID(shape,ShapeType); todo fix
- FUNC1R(RID, shape_create, ShapeType);
+ FUNCRID(line_shape)
+ FUNCRID(ray_shape)
+ FUNCRID(segment_shape)
+ FUNCRID(circle_shape)
+ FUNCRID(rectangle_shape)
+ FUNCRID(capsule_shape)
+ FUNCRID(convex_polygon_shape)
+ FUNCRID(concave_polygon_shape)
+
FUNC2(shape_set_data, RID, const Variant &);
FUNC2(shape_set_custom_solver_bias, RID, real_t);
@@ -104,7 +101,7 @@ public:
/* SPACE API */
- FUNC0R(RID, space_create);
+ FUNCRID(space);
FUNC2(space_set_active, RID, bool);
FUNC1RC(bool, space_is_active, RID);
@@ -134,7 +131,7 @@ public:
/* AREA API */
//FUNC0RID(area);
- FUNC0R(RID, area_create);
+ FUNCRID(area);
FUNC2(area_set_space, RID, RID);
FUNC1RC(RID, area_get_space, RID);
@@ -174,7 +171,7 @@ public:
/* BODY API */
//FUNC2RID(body,BodyMode,bool);
- FUNC2R(RID, body_create, BodyMode, bool)
+ FUNCRID(body)
FUNC2(body_set_space, RID, RID);
FUNC1RC(RID, body_get_space, RID);
@@ -253,6 +250,13 @@ public:
return physics_2d_server->body_test_motion(p_body, p_from, p_motion, p_margin, r_result);
}
+ // this function only works on physics process, errors and returns null otherwise
+ Physics2DDirectBodyState *body_get_direct_state(RID p_body) {
+
+ ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), NULL);
+ return physics_2d_server->body_get_direct_state(p_body);
+ }
+
/* JOINT API */
FUNC3(joint_set_param, RID, JointParam, real_t);
@@ -262,6 +266,8 @@ public:
///FUNC5RID(groove_joint,const Vector2&,const Vector2&,const Vector2&,RID,RID);
///FUNC4RID(damped_spring_joint,const Vector2&,const Vector2&,RID,RID);
+ //TODO need to convert this to FUNCRID, but it's a hassle..
+
FUNC3R(RID, pin_joint_create, const Vector2 &, RID, RID);
FUNC5R(RID, groove_joint_create, const Vector2 &, const Vector2 &, const Vector2 &, RID, RID);
FUNC4R(RID, damped_spring_joint_create, const Vector2 &, const Vector2 &, RID, RID);
diff --git a/servers/physics_2d/space_2d_sw.cpp b/servers/physics_2d/space_2d_sw.cpp
index 8f22d1cd44..3b8eb19dd1 100644
--- a/servers/physics_2d/space_2d_sw.cpp
+++ b/servers/physics_2d/space_2d_sw.cpp
@@ -32,9 +32,9 @@
#include "collision_solver_2d_sw.h"
#include "pair.h"
#include "physics_2d_server_sw.h"
-_FORCE_INLINE_ static bool _match_object_type_query(CollisionObject2DSW *p_object, uint32_t p_collision_layer, uint32_t p_type_mask) {
+_FORCE_INLINE_ static bool _match_object_type_query(CollisionObject2DSW *p_object, uint32_t p_collision_mask, uint32_t p_type_mask) {
- if ((p_object->get_collision_layer() & p_collision_layer) == 0)
+ if ((p_object->get_collision_layer() & p_collision_mask) == 0)
return false;
if (p_object->get_type() == CollisionObject2DSW::TYPE_AREA)
@@ -45,7 +45,7 @@ _FORCE_INLINE_ static bool _match_object_type_query(CollisionObject2DSW *p_objec
return (1 << body->get_mode()) & p_type_mask;
}
-int Physics2DDirectSpaceStateSW::intersect_point(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_layer, uint32_t p_object_type_mask, bool p_pick_point) {
+int Physics2DDirectSpaceStateSW::intersect_point(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, uint32_t p_object_type_mask, bool p_pick_point) {
if (p_result_max <= 0)
return 0;
@@ -60,7 +60,7 @@ int Physics2DDirectSpaceStateSW::intersect_point(const Vector2 &p_point, ShapeRe
for (int i = 0; i < amount; i++) {
- if (!_match_object_type_query(space->intersection_query_results[i], p_collision_layer, p_object_type_mask))
+ if (!_match_object_type_query(space->intersection_query_results[i], p_collision_mask, p_object_type_mask))
continue;
if (p_exclude.has(space->intersection_query_results[i]->get_self()))
@@ -96,7 +96,7 @@ int Physics2DDirectSpaceStateSW::intersect_point(const Vector2 &p_point, ShapeRe
return cc;
}
-bool Physics2DDirectSpaceStateSW::intersect_ray(const Vector2 &p_from, const Vector2 &p_to, RayResult &r_result, const Set<RID> &p_exclude, uint32_t p_collision_layer, uint32_t p_object_type_mask) {
+bool Physics2DDirectSpaceStateSW::intersect_ray(const Vector2 &p_from, const Vector2 &p_to, RayResult &r_result, const Set<RID> &p_exclude, uint32_t p_collision_mask, uint32_t p_object_type_mask) {
ERR_FAIL_COND_V(space->locked, false);
@@ -118,7 +118,7 @@ bool Physics2DDirectSpaceStateSW::intersect_ray(const Vector2 &p_from, const Vec
for (int i = 0; i < amount; i++) {
- if (!_match_object_type_query(space->intersection_query_results[i], p_collision_layer, p_object_type_mask))
+ if (!_match_object_type_query(space->intersection_query_results[i], p_collision_mask, p_object_type_mask))
continue;
if (p_exclude.has(space->intersection_query_results[i]->get_self()))
@@ -176,7 +176,7 @@ bool Physics2DDirectSpaceStateSW::intersect_ray(const Vector2 &p_from, const Vec
return true;
}
-int Physics2DDirectSpaceStateSW::intersect_shape(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_layer, uint32_t p_object_type_mask) {
+int Physics2DDirectSpaceStateSW::intersect_shape(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, uint32_t p_object_type_mask) {
if (p_result_max <= 0)
return 0;
@@ -193,7 +193,7 @@ int Physics2DDirectSpaceStateSW::intersect_shape(const RID &p_shape, const Trans
for (int i = 0; i < amount; i++) {
- if (!_match_object_type_query(space->intersection_query_results[i], p_collision_layer, p_object_type_mask))
+ if (!_match_object_type_query(space->intersection_query_results[i], p_collision_mask, p_object_type_mask))
continue;
if (p_exclude.has(space->intersection_query_results[i]->get_self()))
@@ -218,7 +218,7 @@ int Physics2DDirectSpaceStateSW::intersect_shape(const RID &p_shape, const Trans
return cc;
}
-bool Physics2DDirectSpaceStateSW::cast_motion(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude, uint32_t p_collision_layer, uint32_t p_object_type_mask) {
+bool Physics2DDirectSpaceStateSW::cast_motion(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude, uint32_t p_collision_mask, uint32_t p_object_type_mask) {
Shape2DSW *shape = Physics2DServerSW::singletonsw->shape_owner.get(p_shape);
ERR_FAIL_COND_V(!shape, false);
@@ -239,7 +239,7 @@ bool Physics2DDirectSpaceStateSW::cast_motion(const RID &p_shape, const Transfor
for (int i = 0; i < amount; i++) {
- if (!_match_object_type_query(space->intersection_query_results[i], p_collision_layer, p_object_type_mask))
+ if (!_match_object_type_query(space->intersection_query_results[i], p_collision_mask, p_object_type_mask))
continue;
if (p_exclude.has(space->intersection_query_results[i]->get_self()))
@@ -302,7 +302,7 @@ bool Physics2DDirectSpaceStateSW::cast_motion(const RID &p_shape, const Transfor
return true;
}
-bool Physics2DDirectSpaceStateSW::collide_shape(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, Vector2 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude, uint32_t p_collision_layer, uint32_t p_object_type_mask) {
+bool Physics2DDirectSpaceStateSW::collide_shape(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, Vector2 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude, uint32_t p_collision_mask, uint32_t p_object_type_mask) {
if (p_result_max <= 0)
return 0;
@@ -333,7 +333,7 @@ bool Physics2DDirectSpaceStateSW::collide_shape(RID p_shape, const Transform2D &
for (int i = 0; i < amount; i++) {
- if (!_match_object_type_query(space->intersection_query_results[i], p_collision_layer, p_object_type_mask))
+ if (!_match_object_type_query(space->intersection_query_results[i], p_collision_mask, p_object_type_mask))
continue;
const CollisionObject2DSW *col_obj = space->intersection_query_results[i];
@@ -391,7 +391,7 @@ static void _rest_cbk_result(const Vector2 &p_point_A, const Vector2 &p_point_B,
rd->best_shape = rd->shape;
}
-bool Physics2DDirectSpaceStateSW::rest_info(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude, uint32_t p_collision_layer, uint32_t p_object_type_mask) {
+bool Physics2DDirectSpaceStateSW::rest_info(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude, uint32_t p_collision_mask, uint32_t p_object_type_mask) {
Shape2DSW *shape = Physics2DServerSW::singletonsw->shape_owner.get(p_shape);
ERR_FAIL_COND_V(!shape, 0);
@@ -409,7 +409,7 @@ bool Physics2DDirectSpaceStateSW::rest_info(RID p_shape, const Transform2D &p_sh
for (int i = 0; i < amount; i++) {
- if (!_match_object_type_query(space->intersection_query_results[i], p_collision_layer, p_object_type_mask))
+ if (!_match_object_type_query(space->intersection_query_results[i], p_collision_mask, p_object_type_mask))
continue;
const CollisionObject2DSW *col_obj = space->intersection_query_results[i];
@@ -626,13 +626,13 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
int amount = _cull_aabb_for_body(p_body, motion_aabb);
- for (int j = 0; j < p_body->get_shape_count(); j++) {
+ for (int body_shape_idx = 0; body_shape_idx < p_body->get_shape_count(); body_shape_idx++) {
- if (p_body->is_shape_set_as_disabled(j))
+ if (p_body->is_shape_set_as_disabled(body_shape_idx))
continue;
- Transform2D body_shape_xform = body_transform * p_body->get_shape_transform(j);
- Shape2DSW *body_shape = p_body->get_shape(j);
+ Transform2D body_shape_xform = body_transform * p_body->get_shape_transform(body_shape_idx);
+ Shape2DSW *body_shape = p_body->get_shape(body_shape_idx);
bool stuck = false;
@@ -642,14 +642,14 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
for (int i = 0; i < amount; i++) {
const CollisionObject2DSW *col_obj = intersection_query_results[i];
- int shape_idx = intersection_query_subindex_results[i];
- Shape2DSW *against_shape = col_obj->get_shape(shape_idx);
+ int col_shape_idx = intersection_query_subindex_results[i];
+ Shape2DSW *against_shape = col_obj->get_shape(col_shape_idx);
bool excluded = false;
for (int k = 0; k < excluded_shape_pair_count; k++) {
- if (excluded_shape_pairs[k].local_shape == body_shape && excluded_shape_pairs[k].against_object == col_obj && excluded_shape_pairs[k].against_shape_index == shape_idx) {
+ if (excluded_shape_pairs[k].local_shape == body_shape && excluded_shape_pairs[k].against_object == col_obj && excluded_shape_pairs[k].against_shape_index == col_shape_idx) {
excluded = true;
break;
}
@@ -660,7 +660,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
continue;
}
- Transform2D col_obj_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx);
+ Transform2D col_obj_xform = col_obj->get_transform() * col_obj->get_shape_transform(col_shape_idx);
//test initial overlap, does it collide if going all the way?
if (!CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_motion, against_shape, col_obj_xform, Vector2(), NULL, NULL, NULL, 0)) {
continue;
@@ -669,7 +669,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
//test initial overlap
if (CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj_xform, Vector2(), NULL, NULL, NULL, 0)) {
- if (col_obj->is_shape_set_as_one_way_collision(j)) {
+ if (col_obj->is_shape_set_as_one_way_collision(col_shape_idx)) {
continue;
}
@@ -698,7 +698,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
}
}
- if (col_obj->is_shape_set_as_one_way_collision(j)) {
+ if (col_obj->is_shape_set_as_one_way_collision(col_shape_idx)) {
Vector2 cd[2];
Physics2DServerSW::CollCbkData cbk;
@@ -710,7 +710,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
cbk.valid_depth = 10e20;
Vector2 sep = mnormal; //important optimization for this to work fast enough
- bool collided = CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_motion * (hi + contact_max_allowed_penetration), col_obj->get_shape(shape_idx), col_obj_xform, Vector2(), Physics2DServerSW::_shape_col_cbk, &cbk, &sep, 0);
+ bool collided = CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_motion * (hi + contact_max_allowed_penetration), col_obj->get_shape(col_shape_idx), col_obj_xform, Vector2(), Physics2DServerSW::_shape_col_cbk, &cbk, &sep, 0);
if (!collided || cbk.amount == 0) {
continue;
}
@@ -726,7 +726,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
safe = 0;
unsafe = 0;
- best_shape = j; //sadly it's the best
+ best_shape = body_shape_idx; //sadly it's the best
break;
}
if (best_safe == 1.0) {
@@ -736,7 +736,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
safe = best_safe;
unsafe = best_unsafe;
- best_shape = j;
+ best_shape = body_shape_idx;
}
}
}
@@ -969,15 +969,15 @@ void Space2DSW::call_queries() {
while (state_query_list.first()) {
Body2DSW *b = state_query_list.first()->self();
- b->call_queries();
state_query_list.remove(state_query_list.first());
+ b->call_queries();
}
while (monitor_query_list.first()) {
Area2DSW *a = monitor_query_list.first()->self();
- a->call_queries();
monitor_query_list.remove(monitor_query_list.first());
+ a->call_queries();
}
}
diff --git a/servers/physics_2d/space_2d_sw.h b/servers/physics_2d/space_2d_sw.h
index c7e7497397..bf0796fb22 100644
--- a/servers/physics_2d/space_2d_sw.h
+++ b/servers/physics_2d/space_2d_sw.h
@@ -47,12 +47,12 @@ class Physics2DDirectSpaceStateSW : public Physics2DDirectSpaceState {
public:
Space2DSW *space;
- virtual int intersect_point(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, uint32_t p_object_type_mask = TYPE_MASK_COLLISION, bool p_pick_point = false);
- virtual bool intersect_ray(const Vector2 &p_from, const Vector2 &p_to, RayResult &r_result, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, uint32_t p_object_type_mask = TYPE_MASK_COLLISION);
- virtual int intersect_shape(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, uint32_t p_object_type_mask = TYPE_MASK_COLLISION);
- virtual bool cast_motion(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, uint32_t p_object_type_mask = TYPE_MASK_COLLISION);
- virtual bool collide_shape(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, Vector2 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, uint32_t p_object_type_mask = TYPE_MASK_COLLISION);
- virtual bool rest_info(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, uint32_t p_object_type_mask = TYPE_MASK_COLLISION);
+ virtual int intersect_point(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, uint32_t p_object_type_mask = TYPE_MASK_COLLISION, bool p_pick_point = false);
+ virtual bool intersect_ray(const Vector2 &p_from, const Vector2 &p_to, RayResult &r_result, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, uint32_t p_object_type_mask = TYPE_MASK_COLLISION);
+ virtual int intersect_shape(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, uint32_t p_object_type_mask = TYPE_MASK_COLLISION);
+ virtual bool cast_motion(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, uint32_t p_object_type_mask = TYPE_MASK_COLLISION);
+ virtual bool collide_shape(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, Vector2 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, uint32_t p_object_type_mask = TYPE_MASK_COLLISION);
+ virtual bool rest_info(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, uint32_t p_object_type_mask = TYPE_MASK_COLLISION);
Physics2DDirectSpaceStateSW();
};
diff --git a/servers/physics_2d_server.cpp b/servers/physics_2d_server.cpp
index b42b85b1be..650d3d0f62 100644
--- a/servers/physics_2d_server.cpp
+++ b/servers/physics_2d_server.cpp
@@ -28,7 +28,9 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "physics_2d_server.h"
+#include "core/project_settings.h"
#include "print_string.h"
+
Physics2DServer *Physics2DServer::singleton = NULL;
void Physics2DDirectBodyState::integrate_forces() {
@@ -358,8 +360,8 @@ void Physics2DDirectSpaceState::_bind_methods() {
BIND_ENUM_CONSTANT(TYPE_MASK_KINEMATIC_BODY);
BIND_ENUM_CONSTANT(TYPE_MASK_RIGID_BODY);
BIND_ENUM_CONSTANT(TYPE_MASK_CHARACTER_BODY);
- BIND_ENUM_CONSTANT(TYPE_MASK_AREA);
BIND_ENUM_CONSTANT(TYPE_MASK_COLLISION);
+ BIND_ENUM_CONSTANT(TYPE_MASK_AREA);
}
int Physics2DShapeQueryResult::get_result_count() const {
@@ -473,7 +475,15 @@ bool Physics2DServer::_body_test_motion(RID p_body, const Transform2D &p_from, c
void Physics2DServer::_bind_methods() {
- ClassDB::bind_method(D_METHOD("shape_create", "type"), &Physics2DServer::shape_create);
+ ClassDB::bind_method(D_METHOD("line_shape_create"), &Physics2DServer::line_shape_create);
+ ClassDB::bind_method(D_METHOD("ray_shape_create"), &Physics2DServer::ray_shape_create);
+ ClassDB::bind_method(D_METHOD("segment_shape_create"), &Physics2DServer::segment_shape_create);
+ ClassDB::bind_method(D_METHOD("circle_shape_create"), &Physics2DServer::circle_shape_create);
+ ClassDB::bind_method(D_METHOD("rectangle_shape_create"), &Physics2DServer::rectangle_shape_create);
+ ClassDB::bind_method(D_METHOD("capsule_shape_create"), &Physics2DServer::capsule_shape_create);
+ ClassDB::bind_method(D_METHOD("convex_polygon_shape_create"), &Physics2DServer::convex_polygon_shape_create);
+ ClassDB::bind_method(D_METHOD("concave_polygon_shape_create"), &Physics2DServer::concave_polygon_shape_create);
+
ClassDB::bind_method(D_METHOD("shape_set_data", "shape", "data"), &Physics2DServer::shape_set_data);
ClassDB::bind_method(D_METHOD("shape_get_type", "shape"), &Physics2DServer::shape_get_type);
@@ -519,7 +529,7 @@ void Physics2DServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("area_set_monitor_callback", "area", "receiver", "method"), &Physics2DServer::area_set_monitor_callback);
- ClassDB::bind_method(D_METHOD("body_create", "mode", "init_sleeping"), &Physics2DServer::body_create, DEFVAL(BODY_MODE_RIGID), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("body_create"), &Physics2DServer::body_create);
ClassDB::bind_method(D_METHOD("body_set_space", "body", "space"), &Physics2DServer::body_set_space);
ClassDB::bind_method(D_METHOD("body_get_space", "body"), &Physics2DServer::body_get_space);
@@ -579,6 +589,8 @@ void Physics2DServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("body_test_motion", "body", "from", "motion", "margin", "result"), &Physics2DServer::_body_test_motion, DEFVAL(0.08), DEFVAL(Variant()));
+ ClassDB::bind_method(D_METHOD("body_get_direct_state", "body"), &Physics2DServer::body_get_direct_state);
+
/* JOINT API */
ClassDB::bind_method(D_METHOD("joint_set_param", "joint", "param", "value"), &Physics2DServer::joint_set_param);
@@ -613,6 +625,7 @@ void Physics2DServer::_bind_methods() {
BIND_ENUM_CONSTANT(SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS);
BIND_ENUM_CONSTANT(SHAPE_LINE);
+ BIND_ENUM_CONSTANT(SHAPE_RAY);
BIND_ENUM_CONSTANT(SHAPE_SEGMENT);
BIND_ENUM_CONSTANT(SHAPE_CIRCLE);
BIND_ENUM_CONSTANT(SHAPE_RECTANGLE);
@@ -689,3 +702,68 @@ Physics2DServer::~Physics2DServer() {
singleton = NULL;
}
+
+Vector<Physics2DServerManager::ClassInfo> Physics2DServerManager::physics_2d_servers;
+int Physics2DServerManager::default_server_id = -1;
+int Physics2DServerManager::default_server_priority = -1;
+const String Physics2DServerManager::setting_property_name("physics/2d/physics_engine");
+
+void Physics2DServerManager::on_servers_changed() {
+
+ String physics_servers("DEFAULT");
+ for (int i = get_servers_count() - 1; 0 <= i; --i) {
+ physics_servers += "," + get_server_name(i);
+ }
+ ProjectSettings::get_singleton()->set_custom_property_info(setting_property_name, PropertyInfo(Variant::STRING, setting_property_name, PROPERTY_HINT_ENUM, physics_servers));
+}
+
+void Physics2DServerManager::register_server(const String &p_name, CreatePhysics2DServerCallback p_creat_callback) {
+
+ ERR_FAIL_COND(!p_creat_callback);
+ ERR_FAIL_COND(find_server_id(p_name) != -1);
+ physics_2d_servers.push_back(ClassInfo(p_name, p_creat_callback));
+ on_servers_changed();
+}
+
+void Physics2DServerManager::set_default_server(const String &p_name, int p_priority) {
+
+ const int id = find_server_id(p_name);
+ ERR_FAIL_COND(id == -1); // Not found
+ if (default_server_priority < p_priority) {
+ default_server_id = id;
+ default_server_priority = p_priority;
+ }
+}
+
+int Physics2DServerManager::find_server_id(const String &p_name) {
+
+ for (int i = physics_2d_servers.size() - 1; 0 <= i; --i) {
+ if (p_name == physics_2d_servers[i].name) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+int Physics2DServerManager::get_servers_count() {
+ return physics_2d_servers.size();
+}
+
+String Physics2DServerManager::get_server_name(int p_id) {
+ ERR_FAIL_INDEX_V(p_id, get_servers_count(), "");
+ return physics_2d_servers[p_id].name;
+}
+
+Physics2DServer *Physics2DServerManager::new_default_server() {
+ ERR_FAIL_COND_V(default_server_id == -1, NULL);
+ return physics_2d_servers[default_server_id].create_callback();
+}
+
+Physics2DServer *Physics2DServerManager::new_server(const String &p_name) {
+ int id = find_server_id(p_name);
+ if (id == -1) {
+ return NULL;
+ } else {
+ return physics_2d_servers[id].create_callback();
+ }
+}
diff --git a/servers/physics_2d_server.h b/servers/physics_2d_server.h
index 34f885db1d..241255bdb5 100644
--- a/servers/physics_2d_server.h
+++ b/servers/physics_2d_server.h
@@ -252,7 +252,15 @@ public:
SHAPE_CUSTOM, ///< Server-Implementation based custom shape, calling shape_create() with this value will result in an error
};
- virtual RID shape_create(ShapeType p_shape) = 0;
+ virtual RID line_shape_create() = 0;
+ virtual RID ray_shape_create() = 0;
+ virtual RID segment_shape_create() = 0;
+ virtual RID circle_shape_create() = 0;
+ virtual RID rectangle_shape_create() = 0;
+ virtual RID capsule_shape_create() = 0;
+ virtual RID convex_polygon_shape_create() = 0;
+ virtual RID concave_polygon_shape_create() = 0;
+
virtual void shape_set_data(RID p_shape, const Variant &p_data) = 0;
virtual void shape_set_custom_solver_bias(RID p_shape, real_t p_bias) = 0;
@@ -366,7 +374,7 @@ public:
//BODY_MODE_SOFT ??
};
- virtual RID body_create(BodyMode p_mode = BODY_MODE_RIGID, bool p_init_sleeping = false) = 0;
+ virtual RID body_create() = 0;
virtual void body_set_space(RID p_body, RID p_space) = 0;
virtual RID body_get_space(RID p_body) const = 0;
@@ -468,6 +476,9 @@ public:
virtual void body_set_pickable(RID p_body, bool p_pickable) = 0;
+ // this function only works on physics process, errors and returns null otherwise
+ virtual Physics2DDirectBodyState *body_get_direct_state(RID p_body) = 0;
+
struct MotionResult {
Vector2 motion;
@@ -587,6 +598,43 @@ public:
Physics2DTestMotionResult();
};
+typedef Physics2DServer *(*CreatePhysics2DServerCallback)();
+
+class Physics2DServerManager {
+ struct ClassInfo {
+ String name;
+ CreatePhysics2DServerCallback create_callback;
+
+ ClassInfo()
+ : name(""), create_callback(NULL) {}
+
+ ClassInfo(String p_name, CreatePhysics2DServerCallback p_create_callback)
+ : name(p_name), create_callback(p_create_callback) {}
+
+ ClassInfo(const ClassInfo &p_ci)
+ : name(p_ci.name), create_callback(p_ci.create_callback) {}
+ };
+
+ static Vector<ClassInfo> physics_2d_servers;
+ static int default_server_id;
+ static int default_server_priority;
+
+public:
+ static const String setting_property_name;
+
+private:
+ static void on_servers_changed();
+
+public:
+ static void register_server(const String &p_name, CreatePhysics2DServerCallback p_creat_callback);
+ static void set_default_server(const String &p_name, int p_priority = 0);
+ static int find_server_id(const String &p_name);
+ static int get_servers_count();
+ static String get_server_name(int p_id);
+ static Physics2DServer *new_default_server();
+ static Physics2DServer *new_server(const String &p_name);
+};
+
VARIANT_ENUM_CAST(Physics2DServer::ShapeType);
VARIANT_ENUM_CAST(Physics2DServer::SpaceParameter);
VARIANT_ENUM_CAST(Physics2DServer::AreaParameter);
diff --git a/servers/physics_server.cpp b/servers/physics_server.cpp
index 0e54867ee1..88cd728a94 100644
--- a/servers/physics_server.cpp
+++ b/servers/physics_server.cpp
@@ -28,7 +28,9 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "physics_server.h"
+#include "core/project_settings.h"
#include "print_string.h"
+
PhysicsServer *PhysicsServer::singleton = NULL;
void PhysicsDirectBodyState::integrate_forces() {
@@ -353,8 +355,8 @@ void PhysicsDirectSpaceState::_bind_methods() {
BIND_ENUM_CONSTANT(TYPE_MASK_KINEMATIC_BODY);
BIND_ENUM_CONSTANT(TYPE_MASK_RIGID_BODY);
BIND_ENUM_CONSTANT(TYPE_MASK_CHARACTER_BODY);
- BIND_ENUM_CONSTANT(TYPE_MASK_AREA);
BIND_ENUM_CONSTANT(TYPE_MASK_COLLISION);
+ BIND_ENUM_CONSTANT(TYPE_MASK_AREA);
}
int PhysicsShapeQueryResult::get_result_count() const {
@@ -479,6 +481,9 @@ void PhysicsServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("body_set_param", "body", "param", "value"), &PhysicsServer::body_set_param);
ClassDB::bind_method(D_METHOD("body_get_param", "body", "param"), &PhysicsServer::body_get_param);
+ ClassDB::bind_method(D_METHOD("body_set_kinematic_safe_margin", "body", "margin"), &PhysicsServer::body_set_kinematic_safe_margin);
+ ClassDB::bind_method(D_METHOD("body_get_kinematic_safe_margin", "body"), &PhysicsServer::body_get_kinematic_safe_margin);
+
ClassDB::bind_method(D_METHOD("body_set_state", "body", "state", "value"), &PhysicsServer::body_set_state);
ClassDB::bind_method(D_METHOD("body_get_state", "body", "state"), &PhysicsServer::body_get_state);
@@ -504,6 +509,8 @@ void PhysicsServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("body_set_ray_pickable", "body", "enable"), &PhysicsServer::body_set_ray_pickable);
ClassDB::bind_method(D_METHOD("body_is_ray_pickable", "body"), &PhysicsServer::body_is_ray_pickable);
+ ClassDB::bind_method(D_METHOD("body_get_direct_state", "body"), &PhysicsServer::body_get_direct_state);
+
/* JOINT API */
BIND_ENUM_CONSTANT(JOINT_PIN);
@@ -671,14 +678,15 @@ void PhysicsServer::_bind_methods() {
BIND_ENUM_CONSTANT(BODY_MODE_STATIC);
BIND_ENUM_CONSTANT(BODY_MODE_KINEMATIC);
BIND_ENUM_CONSTANT(BODY_MODE_RIGID);
+ BIND_ENUM_CONSTANT(BODY_MODE_SOFT);
BIND_ENUM_CONSTANT(BODY_MODE_CHARACTER);
BIND_ENUM_CONSTANT(BODY_PARAM_BOUNCE);
BIND_ENUM_CONSTANT(BODY_PARAM_FRICTION);
BIND_ENUM_CONSTANT(BODY_PARAM_MASS);
BIND_ENUM_CONSTANT(BODY_PARAM_GRAVITY_SCALE);
- BIND_ENUM_CONSTANT(BODY_PARAM_ANGULAR_DAMP);
BIND_ENUM_CONSTANT(BODY_PARAM_LINEAR_DAMP);
+ BIND_ENUM_CONSTANT(BODY_PARAM_ANGULAR_DAMP);
BIND_ENUM_CONSTANT(BODY_PARAM_MAX);
BIND_ENUM_CONSTANT(BODY_STATE_TRANSFORM);
@@ -730,3 +738,68 @@ PhysicsServer::~PhysicsServer() {
singleton = NULL;
}
+
+Vector<PhysicsServerManager::ClassInfo> PhysicsServerManager::physics_servers;
+int PhysicsServerManager::default_server_id = -1;
+int PhysicsServerManager::default_server_priority = -1;
+const String PhysicsServerManager::setting_property_name("physics/3d/physics_engine");
+
+void PhysicsServerManager::on_servers_changed() {
+
+ String physics_servers("DEFAULT");
+ for (int i = get_servers_count() - 1; 0 <= i; --i) {
+ physics_servers += "," + get_server_name(i);
+ }
+ ProjectSettings::get_singleton()->set_custom_property_info(setting_property_name, PropertyInfo(Variant::STRING, setting_property_name, PROPERTY_HINT_ENUM, physics_servers));
+}
+
+void PhysicsServerManager::register_server(const String &p_name, CreatePhysicsServerCallback p_creat_callback) {
+
+ ERR_FAIL_COND(!p_creat_callback);
+ ERR_FAIL_COND(find_server_id(p_name) != -1);
+ physics_servers.push_back(ClassInfo(p_name, p_creat_callback));
+ on_servers_changed();
+}
+
+void PhysicsServerManager::set_default_server(const String &p_name, int p_priority) {
+
+ const int id = find_server_id(p_name);
+ ERR_FAIL_COND(id == -1); // Not found
+ if (default_server_priority < p_priority) {
+ default_server_id = id;
+ default_server_priority = p_priority;
+ }
+}
+
+int PhysicsServerManager::find_server_id(const String &p_name) {
+
+ for (int i = physics_servers.size() - 1; 0 <= i; --i) {
+ if (p_name == physics_servers[i].name) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+int PhysicsServerManager::get_servers_count() {
+ return physics_servers.size();
+}
+
+String PhysicsServerManager::get_server_name(int p_id) {
+ ERR_FAIL_INDEX_V(p_id, get_servers_count(), "");
+ return physics_servers[p_id].name;
+}
+
+PhysicsServer *PhysicsServerManager::new_default_server() {
+ ERR_FAIL_COND_V(default_server_id == -1, NULL);
+ return physics_servers[default_server_id].create_callback();
+}
+
+PhysicsServer *PhysicsServerManager::new_server(const String &p_name) {
+ int id = find_server_id(p_name);
+ if (id == -1) {
+ return NULL;
+ } else {
+ return physics_servers[id].create_callback();
+ }
+}
diff --git a/servers/physics_server.h b/servers/physics_server.h
index 7012caeae6..64c67eae2a 100644
--- a/servers/physics_server.h
+++ b/servers/physics_server.h
@@ -357,7 +357,7 @@ public:
BODY_MODE_STATIC,
BODY_MODE_KINEMATIC,
BODY_MODE_RIGID,
- //BODY_MODE_SOFT
+ BODY_MODE_SOFT,
BODY_MODE_CHARACTER
};
@@ -411,6 +411,9 @@ public:
virtual void body_set_param(RID p_body, BodyParameter p_param, float p_value) = 0;
virtual float body_get_param(RID p_body, BodyParameter p_param) const = 0;
+ virtual void body_set_kinematic_safe_margin(RID p_body, real_t p_margin) = 0;
+ virtual real_t body_get_kinematic_safe_margin(RID p_body) const = 0;
+
//state
enum BodyState {
BODY_STATE_TRANSFORM,
@@ -464,6 +467,9 @@ public:
virtual void body_set_ray_pickable(RID p_body, bool p_enable) = 0;
virtual bool body_is_ray_pickable(RID p_body) const = 0;
+ // this function only works on physics process, errors and returns null otherwise
+ virtual PhysicsDirectBodyState *body_get_direct_state(RID p_body) = 0;
+
struct MotionResult {
Vector3 motion;
@@ -479,7 +485,7 @@ public:
Variant collider_metadata;
};
- virtual bool body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, float p_margin = 0.001, MotionResult *r_result = NULL) = 0;
+ virtual bool body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, MotionResult *r_result = NULL) = 0;
/* JOINT API */
@@ -655,6 +661,43 @@ public:
~PhysicsServer();
};
+typedef PhysicsServer *(*CreatePhysicsServerCallback)();
+
+class PhysicsServerManager {
+ struct ClassInfo {
+ String name;
+ CreatePhysicsServerCallback create_callback;
+
+ ClassInfo()
+ : name(""), create_callback(NULL) {}
+
+ ClassInfo(String p_name, CreatePhysicsServerCallback p_create_callback)
+ : name(p_name), create_callback(p_create_callback) {}
+
+ ClassInfo(const ClassInfo &p_ci)
+ : name(p_ci.name), create_callback(p_ci.create_callback) {}
+ };
+
+ static Vector<ClassInfo> physics_servers;
+ static int default_server_id;
+ static int default_server_priority;
+
+public:
+ static const String setting_property_name;
+
+private:
+ static void on_servers_changed();
+
+public:
+ static void register_server(const String &p_name, CreatePhysicsServerCallback p_creat_callback);
+ static void set_default_server(const String &p_name, int p_priority = 0);
+ static int find_server_id(const String &p_name);
+ static int get_servers_count();
+ static String get_server_name(int p_id);
+ static PhysicsServer *new_default_server();
+ static PhysicsServer *new_server(const String &p_name);
+};
+
VARIANT_ENUM_CAST(PhysicsServer::ShapeType);
VARIANT_ENUM_CAST(PhysicsServer::SpaceParameter);
VARIANT_ENUM_CAST(PhysicsServer::AreaParameter);
diff --git a/servers/register_server_types.cpp b/servers/register_server_types.cpp
index 845a3443b7..99493afc40 100644
--- a/servers/register_server_types.cpp
+++ b/servers/register_server_types.cpp
@@ -28,11 +28,11 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "register_server_types.h"
+#include "engine.h"
#include "project_settings.h"
#include "arvr/arvr_interface.h"
#include "arvr/arvr_positional_tracker.h"
-#include "arvr/arvr_script_interface.h"
#include "arvr_server.h"
#include "audio/audio_effect.h"
#include "audio/audio_stream.h"
@@ -50,6 +50,9 @@
#include "audio/effects/audio_effect_reverb.h"
#include "audio/effects/audio_effect_stereo_enhance.h"
#include "audio_server.h"
+#include "physics/physics_server_sw.h"
+#include "physics_2d/physics_2d_server_sw.h"
+#include "physics_2d/physics_2d_server_wrap_mt.h"
#include "physics_2d_server.h"
#include "physics_server.h"
#include "script_debugger_remote.h"
@@ -74,27 +77,34 @@ static void _debugger_get_resource_usage(List<ScriptDebuggerRemote::ResourceUsag
}
ShaderTypes *shader_types = NULL;
-ARVRServer *arvr_server = NULL;
+
+PhysicsServer *_createGodotPhysicsCallback() {
+ return memnew(PhysicsServerSW);
+}
+
+Physics2DServer *_createGodotPhysics2DCallback() {
+ return Physics2DServerWrapMT::init_server<Physics2DServerSW>();
+}
void register_server_types() {
- arvr_server = memnew(ARVRServer);
- ProjectSettings::get_singleton()->add_singleton(ProjectSettings::Singleton("VisualServer", VisualServer::get_singleton()));
- ProjectSettings::get_singleton()->add_singleton(ProjectSettings::Singleton("AudioServer", AudioServer::get_singleton()));
- ProjectSettings::get_singleton()->add_singleton(ProjectSettings::Singleton("PhysicsServer", PhysicsServer::get_singleton()));
- ProjectSettings::get_singleton()->add_singleton(ProjectSettings::Singleton("Physics2DServer", Physics2DServer::get_singleton()));
- ProjectSettings::get_singleton()->add_singleton(ProjectSettings::Singleton("ARVRServer", ARVRServer::get_singleton()));
+ ClassDB::register_virtual_class<VisualServer>();
+ ClassDB::register_class<AudioServer>();
+ ClassDB::register_virtual_class<PhysicsServer>();
+ ClassDB::register_virtual_class<Physics2DServer>();
+ ClassDB::register_class<ARVRServer>();
shader_types = memnew(ShaderTypes);
ClassDB::register_virtual_class<ARVRInterface>();
ClassDB::register_class<ARVRPositionalTracker>();
- ClassDB::register_class<ARVRScriptInterface>();
ClassDB::register_virtual_class<AudioStream>();
ClassDB::register_virtual_class<AudioStreamPlayback>();
ClassDB::register_class<AudioStreamRandomPitch>();
ClassDB::register_virtual_class<AudioEffect>();
+ ClassDB::register_class<AudioEffectEQ>();
+ ClassDB::register_class<AudioEffectFilter>();
ClassDB::register_class<AudioBusLayout>();
{
@@ -140,13 +150,31 @@ void register_server_types() {
ClassDB::register_virtual_class<PhysicsShapeQueryResult>();
ScriptDebuggerRemote::resource_usage_func = _debugger_get_resource_usage;
+
+ // Physics 2D
+ GLOBAL_DEF(Physics2DServerManager::setting_property_name, "DEFAULT");
+ ProjectSettings::get_singleton()->set_custom_property_info(Physics2DServerManager::setting_property_name, PropertyInfo(Variant::STRING, Physics2DServerManager::setting_property_name, PROPERTY_HINT_ENUM, "DEFAULT"));
+
+ Physics2DServerManager::register_server("GodotPhysics", &_createGodotPhysics2DCallback);
+ Physics2DServerManager::set_default_server("GodotPhysics");
+
+ // Physics 3D
+ GLOBAL_DEF(PhysicsServerManager::setting_property_name, "DEFAULT");
+ ProjectSettings::get_singleton()->set_custom_property_info(PhysicsServerManager::setting_property_name, PropertyInfo(Variant::STRING, PhysicsServerManager::setting_property_name, PROPERTY_HINT_ENUM, "DEFAULT"));
+
+ PhysicsServerManager::register_server("GodotPhysics", &_createGodotPhysicsCallback);
+ PhysicsServerManager::set_default_server("GodotPhysics");
}
void unregister_server_types() {
- //@TODO move this into iPhone/Android implementation? just have this here for testing...
- // mobile_interface = NULL;
-
memdelete(shader_types);
- memdelete(arvr_server);
+}
+
+void register_server_singletons() {
+ Engine::get_singleton()->add_singleton(Engine::Singleton("VisualServer", VisualServer::get_singleton()));
+ Engine::get_singleton()->add_singleton(Engine::Singleton("AudioServer", AudioServer::get_singleton()));
+ Engine::get_singleton()->add_singleton(Engine::Singleton("PhysicsServer", PhysicsServer::get_singleton()));
+ Engine::get_singleton()->add_singleton(Engine::Singleton("Physics2DServer", Physics2DServer::get_singleton()));
+ Engine::get_singleton()->add_singleton(Engine::Singleton("ARVRServer", ARVRServer::get_singleton()));
}
diff --git a/servers/register_server_types.h b/servers/register_server_types.h
index 2b3ac816ac..e53626ca30 100644
--- a/servers/register_server_types.h
+++ b/servers/register_server_types.h
@@ -33,4 +33,6 @@
void register_server_types();
void unregister_server_types();
+void register_server_singletons();
+
#endif // REGISTER_SERVER_TYPES_H
diff --git a/servers/server_wrap_mt_common.h b/servers/server_wrap_mt_common.h
index 267e5c63b9..51e7f446ea 100644
--- a/servers/server_wrap_mt_common.h
+++ b/servers/server_wrap_mt_common.h
@@ -775,3 +775,12 @@
server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11); \
} \
}
+
+#define FUNC12(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_arg9, m_arg10, m_arg11, m_arg12) \
+ virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8, m_arg9 p9, m_arg10 p10, m_arg11 p11, m_arg12 p12) { \
+ if (Thread::get_caller_id() != server_thread) { \
+ command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12); \
+ } else { \
+ server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12); \
+ } \
+ }
diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h
index b3f6b243de..21d059c48e 100644
--- a/servers/visual/rasterizer.h
+++ b/servers/visual/rasterizer.h
@@ -65,7 +65,7 @@ public:
virtual void environment_set_fog(RID p_env, bool p_enable, float p_begin, float p_end, RID p_gradient_texture) = 0;
virtual void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance, bool p_roughness) = 0;
- virtual void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_radius2, float p_intensity2, float p_bias, float p_light_affect, const Color &p_color, bool p_blur) = 0;
+ virtual void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_radius2, float p_intensity2, float p_bias, float p_light_affect, const Color &p_color, VS::EnvironmentSSAOQuality p_quality, VS::EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness) = 0;
virtual void environment_set_tonemap(RID p_env, VS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) = 0;
@@ -234,7 +234,7 @@ public:
virtual RID mesh_create() = 0;
- virtual void mesh_add_surface(RID p_mesh, uint32_t p_format, VS::PrimitiveType p_primitive, const PoolVector<uint8_t> &p_array, int p_vertex_count, const PoolVector<uint8_t> &p_index_array, int p_index_count, const Rect3 &p_aabb, const Vector<PoolVector<uint8_t> > &p_blend_shapes = Vector<PoolVector<uint8_t> >(), const Vector<Rect3> &p_bone_aabbs = Vector<Rect3>()) = 0;
+ virtual void mesh_add_surface(RID p_mesh, uint32_t p_format, VS::PrimitiveType p_primitive, const PoolVector<uint8_t> &p_array, int p_vertex_count, const PoolVector<uint8_t> &p_index_array, int p_index_count, const AABB &p_aabb, const Vector<PoolVector<uint8_t> > &p_blend_shapes = Vector<PoolVector<uint8_t> >(), const Vector<AABB> &p_bone_aabbs = Vector<AABB>()) = 0;
virtual void mesh_set_blend_shape_count(RID p_mesh, int p_amount) = 0;
virtual int mesh_get_blend_shape_count(RID p_mesh) const = 0;
@@ -242,6 +242,8 @@ public:
virtual void mesh_set_blend_shape_mode(RID p_mesh, VS::BlendShapeMode p_mode) = 0;
virtual VS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const = 0;
+ virtual void mesh_surface_update_region(RID p_mesh, int p_surface, int p_offset, const PoolVector<uint8_t> &p_data) = 0;
+
virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) = 0;
virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const = 0;
@@ -254,17 +256,17 @@ public:
virtual uint32_t mesh_surface_get_format(RID p_mesh, int p_surface) const = 0;
virtual VS::PrimitiveType mesh_surface_get_primitive_type(RID p_mesh, int p_surface) const = 0;
- virtual Rect3 mesh_surface_get_aabb(RID p_mesh, int p_surface) const = 0;
+ virtual AABB mesh_surface_get_aabb(RID p_mesh, int p_surface) const = 0;
virtual Vector<PoolVector<uint8_t> > mesh_surface_get_blend_shapes(RID p_mesh, int p_surface) const = 0;
- virtual Vector<Rect3> mesh_surface_get_skeleton_aabb(RID p_mesh, int p_surface) const = 0;
+ virtual Vector<AABB> mesh_surface_get_skeleton_aabb(RID p_mesh, int p_surface) const = 0;
virtual void mesh_remove_surface(RID p_mesh, int p_index) = 0;
virtual int mesh_get_surface_count(RID p_mesh) const = 0;
- virtual void mesh_set_custom_aabb(RID p_mesh, const Rect3 &p_aabb) = 0;
- virtual Rect3 mesh_get_custom_aabb(RID p_mesh) const = 0;
+ virtual void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) = 0;
+ virtual AABB mesh_get_custom_aabb(RID p_mesh) const = 0;
- virtual Rect3 mesh_get_aabb(RID p_mesh, RID p_skeleton) const = 0;
+ virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton) const = 0;
virtual void mesh_clear(RID p_mesh) = 0;
/* MULTIMESH API */
@@ -288,7 +290,7 @@ public:
virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible) = 0;
virtual int multimesh_get_visible_instances(RID p_multimesh) const = 0;
- virtual Rect3 multimesh_get_aabb(RID p_multimesh) const = 0;
+ virtual AABB multimesh_get_aabb(RID p_multimesh) const = 0;
/* IMMEDIATE API */
@@ -304,7 +306,7 @@ public:
virtual void immediate_clear(RID p_immediate) = 0;
virtual void immediate_set_material(RID p_immediate, RID p_material) = 0;
virtual RID immediate_get_material(RID p_immediate) const = 0;
- virtual Rect3 immediate_get_aabb(RID p_immediate) const = 0;
+ virtual AABB immediate_get_aabb(RID p_immediate) const = 0;
/* SKELETON API */
@@ -320,6 +322,10 @@ public:
virtual RID light_create(VS::LightType p_type) = 0;
+ RID directional_light_create() { return light_create(VS::LIGHT_DIRECTIONAL); }
+ RID omni_light_create() { return light_create(VS::LIGHT_OMNI); }
+ RID spot_light_create() { return light_create(VS::LIGHT_SPOT); }
+
virtual void light_set_color(RID p_light, const Color &p_color) = 0;
virtual void light_set_param(RID p_light, VS::LightParam p_param, float p_value) = 0;
virtual void light_set_shadow(RID p_light, bool p_enabled) = 0;
@@ -344,7 +350,7 @@ public:
virtual bool light_has_shadow(RID p_light) const = 0;
virtual VS::LightType light_get_type(RID p_light) const = 0;
- virtual Rect3 light_get_aabb(RID p_light) const = 0;
+ virtual AABB light_get_aabb(RID p_light) const = 0;
virtual float light_get_param(RID p_light, VS::LightParam p_param) = 0;
virtual Color light_get_color(RID p_light) = 0;
virtual uint64_t light_get_version(RID p_light) const = 0;
@@ -366,7 +372,7 @@ public:
virtual void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) = 0;
virtual void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) = 0;
- virtual Rect3 reflection_probe_get_aabb(RID p_probe) const = 0;
+ virtual AABB reflection_probe_get_aabb(RID p_probe) const = 0;
virtual VS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const = 0;
virtual uint32_t reflection_probe_get_cull_mask(RID p_probe) const = 0;
virtual Vector3 reflection_probe_get_extents(RID p_probe) const = 0;
@@ -384,8 +390,8 @@ public:
virtual RID gi_probe_create() = 0;
- virtual void gi_probe_set_bounds(RID p_probe, const Rect3 &p_bounds) = 0;
- virtual Rect3 gi_probe_get_bounds(RID p_probe) const = 0;
+ virtual void gi_probe_set_bounds(RID p_probe, const AABB &p_bounds) = 0;
+ virtual AABB gi_probe_get_bounds(RID p_probe) const = 0;
virtual void gi_probe_set_cell_size(RID p_probe, float p_range) = 0;
virtual float gi_probe_get_cell_size(RID p_probe) const = 0;
@@ -440,7 +446,7 @@ public:
virtual void particles_set_pre_process_time(RID p_particles, float p_time) = 0;
virtual void particles_set_explosiveness_ratio(RID p_particles, float p_ratio) = 0;
virtual void particles_set_randomness_ratio(RID p_particles, float p_ratio) = 0;
- virtual void particles_set_custom_aabb(RID p_particles, const Rect3 &p_aabb) = 0;
+ virtual void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) = 0;
virtual void particles_set_speed_scale(RID p_particles, float p_scale) = 0;
virtual void particles_set_use_local_coordinates(RID p_particles, bool p_enable) = 0;
virtual void particles_set_process_material(RID p_particles, RID p_material) = 0;
@@ -454,8 +460,8 @@ public:
virtual void particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) = 0;
virtual void particles_request_process(RID p_particles) = 0;
- virtual Rect3 particles_get_current_aabb(RID p_particles) = 0;
- virtual Rect3 particles_get_aabb(RID p_particles) const = 0;
+ virtual AABB particles_get_current_aabb(RID p_particles) = 0;
+ virtual AABB particles_get_aabb(RID p_particles) const = 0;
virtual void particles_set_emission_transform(RID p_particles, const Transform &p_transform) = 0;
@@ -876,7 +882,7 @@ public:
case Item::Command::TYPE_MESH: {
const Item::CommandMesh *mesh = static_cast<const Item::CommandMesh *>(c);
- Rect3 aabb = RasterizerStorage::base_singleton->mesh_get_aabb(mesh->mesh, mesh->skeleton);
+ AABB aabb = RasterizerStorage::base_singleton->mesh_get_aabb(mesh->mesh, mesh->skeleton);
r = Rect2(aabb.position.x, aabb.position.y, aabb.size.x, aabb.size.y);
@@ -884,7 +890,7 @@ public:
case Item::Command::TYPE_MULTIMESH: {
const Item::CommandMultiMesh *multimesh = static_cast<const Item::CommandMultiMesh *>(c);
- Rect3 aabb = RasterizerStorage::base_singleton->multimesh_get_aabb(multimesh->multimesh);
+ AABB aabb = RasterizerStorage::base_singleton->multimesh_get_aabb(multimesh->multimesh);
r = Rect2(aabb.position.x, aabb.position.y, aabb.size.x, aabb.size.y);
@@ -893,7 +899,7 @@ public:
const Item::CommandParticles *particles_cmd = static_cast<const Item::CommandParticles *>(c);
if (particles_cmd->particles.is_valid()) {
- Rect3 aabb = RasterizerStorage::base_singleton->particles_get_aabb(particles_cmd->particles);
+ AABB aabb = RasterizerStorage::base_singleton->particles_get_aabb(particles_cmd->particles);
r = Rect2(aabb.position.x, aabb.position.y, aabb.size.x, aabb.size.y);
}
diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp
index b2a11deea1..8fee6050a0 100644
--- a/servers/visual/shader_language.cpp
+++ b/servers/visual/shader_language.cpp
@@ -2586,6 +2586,8 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
} else if (tk.type == TK_BRACKET_OPEN) {
Node *index = _parse_and_reduce_expression(p_block, p_builtin_types);
+ if (!index)
+ return NULL;
if (index->get_datatype() != TYPE_INT && index->get_datatype() != TYPE_UINT) {
_set_error("Only integer datatypes are allowed for indexing");
diff --git a/servers/visual/visual_server_canvas.h b/servers/visual/visual_server_canvas.h
index 09ac9959f9..a92370f1f0 100644
--- a/servers/visual/visual_server_canvas.h
+++ b/servers/visual/visual_server_canvas.h
@@ -175,7 +175,7 @@ public:
void canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color);
void canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color);
void canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, RID p_normal_map = RID());
- void canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, RID p_normal_map = RID(), bool p_clip_uv = true);
+ void canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, RID p_normal_map = RID(), bool p_clip_uv = false);
void canvas_item_add_nine_patch(RID p_item, const Rect2 &p_rect, const Rect2 &p_source, RID p_texture, const Vector2 &p_topleft, const Vector2 &p_bottomright, VS::NinePatchAxisMode p_x_axis_mode = VS::NINE_PATCH_STRETCH, VS::NinePatchAxisMode p_y_axis_mode = VS::NINE_PATCH_STRETCH, bool p_draw_center = true, const Color &p_modulate = Color(1, 1, 1), RID p_normal_map = RID());
void canvas_item_add_primitive(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture, float p_width = 1.0, RID p_normal_map = RID());
void canvas_item_add_polygon(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), RID p_texture = RID(), RID p_normal_map = RID(), bool p_antialiased = false);
diff --git a/servers/visual/visual_server_raster.cpp b/servers/visual/visual_server_raster.cpp
index 68ca586caf..9432d3fdd9 100644
--- a/servers/visual/visual_server_raster.cpp
+++ b/servers/visual/visual_server_raster.cpp
@@ -90,17 +90,10 @@ void VisualServerRaster::request_frame_drawn_callback(Object *p_where, const Str
fdc.param = p_userdata;
frame_drawn_callbacks.push_back(fdc);
-
- print_line("added callback to draw");
}
void VisualServerRaster::draw() {
- /*
- if (changes)
- print_line("changes: "+itos(changes));
- */
-
changes = 0;
VSG::rasterizer->begin_frame();
@@ -109,9 +102,8 @@ void VisualServerRaster::draw() {
VSG::viewport->draw_viewports();
VSG::scene->render_probes();
- //_draw_cursors_and_margins();
+ _draw_margins();
VSG::rasterizer->end_frame();
- //draw_extra_frame=VS:rasterizer->needs_to_draw_next_frame();
while (frame_drawn_callbacks.front()) {
@@ -129,7 +121,7 @@ void VisualServerRaster::draw() {
frame_drawn_callbacks.pop_front();
}
- _draw_margins();
+ emit_signal("frame_drawn_in_thread");
}
void VisualServerRaster::sync() {
}
diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h
index 888fb29f93..7551485919 100644
--- a/servers/visual/visual_server_raster.h
+++ b/servers/visual/visual_server_raster.h
@@ -73,527 +73,12 @@ class VisualServerRaster : public VisualServer {
List<FrameDrawnCallbacks> frame_drawn_callbacks;
-// FIXME: Kept as reference for future implementation
-#if 0
- struct Room {
-
- bool occlude_exterior;
- BSP_Tree bounds;
- Room() { occlude_exterior=true; }
- };
-
-
- BalloonAllocator<> octree_allocator;
-
- struct OctreeAllocator {
-
- static BalloonAllocator<> *allocator;
-
- _FORCE_INLINE_ static void *alloc(size_t p_size) { return allocator->alloc(p_size); }
- _FORCE_INLINE_ static void free(void *p_ptr) { return allocator->free(p_ptr); }
-
- };
-
- struct Portal {
-
- bool enabled;
- float disable_distance;
- Color disable_color;
- float connect_range;
- Vector<Point2> shape;
- Rect2 bounds;
-
-
- Portal() { enabled=true; disable_distance=50; disable_color=Color(); connect_range=0.8; }
- };
-
- struct BakedLight {
-
- Rasterizer::BakedLightData data;
- PoolVector<int> sampler;
- Rect3 octree_aabb;
- Size2i octree_tex_size;
- Size2i light_tex_size;
-
- };
-
- struct BakedLightSampler {
-
- float params[BAKED_LIGHT_SAMPLER_MAX];
- int resolution;
- Vector<Vector3> dp_cache;
-
- BakedLightSampler() {
- params[BAKED_LIGHT_SAMPLER_STRENGTH]=1.0;
- params[BAKED_LIGHT_SAMPLER_ATTENUATION]=1.0;
- params[BAKED_LIGHT_SAMPLER_RADIUS]=1.0;
- params[BAKED_LIGHT_SAMPLER_DETAIL_RATIO]=0.1;
- resolution=16;
- }
- };
-
- void _update_baked_light_sampler_dp_cache(BakedLightSampler * blsamp);
- struct Camera {
-
- enum Type {
- PERSPECTIVE,
- ORTHOGONAL
- };
- Type type;
- float fov;
- float znear,zfar;
- float size;
- uint32_t visible_layers;
- bool vaspect;
- RID env;
-
- Transform transform;
-
- Camera() {
-
- visible_layers=0xFFFFFFFF;
- fov=60;
- type=PERSPECTIVE;
- znear=0.1; zfar=100;
- size=1.0;
- vaspect=false;
-
- }
- };
-
-
- struct Instance;
- typedef Set<Instance*,Comparator<Instance*>,OctreeAllocator> InstanceSet;
- struct Scenario;
-
- struct Instance {
-
- enum {
-
- MAX_LIGHTS=4
- };
-
- RID self;
- OctreeElementID octree_id;
- Scenario *scenario;
- bool update;
- bool update_aabb;
- bool update_materials;
- Instance *update_next;
- InstanceType base_type;
-
- RID base_rid;
-
- Rect3 aabb;
- Rect3 transformed_aabb;
- uint32_t object_ID;
- bool visible;
- bool visible_in_all_rooms;
- uint32_t layer_mask;
- float draw_range_begin;
- float draw_range_end;
- float extra_margin;
-
-
-
- Rasterizer::InstanceData data;
-
-
- Set<Instance*> auto_rooms;
- Set<Instance*> valid_auto_rooms;
- Instance *room;
- List<Instance*>::Element *RE;
- Instance *baked_light;
- List<Instance*>::Element *BLE;
- Instance *sampled_light;
- bool exterior;
-
- uint64_t last_render_pass;
- uint64_t last_frame_pass;
-
- uint64_t version; // changes to this, and changes to base increase version
-
- InstanceSet lights;
- bool light_cache_dirty;
-
-
-
- struct RoomInfo {
-
- Transform affine_inverse;
- Room *room;
- List<Instance*> owned_geometry_instances;
- List<Instance*> owned_portal_instances;
- List<Instance*> owned_room_instances;
- List<Instance*> owned_light_instances; //not used, but just for the sake of it
- Set<Instance*> disconnected_child_portals;
- Set<Instance*> owned_autoroom_geometry;
- uint64_t last_visited_pass;
- RoomInfo() { last_visited_pass=0; }
-
- };
-
- struct PortalInfo {
-
- Portal *portal;
- Set<Instance*> candidate_set;
- Instance *connected;
- uint64_t last_visited_pass;
-
- Plane plane_cache;
- Vector<Vector3> transformed_point_cache;
-
-
- PortalInfo() { connected=NULL; last_visited_pass=0;}
- };
-
- struct LightInfo {
-
- RID instance;
- int light_set_index;
- uint64_t last_version;
- uint64_t last_add_pass;
- List<RID>::Element *D; // directional light in scenario
- InstanceSet affected;
- bool enabled;
- float dtc; //distance to camera, used for sorting
-
-
- LightInfo() {
-
- D=NULL;
- light_set_index=-1;
- last_add_pass=0;
- enabled=true;
- }
- };
-
- struct BakedLightInfo {
-
- BakedLight *baked_light;
- Transform affine_inverse;
- List<Instance*> owned_instances;
- };
-
- struct BakedLightSamplerInfo {
-
- Set<Instance*> baked_lights;
- Set<Instance*> owned_instances;
- BakedLightSampler *sampler;
- int resolution;
- Vector<Color> light_bufer;
- RID sampled_light;
- uint64_t last_pass;
- Transform xform; // viewspace normal to lightspace, might not use one.
- BakedLightSamplerInfo() {
- sampler=NULL;
- last_pass=0;
- resolution=0;
- }
- };
-
- struct ParticlesInfo {
-
- RID instance;
- };
-
-
- RoomInfo *room_info;
- LightInfo *light_info;
- ParticlesInfo *particles_info;
- PortalInfo * portal_info;
- BakedLightInfo * baked_light_info;
- BakedLightSamplerInfo * baked_light_sampler_info;
-
-
- Instance() {
- octree_id=0;
- update_next=0;
- object_ID=0;
- last_render_pass=0;
- last_frame_pass=0;
- light_info=0;
- particles_info=0;
- update_next=NULL;
- update=false;
- visible=true;
- data.cast_shadows=SHADOW_CASTING_SETTING_ON;
- data.receive_shadows=true;
- data.depth_scale=false;
- data.billboard=false;
- data.billboard_y=false;
- data.baked_light=NULL;
- data.baked_light_octree_xform=NULL;
- data.baked_lightmap_id=-1;
- version=1;
- room_info=NULL;
- room=NULL;
- RE=NULL;
- portal_info=NULL;
- exterior=false;
- layer_mask=1;
- draw_range_begin=0;
- draw_range_end=0;
- extra_margin=0;
- visible_in_all_rooms=false;
- update_aabb=false;
- update_materials=false;
-
- baked_light=NULL;
- baked_light_info=NULL;
- baked_light_sampler_info=NULL;
- sampled_light=NULL;
- BLE=NULL;
-
- light_cache_dirty=true;
-
- }
-
- ~Instance() {
-
- if (light_info)
- memdelete(light_info);
- if (particles_info)
- memdelete(particles_info);
- if (room_info)
- memdelete(room_info);
- if (portal_info)
- memdelete(portal_info);
- if (baked_light_info)
- memdelete(baked_light_info);
- };
- };
-
- struct _InstanceLightsort {
-
- bool operator()(const Instance* p_A, const Instance* p_B) const { return p_A->light_info->dtc < p_B->light_info->dtc; }
- };
-
- struct Scenario {
-
-
- ScenarioDebugMode debug;
- RID self;
- // well wtf, balloon allocator is slower?
- typedef ::Octree<Instance,true> Octree;
-
- Octree octree;
-
- List<RID> directional_lights;
- RID environment;
- RID fallback_environment;
-
- Instance *dirty_instances;
-
- Scenario() { dirty_instances=NULL; debug=SCENARIO_DEBUG_DISABLED; }
- };
-
-
-
- mutable RID_Owner<Rasterizer::ShaderMaterial> canvas_item_material_owner;
-
-
-
- struct Viewport {
-
- RID self;
- RID parent;
-
- VisualServer::ViewportRect rect;
- RID camera;
- RID scenario;
- RID viewport_data;
-
- RenderTargetUpdateMode render_target_update_mode;
- RID render_target;
- RID render_target_texture;
-
- Rect2 rt_to_screen_rect;
-
- bool hide_scenario;
- bool hide_canvas;
- bool transparent_bg;
- bool queue_capture;
- bool render_target_vflip;
- bool render_target_clear_on_new_frame;
- bool render_target_clear;
- bool disable_environment;
-
- Image capture;
-
- bool rendered_in_prev_frame;
-
- struct CanvasKey {
-
- int layer;
- RID canvas;
- bool operator<(const CanvasKey& p_canvas) const { if (layer==p_canvas.layer) return canvas < p_canvas.canvas; return layer<p_canvas.layer; }
- CanvasKey() { layer=0; }
- CanvasKey(const RID& p_canvas, int p_layer) { canvas=p_canvas; layer=p_layer; }
- };
-
- struct CanvasData {
-
- Canvas *canvas;
- Transform2D transform;
- int layer;
- };
-
- Transform2D global_transform;
-
- Map<RID,CanvasData> canvas_map;
-
- SelfList<Viewport> update_list;
-
- Viewport() : update_list(this) { transparent_bg=false; render_target_update_mode=RENDER_TARGET_UPDATE_WHEN_VISIBLE; queue_capture=false; rendered_in_prev_frame=false; render_target_vflip=false; render_target_clear_on_new_frame=true; render_target_clear=true; disable_environment=false; }
- };
-
- SelfList<Viewport>::List viewport_update_list;
-
- Map<RID,int> screen_viewports;
-
- struct CullRange {
-
- Plane nearp;
- float min,max;
- float z_near,z_far;
-
- void add_aabb(const Rect3& p_aabb) {
-
-
- }
- };
-
- struct Cursor {
-
- Point2 pos;
- float rot;
- RID texture;
- Point2 center;
- bool visible;
- Rect2 region;
- Cursor() {
-
- rot = 0;
- visible = false;
- region = Rect2();
- };
- };
-
- Rect2 canvas_clip;
- Color clear_color;
- Cursor cursors[MAX_CURSORS];
- RID default_cursor_texture;
-
- static void* instance_pair(void *p_self, OctreeElementID,Instance *p_A,int, OctreeElementID,Instance *p_B,int);
- static void instance_unpair(void *p_self, OctreeElementID,Instance *p_A,int, OctreeElementID,Instance *p_B,int,void*);
-
- Instance *instance_cull_result[MAX_INSTANCE_CULL];
- Instance *instance_shadow_cull_result[MAX_INSTANCE_CULL]; //used for generating shadowmaps
- Instance *light_cull_result[MAX_LIGHTS_CULLED];
- int light_cull_count;
-
- Instance *exterior_portal_cull_result[MAX_EXTERIOR_PORTALS];
- int exterior_portal_cull_count;
- bool exterior_visited;
-
- Instance *light_sampler_cull_result[MAX_LIGHT_SAMPLERS];
- int light_samplers_culled;
-
- Instance *room_cull_result[MAX_ROOM_CULL];
- int room_cull_count;
- bool room_cull_enabled;
- bool light_discard_enabled;
- bool shadows_enabled;
- int black_margin[4];
- RID black_image[4];
-
- Vector<Vector3> aabb_random_points;
- Vector<Vector3> transformed_aabb_random_points;
-
- void _instance_validate_autorooms(Instance *p_geometry);
-
- void _portal_disconnect(Instance *p_portal,bool p_cleanup=false);
- void _portal_attempt_connect(Instance *p_portal);
- void _dependency_queue_update(RID p_rid, bool p_update_aabb=false, bool p_update_materials=false);
- _FORCE_INLINE_ void _instance_queue_update(Instance *p_instance,bool p_update_aabb=false,bool p_update_materials=false);
- void _update_instances();
- void _update_instance_aabb(Instance *p_instance);
- void _update_instance(Instance *p_instance);
- void _free_attached_instances(RID p_rid,bool p_free_scenario=false);
- void _clean_up_owner(RID_OwnerBase *p_owner,String p_type);
-
- Instance *instance_update_list;
-
- //RID default_scenario;
- //RID default_viewport;
-
- RID test_cube;
-
-
- mutable RID_Owner<Room> room_owner;
- mutable RID_Owner<Portal> portal_owner;
-
- mutable RID_Owner<BakedLight> baked_light_owner;
- mutable RID_Owner<BakedLightSampler> baked_light_sampler_owner;
-
- mutable RID_Owner<Camera> camera_owner;
- mutable RID_Owner<Viewport> viewport_owner;
-
- mutable RID_Owner<Scenario> scenario_owner;
- mutable RID_Owner<Instance> instance_owner;
-
- mutable RID_Owner<Canvas> canvas_owner;
- mutable RID_Owner<CanvasItem> canvas_item_owner;
-
- Map< RID, Set<RID> > instance_dependency_map;
- Map< RID, Set<Instance*> > skeleton_dependency_map;
-
-
- ViewportRect viewport_rect;
- _FORCE_INLINE_ void _instance_draw(Instance *p_instance);
-
- bool _test_portal_cull(Camera *p_camera, Instance *p_portal_from, Instance *p_portal_to);
- void _cull_portal(Camera *p_camera, Instance *p_portal,Instance *p_from_portal);
- void _cull_room(Camera *p_camera, Instance *p_room,Instance *p_from_portal=NULL);
- void _process_sampled_light(const Transform &p_camera, Instance *p_sampled_light, bool p_linear_colorspace);
-
- void _render_no_camera(Viewport *p_viewport,Camera *p_camera, Scenario *p_scenario);
- void _render_camera(Viewport *p_viewport,Camera *p_camera, Scenario *p_scenario);
- static void _render_canvas_item_viewport(VisualServer* p_self,void *p_vp,const Rect2& p_rect);
- void _render_canvas_item_tree(CanvasItem *p_canvas_item, const Transform2D& p_transform, const Rect2& p_clip_rect, const Color &p_modulate, Rasterizer::CanvasLight *p_lights);
- void _render_canvas_item(CanvasItem *p_canvas_item, const Transform2D& p_transform, const Rect2& p_clip_rect, float p_opacity, int p_z, Rasterizer::CanvasItem **z_list, Rasterizer::CanvasItem **z_last_list, CanvasItem *p_canvas_clip, CanvasItem *p_material_owner);
- void _render_canvas(Canvas *p_canvas, const Transform2D &p_transform, Rasterizer::CanvasLight *p_lights, Rasterizer::CanvasLight *p_masked_lights);
- void _light_mask_canvas_items(int p_z,Rasterizer::CanvasItem *p_canvas_item,Rasterizer::CanvasLight *p_masked_lights);
-
- Vector<Vector3> _camera_generate_endpoints(Instance *p_light,Camera *p_camera,float p_range_min, float p_range_max);
- Vector<Plane> _camera_generate_orthogonal_planes(Instance *p_light,Camera *p_camera,float p_range_min, float p_range_max);
-
- void _light_instance_update_lispsm_shadow(Instance *p_light,Scenario *p_scenario,Camera *p_camera,const CullRange& p_cull_range);
- void _light_instance_update_pssm_shadow(Instance *p_light,Scenario *p_scenario,Camera *p_camera,const CullRange& p_cull_range);
-
- void _light_instance_update_shadow(Instance *p_light,Scenario *p_scenario,Camera *p_camera,const CullRange& p_cull_range);
-
- uint64_t render_pass;
- int changes;
- bool draw_extra_frame;
-
- void _draw_viewport_camera(Viewport *p_viewport, bool p_ignore_camera);
- void _draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_ofs_y,int p_parent_w,int p_parent_h);
- void _draw_viewports();
- void _draw_cursors_and_margins();
-
-
- Rasterizer *rasterizer;
-
-#endif
-
void _draw_margins();
static void _changes_changed() {}
public:
-//if editor is redrawing when it shouldn't, enable this and put a breakpoint in _changes_changed()
-//#define DEBUG_CHANGES
+ //if editor is redrawing when it shouldn't, enable this and put a breakpoint in _changes_changed()
+ //#define DEBUG_CHANGES
#ifdef DEBUG_CHANGES
_FORCE_INLINE_ static void redraw_request() {
@@ -611,7 +96,7 @@ public:
#define DISPLAY_CHANGED \
changes++;
#endif
-// print_line(String("CHANGED: ") + __FUNCTION__);
+ // print_line(String("CHANGED: ") + __FUNCTION__);
#define BIND0R(m_r, m_name) \
m_r m_name() { return BINDBASE->m_name(); }
@@ -652,6 +137,8 @@ public:
void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8, m_type9 arg9, m_type10 arg10) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); }
#define BIND11(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8, m_type9, m_type10, m_type11) \
void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8, m_type9 arg9, m_type10 arg10, m_type11 arg11) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11); }
+#define BIND12(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8, m_type9, m_type10, m_type11, m_type12) \
+ void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8, m_type9 arg9, m_type10 arg10, m_type11 arg11, m_type12 arg12) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12); }
//from now on, calls forwarded to this singleton
#define BINDBASE VSG::storage
@@ -716,7 +203,7 @@ public:
BIND0R(RID, mesh_create)
- BIND10(mesh_add_surface, RID, uint32_t, PrimitiveType, const PoolVector<uint8_t> &, int, const PoolVector<uint8_t> &, int, const Rect3 &, const Vector<PoolVector<uint8_t> > &, const Vector<Rect3> &)
+ BIND10(mesh_add_surface, RID, uint32_t, PrimitiveType, const PoolVector<uint8_t> &, int, const PoolVector<uint8_t> &, int, const AABB &, const Vector<PoolVector<uint8_t> > &, const Vector<AABB> &)
BIND2(mesh_set_blend_shape_count, RID, int)
BIND1RC(int, mesh_get_blend_shape_count, RID)
@@ -724,6 +211,8 @@ public:
BIND2(mesh_set_blend_shape_mode, RID, BlendShapeMode)
BIND1RC(BlendShapeMode, mesh_get_blend_shape_mode, RID)
+ BIND4(mesh_surface_update_region, RID, int, int, const PoolVector<uint8_t> &)
+
BIND3(mesh_surface_set_material, RID, int, RID)
BIND2RC(RID, mesh_surface_get_material, RID, int)
@@ -736,15 +225,15 @@ public:
BIND2RC(uint32_t, mesh_surface_get_format, RID, int)
BIND2RC(PrimitiveType, mesh_surface_get_primitive_type, RID, int)
- BIND2RC(Rect3, mesh_surface_get_aabb, RID, int)
+ BIND2RC(AABB, mesh_surface_get_aabb, RID, int)
BIND2RC(Vector<PoolVector<uint8_t> >, mesh_surface_get_blend_shapes, RID, int)
- BIND2RC(Vector<Rect3>, mesh_surface_get_skeleton_aabb, RID, int)
+ BIND2RC(Vector<AABB>, mesh_surface_get_skeleton_aabb, RID, int)
BIND2(mesh_remove_surface, RID, int)
BIND1RC(int, mesh_get_surface_count, RID)
- BIND2(mesh_set_custom_aabb, RID, const Rect3 &)
- BIND1RC(Rect3, mesh_get_custom_aabb, RID)
+ BIND2(mesh_set_custom_aabb, RID, const AABB &)
+ BIND1RC(AABB, mesh_get_custom_aabb, RID)
BIND1(mesh_clear, RID)
@@ -761,7 +250,7 @@ public:
BIND3(multimesh_instance_set_color, RID, int, const Color &)
BIND1RC(RID, multimesh_get_mesh, RID)
- BIND1RC(Rect3, multimesh_get_aabb, RID)
+ BIND1RC(AABB, multimesh_get_aabb, RID)
BIND2RC(Transform, multimesh_instance_get_transform, RID, int)
BIND2RC(Transform2D, multimesh_instance_get_transform_2d, RID, int)
@@ -797,7 +286,9 @@ public:
/* Light API */
- BIND1R(RID, light_create, LightType)
+ BIND0R(RID, directional_light_create)
+ BIND0R(RID, omni_light_create)
+ BIND0R(RID, spot_light_create)
BIND2(light_set_color, RID, const Color &)
BIND3(light_set_param, RID, LightParam, float)
@@ -836,8 +327,8 @@ public:
BIND0R(RID, gi_probe_create)
- BIND2(gi_probe_set_bounds, RID, const Rect3 &)
- BIND1RC(Rect3, gi_probe_get_bounds, RID)
+ BIND2(gi_probe_set_bounds, RID, const AABB &)
+ BIND1RC(AABB, gi_probe_get_bounds, RID)
BIND2(gi_probe_set_cell_size, RID, float)
BIND1RC(float, gi_probe_get_cell_size, RID)
@@ -880,7 +371,7 @@ public:
BIND2(particles_set_pre_process_time, RID, float)
BIND2(particles_set_explosiveness_ratio, RID, float)
BIND2(particles_set_randomness_ratio, RID, float)
- BIND2(particles_set_custom_aabb, RID, const Rect3 &)
+ BIND2(particles_set_custom_aabb, RID, const AABB &)
BIND2(particles_set_speed_scale, RID, float)
BIND2(particles_set_use_local_coordinates, RID, bool)
BIND2(particles_set_process_material, RID, RID)
@@ -893,7 +384,7 @@ public:
BIND2(particles_set_draw_passes, RID, int)
BIND3(particles_set_draw_pass_mesh, RID, int, RID)
- BIND1R(Rect3, particles_get_current_aabb, RID)
+ BIND1R(AABB, particles_get_current_aabb, RID)
BIND2(particles_set_emission_transform, RID, const Transform &)
#undef BINDBASE
@@ -958,7 +449,7 @@ public:
BIND2R(int, viewport_get_render_info, RID, ViewportRenderInfo)
BIND2(viewport_set_debug_draw, RID, ViewportDebugDraw)
-/* ENVIRONMENT API */
+ /* ENVIRONMENT API */
#undef BINDBASE
//from now on, calls forwarded to this singleton
@@ -974,7 +465,7 @@ public:
BIND2(environment_set_canvas_max_layer, RID, int)
BIND4(environment_set_ambient_light, RID, const Color &, float, float)
BIND7(environment_set_ssr, RID, bool, int, float, float, float, bool)
- BIND10(environment_set_ssao, RID, bool, float, float, float, float, float, float, const Color &, bool)
+ BIND12(environment_set_ssao, RID, bool, float, float, float, float, float, float, const Color &, EnvironmentSSAOQuality, EnvironmentSSAOBlur, float)
BIND6(environment_set_dof_blur_near, RID, bool, float, float, float, EnvironmentDOFBlurQuality)
BIND6(environment_set_dof_blur_far, RID, bool, float, float, float, EnvironmentDOFBlurQuality)
@@ -988,7 +479,7 @@ public:
BIND6(environment_set_fog_depth, RID, bool, float, float, bool, float)
BIND5(environment_set_fog_height, RID, bool, float, float, float)
-/* SCENARIO API */
+ /* SCENARIO API */
#undef BINDBASE
#define BINDBASE VSG::scene
@@ -1013,13 +504,15 @@ public:
BIND3(instance_set_surface_material, RID, int, RID)
BIND2(instance_set_visible, RID, bool)
+ BIND2(instance_set_custom_aabb, RID, AABB)
+
BIND2(instance_attach_skeleton, RID, RID)
BIND2(instance_set_exterior, RID, bool)
BIND2(instance_set_extra_visibility_margin, RID, real_t)
// don't use these in a game!
- BIND2RC(Vector<ObjectID>, instances_cull_aabb, const Rect3 &, RID)
+ BIND2RC(Vector<ObjectID>, instances_cull_aabb, const AABB &, RID)
BIND3RC(Vector<ObjectID>, instances_cull_ray, const Vector3 &, const Vector3 &, RID)
BIND2RC(Vector<ObjectID>, instances_cull_convex, const Vector<Plane> &, RID)
diff --git a/servers/visual/visual_server_scene.cpp b/servers/visual/visual_server_scene.cpp
index e49baf0763..5b1eb8357d 100644
--- a/servers/visual/visual_server_scene.cpp
+++ b/servers/visual/visual_server_scene.cpp
@@ -587,6 +587,36 @@ void VisualServerScene::instance_set_visible(RID p_instance, bool p_visible) {
}
}
+inline bool is_geometry_instance(VisualServer::InstanceType p_type) {
+ return p_type == VS::INSTANCE_MESH || p_type == VS::INSTANCE_MULTIMESH || p_type == VS::INSTANCE_PARTICLES || p_type == VS::INSTANCE_IMMEDIATE;
+}
+
+void VisualServerScene::instance_set_custom_aabb(RID p_instance, AABB p_aabb) {
+
+ Instance *instance = instance_owner.get(p_instance);
+ ERR_FAIL_COND(!instance);
+ ERR_FAIL_COND(!is_geometry_instance(instance->base_type));
+
+ if(p_aabb != AABB()) {
+
+ // Set custom AABB
+ if (instance->custom_aabb == NULL)
+ instance->custom_aabb = memnew(AABB);
+ *instance->custom_aabb = p_aabb;
+
+ } else {
+
+ // Clear custom AABB
+ if (instance->custom_aabb != NULL) {
+ memdelete(instance->custom_aabb);
+ instance->custom_aabb = NULL;
+ }
+ }
+
+ if (instance->scenario)
+ _instance_queue_update(instance, true, false);
+}
+
void VisualServerScene::instance_attach_skeleton(RID p_instance, RID p_skeleton) {
Instance *instance = instance_owner.get(p_instance);
@@ -614,7 +644,7 @@ void VisualServerScene::instance_set_exterior(RID p_instance, bool p_enabled) {
void VisualServerScene::instance_set_extra_visibility_margin(RID p_instance, real_t p_margin) {
}
-Vector<ObjectID> VisualServerScene::instances_cull_aabb(const Rect3 &p_aabb, RID p_scenario) const {
+Vector<ObjectID> VisualServerScene::instances_cull_aabb(const AABB &p_aabb, RID p_scenario) const {
Vector<ObjectID> instances;
Scenario *scenario = scenario_owner.get(p_scenario);
@@ -772,7 +802,7 @@ void VisualServerScene::_update_instance(Instance *p_instance) {
p_instance->mirror = p_instance->transform.basis.determinant() < 0.0;
- Rect3 new_aabb;
+ AABB new_aabb;
new_aabb = p_instance->transform.xform(p_instance->aabb);
@@ -817,7 +847,7 @@ void VisualServerScene::_update_instance(Instance *p_instance) {
void VisualServerScene::_update_instance_aabb(Instance *p_instance) {
- Rect3 new_aabb;
+ AABB new_aabb;
ERR_FAIL_COND(p_instance->base_type != VS::INSTANCE_NONE && !p_instance->base.is_valid());
@@ -828,23 +858,35 @@ void VisualServerScene::_update_instance_aabb(Instance *p_instance) {
} break;
case VisualServer::INSTANCE_MESH: {
- new_aabb = VSG::storage->mesh_get_aabb(p_instance->base, p_instance->skeleton);
+ if (p_instance->custom_aabb)
+ new_aabb = *p_instance->custom_aabb;
+ else
+ new_aabb = VSG::storage->mesh_get_aabb(p_instance->base, p_instance->skeleton);
} break;
case VisualServer::INSTANCE_MULTIMESH: {
- new_aabb = VSG::storage->multimesh_get_aabb(p_instance->base);
+ if (p_instance->custom_aabb)
+ new_aabb = *p_instance->custom_aabb;
+ else
+ new_aabb = VSG::storage->multimesh_get_aabb(p_instance->base);
} break;
case VisualServer::INSTANCE_IMMEDIATE: {
- new_aabb = VSG::storage->immediate_get_aabb(p_instance->base);
+ if (p_instance->custom_aabb)
+ new_aabb = *p_instance->custom_aabb;
+ else
+ new_aabb = VSG::storage->immediate_get_aabb(p_instance->base);
} break;
case VisualServer::INSTANCE_PARTICLES: {
- new_aabb = VSG::storage->particles_get_aabb(p_instance->base);
+ if (p_instance->custom_aabb)
+ new_aabb = *p_instance->custom_aabb;
+ else
+ new_aabb = VSG::storage->particles_get_aabb(p_instance->base);
} break;
case VisualServer::INSTANCE_LIGHT: {
@@ -866,6 +908,7 @@ void VisualServerScene::_update_instance_aabb(Instance *p_instance) {
default: {}
}
+ // <Zylann> This is why I didn't re-use Instance::aabb to implement custom AABBs
if (p_instance->extra_margin)
new_aabb.grow_by(p_instance->extra_margin);
@@ -1863,7 +1906,7 @@ void VisualServerScene::_setup_gi_probe(Instance *p_instance) {
probe->dynamic.enabled = true;
Transform cell_to_xform = VSG::storage->gi_probe_get_to_cell_xform(p_instance->base);
- Rect3 bounds = VSG::storage->gi_probe_get_bounds(p_instance->base);
+ AABB bounds = VSG::storage->gi_probe_get_bounds(p_instance->base);
float cell_size = VSG::storage->gi_probe_get_cell_size(p_instance->base);
probe->dynamic.light_to_cell_xform = cell_to_xform * p_instance->transform.affine_inverse();
@@ -2562,7 +2605,7 @@ bool VisualServerScene::_check_gi_probe(Instance *p_gi_probe) {
InstanceGIProbeData::LightCache lc;
lc.type = VSG::storage->light_get_type(E->get()->base);
lc.color = VSG::storage->light_get_color(E->get()->base);
- lc.energy = VSG::storage->light_get_param(E->get()->base, VS::LIGHT_PARAM_ENERGY);
+ lc.energy = VSG::storage->light_get_param(E->get()->base, VS::LIGHT_PARAM_ENERGY) * VSG::storage->light_get_param(E->get()->base, VS::LIGHT_PARAM_INDIRECT_ENERGY);
lc.radius = VSG::storage->light_get_param(E->get()->base, VS::LIGHT_PARAM_RANGE);
lc.attenuation = VSG::storage->light_get_param(E->get()->base, VS::LIGHT_PARAM_ATTENUATION);
lc.spot_angle = VSG::storage->light_get_param(E->get()->base, VS::LIGHT_PARAM_SPOT_ANGLE);
@@ -2582,7 +2625,7 @@ bool VisualServerScene::_check_gi_probe(Instance *p_gi_probe) {
InstanceGIProbeData::LightCache lc;
lc.type = VSG::storage->light_get_type(E->get()->base);
lc.color = VSG::storage->light_get_color(E->get()->base);
- lc.energy = VSG::storage->light_get_param(E->get()->base, VS::LIGHT_PARAM_ENERGY);
+ lc.energy = VSG::storage->light_get_param(E->get()->base, VS::LIGHT_PARAM_ENERGY) * VSG::storage->light_get_param(E->get()->base, VS::LIGHT_PARAM_INDIRECT_ENERGY);
lc.radius = VSG::storage->light_get_param(E->get()->base, VS::LIGHT_PARAM_RANGE);
lc.attenuation = VSG::storage->light_get_param(E->get()->base, VS::LIGHT_PARAM_ATTENUATION);
lc.spot_angle = VSG::storage->light_get_param(E->get()->base, VS::LIGHT_PARAM_SPOT_ANGLE);
diff --git a/servers/visual/visual_server_scene.h b/servers/visual/visual_server_scene.h
index d30a2108a5..d075be76ca 100644
--- a/servers/visual/visual_server_scene.h
+++ b/servers/visual/visual_server_scene.h
@@ -195,8 +195,9 @@ public:
SelfList<Instance> update_item;
- Rect3 aabb;
- Rect3 transformed_aabb;
+ AABB aabb;
+ AABB transformed_aabb;
+ AABB *custom_aabb; // <Zylann> would using aabb directly with a bool be better?
float extra_margin;
uint32_t object_ID;
@@ -251,12 +252,16 @@ public:
last_frame_pass = 0;
version = 1;
base_data = NULL;
+
+ custom_aabb = NULL;
}
~Instance() {
if (base_data)
memdelete(base_data);
+ if (custom_aabb)
+ memdelete(custom_aabb);
}
};
@@ -460,13 +465,15 @@ public:
virtual void instance_set_surface_material(RID p_instance, int p_surface, RID p_material);
virtual void instance_set_visible(RID p_instance, bool p_visible);
+ virtual void instance_set_custom_aabb(RID p_insatnce, AABB aabb);
+
virtual void instance_attach_skeleton(RID p_instance, RID p_skeleton);
virtual void instance_set_exterior(RID p_instance, bool p_enabled);
virtual void instance_set_extra_visibility_margin(RID p_instance, real_t p_margin);
// don't use these in a game!
- virtual Vector<ObjectID> instances_cull_aabb(const Rect3 &p_aabb, RID p_scenario = RID()) const;
+ virtual Vector<ObjectID> instances_cull_aabb(const AABB &p_aabb, RID p_scenario = RID()) const;
virtual Vector<ObjectID> instances_cull_ray(const Vector3 &p_from, const Vector3 &p_to, RID p_scenario = RID()) const;
virtual Vector<ObjectID> instances_cull_convex(const Vector<Plane> &p_convex, RID p_scenario = RID()) const;
diff --git a/servers/visual/visual_server_viewport.cpp b/servers/visual/visual_server_viewport.cpp
index 0dca09a5bf..fbf593f5b9 100644
--- a/servers/visual/visual_server_viewport.cpp
+++ b/servers/visual/visual_server_viewport.cpp
@@ -54,7 +54,7 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E
bool can_draw_3d = !p_viewport->disable_3d && !p_viewport->disable_3d_by_usage && VSG::scene->camera_owner.owns(p_viewport->camera);
if (p_viewport->clear_mode != VS::VIEWPORT_CLEAR_NEVER) {
- VSG::rasterizer->clear_render_target(clear_color);
+ VSG::rasterizer->clear_render_target(p_viewport->transparent_bg ? Color(0, 0, 0, 0) : clear_color);
if (p_viewport->clear_mode == VS::VIEWPORT_CLEAR_ONLY_NEXT_FRAME) {
p_viewport->clear_mode = VS::VIEWPORT_CLEAR_NEVER;
}
@@ -268,7 +268,7 @@ void VisualServerViewport::draw_viewports() {
if (vp->use_arvr && arvr_interface.is_valid()) {
// override our size, make sure it matches our required size
- Size2 size = arvr_interface->get_recommended_render_targetsize();
+ Size2 size = arvr_interface->get_render_targetsize();
VSG::storage->render_target_set_size(vp->render_target, size.x, size.y);
// render mono or left eye first
@@ -504,6 +504,7 @@ void VisualServerViewport::viewport_set_transparent_background(RID p_viewport, b
ERR_FAIL_COND(!viewport);
VSG::storage->render_target_set_flag(viewport->render_target, RasterizerStorage::RENDER_TARGET_TRANSPARENT, p_enabled);
+ viewport->transparent_bg = true;
}
void VisualServerViewport::viewport_set_global_canvas_transform(RID p_viewport, const Transform2D &p_transform) {
diff --git a/servers/visual/visual_server_viewport.h b/servers/visual/visual_server_viewport.h
index 8a294a9129..8db6eda133 100644
--- a/servers/visual/visual_server_viewport.h
+++ b/servers/visual/visual_server_viewport.h
@@ -72,6 +72,8 @@ public:
VS::ViewportClearMode clear_mode;
+ bool transparent_bg;
+
struct CanvasKey {
int layer;
@@ -101,6 +103,7 @@ public:
Viewport() {
update_mode = VS::VIEWPORT_UPDATE_WHEN_VISIBLE;
clear_mode = VS::VIEWPORT_CLEAR_ALWAYS;
+ transparent_bg = false;
disable_environment = false;
viewport_to_screen = 0;
shadow_atlas_size = 0;
diff --git a/servers/visual/visual_server_wrap_mt.cpp b/servers/visual/visual_server_wrap_mt.cpp
index d9a0077e60..1a03c72529 100644
--- a/servers/visual/visual_server_wrap_mt.cpp
+++ b/servers/visual/visual_server_wrap_mt.cpp
@@ -154,14 +154,34 @@ void VisualServerWrapMT::finish() {
Thread::wait_to_finish(thread);
memdelete(thread);
- texture_free_cached_ids();
- //mesh_free_cached_ids();
-
thread = NULL;
} else {
visual_server->finish();
}
+ texture_free_cached_ids();
+ shader_free_cached_ids();
+ material_free_cached_ids();
+ mesh_free_cached_ids();
+ multimesh_free_cached_ids();
+ immediate_free_cached_ids();
+ skeleton_free_cached_ids();
+ directional_light_free_cached_ids();
+ omni_light_free_cached_ids();
+ spot_light_free_cached_ids();
+ reflection_probe_free_cached_ids();
+ gi_probe_free_cached_ids();
+ particles_free_cached_ids();
+ camera_free_cached_ids();
+ viewport_free_cached_ids();
+ environment_free_cached_ids();
+ scenario_free_cached_ids();
+ instance_free_cached_ids();
+ canvas_free_cached_ids();
+ canvas_item_free_cached_ids();
+ canvas_light_occluder_free_cached_ids();
+ canvas_occluder_polygon_free_cached_ids();
+
if (draw_mutex)
memdelete(draw_mutex);
}
diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h
index caec890217..e120eb5ad3 100644
--- a/servers/visual/visual_server_wrap_mt.h
+++ b/servers/visual/visual_server_wrap_mt.h
@@ -63,7 +63,7 @@ class VisualServerWrapMT : public VisualServer {
int pool_max_size;
-//#define DEBUG_SYNC
+ //#define DEBUG_SYNC
#ifdef DEBUG_SYNC
#define SYNC_DEBUG print_line("sync on: " + String(__FUNCTION__));
@@ -103,12 +103,12 @@ public:
/* SKY API */
- FUNC0R(RID, sky_create)
+ FUNCRID(sky)
FUNC3(sky_set_texture, RID, RID, int)
/* SHADER API */
- FUNC0R(RID, shader_create)
+ FUNCRID(shader)
FUNC2(shader_set_code, RID, const String &)
FUNC1RC(String, shader_get_code, RID)
@@ -120,7 +120,7 @@ public:
/* COMMON MATERIAL API */
- FUNC0R(RID, material_create)
+ FUNCRID(material)
FUNC2(material_set_shader, RID, RID)
FUNC1RC(RID, material_get_shader, RID)
@@ -134,9 +134,9 @@ public:
/* MESH API */
- FUNC0R(RID, mesh_create)
+ FUNCRID(mesh)
- FUNC10(mesh_add_surface, RID, uint32_t, PrimitiveType, const PoolVector<uint8_t> &, int, const PoolVector<uint8_t> &, int, const Rect3 &, const Vector<PoolVector<uint8_t> > &, const Vector<Rect3> &)
+ FUNC10(mesh_add_surface, RID, uint32_t, PrimitiveType, const PoolVector<uint8_t> &, int, const PoolVector<uint8_t> &, int, const AABB &, const Vector<PoolVector<uint8_t> > &, const Vector<AABB> &)
FUNC2(mesh_set_blend_shape_count, RID, int)
FUNC1RC(int, mesh_get_blend_shape_count, RID)
@@ -144,6 +144,8 @@ public:
FUNC2(mesh_set_blend_shape_mode, RID, BlendShapeMode)
FUNC1RC(BlendShapeMode, mesh_get_blend_shape_mode, RID)
+ FUNC4(mesh_surface_update_region, RID, int, int, const PoolVector<uint8_t> &)
+
FUNC3(mesh_surface_set_material, RID, int, RID)
FUNC2RC(RID, mesh_surface_get_material, RID, int)
@@ -156,21 +158,21 @@ public:
FUNC2RC(uint32_t, mesh_surface_get_format, RID, int)
FUNC2RC(PrimitiveType, mesh_surface_get_primitive_type, RID, int)
- FUNC2RC(Rect3, mesh_surface_get_aabb, RID, int)
+ FUNC2RC(AABB, mesh_surface_get_aabb, RID, int)
FUNC2RC(Vector<PoolVector<uint8_t> >, mesh_surface_get_blend_shapes, RID, int)
- FUNC2RC(Vector<Rect3>, mesh_surface_get_skeleton_aabb, RID, int)
+ FUNC2RC(Vector<AABB>, mesh_surface_get_skeleton_aabb, RID, int)
FUNC2(mesh_remove_surface, RID, int)
FUNC1RC(int, mesh_get_surface_count, RID)
- FUNC2(mesh_set_custom_aabb, RID, const Rect3 &)
- FUNC1RC(Rect3, mesh_get_custom_aabb, RID)
+ FUNC2(mesh_set_custom_aabb, RID, const AABB &)
+ FUNC1RC(AABB, mesh_get_custom_aabb, RID)
FUNC1(mesh_clear, RID)
/* MULTIMESH API */
- FUNC0R(RID, multimesh_create)
+ FUNCRID(multimesh)
FUNC4(multimesh_allocate, RID, int, MultimeshTransformFormat, MultimeshColorFormat)
FUNC1RC(int, multimesh_get_instance_count, RID)
@@ -181,7 +183,7 @@ public:
FUNC3(multimesh_instance_set_color, RID, int, const Color &)
FUNC1RC(RID, multimesh_get_mesh, RID)
- FUNC1RC(Rect3, multimesh_get_aabb, RID)
+ FUNC1RC(AABB, multimesh_get_aabb, RID)
FUNC2RC(Transform, multimesh_instance_get_transform, RID, int)
FUNC2RC(Transform2D, multimesh_instance_get_transform_2d, RID, int)
@@ -192,7 +194,7 @@ public:
/* IMMEDIATE API */
- FUNC0R(RID, immediate_create)
+ FUNCRID(immediate)
FUNC3(immediate_begin, RID, PrimitiveType, RID)
FUNC2(immediate_vertex, RID, const Vector3 &)
FUNC2(immediate_normal, RID, const Vector3 &)
@@ -207,7 +209,7 @@ public:
/* SKELETON API */
- FUNC0R(RID, skeleton_create)
+ FUNCRID(skeleton)
FUNC3(skeleton_allocate, RID, int, bool)
FUNC1RC(int, skeleton_get_bone_count, RID)
FUNC3(skeleton_bone_set_transform, RID, int, const Transform &)
@@ -217,7 +219,9 @@ public:
/* Light API */
- FUNC1R(RID, light_create, LightType)
+ FUNCRID(directional_light)
+ FUNCRID(omni_light)
+ FUNCRID(spot_light)
FUNC2(light_set_color, RID, const Color &)
FUNC3(light_set_param, RID, LightParam, float)
@@ -237,7 +241,7 @@ public:
/* PROBE API */
- FUNC0R(RID, reflection_probe_create)
+ FUNCRID(reflection_probe)
FUNC2(reflection_probe_set_update_mode, RID, ReflectionProbeUpdateMode)
FUNC2(reflection_probe_set_intensity, RID, float)
@@ -254,10 +258,10 @@ public:
/* BAKED LIGHT API */
- FUNC0R(RID, gi_probe_create)
+ FUNCRID(gi_probe)
- FUNC2(gi_probe_set_bounds, RID, const Rect3 &)
- FUNC1RC(Rect3, gi_probe_get_bounds, RID)
+ FUNC2(gi_probe_set_bounds, RID, const AABB &)
+ FUNC1RC(AABB, gi_probe_get_bounds, RID)
FUNC2(gi_probe_set_cell_size, RID, float)
FUNC1RC(float, gi_probe_get_cell_size, RID)
@@ -291,7 +295,7 @@ public:
/* PARTICLES */
- FUNC0R(RID, particles_create)
+ FUNCRID(particles)
FUNC2(particles_set_emitting, RID, bool)
FUNC2(particles_set_amount, RID, int)
@@ -300,7 +304,7 @@ public:
FUNC2(particles_set_pre_process_time, RID, float)
FUNC2(particles_set_explosiveness_ratio, RID, float)
FUNC2(particles_set_randomness_ratio, RID, float)
- FUNC2(particles_set_custom_aabb, RID, const Rect3 &)
+ FUNC2(particles_set_custom_aabb, RID, const AABB &)
FUNC2(particles_set_speed_scale, RID, float)
FUNC2(particles_set_use_local_coordinates, RID, bool)
FUNC2(particles_set_process_material, RID, RID)
@@ -314,11 +318,11 @@ public:
FUNC3(particles_set_draw_pass_mesh, RID, int, RID)
FUNC2(particles_set_emission_transform, RID, const Transform &)
- FUNC1R(Rect3, particles_get_current_aabb, RID)
+ FUNC1R(AABB, particles_get_current_aabb, RID)
/* CAMERA API */
- FUNC0R(RID, camera_create)
+ FUNCRID(camera)
FUNC4(camera_set_perspective, RID, float, float, float)
FUNC4(camera_set_orthogonal, RID, float, float, float)
FUNC2(camera_set_transform, RID, const Transform &)
@@ -328,7 +332,7 @@ public:
/* VIEWPORT TARGET API */
- FUNC0R(RID, viewport_create)
+ FUNCRID(viewport)
FUNC2(viewport_set_use_arvr, RID, bool)
@@ -377,7 +381,7 @@ public:
/* ENVIRONMENT API */
- FUNC0R(RID, environment_create)
+ FUNCRID(environment)
FUNC2(environment_set_background, RID, EnvironmentBG)
FUNC2(environment_set_sky, RID, RID)
@@ -387,7 +391,7 @@ public:
FUNC2(environment_set_canvas_max_layer, RID, int)
FUNC4(environment_set_ambient_light, RID, const Color &, float, float)
FUNC7(environment_set_ssr, RID, bool, int, float, float, float, bool)
- FUNC10(environment_set_ssao, RID, bool, float, float, float, float, float, float, const Color &, bool)
+ FUNC12(environment_set_ssao, RID, bool, float, float, float, float, float, float, const Color &, EnvironmentSSAOQuality, EnvironmentSSAOBlur, float)
FUNC6(environment_set_dof_blur_near, RID, bool, float, float, float, EnvironmentDOFBlurQuality)
FUNC6(environment_set_dof_blur_far, RID, bool, float, float, float, EnvironmentDOFBlurQuality)
@@ -401,7 +405,7 @@ public:
FUNC6(environment_set_fog_depth, RID, bool, float, float, bool, float)
FUNC5(environment_set_fog_height, RID, bool, float, float, float)
- FUNC0R(RID, scenario_create)
+ FUNCRID(scenario)
FUNC2(scenario_set_debug, RID, ScenarioDebugMode)
FUNC2(scenario_set_environment, RID, RID)
@@ -410,7 +414,7 @@ public:
/* INSTANCING API */
// from can be mesh, light, area and portal so far.
- FUNC0R(RID, instance_create)
+ FUNCRID(instance)
FUNC2(instance_set_base, RID, RID) // from can be mesh, light, poly, area and portal so far.
FUNC2(instance_set_scenario, RID, RID) // from can be mesh, light, poly, area and portal so far.
@@ -420,6 +424,7 @@ public:
FUNC3(instance_set_blend_shape_weight, RID, int, float)
FUNC3(instance_set_surface_material, RID, int, RID)
FUNC2(instance_set_visible, RID, bool)
+ FUNC2(instance_set_custom_aabb, RID, AABB)
FUNC2(instance_attach_skeleton, RID, RID)
FUNC2(instance_set_exterior, RID, bool)
@@ -427,7 +432,7 @@ public:
FUNC2(instance_set_extra_visibility_margin, RID, real_t)
// don't use these in a game!
- FUNC2RC(Vector<ObjectID>, instances_cull_aabb, const Rect3 &, RID)
+ FUNC2RC(Vector<ObjectID>, instances_cull_aabb, const AABB &, RID)
FUNC3RC(Vector<ObjectID>, instances_cull_ray, const Vector3 &, const Vector3 &, RID)
FUNC2RC(Vector<ObjectID>, instances_cull_convex, const Vector<Plane> &, RID)
@@ -440,11 +445,11 @@ public:
/* CANVAS (2D) */
- FUNC0R(RID, canvas_create)
+ FUNCRID(canvas)
FUNC3(canvas_set_item_mirroring, RID, RID, const Point2 &)
FUNC2(canvas_set_modulate, RID, const Color &)
- FUNC0R(RID, canvas_item_create)
+ FUNCRID(canvas_item)
FUNC2(canvas_item_set_parent, RID, RID)
FUNC2(canvas_item_set_visible, RID, bool)
@@ -510,14 +515,14 @@ public:
FUNC2(canvas_light_set_shadow_color, RID, const Color &)
FUNC2(canvas_light_set_shadow_smooth, RID, float)
- FUNC0R(RID, canvas_light_occluder_create)
+ FUNCRID(canvas_light_occluder)
FUNC2(canvas_light_occluder_attach_to_canvas, RID, RID)
FUNC2(canvas_light_occluder_set_enabled, RID, bool)
FUNC2(canvas_light_occluder_set_polygon, RID, RID)
FUNC2(canvas_light_occluder_set_transform, RID, const Transform2D &)
FUNC2(canvas_light_occluder_set_light_mask, RID, int)
- FUNC0R(RID, canvas_occluder_polygon_create)
+ FUNCRID(canvas_occluder_polygon)
FUNC3(canvas_occluder_polygon_set_shape, RID, const PoolVector<Vector2> &, bool)
FUNC2(canvas_occluder_polygon_set_shape_as_lines, RID, const PoolVector<Vector2> &)
diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp
index 47a5f4c7f3..10f350d667 100644
--- a/servers/visual_server.cpp
+++ b/servers/visual_server.cpp
@@ -62,6 +62,31 @@ RID VisualServer::texture_create_from_image(const Ref<Image> &p_image, uint32_t
return texture;
}
+Array VisualServer::_texture_debug_usage_bind() {
+
+ List<TextureInfo> list;
+ texture_debug_usage(&list);
+ Array arr;
+ for (const List<TextureInfo>::Element *E = list.front(); E; E = E->next()) {
+
+ Dictionary dict;
+ dict["texture"] = E->get().texture;
+ dict["size"] = E->get().size;
+ dict["format"] = E->get().format;
+ dict["bytes"] = E->get().bytes;
+ dict["path"] = E->get().path;
+ arr.push_back(dict);
+ }
+ return arr;
+}
+
+Array VisualServer::_shader_get_param_list_bind(RID p_shader) const {
+
+ List<PropertyInfo> l;
+ shader_get_param_list(p_shader, &l);
+ return convert_property_list(&l);
+}
+
RID VisualServer::get_test_texture() {
if (test_texture.is_valid()) {
@@ -283,7 +308,7 @@ RID VisualServer::get_white_texture() {
#define SMALL_VEC2 Vector2(0.00001, 0.00001)
#define SMALL_VEC3 Vector3(0.00001, 0.00001, 0.00001)
-Error VisualServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint32_t *p_offsets, uint32_t p_stride, PoolVector<uint8_t> &r_vertex_array, int p_vertex_array_len, PoolVector<uint8_t> &r_index_array, int p_index_array_len, Rect3 &r_aabb, Vector<Rect3> r_bone_aabb) {
+Error VisualServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint32_t *p_offsets, uint32_t p_stride, PoolVector<uint8_t> &r_vertex_array, int p_vertex_array_len, PoolVector<uint8_t> &r_index_array, int p_index_array_len, AABB &r_aabb, Vector<AABB> r_bone_aabb) {
PoolVector<uint8_t>::Write vw = r_vertex_array.write();
@@ -348,7 +373,7 @@ Error VisualServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint32_
}
}
- r_aabb = Rect3(Vector3(aabb.position.x, aabb.position.y, 0), Vector3(aabb.size.x, aabb.size.y, 0));
+ r_aabb = AABB(Vector3(aabb.position.x, aabb.position.y, 0), Vector3(aabb.size.x, aabb.size.y, 0));
} else {
PoolVector<Vector3> array = p_arrays[ai];
@@ -358,7 +383,7 @@ Error VisualServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint32_
const Vector3 *src = read.ptr();
// setting vertices means regenerating the AABB
- Rect3 aabb;
+ AABB aabb;
if (p_format & ARRAY_COMPRESS_VERTEX) {
@@ -370,7 +395,7 @@ Error VisualServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint32_
if (i == 0) {
- aabb = Rect3(src[i], SMALL_VEC3);
+ aabb = AABB(src[i], SMALL_VEC3);
} else {
aabb.expand_to(src[i]);
@@ -386,7 +411,7 @@ Error VisualServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint32_
if (i == 0) {
- aabb = Rect3(src[i], SMALL_VEC3);
+ aabb = AABB(src[i], SMALL_VEC3);
} else {
aabb.expand_to(src[i]);
@@ -703,7 +728,7 @@ Error VisualServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint32_
PoolVector<int>::Read rb = bones.read();
PoolVector<float>::Read rw = weights.read();
- Rect3 *bptr = r_bone_aabb.ptr();
+ AABB *bptr = r_bone_aabb.ptr();
for (int i = 0; i < vs; i++) {
@@ -718,7 +743,7 @@ Error VisualServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint32_
if (bptr->size.x < 0) {
//first
- bptr[idx] = Rect3(v, SMALL_VEC3);
+ bptr[idx] = AABB(v, SMALL_VEC3);
any_valid = true;
} else {
bptr[idx].expand_to(v);
@@ -950,8 +975,8 @@ void VisualServer::mesh_add_surface_from_arrays(RID p_mesh, PrimitiveType p_prim
PoolVector<uint8_t> index_array;
index_array.resize(index_array_size);
- Rect3 aabb;
- Vector<Rect3> bone_aabb;
+ AABB aabb;
+ Vector<AABB> bone_aabb;
Error err = _surface_set_data(p_arrays, format, offsets, total_elem_size, vertex_array, array_len, index_array, index_array_len, aabb, bone_aabb);
@@ -968,7 +993,7 @@ void VisualServer::mesh_add_surface_from_arrays(RID p_mesh, PrimitiveType p_prim
vertex_array_shape.resize(array_size);
PoolVector<uint8_t> noindex;
- Rect3 laabb;
+ AABB laabb;
Error err = _surface_set_data(p_blend_shapes[i], format & ~ARRAY_FORMAT_INDEX, offsets, total_elem_size, vertex_array_shape, array_len, noindex, 0, laabb, bone_aabb);
aabb.merge_with(laabb);
if (err) {
@@ -1443,20 +1468,396 @@ Array VisualServer::mesh_surface_get_blend_shape_arrays(RID p_mesh, int p_surfac
}
}
+Array VisualServer::_mesh_surface_get_skeleton_aabb_bind(RID p_mesh, int p_surface) const {
+
+ Vector<AABB> vec = VS::get_singleton()->mesh_surface_get_skeleton_aabb(p_mesh, p_surface);
+ Array arr;
+ for (int i = 0; i < vec.size(); i++) {
+ arr[i] = vec[i];
+ }
+ return arr;
+}
+
void VisualServer::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("force_sync"), &VisualServer::sync);
ClassDB::bind_method(D_METHOD("force_draw"), &VisualServer::draw);
+
ClassDB::bind_method(D_METHOD("texture_create"), &VisualServer::texture_create);
ClassDB::bind_method(D_METHOD("texture_create_from_image", "image", "flags"), &VisualServer::texture_create_from_image, DEFVAL(TEXTURE_FLAGS_DEFAULT));
- //ClassDB::bind_method(D_METHOD("texture_allocate"),&VisualServer::texture_allocate,DEFVAL( TEXTURE_FLAGS_DEFAULT ) );
- //ClassDB::bind_method(D_METHOD("texture_set_data"),&VisualServer::texture_blit_rect,DEFVAL( CUBEMAP_LEFT ) );
- //ClassDB::bind_method(D_METHOD("texture_get_rect"),&VisualServer::texture_get_rect );
+ ClassDB::bind_method(D_METHOD("texture_allocate", "texture", "width", "height", "format", "flags"), &VisualServer::texture_allocate, DEFVAL(TEXTURE_FLAGS_DEFAULT));
+ ClassDB::bind_method(D_METHOD("texture_set_data", "texture", "image", "cube_side"), &VisualServer::texture_set_data, DEFVAL(CUBEMAP_LEFT));
+ ClassDB::bind_method(D_METHOD("texture_get_data", "texture", "cube_side"), &VisualServer::texture_get_data, DEFVAL(CUBEMAP_LEFT));
ClassDB::bind_method(D_METHOD("texture_set_flags", "texture", "flags"), &VisualServer::texture_set_flags);
ClassDB::bind_method(D_METHOD("texture_get_flags", "texture"), &VisualServer::texture_get_flags);
+ ClassDB::bind_method(D_METHOD("texture_get_format", "texture"), &VisualServer::texture_get_format);
+ ClassDB::bind_method(D_METHOD("texture_get_texid", "texture"), &VisualServer::texture_get_texid);
ClassDB::bind_method(D_METHOD("texture_get_width", "texture"), &VisualServer::texture_get_width);
ClassDB::bind_method(D_METHOD("texture_get_height", "texture"), &VisualServer::texture_get_height);
-
+ ClassDB::bind_method(D_METHOD("texture_set_size_override", "texture", "width", "height"), &VisualServer::texture_set_size_override);
+ ClassDB::bind_method(D_METHOD("texture_set_path", "texture", "path"), &VisualServer::texture_set_path);
+ ClassDB::bind_method(D_METHOD("texture_get_path", "texture"), &VisualServer::texture_get_path);
ClassDB::bind_method(D_METHOD("texture_set_shrink_all_x2_on_set_data", "shrink"), &VisualServer::texture_set_shrink_all_x2_on_set_data);
+
+ ClassDB::bind_method(D_METHOD("texture_debug_usage"), &VisualServer::_texture_debug_usage_bind);
+ ClassDB::bind_method(D_METHOD("textures_keep_original", "enable"), &VisualServer::textures_keep_original);
+
+ ClassDB::bind_method(D_METHOD("sky_create"), &VisualServer::sky_create);
+ ClassDB::bind_method(D_METHOD("sky_set_texture", "sky", "cube_map", "radiance_size"), &VisualServer::sky_set_texture);
+
+ ClassDB::bind_method(D_METHOD("shader_create"), &VisualServer::shader_create);
+ ClassDB::bind_method(D_METHOD("shader_set_code", "shader", "code"), &VisualServer::shader_set_code);
+ ClassDB::bind_method(D_METHOD("shader_get_code", "shader"), &VisualServer::shader_get_code);
+ ClassDB::bind_method(D_METHOD("shader_get_param_list", "shader"), &VisualServer::_shader_get_param_list_bind);
+ ClassDB::bind_method(D_METHOD("shader_set_default_texture_param", "shader", "name", "texture"), &VisualServer::shader_set_default_texture_param);
+ ClassDB::bind_method(D_METHOD("shader_get_default_texture_param", "shader", "name"), &VisualServer::shader_get_default_texture_param);
+
+ ClassDB::bind_method(D_METHOD("material_create"), &VisualServer::material_create);
+ ClassDB::bind_method(D_METHOD("material_set_shader", "shader_material", "shader"), &VisualServer::material_set_shader);
+ ClassDB::bind_method(D_METHOD("material_get_shader", "shader_material"), &VisualServer::material_get_shader);
+ ClassDB::bind_method(D_METHOD("material_set_param", "material", "parameter", "value"), &VisualServer::material_set_param);
+ ClassDB::bind_method(D_METHOD("material_get_param", "material", "parameter"), &VisualServer::material_get_param);
+ ClassDB::bind_method(D_METHOD("material_set_render_priority", "material", "priority"), &VisualServer::material_set_render_priority);
+ ClassDB::bind_method(D_METHOD("material_set_line_width", "material", "width"), &VisualServer::material_set_line_width);
+ ClassDB::bind_method(D_METHOD("material_set_next_pass", "material", "next_material"), &VisualServer::material_set_next_pass);
+
+ ClassDB::bind_method(D_METHOD("mesh_create"), &VisualServer::mesh_create);
+ ClassDB::bind_method(D_METHOD("mesh_add_surface_from_arrays", "mesh", "primtive", "arrays", "blend_shapes", "compress_format"), &VisualServer::mesh_add_surface_from_arrays, DEFVAL(Array()), DEFVAL(ARRAY_COMPRESS_DEFAULT));
+ ClassDB::bind_method(D_METHOD("mesh_set_blend_shape_count", "mesh", "amount"), &VisualServer::mesh_set_blend_shape_count);
+ ClassDB::bind_method(D_METHOD("mesh_get_blend_shape_count", "mesh"), &VisualServer::mesh_get_blend_shape_count);
+ ClassDB::bind_method(D_METHOD("mesh_set_blend_shape_mode", "mesh", "mode"), &VisualServer::mesh_set_blend_shape_mode);
+ ClassDB::bind_method(D_METHOD("mesh_get_blend_shape_mode", "mesh"), &VisualServer::mesh_get_blend_shape_mode);
+ ClassDB::bind_method(D_METHOD("mesh_surface_set_material", "mesh", "surface", "material"), &VisualServer::mesh_surface_set_material);
+ ClassDB::bind_method(D_METHOD("mesh_surface_get_material", "mesh", "surface"), &VisualServer::mesh_surface_get_material);
+ ClassDB::bind_method(D_METHOD("mesh_surface_get_array_len", "mesh", "surface"), &VisualServer::mesh_surface_get_array_len);
+ ClassDB::bind_method(D_METHOD("mesh_surface_get_array_index_len", "mesh", "surface"), &VisualServer::mesh_surface_get_array_index_len);
+ ClassDB::bind_method(D_METHOD("mesh_surface_get_array", "mesh", "surface"), &VisualServer::mesh_surface_get_array);
+ ClassDB::bind_method(D_METHOD("mesh_surface_get_index_array", "mesh", "surface"), &VisualServer::mesh_surface_get_index_array);
+ ClassDB::bind_method(D_METHOD("mesh_surface_get_arrays", "mesh", "surface"), &VisualServer::mesh_surface_get_arrays);
+ ClassDB::bind_method(D_METHOD("mesh_surface_get_blend_shape_arrays", "mesh", "surface"), &VisualServer::mesh_surface_get_blend_shape_arrays);
+ ClassDB::bind_method(D_METHOD("mesh_surface_get_format", "mesh", "surface"), &VisualServer::mesh_surface_get_format);
+ ClassDB::bind_method(D_METHOD("mesh_surface_get_primitive_type", "mesh", "surface"), &VisualServer::mesh_surface_get_primitive_type);
+ ClassDB::bind_method(D_METHOD("mesh_surface_get_aabb", "mesh", "surface"), &VisualServer::mesh_surface_get_aabb);
+ ClassDB::bind_method(D_METHOD("mesh_surface_get_skeleton_aabb", "mesh", "surface"), &VisualServer::_mesh_surface_get_skeleton_aabb_bind);
+ ClassDB::bind_method(D_METHOD("mesh_remove_surface", "mesh", "index"), &VisualServer::mesh_remove_surface);
+ ClassDB::bind_method(D_METHOD("mesh_get_surface_count", "mesh"), &VisualServer::mesh_get_surface_count);
+ ClassDB::bind_method(D_METHOD("mesh_set_custom_aabb", "mesh", "aabb"), &VisualServer::mesh_set_custom_aabb);
+ ClassDB::bind_method(D_METHOD("mesh_get_custom_aabb", "mesh"), &VisualServer::mesh_get_custom_aabb);
+ ClassDB::bind_method(D_METHOD("mesh_clear", "mesh"), &VisualServer::mesh_clear);
+
+ // TODO: multimesh_*, immediate_*, skeleton_*, light_*, reflection_probe_*, gi_probe_*, particles_*, camera_*
+
+ ClassDB::bind_method(D_METHOD("viewport_create"), &VisualServer::viewport_create);
+ ClassDB::bind_method(D_METHOD("viewport_set_use_arvr", "viewport", "use_arvr"), &VisualServer::viewport_set_use_arvr);
+ ClassDB::bind_method(D_METHOD("viewport_set_size", "viewport", "width", "height"), &VisualServer::viewport_set_size);
+ ClassDB::bind_method(D_METHOD("viewport_set_active", "viewport", "active"), &VisualServer::viewport_set_active);
+ ClassDB::bind_method(D_METHOD("viewport_set_parent_viewport", "viewport", "parent_viewport"), &VisualServer::viewport_set_parent_viewport);
+ ClassDB::bind_method(D_METHOD("viewport_attach_to_screen", "viewport", "rect", "screen"), &VisualServer::viewport_attach_to_screen, DEFVAL(Rect2()), DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("viewport_detach", "viewport"), &VisualServer::viewport_detach);
+ ClassDB::bind_method(D_METHOD("viewport_set_update_mode", "viewport", "update_mode"), &VisualServer::viewport_set_update_mode);
+ ClassDB::bind_method(D_METHOD("viewport_set_vflip", "viewport", "enabled"), &VisualServer::viewport_set_vflip);
+ ClassDB::bind_method(D_METHOD("viewport_set_clear_mode", "viewport", "clear_mode"), &VisualServer::viewport_set_clear_mode);
+ ClassDB::bind_method(D_METHOD("viewport_get_texture", "viewport"), &VisualServer::viewport_get_texture);
+ ClassDB::bind_method(D_METHOD("viewport_set_hide_scenario", "viewport", "hidden"), &VisualServer::viewport_set_hide_scenario);
+ ClassDB::bind_method(D_METHOD("viewport_set_hide_canvas", "viewport", "hidden"), &VisualServer::viewport_set_hide_canvas);
+ ClassDB::bind_method(D_METHOD("viewport_set_disable_environment", "viewport", "disabled"), &VisualServer::viewport_set_disable_environment);
+ ClassDB::bind_method(D_METHOD("viewport_set_disable_3d", "viewport", "disabled"), &VisualServer::viewport_set_disable_3d);
+ ClassDB::bind_method(D_METHOD("viewport_attach_camera", "viewport", "camera"), &VisualServer::viewport_attach_camera);
+ ClassDB::bind_method(D_METHOD("viewport_set_scenario", "viewport", "scenario"), &VisualServer::viewport_set_scenario);
+ ClassDB::bind_method(D_METHOD("viewport_attach_canvas", "viewport", "canvas"), &VisualServer::viewport_attach_canvas);
+ ClassDB::bind_method(D_METHOD("viewport_remove_canvas", "viewport", "canvas"), &VisualServer::viewport_remove_canvas);
+ ClassDB::bind_method(D_METHOD("viewport_set_canvas_transform", "viewport", "canvas", "offset"), &VisualServer::viewport_set_canvas_transform);
+ ClassDB::bind_method(D_METHOD("viewport_set_transparent_background", "viewport", "enabled"), &VisualServer::viewport_set_transparent_background);
+ ClassDB::bind_method(D_METHOD("viewport_set_global_canvas_transform", "viewport", "transform"), &VisualServer::viewport_set_global_canvas_transform);
+ ClassDB::bind_method(D_METHOD("viewport_set_canvas_layer", "viewport", "canvas", "layer"), &VisualServer::viewport_set_canvas_layer);
+ ClassDB::bind_method(D_METHOD("viewport_set_shadow_atlas_size", "viewport", "size"), &VisualServer::viewport_set_shadow_atlas_size);
+ ClassDB::bind_method(D_METHOD("viewport_set_shadow_atlas_quadrant_subdivision", "viewport", "quadrant", "subdivision"), &VisualServer::viewport_set_shadow_atlas_quadrant_subdivision);
+ ClassDB::bind_method(D_METHOD("viewport_set_msaa", "viewport", "msaa"), &VisualServer::viewport_set_msaa);
+ ClassDB::bind_method(D_METHOD("viewport_set_hdr", "viewport", "enabled"), &VisualServer::viewport_set_hdr);
+ ClassDB::bind_method(D_METHOD("viewport_set_usage", "viewport", "usage"), &VisualServer::viewport_set_usage);
+ ClassDB::bind_method(D_METHOD("viewport_get_render_info", "viewport", "info"), &VisualServer::viewport_get_render_info);
+ ClassDB::bind_method(D_METHOD("viewport_set_debug_draw", "viewport", "draw"), &VisualServer::viewport_set_debug_draw);
+
+ // TODO: environment_*, scenario_*, instance_*
+
+ ClassDB::bind_method(D_METHOD("canvas_create"), &VisualServer::canvas_create);
+ ClassDB::bind_method(D_METHOD("canvas_set_item_mirroring", "canvas", "item", "mirroring"), &VisualServer::canvas_set_item_mirroring);
+ ClassDB::bind_method(D_METHOD("canvas_set_modulate", "canvas", "color"), &VisualServer::canvas_set_modulate);
+
+ ClassDB::bind_method(D_METHOD("canvas_item_create"), &VisualServer::canvas_item_create);
+ ClassDB::bind_method(D_METHOD("canvas_item_set_parent", "item", "parent"), &VisualServer::canvas_item_set_parent);
+ ClassDB::bind_method(D_METHOD("canvas_item_set_visible", "item", "visible"), &VisualServer::canvas_item_set_visible);
+ ClassDB::bind_method(D_METHOD("canvas_item_set_light_mask", "item", "mask"), &VisualServer::canvas_item_set_light_mask);
+ ClassDB::bind_method(D_METHOD("canvas_item_set_transform", "item", "transform"), &VisualServer::canvas_item_set_transform);
+ ClassDB::bind_method(D_METHOD("canvas_item_set_clip", "item", "clip"), &VisualServer::canvas_item_set_clip);
+ ClassDB::bind_method(D_METHOD("canvas_item_set_distance_field_mode", "item", "enabled"), &VisualServer::canvas_item_set_distance_field_mode);
+ ClassDB::bind_method(D_METHOD("canvas_item_set_custom_rect", "item", "use_custom_rect", "rect"), &VisualServer::canvas_item_set_custom_rect, DEFVAL(Rect2()));
+ ClassDB::bind_method(D_METHOD("canvas_item_set_modulate", "item", "color"), &VisualServer::canvas_item_set_modulate);
+ ClassDB::bind_method(D_METHOD("canvas_item_set_self_modulate", "item", "color"), &VisualServer::canvas_item_set_self_modulate);
+ ClassDB::bind_method(D_METHOD("canvas_item_set_draw_behind_parent", "item", "enabled"), &VisualServer::canvas_item_set_draw_behind_parent);
+ ClassDB::bind_method(D_METHOD("canvas_item_add_line", "item", "from", "to", "color", "width", "antialiased"), &VisualServer::canvas_item_add_line, DEFVAL(1.0), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("canvas_item_add_polyline", "item", "points", "colors", "width", "antialiased"), &VisualServer::canvas_item_add_polyline, DEFVAL(1.0), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("canvas_item_add_rect", "item", "rect", "color"), &VisualServer::canvas_item_add_rect);
+ ClassDB::bind_method(D_METHOD("canvas_item_add_circle", "item", "pos", "radius", "color"), &VisualServer::canvas_item_add_circle);
+ ClassDB::bind_method(D_METHOD("canvas_item_add_texture_rect", "item", "rect", "texture", "tile", "modulate", "transpose", "normal_map"), &VisualServer::canvas_item_add_texture_rect, DEFVAL(false), DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(RID()));
+ ClassDB::bind_method(D_METHOD("canvas_item_add_texture_rect_region", "item", "rect", "texture", "src_rect", "modulate", "transpose", "normal_map", "clip_uv"), &VisualServer::canvas_item_add_texture_rect_region, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(RID()), DEFVAL(true));
+ ClassDB::bind_method(D_METHOD("canvas_item_add_nine_patch", "item", "rect", "source", "texture", "topleft", "bottomright", "x_axis_mode", "y_axis_mode", "draw_center", "modulate", "normal_map"), &VisualServer::canvas_item_add_nine_patch, DEFVAL(NINE_PATCH_STRETCH), DEFVAL(NINE_PATCH_STRETCH), DEFVAL(true), DEFVAL(Color(1, 1, 1)), DEFVAL(RID()));
+ ClassDB::bind_method(D_METHOD("canvas_item_add_primitive", "item", "points", "colors", "uvs", "texture", "width", "normal_map"), &VisualServer::canvas_item_add_primitive, DEFVAL(1.0), DEFVAL(RID()));
+ ClassDB::bind_method(D_METHOD("canvas_item_add_polygon", "item", "points", "colors", "uvs", "texture", "normal_map", "antialiased"), &VisualServer::canvas_item_add_polygon, DEFVAL(Vector<Point2>()), DEFVAL(RID()), DEFVAL(RID()), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("canvas_item_add_triangle_array", "item", "indices", "points", "colors", "uvs", "texture", "count", "normal_map"), &VisualServer::canvas_item_add_triangle_array, DEFVAL(Vector<Point2>()), DEFVAL(RID()), DEFVAL(-1), DEFVAL(RID()));
+ ClassDB::bind_method(D_METHOD("canvas_item_add_mesh", "item", "mesh", "skeleton"), &VisualServer::canvas_item_add_mesh, DEFVAL(RID()));
+ ClassDB::bind_method(D_METHOD("canvas_item_add_multimesh", "item", "mesh", "skeleton"), &VisualServer::canvas_item_add_multimesh, DEFVAL(RID()));
+ ClassDB::bind_method(D_METHOD("canvas_item_add_particles", "item", "particles", "texture", "normal_map", "h_frames", "v_frames"), &VisualServer::canvas_item_add_particles);
+ ClassDB::bind_method(D_METHOD("canvas_item_add_set_transform", "item", "transform"), &VisualServer::canvas_item_add_set_transform);
+ ClassDB::bind_method(D_METHOD("canvas_item_add_clip_ignore", "item", "ignore"), &VisualServer::canvas_item_add_clip_ignore);
+ ClassDB::bind_method(D_METHOD("canvas_item_set_sort_children_by_y", "item", "enabled"), &VisualServer::canvas_item_set_sort_children_by_y);
+ ClassDB::bind_method(D_METHOD("canvas_item_set_z", "item", "z"), &VisualServer::canvas_item_set_z);
+ ClassDB::bind_method(D_METHOD("canvas_item_set_z_as_relative_to_parent", "item", "enabled"), &VisualServer::canvas_item_set_z_as_relative_to_parent);
+ ClassDB::bind_method(D_METHOD("canvas_item_set_copy_to_backbuffer", "item", "enabled", "rect"), &VisualServer::canvas_item_set_copy_to_backbuffer);
+ ClassDB::bind_method(D_METHOD("canvas_item_clear", "item"), &VisualServer::canvas_item_clear);
+ ClassDB::bind_method(D_METHOD("canvas_item_set_draw_index", "item", "index"), &VisualServer::canvas_item_set_draw_index);
+ ClassDB::bind_method(D_METHOD("canvas_item_set_material", "item", "material"), &VisualServer::canvas_item_set_material);
+ ClassDB::bind_method(D_METHOD("canvas_item_set_use_parent_material", "item", "enabled"), &VisualServer::canvas_item_set_use_parent_material);
+ ClassDB::bind_method(D_METHOD("canvas_light_create"), &VisualServer::canvas_light_create);
+ ClassDB::bind_method(D_METHOD("canvas_light_attach_to_canvas", "light", "canvas"), &VisualServer::canvas_light_attach_to_canvas);
+ ClassDB::bind_method(D_METHOD("canvas_light_set_enabled", "light", "enabled"), &VisualServer::canvas_light_set_enabled);
+ ClassDB::bind_method(D_METHOD("canvas_light_set_scale", "light", "scale"), &VisualServer::canvas_light_set_scale);
+ ClassDB::bind_method(D_METHOD("canvas_light_set_transform", "light", "transform"), &VisualServer::canvas_light_set_transform);
+ ClassDB::bind_method(D_METHOD("canvas_light_set_texture", "light", "texture"), &VisualServer::canvas_light_set_texture);
+ ClassDB::bind_method(D_METHOD("canvas_light_set_texture_offset", "light", "offset"), &VisualServer::canvas_light_set_texture_offset);
+ ClassDB::bind_method(D_METHOD("canvas_light_set_color", "light", "color"), &VisualServer::canvas_light_set_color);
+ ClassDB::bind_method(D_METHOD("canvas_light_set_height", "light", "height"), &VisualServer::canvas_light_set_height);
+ ClassDB::bind_method(D_METHOD("canvas_light_set_energy", "light", "energy"), &VisualServer::canvas_light_set_energy);
+ ClassDB::bind_method(D_METHOD("canvas_light_set_z_range", "light", "min_z", "max_z"), &VisualServer::canvas_light_set_z_range);
+ ClassDB::bind_method(D_METHOD("canvas_light_set_layer_range", "light", "min_layer", "max_layer"), &VisualServer::canvas_light_set_layer_range);
+ ClassDB::bind_method(D_METHOD("canvas_light_set_item_cull_mask", "light", "mask"), &VisualServer::canvas_light_set_item_cull_mask);
+ ClassDB::bind_method(D_METHOD("canvas_light_set_item_shadow_cull_mask", "light", "mask"), &VisualServer::canvas_light_set_item_shadow_cull_mask);
+ ClassDB::bind_method(D_METHOD("canvas_light_set_mode", "light", "mode"), &VisualServer::canvas_light_set_mode);
+ ClassDB::bind_method(D_METHOD("canvas_light_set_shadow_enabled", "light", "enabled"), &VisualServer::canvas_light_set_shadow_enabled);
+ ClassDB::bind_method(D_METHOD("canvas_light_set_shadow_buffer_size", "light", "size"), &VisualServer::canvas_light_set_shadow_buffer_size);
+ ClassDB::bind_method(D_METHOD("canvas_light_set_shadow_gradient_length", "light", "length"), &VisualServer::canvas_light_set_shadow_gradient_length);
+ ClassDB::bind_method(D_METHOD("canvas_light_set_shadow_filter", "light", "filter"), &VisualServer::canvas_light_set_shadow_filter);
+ ClassDB::bind_method(D_METHOD("canvas_light_set_shadow_color", "light", "color"), &VisualServer::canvas_light_set_shadow_color);
+ ClassDB::bind_method(D_METHOD("canvas_light_set_shadow_smooth", "light", "smooth"), &VisualServer::canvas_light_set_shadow_smooth);
+
+ ClassDB::bind_method(D_METHOD("canvas_light_occluder_create"), &VisualServer::canvas_light_occluder_create);
+ ClassDB::bind_method(D_METHOD("canvas_light_occluder_attach_to_canvas", "occluder", "canvas"), &VisualServer::canvas_light_occluder_attach_to_canvas);
+ ClassDB::bind_method(D_METHOD("canvas_light_occluder_set_enabled", "occluder", "enabled"), &VisualServer::canvas_light_occluder_set_enabled);
+ ClassDB::bind_method(D_METHOD("canvas_light_occluder_set_polygon", "occluder", "polygon"), &VisualServer::canvas_light_occluder_set_polygon);
+ ClassDB::bind_method(D_METHOD("canvas_light_occluder_set_transform", "occluder", "transform"), &VisualServer::canvas_light_occluder_set_transform);
+ ClassDB::bind_method(D_METHOD("canvas_light_occluder_set_light_mask", "occluder", "mask"), &VisualServer::canvas_light_occluder_set_light_mask);
+
+ ClassDB::bind_method(D_METHOD("canvas_occluder_polygon_create"), &VisualServer::canvas_occluder_polygon_create);
+ ClassDB::bind_method(D_METHOD("canvas_occluder_polygon_set_shape", "occluder_polygon", "shape", "closed"), &VisualServer::canvas_occluder_polygon_set_shape);
+ ClassDB::bind_method(D_METHOD("canvas_occluder_polygon_set_shape_as_lines", "occluder_polygon", "shape"), &VisualServer::canvas_occluder_polygon_set_shape_as_lines);
+ ClassDB::bind_method(D_METHOD("canvas_occluder_polygon_set_cull_mode", "occluder_polygon", "mode"), &VisualServer::canvas_occluder_polygon_set_cull_mode);
+
+ ClassDB::bind_method(D_METHOD("black_bars_set_margins", "left", "top", "right", "bottom"), &VisualServer::black_bars_set_margins);
+ ClassDB::bind_method(D_METHOD("black_bars_set_images", "left", "top", "right", "bottom"), &VisualServer::black_bars_set_images);
+
+ ClassDB::bind_method(D_METHOD("free", "rid"), &VisualServer::free);
+
+ ClassDB::bind_method(D_METHOD("request_frame_drawn_callback", "where", "method", "userdata"), &VisualServer::request_frame_drawn_callback);
+ ClassDB::bind_method(D_METHOD("draw"), &VisualServer::draw);
+ ClassDB::bind_method(D_METHOD("sync"), &VisualServer::sync);
+ ClassDB::bind_method(D_METHOD("has_changed"), &VisualServer::has_changed);
+ 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_test_cube"), &VisualServer::get_test_cube);
+ ClassDB::bind_method(D_METHOD("get_test_texture"), &VisualServer::get_test_texture);
+ ClassDB::bind_method(D_METHOD("get_white_texture"), &VisualServer::get_white_texture);
+
+ ClassDB::bind_method(D_METHOD("make_sphere_mesh", "latitudes", "longitudes", "radius"), &VisualServer::make_sphere_mesh);
+
+ ClassDB::bind_method(D_METHOD("set_boot_image", "image", "color", "scale"), &VisualServer::set_boot_image);
+ ClassDB::bind_method(D_METHOD("set_default_clear_color", "color"), &VisualServer::set_default_clear_color);
+
+ ClassDB::bind_method(D_METHOD("has_feature", "feature"), &VisualServer::has_feature);
+ ClassDB::bind_method(D_METHOD("has_os_feature", "feature"), &VisualServer::has_os_feature);
+ ClassDB::bind_method(D_METHOD("set_debug_generate_wireframes", "generate"), &VisualServer::set_debug_generate_wireframes);
+
+ BIND_CONSTANT(NO_INDEX_ARRAY);
+ BIND_CONSTANT(ARRAY_WEIGHTS_SIZE);
+ BIND_CONSTANT(CANVAS_ITEM_Z_MIN);
+ BIND_CONSTANT(CANVAS_ITEM_Z_MAX);
+ BIND_CONSTANT(MAX_GLOW_LEVELS);
+ BIND_CONSTANT(MAX_CURSORS);
+ BIND_CONSTANT(MATERIAL_RENDER_PRIORITY_MIN);
+ BIND_CONSTANT(MATERIAL_RENDER_PRIORITY_MAX);
+
+ BIND_ENUM_CONSTANT(CUBEMAP_LEFT);
+ BIND_ENUM_CONSTANT(CUBEMAP_RIGHT);
+ BIND_ENUM_CONSTANT(CUBEMAP_BOTTOM);
+ BIND_ENUM_CONSTANT(CUBEMAP_TOP);
+ BIND_ENUM_CONSTANT(CUBEMAP_FRONT);
+ BIND_ENUM_CONSTANT(CUBEMAP_BACK);
+
+ BIND_ENUM_CONSTANT(TEXTURE_FLAG_MIPMAPS);
+ BIND_ENUM_CONSTANT(TEXTURE_FLAG_REPEAT);
+ BIND_ENUM_CONSTANT(TEXTURE_FLAG_FILTER);
+ BIND_ENUM_CONSTANT(TEXTURE_FLAG_ANISOTROPIC_FILTER);
+ BIND_ENUM_CONSTANT(TEXTURE_FLAG_CONVERT_TO_LINEAR);
+ BIND_ENUM_CONSTANT(TEXTURE_FLAG_MIRRORED_REPEAT);
+ BIND_ENUM_CONSTANT(TEXTURE_FLAG_CUBEMAP);
+ BIND_ENUM_CONSTANT(TEXTURE_FLAG_USED_FOR_STREAMING);
+ BIND_ENUM_CONSTANT(TEXTURE_FLAGS_DEFAULT);
+
+ BIND_ENUM_CONSTANT(SHADER_SPATIAL);
+ BIND_ENUM_CONSTANT(SHADER_CANVAS_ITEM);
+ BIND_ENUM_CONSTANT(SHADER_PARTICLES);
+ BIND_ENUM_CONSTANT(SHADER_MAX);
+
+ BIND_ENUM_CONSTANT(ARRAY_VERTEX);
+ BIND_ENUM_CONSTANT(ARRAY_NORMAL);
+ BIND_ENUM_CONSTANT(ARRAY_TANGENT);
+ BIND_ENUM_CONSTANT(ARRAY_COLOR);
+ BIND_ENUM_CONSTANT(ARRAY_TEX_UV);
+ BIND_ENUM_CONSTANT(ARRAY_TEX_UV2);
+ BIND_ENUM_CONSTANT(ARRAY_BONES);
+ BIND_ENUM_CONSTANT(ARRAY_WEIGHTS);
+ BIND_ENUM_CONSTANT(ARRAY_INDEX);
+ BIND_ENUM_CONSTANT(ARRAY_MAX);
+
+ BIND_ENUM_CONSTANT(ARRAY_FORMAT_VERTEX);
+ BIND_ENUM_CONSTANT(ARRAY_FORMAT_NORMAL);
+ BIND_ENUM_CONSTANT(ARRAY_FORMAT_TANGENT);
+ BIND_ENUM_CONSTANT(ARRAY_FORMAT_COLOR);
+ BIND_ENUM_CONSTANT(ARRAY_FORMAT_TEX_UV);
+ BIND_ENUM_CONSTANT(ARRAY_FORMAT_TEX_UV2);
+ BIND_ENUM_CONSTANT(ARRAY_FORMAT_BONES);
+ BIND_ENUM_CONSTANT(ARRAY_FORMAT_WEIGHTS);
+ BIND_ENUM_CONSTANT(ARRAY_FORMAT_INDEX);
+ BIND_ENUM_CONSTANT(ARRAY_COMPRESS_VERTEX);
+ BIND_ENUM_CONSTANT(ARRAY_COMPRESS_NORMAL);
+ BIND_ENUM_CONSTANT(ARRAY_COMPRESS_TANGENT);
+ BIND_ENUM_CONSTANT(ARRAY_COMPRESS_COLOR);
+ BIND_ENUM_CONSTANT(ARRAY_COMPRESS_TEX_UV);
+ BIND_ENUM_CONSTANT(ARRAY_COMPRESS_TEX_UV2);
+ BIND_ENUM_CONSTANT(ARRAY_COMPRESS_BONES);
+ BIND_ENUM_CONSTANT(ARRAY_COMPRESS_WEIGHTS);
+ BIND_ENUM_CONSTANT(ARRAY_COMPRESS_INDEX);
+ BIND_ENUM_CONSTANT(ARRAY_FLAG_USE_2D_VERTICES);
+ BIND_ENUM_CONSTANT(ARRAY_FLAG_USE_16_BIT_BONES);
+ BIND_ENUM_CONSTANT(ARRAY_COMPRESS_DEFAULT);
+
+ BIND_ENUM_CONSTANT(PRIMITIVE_POINTS);
+ BIND_ENUM_CONSTANT(PRIMITIVE_LINES);
+ BIND_ENUM_CONSTANT(PRIMITIVE_LINE_STRIP);
+ BIND_ENUM_CONSTANT(PRIMITIVE_LINE_LOOP);
+ BIND_ENUM_CONSTANT(PRIMITIVE_TRIANGLES);
+ BIND_ENUM_CONSTANT(PRIMITIVE_TRIANGLE_STRIP);
+ BIND_ENUM_CONSTANT(PRIMITIVE_TRIANGLE_FAN);
+ BIND_ENUM_CONSTANT(PRIMITIVE_MAX);
+
+ BIND_ENUM_CONSTANT(BLEND_SHAPE_MODE_NORMALIZED);
+ BIND_ENUM_CONSTANT(BLEND_SHAPE_MODE_RELATIVE);
+
+ BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL);
+ BIND_ENUM_CONSTANT(LIGHT_OMNI);
+ BIND_ENUM_CONSTANT(LIGHT_SPOT);
+
+ BIND_ENUM_CONSTANT(LIGHT_PARAM_ENERGY);
+ BIND_ENUM_CONSTANT(LIGHT_PARAM_SPECULAR);
+ BIND_ENUM_CONSTANT(LIGHT_PARAM_RANGE);
+ BIND_ENUM_CONSTANT(LIGHT_PARAM_ATTENUATION);
+ BIND_ENUM_CONSTANT(LIGHT_PARAM_SPOT_ANGLE);
+ BIND_ENUM_CONSTANT(LIGHT_PARAM_SPOT_ATTENUATION);
+ BIND_ENUM_CONSTANT(LIGHT_PARAM_CONTACT_SHADOW_SIZE);
+ BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_MAX_DISTANCE);
+ BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET);
+ BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET);
+ BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET);
+ BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_NORMAL_BIAS);
+ BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_BIAS);
+ BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE);
+ BIND_ENUM_CONSTANT(LIGHT_PARAM_MAX);
+
+ BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_DISABLED);
+ BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_ONCE);
+ BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_WHEN_VISIBLE);
+ BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_ALWAYS);
+
+ BIND_ENUM_CONSTANT(VIEWPORT_CLEAR_ALWAYS);
+ BIND_ENUM_CONSTANT(VIEWPORT_CLEAR_NEVER);
+ BIND_ENUM_CONSTANT(VIEWPORT_CLEAR_ONLY_NEXT_FRAME);
+
+ BIND_ENUM_CONSTANT(VIEWPORT_MSAA_DISABLED);
+ BIND_ENUM_CONSTANT(VIEWPORT_MSAA_2X);
+ BIND_ENUM_CONSTANT(VIEWPORT_MSAA_4X);
+ BIND_ENUM_CONSTANT(VIEWPORT_MSAA_8X);
+ BIND_ENUM_CONSTANT(VIEWPORT_MSAA_16X);
+
+ BIND_ENUM_CONSTANT(VIEWPORT_USAGE_2D);
+ BIND_ENUM_CONSTANT(VIEWPORT_USAGE_2D_NO_SAMPLING);
+ BIND_ENUM_CONSTANT(VIEWPORT_USAGE_3D);
+ BIND_ENUM_CONSTANT(VIEWPORT_USAGE_3D_NO_EFFECTS);
+
+ BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_OBJECTS_IN_FRAME);
+ BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_VERTICES_IN_FRAME);
+ BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_MATERIAL_CHANGES_IN_FRAME);
+ BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_SHADER_CHANGES_IN_FRAME);
+ BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_SURFACE_CHANGES_IN_FRAME);
+ BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_DRAW_CALLS_IN_FRAME);
+ BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_MAX);
+
+ BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_DISABLED);
+ BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_UNSHADED);
+ BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_OVERDRAW);
+ BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_WIREFRAME);
+
+ BIND_ENUM_CONSTANT(SCENARIO_DEBUG_DISABLED);
+ BIND_ENUM_CONSTANT(SCENARIO_DEBUG_WIREFRAME);
+ BIND_ENUM_CONSTANT(SCENARIO_DEBUG_OVERDRAW);
+ BIND_ENUM_CONSTANT(SCENARIO_DEBUG_SHADELESS);
+
+ BIND_ENUM_CONSTANT(INSTANCE_NONE);
+ BIND_ENUM_CONSTANT(INSTANCE_MESH);
+ BIND_ENUM_CONSTANT(INSTANCE_MULTIMESH);
+ BIND_ENUM_CONSTANT(INSTANCE_IMMEDIATE);
+ BIND_ENUM_CONSTANT(INSTANCE_PARTICLES);
+ BIND_ENUM_CONSTANT(INSTANCE_LIGHT);
+ BIND_ENUM_CONSTANT(INSTANCE_REFLECTION_PROBE);
+ BIND_ENUM_CONSTANT(INSTANCE_GI_PROBE);
+ BIND_ENUM_CONSTANT(INSTANCE_MAX);
+ BIND_ENUM_CONSTANT(INSTANCE_GEOMETRY_MASK);
+
+ BIND_ENUM_CONSTANT(NINE_PATCH_STRETCH);
+ BIND_ENUM_CONSTANT(NINE_PATCH_TILE);
+ BIND_ENUM_CONSTANT(NINE_PATCH_TILE_FIT);
+
+ BIND_ENUM_CONSTANT(CANVAS_LIGHT_MODE_ADD);
+ BIND_ENUM_CONSTANT(CANVAS_LIGHT_MODE_SUB);
+ BIND_ENUM_CONSTANT(CANVAS_LIGHT_MODE_MIX);
+ BIND_ENUM_CONSTANT(CANVAS_LIGHT_MODE_MASK);
+
+ BIND_ENUM_CONSTANT(CANVAS_LIGHT_FILTER_NONE);
+ BIND_ENUM_CONSTANT(CANVAS_LIGHT_FILTER_PCF3);
+ BIND_ENUM_CONSTANT(CANVAS_LIGHT_FILTER_PCF5);
+ BIND_ENUM_CONSTANT(CANVAS_LIGHT_FILTER_PCF7);
+ BIND_ENUM_CONSTANT(CANVAS_LIGHT_FILTER_PCF9);
+ BIND_ENUM_CONSTANT(CANVAS_LIGHT_FILTER_PCF13);
+
+ BIND_ENUM_CONSTANT(CANVAS_OCCLUDER_POLYGON_CULL_DISABLED);
+ BIND_ENUM_CONSTANT(CANVAS_OCCLUDER_POLYGON_CULL_CLOCKWISE);
+ BIND_ENUM_CONSTANT(CANVAS_OCCLUDER_POLYGON_CULL_COUNTER_CLOCKWISE);
+
+ BIND_ENUM_CONSTANT(INFO_OBJECTS_IN_FRAME);
+ BIND_ENUM_CONSTANT(INFO_VERTICES_IN_FRAME);
+ BIND_ENUM_CONSTANT(INFO_MATERIAL_CHANGES_IN_FRAME);
+ BIND_ENUM_CONSTANT(INFO_SHADER_CHANGES_IN_FRAME);
+ BIND_ENUM_CONSTANT(INFO_SURFACE_CHANGES_IN_FRAME);
+ BIND_ENUM_CONSTANT(INFO_DRAW_CALLS_IN_FRAME);
+ BIND_ENUM_CONSTANT(INFO_USAGE_VIDEO_MEM_TOTAL);
+ BIND_ENUM_CONSTANT(INFO_VIDEO_MEM_USED);
+ BIND_ENUM_CONSTANT(INFO_TEXTURE_MEM_USED);
+ BIND_ENUM_CONSTANT(INFO_VERTEX_MEM_USED);
+
+ BIND_ENUM_CONSTANT(FEATURE_SHADERS);
+ BIND_ENUM_CONSTANT(FEATURE_MULTITHREADED);
+
+ ADD_SIGNAL(MethodInfo("frame_drawn_in_thread"));
}
void VisualServer::_canvas_item_add_style_box(RID p_item, const Rect2 &p_rect, const Rect2 &p_source, RID p_texture, const Vector<float> &p_margins, const Color &p_modulate) {
diff --git a/servers/visual_server.h b/servers/visual_server.h
index 1cc097f50e..c4b1583009 100644
--- a/servers/visual_server.h
+++ b/servers/visual_server.h
@@ -60,7 +60,7 @@ protected:
RID white_texture;
RID test_material;
- Error _surface_set_data(Array p_arrays, uint32_t p_format, uint32_t *p_offsets, uint32_t p_stride, PoolVector<uint8_t> &r_vertex_array, int p_vertex_array_len, PoolVector<uint8_t> &r_index_array, int p_index_array_len, Rect3 &r_aabb, Vector<Rect3> r_bone_aabb);
+ Error _surface_set_data(Array p_arrays, uint32_t p_format, uint32_t *p_offsets, uint32_t p_stride, PoolVector<uint8_t> &r_vertex_array, int p_vertex_array_len, PoolVector<uint8_t> &r_index_array, int p_index_array_len, AABB &r_aabb, Vector<AABB> r_bone_aabb);
static VisualServer *(*create_func)();
static void _bind_methods();
@@ -137,6 +137,7 @@ public:
};
virtual void texture_debug_usage(List<TextureInfo> *r_info) = 0;
+ Array _texture_debug_usage_bind();
virtual void textures_keep_original(bool p_enable) = 0;
@@ -160,6 +161,7 @@ public:
virtual void shader_set_code(RID p_shader, const String &p_code) = 0;
virtual String shader_get_code(RID p_shader) const = 0;
virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const = 0;
+ Array _shader_get_param_list_bind(RID p_shader) const;
virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture) = 0;
virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name) const = 0;
@@ -225,6 +227,7 @@ public:
ARRAY_FLAG_USE_2D_VERTICES = ARRAY_COMPRESS_INDEX << 1,
ARRAY_FLAG_USE_16_BIT_BONES = ARRAY_COMPRESS_INDEX << 2,
+ ARRAY_FLAG_USE_DYNAMIC_UPDATE = ARRAY_COMPRESS_INDEX << 3,
ARRAY_COMPRESS_DEFAULT = ARRAY_COMPRESS_VERTEX | ARRAY_COMPRESS_NORMAL | ARRAY_COMPRESS_TANGENT | ARRAY_COMPRESS_COLOR | ARRAY_COMPRESS_TEX_UV | ARRAY_COMPRESS_TEX_UV2 | ARRAY_COMPRESS_WEIGHTS
@@ -244,7 +247,7 @@ public:
virtual RID mesh_create() = 0;
virtual void mesh_add_surface_from_arrays(RID p_mesh, PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes = Array(), uint32_t p_compress_format = ARRAY_COMPRESS_DEFAULT);
- virtual void mesh_add_surface(RID p_mesh, uint32_t p_format, PrimitiveType p_primitive, const PoolVector<uint8_t> &p_array, int p_vertex_count, const PoolVector<uint8_t> &p_index_array, int p_index_count, const Rect3 &p_aabb, const Vector<PoolVector<uint8_t> > &p_blend_shapes = Vector<PoolVector<uint8_t> >(), const Vector<Rect3> &p_bone_aabbs = Vector<Rect3>()) = 0;
+ virtual void mesh_add_surface(RID p_mesh, uint32_t p_format, PrimitiveType p_primitive, const PoolVector<uint8_t> &p_array, int p_vertex_count, const PoolVector<uint8_t> &p_index_array, int p_index_count, const AABB &p_aabb, const Vector<PoolVector<uint8_t> > &p_blend_shapes = Vector<PoolVector<uint8_t> >(), const Vector<AABB> &p_bone_aabbs = Vector<AABB>()) = 0;
virtual void mesh_set_blend_shape_count(RID p_mesh, int p_amount) = 0;
virtual int mesh_get_blend_shape_count(RID p_mesh) const = 0;
@@ -257,6 +260,8 @@ public:
virtual void mesh_set_blend_shape_mode(RID p_mesh, BlendShapeMode p_mode) = 0;
virtual BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const = 0;
+ virtual void mesh_surface_update_region(RID p_mesh, int p_surface, int p_offset, const PoolVector<uint8_t> &p_data) = 0;
+
virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) = 0;
virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const = 0;
@@ -272,15 +277,16 @@ public:
virtual uint32_t mesh_surface_get_format(RID p_mesh, int p_surface) const = 0;
virtual PrimitiveType mesh_surface_get_primitive_type(RID p_mesh, int p_surface) const = 0;
- virtual Rect3 mesh_surface_get_aabb(RID p_mesh, int p_surface) const = 0;
+ virtual AABB mesh_surface_get_aabb(RID p_mesh, int p_surface) const = 0;
virtual Vector<PoolVector<uint8_t> > mesh_surface_get_blend_shapes(RID p_mesh, int p_surface) const = 0;
- virtual Vector<Rect3> mesh_surface_get_skeleton_aabb(RID p_mesh, int p_surface) const = 0;
+ virtual Vector<AABB> mesh_surface_get_skeleton_aabb(RID p_mesh, int p_surface) const = 0;
+ Array _mesh_surface_get_skeleton_aabb_bind(RID p_mesh, int p_surface) const;
virtual void mesh_remove_surface(RID p_mesh, int p_index) = 0;
virtual int mesh_get_surface_count(RID p_mesh) const = 0;
- virtual void mesh_set_custom_aabb(RID p_mesh, const Rect3 &p_aabb) = 0;
- virtual Rect3 mesh_get_custom_aabb(RID p_mesh) const = 0;
+ virtual void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) = 0;
+ virtual AABB mesh_get_custom_aabb(RID p_mesh) const = 0;
virtual void mesh_clear(RID p_mesh) = 0;
@@ -308,7 +314,7 @@ public:
virtual void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) = 0;
virtual RID multimesh_get_mesh(RID p_multimesh) const = 0;
- virtual Rect3 multimesh_get_aabb(RID p_multimesh) const = 0;
+ virtual AABB multimesh_get_aabb(RID p_multimesh) const = 0;
virtual Transform multimesh_instance_get_transform(RID p_multimesh, int p_index) const = 0;
virtual Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const = 0;
@@ -354,6 +360,7 @@ public:
enum LightParam {
LIGHT_PARAM_ENERGY,
+ LIGHT_PARAM_INDIRECT_ENERGY,
LIGHT_PARAM_SPECULAR,
LIGHT_PARAM_RANGE,
LIGHT_PARAM_ATTENUATION,
@@ -370,7 +377,9 @@ public:
LIGHT_PARAM_MAX
};
- virtual RID light_create(LightType p_type) = 0;
+ virtual RID directional_light_create() = 0;
+ virtual RID omni_light_create() = 0;
+ virtual RID spot_light_create() = 0;
virtual void light_set_color(RID p_light, const Color &p_color) = 0;
virtual void light_set_param(RID p_light, LightParam p_param, float p_value) = 0;
@@ -441,8 +450,8 @@ public:
virtual RID gi_probe_create() = 0;
- virtual void gi_probe_set_bounds(RID p_probe, const Rect3 &p_bounds) = 0;
- virtual Rect3 gi_probe_get_bounds(RID p_probe) const = 0;
+ virtual void gi_probe_set_bounds(RID p_probe, const AABB &p_bounds) = 0;
+ virtual AABB gi_probe_get_bounds(RID p_probe) const = 0;
virtual void gi_probe_set_cell_size(RID p_probe, float p_range) = 0;
virtual float gi_probe_get_cell_size(RID p_probe) const = 0;
@@ -485,7 +494,7 @@ public:
virtual void particles_set_pre_process_time(RID p_particles, float p_time) = 0;
virtual void particles_set_explosiveness_ratio(RID p_particles, float p_ratio) = 0;
virtual void particles_set_randomness_ratio(RID p_particles, float p_ratio) = 0;
- virtual void particles_set_custom_aabb(RID p_particles, const Rect3 &p_aabb) = 0;
+ virtual void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) = 0;
virtual void particles_set_speed_scale(RID p_particles, float p_scale) = 0;
virtual void particles_set_use_local_coordinates(RID p_particles, bool p_enable) = 0;
virtual void particles_set_process_material(RID p_particles, RID p_material) = 0;
@@ -504,7 +513,7 @@ public:
virtual void particles_set_draw_passes(RID p_particles, int p_count) = 0;
virtual void particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) = 0;
- virtual Rect3 particles_get_current_aabb(RID p_particles) = 0;
+ virtual AABB particles_get_current_aabb(RID p_particles) = 0;
virtual void particles_set_emission_transform(RID p_particles, const Transform &p_transform) = 0; //this is only used for 2D, in 3D it's automatic
@@ -675,7 +684,21 @@ public:
virtual void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, RID p_ramp) = 0;
virtual void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_in, float p_fade_out, float p_depth_tolerance, bool p_roughness) = 0;
- virtual void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_radius2, float p_intensity2, float p_bias, float p_light_affect, const Color &p_color, bool p_blur) = 0;
+
+ enum EnvironmentSSAOQuality {
+ ENV_SSAO_QUALITY_LOW,
+ ENV_SSAO_QUALITY_MEDIUM,
+ ENV_SSAO_QUALITY_HIGH,
+ };
+
+ enum EnvironmentSSAOBlur {
+ ENV_SSAO_BLUR_DISABLED,
+ ENV_SSAO_BLUR_1x1,
+ ENV_SSAO_BLUR_2x2,
+ ENV_SSAO_BLUR_3x3,
+ };
+
+ virtual void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_radius2, float p_intensity2, float p_bias, float p_light_affect, const Color &p_color, EnvironmentSSAOQuality p_quality, EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness) = 0;
virtual void environment_set_fog(RID p_env, bool p_enable, const Color &p_color, const Color &p_sun_color, float p_sun_amount) = 0;
virtual void environment_set_fog_depth(RID p_env, bool p_enable, float p_depth_begin, float p_depth_curve, bool p_transmit, float p_transmit_curve) = 0;
@@ -730,13 +753,15 @@ public:
virtual void instance_set_surface_material(RID p_instance, int p_surface, RID p_material) = 0;
virtual void instance_set_visible(RID p_instance, bool p_visible) = 0;
+ virtual void instance_set_custom_aabb(RID p_instance, AABB aabb) = 0;
+
virtual void instance_attach_skeleton(RID p_instance, RID p_skeleton) = 0;
virtual void instance_set_exterior(RID p_instance, bool p_enabled) = 0;
virtual void instance_set_extra_visibility_margin(RID p_instance, real_t p_margin) = 0;
// don't use these in a game!
- virtual Vector<ObjectID> instances_cull_aabb(const Rect3 &p_aabb, RID p_scenario = RID()) const = 0;
+ virtual Vector<ObjectID> instances_cull_aabb(const AABB &p_aabb, RID p_scenario = RID()) const = 0;
virtual Vector<ObjectID> instances_cull_ray(const Vector3 &p_from, const Vector3 &p_to, RID p_scenario = RID()) const = 0;
virtual Vector<ObjectID> instances_cull_convex(const Vector<Plane> &p_convex, RID p_scenario = RID()) const = 0;
@@ -791,7 +816,7 @@ public:
virtual void canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color) = 0;
virtual void canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color) = 0;
virtual void canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, RID p_normal_map = RID()) = 0;
- virtual void canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, RID p_normal_map = RID(), bool p_clip_uv = true) = 0;
+ virtual void canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, RID p_normal_map = RID(), bool p_clip_uv = false) = 0;
virtual void canvas_item_add_nine_patch(RID p_item, const Rect2 &p_rect, const Rect2 &p_source, RID p_texture, const Vector2 &p_topleft, const Vector2 &p_bottomright, NinePatchAxisMode p_x_axis_mode = NINE_PATCH_STRETCH, NinePatchAxisMode p_y_axis_mode = NINE_PATCH_STRETCH, bool p_draw_center = true, const Color &p_modulate = Color(1, 1, 1), RID p_normal_map = RID()) = 0;
virtual void canvas_item_add_primitive(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture, float p_width = 1.0, RID p_normal_map = RID()) = 0;
virtual void canvas_item_add_polygon(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), RID p_texture = RID(), RID p_normal_map = RID(), bool p_antialiased = false) = 0;
@@ -941,18 +966,29 @@ public:
};
// make variant understand the enums
-
VARIANT_ENUM_CAST(VisualServer::CubeMapSide);
VARIANT_ENUM_CAST(VisualServer::TextureFlags);
VARIANT_ENUM_CAST(VisualServer::ShaderMode);
VARIANT_ENUM_CAST(VisualServer::ArrayType);
VARIANT_ENUM_CAST(VisualServer::ArrayFormat);
VARIANT_ENUM_CAST(VisualServer::PrimitiveType);
+VARIANT_ENUM_CAST(VisualServer::BlendShapeMode);
VARIANT_ENUM_CAST(VisualServer::LightType);
VARIANT_ENUM_CAST(VisualServer::LightParam);
+VARIANT_ENUM_CAST(VisualServer::ViewportUpdateMode);
+VARIANT_ENUM_CAST(VisualServer::ViewportClearMode);
+VARIANT_ENUM_CAST(VisualServer::ViewportMSAA);
+VARIANT_ENUM_CAST(VisualServer::ViewportUsage);
+VARIANT_ENUM_CAST(VisualServer::ViewportRenderInfo);
+VARIANT_ENUM_CAST(VisualServer::ViewportDebugDraw);
VARIANT_ENUM_CAST(VisualServer::ScenarioDebugMode);
VARIANT_ENUM_CAST(VisualServer::InstanceType);
+VARIANT_ENUM_CAST(VisualServer::NinePatchAxisMode);
+VARIANT_ENUM_CAST(VisualServer::CanvasLightMode);
+VARIANT_ENUM_CAST(VisualServer::CanvasLightShadowFilter);
+VARIANT_ENUM_CAST(VisualServer::CanvasOccluderPolygonCullMode);
VARIANT_ENUM_CAST(VisualServer::RenderInfo);
+VARIANT_ENUM_CAST(VisualServer::Features);
//typedef VisualServer VS; // makes it easier to use
#define VS VisualServer
diff --git a/thirdparty/README.md b/thirdparty/README.md
index c081ad29b6..05aface43b 100644
--- a/thirdparty/README.md
+++ b/thirdparty/README.md
@@ -73,7 +73,7 @@ Use UI font if exists, because it has tight vertial metrix and good for UI.
## freetype
- Upstream: https://www.freetype.org
-- Version: 2.8
+- Version: 2.8.1
- License: FreeType License (BSD-like)
Files extracted from upstream source:
@@ -121,7 +121,7 @@ Files extracted from upstream source:
## libpng
- Upstream: http://libpng.org/pub/png/libpng.html
-- Version: 1.6.32
+- Version: 1.6.34
- License: libpng/zlib
Files extracted from upstream source:
@@ -416,7 +416,7 @@ Files extracted from upstream source:
## zstd
- Upstream: https://github.com/facebook/zstd
-- Version: 1.3.1
+- Version: 1.3.2
- License: BSD-3-Clause
Files extracted from upstream source:
diff --git a/thirdparty/bullet/src/Bullet3Collision/BroadPhaseCollision/b3BroadphaseCallback.h b/thirdparty/bullet/src/Bullet3Collision/BroadPhaseCollision/b3BroadphaseCallback.h
new file mode 100644
index 0000000000..1bc56cf80a
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Collision/BroadPhaseCollision/b3BroadphaseCallback.h
@@ -0,0 +1,40 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2013 Erwin Coumans 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 B3_BROADPHASE_CALLBACK_H
+#define B3_BROADPHASE_CALLBACK_H
+
+#include "Bullet3Common/b3Vector3.h"
+struct b3BroadphaseProxy;
+
+
+struct b3BroadphaseAabbCallback
+{
+ virtual ~b3BroadphaseAabbCallback() {}
+ virtual bool process(const b3BroadphaseProxy* proxy) = 0;
+};
+
+
+struct b3BroadphaseRayCallback : public b3BroadphaseAabbCallback
+{
+ ///added some cached data to accelerate ray-AABB tests
+ b3Vector3 m_rayDirectionInverse;
+ unsigned int m_signs[3];
+ b3Scalar m_lambda_max;
+
+ virtual ~b3BroadphaseRayCallback() {}
+};
+
+#endif //B3_BROADPHASE_CALLBACK_H
diff --git a/thirdparty/bullet/src/Bullet3Collision/BroadPhaseCollision/b3DynamicBvh.cpp b/thirdparty/bullet/src/Bullet3Collision/BroadPhaseCollision/b3DynamicBvh.cpp
new file mode 100644
index 0000000000..0f04efe331
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Collision/BroadPhaseCollision/b3DynamicBvh.cpp
@@ -0,0 +1,1325 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2013 Erwin Coumans 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.
+*/
+///b3DynamicBvh implementation by Nathanael Presson
+
+#include "b3DynamicBvh.h"
+
+//
+typedef b3AlignedObjectArray<b3DbvtNode*> b3NodeArray;
+typedef b3AlignedObjectArray<const b3DbvtNode*> b3ConstNodeArray;
+
+//
+struct b3DbvtNodeEnumerator : b3DynamicBvh::ICollide
+{
+ b3ConstNodeArray nodes;
+ void Process(const b3DbvtNode* n) { nodes.push_back(n); }
+};
+
+//
+static B3_DBVT_INLINE int b3IndexOf(const b3DbvtNode* node)
+{
+ return(node->parent->childs[1]==node);
+}
+
+//
+static B3_DBVT_INLINE b3DbvtVolume b3Merge( const b3DbvtVolume& a,
+ const b3DbvtVolume& b)
+{
+#if (B3_DBVT_MERGE_IMPL==B3_DBVT_IMPL_SSE)
+ B3_ATTRIBUTE_ALIGNED16(char locals[sizeof(b3DbvtAabbMm)]);
+ b3DbvtVolume& res=*(b3DbvtVolume*)locals;
+#else
+ b3DbvtVolume res;
+#endif
+ b3Merge(a,b,res);
+ return(res);
+}
+
+// volume+edge lengths
+static B3_DBVT_INLINE b3Scalar b3Size(const b3DbvtVolume& a)
+{
+ const b3Vector3 edges=a.Lengths();
+ return( edges.x*edges.y*edges.z+
+ edges.x+edges.y+edges.z);
+}
+
+//
+static void b3GetMaxDepth(const b3DbvtNode* node,int depth,int& maxdepth)
+{
+ if(node->isinternal())
+ {
+ b3GetMaxDepth(node->childs[0],depth+1,maxdepth);
+ b3GetMaxDepth(node->childs[1],depth+1,maxdepth);
+ } else maxdepth=b3Max(maxdepth,depth);
+}
+
+//
+static B3_DBVT_INLINE void b3DeleteNode( b3DynamicBvh* pdbvt,
+ b3DbvtNode* node)
+{
+ b3AlignedFree(pdbvt->m_free);
+ pdbvt->m_free=node;
+}
+
+//
+static void b3RecurseDeleteNode( b3DynamicBvh* pdbvt,
+ b3DbvtNode* node)
+{
+ if(!node->isleaf())
+ {
+ b3RecurseDeleteNode(pdbvt,node->childs[0]);
+ b3RecurseDeleteNode(pdbvt,node->childs[1]);
+ }
+ if(node==pdbvt->m_root) pdbvt->m_root=0;
+ b3DeleteNode(pdbvt,node);
+}
+
+//
+static B3_DBVT_INLINE b3DbvtNode* b3CreateNode( b3DynamicBvh* pdbvt,
+ b3DbvtNode* parent,
+ void* data)
+{
+ b3DbvtNode* node;
+ if(pdbvt->m_free)
+ { node=pdbvt->m_free;pdbvt->m_free=0; }
+ else
+ { node=new(b3AlignedAlloc(sizeof(b3DbvtNode),16)) b3DbvtNode(); }
+ node->parent = parent;
+ node->data = data;
+ node->childs[1] = 0;
+ return(node);
+}
+
+//
+static B3_DBVT_INLINE b3DbvtNode* b3CreateNode( b3DynamicBvh* pdbvt,
+ b3DbvtNode* parent,
+ const b3DbvtVolume& volume,
+ void* data)
+{
+ b3DbvtNode* node=b3CreateNode(pdbvt,parent,data);
+ node->volume=volume;
+ return(node);
+}
+
+//
+static B3_DBVT_INLINE b3DbvtNode* b3CreateNode( b3DynamicBvh* pdbvt,
+ b3DbvtNode* parent,
+ const b3DbvtVolume& volume0,
+ const b3DbvtVolume& volume1,
+ void* data)
+{
+ b3DbvtNode* node=b3CreateNode(pdbvt,parent,data);
+ b3Merge(volume0,volume1,node->volume);
+ return(node);
+}
+
+//
+static void b3InsertLeaf( b3DynamicBvh* pdbvt,
+ b3DbvtNode* root,
+ b3DbvtNode* leaf)
+{
+ if(!pdbvt->m_root)
+ {
+ pdbvt->m_root = leaf;
+ leaf->parent = 0;
+ }
+ else
+ {
+ if(!root->isleaf())
+ {
+ do {
+ root=root->childs[b3Select( leaf->volume,
+ root->childs[0]->volume,
+ root->childs[1]->volume)];
+ } while(!root->isleaf());
+ }
+ b3DbvtNode* prev=root->parent;
+ b3DbvtNode* node=b3CreateNode(pdbvt,prev,leaf->volume,root->volume,0);
+ if(prev)
+ {
+ prev->childs[b3IndexOf(root)] = node;
+ node->childs[0] = root;root->parent=node;
+ node->childs[1] = leaf;leaf->parent=node;
+ do {
+ if(!prev->volume.Contain(node->volume))
+ b3Merge(prev->childs[0]->volume,prev->childs[1]->volume,prev->volume);
+ else
+ break;
+ node=prev;
+ } while(0!=(prev=node->parent));
+ }
+ else
+ {
+ node->childs[0] = root;root->parent=node;
+ node->childs[1] = leaf;leaf->parent=node;
+ pdbvt->m_root = node;
+ }
+ }
+}
+
+//
+static b3DbvtNode* b3RemoveLeaf( b3DynamicBvh* pdbvt,
+ b3DbvtNode* leaf)
+{
+ if(leaf==pdbvt->m_root)
+ {
+ pdbvt->m_root=0;
+ return(0);
+ }
+ else
+ {
+ b3DbvtNode* parent=leaf->parent;
+ b3DbvtNode* prev=parent->parent;
+ b3DbvtNode* sibling=parent->childs[1-b3IndexOf(leaf)];
+ if(prev)
+ {
+ prev->childs[b3IndexOf(parent)]=sibling;
+ sibling->parent=prev;
+ b3DeleteNode(pdbvt,parent);
+ while(prev)
+ {
+ const b3DbvtVolume pb=prev->volume;
+ b3Merge(prev->childs[0]->volume,prev->childs[1]->volume,prev->volume);
+ if(b3NotEqual(pb,prev->volume))
+ {
+ prev=prev->parent;
+ } else break;
+ }
+ return(prev?prev:pdbvt->m_root);
+ }
+ else
+ {
+ pdbvt->m_root=sibling;
+ sibling->parent=0;
+ b3DeleteNode(pdbvt,parent);
+ return(pdbvt->m_root);
+ }
+ }
+}
+
+//
+static void b3FetchLeaves(b3DynamicBvh* pdbvt,
+ b3DbvtNode* root,
+ b3NodeArray& leaves,
+ int depth=-1)
+{
+ if(root->isinternal()&&depth)
+ {
+ b3FetchLeaves(pdbvt,root->childs[0],leaves,depth-1);
+ b3FetchLeaves(pdbvt,root->childs[1],leaves,depth-1);
+ b3DeleteNode(pdbvt,root);
+ }
+ else
+ {
+ leaves.push_back(root);
+ }
+}
+
+static bool b3LeftOfAxis( const b3DbvtNode* node,
+ const b3Vector3& org,
+ const b3Vector3& axis)
+{
+ return b3Dot(axis,node->volume.Center()-org) <= 0;
+}
+
+// Partitions leaves such that leaves[0, n) are on the
+// left of axis, and leaves[n, count) are on the right
+// of axis. returns N.
+static int b3Split( b3DbvtNode** leaves,
+ int count,
+ const b3Vector3& org,
+ const b3Vector3& axis)
+{
+ int begin=0;
+ int end=count;
+ for(;;)
+ {
+ while(begin!=end && b3LeftOfAxis(leaves[begin],org,axis))
+ {
+ ++begin;
+ }
+
+ if(begin==end)
+ {
+ break;
+ }
+
+ while(begin!=end && !b3LeftOfAxis(leaves[end-1],org,axis))
+ {
+ --end;
+ }
+
+ if(begin==end)
+ {
+ break;
+ }
+
+ // swap out of place nodes
+ --end;
+ b3DbvtNode* temp=leaves[begin];
+ leaves[begin]=leaves[end];
+ leaves[end]=temp;
+ ++begin;
+ }
+
+ return begin;
+}
+
+//
+static b3DbvtVolume b3Bounds( b3DbvtNode** leaves,
+ int count)
+{
+#if B3_DBVT_MERGE_IMPL==B3_DBVT_IMPL_SSE
+ B3_ATTRIBUTE_ALIGNED16(char locals[sizeof(b3DbvtVolume)]);
+ b3DbvtVolume& volume=*(b3DbvtVolume*)locals;
+ volume=leaves[0]->volume;
+#else
+ b3DbvtVolume volume=leaves[0]->volume;
+#endif
+ for(int i=1,ni=count;i<ni;++i)
+ {
+ b3Merge(volume,leaves[i]->volume,volume);
+ }
+ return(volume);
+}
+
+//
+static void b3BottomUp( b3DynamicBvh* pdbvt,
+ b3DbvtNode** leaves,
+ int count)
+{
+ while(count>1)
+ {
+ b3Scalar minsize=B3_INFINITY;
+ int minidx[2]={-1,-1};
+ for(int i=0;i<count;++i)
+ {
+ for(int j=i+1;j<count;++j)
+ {
+ const b3Scalar sz=b3Size(b3Merge(leaves[i]->volume,leaves[j]->volume));
+ if(sz<minsize)
+ {
+ minsize = sz;
+ minidx[0] = i;
+ minidx[1] = j;
+ }
+ }
+ }
+ b3DbvtNode* n[] = {leaves[minidx[0]],leaves[minidx[1]]};
+ b3DbvtNode* p = b3CreateNode(pdbvt,0,n[0]->volume,n[1]->volume,0);
+ p->childs[0] = n[0];
+ p->childs[1] = n[1];
+ n[0]->parent = p;
+ n[1]->parent = p;
+ leaves[minidx[0]] = p;
+ leaves[minidx[1]] = leaves[count-1];
+ --count;
+ }
+}
+
+//
+static b3DbvtNode* b3TopDown(b3DynamicBvh* pdbvt,
+ b3DbvtNode** leaves,
+ int count,
+ int bu_treshold)
+{
+ static const b3Vector3 axis[]={b3MakeVector3(1,0,0),
+ b3MakeVector3(0,1,0),
+ b3MakeVector3(0,0,1)};
+ b3Assert(bu_treshold>1);
+ if(count>1)
+ {
+ if(count>bu_treshold)
+ {
+ const b3DbvtVolume vol=b3Bounds(leaves,count);
+ const b3Vector3 org=vol.Center();
+ int partition;
+ int bestaxis=-1;
+ int bestmidp=count;
+ int splitcount[3][2]={{0,0},{0,0},{0,0}};
+ int i;
+ for( i=0;i<count;++i)
+ {
+ const b3Vector3 x=leaves[i]->volume.Center()-org;
+ for(int j=0;j<3;++j)
+ {
+ ++splitcount[j][b3Dot(x,axis[j])>0?1:0];
+ }
+ }
+ for( i=0;i<3;++i)
+ {
+ if((splitcount[i][0]>0)&&(splitcount[i][1]>0))
+ {
+ const int midp=(int)b3Fabs(b3Scalar(splitcount[i][0]-splitcount[i][1]));
+ if(midp<bestmidp)
+ {
+ bestaxis=i;
+ bestmidp=midp;
+ }
+ }
+ }
+ if(bestaxis>=0)
+ {
+ partition=b3Split(leaves,count,org,axis[bestaxis]);
+ b3Assert(partition!=0 && partition!=count);
+ }
+ else
+ {
+ partition=count/2+1;
+ }
+ b3DbvtNode* node=b3CreateNode(pdbvt,0,vol,0);
+ node->childs[0]=b3TopDown(pdbvt,&leaves[0],partition,bu_treshold);
+ node->childs[1]=b3TopDown(pdbvt,&leaves[partition],count-partition,bu_treshold);
+ node->childs[0]->parent=node;
+ node->childs[1]->parent=node;
+ return(node);
+ }
+ else
+ {
+ b3BottomUp(pdbvt,leaves,count);
+ return(leaves[0]);
+ }
+ }
+ return(leaves[0]);
+}
+
+//
+static B3_DBVT_INLINE b3DbvtNode* b3Sort(b3DbvtNode* n,b3DbvtNode*& r)
+{
+ b3DbvtNode* p=n->parent;
+ b3Assert(n->isinternal());
+ if(p>n)
+ {
+ const int i=b3IndexOf(n);
+ const int j=1-i;
+ b3DbvtNode* s=p->childs[j];
+ b3DbvtNode* q=p->parent;
+ b3Assert(n==p->childs[i]);
+ if(q) q->childs[b3IndexOf(p)]=n; else r=n;
+ s->parent=n;
+ p->parent=n;
+ n->parent=q;
+ p->childs[0]=n->childs[0];
+ p->childs[1]=n->childs[1];
+ n->childs[0]->parent=p;
+ n->childs[1]->parent=p;
+ n->childs[i]=p;
+ n->childs[j]=s;
+ b3Swap(p->volume,n->volume);
+ return(p);
+ }
+ return(n);
+}
+
+#if 0
+static B3_DBVT_INLINE b3DbvtNode* walkup(b3DbvtNode* n,int count)
+{
+ while(n&&(count--)) n=n->parent;
+ return(n);
+}
+#endif
+
+//
+// Api
+//
+
+//
+b3DynamicBvh::b3DynamicBvh()
+{
+ m_root = 0;
+ m_free = 0;
+ m_lkhd = -1;
+ m_leaves = 0;
+ m_opath = 0;
+}
+
+//
+b3DynamicBvh::~b3DynamicBvh()
+{
+ clear();
+}
+
+//
+void b3DynamicBvh::clear()
+{
+ if(m_root)
+ b3RecurseDeleteNode(this,m_root);
+ b3AlignedFree(m_free);
+ m_free=0;
+ m_lkhd = -1;
+ m_stkStack.clear();
+ m_opath = 0;
+
+}
+
+//
+void b3DynamicBvh::optimizeBottomUp()
+{
+ if(m_root)
+ {
+ b3NodeArray leaves;
+ leaves.reserve(m_leaves);
+ b3FetchLeaves(this,m_root,leaves);
+ b3BottomUp(this,&leaves[0],leaves.size());
+ m_root=leaves[0];
+ }
+}
+
+//
+void b3DynamicBvh::optimizeTopDown(int bu_treshold)
+{
+ if(m_root)
+ {
+ b3NodeArray leaves;
+ leaves.reserve(m_leaves);
+ b3FetchLeaves(this,m_root,leaves);
+ m_root=b3TopDown(this,&leaves[0],leaves.size(),bu_treshold);
+ }
+}
+
+//
+void b3DynamicBvh::optimizeIncremental(int passes)
+{
+ if(passes<0) passes=m_leaves;
+ if(m_root&&(passes>0))
+ {
+ do {
+ b3DbvtNode* node=m_root;
+ unsigned bit=0;
+ while(node->isinternal())
+ {
+ node=b3Sort(node,m_root)->childs[(m_opath>>bit)&1];
+ bit=(bit+1)&(sizeof(unsigned)*8-1);
+ }
+ update(node);
+ ++m_opath;
+ } while(--passes);
+ }
+}
+
+//
+b3DbvtNode* b3DynamicBvh::insert(const b3DbvtVolume& volume,void* data)
+{
+ b3DbvtNode* leaf=b3CreateNode(this,0,volume,data);
+ b3InsertLeaf(this,m_root,leaf);
+ ++m_leaves;
+ return(leaf);
+}
+
+//
+void b3DynamicBvh::update(b3DbvtNode* leaf,int lookahead)
+{
+ b3DbvtNode* root=b3RemoveLeaf(this,leaf);
+ if(root)
+ {
+ if(lookahead>=0)
+ {
+ for(int i=0;(i<lookahead)&&root->parent;++i)
+ {
+ root=root->parent;
+ }
+ } else root=m_root;
+ }
+ b3InsertLeaf(this,root,leaf);
+}
+
+//
+void b3DynamicBvh::update(b3DbvtNode* leaf,b3DbvtVolume& volume)
+{
+ b3DbvtNode* root=b3RemoveLeaf(this,leaf);
+ if(root)
+ {
+ if(m_lkhd>=0)
+ {
+ for(int i=0;(i<m_lkhd)&&root->parent;++i)
+ {
+ root=root->parent;
+ }
+ } else root=m_root;
+ }
+ leaf->volume=volume;
+ b3InsertLeaf(this,root,leaf);
+}
+
+//
+bool b3DynamicBvh::update(b3DbvtNode* leaf,b3DbvtVolume& volume,const b3Vector3& velocity,b3Scalar margin)
+{
+ if(leaf->volume.Contain(volume)) return(false);
+ volume.Expand(b3MakeVector3(margin,margin,margin));
+ volume.SignedExpand(velocity);
+ update(leaf,volume);
+ return(true);
+}
+
+//
+bool b3DynamicBvh::update(b3DbvtNode* leaf,b3DbvtVolume& volume,const b3Vector3& velocity)
+{
+ if(leaf->volume.Contain(volume)) return(false);
+ volume.SignedExpand(velocity);
+ update(leaf,volume);
+ return(true);
+}
+
+//
+bool b3DynamicBvh::update(b3DbvtNode* leaf,b3DbvtVolume& volume,b3Scalar margin)
+{
+ if(leaf->volume.Contain(volume)) return(false);
+ volume.Expand(b3MakeVector3(margin,margin,margin));
+ update(leaf,volume);
+ return(true);
+}
+
+//
+void b3DynamicBvh::remove(b3DbvtNode* leaf)
+{
+ b3RemoveLeaf(this,leaf);
+ b3DeleteNode(this,leaf);
+ --m_leaves;
+}
+
+//
+void b3DynamicBvh::write(IWriter* iwriter) const
+{
+ b3DbvtNodeEnumerator nodes;
+ nodes.nodes.reserve(m_leaves*2);
+ enumNodes(m_root,nodes);
+ iwriter->Prepare(m_root,nodes.nodes.size());
+ for(int i=0;i<nodes.nodes.size();++i)
+ {
+ const b3DbvtNode* n=nodes.nodes[i];
+ int p=-1;
+ if(n->parent) p=nodes.nodes.findLinearSearch(n->parent);
+ if(n->isinternal())
+ {
+ const int c0=nodes.nodes.findLinearSearch(n->childs[0]);
+ const int c1=nodes.nodes.findLinearSearch(n->childs[1]);
+ iwriter->WriteNode(n,i,p,c0,c1);
+ }
+ else
+ {
+ iwriter->WriteLeaf(n,i,p);
+ }
+ }
+}
+
+//
+void b3DynamicBvh::clone(b3DynamicBvh& dest,IClone* iclone) const
+{
+ dest.clear();
+ if(m_root!=0)
+ {
+ b3AlignedObjectArray<sStkCLN> stack;
+ stack.reserve(m_leaves);
+ stack.push_back(sStkCLN(m_root,0));
+ do {
+ const int i=stack.size()-1;
+ const sStkCLN e=stack[i];
+ b3DbvtNode* n=b3CreateNode(&dest,e.parent,e.node->volume,e.node->data);
+ stack.pop_back();
+ if(e.parent!=0)
+ e.parent->childs[i&1]=n;
+ else
+ dest.m_root=n;
+ if(e.node->isinternal())
+ {
+ stack.push_back(sStkCLN(e.node->childs[0],n));
+ stack.push_back(sStkCLN(e.node->childs[1],n));
+ }
+ else
+ {
+ iclone->CloneLeaf(n);
+ }
+ } while(stack.size()>0);
+ }
+}
+
+//
+int b3DynamicBvh::maxdepth(const b3DbvtNode* node)
+{
+ int depth=0;
+ if(node) b3GetMaxDepth(node,1,depth);
+ return(depth);
+}
+
+//
+int b3DynamicBvh::countLeaves(const b3DbvtNode* node)
+{
+ if(node->isinternal())
+ return(countLeaves(node->childs[0])+countLeaves(node->childs[1]));
+ else
+ return(1);
+}
+
+//
+void b3DynamicBvh::extractLeaves(const b3DbvtNode* node,b3AlignedObjectArray<const b3DbvtNode*>& leaves)
+{
+ if(node->isinternal())
+ {
+ extractLeaves(node->childs[0],leaves);
+ extractLeaves(node->childs[1],leaves);
+ }
+ else
+ {
+ leaves.push_back(node);
+ }
+}
+
+//
+#if B3_DBVT_ENABLE_BENCHMARK
+
+#include <stdio.h>
+#include <stdlib.h>
+
+
+/*
+q6600,2.4ghz
+
+/Ox /Ob2 /Oi /Ot /I "." /I "..\.." /I "..\..\src" /D "NDEBUG" /D "_LIB" /D "_WINDOWS" /D "_CRT_SECURE_NO_DEPRECATE" /D "_CRT_NONSTDC_NO_DEPRECATE" /D "WIN32"
+/GF /FD /MT /GS- /Gy /arch:SSE2 /Zc:wchar_t- /Fp"..\..\out\release8\build\libbulletcollision\libbulletcollision.pch"
+/Fo"..\..\out\release8\build\libbulletcollision\\"
+/Fd"..\..\out\release8\build\libbulletcollision\bulletcollision.pdb"
+/W3 /nologo /c /Wp64 /Zi /errorReport:prompt
+
+Benchmarking dbvt...
+World scale: 100.000000
+Extents base: 1.000000
+Extents range: 4.000000
+Leaves: 8192
+sizeof(b3DbvtVolume): 32 bytes
+sizeof(b3DbvtNode): 44 bytes
+[1] b3DbvtVolume intersections: 3499 ms (-1%)
+[2] b3DbvtVolume merges: 1934 ms (0%)
+[3] b3DynamicBvh::collideTT: 5485 ms (-21%)
+[4] b3DynamicBvh::collideTT self: 2814 ms (-20%)
+[5] b3DynamicBvh::collideTT xform: 7379 ms (-1%)
+[6] b3DynamicBvh::collideTT xform,self: 7270 ms (-2%)
+[7] b3DynamicBvh::rayTest: 6314 ms (0%),(332143 r/s)
+[8] insert/remove: 2093 ms (0%),(1001983 ir/s)
+[9] updates (teleport): 1879 ms (-3%),(1116100 u/s)
+[10] updates (jitter): 1244 ms (-4%),(1685813 u/s)
+[11] optimize (incremental): 2514 ms (0%),(1668000 o/s)
+[12] b3DbvtVolume notequal: 3659 ms (0%)
+[13] culling(OCL+fullsort): 2218 ms (0%),(461 t/s)
+[14] culling(OCL+qsort): 3688 ms (5%),(2221 t/s)
+[15] culling(KDOP+qsort): 1139 ms (-1%),(7192 t/s)
+[16] insert/remove batch(256): 5092 ms (0%),(823704 bir/s)
+[17] b3DbvtVolume select: 3419 ms (0%)
+*/
+
+struct b3DbvtBenchmark
+{
+ struct NilPolicy : b3DynamicBvh::ICollide
+ {
+ NilPolicy() : m_pcount(0),m_depth(-B3_INFINITY),m_checksort(true) {}
+ void Process(const b3DbvtNode*,const b3DbvtNode*) { ++m_pcount; }
+ void Process(const b3DbvtNode*) { ++m_pcount; }
+ void Process(const b3DbvtNode*,b3Scalar depth)
+ {
+ ++m_pcount;
+ if(m_checksort)
+ { if(depth>=m_depth) m_depth=depth; else printf("wrong depth: %f (should be >= %f)\r\n",depth,m_depth); }
+ }
+ int m_pcount;
+ b3Scalar m_depth;
+ bool m_checksort;
+ };
+ struct P14 : b3DynamicBvh::ICollide
+ {
+ struct Node
+ {
+ const b3DbvtNode* leaf;
+ b3Scalar depth;
+ };
+ void Process(const b3DbvtNode* leaf,b3Scalar depth)
+ {
+ Node n;
+ n.leaf = leaf;
+ n.depth = depth;
+ }
+ static int sortfnc(const Node& a,const Node& b)
+ {
+ if(a.depth<b.depth) return(+1);
+ if(a.depth>b.depth) return(-1);
+ return(0);
+ }
+ b3AlignedObjectArray<Node> m_nodes;
+ };
+ struct P15 : b3DynamicBvh::ICollide
+ {
+ struct Node
+ {
+ const b3DbvtNode* leaf;
+ b3Scalar depth;
+ };
+ void Process(const b3DbvtNode* leaf)
+ {
+ Node n;
+ n.leaf = leaf;
+ n.depth = dot(leaf->volume.Center(),m_axis);
+ }
+ static int sortfnc(const Node& a,const Node& b)
+ {
+ if(a.depth<b.depth) return(+1);
+ if(a.depth>b.depth) return(-1);
+ return(0);
+ }
+ b3AlignedObjectArray<Node> m_nodes;
+ b3Vector3 m_axis;
+ };
+ static b3Scalar RandUnit()
+ {
+ return(rand()/(b3Scalar)RAND_MAX);
+ }
+ static b3Vector3 RandVector3()
+ {
+ return(b3Vector3(RandUnit(),RandUnit(),RandUnit()));
+ }
+ static b3Vector3 RandVector3(b3Scalar cs)
+ {
+ return(RandVector3()*cs-b3Vector3(cs,cs,cs)/2);
+ }
+ static b3DbvtVolume RandVolume(b3Scalar cs,b3Scalar eb,b3Scalar es)
+ {
+ return(b3DbvtVolume::FromCE(RandVector3(cs),b3Vector3(eb,eb,eb)+RandVector3()*es));
+ }
+ static b3Transform RandTransform(b3Scalar cs)
+ {
+ b3Transform t;
+ t.setOrigin(RandVector3(cs));
+ t.setRotation(b3Quaternion(RandUnit()*B3_PI*2,RandUnit()*B3_PI*2,RandUnit()*B3_PI*2).normalized());
+ return(t);
+ }
+ static void RandTree(b3Scalar cs,b3Scalar eb,b3Scalar es,int leaves,b3DynamicBvh& dbvt)
+ {
+ dbvt.clear();
+ for(int i=0;i<leaves;++i)
+ {
+ dbvt.insert(RandVolume(cs,eb,es),0);
+ }
+ }
+};
+
+void b3DynamicBvh::benchmark()
+{
+ static const b3Scalar cfgVolumeCenterScale = 100;
+ static const b3Scalar cfgVolumeExentsBase = 1;
+ static const b3Scalar cfgVolumeExentsScale = 4;
+ static const int cfgLeaves = 8192;
+ static const bool cfgEnable = true;
+
+ //[1] b3DbvtVolume intersections
+ bool cfgBenchmark1_Enable = cfgEnable;
+ static const int cfgBenchmark1_Iterations = 8;
+ static const int cfgBenchmark1_Reference = 3499;
+ //[2] b3DbvtVolume merges
+ bool cfgBenchmark2_Enable = cfgEnable;
+ static const int cfgBenchmark2_Iterations = 4;
+ static const int cfgBenchmark2_Reference = 1945;
+ //[3] b3DynamicBvh::collideTT
+ bool cfgBenchmark3_Enable = cfgEnable;
+ static const int cfgBenchmark3_Iterations = 512;
+ static const int cfgBenchmark3_Reference = 5485;
+ //[4] b3DynamicBvh::collideTT self
+ bool cfgBenchmark4_Enable = cfgEnable;
+ static const int cfgBenchmark4_Iterations = 512;
+ static const int cfgBenchmark4_Reference = 2814;
+ //[5] b3DynamicBvh::collideTT xform
+ bool cfgBenchmark5_Enable = cfgEnable;
+ static const int cfgBenchmark5_Iterations = 512;
+ static const b3Scalar cfgBenchmark5_OffsetScale = 2;
+ static const int cfgBenchmark5_Reference = 7379;
+ //[6] b3DynamicBvh::collideTT xform,self
+ bool cfgBenchmark6_Enable = cfgEnable;
+ static const int cfgBenchmark6_Iterations = 512;
+ static const b3Scalar cfgBenchmark6_OffsetScale = 2;
+ static const int cfgBenchmark6_Reference = 7270;
+ //[7] b3DynamicBvh::rayTest
+ bool cfgBenchmark7_Enable = cfgEnable;
+ static const int cfgBenchmark7_Passes = 32;
+ static const int cfgBenchmark7_Iterations = 65536;
+ static const int cfgBenchmark7_Reference = 6307;
+ //[8] insert/remove
+ bool cfgBenchmark8_Enable = cfgEnable;
+ static const int cfgBenchmark8_Passes = 32;
+ static const int cfgBenchmark8_Iterations = 65536;
+ static const int cfgBenchmark8_Reference = 2105;
+ //[9] updates (teleport)
+ bool cfgBenchmark9_Enable = cfgEnable;
+ static const int cfgBenchmark9_Passes = 32;
+ static const int cfgBenchmark9_Iterations = 65536;
+ static const int cfgBenchmark9_Reference = 1879;
+ //[10] updates (jitter)
+ bool cfgBenchmark10_Enable = cfgEnable;
+ static const b3Scalar cfgBenchmark10_Scale = cfgVolumeCenterScale/10000;
+ static const int cfgBenchmark10_Passes = 32;
+ static const int cfgBenchmark10_Iterations = 65536;
+ static const int cfgBenchmark10_Reference = 1244;
+ //[11] optimize (incremental)
+ bool cfgBenchmark11_Enable = cfgEnable;
+ static const int cfgBenchmark11_Passes = 64;
+ static const int cfgBenchmark11_Iterations = 65536;
+ static const int cfgBenchmark11_Reference = 2510;
+ //[12] b3DbvtVolume notequal
+ bool cfgBenchmark12_Enable = cfgEnable;
+ static const int cfgBenchmark12_Iterations = 32;
+ static const int cfgBenchmark12_Reference = 3677;
+ //[13] culling(OCL+fullsort)
+ bool cfgBenchmark13_Enable = cfgEnable;
+ static const int cfgBenchmark13_Iterations = 1024;
+ static const int cfgBenchmark13_Reference = 2231;
+ //[14] culling(OCL+qsort)
+ bool cfgBenchmark14_Enable = cfgEnable;
+ static const int cfgBenchmark14_Iterations = 8192;
+ static const int cfgBenchmark14_Reference = 3500;
+ //[15] culling(KDOP+qsort)
+ bool cfgBenchmark15_Enable = cfgEnable;
+ static const int cfgBenchmark15_Iterations = 8192;
+ static const int cfgBenchmark15_Reference = 1151;
+ //[16] insert/remove batch
+ bool cfgBenchmark16_Enable = cfgEnable;
+ static const int cfgBenchmark16_BatchCount = 256;
+ static const int cfgBenchmark16_Passes = 16384;
+ static const int cfgBenchmark16_Reference = 5138;
+ //[17] select
+ bool cfgBenchmark17_Enable = cfgEnable;
+ static const int cfgBenchmark17_Iterations = 4;
+ static const int cfgBenchmark17_Reference = 3390;
+
+ b3Clock wallclock;
+ printf("Benchmarking dbvt...\r\n");
+ printf("\tWorld scale: %f\r\n",cfgVolumeCenterScale);
+ printf("\tExtents base: %f\r\n",cfgVolumeExentsBase);
+ printf("\tExtents range: %f\r\n",cfgVolumeExentsScale);
+ printf("\tLeaves: %u\r\n",cfgLeaves);
+ printf("\tsizeof(b3DbvtVolume): %u bytes\r\n",sizeof(b3DbvtVolume));
+ printf("\tsizeof(b3DbvtNode): %u bytes\r\n",sizeof(b3DbvtNode));
+ if(cfgBenchmark1_Enable)
+ {// Benchmark 1
+ srand(380843);
+ b3AlignedObjectArray<b3DbvtVolume> volumes;
+ b3AlignedObjectArray<bool> results;
+ volumes.resize(cfgLeaves);
+ results.resize(cfgLeaves);
+ for(int i=0;i<cfgLeaves;++i)
+ {
+ volumes[i]=b3DbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale);
+ }
+ printf("[1] b3DbvtVolume intersections: ");
+ wallclock.reset();
+ for(int i=0;i<cfgBenchmark1_Iterations;++i)
+ {
+ for(int j=0;j<cfgLeaves;++j)
+ {
+ for(int k=0;k<cfgLeaves;++k)
+ {
+ results[k]=Intersect(volumes[j],volumes[k]);
+ }
+ }
+ }
+ const int time=(int)wallclock.getTimeMilliseconds();
+ printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark1_Reference)*100/time);
+ }
+ if(cfgBenchmark2_Enable)
+ {// Benchmark 2
+ srand(380843);
+ b3AlignedObjectArray<b3DbvtVolume> volumes;
+ b3AlignedObjectArray<b3DbvtVolume> results;
+ volumes.resize(cfgLeaves);
+ results.resize(cfgLeaves);
+ for(int i=0;i<cfgLeaves;++i)
+ {
+ volumes[i]=b3DbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale);
+ }
+ printf("[2] b3DbvtVolume merges: ");
+ wallclock.reset();
+ for(int i=0;i<cfgBenchmark2_Iterations;++i)
+ {
+ for(int j=0;j<cfgLeaves;++j)
+ {
+ for(int k=0;k<cfgLeaves;++k)
+ {
+ Merge(volumes[j],volumes[k],results[k]);
+ }
+ }
+ }
+ const int time=(int)wallclock.getTimeMilliseconds();
+ printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark2_Reference)*100/time);
+ }
+ if(cfgBenchmark3_Enable)
+ {// Benchmark 3
+ srand(380843);
+ b3DynamicBvh dbvt[2];
+ b3DbvtBenchmark::NilPolicy policy;
+ b3DbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt[0]);
+ b3DbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt[1]);
+ dbvt[0].optimizeTopDown();
+ dbvt[1].optimizeTopDown();
+ printf("[3] b3DynamicBvh::collideTT: ");
+ wallclock.reset();
+ for(int i=0;i<cfgBenchmark3_Iterations;++i)
+ {
+ b3DynamicBvh::collideTT(dbvt[0].m_root,dbvt[1].m_root,policy);
+ }
+ const int time=(int)wallclock.getTimeMilliseconds();
+ printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark3_Reference)*100/time);
+ }
+ if(cfgBenchmark4_Enable)
+ {// Benchmark 4
+ srand(380843);
+ b3DynamicBvh dbvt;
+ b3DbvtBenchmark::NilPolicy policy;
+ b3DbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ dbvt.optimizeTopDown();
+ printf("[4] b3DynamicBvh::collideTT self: ");
+ wallclock.reset();
+ for(int i=0;i<cfgBenchmark4_Iterations;++i)
+ {
+ b3DynamicBvh::collideTT(dbvt.m_root,dbvt.m_root,policy);
+ }
+ const int time=(int)wallclock.getTimeMilliseconds();
+ printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark4_Reference)*100/time);
+ }
+ if(cfgBenchmark5_Enable)
+ {// Benchmark 5
+ srand(380843);
+ b3DynamicBvh dbvt[2];
+ b3AlignedObjectArray<b3Transform> transforms;
+ b3DbvtBenchmark::NilPolicy policy;
+ transforms.resize(cfgBenchmark5_Iterations);
+ for(int i=0;i<transforms.size();++i)
+ {
+ transforms[i]=b3DbvtBenchmark::RandTransform(cfgVolumeCenterScale*cfgBenchmark5_OffsetScale);
+ }
+ b3DbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt[0]);
+ b3DbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt[1]);
+ dbvt[0].optimizeTopDown();
+ dbvt[1].optimizeTopDown();
+ printf("[5] b3DynamicBvh::collideTT xform: ");
+ wallclock.reset();
+ for(int i=0;i<cfgBenchmark5_Iterations;++i)
+ {
+ b3DynamicBvh::collideTT(dbvt[0].m_root,dbvt[1].m_root,transforms[i],policy);
+ }
+ const int time=(int)wallclock.getTimeMilliseconds();
+ printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark5_Reference)*100/time);
+ }
+ if(cfgBenchmark6_Enable)
+ {// Benchmark 6
+ srand(380843);
+ b3DynamicBvh dbvt;
+ b3AlignedObjectArray<b3Transform> transforms;
+ b3DbvtBenchmark::NilPolicy policy;
+ transforms.resize(cfgBenchmark6_Iterations);
+ for(int i=0;i<transforms.size();++i)
+ {
+ transforms[i]=b3DbvtBenchmark::RandTransform(cfgVolumeCenterScale*cfgBenchmark6_OffsetScale);
+ }
+ b3DbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ dbvt.optimizeTopDown();
+ printf("[6] b3DynamicBvh::collideTT xform,self: ");
+ wallclock.reset();
+ for(int i=0;i<cfgBenchmark6_Iterations;++i)
+ {
+ b3DynamicBvh::collideTT(dbvt.m_root,dbvt.m_root,transforms[i],policy);
+ }
+ const int time=(int)wallclock.getTimeMilliseconds();
+ printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark6_Reference)*100/time);
+ }
+ if(cfgBenchmark7_Enable)
+ {// Benchmark 7
+ srand(380843);
+ b3DynamicBvh dbvt;
+ b3AlignedObjectArray<b3Vector3> rayorg;
+ b3AlignedObjectArray<b3Vector3> raydir;
+ b3DbvtBenchmark::NilPolicy policy;
+ rayorg.resize(cfgBenchmark7_Iterations);
+ raydir.resize(cfgBenchmark7_Iterations);
+ for(int i=0;i<rayorg.size();++i)
+ {
+ rayorg[i]=b3DbvtBenchmark::RandVector3(cfgVolumeCenterScale*2);
+ raydir[i]=b3DbvtBenchmark::RandVector3(cfgVolumeCenterScale*2);
+ }
+ b3DbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ dbvt.optimizeTopDown();
+ printf("[7] b3DynamicBvh::rayTest: ");
+ wallclock.reset();
+ for(int i=0;i<cfgBenchmark7_Passes;++i)
+ {
+ for(int j=0;j<cfgBenchmark7_Iterations;++j)
+ {
+ b3DynamicBvh::rayTest(dbvt.m_root,rayorg[j],rayorg[j]+raydir[j],policy);
+ }
+ }
+ const int time=(int)wallclock.getTimeMilliseconds();
+ unsigned rays=cfgBenchmark7_Passes*cfgBenchmark7_Iterations;
+ printf("%u ms (%i%%),(%u r/s)\r\n",time,(time-cfgBenchmark7_Reference)*100/time,(rays*1000)/time);
+ }
+ if(cfgBenchmark8_Enable)
+ {// Benchmark 8
+ srand(380843);
+ b3DynamicBvh dbvt;
+ b3DbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ dbvt.optimizeTopDown();
+ printf("[8] insert/remove: ");
+ wallclock.reset();
+ for(int i=0;i<cfgBenchmark8_Passes;++i)
+ {
+ for(int j=0;j<cfgBenchmark8_Iterations;++j)
+ {
+ dbvt.remove(dbvt.insert(b3DbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale),0));
+ }
+ }
+ const int time=(int)wallclock.getTimeMilliseconds();
+ const int ir=cfgBenchmark8_Passes*cfgBenchmark8_Iterations;
+ printf("%u ms (%i%%),(%u ir/s)\r\n",time,(time-cfgBenchmark8_Reference)*100/time,ir*1000/time);
+ }
+ if(cfgBenchmark9_Enable)
+ {// Benchmark 9
+ srand(380843);
+ b3DynamicBvh dbvt;
+ b3AlignedObjectArray<const b3DbvtNode*> leaves;
+ b3DbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ dbvt.optimizeTopDown();
+ dbvt.extractLeaves(dbvt.m_root,leaves);
+ printf("[9] updates (teleport): ");
+ wallclock.reset();
+ for(int i=0;i<cfgBenchmark9_Passes;++i)
+ {
+ for(int j=0;j<cfgBenchmark9_Iterations;++j)
+ {
+ dbvt.update(const_cast<b3DbvtNode*>(leaves[rand()%cfgLeaves]),
+ b3DbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale));
+ }
+ }
+ const int time=(int)wallclock.getTimeMilliseconds();
+ const int up=cfgBenchmark9_Passes*cfgBenchmark9_Iterations;
+ printf("%u ms (%i%%),(%u u/s)\r\n",time,(time-cfgBenchmark9_Reference)*100/time,up*1000/time);
+ }
+ if(cfgBenchmark10_Enable)
+ {// Benchmark 10
+ srand(380843);
+ b3DynamicBvh dbvt;
+ b3AlignedObjectArray<const b3DbvtNode*> leaves;
+ b3AlignedObjectArray<b3Vector3> vectors;
+ vectors.resize(cfgBenchmark10_Iterations);
+ for(int i=0;i<vectors.size();++i)
+ {
+ vectors[i]=(b3DbvtBenchmark::RandVector3()*2-b3Vector3(1,1,1))*cfgBenchmark10_Scale;
+ }
+ b3DbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ dbvt.optimizeTopDown();
+ dbvt.extractLeaves(dbvt.m_root,leaves);
+ printf("[10] updates (jitter): ");
+ wallclock.reset();
+
+ for(int i=0;i<cfgBenchmark10_Passes;++i)
+ {
+ for(int j=0;j<cfgBenchmark10_Iterations;++j)
+ {
+ const b3Vector3& d=vectors[j];
+ b3DbvtNode* l=const_cast<b3DbvtNode*>(leaves[rand()%cfgLeaves]);
+ b3DbvtVolume v=b3DbvtVolume::FromMM(l->volume.Mins()+d,l->volume.Maxs()+d);
+ dbvt.update(l,v);
+ }
+ }
+ const int time=(int)wallclock.getTimeMilliseconds();
+ const int up=cfgBenchmark10_Passes*cfgBenchmark10_Iterations;
+ printf("%u ms (%i%%),(%u u/s)\r\n",time,(time-cfgBenchmark10_Reference)*100/time,up*1000/time);
+ }
+ if(cfgBenchmark11_Enable)
+ {// Benchmark 11
+ srand(380843);
+ b3DynamicBvh dbvt;
+ b3DbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ dbvt.optimizeTopDown();
+ printf("[11] optimize (incremental): ");
+ wallclock.reset();
+ for(int i=0;i<cfgBenchmark11_Passes;++i)
+ {
+ dbvt.optimizeIncremental(cfgBenchmark11_Iterations);
+ }
+ const int time=(int)wallclock.getTimeMilliseconds();
+ const int op=cfgBenchmark11_Passes*cfgBenchmark11_Iterations;
+ printf("%u ms (%i%%),(%u o/s)\r\n",time,(time-cfgBenchmark11_Reference)*100/time,op/time*1000);
+ }
+ if(cfgBenchmark12_Enable)
+ {// Benchmark 12
+ srand(380843);
+ b3AlignedObjectArray<b3DbvtVolume> volumes;
+ b3AlignedObjectArray<bool> results;
+ volumes.resize(cfgLeaves);
+ results.resize(cfgLeaves);
+ for(int i=0;i<cfgLeaves;++i)
+ {
+ volumes[i]=b3DbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale);
+ }
+ printf("[12] b3DbvtVolume notequal: ");
+ wallclock.reset();
+ for(int i=0;i<cfgBenchmark12_Iterations;++i)
+ {
+ for(int j=0;j<cfgLeaves;++j)
+ {
+ for(int k=0;k<cfgLeaves;++k)
+ {
+ results[k]=NotEqual(volumes[j],volumes[k]);
+ }
+ }
+ }
+ const int time=(int)wallclock.getTimeMilliseconds();
+ printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark12_Reference)*100/time);
+ }
+ if(cfgBenchmark13_Enable)
+ {// Benchmark 13
+ srand(380843);
+ b3DynamicBvh dbvt;
+ b3AlignedObjectArray<b3Vector3> vectors;
+ b3DbvtBenchmark::NilPolicy policy;
+ vectors.resize(cfgBenchmark13_Iterations);
+ for(int i=0;i<vectors.size();++i)
+ {
+ vectors[i]=(b3DbvtBenchmark::RandVector3()*2-b3Vector3(1,1,1)).normalized();
+ }
+ b3DbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ dbvt.optimizeTopDown();
+ printf("[13] culling(OCL+fullsort): ");
+ wallclock.reset();
+ for(int i=0;i<cfgBenchmark13_Iterations;++i)
+ {
+ static const b3Scalar offset=0;
+ policy.m_depth=-B3_INFINITY;
+ dbvt.collideOCL(dbvt.m_root,&vectors[i],&offset,vectors[i],1,policy);
+ }
+ const int time=(int)wallclock.getTimeMilliseconds();
+ const int t=cfgBenchmark13_Iterations;
+ printf("%u ms (%i%%),(%u t/s)\r\n",time,(time-cfgBenchmark13_Reference)*100/time,(t*1000)/time);
+ }
+ if(cfgBenchmark14_Enable)
+ {// Benchmark 14
+ srand(380843);
+ b3DynamicBvh dbvt;
+ b3AlignedObjectArray<b3Vector3> vectors;
+ b3DbvtBenchmark::P14 policy;
+ vectors.resize(cfgBenchmark14_Iterations);
+ for(int i=0;i<vectors.size();++i)
+ {
+ vectors[i]=(b3DbvtBenchmark::RandVector3()*2-b3Vector3(1,1,1)).normalized();
+ }
+ b3DbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ dbvt.optimizeTopDown();
+ policy.m_nodes.reserve(cfgLeaves);
+ printf("[14] culling(OCL+qsort): ");
+ wallclock.reset();
+ for(int i=0;i<cfgBenchmark14_Iterations;++i)
+ {
+ static const b3Scalar offset=0;
+ policy.m_nodes.resize(0);
+ dbvt.collideOCL(dbvt.m_root,&vectors[i],&offset,vectors[i],1,policy,false);
+ policy.m_nodes.quickSort(b3DbvtBenchmark::P14::sortfnc);
+ }
+ const int time=(int)wallclock.getTimeMilliseconds();
+ const int t=cfgBenchmark14_Iterations;
+ printf("%u ms (%i%%),(%u t/s)\r\n",time,(time-cfgBenchmark14_Reference)*100/time,(t*1000)/time);
+ }
+ if(cfgBenchmark15_Enable)
+ {// Benchmark 15
+ srand(380843);
+ b3DynamicBvh dbvt;
+ b3AlignedObjectArray<b3Vector3> vectors;
+ b3DbvtBenchmark::P15 policy;
+ vectors.resize(cfgBenchmark15_Iterations);
+ for(int i=0;i<vectors.size();++i)
+ {
+ vectors[i]=(b3DbvtBenchmark::RandVector3()*2-b3Vector3(1,1,1)).normalized();
+ }
+ b3DbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ dbvt.optimizeTopDown();
+ policy.m_nodes.reserve(cfgLeaves);
+ printf("[15] culling(KDOP+qsort): ");
+ wallclock.reset();
+ for(int i=0;i<cfgBenchmark15_Iterations;++i)
+ {
+ static const b3Scalar offset=0;
+ policy.m_nodes.resize(0);
+ policy.m_axis=vectors[i];
+ dbvt.collideKDOP(dbvt.m_root,&vectors[i],&offset,1,policy);
+ policy.m_nodes.quickSort(b3DbvtBenchmark::P15::sortfnc);
+ }
+ const int time=(int)wallclock.getTimeMilliseconds();
+ const int t=cfgBenchmark15_Iterations;
+ printf("%u ms (%i%%),(%u t/s)\r\n",time,(time-cfgBenchmark15_Reference)*100/time,(t*1000)/time);
+ }
+ if(cfgBenchmark16_Enable)
+ {// Benchmark 16
+ srand(380843);
+ b3DynamicBvh dbvt;
+ b3AlignedObjectArray<b3DbvtNode*> batch;
+ b3DbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ dbvt.optimizeTopDown();
+ batch.reserve(cfgBenchmark16_BatchCount);
+ printf("[16] insert/remove batch(%u): ",cfgBenchmark16_BatchCount);
+ wallclock.reset();
+ for(int i=0;i<cfgBenchmark16_Passes;++i)
+ {
+ for(int j=0;j<cfgBenchmark16_BatchCount;++j)
+ {
+ batch.push_back(dbvt.insert(b3DbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale),0));
+ }
+ for(int j=0;j<cfgBenchmark16_BatchCount;++j)
+ {
+ dbvt.remove(batch[j]);
+ }
+ batch.resize(0);
+ }
+ const int time=(int)wallclock.getTimeMilliseconds();
+ const int ir=cfgBenchmark16_Passes*cfgBenchmark16_BatchCount;
+ printf("%u ms (%i%%),(%u bir/s)\r\n",time,(time-cfgBenchmark16_Reference)*100/time,int(ir*1000.0/time));
+ }
+ if(cfgBenchmark17_Enable)
+ {// Benchmark 17
+ srand(380843);
+ b3AlignedObjectArray<b3DbvtVolume> volumes;
+ b3AlignedObjectArray<int> results;
+ b3AlignedObjectArray<int> indices;
+ volumes.resize(cfgLeaves);
+ results.resize(cfgLeaves);
+ indices.resize(cfgLeaves);
+ for(int i=0;i<cfgLeaves;++i)
+ {
+ indices[i]=i;
+ volumes[i]=b3DbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale);
+ }
+ for(int i=0;i<cfgLeaves;++i)
+ {
+ b3Swap(indices[i],indices[rand()%cfgLeaves]);
+ }
+ printf("[17] b3DbvtVolume select: ");
+ wallclock.reset();
+ for(int i=0;i<cfgBenchmark17_Iterations;++i)
+ {
+ for(int j=0;j<cfgLeaves;++j)
+ {
+ for(int k=0;k<cfgLeaves;++k)
+ {
+ const int idx=indices[k];
+ results[idx]=Select(volumes[idx],volumes[j],volumes[k]);
+ }
+ }
+ }
+ const int time=(int)wallclock.getTimeMilliseconds();
+ printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark17_Reference)*100/time);
+ }
+ printf("\r\n\r\n");
+}
+#endif
diff --git a/thirdparty/bullet/src/Bullet3Collision/BroadPhaseCollision/b3DynamicBvh.h b/thirdparty/bullet/src/Bullet3Collision/BroadPhaseCollision/b3DynamicBvh.h
new file mode 100644
index 0000000000..c004b9130f
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Collision/BroadPhaseCollision/b3DynamicBvh.h
@@ -0,0 +1,1269 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2013 Erwin Coumans 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.
+*/
+///b3DynamicBvh implementation by Nathanael Presson
+
+#ifndef B3_DYNAMIC_BOUNDING_VOLUME_TREE_H
+#define B3_DYNAMIC_BOUNDING_VOLUME_TREE_H
+
+#include "Bullet3Common/b3AlignedObjectArray.h"
+#include "Bullet3Common/b3Vector3.h"
+#include "Bullet3Common/b3Transform.h"
+#include "Bullet3Geometry/b3AabbUtil.h"
+
+//
+// Compile time configuration
+//
+
+
+// Implementation profiles
+#define B3_DBVT_IMPL_GENERIC 0 // Generic implementation
+#define B3_DBVT_IMPL_SSE 1 // SSE
+
+// Template implementation of ICollide
+#ifdef _WIN32
+#if (defined (_MSC_VER) && _MSC_VER >= 1400)
+#define B3_DBVT_USE_TEMPLATE 1
+#else
+#define B3_DBVT_USE_TEMPLATE 0
+#endif
+#else
+#define B3_DBVT_USE_TEMPLATE 0
+#endif
+
+// Use only intrinsics instead of inline asm
+#define B3_DBVT_USE_INTRINSIC_SSE 1
+
+// Using memmov for collideOCL
+#define B3_DBVT_USE_MEMMOVE 1
+
+// Enable benchmarking code
+#define B3_DBVT_ENABLE_BENCHMARK 0
+
+// Inlining
+#define B3_DBVT_INLINE B3_FORCE_INLINE
+
+// Specific methods implementation
+
+//SSE gives errors on a MSVC 7.1
+#if defined (B3_USE_SSE) //&& defined (_WIN32)
+#define B3_DBVT_SELECT_IMPL B3_DBVT_IMPL_SSE
+#define B3_DBVT_MERGE_IMPL B3_DBVT_IMPL_SSE
+#define B3_DBVT_INT0_IMPL B3_DBVT_IMPL_SSE
+#else
+#define B3_DBVT_SELECT_IMPL B3_DBVT_IMPL_GENERIC
+#define B3_DBVT_MERGE_IMPL B3_DBVT_IMPL_GENERIC
+#define B3_DBVT_INT0_IMPL B3_DBVT_IMPL_GENERIC
+#endif
+
+#if (B3_DBVT_SELECT_IMPL==B3_DBVT_IMPL_SSE)|| \
+ (B3_DBVT_MERGE_IMPL==B3_DBVT_IMPL_SSE)|| \
+ (B3_DBVT_INT0_IMPL==B3_DBVT_IMPL_SSE)
+#include <emmintrin.h>
+#endif
+
+//
+// Auto config and checks
+//
+
+#if B3_DBVT_USE_TEMPLATE
+#define B3_DBVT_VIRTUAL
+#define B3_DBVT_VIRTUAL_DTOR(a)
+#define B3_DBVT_PREFIX template <typename T>
+#define B3_DBVT_IPOLICY T& policy
+#define B3_DBVT_CHECKTYPE static const ICollide& typechecker=*(T*)1;(void)typechecker;
+#else
+#define B3_DBVT_VIRTUAL_DTOR(a) virtual ~a() {}
+#define B3_DBVT_VIRTUAL virtual
+#define B3_DBVT_PREFIX
+#define B3_DBVT_IPOLICY ICollide& policy
+#define B3_DBVT_CHECKTYPE
+#endif
+
+#if B3_DBVT_USE_MEMMOVE
+#if !defined( __CELLOS_LV2__) && !defined(__MWERKS__)
+#include <memory.h>
+#endif
+#include <string.h>
+#endif
+
+#ifndef B3_DBVT_USE_TEMPLATE
+#error "B3_DBVT_USE_TEMPLATE undefined"
+#endif
+
+#ifndef B3_DBVT_USE_MEMMOVE
+#error "B3_DBVT_USE_MEMMOVE undefined"
+#endif
+
+#ifndef B3_DBVT_ENABLE_BENCHMARK
+#error "B3_DBVT_ENABLE_BENCHMARK undefined"
+#endif
+
+#ifndef B3_DBVT_SELECT_IMPL
+#error "B3_DBVT_SELECT_IMPL undefined"
+#endif
+
+#ifndef B3_DBVT_MERGE_IMPL
+#error "B3_DBVT_MERGE_IMPL undefined"
+#endif
+
+#ifndef B3_DBVT_INT0_IMPL
+#error "B3_DBVT_INT0_IMPL undefined"
+#endif
+
+//
+// Defaults volumes
+//
+
+/* b3DbvtAabbMm */
+struct b3DbvtAabbMm
+{
+ B3_DBVT_INLINE b3Vector3 Center() const { return((mi+mx)/2); }
+ B3_DBVT_INLINE b3Vector3 Lengths() const { return(mx-mi); }
+ B3_DBVT_INLINE b3Vector3 Extents() const { return((mx-mi)/2); }
+ B3_DBVT_INLINE const b3Vector3& Mins() const { return(mi); }
+ B3_DBVT_INLINE const b3Vector3& Maxs() const { return(mx); }
+ static inline b3DbvtAabbMm FromCE(const b3Vector3& c,const b3Vector3& e);
+ static inline b3DbvtAabbMm FromCR(const b3Vector3& c,b3Scalar r);
+ static inline b3DbvtAabbMm FromMM(const b3Vector3& mi,const b3Vector3& mx);
+ static inline b3DbvtAabbMm FromPoints(const b3Vector3* pts,int n);
+ static inline b3DbvtAabbMm FromPoints(const b3Vector3** ppts,int n);
+ B3_DBVT_INLINE void Expand(const b3Vector3& e);
+ B3_DBVT_INLINE void SignedExpand(const b3Vector3& e);
+ B3_DBVT_INLINE bool Contain(const b3DbvtAabbMm& a) const;
+ B3_DBVT_INLINE int Classify(const b3Vector3& n,b3Scalar o,int s) const;
+ B3_DBVT_INLINE b3Scalar ProjectMinimum(const b3Vector3& v,unsigned signs) const;
+ B3_DBVT_INLINE friend bool b3Intersect( const b3DbvtAabbMm& a,
+ const b3DbvtAabbMm& b);
+
+ B3_DBVT_INLINE friend bool b3Intersect( const b3DbvtAabbMm& a,
+ const b3Vector3& b);
+
+ B3_DBVT_INLINE friend b3Scalar b3Proximity( const b3DbvtAabbMm& a,
+ const b3DbvtAabbMm& b);
+ B3_DBVT_INLINE friend int b3Select( const b3DbvtAabbMm& o,
+ const b3DbvtAabbMm& a,
+ const b3DbvtAabbMm& b);
+ B3_DBVT_INLINE friend void b3Merge( const b3DbvtAabbMm& a,
+ const b3DbvtAabbMm& b,
+ b3DbvtAabbMm& r);
+ B3_DBVT_INLINE friend bool b3NotEqual( const b3DbvtAabbMm& a,
+ const b3DbvtAabbMm& b);
+
+ B3_DBVT_INLINE b3Vector3& tMins() { return(mi); }
+ B3_DBVT_INLINE b3Vector3& tMaxs() { return(mx); }
+
+private:
+ B3_DBVT_INLINE void AddSpan(const b3Vector3& d,b3Scalar& smi,b3Scalar& smx) const;
+private:
+ b3Vector3 mi,mx;
+};
+
+// Types
+typedef b3DbvtAabbMm b3DbvtVolume;
+
+/* b3DbvtNode */
+struct b3DbvtNode
+{
+ b3DbvtVolume volume;
+ b3DbvtNode* parent;
+ B3_DBVT_INLINE bool isleaf() const { return(childs[1]==0); }
+ B3_DBVT_INLINE bool isinternal() const { return(!isleaf()); }
+ union
+ {
+ b3DbvtNode* childs[2];
+ void* data;
+ int dataAsInt;
+ };
+};
+
+///The b3DynamicBvh class implements a fast dynamic bounding volume tree based on axis aligned bounding boxes (aabb tree).
+///This b3DynamicBvh is used for soft body collision detection and for the b3DynamicBvhBroadphase. It has a fast insert, remove and update of nodes.
+///Unlike the b3QuantizedBvh, nodes can be dynamically moved around, which allows for change in topology of the underlying data structure.
+struct b3DynamicBvh
+{
+ /* Stack element */
+ struct sStkNN
+ {
+ const b3DbvtNode* a;
+ const b3DbvtNode* b;
+ sStkNN() {}
+ sStkNN(const b3DbvtNode* na,const b3DbvtNode* nb) : a(na),b(nb) {}
+ };
+ struct sStkNP
+ {
+ const b3DbvtNode* node;
+ int mask;
+ sStkNP(const b3DbvtNode* n,unsigned m) : node(n),mask(m) {}
+ };
+ struct sStkNPS
+ {
+ const b3DbvtNode* node;
+ int mask;
+ b3Scalar value;
+ sStkNPS() {}
+ sStkNPS(const b3DbvtNode* n,unsigned m,b3Scalar v) : node(n),mask(m),value(v) {}
+ };
+ struct sStkCLN
+ {
+ const b3DbvtNode* node;
+ b3DbvtNode* parent;
+ sStkCLN(const b3DbvtNode* n,b3DbvtNode* p) : node(n),parent(p) {}
+ };
+ // Policies/Interfaces
+
+ /* ICollide */
+ struct ICollide
+ {
+ B3_DBVT_VIRTUAL_DTOR(ICollide)
+ B3_DBVT_VIRTUAL void Process(const b3DbvtNode*,const b3DbvtNode*) {}
+ B3_DBVT_VIRTUAL void Process(const b3DbvtNode*) {}
+ B3_DBVT_VIRTUAL void Process(const b3DbvtNode* n,b3Scalar) { Process(n); }
+ B3_DBVT_VIRTUAL bool Descent(const b3DbvtNode*) { return(true); }
+ B3_DBVT_VIRTUAL bool AllLeaves(const b3DbvtNode*) { return(true); }
+ };
+ /* IWriter */
+ struct IWriter
+ {
+ virtual ~IWriter() {}
+ virtual void Prepare(const b3DbvtNode* root,int numnodes)=0;
+ virtual void WriteNode(const b3DbvtNode*,int index,int parent,int child0,int child1)=0;
+ virtual void WriteLeaf(const b3DbvtNode*,int index,int parent)=0;
+ };
+ /* IClone */
+ struct IClone
+ {
+ virtual ~IClone() {}
+ virtual void CloneLeaf(b3DbvtNode*) {}
+ };
+
+ // Constants
+ enum {
+ B3_SIMPLE_STACKSIZE = 64,
+ B3_DOUBLE_STACKSIZE = B3_SIMPLE_STACKSIZE*2
+ };
+
+ // Fields
+ b3DbvtNode* m_root;
+ b3DbvtNode* m_free;
+ int m_lkhd;
+ int m_leaves;
+ unsigned m_opath;
+
+
+ b3AlignedObjectArray<sStkNN> m_stkStack;
+ mutable b3AlignedObjectArray<const b3DbvtNode*> m_rayTestStack;
+
+
+ // Methods
+ b3DynamicBvh();
+ ~b3DynamicBvh();
+ void clear();
+ bool empty() const { return(0==m_root); }
+ void optimizeBottomUp();
+ void optimizeTopDown(int bu_treshold=128);
+ void optimizeIncremental(int passes);
+ b3DbvtNode* insert(const b3DbvtVolume& box,void* data);
+ void update(b3DbvtNode* leaf,int lookahead=-1);
+ void update(b3DbvtNode* leaf,b3DbvtVolume& volume);
+ bool update(b3DbvtNode* leaf,b3DbvtVolume& volume,const b3Vector3& velocity,b3Scalar margin);
+ bool update(b3DbvtNode* leaf,b3DbvtVolume& volume,const b3Vector3& velocity);
+ bool update(b3DbvtNode* leaf,b3DbvtVolume& volume,b3Scalar margin);
+ void remove(b3DbvtNode* leaf);
+ void write(IWriter* iwriter) const;
+ void clone(b3DynamicBvh& dest,IClone* iclone=0) const;
+ static int maxdepth(const b3DbvtNode* node);
+ static int countLeaves(const b3DbvtNode* node);
+ static void extractLeaves(const b3DbvtNode* node,b3AlignedObjectArray<const b3DbvtNode*>& leaves);
+#if B3_DBVT_ENABLE_BENCHMARK
+ static void benchmark();
+#else
+ static void benchmark(){}
+#endif
+ // B3_DBVT_IPOLICY must support ICollide policy/interface
+ B3_DBVT_PREFIX
+ static void enumNodes( const b3DbvtNode* root,
+ B3_DBVT_IPOLICY);
+ B3_DBVT_PREFIX
+ static void enumLeaves( const b3DbvtNode* root,
+ B3_DBVT_IPOLICY);
+ B3_DBVT_PREFIX
+ void collideTT( const b3DbvtNode* root0,
+ const b3DbvtNode* root1,
+ B3_DBVT_IPOLICY);
+
+ B3_DBVT_PREFIX
+ void collideTTpersistentStack( const b3DbvtNode* root0,
+ const b3DbvtNode* root1,
+ B3_DBVT_IPOLICY);
+#if 0
+ B3_DBVT_PREFIX
+ void collideTT( const b3DbvtNode* root0,
+ const b3DbvtNode* root1,
+ const b3Transform& xform,
+ B3_DBVT_IPOLICY);
+ B3_DBVT_PREFIX
+ void collideTT( const b3DbvtNode* root0,
+ const b3Transform& xform0,
+ const b3DbvtNode* root1,
+ const b3Transform& xform1,
+ B3_DBVT_IPOLICY);
+#endif
+
+ B3_DBVT_PREFIX
+ void collideTV( const b3DbvtNode* root,
+ const b3DbvtVolume& volume,
+ B3_DBVT_IPOLICY) const;
+ ///rayTest is a re-entrant ray test, and can be called in parallel as long as the b3AlignedAlloc is thread-safe (uses locking etc)
+ ///rayTest is slower than rayTestInternal, because it builds a local stack, using memory allocations, and it recomputes signs/rayDirectionInverses each time
+ B3_DBVT_PREFIX
+ static void rayTest( const b3DbvtNode* root,
+ const b3Vector3& rayFrom,
+ const b3Vector3& rayTo,
+ B3_DBVT_IPOLICY);
+ ///rayTestInternal is faster than rayTest, because it uses a persistent stack (to reduce dynamic memory allocations to a minimum) and it uses precomputed signs/rayInverseDirections
+ ///rayTestInternal is used by b3DynamicBvhBroadphase to accelerate world ray casts
+ B3_DBVT_PREFIX
+ void rayTestInternal( const b3DbvtNode* root,
+ const b3Vector3& rayFrom,
+ const b3Vector3& rayTo,
+ const b3Vector3& rayDirectionInverse,
+ unsigned int signs[3],
+ b3Scalar lambda_max,
+ const b3Vector3& aabbMin,
+ const b3Vector3& aabbMax,
+ B3_DBVT_IPOLICY) const;
+
+ B3_DBVT_PREFIX
+ static void collideKDOP(const b3DbvtNode* root,
+ const b3Vector3* normals,
+ const b3Scalar* offsets,
+ int count,
+ B3_DBVT_IPOLICY);
+ B3_DBVT_PREFIX
+ static void collideOCL( const b3DbvtNode* root,
+ const b3Vector3* normals,
+ const b3Scalar* offsets,
+ const b3Vector3& sortaxis,
+ int count,
+ B3_DBVT_IPOLICY,
+ bool fullsort=true);
+ B3_DBVT_PREFIX
+ static void collideTU( const b3DbvtNode* root,
+ B3_DBVT_IPOLICY);
+ // Helpers
+ static B3_DBVT_INLINE int nearest(const int* i,const b3DynamicBvh::sStkNPS* a,b3Scalar v,int l,int h)
+ {
+ int m=0;
+ while(l<h)
+ {
+ m=(l+h)>>1;
+ if(a[i[m]].value>=v) l=m+1; else h=m;
+ }
+ return(h);
+ }
+ static B3_DBVT_INLINE int allocate( b3AlignedObjectArray<int>& ifree,
+ b3AlignedObjectArray<sStkNPS>& stock,
+ const sStkNPS& value)
+ {
+ int i;
+ if(ifree.size()>0)
+ { i=ifree[ifree.size()-1];ifree.pop_back();stock[i]=value; }
+ else
+ { i=stock.size();stock.push_back(value); }
+ return(i);
+ }
+ //
+private:
+ b3DynamicBvh(const b3DynamicBvh&) {}
+};
+
+//
+// Inline's
+//
+
+//
+inline b3DbvtAabbMm b3DbvtAabbMm::FromCE(const b3Vector3& c,const b3Vector3& e)
+{
+ b3DbvtAabbMm box;
+ box.mi=c-e;box.mx=c+e;
+ return(box);
+}
+
+//
+inline b3DbvtAabbMm b3DbvtAabbMm::FromCR(const b3Vector3& c,b3Scalar r)
+{
+ return(FromCE(c,b3MakeVector3(r,r,r)));
+}
+
+//
+inline b3DbvtAabbMm b3DbvtAabbMm::FromMM(const b3Vector3& mi,const b3Vector3& mx)
+{
+ b3DbvtAabbMm box;
+ box.mi=mi;box.mx=mx;
+ return(box);
+}
+
+//
+inline b3DbvtAabbMm b3DbvtAabbMm::FromPoints(const b3Vector3* pts,int n)
+{
+ b3DbvtAabbMm box;
+ box.mi=box.mx=pts[0];
+ for(int i=1;i<n;++i)
+ {
+ box.mi.setMin(pts[i]);
+ box.mx.setMax(pts[i]);
+ }
+ return(box);
+}
+
+//
+inline b3DbvtAabbMm b3DbvtAabbMm::FromPoints(const b3Vector3** ppts,int n)
+{
+ b3DbvtAabbMm box;
+ box.mi=box.mx=*ppts[0];
+ for(int i=1;i<n;++i)
+ {
+ box.mi.setMin(*ppts[i]);
+ box.mx.setMax(*ppts[i]);
+ }
+ return(box);
+}
+
+//
+B3_DBVT_INLINE void b3DbvtAabbMm::Expand(const b3Vector3& e)
+{
+ mi-=e;mx+=e;
+}
+
+//
+B3_DBVT_INLINE void b3DbvtAabbMm::SignedExpand(const b3Vector3& e)
+{
+ if(e.x>0) mx.setX(mx.x+e[0]); else mi.setX(mi.x+e[0]);
+ if(e.y>0) mx.setY(mx.y+e[1]); else mi.setY(mi.y+e[1]);
+ if(e.z>0) mx.setZ(mx.z+e[2]); else mi.setZ(mi.z+e[2]);
+}
+
+//
+B3_DBVT_INLINE bool b3DbvtAabbMm::Contain(const b3DbvtAabbMm& a) const
+{
+ return( (mi.x<=a.mi.x)&&
+ (mi.y<=a.mi.y)&&
+ (mi.z<=a.mi.z)&&
+ (mx.x>=a.mx.x)&&
+ (mx.y>=a.mx.y)&&
+ (mx.z>=a.mx.z));
+}
+
+//
+B3_DBVT_INLINE int b3DbvtAabbMm::Classify(const b3Vector3& n,b3Scalar o,int s) const
+{
+ b3Vector3 pi,px;
+ switch(s)
+ {
+ case (0+0+0): px=b3MakeVector3(mi.x,mi.y,mi.z);
+ pi=b3MakeVector3(mx.x,mx.y,mx.z);break;
+ case (1+0+0): px=b3MakeVector3(mx.x,mi.y,mi.z);
+ pi=b3MakeVector3(mi.x,mx.y,mx.z);break;
+ case (0+2+0): px=b3MakeVector3(mi.x,mx.y,mi.z);
+ pi=b3MakeVector3(mx.x,mi.y,mx.z);break;
+ case (1+2+0): px=b3MakeVector3(mx.x,mx.y,mi.z);
+ pi=b3MakeVector3(mi.x,mi.y,mx.z);break;
+ case (0+0+4): px=b3MakeVector3(mi.x,mi.y,mx.z);
+ pi=b3MakeVector3(mx.x,mx.y,mi.z);break;
+ case (1+0+4): px=b3MakeVector3(mx.x,mi.y,mx.z);
+ pi=b3MakeVector3(mi.x,mx.y,mi.z);break;
+ case (0+2+4): px=b3MakeVector3(mi.x,mx.y,mx.z);
+ pi=b3MakeVector3(mx.x,mi.y,mi.z);break;
+ case (1+2+4): px=b3MakeVector3(mx.x,mx.y,mx.z);
+ pi=b3MakeVector3(mi.x,mi.y,mi.z);break;
+ }
+ if((b3Dot(n,px)+o)<0) return(-1);
+ if((b3Dot(n,pi)+o)>=0) return(+1);
+ return(0);
+}
+
+//
+B3_DBVT_INLINE b3Scalar b3DbvtAabbMm::ProjectMinimum(const b3Vector3& v,unsigned signs) const
+{
+ const b3Vector3* b[]={&mx,&mi};
+ const b3Vector3 p = b3MakeVector3( b[(signs>>0)&1]->x,
+ b[(signs>>1)&1]->y,
+ b[(signs>>2)&1]->z);
+ return(b3Dot(p,v));
+}
+
+//
+B3_DBVT_INLINE void b3DbvtAabbMm::AddSpan(const b3Vector3& d,b3Scalar& smi,b3Scalar& smx) const
+{
+ for(int i=0;i<3;++i)
+ {
+ if(d[i]<0)
+ { smi+=mx[i]*d[i];smx+=mi[i]*d[i]; }
+ else
+ { smi+=mi[i]*d[i];smx+=mx[i]*d[i]; }
+ }
+}
+
+//
+B3_DBVT_INLINE bool b3Intersect( const b3DbvtAabbMm& a,
+ const b3DbvtAabbMm& b)
+{
+#if B3_DBVT_INT0_IMPL == B3_DBVT_IMPL_SSE
+ const __m128 rt(_mm_or_ps( _mm_cmplt_ps(_mm_load_ps(b.mx),_mm_load_ps(a.mi)),
+ _mm_cmplt_ps(_mm_load_ps(a.mx),_mm_load_ps(b.mi))));
+#if defined (_WIN32)
+ const __int32* pu((const __int32*)&rt);
+#else
+ const int* pu((const int*)&rt);
+#endif
+ return((pu[0]|pu[1]|pu[2])==0);
+#else
+ return( (a.mi.x<=b.mx.x)&&
+ (a.mx.x>=b.mi.x)&&
+ (a.mi.y<=b.mx.y)&&
+ (a.mx.y>=b.mi.y)&&
+ (a.mi.z<=b.mx.z)&&
+ (a.mx.z>=b.mi.z));
+#endif
+}
+
+
+
+//
+B3_DBVT_INLINE bool b3Intersect( const b3DbvtAabbMm& a,
+ const b3Vector3& b)
+{
+ return( (b.x>=a.mi.x)&&
+ (b.y>=a.mi.y)&&
+ (b.z>=a.mi.z)&&
+ (b.x<=a.mx.x)&&
+ (b.y<=a.mx.y)&&
+ (b.z<=a.mx.z));
+}
+
+
+
+
+
+//////////////////////////////////////
+
+
+//
+B3_DBVT_INLINE b3Scalar b3Proximity( const b3DbvtAabbMm& a,
+ const b3DbvtAabbMm& b)
+{
+ const b3Vector3 d=(a.mi+a.mx)-(b.mi+b.mx);
+ return(b3Fabs(d.x)+b3Fabs(d.y)+b3Fabs(d.z));
+}
+
+
+
+//
+B3_DBVT_INLINE int b3Select( const b3DbvtAabbMm& o,
+ const b3DbvtAabbMm& a,
+ const b3DbvtAabbMm& b)
+{
+#if B3_DBVT_SELECT_IMPL == B3_DBVT_IMPL_SSE
+
+#if defined (_WIN32)
+ static B3_ATTRIBUTE_ALIGNED16(const unsigned __int32) mask[]={0x7fffffff,0x7fffffff,0x7fffffff,0x7fffffff};
+#else
+ static B3_ATTRIBUTE_ALIGNED16(const unsigned int) mask[]={0x7fffffff,0x7fffffff,0x7fffffff,0x00000000 /*0x7fffffff*/};
+#endif
+ ///@todo: the intrinsic version is 11% slower
+#if B3_DBVT_USE_INTRINSIC_SSE
+
+ union b3SSEUnion ///NOTE: if we use more intrinsics, move b3SSEUnion into the LinearMath directory
+ {
+ __m128 ssereg;
+ float floats[4];
+ int ints[4];
+ };
+
+ __m128 omi(_mm_load_ps(o.mi));
+ omi=_mm_add_ps(omi,_mm_load_ps(o.mx));
+ __m128 ami(_mm_load_ps(a.mi));
+ ami=_mm_add_ps(ami,_mm_load_ps(a.mx));
+ ami=_mm_sub_ps(ami,omi);
+ ami=_mm_and_ps(ami,_mm_load_ps((const float*)mask));
+ __m128 bmi(_mm_load_ps(b.mi));
+ bmi=_mm_add_ps(bmi,_mm_load_ps(b.mx));
+ bmi=_mm_sub_ps(bmi,omi);
+ bmi=_mm_and_ps(bmi,_mm_load_ps((const float*)mask));
+ __m128 t0(_mm_movehl_ps(ami,ami));
+ ami=_mm_add_ps(ami,t0);
+ ami=_mm_add_ss(ami,_mm_shuffle_ps(ami,ami,1));
+ __m128 t1(_mm_movehl_ps(bmi,bmi));
+ bmi=_mm_add_ps(bmi,t1);
+ bmi=_mm_add_ss(bmi,_mm_shuffle_ps(bmi,bmi,1));
+
+ b3SSEUnion tmp;
+ tmp.ssereg = _mm_cmple_ss(bmi,ami);
+ return tmp.ints[0]&1;
+
+#else
+ B3_ATTRIBUTE_ALIGNED16(__int32 r[1]);
+ __asm
+ {
+ mov eax,o
+ mov ecx,a
+ mov edx,b
+ movaps xmm0,[eax]
+ movaps xmm5,mask
+ addps xmm0,[eax+16]
+ movaps xmm1,[ecx]
+ movaps xmm2,[edx]
+ addps xmm1,[ecx+16]
+ addps xmm2,[edx+16]
+ subps xmm1,xmm0
+ subps xmm2,xmm0
+ andps xmm1,xmm5
+ andps xmm2,xmm5
+ movhlps xmm3,xmm1
+ movhlps xmm4,xmm2
+ addps xmm1,xmm3
+ addps xmm2,xmm4
+ pshufd xmm3,xmm1,1
+ pshufd xmm4,xmm2,1
+ addss xmm1,xmm3
+ addss xmm2,xmm4
+ cmpless xmm2,xmm1
+ movss r,xmm2
+ }
+ return(r[0]&1);
+#endif
+#else
+ return(b3Proximity(o,a)<b3Proximity(o,b)?0:1);
+#endif
+}
+
+//
+B3_DBVT_INLINE void b3Merge( const b3DbvtAabbMm& a,
+ const b3DbvtAabbMm& b,
+ b3DbvtAabbMm& r)
+{
+#if B3_DBVT_MERGE_IMPL==B3_DBVT_IMPL_SSE
+ __m128 ami(_mm_load_ps(a.mi));
+ __m128 amx(_mm_load_ps(a.mx));
+ __m128 bmi(_mm_load_ps(b.mi));
+ __m128 bmx(_mm_load_ps(b.mx));
+ ami=_mm_min_ps(ami,bmi);
+ amx=_mm_max_ps(amx,bmx);
+ _mm_store_ps(r.mi,ami);
+ _mm_store_ps(r.mx,amx);
+#else
+ for(int i=0;i<3;++i)
+ {
+ if(a.mi[i]<b.mi[i]) r.mi[i]=a.mi[i]; else r.mi[i]=b.mi[i];
+ if(a.mx[i]>b.mx[i]) r.mx[i]=a.mx[i]; else r.mx[i]=b.mx[i];
+ }
+#endif
+}
+
+//
+B3_DBVT_INLINE bool b3NotEqual( const b3DbvtAabbMm& a,
+ const b3DbvtAabbMm& b)
+{
+ return( (a.mi.x!=b.mi.x)||
+ (a.mi.y!=b.mi.y)||
+ (a.mi.z!=b.mi.z)||
+ (a.mx.x!=b.mx.x)||
+ (a.mx.y!=b.mx.y)||
+ (a.mx.z!=b.mx.z));
+}
+
+//
+// Inline's
+//
+
+//
+B3_DBVT_PREFIX
+inline void b3DynamicBvh::enumNodes( const b3DbvtNode* root,
+ B3_DBVT_IPOLICY)
+{
+ B3_DBVT_CHECKTYPE
+ policy.Process(root);
+ if(root->isinternal())
+ {
+ enumNodes(root->childs[0],policy);
+ enumNodes(root->childs[1],policy);
+ }
+}
+
+//
+B3_DBVT_PREFIX
+inline void b3DynamicBvh::enumLeaves( const b3DbvtNode* root,
+ B3_DBVT_IPOLICY)
+{
+ B3_DBVT_CHECKTYPE
+ if(root->isinternal())
+ {
+ enumLeaves(root->childs[0],policy);
+ enumLeaves(root->childs[1],policy);
+ }
+ else
+ {
+ policy.Process(root);
+ }
+}
+
+//
+B3_DBVT_PREFIX
+inline void b3DynamicBvh::collideTT( const b3DbvtNode* root0,
+ const b3DbvtNode* root1,
+ B3_DBVT_IPOLICY)
+{
+ B3_DBVT_CHECKTYPE
+ if(root0&&root1)
+ {
+ int depth=1;
+ int treshold=B3_DOUBLE_STACKSIZE-4;
+ b3AlignedObjectArray<sStkNN> stkStack;
+ stkStack.resize(B3_DOUBLE_STACKSIZE);
+ stkStack[0]=sStkNN(root0,root1);
+ 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(b3Intersect(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);
+ }
+}
+
+
+
+B3_DBVT_PREFIX
+inline void b3DynamicBvh::collideTTpersistentStack( const b3DbvtNode* root0,
+ const b3DbvtNode* root1,
+ B3_DBVT_IPOLICY)
+{
+ B3_DBVT_CHECKTYPE
+ if(root0&&root1)
+ {
+ int depth=1;
+ int treshold=B3_DOUBLE_STACKSIZE-4;
+
+ m_stkStack.resize(B3_DOUBLE_STACKSIZE);
+ m_stkStack[0]=sStkNN(root0,root1);
+ do {
+ sStkNN p=m_stkStack[--depth];
+ if(depth>treshold)
+ {
+ m_stkStack.resize(m_stkStack.size()*2);
+ treshold=m_stkStack.size()-4;
+ }
+ if(p.a==p.b)
+ {
+ if(p.a->isinternal())
+ {
+ m_stkStack[depth++]=sStkNN(p.a->childs[0],p.a->childs[0]);
+ m_stkStack[depth++]=sStkNN(p.a->childs[1],p.a->childs[1]);
+ m_stkStack[depth++]=sStkNN(p.a->childs[0],p.a->childs[1]);
+ }
+ }
+ else if(b3Intersect(p.a->volume,p.b->volume))
+ {
+ if(p.a->isinternal())
+ {
+ if(p.b->isinternal())
+ {
+ m_stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[0]);
+ m_stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[0]);
+ m_stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[1]);
+ m_stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[1]);
+ }
+ else
+ {
+ m_stkStack[depth++]=sStkNN(p.a->childs[0],p.b);
+ m_stkStack[depth++]=sStkNN(p.a->childs[1],p.b);
+ }
+ }
+ else
+ {
+ if(p.b->isinternal())
+ {
+ m_stkStack[depth++]=sStkNN(p.a,p.b->childs[0]);
+ m_stkStack[depth++]=sStkNN(p.a,p.b->childs[1]);
+ }
+ else
+ {
+ policy.Process(p.a,p.b);
+ }
+ }
+ }
+ } while(depth);
+ }
+}
+
+#if 0
+//
+B3_DBVT_PREFIX
+inline void b3DynamicBvh::collideTT( const b3DbvtNode* root0,
+ const b3DbvtNode* root1,
+ const b3Transform& xform,
+ B3_DBVT_IPOLICY)
+{
+ B3_DBVT_CHECKTYPE
+ if(root0&&root1)
+ {
+ int depth=1;
+ int treshold=B3_DOUBLE_STACKSIZE-4;
+ b3AlignedObjectArray<sStkNN> stkStack;
+ stkStack.resize(B3_DOUBLE_STACKSIZE);
+ stkStack[0]=sStkNN(root0,root1);
+ do {
+ sStkNN p=stkStack[--depth];
+ if(b3Intersect(p.a->volume,p.b->volume,xform))
+ {
+ if(depth>treshold)
+ {
+ stkStack.resize(stkStack.size()*2);
+ treshold=stkStack.size()-4;
+ }
+ 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);
+ }
+}
+//
+B3_DBVT_PREFIX
+inline void b3DynamicBvh::collideTT( const b3DbvtNode* root0,
+ const b3Transform& xform0,
+ const b3DbvtNode* root1,
+ const b3Transform& xform1,
+ B3_DBVT_IPOLICY)
+{
+ const b3Transform xform=xform0.inverse()*xform1;
+ collideTT(root0,root1,xform,policy);
+}
+#endif
+
+//
+B3_DBVT_PREFIX
+inline void b3DynamicBvh::collideTV( const b3DbvtNode* root,
+ const b3DbvtVolume& vol,
+ B3_DBVT_IPOLICY) const
+{
+ B3_DBVT_CHECKTYPE
+ if(root)
+ {
+ B3_ATTRIBUTE_ALIGNED16(b3DbvtVolume) volume(vol);
+ b3AlignedObjectArray<const b3DbvtNode*> stack;
+ stack.resize(0);
+ stack.reserve(B3_SIMPLE_STACKSIZE);
+ stack.push_back(root);
+ do {
+ const b3DbvtNode* n=stack[stack.size()-1];
+ stack.pop_back();
+ if(b3Intersect(n->volume,volume))
+ {
+ if(n->isinternal())
+ {
+ stack.push_back(n->childs[0]);
+ stack.push_back(n->childs[1]);
+ }
+ else
+ {
+ policy.Process(n);
+ }
+ }
+ } while(stack.size()>0);
+ }
+}
+
+B3_DBVT_PREFIX
+inline void b3DynamicBvh::rayTestInternal( const b3DbvtNode* root,
+ const b3Vector3& rayFrom,
+ const b3Vector3& rayTo,
+ const b3Vector3& rayDirectionInverse,
+ unsigned int signs[3],
+ b3Scalar lambda_max,
+ const b3Vector3& aabbMin,
+ const b3Vector3& aabbMax,
+ B3_DBVT_IPOLICY) const
+{
+ (void) rayTo;
+ B3_DBVT_CHECKTYPE
+ if(root)
+ {
+ int depth=1;
+ int treshold=B3_DOUBLE_STACKSIZE-2;
+ b3AlignedObjectArray<const b3DbvtNode*>& stack = m_rayTestStack;
+ stack.resize(B3_DOUBLE_STACKSIZE);
+ stack[0]=root;
+ b3Vector3 bounds[2];
+ do
+ {
+ const b3DbvtNode* node=stack[--depth];
+ bounds[0] = node->volume.Mins()-aabbMax;
+ bounds[1] = node->volume.Maxs()-aabbMin;
+ b3Scalar tmin=1.f,lambda_min=0.f;
+ unsigned int result1=false;
+ result1 = b3RayAabb2(rayFrom,rayDirectionInverse,signs,bounds,tmin,lambda_min,lambda_max);
+ if(result1)
+ {
+ if(node->isinternal())
+ {
+ if(depth>treshold)
+ {
+ stack.resize(stack.size()*2);
+ treshold=stack.size()-2;
+ }
+ stack[depth++]=node->childs[0];
+ stack[depth++]=node->childs[1];
+ }
+ else
+ {
+ policy.Process(node);
+ }
+ }
+ } while(depth);
+ }
+}
+
+//
+B3_DBVT_PREFIX
+inline void b3DynamicBvh::rayTest( const b3DbvtNode* root,
+ const b3Vector3& rayFrom,
+ const b3Vector3& rayTo,
+ B3_DBVT_IPOLICY)
+{
+ B3_DBVT_CHECKTYPE
+ if(root)
+ {
+ b3Vector3 rayDir = (rayTo-rayFrom);
+ rayDir.normalize ();
+
+ ///what about division by zero? --> just set rayDirection[i] to INF/B3_LARGE_FLOAT
+ b3Vector3 rayDirectionInverse;
+ rayDirectionInverse[0] = rayDir[0] == b3Scalar(0.0) ? b3Scalar(B3_LARGE_FLOAT) : b3Scalar(1.0) / rayDir[0];
+ rayDirectionInverse[1] = rayDir[1] == b3Scalar(0.0) ? b3Scalar(B3_LARGE_FLOAT) : b3Scalar(1.0) / rayDir[1];
+ rayDirectionInverse[2] = rayDir[2] == b3Scalar(0.0) ? b3Scalar(B3_LARGE_FLOAT) : b3Scalar(1.0) / rayDir[2];
+ unsigned int signs[3] = { rayDirectionInverse[0] < 0.0, rayDirectionInverse[1] < 0.0, rayDirectionInverse[2] < 0.0};
+
+ b3Scalar lambda_max = rayDir.dot(rayTo-rayFrom);
+#ifdef COMPARE_BTRAY_AABB2
+ b3Vector3 resultNormal;
+#endif//COMPARE_BTRAY_AABB2
+
+ b3AlignedObjectArray<const b3DbvtNode*> stack;
+
+ int depth=1;
+ int treshold=B3_DOUBLE_STACKSIZE-2;
+
+ stack.resize(B3_DOUBLE_STACKSIZE);
+ stack[0]=root;
+ b3Vector3 bounds[2];
+ do {
+ const b3DbvtNode* node=stack[--depth];
+
+ bounds[0] = node->volume.Mins();
+ bounds[1] = node->volume.Maxs();
+
+ b3Scalar tmin=1.f,lambda_min=0.f;
+ unsigned int result1 = b3RayAabb2(rayFrom,rayDirectionInverse,signs,bounds,tmin,lambda_min,lambda_max);
+
+#ifdef COMPARE_BTRAY_AABB2
+ b3Scalar param=1.f;
+ bool result2 = b3RayAabb(rayFrom,rayTo,node->volume.Mins(),node->volume.Maxs(),param,resultNormal);
+ b3Assert(result1 == result2);
+#endif //TEST_BTRAY_AABB2
+
+ if(result1)
+ {
+ if(node->isinternal())
+ {
+ if(depth>treshold)
+ {
+ stack.resize(stack.size()*2);
+ treshold=stack.size()-2;
+ }
+ stack[depth++]=node->childs[0];
+ stack[depth++]=node->childs[1];
+ }
+ else
+ {
+ policy.Process(node);
+ }
+ }
+ } while(depth);
+
+ }
+}
+
+//
+B3_DBVT_PREFIX
+inline void b3DynamicBvh::collideKDOP(const b3DbvtNode* root,
+ const b3Vector3* normals,
+ const b3Scalar* offsets,
+ int count,
+ B3_DBVT_IPOLICY)
+{
+ B3_DBVT_CHECKTYPE
+ if(root)
+ {
+ const int inside=(1<<count)-1;
+ b3AlignedObjectArray<sStkNP> stack;
+ int signs[sizeof(unsigned)*8];
+ b3Assert(count<int (sizeof(signs)/sizeof(signs[0])));
+ for(int i=0;i<count;++i)
+ {
+ signs[i]= ((normals[i].x>=0)?1:0)+
+ ((normals[i].y>=0)?2:0)+
+ ((normals[i].z>=0)?4:0);
+ }
+ stack.reserve(B3_SIMPLE_STACKSIZE);
+ stack.push_back(sStkNP(root,0));
+ do {
+ sStkNP se=stack[stack.size()-1];
+ bool out=false;
+ stack.pop_back();
+ for(int i=0,j=1;(!out)&&(i<count);++i,j<<=1)
+ {
+ if(0==(se.mask&j))
+ {
+ const int side=se.node->volume.Classify(normals[i],offsets[i],signs[i]);
+ switch(side)
+ {
+ case -1: out=true;break;
+ case +1: se.mask|=j;break;
+ }
+ }
+ }
+ if(!out)
+ {
+ if((se.mask!=inside)&&(se.node->isinternal()))
+ {
+ stack.push_back(sStkNP(se.node->childs[0],se.mask));
+ stack.push_back(sStkNP(se.node->childs[1],se.mask));
+ }
+ else
+ {
+ if(policy.AllLeaves(se.node)) enumLeaves(se.node,policy);
+ }
+ }
+ } while(stack.size());
+ }
+}
+
+//
+B3_DBVT_PREFIX
+inline void b3DynamicBvh::collideOCL( const b3DbvtNode* root,
+ const b3Vector3* normals,
+ const b3Scalar* offsets,
+ const b3Vector3& sortaxis,
+ int count,
+ B3_DBVT_IPOLICY,
+ bool fsort)
+{
+ B3_DBVT_CHECKTYPE
+ if(root)
+ {
+ const unsigned srtsgns=(sortaxis[0]>=0?1:0)+
+ (sortaxis[1]>=0?2:0)+
+ (sortaxis[2]>=0?4:0);
+ const int inside=(1<<count)-1;
+ b3AlignedObjectArray<sStkNPS> stock;
+ b3AlignedObjectArray<int> ifree;
+ b3AlignedObjectArray<int> stack;
+ int signs[sizeof(unsigned)*8];
+ b3Assert(count<int (sizeof(signs)/sizeof(signs[0])));
+ for(int i=0;i<count;++i)
+ {
+ signs[i]= ((normals[i].x>=0)?1:0)+
+ ((normals[i].y>=0)?2:0)+
+ ((normals[i].z>=0)?4:0);
+ }
+ stock.reserve(B3_SIMPLE_STACKSIZE);
+ stack.reserve(B3_SIMPLE_STACKSIZE);
+ ifree.reserve(B3_SIMPLE_STACKSIZE);
+ stack.push_back(allocate(ifree,stock,sStkNPS(root,0,root->volume.ProjectMinimum(sortaxis,srtsgns))));
+ do {
+ const int id=stack[stack.size()-1];
+ sStkNPS se=stock[id];
+ stack.pop_back();ifree.push_back(id);
+ if(se.mask!=inside)
+ {
+ bool out=false;
+ for(int i=0,j=1;(!out)&&(i<count);++i,j<<=1)
+ {
+ if(0==(se.mask&j))
+ {
+ const int side=se.node->volume.Classify(normals[i],offsets[i],signs[i]);
+ switch(side)
+ {
+ case -1: out=true;break;
+ case +1: se.mask|=j;break;
+ }
+ }
+ }
+ if(out) continue;
+ }
+ if(policy.Descent(se.node))
+ {
+ if(se.node->isinternal())
+ {
+ const b3DbvtNode* pns[]={ se.node->childs[0],se.node->childs[1]};
+ sStkNPS nes[]={ sStkNPS(pns[0],se.mask,pns[0]->volume.ProjectMinimum(sortaxis,srtsgns)),
+ sStkNPS(pns[1],se.mask,pns[1]->volume.ProjectMinimum(sortaxis,srtsgns))};
+ const int q=nes[0].value<nes[1].value?1:0;
+ int j=stack.size();
+ if(fsort&&(j>0))
+ {
+ /* Insert 0 */
+ j=nearest(&stack[0],&stock[0],nes[q].value,0,stack.size());
+ stack.push_back(0);
+#if B3_DBVT_USE_MEMMOVE
+ memmove(&stack[j+1],&stack[j],sizeof(int)*(stack.size()-j-1));
+#else
+ for(int k=stack.size()-1;k>j;--k) stack[k]=stack[k-1];
+#endif
+ stack[j]=allocate(ifree,stock,nes[q]);
+ /* Insert 1 */
+ j=nearest(&stack[0],&stock[0],nes[1-q].value,j,stack.size());
+ stack.push_back(0);
+#if B3_DBVT_USE_MEMMOVE
+ memmove(&stack[j+1],&stack[j],sizeof(int)*(stack.size()-j-1));
+#else
+ for(int k=stack.size()-1;k>j;--k) stack[k]=stack[k-1];
+#endif
+ stack[j]=allocate(ifree,stock,nes[1-q]);
+ }
+ else
+ {
+ stack.push_back(allocate(ifree,stock,nes[q]));
+ stack.push_back(allocate(ifree,stock,nes[1-q]));
+ }
+ }
+ else
+ {
+ policy.Process(se.node,se.value);
+ }
+ }
+ } while(stack.size());
+ }
+}
+
+//
+B3_DBVT_PREFIX
+inline void b3DynamicBvh::collideTU( const b3DbvtNode* root,
+ B3_DBVT_IPOLICY)
+{
+ B3_DBVT_CHECKTYPE
+ if(root)
+ {
+ b3AlignedObjectArray<const b3DbvtNode*> stack;
+ stack.reserve(B3_SIMPLE_STACKSIZE);
+ stack.push_back(root);
+ do {
+ const b3DbvtNode* n=stack[stack.size()-1];
+ stack.pop_back();
+ if(policy.Descent(n))
+ {
+ if(n->isinternal())
+ { stack.push_back(n->childs[0]);stack.push_back(n->childs[1]); }
+ else
+ { policy.Process(n); }
+ }
+ } while(stack.size()>0);
+ }
+}
+
+//
+// PP Cleanup
+//
+
+#undef B3_DBVT_USE_MEMMOVE
+#undef B3_DBVT_USE_TEMPLATE
+#undef B3_DBVT_VIRTUAL_DTOR
+#undef B3_DBVT_VIRTUAL
+#undef B3_DBVT_PREFIX
+#undef B3_DBVT_IPOLICY
+#undef B3_DBVT_CHECKTYPE
+#undef B3_DBVT_IMPL_GENERIC
+#undef B3_DBVT_IMPL_SSE
+#undef B3_DBVT_USE_INTRINSIC_SSE
+#undef B3_DBVT_SELECT_IMPL
+#undef B3_DBVT_MERGE_IMPL
+#undef B3_DBVT_INT0_IMPL
+
+#endif
diff --git a/thirdparty/bullet/src/Bullet3Collision/BroadPhaseCollision/b3DynamicBvhBroadphase.cpp b/thirdparty/bullet/src/Bullet3Collision/BroadPhaseCollision/b3DynamicBvhBroadphase.cpp
new file mode 100644
index 0000000000..bc150955b8
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Collision/BroadPhaseCollision/b3DynamicBvhBroadphase.cpp
@@ -0,0 +1,804 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2013 Erwin Coumans 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.
+*/
+
+///b3DynamicBvhBroadphase implementation by Nathanael Presson
+
+#include "b3DynamicBvhBroadphase.h"
+#include "b3OverlappingPair.h"
+
+//
+// Profiling
+//
+
+#if B3_DBVT_BP_PROFILE||B3_DBVT_BP_ENABLE_BENCHMARK
+#include <stdio.h>
+#endif
+
+#if B3_DBVT_BP_PROFILE
+struct b3ProfileScope
+{
+ __forceinline b3ProfileScope(b3Clock& clock,unsigned long& value) :
+ m_clock(&clock),m_value(&value),m_base(clock.getTimeMicroseconds())
+ {
+ }
+ __forceinline ~b3ProfileScope()
+ {
+ (*m_value)+=m_clock->getTimeMicroseconds()-m_base;
+ }
+ b3Clock* m_clock;
+ unsigned long* m_value;
+ unsigned long m_base;
+};
+#define b3SPC(_value_) b3ProfileScope spc_scope(m_clock,_value_)
+#else
+#define b3SPC(_value_)
+#endif
+
+//
+// Helpers
+//
+
+//
+template <typename T>
+static inline void b3ListAppend(T* item,T*& list)
+{
+ item->links[0]=0;
+ item->links[1]=list;
+ if(list) list->links[0]=item;
+ list=item;
+}
+
+//
+template <typename T>
+static inline void b3ListRemove(T* item,T*& list)
+{
+ if(item->links[0]) item->links[0]->links[1]=item->links[1]; else list=item->links[1];
+ if(item->links[1]) item->links[1]->links[0]=item->links[0];
+}
+
+//
+template <typename T>
+static inline int b3ListCount(T* root)
+{
+ int n=0;
+ while(root) { ++n;root=root->links[1]; }
+ return(n);
+}
+
+//
+template <typename T>
+static inline void b3Clear(T& value)
+{
+ static const struct ZeroDummy : T {} zerodummy;
+ value=zerodummy;
+}
+
+//
+// Colliders
+//
+
+/* Tree collider */
+struct b3DbvtTreeCollider : b3DynamicBvh::ICollide
+{
+ b3DynamicBvhBroadphase* pbp;
+ b3DbvtProxy* proxy;
+ b3DbvtTreeCollider(b3DynamicBvhBroadphase* p) : pbp(p) {}
+ void Process(const b3DbvtNode* na,const b3DbvtNode* nb)
+ {
+ if(na!=nb)
+ {
+ b3DbvtProxy* pa=(b3DbvtProxy*)na->data;
+ b3DbvtProxy* pb=(b3DbvtProxy*)nb->data;
+#if B3_DBVT_BP_SORTPAIRS
+ if(pa->m_uniqueId>pb->m_uniqueId)
+ b3Swap(pa,pb);
+#endif
+ pbp->m_paircache->addOverlappingPair(pa->getUid(),pb->getUid());
+ ++pbp->m_newpairs;
+ }
+ }
+ void Process(const b3DbvtNode* n)
+ {
+ Process(n,proxy->leaf);
+ }
+};
+
+//
+// b3DynamicBvhBroadphase
+//
+
+//
+b3DynamicBvhBroadphase::b3DynamicBvhBroadphase(int proxyCapacity, b3OverlappingPairCache* paircache)
+{
+ m_deferedcollide = false;
+ m_needcleanup = true;
+ m_releasepaircache = (paircache!=0)?false:true;
+ m_prediction = 0;
+ m_stageCurrent = 0;
+ m_fixedleft = 0;
+ m_fupdates = 1;
+ m_dupdates = 0;
+ m_cupdates = 10;
+ m_newpairs = 1;
+ m_updates_call = 0;
+ m_updates_done = 0;
+ m_updates_ratio = 0;
+ m_paircache = paircache? paircache : new(b3AlignedAlloc(sizeof(b3HashedOverlappingPairCache),16)) b3HashedOverlappingPairCache();
+
+ m_pid = 0;
+ m_cid = 0;
+ for(int i=0;i<=STAGECOUNT;++i)
+ {
+ m_stageRoots[i]=0;
+ }
+#if B3_DBVT_BP_PROFILE
+ b3Clear(m_profiling);
+#endif
+ m_proxies.resize(proxyCapacity);
+}
+
+//
+b3DynamicBvhBroadphase::~b3DynamicBvhBroadphase()
+{
+ if(m_releasepaircache)
+ {
+ m_paircache->~b3OverlappingPairCache();
+ b3AlignedFree(m_paircache);
+ }
+}
+
+//
+b3BroadphaseProxy* b3DynamicBvhBroadphase::createProxy( const b3Vector3& aabbMin,
+ const b3Vector3& aabbMax,
+ int objectId,
+ void* userPtr,
+ int collisionFilterGroup,
+ int collisionFilterMask)
+{
+ b3DbvtProxy* mem = &m_proxies[objectId];
+ b3DbvtProxy* proxy=new(mem) b3DbvtProxy( aabbMin,aabbMax,userPtr,
+ collisionFilterGroup,
+ collisionFilterMask);
+
+ b3DbvtAabbMm aabb = b3DbvtVolume::FromMM(aabbMin,aabbMax);
+
+ //bproxy->aabb = b3DbvtVolume::FromMM(aabbMin,aabbMax);
+ proxy->stage = m_stageCurrent;
+ proxy->m_uniqueId = objectId;
+ proxy->leaf = m_sets[0].insert(aabb,proxy);
+ b3ListAppend(proxy,m_stageRoots[m_stageCurrent]);
+ if(!m_deferedcollide)
+ {
+ b3DbvtTreeCollider collider(this);
+ collider.proxy=proxy;
+ m_sets[0].collideTV(m_sets[0].m_root,aabb,collider);
+ m_sets[1].collideTV(m_sets[1].m_root,aabb,collider);
+ }
+ return(proxy);
+}
+
+//
+void b3DynamicBvhBroadphase::destroyProxy( b3BroadphaseProxy* absproxy,
+ b3Dispatcher* dispatcher)
+{
+ b3DbvtProxy* proxy=(b3DbvtProxy*)absproxy;
+ if(proxy->stage==STAGECOUNT)
+ m_sets[1].remove(proxy->leaf);
+ else
+ m_sets[0].remove(proxy->leaf);
+ b3ListRemove(proxy,m_stageRoots[proxy->stage]);
+ m_paircache->removeOverlappingPairsContainingProxy(proxy->getUid(),dispatcher);
+
+ m_needcleanup=true;
+}
+
+void b3DynamicBvhBroadphase::getAabb(int objectId,b3Vector3& aabbMin, b3Vector3& aabbMax ) const
+{
+ const b3DbvtProxy* proxy=&m_proxies[objectId];
+ aabbMin = proxy->m_aabbMin;
+ aabbMax = proxy->m_aabbMax;
+}
+/*
+void b3DynamicBvhBroadphase::getAabb(b3BroadphaseProxy* absproxy,b3Vector3& aabbMin, b3Vector3& aabbMax ) const
+{
+ b3DbvtProxy* proxy=(b3DbvtProxy*)absproxy;
+ aabbMin = proxy->m_aabbMin;
+ aabbMax = proxy->m_aabbMax;
+}
+*/
+
+
+struct BroadphaseRayTester : b3DynamicBvh::ICollide
+{
+ b3BroadphaseRayCallback& m_rayCallback;
+ BroadphaseRayTester(b3BroadphaseRayCallback& orgCallback)
+ :m_rayCallback(orgCallback)
+ {
+ }
+ void Process(const b3DbvtNode* leaf)
+ {
+ b3DbvtProxy* proxy=(b3DbvtProxy*)leaf->data;
+ m_rayCallback.process(proxy);
+ }
+};
+
+void b3DynamicBvhBroadphase::rayTest(const b3Vector3& rayFrom,const b3Vector3& rayTo, b3BroadphaseRayCallback& rayCallback,const b3Vector3& aabbMin,const b3Vector3& aabbMax)
+{
+ BroadphaseRayTester callback(rayCallback);
+
+ m_sets[0].rayTestInternal( m_sets[0].m_root,
+ rayFrom,
+ rayTo,
+ rayCallback.m_rayDirectionInverse,
+ rayCallback.m_signs,
+ rayCallback.m_lambda_max,
+ aabbMin,
+ aabbMax,
+ callback);
+
+ m_sets[1].rayTestInternal( m_sets[1].m_root,
+ rayFrom,
+ rayTo,
+ rayCallback.m_rayDirectionInverse,
+ rayCallback.m_signs,
+ rayCallback.m_lambda_max,
+ aabbMin,
+ aabbMax,
+ callback);
+
+}
+
+
+struct BroadphaseAabbTester : b3DynamicBvh::ICollide
+{
+ b3BroadphaseAabbCallback& m_aabbCallback;
+ BroadphaseAabbTester(b3BroadphaseAabbCallback& orgCallback)
+ :m_aabbCallback(orgCallback)
+ {
+ }
+ void Process(const b3DbvtNode* leaf)
+ {
+ b3DbvtProxy* proxy=(b3DbvtProxy*)leaf->data;
+ m_aabbCallback.process(proxy);
+ }
+};
+
+void b3DynamicBvhBroadphase::aabbTest(const b3Vector3& aabbMin,const b3Vector3& aabbMax,b3BroadphaseAabbCallback& aabbCallback)
+{
+ BroadphaseAabbTester callback(aabbCallback);
+
+ const B3_ATTRIBUTE_ALIGNED16(b3DbvtVolume) bounds=b3DbvtVolume::FromMM(aabbMin,aabbMax);
+ //process all children, that overlap with the given AABB bounds
+ m_sets[0].collideTV(m_sets[0].m_root,bounds,callback);
+ m_sets[1].collideTV(m_sets[1].m_root,bounds,callback);
+
+}
+
+
+
+//
+void b3DynamicBvhBroadphase::setAabb(int objectId,
+ const b3Vector3& aabbMin,
+ const b3Vector3& aabbMax,
+ b3Dispatcher* /*dispatcher*/)
+{
+ b3DbvtProxy* proxy=&m_proxies[objectId];
+// b3DbvtProxy* proxy=(b3DbvtProxy*)absproxy;
+ B3_ATTRIBUTE_ALIGNED16(b3DbvtVolume) aabb=b3DbvtVolume::FromMM(aabbMin,aabbMax);
+#if B3_DBVT_BP_PREVENTFALSEUPDATE
+ if(b3NotEqual(aabb,proxy->leaf->volume))
+#endif
+ {
+ bool docollide=false;
+ if(proxy->stage==STAGECOUNT)
+ {/* fixed -> dynamic set */
+ m_sets[1].remove(proxy->leaf);
+ proxy->leaf=m_sets[0].insert(aabb,proxy);
+ docollide=true;
+ }
+ else
+ {/* dynamic set */
+ ++m_updates_call;
+ if(b3Intersect(proxy->leaf->volume,aabb))
+ {/* Moving */
+
+ const b3Vector3 delta=aabbMin-proxy->m_aabbMin;
+ b3Vector3 velocity(((proxy->m_aabbMax-proxy->m_aabbMin)/2)*m_prediction);
+ if(delta[0]<0) velocity[0]=-velocity[0];
+ if(delta[1]<0) velocity[1]=-velocity[1];
+ if(delta[2]<0) velocity[2]=-velocity[2];
+ if (
+#ifdef B3_DBVT_BP_MARGIN
+ m_sets[0].update(proxy->leaf,aabb,velocity,B3_DBVT_BP_MARGIN)
+#else
+ m_sets[0].update(proxy->leaf,aabb,velocity)
+#endif
+ )
+ {
+ ++m_updates_done;
+ docollide=true;
+ }
+ }
+ else
+ {/* Teleporting */
+ m_sets[0].update(proxy->leaf,aabb);
+ ++m_updates_done;
+ docollide=true;
+ }
+ }
+ b3ListRemove(proxy,m_stageRoots[proxy->stage]);
+ proxy->m_aabbMin = aabbMin;
+ proxy->m_aabbMax = aabbMax;
+ proxy->stage = m_stageCurrent;
+ b3ListAppend(proxy,m_stageRoots[m_stageCurrent]);
+ if(docollide)
+ {
+ m_needcleanup=true;
+ if(!m_deferedcollide)
+ {
+ b3DbvtTreeCollider collider(this);
+ m_sets[1].collideTTpersistentStack(m_sets[1].m_root,proxy->leaf,collider);
+ m_sets[0].collideTTpersistentStack(m_sets[0].m_root,proxy->leaf,collider);
+ }
+ }
+ }
+}
+
+
+//
+void b3DynamicBvhBroadphase::setAabbForceUpdate( b3BroadphaseProxy* absproxy,
+ const b3Vector3& aabbMin,
+ const b3Vector3& aabbMax,
+ b3Dispatcher* /*dispatcher*/)
+{
+ b3DbvtProxy* proxy=(b3DbvtProxy*)absproxy;
+ B3_ATTRIBUTE_ALIGNED16(b3DbvtVolume) aabb=b3DbvtVolume::FromMM(aabbMin,aabbMax);
+ bool docollide=false;
+ if(proxy->stage==STAGECOUNT)
+ {/* fixed -> dynamic set */
+ m_sets[1].remove(proxy->leaf);
+ proxy->leaf=m_sets[0].insert(aabb,proxy);
+ docollide=true;
+ }
+ else
+ {/* dynamic set */
+ ++m_updates_call;
+ /* Teleporting */
+ m_sets[0].update(proxy->leaf,aabb);
+ ++m_updates_done;
+ docollide=true;
+ }
+ b3ListRemove(proxy,m_stageRoots[proxy->stage]);
+ proxy->m_aabbMin = aabbMin;
+ proxy->m_aabbMax = aabbMax;
+ proxy->stage = m_stageCurrent;
+ b3ListAppend(proxy,m_stageRoots[m_stageCurrent]);
+ if(docollide)
+ {
+ m_needcleanup=true;
+ if(!m_deferedcollide)
+ {
+ b3DbvtTreeCollider collider(this);
+ m_sets[1].collideTTpersistentStack(m_sets[1].m_root,proxy->leaf,collider);
+ m_sets[0].collideTTpersistentStack(m_sets[0].m_root,proxy->leaf,collider);
+ }
+ }
+}
+
+//
+void b3DynamicBvhBroadphase::calculateOverlappingPairs(b3Dispatcher* dispatcher)
+{
+ collide(dispatcher);
+#if B3_DBVT_BP_PROFILE
+ if(0==(m_pid%B3_DBVT_BP_PROFILING_RATE))
+ {
+ printf("fixed(%u) dynamics(%u) pairs(%u)\r\n",m_sets[1].m_leaves,m_sets[0].m_leaves,m_paircache->getNumOverlappingPairs());
+ unsigned int total=m_profiling.m_total;
+ if(total<=0) total=1;
+ printf("ddcollide: %u%% (%uus)\r\n",(50+m_profiling.m_ddcollide*100)/total,m_profiling.m_ddcollide/B3_DBVT_BP_PROFILING_RATE);
+ printf("fdcollide: %u%% (%uus)\r\n",(50+m_profiling.m_fdcollide*100)/total,m_profiling.m_fdcollide/B3_DBVT_BP_PROFILING_RATE);
+ printf("cleanup: %u%% (%uus)\r\n",(50+m_profiling.m_cleanup*100)/total,m_profiling.m_cleanup/B3_DBVT_BP_PROFILING_RATE);
+ printf("total: %uus\r\n",total/B3_DBVT_BP_PROFILING_RATE);
+ const unsigned long sum=m_profiling.m_ddcollide+
+ m_profiling.m_fdcollide+
+ m_profiling.m_cleanup;
+ printf("leaked: %u%% (%uus)\r\n",100-((50+sum*100)/total),(total-sum)/B3_DBVT_BP_PROFILING_RATE);
+ printf("job counts: %u%%\r\n",(m_profiling.m_jobcount*100)/((m_sets[0].m_leaves+m_sets[1].m_leaves)*B3_DBVT_BP_PROFILING_RATE));
+ b3Clear(m_profiling);
+ m_clock.reset();
+ }
+#endif
+
+ performDeferredRemoval(dispatcher);
+
+}
+
+void b3DynamicBvhBroadphase::performDeferredRemoval(b3Dispatcher* dispatcher)
+{
+
+ if (m_paircache->hasDeferredRemoval())
+ {
+
+ b3BroadphasePairArray& overlappingPairArray = m_paircache->getOverlappingPairArray();
+
+ //perform a sort, to find duplicates and to sort 'invalid' pairs to the end
+ overlappingPairArray.quickSort(b3BroadphasePairSortPredicate());
+
+ int invalidPair = 0;
+
+
+ int i;
+
+ b3BroadphasePair previousPair = b3MakeBroadphasePair(-1,-1);
+
+
+
+ for (i=0;i<overlappingPairArray.size();i++)
+ {
+
+ b3BroadphasePair& pair = overlappingPairArray[i];
+
+ bool isDuplicate = (pair == previousPair);
+
+ previousPair = pair;
+
+ bool needsRemoval = false;
+
+ if (!isDuplicate)
+ {
+ //important to perform AABB check that is consistent with the broadphase
+ b3DbvtProxy* pa=&m_proxies[pair.x];
+ b3DbvtProxy* pb=&m_proxies[pair.y];
+ bool hasOverlap = b3Intersect(pa->leaf->volume,pb->leaf->volume);
+
+ if (hasOverlap)
+ {
+ needsRemoval = false;
+ } else
+ {
+ needsRemoval = true;
+ }
+ } else
+ {
+ //remove duplicate
+ needsRemoval = true;
+ //should have no algorithm
+ }
+
+ if (needsRemoval)
+ {
+ m_paircache->cleanOverlappingPair(pair,dispatcher);
+
+ pair.x = -1;
+ pair.y = -1;
+ invalidPair++;
+ }
+
+ }
+
+ //perform a sort, to sort 'invalid' pairs to the end
+ overlappingPairArray.quickSort(b3BroadphasePairSortPredicate());
+ overlappingPairArray.resize(overlappingPairArray.size() - invalidPair);
+ }
+}
+
+//
+void b3DynamicBvhBroadphase::collide(b3Dispatcher* dispatcher)
+{
+ /*printf("---------------------------------------------------------\n");
+ printf("m_sets[0].m_leaves=%d\n",m_sets[0].m_leaves);
+ printf("m_sets[1].m_leaves=%d\n",m_sets[1].m_leaves);
+ printf("numPairs = %d\n",getOverlappingPairCache()->getNumOverlappingPairs());
+ {
+ int i;
+ for (i=0;i<getOverlappingPairCache()->getNumOverlappingPairs();i++)
+ {
+ printf("pair[%d]=(%d,%d),",i,getOverlappingPairCache()->getOverlappingPairArray()[i].m_pProxy0->getUid(),
+ getOverlappingPairCache()->getOverlappingPairArray()[i].m_pProxy1->getUid());
+ }
+ printf("\n");
+ }
+*/
+
+
+
+ b3SPC(m_profiling.m_total);
+ /* optimize */
+ m_sets[0].optimizeIncremental(1+(m_sets[0].m_leaves*m_dupdates)/100);
+ if(m_fixedleft)
+ {
+ const int count=1+(m_sets[1].m_leaves*m_fupdates)/100;
+ m_sets[1].optimizeIncremental(1+(m_sets[1].m_leaves*m_fupdates)/100);
+ m_fixedleft=b3Max<int>(0,m_fixedleft-count);
+ }
+ /* dynamic -> fixed set */
+ m_stageCurrent=(m_stageCurrent+1)%STAGECOUNT;
+ b3DbvtProxy* current=m_stageRoots[m_stageCurrent];
+ if(current)
+ {
+ b3DbvtTreeCollider collider(this);
+ do {
+ b3DbvtProxy* next=current->links[1];
+ b3ListRemove(current,m_stageRoots[current->stage]);
+ b3ListAppend(current,m_stageRoots[STAGECOUNT]);
+#if B3_DBVT_BP_ACCURATESLEEPING
+ m_paircache->removeOverlappingPairsContainingProxy(current,dispatcher);
+ collider.proxy=current;
+ b3DynamicBvh::collideTV(m_sets[0].m_root,current->aabb,collider);
+ b3DynamicBvh::collideTV(m_sets[1].m_root,current->aabb,collider);
+#endif
+ m_sets[0].remove(current->leaf);
+ B3_ATTRIBUTE_ALIGNED16(b3DbvtVolume) curAabb=b3DbvtVolume::FromMM(current->m_aabbMin,current->m_aabbMax);
+ current->leaf = m_sets[1].insert(curAabb,current);
+ current->stage = STAGECOUNT;
+ current = next;
+ } while(current);
+ m_fixedleft=m_sets[1].m_leaves;
+ m_needcleanup=true;
+ }
+ /* collide dynamics */
+ {
+ b3DbvtTreeCollider collider(this);
+ if(m_deferedcollide)
+ {
+ b3SPC(m_profiling.m_fdcollide);
+ m_sets[0].collideTTpersistentStack(m_sets[0].m_root,m_sets[1].m_root,collider);
+ }
+ if(m_deferedcollide)
+ {
+ b3SPC(m_profiling.m_ddcollide);
+ m_sets[0].collideTTpersistentStack(m_sets[0].m_root,m_sets[0].m_root,collider);
+ }
+ }
+ /* clean up */
+ if(m_needcleanup)
+ {
+ b3SPC(m_profiling.m_cleanup);
+ b3BroadphasePairArray& pairs=m_paircache->getOverlappingPairArray();
+ if(pairs.size()>0)
+ {
+
+ int ni=b3Min(pairs.size(),b3Max<int>(m_newpairs,(pairs.size()*m_cupdates)/100));
+ for(int i=0;i<ni;++i)
+ {
+ b3BroadphasePair& p=pairs[(m_cid+i)%pairs.size()];
+ b3DbvtProxy* pa=&m_proxies[p.x];
+ b3DbvtProxy* pb=&m_proxies[p.y];
+ if(!b3Intersect(pa->leaf->volume,pb->leaf->volume))
+ {
+#if B3_DBVT_BP_SORTPAIRS
+ if(pa->m_uniqueId>pb->m_uniqueId)
+ b3Swap(pa,pb);
+#endif
+ m_paircache->removeOverlappingPair(pa->getUid(),pb->getUid(),dispatcher);
+ --ni;--i;
+ }
+ }
+ if(pairs.size()>0) m_cid=(m_cid+ni)%pairs.size(); else m_cid=0;
+ }
+ }
+ ++m_pid;
+ m_newpairs=1;
+ m_needcleanup=false;
+ if(m_updates_call>0)
+ { m_updates_ratio=m_updates_done/(b3Scalar)m_updates_call; }
+ else
+ { m_updates_ratio=0; }
+ m_updates_done/=2;
+ m_updates_call/=2;
+}
+
+//
+void b3DynamicBvhBroadphase::optimize()
+{
+ m_sets[0].optimizeTopDown();
+ m_sets[1].optimizeTopDown();
+}
+
+//
+b3OverlappingPairCache* b3DynamicBvhBroadphase::getOverlappingPairCache()
+{
+ return(m_paircache);
+}
+
+//
+const b3OverlappingPairCache* b3DynamicBvhBroadphase::getOverlappingPairCache() const
+{
+ return(m_paircache);
+}
+
+//
+void b3DynamicBvhBroadphase::getBroadphaseAabb(b3Vector3& aabbMin,b3Vector3& aabbMax) const
+{
+
+ B3_ATTRIBUTE_ALIGNED16(b3DbvtVolume) bounds;
+
+ if(!m_sets[0].empty())
+ if(!m_sets[1].empty()) b3Merge( m_sets[0].m_root->volume,
+ m_sets[1].m_root->volume,bounds);
+ else
+ bounds=m_sets[0].m_root->volume;
+ else if(!m_sets[1].empty()) bounds=m_sets[1].m_root->volume;
+ else
+ bounds=b3DbvtVolume::FromCR(b3MakeVector3(0,0,0),0);
+ aabbMin=bounds.Mins();
+ aabbMax=bounds.Maxs();
+}
+
+void b3DynamicBvhBroadphase::resetPool(b3Dispatcher* dispatcher)
+{
+
+ int totalObjects = m_sets[0].m_leaves + m_sets[1].m_leaves;
+ if (!totalObjects)
+ {
+ //reset internal dynamic tree data structures
+ m_sets[0].clear();
+ m_sets[1].clear();
+
+ m_deferedcollide = false;
+ m_needcleanup = true;
+ m_stageCurrent = 0;
+ m_fixedleft = 0;
+ m_fupdates = 1;
+ m_dupdates = 0;
+ m_cupdates = 10;
+ m_newpairs = 1;
+ m_updates_call = 0;
+ m_updates_done = 0;
+ m_updates_ratio = 0;
+
+ m_pid = 0;
+ m_cid = 0;
+ for(int i=0;i<=STAGECOUNT;++i)
+ {
+ m_stageRoots[i]=0;
+ }
+ }
+}
+
+//
+void b3DynamicBvhBroadphase::printStats()
+{}
+
+//
+#if B3_DBVT_BP_ENABLE_BENCHMARK
+
+struct b3BroadphaseBenchmark
+{
+ struct Experiment
+ {
+ const char* name;
+ int object_count;
+ int update_count;
+ int spawn_count;
+ int iterations;
+ b3Scalar speed;
+ b3Scalar amplitude;
+ };
+ struct Object
+ {
+ b3Vector3 center;
+ b3Vector3 extents;
+ b3BroadphaseProxy* proxy;
+ b3Scalar time;
+ void update(b3Scalar speed,b3Scalar amplitude,b3BroadphaseInterface* pbi)
+ {
+ time += speed;
+ center[0] = b3Cos(time*(b3Scalar)2.17)*amplitude+
+ b3Sin(time)*amplitude/2;
+ center[1] = b3Cos(time*(b3Scalar)1.38)*amplitude+
+ b3Sin(time)*amplitude;
+ center[2] = b3Sin(time*(b3Scalar)0.777)*amplitude;
+ pbi->setAabb(proxy,center-extents,center+extents,0);
+ }
+ };
+ static int UnsignedRand(int range=RAND_MAX-1) { return(rand()%(range+1)); }
+ static b3Scalar UnitRand() { return(UnsignedRand(16384)/(b3Scalar)16384); }
+ static void OutputTime(const char* name,b3Clock& c,unsigned count=0)
+ {
+ const unsigned long us=c.getTimeMicroseconds();
+ const unsigned long ms=(us+500)/1000;
+ const b3Scalar sec=us/(b3Scalar)(1000*1000);
+ if(count>0)
+ printf("%s : %u us (%u ms), %.2f/s\r\n",name,us,ms,count/sec);
+ else
+ printf("%s : %u us (%u ms)\r\n",name,us,ms);
+ }
+};
+
+void b3DynamicBvhBroadphase::benchmark(b3BroadphaseInterface* pbi)
+{
+ static const b3BroadphaseBenchmark::Experiment experiments[]=
+ {
+ {"1024o.10%",1024,10,0,8192,(b3Scalar)0.005,(b3Scalar)100},
+ /*{"4096o.10%",4096,10,0,8192,(b3Scalar)0.005,(b3Scalar)100},
+ {"8192o.10%",8192,10,0,8192,(b3Scalar)0.005,(b3Scalar)100},*/
+ };
+ static const int nexperiments=sizeof(experiments)/sizeof(experiments[0]);
+ b3AlignedObjectArray<b3BroadphaseBenchmark::Object*> objects;
+ b3Clock wallclock;
+ /* Begin */
+ for(int iexp=0;iexp<nexperiments;++iexp)
+ {
+ const b3BroadphaseBenchmark::Experiment& experiment=experiments[iexp];
+ const int object_count=experiment.object_count;
+ const int update_count=(object_count*experiment.update_count)/100;
+ const int spawn_count=(object_count*experiment.spawn_count)/100;
+ const b3Scalar speed=experiment.speed;
+ const b3Scalar amplitude=experiment.amplitude;
+ printf("Experiment #%u '%s':\r\n",iexp,experiment.name);
+ printf("\tObjects: %u\r\n",object_count);
+ printf("\tUpdate: %u\r\n",update_count);
+ printf("\tSpawn: %u\r\n",spawn_count);
+ printf("\tSpeed: %f\r\n",speed);
+ printf("\tAmplitude: %f\r\n",amplitude);
+ srand(180673);
+ /* Create objects */
+ wallclock.reset();
+ objects.reserve(object_count);
+ for(int i=0;i<object_count;++i)
+ {
+ b3BroadphaseBenchmark::Object* po=new b3BroadphaseBenchmark::Object();
+ po->center[0]=b3BroadphaseBenchmark::UnitRand()*50;
+ po->center[1]=b3BroadphaseBenchmark::UnitRand()*50;
+ po->center[2]=b3BroadphaseBenchmark::UnitRand()*50;
+ po->extents[0]=b3BroadphaseBenchmark::UnitRand()*2+2;
+ po->extents[1]=b3BroadphaseBenchmark::UnitRand()*2+2;
+ po->extents[2]=b3BroadphaseBenchmark::UnitRand()*2+2;
+ po->time=b3BroadphaseBenchmark::UnitRand()*2000;
+ po->proxy=pbi->createProxy(po->center-po->extents,po->center+po->extents,0,po,1,1,0,0);
+ objects.push_back(po);
+ }
+ b3BroadphaseBenchmark::OutputTime("\tInitialization",wallclock);
+ /* First update */
+ wallclock.reset();
+ for(int i=0;i<objects.size();++i)
+ {
+ objects[i]->update(speed,amplitude,pbi);
+ }
+ b3BroadphaseBenchmark::OutputTime("\tFirst update",wallclock);
+ /* Updates */
+ wallclock.reset();
+ for(int i=0;i<experiment.iterations;++i)
+ {
+ for(int j=0;j<update_count;++j)
+ {
+ objects[j]->update(speed,amplitude,pbi);
+ }
+ pbi->calculateOverlappingPairs(0);
+ }
+ b3BroadphaseBenchmark::OutputTime("\tUpdate",wallclock,experiment.iterations);
+ /* Clean up */
+ wallclock.reset();
+ for(int i=0;i<objects.size();++i)
+ {
+ pbi->destroyProxy(objects[i]->proxy,0);
+ delete objects[i];
+ }
+ objects.resize(0);
+ b3BroadphaseBenchmark::OutputTime("\tRelease",wallclock);
+ }
+
+}
+#else
+/*void b3DynamicBvhBroadphase::benchmark(b3BroadphaseInterface*)
+{}
+*/
+#endif
+
+#if B3_DBVT_BP_PROFILE
+#undef b3SPC
+#endif
+
diff --git a/thirdparty/bullet/src/Bullet3Collision/BroadPhaseCollision/b3DynamicBvhBroadphase.h b/thirdparty/bullet/src/Bullet3Collision/BroadPhaseCollision/b3DynamicBvhBroadphase.h
new file mode 100644
index 0000000000..7ac085d90c
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Collision/BroadPhaseCollision/b3DynamicBvhBroadphase.h
@@ -0,0 +1,206 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2013 Erwin Coumans 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.
+*/
+
+///b3DynamicBvhBroadphase implementation by Nathanael Presson
+#ifndef B3_DBVT_BROADPHASE_H
+#define B3_DBVT_BROADPHASE_H
+
+#include "Bullet3Collision/BroadPhaseCollision/b3DynamicBvh.h"
+#include "Bullet3Collision/BroadPhaseCollision/b3OverlappingPairCache.h"
+#include "Bullet3Common/b3AlignedObjectArray.h"
+
+#include "b3BroadphaseCallback.h"
+
+//
+// Compile time config
+//
+
+#define B3_DBVT_BP_PROFILE 0
+//#define B3_DBVT_BP_SORTPAIRS 1
+#define B3_DBVT_BP_PREVENTFALSEUPDATE 0
+#define B3_DBVT_BP_ACCURATESLEEPING 0
+#define B3_DBVT_BP_ENABLE_BENCHMARK 0
+#define B3_DBVT_BP_MARGIN (b3Scalar)0.05
+
+#if B3_DBVT_BP_PROFILE
+#define B3_DBVT_BP_PROFILING_RATE 256
+
+#endif
+
+
+
+
+B3_ATTRIBUTE_ALIGNED16(struct) b3BroadphaseProxy
+{
+
+B3_DECLARE_ALIGNED_ALLOCATOR();
+
+ ///optional filtering to cull potential collisions
+ enum CollisionFilterGroups
+ {
+ DefaultFilter = 1,
+ StaticFilter = 2,
+ KinematicFilter = 4,
+ DebrisFilter = 8,
+ SensorTrigger = 16,
+ CharacterFilter = 32,
+ AllFilter = -1 //all bits sets: DefaultFilter | StaticFilter | KinematicFilter | DebrisFilter | SensorTrigger
+ };
+
+ //Usually the client b3CollisionObject or Rigidbody class
+ void* m_clientObject;
+ int m_collisionFilterGroup;
+ int m_collisionFilterMask;
+ int m_uniqueId;//m_uniqueId is introduced for paircache. could get rid of this, by calculating the address offset etc.
+
+ b3Vector3 m_aabbMin;
+ b3Vector3 m_aabbMax;
+
+ B3_FORCE_INLINE int getUid() const
+ {
+ return m_uniqueId;
+ }
+
+ //used for memory pools
+ b3BroadphaseProxy() :m_clientObject(0)
+ {
+ }
+
+ b3BroadphaseProxy(const b3Vector3& aabbMin,const b3Vector3& aabbMax,void* userPtr, int collisionFilterGroup, int collisionFilterMask)
+ :m_clientObject(userPtr),
+ m_collisionFilterGroup(collisionFilterGroup),
+ m_collisionFilterMask(collisionFilterMask),
+ m_aabbMin(aabbMin),
+ m_aabbMax(aabbMax)
+ {
+ }
+};
+
+
+
+
+
+//
+// b3DbvtProxy
+//
+struct b3DbvtProxy : b3BroadphaseProxy
+{
+ /* Fields */
+ //b3DbvtAabbMm aabb;
+ b3DbvtNode* leaf;
+ b3DbvtProxy* links[2];
+ int stage;
+ /* ctor */
+
+ explicit b3DbvtProxy() {}
+ b3DbvtProxy(const b3Vector3& aabbMin,const b3Vector3& aabbMax,void* userPtr, int collisionFilterGroup, int collisionFilterMask) :
+ b3BroadphaseProxy(aabbMin,aabbMax,userPtr,collisionFilterGroup,collisionFilterMask)
+ {
+ links[0]=links[1]=0;
+ }
+};
+
+typedef b3AlignedObjectArray<b3DbvtProxy*> b3DbvtProxyArray;
+
+///The b3DynamicBvhBroadphase implements a broadphase using two dynamic AABB bounding volume hierarchies/trees (see b3DynamicBvh).
+///One tree is used for static/non-moving objects, and another tree is used for dynamic objects. Objects can move from one tree to the other.
+///This is a very fast broadphase, especially for very dynamic worlds where many objects are moving. Its insert/add and remove of objects is generally faster than the sweep and prune broadphases b3AxisSweep3 and b332BitAxisSweep3.
+struct b3DynamicBvhBroadphase
+{
+ /* Config */
+ enum {
+ DYNAMIC_SET = 0, /* Dynamic set index */
+ FIXED_SET = 1, /* Fixed set index */
+ STAGECOUNT = 2 /* Number of stages */
+ };
+ /* Fields */
+ b3DynamicBvh m_sets[2]; // Dbvt sets
+ b3DbvtProxy* m_stageRoots[STAGECOUNT+1]; // Stages list
+
+ b3AlignedObjectArray<b3DbvtProxy> m_proxies;
+ b3OverlappingPairCache* m_paircache; // Pair cache
+ b3Scalar m_prediction; // Velocity prediction
+ int m_stageCurrent; // Current stage
+ int m_fupdates; // % of fixed updates per frame
+ int m_dupdates; // % of dynamic updates per frame
+ int m_cupdates; // % of cleanup updates per frame
+ int m_newpairs; // Number of pairs created
+ int m_fixedleft; // Fixed optimization left
+ unsigned m_updates_call; // Number of updates call
+ unsigned m_updates_done; // Number of updates done
+ b3Scalar m_updates_ratio; // m_updates_done/m_updates_call
+ int m_pid; // Parse id
+ int m_cid; // Cleanup index
+ bool m_releasepaircache; // Release pair cache on delete
+ bool m_deferedcollide; // Defere dynamic/static collision to collide call
+ bool m_needcleanup; // Need to run cleanup?
+#if B3_DBVT_BP_PROFILE
+ b3Clock m_clock;
+ struct {
+ unsigned long m_total;
+ unsigned long m_ddcollide;
+ unsigned long m_fdcollide;
+ unsigned long m_cleanup;
+ unsigned long m_jobcount;
+ } m_profiling;
+#endif
+ /* Methods */
+ b3DynamicBvhBroadphase(int proxyCapacity, b3OverlappingPairCache* paircache=0);
+ virtual ~b3DynamicBvhBroadphase();
+ void collide(b3Dispatcher* dispatcher);
+ void optimize();
+
+ /* b3BroadphaseInterface Implementation */
+ b3BroadphaseProxy* createProxy(const b3Vector3& aabbMin,const b3Vector3& aabbMax,int objectIndex,void* userPtr, int collisionFilterGroup, int collisionFilterMask);
+ virtual void destroyProxy(b3BroadphaseProxy* proxy,b3Dispatcher* dispatcher);
+ virtual void setAabb(int objectId,const b3Vector3& aabbMin,const b3Vector3& aabbMax,b3Dispatcher* dispatcher);
+ virtual void rayTest(const b3Vector3& rayFrom,const b3Vector3& rayTo, b3BroadphaseRayCallback& rayCallback, const b3Vector3& aabbMin=b3MakeVector3(0,0,0), const b3Vector3& aabbMax = b3MakeVector3(0,0,0));
+ virtual void aabbTest(const b3Vector3& aabbMin, const b3Vector3& aabbMax, b3BroadphaseAabbCallback& callback);
+
+ //virtual void getAabb(b3BroadphaseProxy* proxy,b3Vector3& aabbMin, b3Vector3& aabbMax ) const;
+ virtual void getAabb(int objectId,b3Vector3& aabbMin, b3Vector3& aabbMax ) const;
+ virtual void calculateOverlappingPairs(b3Dispatcher* dispatcher=0);
+ virtual b3OverlappingPairCache* getOverlappingPairCache();
+ virtual const b3OverlappingPairCache* getOverlappingPairCache() const;
+ virtual void getBroadphaseAabb(b3Vector3& aabbMin,b3Vector3& aabbMax) const;
+ virtual void printStats();
+
+
+ ///reset broadphase internal structures, to ensure determinism/reproducability
+ virtual void resetPool(b3Dispatcher* dispatcher);
+
+ void performDeferredRemoval(b3Dispatcher* dispatcher);
+
+ void setVelocityPrediction(b3Scalar prediction)
+ {
+ m_prediction = prediction;
+ }
+ b3Scalar getVelocityPrediction() const
+ {
+ return m_prediction;
+ }
+
+ ///this setAabbForceUpdate is similar to setAabb but always forces the aabb update.
+ ///it is not part of the b3BroadphaseInterface but specific to b3DynamicBvhBroadphase.
+ ///it bypasses certain optimizations that prevent aabb updates (when the aabb shrinks), see
+ ///http://code.google.com/p/bullet/issues/detail?id=223
+ void setAabbForceUpdate( b3BroadphaseProxy* absproxy,const b3Vector3& aabbMin,const b3Vector3& aabbMax,b3Dispatcher* /*dispatcher*/);
+
+ //static void benchmark(b3BroadphaseInterface*);
+
+
+};
+
+#endif
diff --git a/thirdparty/bullet/src/Bullet3Collision/BroadPhaseCollision/b3OverlappingPair.h b/thirdparty/bullet/src/Bullet3Collision/BroadPhaseCollision/b3OverlappingPair.h
new file mode 100644
index 0000000000..39bf27de3e
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Collision/BroadPhaseCollision/b3OverlappingPair.h
@@ -0,0 +1,72 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2013 Erwin Coumans 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 B3_OVERLAPPING_PAIR_H
+#define B3_OVERLAPPING_PAIR_H
+
+#include "Bullet3Common/shared/b3Int4.h"
+
+#define B3_NEW_PAIR_MARKER -1
+#define B3_REMOVED_PAIR_MARKER -2
+
+typedef b3Int4 b3BroadphasePair;
+
+inline b3Int4 b3MakeBroadphasePair(int xx,int yy)
+{
+ b3Int4 pair;
+
+ if (xx < yy)
+ {
+ pair.x = xx;
+ pair.y = yy;
+ }
+ else
+ {
+ pair.x = yy;
+ pair.y = xx;
+ }
+ pair.z = B3_NEW_PAIR_MARKER;
+ pair.w = B3_NEW_PAIR_MARKER;
+ return pair;
+}
+
+/*struct b3BroadphasePair : public b3Int4
+{
+ explicit b3BroadphasePair(){}
+
+};
+*/
+
+class b3BroadphasePairSortPredicate
+{
+ public:
+
+ bool operator() ( const b3BroadphasePair& a, const b3BroadphasePair& b ) const
+ {
+ const int uidA0 = a.x;
+ const int uidB0 = b.x;
+ const int uidA1 = a.y;
+ const int uidB1 = b.y;
+ return uidA0 > uidB0 || (uidA0 == uidB0 && uidA1 > uidB1);
+ }
+};
+
+B3_FORCE_INLINE bool operator==(const b3BroadphasePair& a, const b3BroadphasePair& b)
+{
+ return (a.x == b.x ) && (a.y == b.y );
+}
+
+#endif //B3_OVERLAPPING_PAIR_H
+
diff --git a/thirdparty/bullet/src/Bullet3Collision/BroadPhaseCollision/b3OverlappingPairCache.cpp b/thirdparty/bullet/src/Bullet3Collision/BroadPhaseCollision/b3OverlappingPairCache.cpp
new file mode 100644
index 0000000000..e4bda61624
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Collision/BroadPhaseCollision/b3OverlappingPairCache.cpp
@@ -0,0 +1,638 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2013 Erwin Coumans 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 "b3OverlappingPairCache.h"
+
+//#include "b3Dispatcher.h"
+//#include "b3CollisionAlgorithm.h"
+#include "Bullet3Geometry/b3AabbUtil.h"
+
+#include <stdio.h>
+
+int b3g_overlappingPairs = 0;
+int b3g_removePairs =0;
+int b3g_addedPairs =0;
+int b3g_findPairs =0;
+
+
+
+
+b3HashedOverlappingPairCache::b3HashedOverlappingPairCache():
+ m_overlapFilterCallback(0)
+//, m_blockedForChanges(false)
+{
+ int initialAllocatedSize= 2;
+ m_overlappingPairArray.reserve(initialAllocatedSize);
+ growTables();
+}
+
+
+
+
+b3HashedOverlappingPairCache::~b3HashedOverlappingPairCache()
+{
+}
+
+
+
+void b3HashedOverlappingPairCache::cleanOverlappingPair(b3BroadphasePair& pair,b3Dispatcher* dispatcher)
+{
+/* if (pair.m_algorithm)
+ {
+ {
+ pair.m_algorithm->~b3CollisionAlgorithm();
+ dispatcher->freeCollisionAlgorithm(pair.m_algorithm);
+ pair.m_algorithm=0;
+ }
+ }
+ */
+
+}
+
+
+
+
+void b3HashedOverlappingPairCache::cleanProxyFromPairs(int proxy,b3Dispatcher* dispatcher)
+{
+
+ class CleanPairCallback : public b3OverlapCallback
+ {
+ int m_cleanProxy;
+ b3OverlappingPairCache* m_pairCache;
+ b3Dispatcher* m_dispatcher;
+
+ public:
+ CleanPairCallback(int cleanProxy,b3OverlappingPairCache* pairCache,b3Dispatcher* dispatcher)
+ :m_cleanProxy(cleanProxy),
+ m_pairCache(pairCache),
+ m_dispatcher(dispatcher)
+ {
+ }
+ virtual bool processOverlap(b3BroadphasePair& pair)
+ {
+ if ((pair.x == m_cleanProxy) ||
+ (pair.y == m_cleanProxy))
+ {
+ m_pairCache->cleanOverlappingPair(pair,m_dispatcher);
+ }
+ return false;
+ }
+
+ };
+
+ CleanPairCallback cleanPairs(proxy,this,dispatcher);
+
+ processAllOverlappingPairs(&cleanPairs,dispatcher);
+
+}
+
+
+
+
+void b3HashedOverlappingPairCache::removeOverlappingPairsContainingProxy(int proxy,b3Dispatcher* dispatcher)
+{
+
+ class RemovePairCallback : public b3OverlapCallback
+ {
+ int m_obsoleteProxy;
+
+ public:
+ RemovePairCallback(int obsoleteProxy)
+ :m_obsoleteProxy(obsoleteProxy)
+ {
+ }
+ virtual bool processOverlap(b3BroadphasePair& pair)
+ {
+ return ((pair.x == m_obsoleteProxy) ||
+ (pair.y == m_obsoleteProxy));
+ }
+
+ };
+
+
+ RemovePairCallback removeCallback(proxy);
+
+ processAllOverlappingPairs(&removeCallback,dispatcher);
+}
+
+
+
+
+
+b3BroadphasePair* b3HashedOverlappingPairCache::findPair(int proxy0, int proxy1)
+{
+ b3g_findPairs++;
+ if(proxy0 >proxy1)
+ b3Swap(proxy0,proxy1);
+ int proxyId1 = proxy0;
+ int proxyId2 = proxy1;
+
+ /*if (proxyId1 > proxyId2)
+ b3Swap(proxyId1, proxyId2);*/
+
+ int hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1), static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity()-1));
+
+ if (hash >= m_hashTable.size())
+ {
+ return NULL;
+ }
+
+ int index = m_hashTable[hash];
+ while (index != B3_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyId1, proxyId2) == false)
+ {
+ index = m_next[index];
+ }
+
+ if (index == B3_NULL_PAIR)
+ {
+ return NULL;
+ }
+
+ b3Assert(index < m_overlappingPairArray.size());
+
+ return &m_overlappingPairArray[index];
+}
+
+//#include <stdio.h>
+
+void b3HashedOverlappingPairCache::growTables()
+{
+
+ int newCapacity = m_overlappingPairArray.capacity();
+
+ if (m_hashTable.size() < newCapacity)
+ {
+ //grow hashtable and next table
+ int curHashtableSize = m_hashTable.size();
+
+ m_hashTable.resize(newCapacity);
+ m_next.resize(newCapacity);
+
+
+ int i;
+
+ for (i= 0; i < newCapacity; ++i)
+ {
+ m_hashTable[i] = B3_NULL_PAIR;
+ }
+ for (i = 0; i < newCapacity; ++i)
+ {
+ m_next[i] = B3_NULL_PAIR;
+ }
+
+ for(i=0;i<curHashtableSize;i++)
+ {
+
+ const b3BroadphasePair& pair = m_overlappingPairArray[i];
+ int proxyId1 = pair.x;
+ int proxyId2 = pair.y;
+ /*if (proxyId1 > proxyId2)
+ b3Swap(proxyId1, proxyId2);*/
+ int hashValue = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1),static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity()-1)); // New hash value with new mask
+ m_next[i] = m_hashTable[hashValue];
+ m_hashTable[hashValue] = i;
+ }
+
+
+ }
+}
+
+b3BroadphasePair* b3HashedOverlappingPairCache::internalAddPair(int proxy0, int proxy1)
+{
+ if(proxy0>proxy1)
+ b3Swap(proxy0,proxy1);
+ int proxyId1 = proxy0;
+ int proxyId2 = proxy1;
+
+ /*if (proxyId1 > proxyId2)
+ b3Swap(proxyId1, proxyId2);*/
+
+ int hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1),static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity()-1)); // New hash value with new mask
+
+
+ b3BroadphasePair* pair = internalFindPair(proxy0, proxy1, hash);
+ if (pair != NULL)
+ {
+ return pair;
+ }
+ /*for(int i=0;i<m_overlappingPairArray.size();++i)
+ {
+ if( (m_overlappingPairArray[i].m_pProxy0==proxy0)&&
+ (m_overlappingPairArray[i].m_pProxy1==proxy1))
+ {
+ printf("Adding duplicated %u<>%u\r\n",proxyId1,proxyId2);
+ internalFindPair(proxy0, proxy1, hash);
+ }
+ }*/
+ int count = m_overlappingPairArray.size();
+ int oldCapacity = m_overlappingPairArray.capacity();
+ pair = &m_overlappingPairArray.expandNonInitializing();
+
+ //this is where we add an actual pair, so also call the 'ghost'
+// if (m_ghostPairCallback)
+// m_ghostPairCallback->addOverlappingPair(proxy0,proxy1);
+
+ int newCapacity = m_overlappingPairArray.capacity();
+
+ if (oldCapacity < newCapacity)
+ {
+ growTables();
+ //hash with new capacity
+ hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1),static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity()-1));
+ }
+
+ *pair = b3MakeBroadphasePair(proxy0,proxy1);
+
+// pair->m_pProxy0 = proxy0;
+// pair->m_pProxy1 = proxy1;
+ //pair->m_algorithm = 0;
+ //pair->m_internalTmpValue = 0;
+
+
+ m_next[count] = m_hashTable[hash];
+ m_hashTable[hash] = count;
+
+ return pair;
+}
+
+
+
+void* b3HashedOverlappingPairCache::removeOverlappingPair(int proxy0, int proxy1,b3Dispatcher* dispatcher)
+{
+ b3g_removePairs++;
+ if(proxy0>proxy1)
+ b3Swap(proxy0,proxy1);
+ int proxyId1 = proxy0;
+ int proxyId2 = proxy1;
+
+ /*if (proxyId1 > proxyId2)
+ b3Swap(proxyId1, proxyId2);*/
+
+ int hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1),static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity()-1));
+
+ b3BroadphasePair* pair = internalFindPair(proxy0, proxy1, hash);
+ if (pair == NULL)
+ {
+ return 0;
+ }
+
+ cleanOverlappingPair(*pair,dispatcher);
+
+
+
+ int pairIndex = int(pair - &m_overlappingPairArray[0]);
+ b3Assert(pairIndex < m_overlappingPairArray.size());
+
+ // Remove the pair from the hash table.
+ int index = m_hashTable[hash];
+ b3Assert(index != B3_NULL_PAIR);
+
+ int previous = B3_NULL_PAIR;
+ while (index != pairIndex)
+ {
+ previous = index;
+ index = m_next[index];
+ }
+
+ if (previous != B3_NULL_PAIR)
+ {
+ b3Assert(m_next[previous] == pairIndex);
+ m_next[previous] = m_next[pairIndex];
+ }
+ else
+ {
+ m_hashTable[hash] = m_next[pairIndex];
+ }
+
+ // We now move the last pair into spot of the
+ // pair being removed. We need to fix the hash
+ // table indices to support the move.
+
+ int lastPairIndex = m_overlappingPairArray.size() - 1;
+
+ //if (m_ghostPairCallback)
+ // m_ghostPairCallback->removeOverlappingPair(proxy0, proxy1,dispatcher);
+
+ // If the removed pair is the last pair, we are done.
+ if (lastPairIndex == pairIndex)
+ {
+ m_overlappingPairArray.pop_back();
+ return 0;
+ }
+
+ // Remove the last pair from the hash table.
+ const b3BroadphasePair* last = &m_overlappingPairArray[lastPairIndex];
+ /* missing swap here too, Nat. */
+ int lastHash = static_cast<int>(getHash(static_cast<unsigned int>(last->x), static_cast<unsigned int>(last->y)) & (m_overlappingPairArray.capacity()-1));
+
+ index = m_hashTable[lastHash];
+ b3Assert(index != B3_NULL_PAIR);
+
+ previous = B3_NULL_PAIR;
+ while (index != lastPairIndex)
+ {
+ previous = index;
+ index = m_next[index];
+ }
+
+ if (previous != B3_NULL_PAIR)
+ {
+ b3Assert(m_next[previous] == lastPairIndex);
+ m_next[previous] = m_next[lastPairIndex];
+ }
+ else
+ {
+ m_hashTable[lastHash] = m_next[lastPairIndex];
+ }
+
+ // Copy the last pair into the remove pair's spot.
+ m_overlappingPairArray[pairIndex] = m_overlappingPairArray[lastPairIndex];
+
+ // Insert the last pair into the hash table
+ m_next[pairIndex] = m_hashTable[lastHash];
+ m_hashTable[lastHash] = pairIndex;
+
+ m_overlappingPairArray.pop_back();
+
+ return 0;
+}
+//#include <stdio.h>
+
+void b3HashedOverlappingPairCache::processAllOverlappingPairs(b3OverlapCallback* callback,b3Dispatcher* dispatcher)
+{
+
+ int i;
+
+// printf("m_overlappingPairArray.size()=%d\n",m_overlappingPairArray.size());
+ for (i=0;i<m_overlappingPairArray.size();)
+ {
+
+ b3BroadphasePair* pair = &m_overlappingPairArray[i];
+ if (callback->processOverlap(*pair))
+ {
+ removeOverlappingPair(pair->x,pair->y,dispatcher);
+
+ b3g_overlappingPairs--;
+ } else
+ {
+ i++;
+ }
+ }
+}
+
+
+
+
+
+void b3HashedOverlappingPairCache::sortOverlappingPairs(b3Dispatcher* dispatcher)
+{
+ ///need to keep hashmap in sync with pair address, so rebuild all
+ b3BroadphasePairArray tmpPairs;
+ int i;
+ for (i=0;i<m_overlappingPairArray.size();i++)
+ {
+ tmpPairs.push_back(m_overlappingPairArray[i]);
+ }
+
+ for (i=0;i<tmpPairs.size();i++)
+ {
+ removeOverlappingPair(tmpPairs[i].x,tmpPairs[i].y,dispatcher);
+ }
+
+ for (i = 0; i < m_next.size(); i++)
+ {
+ m_next[i] = B3_NULL_PAIR;
+ }
+
+ tmpPairs.quickSort(b3BroadphasePairSortPredicate());
+
+ for (i=0;i<tmpPairs.size();i++)
+ {
+ addOverlappingPair(tmpPairs[i].x ,tmpPairs[i].y);
+ }
+
+
+}
+
+
+void* b3SortedOverlappingPairCache::removeOverlappingPair(int proxy0,int proxy1, b3Dispatcher* dispatcher )
+{
+ if (!hasDeferredRemoval())
+ {
+ b3BroadphasePair findPair = b3MakeBroadphasePair(proxy0,proxy1);
+
+
+ int findIndex = m_overlappingPairArray.findLinearSearch(findPair);
+ if (findIndex < m_overlappingPairArray.size())
+ {
+ b3g_overlappingPairs--;
+ b3BroadphasePair& pair = m_overlappingPairArray[findIndex];
+
+ cleanOverlappingPair(pair,dispatcher);
+ //if (m_ghostPairCallback)
+ // m_ghostPairCallback->removeOverlappingPair(proxy0, proxy1,dispatcher);
+
+ m_overlappingPairArray.swap(findIndex,m_overlappingPairArray.capacity()-1);
+ m_overlappingPairArray.pop_back();
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
+
+
+
+
+
+
+
+b3BroadphasePair* b3SortedOverlappingPairCache::addOverlappingPair(int proxy0,int proxy1)
+{
+ //don't add overlap with own
+ b3Assert(proxy0 != proxy1);
+
+ if (!needsBroadphaseCollision(proxy0,proxy1))
+ return 0;
+
+ b3BroadphasePair* pair = &m_overlappingPairArray.expandNonInitializing();
+ *pair = b3MakeBroadphasePair(proxy0,proxy1);
+
+
+ b3g_overlappingPairs++;
+ b3g_addedPairs++;
+
+// if (m_ghostPairCallback)
+// m_ghostPairCallback->addOverlappingPair(proxy0, proxy1);
+ return pair;
+
+}
+
+///this findPair becomes really slow. Either sort the list to speedup the query, or
+///use a different solution. It is mainly used for Removing overlapping pairs. Removal could be delayed.
+///we could keep a linked list in each proxy, and store pair in one of the proxies (with lowest memory address)
+///Also we can use a 2D bitmap, which can be useful for a future GPU implementation
+ b3BroadphasePair* b3SortedOverlappingPairCache::findPair(int proxy0,int proxy1)
+{
+ if (!needsBroadphaseCollision(proxy0,proxy1))
+ return 0;
+
+ b3BroadphasePair tmpPair = b3MakeBroadphasePair(proxy0,proxy1);
+ int findIndex = m_overlappingPairArray.findLinearSearch(tmpPair);
+
+ if (findIndex < m_overlappingPairArray.size())
+ {
+ //b3Assert(it != m_overlappingPairSet.end());
+ b3BroadphasePair* pair = &m_overlappingPairArray[findIndex];
+ return pair;
+ }
+ return 0;
+}
+
+
+
+
+
+
+
+
+
+
+//#include <stdio.h>
+
+void b3SortedOverlappingPairCache::processAllOverlappingPairs(b3OverlapCallback* callback,b3Dispatcher* dispatcher)
+{
+
+ int i;
+
+ for (i=0;i<m_overlappingPairArray.size();)
+ {
+
+ b3BroadphasePair* pair = &m_overlappingPairArray[i];
+ if (callback->processOverlap(*pair))
+ {
+ cleanOverlappingPair(*pair,dispatcher);
+ pair->x = -1;
+ pair->y = -1;
+ m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1);
+ m_overlappingPairArray.pop_back();
+ b3g_overlappingPairs--;
+ } else
+ {
+ i++;
+ }
+ }
+}
+
+
+
+
+b3SortedOverlappingPairCache::b3SortedOverlappingPairCache():
+ m_blockedForChanges(false),
+ m_hasDeferredRemoval(true),
+ m_overlapFilterCallback(0)
+
+{
+ int initialAllocatedSize= 2;
+ m_overlappingPairArray.reserve(initialAllocatedSize);
+}
+
+b3SortedOverlappingPairCache::~b3SortedOverlappingPairCache()
+{
+}
+
+void b3SortedOverlappingPairCache::cleanOverlappingPair(b3BroadphasePair& pair,b3Dispatcher* dispatcher)
+{
+/* if (pair.m_algorithm)
+ {
+ {
+ pair.m_algorithm->~b3CollisionAlgorithm();
+ dispatcher->freeCollisionAlgorithm(pair.m_algorithm);
+ pair.m_algorithm=0;
+ b3g_removePairs--;
+ }
+ }
+ */
+}
+
+
+void b3SortedOverlappingPairCache::cleanProxyFromPairs(int proxy,b3Dispatcher* dispatcher)
+{
+
+ class CleanPairCallback : public b3OverlapCallback
+ {
+ int m_cleanProxy;
+ b3OverlappingPairCache* m_pairCache;
+ b3Dispatcher* m_dispatcher;
+
+ public:
+ CleanPairCallback(int cleanProxy,b3OverlappingPairCache* pairCache,b3Dispatcher* dispatcher)
+ :m_cleanProxy(cleanProxy),
+ m_pairCache(pairCache),
+ m_dispatcher(dispatcher)
+ {
+ }
+ virtual bool processOverlap(b3BroadphasePair& pair)
+ {
+ if ((pair.x == m_cleanProxy) ||
+ (pair.y == m_cleanProxy))
+ {
+ m_pairCache->cleanOverlappingPair(pair,m_dispatcher);
+ }
+ return false;
+ }
+
+ };
+
+ CleanPairCallback cleanPairs(proxy,this,dispatcher);
+
+ processAllOverlappingPairs(&cleanPairs,dispatcher);
+
+}
+
+
+void b3SortedOverlappingPairCache::removeOverlappingPairsContainingProxy(int proxy,b3Dispatcher* dispatcher)
+{
+
+ class RemovePairCallback : public b3OverlapCallback
+ {
+ int m_obsoleteProxy;
+
+ public:
+ RemovePairCallback(int obsoleteProxy)
+ :m_obsoleteProxy(obsoleteProxy)
+ {
+ }
+ virtual bool processOverlap(b3BroadphasePair& pair)
+ {
+ return ((pair.x == m_obsoleteProxy) ||
+ (pair.y == m_obsoleteProxy));
+ }
+
+ };
+
+ RemovePairCallback removeCallback(proxy);
+
+ processAllOverlappingPairs(&removeCallback,dispatcher);
+}
+
+void b3SortedOverlappingPairCache::sortOverlappingPairs(b3Dispatcher* dispatcher)
+{
+ //should already be sorted
+}
+
diff --git a/thirdparty/bullet/src/Bullet3Collision/BroadPhaseCollision/b3OverlappingPairCache.h b/thirdparty/bullet/src/Bullet3Collision/BroadPhaseCollision/b3OverlappingPairCache.h
new file mode 100644
index 0000000000..f67eb676f1
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Collision/BroadPhaseCollision/b3OverlappingPairCache.h
@@ -0,0 +1,474 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2013 Erwin Coumans 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 B3_OVERLAPPING_PAIR_CACHE_H
+#define B3_OVERLAPPING_PAIR_CACHE_H
+
+#include "Bullet3Common/shared/b3Int2.h"
+#include "Bullet3Common/b3AlignedObjectArray.h"
+
+class b3Dispatcher;
+#include "b3OverlappingPair.h"
+
+
+
+typedef b3AlignedObjectArray<b3BroadphasePair> b3BroadphasePairArray;
+
+struct b3OverlapCallback
+{
+ virtual ~b3OverlapCallback()
+ {}
+ //return true for deletion of the pair
+ virtual bool processOverlap(b3BroadphasePair& pair) = 0;
+
+};
+
+struct b3OverlapFilterCallback
+{
+ virtual ~b3OverlapFilterCallback()
+ {}
+ // return true when pairs need collision
+ virtual bool needBroadphaseCollision(int proxy0,int proxy1) const = 0;
+};
+
+
+
+
+
+
+
+extern int b3g_removePairs;
+extern int b3g_addedPairs;
+extern int b3g_findPairs;
+
+const int B3_NULL_PAIR=0xffffffff;
+
+///The b3OverlappingPairCache provides an interface for overlapping pair management (add, remove, storage), used by the b3BroadphaseInterface broadphases.
+///The b3HashedOverlappingPairCache and b3SortedOverlappingPairCache classes are two implementations.
+class b3OverlappingPairCache
+{
+public:
+ virtual ~b3OverlappingPairCache() {} // this is needed so we can get to the derived class destructor
+
+ virtual b3BroadphasePair* getOverlappingPairArrayPtr() = 0;
+
+ virtual const b3BroadphasePair* getOverlappingPairArrayPtr() const = 0;
+
+ virtual b3BroadphasePairArray& getOverlappingPairArray() = 0;
+
+ virtual void cleanOverlappingPair(b3BroadphasePair& pair,b3Dispatcher* dispatcher) = 0;
+
+ virtual int getNumOverlappingPairs() const = 0;
+
+ virtual void cleanProxyFromPairs(int proxy,b3Dispatcher* dispatcher) = 0;
+
+ virtual void setOverlapFilterCallback(b3OverlapFilterCallback* callback) = 0;
+
+ virtual void processAllOverlappingPairs(b3OverlapCallback*,b3Dispatcher* dispatcher) = 0;
+
+ virtual b3BroadphasePair* findPair(int proxy0, int proxy1) = 0;
+
+ virtual bool hasDeferredRemoval() = 0;
+
+ //virtual void setInternalGhostPairCallback(b3OverlappingPairCallback* ghostPairCallback)=0;
+
+ virtual b3BroadphasePair* addOverlappingPair(int proxy0,int proxy1)=0;
+ virtual void* removeOverlappingPair(int proxy0,int proxy1,b3Dispatcher* dispatcher)=0;
+ virtual void removeOverlappingPairsContainingProxy(int /*proxy0*/,b3Dispatcher* /*dispatcher*/)=0;
+
+ virtual void sortOverlappingPairs(b3Dispatcher* dispatcher) = 0;
+
+
+};
+
+/// Hash-space based Pair Cache, thanks to Erin Catto, Box2D, http://www.box2d.org, and Pierre Terdiman, Codercorner, http://codercorner.com
+class b3HashedOverlappingPairCache : public b3OverlappingPairCache
+{
+ b3BroadphasePairArray m_overlappingPairArray;
+ b3OverlapFilterCallback* m_overlapFilterCallback;
+// bool m_blockedForChanges;
+
+
+public:
+ b3HashedOverlappingPairCache();
+ virtual ~b3HashedOverlappingPairCache();
+
+
+ virtual void removeOverlappingPairsContainingProxy(int proxy,b3Dispatcher* dispatcher);
+
+ virtual void* removeOverlappingPair(int proxy0,int proxy1,b3Dispatcher* dispatcher);
+
+ B3_FORCE_INLINE bool needsBroadphaseCollision(int proxy0,int proxy1) const
+ {
+ if (m_overlapFilterCallback)
+ return m_overlapFilterCallback->needBroadphaseCollision(proxy0,proxy1);
+
+ bool collides = true;//(proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0;
+ //collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask);
+
+ return collides;
+ }
+
+ // Add a pair and return the new pair. If the pair already exists,
+ // no new pair is created and the old one is returned.
+ virtual b3BroadphasePair* addOverlappingPair(int proxy0,int proxy1)
+ {
+ b3g_addedPairs++;
+
+ if (!needsBroadphaseCollision(proxy0,proxy1))
+ return 0;
+
+ return internalAddPair(proxy0,proxy1);
+ }
+
+
+
+ void cleanProxyFromPairs(int proxy,b3Dispatcher* dispatcher);
+
+
+ virtual void processAllOverlappingPairs(b3OverlapCallback*,b3Dispatcher* dispatcher);
+
+ virtual b3BroadphasePair* getOverlappingPairArrayPtr()
+ {
+ return &m_overlappingPairArray[0];
+ }
+
+ const b3BroadphasePair* getOverlappingPairArrayPtr() const
+ {
+ return &m_overlappingPairArray[0];
+ }
+
+ b3BroadphasePairArray& getOverlappingPairArray()
+ {
+ return m_overlappingPairArray;
+ }
+
+ const b3BroadphasePairArray& getOverlappingPairArray() const
+ {
+ return m_overlappingPairArray;
+ }
+
+ void cleanOverlappingPair(b3BroadphasePair& pair,b3Dispatcher* dispatcher);
+
+
+
+ b3BroadphasePair* findPair(int proxy0, int proxy1);
+
+ int GetCount() const { return m_overlappingPairArray.size(); }
+// b3BroadphasePair* GetPairs() { return m_pairs; }
+
+ b3OverlapFilterCallback* getOverlapFilterCallback()
+ {
+ return m_overlapFilterCallback;
+ }
+
+ void setOverlapFilterCallback(b3OverlapFilterCallback* callback)
+ {
+ m_overlapFilterCallback = callback;
+ }
+
+ int getNumOverlappingPairs() const
+ {
+ return m_overlappingPairArray.size();
+ }
+private:
+
+ b3BroadphasePair* internalAddPair(int proxy0,int proxy1);
+
+ void growTables();
+
+ B3_FORCE_INLINE bool equalsPair(const b3BroadphasePair& pair, int proxyId1, int proxyId2)
+ {
+ return pair.x == proxyId1 && pair.y == proxyId2;
+ }
+
+ /*
+ // Thomas Wang's hash, see: http://www.concentric.net/~Ttwang/tech/inthash.htm
+ // This assumes proxyId1 and proxyId2 are 16-bit.
+ B3_FORCE_INLINE int getHash(int proxyId1, int proxyId2)
+ {
+ int key = (proxyId2 << 16) | proxyId1;
+ key = ~key + (key << 15);
+ key = key ^ (key >> 12);
+ key = key + (key << 2);
+ key = key ^ (key >> 4);
+ key = key * 2057;
+ key = key ^ (key >> 16);
+ return key;
+ }
+ */
+
+
+
+ B3_FORCE_INLINE unsigned int getHash(unsigned int proxyId1, unsigned int proxyId2)
+ {
+ int key = static_cast<int>(((unsigned int)proxyId1) | (((unsigned int)proxyId2) <<16));
+ // Thomas Wang's hash
+
+ key += ~(key << 15);
+ key ^= (key >> 10);
+ key += (key << 3);
+ key ^= (key >> 6);
+ key += ~(key << 11);
+ key ^= (key >> 16);
+ return static_cast<unsigned int>(key);
+ }
+
+
+
+
+
+ B3_FORCE_INLINE b3BroadphasePair* internalFindPair(int proxy0, int proxy1, int hash)
+ {
+ int proxyId1 = proxy0;
+ int proxyId2 = proxy1;
+ #if 0 // wrong, 'equalsPair' use unsorted uids, copy-past devil striked again. Nat.
+ if (proxyId1 > proxyId2)
+ b3Swap(proxyId1, proxyId2);
+ #endif
+
+ int index = m_hashTable[hash];
+
+ while( index != B3_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyId1, proxyId2) == false)
+ {
+ index = m_next[index];
+ }
+
+ if ( index == B3_NULL_PAIR )
+ {
+ return NULL;
+ }
+
+ b3Assert(index < m_overlappingPairArray.size());
+
+ return &m_overlappingPairArray[index];
+ }
+
+ virtual bool hasDeferredRemoval()
+ {
+ return false;
+ }
+
+/* virtual void setInternalGhostPairCallback(b3OverlappingPairCallback* ghostPairCallback)
+ {
+ m_ghostPairCallback = ghostPairCallback;
+ }
+ */
+
+ virtual void sortOverlappingPairs(b3Dispatcher* dispatcher);
+
+
+protected:
+
+ b3AlignedObjectArray<int> m_hashTable;
+ b3AlignedObjectArray<int> m_next;
+// b3OverlappingPairCallback* m_ghostPairCallback;
+
+};
+
+
+
+
+///b3SortedOverlappingPairCache maintains the objects with overlapping AABB
+///Typically managed by the Broadphase, Axis3Sweep or b3SimpleBroadphase
+class b3SortedOverlappingPairCache : public b3OverlappingPairCache
+{
+ protected:
+ //avoid brute-force finding all the time
+ b3BroadphasePairArray m_overlappingPairArray;
+
+ //during the dispatch, check that user doesn't destroy/create proxy
+ bool m_blockedForChanges;
+
+ ///by default, do the removal during the pair traversal
+ bool m_hasDeferredRemoval;
+
+ //if set, use the callback instead of the built in filter in needBroadphaseCollision
+ b3OverlapFilterCallback* m_overlapFilterCallback;
+
+// b3OverlappingPairCallback* m_ghostPairCallback;
+
+ public:
+
+ b3SortedOverlappingPairCache();
+ virtual ~b3SortedOverlappingPairCache();
+
+ virtual void processAllOverlappingPairs(b3OverlapCallback*,b3Dispatcher* dispatcher);
+
+ void* removeOverlappingPair(int proxy0,int proxy1,b3Dispatcher* dispatcher);
+
+ void cleanOverlappingPair(b3BroadphasePair& pair,b3Dispatcher* dispatcher);
+
+ b3BroadphasePair* addOverlappingPair(int proxy0,int proxy1);
+
+ b3BroadphasePair* findPair(int proxy0,int proxy1);
+
+
+ void cleanProxyFromPairs(int proxy,b3Dispatcher* dispatcher);
+
+ virtual void removeOverlappingPairsContainingProxy(int proxy,b3Dispatcher* dispatcher);
+
+
+ inline bool needsBroadphaseCollision(int proxy0,int proxy1) const
+ {
+ if (m_overlapFilterCallback)
+ return m_overlapFilterCallback->needBroadphaseCollision(proxy0,proxy1);
+
+ bool collides = true;//(proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0;
+ //collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask);
+
+ return collides;
+ }
+
+ b3BroadphasePairArray& getOverlappingPairArray()
+ {
+ return m_overlappingPairArray;
+ }
+
+ const b3BroadphasePairArray& getOverlappingPairArray() const
+ {
+ return m_overlappingPairArray;
+ }
+
+
+
+
+ b3BroadphasePair* getOverlappingPairArrayPtr()
+ {
+ return &m_overlappingPairArray[0];
+ }
+
+ const b3BroadphasePair* getOverlappingPairArrayPtr() const
+ {
+ return &m_overlappingPairArray[0];
+ }
+
+ int getNumOverlappingPairs() const
+ {
+ return m_overlappingPairArray.size();
+ }
+
+ b3OverlapFilterCallback* getOverlapFilterCallback()
+ {
+ return m_overlapFilterCallback;
+ }
+
+ void setOverlapFilterCallback(b3OverlapFilterCallback* callback)
+ {
+ m_overlapFilterCallback = callback;
+ }
+
+ virtual bool hasDeferredRemoval()
+ {
+ return m_hasDeferredRemoval;
+ }
+
+/* virtual void setInternalGhostPairCallback(b3OverlappingPairCallback* ghostPairCallback)
+ {
+ m_ghostPairCallback = ghostPairCallback;
+ }
+ */
+ virtual void sortOverlappingPairs(b3Dispatcher* dispatcher);
+
+
+};
+
+
+
+///b3NullPairCache skips add/removal of overlapping pairs. Userful for benchmarking and unit testing.
+class b3NullPairCache : public b3OverlappingPairCache
+{
+
+ b3BroadphasePairArray m_overlappingPairArray;
+
+public:
+
+ virtual b3BroadphasePair* getOverlappingPairArrayPtr()
+ {
+ return &m_overlappingPairArray[0];
+ }
+ const b3BroadphasePair* getOverlappingPairArrayPtr() const
+ {
+ return &m_overlappingPairArray[0];
+ }
+ b3BroadphasePairArray& getOverlappingPairArray()
+ {
+ return m_overlappingPairArray;
+ }
+
+ virtual void cleanOverlappingPair(b3BroadphasePair& /*pair*/,b3Dispatcher* /*dispatcher*/)
+ {
+
+ }
+
+ virtual int getNumOverlappingPairs() const
+ {
+ return 0;
+ }
+
+ virtual void cleanProxyFromPairs(int /*proxy*/,b3Dispatcher* /*dispatcher*/)
+ {
+
+ }
+
+ virtual void setOverlapFilterCallback(b3OverlapFilterCallback* /*callback*/)
+ {
+ }
+
+ virtual void processAllOverlappingPairs(b3OverlapCallback*,b3Dispatcher* /*dispatcher*/)
+ {
+ }
+
+ virtual b3BroadphasePair* findPair(int /*proxy0*/, int /*proxy1*/)
+ {
+ return 0;
+ }
+
+ virtual bool hasDeferredRemoval()
+ {
+ return true;
+ }
+
+// virtual void setInternalGhostPairCallback(b3OverlappingPairCallback* /* ghostPairCallback */)
+// {
+//
+// }
+
+ virtual b3BroadphasePair* addOverlappingPair(int /*proxy0*/,int /*proxy1*/)
+ {
+ return 0;
+ }
+
+ virtual void* removeOverlappingPair(int /*proxy0*/,int /*proxy1*/,b3Dispatcher* /*dispatcher*/)
+ {
+ return 0;
+ }
+
+ virtual void removeOverlappingPairsContainingProxy(int /*proxy0*/,b3Dispatcher* /*dispatcher*/)
+ {
+ }
+
+ virtual void sortOverlappingPairs(b3Dispatcher* dispatcher)
+ {
+ (void) dispatcher;
+ }
+
+
+};
+
+
+#endif //B3_OVERLAPPING_PAIR_CACHE_H
+
+
diff --git a/thirdparty/bullet/src/Bullet3Collision/BroadPhaseCollision/shared/b3Aabb.h b/thirdparty/bullet/src/Bullet3Collision/BroadPhaseCollision/shared/b3Aabb.h
new file mode 100644
index 0000000000..7f9bf990bf
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Collision/BroadPhaseCollision/shared/b3Aabb.h
@@ -0,0 +1,59 @@
+
+#ifndef B3_AABB_H
+#define B3_AABB_H
+
+
+#include "Bullet3Common/shared/b3Float4.h"
+#include "Bullet3Common/shared/b3Mat3x3.h"
+
+typedef struct b3Aabb b3Aabb_t;
+
+struct b3Aabb
+{
+ union
+ {
+ float m_min[4];
+ b3Float4 m_minVec;
+ int m_minIndices[4];
+ };
+ union
+ {
+ float m_max[4];
+ b3Float4 m_maxVec;
+ int m_signedMaxIndices[4];
+ };
+};
+
+inline void b3TransformAabb2(b3Float4ConstArg localAabbMin,b3Float4ConstArg localAabbMax, float margin,
+ b3Float4ConstArg pos,
+ b3QuatConstArg orn,
+ b3Float4* aabbMinOut,b3Float4* aabbMaxOut)
+{
+ b3Float4 localHalfExtents = 0.5f*(localAabbMax-localAabbMin);
+ localHalfExtents+=b3MakeFloat4(margin,margin,margin,0.f);
+ b3Float4 localCenter = 0.5f*(localAabbMax+localAabbMin);
+ b3Mat3x3 m;
+ m = b3QuatGetRotationMatrix(orn);
+ b3Mat3x3 abs_b = b3AbsoluteMat3x3(m);
+ b3Float4 center = b3TransformPoint(localCenter,pos,orn);
+
+ b3Float4 extent = b3MakeFloat4(b3Dot3F4(localHalfExtents,b3GetRow(abs_b,0)),
+ b3Dot3F4(localHalfExtents,b3GetRow(abs_b,1)),
+ b3Dot3F4(localHalfExtents,b3GetRow(abs_b,2)),
+ 0.f);
+ *aabbMinOut = center-extent;
+ *aabbMaxOut = center+extent;
+}
+
+/// conservative test for overlap between two aabbs
+inline bool b3TestAabbAgainstAabb(b3Float4ConstArg aabbMin1,b3Float4ConstArg aabbMax1,
+ b3Float4ConstArg aabbMin2, b3Float4ConstArg aabbMax2)
+{
+ bool overlap = true;
+ overlap = (aabbMin1.x > aabbMax2.x || aabbMax1.x < aabbMin2.x) ? false : overlap;
+ overlap = (aabbMin1.z > aabbMax2.z || aabbMax1.z < aabbMin2.z) ? false : overlap;
+ overlap = (aabbMin1.y > aabbMax2.y || aabbMax1.y < aabbMin2.y) ? false : overlap;
+ return overlap;
+}
+
+#endif //B3_AABB_H
diff --git a/thirdparty/bullet/src/Bullet3Collision/CMakeLists.txt b/thirdparty/bullet/src/Bullet3Collision/CMakeLists.txt
new file mode 100644
index 0000000000..130095cc04
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Collision/CMakeLists.txt
@@ -0,0 +1,93 @@
+
+INCLUDE_DIRECTORIES(
+ ${BULLET_PHYSICS_SOURCE_DIR}/src
+)
+
+SET(Bullet3Collision_SRCS
+ BroadPhaseCollision/b3DynamicBvh.cpp
+ BroadPhaseCollision/b3DynamicBvhBroadphase.cpp
+ BroadPhaseCollision/b3OverlappingPairCache.cpp
+ NarrowPhaseCollision/b3ConvexUtility.cpp
+ NarrowPhaseCollision/b3CpuNarrowPhase.cpp
+)
+
+SET(Bullet3CollisionBroadPhase_HDRS
+ BroadPhaseCollision/b3BroadphaseCallback.h
+ BroadPhaseCollision/b3DynamicBvh.h
+ BroadPhaseCollision/b3DynamicBvhBroadphase.h
+ BroadPhaseCollision/b3OverlappingPair.h
+ BroadPhaseCollision/b3OverlappingPairCache.h
+)
+SET(Bullet3CollisionBroadPhaseShared_HDRS
+ BroadPhaseCollision/shared/b3Aabb.h
+)
+
+SET(Bullet3CollisionNarrowPhase_HDRS
+ NarrowPhaseCollision/b3Config.h
+ NarrowPhaseCollision/b3Contact4.h
+ NarrowPhaseCollision/b3ConvexUtility.h
+ NarrowPhaseCollision/b3CpuNarrowPhase.h
+ NarrowPhaseCollision/b3RaycastInfo.h
+ NarrowPhaseCollision/b3RigidBodyCL.h
+)
+SET(Bullet3CollisionNarrowPhaseShared_HDRS
+
+ NarrowPhaseCollision/shared/b3BvhSubtreeInfoData.h
+ NarrowPhaseCollision/shared/b3BvhTraversal.h
+ NarrowPhaseCollision/shared/b3ClipFaces.h
+ NarrowPhaseCollision/shared/b3Collidable.h
+ NarrowPhaseCollision/shared/b3Contact4Data.h
+ NarrowPhaseCollision/shared/b3ContactConvexConvexSAT.h
+ NarrowPhaseCollision/shared/b3ContactSphereSphere.h
+ NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h
+ NarrowPhaseCollision/shared/b3FindConcaveSatAxis.h
+ NarrowPhaseCollision/shared/b3FindSeparatingAxis.h
+ NarrowPhaseCollision/shared/b3MprPenetration.h
+ NarrowPhaseCollision/shared/b3NewContactReduction.h
+ NarrowPhaseCollision/shared/b3QuantizedBvhNodeData.h
+ NarrowPhaseCollision/shared/b3ReduceContacts.h
+ NarrowPhaseCollision/shared/b3RigidBodyData.h
+ NarrowPhaseCollision/shared/b3UpdateAabbs.h
+)
+
+SET(Bullet3Collision_HDRS
+ ${Bullet3CollisionBroadPhase_HDRS}
+ ${Bullet3CollisionBroadPhaseShared_HDRS}
+ ${Bullet3CollisionNarrowPhaseShared_HDRS}
+ ${Bullet3CollisionNarrowPhase_HDRS}
+)
+
+ADD_LIBRARY(Bullet3Collision ${Bullet3Collision_SRCS} ${Bullet3Collision_HDRS})
+if (BUILD_SHARED_LIBS)
+ target_link_libraries(Bullet3Collision Bullet3Geometry)
+endif ()
+SET_TARGET_PROPERTIES(Bullet3Collision PROPERTIES VERSION ${BULLET_VERSION})
+SET_TARGET_PROPERTIES(Bullet3Collision PROPERTIES SOVERSION ${BULLET_VERSION})
+
+IF (INSTALL_LIBS)
+ IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
+ #FILES_MATCHING requires CMake 2.6
+ IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
+ IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+ INSTALL(TARGETS Bullet3Collision DESTINATION .)
+ ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+ INSTALL(TARGETS Bullet3Collision
+ RUNTIME DESTINATION bin
+ LIBRARY DESTINATION lib${LIB_SUFFIX}
+ ARCHIVE DESTINATION lib${LIB_SUFFIX})
+ INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.h" PATTERN
+".svn" EXCLUDE PATTERN "CMakeFiles" EXCLUDE)
+ ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+ ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
+
+ IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+ SET_TARGET_PROPERTIES(Bullet3Collision PROPERTIES FRAMEWORK true)
+ SET_TARGET_PROPERTIES(Bullet3Collision PROPERTIES PUBLIC_HEADER "${Bullet3Collision_HDRS}")
+ # Have to list out sub-directories manually:
+ #todo
+ #SET_PROPERTY(SOURCE ${Bullet3CollisionBroadPhase_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/BroadPhaseCollision)
+
+ ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+ ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
+ENDIF (INSTALL_LIBS)
diff --git a/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/b3Config.h b/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/b3Config.h
new file mode 100644
index 0000000000..65d4a21613
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/b3Config.h
@@ -0,0 +1,41 @@
+#ifndef B3_CONFIG_H
+#define B3_CONFIG_H
+
+struct b3Config
+{
+ int m_maxConvexBodies;
+ int m_maxConvexShapes;
+ int m_maxBroadphasePairs;
+ int m_maxContactCapacity;
+ int m_compoundPairCapacity;
+
+ int m_maxVerticesPerFace;
+ int m_maxFacesPerShape;
+ int m_maxConvexVertices;
+ int m_maxConvexIndices;
+ int m_maxConvexUniqueEdges;
+
+ int m_maxCompoundChildShapes;
+
+ int m_maxTriConvexPairCapacity;
+
+ b3Config()
+ :m_maxConvexBodies(128*1024),
+ m_maxVerticesPerFace(64),
+ m_maxFacesPerShape(12),
+ m_maxConvexVertices(8192),
+ m_maxConvexIndices(81920),
+ m_maxConvexUniqueEdges(8192),
+ m_maxCompoundChildShapes(8192),
+ m_maxTriConvexPairCapacity(256*1024)
+ {
+ m_maxConvexShapes = m_maxConvexBodies;
+ m_maxBroadphasePairs = 16*m_maxConvexBodies;
+ m_maxContactCapacity = m_maxBroadphasePairs;
+ m_compoundPairCapacity = 1024*1024;
+ }
+};
+
+
+#endif//B3_CONFIG_H
+
diff --git a/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/b3Contact4.h b/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/b3Contact4.h
new file mode 100644
index 0000000000..fb25165673
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/b3Contact4.h
@@ -0,0 +1,46 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2013 Erwin Coumans 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 B3_CONTACT4_H
+#define B3_CONTACT4_H
+
+#include "Bullet3Common/b3Vector3.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h"
+
+B3_ATTRIBUTE_ALIGNED16(struct) b3Contact4 : public b3Contact4Data
+{
+ B3_DECLARE_ALIGNED_ALLOCATOR();
+
+ int getBodyA()const {return abs(m_bodyAPtrAndSignBit);}
+ int getBodyB()const {return abs(m_bodyBPtrAndSignBit);}
+ bool isBodyAFixed()const { return m_bodyAPtrAndSignBit<0;}
+ bool isBodyBFixed()const { return m_bodyBPtrAndSignBit<0;}
+ // todo. make it safer
+ int& getBatchIdx() { return m_batchIdx; }
+ const int& getBatchIdx() const { return m_batchIdx; }
+ float getRestituitionCoeff() const { return ((float)m_restituitionCoeffCmp/(float)0xffff); }
+ void setRestituitionCoeff( float c ) { b3Assert( c >= 0.f && c <= 1.f ); m_restituitionCoeffCmp = (unsigned short)(c*0xffff); }
+ float getFrictionCoeff() const { return ((float)m_frictionCoeffCmp/(float)0xffff); }
+ void setFrictionCoeff( float c ) { b3Assert( c >= 0.f && c <= 1.f ); m_frictionCoeffCmp = (unsigned short)(c*0xffff); }
+
+ //float& getNPoints() { return m_worldNormal[3]; }
+ int getNPoints() const { return (int) m_worldNormalOnB.w; }
+
+ float getPenetration(int idx) const { return m_worldPosB[idx].w; }
+
+ bool isInvalid() const { return (getBodyA()==0 || getBodyB()==0); }
+};
+
+#endif //B3_CONTACT4_H
diff --git a/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/b3ConvexUtility.cpp b/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/b3ConvexUtility.cpp
new file mode 100644
index 0000000000..55706fa631
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/b3ConvexUtility.cpp
@@ -0,0 +1,520 @@
+/*
+Copyright (c) 2012 Advanced Micro Devices, Inc.
+
+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.
+*/
+//Originally written by Erwin Coumans
+
+
+#include "b3ConvexUtility.h"
+#include "Bullet3Geometry/b3ConvexHullComputer.h"
+#include "Bullet3Geometry/b3GrahamScan2dConvexHull.h"
+#include "Bullet3Common/b3Quaternion.h"
+#include "Bullet3Common/b3HashMap.h"
+
+
+
+
+
+b3ConvexUtility::~b3ConvexUtility()
+{
+}
+
+bool b3ConvexUtility::initializePolyhedralFeatures(const b3Vector3* orgVertices, int numPoints, bool mergeCoplanarTriangles)
+{
+
+
+
+ b3ConvexHullComputer conv;
+ conv.compute(&orgVertices[0].getX(), sizeof(b3Vector3),numPoints,0.f,0.f);
+
+ b3AlignedObjectArray<b3Vector3> faceNormals;
+ int numFaces = conv.faces.size();
+ faceNormals.resize(numFaces);
+ b3ConvexHullComputer* convexUtil = &conv;
+
+
+ b3AlignedObjectArray<b3MyFace> tmpFaces;
+ tmpFaces.resize(numFaces);
+
+ int numVertices = convexUtil->vertices.size();
+ m_vertices.resize(numVertices);
+ for (int p=0;p<numVertices;p++)
+ {
+ m_vertices[p] = convexUtil->vertices[p];
+ }
+
+
+ for (int i=0;i<numFaces;i++)
+ {
+ int face = convexUtil->faces[i];
+ //printf("face=%d\n",face);
+ const b3ConvexHullComputer::Edge* firstEdge = &convexUtil->edges[face];
+ const b3ConvexHullComputer::Edge* edge = firstEdge;
+
+ b3Vector3 edges[3];
+ int numEdges = 0;
+ //compute face normals
+
+ do
+ {
+
+ int src = edge->getSourceVertex();
+ tmpFaces[i].m_indices.push_back(src);
+ int targ = edge->getTargetVertex();
+ b3Vector3 wa = convexUtil->vertices[src];
+
+ b3Vector3 wb = convexUtil->vertices[targ];
+ b3Vector3 newEdge = wb-wa;
+ newEdge.normalize();
+ if (numEdges<2)
+ edges[numEdges++] = newEdge;
+
+ edge = edge->getNextEdgeOfFace();
+ } while (edge!=firstEdge);
+
+ b3Scalar planeEq = 1e30f;
+
+
+ if (numEdges==2)
+ {
+ faceNormals[i] = edges[0].cross(edges[1]);
+ faceNormals[i].normalize();
+ tmpFaces[i].m_plane[0] = faceNormals[i].getX();
+ tmpFaces[i].m_plane[1] = faceNormals[i].getY();
+ tmpFaces[i].m_plane[2] = faceNormals[i].getZ();
+ tmpFaces[i].m_plane[3] = planeEq;
+
+ }
+ else
+ {
+ b3Assert(0);//degenerate?
+ faceNormals[i].setZero();
+ }
+
+ for (int v=0;v<tmpFaces[i].m_indices.size();v++)
+ {
+ b3Scalar eq = m_vertices[tmpFaces[i].m_indices[v]].dot(faceNormals[i]);
+ if (planeEq>eq)
+ {
+ planeEq=eq;
+ }
+ }
+ tmpFaces[i].m_plane[3] = -planeEq;
+ }
+
+ //merge coplanar faces and copy them to m_polyhedron
+
+ b3Scalar faceWeldThreshold= 0.999f;
+ b3AlignedObjectArray<int> todoFaces;
+ for (int i=0;i<tmpFaces.size();i++)
+ todoFaces.push_back(i);
+
+ while (todoFaces.size())
+ {
+ b3AlignedObjectArray<int> coplanarFaceGroup;
+ int refFace = todoFaces[todoFaces.size()-1];
+
+ coplanarFaceGroup.push_back(refFace);
+ b3MyFace& faceA = tmpFaces[refFace];
+ todoFaces.pop_back();
+
+ b3Vector3 faceNormalA = b3MakeVector3(faceA.m_plane[0],faceA.m_plane[1],faceA.m_plane[2]);
+ for (int j=todoFaces.size()-1;j>=0;j--)
+ {
+ int i = todoFaces[j];
+ b3MyFace& faceB = tmpFaces[i];
+ b3Vector3 faceNormalB = b3MakeVector3(faceB.m_plane[0],faceB.m_plane[1],faceB.m_plane[2]);
+ if (faceNormalA.dot(faceNormalB)>faceWeldThreshold)
+ {
+ coplanarFaceGroup.push_back(i);
+ todoFaces.remove(i);
+ }
+ }
+
+
+ bool did_merge = false;
+ if (coplanarFaceGroup.size()>1)
+ {
+ //do the merge: use Graham Scan 2d convex hull
+
+ b3AlignedObjectArray<b3GrahamVector3> orgpoints;
+ b3Vector3 averageFaceNormal = b3MakeVector3(0,0,0);
+
+ for (int i=0;i<coplanarFaceGroup.size();i++)
+ {
+// m_polyhedron->m_faces.push_back(tmpFaces[coplanarFaceGroup[i]]);
+
+ b3MyFace& face = tmpFaces[coplanarFaceGroup[i]];
+ b3Vector3 faceNormal = b3MakeVector3(face.m_plane[0],face.m_plane[1],face.m_plane[2]);
+ averageFaceNormal+=faceNormal;
+ for (int f=0;f<face.m_indices.size();f++)
+ {
+ int orgIndex = face.m_indices[f];
+ b3Vector3 pt = m_vertices[orgIndex];
+
+ bool found = false;
+
+ for (int i=0;i<orgpoints.size();i++)
+ {
+ //if ((orgpoints[i].m_orgIndex == orgIndex) || ((rotatedPt-orgpoints[i]).length2()<0.0001))
+ if (orgpoints[i].m_orgIndex == orgIndex)
+ {
+ found=true;
+ break;
+ }
+ }
+ if (!found)
+ orgpoints.push_back(b3GrahamVector3(pt,orgIndex));
+ }
+ }
+
+
+
+ b3MyFace combinedFace;
+ for (int i=0;i<4;i++)
+ combinedFace.m_plane[i] = tmpFaces[coplanarFaceGroup[0]].m_plane[i];
+
+ b3AlignedObjectArray<b3GrahamVector3> hull;
+
+ averageFaceNormal.normalize();
+ b3GrahamScanConvexHull2D(orgpoints,hull,averageFaceNormal);
+
+ for (int i=0;i<hull.size();i++)
+ {
+ combinedFace.m_indices.push_back(hull[i].m_orgIndex);
+ for(int k = 0; k < orgpoints.size(); k++)
+ {
+ if(orgpoints[k].m_orgIndex == hull[i].m_orgIndex)
+ {
+ orgpoints[k].m_orgIndex = -1; // invalidate...
+ break;
+ }
+ }
+ }
+
+ // are there rejected vertices?
+ bool reject_merge = false;
+
+
+
+ for(int i = 0; i < orgpoints.size(); i++) {
+ if(orgpoints[i].m_orgIndex == -1)
+ continue; // this is in the hull...
+ // this vertex is rejected -- is anybody else using this vertex?
+ for(int j = 0; j < tmpFaces.size(); j++) {
+
+ b3MyFace& face = tmpFaces[j];
+ // is this a face of the current coplanar group?
+ bool is_in_current_group = false;
+ for(int k = 0; k < coplanarFaceGroup.size(); k++) {
+ if(coplanarFaceGroup[k] == j) {
+ is_in_current_group = true;
+ break;
+ }
+ }
+ if(is_in_current_group) // ignore this face...
+ continue;
+ // does this face use this rejected vertex?
+ for(int v = 0; v < face.m_indices.size(); v++) {
+ if(face.m_indices[v] == orgpoints[i].m_orgIndex) {
+ // this rejected vertex is used in another face -- reject merge
+ reject_merge = true;
+ break;
+ }
+ }
+ if(reject_merge)
+ break;
+ }
+ if(reject_merge)
+ break;
+ }
+
+ if (!reject_merge)
+ {
+ // do this merge!
+ did_merge = true;
+ m_faces.push_back(combinedFace);
+ }
+ }
+ if(!did_merge)
+ {
+ for (int i=0;i<coplanarFaceGroup.size();i++)
+ {
+ b3MyFace face = tmpFaces[coplanarFaceGroup[i]];
+ m_faces.push_back(face);
+ }
+
+ }
+
+
+
+ }
+
+ initialize();
+
+ return true;
+}
+
+
+
+
+
+
+inline bool IsAlmostZero(const b3Vector3& v)
+{
+ if(fabsf(v.getX())>1e-6 || fabsf(v.getY())>1e-6 || fabsf(v.getZ())>1e-6) return false;
+ return true;
+}
+
+struct b3InternalVertexPair
+{
+ b3InternalVertexPair(short int v0,short int v1)
+ :m_v0(v0),
+ m_v1(v1)
+ {
+ if (m_v1>m_v0)
+ b3Swap(m_v0,m_v1);
+ }
+ short int m_v0;
+ short int m_v1;
+ int getHash() const
+ {
+ return m_v0+(m_v1<<16);
+ }
+ bool equals(const b3InternalVertexPair& other) const
+ {
+ return m_v0==other.m_v0 && m_v1==other.m_v1;
+ }
+};
+
+struct b3InternalEdge
+{
+ b3InternalEdge()
+ :m_face0(-1),
+ m_face1(-1)
+ {
+ }
+ short int m_face0;
+ short int m_face1;
+};
+
+//
+
+#ifdef TEST_INTERNAL_OBJECTS
+bool b3ConvexUtility::testContainment() const
+{
+ for(int p=0;p<8;p++)
+ {
+ b3Vector3 LocalPt;
+ if(p==0) LocalPt = m_localCenter + b3Vector3(m_extents[0], m_extents[1], m_extents[2]);
+ else if(p==1) LocalPt = m_localCenter + b3Vector3(m_extents[0], m_extents[1], -m_extents[2]);
+ else if(p==2) LocalPt = m_localCenter + b3Vector3(m_extents[0], -m_extents[1], m_extents[2]);
+ else if(p==3) LocalPt = m_localCenter + b3Vector3(m_extents[0], -m_extents[1], -m_extents[2]);
+ else if(p==4) LocalPt = m_localCenter + b3Vector3(-m_extents[0], m_extents[1], m_extents[2]);
+ else if(p==5) LocalPt = m_localCenter + b3Vector3(-m_extents[0], m_extents[1], -m_extents[2]);
+ else if(p==6) LocalPt = m_localCenter + b3Vector3(-m_extents[0], -m_extents[1], m_extents[2]);
+ else if(p==7) LocalPt = m_localCenter + b3Vector3(-m_extents[0], -m_extents[1], -m_extents[2]);
+
+ for(int i=0;i<m_faces.size();i++)
+ {
+ const b3Vector3 Normal(m_faces[i].m_plane[0], m_faces[i].m_plane[1], m_faces[i].m_plane[2]);
+ const b3Scalar d = LocalPt.dot(Normal) + m_faces[i].m_plane[3];
+ if(d>0.0f)
+ return false;
+ }
+ }
+ return true;
+}
+#endif
+
+void b3ConvexUtility::initialize()
+{
+
+ b3HashMap<b3InternalVertexPair,b3InternalEdge> edges;
+
+ b3Scalar TotalArea = 0.0f;
+
+ m_localCenter.setValue(0, 0, 0);
+ for(int i=0;i<m_faces.size();i++)
+ {
+ int numVertices = m_faces[i].m_indices.size();
+ int NbTris = numVertices;
+ for(int j=0;j<NbTris;j++)
+ {
+ int k = (j+1)%numVertices;
+ b3InternalVertexPair vp(m_faces[i].m_indices[j],m_faces[i].m_indices[k]);
+ b3InternalEdge* edptr = edges.find(vp);
+ b3Vector3 edge = m_vertices[vp.m_v1]-m_vertices[vp.m_v0];
+ edge.normalize();
+
+ bool found = false;
+ b3Vector3 diff,diff2;
+
+ for (int p=0;p<m_uniqueEdges.size();p++)
+ {
+ diff = m_uniqueEdges[p]-edge;
+ diff2 = m_uniqueEdges[p]+edge;
+
+ // if ((diff.length2()==0.f) ||
+ // (diff2.length2()==0.f))
+
+ if (IsAlmostZero(diff) ||
+ IsAlmostZero(diff2))
+ {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found)
+ {
+ m_uniqueEdges.push_back(edge);
+ }
+
+ if (edptr)
+ {
+ //TBD: figure out why I added this assert
+// b3Assert(edptr->m_face0>=0);
+ // b3Assert(edptr->m_face1<0);
+ edptr->m_face1 = i;
+ } else
+ {
+ b3InternalEdge ed;
+ ed.m_face0 = i;
+ edges.insert(vp,ed);
+ }
+ }
+ }
+
+#ifdef USE_CONNECTED_FACES
+ for(int i=0;i<m_faces.size();i++)
+ {
+ int numVertices = m_faces[i].m_indices.size();
+ m_faces[i].m_connectedFaces.resize(numVertices);
+
+ for(int j=0;j<numVertices;j++)
+ {
+ int k = (j+1)%numVertices;
+ b3InternalVertexPair vp(m_faces[i].m_indices[j],m_faces[i].m_indices[k]);
+ b3InternalEdge* edptr = edges.find(vp);
+ b3Assert(edptr);
+ b3Assert(edptr->m_face0>=0);
+ b3Assert(edptr->m_face1>=0);
+
+ int connectedFace = (edptr->m_face0==i)?edptr->m_face1:edptr->m_face0;
+ m_faces[i].m_connectedFaces[j] = connectedFace;
+ }
+ }
+#endif//USE_CONNECTED_FACES
+
+ for(int i=0;i<m_faces.size();i++)
+ {
+ int numVertices = m_faces[i].m_indices.size();
+ int NbTris = numVertices-2;
+
+ const b3Vector3& p0 = m_vertices[m_faces[i].m_indices[0]];
+ for(int j=1;j<=NbTris;j++)
+ {
+ int k = (j+1)%numVertices;
+ const b3Vector3& p1 = m_vertices[m_faces[i].m_indices[j]];
+ const b3Vector3& p2 = m_vertices[m_faces[i].m_indices[k]];
+ b3Scalar Area = ((p0 - p1).cross(p0 - p2)).length() * 0.5f;
+ b3Vector3 Center = (p0+p1+p2)/3.0f;
+ m_localCenter += Area * Center;
+ TotalArea += Area;
+ }
+ }
+ m_localCenter /= TotalArea;
+
+
+
+
+#ifdef TEST_INTERNAL_OBJECTS
+ if(1)
+ {
+ m_radius = FLT_MAX;
+ for(int i=0;i<m_faces.size();i++)
+ {
+ const b3Vector3 Normal(m_faces[i].m_plane[0], m_faces[i].m_plane[1], m_faces[i].m_plane[2]);
+ const b3Scalar dist = b3Fabs(m_localCenter.dot(Normal) + m_faces[i].m_plane[3]);
+ if(dist<m_radius)
+ m_radius = dist;
+ }
+
+
+ b3Scalar MinX = FLT_MAX;
+ b3Scalar MinY = FLT_MAX;
+ b3Scalar MinZ = FLT_MAX;
+ b3Scalar MaxX = -FLT_MAX;
+ b3Scalar MaxY = -FLT_MAX;
+ b3Scalar MaxZ = -FLT_MAX;
+ for(int i=0; i<m_vertices.size(); i++)
+ {
+ const b3Vector3& pt = m_vertices[i];
+ if(pt.getX()<MinX) MinX = pt.getX();
+ if(pt.getX()>MaxX) MaxX = pt.getX();
+ if(pt.getY()<MinY) MinY = pt.getY();
+ if(pt.getY()>MaxY) MaxY = pt.getY();
+ if(pt.getZ()<MinZ) MinZ = pt.getZ();
+ if(pt.getZ()>MaxZ) MaxZ = pt.getZ();
+ }
+ mC.setValue(MaxX+MinX, MaxY+MinY, MaxZ+MinZ);
+ mE.setValue(MaxX-MinX, MaxY-MinY, MaxZ-MinZ);
+
+
+
+// const b3Scalar r = m_radius / sqrtf(2.0f);
+ const b3Scalar r = m_radius / sqrtf(3.0f);
+ const int LargestExtent = mE.maxAxis();
+ const b3Scalar Step = (mE[LargestExtent]*0.5f - r)/1024.0f;
+ m_extents[0] = m_extents[1] = m_extents[2] = r;
+ m_extents[LargestExtent] = mE[LargestExtent]*0.5f;
+ bool FoundBox = false;
+ for(int j=0;j<1024;j++)
+ {
+ if(testContainment())
+ {
+ FoundBox = true;
+ break;
+ }
+
+ m_extents[LargestExtent] -= Step;
+ }
+ if(!FoundBox)
+ {
+ m_extents[0] = m_extents[1] = m_extents[2] = r;
+ }
+ else
+ {
+ // Refine the box
+ const b3Scalar Step = (m_radius - r)/1024.0f;
+ const int e0 = (1<<LargestExtent) & 3;
+ const int e1 = (1<<e0) & 3;
+
+ for(int j=0;j<1024;j++)
+ {
+ const b3Scalar Saved0 = m_extents[e0];
+ const b3Scalar Saved1 = m_extents[e1];
+ m_extents[e0] += Step;
+ m_extents[e1] += Step;
+
+ if(!testContainment())
+ {
+ m_extents[e0] = Saved0;
+ m_extents[e1] = Saved1;
+ break;
+ }
+ }
+ }
+ }
+#endif
+}
diff --git a/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/b3ConvexUtility.h b/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/b3ConvexUtility.h
new file mode 100644
index 0000000000..86c4151f8c
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/b3ConvexUtility.h
@@ -0,0 +1,62 @@
+
+/*
+Copyright (c) 2012 Advanced Micro Devices, Inc.
+
+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.
+*/
+//Originally written by Erwin Coumans
+
+#ifndef _BT_CONVEX_UTILITY_H
+#define _BT_CONVEX_UTILITY_H
+
+#include "Bullet3Common/b3AlignedObjectArray.h"
+#include "Bullet3Common/b3Transform.h"
+
+
+
+
+struct b3MyFace
+{
+ b3AlignedObjectArray<int> m_indices;
+ b3Scalar m_plane[4];
+};
+
+B3_ATTRIBUTE_ALIGNED16(class) b3ConvexUtility
+{
+ public:
+ B3_DECLARE_ALIGNED_ALLOCATOR();
+
+ b3Vector3 m_localCenter;
+ b3Vector3 m_extents;
+ b3Vector3 mC;
+ b3Vector3 mE;
+ b3Scalar m_radius;
+
+ b3AlignedObjectArray<b3Vector3> m_vertices;
+ b3AlignedObjectArray<b3MyFace> m_faces;
+ b3AlignedObjectArray<b3Vector3> m_uniqueEdges;
+
+
+ b3ConvexUtility()
+ {
+ }
+ virtual ~b3ConvexUtility();
+
+ bool initializePolyhedralFeatures(const b3Vector3* orgVertices, int numVertices, bool mergeCoplanarTriangles=true);
+
+ void initialize();
+ bool testContainment() const;
+
+
+
+};
+#endif
+ \ No newline at end of file
diff --git a/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/b3CpuNarrowPhase.cpp b/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/b3CpuNarrowPhase.cpp
new file mode 100644
index 0000000000..c3134b2c65
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/b3CpuNarrowPhase.cpp
@@ -0,0 +1,323 @@
+#include "b3CpuNarrowPhase.h"
+#include "Bullet3Collision/NarrowPhaseCollision/b3ConvexUtility.h"
+#include "Bullet3Collision/NarrowPhaseCollision/b3Config.h"
+
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3ContactConvexConvexSAT.h"
+
+
+struct b3CpuNarrowPhaseInternalData
+{
+ b3AlignedObjectArray<b3Aabb> m_localShapeAABBCPU;
+ b3AlignedObjectArray<b3Collidable> m_collidablesCPU;
+ b3AlignedObjectArray<b3ConvexUtility*> m_convexData;
+ b3Config m_config;
+
+
+ b3AlignedObjectArray<b3ConvexPolyhedronData> m_convexPolyhedra;
+ b3AlignedObjectArray<b3Vector3> m_uniqueEdges;
+ b3AlignedObjectArray<b3Vector3> m_convexVertices;
+ b3AlignedObjectArray<int> m_convexIndices;
+ b3AlignedObjectArray<b3GpuFace> m_convexFaces;
+
+ b3AlignedObjectArray<b3Contact4Data> m_contacts;
+
+ int m_numAcceleratedShapes;
+};
+
+
+const b3AlignedObjectArray<b3Contact4Data>& b3CpuNarrowPhase::getContacts() const
+{
+ return m_data->m_contacts;
+}
+
+b3Collidable& b3CpuNarrowPhase::getCollidableCpu(int collidableIndex)
+{
+ return m_data->m_collidablesCPU[collidableIndex];
+}
+
+const b3Collidable& b3CpuNarrowPhase::getCollidableCpu(int collidableIndex) const
+{
+ return m_data->m_collidablesCPU[collidableIndex];
+}
+
+
+b3CpuNarrowPhase::b3CpuNarrowPhase(const struct b3Config& config)
+{
+ m_data = new b3CpuNarrowPhaseInternalData;
+ m_data->m_config = config;
+ m_data->m_numAcceleratedShapes = 0;
+}
+
+b3CpuNarrowPhase::~b3CpuNarrowPhase()
+{
+ delete m_data;
+}
+
+void b3CpuNarrowPhase::computeContacts(b3AlignedObjectArray<b3Int4>& pairs, b3AlignedObjectArray<b3Aabb>& aabbsWorldSpace, b3AlignedObjectArray<b3RigidBodyData>& bodies)
+{
+ int nPairs = pairs.size();
+ int numContacts = 0;
+ int maxContactCapacity = m_data->m_config.m_maxContactCapacity;
+ m_data->m_contacts.resize(maxContactCapacity);
+
+ for (int i=0;i<nPairs;i++)
+ {
+ int bodyIndexA = pairs[i].x;
+ int bodyIndexB = pairs[i].y;
+ int collidableIndexA = bodies[bodyIndexA].m_collidableIdx;
+ int collidableIndexB = bodies[bodyIndexB].m_collidableIdx;
+
+ if (m_data->m_collidablesCPU[collidableIndexA].m_shapeType == SHAPE_SPHERE &&
+ m_data->m_collidablesCPU[collidableIndexB].m_shapeType == SHAPE_CONVEX_HULL)
+ {
+// computeContactSphereConvex(i,bodyIndexA,bodyIndexB,collidableIndexA,collidableIndexB,&bodies[0],
+// &m_data->m_collidablesCPU[0],&hostConvexData[0],&hostVertices[0],&hostIndices[0],&hostFaces[0],&hostContacts[0],nContacts,maxContactCapacity);
+ }
+
+ if (m_data->m_collidablesCPU[collidableIndexA].m_shapeType == SHAPE_CONVEX_HULL &&
+ m_data->m_collidablesCPU[collidableIndexB].m_shapeType == SHAPE_SPHERE)
+ {
+// computeContactSphereConvex(i,bodyIndexB,bodyIndexA,collidableIndexB,collidableIndexA,&bodies[0],
+// &m_data->m_collidablesCPU[0],&hostConvexData[0],&hostVertices[0],&hostIndices[0],&hostFaces[0],&hostContacts[0],nContacts,maxContactCapacity);
+ //printf("convex-sphere\n");
+
+ }
+
+ if (m_data->m_collidablesCPU[collidableIndexA].m_shapeType == SHAPE_CONVEX_HULL &&
+ m_data->m_collidablesCPU[collidableIndexB].m_shapeType == SHAPE_PLANE)
+ {
+// computeContactPlaneConvex(i,bodyIndexB,bodyIndexA,collidableIndexB,collidableIndexA,&bodies[0],
+// &m_data->m_collidablesCPU[0],&hostConvexData[0],&hostVertices[0],&hostIndices[0],&hostFaces[0],&hostContacts[0],nContacts,maxContactCapacity);
+// printf("convex-plane\n");
+
+ }
+
+ if (m_data->m_collidablesCPU[collidableIndexA].m_shapeType == SHAPE_PLANE &&
+ m_data->m_collidablesCPU[collidableIndexB].m_shapeType == SHAPE_CONVEX_HULL)
+ {
+// computeContactPlaneConvex(i,bodyIndexA,bodyIndexB,collidableIndexA,collidableIndexB,&bodies[0],
+// &m_data->m_collidablesCPU[0],&hostConvexData[0],&hostVertices[0],&hostIndices[0],&hostFaces[0],&hostContacts[0],nContacts,maxContactCapacity);
+// printf("plane-convex\n");
+
+ }
+
+ if (m_data->m_collidablesCPU[collidableIndexA].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS &&
+ m_data->m_collidablesCPU[collidableIndexB].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS)
+ {
+// computeContactCompoundCompound(i,bodyIndexB,bodyIndexA,collidableIndexB,collidableIndexA,&bodies[0],
+// &m_data->m_collidablesCPU[0],&hostConvexData[0],&cpuChildShapes[0], hostAabbsWorldSpace,hostAabbsLocalSpace,hostVertices,hostUniqueEdges,hostIndices,hostFaces,&hostContacts[0],
+// nContacts,maxContactCapacity,treeNodesCPU,subTreesCPU,bvhInfoCPU);
+// printf("convex-plane\n");
+
+ }
+
+
+ if (m_data->m_collidablesCPU[collidableIndexA].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS &&
+ m_data->m_collidablesCPU[collidableIndexB].m_shapeType == SHAPE_PLANE)
+ {
+// computeContactPlaneCompound(i,bodyIndexB,bodyIndexA,collidableIndexB,collidableIndexA,&bodies[0],
+// &m_data->m_collidablesCPU[0],&hostConvexData[0],&cpuChildShapes[0], &hostVertices[0],&hostIndices[0],&hostFaces[0],&hostContacts[0],nContacts,maxContactCapacity);
+// printf("convex-plane\n");
+
+ }
+
+ if (m_data->m_collidablesCPU[collidableIndexA].m_shapeType == SHAPE_PLANE &&
+ m_data->m_collidablesCPU[collidableIndexB].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS)
+ {
+// computeContactPlaneCompound(i,bodyIndexA,bodyIndexB,collidableIndexA,collidableIndexB,&bodies[0],
+// &m_data->m_collidablesCPU[0],&hostConvexData[0],&cpuChildShapes[0],&hostVertices[0],&hostIndices[0],&hostFaces[0],&hostContacts[0],nContacts,maxContactCapacity);
+// printf("plane-convex\n");
+
+ }
+
+ if (m_data->m_collidablesCPU[collidableIndexA].m_shapeType == SHAPE_CONVEX_HULL &&
+ m_data->m_collidablesCPU[collidableIndexB].m_shapeType == SHAPE_CONVEX_HULL)
+ {
+ //printf("pairs[i].z=%d\n",pairs[i].z);
+ //int contactIndex = computeContactConvexConvex2(i,bodyIndexA,bodyIndexB,collidableIndexA,collidableIndexB,bodies,
+ // m_data->m_collidablesCPU,hostConvexData,hostVertices,hostUniqueEdges,hostIndices,hostFaces,hostContacts,nContacts,maxContactCapacity,oldHostContacts);
+ int contactIndex = b3ContactConvexConvexSAT(i,bodyIndexA,bodyIndexB,collidableIndexA,collidableIndexB,bodies,
+ m_data->m_collidablesCPU,m_data->m_convexPolyhedra,m_data->m_convexVertices,m_data->m_uniqueEdges,m_data->m_convexIndices,m_data->m_convexFaces,m_data->m_contacts,numContacts,maxContactCapacity);
+
+
+ if (contactIndex>=0)
+ {
+ pairs[i].z = contactIndex;
+ }
+// printf("plane-convex\n");
+
+ }
+
+
+ }
+
+ m_data->m_contacts.resize(numContacts);
+}
+
+int b3CpuNarrowPhase::registerConvexHullShape(b3ConvexUtility* utilPtr)
+{
+ int collidableIndex = allocateCollidable();
+ if (collidableIndex<0)
+ return collidableIndex;
+
+
+ b3Collidable& col = m_data->m_collidablesCPU[collidableIndex];
+ col.m_shapeType = SHAPE_CONVEX_HULL;
+ col.m_shapeIndex = -1;
+
+
+ {
+ b3Vector3 localCenter=b3MakeVector3(0,0,0);
+ for (int i=0;i<utilPtr->m_vertices.size();i++)
+ localCenter+=utilPtr->m_vertices[i];
+ localCenter*= (1.f/utilPtr->m_vertices.size());
+ utilPtr->m_localCenter = localCenter;
+
+ col.m_shapeIndex = registerConvexHullShapeInternal(utilPtr,col);
+ }
+
+ if (col.m_shapeIndex>=0)
+ {
+ b3Aabb aabb;
+
+ b3Vector3 myAabbMin=b3MakeVector3(1e30f,1e30f,1e30f);
+ b3Vector3 myAabbMax=b3MakeVector3(-1e30f,-1e30f,-1e30f);
+
+ for (int i=0;i<utilPtr->m_vertices.size();i++)
+ {
+ myAabbMin.setMin(utilPtr->m_vertices[i]);
+ myAabbMax.setMax(utilPtr->m_vertices[i]);
+ }
+ aabb.m_min[0] = myAabbMin[0];
+ aabb.m_min[1] = myAabbMin[1];
+ aabb.m_min[2] = myAabbMin[2];
+ aabb.m_minIndices[3] = 0;
+
+ aabb.m_max[0] = myAabbMax[0];
+ aabb.m_max[1] = myAabbMax[1];
+ aabb.m_max[2] = myAabbMax[2];
+ aabb.m_signedMaxIndices[3] = 0;
+
+ m_data->m_localShapeAABBCPU.push_back(aabb);
+
+ }
+
+ return collidableIndex;
+}
+
+int b3CpuNarrowPhase::allocateCollidable()
+{
+ int curSize = m_data->m_collidablesCPU.size();
+ if (curSize<m_data->m_config.m_maxConvexShapes)
+ {
+ m_data->m_collidablesCPU.expand();
+ return curSize;
+ }
+ else
+ {
+ b3Error("allocateCollidable out-of-range %d\n",m_data->m_config.m_maxConvexShapes);
+ }
+ return -1;
+
+}
+
+int b3CpuNarrowPhase::registerConvexHullShape(const float* vertices, int strideInBytes, int numVertices, const float* scaling)
+{
+ b3AlignedObjectArray<b3Vector3> verts;
+
+ unsigned char* vts = (unsigned char*) vertices;
+ for (int i=0;i<numVertices;i++)
+ {
+ float* vertex = (float*) &vts[i*strideInBytes];
+ verts.push_back(b3MakeVector3(vertex[0]*scaling[0],vertex[1]*scaling[1],vertex[2]*scaling[2]));
+ }
+
+ b3ConvexUtility* utilPtr = new b3ConvexUtility();
+ bool merge = true;
+ if (numVertices)
+ {
+ utilPtr->initializePolyhedralFeatures(&verts[0],verts.size(),merge);
+ }
+
+ int collidableIndex = registerConvexHullShape(utilPtr);
+
+ delete utilPtr;
+ return collidableIndex;
+}
+
+
+int b3CpuNarrowPhase::registerConvexHullShapeInternal(b3ConvexUtility* convexPtr,b3Collidable& col)
+{
+
+ m_data->m_convexData.resize(m_data->m_numAcceleratedShapes+1);
+ m_data->m_convexPolyhedra.resize(m_data->m_numAcceleratedShapes+1);
+
+
+ b3ConvexPolyhedronData& convex = m_data->m_convexPolyhedra.at(m_data->m_convexPolyhedra.size()-1);
+ convex.mC = convexPtr->mC;
+ convex.mE = convexPtr->mE;
+ convex.m_extents= convexPtr->m_extents;
+ convex.m_localCenter = convexPtr->m_localCenter;
+ convex.m_radius = convexPtr->m_radius;
+
+ convex.m_numUniqueEdges = convexPtr->m_uniqueEdges.size();
+ int edgeOffset = m_data->m_uniqueEdges.size();
+ convex.m_uniqueEdgesOffset = edgeOffset;
+
+ m_data->m_uniqueEdges.resize(edgeOffset+convex.m_numUniqueEdges);
+
+ //convex data here
+ int i;
+ for ( i=0;i<convexPtr->m_uniqueEdges.size();i++)
+ {
+ m_data->m_uniqueEdges[edgeOffset+i] = convexPtr->m_uniqueEdges[i];
+ }
+
+ int faceOffset = m_data->m_convexFaces.size();
+ convex.m_faceOffset = faceOffset;
+ convex.m_numFaces = convexPtr->m_faces.size();
+
+ m_data->m_convexFaces.resize(faceOffset+convex.m_numFaces);
+
+
+ for (i=0;i<convexPtr->m_faces.size();i++)
+ {
+ m_data->m_convexFaces[convex.m_faceOffset+i].m_plane = b3MakeVector3(convexPtr->m_faces[i].m_plane[0],
+ convexPtr->m_faces[i].m_plane[1],
+ convexPtr->m_faces[i].m_plane[2],
+ convexPtr->m_faces[i].m_plane[3]);
+
+
+ int indexOffset = m_data->m_convexIndices.size();
+ int numIndices = convexPtr->m_faces[i].m_indices.size();
+ m_data->m_convexFaces[convex.m_faceOffset+i].m_numIndices = numIndices;
+ m_data->m_convexFaces[convex.m_faceOffset+i].m_indexOffset = indexOffset;
+ m_data->m_convexIndices.resize(indexOffset+numIndices);
+ for (int p=0;p<numIndices;p++)
+ {
+ m_data->m_convexIndices[indexOffset+p] = convexPtr->m_faces[i].m_indices[p];
+ }
+ }
+
+ convex.m_numVertices = convexPtr->m_vertices.size();
+ int vertexOffset = m_data->m_convexVertices.size();
+ convex.m_vertexOffset =vertexOffset;
+
+ m_data->m_convexVertices.resize(vertexOffset+convex.m_numVertices);
+ for (int i=0;i<convexPtr->m_vertices.size();i++)
+ {
+ m_data->m_convexVertices[vertexOffset+i] = convexPtr->m_vertices[i];
+ }
+
+ (m_data->m_convexData)[m_data->m_numAcceleratedShapes] = convexPtr;
+
+
+
+ return m_data->m_numAcceleratedShapes++;
+}
+
+const b3Aabb& b3CpuNarrowPhase::getLocalSpaceAabb(int collidableIndex) const
+{
+ return m_data->m_localShapeAABBCPU[collidableIndex];
+}
diff --git a/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/b3CpuNarrowPhase.h b/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/b3CpuNarrowPhase.h
new file mode 100644
index 0000000000..528be3346d
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/b3CpuNarrowPhase.h
@@ -0,0 +1,105 @@
+#ifndef B3_CPU_NARROWPHASE_H
+#define B3_CPU_NARROWPHASE_H
+
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h"
+#include "Bullet3Common/b3AlignedObjectArray.h"
+#include "Bullet3Common/b3Vector3.h"
+#include "Bullet3Collision/BroadPhaseCollision/shared/b3Aabb.h"
+#include "Bullet3Common/shared/b3Int4.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h"
+
+class b3CpuNarrowPhase
+{
+protected:
+
+ struct b3CpuNarrowPhaseInternalData* m_data;
+ int m_acceleratedCompanionShapeIndex;
+ int m_planeBodyIndex;
+ int m_static0Index;
+
+ int registerConvexHullShapeInternal(class b3ConvexUtility* convexPtr,b3Collidable& col);
+ int registerConcaveMeshShape(b3AlignedObjectArray<b3Vector3>* vertices, b3AlignedObjectArray<int>* indices, b3Collidable& col, const float* scaling);
+
+public:
+
+
+
+
+ b3CpuNarrowPhase(const struct b3Config& config);
+
+ virtual ~b3CpuNarrowPhase(void);
+
+ int registerSphereShape(float radius);
+ int registerPlaneShape(const b3Vector3& planeNormal, float planeConstant);
+
+ int registerCompoundShape(b3AlignedObjectArray<b3GpuChildShape>* childShapes);
+ int registerFace(const b3Vector3& faceNormal, float faceConstant);
+
+ int registerConcaveMesh(b3AlignedObjectArray<b3Vector3>* vertices, b3AlignedObjectArray<int>* indices,const float* scaling);
+
+ //do they need to be merged?
+
+ int registerConvexHullShape(b3ConvexUtility* utilPtr);
+ int registerConvexHullShape(const float* vertices, int strideInBytes, int numVertices, const float* scaling);
+
+ //int registerRigidBody(int collidableIndex, float mass, const float* position, const float* orientation, const float* aabbMin, const float* aabbMax,bool writeToGpu);
+ void setObjectTransform(const float* position, const float* orientation , int bodyIndex);
+
+ void writeAllBodiesToGpu();
+ void reset();
+ void readbackAllBodiesToCpu();
+ bool getObjectTransformFromCpu(float* position, float* orientation , int bodyIndex) const;
+
+ void setObjectTransformCpu(float* position, float* orientation , int bodyIndex);
+ void setObjectVelocityCpu(float* linVel, float* angVel, int bodyIndex);
+
+
+ //virtual void computeContacts(cl_mem broadphasePairs, int numBroadphasePairs, cl_mem aabbsWorldSpace, int numObjects);
+ virtual void computeContacts(b3AlignedObjectArray<b3Int4>& pairs, b3AlignedObjectArray<b3Aabb>& aabbsWorldSpace, b3AlignedObjectArray<b3RigidBodyData>& bodies);
+
+
+
+ const struct b3RigidBodyData* getBodiesCpu() const;
+ //struct b3RigidBodyData* getBodiesCpu();
+
+ int getNumBodiesGpu() const;
+
+
+ int getNumBodyInertiasGpu() const;
+
+
+ const struct b3Collidable* getCollidablesCpu() const;
+ int getNumCollidablesGpu() const;
+
+
+ /*const struct b3Contact4* getContactsCPU() const;
+
+
+ int getNumContactsGpu() const;
+ */
+
+ const b3AlignedObjectArray<b3Contact4Data>& getContacts() const;
+
+
+ int getNumRigidBodies() const;
+
+ int allocateCollidable();
+
+ int getStatic0Index() const
+ {
+ return m_static0Index;
+ }
+ b3Collidable& getCollidableCpu(int collidableIndex);
+ const b3Collidable& getCollidableCpu(int collidableIndex) const;
+
+ const b3CpuNarrowPhaseInternalData* getInternalData() const
+ {
+ return m_data;
+ }
+
+ const struct b3Aabb& getLocalSpaceAabb(int collidableIndex) const;
+};
+
+#endif //B3_CPU_NARROWPHASE_H
+
diff --git a/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/b3RaycastInfo.h b/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/b3RaycastInfo.h
new file mode 100644
index 0000000000..fba8bd07a4
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/b3RaycastInfo.h
@@ -0,0 +1,24 @@
+
+#ifndef B3_RAYCAST_INFO_H
+#define B3_RAYCAST_INFO_H
+
+#include "Bullet3Common/b3Vector3.h"
+
+B3_ATTRIBUTE_ALIGNED16(struct) b3RayInfo
+{
+ b3Vector3 m_from;
+ b3Vector3 m_to;
+};
+
+B3_ATTRIBUTE_ALIGNED16(struct) b3RayHit
+{
+ b3Scalar m_hitFraction;
+ int m_hitBody;
+ int m_hitResult1;
+ int m_hitResult2;
+ b3Vector3 m_hitPoint;
+ b3Vector3 m_hitNormal;
+};
+
+#endif //B3_RAYCAST_INFO_H
+
diff --git a/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/b3RigidBodyCL.h b/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/b3RigidBodyCL.h
new file mode 100644
index 0000000000..d58f71802f
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/b3RigidBodyCL.h
@@ -0,0 +1,30 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2013 Erwin Coumans 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 B3_RIGID_BODY_CL
+#define B3_RIGID_BODY_CL
+
+#include "Bullet3Common/b3Scalar.h"
+#include "Bullet3Common/b3Matrix3x3.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
+
+
+inline float b3GetInvMass(const b3RigidBodyData& body)
+{
+ return body.m_invMass;
+}
+
+
+#endif//B3_RIGID_BODY_CL
diff --git a/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3BvhSubtreeInfoData.h b/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3BvhSubtreeInfoData.h
new file mode 100644
index 0000000000..8788ccbb47
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3BvhSubtreeInfoData.h
@@ -0,0 +1,20 @@
+
+#ifndef B3_BVH_SUBTREE_INFO_DATA_H
+#define B3_BVH_SUBTREE_INFO_DATA_H
+
+typedef struct b3BvhSubtreeInfoData b3BvhSubtreeInfoData_t;
+
+struct b3BvhSubtreeInfoData
+{
+ //12 bytes
+ unsigned short int m_quantizedAabbMin[3];
+ unsigned short int m_quantizedAabbMax[3];
+ //4 bytes, points to the root of the subtree
+ int m_rootNodeIndex;
+ //4 bytes
+ int m_subtreeSize;
+ int m_padding[3];
+};
+
+#endif //B3_BVH_SUBTREE_INFO_DATA_H
+
diff --git a/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3BvhTraversal.h b/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3BvhTraversal.h
new file mode 100644
index 0000000000..2618da24bc
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3BvhTraversal.h
@@ -0,0 +1,126 @@
+
+
+#include "Bullet3Common/shared/b3Int4.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h"
+#include "Bullet3Collision/BroadPhaseCollision/shared/b3Aabb.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3BvhSubtreeInfoData.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3QuantizedBvhNodeData.h"
+
+
+
+// work-in-progress
+void b3BvhTraversal( __global const b3Int4* pairs,
+ __global const b3RigidBodyData* rigidBodies,
+ __global const b3Collidable* collidables,
+ __global b3Aabb* aabbs,
+ __global b3Int4* concavePairsOut,
+ __global volatile int* numConcavePairsOut,
+ __global const b3BvhSubtreeInfo* subtreeHeadersRoot,
+ __global const b3QuantizedBvhNode* quantizedNodesRoot,
+ __global const b3BvhInfo* bvhInfos,
+ int numPairs,
+ int maxNumConcavePairsCapacity,
+ int id)
+{
+
+ int bodyIndexA = pairs[id].x;
+ int bodyIndexB = pairs[id].y;
+ int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
+ int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
+
+ //once the broadphase avoids static-static pairs, we can remove this test
+ if ((rigidBodies[bodyIndexA].m_invMass==0) &&(rigidBodies[bodyIndexB].m_invMass==0))
+ {
+ return;
+ }
+
+ if (collidables[collidableIndexA].m_shapeType!=SHAPE_CONCAVE_TRIMESH)
+ return;
+
+ int shapeTypeB = collidables[collidableIndexB].m_shapeType;
+
+ if (shapeTypeB!=SHAPE_CONVEX_HULL &&
+ shapeTypeB!=SHAPE_SPHERE &&
+ shapeTypeB!=SHAPE_COMPOUND_OF_CONVEX_HULLS
+ )
+ return;
+
+ b3BvhInfo bvhInfo = bvhInfos[collidables[collidableIndexA].m_numChildShapes];
+
+ b3Float4 bvhAabbMin = bvhInfo.m_aabbMin;
+ b3Float4 bvhAabbMax = bvhInfo.m_aabbMax;
+ b3Float4 bvhQuantization = bvhInfo.m_quantization;
+ int numSubtreeHeaders = bvhInfo.m_numSubTrees;
+ __global const b3BvhSubtreeInfoData* subtreeHeaders = &subtreeHeadersRoot[bvhInfo.m_subTreeOffset];
+ __global const b3QuantizedBvhNodeData* quantizedNodes = &quantizedNodesRoot[bvhInfo.m_nodeOffset];
+
+
+ unsigned short int quantizedQueryAabbMin[3];
+ unsigned short int quantizedQueryAabbMax[3];
+ b3QuantizeWithClamp(quantizedQueryAabbMin,aabbs[bodyIndexB].m_minVec,false,bvhAabbMin, bvhAabbMax,bvhQuantization);
+ b3QuantizeWithClamp(quantizedQueryAabbMax,aabbs[bodyIndexB].m_maxVec,true ,bvhAabbMin, bvhAabbMax,bvhQuantization);
+
+ for (int i=0;i<numSubtreeHeaders;i++)
+ {
+ b3BvhSubtreeInfoData subtree = subtreeHeaders[i];
+
+ int overlap = b3TestQuantizedAabbAgainstQuantizedAabbSlow(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax);
+ if (overlap != 0)
+ {
+ int startNodeIndex = subtree.m_rootNodeIndex;
+ int endNodeIndex = subtree.m_rootNodeIndex+subtree.m_subtreeSize;
+ int curIndex = startNodeIndex;
+ int escapeIndex;
+ int isLeafNode;
+ int aabbOverlap;
+ while (curIndex < endNodeIndex)
+ {
+ b3QuantizedBvhNodeData rootNode = quantizedNodes[curIndex];
+ aabbOverlap = b3TestQuantizedAabbAgainstQuantizedAabbSlow(quantizedQueryAabbMin,quantizedQueryAabbMax,rootNode.m_quantizedAabbMin,rootNode.m_quantizedAabbMax);
+ isLeafNode = b3IsLeaf(&rootNode);
+ if (aabbOverlap)
+ {
+ if (isLeafNode)
+ {
+ int triangleIndex = b3GetTriangleIndex(&rootNode);
+ if (shapeTypeB==SHAPE_COMPOUND_OF_CONVEX_HULLS)
+ {
+ int numChildrenB = collidables[collidableIndexB].m_numChildShapes;
+ int pairIdx = b3AtomicAdd (numConcavePairsOut,numChildrenB);
+ for (int b=0;b<numChildrenB;b++)
+ {
+ if ((pairIdx+b)<maxNumConcavePairsCapacity)
+ {
+ int childShapeIndexB = collidables[collidableIndexB].m_shapeIndex+b;
+ b3Int4 newPair = b3MakeInt4(bodyIndexA,bodyIndexB,triangleIndex,childShapeIndexB);
+ concavePairsOut[pairIdx+b] = newPair;
+ }
+ }
+ } else
+ {
+ int pairIdx = b3AtomicInc(numConcavePairsOut);
+ if (pairIdx<maxNumConcavePairsCapacity)
+ {
+ b3Int4 newPair = b3MakeInt4(bodyIndexA,bodyIndexB,triangleIndex,0);
+ concavePairsOut[pairIdx] = newPair;
+ }
+ }
+ }
+ curIndex++;
+ } else
+ {
+ if (isLeafNode)
+ {
+ curIndex++;
+ } else
+ {
+ escapeIndex = b3GetEscapeIndex(&rootNode);
+ curIndex += escapeIndex;
+ }
+ }
+ }
+ }
+ }
+
+} \ No newline at end of file
diff --git a/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3ClipFaces.h b/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3ClipFaces.h
new file mode 100644
index 0000000000..8009e7d6e0
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3ClipFaces.h
@@ -0,0 +1,188 @@
+#ifndef B3_CLIP_FACES_H
+#define B3_CLIP_FACES_H
+
+
+#include "Bullet3Common/shared/b3Int4.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h"
+#include "Bullet3Collision/BroadPhaseCollision/shared/b3Aabb.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3BvhSubtreeInfoData.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3QuantizedBvhNodeData.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h"
+
+
+inline b3Float4 b3Lerp3(b3Float4ConstArg a,b3Float4ConstArg b, float t)
+{
+ return b3MakeFloat4( a.x + (b.x - a.x) * t,
+ a.y + (b.y - a.y) * t,
+ a.z + (b.z - a.z) * t,
+ 0.f);
+}
+
+// Clips a face to the back of a plane, return the number of vertices out, stored in ppVtxOut
+int clipFaceGlobal(__global const b3Float4* pVtxIn, int numVertsIn, b3Float4ConstArg planeNormalWS,float planeEqWS, __global b3Float4* ppVtxOut)
+{
+
+ int ve;
+ float ds, de;
+ int numVertsOut = 0;
+ //double-check next test
+ // if (numVertsIn < 2)
+ // return 0;
+
+ b3Float4 firstVertex=pVtxIn[numVertsIn-1];
+ b3Float4 endVertex = pVtxIn[0];
+
+ ds = b3Dot(planeNormalWS,firstVertex)+planeEqWS;
+
+ for (ve = 0; ve < numVertsIn; ve++)
+ {
+ endVertex=pVtxIn[ve];
+ de = b3Dot(planeNormalWS,endVertex)+planeEqWS;
+ if (ds<0)
+ {
+ if (de<0)
+ {
+ // Start < 0, end < 0, so output endVertex
+ ppVtxOut[numVertsOut++] = endVertex;
+ }
+ else
+ {
+ // Start < 0, end >= 0, so output intersection
+ ppVtxOut[numVertsOut++] = b3Lerp3(firstVertex, endVertex,(ds * 1.f/(ds - de)) );
+ }
+ }
+ else
+ {
+ if (de<0)
+ {
+ // Start >= 0, end < 0 so output intersection and end
+ ppVtxOut[numVertsOut++] = b3Lerp3(firstVertex, endVertex,(ds * 1.f/(ds - de)) );
+ ppVtxOut[numVertsOut++] = endVertex;
+ }
+ }
+ firstVertex = endVertex;
+ ds = de;
+ }
+ return numVertsOut;
+}
+
+
+__kernel void clipFacesAndFindContactsKernel( __global const b3Float4* separatingNormals,
+ __global const int* hasSeparatingAxis,
+ __global b3Int4* clippingFacesOut,
+ __global b3Float4* worldVertsA1,
+ __global b3Float4* worldNormalsA1,
+ __global b3Float4* worldVertsB1,
+ __global b3Float4* worldVertsB2,
+ int vertexFaceCapacity,
+ int pairIndex
+ )
+{
+// int i = get_global_id(0);
+ //int pairIndex = i;
+ int i = pairIndex;
+
+ float minDist = -1e30f;
+ float maxDist = 0.02f;
+
+// if (i<numPairs)
+ {
+
+ if (hasSeparatingAxis[i])
+ {
+
+// int bodyIndexA = pairs[i].x;
+ // int bodyIndexB = pairs[i].y;
+
+ int numLocalContactsOut = 0;
+
+ int capacityWorldVertsB2 = vertexFaceCapacity;
+
+ __global b3Float4* pVtxIn = &worldVertsB1[pairIndex*capacityWorldVertsB2];
+ __global b3Float4* pVtxOut = &worldVertsB2[pairIndex*capacityWorldVertsB2];
+
+
+ {
+ __global b3Int4* clippingFaces = clippingFacesOut;
+
+
+ int closestFaceA = clippingFaces[pairIndex].x;
+ // int closestFaceB = clippingFaces[pairIndex].y;
+ int numVertsInA = clippingFaces[pairIndex].z;
+ int numVertsInB = clippingFaces[pairIndex].w;
+
+ int numVertsOut = 0;
+
+ if (closestFaceA>=0)
+ {
+
+
+
+ // clip polygon to back of planes of all faces of hull A that are adjacent to witness face
+
+ for(int e0=0;e0<numVertsInA;e0++)
+ {
+ const b3Float4 aw = worldVertsA1[pairIndex*capacityWorldVertsB2+e0];
+ const b3Float4 bw = worldVertsA1[pairIndex*capacityWorldVertsB2+((e0+1)%numVertsInA)];
+ const b3Float4 WorldEdge0 = aw - bw;
+ b3Float4 worldPlaneAnormal1 = worldNormalsA1[pairIndex];
+ b3Float4 planeNormalWS1 = -b3Cross(WorldEdge0,worldPlaneAnormal1);
+ b3Float4 worldA1 = aw;
+ float planeEqWS1 = -b3Dot(worldA1,planeNormalWS1);
+ b3Float4 planeNormalWS = planeNormalWS1;
+ float planeEqWS=planeEqWS1;
+ numVertsOut = clipFaceGlobal(pVtxIn, numVertsInB, planeNormalWS,planeEqWS, pVtxOut);
+ __global b3Float4* tmp = pVtxOut;
+ pVtxOut = pVtxIn;
+ pVtxIn = tmp;
+ numVertsInB = numVertsOut;
+ numVertsOut = 0;
+ }
+
+ b3Float4 planeNormalWS = worldNormalsA1[pairIndex];
+ float planeEqWS=-b3Dot(planeNormalWS,worldVertsA1[pairIndex*capacityWorldVertsB2]);
+
+ for (int i=0;i<numVertsInB;i++)
+ {
+ float depth = b3Dot(planeNormalWS,pVtxIn[i])+planeEqWS;
+ if (depth <=minDist)
+ {
+ depth = minDist;
+ }
+/*
+ static float maxDepth = 0.f;
+ if (depth < maxDepth)
+ {
+ maxDepth = depth;
+ if (maxDepth < -10)
+ {
+ printf("error at framecount %d?\n",myframecount);
+ }
+ printf("maxDepth = %f\n", maxDepth);
+
+ }
+*/
+ if (depth <=maxDist)
+ {
+ b3Float4 pointInWorld = pVtxIn[i];
+ pVtxOut[numLocalContactsOut++] = b3MakeFloat4(pointInWorld.x,pointInWorld.y,pointInWorld.z,depth);
+ }
+ }
+
+ }
+ clippingFaces[pairIndex].w =numLocalContactsOut;
+
+
+ }
+
+ for (int i=0;i<numLocalContactsOut;i++)
+ pVtxIn[i] = pVtxOut[i];
+
+ }// if (hasSeparatingAxis[i])
+ }// if (i<numPairs)
+
+}
+
+#endif //B3_CLIP_FACES_H
+
diff --git a/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h b/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h
new file mode 100644
index 0000000000..77cdc7b7a9
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h
@@ -0,0 +1,76 @@
+
+#ifndef B3_COLLIDABLE_H
+#define B3_COLLIDABLE_H
+
+
+#include "Bullet3Common/shared/b3Float4.h"
+#include "Bullet3Common/shared/b3Quat.h"
+
+enum b3ShapeTypes
+{
+ SHAPE_HEIGHT_FIELD=1,
+
+ SHAPE_CONVEX_HULL=3,
+ SHAPE_PLANE=4,
+ SHAPE_CONCAVE_TRIMESH=5,
+ SHAPE_COMPOUND_OF_CONVEX_HULLS=6,
+ SHAPE_SPHERE=7,
+ MAX_NUM_SHAPE_TYPES,
+};
+
+typedef struct b3Collidable b3Collidable_t;
+
+
+struct b3Collidable
+{
+ union {
+ int m_numChildShapes;
+ int m_bvhIndex;
+ };
+ union
+ {
+ float m_radius;
+ int m_compoundBvhIndex;
+ };
+
+ int m_shapeType;
+ union
+ {
+ int m_shapeIndex;
+ float m_height;
+ };
+};
+
+typedef struct b3GpuChildShape b3GpuChildShape_t;
+struct b3GpuChildShape
+{
+ b3Float4 m_childPosition;
+ b3Quat m_childOrientation;
+ union
+ {
+ int m_shapeIndex;//used for SHAPE_COMPOUND_OF_CONVEX_HULLS
+ int m_capsuleAxis;
+ };
+ union
+ {
+ float m_radius;//used for childshape of SHAPE_COMPOUND_OF_SPHERES or SHAPE_COMPOUND_OF_CAPSULES
+ int m_numChildShapes;//used for compound shape
+ };
+ union
+ {
+ float m_height;//used for childshape of SHAPE_COMPOUND_OF_CAPSULES
+ int m_collidableShapeIndex;
+ };
+ int m_shapeType;
+};
+
+struct b3CompoundOverlappingPair
+{
+ int m_bodyIndexA;
+ int m_bodyIndexB;
+// int m_pairType;
+ int m_childShapeIndexA;
+ int m_childShapeIndexB;
+};
+
+#endif //B3_COLLIDABLE_H
diff --git a/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h b/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h
new file mode 100644
index 0000000000..dfd45cc566
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h
@@ -0,0 +1,40 @@
+#ifndef B3_CONTACT4DATA_H
+#define B3_CONTACT4DATA_H
+
+#include "Bullet3Common/shared/b3Float4.h"
+
+typedef struct b3Contact4Data b3Contact4Data_t;
+
+struct b3Contact4Data
+{
+ b3Float4 m_worldPosB[4];
+// b3Float4 m_localPosA[4];
+// b3Float4 m_localPosB[4];
+ b3Float4 m_worldNormalOnB; // w: m_nPoints
+ unsigned short m_restituitionCoeffCmp;
+ unsigned short m_frictionCoeffCmp;
+ int m_batchIdx;
+ int m_bodyAPtrAndSignBit;//x:m_bodyAPtr, y:m_bodyBPtr
+ int m_bodyBPtrAndSignBit;
+
+ int m_childIndexA;
+ int m_childIndexB;
+ int m_unused1;
+ int m_unused2;
+
+
+};
+
+inline int b3Contact4Data_getNumPoints(const struct b3Contact4Data* contact)
+{
+ return (int)contact->m_worldNormalOnB.w;
+};
+
+inline void b3Contact4Data_setNumPoints(struct b3Contact4Data* contact, int numPoints)
+{
+ contact->m_worldNormalOnB.w = (float)numPoints;
+};
+
+
+
+#endif //B3_CONTACT4DATA_H \ No newline at end of file
diff --git a/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3ContactConvexConvexSAT.h b/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3ContactConvexConvexSAT.h
new file mode 100644
index 0000000000..f295f01a6c
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3ContactConvexConvexSAT.h
@@ -0,0 +1,520 @@
+
+#ifndef B3_CONTACT_CONVEX_CONVEX_SAT_H
+#define B3_CONTACT_CONVEX_CONVEX_SAT_H
+
+
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3FindSeparatingAxis.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3ReduceContacts.h"
+
+#define B3_MAX_VERTS 1024
+
+
+
+inline b3Float4 b3Lerp3(const b3Float4& a,const b3Float4& b, float t)
+{
+ return b3MakeVector3( a.x + (b.x - a.x) * t,
+ a.y + (b.y - a.y) * t,
+ a.z + (b.z - a.z) * t,
+ 0.f);
+}
+
+
+// Clips a face to the back of a plane, return the number of vertices out, stored in ppVtxOut
+inline int b3ClipFace(const b3Float4* pVtxIn, int numVertsIn, b3Float4& planeNormalWS,float planeEqWS, b3Float4* ppVtxOut)
+{
+
+ int ve;
+ float ds, de;
+ int numVertsOut = 0;
+ if (numVertsIn < 2)
+ return 0;
+
+ b3Float4 firstVertex=pVtxIn[numVertsIn-1];
+ b3Float4 endVertex = pVtxIn[0];
+
+ ds = b3Dot3F4(planeNormalWS,firstVertex)+planeEqWS;
+
+ for (ve = 0; ve < numVertsIn; ve++)
+ {
+ endVertex=pVtxIn[ve];
+
+ de = b3Dot3F4(planeNormalWS,endVertex)+planeEqWS;
+
+ if (ds<0)
+ {
+ if (de<0)
+ {
+ // Start < 0, end < 0, so output endVertex
+ ppVtxOut[numVertsOut++] = endVertex;
+ }
+ else
+ {
+ // Start < 0, end >= 0, so output intersection
+ ppVtxOut[numVertsOut++] = b3Lerp3(firstVertex, endVertex,(ds * 1.f/(ds - de)) );
+ }
+ }
+ else
+ {
+ if (de<0)
+ {
+ // Start >= 0, end < 0 so output intersection and end
+ ppVtxOut[numVertsOut++] = b3Lerp3(firstVertex, endVertex,(ds * 1.f/(ds - de)) );
+ ppVtxOut[numVertsOut++] = endVertex;
+ }
+ }
+ firstVertex = endVertex;
+ ds = de;
+ }
+ return numVertsOut;
+}
+
+
+inline int b3ClipFaceAgainstHull(const b3Float4& separatingNormal, const b3ConvexPolyhedronData* hullA,
+ const b3Float4& posA, const b3Quaternion& ornA, b3Float4* worldVertsB1, int numWorldVertsB1,
+ b3Float4* worldVertsB2, int capacityWorldVertsB2,
+ const float minDist, float maxDist,
+ const b3AlignedObjectArray<b3Float4>& verticesA, const b3AlignedObjectArray<b3GpuFace>& facesA, const b3AlignedObjectArray<int>& indicesA,
+ //const b3Float4* verticesB, const b3GpuFace* facesB, const int* indicesB,
+ b3Float4* contactsOut,
+ int contactCapacity)
+{
+ int numContactsOut = 0;
+
+ b3Float4* pVtxIn = worldVertsB1;
+ b3Float4* pVtxOut = worldVertsB2;
+
+ int numVertsIn = numWorldVertsB1;
+ int numVertsOut = 0;
+
+ int closestFaceA=-1;
+ {
+ float dmin = FLT_MAX;
+ for(int face=0;face<hullA->m_numFaces;face++)
+ {
+ const b3Float4 Normal = b3MakeVector3(
+ facesA[hullA->m_faceOffset+face].m_plane.x,
+ facesA[hullA->m_faceOffset+face].m_plane.y,
+ facesA[hullA->m_faceOffset+face].m_plane.z,0.f);
+ const b3Float4 faceANormalWS = b3QuatRotate(ornA,Normal);
+
+ float d = b3Dot3F4(faceANormalWS,separatingNormal);
+ if (d < dmin)
+ {
+ dmin = d;
+ closestFaceA = face;
+ }
+ }
+ }
+ if (closestFaceA<0)
+ return numContactsOut;
+
+ b3GpuFace polyA = facesA[hullA->m_faceOffset+closestFaceA];
+
+ // clip polygon to back of planes of all faces of hull A that are adjacent to witness face
+ //int numContacts = numWorldVertsB1;
+ int numVerticesA = polyA.m_numIndices;
+ for(int e0=0;e0<numVerticesA;e0++)
+ {
+ const b3Float4 a = verticesA[hullA->m_vertexOffset+indicesA[polyA.m_indexOffset+e0]];
+ const b3Float4 b = verticesA[hullA->m_vertexOffset+indicesA[polyA.m_indexOffset+((e0+1)%numVerticesA)]];
+ const b3Float4 edge0 = a - b;
+ const b3Float4 WorldEdge0 = b3QuatRotate(ornA,edge0);
+ b3Float4 planeNormalA = b3MakeFloat4(polyA.m_plane.x,polyA.m_plane.y,polyA.m_plane.z,0.f);
+ b3Float4 worldPlaneAnormal1 = b3QuatRotate(ornA,planeNormalA);
+
+ b3Float4 planeNormalWS1 = -b3Cross3(WorldEdge0,worldPlaneAnormal1);
+ b3Float4 worldA1 = b3TransformPoint(a,posA,ornA);
+ float planeEqWS1 = -b3Dot3F4(worldA1,planeNormalWS1);
+
+ b3Float4 planeNormalWS = planeNormalWS1;
+ float planeEqWS=planeEqWS1;
+
+ //clip face
+ //clipFace(*pVtxIn, *pVtxOut,planeNormalWS,planeEqWS);
+ numVertsOut = b3ClipFace(pVtxIn, numVertsIn, planeNormalWS,planeEqWS, pVtxOut);
+
+ //btSwap(pVtxIn,pVtxOut);
+ b3Float4* tmp = pVtxOut;
+ pVtxOut = pVtxIn;
+ pVtxIn = tmp;
+ numVertsIn = numVertsOut;
+ numVertsOut = 0;
+ }
+
+
+ // only keep points that are behind the witness face
+ {
+ b3Float4 localPlaneNormal = b3MakeFloat4(polyA.m_plane.x,polyA.m_plane.y,polyA.m_plane.z,0.f);
+ float localPlaneEq = polyA.m_plane.w;
+ b3Float4 planeNormalWS = b3QuatRotate(ornA,localPlaneNormal);
+ float planeEqWS=localPlaneEq-b3Dot3F4(planeNormalWS,posA);
+ for (int i=0;i<numVertsIn;i++)
+ {
+ float depth = b3Dot3F4(planeNormalWS,pVtxIn[i])+planeEqWS;
+ if (depth <=minDist)
+ {
+ depth = minDist;
+ }
+ if (numContactsOut<contactCapacity)
+ {
+ if (depth <=maxDist)
+ {
+ b3Float4 pointInWorld = pVtxIn[i];
+ //resultOut.addContactPoint(separatingNormal,point,depth);
+ contactsOut[numContactsOut++] = b3MakeVector3(pointInWorld.x,pointInWorld.y,pointInWorld.z,depth);
+ //printf("depth=%f\n",depth);
+ }
+ } else
+ {
+ b3Error("exceeding contact capacity (%d,%df)\n", numContactsOut,contactCapacity);
+ }
+ }
+ }
+
+ return numContactsOut;
+}
+
+
+
+inline int b3ClipHullAgainstHull(const b3Float4& separatingNormal,
+ const b3ConvexPolyhedronData& hullA, const b3ConvexPolyhedronData& hullB,
+ const b3Float4& posA, const b3Quaternion& ornA,const b3Float4& posB, const b3Quaternion& ornB,
+ b3Float4* worldVertsB1, b3Float4* worldVertsB2, int capacityWorldVerts,
+ const float minDist, float maxDist,
+ const b3AlignedObjectArray<b3Float4>& verticesA, const b3AlignedObjectArray<b3GpuFace>& facesA, const b3AlignedObjectArray<int>& indicesA,
+ const b3AlignedObjectArray<b3Float4>& verticesB, const b3AlignedObjectArray<b3GpuFace>& facesB, const b3AlignedObjectArray<int>& indicesB,
+
+ b3Float4* contactsOut,
+ int contactCapacity)
+{
+ int numContactsOut = 0;
+ int numWorldVertsB1= 0;
+
+ B3_PROFILE("clipHullAgainstHull");
+
+ //float curMaxDist=maxDist;
+ int closestFaceB=-1;
+ float dmax = -FLT_MAX;
+
+ {
+ //B3_PROFILE("closestFaceB");
+ if (hullB.m_numFaces!=1)
+ {
+ //printf("wtf\n");
+ }
+ static bool once = true;
+ //printf("separatingNormal=%f,%f,%f\n",separatingNormal.x,separatingNormal.y,separatingNormal.z);
+
+ for(int face=0;face<hullB.m_numFaces;face++)
+ {
+#ifdef BT_DEBUG_SAT_FACE
+ if (once)
+ printf("face %d\n",face);
+ const b3GpuFace* faceB = &facesB[hullB.m_faceOffset+face];
+ if (once)
+ {
+ for (int i=0;i<faceB->m_numIndices;i++)
+ {
+ b3Float4 vert = verticesB[hullB.m_vertexOffset+indicesB[faceB->m_indexOffset+i]];
+ printf("vert[%d] = %f,%f,%f\n",i,vert.x,vert.y,vert.z);
+ }
+ }
+#endif //BT_DEBUG_SAT_FACE
+ //if (facesB[hullB.m_faceOffset+face].m_numIndices>2)
+ {
+ const b3Float4 Normal = b3MakeVector3(facesB[hullB.m_faceOffset+face].m_plane.x,
+ facesB[hullB.m_faceOffset+face].m_plane.y, facesB[hullB.m_faceOffset+face].m_plane.z,0.f);
+ const b3Float4 WorldNormal = b3QuatRotate(ornB, Normal);
+#ifdef BT_DEBUG_SAT_FACE
+ if (once)
+ printf("faceNormal = %f,%f,%f\n",Normal.x,Normal.y,Normal.z);
+#endif
+ float d = b3Dot3F4(WorldNormal,separatingNormal);
+ if (d > dmax)
+ {
+ dmax = d;
+ closestFaceB = face;
+ }
+ }
+ }
+ once = false;
+ }
+
+
+ b3Assert(closestFaceB>=0);
+ {
+ //B3_PROFILE("worldVertsB1");
+ const b3GpuFace& polyB = facesB[hullB.m_faceOffset+closestFaceB];
+ const int numVertices = polyB.m_numIndices;
+ for(int e0=0;e0<numVertices;e0++)
+ {
+ const b3Float4& b = verticesB[hullB.m_vertexOffset+indicesB[polyB.m_indexOffset+e0]];
+ worldVertsB1[numWorldVertsB1++] = b3TransformPoint(b,posB,ornB);
+ }
+ }
+
+ if (closestFaceB>=0)
+ {
+ //B3_PROFILE("clipFaceAgainstHull");
+ numContactsOut = b3ClipFaceAgainstHull((b3Float4&)separatingNormal, &hullA,
+ posA,ornA,
+ worldVertsB1,numWorldVertsB1,worldVertsB2,capacityWorldVerts, minDist, maxDist,
+ verticesA, facesA, indicesA,
+ contactsOut,contactCapacity);
+ }
+
+ return numContactsOut;
+}
+
+
+
+
+inline int b3ClipHullHullSingle(
+ int bodyIndexA, int bodyIndexB,
+ const b3Float4& posA,
+ const b3Quaternion& ornA,
+ const b3Float4& posB,
+ const b3Quaternion& ornB,
+
+ int collidableIndexA, int collidableIndexB,
+
+ const b3AlignedObjectArray<b3RigidBodyData>* bodyBuf,
+ b3AlignedObjectArray<b3Contact4Data>* globalContactOut,
+ int& nContacts,
+
+ const b3AlignedObjectArray<b3ConvexPolyhedronData>& hostConvexDataA,
+ const b3AlignedObjectArray<b3ConvexPolyhedronData>& hostConvexDataB,
+
+ const b3AlignedObjectArray<b3Vector3>& verticesA,
+ const b3AlignedObjectArray<b3Vector3>& uniqueEdgesA,
+ const b3AlignedObjectArray<b3GpuFace>& facesA,
+ const b3AlignedObjectArray<int>& indicesA,
+
+ const b3AlignedObjectArray<b3Vector3>& verticesB,
+ const b3AlignedObjectArray<b3Vector3>& uniqueEdgesB,
+ const b3AlignedObjectArray<b3GpuFace>& facesB,
+ const b3AlignedObjectArray<int>& indicesB,
+
+ const b3AlignedObjectArray<b3Collidable>& hostCollidablesA,
+ const b3AlignedObjectArray<b3Collidable>& hostCollidablesB,
+ const b3Vector3& sepNormalWorldSpace,
+ int maxContactCapacity )
+{
+ int contactIndex = -1;
+ b3ConvexPolyhedronData hullA, hullB;
+
+ b3Collidable colA = hostCollidablesA[collidableIndexA];
+ hullA = hostConvexDataA[colA.m_shapeIndex];
+ //printf("numvertsA = %d\n",hullA.m_numVertices);
+
+
+ b3Collidable colB = hostCollidablesB[collidableIndexB];
+ hullB = hostConvexDataB[colB.m_shapeIndex];
+ //printf("numvertsB = %d\n",hullB.m_numVertices);
+
+
+ b3Float4 contactsOut[B3_MAX_VERTS];
+ int localContactCapacity = B3_MAX_VERTS;
+
+#ifdef _WIN32
+ b3Assert(_finite(bodyBuf->at(bodyIndexA).m_pos.x));
+ b3Assert(_finite(bodyBuf->at(bodyIndexB).m_pos.x));
+#endif
+
+
+ {
+
+ b3Float4 worldVertsB1[B3_MAX_VERTS];
+ b3Float4 worldVertsB2[B3_MAX_VERTS];
+ int capacityWorldVerts = B3_MAX_VERTS;
+
+ b3Float4 hostNormal = b3MakeFloat4(sepNormalWorldSpace.x,sepNormalWorldSpace.y,sepNormalWorldSpace.z,0.f);
+ int shapeA = hostCollidablesA[collidableIndexA].m_shapeIndex;
+ int shapeB = hostCollidablesB[collidableIndexB].m_shapeIndex;
+
+ b3Scalar minDist = -1;
+ b3Scalar maxDist = 0.;
+
+
+
+ b3Transform trA,trB;
+ {
+ //B3_PROFILE("b3TransformPoint computation");
+ //trA.setIdentity();
+ trA.setOrigin(b3MakeVector3(posA.x,posA.y,posA.z));
+ trA.setRotation(b3Quaternion(ornA.x,ornA.y,ornA.z,ornA.w));
+
+ //trB.setIdentity();
+ trB.setOrigin(b3MakeVector3(posB.x,posB.y,posB.z));
+ trB.setRotation(b3Quaternion(ornB.x,ornB.y,ornB.z,ornB.w));
+ }
+
+ b3Quaternion trAorn = trA.getRotation();
+ b3Quaternion trBorn = trB.getRotation();
+
+ int numContactsOut = b3ClipHullAgainstHull(hostNormal,
+ hostConvexDataA.at(shapeA),
+ hostConvexDataB.at(shapeB),
+ (b3Float4&)trA.getOrigin(), (b3Quaternion&)trAorn,
+ (b3Float4&)trB.getOrigin(), (b3Quaternion&)trBorn,
+ worldVertsB1,worldVertsB2,capacityWorldVerts,
+ minDist, maxDist,
+ verticesA, facesA,indicesA,
+ verticesB, facesB,indicesB,
+
+ contactsOut,localContactCapacity);
+
+ if (numContactsOut>0)
+ {
+ B3_PROFILE("overlap");
+
+ b3Float4 normalOnSurfaceB = (b3Float4&)hostNormal;
+// b3Float4 centerOut;
+
+ b3Int4 contactIdx;
+ contactIdx.x = 0;
+ contactIdx.y = 1;
+ contactIdx.z = 2;
+ contactIdx.w = 3;
+
+ int numPoints = 0;
+
+ {
+ B3_PROFILE("extractManifold");
+ numPoints = b3ReduceContacts(contactsOut, numContactsOut, normalOnSurfaceB, &contactIdx);
+ }
+
+ b3Assert(numPoints);
+
+ if (nContacts<maxContactCapacity)
+ {
+ contactIndex = nContacts;
+ globalContactOut->expand();
+ b3Contact4Data& contact = globalContactOut->at(nContacts);
+ contact.m_batchIdx = 0;//i;
+ contact.m_bodyAPtrAndSignBit = (bodyBuf->at(bodyIndexA).m_invMass==0)? -bodyIndexA:bodyIndexA;
+ contact.m_bodyBPtrAndSignBit = (bodyBuf->at(bodyIndexB).m_invMass==0)? -bodyIndexB:bodyIndexB;
+
+ contact.m_frictionCoeffCmp = 45874;
+ contact.m_restituitionCoeffCmp = 0;
+
+ // float distance = 0.f;
+ for (int p=0;p<numPoints;p++)
+ {
+ contact.m_worldPosB[p] = contactsOut[contactIdx.s[p]];//check if it is actually on B
+ contact.m_worldNormalOnB = normalOnSurfaceB;
+ }
+ //printf("bodyIndexA %d,bodyIndexB %d,normal=%f,%f,%f numPoints %d\n",bodyIndexA,bodyIndexB,normalOnSurfaceB.x,normalOnSurfaceB.y,normalOnSurfaceB.z,numPoints);
+ contact.m_worldNormalOnB.w = (b3Scalar)numPoints;
+ nContacts++;
+ } else
+ {
+ b3Error("Error: exceeding contact capacity (%d/%d)\n", nContacts,maxContactCapacity);
+ }
+ }
+ }
+ return contactIndex;
+}
+
+
+
+
+
+inline int b3ContactConvexConvexSAT(
+ int pairIndex,
+ int bodyIndexA, int bodyIndexB,
+ int collidableIndexA, int collidableIndexB,
+ const b3AlignedObjectArray<b3RigidBodyData>& rigidBodies,
+ const b3AlignedObjectArray<b3Collidable>& collidables,
+ const b3AlignedObjectArray<b3ConvexPolyhedronData>& convexShapes,
+ const b3AlignedObjectArray<b3Float4>& convexVertices,
+ const b3AlignedObjectArray<b3Float4>& uniqueEdges,
+ const b3AlignedObjectArray<int>& convexIndices,
+ const b3AlignedObjectArray<b3GpuFace>& faces,
+ b3AlignedObjectArray<b3Contact4Data>& globalContactsOut,
+ int& nGlobalContactsOut,
+ int maxContactCapacity)
+{
+ int contactIndex = -1;
+
+
+ b3Float4 posA = rigidBodies[bodyIndexA].m_pos;
+ b3Quaternion ornA = rigidBodies[bodyIndexA].m_quat;
+ b3Float4 posB = rigidBodies[bodyIndexB].m_pos;
+ b3Quaternion ornB = rigidBodies[bodyIndexB].m_quat;
+
+
+ b3ConvexPolyhedronData hullA, hullB;
+
+ b3Float4 sepNormalWorldSpace;
+
+
+
+ b3Collidable colA = collidables[collidableIndexA];
+ hullA = convexShapes[colA.m_shapeIndex];
+ //printf("numvertsA = %d\n",hullA.m_numVertices);
+
+
+ b3Collidable colB = collidables[collidableIndexB];
+ hullB = convexShapes[colB.m_shapeIndex];
+ //printf("numvertsB = %d\n",hullB.m_numVertices);
+
+
+
+
+#ifdef _WIN32
+ b3Assert(_finite(rigidBodies[bodyIndexA].m_pos.x));
+ b3Assert(_finite(rigidBodies[bodyIndexB].m_pos.x));
+#endif
+
+ bool foundSepAxis = b3FindSeparatingAxis(hullA,hullB,
+ posA,
+ ornA,
+ posB,
+ ornB,
+
+ convexVertices,uniqueEdges,faces,convexIndices,
+ convexVertices,uniqueEdges,faces,convexIndices,
+
+ sepNormalWorldSpace
+ );
+
+
+ if (foundSepAxis)
+ {
+
+
+ contactIndex = b3ClipHullHullSingle(
+ bodyIndexA, bodyIndexB,
+ posA,ornA,
+ posB,ornB,
+ collidableIndexA, collidableIndexB,
+ &rigidBodies,
+ &globalContactsOut,
+ nGlobalContactsOut,
+
+ convexShapes,
+ convexShapes,
+
+ convexVertices,
+ uniqueEdges,
+ faces,
+ convexIndices,
+
+ convexVertices,
+ uniqueEdges,
+ faces,
+ convexIndices,
+
+ collidables,
+ collidables,
+ sepNormalWorldSpace,
+ maxContactCapacity);
+
+ }
+
+ return contactIndex;
+}
+
+#endif //B3_CONTACT_CONVEX_CONVEX_SAT_H
diff --git a/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3ContactSphereSphere.h b/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3ContactSphereSphere.h
new file mode 100644
index 0000000000..a3fa82287b
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3ContactSphereSphere.h
@@ -0,0 +1,162 @@
+
+#ifndef B3_CONTACT_SPHERE_SPHERE_H
+#define B3_CONTACT_SPHERE_SPHERE_H
+
+
+
+
+
+void computeContactSphereConvex(int pairIndex,
+ int bodyIndexA, int bodyIndexB,
+ int collidableIndexA, int collidableIndexB,
+ const b3RigidBodyData* rigidBodies,
+ const b3Collidable* collidables,
+ const b3ConvexPolyhedronData* convexShapes,
+ const b3Vector3* convexVertices,
+ const int* convexIndices,
+ const b3GpuFace* faces,
+ b3Contact4* globalContactsOut,
+ int& nGlobalContactsOut,
+ int maxContactCapacity)
+{
+
+ float radius = collidables[collidableIndexA].m_radius;
+ float4 spherePos1 = rigidBodies[bodyIndexA].m_pos;
+ b3Quaternion sphereOrn = rigidBodies[bodyIndexA].m_quat;
+
+
+
+ float4 pos = rigidBodies[bodyIndexB].m_pos;
+
+
+ b3Quaternion quat = rigidBodies[bodyIndexB].m_quat;
+
+ b3Transform tr;
+ tr.setIdentity();
+ tr.setOrigin(pos);
+ tr.setRotation(quat);
+ b3Transform trInv = tr.inverse();
+
+ float4 spherePos = trInv(spherePos1);
+
+ int collidableIndex = rigidBodies[bodyIndexB].m_collidableIdx;
+ int shapeIndex = collidables[collidableIndex].m_shapeIndex;
+ int numFaces = convexShapes[shapeIndex].m_numFaces;
+ float4 closestPnt = b3MakeVector3(0, 0, 0, 0);
+ float4 hitNormalWorld = b3MakeVector3(0, 0, 0, 0);
+ float minDist = -1000000.f; // TODO: What is the largest/smallest float?
+ bool bCollide = true;
+ int region = -1;
+ float4 localHitNormal;
+ for ( int f = 0; f < numFaces; f++ )
+ {
+ b3GpuFace face = faces[convexShapes[shapeIndex].m_faceOffset+f];
+ float4 planeEqn;
+ float4 localPlaneNormal = b3MakeVector3(face.m_plane.x,face.m_plane.y,face.m_plane.z,0.f);
+ float4 n1 = localPlaneNormal;//quatRotate(quat,localPlaneNormal);
+ planeEqn = n1;
+ planeEqn[3] = face.m_plane.w;
+
+ float4 pntReturn;
+ float dist = signedDistanceFromPointToPlane(spherePos, planeEqn, &pntReturn);
+
+ if ( dist > radius)
+ {
+ bCollide = false;
+ break;
+ }
+
+ if ( dist > 0 )
+ {
+ //might hit an edge or vertex
+ b3Vector3 out;
+
+ bool isInPoly = IsPointInPolygon(spherePos,
+ &face,
+ &convexVertices[convexShapes[shapeIndex].m_vertexOffset],
+ convexIndices,
+ &out);
+ if (isInPoly)
+ {
+ if (dist>minDist)
+ {
+ minDist = dist;
+ closestPnt = pntReturn;
+ localHitNormal = planeEqn;
+ region=1;
+ }
+ } else
+ {
+ b3Vector3 tmp = spherePos-out;
+ b3Scalar l2 = tmp.length2();
+ if (l2<radius*radius)
+ {
+ dist = b3Sqrt(l2);
+ if (dist>minDist)
+ {
+ minDist = dist;
+ closestPnt = out;
+ localHitNormal = tmp/dist;
+ region=2;
+ }
+
+ } else
+ {
+ bCollide = false;
+ break;
+ }
+ }
+ }
+ else
+ {
+ if ( dist > minDist )
+ {
+ minDist = dist;
+ closestPnt = pntReturn;
+ localHitNormal = planeEqn;
+ region=3;
+ }
+ }
+ }
+ static int numChecks = 0;
+ numChecks++;
+
+ if (bCollide && minDist > -10000)
+ {
+
+ float4 normalOnSurfaceB1 = tr.getBasis()*localHitNormal;//-hitNormalWorld;
+ float4 pOnB1 = tr(closestPnt);
+ //printf("dist ,%f,",minDist);
+ float actualDepth = minDist-radius;
+ if (actualDepth<0)
+ {
+ //printf("actualDepth = ,%f,", actualDepth);
+ //printf("normalOnSurfaceB1 = ,%f,%f,%f,", normalOnSurfaceB1.x,normalOnSurfaceB1.y,normalOnSurfaceB1.z);
+ //printf("region=,%d,\n", region);
+ pOnB1[3] = actualDepth;
+
+ int dstIdx;
+// dstIdx = nGlobalContactsOut++;//AppendInc( nGlobalContactsOut, dstIdx );
+
+ if (nGlobalContactsOut < maxContactCapacity)
+ {
+ dstIdx=nGlobalContactsOut;
+ nGlobalContactsOut++;
+
+ b3Contact4* c = &globalContactsOut[dstIdx];
+ c->m_worldNormalOnB = normalOnSurfaceB1;
+ c->setFrictionCoeff(0.7);
+ c->setRestituitionCoeff(0.f);
+
+ c->m_batchIdx = pairIndex;
+ c->m_bodyAPtrAndSignBit = rigidBodies[bodyIndexA].m_invMass==0?-bodyIndexA:bodyIndexA;
+ c->m_bodyBPtrAndSignBit = rigidBodies[bodyIndexB].m_invMass==0?-bodyIndexB:bodyIndexB;
+ c->m_worldPosB[0] = pOnB1;
+ int numPoints = 1;
+ c->m_worldNormalOnB.w = (b3Scalar)numPoints;
+ }//if (dstIdx < numPairs)
+ }
+ }//if (hasCollision)
+
+}
+#endif //B3_CONTACT_SPHERE_SPHERE_H
diff --git a/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h b/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h
new file mode 100644
index 0000000000..5c5f4e297f
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h
@@ -0,0 +1,40 @@
+
+#ifndef B3_CONVEX_POLYHEDRON_DATA_H
+#define B3_CONVEX_POLYHEDRON_DATA_H
+
+
+
+#include "Bullet3Common/shared/b3Float4.h"
+#include "Bullet3Common/shared/b3Quat.h"
+
+typedef struct b3GpuFace b3GpuFace_t;
+struct b3GpuFace
+{
+ b3Float4 m_plane;
+ int m_indexOffset;
+ int m_numIndices;
+ int m_unusedPadding1;
+ int m_unusedPadding2;
+};
+
+typedef struct b3ConvexPolyhedronData b3ConvexPolyhedronData_t;
+
+struct b3ConvexPolyhedronData
+{
+ b3Float4 m_localCenter;
+ b3Float4 m_extents;
+ b3Float4 mC;
+ b3Float4 mE;
+
+ float m_radius;
+ int m_faceOffset;
+ int m_numFaces;
+ int m_numVertices;
+
+ int m_vertexOffset;
+ int m_uniqueEdgesOffset;
+ int m_numUniqueEdges;
+ int m_unused;
+};
+
+#endif //B3_CONVEX_POLYHEDRON_DATA_H
diff --git a/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3FindConcaveSatAxis.h b/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3FindConcaveSatAxis.h
new file mode 100644
index 0000000000..89993f3565
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3FindConcaveSatAxis.h
@@ -0,0 +1,832 @@
+#ifndef B3_FIND_CONCAVE_SEPARATING_AXIS_H
+#define B3_FIND_CONCAVE_SEPARATING_AXIS_H
+
+#define B3_TRIANGLE_NUM_CONVEX_FACES 5
+
+
+#include "Bullet3Common/shared/b3Int4.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h"
+#include "Bullet3Collision/BroadPhaseCollision/shared/b3Aabb.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3BvhSubtreeInfoData.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3QuantizedBvhNodeData.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h"
+
+
+inline void b3Project(__global const b3ConvexPolyhedronData* hull, b3Float4ConstArg pos, b3QuatConstArg orn,
+const b3Float4* dir, __global const b3Float4* vertices, float* min, float* max)
+{
+ min[0] = FLT_MAX;
+ max[0] = -FLT_MAX;
+ int numVerts = hull->m_numVertices;
+
+ const b3Float4 localDir = b3QuatRotate(b3QuatInverse(orn),*dir);
+ float offset = b3Dot(pos,*dir);
+ for(int i=0;i<numVerts;i++)
+ {
+ float dp = b3Dot(vertices[hull->m_vertexOffset+i],localDir);
+ if(dp < min[0])
+ min[0] = dp;
+ if(dp > max[0])
+ max[0] = dp;
+ }
+ if(min[0]>max[0])
+ {
+ float tmp = min[0];
+ min[0] = max[0];
+ max[0] = tmp;
+ }
+ min[0] += offset;
+ max[0] += offset;
+}
+
+
+inline bool b3TestSepAxis(const b3ConvexPolyhedronData* hullA, __global const b3ConvexPolyhedronData* hullB,
+ b3Float4ConstArg posA,b3QuatConstArg ornA,
+ b3Float4ConstArg posB,b3QuatConstArg ornB,
+ b3Float4* sep_axis, const b3Float4* verticesA, __global const b3Float4* verticesB,float* depth)
+{
+ float Min0,Max0;
+ float Min1,Max1;
+ b3Project(hullA,posA,ornA,sep_axis,verticesA, &Min0, &Max0);
+ b3Project(hullB,posB,ornB, sep_axis,verticesB, &Min1, &Max1);
+
+ if(Max0<Min1 || Max1<Min0)
+ return false;
+
+ float d0 = Max0 - Min1;
+ float d1 = Max1 - Min0;
+ *depth = d0<d1 ? d0:d1;
+ return true;
+}
+
+
+bool b3FindSeparatingAxis( const b3ConvexPolyhedronData* hullA, __global const b3ConvexPolyhedronData* hullB,
+ b3Float4ConstArg posA1,
+ b3QuatConstArg ornA,
+ b3Float4ConstArg posB1,
+ b3QuatConstArg ornB,
+ b3Float4ConstArg DeltaC2,
+
+ const b3Float4* verticesA,
+ const b3Float4* uniqueEdgesA,
+ const b3GpuFace* facesA,
+ const int* indicesA,
+
+ __global const b3Float4* verticesB,
+ __global const b3Float4* uniqueEdgesB,
+ __global const b3GpuFace* facesB,
+ __global const int* indicesB,
+ b3Float4* sep,
+ float* dmin)
+{
+
+
+ b3Float4 posA = posA1;
+ posA.w = 0.f;
+ b3Float4 posB = posB1;
+ posB.w = 0.f;
+/*
+ static int maxFaceVertex = 0;
+
+ int curFaceVertexAB = hullA->m_numFaces*hullB->m_numVertices;
+ curFaceVertexAB+= hullB->m_numFaces*hullA->m_numVertices;
+
+ if (curFaceVertexAB>maxFaceVertex)
+ {
+ maxFaceVertex = curFaceVertexAB;
+ printf("curFaceVertexAB = %d\n",curFaceVertexAB);
+ printf("hullA->m_numFaces = %d\n",hullA->m_numFaces);
+ printf("hullA->m_numVertices = %d\n",hullA->m_numVertices);
+ printf("hullB->m_numVertices = %d\n",hullB->m_numVertices);
+ }
+*/
+
+ int curPlaneTests=0;
+ {
+ int numFacesA = hullA->m_numFaces;
+ // Test normals from hullA
+ for(int i=0;i<numFacesA;i++)
+ {
+ const b3Float4 normal = facesA[hullA->m_faceOffset+i].m_plane;
+ b3Float4 faceANormalWS = b3QuatRotate(ornA,normal);
+ if (b3Dot(DeltaC2,faceANormalWS)<0)
+ faceANormalWS*=-1.f;
+ curPlaneTests++;
+ float d;
+ if(!b3TestSepAxis( hullA, hullB, posA,ornA,posB,ornB,&faceANormalWS, verticesA, verticesB,&d))
+ return false;
+ if(d<*dmin)
+ {
+ *dmin = d;
+ *sep = faceANormalWS;
+ }
+ }
+ }
+ if((b3Dot(-DeltaC2,*sep))>0.0f)
+ {
+ *sep = -(*sep);
+ }
+ return true;
+}
+
+
+b3Vector3 unitSphere162[]=
+{
+ b3MakeVector3(0.000000,-1.000000,0.000000),
+b3MakeVector3(0.203181,-0.967950,0.147618),
+b3MakeVector3(-0.077607,-0.967950,0.238853),
+b3MakeVector3(0.723607,-0.447220,0.525725),
+b3MakeVector3(0.609547,-0.657519,0.442856),
+b3MakeVector3(0.812729,-0.502301,0.295238),
+b3MakeVector3(-0.251147,-0.967949,0.000000),
+b3MakeVector3(-0.077607,-0.967950,-0.238853),
+b3MakeVector3(0.203181,-0.967950,-0.147618),
+b3MakeVector3(0.860698,-0.251151,0.442858),
+b3MakeVector3(-0.276388,-0.447220,0.850649),
+b3MakeVector3(-0.029639,-0.502302,0.864184),
+b3MakeVector3(-0.155215,-0.251152,0.955422),
+b3MakeVector3(-0.894426,-0.447216,0.000000),
+b3MakeVector3(-0.831051,-0.502299,0.238853),
+b3MakeVector3(-0.956626,-0.251149,0.147618),
+b3MakeVector3(-0.276388,-0.447220,-0.850649),
+b3MakeVector3(-0.483971,-0.502302,-0.716565),
+b3MakeVector3(-0.436007,-0.251152,-0.864188),
+b3MakeVector3(0.723607,-0.447220,-0.525725),
+b3MakeVector3(0.531941,-0.502302,-0.681712),
+b3MakeVector3(0.687159,-0.251152,-0.681715),
+b3MakeVector3(0.687159,-0.251152,0.681715),
+b3MakeVector3(-0.436007,-0.251152,0.864188),
+b3MakeVector3(-0.956626,-0.251149,-0.147618),
+b3MakeVector3(-0.155215,-0.251152,-0.955422),
+b3MakeVector3(0.860698,-0.251151,-0.442858),
+b3MakeVector3(0.276388,0.447220,0.850649),
+b3MakeVector3(0.483971,0.502302,0.716565),
+b3MakeVector3(0.232822,0.657519,0.716563),
+b3MakeVector3(-0.723607,0.447220,0.525725),
+b3MakeVector3(-0.531941,0.502302,0.681712),
+b3MakeVector3(-0.609547,0.657519,0.442856),
+b3MakeVector3(-0.723607,0.447220,-0.525725),
+b3MakeVector3(-0.812729,0.502301,-0.295238),
+b3MakeVector3(-0.609547,0.657519,-0.442856),
+b3MakeVector3(0.276388,0.447220,-0.850649),
+b3MakeVector3(0.029639,0.502302,-0.864184),
+b3MakeVector3(0.232822,0.657519,-0.716563),
+b3MakeVector3(0.894426,0.447216,0.000000),
+b3MakeVector3(0.831051,0.502299,-0.238853),
+b3MakeVector3(0.753442,0.657515,0.000000),
+b3MakeVector3(-0.232822,-0.657519,0.716563),
+b3MakeVector3(-0.162456,-0.850654,0.499995),
+b3MakeVector3(0.052790,-0.723612,0.688185),
+b3MakeVector3(0.138199,-0.894429,0.425321),
+b3MakeVector3(0.262869,-0.525738,0.809012),
+b3MakeVector3(0.361805,-0.723611,0.587779),
+b3MakeVector3(0.531941,-0.502302,0.681712),
+b3MakeVector3(0.425323,-0.850654,0.309011),
+b3MakeVector3(0.812729,-0.502301,-0.295238),
+b3MakeVector3(0.609547,-0.657519,-0.442856),
+b3MakeVector3(0.850648,-0.525736,0.000000),
+b3MakeVector3(0.670817,-0.723611,-0.162457),
+b3MakeVector3(0.670817,-0.723610,0.162458),
+b3MakeVector3(0.425323,-0.850654,-0.309011),
+b3MakeVector3(0.447211,-0.894428,0.000001),
+b3MakeVector3(-0.753442,-0.657515,0.000000),
+b3MakeVector3(-0.525730,-0.850652,0.000000),
+b3MakeVector3(-0.638195,-0.723609,0.262864),
+b3MakeVector3(-0.361801,-0.894428,0.262864),
+b3MakeVector3(-0.688189,-0.525736,0.499997),
+b3MakeVector3(-0.447211,-0.723610,0.525729),
+b3MakeVector3(-0.483971,-0.502302,0.716565),
+b3MakeVector3(-0.232822,-0.657519,-0.716563),
+b3MakeVector3(-0.162456,-0.850654,-0.499995),
+b3MakeVector3(-0.447211,-0.723611,-0.525727),
+b3MakeVector3(-0.361801,-0.894429,-0.262863),
+b3MakeVector3(-0.688189,-0.525736,-0.499997),
+b3MakeVector3(-0.638195,-0.723609,-0.262863),
+b3MakeVector3(-0.831051,-0.502299,-0.238853),
+b3MakeVector3(0.361804,-0.723612,-0.587779),
+b3MakeVector3(0.138197,-0.894429,-0.425321),
+b3MakeVector3(0.262869,-0.525738,-0.809012),
+b3MakeVector3(0.052789,-0.723611,-0.688186),
+b3MakeVector3(-0.029639,-0.502302,-0.864184),
+b3MakeVector3(0.956626,0.251149,0.147618),
+b3MakeVector3(0.956626,0.251149,-0.147618),
+b3MakeVector3(0.951058,-0.000000,0.309013),
+b3MakeVector3(1.000000,0.000000,0.000000),
+b3MakeVector3(0.947213,-0.276396,0.162458),
+b3MakeVector3(0.951058,0.000000,-0.309013),
+b3MakeVector3(0.947213,-0.276396,-0.162458),
+b3MakeVector3(0.155215,0.251152,0.955422),
+b3MakeVector3(0.436007,0.251152,0.864188),
+b3MakeVector3(-0.000000,-0.000000,1.000000),
+b3MakeVector3(0.309017,0.000000,0.951056),
+b3MakeVector3(0.138199,-0.276398,0.951055),
+b3MakeVector3(0.587786,0.000000,0.809017),
+b3MakeVector3(0.447216,-0.276398,0.850648),
+b3MakeVector3(-0.860698,0.251151,0.442858),
+b3MakeVector3(-0.687159,0.251152,0.681715),
+b3MakeVector3(-0.951058,-0.000000,0.309013),
+b3MakeVector3(-0.809018,0.000000,0.587783),
+b3MakeVector3(-0.861803,-0.276396,0.425324),
+b3MakeVector3(-0.587786,0.000000,0.809017),
+b3MakeVector3(-0.670819,-0.276397,0.688191),
+b3MakeVector3(-0.687159,0.251152,-0.681715),
+b3MakeVector3(-0.860698,0.251151,-0.442858),
+b3MakeVector3(-0.587786,-0.000000,-0.809017),
+b3MakeVector3(-0.809018,-0.000000,-0.587783),
+b3MakeVector3(-0.670819,-0.276397,-0.688191),
+b3MakeVector3(-0.951058,0.000000,-0.309013),
+b3MakeVector3(-0.861803,-0.276396,-0.425324),
+b3MakeVector3(0.436007,0.251152,-0.864188),
+b3MakeVector3(0.155215,0.251152,-0.955422),
+b3MakeVector3(0.587786,-0.000000,-0.809017),
+b3MakeVector3(0.309017,-0.000000,-0.951056),
+b3MakeVector3(0.447216,-0.276398,-0.850648),
+b3MakeVector3(0.000000,0.000000,-1.000000),
+b3MakeVector3(0.138199,-0.276398,-0.951055),
+b3MakeVector3(0.670820,0.276396,0.688190),
+b3MakeVector3(0.809019,-0.000002,0.587783),
+b3MakeVector3(0.688189,0.525736,0.499997),
+b3MakeVector3(0.861804,0.276394,0.425323),
+b3MakeVector3(0.831051,0.502299,0.238853),
+b3MakeVector3(-0.447216,0.276397,0.850649),
+b3MakeVector3(-0.309017,-0.000001,0.951056),
+b3MakeVector3(-0.262869,0.525738,0.809012),
+b3MakeVector3(-0.138199,0.276397,0.951055),
+b3MakeVector3(0.029639,0.502302,0.864184),
+b3MakeVector3(-0.947213,0.276396,-0.162458),
+b3MakeVector3(-1.000000,0.000001,0.000000),
+b3MakeVector3(-0.850648,0.525736,-0.000000),
+b3MakeVector3(-0.947213,0.276397,0.162458),
+b3MakeVector3(-0.812729,0.502301,0.295238),
+b3MakeVector3(-0.138199,0.276397,-0.951055),
+b3MakeVector3(-0.309016,-0.000000,-0.951057),
+b3MakeVector3(-0.262869,0.525738,-0.809012),
+b3MakeVector3(-0.447215,0.276397,-0.850649),
+b3MakeVector3(-0.531941,0.502302,-0.681712),
+b3MakeVector3(0.861804,0.276396,-0.425322),
+b3MakeVector3(0.809019,0.000000,-0.587782),
+b3MakeVector3(0.688189,0.525736,-0.499997),
+b3MakeVector3(0.670821,0.276397,-0.688189),
+b3MakeVector3(0.483971,0.502302,-0.716565),
+b3MakeVector3(0.077607,0.967950,0.238853),
+b3MakeVector3(0.251147,0.967949,0.000000),
+b3MakeVector3(0.000000,1.000000,0.000000),
+b3MakeVector3(0.162456,0.850654,0.499995),
+b3MakeVector3(0.361800,0.894429,0.262863),
+b3MakeVector3(0.447209,0.723612,0.525728),
+b3MakeVector3(0.525730,0.850652,0.000000),
+b3MakeVector3(0.638194,0.723610,0.262864),
+b3MakeVector3(-0.203181,0.967950,0.147618),
+b3MakeVector3(-0.425323,0.850654,0.309011),
+b3MakeVector3(-0.138197,0.894430,0.425320),
+b3MakeVector3(-0.361804,0.723612,0.587778),
+b3MakeVector3(-0.052790,0.723612,0.688185),
+b3MakeVector3(-0.203181,0.967950,-0.147618),
+b3MakeVector3(-0.425323,0.850654,-0.309011),
+b3MakeVector3(-0.447210,0.894429,0.000000),
+b3MakeVector3(-0.670817,0.723611,-0.162457),
+b3MakeVector3(-0.670817,0.723611,0.162457),
+b3MakeVector3(0.077607,0.967950,-0.238853),
+b3MakeVector3(0.162456,0.850654,-0.499995),
+b3MakeVector3(-0.138197,0.894430,-0.425320),
+b3MakeVector3(-0.052790,0.723612,-0.688185),
+b3MakeVector3(-0.361804,0.723612,-0.587778),
+b3MakeVector3(0.361800,0.894429,-0.262863),
+b3MakeVector3(0.638194,0.723610,-0.262864),
+b3MakeVector3(0.447209,0.723612,-0.525728)
+};
+
+
+bool b3FindSeparatingAxisEdgeEdge( const b3ConvexPolyhedronData* hullA, __global const b3ConvexPolyhedronData* hullB,
+ b3Float4ConstArg posA1,
+ b3QuatConstArg ornA,
+ b3Float4ConstArg posB1,
+ b3QuatConstArg ornB,
+ b3Float4ConstArg DeltaC2,
+ const b3Float4* verticesA,
+ const b3Float4* uniqueEdgesA,
+ const b3GpuFace* facesA,
+ const int* indicesA,
+ __global const b3Float4* verticesB,
+ __global const b3Float4* uniqueEdgesB,
+ __global const b3GpuFace* facesB,
+ __global const int* indicesB,
+ b3Float4* sep,
+ float* dmin,
+ bool searchAllEdgeEdge)
+{
+
+
+ b3Float4 posA = posA1;
+ posA.w = 0.f;
+ b3Float4 posB = posB1;
+ posB.w = 0.f;
+
+// int curPlaneTests=0;
+
+ int curEdgeEdge = 0;
+ // Test edges
+ static int maxEdgeTests = 0;
+ int curEdgeTests = hullA->m_numUniqueEdges * hullB->m_numUniqueEdges;
+ if (curEdgeTests >maxEdgeTests )
+ {
+ maxEdgeTests = curEdgeTests ;
+ printf("maxEdgeTests = %d\n",maxEdgeTests );
+ printf("hullA->m_numUniqueEdges = %d\n",hullA->m_numUniqueEdges);
+ printf("hullB->m_numUniqueEdges = %d\n",hullB->m_numUniqueEdges);
+
+ }
+
+
+ if (searchAllEdgeEdge)
+ {
+ for(int e0=0;e0<hullA->m_numUniqueEdges;e0++)
+ {
+ const b3Float4 edge0 = uniqueEdgesA[hullA->m_uniqueEdgesOffset+e0];
+ b3Float4 edge0World = b3QuatRotate(ornA,edge0);
+
+ for(int e1=0;e1<hullB->m_numUniqueEdges;e1++)
+ {
+ const b3Float4 edge1 = uniqueEdgesB[hullB->m_uniqueEdgesOffset+e1];
+ b3Float4 edge1World = b3QuatRotate(ornB,edge1);
+
+
+ b3Float4 crossje = b3Cross(edge0World,edge1World);
+
+ curEdgeEdge++;
+ if(!b3IsAlmostZero(crossje))
+ {
+ crossje = b3Normalized(crossje);
+ if (b3Dot(DeltaC2,crossje)<0)
+ crossje *= -1.f;
+
+ float dist;
+ bool result = true;
+ {
+ float Min0,Max0;
+ float Min1,Max1;
+ b3Project(hullA,posA,ornA,&crossje,verticesA, &Min0, &Max0);
+ b3Project(hullB,posB,ornB,&crossje,verticesB, &Min1, &Max1);
+
+ if(Max0<Min1 || Max1<Min0)
+ return false;
+
+ float d0 = Max0 - Min1;
+ float d1 = Max1 - Min0;
+ dist = d0<d1 ? d0:d1;
+ result = true;
+
+ }
+
+
+ if(dist<*dmin)
+ {
+ *dmin = dist;
+ *sep = crossje;
+ }
+ }
+ }
+
+ }
+ } else
+ {
+ int numDirections = sizeof(unitSphere162)/sizeof(b3Vector3);
+ //printf("numDirections =%d\n",numDirections );
+
+
+ for(int i=0;i<numDirections;i++)
+ {
+ b3Float4 crossje = unitSphere162[i];
+ {
+ //if (b3Dot(DeltaC2,crossje)>0)
+ {
+ float dist;
+ bool result = true;
+ {
+ float Min0,Max0;
+ float Min1,Max1;
+ b3Project(hullA,posA,ornA,&crossje,verticesA, &Min0, &Max0);
+ b3Project(hullB,posB,ornB,&crossje,verticesB, &Min1, &Max1);
+
+ if(Max0<Min1 || Max1<Min0)
+ return false;
+
+ float d0 = Max0 - Min1;
+ float d1 = Max1 - Min0;
+ dist = d0<d1 ? d0:d1;
+ result = true;
+
+ }
+
+
+ if(dist<*dmin)
+ {
+ *dmin = dist;
+ *sep = crossje;
+ }
+ }
+ }
+ }
+
+ }
+
+
+ if((b3Dot(-DeltaC2,*sep))>0.0f)
+ {
+ *sep = -(*sep);
+ }
+ return true;
+}
+
+
+
+inline int b3FindClippingFaces(b3Float4ConstArg separatingNormal,
+ __global const b3ConvexPolyhedronData_t* hullA, __global const b3ConvexPolyhedronData_t* hullB,
+ b3Float4ConstArg posA, b3QuatConstArg ornA,b3Float4ConstArg posB, b3QuatConstArg ornB,
+ __global b3Float4* worldVertsA1,
+ __global b3Float4* worldNormalsA1,
+ __global b3Float4* worldVertsB1,
+ int capacityWorldVerts,
+ const float minDist, float maxDist,
+ __global const b3Float4* verticesA,
+ __global const b3GpuFace_t* facesA,
+ __global const int* indicesA,
+ __global const b3Float4* verticesB,
+ __global const b3GpuFace_t* facesB,
+ __global const int* indicesB,
+
+ __global b3Int4* clippingFaces, int pairIndex)
+{
+ int numContactsOut = 0;
+ int numWorldVertsB1= 0;
+
+
+ int closestFaceB=-1;
+ float dmax = -FLT_MAX;
+
+ {
+ for(int face=0;face<hullB->m_numFaces;face++)
+ {
+ const b3Float4 Normal = b3MakeFloat4(facesB[hullB->m_faceOffset+face].m_plane.x,
+ facesB[hullB->m_faceOffset+face].m_plane.y, facesB[hullB->m_faceOffset+face].m_plane.z,0.f);
+ const b3Float4 WorldNormal = b3QuatRotate(ornB, Normal);
+ float d = b3Dot(WorldNormal,separatingNormal);
+ if (d > dmax)
+ {
+ dmax = d;
+ closestFaceB = face;
+ }
+ }
+ }
+
+ {
+ const b3GpuFace_t polyB = facesB[hullB->m_faceOffset+closestFaceB];
+ const int numVertices = polyB.m_numIndices;
+ for(int e0=0;e0<numVertices;e0++)
+ {
+ const b3Float4 b = verticesB[hullB->m_vertexOffset+indicesB[polyB.m_indexOffset+e0]];
+ worldVertsB1[pairIndex*capacityWorldVerts+numWorldVertsB1++] = b3TransformPoint(b,posB,ornB);
+ }
+ }
+
+ int closestFaceA=-1;
+ {
+ float dmin = FLT_MAX;
+ for(int face=0;face<hullA->m_numFaces;face++)
+ {
+ const b3Float4 Normal = b3MakeFloat4(
+ facesA[hullA->m_faceOffset+face].m_plane.x,
+ facesA[hullA->m_faceOffset+face].m_plane.y,
+ facesA[hullA->m_faceOffset+face].m_plane.z,
+ 0.f);
+ const b3Float4 faceANormalWS = b3QuatRotate(ornA,Normal);
+
+ float d = b3Dot(faceANormalWS,separatingNormal);
+ if (d < dmin)
+ {
+ dmin = d;
+ closestFaceA = face;
+ worldNormalsA1[pairIndex] = faceANormalWS;
+ }
+ }
+ }
+
+ int numVerticesA = facesA[hullA->m_faceOffset+closestFaceA].m_numIndices;
+ for(int e0=0;e0<numVerticesA;e0++)
+ {
+ const b3Float4 a = verticesA[hullA->m_vertexOffset+indicesA[facesA[hullA->m_faceOffset+closestFaceA].m_indexOffset+e0]];
+ worldVertsA1[pairIndex*capacityWorldVerts+e0] = b3TransformPoint(a, posA,ornA);
+ }
+
+ clippingFaces[pairIndex].x = closestFaceA;
+ clippingFaces[pairIndex].y = closestFaceB;
+ clippingFaces[pairIndex].z = numVerticesA;
+ clippingFaces[pairIndex].w = numWorldVertsB1;
+
+
+ return numContactsOut;
+}
+
+
+
+
+__kernel void b3FindConcaveSeparatingAxisKernel( __global b3Int4* concavePairs,
+ __global const b3RigidBodyData* rigidBodies,
+ __global const b3Collidable* collidables,
+ __global const b3ConvexPolyhedronData* convexShapes,
+ __global const b3Float4* vertices,
+ __global const b3Float4* uniqueEdges,
+ __global const b3GpuFace* faces,
+ __global const int* indices,
+ __global const b3GpuChildShape* gpuChildShapes,
+ __global b3Aabb* aabbs,
+ __global b3Float4* concaveSeparatingNormalsOut,
+ __global b3Int4* clippingFacesOut,
+ __global b3Vector3* worldVertsA1Out,
+ __global b3Vector3* worldNormalsA1Out,
+ __global b3Vector3* worldVertsB1Out,
+ __global int* hasSeparatingNormals,
+ int vertexFaceCapacity,
+ int numConcavePairs,
+ int pairIdx
+ )
+{
+ int i = pairIdx;
+/* int i = get_global_id(0);
+ if (i>=numConcavePairs)
+ return;
+ int pairIdx = i;
+ */
+
+ int bodyIndexA = concavePairs[i].x;
+ int bodyIndexB = concavePairs[i].y;
+
+ int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
+ int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
+
+ int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
+ int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
+
+ if (collidables[collidableIndexB].m_shapeType!=SHAPE_CONVEX_HULL&&
+ collidables[collidableIndexB].m_shapeType!=SHAPE_COMPOUND_OF_CONVEX_HULLS)
+ {
+ concavePairs[pairIdx].w = -1;
+ return;
+ }
+
+ hasSeparatingNormals[i] = 0;
+
+// int numFacesA = convexShapes[shapeIndexA].m_numFaces;
+ int numActualConcaveConvexTests = 0;
+
+ int f = concavePairs[i].z;
+
+ bool overlap = false;
+
+ b3ConvexPolyhedronData convexPolyhedronA;
+
+ //add 3 vertices of the triangle
+ convexPolyhedronA.m_numVertices = 3;
+ convexPolyhedronA.m_vertexOffset = 0;
+ b3Float4 localCenter = b3MakeFloat4(0.f,0.f,0.f,0.f);
+
+ b3GpuFace face = faces[convexShapes[shapeIndexA].m_faceOffset+f];
+ b3Aabb triAabb;
+ triAabb.m_minVec = b3MakeFloat4(1e30f,1e30f,1e30f,0.f);
+ triAabb.m_maxVec = b3MakeFloat4(-1e30f,-1e30f,-1e30f,0.f);
+
+ b3Float4 verticesA[3];
+ for (int i=0;i<3;i++)
+ {
+ int index = indices[face.m_indexOffset+i];
+ b3Float4 vert = vertices[convexShapes[shapeIndexA].m_vertexOffset+index];
+ verticesA[i] = vert;
+ localCenter += vert;
+
+ triAabb.m_minVec = b3MinFloat4(triAabb.m_minVec,vert);
+ triAabb.m_maxVec = b3MaxFloat4(triAabb.m_maxVec,vert);
+
+ }
+
+ overlap = true;
+ overlap = (triAabb.m_minVec.x > aabbs[bodyIndexB].m_maxVec.x || triAabb.m_maxVec.x < aabbs[bodyIndexB].m_minVec.x) ? false : overlap;
+ overlap = (triAabb.m_minVec.z > aabbs[bodyIndexB].m_maxVec.z || triAabb.m_maxVec.z < aabbs[bodyIndexB].m_minVec.z) ? false : overlap;
+ overlap = (triAabb.m_minVec.y > aabbs[bodyIndexB].m_maxVec.y || triAabb.m_maxVec.y < aabbs[bodyIndexB].m_minVec.y) ? false : overlap;
+
+ if (overlap)
+ {
+ float dmin = FLT_MAX;
+ int hasSeparatingAxis=5;
+ b3Float4 sepAxis=b3MakeFloat4(1,2,3,4);
+
+ // int localCC=0;
+ numActualConcaveConvexTests++;
+
+ //a triangle has 3 unique edges
+ convexPolyhedronA.m_numUniqueEdges = 3;
+ convexPolyhedronA.m_uniqueEdgesOffset = 0;
+ b3Float4 uniqueEdgesA[3];
+
+ uniqueEdgesA[0] = (verticesA[1]-verticesA[0]);
+ uniqueEdgesA[1] = (verticesA[2]-verticesA[1]);
+ uniqueEdgesA[2] = (verticesA[0]-verticesA[2]);
+
+
+ convexPolyhedronA.m_faceOffset = 0;
+
+ b3Float4 normal = b3MakeFloat4(face.m_plane.x,face.m_plane.y,face.m_plane.z,0.f);
+
+ b3GpuFace facesA[B3_TRIANGLE_NUM_CONVEX_FACES];
+ int indicesA[3+3+2+2+2];
+ int curUsedIndices=0;
+ int fidx=0;
+
+ //front size of triangle
+ {
+ facesA[fidx].m_indexOffset=curUsedIndices;
+ indicesA[0] = 0;
+ indicesA[1] = 1;
+ indicesA[2] = 2;
+ curUsedIndices+=3;
+ float c = face.m_plane.w;
+ facesA[fidx].m_plane.x = normal.x;
+ facesA[fidx].m_plane.y = normal.y;
+ facesA[fidx].m_plane.z = normal.z;
+ facesA[fidx].m_plane.w = c;
+ facesA[fidx].m_numIndices=3;
+ }
+ fidx++;
+ //back size of triangle
+ {
+ facesA[fidx].m_indexOffset=curUsedIndices;
+ indicesA[3]=2;
+ indicesA[4]=1;
+ indicesA[5]=0;
+ curUsedIndices+=3;
+ float c = b3Dot(normal,verticesA[0]);
+ // float c1 = -face.m_plane.w;
+ facesA[fidx].m_plane.x = -normal.x;
+ facesA[fidx].m_plane.y = -normal.y;
+ facesA[fidx].m_plane.z = -normal.z;
+ facesA[fidx].m_plane.w = c;
+ facesA[fidx].m_numIndices=3;
+ }
+ fidx++;
+
+ bool addEdgePlanes = true;
+ if (addEdgePlanes)
+ {
+ int numVertices=3;
+ int prevVertex = numVertices-1;
+ for (int i=0;i<numVertices;i++)
+ {
+ b3Float4 v0 = verticesA[i];
+ b3Float4 v1 = verticesA[prevVertex];
+
+ b3Float4 edgeNormal = b3Normalized(b3Cross(normal,v1-v0));
+ float c = -b3Dot(edgeNormal,v0);
+
+ facesA[fidx].m_numIndices = 2;
+ facesA[fidx].m_indexOffset=curUsedIndices;
+ indicesA[curUsedIndices++]=i;
+ indicesA[curUsedIndices++]=prevVertex;
+
+ facesA[fidx].m_plane.x = edgeNormal.x;
+ facesA[fidx].m_plane.y = edgeNormal.y;
+ facesA[fidx].m_plane.z = edgeNormal.z;
+ facesA[fidx].m_plane.w = c;
+ fidx++;
+ prevVertex = i;
+ }
+ }
+ convexPolyhedronA.m_numFaces = B3_TRIANGLE_NUM_CONVEX_FACES;
+ convexPolyhedronA.m_localCenter = localCenter*(1.f/3.f);
+
+
+ b3Float4 posA = rigidBodies[bodyIndexA].m_pos;
+ posA.w = 0.f;
+ b3Float4 posB = rigidBodies[bodyIndexB].m_pos;
+ posB.w = 0.f;
+
+ b3Quaternion ornA = rigidBodies[bodyIndexA].m_quat;
+ b3Quaternion ornB =rigidBodies[bodyIndexB].m_quat;
+
+
+
+
+ ///////////////////
+ ///compound shape support
+
+ if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)
+ {
+ int compoundChild = concavePairs[pairIdx].w;
+ int childShapeIndexB = compoundChild;//collidables[collidableIndexB].m_shapeIndex+compoundChild;
+ int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;
+ b3Float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;
+ b3Quaternion childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;
+ b3Float4 newPosB = b3TransformPoint(childPosB,posB,ornB);
+ b3Quaternion newOrnB = b3QuatMul(ornB,childOrnB);
+ posB = newPosB;
+ ornB = newOrnB;
+ shapeIndexB = collidables[childColIndexB].m_shapeIndex;
+ }
+ //////////////////
+
+ b3Float4 c0local = convexPolyhedronA.m_localCenter;
+ b3Float4 c0 = b3TransformPoint(c0local, posA, ornA);
+ b3Float4 c1local = convexShapes[shapeIndexB].m_localCenter;
+ b3Float4 c1 = b3TransformPoint(c1local,posB,ornB);
+ const b3Float4 DeltaC2 = c0 - c1;
+
+
+ bool sepA = b3FindSeparatingAxis( &convexPolyhedronA, &convexShapes[shapeIndexB],
+ posA,ornA,
+ posB,ornB,
+ DeltaC2,
+ verticesA,uniqueEdgesA,facesA,indicesA,
+ vertices,uniqueEdges,faces,indices,
+ &sepAxis,&dmin);
+ hasSeparatingAxis = 4;
+ if (!sepA)
+ {
+ hasSeparatingAxis = 0;
+ } else
+ {
+ bool sepB = b3FindSeparatingAxis( &convexShapes[shapeIndexB],&convexPolyhedronA,
+ posB,ornB,
+ posA,ornA,
+ DeltaC2,
+ vertices,uniqueEdges,faces,indices,
+ verticesA,uniqueEdgesA,facesA,indicesA,
+ &sepAxis,&dmin);
+
+ if (!sepB)
+ {
+ hasSeparatingAxis = 0;
+ } else
+ {
+ bool sepEE = b3FindSeparatingAxisEdgeEdge( &convexPolyhedronA, &convexShapes[shapeIndexB],
+ posA,ornA,
+ posB,ornB,
+ DeltaC2,
+ verticesA,uniqueEdgesA,facesA,indicesA,
+ vertices,uniqueEdges,faces,indices,
+ &sepAxis,&dmin,true);
+
+ if (!sepEE)
+ {
+ hasSeparatingAxis = 0;
+ } else
+ {
+ hasSeparatingAxis = 1;
+ }
+ }
+ }
+
+ if (hasSeparatingAxis)
+ {
+ hasSeparatingNormals[i]=1;
+ sepAxis.w = dmin;
+ concaveSeparatingNormalsOut[pairIdx]=sepAxis;
+
+ //now compute clipping faces A and B, and world-space clipping vertices A and B...
+
+ float minDist = -1e30f;
+ float maxDist = 0.02f;
+
+ b3FindClippingFaces(sepAxis,
+ &convexPolyhedronA,
+ &convexShapes[shapeIndexB],
+ posA,ornA,
+ posB,ornB,
+ worldVertsA1Out,
+ worldNormalsA1Out,
+ worldVertsB1Out,
+ vertexFaceCapacity,
+ minDist, maxDist,
+ verticesA,
+ facesA,
+ indicesA,
+
+ vertices,
+ faces,
+ indices,
+ clippingFacesOut, pairIdx);
+
+ } else
+ {
+ //mark this pair as in-active
+ concavePairs[pairIdx].w = -1;
+ }
+ }
+ else
+ {
+ //mark this pair as in-active
+ concavePairs[pairIdx].w = -1;
+ }
+}
+
+
+#endif //B3_FIND_CONCAVE_SEPARATING_AXIS_H
+
diff --git a/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3FindSeparatingAxis.h b/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3FindSeparatingAxis.h
new file mode 100644
index 0000000000..332dbc278c
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3FindSeparatingAxis.h
@@ -0,0 +1,206 @@
+#ifndef B3_FIND_SEPARATING_AXIS_H
+#define B3_FIND_SEPARATING_AXIS_H
+
+
+inline void b3ProjectAxis(const b3ConvexPolyhedronData& hull, const b3Float4& pos, const b3Quaternion& orn, const b3Float4& dir, const b3AlignedObjectArray<b3Vector3>& vertices, b3Scalar& min, b3Scalar& max)
+{
+ min = FLT_MAX;
+ max = -FLT_MAX;
+ int numVerts = hull.m_numVertices;
+
+ const b3Float4 localDir = b3QuatRotate(orn.inverse(),dir);
+
+ b3Scalar offset = b3Dot3F4(pos,dir);
+
+ for(int i=0;i<numVerts;i++)
+ {
+ //b3Vector3 pt = trans * vertices[m_vertexOffset+i];
+ //b3Scalar dp = pt.dot(dir);
+ //b3Vector3 vertex = vertices[hull.m_vertexOffset+i];
+ b3Scalar dp = b3Dot3F4((b3Float4&)vertices[hull.m_vertexOffset+i],localDir);
+ //b3Assert(dp==dpL);
+ if(dp < min) min = dp;
+ if(dp > max) max = dp;
+ }
+ if(min>max)
+ {
+ b3Scalar tmp = min;
+ min = max;
+ max = tmp;
+ }
+ min += offset;
+ max += offset;
+}
+
+
+inline bool b3TestSepAxis(const b3ConvexPolyhedronData& hullA, const b3ConvexPolyhedronData& hullB,
+ const b3Float4& posA,const b3Quaternion& ornA,
+ const b3Float4& posB,const b3Quaternion& ornB,
+ const b3Float4& sep_axis, const b3AlignedObjectArray<b3Vector3>& verticesA,const b3AlignedObjectArray<b3Vector3>& verticesB,b3Scalar& depth)
+{
+ b3Scalar Min0,Max0;
+ b3Scalar Min1,Max1;
+ b3ProjectAxis(hullA,posA,ornA,sep_axis,verticesA, Min0, Max0);
+ b3ProjectAxis(hullB,posB,ornB, sep_axis,verticesB, Min1, Max1);
+
+ if(Max0<Min1 || Max1<Min0)
+ return false;
+
+ b3Scalar d0 = Max0 - Min1;
+ b3Assert(d0>=0.0f);
+ b3Scalar d1 = Max1 - Min0;
+ b3Assert(d1>=0.0f);
+ depth = d0<d1 ? d0:d1;
+ return true;
+}
+
+
+inline bool b3FindSeparatingAxis( const b3ConvexPolyhedronData& hullA, const b3ConvexPolyhedronData& hullB,
+ const b3Float4& posA1,
+ const b3Quaternion& ornA,
+ const b3Float4& posB1,
+ const b3Quaternion& ornB,
+ const b3AlignedObjectArray<b3Vector3>& verticesA,
+ const b3AlignedObjectArray<b3Vector3>& uniqueEdgesA,
+ const b3AlignedObjectArray<b3GpuFace>& facesA,
+ const b3AlignedObjectArray<int>& indicesA,
+ const b3AlignedObjectArray<b3Vector3>& verticesB,
+ const b3AlignedObjectArray<b3Vector3>& uniqueEdgesB,
+ const b3AlignedObjectArray<b3GpuFace>& facesB,
+ const b3AlignedObjectArray<int>& indicesB,
+
+ b3Vector3& sep)
+{
+ B3_PROFILE("findSeparatingAxis");
+
+ b3Float4 posA = posA1;
+ posA.w = 0.f;
+ b3Float4 posB = posB1;
+ posB.w = 0.f;
+//#ifdef TEST_INTERNAL_OBJECTS
+ b3Float4 c0local = (b3Float4&)hullA.m_localCenter;
+
+ b3Float4 c0 = b3TransformPoint(c0local, posA, ornA);
+ b3Float4 c1local = (b3Float4&)hullB.m_localCenter;
+ b3Float4 c1 = b3TransformPoint(c1local,posB,ornB);
+ const b3Float4 deltaC2 = c0 - c1;
+//#endif
+
+ b3Scalar dmin = FLT_MAX;
+ int curPlaneTests=0;
+
+ int numFacesA = hullA.m_numFaces;
+ // Test normals from hullA
+ for(int i=0;i<numFacesA;i++)
+ {
+ const b3Float4& normal = (b3Float4&)facesA[hullA.m_faceOffset+i].m_plane;
+ b3Float4 faceANormalWS = b3QuatRotate(ornA,normal);
+
+ if (b3Dot3F4(deltaC2,faceANormalWS)<0)
+ faceANormalWS*=-1.f;
+
+ curPlaneTests++;
+#ifdef TEST_INTERNAL_OBJECTS
+ gExpectedNbTests++;
+ if(gUseInternalObject && !TestInternalObjects(transA,transB, DeltaC2, faceANormalWS, hullA, hullB, dmin))
+ continue;
+ gActualNbTests++;
+#endif
+
+
+ b3Scalar d;
+ if(!b3TestSepAxis( hullA, hullB, posA,ornA,posB,ornB,faceANormalWS, verticesA, verticesB,d))
+ return false;
+
+ if(d<dmin)
+ {
+ dmin = d;
+ sep = (b3Vector3&)faceANormalWS;
+ }
+ }
+
+ int numFacesB = hullB.m_numFaces;
+ // Test normals from hullB
+ for(int i=0;i<numFacesB;i++)
+ {
+ b3Float4 normal = (b3Float4&)facesB[hullB.m_faceOffset+i].m_plane;
+ b3Float4 WorldNormal = b3QuatRotate(ornB, normal);
+
+ if (b3Dot3F4(deltaC2,WorldNormal)<0)
+ {
+ WorldNormal*=-1.f;
+ }
+ curPlaneTests++;
+#ifdef TEST_INTERNAL_OBJECTS
+ gExpectedNbTests++;
+ if(gUseInternalObject && !TestInternalObjects(transA,transB,DeltaC2, WorldNormal, hullA, hullB, dmin))
+ continue;
+ gActualNbTests++;
+#endif
+
+ b3Scalar d;
+ if(!b3TestSepAxis(hullA, hullB,posA,ornA,posB,ornB,WorldNormal,verticesA,verticesB,d))
+ return false;
+
+ if(d<dmin)
+ {
+ dmin = d;
+ sep = (b3Vector3&)WorldNormal;
+ }
+ }
+
+// b3Vector3 edgeAstart,edgeAend,edgeBstart,edgeBend;
+
+ int curEdgeEdge = 0;
+ // Test edges
+ for(int e0=0;e0<hullA.m_numUniqueEdges;e0++)
+ {
+ const b3Float4& edge0 = (b3Float4&) uniqueEdgesA[hullA.m_uniqueEdgesOffset+e0];
+ b3Float4 edge0World = b3QuatRotate(ornA,(b3Float4&)edge0);
+
+ for(int e1=0;e1<hullB.m_numUniqueEdges;e1++)
+ {
+ const b3Vector3 edge1 = uniqueEdgesB[hullB.m_uniqueEdgesOffset+e1];
+ b3Float4 edge1World = b3QuatRotate(ornB,(b3Float4&)edge1);
+
+
+ b3Float4 crossje = b3Cross3(edge0World,edge1World);
+
+ curEdgeEdge++;
+ if(!b3IsAlmostZero((b3Vector3&)crossje))
+ {
+ crossje = b3FastNormalized3(crossje);
+ if (b3Dot3F4(deltaC2,crossje)<0)
+ crossje*=-1.f;
+
+
+#ifdef TEST_INTERNAL_OBJECTS
+ gExpectedNbTests++;
+ if(gUseInternalObject && !TestInternalObjects(transA,transB,DeltaC2, Cross, hullA, hullB, dmin))
+ continue;
+ gActualNbTests++;
+#endif
+
+ b3Scalar dist;
+ if(!b3TestSepAxis( hullA, hullB, posA,ornA,posB,ornB,crossje, verticesA,verticesB,dist))
+ return false;
+
+ if(dist<dmin)
+ {
+ dmin = dist;
+ sep = (b3Vector3&)crossje;
+ }
+ }
+ }
+
+ }
+
+
+ if((b3Dot3F4(-deltaC2,(b3Float4&)sep))>0.0f)
+ sep = -sep;
+
+ return true;
+}
+
+#endif //B3_FIND_SEPARATING_AXIS_H
+
diff --git a/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3MprPenetration.h b/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3MprPenetration.h
new file mode 100644
index 0000000000..6c3ad7c9dd
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3MprPenetration.h
@@ -0,0 +1,920 @@
+
+/***
+ * ---------------------------------
+ * Copyright (c)2012 Daniel Fiser <danfis@danfis.cz>
+ *
+ * This file was ported from mpr.c file, part of libccd.
+ * The Minkoski Portal Refinement implementation was ported
+ * to OpenCL by Erwin Coumans for the Bullet 3 Physics library.
+ * at http://github.com/erwincoumans/bullet3
+ *
+ * Distributed under the OSI-approved BSD License (the "License");
+ * see <http://www.opensource.org/licenses/bsd-license.php>.
+ * This software is distributed WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the License for more information.
+ */
+
+
+
+
+#ifndef B3_MPR_PENETRATION_H
+#define B3_MPR_PENETRATION_H
+
+#include "Bullet3Common/shared/b3PlatformDefinitions.h"
+#include "Bullet3Common/shared/b3Float4.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h"
+
+
+
+
+#ifdef __cplusplus
+#define B3_MPR_SQRT sqrtf
+#else
+#define B3_MPR_SQRT sqrt
+#endif
+#define B3_MPR_FMIN(x, y) ((x) < (y) ? (x) : (y))
+#define B3_MPR_FABS fabs
+
+#define B3_MPR_TOLERANCE 1E-6f
+#define B3_MPR_MAX_ITERATIONS 1000
+
+struct _b3MprSupport_t
+{
+ b3Float4 v; //!< Support point in minkowski sum
+ b3Float4 v1; //!< Support point in obj1
+ b3Float4 v2; //!< Support point in obj2
+};
+typedef struct _b3MprSupport_t b3MprSupport_t;
+
+struct _b3MprSimplex_t
+{
+ b3MprSupport_t ps[4];
+ int last; //!< index of last added point
+};
+typedef struct _b3MprSimplex_t b3MprSimplex_t;
+
+inline b3MprSupport_t* b3MprSimplexPointW(b3MprSimplex_t *s, int idx)
+{
+ return &s->ps[idx];
+}
+
+inline void b3MprSimplexSetSize(b3MprSimplex_t *s, int size)
+{
+ s->last = size - 1;
+}
+
+
+inline int b3MprSimplexSize(const b3MprSimplex_t *s)
+{
+ return s->last + 1;
+}
+
+
+inline const b3MprSupport_t* b3MprSimplexPoint(const b3MprSimplex_t* s, int idx)
+{
+ // here is no check on boundaries
+ return &s->ps[idx];
+}
+
+inline void b3MprSupportCopy(b3MprSupport_t *d, const b3MprSupport_t *s)
+{
+ *d = *s;
+}
+
+inline void b3MprSimplexSet(b3MprSimplex_t *s, size_t pos, const b3MprSupport_t *a)
+{
+ b3MprSupportCopy(s->ps + pos, a);
+}
+
+
+inline void b3MprSimplexSwap(b3MprSimplex_t *s, size_t pos1, size_t pos2)
+{
+ b3MprSupport_t supp;
+
+ b3MprSupportCopy(&supp, &s->ps[pos1]);
+ b3MprSupportCopy(&s->ps[pos1], &s->ps[pos2]);
+ b3MprSupportCopy(&s->ps[pos2], &supp);
+}
+
+
+inline int b3MprIsZero(float val)
+{
+ return B3_MPR_FABS(val) < FLT_EPSILON;
+}
+
+
+
+inline int b3MprEq(float _a, float _b)
+{
+ float ab;
+ float a, b;
+
+ ab = B3_MPR_FABS(_a - _b);
+ if (B3_MPR_FABS(ab) < FLT_EPSILON)
+ return 1;
+
+ a = B3_MPR_FABS(_a);
+ b = B3_MPR_FABS(_b);
+ if (b > a){
+ return ab < FLT_EPSILON * b;
+ }else{
+ return ab < FLT_EPSILON * a;
+ }
+}
+
+
+inline int b3MprVec3Eq(const b3Float4* a, const b3Float4 *b)
+{
+ return b3MprEq((*a).x, (*b).x)
+ && b3MprEq((*a).y, (*b).y)
+ && b3MprEq((*a).z, (*b).z);
+}
+
+
+
+inline b3Float4 b3LocalGetSupportVertex(b3Float4ConstArg supportVec,__global const b3ConvexPolyhedronData_t* hull, b3ConstArray(b3Float4) verticesA)
+{
+ b3Float4 supVec = b3MakeFloat4(0,0,0,0);
+ float maxDot = -B3_LARGE_FLOAT;
+
+ if( 0 < hull->m_numVertices )
+ {
+ const b3Float4 scaled = supportVec;
+ int index = b3MaxDot(scaled, &verticesA[hull->m_vertexOffset], hull->m_numVertices, &maxDot);
+ return verticesA[hull->m_vertexOffset+index];
+ }
+
+ return supVec;
+
+}
+
+
+B3_STATIC void b3MprConvexSupport(int pairIndex,int bodyIndex, b3ConstArray(b3RigidBodyData_t) cpuBodyBuf,
+ b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData,
+ b3ConstArray(b3Collidable_t) cpuCollidables,
+ b3ConstArray(b3Float4) cpuVertices,
+ __global b3Float4* sepAxis,
+ const b3Float4* _dir, b3Float4* outp, int logme)
+{
+ //dir is in worldspace, move to local space
+
+ b3Float4 pos = cpuBodyBuf[bodyIndex].m_pos;
+ b3Quat orn = cpuBodyBuf[bodyIndex].m_quat;
+
+ b3Float4 dir = b3MakeFloat4((*_dir).x,(*_dir).y,(*_dir).z,0.f);
+
+ const b3Float4 localDir = b3QuatRotate(b3QuatInverse(orn),dir);
+
+
+ //find local support vertex
+ int colIndex = cpuBodyBuf[bodyIndex].m_collidableIdx;
+
+ b3Assert(cpuCollidables[colIndex].m_shapeType==SHAPE_CONVEX_HULL);
+ __global const b3ConvexPolyhedronData_t* hull = &cpuConvexData[cpuCollidables[colIndex].m_shapeIndex];
+
+ b3Float4 pInA;
+ if (logme)
+ {
+
+
+ // b3Float4 supVec = b3MakeFloat4(0,0,0,0);
+ float maxDot = -B3_LARGE_FLOAT;
+
+ if( 0 < hull->m_numVertices )
+ {
+ const b3Float4 scaled = localDir;
+ int index = b3MaxDot(scaled, &cpuVertices[hull->m_vertexOffset], hull->m_numVertices, &maxDot);
+ pInA = cpuVertices[hull->m_vertexOffset+index];
+
+ }
+
+
+ } else
+ {
+ pInA = b3LocalGetSupportVertex(localDir,hull,cpuVertices);
+ }
+
+ //move vertex to world space
+ *outp = b3TransformPoint(pInA,pos,orn);
+
+}
+
+inline void b3MprSupport(int pairIndex,int bodyIndexA, int bodyIndexB, b3ConstArray(b3RigidBodyData_t) cpuBodyBuf,
+ b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData,
+ b3ConstArray(b3Collidable_t) cpuCollidables,
+ b3ConstArray(b3Float4) cpuVertices,
+ __global b3Float4* sepAxis,
+ const b3Float4* _dir, b3MprSupport_t *supp)
+{
+ b3Float4 dir;
+ dir = *_dir;
+ b3MprConvexSupport(pairIndex,bodyIndexA,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices,sepAxis,&dir, &supp->v1,0);
+ dir = *_dir*-1.f;
+ b3MprConvexSupport(pairIndex,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices,sepAxis,&dir, &supp->v2,0);
+ supp->v = supp->v1 - supp->v2;
+}
+
+
+
+
+
+
+
+
+
+inline void b3FindOrigin(int bodyIndexA, int bodyIndexB, b3ConstArray(b3RigidBodyData_t) cpuBodyBuf, b3MprSupport_t *center)
+{
+
+ center->v1 = cpuBodyBuf[bodyIndexA].m_pos;
+ center->v2 = cpuBodyBuf[bodyIndexB].m_pos;
+ center->v = center->v1 - center->v2;
+}
+
+inline void b3MprVec3Set(b3Float4 *v, float x, float y, float z)
+{
+ (*v).x = x;
+ (*v).y = y;
+ (*v).z = z;
+ (*v).w = 0.f;
+}
+
+inline void b3MprVec3Add(b3Float4 *v, const b3Float4 *w)
+{
+ (*v).x += (*w).x;
+ (*v).y += (*w).y;
+ (*v).z += (*w).z;
+}
+
+inline void b3MprVec3Copy(b3Float4 *v, const b3Float4 *w)
+{
+ *v = *w;
+}
+
+inline void b3MprVec3Scale(b3Float4 *d, float k)
+{
+ *d *= k;
+}
+
+inline float b3MprVec3Dot(const b3Float4 *a, const b3Float4 *b)
+{
+ float dot;
+
+ dot = b3Dot3F4(*a,*b);
+ return dot;
+}
+
+
+inline float b3MprVec3Len2(const b3Float4 *v)
+{
+ return b3MprVec3Dot(v, v);
+}
+
+inline void b3MprVec3Normalize(b3Float4 *d)
+{
+ float k = 1.f / B3_MPR_SQRT(b3MprVec3Len2(d));
+ b3MprVec3Scale(d, k);
+}
+
+inline void b3MprVec3Cross(b3Float4 *d, const b3Float4 *a, const b3Float4 *b)
+{
+ *d = b3Cross3(*a,*b);
+
+}
+
+
+inline void b3MprVec3Sub2(b3Float4 *d, const b3Float4 *v, const b3Float4 *w)
+{
+ *d = *v - *w;
+}
+
+inline void b3PortalDir(const b3MprSimplex_t *portal, b3Float4 *dir)
+{
+ b3Float4 v2v1, v3v1;
+
+ b3MprVec3Sub2(&v2v1, &b3MprSimplexPoint(portal, 2)->v,
+ &b3MprSimplexPoint(portal, 1)->v);
+ b3MprVec3Sub2(&v3v1, &b3MprSimplexPoint(portal, 3)->v,
+ &b3MprSimplexPoint(portal, 1)->v);
+ b3MprVec3Cross(dir, &v2v1, &v3v1);
+ b3MprVec3Normalize(dir);
+}
+
+
+inline int portalEncapsulesOrigin(const b3MprSimplex_t *portal,
+ const b3Float4 *dir)
+{
+ float dot;
+ dot = b3MprVec3Dot(dir, &b3MprSimplexPoint(portal, 1)->v);
+ return b3MprIsZero(dot) || dot > 0.f;
+}
+
+inline int portalReachTolerance(const b3MprSimplex_t *portal,
+ const b3MprSupport_t *v4,
+ const b3Float4 *dir)
+{
+ float dv1, dv2, dv3, dv4;
+ float dot1, dot2, dot3;
+
+ // find the smallest dot product of dir and {v1-v4, v2-v4, v3-v4}
+
+ dv1 = b3MprVec3Dot(&b3MprSimplexPoint(portal, 1)->v, dir);
+ dv2 = b3MprVec3Dot(&b3MprSimplexPoint(portal, 2)->v, dir);
+ dv3 = b3MprVec3Dot(&b3MprSimplexPoint(portal, 3)->v, dir);
+ dv4 = b3MprVec3Dot(&v4->v, dir);
+
+ dot1 = dv4 - dv1;
+ dot2 = dv4 - dv2;
+ dot3 = dv4 - dv3;
+
+ dot1 = B3_MPR_FMIN(dot1, dot2);
+ dot1 = B3_MPR_FMIN(dot1, dot3);
+
+ return b3MprEq(dot1, B3_MPR_TOLERANCE) || dot1 < B3_MPR_TOLERANCE;
+}
+
+inline int portalCanEncapsuleOrigin(const b3MprSimplex_t *portal,
+ const b3MprSupport_t *v4,
+ const b3Float4 *dir)
+{
+ float dot;
+ dot = b3MprVec3Dot(&v4->v, dir);
+ return b3MprIsZero(dot) || dot > 0.f;
+}
+
+inline void b3ExpandPortal(b3MprSimplex_t *portal,
+ const b3MprSupport_t *v4)
+{
+ float dot;
+ b3Float4 v4v0;
+
+ b3MprVec3Cross(&v4v0, &v4->v, &b3MprSimplexPoint(portal, 0)->v);
+ dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 1)->v, &v4v0);
+ if (dot > 0.f){
+ dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 2)->v, &v4v0);
+ if (dot > 0.f){
+ b3MprSimplexSet(portal, 1, v4);
+ }else{
+ b3MprSimplexSet(portal, 3, v4);
+ }
+ }else{
+ dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 3)->v, &v4v0);
+ if (dot > 0.f){
+ b3MprSimplexSet(portal, 2, v4);
+ }else{
+ b3MprSimplexSet(portal, 1, v4);
+ }
+ }
+}
+
+
+
+B3_STATIC int b3DiscoverPortal(int pairIndex, int bodyIndexA, int bodyIndexB, b3ConstArray(b3RigidBodyData_t) cpuBodyBuf,
+ b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData,
+ b3ConstArray(b3Collidable_t) cpuCollidables,
+ b3ConstArray(b3Float4) cpuVertices,
+ __global b3Float4* sepAxis,
+ __global int* hasSepAxis,
+ b3MprSimplex_t *portal)
+{
+ b3Float4 dir, va, vb;
+ float dot;
+ int cont;
+
+
+
+ // vertex 0 is center of portal
+ b3FindOrigin(bodyIndexA,bodyIndexB,cpuBodyBuf, b3MprSimplexPointW(portal, 0));
+ // vertex 0 is center of portal
+ b3MprSimplexSetSize(portal, 1);
+
+
+
+ b3Float4 zero = b3MakeFloat4(0,0,0,0);
+ b3Float4* b3mpr_vec3_origin = &zero;
+
+ if (b3MprVec3Eq(&b3MprSimplexPoint(portal, 0)->v, b3mpr_vec3_origin)){
+ // Portal's center lies on origin (0,0,0) => we know that objects
+ // intersect but we would need to know penetration info.
+ // So move center little bit...
+ b3MprVec3Set(&va, FLT_EPSILON * 10.f, 0.f, 0.f);
+ b3MprVec3Add(&b3MprSimplexPointW(portal, 0)->v, &va);
+ }
+
+
+ // vertex 1 = support in direction of origin
+ b3MprVec3Copy(&dir, &b3MprSimplexPoint(portal, 0)->v);
+ b3MprVec3Scale(&dir, -1.f);
+ b3MprVec3Normalize(&dir);
+
+
+ b3MprSupport(pairIndex,bodyIndexA,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices, sepAxis,&dir, b3MprSimplexPointW(portal, 1));
+
+ b3MprSimplexSetSize(portal, 2);
+
+ // test if origin isn't outside of v1
+ dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 1)->v, &dir);
+
+
+ if (b3MprIsZero(dot) || dot < 0.f)
+ return -1;
+
+
+ // vertex 2
+ b3MprVec3Cross(&dir, &b3MprSimplexPoint(portal, 0)->v,
+ &b3MprSimplexPoint(portal, 1)->v);
+ if (b3MprIsZero(b3MprVec3Len2(&dir))){
+ if (b3MprVec3Eq(&b3MprSimplexPoint(portal, 1)->v, b3mpr_vec3_origin)){
+ // origin lies on v1
+ return 1;
+ }else{
+ // origin lies on v0-v1 segment
+ return 2;
+ }
+ }
+
+ b3MprVec3Normalize(&dir);
+ b3MprSupport(pairIndex,bodyIndexA,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices, sepAxis,&dir, b3MprSimplexPointW(portal, 2));
+
+ dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 2)->v, &dir);
+ if (b3MprIsZero(dot) || dot < 0.f)
+ return -1;
+
+ b3MprSimplexSetSize(portal, 3);
+
+ // vertex 3 direction
+ b3MprVec3Sub2(&va, &b3MprSimplexPoint(portal, 1)->v,
+ &b3MprSimplexPoint(portal, 0)->v);
+ b3MprVec3Sub2(&vb, &b3MprSimplexPoint(portal, 2)->v,
+ &b3MprSimplexPoint(portal, 0)->v);
+ b3MprVec3Cross(&dir, &va, &vb);
+ b3MprVec3Normalize(&dir);
+
+ // it is better to form portal faces to be oriented "outside" origin
+ dot = b3MprVec3Dot(&dir, &b3MprSimplexPoint(portal, 0)->v);
+ if (dot > 0.f){
+ b3MprSimplexSwap(portal, 1, 2);
+ b3MprVec3Scale(&dir, -1.f);
+ }
+
+ while (b3MprSimplexSize(portal) < 4){
+ b3MprSupport(pairIndex,bodyIndexA,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices, sepAxis,&dir, b3MprSimplexPointW(portal, 3));
+
+ dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 3)->v, &dir);
+ if (b3MprIsZero(dot) || dot < 0.f)
+ return -1;
+
+ cont = 0;
+
+ // test if origin is outside (v1, v0, v3) - set v2 as v3 and
+ // continue
+ b3MprVec3Cross(&va, &b3MprSimplexPoint(portal, 1)->v,
+ &b3MprSimplexPoint(portal, 3)->v);
+ dot = b3MprVec3Dot(&va, &b3MprSimplexPoint(portal, 0)->v);
+ if (dot < 0.f && !b3MprIsZero(dot)){
+ b3MprSimplexSet(portal, 2, b3MprSimplexPoint(portal, 3));
+ cont = 1;
+ }
+
+ if (!cont){
+ // test if origin is outside (v3, v0, v2) - set v1 as v3 and
+ // continue
+ b3MprVec3Cross(&va, &b3MprSimplexPoint(portal, 3)->v,
+ &b3MprSimplexPoint(portal, 2)->v);
+ dot = b3MprVec3Dot(&va, &b3MprSimplexPoint(portal, 0)->v);
+ if (dot < 0.f && !b3MprIsZero(dot)){
+ b3MprSimplexSet(portal, 1, b3MprSimplexPoint(portal, 3));
+ cont = 1;
+ }
+ }
+
+ if (cont){
+ b3MprVec3Sub2(&va, &b3MprSimplexPoint(portal, 1)->v,
+ &b3MprSimplexPoint(portal, 0)->v);
+ b3MprVec3Sub2(&vb, &b3MprSimplexPoint(portal, 2)->v,
+ &b3MprSimplexPoint(portal, 0)->v);
+ b3MprVec3Cross(&dir, &va, &vb);
+ b3MprVec3Normalize(&dir);
+ }else{
+ b3MprSimplexSetSize(portal, 4);
+ }
+ }
+
+ return 0;
+}
+
+
+B3_STATIC int b3RefinePortal(int pairIndex,int bodyIndexA, int bodyIndexB, b3ConstArray(b3RigidBodyData_t) cpuBodyBuf,
+ b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData,
+ b3ConstArray(b3Collidable_t) cpuCollidables,
+ b3ConstArray(b3Float4) cpuVertices,
+ __global b3Float4* sepAxis,
+ b3MprSimplex_t *portal)
+{
+ b3Float4 dir;
+ b3MprSupport_t v4;
+
+ for (int i=0;i<B3_MPR_MAX_ITERATIONS;i++)
+ //while (1)
+ {
+ // compute direction outside the portal (from v0 throught v1,v2,v3
+ // face)
+ b3PortalDir(portal, &dir);
+
+ // test if origin is inside the portal
+ if (portalEncapsulesOrigin(portal, &dir))
+ return 0;
+
+ // get next support point
+
+ b3MprSupport(pairIndex,bodyIndexA,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices, sepAxis,&dir, &v4);
+
+
+ // test if v4 can expand portal to contain origin and if portal
+ // expanding doesn't reach given tolerance
+ if (!portalCanEncapsuleOrigin(portal, &v4, &dir)
+ || portalReachTolerance(portal, &v4, &dir))
+ {
+ return -1;
+ }
+
+ // v1-v2-v3 triangle must be rearranged to face outside Minkowski
+ // difference (direction from v0).
+ b3ExpandPortal(portal, &v4);
+ }
+
+ return -1;
+}
+
+B3_STATIC void b3FindPos(const b3MprSimplex_t *portal, b3Float4 *pos)
+{
+
+ b3Float4 zero = b3MakeFloat4(0,0,0,0);
+ b3Float4* b3mpr_vec3_origin = &zero;
+
+ b3Float4 dir;
+ size_t i;
+ float b[4], sum, inv;
+ b3Float4 vec, p1, p2;
+
+ b3PortalDir(portal, &dir);
+
+ // use barycentric coordinates of tetrahedron to find origin
+ b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 1)->v,
+ &b3MprSimplexPoint(portal, 2)->v);
+ b[0] = b3MprVec3Dot(&vec, &b3MprSimplexPoint(portal, 3)->v);
+
+ b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 3)->v,
+ &b3MprSimplexPoint(portal, 2)->v);
+ b[1] = b3MprVec3Dot(&vec, &b3MprSimplexPoint(portal, 0)->v);
+
+ b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 0)->v,
+ &b3MprSimplexPoint(portal, 1)->v);
+ b[2] = b3MprVec3Dot(&vec, &b3MprSimplexPoint(portal, 3)->v);
+
+ b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 2)->v,
+ &b3MprSimplexPoint(portal, 1)->v);
+ b[3] = b3MprVec3Dot(&vec, &b3MprSimplexPoint(portal, 0)->v);
+
+ sum = b[0] + b[1] + b[2] + b[3];
+
+ if (b3MprIsZero(sum) || sum < 0.f){
+ b[0] = 0.f;
+
+ b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 2)->v,
+ &b3MprSimplexPoint(portal, 3)->v);
+ b[1] = b3MprVec3Dot(&vec, &dir);
+ b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 3)->v,
+ &b3MprSimplexPoint(portal, 1)->v);
+ b[2] = b3MprVec3Dot(&vec, &dir);
+ b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 1)->v,
+ &b3MprSimplexPoint(portal, 2)->v);
+ b[3] = b3MprVec3Dot(&vec, &dir);
+
+ sum = b[1] + b[2] + b[3];
+ }
+
+ inv = 1.f / sum;
+
+ b3MprVec3Copy(&p1, b3mpr_vec3_origin);
+ b3MprVec3Copy(&p2, b3mpr_vec3_origin);
+ for (i = 0; i < 4; i++){
+ b3MprVec3Copy(&vec, &b3MprSimplexPoint(portal, i)->v1);
+ b3MprVec3Scale(&vec, b[i]);
+ b3MprVec3Add(&p1, &vec);
+
+ b3MprVec3Copy(&vec, &b3MprSimplexPoint(portal, i)->v2);
+ b3MprVec3Scale(&vec, b[i]);
+ b3MprVec3Add(&p2, &vec);
+ }
+ b3MprVec3Scale(&p1, inv);
+ b3MprVec3Scale(&p2, inv);
+
+ b3MprVec3Copy(pos, &p1);
+ b3MprVec3Add(pos, &p2);
+ b3MprVec3Scale(pos, 0.5);
+}
+
+inline float b3MprVec3Dist2(const b3Float4 *a, const b3Float4 *b)
+{
+ b3Float4 ab;
+ b3MprVec3Sub2(&ab, a, b);
+ return b3MprVec3Len2(&ab);
+}
+
+inline float _b3MprVec3PointSegmentDist2(const b3Float4 *P,
+ const b3Float4 *x0,
+ const b3Float4 *b,
+ b3Float4 *witness)
+{
+ // The computation comes from solving equation of segment:
+ // S(t) = x0 + t.d
+ // where - x0 is initial point of segment
+ // - d is direction of segment from x0 (|d| > 0)
+ // - t belongs to <0, 1> interval
+ //
+ // Than, distance from a segment to some point P can be expressed:
+ // D(t) = |x0 + t.d - P|^2
+ // which is distance from any point on segment. Minimization
+ // of this function brings distance from P to segment.
+ // Minimization of D(t) leads to simple quadratic equation that's
+ // solving is straightforward.
+ //
+ // Bonus of this method is witness point for free.
+
+ float dist, t;
+ b3Float4 d, a;
+
+ // direction of segment
+ b3MprVec3Sub2(&d, b, x0);
+
+ // precompute vector from P to x0
+ b3MprVec3Sub2(&a, x0, P);
+
+ t = -1.f * b3MprVec3Dot(&a, &d);
+ t /= b3MprVec3Len2(&d);
+
+ if (t < 0.f || b3MprIsZero(t)){
+ dist = b3MprVec3Dist2(x0, P);
+ if (witness)
+ b3MprVec3Copy(witness, x0);
+ }else if (t > 1.f || b3MprEq(t, 1.f)){
+ dist = b3MprVec3Dist2(b, P);
+ if (witness)
+ b3MprVec3Copy(witness, b);
+ }else{
+ if (witness){
+ b3MprVec3Copy(witness, &d);
+ b3MprVec3Scale(witness, t);
+ b3MprVec3Add(witness, x0);
+ dist = b3MprVec3Dist2(witness, P);
+ }else{
+ // recycling variables
+ b3MprVec3Scale(&d, t);
+ b3MprVec3Add(&d, &a);
+ dist = b3MprVec3Len2(&d);
+ }
+ }
+
+ return dist;
+}
+
+
+inline float b3MprVec3PointTriDist2(const b3Float4 *P,
+ const b3Float4 *x0, const b3Float4 *B,
+ const b3Float4 *C,
+ b3Float4 *witness)
+{
+ // Computation comes from analytic expression for triangle (x0, B, C)
+ // T(s, t) = x0 + s.d1 + t.d2, where d1 = B - x0 and d2 = C - x0 and
+ // Then equation for distance is:
+ // D(s, t) = | T(s, t) - P |^2
+ // This leads to minimization of quadratic function of two variables.
+ // The solution from is taken only if s is between 0 and 1, t is
+ // between 0 and 1 and t + s < 1, otherwise distance from segment is
+ // computed.
+
+ b3Float4 d1, d2, a;
+ float u, v, w, p, q, r;
+ float s, t, dist, dist2;
+ b3Float4 witness2;
+
+ b3MprVec3Sub2(&d1, B, x0);
+ b3MprVec3Sub2(&d2, C, x0);
+ b3MprVec3Sub2(&a, x0, P);
+
+ u = b3MprVec3Dot(&a, &a);
+ v = b3MprVec3Dot(&d1, &d1);
+ w = b3MprVec3Dot(&d2, &d2);
+ p = b3MprVec3Dot(&a, &d1);
+ q = b3MprVec3Dot(&a, &d2);
+ r = b3MprVec3Dot(&d1, &d2);
+
+ s = (q * r - w * p) / (w * v - r * r);
+ t = (-s * r - q) / w;
+
+ if ((b3MprIsZero(s) || s > 0.f)
+ && (b3MprEq(s, 1.f) || s < 1.f)
+ && (b3MprIsZero(t) || t > 0.f)
+ && (b3MprEq(t, 1.f) || t < 1.f)
+ && (b3MprEq(t + s, 1.f) || t + s < 1.f)){
+
+ if (witness){
+ b3MprVec3Scale(&d1, s);
+ b3MprVec3Scale(&d2, t);
+ b3MprVec3Copy(witness, x0);
+ b3MprVec3Add(witness, &d1);
+ b3MprVec3Add(witness, &d2);
+
+ dist = b3MprVec3Dist2(witness, P);
+ }else{
+ dist = s * s * v;
+ dist += t * t * w;
+ dist += 2.f * s * t * r;
+ dist += 2.f * s * p;
+ dist += 2.f * t * q;
+ dist += u;
+ }
+ }else{
+ dist = _b3MprVec3PointSegmentDist2(P, x0, B, witness);
+
+ dist2 = _b3MprVec3PointSegmentDist2(P, x0, C, &witness2);
+ if (dist2 < dist){
+ dist = dist2;
+ if (witness)
+ b3MprVec3Copy(witness, &witness2);
+ }
+
+ dist2 = _b3MprVec3PointSegmentDist2(P, B, C, &witness2);
+ if (dist2 < dist){
+ dist = dist2;
+ if (witness)
+ b3MprVec3Copy(witness, &witness2);
+ }
+ }
+
+ return dist;
+}
+
+
+B3_STATIC void b3FindPenetr(int pairIndex,int bodyIndexA, int bodyIndexB, b3ConstArray(b3RigidBodyData_t) cpuBodyBuf,
+ b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData,
+ b3ConstArray(b3Collidable_t) cpuCollidables,
+ b3ConstArray(b3Float4) cpuVertices,
+ __global b3Float4* sepAxis,
+ b3MprSimplex_t *portal,
+ float *depth, b3Float4 *pdir, b3Float4 *pos)
+{
+ b3Float4 dir;
+ b3MprSupport_t v4;
+ unsigned long iterations;
+
+ b3Float4 zero = b3MakeFloat4(0,0,0,0);
+ b3Float4* b3mpr_vec3_origin = &zero;
+
+
+ iterations = 1UL;
+ for (int i=0;i<B3_MPR_MAX_ITERATIONS;i++)
+ //while (1)
+ {
+ // compute portal direction and obtain next support point
+ b3PortalDir(portal, &dir);
+
+ b3MprSupport(pairIndex,bodyIndexA,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices, sepAxis,&dir, &v4);
+
+
+ // reached tolerance -> find penetration info
+ if (portalReachTolerance(portal, &v4, &dir)
+ || iterations ==B3_MPR_MAX_ITERATIONS)
+ {
+ *depth = b3MprVec3PointTriDist2(b3mpr_vec3_origin,&b3MprSimplexPoint(portal, 1)->v,&b3MprSimplexPoint(portal, 2)->v,&b3MprSimplexPoint(portal, 3)->v,pdir);
+ *depth = B3_MPR_SQRT(*depth);
+
+ if (b3MprIsZero((*pdir).x) && b3MprIsZero((*pdir).y) && b3MprIsZero((*pdir).z))
+ {
+
+ *pdir = dir;
+ }
+ b3MprVec3Normalize(pdir);
+
+ // barycentric coordinates:
+ b3FindPos(portal, pos);
+
+
+ return;
+ }
+
+ b3ExpandPortal(portal, &v4);
+
+ iterations++;
+ }
+}
+
+B3_STATIC void b3FindPenetrTouch(b3MprSimplex_t *portal,float *depth, b3Float4 *dir, b3Float4 *pos)
+{
+ // Touching contact on portal's v1 - so depth is zero and direction
+ // is unimportant and pos can be guessed
+ *depth = 0.f;
+ b3Float4 zero = b3MakeFloat4(0,0,0,0);
+ b3Float4* b3mpr_vec3_origin = &zero;
+
+
+ b3MprVec3Copy(dir, b3mpr_vec3_origin);
+
+ b3MprVec3Copy(pos, &b3MprSimplexPoint(portal, 1)->v1);
+ b3MprVec3Add(pos, &b3MprSimplexPoint(portal, 1)->v2);
+ b3MprVec3Scale(pos, 0.5);
+}
+
+B3_STATIC void b3FindPenetrSegment(b3MprSimplex_t *portal,
+ float *depth, b3Float4 *dir, b3Float4 *pos)
+{
+
+ // Origin lies on v0-v1 segment.
+ // Depth is distance to v1, direction also and position must be
+ // computed
+
+ b3MprVec3Copy(pos, &b3MprSimplexPoint(portal, 1)->v1);
+ b3MprVec3Add(pos, &b3MprSimplexPoint(portal, 1)->v2);
+ b3MprVec3Scale(pos, 0.5f);
+
+
+ b3MprVec3Copy(dir, &b3MprSimplexPoint(portal, 1)->v);
+ *depth = B3_MPR_SQRT(b3MprVec3Len2(dir));
+ b3MprVec3Normalize(dir);
+}
+
+
+
+inline int b3MprPenetration(int pairIndex, int bodyIndexA, int bodyIndexB,
+ b3ConstArray(b3RigidBodyData_t) cpuBodyBuf,
+ b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData,
+ b3ConstArray(b3Collidable_t) cpuCollidables,
+ b3ConstArray(b3Float4) cpuVertices,
+ __global b3Float4* sepAxis,
+ __global int* hasSepAxis,
+ float *depthOut, b3Float4* dirOut, b3Float4* posOut)
+{
+
+ b3MprSimplex_t portal;
+
+
+// if (!hasSepAxis[pairIndex])
+ // return -1;
+
+ hasSepAxis[pairIndex] = 0;
+ int res;
+
+ // Phase 1: Portal discovery
+ res = b3DiscoverPortal(pairIndex,bodyIndexA,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices,sepAxis,hasSepAxis, &portal);
+
+
+ //sepAxis[pairIndex] = *pdir;//or -dir?
+
+ switch (res)
+ {
+ case 0:
+ {
+ // Phase 2: Portal refinement
+
+ res = b3RefinePortal(pairIndex,bodyIndexA,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices, sepAxis,&portal);
+ if (res < 0)
+ return -1;
+
+ // Phase 3. Penetration info
+ b3FindPenetr(pairIndex,bodyIndexA,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices, sepAxis,&portal, depthOut, dirOut, posOut);
+ hasSepAxis[pairIndex] = 1;
+ sepAxis[pairIndex] = -*dirOut;
+ break;
+ }
+ case 1:
+ {
+ // Touching contact on portal's v1.
+ b3FindPenetrTouch(&portal, depthOut, dirOut, posOut);
+ break;
+ }
+ case 2:
+ {
+
+ b3FindPenetrSegment( &portal, depthOut, dirOut, posOut);
+ break;
+ }
+ default:
+ {
+ hasSepAxis[pairIndex]=0;
+ //if (res < 0)
+ //{
+ // Origin isn't inside portal - no collision.
+ return -1;
+ //}
+ }
+ };
+
+ return 0;
+};
+
+
+
+#endif //B3_MPR_PENETRATION_H
diff --git a/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3NewContactReduction.h b/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3NewContactReduction.h
new file mode 100644
index 0000000000..718222ebca
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3NewContactReduction.h
@@ -0,0 +1,196 @@
+
+#ifndef B3_NEW_CONTACT_REDUCTION_H
+#define B3_NEW_CONTACT_REDUCTION_H
+
+#include "Bullet3Common/shared/b3Float4.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h"
+
+#define GET_NPOINTS(x) (x).m_worldNormalOnB.w
+
+
+int b3ExtractManifoldSequentialGlobal(__global const b3Float4* p, int nPoints, b3Float4ConstArg nearNormal, b3Int4* contactIdx)
+{
+ if( nPoints == 0 )
+ return 0;
+
+ if (nPoints <=4)
+ return nPoints;
+
+
+ if (nPoints >64)
+ nPoints = 64;
+
+ b3Float4 center = b3MakeFloat4(0,0,0,0);
+ {
+
+ for (int i=0;i<nPoints;i++)
+ center += p[i];
+ center /= (float)nPoints;
+ }
+
+
+
+ // sample 4 directions
+
+ b3Float4 aVector = p[0] - center;
+ b3Float4 u = b3Cross( nearNormal, aVector );
+ b3Float4 v = b3Cross( nearNormal, u );
+ u = b3Normalized( u );
+ v = b3Normalized( v );
+
+
+ //keep point with deepest penetration
+ float minW= FLT_MAX;
+
+ int minIndex=-1;
+
+ b3Float4 maxDots;
+ maxDots.x = FLT_MIN;
+ maxDots.y = FLT_MIN;
+ maxDots.z = FLT_MIN;
+ maxDots.w = FLT_MIN;
+
+ // idx, distance
+ for(int ie = 0; ie<nPoints; ie++ )
+ {
+ if (p[ie].w<minW)
+ {
+ minW = p[ie].w;
+ minIndex=ie;
+ }
+ float f;
+ b3Float4 r = p[ie]-center;
+ f = b3Dot( u, r );
+ if (f<maxDots.x)
+ {
+ maxDots.x = f;
+ contactIdx[0].x = ie;
+ }
+
+ f = b3Dot( -u, r );
+ if (f<maxDots.y)
+ {
+ maxDots.y = f;
+ contactIdx[0].y = ie;
+ }
+
+
+ f = b3Dot( v, r );
+ if (f<maxDots.z)
+ {
+ maxDots.z = f;
+ contactIdx[0].z = ie;
+ }
+
+ f = b3Dot( -v, r );
+ if (f<maxDots.w)
+ {
+ maxDots.w = f;
+ contactIdx[0].w = ie;
+ }
+
+ }
+
+ if (contactIdx[0].x != minIndex && contactIdx[0].y != minIndex && contactIdx[0].z != minIndex && contactIdx[0].w != minIndex)
+ {
+ //replace the first contact with minimum (todo: replace contact with least penetration)
+ contactIdx[0].x = minIndex;
+ }
+
+ return 4;
+
+}
+
+__kernel void b3NewContactReductionKernel( __global b3Int4* pairs,
+ __global const b3RigidBodyData_t* rigidBodies,
+ __global const b3Float4* separatingNormals,
+ __global const int* hasSeparatingAxis,
+ __global struct b3Contact4Data* globalContactsOut,
+ __global b3Int4* clippingFaces,
+ __global b3Float4* worldVertsB2,
+ volatile __global int* nGlobalContactsOut,
+ int vertexFaceCapacity,
+ int contactCapacity,
+ int numPairs,
+ int pairIndex
+ )
+{
+// int i = get_global_id(0);
+ //int pairIndex = i;
+ int i = pairIndex;
+
+ b3Int4 contactIdx;
+ contactIdx=b3MakeInt4(0,1,2,3);
+
+ if (i<numPairs)
+ {
+
+ if (hasSeparatingAxis[i])
+ {
+
+
+
+
+ int nPoints = clippingFaces[pairIndex].w;
+
+ if (nPoints>0)
+ {
+
+ __global b3Float4* pointsIn = &worldVertsB2[pairIndex*vertexFaceCapacity];
+ b3Float4 normal = -separatingNormals[i];
+
+ int nReducedContacts = b3ExtractManifoldSequentialGlobal(pointsIn, nPoints, normal, &contactIdx);
+
+ int dstIdx;
+ dstIdx = b3AtomicInc( nGlobalContactsOut);
+
+//#if 0
+ b3Assert(dstIdx < contactCapacity);
+ if (dstIdx < contactCapacity)
+ {
+
+ __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];
+ c->m_worldNormalOnB = -normal;
+ c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);
+ c->m_batchIdx = pairIndex;
+ int bodyA = pairs[pairIndex].x;
+ int bodyB = pairs[pairIndex].y;
+
+ pairs[pairIndex].w = dstIdx;
+
+ c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0?-bodyA:bodyA;
+ c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0?-bodyB:bodyB;
+ c->m_childIndexA =-1;
+ c->m_childIndexB =-1;
+
+ switch (nReducedContacts)
+ {
+ case 4:
+ c->m_worldPosB[3] = pointsIn[contactIdx.w];
+ case 3:
+ c->m_worldPosB[2] = pointsIn[contactIdx.z];
+ case 2:
+ c->m_worldPosB[1] = pointsIn[contactIdx.y];
+ case 1:
+ c->m_worldPosB[0] = pointsIn[contactIdx.x];
+ default:
+ {
+ }
+ };
+
+ GET_NPOINTS(*c) = nReducedContacts;
+
+ }
+
+
+//#endif
+
+ }// if (numContactsOut>0)
+ }// if (hasSeparatingAxis[i])
+ }// if (i<numPairs)
+
+
+
+}
+#endif
diff --git a/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3QuantizedBvhNodeData.h b/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3QuantizedBvhNodeData.h
new file mode 100644
index 0000000000..3661e43cf1
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3QuantizedBvhNodeData.h
@@ -0,0 +1,90 @@
+
+
+#ifndef B3_QUANTIZED_BVH_NODE_H
+#define B3_QUANTIZED_BVH_NODE_H
+
+#include "Bullet3Common/shared/b3Float4.h"
+
+#define B3_MAX_NUM_PARTS_IN_BITS 10
+
+///b3QuantizedBvhNodeData is a compressed aabb node, 16 bytes.
+///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range).
+typedef struct b3QuantizedBvhNodeData b3QuantizedBvhNodeData_t;
+
+struct b3QuantizedBvhNodeData
+{
+ //12 bytes
+ unsigned short int m_quantizedAabbMin[3];
+ unsigned short int m_quantizedAabbMax[3];
+ //4 bytes
+ int m_escapeIndexOrTriangleIndex;
+};
+
+inline int b3GetTriangleIndex(const b3QuantizedBvhNodeData* rootNode)
+{
+ unsigned int x=0;
+ unsigned int y = (~(x&0))<<(31-B3_MAX_NUM_PARTS_IN_BITS);
+ // Get only the lower bits where the triangle index is stored
+ return (rootNode->m_escapeIndexOrTriangleIndex&~(y));
+}
+
+inline int b3IsLeaf(const b3QuantizedBvhNodeData* rootNode)
+{
+ //skipindex is negative (internal node), triangleindex >=0 (leafnode)
+ return (rootNode->m_escapeIndexOrTriangleIndex >= 0)? 1 : 0;
+}
+
+inline int b3GetEscapeIndex(const b3QuantizedBvhNodeData* rootNode)
+{
+ return -rootNode->m_escapeIndexOrTriangleIndex;
+}
+
+inline void b3QuantizeWithClamp(unsigned short* out, b3Float4ConstArg point2,int isMax, b3Float4ConstArg bvhAabbMin, b3Float4ConstArg bvhAabbMax, b3Float4ConstArg bvhQuantization)
+{
+ b3Float4 clampedPoint = b3MaxFloat4(point2,bvhAabbMin);
+ clampedPoint = b3MinFloat4 (clampedPoint, bvhAabbMax);
+
+ b3Float4 v = (clampedPoint - bvhAabbMin) * bvhQuantization;
+ if (isMax)
+ {
+ out[0] = (unsigned short) (((unsigned short)(v.x+1.f) | 1));
+ out[1] = (unsigned short) (((unsigned short)(v.y+1.f) | 1));
+ out[2] = (unsigned short) (((unsigned short)(v.z+1.f) | 1));
+ } else
+ {
+ out[0] = (unsigned short) (((unsigned short)(v.x) & 0xfffe));
+ out[1] = (unsigned short) (((unsigned short)(v.y) & 0xfffe));
+ out[2] = (unsigned short) (((unsigned short)(v.z) & 0xfffe));
+ }
+
+}
+
+
+inline int b3TestQuantizedAabbAgainstQuantizedAabbSlow(
+ const unsigned short int* aabbMin1,
+ const unsigned short int* aabbMax1,
+ const unsigned short int* aabbMin2,
+ const unsigned short int* aabbMax2)
+{
+ //int overlap = 1;
+ if (aabbMin1[0] > aabbMax2[0])
+ return 0;
+ if (aabbMax1[0] < aabbMin2[0])
+ return 0;
+ if (aabbMin1[1] > aabbMax2[1])
+ return 0;
+ if (aabbMax1[1] < aabbMin2[1])
+ return 0;
+ if (aabbMin1[2] > aabbMax2[2])
+ return 0;
+ if (aabbMax1[2] < aabbMin2[2])
+ return 0;
+ return 1;
+ //overlap = ((aabbMin1[0] > aabbMax2[0]) || (aabbMax1[0] < aabbMin2[0])) ? 0 : overlap;
+ //overlap = ((aabbMin1[2] > aabbMax2[2]) || (aabbMax1[2] < aabbMin2[2])) ? 0 : overlap;
+ //overlap = ((aabbMin1[1] > aabbMax2[1]) || (aabbMax1[1] < aabbMin2[1])) ? 0 : overlap;
+ //return overlap;
+}
+
+
+#endif //B3_QUANTIZED_BVH_NODE_H
diff --git a/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3ReduceContacts.h b/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3ReduceContacts.h
new file mode 100644
index 0000000000..35b5197006
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3ReduceContacts.h
@@ -0,0 +1,97 @@
+#ifndef B3_REDUCE_CONTACTS_H
+#define B3_REDUCE_CONTACTS_H
+
+inline int b3ReduceContacts(const b3Float4* p, int nPoints, const b3Float4& nearNormal, b3Int4* contactIdx)
+{
+ if( nPoints == 0 )
+ return 0;
+
+ if (nPoints <=4)
+ return nPoints;
+
+
+ if (nPoints >64)
+ nPoints = 64;
+
+ b3Float4 center = b3MakeFloat4(0,0,0,0);
+ {
+
+ for (int i=0;i<nPoints;i++)
+ center += p[i];
+ center /= (float)nPoints;
+ }
+
+
+
+ // sample 4 directions
+
+ b3Float4 aVector = p[0] - center;
+ b3Float4 u = b3Cross3( nearNormal, aVector );
+ b3Float4 v = b3Cross3( nearNormal, u );
+ u = b3FastNormalized3( u );
+ v = b3FastNormalized3( v );
+
+
+ //keep point with deepest penetration
+ float minW= FLT_MAX;
+
+ int minIndex=-1;
+
+ b3Float4 maxDots;
+ maxDots.x = FLT_MIN;
+ maxDots.y = FLT_MIN;
+ maxDots.z = FLT_MIN;
+ maxDots.w = FLT_MIN;
+
+ // idx, distance
+ for(int ie = 0; ie<nPoints; ie++ )
+ {
+ if (p[ie].w<minW)
+ {
+ minW = p[ie].w;
+ minIndex=ie;
+ }
+ float f;
+ b3Float4 r = p[ie]-center;
+ f = b3Dot3F4( u, r );
+ if (f<maxDots.x)
+ {
+ maxDots.x = f;
+ contactIdx[0].x = ie;
+ }
+
+ f = b3Dot3F4( -u, r );
+ if (f<maxDots.y)
+ {
+ maxDots.y = f;
+ contactIdx[0].y = ie;
+ }
+
+
+ f = b3Dot3F4( v, r );
+ if (f<maxDots.z)
+ {
+ maxDots.z = f;
+ contactIdx[0].z = ie;
+ }
+
+ f = b3Dot3F4( -v, r );
+ if (f<maxDots.w)
+ {
+ maxDots.w = f;
+ contactIdx[0].w = ie;
+ }
+
+ }
+
+ if (contactIdx[0].x != minIndex && contactIdx[0].y != minIndex && contactIdx[0].z != minIndex && contactIdx[0].w != minIndex)
+ {
+ //replace the first contact with minimum (todo: replace contact with least penetration)
+ contactIdx[0].x = minIndex;
+ }
+
+ return 4;
+
+}
+
+#endif //B3_REDUCE_CONTACTS_H
diff --git a/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h b/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h
new file mode 100644
index 0000000000..50632c871f
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h
@@ -0,0 +1,34 @@
+#ifndef B3_RIGIDBODY_DATA_H
+#define B3_RIGIDBODY_DATA_H
+
+#include "Bullet3Common/shared/b3Float4.h"
+#include "Bullet3Common/shared/b3Quat.h"
+#include "Bullet3Common/shared/b3Mat3x3.h"
+
+typedef struct b3RigidBodyData b3RigidBodyData_t;
+
+
+struct b3RigidBodyData
+{
+ b3Float4 m_pos;
+ b3Quat m_quat;
+ b3Float4 m_linVel;
+ b3Float4 m_angVel;
+
+ int m_collidableIdx;
+ float m_invMass;
+ float m_restituitionCoeff;
+ float m_frictionCoeff;
+};
+
+typedef struct b3InertiaData b3InertiaData_t;
+
+struct b3InertiaData
+{
+ b3Mat3x3 m_invInertiaWorld;
+ b3Mat3x3 m_initInvInertia;
+};
+
+
+#endif //B3_RIGIDBODY_DATA_H
+ \ No newline at end of file
diff --git a/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3UpdateAabbs.h b/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3UpdateAabbs.h
new file mode 100644
index 0000000000..8d40d19a03
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Collision/NarrowPhaseCollision/shared/b3UpdateAabbs.h
@@ -0,0 +1,40 @@
+#ifndef B3_UPDATE_AABBS_H
+#define B3_UPDATE_AABBS_H
+
+
+
+#include "Bullet3Collision/BroadPhaseCollision/shared/b3Aabb.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
+
+
+
+void b3ComputeWorldAabb( int bodyId, __global const b3RigidBodyData_t* bodies, __global const b3Collidable_t* collidables, __global const b3Aabb_t* localShapeAABB, __global b3Aabb_t* worldAabbs)
+{
+ __global const b3RigidBodyData_t* body = &bodies[bodyId];
+
+ b3Float4 position = body->m_pos;
+ b3Quat orientation = body->m_quat;
+
+ int collidableIndex = body->m_collidableIdx;
+ int shapeIndex = collidables[collidableIndex].m_shapeIndex;
+
+ if (shapeIndex>=0)
+ {
+
+ b3Aabb_t localAabb = localShapeAABB[collidableIndex];
+ b3Aabb_t worldAabb;
+
+ b3Float4 aabbAMinOut,aabbAMaxOut;
+ float margin = 0.f;
+ b3TransformAabb2(localAabb.m_minVec,localAabb.m_maxVec,margin,position,orientation,&aabbAMinOut,&aabbAMaxOut);
+
+ worldAabb.m_minVec =aabbAMinOut;
+ worldAabb.m_minIndices[3] = bodyId;
+ worldAabb.m_maxVec = aabbAMaxOut;
+ worldAabb.m_signedMaxIndices[3] = body[bodyId].m_invMass==0.f? 0 : 1;
+ worldAabbs[bodyId] = worldAabb;
+ }
+}
+
+#endif //B3_UPDATE_AABBS_H
diff --git a/thirdparty/bullet/src/Bullet3Collision/premake4.lua b/thirdparty/bullet/src/Bullet3Collision/premake4.lua
new file mode 100644
index 0000000000..0b47f8ea5b
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Collision/premake4.lua
@@ -0,0 +1,13 @@
+ project "Bullet3Collision"
+
+ language "C++"
+
+ kind "StaticLib"
+
+ includedirs {".."}
+
+
+ files {
+ "**.cpp",
+ "**.h"
+ } \ No newline at end of file
diff --git a/thirdparty/bullet/src/Bullet3Common/CMakeLists.txt b/thirdparty/bullet/src/Bullet3Common/CMakeLists.txt
new file mode 100644
index 0000000000..e899e67d94
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Common/CMakeLists.txt
@@ -0,0 +1,63 @@
+
+INCLUDE_DIRECTORIES(
+ ${BULLET_PHYSICS_SOURCE_DIR}/src
+)
+
+SET(Bullet3Common_SRCS
+ b3AlignedAllocator.cpp
+ b3Vector3.cpp
+ b3Logging.cpp
+)
+
+SET(Bullet3Common_HDRS
+ b3AlignedAllocator.h
+ b3AlignedObjectArray.h
+ b3CommandLineArgs.h
+ b3HashMap.h
+ b3Logging.h
+ b3Matrix3x3.h
+ b3MinMax.h
+ b3PoolAllocator.h
+ b3QuadWord.h
+ b3Quaternion.h
+ b3Random.h
+ b3Scalar.h
+ b3StackAlloc.h
+ b3Transform.h
+ b3TransformUtil.h
+ b3Vector3.h
+ shared/b3Float4
+ shared/b3Int2.h
+ shared/b3Int4.h
+ shared/b3Mat3x3.h
+ shared/b3PlatformDefinitions
+ shared/b3Quat.h
+)
+
+ADD_LIBRARY(Bullet3Common ${Bullet3Common_SRCS} ${Bullet3Common_HDRS})
+SET_TARGET_PROPERTIES(Bullet3Common PROPERTIES VERSION ${BULLET_VERSION})
+SET_TARGET_PROPERTIES(Bullet3Common PROPERTIES SOVERSION ${BULLET_VERSION})
+
+IF (INSTALL_LIBS)
+ IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
+ #FILES_MATCHING requires CMake 2.6
+ IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
+ IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+ INSTALL(TARGETS Bullet3Common DESTINATION .)
+ ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+ INSTALL(TARGETS Bullet3Common
+ RUNTIME DESTINATION bin
+ LIBRARY DESTINATION lib${LIB_SUFFIX}
+ ARCHIVE DESTINATION lib${LIB_SUFFIX})
+ INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.h" PATTERN
+".svn" EXCLUDE PATTERN "CMakeFiles" EXCLUDE)
+ ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+ ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
+
+ IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+ SET_TARGET_PROPERTIES(Bullet3Common PROPERTIES FRAMEWORK true)
+ SET_TARGET_PROPERTIES(Bullet3Common PROPERTIES PUBLIC_HEADER "${Bullet3Common_HDRS}")
+ ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+ ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
+ENDIF (INSTALL_LIBS)
diff --git a/thirdparty/bullet/src/Bullet3Common/b3AlignedAllocator.cpp b/thirdparty/bullet/src/Bullet3Common/b3AlignedAllocator.cpp
new file mode 100644
index 0000000000..b98e2b4d33
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Common/b3AlignedAllocator.cpp
@@ -0,0 +1,181 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2013 Erwin Coumans 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 "b3AlignedAllocator.h"
+
+int b3g_numAlignedAllocs = 0;
+int b3g_numAlignedFree = 0;
+int b3g_totalBytesAlignedAllocs = 0;//detect memory leaks
+
+static void *b3AllocDefault(size_t size)
+{
+ return malloc(size);
+}
+
+static void b3FreeDefault(void *ptr)
+{
+ free(ptr);
+}
+
+static b3AllocFunc* b3s_allocFunc = b3AllocDefault;
+static b3FreeFunc* b3s_freeFunc = b3FreeDefault;
+
+
+
+#if defined (B3_HAS_ALIGNED_ALLOCATOR)
+#include <malloc.h>
+static void *b3AlignedAllocDefault(size_t size, int alignment)
+{
+ return _aligned_malloc(size, (size_t)alignment);
+}
+
+static void b3AlignedFreeDefault(void *ptr)
+{
+ _aligned_free(ptr);
+}
+#elif defined(__CELLOS_LV2__)
+#include <stdlib.h>
+
+static inline void *b3AlignedAllocDefault(size_t size, int alignment)
+{
+ return memalign(alignment, size);
+}
+
+static inline void b3AlignedFreeDefault(void *ptr)
+{
+ free(ptr);
+}
+#else
+
+
+
+
+
+static inline void *b3AlignedAllocDefault(size_t size, int alignment)
+{
+ void *ret;
+ char *real;
+ real = (char *)b3s_allocFunc(size + sizeof(void *) + (alignment-1));
+ if (real) {
+ ret = b3AlignPointer(real + sizeof(void *),alignment);
+ *((void **)(ret)-1) = (void *)(real);
+ } else {
+ ret = (void *)(real);
+ }
+ return (ret);
+}
+
+static inline void b3AlignedFreeDefault(void *ptr)
+{
+ void* real;
+
+ if (ptr) {
+ real = *((void **)(ptr)-1);
+ b3s_freeFunc(real);
+ }
+}
+#endif
+
+
+static b3AlignedAllocFunc* b3s_alignedAllocFunc = b3AlignedAllocDefault;
+static b3AlignedFreeFunc* b3s_alignedFreeFunc = b3AlignedFreeDefault;
+
+void b3AlignedAllocSetCustomAligned(b3AlignedAllocFunc *allocFunc, b3AlignedFreeFunc *freeFunc)
+{
+ b3s_alignedAllocFunc = allocFunc ? allocFunc : b3AlignedAllocDefault;
+ b3s_alignedFreeFunc = freeFunc ? freeFunc : b3AlignedFreeDefault;
+}
+
+void b3AlignedAllocSetCustom(b3AllocFunc *allocFunc, b3FreeFunc *freeFunc)
+{
+ b3s_allocFunc = allocFunc ? allocFunc : b3AllocDefault;
+ b3s_freeFunc = freeFunc ? freeFunc : b3FreeDefault;
+}
+
+#ifdef B3_DEBUG_MEMORY_ALLOCATIONS
+//this generic allocator provides the total allocated number of bytes
+#include <stdio.h>
+
+void* b3AlignedAllocInternal (size_t size, int alignment,int line,char* filename)
+{
+ void *ret;
+ char *real;
+
+ b3g_totalBytesAlignedAllocs += size;
+ b3g_numAlignedAllocs++;
+
+
+ real = (char *)b3s_allocFunc(size + 2*sizeof(void *) + (alignment-1));
+ if (real) {
+ ret = (void*) b3AlignPointer(real + 2*sizeof(void *), alignment);
+ *((void **)(ret)-1) = (void *)(real);
+ *((int*)(ret)-2) = size;
+
+ } else {
+ ret = (void *)(real);//??
+ }
+
+ b3Printf("allocation#%d at address %x, from %s,line %d, size %d\n",b3g_numAlignedAllocs,real, filename,line,size);
+
+ int* ptr = (int*)ret;
+ *ptr = 12;
+ return (ret);
+}
+
+void b3AlignedFreeInternal (void* ptr,int line,char* filename)
+{
+
+ void* real;
+ b3g_numAlignedFree++;
+
+ if (ptr) {
+ real = *((void **)(ptr)-1);
+ int size = *((int*)(ptr)-2);
+ b3g_totalBytesAlignedAllocs -= size;
+
+ b3Printf("free #%d at address %x, from %s,line %d, size %d\n",b3g_numAlignedFree,real, filename,line,size);
+
+ b3s_freeFunc(real);
+ } else
+ {
+ b3Printf("NULL ptr\n");
+ }
+}
+
+#else //B3_DEBUG_MEMORY_ALLOCATIONS
+
+void* b3AlignedAllocInternal (size_t size, int alignment)
+{
+ b3g_numAlignedAllocs++;
+ void* ptr;
+ ptr = b3s_alignedAllocFunc(size, alignment);
+// b3Printf("b3AlignedAllocInternal %d, %x\n",size,ptr);
+ return ptr;
+}
+
+void b3AlignedFreeInternal (void* ptr)
+{
+ if (!ptr)
+ {
+ return;
+ }
+
+ b3g_numAlignedFree++;
+// b3Printf("b3AlignedFreeInternal %x\n",ptr);
+ b3s_alignedFreeFunc(ptr);
+}
+
+#endif //B3_DEBUG_MEMORY_ALLOCATIONS
+
diff --git a/thirdparty/bullet/src/Bullet3Common/b3AlignedAllocator.h b/thirdparty/bullet/src/Bullet3Common/b3AlignedAllocator.h
new file mode 100644
index 0000000000..be418bd55f
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Common/b3AlignedAllocator.h
@@ -0,0 +1,107 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2013 Erwin Coumans 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 B3_ALIGNED_ALLOCATOR
+#define B3_ALIGNED_ALLOCATOR
+
+///we probably replace this with our own aligned memory allocator
+///so we replace _aligned_malloc and _aligned_free with our own
+///that is better portable and more predictable
+
+#include "b3Scalar.h"
+//#define B3_DEBUG_MEMORY_ALLOCATIONS 1
+#ifdef B3_DEBUG_MEMORY_ALLOCATIONS
+
+#define b3AlignedAlloc(a,b) \
+ b3AlignedAllocInternal(a,b,__LINE__,__FILE__)
+
+#define b3AlignedFree(ptr) \
+ b3AlignedFreeInternal(ptr,__LINE__,__FILE__)
+
+void* b3AlignedAllocInternal (size_t size, int alignment,int line,char* filename);
+
+void b3AlignedFreeInternal (void* ptr,int line,char* filename);
+
+#else
+ void* b3AlignedAllocInternal (size_t size, int alignment);
+ void b3AlignedFreeInternal (void* ptr);
+
+ #define b3AlignedAlloc(size,alignment) b3AlignedAllocInternal(size,alignment)
+ #define b3AlignedFree(ptr) b3AlignedFreeInternal(ptr)
+
+#endif
+typedef int btSizeType;
+
+typedef void *(b3AlignedAllocFunc)(size_t size, int alignment);
+typedef void (b3AlignedFreeFunc)(void *memblock);
+typedef void *(b3AllocFunc)(size_t size);
+typedef void (b3FreeFunc)(void *memblock);
+
+///The developer can let all Bullet memory allocations go through a custom memory allocator, using b3AlignedAllocSetCustom
+void b3AlignedAllocSetCustom(b3AllocFunc *allocFunc, b3FreeFunc *freeFunc);
+///If the developer has already an custom aligned allocator, then b3AlignedAllocSetCustomAligned can be used. The default aligned allocator pre-allocates extra memory using the non-aligned allocator, and instruments it.
+void b3AlignedAllocSetCustomAligned(b3AlignedAllocFunc *allocFunc, b3AlignedFreeFunc *freeFunc);
+
+
+///The b3AlignedAllocator is a portable class for aligned memory allocations.
+///Default implementations for unaligned and aligned allocations can be overridden by a custom allocator using b3AlignedAllocSetCustom and b3AlignedAllocSetCustomAligned.
+template < typename T , unsigned Alignment >
+class b3AlignedAllocator {
+
+ typedef b3AlignedAllocator< T , Alignment > self_type;
+
+public:
+
+ //just going down a list:
+ b3AlignedAllocator() {}
+ /*
+ b3AlignedAllocator( const self_type & ) {}
+ */
+
+ template < typename Other >
+ b3AlignedAllocator( const b3AlignedAllocator< Other , Alignment > & ) {}
+
+ typedef const T* const_pointer;
+ typedef const T& const_reference;
+ typedef T* pointer;
+ typedef T& reference;
+ typedef T value_type;
+
+ pointer address ( reference ref ) const { return &ref; }
+ const_pointer address ( const_reference ref ) const { return &ref; }
+ pointer allocate ( btSizeType n , const_pointer * hint = 0 ) {
+ (void)hint;
+ return reinterpret_cast< pointer >(b3AlignedAlloc( sizeof(value_type) * n , Alignment ));
+ }
+ void construct ( pointer ptr , const value_type & value ) { new (ptr) value_type( value ); }
+ void deallocate( pointer ptr ) {
+ b3AlignedFree( reinterpret_cast< void * >( ptr ) );
+ }
+ void destroy ( pointer ptr ) { ptr->~value_type(); }
+
+
+ template < typename O > struct rebind {
+ typedef b3AlignedAllocator< O , Alignment > other;
+ };
+ template < typename O >
+ self_type & operator=( const b3AlignedAllocator< O , Alignment > & ) { return *this; }
+
+ friend bool operator==( const self_type & , const self_type & ) { return true; }
+};
+
+
+
+#endif //B3_ALIGNED_ALLOCATOR
+
diff --git a/thirdparty/bullet/src/Bullet3Common/b3AlignedObjectArray.h b/thirdparty/bullet/src/Bullet3Common/b3AlignedObjectArray.h
new file mode 100644
index 0000000000..947362d08e
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Common/b3AlignedObjectArray.h
@@ -0,0 +1,533 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2013 Erwin Coumans 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 B3_OBJECT_ARRAY__
+#define B3_OBJECT_ARRAY__
+
+#include "b3Scalar.h" // has definitions like B3_FORCE_INLINE
+#include "b3AlignedAllocator.h"
+
+///If the platform doesn't support placement new, you can disable B3_USE_PLACEMENT_NEW
+///then the b3AlignedObjectArray doesn't support objects with virtual methods, and non-trivial constructors/destructors
+///You can enable B3_USE_MEMCPY, then swapping elements in the array will use memcpy instead of operator=
+///see discussion here: http://continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1231 and
+///http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1240
+
+#define B3_USE_PLACEMENT_NEW 1
+//#define B3_USE_MEMCPY 1 //disable, because it is cumbersome to find out for each platform where memcpy is defined. It can be in <memory.h> or <string.h> or otherwise...
+#define B3_ALLOW_ARRAY_COPY_OPERATOR // enabling this can accidently perform deep copies of data if you are not careful
+
+#ifdef B3_USE_MEMCPY
+#include <memory.h>
+#include <string.h>
+#endif //B3_USE_MEMCPY
+
+#ifdef B3_USE_PLACEMENT_NEW
+#include <new> //for placement new
+#endif //B3_USE_PLACEMENT_NEW
+
+
+///The b3AlignedObjectArray template class uses a subset of the stl::vector interface for its methods
+///It is developed to replace stl::vector to avoid portability issues, including STL alignment issues to add SIMD/SSE data
+template <typename T>
+//template <class T>
+class b3AlignedObjectArray
+{
+ b3AlignedAllocator<T , 16> m_allocator;
+
+ int m_size;
+ int m_capacity;
+ T* m_data;
+ //PCK: added this line
+ bool m_ownsMemory;
+
+#ifdef B3_ALLOW_ARRAY_COPY_OPERATOR
+public:
+ B3_FORCE_INLINE b3AlignedObjectArray<T>& operator=(const b3AlignedObjectArray<T> &other)
+ {
+ copyFromArray(other);
+ return *this;
+ }
+#else//B3_ALLOW_ARRAY_COPY_OPERATOR
+private:
+ B3_FORCE_INLINE b3AlignedObjectArray<T>& operator=(const b3AlignedObjectArray<T> &other);
+#endif//B3_ALLOW_ARRAY_COPY_OPERATOR
+
+protected:
+ B3_FORCE_INLINE int allocSize(int size)
+ {
+ return (size ? size*2 : 1);
+ }
+ B3_FORCE_INLINE void copy(int start,int end, T* dest) const
+ {
+ int i;
+ for (i=start;i<end;++i)
+#ifdef B3_USE_PLACEMENT_NEW
+ new (&dest[i]) T(m_data[i]);
+#else
+ dest[i] = m_data[i];
+#endif //B3_USE_PLACEMENT_NEW
+ }
+
+ B3_FORCE_INLINE void init()
+ {
+ //PCK: added this line
+ m_ownsMemory = true;
+ m_data = 0;
+ m_size = 0;
+ m_capacity = 0;
+ }
+ B3_FORCE_INLINE void destroy(int first,int last)
+ {
+ int i;
+ for (i=first; i<last;i++)
+ {
+ m_data[i].~T();
+ }
+ }
+
+ B3_FORCE_INLINE void* allocate(int size)
+ {
+ if (size)
+ return m_allocator.allocate(size);
+ return 0;
+ }
+
+ B3_FORCE_INLINE void deallocate()
+ {
+ if(m_data) {
+ //PCK: enclosed the deallocation in this block
+ if (m_ownsMemory)
+ {
+ m_allocator.deallocate(m_data);
+ }
+ m_data = 0;
+ }
+ }
+
+
+
+
+ public:
+
+ b3AlignedObjectArray()
+ {
+ init();
+ }
+
+ ~b3AlignedObjectArray()
+ {
+ clear();
+ }
+
+ ///Generally it is best to avoid using the copy constructor of an b3AlignedObjectArray, and use a (const) reference to the array instead.
+ b3AlignedObjectArray(const b3AlignedObjectArray& otherArray)
+ {
+ init();
+
+ int otherSize = otherArray.size();
+ resize (otherSize);
+ otherArray.copy(0, otherSize, m_data);
+ }
+
+
+
+ /// return the number of elements in the array
+ B3_FORCE_INLINE int size() const
+ {
+ return m_size;
+ }
+
+ B3_FORCE_INLINE const T& at(int n) const
+ {
+ b3Assert(n>=0);
+ b3Assert(n<size());
+ return m_data[n];
+ }
+
+ B3_FORCE_INLINE T& at(int n)
+ {
+ b3Assert(n>=0);
+ b3Assert(n<size());
+ return m_data[n];
+ }
+
+ B3_FORCE_INLINE const T& operator[](int n) const
+ {
+ b3Assert(n>=0);
+ b3Assert(n<size());
+ return m_data[n];
+ }
+
+ B3_FORCE_INLINE T& operator[](int n)
+ {
+ b3Assert(n>=0);
+ b3Assert(n<size());
+ return m_data[n];
+ }
+
+
+ ///clear the array, deallocated memory. Generally it is better to use array.resize(0), to reduce performance overhead of run-time memory (de)allocations.
+ B3_FORCE_INLINE void clear()
+ {
+ destroy(0,size());
+
+ deallocate();
+
+ init();
+ }
+
+ B3_FORCE_INLINE void pop_back()
+ {
+ b3Assert(m_size>0);
+ m_size--;
+ m_data[m_size].~T();
+ }
+
+
+ ///resize changes the number of elements in the array. If the new size is larger, the new elements will be constructed using the optional second argument.
+ ///when the new number of elements is smaller, the destructor will be called, but memory will not be freed, to reduce performance overhead of run-time memory (de)allocations.
+ B3_FORCE_INLINE void resizeNoInitialize(int newsize)
+ {
+ int curSize = size();
+
+ if (newsize < curSize)
+ {
+ } else
+ {
+ if (newsize > size())
+ {
+ reserve(newsize);
+ }
+ //leave this uninitialized
+ }
+ m_size = newsize;
+ }
+
+ B3_FORCE_INLINE void resize(int newsize, const T& fillData=T())
+ {
+ int curSize = size();
+
+ if (newsize < curSize)
+ {
+ for(int i = newsize; i < curSize; i++)
+ {
+ m_data[i].~T();
+ }
+ } else
+ {
+ if (newsize > size())
+ {
+ reserve(newsize);
+ }
+#ifdef B3_USE_PLACEMENT_NEW
+ for (int i=curSize;i<newsize;i++)
+ {
+ new ( &m_data[i]) T(fillData);
+ }
+#endif //B3_USE_PLACEMENT_NEW
+
+ }
+
+ m_size = newsize;
+ }
+ B3_FORCE_INLINE T& expandNonInitializing( )
+ {
+ int sz = size();
+ if( sz == capacity() )
+ {
+ reserve( allocSize(size()) );
+ }
+ m_size++;
+
+ return m_data[sz];
+ }
+
+
+ B3_FORCE_INLINE T& expand( const T& fillValue=T())
+ {
+ int sz = size();
+ if( sz == capacity() )
+ {
+ reserve( allocSize(size()) );
+ }
+ m_size++;
+#ifdef B3_USE_PLACEMENT_NEW
+ new (&m_data[sz]) T(fillValue); //use the in-place new (not really allocating heap memory)
+#endif
+
+ return m_data[sz];
+ }
+
+
+ B3_FORCE_INLINE void push_back(const T& _Val)
+ {
+ int sz = size();
+ if( sz == capacity() )
+ {
+ reserve( allocSize(size()) );
+ }
+
+#ifdef B3_USE_PLACEMENT_NEW
+ new ( &m_data[m_size] ) T(_Val);
+#else
+ m_data[size()] = _Val;
+#endif //B3_USE_PLACEMENT_NEW
+
+ m_size++;
+ }
+
+
+ /// return the pre-allocated (reserved) elements, this is at least as large as the total number of elements,see size() and reserve()
+ B3_FORCE_INLINE int capacity() const
+ {
+ return m_capacity;
+ }
+
+ B3_FORCE_INLINE void reserve(int _Count)
+ { // determine new minimum length of allocated storage
+ if (capacity() < _Count)
+ { // not enough room, reallocate
+ T* s = (T*)allocate(_Count);
+ b3Assert(s);
+ if (s==0)
+ {
+ b3Error("b3AlignedObjectArray reserve out-of-memory\n");
+ _Count=0;
+ m_size=0;
+ }
+ copy(0, size(), s);
+
+ destroy(0,size());
+
+ deallocate();
+
+ //PCK: added this line
+ m_ownsMemory = true;
+
+ m_data = s;
+
+ m_capacity = _Count;
+
+ }
+ }
+
+
+ class less
+ {
+ public:
+
+ bool operator() ( const T& a, const T& b )
+ {
+ return ( a < b );
+ }
+ };
+
+
+ template <typename L>
+ void quickSortInternal(const L& CompareFunc,int lo, int hi)
+ {
+ // lo is the lower index, hi is the upper index
+ // of the region of array a that is to be sorted
+ int i=lo, j=hi;
+ T x=m_data[(lo+hi)/2];
+
+ // partition
+ do
+ {
+ while (CompareFunc(m_data[i],x))
+ i++;
+ while (CompareFunc(x,m_data[j]))
+ j--;
+ if (i<=j)
+ {
+ swap(i,j);
+ i++; j--;
+ }
+ } while (i<=j);
+
+ // recursion
+ if (lo<j)
+ quickSortInternal( CompareFunc, lo, j);
+ if (i<hi)
+ quickSortInternal( CompareFunc, i, hi);
+ }
+
+
+ template <typename L>
+ void quickSort(const L& CompareFunc)
+ {
+ //don't sort 0 or 1 elements
+ if (size()>1)
+ {
+ quickSortInternal(CompareFunc,0,size()-1);
+ }
+ }
+
+
+ ///heap sort from http://www.csse.monash.edu.au/~lloyd/tildeAlgDS/Sort/Heap/
+ template <typename L>
+ void downHeap(T *pArr, int k, int n, const L& CompareFunc)
+ {
+ /* PRE: a[k+1..N] is a heap */
+ /* POST: a[k..N] is a heap */
+
+ T temp = pArr[k - 1];
+ /* k has child(s) */
+ while (k <= n/2)
+ {
+ int child = 2*k;
+
+ if ((child < n) && CompareFunc(pArr[child - 1] , pArr[child]))
+ {
+ child++;
+ }
+ /* pick larger child */
+ if (CompareFunc(temp , pArr[child - 1]))
+ {
+ /* move child up */
+ pArr[k - 1] = pArr[child - 1];
+ k = child;
+ }
+ else
+ {
+ break;
+ }
+ }
+ pArr[k - 1] = temp;
+ } /*downHeap*/
+
+ void swap(int index0,int index1)
+ {
+#ifdef B3_USE_MEMCPY
+ char temp[sizeof(T)];
+ memcpy(temp,&m_data[index0],sizeof(T));
+ memcpy(&m_data[index0],&m_data[index1],sizeof(T));
+ memcpy(&m_data[index1],temp,sizeof(T));
+#else
+ T temp = m_data[index0];
+ m_data[index0] = m_data[index1];
+ m_data[index1] = temp;
+#endif //B3_USE_PLACEMENT_NEW
+
+ }
+
+ template <typename L>
+ void heapSort(const L& CompareFunc)
+ {
+ /* sort a[0..N-1], N.B. 0 to N-1 */
+ int k;
+ int n = m_size;
+ for (k = n/2; k > 0; k--)
+ {
+ downHeap(m_data, k, n, CompareFunc);
+ }
+
+ /* a[1..N] is now a heap */
+ while ( n>=1 )
+ {
+ swap(0,n-1); /* largest of a[0..n-1] */
+
+
+ n = n - 1;
+ /* restore a[1..i-1] heap */
+ downHeap(m_data, 1, n, CompareFunc);
+ }
+ }
+
+ ///non-recursive binary search, assumes sorted array
+ int findBinarySearch(const T& key) const
+ {
+ int first = 0;
+ int last = size()-1;
+
+ //assume sorted array
+ while (first <= last) {
+ int mid = (first + last) / 2; // compute mid point.
+ if (key > m_data[mid])
+ first = mid + 1; // repeat search in top half.
+ else if (key < m_data[mid])
+ last = mid - 1; // repeat search in bottom half.
+ else
+ return mid; // found it. return position /////
+ }
+ return size(); // failed to find key
+ }
+
+
+ int findLinearSearch(const T& key) const
+ {
+ int index=size();
+ int i;
+
+ for (i=0;i<size();i++)
+ {
+ if (m_data[i] == key)
+ {
+ index = i;
+ break;
+ }
+ }
+ return index;
+ }
+
+ int findLinearSearch2(const T& key) const
+ {
+ int index=-1;
+ int i;
+
+ for (i=0;i<size();i++)
+ {
+ if (m_data[i] == key)
+ {
+ index = i;
+ break;
+ }
+ }
+ return index;
+ }
+
+ void remove(const T& key)
+ {
+
+ int findIndex = findLinearSearch(key);
+ if (findIndex<size())
+ {
+ swap( findIndex,size()-1);
+ pop_back();
+ }
+ }
+
+ //PCK: whole function
+ void initializeFromBuffer(void *buffer, int size, int capacity)
+ {
+ clear();
+ m_ownsMemory = false;
+ m_data = (T*)buffer;
+ m_size = size;
+ m_capacity = capacity;
+ }
+
+ void copyFromArray(const b3AlignedObjectArray& otherArray)
+ {
+ int otherSize = otherArray.size();
+ resize (otherSize);
+ otherArray.copy(0, otherSize, m_data);
+ }
+
+};
+
+#endif //B3_OBJECT_ARRAY__
diff --git a/thirdparty/bullet/src/Bullet3Common/b3CommandLineArgs.h b/thirdparty/bullet/src/Bullet3Common/b3CommandLineArgs.h
new file mode 100644
index 0000000000..38df8e2600
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Common/b3CommandLineArgs.h
@@ -0,0 +1,101 @@
+#ifndef COMMAND_LINE_ARGS_H
+#define COMMAND_LINE_ARGS_H
+
+/******************************************************************************
+ * Command-line parsing
+ ******************************************************************************/
+#include <map>
+#include <algorithm>
+#include <string>
+#include <cstring>
+#include <sstream>
+class b3CommandLineArgs
+{
+protected:
+
+ std::map<std::string, std::string> pairs;
+
+public:
+
+ // Constructor
+ b3CommandLineArgs(int argc, char **argv)
+ {
+ addArgs(argc,argv);
+ }
+
+ void addArgs(int argc, char**argv)
+ {
+ for (int i = 1; i < argc; i++)
+ {
+ std::string arg = argv[i];
+
+ if ((arg.length() < 2) || (arg[0] != '-') || (arg[1] != '-')) {
+ continue;
+ }
+
+ std::string::size_type pos;
+ std::string key, val;
+ if ((pos = arg.find( '=')) == std::string::npos) {
+ key = std::string(arg, 2, arg.length() - 2);
+ val = "";
+ } else {
+ key = std::string(arg, 2, pos - 2);
+ val = std::string(arg, pos + 1, arg.length() - 1);
+ }
+
+ //only add new keys, don't replace existing
+ if(pairs.find(key) == pairs.end())
+ {
+ pairs[key] = val;
+ }
+ }
+ }
+
+ bool CheckCmdLineFlag(const char* arg_name)
+ {
+ std::map<std::string, std::string>::iterator itr;
+ if ((itr = pairs.find(arg_name)) != pairs.end()) {
+ return true;
+ }
+ return false;
+ }
+
+ template <typename T>
+ bool GetCmdLineArgument(const char *arg_name, T &val);
+
+ int ParsedArgc()
+ {
+ return pairs.size();
+ }
+};
+
+template <typename T>
+inline bool b3CommandLineArgs::GetCmdLineArgument(const char *arg_name, T &val)
+{
+ std::map<std::string, std::string>::iterator itr;
+ if ((itr = pairs.find(arg_name)) != pairs.end()) {
+ std::istringstream strstream(itr->second);
+ strstream >> val;
+ return true;
+ }
+ return false;
+}
+
+template <>
+inline bool b3CommandLineArgs::GetCmdLineArgument<char*>(const char* arg_name, char* &val)
+{
+ std::map<std::string, std::string>::iterator itr;
+ if ((itr = pairs.find(arg_name)) != pairs.end()) {
+
+ std::string s = itr->second;
+ val = (char*) malloc(sizeof(char) * (s.length() + 1));
+ std::strcpy(val, s.c_str());
+ return true;
+ } else {
+ val = NULL;
+ }
+ return false;
+}
+
+
+#endif //COMMAND_LINE_ARGS_H
diff --git a/thirdparty/bullet/src/Bullet3Common/b3FileUtils.h b/thirdparty/bullet/src/Bullet3Common/b3FileUtils.h
new file mode 100644
index 0000000000..1a331029ea
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Common/b3FileUtils.h
@@ -0,0 +1,138 @@
+#ifndef B3_FILE_UTILS_H
+#define B3_FILE_UTILS_H
+
+#include <stdio.h>
+#include "b3Scalar.h"
+#include <stddef.h>//ptrdiff_h
+#include <string.h>
+
+struct b3FileUtils
+{
+ b3FileUtils()
+ {
+ }
+ virtual ~b3FileUtils()
+ {
+ }
+
+ static bool findFile(const char* orgFileName, char* relativeFileName, int maxRelativeFileNameMaxLen)
+ {
+ FILE* f=0;
+ f = fopen(orgFileName,"rb");
+ if (f)
+ {
+ //printf("original file found: [%s]\n", orgFileName);
+ sprintf(relativeFileName,"%s", orgFileName);
+ fclose(f);
+ return true;
+ }
+
+ //printf("Trying various directories, relative to current working directory\n");
+ const char* prefix[]={"./","./data/","../data/","../../data/","../../../data/","../../../../data/"};
+ int numPrefixes = sizeof(prefix)/sizeof(const char*);
+
+ f=0;
+ bool fileFound = false;
+
+ for (int i=0;!f && i<numPrefixes;i++)
+ {
+#ifdef _WIN32
+ sprintf_s(relativeFileName,maxRelativeFileNameMaxLen,"%s%s",prefix[i],orgFileName);
+#else
+ sprintf(relativeFileName,"%s%s",prefix[i],orgFileName);
+#endif
+ f = fopen(relativeFileName,"rb");
+ if (f)
+ {
+ fileFound = true;
+ break;
+ }
+ }
+ if (f)
+ {
+ fclose(f);
+ }
+
+ return fileFound;
+ }
+
+ static const char* strip2(const char* name, const char* pattern)
+ {
+ size_t const patlen = strlen(pattern);
+ size_t patcnt = 0;
+ const char * oriptr;
+ const char * patloc;
+ // find how many times the pattern occurs in the original string
+ for (oriptr = name; (patloc = strstr(oriptr, pattern)); oriptr = patloc + patlen)
+ {
+ patcnt++;
+ }
+ return oriptr;
+ }
+
+
+
+ static int extractPath(const char* fileName, char* path, int maxPathLength)
+ {
+ const char* stripped = strip2(fileName, "/");
+ stripped = strip2(stripped, "\\");
+
+ ptrdiff_t len = stripped-fileName;
+ b3Assert((len+1)<maxPathLength);
+
+ if (len && ((len+1)<maxPathLength))
+ {
+
+ for (int i=0;i<len;i++)
+ {
+ path[i] = fileName[i];
+ }
+ path[len]=0;
+ } else
+ {
+ len = 0;
+ b3Assert(maxPathLength>0);
+ if (maxPathLength>0)
+ {
+ path[len] = 0;
+ }
+ }
+ return len;
+ }
+
+ static char toLowerChar(const char t)
+ {
+ if (t>=(char)'A' && t<=(char)'Z')
+ return t + ((char)'a' - (char)'A');
+ else
+ return t;
+ }
+
+
+ static void toLower(char* str)
+ {
+ int len=strlen(str);
+ for (int i=0;i<len;i++)
+ {
+ str[i] = toLowerChar(str[i]);
+ }
+ }
+
+
+ /*static const char* strip2(const char* name, const char* pattern)
+ {
+ size_t const patlen = strlen(pattern);
+ size_t patcnt = 0;
+ const char * oriptr;
+ const char * patloc;
+ // find how many times the pattern occurs in the original string
+ for (oriptr = name; patloc = strstr(oriptr, pattern); oriptr = patloc + patlen)
+ {
+ patcnt++;
+ }
+ return oriptr;
+ }
+ */
+
+};
+#endif //B3_FILE_UTILS_H
diff --git a/thirdparty/bullet/src/Bullet3Common/b3HashMap.h b/thirdparty/bullet/src/Bullet3Common/b3HashMap.h
new file mode 100644
index 0000000000..24a59d9baa
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Common/b3HashMap.h
@@ -0,0 +1,466 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2013 Erwin Coumans 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 B3_HASH_MAP_H
+#define B3_HASH_MAP_H
+
+#include "b3AlignedObjectArray.h"
+
+
+#include <string>
+
+///very basic hashable string implementation, compatible with b3HashMap
+struct b3HashString
+{
+ std::string m_string;
+ unsigned int m_hash;
+
+ B3_FORCE_INLINE unsigned int getHash()const
+ {
+ return m_hash;
+ }
+
+
+ b3HashString(const char* name)
+ :m_string(name)
+ {
+
+ /* magic numbers from http://www.isthe.com/chongo/tech/comp/fnv/ */
+ static const unsigned int InitialFNV = 2166136261u;
+ static const unsigned int FNVMultiple = 16777619u;
+
+ /* Fowler / Noll / Vo (FNV) Hash */
+ unsigned int hash = InitialFNV;
+ int len = m_string.length();
+ for(int i = 0; i<len; i++)
+ {
+ hash = hash ^ (m_string[i]); /* xor the low 8 bits */
+ hash = hash * FNVMultiple; /* multiply by the magic number */
+ }
+ m_hash = hash;
+ }
+
+ int portableStringCompare(const char* src, const char* dst) const
+ {
+ int ret = 0 ;
+
+ while( ! (ret = *(unsigned char *)src - *(unsigned char *)dst) && *dst)
+ ++src, ++dst;
+
+ if ( ret < 0 )
+ ret = -1 ;
+ else if ( ret > 0 )
+ ret = 1 ;
+
+ return( ret );
+ }
+
+ bool equals(const b3HashString& other) const
+ {
+ return (m_string == other.m_string);
+ }
+
+};
+
+
+const int B3_HASH_NULL=0xffffffff;
+
+
+class b3HashInt
+{
+ int m_uid;
+public:
+ b3HashInt(int uid) :m_uid(uid)
+ {
+ }
+
+ int getUid1() const
+ {
+ return m_uid;
+ }
+
+ void setUid1(int uid)
+ {
+ m_uid = uid;
+ }
+
+ bool equals(const b3HashInt& other) const
+ {
+ return getUid1() == other.getUid1();
+ }
+ //to our success
+ B3_FORCE_INLINE unsigned int getHash()const
+ {
+ int key = m_uid;
+ // Thomas Wang's hash
+ key += ~(key << 15); key ^= (key >> 10); key += (key << 3); key ^= (key >> 6); key += ~(key << 11); key ^= (key >> 16);
+ return key;
+ }
+};
+
+
+
+class b3HashPtr
+{
+
+ union
+ {
+ const void* m_pointer;
+ int m_hashValues[2];
+ };
+
+public:
+
+ b3HashPtr(const void* ptr)
+ :m_pointer(ptr)
+ {
+ }
+
+ const void* getPointer() const
+ {
+ return m_pointer;
+ }
+
+ bool equals(const b3HashPtr& other) const
+ {
+ return getPointer() == other.getPointer();
+ }
+
+ //to our success
+ B3_FORCE_INLINE unsigned int getHash()const
+ {
+ const bool VOID_IS_8 = ((sizeof(void*)==8));
+
+ int key = VOID_IS_8? m_hashValues[0]+m_hashValues[1] : m_hashValues[0];
+
+ // Thomas Wang's hash
+ key += ~(key << 15); key ^= (key >> 10); key += (key << 3); key ^= (key >> 6); key += ~(key << 11); key ^= (key >> 16);
+ return key;
+ }
+
+
+};
+
+
+template <class Value>
+class b3HashKeyPtr
+{
+ int m_uid;
+public:
+
+ b3HashKeyPtr(int uid) :m_uid(uid)
+ {
+ }
+
+ int getUid1() const
+ {
+ return m_uid;
+ }
+
+ bool equals(const b3HashKeyPtr<Value>& other) const
+ {
+ return getUid1() == other.getUid1();
+ }
+
+ //to our success
+ B3_FORCE_INLINE unsigned int getHash()const
+ {
+ int key = m_uid;
+ // Thomas Wang's hash
+ key += ~(key << 15); key ^= (key >> 10); key += (key << 3); key ^= (key >> 6); key += ~(key << 11); key ^= (key >> 16);
+ return key;
+ }
+
+
+};
+
+
+template <class Value>
+class b3HashKey
+{
+ int m_uid;
+public:
+
+ b3HashKey(int uid) :m_uid(uid)
+ {
+ }
+
+ int getUid1() const
+ {
+ return m_uid;
+ }
+
+ bool equals(const b3HashKey<Value>& other) const
+ {
+ return getUid1() == other.getUid1();
+ }
+ //to our success
+ B3_FORCE_INLINE unsigned int getHash()const
+ {
+ int key = m_uid;
+ // Thomas Wang's hash
+ key += ~(key << 15); key ^= (key >> 10); key += (key << 3); key ^= (key >> 6); key += ~(key << 11); key ^= (key >> 16);
+ return key;
+ }
+};
+
+
+///The b3HashMap template class implements a generic and lightweight hashmap.
+///A basic sample of how to use b3HashMap is located in Demos\BasicDemo\main.cpp
+template <class Key, class Value>
+class b3HashMap
+{
+
+protected:
+ b3AlignedObjectArray<int> m_hashTable;
+ b3AlignedObjectArray<int> m_next;
+
+ b3AlignedObjectArray<Value> m_valueArray;
+ b3AlignedObjectArray<Key> m_keyArray;
+
+ void growTables(const Key& /*key*/)
+ {
+ int newCapacity = m_valueArray.capacity();
+
+ if (m_hashTable.size() < newCapacity)
+ {
+ //grow hashtable and next table
+ int curHashtableSize = m_hashTable.size();
+
+ m_hashTable.resize(newCapacity);
+ m_next.resize(newCapacity);
+
+ int i;
+
+ for (i= 0; i < newCapacity; ++i)
+ {
+ m_hashTable[i] = B3_HASH_NULL;
+ }
+ for (i = 0; i < newCapacity; ++i)
+ {
+ m_next[i] = B3_HASH_NULL;
+ }
+
+ for(i=0;i<curHashtableSize;i++)
+ {
+ //const Value& value = m_valueArray[i];
+ //const Key& key = m_keyArray[i];
+
+ int hashValue = m_keyArray[i].getHash() & (m_valueArray.capacity()-1); // New hash value with new mask
+ m_next[i] = m_hashTable[hashValue];
+ m_hashTable[hashValue] = i;
+ }
+
+
+ }
+ }
+
+ public:
+
+ void insert(const Key& key, const Value& value) {
+ int hash = key.getHash() & (m_valueArray.capacity()-1);
+
+ //replace value if the key is already there
+ int index = findIndex(key);
+ if (index != B3_HASH_NULL)
+ {
+ m_valueArray[index]=value;
+ return;
+ }
+
+ int count = m_valueArray.size();
+ int oldCapacity = m_valueArray.capacity();
+ m_valueArray.push_back(value);
+ m_keyArray.push_back(key);
+
+ int newCapacity = m_valueArray.capacity();
+ if (oldCapacity < newCapacity)
+ {
+ growTables(key);
+ //hash with new capacity
+ hash = key.getHash() & (m_valueArray.capacity()-1);
+ }
+ m_next[count] = m_hashTable[hash];
+ m_hashTable[hash] = count;
+ }
+
+ void remove(const Key& key) {
+
+ int hash = key.getHash() & (m_valueArray.capacity()-1);
+
+ int pairIndex = findIndex(key);
+
+ if (pairIndex ==B3_HASH_NULL)
+ {
+ return;
+ }
+
+ // Remove the pair from the hash table.
+ int index = m_hashTable[hash];
+ b3Assert(index != B3_HASH_NULL);
+
+ int previous = B3_HASH_NULL;
+ while (index != pairIndex)
+ {
+ previous = index;
+ index = m_next[index];
+ }
+
+ if (previous != B3_HASH_NULL)
+ {
+ b3Assert(m_next[previous] == pairIndex);
+ m_next[previous] = m_next[pairIndex];
+ }
+ else
+ {
+ m_hashTable[hash] = m_next[pairIndex];
+ }
+
+ // We now move the last pair into spot of the
+ // pair being removed. We need to fix the hash
+ // table indices to support the move.
+
+ int lastPairIndex = m_valueArray.size() - 1;
+
+ // If the removed pair is the last pair, we are done.
+ if (lastPairIndex == pairIndex)
+ {
+ m_valueArray.pop_back();
+ m_keyArray.pop_back();
+ return;
+ }
+
+ // Remove the last pair from the hash table.
+ int lastHash = m_keyArray[lastPairIndex].getHash() & (m_valueArray.capacity()-1);
+
+ index = m_hashTable[lastHash];
+ b3Assert(index != B3_HASH_NULL);
+
+ previous = B3_HASH_NULL;
+ while (index != lastPairIndex)
+ {
+ previous = index;
+ index = m_next[index];
+ }
+
+ if (previous != B3_HASH_NULL)
+ {
+ b3Assert(m_next[previous] == lastPairIndex);
+ m_next[previous] = m_next[lastPairIndex];
+ }
+ else
+ {
+ m_hashTable[lastHash] = m_next[lastPairIndex];
+ }
+
+ // Copy the last pair into the remove pair's spot.
+ m_valueArray[pairIndex] = m_valueArray[lastPairIndex];
+ m_keyArray[pairIndex] = m_keyArray[lastPairIndex];
+
+ // Insert the last pair into the hash table
+ m_next[pairIndex] = m_hashTable[lastHash];
+ m_hashTable[lastHash] = pairIndex;
+
+ m_valueArray.pop_back();
+ m_keyArray.pop_back();
+
+ }
+
+
+ int size() const
+ {
+ return m_valueArray.size();
+ }
+
+ const Value* getAtIndex(int index) const
+ {
+ b3Assert(index < m_valueArray.size());
+
+ return &m_valueArray[index];
+ }
+
+ Value* getAtIndex(int index)
+ {
+ b3Assert(index < m_valueArray.size());
+
+ return &m_valueArray[index];
+ }
+
+ Key getKeyAtIndex(int index)
+ {
+ b3Assert(index < m_keyArray.size());
+ return m_keyArray[index];
+ }
+
+ const Key getKeyAtIndex(int index) const
+ {
+ b3Assert(index < m_keyArray.size());
+ return m_keyArray[index];
+ }
+
+ Value* operator[](const Key& key) {
+ return find(key);
+ }
+
+ const Value* find(const Key& key) const
+ {
+ int index = findIndex(key);
+ if (index == B3_HASH_NULL)
+ {
+ return NULL;
+ }
+ return &m_valueArray[index];
+ }
+
+ Value* find(const Key& key)
+ {
+ int index = findIndex(key);
+ if (index == B3_HASH_NULL)
+ {
+ return NULL;
+ }
+ return &m_valueArray[index];
+ }
+
+
+ int findIndex(const Key& key) const
+ {
+ unsigned int hash = key.getHash() & (m_valueArray.capacity()-1);
+
+ if (hash >= (unsigned int)m_hashTable.size())
+ {
+ return B3_HASH_NULL;
+ }
+
+ int index = m_hashTable[hash];
+ while ((index != B3_HASH_NULL) && key.equals(m_keyArray[index]) == false)
+ {
+ index = m_next[index];
+ }
+ return index;
+ }
+
+ void clear()
+ {
+ m_hashTable.clear();
+ m_next.clear();
+ m_valueArray.clear();
+ m_keyArray.clear();
+ }
+
+};
+
+#endif //B3_HASH_MAP_H
diff --git a/thirdparty/bullet/src/Bullet3Common/b3Logging.cpp b/thirdparty/bullet/src/Bullet3Common/b3Logging.cpp
new file mode 100644
index 0000000000..a8e9507155
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Common/b3Logging.cpp
@@ -0,0 +1,160 @@
+/*
+Copyright (c) 2013 Advanced Micro Devices, Inc.
+
+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.
+*/
+//Originally written by Erwin Coumans
+
+#include "b3Logging.h"
+
+#include <stdio.h>
+#include <stdarg.h>
+
+#ifdef _WIN32
+#include <windows.h>
+#endif //_WIN32
+
+
+void b3PrintfFuncDefault(const char* msg)
+{
+#ifdef _WIN32
+ OutputDebugStringA(msg);
+#endif
+ printf("%s",msg);
+ //is this portable?
+ fflush(stdout);
+}
+
+void b3WarningMessageFuncDefault(const char* msg)
+{
+#ifdef _WIN32
+ OutputDebugStringA(msg);
+#endif
+ printf("%s",msg);
+ //is this portable?
+ fflush(stdout);
+
+}
+
+
+void b3ErrorMessageFuncDefault(const char* msg)
+{
+#ifdef _WIN32
+ OutputDebugStringA(msg);
+#endif
+ printf("%s",msg);
+
+ //is this portable?
+ fflush(stdout);
+
+}
+
+
+
+static b3PrintfFunc* b3s_printfFunc = b3PrintfFuncDefault;
+static b3WarningMessageFunc* b3s_warningMessageFunc = b3WarningMessageFuncDefault;
+static b3ErrorMessageFunc* b3s_errorMessageFunc = b3ErrorMessageFuncDefault;
+
+
+///The developer can route b3Printf output using their own implementation
+void b3SetCustomPrintfFunc(b3PrintfFunc* printfFunc)
+{
+ b3s_printfFunc = printfFunc;
+}
+void b3SetCustomWarningMessageFunc(b3PrintfFunc* warningMessageFunc)
+{
+ b3s_warningMessageFunc = warningMessageFunc;
+}
+void b3SetCustomErrorMessageFunc(b3PrintfFunc* errorMessageFunc)
+{
+ b3s_errorMessageFunc = errorMessageFunc;
+}
+
+//#define B3_MAX_DEBUG_STRING_LENGTH 2048
+#define B3_MAX_DEBUG_STRING_LENGTH 32768
+
+
+void b3OutputPrintfVarArgsInternal(const char *str, ...)
+{
+ char strDebug[B3_MAX_DEBUG_STRING_LENGTH]={0};
+ va_list argList;
+ va_start(argList, str);
+#ifdef _MSC_VER
+ vsprintf_s(strDebug,B3_MAX_DEBUG_STRING_LENGTH,str,argList);
+#else
+ vsnprintf(strDebug,B3_MAX_DEBUG_STRING_LENGTH,str,argList);
+#endif
+ (b3s_printfFunc)(strDebug);
+ va_end(argList);
+}
+void b3OutputWarningMessageVarArgsInternal(const char *str, ...)
+{
+ char strDebug[B3_MAX_DEBUG_STRING_LENGTH]={0};
+ va_list argList;
+ va_start(argList, str);
+#ifdef _MSC_VER
+ vsprintf_s(strDebug,B3_MAX_DEBUG_STRING_LENGTH,str,argList);
+#else
+ vsnprintf(strDebug,B3_MAX_DEBUG_STRING_LENGTH,str,argList);
+#endif
+ (b3s_warningMessageFunc)(strDebug);
+ va_end(argList);
+}
+void b3OutputErrorMessageVarArgsInternal(const char *str, ...)
+{
+
+ char strDebug[B3_MAX_DEBUG_STRING_LENGTH]={0};
+ va_list argList;
+ va_start(argList, str);
+#ifdef _MSC_VER
+ vsprintf_s(strDebug,B3_MAX_DEBUG_STRING_LENGTH,str,argList);
+#else
+ vsnprintf(strDebug,B3_MAX_DEBUG_STRING_LENGTH,str,argList);
+#endif
+ (b3s_errorMessageFunc)(strDebug);
+ va_end(argList);
+
+}
+
+
+void b3EnterProfileZoneDefault(const char* name)
+{
+}
+void b3LeaveProfileZoneDefault()
+{
+}
+static b3EnterProfileZoneFunc* b3s_enterFunc = b3EnterProfileZoneDefault;
+static b3LeaveProfileZoneFunc* b3s_leaveFunc = b3LeaveProfileZoneDefault;
+void b3EnterProfileZone(const char* name)
+{
+ (b3s_enterFunc)(name);
+}
+void b3LeaveProfileZone()
+{
+ (b3s_leaveFunc)();
+}
+
+void b3SetCustomEnterProfileZoneFunc(b3EnterProfileZoneFunc* enterFunc)
+{
+ b3s_enterFunc = enterFunc;
+}
+void b3SetCustomLeaveProfileZoneFunc(b3LeaveProfileZoneFunc* leaveFunc)
+{
+ b3s_leaveFunc = leaveFunc;
+}
+
+
+
+
+#ifndef _MSC_VER
+#undef vsprintf_s
+#endif
+
diff --git a/thirdparty/bullet/src/Bullet3Common/b3Logging.h b/thirdparty/bullet/src/Bullet3Common/b3Logging.h
new file mode 100644
index 0000000000..b302effe43
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Common/b3Logging.h
@@ -0,0 +1,77 @@
+
+#ifndef B3_LOGGING_H
+#define B3_LOGGING_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///We add the do/while so that the statement "if (condition) b3Printf("test"); else {...}" would fail
+///You can also customize the message by uncommenting out a different line below
+#define b3Printf(...) b3OutputPrintfVarArgsInternal(__VA_ARGS__)
+//#define b3Printf(...) do {b3OutputPrintfVarArgsInternal("b3Printf[%s,%d]:",__FILE__,__LINE__);b3OutputPrintfVarArgsInternal(__VA_ARGS__); } while(0)
+//#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)
+
+
+#ifndef B3_NO_PROFILE
+
+void b3EnterProfileZone(const char* name);
+void b3LeaveProfileZone();
+#ifdef __cplusplus
+
+class b3ProfileZone
+{
+public:
+ b3ProfileZone(const char* name)
+ {
+ b3EnterProfileZone( name );
+ }
+
+ ~b3ProfileZone()
+ {
+ b3LeaveProfileZone();
+ }
+};
+
+#define B3_PROFILE( name ) b3ProfileZone __profile( name )
+#endif
+
+#else //B3_NO_PROFILE
+
+#define B3_PROFILE( name )
+#define b3StartProfile(a)
+#define b3StopProfile
+
+#endif //#ifndef B3_NO_PROFILE
+
+
+typedef void (b3PrintfFunc)(const char* msg);
+typedef void (b3WarningMessageFunc)(const char* msg);
+typedef void (b3ErrorMessageFunc)(const char* msg);
+typedef void (b3EnterProfileZoneFunc)(const char* msg);
+typedef void (b3LeaveProfileZoneFunc)();
+
+///The developer can route b3Printf output using their own implementation
+void b3SetCustomPrintfFunc(b3PrintfFunc* printfFunc);
+void b3SetCustomWarningMessageFunc(b3WarningMessageFunc* warningMsgFunc);
+void b3SetCustomErrorMessageFunc(b3ErrorMessageFunc* errorMsgFunc);
+
+///Set custom profile zone functions (zones can be nested)
+void b3SetCustomEnterProfileZoneFunc(b3EnterProfileZoneFunc* enterFunc);
+void b3SetCustomLeaveProfileZoneFunc(b3LeaveProfileZoneFunc* leaveFunc);
+
+///Don't use those internal functions directly, use the b3Printf or b3SetCustomPrintfFunc instead (or warning/error version)
+void b3OutputPrintfVarArgsInternal(const char *str, ...);
+void b3OutputWarningMessageVarArgsInternal(const char *str, ...);
+void b3OutputErrorMessageVarArgsInternal(const char *str, ...);
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif//B3_LOGGING_H \ No newline at end of file
diff --git a/thirdparty/bullet/src/Bullet3Common/b3Matrix3x3.h b/thirdparty/bullet/src/Bullet3Common/b3Matrix3x3.h
new file mode 100644
index 0000000000..89b57cf59a
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Common/b3Matrix3x3.h
@@ -0,0 +1,1362 @@
+/*
+Copyright (c) 2003-2013 Gino van den Bergen / Erwin Coumans 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 B3_MATRIX3x3_H
+#define B3_MATRIX3x3_H
+
+#include "b3Vector3.h"
+#include "b3Quaternion.h"
+#include <stdio.h>
+
+#ifdef B3_USE_SSE
+//const __m128 B3_ATTRIBUTE_ALIGNED16(b3v2220) = {2.0f, 2.0f, 2.0f, 0.0f};
+const __m128 B3_ATTRIBUTE_ALIGNED16(b3vMPPP) = {-0.0f, +0.0f, +0.0f, +0.0f};
+#endif
+
+#if defined(B3_USE_SSE) || defined(B3_USE_NEON)
+const b3SimdFloat4 B3_ATTRIBUTE_ALIGNED16(b3v1000) = {1.0f, 0.0f, 0.0f, 0.0f};
+const b3SimdFloat4 B3_ATTRIBUTE_ALIGNED16(b3v0100) = {0.0f, 1.0f, 0.0f, 0.0f};
+const b3SimdFloat4 B3_ATTRIBUTE_ALIGNED16(b3v0010) = {0.0f, 0.0f, 1.0f, 0.0f};
+#endif
+
+#ifdef B3_USE_DOUBLE_PRECISION
+#define b3Matrix3x3Data b3Matrix3x3DoubleData
+#else
+#define b3Matrix3x3Data b3Matrix3x3FloatData
+#endif //B3_USE_DOUBLE_PRECISION
+
+
+/**@brief The b3Matrix3x3 class implements a 3x3 rotation matrix, to perform linear algebra in combination with b3Quaternion, b3Transform and b3Vector3.
+* Make sure to only include a pure orthogonal matrix without scaling. */
+B3_ATTRIBUTE_ALIGNED16(class) b3Matrix3x3 {
+
+ ///Data storage for the matrix, each vector is a row of the matrix
+ b3Vector3 m_el[3];
+
+public:
+ /** @brief No initializaion constructor */
+ b3Matrix3x3 () {}
+
+ // explicit b3Matrix3x3(const b3Scalar *m) { setFromOpenGLSubMatrix(m); }
+
+ /**@brief Constructor from Quaternion */
+ explicit b3Matrix3x3(const b3Quaternion& q) { setRotation(q); }
+ /*
+ template <typename b3Scalar>
+ Matrix3x3(const b3Scalar& yaw, const b3Scalar& pitch, const b3Scalar& roll)
+ {
+ setEulerYPR(yaw, pitch, roll);
+ }
+ */
+ /** @brief Constructor with row major formatting */
+ b3Matrix3x3(const b3Scalar& xx, const b3Scalar& xy, const b3Scalar& xz,
+ const b3Scalar& yx, const b3Scalar& yy, const b3Scalar& yz,
+ const b3Scalar& zx, const b3Scalar& zy, const b3Scalar& zz)
+ {
+ setValue(xx, xy, xz,
+ yx, yy, yz,
+ zx, zy, zz);
+ }
+
+#if (defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE))|| defined (B3_USE_NEON)
+ B3_FORCE_INLINE b3Matrix3x3 (const b3SimdFloat4 v0, const b3SimdFloat4 v1, const b3SimdFloat4 v2 )
+ {
+ m_el[0].mVec128 = v0;
+ m_el[1].mVec128 = v1;
+ m_el[2].mVec128 = v2;
+ }
+
+ B3_FORCE_INLINE b3Matrix3x3 (const b3Vector3& v0, const b3Vector3& v1, const b3Vector3& v2 )
+ {
+ m_el[0] = v0;
+ m_el[1] = v1;
+ m_el[2] = v2;
+ }
+
+ // Copy constructor
+ B3_FORCE_INLINE b3Matrix3x3(const b3Matrix3x3& rhs)
+ {
+ m_el[0].mVec128 = rhs.m_el[0].mVec128;
+ m_el[1].mVec128 = rhs.m_el[1].mVec128;
+ m_el[2].mVec128 = rhs.m_el[2].mVec128;
+ }
+
+ // Assignment Operator
+ B3_FORCE_INLINE b3Matrix3x3& operator=(const b3Matrix3x3& m)
+ {
+ m_el[0].mVec128 = m.m_el[0].mVec128;
+ m_el[1].mVec128 = m.m_el[1].mVec128;
+ m_el[2].mVec128 = m.m_el[2].mVec128;
+
+ return *this;
+ }
+
+#else
+
+ /** @brief Copy constructor */
+ B3_FORCE_INLINE b3Matrix3x3 (const b3Matrix3x3& other)
+ {
+ m_el[0] = other.m_el[0];
+ m_el[1] = other.m_el[1];
+ m_el[2] = other.m_el[2];
+ }
+
+ /** @brief Assignment Operator */
+ B3_FORCE_INLINE b3Matrix3x3& operator=(const b3Matrix3x3& other)
+ {
+ m_el[0] = other.m_el[0];
+ m_el[1] = other.m_el[1];
+ m_el[2] = other.m_el[2];
+ return *this;
+ }
+
+#endif
+
+ /** @brief Get a column of the matrix as a vector
+ * @param i Column number 0 indexed */
+ B3_FORCE_INLINE b3Vector3 getColumn(int i) const
+ {
+ return b3MakeVector3(m_el[0][i],m_el[1][i],m_el[2][i]);
+ }
+
+
+ /** @brief Get a row of the matrix as a vector
+ * @param i Row number 0 indexed */
+ B3_FORCE_INLINE const b3Vector3& getRow(int i) const
+ {
+ b3FullAssert(0 <= i && i < 3);
+ return m_el[i];
+ }
+
+ /** @brief Get a mutable reference to a row of the matrix as a vector
+ * @param i Row number 0 indexed */
+ B3_FORCE_INLINE b3Vector3& operator[](int i)
+ {
+ b3FullAssert(0 <= i && i < 3);
+ return m_el[i];
+ }
+
+ /** @brief Get a const reference to a row of the matrix as a vector
+ * @param i Row number 0 indexed */
+ B3_FORCE_INLINE const b3Vector3& operator[](int i) const
+ {
+ b3FullAssert(0 <= i && i < 3);
+ return m_el[i];
+ }
+
+ /** @brief Multiply by the target matrix on the right
+ * @param m Rotation matrix to be applied
+ * Equivilant to this = this * m */
+ b3Matrix3x3& operator*=(const b3Matrix3x3& m);
+
+ /** @brief Adds by the target matrix on the right
+ * @param m matrix to be applied
+ * Equivilant to this = this + m */
+ b3Matrix3x3& operator+=(const b3Matrix3x3& m);
+
+ /** @brief Substractss by the target matrix on the right
+ * @param m matrix to be applied
+ * Equivilant to this = this - m */
+ b3Matrix3x3& operator-=(const b3Matrix3x3& m);
+
+ /** @brief Set from the rotational part of a 4x4 OpenGL matrix
+ * @param m A pointer to the beginning of the array of scalars*/
+ void setFromOpenGLSubMatrix(const b3Scalar *m)
+ {
+ m_el[0].setValue(m[0],m[4],m[8]);
+ m_el[1].setValue(m[1],m[5],m[9]);
+ m_el[2].setValue(m[2],m[6],m[10]);
+
+ }
+ /** @brief Set the values of the matrix explicitly (row major)
+ * @param xx Top left
+ * @param xy Top Middle
+ * @param xz Top Right
+ * @param yx Middle Left
+ * @param yy Middle Middle
+ * @param yz Middle Right
+ * @param zx Bottom Left
+ * @param zy Bottom Middle
+ * @param zz Bottom Right*/
+ void setValue(const b3Scalar& xx, const b3Scalar& xy, const b3Scalar& xz,
+ const b3Scalar& yx, const b3Scalar& yy, const b3Scalar& yz,
+ const b3Scalar& zx, const b3Scalar& zy, const b3Scalar& zz)
+ {
+ m_el[0].setValue(xx,xy,xz);
+ m_el[1].setValue(yx,yy,yz);
+ m_el[2].setValue(zx,zy,zz);
+ }
+
+ /** @brief Set the matrix from a quaternion
+ * @param q The Quaternion to match */
+ void setRotation(const b3Quaternion& q)
+ {
+ b3Scalar d = q.length2();
+ b3FullAssert(d != b3Scalar(0.0));
+ b3Scalar s = b3Scalar(2.0) / d;
+
+ #if defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+ __m128 vs, Q = q.get128();
+ __m128i Qi = b3CastfTo128i(Q);
+ __m128 Y, Z;
+ __m128 V1, V2, V3;
+ __m128 V11, V21, V31;
+ __m128 NQ = _mm_xor_ps(Q, b3vMzeroMask);
+ __m128i NQi = b3CastfTo128i(NQ);
+
+ V1 = b3CastiTo128f(_mm_shuffle_epi32 (Qi, B3_SHUFFLE(1,0,2,3))); // Y X Z W
+ V2 = _mm_shuffle_ps(NQ, Q, B3_SHUFFLE(0,0,1,3)); // -X -X Y W
+ V3 = b3CastiTo128f(_mm_shuffle_epi32 (Qi, B3_SHUFFLE(2,1,0,3))); // Z Y X W
+ V1 = _mm_xor_ps(V1, b3vMPPP); // change the sign of the first element
+
+ V11 = b3CastiTo128f(_mm_shuffle_epi32 (Qi, B3_SHUFFLE(1,1,0,3))); // Y Y X W
+ V21 = _mm_unpackhi_ps(Q, Q); // Z Z W W
+ V31 = _mm_shuffle_ps(Q, NQ, B3_SHUFFLE(0,2,0,3)); // X Z -X -W
+
+ V2 = V2 * V1; //
+ V1 = V1 * V11; //
+ V3 = V3 * V31; //
+
+ V11 = _mm_shuffle_ps(NQ, Q, B3_SHUFFLE(2,3,1,3)); // -Z -W Y W
+ V11 = V11 * V21; //
+ V21 = _mm_xor_ps(V21, b3vMPPP); // change the sign of the first element
+ V31 = _mm_shuffle_ps(Q, NQ, B3_SHUFFLE(3,3,1,3)); // W W -Y -W
+ V31 = _mm_xor_ps(V31, b3vMPPP); // change the sign of the first element
+ Y = b3CastiTo128f(_mm_shuffle_epi32 (NQi, B3_SHUFFLE(3,2,0,3))); // -W -Z -X -W
+ Z = b3CastiTo128f(_mm_shuffle_epi32 (Qi, B3_SHUFFLE(1,0,1,3))); // Y X Y W
+
+ vs = _mm_load_ss(&s);
+ V21 = V21 * Y;
+ V31 = V31 * Z;
+
+ V1 = V1 + V11;
+ V2 = V2 + V21;
+ V3 = V3 + V31;
+
+ vs = b3_splat3_ps(vs, 0);
+ // s ready
+ V1 = V1 * vs;
+ V2 = V2 * vs;
+ V3 = V3 * vs;
+
+ V1 = V1 + b3v1000;
+ V2 = V2 + b3v0100;
+ V3 = V3 + b3v0010;
+
+ m_el[0] = b3MakeVector3(V1);
+ m_el[1] = b3MakeVector3(V2);
+ m_el[2] = b3MakeVector3(V3);
+ #else
+ b3Scalar xs = q.getX() * s, ys = q.getY() * s, zs = q.getZ() * s;
+ b3Scalar wx = q.getW() * xs, wy = q.getW() * ys, wz = q.getW() * zs;
+ b3Scalar xx = q.getX() * xs, xy = q.getX() * ys, xz = q.getX() * zs;
+ b3Scalar yy = q.getY() * ys, yz = q.getY() * zs, zz = q.getZ() * zs;
+ setValue(
+ b3Scalar(1.0) - (yy + zz), xy - wz, xz + wy,
+ xy + wz, b3Scalar(1.0) - (xx + zz), yz - wx,
+ xz - wy, yz + wx, b3Scalar(1.0) - (xx + yy));
+ #endif
+ }
+
+
+ /** @brief Set the matrix from euler angles using YPR around YXZ respectively
+ * @param yaw Yaw about Y axis
+ * @param pitch Pitch about X axis
+ * @param roll Roll about Z axis
+ */
+ void setEulerYPR(const b3Scalar& yaw, const b3Scalar& pitch, const b3Scalar& roll)
+ {
+ setEulerZYX(roll, pitch, yaw);
+ }
+
+ /** @brief Set the matrix from euler angles YPR around ZYX axes
+ * @param eulerX Roll about X axis
+ * @param eulerY Pitch around Y axis
+ * @param eulerZ Yaw aboud Z axis
+ *
+ * These angles are used to produce a rotation matrix. The euler
+ * angles are applied in ZYX order. I.e a vector is first rotated
+ * about X then Y and then Z
+ **/
+ void setEulerZYX(b3Scalar eulerX,b3Scalar eulerY,b3Scalar eulerZ) {
+ ///@todo proposed to reverse this since it's labeled zyx but takes arguments xyz and it will match all other parts of the code
+ b3Scalar ci ( b3Cos(eulerX));
+ b3Scalar cj ( b3Cos(eulerY));
+ b3Scalar ch ( b3Cos(eulerZ));
+ b3Scalar si ( b3Sin(eulerX));
+ b3Scalar sj ( b3Sin(eulerY));
+ b3Scalar sh ( b3Sin(eulerZ));
+ b3Scalar cc = ci * ch;
+ b3Scalar cs = ci * sh;
+ b3Scalar sc = si * ch;
+ b3Scalar ss = si * sh;
+
+ setValue(cj * ch, sj * sc - cs, sj * cc + ss,
+ cj * sh, sj * ss + cc, sj * cs - sc,
+ -sj, cj * si, cj * ci);
+ }
+
+ /**@brief Set the matrix to the identity */
+ void setIdentity()
+ {
+#if (defined(B3_USE_SSE_IN_API)&& defined (B3_USE_SSE)) || defined(B3_USE_NEON)
+ m_el[0] = b3MakeVector3(b3v1000);
+ m_el[1] = b3MakeVector3(b3v0100);
+ m_el[2] = b3MakeVector3(b3v0010);
+#else
+ setValue(b3Scalar(1.0), b3Scalar(0.0), b3Scalar(0.0),
+ b3Scalar(0.0), b3Scalar(1.0), b3Scalar(0.0),
+ b3Scalar(0.0), b3Scalar(0.0), b3Scalar(1.0));
+#endif
+ }
+
+ static const b3Matrix3x3& getIdentity()
+ {
+#if (defined(B3_USE_SSE_IN_API)&& defined (B3_USE_SSE)) || defined(B3_USE_NEON)
+ static const b3Matrix3x3
+ identityMatrix(b3v1000, b3v0100, b3v0010);
+#else
+ static const b3Matrix3x3
+ identityMatrix(
+ b3Scalar(1.0), b3Scalar(0.0), b3Scalar(0.0),
+ b3Scalar(0.0), b3Scalar(1.0), b3Scalar(0.0),
+ b3Scalar(0.0), b3Scalar(0.0), b3Scalar(1.0));
+#endif
+ return identityMatrix;
+ }
+
+ /**@brief Fill the rotational part of an OpenGL matrix and clear the shear/perspective
+ * @param m The array to be filled */
+ void getOpenGLSubMatrix(b3Scalar *m) const
+ {
+#if defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+ __m128 v0 = m_el[0].mVec128;
+ __m128 v1 = m_el[1].mVec128;
+ __m128 v2 = m_el[2].mVec128; // x2 y2 z2 w2
+ __m128 *vm = (__m128 *)m;
+ __m128 vT;
+
+ v2 = _mm_and_ps(v2, b3vFFF0fMask); // x2 y2 z2 0
+
+ vT = _mm_unpackhi_ps(v0, v1); // z0 z1 * *
+ v0 = _mm_unpacklo_ps(v0, v1); // x0 x1 y0 y1
+
+ v1 = _mm_shuffle_ps(v0, v2, B3_SHUFFLE(2, 3, 1, 3) ); // y0 y1 y2 0
+ v0 = _mm_shuffle_ps(v0, v2, B3_SHUFFLE(0, 1, 0, 3) ); // x0 x1 x2 0
+ v2 = b3CastdTo128f(_mm_move_sd(b3CastfTo128d(v2), b3CastfTo128d(vT))); // z0 z1 z2 0
+
+ vm[0] = v0;
+ vm[1] = v1;
+ vm[2] = v2;
+#elif defined(B3_USE_NEON)
+ // note: zeros the w channel. We can preserve it at the cost of two more vtrn instructions.
+ static const uint32x2_t zMask = (const uint32x2_t) {-1, 0 };
+ float32x4_t *vm = (float32x4_t *)m;
+ float32x4x2_t top = vtrnq_f32( m_el[0].mVec128, m_el[1].mVec128 ); // {x0 x1 z0 z1}, {y0 y1 w0 w1}
+ float32x2x2_t bl = vtrn_f32( vget_low_f32(m_el[2].mVec128), vdup_n_f32(0.0f) ); // {x2 0 }, {y2 0}
+ float32x4_t v0 = vcombine_f32( vget_low_f32(top.val[0]), bl.val[0] );
+ float32x4_t v1 = vcombine_f32( vget_low_f32(top.val[1]), bl.val[1] );
+ float32x2_t q = (float32x2_t) vand_u32( (uint32x2_t) vget_high_f32( m_el[2].mVec128), zMask );
+ float32x4_t v2 = vcombine_f32( vget_high_f32(top.val[0]), q ); // z0 z1 z2 0
+
+ vm[0] = v0;
+ vm[1] = v1;
+ vm[2] = v2;
+#else
+ m[0] = b3Scalar(m_el[0].getX());
+ m[1] = b3Scalar(m_el[1].getX());
+ m[2] = b3Scalar(m_el[2].getX());
+ m[3] = b3Scalar(0.0);
+ m[4] = b3Scalar(m_el[0].getY());
+ m[5] = b3Scalar(m_el[1].getY());
+ m[6] = b3Scalar(m_el[2].getY());
+ m[7] = b3Scalar(0.0);
+ m[8] = b3Scalar(m_el[0].getZ());
+ m[9] = b3Scalar(m_el[1].getZ());
+ m[10] = b3Scalar(m_el[2].getZ());
+ m[11] = b3Scalar(0.0);
+#endif
+ }
+
+ /**@brief Get the matrix represented as a quaternion
+ * @param q The quaternion which will be set */
+ void getRotation(b3Quaternion& q) const
+ {
+#if (defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE))|| defined (B3_USE_NEON)
+ b3Scalar trace = m_el[0].getX() + m_el[1].getY() + m_el[2].getZ();
+ b3Scalar s, x;
+
+ union {
+ b3SimdFloat4 vec;
+ b3Scalar f[4];
+ } temp;
+
+ if (trace > b3Scalar(0.0))
+ {
+ x = trace + b3Scalar(1.0);
+
+ temp.f[0]=m_el[2].getY() - m_el[1].getZ();
+ temp.f[1]=m_el[0].getZ() - m_el[2].getX();
+ temp.f[2]=m_el[1].getX() - m_el[0].getY();
+ temp.f[3]=x;
+ //temp.f[3]= s * b3Scalar(0.5);
+ }
+ else
+ {
+ int i, j, k;
+ if(m_el[0].getX() < m_el[1].getY())
+ {
+ if( m_el[1].getY() < m_el[2].getZ() )
+ { i = 2; j = 0; k = 1; }
+ else
+ { i = 1; j = 2; k = 0; }
+ }
+ else
+ {
+ if( m_el[0].getX() < m_el[2].getZ())
+ { i = 2; j = 0; k = 1; }
+ else
+ { i = 0; j = 1; k = 2; }
+ }
+
+ x = m_el[i][i] - m_el[j][j] - m_el[k][k] + b3Scalar(1.0);
+
+ temp.f[3] = (m_el[k][j] - m_el[j][k]);
+ temp.f[j] = (m_el[j][i] + m_el[i][j]);
+ temp.f[k] = (m_el[k][i] + m_el[i][k]);
+ temp.f[i] = x;
+ //temp.f[i] = s * b3Scalar(0.5);
+ }
+
+ s = b3Sqrt(x);
+ q.set128(temp.vec);
+ s = b3Scalar(0.5) / s;
+
+ q *= s;
+#else
+ b3Scalar trace = m_el[0].getX() + m_el[1].getY() + m_el[2].getZ();
+
+ b3Scalar temp[4];
+
+ if (trace > b3Scalar(0.0))
+ {
+ b3Scalar s = b3Sqrt(trace + b3Scalar(1.0));
+ temp[3]=(s * b3Scalar(0.5));
+ s = b3Scalar(0.5) / s;
+
+ temp[0]=((m_el[2].getY() - m_el[1].getZ()) * s);
+ temp[1]=((m_el[0].getZ() - m_el[2].getX()) * s);
+ temp[2]=((m_el[1].getX() - m_el[0].getY()) * s);
+ }
+ else
+ {
+ int i = m_el[0].getX() < m_el[1].getY() ?
+ (m_el[1].getY() < m_el[2].getZ() ? 2 : 1) :
+ (m_el[0].getX() < m_el[2].getZ() ? 2 : 0);
+ int j = (i + 1) % 3;
+ int k = (i + 2) % 3;
+
+ b3Scalar s = b3Sqrt(m_el[i][i] - m_el[j][j] - m_el[k][k] + b3Scalar(1.0));
+ temp[i] = s * b3Scalar(0.5);
+ s = b3Scalar(0.5) / s;
+
+ temp[3] = (m_el[k][j] - m_el[j][k]) * s;
+ temp[j] = (m_el[j][i] + m_el[i][j]) * s;
+ temp[k] = (m_el[k][i] + m_el[i][k]) * s;
+ }
+ q.setValue(temp[0],temp[1],temp[2],temp[3]);
+#endif
+ }
+
+ /**@brief Get the matrix represented as euler angles around YXZ, roundtrip with setEulerYPR
+ * @param yaw Yaw around Y axis
+ * @param pitch Pitch around X axis
+ * @param roll around Z axis */
+ void getEulerYPR(b3Scalar& yaw, b3Scalar& pitch, b3Scalar& roll) const
+ {
+
+ // first use the normal calculus
+ yaw = b3Scalar(b3Atan2(m_el[1].getX(), m_el[0].getX()));
+ pitch = b3Scalar(b3Asin(-m_el[2].getX()));
+ roll = b3Scalar(b3Atan2(m_el[2].getY(), m_el[2].getZ()));
+
+ // on pitch = +/-HalfPI
+ if (b3Fabs(pitch)==B3_HALF_PI)
+ {
+ if (yaw>0)
+ yaw-=B3_PI;
+ else
+ yaw+=B3_PI;
+
+ if (roll>0)
+ roll-=B3_PI;
+ else
+ roll+=B3_PI;
+ }
+ };
+
+
+ /**@brief Get the matrix represented as euler angles around ZYX
+ * @param yaw Yaw around X axis
+ * @param pitch Pitch around Y axis
+ * @param roll around X axis
+ * @param solution_number Which solution of two possible solutions ( 1 or 2) are possible values*/
+ void getEulerZYX(b3Scalar& yaw, b3Scalar& pitch, b3Scalar& roll, unsigned int solution_number = 1) const
+ {
+ struct Euler
+ {
+ b3Scalar yaw;
+ b3Scalar pitch;
+ b3Scalar roll;
+ };
+
+ Euler euler_out;
+ Euler euler_out2; //second solution
+ //get the pointer to the raw data
+
+ // Check that pitch is not at a singularity
+ if (b3Fabs(m_el[2].getX()) >= 1)
+ {
+ euler_out.yaw = 0;
+ euler_out2.yaw = 0;
+
+ // From difference of angles formula
+ b3Scalar delta = b3Atan2(m_el[0].getX(),m_el[0].getZ());
+ if (m_el[2].getX() > 0) //gimbal locked up
+ {
+ euler_out.pitch = B3_PI / b3Scalar(2.0);
+ euler_out2.pitch = B3_PI / b3Scalar(2.0);
+ euler_out.roll = euler_out.pitch + delta;
+ euler_out2.roll = euler_out.pitch + delta;
+ }
+ else // gimbal locked down
+ {
+ euler_out.pitch = -B3_PI / b3Scalar(2.0);
+ euler_out2.pitch = -B3_PI / b3Scalar(2.0);
+ euler_out.roll = -euler_out.pitch + delta;
+ euler_out2.roll = -euler_out.pitch + delta;
+ }
+ }
+ else
+ {
+ euler_out.pitch = - b3Asin(m_el[2].getX());
+ euler_out2.pitch = B3_PI - euler_out.pitch;
+
+ euler_out.roll = b3Atan2(m_el[2].getY()/b3Cos(euler_out.pitch),
+ m_el[2].getZ()/b3Cos(euler_out.pitch));
+ euler_out2.roll = b3Atan2(m_el[2].getY()/b3Cos(euler_out2.pitch),
+ m_el[2].getZ()/b3Cos(euler_out2.pitch));
+
+ euler_out.yaw = b3Atan2(m_el[1].getX()/b3Cos(euler_out.pitch),
+ m_el[0].getX()/b3Cos(euler_out.pitch));
+ euler_out2.yaw = b3Atan2(m_el[1].getX()/b3Cos(euler_out2.pitch),
+ m_el[0].getX()/b3Cos(euler_out2.pitch));
+ }
+
+ if (solution_number == 1)
+ {
+ yaw = euler_out.yaw;
+ pitch = euler_out.pitch;
+ roll = euler_out.roll;
+ }
+ else
+ {
+ yaw = euler_out2.yaw;
+ pitch = euler_out2.pitch;
+ roll = euler_out2.roll;
+ }
+ }
+
+ /**@brief Create a scaled copy of the matrix
+ * @param s Scaling vector The elements of the vector will scale each column */
+
+ b3Matrix3x3 scaled(const b3Vector3& s) const
+ {
+#if (defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE))|| defined (B3_USE_NEON)
+ return b3Matrix3x3(m_el[0] * s, m_el[1] * s, m_el[2] * s);
+#else
+ return b3Matrix3x3(
+ m_el[0].getX() * s.getX(), m_el[0].getY() * s.getY(), m_el[0].getZ() * s.getZ(),
+ m_el[1].getX() * s.getX(), m_el[1].getY() * s.getY(), m_el[1].getZ() * s.getZ(),
+ m_el[2].getX() * s.getX(), m_el[2].getY() * s.getY(), m_el[2].getZ() * s.getZ());
+#endif
+ }
+
+ /**@brief Return the determinant of the matrix */
+ b3Scalar determinant() const;
+ /**@brief Return the adjoint of the matrix */
+ b3Matrix3x3 adjoint() const;
+ /**@brief Return the matrix with all values non negative */
+ b3Matrix3x3 absolute() const;
+ /**@brief Return the transpose of the matrix */
+ b3Matrix3x3 transpose() const;
+ /**@brief Return the inverse of the matrix */
+ b3Matrix3x3 inverse() const;
+
+ b3Matrix3x3 transposeTimes(const b3Matrix3x3& m) const;
+ b3Matrix3x3 timesTranspose(const b3Matrix3x3& m) const;
+
+ B3_FORCE_INLINE b3Scalar tdotx(const b3Vector3& v) const
+ {
+ return m_el[0].getX() * v.getX() + m_el[1].getX() * v.getY() + m_el[2].getX() * v.getZ();
+ }
+ B3_FORCE_INLINE b3Scalar tdoty(const b3Vector3& v) const
+ {
+ return m_el[0].getY() * v.getX() + m_el[1].getY() * v.getY() + m_el[2].getY() * v.getZ();
+ }
+ B3_FORCE_INLINE b3Scalar tdotz(const b3Vector3& v) const
+ {
+ return m_el[0].getZ() * v.getX() + m_el[1].getZ() * v.getY() + m_el[2].getZ() * v.getZ();
+ }
+
+
+ /**@brief diagonalizes this matrix by the Jacobi method.
+ * @param rot stores the rotation from the coordinate system in which the matrix is diagonal to the original
+ * coordinate system, i.e., old_this = rot * new_this * rot^T.
+ * @param threshold See iteration
+ * @param iteration The iteration stops when all off-diagonal elements are less than the threshold multiplied
+ * by the sum of the absolute values of the diagonal, or when maxSteps have been executed.
+ *
+ * Note that this matrix is assumed to be symmetric.
+ */
+ void diagonalize(b3Matrix3x3& rot, b3Scalar threshold, int maxSteps)
+ {
+ rot.setIdentity();
+ for (int step = maxSteps; step > 0; step--)
+ {
+ // find off-diagonal element [p][q] with largest magnitude
+ int p = 0;
+ int q = 1;
+ int r = 2;
+ b3Scalar max = b3Fabs(m_el[0][1]);
+ b3Scalar v = b3Fabs(m_el[0][2]);
+ if (v > max)
+ {
+ q = 2;
+ r = 1;
+ max = v;
+ }
+ v = b3Fabs(m_el[1][2]);
+ if (v > max)
+ {
+ p = 1;
+ q = 2;
+ r = 0;
+ max = v;
+ }
+
+ b3Scalar t = threshold * (b3Fabs(m_el[0][0]) + b3Fabs(m_el[1][1]) + b3Fabs(m_el[2][2]));
+ if (max <= t)
+ {
+ if (max <= B3_EPSILON * t)
+ {
+ return;
+ }
+ step = 1;
+ }
+
+ // compute Jacobi rotation J which leads to a zero for element [p][q]
+ b3Scalar mpq = m_el[p][q];
+ b3Scalar theta = (m_el[q][q] - m_el[p][p]) / (2 * mpq);
+ b3Scalar theta2 = theta * theta;
+ b3Scalar cos;
+ b3Scalar sin;
+ if (theta2 * theta2 < b3Scalar(10 / B3_EPSILON))
+ {
+ t = (theta >= 0) ? 1 / (theta + b3Sqrt(1 + theta2))
+ : 1 / (theta - b3Sqrt(1 + theta2));
+ cos = 1 / b3Sqrt(1 + t * t);
+ sin = cos * t;
+ }
+ else
+ {
+ // approximation for large theta-value, i.e., a nearly diagonal matrix
+ t = 1 / (theta * (2 + b3Scalar(0.5) / theta2));
+ cos = 1 - b3Scalar(0.5) * t * t;
+ sin = cos * t;
+ }
+
+ // apply rotation to matrix (this = J^T * this * J)
+ m_el[p][q] = m_el[q][p] = 0;
+ m_el[p][p] -= t * mpq;
+ m_el[q][q] += t * mpq;
+ b3Scalar mrp = m_el[r][p];
+ b3Scalar mrq = m_el[r][q];
+ m_el[r][p] = m_el[p][r] = cos * mrp - sin * mrq;
+ m_el[r][q] = m_el[q][r] = cos * mrq + sin * mrp;
+
+ // apply rotation to rot (rot = rot * J)
+ for (int i = 0; i < 3; i++)
+ {
+ b3Vector3& row = rot[i];
+ mrp = row[p];
+ mrq = row[q];
+ row[p] = cos * mrp - sin * mrq;
+ row[q] = cos * mrq + sin * mrp;
+ }
+ }
+ }
+
+
+
+
+ /**@brief Calculate the matrix cofactor
+ * @param r1 The first row to use for calculating the cofactor
+ * @param c1 The first column to use for calculating the cofactor
+ * @param r1 The second row to use for calculating the cofactor
+ * @param c1 The second column to use for calculating the cofactor
+ * See http://en.wikipedia.org/wiki/Cofactor_(linear_algebra) for more details
+ */
+ b3Scalar cofac(int r1, int c1, int r2, int c2) const
+ {
+ return m_el[r1][c1] * m_el[r2][c2] - m_el[r1][c2] * m_el[r2][c1];
+ }
+
+ void serialize(struct b3Matrix3x3Data& dataOut) const;
+
+ void serializeFloat(struct b3Matrix3x3FloatData& dataOut) const;
+
+ void deSerialize(const struct b3Matrix3x3Data& dataIn);
+
+ void deSerializeFloat(const struct b3Matrix3x3FloatData& dataIn);
+
+ void deSerializeDouble(const struct b3Matrix3x3DoubleData& dataIn);
+
+};
+
+
+B3_FORCE_INLINE b3Matrix3x3&
+b3Matrix3x3::operator*=(const b3Matrix3x3& m)
+{
+#if defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+ __m128 rv00, rv01, rv02;
+ __m128 rv10, rv11, rv12;
+ __m128 rv20, rv21, rv22;
+ __m128 mv0, mv1, mv2;
+
+ rv02 = m_el[0].mVec128;
+ rv12 = m_el[1].mVec128;
+ rv22 = m_el[2].mVec128;
+
+ mv0 = _mm_and_ps(m[0].mVec128, b3vFFF0fMask);
+ mv1 = _mm_and_ps(m[1].mVec128, b3vFFF0fMask);
+ mv2 = _mm_and_ps(m[2].mVec128, b3vFFF0fMask);
+
+ // rv0
+ rv00 = b3_splat_ps(rv02, 0);
+ rv01 = b3_splat_ps(rv02, 1);
+ rv02 = b3_splat_ps(rv02, 2);
+
+ rv00 = _mm_mul_ps(rv00, mv0);
+ rv01 = _mm_mul_ps(rv01, mv1);
+ rv02 = _mm_mul_ps(rv02, mv2);
+
+ // rv1
+ rv10 = b3_splat_ps(rv12, 0);
+ rv11 = b3_splat_ps(rv12, 1);
+ rv12 = b3_splat_ps(rv12, 2);
+
+ rv10 = _mm_mul_ps(rv10, mv0);
+ rv11 = _mm_mul_ps(rv11, mv1);
+ rv12 = _mm_mul_ps(rv12, mv2);
+
+ // rv2
+ rv20 = b3_splat_ps(rv22, 0);
+ rv21 = b3_splat_ps(rv22, 1);
+ rv22 = b3_splat_ps(rv22, 2);
+
+ rv20 = _mm_mul_ps(rv20, mv0);
+ rv21 = _mm_mul_ps(rv21, mv1);
+ rv22 = _mm_mul_ps(rv22, mv2);
+
+ rv00 = _mm_add_ps(rv00, rv01);
+ rv10 = _mm_add_ps(rv10, rv11);
+ rv20 = _mm_add_ps(rv20, rv21);
+
+ m_el[0].mVec128 = _mm_add_ps(rv00, rv02);
+ m_el[1].mVec128 = _mm_add_ps(rv10, rv12);
+ m_el[2].mVec128 = _mm_add_ps(rv20, rv22);
+
+#elif defined(B3_USE_NEON)
+
+ float32x4_t rv0, rv1, rv2;
+ float32x4_t v0, v1, v2;
+ float32x4_t mv0, mv1, mv2;
+
+ v0 = m_el[0].mVec128;
+ v1 = m_el[1].mVec128;
+ v2 = m_el[2].mVec128;
+
+ mv0 = (float32x4_t) vandq_s32((int32x4_t)m[0].mVec128, b3vFFF0Mask);
+ mv1 = (float32x4_t) vandq_s32((int32x4_t)m[1].mVec128, b3vFFF0Mask);
+ mv2 = (float32x4_t) vandq_s32((int32x4_t)m[2].mVec128, b3vFFF0Mask);
+
+ rv0 = vmulq_lane_f32(mv0, vget_low_f32(v0), 0);
+ rv1 = vmulq_lane_f32(mv0, vget_low_f32(v1), 0);
+ rv2 = vmulq_lane_f32(mv0, vget_low_f32(v2), 0);
+
+ rv0 = vmlaq_lane_f32(rv0, mv1, vget_low_f32(v0), 1);
+ rv1 = vmlaq_lane_f32(rv1, mv1, vget_low_f32(v1), 1);
+ rv2 = vmlaq_lane_f32(rv2, mv1, vget_low_f32(v2), 1);
+
+ rv0 = vmlaq_lane_f32(rv0, mv2, vget_high_f32(v0), 0);
+ rv1 = vmlaq_lane_f32(rv1, mv2, vget_high_f32(v1), 0);
+ rv2 = vmlaq_lane_f32(rv2, mv2, vget_high_f32(v2), 0);
+
+ m_el[0].mVec128 = rv0;
+ m_el[1].mVec128 = rv1;
+ m_el[2].mVec128 = rv2;
+#else
+ setValue(
+ m.tdotx(m_el[0]), m.tdoty(m_el[0]), m.tdotz(m_el[0]),
+ m.tdotx(m_el[1]), m.tdoty(m_el[1]), m.tdotz(m_el[1]),
+ m.tdotx(m_el[2]), m.tdoty(m_el[2]), m.tdotz(m_el[2]));
+#endif
+ return *this;
+}
+
+B3_FORCE_INLINE b3Matrix3x3&
+b3Matrix3x3::operator+=(const b3Matrix3x3& m)
+{
+#if (defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE))|| defined (B3_USE_NEON)
+ m_el[0].mVec128 = m_el[0].mVec128 + m.m_el[0].mVec128;
+ m_el[1].mVec128 = m_el[1].mVec128 + m.m_el[1].mVec128;
+ m_el[2].mVec128 = m_el[2].mVec128 + m.m_el[2].mVec128;
+#else
+ setValue(
+ m_el[0][0]+m.m_el[0][0],
+ m_el[0][1]+m.m_el[0][1],
+ m_el[0][2]+m.m_el[0][2],
+ m_el[1][0]+m.m_el[1][0],
+ m_el[1][1]+m.m_el[1][1],
+ m_el[1][2]+m.m_el[1][2],
+ m_el[2][0]+m.m_el[2][0],
+ m_el[2][1]+m.m_el[2][1],
+ m_el[2][2]+m.m_el[2][2]);
+#endif
+ return *this;
+}
+
+B3_FORCE_INLINE b3Matrix3x3
+operator*(const b3Matrix3x3& m, const b3Scalar & k)
+{
+#if (defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE))
+ __m128 vk = b3_splat_ps(_mm_load_ss((float *)&k), 0x80);
+ return b3Matrix3x3(
+ _mm_mul_ps(m[0].mVec128, vk),
+ _mm_mul_ps(m[1].mVec128, vk),
+ _mm_mul_ps(m[2].mVec128, vk));
+#elif defined(B3_USE_NEON)
+ return b3Matrix3x3(
+ vmulq_n_f32(m[0].mVec128, k),
+ vmulq_n_f32(m[1].mVec128, k),
+ vmulq_n_f32(m[2].mVec128, k));
+#else
+ return b3Matrix3x3(
+ m[0].getX()*k,m[0].getY()*k,m[0].getZ()*k,
+ m[1].getX()*k,m[1].getY()*k,m[1].getZ()*k,
+ m[2].getX()*k,m[2].getY()*k,m[2].getZ()*k);
+#endif
+}
+
+B3_FORCE_INLINE b3Matrix3x3
+operator+(const b3Matrix3x3& m1, const b3Matrix3x3& m2)
+{
+#if (defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE))|| defined (B3_USE_NEON)
+ return b3Matrix3x3(
+ m1[0].mVec128 + m2[0].mVec128,
+ m1[1].mVec128 + m2[1].mVec128,
+ m1[2].mVec128 + m2[2].mVec128);
+#else
+ return b3Matrix3x3(
+ m1[0][0]+m2[0][0],
+ m1[0][1]+m2[0][1],
+ m1[0][2]+m2[0][2],
+
+ m1[1][0]+m2[1][0],
+ m1[1][1]+m2[1][1],
+ m1[1][2]+m2[1][2],
+
+ m1[2][0]+m2[2][0],
+ m1[2][1]+m2[2][1],
+ m1[2][2]+m2[2][2]);
+#endif
+}
+
+B3_FORCE_INLINE b3Matrix3x3
+operator-(const b3Matrix3x3& m1, const b3Matrix3x3& m2)
+{
+#if (defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE))|| defined (B3_USE_NEON)
+ return b3Matrix3x3(
+ m1[0].mVec128 - m2[0].mVec128,
+ m1[1].mVec128 - m2[1].mVec128,
+ m1[2].mVec128 - m2[2].mVec128);
+#else
+ return b3Matrix3x3(
+ m1[0][0]-m2[0][0],
+ m1[0][1]-m2[0][1],
+ m1[0][2]-m2[0][2],
+
+ m1[1][0]-m2[1][0],
+ m1[1][1]-m2[1][1],
+ m1[1][2]-m2[1][2],
+
+ m1[2][0]-m2[2][0],
+ m1[2][1]-m2[2][1],
+ m1[2][2]-m2[2][2]);
+#endif
+}
+
+
+B3_FORCE_INLINE b3Matrix3x3&
+b3Matrix3x3::operator-=(const b3Matrix3x3& m)
+{
+#if (defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE))|| defined (B3_USE_NEON)
+ m_el[0].mVec128 = m_el[0].mVec128 - m.m_el[0].mVec128;
+ m_el[1].mVec128 = m_el[1].mVec128 - m.m_el[1].mVec128;
+ m_el[2].mVec128 = m_el[2].mVec128 - m.m_el[2].mVec128;
+#else
+ setValue(
+ m_el[0][0]-m.m_el[0][0],
+ m_el[0][1]-m.m_el[0][1],
+ m_el[0][2]-m.m_el[0][2],
+ m_el[1][0]-m.m_el[1][0],
+ m_el[1][1]-m.m_el[1][1],
+ m_el[1][2]-m.m_el[1][2],
+ m_el[2][0]-m.m_el[2][0],
+ m_el[2][1]-m.m_el[2][1],
+ m_el[2][2]-m.m_el[2][2]);
+#endif
+ return *this;
+}
+
+
+B3_FORCE_INLINE b3Scalar
+b3Matrix3x3::determinant() const
+{
+ return b3Triple((*this)[0], (*this)[1], (*this)[2]);
+}
+
+
+B3_FORCE_INLINE b3Matrix3x3
+b3Matrix3x3::absolute() const
+{
+#if (defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE))
+ return b3Matrix3x3(
+ _mm_and_ps(m_el[0].mVec128, b3vAbsfMask),
+ _mm_and_ps(m_el[1].mVec128, b3vAbsfMask),
+ _mm_and_ps(m_el[2].mVec128, b3vAbsfMask));
+#elif defined(B3_USE_NEON)
+ return b3Matrix3x3(
+ (float32x4_t)vandq_s32((int32x4_t)m_el[0].mVec128, b3v3AbsMask),
+ (float32x4_t)vandq_s32((int32x4_t)m_el[1].mVec128, b3v3AbsMask),
+ (float32x4_t)vandq_s32((int32x4_t)m_el[2].mVec128, b3v3AbsMask));
+#else
+ return b3Matrix3x3(
+ b3Fabs(m_el[0].getX()), b3Fabs(m_el[0].getY()), b3Fabs(m_el[0].getZ()),
+ b3Fabs(m_el[1].getX()), b3Fabs(m_el[1].getY()), b3Fabs(m_el[1].getZ()),
+ b3Fabs(m_el[2].getX()), b3Fabs(m_el[2].getY()), b3Fabs(m_el[2].getZ()));
+#endif
+}
+
+B3_FORCE_INLINE b3Matrix3x3
+b3Matrix3x3::transpose() const
+{
+#if (defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE))
+ __m128 v0 = m_el[0].mVec128;
+ __m128 v1 = m_el[1].mVec128;
+ __m128 v2 = m_el[2].mVec128; // x2 y2 z2 w2
+ __m128 vT;
+
+ v2 = _mm_and_ps(v2, b3vFFF0fMask); // x2 y2 z2 0
+
+ vT = _mm_unpackhi_ps(v0, v1); // z0 z1 * *
+ v0 = _mm_unpacklo_ps(v0, v1); // x0 x1 y0 y1
+
+ v1 = _mm_shuffle_ps(v0, v2, B3_SHUFFLE(2, 3, 1, 3) ); // y0 y1 y2 0
+ v0 = _mm_shuffle_ps(v0, v2, B3_SHUFFLE(0, 1, 0, 3) ); // x0 x1 x2 0
+ v2 = b3CastdTo128f(_mm_move_sd(b3CastfTo128d(v2), b3CastfTo128d(vT))); // z0 z1 z2 0
+
+
+ return b3Matrix3x3( v0, v1, v2 );
+#elif defined(B3_USE_NEON)
+ // note: zeros the w channel. We can preserve it at the cost of two more vtrn instructions.
+ static const uint32x2_t zMask = (const uint32x2_t) {-1, 0 };
+ float32x4x2_t top = vtrnq_f32( m_el[0].mVec128, m_el[1].mVec128 ); // {x0 x1 z0 z1}, {y0 y1 w0 w1}
+ float32x2x2_t bl = vtrn_f32( vget_low_f32(m_el[2].mVec128), vdup_n_f32(0.0f) ); // {x2 0 }, {y2 0}
+ float32x4_t v0 = vcombine_f32( vget_low_f32(top.val[0]), bl.val[0] );
+ float32x4_t v1 = vcombine_f32( vget_low_f32(top.val[1]), bl.val[1] );
+ float32x2_t q = (float32x2_t) vand_u32( (uint32x2_t) vget_high_f32( m_el[2].mVec128), zMask );
+ float32x4_t v2 = vcombine_f32( vget_high_f32(top.val[0]), q ); // z0 z1 z2 0
+ return b3Matrix3x3( v0, v1, v2 );
+#else
+ return b3Matrix3x3( m_el[0].getX(), m_el[1].getX(), m_el[2].getX(),
+ m_el[0].getY(), m_el[1].getY(), m_el[2].getY(),
+ m_el[0].getZ(), m_el[1].getZ(), m_el[2].getZ());
+#endif
+}
+
+B3_FORCE_INLINE b3Matrix3x3
+b3Matrix3x3::adjoint() const
+{
+ return b3Matrix3x3(cofac(1, 1, 2, 2), cofac(0, 2, 2, 1), cofac(0, 1, 1, 2),
+ cofac(1, 2, 2, 0), cofac(0, 0, 2, 2), cofac(0, 2, 1, 0),
+ cofac(1, 0, 2, 1), cofac(0, 1, 2, 0), cofac(0, 0, 1, 1));
+}
+
+B3_FORCE_INLINE b3Matrix3x3
+b3Matrix3x3::inverse() const
+{
+ b3Vector3 co = b3MakeVector3(cofac(1, 1, 2, 2), cofac(1, 2, 2, 0), cofac(1, 0, 2, 1));
+ b3Scalar det = (*this)[0].dot(co);
+ b3FullAssert(det != b3Scalar(0.0));
+ b3Scalar s = b3Scalar(1.0) / det;
+ return b3Matrix3x3(co.getX() * s, cofac(0, 2, 2, 1) * s, cofac(0, 1, 1, 2) * s,
+ co.getY() * s, cofac(0, 0, 2, 2) * s, cofac(0, 2, 1, 0) * s,
+ co.getZ() * s, cofac(0, 1, 2, 0) * s, cofac(0, 0, 1, 1) * s);
+}
+
+B3_FORCE_INLINE b3Matrix3x3
+b3Matrix3x3::transposeTimes(const b3Matrix3x3& m) const
+{
+#if (defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE))
+ // zeros w
+// static const __m128i xyzMask = (const __m128i){ -1ULL, 0xffffffffULL };
+ __m128 row = m_el[0].mVec128;
+ __m128 m0 = _mm_and_ps( m.getRow(0).mVec128, b3vFFF0fMask );
+ __m128 m1 = _mm_and_ps( m.getRow(1).mVec128, b3vFFF0fMask);
+ __m128 m2 = _mm_and_ps( m.getRow(2).mVec128, b3vFFF0fMask );
+ __m128 r0 = _mm_mul_ps(m0, _mm_shuffle_ps(row, row, 0));
+ __m128 r1 = _mm_mul_ps(m0, _mm_shuffle_ps(row, row, 0x55));
+ __m128 r2 = _mm_mul_ps(m0, _mm_shuffle_ps(row, row, 0xaa));
+ row = m_el[1].mVec128;
+ r0 = _mm_add_ps( r0, _mm_mul_ps(m1, _mm_shuffle_ps(row, row, 0)));
+ r1 = _mm_add_ps( r1, _mm_mul_ps(m1, _mm_shuffle_ps(row, row, 0x55)));
+ r2 = _mm_add_ps( r2, _mm_mul_ps(m1, _mm_shuffle_ps(row, row, 0xaa)));
+ row = m_el[2].mVec128;
+ r0 = _mm_add_ps( r0, _mm_mul_ps(m2, _mm_shuffle_ps(row, row, 0)));
+ r1 = _mm_add_ps( r1, _mm_mul_ps(m2, _mm_shuffle_ps(row, row, 0x55)));
+ r2 = _mm_add_ps( r2, _mm_mul_ps(m2, _mm_shuffle_ps(row, row, 0xaa)));
+ return b3Matrix3x3( r0, r1, r2 );
+
+#elif defined B3_USE_NEON
+ // zeros w
+ static const uint32x4_t xyzMask = (const uint32x4_t){ -1, -1, -1, 0 };
+ float32x4_t m0 = (float32x4_t) vandq_u32( (uint32x4_t) m.getRow(0).mVec128, xyzMask );
+ float32x4_t m1 = (float32x4_t) vandq_u32( (uint32x4_t) m.getRow(1).mVec128, xyzMask );
+ float32x4_t m2 = (float32x4_t) vandq_u32( (uint32x4_t) m.getRow(2).mVec128, xyzMask );
+ float32x4_t row = m_el[0].mVec128;
+ float32x4_t r0 = vmulq_lane_f32( m0, vget_low_f32(row), 0);
+ float32x4_t r1 = vmulq_lane_f32( m0, vget_low_f32(row), 1);
+ float32x4_t r2 = vmulq_lane_f32( m0, vget_high_f32(row), 0);
+ row = m_el[1].mVec128;
+ r0 = vmlaq_lane_f32( r0, m1, vget_low_f32(row), 0);
+ r1 = vmlaq_lane_f32( r1, m1, vget_low_f32(row), 1);
+ r2 = vmlaq_lane_f32( r2, m1, vget_high_f32(row), 0);
+ row = m_el[2].mVec128;
+ r0 = vmlaq_lane_f32( r0, m2, vget_low_f32(row), 0);
+ r1 = vmlaq_lane_f32( r1, m2, vget_low_f32(row), 1);
+ r2 = vmlaq_lane_f32( r2, m2, vget_high_f32(row), 0);
+ return b3Matrix3x3( r0, r1, r2 );
+#else
+ return b3Matrix3x3(
+ m_el[0].getX() * m[0].getX() + m_el[1].getX() * m[1].getX() + m_el[2].getX() * m[2].getX(),
+ m_el[0].getX() * m[0].getY() + m_el[1].getX() * m[1].getY() + m_el[2].getX() * m[2].getY(),
+ m_el[0].getX() * m[0].getZ() + m_el[1].getX() * m[1].getZ() + m_el[2].getX() * m[2].getZ(),
+ m_el[0].getY() * m[0].getX() + m_el[1].getY() * m[1].getX() + m_el[2].getY() * m[2].getX(),
+ m_el[0].getY() * m[0].getY() + m_el[1].getY() * m[1].getY() + m_el[2].getY() * m[2].getY(),
+ m_el[0].getY() * m[0].getZ() + m_el[1].getY() * m[1].getZ() + m_el[2].getY() * m[2].getZ(),
+ m_el[0].getZ() * m[0].getX() + m_el[1].getZ() * m[1].getX() + m_el[2].getZ() * m[2].getX(),
+ m_el[0].getZ() * m[0].getY() + m_el[1].getZ() * m[1].getY() + m_el[2].getZ() * m[2].getY(),
+ m_el[0].getZ() * m[0].getZ() + m_el[1].getZ() * m[1].getZ() + m_el[2].getZ() * m[2].getZ());
+#endif
+}
+
+B3_FORCE_INLINE b3Matrix3x3
+b3Matrix3x3::timesTranspose(const b3Matrix3x3& m) const
+{
+#if (defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE))
+ __m128 a0 = m_el[0].mVec128;
+ __m128 a1 = m_el[1].mVec128;
+ __m128 a2 = m_el[2].mVec128;
+
+ b3Matrix3x3 mT = m.transpose(); // we rely on transpose() zeroing w channel so that we don't have to do it here
+ __m128 mx = mT[0].mVec128;
+ __m128 my = mT[1].mVec128;
+ __m128 mz = mT[2].mVec128;
+
+ __m128 r0 = _mm_mul_ps(mx, _mm_shuffle_ps(a0, a0, 0x00));
+ __m128 r1 = _mm_mul_ps(mx, _mm_shuffle_ps(a1, a1, 0x00));
+ __m128 r2 = _mm_mul_ps(mx, _mm_shuffle_ps(a2, a2, 0x00));
+ r0 = _mm_add_ps(r0, _mm_mul_ps(my, _mm_shuffle_ps(a0, a0, 0x55)));
+ r1 = _mm_add_ps(r1, _mm_mul_ps(my, _mm_shuffle_ps(a1, a1, 0x55)));
+ r2 = _mm_add_ps(r2, _mm_mul_ps(my, _mm_shuffle_ps(a2, a2, 0x55)));
+ r0 = _mm_add_ps(r0, _mm_mul_ps(mz, _mm_shuffle_ps(a0, a0, 0xaa)));
+ r1 = _mm_add_ps(r1, _mm_mul_ps(mz, _mm_shuffle_ps(a1, a1, 0xaa)));
+ r2 = _mm_add_ps(r2, _mm_mul_ps(mz, _mm_shuffle_ps(a2, a2, 0xaa)));
+ return b3Matrix3x3( r0, r1, r2);
+
+#elif defined B3_USE_NEON
+ float32x4_t a0 = m_el[0].mVec128;
+ float32x4_t a1 = m_el[1].mVec128;
+ float32x4_t a2 = m_el[2].mVec128;
+
+ b3Matrix3x3 mT = m.transpose(); // we rely on transpose() zeroing w channel so that we don't have to do it here
+ float32x4_t mx = mT[0].mVec128;
+ float32x4_t my = mT[1].mVec128;
+ float32x4_t mz = mT[2].mVec128;
+
+ float32x4_t r0 = vmulq_lane_f32( mx, vget_low_f32(a0), 0);
+ float32x4_t r1 = vmulq_lane_f32( mx, vget_low_f32(a1), 0);
+ float32x4_t r2 = vmulq_lane_f32( mx, vget_low_f32(a2), 0);
+ r0 = vmlaq_lane_f32( r0, my, vget_low_f32(a0), 1);
+ r1 = vmlaq_lane_f32( r1, my, vget_low_f32(a1), 1);
+ r2 = vmlaq_lane_f32( r2, my, vget_low_f32(a2), 1);
+ r0 = vmlaq_lane_f32( r0, mz, vget_high_f32(a0), 0);
+ r1 = vmlaq_lane_f32( r1, mz, vget_high_f32(a1), 0);
+ r2 = vmlaq_lane_f32( r2, mz, vget_high_f32(a2), 0);
+ return b3Matrix3x3( r0, r1, r2 );
+
+#else
+ return b3Matrix3x3(
+ m_el[0].dot(m[0]), m_el[0].dot(m[1]), m_el[0].dot(m[2]),
+ m_el[1].dot(m[0]), m_el[1].dot(m[1]), m_el[1].dot(m[2]),
+ m_el[2].dot(m[0]), m_el[2].dot(m[1]), m_el[2].dot(m[2]));
+#endif
+}
+
+B3_FORCE_INLINE b3Vector3
+operator*(const b3Matrix3x3& m, const b3Vector3& v)
+{
+#if (defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE))|| defined (B3_USE_NEON)
+ return v.dot3(m[0], m[1], m[2]);
+#else
+ return b3MakeVector3(m[0].dot(v), m[1].dot(v), m[2].dot(v));
+#endif
+}
+
+
+B3_FORCE_INLINE b3Vector3
+operator*(const b3Vector3& v, const b3Matrix3x3& m)
+{
+#if (defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE))
+
+ const __m128 vv = v.mVec128;
+
+ __m128 c0 = b3_splat_ps( vv, 0);
+ __m128 c1 = b3_splat_ps( vv, 1);
+ __m128 c2 = b3_splat_ps( vv, 2);
+
+ c0 = _mm_mul_ps(c0, _mm_and_ps(m[0].mVec128, b3vFFF0fMask) );
+ c1 = _mm_mul_ps(c1, _mm_and_ps(m[1].mVec128, b3vFFF0fMask) );
+ c0 = _mm_add_ps(c0, c1);
+ c2 = _mm_mul_ps(c2, _mm_and_ps(m[2].mVec128, b3vFFF0fMask) );
+
+ return b3MakeVector3(_mm_add_ps(c0, c2));
+#elif defined(B3_USE_NEON)
+ const float32x4_t vv = v.mVec128;
+ const float32x2_t vlo = vget_low_f32(vv);
+ const float32x2_t vhi = vget_high_f32(vv);
+
+ float32x4_t c0, c1, c2;
+
+ c0 = (float32x4_t) vandq_s32((int32x4_t)m[0].mVec128, b3vFFF0Mask);
+ c1 = (float32x4_t) vandq_s32((int32x4_t)m[1].mVec128, b3vFFF0Mask);
+ c2 = (float32x4_t) vandq_s32((int32x4_t)m[2].mVec128, b3vFFF0Mask);
+
+ c0 = vmulq_lane_f32(c0, vlo, 0);
+ c1 = vmulq_lane_f32(c1, vlo, 1);
+ c2 = vmulq_lane_f32(c2, vhi, 0);
+ c0 = vaddq_f32(c0, c1);
+ c0 = vaddq_f32(c0, c2);
+
+ return b3MakeVector3(c0);
+#else
+ return b3MakeVector3(m.tdotx(v), m.tdoty(v), m.tdotz(v));
+#endif
+}
+
+B3_FORCE_INLINE b3Matrix3x3
+operator*(const b3Matrix3x3& m1, const b3Matrix3x3& m2)
+{
+#if (defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE))
+
+ __m128 m10 = m1[0].mVec128;
+ __m128 m11 = m1[1].mVec128;
+ __m128 m12 = m1[2].mVec128;
+
+ __m128 m2v = _mm_and_ps(m2[0].mVec128, b3vFFF0fMask);
+
+ __m128 c0 = b3_splat_ps( m10, 0);
+ __m128 c1 = b3_splat_ps( m11, 0);
+ __m128 c2 = b3_splat_ps( m12, 0);
+
+ c0 = _mm_mul_ps(c0, m2v);
+ c1 = _mm_mul_ps(c1, m2v);
+ c2 = _mm_mul_ps(c2, m2v);
+
+ m2v = _mm_and_ps(m2[1].mVec128, b3vFFF0fMask);
+
+ __m128 c0_1 = b3_splat_ps( m10, 1);
+ __m128 c1_1 = b3_splat_ps( m11, 1);
+ __m128 c2_1 = b3_splat_ps( m12, 1);
+
+ c0_1 = _mm_mul_ps(c0_1, m2v);
+ c1_1 = _mm_mul_ps(c1_1, m2v);
+ c2_1 = _mm_mul_ps(c2_1, m2v);
+
+ m2v = _mm_and_ps(m2[2].mVec128, b3vFFF0fMask);
+
+ c0 = _mm_add_ps(c0, c0_1);
+ c1 = _mm_add_ps(c1, c1_1);
+ c2 = _mm_add_ps(c2, c2_1);
+
+ m10 = b3_splat_ps( m10, 2);
+ m11 = b3_splat_ps( m11, 2);
+ m12 = b3_splat_ps( m12, 2);
+
+ m10 = _mm_mul_ps(m10, m2v);
+ m11 = _mm_mul_ps(m11, m2v);
+ m12 = _mm_mul_ps(m12, m2v);
+
+ c0 = _mm_add_ps(c0, m10);
+ c1 = _mm_add_ps(c1, m11);
+ c2 = _mm_add_ps(c2, m12);
+
+ return b3Matrix3x3(c0, c1, c2);
+
+#elif defined(B3_USE_NEON)
+
+ float32x4_t rv0, rv1, rv2;
+ float32x4_t v0, v1, v2;
+ float32x4_t mv0, mv1, mv2;
+
+ v0 = m1[0].mVec128;
+ v1 = m1[1].mVec128;
+ v2 = m1[2].mVec128;
+
+ mv0 = (float32x4_t) vandq_s32((int32x4_t)m2[0].mVec128, b3vFFF0Mask);
+ mv1 = (float32x4_t) vandq_s32((int32x4_t)m2[1].mVec128, b3vFFF0Mask);
+ mv2 = (float32x4_t) vandq_s32((int32x4_t)m2[2].mVec128, b3vFFF0Mask);
+
+ rv0 = vmulq_lane_f32(mv0, vget_low_f32(v0), 0);
+ rv1 = vmulq_lane_f32(mv0, vget_low_f32(v1), 0);
+ rv2 = vmulq_lane_f32(mv0, vget_low_f32(v2), 0);
+
+ rv0 = vmlaq_lane_f32(rv0, mv1, vget_low_f32(v0), 1);
+ rv1 = vmlaq_lane_f32(rv1, mv1, vget_low_f32(v1), 1);
+ rv2 = vmlaq_lane_f32(rv2, mv1, vget_low_f32(v2), 1);
+
+ rv0 = vmlaq_lane_f32(rv0, mv2, vget_high_f32(v0), 0);
+ rv1 = vmlaq_lane_f32(rv1, mv2, vget_high_f32(v1), 0);
+ rv2 = vmlaq_lane_f32(rv2, mv2, vget_high_f32(v2), 0);
+
+ return b3Matrix3x3(rv0, rv1, rv2);
+
+#else
+ return b3Matrix3x3(
+ m2.tdotx( m1[0]), m2.tdoty( m1[0]), m2.tdotz( m1[0]),
+ m2.tdotx( m1[1]), m2.tdoty( m1[1]), m2.tdotz( m1[1]),
+ m2.tdotx( m1[2]), m2.tdoty( m1[2]), m2.tdotz( m1[2]));
+#endif
+}
+
+/*
+B3_FORCE_INLINE b3Matrix3x3 b3MultTransposeLeft(const b3Matrix3x3& m1, const b3Matrix3x3& m2) {
+return b3Matrix3x3(
+m1[0][0] * m2[0][0] + m1[1][0] * m2[1][0] + m1[2][0] * m2[2][0],
+m1[0][0] * m2[0][1] + m1[1][0] * m2[1][1] + m1[2][0] * m2[2][1],
+m1[0][0] * m2[0][2] + m1[1][0] * m2[1][2] + m1[2][0] * m2[2][2],
+m1[0][1] * m2[0][0] + m1[1][1] * m2[1][0] + m1[2][1] * m2[2][0],
+m1[0][1] * m2[0][1] + m1[1][1] * m2[1][1] + m1[2][1] * m2[2][1],
+m1[0][1] * m2[0][2] + m1[1][1] * m2[1][2] + m1[2][1] * m2[2][2],
+m1[0][2] * m2[0][0] + m1[1][2] * m2[1][0] + m1[2][2] * m2[2][0],
+m1[0][2] * m2[0][1] + m1[1][2] * m2[1][1] + m1[2][2] * m2[2][1],
+m1[0][2] * m2[0][2] + m1[1][2] * m2[1][2] + m1[2][2] * m2[2][2]);
+}
+*/
+
+/**@brief Equality operator between two matrices
+* It will test all elements are equal. */
+B3_FORCE_INLINE bool operator==(const b3Matrix3x3& m1, const b3Matrix3x3& m2)
+{
+#if (defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE))
+
+ __m128 c0, c1, c2;
+
+ c0 = _mm_cmpeq_ps(m1[0].mVec128, m2[0].mVec128);
+ c1 = _mm_cmpeq_ps(m1[1].mVec128, m2[1].mVec128);
+ c2 = _mm_cmpeq_ps(m1[2].mVec128, m2[2].mVec128);
+
+ c0 = _mm_and_ps(c0, c1);
+ c0 = _mm_and_ps(c0, c2);
+
+ return (0x7 == _mm_movemask_ps((__m128)c0));
+#else
+ return
+ ( m1[0][0] == m2[0][0] && m1[1][0] == m2[1][0] && m1[2][0] == m2[2][0] &&
+ m1[0][1] == m2[0][1] && m1[1][1] == m2[1][1] && m1[2][1] == m2[2][1] &&
+ m1[0][2] == m2[0][2] && m1[1][2] == m2[1][2] && m1[2][2] == m2[2][2] );
+#endif
+}
+
+///for serialization
+struct b3Matrix3x3FloatData
+{
+ b3Vector3FloatData m_el[3];
+};
+
+///for serialization
+struct b3Matrix3x3DoubleData
+{
+ b3Vector3DoubleData m_el[3];
+};
+
+
+
+
+B3_FORCE_INLINE void b3Matrix3x3::serialize(struct b3Matrix3x3Data& dataOut) const
+{
+ for (int i=0;i<3;i++)
+ m_el[i].serialize(dataOut.m_el[i]);
+}
+
+B3_FORCE_INLINE void b3Matrix3x3::serializeFloat(struct b3Matrix3x3FloatData& dataOut) const
+{
+ for (int i=0;i<3;i++)
+ m_el[i].serializeFloat(dataOut.m_el[i]);
+}
+
+
+B3_FORCE_INLINE void b3Matrix3x3::deSerialize(const struct b3Matrix3x3Data& dataIn)
+{
+ for (int i=0;i<3;i++)
+ m_el[i].deSerialize(dataIn.m_el[i]);
+}
+
+B3_FORCE_INLINE void b3Matrix3x3::deSerializeFloat(const struct b3Matrix3x3FloatData& dataIn)
+{
+ for (int i=0;i<3;i++)
+ m_el[i].deSerializeFloat(dataIn.m_el[i]);
+}
+
+B3_FORCE_INLINE void b3Matrix3x3::deSerializeDouble(const struct b3Matrix3x3DoubleData& dataIn)
+{
+ for (int i=0;i<3;i++)
+ m_el[i].deSerializeDouble(dataIn.m_el[i]);
+}
+
+#endif //B3_MATRIX3x3_H
+
diff --git a/thirdparty/bullet/src/Bullet3Common/b3MinMax.h b/thirdparty/bullet/src/Bullet3Common/b3MinMax.h
new file mode 100644
index 0000000000..73af23a4f9
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Common/b3MinMax.h
@@ -0,0 +1,71 @@
+/*
+Copyright (c) 2003-2013 Gino van den Bergen / Erwin Coumans 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 B3_GEN_MINMAX_H
+#define B3_GEN_MINMAX_H
+
+#include "b3Scalar.h"
+
+template <class T>
+B3_FORCE_INLINE const T& b3Min(const T& a, const T& b)
+{
+ return a < b ? a : b ;
+}
+
+template <class T>
+B3_FORCE_INLINE const T& b3Max(const T& a, const T& b)
+{
+ return a > b ? a : b;
+}
+
+template <class T>
+B3_FORCE_INLINE const T& b3Clamped(const T& a, const T& lb, const T& ub)
+{
+ return a < lb ? lb : (ub < a ? ub : a);
+}
+
+template <class T>
+B3_FORCE_INLINE void b3SetMin(T& a, const T& b)
+{
+ if (b < a)
+ {
+ a = b;
+ }
+}
+
+template <class T>
+B3_FORCE_INLINE void b3SetMax(T& a, const T& b)
+{
+ if (a < b)
+ {
+ a = b;
+ }
+}
+
+template <class T>
+B3_FORCE_INLINE void b3Clamp(T& a, const T& lb, const T& ub)
+{
+ if (a < lb)
+ {
+ a = lb;
+ }
+ else if (ub < a)
+ {
+ a = ub;
+ }
+}
+
+#endif //B3_GEN_MINMAX_H
diff --git a/thirdparty/bullet/src/Bullet3Common/b3PoolAllocator.h b/thirdparty/bullet/src/Bullet3Common/b3PoolAllocator.h
new file mode 100644
index 0000000000..2fcdcf5b24
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Common/b3PoolAllocator.h
@@ -0,0 +1,121 @@
+/*
+Copyright (c) 2003-2013 Gino van den Bergen / Erwin Coumans 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_POOL_ALLOCATOR_H
+#define _BT_POOL_ALLOCATOR_H
+
+#include "b3Scalar.h"
+#include "b3AlignedAllocator.h"
+
+///The b3PoolAllocator class allows to efficiently allocate a large pool of objects, instead of dynamically allocating them separately.
+class b3PoolAllocator
+{
+ int m_elemSize;
+ int m_maxElements;
+ int m_freeCount;
+ void* m_firstFree;
+ unsigned char* m_pool;
+
+public:
+
+ b3PoolAllocator(int elemSize, int maxElements)
+ :m_elemSize(elemSize),
+ m_maxElements(maxElements)
+ {
+ m_pool = (unsigned char*) b3AlignedAlloc( static_cast<unsigned int>(m_elemSize*m_maxElements),16);
+
+ unsigned char* p = m_pool;
+ m_firstFree = p;
+ m_freeCount = m_maxElements;
+ int count = m_maxElements;
+ while (--count) {
+ *(void**)p = (p + m_elemSize);
+ p += m_elemSize;
+ }
+ *(void**)p = 0;
+ }
+
+ ~b3PoolAllocator()
+ {
+ b3AlignedFree( m_pool);
+ }
+
+ int getFreeCount() const
+ {
+ return m_freeCount;
+ }
+
+ int getUsedCount() const
+ {
+ return m_maxElements - m_freeCount;
+ }
+
+ int getMaxCount() const
+ {
+ return m_maxElements;
+ }
+
+ void* allocate(int size)
+ {
+ // release mode fix
+ (void)size;
+ b3Assert(!size || size<=m_elemSize);
+ b3Assert(m_freeCount>0);
+ void* result = m_firstFree;
+ m_firstFree = *(void**)m_firstFree;
+ --m_freeCount;
+ return result;
+ }
+
+ bool validPtr(void* ptr)
+ {
+ if (ptr) {
+ if (((unsigned char*)ptr >= m_pool && (unsigned char*)ptr < m_pool + m_maxElements * m_elemSize))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ void freeMemory(void* ptr)
+ {
+ if (ptr) {
+ b3Assert((unsigned char*)ptr >= m_pool && (unsigned char*)ptr < m_pool + m_maxElements * m_elemSize);
+
+ *(void**)ptr = m_firstFree;
+ m_firstFree = ptr;
+ ++m_freeCount;
+ }
+ }
+
+ int getElementSize() const
+ {
+ return m_elemSize;
+ }
+
+ unsigned char* getPoolAddress()
+ {
+ return m_pool;
+ }
+
+ const unsigned char* getPoolAddress() const
+ {
+ return m_pool;
+ }
+
+};
+
+#endif //_BT_POOL_ALLOCATOR_H
diff --git a/thirdparty/bullet/src/Bullet3Common/b3QuadWord.h b/thirdparty/bullet/src/Bullet3Common/b3QuadWord.h
new file mode 100644
index 0000000000..65c9581977
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Common/b3QuadWord.h
@@ -0,0 +1,245 @@
+/*
+Copyright (c) 2003-2013 Gino van den Bergen / Erwin Coumans 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 B3_SIMD_QUADWORD_H
+#define B3_SIMD_QUADWORD_H
+
+#include "b3Scalar.h"
+#include "b3MinMax.h"
+
+
+
+
+
+#if defined (__CELLOS_LV2) && defined (__SPU__)
+#include <altivec.h>
+#endif
+
+/**@brief The b3QuadWord class is base class for b3Vector3 and b3Quaternion.
+ * Some issues under PS3 Linux with IBM 2.1 SDK, gcc compiler prevent from using aligned quadword.
+ */
+#ifndef USE_LIBSPE2
+B3_ATTRIBUTE_ALIGNED16(class) b3QuadWord
+#else
+class b3QuadWord
+#endif
+{
+protected:
+
+#if defined (__SPU__) && defined (__CELLOS_LV2__)
+ union {
+ vec_float4 mVec128;
+ b3Scalar m_floats[4];
+ };
+public:
+ vec_float4 get128() const
+ {
+ return mVec128;
+ }
+
+#else //__CELLOS_LV2__ __SPU__
+
+#if defined(B3_USE_SSE) || defined(B3_USE_NEON)
+public:
+ union {
+ b3SimdFloat4 mVec128;
+ b3Scalar m_floats[4];
+ struct {b3Scalar x,y,z,w;};
+ };
+public:
+ B3_FORCE_INLINE b3SimdFloat4 get128() const
+ {
+ return mVec128;
+ }
+ B3_FORCE_INLINE void set128(b3SimdFloat4 v128)
+ {
+ mVec128 = v128;
+ }
+#else
+public:
+ union
+ {
+ b3Scalar m_floats[4];
+ struct {b3Scalar x,y,z,w;};
+ };
+#endif // B3_USE_SSE
+
+#endif //__CELLOS_LV2__ __SPU__
+
+ public:
+
+#if defined(B3_USE_SSE) || defined(B3_USE_NEON)
+
+ // Set Vector
+ B3_FORCE_INLINE b3QuadWord(const b3SimdFloat4 vec)
+ {
+ mVec128 = vec;
+ }
+
+ // Copy constructor
+ B3_FORCE_INLINE b3QuadWord(const b3QuadWord& rhs)
+ {
+ mVec128 = rhs.mVec128;
+ }
+
+ // Assignment Operator
+ B3_FORCE_INLINE b3QuadWord&
+ operator=(const b3QuadWord& v)
+ {
+ mVec128 = v.mVec128;
+
+ return *this;
+ }
+
+#endif
+
+ /**@brief Return the x value */
+ B3_FORCE_INLINE const b3Scalar& getX() const { return m_floats[0]; }
+ /**@brief Return the y value */
+ B3_FORCE_INLINE const b3Scalar& getY() const { return m_floats[1]; }
+ /**@brief Return the z value */
+ B3_FORCE_INLINE const b3Scalar& getZ() const { return m_floats[2]; }
+ /**@brief Set the x value */
+ B3_FORCE_INLINE void setX(b3Scalar _x) { m_floats[0] = _x;};
+ /**@brief Set the y value */
+ B3_FORCE_INLINE void setY(b3Scalar _y) { m_floats[1] = _y;};
+ /**@brief Set the z value */
+ B3_FORCE_INLINE void setZ(b3Scalar _z) { m_floats[2] = _z;};
+ /**@brief Set the w value */
+ B3_FORCE_INLINE void setW(b3Scalar _w) { m_floats[3] = _w;};
+ /**@brief Return the x value */
+
+
+ //B3_FORCE_INLINE b3Scalar& operator[](int i) { return (&m_floats[0])[i]; }
+ //B3_FORCE_INLINE const b3Scalar& operator[](int i) const { return (&m_floats[0])[i]; }
+ ///operator b3Scalar*() replaces operator[], using implicit conversion. We added operator != and operator == to avoid pointer comparisons.
+ B3_FORCE_INLINE operator b3Scalar *() { return &m_floats[0]; }
+ B3_FORCE_INLINE operator const b3Scalar *() const { return &m_floats[0]; }
+
+ B3_FORCE_INLINE bool operator==(const b3QuadWord& other) const
+ {
+#ifdef B3_USE_SSE
+ return (0xf == _mm_movemask_ps((__m128)_mm_cmpeq_ps(mVec128, other.mVec128)));
+#else
+ return ((m_floats[3]==other.m_floats[3]) &&
+ (m_floats[2]==other.m_floats[2]) &&
+ (m_floats[1]==other.m_floats[1]) &&
+ (m_floats[0]==other.m_floats[0]));
+#endif
+ }
+
+ B3_FORCE_INLINE bool operator!=(const b3QuadWord& other) const
+ {
+ return !(*this == other);
+ }
+
+ /**@brief Set x,y,z and zero w
+ * @param x Value of x
+ * @param y Value of y
+ * @param z Value of z
+ */
+ B3_FORCE_INLINE void setValue(const b3Scalar& _x, const b3Scalar& _y, const b3Scalar& _z)
+ {
+ m_floats[0]=_x;
+ m_floats[1]=_y;
+ m_floats[2]=_z;
+ m_floats[3] = 0.f;
+ }
+
+/* void getValue(b3Scalar *m) const
+ {
+ m[0] = m_floats[0];
+ m[1] = m_floats[1];
+ m[2] = m_floats[2];
+ }
+*/
+/**@brief Set the values
+ * @param x Value of x
+ * @param y Value of y
+ * @param z Value of z
+ * @param w Value of w
+ */
+ B3_FORCE_INLINE void setValue(const b3Scalar& _x, const b3Scalar& _y, const b3Scalar& _z,const b3Scalar& _w)
+ {
+ m_floats[0]=_x;
+ m_floats[1]=_y;
+ m_floats[2]=_z;
+ m_floats[3]=_w;
+ }
+ /**@brief No initialization constructor */
+ B3_FORCE_INLINE b3QuadWord()
+ // :m_floats[0](b3Scalar(0.)),m_floats[1](b3Scalar(0.)),m_floats[2](b3Scalar(0.)),m_floats[3](b3Scalar(0.))
+ {
+ }
+
+ /**@brief Three argument constructor (zeros w)
+ * @param x Value of x
+ * @param y Value of y
+ * @param z Value of z
+ */
+ B3_FORCE_INLINE b3QuadWord(const b3Scalar& _x, const b3Scalar& _y, const b3Scalar& _z)
+ {
+ m_floats[0] = _x, m_floats[1] = _y, m_floats[2] = _z, m_floats[3] = 0.0f;
+ }
+
+/**@brief Initializing constructor
+ * @param x Value of x
+ * @param y Value of y
+ * @param z Value of z
+ * @param w Value of w
+ */
+ B3_FORCE_INLINE b3QuadWord(const b3Scalar& _x, const b3Scalar& _y, const b3Scalar& _z,const b3Scalar& _w)
+ {
+ m_floats[0] = _x, m_floats[1] = _y, m_floats[2] = _z, m_floats[3] = _w;
+ }
+
+ /**@brief Set each element to the max of the current values and the values of another b3QuadWord
+ * @param other The other b3QuadWord to compare with
+ */
+ B3_FORCE_INLINE void setMax(const b3QuadWord& other)
+ {
+ #ifdef B3_USE_SSE
+ mVec128 = _mm_max_ps(mVec128, other.mVec128);
+ #elif defined(B3_USE_NEON)
+ mVec128 = vmaxq_f32(mVec128, other.mVec128);
+ #else
+ b3SetMax(m_floats[0], other.m_floats[0]);
+ b3SetMax(m_floats[1], other.m_floats[1]);
+ b3SetMax(m_floats[2], other.m_floats[2]);
+ b3SetMax(m_floats[3], other.m_floats[3]);
+ #endif
+ }
+ /**@brief Set each element to the min of the current values and the values of another b3QuadWord
+ * @param other The other b3QuadWord to compare with
+ */
+ B3_FORCE_INLINE void setMin(const b3QuadWord& other)
+ {
+ #ifdef B3_USE_SSE
+ mVec128 = _mm_min_ps(mVec128, other.mVec128);
+ #elif defined(B3_USE_NEON)
+ mVec128 = vminq_f32(mVec128, other.mVec128);
+ #else
+ b3SetMin(m_floats[0], other.m_floats[0]);
+ b3SetMin(m_floats[1], other.m_floats[1]);
+ b3SetMin(m_floats[2], other.m_floats[2]);
+ b3SetMin(m_floats[3], other.m_floats[3]);
+ #endif
+ }
+
+
+
+};
+
+#endif //B3_SIMD_QUADWORD_H
diff --git a/thirdparty/bullet/src/Bullet3Common/b3Quaternion.h b/thirdparty/bullet/src/Bullet3Common/b3Quaternion.h
new file mode 100644
index 0000000000..ad20543348
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Common/b3Quaternion.h
@@ -0,0 +1,918 @@
+/*
+Copyright (c) 2003-2013 Gino van den Bergen / Erwin Coumans 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 B3_SIMD__QUATERNION_H_
+#define B3_SIMD__QUATERNION_H_
+
+
+#include "b3Vector3.h"
+#include "b3QuadWord.h"
+
+
+
+
+
+#ifdef B3_USE_SSE
+
+const __m128 B3_ATTRIBUTE_ALIGNED16(b3vOnes) = {1.0f, 1.0f, 1.0f, 1.0f};
+
+#endif
+
+#if defined(B3_USE_SSE) || defined(B3_USE_NEON)
+
+const b3SimdFloat4 B3_ATTRIBUTE_ALIGNED16(b3vQInv) = {-0.0f, -0.0f, -0.0f, +0.0f};
+const b3SimdFloat4 B3_ATTRIBUTE_ALIGNED16(b3vPPPM) = {+0.0f, +0.0f, +0.0f, -0.0f};
+
+#endif
+
+/**@brief The b3Quaternion implements quaternion to perform linear algebra rotations in combination with b3Matrix3x3, b3Vector3 and b3Transform. */
+class b3Quaternion : public b3QuadWord {
+public:
+ /**@brief No initialization constructor */
+ b3Quaternion() {}
+
+#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE))|| defined(B3_USE_NEON)
+ // Set Vector
+ B3_FORCE_INLINE b3Quaternion(const b3SimdFloat4 vec)
+ {
+ mVec128 = vec;
+ }
+
+ // Copy constructor
+ B3_FORCE_INLINE b3Quaternion(const b3Quaternion& rhs)
+ {
+ mVec128 = rhs.mVec128;
+ }
+
+ // Assignment Operator
+ B3_FORCE_INLINE b3Quaternion&
+ operator=(const b3Quaternion& v)
+ {
+ mVec128 = v.mVec128;
+
+ return *this;
+ }
+
+#endif
+
+ // template <typename b3Scalar>
+ // explicit Quaternion(const b3Scalar *v) : Tuple4<b3Scalar>(v) {}
+ /**@brief Constructor from scalars */
+ b3Quaternion(const b3Scalar& _x, const b3Scalar& _y, const b3Scalar& _z, const b3Scalar& _w)
+ : b3QuadWord(_x, _y, _z, _w)
+ {
+ //b3Assert(!((_x==1.f) && (_y==0.f) && (_z==0.f) && (_w==0.f)));
+ }
+ /**@brief Axis angle Constructor
+ * @param axis The axis which the rotation is around
+ * @param angle The magnitude of the rotation around the angle (Radians) */
+ b3Quaternion(const b3Vector3& _axis, const b3Scalar& _angle)
+ {
+ setRotation(_axis, _angle);
+ }
+ /**@brief Constructor from Euler angles
+ * @param yaw Angle around Y unless B3_EULER_DEFAULT_ZYX defined then Z
+ * @param pitch Angle around X unless B3_EULER_DEFAULT_ZYX defined then Y
+ * @param roll Angle around Z unless B3_EULER_DEFAULT_ZYX defined then X */
+ b3Quaternion(const b3Scalar& yaw, const b3Scalar& pitch, const b3Scalar& roll)
+ {
+#ifndef B3_EULER_DEFAULT_ZYX
+ setEuler(yaw, pitch, roll);
+#else
+ setEulerZYX(yaw, pitch, roll);
+#endif
+ }
+ /**@brief Set the rotation using axis angle notation
+ * @param axis The axis around which to rotate
+ * @param angle The magnitude of the rotation in Radians */
+ void setRotation(const b3Vector3& axis, const b3Scalar& _angle)
+ {
+ b3Scalar d = axis.length();
+ b3Assert(d != b3Scalar(0.0));
+ b3Scalar s = b3Sin(_angle * b3Scalar(0.5)) / d;
+ setValue(axis.getX() * s, axis.getY() * s, axis.getZ() * s,
+ b3Cos(_angle * b3Scalar(0.5)));
+ }
+ /**@brief Set the quaternion using Euler angles
+ * @param yaw Angle around Y
+ * @param pitch Angle around X
+ * @param roll Angle around Z */
+ void setEuler(const b3Scalar& yaw, const b3Scalar& pitch, const b3Scalar& roll)
+ {
+ b3Scalar halfYaw = b3Scalar(yaw) * b3Scalar(0.5);
+ b3Scalar halfPitch = b3Scalar(pitch) * b3Scalar(0.5);
+ b3Scalar halfRoll = b3Scalar(roll) * b3Scalar(0.5);
+ b3Scalar cosYaw = b3Cos(halfYaw);
+ b3Scalar sinYaw = b3Sin(halfYaw);
+ b3Scalar cosPitch = b3Cos(halfPitch);
+ b3Scalar sinPitch = b3Sin(halfPitch);
+ b3Scalar cosRoll = b3Cos(halfRoll);
+ b3Scalar sinRoll = b3Sin(halfRoll);
+ setValue(cosRoll * sinPitch * cosYaw + sinRoll * cosPitch * sinYaw,
+ cosRoll * cosPitch * sinYaw - sinRoll * sinPitch * cosYaw,
+ sinRoll * cosPitch * cosYaw - cosRoll * sinPitch * sinYaw,
+ cosRoll * cosPitch * cosYaw + sinRoll * sinPitch * sinYaw);
+ }
+
+ /**@brief Set the quaternion using euler angles
+ * @param yaw Angle around Z
+ * @param pitch Angle around Y
+ * @param roll Angle around X */
+ void setEulerZYX(const b3Scalar& yawZ, const b3Scalar& pitchY, const b3Scalar& rollX)
+ {
+ b3Scalar halfYaw = b3Scalar(yawZ) * b3Scalar(0.5);
+ b3Scalar halfPitch = b3Scalar(pitchY) * b3Scalar(0.5);
+ b3Scalar halfRoll = b3Scalar(rollX) * b3Scalar(0.5);
+ b3Scalar cosYaw = b3Cos(halfYaw);
+ b3Scalar sinYaw = b3Sin(halfYaw);
+ b3Scalar cosPitch = b3Cos(halfPitch);
+ b3Scalar sinPitch = b3Sin(halfPitch);
+ b3Scalar cosRoll = b3Cos(halfRoll);
+ b3Scalar sinRoll = b3Sin(halfRoll);
+ setValue(sinRoll * cosPitch * cosYaw - cosRoll * sinPitch * sinYaw, //x
+ cosRoll * sinPitch * cosYaw + sinRoll * cosPitch * sinYaw, //y
+ cosRoll * cosPitch * sinYaw - sinRoll * sinPitch * cosYaw, //z
+ cosRoll * cosPitch * cosYaw + sinRoll * sinPitch * sinYaw); //formerly yzx
+ normalize();
+ }
+
+ /**@brief Get the euler angles from this quaternion
+ * @param yaw Angle around Z
+ * @param pitch Angle around Y
+ * @param roll Angle around X */
+ void getEulerZYX(b3Scalar& yawZ, b3Scalar& pitchY, b3Scalar& rollX) const
+ {
+ b3Scalar squ;
+ b3Scalar sqx;
+ b3Scalar sqy;
+ b3Scalar sqz;
+ b3Scalar sarg;
+ sqx = m_floats[0] * m_floats[0];
+ sqy = m_floats[1] * m_floats[1];
+ sqz = m_floats[2] * m_floats[2];
+ squ = m_floats[3] * m_floats[3];
+ rollX = b3Atan2(2 * (m_floats[1] * m_floats[2] + m_floats[3] * m_floats[0]), squ - sqx - sqy + sqz);
+ sarg = b3Scalar(-2.) * (m_floats[0] * m_floats[2] - m_floats[3] * m_floats[1]);
+ pitchY = sarg <= b3Scalar(-1.0) ? b3Scalar(-0.5) * B3_PI: (sarg >= b3Scalar(1.0) ? b3Scalar(0.5) * B3_PI : b3Asin(sarg));
+ yawZ = b3Atan2(2 * (m_floats[0] * m_floats[1] + m_floats[3] * m_floats[2]), squ + sqx - sqy - sqz);
+ }
+
+ /**@brief Add two quaternions
+ * @param q The quaternion to add to this one */
+ B3_FORCE_INLINE b3Quaternion& operator+=(const b3Quaternion& q)
+ {
+#if defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+ mVec128 = _mm_add_ps(mVec128, q.mVec128);
+#elif defined(B3_USE_NEON)
+ mVec128 = vaddq_f32(mVec128, q.mVec128);
+#else
+ m_floats[0] += q.getX();
+ m_floats[1] += q.getY();
+ m_floats[2] += q.getZ();
+ m_floats[3] += q.m_floats[3];
+#endif
+ return *this;
+ }
+
+ /**@brief Subtract out a quaternion
+ * @param q The quaternion to subtract from this one */
+ b3Quaternion& operator-=(const b3Quaternion& q)
+ {
+#if defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+ mVec128 = _mm_sub_ps(mVec128, q.mVec128);
+#elif defined(B3_USE_NEON)
+ mVec128 = vsubq_f32(mVec128, q.mVec128);
+#else
+ m_floats[0] -= q.getX();
+ m_floats[1] -= q.getY();
+ m_floats[2] -= q.getZ();
+ m_floats[3] -= q.m_floats[3];
+#endif
+ return *this;
+ }
+
+ /**@brief Scale this quaternion
+ * @param s The scalar to scale by */
+ b3Quaternion& operator*=(const b3Scalar& s)
+ {
+#if defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+ __m128 vs = _mm_load_ss(&s); // (S 0 0 0)
+ vs = b3_pshufd_ps(vs, 0); // (S S S S)
+ mVec128 = _mm_mul_ps(mVec128, vs);
+#elif defined(B3_USE_NEON)
+ mVec128 = vmulq_n_f32(mVec128, s);
+#else
+ m_floats[0] *= s;
+ m_floats[1] *= s;
+ m_floats[2] *= s;
+ m_floats[3] *= s;
+#endif
+ return *this;
+ }
+
+ /**@brief Multiply this quaternion by q on the right
+ * @param q The other quaternion
+ * Equivilant to this = this * q */
+ b3Quaternion& operator*=(const b3Quaternion& q)
+ {
+#if defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+ __m128 vQ2 = q.get128();
+
+ __m128 A1 = b3_pshufd_ps(mVec128, B3_SHUFFLE(0,1,2,0));
+ __m128 B1 = b3_pshufd_ps(vQ2, B3_SHUFFLE(3,3,3,0));
+
+ A1 = A1 * B1;
+
+ __m128 A2 = b3_pshufd_ps(mVec128, B3_SHUFFLE(1,2,0,1));
+ __m128 B2 = b3_pshufd_ps(vQ2, B3_SHUFFLE(2,0,1,1));
+
+ A2 = A2 * B2;
+
+ B1 = b3_pshufd_ps(mVec128, B3_SHUFFLE(2,0,1,2));
+ B2 = b3_pshufd_ps(vQ2, B3_SHUFFLE(1,2,0,2));
+
+ B1 = B1 * B2; // A3 *= B3
+
+ mVec128 = b3_splat_ps(mVec128, 3); // A0
+ mVec128 = mVec128 * vQ2; // A0 * B0
+
+ A1 = A1 + A2; // AB12
+ mVec128 = mVec128 - B1; // AB03 = AB0 - AB3
+ A1 = _mm_xor_ps(A1, b3vPPPM); // change sign of the last element
+ mVec128 = mVec128+ A1; // AB03 + AB12
+
+#elif defined(B3_USE_NEON)
+
+ float32x4_t vQ1 = mVec128;
+ float32x4_t vQ2 = q.get128();
+ float32x4_t A0, A1, B1, A2, B2, A3, B3;
+ float32x2_t vQ1zx, vQ2wx, vQ1yz, vQ2zx, vQ2yz, vQ2xz;
+
+ {
+ float32x2x2_t tmp;
+ tmp = vtrn_f32( vget_high_f32(vQ1), vget_low_f32(vQ1) ); // {z x}, {w y}
+ vQ1zx = tmp.val[0];
+
+ tmp = vtrn_f32( vget_high_f32(vQ2), vget_low_f32(vQ2) ); // {z x}, {w y}
+ vQ2zx = tmp.val[0];
+ }
+ vQ2wx = vext_f32(vget_high_f32(vQ2), vget_low_f32(vQ2), 1);
+
+ vQ1yz = vext_f32(vget_low_f32(vQ1), vget_high_f32(vQ1), 1);
+
+ vQ2yz = vext_f32(vget_low_f32(vQ2), vget_high_f32(vQ2), 1);
+ vQ2xz = vext_f32(vQ2zx, vQ2zx, 1);
+
+ A1 = vcombine_f32(vget_low_f32(vQ1), vQ1zx); // X Y z x
+ B1 = vcombine_f32(vdup_lane_f32(vget_high_f32(vQ2), 1), vQ2wx); // W W W X
+
+ A2 = vcombine_f32(vQ1yz, vget_low_f32(vQ1));
+ B2 = vcombine_f32(vQ2zx, vdup_lane_f32(vget_low_f32(vQ2), 1));
+
+ A3 = vcombine_f32(vQ1zx, vQ1yz); // Z X Y Z
+ B3 = vcombine_f32(vQ2yz, vQ2xz); // Y Z x z
+
+ A1 = vmulq_f32(A1, B1);
+ A2 = vmulq_f32(A2, B2);
+ A3 = vmulq_f32(A3, B3); // A3 *= B3
+ A0 = vmulq_lane_f32(vQ2, vget_high_f32(vQ1), 1); // A0 * B0
+
+ A1 = vaddq_f32(A1, A2); // AB12 = AB1 + AB2
+ A0 = vsubq_f32(A0, A3); // AB03 = AB0 - AB3
+
+ // change the sign of the last element
+ A1 = (b3SimdFloat4)veorq_s32((int32x4_t)A1, (int32x4_t)b3vPPPM);
+ A0 = vaddq_f32(A0, A1); // AB03 + AB12
+
+ mVec128 = A0;
+#else
+ setValue(
+ m_floats[3] * q.getX() + m_floats[0] * q.m_floats[3] + m_floats[1] * q.getZ() - m_floats[2] * q.getY(),
+ m_floats[3] * q.getY() + m_floats[1] * q.m_floats[3] + m_floats[2] * q.getX() - m_floats[0] * q.getZ(),
+ m_floats[3] * q.getZ() + m_floats[2] * q.m_floats[3] + m_floats[0] * q.getY() - m_floats[1] * q.getX(),
+ m_floats[3] * q.m_floats[3] - m_floats[0] * q.getX() - m_floats[1] * q.getY() - m_floats[2] * q.getZ());
+#endif
+ return *this;
+ }
+ /**@brief Return the dot product between this quaternion and another
+ * @param q The other quaternion */
+ b3Scalar dot(const b3Quaternion& q) const
+ {
+#if defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+ __m128 vd;
+
+ vd = _mm_mul_ps(mVec128, q.mVec128);
+
+ __m128 t = _mm_movehl_ps(vd, vd);
+ vd = _mm_add_ps(vd, t);
+ t = _mm_shuffle_ps(vd, vd, 0x55);
+ vd = _mm_add_ss(vd, t);
+
+ return _mm_cvtss_f32(vd);
+#elif defined(B3_USE_NEON)
+ float32x4_t vd = vmulq_f32(mVec128, q.mVec128);
+ float32x2_t x = vpadd_f32(vget_low_f32(vd), vget_high_f32(vd));
+ x = vpadd_f32(x, x);
+ return vget_lane_f32(x, 0);
+#else
+ return m_floats[0] * q.getX() +
+ m_floats[1] * q.getY() +
+ m_floats[2] * q.getZ() +
+ m_floats[3] * q.m_floats[3];
+#endif
+ }
+
+ /**@brief Return the length squared of the quaternion */
+ b3Scalar length2() const
+ {
+ return dot(*this);
+ }
+
+ /**@brief Return the length of the quaternion */
+ b3Scalar length() const
+ {
+ return b3Sqrt(length2());
+ }
+
+ /**@brief Normalize the quaternion
+ * Such that x^2 + y^2 + z^2 +w^2 = 1 */
+ b3Quaternion& normalize()
+ {
+#if defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+ __m128 vd;
+
+ vd = _mm_mul_ps(mVec128, mVec128);
+
+ __m128 t = _mm_movehl_ps(vd, vd);
+ vd = _mm_add_ps(vd, t);
+ t = _mm_shuffle_ps(vd, vd, 0x55);
+ vd = _mm_add_ss(vd, t);
+
+ vd = _mm_sqrt_ss(vd);
+ vd = _mm_div_ss(b3vOnes, vd);
+ vd = b3_pshufd_ps(vd, 0); // splat
+ mVec128 = _mm_mul_ps(mVec128, vd);
+
+ return *this;
+#else
+ return *this /= length();
+#endif
+ }
+
+ /**@brief Return a scaled version of this quaternion
+ * @param s The scale factor */
+ B3_FORCE_INLINE b3Quaternion
+ operator*(const b3Scalar& s) const
+ {
+#if defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+ __m128 vs = _mm_load_ss(&s); // (S 0 0 0)
+ vs = b3_pshufd_ps(vs, 0x00); // (S S S S)
+
+ return b3Quaternion(_mm_mul_ps(mVec128, vs));
+#elif defined(B3_USE_NEON)
+ return b3Quaternion(vmulq_n_f32(mVec128, s));
+#else
+ return b3Quaternion(getX() * s, getY() * s, getZ() * s, m_floats[3] * s);
+#endif
+ }
+
+ /**@brief Return an inversely scaled versionof this quaternion
+ * @param s The inverse scale factor */
+ b3Quaternion operator/(const b3Scalar& s) const
+ {
+ b3Assert(s != b3Scalar(0.0));
+ return *this * (b3Scalar(1.0) / s);
+ }
+
+ /**@brief Inversely scale this quaternion
+ * @param s The scale factor */
+ b3Quaternion& operator/=(const b3Scalar& s)
+ {
+ b3Assert(s != b3Scalar(0.0));
+ return *this *= b3Scalar(1.0) / s;
+ }
+
+ /**@brief Return a normalized version of this quaternion */
+ b3Quaternion normalized() const
+ {
+ return *this / length();
+ }
+ /**@brief Return the angle between this quaternion and the other
+ * @param q The other quaternion */
+ b3Scalar angle(const b3Quaternion& q) const
+ {
+ b3Scalar s = b3Sqrt(length2() * q.length2());
+ b3Assert(s != b3Scalar(0.0));
+ return b3Acos(dot(q) / s);
+ }
+ /**@brief Return the angle of rotation represented by this quaternion */
+ b3Scalar getAngle() const
+ {
+ b3Scalar s = b3Scalar(2.) * b3Acos(m_floats[3]);
+ return s;
+ }
+
+ /**@brief Return the axis of the rotation represented by this quaternion */
+ b3Vector3 getAxis() const
+ {
+ b3Scalar s_squared = 1.f-m_floats[3]*m_floats[3];
+
+ if (s_squared < b3Scalar(10.) * B3_EPSILON) //Check for divide by zero
+ return b3MakeVector3(1.0, 0.0, 0.0); // Arbitrary
+ b3Scalar s = 1.f/b3Sqrt(s_squared);
+ return b3MakeVector3(m_floats[0] * s, m_floats[1] * s, m_floats[2] * s);
+ }
+
+ /**@brief Return the inverse of this quaternion */
+ b3Quaternion inverse() const
+ {
+#if defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+ return b3Quaternion(_mm_xor_ps(mVec128, b3vQInv));
+#elif defined(B3_USE_NEON)
+ return b3Quaternion((b3SimdFloat4)veorq_s32((int32x4_t)mVec128, (int32x4_t)b3vQInv));
+#else
+ return b3Quaternion(-m_floats[0], -m_floats[1], -m_floats[2], m_floats[3]);
+#endif
+ }
+
+ /**@brief Return the sum of this quaternion and the other
+ * @param q2 The other quaternion */
+ B3_FORCE_INLINE b3Quaternion
+ operator+(const b3Quaternion& q2) const
+ {
+#if defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+ return b3Quaternion(_mm_add_ps(mVec128, q2.mVec128));
+#elif defined(B3_USE_NEON)
+ return b3Quaternion(vaddq_f32(mVec128, q2.mVec128));
+#else
+ const b3Quaternion& q1 = *this;
+ return b3Quaternion(q1.getX() + q2.getX(), q1.getY() + q2.getY(), q1.getZ() + q2.getZ(), q1.m_floats[3] + q2.m_floats[3]);
+#endif
+ }
+
+ /**@brief Return the difference between this quaternion and the other
+ * @param q2 The other quaternion */
+ B3_FORCE_INLINE b3Quaternion
+ operator-(const b3Quaternion& q2) const
+ {
+#if defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+ return b3Quaternion(_mm_sub_ps(mVec128, q2.mVec128));
+#elif defined(B3_USE_NEON)
+ return b3Quaternion(vsubq_f32(mVec128, q2.mVec128));
+#else
+ const b3Quaternion& q1 = *this;
+ return b3Quaternion(q1.getX() - q2.getX(), q1.getY() - q2.getY(), q1.getZ() - q2.getZ(), q1.m_floats[3] - q2.m_floats[3]);
+#endif
+ }
+
+ /**@brief Return the negative of this quaternion
+ * This simply negates each element */
+ B3_FORCE_INLINE b3Quaternion operator-() const
+ {
+#if defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+ return b3Quaternion(_mm_xor_ps(mVec128, b3vMzeroMask));
+#elif defined(B3_USE_NEON)
+ return b3Quaternion((b3SimdFloat4)veorq_s32((int32x4_t)mVec128, (int32x4_t)b3vMzeroMask) );
+#else
+ const b3Quaternion& q2 = *this;
+ return b3Quaternion( - q2.getX(), - q2.getY(), - q2.getZ(), - q2.m_floats[3]);
+#endif
+ }
+ /**@todo document this and it's use */
+ B3_FORCE_INLINE b3Quaternion farthest( const b3Quaternion& qd) const
+ {
+ b3Quaternion diff,sum;
+ diff = *this - qd;
+ sum = *this + qd;
+ if( diff.dot(diff) > sum.dot(sum) )
+ return qd;
+ return (-qd);
+ }
+
+ /**@todo document this and it's use */
+ B3_FORCE_INLINE b3Quaternion nearest( const b3Quaternion& qd) const
+ {
+ b3Quaternion diff,sum;
+ diff = *this - qd;
+ sum = *this + qd;
+ if( diff.dot(diff) < sum.dot(sum) )
+ return qd;
+ return (-qd);
+ }
+
+
+ /**@brief Return the quaternion which is the result of Spherical Linear Interpolation between this and the other quaternion
+ * @param q The other quaternion to interpolate with
+ * @param t The ratio between this and q to interpolate. If t = 0 the result is this, if t=1 the result is q.
+ * Slerp interpolates assuming constant velocity. */
+ b3Quaternion slerp(const b3Quaternion& q, const b3Scalar& t) const
+ {
+ b3Scalar magnitude = b3Sqrt(length2() * q.length2());
+ b3Assert(magnitude > b3Scalar(0));
+
+ b3Scalar product = dot(q) / magnitude;
+ if (b3Fabs(product) < b3Scalar(1))
+ {
+ // Take care of long angle case see http://en.wikipedia.org/wiki/Slerp
+ const b3Scalar sign = (product < 0) ? b3Scalar(-1) : b3Scalar(1);
+
+ const b3Scalar theta = b3Acos(sign * product);
+ const b3Scalar s1 = b3Sin(sign * t * theta);
+ const b3Scalar d = b3Scalar(1.0) / b3Sin(theta);
+ const b3Scalar s0 = b3Sin((b3Scalar(1.0) - t) * theta);
+
+ return b3Quaternion(
+ (m_floats[0] * s0 + q.getX() * s1) * d,
+ (m_floats[1] * s0 + q.getY() * s1) * d,
+ (m_floats[2] * s0 + q.getZ() * s1) * d,
+ (m_floats[3] * s0 + q.m_floats[3] * s1) * d);
+ }
+ else
+ {
+ return *this;
+ }
+ }
+
+ static const b3Quaternion& getIdentity()
+ {
+ static const b3Quaternion identityQuat(b3Scalar(0.),b3Scalar(0.),b3Scalar(0.),b3Scalar(1.));
+ return identityQuat;
+ }
+
+ B3_FORCE_INLINE const b3Scalar& getW() const { return m_floats[3]; }
+
+
+};
+
+
+
+
+
+/**@brief Return the product of two quaternions */
+B3_FORCE_INLINE b3Quaternion
+operator*(const b3Quaternion& q1, const b3Quaternion& q2)
+{
+#if defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+ __m128 vQ1 = q1.get128();
+ __m128 vQ2 = q2.get128();
+ __m128 A0, A1, B1, A2, B2;
+
+ A1 = b3_pshufd_ps(vQ1, B3_SHUFFLE(0,1,2,0)); // X Y z x // vtrn
+ B1 = b3_pshufd_ps(vQ2, B3_SHUFFLE(3,3,3,0)); // W W W X // vdup vext
+
+ A1 = A1 * B1;
+
+ A2 = b3_pshufd_ps(vQ1, B3_SHUFFLE(1,2,0,1)); // Y Z X Y // vext
+ B2 = b3_pshufd_ps(vQ2, B3_SHUFFLE(2,0,1,1)); // z x Y Y // vtrn vdup
+
+ A2 = A2 * B2;
+
+ B1 = b3_pshufd_ps(vQ1, B3_SHUFFLE(2,0,1,2)); // z x Y Z // vtrn vext
+ B2 = b3_pshufd_ps(vQ2, B3_SHUFFLE(1,2,0,2)); // Y Z x z // vext vtrn
+
+ B1 = B1 * B2; // A3 *= B3
+
+ A0 = b3_splat_ps(vQ1, 3); // A0
+ A0 = A0 * vQ2; // A0 * B0
+
+ A1 = A1 + A2; // AB12
+ A0 = A0 - B1; // AB03 = AB0 - AB3
+
+ A1 = _mm_xor_ps(A1, b3vPPPM); // change sign of the last element
+ A0 = A0 + A1; // AB03 + AB12
+
+ return b3Quaternion(A0);
+
+#elif defined(B3_USE_NEON)
+
+ float32x4_t vQ1 = q1.get128();
+ float32x4_t vQ2 = q2.get128();
+ float32x4_t A0, A1, B1, A2, B2, A3, B3;
+ float32x2_t vQ1zx, vQ2wx, vQ1yz, vQ2zx, vQ2yz, vQ2xz;
+
+ {
+ float32x2x2_t tmp;
+ tmp = vtrn_f32( vget_high_f32(vQ1), vget_low_f32(vQ1) ); // {z x}, {w y}
+ vQ1zx = tmp.val[0];
+
+ tmp = vtrn_f32( vget_high_f32(vQ2), vget_low_f32(vQ2) ); // {z x}, {w y}
+ vQ2zx = tmp.val[0];
+ }
+ vQ2wx = vext_f32(vget_high_f32(vQ2), vget_low_f32(vQ2), 1);
+
+ vQ1yz = vext_f32(vget_low_f32(vQ1), vget_high_f32(vQ1), 1);
+
+ vQ2yz = vext_f32(vget_low_f32(vQ2), vget_high_f32(vQ2), 1);
+ vQ2xz = vext_f32(vQ2zx, vQ2zx, 1);
+
+ A1 = vcombine_f32(vget_low_f32(vQ1), vQ1zx); // X Y z x
+ B1 = vcombine_f32(vdup_lane_f32(vget_high_f32(vQ2), 1), vQ2wx); // W W W X
+
+ A2 = vcombine_f32(vQ1yz, vget_low_f32(vQ1));
+ B2 = vcombine_f32(vQ2zx, vdup_lane_f32(vget_low_f32(vQ2), 1));
+
+ A3 = vcombine_f32(vQ1zx, vQ1yz); // Z X Y Z
+ B3 = vcombine_f32(vQ2yz, vQ2xz); // Y Z x z
+
+ A1 = vmulq_f32(A1, B1);
+ A2 = vmulq_f32(A2, B2);
+ A3 = vmulq_f32(A3, B3); // A3 *= B3
+ A0 = vmulq_lane_f32(vQ2, vget_high_f32(vQ1), 1); // A0 * B0
+
+ A1 = vaddq_f32(A1, A2); // AB12 = AB1 + AB2
+ A0 = vsubq_f32(A0, A3); // AB03 = AB0 - AB3
+
+ // change the sign of the last element
+ A1 = (b3SimdFloat4)veorq_s32((int32x4_t)A1, (int32x4_t)b3vPPPM);
+ A0 = vaddq_f32(A0, A1); // AB03 + AB12
+
+ return b3Quaternion(A0);
+
+#else
+ return b3Quaternion(
+ q1.getW() * q2.getX() + q1.getX() * q2.getW() + q1.getY() * q2.getZ() - q1.getZ() * q2.getY(),
+ q1.getW() * q2.getY() + q1.getY() * q2.getW() + q1.getZ() * q2.getX() - q1.getX() * q2.getZ(),
+ q1.getW() * q2.getZ() + q1.getZ() * q2.getW() + q1.getX() * q2.getY() - q1.getY() * q2.getX(),
+ q1.getW() * q2.getW() - q1.getX() * q2.getX() - q1.getY() * q2.getY() - q1.getZ() * q2.getZ());
+#endif
+}
+
+B3_FORCE_INLINE b3Quaternion
+operator*(const b3Quaternion& q, const b3Vector3& w)
+{
+#if defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+ __m128 vQ1 = q.get128();
+ __m128 vQ2 = w.get128();
+ __m128 A1, B1, A2, B2, A3, B3;
+
+ A1 = b3_pshufd_ps(vQ1, B3_SHUFFLE(3,3,3,0));
+ B1 = b3_pshufd_ps(vQ2, B3_SHUFFLE(0,1,2,0));
+
+ A1 = A1 * B1;
+
+ A2 = b3_pshufd_ps(vQ1, B3_SHUFFLE(1,2,0,1));
+ B2 = b3_pshufd_ps(vQ2, B3_SHUFFLE(2,0,1,1));
+
+ A2 = A2 * B2;
+
+ A3 = b3_pshufd_ps(vQ1, B3_SHUFFLE(2,0,1,2));
+ B3 = b3_pshufd_ps(vQ2, B3_SHUFFLE(1,2,0,2));
+
+ A3 = A3 * B3; // A3 *= B3
+
+ A1 = A1 + A2; // AB12
+ A1 = _mm_xor_ps(A1, b3vPPPM); // change sign of the last element
+ A1 = A1 - A3; // AB123 = AB12 - AB3
+
+ return b3Quaternion(A1);
+
+#elif defined(B3_USE_NEON)
+
+ float32x4_t vQ1 = q.get128();
+ float32x4_t vQ2 = w.get128();
+ float32x4_t A1, B1, A2, B2, A3, B3;
+ float32x2_t vQ1wx, vQ2zx, vQ1yz, vQ2yz, vQ1zx, vQ2xz;
+
+ vQ1wx = vext_f32(vget_high_f32(vQ1), vget_low_f32(vQ1), 1);
+ {
+ float32x2x2_t tmp;
+
+ tmp = vtrn_f32( vget_high_f32(vQ2), vget_low_f32(vQ2) ); // {z x}, {w y}
+ vQ2zx = tmp.val[0];
+
+ tmp = vtrn_f32( vget_high_f32(vQ1), vget_low_f32(vQ1) ); // {z x}, {w y}
+ vQ1zx = tmp.val[0];
+ }
+
+ vQ1yz = vext_f32(vget_low_f32(vQ1), vget_high_f32(vQ1), 1);
+
+ vQ2yz = vext_f32(vget_low_f32(vQ2), vget_high_f32(vQ2), 1);
+ vQ2xz = vext_f32(vQ2zx, vQ2zx, 1);
+
+ A1 = vcombine_f32(vdup_lane_f32(vget_high_f32(vQ1), 1), vQ1wx); // W W W X
+ B1 = vcombine_f32(vget_low_f32(vQ2), vQ2zx); // X Y z x
+
+ A2 = vcombine_f32(vQ1yz, vget_low_f32(vQ1));
+ B2 = vcombine_f32(vQ2zx, vdup_lane_f32(vget_low_f32(vQ2), 1));
+
+ A3 = vcombine_f32(vQ1zx, vQ1yz); // Z X Y Z
+ B3 = vcombine_f32(vQ2yz, vQ2xz); // Y Z x z
+
+ A1 = vmulq_f32(A1, B1);
+ A2 = vmulq_f32(A2, B2);
+ A3 = vmulq_f32(A3, B3); // A3 *= B3
+
+ A1 = vaddq_f32(A1, A2); // AB12 = AB1 + AB2
+
+ // change the sign of the last element
+ A1 = (b3SimdFloat4)veorq_s32((int32x4_t)A1, (int32x4_t)b3vPPPM);
+
+ A1 = vsubq_f32(A1, A3); // AB123 = AB12 - AB3
+
+ return b3Quaternion(A1);
+
+#else
+ return b3Quaternion(
+ q.getW() * w.getX() + q.getY() * w.getZ() - q.getZ() * w.getY(),
+ q.getW() * w.getY() + q.getZ() * w.getX() - q.getX() * w.getZ(),
+ q.getW() * w.getZ() + q.getX() * w.getY() - q.getY() * w.getX(),
+ -q.getX() * w.getX() - q.getY() * w.getY() - q.getZ() * w.getZ());
+#endif
+}
+
+B3_FORCE_INLINE b3Quaternion
+operator*(const b3Vector3& w, const b3Quaternion& q)
+{
+#if defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+ __m128 vQ1 = w.get128();
+ __m128 vQ2 = q.get128();
+ __m128 A1, B1, A2, B2, A3, B3;
+
+ A1 = b3_pshufd_ps(vQ1, B3_SHUFFLE(0,1,2,0)); // X Y z x
+ B1 = b3_pshufd_ps(vQ2, B3_SHUFFLE(3,3,3,0)); // W W W X
+
+ A1 = A1 * B1;
+
+ A2 = b3_pshufd_ps(vQ1, B3_SHUFFLE(1,2,0,1));
+ B2 = b3_pshufd_ps(vQ2, B3_SHUFFLE(2,0,1,1));
+
+ A2 = A2 *B2;
+
+ A3 = b3_pshufd_ps(vQ1, B3_SHUFFLE(2,0,1,2));
+ B3 = b3_pshufd_ps(vQ2, B3_SHUFFLE(1,2,0,2));
+
+ A3 = A3 * B3; // A3 *= B3
+
+ A1 = A1 + A2; // AB12
+ A1 = _mm_xor_ps(A1, b3vPPPM); // change sign of the last element
+ A1 = A1 - A3; // AB123 = AB12 - AB3
+
+ return b3Quaternion(A1);
+
+#elif defined(B3_USE_NEON)
+
+ float32x4_t vQ1 = w.get128();
+ float32x4_t vQ2 = q.get128();
+ float32x4_t A1, B1, A2, B2, A3, B3;
+ float32x2_t vQ1zx, vQ2wx, vQ1yz, vQ2zx, vQ2yz, vQ2xz;
+
+ {
+ float32x2x2_t tmp;
+
+ tmp = vtrn_f32( vget_high_f32(vQ1), vget_low_f32(vQ1) ); // {z x}, {w y}
+ vQ1zx = tmp.val[0];
+
+ tmp = vtrn_f32( vget_high_f32(vQ2), vget_low_f32(vQ2) ); // {z x}, {w y}
+ vQ2zx = tmp.val[0];
+ }
+ vQ2wx = vext_f32(vget_high_f32(vQ2), vget_low_f32(vQ2), 1);
+
+ vQ1yz = vext_f32(vget_low_f32(vQ1), vget_high_f32(vQ1), 1);
+
+ vQ2yz = vext_f32(vget_low_f32(vQ2), vget_high_f32(vQ2), 1);
+ vQ2xz = vext_f32(vQ2zx, vQ2zx, 1);
+
+ A1 = vcombine_f32(vget_low_f32(vQ1), vQ1zx); // X Y z x
+ B1 = vcombine_f32(vdup_lane_f32(vget_high_f32(vQ2), 1), vQ2wx); // W W W X
+
+ A2 = vcombine_f32(vQ1yz, vget_low_f32(vQ1));
+ B2 = vcombine_f32(vQ2zx, vdup_lane_f32(vget_low_f32(vQ2), 1));
+
+ A3 = vcombine_f32(vQ1zx, vQ1yz); // Z X Y Z
+ B3 = vcombine_f32(vQ2yz, vQ2xz); // Y Z x z
+
+ A1 = vmulq_f32(A1, B1);
+ A2 = vmulq_f32(A2, B2);
+ A3 = vmulq_f32(A3, B3); // A3 *= B3
+
+ A1 = vaddq_f32(A1, A2); // AB12 = AB1 + AB2
+
+ // change the sign of the last element
+ A1 = (b3SimdFloat4)veorq_s32((int32x4_t)A1, (int32x4_t)b3vPPPM);
+
+ A1 = vsubq_f32(A1, A3); // AB123 = AB12 - AB3
+
+ return b3Quaternion(A1);
+
+#else
+ return b3Quaternion(
+ +w.getX() * q.getW() + w.getY() * q.getZ() - w.getZ() * q.getY(),
+ +w.getY() * q.getW() + w.getZ() * q.getX() - w.getX() * q.getZ(),
+ +w.getZ() * q.getW() + w.getX() * q.getY() - w.getY() * q.getX(),
+ -w.getX() * q.getX() - w.getY() * q.getY() - w.getZ() * q.getZ());
+#endif
+}
+
+/**@brief Calculate the dot product between two quaternions */
+B3_FORCE_INLINE b3Scalar
+b3Dot(const b3Quaternion& q1, const b3Quaternion& q2)
+{
+ return q1.dot(q2);
+}
+
+
+/**@brief Return the length of a quaternion */
+B3_FORCE_INLINE b3Scalar
+b3Length(const b3Quaternion& q)
+{
+ return q.length();
+}
+
+/**@brief Return the angle between two quaternions*/
+B3_FORCE_INLINE b3Scalar
+b3Angle(const b3Quaternion& q1, const b3Quaternion& q2)
+{
+ return q1.angle(q2);
+}
+
+/**@brief Return the inverse of a quaternion*/
+B3_FORCE_INLINE b3Quaternion
+b3Inverse(const b3Quaternion& q)
+{
+ return q.inverse();
+}
+
+/**@brief Return the result of spherical linear interpolation betwen two quaternions
+ * @param q1 The first quaternion
+ * @param q2 The second quaternion
+ * @param t The ration between q1 and q2. t = 0 return q1, t=1 returns q2
+ * Slerp assumes constant velocity between positions. */
+B3_FORCE_INLINE b3Quaternion
+b3Slerp(const b3Quaternion& q1, const b3Quaternion& q2, const b3Scalar& t)
+{
+ return q1.slerp(q2, t);
+}
+
+B3_FORCE_INLINE b3Quaternion
+b3QuatMul(const b3Quaternion& rot0, const b3Quaternion& rot1)
+{
+ return rot0*rot1;
+}
+
+B3_FORCE_INLINE b3Quaternion
+b3QuatNormalized(const b3Quaternion& orn)
+{
+ return orn.normalized();
+}
+
+
+
+B3_FORCE_INLINE b3Vector3
+b3QuatRotate(const b3Quaternion& rotation, const b3Vector3& v)
+{
+ b3Quaternion q = rotation * v;
+ q *= rotation.inverse();
+#if defined (B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+ return b3MakeVector3(_mm_and_ps(q.get128(), b3vFFF0fMask));
+#elif defined(B3_USE_NEON)
+ return b3MakeVector3((float32x4_t)vandq_s32((int32x4_t)q.get128(), b3vFFF0Mask));
+#else
+ return b3MakeVector3(q.getX(),q.getY(),q.getZ());
+#endif
+}
+
+B3_FORCE_INLINE b3Quaternion
+b3ShortestArcQuat(const b3Vector3& v0, const b3Vector3& v1) // Game Programming Gems 2.10. make sure v0,v1 are normalized
+{
+ b3Vector3 c = v0.cross(v1);
+ b3Scalar d = v0.dot(v1);
+
+ if (d < -1.0 + B3_EPSILON)
+ {
+ b3Vector3 n,unused;
+ b3PlaneSpace1(v0,n,unused);
+ return b3Quaternion(n.getX(),n.getY(),n.getZ(),0.0f); // just pick any vector that is orthogonal to v0
+ }
+
+ b3Scalar s = b3Sqrt((1.0f + d) * 2.0f);
+ b3Scalar rs = 1.0f / s;
+
+ return b3Quaternion(c.getX()*rs,c.getY()*rs,c.getZ()*rs,s * 0.5f);
+
+}
+
+B3_FORCE_INLINE b3Quaternion
+b3ShortestArcQuatNormalize2(b3Vector3& v0,b3Vector3& v1)
+{
+ v0.normalize();
+ v1.normalize();
+ return b3ShortestArcQuat(v0,v1);
+}
+
+#endif //B3_SIMD__QUATERNION_H_
+
+
+
diff --git a/thirdparty/bullet/src/Bullet3Common/b3Random.h b/thirdparty/bullet/src/Bullet3Common/b3Random.h
new file mode 100644
index 0000000000..dc040f1562
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Common/b3Random.h
@@ -0,0 +1,50 @@
+/*
+Copyright (c) 2003-2013 Gino van den Bergen / Erwin Coumans 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 B3_GEN_RANDOM_H
+#define B3_GEN_RANDOM_H
+
+#include "b3Scalar.h"
+
+#ifdef MT19937
+
+#include <limits.h>
+#include <mt19937.h>
+
+#define B3_RAND_MAX UINT_MAX
+
+B3_FORCE_INLINE void b3Srand(unsigned int seed) { init_genrand(seed); }
+B3_FORCE_INLINE unsigned int b3rand() { return genrand_int32(); }
+
+#else
+
+#include <stdlib.h>
+
+#define B3_RAND_MAX RAND_MAX
+
+B3_FORCE_INLINE void b3Srand(unsigned int seed) { srand(seed); }
+B3_FORCE_INLINE unsigned int b3rand() { return rand(); }
+
+#endif
+
+inline b3Scalar b3RandRange(b3Scalar minRange, b3Scalar maxRange)
+{
+ return (b3rand() / (b3Scalar(B3_RAND_MAX) + b3Scalar(1.0))) * (maxRange - minRange) + minRange;
+}
+
+
+#endif //B3_GEN_RANDOM_H
+
diff --git a/thirdparty/bullet/src/Bullet3Common/b3ResizablePool.h b/thirdparty/bullet/src/Bullet3Common/b3ResizablePool.h
new file mode 100644
index 0000000000..06ad8a778d
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Common/b3ResizablePool.h
@@ -0,0 +1,182 @@
+
+#ifndef B3_RESIZABLE_POOL_H
+#define B3_RESIZABLE_POOL_H
+
+#include "Bullet3Common/b3AlignedObjectArray.h"
+
+enum
+{
+ B3_POOL_HANDLE_TERMINAL_FREE=-1,
+ B3_POOL_HANDLE_TERMINAL_USED =-2
+};
+
+template <typename U>
+struct b3PoolBodyHandle : public U
+{
+ B3_DECLARE_ALIGNED_ALLOCATOR();
+
+ int m_nextFreeHandle;
+ void setNextFree(int next)
+ {
+ m_nextFreeHandle = next;
+ }
+ int getNextFree() const
+ {
+ return m_nextFreeHandle;
+ }
+};
+
+template <typename T>
+class b3ResizablePool
+{
+
+protected:
+ b3AlignedObjectArray<T> m_bodyHandles;
+ int m_numUsedHandles; // number of active handles
+ int m_firstFreeHandle; // free handles list
+
+ T* getHandleInternal(int handle)
+ {
+ return &m_bodyHandles[handle];
+
+ }
+ const T* getHandleInternal(int handle) const
+ {
+ return &m_bodyHandles[handle];
+ }
+
+public:
+
+ b3ResizablePool()
+ {
+ initHandles();
+ }
+
+ virtual ~b3ResizablePool()
+ {
+ exitHandles();
+ }
+///handle management
+
+ int getNumHandles() const
+ {
+ return m_bodyHandles.size();
+ }
+
+ void getUsedHandles(b3AlignedObjectArray<int>& usedHandles) const
+ {
+
+ for (int i=0;i<m_bodyHandles.size();i++)
+ {
+ if (m_bodyHandles[i].getNextFree()==B3_POOL_HANDLE_TERMINAL_USED)
+ {
+ usedHandles.push_back(i);
+ }
+ }
+ }
+
+
+
+ T* getHandle(int handle)
+ {
+ b3Assert(handle>=0);
+ b3Assert(handle<m_bodyHandles.size());
+ if ((handle<0) || (handle>=m_bodyHandles.size()))
+ {
+ return 0;
+ }
+
+ if (m_bodyHandles[handle].getNextFree()==B3_POOL_HANDLE_TERMINAL_USED)
+ {
+ return &m_bodyHandles[handle];
+ }
+ return 0;
+
+ }
+ const T* getHandle(int handle) const
+ {
+ b3Assert(handle>=0);
+ b3Assert(handle<m_bodyHandles.size());
+ if ((handle<0) || (handle>=m_bodyHandles.size()))
+ {
+ return 0;
+ }
+
+ if (m_bodyHandles[handle].getNextFree()==B3_POOL_HANDLE_TERMINAL_USED)
+ {
+ return &m_bodyHandles[handle];
+ }
+ return 0;
+ }
+
+ void increaseHandleCapacity(int extraCapacity)
+ {
+ int curCapacity = m_bodyHandles.size();
+ //b3Assert(curCapacity == m_numUsedHandles);
+ int newCapacity = curCapacity + extraCapacity;
+ m_bodyHandles.resize(newCapacity);
+
+ {
+ for (int i = curCapacity; i < newCapacity; i++)
+ m_bodyHandles[i].setNextFree(i + 1);
+
+
+ m_bodyHandles[newCapacity - 1].setNextFree(-1);
+ }
+ m_firstFreeHandle = curCapacity;
+ }
+ void initHandles()
+ {
+ m_numUsedHandles = 0;
+ m_firstFreeHandle = -1;
+
+ increaseHandleCapacity(1);
+ }
+
+ void exitHandles()
+ {
+ m_bodyHandles.resize(0);
+ m_firstFreeHandle = -1;
+ m_numUsedHandles = 0;
+ }
+
+ int allocHandle()
+ {
+ b3Assert(m_firstFreeHandle>=0);
+
+ int handle = m_firstFreeHandle;
+ m_firstFreeHandle = getHandleInternal(handle)->getNextFree();
+ m_numUsedHandles++;
+
+ if (m_firstFreeHandle<0)
+ {
+ //int curCapacity = m_bodyHandles.size();
+ int additionalCapacity= m_bodyHandles.size();
+ increaseHandleCapacity(additionalCapacity);
+
+
+ getHandleInternal(handle)->setNextFree(m_firstFreeHandle);
+ }
+ getHandleInternal(handle)->setNextFree(B3_POOL_HANDLE_TERMINAL_USED);
+ getHandleInternal(handle)->clear();
+ return handle;
+ }
+
+
+ void freeHandle(int handle)
+ {
+ b3Assert(handle >= 0);
+
+ if (m_bodyHandles[handle].getNextFree()==B3_POOL_HANDLE_TERMINAL_USED)
+ {
+ getHandleInternal(handle)->clear();
+ getHandleInternal(handle)->setNextFree(m_firstFreeHandle);
+ m_firstFreeHandle = handle;
+ m_numUsedHandles--;
+ }
+ }
+};
+ ///end handle management
+
+ #endif //B3_RESIZABLE_POOL_H
+ \ No newline at end of file
diff --git a/thirdparty/bullet/src/Bullet3Common/b3Scalar.h b/thirdparty/bullet/src/Bullet3Common/b3Scalar.h
new file mode 100644
index 0000000000..dbc7fea397
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Common/b3Scalar.h
@@ -0,0 +1,663 @@
+/*
+Copyright (c) 2003-2013 Gino van den Bergen / Erwin Coumans 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 B3_SCALAR_H
+#define B3_SCALAR_H
+
+#ifdef B3_MANAGED_CODE
+//Aligned data types not supported in managed code
+#pragma unmanaged
+#endif
+
+
+
+#include <math.h>
+#include <stdlib.h>//size_t for MSVC 6.0
+#include <float.h>
+
+//Original repository is at http://github.com/erwincoumans/bullet3
+#define B3_BULLET_VERSION 300
+
+inline int b3GetVersion()
+{
+ return B3_BULLET_VERSION;
+}
+
+#if defined(DEBUG) || defined (_DEBUG)
+#define B3_DEBUG
+#endif
+
+#include "b3Logging.h"//for b3Error
+
+
+#ifdef _WIN32
+
+ #if defined(__MINGW32__) || defined(__CYGWIN__) || (defined (_MSC_VER) && _MSC_VER < 1300)
+
+ #define B3_FORCE_INLINE inline
+ #define B3_ATTRIBUTE_ALIGNED16(a) a
+ #define B3_ATTRIBUTE_ALIGNED64(a) a
+ #define B3_ATTRIBUTE_ALIGNED128(a) a
+ #else
+ //#define B3_HAS_ALIGNED_ALLOCATOR
+ #pragma warning(disable : 4324) // disable padding warning
+// #pragma warning(disable:4530) // Disable the exception disable but used in MSCV Stl warning.
+ #pragma warning(disable:4996) //Turn off warnings about deprecated C routines
+// #pragma warning(disable:4786) // Disable the "debug name too long" warning
+
+ #define B3_FORCE_INLINE __forceinline
+ #define B3_ATTRIBUTE_ALIGNED16(a) __declspec(align(16)) a
+ #define B3_ATTRIBUTE_ALIGNED64(a) __declspec(align(64)) a
+ #define B3_ATTRIBUTE_ALIGNED128(a) __declspec (align(128)) a
+ #ifdef _XBOX
+ #define B3_USE_VMX128
+
+ #include <ppcintrinsics.h>
+ #define B3_HAVE_NATIVE_FSEL
+ #define b3Fsel(a,b,c) __fsel((a),(b),(c))
+ #else
+
+#if (defined (_WIN32) && (_MSC_VER) && _MSC_VER >= 1400) && (!defined (B3_USE_DOUBLE_PRECISION))
+ #if (defined (_M_IX86) || defined (_M_X64))
+ #define B3_USE_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
+ //(structured embedding Bullet structs/classes need to be 16-byte aligned)
+ //with relatively little performance gain
+ //If you are not embedded Bullet data in your classes, or make sure that you align those classes on 16-byte boundaries
+ //you can manually enable this line or set it in the build system for a bit of performance gain (a few percent, dependent on usage)
+ //#define B3_USE_SSE_IN_API
+ #endif //B3_USE_SSE
+ #include <emmintrin.h>
+ #endif
+#endif
+
+ #endif//_XBOX
+
+ #endif //__MINGW32__
+
+#ifdef B3_DEBUG
+ #ifdef _MSC_VER
+ #include <stdio.h>
+ #define b3Assert(x) { if(!(x)){b3Error("Assert "__FILE__ ":%u ("#x")\n", __LINE__);__debugbreak(); }}
+ #else//_MSC_VER
+ #include <assert.h>
+ #define b3Assert assert
+ #endif//_MSC_VER
+#else
+ #define b3Assert(x)
+#endif
+ //b3FullAssert is optional, slows down a lot
+ #define b3FullAssert(x)
+
+ #define b3Likely(_c) _c
+ #define b3Unlikely(_c) _c
+
+#else
+
+#if defined (__CELLOS_LV2__)
+ #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)))
+ #ifndef assert
+ #include <assert.h>
+ #endif
+#ifdef B3_DEBUG
+#ifdef __SPU__
+#include <spu_printf.h>
+#define printf spu_printf
+ #define b3Assert(x) {if(!(x)){b3Error("Assert "__FILE__ ":%u ("#x")\n", __LINE__);spu_hcmpeq(0,0);}}
+#else
+ #define b3Assert assert
+#endif
+
+#else
+ #define b3Assert(x)
+#endif
+ //b3FullAssert is optional, slows down a lot
+ #define b3FullAssert(x)
+
+ #define b3Likely(_c) _c
+ #define b3Unlikely(_c) _c
+
+#else
+
+#ifdef USE_LIBSPE2
+
+ #define B3_FORCE_INLINE __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)))
+ #ifndef assert
+ #include <assert.h>
+ #endif
+#ifdef B3_DEBUG
+ #define b3Assert assert
+#else
+ #define b3Assert(x)
+#endif
+ //b3FullAssert is optional, slows down a lot
+ #define b3FullAssert(x)
+
+
+ #define b3Likely(_c) __builtin_expect((_c), 1)
+ #define b3Unlikely(_c) __builtin_expect((_c), 0)
+
+
+#else
+ //non-windows systems
+
+#if (defined (__APPLE__) && (!defined (B3_USE_DOUBLE_PRECISION)))
+ #if defined (__i386__) || defined (__x86_64__)
+ #define B3_USE_SSE
+ //B3_USE_SSE_IN_API is enabled on Mac OSX by default, because memory is automatically aligned on 16-byte boundaries
+ //if apps run into issues, we will disable the next line
+ #define B3_USE_SSE_IN_API
+ #ifdef B3_USE_SSE
+ // include appropriate SSE level
+ #if defined (__SSE4_1__)
+ #include <smmintrin.h>
+ #elif defined (__SSSE3__)
+ #include <tmmintrin.h>
+ #elif defined (__SSE3__)
+ #include <pmmintrin.h>
+ #else
+ #include <emmintrin.h>
+ #endif
+ #endif //B3_USE_SSE
+ #elif defined( __armv7__ )
+ #ifdef __clang__
+ #define B3_USE_NEON 1
+
+ #if defined B3_USE_NEON && defined (__clang__)
+ #include <arm_neon.h>
+ #endif//B3_USE_NEON
+ #endif //__clang__
+ #endif//__arm__
+
+ #define B3_FORCE_INLINE inline __attribute__ ((always_inline))
+///@todo: check out alignment methods for other platforms/compilers
+ #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)))
+ #ifndef assert
+ #include <assert.h>
+ #endif
+
+ #if defined(DEBUG) || defined (_DEBUG)
+ #if defined (__i386__) || defined (__x86_64__)
+ #include <stdio.h>
+ #define b3Assert(x)\
+ {\
+ if(!(x))\
+ {\
+ b3Error("Assert %s in line %d, file %s\n",#x, __LINE__, __FILE__);\
+ asm volatile ("int3");\
+ }\
+ }
+ #else//defined (__i386__) || defined (__x86_64__)
+ #define b3Assert assert
+ #endif//defined (__i386__) || defined (__x86_64__)
+ #else//defined(DEBUG) || defined (_DEBUG)
+ #define b3Assert(x)
+ #endif//defined(DEBUG) || defined (_DEBUG)
+
+ //b3FullAssert is optional, slows down a lot
+ #define b3FullAssert(x)
+ #define b3Likely(_c) _c
+ #define b3Unlikely(_c) _c
+
+#else
+
+ #define B3_FORCE_INLINE inline
+ ///@todo: check out alignment methods for other platforms/compilers
+ #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)))
+ ///#define B3_ATTRIBUTE_ALIGNED16(a) a
+ ///#define B3_ATTRIBUTE_ALIGNED64(a) a
+ ///#define B3_ATTRIBUTE_ALIGNED128(a) a
+ #ifndef assert
+ #include <assert.h>
+ #endif
+
+#if defined(DEBUG) || defined (_DEBUG)
+ #define b3Assert assert
+#else
+ #define b3Assert(x)
+#endif
+
+ //b3FullAssert is optional, slows down a lot
+ #define b3FullAssert(x)
+ #define b3Likely(_c) _c
+ #define b3Unlikely(_c) _c
+#endif //__APPLE__
+
+#endif // LIBSPE2
+
+#endif //__CELLOS_LV2__
+#endif
+
+
+///The b3Scalar type abstracts floating point numbers, to easily switch between double and single floating point precision.
+#if defined(B3_USE_DOUBLE_PRECISION)
+typedef double b3Scalar;
+//this number could be bigger in double precision
+#define B3_LARGE_FLOAT 1e30
+#else
+typedef float b3Scalar;
+//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX
+#define B3_LARGE_FLOAT 1e18f
+#endif
+
+#ifdef B3_USE_SSE
+typedef __m128 b3SimdFloat4;
+#endif//B3_USE_SSE
+
+#if defined B3_USE_SSE_IN_API && defined (B3_USE_SSE)
+#ifdef _WIN32
+
+#ifndef B3_NAN
+static int b3NanMask = 0x7F800001;
+#define B3_NAN (*(float*)&b3NanMask)
+#endif
+
+#ifndef B3_INFINITY_MASK
+static int b3InfinityMask = 0x7F800000;
+#define B3_INFINITY_MASK (*(float*)&b3InfinityMask)
+#endif
+
+inline __m128 operator + (const __m128 A, const __m128 B)
+{
+ return _mm_add_ps(A, B);
+}
+
+inline __m128 operator - (const __m128 A, const __m128 B)
+{
+ return _mm_sub_ps(A, B);
+}
+
+inline __m128 operator * (const __m128 A, const __m128 B)
+{
+ return _mm_mul_ps(A, B);
+}
+
+#define b3CastfTo128i(a) (_mm_castps_si128(a))
+#define b3CastfTo128d(a) (_mm_castps_pd(a))
+#define b3CastiTo128f(a) (_mm_castsi128_ps(a))
+#define b3CastdTo128f(a) (_mm_castpd_ps(a))
+#define b3CastdTo128i(a) (_mm_castpd_si128(a))
+#define b3Assign128(r0,r1,r2,r3) _mm_setr_ps(r0,r1,r2,r3)
+
+#else//_WIN32
+
+#define b3CastfTo128i(a) ((__m128i)(a))
+#define b3CastfTo128d(a) ((__m128d)(a))
+#define b3CastiTo128f(a) ((__m128) (a))
+#define b3CastdTo128f(a) ((__m128) (a))
+#define b3CastdTo128i(a) ((__m128i)(a))
+#define b3Assign128(r0,r1,r2,r3) (__m128){r0,r1,r2,r3}
+#endif//_WIN32
+#endif //B3_USE_SSE_IN_API
+
+#ifdef B3_USE_NEON
+#include <arm_neon.h>
+
+typedef float32x4_t b3SimdFloat4;
+#define B3_INFINITY INFINITY
+#define B3_NAN NAN
+#define b3Assign128(r0,r1,r2,r3) (float32x4_t){r0,r1,r2,r3}
+#endif
+
+
+
+
+
+#define B3_DECLARE_ALIGNED_ALLOCATOR() \
+ B3_FORCE_INLINE void* operator new(size_t sizeInBytes) { return b3AlignedAlloc(sizeInBytes,16); } \
+ B3_FORCE_INLINE void operator delete(void* ptr) { b3AlignedFree(ptr); } \
+ B3_FORCE_INLINE void* operator new(size_t, void* ptr) { return ptr; } \
+ B3_FORCE_INLINE void operator delete(void*, void*) { } \
+ B3_FORCE_INLINE void* operator new[](size_t sizeInBytes) { return b3AlignedAlloc(sizeInBytes,16); } \
+ B3_FORCE_INLINE void operator delete[](void* ptr) { b3AlignedFree(ptr); } \
+ B3_FORCE_INLINE void* operator new[](size_t, void* ptr) { return ptr; } \
+ B3_FORCE_INLINE void operator delete[](void*, void*) { } \
+
+
+
+#if defined(B3_USE_DOUBLE_PRECISION) || defined(B3_FORCE_DOUBLE_FUNCTIONS)
+
+B3_FORCE_INLINE b3Scalar b3Sqrt(b3Scalar x) { return sqrt(x); }
+B3_FORCE_INLINE b3Scalar b3Fabs(b3Scalar x) { return fabs(x); }
+B3_FORCE_INLINE b3Scalar b3Cos(b3Scalar x) { return cos(x); }
+B3_FORCE_INLINE b3Scalar b3Sin(b3Scalar x) { return sin(x); }
+B3_FORCE_INLINE b3Scalar b3Tan(b3Scalar x) { return tan(x); }
+B3_FORCE_INLINE b3Scalar b3Acos(b3Scalar x) { if (x<b3Scalar(-1)) x=b3Scalar(-1); if (x>b3Scalar(1)) x=b3Scalar(1); return acos(x); }
+B3_FORCE_INLINE b3Scalar b3Asin(b3Scalar x) { if (x<b3Scalar(-1)) x=b3Scalar(-1); if (x>b3Scalar(1)) x=b3Scalar(1); return asin(x); }
+B3_FORCE_INLINE b3Scalar b3Atan(b3Scalar x) { return atan(x); }
+B3_FORCE_INLINE b3Scalar b3Atan2(b3Scalar x, b3Scalar y) { return atan2(x, y); }
+B3_FORCE_INLINE b3Scalar b3Exp(b3Scalar x) { return exp(x); }
+B3_FORCE_INLINE b3Scalar b3Log(b3Scalar x) { return log(x); }
+B3_FORCE_INLINE b3Scalar b3Pow(b3Scalar x,b3Scalar y) { return pow(x,y); }
+B3_FORCE_INLINE b3Scalar b3Fmod(b3Scalar x,b3Scalar y) { return fmod(x,y); }
+
+#else
+
+B3_FORCE_INLINE b3Scalar b3Sqrt(b3Scalar y)
+{
+#ifdef USE_APPROXIMATION
+ double x, z, tempf;
+ unsigned long *tfptr = ((unsigned long *)&tempf) + 1;
+
+ tempf = y;
+ *tfptr = (0xbfcdd90a - *tfptr)>>1; /* estimate of 1/sqrt(y) */
+ x = tempf;
+ z = y*b3Scalar(0.5);
+ x = (b3Scalar(1.5)*x)-(x*x)*(x*z); /* iteration formula */
+ x = (b3Scalar(1.5)*x)-(x*x)*(x*z);
+ x = (b3Scalar(1.5)*x)-(x*x)*(x*z);
+ x = (b3Scalar(1.5)*x)-(x*x)*(x*z);
+ x = (b3Scalar(1.5)*x)-(x*x)*(x*z);
+ return x*y;
+#else
+ return sqrtf(y);
+#endif
+}
+B3_FORCE_INLINE b3Scalar b3Fabs(b3Scalar x) { return fabsf(x); }
+B3_FORCE_INLINE b3Scalar b3Cos(b3Scalar x) { return cosf(x); }
+B3_FORCE_INLINE b3Scalar b3Sin(b3Scalar x) { return sinf(x); }
+B3_FORCE_INLINE b3Scalar b3Tan(b3Scalar x) { return tanf(x); }
+B3_FORCE_INLINE b3Scalar b3Acos(b3Scalar x) {
+ if (x<b3Scalar(-1))
+ x=b3Scalar(-1);
+ if (x>b3Scalar(1))
+ x=b3Scalar(1);
+ return acosf(x);
+}
+B3_FORCE_INLINE b3Scalar b3Asin(b3Scalar x) {
+ if (x<b3Scalar(-1))
+ x=b3Scalar(-1);
+ if (x>b3Scalar(1))
+ x=b3Scalar(1);
+ return asinf(x);
+}
+B3_FORCE_INLINE b3Scalar b3Atan(b3Scalar x) { return atanf(x); }
+B3_FORCE_INLINE b3Scalar b3Atan2(b3Scalar x, b3Scalar y) { return atan2f(x, y); }
+B3_FORCE_INLINE b3Scalar b3Exp(b3Scalar x) { return expf(x); }
+B3_FORCE_INLINE b3Scalar b3Log(b3Scalar x) { return logf(x); }
+B3_FORCE_INLINE b3Scalar b3Pow(b3Scalar x,b3Scalar y) { return powf(x,y); }
+B3_FORCE_INLINE b3Scalar b3Fmod(b3Scalar x,b3Scalar y) { return fmodf(x,y); }
+
+#endif
+
+#define B3_2_PI b3Scalar(6.283185307179586232)
+#define B3_PI (B3_2_PI * b3Scalar(0.5))
+#define B3_HALF_PI (B3_2_PI * b3Scalar(0.25))
+#define B3_RADS_PER_DEG (B3_2_PI / b3Scalar(360.0))
+#define B3_DEGS_PER_RAD (b3Scalar(360.0) / B3_2_PI)
+#define B3_SQRT12 b3Scalar(0.7071067811865475244008443621048490)
+
+#define b3RecipSqrt(x) ((b3Scalar)(b3Scalar(1.0)/b3Sqrt(b3Scalar(x)))) /* reciprocal square root */
+
+
+#ifdef B3_USE_DOUBLE_PRECISION
+#define B3_EPSILON DBL_EPSILON
+#define B3_INFINITY DBL_MAX
+#else
+#define B3_EPSILON FLT_EPSILON
+#define B3_INFINITY FLT_MAX
+#endif
+
+B3_FORCE_INLINE b3Scalar b3Atan2Fast(b3Scalar y, b3Scalar x)
+{
+ b3Scalar coeff_1 = B3_PI / 4.0f;
+ b3Scalar coeff_2 = 3.0f * coeff_1;
+ b3Scalar abs_y = b3Fabs(y);
+ b3Scalar angle;
+ if (x >= 0.0f) {
+ b3Scalar r = (x - abs_y) / (x + abs_y);
+ angle = coeff_1 - coeff_1 * r;
+ } else {
+ b3Scalar r = (x + abs_y) / (abs_y - x);
+ angle = coeff_2 - coeff_1 * r;
+ }
+ return (y < 0.0f) ? -angle : angle;
+}
+
+B3_FORCE_INLINE bool b3FuzzyZero(b3Scalar x) { return b3Fabs(x) < B3_EPSILON; }
+
+B3_FORCE_INLINE bool b3Equal(b3Scalar a, b3Scalar eps) {
+ return (((a) <= eps) && !((a) < -eps));
+}
+B3_FORCE_INLINE bool b3GreaterEqual (b3Scalar a, b3Scalar eps) {
+ return (!((a) <= eps));
+}
+
+
+B3_FORCE_INLINE int b3IsNegative(b3Scalar x) {
+ return x < b3Scalar(0.0) ? 1 : 0;
+}
+
+B3_FORCE_INLINE b3Scalar b3Radians(b3Scalar x) { return x * B3_RADS_PER_DEG; }
+B3_FORCE_INLINE b3Scalar b3Degrees(b3Scalar x) { return x * B3_DEGS_PER_RAD; }
+
+#define B3_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name
+
+#ifndef b3Fsel
+B3_FORCE_INLINE b3Scalar b3Fsel(b3Scalar a, b3Scalar b, b3Scalar c)
+{
+ return a >= 0 ? b : c;
+}
+#endif
+#define b3Fsels(a,b,c) (b3Scalar)b3Fsel(a,b,c)
+
+
+B3_FORCE_INLINE bool b3MachineIsLittleEndian()
+{
+ long int i = 1;
+ const char *p = (const char *) &i;
+ if (p[0] == 1) // Lowest address contains the least significant byte
+ return true;
+ else
+ return false;
+}
+
+
+
+///b3Select avoids branches, which makes performance much better for consoles like Playstation 3 and XBox 360
+///Thanks Phil Knight. See also http://www.cellperformance.com/articles/2006/04/more_techniques_for_eliminatin_1.html
+B3_FORCE_INLINE unsigned b3Select(unsigned condition, unsigned valueIfConditionNonZero, unsigned valueIfConditionZero)
+{
+ // Set testNz to 0xFFFFFFFF if condition is nonzero, 0x00000000 if condition is zero
+ // Rely on positive value or'ed with its negative having sign bit on
+ // and zero value or'ed with its negative (which is still zero) having sign bit off
+ // Use arithmetic shift right, shifting the sign bit through all 32 bits
+ unsigned testNz = (unsigned)(((int)condition | -(int)condition) >> 31);
+ unsigned testEqz = ~testNz;
+ return ((valueIfConditionNonZero & testNz) | (valueIfConditionZero & testEqz));
+}
+B3_FORCE_INLINE int b3Select(unsigned condition, int valueIfConditionNonZero, int valueIfConditionZero)
+{
+ unsigned testNz = (unsigned)(((int)condition | -(int)condition) >> 31);
+ unsigned testEqz = ~testNz;
+ return static_cast<int>((valueIfConditionNonZero & testNz) | (valueIfConditionZero & testEqz));
+}
+B3_FORCE_INLINE float b3Select(unsigned condition, float valueIfConditionNonZero, float valueIfConditionZero)
+{
+#ifdef B3_HAVE_NATIVE_FSEL
+ return (float)b3Fsel((b3Scalar)condition - b3Scalar(1.0f), valueIfConditionNonZero, valueIfConditionZero);
+#else
+ return (condition != 0) ? valueIfConditionNonZero : valueIfConditionZero;
+#endif
+}
+
+template<typename T> B3_FORCE_INLINE void b3Swap(T& a, T& b)
+{
+ T tmp = a;
+ a = b;
+ b = tmp;
+}
+
+
+//PCK: endian swapping functions
+B3_FORCE_INLINE unsigned b3SwapEndian(unsigned val)
+{
+ return (((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24));
+}
+
+B3_FORCE_INLINE unsigned short b3SwapEndian(unsigned short val)
+{
+ return static_cast<unsigned short>(((val & 0xff00) >> 8) | ((val & 0x00ff) << 8));
+}
+
+B3_FORCE_INLINE unsigned b3SwapEndian(int val)
+{
+ return b3SwapEndian((unsigned)val);
+}
+
+B3_FORCE_INLINE unsigned short b3SwapEndian(short val)
+{
+ return b3SwapEndian((unsigned short) val);
+}
+
+///b3SwapFloat uses using char pointers to swap the endianness
+////b3SwapFloat/b3SwapDouble will NOT return a float, because the machine might 'correct' invalid floating point values
+///Not all values of sign/exponent/mantissa are valid floating point numbers according to IEEE 754.
+///When a floating point unit is faced with an invalid value, it may actually change the value, or worse, throw an exception.
+///In most systems, running user mode code, you wouldn't get an exception, but instead the hardware/os/runtime will 'fix' the number for you.
+///so instead of returning a float/double, we return integer/long long integer
+B3_FORCE_INLINE unsigned int b3SwapEndianFloat(float d)
+{
+ unsigned int a = 0;
+ unsigned char *dst = (unsigned char *)&a;
+ unsigned char *src = (unsigned char *)&d;
+
+ dst[0] = src[3];
+ dst[1] = src[2];
+ dst[2] = src[1];
+ dst[3] = src[0];
+ return a;
+}
+
+// unswap using char pointers
+B3_FORCE_INLINE float b3UnswapEndianFloat(unsigned int a)
+{
+ float d = 0.0f;
+ unsigned char *src = (unsigned char *)&a;
+ unsigned char *dst = (unsigned char *)&d;
+
+ dst[0] = src[3];
+ dst[1] = src[2];
+ dst[2] = src[1];
+ dst[3] = src[0];
+
+ return d;
+}
+
+
+// swap using char pointers
+B3_FORCE_INLINE void b3SwapEndianDouble(double d, unsigned char* dst)
+{
+ unsigned char *src = (unsigned char *)&d;
+
+ dst[0] = src[7];
+ dst[1] = src[6];
+ dst[2] = src[5];
+ dst[3] = src[4];
+ dst[4] = src[3];
+ dst[5] = src[2];
+ dst[6] = src[1];
+ dst[7] = src[0];
+
+}
+
+// unswap using char pointers
+B3_FORCE_INLINE double b3UnswapEndianDouble(const unsigned char *src)
+{
+ double d = 0.0;
+ unsigned char *dst = (unsigned char *)&d;
+
+ dst[0] = src[7];
+ dst[1] = src[6];
+ dst[2] = src[5];
+ dst[3] = src[4];
+ dst[4] = src[3];
+ dst[5] = src[2];
+ dst[6] = src[1];
+ dst[7] = src[0];
+
+ return d;
+}
+
+// returns normalized value in range [-B3_PI, B3_PI]
+B3_FORCE_INLINE b3Scalar b3NormalizeAngle(b3Scalar angleInRadians)
+{
+ angleInRadians = b3Fmod(angleInRadians, B3_2_PI);
+ if(angleInRadians < -B3_PI)
+ {
+ return angleInRadians + B3_2_PI;
+ }
+ else if(angleInRadians > B3_PI)
+ {
+ return angleInRadians - B3_2_PI;
+ }
+ else
+ {
+ return angleInRadians;
+ }
+}
+
+///rudimentary class to provide type info
+struct b3TypedObject
+{
+ b3TypedObject(int objectType)
+ :m_objectType(objectType)
+ {
+ }
+ int m_objectType;
+ inline int getObjectType() const
+ {
+ return m_objectType;
+ }
+};
+
+
+
+///align a pointer to the provided alignment, upwards
+template <typename T>T* b3AlignPointer(T* unalignedPtr, size_t alignment)
+{
+
+ struct b3ConvertPointerSizeT
+ {
+ union
+ {
+ T* ptr;
+ size_t integer;
+ };
+ };
+ b3ConvertPointerSizeT converter;
+
+
+ const size_t bit_mask = ~(alignment - 1);
+ converter.ptr = unalignedPtr;
+ converter.integer += alignment-1;
+ converter.integer &= bit_mask;
+ return converter.ptr;
+}
+
+#endif //B3_SCALAR_H
diff --git a/thirdparty/bullet/src/Bullet3Common/b3StackAlloc.h b/thirdparty/bullet/src/Bullet3Common/b3StackAlloc.h
new file mode 100644
index 0000000000..de7de056b5
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Common/b3StackAlloc.h
@@ -0,0 +1,116 @@
+/*
+Copyright (c) 2003-2013 Gino van den Bergen / Erwin Coumans 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.
+*/
+
+/*
+StackAlloc extracted from GJK-EPA collision solver by Nathanael Presson
+Nov.2006
+*/
+
+#ifndef B3_STACK_ALLOC
+#define B3_STACK_ALLOC
+
+#include "b3Scalar.h" //for b3Assert
+#include "b3AlignedAllocator.h"
+
+///The b3Block class is an internal structure for the b3StackAlloc memory allocator.
+struct b3Block
+{
+ b3Block* previous;
+ unsigned char* address;
+};
+
+///The StackAlloc class provides some fast stack-based memory allocator (LIFO last-in first-out)
+class b3StackAlloc
+{
+public:
+
+ b3StackAlloc(unsigned int size) { ctor();create(size); }
+ ~b3StackAlloc() { destroy(); }
+
+ inline void create(unsigned int size)
+ {
+ destroy();
+ data = (unsigned char*) b3AlignedAlloc(size,16);
+ totalsize = size;
+ }
+ inline void destroy()
+ {
+ b3Assert(usedsize==0);
+ //Raise(L"StackAlloc is still in use");
+
+ if(usedsize==0)
+ {
+ if(!ischild && data)
+ b3AlignedFree(data);
+
+ data = 0;
+ usedsize = 0;
+ }
+
+ }
+
+ int getAvailableMemory() const
+ {
+ return static_cast<int>(totalsize - usedsize);
+ }
+
+ unsigned char* allocate(unsigned int size)
+ {
+ const unsigned int nus(usedsize+size);
+ if(nus<totalsize)
+ {
+ usedsize=nus;
+ return(data+(usedsize-size));
+ }
+ b3Assert(0);
+ //&& (L"Not enough memory"));
+
+ return(0);
+ }
+ B3_FORCE_INLINE b3Block* beginBlock()
+ {
+ b3Block* pb = (b3Block*)allocate(sizeof(b3Block));
+ pb->previous = current;
+ pb->address = data+usedsize;
+ current = pb;
+ return(pb);
+ }
+ B3_FORCE_INLINE void endBlock(b3Block* block)
+ {
+ b3Assert(block==current);
+ //Raise(L"Unmatched blocks");
+ if(block==current)
+ {
+ current = block->previous;
+ usedsize = (unsigned int)((block->address-data)-sizeof(b3Block));
+ }
+ }
+
+private:
+ void ctor()
+ {
+ data = 0;
+ totalsize = 0;
+ usedsize = 0;
+ current = 0;
+ ischild = false;
+ }
+ unsigned char* data;
+ unsigned int totalsize;
+ unsigned int usedsize;
+ b3Block* current;
+ bool ischild;
+};
+
+#endif //B3_STACK_ALLOC
diff --git a/thirdparty/bullet/src/Bullet3Common/b3Transform.h b/thirdparty/bullet/src/Bullet3Common/b3Transform.h
new file mode 100644
index 0000000000..fa480759be
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Common/b3Transform.h
@@ -0,0 +1,304 @@
+/*
+Copyright (c) 2003-2013 Gino van den Bergen / Erwin Coumans 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 B3_TRANSFORM_H
+#define B3_TRANSFORM_H
+
+
+#include "b3Matrix3x3.h"
+
+#ifdef B3_USE_DOUBLE_PRECISION
+#define b3TransformData b3TransformDoubleData
+#else
+#define b3TransformData b3TransformFloatData
+#endif
+
+
+
+
+/**@brief The b3Transform class supports rigid transforms with only translation and rotation and no scaling/shear.
+ *It can be used in combination with b3Vector3, b3Quaternion and b3Matrix3x3 linear algebra classes. */
+B3_ATTRIBUTE_ALIGNED16(class) b3Transform {
+
+ ///Storage for the rotation
+ b3Matrix3x3 m_basis;
+ ///Storage for the translation
+ b3Vector3 m_origin;
+
+public:
+
+ /**@brief No initialization constructor */
+ b3Transform() {}
+ /**@brief Constructor from b3Quaternion (optional b3Vector3 )
+ * @param q Rotation from quaternion
+ * @param c Translation from Vector (default 0,0,0) */
+ explicit B3_FORCE_INLINE b3Transform(const b3Quaternion& q,
+ const b3Vector3& c = b3MakeVector3(b3Scalar(0), b3Scalar(0), b3Scalar(0)))
+ : m_basis(q),
+ m_origin(c)
+ {}
+
+ /**@brief Constructor from b3Matrix3x3 (optional b3Vector3)
+ * @param b Rotation from Matrix
+ * @param c Translation from Vector default (0,0,0)*/
+ explicit B3_FORCE_INLINE b3Transform(const b3Matrix3x3& b,
+ const b3Vector3& c = b3MakeVector3(b3Scalar(0), b3Scalar(0), b3Scalar(0)))
+ : m_basis(b),
+ m_origin(c)
+ {}
+ /**@brief Copy constructor */
+ B3_FORCE_INLINE b3Transform (const b3Transform& other)
+ : m_basis(other.m_basis),
+ m_origin(other.m_origin)
+ {
+ }
+ /**@brief Assignment Operator */
+ B3_FORCE_INLINE b3Transform& operator=(const b3Transform& other)
+ {
+ m_basis = other.m_basis;
+ m_origin = other.m_origin;
+ return *this;
+ }
+
+
+ /**@brief Set the current transform as the value of the product of two transforms
+ * @param t1 Transform 1
+ * @param t2 Transform 2
+ * This = Transform1 * Transform2 */
+ B3_FORCE_INLINE void mult(const b3Transform& t1, const b3Transform& t2) {
+ m_basis = t1.m_basis * t2.m_basis;
+ m_origin = t1(t2.m_origin);
+ }
+
+/* void multInverseLeft(const b3Transform& t1, const b3Transform& t2) {
+ b3Vector3 v = t2.m_origin - t1.m_origin;
+ m_basis = b3MultTransposeLeft(t1.m_basis, t2.m_basis);
+ m_origin = v * t1.m_basis;
+ }
+ */
+
+/**@brief Return the transform of the vector */
+ B3_FORCE_INLINE b3Vector3 operator()(const b3Vector3& x) const
+ {
+ return x.dot3(m_basis[0], m_basis[1], m_basis[2]) + m_origin;
+ }
+
+ /**@brief Return the transform of the vector */
+ B3_FORCE_INLINE b3Vector3 operator*(const b3Vector3& x) const
+ {
+ return (*this)(x);
+ }
+
+ /**@brief Return the transform of the b3Quaternion */
+ B3_FORCE_INLINE b3Quaternion operator*(const b3Quaternion& q) const
+ {
+ return getRotation() * q;
+ }
+
+ /**@brief Return the basis matrix for the rotation */
+ B3_FORCE_INLINE b3Matrix3x3& getBasis() { return m_basis; }
+ /**@brief Return the basis matrix for the rotation */
+ B3_FORCE_INLINE const b3Matrix3x3& getBasis() const { return m_basis; }
+
+ /**@brief Return the origin vector translation */
+ B3_FORCE_INLINE b3Vector3& getOrigin() { return m_origin; }
+ /**@brief Return the origin vector translation */
+ B3_FORCE_INLINE const b3Vector3& getOrigin() const { return m_origin; }
+
+ /**@brief Return a quaternion representing the rotation */
+ b3Quaternion getRotation() const {
+ b3Quaternion q;
+ m_basis.getRotation(q);
+ return q;
+ }
+
+
+ /**@brief Set from an array
+ * @param m A pointer to a 15 element array (12 rotation(row major padded on the right by 1), and 3 translation */
+ void setFromOpenGLMatrix(const b3Scalar *m)
+ {
+ m_basis.setFromOpenGLSubMatrix(m);
+ m_origin.setValue(m[12],m[13],m[14]);
+ }
+
+ /**@brief Fill an array representation
+ * @param m A pointer to a 15 element array (12 rotation(row major padded on the right by 1), and 3 translation */
+ void getOpenGLMatrix(b3Scalar *m) const
+ {
+ m_basis.getOpenGLSubMatrix(m);
+ m[12] = m_origin.getX();
+ m[13] = m_origin.getY();
+ m[14] = m_origin.getZ();
+ m[15] = b3Scalar(1.0);
+ }
+
+ /**@brief Set the translational element
+ * @param origin The vector to set the translation to */
+ B3_FORCE_INLINE void setOrigin(const b3Vector3& origin)
+ {
+ m_origin = origin;
+ }
+
+ B3_FORCE_INLINE b3Vector3 invXform(const b3Vector3& inVec) const;
+
+
+ /**@brief Set the rotational element by b3Matrix3x3 */
+ B3_FORCE_INLINE void setBasis(const b3Matrix3x3& basis)
+ {
+ m_basis = basis;
+ }
+
+ /**@brief Set the rotational element by b3Quaternion */
+ B3_FORCE_INLINE void setRotation(const b3Quaternion& q)
+ {
+ m_basis.setRotation(q);
+ }
+
+
+ /**@brief Set this transformation to the identity */
+ void setIdentity()
+ {
+ m_basis.setIdentity();
+ m_origin.setValue(b3Scalar(0.0), b3Scalar(0.0), b3Scalar(0.0));
+ }
+
+ /**@brief Multiply this Transform by another(this = this * another)
+ * @param t The other transform */
+ b3Transform& operator*=(const b3Transform& t)
+ {
+ m_origin += m_basis * t.m_origin;
+ m_basis *= t.m_basis;
+ return *this;
+ }
+
+ /**@brief Return the inverse of this transform */
+ b3Transform inverse() const
+ {
+ b3Matrix3x3 inv = m_basis.transpose();
+ return b3Transform(inv, inv * -m_origin);
+ }
+
+ /**@brief Return the inverse of this transform times the other transform
+ * @param t The other transform
+ * return this.inverse() * the other */
+ b3Transform inverseTimes(const b3Transform& t) const;
+
+ /**@brief Return the product of this transform and the other */
+ b3Transform operator*(const b3Transform& t) const;
+
+ /**@brief Return an identity transform */
+ static const b3Transform& getIdentity()
+ {
+ static const b3Transform identityTransform(b3Matrix3x3::getIdentity());
+ return identityTransform;
+ }
+
+ void serialize(struct b3TransformData& dataOut) const;
+
+ void serializeFloat(struct b3TransformFloatData& dataOut) const;
+
+ void deSerialize(const struct b3TransformData& dataIn);
+
+ void deSerializeDouble(const struct b3TransformDoubleData& dataIn);
+
+ void deSerializeFloat(const struct b3TransformFloatData& dataIn);
+
+};
+
+
+B3_FORCE_INLINE b3Vector3
+b3Transform::invXform(const b3Vector3& inVec) const
+{
+ b3Vector3 v = inVec - m_origin;
+ return (m_basis.transpose() * v);
+}
+
+B3_FORCE_INLINE b3Transform
+b3Transform::inverseTimes(const b3Transform& t) const
+{
+ b3Vector3 v = t.getOrigin() - m_origin;
+ return b3Transform(m_basis.transposeTimes(t.m_basis),
+ v * m_basis);
+}
+
+B3_FORCE_INLINE b3Transform
+b3Transform::operator*(const b3Transform& t) const
+{
+ return b3Transform(m_basis * t.m_basis,
+ (*this)(t.m_origin));
+}
+
+/**@brief Test if two transforms have all elements equal */
+B3_FORCE_INLINE bool operator==(const b3Transform& t1, const b3Transform& t2)
+{
+ return ( t1.getBasis() == t2.getBasis() &&
+ t1.getOrigin() == t2.getOrigin() );
+}
+
+
+///for serialization
+struct b3TransformFloatData
+{
+ b3Matrix3x3FloatData m_basis;
+ b3Vector3FloatData m_origin;
+};
+
+struct b3TransformDoubleData
+{
+ b3Matrix3x3DoubleData m_basis;
+ b3Vector3DoubleData m_origin;
+};
+
+
+
+B3_FORCE_INLINE void b3Transform::serialize(b3TransformData& dataOut) const
+{
+ m_basis.serialize(dataOut.m_basis);
+ m_origin.serialize(dataOut.m_origin);
+}
+
+B3_FORCE_INLINE void b3Transform::serializeFloat(b3TransformFloatData& dataOut) const
+{
+ m_basis.serializeFloat(dataOut.m_basis);
+ m_origin.serializeFloat(dataOut.m_origin);
+}
+
+
+B3_FORCE_INLINE void b3Transform::deSerialize(const b3TransformData& dataIn)
+{
+ m_basis.deSerialize(dataIn.m_basis);
+ m_origin.deSerialize(dataIn.m_origin);
+}
+
+B3_FORCE_INLINE void b3Transform::deSerializeFloat(const b3TransformFloatData& dataIn)
+{
+ m_basis.deSerializeFloat(dataIn.m_basis);
+ m_origin.deSerializeFloat(dataIn.m_origin);
+}
+
+B3_FORCE_INLINE void b3Transform::deSerializeDouble(const b3TransformDoubleData& dataIn)
+{
+ m_basis.deSerializeDouble(dataIn.m_basis);
+ m_origin.deSerializeDouble(dataIn.m_origin);
+}
+
+
+#endif //B3_TRANSFORM_H
+
+
+
+
+
+
diff --git a/thirdparty/bullet/src/Bullet3Common/b3TransformUtil.h b/thirdparty/bullet/src/Bullet3Common/b3TransformUtil.h
new file mode 100644
index 0000000000..6ce580c132
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Common/b3TransformUtil.h
@@ -0,0 +1,228 @@
+/*
+Copyright (c) 2003-2013 Gino van den Bergen / Erwin Coumans 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 B3_TRANSFORM_UTIL_H
+#define B3_TRANSFORM_UTIL_H
+
+#include "b3Transform.h"
+#define B3_ANGULAR_MOTION_THRESHOLD b3Scalar(0.5)*B3_HALF_PI
+
+
+
+
+B3_FORCE_INLINE b3Vector3 b3AabbSupport(const b3Vector3& halfExtents,const b3Vector3& supportDir)
+{
+ return b3MakeVector3(supportDir.getX() < b3Scalar(0.0) ? -halfExtents.getX() : halfExtents.getX(),
+ supportDir.getY() < b3Scalar(0.0) ? -halfExtents.getY() : halfExtents.getY(),
+ supportDir.getZ() < b3Scalar(0.0) ? -halfExtents.getZ() : halfExtents.getZ());
+}
+
+
+
+
+
+
+/// Utils related to temporal transforms
+class b3TransformUtil
+{
+
+public:
+
+ static void integrateTransform(const b3Transform& curTrans,const b3Vector3& linvel,const b3Vector3& angvel,b3Scalar timeStep,b3Transform& predictedTransform)
+ {
+ predictedTransform.setOrigin(curTrans.getOrigin() + linvel * timeStep);
+// #define QUATERNION_DERIVATIVE
+ #ifdef QUATERNION_DERIVATIVE
+ b3Quaternion predictedOrn = curTrans.getRotation();
+ predictedOrn += (angvel * predictedOrn) * (timeStep * b3Scalar(0.5));
+ predictedOrn.normalize();
+ #else
+ //Exponential map
+ //google for "Practical Parameterization of Rotations Using the Exponential Map", F. Sebastian Grassia
+
+ b3Vector3 axis;
+ b3Scalar fAngle = angvel.length();
+ //limit the angular motion
+ if (fAngle*timeStep > B3_ANGULAR_MOTION_THRESHOLD)
+ {
+ fAngle = B3_ANGULAR_MOTION_THRESHOLD / timeStep;
+ }
+
+ if ( fAngle < b3Scalar(0.001) )
+ {
+ // use Taylor's expansions of sync function
+ axis = angvel*( b3Scalar(0.5)*timeStep-(timeStep*timeStep*timeStep)*(b3Scalar(0.020833333333))*fAngle*fAngle );
+ }
+ else
+ {
+ // sync(fAngle) = sin(c*fAngle)/t
+ axis = angvel*( b3Sin(b3Scalar(0.5)*fAngle*timeStep)/fAngle );
+ }
+ b3Quaternion dorn (axis.getX(),axis.getY(),axis.getZ(),b3Cos( fAngle*timeStep*b3Scalar(0.5) ));
+ b3Quaternion orn0 = curTrans.getRotation();
+
+ b3Quaternion predictedOrn = dorn * orn0;
+ predictedOrn.normalize();
+ #endif
+ predictedTransform.setRotation(predictedOrn);
+ }
+
+ static void calculateVelocityQuaternion(const b3Vector3& pos0,const b3Vector3& pos1,const b3Quaternion& orn0,const b3Quaternion& orn1,b3Scalar timeStep,b3Vector3& linVel,b3Vector3& angVel)
+ {
+ linVel = (pos1 - pos0) / timeStep;
+ b3Vector3 axis;
+ b3Scalar angle;
+ if (orn0 != orn1)
+ {
+ calculateDiffAxisAngleQuaternion(orn0,orn1,axis,angle);
+ angVel = axis * angle / timeStep;
+ } else
+ {
+ angVel.setValue(0,0,0);
+ }
+ }
+
+ static void calculateDiffAxisAngleQuaternion(const b3Quaternion& orn0,const b3Quaternion& orn1a,b3Vector3& axis,b3Scalar& angle)
+ {
+ b3Quaternion orn1 = orn0.nearest(orn1a);
+ b3Quaternion dorn = orn1 * orn0.inverse();
+ angle = dorn.getAngle();
+ axis = b3MakeVector3(dorn.getX(),dorn.getY(),dorn.getZ());
+ axis[3] = b3Scalar(0.);
+ //check for axis length
+ b3Scalar len = axis.length2();
+ if (len < B3_EPSILON*B3_EPSILON)
+ axis = b3MakeVector3(b3Scalar(1.),b3Scalar(0.),b3Scalar(0.));
+ else
+ axis /= b3Sqrt(len);
+ }
+
+ static void calculateVelocity(const b3Transform& transform0,const b3Transform& transform1,b3Scalar timeStep,b3Vector3& linVel,b3Vector3& angVel)
+ {
+ linVel = (transform1.getOrigin() - transform0.getOrigin()) / timeStep;
+ b3Vector3 axis;
+ b3Scalar angle;
+ calculateDiffAxisAngle(transform0,transform1,axis,angle);
+ angVel = axis * angle / timeStep;
+ }
+
+ static void calculateDiffAxisAngle(const b3Transform& transform0,const b3Transform& transform1,b3Vector3& axis,b3Scalar& angle)
+ {
+ b3Matrix3x3 dmat = transform1.getBasis() * transform0.getBasis().inverse();
+ b3Quaternion dorn;
+ dmat.getRotation(dorn);
+
+ ///floating point inaccuracy can lead to w component > 1..., which breaks
+ dorn.normalize();
+
+ angle = dorn.getAngle();
+ axis = b3MakeVector3(dorn.getX(),dorn.getY(),dorn.getZ());
+ axis[3] = b3Scalar(0.);
+ //check for axis length
+ b3Scalar len = axis.length2();
+ if (len < B3_EPSILON*B3_EPSILON)
+ axis = b3MakeVector3(b3Scalar(1.),b3Scalar(0.),b3Scalar(0.));
+ else
+ axis /= b3Sqrt(len);
+ }
+
+};
+
+
+///The b3ConvexSeparatingDistanceUtil can help speed up convex collision detection
+///by conservatively updating a cached separating distance/vector instead of re-calculating the closest distance
+class b3ConvexSeparatingDistanceUtil
+{
+ b3Quaternion m_ornA;
+ b3Quaternion m_ornB;
+ b3Vector3 m_posA;
+ b3Vector3 m_posB;
+
+ b3Vector3 m_separatingNormal;
+
+ b3Scalar m_boundingRadiusA;
+ b3Scalar m_boundingRadiusB;
+ b3Scalar m_separatingDistance;
+
+public:
+
+ b3ConvexSeparatingDistanceUtil(b3Scalar boundingRadiusA,b3Scalar boundingRadiusB)
+ :m_boundingRadiusA(boundingRadiusA),
+ m_boundingRadiusB(boundingRadiusB),
+ m_separatingDistance(0.f)
+ {
+ }
+
+ b3Scalar getConservativeSeparatingDistance()
+ {
+ return m_separatingDistance;
+ }
+
+ void updateSeparatingDistance(const b3Transform& transA,const b3Transform& transB)
+ {
+ const b3Vector3& toPosA = transA.getOrigin();
+ const b3Vector3& toPosB = transB.getOrigin();
+ b3Quaternion toOrnA = transA.getRotation();
+ b3Quaternion toOrnB = transB.getRotation();
+
+ if (m_separatingDistance>0.f)
+ {
+
+
+ b3Vector3 linVelA,angVelA,linVelB,angVelB;
+ b3TransformUtil::calculateVelocityQuaternion(m_posA,toPosA,m_ornA,toOrnA,b3Scalar(1.),linVelA,angVelA);
+ b3TransformUtil::calculateVelocityQuaternion(m_posB,toPosB,m_ornB,toOrnB,b3Scalar(1.),linVelB,angVelB);
+ b3Scalar maxAngularProjectedVelocity = angVelA.length() * m_boundingRadiusA + angVelB.length() * m_boundingRadiusB;
+ b3Vector3 relLinVel = (linVelB-linVelA);
+ b3Scalar relLinVelocLength = relLinVel.dot(m_separatingNormal);
+ if (relLinVelocLength<0.f)
+ {
+ relLinVelocLength = 0.f;
+ }
+
+ b3Scalar projectedMotion = maxAngularProjectedVelocity +relLinVelocLength;
+ m_separatingDistance -= projectedMotion;
+ }
+
+ m_posA = toPosA;
+ m_posB = toPosB;
+ m_ornA = toOrnA;
+ m_ornB = toOrnB;
+ }
+
+ void initSeparatingDistance(const b3Vector3& separatingVector,b3Scalar separatingDistance,const b3Transform& transA,const b3Transform& transB)
+ {
+ m_separatingDistance = separatingDistance;
+
+ if (m_separatingDistance>0.f)
+ {
+ m_separatingNormal = separatingVector;
+
+ const b3Vector3& toPosA = transA.getOrigin();
+ const b3Vector3& toPosB = transB.getOrigin();
+ b3Quaternion toOrnA = transA.getRotation();
+ b3Quaternion toOrnB = transB.getRotation();
+ m_posA = toPosA;
+ m_posB = toPosB;
+ m_ornA = toOrnA;
+ m_ornB = toOrnB;
+ }
+ }
+
+};
+
+
+#endif //B3_TRANSFORM_UTIL_H
+
diff --git a/thirdparty/bullet/src/Bullet3Common/b3Vector3.cpp b/thirdparty/bullet/src/Bullet3Common/b3Vector3.cpp
new file mode 100644
index 0000000000..5f5ac4ac04
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Common/b3Vector3.cpp
@@ -0,0 +1,1631 @@
+/*
+ Copyright (c) 2011-213 Apple 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.
+
+ This source version has been altered.
+ */
+
+#if defined (_WIN32) || defined (__i386__)
+#define B3_USE_SSE_IN_API
+#endif
+
+#include "b3Vector3.h"
+
+#if defined (B3_USE_SSE) || defined (B3_USE_NEON)
+
+#ifdef __APPLE__
+#include <stdint.h>
+typedef float float4 __attribute__ ((vector_size(16)));
+#else
+#define float4 __m128
+#endif
+//typedef uint32_t uint4 __attribute__ ((vector_size(16)));
+
+
+#if defined B3_USE_SSE || defined _WIN32
+
+#define LOG2_ARRAY_SIZE 6
+#define STACK_ARRAY_COUNT (1UL << LOG2_ARRAY_SIZE)
+
+#include <emmintrin.h>
+
+long b3_maxdot_large( const float *vv, const float *vec, unsigned long count, float *dotResult );
+long b3_maxdot_large( const float *vv, const float *vec, unsigned long count, float *dotResult )
+{
+ const float4 *vertices = (const float4*) vv;
+ static const unsigned char indexTable[16] = {(unsigned char)-1, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 };
+ float4 dotMax = b3Assign128( -B3_INFINITY, -B3_INFINITY, -B3_INFINITY, -B3_INFINITY );
+ float4 vvec = _mm_loadu_ps( vec );
+ float4 vHi = b3CastiTo128f(_mm_shuffle_epi32( b3CastfTo128i( vvec), 0xaa )); /// zzzz
+ float4 vLo = _mm_movelh_ps( vvec, vvec ); /// xyxy
+
+ long maxIndex = -1L;
+
+ size_t segment = 0;
+ float4 stack_array[ STACK_ARRAY_COUNT ];
+
+#if DEBUG
+ // memset( stack_array, -1, STACK_ARRAY_COUNT * sizeof(stack_array[0]) );
+#endif
+
+ size_t index;
+ float4 max;
+ // Faster loop without cleanup code for full tiles
+ for ( segment = 0; segment + STACK_ARRAY_COUNT*4 <= count; segment += STACK_ARRAY_COUNT*4 )
+ {
+ max = dotMax;
+
+ for( index = 0; index < STACK_ARRAY_COUNT; index+= 4 )
+ { // do four dot products at a time. Carefully avoid touching the w element.
+ float4 v0 = vertices[0];
+ float4 v1 = vertices[1];
+ float4 v2 = vertices[2];
+ float4 v3 = vertices[3]; vertices += 4;
+
+ float4 lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
+ float4 hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
+ float4 lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
+ float4 hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
+
+ lo0 = lo0*vLo;
+ lo1 = lo1*vLo;
+ float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z*vHi;
+ x = x+y;
+ x = x+z;
+ stack_array[index] = x;
+ max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3]; vertices += 4;
+
+ lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
+
+ lo0 = lo0*vLo;
+ lo1 = lo1*vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z*vHi;
+ x = x+y;
+ x = x+z;
+ stack_array[index+1] = x;
+ max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3]; vertices += 4;
+
+ lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
+
+ lo0 = lo0*vLo;
+ lo1 = lo1*vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z*vHi;
+ x = x+y;
+ x = x+z;
+ stack_array[index+2] = x;
+ max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3]; vertices += 4;
+
+ lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
+
+ lo0 = lo0*vLo;
+ lo1 = lo1*vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z*vHi;
+ x = x+y;
+ x = x+z;
+ stack_array[index+3] = x;
+ max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan
+
+ // It is too costly to keep the index of the max here. We will look for it again later. We save a lot of work this way.
+ }
+
+ // If we found a new max
+ if( 0xf != _mm_movemask_ps( (float4) _mm_cmpeq_ps(max, dotMax)))
+ {
+ // copy the new max across all lanes of our max accumulator
+ max = _mm_max_ps(max, (float4) _mm_shuffle_ps( max, max, 0x4e));
+ max = _mm_max_ps(max, (float4) _mm_shuffle_ps( max, max, 0xb1));
+
+ dotMax = max;
+
+ // find first occurrence of that max
+ size_t test;
+ for( index = 0; 0 == (test=_mm_movemask_ps( _mm_cmpeq_ps( stack_array[index], max))); index++ ) // local_count must be a multiple of 4
+ {}
+ // record where it is.
+ maxIndex = 4*index + segment + indexTable[test];
+ }
+ }
+
+ // account for work we've already done
+ count -= segment;
+
+ // Deal with the last < STACK_ARRAY_COUNT vectors
+ max = dotMax;
+ index = 0;
+
+
+ if( b3Unlikely( count > 16) )
+ {
+ for( ; index + 4 <= count / 4; index+=4 )
+ { // do four dot products at a time. Carefully avoid touching the w element.
+ float4 v0 = vertices[0];
+ float4 v1 = vertices[1];
+ float4 v2 = vertices[2];
+ float4 v3 = vertices[3]; vertices += 4;
+
+ float4 lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
+ float4 hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
+ float4 lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
+ float4 hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
+
+ lo0 = lo0*vLo;
+ lo1 = lo1*vLo;
+ float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z*vHi;
+ x = x+y;
+ x = x+z;
+ stack_array[index] = x;
+ max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3]; vertices += 4;
+
+ lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
+
+ lo0 = lo0*vLo;
+ lo1 = lo1*vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z*vHi;
+ x = x+y;
+ x = x+z;
+ stack_array[index+1] = x;
+ max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3]; vertices += 4;
+
+ lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
+
+ lo0 = lo0*vLo;
+ lo1 = lo1*vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z*vHi;
+ x = x+y;
+ x = x+z;
+ stack_array[index+2] = x;
+ max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3]; vertices += 4;
+
+ lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
+
+ lo0 = lo0*vLo;
+ lo1 = lo1*vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z*vHi;
+ x = x+y;
+ x = x+z;
+ stack_array[index+3] = x;
+ max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan
+
+ // It is too costly to keep the index of the max here. We will look for it again later. We save a lot of work this way.
+ }
+ }
+
+ size_t localCount = (count & -4L) - 4*index;
+ if( localCount )
+ {
+#ifdef __APPLE__
+ float4 t0, t1, t2, t3, t4;
+ float4 * sap = &stack_array[index + localCount / 4];
+ vertices += localCount; // counter the offset
+ size_t byteIndex = -(localCount) * sizeof(float);
+ //AT&T Code style assembly
+ asm volatile
+ ( ".align 4 \n\
+ 0: movaps %[max], %[t2] // move max out of the way to avoid propagating NaNs in max \n\
+ movaps (%[vertices], %[byteIndex], 4), %[t0] // vertices[0] \n\
+ movaps 16(%[vertices], %[byteIndex], 4), %[t1] // vertices[1] \n\
+ movaps %[t0], %[max] // vertices[0] \n\
+ movlhps %[t1], %[max] // x0y0x1y1 \n\
+ movaps 32(%[vertices], %[byteIndex], 4), %[t3] // vertices[2] \n\
+ movaps 48(%[vertices], %[byteIndex], 4), %[t4] // vertices[3] \n\
+ mulps %[vLo], %[max] // x0y0x1y1 * vLo \n\
+ movhlps %[t0], %[t1] // z0w0z1w1 \n\
+ movaps %[t3], %[t0] // vertices[2] \n\
+ movlhps %[t4], %[t0] // x2y2x3y3 \n\
+ mulps %[vLo], %[t0] // x2y2x3y3 * vLo \n\
+ movhlps %[t3], %[t4] // z2w2z3w3 \n\
+ shufps $0x88, %[t4], %[t1] // z0z1z2z3 \n\
+ mulps %[vHi], %[t1] // z0z1z2z3 * vHi \n\
+ movaps %[max], %[t3] // x0y0x1y1 * vLo \n\
+ shufps $0x88, %[t0], %[max] // x0x1x2x3 * vLo.x \n\
+ shufps $0xdd, %[t0], %[t3] // y0y1y2y3 * vLo.y \n\
+ addps %[t3], %[max] // x + y \n\
+ addps %[t1], %[max] // x + y + z \n\
+ movaps %[max], (%[sap], %[byteIndex]) // record result for later scrutiny \n\
+ maxps %[t2], %[max] // record max, restore max \n\
+ add $16, %[byteIndex] // advance loop counter\n\
+ jnz 0b \n\
+ "
+ : [max] "+x" (max), [t0] "=&x" (t0), [t1] "=&x" (t1), [t2] "=&x" (t2), [t3] "=&x" (t3), [t4] "=&x" (t4), [byteIndex] "+r" (byteIndex)
+ : [vLo] "x" (vLo), [vHi] "x" (vHi), [vertices] "r" (vertices), [sap] "r" (sap)
+ : "memory", "cc"
+ );
+ index += localCount/4;
+#else
+ {
+ for( unsigned int i=0; i<localCount/4; i++,index++)
+ { // do four dot products at a time. Carefully avoid touching the w element.
+ float4 v0 = vertices[0];
+ float4 v1 = vertices[1];
+ float4 v2 = vertices[2];
+ float4 v3 = vertices[3];
+ vertices += 4;
+
+ float4 lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
+ float4 hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
+ float4 lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
+ float4 hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
+
+ lo0 = lo0*vLo;
+ lo1 = lo1*vLo;
+ float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z*vHi;
+ x = x+y;
+ x = x+z;
+ stack_array[index] = x;
+ max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan
+ }
+ }
+#endif //__APPLE__
+ }
+
+ // process the last few points
+ if( count & 3 )
+ {
+ float4 v0, v1, v2, x, y, z;
+ switch( count & 3 )
+ {
+ case 3:
+ {
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+
+ // Calculate 3 dot products, transpose, duplicate v2
+ float4 lo0 = _mm_movelh_ps( v0, v1); // xyxy.lo
+ float4 hi0 = _mm_movehl_ps( v1, v0); // z?z?.lo
+ lo0 = lo0*vLo;
+ z = _mm_shuffle_ps(hi0, v2, 0xa8 ); // z0z1z2z2
+ z = z*vHi;
+ float4 lo1 = _mm_movelh_ps(v2, v2); // xyxy
+ lo1 = lo1*vLo;
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ }
+ break;
+ case 2:
+ {
+ v0 = vertices[0];
+ v1 = vertices[1];
+ float4 xy = _mm_movelh_ps(v0, v1);
+ z = _mm_movehl_ps(v1, v0);
+ xy = xy*vLo;
+ z = _mm_shuffle_ps( z, z, 0xa8);
+ x = _mm_shuffle_ps( xy, xy, 0xa8);
+ y = _mm_shuffle_ps( xy, xy, 0xfd);
+ z = z*vHi;
+ }
+ break;
+ case 1:
+ {
+ float4 xy = vertices[0];
+ z = _mm_shuffle_ps( xy, xy, 0xaa);
+ xy = xy*vLo;
+ z = z*vHi;
+ x = _mm_shuffle_ps(xy, xy, 0);
+ y = _mm_shuffle_ps(xy, xy, 0x55);
+ }
+ break;
+ }
+ x = x+y;
+ x = x+z;
+ stack_array[index] = x;
+ max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan
+ index++;
+ }
+
+ // if we found a new max.
+ if( 0 == segment || 0xf != _mm_movemask_ps( (float4) _mm_cmpeq_ps(max, dotMax)))
+ { // we found a new max. Search for it
+ // find max across the max vector, place in all elements of max -- big latency hit here
+ max = _mm_max_ps(max, (float4) _mm_shuffle_ps( max, max, 0x4e));
+ max = _mm_max_ps(max, (float4) _mm_shuffle_ps( max, max, 0xb1));
+
+ // It is slightly faster to do this part in scalar code when count < 8. However, the common case for
+ // this where it actually makes a difference is handled in the early out at the top of the function,
+ // so it is less than a 1% difference here. I opted for improved code size, fewer branches and reduced
+ // complexity, and removed it.
+
+ dotMax = max;
+
+ // scan for the first occurence of max in the array
+ size_t test;
+ for( index = 0; 0 == (test=_mm_movemask_ps( _mm_cmpeq_ps( stack_array[index], max))); index++ ) // local_count must be a multiple of 4
+ {}
+ maxIndex = 4*index + segment + indexTable[test];
+ }
+
+ _mm_store_ss( dotResult, dotMax);
+ return maxIndex;
+}
+
+long b3_mindot_large( const float *vv, const float *vec, unsigned long count, float *dotResult );
+
+long b3_mindot_large( const float *vv, const float *vec, unsigned long count, float *dotResult )
+{
+ const float4 *vertices = (const float4*) vv;
+ static const unsigned char indexTable[16] = {(unsigned char)-1, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 };
+
+ float4 dotmin = b3Assign128( B3_INFINITY, B3_INFINITY, B3_INFINITY, B3_INFINITY );
+ float4 vvec = _mm_loadu_ps( vec );
+ float4 vHi = b3CastiTo128f(_mm_shuffle_epi32( b3CastfTo128i( vvec), 0xaa )); /// zzzz
+ float4 vLo = _mm_movelh_ps( vvec, vvec ); /// xyxy
+
+ long minIndex = -1L;
+
+ size_t segment = 0;
+ float4 stack_array[ STACK_ARRAY_COUNT ];
+
+#if DEBUG
+ // memset( stack_array, -1, STACK_ARRAY_COUNT * sizeof(stack_array[0]) );
+#endif
+
+ size_t index;
+ float4 min;
+ // Faster loop without cleanup code for full tiles
+ for ( segment = 0; segment + STACK_ARRAY_COUNT*4 <= count; segment += STACK_ARRAY_COUNT*4 )
+ {
+ min = dotmin;
+
+ for( index = 0; index < STACK_ARRAY_COUNT; index+= 4 )
+ { // do four dot products at a time. Carefully avoid touching the w element.
+ float4 v0 = vertices[0];
+ float4 v1 = vertices[1];
+ float4 v2 = vertices[2];
+ float4 v3 = vertices[3]; vertices += 4;
+
+ float4 lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
+ float4 hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
+ float4 lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
+ float4 hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
+
+ lo0 = lo0*vLo;
+ lo1 = lo1*vLo;
+ float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z*vHi;
+ x = x+y;
+ x = x+z;
+ stack_array[index] = x;
+ min = _mm_min_ps( x, min ); // control the order here so that min is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3]; vertices += 4;
+
+ lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
+
+ lo0 = lo0*vLo;
+ lo1 = lo1*vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z*vHi;
+ x = x+y;
+ x = x+z;
+ stack_array[index+1] = x;
+ min = _mm_min_ps( x, min ); // control the order here so that min is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3]; vertices += 4;
+
+ lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
+
+ lo0 = lo0*vLo;
+ lo1 = lo1*vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z*vHi;
+ x = x+y;
+ x = x+z;
+ stack_array[index+2] = x;
+ min = _mm_min_ps( x, min ); // control the order here so that min is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3]; vertices += 4;
+
+ lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
+
+ lo0 = lo0*vLo;
+ lo1 = lo1*vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z*vHi;
+ x = x+y;
+ x = x+z;
+ stack_array[index+3] = x;
+ min = _mm_min_ps( x, min ); // control the order here so that min is never NaN even if x is nan
+
+ // It is too costly to keep the index of the min here. We will look for it again later. We save a lot of work this way.
+ }
+
+ // If we found a new min
+ if( 0xf != _mm_movemask_ps( (float4) _mm_cmpeq_ps(min, dotmin)))
+ {
+ // copy the new min across all lanes of our min accumulator
+ min = _mm_min_ps(min, (float4) _mm_shuffle_ps( min, min, 0x4e));
+ min = _mm_min_ps(min, (float4) _mm_shuffle_ps( min, min, 0xb1));
+
+ dotmin = min;
+
+ // find first occurrence of that min
+ size_t test;
+ for( index = 0; 0 == (test=_mm_movemask_ps( _mm_cmpeq_ps( stack_array[index], min))); index++ ) // local_count must be a multiple of 4
+ {}
+ // record where it is.
+ minIndex = 4*index + segment + indexTable[test];
+ }
+ }
+
+ // account for work we've already done
+ count -= segment;
+
+ // Deal with the last < STACK_ARRAY_COUNT vectors
+ min = dotmin;
+ index = 0;
+
+
+ if(b3Unlikely( count > 16) )
+ {
+ for( ; index + 4 <= count / 4; index+=4 )
+ { // do four dot products at a time. Carefully avoid touching the w element.
+ float4 v0 = vertices[0];
+ float4 v1 = vertices[1];
+ float4 v2 = vertices[2];
+ float4 v3 = vertices[3]; vertices += 4;
+
+ float4 lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
+ float4 hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
+ float4 lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
+ float4 hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
+
+ lo0 = lo0*vLo;
+ lo1 = lo1*vLo;
+ float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z*vHi;
+ x = x+y;
+ x = x+z;
+ stack_array[index] = x;
+ min = _mm_min_ps( x, min ); // control the order here so that min is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3]; vertices += 4;
+
+ lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
+
+ lo0 = lo0*vLo;
+ lo1 = lo1*vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z*vHi;
+ x = x+y;
+ x = x+z;
+ stack_array[index+1] = x;
+ min = _mm_min_ps( x, min ); // control the order here so that min is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3]; vertices += 4;
+
+ lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
+
+ lo0 = lo0*vLo;
+ lo1 = lo1*vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z*vHi;
+ x = x+y;
+ x = x+z;
+ stack_array[index+2] = x;
+ min = _mm_min_ps( x, min ); // control the order here so that min is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3]; vertices += 4;
+
+ lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
+
+ lo0 = lo0*vLo;
+ lo1 = lo1*vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z*vHi;
+ x = x+y;
+ x = x+z;
+ stack_array[index+3] = x;
+ min = _mm_min_ps( x, min ); // control the order here so that min is never NaN even if x is nan
+
+ // It is too costly to keep the index of the min here. We will look for it again later. We save a lot of work this way.
+ }
+ }
+
+ size_t localCount = (count & -4L) - 4*index;
+ if( localCount )
+ {
+
+
+#ifdef __APPLE__
+ vertices += localCount; // counter the offset
+ float4 t0, t1, t2, t3, t4;
+ size_t byteIndex = -(localCount) * sizeof(float);
+ float4 * sap = &stack_array[index + localCount / 4];
+
+ asm volatile
+ ( ".align 4 \n\
+ 0: movaps %[min], %[t2] // move min out of the way to avoid propagating NaNs in min \n\
+ movaps (%[vertices], %[byteIndex], 4), %[t0] // vertices[0] \n\
+ movaps 16(%[vertices], %[byteIndex], 4), %[t1] // vertices[1] \n\
+ movaps %[t0], %[min] // vertices[0] \n\
+ movlhps %[t1], %[min] // x0y0x1y1 \n\
+ movaps 32(%[vertices], %[byteIndex], 4), %[t3] // vertices[2] \n\
+ movaps 48(%[vertices], %[byteIndex], 4), %[t4] // vertices[3] \n\
+ mulps %[vLo], %[min] // x0y0x1y1 * vLo \n\
+ movhlps %[t0], %[t1] // z0w0z1w1 \n\
+ movaps %[t3], %[t0] // vertices[2] \n\
+ movlhps %[t4], %[t0] // x2y2x3y3 \n\
+ movhlps %[t3], %[t4] // z2w2z3w3 \n\
+ mulps %[vLo], %[t0] // x2y2x3y3 * vLo \n\
+ shufps $0x88, %[t4], %[t1] // z0z1z2z3 \n\
+ mulps %[vHi], %[t1] // z0z1z2z3 * vHi \n\
+ movaps %[min], %[t3] // x0y0x1y1 * vLo \n\
+ shufps $0x88, %[t0], %[min] // x0x1x2x3 * vLo.x \n\
+ shufps $0xdd, %[t0], %[t3] // y0y1y2y3 * vLo.y \n\
+ addps %[t3], %[min] // x + y \n\
+ addps %[t1], %[min] // x + y + z \n\
+ movaps %[min], (%[sap], %[byteIndex]) // record result for later scrutiny \n\
+ minps %[t2], %[min] // record min, restore min \n\
+ add $16, %[byteIndex] // advance loop counter\n\
+ jnz 0b \n\
+ "
+ : [min] "+x" (min), [t0] "=&x" (t0), [t1] "=&x" (t1), [t2] "=&x" (t2), [t3] "=&x" (t3), [t4] "=&x" (t4), [byteIndex] "+r" (byteIndex)
+ : [vLo] "x" (vLo), [vHi] "x" (vHi), [vertices] "r" (vertices), [sap] "r" (sap)
+ : "memory", "cc"
+ );
+ index += localCount/4;
+#else
+ {
+ for( unsigned int i=0; i<localCount/4; i++,index++)
+ { // do four dot products at a time. Carefully avoid touching the w element.
+ float4 v0 = vertices[0];
+ float4 v1 = vertices[1];
+ float4 v2 = vertices[2];
+ float4 v3 = vertices[3];
+ vertices += 4;
+
+ float4 lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
+ float4 hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
+ float4 lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
+ float4 hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
+
+ lo0 = lo0*vLo;
+ lo1 = lo1*vLo;
+ float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z*vHi;
+ x = x+y;
+ x = x+z;
+ stack_array[index] = x;
+ min = _mm_min_ps( x, min ); // control the order here so that max is never NaN even if x is nan
+ }
+ }
+
+#endif
+ }
+
+ // process the last few points
+ if( count & 3 )
+ {
+ float4 v0, v1, v2, x, y, z;
+ switch( count & 3 )
+ {
+ case 3:
+ {
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+
+ // Calculate 3 dot products, transpose, duplicate v2
+ float4 lo0 = _mm_movelh_ps( v0, v1); // xyxy.lo
+ float4 hi0 = _mm_movehl_ps( v1, v0); // z?z?.lo
+ lo0 = lo0*vLo;
+ z = _mm_shuffle_ps(hi0, v2, 0xa8 ); // z0z1z2z2
+ z = z*vHi;
+ float4 lo1 = _mm_movelh_ps(v2, v2); // xyxy
+ lo1 = lo1*vLo;
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ }
+ break;
+ case 2:
+ {
+ v0 = vertices[0];
+ v1 = vertices[1];
+ float4 xy = _mm_movelh_ps(v0, v1);
+ z = _mm_movehl_ps(v1, v0);
+ xy = xy*vLo;
+ z = _mm_shuffle_ps( z, z, 0xa8);
+ x = _mm_shuffle_ps( xy, xy, 0xa8);
+ y = _mm_shuffle_ps( xy, xy, 0xfd);
+ z = z*vHi;
+ }
+ break;
+ case 1:
+ {
+ float4 xy = vertices[0];
+ z = _mm_shuffle_ps( xy, xy, 0xaa);
+ xy = xy*vLo;
+ z = z*vHi;
+ x = _mm_shuffle_ps(xy, xy, 0);
+ y = _mm_shuffle_ps(xy, xy, 0x55);
+ }
+ break;
+ }
+ x = x+y;
+ x = x+z;
+ stack_array[index] = x;
+ min = _mm_min_ps( x, min ); // control the order here so that min is never NaN even if x is nan
+ index++;
+ }
+
+ // if we found a new min.
+ if( 0 == segment || 0xf != _mm_movemask_ps( (float4) _mm_cmpeq_ps(min, dotmin)))
+ { // we found a new min. Search for it
+ // find min across the min vector, place in all elements of min -- big latency hit here
+ min = _mm_min_ps(min, (float4) _mm_shuffle_ps( min, min, 0x4e));
+ min = _mm_min_ps(min, (float4) _mm_shuffle_ps( min, min, 0xb1));
+
+ // It is slightly faster to do this part in scalar code when count < 8. However, the common case for
+ // this where it actually makes a difference is handled in the early out at the top of the function,
+ // so it is less than a 1% difference here. I opted for improved code size, fewer branches and reduced
+ // complexity, and removed it.
+
+ dotmin = min;
+
+ // scan for the first occurence of min in the array
+ size_t test;
+ for( index = 0; 0 == (test=_mm_movemask_ps( _mm_cmpeq_ps( stack_array[index], min))); index++ ) // local_count must be a multiple of 4
+ {}
+ minIndex = 4*index + segment + indexTable[test];
+ }
+
+ _mm_store_ss( dotResult, dotmin);
+ return minIndex;
+}
+
+
+#elif defined B3_USE_NEON
+#define ARM_NEON_GCC_COMPATIBILITY 1
+#include <arm_neon.h>
+
+
+static long b3_maxdot_large_v0( const float *vv, const float *vec, unsigned long count, float *dotResult );
+static long b3_maxdot_large_v1( const float *vv, const float *vec, unsigned long count, float *dotResult );
+static long b3_maxdot_large_sel( const float *vv, const float *vec, unsigned long count, float *dotResult );
+static long b3_mindot_large_v0( const float *vv, const float *vec, unsigned long count, float *dotResult );
+static long b3_mindot_large_v1( const float *vv, const float *vec, unsigned long count, float *dotResult );
+static long b3_mindot_large_sel( const float *vv, const float *vec, unsigned long count, float *dotResult );
+
+long (*b3_maxdot_large)( const float *vv, const float *vec, unsigned long count, float *dotResult ) = b3_maxdot_large_sel;
+long (*b3_mindot_large)( const float *vv, const float *vec, unsigned long count, float *dotResult ) = b3_mindot_large_sel;
+
+extern "C" {int _get_cpu_capabilities( void );}
+
+static long b3_maxdot_large_sel( const float *vv, const float *vec, unsigned long count, float *dotResult )
+{
+ if( _get_cpu_capabilities() & 0x2000 )
+ b3_maxdot_large = _maxdot_large_v1;
+ else
+ b3_maxdot_large = _maxdot_large_v0;
+
+ return b3_maxdot_large(vv, vec, count, dotResult);
+}
+
+static long b3_mindot_large_sel( const float *vv, const float *vec, unsigned long count, float *dotResult )
+{
+ if( _get_cpu_capabilities() & 0x2000 )
+ b3_mindot_large = _mindot_large_v1;
+ else
+ b3_mindot_large = _mindot_large_v0;
+
+ return b3_mindot_large(vv, vec, count, dotResult);
+}
+
+
+
+#define vld1q_f32_aligned_postincrement( _ptr ) ({ float32x4_t _r; asm( "vld1.f32 {%0}, [%1, :128]!\n" : "=w" (_r), "+r" (_ptr) ); /*return*/ _r; })
+
+
+long b3_maxdot_large_v0( const float *vv, const float *vec, unsigned long count, float *dotResult )
+{
+ unsigned long i = 0;
+ float32x4_t vvec = vld1q_f32_aligned_postincrement( vec );
+ float32x2_t vLo = vget_low_f32(vvec);
+ float32x2_t vHi = vdup_lane_f32(vget_high_f32(vvec), 0);
+ float32x2_t dotMaxLo = (float32x2_t) { -B3_INFINITY, -B3_INFINITY };
+ float32x2_t dotMaxHi = (float32x2_t) { -B3_INFINITY, -B3_INFINITY };
+ uint32x2_t indexLo = (uint32x2_t) {0, 1};
+ uint32x2_t indexHi = (uint32x2_t) {2, 3};
+ uint32x2_t iLo = (uint32x2_t) {-1, -1};
+ uint32x2_t iHi = (uint32x2_t) {-1, -1};
+ const uint32x2_t four = (uint32x2_t) {4,4};
+
+ for( ; i+8 <= count; i+= 8 )
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v3 = vld1q_f32_aligned_postincrement( vv );
+
+ float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo);
+ float32x2_t xy1 = vmul_f32( vget_low_f32(v1), vLo);
+ float32x2_t xy2 = vmul_f32( vget_low_f32(v2), vLo);
+ float32x2_t xy3 = vmul_f32( vget_low_f32(v3), vLo);
+
+ float32x2x2_t z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1));
+ float32x2x2_t z1 = vtrn_f32( vget_high_f32(v2), vget_high_f32(v3));
+ float32x2_t zLo = vmul_f32( z0.val[0], vHi);
+ float32x2_t zHi = vmul_f32( z1.val[0], vHi);
+
+ float32x2_t rLo = vpadd_f32( xy0, xy1);
+ float32x2_t rHi = vpadd_f32( xy2, xy3);
+ rLo = vadd_f32(rLo, zLo);
+ rHi = vadd_f32(rHi, zHi);
+
+ uint32x2_t maskLo = vcgt_f32( rLo, dotMaxLo );
+ uint32x2_t maskHi = vcgt_f32( rHi, dotMaxHi );
+ dotMaxLo = vbsl_f32( maskLo, rLo, dotMaxLo);
+ dotMaxHi = vbsl_f32( maskHi, rHi, dotMaxHi);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ iHi = vbsl_u32(maskHi, indexHi, iHi);
+ indexLo = vadd_u32(indexLo, four);
+ indexHi = vadd_u32(indexHi, four);
+
+ v0 = vld1q_f32_aligned_postincrement( vv );
+ v1 = vld1q_f32_aligned_postincrement( vv );
+ v2 = vld1q_f32_aligned_postincrement( vv );
+ v3 = vld1q_f32_aligned_postincrement( vv );
+
+ xy0 = vmul_f32( vget_low_f32(v0), vLo);
+ xy1 = vmul_f32( vget_low_f32(v1), vLo);
+ xy2 = vmul_f32( vget_low_f32(v2), vLo);
+ xy3 = vmul_f32( vget_low_f32(v3), vLo);
+
+ z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1));
+ z1 = vtrn_f32( vget_high_f32(v2), vget_high_f32(v3));
+ zLo = vmul_f32( z0.val[0], vHi);
+ zHi = vmul_f32( z1.val[0], vHi);
+
+ rLo = vpadd_f32( xy0, xy1);
+ rHi = vpadd_f32( xy2, xy3);
+ rLo = vadd_f32(rLo, zLo);
+ rHi = vadd_f32(rHi, zHi);
+
+ maskLo = vcgt_f32( rLo, dotMaxLo );
+ maskHi = vcgt_f32( rHi, dotMaxHi );
+ dotMaxLo = vbsl_f32( maskLo, rLo, dotMaxLo);
+ dotMaxHi = vbsl_f32( maskHi, rHi, dotMaxHi);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ iHi = vbsl_u32(maskHi, indexHi, iHi);
+ indexLo = vadd_u32(indexLo, four);
+ indexHi = vadd_u32(indexHi, four);
+ }
+
+ for( ; i+4 <= count; i+= 4 )
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v3 = vld1q_f32_aligned_postincrement( vv );
+
+ float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo);
+ float32x2_t xy1 = vmul_f32( vget_low_f32(v1), vLo);
+ float32x2_t xy2 = vmul_f32( vget_low_f32(v2), vLo);
+ float32x2_t xy3 = vmul_f32( vget_low_f32(v3), vLo);
+
+ float32x2x2_t z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1));
+ float32x2x2_t z1 = vtrn_f32( vget_high_f32(v2), vget_high_f32(v3));
+ float32x2_t zLo = vmul_f32( z0.val[0], vHi);
+ float32x2_t zHi = vmul_f32( z1.val[0], vHi);
+
+ float32x2_t rLo = vpadd_f32( xy0, xy1);
+ float32x2_t rHi = vpadd_f32( xy2, xy3);
+ rLo = vadd_f32(rLo, zLo);
+ rHi = vadd_f32(rHi, zHi);
+
+ uint32x2_t maskLo = vcgt_f32( rLo, dotMaxLo );
+ uint32x2_t maskHi = vcgt_f32( rHi, dotMaxHi );
+ dotMaxLo = vbsl_f32( maskLo, rLo, dotMaxLo);
+ dotMaxHi = vbsl_f32( maskHi, rHi, dotMaxHi);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ iHi = vbsl_u32(maskHi, indexHi, iHi);
+ indexLo = vadd_u32(indexLo, four);
+ indexHi = vadd_u32(indexHi, four);
+ }
+
+ switch( count & 3 )
+ {
+ case 3:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
+
+ float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo);
+ float32x2_t xy1 = vmul_f32( vget_low_f32(v1), vLo);
+ float32x2_t xy2 = vmul_f32( vget_low_f32(v2), vLo);
+
+ float32x2x2_t z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1));
+ float32x2_t zLo = vmul_f32( z0.val[0], vHi);
+ float32x2_t zHi = vmul_f32( vdup_lane_f32(vget_high_f32(v2), 0), vHi);
+
+ float32x2_t rLo = vpadd_f32( xy0, xy1);
+ float32x2_t rHi = vpadd_f32( xy2, xy2);
+ rLo = vadd_f32(rLo, zLo);
+ rHi = vadd_f32(rHi, zHi);
+
+ uint32x2_t maskLo = vcgt_f32( rLo, dotMaxLo );
+ uint32x2_t maskHi = vcgt_f32( rHi, dotMaxHi );
+ dotMaxLo = vbsl_f32( maskLo, rLo, dotMaxLo);
+ dotMaxHi = vbsl_f32( maskHi, rHi, dotMaxHi);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ iHi = vbsl_u32(maskHi, indexHi, iHi);
+ }
+ break;
+ case 2:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
+
+ float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo);
+ float32x2_t xy1 = vmul_f32( vget_low_f32(v1), vLo);
+
+ float32x2x2_t z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1));
+ float32x2_t zLo = vmul_f32( z0.val[0], vHi);
+
+ float32x2_t rLo = vpadd_f32( xy0, xy1);
+ rLo = vadd_f32(rLo, zLo);
+
+ uint32x2_t maskLo = vcgt_f32( rLo, dotMaxLo );
+ dotMaxLo = vbsl_f32( maskLo, rLo, dotMaxLo);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ }
+ break;
+ case 1:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+ float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo);
+ float32x2_t z0 = vdup_lane_f32(vget_high_f32(v0), 0);
+ float32x2_t zLo = vmul_f32( z0, vHi);
+ float32x2_t rLo = vpadd_f32( xy0, xy0);
+ rLo = vadd_f32(rLo, zLo);
+ uint32x2_t maskLo = vcgt_f32( rLo, dotMaxLo );
+ dotMaxLo = vbsl_f32( maskLo, rLo, dotMaxLo);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ // select best answer between hi and lo results
+ uint32x2_t mask = vcgt_f32( dotMaxHi, dotMaxLo );
+ dotMaxLo = vbsl_f32(mask, dotMaxHi, dotMaxLo);
+ iLo = vbsl_u32(mask, iHi, iLo);
+
+ // select best answer between even and odd results
+ dotMaxHi = vdup_lane_f32(dotMaxLo, 1);
+ iHi = vdup_lane_u32(iLo, 1);
+ mask = vcgt_f32( dotMaxHi, dotMaxLo );
+ dotMaxLo = vbsl_f32(mask, dotMaxHi, dotMaxLo);
+ iLo = vbsl_u32(mask, iHi, iLo);
+
+ *dotResult = vget_lane_f32( dotMaxLo, 0);
+ return vget_lane_u32(iLo, 0);
+}
+
+
+long b3_maxdot_large_v1( const float *vv, const float *vec, unsigned long count, float *dotResult )
+{
+ float32x4_t vvec = vld1q_f32_aligned_postincrement( vec );
+ float32x4_t vLo = vcombine_f32(vget_low_f32(vvec), vget_low_f32(vvec));
+ float32x4_t vHi = vdupq_lane_f32(vget_high_f32(vvec), 0);
+ const uint32x4_t four = (uint32x4_t){ 4, 4, 4, 4 };
+ uint32x4_t local_index = (uint32x4_t) {0, 1, 2, 3};
+ uint32x4_t index = (uint32x4_t) { -1, -1, -1, -1 };
+ float32x4_t maxDot = (float32x4_t) { -B3_INFINITY, -B3_INFINITY, -B3_INFINITY, -B3_INFINITY };
+
+ unsigned long i = 0;
+ for( ; i + 8 <= count; i += 8 )
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v3 = vld1q_f32_aligned_postincrement( vv );
+
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1));
+ float32x4_t xy1 = vcombine_f32( vget_low_f32(v2), vget_low_f32(v3));
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1));
+ float32x4_t z1 = vcombine_f32( vget_high_f32(v2), vget_high_f32(v3));
+
+ xy0 = vmulq_f32(xy0, vLo);
+ xy1 = vmulq_f32(xy1, vLo);
+
+ float32x4x2_t zb = vuzpq_f32( z0, z1);
+ float32x4_t z = vmulq_f32( zb.val[0], vHi);
+ float32x4x2_t xy = vuzpq_f32( xy0, xy1);
+ float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ uint32x4_t mask = vcgtq_f32(x, maxDot);
+ maxDot = vbslq_f32( mask, x, maxDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+
+ v0 = vld1q_f32_aligned_postincrement( vv );
+ v1 = vld1q_f32_aligned_postincrement( vv );
+ v2 = vld1q_f32_aligned_postincrement( vv );
+ v3 = vld1q_f32_aligned_postincrement( vv );
+
+ // the next two lines should resolve to a single vswp d, d
+ xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1));
+ xy1 = vcombine_f32( vget_low_f32(v2), vget_low_f32(v3));
+ // the next two lines should resolve to a single vswp d, d
+ z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1));
+ z1 = vcombine_f32( vget_high_f32(v2), vget_high_f32(v3));
+
+ xy0 = vmulq_f32(xy0, vLo);
+ xy1 = vmulq_f32(xy1, vLo);
+
+ zb = vuzpq_f32( z0, z1);
+ z = vmulq_f32( zb.val[0], vHi);
+ xy = vuzpq_f32( xy0, xy1);
+ x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ mask = vcgtq_f32(x, maxDot);
+ maxDot = vbslq_f32( mask, x, maxDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+ }
+
+ for( ; i + 4 <= count; i += 4 )
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v3 = vld1q_f32_aligned_postincrement( vv );
+
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1));
+ float32x4_t xy1 = vcombine_f32( vget_low_f32(v2), vget_low_f32(v3));
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1));
+ float32x4_t z1 = vcombine_f32( vget_high_f32(v2), vget_high_f32(v3));
+
+ xy0 = vmulq_f32(xy0, vLo);
+ xy1 = vmulq_f32(xy1, vLo);
+
+ float32x4x2_t zb = vuzpq_f32( z0, z1);
+ float32x4_t z = vmulq_f32( zb.val[0], vHi);
+ float32x4x2_t xy = vuzpq_f32( xy0, xy1);
+ float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ uint32x4_t mask = vcgtq_f32(x, maxDot);
+ maxDot = vbslq_f32( mask, x, maxDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+ }
+
+ switch (count & 3) {
+ case 3:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
+
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1));
+ float32x4_t xy1 = vcombine_f32( vget_low_f32(v2), vget_low_f32(v2));
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1));
+ float32x4_t z1 = vcombine_f32( vget_high_f32(v2), vget_high_f32(v2));
+
+ xy0 = vmulq_f32(xy0, vLo);
+ xy1 = vmulq_f32(xy1, vLo);
+
+ float32x4x2_t zb = vuzpq_f32( z0, z1);
+ float32x4_t z = vmulq_f32( zb.val[0], vHi);
+ float32x4x2_t xy = vuzpq_f32( xy0, xy1);
+ float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ uint32x4_t mask = vcgtq_f32(x, maxDot);
+ maxDot = vbslq_f32( mask, x, maxDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+ }
+ break;
+
+ case 2:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
+
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1));
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1));
+
+ xy0 = vmulq_f32(xy0, vLo);
+
+ float32x4x2_t zb = vuzpq_f32( z0, z0);
+ float32x4_t z = vmulq_f32( zb.val[0], vHi);
+ float32x4x2_t xy = vuzpq_f32( xy0, xy0);
+ float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ uint32x4_t mask = vcgtq_f32(x, maxDot);
+ maxDot = vbslq_f32( mask, x, maxDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+ }
+ break;
+
+ case 1:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v0));
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t z = vdupq_lane_f32(vget_high_f32(v0), 0);
+
+ xy0 = vmulq_f32(xy0, vLo);
+
+ z = vmulq_f32( z, vHi);
+ float32x4x2_t xy = vuzpq_f32( xy0, xy0);
+ float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ uint32x4_t mask = vcgtq_f32(x, maxDot);
+ maxDot = vbslq_f32( mask, x, maxDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+
+ // select best answer between hi and lo results
+ uint32x2_t mask = vcgt_f32( vget_high_f32(maxDot), vget_low_f32(maxDot));
+ float32x2_t maxDot2 = vbsl_f32(mask, vget_high_f32(maxDot), vget_low_f32(maxDot));
+ uint32x2_t index2 = vbsl_u32(mask, vget_high_u32(index), vget_low_u32(index));
+
+ // select best answer between even and odd results
+ float32x2_t maxDotO = vdup_lane_f32(maxDot2, 1);
+ uint32x2_t indexHi = vdup_lane_u32(index2, 1);
+ mask = vcgt_f32( maxDotO, maxDot2 );
+ maxDot2 = vbsl_f32(mask, maxDotO, maxDot2);
+ index2 = vbsl_u32(mask, indexHi, index2);
+
+ *dotResult = vget_lane_f32( maxDot2, 0);
+ return vget_lane_u32(index2, 0);
+
+}
+
+long b3_mindot_large_v0( const float *vv, const float *vec, unsigned long count, float *dotResult )
+{
+ unsigned long i = 0;
+ float32x4_t vvec = vld1q_f32_aligned_postincrement( vec );
+ float32x2_t vLo = vget_low_f32(vvec);
+ float32x2_t vHi = vdup_lane_f32(vget_high_f32(vvec), 0);
+ float32x2_t dotMinLo = (float32x2_t) { B3_INFINITY, B3_INFINITY };
+ float32x2_t dotMinHi = (float32x2_t) { B3_INFINITY, B3_INFINITY };
+ uint32x2_t indexLo = (uint32x2_t) {0, 1};
+ uint32x2_t indexHi = (uint32x2_t) {2, 3};
+ uint32x2_t iLo = (uint32x2_t) {-1, -1};
+ uint32x2_t iHi = (uint32x2_t) {-1, -1};
+ const uint32x2_t four = (uint32x2_t) {4,4};
+
+ for( ; i+8 <= count; i+= 8 )
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v3 = vld1q_f32_aligned_postincrement( vv );
+
+ float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo);
+ float32x2_t xy1 = vmul_f32( vget_low_f32(v1), vLo);
+ float32x2_t xy2 = vmul_f32( vget_low_f32(v2), vLo);
+ float32x2_t xy3 = vmul_f32( vget_low_f32(v3), vLo);
+
+ float32x2x2_t z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1));
+ float32x2x2_t z1 = vtrn_f32( vget_high_f32(v2), vget_high_f32(v3));
+ float32x2_t zLo = vmul_f32( z0.val[0], vHi);
+ float32x2_t zHi = vmul_f32( z1.val[0], vHi);
+
+ float32x2_t rLo = vpadd_f32( xy0, xy1);
+ float32x2_t rHi = vpadd_f32( xy2, xy3);
+ rLo = vadd_f32(rLo, zLo);
+ rHi = vadd_f32(rHi, zHi);
+
+ uint32x2_t maskLo = vclt_f32( rLo, dotMinLo );
+ uint32x2_t maskHi = vclt_f32( rHi, dotMinHi );
+ dotMinLo = vbsl_f32( maskLo, rLo, dotMinLo);
+ dotMinHi = vbsl_f32( maskHi, rHi, dotMinHi);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ iHi = vbsl_u32(maskHi, indexHi, iHi);
+ indexLo = vadd_u32(indexLo, four);
+ indexHi = vadd_u32(indexHi, four);
+
+ v0 = vld1q_f32_aligned_postincrement( vv );
+ v1 = vld1q_f32_aligned_postincrement( vv );
+ v2 = vld1q_f32_aligned_postincrement( vv );
+ v3 = vld1q_f32_aligned_postincrement( vv );
+
+ xy0 = vmul_f32( vget_low_f32(v0), vLo);
+ xy1 = vmul_f32( vget_low_f32(v1), vLo);
+ xy2 = vmul_f32( vget_low_f32(v2), vLo);
+ xy3 = vmul_f32( vget_low_f32(v3), vLo);
+
+ z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1));
+ z1 = vtrn_f32( vget_high_f32(v2), vget_high_f32(v3));
+ zLo = vmul_f32( z0.val[0], vHi);
+ zHi = vmul_f32( z1.val[0], vHi);
+
+ rLo = vpadd_f32( xy0, xy1);
+ rHi = vpadd_f32( xy2, xy3);
+ rLo = vadd_f32(rLo, zLo);
+ rHi = vadd_f32(rHi, zHi);
+
+ maskLo = vclt_f32( rLo, dotMinLo );
+ maskHi = vclt_f32( rHi, dotMinHi );
+ dotMinLo = vbsl_f32( maskLo, rLo, dotMinLo);
+ dotMinHi = vbsl_f32( maskHi, rHi, dotMinHi);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ iHi = vbsl_u32(maskHi, indexHi, iHi);
+ indexLo = vadd_u32(indexLo, four);
+ indexHi = vadd_u32(indexHi, four);
+ }
+
+ for( ; i+4 <= count; i+= 4 )
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v3 = vld1q_f32_aligned_postincrement( vv );
+
+ float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo);
+ float32x2_t xy1 = vmul_f32( vget_low_f32(v1), vLo);
+ float32x2_t xy2 = vmul_f32( vget_low_f32(v2), vLo);
+ float32x2_t xy3 = vmul_f32( vget_low_f32(v3), vLo);
+
+ float32x2x2_t z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1));
+ float32x2x2_t z1 = vtrn_f32( vget_high_f32(v2), vget_high_f32(v3));
+ float32x2_t zLo = vmul_f32( z0.val[0], vHi);
+ float32x2_t zHi = vmul_f32( z1.val[0], vHi);
+
+ float32x2_t rLo = vpadd_f32( xy0, xy1);
+ float32x2_t rHi = vpadd_f32( xy2, xy3);
+ rLo = vadd_f32(rLo, zLo);
+ rHi = vadd_f32(rHi, zHi);
+
+ uint32x2_t maskLo = vclt_f32( rLo, dotMinLo );
+ uint32x2_t maskHi = vclt_f32( rHi, dotMinHi );
+ dotMinLo = vbsl_f32( maskLo, rLo, dotMinLo);
+ dotMinHi = vbsl_f32( maskHi, rHi, dotMinHi);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ iHi = vbsl_u32(maskHi, indexHi, iHi);
+ indexLo = vadd_u32(indexLo, four);
+ indexHi = vadd_u32(indexHi, four);
+ }
+ switch( count & 3 )
+ {
+ case 3:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
+
+ float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo);
+ float32x2_t xy1 = vmul_f32( vget_low_f32(v1), vLo);
+ float32x2_t xy2 = vmul_f32( vget_low_f32(v2), vLo);
+
+ float32x2x2_t z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1));
+ float32x2_t zLo = vmul_f32( z0.val[0], vHi);
+ float32x2_t zHi = vmul_f32( vdup_lane_f32(vget_high_f32(v2), 0), vHi);
+
+ float32x2_t rLo = vpadd_f32( xy0, xy1);
+ float32x2_t rHi = vpadd_f32( xy2, xy2);
+ rLo = vadd_f32(rLo, zLo);
+ rHi = vadd_f32(rHi, zHi);
+
+ uint32x2_t maskLo = vclt_f32( rLo, dotMinLo );
+ uint32x2_t maskHi = vclt_f32( rHi, dotMinHi );
+ dotMinLo = vbsl_f32( maskLo, rLo, dotMinLo);
+ dotMinHi = vbsl_f32( maskHi, rHi, dotMinHi);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ iHi = vbsl_u32(maskHi, indexHi, iHi);
+ }
+ break;
+ case 2:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
+
+ float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo);
+ float32x2_t xy1 = vmul_f32( vget_low_f32(v1), vLo);
+
+ float32x2x2_t z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1));
+ float32x2_t zLo = vmul_f32( z0.val[0], vHi);
+
+ float32x2_t rLo = vpadd_f32( xy0, xy1);
+ rLo = vadd_f32(rLo, zLo);
+
+ uint32x2_t maskLo = vclt_f32( rLo, dotMinLo );
+ dotMinLo = vbsl_f32( maskLo, rLo, dotMinLo);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ }
+ break;
+ case 1:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+ float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo);
+ float32x2_t z0 = vdup_lane_f32(vget_high_f32(v0), 0);
+ float32x2_t zLo = vmul_f32( z0, vHi);
+ float32x2_t rLo = vpadd_f32( xy0, xy0);
+ rLo = vadd_f32(rLo, zLo);
+ uint32x2_t maskLo = vclt_f32( rLo, dotMinLo );
+ dotMinLo = vbsl_f32( maskLo, rLo, dotMinLo);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ // select best answer between hi and lo results
+ uint32x2_t mask = vclt_f32( dotMinHi, dotMinLo );
+ dotMinLo = vbsl_f32(mask, dotMinHi, dotMinLo);
+ iLo = vbsl_u32(mask, iHi, iLo);
+
+ // select best answer between even and odd results
+ dotMinHi = vdup_lane_f32(dotMinLo, 1);
+ iHi = vdup_lane_u32(iLo, 1);
+ mask = vclt_f32( dotMinHi, dotMinLo );
+ dotMinLo = vbsl_f32(mask, dotMinHi, dotMinLo);
+ iLo = vbsl_u32(mask, iHi, iLo);
+
+ *dotResult = vget_lane_f32( dotMinLo, 0);
+ return vget_lane_u32(iLo, 0);
+}
+
+long b3_mindot_large_v1( const float *vv, const float *vec, unsigned long count, float *dotResult )
+{
+ float32x4_t vvec = vld1q_f32_aligned_postincrement( vec );
+ float32x4_t vLo = vcombine_f32(vget_low_f32(vvec), vget_low_f32(vvec));
+ float32x4_t vHi = vdupq_lane_f32(vget_high_f32(vvec), 0);
+ const uint32x4_t four = (uint32x4_t){ 4, 4, 4, 4 };
+ uint32x4_t local_index = (uint32x4_t) {0, 1, 2, 3};
+ uint32x4_t index = (uint32x4_t) { -1, -1, -1, -1 };
+ float32x4_t minDot = (float32x4_t) { B3_INFINITY, B3_INFINITY, B3_INFINITY, B3_INFINITY };
+
+ unsigned long i = 0;
+ for( ; i + 8 <= count; i += 8 )
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v3 = vld1q_f32_aligned_postincrement( vv );
+
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1));
+ float32x4_t xy1 = vcombine_f32( vget_low_f32(v2), vget_low_f32(v3));
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1));
+ float32x4_t z1 = vcombine_f32( vget_high_f32(v2), vget_high_f32(v3));
+
+ xy0 = vmulq_f32(xy0, vLo);
+ xy1 = vmulq_f32(xy1, vLo);
+
+ float32x4x2_t zb = vuzpq_f32( z0, z1);
+ float32x4_t z = vmulq_f32( zb.val[0], vHi);
+ float32x4x2_t xy = vuzpq_f32( xy0, xy1);
+ float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ uint32x4_t mask = vcltq_f32(x, minDot);
+ minDot = vbslq_f32( mask, x, minDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+
+ v0 = vld1q_f32_aligned_postincrement( vv );
+ v1 = vld1q_f32_aligned_postincrement( vv );
+ v2 = vld1q_f32_aligned_postincrement( vv );
+ v3 = vld1q_f32_aligned_postincrement( vv );
+
+ // the next two lines should resolve to a single vswp d, d
+ xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1));
+ xy1 = vcombine_f32( vget_low_f32(v2), vget_low_f32(v3));
+ // the next two lines should resolve to a single vswp d, d
+ z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1));
+ z1 = vcombine_f32( vget_high_f32(v2), vget_high_f32(v3));
+
+ xy0 = vmulq_f32(xy0, vLo);
+ xy1 = vmulq_f32(xy1, vLo);
+
+ zb = vuzpq_f32( z0, z1);
+ z = vmulq_f32( zb.val[0], vHi);
+ xy = vuzpq_f32( xy0, xy1);
+ x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ mask = vcltq_f32(x, minDot);
+ minDot = vbslq_f32( mask, x, minDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+ }
+
+ for( ; i + 4 <= count; i += 4 )
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v3 = vld1q_f32_aligned_postincrement( vv );
+
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1));
+ float32x4_t xy1 = vcombine_f32( vget_low_f32(v2), vget_low_f32(v3));
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1));
+ float32x4_t z1 = vcombine_f32( vget_high_f32(v2), vget_high_f32(v3));
+
+ xy0 = vmulq_f32(xy0, vLo);
+ xy1 = vmulq_f32(xy1, vLo);
+
+ float32x4x2_t zb = vuzpq_f32( z0, z1);
+ float32x4_t z = vmulq_f32( zb.val[0], vHi);
+ float32x4x2_t xy = vuzpq_f32( xy0, xy1);
+ float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ uint32x4_t mask = vcltq_f32(x, minDot);
+ minDot = vbslq_f32( mask, x, minDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+ }
+
+ switch (count & 3) {
+ case 3:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
+
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1));
+ float32x4_t xy1 = vcombine_f32( vget_low_f32(v2), vget_low_f32(v2));
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1));
+ float32x4_t z1 = vcombine_f32( vget_high_f32(v2), vget_high_f32(v2));
+
+ xy0 = vmulq_f32(xy0, vLo);
+ xy1 = vmulq_f32(xy1, vLo);
+
+ float32x4x2_t zb = vuzpq_f32( z0, z1);
+ float32x4_t z = vmulq_f32( zb.val[0], vHi);
+ float32x4x2_t xy = vuzpq_f32( xy0, xy1);
+ float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ uint32x4_t mask = vcltq_f32(x, minDot);
+ minDot = vbslq_f32( mask, x, minDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+ }
+ break;
+
+ case 2:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
+
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1));
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1));
+
+ xy0 = vmulq_f32(xy0, vLo);
+
+ float32x4x2_t zb = vuzpq_f32( z0, z0);
+ float32x4_t z = vmulq_f32( zb.val[0], vHi);
+ float32x4x2_t xy = vuzpq_f32( xy0, xy0);
+ float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ uint32x4_t mask = vcltq_f32(x, minDot);
+ minDot = vbslq_f32( mask, x, minDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+ }
+ break;
+
+ case 1:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v0));
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t z = vdupq_lane_f32(vget_high_f32(v0), 0);
+
+ xy0 = vmulq_f32(xy0, vLo);
+
+ z = vmulq_f32( z, vHi);
+ float32x4x2_t xy = vuzpq_f32( xy0, xy0);
+ float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ uint32x4_t mask = vcltq_f32(x, minDot);
+ minDot = vbslq_f32( mask, x, minDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+
+ // select best answer between hi and lo results
+ uint32x2_t mask = vclt_f32( vget_high_f32(minDot), vget_low_f32(minDot));
+ float32x2_t minDot2 = vbsl_f32(mask, vget_high_f32(minDot), vget_low_f32(minDot));
+ uint32x2_t index2 = vbsl_u32(mask, vget_high_u32(index), vget_low_u32(index));
+
+ // select best answer between even and odd results
+ float32x2_t minDotO = vdup_lane_f32(minDot2, 1);
+ uint32x2_t indexHi = vdup_lane_u32(index2, 1);
+ mask = vclt_f32( minDotO, minDot2 );
+ minDot2 = vbsl_f32(mask, minDotO, minDot2);
+ index2 = vbsl_u32(mask, indexHi, index2);
+
+ *dotResult = vget_lane_f32( minDot2, 0);
+ return vget_lane_u32(index2, 0);
+
+}
+
+#else
+ #error Unhandled __APPLE__ arch
+#endif
+
+#endif /* __APPLE__ */
+
+
diff --git a/thirdparty/bullet/src/Bullet3Common/b3Vector3.h b/thirdparty/bullet/src/Bullet3Common/b3Vector3.h
new file mode 100644
index 0000000000..16ec02b0ed
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Common/b3Vector3.h
@@ -0,0 +1,1344 @@
+/*
+Copyright (c) 2003-2013 Gino van den Bergen / Erwin Coumans 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 B3_VECTOR3_H
+#define B3_VECTOR3_H
+
+//#include <stdint.h>
+#include "b3Scalar.h"
+#include "b3MinMax.h"
+#include "b3AlignedAllocator.h"
+
+#ifdef B3_USE_DOUBLE_PRECISION
+#define b3Vector3Data b3Vector3DoubleData
+#define b3Vector3DataName "b3Vector3DoubleData"
+#else
+#define b3Vector3Data b3Vector3FloatData
+#define b3Vector3DataName "b3Vector3FloatData"
+#endif //B3_USE_DOUBLE_PRECISION
+
+#if defined B3_USE_SSE
+
+//typedef uint32_t __m128i __attribute__ ((vector_size(16)));
+
+#ifdef _MSC_VER
+#pragma warning(disable: 4556) // value of intrinsic immediate argument '4294967239' is out of range '0 - 255'
+#endif
+
+
+#define B3_SHUFFLE(x,y,z,w) ((w)<<6 | (z)<<4 | (y)<<2 | (x))
+//#define b3_pshufd_ps( _a, _mask ) (__m128) _mm_shuffle_epi32((__m128i)(_a), (_mask) )
+#define b3_pshufd_ps( _a, _mask ) _mm_shuffle_ps((_a), (_a), (_mask) )
+#define b3_splat3_ps( _a, _i ) b3_pshufd_ps((_a), B3_SHUFFLE(_i,_i,_i, 3) )
+#define b3_splat_ps( _a, _i ) b3_pshufd_ps((_a), B3_SHUFFLE(_i,_i,_i,_i) )
+
+#define b3v3AbsiMask (_mm_set_epi32(0x00000000, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF))
+#define b3vAbsMask (_mm_set_epi32( 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF))
+#define b3vFFF0Mask (_mm_set_epi32(0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF))
+#define b3v3AbsfMask b3CastiTo128f(b3v3AbsiMask)
+#define b3vFFF0fMask b3CastiTo128f(b3vFFF0Mask)
+#define b3vxyzMaskf b3vFFF0fMask
+#define b3vAbsfMask b3CastiTo128f(b3vAbsMask)
+
+
+
+const __m128 B3_ATTRIBUTE_ALIGNED16(b3vMzeroMask) = {-0.0f, -0.0f, -0.0f, -0.0f};
+const __m128 B3_ATTRIBUTE_ALIGNED16(b3v1110) = {1.0f, 1.0f, 1.0f, 0.0f};
+const __m128 B3_ATTRIBUTE_ALIGNED16(b3vHalf) = {0.5f, 0.5f, 0.5f, 0.5f};
+const __m128 B3_ATTRIBUTE_ALIGNED16(b3v1_5) = {1.5f, 1.5f, 1.5f, 1.5f};
+
+#endif
+
+#ifdef B3_USE_NEON
+
+const float32x4_t B3_ATTRIBUTE_ALIGNED16(b3vMzeroMask) = (float32x4_t){-0.0f, -0.0f, -0.0f, -0.0f};
+const int32x4_t B3_ATTRIBUTE_ALIGNED16(b3vFFF0Mask) = (int32x4_t){0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0};
+const int32x4_t B3_ATTRIBUTE_ALIGNED16(b3vAbsMask) = (int32x4_t){0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF};
+const int32x4_t B3_ATTRIBUTE_ALIGNED16(b3v3AbsMask) = (int32x4_t){0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x0};
+
+#endif
+
+class b3Vector3;
+class b3Vector4;
+
+#if defined(B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+//#if defined (B3_USE_SSE) || defined (B3_USE_NEON)
+inline b3Vector3 b3MakeVector3( b3SimdFloat4 v);
+inline b3Vector4 b3MakeVector4( b3SimdFloat4 vec);
+#endif
+
+inline b3Vector3 b3MakeVector3(b3Scalar x,b3Scalar y,b3Scalar z);
+inline b3Vector3 b3MakeVector3(b3Scalar x,b3Scalar y,b3Scalar z, b3Scalar w);
+inline b3Vector4 b3MakeVector4(b3Scalar x,b3Scalar y,b3Scalar z,b3Scalar w);
+
+
+/**@brief b3Vector3 can be used to represent 3D points and vectors.
+ * It has an un-used w component to suit 16-byte alignment when b3Vector3 is stored in containers. This extra component can be used by derived classes (Quaternion?) or by user
+ * Ideally, this class should be replaced by a platform optimized SIMD version that keeps the data in registers
+ */
+B3_ATTRIBUTE_ALIGNED16(class) b3Vector3
+{
+public:
+#if defined (B3_USE_SSE) || defined(B3_USE_NEON) // _WIN32 || ARM
+ union {
+ b3SimdFloat4 mVec128;
+ float m_floats[4];
+ struct {float x,y,z,w;};
+
+ };
+#else
+ union
+ {
+ float m_floats[4];
+ struct {float x,y,z,w;};
+ };
+#endif
+
+
+public:
+
+ B3_DECLARE_ALIGNED_ALLOCATOR();
+
+#if defined (B3_USE_SSE) || defined(B3_USE_NEON) // _WIN32 || ARM
+
+ /*B3_FORCE_INLINE b3Vector3()
+ {
+ }
+ */
+
+ B3_FORCE_INLINE b3SimdFloat4 get128() const
+ {
+ return mVec128;
+ }
+ B3_FORCE_INLINE void set128(b3SimdFloat4 v128)
+ {
+ mVec128 = v128;
+ }
+#endif
+
+ public:
+
+
+
+/**@brief Add a vector to this one
+ * @param The vector to add to this one */
+ B3_FORCE_INLINE b3Vector3& operator+=(const b3Vector3& v)
+ {
+#if defined(B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+ mVec128 = _mm_add_ps(mVec128, v.mVec128);
+#elif defined(B3_USE_NEON)
+ mVec128 = vaddq_f32(mVec128, v.mVec128);
+#else
+ m_floats[0] += v.m_floats[0];
+ m_floats[1] += v.m_floats[1];
+ m_floats[2] += v.m_floats[2];
+#endif
+ return *this;
+ }
+
+
+ /**@brief Subtract a vector from this one
+ * @param The vector to subtract */
+ B3_FORCE_INLINE b3Vector3& operator-=(const b3Vector3& v)
+ {
+#if defined(B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+ mVec128 = _mm_sub_ps(mVec128, v.mVec128);
+#elif defined(B3_USE_NEON)
+ mVec128 = vsubq_f32(mVec128, v.mVec128);
+#else
+ m_floats[0] -= v.m_floats[0];
+ m_floats[1] -= v.m_floats[1];
+ m_floats[2] -= v.m_floats[2];
+#endif
+ return *this;
+ }
+
+ /**@brief Scale the vector
+ * @param s Scale factor */
+ B3_FORCE_INLINE b3Vector3& operator*=(const b3Scalar& s)
+ {
+#if defined(B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+ __m128 vs = _mm_load_ss(&s); // (S 0 0 0)
+ vs = b3_pshufd_ps(vs, 0x80); // (S S S 0.0)
+ mVec128 = _mm_mul_ps(mVec128, vs);
+#elif defined(B3_USE_NEON)
+ mVec128 = vmulq_n_f32(mVec128, s);
+#else
+ m_floats[0] *= s;
+ m_floats[1] *= s;
+ m_floats[2] *= s;
+#endif
+ return *this;
+ }
+
+ /**@brief Inversely scale the vector
+ * @param s Scale factor to divide by */
+ B3_FORCE_INLINE b3Vector3& operator/=(const b3Scalar& s)
+ {
+ b3FullAssert(s != b3Scalar(0.0));
+
+#if 0 //defined(B3_USE_SSE_IN_API)
+// this code is not faster !
+ __m128 vs = _mm_load_ss(&s);
+ vs = _mm_div_ss(b3v1110, vs);
+ vs = b3_pshufd_ps(vs, 0x00); // (S S S S)
+
+ mVec128 = _mm_mul_ps(mVec128, vs);
+
+ return *this;
+#else
+ return *this *= b3Scalar(1.0) / s;
+#endif
+ }
+
+ /**@brief Return the dot product
+ * @param v The other vector in the dot product */
+ B3_FORCE_INLINE b3Scalar dot(const b3Vector3& v) const
+ {
+#if defined(B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+ __m128 vd = _mm_mul_ps(mVec128, v.mVec128);
+ __m128 z = _mm_movehl_ps(vd, vd);
+ __m128 y = _mm_shuffle_ps(vd, vd, 0x55);
+ vd = _mm_add_ss(vd, y);
+ vd = _mm_add_ss(vd, z);
+ return _mm_cvtss_f32(vd);
+#elif defined(B3_USE_NEON)
+ float32x4_t vd = vmulq_f32(mVec128, v.mVec128);
+ float32x2_t x = vpadd_f32(vget_low_f32(vd), vget_low_f32(vd));
+ x = vadd_f32(x, vget_high_f32(vd));
+ return vget_lane_f32(x, 0);
+#else
+ return m_floats[0] * v.m_floats[0] +
+ m_floats[1] * v.m_floats[1] +
+ m_floats[2] * v.m_floats[2];
+#endif
+ }
+
+ /**@brief Return the length of the vector squared */
+ B3_FORCE_INLINE b3Scalar length2() const
+ {
+ return dot(*this);
+ }
+
+ /**@brief Return the length of the vector */
+ B3_FORCE_INLINE b3Scalar length() const
+ {
+ return b3Sqrt(length2());
+ }
+
+ /**@brief Return the distance squared between the ends of this and another vector
+ * This is symantically treating the vector like a point */
+ B3_FORCE_INLINE b3Scalar distance2(const b3Vector3& v) const;
+
+ /**@brief Return the distance between the ends of this and another vector
+ * This is symantically treating the vector like a point */
+ B3_FORCE_INLINE b3Scalar distance(const b3Vector3& v) const;
+
+ B3_FORCE_INLINE b3Vector3& safeNormalize()
+ {
+ b3Scalar l2 = length2();
+ //triNormal.normalize();
+ if (l2 >= B3_EPSILON*B3_EPSILON)
+ {
+ (*this) /= b3Sqrt(l2);
+ }
+ else
+ {
+ setValue(1, 0, 0);
+ }
+ return *this;
+ }
+
+ /**@brief Normalize this vector
+ * x^2 + y^2 + z^2 = 1 */
+ B3_FORCE_INLINE b3Vector3& normalize()
+ {
+#if defined(B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+ // dot product first
+ __m128 vd = _mm_mul_ps(mVec128, mVec128);
+ __m128 z = _mm_movehl_ps(vd, vd);
+ __m128 y = _mm_shuffle_ps(vd, vd, 0x55);
+ vd = _mm_add_ss(vd, y);
+ vd = _mm_add_ss(vd, z);
+
+ #if 0
+ vd = _mm_sqrt_ss(vd);
+ vd = _mm_div_ss(b3v1110, vd);
+ vd = b3_splat_ps(vd, 0x80);
+ mVec128 = _mm_mul_ps(mVec128, vd);
+ #else
+
+ // NR step 1/sqrt(x) - vd is x, y is output
+ y = _mm_rsqrt_ss(vd); // estimate
+
+ // one step NR
+ z = b3v1_5;
+ vd = _mm_mul_ss(vd, b3vHalf); // vd * 0.5
+ //x2 = vd;
+ vd = _mm_mul_ss(vd, y); // vd * 0.5 * y0
+ vd = _mm_mul_ss(vd, y); // vd * 0.5 * y0 * y0
+ z = _mm_sub_ss(z, vd); // 1.5 - vd * 0.5 * y0 * y0
+
+ y = _mm_mul_ss(y, z); // y0 * (1.5 - vd * 0.5 * y0 * y0)
+
+ y = b3_splat_ps(y, 0x80);
+ mVec128 = _mm_mul_ps(mVec128, y);
+
+ #endif
+
+
+ return *this;
+#else
+ return *this /= length();
+#endif
+ }
+
+ /**@brief Return a normalized version of this vector */
+ B3_FORCE_INLINE b3Vector3 normalized() const;
+
+ /**@brief Return a rotated version of this vector
+ * @param wAxis The axis to rotate about
+ * @param angle The angle to rotate by */
+ B3_FORCE_INLINE b3Vector3 rotate( const b3Vector3& wAxis, const b3Scalar angle ) const;
+
+ /**@brief Return the angle between this and another vector
+ * @param v The other vector */
+ B3_FORCE_INLINE b3Scalar angle(const b3Vector3& v) const
+ {
+ b3Scalar s = b3Sqrt(length2() * v.length2());
+ b3FullAssert(s != b3Scalar(0.0));
+ return b3Acos(dot(v) / s);
+ }
+
+ /**@brief Return a vector will the absolute values of each element */
+ B3_FORCE_INLINE b3Vector3 absolute() const
+ {
+#if defined(B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+ return b3MakeVector3(_mm_and_ps(mVec128, b3v3AbsfMask));
+#elif defined(B3_USE_NEON)
+ return b3Vector3(vabsq_f32(mVec128));
+#else
+ return b3MakeVector3(
+ b3Fabs(m_floats[0]),
+ b3Fabs(m_floats[1]),
+ b3Fabs(m_floats[2]));
+#endif
+ }
+
+ /**@brief Return the cross product between this and another vector
+ * @param v The other vector */
+ B3_FORCE_INLINE b3Vector3 cross(const b3Vector3& v) const
+ {
+#if defined(B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+ __m128 T, V;
+
+ T = b3_pshufd_ps(mVec128, B3_SHUFFLE(1, 2, 0, 3)); // (Y Z X 0)
+ V = b3_pshufd_ps(v.mVec128, B3_SHUFFLE(1, 2, 0, 3)); // (Y Z X 0)
+
+ V = _mm_mul_ps(V, mVec128);
+ T = _mm_mul_ps(T, v.mVec128);
+ V = _mm_sub_ps(V, T);
+
+ V = b3_pshufd_ps(V, B3_SHUFFLE(1, 2, 0, 3));
+ return b3MakeVector3(V);
+#elif defined(B3_USE_NEON)
+ float32x4_t T, V;
+ // form (Y, Z, X, _) of mVec128 and v.mVec128
+ float32x2_t Tlow = vget_low_f32(mVec128);
+ float32x2_t Vlow = vget_low_f32(v.mVec128);
+ T = vcombine_f32(vext_f32(Tlow, vget_high_f32(mVec128), 1), Tlow);
+ V = vcombine_f32(vext_f32(Vlow, vget_high_f32(v.mVec128), 1), Vlow);
+
+ V = vmulq_f32(V, mVec128);
+ T = vmulq_f32(T, v.mVec128);
+ V = vsubq_f32(V, T);
+ Vlow = vget_low_f32(V);
+ // form (Y, Z, X, _);
+ V = vcombine_f32(vext_f32(Vlow, vget_high_f32(V), 1), Vlow);
+ V = (float32x4_t)vandq_s32((int32x4_t)V, b3vFFF0Mask);
+
+ return b3Vector3(V);
+#else
+ return b3MakeVector3(
+ m_floats[1] * v.m_floats[2] - m_floats[2] * v.m_floats[1],
+ m_floats[2] * v.m_floats[0] - m_floats[0] * v.m_floats[2],
+ m_floats[0] * v.m_floats[1] - m_floats[1] * v.m_floats[0]);
+#endif
+ }
+
+ B3_FORCE_INLINE b3Scalar triple(const b3Vector3& v1, const b3Vector3& v2) const
+ {
+#if defined(B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+ // cross:
+ __m128 T = _mm_shuffle_ps(v1.mVec128, v1.mVec128, B3_SHUFFLE(1, 2, 0, 3)); // (Y Z X 0)
+ __m128 V = _mm_shuffle_ps(v2.mVec128, v2.mVec128, B3_SHUFFLE(1, 2, 0, 3)); // (Y Z X 0)
+
+ V = _mm_mul_ps(V, v1.mVec128);
+ T = _mm_mul_ps(T, v2.mVec128);
+ V = _mm_sub_ps(V, T);
+
+ V = _mm_shuffle_ps(V, V, B3_SHUFFLE(1, 2, 0, 3));
+
+ // dot:
+ V = _mm_mul_ps(V, mVec128);
+ __m128 z = _mm_movehl_ps(V, V);
+ __m128 y = _mm_shuffle_ps(V, V, 0x55);
+ V = _mm_add_ss(V, y);
+ V = _mm_add_ss(V, z);
+ return _mm_cvtss_f32(V);
+
+#elif defined(B3_USE_NEON)
+ // cross:
+ float32x4_t T, V;
+ // form (Y, Z, X, _) of mVec128 and v.mVec128
+ float32x2_t Tlow = vget_low_f32(v1.mVec128);
+ float32x2_t Vlow = vget_low_f32(v2.mVec128);
+ T = vcombine_f32(vext_f32(Tlow, vget_high_f32(v1.mVec128), 1), Tlow);
+ V = vcombine_f32(vext_f32(Vlow, vget_high_f32(v2.mVec128), 1), Vlow);
+
+ V = vmulq_f32(V, v1.mVec128);
+ T = vmulq_f32(T, v2.mVec128);
+ V = vsubq_f32(V, T);
+ Vlow = vget_low_f32(V);
+ // form (Y, Z, X, _);
+ V = vcombine_f32(vext_f32(Vlow, vget_high_f32(V), 1), Vlow);
+
+ // dot:
+ V = vmulq_f32(mVec128, V);
+ float32x2_t x = vpadd_f32(vget_low_f32(V), vget_low_f32(V));
+ x = vadd_f32(x, vget_high_f32(V));
+ return vget_lane_f32(x, 0);
+#else
+ return
+ m_floats[0] * (v1.m_floats[1] * v2.m_floats[2] - v1.m_floats[2] * v2.m_floats[1]) +
+ m_floats[1] * (v1.m_floats[2] * v2.m_floats[0] - v1.m_floats[0] * v2.m_floats[2]) +
+ m_floats[2] * (v1.m_floats[0] * v2.m_floats[1] - v1.m_floats[1] * v2.m_floats[0]);
+#endif
+ }
+
+ /**@brief Return the axis with the smallest value
+ * Note return values are 0,1,2 for x, y, or z */
+ B3_FORCE_INLINE int minAxis() const
+ {
+ return m_floats[0] < m_floats[1] ? (m_floats[0] <m_floats[2] ? 0 : 2) : (m_floats[1] <m_floats[2] ? 1 : 2);
+ }
+
+ /**@brief Return the axis with the largest value
+ * Note return values are 0,1,2 for x, y, or z */
+ B3_FORCE_INLINE int maxAxis() const
+ {
+ return m_floats[0] < m_floats[1] ? (m_floats[1] <m_floats[2] ? 2 : 1) : (m_floats[0] <m_floats[2] ? 2 : 0);
+ }
+
+ B3_FORCE_INLINE int furthestAxis() const
+ {
+ return absolute().minAxis();
+ }
+
+ B3_FORCE_INLINE int closestAxis() const
+ {
+ return absolute().maxAxis();
+ }
+
+
+ B3_FORCE_INLINE void setInterpolate3(const b3Vector3& v0, const b3Vector3& v1, b3Scalar rt)
+ {
+#if defined(B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+ __m128 vrt = _mm_load_ss(&rt); // (rt 0 0 0)
+ b3Scalar s = b3Scalar(1.0) - rt;
+ __m128 vs = _mm_load_ss(&s); // (S 0 0 0)
+ vs = b3_pshufd_ps(vs, 0x80); // (S S S 0.0)
+ __m128 r0 = _mm_mul_ps(v0.mVec128, vs);
+ vrt = b3_pshufd_ps(vrt, 0x80); // (rt rt rt 0.0)
+ __m128 r1 = _mm_mul_ps(v1.mVec128, vrt);
+ __m128 tmp3 = _mm_add_ps(r0,r1);
+ mVec128 = tmp3;
+#elif defined(B3_USE_NEON)
+ float32x4_t vl = vsubq_f32(v1.mVec128, v0.mVec128);
+ vl = vmulq_n_f32(vl, rt);
+ mVec128 = vaddq_f32(vl, v0.mVec128);
+#else
+ b3Scalar s = b3Scalar(1.0) - rt;
+ m_floats[0] = s * v0.m_floats[0] + rt * v1.m_floats[0];
+ m_floats[1] = s * v0.m_floats[1] + rt * v1.m_floats[1];
+ m_floats[2] = s * v0.m_floats[2] + rt * v1.m_floats[2];
+ //don't do the unused w component
+ // m_co[3] = s * v0[3] + rt * v1[3];
+#endif
+ }
+
+ /**@brief Return the linear interpolation between this and another vector
+ * @param v The other vector
+ * @param t The ration of this to v (t = 0 => return this, t=1 => return other) */
+ B3_FORCE_INLINE b3Vector3 lerp(const b3Vector3& v, const b3Scalar& t) const
+ {
+#if defined(B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+ __m128 vt = _mm_load_ss(&t); // (t 0 0 0)
+ vt = b3_pshufd_ps(vt, 0x80); // (rt rt rt 0.0)
+ __m128 vl = _mm_sub_ps(v.mVec128, mVec128);
+ vl = _mm_mul_ps(vl, vt);
+ vl = _mm_add_ps(vl, mVec128);
+
+ return b3MakeVector3(vl);
+#elif defined(B3_USE_NEON)
+ float32x4_t vl = vsubq_f32(v.mVec128, mVec128);
+ vl = vmulq_n_f32(vl, t);
+ vl = vaddq_f32(vl, mVec128);
+
+ return b3Vector3(vl);
+#else
+ return
+ b3MakeVector3( m_floats[0] + (v.m_floats[0] - m_floats[0]) * t,
+ m_floats[1] + (v.m_floats[1] - m_floats[1]) * t,
+ m_floats[2] + (v.m_floats[2] - m_floats[2]) * t);
+#endif
+ }
+
+ /**@brief Elementwise multiply this vector by the other
+ * @param v The other vector */
+ B3_FORCE_INLINE b3Vector3& operator*=(const b3Vector3& v)
+ {
+#if defined(B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+ mVec128 = _mm_mul_ps(mVec128, v.mVec128);
+#elif defined(B3_USE_NEON)
+ mVec128 = vmulq_f32(mVec128, v.mVec128);
+#else
+ m_floats[0] *= v.m_floats[0];
+ m_floats[1] *= v.m_floats[1];
+ m_floats[2] *= v.m_floats[2];
+#endif
+ return *this;
+ }
+
+ /**@brief Return the x value */
+ B3_FORCE_INLINE const b3Scalar& getX() const { return m_floats[0]; }
+ /**@brief Return the y value */
+ B3_FORCE_INLINE const b3Scalar& getY() const { return m_floats[1]; }
+ /**@brief Return the z value */
+ B3_FORCE_INLINE const b3Scalar& getZ() const { return m_floats[2]; }
+/**@brief Return the w value */
+ B3_FORCE_INLINE const b3Scalar& getW() const { return m_floats[3]; }
+
+ /**@brief Set the x value */
+ B3_FORCE_INLINE void setX(b3Scalar _x) { m_floats[0] = _x;};
+ /**@brief Set the y value */
+ B3_FORCE_INLINE void setY(b3Scalar _y) { m_floats[1] = _y;};
+ /**@brief Set the z value */
+ B3_FORCE_INLINE void setZ(b3Scalar _z) { m_floats[2] = _z;};
+ /**@brief Set the w value */
+ B3_FORCE_INLINE void setW(b3Scalar _w) { m_floats[3] = _w;};
+
+ //B3_FORCE_INLINE b3Scalar& operator[](int i) { return (&m_floats[0])[i]; }
+ //B3_FORCE_INLINE const b3Scalar& operator[](int i) const { return (&m_floats[0])[i]; }
+ ///operator b3Scalar*() replaces operator[], using implicit conversion. We added operator != and operator == to avoid pointer comparisons.
+ B3_FORCE_INLINE operator b3Scalar *() { return &m_floats[0]; }
+ B3_FORCE_INLINE operator const b3Scalar *() const { return &m_floats[0]; }
+
+ B3_FORCE_INLINE bool operator==(const b3Vector3& other) const
+ {
+#if defined(B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+ return (0xf == _mm_movemask_ps((__m128)_mm_cmpeq_ps(mVec128, other.mVec128)));
+#else
+ return ((m_floats[3]==other.m_floats[3]) &&
+ (m_floats[2]==other.m_floats[2]) &&
+ (m_floats[1]==other.m_floats[1]) &&
+ (m_floats[0]==other.m_floats[0]));
+#endif
+ }
+
+ B3_FORCE_INLINE bool operator!=(const b3Vector3& other) const
+ {
+ return !(*this == other);
+ }
+
+ /**@brief Set each element to the max of the current values and the values of another b3Vector3
+ * @param other The other b3Vector3 to compare with
+ */
+ B3_FORCE_INLINE void setMax(const b3Vector3& other)
+ {
+#if defined(B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+ mVec128 = _mm_max_ps(mVec128, other.mVec128);
+#elif defined(B3_USE_NEON)
+ mVec128 = vmaxq_f32(mVec128, other.mVec128);
+#else
+ b3SetMax(m_floats[0], other.m_floats[0]);
+ b3SetMax(m_floats[1], other.m_floats[1]);
+ b3SetMax(m_floats[2], other.m_floats[2]);
+ b3SetMax(m_floats[3], other.m_floats[3]);
+#endif
+ }
+
+ /**@brief Set each element to the min of the current values and the values of another b3Vector3
+ * @param other The other b3Vector3 to compare with
+ */
+ B3_FORCE_INLINE void setMin(const b3Vector3& other)
+ {
+#if defined(B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+ mVec128 = _mm_min_ps(mVec128, other.mVec128);
+#elif defined(B3_USE_NEON)
+ mVec128 = vminq_f32(mVec128, other.mVec128);
+#else
+ b3SetMin(m_floats[0], other.m_floats[0]);
+ b3SetMin(m_floats[1], other.m_floats[1]);
+ b3SetMin(m_floats[2], other.m_floats[2]);
+ b3SetMin(m_floats[3], other.m_floats[3]);
+#endif
+ }
+
+ B3_FORCE_INLINE void setValue(const b3Scalar& _x, const b3Scalar& _y, const b3Scalar& _z)
+ {
+ m_floats[0]=_x;
+ m_floats[1]=_y;
+ m_floats[2]=_z;
+ m_floats[3] = b3Scalar(0.f);
+ }
+
+ void getSkewSymmetricMatrix(b3Vector3* v0,b3Vector3* v1,b3Vector3* v2) const
+ {
+#if defined(B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+
+ __m128 V = _mm_and_ps(mVec128, b3vFFF0fMask);
+ __m128 V0 = _mm_xor_ps(b3vMzeroMask, V);
+ __m128 V2 = _mm_movelh_ps(V0, V);
+
+ __m128 V1 = _mm_shuffle_ps(V, V0, 0xCE);
+
+ V0 = _mm_shuffle_ps(V0, V, 0xDB);
+ V2 = _mm_shuffle_ps(V2, V, 0xF9);
+
+ v0->mVec128 = V0;
+ v1->mVec128 = V1;
+ v2->mVec128 = V2;
+#else
+ v0->setValue(0. ,-getZ() ,getY());
+ v1->setValue(getZ() ,0. ,-getX());
+ v2->setValue(-getY() ,getX() ,0.);
+#endif
+ }
+
+ void setZero()
+ {
+#if defined(B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+ mVec128 = (__m128)_mm_xor_ps(mVec128, mVec128);
+#elif defined(B3_USE_NEON)
+ int32x4_t vi = vdupq_n_s32(0);
+ mVec128 = vreinterpretq_f32_s32(vi);
+#else
+ setValue(b3Scalar(0.),b3Scalar(0.),b3Scalar(0.));
+#endif
+ }
+
+ B3_FORCE_INLINE bool isZero() const
+ {
+ return m_floats[0] == b3Scalar(0) && m_floats[1] == b3Scalar(0) && m_floats[2] == b3Scalar(0);
+ }
+
+ B3_FORCE_INLINE bool fuzzyZero() const
+ {
+ return length2() < B3_EPSILON;
+ }
+
+ B3_FORCE_INLINE void serialize(struct b3Vector3Data& dataOut) const;
+
+ B3_FORCE_INLINE void deSerialize(const struct b3Vector3Data& dataIn);
+
+ B3_FORCE_INLINE void serializeFloat(struct b3Vector3FloatData& dataOut) const;
+
+ B3_FORCE_INLINE void deSerializeFloat(const struct b3Vector3FloatData& dataIn);
+
+ B3_FORCE_INLINE void serializeDouble(struct b3Vector3DoubleData& dataOut) const;
+
+ B3_FORCE_INLINE void deSerializeDouble(const struct b3Vector3DoubleData& dataIn);
+
+ /**@brief returns index of maximum dot product between this and vectors in array[]
+ * @param array The other vectors
+ * @param array_count The number of other vectors
+ * @param dotOut The maximum dot product */
+ B3_FORCE_INLINE long maxDot( const b3Vector3 *array, long array_count, b3Scalar &dotOut ) const;
+
+ /**@brief returns index of minimum dot product between this and vectors in array[]
+ * @param array The other vectors
+ * @param array_count The number of other vectors
+ * @param dotOut The minimum dot product */
+ B3_FORCE_INLINE long minDot( const b3Vector3 *array, long array_count, b3Scalar &dotOut ) const;
+
+ /* create a vector as b3Vector3( this->dot( b3Vector3 v0 ), this->dot( b3Vector3 v1), this->dot( b3Vector3 v2 )) */
+ B3_FORCE_INLINE b3Vector3 dot3( const b3Vector3 &v0, const b3Vector3 &v1, const b3Vector3 &v2 ) const
+ {
+#if defined(B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+
+ __m128 a0 = _mm_mul_ps( v0.mVec128, this->mVec128 );
+ __m128 a1 = _mm_mul_ps( v1.mVec128, this->mVec128 );
+ __m128 a2 = _mm_mul_ps( v2.mVec128, this->mVec128 );
+ __m128 b0 = _mm_unpacklo_ps( a0, a1 );
+ __m128 b1 = _mm_unpackhi_ps( a0, a1 );
+ __m128 b2 = _mm_unpacklo_ps( a2, _mm_setzero_ps() );
+ __m128 r = _mm_movelh_ps( b0, b2 );
+ r = _mm_add_ps( r, _mm_movehl_ps( b2, b0 ));
+ a2 = _mm_and_ps( a2, b3vxyzMaskf);
+ r = _mm_add_ps( r, b3CastdTo128f (_mm_move_sd( b3CastfTo128d(a2), b3CastfTo128d(b1) )));
+ return b3MakeVector3(r);
+
+#elif defined(B3_USE_NEON)
+ static const uint32x4_t xyzMask = (const uint32x4_t){ -1, -1, -1, 0 };
+ float32x4_t a0 = vmulq_f32( v0.mVec128, this->mVec128);
+ float32x4_t a1 = vmulq_f32( v1.mVec128, this->mVec128);
+ float32x4_t a2 = vmulq_f32( v2.mVec128, this->mVec128);
+ float32x2x2_t zLo = vtrn_f32( vget_high_f32(a0), vget_high_f32(a1));
+ a2 = (float32x4_t) vandq_u32((uint32x4_t) a2, xyzMask );
+ float32x2_t b0 = vadd_f32( vpadd_f32( vget_low_f32(a0), vget_low_f32(a1)), zLo.val[0] );
+ float32x2_t b1 = vpadd_f32( vpadd_f32( vget_low_f32(a2), vget_high_f32(a2)), vdup_n_f32(0.0f));
+ return b3Vector3( vcombine_f32(b0, b1) );
+#else
+ return b3MakeVector3( dot(v0), dot(v1), dot(v2));
+#endif
+ }
+};
+
+/**@brief Return the sum of two vectors (Point symantics)*/
+B3_FORCE_INLINE b3Vector3
+operator+(const b3Vector3& v1, const b3Vector3& v2)
+{
+#if defined(B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+ return b3MakeVector3(_mm_add_ps(v1.mVec128, v2.mVec128));
+#elif defined(B3_USE_NEON)
+ return b3MakeVector3(vaddq_f32(v1.mVec128, v2.mVec128));
+#else
+ return b3MakeVector3(
+ v1.m_floats[0] + v2.m_floats[0],
+ v1.m_floats[1] + v2.m_floats[1],
+ v1.m_floats[2] + v2.m_floats[2]);
+#endif
+}
+
+/**@brief Return the elementwise product of two vectors */
+B3_FORCE_INLINE b3Vector3
+operator*(const b3Vector3& v1, const b3Vector3& v2)
+{
+#if defined(B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+ return b3MakeVector3(_mm_mul_ps(v1.mVec128, v2.mVec128));
+#elif defined(B3_USE_NEON)
+ return b3MakeVector3(vmulq_f32(v1.mVec128, v2.mVec128));
+#else
+ return b3MakeVector3(
+ v1.m_floats[0] * v2.m_floats[0],
+ v1.m_floats[1] * v2.m_floats[1],
+ v1.m_floats[2] * v2.m_floats[2]);
+#endif
+}
+
+/**@brief Return the difference between two vectors */
+B3_FORCE_INLINE b3Vector3
+operator-(const b3Vector3& v1, const b3Vector3& v2)
+{
+#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE))
+
+ // without _mm_and_ps this code causes slowdown in Concave moving
+ __m128 r = _mm_sub_ps(v1.mVec128, v2.mVec128);
+ return b3MakeVector3(_mm_and_ps(r, b3vFFF0fMask));
+#elif defined(B3_USE_NEON)
+ float32x4_t r = vsubq_f32(v1.mVec128, v2.mVec128);
+ return b3MakeVector3((float32x4_t)vandq_s32((int32x4_t)r, b3vFFF0Mask));
+#else
+ return b3MakeVector3(
+ v1.m_floats[0] - v2.m_floats[0],
+ v1.m_floats[1] - v2.m_floats[1],
+ v1.m_floats[2] - v2.m_floats[2]);
+#endif
+}
+
+/**@brief Return the negative of the vector */
+B3_FORCE_INLINE b3Vector3
+operator-(const b3Vector3& v)
+{
+#if (defined(B3_USE_SSE_IN_API) && defined (B3_USE_SSE))
+ __m128 r = _mm_xor_ps(v.mVec128, b3vMzeroMask);
+ return b3MakeVector3(_mm_and_ps(r, b3vFFF0fMask));
+#elif defined(B3_USE_NEON)
+ return b3MakeVector3((b3SimdFloat4)veorq_s32((int32x4_t)v.mVec128, (int32x4_t)b3vMzeroMask));
+#else
+ return b3MakeVector3(-v.m_floats[0], -v.m_floats[1], -v.m_floats[2]);
+#endif
+}
+
+/**@brief Return the vector scaled by s */
+B3_FORCE_INLINE b3Vector3
+operator*(const b3Vector3& v, const b3Scalar& s)
+{
+#if defined(B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+ __m128 vs = _mm_load_ss(&s); // (S 0 0 0)
+ vs = b3_pshufd_ps(vs, 0x80); // (S S S 0.0)
+ return b3MakeVector3(_mm_mul_ps(v.mVec128, vs));
+#elif defined(B3_USE_NEON)
+ float32x4_t r = vmulq_n_f32(v.mVec128, s);
+ return b3MakeVector3((float32x4_t)vandq_s32((int32x4_t)r, b3vFFF0Mask));
+#else
+ return b3MakeVector3(v.m_floats[0] * s, v.m_floats[1] * s, v.m_floats[2] * s);
+#endif
+}
+
+/**@brief Return the vector scaled by s */
+B3_FORCE_INLINE b3Vector3
+operator*(const b3Scalar& s, const b3Vector3& v)
+{
+ return v * s;
+}
+
+/**@brief Return the vector inversely scaled by s */
+B3_FORCE_INLINE b3Vector3
+operator/(const b3Vector3& v, const b3Scalar& s)
+{
+ b3FullAssert(s != b3Scalar(0.0));
+#if 0 //defined(B3_USE_SSE_IN_API)
+// this code is not faster !
+ __m128 vs = _mm_load_ss(&s);
+ vs = _mm_div_ss(b3v1110, vs);
+ vs = b3_pshufd_ps(vs, 0x00); // (S S S S)
+
+ return b3Vector3(_mm_mul_ps(v.mVec128, vs));
+#else
+ return v * (b3Scalar(1.0) / s);
+#endif
+}
+
+/**@brief Return the vector inversely scaled by s */
+B3_FORCE_INLINE b3Vector3
+operator/(const b3Vector3& v1, const b3Vector3& v2)
+{
+#if (defined(B3_USE_SSE_IN_API)&& defined (B3_USE_SSE))
+ __m128 vec = _mm_div_ps(v1.mVec128, v2.mVec128);
+ vec = _mm_and_ps(vec, b3vFFF0fMask);
+ return b3MakeVector3(vec);
+#elif defined(B3_USE_NEON)
+ float32x4_t x, y, v, m;
+
+ x = v1.mVec128;
+ y = v2.mVec128;
+
+ v = vrecpeq_f32(y); // v ~ 1/y
+ m = vrecpsq_f32(y, v); // m = (2-v*y)
+ v = vmulq_f32(v, m); // vv = v*m ~~ 1/y
+ m = vrecpsq_f32(y, v); // mm = (2-vv*y)
+ v = vmulq_f32(v, x); // x*vv
+ v = vmulq_f32(v, m); // (x*vv)*(2-vv*y) = x*(vv(2-vv*y)) ~~~ x/y
+
+ return b3Vector3(v);
+#else
+ return b3MakeVector3(
+ v1.m_floats[0] / v2.m_floats[0],
+ v1.m_floats[1] / v2.m_floats[1],
+ v1.m_floats[2] / v2.m_floats[2]);
+#endif
+}
+
+/**@brief Return the dot product between two vectors */
+B3_FORCE_INLINE b3Scalar
+b3Dot(const b3Vector3& v1, const b3Vector3& v2)
+{
+ return v1.dot(v2);
+}
+
+
+/**@brief Return the distance squared between two vectors */
+B3_FORCE_INLINE b3Scalar
+b3Distance2(const b3Vector3& v1, const b3Vector3& v2)
+{
+ return v1.distance2(v2);
+}
+
+
+/**@brief Return the distance between two vectors */
+B3_FORCE_INLINE b3Scalar
+b3Distance(const b3Vector3& v1, const b3Vector3& v2)
+{
+ return v1.distance(v2);
+}
+
+/**@brief Return the angle between two vectors */
+B3_FORCE_INLINE b3Scalar
+b3Angle(const b3Vector3& v1, const b3Vector3& v2)
+{
+ return v1.angle(v2);
+}
+
+/**@brief Return the cross product of two vectors */
+B3_FORCE_INLINE b3Vector3
+b3Cross(const b3Vector3& v1, const b3Vector3& v2)
+{
+ return v1.cross(v2);
+}
+
+B3_FORCE_INLINE b3Scalar
+b3Triple(const b3Vector3& v1, const b3Vector3& v2, const b3Vector3& v3)
+{
+ return v1.triple(v2, v3);
+}
+
+/**@brief Return the linear interpolation between two vectors
+ * @param v1 One vector
+ * @param v2 The other vector
+ * @param t The ration of this to v (t = 0 => return v1, t=1 => return v2) */
+B3_FORCE_INLINE b3Vector3
+b3Lerp(const b3Vector3& v1, const b3Vector3& v2, const b3Scalar& t)
+{
+ return v1.lerp(v2, t);
+}
+
+
+
+B3_FORCE_INLINE b3Scalar b3Vector3::distance2(const b3Vector3& v) const
+{
+ return (v - *this).length2();
+}
+
+B3_FORCE_INLINE b3Scalar b3Vector3::distance(const b3Vector3& v) const
+{
+ return (v - *this).length();
+}
+
+B3_FORCE_INLINE b3Vector3 b3Vector3::normalized() const
+{
+#if defined(B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+ b3Vector3 norm = *this;
+
+ return norm.normalize();
+#else
+ return *this / length();
+#endif
+}
+
+B3_FORCE_INLINE b3Vector3 b3Vector3::rotate( const b3Vector3& wAxis, const b3Scalar _angle ) const
+{
+ // wAxis must be a unit lenght vector
+
+#if defined(B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+
+ __m128 O = _mm_mul_ps(wAxis.mVec128, mVec128);
+ b3Scalar ssin = b3Sin( _angle );
+ __m128 C = wAxis.cross( b3MakeVector3(mVec128) ).mVec128;
+ O = _mm_and_ps(O, b3vFFF0fMask);
+ b3Scalar scos = b3Cos( _angle );
+
+ __m128 vsin = _mm_load_ss(&ssin); // (S 0 0 0)
+ __m128 vcos = _mm_load_ss(&scos); // (S 0 0 0)
+
+ __m128 Y = b3_pshufd_ps(O, 0xC9); // (Y Z X 0)
+ __m128 Z = b3_pshufd_ps(O, 0xD2); // (Z X Y 0)
+ O = _mm_add_ps(O, Y);
+ vsin = b3_pshufd_ps(vsin, 0x80); // (S S S 0)
+ O = _mm_add_ps(O, Z);
+ vcos = b3_pshufd_ps(vcos, 0x80); // (S S S 0)
+
+ vsin = vsin * C;
+ O = O * wAxis.mVec128;
+ __m128 X = mVec128 - O;
+
+ O = O + vsin;
+ vcos = vcos * X;
+ O = O + vcos;
+
+ return b3MakeVector3(O);
+#else
+ b3Vector3 o = wAxis * wAxis.dot( *this );
+ b3Vector3 _x = *this - o;
+ b3Vector3 _y;
+
+ _y = wAxis.cross( *this );
+
+ return ( o + _x * b3Cos( _angle ) + _y * b3Sin( _angle ) );
+#endif
+}
+
+B3_FORCE_INLINE long b3Vector3::maxDot( const b3Vector3 *array, long array_count, b3Scalar &dotOut ) const
+{
+#if defined (B3_USE_SSE) || defined (B3_USE_NEON)
+ #if defined _WIN32 || defined (B3_USE_SSE)
+ const long scalar_cutoff = 10;
+ long b3_maxdot_large( const float *array, const float *vec, unsigned long array_count, float *dotOut );
+ #elif defined B3_USE_NEON
+ const long scalar_cutoff = 4;
+ extern long (*_maxdot_large)( const float *array, const float *vec, unsigned long array_count, float *dotOut );
+ #endif
+ if( array_count < scalar_cutoff )
+#else
+
+#endif//B3_USE_SSE || B3_USE_NEON
+ {
+ b3Scalar maxDot = -B3_INFINITY;
+ int i = 0;
+ int ptIndex = -1;
+ for( i = 0; i < array_count; i++ )
+ {
+ b3Scalar dot = array[i].dot(*this);
+
+ if( dot > maxDot )
+ {
+ maxDot = dot;
+ ptIndex = i;
+ }
+ }
+
+ b3Assert(ptIndex>=0);
+ if (ptIndex<0)
+ {
+ ptIndex = 0;
+ }
+ dotOut = maxDot;
+ return ptIndex;
+ }
+#if defined (B3_USE_SSE) || defined (B3_USE_NEON)
+ return b3_maxdot_large( (float*) array, (float*) &m_floats[0], array_count, &dotOut );
+#endif
+}
+
+B3_FORCE_INLINE long b3Vector3::minDot( const b3Vector3 *array, long array_count, b3Scalar &dotOut ) const
+{
+#if defined (B3_USE_SSE) || defined (B3_USE_NEON)
+ #if defined B3_USE_SSE
+ const long scalar_cutoff = 10;
+ long b3_mindot_large( const float *array, const float *vec, unsigned long array_count, float *dotOut );
+ #elif defined B3_USE_NEON
+ const long scalar_cutoff = 4;
+ extern long (*b3_mindot_large)( const float *array, const float *vec, unsigned long array_count, float *dotOut );
+ #else
+ #error unhandled arch!
+ #endif
+
+ if( array_count < scalar_cutoff )
+#endif//B3_USE_SSE || B3_USE_NEON
+ {
+ b3Scalar minDot = B3_INFINITY;
+ int i = 0;
+ int ptIndex = -1;
+
+ for( i = 0; i < array_count; i++ )
+ {
+ b3Scalar dot = array[i].dot(*this);
+
+ if( dot < minDot )
+ {
+ minDot = dot;
+ ptIndex = i;
+ }
+ }
+
+ dotOut = minDot;
+
+ return ptIndex;
+ }
+#if defined (B3_USE_SSE) || defined (B3_USE_NEON)
+ return b3_mindot_large( (float*) array, (float*) &m_floats[0], array_count, &dotOut );
+#endif
+}
+
+
+class b3Vector4 : public b3Vector3
+{
+public:
+
+
+
+
+
+
+ B3_FORCE_INLINE b3Vector4 absolute4() const
+ {
+#if defined(B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+ return b3MakeVector4(_mm_and_ps(mVec128, b3vAbsfMask));
+#elif defined(B3_USE_NEON)
+ return b3Vector4(vabsq_f32(mVec128));
+#else
+ return b3MakeVector4(
+ b3Fabs(m_floats[0]),
+ b3Fabs(m_floats[1]),
+ b3Fabs(m_floats[2]),
+ b3Fabs(m_floats[3]));
+#endif
+ }
+
+
+ b3Scalar getW() const { return m_floats[3];}
+
+
+ B3_FORCE_INLINE int maxAxis4() const
+ {
+ int maxIndex = -1;
+ b3Scalar maxVal = b3Scalar(-B3_LARGE_FLOAT);
+ if (m_floats[0] > maxVal)
+ {
+ maxIndex = 0;
+ maxVal = m_floats[0];
+ }
+ if (m_floats[1] > maxVal)
+ {
+ maxIndex = 1;
+ maxVal = m_floats[1];
+ }
+ if (m_floats[2] > maxVal)
+ {
+ maxIndex = 2;
+ maxVal =m_floats[2];
+ }
+ if (m_floats[3] > maxVal)
+ {
+ maxIndex = 3;
+ }
+
+ return maxIndex;
+ }
+
+
+ B3_FORCE_INLINE int minAxis4() const
+ {
+ int minIndex = -1;
+ b3Scalar minVal = b3Scalar(B3_LARGE_FLOAT);
+ if (m_floats[0] < minVal)
+ {
+ minIndex = 0;
+ minVal = m_floats[0];
+ }
+ if (m_floats[1] < minVal)
+ {
+ minIndex = 1;
+ minVal = m_floats[1];
+ }
+ if (m_floats[2] < minVal)
+ {
+ minIndex = 2;
+ minVal =m_floats[2];
+ }
+ if (m_floats[3] < minVal)
+ {
+ minIndex = 3;
+ minVal = m_floats[3];
+ }
+
+ return minIndex;
+ }
+
+
+ B3_FORCE_INLINE int closestAxis4() const
+ {
+ return absolute4().maxAxis4();
+ }
+
+
+
+
+ /**@brief Set x,y,z and zero w
+ * @param x Value of x
+ * @param y Value of y
+ * @param z Value of z
+ */
+
+
+/* void getValue(b3Scalar *m) const
+ {
+ m[0] = m_floats[0];
+ m[1] = m_floats[1];
+ m[2] =m_floats[2];
+ }
+*/
+/**@brief Set the values
+ * @param x Value of x
+ * @param y Value of y
+ * @param z Value of z
+ * @param w Value of w
+ */
+ B3_FORCE_INLINE void setValue(const b3Scalar& _x, const b3Scalar& _y, const b3Scalar& _z,const b3Scalar& _w)
+ {
+ m_floats[0]=_x;
+ m_floats[1]=_y;
+ m_floats[2]=_z;
+ m_floats[3]=_w;
+ }
+
+
+};
+
+
+///b3SwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization
+B3_FORCE_INLINE void b3SwapScalarEndian(const b3Scalar& sourceVal, b3Scalar& destVal)
+{
+ #ifdef B3_USE_DOUBLE_PRECISION
+ unsigned char* dest = (unsigned char*) &destVal;
+ unsigned char* src = (unsigned char*) &sourceVal;
+ dest[0] = src[7];
+ dest[1] = src[6];
+ dest[2] = src[5];
+ dest[3] = src[4];
+ dest[4] = src[3];
+ dest[5] = src[2];
+ dest[6] = src[1];
+ dest[7] = src[0];
+#else
+ unsigned char* dest = (unsigned char*) &destVal;
+ unsigned char* src = (unsigned char*) &sourceVal;
+ dest[0] = src[3];
+ dest[1] = src[2];
+ dest[2] = src[1];
+ dest[3] = src[0];
+#endif //B3_USE_DOUBLE_PRECISION
+}
+///b3SwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization
+B3_FORCE_INLINE void b3SwapVector3Endian(const b3Vector3& sourceVec, b3Vector3& destVec)
+{
+ for (int i=0;i<4;i++)
+ {
+ b3SwapScalarEndian(sourceVec[i],destVec[i]);
+ }
+
+}
+
+///b3UnSwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization
+B3_FORCE_INLINE void b3UnSwapVector3Endian(b3Vector3& vector)
+{
+
+ b3Vector3 swappedVec;
+ for (int i=0;i<4;i++)
+ {
+ b3SwapScalarEndian(vector[i],swappedVec[i]);
+ }
+ vector = swappedVec;
+}
+
+template <class T>
+B3_FORCE_INLINE void b3PlaneSpace1 (const T& n, T& p, T& q)
+{
+ if (b3Fabs(n[2]) > B3_SQRT12) {
+ // choose p in y-z plane
+ b3Scalar a = n[1]*n[1] + n[2]*n[2];
+ b3Scalar k = b3RecipSqrt (a);
+ p[0] = 0;
+ p[1] = -n[2]*k;
+ p[2] = n[1]*k;
+ // set q = n x p
+ q[0] = a*k;
+ q[1] = -n[0]*p[2];
+ q[2] = n[0]*p[1];
+ }
+ else {
+ // choose p in x-y plane
+ b3Scalar a = n[0]*n[0] + n[1]*n[1];
+ b3Scalar k = b3RecipSqrt (a);
+ p[0] = -n[1]*k;
+ p[1] = n[0]*k;
+ p[2] = 0;
+ // set q = n x p
+ q[0] = -n[2]*p[1];
+ q[1] = n[2]*p[0];
+ q[2] = a*k;
+ }
+}
+
+
+struct b3Vector3FloatData
+{
+ float m_floats[4];
+};
+
+struct b3Vector3DoubleData
+{
+ double m_floats[4];
+
+};
+
+B3_FORCE_INLINE void b3Vector3::serializeFloat(struct b3Vector3FloatData& dataOut) const
+{
+ ///could also do a memcpy, check if it is worth it
+ for (int i=0;i<4;i++)
+ dataOut.m_floats[i] = float(m_floats[i]);
+}
+
+B3_FORCE_INLINE void b3Vector3::deSerializeFloat(const struct b3Vector3FloatData& dataIn)
+{
+ for (int i=0;i<4;i++)
+ m_floats[i] = b3Scalar(dataIn.m_floats[i]);
+}
+
+
+B3_FORCE_INLINE void b3Vector3::serializeDouble(struct b3Vector3DoubleData& dataOut) const
+{
+ ///could also do a memcpy, check if it is worth it
+ for (int i=0;i<4;i++)
+ dataOut.m_floats[i] = double(m_floats[i]);
+}
+
+B3_FORCE_INLINE void b3Vector3::deSerializeDouble(const struct b3Vector3DoubleData& dataIn)
+{
+ for (int i=0;i<4;i++)
+ m_floats[i] = b3Scalar(dataIn.m_floats[i]);
+}
+
+
+B3_FORCE_INLINE void b3Vector3::serialize(struct b3Vector3Data& dataOut) const
+{
+ ///could also do a memcpy, check if it is worth it
+ for (int i=0;i<4;i++)
+ dataOut.m_floats[i] = m_floats[i];
+}
+
+B3_FORCE_INLINE void b3Vector3::deSerialize(const struct b3Vector3Data& dataIn)
+{
+ for (int i=0;i<4;i++)
+ m_floats[i] = dataIn.m_floats[i];
+}
+
+
+
+
+inline b3Vector3 b3MakeVector3(b3Scalar x,b3Scalar y,b3Scalar z)
+{
+ b3Vector3 tmp;
+ tmp.setValue(x,y,z);
+ return tmp;
+}
+
+inline b3Vector3 b3MakeVector3(b3Scalar x,b3Scalar y,b3Scalar z, b3Scalar w)
+{
+ b3Vector3 tmp;
+ tmp.setValue(x,y,z);
+ tmp.w = w;
+ return tmp;
+}
+
+inline b3Vector4 b3MakeVector4(b3Scalar x,b3Scalar y,b3Scalar z,b3Scalar w)
+{
+ b3Vector4 tmp;
+ tmp.setValue(x,y,z,w);
+ return tmp;
+}
+
+#if defined(B3_USE_SSE_IN_API) && defined (B3_USE_SSE)
+
+inline b3Vector3 b3MakeVector3( b3SimdFloat4 v)
+{
+ b3Vector3 tmp;
+ tmp.set128(v);
+ return tmp;
+}
+
+inline b3Vector4 b3MakeVector4(b3SimdFloat4 vec)
+{
+ b3Vector4 tmp;
+ tmp.set128(vec);
+ return tmp;
+}
+
+#endif
+
+
+#endif //B3_VECTOR3_H
diff --git a/thirdparty/bullet/src/Bullet3Common/premake4.lua b/thirdparty/bullet/src/Bullet3Common/premake4.lua
new file mode 100644
index 0000000000..1331c6327e
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Common/premake4.lua
@@ -0,0 +1,12 @@
+ project "Bullet3Common"
+
+ language "C++"
+
+ kind "StaticLib"
+
+ includedirs {".."}
+
+ files {
+ "*.cpp",
+ "*.h"
+ }
diff --git a/thirdparty/bullet/src/Bullet3Common/shared/b3Float4.h b/thirdparty/bullet/src/Bullet3Common/shared/b3Float4.h
new file mode 100644
index 0000000000..5e4b95bcee
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Common/shared/b3Float4.h
@@ -0,0 +1,97 @@
+#ifndef B3_FLOAT4_H
+#define B3_FLOAT4_H
+
+#include "Bullet3Common/shared/b3PlatformDefinitions.h"
+
+#ifdef __cplusplus
+ #include "Bullet3Common/b3Vector3.h"
+ #define b3Float4 b3Vector3
+ #define b3Float4ConstArg const b3Vector3&
+ #define b3Dot3F4 b3Dot
+ #define b3Cross3 b3Cross
+ #define b3MakeFloat4 b3MakeVector3
+ inline b3Vector3 b3Normalized(const b3Vector3& vec)
+ {
+ return vec.normalized();
+ }
+
+ inline b3Float4 b3FastNormalized3(b3Float4ConstArg v)
+ {
+ return v.normalized();
+ }
+
+ inline b3Float4 b3MaxFloat4 (const b3Float4& a, const b3Float4& b)
+ {
+ b3Float4 tmp = a;
+ tmp.setMax(b);
+ return tmp;
+ }
+ inline b3Float4 b3MinFloat4 (const b3Float4& a, const b3Float4& b)
+ {
+ b3Float4 tmp = a;
+ tmp.setMin(b);
+ return tmp;
+ }
+
+
+
+#else
+ typedef float4 b3Float4;
+ #define b3Float4ConstArg const b3Float4
+ #define b3MakeFloat4 (float4)
+ float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)
+ {
+ float4 a1 = b3MakeFloat4(v0.xyz,0.f);
+ float4 b1 = b3MakeFloat4(v1.xyz,0.f);
+ return dot(a1, b1);
+ }
+ b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)
+ {
+ float4 a1 = b3MakeFloat4(v0.xyz,0.f);
+ float4 b1 = b3MakeFloat4(v1.xyz,0.f);
+ return cross(a1, b1);
+ }
+ #define b3MinFloat4 min
+ #define b3MaxFloat4 max
+
+ #define b3Normalized(a) normalize(a)
+
+#endif
+
+
+
+inline bool b3IsAlmostZero(b3Float4ConstArg v)
+{
+ if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6)
+ return false;
+ return true;
+}
+
+
+inline int b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )
+{
+ float maxDot = -B3_INFINITY;
+ int i = 0;
+ int ptIndex = -1;
+ for( i = 0; i < vecLen; i++ )
+ {
+ float dot = b3Dot3F4(vecArray[i],vec);
+
+ if( dot > maxDot )
+ {
+ maxDot = dot;
+ ptIndex = i;
+ }
+ }
+ b3Assert(ptIndex>=0);
+ if (ptIndex<0)
+ {
+ ptIndex = 0;
+ }
+ *dotOut = maxDot;
+ return ptIndex;
+}
+
+
+
+#endif //B3_FLOAT4_H
diff --git a/thirdparty/bullet/src/Bullet3Common/shared/b3Int2.h b/thirdparty/bullet/src/Bullet3Common/shared/b3Int2.h
new file mode 100644
index 0000000000..f1d01f81a5
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Common/shared/b3Int2.h
@@ -0,0 +1,64 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2013 Erwin Coumans 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 B3_INT2_H
+#define B3_INT2_H
+
+#ifdef __cplusplus
+
+struct b3UnsignedInt2
+{
+ union
+ {
+ struct
+ {
+ unsigned int x,y;
+ };
+ struct
+ {
+ unsigned int s[2];
+ };
+ };
+};
+
+struct b3Int2
+{
+ union
+ {
+ struct
+ {
+ int x,y;
+ };
+ struct
+ {
+ int s[2];
+ };
+ };
+};
+
+inline b3Int2 b3MakeInt2(int x, int y)
+{
+ b3Int2 v;
+ v.s[0] = x; v.s[1] = y;
+ return v;
+}
+#else
+
+#define b3UnsignedInt2 uint2
+#define b3Int2 int2
+#define b3MakeInt2 (int2)
+
+#endif //__cplusplus
+#endif \ No newline at end of file
diff --git a/thirdparty/bullet/src/Bullet3Common/shared/b3Int4.h b/thirdparty/bullet/src/Bullet3Common/shared/b3Int4.h
new file mode 100644
index 0000000000..aa02d6beef
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Common/shared/b3Int4.h
@@ -0,0 +1,68 @@
+#ifndef B3_INT4_H
+#define B3_INT4_H
+
+#ifdef __cplusplus
+
+#include "Bullet3Common/b3Scalar.h"
+
+
+B3_ATTRIBUTE_ALIGNED16(struct) b3UnsignedInt4
+{
+ B3_DECLARE_ALIGNED_ALLOCATOR();
+
+ union
+ {
+ struct
+ {
+ unsigned int x,y,z,w;
+ };
+ struct
+ {
+ unsigned int s[4];
+ };
+ };
+};
+
+B3_ATTRIBUTE_ALIGNED16(struct) b3Int4
+{
+ B3_DECLARE_ALIGNED_ALLOCATOR();
+
+ union
+ {
+ struct
+ {
+ int x,y,z,w;
+ };
+ struct
+ {
+ int s[4];
+ };
+ };
+};
+
+B3_FORCE_INLINE b3Int4 b3MakeInt4(int x, int y, int z, int w = 0)
+{
+ b3Int4 v;
+ v.s[0] = x; v.s[1] = y; v.s[2] = z; v.s[3] = w;
+ return v;
+}
+
+B3_FORCE_INLINE b3UnsignedInt4 b3MakeUnsignedInt4(unsigned int x, unsigned int y, unsigned int z, unsigned int w = 0)
+{
+ b3UnsignedInt4 v;
+ v.s[0] = x; v.s[1] = y; v.s[2] = z; v.s[3] = w;
+ return v;
+}
+
+#else
+
+
+#define b3UnsignedInt4 uint4
+#define b3Int4 int4
+#define b3MakeInt4 (int4)
+#define b3MakeUnsignedInt4 (uint4)
+
+
+#endif //__cplusplus
+
+#endif //B3_INT4_H
diff --git a/thirdparty/bullet/src/Bullet3Common/shared/b3Mat3x3.h b/thirdparty/bullet/src/Bullet3Common/shared/b3Mat3x3.h
new file mode 100644
index 0000000000..7b1fef32f8
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Common/shared/b3Mat3x3.h
@@ -0,0 +1,179 @@
+
+#ifndef B3_MAT3x3_H
+#define B3_MAT3x3_H
+
+#include "Bullet3Common/shared/b3Quat.h"
+
+
+#ifdef __cplusplus
+
+#include "Bullet3Common/b3Matrix3x3.h"
+
+#define b3Mat3x3 b3Matrix3x3
+#define b3Mat3x3ConstArg const b3Matrix3x3&
+
+inline b3Mat3x3 b3QuatGetRotationMatrix(b3QuatConstArg quat)
+{
+ return b3Mat3x3(quat);
+}
+
+inline b3Mat3x3 b3AbsoluteMat3x3(b3Mat3x3ConstArg mat)
+{
+ return mat.absolute();
+}
+
+#define b3GetRow(m,row) m.getRow(row)
+
+__inline
+b3Float4 mtMul3(b3Float4ConstArg a, b3Mat3x3ConstArg b)
+{
+ return b*a;
+}
+
+
+#else
+
+typedef struct
+{
+ b3Float4 m_row[3];
+}b3Mat3x3;
+
+#define b3Mat3x3ConstArg const b3Mat3x3
+#define b3GetRow(m,row) (m.m_row[row])
+
+inline b3Mat3x3 b3QuatGetRotationMatrix(b3Quat quat)
+{
+ b3Float4 quat2 = (b3Float4)(quat.x*quat.x, quat.y*quat.y, quat.z*quat.z, 0.f);
+ b3Mat3x3 out;
+
+ out.m_row[0].x=1-2*quat2.y-2*quat2.z;
+ out.m_row[0].y=2*quat.x*quat.y-2*quat.w*quat.z;
+ out.m_row[0].z=2*quat.x*quat.z+2*quat.w*quat.y;
+ out.m_row[0].w = 0.f;
+
+ out.m_row[1].x=2*quat.x*quat.y+2*quat.w*quat.z;
+ out.m_row[1].y=1-2*quat2.x-2*quat2.z;
+ out.m_row[1].z=2*quat.y*quat.z-2*quat.w*quat.x;
+ out.m_row[1].w = 0.f;
+
+ out.m_row[2].x=2*quat.x*quat.z-2*quat.w*quat.y;
+ out.m_row[2].y=2*quat.y*quat.z+2*quat.w*quat.x;
+ out.m_row[2].z=1-2*quat2.x-2*quat2.y;
+ out.m_row[2].w = 0.f;
+
+ return out;
+}
+
+inline b3Mat3x3 b3AbsoluteMat3x3(b3Mat3x3ConstArg matIn)
+{
+ b3Mat3x3 out;
+ out.m_row[0] = fabs(matIn.m_row[0]);
+ out.m_row[1] = fabs(matIn.m_row[1]);
+ out.m_row[2] = fabs(matIn.m_row[2]);
+ return out;
+}
+
+
+__inline
+b3Mat3x3 mtZero();
+
+__inline
+b3Mat3x3 mtIdentity();
+
+__inline
+b3Mat3x3 mtTranspose(b3Mat3x3 m);
+
+__inline
+b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b);
+
+__inline
+b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b);
+
+__inline
+b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b);
+
+__inline
+b3Mat3x3 mtZero()
+{
+ b3Mat3x3 m;
+ m.m_row[0] = (b3Float4)(0.f);
+ m.m_row[1] = (b3Float4)(0.f);
+ m.m_row[2] = (b3Float4)(0.f);
+ return m;
+}
+
+__inline
+b3Mat3x3 mtIdentity()
+{
+ b3Mat3x3 m;
+ m.m_row[0] = (b3Float4)(1,0,0,0);
+ m.m_row[1] = (b3Float4)(0,1,0,0);
+ m.m_row[2] = (b3Float4)(0,0,1,0);
+ return m;
+}
+
+__inline
+b3Mat3x3 mtTranspose(b3Mat3x3 m)
+{
+ b3Mat3x3 out;
+ out.m_row[0] = (b3Float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);
+ out.m_row[1] = (b3Float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);
+ out.m_row[2] = (b3Float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);
+ return out;
+}
+
+__inline
+b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b)
+{
+ b3Mat3x3 transB;
+ transB = mtTranspose( b );
+ b3Mat3x3 ans;
+ // why this doesn't run when 0ing in the for{}
+ a.m_row[0].w = 0.f;
+ a.m_row[1].w = 0.f;
+ a.m_row[2].w = 0.f;
+ for(int i=0; i<3; i++)
+ {
+// a.m_row[i].w = 0.f;
+ ans.m_row[i].x = b3Dot3F4(a.m_row[i],transB.m_row[0]);
+ ans.m_row[i].y = b3Dot3F4(a.m_row[i],transB.m_row[1]);
+ ans.m_row[i].z = b3Dot3F4(a.m_row[i],transB.m_row[2]);
+ ans.m_row[i].w = 0.f;
+ }
+ return ans;
+}
+
+__inline
+b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b)
+{
+ b3Float4 ans;
+ ans.x = b3Dot3F4( a.m_row[0], b );
+ ans.y = b3Dot3F4( a.m_row[1], b );
+ ans.z = b3Dot3F4( a.m_row[2], b );
+ ans.w = 0.f;
+ return ans;
+}
+
+__inline
+b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b)
+{
+ b3Float4 colx = b3MakeFloat4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);
+ b3Float4 coly = b3MakeFloat4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);
+ b3Float4 colz = b3MakeFloat4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);
+
+ b3Float4 ans;
+ ans.x = b3Dot3F4( a, colx );
+ ans.y = b3Dot3F4( a, coly );
+ ans.z = b3Dot3F4( a, colz );
+ return ans;
+}
+
+
+#endif
+
+
+
+
+
+
+#endif //B3_MAT3x3_H
diff --git a/thirdparty/bullet/src/Bullet3Common/shared/b3PlatformDefinitions.h b/thirdparty/bullet/src/Bullet3Common/shared/b3PlatformDefinitions.h
new file mode 100644
index 0000000000..1c133fb088
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Common/shared/b3PlatformDefinitions.h
@@ -0,0 +1,41 @@
+#ifndef B3_PLATFORM_DEFINITIONS_H
+#define B3_PLATFORM_DEFINITIONS_H
+
+struct MyTest
+{
+ int bla;
+};
+
+#ifdef __cplusplus
+//#define b3ConstArray(a) const b3AlignedObjectArray<a>&
+#define b3ConstArray(a) const a*
+#define b3AtomicInc(a) ((*a)++)
+
+inline int b3AtomicAdd (volatile int *p, int val)
+{
+ int oldValue = *p;
+ int newValue = oldValue+val;
+ *p = newValue;
+ return oldValue;
+}
+
+#define __global
+
+#define B3_STATIC static
+#else
+//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX
+#define B3_LARGE_FLOAT 1e18f
+#define B3_INFINITY 1e18f
+#define b3Assert(a)
+#define b3ConstArray(a) __global const a*
+#define b3AtomicInc atomic_inc
+#define b3AtomicAdd atomic_add
+#define b3Fabs fabs
+#define b3Sqrt native_sqrt
+#define b3Sin native_sin
+#define b3Cos native_cos
+
+#define B3_STATIC
+#endif
+
+#endif
diff --git a/thirdparty/bullet/src/Bullet3Common/shared/b3Quat.h b/thirdparty/bullet/src/Bullet3Common/shared/b3Quat.h
new file mode 100644
index 0000000000..f262d5e08f
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Common/shared/b3Quat.h
@@ -0,0 +1,103 @@
+#ifndef B3_QUAT_H
+#define B3_QUAT_H
+
+#include "Bullet3Common/shared/b3PlatformDefinitions.h"
+#include "Bullet3Common/shared/b3Float4.h"
+
+#ifdef __cplusplus
+ #include "Bullet3Common/b3Quaternion.h"
+ #include "Bullet3Common/b3Transform.h"
+
+ #define b3Quat b3Quaternion
+ #define b3QuatConstArg const b3Quaternion&
+ inline b3Quat b3QuatInverse(b3QuatConstArg orn)
+ {
+ return orn.inverse();
+ }
+
+ inline b3Float4 b3TransformPoint(b3Float4ConstArg point, b3Float4ConstArg translation, b3QuatConstArg orientation)
+ {
+ b3Transform tr;
+ tr.setOrigin(translation);
+ tr.setRotation(orientation);
+ return tr(point);
+ }
+
+#else
+ typedef float4 b3Quat;
+ #define b3QuatConstArg const b3Quat
+
+
+inline float4 b3FastNormalize4(float4 v)
+{
+ v = (float4)(v.xyz,0.f);
+ return fast_normalize(v);
+}
+
+inline b3Quat b3QuatMul(b3Quat a, b3Quat b);
+inline b3Quat b3QuatNormalized(b3QuatConstArg in);
+inline b3Quat b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec);
+inline b3Quat b3QuatInvert(b3QuatConstArg q);
+inline b3Quat b3QuatInverse(b3QuatConstArg q);
+
+inline b3Quat b3QuatMul(b3QuatConstArg a, b3QuatConstArg b)
+{
+ b3Quat ans;
+ ans = b3Cross3( a, b );
+ ans += a.w*b+b.w*a;
+// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);
+ ans.w = a.w*b.w - b3Dot3F4(a, b);
+ return ans;
+}
+
+inline b3Quat b3QuatNormalized(b3QuatConstArg in)
+{
+ b3Quat q;
+ q=in;
+ //return b3FastNormalize4(in);
+ float len = native_sqrt(dot(q, q));
+ if(len > 0.f)
+ {
+ q *= 1.f / len;
+ }
+ else
+ {
+ q.x = q.y = q.z = 0.f;
+ q.w = 1.f;
+ }
+ return q;
+}
+inline float4 b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec)
+{
+ b3Quat qInv = b3QuatInvert( q );
+ float4 vcpy = vec;
+ vcpy.w = 0.f;
+ float4 out = b3QuatMul(b3QuatMul(q,vcpy),qInv);
+ return out;
+}
+
+
+
+inline b3Quat b3QuatInverse(b3QuatConstArg q)
+{
+ return (b3Quat)(-q.xyz, q.w);
+}
+
+inline b3Quat b3QuatInvert(b3QuatConstArg q)
+{
+ return (b3Quat)(-q.xyz, q.w);
+}
+
+inline float4 b3QuatInvRotate(b3QuatConstArg q, b3QuatConstArg vec)
+{
+ return b3QuatRotate( b3QuatInvert( q ), vec );
+}
+
+inline b3Float4 b3TransformPoint(b3Float4ConstArg point, b3Float4ConstArg translation, b3QuatConstArg orientation)
+{
+ return b3QuatRotate( orientation, point ) + (translation);
+}
+
+#endif
+
+#endif //B3_QUAT_H
diff --git a/thirdparty/bullet/src/Bullet3Dynamics/CMakeLists.txt b/thirdparty/bullet/src/Bullet3Dynamics/CMakeLists.txt
new file mode 100644
index 0000000000..94c120d9b5
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Dynamics/CMakeLists.txt
@@ -0,0 +1,61 @@
+
+INCLUDE_DIRECTORIES(
+ ${BULLET_PHYSICS_SOURCE_DIR}/src
+)
+
+SET(Bullet3Dynamics_SRCS
+ b3CpuRigidBodyPipeline.cpp
+ ConstraintSolver/b3FixedConstraint.cpp
+ ConstraintSolver/b3Generic6DofConstraint.cpp
+ ConstraintSolver/b3PgsJacobiSolver.cpp
+ ConstraintSolver/b3Point2PointConstraint.cpp
+ ConstraintSolver/b3TypedConstraint.cpp
+)
+
+SET(Bullet3Dynamics_HDRS
+ b3CpuRigidBodyPipeline.h
+ ConstraintSolver/b3ContactSolverInfo.h
+ ConstraintSolver/b3FixedConstraint.h
+ ConstraintSolver/b3Generic6DofConstraint.h
+ ConstraintSolver/b3JacobianEntry.h
+ ConstraintSolver/b3PgsJacobiSolver.h
+ ConstraintSolver/b3Point2PointConstraint.h
+ ConstraintSolver/b3SolverBody.h
+ ConstraintSolver/b3SolverConstraint.h
+ ConstraintSolver/b3TypedConstraint.h
+ shared/b3ContactConstraint4.h
+ shared/b3ConvertConstraint4.h
+ shared/b3Inertia.h
+ shared/b3IntegrateTransforms.h
+)
+
+ADD_LIBRARY(Bullet3Dynamics ${Bullet3Dynamics_SRCS} ${Bullet3Dynamics_HDRS})
+if (BUILD_SHARED_LIBS)
+ target_link_libraries(Bullet3Dynamics Bullet3Collision)
+endif ()
+SET_TARGET_PROPERTIES(Bullet3Dynamics PROPERTIES VERSION ${BULLET_VERSION})
+SET_TARGET_PROPERTIES(Bullet3Dynamics PROPERTIES SOVERSION ${BULLET_VERSION})
+
+IF (INSTALL_LIBS)
+ IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
+ #FILES_MATCHING requires CMake 2.6
+ IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
+ IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+ INSTALL(TARGETS Bullet3Dynamics DESTINATION .)
+ ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+ INSTALL(TARGETS Bullet3Dynamics
+ RUNTIME DESTINATION bin
+ LIBRARY DESTINATION lib${LIB_SUFFIX}
+ ARCHIVE DESTINATION lib${LIB_SUFFIX})
+ INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.h" PATTERN
+".svn" EXCLUDE PATTERN "CMakeFiles" EXCLUDE)
+ ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+ ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
+
+ IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+ SET_TARGET_PROPERTIES(Bullet3Dynamics PROPERTIES FRAMEWORK true)
+ SET_TARGET_PROPERTIES(Bullet3Dynamics PROPERTIES PUBLIC_HEADER "${Bullet3Dynamics_HDRS}")
+ ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+ ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
+ENDIF (INSTALL_LIBS)
diff --git a/thirdparty/bullet/src/Bullet3Dynamics/ConstraintSolver/b3ContactSolverInfo.h b/thirdparty/bullet/src/Bullet3Dynamics/ConstraintSolver/b3ContactSolverInfo.h
new file mode 100644
index 0000000000..7a12257b33
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Dynamics/ConstraintSolver/b3ContactSolverInfo.h
@@ -0,0 +1,159 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef B3_CONTACT_SOLVER_INFO
+#define B3_CONTACT_SOLVER_INFO
+
+#include "Bullet3Common/b3Scalar.h"
+
+enum b3SolverMode
+{
+ B3_SOLVER_RANDMIZE_ORDER = 1,
+ B3_SOLVER_FRICTION_SEPARATE = 2,
+ B3_SOLVER_USE_WARMSTARTING = 4,
+ B3_SOLVER_USE_2_FRICTION_DIRECTIONS = 16,
+ B3_SOLVER_ENABLE_FRICTION_DIRECTION_CACHING = 32,
+ B3_SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION = 64,
+ B3_SOLVER_CACHE_FRIENDLY = 128,
+ B3_SOLVER_SIMD = 256,
+ B3_SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS = 512,
+ B3_SOLVER_ALLOW_ZERO_LENGTH_FRICTION_DIRECTIONS = 1024
+};
+
+struct b3ContactSolverInfoData
+{
+
+
+ b3Scalar m_tau;
+ b3Scalar m_damping;//global non-contact constraint damping, can be locally overridden by constraints during 'getInfo2'.
+ b3Scalar m_friction;
+ b3Scalar m_timeStep;
+ b3Scalar m_restitution;
+ int m_numIterations;
+ b3Scalar m_maxErrorReduction;
+ b3Scalar m_sor;
+ b3Scalar m_erp;//used as Baumgarte factor
+ b3Scalar m_erp2;//used in Split Impulse
+ b3Scalar m_globalCfm;//constraint force mixing
+ int m_splitImpulse;
+ b3Scalar m_splitImpulsePenetrationThreshold;
+ b3Scalar m_splitImpulseTurnErp;
+ b3Scalar m_linearSlop;
+ b3Scalar m_warmstartingFactor;
+
+ int m_solverMode;
+ int m_restingContactRestitutionThreshold;
+ int m_minimumSolverBatchSize;
+ b3Scalar m_maxGyroscopicForce;
+ b3Scalar m_singleAxisRollingFrictionThreshold;
+
+
+};
+
+struct b3ContactSolverInfo : public b3ContactSolverInfoData
+{
+
+
+
+ inline b3ContactSolverInfo()
+ {
+ m_tau = b3Scalar(0.6);
+ m_damping = b3Scalar(1.0);
+ m_friction = b3Scalar(0.3);
+ m_timeStep = b3Scalar(1.f/60.f);
+ m_restitution = b3Scalar(0.);
+ m_maxErrorReduction = b3Scalar(20.);
+ m_numIterations = 10;
+ m_erp = b3Scalar(0.2);
+ m_erp2 = b3Scalar(0.8);
+ m_globalCfm = b3Scalar(0.);
+ m_sor = b3Scalar(1.);
+ m_splitImpulse = true;
+ m_splitImpulsePenetrationThreshold = -.04f;
+ m_splitImpulseTurnErp = 0.1f;
+ m_linearSlop = b3Scalar(0.0);
+ m_warmstartingFactor=b3Scalar(0.85);
+ //m_solverMode = B3_SOLVER_USE_WARMSTARTING | B3_SOLVER_SIMD | B3_SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION|B3_SOLVER_USE_2_FRICTION_DIRECTIONS|B3_SOLVER_ENABLE_FRICTION_DIRECTION_CACHING;// | B3_SOLVER_RANDMIZE_ORDER;
+ m_solverMode = B3_SOLVER_USE_WARMSTARTING | B3_SOLVER_SIMD;// | B3_SOLVER_RANDMIZE_ORDER;
+ m_restingContactRestitutionThreshold = 2;//unused as of 2.81
+ m_minimumSolverBatchSize = 128; //try to combine islands until the amount of constraints reaches this limit
+ m_maxGyroscopicForce = 100.f; ///only used to clamp forces for bodies that have their B3_ENABLE_GYROPSCOPIC_FORCE flag set (using b3RigidBody::setFlag)
+ m_singleAxisRollingFrictionThreshold = 1e30f;///if the velocity is above this threshold, it will use a single constraint row (axis), otherwise 3 rows.
+ }
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct b3ContactSolverInfoDoubleData
+{
+ double m_tau;
+ double m_damping;//global non-contact constraint damping, can be locally overridden by constraints during 'getInfo2'.
+ double m_friction;
+ double m_timeStep;
+ double m_restitution;
+ double m_maxErrorReduction;
+ double m_sor;
+ double m_erp;//used as Baumgarte factor
+ double m_erp2;//used in Split Impulse
+ double m_globalCfm;//constraint force mixing
+ double m_splitImpulsePenetrationThreshold;
+ double m_splitImpulseTurnErp;
+ double m_linearSlop;
+ double m_warmstartingFactor;
+ double m_maxGyroscopicForce;
+ double m_singleAxisRollingFrictionThreshold;
+
+ int m_numIterations;
+ int m_solverMode;
+ int m_restingContactRestitutionThreshold;
+ int m_minimumSolverBatchSize;
+ int m_splitImpulse;
+ char m_padding[4];
+
+};
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct b3ContactSolverInfoFloatData
+{
+ float m_tau;
+ float m_damping;//global non-contact constraint damping, can be locally overridden by constraints during 'getInfo2'.
+ float m_friction;
+ float m_timeStep;
+
+ float m_restitution;
+ float m_maxErrorReduction;
+ float m_sor;
+ float m_erp;//used as Baumgarte factor
+
+ float m_erp2;//used in Split Impulse
+ float m_globalCfm;//constraint force mixing
+ float m_splitImpulsePenetrationThreshold;
+ float m_splitImpulseTurnErp;
+
+ float m_linearSlop;
+ float m_warmstartingFactor;
+ float m_maxGyroscopicForce;
+ float m_singleAxisRollingFrictionThreshold;
+
+ int m_numIterations;
+ int m_solverMode;
+ int m_restingContactRestitutionThreshold;
+ int m_minimumSolverBatchSize;
+
+ int m_splitImpulse;
+ char m_padding[4];
+};
+
+
+
+#endif //B3_CONTACT_SOLVER_INFO
diff --git a/thirdparty/bullet/src/Bullet3Dynamics/ConstraintSolver/b3FixedConstraint.cpp b/thirdparty/bullet/src/Bullet3Dynamics/ConstraintSolver/b3FixedConstraint.cpp
new file mode 100644
index 0000000000..5e11e74935
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Dynamics/ConstraintSolver/b3FixedConstraint.cpp
@@ -0,0 +1,108 @@
+
+#include "b3FixedConstraint.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
+#include "Bullet3Common/b3TransformUtil.h"
+#include <new>
+
+
+b3FixedConstraint::b3FixedConstraint(int rbA,int rbB, const b3Transform& frameInA,const b3Transform& frameInB)
+:b3TypedConstraint(B3_FIXED_CONSTRAINT_TYPE,rbA,rbB)
+{
+ m_pivotInA = frameInA.getOrigin();
+ m_pivotInB = frameInB.getOrigin();
+ m_relTargetAB = frameInA.getRotation()*frameInB.getRotation().inverse();
+
+}
+
+b3FixedConstraint::~b3FixedConstraint ()
+{
+}
+
+
+void b3FixedConstraint::getInfo1 (b3ConstraintInfo1* info,const b3RigidBodyData* bodies)
+{
+ info->m_numConstraintRows = 6;
+ info->nub = 6;
+}
+
+void b3FixedConstraint::getInfo2 (b3ConstraintInfo2* info, const b3RigidBodyData* bodies)
+{
+ //fix the 3 linear degrees of freedom
+
+ const b3Vector3& worldPosA = bodies[m_rbA].m_pos;
+ const b3Quaternion& worldOrnA = bodies[m_rbA].m_quat;
+ const b3Vector3& worldPosB= bodies[m_rbB].m_pos;
+ const b3Quaternion& worldOrnB = bodies[m_rbB].m_quat;
+
+ info->m_J1linearAxis[0] = 1;
+ info->m_J1linearAxis[info->rowskip+1] = 1;
+ info->m_J1linearAxis[2*info->rowskip+2] = 1;
+
+ b3Vector3 a1 = b3QuatRotate(worldOrnA,m_pivotInA);
+ {
+ b3Vector3* angular0 = (b3Vector3*)(info->m_J1angularAxis);
+ b3Vector3* angular1 = (b3Vector3*)(info->m_J1angularAxis+info->rowskip);
+ b3Vector3* angular2 = (b3Vector3*)(info->m_J1angularAxis+2*info->rowskip);
+ b3Vector3 a1neg = -a1;
+ a1neg.getSkewSymmetricMatrix(angular0,angular1,angular2);
+ }
+
+ if (info->m_J2linearAxis)
+ {
+ info->m_J2linearAxis[0] = -1;
+ info->m_J2linearAxis[info->rowskip+1] = -1;
+ info->m_J2linearAxis[2*info->rowskip+2] = -1;
+ }
+
+ b3Vector3 a2 = b3QuatRotate(worldOrnB,m_pivotInB);
+
+ {
+ // b3Vector3 a2n = -a2;
+ b3Vector3* angular0 = (b3Vector3*)(info->m_J2angularAxis);
+ b3Vector3* angular1 = (b3Vector3*)(info->m_J2angularAxis+info->rowskip);
+ b3Vector3* angular2 = (b3Vector3*)(info->m_J2angularAxis+2*info->rowskip);
+ a2.getSkewSymmetricMatrix(angular0,angular1,angular2);
+ }
+
+ // set right hand side for the linear dofs
+ b3Scalar k = info->fps * info->erp;
+ b3Vector3 linearError = k*(a2+worldPosB-a1-worldPosA);
+ int j;
+ for (j=0; j<3; j++)
+ {
+ info->m_constraintError[j*info->rowskip] = linearError[j];
+ //printf("info->m_constraintError[%d]=%f\n",j,info->m_constraintError[j]);
+ }
+
+ //fix the 3 angular degrees of freedom
+
+ int start_row = 3;
+ int s = info->rowskip;
+ int start_index = start_row * s;
+
+ // 3 rows to make body rotations equal
+ info->m_J1angularAxis[start_index] = 1;
+ info->m_J1angularAxis[start_index + s + 1] = 1;
+ info->m_J1angularAxis[start_index + s*2+2] = 1;
+ if ( info->m_J2angularAxis)
+ {
+ info->m_J2angularAxis[start_index] = -1;
+ info->m_J2angularAxis[start_index + s+1] = -1;
+ info->m_J2angularAxis[start_index + s*2+2] = -1;
+ }
+
+
+ // set right hand side for the angular dofs
+
+ b3Vector3 diff;
+ b3Scalar angle;
+ b3Quaternion qrelCur = worldOrnA *worldOrnB.inverse();
+
+ b3TransformUtil::calculateDiffAxisAngleQuaternion(m_relTargetAB,qrelCur,diff,angle);
+ diff*=-angle;
+ for (j=0; j<3; j++)
+ {
+ info->m_constraintError[(3+j)*info->rowskip] = k * diff[j];
+ }
+
+} \ No newline at end of file
diff --git a/thirdparty/bullet/src/Bullet3Dynamics/ConstraintSolver/b3FixedConstraint.h b/thirdparty/bullet/src/Bullet3Dynamics/ConstraintSolver/b3FixedConstraint.h
new file mode 100644
index 0000000000..e884a82912
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Dynamics/ConstraintSolver/b3FixedConstraint.h
@@ -0,0 +1,35 @@
+
+#ifndef B3_FIXED_CONSTRAINT_H
+#define B3_FIXED_CONSTRAINT_H
+
+#include "b3TypedConstraint.h"
+
+B3_ATTRIBUTE_ALIGNED16(class) b3FixedConstraint : public b3TypedConstraint
+{
+ b3Vector3 m_pivotInA;
+ b3Vector3 m_pivotInB;
+ b3Quaternion m_relTargetAB;
+
+public:
+ b3FixedConstraint(int rbA,int rbB, const b3Transform& frameInA,const b3Transform& frameInB);
+
+ virtual ~b3FixedConstraint();
+
+
+ virtual void getInfo1 (b3ConstraintInfo1* info,const b3RigidBodyData* bodies);
+
+ virtual void getInfo2 (b3ConstraintInfo2* info, const b3RigidBodyData* bodies);
+
+ virtual void setParam(int num, b3Scalar value, int axis = -1)
+ {
+ b3Assert(0);
+ }
+ virtual b3Scalar getParam(int num, int axis = -1) const
+ {
+ b3Assert(0);
+ return 0.f;
+ }
+
+};
+
+#endif //B3_FIXED_CONSTRAINT_H
diff --git a/thirdparty/bullet/src/Bullet3Dynamics/ConstraintSolver/b3Generic6DofConstraint.cpp b/thirdparty/bullet/src/Bullet3Dynamics/ConstraintSolver/b3Generic6DofConstraint.cpp
new file mode 100644
index 0000000000..168a773d56
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Dynamics/ConstraintSolver/b3Generic6DofConstraint.cpp
@@ -0,0 +1,807 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+/*
+2007-09-09
+Refactored by Francisco Le?n
+email: projectileman@yahoo.com
+http://gimpact.sf.net
+*/
+
+#include "b3Generic6DofConstraint.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
+
+#include "Bullet3Common/b3TransformUtil.h"
+#include "Bullet3Common/b3TransformUtil.h"
+#include <new>
+
+
+
+#define D6_USE_OBSOLETE_METHOD false
+#define D6_USE_FRAME_OFFSET true
+
+
+
+
+
+
+b3Generic6DofConstraint::b3Generic6DofConstraint(int rbA,int rbB, const b3Transform& frameInA, const b3Transform& frameInB, bool useLinearReferenceFrameA, const b3RigidBodyData* bodies)
+: b3TypedConstraint(B3_D6_CONSTRAINT_TYPE, rbA, rbB)
+, m_frameInA(frameInA)
+, m_frameInB(frameInB),
+m_useLinearReferenceFrameA(useLinearReferenceFrameA),
+m_useOffsetForConstraintFrame(D6_USE_FRAME_OFFSET),
+m_flags(0)
+{
+ calculateTransforms(bodies);
+}
+
+
+
+
+
+
+#define GENERIC_D6_DISABLE_WARMSTARTING 1
+
+
+
+b3Scalar btGetMatrixElem(const b3Matrix3x3& mat, int index);
+b3Scalar btGetMatrixElem(const b3Matrix3x3& mat, int index)
+{
+ int i = index%3;
+ int j = index/3;
+ return mat[i][j];
+}
+
+
+
+///MatrixToEulerXYZ from http://www.geometrictools.com/LibFoundation/Mathematics/Wm4Matrix3.inl.html
+bool matrixToEulerXYZ(const b3Matrix3x3& mat,b3Vector3& xyz);
+bool matrixToEulerXYZ(const b3Matrix3x3& mat,b3Vector3& xyz)
+{
+ // // rot = cy*cz -cy*sz sy
+ // // cz*sx*sy+cx*sz cx*cz-sx*sy*sz -cy*sx
+ // // -cx*cz*sy+sx*sz cz*sx+cx*sy*sz cx*cy
+ //
+
+ b3Scalar fi = btGetMatrixElem(mat,2);
+ if (fi < b3Scalar(1.0f))
+ {
+ if (fi > b3Scalar(-1.0f))
+ {
+ xyz[0] = b3Atan2(-btGetMatrixElem(mat,5),btGetMatrixElem(mat,8));
+ xyz[1] = b3Asin(btGetMatrixElem(mat,2));
+ xyz[2] = b3Atan2(-btGetMatrixElem(mat,1),btGetMatrixElem(mat,0));
+ return true;
+ }
+ else
+ {
+ // WARNING. Not unique. XA - ZA = -atan2(r10,r11)
+ xyz[0] = -b3Atan2(btGetMatrixElem(mat,3),btGetMatrixElem(mat,4));
+ xyz[1] = -B3_HALF_PI;
+ xyz[2] = b3Scalar(0.0);
+ return false;
+ }
+ }
+ else
+ {
+ // WARNING. Not unique. XAngle + ZAngle = atan2(r10,r11)
+ xyz[0] = b3Atan2(btGetMatrixElem(mat,3),btGetMatrixElem(mat,4));
+ xyz[1] = B3_HALF_PI;
+ xyz[2] = 0.0;
+ }
+ return false;
+}
+
+//////////////////////////// b3RotationalLimitMotor ////////////////////////////////////
+
+int b3RotationalLimitMotor::testLimitValue(b3Scalar test_value)
+{
+ if(m_loLimit>m_hiLimit)
+ {
+ m_currentLimit = 0;//Free from violation
+ return 0;
+ }
+ if (test_value < m_loLimit)
+ {
+ m_currentLimit = 1;//low limit violation
+ m_currentLimitError = test_value - m_loLimit;
+ if(m_currentLimitError>B3_PI)
+ m_currentLimitError-=B3_2_PI;
+ else if(m_currentLimitError<-B3_PI)
+ m_currentLimitError+=B3_2_PI;
+ return 1;
+ }
+ else if (test_value> m_hiLimit)
+ {
+ m_currentLimit = 2;//High limit violation
+ m_currentLimitError = test_value - m_hiLimit;
+ if(m_currentLimitError>B3_PI)
+ m_currentLimitError-=B3_2_PI;
+ else if(m_currentLimitError<-B3_PI)
+ m_currentLimitError+=B3_2_PI;
+ return 2;
+ };
+
+ m_currentLimit = 0;//Free from violation
+ return 0;
+
+}
+
+
+
+
+//////////////////////////// End b3RotationalLimitMotor ////////////////////////////////////
+
+
+
+
+//////////////////////////// b3TranslationalLimitMotor ////////////////////////////////////
+
+
+int b3TranslationalLimitMotor::testLimitValue(int limitIndex, b3Scalar test_value)
+{
+ b3Scalar loLimit = m_lowerLimit[limitIndex];
+ b3Scalar hiLimit = m_upperLimit[limitIndex];
+ if(loLimit > hiLimit)
+ {
+ m_currentLimit[limitIndex] = 0;//Free from violation
+ m_currentLimitError[limitIndex] = b3Scalar(0.f);
+ return 0;
+ }
+
+ if (test_value < loLimit)
+ {
+ m_currentLimit[limitIndex] = 2;//low limit violation
+ m_currentLimitError[limitIndex] = test_value - loLimit;
+ return 2;
+ }
+ else if (test_value> hiLimit)
+ {
+ m_currentLimit[limitIndex] = 1;//High limit violation
+ m_currentLimitError[limitIndex] = test_value - hiLimit;
+ return 1;
+ };
+
+ m_currentLimit[limitIndex] = 0;//Free from violation
+ m_currentLimitError[limitIndex] = b3Scalar(0.f);
+ return 0;
+}
+
+
+
+//////////////////////////// b3TranslationalLimitMotor ////////////////////////////////////
+
+void b3Generic6DofConstraint::calculateAngleInfo()
+{
+ b3Matrix3x3 relative_frame = m_calculatedTransformA.getBasis().inverse()*m_calculatedTransformB.getBasis();
+ matrixToEulerXYZ(relative_frame,m_calculatedAxisAngleDiff);
+ // in euler angle mode we do not actually constrain the angular velocity
+ // along the axes axis[0] and axis[2] (although we do use axis[1]) :
+ //
+ // to get constrain w2-w1 along ...not
+ // ------ --------------------- ------
+ // d(angle[0])/dt = 0 ax[1] x ax[2] ax[0]
+ // d(angle[1])/dt = 0 ax[1]
+ // d(angle[2])/dt = 0 ax[0] x ax[1] ax[2]
+ //
+ // constraining w2-w1 along an axis 'a' means that a'*(w2-w1)=0.
+ // to prove the result for angle[0], write the expression for angle[0] from
+ // GetInfo1 then take the derivative. to prove this for angle[2] it is
+ // easier to take the euler rate expression for d(angle[2])/dt with respect
+ // to the components of w and set that to 0.
+ b3Vector3 axis0 = m_calculatedTransformB.getBasis().getColumn(0);
+ b3Vector3 axis2 = m_calculatedTransformA.getBasis().getColumn(2);
+
+ m_calculatedAxis[1] = axis2.cross(axis0);
+ m_calculatedAxis[0] = m_calculatedAxis[1].cross(axis2);
+ m_calculatedAxis[2] = axis0.cross(m_calculatedAxis[1]);
+
+ m_calculatedAxis[0].normalize();
+ m_calculatedAxis[1].normalize();
+ m_calculatedAxis[2].normalize();
+
+}
+
+static b3Transform getCenterOfMassTransform(const b3RigidBodyData& body)
+{
+ b3Transform tr(body.m_quat,body.m_pos);
+ return tr;
+}
+
+void b3Generic6DofConstraint::calculateTransforms(const b3RigidBodyData* bodies)
+{
+ b3Transform transA;
+ b3Transform transB;
+ transA = getCenterOfMassTransform(bodies[m_rbA]);
+ transB = getCenterOfMassTransform(bodies[m_rbB]);
+ calculateTransforms(transA,transB,bodies);
+}
+
+void b3Generic6DofConstraint::calculateTransforms(const b3Transform& transA,const b3Transform& transB,const b3RigidBodyData* bodies)
+{
+ m_calculatedTransformA = transA * m_frameInA;
+ m_calculatedTransformB = transB * m_frameInB;
+ calculateLinearInfo();
+ calculateAngleInfo();
+ if(m_useOffsetForConstraintFrame)
+ { // get weight factors depending on masses
+ b3Scalar miA = bodies[m_rbA].m_invMass;
+ b3Scalar miB = bodies[m_rbB].m_invMass;
+ m_hasStaticBody = (miA < B3_EPSILON) || (miB < B3_EPSILON);
+ b3Scalar miS = miA + miB;
+ if(miS > b3Scalar(0.f))
+ {
+ m_factA = miB / miS;
+ }
+ else
+ {
+ m_factA = b3Scalar(0.5f);
+ }
+ m_factB = b3Scalar(1.0f) - m_factA;
+ }
+}
+
+
+
+
+
+
+
+bool b3Generic6DofConstraint::testAngularLimitMotor(int axis_index)
+{
+ b3Scalar angle = m_calculatedAxisAngleDiff[axis_index];
+ angle = b3AdjustAngleToLimits(angle, m_angularLimits[axis_index].m_loLimit, m_angularLimits[axis_index].m_hiLimit);
+ m_angularLimits[axis_index].m_currentPosition = angle;
+ //test limits
+ m_angularLimits[axis_index].testLimitValue(angle);
+ return m_angularLimits[axis_index].needApplyTorques();
+}
+
+
+
+
+void b3Generic6DofConstraint::getInfo1 (b3ConstraintInfo1* info,const b3RigidBodyData* bodies)
+{
+ //prepare constraint
+ calculateTransforms(getCenterOfMassTransform(bodies[m_rbA]),getCenterOfMassTransform(bodies[m_rbB]),bodies);
+ info->m_numConstraintRows = 0;
+ info->nub = 6;
+ int i;
+ //test linear limits
+ for(i = 0; i < 3; i++)
+ {
+ if(m_linearLimits.needApplyForce(i))
+ {
+ info->m_numConstraintRows++;
+ info->nub--;
+ }
+ }
+ //test angular limits
+ for (i=0;i<3 ;i++ )
+ {
+ if(testAngularLimitMotor(i))
+ {
+ info->m_numConstraintRows++;
+ info->nub--;
+ }
+ }
+// printf("info->m_numConstraintRows=%d\n",info->m_numConstraintRows);
+}
+
+void b3Generic6DofConstraint::getInfo1NonVirtual (b3ConstraintInfo1* info,const b3RigidBodyData* bodies)
+{
+ //pre-allocate all 6
+ info->m_numConstraintRows = 6;
+ info->nub = 0;
+}
+
+
+void b3Generic6DofConstraint::getInfo2 (b3ConstraintInfo2* info,const b3RigidBodyData* bodies)
+{
+
+ b3Transform transA = getCenterOfMassTransform(bodies[m_rbA]);
+ b3Transform transB = getCenterOfMassTransform(bodies[m_rbB]);
+ const b3Vector3& linVelA = bodies[m_rbA].m_linVel;
+ const b3Vector3& linVelB = bodies[m_rbB].m_linVel;
+ const b3Vector3& angVelA = bodies[m_rbA].m_angVel;
+ const b3Vector3& angVelB = bodies[m_rbB].m_angVel;
+
+ if(m_useOffsetForConstraintFrame)
+ { // for stability better to solve angular limits first
+ int row = setAngularLimits(info, 0,transA,transB,linVelA,linVelB,angVelA,angVelB);
+ setLinearLimits(info, row, transA,transB,linVelA,linVelB,angVelA,angVelB);
+ }
+ else
+ { // leave old version for compatibility
+ int row = setLinearLimits(info, 0, transA,transB,linVelA,linVelB,angVelA,angVelB);
+ setAngularLimits(info, row,transA,transB,linVelA,linVelB,angVelA,angVelB);
+ }
+
+}
+
+
+void b3Generic6DofConstraint::getInfo2NonVirtual (b3ConstraintInfo2* info, const b3Transform& transA,const b3Transform& transB,const b3Vector3& linVelA,const b3Vector3& linVelB,const b3Vector3& angVelA,const b3Vector3& angVelB,const b3RigidBodyData* bodies)
+{
+
+ //prepare constraint
+ calculateTransforms(transA,transB,bodies);
+
+ int i;
+ for (i=0;i<3 ;i++ )
+ {
+ testAngularLimitMotor(i);
+ }
+
+ if(m_useOffsetForConstraintFrame)
+ { // for stability better to solve angular limits first
+ int row = setAngularLimits(info, 0,transA,transB,linVelA,linVelB,angVelA,angVelB);
+ setLinearLimits(info, row, transA,transB,linVelA,linVelB,angVelA,angVelB);
+ }
+ else
+ { // leave old version for compatibility
+ int row = setLinearLimits(info, 0, transA,transB,linVelA,linVelB,angVelA,angVelB);
+ setAngularLimits(info, row,transA,transB,linVelA,linVelB,angVelA,angVelB);
+ }
+}
+
+
+
+int b3Generic6DofConstraint::setLinearLimits(b3ConstraintInfo2* info, int row, const b3Transform& transA,const b3Transform& transB,const b3Vector3& linVelA,const b3Vector3& linVelB,const b3Vector3& angVelA,const b3Vector3& angVelB)
+{
+// int row = 0;
+ //solve linear limits
+ b3RotationalLimitMotor limot;
+ for (int i=0;i<3 ;i++ )
+ {
+ if(m_linearLimits.needApplyForce(i))
+ { // re-use rotational motor code
+ limot.m_bounce = b3Scalar(0.f);
+ limot.m_currentLimit = m_linearLimits.m_currentLimit[i];
+ limot.m_currentPosition = m_linearLimits.m_currentLinearDiff[i];
+ limot.m_currentLimitError = m_linearLimits.m_currentLimitError[i];
+ limot.m_damping = m_linearLimits.m_damping;
+ limot.m_enableMotor = m_linearLimits.m_enableMotor[i];
+ limot.m_hiLimit = m_linearLimits.m_upperLimit[i];
+ limot.m_limitSoftness = m_linearLimits.m_limitSoftness;
+ limot.m_loLimit = m_linearLimits.m_lowerLimit[i];
+ limot.m_maxLimitForce = b3Scalar(0.f);
+ limot.m_maxMotorForce = m_linearLimits.m_maxMotorForce[i];
+ limot.m_targetVelocity = m_linearLimits.m_targetVelocity[i];
+ b3Vector3 axis = m_calculatedTransformA.getBasis().getColumn(i);
+ int flags = m_flags >> (i * B3_6DOF_FLAGS_AXIS_SHIFT);
+ limot.m_normalCFM = (flags & B3_6DOF_FLAGS_CFM_NORM) ? m_linearLimits.m_normalCFM[i] : info->cfm[0];
+ limot.m_stopCFM = (flags & B3_6DOF_FLAGS_CFM_STOP) ? m_linearLimits.m_stopCFM[i] : info->cfm[0];
+ limot.m_stopERP = (flags & B3_6DOF_FLAGS_ERP_STOP) ? m_linearLimits.m_stopERP[i] : info->erp;
+ if(m_useOffsetForConstraintFrame)
+ {
+ int indx1 = (i + 1) % 3;
+ int indx2 = (i + 2) % 3;
+ int rotAllowed = 1; // rotations around orthos to current axis
+ if(m_angularLimits[indx1].m_currentLimit && m_angularLimits[indx2].m_currentLimit)
+ {
+ rotAllowed = 0;
+ }
+ row += get_limit_motor_info2(&limot, transA,transB,linVelA,linVelB,angVelA,angVelB, info, row, axis, 0, rotAllowed);
+ }
+ else
+ {
+ row += get_limit_motor_info2(&limot, transA,transB,linVelA,linVelB,angVelA,angVelB, info, row, axis, 0);
+ }
+ }
+ }
+ return row;
+}
+
+
+
+int b3Generic6DofConstraint::setAngularLimits(b3ConstraintInfo2 *info, int row_offset, const b3Transform& transA,const b3Transform& transB,const b3Vector3& linVelA,const b3Vector3& linVelB,const b3Vector3& angVelA,const b3Vector3& angVelB)
+{
+ b3Generic6DofConstraint * d6constraint = this;
+ int row = row_offset;
+ //solve angular limits
+ for (int i=0;i<3 ;i++ )
+ {
+ if(d6constraint->getRotationalLimitMotor(i)->needApplyTorques())
+ {
+ b3Vector3 axis = d6constraint->getAxis(i);
+ int flags = m_flags >> ((i + 3) * B3_6DOF_FLAGS_AXIS_SHIFT);
+ if(!(flags & B3_6DOF_FLAGS_CFM_NORM))
+ {
+ m_angularLimits[i].m_normalCFM = info->cfm[0];
+ }
+ if(!(flags & B3_6DOF_FLAGS_CFM_STOP))
+ {
+ m_angularLimits[i].m_stopCFM = info->cfm[0];
+ }
+ if(!(flags & B3_6DOF_FLAGS_ERP_STOP))
+ {
+ m_angularLimits[i].m_stopERP = info->erp;
+ }
+ row += get_limit_motor_info2(d6constraint->getRotationalLimitMotor(i),
+ transA,transB,linVelA,linVelB,angVelA,angVelB, info,row,axis,1);
+ }
+ }
+
+ return row;
+}
+
+
+
+
+void b3Generic6DofConstraint::updateRHS(b3Scalar timeStep)
+{
+ (void)timeStep;
+
+}
+
+
+void b3Generic6DofConstraint::setFrames(const b3Transform& frameA, const b3Transform& frameB,const b3RigidBodyData* bodies)
+{
+ m_frameInA = frameA;
+ m_frameInB = frameB;
+
+ calculateTransforms(bodies);
+}
+
+
+
+b3Vector3 b3Generic6DofConstraint::getAxis(int axis_index) const
+{
+ return m_calculatedAxis[axis_index];
+}
+
+
+b3Scalar b3Generic6DofConstraint::getRelativePivotPosition(int axisIndex) const
+{
+ return m_calculatedLinearDiff[axisIndex];
+}
+
+
+b3Scalar b3Generic6DofConstraint::getAngle(int axisIndex) const
+{
+ return m_calculatedAxisAngleDiff[axisIndex];
+}
+
+
+
+void b3Generic6DofConstraint::calcAnchorPos(const b3RigidBodyData* bodies)
+{
+ b3Scalar imA = bodies[m_rbA].m_invMass;
+ b3Scalar imB = bodies[m_rbB].m_invMass;
+ b3Scalar weight;
+ if(imB == b3Scalar(0.0))
+ {
+ weight = b3Scalar(1.0);
+ }
+ else
+ {
+ weight = imA / (imA + imB);
+ }
+ const b3Vector3& pA = m_calculatedTransformA.getOrigin();
+ const b3Vector3& pB = m_calculatedTransformB.getOrigin();
+ m_AnchorPos = pA * weight + pB * (b3Scalar(1.0) - weight);
+ return;
+}
+
+
+
+void b3Generic6DofConstraint::calculateLinearInfo()
+{
+ m_calculatedLinearDiff = m_calculatedTransformB.getOrigin() - m_calculatedTransformA.getOrigin();
+ m_calculatedLinearDiff = m_calculatedTransformA.getBasis().inverse() * m_calculatedLinearDiff;
+ for(int i = 0; i < 3; i++)
+ {
+ m_linearLimits.m_currentLinearDiff[i] = m_calculatedLinearDiff[i];
+ m_linearLimits.testLimitValue(i, m_calculatedLinearDiff[i]);
+ }
+}
+
+
+
+int b3Generic6DofConstraint::get_limit_motor_info2(
+ b3RotationalLimitMotor * limot,
+ const b3Transform& transA,const b3Transform& transB,const b3Vector3& linVelA,const b3Vector3& linVelB,const b3Vector3& angVelA,const b3Vector3& angVelB,
+ b3ConstraintInfo2 *info, int row, b3Vector3& ax1, int rotational,int rotAllowed)
+{
+ int srow = row * info->rowskip;
+ bool powered = limot->m_enableMotor;
+ int limit = limot->m_currentLimit;
+ if (powered || limit)
+ { // if the joint is powered, or has joint limits, add in the extra row
+ b3Scalar *J1 = rotational ? info->m_J1angularAxis : info->m_J1linearAxis;
+ b3Scalar *J2 = rotational ? info->m_J2angularAxis : info->m_J2linearAxis;
+ if (J1)
+ {
+ J1[srow+0] = ax1[0];
+ J1[srow+1] = ax1[1];
+ J1[srow+2] = ax1[2];
+ }
+ if (J2)
+ {
+ J2[srow+0] = -ax1[0];
+ J2[srow+1] = -ax1[1];
+ J2[srow+2] = -ax1[2];
+ }
+ if((!rotational))
+ {
+ if (m_useOffsetForConstraintFrame)
+ {
+ b3Vector3 tmpA, tmpB, relA, relB;
+ // get vector from bodyB to frameB in WCS
+ relB = m_calculatedTransformB.getOrigin() - transB.getOrigin();
+ // get its projection to constraint axis
+ b3Vector3 projB = ax1 * relB.dot(ax1);
+ // get vector directed from bodyB to constraint axis (and orthogonal to it)
+ b3Vector3 orthoB = relB - projB;
+ // same for bodyA
+ relA = m_calculatedTransformA.getOrigin() - transA.getOrigin();
+ b3Vector3 projA = ax1 * relA.dot(ax1);
+ b3Vector3 orthoA = relA - projA;
+ // get desired offset between frames A and B along constraint axis
+ b3Scalar desiredOffs = limot->m_currentPosition - limot->m_currentLimitError;
+ // desired vector from projection of center of bodyA to projection of center of bodyB to constraint axis
+ b3Vector3 totalDist = projA + ax1 * desiredOffs - projB;
+ // get offset vectors relA and relB
+ relA = orthoA + totalDist * m_factA;
+ relB = orthoB - totalDist * m_factB;
+ tmpA = relA.cross(ax1);
+ tmpB = relB.cross(ax1);
+ if(m_hasStaticBody && (!rotAllowed))
+ {
+ tmpA *= m_factA;
+ tmpB *= m_factB;
+ }
+ int i;
+ for (i=0; i<3; i++) info->m_J1angularAxis[srow+i] = tmpA[i];
+ for (i=0; i<3; i++) info->m_J2angularAxis[srow+i] = -tmpB[i];
+ } else
+ {
+ b3Vector3 ltd; // Linear Torque Decoupling vector
+ b3Vector3 c = m_calculatedTransformB.getOrigin() - transA.getOrigin();
+ ltd = c.cross(ax1);
+ info->m_J1angularAxis[srow+0] = ltd[0];
+ info->m_J1angularAxis[srow+1] = ltd[1];
+ info->m_J1angularAxis[srow+2] = ltd[2];
+
+ c = m_calculatedTransformB.getOrigin() - transB.getOrigin();
+ ltd = -c.cross(ax1);
+ info->m_J2angularAxis[srow+0] = ltd[0];
+ info->m_J2angularAxis[srow+1] = ltd[1];
+ info->m_J2angularAxis[srow+2] = ltd[2];
+ }
+ }
+ // if we're limited low and high simultaneously, the joint motor is
+ // ineffective
+ if (limit && (limot->m_loLimit == limot->m_hiLimit)) powered = false;
+ info->m_constraintError[srow] = b3Scalar(0.f);
+ if (powered)
+ {
+ info->cfm[srow] = limot->m_normalCFM;
+ if(!limit)
+ {
+ b3Scalar tag_vel = rotational ? limot->m_targetVelocity : -limot->m_targetVelocity;
+
+ b3Scalar mot_fact = getMotorFactor( limot->m_currentPosition,
+ limot->m_loLimit,
+ limot->m_hiLimit,
+ tag_vel,
+ info->fps * limot->m_stopERP);
+ info->m_constraintError[srow] += mot_fact * limot->m_targetVelocity;
+ info->m_lowerLimit[srow] = -limot->m_maxMotorForce;
+ info->m_upperLimit[srow] = limot->m_maxMotorForce;
+ }
+ }
+ if(limit)
+ {
+ b3Scalar k = info->fps * limot->m_stopERP;
+ if(!rotational)
+ {
+ info->m_constraintError[srow] += k * limot->m_currentLimitError;
+ }
+ else
+ {
+ info->m_constraintError[srow] += -k * limot->m_currentLimitError;
+ }
+ info->cfm[srow] = limot->m_stopCFM;
+ if (limot->m_loLimit == limot->m_hiLimit)
+ { // limited low and high simultaneously
+ info->m_lowerLimit[srow] = -B3_INFINITY;
+ info->m_upperLimit[srow] = B3_INFINITY;
+ }
+ else
+ {
+ if (limit == 1)
+ {
+ info->m_lowerLimit[srow] = 0;
+ info->m_upperLimit[srow] = B3_INFINITY;
+ }
+ else
+ {
+ info->m_lowerLimit[srow] = -B3_INFINITY;
+ info->m_upperLimit[srow] = 0;
+ }
+ // deal with bounce
+ if (limot->m_bounce > 0)
+ {
+ // calculate joint velocity
+ b3Scalar vel;
+ if (rotational)
+ {
+ vel = angVelA.dot(ax1);
+//make sure that if no body -> angVelB == zero vec
+// if (body1)
+ vel -= angVelB.dot(ax1);
+ }
+ else
+ {
+ vel = linVelA.dot(ax1);
+//make sure that if no body -> angVelB == zero vec
+// if (body1)
+ vel -= linVelB.dot(ax1);
+ }
+ // only apply bounce if the velocity is incoming, and if the
+ // resulting c[] exceeds what we already have.
+ if (limit == 1)
+ {
+ if (vel < 0)
+ {
+ b3Scalar newc = -limot->m_bounce* vel;
+ if (newc > info->m_constraintError[srow])
+ info->m_constraintError[srow] = newc;
+ }
+ }
+ else
+ {
+ if (vel > 0)
+ {
+ b3Scalar newc = -limot->m_bounce * vel;
+ if (newc < info->m_constraintError[srow])
+ info->m_constraintError[srow] = newc;
+ }
+ }
+ }
+ }
+ }
+ return 1;
+ }
+ else return 0;
+}
+
+
+
+
+
+
+ ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
+ ///If no axis is provided, it uses the default axis for this constraint.
+void b3Generic6DofConstraint::setParam(int num, b3Scalar value, int axis)
+{
+ if((axis >= 0) && (axis < 3))
+ {
+ switch(num)
+ {
+ case B3_CONSTRAINT_STOP_ERP :
+ m_linearLimits.m_stopERP[axis] = value;
+ m_flags |= B3_6DOF_FLAGS_ERP_STOP << (axis * B3_6DOF_FLAGS_AXIS_SHIFT);
+ break;
+ case B3_CONSTRAINT_STOP_CFM :
+ m_linearLimits.m_stopCFM[axis] = value;
+ m_flags |= B3_6DOF_FLAGS_CFM_STOP << (axis * B3_6DOF_FLAGS_AXIS_SHIFT);
+ break;
+ case B3_CONSTRAINT_CFM :
+ m_linearLimits.m_normalCFM[axis] = value;
+ m_flags |= B3_6DOF_FLAGS_CFM_NORM << (axis * B3_6DOF_FLAGS_AXIS_SHIFT);
+ break;
+ default :
+ b3AssertConstrParams(0);
+ }
+ }
+ else if((axis >=3) && (axis < 6))
+ {
+ switch(num)
+ {
+ case B3_CONSTRAINT_STOP_ERP :
+ m_angularLimits[axis - 3].m_stopERP = value;
+ m_flags |= B3_6DOF_FLAGS_ERP_STOP << (axis * B3_6DOF_FLAGS_AXIS_SHIFT);
+ break;
+ case B3_CONSTRAINT_STOP_CFM :
+ m_angularLimits[axis - 3].m_stopCFM = value;
+ m_flags |= B3_6DOF_FLAGS_CFM_STOP << (axis * B3_6DOF_FLAGS_AXIS_SHIFT);
+ break;
+ case B3_CONSTRAINT_CFM :
+ m_angularLimits[axis - 3].m_normalCFM = value;
+ m_flags |= B3_6DOF_FLAGS_CFM_NORM << (axis * B3_6DOF_FLAGS_AXIS_SHIFT);
+ break;
+ default :
+ b3AssertConstrParams(0);
+ }
+ }
+ else
+ {
+ b3AssertConstrParams(0);
+ }
+}
+
+ ///return the local value of parameter
+b3Scalar b3Generic6DofConstraint::getParam(int num, int axis) const
+{
+ b3Scalar retVal = 0;
+ if((axis >= 0) && (axis < 3))
+ {
+ switch(num)
+ {
+ case B3_CONSTRAINT_STOP_ERP :
+ b3AssertConstrParams(m_flags & (B3_6DOF_FLAGS_ERP_STOP << (axis * B3_6DOF_FLAGS_AXIS_SHIFT)));
+ retVal = m_linearLimits.m_stopERP[axis];
+ break;
+ case B3_CONSTRAINT_STOP_CFM :
+ b3AssertConstrParams(m_flags & (B3_6DOF_FLAGS_CFM_STOP << (axis * B3_6DOF_FLAGS_AXIS_SHIFT)));
+ retVal = m_linearLimits.m_stopCFM[axis];
+ break;
+ case B3_CONSTRAINT_CFM :
+ b3AssertConstrParams(m_flags & (B3_6DOF_FLAGS_CFM_NORM << (axis * B3_6DOF_FLAGS_AXIS_SHIFT)));
+ retVal = m_linearLimits.m_normalCFM[axis];
+ break;
+ default :
+ b3AssertConstrParams(0);
+ }
+ }
+ else if((axis >=3) && (axis < 6))
+ {
+ switch(num)
+ {
+ case B3_CONSTRAINT_STOP_ERP :
+ b3AssertConstrParams(m_flags & (B3_6DOF_FLAGS_ERP_STOP << (axis * B3_6DOF_FLAGS_AXIS_SHIFT)));
+ retVal = m_angularLimits[axis - 3].m_stopERP;
+ break;
+ case B3_CONSTRAINT_STOP_CFM :
+ b3AssertConstrParams(m_flags & (B3_6DOF_FLAGS_CFM_STOP << (axis * B3_6DOF_FLAGS_AXIS_SHIFT)));
+ retVal = m_angularLimits[axis - 3].m_stopCFM;
+ break;
+ case B3_CONSTRAINT_CFM :
+ b3AssertConstrParams(m_flags & (B3_6DOF_FLAGS_CFM_NORM << (axis * B3_6DOF_FLAGS_AXIS_SHIFT)));
+ retVal = m_angularLimits[axis - 3].m_normalCFM;
+ break;
+ default :
+ b3AssertConstrParams(0);
+ }
+ }
+ else
+ {
+ b3AssertConstrParams(0);
+ }
+ return retVal;
+}
+
+
+
+void b3Generic6DofConstraint::setAxis(const b3Vector3& axis1,const b3Vector3& axis2, const b3RigidBodyData* bodies)
+{
+ b3Vector3 zAxis = axis1.normalized();
+ b3Vector3 yAxis = axis2.normalized();
+ b3Vector3 xAxis = yAxis.cross(zAxis); // we want right coordinate system
+
+ b3Transform frameInW;
+ frameInW.setIdentity();
+ frameInW.getBasis().setValue( xAxis[0], yAxis[0], zAxis[0],
+ xAxis[1], yAxis[1], zAxis[1],
+ xAxis[2], yAxis[2], zAxis[2]);
+
+ // now get constraint frame in local coordinate systems
+ m_frameInA = getCenterOfMassTransform(bodies[m_rbA]).inverse() * frameInW;
+ m_frameInB = getCenterOfMassTransform(bodies[m_rbB]).inverse() * frameInW;
+
+ calculateTransforms(bodies);
+}
diff --git a/thirdparty/bullet/src/Bullet3Dynamics/ConstraintSolver/b3Generic6DofConstraint.h b/thirdparty/bullet/src/Bullet3Dynamics/ConstraintSolver/b3Generic6DofConstraint.h
new file mode 100644
index 0000000000..084d36055c
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Dynamics/ConstraintSolver/b3Generic6DofConstraint.h
@@ -0,0 +1,550 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+/// 2009 March: b3Generic6DofConstraint refactored by Roman Ponomarev
+/// Added support for generic constraint solver through getInfo1/getInfo2 methods
+
+/*
+2007-09-09
+b3Generic6DofConstraint Refactored by Francisco Le?n
+email: projectileman@yahoo.com
+http://gimpact.sf.net
+*/
+
+
+#ifndef B3_GENERIC_6DOF_CONSTRAINT_H
+#define B3_GENERIC_6DOF_CONSTRAINT_H
+
+#include "Bullet3Common/b3Vector3.h"
+#include "b3JacobianEntry.h"
+#include "b3TypedConstraint.h"
+
+struct b3RigidBodyData;
+
+
+
+
+//! Rotation Limit structure for generic joints
+class b3RotationalLimitMotor
+{
+public:
+ //! limit_parameters
+ //!@{
+ b3Scalar m_loLimit;//!< joint limit
+ b3Scalar m_hiLimit;//!< joint limit
+ b3Scalar m_targetVelocity;//!< target motor velocity
+ b3Scalar m_maxMotorForce;//!< max force on motor
+ b3Scalar m_maxLimitForce;//!< max force on limit
+ b3Scalar m_damping;//!< Damping.
+ b3Scalar m_limitSoftness;//! Relaxation factor
+ b3Scalar m_normalCFM;//!< Constraint force mixing factor
+ b3Scalar m_stopERP;//!< Error tolerance factor when joint is at limit
+ b3Scalar m_stopCFM;//!< Constraint force mixing factor when joint is at limit
+ b3Scalar m_bounce;//!< restitution factor
+ bool m_enableMotor;
+
+ //!@}
+
+ //! temp_variables
+ //!@{
+ b3Scalar m_currentLimitError;//! How much is violated this limit
+ b3Scalar m_currentPosition; //! current value of angle
+ int m_currentLimit;//!< 0=free, 1=at lo limit, 2=at hi limit
+ b3Scalar m_accumulatedImpulse;
+ //!@}
+
+ b3RotationalLimitMotor()
+ {
+ m_accumulatedImpulse = 0.f;
+ m_targetVelocity = 0;
+ m_maxMotorForce = 0.1f;
+ m_maxLimitForce = 300.0f;
+ m_loLimit = 1.0f;
+ m_hiLimit = -1.0f;
+ m_normalCFM = 0.f;
+ m_stopERP = 0.2f;
+ m_stopCFM = 0.f;
+ m_bounce = 0.0f;
+ m_damping = 1.0f;
+ m_limitSoftness = 0.5f;
+ m_currentLimit = 0;
+ m_currentLimitError = 0;
+ m_enableMotor = false;
+ }
+
+ b3RotationalLimitMotor(const b3RotationalLimitMotor & limot)
+ {
+ m_targetVelocity = limot.m_targetVelocity;
+ m_maxMotorForce = limot.m_maxMotorForce;
+ m_limitSoftness = limot.m_limitSoftness;
+ m_loLimit = limot.m_loLimit;
+ m_hiLimit = limot.m_hiLimit;
+ m_normalCFM = limot.m_normalCFM;
+ m_stopERP = limot.m_stopERP;
+ m_stopCFM = limot.m_stopCFM;
+ m_bounce = limot.m_bounce;
+ m_currentLimit = limot.m_currentLimit;
+ m_currentLimitError = limot.m_currentLimitError;
+ m_enableMotor = limot.m_enableMotor;
+ }
+
+
+
+ //! Is limited
+ bool isLimited()
+ {
+ if(m_loLimit > m_hiLimit) return false;
+ return true;
+ }
+
+ //! Need apply correction
+ bool needApplyTorques()
+ {
+ if(m_currentLimit == 0 && m_enableMotor == false) return false;
+ return true;
+ }
+
+ //! calculates error
+ /*!
+ calculates m_currentLimit and m_currentLimitError.
+ */
+ int testLimitValue(b3Scalar test_value);
+
+ //! apply the correction impulses for two bodies
+ b3Scalar solveAngularLimits(b3Scalar timeStep,b3Vector3& axis, b3Scalar jacDiagABInv,b3RigidBodyData * body0, b3RigidBodyData * body1);
+
+};
+
+
+
+class b3TranslationalLimitMotor
+{
+public:
+ b3Vector3 m_lowerLimit;//!< the constraint lower limits
+ b3Vector3 m_upperLimit;//!< the constraint upper limits
+ b3Vector3 m_accumulatedImpulse;
+ //! Linear_Limit_parameters
+ //!@{
+ b3Vector3 m_normalCFM;//!< Constraint force mixing factor
+ b3Vector3 m_stopERP;//!< Error tolerance factor when joint is at limit
+ b3Vector3 m_stopCFM;//!< Constraint force mixing factor when joint is at limit
+ b3Vector3 m_targetVelocity;//!< target motor velocity
+ b3Vector3 m_maxMotorForce;//!< max force on motor
+ b3Vector3 m_currentLimitError;//! How much is violated this limit
+ b3Vector3 m_currentLinearDiff;//! Current relative offset of constraint frames
+ b3Scalar m_limitSoftness;//!< Softness for linear limit
+ b3Scalar m_damping;//!< Damping for linear limit
+ b3Scalar m_restitution;//! Bounce parameter for linear limit
+ //!@}
+ bool m_enableMotor[3];
+ int m_currentLimit[3];//!< 0=free, 1=at lower limit, 2=at upper limit
+
+ b3TranslationalLimitMotor()
+ {
+ m_lowerLimit.setValue(0.f,0.f,0.f);
+ m_upperLimit.setValue(0.f,0.f,0.f);
+ m_accumulatedImpulse.setValue(0.f,0.f,0.f);
+ m_normalCFM.setValue(0.f, 0.f, 0.f);
+ m_stopERP.setValue(0.2f, 0.2f, 0.2f);
+ m_stopCFM.setValue(0.f, 0.f, 0.f);
+
+ m_limitSoftness = 0.7f;
+ m_damping = b3Scalar(1.0f);
+ m_restitution = b3Scalar(0.5f);
+ for(int i=0; i < 3; i++)
+ {
+ m_enableMotor[i] = false;
+ m_targetVelocity[i] = b3Scalar(0.f);
+ m_maxMotorForce[i] = b3Scalar(0.f);
+ }
+ }
+
+ b3TranslationalLimitMotor(const b3TranslationalLimitMotor & other )
+ {
+ m_lowerLimit = other.m_lowerLimit;
+ m_upperLimit = other.m_upperLimit;
+ m_accumulatedImpulse = other.m_accumulatedImpulse;
+
+ m_limitSoftness = other.m_limitSoftness ;
+ m_damping = other.m_damping;
+ m_restitution = other.m_restitution;
+ m_normalCFM = other.m_normalCFM;
+ m_stopERP = other.m_stopERP;
+ m_stopCFM = other.m_stopCFM;
+
+ for(int i=0; i < 3; i++)
+ {
+ m_enableMotor[i] = other.m_enableMotor[i];
+ m_targetVelocity[i] = other.m_targetVelocity[i];
+ m_maxMotorForce[i] = other.m_maxMotorForce[i];
+ }
+ }
+
+ //! Test limit
+ /*!
+ - free means upper < lower,
+ - locked means upper == lower
+ - limited means upper > lower
+ - limitIndex: first 3 are linear, next 3 are angular
+ */
+ inline bool isLimited(int limitIndex)
+ {
+ return (m_upperLimit[limitIndex] >= m_lowerLimit[limitIndex]);
+ }
+ inline bool needApplyForce(int limitIndex)
+ {
+ if(m_currentLimit[limitIndex] == 0 && m_enableMotor[limitIndex] == false) return false;
+ return true;
+ }
+ int testLimitValue(int limitIndex, b3Scalar test_value);
+
+
+ b3Scalar solveLinearAxis(
+ b3Scalar timeStep,
+ b3Scalar jacDiagABInv,
+ b3RigidBodyData& body1,const b3Vector3 &pointInA,
+ b3RigidBodyData& body2,const b3Vector3 &pointInB,
+ int limit_index,
+ const b3Vector3 & axis_normal_on_a,
+ const b3Vector3 & anchorPos);
+
+
+};
+
+enum b36DofFlags
+{
+ B3_6DOF_FLAGS_CFM_NORM = 1,
+ B3_6DOF_FLAGS_CFM_STOP = 2,
+ B3_6DOF_FLAGS_ERP_STOP = 4
+};
+#define B3_6DOF_FLAGS_AXIS_SHIFT 3 // bits per axis
+
+
+/// b3Generic6DofConstraint between two rigidbodies each with a pivotpoint that descibes the axis location in local space
+/*!
+b3Generic6DofConstraint can leave any of the 6 degree of freedom 'free' or 'locked'.
+currently this limit supports rotational motors<br>
+<ul>
+<li> For Linear limits, use b3Generic6DofConstraint.setLinearUpperLimit, b3Generic6DofConstraint.setLinearLowerLimit. You can set the parameters with the b3TranslationalLimitMotor structure accsesible through the b3Generic6DofConstraint.getTranslationalLimitMotor method.
+At this moment translational motors are not supported. May be in the future. </li>
+
+<li> For Angular limits, use the b3RotationalLimitMotor structure for configuring the limit.
+This is accessible through b3Generic6DofConstraint.getLimitMotor method,
+This brings support for limit parameters and motors. </li>
+
+<li> Angulars limits have these possible ranges:
+<table border=1 >
+<tr>
+ <td><b>AXIS</b></td>
+ <td><b>MIN ANGLE</b></td>
+ <td><b>MAX ANGLE</b></td>
+</tr><tr>
+ <td>X</td>
+ <td>-PI</td>
+ <td>PI</td>
+</tr><tr>
+ <td>Y</td>
+ <td>-PI/2</td>
+ <td>PI/2</td>
+</tr><tr>
+ <td>Z</td>
+ <td>-PI</td>
+ <td>PI</td>
+</tr>
+</table>
+</li>
+</ul>
+
+*/
+B3_ATTRIBUTE_ALIGNED16(class) b3Generic6DofConstraint : public b3TypedConstraint
+{
+protected:
+
+ //! relative_frames
+ //!@{
+ b3Transform m_frameInA;//!< the constraint space w.r.t body A
+ b3Transform m_frameInB;//!< the constraint space w.r.t body B
+ //!@}
+
+ //! Jacobians
+ //!@{
+// b3JacobianEntry m_jacLinear[3];//!< 3 orthogonal linear constraints
+// b3JacobianEntry m_jacAng[3];//!< 3 orthogonal angular constraints
+ //!@}
+
+ //! Linear_Limit_parameters
+ //!@{
+ b3TranslationalLimitMotor m_linearLimits;
+ //!@}
+
+
+ //! hinge_parameters
+ //!@{
+ b3RotationalLimitMotor m_angularLimits[3];
+ //!@}
+
+
+protected:
+ //! temporal variables
+ //!@{
+ b3Transform m_calculatedTransformA;
+ b3Transform m_calculatedTransformB;
+ b3Vector3 m_calculatedAxisAngleDiff;
+ b3Vector3 m_calculatedAxis[3];
+ b3Vector3 m_calculatedLinearDiff;
+ b3Scalar m_timeStep;
+ b3Scalar m_factA;
+ b3Scalar m_factB;
+ bool m_hasStaticBody;
+
+ b3Vector3 m_AnchorPos; // point betwen pivots of bodies A and B to solve linear axes
+
+ bool m_useLinearReferenceFrameA;
+ bool m_useOffsetForConstraintFrame;
+
+ int m_flags;
+
+ //!@}
+
+ b3Generic6DofConstraint& operator=(b3Generic6DofConstraint& other)
+ {
+ b3Assert(0);
+ (void) other;
+ return *this;
+ }
+
+
+ int setAngularLimits(b3ConstraintInfo2 *info, int row_offset,const b3Transform& transA,const b3Transform& transB,const b3Vector3& linVelA,const b3Vector3& linVelB,const b3Vector3& angVelA,const b3Vector3& angVelB);
+
+ int setLinearLimits(b3ConstraintInfo2 *info, int row, const b3Transform& transA,const b3Transform& transB,const b3Vector3& linVelA,const b3Vector3& linVelB,const b3Vector3& angVelA,const b3Vector3& angVelB);
+
+
+ // tests linear limits
+ void calculateLinearInfo();
+
+ //! calcs the euler angles between the two bodies.
+ void calculateAngleInfo();
+
+
+
+public:
+
+ B3_DECLARE_ALIGNED_ALLOCATOR();
+
+ b3Generic6DofConstraint(int rbA, int rbB, const b3Transform& frameInA, const b3Transform& frameInB ,bool useLinearReferenceFrameA,const b3RigidBodyData* bodies);
+
+ //! Calcs global transform of the offsets
+ /*!
+ Calcs the global transform for the joint offset for body A an B, and also calcs the agle differences between the bodies.
+ \sa b3Generic6DofConstraint.getCalculatedTransformA , b3Generic6DofConstraint.getCalculatedTransformB, b3Generic6DofConstraint.calculateAngleInfo
+ */
+ void calculateTransforms(const b3Transform& transA,const b3Transform& transB,const b3RigidBodyData* bodies);
+
+ void calculateTransforms(const b3RigidBodyData* bodies);
+
+ //! Gets the global transform of the offset for body A
+ /*!
+ \sa b3Generic6DofConstraint.getFrameOffsetA, b3Generic6DofConstraint.getFrameOffsetB, b3Generic6DofConstraint.calculateAngleInfo.
+ */
+ const b3Transform & getCalculatedTransformA() const
+ {
+ return m_calculatedTransformA;
+ }
+
+ //! Gets the global transform of the offset for body B
+ /*!
+ \sa b3Generic6DofConstraint.getFrameOffsetA, b3Generic6DofConstraint.getFrameOffsetB, b3Generic6DofConstraint.calculateAngleInfo.
+ */
+ const b3Transform & getCalculatedTransformB() const
+ {
+ return m_calculatedTransformB;
+ }
+
+ const b3Transform & getFrameOffsetA() const
+ {
+ return m_frameInA;
+ }
+
+ const b3Transform & getFrameOffsetB() const
+ {
+ return m_frameInB;
+ }
+
+
+ b3Transform & getFrameOffsetA()
+ {
+ return m_frameInA;
+ }
+
+ b3Transform & getFrameOffsetB()
+ {
+ return m_frameInB;
+ }
+
+
+
+ virtual void getInfo1 (b3ConstraintInfo1* info,const b3RigidBodyData* bodies);
+
+ void getInfo1NonVirtual (b3ConstraintInfo1* info,const b3RigidBodyData* bodies);
+
+ virtual void getInfo2 (b3ConstraintInfo2* info,const b3RigidBodyData* bodies);
+
+ void getInfo2NonVirtual (b3ConstraintInfo2* info,const b3Transform& transA,const b3Transform& transB,const b3Vector3& linVelA,const b3Vector3& linVelB,const b3Vector3& angVelA,const b3Vector3& angVelB,const b3RigidBodyData* bodies);
+
+
+ void updateRHS(b3Scalar timeStep);
+
+ //! Get the rotation axis in global coordinates
+ b3Vector3 getAxis(int axis_index) const;
+
+ //! Get the relative Euler angle
+ /*!
+ \pre b3Generic6DofConstraint::calculateTransforms() must be called previously.
+ */
+ b3Scalar getAngle(int axis_index) const;
+
+ //! Get the relative position of the constraint pivot
+ /*!
+ \pre b3Generic6DofConstraint::calculateTransforms() must be called previously.
+ */
+ b3Scalar getRelativePivotPosition(int axis_index) const;
+
+ void setFrames(const b3Transform & frameA, const b3Transform & frameB, const b3RigidBodyData* bodies);
+
+ //! Test angular limit.
+ /*!
+ Calculates angular correction and returns true if limit needs to be corrected.
+ \pre b3Generic6DofConstraint::calculateTransforms() must be called previously.
+ */
+ bool testAngularLimitMotor(int axis_index);
+
+ void setLinearLowerLimit(const b3Vector3& linearLower)
+ {
+ m_linearLimits.m_lowerLimit = linearLower;
+ }
+
+ void getLinearLowerLimit(b3Vector3& linearLower)
+ {
+ linearLower = m_linearLimits.m_lowerLimit;
+ }
+
+ void setLinearUpperLimit(const b3Vector3& linearUpper)
+ {
+ m_linearLimits.m_upperLimit = linearUpper;
+ }
+
+ void getLinearUpperLimit(b3Vector3& linearUpper)
+ {
+ linearUpper = m_linearLimits.m_upperLimit;
+ }
+
+ void setAngularLowerLimit(const b3Vector3& angularLower)
+ {
+ for(int i = 0; i < 3; i++)
+ m_angularLimits[i].m_loLimit = b3NormalizeAngle(angularLower[i]);
+ }
+
+ void getAngularLowerLimit(b3Vector3& angularLower)
+ {
+ for(int i = 0; i < 3; i++)
+ angularLower[i] = m_angularLimits[i].m_loLimit;
+ }
+
+ void setAngularUpperLimit(const b3Vector3& angularUpper)
+ {
+ for(int i = 0; i < 3; i++)
+ m_angularLimits[i].m_hiLimit = b3NormalizeAngle(angularUpper[i]);
+ }
+
+ void getAngularUpperLimit(b3Vector3& angularUpper)
+ {
+ for(int i = 0; i < 3; i++)
+ angularUpper[i] = m_angularLimits[i].m_hiLimit;
+ }
+
+ //! Retrieves the angular limit informacion
+ b3RotationalLimitMotor * getRotationalLimitMotor(int index)
+ {
+ return &m_angularLimits[index];
+ }
+
+ //! Retrieves the limit informacion
+ b3TranslationalLimitMotor * getTranslationalLimitMotor()
+ {
+ return &m_linearLimits;
+ }
+
+ //first 3 are linear, next 3 are angular
+ void setLimit(int axis, b3Scalar lo, b3Scalar hi)
+ {
+ if(axis<3)
+ {
+ m_linearLimits.m_lowerLimit[axis] = lo;
+ m_linearLimits.m_upperLimit[axis] = hi;
+ }
+ else
+ {
+ lo = b3NormalizeAngle(lo);
+ hi = b3NormalizeAngle(hi);
+ m_angularLimits[axis-3].m_loLimit = lo;
+ m_angularLimits[axis-3].m_hiLimit = hi;
+ }
+ }
+
+ //! Test limit
+ /*!
+ - free means upper < lower,
+ - locked means upper == lower
+ - limited means upper > lower
+ - limitIndex: first 3 are linear, next 3 are angular
+ */
+ bool isLimited(int limitIndex)
+ {
+ if(limitIndex<3)
+ {
+ return m_linearLimits.isLimited(limitIndex);
+
+ }
+ return m_angularLimits[limitIndex-3].isLimited();
+ }
+
+ virtual void calcAnchorPos(const b3RigidBodyData* bodies); // overridable
+
+ int get_limit_motor_info2( b3RotationalLimitMotor * limot,
+ const b3Transform& transA,const b3Transform& transB,const b3Vector3& linVelA,const b3Vector3& linVelB,const b3Vector3& angVelA,const b3Vector3& angVelB,
+ b3ConstraintInfo2 *info, int row, b3Vector3& ax1, int rotational, int rotAllowed = false);
+
+ // access for UseFrameOffset
+ bool getUseFrameOffset() { return m_useOffsetForConstraintFrame; }
+ void setUseFrameOffset(bool frameOffsetOnOff) { m_useOffsetForConstraintFrame = frameOffsetOnOff; }
+
+ ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
+ ///If no axis is provided, it uses the default axis for this constraint.
+ virtual void setParam(int num, b3Scalar value, int axis = -1);
+ ///return the local value of parameter
+ virtual b3Scalar getParam(int num, int axis = -1) const;
+
+ void setAxis( const b3Vector3& axis1, const b3Vector3& axis2,const b3RigidBodyData* bodies);
+
+
+
+
+};
+
+
+
+
+
+#endif //B3_GENERIC_6DOF_CONSTRAINT_H
diff --git a/thirdparty/bullet/src/Bullet3Dynamics/ConstraintSolver/b3JacobianEntry.h b/thirdparty/bullet/src/Bullet3Dynamics/ConstraintSolver/b3JacobianEntry.h
new file mode 100644
index 0000000000..a55168eb38
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Dynamics/ConstraintSolver/b3JacobianEntry.h
@@ -0,0 +1,155 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef B3_JACOBIAN_ENTRY_H
+#define B3_JACOBIAN_ENTRY_H
+
+#include "Bullet3Common/b3Matrix3x3.h"
+
+
+//notes:
+// Another memory optimization would be to store m_1MinvJt in the remaining 3 w components
+// which makes the b3JacobianEntry memory layout 16 bytes
+// if you only are interested in angular part, just feed massInvA and massInvB zero
+
+/// Jacobian entry is an abstraction that allows to describe constraints
+/// it can be used in combination with a constraint solver
+/// Can be used to relate the effect of an impulse to the constraint error
+B3_ATTRIBUTE_ALIGNED16(class) b3JacobianEntry
+{
+public:
+ b3JacobianEntry() {};
+ //constraint between two different rigidbodies
+ b3JacobianEntry(
+ const b3Matrix3x3& world2A,
+ const b3Matrix3x3& world2B,
+ const b3Vector3& rel_pos1,const b3Vector3& rel_pos2,
+ const b3Vector3& jointAxis,
+ const b3Vector3& inertiaInvA,
+ const b3Scalar massInvA,
+ const b3Vector3& inertiaInvB,
+ const b3Scalar massInvB)
+ :m_linearJointAxis(jointAxis)
+ {
+ m_aJ = world2A*(rel_pos1.cross(m_linearJointAxis));
+ m_bJ = world2B*(rel_pos2.cross(-m_linearJointAxis));
+ m_0MinvJt = inertiaInvA * m_aJ;
+ m_1MinvJt = inertiaInvB * m_bJ;
+ m_Adiag = massInvA + m_0MinvJt.dot(m_aJ) + massInvB + m_1MinvJt.dot(m_bJ);
+
+ b3Assert(m_Adiag > b3Scalar(0.0));
+ }
+
+ //angular constraint between two different rigidbodies
+ b3JacobianEntry(const b3Vector3& jointAxis,
+ const b3Matrix3x3& world2A,
+ const b3Matrix3x3& world2B,
+ const b3Vector3& inertiaInvA,
+ const b3Vector3& inertiaInvB)
+ :m_linearJointAxis(b3MakeVector3(b3Scalar(0.),b3Scalar(0.),b3Scalar(0.)))
+ {
+ m_aJ= world2A*jointAxis;
+ m_bJ = world2B*-jointAxis;
+ m_0MinvJt = inertiaInvA * m_aJ;
+ m_1MinvJt = inertiaInvB * m_bJ;
+ m_Adiag = m_0MinvJt.dot(m_aJ) + m_1MinvJt.dot(m_bJ);
+
+ b3Assert(m_Adiag > b3Scalar(0.0));
+ }
+
+ //angular constraint between two different rigidbodies
+ b3JacobianEntry(const b3Vector3& axisInA,
+ const b3Vector3& axisInB,
+ const b3Vector3& inertiaInvA,
+ const b3Vector3& inertiaInvB)
+ : m_linearJointAxis(b3MakeVector3(b3Scalar(0.),b3Scalar(0.),b3Scalar(0.)))
+ , m_aJ(axisInA)
+ , m_bJ(-axisInB)
+ {
+ m_0MinvJt = inertiaInvA * m_aJ;
+ m_1MinvJt = inertiaInvB * m_bJ;
+ m_Adiag = m_0MinvJt.dot(m_aJ) + m_1MinvJt.dot(m_bJ);
+
+ b3Assert(m_Adiag > b3Scalar(0.0));
+ }
+
+ //constraint on one rigidbody
+ b3JacobianEntry(
+ const b3Matrix3x3& world2A,
+ const b3Vector3& rel_pos1,const b3Vector3& rel_pos2,
+ const b3Vector3& jointAxis,
+ const b3Vector3& inertiaInvA,
+ const b3Scalar massInvA)
+ :m_linearJointAxis(jointAxis)
+ {
+ m_aJ= world2A*(rel_pos1.cross(jointAxis));
+ m_bJ = world2A*(rel_pos2.cross(-jointAxis));
+ m_0MinvJt = inertiaInvA * m_aJ;
+ m_1MinvJt = b3MakeVector3(b3Scalar(0.),b3Scalar(0.),b3Scalar(0.));
+ m_Adiag = massInvA + m_0MinvJt.dot(m_aJ);
+
+ b3Assert(m_Adiag > b3Scalar(0.0));
+ }
+
+ b3Scalar getDiagonal() const { return m_Adiag; }
+
+ // for two constraints on the same rigidbody (for example vehicle friction)
+ b3Scalar getNonDiagonal(const b3JacobianEntry& jacB, const b3Scalar massInvA) const
+ {
+ const b3JacobianEntry& jacA = *this;
+ b3Scalar lin = massInvA * jacA.m_linearJointAxis.dot(jacB.m_linearJointAxis);
+ b3Scalar ang = jacA.m_0MinvJt.dot(jacB.m_aJ);
+ return lin + ang;
+ }
+
+
+
+ // for two constraints on sharing two same rigidbodies (for example two contact points between two rigidbodies)
+ b3Scalar getNonDiagonal(const b3JacobianEntry& jacB,const b3Scalar massInvA,const b3Scalar massInvB) const
+ {
+ const b3JacobianEntry& jacA = *this;
+ b3Vector3 lin = jacA.m_linearJointAxis * jacB.m_linearJointAxis;
+ b3Vector3 ang0 = jacA.m_0MinvJt * jacB.m_aJ;
+ b3Vector3 ang1 = jacA.m_1MinvJt * jacB.m_bJ;
+ b3Vector3 lin0 = massInvA * lin ;
+ b3Vector3 lin1 = massInvB * lin;
+ b3Vector3 sum = ang0+ang1+lin0+lin1;
+ return sum[0]+sum[1]+sum[2];
+ }
+
+ b3Scalar getRelativeVelocity(const b3Vector3& linvelA,const b3Vector3& angvelA,const b3Vector3& linvelB,const b3Vector3& angvelB)
+ {
+ b3Vector3 linrel = linvelA - linvelB;
+ b3Vector3 angvela = angvelA * m_aJ;
+ b3Vector3 angvelb = angvelB * m_bJ;
+ linrel *= m_linearJointAxis;
+ angvela += angvelb;
+ angvela += linrel;
+ b3Scalar rel_vel2 = angvela[0]+angvela[1]+angvela[2];
+ return rel_vel2 + B3_EPSILON;
+ }
+//private:
+
+ b3Vector3 m_linearJointAxis;
+ b3Vector3 m_aJ;
+ b3Vector3 m_bJ;
+ b3Vector3 m_0MinvJt;
+ b3Vector3 m_1MinvJt;
+ //Optimization: can be stored in the w/last component of one of the vectors
+ b3Scalar m_Adiag;
+
+};
+
+#endif //B3_JACOBIAN_ENTRY_H
diff --git a/thirdparty/bullet/src/Bullet3Dynamics/ConstraintSolver/b3PgsJacobiSolver.cpp b/thirdparty/bullet/src/Bullet3Dynamics/ConstraintSolver/b3PgsJacobiSolver.cpp
new file mode 100644
index 0000000000..de729d4556
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Dynamics/ConstraintSolver/b3PgsJacobiSolver.cpp
@@ -0,0 +1,1815 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2012 Erwin Coumans 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.
+*/
+
+//enable B3_SOLVER_DEBUG if you experience solver crashes
+//#define B3_SOLVER_DEBUG
+//#define COMPUTE_IMPULSE_DENOM 1
+//It is not necessary (redundant) to refresh contact manifolds, this refresh has been moved to the collision algorithms.
+
+//#define DISABLE_JOINTS
+
+#include "b3PgsJacobiSolver.h"
+#include "Bullet3Common/b3MinMax.h"
+#include "b3TypedConstraint.h"
+#include <new>
+#include "Bullet3Common/b3StackAlloc.h"
+
+//#include "b3SolverBody.h"
+//#include "b3SolverConstraint.h"
+#include "Bullet3Common/b3AlignedObjectArray.h"
+#include <string.h> //for memset
+//#include "../../dynamics/basic_demo/Stubs/AdlContact4.h"
+#include "Bullet3Collision/NarrowPhaseCollision/b3Contact4.h"
+
+
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
+
+static b3Transform getWorldTransform(b3RigidBodyData* rb)
+{
+ b3Transform newTrans;
+ newTrans.setOrigin(rb->m_pos);
+ newTrans.setRotation(rb->m_quat);
+ return newTrans;
+}
+
+static const b3Matrix3x3& getInvInertiaTensorWorld(b3InertiaData* inertia)
+{
+ return inertia->m_invInertiaWorld;
+}
+
+
+
+static const b3Vector3& getLinearVelocity(b3RigidBodyData* rb)
+{
+ return rb->m_linVel;
+}
+
+static const b3Vector3& getAngularVelocity(b3RigidBodyData* rb)
+{
+ return rb->m_angVel;
+}
+
+static b3Vector3 getVelocityInLocalPoint(b3RigidBodyData* rb, const b3Vector3& rel_pos)
+{
+ //we also calculate lin/ang velocity for kinematic objects
+ return getLinearVelocity(rb) + getAngularVelocity(rb).cross(rel_pos);
+
+}
+
+struct b3ContactPoint
+{
+ b3Vector3 m_positionWorldOnA;
+ b3Vector3 m_positionWorldOnB;
+ b3Vector3 m_normalWorldOnB;
+ b3Scalar m_appliedImpulse;
+ b3Scalar m_distance;
+ b3Scalar m_combinedRestitution;
+
+ ///information related to friction
+ b3Scalar m_combinedFriction;
+ b3Vector3 m_lateralFrictionDir1;
+ b3Vector3 m_lateralFrictionDir2;
+ b3Scalar m_appliedImpulseLateral1;
+ b3Scalar m_appliedImpulseLateral2;
+ b3Scalar m_combinedRollingFriction;
+ b3Scalar m_contactMotion1;
+ b3Scalar m_contactMotion2;
+ b3Scalar m_contactCFM1;
+ b3Scalar m_contactCFM2;
+
+ bool m_lateralFrictionInitialized;
+
+ b3Vector3 getPositionWorldOnA()
+ {
+ return m_positionWorldOnA;
+ }
+ b3Vector3 getPositionWorldOnB()
+ {
+ return m_positionWorldOnB;
+ }
+ b3Scalar getDistance()
+ {
+ return m_distance;
+ }
+};
+
+void getContactPoint(b3Contact4* contact, int contactIndex, b3ContactPoint& pointOut)
+{
+ pointOut.m_appliedImpulse = 0.f;
+ pointOut.m_appliedImpulseLateral1 = 0.f;
+ pointOut.m_appliedImpulseLateral2 = 0.f;
+ pointOut.m_combinedFriction = contact->getFrictionCoeff();
+ pointOut.m_combinedRestitution = contact->getRestituitionCoeff();
+ pointOut.m_combinedRollingFriction = 0.f;
+ pointOut.m_contactCFM1 = 0.f;
+ pointOut.m_contactCFM2 = 0.f;
+ pointOut.m_contactMotion1 = 0.f;
+ pointOut.m_contactMotion2 = 0.f;
+ pointOut.m_distance = contact->getPenetration(contactIndex);//??0.01f
+ b3Vector3 normalOnB = contact->m_worldNormalOnB;
+ normalOnB.normalize();//is this needed?
+
+ b3Vector3 l1,l2;
+ b3PlaneSpace1(normalOnB,l1,l2);
+
+ pointOut.m_normalWorldOnB = normalOnB;
+ //printf("normalOnB = %f,%f,%f\n",normalOnB.getX(),normalOnB.getY(),normalOnB.getZ());
+ pointOut.m_lateralFrictionDir1 = l1;
+ pointOut.m_lateralFrictionDir2 = l2;
+ pointOut.m_lateralFrictionInitialized = true;
+
+
+ b3Vector3 worldPosB = contact->m_worldPosB[contactIndex];
+ pointOut.m_positionWorldOnB = worldPosB;
+ pointOut.m_positionWorldOnA = worldPosB+normalOnB*pointOut.m_distance;
+}
+
+int getNumContacts(b3Contact4* contact)
+{
+ return contact->getNPoints();
+}
+
+b3PgsJacobiSolver::b3PgsJacobiSolver(bool usePgs)
+:m_usePgs(usePgs),
+m_numSplitImpulseRecoveries(0),
+m_btSeed2(0)
+{
+
+}
+
+b3PgsJacobiSolver::~b3PgsJacobiSolver()
+{
+}
+
+void b3PgsJacobiSolver::solveContacts(int numBodies, b3RigidBodyData* bodies, b3InertiaData* inertias, int numContacts, b3Contact4* contacts, int numConstraints, b3TypedConstraint** constraints)
+{
+ b3ContactSolverInfo infoGlobal;
+ infoGlobal.m_splitImpulse = false;
+ infoGlobal.m_timeStep = 1.f/60.f;
+ infoGlobal.m_numIterations = 4;//4;
+// infoGlobal.m_solverMode|=B3_SOLVER_USE_2_FRICTION_DIRECTIONS|B3_SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS|B3_SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION;
+ //infoGlobal.m_solverMode|=B3_SOLVER_USE_2_FRICTION_DIRECTIONS|B3_SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS;
+ infoGlobal.m_solverMode|=B3_SOLVER_USE_2_FRICTION_DIRECTIONS;
+
+ //if (infoGlobal.m_solverMode & B3_SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS)
+ //if ((infoGlobal.m_solverMode & B3_SOLVER_USE_2_FRICTION_DIRECTIONS) && (infoGlobal.m_solverMode & B3_SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION))
+
+
+ solveGroup(bodies,inertias,numBodies,contacts,numContacts,constraints,numConstraints,infoGlobal);
+
+ if (!numContacts)
+ return;
+}
+
+
+
+
+/// b3PgsJacobiSolver Sequentially applies impulses
+b3Scalar b3PgsJacobiSolver::solveGroup(b3RigidBodyData* bodies,
+ b3InertiaData* inertias,
+ int numBodies,
+ b3Contact4* manifoldPtr,
+ int numManifolds,
+ b3TypedConstraint** constraints,
+ int numConstraints,
+ const b3ContactSolverInfo& infoGlobal)
+{
+
+ B3_PROFILE("solveGroup");
+ //you need to provide at least some bodies
+
+ solveGroupCacheFriendlySetup( bodies, inertias,numBodies, manifoldPtr, numManifolds,constraints, numConstraints,infoGlobal);
+
+ solveGroupCacheFriendlyIterations(constraints, numConstraints,infoGlobal);
+
+ solveGroupCacheFriendlyFinish(bodies, inertias,numBodies, infoGlobal);
+
+ return 0.f;
+}
+
+
+
+
+
+
+
+
+
+#ifdef USE_SIMD
+#include <emmintrin.h>
+#define b3VecSplat(x, e) _mm_shuffle_ps(x, x, _MM_SHUFFLE(e,e,e,e))
+static inline __m128 b3SimdDot3( __m128 vec0, __m128 vec1 )
+{
+ __m128 result = _mm_mul_ps( vec0, vec1);
+ return _mm_add_ps( b3VecSplat( result, 0 ), _mm_add_ps( b3VecSplat( result, 1 ), b3VecSplat( result, 2 ) ) );
+}
+#endif//USE_SIMD
+
+// Project Gauss Seidel or the equivalent Sequential Impulse
+void b3PgsJacobiSolver::resolveSingleConstraintRowGenericSIMD(b3SolverBody& body1,b3SolverBody& body2,const b3SolverConstraint& c)
+{
+#ifdef USE_SIMD
+ __m128 cpAppliedImp = _mm_set1_ps(c.m_appliedImpulse);
+ __m128 lowerLimit1 = _mm_set1_ps(c.m_lowerLimit);
+ __m128 upperLimit1 = _mm_set1_ps(c.m_upperLimit);
+ __m128 deltaImpulse = _mm_sub_ps(_mm_set1_ps(c.m_rhs), _mm_mul_ps(_mm_set1_ps(c.m_appliedImpulse),_mm_set1_ps(c.m_cfm)));
+ __m128 deltaVel1Dotn = _mm_add_ps(b3SimdDot3(c.m_contactNormal.mVec128,body1.internalGetDeltaLinearVelocity().mVec128), b3SimdDot3(c.m_relpos1CrossNormal.mVec128,body1.internalGetDeltaAngularVelocity().mVec128));
+ __m128 deltaVel2Dotn = _mm_sub_ps(b3SimdDot3(c.m_relpos2CrossNormal.mVec128,body2.internalGetDeltaAngularVelocity().mVec128),b3SimdDot3((c.m_contactNormal).mVec128,body2.internalGetDeltaLinearVelocity().mVec128));
+ deltaImpulse = _mm_sub_ps(deltaImpulse,_mm_mul_ps(deltaVel1Dotn,_mm_set1_ps(c.m_jacDiagABInv)));
+ deltaImpulse = _mm_sub_ps(deltaImpulse,_mm_mul_ps(deltaVel2Dotn,_mm_set1_ps(c.m_jacDiagABInv)));
+ b3SimdScalar sum = _mm_add_ps(cpAppliedImp,deltaImpulse);
+ b3SimdScalar resultLowerLess,resultUpperLess;
+ resultLowerLess = _mm_cmplt_ps(sum,lowerLimit1);
+ resultUpperLess = _mm_cmplt_ps(sum,upperLimit1);
+ __m128 lowMinApplied = _mm_sub_ps(lowerLimit1,cpAppliedImp);
+ deltaImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowMinApplied), _mm_andnot_ps(resultLowerLess, deltaImpulse) );
+ c.m_appliedImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowerLimit1), _mm_andnot_ps(resultLowerLess, sum) );
+ __m128 upperMinApplied = _mm_sub_ps(upperLimit1,cpAppliedImp);
+ deltaImpulse = _mm_or_ps( _mm_and_ps(resultUpperLess, deltaImpulse), _mm_andnot_ps(resultUpperLess, upperMinApplied) );
+ c.m_appliedImpulse = _mm_or_ps( _mm_and_ps(resultUpperLess, c.m_appliedImpulse), _mm_andnot_ps(resultUpperLess, upperLimit1) );
+ __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal.mVec128,body1.internalGetInvMass().mVec128);
+ __m128 linearComponentB = _mm_mul_ps((c.m_contactNormal).mVec128,body2.internalGetInvMass().mVec128);
+ __m128 impulseMagnitude = deltaImpulse;
+ body1.internalGetDeltaLinearVelocity().mVec128 = _mm_add_ps(body1.internalGetDeltaLinearVelocity().mVec128,_mm_mul_ps(linearComponentA,impulseMagnitude));
+ body1.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(body1.internalGetDeltaAngularVelocity().mVec128 ,_mm_mul_ps(c.m_angularComponentA.mVec128,impulseMagnitude));
+ body2.internalGetDeltaLinearVelocity().mVec128 = _mm_sub_ps(body2.internalGetDeltaLinearVelocity().mVec128,_mm_mul_ps(linearComponentB,impulseMagnitude));
+ body2.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(body2.internalGetDeltaAngularVelocity().mVec128 ,_mm_mul_ps(c.m_angularComponentB.mVec128,impulseMagnitude));
+#else
+ resolveSingleConstraintRowGeneric(body1,body2,c);
+#endif
+}
+
+// Project Gauss Seidel or the equivalent Sequential Impulse
+ void b3PgsJacobiSolver::resolveSingleConstraintRowGeneric(b3SolverBody& body1,b3SolverBody& body2,const b3SolverConstraint& c)
+{
+ b3Scalar deltaImpulse = c.m_rhs-b3Scalar(c.m_appliedImpulse)*c.m_cfm;
+ const b3Scalar deltaVel1Dotn = c.m_contactNormal.dot(body1.internalGetDeltaLinearVelocity()) + c.m_relpos1CrossNormal.dot(body1.internalGetDeltaAngularVelocity());
+ const b3Scalar deltaVel2Dotn = -c.m_contactNormal.dot(body2.internalGetDeltaLinearVelocity()) + c.m_relpos2CrossNormal.dot(body2.internalGetDeltaAngularVelocity());
+
+// const b3Scalar delta_rel_vel = deltaVel1Dotn-deltaVel2Dotn;
+ deltaImpulse -= deltaVel1Dotn*c.m_jacDiagABInv;
+ deltaImpulse -= deltaVel2Dotn*c.m_jacDiagABInv;
+
+ const b3Scalar sum = b3Scalar(c.m_appliedImpulse) + deltaImpulse;
+ if (sum < c.m_lowerLimit)
+ {
+ deltaImpulse = c.m_lowerLimit-c.m_appliedImpulse;
+ c.m_appliedImpulse = c.m_lowerLimit;
+ }
+ else if (sum > c.m_upperLimit)
+ {
+ deltaImpulse = c.m_upperLimit-c.m_appliedImpulse;
+ c.m_appliedImpulse = c.m_upperLimit;
+ }
+ else
+ {
+ c.m_appliedImpulse = sum;
+ }
+
+ body1.internalApplyImpulse(c.m_contactNormal*body1.internalGetInvMass(),c.m_angularComponentA,deltaImpulse);
+ body2.internalApplyImpulse(-c.m_contactNormal*body2.internalGetInvMass(),c.m_angularComponentB,deltaImpulse);
+}
+
+ void b3PgsJacobiSolver::resolveSingleConstraintRowLowerLimitSIMD(b3SolverBody& body1,b3SolverBody& body2,const b3SolverConstraint& c)
+{
+#ifdef USE_SIMD
+ __m128 cpAppliedImp = _mm_set1_ps(c.m_appliedImpulse);
+ __m128 lowerLimit1 = _mm_set1_ps(c.m_lowerLimit);
+ __m128 upperLimit1 = _mm_set1_ps(c.m_upperLimit);
+ __m128 deltaImpulse = _mm_sub_ps(_mm_set1_ps(c.m_rhs), _mm_mul_ps(_mm_set1_ps(c.m_appliedImpulse),_mm_set1_ps(c.m_cfm)));
+ __m128 deltaVel1Dotn = _mm_add_ps(b3SimdDot3(c.m_contactNormal.mVec128,body1.internalGetDeltaLinearVelocity().mVec128), b3SimdDot3(c.m_relpos1CrossNormal.mVec128,body1.internalGetDeltaAngularVelocity().mVec128));
+ __m128 deltaVel2Dotn = _mm_sub_ps(b3SimdDot3(c.m_relpos2CrossNormal.mVec128,body2.internalGetDeltaAngularVelocity().mVec128),b3SimdDot3((c.m_contactNormal).mVec128,body2.internalGetDeltaLinearVelocity().mVec128));
+ deltaImpulse = _mm_sub_ps(deltaImpulse,_mm_mul_ps(deltaVel1Dotn,_mm_set1_ps(c.m_jacDiagABInv)));
+ deltaImpulse = _mm_sub_ps(deltaImpulse,_mm_mul_ps(deltaVel2Dotn,_mm_set1_ps(c.m_jacDiagABInv)));
+ b3SimdScalar sum = _mm_add_ps(cpAppliedImp,deltaImpulse);
+ b3SimdScalar resultLowerLess,resultUpperLess;
+ resultLowerLess = _mm_cmplt_ps(sum,lowerLimit1);
+ resultUpperLess = _mm_cmplt_ps(sum,upperLimit1);
+ __m128 lowMinApplied = _mm_sub_ps(lowerLimit1,cpAppliedImp);
+ deltaImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowMinApplied), _mm_andnot_ps(resultLowerLess, deltaImpulse) );
+ c.m_appliedImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowerLimit1), _mm_andnot_ps(resultLowerLess, sum) );
+ __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal.mVec128,body1.internalGetInvMass().mVec128);
+ __m128 linearComponentB = _mm_mul_ps((c.m_contactNormal).mVec128,body2.internalGetInvMass().mVec128);
+ __m128 impulseMagnitude = deltaImpulse;
+ body1.internalGetDeltaLinearVelocity().mVec128 = _mm_add_ps(body1.internalGetDeltaLinearVelocity().mVec128,_mm_mul_ps(linearComponentA,impulseMagnitude));
+ body1.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(body1.internalGetDeltaAngularVelocity().mVec128 ,_mm_mul_ps(c.m_angularComponentA.mVec128,impulseMagnitude));
+ body2.internalGetDeltaLinearVelocity().mVec128 = _mm_sub_ps(body2.internalGetDeltaLinearVelocity().mVec128,_mm_mul_ps(linearComponentB,impulseMagnitude));
+ body2.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(body2.internalGetDeltaAngularVelocity().mVec128 ,_mm_mul_ps(c.m_angularComponentB.mVec128,impulseMagnitude));
+#else
+ resolveSingleConstraintRowLowerLimit(body1,body2,c);
+#endif
+}
+
+// Project Gauss Seidel or the equivalent Sequential Impulse
+ void b3PgsJacobiSolver::resolveSingleConstraintRowLowerLimit(b3SolverBody& body1,b3SolverBody& body2,const b3SolverConstraint& c)
+{
+ b3Scalar deltaImpulse = c.m_rhs-b3Scalar(c.m_appliedImpulse)*c.m_cfm;
+ const b3Scalar deltaVel1Dotn = c.m_contactNormal.dot(body1.internalGetDeltaLinearVelocity()) + c.m_relpos1CrossNormal.dot(body1.internalGetDeltaAngularVelocity());
+ const b3Scalar deltaVel2Dotn = -c.m_contactNormal.dot(body2.internalGetDeltaLinearVelocity()) + c.m_relpos2CrossNormal.dot(body2.internalGetDeltaAngularVelocity());
+
+ deltaImpulse -= deltaVel1Dotn*c.m_jacDiagABInv;
+ deltaImpulse -= deltaVel2Dotn*c.m_jacDiagABInv;
+ const b3Scalar sum = b3Scalar(c.m_appliedImpulse) + deltaImpulse;
+ if (sum < c.m_lowerLimit)
+ {
+ deltaImpulse = c.m_lowerLimit-c.m_appliedImpulse;
+ c.m_appliedImpulse = c.m_lowerLimit;
+ }
+ else
+ {
+ c.m_appliedImpulse = sum;
+ }
+ body1.internalApplyImpulse(c.m_contactNormal*body1.internalGetInvMass(),c.m_angularComponentA,deltaImpulse);
+ body2.internalApplyImpulse(-c.m_contactNormal*body2.internalGetInvMass(),c.m_angularComponentB,deltaImpulse);
+}
+
+
+void b3PgsJacobiSolver::resolveSplitPenetrationImpulseCacheFriendly(
+ b3SolverBody& body1,
+ b3SolverBody& body2,
+ const b3SolverConstraint& c)
+{
+ if (c.m_rhsPenetration)
+ {
+ m_numSplitImpulseRecoveries++;
+ b3Scalar deltaImpulse = c.m_rhsPenetration-b3Scalar(c.m_appliedPushImpulse)*c.m_cfm;
+ const b3Scalar deltaVel1Dotn = c.m_contactNormal.dot(body1.internalGetPushVelocity()) + c.m_relpos1CrossNormal.dot(body1.internalGetTurnVelocity());
+ const b3Scalar deltaVel2Dotn = -c.m_contactNormal.dot(body2.internalGetPushVelocity()) + c.m_relpos2CrossNormal.dot(body2.internalGetTurnVelocity());
+
+ deltaImpulse -= deltaVel1Dotn*c.m_jacDiagABInv;
+ deltaImpulse -= deltaVel2Dotn*c.m_jacDiagABInv;
+ const b3Scalar sum = b3Scalar(c.m_appliedPushImpulse) + deltaImpulse;
+ if (sum < c.m_lowerLimit)
+ {
+ deltaImpulse = c.m_lowerLimit-c.m_appliedPushImpulse;
+ c.m_appliedPushImpulse = c.m_lowerLimit;
+ }
+ else
+ {
+ c.m_appliedPushImpulse = sum;
+ }
+ body1.internalApplyPushImpulse(c.m_contactNormal*body1.internalGetInvMass(),c.m_angularComponentA,deltaImpulse);
+ body2.internalApplyPushImpulse(-c.m_contactNormal*body2.internalGetInvMass(),c.m_angularComponentB,deltaImpulse);
+ }
+}
+
+ void b3PgsJacobiSolver::resolveSplitPenetrationSIMD(b3SolverBody& body1,b3SolverBody& body2,const b3SolverConstraint& c)
+{
+#ifdef USE_SIMD
+ if (!c.m_rhsPenetration)
+ return;
+
+ m_numSplitImpulseRecoveries++;
+
+ __m128 cpAppliedImp = _mm_set1_ps(c.m_appliedPushImpulse);
+ __m128 lowerLimit1 = _mm_set1_ps(c.m_lowerLimit);
+ __m128 upperLimit1 = _mm_set1_ps(c.m_upperLimit);
+ __m128 deltaImpulse = _mm_sub_ps(_mm_set1_ps(c.m_rhsPenetration), _mm_mul_ps(_mm_set1_ps(c.m_appliedPushImpulse),_mm_set1_ps(c.m_cfm)));
+ __m128 deltaVel1Dotn = _mm_add_ps(b3SimdDot3(c.m_contactNormal.mVec128,body1.internalGetPushVelocity().mVec128), b3SimdDot3(c.m_relpos1CrossNormal.mVec128,body1.internalGetTurnVelocity().mVec128));
+ __m128 deltaVel2Dotn = _mm_sub_ps(b3SimdDot3(c.m_relpos2CrossNormal.mVec128,body2.internalGetTurnVelocity().mVec128),b3SimdDot3((c.m_contactNormal).mVec128,body2.internalGetPushVelocity().mVec128));
+ deltaImpulse = _mm_sub_ps(deltaImpulse,_mm_mul_ps(deltaVel1Dotn,_mm_set1_ps(c.m_jacDiagABInv)));
+ deltaImpulse = _mm_sub_ps(deltaImpulse,_mm_mul_ps(deltaVel2Dotn,_mm_set1_ps(c.m_jacDiagABInv)));
+ b3SimdScalar sum = _mm_add_ps(cpAppliedImp,deltaImpulse);
+ b3SimdScalar resultLowerLess,resultUpperLess;
+ resultLowerLess = _mm_cmplt_ps(sum,lowerLimit1);
+ resultUpperLess = _mm_cmplt_ps(sum,upperLimit1);
+ __m128 lowMinApplied = _mm_sub_ps(lowerLimit1,cpAppliedImp);
+ deltaImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowMinApplied), _mm_andnot_ps(resultLowerLess, deltaImpulse) );
+ c.m_appliedPushImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowerLimit1), _mm_andnot_ps(resultLowerLess, sum) );
+ __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal.mVec128,body1.internalGetInvMass().mVec128);
+ __m128 linearComponentB = _mm_mul_ps((c.m_contactNormal).mVec128,body2.internalGetInvMass().mVec128);
+ __m128 impulseMagnitude = deltaImpulse;
+ body1.internalGetPushVelocity().mVec128 = _mm_add_ps(body1.internalGetPushVelocity().mVec128,_mm_mul_ps(linearComponentA,impulseMagnitude));
+ body1.internalGetTurnVelocity().mVec128 = _mm_add_ps(body1.internalGetTurnVelocity().mVec128 ,_mm_mul_ps(c.m_angularComponentA.mVec128,impulseMagnitude));
+ body2.internalGetPushVelocity().mVec128 = _mm_sub_ps(body2.internalGetPushVelocity().mVec128,_mm_mul_ps(linearComponentB,impulseMagnitude));
+ body2.internalGetTurnVelocity().mVec128 = _mm_add_ps(body2.internalGetTurnVelocity().mVec128 ,_mm_mul_ps(c.m_angularComponentB.mVec128,impulseMagnitude));
+#else
+ resolveSplitPenetrationImpulseCacheFriendly(body1,body2,c);
+#endif
+}
+
+
+
+unsigned long b3PgsJacobiSolver::b3Rand2()
+{
+ m_btSeed2 = (1664525L*m_btSeed2 + 1013904223L) & 0xffffffff;
+ return m_btSeed2;
+}
+
+
+
+//See ODE: adam's all-int straightforward(?) dRandInt (0..n-1)
+int b3PgsJacobiSolver::b3RandInt2 (int n)
+{
+ // seems good; xor-fold and modulus
+ const unsigned long un = static_cast<unsigned long>(n);
+ unsigned long r = b3Rand2();
+
+ // 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) {
+ r ^= (r >> 16);
+ if (un <= 0x00000100UL) {
+ r ^= (r >> 8);
+ if (un <= 0x00000010UL) {
+ r ^= (r >> 4);
+ if (un <= 0x00000004UL) {
+ r ^= (r >> 2);
+ if (un <= 0x00000002UL) {
+ r ^= (r >> 1);
+ }
+ }
+ }
+ }
+ }
+
+ return (int) (r % un);
+}
+
+
+
+void b3PgsJacobiSolver::initSolverBody(int bodyIndex, b3SolverBody* solverBody, b3RigidBodyData* rb)
+{
+
+ solverBody->m_deltaLinearVelocity.setValue(0.f,0.f,0.f);
+ solverBody->m_deltaAngularVelocity.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 = getWorldTransform(rb);
+ solverBody->internalSetInvMass(b3MakeVector3(rb->m_invMass,rb->m_invMass,rb->m_invMass));
+ solverBody->m_originalBodyIndex = bodyIndex;
+ solverBody->m_angularFactor = b3MakeVector3(1,1,1);
+ solverBody->m_linearFactor = b3MakeVector3(1,1,1);
+ solverBody->m_linearVelocity = getLinearVelocity(rb);
+ solverBody->m_angularVelocity = getAngularVelocity(rb);
+ } else
+ {
+ solverBody->m_worldTransform.setIdentity();
+ solverBody->internalSetInvMass(b3MakeVector3(0,0,0));
+ solverBody->m_originalBodyIndex = bodyIndex;
+ 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);
+ }
+
+
+}
+
+
+
+
+
+
+b3Scalar b3PgsJacobiSolver::restitutionCurve(b3Scalar rel_vel, b3Scalar restitution)
+{
+ b3Scalar rest = restitution * -rel_vel;
+ return rest;
+}
+
+
+
+
+
+
+void b3PgsJacobiSolver::setupFrictionConstraint(b3RigidBodyData* bodies,b3InertiaData* inertias, b3SolverConstraint& solverConstraint, const b3Vector3& normalAxis,int solverBodyIdA,int solverBodyIdB,b3ContactPoint& cp,const b3Vector3& rel_pos1,const b3Vector3& rel_pos2,b3RigidBodyData* colObj0,b3RigidBodyData* colObj1, b3Scalar relaxation, b3Scalar desiredVelocity, b3Scalar cfmSlip)
+{
+
+
+ solverConstraint.m_contactNormal = normalAxis;
+ b3SolverBody& solverBodyA = m_tmpSolverBodyPool[solverBodyIdA];
+ b3SolverBody& solverBodyB = m_tmpSolverBodyPool[solverBodyIdB];
+
+ b3RigidBodyData* body0 = &bodies[solverBodyA.m_originalBodyIndex];
+ b3RigidBodyData* body1 = &bodies[solverBodyB.m_originalBodyIndex];
+
+
+ solverConstraint.m_solverBodyIdA = solverBodyIdA;
+ solverConstraint.m_solverBodyIdB = solverBodyIdB;
+
+ solverConstraint.m_friction = cp.m_combinedFriction;
+ solverConstraint.m_originalContactPoint = 0;
+
+ solverConstraint.m_appliedImpulse = 0.f;
+ solverConstraint.m_appliedPushImpulse = 0.f;
+
+ {
+ b3Vector3 ftorqueAxis1 = rel_pos1.cross(solverConstraint.m_contactNormal);
+ solverConstraint.m_relpos1CrossNormal = ftorqueAxis1;
+ solverConstraint.m_angularComponentA = body0 ? getInvInertiaTensorWorld(&inertias[solverBodyA.m_originalBodyIndex])*ftorqueAxis1 : b3MakeVector3(0,0,0);
+ }
+ {
+ b3Vector3 ftorqueAxis1 = rel_pos2.cross(-solverConstraint.m_contactNormal);
+ solverConstraint.m_relpos2CrossNormal = ftorqueAxis1;
+ solverConstraint.m_angularComponentB = body1 ? getInvInertiaTensorWorld(&inertias[solverBodyB.m_originalBodyIndex])*ftorqueAxis1 : b3MakeVector3(0,0,0);
+ }
+
+ b3Scalar scaledDenom;
+
+ {
+ b3Vector3 vec;
+ b3Scalar denom0 = 0.f;
+ b3Scalar denom1 = 0.f;
+ if (body0)
+ {
+ vec = ( solverConstraint.m_angularComponentA).cross(rel_pos1);
+ denom0 = body0->m_invMass + normalAxis.dot(vec);
+ }
+ if (body1)
+ {
+ vec = ( -solverConstraint.m_angularComponentB).cross(rel_pos2);
+ denom1 = body1->m_invMass + normalAxis.dot(vec);
+ }
+
+ b3Scalar denom;
+ if (m_usePgs)
+ {
+ scaledDenom = denom = relaxation/(denom0+denom1);
+ } else
+ {
+ denom = relaxation/(denom0+denom1);
+ b3Scalar countA = body0->m_invMass ? b3Scalar(m_bodyCount[solverBodyA.m_originalBodyIndex]): 1.f;
+ b3Scalar countB = body1->m_invMass ? b3Scalar(m_bodyCount[solverBodyB.m_originalBodyIndex]): 1.f;
+
+ scaledDenom = relaxation/(denom0*countA+denom1*countB);
+ }
+
+ solverConstraint.m_jacDiagABInv = denom;
+ }
+
+ {
+
+
+ b3Scalar rel_vel;
+ b3Scalar vel1Dotn = solverConstraint.m_contactNormal.dot(body0?solverBodyA.m_linearVelocity:b3MakeVector3(0,0,0))
+ + solverConstraint.m_relpos1CrossNormal.dot(body0?solverBodyA.m_angularVelocity:b3MakeVector3(0,0,0));
+ b3Scalar vel2Dotn = -solverConstraint.m_contactNormal.dot(body1?solverBodyB.m_linearVelocity:b3MakeVector3(0,0,0))
+ + solverConstraint.m_relpos2CrossNormal.dot(body1?solverBodyB.m_angularVelocity:b3MakeVector3(0,0,0));
+
+ rel_vel = vel1Dotn+vel2Dotn;
+
+// b3Scalar positionalError = 0.f;
+
+ b3SimdScalar velocityError = desiredVelocity - rel_vel;
+ b3SimdScalar velocityImpulse = velocityError * b3SimdScalar(scaledDenom);//solverConstraint.m_jacDiagABInv);
+ solverConstraint.m_rhs = velocityImpulse;
+ solverConstraint.m_cfm = cfmSlip;
+ solverConstraint.m_lowerLimit = 0;
+ solverConstraint.m_upperLimit = 1e10f;
+
+ }
+}
+
+b3SolverConstraint& b3PgsJacobiSolver::addFrictionConstraint(b3RigidBodyData* bodies,b3InertiaData* inertias, const b3Vector3& normalAxis,int solverBodyIdA,int solverBodyIdB,int frictionIndex,b3ContactPoint& cp,const b3Vector3& rel_pos1,const b3Vector3& rel_pos2,b3RigidBodyData* colObj0,b3RigidBodyData* colObj1, b3Scalar relaxation, b3Scalar desiredVelocity, b3Scalar cfmSlip)
+{
+ b3SolverConstraint& solverConstraint = m_tmpSolverContactFrictionConstraintPool.expandNonInitializing();
+ solverConstraint.m_frictionIndex = frictionIndex;
+ setupFrictionConstraint(bodies,inertias,solverConstraint, normalAxis, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2,
+ colObj0, colObj1, relaxation, desiredVelocity, cfmSlip);
+ return solverConstraint;
+}
+
+
+void b3PgsJacobiSolver::setupRollingFrictionConstraint(b3RigidBodyData* bodies,b3InertiaData* inertias, b3SolverConstraint& solverConstraint, const b3Vector3& normalAxis1,int solverBodyIdA,int solverBodyIdB,
+ b3ContactPoint& cp,const b3Vector3& rel_pos1,const b3Vector3& rel_pos2,
+ b3RigidBodyData* colObj0,b3RigidBodyData* colObj1, b3Scalar relaxation,
+ b3Scalar desiredVelocity, b3Scalar cfmSlip)
+
+{
+ b3Vector3 normalAxis=b3MakeVector3(0,0,0);
+
+
+ solverConstraint.m_contactNormal = normalAxis;
+ b3SolverBody& solverBodyA = m_tmpSolverBodyPool[solverBodyIdA];
+ b3SolverBody& solverBodyB = m_tmpSolverBodyPool[solverBodyIdB];
+
+ b3RigidBodyData* body0 = &bodies[m_tmpSolverBodyPool[solverBodyIdA].m_originalBodyIndex];
+ b3RigidBodyData* body1 = &bodies[m_tmpSolverBodyPool[solverBodyIdB].m_originalBodyIndex];
+
+ solverConstraint.m_solverBodyIdA = solverBodyIdA;
+ solverConstraint.m_solverBodyIdB = solverBodyIdB;
+
+ solverConstraint.m_friction = cp.m_combinedRollingFriction;
+ solverConstraint.m_originalContactPoint = 0;
+
+ solverConstraint.m_appliedImpulse = 0.f;
+ solverConstraint.m_appliedPushImpulse = 0.f;
+
+ {
+ b3Vector3 ftorqueAxis1 = -normalAxis1;
+ solverConstraint.m_relpos1CrossNormal = ftorqueAxis1;
+ solverConstraint.m_angularComponentA = body0 ? getInvInertiaTensorWorld(&inertias[solverBodyA.m_originalBodyIndex])*ftorqueAxis1 : b3MakeVector3(0,0,0);
+ }
+ {
+ b3Vector3 ftorqueAxis1 = normalAxis1;
+ solverConstraint.m_relpos2CrossNormal = ftorqueAxis1;
+ solverConstraint.m_angularComponentB = body1 ? getInvInertiaTensorWorld(&inertias[solverBodyB.m_originalBodyIndex])*ftorqueAxis1 : b3MakeVector3(0,0,0);
+ }
+
+
+ {
+ b3Vector3 iMJaA = body0?getInvInertiaTensorWorld(&inertias[solverBodyA.m_originalBodyIndex])*solverConstraint.m_relpos1CrossNormal:b3MakeVector3(0,0,0);
+ b3Vector3 iMJaB = body1?getInvInertiaTensorWorld(&inertias[solverBodyB.m_originalBodyIndex])*solverConstraint.m_relpos2CrossNormal:b3MakeVector3(0,0,0);
+ b3Scalar sum = 0;
+ sum += iMJaA.dot(solverConstraint.m_relpos1CrossNormal);
+ sum += iMJaB.dot(solverConstraint.m_relpos2CrossNormal);
+ solverConstraint.m_jacDiagABInv = b3Scalar(1.)/sum;
+ }
+
+ {
+
+
+ b3Scalar rel_vel;
+ b3Scalar vel1Dotn = solverConstraint.m_contactNormal.dot(body0?solverBodyA.m_linearVelocity:b3MakeVector3(0,0,0))
+ + solverConstraint.m_relpos1CrossNormal.dot(body0?solverBodyA.m_angularVelocity:b3MakeVector3(0,0,0));
+ b3Scalar vel2Dotn = -solverConstraint.m_contactNormal.dot(body1?solverBodyB.m_linearVelocity:b3MakeVector3(0,0,0))
+ + solverConstraint.m_relpos2CrossNormal.dot(body1?solverBodyB.m_angularVelocity:b3MakeVector3(0,0,0));
+
+ rel_vel = vel1Dotn+vel2Dotn;
+
+// b3Scalar positionalError = 0.f;
+
+ b3SimdScalar velocityError = desiredVelocity - rel_vel;
+ b3SimdScalar velocityImpulse = velocityError * b3SimdScalar(solverConstraint.m_jacDiagABInv);
+ solverConstraint.m_rhs = velocityImpulse;
+ solverConstraint.m_cfm = cfmSlip;
+ solverConstraint.m_lowerLimit = 0;
+ solverConstraint.m_upperLimit = 1e10f;
+
+ }
+}
+
+
+
+
+
+
+
+
+b3SolverConstraint& b3PgsJacobiSolver::addRollingFrictionConstraint(b3RigidBodyData* bodies,b3InertiaData* inertias,const b3Vector3& normalAxis,int solverBodyIdA,int solverBodyIdB,int frictionIndex,b3ContactPoint& cp,const b3Vector3& rel_pos1,const b3Vector3& rel_pos2,b3RigidBodyData* colObj0,b3RigidBodyData* colObj1, b3Scalar relaxation, b3Scalar desiredVelocity, b3Scalar cfmSlip)
+{
+ b3SolverConstraint& solverConstraint = m_tmpSolverContactRollingFrictionConstraintPool.expandNonInitializing();
+ solverConstraint.m_frictionIndex = frictionIndex;
+ setupRollingFrictionConstraint(bodies,inertias,solverConstraint, normalAxis, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2,
+ colObj0, colObj1, relaxation, desiredVelocity, cfmSlip);
+ return solverConstraint;
+}
+
+
+int b3PgsJacobiSolver::getOrInitSolverBody(int bodyIndex, b3RigidBodyData* bodies,b3InertiaData* inertias)
+{
+ //b3Assert(bodyIndex< m_tmpSolverBodyPool.size());
+
+ b3RigidBodyData& body = bodies[bodyIndex];
+ int curIndex = -1;
+ if (m_usePgs || body.m_invMass==0.f)
+ {
+ if (m_bodyCount[bodyIndex]<0)
+ {
+ curIndex = m_tmpSolverBodyPool.size();
+ b3SolverBody& solverBody = m_tmpSolverBodyPool.expand();
+ initSolverBody(bodyIndex,&solverBody,&body);
+ solverBody.m_originalBodyIndex = bodyIndex;
+ m_bodyCount[bodyIndex] = curIndex;
+ } else
+ {
+ curIndex = m_bodyCount[bodyIndex];
+ }
+ } else
+ {
+ b3Assert(m_bodyCount[bodyIndex]>0);
+ m_bodyCountCheck[bodyIndex]++;
+ curIndex = m_tmpSolverBodyPool.size();
+ b3SolverBody& solverBody = m_tmpSolverBodyPool.expand();
+ initSolverBody(bodyIndex,&solverBody,&body);
+ solverBody.m_originalBodyIndex = bodyIndex;
+ }
+
+ b3Assert(curIndex>=0);
+ return curIndex;
+
+}
+#include <stdio.h>
+
+
+void b3PgsJacobiSolver::setupContactConstraint(b3RigidBodyData* bodies, b3InertiaData* inertias,b3SolverConstraint& solverConstraint,
+ int solverBodyIdA, int solverBodyIdB,
+ b3ContactPoint& cp, const b3ContactSolverInfo& infoGlobal,
+ b3Vector3& vel, b3Scalar& rel_vel, b3Scalar& relaxation,
+ b3Vector3& rel_pos1, b3Vector3& rel_pos2)
+{
+
+ const b3Vector3& pos1 = cp.getPositionWorldOnA();
+ const b3Vector3& pos2 = cp.getPositionWorldOnB();
+
+ b3SolverBody* bodyA = &m_tmpSolverBodyPool[solverBodyIdA];
+ b3SolverBody* bodyB = &m_tmpSolverBodyPool[solverBodyIdB];
+
+ b3RigidBodyData* rb0 = &bodies[bodyA->m_originalBodyIndex];
+ b3RigidBodyData* rb1 = &bodies[bodyB->m_originalBodyIndex];
+
+// b3Vector3 rel_pos1 = pos1 - colObj0->getWorldTransform().getOrigin();
+// b3Vector3 rel_pos2 = pos2 - colObj1->getWorldTransform().getOrigin();
+ rel_pos1 = pos1 - bodyA->getWorldTransform().getOrigin();
+ rel_pos2 = pos2 - bodyB->getWorldTransform().getOrigin();
+
+ relaxation = 1.f;
+
+ b3Vector3 torqueAxis0 = rel_pos1.cross(cp.m_normalWorldOnB);
+ solverConstraint.m_angularComponentA = rb0 ? getInvInertiaTensorWorld(&inertias[bodyA->m_originalBodyIndex])*torqueAxis0 : b3MakeVector3(0,0,0);
+ b3Vector3 torqueAxis1 = rel_pos2.cross(cp.m_normalWorldOnB);
+ solverConstraint.m_angularComponentB = rb1 ? getInvInertiaTensorWorld(&inertias[bodyB->m_originalBodyIndex])*-torqueAxis1 : b3MakeVector3(0,0,0);
+
+ b3Scalar scaledDenom;
+ {
+#ifdef COMPUTE_IMPULSE_DENOM
+ b3Scalar denom0 = rb0->computeImpulseDenominator(pos1,cp.m_normalWorldOnB);
+ b3Scalar denom1 = rb1->computeImpulseDenominator(pos2,cp.m_normalWorldOnB);
+#else
+ b3Vector3 vec;
+ b3Scalar denom0 = 0.f;
+ b3Scalar denom1 = 0.f;
+ if (rb0)
+ {
+ vec = ( solverConstraint.m_angularComponentA).cross(rel_pos1);
+ denom0 = rb0->m_invMass + cp.m_normalWorldOnB.dot(vec);
+ }
+ if (rb1)
+ {
+ vec = ( -solverConstraint.m_angularComponentB).cross(rel_pos2);
+ denom1 = rb1->m_invMass + cp.m_normalWorldOnB.dot(vec);
+ }
+#endif //COMPUTE_IMPULSE_DENOM
+
+
+ b3Scalar denom;
+ if (m_usePgs)
+ {
+ scaledDenom = denom = relaxation/(denom0+denom1);
+ } else
+ {
+ denom = relaxation/(denom0+denom1);
+
+ b3Scalar countA = rb0->m_invMass? b3Scalar(m_bodyCount[bodyA->m_originalBodyIndex]) : 1.f;
+ b3Scalar countB = rb1->m_invMass? b3Scalar(m_bodyCount[bodyB->m_originalBodyIndex]) : 1.f;
+ scaledDenom = relaxation/(denom0*countA+denom1*countB);
+ }
+ solverConstraint.m_jacDiagABInv = denom;
+ }
+
+ solverConstraint.m_contactNormal = cp.m_normalWorldOnB;
+ solverConstraint.m_relpos1CrossNormal = torqueAxis0;
+ solverConstraint.m_relpos2CrossNormal = -torqueAxis1;
+
+ b3Scalar restitution = 0.f;
+ b3Scalar penetration = cp.getDistance()+infoGlobal.m_linearSlop;
+
+ {
+ b3Vector3 vel1,vel2;
+
+ vel1 = rb0? getVelocityInLocalPoint(rb0,rel_pos1) : b3MakeVector3(0,0,0);
+ vel2 = rb1? getVelocityInLocalPoint(rb1, rel_pos2) : b3MakeVector3(0,0,0);
+
+ // b3Vector3 vel2 = rb1 ? rb1->getVelocityInLocalPoint(rel_pos2) : b3Vector3(0,0,0);
+ vel = vel1 - vel2;
+ rel_vel = cp.m_normalWorldOnB.dot(vel);
+
+
+
+ solverConstraint.m_friction = cp.m_combinedFriction;
+
+
+ restitution = restitutionCurve(rel_vel, cp.m_combinedRestitution);
+ if (restitution <= b3Scalar(0.))
+ {
+ restitution = 0.f;
+ };
+ }
+
+
+ ///warm starting (or zero if disabled)
+ if (infoGlobal.m_solverMode & B3_SOLVER_USE_WARMSTARTING)
+ {
+ solverConstraint.m_appliedImpulse = cp.m_appliedImpulse * infoGlobal.m_warmstartingFactor;
+ if (rb0)
+ bodyA->internalApplyImpulse(solverConstraint.m_contactNormal*bodyA->internalGetInvMass(),solverConstraint.m_angularComponentA,solverConstraint.m_appliedImpulse);
+ if (rb1)
+ bodyB->internalApplyImpulse(solverConstraint.m_contactNormal*bodyB->internalGetInvMass(),-solverConstraint.m_angularComponentB,-(b3Scalar)solverConstraint.m_appliedImpulse);
+ } else
+ {
+ solverConstraint.m_appliedImpulse = 0.f;
+ }
+
+ solverConstraint.m_appliedPushImpulse = 0.f;
+
+ {
+ b3Scalar vel1Dotn = solverConstraint.m_contactNormal.dot(rb0?bodyA->m_linearVelocity:b3MakeVector3(0,0,0))
+ + solverConstraint.m_relpos1CrossNormal.dot(rb0?bodyA->m_angularVelocity:b3MakeVector3(0,0,0));
+ b3Scalar vel2Dotn = -solverConstraint.m_contactNormal.dot(rb1?bodyB->m_linearVelocity:b3MakeVector3(0,0,0))
+ + solverConstraint.m_relpos2CrossNormal.dot(rb1?bodyB->m_angularVelocity:b3MakeVector3(0,0,0));
+ b3Scalar rel_vel = vel1Dotn+vel2Dotn;
+
+ b3Scalar positionalError = 0.f;
+ b3Scalar velocityError = restitution - rel_vel;// * damping;
+
+
+ b3Scalar erp = infoGlobal.m_erp2;
+ if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold))
+ {
+ erp = infoGlobal.m_erp;
+ }
+
+ if (penetration>0)
+ {
+ positionalError = 0;
+
+ velocityError -= penetration / infoGlobal.m_timeStep;
+ } else
+ {
+ positionalError = -penetration * erp/infoGlobal.m_timeStep;
+ }
+
+ b3Scalar penetrationImpulse = positionalError*scaledDenom;//solverConstraint.m_jacDiagABInv;
+ b3Scalar velocityImpulse = velocityError *scaledDenom;//solverConstraint.m_jacDiagABInv;
+
+ if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold))
+ {
+ //combine position and velocity into rhs
+ solverConstraint.m_rhs = penetrationImpulse+velocityImpulse;
+ solverConstraint.m_rhsPenetration = 0.f;
+
+ } else
+ {
+ //split position and velocity into rhs and m_rhsPenetration
+ solverConstraint.m_rhs = velocityImpulse;
+ solverConstraint.m_rhsPenetration = penetrationImpulse;
+ }
+ solverConstraint.m_cfm = 0.f;
+ solverConstraint.m_lowerLimit = 0;
+ solverConstraint.m_upperLimit = 1e10f;
+ }
+
+
+
+
+}
+
+
+
+void b3PgsJacobiSolver::setFrictionConstraintImpulse( b3RigidBodyData* bodies, b3InertiaData* inertias,b3SolverConstraint& solverConstraint,
+ int solverBodyIdA, int solverBodyIdB,
+ b3ContactPoint& cp, const b3ContactSolverInfo& infoGlobal)
+{
+
+ b3SolverBody* bodyA = &m_tmpSolverBodyPool[solverBodyIdA];
+ b3SolverBody* bodyB = &m_tmpSolverBodyPool[solverBodyIdB];
+
+
+ {
+ b3SolverConstraint& frictionConstraint1 = m_tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex];
+ if (infoGlobal.m_solverMode & B3_SOLVER_USE_WARMSTARTING)
+ {
+ frictionConstraint1.m_appliedImpulse = cp.m_appliedImpulseLateral1 * infoGlobal.m_warmstartingFactor;
+ if (bodies[bodyA->m_originalBodyIndex].m_invMass)
+ bodyA->internalApplyImpulse(frictionConstraint1.m_contactNormal*bodies[bodyA->m_originalBodyIndex].m_invMass,frictionConstraint1.m_angularComponentA,frictionConstraint1.m_appliedImpulse);
+ if (bodies[bodyB->m_originalBodyIndex].m_invMass)
+ bodyB->internalApplyImpulse(frictionConstraint1.m_contactNormal*bodies[bodyB->m_originalBodyIndex].m_invMass,-frictionConstraint1.m_angularComponentB,-(b3Scalar)frictionConstraint1.m_appliedImpulse);
+ } else
+ {
+ frictionConstraint1.m_appliedImpulse = 0.f;
+ }
+ }
+
+ if ((infoGlobal.m_solverMode & B3_SOLVER_USE_2_FRICTION_DIRECTIONS))
+ {
+ b3SolverConstraint& frictionConstraint2 = m_tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex+1];
+ if (infoGlobal.m_solverMode & B3_SOLVER_USE_WARMSTARTING)
+ {
+ frictionConstraint2.m_appliedImpulse = cp.m_appliedImpulseLateral2 * infoGlobal.m_warmstartingFactor;
+ if (bodies[bodyA->m_originalBodyIndex].m_invMass)
+ bodyA->internalApplyImpulse(frictionConstraint2.m_contactNormal*bodies[bodyA->m_originalBodyIndex].m_invMass,frictionConstraint2.m_angularComponentA,frictionConstraint2.m_appliedImpulse);
+ if (bodies[bodyB->m_originalBodyIndex].m_invMass)
+ bodyB->internalApplyImpulse(frictionConstraint2.m_contactNormal*bodies[bodyB->m_originalBodyIndex].m_invMass,-frictionConstraint2.m_angularComponentB,-(b3Scalar)frictionConstraint2.m_appliedImpulse);
+ } else
+ {
+ frictionConstraint2.m_appliedImpulse = 0.f;
+ }
+ }
+}
+
+
+
+
+void b3PgsJacobiSolver::convertContact(b3RigidBodyData* bodies, b3InertiaData* inertias,b3Contact4* manifold,const b3ContactSolverInfo& infoGlobal)
+{
+ b3RigidBodyData* colObj0=0,*colObj1=0;
+
+
+ int solverBodyIdA = getOrInitSolverBody(manifold->getBodyA(),bodies,inertias);
+ int solverBodyIdB = getOrInitSolverBody(manifold->getBodyB(),bodies,inertias);
+
+// b3RigidBody* bodyA = b3RigidBody::upcast(colObj0);
+// b3RigidBody* bodyB = b3RigidBody::upcast(colObj1);
+
+ b3SolverBody* solverBodyA = &m_tmpSolverBodyPool[solverBodyIdA];
+ b3SolverBody* solverBodyB = &m_tmpSolverBodyPool[solverBodyIdB];
+
+
+
+ ///avoid collision response between two static objects
+ if (solverBodyA->m_invMass.isZero() && solverBodyB->m_invMass.isZero())
+ return;
+
+ int rollingFriction=1;
+ int numContacts = getNumContacts(manifold);
+ for (int j=0;j<numContacts;j++)
+ {
+
+ b3ContactPoint cp;
+ getContactPoint(manifold,j,cp);
+
+ if (cp.getDistance() <= getContactProcessingThreshold(manifold))
+ {
+ b3Vector3 rel_pos1;
+ b3Vector3 rel_pos2;
+ b3Scalar relaxation;
+ b3Scalar rel_vel;
+ b3Vector3 vel;
+
+ int frictionIndex = m_tmpSolverContactConstraintPool.size();
+ b3SolverConstraint& solverConstraint = m_tmpSolverContactConstraintPool.expandNonInitializing();
+// b3RigidBody* rb0 = b3RigidBody::upcast(colObj0);
+// b3RigidBody* rb1 = b3RigidBody::upcast(colObj1);
+ solverConstraint.m_solverBodyIdA = solverBodyIdA;
+ solverConstraint.m_solverBodyIdB = solverBodyIdB;
+
+ solverConstraint.m_originalContactPoint = &cp;
+
+ setupContactConstraint(bodies,inertias,solverConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal, vel, rel_vel, relaxation, rel_pos1, rel_pos2);
+
+// const b3Vector3& pos1 = cp.getPositionWorldOnA();
+// const b3Vector3& pos2 = cp.getPositionWorldOnB();
+
+ /////setup the friction constraints
+
+ solverConstraint.m_frictionIndex = m_tmpSolverContactFrictionConstraintPool.size();
+
+ b3Vector3 angVelA,angVelB;
+ solverBodyA->getAngularVelocity(angVelA);
+ solverBodyB->getAngularVelocity(angVelB);
+ b3Vector3 relAngVel = angVelB-angVelA;
+
+ if ((cp.m_combinedRollingFriction>0.f) && (rollingFriction>0))
+ {
+ //only a single rollingFriction per manifold
+ rollingFriction--;
+ if (relAngVel.length()>infoGlobal.m_singleAxisRollingFrictionThreshold)
+ {
+ relAngVel.normalize();
+ if (relAngVel.length()>0.001)
+ addRollingFrictionConstraint(bodies,inertias,relAngVel,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
+
+ } else
+ {
+ addRollingFrictionConstraint(bodies,inertias,cp.m_normalWorldOnB,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
+ b3Vector3 axis0,axis1;
+ b3PlaneSpace1(cp.m_normalWorldOnB,axis0,axis1);
+ if (axis0.length()>0.001)
+ addRollingFrictionConstraint(bodies,inertias,axis0,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
+ if (axis1.length()>0.001)
+ addRollingFrictionConstraint(bodies,inertias,axis1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,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
+ ///based on the relative linear velocity.
+ ///If the relative velocity it zero, it will automatically compute a friction direction.
+
+ ///You can also enable two friction directions, using the B3_SOLVER_USE_2_FRICTION_DIRECTIONS.
+ ///In that case, the second friction direction will be orthogonal to both contact normal and first friction direction.
+ ///
+ ///If you choose B3_SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION, then the friction will be independent from the relative projected velocity.
+ ///
+ ///The user can manually override the friction directions for certain contacts using a contact callback,
+ ///and set the cp.m_lateralFrictionInitialized to true
+ ///In that case, you can set the target relative motion in each friction direction (cp.m_contactMotion1 and cp.m_contactMotion2)
+ ///this will give a conveyor belt effect
+ ///
+ if (!(infoGlobal.m_solverMode & B3_SOLVER_ENABLE_FRICTION_DIRECTION_CACHING) || !cp.m_lateralFrictionInitialized)
+ {
+ cp.m_lateralFrictionDir1 = vel - cp.m_normalWorldOnB * rel_vel;
+ b3Scalar lat_rel_vel = cp.m_lateralFrictionDir1.length2();
+ if (!(infoGlobal.m_solverMode & B3_SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION) && lat_rel_vel > B3_EPSILON)
+ {
+ cp.m_lateralFrictionDir1 *= 1.f/b3Sqrt(lat_rel_vel);
+ if((infoGlobal.m_solverMode & B3_SOLVER_USE_2_FRICTION_DIRECTIONS))
+ {
+ cp.m_lateralFrictionDir2 = cp.m_lateralFrictionDir1.cross(cp.m_normalWorldOnB);
+ cp.m_lateralFrictionDir2.normalize();//??
+ addFrictionConstraint(bodies,inertias,cp.m_lateralFrictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
+
+ }
+
+ addFrictionConstraint(bodies,inertias,cp.m_lateralFrictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
+
+ } else
+ {
+ b3PlaneSpace1(cp.m_normalWorldOnB,cp.m_lateralFrictionDir1,cp.m_lateralFrictionDir2);
+
+ if ((infoGlobal.m_solverMode & B3_SOLVER_USE_2_FRICTION_DIRECTIONS))
+ {
+ addFrictionConstraint(bodies,inertias,cp.m_lateralFrictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
+ }
+
+ addFrictionConstraint(bodies,inertias,cp.m_lateralFrictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
+
+ if ((infoGlobal.m_solverMode & B3_SOLVER_USE_2_FRICTION_DIRECTIONS) && (infoGlobal.m_solverMode & B3_SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION))
+ {
+ cp.m_lateralFrictionInitialized = true;
+ }
+ }
+
+ } else
+ {
+ addFrictionConstraint(bodies,inertias,cp.m_lateralFrictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation,cp.m_contactMotion1, cp.m_contactCFM1);
+
+ if ((infoGlobal.m_solverMode & B3_SOLVER_USE_2_FRICTION_DIRECTIONS))
+ addFrictionConstraint(bodies,inertias,cp.m_lateralFrictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation, cp.m_contactMotion2, cp.m_contactCFM2);
+
+ setFrictionConstraintImpulse( bodies,inertias,solverConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal);
+ }
+
+
+
+
+ }
+ }
+}
+
+b3Scalar b3PgsJacobiSolver::solveGroupCacheFriendlySetup(b3RigidBodyData* bodies, b3InertiaData* inertias, int numBodies, b3Contact4* manifoldPtr, int numManifolds,b3TypedConstraint** constraints,int numConstraints,const b3ContactSolverInfo& infoGlobal)
+{
+ B3_PROFILE("solveGroupCacheFriendlySetup");
+
+
+ m_maxOverrideNumSolverIterations = 0;
+
+
+
+ m_tmpSolverBodyPool.resize(0);
+
+
+ m_bodyCount.resize(0);
+ m_bodyCount.resize(numBodies,0);
+ m_bodyCountCheck.resize(0);
+ m_bodyCountCheck.resize(numBodies,0);
+
+ m_deltaLinearVelocities.resize(0);
+ m_deltaLinearVelocities.resize(numBodies,b3MakeVector3(0,0,0));
+ m_deltaAngularVelocities.resize(0);
+ m_deltaAngularVelocities.resize(numBodies,b3MakeVector3(0,0,0));
+
+ //int totalBodies = 0;
+
+ for (int i=0;i<numConstraints;i++)
+ {
+ int bodyIndexA = constraints[i]->getRigidBodyA();
+ int bodyIndexB = constraints[i]->getRigidBodyB();
+ if (m_usePgs)
+ {
+ m_bodyCount[bodyIndexA]=-1;
+ m_bodyCount[bodyIndexB]=-1;
+ } else
+ {
+ //didn't implement joints with Jacobi version yet
+ b3Assert(0);
+ }
+
+ }
+ for (int i=0;i<numManifolds;i++)
+ {
+ int bodyIndexA = manifoldPtr[i].getBodyA();
+ int bodyIndexB = manifoldPtr[i].getBodyB();
+ if (m_usePgs)
+ {
+ m_bodyCount[bodyIndexA]=-1;
+ m_bodyCount[bodyIndexB]=-1;
+ } else
+ {
+ if (bodies[bodyIndexA].m_invMass)
+ {
+ //m_bodyCount[bodyIndexA]+=manifoldPtr[i].getNPoints();
+ m_bodyCount[bodyIndexA]++;
+ }
+ else
+ m_bodyCount[bodyIndexA]=-1;
+
+ if (bodies[bodyIndexB].m_invMass)
+ // m_bodyCount[bodyIndexB]+=manifoldPtr[i].getNPoints();
+ m_bodyCount[bodyIndexB]++;
+ else
+ m_bodyCount[bodyIndexB]=-1;
+ }
+
+ }
+
+
+
+ if (1)
+ {
+ int j;
+ for (j=0;j<numConstraints;j++)
+ {
+ b3TypedConstraint* constraint = constraints[j];
+
+ constraint->internalSetAppliedImpulse(0.0f);
+ }
+ }
+
+ //b3RigidBody* rb0=0,*rb1=0;
+ //if (1)
+ {
+ {
+
+ int totalNumRows = 0;
+ int i;
+
+ m_tmpConstraintSizesPool.resizeNoInitialize(numConstraints);
+ //calculate the total number of contraint rows
+ for (i=0;i<numConstraints;i++)
+ {
+ b3TypedConstraint::b3ConstraintInfo1& info1 = m_tmpConstraintSizesPool[i];
+ b3JointFeedback* fb = constraints[i]->getJointFeedback();
+ if (fb)
+ {
+ fb->m_appliedForceBodyA.setZero();
+ fb->m_appliedTorqueBodyA.setZero();
+ fb->m_appliedForceBodyB.setZero();
+ fb->m_appliedTorqueBodyB.setZero();
+ }
+
+ if (constraints[i]->isEnabled())
+ {
+ }
+ if (constraints[i]->isEnabled())
+ {
+ constraints[i]->getInfo1(&info1,bodies);
+ } else
+ {
+ info1.m_numConstraintRows = 0;
+ info1.nub = 0;
+ }
+ totalNumRows += info1.m_numConstraintRows;
+ }
+ m_tmpSolverNonContactConstraintPool.resizeNoInitialize(totalNumRows);
+
+
+#ifndef DISABLE_JOINTS
+ ///setup the b3SolverConstraints
+ int currentRow = 0;
+
+ for (i=0;i<numConstraints;i++)
+ {
+ const b3TypedConstraint::b3ConstraintInfo1& info1 = m_tmpConstraintSizesPool[i];
+
+ if (info1.m_numConstraintRows)
+ {
+ b3Assert(currentRow<totalNumRows);
+
+ b3SolverConstraint* currentConstraintRow = &m_tmpSolverNonContactConstraintPool[currentRow];
+ b3TypedConstraint* constraint = constraints[i];
+
+ b3RigidBodyData& rbA = bodies[ constraint->getRigidBodyA()];
+ //b3RigidBody& rbA = constraint->getRigidBodyA();
+ // b3RigidBody& rbB = constraint->getRigidBodyB();
+ b3RigidBodyData& rbB = bodies[ constraint->getRigidBodyB()];
+
+ int solverBodyIdA = getOrInitSolverBody(constraint->getRigidBodyA(),bodies,inertias);
+ int solverBodyIdB = getOrInitSolverBody(constraint->getRigidBodyB(),bodies,inertias);
+
+ b3SolverBody* bodyAPtr = &m_tmpSolverBodyPool[solverBodyIdA];
+ b3SolverBody* bodyBPtr = &m_tmpSolverBodyPool[solverBodyIdB];
+
+
+
+
+ int overrideNumSolverIterations = constraint->getOverrideNumSolverIterations() > 0 ? constraint->getOverrideNumSolverIterations() : infoGlobal.m_numIterations;
+ if (overrideNumSolverIterations>m_maxOverrideNumSolverIterations)
+ m_maxOverrideNumSolverIterations = overrideNumSolverIterations;
+
+
+ int j;
+ for ( j=0;j<info1.m_numConstraintRows;j++)
+ {
+ memset(&currentConstraintRow[j],0,sizeof(b3SolverConstraint));
+ currentConstraintRow[j].m_lowerLimit = -B3_INFINITY;
+ currentConstraintRow[j].m_upperLimit = B3_INFINITY;
+ currentConstraintRow[j].m_appliedImpulse = 0.f;
+ currentConstraintRow[j].m_appliedPushImpulse = 0.f;
+ currentConstraintRow[j].m_solverBodyIdA = solverBodyIdA;
+ currentConstraintRow[j].m_solverBodyIdB = solverBodyIdB;
+ currentConstraintRow[j].m_overrideNumSolverIterations = overrideNumSolverIterations;
+ }
+
+ bodyAPtr->internalGetDeltaLinearVelocity().setValue(0.f,0.f,0.f);
+ bodyAPtr->internalGetDeltaAngularVelocity().setValue(0.f,0.f,0.f);
+ bodyAPtr->internalGetPushVelocity().setValue(0.f,0.f,0.f);
+ bodyAPtr->internalGetTurnVelocity().setValue(0.f,0.f,0.f);
+ bodyBPtr->internalGetDeltaLinearVelocity().setValue(0.f,0.f,0.f);
+ bodyBPtr->internalGetDeltaAngularVelocity().setValue(0.f,0.f,0.f);
+ bodyBPtr->internalGetPushVelocity().setValue(0.f,0.f,0.f);
+ bodyBPtr->internalGetTurnVelocity().setValue(0.f,0.f,0.f);
+
+
+ b3TypedConstraint::b3ConstraintInfo2 info2;
+ info2.fps = 1.f/infoGlobal.m_timeStep;
+ info2.erp = infoGlobal.m_erp;
+ info2.m_J1linearAxis = currentConstraintRow->m_contactNormal;
+ info2.m_J1angularAxis = currentConstraintRow->m_relpos1CrossNormal;
+ info2.m_J2linearAxis = 0;
+ info2.m_J2angularAxis = currentConstraintRow->m_relpos2CrossNormal;
+ info2.rowskip = sizeof(b3SolverConstraint)/sizeof(b3Scalar);//check this
+ ///the size of b3SolverConstraint needs be a multiple of b3Scalar
+ b3Assert(info2.rowskip*sizeof(b3Scalar)== sizeof(b3SolverConstraint));
+ info2.m_constraintError = &currentConstraintRow->m_rhs;
+ currentConstraintRow->m_cfm = infoGlobal.m_globalCfm;
+ info2.m_damping = infoGlobal.m_damping;
+ info2.cfm = &currentConstraintRow->m_cfm;
+ info2.m_lowerLimit = &currentConstraintRow->m_lowerLimit;
+ info2.m_upperLimit = &currentConstraintRow->m_upperLimit;
+ info2.m_numIterations = infoGlobal.m_numIterations;
+ constraints[i]->getInfo2(&info2,bodies);
+
+ ///finalize the constraint setup
+ for ( j=0;j<info1.m_numConstraintRows;j++)
+ {
+ b3SolverConstraint& solverConstraint = currentConstraintRow[j];
+
+ if (solverConstraint.m_upperLimit>=constraints[i]->getBreakingImpulseThreshold())
+ {
+ solverConstraint.m_upperLimit = constraints[i]->getBreakingImpulseThreshold();
+ }
+
+ if (solverConstraint.m_lowerLimit<=-constraints[i]->getBreakingImpulseThreshold())
+ {
+ solverConstraint.m_lowerLimit = -constraints[i]->getBreakingImpulseThreshold();
+ }
+
+ solverConstraint.m_originalContactPoint = constraint;
+
+ b3Matrix3x3& invInertiaWorldA= inertias[constraint->getRigidBodyA()].m_invInertiaWorld;
+ {
+
+ //b3Vector3 angularFactorA(1,1,1);
+ const b3Vector3& ftorqueAxis1 = solverConstraint.m_relpos1CrossNormal;
+ solverConstraint.m_angularComponentA = invInertiaWorldA*ftorqueAxis1;//*angularFactorA;
+ }
+
+ b3Matrix3x3& invInertiaWorldB= inertias[constraint->getRigidBodyB()].m_invInertiaWorld;
+ {
+
+ const b3Vector3& ftorqueAxis2 = solverConstraint.m_relpos2CrossNormal;
+ solverConstraint.m_angularComponentB = invInertiaWorldB*ftorqueAxis2;//*constraint->getRigidBodyB().getAngularFactor();
+ }
+
+ {
+ //it is ok to use solverConstraint.m_contactNormal instead of -solverConstraint.m_contactNormal
+ //because it gets multiplied iMJlB
+ b3Vector3 iMJlA = solverConstraint.m_contactNormal*rbA.m_invMass;
+ b3Vector3 iMJaA = invInertiaWorldA*solverConstraint.m_relpos1CrossNormal;
+ b3Vector3 iMJlB = solverConstraint.m_contactNormal*rbB.m_invMass;//sign of normal?
+ b3Vector3 iMJaB = invInertiaWorldB*solverConstraint.m_relpos2CrossNormal;
+
+ b3Scalar sum = iMJlA.dot(solverConstraint.m_contactNormal);
+ sum += iMJaA.dot(solverConstraint.m_relpos1CrossNormal);
+ sum += iMJlB.dot(solverConstraint.m_contactNormal);
+ sum += iMJaB.dot(solverConstraint.m_relpos2CrossNormal);
+ b3Scalar fsum = b3Fabs(sum);
+ b3Assert(fsum > B3_EPSILON);
+ solverConstraint.m_jacDiagABInv = fsum>B3_EPSILON?b3Scalar(1.)/sum : 0.f;
+ }
+
+
+ ///fix rhs
+ ///todo: add force/torque accelerators
+ {
+ b3Scalar rel_vel;
+ b3Scalar vel1Dotn = solverConstraint.m_contactNormal.dot(rbA.m_linVel) + solverConstraint.m_relpos1CrossNormal.dot(rbA.m_angVel);
+ b3Scalar vel2Dotn = -solverConstraint.m_contactNormal.dot(rbB.m_linVel) + solverConstraint.m_relpos2CrossNormal.dot(rbB.m_angVel);
+
+ rel_vel = vel1Dotn+vel2Dotn;
+
+ b3Scalar restitution = 0.f;
+ b3Scalar positionalError = solverConstraint.m_rhs;//already filled in by getConstraintInfo2
+ b3Scalar velocityError = restitution - rel_vel * info2.m_damping;
+ b3Scalar penetrationImpulse = positionalError*solverConstraint.m_jacDiagABInv;
+ b3Scalar velocityImpulse = velocityError *solverConstraint.m_jacDiagABInv;
+ solverConstraint.m_rhs = penetrationImpulse+velocityImpulse;
+ solverConstraint.m_appliedImpulse = 0.f;
+
+ }
+ }
+ }
+ currentRow+=m_tmpConstraintSizesPool[i].m_numConstraintRows;
+ }
+#endif //DISABLE_JOINTS
+ }
+
+
+ {
+ int i;
+
+ for (i=0;i<numManifolds;i++)
+ {
+ b3Contact4& manifold = manifoldPtr[i];
+ convertContact(bodies,inertias,&manifold,infoGlobal);
+ }
+ }
+ }
+
+// b3ContactSolverInfo info = infoGlobal;
+
+
+ int numNonContactPool = m_tmpSolverNonContactConstraintPool.size();
+ int numConstraintPool = m_tmpSolverContactConstraintPool.size();
+ int numFrictionPool = m_tmpSolverContactFrictionConstraintPool.size();
+
+ ///@todo: use stack allocator for such temporarily memory, same for solver bodies/constraints
+ m_orderNonContactConstraintPool.resizeNoInitialize(numNonContactPool);
+ if ((infoGlobal.m_solverMode & B3_SOLVER_USE_2_FRICTION_DIRECTIONS))
+ m_orderTmpConstraintPool.resizeNoInitialize(numConstraintPool*2);
+ else
+ m_orderTmpConstraintPool.resizeNoInitialize(numConstraintPool);
+
+ m_orderFrictionConstraintPool.resizeNoInitialize(numFrictionPool);
+ {
+ int i;
+ for (i=0;i<numNonContactPool;i++)
+ {
+ m_orderNonContactConstraintPool[i] = i;
+ }
+ for (i=0;i<numConstraintPool;i++)
+ {
+ m_orderTmpConstraintPool[i] = i;
+ }
+ for (i=0;i<numFrictionPool;i++)
+ {
+ m_orderFrictionConstraintPool[i] = i;
+ }
+ }
+
+ return 0.f;
+
+}
+
+
+b3Scalar b3PgsJacobiSolver::solveSingleIteration(int iteration,b3TypedConstraint** constraints,int numConstraints,const b3ContactSolverInfo& infoGlobal)
+{
+
+ int numNonContactPool = m_tmpSolverNonContactConstraintPool.size();
+ int numConstraintPool = m_tmpSolverContactConstraintPool.size();
+ int numFrictionPool = m_tmpSolverContactFrictionConstraintPool.size();
+
+ if (infoGlobal.m_solverMode & B3_SOLVER_RANDMIZE_ORDER)
+ {
+ if (1) // uncomment this for a bit less random ((iteration & 7) == 0)
+ {
+
+ for (int j=0; j<numNonContactPool; ++j) {
+ int tmp = m_orderNonContactConstraintPool[j];
+ int swapi = b3RandInt2(j+1);
+ m_orderNonContactConstraintPool[j] = m_orderNonContactConstraintPool[swapi];
+ m_orderNonContactConstraintPool[swapi] = tmp;
+ }
+
+ //contact/friction constraints are not solved more than
+ if (iteration< infoGlobal.m_numIterations)
+ {
+ for (int j=0; j<numConstraintPool; ++j) {
+ int tmp = m_orderTmpConstraintPool[j];
+ int swapi = b3RandInt2(j+1);
+ m_orderTmpConstraintPool[j] = m_orderTmpConstraintPool[swapi];
+ m_orderTmpConstraintPool[swapi] = tmp;
+ }
+
+ for (int j=0; j<numFrictionPool; ++j) {
+ int tmp = m_orderFrictionConstraintPool[j];
+ int swapi = b3RandInt2(j+1);
+ m_orderFrictionConstraintPool[j] = m_orderFrictionConstraintPool[swapi];
+ m_orderFrictionConstraintPool[swapi] = tmp;
+ }
+ }
+ }
+ }
+
+ if (infoGlobal.m_solverMode & B3_SOLVER_SIMD)
+ {
+ ///solve all joint constraints, using SIMD, if available
+ for (int j=0;j<m_tmpSolverNonContactConstraintPool.size();j++)
+ {
+ b3SolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[m_orderNonContactConstraintPool[j]];
+ if (iteration < constraint.m_overrideNumSolverIterations)
+ resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[constraint.m_solverBodyIdA],m_tmpSolverBodyPool[constraint.m_solverBodyIdB],constraint);
+ }
+
+ if (iteration< infoGlobal.m_numIterations)
+ {
+
+ ///solve all contact constraints using SIMD, if available
+ if (infoGlobal.m_solverMode & B3_SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS)
+ {
+ int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
+ int multiplier = (infoGlobal.m_solverMode & B3_SOLVER_USE_2_FRICTION_DIRECTIONS)? 2 : 1;
+
+ for (int c=0;c<numPoolConstraints;c++)
+ {
+ b3Scalar totalImpulse =0;
+
+ {
+ const b3SolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[c]];
+ resolveSingleConstraintRowLowerLimitSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
+ totalImpulse = solveManifold.m_appliedImpulse;
+ }
+ bool applyFriction = true;
+ if (applyFriction)
+ {
+ {
+
+ b3SolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[c*multiplier]];
+
+ if (totalImpulse>b3Scalar(0))
+ {
+ solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse);
+ solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse;
+
+ resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
+ }
+ }
+
+ if (infoGlobal.m_solverMode & B3_SOLVER_USE_2_FRICTION_DIRECTIONS)
+ {
+
+ b3SolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[c*multiplier+1]];
+
+ if (totalImpulse>b3Scalar(0))
+ {
+ solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse);
+ solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse;
+
+ resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
+ }
+ }
+ }
+ }
+
+ }
+ else//B3_SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS
+ {
+ //solve the friction constraints after all contact constraints, don't interleave them
+ int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
+ int j;
+
+ for (j=0;j<numPoolConstraints;j++)
+ {
+ const b3SolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
+ resolveSingleConstraintRowLowerLimitSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
+
+ }
+
+ if (!m_usePgs)
+ averageVelocities();
+
+
+ ///solve all friction constraints, using SIMD, if available
+
+ int numFrictionPoolConstraints = m_tmpSolverContactFrictionConstraintPool.size();
+ for (j=0;j<numFrictionPoolConstraints;j++)
+ {
+ b3SolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[j]];
+ b3Scalar totalImpulse = m_tmpSolverContactConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
+
+ if (totalImpulse>b3Scalar(0))
+ {
+ solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse);
+ solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse;
+
+ resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
+ }
+ }
+
+
+ int numRollingFrictionPoolConstraints = m_tmpSolverContactRollingFrictionConstraintPool.size();
+ for (j=0;j<numRollingFrictionPoolConstraints;j++)
+ {
+
+ b3SolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[j];
+ b3Scalar totalImpulse = m_tmpSolverContactConstraintPool[rollingFrictionConstraint.m_frictionIndex].m_appliedImpulse;
+ if (totalImpulse>b3Scalar(0))
+ {
+ b3Scalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction*totalImpulse;
+ if (rollingFrictionMagnitude>rollingFrictionConstraint.m_friction)
+ rollingFrictionMagnitude = rollingFrictionConstraint.m_friction;
+
+ rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude;
+ rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude;
+
+ resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA],m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB],rollingFrictionConstraint);
+ }
+ }
+
+
+ }
+ }
+ } else
+ {
+ //non-SIMD version
+ ///solve all joint constraints
+ for (int j=0;j<m_tmpSolverNonContactConstraintPool.size();j++)
+ {
+ b3SolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[m_orderNonContactConstraintPool[j]];
+ if (iteration < constraint.m_overrideNumSolverIterations)
+ resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[constraint.m_solverBodyIdA],m_tmpSolverBodyPool[constraint.m_solverBodyIdB],constraint);
+ }
+
+ if (iteration< infoGlobal.m_numIterations)
+ {
+
+ ///solve all contact constraints
+ int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
+ for (int j=0;j<numPoolConstraints;j++)
+ {
+ const b3SolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
+ resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
+ }
+ ///solve all friction constraints
+ int numFrictionPoolConstraints = m_tmpSolverContactFrictionConstraintPool.size();
+ for (int j=0;j<numFrictionPoolConstraints;j++)
+ {
+ b3SolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[j]];
+ b3Scalar totalImpulse = m_tmpSolverContactConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
+
+ if (totalImpulse>b3Scalar(0))
+ {
+ solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse);
+ solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse;
+
+ resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
+ }
+ }
+
+ int numRollingFrictionPoolConstraints = m_tmpSolverContactRollingFrictionConstraintPool.size();
+ for (int j=0;j<numRollingFrictionPoolConstraints;j++)
+ {
+ b3SolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[j];
+ b3Scalar totalImpulse = m_tmpSolverContactConstraintPool[rollingFrictionConstraint.m_frictionIndex].m_appliedImpulse;
+ if (totalImpulse>b3Scalar(0))
+ {
+ b3Scalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction*totalImpulse;
+ if (rollingFrictionMagnitude>rollingFrictionConstraint.m_friction)
+ rollingFrictionMagnitude = rollingFrictionConstraint.m_friction;
+
+ rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude;
+ rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude;
+
+ resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA],m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB],rollingFrictionConstraint);
+ }
+ }
+ }
+ }
+ return 0.f;
+}
+
+
+void b3PgsJacobiSolver::solveGroupCacheFriendlySplitImpulseIterations(b3TypedConstraint** constraints,int numConstraints,const b3ContactSolverInfo& infoGlobal)
+{
+ int iteration;
+ if (infoGlobal.m_splitImpulse)
+ {
+ if (infoGlobal.m_solverMode & B3_SOLVER_SIMD)
+ {
+ for ( iteration = 0;iteration<infoGlobal.m_numIterations;iteration++)
+ {
+ {
+ int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
+ int j;
+ for (j=0;j<numPoolConstraints;j++)
+ {
+ const b3SolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
+
+ resolveSplitPenetrationSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
+ }
+ }
+ }
+ }
+ else
+ {
+ for ( iteration = 0;iteration<infoGlobal.m_numIterations;iteration++)
+ {
+ {
+ int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
+ int j;
+ for (j=0;j<numPoolConstraints;j++)
+ {
+ const b3SolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
+
+ resolveSplitPenetrationImpulseCacheFriendly(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
+ }
+ }
+ }
+ }
+ }
+}
+
+b3Scalar b3PgsJacobiSolver::solveGroupCacheFriendlyIterations(b3TypedConstraint** constraints,int numConstraints,const b3ContactSolverInfo& infoGlobal)
+{
+ B3_PROFILE("solveGroupCacheFriendlyIterations");
+
+ {
+ ///this is a special step to resolve penetrations (just for contacts)
+ solveGroupCacheFriendlySplitImpulseIterations(constraints,numConstraints,infoGlobal);
+
+ int maxIterations = m_maxOverrideNumSolverIterations > infoGlobal.m_numIterations? m_maxOverrideNumSolverIterations : infoGlobal.m_numIterations;
+
+ for ( int iteration = 0 ; iteration< maxIterations ; iteration++)
+ //for ( int iteration = maxIterations-1 ; iteration >= 0;iteration--)
+ {
+
+ solveSingleIteration(iteration, constraints,numConstraints,infoGlobal);
+
+
+ if (!m_usePgs)
+ {
+ averageVelocities();
+ }
+ }
+
+ }
+ return 0.f;
+}
+
+void b3PgsJacobiSolver::averageVelocities()
+{
+ B3_PROFILE("averaging");
+ //average the velocities
+ int numBodies = m_bodyCount.size();
+
+ m_deltaLinearVelocities.resize(0);
+ m_deltaLinearVelocities.resize(numBodies,b3MakeVector3(0,0,0));
+ m_deltaAngularVelocities.resize(0);
+ m_deltaAngularVelocities.resize(numBodies,b3MakeVector3(0,0,0));
+
+ for (int i=0;i<m_tmpSolverBodyPool.size();i++)
+ {
+ if (!m_tmpSolverBodyPool[i].m_invMass.isZero())
+ {
+ int orgBodyIndex = m_tmpSolverBodyPool[i].m_originalBodyIndex;
+ m_deltaLinearVelocities[orgBodyIndex]+=m_tmpSolverBodyPool[i].getDeltaLinearVelocity();
+ m_deltaAngularVelocities[orgBodyIndex]+=m_tmpSolverBodyPool[i].getDeltaAngularVelocity();
+ }
+ }
+
+ for (int i=0;i<m_tmpSolverBodyPool.size();i++)
+ {
+ int orgBodyIndex = m_tmpSolverBodyPool[i].m_originalBodyIndex;
+
+ if (!m_tmpSolverBodyPool[i].m_invMass.isZero())
+ {
+
+ b3Assert(m_bodyCount[orgBodyIndex] == m_bodyCountCheck[orgBodyIndex]);
+
+ b3Scalar factor = 1.f/b3Scalar(m_bodyCount[orgBodyIndex]);
+
+
+ m_tmpSolverBodyPool[i].m_deltaLinearVelocity = m_deltaLinearVelocities[orgBodyIndex]*factor;
+ m_tmpSolverBodyPool[i].m_deltaAngularVelocity = m_deltaAngularVelocities[orgBodyIndex]*factor;
+ }
+ }
+}
+
+b3Scalar b3PgsJacobiSolver::solveGroupCacheFriendlyFinish(b3RigidBodyData* bodies,b3InertiaData* inertias,int numBodies,const b3ContactSolverInfo& infoGlobal)
+{
+ B3_PROFILE("solveGroupCacheFriendlyFinish");
+ int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
+ int i,j;
+
+ if (infoGlobal.m_solverMode & B3_SOLVER_USE_WARMSTARTING)
+ {
+ for (j=0;j<numPoolConstraints;j++)
+ {
+ const b3SolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[j];
+ b3ContactPoint* pt = (b3ContactPoint*) solveManifold.m_originalContactPoint;
+ b3Assert(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 = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
+ //printf("pt->m_appliedImpulseLateral1 = %f\n", pt->m_appliedImpulseLateral1);
+ if ((infoGlobal.m_solverMode & B3_SOLVER_USE_2_FRICTION_DIRECTIONS))
+ {
+ pt->m_appliedImpulseLateral2 = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex+1].m_appliedImpulse;
+ }
+ //do a callback here?
+ }
+ }
+
+ numPoolConstraints = m_tmpSolverNonContactConstraintPool.size();
+ for (j=0;j<numPoolConstraints;j++)
+ {
+ const b3SolverConstraint& solverConstr = m_tmpSolverNonContactConstraintPool[j];
+ b3TypedConstraint* constr = (b3TypedConstraint*)solverConstr.m_originalContactPoint;
+ b3JointFeedback* fb = constr->getJointFeedback();
+ if (fb)
+ {
+ b3SolverBody* bodyA = &m_tmpSolverBodyPool[solverConstr.m_solverBodyIdA];
+ b3SolverBody* bodyB = &m_tmpSolverBodyPool[solverConstr.m_solverBodyIdB];
+
+ fb->m_appliedForceBodyA += solverConstr.m_contactNormal*solverConstr.m_appliedImpulse*bodyA->m_linearFactor/infoGlobal.m_timeStep;
+ fb->m_appliedForceBodyB += -solverConstr.m_contactNormal*solverConstr.m_appliedImpulse*bodyB->m_linearFactor/infoGlobal.m_timeStep;
+ fb->m_appliedTorqueBodyA += solverConstr.m_relpos1CrossNormal* bodyA->m_angularFactor*solverConstr.m_appliedImpulse/infoGlobal.m_timeStep;
+ fb->m_appliedTorqueBodyB += -solverConstr.m_relpos1CrossNormal* bodyB->m_angularFactor*solverConstr.m_appliedImpulse/infoGlobal.m_timeStep;
+
+ }
+
+ constr->internalSetAppliedImpulse(solverConstr.m_appliedImpulse);
+ if (b3Fabs(solverConstr.m_appliedImpulse)>=constr->getBreakingImpulseThreshold())
+ {
+ constr->setEnabled(false);
+ }
+ }
+
+ {
+ B3_PROFILE("write back velocities and transforms");
+ for ( i=0;i<m_tmpSolverBodyPool.size();i++)
+ {
+ int bodyIndex = m_tmpSolverBodyPool[i].m_originalBodyIndex;
+ //b3Assert(i==bodyIndex);
+
+ b3RigidBodyData* body = &bodies[bodyIndex];
+ if (body->m_invMass)
+ {
+ if (infoGlobal.m_splitImpulse)
+ m_tmpSolverBodyPool[i].writebackVelocityAndTransform(infoGlobal.m_timeStep, infoGlobal.m_splitImpulseTurnErp);
+ else
+ m_tmpSolverBodyPool[i].writebackVelocity();
+
+ if (m_usePgs)
+ {
+ body->m_linVel = m_tmpSolverBodyPool[i].m_linearVelocity;
+ body->m_angVel = m_tmpSolverBodyPool[i].m_angularVelocity;
+ } else
+ {
+ b3Scalar factor = 1.f/b3Scalar(m_bodyCount[bodyIndex]);
+
+ b3Vector3 deltaLinVel = m_deltaLinearVelocities[bodyIndex]*factor;
+ b3Vector3 deltaAngVel = m_deltaAngularVelocities[bodyIndex]*factor;
+ //printf("body %d\n",bodyIndex);
+ //printf("deltaLinVel = %f,%f,%f\n",deltaLinVel.getX(),deltaLinVel.getY(),deltaLinVel.getZ());
+ //printf("deltaAngVel = %f,%f,%f\n",deltaAngVel.getX(),deltaAngVel.getY(),deltaAngVel.getZ());
+
+ body->m_linVel += deltaLinVel;
+ body->m_angVel += deltaAngVel;
+ }
+
+ if (infoGlobal.m_splitImpulse)
+ {
+ body->m_pos = m_tmpSolverBodyPool[i].m_worldTransform.getOrigin();
+ b3Quaternion orn;
+ orn = m_tmpSolverBodyPool[i].m_worldTransform.getRotation();
+ body->m_quat = orn;
+ }
+ }
+ }
+ }
+
+
+ m_tmpSolverContactConstraintPool.resizeNoInitialize(0);
+ m_tmpSolverNonContactConstraintPool.resizeNoInitialize(0);
+ m_tmpSolverContactFrictionConstraintPool.resizeNoInitialize(0);
+ m_tmpSolverContactRollingFrictionConstraintPool.resizeNoInitialize(0);
+
+ m_tmpSolverBodyPool.resizeNoInitialize(0);
+ return 0.f;
+}
+
+
+
+void b3PgsJacobiSolver::reset()
+{
+ m_btSeed2 = 0;
+} \ No newline at end of file
diff --git a/thirdparty/bullet/src/Bullet3Dynamics/ConstraintSolver/b3PgsJacobiSolver.h b/thirdparty/bullet/src/Bullet3Dynamics/ConstraintSolver/b3PgsJacobiSolver.h
new file mode 100644
index 0000000000..d2ca307fab
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Dynamics/ConstraintSolver/b3PgsJacobiSolver.h
@@ -0,0 +1,149 @@
+#ifndef B3_PGS_JACOBI_SOLVER
+#define B3_PGS_JACOBI_SOLVER
+
+
+struct b3Contact4;
+struct b3ContactPoint;
+
+
+class b3Dispatcher;
+
+#include "b3TypedConstraint.h"
+#include "b3ContactSolverInfo.h"
+#include "b3SolverBody.h"
+#include "b3SolverConstraint.h"
+
+struct b3RigidBodyData;
+struct b3InertiaData;
+
+class b3PgsJacobiSolver
+{
+
+protected:
+ b3AlignedObjectArray<b3SolverBody> m_tmpSolverBodyPool;
+ b3ConstraintArray m_tmpSolverContactConstraintPool;
+ b3ConstraintArray m_tmpSolverNonContactConstraintPool;
+ b3ConstraintArray m_tmpSolverContactFrictionConstraintPool;
+ b3ConstraintArray m_tmpSolverContactRollingFrictionConstraintPool;
+
+ b3AlignedObjectArray<int> m_orderTmpConstraintPool;
+ b3AlignedObjectArray<int> m_orderNonContactConstraintPool;
+ b3AlignedObjectArray<int> m_orderFrictionConstraintPool;
+ b3AlignedObjectArray<b3TypedConstraint::b3ConstraintInfo1> m_tmpConstraintSizesPool;
+
+ b3AlignedObjectArray<int> m_bodyCount;
+ b3AlignedObjectArray<int> m_bodyCountCheck;
+
+ b3AlignedObjectArray<b3Vector3> m_deltaLinearVelocities;
+ b3AlignedObjectArray<b3Vector3> m_deltaAngularVelocities;
+
+ bool m_usePgs;
+ void averageVelocities();
+
+ int m_maxOverrideNumSolverIterations;
+
+ int m_numSplitImpulseRecoveries;
+
+ b3Scalar getContactProcessingThreshold(b3Contact4* contact)
+ {
+ return 0.02f;
+ }
+ void setupFrictionConstraint( b3RigidBodyData* bodies,b3InertiaData* inertias, b3SolverConstraint& solverConstraint, const b3Vector3& normalAxis,int solverBodyIdA,int solverBodyIdB,
+ b3ContactPoint& cp,const b3Vector3& rel_pos1,const b3Vector3& rel_pos2,
+ b3RigidBodyData* colObj0,b3RigidBodyData* colObj1, b3Scalar relaxation,
+ b3Scalar desiredVelocity=0., b3Scalar cfmSlip=0.);
+
+ void setupRollingFrictionConstraint(b3RigidBodyData* bodies,b3InertiaData* inertias, b3SolverConstraint& solverConstraint, const b3Vector3& normalAxis,int solverBodyIdA,int solverBodyIdB,
+ b3ContactPoint& cp,const b3Vector3& rel_pos1,const b3Vector3& rel_pos2,
+ b3RigidBodyData* colObj0,b3RigidBodyData* colObj1, b3Scalar relaxation,
+ b3Scalar desiredVelocity=0., b3Scalar cfmSlip=0.);
+
+ b3SolverConstraint& addFrictionConstraint(b3RigidBodyData* bodies,b3InertiaData* inertias,const b3Vector3& normalAxis,int solverBodyIdA,int solverBodyIdB,int frictionIndex,b3ContactPoint& cp,const b3Vector3& rel_pos1,const b3Vector3& rel_pos2,b3RigidBodyData* colObj0,b3RigidBodyData* colObj1, b3Scalar relaxation, b3Scalar desiredVelocity=0., b3Scalar cfmSlip=0.);
+ b3SolverConstraint& addRollingFrictionConstraint(b3RigidBodyData* bodies,b3InertiaData* inertias,const b3Vector3& normalAxis,int solverBodyIdA,int solverBodyIdB,int frictionIndex,b3ContactPoint& cp,const b3Vector3& rel_pos1,const b3Vector3& rel_pos2,b3RigidBodyData* colObj0,b3RigidBodyData* colObj1, b3Scalar relaxation, b3Scalar desiredVelocity=0, b3Scalar cfmSlip=0.f);
+
+
+ void setupContactConstraint(b3RigidBodyData* bodies, b3InertiaData* inertias,
+ b3SolverConstraint& solverConstraint, int solverBodyIdA, int solverBodyIdB, b3ContactPoint& cp,
+ const b3ContactSolverInfo& infoGlobal, b3Vector3& vel, b3Scalar& rel_vel, b3Scalar& relaxation,
+ b3Vector3& rel_pos1, b3Vector3& rel_pos2);
+
+ void setFrictionConstraintImpulse( b3RigidBodyData* bodies, b3InertiaData* inertias,b3SolverConstraint& solverConstraint, int solverBodyIdA,int solverBodyIdB,
+ b3ContactPoint& cp, const b3ContactSolverInfo& infoGlobal);
+
+ ///m_btSeed2 is used for re-arranging the constraint rows. improves convergence/quality of friction
+ unsigned long m_btSeed2;
+
+
+ b3Scalar restitutionCurve(b3Scalar rel_vel, b3Scalar restitution);
+
+ void convertContact(b3RigidBodyData* bodies, b3InertiaData* inertias,b3Contact4* manifold,const b3ContactSolverInfo& infoGlobal);
+
+
+ void resolveSplitPenetrationSIMD(
+ b3SolverBody& bodyA,b3SolverBody& bodyB,
+ const b3SolverConstraint& contactConstraint);
+
+ void resolveSplitPenetrationImpulseCacheFriendly(
+ b3SolverBody& bodyA,b3SolverBody& bodyB,
+ const b3SolverConstraint& contactConstraint);
+
+ //internal method
+ int getOrInitSolverBody(int bodyIndex, b3RigidBodyData* bodies,b3InertiaData* inertias);
+ void initSolverBody(int bodyIndex, b3SolverBody* solverBody, b3RigidBodyData* collisionObject);
+
+ void resolveSingleConstraintRowGeneric(b3SolverBody& bodyA,b3SolverBody& bodyB,const b3SolverConstraint& contactConstraint);
+
+ void resolveSingleConstraintRowGenericSIMD(b3SolverBody& bodyA,b3SolverBody& bodyB,const b3SolverConstraint& contactConstraint);
+
+ void resolveSingleConstraintRowLowerLimit(b3SolverBody& bodyA,b3SolverBody& bodyB,const b3SolverConstraint& contactConstraint);
+
+ void resolveSingleConstraintRowLowerLimitSIMD(b3SolverBody& bodyA,b3SolverBody& bodyB,const b3SolverConstraint& contactConstraint);
+
+protected:
+
+ virtual b3Scalar solveGroupCacheFriendlySetup(b3RigidBodyData* bodies, b3InertiaData* inertias,int numBodies,b3Contact4* manifoldPtr, int numManifolds,b3TypedConstraint** constraints,int numConstraints,const b3ContactSolverInfo& infoGlobal);
+
+
+ virtual b3Scalar solveGroupCacheFriendlyIterations(b3TypedConstraint** constraints,int numConstraints,const b3ContactSolverInfo& infoGlobal);
+ virtual void solveGroupCacheFriendlySplitImpulseIterations(b3TypedConstraint** constraints,int numConstraints,const b3ContactSolverInfo& infoGlobal);
+ b3Scalar solveSingleIteration(int iteration, b3TypedConstraint** constraints,int numConstraints,const b3ContactSolverInfo& infoGlobal);
+
+
+ virtual b3Scalar solveGroupCacheFriendlyFinish(b3RigidBodyData* bodies, b3InertiaData* inertias,int numBodies,const b3ContactSolverInfo& infoGlobal);
+
+
+public:
+
+ B3_DECLARE_ALIGNED_ALLOCATOR();
+
+ b3PgsJacobiSolver(bool usePgs);
+ virtual ~b3PgsJacobiSolver();
+
+// void solveContacts(int numBodies, b3RigidBodyData* bodies, b3InertiaData* inertias, int numContacts, b3Contact4* contacts);
+ void solveContacts(int numBodies, b3RigidBodyData* bodies, b3InertiaData* inertias, int numContacts, b3Contact4* contacts, int numConstraints, b3TypedConstraint** constraints);
+
+ b3Scalar solveGroup(b3RigidBodyData* bodies,b3InertiaData* inertias,int numBodies,b3Contact4* manifoldPtr, int numManifolds,b3TypedConstraint** constraints,int numConstraints,const b3ContactSolverInfo& infoGlobal);
+
+ ///clear internal cached data and reset random seed
+ virtual void reset();
+
+ unsigned long b3Rand2();
+
+ int b3RandInt2 (int n);
+
+ void setRandSeed(unsigned long seed)
+ {
+ m_btSeed2 = seed;
+ }
+ unsigned long getRandSeed() const
+ {
+ return m_btSeed2;
+ }
+
+
+
+
+};
+
+#endif //B3_PGS_JACOBI_SOLVER
+
diff --git a/thirdparty/bullet/src/Bullet3Dynamics/ConstraintSolver/b3Point2PointConstraint.cpp b/thirdparty/bullet/src/Bullet3Dynamics/ConstraintSolver/b3Point2PointConstraint.cpp
new file mode 100644
index 0000000000..02c11db320
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Dynamics/ConstraintSolver/b3Point2PointConstraint.cpp
@@ -0,0 +1,209 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "b3Point2PointConstraint.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
+
+#include <new>
+
+
+
+
+
+b3Point2PointConstraint::b3Point2PointConstraint(int rbA,int rbB, const b3Vector3& pivotInA,const b3Vector3& pivotInB)
+:b3TypedConstraint(B3_POINT2POINT_CONSTRAINT_TYPE,rbA,rbB),m_pivotInA(pivotInA),m_pivotInB(pivotInB),
+m_flags(0)
+{
+
+}
+
+/*
+b3Point2PointConstraint::b3Point2PointConstraint(int rbA,const b3Vector3& pivotInA)
+:b3TypedConstraint(B3_POINT2POINT_CONSTRAINT_TYPE,rbA),m_pivotInA(pivotInA),m_pivotInB(rbA.getCenterOfMassTransform()(pivotInA)),
+m_flags(0),
+m_useSolveConstraintObsolete(false)
+{
+
+}
+*/
+
+
+void b3Point2PointConstraint::getInfo1 (b3ConstraintInfo1* info,const b3RigidBodyData* bodies)
+{
+ getInfo1NonVirtual(info,bodies);
+}
+
+void b3Point2PointConstraint::getInfo1NonVirtual (b3ConstraintInfo1* info,const b3RigidBodyData* bodies)
+{
+ info->m_numConstraintRows = 3;
+ info->nub = 3;
+}
+
+
+
+
+void b3Point2PointConstraint::getInfo2 (b3ConstraintInfo2* info, const b3RigidBodyData* bodies)
+{
+ b3Transform trA;
+ trA.setIdentity();
+ trA.setOrigin(bodies[m_rbA].m_pos);
+ trA.setRotation(bodies[m_rbA].m_quat);
+
+ b3Transform trB;
+ trB.setIdentity();
+ trB.setOrigin(bodies[m_rbB].m_pos);
+ trB.setRotation(bodies[m_rbB].m_quat);
+
+ getInfo2NonVirtual(info, trA,trB);
+}
+
+void b3Point2PointConstraint::getInfo2NonVirtual (b3ConstraintInfo2* info, const b3Transform& body0_trans, const b3Transform& body1_trans)
+{
+
+ //retrieve matrices
+
+ // anchor points in global coordinates with respect to body PORs.
+
+ // set jacobian
+ info->m_J1linearAxis[0] = 1;
+ info->m_J1linearAxis[info->rowskip+1] = 1;
+ info->m_J1linearAxis[2*info->rowskip+2] = 1;
+
+ b3Vector3 a1 = body0_trans.getBasis()*getPivotInA();
+ //b3Vector3 a1a = b3QuatRotate(body0_trans.getRotation(),getPivotInA());
+
+ {
+ b3Vector3* angular0 = (b3Vector3*)(info->m_J1angularAxis);
+ b3Vector3* angular1 = (b3Vector3*)(info->m_J1angularAxis+info->rowskip);
+ b3Vector3* angular2 = (b3Vector3*)(info->m_J1angularAxis+2*info->rowskip);
+ b3Vector3 a1neg = -a1;
+ a1neg.getSkewSymmetricMatrix(angular0,angular1,angular2);
+ }
+
+ if (info->m_J2linearAxis)
+ {
+ info->m_J2linearAxis[0] = -1;
+ info->m_J2linearAxis[info->rowskip+1] = -1;
+ info->m_J2linearAxis[2*info->rowskip+2] = -1;
+ }
+
+ b3Vector3 a2 = body1_trans.getBasis()*getPivotInB();
+
+ {
+ // b3Vector3 a2n = -a2;
+ b3Vector3* angular0 = (b3Vector3*)(info->m_J2angularAxis);
+ b3Vector3* angular1 = (b3Vector3*)(info->m_J2angularAxis+info->rowskip);
+ b3Vector3* angular2 = (b3Vector3*)(info->m_J2angularAxis+2*info->rowskip);
+ a2.getSkewSymmetricMatrix(angular0,angular1,angular2);
+ }
+
+
+
+ // set right hand side
+ b3Scalar currERP = (m_flags & B3_P2P_FLAGS_ERP) ? m_erp : info->erp;
+ b3Scalar k = info->fps * currERP;
+ int j;
+ for (j=0; j<3; j++)
+ {
+ info->m_constraintError[j*info->rowskip] = k * (a2[j] + body1_trans.getOrigin()[j] - a1[j] - body0_trans.getOrigin()[j]);
+ //printf("info->m_constraintError[%d]=%f\n",j,info->m_constraintError[j]);
+ }
+ if(m_flags & B3_P2P_FLAGS_CFM)
+ {
+ for (j=0; j<3; j++)
+ {
+ info->cfm[j*info->rowskip] = m_cfm;
+ }
+ }
+
+ b3Scalar impulseClamp = m_setting.m_impulseClamp;//
+ for (j=0; j<3; j++)
+ {
+ if (m_setting.m_impulseClamp > 0)
+ {
+ info->m_lowerLimit[j*info->rowskip] = -impulseClamp;
+ info->m_upperLimit[j*info->rowskip] = impulseClamp;
+ }
+ }
+ info->m_damping = m_setting.m_damping;
+
+}
+
+
+
+void b3Point2PointConstraint::updateRHS(b3Scalar timeStep)
+{
+ (void)timeStep;
+
+}
+
+///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
+///If no axis is provided, it uses the default axis for this constraint.
+void b3Point2PointConstraint::setParam(int num, b3Scalar value, int axis)
+{
+ if(axis != -1)
+ {
+ b3AssertConstrParams(0);
+ }
+ else
+ {
+ switch(num)
+ {
+ case B3_CONSTRAINT_ERP :
+ case B3_CONSTRAINT_STOP_ERP :
+ m_erp = value;
+ m_flags |= B3_P2P_FLAGS_ERP;
+ break;
+ case B3_CONSTRAINT_CFM :
+ case B3_CONSTRAINT_STOP_CFM :
+ m_cfm = value;
+ m_flags |= B3_P2P_FLAGS_CFM;
+ break;
+ default:
+ b3AssertConstrParams(0);
+ }
+ }
+}
+
+///return the local value of parameter
+b3Scalar b3Point2PointConstraint::getParam(int num, int axis) const
+{
+ b3Scalar retVal(B3_INFINITY);
+ if(axis != -1)
+ {
+ b3AssertConstrParams(0);
+ }
+ else
+ {
+ switch(num)
+ {
+ case B3_CONSTRAINT_ERP :
+ case B3_CONSTRAINT_STOP_ERP :
+ b3AssertConstrParams(m_flags & B3_P2P_FLAGS_ERP);
+ retVal = m_erp;
+ break;
+ case B3_CONSTRAINT_CFM :
+ case B3_CONSTRAINT_STOP_CFM :
+ b3AssertConstrParams(m_flags & B3_P2P_FLAGS_CFM);
+ retVal = m_cfm;
+ break;
+ default:
+ b3AssertConstrParams(0);
+ }
+ }
+ return retVal;
+}
+
diff --git a/thirdparty/bullet/src/Bullet3Dynamics/ConstraintSolver/b3Point2PointConstraint.h b/thirdparty/bullet/src/Bullet3Dynamics/ConstraintSolver/b3Point2PointConstraint.h
new file mode 100644
index 0000000000..681b487334
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Dynamics/ConstraintSolver/b3Point2PointConstraint.h
@@ -0,0 +1,159 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef B3_POINT2POINTCONSTRAINT_H
+#define B3_POINT2POINTCONSTRAINT_H
+
+#include "Bullet3Common/b3Vector3.h"
+//#include "b3JacobianEntry.h"
+#include "b3TypedConstraint.h"
+
+class b3RigidBody;
+
+
+#ifdef B3_USE_DOUBLE_PRECISION
+#define b3Point2PointConstraintData b3Point2PointConstraintDoubleData
+#define b3Point2PointConstraintDataName "b3Point2PointConstraintDoubleData"
+#else
+#define b3Point2PointConstraintData b3Point2PointConstraintFloatData
+#define b3Point2PointConstraintDataName "b3Point2PointConstraintFloatData"
+#endif //B3_USE_DOUBLE_PRECISION
+
+struct b3ConstraintSetting
+{
+ b3ConstraintSetting() :
+ m_tau(b3Scalar(0.3)),
+ m_damping(b3Scalar(1.)),
+ m_impulseClamp(b3Scalar(0.))
+ {
+ }
+ b3Scalar m_tau;
+ b3Scalar m_damping;
+ b3Scalar m_impulseClamp;
+};
+
+enum b3Point2PointFlags
+{
+ B3_P2P_FLAGS_ERP = 1,
+ B3_P2P_FLAGS_CFM = 2
+};
+
+/// point to point constraint between two rigidbodies each with a pivotpoint that descibes the 'ballsocket' location in local space
+B3_ATTRIBUTE_ALIGNED16(class) b3Point2PointConstraint : public b3TypedConstraint
+{
+#ifdef IN_PARALLELL_SOLVER
+public:
+#endif
+
+ b3Vector3 m_pivotInA;
+ b3Vector3 m_pivotInB;
+
+ int m_flags;
+ b3Scalar m_erp;
+ b3Scalar m_cfm;
+
+public:
+
+ B3_DECLARE_ALIGNED_ALLOCATOR();
+
+ b3ConstraintSetting m_setting;
+
+ b3Point2PointConstraint(int rbA,int rbB, const b3Vector3& pivotInA,const b3Vector3& pivotInB);
+
+ //b3Point2PointConstraint(int rbA,const b3Vector3& pivotInA);
+
+
+
+ virtual void getInfo1 (b3ConstraintInfo1* info,const b3RigidBodyData* bodies);
+
+ void getInfo1NonVirtual (b3ConstraintInfo1* info,const b3RigidBodyData* bodies);
+
+ virtual void getInfo2 (b3ConstraintInfo2* info, const b3RigidBodyData* bodies);
+
+ void getInfo2NonVirtual (b3ConstraintInfo2* info, const b3Transform& body0_trans, const b3Transform& body1_trans);
+
+ void updateRHS(b3Scalar timeStep);
+
+ void setPivotA(const b3Vector3& pivotA)
+ {
+ m_pivotInA = pivotA;
+ }
+
+ void setPivotB(const b3Vector3& pivotB)
+ {
+ m_pivotInB = pivotB;
+ }
+
+ const b3Vector3& getPivotInA() const
+ {
+ return m_pivotInA;
+ }
+
+ const b3Vector3& getPivotInB() const
+ {
+ return m_pivotInB;
+ }
+
+ ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
+ ///If no axis is provided, it uses the default axis for this constraint.
+ virtual void setParam(int num, b3Scalar value, int axis = -1);
+ ///return the local value of parameter
+ virtual b3Scalar getParam(int num, int axis = -1) const;
+
+// virtual int calculateSerializeBufferSize() const;
+
+ ///fills the dataBuffer and returns the struct name (and 0 on failure)
+// virtual const char* serialize(void* dataBuffer, b3Serializer* serializer) const;
+
+
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct b3Point2PointConstraintFloatData
+{
+ b3TypedConstraintData m_typeConstraintData;
+ b3Vector3FloatData m_pivotInA;
+ b3Vector3FloatData m_pivotInB;
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct b3Point2PointConstraintDoubleData
+{
+ b3TypedConstraintData m_typeConstraintData;
+ b3Vector3DoubleData m_pivotInA;
+ b3Vector3DoubleData m_pivotInB;
+};
+
+/*
+B3_FORCE_INLINE int b3Point2PointConstraint::calculateSerializeBufferSize() const
+{
+ return sizeof(b3Point2PointConstraintData);
+
+}
+
+ ///fills the dataBuffer and returns the struct name (and 0 on failure)
+B3_FORCE_INLINE const char* b3Point2PointConstraint::serialize(void* dataBuffer, b3Serializer* serializer) const
+{
+ b3Point2PointConstraintData* p2pData = (b3Point2PointConstraintData*)dataBuffer;
+
+ b3TypedConstraint::serialize(&p2pData->m_typeConstraintData,serializer);
+ m_pivotInA.serialize(p2pData->m_pivotInA);
+ m_pivotInB.serialize(p2pData->m_pivotInB);
+
+ return b3Point2PointConstraintDataName;
+}
+*/
+
+#endif //B3_POINT2POINTCONSTRAINT_H
diff --git a/thirdparty/bullet/src/Bullet3Dynamics/ConstraintSolver/b3SolverBody.h b/thirdparty/bullet/src/Bullet3Dynamics/ConstraintSolver/b3SolverBody.h
new file mode 100644
index 0000000000..0049317d98
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Dynamics/ConstraintSolver/b3SolverBody.h
@@ -0,0 +1,302 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef B3_SOLVER_BODY_H
+#define B3_SOLVER_BODY_H
+
+
+#include "Bullet3Common/b3Vector3.h"
+#include "Bullet3Common/b3Matrix3x3.h"
+
+#include "Bullet3Common/b3AlignedAllocator.h"
+#include "Bullet3Common/b3TransformUtil.h"
+
+///Until we get other contributions, only use SIMD on Windows, when using Visual Studio 2008 or later, and not double precision
+#ifdef B3_USE_SSE
+#define USE_SIMD 1
+#endif //
+
+
+#ifdef USE_SIMD
+
+struct b3SimdScalar
+{
+ B3_FORCE_INLINE b3SimdScalar()
+ {
+
+ }
+
+ B3_FORCE_INLINE b3SimdScalar(float fl)
+ :m_vec128 (_mm_set1_ps(fl))
+ {
+ }
+
+ B3_FORCE_INLINE b3SimdScalar(__m128 v128)
+ :m_vec128(v128)
+ {
+ }
+ union
+ {
+ __m128 m_vec128;
+ float m_floats[4];
+ float x,y,z,w;
+ int m_ints[4];
+ b3Scalar m_unusedPadding;
+ };
+ B3_FORCE_INLINE __m128 get128()
+ {
+ return m_vec128;
+ }
+
+ B3_FORCE_INLINE const __m128 get128() const
+ {
+ return m_vec128;
+ }
+
+ B3_FORCE_INLINE void set128(__m128 v128)
+ {
+ m_vec128 = v128;
+ }
+
+ B3_FORCE_INLINE operator __m128()
+ {
+ return m_vec128;
+ }
+ B3_FORCE_INLINE operator const __m128() const
+ {
+ return m_vec128;
+ }
+
+ B3_FORCE_INLINE operator float() const
+ {
+ return m_floats[0];
+ }
+
+};
+
+///@brief Return the elementwise product of two b3SimdScalar
+B3_FORCE_INLINE b3SimdScalar
+operator*(const b3SimdScalar& v1, const b3SimdScalar& v2)
+{
+ return b3SimdScalar(_mm_mul_ps(v1.get128(),v2.get128()));
+}
+
+///@brief Return the elementwise product of two b3SimdScalar
+B3_FORCE_INLINE b3SimdScalar
+operator+(const b3SimdScalar& v1, const b3SimdScalar& v2)
+{
+ return b3SimdScalar(_mm_add_ps(v1.get128(),v2.get128()));
+}
+
+
+#else
+#define b3SimdScalar b3Scalar
+#endif
+
+///The b3SolverBody is an internal datastructure for the constraint solver. Only necessary data is packed to increase cache coherence/performance.
+B3_ATTRIBUTE_ALIGNED16 (struct) b3SolverBody
+{
+ B3_DECLARE_ALIGNED_ALLOCATOR();
+ b3Transform m_worldTransform;
+ b3Vector3 m_deltaLinearVelocity;
+ b3Vector3 m_deltaAngularVelocity;
+ b3Vector3 m_angularFactor;
+ b3Vector3 m_linearFactor;
+ b3Vector3 m_invMass;
+ b3Vector3 m_pushVelocity;
+ b3Vector3 m_turnVelocity;
+ b3Vector3 m_linearVelocity;
+ b3Vector3 m_angularVelocity;
+
+ union
+ {
+ void* m_originalBody;
+ int m_originalBodyIndex;
+ };
+
+ int padding[3];
+
+
+ void setWorldTransform(const b3Transform& worldTransform)
+ {
+ m_worldTransform = worldTransform;
+ }
+
+ const b3Transform& getWorldTransform() const
+ {
+ return m_worldTransform;
+ }
+
+ B3_FORCE_INLINE void getVelocityInLocalPointObsolete(const b3Vector3& rel_pos, b3Vector3& velocity ) const
+ {
+ if (m_originalBody)
+ velocity = m_linearVelocity+m_deltaLinearVelocity + (m_angularVelocity+m_deltaAngularVelocity).cross(rel_pos);
+ else
+ velocity.setValue(0,0,0);
+ }
+
+ B3_FORCE_INLINE void getAngularVelocity(b3Vector3& angVel) const
+ {
+ if (m_originalBody)
+ angVel =m_angularVelocity+m_deltaAngularVelocity;
+ else
+ angVel.setValue(0,0,0);
+ }
+
+
+ //Optimization for the iterative solver: avoid calculating constant terms involving inertia, normal, relative position
+ B3_FORCE_INLINE void applyImpulse(const b3Vector3& linearComponent, const b3Vector3& angularComponent,const b3Scalar impulseMagnitude)
+ {
+ if (m_originalBody)
+ {
+ m_deltaLinearVelocity += linearComponent*impulseMagnitude*m_linearFactor;
+ m_deltaAngularVelocity += angularComponent*(impulseMagnitude*m_angularFactor);
+ }
+ }
+
+ B3_FORCE_INLINE void internalApplyPushImpulse(const b3Vector3& linearComponent, const b3Vector3& angularComponent,b3Scalar impulseMagnitude)
+ {
+ if (m_originalBody)
+ {
+ m_pushVelocity += linearComponent*impulseMagnitude*m_linearFactor;
+ m_turnVelocity += angularComponent*(impulseMagnitude*m_angularFactor);
+ }
+ }
+
+
+
+ const b3Vector3& getDeltaLinearVelocity() const
+ {
+ return m_deltaLinearVelocity;
+ }
+
+ const b3Vector3& getDeltaAngularVelocity() const
+ {
+ return m_deltaAngularVelocity;
+ }
+
+ const b3Vector3& getPushVelocity() const
+ {
+ return m_pushVelocity;
+ }
+
+ const b3Vector3& getTurnVelocity() const
+ {
+ return m_turnVelocity;
+ }
+
+
+ ////////////////////////////////////////////////
+ ///some internal methods, don't use them
+
+ b3Vector3& internalGetDeltaLinearVelocity()
+ {
+ return m_deltaLinearVelocity;
+ }
+
+ b3Vector3& internalGetDeltaAngularVelocity()
+ {
+ return m_deltaAngularVelocity;
+ }
+
+ const b3Vector3& internalGetAngularFactor() const
+ {
+ return m_angularFactor;
+ }
+
+ const b3Vector3& internalGetInvMass() const
+ {
+ return m_invMass;
+ }
+
+ void internalSetInvMass(const b3Vector3& invMass)
+ {
+ m_invMass = invMass;
+ }
+
+ b3Vector3& internalGetPushVelocity()
+ {
+ return m_pushVelocity;
+ }
+
+ b3Vector3& internalGetTurnVelocity()
+ {
+ return m_turnVelocity;
+ }
+
+ B3_FORCE_INLINE void internalGetVelocityInLocalPointObsolete(const b3Vector3& rel_pos, b3Vector3& velocity ) const
+ {
+ velocity = m_linearVelocity+m_deltaLinearVelocity + (m_angularVelocity+m_deltaAngularVelocity).cross(rel_pos);
+ }
+
+ B3_FORCE_INLINE void internalGetAngularVelocity(b3Vector3& angVel) const
+ {
+ angVel = m_angularVelocity+m_deltaAngularVelocity;
+ }
+
+
+ //Optimization for the iterative solver: avoid calculating constant terms involving inertia, normal, relative position
+ B3_FORCE_INLINE void internalApplyImpulse(const b3Vector3& linearComponent, const b3Vector3& angularComponent,const b3Scalar impulseMagnitude)
+ {
+ //if (m_originalBody)
+ {
+ m_deltaLinearVelocity += linearComponent*impulseMagnitude*m_linearFactor;
+ m_deltaAngularVelocity += angularComponent*(impulseMagnitude*m_angularFactor);
+ }
+ }
+
+
+
+
+ void writebackVelocity()
+ {
+ //if (m_originalBody>=0)
+ {
+ m_linearVelocity +=m_deltaLinearVelocity;
+ m_angularVelocity += m_deltaAngularVelocity;
+
+ //m_originalBody->setCompanionId(-1);
+ }
+ }
+
+
+ void writebackVelocityAndTransform(b3Scalar timeStep, b3Scalar splitImpulseTurnErp)
+ {
+ (void) timeStep;
+ if (m_originalBody)
+ {
+ m_linearVelocity += m_deltaLinearVelocity;
+ m_angularVelocity += m_deltaAngularVelocity;
+
+ //correct the position/orientation based on push/turn recovery
+ b3Transform newTransform;
+ if (m_pushVelocity[0]!=0.f || m_pushVelocity[1]!=0 || m_pushVelocity[2]!=0 || m_turnVelocity[0]!=0.f || m_turnVelocity[1]!=0 || m_turnVelocity[2]!=0)
+ {
+ // b3Quaternion orn = m_worldTransform.getRotation();
+ b3TransformUtil::integrateTransform(m_worldTransform,m_pushVelocity,m_turnVelocity*splitImpulseTurnErp,timeStep,newTransform);
+ m_worldTransform = newTransform;
+ }
+ //m_worldTransform.setRotation(orn);
+ //m_originalBody->setCompanionId(-1);
+ }
+ }
+
+
+
+};
+
+#endif //B3_SOLVER_BODY_H
+
+
diff --git a/thirdparty/bullet/src/Bullet3Dynamics/ConstraintSolver/b3SolverConstraint.h b/thirdparty/bullet/src/Bullet3Dynamics/ConstraintSolver/b3SolverConstraint.h
new file mode 100644
index 0000000000..bce83d4608
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Dynamics/ConstraintSolver/b3SolverConstraint.h
@@ -0,0 +1,80 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef B3_SOLVER_CONSTRAINT_H
+#define B3_SOLVER_CONSTRAINT_H
+
+
+#include "Bullet3Common/b3Vector3.h"
+#include "Bullet3Common/b3Matrix3x3.h"
+//#include "b3JacobianEntry.h"
+#include "Bullet3Common/b3AlignedObjectArray.h"
+
+//#define NO_FRICTION_TANGENTIALS 1
+#include "b3SolverBody.h"
+
+
+///1D constraint along a normal axis between bodyA and bodyB. It can be combined to solve contact and friction constraints.
+B3_ATTRIBUTE_ALIGNED16 (struct) b3SolverConstraint
+{
+ B3_DECLARE_ALIGNED_ALLOCATOR();
+
+ b3Vector3 m_relpos1CrossNormal;
+ b3Vector3 m_contactNormal;
+
+ b3Vector3 m_relpos2CrossNormal;
+ //b3Vector3 m_contactNormal2;//usually m_contactNormal2 == -m_contactNormal
+
+ b3Vector3 m_angularComponentA;
+ b3Vector3 m_angularComponentB;
+
+ mutable b3SimdScalar m_appliedPushImpulse;
+ mutable b3SimdScalar m_appliedImpulse;
+ int m_padding1;
+ int m_padding2;
+ b3Scalar m_friction;
+ b3Scalar m_jacDiagABInv;
+ b3Scalar m_rhs;
+ b3Scalar m_cfm;
+
+ b3Scalar m_lowerLimit;
+ b3Scalar m_upperLimit;
+ b3Scalar m_rhsPenetration;
+ union
+ {
+ void* m_originalContactPoint;
+ b3Scalar m_unusedPadding4;
+ };
+
+ int m_overrideNumSolverIterations;
+ int m_frictionIndex;
+ int m_solverBodyIdA;
+ int m_solverBodyIdB;
+
+
+ enum b3SolverConstraintType
+ {
+ B3_SOLVER_CONTACT_1D = 0,
+ B3_SOLVER_FRICTION_1D
+ };
+};
+
+typedef b3AlignedObjectArray<b3SolverConstraint> b3ConstraintArray;
+
+
+#endif //B3_SOLVER_CONSTRAINT_H
+
+
+
diff --git a/thirdparty/bullet/src/Bullet3Dynamics/ConstraintSolver/b3TypedConstraint.cpp b/thirdparty/bullet/src/Bullet3Dynamics/ConstraintSolver/b3TypedConstraint.cpp
new file mode 100644
index 0000000000..699c481d64
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Dynamics/ConstraintSolver/b3TypedConstraint.cpp
@@ -0,0 +1,161 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "b3TypedConstraint.h"
+//#include "Bullet3Common/b3Serializer.h"
+
+
+#define B3_DEFAULT_DEBUGDRAW_SIZE b3Scalar(0.3f)
+
+
+
+b3TypedConstraint::b3TypedConstraint(b3TypedConstraintType type, int rbA,int rbB)
+:b3TypedObject(type),
+m_userConstraintType(-1),
+m_userConstraintPtr((void*)-1),
+m_breakingImpulseThreshold(B3_INFINITY),
+m_isEnabled(true),
+m_needsFeedback(false),
+m_overrideNumSolverIterations(-1),
+m_rbA(rbA),
+m_rbB(rbB),
+m_appliedImpulse(b3Scalar(0.)),
+m_dbgDrawSize(B3_DEFAULT_DEBUGDRAW_SIZE),
+m_jointFeedback(0)
+{
+}
+
+
+
+
+b3Scalar b3TypedConstraint::getMotorFactor(b3Scalar pos, b3Scalar lowLim, b3Scalar uppLim, b3Scalar vel, b3Scalar timeFact)
+{
+ if(lowLim > uppLim)
+ {
+ return b3Scalar(1.0f);
+ }
+ else if(lowLim == uppLim)
+ {
+ return b3Scalar(0.0f);
+ }
+ b3Scalar lim_fact = b3Scalar(1.0f);
+ b3Scalar delta_max = vel / timeFact;
+ if(delta_max < b3Scalar(0.0f))
+ {
+ if((pos >= lowLim) && (pos < (lowLim - delta_max)))
+ {
+ lim_fact = (lowLim - pos) / delta_max;
+ }
+ else if(pos < lowLim)
+ {
+ lim_fact = b3Scalar(0.0f);
+ }
+ else
+ {
+ lim_fact = b3Scalar(1.0f);
+ }
+ }
+ else if(delta_max > b3Scalar(0.0f))
+ {
+ if((pos <= uppLim) && (pos > (uppLim - delta_max)))
+ {
+ lim_fact = (uppLim - pos) / delta_max;
+ }
+ else if(pos > uppLim)
+ {
+ lim_fact = b3Scalar(0.0f);
+ }
+ else
+ {
+ lim_fact = b3Scalar(1.0f);
+ }
+ }
+ else
+ {
+ lim_fact = b3Scalar(0.0f);
+ }
+ return lim_fact;
+}
+
+
+
+void b3AngularLimit::set(b3Scalar low, b3Scalar high, b3Scalar _softness, b3Scalar _biasFactor, b3Scalar _relaxationFactor)
+{
+ m_halfRange = (high - low) / 2.0f;
+ m_center = b3NormalizeAngle(low + m_halfRange);
+ m_softness = _softness;
+ m_biasFactor = _biasFactor;
+ m_relaxationFactor = _relaxationFactor;
+}
+
+void b3AngularLimit::test(const b3Scalar angle)
+{
+ m_correction = 0.0f;
+ m_sign = 0.0f;
+ m_solveLimit = false;
+
+ if (m_halfRange >= 0.0f)
+ {
+ b3Scalar deviation = b3NormalizeAngle(angle - m_center);
+ if (deviation < -m_halfRange)
+ {
+ m_solveLimit = true;
+ m_correction = - (deviation + m_halfRange);
+ m_sign = +1.0f;
+ }
+ else if (deviation > m_halfRange)
+ {
+ m_solveLimit = true;
+ m_correction = m_halfRange - deviation;
+ m_sign = -1.0f;
+ }
+ }
+}
+
+
+b3Scalar b3AngularLimit::getError() const
+{
+ return m_correction * m_sign;
+}
+
+void b3AngularLimit::fit(b3Scalar& angle) const
+{
+ if (m_halfRange > 0.0f)
+ {
+ b3Scalar relativeAngle = b3NormalizeAngle(angle - m_center);
+ if (!b3Equal(relativeAngle, m_halfRange))
+ {
+ if (relativeAngle > 0.0f)
+ {
+ angle = getHigh();
+ }
+ else
+ {
+ angle = getLow();
+ }
+ }
+ }
+}
+
+b3Scalar b3AngularLimit::getLow() const
+{
+ return b3NormalizeAngle(m_center - m_halfRange);
+}
+
+b3Scalar b3AngularLimit::getHigh() const
+{
+ return b3NormalizeAngle(m_center + m_halfRange);
+}
diff --git a/thirdparty/bullet/src/Bullet3Dynamics/ConstraintSolver/b3TypedConstraint.h b/thirdparty/bullet/src/Bullet3Dynamics/ConstraintSolver/b3TypedConstraint.h
new file mode 100644
index 0000000000..cf9cec0d5e
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Dynamics/ConstraintSolver/b3TypedConstraint.h
@@ -0,0 +1,483 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2010 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef B3_TYPED_CONSTRAINT_H
+#define B3_TYPED_CONSTRAINT_H
+
+
+#include "Bullet3Common/b3Scalar.h"
+#include "b3SolverConstraint.h"
+
+class b3Serializer;
+
+//Don't change any of the existing enum values, so add enum types at the end for serialization compatibility
+enum b3TypedConstraintType
+{
+ B3_POINT2POINT_CONSTRAINT_TYPE=3,
+ B3_HINGE_CONSTRAINT_TYPE,
+ B3_CONETWIST_CONSTRAINT_TYPE,
+ B3_D6_CONSTRAINT_TYPE,
+ B3_SLIDER_CONSTRAINT_TYPE,
+ B3_CONTACT_CONSTRAINT_TYPE,
+ B3_D6_SPRING_CONSTRAINT_TYPE,
+ B3_GEAR_CONSTRAINT_TYPE,
+ B3_FIXED_CONSTRAINT_TYPE,
+ B3_MAX_CONSTRAINT_TYPE
+};
+
+
+enum b3ConstraintParams
+{
+ B3_CONSTRAINT_ERP=1,
+ B3_CONSTRAINT_STOP_ERP,
+ B3_CONSTRAINT_CFM,
+ B3_CONSTRAINT_STOP_CFM
+};
+
+#if 1
+ #define b3AssertConstrParams(_par) b3Assert(_par)
+#else
+ #define b3AssertConstrParams(_par)
+#endif
+
+
+B3_ATTRIBUTE_ALIGNED16(struct) b3JointFeedback
+{
+ b3Vector3 m_appliedForceBodyA;
+ b3Vector3 m_appliedTorqueBodyA;
+ b3Vector3 m_appliedForceBodyB;
+ b3Vector3 m_appliedTorqueBodyB;
+};
+
+
+struct b3RigidBodyData;
+
+
+///TypedConstraint is the baseclass for Bullet constraints and vehicles
+B3_ATTRIBUTE_ALIGNED16(class) b3TypedConstraint : public b3TypedObject
+{
+ int m_userConstraintType;
+
+ union
+ {
+ int m_userConstraintId;
+ void* m_userConstraintPtr;
+ };
+
+ b3Scalar m_breakingImpulseThreshold;
+ bool m_isEnabled;
+ bool m_needsFeedback;
+ int m_overrideNumSolverIterations;
+
+
+ b3TypedConstraint& operator=(b3TypedConstraint& other)
+ {
+ b3Assert(0);
+ (void) other;
+ return *this;
+ }
+
+protected:
+ int m_rbA;
+ int m_rbB;
+ b3Scalar m_appliedImpulse;
+ b3Scalar m_dbgDrawSize;
+ b3JointFeedback* m_jointFeedback;
+
+ ///internal method used by the constraint solver, don't use them directly
+ b3Scalar getMotorFactor(b3Scalar pos, b3Scalar lowLim, b3Scalar uppLim, b3Scalar vel, b3Scalar timeFact);
+
+
+public:
+
+ B3_DECLARE_ALIGNED_ALLOCATOR();
+
+ virtual ~b3TypedConstraint() {};
+ b3TypedConstraint(b3TypedConstraintType type, int bodyA,int bodyB);
+
+ struct b3ConstraintInfo1 {
+ int m_numConstraintRows,nub;
+ };
+
+
+
+ struct b3ConstraintInfo2 {
+ // integrator parameters: frames per second (1/stepsize), default error
+ // reduction parameter (0..1).
+ b3Scalar fps,erp;
+
+ // for the first and second body, pointers to two (linear and angular)
+ // n*3 jacobian sub matrices, stored by rows. these matrices will have
+ // been initialized to 0 on entry. if the second body is zero then the
+ // J2xx pointers may be 0.
+ b3Scalar *m_J1linearAxis,*m_J1angularAxis,*m_J2linearAxis,*m_J2angularAxis;
+
+ // elements to jump from one row to the next in J's
+ int rowskip;
+
+ // right hand sides of the equation J*v = c + cfm * lambda. cfm is the
+ // "constraint force mixing" vector. c is set to zero on entry, cfm is
+ // set to a constant value (typically very small or zero) value on entry.
+ b3Scalar *m_constraintError,*cfm;
+
+ // lo and hi limits for variables (set to -/+ infinity on entry).
+ b3Scalar *m_lowerLimit,*m_upperLimit;
+
+ // findex vector for variables. see the LCP solver interface for a
+ // description of what this does. this is set to -1 on entry.
+ // note that the returned indexes are relative to the first index of
+ // the constraint.
+ int *findex;
+ // number of solver iterations
+ int m_numIterations;
+
+ //damping of the velocity
+ b3Scalar m_damping;
+ };
+
+ int getOverrideNumSolverIterations() const
+ {
+ return m_overrideNumSolverIterations;
+ }
+
+ ///override the number of constraint solver iterations used to solve this constraint
+ ///-1 will use the default number of iterations, as specified in SolverInfo.m_numIterations
+ void setOverrideNumSolverIterations(int overideNumIterations)
+ {
+ m_overrideNumSolverIterations = overideNumIterations;
+ }
+
+
+ ///internal method used by the constraint solver, don't use them directly
+ virtual void setupSolverConstraint(b3ConstraintArray& ca, int solverBodyA,int solverBodyB, b3Scalar timeStep)
+ {
+ (void)ca;
+ (void)solverBodyA;
+ (void)solverBodyB;
+ (void)timeStep;
+ }
+
+ ///internal method used by the constraint solver, don't use them directly
+ virtual void getInfo1 (b3ConstraintInfo1* info,const b3RigidBodyData* bodies)=0;
+
+ ///internal method used by the constraint solver, don't use them directly
+ virtual void getInfo2 (b3ConstraintInfo2* info, const b3RigidBodyData* bodies)=0;
+
+ ///internal method used by the constraint solver, don't use them directly
+ void internalSetAppliedImpulse(b3Scalar appliedImpulse)
+ {
+ m_appliedImpulse = appliedImpulse;
+ }
+ ///internal method used by the constraint solver, don't use them directly
+ b3Scalar internalGetAppliedImpulse()
+ {
+ return m_appliedImpulse;
+ }
+
+
+ b3Scalar getBreakingImpulseThreshold() const
+ {
+ return m_breakingImpulseThreshold;
+ }
+
+ void setBreakingImpulseThreshold(b3Scalar threshold)
+ {
+ m_breakingImpulseThreshold = threshold;
+ }
+
+ bool isEnabled() const
+ {
+ return m_isEnabled;
+ }
+
+ void setEnabled(bool enabled)
+ {
+ m_isEnabled=enabled;
+ }
+
+
+ ///internal method used by the constraint solver, don't use them directly
+ virtual void solveConstraintObsolete(b3SolverBody& /*bodyA*/,b3SolverBody& /*bodyB*/,b3Scalar /*timeStep*/) {};
+
+
+ int getRigidBodyA() const
+ {
+ return m_rbA;
+ }
+ int getRigidBodyB() const
+ {
+ return m_rbB;
+ }
+
+
+ int getRigidBodyA()
+ {
+ return m_rbA;
+ }
+ int getRigidBodyB()
+ {
+ return m_rbB;
+ }
+
+ int getUserConstraintType() const
+ {
+ return m_userConstraintType ;
+ }
+
+ void setUserConstraintType(int userConstraintType)
+ {
+ m_userConstraintType = userConstraintType;
+ };
+
+ void setUserConstraintId(int uid)
+ {
+ m_userConstraintId = uid;
+ }
+
+ int getUserConstraintId() const
+ {
+ return m_userConstraintId;
+ }
+
+ void setUserConstraintPtr(void* ptr)
+ {
+ m_userConstraintPtr = ptr;
+ }
+
+ void* getUserConstraintPtr()
+ {
+ return m_userConstraintPtr;
+ }
+
+ void setJointFeedback(b3JointFeedback* jointFeedback)
+ {
+ m_jointFeedback = jointFeedback;
+ }
+
+ const b3JointFeedback* getJointFeedback() const
+ {
+ return m_jointFeedback;
+ }
+
+ b3JointFeedback* getJointFeedback()
+ {
+ return m_jointFeedback;
+ }
+
+
+ int getUid() const
+ {
+ return m_userConstraintId;
+ }
+
+ bool needsFeedback() const
+ {
+ return m_needsFeedback;
+ }
+
+ ///enableFeedback will allow to read the applied linear and angular impulse
+ ///use getAppliedImpulse, getAppliedLinearImpulse and getAppliedAngularImpulse to read feedback information
+ void enableFeedback(bool needsFeedback)
+ {
+ m_needsFeedback = needsFeedback;
+ }
+
+ ///getAppliedImpulse is an estimated total applied impulse.
+ ///This feedback could be used to determine breaking constraints or playing sounds.
+ b3Scalar getAppliedImpulse() const
+ {
+ b3Assert(m_needsFeedback);
+ return m_appliedImpulse;
+ }
+
+ b3TypedConstraintType getConstraintType () const
+ {
+ return b3TypedConstraintType(m_objectType);
+ }
+
+ void setDbgDrawSize(b3Scalar dbgDrawSize)
+ {
+ m_dbgDrawSize = dbgDrawSize;
+ }
+ b3Scalar getDbgDrawSize()
+ {
+ return m_dbgDrawSize;
+ }
+
+ ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
+ ///If no axis is provided, it uses the default axis for this constraint.
+ virtual void setParam(int num, b3Scalar value, int axis = -1) = 0;
+
+ ///return the local value of parameter
+ virtual b3Scalar getParam(int num, int axis = -1) const = 0;
+
+// virtual int calculateSerializeBufferSize() const;
+
+ ///fills the dataBuffer and returns the struct name (and 0 on failure)
+ //virtual const char* serialize(void* dataBuffer, b3Serializer* serializer) const;
+
+};
+
+// returns angle in range [-B3_2_PI, B3_2_PI], closest to one of the limits
+// all arguments should be normalized angles (i.e. in range [-B3_PI, B3_PI])
+B3_FORCE_INLINE b3Scalar b3AdjustAngleToLimits(b3Scalar angleInRadians, b3Scalar angleLowerLimitInRadians, b3Scalar angleUpperLimitInRadians)
+{
+ if(angleLowerLimitInRadians >= angleUpperLimitInRadians)
+ {
+ return angleInRadians;
+ }
+ else if(angleInRadians < angleLowerLimitInRadians)
+ {
+ b3Scalar diffLo = b3Fabs(b3NormalizeAngle(angleLowerLimitInRadians - angleInRadians));
+ b3Scalar diffHi = b3Fabs(b3NormalizeAngle(angleUpperLimitInRadians - angleInRadians));
+ return (diffLo < diffHi) ? angleInRadians : (angleInRadians + B3_2_PI);
+ }
+ else if(angleInRadians > angleUpperLimitInRadians)
+ {
+ b3Scalar diffHi = b3Fabs(b3NormalizeAngle(angleInRadians - angleUpperLimitInRadians));
+ b3Scalar diffLo = b3Fabs(b3NormalizeAngle(angleInRadians - angleLowerLimitInRadians));
+ return (diffLo < diffHi) ? (angleInRadians - B3_2_PI) : angleInRadians;
+ }
+ else
+ {
+ return angleInRadians;
+ }
+}
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct b3TypedConstraintData
+{
+ int m_bodyA;
+ int m_bodyB;
+ char *m_name;
+
+ int m_objectType;
+ int m_userConstraintType;
+ int m_userConstraintId;
+ int m_needsFeedback;
+
+ float m_appliedImpulse;
+ float m_dbgDrawSize;
+
+ int m_disableCollisionsBetweenLinkedBodies;
+ int m_overrideNumSolverIterations;
+
+ float m_breakingImpulseThreshold;
+ int m_isEnabled;
+
+};
+
+/*B3_FORCE_INLINE int b3TypedConstraint::calculateSerializeBufferSize() const
+{
+ return sizeof(b3TypedConstraintData);
+}
+*/
+
+
+class b3AngularLimit
+{
+private:
+ b3Scalar
+ m_center,
+ m_halfRange,
+ m_softness,
+ m_biasFactor,
+ m_relaxationFactor,
+ m_correction,
+ m_sign;
+
+ bool
+ m_solveLimit;
+
+public:
+ /// Default constructor initializes limit as inactive, allowing free constraint movement
+ b3AngularLimit()
+ :m_center(0.0f),
+ m_halfRange(-1.0f),
+ m_softness(0.9f),
+ m_biasFactor(0.3f),
+ m_relaxationFactor(1.0f),
+ m_correction(0.0f),
+ m_sign(0.0f),
+ m_solveLimit(false)
+ {}
+
+ /// Sets all limit's parameters.
+ /// When low > high limit becomes inactive.
+ /// When high - low > 2PI limit is ineffective too becouse no angle can exceed the limit
+ void set(b3Scalar low, b3Scalar high, b3Scalar _softness = 0.9f, b3Scalar _biasFactor = 0.3f, b3Scalar _relaxationFactor = 1.0f);
+
+ /// Checks conastaint angle against limit. If limit is active and the angle violates the limit
+ /// correction is calculated.
+ void test(const b3Scalar angle);
+
+ /// Returns limit's softness
+ inline b3Scalar getSoftness() const
+ {
+ return m_softness;
+ }
+
+ /// Returns limit's bias factor
+ inline b3Scalar getBiasFactor() const
+ {
+ return m_biasFactor;
+ }
+
+ /// Returns limit's relaxation factor
+ inline b3Scalar getRelaxationFactor() const
+ {
+ return m_relaxationFactor;
+ }
+
+ /// Returns correction value evaluated when test() was invoked
+ inline b3Scalar getCorrection() const
+ {
+ return m_correction;
+ }
+
+ /// Returns sign value evaluated when test() was invoked
+ inline b3Scalar getSign() const
+ {
+ return m_sign;
+ }
+
+ /// Gives half of the distance between min and max limit angle
+ inline b3Scalar getHalfRange() const
+ {
+ return m_halfRange;
+ }
+
+ /// Returns true when the last test() invocation recognized limit violation
+ inline bool isLimit() const
+ {
+ return m_solveLimit;
+ }
+
+ /// Checks given angle against limit. If limit is active and angle doesn't fit it, the angle
+ /// returned is modified so it equals to the limit closest to given angle.
+ void fit(b3Scalar& angle) const;
+
+ /// Returns correction value multiplied by sign value
+ b3Scalar getError() const;
+
+ b3Scalar getLow() const;
+
+ b3Scalar getHigh() const;
+
+};
+
+
+
+#endif //B3_TYPED_CONSTRAINT_H
diff --git a/thirdparty/bullet/src/Bullet3Dynamics/b3CpuRigidBodyPipeline.cpp b/thirdparty/bullet/src/Bullet3Dynamics/b3CpuRigidBodyPipeline.cpp
new file mode 100644
index 0000000000..fbc84cc28d
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Dynamics/b3CpuRigidBodyPipeline.cpp
@@ -0,0 +1,488 @@
+#include "b3CpuRigidBodyPipeline.h"
+
+#include "Bullet3Dynamics/shared/b3IntegrateTransforms.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
+#include "Bullet3Collision/BroadPhaseCollision/b3DynamicBvhBroadphase.h"
+#include "Bullet3Collision/NarrowPhaseCollision/b3Config.h"
+#include "Bullet3Collision/NarrowPhaseCollision/b3CpuNarrowPhase.h"
+#include "Bullet3Collision/BroadPhaseCollision/shared/b3Aabb.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h"
+#include "Bullet3Common/b3Vector3.h"
+#include "Bullet3Dynamics/shared/b3ContactConstraint4.h"
+#include "Bullet3Dynamics/shared/b3Inertia.h"
+
+
+struct b3CpuRigidBodyPipelineInternalData
+{
+ b3AlignedObjectArray<b3RigidBodyData> m_rigidBodies;
+ b3AlignedObjectArray<b3Inertia> m_inertias;
+ b3AlignedObjectArray<b3Aabb> m_aabbWorldSpace;
+
+ b3DynamicBvhBroadphase* m_bp;
+ b3CpuNarrowPhase* m_np;
+ b3Config m_config;
+};
+
+
+b3CpuRigidBodyPipeline::b3CpuRigidBodyPipeline(class b3CpuNarrowPhase* narrowphase, struct b3DynamicBvhBroadphase* broadphaseDbvt, const b3Config& config)
+{
+ m_data = new b3CpuRigidBodyPipelineInternalData;
+ m_data->m_np = narrowphase;
+ m_data->m_bp = broadphaseDbvt;
+ m_data->m_config = config;
+}
+
+b3CpuRigidBodyPipeline::~b3CpuRigidBodyPipeline()
+{
+ delete m_data;
+}
+
+void b3CpuRigidBodyPipeline::updateAabbWorldSpace()
+{
+
+ for (int i=0;i<this->getNumBodies();i++)
+ {
+ b3RigidBodyData* body = &m_data->m_rigidBodies[i];
+ b3Float4 position = body->m_pos;
+ b3Quat orientation = body->m_quat;
+
+ int collidableIndex = body->m_collidableIdx;
+ b3Collidable& collidable = m_data->m_np->getCollidableCpu(collidableIndex);
+ int shapeIndex = collidable.m_shapeIndex;
+
+ if (shapeIndex>=0)
+ {
+
+
+ b3Aabb localAabb = m_data->m_np->getLocalSpaceAabb(shapeIndex);
+ b3Aabb& worldAabb = m_data->m_aabbWorldSpace[i];
+ float margin=0.f;
+ b3TransformAabb2(localAabb.m_minVec,localAabb.m_maxVec,margin,position,orientation,&worldAabb.m_minVec,&worldAabb.m_maxVec);
+ m_data->m_bp->setAabb(i,worldAabb.m_minVec,worldAabb.m_maxVec,0);
+ }
+ }
+}
+
+void b3CpuRigidBodyPipeline::computeOverlappingPairs()
+{
+ int numPairs = m_data->m_bp->getOverlappingPairCache()->getNumOverlappingPairs();
+ m_data->m_bp->calculateOverlappingPairs();
+ numPairs = m_data->m_bp->getOverlappingPairCache()->getNumOverlappingPairs();
+ printf("numPairs=%d\n",numPairs);
+}
+
+void b3CpuRigidBodyPipeline::computeContactPoints()
+{
+
+ b3AlignedObjectArray<b3Int4>& pairs = m_data->m_bp->getOverlappingPairCache()->getOverlappingPairArray();
+
+ m_data->m_np->computeContacts(pairs,m_data->m_aabbWorldSpace, m_data->m_rigidBodies);
+
+}
+void b3CpuRigidBodyPipeline::stepSimulation(float deltaTime)
+{
+
+ //update world space aabb's
+ updateAabbWorldSpace();
+
+ //compute overlapping pairs
+ computeOverlappingPairs();
+
+ //compute contacts
+ computeContactPoints();
+
+ //solve contacts
+
+ //update transforms
+ integrate(deltaTime);
+
+
+}
+
+
+static inline float b3CalcRelVel(const b3Vector3& l0, const b3Vector3& l1, const b3Vector3& a0, const b3Vector3& a1,
+ const b3Vector3& linVel0, const b3Vector3& angVel0, const b3Vector3& linVel1, const b3Vector3& angVel1)
+{
+ return b3Dot(l0, linVel0) + b3Dot(a0, angVel0) + b3Dot(l1, linVel1) + b3Dot(a1, angVel1);
+}
+
+
+static inline void b3SetLinearAndAngular(const b3Vector3& n, const b3Vector3& r0, const b3Vector3& r1,
+ b3Vector3& linear, b3Vector3& angular0, b3Vector3& angular1)
+{
+ linear = -n;
+ angular0 = -b3Cross(r0, n);
+ angular1 = b3Cross(r1, n);
+}
+
+
+
+static inline void b3SolveContact(b3ContactConstraint4& cs,
+ const b3Vector3& posA, b3Vector3& linVelA, b3Vector3& angVelA, float invMassA, const b3Matrix3x3& invInertiaA,
+ const b3Vector3& posB, b3Vector3& linVelB, b3Vector3& angVelB, float invMassB, const b3Matrix3x3& invInertiaB,
+ float maxRambdaDt[4], float minRambdaDt[4])
+{
+
+ b3Vector3 dLinVelA; dLinVelA.setZero();
+ b3Vector3 dAngVelA; dAngVelA.setZero();
+ b3Vector3 dLinVelB; dLinVelB.setZero();
+ b3Vector3 dAngVelB; dAngVelB.setZero();
+
+ for(int ic=0; ic<4; ic++)
+ {
+ // dont necessary because this makes change to 0
+ if( cs.m_jacCoeffInv[ic] == 0.f ) continue;
+
+ {
+ b3Vector3 angular0, angular1, linear;
+ b3Vector3 r0 = cs.m_worldPos[ic] - (b3Vector3&)posA;
+ b3Vector3 r1 = cs.m_worldPos[ic] - (b3Vector3&)posB;
+ b3SetLinearAndAngular( (const b3Vector3 &)-cs.m_linear, (const b3Vector3 &)r0, (const b3Vector3 &)r1, linear, angular0, angular1 );
+
+ float rambdaDt = b3CalcRelVel((const b3Vector3 &)cs.m_linear,(const b3Vector3 &) -cs.m_linear, angular0, angular1,
+ linVelA, angVelA, linVelB, angVelB ) + cs.m_b[ic];
+ rambdaDt *= cs.m_jacCoeffInv[ic];
+
+ {
+ float prevSum = cs.m_appliedRambdaDt[ic];
+ float updated = prevSum;
+ updated += rambdaDt;
+ updated = b3Max( updated, minRambdaDt[ic] );
+ updated = b3Min( updated, maxRambdaDt[ic] );
+ rambdaDt = updated - prevSum;
+ cs.m_appliedRambdaDt[ic] = updated;
+ }
+
+ b3Vector3 linImp0 = invMassA*linear*rambdaDt;
+ b3Vector3 linImp1 = invMassB*(-linear)*rambdaDt;
+ b3Vector3 angImp0 = (invInertiaA* angular0)*rambdaDt;
+ b3Vector3 angImp1 = (invInertiaB* angular1)*rambdaDt;
+#ifdef _WIN32
+ b3Assert(_finite(linImp0.getX()));
+ b3Assert(_finite(linImp1.getX()));
+#endif
+ {
+ linVelA += linImp0;
+ angVelA += angImp0;
+ linVelB += linImp1;
+ angVelB += angImp1;
+ }
+ }
+ }
+
+
+}
+
+
+
+
+
+static inline void b3SolveFriction(b3ContactConstraint4& cs,
+ const b3Vector3& posA, b3Vector3& linVelA, b3Vector3& angVelA, float invMassA, const b3Matrix3x3& invInertiaA,
+ const b3Vector3& posB, b3Vector3& linVelB, b3Vector3& angVelB, float invMassB, const b3Matrix3x3& invInertiaB,
+ float maxRambdaDt[4], float minRambdaDt[4])
+{
+
+ if( cs.m_fJacCoeffInv[0] == 0 && cs.m_fJacCoeffInv[0] == 0 ) return;
+ const b3Vector3& center = (const b3Vector3&)cs.m_center;
+
+ b3Vector3 n = -(const b3Vector3&)cs.m_linear;
+
+ b3Vector3 tangent[2];
+
+ b3PlaneSpace1 (n, tangent[0],tangent[1]);
+
+ b3Vector3 angular0, angular1, linear;
+ b3Vector3 r0 = center - posA;
+ b3Vector3 r1 = center - posB;
+ for(int i=0; i<2; i++)
+ {
+ b3SetLinearAndAngular( tangent[i], r0, r1, linear, angular0, angular1 );
+ float rambdaDt = b3CalcRelVel(linear, -linear, angular0, angular1,
+ linVelA, angVelA, linVelB, angVelB );
+ rambdaDt *= cs.m_fJacCoeffInv[i];
+
+ {
+ float prevSum = cs.m_fAppliedRambdaDt[i];
+ float updated = prevSum;
+ updated += rambdaDt;
+ updated = b3Max( updated, minRambdaDt[i] );
+ updated = b3Min( updated, maxRambdaDt[i] );
+ rambdaDt = updated - prevSum;
+ cs.m_fAppliedRambdaDt[i] = updated;
+ }
+
+ b3Vector3 linImp0 = invMassA*linear*rambdaDt;
+ b3Vector3 linImp1 = invMassB*(-linear)*rambdaDt;
+ b3Vector3 angImp0 = (invInertiaA* angular0)*rambdaDt;
+ b3Vector3 angImp1 = (invInertiaB* angular1)*rambdaDt;
+#ifdef _WIN32
+ b3Assert(_finite(linImp0.getX()));
+ b3Assert(_finite(linImp1.getX()));
+#endif
+ linVelA += linImp0;
+ angVelA += angImp0;
+ linVelB += linImp1;
+ angVelB += angImp1;
+ }
+
+ { // angular damping for point constraint
+ b3Vector3 ab = ( posB - posA ).normalized();
+ b3Vector3 ac = ( center - posA ).normalized();
+ if( b3Dot( ab, ac ) > 0.95f || (invMassA == 0.f || invMassB == 0.f))
+ {
+ float angNA = b3Dot( n, angVelA );
+ float angNB = b3Dot( n, angVelB );
+
+ angVelA -= (angNA*0.1f)*n;
+ angVelB -= (angNB*0.1f)*n;
+ }
+ }
+
+}
+
+
+
+
+
+struct b3SolveTask// : public ThreadPool::Task
+{
+ b3SolveTask(b3AlignedObjectArray<b3RigidBodyData>& bodies,
+ b3AlignedObjectArray<b3Inertia>& shapes,
+ b3AlignedObjectArray<b3ContactConstraint4>& constraints,
+ int start, int nConstraints,
+ int maxNumBatches,
+ b3AlignedObjectArray<int>* wgUsedBodies, int curWgidx
+ )
+ : m_bodies( bodies ), m_shapes( shapes ), m_constraints( constraints ),
+ m_wgUsedBodies(wgUsedBodies),m_curWgidx(curWgidx),
+m_start( start ),
+ m_nConstraints( nConstraints ),
+ m_solveFriction( true ),
+ m_maxNumBatches(maxNumBatches)
+ {}
+
+ unsigned short int getType(){ return 0; }
+
+ void run(int tIdx)
+ {
+ b3AlignedObjectArray<int> usedBodies;
+ //printf("run..............\n");
+
+
+ for (int bb=0;bb<m_maxNumBatches;bb++)
+ {
+ usedBodies.resize(0);
+ for(int ic=m_nConstraints-1; ic>=0; ic--)
+ //for(int ic=0; ic<m_nConstraints; ic++)
+ {
+
+ int i = m_start + ic;
+ if (m_constraints[i].m_batchIdx != bb)
+ continue;
+
+ float frictionCoeff = b3GetFrictionCoeff(&m_constraints[i]);
+ int aIdx = (int)m_constraints[i].m_bodyA;
+ int bIdx = (int)m_constraints[i].m_bodyB;
+ //int localBatch = m_constraints[i].m_batchIdx;
+ b3RigidBodyData& bodyA = m_bodies[aIdx];
+ b3RigidBodyData& bodyB = m_bodies[bIdx];
+
+#if 0
+ if ((bodyA.m_invMass) && (bodyB.m_invMass))
+ {
+ // printf("aIdx=%d, bIdx=%d\n", aIdx,bIdx);
+ }
+ if (bIdx==10)
+ {
+ //printf("ic(b)=%d, localBatch=%d\n",ic,localBatch);
+ }
+#endif
+ if (aIdx==10)
+ {
+ //printf("ic(a)=%d, localBatch=%d\n",ic,localBatch);
+ }
+ if (usedBodies.size()<(aIdx+1))
+ {
+ usedBodies.resize(aIdx+1,0);
+ }
+
+ if (usedBodies.size()<(bIdx+1))
+ {
+ usedBodies.resize(bIdx+1,0);
+ }
+
+ if (bodyA.m_invMass)
+ {
+ b3Assert(usedBodies[aIdx]==0);
+ usedBodies[aIdx]++;
+ }
+
+ if (bodyB.m_invMass)
+ {
+ b3Assert(usedBodies[bIdx]==0);
+ usedBodies[bIdx]++;
+ }
+
+
+ if( !m_solveFriction )
+ {
+ float maxRambdaDt[4] = {FLT_MAX,FLT_MAX,FLT_MAX,FLT_MAX};
+ float minRambdaDt[4] = {0.f,0.f,0.f,0.f};
+
+ b3SolveContact( m_constraints[i], (b3Vector3&)bodyA.m_pos, (b3Vector3&)bodyA.m_linVel, (b3Vector3&)bodyA.m_angVel, bodyA.m_invMass, (const b3Matrix3x3 &)m_shapes[aIdx].m_invInertiaWorld,
+ (b3Vector3&)bodyB.m_pos, (b3Vector3&)bodyB.m_linVel, (b3Vector3&)bodyB.m_angVel, bodyB.m_invMass, (const b3Matrix3x3 &)m_shapes[bIdx].m_invInertiaWorld,
+ maxRambdaDt, minRambdaDt );
+
+ }
+ else
+ {
+ float maxRambdaDt[4] = {FLT_MAX,FLT_MAX,FLT_MAX,FLT_MAX};
+ float minRambdaDt[4] = {0.f,0.f,0.f,0.f};
+
+ float sum = 0;
+ for(int j=0; j<4; j++)
+ {
+ sum +=m_constraints[i].m_appliedRambdaDt[j];
+ }
+ frictionCoeff = 0.7f;
+ for(int j=0; j<4; j++)
+ {
+ maxRambdaDt[j] = frictionCoeff*sum;
+ minRambdaDt[j] = -maxRambdaDt[j];
+ }
+
+ b3SolveFriction( m_constraints[i], (b3Vector3&)bodyA.m_pos, (b3Vector3&)bodyA.m_linVel, (b3Vector3&)bodyA.m_angVel, bodyA.m_invMass,(const b3Matrix3x3 &) m_shapes[aIdx].m_invInertiaWorld,
+ (b3Vector3&)bodyB.m_pos, (b3Vector3&)bodyB.m_linVel, (b3Vector3&)bodyB.m_angVel, bodyB.m_invMass,(const b3Matrix3x3 &) m_shapes[bIdx].m_invInertiaWorld,
+ maxRambdaDt, minRambdaDt );
+
+ }
+ }
+
+ if (m_wgUsedBodies)
+ {
+ if (m_wgUsedBodies[m_curWgidx].size()<usedBodies.size())
+ {
+ m_wgUsedBodies[m_curWgidx].resize(usedBodies.size());
+ }
+ for (int i=0;i<usedBodies.size();i++)
+ {
+ if (usedBodies[i])
+ {
+ //printf("cell %d uses body %d\n", m_curWgidx,i);
+ m_wgUsedBodies[m_curWgidx][i]=1;
+ }
+ }
+ }
+
+ }
+
+
+
+ }
+
+ b3AlignedObjectArray<b3RigidBodyData>& m_bodies;
+ b3AlignedObjectArray<b3Inertia>& m_shapes;
+ b3AlignedObjectArray<b3ContactConstraint4>& m_constraints;
+ b3AlignedObjectArray<int>* m_wgUsedBodies;
+ int m_curWgidx;
+ int m_start;
+ int m_nConstraints;
+ bool m_solveFriction;
+ int m_maxNumBatches;
+};
+
+void b3CpuRigidBodyPipeline::solveContactConstraints()
+{
+ int m_nIterations = 4;
+
+ b3AlignedObjectArray<b3ContactConstraint4> contactConstraints;
+// const b3AlignedObjectArray<b3Contact4Data>& contacts = m_data->m_np->getContacts();
+ int n = contactConstraints.size();
+ //convert contacts...
+
+
+
+ int maxNumBatches = 250;
+
+ for(int iter=0; iter<m_nIterations; iter++)
+ {
+ b3SolveTask task( m_data->m_rigidBodies, m_data->m_inertias, contactConstraints, 0, n ,maxNumBatches,0,0);
+ task.m_solveFriction = false;
+ task.run(0);
+ }
+
+ for(int iter=0; iter<m_nIterations; iter++)
+ {
+ b3SolveTask task( m_data->m_rigidBodies, m_data->m_inertias, contactConstraints, 0, n ,maxNumBatches,0,0);
+ task.m_solveFriction = true;
+ task.run(0);
+ }
+}
+
+void b3CpuRigidBodyPipeline::integrate(float deltaTime)
+{
+ float angDamping=0.f;
+ b3Vector3 gravityAcceleration=b3MakeVector3(0,-9,0);
+
+ //integrate transforms (external forces/gravity should be moved into constraint solver)
+ for (int i=0;i<m_data->m_rigidBodies.size();i++)
+ {
+ b3IntegrateTransform(&m_data->m_rigidBodies[i],deltaTime,angDamping,gravityAcceleration);
+ }
+
+}
+
+int b3CpuRigidBodyPipeline::registerPhysicsInstance(float mass, const float* position, const float* orientation, int collidableIndex, int userData)
+{
+ b3RigidBodyData body;
+ int bodyIndex = m_data->m_rigidBodies.size();
+ body.m_invMass = mass ? 1.f/mass : 0.f;
+ body.m_angVel.setValue(0,0,0);
+ body.m_collidableIdx = collidableIndex;
+ body.m_frictionCoeff = 0.3f;
+ body.m_linVel.setValue(0,0,0);
+ body.m_pos.setValue(position[0],position[1],position[2]);
+ body.m_quat.setValue(orientation[0],orientation[1],orientation[2],orientation[3]);
+ body.m_restituitionCoeff = 0.f;
+
+ m_data->m_rigidBodies.push_back(body);
+
+
+ if (collidableIndex>=0)
+ {
+ b3Aabb& worldAabb = m_data->m_aabbWorldSpace.expand();
+
+ b3Aabb localAabb = m_data->m_np->getLocalSpaceAabb(collidableIndex);
+ b3Vector3 localAabbMin=b3MakeVector3(localAabb.m_min[0],localAabb.m_min[1],localAabb.m_min[2]);
+ b3Vector3 localAabbMax=b3MakeVector3(localAabb.m_max[0],localAabb.m_max[1],localAabb.m_max[2]);
+
+ b3Scalar margin = 0.01f;
+ b3Transform t;
+ t.setIdentity();
+ t.setOrigin(b3MakeVector3(position[0],position[1],position[2]));
+ t.setRotation(b3Quaternion(orientation[0],orientation[1],orientation[2],orientation[3]));
+ b3TransformAabb(localAabbMin,localAabbMax, margin,t,worldAabb.m_minVec,worldAabb.m_maxVec);
+
+ m_data->m_bp->createProxy(worldAabb.m_minVec,worldAabb.m_maxVec,bodyIndex,0,1,1);
+// b3Vector3 aabbMin,aabbMax;
+ // m_data->m_bp->getAabb(bodyIndex,aabbMin,aabbMax);
+
+ } else
+ {
+ b3Error("registerPhysicsInstance using invalid collidableIndex\n");
+ }
+
+ return bodyIndex;
+}
+
+
+const struct b3RigidBodyData* b3CpuRigidBodyPipeline::getBodyBuffer() const
+{
+ return m_data->m_rigidBodies.size() ? &m_data->m_rigidBodies[0] : 0;
+}
+
+int b3CpuRigidBodyPipeline::getNumBodies() const
+{
+ return m_data->m_rigidBodies.size();
+}
diff --git a/thirdparty/bullet/src/Bullet3Dynamics/b3CpuRigidBodyPipeline.h b/thirdparty/bullet/src/Bullet3Dynamics/b3CpuRigidBodyPipeline.h
new file mode 100644
index 0000000000..2f3c2ae77e
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Dynamics/b3CpuRigidBodyPipeline.h
@@ -0,0 +1,67 @@
+/*
+Copyright (c) 2013 Advanced Micro Devices, Inc.
+
+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.
+*/
+//Originally written by Erwin Coumans
+
+#ifndef B3_CPU_RIGIDBODY_PIPELINE_H
+#define B3_CPU_RIGIDBODY_PIPELINE_H
+
+
+
+#include "Bullet3Common/b3AlignedObjectArray.h"
+#include "Bullet3Collision/NarrowPhaseCollision/b3RaycastInfo.h"
+
+class b3CpuRigidBodyPipeline
+{
+protected:
+ struct b3CpuRigidBodyPipelineInternalData* m_data;
+
+ int allocateCollidable();
+
+public:
+
+
+ b3CpuRigidBodyPipeline(class b3CpuNarrowPhase* narrowphase, struct b3DynamicBvhBroadphase* broadphaseDbvt, const struct b3Config& config);
+ virtual ~b3CpuRigidBodyPipeline();
+
+ virtual void stepSimulation(float deltaTime);
+ virtual void integrate(float timeStep);
+ virtual void updateAabbWorldSpace();
+ virtual void computeOverlappingPairs();
+ virtual void computeContactPoints();
+ virtual void solveContactConstraints();
+
+ int registerConvexPolyhedron(class b3ConvexUtility* convex);
+
+ int registerPhysicsInstance(float mass, const float* position, const float* orientation, int collisionShapeIndex, int userData);
+ void writeAllInstancesToGpu();
+ void copyConstraintsToHost();
+ void setGravity(const float* grav);
+ void reset();
+
+ int createPoint2PointConstraint(int bodyA, int bodyB, const float* pivotInA, const float* pivotInB,float breakingThreshold);
+ int createFixedConstraint(int bodyA, int bodyB, const float* pivotInA, const float* pivotInB, const float* relTargetAB, float breakingThreshold);
+ void removeConstraintByUid(int uid);
+
+ void addConstraint(class b3TypedConstraint* constraint);
+ void removeConstraint(b3TypedConstraint* constraint);
+
+ void castRays(const b3AlignedObjectArray<b3RayInfo>& rays, b3AlignedObjectArray<b3RayHit>& hitResults);
+
+ const struct b3RigidBodyData* getBodyBuffer() const;
+
+ int getNumBodies() const;
+
+};
+
+#endif //B3_CPU_RIGIDBODY_PIPELINE_H \ No newline at end of file
diff --git a/thirdparty/bullet/src/Bullet3Dynamics/premake4.lua b/thirdparty/bullet/src/Bullet3Dynamics/premake4.lua
new file mode 100644
index 0000000000..669336a6a1
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Dynamics/premake4.lua
@@ -0,0 +1,15 @@
+ project "Bullet3Dynamics"
+
+ language "C++"
+
+ kind "StaticLib"
+
+ includedirs {
+ ".."
+ }
+
+
+ files {
+ "**.cpp",
+ "**.h"
+ } \ No newline at end of file
diff --git a/thirdparty/bullet/src/Bullet3Dynamics/shared/b3ContactConstraint4.h b/thirdparty/bullet/src/Bullet3Dynamics/shared/b3ContactConstraint4.h
new file mode 100644
index 0000000000..68cf65e312
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Dynamics/shared/b3ContactConstraint4.h
@@ -0,0 +1,34 @@
+#ifndef B3_CONTACT_CONSTRAINT5_H
+#define B3_CONTACT_CONSTRAINT5_H
+
+#include "Bullet3Common/shared/b3Float4.h"
+
+typedef struct b3ContactConstraint4 b3ContactConstraint4_t;
+
+
+struct b3ContactConstraint4
+{
+
+ b3Float4 m_linear;//normal?
+ b3Float4 m_worldPos[4];
+ b3Float4 m_center; // friction
+ float m_jacCoeffInv[4];
+ float m_b[4];
+ float m_appliedRambdaDt[4];
+ float m_fJacCoeffInv[2]; // friction
+ float m_fAppliedRambdaDt[2]; // friction
+
+ unsigned int m_bodyA;
+ unsigned int m_bodyB;
+ int m_batchIdx;
+ unsigned int m_paddings;
+
+};
+
+//inline void setFrictionCoeff(float value) { m_linear[3] = value; }
+inline float b3GetFrictionCoeff(b3ContactConstraint4_t* constraint)
+{
+ return constraint->m_linear.w;
+}
+
+#endif //B3_CONTACT_CONSTRAINT5_H
diff --git a/thirdparty/bullet/src/Bullet3Dynamics/shared/b3ConvertConstraint4.h b/thirdparty/bullet/src/Bullet3Dynamics/shared/b3ConvertConstraint4.h
new file mode 100644
index 0000000000..805a2bd3ea
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Dynamics/shared/b3ConvertConstraint4.h
@@ -0,0 +1,153 @@
+
+
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h"
+#include "Bullet3Dynamics/shared/b3ContactConstraint4.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
+
+
+void b3PlaneSpace1 (b3Float4ConstArg n, b3Float4* p, b3Float4* q);
+ void b3PlaneSpace1 (b3Float4ConstArg n, b3Float4* p, b3Float4* q)
+{
+ if (b3Fabs(n.z) > 0.70710678f) {
+ // choose p in y-z plane
+ float a = n.y*n.y + n.z*n.z;
+ float k = 1.f/sqrt(a);
+ p[0].x = 0;
+ p[0].y = -n.z*k;
+ p[0].z = n.y*k;
+ // set q = n x p
+ q[0].x = a*k;
+ q[0].y = -n.x*p[0].z;
+ q[0].z = n.x*p[0].y;
+ }
+ else {
+ // choose p in x-y plane
+ float a = n.x*n.x + n.y*n.y;
+ float k = 1.f/sqrt(a);
+ p[0].x = -n.y*k;
+ p[0].y = n.x*k;
+ p[0].z = 0;
+ // set q = n x p
+ q[0].x = -n.z*p[0].y;
+ q[0].y = n.z*p[0].x;
+ q[0].z = a*k;
+ }
+}
+
+
+
+void setLinearAndAngular( b3Float4ConstArg n, b3Float4ConstArg r0, b3Float4ConstArg r1, b3Float4* linear, b3Float4* angular0, b3Float4* angular1)
+{
+ *linear = b3MakeFloat4(n.x,n.y,n.z,0.f);
+ *angular0 = b3Cross3(r0, n);
+ *angular1 = -b3Cross3(r1, n);
+}
+
+
+float calcRelVel( b3Float4ConstArg l0, b3Float4ConstArg l1, b3Float4ConstArg a0, b3Float4ConstArg a1, b3Float4ConstArg linVel0,
+ b3Float4ConstArg angVel0, b3Float4ConstArg linVel1, b3Float4ConstArg angVel1 )
+{
+ return b3Dot3F4(l0, linVel0) + b3Dot3F4(a0, angVel0) + b3Dot3F4(l1, linVel1) + b3Dot3F4(a1, angVel1);
+}
+
+
+float calcJacCoeff(b3Float4ConstArg linear0, b3Float4ConstArg linear1, b3Float4ConstArg angular0, b3Float4ConstArg angular1,
+ float invMass0, const b3Mat3x3* invInertia0, float invMass1, const b3Mat3x3* invInertia1)
+{
+ // linear0,1 are normlized
+ float jmj0 = invMass0;//b3Dot3F4(linear0, linear0)*invMass0;
+ float jmj1 = b3Dot3F4(mtMul3(angular0,*invInertia0), angular0);
+ float jmj2 = invMass1;//b3Dot3F4(linear1, linear1)*invMass1;
+ float jmj3 = b3Dot3F4(mtMul3(angular1,*invInertia1), angular1);
+ return -1.f/(jmj0+jmj1+jmj2+jmj3);
+}
+
+
+void setConstraint4( b3Float4ConstArg posA, b3Float4ConstArg linVelA, b3Float4ConstArg angVelA, float invMassA, b3Mat3x3ConstArg invInertiaA,
+ b3Float4ConstArg posB, b3Float4ConstArg linVelB, b3Float4ConstArg angVelB, float invMassB, b3Mat3x3ConstArg invInertiaB,
+ __global struct b3Contact4Data* src, float dt, float positionDrift, float positionConstraintCoeff,
+ b3ContactConstraint4_t* dstC )
+{
+ dstC->m_bodyA = abs(src->m_bodyAPtrAndSignBit);
+ dstC->m_bodyB = abs(src->m_bodyBPtrAndSignBit);
+
+ float dtInv = 1.f/dt;
+ for(int ic=0; ic<4; ic++)
+ {
+ dstC->m_appliedRambdaDt[ic] = 0.f;
+ }
+ dstC->m_fJacCoeffInv[0] = dstC->m_fJacCoeffInv[1] = 0.f;
+
+
+ dstC->m_linear = src->m_worldNormalOnB;
+ dstC->m_linear.w = 0.7f ;//src->getFrictionCoeff() );
+ for(int ic=0; ic<4; ic++)
+ {
+ b3Float4 r0 = src->m_worldPosB[ic] - posA;
+ b3Float4 r1 = src->m_worldPosB[ic] - posB;
+
+ if( ic >= src->m_worldNormalOnB.w )//npoints
+ {
+ dstC->m_jacCoeffInv[ic] = 0.f;
+ continue;
+ }
+
+ float relVelN;
+ {
+ b3Float4 linear, angular0, angular1;
+ setLinearAndAngular(src->m_worldNormalOnB, r0, r1, &linear, &angular0, &angular1);
+
+ dstC->m_jacCoeffInv[ic] = calcJacCoeff(linear, -linear, angular0, angular1,
+ invMassA, &invInertiaA, invMassB, &invInertiaB );
+
+ relVelN = calcRelVel(linear, -linear, angular0, angular1,
+ linVelA, angVelA, linVelB, angVelB);
+
+ float e = 0.f;//src->getRestituitionCoeff();
+ if( relVelN*relVelN < 0.004f ) e = 0.f;
+
+ dstC->m_b[ic] = e*relVelN;
+ //float penetration = src->m_worldPosB[ic].w;
+ dstC->m_b[ic] += (src->m_worldPosB[ic].w + positionDrift)*positionConstraintCoeff*dtInv;
+ dstC->m_appliedRambdaDt[ic] = 0.f;
+ }
+ }
+
+ if( src->m_worldNormalOnB.w > 0 )//npoints
+ { // prepare friction
+ b3Float4 center = b3MakeFloat4(0.f,0.f,0.f,0.f);
+ for(int i=0; i<src->m_worldNormalOnB.w; i++)
+ center += src->m_worldPosB[i];
+ center /= (float)src->m_worldNormalOnB.w;
+
+ b3Float4 tangent[2];
+ b3PlaneSpace1(src->m_worldNormalOnB,&tangent[0],&tangent[1]);
+
+ b3Float4 r[2];
+ r[0] = center - posA;
+ r[1] = center - posB;
+
+ for(int i=0; i<2; i++)
+ {
+ b3Float4 linear, angular0, angular1;
+ setLinearAndAngular(tangent[i], r[0], r[1], &linear, &angular0, &angular1);
+
+ dstC->m_fJacCoeffInv[i] = calcJacCoeff(linear, -linear, angular0, angular1,
+ invMassA, &invInertiaA, invMassB, &invInertiaB );
+ dstC->m_fAppliedRambdaDt[i] = 0.f;
+ }
+ dstC->m_center = center;
+ }
+
+ for(int i=0; i<4; i++)
+ {
+ if( i<src->m_worldNormalOnB.w )
+ {
+ dstC->m_worldPos[i] = src->m_worldPosB[i];
+ }
+ else
+ {
+ dstC->m_worldPos[i] = b3MakeFloat4(0.f,0.f,0.f,0.f);
+ }
+ }
+}
diff --git a/thirdparty/bullet/src/Bullet3Dynamics/shared/b3Inertia.h b/thirdparty/bullet/src/Bullet3Dynamics/shared/b3Inertia.h
new file mode 100644
index 0000000000..96fe9f8b39
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Dynamics/shared/b3Inertia.h
@@ -0,0 +1,15 @@
+
+
+#ifndef B3_INERTIA_H
+#define B3_INERTIA_H
+
+#include "Bullet3Common/shared/b3Mat3x3.h"
+
+struct b3Inertia
+{
+ b3Mat3x3 m_invInertiaWorld;
+ b3Mat3x3 m_initInvInertia;
+};
+
+
+#endif //B3_INERTIA_H \ No newline at end of file
diff --git a/thirdparty/bullet/src/Bullet3Dynamics/shared/b3IntegrateTransforms.h b/thirdparty/bullet/src/Bullet3Dynamics/shared/b3IntegrateTransforms.h
new file mode 100644
index 0000000000..e96f90d3f3
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Dynamics/shared/b3IntegrateTransforms.h
@@ -0,0 +1,113 @@
+
+
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
+
+
+
+inline void integrateSingleTransform( __global b3RigidBodyData_t* bodies,int nodeID, float timeStep, float angularDamping, b3Float4ConstArg gravityAcceleration)
+{
+
+ if (bodies[nodeID].m_invMass != 0.f)
+ {
+ float BT_GPU_ANGULAR_MOTION_THRESHOLD = (0.25f * 3.14159254f);
+
+ //angular velocity
+ {
+ b3Float4 axis;
+ //add some hardcoded angular damping
+ bodies[nodeID].m_angVel.x *= angularDamping;
+ bodies[nodeID].m_angVel.y *= angularDamping;
+ bodies[nodeID].m_angVel.z *= angularDamping;
+
+ b3Float4 angvel = bodies[nodeID].m_angVel;
+
+ float fAngle = b3Sqrt(b3Dot3F4(angvel, angvel));
+
+ //limit the angular motion
+ if(fAngle*timeStep > BT_GPU_ANGULAR_MOTION_THRESHOLD)
+ {
+ fAngle = BT_GPU_ANGULAR_MOTION_THRESHOLD / timeStep;
+ }
+ if(fAngle < 0.001f)
+ {
+ // use Taylor's expansions of sync function
+ axis = angvel * (0.5f*timeStep-(timeStep*timeStep*timeStep)*0.020833333333f * fAngle * fAngle);
+ }
+ else
+ {
+ // sync(fAngle) = sin(c*fAngle)/t
+ axis = angvel * ( b3Sin(0.5f * fAngle * timeStep) / fAngle);
+ }
+
+ b3Quat dorn;
+ dorn.x = axis.x;
+ dorn.y = axis.y;
+ dorn.z = axis.z;
+ dorn.w = b3Cos(fAngle * timeStep * 0.5f);
+ b3Quat orn0 = bodies[nodeID].m_quat;
+ b3Quat predictedOrn = b3QuatMul(dorn, orn0);
+ predictedOrn = b3QuatNormalized(predictedOrn);
+ bodies[nodeID].m_quat=predictedOrn;
+ }
+ //linear velocity
+ bodies[nodeID].m_pos += bodies[nodeID].m_linVel * timeStep;
+
+ //apply gravity
+ bodies[nodeID].m_linVel += gravityAcceleration * timeStep;
+
+ }
+
+}
+
+inline void b3IntegrateTransform( __global b3RigidBodyData_t* body, float timeStep, float angularDamping, b3Float4ConstArg gravityAcceleration)
+{
+ float BT_GPU_ANGULAR_MOTION_THRESHOLD = (0.25f * 3.14159254f);
+
+ if( (body->m_invMass != 0.f))
+ {
+ //angular velocity
+ {
+ b3Float4 axis;
+ //add some hardcoded angular damping
+ body->m_angVel.x *= angularDamping;
+ body->m_angVel.y *= angularDamping;
+ body->m_angVel.z *= angularDamping;
+
+ b3Float4 angvel = body->m_angVel;
+ float fAngle = b3Sqrt(b3Dot3F4(angvel, angvel));
+ //limit the angular motion
+ if(fAngle*timeStep > BT_GPU_ANGULAR_MOTION_THRESHOLD)
+ {
+ fAngle = BT_GPU_ANGULAR_MOTION_THRESHOLD / timeStep;
+ }
+ if(fAngle < 0.001f)
+ {
+ // use Taylor's expansions of sync function
+ axis = angvel * (0.5f*timeStep-(timeStep*timeStep*timeStep)*0.020833333333f * fAngle * fAngle);
+ }
+ else
+ {
+ // sync(fAngle) = sin(c*fAngle)/t
+ axis = angvel * ( b3Sin(0.5f * fAngle * timeStep) / fAngle);
+ }
+ b3Quat dorn;
+ dorn.x = axis.x;
+ dorn.y = axis.y;
+ dorn.z = axis.z;
+ dorn.w = b3Cos(fAngle * timeStep * 0.5f);
+ b3Quat orn0 = body->m_quat;
+
+ b3Quat predictedOrn = b3QuatMul(dorn, orn0);
+ predictedOrn = b3QuatNormalized(predictedOrn);
+ body->m_quat=predictedOrn;
+ }
+
+ //apply gravity
+ body->m_linVel += gravityAcceleration * timeStep;
+
+ //linear velocity
+ body->m_pos += body->m_linVel * timeStep;
+
+ }
+
+}
diff --git a/thirdparty/bullet/src/Bullet3Geometry/CMakeLists.txt b/thirdparty/bullet/src/Bullet3Geometry/CMakeLists.txt
new file mode 100644
index 0000000000..8206872705
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Geometry/CMakeLists.txt
@@ -0,0 +1,47 @@
+
+INCLUDE_DIRECTORIES(
+ ${BULLET_PHYSICS_SOURCE_DIR}/src
+)
+
+SET(Bullet3Geometry_SRCS
+ b3ConvexHullComputer.cpp
+ b3GeometryUtil.cpp
+)
+
+SET(Bullet3Geometry_HDRS
+ b3AabbUtil.h
+ b3ConvexHullComputer.h
+ b3GeometryUtil.h
+ b3GrahamScan2dConvexHull.h
+)
+
+ADD_LIBRARY(Bullet3Geometry ${Bullet3Geometry_SRCS} ${Bullet3Geometry_HDRS})
+if (BUILD_SHARED_LIBS)
+ target_link_libraries(Bullet3Geometry Bullet3Common)
+endif()
+SET_TARGET_PROPERTIES(Bullet3Geometry PROPERTIES VERSION ${BULLET_VERSION})
+SET_TARGET_PROPERTIES(Bullet3Geometry PROPERTIES SOVERSION ${BULLET_VERSION})
+
+IF (INSTALL_LIBS)
+ IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
+ #FILES_MATCHING requires CMake 2.6
+ IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
+ IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+ INSTALL(TARGETS Bullet3Geometry DESTINATION .)
+ ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+ INSTALL(TARGETS Bullet3Geometry
+ RUNTIME DESTINATION bin
+ LIBRARY DESTINATION lib${LIB_SUFFIX}
+ ARCHIVE DESTINATION lib${LIB_SUFFIX})
+ INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.h" PATTERN
+".svn" EXCLUDE PATTERN "CMakeFiles" EXCLUDE)
+ ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+ ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
+
+ IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+ SET_TARGET_PROPERTIES(Bullet3Geometry PROPERTIES FRAMEWORK true)
+ SET_TARGET_PROPERTIES(Bullet3Geometry PROPERTIES PUBLIC_HEADER "${Bullet3Geometry_HDRS}")
+ ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+ ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
+ENDIF (INSTALL_LIBS)
diff --git a/thirdparty/bullet/src/Bullet3Geometry/b3AabbUtil.h b/thirdparty/bullet/src/Bullet3Geometry/b3AabbUtil.h
new file mode 100644
index 0000000000..4c72d5bbfc
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Geometry/b3AabbUtil.h
@@ -0,0 +1,232 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+#ifndef B3_AABB_UTIL2
+#define B3_AABB_UTIL2
+
+#include "Bullet3Common/b3Transform.h"
+#include "Bullet3Common/b3Vector3.h"
+#include "Bullet3Common/b3MinMax.h"
+
+
+
+B3_FORCE_INLINE void b3AabbExpand (b3Vector3& aabbMin,
+ b3Vector3& aabbMax,
+ const b3Vector3& expansionMin,
+ const b3Vector3& expansionMax)
+{
+ aabbMin = aabbMin + expansionMin;
+ aabbMax = aabbMax + expansionMax;
+}
+
+/// conservative test for overlap between two aabbs
+B3_FORCE_INLINE bool b3TestPointAgainstAabb2(const b3Vector3 &aabbMin1, const b3Vector3 &aabbMax1,
+ const b3Vector3 &point)
+{
+ bool overlap = true;
+ overlap = (aabbMin1.getX() > point.getX() || aabbMax1.getX() < point.getX()) ? false : overlap;
+ overlap = (aabbMin1.getZ() > point.getZ() || aabbMax1.getZ() < point.getZ()) ? false : overlap;
+ overlap = (aabbMin1.getY() > point.getY() || aabbMax1.getY() < point.getY()) ? false : overlap;
+ return overlap;
+}
+
+
+/// conservative test for overlap between two aabbs
+B3_FORCE_INLINE bool b3TestAabbAgainstAabb2(const b3Vector3 &aabbMin1, const b3Vector3 &aabbMax1,
+ const b3Vector3 &aabbMin2, const b3Vector3 &aabbMax2)
+{
+ bool overlap = true;
+ overlap = (aabbMin1.getX() > aabbMax2.getX() || aabbMax1.getX() < aabbMin2.getX()) ? false : overlap;
+ overlap = (aabbMin1.getZ() > aabbMax2.getZ() || aabbMax1.getZ() < aabbMin2.getZ()) ? false : overlap;
+ overlap = (aabbMin1.getY() > aabbMax2.getY() || aabbMax1.getY() < aabbMin2.getY()) ? false : overlap;
+ return overlap;
+}
+
+/// conservative test for overlap between triangle and aabb
+B3_FORCE_INLINE bool b3TestTriangleAgainstAabb2(const b3Vector3 *vertices,
+ const b3Vector3 &aabbMin, const b3Vector3 &aabbMax)
+{
+ const b3Vector3 &p1 = vertices[0];
+ const b3Vector3 &p2 = vertices[1];
+ const b3Vector3 &p3 = vertices[2];
+
+ if (b3Min(b3Min(p1[0], p2[0]), p3[0]) > aabbMax[0]) return false;
+ if (b3Max(b3Max(p1[0], p2[0]), p3[0]) < aabbMin[0]) return false;
+
+ if (b3Min(b3Min(p1[2], p2[2]), p3[2]) > aabbMax[2]) return false;
+ if (b3Max(b3Max(p1[2], p2[2]), p3[2]) < aabbMin[2]) return false;
+
+ if (b3Min(b3Min(p1[1], p2[1]), p3[1]) > aabbMax[1]) return false;
+ if (b3Max(b3Max(p1[1], p2[1]), p3[1]) < aabbMin[1]) return false;
+ return true;
+}
+
+
+B3_FORCE_INLINE int b3Outcode(const b3Vector3& p,const b3Vector3& halfExtent)
+{
+ return (p.getX() < -halfExtent.getX() ? 0x01 : 0x0) |
+ (p.getX() > halfExtent.getX() ? 0x08 : 0x0) |
+ (p.getY() < -halfExtent.getY() ? 0x02 : 0x0) |
+ (p.getY() > halfExtent.getY() ? 0x10 : 0x0) |
+ (p.getZ() < -halfExtent.getZ() ? 0x4 : 0x0) |
+ (p.getZ() > halfExtent.getZ() ? 0x20 : 0x0);
+}
+
+
+
+B3_FORCE_INLINE bool b3RayAabb2(const b3Vector3& rayFrom,
+ const b3Vector3& rayInvDirection,
+ const unsigned int raySign[3],
+ const b3Vector3 bounds[2],
+ b3Scalar& tmin,
+ b3Scalar lambda_min,
+ b3Scalar lambda_max)
+{
+ b3Scalar tmax, tymin, tymax, tzmin, tzmax;
+ tmin = (bounds[raySign[0]].getX() - rayFrom.getX()) * rayInvDirection.getX();
+ tmax = (bounds[1-raySign[0]].getX() - rayFrom.getX()) * rayInvDirection.getX();
+ tymin = (bounds[raySign[1]].getY() - rayFrom.getY()) * rayInvDirection.getY();
+ tymax = (bounds[1-raySign[1]].getY() - rayFrom.getY()) * rayInvDirection.getY();
+
+ if ( (tmin > tymax) || (tymin > tmax) )
+ return false;
+
+ if (tymin > tmin)
+ tmin = tymin;
+
+ if (tymax < tmax)
+ tmax = tymax;
+
+ tzmin = (bounds[raySign[2]].getZ() - rayFrom.getZ()) * rayInvDirection.getZ();
+ tzmax = (bounds[1-raySign[2]].getZ() - rayFrom.getZ()) * rayInvDirection.getZ();
+
+ if ( (tmin > tzmax) || (tzmin > tmax) )
+ return false;
+ if (tzmin > tmin)
+ tmin = tzmin;
+ if (tzmax < tmax)
+ tmax = tzmax;
+ return ( (tmin < lambda_max) && (tmax > lambda_min) );
+}
+
+B3_FORCE_INLINE bool b3RayAabb(const b3Vector3& rayFrom,
+ const b3Vector3& rayTo,
+ const b3Vector3& aabbMin,
+ const b3Vector3& aabbMax,
+ b3Scalar& param, b3Vector3& normal)
+{
+ b3Vector3 aabbHalfExtent = (aabbMax-aabbMin)* b3Scalar(0.5);
+ b3Vector3 aabbCenter = (aabbMax+aabbMin)* b3Scalar(0.5);
+ b3Vector3 source = rayFrom - aabbCenter;
+ b3Vector3 target = rayTo - aabbCenter;
+ int sourceOutcode = b3Outcode(source,aabbHalfExtent);
+ int targetOutcode = b3Outcode(target,aabbHalfExtent);
+ if ((sourceOutcode & targetOutcode) == 0x0)
+ {
+ b3Scalar lambda_enter = b3Scalar(0.0);
+ b3Scalar lambda_exit = param;
+ b3Vector3 r = target - source;
+ int i;
+ b3Scalar normSign = 1;
+ b3Vector3 hitNormal = b3MakeVector3(0,0,0);
+ int bit=1;
+
+ for (int j=0;j<2;j++)
+ {
+ for (i = 0; i != 3; ++i)
+ {
+ if (sourceOutcode & bit)
+ {
+ b3Scalar lambda = (-source[i] - aabbHalfExtent[i]*normSign) / r[i];
+ if (lambda_enter <= lambda)
+ {
+ lambda_enter = lambda;
+ hitNormal.setValue(0,0,0);
+ hitNormal[i] = normSign;
+ }
+ }
+ else if (targetOutcode & bit)
+ {
+ b3Scalar lambda = (-source[i] - aabbHalfExtent[i]*normSign) / r[i];
+ b3SetMin(lambda_exit, lambda);
+ }
+ bit<<=1;
+ }
+ normSign = b3Scalar(-1.);
+ }
+ if (lambda_enter <= lambda_exit)
+ {
+ param = lambda_enter;
+ normal = hitNormal;
+ return true;
+ }
+ }
+ return false;
+}
+
+
+
+B3_FORCE_INLINE void b3TransformAabb(const b3Vector3& halfExtents, b3Scalar margin,const b3Transform& t,b3Vector3& aabbMinOut,b3Vector3& aabbMaxOut)
+{
+ b3Vector3 halfExtentsWithMargin = halfExtents+b3MakeVector3(margin,margin,margin);
+ b3Matrix3x3 abs_b = t.getBasis().absolute();
+ b3Vector3 center = t.getOrigin();
+ b3Vector3 extent = halfExtentsWithMargin.dot3( abs_b[0], abs_b[1], abs_b[2] );
+ aabbMinOut = center - extent;
+ aabbMaxOut = center + extent;
+}
+
+
+B3_FORCE_INLINE void b3TransformAabb(const b3Vector3& localAabbMin,const b3Vector3& localAabbMax, b3Scalar margin,const b3Transform& trans,b3Vector3& aabbMinOut,b3Vector3& aabbMaxOut)
+{
+ //b3Assert(localAabbMin.getX() <= localAabbMax.getX());
+ //b3Assert(localAabbMin.getY() <= localAabbMax.getY());
+ //b3Assert(localAabbMin.getZ() <= localAabbMax.getZ());
+ b3Vector3 localHalfExtents = b3Scalar(0.5)*(localAabbMax-localAabbMin);
+ localHalfExtents+=b3MakeVector3(margin,margin,margin);
+
+ b3Vector3 localCenter = b3Scalar(0.5)*(localAabbMax+localAabbMin);
+ b3Matrix3x3 abs_b = trans.getBasis().absolute();
+ b3Vector3 center = trans(localCenter);
+ b3Vector3 extent = localHalfExtents.dot3( abs_b[0], abs_b[1], abs_b[2] );
+ aabbMinOut = center-extent;
+ aabbMaxOut = center+extent;
+}
+
+#define B3_USE_BANCHLESS 1
+#ifdef B3_USE_BANCHLESS
+ //This block replaces the block below and uses no branches, and replaces the 8 bit return with a 32 bit return for improved performance (~3x on XBox 360)
+ B3_FORCE_INLINE unsigned b3TestQuantizedAabbAgainstQuantizedAabb(const unsigned short int* aabbMin1,const unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2)
+ {
+ return static_cast<unsigned int>(b3Select((unsigned)((aabbMin1[0] <= aabbMax2[0]) & (aabbMax1[0] >= aabbMin2[0])
+ & (aabbMin1[2] <= aabbMax2[2]) & (aabbMax1[2] >= aabbMin2[2])
+ & (aabbMin1[1] <= aabbMax2[1]) & (aabbMax1[1] >= aabbMin2[1])),
+ 1, 0));
+ }
+#else
+ B3_FORCE_INLINE bool b3TestQuantizedAabbAgainstQuantizedAabb(const unsigned short int* aabbMin1,const unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2)
+ {
+ bool overlap = true;
+ overlap = (aabbMin1[0] > aabbMax2[0] || aabbMax1[0] < aabbMin2[0]) ? false : overlap;
+ overlap = (aabbMin1[2] > aabbMax2[2] || aabbMax1[2] < aabbMin2[2]) ? false : overlap;
+ overlap = (aabbMin1[1] > aabbMax2[1] || aabbMax1[1] < aabbMin2[1]) ? false : overlap;
+ return overlap;
+ }
+#endif //B3_USE_BANCHLESS
+
+#endif //B3_AABB_UTIL2
+
+
diff --git a/thirdparty/bullet/src/Bullet3Geometry/b3ConvexHullComputer.cpp b/thirdparty/bullet/src/Bullet3Geometry/b3ConvexHullComputer.cpp
new file mode 100644
index 0000000000..18835c38d5
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Geometry/b3ConvexHullComputer.cpp
@@ -0,0 +1,2755 @@
+/*
+Copyright (c) 2011 Ole Kniemeyer, MAXON, www.maxon.net
+
+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 <string.h>
+
+#include "b3ConvexHullComputer.h"
+#include "Bullet3Common/b3AlignedObjectArray.h"
+#include "Bullet3Common/b3MinMax.h"
+#include "Bullet3Common/b3Vector3.h"
+
+#ifdef __GNUC__
+ #include <stdint.h>
+ typedef int32_t btInt32_t;
+ typedef int64_t btInt64_t;
+ typedef uint32_t btUint32_t;
+ typedef uint64_t btUint64_t;
+#elif defined(_MSC_VER)
+ typedef __int32 btInt32_t;
+ typedef __int64 btInt64_t;
+ typedef unsigned __int32 btUint32_t;
+ typedef unsigned __int64 btUint64_t;
+#else
+ typedef int btInt32_t;
+ typedef long long int btInt64_t;
+ typedef unsigned int btUint32_t;
+ typedef unsigned long long int btUint64_t;
+#endif
+
+
+//The definition of USE_X86_64_ASM is moved into the build system. You can enable it manually by commenting out the following lines
+//#if (defined(__GNUC__) && defined(__x86_64__) && !defined(__ICL)) // || (defined(__ICL) && defined(_M_X64)) bug in Intel compiler, disable inline assembly
+// #define USE_X86_64_ASM
+//#endif
+
+
+//#define DEBUG_CONVEX_HULL
+//#define SHOW_ITERATIONS
+
+#if defined(DEBUG_CONVEX_HULL) || defined(SHOW_ITERATIONS)
+ #include <stdio.h>
+#endif
+
+// Convex hull implementation based on Preparata and Hong
+// Ole Kniemeyer, MAXON Computer GmbH
+class b3ConvexHullInternal
+{
+ public:
+
+ class Point64
+ {
+ public:
+ btInt64_t x;
+ btInt64_t y;
+ btInt64_t z;
+
+ Point64(btInt64_t x, btInt64_t y, btInt64_t z): x(x), y(y), z(z)
+ {
+ }
+
+ bool isZero()
+ {
+ return (x == 0) && (y == 0) && (z == 0);
+ }
+
+ btInt64_t dot(const Point64& b) const
+ {
+ return x * b.x + y * b.y + z * b.z;
+ }
+ };
+
+ class Point32
+ {
+ public:
+ btInt32_t x;
+ btInt32_t y;
+ btInt32_t z;
+ int index;
+
+ Point32()
+ {
+ }
+
+ Point32(btInt32_t x, btInt32_t y, btInt32_t z): x(x), y(y), z(z), index(-1)
+ {
+ }
+
+ bool operator==(const Point32& b) const
+ {
+ return (x == b.x) && (y == b.y) && (z == b.z);
+ }
+
+ bool operator!=(const Point32& b) const
+ {
+ return (x != b.x) || (y != b.y) || (z != b.z);
+ }
+
+ bool isZero()
+ {
+ return (x == 0) && (y == 0) && (z == 0);
+ }
+
+ Point64 cross(const Point32& b) const
+ {
+ return Point64(y * b.z - z * b.y, z * b.x - x * b.z, x * b.y - y * b.x);
+ }
+
+ Point64 cross(const Point64& b) const
+ {
+ return Point64(y * b.z - z * b.y, z * b.x - x * b.z, x * b.y - y * b.x);
+ }
+
+ btInt64_t dot(const Point32& b) const
+ {
+ return x * b.x + y * b.y + z * b.z;
+ }
+
+ btInt64_t dot(const Point64& b) const
+ {
+ return x * b.x + y * b.y + z * b.z;
+ }
+
+ Point32 operator+(const Point32& b) const
+ {
+ return Point32(x + b.x, y + b.y, z + b.z);
+ }
+
+ Point32 operator-(const Point32& b) const
+ {
+ return Point32(x - b.x, y - b.y, z - b.z);
+ }
+ };
+
+ class Int128
+ {
+ public:
+ btUint64_t low;
+ btUint64_t high;
+
+ Int128()
+ {
+ }
+
+ Int128(btUint64_t low, btUint64_t high): low(low), high(high)
+ {
+ }
+
+ Int128(btUint64_t low): low(low), high(0)
+ {
+ }
+
+ Int128(btInt64_t value): low(value), high((value >= 0) ? 0 : (btUint64_t) -1LL)
+ {
+ }
+
+ static Int128 mul(btInt64_t a, btInt64_t b);
+
+ static Int128 mul(btUint64_t a, btUint64_t b);
+
+ Int128 operator-() const
+ {
+ return Int128((btUint64_t) -(btInt64_t)low, ~high + (low == 0));
+ }
+
+ Int128 operator+(const Int128& b) const
+ {
+#ifdef USE_X86_64_ASM
+ Int128 result;
+ __asm__ ("addq %[bl], %[rl]\n\t"
+ "adcq %[bh], %[rh]\n\t"
+ : [rl] "=r" (result.low), [rh] "=r" (result.high)
+ : "0"(low), "1"(high), [bl] "g"(b.low), [bh] "g"(b.high)
+ : "cc" );
+ return result;
+#else
+ btUint64_t lo = low + b.low;
+ return Int128(lo, high + b.high + (lo < low));
+#endif
+ }
+
+ Int128 operator-(const Int128& b) const
+ {
+#ifdef USE_X86_64_ASM
+ Int128 result;
+ __asm__ ("subq %[bl], %[rl]\n\t"
+ "sbbq %[bh], %[rh]\n\t"
+ : [rl] "=r" (result.low), [rh] "=r" (result.high)
+ : "0"(low), "1"(high), [bl] "g"(b.low), [bh] "g"(b.high)
+ : "cc" );
+ return result;
+#else
+ return *this + -b;
+#endif
+ }
+
+ Int128& operator+=(const Int128& b)
+ {
+#ifdef USE_X86_64_ASM
+ __asm__ ("addq %[bl], %[rl]\n\t"
+ "adcq %[bh], %[rh]\n\t"
+ : [rl] "=r" (low), [rh] "=r" (high)
+ : "0"(low), "1"(high), [bl] "g"(b.low), [bh] "g"(b.high)
+ : "cc" );
+#else
+ btUint64_t lo = low + b.low;
+ if (lo < low)
+ {
+ ++high;
+ }
+ low = lo;
+ high += b.high;
+#endif
+ return *this;
+ }
+
+ Int128& operator++()
+ {
+ if (++low == 0)
+ {
+ ++high;
+ }
+ return *this;
+ }
+
+ Int128 operator*(btInt64_t b) const;
+
+ b3Scalar toScalar() const
+ {
+ return ((btInt64_t) high >= 0) ? b3Scalar(high) * (b3Scalar(0x100000000LL) * b3Scalar(0x100000000LL)) + b3Scalar(low)
+ : -(-*this).toScalar();
+ }
+
+ int getSign() const
+ {
+ return ((btInt64_t) high < 0) ? -1 : (high || low) ? 1 : 0;
+ }
+
+ bool operator<(const Int128& b) const
+ {
+ return (high < b.high) || ((high == b.high) && (low < b.low));
+ }
+
+ int ucmp(const Int128&b) const
+ {
+ if (high < b.high)
+ {
+ return -1;
+ }
+ if (high > b.high)
+ {
+ return 1;
+ }
+ if (low < b.low)
+ {
+ return -1;
+ }
+ if (low > b.low)
+ {
+ return 1;
+ }
+ return 0;
+ }
+ };
+
+
+ class Rational64
+ {
+ private:
+ btUint64_t m_numerator;
+ btUint64_t m_denominator;
+ int sign;
+
+ public:
+ Rational64(btInt64_t numerator, btInt64_t denominator)
+ {
+ if (numerator > 0)
+ {
+ sign = 1;
+ m_numerator = (btUint64_t) numerator;
+ }
+ else if (numerator < 0)
+ {
+ sign = -1;
+ m_numerator = (btUint64_t) -numerator;
+ }
+ else
+ {
+ sign = 0;
+ m_numerator = 0;
+ }
+ if (denominator > 0)
+ {
+ m_denominator = (btUint64_t) denominator;
+ }
+ else if (denominator < 0)
+ {
+ sign = -sign;
+ m_denominator = (btUint64_t) -denominator;
+ }
+ else
+ {
+ m_denominator = 0;
+ }
+ }
+
+ bool isNegativeInfinity() const
+ {
+ return (sign < 0) && (m_denominator == 0);
+ }
+
+ bool isNaN() const
+ {
+ return (sign == 0) && (m_denominator == 0);
+ }
+
+ int compare(const Rational64& b) const;
+
+ b3Scalar toScalar() const
+ {
+ return sign * ((m_denominator == 0) ? B3_INFINITY : (b3Scalar) m_numerator / m_denominator);
+ }
+ };
+
+
+ class Rational128
+ {
+ private:
+ Int128 numerator;
+ Int128 denominator;
+ int sign;
+ bool isInt64;
+
+ public:
+ Rational128(btInt64_t value)
+ {
+ if (value > 0)
+ {
+ sign = 1;
+ this->numerator = value;
+ }
+ else if (value < 0)
+ {
+ sign = -1;
+ this->numerator = -value;
+ }
+ else
+ {
+ sign = 0;
+ this->numerator = (btUint64_t) 0;
+ }
+ this->denominator = (btUint64_t) 1;
+ isInt64 = true;
+ }
+
+ Rational128(const Int128& numerator, const Int128& denominator)
+ {
+ sign = numerator.getSign();
+ if (sign >= 0)
+ {
+ this->numerator = numerator;
+ }
+ else
+ {
+ this->numerator = -numerator;
+ }
+ int dsign = denominator.getSign();
+ if (dsign >= 0)
+ {
+ this->denominator = denominator;
+ }
+ else
+ {
+ sign = -sign;
+ this->denominator = -denominator;
+ }
+ isInt64 = false;
+ }
+
+ int compare(const Rational128& b) const;
+
+ int compare(btInt64_t b) const;
+
+ b3Scalar toScalar() const
+ {
+ return sign * ((denominator.getSign() == 0) ? B3_INFINITY : numerator.toScalar() / denominator.toScalar());
+ }
+ };
+
+ class PointR128
+ {
+ public:
+ Int128 x;
+ Int128 y;
+ Int128 z;
+ Int128 denominator;
+
+ PointR128()
+ {
+ }
+
+ PointR128(Int128 x, Int128 y, Int128 z, Int128 denominator): x(x), y(y), z(z), denominator(denominator)
+ {
+ }
+
+ b3Scalar xvalue() const
+ {
+ return x.toScalar() / denominator.toScalar();
+ }
+
+ b3Scalar yvalue() const
+ {
+ return y.toScalar() / denominator.toScalar();
+ }
+
+ b3Scalar zvalue() const
+ {
+ return z.toScalar() / denominator.toScalar();
+ }
+ };
+
+
+ class Edge;
+ class Face;
+
+ class Vertex
+ {
+ public:
+ Vertex* next;
+ Vertex* prev;
+ Edge* edges;
+ Face* firstNearbyFace;
+ Face* lastNearbyFace;
+ PointR128 point128;
+ Point32 point;
+ int copy;
+
+ Vertex(): next(NULL), prev(NULL), edges(NULL), firstNearbyFace(NULL), lastNearbyFace(NULL), copy(-1)
+ {
+ }
+
+#ifdef DEBUG_CONVEX_HULL
+ void print()
+ {
+ b3Printf("V%d (%d, %d, %d)", point.index, point.x, point.y, point.z);
+ }
+
+ void printGraph();
+#endif
+
+ Point32 operator-(const Vertex& b) const
+ {
+ return point - b.point;
+ }
+
+ Rational128 dot(const Point64& b) const
+ {
+ return (point.index >= 0) ? Rational128(point.dot(b))
+ : Rational128(point128.x * b.x + point128.y * b.y + point128.z * b.z, point128.denominator);
+ }
+
+ b3Scalar xvalue() const
+ {
+ return (point.index >= 0) ? b3Scalar(point.x) : point128.xvalue();
+ }
+
+ b3Scalar yvalue() const
+ {
+ return (point.index >= 0) ? b3Scalar(point.y) : point128.yvalue();
+ }
+
+ b3Scalar zvalue() const
+ {
+ return (point.index >= 0) ? b3Scalar(point.z) : point128.zvalue();
+ }
+
+ void receiveNearbyFaces(Vertex* src)
+ {
+ if (lastNearbyFace)
+ {
+ lastNearbyFace->nextWithSameNearbyVertex = src->firstNearbyFace;
+ }
+ else
+ {
+ firstNearbyFace = src->firstNearbyFace;
+ }
+ if (src->lastNearbyFace)
+ {
+ lastNearbyFace = src->lastNearbyFace;
+ }
+ for (Face* f = src->firstNearbyFace; f; f = f->nextWithSameNearbyVertex)
+ {
+ b3Assert(f->nearbyVertex == src);
+ f->nearbyVertex = this;
+ }
+ src->firstNearbyFace = NULL;
+ src->lastNearbyFace = NULL;
+ }
+ };
+
+
+ class Edge
+ {
+ public:
+ Edge* next;
+ Edge* prev;
+ Edge* reverse;
+ Vertex* target;
+ Face* face;
+ int copy;
+
+ ~Edge()
+ {
+ next = NULL;
+ prev = NULL;
+ reverse = NULL;
+ target = NULL;
+ face = NULL;
+ }
+
+ void link(Edge* n)
+ {
+ b3Assert(reverse->target == n->reverse->target);
+ next = n;
+ n->prev = this;
+ }
+
+#ifdef DEBUG_CONVEX_HULL
+ void print()
+ {
+ b3Printf("E%p : %d -> %d, n=%p p=%p (0 %d\t%d\t%d) -> (%d %d %d)", this, reverse->target->point.index, target->point.index, next, prev,
+ reverse->target->point.x, reverse->target->point.y, reverse->target->point.z, target->point.x, target->point.y, target->point.z);
+ }
+#endif
+ };
+
+ class Face
+ {
+ public:
+ Face* next;
+ Vertex* nearbyVertex;
+ Face* nextWithSameNearbyVertex;
+ Point32 origin;
+ Point32 dir0;
+ Point32 dir1;
+
+ Face(): next(NULL), nearbyVertex(NULL), nextWithSameNearbyVertex(NULL)
+ {
+ }
+
+ void init(Vertex* a, Vertex* b, Vertex* c)
+ {
+ nearbyVertex = a;
+ origin = a->point;
+ dir0 = *b - *a;
+ dir1 = *c - *a;
+ if (a->lastNearbyFace)
+ {
+ a->lastNearbyFace->nextWithSameNearbyVertex = this;
+ }
+ else
+ {
+ a->firstNearbyFace = this;
+ }
+ a->lastNearbyFace = this;
+ }
+
+ Point64 getNormal()
+ {
+ return dir0.cross(dir1);
+ }
+ };
+
+ template<typename UWord, typename UHWord> class DMul
+ {
+ private:
+ static btUint32_t high(btUint64_t value)
+ {
+ return (btUint32_t) (value >> 32);
+ }
+
+ static btUint32_t low(btUint64_t value)
+ {
+ return (btUint32_t) value;
+ }
+
+ static btUint64_t mul(btUint32_t a, btUint32_t b)
+ {
+ return (btUint64_t) a * (btUint64_t) b;
+ }
+
+ static void shlHalf(btUint64_t& value)
+ {
+ value <<= 32;
+ }
+
+ static btUint64_t high(Int128 value)
+ {
+ return value.high;
+ }
+
+ static btUint64_t low(Int128 value)
+ {
+ return value.low;
+ }
+
+ static Int128 mul(btUint64_t a, btUint64_t b)
+ {
+ return Int128::mul(a, b);
+ }
+
+ static void shlHalf(Int128& value)
+ {
+ value.high = value.low;
+ value.low = 0;
+ }
+
+ public:
+
+ static void mul(UWord a, UWord b, UWord& resLow, UWord& resHigh)
+ {
+ UWord p00 = mul(low(a), low(b));
+ UWord p01 = mul(low(a), high(b));
+ UWord p10 = mul(high(a), low(b));
+ UWord p11 = mul(high(a), high(b));
+ UWord p0110 = UWord(low(p01)) + UWord(low(p10));
+ p11 += high(p01);
+ p11 += high(p10);
+ p11 += high(p0110);
+ shlHalf(p0110);
+ p00 += p0110;
+ if (p00 < p0110)
+ {
+ ++p11;
+ }
+ resLow = p00;
+ resHigh = p11;
+ }
+ };
+
+ private:
+
+ class IntermediateHull
+ {
+ public:
+ Vertex* minXy;
+ Vertex* maxXy;
+ Vertex* minYx;
+ Vertex* maxYx;
+
+ IntermediateHull(): minXy(NULL), maxXy(NULL), minYx(NULL), maxYx(NULL)
+ {
+ }
+
+ void print();
+ };
+
+ enum Orientation {NONE, CLOCKWISE, COUNTER_CLOCKWISE};
+
+ template <typename T> class PoolArray
+ {
+ private:
+ T* array;
+ int size;
+
+ public:
+ PoolArray<T>* next;
+
+ PoolArray(int size): size(size), next(NULL)
+ {
+ array = (T*) b3AlignedAlloc(sizeof(T) * size, 16);
+ }
+
+ ~PoolArray()
+ {
+ b3AlignedFree(array);
+ }
+
+ T* init()
+ {
+ T* o = array;
+ for (int i = 0; i < size; i++, o++)
+ {
+ o->next = (i+1 < size) ? o + 1 : NULL;
+ }
+ return array;
+ }
+ };
+
+ template <typename T> class Pool
+ {
+ private:
+ PoolArray<T>* arrays;
+ PoolArray<T>* nextArray;
+ T* freeObjects;
+ int arraySize;
+
+ public:
+ Pool(): arrays(NULL), nextArray(NULL), freeObjects(NULL), arraySize(256)
+ {
+ }
+
+ ~Pool()
+ {
+ while (arrays)
+ {
+ PoolArray<T>* p = arrays;
+ arrays = p->next;
+ p->~PoolArray<T>();
+ b3AlignedFree(p);
+ }
+ }
+
+ void reset()
+ {
+ nextArray = arrays;
+ freeObjects = NULL;
+ }
+
+ void setArraySize(int arraySize)
+ {
+ this->arraySize = arraySize;
+ }
+
+ T* newObject()
+ {
+ T* o = freeObjects;
+ if (!o)
+ {
+ PoolArray<T>* p = nextArray;
+ if (p)
+ {
+ nextArray = p->next;
+ }
+ else
+ {
+ p = new(b3AlignedAlloc(sizeof(PoolArray<T>), 16)) PoolArray<T>(arraySize);
+ p->next = arrays;
+ arrays = p;
+ }
+ o = p->init();
+ }
+ freeObjects = o->next;
+ return new(o) T();
+ };
+
+ void freeObject(T* object)
+ {
+ object->~T();
+ object->next = freeObjects;
+ freeObjects = object;
+ }
+ };
+
+ b3Vector3 scaling;
+ b3Vector3 center;
+ Pool<Vertex> vertexPool;
+ Pool<Edge> edgePool;
+ Pool<Face> facePool;
+ b3AlignedObjectArray<Vertex*> originalVertices;
+ int mergeStamp;
+ int minAxis;
+ int medAxis;
+ int maxAxis;
+ int usedEdgePairs;
+ int maxUsedEdgePairs;
+
+ static Orientation getOrientation(const Edge* prev, const Edge* next, const Point32& s, const Point32& t);
+ Edge* findMaxAngle(bool ccw, const Vertex* start, const Point32& s, const Point64& rxs, const Point64& sxrxs, Rational64& minCot);
+ void findEdgeForCoplanarFaces(Vertex* c0, Vertex* c1, Edge*& e0, Edge*& e1, Vertex* stop0, Vertex* stop1);
+
+ Edge* newEdgePair(Vertex* from, Vertex* to);
+
+ void removeEdgePair(Edge* edge)
+ {
+ Edge* n = edge->next;
+ Edge* r = edge->reverse;
+
+ b3Assert(edge->target && r->target);
+
+ if (n != edge)
+ {
+ n->prev = edge->prev;
+ edge->prev->next = n;
+ r->target->edges = n;
+ }
+ else
+ {
+ r->target->edges = NULL;
+ }
+
+ n = r->next;
+
+ if (n != r)
+ {
+ n->prev = r->prev;
+ r->prev->next = n;
+ edge->target->edges = n;
+ }
+ else
+ {
+ edge->target->edges = NULL;
+ }
+
+ edgePool.freeObject(edge);
+ edgePool.freeObject(r);
+ usedEdgePairs--;
+ }
+
+ void computeInternal(int start, int end, IntermediateHull& result);
+
+ bool mergeProjection(IntermediateHull& h0, IntermediateHull& h1, Vertex*& c0, Vertex*& c1);
+
+ void merge(IntermediateHull& h0, IntermediateHull& h1);
+
+ b3Vector3 toBtVector(const Point32& v);
+
+ b3Vector3 getBtNormal(Face* face);
+
+ bool shiftFace(Face* face, b3Scalar amount, b3AlignedObjectArray<Vertex*> stack);
+
+ public:
+ Vertex* vertexList;
+
+ void compute(const void* coords, bool doubleCoords, int stride, int count);
+
+ b3Vector3 getCoordinates(const Vertex* v);
+
+ b3Scalar shrink(b3Scalar amount, b3Scalar clampAmount);
+};
+
+
+b3ConvexHullInternal::Int128 b3ConvexHullInternal::Int128::operator*(btInt64_t b) const
+{
+ bool negative = (btInt64_t) high < 0;
+ Int128 a = negative ? -*this : *this;
+ if (b < 0)
+ {
+ negative = !negative;
+ b = -b;
+ }
+ Int128 result = mul(a.low, (btUint64_t) b);
+ result.high += a.high * (btUint64_t) b;
+ return negative ? -result : result;
+}
+
+b3ConvexHullInternal::Int128 b3ConvexHullInternal::Int128::mul(btInt64_t a, btInt64_t b)
+{
+ Int128 result;
+
+#ifdef USE_X86_64_ASM
+ __asm__ ("imulq %[b]"
+ : "=a" (result.low), "=d" (result.high)
+ : "0"(a), [b] "r"(b)
+ : "cc" );
+ return result;
+
+#else
+ bool negative = a < 0;
+ if (negative)
+ {
+ a = -a;
+ }
+ if (b < 0)
+ {
+ negative = !negative;
+ b = -b;
+ }
+ DMul<btUint64_t, btUint32_t>::mul((btUint64_t) a, (btUint64_t) b, result.low, result.high);
+ return negative ? -result : result;
+#endif
+}
+
+b3ConvexHullInternal::Int128 b3ConvexHullInternal::Int128::mul(btUint64_t a, btUint64_t b)
+{
+ Int128 result;
+
+#ifdef USE_X86_64_ASM
+ __asm__ ("mulq %[b]"
+ : "=a" (result.low), "=d" (result.high)
+ : "0"(a), [b] "r"(b)
+ : "cc" );
+
+#else
+ DMul<btUint64_t, btUint32_t>::mul(a, b, result.low, result.high);
+#endif
+
+ return result;
+}
+
+int b3ConvexHullInternal::Rational64::compare(const Rational64& b) const
+{
+ if (sign != b.sign)
+ {
+ return sign - b.sign;
+ }
+ else if (sign == 0)
+ {
+ return 0;
+ }
+
+ // return (numerator * b.denominator > b.numerator * denominator) ? sign : (numerator * b.denominator < b.numerator * denominator) ? -sign : 0;
+
+#ifdef USE_X86_64_ASM
+
+ int result;
+ btInt64_t tmp;
+ btInt64_t dummy;
+ __asm__ ("mulq %[bn]\n\t"
+ "movq %%rax, %[tmp]\n\t"
+ "movq %%rdx, %%rbx\n\t"
+ "movq %[tn], %%rax\n\t"
+ "mulq %[bd]\n\t"
+ "subq %[tmp], %%rax\n\t"
+ "sbbq %%rbx, %%rdx\n\t" // rdx:rax contains 128-bit-difference "numerator*b.denominator - b.numerator*denominator"
+ "setnsb %%bh\n\t" // bh=1 if difference is non-negative, bh=0 otherwise
+ "orq %%rdx, %%rax\n\t"
+ "setnzb %%bl\n\t" // bl=1 if difference if non-zero, bl=0 if it is zero
+ "decb %%bh\n\t" // now bx=0x0000 if difference is zero, 0xff01 if it is negative, 0x0001 if it is positive (i.e., same sign as difference)
+ "shll $16, %%ebx\n\t" // ebx has same sign as difference
+ : "=&b"(result), [tmp] "=&r"(tmp), "=a"(dummy)
+ : "a"(denominator), [bn] "g"(b.numerator), [tn] "g"(numerator), [bd] "g"(b.denominator)
+ : "%rdx", "cc" );
+ return result ? result ^ sign // if sign is +1, only bit 0 of result is inverted, which does not change the sign of result (and cannot result in zero)
+ // if sign is -1, all bits of result are inverted, which changes the sign of result (and again cannot result in zero)
+ : 0;
+
+#else
+
+ return sign * Int128::mul(m_numerator, b.m_denominator).ucmp(Int128::mul(m_denominator, b.m_numerator));
+
+#endif
+}
+
+int b3ConvexHullInternal::Rational128::compare(const Rational128& b) const
+{
+ if (sign != b.sign)
+ {
+ return sign - b.sign;
+ }
+ else if (sign == 0)
+ {
+ return 0;
+ }
+ if (isInt64)
+ {
+ return -b.compare(sign * (btInt64_t) numerator.low);
+ }
+
+ Int128 nbdLow, nbdHigh, dbnLow, dbnHigh;
+ DMul<Int128, btUint64_t>::mul(numerator, b.denominator, nbdLow, nbdHigh);
+ DMul<Int128, btUint64_t>::mul(denominator, b.numerator, dbnLow, dbnHigh);
+
+ int cmp = nbdHigh.ucmp(dbnHigh);
+ if (cmp)
+ {
+ return cmp * sign;
+ }
+ return nbdLow.ucmp(dbnLow) * sign;
+}
+
+int b3ConvexHullInternal::Rational128::compare(btInt64_t b) const
+{
+ if (isInt64)
+ {
+ btInt64_t a = sign * (btInt64_t) numerator.low;
+ return (a > b) ? 1 : (a < b) ? -1 : 0;
+ }
+ if (b > 0)
+ {
+ if (sign <= 0)
+ {
+ return -1;
+ }
+ }
+ else if (b < 0)
+ {
+ if (sign >= 0)
+ {
+ return 1;
+ }
+ b = -b;
+ }
+ else
+ {
+ return sign;
+ }
+
+ return numerator.ucmp(denominator * b) * sign;
+}
+
+
+b3ConvexHullInternal::Edge* b3ConvexHullInternal::newEdgePair(Vertex* from, Vertex* to)
+{
+ b3Assert(from && to);
+ Edge* e = edgePool.newObject();
+ Edge* r = edgePool.newObject();
+ e->reverse = r;
+ r->reverse = e;
+ e->copy = mergeStamp;
+ r->copy = mergeStamp;
+ e->target = to;
+ r->target = from;
+ e->face = NULL;
+ r->face = NULL;
+ usedEdgePairs++;
+ if (usedEdgePairs > maxUsedEdgePairs)
+ {
+ maxUsedEdgePairs = usedEdgePairs;
+ }
+ return e;
+}
+
+bool b3ConvexHullInternal::mergeProjection(IntermediateHull& h0, IntermediateHull& h1, Vertex*& c0, Vertex*& c1)
+{
+ Vertex* v0 = h0.maxYx;
+ Vertex* v1 = h1.minYx;
+ if ((v0->point.x == v1->point.x) && (v0->point.y == v1->point.y))
+ {
+ b3Assert(v0->point.z < v1->point.z);
+ Vertex* v1p = v1->prev;
+ if (v1p == v1)
+ {
+ c0 = v0;
+ if (v1->edges)
+ {
+ b3Assert(v1->edges->next == v1->edges);
+ v1 = v1->edges->target;
+ b3Assert(v1->edges->next == v1->edges);
+ }
+ c1 = v1;
+ return false;
+ }
+ Vertex* v1n = v1->next;
+ v1p->next = v1n;
+ v1n->prev = v1p;
+ if (v1 == h1.minXy)
+ {
+ if ((v1n->point.x < v1p->point.x) || ((v1n->point.x == v1p->point.x) && (v1n->point.y < v1p->point.y)))
+ {
+ h1.minXy = v1n;
+ }
+ else
+ {
+ h1.minXy = v1p;
+ }
+ }
+ if (v1 == h1.maxXy)
+ {
+ if ((v1n->point.x > v1p->point.x) || ((v1n->point.x == v1p->point.x) && (v1n->point.y > v1p->point.y)))
+ {
+ h1.maxXy = v1n;
+ }
+ else
+ {
+ h1.maxXy = v1p;
+ }
+ }
+ }
+
+ v0 = h0.maxXy;
+ v1 = h1.maxXy;
+ Vertex* v00 = NULL;
+ Vertex* v10 = NULL;
+ btInt32_t sign = 1;
+
+ for (int side = 0; side <= 1; side++)
+ {
+ btInt32_t dx = (v1->point.x - v0->point.x) * sign;
+ if (dx > 0)
+ {
+ while (true)
+ {
+ btInt32_t dy = v1->point.y - v0->point.y;
+
+ Vertex* w0 = side ? v0->next : v0->prev;
+ if (w0 != v0)
+ {
+ btInt32_t dx0 = (w0->point.x - v0->point.x) * sign;
+ btInt32_t dy0 = w0->point.y - v0->point.y;
+ if ((dy0 <= 0) && ((dx0 == 0) || ((dx0 < 0) && (dy0 * dx <= dy * dx0))))
+ {
+ v0 = w0;
+ dx = (v1->point.x - v0->point.x) * sign;
+ continue;
+ }
+ }
+
+ Vertex* w1 = side ? v1->next : v1->prev;
+ if (w1 != v1)
+ {
+ btInt32_t dx1 = (w1->point.x - v1->point.x) * sign;
+ btInt32_t dy1 = w1->point.y - v1->point.y;
+ btInt32_t dxn = (w1->point.x - v0->point.x) * sign;
+ if ((dxn > 0) && (dy1 < 0) && ((dx1 == 0) || ((dx1 < 0) && (dy1 * dx < dy * dx1))))
+ {
+ v1 = w1;
+ dx = dxn;
+ continue;
+ }
+ }
+
+ break;
+ }
+ }
+ else if (dx < 0)
+ {
+ while (true)
+ {
+ btInt32_t dy = v1->point.y - v0->point.y;
+
+ Vertex* w1 = side ? v1->prev : v1->next;
+ if (w1 != v1)
+ {
+ btInt32_t dx1 = (w1->point.x - v1->point.x) * sign;
+ btInt32_t dy1 = w1->point.y - v1->point.y;
+ if ((dy1 >= 0) && ((dx1 == 0) || ((dx1 < 0) && (dy1 * dx <= dy * dx1))))
+ {
+ v1 = w1;
+ dx = (v1->point.x - v0->point.x) * sign;
+ continue;
+ }
+ }
+
+ Vertex* w0 = side ? v0->prev : v0->next;
+ if (w0 != v0)
+ {
+ btInt32_t dx0 = (w0->point.x - v0->point.x) * sign;
+ btInt32_t dy0 = w0->point.y - v0->point.y;
+ btInt32_t dxn = (v1->point.x - w0->point.x) * sign;
+ if ((dxn < 0) && (dy0 > 0) && ((dx0 == 0) || ((dx0 < 0) && (dy0 * dx < dy * dx0))))
+ {
+ v0 = w0;
+ dx = dxn;
+ continue;
+ }
+ }
+
+ break;
+ }
+ }
+ else
+ {
+ btInt32_t x = v0->point.x;
+ btInt32_t y0 = v0->point.y;
+ Vertex* w0 = v0;
+ Vertex* t;
+ while (((t = side ? w0->next : w0->prev) != v0) && (t->point.x == x) && (t->point.y <= y0))
+ {
+ w0 = t;
+ y0 = t->point.y;
+ }
+ v0 = w0;
+
+ btInt32_t y1 = v1->point.y;
+ Vertex* w1 = v1;
+ while (((t = side ? w1->prev : w1->next) != v1) && (t->point.x == x) && (t->point.y >= y1))
+ {
+ w1 = t;
+ y1 = t->point.y;
+ }
+ v1 = w1;
+ }
+
+ if (side == 0)
+ {
+ v00 = v0;
+ v10 = v1;
+
+ v0 = h0.minXy;
+ v1 = h1.minXy;
+ sign = -1;
+ }
+ }
+
+ v0->prev = v1;
+ v1->next = v0;
+
+ v00->next = v10;
+ v10->prev = v00;
+
+ if (h1.minXy->point.x < h0.minXy->point.x)
+ {
+ h0.minXy = h1.minXy;
+ }
+ if (h1.maxXy->point.x >= h0.maxXy->point.x)
+ {
+ h0.maxXy = h1.maxXy;
+ }
+
+ h0.maxYx = h1.maxYx;
+
+ c0 = v00;
+ c1 = v10;
+
+ return true;
+}
+
+void b3ConvexHullInternal::computeInternal(int start, int end, IntermediateHull& result)
+{
+ int n = end - start;
+ switch (n)
+ {
+ case 0:
+ result.minXy = NULL;
+ result.maxXy = NULL;
+ result.minYx = NULL;
+ result.maxYx = NULL;
+ return;
+ case 2:
+ {
+ Vertex* v = originalVertices[start];
+ Vertex* w = v + 1;
+ if (v->point != w->point)
+ {
+ btInt32_t dx = v->point.x - w->point.x;
+ btInt32_t dy = v->point.y - w->point.y;
+
+ if ((dx == 0) && (dy == 0))
+ {
+ if (v->point.z > w->point.z)
+ {
+ Vertex* t = w;
+ w = v;
+ v = t;
+ }
+ b3Assert(v->point.z < w->point.z);
+ v->next = v;
+ v->prev = v;
+ result.minXy = v;
+ result.maxXy = v;
+ result.minYx = v;
+ result.maxYx = v;
+ }
+ else
+ {
+ v->next = w;
+ v->prev = w;
+ w->next = v;
+ w->prev = v;
+
+ if ((dx < 0) || ((dx == 0) && (dy < 0)))
+ {
+ result.minXy = v;
+ result.maxXy = w;
+ }
+ else
+ {
+ result.minXy = w;
+ result.maxXy = v;
+ }
+
+ if ((dy < 0) || ((dy == 0) && (dx < 0)))
+ {
+ result.minYx = v;
+ result.maxYx = w;
+ }
+ else
+ {
+ result.minYx = w;
+ result.maxYx = v;
+ }
+ }
+
+ Edge* e = newEdgePair(v, w);
+ e->link(e);
+ v->edges = e;
+
+ e = e->reverse;
+ e->link(e);
+ w->edges = e;
+
+ return;
+ }
+ }
+ // lint -fallthrough
+ case 1:
+ {
+ Vertex* v = originalVertices[start];
+ v->edges = NULL;
+ v->next = v;
+ v->prev = v;
+
+ result.minXy = v;
+ result.maxXy = v;
+ result.minYx = v;
+ result.maxYx = v;
+
+ return;
+ }
+ }
+
+ int split0 = start + n / 2;
+ Point32 p = originalVertices[split0-1]->point;
+ int split1 = split0;
+ while ((split1 < end) && (originalVertices[split1]->point == p))
+ {
+ split1++;
+ }
+ computeInternal(start, split0, result);
+ IntermediateHull hull1;
+ computeInternal(split1, end, hull1);
+#ifdef DEBUG_CONVEX_HULL
+ b3Printf("\n\nMerge\n");
+ result.print();
+ hull1.print();
+#endif
+ merge(result, hull1);
+#ifdef DEBUG_CONVEX_HULL
+ b3Printf("\n Result\n");
+ result.print();
+#endif
+}
+
+#ifdef DEBUG_CONVEX_HULL
+void b3ConvexHullInternal::IntermediateHull::print()
+{
+ b3Printf(" Hull\n");
+ for (Vertex* v = minXy; v; )
+ {
+ b3Printf(" ");
+ v->print();
+ if (v == maxXy)
+ {
+ b3Printf(" maxXy");
+ }
+ if (v == minYx)
+ {
+ b3Printf(" minYx");
+ }
+ if (v == maxYx)
+ {
+ b3Printf(" maxYx");
+ }
+ if (v->next->prev != v)
+ {
+ b3Printf(" Inconsistency");
+ }
+ b3Printf("\n");
+ v = v->next;
+ if (v == minXy)
+ {
+ break;
+ }
+ }
+ if (minXy)
+ {
+ minXy->copy = (minXy->copy == -1) ? -2 : -1;
+ minXy->printGraph();
+ }
+}
+
+void b3ConvexHullInternal::Vertex::printGraph()
+{
+ print();
+ b3Printf("\nEdges\n");
+ Edge* e = edges;
+ if (e)
+ {
+ do
+ {
+ e->print();
+ b3Printf("\n");
+ e = e->next;
+ } while (e != edges);
+ do
+ {
+ Vertex* v = e->target;
+ if (v->copy != copy)
+ {
+ v->copy = copy;
+ v->printGraph();
+ }
+ e = e->next;
+ } while (e != edges);
+ }
+}
+#endif
+
+b3ConvexHullInternal::Orientation b3ConvexHullInternal::getOrientation(const Edge* prev, const Edge* next, const Point32& s, const Point32& t)
+{
+ b3Assert(prev->reverse->target == next->reverse->target);
+ if (prev->next == next)
+ {
+ if (prev->prev == next)
+ {
+ Point64 n = t.cross(s);
+ Point64 m = (*prev->target - *next->reverse->target).cross(*next->target - *next->reverse->target);
+ b3Assert(!m.isZero());
+ btInt64_t dot = n.dot(m);
+ b3Assert(dot != 0);
+ return (dot > 0) ? COUNTER_CLOCKWISE : CLOCKWISE;
+ }
+ return COUNTER_CLOCKWISE;
+ }
+ else if (prev->prev == next)
+ {
+ return CLOCKWISE;
+ }
+ else
+ {
+ return NONE;
+ }
+}
+
+b3ConvexHullInternal::Edge* b3ConvexHullInternal::findMaxAngle(bool ccw, const Vertex* start, const Point32& s, const Point64& rxs, const Point64& sxrxs, Rational64& minCot)
+{
+ Edge* minEdge = NULL;
+
+#ifdef DEBUG_CONVEX_HULL
+ b3Printf("find max edge for %d\n", start->point.index);
+#endif
+ Edge* e = start->edges;
+ if (e)
+ {
+ do
+ {
+ if (e->copy > mergeStamp)
+ {
+ Point32 t = *e->target - *start;
+ Rational64 cot(t.dot(sxrxs), t.dot(rxs));
+#ifdef DEBUG_CONVEX_HULL
+ b3Printf(" Angle is %f (%d) for ", (float) b3Atan(cot.toScalar()), (int) cot.isNaN());
+ e->print();
+#endif
+ if (cot.isNaN())
+ {
+ b3Assert(ccw ? (t.dot(s) < 0) : (t.dot(s) > 0));
+ }
+ else
+ {
+ int cmp;
+ if (minEdge == NULL)
+ {
+ minCot = cot;
+ minEdge = e;
+ }
+ else if ((cmp = cot.compare(minCot)) < 0)
+ {
+ minCot = cot;
+ minEdge = e;
+ }
+ else if ((cmp == 0) && (ccw == (getOrientation(minEdge, e, s, t) == COUNTER_CLOCKWISE)))
+ {
+ minEdge = e;
+ }
+ }
+#ifdef DEBUG_CONVEX_HULL
+ b3Printf("\n");
+#endif
+ }
+ e = e->next;
+ } while (e != start->edges);
+ }
+ return minEdge;
+}
+
+void b3ConvexHullInternal::findEdgeForCoplanarFaces(Vertex* c0, Vertex* c1, Edge*& e0, Edge*& e1, Vertex* stop0, Vertex* stop1)
+{
+ Edge* start0 = e0;
+ Edge* start1 = e1;
+ Point32 et0 = start0 ? start0->target->point : c0->point;
+ Point32 et1 = start1 ? start1->target->point : c1->point;
+ Point32 s = c1->point - c0->point;
+ Point64 normal = ((start0 ? start0 : start1)->target->point - c0->point).cross(s);
+ btInt64_t dist = c0->point.dot(normal);
+ b3Assert(!start1 || (start1->target->point.dot(normal) == dist));
+ Point64 perp = s.cross(normal);
+ b3Assert(!perp.isZero());
+
+#ifdef DEBUG_CONVEX_HULL
+ b3Printf(" Advancing %d %d (%p %p, %d %d)\n", c0->point.index, c1->point.index, start0, start1, start0 ? start0->target->point.index : -1, start1 ? start1->target->point.index : -1);
+#endif
+
+ btInt64_t maxDot0 = et0.dot(perp);
+ if (e0)
+ {
+ while (e0->target != stop0)
+ {
+ Edge* e = e0->reverse->prev;
+ if (e->target->point.dot(normal) < dist)
+ {
+ break;
+ }
+ b3Assert(e->target->point.dot(normal) == dist);
+ if (e->copy == mergeStamp)
+ {
+ break;
+ }
+ btInt64_t dot = e->target->point.dot(perp);
+ if (dot <= maxDot0)
+ {
+ break;
+ }
+ maxDot0 = dot;
+ e0 = e;
+ et0 = e->target->point;
+ }
+ }
+
+ btInt64_t maxDot1 = et1.dot(perp);
+ if (e1)
+ {
+ while (e1->target != stop1)
+ {
+ Edge* e = e1->reverse->next;
+ if (e->target->point.dot(normal) < dist)
+ {
+ break;
+ }
+ b3Assert(e->target->point.dot(normal) == dist);
+ if (e->copy == mergeStamp)
+ {
+ break;
+ }
+ btInt64_t dot = e->target->point.dot(perp);
+ if (dot <= maxDot1)
+ {
+ break;
+ }
+ maxDot1 = dot;
+ e1 = e;
+ et1 = e->target->point;
+ }
+ }
+
+#ifdef DEBUG_CONVEX_HULL
+ b3Printf(" Starting at %d %d\n", et0.index, et1.index);
+#endif
+
+ btInt64_t dx = maxDot1 - maxDot0;
+ if (dx > 0)
+ {
+ while (true)
+ {
+ btInt64_t dy = (et1 - et0).dot(s);
+
+ if (e0 && (e0->target != stop0))
+ {
+ Edge* f0 = e0->next->reverse;
+ if (f0->copy > mergeStamp)
+ {
+ btInt64_t dx0 = (f0->target->point - et0).dot(perp);
+ btInt64_t dy0 = (f0->target->point - et0).dot(s);
+ if ((dx0 == 0) ? (dy0 < 0) : ((dx0 < 0) && (Rational64(dy0, dx0).compare(Rational64(dy, dx)) >= 0)))
+ {
+ et0 = f0->target->point;
+ dx = (et1 - et0).dot(perp);
+ e0 = (e0 == start0) ? NULL : f0;
+ continue;
+ }
+ }
+ }
+
+ if (e1 && (e1->target != stop1))
+ {
+ Edge* f1 = e1->reverse->next;
+ if (f1->copy > mergeStamp)
+ {
+ Point32 d1 = f1->target->point - et1;
+ if (d1.dot(normal) == 0)
+ {
+ btInt64_t dx1 = d1.dot(perp);
+ btInt64_t dy1 = d1.dot(s);
+ btInt64_t dxn = (f1->target->point - et0).dot(perp);
+ if ((dxn > 0) && ((dx1 == 0) ? (dy1 < 0) : ((dx1 < 0) && (Rational64(dy1, dx1).compare(Rational64(dy, dx)) > 0))))
+ {
+ e1 = f1;
+ et1 = e1->target->point;
+ dx = dxn;
+ continue;
+ }
+ }
+ else
+ {
+ b3Assert((e1 == start1) && (d1.dot(normal) < 0));
+ }
+ }
+ }
+
+ break;
+ }
+ }
+ else if (dx < 0)
+ {
+ while (true)
+ {
+ btInt64_t dy = (et1 - et0).dot(s);
+
+ if (e1 && (e1->target != stop1))
+ {
+ Edge* f1 = e1->prev->reverse;
+ if (f1->copy > mergeStamp)
+ {
+ btInt64_t dx1 = (f1->target->point - et1).dot(perp);
+ btInt64_t dy1 = (f1->target->point - et1).dot(s);
+ if ((dx1 == 0) ? (dy1 > 0) : ((dx1 < 0) && (Rational64(dy1, dx1).compare(Rational64(dy, dx)) <= 0)))
+ {
+ et1 = f1->target->point;
+ dx = (et1 - et0).dot(perp);
+ e1 = (e1 == start1) ? NULL : f1;
+ continue;
+ }
+ }
+ }
+
+ if (e0 && (e0->target != stop0))
+ {
+ Edge* f0 = e0->reverse->prev;
+ if (f0->copy > mergeStamp)
+ {
+ Point32 d0 = f0->target->point - et0;
+ if (d0.dot(normal) == 0)
+ {
+ btInt64_t dx0 = d0.dot(perp);
+ btInt64_t dy0 = d0.dot(s);
+ btInt64_t dxn = (et1 - f0->target->point).dot(perp);
+ if ((dxn < 0) && ((dx0 == 0) ? (dy0 > 0) : ((dx0 < 0) && (Rational64(dy0, dx0).compare(Rational64(dy, dx)) < 0))))
+ {
+ e0 = f0;
+ et0 = e0->target->point;
+ dx = dxn;
+ continue;
+ }
+ }
+ else
+ {
+ b3Assert((e0 == start0) && (d0.dot(normal) < 0));
+ }
+ }
+ }
+
+ break;
+ }
+ }
+#ifdef DEBUG_CONVEX_HULL
+ b3Printf(" Advanced edges to %d %d\n", et0.index, et1.index);
+#endif
+}
+
+
+void b3ConvexHullInternal::merge(IntermediateHull& h0, IntermediateHull& h1)
+{
+ if (!h1.maxXy)
+ {
+ return;
+ }
+ if (!h0.maxXy)
+ {
+ h0 = h1;
+ return;
+ }
+
+ mergeStamp--;
+
+ Vertex* c0 = NULL;
+ Edge* toPrev0 = NULL;
+ Edge* firstNew0 = NULL;
+ Edge* pendingHead0 = NULL;
+ Edge* pendingTail0 = NULL;
+ Vertex* c1 = NULL;
+ Edge* toPrev1 = NULL;
+ Edge* firstNew1 = NULL;
+ Edge* pendingHead1 = NULL;
+ Edge* pendingTail1 = NULL;
+ Point32 prevPoint;
+
+ if (mergeProjection(h0, h1, c0, c1))
+ {
+ Point32 s = *c1 - *c0;
+ Point64 normal = Point32(0, 0, -1).cross(s);
+ Point64 t = s.cross(normal);
+ b3Assert(!t.isZero());
+
+ Edge* e = c0->edges;
+ Edge* start0 = NULL;
+ if (e)
+ {
+ do
+ {
+ btInt64_t dot = (*e->target - *c0).dot(normal);
+ b3Assert(dot <= 0);
+ if ((dot == 0) && ((*e->target - *c0).dot(t) > 0))
+ {
+ if (!start0 || (getOrientation(start0, e, s, Point32(0, 0, -1)) == CLOCKWISE))
+ {
+ start0 = e;
+ }
+ }
+ e = e->next;
+ } while (e != c0->edges);
+ }
+
+ e = c1->edges;
+ Edge* start1 = NULL;
+ if (e)
+ {
+ do
+ {
+ btInt64_t dot = (*e->target - *c1).dot(normal);
+ b3Assert(dot <= 0);
+ if ((dot == 0) && ((*e->target - *c1).dot(t) > 0))
+ {
+ if (!start1 || (getOrientation(start1, e, s, Point32(0, 0, -1)) == COUNTER_CLOCKWISE))
+ {
+ start1 = e;
+ }
+ }
+ e = e->next;
+ } while (e != c1->edges);
+ }
+
+ if (start0 || start1)
+ {
+ findEdgeForCoplanarFaces(c0, c1, start0, start1, NULL, NULL);
+ if (start0)
+ {
+ c0 = start0->target;
+ }
+ if (start1)
+ {
+ c1 = start1->target;
+ }
+ }
+
+ prevPoint = c1->point;
+ prevPoint.z++;
+ }
+ else
+ {
+ prevPoint = c1->point;
+ prevPoint.x++;
+ }
+
+ Vertex* first0 = c0;
+ Vertex* first1 = c1;
+ bool firstRun = true;
+
+ while (true)
+ {
+ Point32 s = *c1 - *c0;
+ Point32 r = prevPoint - c0->point;
+ Point64 rxs = r.cross(s);
+ Point64 sxrxs = s.cross(rxs);
+
+#ifdef DEBUG_CONVEX_HULL
+ b3Printf("\n Checking %d %d\n", c0->point.index, c1->point.index);
+#endif
+ Rational64 minCot0(0, 0);
+ Edge* min0 = findMaxAngle(false, c0, s, rxs, sxrxs, minCot0);
+ Rational64 minCot1(0, 0);
+ Edge* min1 = findMaxAngle(true, c1, s, rxs, sxrxs, minCot1);
+ if (!min0 && !min1)
+ {
+ Edge* e = newEdgePair(c0, c1);
+ e->link(e);
+ c0->edges = e;
+
+ e = e->reverse;
+ e->link(e);
+ c1->edges = e;
+ return;
+ }
+ else
+ {
+ int cmp = !min0 ? 1 : !min1 ? -1 : minCot0.compare(minCot1);
+#ifdef DEBUG_CONVEX_HULL
+ b3Printf(" -> Result %d\n", cmp);
+#endif
+ if (firstRun || ((cmp >= 0) ? !minCot1.isNegativeInfinity() : !minCot0.isNegativeInfinity()))
+ {
+ Edge* e = newEdgePair(c0, c1);
+ if (pendingTail0)
+ {
+ pendingTail0->prev = e;
+ }
+ else
+ {
+ pendingHead0 = e;
+ }
+ e->next = pendingTail0;
+ pendingTail0 = e;
+
+ e = e->reverse;
+ if (pendingTail1)
+ {
+ pendingTail1->next = e;
+ }
+ else
+ {
+ pendingHead1 = e;
+ }
+ e->prev = pendingTail1;
+ pendingTail1 = e;
+ }
+
+ Edge* e0 = min0;
+ Edge* e1 = min1;
+
+#ifdef DEBUG_CONVEX_HULL
+ b3Printf(" Found min edges to %d %d\n", e0 ? e0->target->point.index : -1, e1 ? e1->target->point.index : -1);
+#endif
+
+ if (cmp == 0)
+ {
+ findEdgeForCoplanarFaces(c0, c1, e0, e1, NULL, NULL);
+ }
+
+ if ((cmp >= 0) && e1)
+ {
+ if (toPrev1)
+ {
+ for (Edge* e = toPrev1->next, *n = NULL; e != min1; e = n)
+ {
+ n = e->next;
+ removeEdgePair(e);
+ }
+ }
+
+ if (pendingTail1)
+ {
+ if (toPrev1)
+ {
+ toPrev1->link(pendingHead1);
+ }
+ else
+ {
+ min1->prev->link(pendingHead1);
+ firstNew1 = pendingHead1;
+ }
+ pendingTail1->link(min1);
+ pendingHead1 = NULL;
+ pendingTail1 = NULL;
+ }
+ else if (!toPrev1)
+ {
+ firstNew1 = min1;
+ }
+
+ prevPoint = c1->point;
+ c1 = e1->target;
+ toPrev1 = e1->reverse;
+ }
+
+ if ((cmp <= 0) && e0)
+ {
+ if (toPrev0)
+ {
+ for (Edge* e = toPrev0->prev, *n = NULL; e != min0; e = n)
+ {
+ n = e->prev;
+ removeEdgePair(e);
+ }
+ }
+
+ if (pendingTail0)
+ {
+ if (toPrev0)
+ {
+ pendingHead0->link(toPrev0);
+ }
+ else
+ {
+ pendingHead0->link(min0->next);
+ firstNew0 = pendingHead0;
+ }
+ min0->link(pendingTail0);
+ pendingHead0 = NULL;
+ pendingTail0 = NULL;
+ }
+ else if (!toPrev0)
+ {
+ firstNew0 = min0;
+ }
+
+ prevPoint = c0->point;
+ c0 = e0->target;
+ toPrev0 = e0->reverse;
+ }
+ }
+
+ if ((c0 == first0) && (c1 == first1))
+ {
+ if (toPrev0 == NULL)
+ {
+ pendingHead0->link(pendingTail0);
+ c0->edges = pendingTail0;
+ }
+ else
+ {
+ for (Edge* e = toPrev0->prev, *n = NULL; e != firstNew0; e = n)
+ {
+ n = e->prev;
+ removeEdgePair(e);
+ }
+ if (pendingTail0)
+ {
+ pendingHead0->link(toPrev0);
+ firstNew0->link(pendingTail0);
+ }
+ }
+
+ if (toPrev1 == NULL)
+ {
+ pendingTail1->link(pendingHead1);
+ c1->edges = pendingTail1;
+ }
+ else
+ {
+ for (Edge* e = toPrev1->next, *n = NULL; e != firstNew1; e = n)
+ {
+ n = e->next;
+ removeEdgePair(e);
+ }
+ if (pendingTail1)
+ {
+ toPrev1->link(pendingHead1);
+ pendingTail1->link(firstNew1);
+ }
+ }
+
+ return;
+ }
+
+ firstRun = false;
+ }
+}
+
+
+static bool b3PointCmp(const b3ConvexHullInternal::Point32& p, const b3ConvexHullInternal::Point32& q)
+{
+ return (p.y < q.y) || ((p.y == q.y) && ((p.x < q.x) || ((p.x == q.x) && (p.z < q.z))));
+}
+
+void b3ConvexHullInternal::compute(const void* coords, bool doubleCoords, int stride, int count)
+{
+ b3Vector3 min = b3MakeVector3(b3Scalar(1e30), b3Scalar(1e30), b3Scalar(1e30)), max = b3MakeVector3(b3Scalar(-1e30), b3Scalar(-1e30), b3Scalar(-1e30));
+ const char* ptr = (const char*) coords;
+ if (doubleCoords)
+ {
+ for (int i = 0; i < count; i++)
+ {
+ const double* v = (const double*) ptr;
+ b3Vector3 p = b3MakeVector3((b3Scalar) v[0], (b3Scalar) v[1], (b3Scalar) v[2]);
+ ptr += stride;
+ min.setMin(p);
+ max.setMax(p);
+ }
+ }
+ else
+ {
+ for (int i = 0; i < count; i++)
+ {
+ const float* v = (const float*) ptr;
+ b3Vector3 p = b3MakeVector3(v[0], v[1], v[2]);
+ ptr += stride;
+ min.setMin(p);
+ max.setMax(p);
+ }
+ }
+
+ b3Vector3 s = max - min;
+ maxAxis = s.maxAxis();
+ minAxis = s.minAxis();
+ if (minAxis == maxAxis)
+ {
+ minAxis = (maxAxis + 1) % 3;
+ }
+ medAxis = 3 - maxAxis - minAxis;
+
+ s /= b3Scalar(10216);
+ if (((medAxis + 1) % 3) != maxAxis)
+ {
+ s *= -1;
+ }
+ scaling = s;
+
+ if (s[0] != 0)
+ {
+ s[0] = b3Scalar(1) / s[0];
+ }
+ if (s[1] != 0)
+ {
+ s[1] = b3Scalar(1) / s[1];
+ }
+ if (s[2] != 0)
+ {
+ s[2] = b3Scalar(1) / s[2];
+ }
+
+ center = (min + max) * b3Scalar(0.5);
+
+ b3AlignedObjectArray<Point32> points;
+ points.resize(count);
+ ptr = (const char*) coords;
+ if (doubleCoords)
+ {
+ for (int i = 0; i < count; i++)
+ {
+ const double* v = (const double*) ptr;
+ b3Vector3 p = b3MakeVector3((b3Scalar) v[0], (b3Scalar) v[1], (b3Scalar) v[2]);
+ ptr += stride;
+ p = (p - center) * s;
+ points[i].x = (btInt32_t) p[medAxis];
+ points[i].y = (btInt32_t) p[maxAxis];
+ points[i].z = (btInt32_t) p[minAxis];
+ points[i].index = i;
+ }
+ }
+ else
+ {
+ for (int i = 0; i < count; i++)
+ {
+ const float* v = (const float*) ptr;
+ b3Vector3 p = b3MakeVector3(v[0], v[1], v[2]);
+ ptr += stride;
+ p = (p - center) * s;
+ points[i].x = (btInt32_t) p[medAxis];
+ points[i].y = (btInt32_t) p[maxAxis];
+ points[i].z = (btInt32_t) p[minAxis];
+ points[i].index = i;
+ }
+ }
+ points.quickSort(b3PointCmp);
+
+ vertexPool.reset();
+ vertexPool.setArraySize(count);
+ originalVertices.resize(count);
+ for (int i = 0; i < count; i++)
+ {
+ Vertex* v = vertexPool.newObject();
+ v->edges = NULL;
+ v->point = points[i];
+ v->copy = -1;
+ originalVertices[i] = v;
+ }
+
+ points.clear();
+
+ edgePool.reset();
+ edgePool.setArraySize(6 * count);
+
+ usedEdgePairs = 0;
+ maxUsedEdgePairs = 0;
+
+ mergeStamp = -3;
+
+ IntermediateHull hull;
+ computeInternal(0, count, hull);
+ vertexList = hull.minXy;
+#ifdef DEBUG_CONVEX_HULL
+ b3Printf("max. edges %d (3v = %d)", maxUsedEdgePairs, 3 * count);
+#endif
+}
+
+b3Vector3 b3ConvexHullInternal::toBtVector(const Point32& v)
+{
+ b3Vector3 p;
+ p[medAxis] = b3Scalar(v.x);
+ p[maxAxis] = b3Scalar(v.y);
+ p[minAxis] = b3Scalar(v.z);
+ return p * scaling;
+}
+
+b3Vector3 b3ConvexHullInternal::getBtNormal(Face* face)
+{
+ return toBtVector(face->dir0).cross(toBtVector(face->dir1)).normalized();
+}
+
+b3Vector3 b3ConvexHullInternal::getCoordinates(const Vertex* v)
+{
+ b3Vector3 p;
+ p[medAxis] = v->xvalue();
+ p[maxAxis] = v->yvalue();
+ p[minAxis] = v->zvalue();
+ return p * scaling + center;
+}
+
+b3Scalar b3ConvexHullInternal::shrink(b3Scalar amount, b3Scalar clampAmount)
+{
+ if (!vertexList)
+ {
+ return 0;
+ }
+ int stamp = --mergeStamp;
+ b3AlignedObjectArray<Vertex*> stack;
+ vertexList->copy = stamp;
+ stack.push_back(vertexList);
+ b3AlignedObjectArray<Face*> faces;
+
+ Point32 ref = vertexList->point;
+ Int128 hullCenterX(0, 0);
+ Int128 hullCenterY(0, 0);
+ Int128 hullCenterZ(0, 0);
+ Int128 volume(0, 0);
+
+ while (stack.size() > 0)
+ {
+ Vertex* v = stack[stack.size() - 1];
+ stack.pop_back();
+ Edge* e = v->edges;
+ if (e)
+ {
+ do
+ {
+ if (e->target->copy != stamp)
+ {
+ e->target->copy = stamp;
+ stack.push_back(e->target);
+ }
+ if (e->copy != stamp)
+ {
+ Face* face = facePool.newObject();
+ face->init(e->target, e->reverse->prev->target, v);
+ faces.push_back(face);
+ Edge* f = e;
+
+ Vertex* a = NULL;
+ Vertex* b = NULL;
+ do
+ {
+ if (a && b)
+ {
+ btInt64_t vol = (v->point - ref).dot((a->point - ref).cross(b->point - ref));
+ b3Assert(vol >= 0);
+ Point32 c = v->point + a->point + b->point + ref;
+ hullCenterX += vol * c.x;
+ hullCenterY += vol * c.y;
+ hullCenterZ += vol * c.z;
+ volume += vol;
+ }
+
+ b3Assert(f->copy != stamp);
+ f->copy = stamp;
+ f->face = face;
+
+ a = b;
+ b = f->target;
+
+ f = f->reverse->prev;
+ } while (f != e);
+ }
+ e = e->next;
+ } while (e != v->edges);
+ }
+ }
+
+ if (volume.getSign() <= 0)
+ {
+ return 0;
+ }
+
+ b3Vector3 hullCenter;
+ hullCenter[medAxis] = hullCenterX.toScalar();
+ hullCenter[maxAxis] = hullCenterY.toScalar();
+ hullCenter[minAxis] = hullCenterZ.toScalar();
+ hullCenter /= 4 * volume.toScalar();
+ hullCenter *= scaling;
+
+ int faceCount = faces.size();
+
+ if (clampAmount > 0)
+ {
+ b3Scalar minDist = B3_INFINITY;
+ for (int i = 0; i < faceCount; i++)
+ {
+ b3Vector3 normal = getBtNormal(faces[i]);
+ b3Scalar dist = normal.dot(toBtVector(faces[i]->origin) - hullCenter);
+ if (dist < minDist)
+ {
+ minDist = dist;
+ }
+ }
+
+ if (minDist <= 0)
+ {
+ return 0;
+ }
+
+ amount = b3Min(amount, minDist * clampAmount);
+ }
+
+ unsigned int seed = 243703;
+ for (int i = 0; i < faceCount; i++, seed = 1664525 * seed + 1013904223)
+ {
+ b3Swap(faces[i], faces[seed % faceCount]);
+ }
+
+ for (int i = 0; i < faceCount; i++)
+ {
+ if (!shiftFace(faces[i], amount, stack))
+ {
+ return -amount;
+ }
+ }
+
+ return amount;
+}
+
+bool b3ConvexHullInternal::shiftFace(Face* face, b3Scalar amount, b3AlignedObjectArray<Vertex*> stack)
+{
+ b3Vector3 origShift = getBtNormal(face) * -amount;
+ if (scaling[0] != 0)
+ {
+ origShift[0] /= scaling[0];
+ }
+ if (scaling[1] != 0)
+ {
+ origShift[1] /= scaling[1];
+ }
+ if (scaling[2] != 0)
+ {
+ origShift[2] /= scaling[2];
+ }
+ Point32 shift((btInt32_t) origShift[medAxis], (btInt32_t) origShift[maxAxis], (btInt32_t) origShift[minAxis]);
+ if (shift.isZero())
+ {
+ return true;
+ }
+ Point64 normal = face->getNormal();
+#ifdef DEBUG_CONVEX_HULL
+ b3Printf("\nShrinking face (%d %d %d) (%d %d %d) (%d %d %d) by (%d %d %d)\n",
+ face->origin.x, face->origin.y, face->origin.z, face->dir0.x, face->dir0.y, face->dir0.z, face->dir1.x, face->dir1.y, face->dir1.z, shift.x, shift.y, shift.z);
+#endif
+ btInt64_t origDot = face->origin.dot(normal);
+ Point32 shiftedOrigin = face->origin + shift;
+ btInt64_t shiftedDot = shiftedOrigin.dot(normal);
+ b3Assert(shiftedDot <= origDot);
+ if (shiftedDot >= origDot)
+ {
+ return false;
+ }
+
+ Edge* intersection = NULL;
+
+ Edge* startEdge = face->nearbyVertex->edges;
+#ifdef DEBUG_CONVEX_HULL
+ b3Printf("Start edge is ");
+ startEdge->print();
+ b3Printf(", normal is (%lld %lld %lld), shifted dot is %lld\n", normal.x, normal.y, normal.z, shiftedDot);
+#endif
+ Rational128 optDot = face->nearbyVertex->dot(normal);
+ int cmp = optDot.compare(shiftedDot);
+#ifdef SHOW_ITERATIONS
+ int n = 0;
+#endif
+ if (cmp >= 0)
+ {
+ Edge* e = startEdge;
+ do
+ {
+#ifdef SHOW_ITERATIONS
+ n++;
+#endif
+ Rational128 dot = e->target->dot(normal);
+ b3Assert(dot.compare(origDot) <= 0);
+#ifdef DEBUG_CONVEX_HULL
+ b3Printf("Moving downwards, edge is ");
+ e->print();
+ b3Printf(", dot is %f (%f %lld)\n", (float) dot.toScalar(), (float) optDot.toScalar(), shiftedDot);
+#endif
+ if (dot.compare(optDot) < 0)
+ {
+ int c = dot.compare(shiftedDot);
+ optDot = dot;
+ e = e->reverse;
+ startEdge = e;
+ if (c < 0)
+ {
+ intersection = e;
+ break;
+ }
+ cmp = c;
+ }
+ e = e->prev;
+ } while (e != startEdge);
+
+ if (!intersection)
+ {
+ return false;
+ }
+ }
+ else
+ {
+ Edge* e = startEdge;
+ do
+ {
+#ifdef SHOW_ITERATIONS
+ n++;
+#endif
+ Rational128 dot = e->target->dot(normal);
+ b3Assert(dot.compare(origDot) <= 0);
+#ifdef DEBUG_CONVEX_HULL
+ b3Printf("Moving upwards, edge is ");
+ e->print();
+ b3Printf(", dot is %f (%f %lld)\n", (float) dot.toScalar(), (float) optDot.toScalar(), shiftedDot);
+#endif
+ if (dot.compare(optDot) > 0)
+ {
+ cmp = dot.compare(shiftedDot);
+ if (cmp >= 0)
+ {
+ intersection = e;
+ break;
+ }
+ optDot = dot;
+ e = e->reverse;
+ startEdge = e;
+ }
+ e = e->prev;
+ } while (e != startEdge);
+
+ if (!intersection)
+ {
+ return true;
+ }
+ }
+
+#ifdef SHOW_ITERATIONS
+ b3Printf("Needed %d iterations to find initial intersection\n", n);
+#endif
+
+ if (cmp == 0)
+ {
+ Edge* e = intersection->reverse->next;
+#ifdef SHOW_ITERATIONS
+ n = 0;
+#endif
+ while (e->target->dot(normal).compare(shiftedDot) <= 0)
+ {
+#ifdef SHOW_ITERATIONS
+ n++;
+#endif
+ e = e->next;
+ if (e == intersection->reverse)
+ {
+ return true;
+ }
+#ifdef DEBUG_CONVEX_HULL
+ b3Printf("Checking for outwards edge, current edge is ");
+ e->print();
+ b3Printf("\n");
+#endif
+ }
+#ifdef SHOW_ITERATIONS
+ b3Printf("Needed %d iterations to check for complete containment\n", n);
+#endif
+ }
+
+ Edge* firstIntersection = NULL;
+ Edge* faceEdge = NULL;
+ Edge* firstFaceEdge = NULL;
+
+#ifdef SHOW_ITERATIONS
+ int m = 0;
+#endif
+ while (true)
+ {
+#ifdef SHOW_ITERATIONS
+ m++;
+#endif
+#ifdef DEBUG_CONVEX_HULL
+ b3Printf("Intersecting edge is ");
+ intersection->print();
+ b3Printf("\n");
+#endif
+ if (cmp == 0)
+ {
+ Edge* e = intersection->reverse->next;
+ startEdge = e;
+#ifdef SHOW_ITERATIONS
+ n = 0;
+#endif
+ while (true)
+ {
+#ifdef SHOW_ITERATIONS
+ n++;
+#endif
+ if (e->target->dot(normal).compare(shiftedDot) >= 0)
+ {
+ break;
+ }
+ intersection = e->reverse;
+ e = e->next;
+ if (e == startEdge)
+ {
+ return true;
+ }
+ }
+#ifdef SHOW_ITERATIONS
+ b3Printf("Needed %d iterations to advance intersection\n", n);
+#endif
+ }
+
+#ifdef DEBUG_CONVEX_HULL
+ b3Printf("Advanced intersecting edge to ");
+ intersection->print();
+ b3Printf(", cmp = %d\n", cmp);
+#endif
+
+ if (!firstIntersection)
+ {
+ firstIntersection = intersection;
+ }
+ else if (intersection == firstIntersection)
+ {
+ break;
+ }
+
+ int prevCmp = cmp;
+ Edge* prevIntersection = intersection;
+ Edge* prevFaceEdge = faceEdge;
+
+ Edge* e = intersection->reverse;
+#ifdef SHOW_ITERATIONS
+ n = 0;
+#endif
+ while (true)
+ {
+#ifdef SHOW_ITERATIONS
+ n++;
+#endif
+ e = e->reverse->prev;
+ b3Assert(e != intersection->reverse);
+ cmp = e->target->dot(normal).compare(shiftedDot);
+#ifdef DEBUG_CONVEX_HULL
+ b3Printf("Testing edge ");
+ e->print();
+ b3Printf(" -> cmp = %d\n", cmp);
+#endif
+ if (cmp >= 0)
+ {
+ intersection = e;
+ break;
+ }
+ }
+#ifdef SHOW_ITERATIONS
+ b3Printf("Needed %d iterations to find other intersection of face\n", n);
+#endif
+
+ if (cmp > 0)
+ {
+ Vertex* removed = intersection->target;
+ e = intersection->reverse;
+ if (e->prev == e)
+ {
+ removed->edges = NULL;
+ }
+ else
+ {
+ removed->edges = e->prev;
+ e->prev->link(e->next);
+ e->link(e);
+ }
+#ifdef DEBUG_CONVEX_HULL
+ b3Printf("1: Removed part contains (%d %d %d)\n", removed->point.x, removed->point.y, removed->point.z);
+#endif
+
+ Point64 n0 = intersection->face->getNormal();
+ Point64 n1 = intersection->reverse->face->getNormal();
+ btInt64_t m00 = face->dir0.dot(n0);
+ btInt64_t m01 = face->dir1.dot(n0);
+ btInt64_t m10 = face->dir0.dot(n1);
+ btInt64_t m11 = face->dir1.dot(n1);
+ btInt64_t r0 = (intersection->face->origin - shiftedOrigin).dot(n0);
+ btInt64_t r1 = (intersection->reverse->face->origin - shiftedOrigin).dot(n1);
+ Int128 det = Int128::mul(m00, m11) - Int128::mul(m01, m10);
+ b3Assert(det.getSign() != 0);
+ Vertex* v = vertexPool.newObject();
+ v->point.index = -1;
+ v->copy = -1;
+ v->point128 = PointR128(Int128::mul(face->dir0.x * r0, m11) - Int128::mul(face->dir0.x * r1, m01)
+ + Int128::mul(face->dir1.x * r1, m00) - Int128::mul(face->dir1.x * r0, m10) + det * shiftedOrigin.x,
+ Int128::mul(face->dir0.y * r0, m11) - Int128::mul(face->dir0.y * r1, m01)
+ + Int128::mul(face->dir1.y * r1, m00) - Int128::mul(face->dir1.y * r0, m10) + det * shiftedOrigin.y,
+ Int128::mul(face->dir0.z * r0, m11) - Int128::mul(face->dir0.z * r1, m01)
+ + Int128::mul(face->dir1.z * r1, m00) - Int128::mul(face->dir1.z * r0, m10) + det * shiftedOrigin.z,
+ det);
+ v->point.x = (btInt32_t) v->point128.xvalue();
+ v->point.y = (btInt32_t) v->point128.yvalue();
+ v->point.z = (btInt32_t) v->point128.zvalue();
+ intersection->target = v;
+ v->edges = e;
+
+ stack.push_back(v);
+ stack.push_back(removed);
+ stack.push_back(NULL);
+ }
+
+ if (cmp || prevCmp || (prevIntersection->reverse->next->target != intersection->target))
+ {
+ faceEdge = newEdgePair(prevIntersection->target, intersection->target);
+ if (prevCmp == 0)
+ {
+ faceEdge->link(prevIntersection->reverse->next);
+ }
+ if ((prevCmp == 0) || prevFaceEdge)
+ {
+ prevIntersection->reverse->link(faceEdge);
+ }
+ if (cmp == 0)
+ {
+ intersection->reverse->prev->link(faceEdge->reverse);
+ }
+ faceEdge->reverse->link(intersection->reverse);
+ }
+ else
+ {
+ faceEdge = prevIntersection->reverse->next;
+ }
+
+ if (prevFaceEdge)
+ {
+ if (prevCmp > 0)
+ {
+ faceEdge->link(prevFaceEdge->reverse);
+ }
+ else if (faceEdge != prevFaceEdge->reverse)
+ {
+ stack.push_back(prevFaceEdge->target);
+ while (faceEdge->next != prevFaceEdge->reverse)
+ {
+ Vertex* removed = faceEdge->next->target;
+ removeEdgePair(faceEdge->next);
+ stack.push_back(removed);
+#ifdef DEBUG_CONVEX_HULL
+ b3Printf("2: Removed part contains (%d %d %d)\n", removed->point.x, removed->point.y, removed->point.z);
+#endif
+ }
+ stack.push_back(NULL);
+ }
+ }
+ faceEdge->face = face;
+ faceEdge->reverse->face = intersection->face;
+
+ if (!firstFaceEdge)
+ {
+ firstFaceEdge = faceEdge;
+ }
+ }
+#ifdef SHOW_ITERATIONS
+ b3Printf("Needed %d iterations to process all intersections\n", m);
+#endif
+
+ if (cmp > 0)
+ {
+ firstFaceEdge->reverse->target = faceEdge->target;
+ firstIntersection->reverse->link(firstFaceEdge);
+ firstFaceEdge->link(faceEdge->reverse);
+ }
+ else if (firstFaceEdge != faceEdge->reverse)
+ {
+ stack.push_back(faceEdge->target);
+ while (firstFaceEdge->next != faceEdge->reverse)
+ {
+ Vertex* removed = firstFaceEdge->next->target;
+ removeEdgePair(firstFaceEdge->next);
+ stack.push_back(removed);
+#ifdef DEBUG_CONVEX_HULL
+ b3Printf("3: Removed part contains (%d %d %d)\n", removed->point.x, removed->point.y, removed->point.z);
+#endif
+ }
+ stack.push_back(NULL);
+ }
+
+ b3Assert(stack.size() > 0);
+ vertexList = stack[0];
+
+#ifdef DEBUG_CONVEX_HULL
+ b3Printf("Removing part\n");
+#endif
+#ifdef SHOW_ITERATIONS
+ n = 0;
+#endif
+ int pos = 0;
+ while (pos < stack.size())
+ {
+ int end = stack.size();
+ while (pos < end)
+ {
+ Vertex* kept = stack[pos++];
+#ifdef DEBUG_CONVEX_HULL
+ kept->print();
+#endif
+ bool deeper = false;
+ Vertex* removed;
+ while ((removed = stack[pos++]) != NULL)
+ {
+#ifdef SHOW_ITERATIONS
+ n++;
+#endif
+ kept->receiveNearbyFaces(removed);
+ while (removed->edges)
+ {
+ if (!deeper)
+ {
+ deeper = true;
+ stack.push_back(kept);
+ }
+ stack.push_back(removed->edges->target);
+ removeEdgePair(removed->edges);
+ }
+ }
+ if (deeper)
+ {
+ stack.push_back(NULL);
+ }
+ }
+ }
+#ifdef SHOW_ITERATIONS
+ b3Printf("Needed %d iterations to remove part\n", n);
+#endif
+
+ stack.resize(0);
+ face->origin = shiftedOrigin;
+
+ return true;
+}
+
+
+static int getVertexCopy(b3ConvexHullInternal::Vertex* vertex, b3AlignedObjectArray<b3ConvexHullInternal::Vertex*>& vertices)
+{
+ int index = vertex->copy;
+ if (index < 0)
+ {
+ index = vertices.size();
+ vertex->copy = index;
+ vertices.push_back(vertex);
+#ifdef DEBUG_CONVEX_HULL
+ b3Printf("Vertex %d gets index *%d\n", vertex->point.index, index);
+#endif
+ }
+ return index;
+}
+
+b3Scalar b3ConvexHullComputer::compute(const void* coords, bool doubleCoords, int stride, int count, b3Scalar shrink, b3Scalar shrinkClamp)
+{
+ if (count <= 0)
+ {
+ vertices.clear();
+ edges.clear();
+ faces.clear();
+ return 0;
+ }
+
+ b3ConvexHullInternal hull;
+ hull.compute(coords, doubleCoords, stride, count);
+
+ b3Scalar shift = 0;
+ if ((shrink > 0) && ((shift = hull.shrink(shrink, shrinkClamp)) < 0))
+ {
+ vertices.clear();
+ edges.clear();
+ faces.clear();
+ return shift;
+ }
+
+ vertices.resize(0);
+ edges.resize(0);
+ faces.resize(0);
+
+ b3AlignedObjectArray<b3ConvexHullInternal::Vertex*> oldVertices;
+ getVertexCopy(hull.vertexList, oldVertices);
+ int copied = 0;
+ while (copied < oldVertices.size())
+ {
+ b3ConvexHullInternal::Vertex* v = oldVertices[copied];
+ vertices.push_back(hull.getCoordinates(v));
+ b3ConvexHullInternal::Edge* firstEdge = v->edges;
+ if (firstEdge)
+ {
+ int firstCopy = -1;
+ int prevCopy = -1;
+ b3ConvexHullInternal::Edge* e = firstEdge;
+ do
+ {
+ if (e->copy < 0)
+ {
+ int s = edges.size();
+ edges.push_back(Edge());
+ edges.push_back(Edge());
+ Edge* c = &edges[s];
+ Edge* r = &edges[s + 1];
+ e->copy = s;
+ e->reverse->copy = s + 1;
+ c->reverse = 1;
+ r->reverse = -1;
+ c->targetVertex = getVertexCopy(e->target, oldVertices);
+ r->targetVertex = copied;
+#ifdef DEBUG_CONVEX_HULL
+ b3Printf(" CREATE: Vertex *%d has edge to *%d\n", copied, c->getTargetVertex());
+#endif
+ }
+ if (prevCopy >= 0)
+ {
+ edges[e->copy].next = prevCopy - e->copy;
+ }
+ else
+ {
+ firstCopy = e->copy;
+ }
+ prevCopy = e->copy;
+ e = e->next;
+ } while (e != firstEdge);
+ edges[firstCopy].next = prevCopy - firstCopy;
+ }
+ copied++;
+ }
+
+ for (int i = 0; i < copied; i++)
+ {
+ b3ConvexHullInternal::Vertex* v = oldVertices[i];
+ b3ConvexHullInternal::Edge* firstEdge = v->edges;
+ if (firstEdge)
+ {
+ b3ConvexHullInternal::Edge* e = firstEdge;
+ do
+ {
+ if (e->copy >= 0)
+ {
+#ifdef DEBUG_CONVEX_HULL
+ b3Printf("Vertex *%d has edge to *%d\n", i, edges[e->copy].getTargetVertex());
+#endif
+ faces.push_back(e->copy);
+ b3ConvexHullInternal::Edge* f = e;
+ do
+ {
+#ifdef DEBUG_CONVEX_HULL
+ b3Printf(" Face *%d\n", edges[f->copy].getTargetVertex());
+#endif
+ f->copy = -1;
+ f = f->reverse->prev;
+ } while (f != e);
+ }
+ e = e->next;
+ } while (e != firstEdge);
+ }
+ }
+
+ return shift;
+}
+
+
+
+
+
diff --git a/thirdparty/bullet/src/Bullet3Geometry/b3ConvexHullComputer.h b/thirdparty/bullet/src/Bullet3Geometry/b3ConvexHullComputer.h
new file mode 100644
index 0000000000..6dcc931a78
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Geometry/b3ConvexHullComputer.h
@@ -0,0 +1,103 @@
+/*
+Copyright (c) 2011 Ole Kniemeyer, MAXON, www.maxon.net
+
+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 B3_CONVEX_HULL_COMPUTER_H
+#define B3_CONVEX_HULL_COMPUTER_H
+
+#include "Bullet3Common/b3Vector3.h"
+#include "Bullet3Common/b3AlignedObjectArray.h"
+
+/// Convex hull implementation based on Preparata and Hong
+/// See http://code.google.com/p/bullet/issues/detail?id=275
+/// Ole Kniemeyer, MAXON Computer GmbH
+class b3ConvexHullComputer
+{
+ private:
+ b3Scalar compute(const void* coords, bool doubleCoords, int stride, int count, b3Scalar shrink, b3Scalar shrinkClamp);
+
+ public:
+
+ class Edge
+ {
+ private:
+ int next;
+ int reverse;
+ int targetVertex;
+
+ friend class b3ConvexHullComputer;
+
+ public:
+ int getSourceVertex() const
+ {
+ return (this + reverse)->targetVertex;
+ }
+
+ int getTargetVertex() const
+ {
+ return targetVertex;
+ }
+
+ const Edge* getNextEdgeOfVertex() const // clockwise list of all edges of a vertex
+ {
+ return this + next;
+ }
+
+ const Edge* getNextEdgeOfFace() const // counter-clockwise list of all edges of a face
+ {
+ return (this + reverse)->getNextEdgeOfVertex();
+ }
+
+ const Edge* getReverseEdge() const
+ {
+ return this + reverse;
+ }
+ };
+
+
+ // Vertices of the output hull
+ b3AlignedObjectArray<b3Vector3> vertices;
+
+ // Edges of the output hull
+ b3AlignedObjectArray<Edge> edges;
+
+ // Faces of the convex hull. Each entry is an index into the "edges" array pointing to an edge of the face. Faces are planar n-gons
+ b3AlignedObjectArray<int> faces;
+
+ /*
+ Compute convex hull of "count" vertices stored in "coords". "stride" is the difference in bytes
+ between the addresses of consecutive vertices. If "shrink" is positive, the convex hull is shrunken
+ by that amount (each face is moved by "shrink" length units towards the center along its normal).
+ If "shrinkClamp" is positive, "shrink" is clamped to not exceed "shrinkClamp * innerRadius", where "innerRadius"
+ is the minimum distance of a face to the center of the convex hull.
+
+ The returned value is the amount by which the hull has been shrunken. If it is negative, the amount was so large
+ that the resulting convex hull is empty.
+
+ The output convex hull can be found in the member variables "vertices", "edges", "faces".
+ */
+ b3Scalar compute(const float* coords, int stride, int count, b3Scalar shrink, b3Scalar shrinkClamp)
+ {
+ return compute(coords, false, stride, count, shrink, shrinkClamp);
+ }
+
+ // same as above, but double precision
+ b3Scalar compute(const double* coords, int stride, int count, b3Scalar shrink, b3Scalar shrinkClamp)
+ {
+ return compute(coords, true, stride, count, shrink, shrinkClamp);
+ }
+};
+
+
+#endif //B3_CONVEX_HULL_COMPUTER_H
+
diff --git a/thirdparty/bullet/src/Bullet3Geometry/b3GeometryUtil.cpp b/thirdparty/bullet/src/Bullet3Geometry/b3GeometryUtil.cpp
new file mode 100644
index 0000000000..dd80fed6bd
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Geometry/b3GeometryUtil.cpp
@@ -0,0 +1,185 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+#include "b3GeometryUtil.h"
+
+
+/*
+ Make sure this dummy function never changes so that it
+ can be used by probes that are checking whether the
+ library is actually installed.
+*/
+extern "C"
+{
+ void b3BulletMathProbe ();
+
+ void b3BulletMathProbe () {}
+}
+
+
+bool b3GeometryUtil::isPointInsidePlanes(const b3AlignedObjectArray<b3Vector3>& planeEquations, const b3Vector3& point, b3Scalar margin)
+{
+ int numbrushes = planeEquations.size();
+ for (int i=0;i<numbrushes;i++)
+ {
+ const b3Vector3& N1 = planeEquations[i];
+ b3Scalar dist = b3Scalar(N1.dot(point))+b3Scalar(N1[3])-margin;
+ if (dist>b3Scalar(0.))
+ {
+ return false;
+ }
+ }
+ return true;
+
+}
+
+
+bool b3GeometryUtil::areVerticesBehindPlane(const b3Vector3& planeNormal, const b3AlignedObjectArray<b3Vector3>& vertices, b3Scalar margin)
+{
+ int numvertices = vertices.size();
+ for (int i=0;i<numvertices;i++)
+ {
+ const b3Vector3& N1 = vertices[i];
+ b3Scalar dist = b3Scalar(planeNormal.dot(N1))+b3Scalar(planeNormal[3])-margin;
+ if (dist>b3Scalar(0.))
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool notExist(const b3Vector3& planeEquation,const b3AlignedObjectArray<b3Vector3>& planeEquations);
+
+bool notExist(const b3Vector3& planeEquation,const b3AlignedObjectArray<b3Vector3>& planeEquations)
+{
+ int numbrushes = planeEquations.size();
+ for (int i=0;i<numbrushes;i++)
+ {
+ const b3Vector3& N1 = planeEquations[i];
+ if (planeEquation.dot(N1) > b3Scalar(0.999))
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+void b3GeometryUtil::getPlaneEquationsFromVertices(b3AlignedObjectArray<b3Vector3>& vertices, b3AlignedObjectArray<b3Vector3>& planeEquationsOut )
+{
+ const int numvertices = vertices.size();
+ // brute force:
+ for (int i=0;i<numvertices;i++)
+ {
+ const b3Vector3& N1 = vertices[i];
+
+
+ for (int j=i+1;j<numvertices;j++)
+ {
+ const b3Vector3& N2 = vertices[j];
+
+ for (int k=j+1;k<numvertices;k++)
+ {
+
+ const b3Vector3& N3 = vertices[k];
+
+ b3Vector3 planeEquation,edge0,edge1;
+ edge0 = N2-N1;
+ edge1 = N3-N1;
+ b3Scalar normalSign = b3Scalar(1.);
+ for (int ww=0;ww<2;ww++)
+ {
+ planeEquation = normalSign * edge0.cross(edge1);
+ if (planeEquation.length2() > b3Scalar(0.0001))
+ {
+ planeEquation.normalize();
+ if (notExist(planeEquation,planeEquationsOut))
+ {
+ planeEquation[3] = -planeEquation.dot(N1);
+
+ //check if inside, and replace supportingVertexOut if needed
+ if (areVerticesBehindPlane(planeEquation,vertices,b3Scalar(0.01)))
+ {
+ planeEquationsOut.push_back(planeEquation);
+ }
+ }
+ }
+ normalSign = b3Scalar(-1.);
+ }
+
+ }
+ }
+ }
+
+}
+
+void b3GeometryUtil::getVerticesFromPlaneEquations(const b3AlignedObjectArray<b3Vector3>& planeEquations , b3AlignedObjectArray<b3Vector3>& verticesOut )
+{
+ const int numbrushes = planeEquations.size();
+ // brute force:
+ for (int i=0;i<numbrushes;i++)
+ {
+ const b3Vector3& N1 = planeEquations[i];
+
+
+ for (int j=i+1;j<numbrushes;j++)
+ {
+ const b3Vector3& N2 = planeEquations[j];
+
+ for (int k=j+1;k<numbrushes;k++)
+ {
+
+ const b3Vector3& N3 = planeEquations[k];
+
+ b3Vector3 n2n3; n2n3 = N2.cross(N3);
+ b3Vector3 n3n1; n3n1 = N3.cross(N1);
+ b3Vector3 n1n2; n1n2 = N1.cross(N2);
+
+ if ( ( n2n3.length2() > b3Scalar(0.0001) ) &&
+ ( n3n1.length2() > b3Scalar(0.0001) ) &&
+ ( n1n2.length2() > b3Scalar(0.0001) ) )
+ {
+ //point P out of 3 plane equations:
+
+ // d1 ( N2 * N3 ) + d2 ( N3 * N1 ) + d3 ( N1 * N2 )
+ //P = -------------------------------------------------------------------------
+ // N1 . ( N2 * N3 )
+
+
+ b3Scalar quotient = (N1.dot(n2n3));
+ if (b3Fabs(quotient) > b3Scalar(0.000001))
+ {
+ quotient = b3Scalar(-1.) / quotient;
+ n2n3 *= N1[3];
+ n3n1 *= N2[3];
+ n1n2 *= N3[3];
+ b3Vector3 potentialVertex = n2n3;
+ potentialVertex += n3n1;
+ potentialVertex += n1n2;
+ potentialVertex *= quotient;
+
+ //check if inside, and replace supportingVertexOut if needed
+ if (isPointInsidePlanes(planeEquations,potentialVertex,b3Scalar(0.01)))
+ {
+ verticesOut.push_back(potentialVertex);
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
diff --git a/thirdparty/bullet/src/Bullet3Geometry/b3GeometryUtil.h b/thirdparty/bullet/src/Bullet3Geometry/b3GeometryUtil.h
new file mode 100644
index 0000000000..8b5fd7ad62
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Geometry/b3GeometryUtil.h
@@ -0,0 +1,42 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#ifndef B3_GEOMETRY_UTIL_H
+#define B3_GEOMETRY_UTIL_H
+
+#include "Bullet3Common/b3Vector3.h"
+#include "Bullet3Common/b3AlignedObjectArray.h"
+
+///The b3GeometryUtil helper class provides a few methods to convert between plane equations and vertices.
+class b3GeometryUtil
+{
+ public:
+
+
+ static void getPlaneEquationsFromVertices(b3AlignedObjectArray<b3Vector3>& vertices, b3AlignedObjectArray<b3Vector3>& planeEquationsOut );
+
+ static void getVerticesFromPlaneEquations(const b3AlignedObjectArray<b3Vector3>& planeEquations , b3AlignedObjectArray<b3Vector3>& verticesOut );
+
+ static bool isInside(const b3AlignedObjectArray<b3Vector3>& vertices, const b3Vector3& planeNormal, b3Scalar margin);
+
+ static bool isPointInsidePlanes(const b3AlignedObjectArray<b3Vector3>& planeEquations, const b3Vector3& point, b3Scalar margin);
+
+ static bool areVerticesBehindPlane(const b3Vector3& planeNormal, const b3AlignedObjectArray<b3Vector3>& vertices, b3Scalar margin);
+
+};
+
+
+#endif //B3_GEOMETRY_UTIL_H
+
diff --git a/thirdparty/bullet/src/Bullet3Geometry/b3GrahamScan2dConvexHull.h b/thirdparty/bullet/src/Bullet3Geometry/b3GrahamScan2dConvexHull.h
new file mode 100644
index 0000000000..1b933c5264
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Geometry/b3GrahamScan2dConvexHull.h
@@ -0,0 +1,117 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2011 Advanced Micro Devices, 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 B3_GRAHAM_SCAN_2D_CONVEX_HULL_H
+#define B3_GRAHAM_SCAN_2D_CONVEX_HULL_H
+
+
+#include "Bullet3Common/b3Vector3.h"
+#include "Bullet3Common/b3AlignedObjectArray.h"
+
+struct b3GrahamVector3 : public b3Vector3
+{
+ b3GrahamVector3(const b3Vector3& org, int orgIndex)
+ :b3Vector3(org),
+ m_orgIndex(orgIndex)
+ {
+ }
+ b3Scalar m_angle;
+ int m_orgIndex;
+};
+
+
+struct b3AngleCompareFunc {
+ b3Vector3 m_anchor;
+ b3AngleCompareFunc(const b3Vector3& anchor)
+ : m_anchor(anchor)
+ {
+ }
+ bool operator()(const b3GrahamVector3& a, const b3GrahamVector3& b) const {
+ if (a.m_angle != b.m_angle)
+ return a.m_angle < b.m_angle;
+ else
+ {
+ b3Scalar al = (a-m_anchor).length2();
+ b3Scalar bl = (b-m_anchor).length2();
+ if (al != bl)
+ return al < bl;
+ else
+ {
+ return a.m_orgIndex < b.m_orgIndex;
+ }
+ }
+ }
+};
+
+inline void b3GrahamScanConvexHull2D(b3AlignedObjectArray<b3GrahamVector3>& originalPoints, b3AlignedObjectArray<b3GrahamVector3>& hull, const b3Vector3& normalAxis)
+{
+ b3Vector3 axis0,axis1;
+ b3PlaneSpace1(normalAxis,axis0,axis1);
+
+
+ if (originalPoints.size()<=1)
+ {
+ for (int i=0;i<originalPoints.size();i++)
+ hull.push_back(originalPoints[0]);
+ return;
+ }
+ //step1 : find anchor point with smallest projection on axis0 and move it to first location
+ for (int i=0;i<originalPoints.size();i++)
+ {
+// const b3Vector3& left = originalPoints[i];
+// const b3Vector3& right = originalPoints[0];
+ b3Scalar projL = originalPoints[i].dot(axis0);
+ b3Scalar projR = originalPoints[0].dot(axis0);
+ if (projL < projR)
+ {
+ originalPoints.swap(0,i);
+ }
+ }
+
+ //also precompute angles
+ originalPoints[0].m_angle = -1e30f;
+ for (int i=1;i<originalPoints.size();i++)
+ {
+ b3Vector3 xvec = axis0;
+ b3Vector3 ar = originalPoints[i]-originalPoints[0];
+ originalPoints[i].m_angle = b3Cross(xvec, ar).dot(normalAxis) / ar.length();
+ }
+
+ //step 2: sort all points, based on 'angle' with this anchor
+ b3AngleCompareFunc comp(originalPoints[0]);
+ originalPoints.quickSortInternal(comp,1,originalPoints.size()-1);
+
+ int i;
+ for (i = 0; i<2; i++)
+ hull.push_back(originalPoints[i]);
+
+ //step 3: keep all 'convex' points and discard concave points (using back tracking)
+ for (; i != originalPoints.size(); i++)
+ {
+ bool isConvex = false;
+ while (!isConvex&& hull.size()>1) {
+ b3Vector3& a = hull[hull.size()-2];
+ b3Vector3& b = hull[hull.size()-1];
+ isConvex = b3Cross(a-b,a-originalPoints[i]).dot(normalAxis)> 0;
+ if (!isConvex)
+ hull.pop_back();
+ else
+ hull.push_back(originalPoints[i]);
+ }
+ }
+}
+
+#endif //B3_GRAHAM_SCAN_2D_CONVEX_HULL_H
diff --git a/thirdparty/bullet/src/Bullet3Geometry/premake4.lua b/thirdparty/bullet/src/Bullet3Geometry/premake4.lua
new file mode 100644
index 0000000000..1a230f8c01
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Geometry/premake4.lua
@@ -0,0 +1,13 @@
+ project "Bullet3Geometry"
+
+ language "C++"
+
+ kind "StaticLib"
+
+ includedirs {".."}
+
+
+ files {
+ "**.cpp",
+ "**.h"
+ } \ No newline at end of file
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/b3GpuBroadphaseInterface.h b/thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/b3GpuBroadphaseInterface.h
new file mode 100644
index 0000000000..0ed8aa8232
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/b3GpuBroadphaseInterface.h
@@ -0,0 +1,44 @@
+
+#ifndef B3_GPU_BROADPHASE_INTERFACE_H
+#define B3_GPU_BROADPHASE_INTERFACE_H
+
+#include "Bullet3OpenCL/Initialize/b3OpenCLInclude.h"
+#include "Bullet3Common/b3Vector3.h"
+#include "b3SapAabb.h"
+#include "Bullet3Common/shared/b3Int2.h"
+#include "Bullet3Common/shared/b3Int4.h"
+#include "Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h"
+
+class b3GpuBroadphaseInterface
+{
+public:
+
+ typedef class b3GpuBroadphaseInterface* (CreateFunc)(cl_context ctx,cl_device_id device, cl_command_queue q);
+
+ virtual ~b3GpuBroadphaseInterface()
+ {
+ }
+
+ virtual void createProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr , int collisionFilterGroup, int collisionFilterMask)=0;
+ virtual void createLargeProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr , int collisionFilterGroup, int collisionFilterMask)=0;
+
+ virtual void calculateOverlappingPairs(int maxPairs)=0;
+ virtual void calculateOverlappingPairsHost(int maxPairs)=0;
+
+ //call writeAabbsToGpu after done making all changes (createProxy etc)
+ virtual void writeAabbsToGpu()=0;
+
+ virtual cl_mem getAabbBufferWS()=0;
+ virtual int getNumOverlap()=0;
+ virtual cl_mem getOverlappingPairBuffer()=0;
+
+ virtual b3OpenCLArray<b3SapAabb>& getAllAabbsGPU()=0;
+ virtual b3AlignedObjectArray<b3SapAabb>& getAllAabbsCPU()=0;
+
+ virtual b3OpenCLArray<b3Int4>& getOverlappingPairsGPU() = 0;
+ virtual b3OpenCLArray<int>& getSmallAabbIndicesGPU() = 0;
+ virtual b3OpenCLArray<int>& getLargeAabbIndicesGPU() = 0;
+
+};
+
+#endif //B3_GPU_BROADPHASE_INTERFACE_H
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/b3GpuGridBroadphase.cpp b/thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/b3GpuGridBroadphase.cpp
new file mode 100644
index 0000000000..74d0c8056c
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/b3GpuGridBroadphase.cpp
@@ -0,0 +1,385 @@
+
+#include "b3GpuGridBroadphase.h"
+#include "Bullet3Geometry/b3AabbUtil.h"
+#include "kernels/gridBroadphaseKernels.h"
+#include "kernels/sapKernels.h"
+//#include "kernels/gridBroadphase.cl"
+
+
+#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
+#include "Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.h"
+
+
+
+#define B3_BROADPHASE_SAP_PATH "src/Bullet3OpenCL/BroadphaseCollision/kernels/sap.cl"
+#define B3_GRID_BROADPHASE_PATH "src/Bullet3OpenCL/BroadphaseCollision/kernels/gridBroadphase.cl"
+
+cl_kernel kCalcHashAABB;
+cl_kernel kClearCellStart;
+cl_kernel kFindCellStart;
+cl_kernel kFindOverlappingPairs;
+cl_kernel m_copyAabbsKernel;
+cl_kernel m_sap2Kernel;
+
+
+
+
+
+//int maxPairsPerBody = 64;
+int maxBodiesPerCell = 256;//??
+
+b3GpuGridBroadphase::b3GpuGridBroadphase(cl_context ctx,cl_device_id device, cl_command_queue q )
+:m_context(ctx),
+m_device(device),
+m_queue(q),
+m_allAabbsGPU1(ctx,q),
+m_smallAabbsMappingGPU(ctx,q),
+m_largeAabbsMappingGPU(ctx,q),
+m_gpuPairs(ctx,q),
+
+m_hashGpu(ctx,q),
+
+m_cellStartGpu(ctx,q),
+m_paramsGPU(ctx,q)
+{
+
+
+ b3Vector3 gridSize = b3MakeVector3(3,3,3);
+ b3Vector3 invGridSize = b3MakeVector3(1.f/gridSize[0],1.f/gridSize[1],1.f/gridSize[2]);
+
+ m_paramsCPU.m_gridSize[0] = 128;
+ m_paramsCPU.m_gridSize[1] = 128;
+ m_paramsCPU.m_gridSize[2] = 128;
+ m_paramsCPU.m_gridSize[3] = maxBodiesPerCell;
+ m_paramsCPU.setMaxBodiesPerCell(maxBodiesPerCell);
+ m_paramsCPU.m_invCellSize[0] = invGridSize[0];
+ m_paramsCPU.m_invCellSize[1] = invGridSize[1];
+ m_paramsCPU.m_invCellSize[2] = invGridSize[2];
+ m_paramsCPU.m_invCellSize[3] = 0.f;
+ m_paramsGPU.push_back(m_paramsCPU);
+
+ cl_int errNum=0;
+
+ {
+ const char* sapSrc = sapCL;
+ cl_program sapProg = b3OpenCLUtils::compileCLProgramFromString(m_context,m_device,sapSrc,&errNum,"",B3_BROADPHASE_SAP_PATH);
+ b3Assert(errNum==CL_SUCCESS);
+ m_copyAabbsKernel= b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,sapSrc, "copyAabbsKernel",&errNum,sapProg );
+ m_sap2Kernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,sapSrc, "computePairsKernelTwoArrays",&errNum,sapProg );
+ b3Assert(errNum==CL_SUCCESS);
+ }
+
+ {
+
+ cl_program gridProg = b3OpenCLUtils::compileCLProgramFromString(m_context,m_device,gridBroadphaseCL,&errNum,"",B3_GRID_BROADPHASE_PATH);
+ b3Assert(errNum==CL_SUCCESS);
+
+ kCalcHashAABB = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,gridBroadphaseCL, "kCalcHashAABB",&errNum,gridProg);
+ b3Assert(errNum==CL_SUCCESS);
+
+ kClearCellStart = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,gridBroadphaseCL, "kClearCellStart",&errNum,gridProg);
+ b3Assert(errNum==CL_SUCCESS);
+
+ kFindCellStart = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,gridBroadphaseCL, "kFindCellStart",&errNum,gridProg);
+ b3Assert(errNum==CL_SUCCESS);
+
+
+ kFindOverlappingPairs = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,gridBroadphaseCL, "kFindOverlappingPairs",&errNum,gridProg);
+ b3Assert(errNum==CL_SUCCESS);
+
+
+
+
+ }
+
+ m_sorter = new b3RadixSort32CL(m_context,m_device,m_queue);
+
+}
+b3GpuGridBroadphase::~b3GpuGridBroadphase()
+{
+ clReleaseKernel( kCalcHashAABB);
+ clReleaseKernel( kClearCellStart);
+ clReleaseKernel( kFindCellStart);
+ clReleaseKernel( kFindOverlappingPairs);
+ clReleaseKernel( m_sap2Kernel);
+ clReleaseKernel( m_copyAabbsKernel);
+
+
+
+ delete m_sorter;
+}
+
+
+
+void b3GpuGridBroadphase::createProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr , int collisionFilterGroup, int collisionFilterMask)
+{
+ b3SapAabb aabb;
+ aabb.m_minVec = aabbMin;
+ aabb.m_maxVec = aabbMax;
+ aabb.m_minIndices[3] = userPtr;
+ aabb.m_signedMaxIndices[3] = m_allAabbsCPU1.size();//NOT userPtr;
+ m_smallAabbsMappingCPU.push_back(m_allAabbsCPU1.size());
+
+ m_allAabbsCPU1.push_back(aabb);
+
+}
+void b3GpuGridBroadphase::createLargeProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr , int collisionFilterGroup, int collisionFilterMask)
+{
+ b3SapAabb aabb;
+ aabb.m_minVec = aabbMin;
+ aabb.m_maxVec = aabbMax;
+ aabb.m_minIndices[3] = userPtr;
+ aabb.m_signedMaxIndices[3] = m_allAabbsCPU1.size();//NOT userPtr;
+ m_largeAabbsMappingCPU.push_back(m_allAabbsCPU1.size());
+
+ m_allAabbsCPU1.push_back(aabb);
+}
+
+void b3GpuGridBroadphase::calculateOverlappingPairs(int maxPairs)
+{
+ B3_PROFILE("b3GpuGridBroadphase::calculateOverlappingPairs");
+
+
+ if (0)
+ {
+ calculateOverlappingPairsHost(maxPairs);
+ /*
+ b3AlignedObjectArray<b3Int4> cpuPairs;
+ m_gpuPairs.copyToHost(cpuPairs);
+ printf("host m_gpuPairs.size()=%d\n",m_gpuPairs.size());
+ for (int i=0;i<m_gpuPairs.size();i++)
+ {
+ printf("host pair %d = %d,%d\n",i,cpuPairs[i].x,cpuPairs[i].y);
+ }
+ */
+ return;
+ }
+
+
+
+
+
+ int numSmallAabbs = m_smallAabbsMappingGPU.size();
+
+ b3OpenCLArray<int> pairCount(m_context,m_queue);
+ pairCount.push_back(0);
+ m_gpuPairs.resize(maxPairs);//numSmallAabbs*maxPairsPerBody);
+
+ {
+ int numLargeAabbs = m_largeAabbsMappingGPU.size();
+ if (numLargeAabbs && numSmallAabbs)
+ {
+ B3_PROFILE("sap2Kernel");
+ b3BufferInfoCL bInfo[] = {
+ b3BufferInfoCL( m_allAabbsGPU1.getBufferCL() ),
+ b3BufferInfoCL( m_largeAabbsMappingGPU.getBufferCL() ),
+ b3BufferInfoCL( m_smallAabbsMappingGPU.getBufferCL() ),
+ b3BufferInfoCL( m_gpuPairs.getBufferCL() ),
+ b3BufferInfoCL(pairCount.getBufferCL())};
+ b3LauncherCL launcher(m_queue, m_sap2Kernel,"m_sap2Kernel");
+ launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst( numLargeAabbs );
+ launcher.setConst( numSmallAabbs);
+ launcher.setConst( 0 );//axis is not used
+ launcher.setConst( maxPairs );
+ //@todo: use actual maximum work item sizes of the device instead of hardcoded values
+ launcher.launch2D( numLargeAabbs, numSmallAabbs,4,64);
+
+ int numPairs = pairCount.at(0);
+
+ if (numPairs >maxPairs)
+ {
+ b3Error("Error running out of pairs: numPairs = %d, maxPairs = %d.\n", numPairs, maxPairs);
+ numPairs =maxPairs;
+ }
+ }
+ }
+
+
+
+
+ if (numSmallAabbs)
+ {
+ B3_PROFILE("gridKernel");
+ m_hashGpu.resize(numSmallAabbs);
+ {
+ B3_PROFILE("kCalcHashAABB");
+ b3LauncherCL launch(m_queue,kCalcHashAABB,"kCalcHashAABB");
+ launch.setConst(numSmallAabbs);
+ launch.setBuffer(m_allAabbsGPU1.getBufferCL());
+ launch.setBuffer(m_smallAabbsMappingGPU.getBufferCL());
+ launch.setBuffer(m_hashGpu.getBufferCL());
+ launch.setBuffer(this->m_paramsGPU.getBufferCL());
+ launch.launch1D(numSmallAabbs);
+ }
+
+ m_sorter->execute(m_hashGpu);
+
+ int numCells = this->m_paramsCPU.m_gridSize[0]*this->m_paramsCPU.m_gridSize[1]*this->m_paramsCPU.m_gridSize[2];
+ m_cellStartGpu.resize(numCells);
+ //b3AlignedObjectArray<int > cellStartCpu;
+
+
+ {
+ B3_PROFILE("kClearCellStart");
+ b3LauncherCL launch(m_queue,kClearCellStart,"kClearCellStart");
+ launch.setConst(numCells);
+ launch.setBuffer(m_cellStartGpu.getBufferCL());
+ launch.launch1D(numCells);
+ //m_cellStartGpu.copyToHost(cellStartCpu);
+ //printf("??\n");
+
+ }
+
+
+ {
+ B3_PROFILE("kFindCellStart");
+ b3LauncherCL launch(m_queue,kFindCellStart,"kFindCellStart");
+ launch.setConst(numSmallAabbs);
+ launch.setBuffer(m_hashGpu.getBufferCL());
+ launch.setBuffer(m_cellStartGpu.getBufferCL());
+ launch.launch1D(numSmallAabbs);
+ //m_cellStartGpu.copyToHost(cellStartCpu);
+ //printf("??\n");
+
+ }
+
+ {
+ B3_PROFILE("kFindOverlappingPairs");
+
+
+ b3LauncherCL launch(m_queue,kFindOverlappingPairs,"kFindOverlappingPairs");
+ launch.setConst(numSmallAabbs);
+ launch.setBuffer(m_allAabbsGPU1.getBufferCL());
+ launch.setBuffer(m_smallAabbsMappingGPU.getBufferCL());
+ launch.setBuffer(m_hashGpu.getBufferCL());
+ launch.setBuffer(m_cellStartGpu.getBufferCL());
+
+ launch.setBuffer(m_paramsGPU.getBufferCL());
+ //launch.setBuffer(0);
+ launch.setBuffer(pairCount.getBufferCL());
+ launch.setBuffer(m_gpuPairs.getBufferCL());
+
+ launch.setConst(maxPairs);
+ launch.launch1D(numSmallAabbs);
+
+
+ int numPairs = pairCount.at(0);
+ if (numPairs >maxPairs)
+ {
+ b3Error("Error running out of pairs: numPairs = %d, maxPairs = %d.\n", numPairs, maxPairs);
+ numPairs =maxPairs;
+ }
+
+ m_gpuPairs.resize(numPairs);
+
+ if (0)
+ {
+ b3AlignedObjectArray<b3Int4> pairsCpu;
+ m_gpuPairs.copyToHost(pairsCpu);
+
+ int sz = m_gpuPairs.size();
+ printf("m_gpuPairs.size()=%d\n",sz);
+ for (int i=0;i<m_gpuPairs.size();i++)
+ {
+ printf("pair %d = %d,%d\n",i,pairsCpu[i].x,pairsCpu[i].y);
+ }
+
+ printf("?!?\n");
+ }
+
+ }
+
+
+ }
+
+
+
+
+
+ //calculateOverlappingPairsHost(maxPairs);
+}
+void b3GpuGridBroadphase::calculateOverlappingPairsHost(int maxPairs)
+{
+
+ m_hostPairs.resize(0);
+ m_allAabbsGPU1.copyToHost(m_allAabbsCPU1);
+ for (int i=0;i<m_allAabbsCPU1.size();i++)
+ {
+ for (int j=i+1;j<m_allAabbsCPU1.size();j++)
+ {
+ if (b3TestAabbAgainstAabb2(m_allAabbsCPU1[i].m_minVec, m_allAabbsCPU1[i].m_maxVec,
+ m_allAabbsCPU1[j].m_minVec,m_allAabbsCPU1[j].m_maxVec))
+ {
+ b3Int4 pair;
+ int a = m_allAabbsCPU1[j].m_minIndices[3];
+ int b = m_allAabbsCPU1[i].m_minIndices[3];
+ if (a<=b)
+ {
+ pair.x = a;
+ pair.y = b;//store the original index in the unsorted aabb array
+ } else
+ {
+ pair.x = b;
+ pair.y = a;//store the original index in the unsorted aabb array
+ }
+
+ if (m_hostPairs.size()<maxPairs)
+ {
+ m_hostPairs.push_back(pair);
+ }
+ }
+ }
+ }
+
+
+ m_gpuPairs.copyFromHost(m_hostPairs);
+
+
+}
+
+ //call writeAabbsToGpu after done making all changes (createProxy etc)
+void b3GpuGridBroadphase::writeAabbsToGpu()
+{
+ m_allAabbsGPU1.copyFromHost(m_allAabbsCPU1);
+ m_smallAabbsMappingGPU.copyFromHost(m_smallAabbsMappingCPU);
+ m_largeAabbsMappingGPU.copyFromHost(m_largeAabbsMappingCPU);
+
+}
+
+cl_mem b3GpuGridBroadphase::getAabbBufferWS()
+{
+ return this->m_allAabbsGPU1.getBufferCL();
+}
+int b3GpuGridBroadphase::getNumOverlap()
+{
+ return m_gpuPairs.size();
+}
+cl_mem b3GpuGridBroadphase::getOverlappingPairBuffer()
+{
+ return m_gpuPairs.getBufferCL();
+}
+
+b3OpenCLArray<b3SapAabb>& b3GpuGridBroadphase::getAllAabbsGPU()
+{
+ return m_allAabbsGPU1;
+}
+
+b3AlignedObjectArray<b3SapAabb>& b3GpuGridBroadphase::getAllAabbsCPU()
+{
+ return m_allAabbsCPU1;
+}
+
+b3OpenCLArray<b3Int4>& b3GpuGridBroadphase::getOverlappingPairsGPU()
+{
+ return m_gpuPairs;
+}
+b3OpenCLArray<int>& b3GpuGridBroadphase::getSmallAabbIndicesGPU()
+{
+ return m_smallAabbsMappingGPU;
+}
+b3OpenCLArray<int>& b3GpuGridBroadphase::getLargeAabbIndicesGPU()
+{
+ return m_largeAabbsMappingGPU;
+}
+
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/b3GpuGridBroadphase.h b/thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/b3GpuGridBroadphase.h
new file mode 100644
index 0000000000..ec18c9f716
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/b3GpuGridBroadphase.h
@@ -0,0 +1,88 @@
+#ifndef B3_GPU_GRID_BROADPHASE_H
+#define B3_GPU_GRID_BROADPHASE_H
+
+#include "b3GpuBroadphaseInterface.h"
+#include "Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.h"
+
+struct b3ParamsGridBroadphaseCL
+{
+
+ float m_invCellSize[4];
+ int m_gridSize[4];
+
+ int getMaxBodiesPerCell() const
+ {
+ return m_gridSize[3];
+ }
+
+ void setMaxBodiesPerCell(int maxOverlap)
+ {
+ m_gridSize[3] = maxOverlap;
+ }
+};
+
+
+class b3GpuGridBroadphase : public b3GpuBroadphaseInterface
+{
+protected:
+ cl_context m_context;
+ cl_device_id m_device;
+ cl_command_queue m_queue;
+
+ b3OpenCLArray<b3SapAabb> m_allAabbsGPU1;
+ b3AlignedObjectArray<b3SapAabb> m_allAabbsCPU1;
+
+ b3OpenCLArray<int> m_smallAabbsMappingGPU;
+ b3AlignedObjectArray<int> m_smallAabbsMappingCPU;
+
+ b3OpenCLArray<int> m_largeAabbsMappingGPU;
+ b3AlignedObjectArray<int> m_largeAabbsMappingCPU;
+
+ b3AlignedObjectArray<b3Int4> m_hostPairs;
+ b3OpenCLArray<b3Int4> m_gpuPairs;
+
+ b3OpenCLArray<b3SortData> m_hashGpu;
+ b3OpenCLArray<int> m_cellStartGpu;
+
+
+ b3ParamsGridBroadphaseCL m_paramsCPU;
+ b3OpenCLArray<b3ParamsGridBroadphaseCL> m_paramsGPU;
+
+ class b3RadixSort32CL* m_sorter;
+
+public:
+
+ b3GpuGridBroadphase(cl_context ctx,cl_device_id device, cl_command_queue q );
+ virtual ~b3GpuGridBroadphase();
+
+ static b3GpuBroadphaseInterface* CreateFunc(cl_context ctx,cl_device_id device, cl_command_queue q)
+ {
+ return new b3GpuGridBroadphase(ctx,device,q);
+ }
+
+
+
+
+ virtual void createProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr , int collisionFilterGroup, int collisionFilterMask);
+ virtual void createLargeProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr , int collisionFilterGroup, int collisionFilterMask);
+
+ virtual void calculateOverlappingPairs(int maxPairs);
+ virtual void calculateOverlappingPairsHost(int maxPairs);
+
+ //call writeAabbsToGpu after done making all changes (createProxy etc)
+ virtual void writeAabbsToGpu();
+
+ virtual cl_mem getAabbBufferWS();
+ virtual int getNumOverlap();
+ virtual cl_mem getOverlappingPairBuffer();
+
+ virtual b3OpenCLArray<b3SapAabb>& getAllAabbsGPU();
+ virtual b3AlignedObjectArray<b3SapAabb>& getAllAabbsCPU();
+
+ virtual b3OpenCLArray<b3Int4>& getOverlappingPairsGPU();
+ virtual b3OpenCLArray<int>& getSmallAabbIndicesGPU();
+ virtual b3OpenCLArray<int>& getLargeAabbIndicesGPU();
+
+};
+
+#endif //B3_GPU_GRID_BROADPHASE_H \ No newline at end of file
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvh.cpp b/thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvh.cpp
new file mode 100644
index 0000000000..641df9eb12
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvh.cpp
@@ -0,0 +1,577 @@
+/*
+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.
+*/
+//Initial Author Jackson Lee, 2014
+
+#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
+#include "Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.h"
+
+#include "b3GpuParallelLinearBvh.h"
+
+b3GpuParallelLinearBvh::b3GpuParallelLinearBvh(cl_context context, cl_device_id device, cl_command_queue queue) :
+ m_queue(queue),
+ m_radixSorter(context, device, queue),
+
+ m_rootNodeIndex(context, queue),
+ m_maxDistanceFromRoot(context, queue),
+ m_temp(context, queue),
+
+ m_internalNodeAabbs(context, queue),
+ m_internalNodeLeafIndexRanges(context, queue),
+ m_internalNodeChildNodes(context, queue),
+ m_internalNodeParentNodes(context, queue),
+
+ m_commonPrefixes(context, queue),
+ m_commonPrefixLengths(context, queue),
+ m_distanceFromRoot(context, queue),
+
+ m_leafNodeParentNodes(context, queue),
+ m_mortonCodesAndAabbIndicies(context, queue),
+ m_mergedAabb(context, queue),
+ m_leafNodeAabbs(context, queue),
+
+ m_largeAabbs(context, queue)
+{
+ m_rootNodeIndex.resize(1);
+ m_maxDistanceFromRoot.resize(1);
+ m_temp.resize(1);
+
+ //
+ const char CL_PROGRAM_PATH[] = "src/Bullet3OpenCL/BroadphaseCollision/kernels/parallelLinearBvh.cl";
+
+ const char* kernelSource = parallelLinearBvhCL; //parallelLinearBvhCL.h
+ cl_int error;
+ char* additionalMacros = 0;
+ m_parallelLinearBvhProgram = b3OpenCLUtils::compileCLProgramFromString(context, device, kernelSource, &error, additionalMacros, CL_PROGRAM_PATH);
+ b3Assert(m_parallelLinearBvhProgram);
+
+ m_separateAabbsKernel = b3OpenCLUtils::compileCLKernelFromString( context, device, kernelSource, "separateAabbs", &error, m_parallelLinearBvhProgram, additionalMacros );
+ b3Assert(m_separateAabbsKernel);
+ m_findAllNodesMergedAabbKernel = b3OpenCLUtils::compileCLKernelFromString( context, device, kernelSource, "findAllNodesMergedAabb", &error, m_parallelLinearBvhProgram, additionalMacros );
+ b3Assert(m_findAllNodesMergedAabbKernel);
+ m_assignMortonCodesAndAabbIndiciesKernel = b3OpenCLUtils::compileCLKernelFromString( context, device, kernelSource, "assignMortonCodesAndAabbIndicies", &error, m_parallelLinearBvhProgram, additionalMacros );
+ b3Assert(m_assignMortonCodesAndAabbIndiciesKernel);
+
+ m_computeAdjacentPairCommonPrefixKernel = b3OpenCLUtils::compileCLKernelFromString( context, device, kernelSource, "computeAdjacentPairCommonPrefix", &error, m_parallelLinearBvhProgram, additionalMacros );
+ b3Assert(m_computeAdjacentPairCommonPrefixKernel);
+ m_buildBinaryRadixTreeLeafNodesKernel = b3OpenCLUtils::compileCLKernelFromString( context, device, kernelSource, "buildBinaryRadixTreeLeafNodes", &error, m_parallelLinearBvhProgram, additionalMacros );
+ b3Assert(m_buildBinaryRadixTreeLeafNodesKernel);
+ m_buildBinaryRadixTreeInternalNodesKernel = b3OpenCLUtils::compileCLKernelFromString( context, device, kernelSource, "buildBinaryRadixTreeInternalNodes", &error, m_parallelLinearBvhProgram, additionalMacros );
+ b3Assert(m_buildBinaryRadixTreeInternalNodesKernel);
+ m_findDistanceFromRootKernel = b3OpenCLUtils::compileCLKernelFromString( context, device, kernelSource, "findDistanceFromRoot", &error, m_parallelLinearBvhProgram, additionalMacros );
+ b3Assert(m_findDistanceFromRootKernel);
+ m_buildBinaryRadixTreeAabbsRecursiveKernel = b3OpenCLUtils::compileCLKernelFromString( context, device, kernelSource, "buildBinaryRadixTreeAabbsRecursive", &error, m_parallelLinearBvhProgram, additionalMacros );
+ b3Assert(m_buildBinaryRadixTreeAabbsRecursiveKernel);
+
+ m_findLeafIndexRangesKernel = b3OpenCLUtils::compileCLKernelFromString( context, device, kernelSource, "findLeafIndexRanges", &error, m_parallelLinearBvhProgram, additionalMacros );
+ b3Assert(m_findLeafIndexRangesKernel);
+
+ m_plbvhCalculateOverlappingPairsKernel = b3OpenCLUtils::compileCLKernelFromString( context, device, kernelSource, "plbvhCalculateOverlappingPairs", &error, m_parallelLinearBvhProgram, additionalMacros );
+ b3Assert(m_plbvhCalculateOverlappingPairsKernel);
+ m_plbvhRayTraverseKernel = b3OpenCLUtils::compileCLKernelFromString( context, device, kernelSource, "plbvhRayTraverse", &error, m_parallelLinearBvhProgram, additionalMacros );
+ b3Assert(m_plbvhRayTraverseKernel);
+ m_plbvhLargeAabbAabbTestKernel = b3OpenCLUtils::compileCLKernelFromString( context, device, kernelSource, "plbvhLargeAabbAabbTest", &error, m_parallelLinearBvhProgram, additionalMacros );
+ b3Assert(m_plbvhLargeAabbAabbTestKernel);
+ m_plbvhLargeAabbRayTestKernel = b3OpenCLUtils::compileCLKernelFromString( context, device, kernelSource, "plbvhLargeAabbRayTest", &error, m_parallelLinearBvhProgram, additionalMacros );
+ b3Assert(m_plbvhLargeAabbRayTestKernel);
+}
+
+b3GpuParallelLinearBvh::~b3GpuParallelLinearBvh()
+{
+ clReleaseKernel(m_separateAabbsKernel);
+ clReleaseKernel(m_findAllNodesMergedAabbKernel);
+ clReleaseKernel(m_assignMortonCodesAndAabbIndiciesKernel);
+
+ clReleaseKernel(m_computeAdjacentPairCommonPrefixKernel);
+ clReleaseKernel(m_buildBinaryRadixTreeLeafNodesKernel);
+ clReleaseKernel(m_buildBinaryRadixTreeInternalNodesKernel);
+ clReleaseKernel(m_findDistanceFromRootKernel);
+ clReleaseKernel(m_buildBinaryRadixTreeAabbsRecursiveKernel);
+
+ clReleaseKernel(m_findLeafIndexRangesKernel);
+
+ clReleaseKernel(m_plbvhCalculateOverlappingPairsKernel);
+ clReleaseKernel(m_plbvhRayTraverseKernel);
+ clReleaseKernel(m_plbvhLargeAabbAabbTestKernel);
+ clReleaseKernel(m_plbvhLargeAabbRayTestKernel);
+
+ clReleaseProgram(m_parallelLinearBvhProgram);
+}
+
+void b3GpuParallelLinearBvh::build(const b3OpenCLArray<b3SapAabb>& worldSpaceAabbs, const b3OpenCLArray<int>& smallAabbIndices,
+ const b3OpenCLArray<int>& largeAabbIndices)
+{
+ B3_PROFILE("b3ParallelLinearBvh::build()");
+
+ int numLargeAabbs = largeAabbIndices.size();
+ int numSmallAabbs = smallAabbIndices.size();
+
+ //Since all AABBs(both large and small) are input as a contiguous array,
+ //with 2 additional arrays used to indicate the indices of large and small AABBs,
+ //it is necessary to separate the AABBs so that the large AABBs will not degrade the quality of the BVH.
+ {
+ B3_PROFILE("Separate large and small AABBs");
+
+ m_largeAabbs.resize(numLargeAabbs);
+ m_leafNodeAabbs.resize(numSmallAabbs);
+
+ //Write large AABBs into m_largeAabbs
+ {
+ b3BufferInfoCL bufferInfo[] =
+ {
+ b3BufferInfoCL( worldSpaceAabbs.getBufferCL() ),
+ b3BufferInfoCL( largeAabbIndices.getBufferCL() ),
+
+ b3BufferInfoCL( m_largeAabbs.getBufferCL() )
+ };
+
+ b3LauncherCL launcher(m_queue, m_separateAabbsKernel, "m_separateAabbsKernel");
+ launcher.setBuffers( bufferInfo, sizeof(bufferInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst(numLargeAabbs);
+
+ launcher.launch1D(numLargeAabbs);
+ }
+
+ //Write small AABBs into m_leafNodeAabbs
+ {
+ b3BufferInfoCL bufferInfo[] =
+ {
+ b3BufferInfoCL( worldSpaceAabbs.getBufferCL() ),
+ b3BufferInfoCL( smallAabbIndices.getBufferCL() ),
+
+ b3BufferInfoCL( m_leafNodeAabbs.getBufferCL() )
+ };
+
+ b3LauncherCL launcher(m_queue, m_separateAabbsKernel, "m_separateAabbsKernel");
+ launcher.setBuffers( bufferInfo, sizeof(bufferInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst(numSmallAabbs);
+
+ launcher.launch1D(numSmallAabbs);
+ }
+
+ clFinish(m_queue);
+ }
+
+ //
+ int numLeaves = numSmallAabbs; //Number of leaves in the BVH == Number of rigid bodies with small AABBs
+ int numInternalNodes = numLeaves - 1;
+
+ if(numLeaves < 2)
+ {
+ //Number of leaf nodes is checked in calculateOverlappingPairs() and testRaysAgainstBvhAabbs(),
+ //so it does not matter if numLeaves == 0 and rootNodeIndex == -1
+ int rootNodeIndex = numLeaves - 1;
+ m_rootNodeIndex.copyFromHostPointer(&rootNodeIndex, 1);
+
+ //Since the AABBs need to be rearranged(sorted) for the BVH construction algorithm,
+ //m_mortonCodesAndAabbIndicies.m_value is used to map a sorted AABB index to the unsorted AABB index
+ //instead of directly moving the AABBs. It needs to be set for the ray cast traversal kernel to work.
+ //( m_mortonCodesAndAabbIndicies[].m_value == unsorted index == index of m_leafNodeAabbs )
+ if(numLeaves == 1)
+ {
+ b3SortData leaf;
+ leaf.m_value = 0; //1 leaf so index is always 0; leaf.m_key does not need to be set
+
+ m_mortonCodesAndAabbIndicies.resize(1);
+ m_mortonCodesAndAabbIndicies.copyFromHostPointer(&leaf, 1);
+ }
+
+ return;
+ }
+
+ //
+ {
+ m_internalNodeAabbs.resize(numInternalNodes);
+ m_internalNodeLeafIndexRanges.resize(numInternalNodes);
+ m_internalNodeChildNodes.resize(numInternalNodes);
+ m_internalNodeParentNodes.resize(numInternalNodes);
+
+ m_commonPrefixes.resize(numInternalNodes);
+ m_commonPrefixLengths.resize(numInternalNodes);
+ m_distanceFromRoot.resize(numInternalNodes);
+
+ m_leafNodeParentNodes.resize(numLeaves);
+ m_mortonCodesAndAabbIndicies.resize(numLeaves);
+ m_mergedAabb.resize(numLeaves);
+ }
+
+ //Find the merged AABB of all small AABBs; this is used to define the size of
+ //each cell in the virtual grid for the next kernel(2^10 cells in each dimension).
+ {
+ B3_PROFILE("Find AABB of merged nodes");
+
+ m_mergedAabb.copyFromOpenCLArray(m_leafNodeAabbs); //Need to make a copy since the kernel modifies the array
+
+ for(int numAabbsNeedingMerge = numLeaves; numAabbsNeedingMerge >= 2;
+ numAabbsNeedingMerge = numAabbsNeedingMerge / 2 + numAabbsNeedingMerge % 2)
+ {
+ b3BufferInfoCL bufferInfo[] =
+ {
+ b3BufferInfoCL( m_mergedAabb.getBufferCL() ) //Resulting AABB is stored in m_mergedAabb[0]
+ };
+
+ b3LauncherCL launcher(m_queue, m_findAllNodesMergedAabbKernel, "m_findAllNodesMergedAabbKernel");
+ launcher.setBuffers( bufferInfo, sizeof(bufferInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst(numAabbsNeedingMerge);
+
+ launcher.launch1D(numAabbsNeedingMerge);
+ }
+
+ clFinish(m_queue);
+ }
+
+ //Insert the center of the AABBs into a virtual grid,
+ //then convert the discrete grid coordinates into a morton code
+ //For each element in m_mortonCodesAndAabbIndicies, set
+ // m_key == morton code (value to sort by)
+ // m_value == small AABB index
+ {
+ B3_PROFILE("Assign morton codes");
+
+ b3BufferInfoCL bufferInfo[] =
+ {
+ b3BufferInfoCL( m_leafNodeAabbs.getBufferCL() ),
+ b3BufferInfoCL( m_mergedAabb.getBufferCL() ),
+ b3BufferInfoCL( m_mortonCodesAndAabbIndicies.getBufferCL() )
+ };
+
+ b3LauncherCL launcher(m_queue, m_assignMortonCodesAndAabbIndiciesKernel, "m_assignMortonCodesAndAabbIndiciesKernel");
+ launcher.setBuffers( bufferInfo, sizeof(bufferInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst(numLeaves);
+
+ launcher.launch1D(numLeaves);
+ clFinish(m_queue);
+ }
+
+ //
+ {
+ B3_PROFILE("Sort leaves by morton codes");
+
+ m_radixSorter.execute(m_mortonCodesAndAabbIndicies);
+ clFinish(m_queue);
+ }
+
+ //
+ constructBinaryRadixTree();
+
+
+ //Since it is a sorted binary radix tree, each internal node contains a contiguous subset of leaf node indices.
+ //The root node contains leaf node indices in the range [0, numLeafNodes - 1].
+ //The child nodes of each node split their parent's index range into 2 contiguous halves.
+ //
+ //For example, if the root has indices [0, 31], its children might partition that range into [0, 11] and [12, 31].
+ //The next level in the tree could then split those ranges into [0, 2], [3, 11], [12, 22], and [23, 31].
+ //
+ //This property can be used for optimizing calculateOverlappingPairs(), to avoid testing each AABB pair twice
+ {
+ B3_PROFILE("m_findLeafIndexRangesKernel");
+
+ b3BufferInfoCL bufferInfo[] =
+ {
+ b3BufferInfoCL( m_internalNodeChildNodes.getBufferCL() ),
+ b3BufferInfoCL( m_internalNodeLeafIndexRanges.getBufferCL() )
+ };
+
+ b3LauncherCL launcher(m_queue, m_findLeafIndexRangesKernel, "m_findLeafIndexRangesKernel");
+ launcher.setBuffers( bufferInfo, sizeof(bufferInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst(numInternalNodes);
+
+ launcher.launch1D(numInternalNodes);
+ clFinish(m_queue);
+ }
+}
+
+void b3GpuParallelLinearBvh::calculateOverlappingPairs(b3OpenCLArray<b3Int4>& out_overlappingPairs)
+{
+ int maxPairs = out_overlappingPairs.size();
+ b3OpenCLArray<int>& numPairsGpu = m_temp;
+
+ int reset = 0;
+ numPairsGpu.copyFromHostPointer(&reset, 1);
+
+ //
+ if( m_leafNodeAabbs.size() > 1 )
+ {
+ B3_PROFILE("PLBVH small-small AABB test");
+
+ int numQueryAabbs = m_leafNodeAabbs.size();
+
+ b3BufferInfoCL bufferInfo[] =
+ {
+ b3BufferInfoCL( m_leafNodeAabbs.getBufferCL() ),
+
+ b3BufferInfoCL( m_rootNodeIndex.getBufferCL() ),
+ b3BufferInfoCL( m_internalNodeChildNodes.getBufferCL() ),
+ b3BufferInfoCL( m_internalNodeAabbs.getBufferCL() ),
+ b3BufferInfoCL( m_internalNodeLeafIndexRanges.getBufferCL() ),
+ b3BufferInfoCL( m_mortonCodesAndAabbIndicies.getBufferCL() ),
+
+ b3BufferInfoCL( numPairsGpu.getBufferCL() ),
+ b3BufferInfoCL( out_overlappingPairs.getBufferCL() )
+ };
+
+ b3LauncherCL launcher(m_queue, m_plbvhCalculateOverlappingPairsKernel, "m_plbvhCalculateOverlappingPairsKernel");
+ launcher.setBuffers( bufferInfo, sizeof(bufferInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst(maxPairs);
+ launcher.setConst(numQueryAabbs);
+
+ launcher.launch1D(numQueryAabbs);
+ clFinish(m_queue);
+ }
+
+ int numLargeAabbRigids = m_largeAabbs.size();
+ if( numLargeAabbRigids > 0 && m_leafNodeAabbs.size() > 0 )
+ {
+ B3_PROFILE("PLBVH large-small AABB test");
+
+ int numQueryAabbs = m_leafNodeAabbs.size();
+
+ b3BufferInfoCL bufferInfo[] =
+ {
+ b3BufferInfoCL( m_leafNodeAabbs.getBufferCL() ),
+ b3BufferInfoCL( m_largeAabbs.getBufferCL() ),
+
+ b3BufferInfoCL( numPairsGpu.getBufferCL() ),
+ b3BufferInfoCL( out_overlappingPairs.getBufferCL() )
+ };
+
+ b3LauncherCL launcher(m_queue, m_plbvhLargeAabbAabbTestKernel, "m_plbvhLargeAabbAabbTestKernel");
+ launcher.setBuffers( bufferInfo, sizeof(bufferInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst(maxPairs);
+ launcher.setConst(numLargeAabbRigids);
+ launcher.setConst(numQueryAabbs);
+
+ launcher.launch1D(numQueryAabbs);
+ clFinish(m_queue);
+ }
+
+
+ //
+ int numPairs = -1;
+ numPairsGpu.copyToHostPointer(&numPairs, 1);
+ if(numPairs > maxPairs)
+ {
+ b3Error("Error running out of pairs: numPairs = %d, maxPairs = %d.\n", numPairs, maxPairs);
+ numPairs = maxPairs;
+ numPairsGpu.copyFromHostPointer(&maxPairs, 1);
+ }
+
+ out_overlappingPairs.resize(numPairs);
+}
+
+
+void b3GpuParallelLinearBvh::testRaysAgainstBvhAabbs(const b3OpenCLArray<b3RayInfo>& rays,
+ b3OpenCLArray<int>& out_numRayRigidPairs, b3OpenCLArray<b3Int2>& out_rayRigidPairs)
+{
+ B3_PROFILE("PLBVH testRaysAgainstBvhAabbs()");
+
+ int numRays = rays.size();
+ int maxRayRigidPairs = out_rayRigidPairs.size();
+
+ int reset = 0;
+ out_numRayRigidPairs.copyFromHostPointer(&reset, 1);
+
+ //
+ if( m_leafNodeAabbs.size() > 0 )
+ {
+ B3_PROFILE("PLBVH ray test small AABB");
+
+ b3BufferInfoCL bufferInfo[] =
+ {
+ b3BufferInfoCL( m_leafNodeAabbs.getBufferCL() ),
+
+ b3BufferInfoCL( m_rootNodeIndex.getBufferCL() ),
+ b3BufferInfoCL( m_internalNodeChildNodes.getBufferCL() ),
+ b3BufferInfoCL( m_internalNodeAabbs.getBufferCL() ),
+ b3BufferInfoCL( m_internalNodeLeafIndexRanges.getBufferCL() ),
+ b3BufferInfoCL( m_mortonCodesAndAabbIndicies.getBufferCL() ),
+
+ b3BufferInfoCL( rays.getBufferCL() ),
+
+ b3BufferInfoCL( out_numRayRigidPairs.getBufferCL() ),
+ b3BufferInfoCL( out_rayRigidPairs.getBufferCL() )
+ };
+
+ b3LauncherCL launcher(m_queue, m_plbvhRayTraverseKernel, "m_plbvhRayTraverseKernel");
+ launcher.setBuffers( bufferInfo, sizeof(bufferInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst(maxRayRigidPairs);
+ launcher.setConst(numRays);
+
+ launcher.launch1D(numRays);
+ clFinish(m_queue);
+ }
+
+ int numLargeAabbRigids = m_largeAabbs.size();
+ if(numLargeAabbRigids > 0)
+ {
+ B3_PROFILE("PLBVH ray test large AABB");
+
+ b3BufferInfoCL bufferInfo[] =
+ {
+ b3BufferInfoCL( m_largeAabbs.getBufferCL() ),
+ b3BufferInfoCL( rays.getBufferCL() ),
+
+ b3BufferInfoCL( out_numRayRigidPairs.getBufferCL() ),
+ b3BufferInfoCL( out_rayRigidPairs.getBufferCL() )
+ };
+
+ b3LauncherCL launcher(m_queue, m_plbvhLargeAabbRayTestKernel, "m_plbvhLargeAabbRayTestKernel");
+ launcher.setBuffers( bufferInfo, sizeof(bufferInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst(numLargeAabbRigids);
+ launcher.setConst(maxRayRigidPairs);
+ launcher.setConst(numRays);
+
+ launcher.launch1D(numRays);
+ clFinish(m_queue);
+ }
+
+ //
+ int numRayRigidPairs = -1;
+ out_numRayRigidPairs.copyToHostPointer(&numRayRigidPairs, 1);
+
+ if(numRayRigidPairs > maxRayRigidPairs)
+ b3Error("Error running out of rayRigid pairs: numRayRigidPairs = %d, maxRayRigidPairs = %d.\n", numRayRigidPairs, maxRayRigidPairs);
+
+}
+
+void b3GpuParallelLinearBvh::constructBinaryRadixTree()
+{
+ B3_PROFILE("b3GpuParallelLinearBvh::constructBinaryRadixTree()");
+
+ int numLeaves = m_leafNodeAabbs.size();
+ int numInternalNodes = numLeaves - 1;
+
+ //Each internal node is placed in between 2 leaf nodes.
+ //By using this arrangement and computing the common prefix between
+ //these 2 adjacent leaf nodes, it is possible to quickly construct a binary radix tree.
+ {
+ B3_PROFILE("m_computeAdjacentPairCommonPrefixKernel");
+
+ b3BufferInfoCL bufferInfo[] =
+ {
+ b3BufferInfoCL( m_mortonCodesAndAabbIndicies.getBufferCL() ),
+ b3BufferInfoCL( m_commonPrefixes.getBufferCL() ),
+ b3BufferInfoCL( m_commonPrefixLengths.getBufferCL() )
+ };
+
+ b3LauncherCL launcher(m_queue, m_computeAdjacentPairCommonPrefixKernel, "m_computeAdjacentPairCommonPrefixKernel");
+ launcher.setBuffers( bufferInfo, sizeof(bufferInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst(numInternalNodes);
+
+ launcher.launch1D(numInternalNodes);
+ clFinish(m_queue);
+ }
+
+ //For each leaf node, select its parent node by
+ //comparing the 2 nearest internal nodes and assign child node indices
+ {
+ B3_PROFILE("m_buildBinaryRadixTreeLeafNodesKernel");
+
+ b3BufferInfoCL bufferInfo[] =
+ {
+ b3BufferInfoCL( m_commonPrefixLengths.getBufferCL() ),
+ b3BufferInfoCL( m_leafNodeParentNodes.getBufferCL() ),
+ b3BufferInfoCL( m_internalNodeChildNodes.getBufferCL() )
+ };
+
+ b3LauncherCL launcher(m_queue, m_buildBinaryRadixTreeLeafNodesKernel, "m_buildBinaryRadixTreeLeafNodesKernel");
+ launcher.setBuffers( bufferInfo, sizeof(bufferInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst(numLeaves);
+
+ launcher.launch1D(numLeaves);
+ clFinish(m_queue);
+ }
+
+ //For each internal node, perform 2 binary searches among the other internal nodes
+ //to its left and right to find its potential parent nodes and assign child node indices
+ {
+ B3_PROFILE("m_buildBinaryRadixTreeInternalNodesKernel");
+
+ b3BufferInfoCL bufferInfo[] =
+ {
+ b3BufferInfoCL( m_commonPrefixes.getBufferCL() ),
+ b3BufferInfoCL( m_commonPrefixLengths.getBufferCL() ),
+ b3BufferInfoCL( m_internalNodeChildNodes.getBufferCL() ),
+ b3BufferInfoCL( m_internalNodeParentNodes.getBufferCL() ),
+ b3BufferInfoCL( m_rootNodeIndex.getBufferCL() )
+ };
+
+ b3LauncherCL launcher(m_queue, m_buildBinaryRadixTreeInternalNodesKernel, "m_buildBinaryRadixTreeInternalNodesKernel");
+ launcher.setBuffers( bufferInfo, sizeof(bufferInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst(numInternalNodes);
+
+ launcher.launch1D(numInternalNodes);
+ clFinish(m_queue);
+ }
+
+ //Find the number of nodes seperating 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.
+ {
+ B3_PROFILE("m_findDistanceFromRootKernel");
+
+ b3BufferInfoCL bufferInfo[] =
+ {
+ b3BufferInfoCL( m_rootNodeIndex.getBufferCL() ),
+ b3BufferInfoCL( m_internalNodeParentNodes.getBufferCL() ),
+ b3BufferInfoCL( m_maxDistanceFromRoot.getBufferCL() ),
+ b3BufferInfoCL( m_distanceFromRoot.getBufferCL() )
+ };
+
+ b3LauncherCL launcher(m_queue, m_findDistanceFromRootKernel, "m_findDistanceFromRootKernel");
+ launcher.setBuffers( bufferInfo, sizeof(bufferInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst(numInternalNodes);
+
+ launcher.launch1D(numInternalNodes);
+ clFinish(m_queue);
+ }
+
+ //Starting from the internal nodes nearest to the leaf nodes, recursively move up
+ //the tree towards the root to set the AABBs of each internal node; each internal node
+ //checks its children and merges their AABBs
+ {
+ B3_PROFILE("m_buildBinaryRadixTreeAabbsRecursiveKernel");
+
+ int maxDistanceFromRoot = -1;
+ {
+ B3_PROFILE("copy maxDistanceFromRoot to CPU");
+ m_maxDistanceFromRoot.copyToHostPointer(&maxDistanceFromRoot, 1);
+ clFinish(m_queue);
+ }
+
+ for(int distanceFromRoot = maxDistanceFromRoot; distanceFromRoot >= 0; --distanceFromRoot)
+ {
+ b3BufferInfoCL bufferInfo[] =
+ {
+ b3BufferInfoCL( m_distanceFromRoot.getBufferCL() ),
+ b3BufferInfoCL( m_mortonCodesAndAabbIndicies.getBufferCL() ),
+ b3BufferInfoCL( m_internalNodeChildNodes.getBufferCL() ),
+ b3BufferInfoCL( m_leafNodeAabbs.getBufferCL() ),
+ b3BufferInfoCL( m_internalNodeAabbs.getBufferCL() )
+ };
+
+ b3LauncherCL launcher(m_queue, m_buildBinaryRadixTreeAabbsRecursiveKernel, "m_buildBinaryRadixTreeAabbsRecursiveKernel");
+ launcher.setBuffers( bufferInfo, sizeof(bufferInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst(maxDistanceFromRoot);
+ launcher.setConst(distanceFromRoot);
+ launcher.setConst(numInternalNodes);
+
+ //It may seem inefficent to launch a thread for each internal node when a
+ //much smaller number of nodes is actually processed, but this is actually
+ //faster than determining the exact nodes that are ready to merge their child AABBs.
+ launcher.launch1D(numInternalNodes);
+ }
+
+ clFinish(m_queue);
+ }
+}
+
+ \ No newline at end of file
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvh.h b/thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvh.h
new file mode 100644
index 0000000000..effe617b7b
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvh.h
@@ -0,0 +1,125 @@
+/*
+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.
+*/
+//Initial Author Jackson Lee, 2014
+
+#ifndef B3_GPU_PARALLEL_LINEAR_BVH_H
+#define B3_GPU_PARALLEL_LINEAR_BVH_H
+
+//#include "Bullet3Collision/BroadPhaseCollision/shared/b3Aabb.h"
+#include "Bullet3OpenCL/BroadphaseCollision/b3SapAabb.h"
+#include "Bullet3Common/shared/b3Int2.h"
+#include "Bullet3Common/shared/b3Int4.h"
+#include "Bullet3Collision/NarrowPhaseCollision/b3RaycastInfo.h"
+
+#include "Bullet3OpenCL/ParallelPrimitives/b3FillCL.h"
+#include "Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.h"
+#include "Bullet3OpenCL/ParallelPrimitives/b3PrefixScanCL.h"
+
+#include "Bullet3OpenCL/BroadphaseCollision/kernels/parallelLinearBvhKernels.h"
+
+#define b3Int64 cl_long
+
+///@brief GPU Parallel Linearized Bounding Volume Heirarchy(LBVH) that is reconstructed every frame
+///@remarks
+///See presentation in docs/b3GpuParallelLinearBvh.pdf for algorithm details.
+///@par
+///Related papers: \n
+///"Fast BVH Construction on GPUs" [Lauterbach et al. 2009] \n
+///"Maximizing Parallelism in the Construction of BVHs, Octrees, and k-d trees" [Karras 2012] \n
+///@par
+///The basic algorithm for building the BVH as presented in [Lauterbach et al. 2009] consists of 4 stages:
+/// - [fully parallel] Assign morton codes for each AABB using its center (after quantizing the AABB centers into a virtual grid)
+/// - [fully parallel] Sort morton codes
+/// - [somewhat parallel] Build binary radix tree (assign parent/child pointers for internal nodes of the BVH)
+/// - [somewhat parallel] Set internal node AABBs
+///@par
+///[Karras 2012] improves on the algorithm by introducing fully parallel methods for the last 2 stages.
+///The BVH implementation here shares many concepts with [Karras 2012], but a different method is used for constructing the tree.
+///Instead of searching for the child nodes of each internal node, we search for the parent node of each node.
+///Additionally, a non-atomic traversal that starts from the leaf nodes and moves towards the root node is used to set the AABBs.
+class b3GpuParallelLinearBvh
+{
+ cl_command_queue m_queue;
+
+ cl_program m_parallelLinearBvhProgram;
+
+ cl_kernel m_separateAabbsKernel;
+ cl_kernel m_findAllNodesMergedAabbKernel;
+ cl_kernel m_assignMortonCodesAndAabbIndiciesKernel;
+
+ //Binary radix tree construction kernels
+ cl_kernel m_computeAdjacentPairCommonPrefixKernel;
+ cl_kernel m_buildBinaryRadixTreeLeafNodesKernel;
+ cl_kernel m_buildBinaryRadixTreeInternalNodesKernel;
+ cl_kernel m_findDistanceFromRootKernel;
+ cl_kernel m_buildBinaryRadixTreeAabbsRecursiveKernel;
+
+ cl_kernel m_findLeafIndexRangesKernel;
+
+ //Traversal kernels
+ cl_kernel m_plbvhCalculateOverlappingPairsKernel;
+ cl_kernel m_plbvhRayTraverseKernel;
+ cl_kernel m_plbvhLargeAabbAabbTestKernel;
+ cl_kernel m_plbvhLargeAabbRayTestKernel;
+
+ b3RadixSort32CL m_radixSorter;
+
+ //1 element
+ b3OpenCLArray<int> m_rootNodeIndex; //Most significant bit(0x80000000) is set to indicate internal node
+ b3OpenCLArray<int> m_maxDistanceFromRoot; //Max number of internal nodes between an internal node and the root node
+ b3OpenCLArray<int> m_temp; //Used to hold the number of pairs in calculateOverlappingPairs()
+
+ //1 element per internal node (number_of_internal_nodes == number_of_leaves - 1)
+ b3OpenCLArray<b3SapAabb> m_internalNodeAabbs;
+ b3OpenCLArray<b3Int2> m_internalNodeLeafIndexRanges; //x == min leaf index, y == max leaf index
+ b3OpenCLArray<b3Int2> m_internalNodeChildNodes; //x == left child, y == right child; msb(0x80000000) is set to indicate internal node
+ b3OpenCLArray<int> m_internalNodeParentNodes; //For parent node index, msb(0x80000000) is not set since it is always internal
+
+ //1 element per internal node; for binary radix tree construction
+ b3OpenCLArray<b3Int64> m_commonPrefixes;
+ b3OpenCLArray<int> m_commonPrefixLengths;
+ b3OpenCLArray<int> m_distanceFromRoot; //Number of internal nodes between this node and the root
+
+ //1 element per leaf node (leaf nodes only include small AABBs)
+ b3OpenCLArray<int> m_leafNodeParentNodes; //For parent node index, msb(0x80000000) is not set since it is always internal
+ b3OpenCLArray<b3SortData> m_mortonCodesAndAabbIndicies; //m_key == morton code, m_value == aabb index in m_leafNodeAabbs
+ b3OpenCLArray<b3SapAabb> m_mergedAabb; //m_mergedAabb[0] contains the merged AABB of all leaf nodes
+ b3OpenCLArray<b3SapAabb> m_leafNodeAabbs; //Contains only small AABBs
+
+ //1 element per large AABB, which is not stored in the BVH
+ b3OpenCLArray<b3SapAabb> m_largeAabbs;
+
+public:
+ b3GpuParallelLinearBvh(cl_context context, cl_device_id device, cl_command_queue queue);
+ virtual ~b3GpuParallelLinearBvh();
+
+ ///Must be called before any other function
+ void build(const b3OpenCLArray<b3SapAabb>& worldSpaceAabbs, const b3OpenCLArray<int>& smallAabbIndices,
+ const b3OpenCLArray<int>& largeAabbIndices);
+
+ ///calculateOverlappingPairs() uses the worldSpaceAabbs parameter of b3GpuParallelLinearBvh::build() as the query AABBs.
+ ///@param out_overlappingPairs The size() of this array is used to determine the max number of pairs.
+ ///If the number of overlapping pairs is < out_overlappingPairs.size(), out_overlappingPairs is resized.
+ void calculateOverlappingPairs(b3OpenCLArray<b3Int4>& out_overlappingPairs);
+
+ ///@param out_numRigidRayPairs Array of length 1; contains the number of detected ray-rigid AABB intersections;
+ ///this value may be greater than out_rayRigidPairs.size() if out_rayRigidPairs is not large enough.
+ ///@param out_rayRigidPairs Contains an array of rays intersecting rigid AABBs; x == ray index, y == rigid body index.
+ ///If the size of this array is insufficient to hold all ray-rigid AABB intersections, additional intersections are discarded.
+ void testRaysAgainstBvhAabbs(const b3OpenCLArray<b3RayInfo>& rays,
+ b3OpenCLArray<int>& out_numRayRigidPairs, b3OpenCLArray<b3Int2>& out_rayRigidPairs);
+
+private:
+ void constructBinaryRadixTree();
+};
+
+#endif
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvhBroadphase.cpp b/thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvhBroadphase.cpp
new file mode 100644
index 0000000000..d2618024ac
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvhBroadphase.cpp
@@ -0,0 +1,80 @@
+/*
+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.
+*/
+//Initial Author Jackson Lee, 2014
+
+#include "b3GpuParallelLinearBvhBroadphase.h"
+
+b3GpuParallelLinearBvhBroadphase::b3GpuParallelLinearBvhBroadphase(cl_context context, cl_device_id device, cl_command_queue queue) :
+ m_plbvh(context, device, queue),
+
+ m_overlappingPairsGpu(context, queue),
+
+ m_aabbsGpu(context, queue),
+ m_smallAabbsMappingGpu(context, queue),
+ m_largeAabbsMappingGpu(context, queue)
+{
+}
+
+void b3GpuParallelLinearBvhBroadphase::createProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr, int collisionFilterGroup, int collisionFilterMask)
+{
+ int newAabbIndex = m_aabbsCpu.size();
+
+ b3SapAabb aabb;
+ aabb.m_minVec = aabbMin;
+ aabb.m_maxVec = aabbMax;
+
+ aabb.m_minIndices[3] = userPtr;
+ aabb.m_signedMaxIndices[3] = newAabbIndex;
+
+ m_smallAabbsMappingCpu.push_back(newAabbIndex);
+
+ m_aabbsCpu.push_back(aabb);
+}
+void b3GpuParallelLinearBvhBroadphase::createLargeProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr, int collisionFilterGroup, int collisionFilterMask)
+{
+ int newAabbIndex = m_aabbsCpu.size();
+
+ b3SapAabb aabb;
+ aabb.m_minVec = aabbMin;
+ aabb.m_maxVec = aabbMax;
+
+ aabb.m_minIndices[3] = userPtr;
+ aabb.m_signedMaxIndices[3] = newAabbIndex;
+
+ m_largeAabbsMappingCpu.push_back(newAabbIndex);
+
+ m_aabbsCpu.push_back(aabb);
+}
+
+void b3GpuParallelLinearBvhBroadphase::calculateOverlappingPairs(int maxPairs)
+{
+ //Reconstruct BVH
+ m_plbvh.build(m_aabbsGpu, m_smallAabbsMappingGpu, m_largeAabbsMappingGpu);
+
+ //
+ m_overlappingPairsGpu.resize(maxPairs);
+ m_plbvh.calculateOverlappingPairs(m_overlappingPairsGpu);
+}
+void b3GpuParallelLinearBvhBroadphase::calculateOverlappingPairsHost(int maxPairs)
+{
+ b3Assert(0); //CPU version not implemented
+}
+
+void b3GpuParallelLinearBvhBroadphase::writeAabbsToGpu()
+{
+ m_aabbsGpu.copyFromHost(m_aabbsCpu);
+ m_smallAabbsMappingGpu.copyFromHost(m_smallAabbsMappingCpu);
+ m_largeAabbsMappingGpu.copyFromHost(m_largeAabbsMappingCpu);
+}
+
+
+
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvhBroadphase.h b/thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvhBroadphase.h
new file mode 100644
index 0000000000..e518500637
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvhBroadphase.h
@@ -0,0 +1,66 @@
+/*
+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.
+*/
+//Initial Author Jackson Lee, 2014
+
+#ifndef B3_GPU_PARALLEL_LINEAR_BVH_BROADPHASE_H
+#define B3_GPU_PARALLEL_LINEAR_BVH_BROADPHASE_H
+
+#include "Bullet3OpenCL/BroadphaseCollision/b3GpuBroadphaseInterface.h"
+
+#include "b3GpuParallelLinearBvh.h"
+
+class b3GpuParallelLinearBvhBroadphase : public b3GpuBroadphaseInterface
+{
+ b3GpuParallelLinearBvh m_plbvh;
+
+ b3OpenCLArray<b3Int4> m_overlappingPairsGpu;
+
+ b3OpenCLArray<b3SapAabb> m_aabbsGpu;
+ b3OpenCLArray<int> m_smallAabbsMappingGpu;
+ b3OpenCLArray<int> m_largeAabbsMappingGpu;
+
+ b3AlignedObjectArray<b3SapAabb> m_aabbsCpu;
+ b3AlignedObjectArray<int> m_smallAabbsMappingCpu;
+ b3AlignedObjectArray<int> m_largeAabbsMappingCpu;
+
+public:
+ b3GpuParallelLinearBvhBroadphase(cl_context context, cl_device_id device, cl_command_queue queue);
+ virtual ~b3GpuParallelLinearBvhBroadphase() {}
+
+ virtual void createProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr, int collisionFilterGroup, int collisionFilterMask);
+ virtual void createLargeProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr, int collisionFilterGroup, int collisionFilterMask);
+
+ virtual void calculateOverlappingPairs(int maxPairs);
+ virtual void calculateOverlappingPairsHost(int maxPairs);
+
+ //call writeAabbsToGpu after done making all changes (createProxy etc)
+ virtual void writeAabbsToGpu();
+
+ virtual int getNumOverlap() { return m_overlappingPairsGpu.size(); }
+ virtual cl_mem getOverlappingPairBuffer() { return m_overlappingPairsGpu.getBufferCL(); }
+
+ virtual cl_mem getAabbBufferWS() { return m_aabbsGpu.getBufferCL(); }
+ virtual b3OpenCLArray<b3SapAabb>& getAllAabbsGPU() { return m_aabbsGpu; }
+
+ virtual b3OpenCLArray<b3Int4>& getOverlappingPairsGPU() { return m_overlappingPairsGpu; }
+ virtual b3OpenCLArray<int>& getSmallAabbIndicesGPU() { return m_smallAabbsMappingGpu; }
+ virtual b3OpenCLArray<int>& getLargeAabbIndicesGPU() { return m_largeAabbsMappingGpu; }
+
+ virtual b3AlignedObjectArray<b3SapAabb>& getAllAabbsCPU() { return m_aabbsCpu; }
+
+ static b3GpuBroadphaseInterface* CreateFunc(cl_context context, cl_device_id device, cl_command_queue queue)
+ {
+ return new b3GpuParallelLinearBvhBroadphase(context, device, queue);
+ }
+};
+
+#endif
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/b3GpuSapBroadphase.cpp b/thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/b3GpuSapBroadphase.cpp
new file mode 100644
index 0000000000..c45fbbdcaa
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/b3GpuSapBroadphase.cpp
@@ -0,0 +1,1366 @@
+
+bool searchIncremental3dSapOnGpu = true;
+#include <limits.h>
+#include "b3GpuSapBroadphase.h"
+#include "Bullet3Common/b3Vector3.h"
+#include "Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.h"
+#include "Bullet3OpenCL/ParallelPrimitives/b3PrefixScanFloat4CL.h"
+
+
+#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
+#include "kernels/sapKernels.h"
+
+#include "Bullet3Common/b3MinMax.h"
+
+#define B3_BROADPHASE_SAP_PATH "src/Bullet3OpenCL/BroadphaseCollision/kernels/sap.cl"
+
+/*
+
+
+
+
+
+
+ b3OpenCLArray<int> m_pairCount;
+
+
+ b3OpenCLArray<b3SapAabb> m_allAabbsGPU;
+ b3AlignedObjectArray<b3SapAabb> m_allAabbsCPU;
+
+ virtual b3OpenCLArray<b3SapAabb>& getAllAabbsGPU()
+ {
+ return m_allAabbsGPU;
+ }
+ virtual b3AlignedObjectArray<b3SapAabb>& getAllAabbsCPU()
+ {
+ return m_allAabbsCPU;
+ }
+
+ b3OpenCLArray<b3Vector3> m_sum;
+ b3OpenCLArray<b3Vector3> m_sum2;
+ b3OpenCLArray<b3Vector3> m_dst;
+
+ b3OpenCLArray<int> m_smallAabbsMappingGPU;
+ b3AlignedObjectArray<int> m_smallAabbsMappingCPU;
+
+ b3OpenCLArray<int> m_largeAabbsMappingGPU;
+ b3AlignedObjectArray<int> m_largeAabbsMappingCPU;
+
+
+ b3OpenCLArray<b3Int4> m_overlappingPairs;
+
+ //temporary gpu work memory
+ b3OpenCLArray<b3SortData> m_gpuSmallSortData;
+ b3OpenCLArray<b3SapAabb> m_gpuSmallSortedAabbs;
+
+ class b3PrefixScanFloat4CL* m_prefixScanFloat4;
+ */
+
+b3GpuSapBroadphase::b3GpuSapBroadphase(cl_context ctx,cl_device_id device, cl_command_queue q , b3GpuSapKernelType kernelType)
+:m_context(ctx),
+m_device(device),
+m_queue(q),
+
+m_objectMinMaxIndexGPUaxis0(ctx,q),
+m_objectMinMaxIndexGPUaxis1(ctx,q),
+m_objectMinMaxIndexGPUaxis2(ctx,q),
+m_objectMinMaxIndexGPUaxis0prev(ctx,q),
+m_objectMinMaxIndexGPUaxis1prev(ctx,q),
+m_objectMinMaxIndexGPUaxis2prev(ctx,q),
+m_sortedAxisGPU0(ctx,q),
+m_sortedAxisGPU1(ctx,q),
+m_sortedAxisGPU2(ctx,q),
+m_sortedAxisGPU0prev(ctx,q),
+m_sortedAxisGPU1prev(ctx,q),
+m_sortedAxisGPU2prev(ctx,q),
+m_addedHostPairsGPU(ctx,q),
+m_removedHostPairsGPU(ctx,q),
+m_addedCountGPU(ctx,q),
+m_removedCountGPU(ctx,q),
+m_currentBuffer(-1),
+m_pairCount(ctx,q),
+m_allAabbsGPU(ctx,q),
+m_sum(ctx,q),
+m_sum2(ctx,q),
+m_dst(ctx,q),
+m_smallAabbsMappingGPU(ctx,q),
+m_largeAabbsMappingGPU(ctx,q),
+m_overlappingPairs(ctx,q),
+m_gpuSmallSortData(ctx,q),
+m_gpuSmallSortedAabbs(ctx,q)
+{
+ const char* sapSrc = sapCL;
+
+
+ cl_int errNum=0;
+
+ b3Assert(m_context);
+ b3Assert(m_device);
+ cl_program sapProg = b3OpenCLUtils::compileCLProgramFromString(m_context,m_device,sapSrc,&errNum,"",B3_BROADPHASE_SAP_PATH);
+ b3Assert(errNum==CL_SUCCESS);
+
+
+ b3Assert(errNum==CL_SUCCESS);
+#ifndef __APPLE__
+ m_prefixScanFloat4 = new b3PrefixScanFloat4CL(m_context,m_device,m_queue);
+#else
+ m_prefixScanFloat4 = 0;
+#endif
+ m_sapKernel = 0;
+
+ switch (kernelType)
+ {
+ case B3_GPU_SAP_KERNEL_BRUTE_FORCE_CPU:
+ {
+ m_sapKernel=0;
+ break;
+ }
+ case B3_GPU_SAP_KERNEL_BRUTE_FORCE_GPU:
+ {
+ m_sapKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,sapSrc, "computePairsKernelBruteForce",&errNum,sapProg );
+ break;
+ }
+
+ case B3_GPU_SAP_KERNEL_ORIGINAL:
+ {
+ m_sapKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,sapSrc, "computePairsKernelOriginal",&errNum,sapProg );
+ break;
+ }
+ case B3_GPU_SAP_KERNEL_BARRIER:
+ {
+ m_sapKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,sapSrc, "computePairsKernelBarrier",&errNum,sapProg );
+ break;
+ }
+ case B3_GPU_SAP_KERNEL_LOCAL_SHARED_MEMORY:
+ {
+ m_sapKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,sapSrc, "computePairsKernelLocalSharedMemory",&errNum,sapProg );
+ break;
+ }
+
+ default:
+ {
+ m_sapKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,sapSrc, "computePairsKernelLocalSharedMemory",&errNum,sapProg );
+ b3Error("Unknown 3D GPU SAP provided, fallback to computePairsKernelLocalSharedMemory");
+ }
+ };
+
+
+
+ m_sap2Kernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,sapSrc, "computePairsKernelTwoArrays",&errNum,sapProg );
+ b3Assert(errNum==CL_SUCCESS);
+
+ m_prepareSumVarianceKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,sapSrc, "prepareSumVarianceKernel",&errNum,sapProg );
+ b3Assert(errNum==CL_SUCCESS);
+
+
+ m_flipFloatKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,sapSrc, "flipFloatKernel",&errNum,sapProg );
+
+ m_copyAabbsKernel= b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,sapSrc, "copyAabbsKernel",&errNum,sapProg );
+
+ m_scatterKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,sapSrc, "scatterKernel",&errNum,sapProg );
+
+ m_sorter = new b3RadixSort32CL(m_context,m_device,m_queue);
+}
+
+b3GpuSapBroadphase::~b3GpuSapBroadphase()
+{
+ delete m_sorter;
+ delete m_prefixScanFloat4;
+
+ clReleaseKernel(m_scatterKernel);
+ clReleaseKernel(m_flipFloatKernel);
+ clReleaseKernel(m_copyAabbsKernel);
+ clReleaseKernel(m_sapKernel);
+ clReleaseKernel(m_sap2Kernel);
+ clReleaseKernel(m_prepareSumVarianceKernel);
+
+
+}
+
+/// conservative test for overlap between two aabbs
+static bool TestAabbAgainstAabb2(const b3Vector3 &aabbMin1, const b3Vector3 &aabbMax1,
+ const b3Vector3 &aabbMin2, const b3Vector3 &aabbMax2)
+{
+ bool overlap = true;
+ overlap = (aabbMin1.getX() > aabbMax2.getX() || aabbMax1.getX() < aabbMin2.getX()) ? false : overlap;
+ overlap = (aabbMin1.getZ() > aabbMax2.getZ() || aabbMax1.getZ() < aabbMin2.getZ()) ? false : overlap;
+ overlap = (aabbMin1.getY() > aabbMax2.getY() || aabbMax1.getY() < aabbMin2.getY()) ? false : overlap;
+ return overlap;
+}
+
+
+
+//http://stereopsis.com/radix.html
+static unsigned int FloatFlip(float fl)
+{
+ unsigned int f = *(unsigned int*)&fl;
+ unsigned int mask = -(int)(f >> 31) | 0x80000000;
+ return f ^ mask;
+};
+
+void b3GpuSapBroadphase::init3dSap()
+{
+ if (m_currentBuffer<0)
+ {
+ m_allAabbsGPU.copyToHost(m_allAabbsCPU);
+
+ m_currentBuffer = 0;
+ for (int axis=0;axis<3;axis++)
+ {
+ for (int buf=0;buf<2;buf++)
+ {
+ int totalNumAabbs = m_allAabbsCPU.size();
+ int numEndPoints = 2*totalNumAabbs;
+ m_sortedAxisCPU[axis][buf].resize(numEndPoints);
+
+ if (buf==m_currentBuffer)
+ {
+ for (int i=0;i<totalNumAabbs;i++)
+ {
+ m_sortedAxisCPU[axis][buf][i*2].m_key = FloatFlip(m_allAabbsCPU[i].m_min[axis])-1;
+ m_sortedAxisCPU[axis][buf][i*2].m_value = i*2;
+ m_sortedAxisCPU[axis][buf][i*2+1].m_key = FloatFlip(m_allAabbsCPU[i].m_max[axis])+1;
+ m_sortedAxisCPU[axis][buf][i*2+1].m_value = i*2+1;
+ }
+ }
+ }
+ }
+
+ for (int axis=0;axis<3;axis++)
+ {
+ m_sorter->executeHost(m_sortedAxisCPU[axis][m_currentBuffer]);
+ }
+
+ for (int axis=0;axis<3;axis++)
+ {
+ //int totalNumAabbs = m_allAabbsCPU.size();
+ int numEndPoints = m_sortedAxisCPU[axis][m_currentBuffer].size();
+ m_objectMinMaxIndexCPU[axis][m_currentBuffer].resize(numEndPoints);
+ for (int i=0;i<numEndPoints;i++)
+ {
+ int destIndex = m_sortedAxisCPU[axis][m_currentBuffer][i].m_value;
+ int newDest = destIndex/2;
+ if (destIndex&1)
+ {
+ m_objectMinMaxIndexCPU[axis][m_currentBuffer][newDest].y=i;
+ } else
+ {
+ m_objectMinMaxIndexCPU[axis][m_currentBuffer][newDest].x=i;
+ }
+ }
+ }
+
+ }
+}
+
+
+static bool b3PairCmp(const b3Int4& p, const b3Int4& q)
+{
+ return ((p.x<q.x) || ((p.x==q.x) && (p.y<q.y)));
+}
+
+
+static bool operator==(const b3Int4& a,const b3Int4& b)
+{
+ return a.x == b.x && a.y == b.y;
+};
+
+static bool operator<(const b3Int4& a,const b3Int4& b)
+{
+ return a.x < b.x || (a.x == b.x && a.y < b.y);
+};
+
+static bool operator>(const b3Int4& a,const b3Int4& b)
+{
+ return a.x > b.x || (a.x == b.x && a.y > b.y);
+};
+
+b3AlignedObjectArray<b3Int4> addedHostPairs;
+b3AlignedObjectArray<b3Int4> removedHostPairs;
+
+b3AlignedObjectArray<b3SapAabb> preAabbs;
+
+void b3GpuSapBroadphase::calculateOverlappingPairsHostIncremental3Sap()
+{
+ //static int framepje = 0;
+ //printf("framepje=%d\n",framepje++);
+
+
+ B3_PROFILE("calculateOverlappingPairsHostIncremental3Sap");
+
+ addedHostPairs.resize(0);
+ removedHostPairs.resize(0);
+
+ b3Assert(m_currentBuffer>=0);
+
+ {
+ preAabbs.resize(m_allAabbsCPU.size());
+ for (int i=0;i<preAabbs.size();i++)
+ {
+ preAabbs[i]=m_allAabbsCPU[i];
+ }
+ }
+
+
+ if (m_currentBuffer<0)
+ return;
+ {
+ B3_PROFILE("m_allAabbsGPU.copyToHost");
+ m_allAabbsGPU.copyToHost(m_allAabbsCPU);
+ }
+
+ b3AlignedObjectArray<b3Int4> allPairs;
+ {
+ B3_PROFILE("m_overlappingPairs.copyToHost");
+ m_overlappingPairs.copyToHost(allPairs);
+ }
+ if (0)
+ {
+ {
+ printf("ab[40].min=%f,%f,%f,ab[40].max=%f,%f,%f\n",
+ m_allAabbsCPU[40].m_min[0], m_allAabbsCPU[40].m_min[1],m_allAabbsCPU[40].m_min[2],
+ m_allAabbsCPU[40].m_max[0], m_allAabbsCPU[40].m_max[1],m_allAabbsCPU[40].m_max[2]);
+ }
+
+ {
+ printf("ab[53].min=%f,%f,%f,ab[53].max=%f,%f,%f\n",
+ m_allAabbsCPU[53].m_min[0], m_allAabbsCPU[53].m_min[1],m_allAabbsCPU[53].m_min[2],
+ m_allAabbsCPU[53].m_max[0], m_allAabbsCPU[53].m_max[1],m_allAabbsCPU[53].m_max[2]);
+ }
+
+
+ {
+ b3Int4 newPair;
+ newPair.x = 40;
+ newPair.y = 53;
+ int index = allPairs.findBinarySearch(newPair);
+ printf("hasPair(40,53)=%d out of %d\n",index, allPairs.size());
+
+ {
+ int overlap = TestAabbAgainstAabb2((const b3Vector3&)m_allAabbsCPU[40].m_min, (const b3Vector3&)m_allAabbsCPU[40].m_max,(const b3Vector3&)m_allAabbsCPU[53].m_min,(const b3Vector3&)m_allAabbsCPU[53].m_max);
+ printf("overlap=%d\n",overlap);
+ }
+
+ if (preAabbs.size())
+ {
+ int prevOverlap = TestAabbAgainstAabb2((const b3Vector3&)preAabbs[40].m_min, (const b3Vector3&)preAabbs[40].m_max,(const b3Vector3&)preAabbs[53].m_min,(const b3Vector3&)preAabbs[53].m_max);
+ printf("prevoverlap=%d\n",prevOverlap);
+ } else
+ {
+ printf("unknown prevoverlap\n");
+ }
+
+ }
+ }
+
+
+ if (0)
+ {
+ for (int i=0;i<m_allAabbsCPU.size();i++)
+ {
+ //printf("aabb[%d] min=%f,%f,%f max=%f,%f,%f\n",i,m_allAabbsCPU[i].m_min[0],m_allAabbsCPU[i].m_min[1],m_allAabbsCPU[i].m_min[2], m_allAabbsCPU[i].m_max[0],m_allAabbsCPU[i].m_max[1],m_allAabbsCPU[i].m_max[2]);
+
+
+ }
+
+ for (int axis=0;axis<3;axis++)
+ {
+ for (int buf=0;buf<2;buf++)
+ {
+ b3Assert(m_sortedAxisCPU[axis][buf].size() == m_allAabbsCPU.size()*2);
+ }
+ }
+ }
+
+
+
+ m_currentBuffer = 1-m_currentBuffer;
+
+
+
+ int totalNumAabbs = m_allAabbsCPU.size();
+
+ {
+ B3_PROFILE("assign m_sortedAxisCPU(FloatFlip)");
+ for (int i=0;i<totalNumAabbs;i++)
+ {
+
+
+ unsigned int keyMin[3];
+ unsigned int keyMax[3];
+ for (int axis=0;axis<3;axis++)
+ {
+ float vmin=m_allAabbsCPU[i].m_min[axis];
+ float vmax = m_allAabbsCPU[i].m_max[axis];
+ keyMin[axis] = FloatFlip(vmin);
+ keyMax[axis] = FloatFlip(vmax);
+
+ m_sortedAxisCPU[axis][m_currentBuffer][i*2].m_key = keyMin[axis]-1;
+ m_sortedAxisCPU[axis][m_currentBuffer][i*2].m_value = i*2;
+ m_sortedAxisCPU[axis][m_currentBuffer][i*2+1].m_key = keyMax[axis]+1;
+ m_sortedAxisCPU[axis][m_currentBuffer][i*2+1].m_value = i*2+1;
+ }
+ //printf("aabb[%d] min=%u,%u,%u max %u,%u,%u\n", i,keyMin[0],keyMin[1],keyMin[2],keyMax[0],keyMax[1],keyMax[2]);
+
+ }
+ }
+
+
+
+ {
+ B3_PROFILE("sort m_sortedAxisCPU");
+ for (int axis=0;axis<3;axis++)
+ m_sorter->executeHost(m_sortedAxisCPU[axis][m_currentBuffer]);
+ }
+
+#if 0
+ if (0)
+ {
+ for (int axis=0;axis<3;axis++)
+ {
+ //printf("axis %d\n",axis);
+ for (int i=0;i<m_sortedAxisCPU[axis][m_currentBuffer].size();i++)
+ {
+ //int key = m_sortedAxisCPU[axis][m_currentBuffer][i].m_key;
+ //int value = m_sortedAxisCPU[axis][m_currentBuffer][i].m_value;
+ //printf("[%d]=%d\n",i,value);
+ }
+
+ }
+ }
+#endif
+
+ {
+ B3_PROFILE("assign m_objectMinMaxIndexCPU");
+ for (int axis=0;axis<3;axis++)
+ {
+ int totalNumAabbs = m_allAabbsCPU.size();
+ int numEndPoints = m_sortedAxisCPU[axis][m_currentBuffer].size();
+ m_objectMinMaxIndexCPU[axis][m_currentBuffer].resize(totalNumAabbs);
+ for (int i=0;i<numEndPoints;i++)
+ {
+ int destIndex = m_sortedAxisCPU[axis][m_currentBuffer][i].m_value;
+ int newDest = destIndex/2;
+ if (destIndex&1)
+ {
+ m_objectMinMaxIndexCPU[axis][m_currentBuffer][newDest].y=i;
+ } else
+ {
+ m_objectMinMaxIndexCPU[axis][m_currentBuffer][newDest].x=i;
+ }
+ }
+ }
+ }
+
+#if 0
+ if (0)
+ {
+ printf("==========================\n");
+ for (int axis=0;axis<3;axis++)
+ {
+ unsigned int curMinIndex40 = m_objectMinMaxIndexCPU[axis][m_currentBuffer][40].x;
+ unsigned int curMaxIndex40 = m_objectMinMaxIndexCPU[axis][m_currentBuffer][40].y;
+ unsigned int prevMaxIndex40 = m_objectMinMaxIndexCPU[axis][1-m_currentBuffer][40].y;
+ unsigned int prevMinIndex40 = m_objectMinMaxIndexCPU[axis][1-m_currentBuffer][40].x;
+
+ int dmin40 = curMinIndex40 - prevMinIndex40;
+ int dmax40 = curMinIndex40 - prevMinIndex40;
+ printf("axis %d curMinIndex40=%d prevMinIndex40=%d\n",axis,curMinIndex40, prevMinIndex40);
+ printf("axis %d curMaxIndex40=%d prevMaxIndex40=%d\n",axis,curMaxIndex40, prevMaxIndex40);
+ }
+ printf(".........................\n");
+ for (int axis=0;axis<3;axis++)
+ {
+ unsigned int curMinIndex53 = m_objectMinMaxIndexCPU[axis][m_currentBuffer][53].x;
+ unsigned int curMaxIndex53 = m_objectMinMaxIndexCPU[axis][m_currentBuffer][53].y;
+ unsigned int prevMaxIndex53 = m_objectMinMaxIndexCPU[axis][1-m_currentBuffer][53].y;
+ unsigned int prevMinIndex53 = m_objectMinMaxIndexCPU[axis][1-m_currentBuffer][53].x;
+
+ int dmin40 = curMinIndex53 - prevMinIndex53;
+ int dmax40 = curMinIndex53 - prevMinIndex53;
+ printf("axis %d curMinIndex53=%d prevMinIndex53=%d\n",axis,curMinIndex53, prevMinIndex53);
+ printf("axis %d curMaxIndex53=%d prevMaxIndex53=%d\n",axis,curMaxIndex53, prevMaxIndex53);
+ }
+
+ }
+#endif
+
+
+ int a = m_objectMinMaxIndexCPU[0][m_currentBuffer].size();
+ int b = m_objectMinMaxIndexCPU[1][m_currentBuffer].size();
+ int c = m_objectMinMaxIndexCPU[2][m_currentBuffer].size();
+ b3Assert(a==b);
+ b3Assert(b==c);
+ /*
+ if (searchIncremental3dSapOnGpu)
+ {
+ B3_PROFILE("computePairsIncremental3dSapKernelGPU");
+ int numObjects = m_objectMinMaxIndexCPU[0][m_currentBuffer].size();
+ int maxCapacity = 1024*1024;
+ {
+ B3_PROFILE("copy from host");
+ m_objectMinMaxIndexGPUaxis0.copyFromHost(m_objectMinMaxIndexCPU[0][m_currentBuffer]);
+ m_objectMinMaxIndexGPUaxis1.copyFromHost(m_objectMinMaxIndexCPU[1][m_currentBuffer]);
+ m_objectMinMaxIndexGPUaxis2.copyFromHost(m_objectMinMaxIndexCPU[2][m_currentBuffer]);
+ m_objectMinMaxIndexGPUaxis0prev.copyFromHost(m_objectMinMaxIndexCPU[0][1-m_currentBuffer]);
+ m_objectMinMaxIndexGPUaxis1prev.copyFromHost(m_objectMinMaxIndexCPU[1][1-m_currentBuffer]);
+ m_objectMinMaxIndexGPUaxis2prev.copyFromHost(m_objectMinMaxIndexCPU[2][1-m_currentBuffer]);
+
+ m_sortedAxisGPU0.copyFromHost(m_sortedAxisCPU[0][m_currentBuffer]);
+ m_sortedAxisGPU1.copyFromHost(m_sortedAxisCPU[1][m_currentBuffer]);
+ m_sortedAxisGPU2.copyFromHost(m_sortedAxisCPU[2][m_currentBuffer]);
+ m_sortedAxisGPU0prev.copyFromHost(m_sortedAxisCPU[0][1-m_currentBuffer]);
+ m_sortedAxisGPU1prev.copyFromHost(m_sortedAxisCPU[1][1-m_currentBuffer]);
+ m_sortedAxisGPU2prev.copyFromHost(m_sortedAxisCPU[2][1-m_currentBuffer]);
+
+
+ m_addedHostPairsGPU.resize(maxCapacity);
+ m_removedHostPairsGPU.resize(maxCapacity);
+
+ m_addedCountGPU.resize(0);
+ m_addedCountGPU.push_back(0);
+ m_removedCountGPU.resize(0);
+ m_removedCountGPU.push_back(0);
+ }
+
+ {
+ B3_PROFILE("launch1D");
+ b3LauncherCL launcher(m_queue, m_computePairsIncremental3dSapKernel,"m_computePairsIncremental3dSapKernel");
+ launcher.setBuffer(m_objectMinMaxIndexGPUaxis0.getBufferCL());
+ launcher.setBuffer(m_objectMinMaxIndexGPUaxis1.getBufferCL());
+ launcher.setBuffer(m_objectMinMaxIndexGPUaxis2.getBufferCL());
+ launcher.setBuffer(m_objectMinMaxIndexGPUaxis0prev.getBufferCL());
+ launcher.setBuffer(m_objectMinMaxIndexGPUaxis1prev.getBufferCL());
+ launcher.setBuffer(m_objectMinMaxIndexGPUaxis2prev.getBufferCL());
+
+ launcher.setBuffer(m_sortedAxisGPU0.getBufferCL());
+ launcher.setBuffer(m_sortedAxisGPU1.getBufferCL());
+ launcher.setBuffer(m_sortedAxisGPU2.getBufferCL());
+ launcher.setBuffer(m_sortedAxisGPU0prev.getBufferCL());
+ launcher.setBuffer(m_sortedAxisGPU1prev.getBufferCL());
+ launcher.setBuffer(m_sortedAxisGPU2prev.getBufferCL());
+
+
+ launcher.setBuffer(m_addedHostPairsGPU.getBufferCL());
+ launcher.setBuffer(m_removedHostPairsGPU.getBufferCL());
+ launcher.setBuffer(m_addedCountGPU.getBufferCL());
+ launcher.setBuffer(m_removedCountGPU.getBufferCL());
+ launcher.setConst(maxCapacity);
+ launcher.setConst( numObjects);
+ launcher.launch1D( numObjects);
+ clFinish(m_queue);
+ }
+
+ {
+ B3_PROFILE("copy to host");
+ int addedCountGPU = m_addedCountGPU.at(0);
+ m_addedHostPairsGPU.resize(addedCountGPU);
+ m_addedHostPairsGPU.copyToHost(addedHostPairs);
+
+ //printf("addedCountGPU=%d\n",addedCountGPU);
+ int removedCountGPU = m_removedCountGPU.at(0);
+ m_removedHostPairsGPU.resize(removedCountGPU);
+ m_removedHostPairsGPU.copyToHost(removedHostPairs);
+ //printf("removedCountGPU=%d\n",removedCountGPU);
+
+ }
+
+
+
+ }
+ else
+ */
+ {
+ int numObjects = m_objectMinMaxIndexCPU[0][m_currentBuffer].size();
+
+ B3_PROFILE("actual search");
+ for (int i=0;i<numObjects;i++)
+ {
+ //int numObjects = m_objectMinMaxIndexCPU[axis][m_currentBuffer].size();
+ //int checkObjects[]={40,53};
+ //int numCheckObjects = sizeof(checkObjects)/sizeof(int);
+
+ //for (int a=0;a<numCheckObjects ;a++)
+
+ for (int axis=0;axis<3;axis++)
+ {
+ //int i = checkObjects[a];
+
+ unsigned int curMinIndex = m_objectMinMaxIndexCPU[axis][m_currentBuffer][i].x;
+ unsigned int curMaxIndex = m_objectMinMaxIndexCPU[axis][m_currentBuffer][i].y;
+ unsigned int prevMinIndex = m_objectMinMaxIndexCPU[axis][1-m_currentBuffer][i].x;
+ int dmin = curMinIndex - prevMinIndex;
+
+ unsigned int prevMaxIndex = m_objectMinMaxIndexCPU[axis][1-m_currentBuffer][i].y;
+
+
+
+ int dmax = curMaxIndex - prevMaxIndex;
+ if (dmin!=0)
+ {
+ //printf("for object %d, dmin=%d\n",i,dmin);
+ }
+ if (dmax!=0)
+ {
+ //printf("for object %d, dmax=%d\n",i,dmax);
+ }
+ for (int otherbuffer = 0;otherbuffer<2;otherbuffer++)
+ {
+ if (dmin!=0)
+ {
+ int stepMin = dmin<0 ? -1 : 1;
+ for (int j=prevMinIndex;j!=curMinIndex;j+=stepMin)
+ {
+ int otherIndex2 = m_sortedAxisCPU[axis][otherbuffer][j].y;
+ int otherIndex = otherIndex2/2;
+ if (otherIndex!=i)
+ {
+ bool otherIsMax = ((otherIndex2&1)!=0);
+
+ if (otherIsMax)
+ {
+ //bool overlap = TestAabbAgainstAabb2((const b3Vector3&)m_allAabbsCPU[i].m_min, (const b3Vector3&)m_allAabbsCPU[i].m_max,(const b3Vector3&)m_allAabbsCPU[otherIndex].m_min,(const b3Vector3&)m_allAabbsCPU[otherIndex].m_max);
+ //bool prevOverlap = TestAabbAgainstAabb2((const b3Vector3&)preAabbs[i].m_min, (const b3Vector3&)preAabbs[i].m_max,(const b3Vector3&)preAabbs[otherIndex].m_min,(const b3Vector3&)preAabbs[otherIndex].m_max);
+
+ bool overlap = true;
+
+ for (int ax=0;ax<3;ax++)
+ {
+ if ((m_objectMinMaxIndexCPU[ax][m_currentBuffer][i].x > m_objectMinMaxIndexCPU[ax][m_currentBuffer][otherIndex].y) ||
+ (m_objectMinMaxIndexCPU[ax][m_currentBuffer][i].y < m_objectMinMaxIndexCPU[ax][m_currentBuffer][otherIndex].x))
+ overlap=false;
+ }
+
+ // b3Assert(overlap2==overlap);
+
+ bool prevOverlap = true;
+
+ for (int ax=0;ax<3;ax++)
+ {
+ if ((m_objectMinMaxIndexCPU[ax][1-m_currentBuffer][i].x > m_objectMinMaxIndexCPU[ax][1-m_currentBuffer][otherIndex].y) ||
+ (m_objectMinMaxIndexCPU[ax][1-m_currentBuffer][i].y < m_objectMinMaxIndexCPU[ax][1-m_currentBuffer][otherIndex].x))
+ prevOverlap=false;
+ }
+
+
+ //b3Assert(overlap==overlap2);
+
+
+
+ if (dmin<0)
+ {
+ if (overlap && !prevOverlap)
+ {
+ //add a pair
+ b3Int4 newPair;
+ if (i<=otherIndex)
+ {
+ newPair.x = i;
+ newPair.y = otherIndex;
+ } else
+ {
+ newPair.x = otherIndex;
+ newPair.y = i;
+ }
+ addedHostPairs.push_back(newPair);
+ }
+ }
+ else
+ {
+ if (!overlap && prevOverlap)
+ {
+
+ //remove a pair
+ b3Int4 removedPair;
+ if (i<=otherIndex)
+ {
+ removedPair.x = i;
+ removedPair.y = otherIndex;
+ } else
+ {
+ removedPair.x = otherIndex;
+ removedPair.y = i;
+ }
+ removedHostPairs.push_back(removedPair);
+ }
+ }//otherisMax
+ }//if (dmin<0)
+ }//if (otherIndex!=i)
+ }//for (int j=
+ }
+
+ if (dmax!=0)
+ {
+ int stepMax = dmax<0 ? -1 : 1;
+ for (int j=prevMaxIndex;j!=curMaxIndex;j+=stepMax)
+ {
+ int otherIndex2 = m_sortedAxisCPU[axis][otherbuffer][j].y;
+ int otherIndex = otherIndex2/2;
+ if (otherIndex!=i)
+ {
+ //bool otherIsMin = ((otherIndex2&1)==0);
+ //if (otherIsMin)
+ {
+ //bool overlap = TestAabbAgainstAabb2((const b3Vector3&)m_allAabbsCPU[i].m_min, (const b3Vector3&)m_allAabbsCPU[i].m_max,(const b3Vector3&)m_allAabbsCPU[otherIndex].m_min,(const b3Vector3&)m_allAabbsCPU[otherIndex].m_max);
+ //bool prevOverlap = TestAabbAgainstAabb2((const b3Vector3&)preAabbs[i].m_min, (const b3Vector3&)preAabbs[i].m_max,(const b3Vector3&)preAabbs[otherIndex].m_min,(const b3Vector3&)preAabbs[otherIndex].m_max);
+
+ bool overlap = true;
+
+ for (int ax=0;ax<3;ax++)
+ {
+ if ((m_objectMinMaxIndexCPU[ax][m_currentBuffer][i].x > m_objectMinMaxIndexCPU[ax][m_currentBuffer][otherIndex].y) ||
+ (m_objectMinMaxIndexCPU[ax][m_currentBuffer][i].y < m_objectMinMaxIndexCPU[ax][m_currentBuffer][otherIndex].x))
+ overlap=false;
+ }
+ //b3Assert(overlap2==overlap);
+
+ bool prevOverlap = true;
+
+ for (int ax=0;ax<3;ax++)
+ {
+ if ((m_objectMinMaxIndexCPU[ax][1-m_currentBuffer][i].x > m_objectMinMaxIndexCPU[ax][1-m_currentBuffer][otherIndex].y) ||
+ (m_objectMinMaxIndexCPU[ax][1-m_currentBuffer][i].y < m_objectMinMaxIndexCPU[ax][1-m_currentBuffer][otherIndex].x))
+ prevOverlap=false;
+ }
+
+
+ if (dmax>0)
+ {
+ if (overlap && !prevOverlap)
+ {
+ //add a pair
+ b3Int4 newPair;
+ if (i<=otherIndex)
+ {
+ newPair.x = i;
+ newPair.y = otherIndex;
+ } else
+ {
+ newPair.x = otherIndex;
+ newPair.y = i;
+ }
+ addedHostPairs.push_back(newPair);
+
+ }
+ }
+ else
+ {
+ if (!overlap && prevOverlap)
+ {
+ //if (otherIndex2&1==0) -> min?
+ //remove a pair
+ b3Int4 removedPair;
+ if (i<=otherIndex)
+ {
+ removedPair.x = i;
+ removedPair.y = otherIndex;
+ } else
+ {
+ removedPair.x = otherIndex;
+ removedPair.y = i;
+ }
+ removedHostPairs.push_back(removedPair);
+
+ }
+ }
+
+ }//if (dmin<0)
+ }//if (otherIndex!=i)
+ }//for (int j=
+ }
+ }//for (int otherbuffer
+ }//for (int axis=0;
+ }//for (int i=0;i<numObjects
+ }
+
+ //remove duplicates and add/remove then to existing m_overlappingPairs
+
+
+
+ {
+ {
+ B3_PROFILE("sort allPairs");
+ allPairs.quickSort(b3PairCmp);
+ }
+ {
+ B3_PROFILE("sort addedHostPairs");
+ addedHostPairs.quickSort(b3PairCmp);
+ }
+ {
+ B3_PROFILE("sort removedHostPairs");
+ removedHostPairs.quickSort(b3PairCmp);
+ }
+ }
+
+ b3Int4 prevPair;
+ prevPair.x = -1;
+ prevPair.y = -1;
+
+ int uniqueRemovedPairs = 0;
+
+ b3AlignedObjectArray<int> removedPositions;
+
+ {
+ B3_PROFILE("actual removing");
+ for (int i=0;i<removedHostPairs.size();i++)
+ {
+ b3Int4 removedPair = removedHostPairs[i];
+ if ((removedPair.x != prevPair.x) || (removedPair.y != prevPair.y))
+ {
+
+ int index1 = allPairs.findBinarySearch(removedPair);
+
+ //#ifdef _DEBUG
+
+
+
+ int index2 = allPairs.findLinearSearch(removedPair);
+ b3Assert(index1==index2);
+
+ //b3Assert(index1!=allPairs.size());
+ if (index1<allPairs.size())
+ //#endif//_DEBUG
+ {
+ uniqueRemovedPairs++;
+ removedPositions.push_back(index1);
+ {
+ //printf("framepje(%d) remove pair(%d):%d,%d\n",framepje,i,removedPair.x,removedPair.y);
+ }
+ }
+ }
+ prevPair = removedPair;
+ }
+
+ if (uniqueRemovedPairs)
+ {
+ for (int i=0;i<removedPositions.size();i++)
+ {
+ allPairs[removedPositions[i]].x = INT_MAX ;
+ allPairs[removedPositions[i]].y = INT_MAX ;
+ }
+ allPairs.quickSort(b3PairCmp);
+ allPairs.resize(allPairs.size()-uniqueRemovedPairs);
+ }
+ }
+ //if (uniqueRemovedPairs)
+ // printf("uniqueRemovedPairs=%d\n",uniqueRemovedPairs);
+ //printf("removedHostPairs.size = %d\n",removedHostPairs.size());
+
+ prevPair.x = -1;
+ prevPair.y = -1;
+
+ int uniqueAddedPairs=0;
+ b3AlignedObjectArray<b3Int4> actualAddedPairs;
+
+ {
+ B3_PROFILE("actual adding");
+ for (int i=0;i<addedHostPairs.size();i++)
+ {
+ b3Int4 newPair = addedHostPairs[i];
+ if ((newPair.x != prevPair.x) || (newPair.y != prevPair.y))
+ {
+//#ifdef _DEBUG
+ int index1 = allPairs.findBinarySearch(newPair);
+
+
+ int index2 = allPairs.findLinearSearch(newPair);
+ b3Assert(index1==index2);
+
+
+ b3Assert(index1==allPairs.size());
+ if (index1!=allPairs.size())
+ {
+ printf("??\n");
+ }
+
+ if (index1==allPairs.size())
+//#endif //_DEBUG
+ {
+ uniqueAddedPairs++;
+ actualAddedPairs.push_back(newPair);
+ }
+ }
+ prevPair = newPair;
+ }
+ for (int i=0;i<actualAddedPairs.size();i++)
+ {
+ //printf("framepje (%d), new pair(%d):%d,%d\n",framepje,i,actualAddedPairs[i].x,actualAddedPairs[i].y);
+ allPairs.push_back(actualAddedPairs[i]);
+ }
+ }
+
+ //if (uniqueAddedPairs)
+ // printf("uniqueAddedPairs=%d\n", uniqueAddedPairs);
+
+
+ {
+ B3_PROFILE("m_overlappingPairs.copyFromHost");
+ m_overlappingPairs.copyFromHost(allPairs);
+ }
+
+
+}
+
+
+
+
+void b3GpuSapBroadphase::calculateOverlappingPairsHost(int maxPairs)
+{
+ //test
+// if (m_currentBuffer>=0)
+ // return calculateOverlappingPairsHostIncremental3Sap();
+
+ b3Assert(m_allAabbsCPU.size() == m_allAabbsGPU.size());
+ m_allAabbsGPU.copyToHost(m_allAabbsCPU);
+
+
+
+ int axis=0;
+ {
+ B3_PROFILE("CPU compute best variance axis");
+ b3Vector3 s=b3MakeVector3(0,0,0),s2=b3MakeVector3(0,0,0);
+ int numRigidBodies = m_smallAabbsMappingCPU.size();
+
+ for(int i=0;i<numRigidBodies;i++)
+ {
+ b3SapAabb aabb = this->m_allAabbsCPU[m_smallAabbsMappingCPU[i]];
+
+ b3Vector3 maxAabb=b3MakeVector3(aabb.m_max[0],aabb.m_max[1],aabb.m_max[2]);
+ b3Vector3 minAabb=b3MakeVector3(aabb.m_min[0],aabb.m_min[1],aabb.m_min[2]);
+ b3Vector3 centerAabb=(maxAabb+minAabb)*0.5f;
+
+ s += centerAabb;
+ s2 += centerAabb*centerAabb;
+ }
+ b3Vector3 v = s2 - (s*s) / (float)numRigidBodies;
+
+ if(v[1] > v[0])
+ axis = 1;
+ if(v[2] > v[axis])
+ axis = 2;
+ }
+
+
+
+
+ b3AlignedObjectArray<b3Int4> hostPairs;
+
+ {
+ int numSmallAabbs = m_smallAabbsMappingCPU.size();
+ for (int i=0;i<numSmallAabbs;i++)
+ {
+ b3SapAabb smallAabbi = m_allAabbsCPU[m_smallAabbsMappingCPU[i]];
+ //float reference = smallAabbi.m_max[axis];
+
+ for (int j=i+1;j<numSmallAabbs;j++)
+ {
+
+ b3SapAabb smallAabbj = m_allAabbsCPU[m_smallAabbsMappingCPU[j]];
+
+ if (TestAabbAgainstAabb2((b3Vector3&)smallAabbi.m_min, (b3Vector3&)smallAabbi.m_max,
+ (b3Vector3&)smallAabbj.m_min,(b3Vector3&)smallAabbj.m_max))
+ {
+ b3Int4 pair;
+ int a = smallAabbi.m_minIndices[3];
+ int b = smallAabbj.m_minIndices[3];
+ if (a<=b)
+ {
+ pair.x = a;//store the original index in the unsorted aabb array
+ pair.y = b;
+ } else
+ {
+ pair.x = b;//store the original index in the unsorted aabb array
+ pair.y = a;
+ }
+ hostPairs.push_back(pair);
+ }
+ }
+ }
+ }
+
+
+ {
+ int numSmallAabbs = m_smallAabbsMappingCPU.size();
+ for (int i=0;i<numSmallAabbs;i++)
+ {
+ b3SapAabb smallAabbi = m_allAabbsCPU[m_smallAabbsMappingCPU[i]];
+
+ //float reference = smallAabbi.m_max[axis];
+ int numLargeAabbs = m_largeAabbsMappingCPU.size();
+
+ for (int j=0;j<numLargeAabbs;j++)
+ {
+ b3SapAabb largeAabbj = m_allAabbsCPU[m_largeAabbsMappingCPU[j]];
+ if (TestAabbAgainstAabb2((b3Vector3&)smallAabbi.m_min, (b3Vector3&)smallAabbi.m_max,
+ (b3Vector3&)largeAabbj.m_min,(b3Vector3&)largeAabbj.m_max))
+ {
+ b3Int4 pair;
+ int a = largeAabbj.m_minIndices[3];
+ int b = smallAabbi.m_minIndices[3];
+ if (a<=b)
+ {
+ pair.x = a;
+ pair.y = b;//store the original index in the unsorted aabb array
+ } else
+ {
+ pair.x = b;
+ pair.y = a;//store the original index in the unsorted aabb array
+ }
+
+ hostPairs.push_back(pair);
+ }
+ }
+ }
+ }
+
+ if (hostPairs.size() > maxPairs)
+ {
+ hostPairs.resize(maxPairs);
+ }
+
+ if (hostPairs.size())
+ {
+ m_overlappingPairs.copyFromHost(hostPairs);
+ } else
+ {
+ m_overlappingPairs.resize(0);
+ }
+
+ //init3dSap();
+
+}
+
+void b3GpuSapBroadphase::reset()
+{
+ m_allAabbsGPU.resize(0);
+ m_allAabbsCPU.resize(0);
+
+
+ m_smallAabbsMappingGPU.resize(0);
+ m_smallAabbsMappingCPU.resize(0);
+
+ m_pairCount.resize(0);
+
+ m_largeAabbsMappingGPU.resize(0);
+ m_largeAabbsMappingCPU.resize(0);
+
+}
+
+
+void b3GpuSapBroadphase::calculateOverlappingPairs(int maxPairs)
+{
+ if (m_sapKernel==0)
+ {
+ calculateOverlappingPairsHost(maxPairs);
+ return;
+ }
+
+ //if (m_currentBuffer>=0)
+ // return calculateOverlappingPairsHostIncremental3Sap();
+
+ //calculateOverlappingPairsHost(maxPairs);
+
+ B3_PROFILE("GPU 1-axis SAP calculateOverlappingPairs");
+
+ int axis = 0;
+
+ {
+
+ //bool syncOnHost = false;
+
+ int numSmallAabbs = m_smallAabbsMappingCPU.size();
+ if (m_prefixScanFloat4 && numSmallAabbs)
+ {
+ B3_PROFILE("GPU compute best variance axis");
+
+ if (m_dst.size()!=(numSmallAabbs+1))
+ {
+ m_dst.resize(numSmallAabbs+128);
+ m_sum.resize(numSmallAabbs+128);
+ m_sum2.resize(numSmallAabbs+128);
+ m_sum.at(numSmallAabbs)=b3MakeVector3(0,0,0); //slow?
+ m_sum2.at(numSmallAabbs)=b3MakeVector3(0,0,0); //slow?
+ }
+
+ b3LauncherCL launcher(m_queue, m_prepareSumVarianceKernel ,"m_prepareSumVarianceKernel");
+ launcher.setBuffer(m_allAabbsGPU.getBufferCL());
+
+ launcher.setBuffer(m_smallAabbsMappingGPU.getBufferCL());
+ launcher.setBuffer(m_sum.getBufferCL());
+ launcher.setBuffer(m_sum2.getBufferCL());
+ launcher.setConst( numSmallAabbs );
+ int num = numSmallAabbs;
+ launcher.launch1D( num);
+
+
+ b3Vector3 s;
+ b3Vector3 s2;
+ m_prefixScanFloat4->execute(m_sum,m_dst,numSmallAabbs+1,&s);
+ m_prefixScanFloat4->execute(m_sum2,m_dst,numSmallAabbs+1,&s2);
+
+ b3Vector3 v = s2 - (s*s) / (float)numSmallAabbs;
+
+ if(v[1] > v[0])
+ axis = 1;
+ if(v[2] > v[axis])
+ axis = 2;
+ }
+
+
+
+ m_gpuSmallSortData.resize(numSmallAabbs);
+
+
+#if 1
+ if (m_smallAabbsMappingGPU.size())
+ {
+
+ B3_PROFILE("flipFloatKernel");
+ b3BufferInfoCL bInfo[] = {
+ b3BufferInfoCL( m_allAabbsGPU.getBufferCL(), true ),
+ b3BufferInfoCL( m_smallAabbsMappingGPU.getBufferCL(), true),
+ b3BufferInfoCL( m_gpuSmallSortData.getBufferCL())};
+ b3LauncherCL launcher(m_queue, m_flipFloatKernel ,"m_flipFloatKernel");
+ launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst( numSmallAabbs );
+ launcher.setConst( axis );
+
+ int num = numSmallAabbs;
+ launcher.launch1D( num);
+ clFinish(m_queue);
+ }
+
+ if (m_gpuSmallSortData.size())
+ {
+ B3_PROFILE("gpu radix sort");
+ m_sorter->execute(m_gpuSmallSortData);
+ clFinish(m_queue);
+ }
+
+ m_gpuSmallSortedAabbs.resize(numSmallAabbs);
+ if (numSmallAabbs)
+ {
+ B3_PROFILE("scatterKernel");
+
+ b3BufferInfoCL bInfo[] = {
+ b3BufferInfoCL( m_allAabbsGPU.getBufferCL(), true ),
+ b3BufferInfoCL( m_smallAabbsMappingGPU.getBufferCL(), true),
+ b3BufferInfoCL( m_gpuSmallSortData.getBufferCL(),true),
+ b3BufferInfoCL(m_gpuSmallSortedAabbs.getBufferCL())};
+ b3LauncherCL launcher(m_queue, m_scatterKernel ,"m_scatterKernel ");
+ launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst( numSmallAabbs);
+ int num = numSmallAabbs;
+ launcher.launch1D( num);
+ clFinish(m_queue);
+
+ }
+
+
+ m_overlappingPairs.resize(maxPairs);
+
+ m_pairCount.resize(0);
+ m_pairCount.push_back(0);
+ int numPairs=0;
+
+ {
+ int numLargeAabbs = m_largeAabbsMappingGPU.size();
+ if (numLargeAabbs && numSmallAabbs)
+ {
+ //@todo
+ B3_PROFILE("sap2Kernel");
+ b3BufferInfoCL bInfo[] = {
+ b3BufferInfoCL( m_allAabbsGPU.getBufferCL() ),
+ b3BufferInfoCL( m_largeAabbsMappingGPU.getBufferCL() ),
+ b3BufferInfoCL( m_smallAabbsMappingGPU.getBufferCL() ),
+ b3BufferInfoCL( m_overlappingPairs.getBufferCL() ),
+ b3BufferInfoCL(m_pairCount.getBufferCL())};
+ b3LauncherCL launcher(m_queue, m_sap2Kernel,"m_sap2Kernel");
+ launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst( numLargeAabbs );
+ launcher.setConst( numSmallAabbs);
+ launcher.setConst( axis );
+ launcher.setConst( maxPairs );
+//@todo: use actual maximum work item sizes of the device instead of hardcoded values
+ launcher.launch2D( numLargeAabbs, numSmallAabbs,4,64);
+
+ numPairs = m_pairCount.at(0);
+ if (numPairs >maxPairs)
+ {
+ b3Error("Error running out of pairs: numPairs = %d, maxPairs = %d.\n", numPairs, maxPairs);
+ numPairs =maxPairs;
+ }
+ }
+ }
+ if (m_gpuSmallSortedAabbs.size())
+ {
+ B3_PROFILE("sapKernel");
+ b3BufferInfoCL bInfo[] = { b3BufferInfoCL( m_gpuSmallSortedAabbs.getBufferCL() ), b3BufferInfoCL( m_overlappingPairs.getBufferCL() ), b3BufferInfoCL(m_pairCount.getBufferCL())};
+ b3LauncherCL launcher(m_queue, m_sapKernel,"m_sapKernel");
+ launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst( numSmallAabbs );
+ launcher.setConst( axis );
+ launcher.setConst( maxPairs );
+
+
+ int num = numSmallAabbs;
+#if 0
+ int buffSize = launcher.getSerializationBufferSize();
+ unsigned char* buf = new unsigned char[buffSize+sizeof(int)];
+ for (int i=0;i<buffSize+1;i++)
+ {
+ unsigned char* ptr = (unsigned char*)&buf[i];
+ *ptr = 0xff;
+ }
+ int actualWrite = launcher.serializeArguments(buf,buffSize);
+
+ unsigned char* cptr = (unsigned char*)&buf[buffSize];
+ // printf("buf[buffSize] = %d\n",*cptr);
+
+ assert(buf[buffSize]==0xff);//check for buffer overrun
+ int* ptr = (int*)&buf[buffSize];
+
+ *ptr = num;
+
+ FILE* f = fopen("m_sapKernelArgs.bin","wb");
+ fwrite(buf,buffSize+sizeof(int),1,f);
+ fclose(f);
+#endif//
+
+ launcher.launch1D( num);
+ clFinish(m_queue);
+
+ numPairs = m_pairCount.at(0);
+ if (numPairs>maxPairs)
+ {
+ b3Error("Error running out of pairs: numPairs = %d, maxPairs = %d.\n", numPairs, maxPairs);
+ numPairs = maxPairs;
+ m_pairCount.resize(0);
+ m_pairCount.push_back(maxPairs);
+ }
+ }
+
+#else
+ int numPairs = 0;
+
+
+ b3LauncherCL launcher(m_queue, m_sapKernel);
+
+ const char* fileName = "m_sapKernelArgs.bin";
+ FILE* f = fopen(fileName,"rb");
+ if (f)
+ {
+ int sizeInBytes=0;
+ if (fseek(f, 0, SEEK_END) || (sizeInBytes = ftell(f)) == EOF || fseek(f, 0, SEEK_SET))
+ {
+ printf("error, cannot get file size\n");
+ exit(0);
+ }
+
+ unsigned char* buf = (unsigned char*) malloc(sizeInBytes);
+ fread(buf,sizeInBytes,1,f);
+ int serializedBytes = launcher.deserializeArgs(buf, sizeInBytes,m_context);
+ int num = *(int*)&buf[serializedBytes];
+ launcher.launch1D( num);
+
+ b3OpenCLArray<int> pairCount(m_context, m_queue);
+ int numElements = launcher.m_arrays[2]->size()/sizeof(int);
+ pairCount.setFromOpenCLBuffer(launcher.m_arrays[2]->getBufferCL(),numElements);
+ numPairs = pairCount.at(0);
+ //printf("overlapping pairs = %d\n",numPairs);
+ b3AlignedObjectArray<b3Int4> hostOoverlappingPairs;
+ b3OpenCLArray<b3Int4> tmpGpuPairs(m_context,m_queue);
+ tmpGpuPairs.setFromOpenCLBuffer(launcher.m_arrays[1]->getBufferCL(),numPairs );
+
+ tmpGpuPairs.copyToHost(hostOoverlappingPairs);
+ m_overlappingPairs.copyFromHost(hostOoverlappingPairs);
+ //printf("hello %d\n", m_overlappingPairs.size());
+ free(buf);
+ fclose(f);
+
+ } else {
+ printf("error: cannot find file %s\n",fileName);
+ }
+
+ clFinish(m_queue);
+
+
+#endif
+
+
+ m_overlappingPairs.resize(numPairs);
+
+ }//B3_PROFILE("GPU_RADIX SORT");
+ //init3dSap();
+}
+
+void b3GpuSapBroadphase::writeAabbsToGpu()
+{
+ m_smallAabbsMappingGPU.copyFromHost(m_smallAabbsMappingCPU);
+ m_largeAabbsMappingGPU.copyFromHost(m_largeAabbsMappingCPU);
+
+ m_allAabbsGPU.copyFromHost(m_allAabbsCPU);//might not be necessary, the 'setupGpuAabbsFull' already takes care of this
+
+
+
+}
+
+void b3GpuSapBroadphase::createLargeProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr , int collisionFilterGroup, int collisionFilterMask)
+{
+ int index = userPtr;
+ b3SapAabb aabb;
+ for (int i=0;i<4;i++)
+ {
+ aabb.m_min[i] = aabbMin[i];
+ aabb.m_max[i] = aabbMax[i];
+ }
+ aabb.m_minIndices[3] = index;
+ aabb.m_signedMaxIndices[3] = m_allAabbsCPU.size();
+ m_largeAabbsMappingCPU.push_back(m_allAabbsCPU.size());
+
+ m_allAabbsCPU.push_back(aabb);
+}
+
+void b3GpuSapBroadphase::createProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr , int collisionFilterGroup, int collisionFilterMask)
+{
+ int index = userPtr;
+ b3SapAabb aabb;
+ for (int i=0;i<4;i++)
+ {
+ aabb.m_min[i] = aabbMin[i];
+ aabb.m_max[i] = aabbMax[i];
+ }
+ aabb.m_minIndices[3] = index;
+ aabb.m_signedMaxIndices[3] = m_allAabbsCPU.size();
+ m_smallAabbsMappingCPU.push_back(m_allAabbsCPU.size());
+
+
+ m_allAabbsCPU.push_back(aabb);
+}
+
+cl_mem b3GpuSapBroadphase::getAabbBufferWS()
+{
+ return m_allAabbsGPU.getBufferCL();
+}
+
+int b3GpuSapBroadphase::getNumOverlap()
+{
+ return m_overlappingPairs.size();
+}
+cl_mem b3GpuSapBroadphase::getOverlappingPairBuffer()
+{
+ return m_overlappingPairs.getBufferCL();
+}
+
+b3OpenCLArray<b3Int4>& b3GpuSapBroadphase::getOverlappingPairsGPU()
+{
+ return m_overlappingPairs;
+}
+b3OpenCLArray<int>& b3GpuSapBroadphase::getSmallAabbIndicesGPU()
+{
+ return m_smallAabbsMappingGPU;
+}
+b3OpenCLArray<int>& b3GpuSapBroadphase::getLargeAabbIndicesGPU()
+{
+ return m_largeAabbsMappingGPU;
+}
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/b3GpuSapBroadphase.h b/thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/b3GpuSapBroadphase.h
new file mode 100644
index 0000000000..8d36ac78f2
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/b3GpuSapBroadphase.h
@@ -0,0 +1,151 @@
+#ifndef B3_GPU_SAP_BROADPHASE_H
+#define B3_GPU_SAP_BROADPHASE_H
+
+#include "Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h"
+#include "Bullet3OpenCL/ParallelPrimitives/b3FillCL.h" //b3Int2
+class b3Vector3;
+#include "Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.h"
+
+#include "b3SapAabb.h"
+#include "Bullet3Common/shared/b3Int2.h"
+
+#include "b3GpuBroadphaseInterface.h"
+
+
+class b3GpuSapBroadphase : public b3GpuBroadphaseInterface
+{
+
+ cl_context m_context;
+ cl_device_id m_device;
+ cl_command_queue m_queue;
+ cl_kernel m_flipFloatKernel;
+ cl_kernel m_scatterKernel ;
+ cl_kernel m_copyAabbsKernel;
+ cl_kernel m_sapKernel;
+ cl_kernel m_sap2Kernel;
+ cl_kernel m_prepareSumVarianceKernel;
+
+
+ class b3RadixSort32CL* m_sorter;
+
+ ///test for 3d SAP
+ b3AlignedObjectArray<b3SortData> m_sortedAxisCPU[3][2];
+ b3AlignedObjectArray<b3UnsignedInt2> m_objectMinMaxIndexCPU[3][2];
+ b3OpenCLArray<b3UnsignedInt2> m_objectMinMaxIndexGPUaxis0;
+ b3OpenCLArray<b3UnsignedInt2> m_objectMinMaxIndexGPUaxis1;
+ b3OpenCLArray<b3UnsignedInt2> m_objectMinMaxIndexGPUaxis2;
+ b3OpenCLArray<b3UnsignedInt2> m_objectMinMaxIndexGPUaxis0prev;
+ b3OpenCLArray<b3UnsignedInt2> m_objectMinMaxIndexGPUaxis1prev;
+ b3OpenCLArray<b3UnsignedInt2> m_objectMinMaxIndexGPUaxis2prev;
+
+ b3OpenCLArray<b3SortData> m_sortedAxisGPU0;
+ b3OpenCLArray<b3SortData> m_sortedAxisGPU1;
+ b3OpenCLArray<b3SortData> m_sortedAxisGPU2;
+ b3OpenCLArray<b3SortData> m_sortedAxisGPU0prev;
+ b3OpenCLArray<b3SortData> m_sortedAxisGPU1prev;
+ b3OpenCLArray<b3SortData> m_sortedAxisGPU2prev;
+
+
+ b3OpenCLArray<b3Int4> m_addedHostPairsGPU;
+ b3OpenCLArray<b3Int4> m_removedHostPairsGPU;
+ b3OpenCLArray<int> m_addedCountGPU;
+ b3OpenCLArray<int> m_removedCountGPU;
+
+ int m_currentBuffer;
+
+public:
+
+ b3OpenCLArray<int> m_pairCount;
+
+
+ b3OpenCLArray<b3SapAabb> m_allAabbsGPU;
+ b3AlignedObjectArray<b3SapAabb> m_allAabbsCPU;
+
+ virtual b3OpenCLArray<b3SapAabb>& getAllAabbsGPU()
+ {
+ return m_allAabbsGPU;
+ }
+ virtual b3AlignedObjectArray<b3SapAabb>& getAllAabbsCPU()
+ {
+ return m_allAabbsCPU;
+ }
+
+ b3OpenCLArray<b3Vector3> m_sum;
+ b3OpenCLArray<b3Vector3> m_sum2;
+ b3OpenCLArray<b3Vector3> m_dst;
+
+ b3OpenCLArray<int> m_smallAabbsMappingGPU;
+ b3AlignedObjectArray<int> m_smallAabbsMappingCPU;
+
+ b3OpenCLArray<int> m_largeAabbsMappingGPU;
+ b3AlignedObjectArray<int> m_largeAabbsMappingCPU;
+
+
+ b3OpenCLArray<b3Int4> m_overlappingPairs;
+
+ //temporary gpu work memory
+ b3OpenCLArray<b3SortData> m_gpuSmallSortData;
+ b3OpenCLArray<b3SapAabb> m_gpuSmallSortedAabbs;
+
+ class b3PrefixScanFloat4CL* m_prefixScanFloat4;
+
+ enum b3GpuSapKernelType
+ {
+ B3_GPU_SAP_KERNEL_BRUTE_FORCE_CPU=1,
+ B3_GPU_SAP_KERNEL_BRUTE_FORCE_GPU,
+ B3_GPU_SAP_KERNEL_ORIGINAL,
+ B3_GPU_SAP_KERNEL_BARRIER,
+ B3_GPU_SAP_KERNEL_LOCAL_SHARED_MEMORY
+ };
+
+ b3GpuSapBroadphase(cl_context ctx,cl_device_id device, cl_command_queue q , b3GpuSapKernelType kernelType=B3_GPU_SAP_KERNEL_LOCAL_SHARED_MEMORY);
+ virtual ~b3GpuSapBroadphase();
+
+ static b3GpuBroadphaseInterface* CreateFuncBruteForceCpu(cl_context ctx,cl_device_id device, cl_command_queue q)
+ {
+ return new b3GpuSapBroadphase(ctx,device,q,B3_GPU_SAP_KERNEL_BRUTE_FORCE_CPU);
+ }
+
+ static b3GpuBroadphaseInterface* CreateFuncBruteForceGpu(cl_context ctx,cl_device_id device, cl_command_queue q)
+ {
+ return new b3GpuSapBroadphase(ctx,device,q,B3_GPU_SAP_KERNEL_BRUTE_FORCE_GPU);
+ }
+
+ static b3GpuBroadphaseInterface* CreateFuncOriginal(cl_context ctx,cl_device_id device, cl_command_queue q)
+ {
+ return new b3GpuSapBroadphase(ctx,device,q,B3_GPU_SAP_KERNEL_ORIGINAL);
+ }
+ static b3GpuBroadphaseInterface* CreateFuncBarrier(cl_context ctx,cl_device_id device, cl_command_queue q)
+ {
+ return new b3GpuSapBroadphase(ctx,device,q,B3_GPU_SAP_KERNEL_BARRIER);
+ }
+ static b3GpuBroadphaseInterface* CreateFuncLocalMemory(cl_context ctx,cl_device_id device, cl_command_queue q)
+ {
+ return new b3GpuSapBroadphase(ctx,device,q,B3_GPU_SAP_KERNEL_LOCAL_SHARED_MEMORY);
+ }
+
+
+ virtual void calculateOverlappingPairs(int maxPairs);
+ virtual void calculateOverlappingPairsHost(int maxPairs);
+
+ void reset();
+
+ void init3dSap();
+ virtual void calculateOverlappingPairsHostIncremental3Sap();
+
+ virtual void createProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr , int collisionFilterGroup, int collisionFilterMask);
+ virtual void createLargeProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr , int collisionFilterGroup, int collisionFilterMask);
+
+ //call writeAabbsToGpu after done making all changes (createProxy etc)
+ virtual void writeAabbsToGpu();
+
+ virtual cl_mem getAabbBufferWS();
+ virtual int getNumOverlap();
+ virtual cl_mem getOverlappingPairBuffer();
+
+ virtual b3OpenCLArray<b3Int4>& getOverlappingPairsGPU();
+ virtual b3OpenCLArray<int>& getSmallAabbIndicesGPU();
+ virtual b3OpenCLArray<int>& getLargeAabbIndicesGPU();
+};
+
+#endif //B3_GPU_SAP_BROADPHASE_H \ No newline at end of file
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/b3SapAabb.h b/thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/b3SapAabb.h
new file mode 100644
index 0000000000..ea6550fede
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/b3SapAabb.h
@@ -0,0 +1,14 @@
+#ifndef B3_SAP_AABB_H
+#define B3_SAP_AABB_H
+
+#include "Bullet3Common/b3Scalar.h"
+#include "Bullet3Collision/BroadPhaseCollision/shared/b3Aabb.h"
+
+///just make sure that the b3Aabb is 16-byte aligned
+B3_ATTRIBUTE_ALIGNED16(struct) b3SapAabb : public b3Aabb
+{
+
+};
+
+
+#endif //B3_SAP_AABB_H
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/kernels/gridBroadphase.cl b/thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/kernels/gridBroadphase.cl
new file mode 100644
index 0000000000..ded4796d33
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/kernels/gridBroadphase.cl
@@ -0,0 +1,216 @@
+
+
+int getPosHash(int4 gridPos, __global float4* pParams)
+{
+ int4 gridDim = *((__global int4*)(pParams + 1));
+ gridPos.x &= gridDim.x - 1;
+ gridPos.y &= gridDim.y - 1;
+ gridPos.z &= gridDim.z - 1;
+ int hash = gridPos.z * gridDim.y * gridDim.x + gridPos.y * gridDim.x + gridPos.x;
+ return hash;
+}
+
+int4 getGridPos(float4 worldPos, __global float4* pParams)
+{
+ int4 gridPos;
+ int4 gridDim = *((__global int4*)(pParams + 1));
+ gridPos.x = (int)floor(worldPos.x * pParams[0].x) & (gridDim.x - 1);
+ gridPos.y = (int)floor(worldPos.y * pParams[0].y) & (gridDim.y - 1);
+ gridPos.z = (int)floor(worldPos.z * pParams[0].z) & (gridDim.z - 1);
+ return gridPos;
+}
+
+
+// calculate grid hash value for each body using its AABB
+__kernel void kCalcHashAABB(int numObjects, __global float4* allpAABB, __global const int* smallAabbMapping, __global int2* pHash, __global float4* pParams )
+{
+ int index = get_global_id(0);
+ if(index >= numObjects)
+ {
+ return;
+ }
+ float4 bbMin = allpAABB[smallAabbMapping[index]*2];
+ float4 bbMax = allpAABB[smallAabbMapping[index]*2 + 1];
+ float4 pos;
+ pos.x = (bbMin.x + bbMax.x) * 0.5f;
+ pos.y = (bbMin.y + bbMax.y) * 0.5f;
+ pos.z = (bbMin.z + bbMax.z) * 0.5f;
+ pos.w = 0.f;
+ // get address in grid
+ int4 gridPos = getGridPos(pos, pParams);
+ int gridHash = getPosHash(gridPos, pParams);
+ // store grid hash and body index
+ int2 hashVal;
+ hashVal.x = gridHash;
+ hashVal.y = index;
+ pHash[index] = hashVal;
+}
+
+__kernel void kClearCellStart( int numCells,
+ __global int* pCellStart )
+{
+ int index = get_global_id(0);
+ if(index >= numCells)
+ {
+ return;
+ }
+ pCellStart[index] = -1;
+}
+
+__kernel void kFindCellStart(int numObjects, __global int2* pHash, __global int* cellStart )
+{
+ __local int sharedHash[513];
+ int index = get_global_id(0);
+ int2 sortedData;
+
+ if(index < numObjects)
+ {
+ sortedData = pHash[index];
+ // Load hash data into shared memory so that we can look
+ // at neighboring body's hash value without loading
+ // two hash values per thread
+ sharedHash[get_local_id(0) + 1] = sortedData.x;
+ if((index > 0) && (get_local_id(0) == 0))
+ {
+ // first thread in block must load neighbor body hash
+ sharedHash[0] = pHash[index-1].x;
+ }
+ }
+ barrier(CLK_LOCAL_MEM_FENCE);
+ if(index < numObjects)
+ {
+ if((index == 0) || (sortedData.x != sharedHash[get_local_id(0)]))
+ {
+ cellStart[sortedData.x] = index;
+ }
+ }
+}
+
+int testAABBOverlap(float4 min0, float4 max0, float4 min1, float4 max1)
+{
+ return (min0.x <= max1.x)&& (min1.x <= max0.x) &&
+ (min0.y <= max1.y)&& (min1.y <= max0.y) &&
+ (min0.z <= max1.z)&& (min1.z <= max0.z);
+}
+
+
+
+
+//search for AABB 'index' against other AABBs' in this cell
+void findPairsInCell( int numObjects,
+ int4 gridPos,
+ int index,
+ __global int2* pHash,
+ __global int* pCellStart,
+ __global float4* allpAABB,
+ __global const int* smallAabbMapping,
+ __global float4* pParams,
+ volatile __global int* pairCount,
+ __global int4* pPairBuff2,
+ int maxPairs
+ )
+{
+ int4 pGridDim = *((__global int4*)(pParams + 1));
+ int maxBodiesPerCell = pGridDim.w;
+ int gridHash = getPosHash(gridPos, pParams);
+ // get start of bucket for this cell
+ int bucketStart = pCellStart[gridHash];
+ if (bucketStart == -1)
+ {
+ return; // cell empty
+ }
+ // iterate over bodies in this cell
+ int2 sortedData = pHash[index];
+ int unsorted_indx = sortedData.y;
+ float4 min0 = allpAABB[smallAabbMapping[unsorted_indx]*2 + 0];
+ float4 max0 = allpAABB[smallAabbMapping[unsorted_indx]*2 + 1];
+ int handleIndex = as_int(min0.w);
+
+ int bucketEnd = bucketStart + maxBodiesPerCell;
+ bucketEnd = (bucketEnd > numObjects) ? numObjects : bucketEnd;
+ for(int index2 = bucketStart; index2 < bucketEnd; index2++)
+ {
+ int2 cellData = pHash[index2];
+ if (cellData.x != gridHash)
+ {
+ break; // no longer in same bucket
+ }
+ int unsorted_indx2 = cellData.y;
+ //if (unsorted_indx2 < unsorted_indx) // check not colliding with self
+ if (unsorted_indx2 != unsorted_indx) // check not colliding with self
+ {
+ float4 min1 = allpAABB[smallAabbMapping[unsorted_indx2]*2 + 0];
+ float4 max1 = allpAABB[smallAabbMapping[unsorted_indx2]*2 + 1];
+ if(testAABBOverlap(min0, max0, min1, max1))
+ {
+ if (pairCount)
+ {
+ int handleIndex2 = as_int(min1.w);
+ if (handleIndex<handleIndex2)
+ {
+ int curPair = atomic_add(pairCount,1);
+ if (curPair<maxPairs)
+ {
+ int4 newpair;
+ newpair.x = handleIndex;
+ newpair.y = handleIndex2;
+ newpair.z = -1;
+ newpair.w = -1;
+ pPairBuff2[curPair] = newpair;
+ }
+ }
+
+ }
+ }
+ }
+ }
+}
+
+__kernel void kFindOverlappingPairs( int numObjects,
+ __global float4* allpAABB,
+ __global const int* smallAabbMapping,
+ __global int2* pHash,
+ __global int* pCellStart,
+ __global float4* pParams ,
+ volatile __global int* pairCount,
+ __global int4* pPairBuff2,
+ int maxPairs
+ )
+
+{
+ int index = get_global_id(0);
+ if(index >= numObjects)
+ {
+ return;
+ }
+ int2 sortedData = pHash[index];
+ int unsorted_indx = sortedData.y;
+ float4 bbMin = allpAABB[smallAabbMapping[unsorted_indx]*2 + 0];
+ float4 bbMax = allpAABB[smallAabbMapping[unsorted_indx]*2 + 1];
+ float4 pos;
+ pos.x = (bbMin.x + bbMax.x) * 0.5f;
+ pos.y = (bbMin.y + bbMax.y) * 0.5f;
+ pos.z = (bbMin.z + bbMax.z) * 0.5f;
+ // get address in grid
+ int4 gridPosA = getGridPos(pos, pParams);
+ int4 gridPosB;
+ // examine only neighbouring cells
+ for(int z=-1; z<=1; z++)
+ {
+ gridPosB.z = gridPosA.z + z;
+ for(int y=-1; y<=1; y++)
+ {
+ gridPosB.y = gridPosA.y + y;
+ for(int x=-1; x<=1; x++)
+ {
+ gridPosB.x = gridPosA.x + x;
+ findPairsInCell(numObjects, gridPosB, index, pHash, pCellStart, allpAABB,smallAabbMapping, pParams, pairCount,pPairBuff2, maxPairs);
+ }
+ }
+ }
+}
+
+
+
+
+
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/kernels/gridBroadphaseKernels.h b/thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/kernels/gridBroadphaseKernels.h
new file mode 100644
index 0000000000..dad42477c3
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/kernels/gridBroadphaseKernels.h
@@ -0,0 +1,199 @@
+//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
+static const char* gridBroadphaseCL= \
+"int getPosHash(int4 gridPos, __global float4* pParams)\n"
+"{\n"
+" int4 gridDim = *((__global int4*)(pParams + 1));\n"
+" gridPos.x &= gridDim.x - 1;\n"
+" gridPos.y &= gridDim.y - 1;\n"
+" gridPos.z &= gridDim.z - 1;\n"
+" int hash = gridPos.z * gridDim.y * gridDim.x + gridPos.y * gridDim.x + gridPos.x;\n"
+" return hash;\n"
+"} \n"
+"int4 getGridPos(float4 worldPos, __global float4* pParams)\n"
+"{\n"
+" int4 gridPos;\n"
+" int4 gridDim = *((__global int4*)(pParams + 1));\n"
+" gridPos.x = (int)floor(worldPos.x * pParams[0].x) & (gridDim.x - 1);\n"
+" gridPos.y = (int)floor(worldPos.y * pParams[0].y) & (gridDim.y - 1);\n"
+" gridPos.z = (int)floor(worldPos.z * pParams[0].z) & (gridDim.z - 1);\n"
+" return gridPos;\n"
+"}\n"
+"// calculate grid hash value for each body using its AABB\n"
+"__kernel void kCalcHashAABB(int numObjects, __global float4* allpAABB, __global const int* smallAabbMapping, __global int2* pHash, __global float4* pParams )\n"
+"{\n"
+" int index = get_global_id(0);\n"
+" if(index >= numObjects)\n"
+" {\n"
+" return;\n"
+" }\n"
+" float4 bbMin = allpAABB[smallAabbMapping[index]*2];\n"
+" float4 bbMax = allpAABB[smallAabbMapping[index]*2 + 1];\n"
+" float4 pos;\n"
+" pos.x = (bbMin.x + bbMax.x) * 0.5f;\n"
+" pos.y = (bbMin.y + bbMax.y) * 0.5f;\n"
+" pos.z = (bbMin.z + bbMax.z) * 0.5f;\n"
+" pos.w = 0.f;\n"
+" // get address in grid\n"
+" int4 gridPos = getGridPos(pos, pParams);\n"
+" int gridHash = getPosHash(gridPos, pParams);\n"
+" // store grid hash and body index\n"
+" int2 hashVal;\n"
+" hashVal.x = gridHash;\n"
+" hashVal.y = index;\n"
+" pHash[index] = hashVal;\n"
+"}\n"
+"__kernel void kClearCellStart( int numCells, \n"
+" __global int* pCellStart )\n"
+"{\n"
+" int index = get_global_id(0);\n"
+" if(index >= numCells)\n"
+" {\n"
+" return;\n"
+" }\n"
+" pCellStart[index] = -1;\n"
+"}\n"
+"__kernel void kFindCellStart(int numObjects, __global int2* pHash, __global int* cellStart )\n"
+"{\n"
+" __local int sharedHash[513];\n"
+" int index = get_global_id(0);\n"
+" int2 sortedData;\n"
+" if(index < numObjects)\n"
+" {\n"
+" sortedData = pHash[index];\n"
+" // Load hash data into shared memory so that we can look \n"
+" // at neighboring body's hash value without loading\n"
+" // two hash values per thread\n"
+" sharedHash[get_local_id(0) + 1] = sortedData.x;\n"
+" if((index > 0) && (get_local_id(0) == 0))\n"
+" {\n"
+" // first thread in block must load neighbor body hash\n"
+" sharedHash[0] = pHash[index-1].x;\n"
+" }\n"
+" }\n"
+" barrier(CLK_LOCAL_MEM_FENCE);\n"
+" if(index < numObjects)\n"
+" {\n"
+" if((index == 0) || (sortedData.x != sharedHash[get_local_id(0)]))\n"
+" {\n"
+" cellStart[sortedData.x] = index;\n"
+" }\n"
+" }\n"
+"}\n"
+"int testAABBOverlap(float4 min0, float4 max0, float4 min1, float4 max1)\n"
+"{\n"
+" return (min0.x <= max1.x)&& (min1.x <= max0.x) && \n"
+" (min0.y <= max1.y)&& (min1.y <= max0.y) && \n"
+" (min0.z <= max1.z)&& (min1.z <= max0.z); \n"
+"}\n"
+"//search for AABB 'index' against other AABBs' in this cell\n"
+"void findPairsInCell( int numObjects,\n"
+" int4 gridPos,\n"
+" int index,\n"
+" __global int2* pHash,\n"
+" __global int* pCellStart,\n"
+" __global float4* allpAABB, \n"
+" __global const int* smallAabbMapping,\n"
+" __global float4* pParams,\n"
+" volatile __global int* pairCount,\n"
+" __global int4* pPairBuff2,\n"
+" int maxPairs\n"
+" )\n"
+"{\n"
+" int4 pGridDim = *((__global int4*)(pParams + 1));\n"
+" int maxBodiesPerCell = pGridDim.w;\n"
+" int gridHash = getPosHash(gridPos, pParams);\n"
+" // get start of bucket for this cell\n"
+" int bucketStart = pCellStart[gridHash];\n"
+" if (bucketStart == -1)\n"
+" {\n"
+" return; // cell empty\n"
+" }\n"
+" // iterate over bodies in this cell\n"
+" int2 sortedData = pHash[index];\n"
+" int unsorted_indx = sortedData.y;\n"
+" float4 min0 = allpAABB[smallAabbMapping[unsorted_indx]*2 + 0]; \n"
+" float4 max0 = allpAABB[smallAabbMapping[unsorted_indx]*2 + 1];\n"
+" int handleIndex = as_int(min0.w);\n"
+" \n"
+" int bucketEnd = bucketStart + maxBodiesPerCell;\n"
+" bucketEnd = (bucketEnd > numObjects) ? numObjects : bucketEnd;\n"
+" for(int index2 = bucketStart; index2 < bucketEnd; index2++) \n"
+" {\n"
+" int2 cellData = pHash[index2];\n"
+" if (cellData.x != gridHash)\n"
+" {\n"
+" break; // no longer in same bucket\n"
+" }\n"
+" int unsorted_indx2 = cellData.y;\n"
+" //if (unsorted_indx2 < unsorted_indx) // check not colliding with self\n"
+" if (unsorted_indx2 != unsorted_indx) // check not colliding with self\n"
+" { \n"
+" float4 min1 = allpAABB[smallAabbMapping[unsorted_indx2]*2 + 0];\n"
+" float4 max1 = allpAABB[smallAabbMapping[unsorted_indx2]*2 + 1];\n"
+" if(testAABBOverlap(min0, max0, min1, max1))\n"
+" {\n"
+" if (pairCount)\n"
+" {\n"
+" int handleIndex2 = as_int(min1.w);\n"
+" if (handleIndex<handleIndex2)\n"
+" {\n"
+" int curPair = atomic_add(pairCount,1);\n"
+" if (curPair<maxPairs)\n"
+" {\n"
+" int4 newpair;\n"
+" newpair.x = handleIndex;\n"
+" newpair.y = handleIndex2;\n"
+" newpair.z = -1;\n"
+" newpair.w = -1;\n"
+" pPairBuff2[curPair] = newpair;\n"
+" }\n"
+" }\n"
+" \n"
+" }\n"
+" }\n"
+" }\n"
+" }\n"
+"}\n"
+"__kernel void kFindOverlappingPairs( int numObjects,\n"
+" __global float4* allpAABB, \n"
+" __global const int* smallAabbMapping,\n"
+" __global int2* pHash, \n"
+" __global int* pCellStart, \n"
+" __global float4* pParams ,\n"
+" volatile __global int* pairCount,\n"
+" __global int4* pPairBuff2,\n"
+" int maxPairs\n"
+" )\n"
+"{\n"
+" int index = get_global_id(0);\n"
+" if(index >= numObjects)\n"
+" {\n"
+" return;\n"
+" }\n"
+" int2 sortedData = pHash[index];\n"
+" int unsorted_indx = sortedData.y;\n"
+" float4 bbMin = allpAABB[smallAabbMapping[unsorted_indx]*2 + 0];\n"
+" float4 bbMax = allpAABB[smallAabbMapping[unsorted_indx]*2 + 1];\n"
+" float4 pos;\n"
+" pos.x = (bbMin.x + bbMax.x) * 0.5f;\n"
+" pos.y = (bbMin.y + bbMax.y) * 0.5f;\n"
+" pos.z = (bbMin.z + bbMax.z) * 0.5f;\n"
+" // get address in grid\n"
+" int4 gridPosA = getGridPos(pos, pParams);\n"
+" int4 gridPosB; \n"
+" // examine only neighbouring cells\n"
+" for(int z=-1; z<=1; z++) \n"
+" {\n"
+" gridPosB.z = gridPosA.z + z;\n"
+" for(int y=-1; y<=1; y++) \n"
+" {\n"
+" gridPosB.y = gridPosA.y + y;\n"
+" for(int x=-1; x<=1; x++) \n"
+" {\n"
+" gridPosB.x = gridPosA.x + x;\n"
+" findPairsInCell(numObjects, gridPosB, index, pHash, pCellStart, allpAABB,smallAabbMapping, pParams, pairCount,pPairBuff2, maxPairs);\n"
+" }\n"
+" }\n"
+" }\n"
+"}\n"
+;
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/kernels/parallelLinearBvh.cl b/thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/kernels/parallelLinearBvh.cl
new file mode 100644
index 0000000000..c375b9bf37
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/kernels/parallelLinearBvh.cl
@@ -0,0 +1,767 @@
+/*
+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.
+*/
+//Initial Author Jackson Lee, 2014
+
+typedef float b3Scalar;
+typedef float4 b3Vector3;
+#define b3Max max
+#define b3Min min
+#define b3Sqrt sqrt
+
+typedef struct
+{
+ unsigned int m_key;
+ unsigned int m_value;
+} SortDataCL;
+
+typedef struct
+{
+ union
+ {
+ float4 m_min;
+ float m_minElems[4];
+ int m_minIndices[4];
+ };
+ union
+ {
+ float4 m_max;
+ float m_maxElems[4];
+ int m_maxIndices[4];
+ };
+} b3AabbCL;
+
+
+unsigned int interleaveBits(unsigned int x)
+{
+ //........ ........ ......12 3456789A //x
+ //....1..2 ..3..4.. 5..6..7. .8..9..A //x after interleaving bits
+
+ //......12 3456789A ......12 3456789A //x ^ (x << 16)
+ //11111111 ........ ........ 11111111 //0x FF 00 00 FF
+ //......12 ........ ........ 3456789A //x = (x ^ (x << 16)) & 0xFF0000FF;
+
+ //......12 ........ 3456789A 3456789A //x ^ (x << 8)
+ //......11 ........ 1111.... ....1111 //0x 03 00 F0 0F
+ //......12 ........ 3456.... ....789A //x = (x ^ (x << 8)) & 0x0300F00F;
+
+ //..12..12 ....3456 3456.... 789A789A //x ^ (x << 4)
+ //......11 ....11.. ..11.... 11....11 //0x 03 0C 30 C3
+ //......12 ....34.. ..56.... 78....9A //x = (x ^ (x << 4)) & 0x030C30C3;
+
+ //....1212 ..3434.. 5656..78 78..9A9A //x ^ (x << 2)
+ //....1..1 ..1..1.. 1..1..1. .1..1..1 //0x 09 24 92 49
+ //....1..2 ..3..4.. 5..6..7. .8..9..A //x = (x ^ (x << 2)) & 0x09249249;
+
+ //........ ........ ......11 11111111 //0x000003FF
+ x &= 0x000003FF; //Clear all bits above bit 10
+
+ x = (x ^ (x << 16)) & 0xFF0000FF;
+ x = (x ^ (x << 8)) & 0x0300F00F;
+ x = (x ^ (x << 4)) & 0x030C30C3;
+ x = (x ^ (x << 2)) & 0x09249249;
+
+ return x;
+}
+unsigned int getMortonCode(unsigned int x, unsigned int y, unsigned int z)
+{
+ return interleaveBits(x) << 0 | interleaveBits(y) << 1 | interleaveBits(z) << 2;
+}
+
+__kernel void separateAabbs(__global b3AabbCL* unseparatedAabbs, __global int* aabbIndices, __global b3AabbCL* out_aabbs, int numAabbsToSeparate)
+{
+ int separatedAabbIndex = get_global_id(0);
+ if(separatedAabbIndex >= numAabbsToSeparate) return;
+
+ int unseparatedAabbIndex = aabbIndices[separatedAabbIndex];
+ out_aabbs[separatedAabbIndex] = unseparatedAabbs[unseparatedAabbIndex];
+}
+
+//Should replace with an optimized parallel reduction
+__kernel void findAllNodesMergedAabb(__global b3AabbCL* out_mergedAabb, int numAabbsNeedingMerge)
+{
+ //Each time this kernel is added to the command queue,
+ //the number of AABBs needing to be merged is halved
+ //
+ //Example with 159 AABBs:
+ // numRemainingAabbs == 159 / 2 + 159 % 2 == 80
+ // numMergedAabbs == 159 - 80 == 79
+ //So, indices [0, 78] are merged with [0 + 80, 78 + 80]
+
+ int numRemainingAabbs = numAabbsNeedingMerge / 2 + numAabbsNeedingMerge % 2;
+ int numMergedAabbs = numAabbsNeedingMerge - numRemainingAabbs;
+
+ int aabbIndex = get_global_id(0);
+ if(aabbIndex >= numMergedAabbs) return;
+
+ int otherAabbIndex = aabbIndex + numRemainingAabbs;
+
+ b3AabbCL aabb = out_mergedAabb[aabbIndex];
+ b3AabbCL otherAabb = out_mergedAabb[otherAabbIndex];
+
+ b3AabbCL mergedAabb;
+ mergedAabb.m_min = b3Min(aabb.m_min, otherAabb.m_min);
+ mergedAabb.m_max = b3Max(aabb.m_max, otherAabb.m_max);
+ out_mergedAabb[aabbIndex] = mergedAabb;
+}
+
+__kernel void assignMortonCodesAndAabbIndicies(__global b3AabbCL* worldSpaceAabbs, __global b3AabbCL* mergedAabbOfAllNodes,
+ __global SortDataCL* out_mortonCodesAndAabbIndices, int numAabbs)
+{
+ int leafNodeIndex = get_global_id(0); //Leaf node index == AABB index
+ if(leafNodeIndex >= numAabbs) return;
+
+ b3AabbCL mergedAabb = mergedAabbOfAllNodes[0];
+ b3Vector3 gridCenter = (mergedAabb.m_min + mergedAabb.m_max) * 0.5f;
+ b3Vector3 gridCellSize = (mergedAabb.m_max - mergedAabb.m_min) / (float)1024;
+
+ b3AabbCL aabb = worldSpaceAabbs[leafNodeIndex];
+ b3Vector3 aabbCenter = (aabb.m_min + aabb.m_max) * 0.5f;
+ b3Vector3 aabbCenterRelativeToGrid = aabbCenter - gridCenter;
+
+ //Quantize into integer coordinates
+ //floor() is needed to prevent the center cell, at (0,0,0) from being twice the size
+ b3Vector3 gridPosition = aabbCenterRelativeToGrid / gridCellSize;
+
+ int4 discretePosition;
+ discretePosition.x = (int)( (gridPosition.x >= 0.0f) ? gridPosition.x : floor(gridPosition.x) );
+ discretePosition.y = (int)( (gridPosition.y >= 0.0f) ? gridPosition.y : floor(gridPosition.y) );
+ discretePosition.z = (int)( (gridPosition.z >= 0.0f) ? gridPosition.z : floor(gridPosition.z) );
+
+ //Clamp coordinates into [-512, 511], then convert range from [-512, 511] to [0, 1023]
+ discretePosition = b3Max( -512, b3Min(discretePosition, 511) );
+ discretePosition += 512;
+
+ //Interleave bits(assign a morton code, also known as a z-curve)
+ unsigned int mortonCode = getMortonCode(discretePosition.x, discretePosition.y, discretePosition.z);
+
+ //
+ SortDataCL mortonCodeIndexPair;
+ mortonCodeIndexPair.m_key = mortonCode;
+ mortonCodeIndexPair.m_value = leafNodeIndex;
+
+ out_mortonCodesAndAabbIndices[leafNodeIndex] = mortonCodeIndexPair;
+}
+
+#define B3_PLVBH_TRAVERSE_MAX_STACK_SIZE 128
+
+//The most significant bit(0x80000000) of a int32 is used to distinguish between leaf and internal nodes.
+//If it is set, then the index is for an internal node; otherwise, it is a leaf node.
+//In both cases, the bit should be cleared to access the actual node index.
+int isLeafNode(int index) { return (index >> 31 == 0); }
+int getIndexWithInternalNodeMarkerRemoved(int index) { return index & (~0x80000000); }
+int getIndexWithInternalNodeMarkerSet(int isLeaf, int index) { return (isLeaf) ? index : (index | 0x80000000); }
+
+//From sap.cl
+#define NEW_PAIR_MARKER -1
+
+bool TestAabbAgainstAabb2(const b3AabbCL* aabb1, const b3AabbCL* aabb2)
+{
+ bool overlap = true;
+ overlap = (aabb1->m_min.x > aabb2->m_max.x || aabb1->m_max.x < aabb2->m_min.x) ? false : overlap;
+ overlap = (aabb1->m_min.z > aabb2->m_max.z || aabb1->m_max.z < aabb2->m_min.z) ? false : overlap;
+ overlap = (aabb1->m_min.y > aabb2->m_max.y || aabb1->m_max.y < aabb2->m_min.y) ? false : overlap;
+ return overlap;
+}
+//From sap.cl
+
+__kernel void plbvhCalculateOverlappingPairs(__global b3AabbCL* rigidAabbs,
+
+ __global int* rootNodeIndex,
+ __global int2* internalNodeChildIndices,
+ __global b3AabbCL* internalNodeAabbs,
+ __global int2* internalNodeLeafIndexRanges,
+
+ __global SortDataCL* mortonCodesAndAabbIndices,
+ __global int* out_numPairs, __global int4* out_overlappingPairs,
+ int maxPairs, int numQueryAabbs)
+{
+ //Using get_group_id()/get_local_id() is Faster than get_global_id(0) since
+ //mortonCodesAndAabbIndices[] contains rigid body indices sorted along the z-curve (more spatially coherent)
+ int queryBvhNodeIndex = get_group_id(0) * get_local_size(0) + get_local_id(0);
+ if(queryBvhNodeIndex >= numQueryAabbs) return;
+
+ int queryRigidIndex = mortonCodesAndAabbIndices[queryBvhNodeIndex].m_value;
+ b3AabbCL queryAabb = rigidAabbs[queryRigidIndex];
+
+ int stack[B3_PLVBH_TRAVERSE_MAX_STACK_SIZE];
+
+ int stackSize = 1;
+ stack[0] = *rootNodeIndex;
+
+ while(stackSize)
+ {
+ int internalOrLeafNodeIndex = stack[ stackSize - 1 ];
+ --stackSize;
+
+ int isLeaf = isLeafNode(internalOrLeafNodeIndex); //Internal node if false
+ int bvhNodeIndex = getIndexWithInternalNodeMarkerRemoved(internalOrLeafNodeIndex);
+
+ //Optimization - if the BVH is structured as a binary radix tree, then
+ //each internal node corresponds to a contiguous range of leaf nodes(internalNodeLeafIndexRanges[]).
+ //This can be used to avoid testing each AABB-AABB pair twice, including preventing each node from colliding with itself.
+ {
+ int highestLeafIndex = (isLeaf) ? bvhNodeIndex : internalNodeLeafIndexRanges[bvhNodeIndex].y;
+ if(highestLeafIndex <= queryBvhNodeIndex) continue;
+ }
+
+ //bvhRigidIndex is not used if internal node
+ int bvhRigidIndex = (isLeaf) ? mortonCodesAndAabbIndices[bvhNodeIndex].m_value : -1;
+
+ b3AabbCL bvhNodeAabb = (isLeaf) ? rigidAabbs[bvhRigidIndex] : internalNodeAabbs[bvhNodeIndex];
+ if( TestAabbAgainstAabb2(&queryAabb, &bvhNodeAabb) )
+ {
+ if(isLeaf)
+ {
+ int4 pair;
+ pair.x = rigidAabbs[queryRigidIndex].m_minIndices[3];
+ pair.y = rigidAabbs[bvhRigidIndex].m_minIndices[3];
+ pair.z = NEW_PAIR_MARKER;
+ pair.w = NEW_PAIR_MARKER;
+
+ int pairIndex = atomic_inc(out_numPairs);
+ if(pairIndex < maxPairs) out_overlappingPairs[pairIndex] = pair;
+ }
+
+ if(!isLeaf) //Internal node
+ {
+ if(stackSize + 2 > B3_PLVBH_TRAVERSE_MAX_STACK_SIZE)
+ {
+ //Error
+ }
+ else
+ {
+ stack[ stackSize++ ] = internalNodeChildIndices[bvhNodeIndex].x;
+ stack[ stackSize++ ] = internalNodeChildIndices[bvhNodeIndex].y;
+ }
+ }
+ }
+
+ }
+}
+
+
+//From rayCastKernels.cl
+typedef struct
+{
+ float4 m_from;
+ float4 m_to;
+} b3RayInfo;
+//From rayCastKernels.cl
+
+b3Vector3 b3Vector3_normalize(b3Vector3 v)
+{
+ b3Vector3 normal = (b3Vector3){v.x, v.y, v.z, 0.f};
+ return normalize(normal); //OpenCL normalize == vector4 normalize
+}
+b3Scalar b3Vector3_length2(b3Vector3 v) { return v.x*v.x + v.y*v.y + v.z*v.z; }
+b3Scalar b3Vector3_dot(b3Vector3 a, b3Vector3 b) { return a.x*b.x + a.y*b.y + a.z*b.z; }
+
+int rayIntersectsAabb(b3Vector3 rayOrigin, b3Scalar rayLength, b3Vector3 rayNormalizedDirection, b3AabbCL aabb)
+{
+ //AABB is considered as 3 pairs of 2 planes( {x_min, x_max}, {y_min, y_max}, {z_min, z_max} ).
+ //t_min is the point of intersection with the closer plane, t_max is the point of intersection with the farther plane.
+ //
+ //if (rayNormalizedDirection.x < 0.0f), then max.x will be the near plane
+ //and min.x will be the far plane; otherwise, it is reversed.
+ //
+ //In order for there to be a collision, the t_min and t_max of each pair must overlap.
+ //This can be tested for by selecting the highest t_min and lowest t_max and comparing them.
+
+ int4 isNegative = isless( rayNormalizedDirection, ((b3Vector3){0.0f, 0.0f, 0.0f, 0.0f}) ); //isless(x,y) returns (x < y)
+
+ //When using vector types, the select() function checks the most signficant bit,
+ //but isless() sets the least significant bit.
+ isNegative <<= 31;
+
+ //select(b, a, condition) == condition ? a : b
+ //When using select() with vector types, (condition[i]) is true if its most significant bit is 1
+ b3Vector3 t_min = ( select(aabb.m_min, aabb.m_max, isNegative) - rayOrigin ) / rayNormalizedDirection;
+ b3Vector3 t_max = ( select(aabb.m_max, aabb.m_min, isNegative) - rayOrigin ) / rayNormalizedDirection;
+
+ b3Scalar t_min_final = 0.0f;
+ b3Scalar t_max_final = rayLength;
+
+ //Must use fmin()/fmax(); if one of the parameters is NaN, then the parameter that is not NaN is returned.
+ //Behavior of min()/max() with NaNs is undefined. (See OpenCL Specification 1.2 [6.12.2] and [6.12.4])
+ //Since the innermost fmin()/fmax() is always not NaN, this should never return NaN.
+ t_min_final = fmax( t_min.z, fmax(t_min.y, fmax(t_min.x, t_min_final)) );
+ t_max_final = fmin( t_max.z, fmin(t_max.y, fmin(t_max.x, t_max_final)) );
+
+ return (t_min_final <= t_max_final);
+}
+
+__kernel void plbvhRayTraverse(__global b3AabbCL* rigidAabbs,
+
+ __global int* rootNodeIndex,
+ __global int2* internalNodeChildIndices,
+ __global b3AabbCL* internalNodeAabbs,
+ __global int2* internalNodeLeafIndexRanges,
+ __global SortDataCL* mortonCodesAndAabbIndices,
+
+ __global b3RayInfo* rays,
+
+ __global int* out_numRayRigidPairs,
+ __global int2* out_rayRigidPairs,
+ int maxRayRigidPairs, int numRays)
+{
+ int rayIndex = get_global_id(0);
+ if(rayIndex >= numRays) return;
+
+ //
+ b3Vector3 rayFrom = rays[rayIndex].m_from;
+ b3Vector3 rayTo = rays[rayIndex].m_to;
+ b3Vector3 rayNormalizedDirection = b3Vector3_normalize(rayTo - rayFrom);
+ b3Scalar rayLength = b3Sqrt( b3Vector3_length2(rayTo - rayFrom) );
+
+ //
+ int stack[B3_PLVBH_TRAVERSE_MAX_STACK_SIZE];
+
+ int stackSize = 1;
+ stack[0] = *rootNodeIndex;
+
+ while(stackSize)
+ {
+ int internalOrLeafNodeIndex = stack[ stackSize - 1 ];
+ --stackSize;
+
+ int isLeaf = isLeafNode(internalOrLeafNodeIndex); //Internal node if false
+ int bvhNodeIndex = getIndexWithInternalNodeMarkerRemoved(internalOrLeafNodeIndex);
+
+ //bvhRigidIndex is not used if internal node
+ int bvhRigidIndex = (isLeaf) ? mortonCodesAndAabbIndices[bvhNodeIndex].m_value : -1;
+
+ b3AabbCL bvhNodeAabb = (isLeaf) ? rigidAabbs[bvhRigidIndex] : internalNodeAabbs[bvhNodeIndex];
+ if( rayIntersectsAabb(rayFrom, rayLength, rayNormalizedDirection, bvhNodeAabb) )
+ {
+ if(isLeaf)
+ {
+ int2 rayRigidPair;
+ rayRigidPair.x = rayIndex;
+ rayRigidPair.y = rigidAabbs[bvhRigidIndex].m_minIndices[3];
+
+ int pairIndex = atomic_inc(out_numRayRigidPairs);
+ if(pairIndex < maxRayRigidPairs) out_rayRigidPairs[pairIndex] = rayRigidPair;
+ }
+
+ if(!isLeaf) //Internal node
+ {
+ if(stackSize + 2 > B3_PLVBH_TRAVERSE_MAX_STACK_SIZE)
+ {
+ //Error
+ }
+ else
+ {
+ stack[ stackSize++ ] = internalNodeChildIndices[bvhNodeIndex].x;
+ stack[ stackSize++ ] = internalNodeChildIndices[bvhNodeIndex].y;
+ }
+ }
+ }
+ }
+}
+
+__kernel void plbvhLargeAabbAabbTest(__global b3AabbCL* smallAabbs, __global b3AabbCL* largeAabbs,
+ __global int* out_numPairs, __global int4* out_overlappingPairs,
+ int maxPairs, int numLargeAabbRigids, int numSmallAabbRigids)
+{
+ int smallAabbIndex = get_global_id(0);
+ if(smallAabbIndex >= numSmallAabbRigids) return;
+
+ b3AabbCL smallAabb = smallAabbs[smallAabbIndex];
+ for(int i = 0; i < numLargeAabbRigids; ++i)
+ {
+ b3AabbCL largeAabb = largeAabbs[i];
+ if( TestAabbAgainstAabb2(&smallAabb, &largeAabb) )
+ {
+ int4 pair;
+ pair.x = largeAabb.m_minIndices[3];
+ pair.y = smallAabb.m_minIndices[3];
+ pair.z = NEW_PAIR_MARKER;
+ pair.w = NEW_PAIR_MARKER;
+
+ int pairIndex = atomic_inc(out_numPairs);
+ if(pairIndex < maxPairs) out_overlappingPairs[pairIndex] = pair;
+ }
+ }
+}
+__kernel void plbvhLargeAabbRayTest(__global b3AabbCL* largeRigidAabbs, __global b3RayInfo* rays,
+ __global int* out_numRayRigidPairs, __global int2* out_rayRigidPairs,
+ int numLargeAabbRigids, int maxRayRigidPairs, int numRays)
+{
+ int rayIndex = get_global_id(0);
+ if(rayIndex >= numRays) return;
+
+ b3Vector3 rayFrom = rays[rayIndex].m_from;
+ b3Vector3 rayTo = rays[rayIndex].m_to;
+ b3Vector3 rayNormalizedDirection = b3Vector3_normalize(rayTo - rayFrom);
+ b3Scalar rayLength = b3Sqrt( b3Vector3_length2(rayTo - rayFrom) );
+
+ for(int i = 0; i < numLargeAabbRigids; ++i)
+ {
+ b3AabbCL rigidAabb = largeRigidAabbs[i];
+ if( rayIntersectsAabb(rayFrom, rayLength, rayNormalizedDirection, rigidAabb) )
+ {
+ int2 rayRigidPair;
+ rayRigidPair.x = rayIndex;
+ rayRigidPair.y = rigidAabb.m_minIndices[3];
+
+ int pairIndex = atomic_inc(out_numRayRigidPairs);
+ if(pairIndex < maxRayRigidPairs) out_rayRigidPairs[pairIndex] = rayRigidPair;
+ }
+ }
+}
+
+
+//Set so that it is always greater than the actual common prefixes, and never selected as a parent node.
+//If there are no duplicates, then the highest common prefix is 32 or 64, depending on the number of bits used for the z-curve.
+//Duplicate common prefixes increase the highest common prefix at most by the number of bits used to index the leaf node.
+//Since 32 bit ints are used to index leaf nodes, the max prefix is 64(32 + 32 bit z-curve) or 96(32 + 64 bit z-curve).
+#define B3_PLBVH_INVALID_COMMON_PREFIX 128
+
+#define B3_PLBVH_ROOT_NODE_MARKER -1
+
+#define b3Int64 long
+
+int computeCommonPrefixLength(b3Int64 i, b3Int64 j) { return (int)clz(i ^ j); }
+b3Int64 computeCommonPrefix(b3Int64 i, b3Int64 j)
+{
+ //This function only needs to return (i & j) in order for the algorithm to work,
+ //but it may help with debugging to mask out the lower bits.
+
+ b3Int64 commonPrefixLength = (b3Int64)computeCommonPrefixLength(i, j);
+
+ b3Int64 sharedBits = i & j;
+ b3Int64 bitmask = ((b3Int64)(~0)) << (64 - commonPrefixLength); //Set all bits after the common prefix to 0
+
+ return sharedBits & bitmask;
+}
+
+//Same as computeCommonPrefixLength(), but allows for prefixes with different lengths
+int getSharedPrefixLength(b3Int64 prefixA, int prefixLengthA, b3Int64 prefixB, int prefixLengthB)
+{
+ return b3Min( computeCommonPrefixLength(prefixA, prefixB), b3Min(prefixLengthA, prefixLengthB) );
+}
+
+__kernel void computeAdjacentPairCommonPrefix(__global SortDataCL* mortonCodesAndAabbIndices,
+ __global b3Int64* out_commonPrefixes,
+ __global int* out_commonPrefixLengths,
+ int numInternalNodes)
+{
+ int internalNodeIndex = get_global_id(0);
+ if (internalNodeIndex >= numInternalNodes) return;
+
+ //Here, (internalNodeIndex + 1) is never out of bounds since it is a leaf node index,
+ //and the number of internal nodes is always numLeafNodes - 1
+ int leftLeafIndex = internalNodeIndex;
+ int rightLeafIndex = internalNodeIndex + 1;
+
+ int leftLeafMortonCode = mortonCodesAndAabbIndices[leftLeafIndex].m_key;
+ int rightLeafMortonCode = mortonCodesAndAabbIndices[rightLeafIndex].m_key;
+
+ //Binary radix tree construction algorithm does not work if there are duplicate morton codes.
+ //Append the index of each leaf node to each morton code so that there are no duplicates.
+ //The algorithm also requires that the morton codes are sorted in ascending order; this requirement
+ //is also satisfied with this method, as (leftLeafIndex < rightLeafIndex) is always true.
+ //
+ //upsample(a, b) == ( ((b3Int64)a) << 32) | b
+ b3Int64 nonduplicateLeftMortonCode = upsample(leftLeafMortonCode, leftLeafIndex);
+ b3Int64 nonduplicateRightMortonCode = upsample(rightLeafMortonCode, rightLeafIndex);
+
+ out_commonPrefixes[internalNodeIndex] = computeCommonPrefix(nonduplicateLeftMortonCode, nonduplicateRightMortonCode);
+ out_commonPrefixLengths[internalNodeIndex] = computeCommonPrefixLength(nonduplicateLeftMortonCode, nonduplicateRightMortonCode);
+}
+
+
+__kernel void buildBinaryRadixTreeLeafNodes(__global int* commonPrefixLengths, __global int* out_leafNodeParentNodes,
+ __global int2* out_childNodes, int numLeafNodes)
+{
+ int leafNodeIndex = get_global_id(0);
+ if (leafNodeIndex >= numLeafNodes) return;
+
+ int numInternalNodes = numLeafNodes - 1;
+
+ int leftSplitIndex = leafNodeIndex - 1;
+ int rightSplitIndex = leafNodeIndex;
+
+ int leftCommonPrefix = (leftSplitIndex >= 0) ? commonPrefixLengths[leftSplitIndex] : B3_PLBVH_INVALID_COMMON_PREFIX;
+ int rightCommonPrefix = (rightSplitIndex < numInternalNodes) ? commonPrefixLengths[rightSplitIndex] : B3_PLBVH_INVALID_COMMON_PREFIX;
+
+ //Parent node is the highest adjacent common prefix that is lower than the node's common prefix
+ //Leaf nodes are considered as having the highest common prefix
+ int isLeftHigherCommonPrefix = (leftCommonPrefix > rightCommonPrefix);
+
+ //Handle cases for the edge nodes; the first and last node
+ //For leaf nodes, leftCommonPrefix and rightCommonPrefix should never both be B3_PLBVH_INVALID_COMMON_PREFIX
+ if(leftCommonPrefix == B3_PLBVH_INVALID_COMMON_PREFIX) isLeftHigherCommonPrefix = false;
+ if(rightCommonPrefix == B3_PLBVH_INVALID_COMMON_PREFIX) isLeftHigherCommonPrefix = true;
+
+ int parentNodeIndex = (isLeftHigherCommonPrefix) ? leftSplitIndex : rightSplitIndex;
+ out_leafNodeParentNodes[leafNodeIndex] = parentNodeIndex;
+
+ int isRightChild = (isLeftHigherCommonPrefix); //If the left node is the parent, then this node is its right child and vice versa
+
+ //out_childNodesAsInt[0] == int2.x == left child
+ //out_childNodesAsInt[1] == int2.y == right child
+ int isLeaf = 1;
+ __global int* out_childNodesAsInt = (__global int*)(&out_childNodes[parentNodeIndex]);
+ out_childNodesAsInt[isRightChild] = getIndexWithInternalNodeMarkerSet(isLeaf, leafNodeIndex);
+}
+
+__kernel void buildBinaryRadixTreeInternalNodes(__global b3Int64* commonPrefixes, __global int* commonPrefixLengths,
+ __global int2* out_childNodes,
+ __global int* out_internalNodeParentNodes, __global int* out_rootNodeIndex,
+ int numInternalNodes)
+{
+ int internalNodeIndex = get_group_id(0) * get_local_size(0) + get_local_id(0);
+ if(internalNodeIndex >= numInternalNodes) return;
+
+ b3Int64 nodePrefix = commonPrefixes[internalNodeIndex];
+ int nodePrefixLength = commonPrefixLengths[internalNodeIndex];
+
+//#define USE_LINEAR_SEARCH
+#ifdef USE_LINEAR_SEARCH
+ int leftIndex = -1;
+ int rightIndex = -1;
+
+ //Find nearest element to left with a lower common prefix
+ for(int i = internalNodeIndex - 1; i >= 0; --i)
+ {
+ int nodeLeftSharedPrefixLength = getSharedPrefixLength(nodePrefix, nodePrefixLength, commonPrefixes[i], commonPrefixLengths[i]);
+ if(nodeLeftSharedPrefixLength < nodePrefixLength)
+ {
+ leftIndex = i;
+ break;
+ }
+ }
+
+ //Find nearest element to right with a lower common prefix
+ for(int i = internalNodeIndex + 1; i < numInternalNodes; ++i)
+ {
+ int nodeRightSharedPrefixLength = getSharedPrefixLength(nodePrefix, nodePrefixLength, commonPrefixes[i], commonPrefixLengths[i]);
+ if(nodeRightSharedPrefixLength < nodePrefixLength)
+ {
+ rightIndex = i;
+ break;
+ }
+ }
+
+#else //Use binary search
+
+ //Find nearest element to left with a lower common prefix
+ int leftIndex = -1;
+ {
+ int lower = 0;
+ int upper = internalNodeIndex - 1;
+
+ while(lower <= upper)
+ {
+ int mid = (lower + upper) / 2;
+ b3Int64 midPrefix = commonPrefixes[mid];
+ int midPrefixLength = commonPrefixLengths[mid];
+
+ int nodeMidSharedPrefixLength = getSharedPrefixLength(nodePrefix, nodePrefixLength, midPrefix, midPrefixLength);
+ if(nodeMidSharedPrefixLength < nodePrefixLength)
+ {
+ int right = mid + 1;
+ if(right < internalNodeIndex)
+ {
+ b3Int64 rightPrefix = commonPrefixes[right];
+ int rightPrefixLength = commonPrefixLengths[right];
+
+ int nodeRightSharedPrefixLength = getSharedPrefixLength(nodePrefix, nodePrefixLength, rightPrefix, rightPrefixLength);
+ if(nodeRightSharedPrefixLength < nodePrefixLength)
+ {
+ lower = right;
+ leftIndex = right;
+ }
+ else
+ {
+ leftIndex = mid;
+ break;
+ }
+ }
+ else
+ {
+ leftIndex = mid;
+ break;
+ }
+ }
+ else upper = mid - 1;
+ }
+ }
+
+ //Find nearest element to right with a lower common prefix
+ int rightIndex = -1;
+ {
+ int lower = internalNodeIndex + 1;
+ int upper = numInternalNodes - 1;
+
+ while(lower <= upper)
+ {
+ int mid = (lower + upper) / 2;
+ b3Int64 midPrefix = commonPrefixes[mid];
+ int midPrefixLength = commonPrefixLengths[mid];
+
+ int nodeMidSharedPrefixLength = getSharedPrefixLength(nodePrefix, nodePrefixLength, midPrefix, midPrefixLength);
+ if(nodeMidSharedPrefixLength < nodePrefixLength)
+ {
+ int left = mid - 1;
+ if(left > internalNodeIndex)
+ {
+ b3Int64 leftPrefix = commonPrefixes[left];
+ int leftPrefixLength = commonPrefixLengths[left];
+
+ int nodeLeftSharedPrefixLength = getSharedPrefixLength(nodePrefix, nodePrefixLength, leftPrefix, leftPrefixLength);
+ if(nodeLeftSharedPrefixLength < nodePrefixLength)
+ {
+ upper = left;
+ rightIndex = left;
+ }
+ else
+ {
+ rightIndex = mid;
+ break;
+ }
+ }
+ else
+ {
+ rightIndex = mid;
+ break;
+ }
+ }
+ else lower = mid + 1;
+ }
+ }
+#endif
+
+ //Select parent
+ {
+ int leftPrefixLength = (leftIndex != -1) ? commonPrefixLengths[leftIndex] : B3_PLBVH_INVALID_COMMON_PREFIX;
+ int rightPrefixLength = (rightIndex != -1) ? commonPrefixLengths[rightIndex] : B3_PLBVH_INVALID_COMMON_PREFIX;
+
+ int isLeftHigherPrefixLength = (leftPrefixLength > rightPrefixLength);
+
+ if(leftPrefixLength == B3_PLBVH_INVALID_COMMON_PREFIX) isLeftHigherPrefixLength = false;
+ else if(rightPrefixLength == B3_PLBVH_INVALID_COMMON_PREFIX) isLeftHigherPrefixLength = true;
+
+ int parentNodeIndex = (isLeftHigherPrefixLength) ? leftIndex : rightIndex;
+
+ int isRootNode = (leftIndex == -1 && rightIndex == -1);
+ out_internalNodeParentNodes[internalNodeIndex] = (!isRootNode) ? parentNodeIndex : B3_PLBVH_ROOT_NODE_MARKER;
+
+ int isLeaf = 0;
+ if(!isRootNode)
+ {
+ int isRightChild = (isLeftHigherPrefixLength); //If the left node is the parent, then this node is its right child and vice versa
+
+ //out_childNodesAsInt[0] == int2.x == left child
+ //out_childNodesAsInt[1] == int2.y == right child
+ __global int* out_childNodesAsInt = (__global int*)(&out_childNodes[parentNodeIndex]);
+ out_childNodesAsInt[isRightChild] = getIndexWithInternalNodeMarkerSet(isLeaf, internalNodeIndex);
+ }
+ else *out_rootNodeIndex = getIndexWithInternalNodeMarkerSet(isLeaf, internalNodeIndex);
+ }
+}
+
+__kernel void findDistanceFromRoot(__global int* rootNodeIndex, __global int* internalNodeParentNodes,
+ __global int* out_maxDistanceFromRoot, __global int* out_distanceFromRoot, int numInternalNodes)
+{
+ if( get_global_id(0) == 0 ) atomic_xchg(out_maxDistanceFromRoot, 0);
+
+ int internalNodeIndex = get_global_id(0);
+ if(internalNodeIndex >= numInternalNodes) return;
+
+ //
+ int distanceFromRoot = 0;
+ {
+ int parentIndex = internalNodeParentNodes[internalNodeIndex];
+ while(parentIndex != B3_PLBVH_ROOT_NODE_MARKER)
+ {
+ parentIndex = internalNodeParentNodes[parentIndex];
+ ++distanceFromRoot;
+ }
+ }
+ out_distanceFromRoot[internalNodeIndex] = distanceFromRoot;
+
+ //
+ __local int localMaxDistanceFromRoot;
+ if( get_local_id(0) == 0 ) localMaxDistanceFromRoot = 0;
+ barrier(CLK_LOCAL_MEM_FENCE);
+
+ atomic_max(&localMaxDistanceFromRoot, distanceFromRoot);
+ barrier(CLK_LOCAL_MEM_FENCE);
+
+ if( get_local_id(0) == 0 ) atomic_max(out_maxDistanceFromRoot, localMaxDistanceFromRoot);
+}
+
+__kernel void buildBinaryRadixTreeAabbsRecursive(__global int* distanceFromRoot, __global SortDataCL* mortonCodesAndAabbIndices,
+ __global int2* childNodes,
+ __global b3AabbCL* leafNodeAabbs, __global b3AabbCL* internalNodeAabbs,
+ int maxDistanceFromRoot, int processedDistance, int numInternalNodes)
+{
+ int internalNodeIndex = get_global_id(0);
+ if(internalNodeIndex >= numInternalNodes) return;
+
+ int distance = distanceFromRoot[internalNodeIndex];
+
+ if(distance == processedDistance)
+ {
+ int leftChildIndex = childNodes[internalNodeIndex].x;
+ int rightChildIndex = childNodes[internalNodeIndex].y;
+
+ int isLeftChildLeaf = isLeafNode(leftChildIndex);
+ int isRightChildLeaf = isLeafNode(rightChildIndex);
+
+ leftChildIndex = getIndexWithInternalNodeMarkerRemoved(leftChildIndex);
+ rightChildIndex = getIndexWithInternalNodeMarkerRemoved(rightChildIndex);
+
+ //leftRigidIndex/rightRigidIndex is not used if internal node
+ int leftRigidIndex = (isLeftChildLeaf) ? mortonCodesAndAabbIndices[leftChildIndex].m_value : -1;
+ int rightRigidIndex = (isRightChildLeaf) ? mortonCodesAndAabbIndices[rightChildIndex].m_value : -1;
+
+ b3AabbCL leftChildAabb = (isLeftChildLeaf) ? leafNodeAabbs[leftRigidIndex] : internalNodeAabbs[leftChildIndex];
+ b3AabbCL rightChildAabb = (isRightChildLeaf) ? leafNodeAabbs[rightRigidIndex] : internalNodeAabbs[rightChildIndex];
+
+ b3AabbCL mergedAabb;
+ mergedAabb.m_min = b3Min(leftChildAabb.m_min, rightChildAabb.m_min);
+ mergedAabb.m_max = b3Max(leftChildAabb.m_max, rightChildAabb.m_max);
+ internalNodeAabbs[internalNodeIndex] = mergedAabb;
+ }
+}
+
+__kernel void findLeafIndexRanges(__global int2* internalNodeChildNodes, __global int2* out_leafIndexRanges, int numInternalNodes)
+{
+ int internalNodeIndex = get_global_id(0);
+ if(internalNodeIndex >= numInternalNodes) return;
+
+ int numLeafNodes = numInternalNodes + 1;
+
+ int2 childNodes = internalNodeChildNodes[internalNodeIndex];
+
+ int2 leafIndexRange; //x == min leaf index, y == max leaf index
+
+ //Find lowest leaf index covered by this internal node
+ {
+ int lowestIndex = childNodes.x; //childNodes.x == Left child
+ while( !isLeafNode(lowestIndex) ) lowestIndex = internalNodeChildNodes[ getIndexWithInternalNodeMarkerRemoved(lowestIndex) ].x;
+ leafIndexRange.x = lowestIndex;
+ }
+
+ //Find highest leaf index covered by this internal node
+ {
+ int highestIndex = childNodes.y; //childNodes.y == Right child
+ while( !isLeafNode(highestIndex) ) highestIndex = internalNodeChildNodes[ getIndexWithInternalNodeMarkerRemoved(highestIndex) ].y;
+ leafIndexRange.y = highestIndex;
+ }
+
+ //
+ out_leafIndexRanges[internalNodeIndex] = leafIndexRange;
+}
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/kernels/parallelLinearBvhKernels.h b/thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/kernels/parallelLinearBvhKernels.h
new file mode 100644
index 0000000000..5eb8f45b16
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/kernels/parallelLinearBvhKernels.h
@@ -0,0 +1,729 @@
+//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
+static const char* parallelLinearBvhCL= \
+"/*\n"
+"This software is provided 'as-is', without any express or implied warranty.\n"
+"In no event will the authors be held liable for any damages arising from the use of this software.\n"
+"Permission is granted to anyone to use this software for any purpose,\n"
+"including commercial applications, and to alter it and redistribute it freely,\n"
+"subject to the following restrictions:\n"
+"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.\n"
+"2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
+"3. This notice may not be removed or altered from any source distribution.\n"
+"*/\n"
+"//Initial Author Jackson Lee, 2014\n"
+"typedef float b3Scalar;\n"
+"typedef float4 b3Vector3;\n"
+"#define b3Max max\n"
+"#define b3Min min\n"
+"#define b3Sqrt sqrt\n"
+"typedef struct\n"
+"{\n"
+" unsigned int m_key;\n"
+" unsigned int m_value;\n"
+"} SortDataCL;\n"
+"typedef struct \n"
+"{\n"
+" union\n"
+" {\n"
+" float4 m_min;\n"
+" float m_minElems[4];\n"
+" int m_minIndices[4];\n"
+" };\n"
+" union\n"
+" {\n"
+" float4 m_max;\n"
+" float m_maxElems[4];\n"
+" int m_maxIndices[4];\n"
+" };\n"
+"} b3AabbCL;\n"
+"unsigned int interleaveBits(unsigned int x)\n"
+"{\n"
+" //........ ........ ......12 3456789A //x\n"
+" //....1..2 ..3..4.. 5..6..7. .8..9..A //x after interleaving bits\n"
+" \n"
+" //......12 3456789A ......12 3456789A //x ^ (x << 16)\n"
+" //11111111 ........ ........ 11111111 //0x FF 00 00 FF\n"
+" //......12 ........ ........ 3456789A //x = (x ^ (x << 16)) & 0xFF0000FF;\n"
+" \n"
+" //......12 ........ 3456789A 3456789A //x ^ (x << 8)\n"
+" //......11 ........ 1111.... ....1111 //0x 03 00 F0 0F\n"
+" //......12 ........ 3456.... ....789A //x = (x ^ (x << 8)) & 0x0300F00F;\n"
+" \n"
+" //..12..12 ....3456 3456.... 789A789A //x ^ (x << 4)\n"
+" //......11 ....11.. ..11.... 11....11 //0x 03 0C 30 C3\n"
+" //......12 ....34.. ..56.... 78....9A //x = (x ^ (x << 4)) & 0x030C30C3;\n"
+" \n"
+" //....1212 ..3434.. 5656..78 78..9A9A //x ^ (x << 2)\n"
+" //....1..1 ..1..1.. 1..1..1. .1..1..1 //0x 09 24 92 49\n"
+" //....1..2 ..3..4.. 5..6..7. .8..9..A //x = (x ^ (x << 2)) & 0x09249249;\n"
+" \n"
+" //........ ........ ......11 11111111 //0x000003FF\n"
+" x &= 0x000003FF; //Clear all bits above bit 10\n"
+" \n"
+" x = (x ^ (x << 16)) & 0xFF0000FF;\n"
+" x = (x ^ (x << 8)) & 0x0300F00F;\n"
+" x = (x ^ (x << 4)) & 0x030C30C3;\n"
+" x = (x ^ (x << 2)) & 0x09249249;\n"
+" \n"
+" return x;\n"
+"}\n"
+"unsigned int getMortonCode(unsigned int x, unsigned int y, unsigned int z)\n"
+"{\n"
+" return interleaveBits(x) << 0 | interleaveBits(y) << 1 | interleaveBits(z) << 2;\n"
+"}\n"
+"__kernel void separateAabbs(__global b3AabbCL* unseparatedAabbs, __global int* aabbIndices, __global b3AabbCL* out_aabbs, int numAabbsToSeparate)\n"
+"{\n"
+" int separatedAabbIndex = get_global_id(0);\n"
+" if(separatedAabbIndex >= numAabbsToSeparate) return;\n"
+" int unseparatedAabbIndex = aabbIndices[separatedAabbIndex];\n"
+" out_aabbs[separatedAabbIndex] = unseparatedAabbs[unseparatedAabbIndex];\n"
+"}\n"
+"//Should replace with an optimized parallel reduction\n"
+"__kernel void findAllNodesMergedAabb(__global b3AabbCL* out_mergedAabb, int numAabbsNeedingMerge)\n"
+"{\n"
+" //Each time this kernel is added to the command queue, \n"
+" //the number of AABBs needing to be merged is halved\n"
+" //\n"
+" //Example with 159 AABBs:\n"
+" // numRemainingAabbs == 159 / 2 + 159 % 2 == 80\n"
+" // numMergedAabbs == 159 - 80 == 79\n"
+" //So, indices [0, 78] are merged with [0 + 80, 78 + 80]\n"
+" \n"
+" int numRemainingAabbs = numAabbsNeedingMerge / 2 + numAabbsNeedingMerge % 2;\n"
+" int numMergedAabbs = numAabbsNeedingMerge - numRemainingAabbs;\n"
+" \n"
+" int aabbIndex = get_global_id(0);\n"
+" if(aabbIndex >= numMergedAabbs) return;\n"
+" \n"
+" int otherAabbIndex = aabbIndex + numRemainingAabbs;\n"
+" \n"
+" b3AabbCL aabb = out_mergedAabb[aabbIndex];\n"
+" b3AabbCL otherAabb = out_mergedAabb[otherAabbIndex];\n"
+" \n"
+" b3AabbCL mergedAabb;\n"
+" mergedAabb.m_min = b3Min(aabb.m_min, otherAabb.m_min);\n"
+" mergedAabb.m_max = b3Max(aabb.m_max, otherAabb.m_max);\n"
+" out_mergedAabb[aabbIndex] = mergedAabb;\n"
+"}\n"
+"__kernel void assignMortonCodesAndAabbIndicies(__global b3AabbCL* worldSpaceAabbs, __global b3AabbCL* mergedAabbOfAllNodes, \n"
+" __global SortDataCL* out_mortonCodesAndAabbIndices, int numAabbs)\n"
+"{\n"
+" int leafNodeIndex = get_global_id(0); //Leaf node index == AABB index\n"
+" if(leafNodeIndex >= numAabbs) return;\n"
+" \n"
+" b3AabbCL mergedAabb = mergedAabbOfAllNodes[0];\n"
+" b3Vector3 gridCenter = (mergedAabb.m_min + mergedAabb.m_max) * 0.5f;\n"
+" b3Vector3 gridCellSize = (mergedAabb.m_max - mergedAabb.m_min) / (float)1024;\n"
+" \n"
+" b3AabbCL aabb = worldSpaceAabbs[leafNodeIndex];\n"
+" b3Vector3 aabbCenter = (aabb.m_min + aabb.m_max) * 0.5f;\n"
+" b3Vector3 aabbCenterRelativeToGrid = aabbCenter - gridCenter;\n"
+" \n"
+" //Quantize into integer coordinates\n"
+" //floor() is needed to prevent the center cell, at (0,0,0) from being twice the size\n"
+" b3Vector3 gridPosition = aabbCenterRelativeToGrid / gridCellSize;\n"
+" \n"
+" int4 discretePosition;\n"
+" discretePosition.x = (int)( (gridPosition.x >= 0.0f) ? gridPosition.x : floor(gridPosition.x) );\n"
+" discretePosition.y = (int)( (gridPosition.y >= 0.0f) ? gridPosition.y : floor(gridPosition.y) );\n"
+" discretePosition.z = (int)( (gridPosition.z >= 0.0f) ? gridPosition.z : floor(gridPosition.z) );\n"
+" \n"
+" //Clamp coordinates into [-512, 511], then convert range from [-512, 511] to [0, 1023]\n"
+" discretePosition = b3Max( -512, b3Min(discretePosition, 511) );\n"
+" discretePosition += 512;\n"
+" \n"
+" //Interleave bits(assign a morton code, also known as a z-curve)\n"
+" unsigned int mortonCode = getMortonCode(discretePosition.x, discretePosition.y, discretePosition.z);\n"
+" \n"
+" //\n"
+" SortDataCL mortonCodeIndexPair;\n"
+" mortonCodeIndexPair.m_key = mortonCode;\n"
+" mortonCodeIndexPair.m_value = leafNodeIndex;\n"
+" \n"
+" out_mortonCodesAndAabbIndices[leafNodeIndex] = mortonCodeIndexPair;\n"
+"}\n"
+"#define B3_PLVBH_TRAVERSE_MAX_STACK_SIZE 128\n"
+"//The most significant bit(0x80000000) of a int32 is used to distinguish between leaf and internal nodes.\n"
+"//If it is set, then the index is for an internal node; otherwise, it is a leaf node. \n"
+"//In both cases, the bit should be cleared to access the actual node index.\n"
+"int isLeafNode(int index) { return (index >> 31 == 0); }\n"
+"int getIndexWithInternalNodeMarkerRemoved(int index) { return index & (~0x80000000); }\n"
+"int getIndexWithInternalNodeMarkerSet(int isLeaf, int index) { return (isLeaf) ? index : (index | 0x80000000); }\n"
+"//From sap.cl\n"
+"#define NEW_PAIR_MARKER -1\n"
+"bool TestAabbAgainstAabb2(const b3AabbCL* aabb1, const b3AabbCL* aabb2)\n"
+"{\n"
+" bool overlap = true;\n"
+" overlap = (aabb1->m_min.x > aabb2->m_max.x || aabb1->m_max.x < aabb2->m_min.x) ? false : overlap;\n"
+" overlap = (aabb1->m_min.z > aabb2->m_max.z || aabb1->m_max.z < aabb2->m_min.z) ? false : overlap;\n"
+" overlap = (aabb1->m_min.y > aabb2->m_max.y || aabb1->m_max.y < aabb2->m_min.y) ? false : overlap;\n"
+" return overlap;\n"
+"}\n"
+"//From sap.cl\n"
+"__kernel void plbvhCalculateOverlappingPairs(__global b3AabbCL* rigidAabbs, \n"
+" __global int* rootNodeIndex, \n"
+" __global int2* internalNodeChildIndices, \n"
+" __global b3AabbCL* internalNodeAabbs,\n"
+" __global int2* internalNodeLeafIndexRanges,\n"
+" \n"
+" __global SortDataCL* mortonCodesAndAabbIndices,\n"
+" __global int* out_numPairs, __global int4* out_overlappingPairs, \n"
+" int maxPairs, int numQueryAabbs)\n"
+"{\n"
+" //Using get_group_id()/get_local_id() is Faster than get_global_id(0) since\n"
+" //mortonCodesAndAabbIndices[] contains rigid body indices sorted along the z-curve (more spatially coherent)\n"
+" int queryBvhNodeIndex = get_group_id(0) * get_local_size(0) + get_local_id(0);\n"
+" if(queryBvhNodeIndex >= numQueryAabbs) return;\n"
+" \n"
+" int queryRigidIndex = mortonCodesAndAabbIndices[queryBvhNodeIndex].m_value;\n"
+" b3AabbCL queryAabb = rigidAabbs[queryRigidIndex];\n"
+" \n"
+" int stack[B3_PLVBH_TRAVERSE_MAX_STACK_SIZE];\n"
+" \n"
+" int stackSize = 1;\n"
+" stack[0] = *rootNodeIndex;\n"
+" \n"
+" while(stackSize)\n"
+" {\n"
+" int internalOrLeafNodeIndex = stack[ stackSize - 1 ];\n"
+" --stackSize;\n"
+" \n"
+" int isLeaf = isLeafNode(internalOrLeafNodeIndex); //Internal node if false\n"
+" int bvhNodeIndex = getIndexWithInternalNodeMarkerRemoved(internalOrLeafNodeIndex);\n"
+" \n"
+" //Optimization - if the BVH is structured as a binary radix tree, then\n"
+" //each internal node corresponds to a contiguous range of leaf nodes(internalNodeLeafIndexRanges[]).\n"
+" //This can be used to avoid testing each AABB-AABB pair twice, including preventing each node from colliding with itself.\n"
+" {\n"
+" int highestLeafIndex = (isLeaf) ? bvhNodeIndex : internalNodeLeafIndexRanges[bvhNodeIndex].y;\n"
+" if(highestLeafIndex <= queryBvhNodeIndex) continue;\n"
+" }\n"
+" \n"
+" //bvhRigidIndex is not used if internal node\n"
+" int bvhRigidIndex = (isLeaf) ? mortonCodesAndAabbIndices[bvhNodeIndex].m_value : -1;\n"
+" \n"
+" b3AabbCL bvhNodeAabb = (isLeaf) ? rigidAabbs[bvhRigidIndex] : internalNodeAabbs[bvhNodeIndex];\n"
+" if( TestAabbAgainstAabb2(&queryAabb, &bvhNodeAabb) )\n"
+" {\n"
+" if(isLeaf)\n"
+" {\n"
+" int4 pair;\n"
+" pair.x = rigidAabbs[queryRigidIndex].m_minIndices[3];\n"
+" pair.y = rigidAabbs[bvhRigidIndex].m_minIndices[3];\n"
+" pair.z = NEW_PAIR_MARKER;\n"
+" pair.w = NEW_PAIR_MARKER;\n"
+" \n"
+" int pairIndex = atomic_inc(out_numPairs);\n"
+" if(pairIndex < maxPairs) out_overlappingPairs[pairIndex] = pair;\n"
+" }\n"
+" \n"
+" if(!isLeaf) //Internal node\n"
+" {\n"
+" if(stackSize + 2 > B3_PLVBH_TRAVERSE_MAX_STACK_SIZE)\n"
+" {\n"
+" //Error\n"
+" }\n"
+" else\n"
+" {\n"
+" stack[ stackSize++ ] = internalNodeChildIndices[bvhNodeIndex].x;\n"
+" stack[ stackSize++ ] = internalNodeChildIndices[bvhNodeIndex].y;\n"
+" }\n"
+" }\n"
+" }\n"
+" \n"
+" }\n"
+"}\n"
+"//From rayCastKernels.cl\n"
+"typedef struct\n"
+"{\n"
+" float4 m_from;\n"
+" float4 m_to;\n"
+"} b3RayInfo;\n"
+"//From rayCastKernels.cl\n"
+"b3Vector3 b3Vector3_normalize(b3Vector3 v)\n"
+"{\n"
+" b3Vector3 normal = (b3Vector3){v.x, v.y, v.z, 0.f};\n"
+" return normalize(normal); //OpenCL normalize == vector4 normalize\n"
+"}\n"
+"b3Scalar b3Vector3_length2(b3Vector3 v) { return v.x*v.x + v.y*v.y + v.z*v.z; }\n"
+"b3Scalar b3Vector3_dot(b3Vector3 a, b3Vector3 b) { return a.x*b.x + a.y*b.y + a.z*b.z; }\n"
+"int rayIntersectsAabb(b3Vector3 rayOrigin, b3Scalar rayLength, b3Vector3 rayNormalizedDirection, b3AabbCL aabb)\n"
+"{\n"
+" //AABB is considered as 3 pairs of 2 planes( {x_min, x_max}, {y_min, y_max}, {z_min, z_max} ).\n"
+" //t_min is the point of intersection with the closer plane, t_max is the point of intersection with the farther plane.\n"
+" //\n"
+" //if (rayNormalizedDirection.x < 0.0f), then max.x will be the near plane \n"
+" //and min.x will be the far plane; otherwise, it is reversed.\n"
+" //\n"
+" //In order for there to be a collision, the t_min and t_max of each pair must overlap.\n"
+" //This can be tested for by selecting the highest t_min and lowest t_max and comparing them.\n"
+" \n"
+" int4 isNegative = isless( rayNormalizedDirection, ((b3Vector3){0.0f, 0.0f, 0.0f, 0.0f}) ); //isless(x,y) returns (x < y)\n"
+" \n"
+" //When using vector types, the select() function checks the most signficant bit, \n"
+" //but isless() sets the least significant bit.\n"
+" isNegative <<= 31;\n"
+" //select(b, a, condition) == condition ? a : b\n"
+" //When using select() with vector types, (condition[i]) is true if its most significant bit is 1\n"
+" b3Vector3 t_min = ( select(aabb.m_min, aabb.m_max, isNegative) - rayOrigin ) / rayNormalizedDirection;\n"
+" b3Vector3 t_max = ( select(aabb.m_max, aabb.m_min, isNegative) - rayOrigin ) / rayNormalizedDirection;\n"
+" \n"
+" b3Scalar t_min_final = 0.0f;\n"
+" b3Scalar t_max_final = rayLength;\n"
+" \n"
+" //Must use fmin()/fmax(); if one of the parameters is NaN, then the parameter that is not NaN is returned. \n"
+" //Behavior of min()/max() with NaNs is undefined. (See OpenCL Specification 1.2 [6.12.2] and [6.12.4])\n"
+" //Since the innermost fmin()/fmax() is always not NaN, this should never return NaN.\n"
+" t_min_final = fmax( t_min.z, fmax(t_min.y, fmax(t_min.x, t_min_final)) );\n"
+" t_max_final = fmin( t_max.z, fmin(t_max.y, fmin(t_max.x, t_max_final)) );\n"
+" \n"
+" return (t_min_final <= t_max_final);\n"
+"}\n"
+"__kernel void plbvhRayTraverse(__global b3AabbCL* rigidAabbs,\n"
+" __global int* rootNodeIndex, \n"
+" __global int2* internalNodeChildIndices, \n"
+" __global b3AabbCL* internalNodeAabbs,\n"
+" __global int2* internalNodeLeafIndexRanges,\n"
+" __global SortDataCL* mortonCodesAndAabbIndices,\n"
+" \n"
+" __global b3RayInfo* rays,\n"
+" \n"
+" __global int* out_numRayRigidPairs, \n"
+" __global int2* out_rayRigidPairs,\n"
+" int maxRayRigidPairs, int numRays)\n"
+"{\n"
+" int rayIndex = get_global_id(0);\n"
+" if(rayIndex >= numRays) return;\n"
+" \n"
+" //\n"
+" b3Vector3 rayFrom = rays[rayIndex].m_from;\n"
+" b3Vector3 rayTo = rays[rayIndex].m_to;\n"
+" b3Vector3 rayNormalizedDirection = b3Vector3_normalize(rayTo - rayFrom);\n"
+" b3Scalar rayLength = b3Sqrt( b3Vector3_length2(rayTo - rayFrom) );\n"
+" \n"
+" //\n"
+" int stack[B3_PLVBH_TRAVERSE_MAX_STACK_SIZE];\n"
+" \n"
+" int stackSize = 1;\n"
+" stack[0] = *rootNodeIndex;\n"
+" \n"
+" while(stackSize)\n"
+" {\n"
+" int internalOrLeafNodeIndex = stack[ stackSize - 1 ];\n"
+" --stackSize;\n"
+" \n"
+" int isLeaf = isLeafNode(internalOrLeafNodeIndex); //Internal node if false\n"
+" int bvhNodeIndex = getIndexWithInternalNodeMarkerRemoved(internalOrLeafNodeIndex);\n"
+" \n"
+" //bvhRigidIndex is not used if internal node\n"
+" int bvhRigidIndex = (isLeaf) ? mortonCodesAndAabbIndices[bvhNodeIndex].m_value : -1;\n"
+" \n"
+" b3AabbCL bvhNodeAabb = (isLeaf) ? rigidAabbs[bvhRigidIndex] : internalNodeAabbs[bvhNodeIndex];\n"
+" if( rayIntersectsAabb(rayFrom, rayLength, rayNormalizedDirection, bvhNodeAabb) )\n"
+" {\n"
+" if(isLeaf)\n"
+" {\n"
+" int2 rayRigidPair;\n"
+" rayRigidPair.x = rayIndex;\n"
+" rayRigidPair.y = rigidAabbs[bvhRigidIndex].m_minIndices[3];\n"
+" \n"
+" int pairIndex = atomic_inc(out_numRayRigidPairs);\n"
+" if(pairIndex < maxRayRigidPairs) out_rayRigidPairs[pairIndex] = rayRigidPair;\n"
+" }\n"
+" \n"
+" if(!isLeaf) //Internal node\n"
+" {\n"
+" if(stackSize + 2 > B3_PLVBH_TRAVERSE_MAX_STACK_SIZE)\n"
+" {\n"
+" //Error\n"
+" }\n"
+" else\n"
+" {\n"
+" stack[ stackSize++ ] = internalNodeChildIndices[bvhNodeIndex].x;\n"
+" stack[ stackSize++ ] = internalNodeChildIndices[bvhNodeIndex].y;\n"
+" }\n"
+" }\n"
+" }\n"
+" }\n"
+"}\n"
+"__kernel void plbvhLargeAabbAabbTest(__global b3AabbCL* smallAabbs, __global b3AabbCL* largeAabbs, \n"
+" __global int* out_numPairs, __global int4* out_overlappingPairs, \n"
+" int maxPairs, int numLargeAabbRigids, int numSmallAabbRigids)\n"
+"{\n"
+" int smallAabbIndex = get_global_id(0);\n"
+" if(smallAabbIndex >= numSmallAabbRigids) return;\n"
+" \n"
+" b3AabbCL smallAabb = smallAabbs[smallAabbIndex];\n"
+" for(int i = 0; i < numLargeAabbRigids; ++i)\n"
+" {\n"
+" b3AabbCL largeAabb = largeAabbs[i];\n"
+" if( TestAabbAgainstAabb2(&smallAabb, &largeAabb) )\n"
+" {\n"
+" int4 pair;\n"
+" pair.x = largeAabb.m_minIndices[3];\n"
+" pair.y = smallAabb.m_minIndices[3];\n"
+" pair.z = NEW_PAIR_MARKER;\n"
+" pair.w = NEW_PAIR_MARKER;\n"
+" \n"
+" int pairIndex = atomic_inc(out_numPairs);\n"
+" if(pairIndex < maxPairs) out_overlappingPairs[pairIndex] = pair;\n"
+" }\n"
+" }\n"
+"}\n"
+"__kernel void plbvhLargeAabbRayTest(__global b3AabbCL* largeRigidAabbs, __global b3RayInfo* rays,\n"
+" __global int* out_numRayRigidPairs, __global int2* out_rayRigidPairs,\n"
+" int numLargeAabbRigids, int maxRayRigidPairs, int numRays)\n"
+"{\n"
+" int rayIndex = get_global_id(0);\n"
+" if(rayIndex >= numRays) return;\n"
+" \n"
+" b3Vector3 rayFrom = rays[rayIndex].m_from;\n"
+" b3Vector3 rayTo = rays[rayIndex].m_to;\n"
+" b3Vector3 rayNormalizedDirection = b3Vector3_normalize(rayTo - rayFrom);\n"
+" b3Scalar rayLength = b3Sqrt( b3Vector3_length2(rayTo - rayFrom) );\n"
+" \n"
+" for(int i = 0; i < numLargeAabbRigids; ++i)\n"
+" {\n"
+" b3AabbCL rigidAabb = largeRigidAabbs[i];\n"
+" if( rayIntersectsAabb(rayFrom, rayLength, rayNormalizedDirection, rigidAabb) )\n"
+" {\n"
+" int2 rayRigidPair;\n"
+" rayRigidPair.x = rayIndex;\n"
+" rayRigidPair.y = rigidAabb.m_minIndices[3];\n"
+" \n"
+" int pairIndex = atomic_inc(out_numRayRigidPairs);\n"
+" if(pairIndex < maxRayRigidPairs) out_rayRigidPairs[pairIndex] = rayRigidPair;\n"
+" }\n"
+" }\n"
+"}\n"
+"//Set so that it is always greater than the actual common prefixes, and never selected as a parent node.\n"
+"//If there are no duplicates, then the highest common prefix is 32 or 64, depending on the number of bits used for the z-curve.\n"
+"//Duplicate common prefixes increase the highest common prefix at most by the number of bits used to index the leaf node.\n"
+"//Since 32 bit ints are used to index leaf nodes, the max prefix is 64(32 + 32 bit z-curve) or 96(32 + 64 bit z-curve).\n"
+"#define B3_PLBVH_INVALID_COMMON_PREFIX 128\n"
+"#define B3_PLBVH_ROOT_NODE_MARKER -1\n"
+"#define b3Int64 long\n"
+"int computeCommonPrefixLength(b3Int64 i, b3Int64 j) { return (int)clz(i ^ j); }\n"
+"b3Int64 computeCommonPrefix(b3Int64 i, b3Int64 j) \n"
+"{\n"
+" //This function only needs to return (i & j) in order for the algorithm to work,\n"
+" //but it may help with debugging to mask out the lower bits.\n"
+" b3Int64 commonPrefixLength = (b3Int64)computeCommonPrefixLength(i, j);\n"
+" b3Int64 sharedBits = i & j;\n"
+" b3Int64 bitmask = ((b3Int64)(~0)) << (64 - commonPrefixLength); //Set all bits after the common prefix to 0\n"
+" \n"
+" return sharedBits & bitmask;\n"
+"}\n"
+"//Same as computeCommonPrefixLength(), but allows for prefixes with different lengths\n"
+"int getSharedPrefixLength(b3Int64 prefixA, int prefixLengthA, b3Int64 prefixB, int prefixLengthB)\n"
+"{\n"
+" return b3Min( computeCommonPrefixLength(prefixA, prefixB), b3Min(prefixLengthA, prefixLengthB) );\n"
+"}\n"
+"__kernel void computeAdjacentPairCommonPrefix(__global SortDataCL* mortonCodesAndAabbIndices,\n"
+" __global b3Int64* out_commonPrefixes,\n"
+" __global int* out_commonPrefixLengths,\n"
+" int numInternalNodes)\n"
+"{\n"
+" int internalNodeIndex = get_global_id(0);\n"
+" if (internalNodeIndex >= numInternalNodes) return;\n"
+" \n"
+" //Here, (internalNodeIndex + 1) is never out of bounds since it is a leaf node index,\n"
+" //and the number of internal nodes is always numLeafNodes - 1\n"
+" int leftLeafIndex = internalNodeIndex;\n"
+" int rightLeafIndex = internalNodeIndex + 1;\n"
+" \n"
+" int leftLeafMortonCode = mortonCodesAndAabbIndices[leftLeafIndex].m_key;\n"
+" int rightLeafMortonCode = mortonCodesAndAabbIndices[rightLeafIndex].m_key;\n"
+" \n"
+" //Binary radix tree construction algorithm does not work if there are duplicate morton codes.\n"
+" //Append the index of each leaf node to each morton code so that there are no duplicates.\n"
+" //The algorithm also requires that the morton codes are sorted in ascending order; this requirement\n"
+" //is also satisfied with this method, as (leftLeafIndex < rightLeafIndex) is always true.\n"
+" //\n"
+" //upsample(a, b) == ( ((b3Int64)a) << 32) | b\n"
+" b3Int64 nonduplicateLeftMortonCode = upsample(leftLeafMortonCode, leftLeafIndex);\n"
+" b3Int64 nonduplicateRightMortonCode = upsample(rightLeafMortonCode, rightLeafIndex);\n"
+" \n"
+" out_commonPrefixes[internalNodeIndex] = computeCommonPrefix(nonduplicateLeftMortonCode, nonduplicateRightMortonCode);\n"
+" out_commonPrefixLengths[internalNodeIndex] = computeCommonPrefixLength(nonduplicateLeftMortonCode, nonduplicateRightMortonCode);\n"
+"}\n"
+"__kernel void buildBinaryRadixTreeLeafNodes(__global int* commonPrefixLengths, __global int* out_leafNodeParentNodes,\n"
+" __global int2* out_childNodes, int numLeafNodes)\n"
+"{\n"
+" int leafNodeIndex = get_global_id(0);\n"
+" if (leafNodeIndex >= numLeafNodes) return;\n"
+" \n"
+" int numInternalNodes = numLeafNodes - 1;\n"
+" \n"
+" int leftSplitIndex = leafNodeIndex - 1;\n"
+" int rightSplitIndex = leafNodeIndex;\n"
+" \n"
+" int leftCommonPrefix = (leftSplitIndex >= 0) ? commonPrefixLengths[leftSplitIndex] : B3_PLBVH_INVALID_COMMON_PREFIX;\n"
+" int rightCommonPrefix = (rightSplitIndex < numInternalNodes) ? commonPrefixLengths[rightSplitIndex] : B3_PLBVH_INVALID_COMMON_PREFIX;\n"
+" \n"
+" //Parent node is the highest adjacent common prefix that is lower than the node's common prefix\n"
+" //Leaf nodes are considered as having the highest common prefix\n"
+" int isLeftHigherCommonPrefix = (leftCommonPrefix > rightCommonPrefix);\n"
+" \n"
+" //Handle cases for the edge nodes; the first and last node\n"
+" //For leaf nodes, leftCommonPrefix and rightCommonPrefix should never both be B3_PLBVH_INVALID_COMMON_PREFIX\n"
+" if(leftCommonPrefix == B3_PLBVH_INVALID_COMMON_PREFIX) isLeftHigherCommonPrefix = false;\n"
+" if(rightCommonPrefix == B3_PLBVH_INVALID_COMMON_PREFIX) isLeftHigherCommonPrefix = true;\n"
+" \n"
+" int parentNodeIndex = (isLeftHigherCommonPrefix) ? leftSplitIndex : rightSplitIndex;\n"
+" out_leafNodeParentNodes[leafNodeIndex] = parentNodeIndex;\n"
+" \n"
+" int isRightChild = (isLeftHigherCommonPrefix); //If the left node is the parent, then this node is its right child and vice versa\n"
+" \n"
+" //out_childNodesAsInt[0] == int2.x == left child\n"
+" //out_childNodesAsInt[1] == int2.y == right child\n"
+" int isLeaf = 1;\n"
+" __global int* out_childNodesAsInt = (__global int*)(&out_childNodes[parentNodeIndex]);\n"
+" out_childNodesAsInt[isRightChild] = getIndexWithInternalNodeMarkerSet(isLeaf, leafNodeIndex);\n"
+"}\n"
+"__kernel void buildBinaryRadixTreeInternalNodes(__global b3Int64* commonPrefixes, __global int* commonPrefixLengths,\n"
+" __global int2* out_childNodes,\n"
+" __global int* out_internalNodeParentNodes, __global int* out_rootNodeIndex,\n"
+" int numInternalNodes)\n"
+"{\n"
+" int internalNodeIndex = get_group_id(0) * get_local_size(0) + get_local_id(0);\n"
+" if(internalNodeIndex >= numInternalNodes) return;\n"
+" \n"
+" b3Int64 nodePrefix = commonPrefixes[internalNodeIndex];\n"
+" int nodePrefixLength = commonPrefixLengths[internalNodeIndex];\n"
+" \n"
+"//#define USE_LINEAR_SEARCH\n"
+"#ifdef USE_LINEAR_SEARCH\n"
+" int leftIndex = -1;\n"
+" int rightIndex = -1;\n"
+" \n"
+" //Find nearest element to left with a lower common prefix\n"
+" for(int i = internalNodeIndex - 1; i >= 0; --i)\n"
+" {\n"
+" int nodeLeftSharedPrefixLength = getSharedPrefixLength(nodePrefix, nodePrefixLength, commonPrefixes[i], commonPrefixLengths[i]);\n"
+" if(nodeLeftSharedPrefixLength < nodePrefixLength)\n"
+" {\n"
+" leftIndex = i;\n"
+" break;\n"
+" }\n"
+" }\n"
+" \n"
+" //Find nearest element to right with a lower common prefix\n"
+" for(int i = internalNodeIndex + 1; i < numInternalNodes; ++i)\n"
+" {\n"
+" int nodeRightSharedPrefixLength = getSharedPrefixLength(nodePrefix, nodePrefixLength, commonPrefixes[i], commonPrefixLengths[i]);\n"
+" if(nodeRightSharedPrefixLength < nodePrefixLength)\n"
+" {\n"
+" rightIndex = i;\n"
+" break;\n"
+" }\n"
+" }\n"
+" \n"
+"#else //Use binary search\n"
+" //Find nearest element to left with a lower common prefix\n"
+" int leftIndex = -1;\n"
+" {\n"
+" int lower = 0;\n"
+" int upper = internalNodeIndex - 1;\n"
+" \n"
+" while(lower <= upper)\n"
+" {\n"
+" int mid = (lower + upper) / 2;\n"
+" b3Int64 midPrefix = commonPrefixes[mid];\n"
+" int midPrefixLength = commonPrefixLengths[mid];\n"
+" \n"
+" int nodeMidSharedPrefixLength = getSharedPrefixLength(nodePrefix, nodePrefixLength, midPrefix, midPrefixLength);\n"
+" if(nodeMidSharedPrefixLength < nodePrefixLength) \n"
+" {\n"
+" int right = mid + 1;\n"
+" if(right < internalNodeIndex)\n"
+" {\n"
+" b3Int64 rightPrefix = commonPrefixes[right];\n"
+" int rightPrefixLength = commonPrefixLengths[right];\n"
+" \n"
+" int nodeRightSharedPrefixLength = getSharedPrefixLength(nodePrefix, nodePrefixLength, rightPrefix, rightPrefixLength);\n"
+" if(nodeRightSharedPrefixLength < nodePrefixLength) \n"
+" {\n"
+" lower = right;\n"
+" leftIndex = right;\n"
+" }\n"
+" else \n"
+" {\n"
+" leftIndex = mid;\n"
+" break;\n"
+" }\n"
+" }\n"
+" else \n"
+" {\n"
+" leftIndex = mid;\n"
+" break;\n"
+" }\n"
+" }\n"
+" else upper = mid - 1;\n"
+" }\n"
+" }\n"
+" \n"
+" //Find nearest element to right with a lower common prefix\n"
+" int rightIndex = -1;\n"
+" {\n"
+" int lower = internalNodeIndex + 1;\n"
+" int upper = numInternalNodes - 1;\n"
+" \n"
+" while(lower <= upper)\n"
+" {\n"
+" int mid = (lower + upper) / 2;\n"
+" b3Int64 midPrefix = commonPrefixes[mid];\n"
+" int midPrefixLength = commonPrefixLengths[mid];\n"
+" \n"
+" int nodeMidSharedPrefixLength = getSharedPrefixLength(nodePrefix, nodePrefixLength, midPrefix, midPrefixLength);\n"
+" if(nodeMidSharedPrefixLength < nodePrefixLength) \n"
+" {\n"
+" int left = mid - 1;\n"
+" if(left > internalNodeIndex)\n"
+" {\n"
+" b3Int64 leftPrefix = commonPrefixes[left];\n"
+" int leftPrefixLength = commonPrefixLengths[left];\n"
+" \n"
+" int nodeLeftSharedPrefixLength = getSharedPrefixLength(nodePrefix, nodePrefixLength, leftPrefix, leftPrefixLength);\n"
+" if(nodeLeftSharedPrefixLength < nodePrefixLength) \n"
+" {\n"
+" upper = left;\n"
+" rightIndex = left;\n"
+" }\n"
+" else \n"
+" {\n"
+" rightIndex = mid;\n"
+" break;\n"
+" }\n"
+" }\n"
+" else \n"
+" {\n"
+" rightIndex = mid;\n"
+" break;\n"
+" }\n"
+" }\n"
+" else lower = mid + 1;\n"
+" }\n"
+" }\n"
+"#endif\n"
+" \n"
+" //Select parent\n"
+" {\n"
+" int leftPrefixLength = (leftIndex != -1) ? commonPrefixLengths[leftIndex] : B3_PLBVH_INVALID_COMMON_PREFIX;\n"
+" int rightPrefixLength = (rightIndex != -1) ? commonPrefixLengths[rightIndex] : B3_PLBVH_INVALID_COMMON_PREFIX;\n"
+" \n"
+" int isLeftHigherPrefixLength = (leftPrefixLength > rightPrefixLength);\n"
+" \n"
+" if(leftPrefixLength == B3_PLBVH_INVALID_COMMON_PREFIX) isLeftHigherPrefixLength = false;\n"
+" else if(rightPrefixLength == B3_PLBVH_INVALID_COMMON_PREFIX) isLeftHigherPrefixLength = true;\n"
+" \n"
+" int parentNodeIndex = (isLeftHigherPrefixLength) ? leftIndex : rightIndex;\n"
+" \n"
+" int isRootNode = (leftIndex == -1 && rightIndex == -1);\n"
+" out_internalNodeParentNodes[internalNodeIndex] = (!isRootNode) ? parentNodeIndex : B3_PLBVH_ROOT_NODE_MARKER;\n"
+" \n"
+" int isLeaf = 0;\n"
+" if(!isRootNode)\n"
+" {\n"
+" int isRightChild = (isLeftHigherPrefixLength); //If the left node is the parent, then this node is its right child and vice versa\n"
+" \n"
+" //out_childNodesAsInt[0] == int2.x == left child\n"
+" //out_childNodesAsInt[1] == int2.y == right child\n"
+" __global int* out_childNodesAsInt = (__global int*)(&out_childNodes[parentNodeIndex]);\n"
+" out_childNodesAsInt[isRightChild] = getIndexWithInternalNodeMarkerSet(isLeaf, internalNodeIndex);\n"
+" }\n"
+" else *out_rootNodeIndex = getIndexWithInternalNodeMarkerSet(isLeaf, internalNodeIndex);\n"
+" }\n"
+"}\n"
+"__kernel void findDistanceFromRoot(__global int* rootNodeIndex, __global int* internalNodeParentNodes,\n"
+" __global int* out_maxDistanceFromRoot, __global int* out_distanceFromRoot, int numInternalNodes)\n"
+"{\n"
+" if( get_global_id(0) == 0 ) atomic_xchg(out_maxDistanceFromRoot, 0);\n"
+" int internalNodeIndex = get_global_id(0);\n"
+" if(internalNodeIndex >= numInternalNodes) return;\n"
+" \n"
+" //\n"
+" int distanceFromRoot = 0;\n"
+" {\n"
+" int parentIndex = internalNodeParentNodes[internalNodeIndex];\n"
+" while(parentIndex != B3_PLBVH_ROOT_NODE_MARKER)\n"
+" {\n"
+" parentIndex = internalNodeParentNodes[parentIndex];\n"
+" ++distanceFromRoot;\n"
+" }\n"
+" }\n"
+" out_distanceFromRoot[internalNodeIndex] = distanceFromRoot;\n"
+" \n"
+" //\n"
+" __local int localMaxDistanceFromRoot;\n"
+" if( get_local_id(0) == 0 ) localMaxDistanceFromRoot = 0;\n"
+" barrier(CLK_LOCAL_MEM_FENCE);\n"
+" \n"
+" atomic_max(&localMaxDistanceFromRoot, distanceFromRoot);\n"
+" barrier(CLK_LOCAL_MEM_FENCE);\n"
+" \n"
+" if( get_local_id(0) == 0 ) atomic_max(out_maxDistanceFromRoot, localMaxDistanceFromRoot);\n"
+"}\n"
+"__kernel void buildBinaryRadixTreeAabbsRecursive(__global int* distanceFromRoot, __global SortDataCL* mortonCodesAndAabbIndices,\n"
+" __global int2* childNodes,\n"
+" __global b3AabbCL* leafNodeAabbs, __global b3AabbCL* internalNodeAabbs,\n"
+" int maxDistanceFromRoot, int processedDistance, int numInternalNodes)\n"
+"{\n"
+" int internalNodeIndex = get_global_id(0);\n"
+" if(internalNodeIndex >= numInternalNodes) return;\n"
+" \n"
+" int distance = distanceFromRoot[internalNodeIndex];\n"
+" \n"
+" if(distance == processedDistance)\n"
+" {\n"
+" int leftChildIndex = childNodes[internalNodeIndex].x;\n"
+" int rightChildIndex = childNodes[internalNodeIndex].y;\n"
+" \n"
+" int isLeftChildLeaf = isLeafNode(leftChildIndex);\n"
+" int isRightChildLeaf = isLeafNode(rightChildIndex);\n"
+" \n"
+" leftChildIndex = getIndexWithInternalNodeMarkerRemoved(leftChildIndex);\n"
+" rightChildIndex = getIndexWithInternalNodeMarkerRemoved(rightChildIndex);\n"
+" \n"
+" //leftRigidIndex/rightRigidIndex is not used if internal node\n"
+" int leftRigidIndex = (isLeftChildLeaf) ? mortonCodesAndAabbIndices[leftChildIndex].m_value : -1;\n"
+" int rightRigidIndex = (isRightChildLeaf) ? mortonCodesAndAabbIndices[rightChildIndex].m_value : -1;\n"
+" \n"
+" b3AabbCL leftChildAabb = (isLeftChildLeaf) ? leafNodeAabbs[leftRigidIndex] : internalNodeAabbs[leftChildIndex];\n"
+" b3AabbCL rightChildAabb = (isRightChildLeaf) ? leafNodeAabbs[rightRigidIndex] : internalNodeAabbs[rightChildIndex];\n"
+" \n"
+" b3AabbCL mergedAabb;\n"
+" mergedAabb.m_min = b3Min(leftChildAabb.m_min, rightChildAabb.m_min);\n"
+" mergedAabb.m_max = b3Max(leftChildAabb.m_max, rightChildAabb.m_max);\n"
+" internalNodeAabbs[internalNodeIndex] = mergedAabb;\n"
+" }\n"
+"}\n"
+"__kernel void findLeafIndexRanges(__global int2* internalNodeChildNodes, __global int2* out_leafIndexRanges, int numInternalNodes)\n"
+"{\n"
+" int internalNodeIndex = get_global_id(0);\n"
+" if(internalNodeIndex >= numInternalNodes) return;\n"
+" \n"
+" int numLeafNodes = numInternalNodes + 1;\n"
+" \n"
+" int2 childNodes = internalNodeChildNodes[internalNodeIndex];\n"
+" \n"
+" int2 leafIndexRange; //x == min leaf index, y == max leaf index\n"
+" \n"
+" //Find lowest leaf index covered by this internal node\n"
+" {\n"
+" int lowestIndex = childNodes.x; //childNodes.x == Left child\n"
+" while( !isLeafNode(lowestIndex) ) lowestIndex = internalNodeChildNodes[ getIndexWithInternalNodeMarkerRemoved(lowestIndex) ].x;\n"
+" leafIndexRange.x = lowestIndex;\n"
+" }\n"
+" \n"
+" //Find highest leaf index covered by this internal node\n"
+" {\n"
+" int highestIndex = childNodes.y; //childNodes.y == Right child\n"
+" while( !isLeafNode(highestIndex) ) highestIndex = internalNodeChildNodes[ getIndexWithInternalNodeMarkerRemoved(highestIndex) ].y;\n"
+" leafIndexRange.y = highestIndex;\n"
+" }\n"
+" \n"
+" //\n"
+" out_leafIndexRanges[internalNodeIndex] = leafIndexRange;\n"
+"}\n"
+;
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/kernels/sap.cl b/thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/kernels/sap.cl
new file mode 100644
index 0000000000..93f77a6433
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/kernels/sap.cl
@@ -0,0 +1,389 @@
+/*
+Copyright (c) 2012 Advanced Micro Devices, Inc.
+
+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.
+*/
+//Originally written by Erwin Coumans
+
+#define NEW_PAIR_MARKER -1
+
+typedef struct
+{
+ union
+ {
+ float4 m_min;
+ float m_minElems[4];
+ int m_minIndices[4];
+ };
+ union
+ {
+ float4 m_max;
+ float m_maxElems[4];
+ int m_maxIndices[4];
+ };
+} btAabbCL;
+
+
+/// conservative test for overlap between two aabbs
+bool TestAabbAgainstAabb2(const btAabbCL* aabb1, __local const btAabbCL* aabb2);
+bool TestAabbAgainstAabb2(const btAabbCL* aabb1, __local const btAabbCL* aabb2)
+{
+ bool overlap = true;
+ overlap = (aabb1->m_min.x > aabb2->m_max.x || aabb1->m_max.x < aabb2->m_min.x) ? false : overlap;
+ overlap = (aabb1->m_min.z > aabb2->m_max.z || aabb1->m_max.z < aabb2->m_min.z) ? false : overlap;
+ overlap = (aabb1->m_min.y > aabb2->m_max.y || aabb1->m_max.y < aabb2->m_min.y) ? false : overlap;
+ return overlap;
+}
+bool TestAabbAgainstAabb2GlobalGlobal(__global const btAabbCL* aabb1, __global const btAabbCL* aabb2);
+bool TestAabbAgainstAabb2GlobalGlobal(__global const btAabbCL* aabb1, __global const btAabbCL* aabb2)
+{
+ bool overlap = true;
+ overlap = (aabb1->m_min.x > aabb2->m_max.x || aabb1->m_max.x < aabb2->m_min.x) ? false : overlap;
+ overlap = (aabb1->m_min.z > aabb2->m_max.z || aabb1->m_max.z < aabb2->m_min.z) ? false : overlap;
+ overlap = (aabb1->m_min.y > aabb2->m_max.y || aabb1->m_max.y < aabb2->m_min.y) ? false : overlap;
+ return overlap;
+}
+
+bool TestAabbAgainstAabb2Global(const btAabbCL* aabb1, __global const btAabbCL* aabb2);
+bool TestAabbAgainstAabb2Global(const btAabbCL* aabb1, __global const btAabbCL* aabb2)
+{
+ bool overlap = true;
+ overlap = (aabb1->m_min.x > aabb2->m_max.x || aabb1->m_max.x < aabb2->m_min.x) ? false : overlap;
+ overlap = (aabb1->m_min.z > aabb2->m_max.z || aabb1->m_max.z < aabb2->m_min.z) ? false : overlap;
+ overlap = (aabb1->m_min.y > aabb2->m_max.y || aabb1->m_max.y < aabb2->m_min.y) ? false : overlap;
+ return overlap;
+}
+
+
+__kernel void computePairsKernelTwoArrays( __global const btAabbCL* unsortedAabbs, __global const int* unsortedAabbMapping, __global const int* unsortedAabbMapping2, volatile __global int4* pairsOut,volatile __global int* pairCount, int numUnsortedAabbs, int numUnSortedAabbs2, int axis, int maxPairs)
+{
+ int i = get_global_id(0);
+ if (i>=numUnsortedAabbs)
+ return;
+
+ int j = get_global_id(1);
+ if (j>=numUnSortedAabbs2)
+ return;
+
+
+ __global const btAabbCL* unsortedAabbPtr = &unsortedAabbs[unsortedAabbMapping[i]];
+ __global const btAabbCL* unsortedAabbPtr2 = &unsortedAabbs[unsortedAabbMapping2[j]];
+
+ if (TestAabbAgainstAabb2GlobalGlobal(unsortedAabbPtr,unsortedAabbPtr2))
+ {
+ int4 myPair;
+
+ int xIndex = unsortedAabbPtr[0].m_minIndices[3];
+ int yIndex = unsortedAabbPtr2[0].m_minIndices[3];
+ if (xIndex>yIndex)
+ {
+ int tmp = xIndex;
+ xIndex=yIndex;
+ yIndex=tmp;
+ }
+
+ myPair.x = xIndex;
+ myPair.y = yIndex;
+ myPair.z = NEW_PAIR_MARKER;
+ myPair.w = NEW_PAIR_MARKER;
+
+
+ int curPair = atomic_inc (pairCount);
+ if (curPair<maxPairs)
+ {
+ pairsOut[curPair] = myPair; //flush to main memory
+ }
+ }
+}
+
+
+
+__kernel void computePairsKernelBruteForce( __global const btAabbCL* aabbs, volatile __global int4* pairsOut,volatile __global int* pairCount, int numObjects, int axis, int maxPairs)
+{
+ int i = get_global_id(0);
+ if (i>=numObjects)
+ return;
+ for (int j=i+1;j<numObjects;j++)
+ {
+ if (TestAabbAgainstAabb2GlobalGlobal(&aabbs[i],&aabbs[j]))
+ {
+ int4 myPair;
+ myPair.x = aabbs[i].m_minIndices[3];
+ myPair.y = aabbs[j].m_minIndices[3];
+ myPair.z = NEW_PAIR_MARKER;
+ myPair.w = NEW_PAIR_MARKER;
+
+ int curPair = atomic_inc (pairCount);
+ if (curPair<maxPairs)
+ {
+ pairsOut[curPair] = myPair; //flush to main memory
+ }
+ }
+ }
+}
+
+__kernel void computePairsKernelOriginal( __global const btAabbCL* aabbs, volatile __global int4* pairsOut,volatile __global int* pairCount, int numObjects, int axis, int maxPairs)
+{
+ int i = get_global_id(0);
+ if (i>=numObjects)
+ return;
+ for (int j=i+1;j<numObjects;j++)
+ {
+ if(aabbs[i].m_maxElems[axis] < (aabbs[j].m_minElems[axis]))
+ {
+ break;
+ }
+ if (TestAabbAgainstAabb2GlobalGlobal(&aabbs[i],&aabbs[j]))
+ {
+ int4 myPair;
+ myPair.x = aabbs[i].m_minIndices[3];
+ myPair.y = aabbs[j].m_minIndices[3];
+ myPair.z = NEW_PAIR_MARKER;
+ myPair.w = NEW_PAIR_MARKER;
+
+ int curPair = atomic_inc (pairCount);
+ if (curPair<maxPairs)
+ {
+ pairsOut[curPair] = myPair; //flush to main memory
+ }
+ }
+ }
+}
+
+
+
+
+__kernel void computePairsKernelBarrier( __global const btAabbCL* aabbs, volatile __global int4* pairsOut,volatile __global int* pairCount, int numObjects, int axis, int maxPairs)
+{
+ int i = get_global_id(0);
+ int localId = get_local_id(0);
+
+ __local int numActiveWgItems[1];
+ __local int breakRequest[1];
+
+ if (localId==0)
+ {
+ numActiveWgItems[0] = 0;
+ breakRequest[0] = 0;
+ }
+ barrier(CLK_LOCAL_MEM_FENCE);
+ atomic_inc(numActiveWgItems);
+ barrier(CLK_LOCAL_MEM_FENCE);
+ int localBreak = 0;
+
+ int j=i+1;
+ do
+ {
+ barrier(CLK_LOCAL_MEM_FENCE);
+
+ if (j<numObjects)
+ {
+ if(aabbs[i].m_maxElems[axis] < (aabbs[j].m_minElems[axis]))
+ {
+ if (!localBreak)
+ {
+ atomic_inc(breakRequest);
+ localBreak = 1;
+ }
+ }
+ }
+
+ barrier(CLK_LOCAL_MEM_FENCE);
+
+ if (j>=numObjects && !localBreak)
+ {
+ atomic_inc(breakRequest);
+ localBreak = 1;
+ }
+ barrier(CLK_LOCAL_MEM_FENCE);
+
+ if (!localBreak)
+ {
+ if (TestAabbAgainstAabb2GlobalGlobal(&aabbs[i],&aabbs[j]))
+ {
+ int4 myPair;
+ myPair.x = aabbs[i].m_minIndices[3];
+ myPair.y = aabbs[j].m_minIndices[3];
+ myPair.z = NEW_PAIR_MARKER;
+ myPair.w = NEW_PAIR_MARKER;
+
+ int curPair = atomic_inc (pairCount);
+ if (curPair<maxPairs)
+ {
+ pairsOut[curPair] = myPair; //flush to main memory
+ }
+ }
+ }
+ j++;
+
+ } while (breakRequest[0]<numActiveWgItems[0]);
+}
+
+
+__kernel void computePairsKernelLocalSharedMemory( __global const btAabbCL* aabbs, volatile __global int4* pairsOut,volatile __global int* pairCount, int numObjects, int axis, int maxPairs)
+{
+ int i = get_global_id(0);
+ int localId = get_local_id(0);
+
+ __local int numActiveWgItems[1];
+ __local int breakRequest[1];
+ __local btAabbCL localAabbs[128];// = aabbs[i];
+
+ btAabbCL myAabb;
+
+ myAabb = (i<numObjects)? aabbs[i]:aabbs[0];
+ float testValue = myAabb.m_maxElems[axis];
+
+ if (localId==0)
+ {
+ numActiveWgItems[0] = 0;
+ breakRequest[0] = 0;
+ }
+ int localCount=0;
+ int block=0;
+ localAabbs[localId] = (i+block)<numObjects? aabbs[i+block] : aabbs[0];
+ localAabbs[localId+64] = (i+block+64)<numObjects? aabbs[i+block+64]: aabbs[0];
+
+ barrier(CLK_LOCAL_MEM_FENCE);
+ atomic_inc(numActiveWgItems);
+ barrier(CLK_LOCAL_MEM_FENCE);
+ int localBreak = 0;
+
+ int j=i+1;
+ do
+ {
+ barrier(CLK_LOCAL_MEM_FENCE);
+
+ if (j<numObjects)
+ {
+ if(testValue < (localAabbs[localCount+localId+1].m_minElems[axis]))
+ {
+ if (!localBreak)
+ {
+ atomic_inc(breakRequest);
+ localBreak = 1;
+ }
+ }
+ }
+
+ barrier(CLK_LOCAL_MEM_FENCE);
+
+ if (j>=numObjects && !localBreak)
+ {
+ atomic_inc(breakRequest);
+ localBreak = 1;
+ }
+ barrier(CLK_LOCAL_MEM_FENCE);
+
+ if (!localBreak)
+ {
+ if (TestAabbAgainstAabb2(&myAabb,&localAabbs[localCount+localId+1]))
+ {
+ int4 myPair;
+ myPair.x = myAabb.m_minIndices[3];
+ myPair.y = localAabbs[localCount+localId+1].m_minIndices[3];
+ myPair.z = NEW_PAIR_MARKER;
+ myPair.w = NEW_PAIR_MARKER;
+
+ int curPair = atomic_inc (pairCount);
+ if (curPair<maxPairs)
+ {
+ pairsOut[curPair] = myPair; //flush to main memory
+ }
+ }
+ }
+
+ barrier(CLK_LOCAL_MEM_FENCE);
+
+ localCount++;
+ if (localCount==64)
+ {
+ localCount = 0;
+ block+=64;
+ localAabbs[localId] = ((i+block)<numObjects) ? aabbs[i+block] : aabbs[0];
+ localAabbs[localId+64] = ((i+64+block)<numObjects) ? aabbs[i+block+64] : aabbs[0];
+ }
+ j++;
+
+ } while (breakRequest[0]<numActiveWgItems[0]);
+
+}
+
+
+
+
+//http://stereopsis.com/radix.html
+unsigned int FloatFlip(float fl);
+unsigned int FloatFlip(float fl)
+{
+ unsigned int f = *(unsigned int*)&fl;
+ unsigned int mask = -(int)(f >> 31) | 0x80000000;
+ return f ^ mask;
+}
+float IFloatFlip(unsigned int f);
+float IFloatFlip(unsigned int f)
+{
+ unsigned int mask = ((f >> 31) - 1) | 0x80000000;
+ unsigned int fl = f ^ mask;
+ return *(float*)&fl;
+}
+
+
+
+
+__kernel void copyAabbsKernel( __global const btAabbCL* allAabbs, __global btAabbCL* destAabbs, int numObjects)
+{
+ int i = get_global_id(0);
+ if (i>=numObjects)
+ return;
+ int src = destAabbs[i].m_maxIndices[3];
+ destAabbs[i] = allAabbs[src];
+ destAabbs[i].m_maxIndices[3] = src;
+}
+
+
+__kernel void flipFloatKernel( __global const btAabbCL* allAabbs, __global const int* smallAabbMapping, __global int2* sortData, int numObjects, int axis)
+{
+ int i = get_global_id(0);
+ if (i>=numObjects)
+ return;
+
+
+ sortData[i].x = FloatFlip(allAabbs[smallAabbMapping[i]].m_minElems[axis]);
+ sortData[i].y = i;
+
+}
+
+
+__kernel void scatterKernel( __global const btAabbCL* allAabbs, __global const int* smallAabbMapping, volatile __global const int2* sortData, __global btAabbCL* sortedAabbs, int numObjects)
+{
+ int i = get_global_id(0);
+ if (i>=numObjects)
+ return;
+
+ sortedAabbs[i] = allAabbs[smallAabbMapping[sortData[i].y]];
+}
+
+
+
+__kernel void prepareSumVarianceKernel( __global const btAabbCL* allAabbs, __global const int* smallAabbMapping, __global float4* sum, __global float4* sum2,int numAabbs)
+{
+ int i = get_global_id(0);
+ if (i>=numAabbs)
+ return;
+
+ btAabbCL smallAabb = allAabbs[smallAabbMapping[i]];
+
+ float4 s;
+ s = (smallAabb.m_max+smallAabb.m_min)*0.5f;
+ sum[i]=s;
+ sum2[i]=s*s;
+}
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/kernels/sapKernels.h b/thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/kernels/sapKernels.h
new file mode 100644
index 0000000000..04d40fcf26
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/BroadphaseCollision/kernels/sapKernels.h
@@ -0,0 +1,342 @@
+//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
+static const char* sapCL= \
+"/*\n"
+"Copyright (c) 2012 Advanced Micro Devices, Inc. \n"
+"This software is provided 'as-is', without any express or implied warranty.\n"
+"In no event will the authors be held liable for any damages arising from the use of this software.\n"
+"Permission is granted to anyone to use this software for any purpose, \n"
+"including commercial applications, and to alter it and redistribute it freely, \n"
+"subject to the following restrictions:\n"
+"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.\n"
+"2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
+"3. This notice may not be removed or altered from any source distribution.\n"
+"*/\n"
+"//Originally written by Erwin Coumans\n"
+"#define NEW_PAIR_MARKER -1\n"
+"typedef struct \n"
+"{\n"
+" union\n"
+" {\n"
+" float4 m_min;\n"
+" float m_minElems[4];\n"
+" int m_minIndices[4];\n"
+" };\n"
+" union\n"
+" {\n"
+" float4 m_max;\n"
+" float m_maxElems[4];\n"
+" int m_maxIndices[4];\n"
+" };\n"
+"} btAabbCL;\n"
+"/// conservative test for overlap between two aabbs\n"
+"bool TestAabbAgainstAabb2(const btAabbCL* aabb1, __local const btAabbCL* aabb2);\n"
+"bool TestAabbAgainstAabb2(const btAabbCL* aabb1, __local const btAabbCL* aabb2)\n"
+"{\n"
+" bool overlap = true;\n"
+" overlap = (aabb1->m_min.x > aabb2->m_max.x || aabb1->m_max.x < aabb2->m_min.x) ? false : overlap;\n"
+" overlap = (aabb1->m_min.z > aabb2->m_max.z || aabb1->m_max.z < aabb2->m_min.z) ? false : overlap;\n"
+" overlap = (aabb1->m_min.y > aabb2->m_max.y || aabb1->m_max.y < aabb2->m_min.y) ? false : overlap;\n"
+" return overlap;\n"
+"}\n"
+"bool TestAabbAgainstAabb2GlobalGlobal(__global const btAabbCL* aabb1, __global const btAabbCL* aabb2);\n"
+"bool TestAabbAgainstAabb2GlobalGlobal(__global const btAabbCL* aabb1, __global const btAabbCL* aabb2)\n"
+"{\n"
+" bool overlap = true;\n"
+" overlap = (aabb1->m_min.x > aabb2->m_max.x || aabb1->m_max.x < aabb2->m_min.x) ? false : overlap;\n"
+" overlap = (aabb1->m_min.z > aabb2->m_max.z || aabb1->m_max.z < aabb2->m_min.z) ? false : overlap;\n"
+" overlap = (aabb1->m_min.y > aabb2->m_max.y || aabb1->m_max.y < aabb2->m_min.y) ? false : overlap;\n"
+" return overlap;\n"
+"}\n"
+"bool TestAabbAgainstAabb2Global(const btAabbCL* aabb1, __global const btAabbCL* aabb2);\n"
+"bool TestAabbAgainstAabb2Global(const btAabbCL* aabb1, __global const btAabbCL* aabb2)\n"
+"{\n"
+" bool overlap = true;\n"
+" overlap = (aabb1->m_min.x > aabb2->m_max.x || aabb1->m_max.x < aabb2->m_min.x) ? false : overlap;\n"
+" overlap = (aabb1->m_min.z > aabb2->m_max.z || aabb1->m_max.z < aabb2->m_min.z) ? false : overlap;\n"
+" overlap = (aabb1->m_min.y > aabb2->m_max.y || aabb1->m_max.y < aabb2->m_min.y) ? false : overlap;\n"
+" return overlap;\n"
+"}\n"
+"__kernel void computePairsKernelTwoArrays( __global const btAabbCL* unsortedAabbs, __global const int* unsortedAabbMapping, __global const int* unsortedAabbMapping2, volatile __global int4* pairsOut,volatile __global int* pairCount, int numUnsortedAabbs, int numUnSortedAabbs2, int axis, int maxPairs)\n"
+"{\n"
+" int i = get_global_id(0);\n"
+" if (i>=numUnsortedAabbs)\n"
+" return;\n"
+" int j = get_global_id(1);\n"
+" if (j>=numUnSortedAabbs2)\n"
+" return;\n"
+" __global const btAabbCL* unsortedAabbPtr = &unsortedAabbs[unsortedAabbMapping[i]];\n"
+" __global const btAabbCL* unsortedAabbPtr2 = &unsortedAabbs[unsortedAabbMapping2[j]];\n"
+" if (TestAabbAgainstAabb2GlobalGlobal(unsortedAabbPtr,unsortedAabbPtr2))\n"
+" {\n"
+" int4 myPair;\n"
+" \n"
+" int xIndex = unsortedAabbPtr[0].m_minIndices[3];\n"
+" int yIndex = unsortedAabbPtr2[0].m_minIndices[3];\n"
+" if (xIndex>yIndex)\n"
+" {\n"
+" int tmp = xIndex;\n"
+" xIndex=yIndex;\n"
+" yIndex=tmp;\n"
+" }\n"
+" \n"
+" myPair.x = xIndex;\n"
+" myPair.y = yIndex;\n"
+" myPair.z = NEW_PAIR_MARKER;\n"
+" myPair.w = NEW_PAIR_MARKER;\n"
+" int curPair = atomic_inc (pairCount);\n"
+" if (curPair<maxPairs)\n"
+" {\n"
+" pairsOut[curPair] = myPair; //flush to main memory\n"
+" }\n"
+" }\n"
+"}\n"
+"__kernel void computePairsKernelBruteForce( __global const btAabbCL* aabbs, volatile __global int4* pairsOut,volatile __global int* pairCount, int numObjects, int axis, int maxPairs)\n"
+"{\n"
+" int i = get_global_id(0);\n"
+" if (i>=numObjects)\n"
+" return;\n"
+" for (int j=i+1;j<numObjects;j++)\n"
+" {\n"
+" if (TestAabbAgainstAabb2GlobalGlobal(&aabbs[i],&aabbs[j]))\n"
+" {\n"
+" int4 myPair;\n"
+" myPair.x = aabbs[i].m_minIndices[3];\n"
+" myPair.y = aabbs[j].m_minIndices[3];\n"
+" myPair.z = NEW_PAIR_MARKER;\n"
+" myPair.w = NEW_PAIR_MARKER;\n"
+" int curPair = atomic_inc (pairCount);\n"
+" if (curPair<maxPairs)\n"
+" {\n"
+" pairsOut[curPair] = myPair; //flush to main memory\n"
+" }\n"
+" }\n"
+" }\n"
+"}\n"
+"__kernel void computePairsKernelOriginal( __global const btAabbCL* aabbs, volatile __global int4* pairsOut,volatile __global int* pairCount, int numObjects, int axis, int maxPairs)\n"
+"{\n"
+" int i = get_global_id(0);\n"
+" if (i>=numObjects)\n"
+" return;\n"
+" for (int j=i+1;j<numObjects;j++)\n"
+" {\n"
+" if(aabbs[i].m_maxElems[axis] < (aabbs[j].m_minElems[axis])) \n"
+" {\n"
+" break;\n"
+" }\n"
+" if (TestAabbAgainstAabb2GlobalGlobal(&aabbs[i],&aabbs[j]))\n"
+" {\n"
+" int4 myPair;\n"
+" myPair.x = aabbs[i].m_minIndices[3];\n"
+" myPair.y = aabbs[j].m_minIndices[3];\n"
+" myPair.z = NEW_PAIR_MARKER;\n"
+" myPair.w = NEW_PAIR_MARKER;\n"
+" int curPair = atomic_inc (pairCount);\n"
+" if (curPair<maxPairs)\n"
+" {\n"
+" pairsOut[curPair] = myPair; //flush to main memory\n"
+" }\n"
+" }\n"
+" }\n"
+"}\n"
+"__kernel void computePairsKernelBarrier( __global const btAabbCL* aabbs, volatile __global int4* pairsOut,volatile __global int* pairCount, int numObjects, int axis, int maxPairs)\n"
+"{\n"
+" int i = get_global_id(0);\n"
+" int localId = get_local_id(0);\n"
+" __local int numActiveWgItems[1];\n"
+" __local int breakRequest[1];\n"
+" if (localId==0)\n"
+" {\n"
+" numActiveWgItems[0] = 0;\n"
+" breakRequest[0] = 0;\n"
+" }\n"
+" barrier(CLK_LOCAL_MEM_FENCE);\n"
+" atomic_inc(numActiveWgItems);\n"
+" barrier(CLK_LOCAL_MEM_FENCE);\n"
+" int localBreak = 0;\n"
+" int j=i+1;\n"
+" do\n"
+" {\n"
+" barrier(CLK_LOCAL_MEM_FENCE);\n"
+" \n"
+" if (j<numObjects)\n"
+" {\n"
+" if(aabbs[i].m_maxElems[axis] < (aabbs[j].m_minElems[axis])) \n"
+" {\n"
+" if (!localBreak)\n"
+" {\n"
+" atomic_inc(breakRequest);\n"
+" localBreak = 1;\n"
+" }\n"
+" }\n"
+" }\n"
+" \n"
+" barrier(CLK_LOCAL_MEM_FENCE);\n"
+" \n"
+" if (j>=numObjects && !localBreak)\n"
+" {\n"
+" atomic_inc(breakRequest);\n"
+" localBreak = 1;\n"
+" }\n"
+" barrier(CLK_LOCAL_MEM_FENCE);\n"
+" \n"
+" if (!localBreak)\n"
+" {\n"
+" if (TestAabbAgainstAabb2GlobalGlobal(&aabbs[i],&aabbs[j]))\n"
+" {\n"
+" int4 myPair;\n"
+" myPair.x = aabbs[i].m_minIndices[3];\n"
+" myPair.y = aabbs[j].m_minIndices[3];\n"
+" myPair.z = NEW_PAIR_MARKER;\n"
+" myPair.w = NEW_PAIR_MARKER;\n"
+" int curPair = atomic_inc (pairCount);\n"
+" if (curPair<maxPairs)\n"
+" {\n"
+" pairsOut[curPair] = myPair; //flush to main memory\n"
+" }\n"
+" }\n"
+" }\n"
+" j++;\n"
+" } while (breakRequest[0]<numActiveWgItems[0]);\n"
+"}\n"
+"__kernel void computePairsKernelLocalSharedMemory( __global const btAabbCL* aabbs, volatile __global int4* pairsOut,volatile __global int* pairCount, int numObjects, int axis, int maxPairs)\n"
+"{\n"
+" int i = get_global_id(0);\n"
+" int localId = get_local_id(0);\n"
+" __local int numActiveWgItems[1];\n"
+" __local int breakRequest[1];\n"
+" __local btAabbCL localAabbs[128];// = aabbs[i];\n"
+" \n"
+" btAabbCL myAabb;\n"
+" \n"
+" myAabb = (i<numObjects)? aabbs[i]:aabbs[0];\n"
+" float testValue = myAabb.m_maxElems[axis];\n"
+" \n"
+" if (localId==0)\n"
+" {\n"
+" numActiveWgItems[0] = 0;\n"
+" breakRequest[0] = 0;\n"
+" }\n"
+" int localCount=0;\n"
+" int block=0;\n"
+" localAabbs[localId] = (i+block)<numObjects? aabbs[i+block] : aabbs[0];\n"
+" localAabbs[localId+64] = (i+block+64)<numObjects? aabbs[i+block+64]: aabbs[0];\n"
+" \n"
+" barrier(CLK_LOCAL_MEM_FENCE);\n"
+" atomic_inc(numActiveWgItems);\n"
+" barrier(CLK_LOCAL_MEM_FENCE);\n"
+" int localBreak = 0;\n"
+" \n"
+" int j=i+1;\n"
+" do\n"
+" {\n"
+" barrier(CLK_LOCAL_MEM_FENCE);\n"
+" \n"
+" if (j<numObjects)\n"
+" {\n"
+" if(testValue < (localAabbs[localCount+localId+1].m_minElems[axis])) \n"
+" {\n"
+" if (!localBreak)\n"
+" {\n"
+" atomic_inc(breakRequest);\n"
+" localBreak = 1;\n"
+" }\n"
+" }\n"
+" }\n"
+" \n"
+" barrier(CLK_LOCAL_MEM_FENCE);\n"
+" \n"
+" if (j>=numObjects && !localBreak)\n"
+" {\n"
+" atomic_inc(breakRequest);\n"
+" localBreak = 1;\n"
+" }\n"
+" barrier(CLK_LOCAL_MEM_FENCE);\n"
+" \n"
+" if (!localBreak)\n"
+" {\n"
+" if (TestAabbAgainstAabb2(&myAabb,&localAabbs[localCount+localId+1]))\n"
+" {\n"
+" int4 myPair;\n"
+" myPair.x = myAabb.m_minIndices[3];\n"
+" myPair.y = localAabbs[localCount+localId+1].m_minIndices[3];\n"
+" myPair.z = NEW_PAIR_MARKER;\n"
+" myPair.w = NEW_PAIR_MARKER;\n"
+" int curPair = atomic_inc (pairCount);\n"
+" if (curPair<maxPairs)\n"
+" {\n"
+" pairsOut[curPair] = myPair; //flush to main memory\n"
+" }\n"
+" }\n"
+" }\n"
+" \n"
+" barrier(CLK_LOCAL_MEM_FENCE);\n"
+" localCount++;\n"
+" if (localCount==64)\n"
+" {\n"
+" localCount = 0;\n"
+" block+=64; \n"
+" localAabbs[localId] = ((i+block)<numObjects) ? aabbs[i+block] : aabbs[0];\n"
+" localAabbs[localId+64] = ((i+64+block)<numObjects) ? aabbs[i+block+64] : aabbs[0];\n"
+" }\n"
+" j++;\n"
+" \n"
+" } while (breakRequest[0]<numActiveWgItems[0]);\n"
+" \n"
+"}\n"
+"//http://stereopsis.com/radix.html\n"
+"unsigned int FloatFlip(float fl);\n"
+"unsigned int FloatFlip(float fl)\n"
+"{\n"
+" unsigned int f = *(unsigned int*)&fl;\n"
+" unsigned int mask = -(int)(f >> 31) | 0x80000000;\n"
+" return f ^ mask;\n"
+"}\n"
+"float IFloatFlip(unsigned int f);\n"
+"float IFloatFlip(unsigned int f)\n"
+"{\n"
+" unsigned int mask = ((f >> 31) - 1) | 0x80000000;\n"
+" unsigned int fl = f ^ mask;\n"
+" return *(float*)&fl;\n"
+"}\n"
+"__kernel void copyAabbsKernel( __global const btAabbCL* allAabbs, __global btAabbCL* destAabbs, int numObjects)\n"
+"{\n"
+" int i = get_global_id(0);\n"
+" if (i>=numObjects)\n"
+" return;\n"
+" int src = destAabbs[i].m_maxIndices[3];\n"
+" destAabbs[i] = allAabbs[src];\n"
+" destAabbs[i].m_maxIndices[3] = src;\n"
+"}\n"
+"__kernel void flipFloatKernel( __global const btAabbCL* allAabbs, __global const int* smallAabbMapping, __global int2* sortData, int numObjects, int axis)\n"
+"{\n"
+" int i = get_global_id(0);\n"
+" if (i>=numObjects)\n"
+" return;\n"
+" \n"
+" \n"
+" sortData[i].x = FloatFlip(allAabbs[smallAabbMapping[i]].m_minElems[axis]);\n"
+" sortData[i].y = i;\n"
+" \n"
+"}\n"
+"__kernel void scatterKernel( __global const btAabbCL* allAabbs, __global const int* smallAabbMapping, volatile __global const int2* sortData, __global btAabbCL* sortedAabbs, int numObjects)\n"
+"{\n"
+" int i = get_global_id(0);\n"
+" if (i>=numObjects)\n"
+" return;\n"
+" \n"
+" sortedAabbs[i] = allAabbs[smallAabbMapping[sortData[i].y]];\n"
+"}\n"
+"__kernel void prepareSumVarianceKernel( __global const btAabbCL* allAabbs, __global const int* smallAabbMapping, __global float4* sum, __global float4* sum2,int numAabbs)\n"
+"{\n"
+" int i = get_global_id(0);\n"
+" if (i>=numAabbs)\n"
+" return;\n"
+" \n"
+" btAabbCL smallAabb = allAabbs[smallAabbMapping[i]];\n"
+" \n"
+" float4 s;\n"
+" s = (smallAabb.m_max+smallAabb.m_min)*0.5f;\n"
+" sum[i]=s;\n"
+" sum2[i]=s*s; \n"
+"}\n"
+;
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/CMakeLists.txt b/thirdparty/bullet/src/Bullet3OpenCL/CMakeLists.txt
new file mode 100644
index 0000000000..1da58d4a99
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/CMakeLists.txt
@@ -0,0 +1,77 @@
+INCLUDE_DIRECTORIES( ${BULLET_PHYSICS_SOURCE_DIR}/src )
+
+ADD_DEFINITIONS(-DB3_USE_CLEW)
+
+SET(Bullet3OpenCL_clew_SRCS
+ ../clew/clew.c
+ BroadphaseCollision/b3GpuGridBroadphase.cpp
+ BroadphaseCollision/b3GpuSapBroadphase.cpp
+ BroadphaseCollision/b3GpuParallelLinearBvhBroadphase.cpp
+ BroadphaseCollision/b3GpuParallelLinearBvh.cpp
+ Initialize/b3OpenCLUtils.cpp
+ NarrowphaseCollision/b3ContactCache.cpp
+ NarrowphaseCollision/b3ConvexHullContact.cpp
+ NarrowphaseCollision/b3GjkEpa.cpp
+ NarrowphaseCollision/b3OptimizedBvh.cpp
+ NarrowphaseCollision/b3QuantizedBvh.cpp
+ NarrowphaseCollision/b3StridingMeshInterface.cpp
+ NarrowphaseCollision/b3TriangleCallback.cpp
+ NarrowphaseCollision/b3TriangleIndexVertexArray.cpp
+ NarrowphaseCollision/b3VoronoiSimplexSolver.cpp
+ ParallelPrimitives/b3BoundSearchCL.cpp
+ ParallelPrimitives/b3FillCL.cpp
+ ParallelPrimitives/b3LauncherCL.cpp
+ ParallelPrimitives/b3PrefixScanCL.cpp
+ ParallelPrimitives/b3PrefixScanFloat4CL.cpp
+ ParallelPrimitives/b3RadixSort32CL.cpp
+ Raycast/b3GpuRaycast.cpp
+ RigidBody/b3GpuGenericConstraint.cpp
+ RigidBody/b3GpuJacobiContactSolver.cpp
+ RigidBody/b3GpuNarrowPhase.cpp
+ RigidBody/b3GpuPgsConstraintSolver.cpp
+ RigidBody/b3GpuPgsContactSolver.cpp
+ RigidBody/b3GpuRigidBodyPipeline.cpp
+ RigidBody/b3Solver.cpp
+)
+
+
+SET(Bullet3OpenCL_clew_HDRS
+# ${Root_HDRS}
+)
+
+
+ADD_LIBRARY(Bullet3OpenCL_clew ${Bullet3OpenCL_clew_SRCS} ${Bullet3OpenCL_clew_HDRS})
+SET_TARGET_PROPERTIES(Bullet3OpenCL_clew PROPERTIES VERSION ${BULLET_VERSION})
+SET_TARGET_PROPERTIES(Bullet3OpenCL_clew PROPERTIES SOVERSION ${BULLET_VERSION})
+IF (BUILD_SHARED_LIBS)
+ TARGET_LINK_LIBRARIES(Bullet3OpenCL_clew LinearMath Bullet3Dynamics ${CMAKE_DL_LIBS})
+ENDIF (BUILD_SHARED_LIBS)
+
+
+IF (INSTALL_LIBS)
+ IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
+ #INSTALL of other files requires CMake 2.6
+ IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
+ IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+ INSTALL(TARGETS Bullet3OpenCL_clew DESTINATION .)
+ ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+ INSTALL(TARGETS Bullet3OpenCL_clew RUNTIME DESTINATION bin
+ LIBRARY DESTINATION lib${LIB_SUFFIX}
+ ARCHIVE DESTINATION lib${LIB_SUFFIX})
+ INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.h" PATTERN ".svn" EXCLUDE PATTERN "CMakeFiles" EXCLUDE)
+# INSTALL(FILES ../btBullet3OpenCL_clewCommon.h
+#DESTINATION ${INCLUDE_INSTALL_DIR}/Bullet3OpenCL_clew)
+ ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+ ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
+
+ IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+ SET_TARGET_PROPERTIES(Bullet3OpenCL_clew PROPERTIES FRAMEWORK true)
+
+ SET_TARGET_PROPERTIES(Bullet3OpenCL_clew PROPERTIES PUBLIC_HEADER "${Root_HDRS}")
+ # Have to list out sub-directories manually:
+ SET_PROPERTY(SOURCE ${BroadphaseCollision_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/BroadphaseCollision)
+
+ ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+ ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
+ENDIF (INSTALL_LIBS)
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/Initialize/b3OpenCLInclude.h b/thirdparty/bullet/src/Bullet3OpenCL/Initialize/b3OpenCLInclude.h
new file mode 100644
index 0000000000..e79182d7cb
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/Initialize/b3OpenCLInclude.h
@@ -0,0 +1,48 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2011 Advanced Micro Devices, 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 B3_OPENCL_INCLUDE_H
+#define B3_OPENCL_INCLUDE_H
+
+#ifdef B3_USE_CLEW
+ #include "clew/clew.h"
+#else
+
+#ifdef __APPLE__
+#ifdef USE_MINICL
+#include <MiniCL/cl.h>
+#else
+#include <OpenCL/cl.h>
+#include <OpenCL/cl_ext.h> //clLogMessagesToStderrAPPLE
+#endif
+#else
+#ifdef USE_MINICL
+#include <MiniCL/cl.h>
+#else
+#include <CL/cl.h>
+#ifdef _WIN32
+#include "CL/cl_gl.h"
+#endif //_WIN32
+#endif
+#endif //__APPLE__
+#endif //B3_USE_CLEW
+
+#include <assert.h>
+#include <stdio.h>
+#define oclCHECKERROR(a, b) if((a)!=(b)) { printf("OCL Error : %d\n", (a)); assert((a) == (b)); }
+
+
+#endif //B3_OPENCL_INCLUDE_H
+
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/Initialize/b3OpenCLUtils.cpp b/thirdparty/bullet/src/Bullet3OpenCL/Initialize/b3OpenCLUtils.cpp
new file mode 100644
index 0000000000..dd194fc7ba
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/Initialize/b3OpenCLUtils.cpp
@@ -0,0 +1,1011 @@
+/*
+Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org
+Copyright (C) 2006 - 2011 Sony Computer Entertainment Inc.
+
+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.
+*/
+
+//Original author: Roman Ponomarev
+//Mostly Reimplemented by Erwin Coumans
+
+
+bool gDebugForceLoadingFromSource = false;
+bool gDebugSkipLoadingBinary = false;
+
+#include "Bullet3Common/b3Logging.h"
+
+#include <string.h>
+
+#ifdef _WIN32
+#pragma warning (disable:4996)
+#endif
+#include "b3OpenCLUtils.h"
+//#include "b3OpenCLInclude.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define B3_MAX_CL_DEVICES 16 //who needs 16 devices?
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+#include <assert.h>
+#define b3Assert assert
+#ifndef _WIN32
+#include <sys/stat.h>
+
+#endif
+
+static const char* sCachedBinaryPath="cache";
+
+
+//Set the preferred platform vendor using the OpenCL SDK
+static const char* spPlatformVendor =
+#if defined(CL_PLATFORM_MINI_CL)
+"MiniCL, SCEA";
+#elif defined(CL_PLATFORM_AMD)
+"Advanced Micro Devices, Inc.";
+#elif defined(CL_PLATFORM_NVIDIA)
+"NVIDIA Corporation";
+#elif defined(CL_PLATFORM_INTEL)
+"Intel(R) Corporation";
+#elif defined(B3_USE_CLEW)
+"clew (OpenCL Extension Wrangler library)";
+#else
+"Unknown Vendor";
+#endif
+
+#ifndef CL_PLATFORM_MINI_CL
+#ifdef _WIN32
+#ifndef B3_USE_CLEW
+#include "CL/cl_gl.h"
+#endif //B3_USE_CLEW
+#endif //_WIN32
+#endif
+
+
+void MyFatalBreakAPPLE( const char * errstr ,
+ const void * private_info ,
+ size_t cb ,
+ void * user_data )
+{
+
+
+ const char* patloc = strstr(errstr, "Warning");
+ //find out if it is a warning or error, exit if error
+
+ if (patloc)
+ {
+ b3Warning("Warning: %s\n", errstr);
+ } else
+ {
+ b3Error("Error: %s\n", errstr);
+ b3Assert(0);
+ }
+
+}
+
+#ifdef B3_USE_CLEW
+
+int b3OpenCLUtils_clewInit()
+{
+ int result = -1;
+
+#ifdef _WIN32
+ const char* cl = "OpenCL.dll";
+#elif defined __APPLE__
+ const char* cl = "/System/Library/Frameworks/OpenCL.framework/Versions/Current/OpenCL";
+#else//presumable Linux?
+ //linux (tested on Ubuntu 12.10 with Catalyst 13.4 beta drivers, not that there is no symbolic link from libOpenCL.so
+ const char* cl = "libOpenCL.so.1";
+ result = clewInit(cl);
+ if (result != CLEW_SUCCESS)
+ {
+ cl = "libOpenCL.so";
+ } else
+ {
+ clewExit();
+ }
+#endif
+ result = clewInit(cl);
+ if (result!=CLEW_SUCCESS)
+ {
+ b3Error("clewInit failed with error code %d\n",result);
+ }
+ else
+ {
+ b3Printf("clewInit succesfull using %s\n",cl);
+ }
+ return result;
+}
+#endif
+
+int b3OpenCLUtils_getNumPlatforms(cl_int* pErrNum)
+{
+#ifdef B3_USE_CLEW
+ b3OpenCLUtils_clewInit();
+#endif
+
+ cl_platform_id pPlatforms[10] = { 0 };
+
+ cl_uint numPlatforms = 0;
+ cl_int ciErrNum = clGetPlatformIDs(10, pPlatforms, &numPlatforms);
+ //cl_int ciErrNum = clGetPlatformIDs(0, NULL, &numPlatforms);
+
+ if(ciErrNum != CL_SUCCESS)
+ {
+ if(pErrNum != NULL)
+ *pErrNum = ciErrNum;
+ }
+ return numPlatforms;
+
+}
+
+const char* b3OpenCLUtils_getSdkVendorName()
+{
+ return spPlatformVendor;
+}
+
+void b3OpenCLUtils_setCachePath(const char* path)
+{
+ sCachedBinaryPath = path;
+}
+
+cl_platform_id b3OpenCLUtils_getPlatform(int platformIndex0, cl_int* pErrNum)
+{
+#ifdef B3_USE_CLEW
+ b3OpenCLUtils_clewInit();
+#endif
+
+ cl_platform_id platform = 0;
+ unsigned int platformIndex = (unsigned int )platformIndex0;
+ cl_uint numPlatforms;
+ cl_int ciErrNum = clGetPlatformIDs(0, NULL, &numPlatforms);
+
+ if (platformIndex<numPlatforms)
+ {
+ cl_platform_id* platforms = (cl_platform_id*) malloc (sizeof(cl_platform_id)*numPlatforms);
+ ciErrNum = clGetPlatformIDs(numPlatforms, platforms, NULL);
+ if(ciErrNum != CL_SUCCESS)
+ {
+ if(pErrNum != NULL)
+ *pErrNum = ciErrNum;
+ return platform;
+ }
+
+ platform = platforms[platformIndex];
+
+ free (platforms);
+ }
+
+ return platform;
+}
+
+void b3OpenCLUtils::getPlatformInfo(cl_platform_id platform, b3OpenCLPlatformInfo* platformInfo)
+{
+ b3Assert(platform);
+ cl_int ciErrNum;
+ ciErrNum = clGetPlatformInfo( platform,CL_PLATFORM_VENDOR,B3_MAX_STRING_LENGTH,platformInfo->m_platformVendor,NULL);
+ oclCHECKERROR(ciErrNum,CL_SUCCESS);
+ ciErrNum = clGetPlatformInfo( platform,CL_PLATFORM_NAME,B3_MAX_STRING_LENGTH,platformInfo->m_platformName,NULL);
+ oclCHECKERROR(ciErrNum,CL_SUCCESS);
+ ciErrNum = clGetPlatformInfo( platform,CL_PLATFORM_VERSION,B3_MAX_STRING_LENGTH,platformInfo->m_platformVersion,NULL);
+ oclCHECKERROR(ciErrNum,CL_SUCCESS);
+}
+
+void b3OpenCLUtils_printPlatformInfo( cl_platform_id platform)
+{
+ b3OpenCLPlatformInfo platformInfo;
+ b3OpenCLUtils::getPlatformInfo (platform, &platformInfo);
+ b3Printf("Platform info:\n");
+ b3Printf(" CL_PLATFORM_VENDOR: \t\t\t%s\n",platformInfo.m_platformVendor);
+ b3Printf(" CL_PLATFORM_NAME: \t\t\t%s\n",platformInfo.m_platformName);
+ b3Printf(" CL_PLATFORM_VERSION: \t\t\t%s\n",platformInfo.m_platformVersion);
+}
+
+
+
+cl_context b3OpenCLUtils_createContextFromPlatform(cl_platform_id platform, cl_device_type deviceType, cl_int* pErrNum, void* pGLContext, void* pGLDC, int preferredDeviceIndex, int preferredPlatformIndex)
+{
+ cl_context retContext = 0;
+ cl_int ciErrNum=0;
+ cl_uint num_entries;
+ cl_device_id devices[B3_MAX_CL_DEVICES];
+ cl_uint num_devices;
+ cl_context_properties* cprops;
+
+ /*
+ * If we could find our platform, use it. Otherwise pass a NULL and get whatever the
+ * implementation thinks we should be using.
+ */
+ cl_context_properties cps[7] = {0,0,0,0,0,0,0};
+ cps[0] = CL_CONTEXT_PLATFORM;
+ cps[1] = (cl_context_properties)platform;
+#ifdef _WIN32
+#ifndef B3_USE_CLEW
+ if (pGLContext && pGLDC)
+ {
+ cps[2] = CL_GL_CONTEXT_KHR;
+ cps[3] = (cl_context_properties)pGLContext;
+ cps[4] = CL_WGL_HDC_KHR;
+ cps[5] = (cl_context_properties)pGLDC;
+ }
+#endif //B3_USE_CLEW
+#endif //_WIN32
+ num_entries = B3_MAX_CL_DEVICES;
+
+
+ num_devices=-1;
+
+ ciErrNum = clGetDeviceIDs(
+ platform,
+ deviceType,
+ num_entries,
+ devices,
+ &num_devices);
+
+ if (ciErrNum<0)
+ {
+ b3Printf("clGetDeviceIDs returned %d\n",ciErrNum);
+ return 0;
+ }
+ cprops = (NULL == platform) ? NULL : cps;
+
+ if (!num_devices)
+ return 0;
+
+ if (pGLContext)
+ {
+ //search for the GPU that relates to the OpenCL context
+ unsigned int i;
+ for (i=0;i<num_devices;i++)
+ {
+ retContext = clCreateContext(cprops,1,&devices[i],NULL,NULL,&ciErrNum);
+ if (ciErrNum==CL_SUCCESS)
+ break;
+ }
+ }
+ else
+ {
+ if (preferredDeviceIndex>=0 && (unsigned int)preferredDeviceIndex<num_devices)
+ {
+ //create a context of the preferred device index
+ retContext = clCreateContext(cprops,1,&devices[preferredDeviceIndex],NULL,NULL,&ciErrNum);
+ } else
+ {
+ //create a context of all devices
+#if defined (__APPLE__)
+ retContext = clCreateContext(cprops,num_devices,devices,MyFatalBreakAPPLE,NULL,&ciErrNum);
+#else
+ b3Printf("numDevices=%d\n",num_devices);
+
+ retContext = clCreateContext(cprops,num_devices,devices,NULL,NULL,&ciErrNum);
+#endif
+ }
+ }
+ if(pErrNum != NULL)
+ {
+ *pErrNum = ciErrNum;
+ };
+
+ return retContext;
+}
+
+cl_context b3OpenCLUtils_createContextFromType(cl_device_type deviceType, cl_int* pErrNum, void* pGLContext, void* pGLDC , int preferredDeviceIndex, int preferredPlatformIndex, cl_platform_id* retPlatformId)
+{
+#ifdef B3_USE_CLEW
+ b3OpenCLUtils_clewInit();
+#endif
+
+
+ cl_uint numPlatforms;
+ cl_context retContext = 0;
+ unsigned int i;
+
+ cl_int ciErrNum = clGetPlatformIDs(0, NULL, &numPlatforms);
+ if(ciErrNum != CL_SUCCESS)
+ {
+ if(pErrNum != NULL) *pErrNum = ciErrNum;
+ return NULL;
+ }
+ if(numPlatforms > 0)
+ {
+ cl_platform_id* platforms = (cl_platform_id*) malloc (sizeof(cl_platform_id)*numPlatforms);
+ ciErrNum = clGetPlatformIDs(numPlatforms, platforms, NULL);
+ if(ciErrNum != CL_SUCCESS)
+ {
+ if(pErrNum != NULL)
+ *pErrNum = ciErrNum;
+ free(platforms);
+ return NULL;
+ }
+
+
+
+ for ( i = 0; i < numPlatforms; ++i)
+ {
+ char pbuf[128];
+ ciErrNum = clGetPlatformInfo( platforms[i],
+ CL_PLATFORM_VENDOR,
+ sizeof(pbuf),
+ pbuf,
+ NULL);
+ if(ciErrNum != CL_SUCCESS)
+ {
+ if(pErrNum != NULL) *pErrNum = ciErrNum;
+ return NULL;
+ }
+
+ if (preferredPlatformIndex>=0 && i==preferredPlatformIndex)
+ {
+ cl_platform_id tmpPlatform = platforms[0];
+ platforms[0] = platforms[i];
+ platforms[i] = tmpPlatform;
+ break;
+ } else
+ {
+ if(!strcmp(pbuf, spPlatformVendor))
+ {
+ cl_platform_id tmpPlatform = platforms[0];
+ platforms[0] = platforms[i];
+ platforms[i] = tmpPlatform;
+ }
+ }
+ }
+
+ for (i = 0; i < numPlatforms; ++i)
+ {
+ cl_platform_id platform = platforms[i];
+ assert(platform);
+
+ retContext = b3OpenCLUtils_createContextFromPlatform(platform,deviceType,pErrNum,pGLContext,pGLDC,preferredDeviceIndex,preferredPlatformIndex);
+
+ if (retContext)
+ {
+// printf("OpenCL platform details:\n");
+ b3OpenCLPlatformInfo platformInfo;
+
+ b3OpenCLUtils::getPlatformInfo(platform, &platformInfo);
+
+ if (retPlatformId)
+ *retPlatformId = platform;
+
+ break;
+ }
+ }
+
+ free (platforms);
+ }
+ return retContext;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+//! Gets the id of the nth device from the context
+//!
+//! @return the id or -1 when out of range
+//! @param cxMainContext OpenCL context
+//! @param device_idx index of the device of interest
+//////////////////////////////////////////////////////////////////////////////
+cl_device_id b3OpenCLUtils_getDevice(cl_context cxMainContext, int deviceIndex)
+{
+ assert(cxMainContext);
+
+ size_t szParmDataBytes;
+ cl_device_id* cdDevices;
+ cl_device_id device ;
+
+ // get the list of devices associated with context
+ clGetContextInfo(cxMainContext, CL_CONTEXT_DEVICES, 0, NULL, &szParmDataBytes);
+
+ if( szParmDataBytes / sizeof(cl_device_id) < (unsigned int)deviceIndex ) {
+ return (cl_device_id)-1;
+ }
+
+ cdDevices = (cl_device_id*) malloc(szParmDataBytes);
+
+ clGetContextInfo(cxMainContext, CL_CONTEXT_DEVICES, szParmDataBytes, cdDevices, NULL);
+
+ device = cdDevices[deviceIndex];
+ free(cdDevices);
+
+ return device;
+}
+
+int b3OpenCLUtils_getNumDevices(cl_context cxMainContext)
+{
+ size_t szParamDataBytes;
+ int device_count;
+ clGetContextInfo(cxMainContext, CL_CONTEXT_DEVICES, 0, NULL, &szParamDataBytes);
+ device_count = (int) szParamDataBytes/ sizeof(cl_device_id);
+ return device_count;
+}
+
+
+
+void b3OpenCLUtils::getDeviceInfo(cl_device_id device, b3OpenCLDeviceInfo* info)
+{
+ // CL_DEVICE_NAME
+ clGetDeviceInfo(device, CL_DEVICE_NAME, B3_MAX_STRING_LENGTH, &info->m_deviceName, NULL);
+
+ // CL_DEVICE_VENDOR
+ clGetDeviceInfo(device, CL_DEVICE_VENDOR, B3_MAX_STRING_LENGTH, &info->m_deviceVendor, NULL);
+
+ // CL_DRIVER_VERSION
+ clGetDeviceInfo(device, CL_DRIVER_VERSION, B3_MAX_STRING_LENGTH, &info->m_driverVersion, NULL);
+
+ // CL_DEVICE_INFO
+ clGetDeviceInfo(device, CL_DEVICE_TYPE, sizeof(cl_device_type), &info->m_deviceType, NULL);
+
+ // CL_DEVICE_MAX_COMPUTE_UNITS
+ clGetDeviceInfo(device, CL_DEVICE_MAX_COMPUTE_UNITS, sizeof(info->m_computeUnits), &info->m_computeUnits, NULL);
+
+ // CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS
+ clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, sizeof(info->m_workitemDims), &info->m_workitemDims, NULL);
+
+ // CL_DEVICE_MAX_WORK_ITEM_SIZES
+ clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_ITEM_SIZES, sizeof(info->m_workItemSize), &info->m_workItemSize, NULL);
+
+ // CL_DEVICE_MAX_WORK_GROUP_SIZE
+ clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_GROUP_SIZE, sizeof(info->m_workgroupSize), &info->m_workgroupSize, NULL);
+
+ // CL_DEVICE_MAX_CLOCK_FREQUENCY
+ clGetDeviceInfo(device, CL_DEVICE_MAX_CLOCK_FREQUENCY, sizeof(info->m_clockFrequency), &info->m_clockFrequency, NULL);
+
+ // CL_DEVICE_ADDRESS_BITS
+ clGetDeviceInfo(device, CL_DEVICE_ADDRESS_BITS, sizeof(info->m_addressBits), &info->m_addressBits, NULL);
+
+ // CL_DEVICE_MAX_MEM_ALLOC_SIZE
+ clGetDeviceInfo(device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof(info->m_maxMemAllocSize), &info->m_maxMemAllocSize, NULL);
+
+ // CL_DEVICE_GLOBAL_MEM_SIZE
+ clGetDeviceInfo(device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof(info->m_globalMemSize), &info->m_globalMemSize, NULL);
+
+ // CL_DEVICE_ERROR_CORRECTION_SUPPORT
+ clGetDeviceInfo(device, CL_DEVICE_ERROR_CORRECTION_SUPPORT, sizeof(info->m_errorCorrectionSupport), &info->m_errorCorrectionSupport, NULL);
+
+ // CL_DEVICE_LOCAL_MEM_TYPE
+ clGetDeviceInfo(device, CL_DEVICE_LOCAL_MEM_TYPE, sizeof(info->m_localMemType), &info->m_localMemType, NULL);
+
+ // CL_DEVICE_LOCAL_MEM_SIZE
+ clGetDeviceInfo(device, CL_DEVICE_LOCAL_MEM_SIZE, sizeof(info->m_localMemSize), &info->m_localMemSize, NULL);
+
+ // CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE
+ clGetDeviceInfo(device, CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE, sizeof(info->m_constantBufferSize), &info->m_constantBufferSize, NULL);
+
+ // CL_DEVICE_QUEUE_PROPERTIES
+ clGetDeviceInfo(device, CL_DEVICE_QUEUE_PROPERTIES, sizeof(info->m_queueProperties), &info->m_queueProperties, NULL);
+
+ // CL_DEVICE_IMAGE_SUPPORT
+ clGetDeviceInfo(device, CL_DEVICE_IMAGE_SUPPORT, sizeof(info->m_imageSupport), &info->m_imageSupport, NULL);
+
+ // CL_DEVICE_MAX_READ_IMAGE_ARGS
+ clGetDeviceInfo(device, CL_DEVICE_MAX_READ_IMAGE_ARGS, sizeof(info->m_maxReadImageArgs), &info->m_maxReadImageArgs, NULL);
+
+ // CL_DEVICE_MAX_WRITE_IMAGE_ARGS
+ clGetDeviceInfo(device, CL_DEVICE_MAX_WRITE_IMAGE_ARGS, sizeof(info->m_maxWriteImageArgs), &info->m_maxWriteImageArgs, NULL);
+
+ // CL_DEVICE_IMAGE2D_MAX_WIDTH, CL_DEVICE_IMAGE2D_MAX_HEIGHT, CL_DEVICE_IMAGE3D_MAX_WIDTH, CL_DEVICE_IMAGE3D_MAX_HEIGHT, CL_DEVICE_IMAGE3D_MAX_DEPTH
+ clGetDeviceInfo(device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof(size_t), &info->m_image2dMaxWidth, NULL);
+ clGetDeviceInfo(device, CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof(size_t), &info->m_image2dMaxHeight, NULL);
+ clGetDeviceInfo(device, CL_DEVICE_IMAGE3D_MAX_WIDTH, sizeof(size_t), &info->m_image3dMaxWidth, NULL);
+ clGetDeviceInfo(device, CL_DEVICE_IMAGE3D_MAX_HEIGHT, sizeof(size_t), &info->m_image3dMaxHeight, NULL);
+ clGetDeviceInfo(device, CL_DEVICE_IMAGE3D_MAX_DEPTH, sizeof(size_t), &info->m_image3dMaxDepth, NULL);
+
+ // CL_DEVICE_EXTENSIONS: get device extensions, and if any then parse & log the string onto separate lines
+ clGetDeviceInfo(device, CL_DEVICE_EXTENSIONS, B3_MAX_STRING_LENGTH, &info->m_deviceExtensions, NULL);
+
+ // CL_DEVICE_PREFERRED_VECTOR_WIDTH_<type>
+ clGetDeviceInfo(device, CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR, sizeof(cl_uint), &info->m_vecWidthChar, NULL);
+ clGetDeviceInfo(device, CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT, sizeof(cl_uint), &info->m_vecWidthShort, NULL);
+ clGetDeviceInfo(device, CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT, sizeof(cl_uint), &info->m_vecWidthInt, NULL);
+ clGetDeviceInfo(device, CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG, sizeof(cl_uint), &info->m_vecWidthLong, NULL);
+ clGetDeviceInfo(device, CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT, sizeof(cl_uint), &info->m_vecWidthFloat, NULL);
+ clGetDeviceInfo(device, CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE, sizeof(cl_uint), &info->m_vecWidthDouble, NULL);
+}
+
+
+void b3OpenCLUtils_printDeviceInfo(cl_device_id device)
+{
+ b3OpenCLDeviceInfo info;
+ b3OpenCLUtils::getDeviceInfo(device,&info);
+ b3Printf("Device Info:\n");
+ b3Printf(" CL_DEVICE_NAME: \t\t\t%s\n", info.m_deviceName);
+ b3Printf(" CL_DEVICE_VENDOR: \t\t\t%s\n", info.m_deviceVendor);
+ b3Printf(" CL_DRIVER_VERSION: \t\t\t%s\n", info.m_driverVersion);
+
+ if( info.m_deviceType & CL_DEVICE_TYPE_CPU )
+ b3Printf(" CL_DEVICE_TYPE:\t\t\t%s\n", "CL_DEVICE_TYPE_CPU");
+ if( info.m_deviceType & CL_DEVICE_TYPE_GPU )
+ b3Printf(" CL_DEVICE_TYPE:\t\t\t%s\n", "CL_DEVICE_TYPE_GPU");
+ if( info.m_deviceType & CL_DEVICE_TYPE_ACCELERATOR )
+ b3Printf(" CL_DEVICE_TYPE:\t\t\t%s\n", "CL_DEVICE_TYPE_ACCELERATOR");
+ if( info.m_deviceType & CL_DEVICE_TYPE_DEFAULT )
+ b3Printf(" CL_DEVICE_TYPE:\t\t\t%s\n", "CL_DEVICE_TYPE_DEFAULT");
+
+ b3Printf(" CL_DEVICE_MAX_COMPUTE_UNITS:\t\t%u\n", info.m_computeUnits);
+ b3Printf(" CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS:\t%u\n", info.m_workitemDims);
+ b3Printf(" CL_DEVICE_MAX_WORK_ITEM_SIZES:\t%u / %u / %u \n", info.m_workItemSize[0], info.m_workItemSize[1], info.m_workItemSize[2]);
+ b3Printf(" CL_DEVICE_MAX_WORK_GROUP_SIZE:\t%u\n", info.m_workgroupSize);
+ b3Printf(" CL_DEVICE_MAX_CLOCK_FREQUENCY:\t%u MHz\n", info.m_clockFrequency);
+ b3Printf(" CL_DEVICE_ADDRESS_BITS:\t\t%u\n", info.m_addressBits);
+ b3Printf(" CL_DEVICE_MAX_MEM_ALLOC_SIZE:\t\t%u MByte\n", (unsigned int)(info.m_maxMemAllocSize/ (1024 * 1024)));
+ b3Printf(" CL_DEVICE_GLOBAL_MEM_SIZE:\t\t%u MByte\n", (unsigned int)(info.m_globalMemSize/ (1024 * 1024)));
+ b3Printf(" CL_DEVICE_ERROR_CORRECTION_SUPPORT:\t%s\n", info.m_errorCorrectionSupport== CL_TRUE ? "yes" : "no");
+ b3Printf(" CL_DEVICE_LOCAL_MEM_TYPE:\t\t%s\n", info.m_localMemType == 1 ? "local" : "global");
+ b3Printf(" CL_DEVICE_LOCAL_MEM_SIZE:\t\t%u KByte\n", (unsigned int)(info.m_localMemSize / 1024));
+ b3Printf(" CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE:\t%u KByte\n", (unsigned int)(info.m_constantBufferSize / 1024));
+ if( info.m_queueProperties & CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE )
+ b3Printf(" CL_DEVICE_QUEUE_PROPERTIES:\t\t%s\n", "CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE");
+ if( info.m_queueProperties & CL_QUEUE_PROFILING_ENABLE )
+ b3Printf(" CL_DEVICE_QUEUE_PROPERTIES:\t\t%s\n", "CL_QUEUE_PROFILING_ENABLE");
+
+ b3Printf(" CL_DEVICE_IMAGE_SUPPORT:\t\t%u\n", info.m_imageSupport);
+
+ b3Printf(" CL_DEVICE_MAX_READ_IMAGE_ARGS:\t%u\n", info.m_maxReadImageArgs);
+ b3Printf(" CL_DEVICE_MAX_WRITE_IMAGE_ARGS:\t%u\n", info.m_maxWriteImageArgs);
+ b3Printf("\n CL_DEVICE_IMAGE <dim>");
+ b3Printf("\t\t\t2D_MAX_WIDTH\t %u\n", info.m_image2dMaxWidth);
+ b3Printf("\t\t\t\t\t2D_MAX_HEIGHT\t %u\n", info.m_image2dMaxHeight);
+ b3Printf("\t\t\t\t\t3D_MAX_WIDTH\t %u\n", info.m_image3dMaxWidth);
+ b3Printf("\t\t\t\t\t3D_MAX_HEIGHT\t %u\n", info.m_image3dMaxHeight);
+ b3Printf("\t\t\t\t\t3D_MAX_DEPTH\t %u\n", info.m_image3dMaxDepth);
+ if (*info.m_deviceExtensions != 0)
+ {
+ b3Printf("\n CL_DEVICE_EXTENSIONS:%s\n",info.m_deviceExtensions);
+ }
+ else
+ {
+ b3Printf(" CL_DEVICE_EXTENSIONS: None\n");
+ }
+ b3Printf(" CL_DEVICE_PREFERRED_VECTOR_WIDTH_<t>\t");
+ b3Printf("CHAR %u, SHORT %u, INT %u,LONG %u, FLOAT %u, DOUBLE %u\n\n\n",
+ info.m_vecWidthChar, info.m_vecWidthShort, info.m_vecWidthInt, info.m_vecWidthLong,info.m_vecWidthFloat, info.m_vecWidthDouble);
+
+
+}
+
+
+static const char* strip2(const char* name, const char* pattern)
+{
+ size_t const patlen = strlen(pattern);
+ size_t patcnt = 0;
+ const char * oriptr;
+ const char * patloc;
+ // find how many times the pattern occurs in the original string
+ for (oriptr = name; (patloc = strstr(oriptr, pattern)); oriptr = patloc + patlen)
+ {
+ patcnt++;
+ }
+ return oriptr;
+}
+
+cl_program b3OpenCLUtils_compileCLProgramFromString(cl_context clContext, cl_device_id device, const char* kernelSourceOrg, cl_int* pErrNum, const char* additionalMacrosArg , const char* clFileNameForCaching, bool disableBinaryCaching)
+{
+ const char* additionalMacros = additionalMacrosArg?additionalMacrosArg:"";
+
+ if (disableBinaryCaching)
+ {
+ //kernelSourceOrg = 0;
+ }
+
+ cl_program m_cpProgram=0;
+ cl_int status;
+
+ char binaryFileName[B3_MAX_STRING_LENGTH];
+
+ char deviceName[256];
+ char driverVersion[256];
+ const char* strippedName;
+ int fileUpToDate = 0;
+#ifdef _WIN32
+ int binaryFileValid=0;
+#endif
+ if (!disableBinaryCaching && clFileNameForCaching)
+ {
+ clGetDeviceInfo(device, CL_DEVICE_NAME, 256, &deviceName, NULL);
+ clGetDeviceInfo(device, CL_DRIVER_VERSION, 256, &driverVersion, NULL);
+
+ strippedName = strip2(clFileNameForCaching,"\\");
+ strippedName = strip2(strippedName,"/");
+
+#ifdef _MSVC_VER
+ sprintf_s(binaryFileName,B3_MAX_STRING_LENGTH,"%s/%s.%s.%s.bin",sCachedBinaryPath,strippedName, deviceName,driverVersion );
+#else
+ sprintf(binaryFileName,"%s/%s.%s.%s.bin",sCachedBinaryPath,strippedName, deviceName,driverVersion );
+#endif
+ }
+ if (clFileNameForCaching && !(disableBinaryCaching || gDebugSkipLoadingBinary||gDebugForceLoadingFromSource) )
+ {
+
+#ifdef _WIN32
+ char* bla=0;
+
+
+
+ //printf("searching for %s\n", binaryFileName);
+
+
+ FILETIME modtimeBinary;
+ CreateDirectoryA(sCachedBinaryPath,0);
+ {
+
+ HANDLE binaryFileHandle = CreateFileA(binaryFileName,GENERIC_READ,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
+ if (binaryFileHandle ==INVALID_HANDLE_VALUE)
+ {
+ DWORD errorCode;
+ errorCode = GetLastError();
+ switch (errorCode)
+ {
+ case ERROR_FILE_NOT_FOUND:
+ {
+ b3Warning("\nCached file not found %s\n", binaryFileName);
+ break;
+ }
+ case ERROR_PATH_NOT_FOUND:
+ {
+ b3Warning("\nCached file path not found %s\n", binaryFileName);
+ break;
+ }
+ default:
+ {
+ b3Warning("\nFailed reading cached file with errorCode = %d\n", errorCode);
+ }
+ }
+ } else
+ {
+ if (GetFileTime(binaryFileHandle, NULL, NULL, &modtimeBinary)==0)
+ {
+ DWORD errorCode;
+ errorCode = GetLastError();
+ b3Warning("\nGetFileTime errorCode = %d\n", errorCode);
+ } else
+ {
+ binaryFileValid = 1;
+ }
+ CloseHandle(binaryFileHandle);
+ }
+
+ if (binaryFileValid)
+ {
+ HANDLE srcFileHandle = CreateFileA(clFileNameForCaching,GENERIC_READ,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
+
+ if (srcFileHandle==INVALID_HANDLE_VALUE)
+ {
+ const char* prefix[]={"./","../","../../","../../../","../../../../"};
+ for (int i=0;(srcFileHandle==INVALID_HANDLE_VALUE) && i<5;i++)
+ {
+ char relativeFileName[1024];
+ sprintf(relativeFileName,"%s%s",prefix[i],clFileNameForCaching);
+ srcFileHandle = CreateFileA(relativeFileName,GENERIC_READ,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
+ }
+
+ }
+
+
+ if (srcFileHandle!=INVALID_HANDLE_VALUE)
+ {
+ FILETIME modtimeSrc;
+ if (GetFileTime(srcFileHandle, NULL, NULL, &modtimeSrc)==0)
+ {
+ DWORD errorCode;
+ errorCode = GetLastError();
+ b3Warning("\nGetFileTime errorCode = %d\n", errorCode);
+ }
+ if ( ( modtimeSrc.dwHighDateTime < modtimeBinary.dwHighDateTime)
+ ||(( modtimeSrc.dwHighDateTime == modtimeBinary.dwHighDateTime)&&(modtimeSrc.dwLowDateTime <= modtimeBinary.dwLowDateTime)))
+ {
+ fileUpToDate=1;
+ } else
+ {
+ b3Warning("\nCached binary file out-of-date (%s)\n",binaryFileName);
+ }
+ CloseHandle(srcFileHandle);
+ }
+ else
+ {
+#ifdef _DEBUG
+ DWORD errorCode;
+ errorCode = GetLastError();
+ switch (errorCode)
+ {
+ case ERROR_FILE_NOT_FOUND:
+ {
+ b3Warning("\nSrc file not found %s\n", clFileNameForCaching);
+ break;
+ }
+ case ERROR_PATH_NOT_FOUND:
+ {
+ b3Warning("\nSrc path not found %s\n", clFileNameForCaching);
+ break;
+ }
+ default:
+ {
+ b3Warning("\nnSrc file reading errorCode = %d\n", errorCode);
+ }
+ }
+
+ //we should make sure the src file exists so we can verify the timestamp with binary
+// assert(0);
+ b3Warning("Warning: cannot find OpenCL kernel %s to verify timestamp of binary cached kernel %s\n",clFileNameForCaching, binaryFileName);
+ fileUpToDate = true;
+#else
+ //if we cannot find the source, assume it is OK in release builds
+ fileUpToDate = true;
+#endif
+ }
+ }
+
+
+ }
+
+
+
+#else
+ fileUpToDate = true;
+ if (mkdir(sCachedBinaryPath,0777) == -1)
+ {
+ }
+ else
+ {
+ b3Printf("Succesfully created cache directory: %s\n", sCachedBinaryPath);
+ }
+#endif //_WIN32
+ }
+
+
+ if( fileUpToDate)
+ {
+#ifdef _MSC_VER
+ FILE* file;
+ if (fopen_s(&file,binaryFileName, "rb")!=0)
+ file=0;
+#else
+ FILE* file = fopen(binaryFileName, "rb");
+#endif
+
+ if (file)
+ {
+ size_t binarySize=0;
+ char* binary =0;
+
+ fseek( file, 0L, SEEK_END );
+ binarySize = ftell( file );
+ rewind( file );
+ binary = (char*)malloc(sizeof(char)*binarySize);
+ int bytesRead;
+ bytesRead = fread( binary, sizeof(char), binarySize, file );
+ fclose( file );
+
+ m_cpProgram = clCreateProgramWithBinary( clContext, 1,&device, &binarySize, (const unsigned char**)&binary, 0, &status );
+ b3Assert( status == CL_SUCCESS );
+ status = clBuildProgram( m_cpProgram, 1, &device, additionalMacros, 0, 0 );
+ b3Assert( status == CL_SUCCESS );
+
+ if( status != CL_SUCCESS )
+ {
+ char *build_log;
+ size_t ret_val_size;
+ clGetProgramBuildInfo(m_cpProgram, device, CL_PROGRAM_BUILD_LOG, 0, NULL, &ret_val_size);
+ build_log = (char*)malloc(sizeof(char)*(ret_val_size+1));
+ clGetProgramBuildInfo(m_cpProgram, device, CL_PROGRAM_BUILD_LOG, ret_val_size, build_log, NULL);
+ build_log[ret_val_size] = '\0';
+ b3Error("%s\n", build_log);
+ free (build_log);
+ b3Assert(0);
+ m_cpProgram = 0;
+
+ b3Warning("clBuildProgram reported failure on cached binary: %s\n",binaryFileName);
+
+ } else
+ {
+ b3Printf("clBuildProgram successfully compiled cached binary: %s\n",binaryFileName);
+ }
+ free (binary);
+
+ } else
+ {
+ b3Warning("Cannot open cached binary: %s\n",binaryFileName);
+ }
+ }
+
+
+
+
+
+
+
+
+
+ if (!m_cpProgram)
+ {
+
+ cl_int localErrNum;
+ char* compileFlags;
+ int flagsize;
+
+
+
+ const char* kernelSource = kernelSourceOrg;
+
+ if (!kernelSourceOrg || gDebugForceLoadingFromSource)
+ {
+ if (clFileNameForCaching)
+ {
+
+ FILE* file = fopen(clFileNameForCaching, "rb");
+ //in many cases the relative path is a few levels up the directory hierarchy, so try it
+ if (!file)
+ {
+ const char* prefix[]={"../","../../","../../../","../../../../"};
+ for (int i=0;!file && i<3;i++)
+ {
+ char relativeFileName[1024];
+ sprintf(relativeFileName,"%s%s",prefix[i],clFileNameForCaching);
+ file = fopen(relativeFileName, "rb");
+ }
+ }
+
+ if (file)
+ {
+ char* kernelSrc=0;
+ fseek( file, 0L, SEEK_END );
+ int kernelSize = ftell( file );
+ rewind( file );
+ kernelSrc = (char*)malloc(kernelSize+1);
+ int readBytes;
+ readBytes = fread((void*)kernelSrc,1,kernelSize, file);
+ kernelSrc[kernelSize] = 0;
+ fclose(file);
+ kernelSource = kernelSrc;
+ }
+ }
+ }
+
+ size_t program_length = kernelSource ? strlen(kernelSource) : 0;
+#ifdef MAC //or __APPLE__?
+ char* flags = "-cl-mad-enable -DMAC ";
+#else
+ const char* flags = "";
+#endif
+
+
+ m_cpProgram = clCreateProgramWithSource(clContext, 1, (const char**)&kernelSource, &program_length, &localErrNum);
+ if (localErrNum!= CL_SUCCESS)
+ {
+ if (pErrNum)
+ *pErrNum = localErrNum;
+ return 0;
+ }
+
+ // Build the program with 'mad' Optimization option
+
+
+
+ flagsize = sizeof(char)*(strlen(additionalMacros) + strlen(flags) + 5);
+ compileFlags = (char*) malloc(flagsize);
+#ifdef _MSC_VER
+ sprintf_s(compileFlags,flagsize, "%s %s", flags, additionalMacros);
+#else
+ sprintf(compileFlags, "%s %s", flags, additionalMacros);
+#endif
+ localErrNum = clBuildProgram(m_cpProgram, 1, &device, compileFlags, NULL, NULL);
+ if (localErrNum!= CL_SUCCESS)
+ {
+ char *build_log;
+ size_t ret_val_size;
+ clGetProgramBuildInfo(m_cpProgram, device, CL_PROGRAM_BUILD_LOG, 0, NULL, &ret_val_size);
+ build_log = (char*) malloc(sizeof(char)*(ret_val_size+1));
+ clGetProgramBuildInfo(m_cpProgram, device, CL_PROGRAM_BUILD_LOG, ret_val_size, build_log, NULL);
+
+ // to be carefully, terminate with \0
+ // there's no information in the reference whether the string is 0 terminated or not
+ build_log[ret_val_size] = '\0';
+
+
+ b3Error("Error in clBuildProgram, Line %u in file %s, Log: \n%s\n !!!\n\n", __LINE__, __FILE__, build_log);
+ free (build_log);
+ if (pErrNum)
+ *pErrNum = localErrNum;
+ return 0;
+ }
+
+
+ if( !disableBinaryCaching && clFileNameForCaching )
+ { // write to binary
+
+ cl_uint numAssociatedDevices;
+ status = clGetProgramInfo( m_cpProgram, CL_PROGRAM_NUM_DEVICES, sizeof(cl_uint), &numAssociatedDevices, 0 );
+ b3Assert( status == CL_SUCCESS );
+ if (numAssociatedDevices==1)
+ {
+
+ size_t binarySize;
+ char* binary ;
+
+ status = clGetProgramInfo( m_cpProgram, CL_PROGRAM_BINARY_SIZES, sizeof(size_t), &binarySize, 0 );
+ b3Assert( status == CL_SUCCESS );
+
+ binary = (char*)malloc(sizeof(char)*binarySize);
+
+ status = clGetProgramInfo( m_cpProgram, CL_PROGRAM_BINARIES, sizeof(char*), &binary, 0 );
+ b3Assert( status == CL_SUCCESS );
+
+ {
+ FILE* file=0;
+#ifdef _MSC_VER
+ if (fopen_s(&file,binaryFileName, "wb")!=0)
+ file=0;
+#else
+ file = fopen(binaryFileName, "wb");
+#endif
+ if (file)
+ {
+ fwrite( binary, sizeof(char), binarySize, file );
+ fclose( file );
+ } else
+ {
+ b3Warning("cannot write file %s\n", binaryFileName);
+ }
+ }
+
+ free (binary);
+ }
+ }
+
+ free(compileFlags);
+
+ }
+ return m_cpProgram;
+}
+
+
+cl_kernel b3OpenCLUtils_compileCLKernelFromString(cl_context clContext, cl_device_id device, const char* kernelSource, const char* kernelName, cl_int* pErrNum, cl_program prog, const char* additionalMacros )
+{
+
+ cl_kernel kernel;
+ cl_int localErrNum;
+
+ cl_program m_cpProgram = prog;
+
+ b3Printf("compiling kernel %s ",kernelName);
+
+ if (!m_cpProgram)
+ {
+ m_cpProgram = b3OpenCLUtils_compileCLProgramFromString(clContext,device,kernelSource,pErrNum, additionalMacros,0, false);
+ }
+
+
+ // Create the kernel
+ kernel = clCreateKernel(m_cpProgram, kernelName, &localErrNum);
+ if (localErrNum != CL_SUCCESS)
+ {
+ b3Error("Error in clCreateKernel, Line %u in file %s, cannot find kernel function %s !!!\n\n", __LINE__, __FILE__, kernelName);
+ assert(0);
+ if (pErrNum)
+ *pErrNum = localErrNum;
+ return 0;
+ }
+
+ if (!prog && m_cpProgram)
+ {
+ clReleaseProgram(m_cpProgram);
+ }
+ b3Printf("ready. \n");
+
+
+ if (pErrNum)
+ *pErrNum = CL_SUCCESS;
+ return kernel;
+
+}
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/Initialize/b3OpenCLUtils.h b/thirdparty/bullet/src/Bullet3OpenCL/Initialize/b3OpenCLUtils.h
new file mode 100644
index 0000000000..db6466e76b
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/Initialize/b3OpenCLUtils.h
@@ -0,0 +1,194 @@
+/*
+Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org
+Copyright (C) 2006 - 2011 Sony Computer Entertainment Inc.
+
+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.
+*/
+
+//original author: Roman Ponomarev
+//cleanup by Erwin Coumans
+
+#ifndef B3_OPENCL_UTILS_H
+#define B3_OPENCL_UTILS_H
+
+#include "b3OpenCLInclude.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+///C API for OpenCL utilities: convenience functions, see below for C++ API
+
+/// CL Context optionally takes a GL context. This is a generic type because we don't really want this code
+/// to have to understand GL types. It is a HGLRC in _WIN32 or a GLXContext otherwise.
+cl_context b3OpenCLUtils_createContextFromType(cl_device_type deviceType, cl_int* pErrNum, void* pGLCtx , void* pGLDC , int preferredDeviceIndex , int preferredPlatformIndex, cl_platform_id* platformId);
+
+int b3OpenCLUtils_getNumDevices(cl_context cxMainContext);
+
+cl_device_id b3OpenCLUtils_getDevice(cl_context cxMainContext, int nr);
+
+void b3OpenCLUtils_printDeviceInfo(cl_device_id device);
+
+cl_kernel b3OpenCLUtils_compileCLKernelFromString( cl_context clContext,cl_device_id device, const char* kernelSource, const char* kernelName, cl_int* pErrNum, cl_program prog,const char* additionalMacros);
+
+//optional
+cl_program b3OpenCLUtils_compileCLProgramFromString( cl_context clContext,cl_device_id device, const char* kernelSource, cl_int* pErrNum,const char* additionalMacros , const char* srcFileNameForCaching, bool disableBinaryCaching);
+
+//the following optional APIs provide access using specific platform information
+int b3OpenCLUtils_getNumPlatforms(cl_int* pErrNum);
+
+///get the nr'th platform, where nr is in the range [0..getNumPlatforms)
+cl_platform_id b3OpenCLUtils_getPlatform(int nr, cl_int* pErrNum);
+
+
+void b3OpenCLUtils_printPlatformInfo(cl_platform_id platform);
+
+const char* b3OpenCLUtils_getSdkVendorName();
+
+///set the path (directory/folder) where the compiled OpenCL kernel are stored
+void b3OpenCLUtils_setCachePath(const char* path);
+
+cl_context b3OpenCLUtils_createContextFromPlatform(cl_platform_id platform, cl_device_type deviceType, cl_int* pErrNum, void* pGLCtx , void* pGLDC ,int preferredDeviceIndex , int preferredPlatformIndex);
+
+#ifdef __cplusplus
+}
+
+#define B3_MAX_STRING_LENGTH 1024
+
+typedef struct
+{
+ char m_deviceName[B3_MAX_STRING_LENGTH];
+ char m_deviceVendor[B3_MAX_STRING_LENGTH];
+ char m_driverVersion[B3_MAX_STRING_LENGTH];
+ char m_deviceExtensions[B3_MAX_STRING_LENGTH];
+
+ cl_device_type m_deviceType;
+ cl_uint m_computeUnits;
+ size_t m_workitemDims;
+ size_t m_workItemSize[3];
+ size_t m_image2dMaxWidth;
+ size_t m_image2dMaxHeight;
+ size_t m_image3dMaxWidth;
+ size_t m_image3dMaxHeight;
+ size_t m_image3dMaxDepth;
+ size_t m_workgroupSize;
+ cl_uint m_clockFrequency;
+ cl_ulong m_constantBufferSize;
+ cl_ulong m_localMemSize;
+ cl_ulong m_globalMemSize;
+ cl_bool m_errorCorrectionSupport;
+ cl_device_local_mem_type m_localMemType;
+ cl_uint m_maxReadImageArgs;
+ cl_uint m_maxWriteImageArgs;
+
+
+
+ cl_uint m_addressBits;
+ cl_ulong m_maxMemAllocSize;
+ cl_command_queue_properties m_queueProperties;
+ cl_bool m_imageSupport;
+ cl_uint m_vecWidthChar;
+ cl_uint m_vecWidthShort;
+ cl_uint m_vecWidthInt;
+ cl_uint m_vecWidthLong;
+ cl_uint m_vecWidthFloat;
+ cl_uint m_vecWidthDouble;
+
+} b3OpenCLDeviceInfo;
+
+struct b3OpenCLPlatformInfo
+{
+ char m_platformVendor[B3_MAX_STRING_LENGTH];
+ char m_platformName[B3_MAX_STRING_LENGTH];
+ char m_platformVersion[B3_MAX_STRING_LENGTH];
+
+ b3OpenCLPlatformInfo()
+ {
+ m_platformVendor[0]=0;
+ m_platformName[0]=0;
+ m_platformVersion[0]=0;
+ }
+};
+
+
+///C++ API for OpenCL utilities: convenience functions
+struct b3OpenCLUtils
+{
+ /// CL Context optionally takes a GL context. This is a generic type because we don't really want this code
+ /// to have to understand GL types. It is a HGLRC in _WIN32 or a GLXContext otherwise.
+ static inline cl_context createContextFromType(cl_device_type deviceType, cl_int* pErrNum, void* pGLCtx = 0, void* pGLDC = 0, int preferredDeviceIndex = -1, int preferredPlatformIndex= - 1, cl_platform_id* platformId=0)
+ {
+ return b3OpenCLUtils_createContextFromType(deviceType, pErrNum, pGLCtx , pGLDC , preferredDeviceIndex, preferredPlatformIndex, platformId);
+ }
+
+ static inline int getNumDevices(cl_context cxMainContext)
+ {
+ return b3OpenCLUtils_getNumDevices(cxMainContext);
+ }
+ static inline cl_device_id getDevice(cl_context cxMainContext, int nr)
+ {
+ return b3OpenCLUtils_getDevice(cxMainContext,nr);
+ }
+
+ static void getDeviceInfo(cl_device_id device, b3OpenCLDeviceInfo* info);
+
+ static inline void printDeviceInfo(cl_device_id device)
+ {
+ b3OpenCLUtils_printDeviceInfo(device);
+ }
+
+ static inline cl_kernel compileCLKernelFromString( cl_context clContext,cl_device_id device, const char* kernelSource, const char* kernelName, cl_int* pErrNum=0, cl_program prog=0,const char* additionalMacros = "" )
+ {
+ return b3OpenCLUtils_compileCLKernelFromString(clContext,device, kernelSource, kernelName, pErrNum, prog,additionalMacros);
+ }
+
+ //optional
+ static inline cl_program compileCLProgramFromString( cl_context clContext,cl_device_id device, const char* kernelSource, cl_int* pErrNum=0,const char* additionalMacros = "" , const char* srcFileNameForCaching=0, bool disableBinaryCaching=false)
+ {
+ return b3OpenCLUtils_compileCLProgramFromString(clContext,device, kernelSource, pErrNum,additionalMacros, srcFileNameForCaching, disableBinaryCaching);
+ }
+
+ //the following optional APIs provide access using specific platform information
+ static inline int getNumPlatforms(cl_int* pErrNum=0)
+ {
+ return b3OpenCLUtils_getNumPlatforms(pErrNum);
+ }
+ ///get the nr'th platform, where nr is in the range [0..getNumPlatforms)
+ static inline cl_platform_id getPlatform(int nr, cl_int* pErrNum=0)
+ {
+ return b3OpenCLUtils_getPlatform(nr,pErrNum);
+ }
+
+ static void getPlatformInfo(cl_platform_id platform, b3OpenCLPlatformInfo* platformInfo);
+
+ static inline void printPlatformInfo(cl_platform_id platform)
+ {
+ b3OpenCLUtils_printPlatformInfo(platform);
+ }
+
+ static inline const char* getSdkVendorName()
+ {
+ return b3OpenCLUtils_getSdkVendorName();
+ }
+ static inline cl_context createContextFromPlatform(cl_platform_id platform, cl_device_type deviceType, cl_int* pErrNum, void* pGLCtx = 0, void* pGLDC = 0,int preferredDeviceIndex = -1, int preferredPlatformIndex= -1)
+ {
+ return b3OpenCLUtils_createContextFromPlatform(platform, deviceType, pErrNum, pGLCtx,pGLDC,preferredDeviceIndex, preferredPlatformIndex);
+ }
+ static void setCachePath(const char* path)
+ {
+ b3OpenCLUtils_setCachePath(path);
+ }
+};
+
+#endif //__cplusplus
+
+#endif // B3_OPENCL_UTILS_H
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3BvhInfo.h b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3BvhInfo.h
new file mode 100644
index 0000000000..872f039506
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3BvhInfo.h
@@ -0,0 +1,18 @@
+#ifndef B3_BVH_INFO_H
+#define B3_BVH_INFO_H
+
+#include "Bullet3Common/b3Vector3.h"
+
+struct b3BvhInfo
+{
+ b3Vector3 m_aabbMin;
+ b3Vector3 m_aabbMax;
+ b3Vector3 m_quantization;
+ int m_numNodes;
+ int m_numSubTrees;
+ int m_nodeOffset;
+ int m_subTreeOffset;
+
+};
+
+#endif //B3_BVH_INFO_H \ No newline at end of file
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3ContactCache.cpp b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3ContactCache.cpp
new file mode 100644
index 0000000000..cb30ee939b
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3ContactCache.cpp
@@ -0,0 +1,258 @@
+
+#if 0
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "b3ContactCache.h"
+#include "Bullet3Common/b3Transform.h"
+
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h"
+
+b3Scalar gContactBreakingThreshold = b3Scalar(0.02);
+
+///gContactCalcArea3Points will approximate the convex hull area using 3 points
+///when setting it to false, it will use 4 points to compute the area: it is more accurate but slower
+bool gContactCalcArea3Points = true;
+
+
+
+
+static inline b3Scalar calcArea4Points(const b3Vector3 &p0,const b3Vector3 &p1,const b3Vector3 &p2,const b3Vector3 &p3)
+{
+ // It calculates possible 3 area constructed from random 4 points and returns the biggest one.
+
+ b3Vector3 a[3],b[3];
+ a[0] = p0 - p1;
+ a[1] = p0 - p2;
+ a[2] = p0 - p3;
+ b[0] = p2 - p3;
+ b[1] = p1 - p3;
+ b[2] = p1 - p2;
+
+ //todo: Following 3 cross production can be easily optimized by SIMD.
+ b3Vector3 tmp0 = a[0].cross(b[0]);
+ b3Vector3 tmp1 = a[1].cross(b[1]);
+ b3Vector3 tmp2 = a[2].cross(b[2]);
+
+ return b3Max(b3Max(tmp0.length2(),tmp1.length2()),tmp2.length2());
+}
+#if 0
+
+//using localPointA for all points
+int b3ContactCache::sortCachedPoints(const b3Vector3& pt)
+{
+ //calculate 4 possible cases areas, and take biggest area
+ //also need to keep 'deepest'
+
+ int maxPenetrationIndex = -1;
+#define KEEP_DEEPEST_POINT 1
+#ifdef KEEP_DEEPEST_POINT
+ b3Scalar maxPenetration = pt.getDistance();
+ for (int i=0;i<4;i++)
+ {
+ if (m_pointCache[i].getDistance() < maxPenetration)
+ {
+ maxPenetrationIndex = i;
+ maxPenetration = m_pointCache[i].getDistance();
+ }
+ }
+#endif //KEEP_DEEPEST_POINT
+
+ b3Scalar res0(b3Scalar(0.)),res1(b3Scalar(0.)),res2(b3Scalar(0.)),res3(b3Scalar(0.));
+
+ if (gContactCalcArea3Points)
+ {
+ if (maxPenetrationIndex != 0)
+ {
+ b3Vector3 a0 = pt.m_localPointA-m_pointCache[1].m_localPointA;
+ b3Vector3 b0 = m_pointCache[3].m_localPointA-m_pointCache[2].m_localPointA;
+ b3Vector3 cross = a0.cross(b0);
+ res0 = cross.length2();
+ }
+ if (maxPenetrationIndex != 1)
+ {
+ b3Vector3 a1 = pt.m_localPointA-m_pointCache[0].m_localPointA;
+ b3Vector3 b1 = m_pointCache[3].m_localPointA-m_pointCache[2].m_localPointA;
+ b3Vector3 cross = a1.cross(b1);
+ res1 = cross.length2();
+ }
+
+ if (maxPenetrationIndex != 2)
+ {
+ b3Vector3 a2 = pt.m_localPointA-m_pointCache[0].m_localPointA;
+ b3Vector3 b2 = m_pointCache[3].m_localPointA-m_pointCache[1].m_localPointA;
+ b3Vector3 cross = a2.cross(b2);
+ res2 = cross.length2();
+ }
+
+ if (maxPenetrationIndex != 3)
+ {
+ b3Vector3 a3 = pt.m_localPointA-m_pointCache[0].m_localPointA;
+ b3Vector3 b3 = m_pointCache[2].m_localPointA-m_pointCache[1].m_localPointA;
+ b3Vector3 cross = a3.cross(b3);
+ res3 = cross.length2();
+ }
+ }
+ else
+ {
+ if(maxPenetrationIndex != 0) {
+ res0 = calcArea4Points(pt.m_localPointA,m_pointCache[1].m_localPointA,m_pointCache[2].m_localPointA,m_pointCache[3].m_localPointA);
+ }
+
+ if(maxPenetrationIndex != 1) {
+ res1 = calcArea4Points(pt.m_localPointA,m_pointCache[0].m_localPointA,m_pointCache[2].m_localPointA,m_pointCache[3].m_localPointA);
+ }
+
+ if(maxPenetrationIndex != 2) {
+ res2 = calcArea4Points(pt.m_localPointA,m_pointCache[0].m_localPointA,m_pointCache[1].m_localPointA,m_pointCache[3].m_localPointA);
+ }
+
+ if(maxPenetrationIndex != 3) {
+ res3 = calcArea4Points(pt.m_localPointA,m_pointCache[0].m_localPointA,m_pointCache[1].m_localPointA,m_pointCache[2].m_localPointA);
+ }
+ }
+ b3Vector4 maxvec(res0,res1,res2,res3);
+ int biggestarea = maxvec.closestAxis4();
+ return biggestarea;
+
+}
+
+
+int b3ContactCache::getCacheEntry(const b3Vector3& newPoint) const
+{
+ b3Scalar shortestDist = getContactBreakingThreshold() * getContactBreakingThreshold();
+ int size = getNumContacts();
+ int nearestPoint = -1;
+ for( int i = 0; i < size; i++ )
+ {
+ const b3Vector3 &mp = m_pointCache[i];
+
+ b3Vector3 diffA = mp.m_localPointA- newPoint.m_localPointA;
+ const b3Scalar distToManiPoint = diffA.dot(diffA);
+ if( distToManiPoint < shortestDist )
+ {
+ shortestDist = distToManiPoint;
+ nearestPoint = i;
+ }
+ }
+ return nearestPoint;
+}
+
+int b3ContactCache::addManifoldPoint(const b3Vector3& newPoint)
+{
+ b3Assert(validContactDistance(newPoint));
+
+ int insertIndex = getNumContacts();
+ if (insertIndex == MANIFOLD_CACHE_SIZE)
+ {
+#if MANIFOLD_CACHE_SIZE >= 4
+ //sort cache so best points come first, based on area
+ insertIndex = sortCachedPoints(newPoint);
+#else
+ insertIndex = 0;
+#endif
+ clearUserCache(m_pointCache[insertIndex]);
+
+ } else
+ {
+ m_cachedPoints++;
+
+
+ }
+ if (insertIndex<0)
+ insertIndex=0;
+
+ //b3Assert(m_pointCache[insertIndex].m_userPersistentData==0);
+ m_pointCache[insertIndex] = newPoint;
+ return insertIndex;
+}
+
+#endif
+
+bool b3ContactCache::validContactDistance(const b3Vector3& pt)
+{
+ return pt.w <= gContactBreakingThreshold;
+}
+
+void b3ContactCache::removeContactPoint(struct b3Contact4Data& newContactCache,int i)
+{
+ int numContacts = b3Contact4Data_getNumPoints(&newContactCache);
+ if (i!=(numContacts-1))
+ {
+ b3Swap(newContactCache.m_localPosA[i],newContactCache.m_localPosA[numContacts-1]);
+ b3Swap(newContactCache.m_localPosB[i],newContactCache.m_localPosB[numContacts-1]);
+ b3Swap(newContactCache.m_worldPosB[i],newContactCache.m_worldPosB[numContacts-1]);
+ }
+ b3Contact4Data_setNumPoints(&newContactCache,numContacts-1);
+
+}
+
+
+void b3ContactCache::refreshContactPoints(const b3Transform& trA,const b3Transform& trB, struct b3Contact4Data& contacts)
+{
+
+ int numContacts = b3Contact4Data_getNumPoints(&contacts);
+
+
+ int i;
+ /// first refresh worldspace positions and distance
+ for (i=numContacts-1;i>=0;i--)
+ {
+ b3Vector3 worldPosA = trA( contacts.m_localPosA[i]);
+ b3Vector3 worldPosB = trB( contacts.m_localPosB[i]);
+ contacts.m_worldPosB[i] = worldPosB;
+ float distance = (worldPosA - worldPosB).dot(contacts.m_worldNormalOnB);
+ contacts.m_worldPosB[i].w = distance;
+ }
+
+ /// then
+ b3Scalar distance2d;
+ b3Vector3 projectedDifference,projectedPoint;
+ for (i=numContacts-1;i>=0;i--)
+ {
+ b3Vector3 worldPosA = trA( contacts.m_localPosA[i]);
+ b3Vector3 worldPosB = trB( contacts.m_localPosB[i]);
+ b3Vector3&pt = contacts.m_worldPosB[i];
+ //contact becomes invalid when signed distance exceeds margin (projected on contactnormal direction)
+ if (!validContactDistance(pt))
+ {
+ removeContactPoint(contacts,i);
+ } else
+ {
+ //contact also becomes invalid when relative movement orthogonal to normal exceeds margin
+ projectedPoint = worldPosA - contacts.m_worldNormalOnB * contacts.m_worldPosB[i].w;
+ projectedDifference = contacts.m_worldPosB[i] - projectedPoint;
+ distance2d = projectedDifference.dot(projectedDifference);
+ if (distance2d > gContactBreakingThreshold*gContactBreakingThreshold )
+ {
+ removeContactPoint(contacts,i);
+ } else
+ {
+ ////contact point processed callback
+ //if (gContactProcessedCallback)
+ // (*gContactProcessedCallback)(manifoldPoint,(void*)m_body0,(void*)m_body1);
+ }
+ }
+ }
+
+
+}
+
+
+
+
+
+#endif
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3ContactCache.h b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3ContactCache.h
new file mode 100644
index 0000000000..d6c9b0a07e
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3ContactCache.h
@@ -0,0 +1,80 @@
+
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2013 Erwin Coumans 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 B3_CONTACT_CACHE_H
+#define B3_CONTACT_CACHE_H
+
+
+#include "Bullet3Common/b3Vector3.h"
+#include "Bullet3Common/b3Transform.h"
+#include "Bullet3Common/b3AlignedAllocator.h"
+
+
+///maximum contact breaking and merging threshold
+extern b3Scalar gContactBreakingThreshold;
+
+
+
+#define MANIFOLD_CACHE_SIZE 4
+
+///b3ContactCache is a contact point cache, it stays persistent as long as objects are overlapping in the broadphase.
+///Those contact points are created by the collision narrow phase.
+///The cache can be empty, or hold 1,2,3 or 4 points. Some collision algorithms (GJK) might only add one point at a time.
+///updates/refreshes old contact points, and throw them away if necessary (distance becomes too large)
+///reduces the cache to 4 points, when more then 4 points are added, using following rules:
+///the contact point with deepest penetration is always kept, and it tries to maximuze the area covered by the points
+///note that some pairs of objects might have more then one contact manifold.
+B3_ATTRIBUTE_ALIGNED16( class) b3ContactCache
+{
+
+
+
+
+ /// sort cached points so most isolated points come first
+ int sortCachedPoints(const b3Vector3& pt);
+
+
+
+public:
+
+ B3_DECLARE_ALIGNED_ALLOCATOR();
+
+
+
+ int addManifoldPoint( const b3Vector3& newPoint);
+
+ /*void replaceContactPoint(const b3Vector3& newPoint,int insertIndex)
+ {
+ b3Assert(validContactDistance(newPoint));
+ m_pointCache[insertIndex] = newPoint;
+ }
+ */
+
+
+
+ static bool validContactDistance(const b3Vector3& pt);
+
+ /// calculated new worldspace coordinates and depth, and reject points that exceed the collision margin
+ static void refreshContactPoints( const b3Transform& trA,const b3Transform& trB, struct b3Contact4Data& newContactCache);
+
+ static void removeContactPoint(struct b3Contact4Data& newContactCache,int i);
+
+
+};
+
+
+
+#endif //B3_CONTACT_CACHE_H
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3ConvexHullContact.cpp b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3ConvexHullContact.cpp
new file mode 100644
index 0000000000..fb435aa7fd
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3ConvexHullContact.cpp
@@ -0,0 +1,4733 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2011 Advanced Micro Devices, 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.
+*/
+
+bool findSeparatingAxisOnGpu = true;
+bool splitSearchSepAxisConcave = false;
+bool splitSearchSepAxisConvex = true;
+bool useMprGpu = true;//use mpr for edge-edge (+contact point) or sat. Needs testing on main OpenCL platforms, before enabling...
+bool bvhTraversalKernelGPU = true;
+bool findConcaveSeparatingAxisKernelGPU = true;
+bool clipConcaveFacesAndFindContactsCPU = false;//false;//true;
+bool clipConvexFacesAndFindContactsCPU = false;//false;//true;
+bool reduceConcaveContactsOnGPU = true;//false;
+bool reduceConvexContactsOnGPU = true;//false;
+bool findConvexClippingFacesGPU = true;
+bool useGjk = false;///option for CPU/host testing, when findSeparatingAxisOnGpu = false
+bool useGjkContacts = false;//////option for CPU/host testing when findSeparatingAxisOnGpu = false
+
+
+static int myframecount=0;///for testing
+
+///This file was written by Erwin Coumans
+///Separating axis rest based on work from Pierre Terdiman, see
+///And contact clipping based on work from Simon Hobbs
+
+//#define B3_DEBUG_SAT_FACE
+
+//#define CHECK_ON_HOST
+
+#ifdef CHECK_ON_HOST
+//#define PERSISTENT_CONTACTS_HOST
+#endif
+
+int b3g_actualSATPairTests=0;
+
+#include "b3ConvexHullContact.h"
+#include <string.h>//memcpy
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3MprPenetration.h"
+
+#include "Bullet3OpenCL/NarrowphaseCollision/b3ContactCache.h"
+#include "Bullet3Geometry/b3AabbUtil.h"
+
+typedef b3AlignedObjectArray<b3Vector3> b3VertexArray;
+
+
+#include <float.h> //for FLT_MAX
+#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
+#include "Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.h"
+//#include "AdlQuaternion.h"
+
+#include "kernels/satKernels.h"
+#include "kernels/mprKernels.h"
+
+#include "kernels/satConcaveKernels.h"
+
+#include "kernels/satClipHullContacts.h"
+#include "kernels/bvhTraversal.h"
+#include "kernels/primitiveContacts.h"
+
+
+#include "Bullet3Geometry/b3AabbUtil.h"
+
+#define BT_NARROWPHASE_SAT_PATH "src/Bullet3OpenCL/NarrowphaseCollision/kernels/sat.cl"
+#define BT_NARROWPHASE_SAT_CONCAVE_PATH "src/Bullet3OpenCL/NarrowphaseCollision/kernels/satConcave.cl"
+
+#define BT_NARROWPHASE_MPR_PATH "src/Bullet3OpenCL/NarrowphaseCollision/kernels/mpr.cl"
+
+
+#define BT_NARROWPHASE_CLIPHULL_PATH "src/Bullet3OpenCL/NarrowphaseCollision/kernels/satClipHullContacts.cl"
+#define BT_NARROWPHASE_BVH_TRAVERSAL_PATH "src/Bullet3OpenCL/NarrowphaseCollision/kernels/bvhTraversal.cl"
+#define BT_NARROWPHASE_PRIMITIVE_CONTACT_PATH "src/Bullet3OpenCL/NarrowphaseCollision/kernels/primitiveContacts.cl"
+
+
+#ifndef __global
+#define __global
+#endif
+
+#ifndef __kernel
+#define __kernel
+#endif
+
+
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3BvhTraversal.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3FindConcaveSatAxis.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3ClipFaces.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3NewContactReduction.h"
+
+
+
+#define dot3F4 b3Dot
+
+GpuSatCollision::GpuSatCollision(cl_context ctx,cl_device_id device, cl_command_queue q )
+:m_context(ctx),
+m_device(device),
+m_queue(q),
+
+m_findSeparatingAxisKernel(0),
+m_findSeparatingAxisVertexFaceKernel(0),
+m_findSeparatingAxisEdgeEdgeKernel(0),
+m_unitSphereDirections(m_context,m_queue),
+
+m_totalContactsOut(m_context, m_queue),
+m_sepNormals(m_context, m_queue),
+m_dmins(m_context,m_queue),
+
+m_hasSeparatingNormals(m_context, m_queue),
+m_concaveSepNormals(m_context, m_queue),
+m_concaveHasSeparatingNormals(m_context,m_queue),
+m_numConcavePairsOut(m_context, m_queue),
+
+
+m_gpuCompoundPairs(m_context, m_queue),
+
+
+m_gpuCompoundSepNormals(m_context, m_queue),
+m_gpuHasCompoundSepNormals(m_context, m_queue),
+
+m_numCompoundPairsOut(m_context, m_queue)
+{
+ m_totalContactsOut.push_back(0);
+
+ cl_int errNum=0;
+
+ if (1)
+ {
+ const char* mprSrc = mprKernelsCL;
+
+ const char* srcConcave = satConcaveKernelsCL;
+ char flags[1024]={0};
+//#ifdef CL_PLATFORM_INTEL
+// sprintf(flags,"-g -s \"%s\"","C:/develop/bullet3_experiments2/opencl/gpu_narrowphase/kernels/sat.cl");
+//#endif
+ m_mprPenetrationKernel = 0;
+ m_findSeparatingAxisUnitSphereKernel = 0;
+
+ if (useMprGpu)
+ {
+ cl_program mprProg = b3OpenCLUtils::compileCLProgramFromString(m_context,m_device,mprSrc,&errNum,flags,BT_NARROWPHASE_MPR_PATH);
+ b3Assert(errNum==CL_SUCCESS);
+
+ m_mprPenetrationKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,mprSrc, "mprPenetrationKernel",&errNum,mprProg );
+ b3Assert(m_mprPenetrationKernel);
+ b3Assert(errNum==CL_SUCCESS);
+
+ m_findSeparatingAxisUnitSphereKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,mprSrc, "findSeparatingAxisUnitSphereKernel",&errNum,mprProg );
+ b3Assert(m_findSeparatingAxisUnitSphereKernel);
+ b3Assert(errNum==CL_SUCCESS);
+
+
+ int numDirections = sizeof(unitSphere162)/sizeof(b3Vector3);
+ m_unitSphereDirections.resize(numDirections);
+ m_unitSphereDirections.copyFromHostPointer(unitSphere162,numDirections,0,true);
+
+
+ }
+
+
+ cl_program satProg = b3OpenCLUtils::compileCLProgramFromString(m_context,m_device,satKernelsCL,&errNum,flags,BT_NARROWPHASE_SAT_PATH);
+ b3Assert(errNum==CL_SUCCESS);
+
+ cl_program satConcaveProg = b3OpenCLUtils::compileCLProgramFromString(m_context,m_device,srcConcave,&errNum,flags,BT_NARROWPHASE_SAT_CONCAVE_PATH);
+ b3Assert(errNum==CL_SUCCESS);
+
+ m_findSeparatingAxisKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,satKernelsCL, "findSeparatingAxisKernel",&errNum,satProg );
+ b3Assert(m_findSeparatingAxisKernel);
+ b3Assert(errNum==CL_SUCCESS);
+
+
+ m_findSeparatingAxisVertexFaceKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,satKernelsCL, "findSeparatingAxisVertexFaceKernel",&errNum,satProg );
+ b3Assert(m_findSeparatingAxisVertexFaceKernel);
+
+ m_findSeparatingAxisEdgeEdgeKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,satKernelsCL, "findSeparatingAxisEdgeEdgeKernel",&errNum,satProg );
+ b3Assert(m_findSeparatingAxisVertexFaceKernel);
+
+
+ m_findConcaveSeparatingAxisKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,satKernelsCL, "findConcaveSeparatingAxisKernel",&errNum,satProg );
+ b3Assert(m_findConcaveSeparatingAxisKernel);
+ b3Assert(errNum==CL_SUCCESS);
+
+ m_findConcaveSeparatingAxisVertexFaceKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,srcConcave, "findConcaveSeparatingAxisVertexFaceKernel",&errNum,satConcaveProg );
+ b3Assert(m_findConcaveSeparatingAxisVertexFaceKernel);
+ b3Assert(errNum==CL_SUCCESS);
+
+ m_findConcaveSeparatingAxisEdgeEdgeKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,srcConcave, "findConcaveSeparatingAxisEdgeEdgeKernel",&errNum,satConcaveProg );
+ b3Assert(m_findConcaveSeparatingAxisEdgeEdgeKernel);
+ b3Assert(errNum==CL_SUCCESS);
+
+
+
+
+ m_findCompoundPairsKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,satKernelsCL, "findCompoundPairsKernel",&errNum,satProg );
+ b3Assert(m_findCompoundPairsKernel);
+ b3Assert(errNum==CL_SUCCESS);
+ m_processCompoundPairsKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,satKernelsCL, "processCompoundPairsKernel",&errNum,satProg );
+ b3Assert(m_processCompoundPairsKernel);
+ b3Assert(errNum==CL_SUCCESS);
+ }
+
+ if (1)
+ {
+ const char* srcClip = satClipKernelsCL;
+
+ char flags[1024]={0};
+//#ifdef CL_PLATFORM_INTEL
+// sprintf(flags,"-g -s \"%s\"","C:/develop/bullet3_experiments2/opencl/gpu_narrowphase/kernels/satClipHullContacts.cl");
+//#endif
+
+ cl_program satClipContactsProg = b3OpenCLUtils::compileCLProgramFromString(m_context,m_device,srcClip,&errNum,flags,BT_NARROWPHASE_CLIPHULL_PATH);
+ b3Assert(errNum==CL_SUCCESS);
+
+ m_clipHullHullKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,srcClip, "clipHullHullKernel",&errNum,satClipContactsProg);
+ b3Assert(errNum==CL_SUCCESS);
+
+ m_clipCompoundsHullHullKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,srcClip, "clipCompoundsHullHullKernel",&errNum,satClipContactsProg);
+ b3Assert(errNum==CL_SUCCESS);
+
+
+ m_findClippingFacesKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,srcClip, "findClippingFacesKernel",&errNum,satClipContactsProg);
+ b3Assert(errNum==CL_SUCCESS);
+
+ m_clipFacesAndFindContacts = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,srcClip, "clipFacesAndFindContactsKernel",&errNum,satClipContactsProg);
+ b3Assert(errNum==CL_SUCCESS);
+
+ m_clipHullHullConcaveConvexKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,srcClip, "clipHullHullConcaveConvexKernel",&errNum,satClipContactsProg);
+ b3Assert(errNum==CL_SUCCESS);
+
+// m_extractManifoldAndAddContactKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,srcClip, "extractManifoldAndAddContactKernel",&errNum,satClipContactsProg);
+ // b3Assert(errNum==CL_SUCCESS);
+
+ m_newContactReductionKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,srcClip,
+ "newContactReductionKernel",&errNum,satClipContactsProg);
+ b3Assert(errNum==CL_SUCCESS);
+ }
+ else
+ {
+ m_clipHullHullKernel=0;
+ m_clipCompoundsHullHullKernel = 0;
+ m_findClippingFacesKernel = 0;
+ m_newContactReductionKernel=0;
+ m_clipFacesAndFindContacts = 0;
+ m_clipHullHullConcaveConvexKernel = 0;
+// m_extractManifoldAndAddContactKernel = 0;
+ }
+
+ if (1)
+ {
+ const char* srcBvh = bvhTraversalKernelCL;
+ cl_program bvhTraversalProg = b3OpenCLUtils::compileCLProgramFromString(m_context,m_device,srcBvh,&errNum,"",BT_NARROWPHASE_BVH_TRAVERSAL_PATH);
+ b3Assert(errNum==CL_SUCCESS);
+
+ m_bvhTraversalKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,srcBvh, "bvhTraversalKernel",&errNum,bvhTraversalProg,"");
+ b3Assert(errNum==CL_SUCCESS);
+
+ }
+
+ {
+ const char* primitiveContactsSrc = primitiveContactsKernelsCL;
+ cl_program primitiveContactsProg = b3OpenCLUtils::compileCLProgramFromString(m_context,m_device,primitiveContactsSrc,&errNum,"",BT_NARROWPHASE_PRIMITIVE_CONTACT_PATH);
+ b3Assert(errNum==CL_SUCCESS);
+
+ m_primitiveContactsKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,primitiveContactsSrc, "primitiveContactsKernel",&errNum,primitiveContactsProg,"");
+ b3Assert(errNum==CL_SUCCESS);
+
+ m_findConcaveSphereContactsKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,primitiveContactsSrc, "findConcaveSphereContactsKernel",&errNum,primitiveContactsProg );
+ b3Assert(errNum==CL_SUCCESS);
+ b3Assert(m_findConcaveSphereContactsKernel);
+
+ m_processCompoundPairsPrimitivesKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,primitiveContactsSrc, "processCompoundPairsPrimitivesKernel",&errNum,primitiveContactsProg,"");
+ b3Assert(errNum==CL_SUCCESS);
+ b3Assert(m_processCompoundPairsPrimitivesKernel);
+
+ }
+
+
+}
+
+GpuSatCollision::~GpuSatCollision()
+{
+
+ if (m_findSeparatingAxisVertexFaceKernel)
+ clReleaseKernel(m_findSeparatingAxisVertexFaceKernel);
+
+ if (m_findSeparatingAxisEdgeEdgeKernel)
+ clReleaseKernel(m_findSeparatingAxisEdgeEdgeKernel);
+
+ if (m_findSeparatingAxisUnitSphereKernel)
+ clReleaseKernel(m_findSeparatingAxisUnitSphereKernel);
+
+ if (m_mprPenetrationKernel)
+ clReleaseKernel(m_mprPenetrationKernel);
+
+
+ if (m_findSeparatingAxisKernel)
+ clReleaseKernel(m_findSeparatingAxisKernel);
+
+ if (m_findConcaveSeparatingAxisVertexFaceKernel)
+ clReleaseKernel(m_findConcaveSeparatingAxisVertexFaceKernel);
+
+
+ if (m_findConcaveSeparatingAxisEdgeEdgeKernel)
+ clReleaseKernel(m_findConcaveSeparatingAxisEdgeEdgeKernel);
+
+ if (m_findConcaveSeparatingAxisKernel)
+ clReleaseKernel(m_findConcaveSeparatingAxisKernel);
+
+ if (m_findCompoundPairsKernel)
+ clReleaseKernel(m_findCompoundPairsKernel);
+
+ if (m_processCompoundPairsKernel)
+ clReleaseKernel(m_processCompoundPairsKernel);
+
+ if (m_findClippingFacesKernel)
+ clReleaseKernel(m_findClippingFacesKernel);
+
+ if (m_clipFacesAndFindContacts)
+ clReleaseKernel(m_clipFacesAndFindContacts);
+ if (m_newContactReductionKernel)
+ clReleaseKernel(m_newContactReductionKernel);
+ if (m_primitiveContactsKernel)
+ clReleaseKernel(m_primitiveContactsKernel);
+
+ if (m_findConcaveSphereContactsKernel)
+ clReleaseKernel(m_findConcaveSphereContactsKernel);
+
+ if (m_processCompoundPairsPrimitivesKernel)
+ clReleaseKernel(m_processCompoundPairsPrimitivesKernel);
+
+ if (m_clipHullHullKernel)
+ clReleaseKernel(m_clipHullHullKernel);
+ if (m_clipCompoundsHullHullKernel)
+ clReleaseKernel(m_clipCompoundsHullHullKernel);
+
+ if (m_clipHullHullConcaveConvexKernel)
+ clReleaseKernel(m_clipHullHullConcaveConvexKernel);
+// if (m_extractManifoldAndAddContactKernel)
+ // clReleaseKernel(m_extractManifoldAndAddContactKernel);
+
+ if (m_bvhTraversalKernel)
+ clReleaseKernel(m_bvhTraversalKernel);
+
+}
+
+struct MyTriangleCallback : public b3NodeOverlapCallback
+{
+ int m_bodyIndexA;
+ int m_bodyIndexB;
+
+ virtual void processNode(int subPart, int triangleIndex)
+ {
+ printf("bodyIndexA %d, bodyIndexB %d\n",m_bodyIndexA,m_bodyIndexB);
+ printf("triangleIndex %d\n", triangleIndex);
+ }
+};
+
+
+#define float4 b3Vector3
+#define make_float4(x,y,z,w) b3MakeVector3(x,y,z,w)
+
+float signedDistanceFromPointToPlane(const float4& point, const float4& planeEqn, float4* closestPointOnFace)
+{
+ float4 n = planeEqn;
+ n[3] = 0.f;
+ float dist = dot3F4(n, point) + planeEqn[3];
+ *closestPointOnFace = point - dist * n;
+ return dist;
+}
+
+
+
+#define cross3(a,b) (a.cross(b))
+b3Vector3 transform(const b3Vector3* v, const b3Vector3* pos, const b3Quaternion* orn)
+{
+ b3Transform tr;
+ tr.setIdentity();
+ tr.setOrigin(*pos);
+ tr.setRotation(*orn);
+ b3Vector3 res = tr(*v);
+ return res;
+}
+
+
+inline bool IsPointInPolygon(const float4& p,
+ const b3GpuFace* face,
+ const float4* baseVertex,
+ const int* convexIndices,
+ float4* out)
+{
+ float4 a;
+ float4 b;
+ float4 ab;
+ float4 ap;
+ float4 v;
+
+ float4 plane = b3MakeVector3(face->m_plane.x,face->m_plane.y,face->m_plane.z,0.f);
+
+ if (face->m_numIndices<2)
+ return false;
+
+
+ float4 v0 = baseVertex[convexIndices[face->m_indexOffset + face->m_numIndices-1]];
+ b = v0;
+
+ for(unsigned i=0; i != face->m_numIndices; ++i)
+ {
+ a = b;
+ float4 vi = baseVertex[convexIndices[face->m_indexOffset + i]];
+ b = vi;
+ ab = b-a;
+ ap = p-a;
+ v = cross3(ab,plane);
+
+ if (b3Dot(ap, v) > 0.f)
+ {
+ float ab_m2 = b3Dot(ab, ab);
+ float rt = ab_m2 != 0.f ? b3Dot(ab, ap) / ab_m2 : 0.f;
+ if (rt <= 0.f)
+ {
+ *out = a;
+ }
+ else if (rt >= 1.f)
+ {
+ *out = b;
+ }
+ else
+ {
+ float s = 1.f - rt;
+ out[0].x = s * a.x + rt * b.x;
+ out[0].y = s * a.y + rt * b.y;
+ out[0].z = s * a.z + rt * b.z;
+ }
+ return false;
+ }
+ }
+ return true;
+}
+
+#define normalize3(a) (a.normalize())
+
+
+int extractManifoldSequentialGlobal( const float4* p, int nPoints, const float4& nearNormal, b3Int4* contactIdx)
+{
+ if( nPoints == 0 )
+ return 0;
+
+ if (nPoints <=4)
+ return nPoints;
+
+
+ if (nPoints >64)
+ nPoints = 64;
+
+ float4 center = b3MakeVector3(0,0,0,0);
+ {
+
+ for (int i=0;i<nPoints;i++)
+ center += p[i];
+ center /= (float)nPoints;
+ }
+
+
+
+ // sample 4 directions
+
+ float4 aVector = p[0] - center;
+ float4 u = cross3( nearNormal, aVector );
+ float4 v = cross3( nearNormal, u );
+ u = normalize3( u );
+ v = normalize3( v );
+
+
+ //keep point with deepest penetration
+ float minW= FLT_MAX;
+
+ int minIndex=-1;
+
+ float4 maxDots;
+ maxDots.x = FLT_MIN;
+ maxDots.y = FLT_MIN;
+ maxDots.z = FLT_MIN;
+ maxDots.w = FLT_MIN;
+
+ // idx, distance
+ for(int ie = 0; ie<nPoints; ie++ )
+ {
+ if (p[ie].w<minW)
+ {
+ minW = p[ie].w;
+ minIndex=ie;
+ }
+ float f;
+ float4 r = p[ie]-center;
+ f = dot3F4( u, r );
+ if (f<maxDots.x)
+ {
+ maxDots.x = f;
+ contactIdx[0].x = ie;
+ }
+
+ f = dot3F4( -u, r );
+ if (f<maxDots.y)
+ {
+ maxDots.y = f;
+ contactIdx[0].y = ie;
+ }
+
+
+ f = dot3F4( v, r );
+ if (f<maxDots.z)
+ {
+ maxDots.z = f;
+ contactIdx[0].z = ie;
+ }
+
+ f = dot3F4( -v, r );
+ if (f<maxDots.w)
+ {
+ maxDots.w = f;
+ contactIdx[0].w = ie;
+ }
+
+ }
+
+ if (contactIdx[0].x != minIndex && contactIdx[0].y != minIndex && contactIdx[0].z != minIndex && contactIdx[0].w != minIndex)
+ {
+ //replace the first contact with minimum (todo: replace contact with least penetration)
+ contactIdx[0].x = minIndex;
+ }
+
+ return 4;
+
+}
+
+
+
+#define MAX_VERTS 1024
+
+
+inline void project(const b3ConvexPolyhedronData& hull, const float4& pos, const b3Quaternion& orn, const float4& dir, const b3AlignedObjectArray<b3Vector3>& vertices, b3Scalar& min, b3Scalar& max)
+{
+ min = FLT_MAX;
+ max = -FLT_MAX;
+ int numVerts = hull.m_numVertices;
+
+ const float4 localDir = b3QuatRotate(orn.inverse(),dir);
+
+ b3Scalar offset = dot3F4(pos,dir);
+
+ for(int i=0;i<numVerts;i++)
+ {
+ //b3Vector3 pt = trans * vertices[m_vertexOffset+i];
+ //b3Scalar dp = pt.dot(dir);
+ //b3Vector3 vertex = vertices[hull.m_vertexOffset+i];
+ b3Scalar dp = dot3F4((float4&)vertices[hull.m_vertexOffset+i],localDir);
+ //b3Assert(dp==dpL);
+ if(dp < min) min = dp;
+ if(dp > max) max = dp;
+ }
+ if(min>max)
+ {
+ b3Scalar tmp = min;
+ min = max;
+ max = tmp;
+ }
+ min += offset;
+ max += offset;
+}
+
+
+static bool TestSepAxis(const b3ConvexPolyhedronData& hullA, const b3ConvexPolyhedronData& hullB,
+ const float4& posA,const b3Quaternion& ornA,
+ const float4& posB,const b3Quaternion& ornB,
+ const float4& sep_axis, const b3AlignedObjectArray<b3Vector3>& verticesA,const b3AlignedObjectArray<b3Vector3>& verticesB,b3Scalar& depth)
+{
+ b3Scalar Min0,Max0;
+ b3Scalar Min1,Max1;
+ project(hullA,posA,ornA,sep_axis,verticesA, Min0, Max0);
+ project(hullB,posB,ornB, sep_axis,verticesB, Min1, Max1);
+
+ if(Max0<Min1 || Max1<Min0)
+ return false;
+
+ b3Scalar d0 = Max0 - Min1;
+ assert(d0>=0.0f);
+ b3Scalar d1 = Max1 - Min0;
+ assert(d1>=0.0f);
+ depth = d0<d1 ? d0:d1;
+ return true;
+}
+
+inline bool IsAlmostZero(const b3Vector3& v)
+{
+ if(fabsf(v.x)>1e-6 || fabsf(v.y)>1e-6 || fabsf(v.z)>1e-6) return false;
+ return true;
+}
+
+
+static bool findSeparatingAxis( const b3ConvexPolyhedronData& hullA, const b3ConvexPolyhedronData& hullB,
+ const float4& posA1,
+ const b3Quaternion& ornA,
+ const float4& posB1,
+ const b3Quaternion& ornB,
+ const b3AlignedObjectArray<b3Vector3>& verticesA,
+ const b3AlignedObjectArray<b3Vector3>& uniqueEdgesA,
+ const b3AlignedObjectArray<b3GpuFace>& facesA,
+ const b3AlignedObjectArray<int>& indicesA,
+ const b3AlignedObjectArray<b3Vector3>& verticesB,
+ const b3AlignedObjectArray<b3Vector3>& uniqueEdgesB,
+ const b3AlignedObjectArray<b3GpuFace>& facesB,
+ const b3AlignedObjectArray<int>& indicesB,
+
+ b3Vector3& sep)
+{
+ B3_PROFILE("findSeparatingAxis");
+
+ b3g_actualSATPairTests++;
+ float4 posA = posA1;
+ posA.w = 0.f;
+ float4 posB = posB1;
+ posB.w = 0.f;
+//#ifdef TEST_INTERNAL_OBJECTS
+ float4 c0local = (float4&)hullA.m_localCenter;
+ float4 c0 = transform(&c0local, &posA, &ornA);
+ float4 c1local = (float4&)hullB.m_localCenter;
+ float4 c1 = transform(&c1local,&posB,&ornB);
+ const float4 deltaC2 = c0 - c1;
+//#endif
+
+ b3Scalar dmin = FLT_MAX;
+ int curPlaneTests=0;
+
+ int numFacesA = hullA.m_numFaces;
+ // Test normals from hullA
+ for(int i=0;i<numFacesA;i++)
+ {
+ const float4& normal = (float4&)facesA[hullA.m_faceOffset+i].m_plane;
+ float4 faceANormalWS = b3QuatRotate(ornA,normal);
+
+ if (dot3F4(deltaC2,faceANormalWS)<0)
+ faceANormalWS*=-1.f;
+
+ curPlaneTests++;
+#ifdef TEST_INTERNAL_OBJECTS
+ gExpectedNbTests++;
+ if(gUseInternalObject && !TestInternalObjects(transA,transB, DeltaC2, faceANormalWS, hullA, hullB, dmin))
+ continue;
+ gActualNbTests++;
+#endif
+
+
+ b3Scalar d;
+ if(!TestSepAxis( hullA, hullB, posA,ornA,posB,ornB,faceANormalWS, verticesA, verticesB,d))
+ return false;
+
+ if(d<dmin)
+ {
+ dmin = d;
+ sep = (b3Vector3&)faceANormalWS;
+ }
+ }
+
+ int numFacesB = hullB.m_numFaces;
+ // Test normals from hullB
+ for(int i=0;i<numFacesB;i++)
+ {
+ float4 normal = (float4&)facesB[hullB.m_faceOffset+i].m_plane;
+ float4 WorldNormal = b3QuatRotate(ornB, normal);
+
+ if (dot3F4(deltaC2,WorldNormal)<0)
+ {
+ WorldNormal*=-1.f;
+ }
+ curPlaneTests++;
+#ifdef TEST_INTERNAL_OBJECTS
+ gExpectedNbTests++;
+ if(gUseInternalObject && !TestInternalObjects(transA,transB,DeltaC2, WorldNormal, hullA, hullB, dmin))
+ continue;
+ gActualNbTests++;
+#endif
+
+ b3Scalar d;
+ if(!TestSepAxis(hullA, hullB,posA,ornA,posB,ornB,WorldNormal,verticesA,verticesB,d))
+ return false;
+
+ if(d<dmin)
+ {
+ dmin = d;
+ sep = (b3Vector3&)WorldNormal;
+ }
+ }
+
+ int curEdgeEdge = 0;
+ // Test edges
+ for(int e0=0;e0<hullA.m_numUniqueEdges;e0++)
+ {
+ const float4& edge0 = (float4&) uniqueEdgesA[hullA.m_uniqueEdgesOffset+e0];
+ float4 edge0World = b3QuatRotate(ornA,(float4&)edge0);
+
+ for(int e1=0;e1<hullB.m_numUniqueEdges;e1++)
+ {
+ const b3Vector3 edge1 = uniqueEdgesB[hullB.m_uniqueEdgesOffset+e1];
+ float4 edge1World = b3QuatRotate(ornB,(float4&)edge1);
+
+
+ float4 crossje = cross3(edge0World,edge1World);
+
+ curEdgeEdge++;
+ if(!IsAlmostZero((b3Vector3&)crossje))
+ {
+ crossje = normalize3(crossje);
+ if (dot3F4(deltaC2,crossje)<0)
+ crossje*=-1.f;
+
+
+#ifdef TEST_INTERNAL_OBJECTS
+ gExpectedNbTests++;
+ if(gUseInternalObject && !TestInternalObjects(transA,transB,DeltaC2, Cross, hullA, hullB, dmin))
+ continue;
+ gActualNbTests++;
+#endif
+
+ b3Scalar dist;
+ if(!TestSepAxis( hullA, hullB, posA,ornA,posB,ornB,crossje, verticesA,verticesB,dist))
+ return false;
+
+ if(dist<dmin)
+ {
+ dmin = dist;
+ sep = (b3Vector3&)crossje;
+ }
+ }
+ }
+
+ }
+
+
+ if((dot3F4(-deltaC2,(float4&)sep))>0.0f)
+ sep = -sep;
+
+ return true;
+}
+
+
+bool findSeparatingAxisEdgeEdge( __global const b3ConvexPolyhedronData* hullA, __global const b3ConvexPolyhedronData* hullB,
+ const b3Float4& posA1,
+ const b3Quat& ornA,
+ const b3Float4& posB1,
+ const b3Quat& ornB,
+ const b3Float4& DeltaC2,
+ __global const b3AlignedObjectArray<float4>& vertices,
+ __global const b3AlignedObjectArray<float4>& uniqueEdges,
+ __global const b3AlignedObjectArray<b3GpuFace>& faces,
+ __global const b3AlignedObjectArray<int>& indices,
+ float4* sep,
+ float* dmin)
+{
+// int i = get_global_id(0);
+
+ float4 posA = posA1;
+ posA.w = 0.f;
+ float4 posB = posB1;
+ posB.w = 0.f;
+
+ //int curPlaneTests=0;
+
+ int curEdgeEdge = 0;
+ // Test edges
+ for(int e0=0;e0<hullA->m_numUniqueEdges;e0++)
+ {
+ const float4 edge0 = uniqueEdges[hullA->m_uniqueEdgesOffset+e0];
+ float4 edge0World = b3QuatRotate(ornA,edge0);
+
+ for(int e1=0;e1<hullB->m_numUniqueEdges;e1++)
+ {
+ const float4 edge1 = uniqueEdges[hullB->m_uniqueEdgesOffset+e1];
+ float4 edge1World = b3QuatRotate(ornB,edge1);
+
+
+ float4 crossje = cross3(edge0World,edge1World);
+
+ curEdgeEdge++;
+ if(!IsAlmostZero(crossje))
+ {
+ crossje = normalize3(crossje);
+ if (dot3F4(DeltaC2,crossje)<0)
+ crossje*=-1.f;
+
+ float dist;
+ bool result = true;
+ {
+ float Min0,Max0;
+ float Min1,Max1;
+ project(*hullA,posA,ornA,crossje,vertices, Min0, Max0);
+ project(*hullB,posB,ornB,crossje,vertices, Min1, Max1);
+
+ if(Max0<Min1 || Max1<Min0)
+ result = false;
+
+ float d0 = Max0 - Min1;
+ float d1 = Max1 - Min0;
+ dist = d0<d1 ? d0:d1;
+ result = true;
+
+ }
+
+
+ if(dist<*dmin)
+ {
+ *dmin = dist;
+ *sep = crossje;
+ }
+ }
+ }
+
+ }
+
+
+ if((dot3F4(-DeltaC2,*sep))>0.0f)
+ {
+ *sep = -(*sep);
+ }
+ return true;
+}
+
+
+__inline float4 lerp3(const float4& a,const float4& b, float t)
+{
+ return b3MakeVector3( a.x + (b.x - a.x) * t,
+ a.y + (b.y - a.y) * t,
+ a.z + (b.z - a.z) * t,
+ 0.f);
+}
+
+
+// Clips a face to the back of a plane, return the number of vertices out, stored in ppVtxOut
+int clipFace(const float4* pVtxIn, int numVertsIn, float4& planeNormalWS,float planeEqWS, float4* ppVtxOut)
+{
+
+ int ve;
+ float ds, de;
+ int numVertsOut = 0;
+ if (numVertsIn < 2)
+ return 0;
+
+ float4 firstVertex=pVtxIn[numVertsIn-1];
+ float4 endVertex = pVtxIn[0];
+
+ ds = dot3F4(planeNormalWS,firstVertex)+planeEqWS;
+
+ for (ve = 0; ve < numVertsIn; ve++)
+ {
+ endVertex=pVtxIn[ve];
+
+ de = dot3F4(planeNormalWS,endVertex)+planeEqWS;
+
+ if (ds<0)
+ {
+ if (de<0)
+ {
+ // Start < 0, end < 0, so output endVertex
+ ppVtxOut[numVertsOut++] = endVertex;
+ }
+ else
+ {
+ // Start < 0, end >= 0, so output intersection
+ ppVtxOut[numVertsOut++] = lerp3(firstVertex, endVertex,(ds * 1.f/(ds - de)) );
+ }
+ }
+ else
+ {
+ if (de<0)
+ {
+ // Start >= 0, end < 0 so output intersection and end
+ ppVtxOut[numVertsOut++] = lerp3(firstVertex, endVertex,(ds * 1.f/(ds - de)) );
+ ppVtxOut[numVertsOut++] = endVertex;
+ }
+ }
+ firstVertex = endVertex;
+ ds = de;
+ }
+ return numVertsOut;
+}
+
+
+int clipFaceAgainstHull(const float4& separatingNormal, const b3ConvexPolyhedronData* hullA,
+ const float4& posA, const b3Quaternion& ornA, float4* worldVertsB1, int numWorldVertsB1,
+ float4* worldVertsB2, int capacityWorldVertsB2,
+ const float minDist, float maxDist,
+ const b3AlignedObjectArray<float4>& verticesA, const b3AlignedObjectArray<b3GpuFace>& facesA, const b3AlignedObjectArray<int>& indicesA,
+ //const float4* verticesB, const b3GpuFace* facesB, const int* indicesB,
+ float4* contactsOut,
+ int contactCapacity)
+{
+ int numContactsOut = 0;
+
+ float4* pVtxIn = worldVertsB1;
+ float4* pVtxOut = worldVertsB2;
+
+ int numVertsIn = numWorldVertsB1;
+ int numVertsOut = 0;
+
+ int closestFaceA=-1;
+ {
+ float dmin = FLT_MAX;
+ for(int face=0;face<hullA->m_numFaces;face++)
+ {
+ const float4 Normal = b3MakeVector3(
+ facesA[hullA->m_faceOffset+face].m_plane.x,
+ facesA[hullA->m_faceOffset+face].m_plane.y,
+ facesA[hullA->m_faceOffset+face].m_plane.z,0.f);
+ const float4 faceANormalWS = b3QuatRotate(ornA,Normal);
+
+ float d = dot3F4(faceANormalWS,separatingNormal);
+ if (d < dmin)
+ {
+ dmin = d;
+ closestFaceA = face;
+ }
+ }
+ }
+ if (closestFaceA<0)
+ return numContactsOut;
+
+ b3GpuFace polyA = facesA[hullA->m_faceOffset+closestFaceA];
+
+ // clip polygon to back of planes of all faces of hull A that are adjacent to witness face
+// int numContacts = numWorldVertsB1;
+ int numVerticesA = polyA.m_numIndices;
+ for(int e0=0;e0<numVerticesA;e0++)
+ {
+ const float4 a = verticesA[hullA->m_vertexOffset+indicesA[polyA.m_indexOffset+e0]];
+ const float4 b = verticesA[hullA->m_vertexOffset+indicesA[polyA.m_indexOffset+((e0+1)%numVerticesA)]];
+ const float4 edge0 = a - b;
+ const float4 WorldEdge0 = b3QuatRotate(ornA,edge0);
+ float4 planeNormalA = make_float4(polyA.m_plane.x,polyA.m_plane.y,polyA.m_plane.z,0.f);
+ float4 worldPlaneAnormal1 = b3QuatRotate(ornA,planeNormalA);
+
+ float4 planeNormalWS1 = -cross3(WorldEdge0,worldPlaneAnormal1);
+ float4 worldA1 = transform(&a,&posA,&ornA);
+ float planeEqWS1 = -dot3F4(worldA1,planeNormalWS1);
+
+ float4 planeNormalWS = planeNormalWS1;
+ float planeEqWS=planeEqWS1;
+
+ //clip face
+ //clipFace(*pVtxIn, *pVtxOut,planeNormalWS,planeEqWS);
+ numVertsOut = clipFace(pVtxIn, numVertsIn, planeNormalWS,planeEqWS, pVtxOut);
+
+ //btSwap(pVtxIn,pVtxOut);
+ float4* tmp = pVtxOut;
+ pVtxOut = pVtxIn;
+ pVtxIn = tmp;
+ numVertsIn = numVertsOut;
+ numVertsOut = 0;
+ }
+
+
+ // only keep points that are behind the witness face
+ {
+ float4 localPlaneNormal = make_float4(polyA.m_plane.x,polyA.m_plane.y,polyA.m_plane.z,0.f);
+ float localPlaneEq = polyA.m_plane.w;
+ float4 planeNormalWS = b3QuatRotate(ornA,localPlaneNormal);
+ float planeEqWS=localPlaneEq-dot3F4(planeNormalWS,posA);
+ for (int i=0;i<numVertsIn;i++)
+ {
+ float depth = dot3F4(planeNormalWS,pVtxIn[i])+planeEqWS;
+ if (depth <=minDist)
+ {
+ depth = minDist;
+ }
+ if (numContactsOut<contactCapacity)
+ {
+ if (depth <=maxDist)
+ {
+ float4 pointInWorld = pVtxIn[i];
+ //resultOut.addContactPoint(separatingNormal,point,depth);
+ contactsOut[numContactsOut++] = b3MakeVector3(pointInWorld.x,pointInWorld.y,pointInWorld.z,depth);
+ //printf("depth=%f\n",depth);
+ }
+ } else
+ {
+ b3Error("exceeding contact capacity (%d,%df)\n", numContactsOut,contactCapacity);
+ }
+ }
+ }
+
+ return numContactsOut;
+}
+
+
+
+static int clipHullAgainstHull(const float4& separatingNormal,
+ const b3ConvexPolyhedronData& hullA, const b3ConvexPolyhedronData& hullB,
+ const float4& posA, const b3Quaternion& ornA,const float4& posB, const b3Quaternion& ornB,
+ float4* worldVertsB1, float4* worldVertsB2, int capacityWorldVerts,
+ const float minDist, float maxDist,
+ const b3AlignedObjectArray<float4>& verticesA, const b3AlignedObjectArray<b3GpuFace>& facesA, const b3AlignedObjectArray<int>& indicesA,
+ const b3AlignedObjectArray<float4>& verticesB, const b3AlignedObjectArray<b3GpuFace>& facesB, const b3AlignedObjectArray<int>& indicesB,
+
+ float4* contactsOut,
+ int contactCapacity)
+{
+ int numContactsOut = 0;
+ int numWorldVertsB1= 0;
+
+ B3_PROFILE("clipHullAgainstHull");
+
+// float curMaxDist=maxDist;
+ int closestFaceB=-1;
+ float dmax = -FLT_MAX;
+
+ {
+ //B3_PROFILE("closestFaceB");
+ if (hullB.m_numFaces!=1)
+ {
+ //printf("wtf\n");
+ }
+ static bool once = true;
+ //printf("separatingNormal=%f,%f,%f\n",separatingNormal.x,separatingNormal.y,separatingNormal.z);
+
+ for(int face=0;face<hullB.m_numFaces;face++)
+ {
+#ifdef BT_DEBUG_SAT_FACE
+ if (once)
+ printf("face %d\n",face);
+ const b3GpuFace* faceB = &facesB[hullB.m_faceOffset+face];
+ if (once)
+ {
+ for (int i=0;i<faceB->m_numIndices;i++)
+ {
+ float4 vert = verticesB[hullB.m_vertexOffset+indicesB[faceB->m_indexOffset+i]];
+ printf("vert[%d] = %f,%f,%f\n",i,vert.x,vert.y,vert.z);
+ }
+ }
+#endif //BT_DEBUG_SAT_FACE
+ //if (facesB[hullB.m_faceOffset+face].m_numIndices>2)
+ {
+ const float4 Normal = b3MakeVector3(facesB[hullB.m_faceOffset+face].m_plane.x,
+ facesB[hullB.m_faceOffset+face].m_plane.y, facesB[hullB.m_faceOffset+face].m_plane.z,0.f);
+ const float4 WorldNormal = b3QuatRotate(ornB, Normal);
+#ifdef BT_DEBUG_SAT_FACE
+ if (once)
+ printf("faceNormal = %f,%f,%f\n",Normal.x,Normal.y,Normal.z);
+#endif
+ float d = dot3F4(WorldNormal,separatingNormal);
+ if (d > dmax)
+ {
+ dmax = d;
+ closestFaceB = face;
+ }
+ }
+ }
+ once = false;
+ }
+
+
+ b3Assert(closestFaceB>=0);
+ {
+ //B3_PROFILE("worldVertsB1");
+ const b3GpuFace& polyB = facesB[hullB.m_faceOffset+closestFaceB];
+ const int numVertices = polyB.m_numIndices;
+ for(int e0=0;e0<numVertices;e0++)
+ {
+ const float4& b = verticesB[hullB.m_vertexOffset+indicesB[polyB.m_indexOffset+e0]];
+ worldVertsB1[numWorldVertsB1++] = transform(&b,&posB,&ornB);
+ }
+ }
+
+ if (closestFaceB>=0)
+ {
+ //B3_PROFILE("clipFaceAgainstHull");
+ numContactsOut = clipFaceAgainstHull((float4&)separatingNormal, &hullA,
+ posA,ornA,
+ worldVertsB1,numWorldVertsB1,worldVertsB2,capacityWorldVerts, minDist, maxDist,
+ verticesA, facesA, indicesA,
+ contactsOut,contactCapacity);
+ }
+
+ return numContactsOut;
+}
+
+
+
+
+
+
+#define PARALLEL_SUM(v, n) for(int j=1; j<n; j++) v[0] += v[j];
+#define PARALLEL_DO(execution, n) for(int ie=0; ie<n; ie++){execution;}
+#define REDUCE_MAX(v, n) {int i=0;\
+for(int offset=0; offset<n; offset++) v[i] = (v[i].y > v[i+offset].y)? v[i]: v[i+offset]; }
+#define REDUCE_MIN(v, n) {int i=0;\
+for(int offset=0; offset<n; offset++) v[i] = (v[i].y < v[i+offset].y)? v[i]: v[i+offset]; }
+
+int extractManifold(const float4* p, int nPoints, const float4& nearNormal, b3Int4* contactIdx)
+{
+ if( nPoints == 0 )
+ return 0;
+
+ if (nPoints <=4)
+ return nPoints;
+
+
+ if (nPoints >64)
+ nPoints = 64;
+
+ float4 center = make_float4(0,0,0,0);
+ {
+
+ for (int i=0;i<nPoints;i++)
+ center += p[i];
+ center /= (float)nPoints;
+ }
+
+
+
+ // sample 4 directions
+
+ float4 aVector = p[0] - center;
+ float4 u = cross3( nearNormal, aVector );
+ float4 v = cross3( nearNormal, u );
+ u = normalize3( u );
+ v = normalize3( v );
+
+
+ //keep point with deepest penetration
+ float minW= FLT_MAX;
+
+ int minIndex=-1;
+
+ float4 maxDots;
+ maxDots.x = FLT_MIN;
+ maxDots.y = FLT_MIN;
+ maxDots.z = FLT_MIN;
+ maxDots.w = FLT_MIN;
+
+ // idx, distance
+ for(int ie = 0; ie<nPoints; ie++ )
+ {
+ if (p[ie].w<minW)
+ {
+ minW = p[ie].w;
+ minIndex=ie;
+ }
+ float f;
+ float4 r = p[ie]-center;
+ f = dot3F4( u, r );
+ if (f<maxDots.x)
+ {
+ maxDots.x = f;
+ contactIdx[0].x = ie;
+ }
+
+ f = dot3F4( -u, r );
+ if (f<maxDots.y)
+ {
+ maxDots.y = f;
+ contactIdx[0].y = ie;
+ }
+
+
+ f = dot3F4( v, r );
+ if (f<maxDots.z)
+ {
+ maxDots.z = f;
+ contactIdx[0].z = ie;
+ }
+
+ f = dot3F4( -v, r );
+ if (f<maxDots.w)
+ {
+ maxDots.w = f;
+ contactIdx[0].w = ie;
+ }
+
+ }
+
+ if (contactIdx[0].x != minIndex && contactIdx[0].y != minIndex && contactIdx[0].z != minIndex && contactIdx[0].w != minIndex)
+ {
+ //replace the first contact with minimum (todo: replace contact with least penetration)
+ contactIdx[0].x = minIndex;
+ }
+
+ return 4;
+
+}
+
+
+
+
+int clipHullHullSingle(
+ int bodyIndexA, int bodyIndexB,
+ const float4& posA,
+ const b3Quaternion& ornA,
+ const float4& posB,
+ const b3Quaternion& ornB,
+
+ int collidableIndexA, int collidableIndexB,
+
+ const b3AlignedObjectArray<b3RigidBodyData>* bodyBuf,
+ b3AlignedObjectArray<b3Contact4>* globalContactOut,
+ int& nContacts,
+
+ const b3AlignedObjectArray<b3ConvexPolyhedronData>& hostConvexDataA,
+ const b3AlignedObjectArray<b3ConvexPolyhedronData>& hostConvexDataB,
+
+ const b3AlignedObjectArray<b3Vector3>& verticesA,
+ const b3AlignedObjectArray<b3Vector3>& uniqueEdgesA,
+ const b3AlignedObjectArray<b3GpuFace>& facesA,
+ const b3AlignedObjectArray<int>& indicesA,
+
+ const b3AlignedObjectArray<b3Vector3>& verticesB,
+ const b3AlignedObjectArray<b3Vector3>& uniqueEdgesB,
+ const b3AlignedObjectArray<b3GpuFace>& facesB,
+ const b3AlignedObjectArray<int>& indicesB,
+
+ const b3AlignedObjectArray<b3Collidable>& hostCollidablesA,
+ const b3AlignedObjectArray<b3Collidable>& hostCollidablesB,
+ const b3Vector3& sepNormalWorldSpace,
+ int maxContactCapacity )
+{
+ int contactIndex = -1;
+ b3ConvexPolyhedronData hullA, hullB;
+
+ b3Collidable colA = hostCollidablesA[collidableIndexA];
+ hullA = hostConvexDataA[colA.m_shapeIndex];
+ //printf("numvertsA = %d\n",hullA.m_numVertices);
+
+
+ b3Collidable colB = hostCollidablesB[collidableIndexB];
+ hullB = hostConvexDataB[colB.m_shapeIndex];
+ //printf("numvertsB = %d\n",hullB.m_numVertices);
+
+
+ float4 contactsOut[MAX_VERTS];
+ int localContactCapacity = MAX_VERTS;
+
+#ifdef _WIN32
+ b3Assert(_finite(bodyBuf->at(bodyIndexA).m_pos.x));
+ b3Assert(_finite(bodyBuf->at(bodyIndexB).m_pos.x));
+#endif
+
+
+ {
+
+ float4 worldVertsB1[MAX_VERTS];
+ float4 worldVertsB2[MAX_VERTS];
+ int capacityWorldVerts = MAX_VERTS;
+
+ float4 hostNormal = make_float4(sepNormalWorldSpace.x,sepNormalWorldSpace.y,sepNormalWorldSpace.z,0.f);
+ int shapeA = hostCollidablesA[collidableIndexA].m_shapeIndex;
+ int shapeB = hostCollidablesB[collidableIndexB].m_shapeIndex;
+
+ b3Scalar minDist = -1;
+ b3Scalar maxDist = 0.;
+
+
+
+ b3Transform trA,trB;
+ {
+ //B3_PROFILE("transform computation");
+ //trA.setIdentity();
+ trA.setOrigin(b3MakeVector3(posA.x,posA.y,posA.z));
+ trA.setRotation(b3Quaternion(ornA.x,ornA.y,ornA.z,ornA.w));
+
+ //trB.setIdentity();
+ trB.setOrigin(b3MakeVector3(posB.x,posB.y,posB.z));
+ trB.setRotation(b3Quaternion(ornB.x,ornB.y,ornB.z,ornB.w));
+ }
+
+ b3Quaternion trAorn = trA.getRotation();
+ b3Quaternion trBorn = trB.getRotation();
+
+ int numContactsOut = clipHullAgainstHull(hostNormal,
+ hostConvexDataA.at(shapeA),
+ hostConvexDataB.at(shapeB),
+ (float4&)trA.getOrigin(), (b3Quaternion&)trAorn,
+ (float4&)trB.getOrigin(), (b3Quaternion&)trBorn,
+ worldVertsB1,worldVertsB2,capacityWorldVerts,
+ minDist, maxDist,
+ verticesA, facesA,indicesA,
+ verticesB, facesB,indicesB,
+
+ contactsOut,localContactCapacity);
+
+ if (numContactsOut>0)
+ {
+ B3_PROFILE("overlap");
+
+ float4 normalOnSurfaceB = (float4&)hostNormal;
+
+ b3Int4 contactIdx;
+ contactIdx.x = 0;
+ contactIdx.y = 1;
+ contactIdx.z = 2;
+ contactIdx.w = 3;
+
+ int numPoints = 0;
+
+ {
+ // B3_PROFILE("extractManifold");
+ numPoints = extractManifold(contactsOut, numContactsOut, normalOnSurfaceB, &contactIdx);
+ }
+
+ b3Assert(numPoints);
+
+ if (nContacts<maxContactCapacity)
+ {
+ contactIndex = nContacts;
+ globalContactOut->expand();
+ b3Contact4& contact = globalContactOut->at(nContacts);
+ contact.m_batchIdx = 0;//i;
+ contact.m_bodyAPtrAndSignBit = (bodyBuf->at(bodyIndexA).m_invMass==0)? -bodyIndexA:bodyIndexA;
+ contact.m_bodyBPtrAndSignBit = (bodyBuf->at(bodyIndexB).m_invMass==0)? -bodyIndexB:bodyIndexB;
+
+ contact.m_frictionCoeffCmp = 45874;
+ contact.m_restituitionCoeffCmp = 0;
+
+ // float distance = 0.f;
+ for (int p=0;p<numPoints;p++)
+ {
+ contact.m_worldPosB[p] = contactsOut[contactIdx.s[p]];//check if it is actually on B
+ contact.m_worldNormalOnB = normalOnSurfaceB;
+ }
+ //printf("bodyIndexA %d,bodyIndexB %d,normal=%f,%f,%f numPoints %d\n",bodyIndexA,bodyIndexB,normalOnSurfaceB.x,normalOnSurfaceB.y,normalOnSurfaceB.z,numPoints);
+ contact.m_worldNormalOnB.w = (b3Scalar)numPoints;
+ nContacts++;
+ } else
+ {
+ b3Error("Error: exceeding contact capacity (%d/%d)\n", nContacts,maxContactCapacity);
+ }
+ }
+ }
+ return contactIndex;
+}
+
+
+
+
+
+void computeContactPlaneConvex(int pairIndex,
+ int bodyIndexA, int bodyIndexB,
+ int collidableIndexA, int collidableIndexB,
+ const b3RigidBodyData* rigidBodies,
+ const b3Collidable* collidables,
+ const b3ConvexPolyhedronData* convexShapes,
+ const b3Vector3* convexVertices,
+ const int* convexIndices,
+ const b3GpuFace* faces,
+ b3Contact4* globalContactsOut,
+ int& nGlobalContactsOut,
+ int maxContactCapacity)
+{
+
+ int shapeIndex = collidables[collidableIndexB].m_shapeIndex;
+ const b3ConvexPolyhedronData* hullB = &convexShapes[shapeIndex];
+
+ b3Vector3 posB = rigidBodies[bodyIndexB].m_pos;
+ b3Quaternion ornB = rigidBodies[bodyIndexB].m_quat;
+ b3Vector3 posA = rigidBodies[bodyIndexA].m_pos;
+ b3Quaternion ornA = rigidBodies[bodyIndexA].m_quat;
+
+// int numContactsOut = 0;
+// int numWorldVertsB1= 0;
+
+ b3Vector3 planeEq = faces[collidables[collidableIndexA].m_shapeIndex].m_plane;
+ b3Vector3 planeNormal=b3MakeVector3(planeEq.x,planeEq.y,planeEq.z);
+ b3Vector3 planeNormalWorld = b3QuatRotate(ornA,planeNormal);
+ float planeConstant = planeEq.w;
+ b3Transform convexWorldTransform;
+ convexWorldTransform.setIdentity();
+ convexWorldTransform.setOrigin(posB);
+ convexWorldTransform.setRotation(ornB);
+ b3Transform planeTransform;
+ planeTransform.setIdentity();
+ planeTransform.setOrigin(posA);
+ planeTransform.setRotation(ornA);
+
+ b3Transform planeInConvex;
+ planeInConvex= convexWorldTransform.inverse() * planeTransform;
+ b3Transform convexInPlane;
+ convexInPlane = planeTransform.inverse() * convexWorldTransform;
+
+ b3Vector3 planeNormalInConvex = planeInConvex.getBasis()*-planeNormal;
+ float maxDot = -1e30;
+ int hitVertex=-1;
+ b3Vector3 hitVtx;
+
+#define MAX_PLANE_CONVEX_POINTS 64
+
+ b3Vector3 contactPoints[MAX_PLANE_CONVEX_POINTS];
+ int numPoints = 0;
+
+ b3Int4 contactIdx;
+ contactIdx.s[0] = 0;
+ contactIdx.s[1] = 1;
+ contactIdx.s[2] = 2;
+ contactIdx.s[3] = 3;
+
+ for (int i=0;i<hullB->m_numVertices;i++)
+ {
+ b3Vector3 vtx = convexVertices[hullB->m_vertexOffset+i];
+ float curDot = vtx.dot(planeNormalInConvex);
+
+
+ if (curDot>maxDot)
+ {
+ hitVertex=i;
+ maxDot=curDot;
+ hitVtx = vtx;
+ //make sure the deepest points is always included
+ if (numPoints==MAX_PLANE_CONVEX_POINTS)
+ numPoints--;
+ }
+
+ if (numPoints<MAX_PLANE_CONVEX_POINTS)
+ {
+ b3Vector3 vtxWorld = convexWorldTransform*vtx;
+ b3Vector3 vtxInPlane = planeTransform.inverse()*vtxWorld;
+ float dist = planeNormal.dot(vtxInPlane)-planeConstant;
+ if (dist<0.f)
+ {
+ vtxWorld.w = dist;
+ contactPoints[numPoints] = vtxWorld;
+ numPoints++;
+ }
+ }
+
+ }
+
+ int numReducedPoints = 0;
+
+ numReducedPoints = numPoints;
+
+ if (numPoints>4)
+ {
+ numReducedPoints = extractManifoldSequentialGlobal( contactPoints, numPoints, planeNormalInConvex, &contactIdx);
+ }
+ int dstIdx;
+// dstIdx = nGlobalContactsOut++;//AppendInc( nGlobalContactsOut, dstIdx );
+
+ if (numReducedPoints>0)
+ {
+ if (nGlobalContactsOut < maxContactCapacity)
+ {
+ dstIdx=nGlobalContactsOut;
+ nGlobalContactsOut++;
+
+ b3Contact4* c = &globalContactsOut[dstIdx];
+ c->m_worldNormalOnB = -planeNormalWorld;
+ c->setFrictionCoeff(0.7);
+ c->setRestituitionCoeff(0.f);
+
+ c->m_batchIdx = pairIndex;
+ c->m_bodyAPtrAndSignBit = rigidBodies[bodyIndexA].m_invMass==0?-bodyIndexA:bodyIndexA;
+ c->m_bodyBPtrAndSignBit = rigidBodies[bodyIndexB].m_invMass==0?-bodyIndexB:bodyIndexB;
+ for (int i=0;i<numReducedPoints;i++)
+ {
+ b3Vector3 pOnB1 = contactPoints[contactIdx.s[i]];
+ c->m_worldPosB[i] = pOnB1;
+ }
+ c->m_worldNormalOnB.w = (b3Scalar)numReducedPoints;
+ }//if (dstIdx < numPairs)
+ }
+
+
+
+// printf("computeContactPlaneConvex\n");
+}
+
+
+
+B3_FORCE_INLINE b3Vector3 MyUnQuantize(const unsigned short* vecIn, const b3Vector3& quantization, const b3Vector3& bvhAabbMin)
+ {
+ b3Vector3 vecOut;
+ vecOut.setValue(
+ (b3Scalar)(vecIn[0]) / (quantization.x),
+ (b3Scalar)(vecIn[1]) / (quantization.y),
+ (b3Scalar)(vecIn[2]) / (quantization.z));
+ vecOut += bvhAabbMin;
+ return vecOut;
+ }
+
+void traverseTreeTree()
+{
+
+}
+
+#include "Bullet3Common/shared/b3Mat3x3.h"
+
+int numAabbChecks = 0;
+int maxNumAabbChecks = 0;
+int maxDepth = 0;
+
+// work-in-progress
+__kernel void findCompoundPairsKernel(
+ int pairIndex,
+ int bodyIndexA,
+ int bodyIndexB,
+ int collidableIndexA,
+ int collidableIndexB,
+ __global const b3RigidBodyData* rigidBodies,
+ __global const b3Collidable* collidables,
+ __global const b3ConvexPolyhedronData* convexShapes,
+ __global const b3AlignedObjectArray<b3Float4>& vertices,
+ __global const b3AlignedObjectArray<b3Aabb>& aabbsWorldSpace,
+ __global const b3AlignedObjectArray<b3Aabb>& aabbsLocalSpace,
+ __global const b3GpuChildShape* gpuChildShapes,
+ __global b3Int4* gpuCompoundPairsOut,
+ __global int* numCompoundPairsOut,
+ int maxNumCompoundPairsCapacity,
+ b3AlignedObjectArray<b3QuantizedBvhNode>& treeNodesCPU,
+ b3AlignedObjectArray<b3BvhSubtreeInfo>& subTreesCPU,
+ b3AlignedObjectArray<b3BvhInfo>& bvhInfoCPU
+ )
+{
+ numAabbChecks=0;
+ maxNumAabbChecks=0;
+// int i = pairIndex;
+ {
+
+
+ int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
+ int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
+
+
+ //once the broadphase avoids static-static pairs, we can remove this test
+ if ((rigidBodies[bodyIndexA].m_invMass==0) &&(rigidBodies[bodyIndexB].m_invMass==0))
+ {
+ return;
+ }
+
+ if ((collidables[collidableIndexA].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS) &&(collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS))
+ {
+ int bvhA = collidables[collidableIndexA].m_compoundBvhIndex;
+ int bvhB = collidables[collidableIndexB].m_compoundBvhIndex;
+ int numSubTreesA = bvhInfoCPU[bvhA].m_numSubTrees;
+ int subTreesOffsetA = bvhInfoCPU[bvhA].m_subTreeOffset;
+ int subTreesOffsetB = bvhInfoCPU[bvhB].m_subTreeOffset;
+
+
+ int numSubTreesB = bvhInfoCPU[bvhB].m_numSubTrees;
+
+ float4 posA = rigidBodies[bodyIndexA].m_pos;
+ b3Quat ornA = rigidBodies[bodyIndexA].m_quat;
+
+ b3Transform transA;
+ transA.setIdentity();
+ transA.setOrigin(posA);
+ transA.setRotation(ornA);
+
+ b3Quat ornB = rigidBodies[bodyIndexB].m_quat;
+ float4 posB = rigidBodies[bodyIndexB].m_pos;
+
+ b3Transform transB;
+ transB.setIdentity();
+ transB.setOrigin(posB);
+ transB.setRotation(ornB);
+
+
+
+ for (int p=0;p<numSubTreesA;p++)
+ {
+ b3BvhSubtreeInfo subtreeA = subTreesCPU[subTreesOffsetA+p];
+ //bvhInfoCPU[bvhA].m_quantization
+ b3Vector3 treeAminLocal = MyUnQuantize(subtreeA.m_quantizedAabbMin,bvhInfoCPU[bvhA].m_quantization,bvhInfoCPU[bvhA].m_aabbMin);
+ b3Vector3 treeAmaxLocal = MyUnQuantize(subtreeA.m_quantizedAabbMax,bvhInfoCPU[bvhA].m_quantization,bvhInfoCPU[bvhA].m_aabbMin);
+
+ b3Vector3 aabbAMinOut,aabbAMaxOut;
+ float margin=0.f;
+ b3TransformAabb2(treeAminLocal,treeAmaxLocal, margin,transA.getOrigin(),transA.getRotation(),&aabbAMinOut,&aabbAMaxOut);
+
+ for (int q=0;q<numSubTreesB;q++)
+ {
+ b3BvhSubtreeInfo subtreeB = subTreesCPU[subTreesOffsetB+q];
+
+ b3Vector3 treeBminLocal = MyUnQuantize(subtreeB.m_quantizedAabbMin,bvhInfoCPU[bvhB].m_quantization,bvhInfoCPU[bvhB].m_aabbMin);
+ b3Vector3 treeBmaxLocal = MyUnQuantize(subtreeB.m_quantizedAabbMax,bvhInfoCPU[bvhB].m_quantization,bvhInfoCPU[bvhB].m_aabbMin);
+
+ b3Vector3 aabbBMinOut,aabbBMaxOut;
+ float margin=0.f;
+ b3TransformAabb2(treeBminLocal,treeBmaxLocal, margin,transB.getOrigin(),transB.getRotation(),&aabbBMinOut,&aabbBMaxOut);
+
+
+ numAabbChecks=0;
+ bool aabbOverlap = b3TestAabbAgainstAabb(aabbAMinOut,aabbAMaxOut,aabbBMinOut,aabbBMaxOut);
+ if (aabbOverlap)
+ {
+
+ int startNodeIndexA = subtreeA.m_rootNodeIndex+bvhInfoCPU[bvhA].m_nodeOffset;
+ // int endNodeIndexA = startNodeIndexA+subtreeA.m_subtreeSize;
+
+ int startNodeIndexB = subtreeB.m_rootNodeIndex+bvhInfoCPU[bvhB].m_nodeOffset;
+ // int endNodeIndexB = startNodeIndexB+subtreeB.m_subtreeSize;
+
+ b3AlignedObjectArray<b3Int2> nodeStack;
+ b3Int2 node0;
+ node0.x = startNodeIndexA;
+ node0.y = startNodeIndexB;
+
+ int maxStackDepth = 1024;
+ nodeStack.resize(maxStackDepth);
+ int depth=0;
+ nodeStack[depth++]=node0;
+
+ do
+ {
+ if (depth > maxDepth)
+ {
+ maxDepth=depth;
+ printf("maxDepth=%d\n",maxDepth);
+ }
+ b3Int2 node = nodeStack[--depth];
+
+ b3Vector3 aMinLocal = MyUnQuantize(treeNodesCPU[node.x].m_quantizedAabbMin,bvhInfoCPU[bvhA].m_quantization,bvhInfoCPU[bvhA].m_aabbMin);
+ b3Vector3 aMaxLocal = MyUnQuantize(treeNodesCPU[node.x].m_quantizedAabbMax,bvhInfoCPU[bvhA].m_quantization,bvhInfoCPU[bvhA].m_aabbMin);
+
+ b3Vector3 bMinLocal = MyUnQuantize(treeNodesCPU[node.y].m_quantizedAabbMin,bvhInfoCPU[bvhB].m_quantization,bvhInfoCPU[bvhB].m_aabbMin);
+ b3Vector3 bMaxLocal = MyUnQuantize(treeNodesCPU[node.y].m_quantizedAabbMax,bvhInfoCPU[bvhB].m_quantization,bvhInfoCPU[bvhB].m_aabbMin);
+
+ float margin=0.f;
+ b3Vector3 aabbAMinOut,aabbAMaxOut;
+ b3TransformAabb2(aMinLocal,aMaxLocal, margin,transA.getOrigin(),transA.getRotation(),&aabbAMinOut,&aabbAMaxOut);
+
+ b3Vector3 aabbBMinOut,aabbBMaxOut;
+ b3TransformAabb2(bMinLocal,bMaxLocal, margin,transB.getOrigin(),transB.getRotation(),&aabbBMinOut,&aabbBMaxOut);
+
+ numAabbChecks++;
+ bool nodeOverlap = b3TestAabbAgainstAabb(aabbAMinOut,aabbAMaxOut,aabbBMinOut,aabbBMaxOut);
+ if (nodeOverlap)
+ {
+ bool isLeafA = treeNodesCPU[node.x].isLeafNode();
+ bool isLeafB = treeNodesCPU[node.y].isLeafNode();
+ bool isInternalA = !isLeafA;
+ bool isInternalB = !isLeafB;
+
+ //fail, even though it might hit two leaf nodes
+ if (depth+4>maxStackDepth && !(isLeafA && isLeafB))
+ {
+ b3Error("Error: traversal exceeded maxStackDepth\n");
+ continue;
+ }
+
+ if(isInternalA)
+ {
+ int nodeAleftChild = node.x+1;
+ bool isNodeALeftChildLeaf = treeNodesCPU[node.x+1].isLeafNode();
+ int nodeArightChild = isNodeALeftChildLeaf? node.x+2 : node.x+1 + treeNodesCPU[node.x+1].getEscapeIndex();
+
+ if(isInternalB)
+ {
+ int nodeBleftChild = node.y+1;
+ bool isNodeBLeftChildLeaf = treeNodesCPU[node.y+1].isLeafNode();
+ int nodeBrightChild = isNodeBLeftChildLeaf? node.y+2 : node.y+1 + treeNodesCPU[node.y+1].getEscapeIndex();
+
+ nodeStack[depth++] = b3MakeInt2(nodeAleftChild, nodeBleftChild);
+ nodeStack[depth++] = b3MakeInt2(nodeArightChild, nodeBleftChild);
+ nodeStack[depth++] = b3MakeInt2(nodeAleftChild, nodeBrightChild);
+ nodeStack[depth++] = b3MakeInt2(nodeArightChild, nodeBrightChild);
+ }
+ else
+ {
+ nodeStack[depth++] = b3MakeInt2(nodeAleftChild,node.y);
+ nodeStack[depth++] = b3MakeInt2(nodeArightChild,node.y);
+ }
+ }
+ else
+ {
+ if(isInternalB)
+ {
+ int nodeBleftChild = node.y+1;
+ bool isNodeBLeftChildLeaf = treeNodesCPU[node.y+1].isLeafNode();
+ int nodeBrightChild = isNodeBLeftChildLeaf? node.y+2 : node.y+1 + treeNodesCPU[node.y+1].getEscapeIndex();
+ nodeStack[depth++] = b3MakeInt2(node.x,nodeBleftChild);
+ nodeStack[depth++] = b3MakeInt2(node.x,nodeBrightChild);
+ }
+ else
+ {
+ int compoundPairIdx = b3AtomicInc(numCompoundPairsOut);
+ if (compoundPairIdx<maxNumCompoundPairsCapacity)
+ {
+ int childShapeIndexA = treeNodesCPU[node.x].getTriangleIndex();
+ int childShapeIndexB = treeNodesCPU[node.y].getTriangleIndex();
+ gpuCompoundPairsOut[compoundPairIdx] = b3MakeInt4(bodyIndexA,bodyIndexB,childShapeIndexA,childShapeIndexB);
+ }
+ }
+ }
+ }
+ } while (depth);
+ maxNumAabbChecks = b3Max(numAabbChecks,maxNumAabbChecks);
+ }
+ }
+ }
+
+ return;
+ }
+
+ if ((collidables[collidableIndexA].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS) ||(collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS))
+ {
+
+ if (collidables[collidableIndexA].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)
+ {
+
+ int numChildrenA = collidables[collidableIndexA].m_numChildShapes;
+ for (int c=0;c<numChildrenA;c++)
+ {
+ int childShapeIndexA = collidables[collidableIndexA].m_shapeIndex+c;
+ int childColIndexA = gpuChildShapes[childShapeIndexA].m_shapeIndex;
+
+ float4 posA = rigidBodies[bodyIndexA].m_pos;
+ b3Quat ornA = rigidBodies[bodyIndexA].m_quat;
+ float4 childPosA = gpuChildShapes[childShapeIndexA].m_childPosition;
+ b3Quat childOrnA = gpuChildShapes[childShapeIndexA].m_childOrientation;
+ float4 newPosA = b3QuatRotate(ornA,childPosA)+posA;
+ b3Quat newOrnA = b3QuatMul(ornA,childOrnA);
+
+
+
+ b3Aabb aabbA = aabbsLocalSpace[childColIndexA];
+
+
+ b3Transform transA;
+ transA.setIdentity();
+ transA.setOrigin(newPosA);
+ transA.setRotation(newOrnA);
+ b3Scalar margin=0.0f;
+
+ b3Vector3 aabbAMinOut,aabbAMaxOut;
+
+ b3TransformAabb2((const b3Float4&)aabbA.m_min,(const b3Float4&)aabbA.m_max, margin,transA.getOrigin(),transA.getRotation(),&aabbAMinOut,&aabbAMaxOut);
+
+ if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)
+ {
+ int numChildrenB = collidables[collidableIndexB].m_numChildShapes;
+ for (int b=0;b<numChildrenB;b++)
+ {
+ int childShapeIndexB = collidables[collidableIndexB].m_shapeIndex+b;
+ int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;
+ b3Quat ornB = rigidBodies[bodyIndexB].m_quat;
+ float4 posB = rigidBodies[bodyIndexB].m_pos;
+ float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;
+ b3Quat childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;
+ float4 newPosB = transform(&childPosB,&posB,&ornB);
+ b3Quat newOrnB = b3QuatMul(ornB,childOrnB);
+
+
+
+ b3Aabb aabbB = aabbsLocalSpace[childColIndexB];
+
+ b3Transform transB;
+ transB.setIdentity();
+ transB.setOrigin(newPosB);
+ transB.setRotation(newOrnB);
+
+ b3Vector3 aabbBMinOut,aabbBMaxOut;
+ b3TransformAabb2((const b3Float4&)aabbB.m_min,(const b3Float4&)aabbB.m_max, margin,transB.getOrigin(),transB.getRotation(),&aabbBMinOut,&aabbBMaxOut);
+
+ numAabbChecks++;
+ bool aabbOverlap = b3TestAabbAgainstAabb(aabbAMinOut,aabbAMaxOut,aabbBMinOut,aabbBMaxOut);
+ if (aabbOverlap)
+ {
+ /*
+ int numFacesA = convexShapes[shapeIndexA].m_numFaces;
+ float dmin = FLT_MAX;
+ float4 posA = newPosA;
+ posA.w = 0.f;
+ float4 posB = newPosB;
+ posB.w = 0.f;
+ float4 c0local = convexShapes[shapeIndexA].m_localCenter;
+ b3Quat ornA = newOrnA;
+ float4 c0 = transform(&c0local, &posA, &ornA);
+ float4 c1local = convexShapes[shapeIndexB].m_localCenter;
+ b3Quat ornB =newOrnB;
+ float4 c1 = transform(&c1local,&posB,&ornB);
+ const float4 DeltaC2 = c0 - c1;
+ */
+ {//
+ int compoundPairIdx = b3AtomicInc(numCompoundPairsOut);
+ if (compoundPairIdx<maxNumCompoundPairsCapacity)
+ {
+ gpuCompoundPairsOut[compoundPairIdx] = b3MakeInt4(bodyIndexA,bodyIndexB,childShapeIndexA,childShapeIndexB);
+ }
+ }//
+ }//fi(1)
+ } //for (int b=0
+ }//if (collidables[collidableIndexB].
+ else//if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)
+ {
+ if (1)
+ {
+ // int numFacesA = convexShapes[shapeIndexA].m_numFaces;
+ // float dmin = FLT_MAX;
+ float4 posA = newPosA;
+ posA.w = 0.f;
+ float4 posB = rigidBodies[bodyIndexB].m_pos;
+ posB.w = 0.f;
+ float4 c0local = convexShapes[shapeIndexA].m_localCenter;
+ b3Quat ornA = newOrnA;
+ float4 c0;
+ c0 = transform(&c0local, &posA, &ornA);
+ float4 c1local = convexShapes[shapeIndexB].m_localCenter;
+ b3Quat ornB = rigidBodies[bodyIndexB].m_quat;
+ float4 c1;
+ c1 = transform(&c1local,&posB,&ornB);
+ // const float4 DeltaC2 = c0 - c1;
+
+ {
+ int compoundPairIdx = b3AtomicInc(numCompoundPairsOut);
+ if (compoundPairIdx<maxNumCompoundPairsCapacity)
+ {
+ gpuCompoundPairsOut[compoundPairIdx] = b3MakeInt4(bodyIndexA,bodyIndexB,childShapeIndexA,-1);
+ }//if (compoundPairIdx<maxNumCompoundPairsCapacity)
+ }//
+ }//fi (1)
+ }//if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)
+ }//for (int b=0;b<numChildrenB;b++)
+ return;
+ }//if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)
+ if ((collidables[collidableIndexA].m_shapeType!=SHAPE_CONCAVE_TRIMESH)
+ && (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS))
+ {
+ int numChildrenB = collidables[collidableIndexB].m_numChildShapes;
+ for (int b=0;b<numChildrenB;b++)
+ {
+ int childShapeIndexB = collidables[collidableIndexB].m_shapeIndex+b;
+ int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;
+ b3Quat ornB = rigidBodies[bodyIndexB].m_quat;
+ float4 posB = rigidBodies[bodyIndexB].m_pos;
+ float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;
+ b3Quat childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;
+ float4 newPosB = b3QuatRotate(ornB,childPosB)+posB;
+ b3Quat newOrnB = b3QuatMul(ornB,childOrnB);
+
+ int shapeIndexB = collidables[childColIndexB].m_shapeIndex;
+
+
+ //////////////////////////////////////
+
+ if (1)
+ {
+ // int numFacesA = convexShapes[shapeIndexA].m_numFaces;
+ // float dmin = FLT_MAX;
+ float4 posA = rigidBodies[bodyIndexA].m_pos;
+ posA.w = 0.f;
+ float4 posB = newPosB;
+ posB.w = 0.f;
+ float4 c0local = convexShapes[shapeIndexA].m_localCenter;
+ b3Quat ornA = rigidBodies[bodyIndexA].m_quat;
+ float4 c0;
+ c0 = transform(&c0local, &posA, &ornA);
+ float4 c1local = convexShapes[shapeIndexB].m_localCenter;
+ b3Quat ornB =newOrnB;
+ float4 c1;
+ c1 = transform(&c1local,&posB,&ornB);
+ // const float4 DeltaC2 = c0 - c1;
+ {//
+ int compoundPairIdx = b3AtomicInc(numCompoundPairsOut);
+ if (compoundPairIdx<maxNumCompoundPairsCapacity)
+ {
+ gpuCompoundPairsOut[compoundPairIdx] = b3MakeInt4(bodyIndexA,bodyIndexB,-1,childShapeIndexB);
+ }//fi (compoundPairIdx<maxNumCompoundPairsCapacity)
+ }//
+ }//fi (1)
+ }//for (int b=0;b<numChildrenB;b++)
+ return;
+ }//if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)
+ return;
+ }//fi ((collidables[collidableIndexA].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS) ||(collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS))
+ }//i<numPairs
+}
+
+
+
+__kernel void processCompoundPairsKernel( __global const b3Int4* gpuCompoundPairs,
+ __global const b3RigidBodyData* rigidBodies,
+ __global const b3Collidable* collidables,
+ __global const b3ConvexPolyhedronData* convexShapes,
+ __global const b3AlignedObjectArray<b3Float4>& vertices,
+ __global const b3AlignedObjectArray<b3Float4>& uniqueEdges,
+ __global const b3AlignedObjectArray<b3GpuFace>& faces,
+ __global const b3AlignedObjectArray<int>& indices,
+ __global b3Aabb* aabbs,
+ __global const b3GpuChildShape* gpuChildShapes,
+ __global b3AlignedObjectArray<b3Float4>& gpuCompoundSepNormalsOut,
+ __global b3AlignedObjectArray<int>& gpuHasCompoundSepNormalsOut,
+ int numCompoundPairs,
+ int i
+ )
+{
+
+// int i = get_global_id(0);
+ if (i<numCompoundPairs)
+ {
+ int bodyIndexA = gpuCompoundPairs[i].x;
+ int bodyIndexB = gpuCompoundPairs[i].y;
+
+ int childShapeIndexA = gpuCompoundPairs[i].z;
+ int childShapeIndexB = gpuCompoundPairs[i].w;
+
+ int collidableIndexA = -1;
+ int collidableIndexB = -1;
+
+ b3Quat ornA = rigidBodies[bodyIndexA].m_quat;
+ float4 posA = rigidBodies[bodyIndexA].m_pos;
+
+ b3Quat ornB = rigidBodies[bodyIndexB].m_quat;
+ float4 posB = rigidBodies[bodyIndexB].m_pos;
+
+ if (childShapeIndexA >= 0)
+ {
+ collidableIndexA = gpuChildShapes[childShapeIndexA].m_shapeIndex;
+ float4 childPosA = gpuChildShapes[childShapeIndexA].m_childPosition;
+ b3Quat childOrnA = gpuChildShapes[childShapeIndexA].m_childOrientation;
+ float4 newPosA = b3QuatRotate(ornA,childPosA)+posA;
+ b3Quat newOrnA = b3QuatMul(ornA,childOrnA);
+ posA = newPosA;
+ ornA = newOrnA;
+ } else
+ {
+ collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
+ }
+
+ if (childShapeIndexB>=0)
+ {
+ collidableIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;
+ float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;
+ b3Quat childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;
+ float4 newPosB = b3QuatRotate(ornB,childPosB)+posB;
+ b3Quat newOrnB = b3QuatMul(ornB,childOrnB);
+ posB = newPosB;
+ ornB = newOrnB;
+ } else
+ {
+ collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
+ }
+
+ gpuHasCompoundSepNormalsOut[i] = 0;
+
+ int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
+ int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
+
+ int shapeTypeA = collidables[collidableIndexA].m_shapeType;
+ int shapeTypeB = collidables[collidableIndexB].m_shapeType;
+
+
+ if ((shapeTypeA != SHAPE_CONVEX_HULL) || (shapeTypeB != SHAPE_CONVEX_HULL))
+ {
+ return;
+ }
+
+ int hasSeparatingAxis = 5;
+
+ // int numFacesA = convexShapes[shapeIndexA].m_numFaces;
+ float dmin = FLT_MAX;
+ posA.w = 0.f;
+ posB.w = 0.f;
+ float4 c0local = convexShapes[shapeIndexA].m_localCenter;
+ float4 c0 = transform(&c0local, &posA, &ornA);
+ float4 c1local = convexShapes[shapeIndexB].m_localCenter;
+ float4 c1 = transform(&c1local,&posB,&ornB);
+ const float4 DeltaC2 = c0 - c1;
+ float4 sepNormal = make_float4(1,0,0,0);
+// bool sepA = findSeparatingAxis( convexShapes[shapeIndexA], convexShapes[shapeIndexB],posA,ornA,posB,ornB,DeltaC2,vertices,uniqueEdges,faces,indices,&sepNormal,&dmin);
+ bool sepA = findSeparatingAxis( convexShapes[shapeIndexA], convexShapes[shapeIndexB],posA,ornA,posB,ornB,vertices,uniqueEdges,faces,indices,vertices,uniqueEdges,faces,indices,sepNormal);//,&dmin);
+
+ hasSeparatingAxis = 4;
+ if (!sepA)
+ {
+ hasSeparatingAxis = 0;
+ } else
+ {
+ bool sepB = findSeparatingAxis( convexShapes[shapeIndexB],convexShapes[shapeIndexA],posB,ornB,posA,ornA,vertices,uniqueEdges,faces,indices,vertices,uniqueEdges,faces,indices,sepNormal);//,&dmin);
+
+ if (!sepB)
+ {
+ hasSeparatingAxis = 0;
+ } else//(!sepB)
+ {
+ bool sepEE = findSeparatingAxisEdgeEdge( &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,posB,ornB,DeltaC2,vertices,uniqueEdges,faces,indices,&sepNormal,&dmin);
+ if (sepEE)
+ {
+ gpuCompoundSepNormalsOut[i] = sepNormal;//fastNormalize4(sepNormal);
+ gpuHasCompoundSepNormalsOut[i] = 1;
+ }//sepEE
+ }//(!sepB)
+ }//(!sepA)
+
+
+ }
+
+}
+
+
+__kernel void clipCompoundsHullHullKernel( __global const b3Int4* gpuCompoundPairs,
+ __global const b3RigidBodyData* rigidBodies,
+ __global const b3Collidable* collidables,
+ __global const b3ConvexPolyhedronData* convexShapes,
+ __global const b3AlignedObjectArray<b3Float4>& vertices,
+ __global const b3AlignedObjectArray<b3Float4>& uniqueEdges,
+ __global const b3AlignedObjectArray<b3GpuFace>& faces,
+ __global const b3AlignedObjectArray<int>& indices,
+ __global const b3GpuChildShape* gpuChildShapes,
+ __global const b3AlignedObjectArray<b3Float4>& gpuCompoundSepNormalsOut,
+ __global const b3AlignedObjectArray<int>& gpuHasCompoundSepNormalsOut,
+ __global struct b3Contact4Data* globalContactsOut,
+ int* nGlobalContactsOut,
+ int numCompoundPairs, int maxContactCapacity, int i)
+{
+
+// int i = get_global_id(0);
+ int pairIndex = i;
+
+ float4 worldVertsB1[64];
+ float4 worldVertsB2[64];
+ int capacityWorldVerts = 64;
+
+ float4 localContactsOut[64];
+ int localContactCapacity=64;
+
+ float minDist = -1e30f;
+ float maxDist = 0.0f;
+
+ if (i<numCompoundPairs)
+ {
+
+ if (gpuHasCompoundSepNormalsOut[i])
+ {
+
+ int bodyIndexA = gpuCompoundPairs[i].x;
+ int bodyIndexB = gpuCompoundPairs[i].y;
+
+ int childShapeIndexA = gpuCompoundPairs[i].z;
+ int childShapeIndexB = gpuCompoundPairs[i].w;
+
+ int collidableIndexA = -1;
+ int collidableIndexB = -1;
+
+ b3Quat ornA = rigidBodies[bodyIndexA].m_quat;
+ float4 posA = rigidBodies[bodyIndexA].m_pos;
+
+ b3Quat ornB = rigidBodies[bodyIndexB].m_quat;
+ float4 posB = rigidBodies[bodyIndexB].m_pos;
+
+ if (childShapeIndexA >= 0)
+ {
+ collidableIndexA = gpuChildShapes[childShapeIndexA].m_shapeIndex;
+ float4 childPosA = gpuChildShapes[childShapeIndexA].m_childPosition;
+ b3Quat childOrnA = gpuChildShapes[childShapeIndexA].m_childOrientation;
+ float4 newPosA = b3QuatRotate(ornA,childPosA)+posA;
+ b3Quat newOrnA = b3QuatMul(ornA,childOrnA);
+ posA = newPosA;
+ ornA = newOrnA;
+ } else
+ {
+ collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
+ }
+
+ if (childShapeIndexB>=0)
+ {
+ collidableIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;
+ float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;
+ b3Quat childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;
+ float4 newPosB = b3QuatRotate(ornB,childPosB)+posB;
+ b3Quat newOrnB = b3QuatMul(ornB,childOrnB);
+ posB = newPosB;
+ ornB = newOrnB;
+ } else
+ {
+ collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
+ }
+
+ int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
+ int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
+
+ int numLocalContactsOut = clipHullAgainstHull(gpuCompoundSepNormalsOut[i],
+ convexShapes[shapeIndexA], convexShapes[shapeIndexB],
+ posA,ornA,
+ posB,ornB,
+ worldVertsB1,worldVertsB2,capacityWorldVerts,
+ minDist, maxDist,
+ vertices,faces,indices,
+ vertices,faces,indices,
+ localContactsOut,localContactCapacity);
+
+ if (numLocalContactsOut>0)
+ {
+ float4 normal = -gpuCompoundSepNormalsOut[i];
+ int nPoints = numLocalContactsOut;
+ float4* pointsIn = localContactsOut;
+ b3Int4 contactIdx;// = {-1,-1,-1,-1};
+
+ contactIdx.s[0] = 0;
+ contactIdx.s[1] = 1;
+ contactIdx.s[2] = 2;
+ contactIdx.s[3] = 3;
+
+ int nReducedContacts = extractManifoldSequentialGlobal(pointsIn, nPoints, normal, &contactIdx);
+
+ int dstIdx;
+ dstIdx = b3AtomicInc( nGlobalContactsOut);
+ if ((dstIdx+nReducedContacts) < maxContactCapacity)
+ {
+ __global struct b3Contact4Data* c = globalContactsOut+ dstIdx;
+ c->m_worldNormalOnB = -normal;
+ c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);
+ c->m_batchIdx = pairIndex;
+ int bodyA = gpuCompoundPairs[pairIndex].x;
+ int bodyB = gpuCompoundPairs[pairIndex].y;
+ c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0?-bodyA:bodyA;
+ c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0?-bodyB:bodyB;
+ c->m_childIndexA = childShapeIndexA;
+ c->m_childIndexB = childShapeIndexB;
+ for (int i=0;i<nReducedContacts;i++)
+ {
+ c->m_worldPosB[i] = pointsIn[contactIdx.s[i]];
+ }
+ b3Contact4Data_setNumPoints(c,nReducedContacts);
+ }
+
+ }// if (numContactsOut>0)
+ }// if (gpuHasCompoundSepNormalsOut[i])
+ }// if (i<numCompoundPairs)
+
+}
+
+
+void computeContactCompoundCompound(int pairIndex,
+ int bodyIndexA, int bodyIndexB,
+ int collidableIndexA, int collidableIndexB,
+ const b3RigidBodyData* rigidBodies,
+ const b3Collidable* collidables,
+ const b3ConvexPolyhedronData* convexShapes,
+ const b3GpuChildShape* cpuChildShapes,
+ const b3AlignedObjectArray<b3Aabb>& hostAabbsWorldSpace,
+ const b3AlignedObjectArray<b3Aabb>& hostAabbsLocalSpace,
+
+ const b3AlignedObjectArray<b3Vector3>& convexVertices,
+ const b3AlignedObjectArray<b3Vector3>& hostUniqueEdges,
+ const b3AlignedObjectArray<int>& convexIndices,
+ const b3AlignedObjectArray<b3GpuFace>& faces,
+
+ b3Contact4* globalContactsOut,
+ int& nGlobalContactsOut,
+ int maxContactCapacity,
+ b3AlignedObjectArray<b3QuantizedBvhNode>& treeNodesCPU,
+ b3AlignedObjectArray<b3BvhSubtreeInfo>& subTreesCPU,
+ b3AlignedObjectArray<b3BvhInfo>& bvhInfoCPU
+ )
+{
+
+ int shapeTypeB = collidables[collidableIndexB].m_shapeType;
+ b3Assert(shapeTypeB == SHAPE_COMPOUND_OF_CONVEX_HULLS);
+
+ b3AlignedObjectArray<b3Int4> cpuCompoundPairsOut;
+ int numCompoundPairsOut=0;
+ int maxNumCompoundPairsCapacity = 8192;//1024;
+ cpuCompoundPairsOut.resize(maxNumCompoundPairsCapacity);
+
+ // work-in-progress
+ findCompoundPairsKernel(
+ pairIndex,
+ bodyIndexA,bodyIndexB,
+ collidableIndexA,collidableIndexB,
+ rigidBodies,
+ collidables,
+ convexShapes,
+ convexVertices,
+ hostAabbsWorldSpace,
+ hostAabbsLocalSpace,
+ cpuChildShapes,
+ &cpuCompoundPairsOut[0],
+ &numCompoundPairsOut,
+ maxNumCompoundPairsCapacity ,
+ treeNodesCPU,
+ subTreesCPU,
+ bvhInfoCPU
+ );
+
+ printf("maxNumAabbChecks=%d\n",maxNumAabbChecks);
+ if (numCompoundPairsOut>maxNumCompoundPairsCapacity)
+ {
+ b3Error("numCompoundPairsOut exceeded maxNumCompoundPairsCapacity (%d)\n",maxNumCompoundPairsCapacity);
+ numCompoundPairsOut=maxNumCompoundPairsCapacity;
+ }
+ b3AlignedObjectArray<b3Float4> cpuCompoundSepNormalsOut;
+ b3AlignedObjectArray<int> cpuHasCompoundSepNormalsOut;
+ cpuCompoundSepNormalsOut.resize(numCompoundPairsOut);
+ cpuHasCompoundSepNormalsOut.resize(numCompoundPairsOut);
+
+ for (int i=0;i<numCompoundPairsOut;i++)
+ {
+
+ processCompoundPairsKernel(&cpuCompoundPairsOut[0],rigidBodies,collidables,convexShapes,convexVertices,hostUniqueEdges,faces,convexIndices,0,cpuChildShapes,
+ cpuCompoundSepNormalsOut,cpuHasCompoundSepNormalsOut,numCompoundPairsOut,i);
+ }
+
+ for (int i=0;i<numCompoundPairsOut;i++)
+ {
+ clipCompoundsHullHullKernel(&cpuCompoundPairsOut[0],rigidBodies,collidables,convexShapes,convexVertices,hostUniqueEdges,faces,convexIndices,cpuChildShapes,
+ cpuCompoundSepNormalsOut,cpuHasCompoundSepNormalsOut,globalContactsOut,&nGlobalContactsOut,numCompoundPairsOut,maxContactCapacity,i);
+ }
+ /*
+ int childColIndexA = gpuChildShapes[childShapeIndexA].m_shapeIndex;
+
+ float4 posA = rigidBodies[bodyIndexA].m_pos;
+ b3Quat ornA = rigidBodies[bodyIndexA].m_quat;
+ float4 childPosA = gpuChildShapes[childShapeIndexA].m_childPosition;
+ b3Quat childOrnA = gpuChildShapes[childShapeIndexA].m_childOrientation;
+ float4 newPosA = b3QuatRotate(ornA,childPosA)+posA;
+ b3Quat newOrnA = b3QuatMul(ornA,childOrnA);
+
+ int shapeIndexA = collidables[childColIndexA].m_shapeIndex;
+
+
+ bool foundSepAxis = findSeparatingAxis(hullA,hullB,
+ posA,
+ ornA,
+ posB,
+ ornB,
+
+ convexVertices,uniqueEdges,faces,convexIndices,
+ convexVertices,uniqueEdges,faces,convexIndices,
+
+ sepNormalWorldSpace
+ );
+ */
+
+
+ /*
+ if (foundSepAxis)
+ {
+
+
+ contactIndex = clipHullHullSingle(
+ bodyIndexA, bodyIndexB,
+ posA,ornA,
+ posB,ornB,
+ collidableIndexA, collidableIndexB,
+ &rigidBodies,
+ &globalContactsOut,
+ nGlobalContactsOut,
+
+ convexShapes,
+ convexShapes,
+
+ convexVertices,
+ uniqueEdges,
+ faces,
+ convexIndices,
+
+ convexVertices,
+ uniqueEdges,
+ faces,
+ convexIndices,
+
+ collidables,
+ collidables,
+ sepNormalWorldSpace,
+ maxContactCapacity);
+
+ }
+ */
+
+// return contactIndex;
+
+ /*
+
+ int numChildrenB = collidables[collidableIndexB].m_numChildShapes;
+ for (int c=0;c<numChildrenB;c++)
+ {
+ int childShapeIndexB = collidables[collidableIndexB].m_shapeIndex+c;
+ int childColIndexB = cpuChildShapes[childShapeIndexB].m_shapeIndex;
+
+ float4 rootPosB = rigidBodies[bodyIndexB].m_pos;
+ b3Quaternion rootOrnB = rigidBodies[bodyIndexB].m_quat;
+ b3Vector3 childPosB = cpuChildShapes[childShapeIndexB].m_childPosition;
+ b3Quaternion childOrnB = cpuChildShapes[childShapeIndexB].m_childOrientation;
+ float4 posB = b3QuatRotate(rootOrnB,childPosB)+rootPosB;
+ b3Quaternion ornB = b3QuatMul(rootOrnB,childOrnB);//b3QuatMul(ornB,childOrnB);
+
+ int shapeIndexB = collidables[childColIndexB].m_shapeIndex;
+
+ const b3ConvexPolyhedronData* hullB = &convexShapes[shapeIndexB];
+
+ }
+ */
+
+}
+
+void computeContactPlaneCompound(int pairIndex,
+ int bodyIndexA, int bodyIndexB,
+ int collidableIndexA, int collidableIndexB,
+ const b3RigidBodyData* rigidBodies,
+ const b3Collidable* collidables,
+ const b3ConvexPolyhedronData* convexShapes,
+ const b3GpuChildShape* cpuChildShapes,
+ const b3Vector3* convexVertices,
+ const int* convexIndices,
+ const b3GpuFace* faces,
+
+ b3Contact4* globalContactsOut,
+ int& nGlobalContactsOut,
+ int maxContactCapacity)
+{
+
+ int shapeTypeB = collidables[collidableIndexB].m_shapeType;
+ b3Assert(shapeTypeB == SHAPE_COMPOUND_OF_CONVEX_HULLS);
+
+
+ int numChildrenB = collidables[collidableIndexB].m_numChildShapes;
+ for (int c=0;c<numChildrenB;c++)
+ {
+ int childShapeIndexB = collidables[collidableIndexB].m_shapeIndex+c;
+ int childColIndexB = cpuChildShapes[childShapeIndexB].m_shapeIndex;
+
+ float4 rootPosB = rigidBodies[bodyIndexB].m_pos;
+ b3Quaternion rootOrnB = rigidBodies[bodyIndexB].m_quat;
+ b3Vector3 childPosB = cpuChildShapes[childShapeIndexB].m_childPosition;
+ b3Quaternion childOrnB = cpuChildShapes[childShapeIndexB].m_childOrientation;
+ float4 posB = b3QuatRotate(rootOrnB,childPosB)+rootPosB;
+ b3Quaternion ornB = rootOrnB*childOrnB;//b3QuatMul(ornB,childOrnB);
+
+ int shapeIndexB = collidables[childColIndexB].m_shapeIndex;
+
+ const b3ConvexPolyhedronData* hullB = &convexShapes[shapeIndexB];
+
+
+ b3Vector3 posA = rigidBodies[bodyIndexA].m_pos;
+ b3Quaternion ornA = rigidBodies[bodyIndexA].m_quat;
+
+ // int numContactsOut = 0;
+ // int numWorldVertsB1= 0;
+
+ b3Vector3 planeEq = faces[collidables[collidableIndexA].m_shapeIndex].m_plane;
+ b3Vector3 planeNormal=b3MakeVector3(planeEq.x,planeEq.y,planeEq.z);
+ b3Vector3 planeNormalWorld = b3QuatRotate(ornA,planeNormal);
+ float planeConstant = planeEq.w;
+ b3Transform convexWorldTransform;
+ convexWorldTransform.setIdentity();
+ convexWorldTransform.setOrigin(posB);
+ convexWorldTransform.setRotation(ornB);
+ b3Transform planeTransform;
+ planeTransform.setIdentity();
+ planeTransform.setOrigin(posA);
+ planeTransform.setRotation(ornA);
+
+ b3Transform planeInConvex;
+ planeInConvex= convexWorldTransform.inverse() * planeTransform;
+ b3Transform convexInPlane;
+ convexInPlane = planeTransform.inverse() * convexWorldTransform;
+
+ b3Vector3 planeNormalInConvex = planeInConvex.getBasis()*-planeNormal;
+ float maxDot = -1e30;
+ int hitVertex=-1;
+ b3Vector3 hitVtx;
+
+ #define MAX_PLANE_CONVEX_POINTS 64
+
+ b3Vector3 contactPoints[MAX_PLANE_CONVEX_POINTS];
+ int numPoints = 0;
+
+ b3Int4 contactIdx;
+ contactIdx.s[0] = 0;
+ contactIdx.s[1] = 1;
+ contactIdx.s[2] = 2;
+ contactIdx.s[3] = 3;
+
+ for (int i=0;i<hullB->m_numVertices;i++)
+ {
+ b3Vector3 vtx = convexVertices[hullB->m_vertexOffset+i];
+ float curDot = vtx.dot(planeNormalInConvex);
+
+
+ if (curDot>maxDot)
+ {
+ hitVertex=i;
+ maxDot=curDot;
+ hitVtx = vtx;
+ //make sure the deepest points is always included
+ if (numPoints==MAX_PLANE_CONVEX_POINTS)
+ numPoints--;
+ }
+
+ if (numPoints<MAX_PLANE_CONVEX_POINTS)
+ {
+ b3Vector3 vtxWorld = convexWorldTransform*vtx;
+ b3Vector3 vtxInPlane = planeTransform.inverse()*vtxWorld;
+ float dist = planeNormal.dot(vtxInPlane)-planeConstant;
+ if (dist<0.f)
+ {
+ vtxWorld.w = dist;
+ contactPoints[numPoints] = vtxWorld;
+ numPoints++;
+ }
+ }
+
+ }
+
+ int numReducedPoints = 0;
+
+ numReducedPoints = numPoints;
+
+ if (numPoints>4)
+ {
+ numReducedPoints = extractManifoldSequentialGlobal( contactPoints, numPoints, planeNormalInConvex, &contactIdx);
+ }
+ int dstIdx;
+ // dstIdx = nGlobalContactsOut++;//AppendInc( nGlobalContactsOut, dstIdx );
+
+ if (numReducedPoints>0)
+ {
+ if (nGlobalContactsOut < maxContactCapacity)
+ {
+ dstIdx=nGlobalContactsOut;
+ nGlobalContactsOut++;
+
+ b3Contact4* c = &globalContactsOut[dstIdx];
+ c->m_worldNormalOnB = -planeNormalWorld;
+ c->setFrictionCoeff(0.7);
+ c->setRestituitionCoeff(0.f);
+
+ c->m_batchIdx = pairIndex;
+ c->m_bodyAPtrAndSignBit = rigidBodies[bodyIndexA].m_invMass==0?-bodyIndexA:bodyIndexA;
+ c->m_bodyBPtrAndSignBit = rigidBodies[bodyIndexB].m_invMass==0?-bodyIndexB:bodyIndexB;
+ for (int i=0;i<numReducedPoints;i++)
+ {
+ b3Vector3 pOnB1 = contactPoints[contactIdx.s[i]];
+ c->m_worldPosB[i] = pOnB1;
+ }
+ c->m_worldNormalOnB.w = (b3Scalar)numReducedPoints;
+ }//if (dstIdx < numPairs)
+ }
+
+ }
+
+
+}
+
+
+
+
+
+void computeContactSphereConvex(int pairIndex,
+ int bodyIndexA, int bodyIndexB,
+ int collidableIndexA, int collidableIndexB,
+ const b3RigidBodyData* rigidBodies,
+ const b3Collidable* collidables,
+ const b3ConvexPolyhedronData* convexShapes,
+ const b3Vector3* convexVertices,
+ const int* convexIndices,
+ const b3GpuFace* faces,
+ b3Contact4* globalContactsOut,
+ int& nGlobalContactsOut,
+ int maxContactCapacity)
+{
+
+ float radius = collidables[collidableIndexA].m_radius;
+ float4 spherePos1 = rigidBodies[bodyIndexA].m_pos;
+ b3Quaternion sphereOrn = rigidBodies[bodyIndexA].m_quat;
+
+
+
+ float4 pos = rigidBodies[bodyIndexB].m_pos;
+
+
+ b3Quaternion quat = rigidBodies[bodyIndexB].m_quat;
+
+ b3Transform tr;
+ tr.setIdentity();
+ tr.setOrigin(pos);
+ tr.setRotation(quat);
+ b3Transform trInv = tr.inverse();
+
+ float4 spherePos = trInv(spherePos1);
+
+ int collidableIndex = rigidBodies[bodyIndexB].m_collidableIdx;
+ int shapeIndex = collidables[collidableIndex].m_shapeIndex;
+ int numFaces = convexShapes[shapeIndex].m_numFaces;
+ float4 closestPnt = b3MakeVector3(0, 0, 0, 0);
+// float4 hitNormalWorld = b3MakeVector3(0, 0, 0, 0);
+ float minDist = -1000000.f; // TODO: What is the largest/smallest float?
+ bool bCollide = true;
+ int region = -1;
+ float4 localHitNormal;
+ for ( int f = 0; f < numFaces; f++ )
+ {
+ b3GpuFace face = faces[convexShapes[shapeIndex].m_faceOffset+f];
+ float4 planeEqn;
+ float4 localPlaneNormal = b3MakeVector3(face.m_plane.x,face.m_plane.y,face.m_plane.z,0.f);
+ float4 n1 = localPlaneNormal;//quatRotate(quat,localPlaneNormal);
+ planeEqn = n1;
+ planeEqn[3] = face.m_plane.w;
+
+ float4 pntReturn;
+ float dist = signedDistanceFromPointToPlane(spherePos, planeEqn, &pntReturn);
+
+ if ( dist > radius)
+ {
+ bCollide = false;
+ break;
+ }
+
+ if ( dist > 0 )
+ {
+ //might hit an edge or vertex
+ b3Vector3 out;
+
+ bool isInPoly = IsPointInPolygon(spherePos,
+ &face,
+ &convexVertices[convexShapes[shapeIndex].m_vertexOffset],
+ convexIndices,
+ &out);
+ if (isInPoly)
+ {
+ if (dist>minDist)
+ {
+ minDist = dist;
+ closestPnt = pntReturn;
+ localHitNormal = planeEqn;
+ region=1;
+ }
+ } else
+ {
+ b3Vector3 tmp = spherePos-out;
+ b3Scalar l2 = tmp.length2();
+ if (l2<radius*radius)
+ {
+ dist = b3Sqrt(l2);
+ if (dist>minDist)
+ {
+ minDist = dist;
+ closestPnt = out;
+ localHitNormal = tmp/dist;
+ region=2;
+ }
+
+ } else
+ {
+ bCollide = false;
+ break;
+ }
+ }
+ }
+ else
+ {
+ if ( dist > minDist )
+ {
+ minDist = dist;
+ closestPnt = pntReturn;
+ localHitNormal = planeEqn;
+ region=3;
+ }
+ }
+ }
+ static int numChecks = 0;
+ numChecks++;
+
+ if (bCollide && minDist > -10000)
+ {
+
+ float4 normalOnSurfaceB1 = tr.getBasis()*localHitNormal;//-hitNormalWorld;
+ float4 pOnB1 = tr(closestPnt);
+ //printf("dist ,%f,",minDist);
+ float actualDepth = minDist-radius;
+ if (actualDepth<0)
+ {
+ //printf("actualDepth = ,%f,", actualDepth);
+ //printf("normalOnSurfaceB1 = ,%f,%f,%f,", normalOnSurfaceB1.x,normalOnSurfaceB1.y,normalOnSurfaceB1.z);
+ //printf("region=,%d,\n", region);
+ pOnB1[3] = actualDepth;
+
+ int dstIdx;
+// dstIdx = nGlobalContactsOut++;//AppendInc( nGlobalContactsOut, dstIdx );
+
+ if (nGlobalContactsOut < maxContactCapacity)
+ {
+ dstIdx=nGlobalContactsOut;
+ nGlobalContactsOut++;
+
+ b3Contact4* c = &globalContactsOut[dstIdx];
+ c->m_worldNormalOnB = normalOnSurfaceB1;
+ c->setFrictionCoeff(0.7);
+ c->setRestituitionCoeff(0.f);
+
+ c->m_batchIdx = pairIndex;
+ c->m_bodyAPtrAndSignBit = rigidBodies[bodyIndexA].m_invMass==0?-bodyIndexA:bodyIndexA;
+ c->m_bodyBPtrAndSignBit = rigidBodies[bodyIndexB].m_invMass==0?-bodyIndexB:bodyIndexB;
+ c->m_worldPosB[0] = pOnB1;
+ int numPoints = 1;
+ c->m_worldNormalOnB.w = (b3Scalar)numPoints;
+ }//if (dstIdx < numPairs)
+ }
+ }//if (hasCollision)
+
+}
+
+
+
+
+int computeContactConvexConvex2(
+ int pairIndex,
+ int bodyIndexA, int bodyIndexB,
+ int collidableIndexA, int collidableIndexB,
+ const b3AlignedObjectArray<b3RigidBodyData>& rigidBodies,
+ const b3AlignedObjectArray<b3Collidable>& collidables,
+ const b3AlignedObjectArray<b3ConvexPolyhedronData>& convexShapes,
+ const b3AlignedObjectArray<b3Vector3>& convexVertices,
+ const b3AlignedObjectArray<b3Vector3>& uniqueEdges,
+ const b3AlignedObjectArray<int>& convexIndices,
+ const b3AlignedObjectArray<b3GpuFace>& faces,
+ b3AlignedObjectArray<b3Contact4>& globalContactsOut,
+ int& nGlobalContactsOut,
+ int maxContactCapacity,
+ const b3AlignedObjectArray<b3Contact4>& oldContacts
+ )
+{
+ int contactIndex = -1;
+ b3Vector3 posA = rigidBodies[bodyIndexA].m_pos;
+ b3Quaternion ornA = rigidBodies[bodyIndexA].m_quat;
+ b3Vector3 posB = rigidBodies[bodyIndexB].m_pos;
+ b3Quaternion ornB = rigidBodies[bodyIndexB].m_quat;
+
+
+ b3ConvexPolyhedronData hullA, hullB;
+
+ b3Vector3 sepNormalWorldSpace;
+
+
+
+ b3Collidable colA = collidables[collidableIndexA];
+ hullA = convexShapes[colA.m_shapeIndex];
+ //printf("numvertsA = %d\n",hullA.m_numVertices);
+
+
+ b3Collidable colB = collidables[collidableIndexB];
+ hullB = convexShapes[colB.m_shapeIndex];
+ //printf("numvertsB = %d\n",hullB.m_numVertices);
+
+// int contactCapacity = MAX_VERTS;
+ //int numContactsOut=0;
+
+
+#ifdef _WIN32
+ b3Assert(_finite(rigidBodies[bodyIndexA].m_pos.x));
+ b3Assert(_finite(rigidBodies[bodyIndexB].m_pos.x));
+#endif
+
+ bool foundSepAxis = findSeparatingAxis(hullA,hullB,
+ posA,
+ ornA,
+ posB,
+ ornB,
+
+ convexVertices,uniqueEdges,faces,convexIndices,
+ convexVertices,uniqueEdges,faces,convexIndices,
+
+ sepNormalWorldSpace
+ );
+
+
+ if (foundSepAxis)
+ {
+
+
+ contactIndex = clipHullHullSingle(
+ bodyIndexA, bodyIndexB,
+ posA,ornA,
+ posB,ornB,
+ collidableIndexA, collidableIndexB,
+ &rigidBodies,
+ &globalContactsOut,
+ nGlobalContactsOut,
+
+ convexShapes,
+ convexShapes,
+
+ convexVertices,
+ uniqueEdges,
+ faces,
+ convexIndices,
+
+ convexVertices,
+ uniqueEdges,
+ faces,
+ convexIndices,
+
+ collidables,
+ collidables,
+ sepNormalWorldSpace,
+ maxContactCapacity);
+
+ }
+
+ return contactIndex;
+}
+
+
+
+
+
+
+
+void GpuSatCollision::computeConvexConvexContactsGPUSAT( b3OpenCLArray<b3Int4>* pairs, int nPairs,
+ const b3OpenCLArray<b3RigidBodyData>* bodyBuf,
+ b3OpenCLArray<b3Contact4>* contactOut, int& nContacts,
+ const b3OpenCLArray<b3Contact4>* oldContacts,
+ int maxContactCapacity,
+ int compoundPairCapacity,
+ const b3OpenCLArray<b3ConvexPolyhedronData>& convexData,
+ const b3OpenCLArray<b3Vector3>& gpuVertices,
+ const b3OpenCLArray<b3Vector3>& gpuUniqueEdges,
+ const b3OpenCLArray<b3GpuFace>& gpuFaces,
+ const b3OpenCLArray<int>& gpuIndices,
+ const b3OpenCLArray<b3Collidable>& gpuCollidables,
+ const b3OpenCLArray<b3GpuChildShape>& gpuChildShapes,
+
+ const b3OpenCLArray<b3Aabb>& clAabbsWorldSpace,
+ const b3OpenCLArray<b3Aabb>& clAabbsLocalSpace,
+
+ b3OpenCLArray<b3Vector3>& worldVertsB1GPU,
+ b3OpenCLArray<b3Int4>& clippingFacesOutGPU,
+ b3OpenCLArray<b3Vector3>& worldNormalsAGPU,
+ b3OpenCLArray<b3Vector3>& worldVertsA1GPU,
+ b3OpenCLArray<b3Vector3>& worldVertsB2GPU,
+ b3AlignedObjectArray<class b3OptimizedBvh*>& bvhDataUnused,
+ b3OpenCLArray<b3QuantizedBvhNode>* treeNodesGPU,
+ b3OpenCLArray<b3BvhSubtreeInfo>* subTreesGPU,
+ b3OpenCLArray<b3BvhInfo>* bvhInfo,
+
+ int numObjects,
+ int maxTriConvexPairCapacity,
+ b3OpenCLArray<b3Int4>& triangleConvexPairsOut,
+ int& numTriConvexPairsOut
+ )
+{
+ myframecount++;
+
+ if (!nPairs)
+ return;
+
+#ifdef CHECK_ON_HOST
+
+
+ b3AlignedObjectArray<b3QuantizedBvhNode> treeNodesCPU;
+ treeNodesGPU->copyToHost(treeNodesCPU);
+
+ b3AlignedObjectArray<b3BvhSubtreeInfo> subTreesCPU;
+ subTreesGPU->copyToHost(subTreesCPU);
+
+ b3AlignedObjectArray<b3BvhInfo> bvhInfoCPU;
+ bvhInfo->copyToHost(bvhInfoCPU);
+
+ b3AlignedObjectArray<b3Aabb> hostAabbsWorldSpace;
+ clAabbsWorldSpace.copyToHost(hostAabbsWorldSpace);
+
+ b3AlignedObjectArray<b3Aabb> hostAabbsLocalSpace;
+ clAabbsLocalSpace.copyToHost(hostAabbsLocalSpace);
+
+ b3AlignedObjectArray<b3Int4> hostPairs;
+ pairs->copyToHost(hostPairs);
+
+ b3AlignedObjectArray<b3RigidBodyData> hostBodyBuf;
+ bodyBuf->copyToHost(hostBodyBuf);
+
+
+
+ b3AlignedObjectArray<b3ConvexPolyhedronData> hostConvexData;
+ convexData.copyToHost(hostConvexData);
+
+ b3AlignedObjectArray<b3Vector3> hostVertices;
+ gpuVertices.copyToHost(hostVertices);
+
+ b3AlignedObjectArray<b3Vector3> hostUniqueEdges;
+ gpuUniqueEdges.copyToHost(hostUniqueEdges);
+ b3AlignedObjectArray<b3GpuFace> hostFaces;
+ gpuFaces.copyToHost(hostFaces);
+ b3AlignedObjectArray<int> hostIndices;
+ gpuIndices.copyToHost(hostIndices);
+ b3AlignedObjectArray<b3Collidable> hostCollidables;
+ gpuCollidables.copyToHost(hostCollidables);
+
+ b3AlignedObjectArray<b3GpuChildShape> cpuChildShapes;
+ gpuChildShapes.copyToHost(cpuChildShapes);
+
+
+ b3AlignedObjectArray<b3Int4> hostTriangleConvexPairs;
+
+ b3AlignedObjectArray<b3Contact4> hostContacts;
+ if (nContacts)
+ {
+ contactOut->copyToHost(hostContacts);
+ }
+
+ b3AlignedObjectArray<b3Contact4> oldHostContacts;
+
+ if (oldContacts->size())
+ {
+ oldContacts->copyToHost(oldHostContacts);
+ }
+
+
+ hostContacts.resize(maxContactCapacity);
+
+ for (int i=0;i<nPairs;i++)
+ {
+ int bodyIndexA = hostPairs[i].x;
+ int bodyIndexB = hostPairs[i].y;
+ int collidableIndexA = hostBodyBuf[bodyIndexA].m_collidableIdx;
+ int collidableIndexB = hostBodyBuf[bodyIndexB].m_collidableIdx;
+
+ if (hostCollidables[collidableIndexA].m_shapeType == SHAPE_SPHERE &&
+ hostCollidables[collidableIndexB].m_shapeType == SHAPE_CONVEX_HULL)
+ {
+ computeContactSphereConvex(i,bodyIndexA,bodyIndexB,collidableIndexA,collidableIndexB,&hostBodyBuf[0],
+ &hostCollidables[0],&hostConvexData[0],&hostVertices[0],&hostIndices[0],&hostFaces[0],&hostContacts[0],nContacts,maxContactCapacity);
+ }
+
+ if (hostCollidables[collidableIndexA].m_shapeType == SHAPE_CONVEX_HULL &&
+ hostCollidables[collidableIndexB].m_shapeType == SHAPE_SPHERE)
+ {
+ computeContactSphereConvex(i,bodyIndexB,bodyIndexA,collidableIndexB,collidableIndexA,&hostBodyBuf[0],
+ &hostCollidables[0],&hostConvexData[0],&hostVertices[0],&hostIndices[0],&hostFaces[0],&hostContacts[0],nContacts,maxContactCapacity);
+ //printf("convex-sphere\n");
+
+ }
+
+ if (hostCollidables[collidableIndexA].m_shapeType == SHAPE_CONVEX_HULL &&
+ hostCollidables[collidableIndexB].m_shapeType == SHAPE_PLANE)
+ {
+ computeContactPlaneConvex(i,bodyIndexB,bodyIndexA,collidableIndexB,collidableIndexA,&hostBodyBuf[0],
+ &hostCollidables[0],&hostConvexData[0],&hostVertices[0],&hostIndices[0],&hostFaces[0],&hostContacts[0],nContacts,maxContactCapacity);
+// printf("convex-plane\n");
+
+ }
+
+ if (hostCollidables[collidableIndexA].m_shapeType == SHAPE_PLANE &&
+ hostCollidables[collidableIndexB].m_shapeType == SHAPE_CONVEX_HULL)
+ {
+ computeContactPlaneConvex(i,bodyIndexA,bodyIndexB,collidableIndexA,collidableIndexB,&hostBodyBuf[0],
+ &hostCollidables[0],&hostConvexData[0],&hostVertices[0],&hostIndices[0],&hostFaces[0],&hostContacts[0],nContacts,maxContactCapacity);
+// printf("plane-convex\n");
+
+ }
+
+ if (hostCollidables[collidableIndexA].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS &&
+ hostCollidables[collidableIndexB].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS)
+ {
+ computeContactCompoundCompound(i,bodyIndexB,bodyIndexA,collidableIndexB,collidableIndexA,&hostBodyBuf[0],
+ &hostCollidables[0],&hostConvexData[0],&cpuChildShapes[0], hostAabbsWorldSpace,hostAabbsLocalSpace,hostVertices,hostUniqueEdges,hostIndices,hostFaces,&hostContacts[0],
+ nContacts,maxContactCapacity,treeNodesCPU,subTreesCPU,bvhInfoCPU);
+// printf("convex-plane\n");
+
+ }
+
+
+ if (hostCollidables[collidableIndexA].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS &&
+ hostCollidables[collidableIndexB].m_shapeType == SHAPE_PLANE)
+ {
+ computeContactPlaneCompound(i,bodyIndexB,bodyIndexA,collidableIndexB,collidableIndexA,&hostBodyBuf[0],
+ &hostCollidables[0],&hostConvexData[0],&cpuChildShapes[0], &hostVertices[0],&hostIndices[0],&hostFaces[0],&hostContacts[0],nContacts,maxContactCapacity);
+// printf("convex-plane\n");
+
+ }
+
+ if (hostCollidables[collidableIndexA].m_shapeType == SHAPE_PLANE &&
+ hostCollidables[collidableIndexB].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS)
+ {
+ computeContactPlaneCompound(i,bodyIndexA,bodyIndexB,collidableIndexA,collidableIndexB,&hostBodyBuf[0],
+ &hostCollidables[0],&hostConvexData[0],&cpuChildShapes[0],&hostVertices[0],&hostIndices[0],&hostFaces[0],&hostContacts[0],nContacts,maxContactCapacity);
+// printf("plane-convex\n");
+
+ }
+
+ if (hostCollidables[collidableIndexA].m_shapeType == SHAPE_CONVEX_HULL &&
+ hostCollidables[collidableIndexB].m_shapeType == SHAPE_CONVEX_HULL)
+ {
+ //printf("hostPairs[i].z=%d\n",hostPairs[i].z);
+ int contactIndex = computeContactConvexConvex2( i,bodyIndexA,bodyIndexB,collidableIndexA,collidableIndexB,hostBodyBuf, hostCollidables,hostConvexData,hostVertices,hostUniqueEdges,hostIndices,hostFaces,hostContacts,nContacts,maxContactCapacity,oldHostContacts);
+ //int contactIndex = computeContactConvexConvex(hostPairs,i,bodyIndexA,bodyIndexB,collidableIndexA,collidableIndexB,hostBodyBuf,hostCollidables,hostConvexData,hostVertices,hostUniqueEdges,hostIndices,hostFaces,hostContacts,nContacts,maxContactCapacity,oldHostContacts);
+
+
+ if (contactIndex>=0)
+ {
+// printf("convex convex contactIndex = %d\n",contactIndex);
+ hostPairs[i].z = contactIndex;
+ }
+// printf("plane-convex\n");
+
+ }
+
+
+ }
+
+ if (hostPairs.size())
+ {
+ pairs->copyFromHost(hostPairs);
+ }
+
+ hostContacts.resize(nContacts);
+ if (nContacts)
+ {
+
+ contactOut->copyFromHost(hostContacts);
+ } else
+ {
+ contactOut->resize(0);
+ }
+
+ m_totalContactsOut.copyFromHostPointer(&nContacts,1,0,true);
+ //printf("(HOST) nContacts = %d\n",nContacts);
+
+#else
+
+ {
+ if (nPairs)
+ {
+ m_totalContactsOut.copyFromHostPointer(&nContacts,1,0,true);
+
+ B3_PROFILE("primitiveContactsKernel");
+ b3BufferInfoCL bInfo[] = {
+ b3BufferInfoCL( pairs->getBufferCL(), true ),
+ b3BufferInfoCL( bodyBuf->getBufferCL(),true),
+ b3BufferInfoCL( gpuCollidables.getBufferCL(),true),
+ b3BufferInfoCL( convexData.getBufferCL(),true),
+ b3BufferInfoCL( gpuVertices.getBufferCL(),true),
+ b3BufferInfoCL( gpuUniqueEdges.getBufferCL(),true),
+ b3BufferInfoCL( gpuFaces.getBufferCL(),true),
+ b3BufferInfoCL( gpuIndices.getBufferCL(),true),
+ b3BufferInfoCL( contactOut->getBufferCL()),
+ b3BufferInfoCL( m_totalContactsOut.getBufferCL())
+ };
+
+ b3LauncherCL launcher(m_queue, m_primitiveContactsKernel,"m_primitiveContactsKernel");
+ launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst( nPairs );
+ launcher.setConst(maxContactCapacity);
+ int num = nPairs;
+ launcher.launch1D( num);
+ clFinish(m_queue);
+
+ nContacts = m_totalContactsOut.at(0);
+ contactOut->resize(nContacts);
+ }
+ }
+
+
+#endif//CHECK_ON_HOST
+
+ B3_PROFILE("computeConvexConvexContactsGPUSAT");
+ // printf("nContacts = %d\n",nContacts);
+
+
+ m_sepNormals.resize(nPairs);
+ m_hasSeparatingNormals.resize(nPairs);
+
+ int concaveCapacity=maxTriConvexPairCapacity;
+ m_concaveSepNormals.resize(concaveCapacity);
+ m_concaveHasSeparatingNormals.resize(concaveCapacity);
+ m_numConcavePairsOut.resize(0);
+ m_numConcavePairsOut.push_back(0);
+
+
+ m_gpuCompoundPairs.resize(compoundPairCapacity);
+
+ m_gpuCompoundSepNormals.resize(compoundPairCapacity);
+
+
+ m_gpuHasCompoundSepNormals.resize(compoundPairCapacity);
+
+ m_numCompoundPairsOut.resize(0);
+ m_numCompoundPairsOut.push_back(0);
+
+ int numCompoundPairs = 0;
+
+ int numConcavePairs =0;
+
+ {
+ clFinish(m_queue);
+ if (findSeparatingAxisOnGpu)
+ {
+ m_dmins.resize(nPairs);
+ if (splitSearchSepAxisConvex)
+ {
+
+
+ if (useMprGpu)
+ {
+ nContacts = m_totalContactsOut.at(0);
+ {
+ B3_PROFILE("mprPenetrationKernel");
+ b3BufferInfoCL bInfo[] = {
+ b3BufferInfoCL( pairs->getBufferCL(), true ),
+ b3BufferInfoCL( bodyBuf->getBufferCL(),true),
+ b3BufferInfoCL( gpuCollidables.getBufferCL(),true),
+ b3BufferInfoCL( convexData.getBufferCL(),true),
+ b3BufferInfoCL( gpuVertices.getBufferCL(),true),
+ b3BufferInfoCL( m_sepNormals.getBufferCL()),
+ b3BufferInfoCL( m_hasSeparatingNormals.getBufferCL()),
+ b3BufferInfoCL( contactOut->getBufferCL()),
+ b3BufferInfoCL( m_totalContactsOut.getBufferCL())
+ };
+
+ b3LauncherCL launcher(m_queue, m_mprPenetrationKernel,"mprPenetrationKernel");
+ launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+
+ launcher.setConst(maxContactCapacity);
+ launcher.setConst( nPairs );
+
+ int num = nPairs;
+ launcher.launch1D( num);
+ clFinish(m_queue);
+ /*
+ b3AlignedObjectArray<int>hostHasSepAxis;
+ m_hasSeparatingNormals.copyToHost(hostHasSepAxis);
+ b3AlignedObjectArray<b3Vector3>hostSepAxis;
+ m_sepNormals.copyToHost(hostSepAxis);
+ */
+ nContacts = m_totalContactsOut.at(0);
+ contactOut->resize(nContacts);
+ // printf("nContacts (after mprPenetrationKernel) = %d\n",nContacts);
+ if (nContacts>maxContactCapacity)
+ {
+
+ b3Error("Error: contacts exceeds capacity (%d/%d)\n", nContacts, maxContactCapacity);
+ nContacts = maxContactCapacity;
+ }
+
+ }
+ }
+
+ if (1)
+ {
+
+ if (1)
+ {
+ {
+ B3_PROFILE("findSeparatingAxisVertexFaceKernel");
+ b3BufferInfoCL bInfo[] = {
+ b3BufferInfoCL( pairs->getBufferCL(), true ),
+ b3BufferInfoCL( bodyBuf->getBufferCL(),true),
+ b3BufferInfoCL( gpuCollidables.getBufferCL(),true),
+ b3BufferInfoCL( convexData.getBufferCL(),true),
+ b3BufferInfoCL( gpuVertices.getBufferCL(),true),
+ b3BufferInfoCL( gpuUniqueEdges.getBufferCL(),true),
+ b3BufferInfoCL( gpuFaces.getBufferCL(),true),
+ b3BufferInfoCL( gpuIndices.getBufferCL(),true),
+ b3BufferInfoCL( clAabbsWorldSpace.getBufferCL(),true),
+ b3BufferInfoCL( m_sepNormals.getBufferCL()),
+ b3BufferInfoCL( m_hasSeparatingNormals.getBufferCL()),
+ b3BufferInfoCL( m_dmins.getBufferCL())
+ };
+
+ b3LauncherCL launcher(m_queue, m_findSeparatingAxisVertexFaceKernel,"findSeparatingAxisVertexFaceKernel");
+ launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst( nPairs );
+
+ int num = nPairs;
+ launcher.launch1D( num);
+ clFinish(m_queue);
+ }
+
+
+ int numDirections = sizeof(unitSphere162)/sizeof(b3Vector3);
+
+ {
+ B3_PROFILE("findSeparatingAxisEdgeEdgeKernel");
+ b3BufferInfoCL bInfo[] = {
+ b3BufferInfoCL( pairs->getBufferCL(), true ),
+ b3BufferInfoCL( bodyBuf->getBufferCL(),true),
+ b3BufferInfoCL( gpuCollidables.getBufferCL(),true),
+ b3BufferInfoCL( convexData.getBufferCL(),true),
+ b3BufferInfoCL( gpuVertices.getBufferCL(),true),
+ b3BufferInfoCL( gpuUniqueEdges.getBufferCL(),true),
+ b3BufferInfoCL( gpuFaces.getBufferCL(),true),
+ b3BufferInfoCL( gpuIndices.getBufferCL(),true),
+ b3BufferInfoCL( clAabbsWorldSpace.getBufferCL(),true),
+ b3BufferInfoCL( m_sepNormals.getBufferCL()),
+ b3BufferInfoCL( m_hasSeparatingNormals.getBufferCL()),
+ b3BufferInfoCL( m_dmins.getBufferCL()),
+ b3BufferInfoCL( m_unitSphereDirections.getBufferCL(),true)
+
+ };
+
+ b3LauncherCL launcher(m_queue, m_findSeparatingAxisEdgeEdgeKernel,"findSeparatingAxisEdgeEdgeKernel");
+ launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst( numDirections);
+ launcher.setConst( nPairs );
+ int num = nPairs;
+ launcher.launch1D( num);
+ clFinish(m_queue);
+
+ }
+ }
+ if (useMprGpu)
+ {
+ B3_PROFILE("findSeparatingAxisUnitSphereKernel");
+ b3BufferInfoCL bInfo[] = {
+ b3BufferInfoCL( pairs->getBufferCL(), true ),
+ b3BufferInfoCL( bodyBuf->getBufferCL(),true),
+ b3BufferInfoCL( gpuCollidables.getBufferCL(),true),
+ b3BufferInfoCL( convexData.getBufferCL(),true),
+ b3BufferInfoCL( gpuVertices.getBufferCL(),true),
+ b3BufferInfoCL( m_unitSphereDirections.getBufferCL(),true),
+ b3BufferInfoCL( m_sepNormals.getBufferCL()),
+ b3BufferInfoCL( m_hasSeparatingNormals.getBufferCL()),
+ b3BufferInfoCL( m_dmins.getBufferCL())
+ };
+
+ b3LauncherCL launcher(m_queue, m_findSeparatingAxisUnitSphereKernel,"findSeparatingAxisUnitSphereKernel");
+ launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ int numDirections = sizeof(unitSphere162)/sizeof(b3Vector3);
+ launcher.setConst( numDirections);
+
+ launcher.setConst( nPairs );
+
+ int num = nPairs;
+ launcher.launch1D( num);
+ clFinish(m_queue);
+ }
+ }
+
+
+ } else
+ {
+ B3_PROFILE("findSeparatingAxisKernel");
+ b3BufferInfoCL bInfo[] = {
+ b3BufferInfoCL( pairs->getBufferCL(), true ),
+ b3BufferInfoCL( bodyBuf->getBufferCL(),true),
+ b3BufferInfoCL( gpuCollidables.getBufferCL(),true),
+ b3BufferInfoCL( convexData.getBufferCL(),true),
+ b3BufferInfoCL( gpuVertices.getBufferCL(),true),
+ b3BufferInfoCL( gpuUniqueEdges.getBufferCL(),true),
+ b3BufferInfoCL( gpuFaces.getBufferCL(),true),
+ b3BufferInfoCL( gpuIndices.getBufferCL(),true),
+ b3BufferInfoCL( clAabbsWorldSpace.getBufferCL(),true),
+ b3BufferInfoCL( m_sepNormals.getBufferCL()),
+ b3BufferInfoCL( m_hasSeparatingNormals.getBufferCL())
+ };
+
+ b3LauncherCL launcher(m_queue, m_findSeparatingAxisKernel,"m_findSeparatingAxisKernel");
+ launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst( nPairs );
+
+ int num = nPairs;
+ launcher.launch1D( num);
+ clFinish(m_queue);
+ }
+
+
+ }
+ else
+ {
+
+ B3_PROFILE("findSeparatingAxisKernel CPU");
+
+
+ b3AlignedObjectArray<b3Int4> hostPairs;
+ pairs->copyToHost(hostPairs);
+ b3AlignedObjectArray<b3RigidBodyData> hostBodyBuf;
+ bodyBuf->copyToHost(hostBodyBuf);
+
+ b3AlignedObjectArray<b3Collidable> hostCollidables;
+ gpuCollidables.copyToHost(hostCollidables);
+
+ b3AlignedObjectArray<b3GpuChildShape> cpuChildShapes;
+ gpuChildShapes.copyToHost(cpuChildShapes);
+
+ b3AlignedObjectArray<b3ConvexPolyhedronData> hostConvexShapeData;
+ convexData.copyToHost(hostConvexShapeData);
+
+ b3AlignedObjectArray<b3Vector3> hostVertices;
+ gpuVertices.copyToHost(hostVertices);
+
+ b3AlignedObjectArray<int> hostHasSepAxis;
+ hostHasSepAxis.resize(nPairs);
+ b3AlignedObjectArray<b3Vector3> hostSepAxis;
+ hostSepAxis.resize(nPairs);
+
+ b3AlignedObjectArray<b3Vector3> hostUniqueEdges;
+ gpuUniqueEdges.copyToHost(hostUniqueEdges);
+ b3AlignedObjectArray<b3GpuFace> hostFaces;
+ gpuFaces.copyToHost(hostFaces);
+
+ b3AlignedObjectArray<int> hostIndices;
+ gpuIndices.copyToHost(hostIndices);
+
+ b3AlignedObjectArray<b3Contact4> hostContacts;
+ if (nContacts)
+ {
+ contactOut->copyToHost(hostContacts);
+ }
+ hostContacts.resize(maxContactCapacity);
+ int nGlobalContactsOut = nContacts;
+
+
+ for (int i=0;i<nPairs;i++)
+ {
+
+ int bodyIndexA = hostPairs[i].x;
+ int bodyIndexB = hostPairs[i].y;
+ int collidableIndexA = hostBodyBuf[bodyIndexA].m_collidableIdx;
+ int collidableIndexB = hostBodyBuf[bodyIndexB].m_collidableIdx;
+
+ int shapeIndexA = hostCollidables[collidableIndexA].m_shapeIndex;
+ int shapeIndexB = hostCollidables[collidableIndexB].m_shapeIndex;
+
+ hostHasSepAxis[i] = 0;
+
+ //once the broadphase avoids static-static pairs, we can remove this test
+ if ((hostBodyBuf[bodyIndexA].m_invMass==0) &&(hostBodyBuf[bodyIndexB].m_invMass==0))
+ {
+ continue;
+ }
+
+
+ if ((hostCollidables[collidableIndexA].m_shapeType!=SHAPE_CONVEX_HULL) ||(hostCollidables[collidableIndexB].m_shapeType!=SHAPE_CONVEX_HULL))
+ {
+ continue;
+ }
+
+ float dmin = FLT_MAX;
+
+ b3ConvexPolyhedronData* convexShapeA = &hostConvexShapeData[shapeIndexA];
+ b3ConvexPolyhedronData* convexShapeB = &hostConvexShapeData[shapeIndexB];
+ b3Vector3 posA = hostBodyBuf[bodyIndexA].m_pos;
+ b3Vector3 posB = hostBodyBuf[bodyIndexB].m_pos;
+ b3Quaternion ornA =hostBodyBuf[bodyIndexA].m_quat;
+ b3Quaternion ornB =hostBodyBuf[bodyIndexB].m_quat;
+
+
+ if (useGjk)
+ {
+
+ //first approximate the separating axis, to 'fail-proof' GJK+EPA or MPR
+ {
+ b3Vector3 c0local = hostConvexShapeData[shapeIndexA].m_localCenter;
+ b3Vector3 c0 = b3TransformPoint(c0local, posA, ornA);
+ b3Vector3 c1local = hostConvexShapeData[shapeIndexB].m_localCenter;
+ b3Vector3 c1 = b3TransformPoint(c1local,posB,ornB);
+ b3Vector3 DeltaC2 = c0 - c1;
+
+ b3Vector3 sepAxis;
+
+ bool hasSepAxisA = b3FindSeparatingAxis(convexShapeA, convexShapeB, posA, ornA, posB, ornB, DeltaC2,
+ &hostVertices.at(0), &hostUniqueEdges.at(0), &hostFaces.at(0), &hostIndices.at(0),
+ &hostVertices.at(0), &hostUniqueEdges.at(0), &hostFaces.at(0), &hostIndices.at(0),
+ &sepAxis, &dmin);
+
+ if (hasSepAxisA)
+ {
+ bool hasSepAxisB = b3FindSeparatingAxis(convexShapeB, convexShapeA, posB, ornB, posA, ornA, DeltaC2,
+ &hostVertices.at(0), &hostUniqueEdges.at(0), &hostFaces.at(0), &hostIndices.at(0),
+ &hostVertices.at(0), &hostUniqueEdges.at(0), &hostFaces.at(0), &hostIndices.at(0),
+ &sepAxis, &dmin);
+ if (hasSepAxisB)
+ {
+ bool hasEdgeEdge =b3FindSeparatingAxisEdgeEdge(convexShapeA, convexShapeB, posA, ornA, posB, ornB, DeltaC2,
+ &hostVertices.at(0), &hostUniqueEdges.at(0), &hostFaces.at(0), &hostIndices.at(0),
+ &hostVertices.at(0), &hostUniqueEdges.at(0), &hostFaces.at(0), &hostIndices.at(0),
+ &sepAxis, &dmin,false);
+
+ if (hasEdgeEdge)
+ {
+ hostHasSepAxis[i] = 1;
+ hostSepAxis[i] = sepAxis;
+ hostSepAxis[i].w = dmin;
+ }
+ }
+ }
+ }
+
+ if (hostHasSepAxis[i])
+ {
+ int pairIndex = i;
+
+ bool useMpr = true;
+ if (useMpr)
+ {
+ int res=0;
+ float depth = 0.f;
+ b3Vector3 sepAxis2 = b3MakeVector3(1,0,0);
+ b3Vector3 resultPointOnBWorld = b3MakeVector3(0,0,0);
+
+ float depthOut;
+ b3Vector3 dirOut;
+ b3Vector3 posOut;
+
+
+ //res = b3MprPenetration(bodyIndexA,bodyIndexB,hostBodyBuf,hostConvexShapeData,hostCollidables,hostVertices,&mprConfig,&depthOut,&dirOut,&posOut);
+ res = b3MprPenetration(pairIndex,bodyIndexA,bodyIndexB,&hostBodyBuf[0],&hostConvexShapeData[0],&hostCollidables[0],&hostVertices[0],&hostSepAxis[0],&hostHasSepAxis[0],&depthOut,&dirOut,&posOut);
+ depth = depthOut;
+ sepAxis2 = b3MakeVector3(-dirOut.x,-dirOut.y,-dirOut.z);
+ resultPointOnBWorld = posOut;
+ //hostHasSepAxis[i] = 0;
+
+
+ if (res==0)
+ {
+ //add point?
+ //printf("depth = %f\n",depth);
+ //printf("normal = %f,%f,%f\n",dir.v[0],dir.v[1],dir.v[2]);
+ //qprintf("pos = %f,%f,%f\n",pos.v[0],pos.v[1],pos.v[2]);
+
+
+
+ float dist=0.f;
+
+ const b3ConvexPolyhedronData& hullA = hostConvexShapeData[hostCollidables[hostBodyBuf[bodyIndexA].m_collidableIdx].m_shapeIndex];
+ const b3ConvexPolyhedronData& hullB = hostConvexShapeData[hostCollidables[hostBodyBuf[bodyIndexB].m_collidableIdx].m_shapeIndex];
+
+ if(b3TestSepAxis( &hullA, &hullB, posA,ornA,posB,ornB,&sepAxis2, &hostVertices[0], &hostVertices[0],&dist))
+ {
+ if (depth > dist)
+ {
+ float diff = depth - dist;
+
+ static float maxdiff = 0.f;
+ if (maxdiff < diff)
+ {
+ maxdiff = diff;
+ printf("maxdiff = %20.10f\n",maxdiff);
+ }
+ }
+ }
+ if (depth > dmin)
+ {
+ b3Vector3 oldAxis = hostSepAxis[i];
+ depth = dmin;
+ sepAxis2 = oldAxis;
+ }
+
+
+
+ if(b3TestSepAxis( &hullA, &hullB, posA,ornA,posB,ornB,&sepAxis2, &hostVertices[0], &hostVertices[0],&dist))
+ {
+ if (depth > dist)
+ {
+ float diff = depth - dist;
+ //printf("?diff = %f\n",diff );
+ static float maxdiff = 0.f;
+ if (maxdiff < diff)
+ {
+ maxdiff = diff;
+ printf("maxdiff = %20.10f\n",maxdiff);
+ }
+ }
+ //this is used for SAT
+ //hostHasSepAxis[i] = 1;
+ //hostSepAxis[i] = sepAxis2;
+
+ //add contact point
+
+ //int contactIndex = nGlobalContactsOut;
+ b3Contact4& newContact = hostContacts.at(nGlobalContactsOut);
+ nGlobalContactsOut++;
+ newContact.m_batchIdx = 0;//i;
+ newContact.m_bodyAPtrAndSignBit = (hostBodyBuf.at(bodyIndexA).m_invMass==0)? -bodyIndexA:bodyIndexA;
+ newContact.m_bodyBPtrAndSignBit = (hostBodyBuf.at(bodyIndexB).m_invMass==0)? -bodyIndexB:bodyIndexB;
+
+ newContact.m_frictionCoeffCmp = 45874;
+ newContact.m_restituitionCoeffCmp = 0;
+
+
+ static float maxDepth = 0.f;
+
+ if (depth > maxDepth)
+ {
+ maxDepth = depth;
+ printf("MPR maxdepth = %f\n",maxDepth );
+
+ }
+
+
+ resultPointOnBWorld.w = -depth;
+ newContact.m_worldPosB[0] = resultPointOnBWorld;
+ //b3Vector3 resultPointOnAWorld = resultPointOnBWorld+depth*sepAxis2;
+ newContact.m_worldNormalOnB = sepAxis2;
+ newContact.m_worldNormalOnB.w = (b3Scalar)1;
+ } else
+ {
+ printf("rejected\n");
+ }
+
+
+ }
+ } else
+ {
+
+
+
+ //int contactIndex = computeContactConvexConvex2( i,bodyIndexA,bodyIndexB,collidableIndexA,collidableIndexB,hostBodyBuf, hostCollidables,hostConvexData,hostVertices,hostUniqueEdges,hostIndices,hostFaces,hostContacts,nContacts,maxContactCapacity,oldHostContacts);
+ b3AlignedObjectArray<b3Contact4> oldHostContacts;
+ int result;
+ result = computeContactConvexConvex2( //hostPairs,
+ pairIndex,
+ bodyIndexA, bodyIndexB,
+ collidableIndexA, collidableIndexB,
+ hostBodyBuf,
+ hostCollidables,
+ hostConvexShapeData,
+ hostVertices,
+ hostUniqueEdges,
+ hostIndices,
+ hostFaces,
+ hostContacts,
+ nGlobalContactsOut,
+ maxContactCapacity,
+ oldHostContacts
+ //hostHasSepAxis,
+ //hostSepAxis
+
+ );
+ }//mpr
+ }//hostHasSepAxis[i] = 1;
+
+ } else
+ {
+
+ b3Vector3 c0local = hostConvexShapeData[shapeIndexA].m_localCenter;
+ b3Vector3 c0 = b3TransformPoint(c0local, posA, ornA);
+ b3Vector3 c1local = hostConvexShapeData[shapeIndexB].m_localCenter;
+ b3Vector3 c1 = b3TransformPoint(c1local,posB,ornB);
+ b3Vector3 DeltaC2 = c0 - c1;
+
+ b3Vector3 sepAxis;
+
+ bool hasSepAxisA = b3FindSeparatingAxis(convexShapeA, convexShapeB, posA, ornA, posB, ornB, DeltaC2,
+ &hostVertices.at(0), &hostUniqueEdges.at(0), &hostFaces.at(0), &hostIndices.at(0),
+ &hostVertices.at(0), &hostUniqueEdges.at(0), &hostFaces.at(0), &hostIndices.at(0),
+ &sepAxis, &dmin);
+
+ if (hasSepAxisA)
+ {
+ bool hasSepAxisB = b3FindSeparatingAxis(convexShapeB, convexShapeA, posB, ornB, posA, ornA, DeltaC2,
+ &hostVertices.at(0), &hostUniqueEdges.at(0), &hostFaces.at(0), &hostIndices.at(0),
+ &hostVertices.at(0), &hostUniqueEdges.at(0), &hostFaces.at(0), &hostIndices.at(0),
+ &sepAxis, &dmin);
+ if (hasSepAxisB)
+ {
+ bool hasEdgeEdge =b3FindSeparatingAxisEdgeEdge(convexShapeA, convexShapeB, posA, ornA, posB, ornB, DeltaC2,
+ &hostVertices.at(0), &hostUniqueEdges.at(0), &hostFaces.at(0), &hostIndices.at(0),
+ &hostVertices.at(0), &hostUniqueEdges.at(0), &hostFaces.at(0), &hostIndices.at(0),
+ &sepAxis, &dmin,true);
+
+ if (hasEdgeEdge)
+ {
+ hostHasSepAxis[i] = 1;
+ hostSepAxis[i] = sepAxis;
+ }
+ }
+ }
+ }
+ }
+
+ if (useGjkContacts)//nGlobalContactsOut>0)
+ {
+ //printf("nGlobalContactsOut=%d\n",nGlobalContactsOut);
+ nContacts = nGlobalContactsOut;
+ contactOut->copyFromHost(hostContacts);
+
+ m_totalContactsOut.copyFromHostPointer(&nContacts,1,0,true);
+ }
+
+ m_hasSeparatingNormals.copyFromHost(hostHasSepAxis);
+ m_sepNormals.copyFromHost(hostSepAxis);
+
+ /*
+ //double-check results from GPU (comment-out the 'else' so both paths are executed
+ b3AlignedObjectArray<int> checkHasSepAxis;
+ m_hasSeparatingNormals.copyToHost(checkHasSepAxis);
+ static int frameCount = 0;
+ frameCount++;
+ for (int i=0;i<nPairs;i++)
+ {
+ if (hostHasSepAxis[i] != checkHasSepAxis[i])
+ {
+ printf("at frameCount %d hostHasSepAxis[%d] = %d but checkHasSepAxis[i] = %d\n",
+ frameCount,i,hostHasSepAxis[i],checkHasSepAxis[i]);
+ }
+ }
+ //m_hasSeparatingNormals.copyFromHost(hostHasSepAxis);
+ // m_sepNormals.copyFromHost(hostSepAxis);
+ */
+ }
+
+
+ numCompoundPairs = m_numCompoundPairsOut.at(0);
+ bool useGpuFindCompoundPairs=true;
+ if (useGpuFindCompoundPairs)
+ {
+ B3_PROFILE("findCompoundPairsKernel");
+ b3BufferInfoCL bInfo[] =
+ {
+ b3BufferInfoCL( pairs->getBufferCL(), true ),
+ b3BufferInfoCL( bodyBuf->getBufferCL(),true),
+ b3BufferInfoCL( gpuCollidables.getBufferCL(),true),
+ b3BufferInfoCL( convexData.getBufferCL(),true),
+ b3BufferInfoCL( gpuVertices.getBufferCL(),true),
+ b3BufferInfoCL( gpuUniqueEdges.getBufferCL(),true),
+ b3BufferInfoCL( gpuFaces.getBufferCL(),true),
+ b3BufferInfoCL( gpuIndices.getBufferCL(),true),
+ b3BufferInfoCL( clAabbsLocalSpace.getBufferCL(),true),
+ b3BufferInfoCL( gpuChildShapes.getBufferCL(),true),
+ b3BufferInfoCL( m_gpuCompoundPairs.getBufferCL()),
+ b3BufferInfoCL( m_numCompoundPairsOut.getBufferCL()),
+ b3BufferInfoCL(subTreesGPU->getBufferCL()),
+ b3BufferInfoCL(treeNodesGPU->getBufferCL()),
+ b3BufferInfoCL(bvhInfo->getBufferCL())
+ };
+
+ b3LauncherCL launcher(m_queue, m_findCompoundPairsKernel,"m_findCompoundPairsKernel");
+ launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst( nPairs );
+ launcher.setConst( compoundPairCapacity);
+
+ int num = nPairs;
+ launcher.launch1D( num);
+ clFinish(m_queue);
+
+ numCompoundPairs = m_numCompoundPairsOut.at(0);
+ //printf("numCompoundPairs =%d\n",numCompoundPairs );
+ if (numCompoundPairs)
+ {
+ //printf("numCompoundPairs=%d\n",numCompoundPairs);
+ }
+
+
+ } else
+ {
+
+
+ b3AlignedObjectArray<b3QuantizedBvhNode> treeNodesCPU;
+ treeNodesGPU->copyToHost(treeNodesCPU);
+
+ b3AlignedObjectArray<b3BvhSubtreeInfo> subTreesCPU;
+ subTreesGPU->copyToHost(subTreesCPU);
+
+ b3AlignedObjectArray<b3BvhInfo> bvhInfoCPU;
+ bvhInfo->copyToHost(bvhInfoCPU);
+
+ b3AlignedObjectArray<b3Aabb> hostAabbsWorldSpace;
+ clAabbsWorldSpace.copyToHost(hostAabbsWorldSpace);
+
+ b3AlignedObjectArray<b3Aabb> hostAabbsLocalSpace;
+ clAabbsLocalSpace.copyToHost(hostAabbsLocalSpace);
+
+ b3AlignedObjectArray<b3Int4> hostPairs;
+ pairs->copyToHost(hostPairs);
+
+ b3AlignedObjectArray<b3RigidBodyData> hostBodyBuf;
+ bodyBuf->copyToHost(hostBodyBuf);
+
+
+ b3AlignedObjectArray<b3Int4> cpuCompoundPairsOut;
+ cpuCompoundPairsOut.resize(compoundPairCapacity);
+
+ b3AlignedObjectArray<b3Collidable> hostCollidables;
+ gpuCollidables.copyToHost(hostCollidables);
+
+ b3AlignedObjectArray<b3GpuChildShape> cpuChildShapes;
+ gpuChildShapes.copyToHost(cpuChildShapes);
+
+ b3AlignedObjectArray<b3ConvexPolyhedronData> hostConvexData;
+ convexData.copyToHost(hostConvexData);
+
+ b3AlignedObjectArray<b3Vector3> hostVertices;
+ gpuVertices.copyToHost(hostVertices);
+
+
+
+
+ for (int pairIndex=0;pairIndex<nPairs;pairIndex++)
+ {
+ int bodyIndexA = hostPairs[pairIndex].x;
+ int bodyIndexB = hostPairs[pairIndex].y;
+ int collidableIndexA = hostBodyBuf[bodyIndexA].m_collidableIdx;
+ int collidableIndexB = hostBodyBuf[bodyIndexB].m_collidableIdx;
+ if (cpuChildShapes.size())
+ {
+ findCompoundPairsKernel(
+ pairIndex,
+ bodyIndexA,
+ bodyIndexB,
+ collidableIndexA,
+ collidableIndexB,
+ &hostBodyBuf[0],
+ &hostCollidables[0],
+ &hostConvexData[0],
+ hostVertices,
+ hostAabbsWorldSpace,
+ hostAabbsLocalSpace,
+ &cpuChildShapes[0],
+ &cpuCompoundPairsOut[0],
+ &numCompoundPairs,
+ compoundPairCapacity,
+ treeNodesCPU,
+ subTreesCPU,
+ bvhInfoCPU
+ );
+ }
+ }
+
+
+ m_numCompoundPairsOut.copyFromHostPointer(&numCompoundPairs,1,0,true);
+ if (numCompoundPairs)
+ {
+ b3CompoundOverlappingPair* ptr = (b3CompoundOverlappingPair*)&cpuCompoundPairsOut[0];
+ m_gpuCompoundPairs.copyFromHostPointer(ptr,numCompoundPairs,0,true);
+ }
+ //cpuCompoundPairsOut
+
+ }
+ if (numCompoundPairs)
+ {
+ printf("numCompoundPairs=%d\n",numCompoundPairs);
+ }
+
+ if (numCompoundPairs > compoundPairCapacity)
+ {
+ b3Error("Exceeded compound pair capacity (%d/%d)\n", numCompoundPairs, compoundPairCapacity);
+ numCompoundPairs = compoundPairCapacity;
+ }
+
+
+
+ m_gpuCompoundPairs.resize(numCompoundPairs);
+ m_gpuHasCompoundSepNormals.resize(numCompoundPairs);
+ m_gpuCompoundSepNormals.resize(numCompoundPairs);
+
+
+ if (numCompoundPairs)
+ {
+ B3_PROFILE("processCompoundPairsPrimitivesKernel");
+ b3BufferInfoCL bInfo[] =
+ {
+ b3BufferInfoCL( m_gpuCompoundPairs.getBufferCL(), true ),
+ b3BufferInfoCL( bodyBuf->getBufferCL(),true),
+ b3BufferInfoCL( gpuCollidables.getBufferCL(),true),
+ b3BufferInfoCL( convexData.getBufferCL(),true),
+ b3BufferInfoCL( gpuVertices.getBufferCL(),true),
+ b3BufferInfoCL( gpuUniqueEdges.getBufferCL(),true),
+ b3BufferInfoCL( gpuFaces.getBufferCL(),true),
+ b3BufferInfoCL( gpuIndices.getBufferCL(),true),
+ b3BufferInfoCL( clAabbsWorldSpace.getBufferCL(),true),
+ b3BufferInfoCL( gpuChildShapes.getBufferCL(),true),
+ b3BufferInfoCL( contactOut->getBufferCL()),
+ b3BufferInfoCL( m_totalContactsOut.getBufferCL())
+ };
+
+ b3LauncherCL launcher(m_queue, m_processCompoundPairsPrimitivesKernel,"m_processCompoundPairsPrimitivesKernel");
+ launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst( numCompoundPairs );
+ launcher.setConst(maxContactCapacity);
+
+ int num = numCompoundPairs;
+ launcher.launch1D( num);
+ clFinish(m_queue);
+ nContacts = m_totalContactsOut.at(0);
+ //printf("nContacts (after processCompoundPairsPrimitivesKernel) = %d\n",nContacts);
+ if (nContacts>maxContactCapacity)
+ {
+
+ b3Error("Error: contacts exceeds capacity (%d/%d)\n", nContacts, maxContactCapacity);
+ nContacts = maxContactCapacity;
+ }
+ }
+
+
+ if (numCompoundPairs)
+ {
+ B3_PROFILE("processCompoundPairsKernel");
+ b3BufferInfoCL bInfo[] =
+ {
+ b3BufferInfoCL( m_gpuCompoundPairs.getBufferCL(), true ),
+ b3BufferInfoCL( bodyBuf->getBufferCL(),true),
+ b3BufferInfoCL( gpuCollidables.getBufferCL(),true),
+ b3BufferInfoCL( convexData.getBufferCL(),true),
+ b3BufferInfoCL( gpuVertices.getBufferCL(),true),
+ b3BufferInfoCL( gpuUniqueEdges.getBufferCL(),true),
+ b3BufferInfoCL( gpuFaces.getBufferCL(),true),
+ b3BufferInfoCL( gpuIndices.getBufferCL(),true),
+ b3BufferInfoCL( clAabbsWorldSpace.getBufferCL(),true),
+ b3BufferInfoCL( gpuChildShapes.getBufferCL(),true),
+ b3BufferInfoCL( m_gpuCompoundSepNormals.getBufferCL()),
+ b3BufferInfoCL( m_gpuHasCompoundSepNormals.getBufferCL())
+ };
+
+ b3LauncherCL launcher(m_queue, m_processCompoundPairsKernel,"m_processCompoundPairsKernel");
+ launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst( numCompoundPairs );
+
+ int num = numCompoundPairs;
+ launcher.launch1D( num);
+ clFinish(m_queue);
+
+ }
+
+
+ //printf("numConcave = %d\n",numConcave);
+
+
+
+// printf("hostNormals.size()=%d\n",hostNormals.size());
+ //int numPairs = pairCount.at(0);
+
+
+
+ }
+ int vertexFaceCapacity = 64;
+
+
+
+ {
+ //now perform the tree query on GPU
+
+
+
+
+ if (treeNodesGPU->size() && treeNodesGPU->size())
+ {
+ if (bvhTraversalKernelGPU)
+ {
+
+ B3_PROFILE("m_bvhTraversalKernel");
+
+
+ numConcavePairs = m_numConcavePairsOut.at(0);
+
+ b3LauncherCL launcher(m_queue, m_bvhTraversalKernel,"m_bvhTraversalKernel");
+ launcher.setBuffer( pairs->getBufferCL());
+ launcher.setBuffer( bodyBuf->getBufferCL());
+ launcher.setBuffer( gpuCollidables.getBufferCL());
+ launcher.setBuffer( clAabbsWorldSpace.getBufferCL());
+ launcher.setBuffer( triangleConvexPairsOut.getBufferCL());
+ launcher.setBuffer( m_numConcavePairsOut.getBufferCL());
+ launcher.setBuffer( subTreesGPU->getBufferCL());
+ launcher.setBuffer( treeNodesGPU->getBufferCL());
+ launcher.setBuffer( bvhInfo->getBufferCL());
+
+ launcher.setConst( nPairs );
+ launcher.setConst( maxTriConvexPairCapacity);
+ int num = nPairs;
+ launcher.launch1D( num);
+ clFinish(m_queue);
+ numConcavePairs = m_numConcavePairsOut.at(0);
+ } else
+ {
+ b3AlignedObjectArray<b3Int4> hostPairs;
+ pairs->copyToHost(hostPairs);
+ b3AlignedObjectArray<b3RigidBodyData> hostBodyBuf;
+ bodyBuf->copyToHost(hostBodyBuf);
+ b3AlignedObjectArray<b3Collidable> hostCollidables;
+ gpuCollidables.copyToHost(hostCollidables);
+ b3AlignedObjectArray<b3Aabb> hostAabbsWorldSpace;
+ clAabbsWorldSpace.copyToHost(hostAabbsWorldSpace);
+
+ //int maxTriConvexPairCapacity,
+ b3AlignedObjectArray<b3Int4> triangleConvexPairsOutHost;
+ triangleConvexPairsOutHost.resize(maxTriConvexPairCapacity);
+
+ //int numTriConvexPairsOutHost=0;
+ numConcavePairs = 0;
+ //m_numConcavePairsOut
+
+ b3AlignedObjectArray<b3QuantizedBvhNode> treeNodesCPU;
+ treeNodesGPU->copyToHost(treeNodesCPU);
+ b3AlignedObjectArray<b3BvhSubtreeInfo> subTreesCPU;
+ subTreesGPU->copyToHost(subTreesCPU);
+ b3AlignedObjectArray<b3BvhInfo> bvhInfoCPU;
+ bvhInfo->copyToHost(bvhInfoCPU);
+ //compute it...
+
+ volatile int hostNumConcavePairsOut=0;
+
+ //
+ for (int i=0;i<nPairs;i++)
+ {
+ b3BvhTraversal( &hostPairs.at(0),
+ &hostBodyBuf.at(0),
+ &hostCollidables.at(0),
+ &hostAabbsWorldSpace.at(0),
+ &triangleConvexPairsOutHost.at(0),
+ &hostNumConcavePairsOut,
+ &subTreesCPU.at(0),
+ &treeNodesCPU.at(0),
+ &bvhInfoCPU.at(0),
+ nPairs,
+ maxTriConvexPairCapacity,
+ i);
+ }
+ numConcavePairs = hostNumConcavePairsOut;
+
+ if (hostNumConcavePairsOut)
+ {
+ triangleConvexPairsOutHost.resize(hostNumConcavePairsOut);
+ triangleConvexPairsOut.copyFromHost(triangleConvexPairsOutHost);
+ }
+ //
+
+ m_numConcavePairsOut.resize(0);
+ m_numConcavePairsOut.push_back(numConcavePairs);
+ }
+
+ //printf("numConcavePairs=%d (max = %d\n",numConcavePairs,maxTriConvexPairCapacity);
+
+ if (numConcavePairs > maxTriConvexPairCapacity)
+ {
+ static int exceeded_maxTriConvexPairCapacity_count = 0;
+ b3Error("Exceeded the maxTriConvexPairCapacity (found %d but max is %d, it happened %d times)\n",
+ numConcavePairs,maxTriConvexPairCapacity,exceeded_maxTriConvexPairCapacity_count++);
+ numConcavePairs = maxTriConvexPairCapacity;
+ }
+ triangleConvexPairsOut.resize(numConcavePairs);
+
+ if (numConcavePairs)
+ {
+
+
+
+
+ clippingFacesOutGPU.resize(numConcavePairs);
+ worldNormalsAGPU.resize(numConcavePairs);
+ worldVertsA1GPU.resize(vertexFaceCapacity*(numConcavePairs));
+ worldVertsB1GPU.resize(vertexFaceCapacity*(numConcavePairs));
+
+
+ if (findConcaveSeparatingAxisKernelGPU)
+ {
+
+ /*
+ m_concaveHasSeparatingNormals.copyFromHost(concaveHasSeparatingNormalsCPU);
+ clippingFacesOutGPU.copyFromHost(clippingFacesOutCPU);
+ worldVertsA1GPU.copyFromHost(worldVertsA1CPU);
+ worldNormalsAGPU.copyFromHost(worldNormalsACPU);
+ worldVertsB1GPU.copyFromHost(worldVertsB1CPU);
+ */
+
+ //now perform a SAT test for each triangle-convex element (stored in triangleConvexPairsOut)
+ if (splitSearchSepAxisConcave)
+ {
+ //printf("numConcavePairs = %d\n",numConcavePairs);
+ m_dmins.resize(numConcavePairs);
+ {
+ B3_PROFILE("findConcaveSeparatingAxisVertexFaceKernel");
+ b3BufferInfoCL bInfo[] = {
+ b3BufferInfoCL( triangleConvexPairsOut.getBufferCL() ),
+ b3BufferInfoCL( bodyBuf->getBufferCL(),true),
+ b3BufferInfoCL( gpuCollidables.getBufferCL(),true),
+ b3BufferInfoCL( convexData.getBufferCL(),true),
+ b3BufferInfoCL( gpuVertices.getBufferCL(),true),
+ b3BufferInfoCL( gpuUniqueEdges.getBufferCL(),true),
+ b3BufferInfoCL( gpuFaces.getBufferCL(),true),
+ b3BufferInfoCL( gpuIndices.getBufferCL(),true),
+ b3BufferInfoCL( gpuChildShapes.getBufferCL(),true),
+ b3BufferInfoCL( clAabbsWorldSpace.getBufferCL(),true),
+ b3BufferInfoCL( m_concaveSepNormals.getBufferCL()),
+ b3BufferInfoCL( m_concaveHasSeparatingNormals.getBufferCL()),
+ b3BufferInfoCL( clippingFacesOutGPU.getBufferCL()),
+ b3BufferInfoCL( worldVertsA1GPU.getBufferCL()),
+ b3BufferInfoCL(worldNormalsAGPU.getBufferCL()),
+ b3BufferInfoCL(worldVertsB1GPU.getBufferCL()),
+ b3BufferInfoCL(m_dmins.getBufferCL())
+ };
+
+ b3LauncherCL launcher(m_queue, m_findConcaveSeparatingAxisVertexFaceKernel,"m_findConcaveSeparatingAxisVertexFaceKernel");
+ launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst(vertexFaceCapacity);
+ launcher.setConst( numConcavePairs );
+
+ int num = numConcavePairs;
+ launcher.launch1D( num);
+ clFinish(m_queue);
+
+
+ }
+// numConcavePairs = 0;
+ if (1)
+ {
+ B3_PROFILE("findConcaveSeparatingAxisEdgeEdgeKernel");
+ b3BufferInfoCL bInfo[] = {
+ b3BufferInfoCL( triangleConvexPairsOut.getBufferCL() ),
+ b3BufferInfoCL( bodyBuf->getBufferCL(),true),
+ b3BufferInfoCL( gpuCollidables.getBufferCL(),true),
+ b3BufferInfoCL( convexData.getBufferCL(),true),
+ b3BufferInfoCL( gpuVertices.getBufferCL(),true),
+ b3BufferInfoCL( gpuUniqueEdges.getBufferCL(),true),
+ b3BufferInfoCL( gpuFaces.getBufferCL(),true),
+ b3BufferInfoCL( gpuIndices.getBufferCL(),true),
+ b3BufferInfoCL( gpuChildShapes.getBufferCL(),true),
+ b3BufferInfoCL( clAabbsWorldSpace.getBufferCL(),true),
+ b3BufferInfoCL( m_concaveSepNormals.getBufferCL()),
+ b3BufferInfoCL( m_concaveHasSeparatingNormals.getBufferCL()),
+ b3BufferInfoCL( clippingFacesOutGPU.getBufferCL()),
+ b3BufferInfoCL( worldVertsA1GPU.getBufferCL()),
+ b3BufferInfoCL(worldNormalsAGPU.getBufferCL()),
+ b3BufferInfoCL(worldVertsB1GPU.getBufferCL()),
+ b3BufferInfoCL(m_dmins.getBufferCL())
+ };
+
+ b3LauncherCL launcher(m_queue, m_findConcaveSeparatingAxisEdgeEdgeKernel,"m_findConcaveSeparatingAxisEdgeEdgeKernel");
+ launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst(vertexFaceCapacity);
+ launcher.setConst( numConcavePairs );
+
+ int num = numConcavePairs;
+ launcher.launch1D( num);
+ clFinish(m_queue);
+ }
+
+
+ // numConcavePairs = 0;
+
+
+
+
+
+
+ } else
+ {
+ B3_PROFILE("findConcaveSeparatingAxisKernel");
+ b3BufferInfoCL bInfo[] = {
+ b3BufferInfoCL( triangleConvexPairsOut.getBufferCL() ),
+ b3BufferInfoCL( bodyBuf->getBufferCL(),true),
+ b3BufferInfoCL( gpuCollidables.getBufferCL(),true),
+ b3BufferInfoCL( convexData.getBufferCL(),true),
+ b3BufferInfoCL( gpuVertices.getBufferCL(),true),
+ b3BufferInfoCL( gpuUniqueEdges.getBufferCL(),true),
+ b3BufferInfoCL( gpuFaces.getBufferCL(),true),
+ b3BufferInfoCL( gpuIndices.getBufferCL(),true),
+ b3BufferInfoCL( gpuChildShapes.getBufferCL(),true),
+ b3BufferInfoCL( clAabbsWorldSpace.getBufferCL(),true),
+ b3BufferInfoCL( m_concaveSepNormals.getBufferCL()),
+ b3BufferInfoCL( m_concaveHasSeparatingNormals.getBufferCL()),
+ b3BufferInfoCL( clippingFacesOutGPU.getBufferCL()),
+ b3BufferInfoCL( worldVertsA1GPU.getBufferCL()),
+ b3BufferInfoCL(worldNormalsAGPU.getBufferCL()),
+ b3BufferInfoCL(worldVertsB1GPU.getBufferCL())
+ };
+
+ b3LauncherCL launcher(m_queue, m_findConcaveSeparatingAxisKernel,"m_findConcaveSeparatingAxisKernel");
+ launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst(vertexFaceCapacity);
+ launcher.setConst( numConcavePairs );
+
+ int num = numConcavePairs;
+ launcher.launch1D( num);
+ clFinish(m_queue);
+ }
+
+
+ } else
+ {
+
+ b3AlignedObjectArray<b3Int4> clippingFacesOutCPU;
+ b3AlignedObjectArray<b3Vector3> worldVertsA1CPU;
+ b3AlignedObjectArray<b3Vector3> worldNormalsACPU;
+ b3AlignedObjectArray<b3Vector3> worldVertsB1CPU;
+ b3AlignedObjectArray<int>concaveHasSeparatingNormalsCPU;
+
+ b3AlignedObjectArray<b3Int4> triangleConvexPairsOutHost;
+ triangleConvexPairsOut.copyToHost(triangleConvexPairsOutHost);
+ //triangleConvexPairsOutHost.resize(maxTriConvexPairCapacity);
+ b3AlignedObjectArray<b3RigidBodyData> hostBodyBuf;
+ bodyBuf->copyToHost(hostBodyBuf);
+ b3AlignedObjectArray<b3Collidable> hostCollidables;
+ gpuCollidables.copyToHost(hostCollidables);
+ b3AlignedObjectArray<b3Aabb> hostAabbsWorldSpace;
+ clAabbsWorldSpace.copyToHost(hostAabbsWorldSpace);
+
+ b3AlignedObjectArray<b3ConvexPolyhedronData> hostConvexData;
+ convexData.copyToHost(hostConvexData);
+
+ b3AlignedObjectArray<b3Vector3> hostVertices;
+ gpuVertices.copyToHost(hostVertices);
+
+ b3AlignedObjectArray<b3Vector3> hostUniqueEdges;
+ gpuUniqueEdges.copyToHost(hostUniqueEdges);
+ b3AlignedObjectArray<b3GpuFace> hostFaces;
+ gpuFaces.copyToHost(hostFaces);
+ b3AlignedObjectArray<int> hostIndices;
+ gpuIndices.copyToHost(hostIndices);
+ b3AlignedObjectArray<b3GpuChildShape> cpuChildShapes;
+ gpuChildShapes.copyToHost(cpuChildShapes);
+
+
+
+ b3AlignedObjectArray<b3Vector3> concaveSepNormalsHost;
+ m_concaveSepNormals.copyToHost(concaveSepNormalsHost);
+ concaveHasSeparatingNormalsCPU.resize(concaveSepNormalsHost.size());
+
+ b3GpuChildShape* childShapePointerCPU = 0;
+ if (cpuChildShapes.size())
+ childShapePointerCPU = &cpuChildShapes.at(0);
+
+ clippingFacesOutCPU.resize(clippingFacesOutGPU.size());
+ worldVertsA1CPU.resize(worldVertsA1GPU.size());
+ worldNormalsACPU.resize(worldNormalsAGPU.size());
+ worldVertsB1CPU.resize(worldVertsB1GPU.size());
+
+ for (int i=0;i<numConcavePairs;i++)
+ {
+ b3FindConcaveSeparatingAxisKernel(&triangleConvexPairsOutHost.at(0),
+ &hostBodyBuf.at(0),
+ &hostCollidables.at(0),
+ &hostConvexData.at(0), &hostVertices.at(0),&hostUniqueEdges.at(0),
+ &hostFaces.at(0),&hostIndices.at(0),childShapePointerCPU,
+ &hostAabbsWorldSpace.at(0),
+ &concaveSepNormalsHost.at(0),
+ &clippingFacesOutCPU.at(0),
+ &worldVertsA1CPU.at(0),
+ &worldNormalsACPU.at(0),
+ &worldVertsB1CPU.at(0),
+ &concaveHasSeparatingNormalsCPU.at(0),
+ vertexFaceCapacity,
+ numConcavePairs,i);
+ };
+
+ m_concaveSepNormals.copyFromHost(concaveSepNormalsHost);
+ m_concaveHasSeparatingNormals.copyFromHost(concaveHasSeparatingNormalsCPU);
+ clippingFacesOutGPU.copyFromHost(clippingFacesOutCPU);
+ worldVertsA1GPU.copyFromHost(worldVertsA1CPU);
+ worldNormalsAGPU.copyFromHost(worldNormalsACPU);
+ worldVertsB1GPU.copyFromHost(worldVertsB1CPU);
+
+
+
+ }
+// b3AlignedObjectArray<b3Vector3> cpuCompoundSepNormals;
+// m_concaveSepNormals.copyToHost(cpuCompoundSepNormals);
+// b3AlignedObjectArray<b3Int4> cpuConcavePairs;
+// triangleConvexPairsOut.copyToHost(cpuConcavePairs);
+
+
+ }
+ }
+
+
+ }
+
+ if (numConcavePairs)
+ {
+ if (numConcavePairs)
+ {
+ B3_PROFILE("findConcaveSphereContactsKernel");
+ nContacts = m_totalContactsOut.at(0);
+// printf("nContacts1 = %d\n",nContacts);
+ b3BufferInfoCL bInfo[] = {
+ b3BufferInfoCL( triangleConvexPairsOut.getBufferCL() ),
+ b3BufferInfoCL( bodyBuf->getBufferCL(),true),
+ b3BufferInfoCL( gpuCollidables.getBufferCL(),true),
+ b3BufferInfoCL( convexData.getBufferCL(),true),
+ b3BufferInfoCL( gpuVertices.getBufferCL(),true),
+ b3BufferInfoCL( gpuUniqueEdges.getBufferCL(),true),
+ b3BufferInfoCL( gpuFaces.getBufferCL(),true),
+ b3BufferInfoCL( gpuIndices.getBufferCL(),true),
+ b3BufferInfoCL( clAabbsWorldSpace.getBufferCL(),true),
+ b3BufferInfoCL( contactOut->getBufferCL()),
+ b3BufferInfoCL( m_totalContactsOut.getBufferCL())
+ };
+
+ b3LauncherCL launcher(m_queue, m_findConcaveSphereContactsKernel,"m_findConcaveSphereContactsKernel");
+ launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+
+ launcher.setConst( numConcavePairs );
+ launcher.setConst(maxContactCapacity);
+
+ int num = numConcavePairs;
+ launcher.launch1D( num);
+ clFinish(m_queue);
+ nContacts = m_totalContactsOut.at(0);
+ //printf("nContacts (after findConcaveSphereContactsKernel) = %d\n",nContacts);
+
+ //printf("nContacts2 = %d\n",nContacts);
+
+ if (nContacts >= maxContactCapacity)
+ {
+ b3Error("Error: contacts exceeds capacity (%d/%d)\n", nContacts, maxContactCapacity);
+ nContacts = maxContactCapacity;
+ }
+ }
+
+ }
+
+
+
+#ifdef __APPLE__
+ bool contactClippingOnGpu = true;
+#else
+ bool contactClippingOnGpu = true;
+#endif
+
+ if (contactClippingOnGpu)
+ {
+ m_totalContactsOut.copyFromHostPointer(&nContacts,1,0,true);
+// printf("nContacts3 = %d\n",nContacts);
+
+
+ //B3_PROFILE("clipHullHullKernel");
+
+ bool breakupConcaveConvexKernel = true;
+
+#ifdef __APPLE__
+ //actually, some Apple OpenCL platform/device combinations work fine...
+ breakupConcaveConvexKernel = true;
+#endif
+ //concave-convex contact clipping
+ if (numConcavePairs)
+ {
+ // printf("numConcavePairs = %d\n", numConcavePairs);
+ // nContacts = m_totalContactsOut.at(0);
+ // printf("nContacts before = %d\n", nContacts);
+
+ if (breakupConcaveConvexKernel)
+ {
+
+ worldVertsB2GPU.resize(vertexFaceCapacity*numConcavePairs);
+
+
+ //clipFacesAndFindContacts
+
+ if (clipConcaveFacesAndFindContactsCPU)
+ {
+
+ b3AlignedObjectArray<b3Int4> clippingFacesOutCPU;
+ b3AlignedObjectArray<b3Vector3> worldVertsA1CPU;
+ b3AlignedObjectArray<b3Vector3> worldNormalsACPU;
+ b3AlignedObjectArray<b3Vector3> worldVertsB1CPU;
+
+ clippingFacesOutGPU.copyToHost(clippingFacesOutCPU);
+ worldVertsA1GPU.copyToHost(worldVertsA1CPU);
+ worldNormalsAGPU.copyToHost(worldNormalsACPU);
+ worldVertsB1GPU.copyToHost(worldVertsB1CPU);
+
+
+
+ b3AlignedObjectArray<int>concaveHasSeparatingNormalsCPU;
+ m_concaveHasSeparatingNormals.copyToHost(concaveHasSeparatingNormalsCPU);
+
+ b3AlignedObjectArray<b3Vector3> concaveSepNormalsHost;
+ m_concaveSepNormals.copyToHost(concaveSepNormalsHost);
+
+ b3AlignedObjectArray<b3Vector3> worldVertsB2CPU;
+ worldVertsB2CPU.resize(worldVertsB2GPU.size());
+
+
+ for (int i=0;i<numConcavePairs;i++)
+ {
+
+ clipFacesAndFindContactsKernel( &concaveSepNormalsHost.at(0),
+ &concaveHasSeparatingNormalsCPU.at(0),
+ &clippingFacesOutCPU.at(0),
+ &worldVertsA1CPU.at(0),
+ &worldNormalsACPU.at(0),
+ &worldVertsB1CPU.at(0),
+ &worldVertsB2CPU.at(0),
+ vertexFaceCapacity,
+ i);
+ }
+
+ clippingFacesOutGPU.copyFromHost(clippingFacesOutCPU);
+ worldVertsB2GPU.copyFromHost(worldVertsB2CPU);
+
+
+ } else
+ {
+
+ if (1)
+ {
+
+
+
+ B3_PROFILE("clipFacesAndFindContacts");
+ //nContacts = m_totalContactsOut.at(0);
+ //int h = m_hasSeparatingNormals.at(0);
+ //int4 p = clippingFacesOutGPU.at(0);
+ b3BufferInfoCL bInfo[] = {
+ b3BufferInfoCL( m_concaveSepNormals.getBufferCL()),
+ b3BufferInfoCL( m_concaveHasSeparatingNormals.getBufferCL()),
+ b3BufferInfoCL( clippingFacesOutGPU.getBufferCL()),
+ b3BufferInfoCL( worldVertsA1GPU.getBufferCL()),
+ b3BufferInfoCL( worldNormalsAGPU.getBufferCL()),
+ b3BufferInfoCL( worldVertsB1GPU.getBufferCL()),
+ b3BufferInfoCL( worldVertsB2GPU.getBufferCL())
+ };
+ b3LauncherCL launcher(m_queue, m_clipFacesAndFindContacts,"m_clipFacesAndFindContacts");
+ launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst(vertexFaceCapacity);
+
+ launcher.setConst( numConcavePairs );
+ int debugMode = 0;
+ launcher.setConst( debugMode);
+ int num = numConcavePairs;
+ launcher.launch1D( num);
+ clFinish(m_queue);
+ //int bla = m_totalContactsOut.at(0);
+ }
+ }
+ //contactReduction
+ {
+ int newContactCapacity=nContacts+numConcavePairs;
+ contactOut->reserve(newContactCapacity);
+ if (reduceConcaveContactsOnGPU)
+ {
+// printf("newReservation = %d\n",newReservation);
+ {
+ B3_PROFILE("newContactReductionKernel");
+ b3BufferInfoCL bInfo[] =
+ {
+ b3BufferInfoCL( triangleConvexPairsOut.getBufferCL(), true ),
+ b3BufferInfoCL( bodyBuf->getBufferCL(),true),
+ b3BufferInfoCL( m_concaveSepNormals.getBufferCL()),
+ b3BufferInfoCL( m_concaveHasSeparatingNormals.getBufferCL()),
+ b3BufferInfoCL( contactOut->getBufferCL()),
+ b3BufferInfoCL( clippingFacesOutGPU.getBufferCL()),
+ b3BufferInfoCL( worldVertsB2GPU.getBufferCL()),
+ b3BufferInfoCL( m_totalContactsOut.getBufferCL())
+ };
+
+ b3LauncherCL launcher(m_queue, m_newContactReductionKernel,"m_newContactReductionKernel");
+ launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst(vertexFaceCapacity);
+ launcher.setConst(newContactCapacity);
+ launcher.setConst( numConcavePairs );
+ int num = numConcavePairs;
+
+ launcher.launch1D( num);
+ }
+ nContacts = m_totalContactsOut.at(0);
+ contactOut->resize(nContacts);
+
+ //printf("contactOut4 (after newContactReductionKernel) = %d\n",nContacts);
+ }else
+ {
+
+ volatile int nGlobalContactsOut = nContacts;
+ b3AlignedObjectArray<b3Int4> triangleConvexPairsOutHost;
+ triangleConvexPairsOut.copyToHost(triangleConvexPairsOutHost);
+ b3AlignedObjectArray<b3RigidBodyData> hostBodyBuf;
+ bodyBuf->copyToHost(hostBodyBuf);
+
+ b3AlignedObjectArray<int>concaveHasSeparatingNormalsCPU;
+ m_concaveHasSeparatingNormals.copyToHost(concaveHasSeparatingNormalsCPU);
+
+ b3AlignedObjectArray<b3Vector3> concaveSepNormalsHost;
+ m_concaveSepNormals.copyToHost(concaveSepNormalsHost);
+
+
+ b3AlignedObjectArray<b3Contact4> hostContacts;
+ if (nContacts)
+ {
+ contactOut->copyToHost(hostContacts);
+ }
+ hostContacts.resize(newContactCapacity);
+
+ b3AlignedObjectArray<b3Int4> clippingFacesOutCPU;
+ b3AlignedObjectArray<b3Vector3> worldVertsB2CPU;
+
+ clippingFacesOutGPU.copyToHost(clippingFacesOutCPU);
+ worldVertsB2GPU.copyToHost(worldVertsB2CPU);
+
+
+
+ for (int i=0;i<numConcavePairs;i++)
+ {
+ b3NewContactReductionKernel( &triangleConvexPairsOutHost.at(0),
+ &hostBodyBuf.at(0),
+ &concaveSepNormalsHost.at(0),
+ &concaveHasSeparatingNormalsCPU.at(0),
+ &hostContacts.at(0),
+ &clippingFacesOutCPU.at(0),
+ &worldVertsB2CPU.at(0),
+ &nGlobalContactsOut,
+ vertexFaceCapacity,
+ newContactCapacity,
+ numConcavePairs,
+ i
+ );
+
+ }
+
+
+ nContacts = nGlobalContactsOut;
+ m_totalContactsOut.copyFromHostPointer(&nContacts,1,0,true);
+// nContacts = m_totalContactsOut.at(0);
+ //contactOut->resize(nContacts);
+ hostContacts.resize(nContacts);
+ //printf("contactOut4 (after newContactReductionKernel) = %d\n",nContacts);
+ contactOut->copyFromHost(hostContacts);
+ }
+
+ }
+ //re-use?
+
+
+ } else
+ {
+ B3_PROFILE("clipHullHullConcaveConvexKernel");
+ nContacts = m_totalContactsOut.at(0);
+ int newContactCapacity = contactOut->capacity();
+
+ //printf("contactOut5 = %d\n",nContacts);
+ b3BufferInfoCL bInfo[] = {
+ b3BufferInfoCL( triangleConvexPairsOut.getBufferCL(), true ),
+ b3BufferInfoCL( bodyBuf->getBufferCL(),true),
+ b3BufferInfoCL( gpuCollidables.getBufferCL(),true),
+ b3BufferInfoCL( convexData.getBufferCL(),true),
+ b3BufferInfoCL( gpuVertices.getBufferCL(),true),
+ b3BufferInfoCL( gpuUniqueEdges.getBufferCL(),true),
+ b3BufferInfoCL( gpuFaces.getBufferCL(),true),
+ b3BufferInfoCL( gpuIndices.getBufferCL(),true),
+ b3BufferInfoCL( gpuChildShapes.getBufferCL(),true),
+ b3BufferInfoCL( m_concaveSepNormals.getBufferCL()),
+ b3BufferInfoCL( contactOut->getBufferCL()),
+ b3BufferInfoCL( m_totalContactsOut.getBufferCL())
+ };
+ b3LauncherCL launcher(m_queue, m_clipHullHullConcaveConvexKernel,"m_clipHullHullConcaveConvexKernel");
+ launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst(newContactCapacity);
+ launcher.setConst( numConcavePairs );
+ int num = numConcavePairs;
+ launcher.launch1D( num);
+ clFinish(m_queue);
+ nContacts = m_totalContactsOut.at(0);
+ contactOut->resize(nContacts);
+ //printf("contactOut6 = %d\n",nContacts);
+ b3AlignedObjectArray<b3Contact4> cpuContacts;
+ contactOut->copyToHost(cpuContacts);
+ }
+ // printf("nContacts after = %d\n", nContacts);
+ }//numConcavePairs
+
+
+
+ //convex-convex contact clipping
+
+ bool breakupKernel = false;
+
+#ifdef __APPLE__
+ breakupKernel = true;
+#endif
+
+#ifdef CHECK_ON_HOST
+ bool computeConvexConvex = false;
+#else
+ bool computeConvexConvex = true;
+#endif//CHECK_ON_HOST
+ if (computeConvexConvex)
+ {
+ B3_PROFILE("clipHullHullKernel");
+ if (breakupKernel)
+ {
+
+
+
+
+ worldVertsB1GPU.resize(vertexFaceCapacity*nPairs);
+ clippingFacesOutGPU.resize(nPairs);
+ worldNormalsAGPU.resize(nPairs);
+ worldVertsA1GPU.resize(vertexFaceCapacity*nPairs);
+ worldVertsB2GPU.resize(vertexFaceCapacity*nPairs);
+
+ if (findConvexClippingFacesGPU)
+ {
+ B3_PROFILE("findClippingFacesKernel");
+ b3BufferInfoCL bInfo[] = {
+ b3BufferInfoCL( pairs->getBufferCL(), true ),
+ b3BufferInfoCL( bodyBuf->getBufferCL(),true),
+ b3BufferInfoCL( gpuCollidables.getBufferCL(),true),
+ b3BufferInfoCL( convexData.getBufferCL(),true),
+ b3BufferInfoCL( gpuVertices.getBufferCL(),true),
+ b3BufferInfoCL( gpuUniqueEdges.getBufferCL(),true),
+ b3BufferInfoCL( gpuFaces.getBufferCL(),true),
+ b3BufferInfoCL( gpuIndices.getBufferCL(),true),
+ b3BufferInfoCL( m_sepNormals.getBufferCL()),
+ b3BufferInfoCL( m_hasSeparatingNormals.getBufferCL()),
+ b3BufferInfoCL( clippingFacesOutGPU.getBufferCL()),
+ b3BufferInfoCL( worldVertsA1GPU.getBufferCL()),
+ b3BufferInfoCL( worldNormalsAGPU.getBufferCL()),
+ b3BufferInfoCL( worldVertsB1GPU.getBufferCL())
+ };
+
+ b3LauncherCL launcher(m_queue, m_findClippingFacesKernel,"m_findClippingFacesKernel");
+ launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst( vertexFaceCapacity);
+ launcher.setConst( nPairs );
+ int num = nPairs;
+ launcher.launch1D( num);
+ clFinish(m_queue);
+
+ } else
+ {
+
+ float minDist = -1e30f;
+ float maxDist = 0.02f;
+
+ b3AlignedObjectArray<b3ConvexPolyhedronData> hostConvexData;
+ convexData.copyToHost(hostConvexData);
+ b3AlignedObjectArray<b3Collidable> hostCollidables;
+ gpuCollidables.copyToHost(hostCollidables);
+
+ b3AlignedObjectArray<int> hostHasSepNormals;
+ m_hasSeparatingNormals.copyToHost(hostHasSepNormals);
+ b3AlignedObjectArray<b3Vector3> cpuSepNormals;
+ m_sepNormals.copyToHost(cpuSepNormals);
+
+ b3AlignedObjectArray<b3Int4> hostPairs;
+ pairs->copyToHost(hostPairs);
+ b3AlignedObjectArray<b3RigidBodyData> hostBodyBuf;
+ bodyBuf->copyToHost(hostBodyBuf);
+
+
+ //worldVertsB1GPU.resize(vertexFaceCapacity*nPairs);
+ b3AlignedObjectArray<b3Vector3> worldVertsB1CPU;
+ worldVertsB1GPU.copyToHost(worldVertsB1CPU);
+
+ b3AlignedObjectArray<b3Int4> clippingFacesOutCPU;
+ clippingFacesOutGPU.copyToHost(clippingFacesOutCPU);
+
+ b3AlignedObjectArray<b3Vector3> worldNormalsACPU;
+ worldNormalsACPU.resize(nPairs);
+
+ b3AlignedObjectArray<b3Vector3> worldVertsA1CPU;
+ worldVertsA1CPU.resize(worldVertsA1GPU.size());
+
+
+ b3AlignedObjectArray<b3Vector3> hostVertices;
+ gpuVertices.copyToHost(hostVertices);
+ b3AlignedObjectArray<b3GpuFace> hostFaces;
+ gpuFaces.copyToHost(hostFaces);
+ b3AlignedObjectArray<int> hostIndices;
+ gpuIndices.copyToHost(hostIndices);
+
+
+ for (int i=0;i<nPairs;i++)
+ {
+
+ int bodyIndexA = hostPairs[i].x;
+ int bodyIndexB = hostPairs[i].y;
+
+ int collidableIndexA = hostBodyBuf[bodyIndexA].m_collidableIdx;
+ int collidableIndexB = hostBodyBuf[bodyIndexB].m_collidableIdx;
+
+ int shapeIndexA = hostCollidables[collidableIndexA].m_shapeIndex;
+ int shapeIndexB = hostCollidables[collidableIndexB].m_shapeIndex;
+
+
+ if (hostHasSepNormals[i])
+ {
+ b3FindClippingFaces(cpuSepNormals[i],
+ &hostConvexData[shapeIndexA],
+ &hostConvexData[shapeIndexB],
+ hostBodyBuf[bodyIndexA].m_pos,hostBodyBuf[bodyIndexA].m_quat,
+ hostBodyBuf[bodyIndexB].m_pos,hostBodyBuf[bodyIndexB].m_quat,
+ &worldVertsA1CPU.at(0),&worldNormalsACPU.at(0),
+ &worldVertsB1CPU.at(0),
+ vertexFaceCapacity,minDist,maxDist,
+ &hostVertices.at(0),&hostFaces.at(0),
+ &hostIndices.at(0),
+ &hostVertices.at(0),&hostFaces.at(0),
+ &hostIndices.at(0),&clippingFacesOutCPU.at(0),i);
+ }
+ }
+
+ clippingFacesOutGPU.copyFromHost(clippingFacesOutCPU);
+ worldVertsA1GPU.copyFromHost(worldVertsA1CPU);
+ worldNormalsAGPU.copyFromHost(worldNormalsACPU);
+ worldVertsB1GPU.copyFromHost(worldVertsB1CPU);
+
+ }
+
+
+
+
+
+ ///clip face B against face A, reduce contacts and append them to a global contact array
+ if (1)
+ {
+ if (clipConvexFacesAndFindContactsCPU)
+ {
+
+ //b3AlignedObjectArray<b3Int4> hostPairs;
+ //pairs->copyToHost(hostPairs);
+
+ b3AlignedObjectArray<b3Vector3> hostSepNormals;
+ m_sepNormals.copyToHost(hostSepNormals);
+ b3AlignedObjectArray<int> hostHasSepAxis;
+ m_hasSeparatingNormals.copyToHost(hostHasSepAxis);
+
+ b3AlignedObjectArray<b3Int4> hostClippingFaces;
+ clippingFacesOutGPU.copyToHost(hostClippingFaces);
+ b3AlignedObjectArray<b3Vector3> worldVertsB2CPU;
+ worldVertsB2CPU.resize(vertexFaceCapacity*nPairs);
+
+ b3AlignedObjectArray<b3Vector3>worldVertsA1CPU;
+ worldVertsA1GPU.copyToHost(worldVertsA1CPU);
+ b3AlignedObjectArray<b3Vector3> worldNormalsACPU;
+ worldNormalsAGPU.copyToHost(worldNormalsACPU);
+
+ b3AlignedObjectArray<b3Vector3> worldVertsB1CPU;
+ worldVertsB1GPU.copyToHost(worldVertsB1CPU);
+
+ /*
+ __global const b3Float4* separatingNormals,
+ __global const int* hasSeparatingAxis,
+ __global b3Int4* clippingFacesOut,
+ __global b3Float4* worldVertsA1,
+ __global b3Float4* worldNormalsA1,
+ __global b3Float4* worldVertsB1,
+ __global b3Float4* worldVertsB2,
+ int vertexFaceCapacity,
+ int pairIndex
+ */
+ for (int i=0;i<nPairs;i++)
+ {
+ clipFacesAndFindContactsKernel(
+ &hostSepNormals.at(0),
+ &hostHasSepAxis.at(0),
+ &hostClippingFaces.at(0),
+ &worldVertsA1CPU.at(0),
+ &worldNormalsACPU.at(0),
+ &worldVertsB1CPU.at(0),
+ &worldVertsB2CPU.at(0),
+
+ vertexFaceCapacity,
+ i);
+ }
+
+ clippingFacesOutGPU.copyFromHost(hostClippingFaces);
+ worldVertsB2GPU.copyFromHost(worldVertsB2CPU);
+
+ } else
+ {
+ B3_PROFILE("clipFacesAndFindContacts");
+ //nContacts = m_totalContactsOut.at(0);
+ //int h = m_hasSeparatingNormals.at(0);
+ //int4 p = clippingFacesOutGPU.at(0);
+ b3BufferInfoCL bInfo[] = {
+ b3BufferInfoCL( m_sepNormals.getBufferCL()),
+ b3BufferInfoCL( m_hasSeparatingNormals.getBufferCL()),
+ b3BufferInfoCL( clippingFacesOutGPU.getBufferCL()),
+ b3BufferInfoCL( worldVertsA1GPU.getBufferCL()),
+ b3BufferInfoCL( worldNormalsAGPU.getBufferCL()),
+ b3BufferInfoCL( worldVertsB1GPU.getBufferCL()),
+ b3BufferInfoCL( worldVertsB2GPU.getBufferCL())
+ };
+
+ b3LauncherCL launcher(m_queue, m_clipFacesAndFindContacts,"m_clipFacesAndFindContacts");
+ launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst(vertexFaceCapacity);
+
+ launcher.setConst( nPairs );
+ int debugMode = 0;
+ launcher.setConst( debugMode);
+ int num = nPairs;
+ launcher.launch1D( num);
+ clFinish(m_queue);
+ }
+
+ {
+ nContacts = m_totalContactsOut.at(0);
+ //printf("nContacts = %d\n",nContacts);
+
+ int newContactCapacity = nContacts+nPairs;
+ contactOut->reserve(newContactCapacity);
+
+ if (reduceConvexContactsOnGPU)
+ {
+ {
+ B3_PROFILE("newContactReductionKernel");
+ b3BufferInfoCL bInfo[] =
+ {
+ b3BufferInfoCL( pairs->getBufferCL(), true ),
+ b3BufferInfoCL( bodyBuf->getBufferCL(),true),
+ b3BufferInfoCL( m_sepNormals.getBufferCL()),
+ b3BufferInfoCL( m_hasSeparatingNormals.getBufferCL()),
+ b3BufferInfoCL( contactOut->getBufferCL()),
+ b3BufferInfoCL( clippingFacesOutGPU.getBufferCL()),
+ b3BufferInfoCL( worldVertsB2GPU.getBufferCL()),
+ b3BufferInfoCL( m_totalContactsOut.getBufferCL())
+ };
+
+ b3LauncherCL launcher(m_queue, m_newContactReductionKernel,"m_newContactReductionKernel");
+ launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst(vertexFaceCapacity);
+ launcher.setConst(newContactCapacity);
+ launcher.setConst( nPairs );
+ int num = nPairs;
+
+ launcher.launch1D( num);
+ }
+ nContacts = m_totalContactsOut.at(0);
+ contactOut->resize(nContacts);
+ } else
+ {
+
+ volatile int nGlobalContactsOut = nContacts;
+ b3AlignedObjectArray<b3Int4> hostPairs;
+ pairs->copyToHost(hostPairs);
+ b3AlignedObjectArray<b3RigidBodyData> hostBodyBuf;
+ bodyBuf->copyToHost(hostBodyBuf);
+ b3AlignedObjectArray<b3Vector3> hostSepNormals;
+ m_sepNormals.copyToHost(hostSepNormals);
+ b3AlignedObjectArray<int> hostHasSepAxis;
+ m_hasSeparatingNormals.copyToHost(hostHasSepAxis);
+ b3AlignedObjectArray<b3Contact4> hostContactsOut;
+ contactOut->copyToHost(hostContactsOut);
+ hostContactsOut.resize(newContactCapacity);
+
+ b3AlignedObjectArray<b3Int4> hostClippingFaces;
+ clippingFacesOutGPU.copyToHost(hostClippingFaces);
+ b3AlignedObjectArray<b3Vector3> worldVertsB2CPU;
+ worldVertsB2GPU.copyToHost(worldVertsB2CPU);
+
+ for (int i=0;i<nPairs;i++)
+ {
+ b3NewContactReductionKernel(&hostPairs.at(0),
+ &hostBodyBuf.at(0),
+ &hostSepNormals.at(0),
+ &hostHasSepAxis.at(0),
+ &hostContactsOut.at(0),
+ &hostClippingFaces.at(0),
+ &worldVertsB2CPU.at(0),
+ &nGlobalContactsOut,
+ vertexFaceCapacity,
+ newContactCapacity,
+ nPairs,
+ i);
+ }
+
+ nContacts = nGlobalContactsOut;
+ m_totalContactsOut.copyFromHostPointer(&nContacts,1,0,true);
+ hostContactsOut.resize(nContacts);
+ //printf("contactOut4 (after newContactReductionKernel) = %d\n",nContacts);
+ contactOut->copyFromHost(hostContactsOut);
+ }
+ // b3Contact4 pt = contactOut->at(0);
+ // printf("nContacts = %d\n",nContacts);
+ }
+ }
+ }
+ else//breakupKernel
+ {
+
+ if (nPairs)
+ {
+ b3BufferInfoCL bInfo[] = {
+ b3BufferInfoCL( pairs->getBufferCL(), true ),
+ b3BufferInfoCL( bodyBuf->getBufferCL(),true),
+ b3BufferInfoCL( gpuCollidables.getBufferCL(),true),
+ b3BufferInfoCL( convexData.getBufferCL(),true),
+ b3BufferInfoCL( gpuVertices.getBufferCL(),true),
+ b3BufferInfoCL( gpuUniqueEdges.getBufferCL(),true),
+ b3BufferInfoCL( gpuFaces.getBufferCL(),true),
+ b3BufferInfoCL( gpuIndices.getBufferCL(),true),
+ b3BufferInfoCL( m_sepNormals.getBufferCL()),
+ b3BufferInfoCL( m_hasSeparatingNormals.getBufferCL()),
+ b3BufferInfoCL( contactOut->getBufferCL()),
+ b3BufferInfoCL( m_totalContactsOut.getBufferCL())
+ };
+ b3LauncherCL launcher(m_queue, m_clipHullHullKernel,"m_clipHullHullKernel");
+ launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst( nPairs );
+ launcher.setConst(maxContactCapacity);
+
+ int num = nPairs;
+ launcher.launch1D( num);
+ clFinish(m_queue);
+
+ nContacts = m_totalContactsOut.at(0);
+ if (nContacts >= maxContactCapacity)
+ {
+ b3Error("Exceeded contact capacity (%d/%d)\n",nContacts,maxContactCapacity);
+ nContacts = maxContactCapacity;
+ }
+ contactOut->resize(nContacts);
+ }
+ }
+
+
+ int nCompoundsPairs = m_gpuCompoundPairs.size();
+
+ if (nCompoundsPairs)
+ {
+ b3BufferInfoCL bInfo[] = {
+ b3BufferInfoCL( m_gpuCompoundPairs.getBufferCL(), true ),
+ b3BufferInfoCL( bodyBuf->getBufferCL(),true),
+ b3BufferInfoCL( gpuCollidables.getBufferCL(),true),
+ b3BufferInfoCL( convexData.getBufferCL(),true),
+ b3BufferInfoCL( gpuVertices.getBufferCL(),true),
+ b3BufferInfoCL( gpuUniqueEdges.getBufferCL(),true),
+ b3BufferInfoCL( gpuFaces.getBufferCL(),true),
+ b3BufferInfoCL( gpuIndices.getBufferCL(),true),
+ b3BufferInfoCL( gpuChildShapes.getBufferCL(),true),
+ b3BufferInfoCL( m_gpuCompoundSepNormals.getBufferCL(),true),
+ b3BufferInfoCL( m_gpuHasCompoundSepNormals.getBufferCL(),true),
+ b3BufferInfoCL( contactOut->getBufferCL()),
+ b3BufferInfoCL( m_totalContactsOut.getBufferCL())
+ };
+ b3LauncherCL launcher(m_queue, m_clipCompoundsHullHullKernel,"m_clipCompoundsHullHullKernel");
+ launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst( nCompoundsPairs );
+ launcher.setConst(maxContactCapacity);
+
+ int num = nCompoundsPairs;
+ launcher.launch1D( num);
+ clFinish(m_queue);
+
+ nContacts = m_totalContactsOut.at(0);
+ if (nContacts>maxContactCapacity)
+ {
+
+ b3Error("Error: contacts exceeds capacity (%d/%d)\n", nContacts, maxContactCapacity);
+ nContacts = maxContactCapacity;
+ }
+ contactOut->resize(nContacts);
+ }//if nCompoundsPairs
+ }
+ }//contactClippingOnGpu
+
+ //printf("nContacts end = %d\n",nContacts);
+
+ //printf("frameCount = %d\n",frameCount++);
+}
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3ConvexHullContact.h b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3ConvexHullContact.h
new file mode 100644
index 0000000000..e24c1579c6
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3ConvexHullContact.h
@@ -0,0 +1,118 @@
+
+#ifndef _CONVEX_HULL_CONTACT_H
+#define _CONVEX_HULL_CONTACT_H
+
+#include "Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
+#include "Bullet3Common/b3AlignedObjectArray.h"
+
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h"
+#include "Bullet3Collision/NarrowPhaseCollision/b3Contact4.h"
+#include "Bullet3Common/shared/b3Int2.h"
+#include "Bullet3Common/shared/b3Int4.h"
+#include "b3OptimizedBvh.h"
+#include "b3BvhInfo.h"
+#include "Bullet3Collision/BroadPhaseCollision/shared/b3Aabb.h"
+
+//#include "../../dynamics/basic_demo/Stubs/ChNarrowPhase.h"
+
+
+
+
+struct GpuSatCollision
+{
+ cl_context m_context;
+ cl_device_id m_device;
+ cl_command_queue m_queue;
+ cl_kernel m_findSeparatingAxisKernel;
+ cl_kernel m_mprPenetrationKernel;
+ cl_kernel m_findSeparatingAxisUnitSphereKernel;
+
+
+ cl_kernel m_findSeparatingAxisVertexFaceKernel;
+ cl_kernel m_findSeparatingAxisEdgeEdgeKernel;
+
+ cl_kernel m_findConcaveSeparatingAxisKernel;
+ cl_kernel m_findConcaveSeparatingAxisVertexFaceKernel;
+ cl_kernel m_findConcaveSeparatingAxisEdgeEdgeKernel;
+
+
+
+
+ cl_kernel m_findCompoundPairsKernel;
+ cl_kernel m_processCompoundPairsKernel;
+
+ cl_kernel m_clipHullHullKernel;
+ cl_kernel m_clipCompoundsHullHullKernel;
+
+ cl_kernel m_clipFacesAndFindContacts;
+ cl_kernel m_findClippingFacesKernel;
+
+ cl_kernel m_clipHullHullConcaveConvexKernel;
+// cl_kernel m_extractManifoldAndAddContactKernel;
+ cl_kernel m_newContactReductionKernel;
+
+ cl_kernel m_bvhTraversalKernel;
+ cl_kernel m_primitiveContactsKernel;
+ cl_kernel m_findConcaveSphereContactsKernel;
+
+ cl_kernel m_processCompoundPairsPrimitivesKernel;
+
+ b3OpenCLArray<b3Vector3> m_unitSphereDirections;
+
+ b3OpenCLArray<int> m_totalContactsOut;
+
+ b3OpenCLArray<b3Vector3> m_sepNormals;
+ b3OpenCLArray<float> m_dmins;
+
+ b3OpenCLArray<int> m_hasSeparatingNormals;
+ b3OpenCLArray<b3Vector3> m_concaveSepNormals;
+ b3OpenCLArray<int> m_concaveHasSeparatingNormals;
+ b3OpenCLArray<int> m_numConcavePairsOut;
+ b3OpenCLArray<b3CompoundOverlappingPair> m_gpuCompoundPairs;
+ b3OpenCLArray<b3Vector3> m_gpuCompoundSepNormals;
+ b3OpenCLArray<int> m_gpuHasCompoundSepNormals;
+ b3OpenCLArray<int> m_numCompoundPairsOut;
+
+
+ GpuSatCollision(cl_context ctx,cl_device_id device, cl_command_queue q );
+ virtual ~GpuSatCollision();
+
+
+ void computeConvexConvexContactsGPUSAT( b3OpenCLArray<b3Int4>* pairs, int nPairs,
+ const b3OpenCLArray<b3RigidBodyData>* bodyBuf,
+ b3OpenCLArray<b3Contact4>* contactOut, int& nContacts,
+ const b3OpenCLArray<b3Contact4>* oldContacts,
+ int maxContactCapacity,
+ int compoundPairCapacity,
+ const b3OpenCLArray<b3ConvexPolyhedronData>& hostConvexData,
+ const b3OpenCLArray<b3Vector3>& vertices,
+ const b3OpenCLArray<b3Vector3>& uniqueEdges,
+ const b3OpenCLArray<b3GpuFace>& faces,
+ const b3OpenCLArray<int>& indices,
+ const b3OpenCLArray<b3Collidable>& gpuCollidables,
+ const b3OpenCLArray<b3GpuChildShape>& gpuChildShapes,
+
+ const b3OpenCLArray<b3Aabb>& clAabbsWorldSpace,
+ const b3OpenCLArray<b3Aabb>& clAabbsLocalSpace,
+
+ b3OpenCLArray<b3Vector3>& worldVertsB1GPU,
+ b3OpenCLArray<b3Int4>& clippingFacesOutGPU,
+ b3OpenCLArray<b3Vector3>& worldNormalsAGPU,
+ b3OpenCLArray<b3Vector3>& worldVertsA1GPU,
+ b3OpenCLArray<b3Vector3>& worldVertsB2GPU,
+ b3AlignedObjectArray<class b3OptimizedBvh*>& bvhData,
+ b3OpenCLArray<b3QuantizedBvhNode>* treeNodesGPU,
+ b3OpenCLArray<b3BvhSubtreeInfo>* subTreesGPU,
+ b3OpenCLArray<b3BvhInfo>* bvhInfo,
+ int numObjects,
+ int maxTriConvexPairCapacity,
+ b3OpenCLArray<b3Int4>& triangleConvexPairs,
+ int& numTriConvexPairsOut
+ );
+
+
+};
+
+#endif //_CONVEX_HULL_CONTACT_H
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3ConvexPolyhedronCL.h b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3ConvexPolyhedronCL.h
new file mode 100644
index 0000000000..337100fb1a
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3ConvexPolyhedronCL.h
@@ -0,0 +1,9 @@
+#ifndef CONVEX_POLYHEDRON_CL
+#define CONVEX_POLYHEDRON_CL
+
+#include "Bullet3Common/b3Transform.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h"
+
+
+
+#endif //CONVEX_POLYHEDRON_CL
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3GjkEpa.cpp b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3GjkEpa.cpp
new file mode 100644
index 0000000000..d636f983c6
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3GjkEpa.cpp
@@ -0,0 +1,1014 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2008 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the
+use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+claim that you wrote the original software. If you use this software in a
+product, an acknowledgment in the product documentation would be appreciated
+but is not required.
+2. Altered source versions must be plainly marked as such, and must not be
+misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+/*
+GJK-EPA collision solver by Nathanael Presson, 2008
+*/
+
+#include "b3GjkEpa.h"
+
+#include "b3SupportMappings.h"
+
+namespace gjkepa2_impl2
+{
+
+ // Config
+
+ /* GJK */
+#define GJK_MAX_ITERATIONS 128
+#define GJK_ACCURACY ((b3Scalar)0.0001)
+#define GJK_MIN_DISTANCE ((b3Scalar)0.0001)
+#define GJK_DUPLICATED_EPS ((b3Scalar)0.0001)
+#define GJK_SIMPLEX2_EPS ((b3Scalar)0.0)
+#define GJK_SIMPLEX3_EPS ((b3Scalar)0.0)
+#define GJK_SIMPLEX4_EPS ((b3Scalar)0.0)
+
+ /* EPA */
+#define EPA_MAX_VERTICES 64
+#define EPA_MAX_FACES (EPA_MAX_VERTICES*2)
+#define EPA_MAX_ITERATIONS 255
+#define EPA_ACCURACY ((b3Scalar)0.0001)
+#define EPA_FALLBACK (10*EPA_ACCURACY)
+#define EPA_PLANE_EPS ((b3Scalar)0.00001)
+#define EPA_INSIDE_EPS ((b3Scalar)0.01)
+
+
+ // Shorthands
+
+
+ // MinkowskiDiff
+ struct b3MinkowskiDiff
+ {
+
+
+ const b3ConvexPolyhedronData* m_shapes[2];
+
+
+ b3Matrix3x3 m_toshape1;
+ b3Transform m_toshape0;
+
+ bool m_enableMargin;
+
+
+ void EnableMargin(bool enable)
+ {
+ m_enableMargin = enable;
+ }
+ inline b3Vector3 Support0(const b3Vector3& d, const b3AlignedObjectArray<b3Vector3>& verticesA) const
+ {
+ if (m_enableMargin)
+ {
+ return localGetSupportVertexWithMargin(d,m_shapes[0],verticesA,0.f);
+ } else
+ {
+ return localGetSupportVertexWithoutMargin(d,m_shapes[0],verticesA);
+ }
+ }
+ inline b3Vector3 Support1(const b3Vector3& d, const b3AlignedObjectArray<b3Vector3>& verticesB) const
+ {
+ if (m_enableMargin)
+ {
+ return m_toshape0*(localGetSupportVertexWithMargin(m_toshape1*d,m_shapes[1],verticesB,0.f));
+ } else
+ {
+ return m_toshape0*(localGetSupportVertexWithoutMargin(m_toshape1*d,m_shapes[1],verticesB));
+ }
+ }
+
+ inline b3Vector3 Support(const b3Vector3& d, const b3AlignedObjectArray<b3Vector3>& verticesA, const b3AlignedObjectArray<b3Vector3>& verticesB) const
+ {
+ return(Support0(d,verticesA)-Support1(-d,verticesB));
+ }
+ b3Vector3 Support(const b3Vector3& d,unsigned int index,const b3AlignedObjectArray<b3Vector3>& verticesA, const b3AlignedObjectArray<b3Vector3>& verticesB) const
+ {
+ if(index)
+ return(Support1(d,verticesA));
+ else
+ return(Support0(d,verticesB));
+ }
+ };
+
+ typedef b3MinkowskiDiff tShape;
+
+
+ // GJK
+ struct b3GJK
+ {
+ /* Types */
+ struct sSV
+ {
+ b3Vector3 d,w;
+ };
+ struct sSimplex
+ {
+ sSV* c[4];
+ b3Scalar p[4];
+ unsigned int rank;
+ };
+ struct eStatus { enum _ {
+ Valid,
+ Inside,
+ Failed };};
+ /* Fields */
+ tShape m_shape;
+ const b3AlignedObjectArray<b3Vector3>& m_verticesA;
+ const b3AlignedObjectArray<b3Vector3>& m_verticesB;
+ b3Vector3 m_ray;
+ b3Scalar m_distance;
+ sSimplex m_simplices[2];
+ sSV m_store[4];
+ sSV* m_free[4];
+ unsigned int m_nfree;
+ unsigned int m_current;
+ sSimplex* m_simplex;
+ eStatus::_ m_status;
+ /* Methods */
+ b3GJK(const b3AlignedObjectArray<b3Vector3>& verticesA,const b3AlignedObjectArray<b3Vector3>& verticesB)
+ :m_verticesA(verticesA),m_verticesB(verticesB)
+ {
+ Initialize();
+ }
+ void Initialize()
+ {
+ m_ray = b3MakeVector3(0,0,0);
+ m_nfree = 0;
+ m_status = eStatus::Failed;
+ m_current = 0;
+ m_distance = 0;
+ }
+ eStatus::_ Evaluate(const tShape& shapearg,const b3Vector3& guess)
+ {
+ unsigned int iterations=0;
+ b3Scalar sqdist=0;
+ b3Scalar alpha=0;
+ b3Vector3 lastw[4];
+ unsigned int clastw=0;
+ /* Initialize solver */
+ m_free[0] = &m_store[0];
+ m_free[1] = &m_store[1];
+ m_free[2] = &m_store[2];
+ m_free[3] = &m_store[3];
+ m_nfree = 4;
+ m_current = 0;
+ m_status = eStatus::Valid;
+ m_shape = shapearg;
+ m_distance = 0;
+ /* Initialize simplex */
+ m_simplices[0].rank = 0;
+ m_ray = guess;
+ const b3Scalar sqrl= m_ray.length2();
+ appendvertice(m_simplices[0],sqrl>0?-m_ray:b3MakeVector3(1,0,0));
+ m_simplices[0].p[0] = 1;
+ m_ray = m_simplices[0].c[0]->w;
+ sqdist = sqrl;
+ lastw[0] =
+ lastw[1] =
+ lastw[2] =
+ lastw[3] = m_ray;
+ /* Loop */
+ do {
+ const unsigned int next=1-m_current;
+ sSimplex& cs=m_simplices[m_current];
+ sSimplex& ns=m_simplices[next];
+ /* Check zero */
+ const b3Scalar rl=m_ray.length();
+ if(rl<GJK_MIN_DISTANCE)
+ {/* Touching or inside */
+ m_status=eStatus::Inside;
+ break;
+ }
+ /* Append new vertice in -'v' direction */
+ appendvertice(cs,-m_ray);
+ const b3Vector3& w=cs.c[cs.rank-1]->w;
+ bool found=false;
+ for(unsigned int i=0;i<4;++i)
+ {
+ if((w-lastw[i]).length2()<GJK_DUPLICATED_EPS)
+ { found=true;break; }
+ }
+ if(found)
+ {/* Return old simplex */
+ removevertice(m_simplices[m_current]);
+ break;
+ }
+ else
+ {/* Update lastw */
+ lastw[clastw=(clastw+1)&3]=w;
+ }
+ /* Check for termination */
+ const b3Scalar omega=b3Dot(m_ray,w)/rl;
+ alpha=b3Max(omega,alpha);
+ if(((rl-alpha)-(GJK_ACCURACY*rl))<=0)
+ {/* Return old simplex */
+ removevertice(m_simplices[m_current]);
+ break;
+ }
+ /* Reduce simplex */
+ b3Scalar weights[4];
+ unsigned int mask=0;
+ switch(cs.rank)
+ {
+ case 2: sqdist=projectorigin( cs.c[0]->w,
+ cs.c[1]->w,
+ weights,mask);break;
+ case 3: sqdist=projectorigin( cs.c[0]->w,
+ cs.c[1]->w,
+ cs.c[2]->w,
+ weights,mask);break;
+ case 4: sqdist=projectorigin( cs.c[0]->w,
+ cs.c[1]->w,
+ cs.c[2]->w,
+ cs.c[3]->w,
+ weights,mask);break;
+ }
+ if(sqdist>=0)
+ {/* Valid */
+ ns.rank = 0;
+ m_ray = b3MakeVector3(0,0,0);
+ m_current = next;
+ for(unsigned int i=0,ni=cs.rank;i<ni;++i)
+ {
+ if(mask&(1<<i))
+ {
+ ns.c[ns.rank] = cs.c[i];
+ ns.p[ns.rank++] = weights[i];
+ m_ray += cs.c[i]->w*weights[i];
+ }
+ else
+ {
+ m_free[m_nfree++] = cs.c[i];
+ }
+ }
+ if(mask==15) m_status=eStatus::Inside;
+ }
+ else
+ {/* Return old simplex */
+ removevertice(m_simplices[m_current]);
+ break;
+ }
+ m_status=((++iterations)<GJK_MAX_ITERATIONS)?m_status:eStatus::Failed;
+ } while(m_status==eStatus::Valid);
+ m_simplex=&m_simplices[m_current];
+ switch(m_status)
+ {
+ case eStatus::Valid: m_distance=m_ray.length();break;
+ case eStatus::Inside: m_distance=0;break;
+ default:
+ {
+ }
+ }
+ return(m_status);
+ }
+ bool EncloseOrigin()
+ {
+ switch(m_simplex->rank)
+ {
+ case 1:
+ {
+ for(unsigned int i=0;i<3;++i)
+ {
+ b3Vector3 axis=b3MakeVector3(0,0,0);
+ axis[i]=1;
+ appendvertice(*m_simplex, axis);
+ if(EncloseOrigin()) return(true);
+ removevertice(*m_simplex);
+ appendvertice(*m_simplex,-axis);
+ if(EncloseOrigin()) return(true);
+ removevertice(*m_simplex);
+ }
+ }
+ break;
+ case 2:
+ {
+ const b3Vector3 d=m_simplex->c[1]->w-m_simplex->c[0]->w;
+ for(unsigned int i=0;i<3;++i)
+ {
+ b3Vector3 axis=b3MakeVector3(0,0,0);
+ axis[i]=1;
+ const b3Vector3 p=b3Cross(d,axis);
+ if(p.length2()>0)
+ {
+ appendvertice(*m_simplex, p);
+ if(EncloseOrigin()) return(true);
+ removevertice(*m_simplex);
+ appendvertice(*m_simplex,-p);
+ if(EncloseOrigin()) return(true);
+ removevertice(*m_simplex);
+ }
+ }
+ }
+ break;
+ case 3:
+ {
+ const b3Vector3 n=b3Cross(m_simplex->c[1]->w-m_simplex->c[0]->w,
+ m_simplex->c[2]->w-m_simplex->c[0]->w);
+ if(n.length2()>0)
+ {
+ appendvertice(*m_simplex,n);
+ if(EncloseOrigin()) return(true);
+ removevertice(*m_simplex);
+ appendvertice(*m_simplex,-n);
+ if(EncloseOrigin()) return(true);
+ removevertice(*m_simplex);
+ }
+ }
+ break;
+ case 4:
+ {
+ if(b3Fabs(det( m_simplex->c[0]->w-m_simplex->c[3]->w,
+ m_simplex->c[1]->w-m_simplex->c[3]->w,
+ m_simplex->c[2]->w-m_simplex->c[3]->w))>0)
+ return(true);
+ }
+ break;
+ }
+ return(false);
+ }
+ /* Internals */
+ void getsupport(const b3Vector3& d,sSV& sv) const
+ {
+ sv.d = d/d.length();
+ sv.w = m_shape.Support(sv.d,m_verticesA,m_verticesB);
+ }
+ void removevertice(sSimplex& simplex)
+ {
+ m_free[m_nfree++]=simplex.c[--simplex.rank];
+ }
+ void appendvertice(sSimplex& simplex,const b3Vector3& v)
+ {
+ simplex.p[simplex.rank]=0;
+ simplex.c[simplex.rank]=m_free[--m_nfree];
+ getsupport(v,*simplex.c[simplex.rank++]);
+ }
+ static b3Scalar det(const b3Vector3& a,const b3Vector3& b,const b3Vector3& c)
+ {
+ return( a.y*b.z*c.x+a.z*b.x*c.y-
+ a.x*b.z*c.y-a.y*b.x*c.z+
+ a.x*b.y*c.z-a.z*b.y*c.x);
+ }
+ static b3Scalar projectorigin( const b3Vector3& a,
+ const b3Vector3& b,
+ b3Scalar* w,unsigned int& m)
+ {
+ const b3Vector3 d=b-a;
+ const b3Scalar l=d.length2();
+ if(l>GJK_SIMPLEX2_EPS)
+ {
+ const b3Scalar t(l>0?-b3Dot(a,d)/l:0);
+ if(t>=1) { w[0]=0;w[1]=1;m=2;return(b.length2()); }
+ else if(t<=0) { w[0]=1;w[1]=0;m=1;return(a.length2()); }
+ else { w[0]=1-(w[1]=t);m=3;return((a+d*t).length2()); }
+ }
+ return(-1);
+ }
+ static b3Scalar projectorigin( const b3Vector3& a,
+ const b3Vector3& b,
+ const b3Vector3& c,
+ b3Scalar* w,unsigned int& m)
+ {
+ static const unsigned int imd3[]={1,2,0};
+ const b3Vector3* vt[]={&a,&b,&c};
+ const b3Vector3 dl[]={a-b,b-c,c-a};
+ const b3Vector3 n=b3Cross(dl[0],dl[1]);
+ const b3Scalar l=n.length2();
+ if(l>GJK_SIMPLEX3_EPS)
+ {
+ b3Scalar mindist=-1;
+ b3Scalar subw[2]={0.f,0.f};
+ unsigned int subm(0);
+ for(unsigned int i=0;i<3;++i)
+ {
+ if(b3Dot(*vt[i],b3Cross(dl[i],n))>0)
+ {
+ const unsigned int j=imd3[i];
+ const b3Scalar subd(projectorigin(*vt[i],*vt[j],subw,subm));
+ if((mindist<0)||(subd<mindist))
+ {
+ mindist = subd;
+ m = static_cast<unsigned int>(((subm&1)?1<<i:0)+((subm&2)?1<<j:0));
+ w[i] = subw[0];
+ w[j] = subw[1];
+ w[imd3[j]] = 0;
+ }
+ }
+ }
+ if(mindist<0)
+ {
+ const b3Scalar d=b3Dot(a,n);
+ const b3Scalar s=b3Sqrt(l);
+ const b3Vector3 p=n*(d/l);
+ mindist = p.length2();
+ m = 7;
+ w[0] = (b3Cross(dl[1],b-p)).length()/s;
+ w[1] = (b3Cross(dl[2],c-p)).length()/s;
+ w[2] = 1-(w[0]+w[1]);
+ }
+ return(mindist);
+ }
+ return(-1);
+ }
+ static b3Scalar projectorigin( const b3Vector3& a,
+ const b3Vector3& b,
+ const b3Vector3& c,
+ const b3Vector3& d,
+ b3Scalar* w,unsigned int& m)
+ {
+ static const unsigned int imd3[]={1,2,0};
+ const b3Vector3* vt[]={&a,&b,&c,&d};
+ const b3Vector3 dl[]={a-d,b-d,c-d};
+ const b3Scalar vl=det(dl[0],dl[1],dl[2]);
+ const bool ng=(vl*b3Dot(a,b3Cross(b-c,a-b)))<=0;
+ if(ng&&(b3Fabs(vl)>GJK_SIMPLEX4_EPS))
+ {
+ b3Scalar mindist=-1;
+ b3Scalar subw[3]={0.f,0.f,0.f};
+ unsigned int subm(0);
+ for(unsigned int i=0;i<3;++i)
+ {
+ const unsigned int j=imd3[i];
+ const b3Scalar s=vl*b3Dot(d,b3Cross(dl[i],dl[j]));
+ if(s>0)
+ {
+ const b3Scalar subd=projectorigin(*vt[i],*vt[j],d,subw,subm);
+ if((mindist<0)||(subd<mindist))
+ {
+ mindist = subd;
+ m = static_cast<unsigned int>((subm&1?1<<i:0)+
+ (subm&2?1<<j:0)+
+ (subm&4?8:0));
+ w[i] = subw[0];
+ w[j] = subw[1];
+ w[imd3[j]] = 0;
+ w[3] = subw[2];
+ }
+ }
+ }
+ if(mindist<0)
+ {
+ mindist = 0;
+ m = 15;
+ w[0] = det(c,b,d)/vl;
+ w[1] = det(a,c,d)/vl;
+ w[2] = det(b,a,d)/vl;
+ w[3] = 1-(w[0]+w[1]+w[2]);
+ }
+ return(mindist);
+ }
+ return(-1);
+ }
+ };
+
+ // EPA
+ struct b3EPA
+ {
+ /* Types */
+ typedef b3GJK::sSV sSV;
+ struct sFace
+ {
+ b3Vector3 n;
+ b3Scalar d;
+ sSV* c[3];
+ sFace* f[3];
+ sFace* l[2];
+ unsigned char e[3];
+ unsigned char pass;
+ };
+ struct sList
+ {
+ sFace* root;
+ unsigned int count;
+ sList() : root(0),count(0) {}
+ };
+ struct sHorizon
+ {
+ sFace* cf;
+ sFace* ff;
+ unsigned int nf;
+ sHorizon() : cf(0),ff(0),nf(0) {}
+ };
+ struct eStatus { enum _ {
+ Valid,
+ Touching,
+ Degenerated,
+ NonConvex,
+ InvalidHull,
+ OutOfFaces,
+ OutOfVertices,
+ AccuraryReached,
+ FallBack,
+ Failed };};
+ /* Fields */
+ eStatus::_ m_status;
+ b3GJK::sSimplex m_result;
+ b3Vector3 m_normal;
+ b3Scalar m_depth;
+ sSV m_sv_store[EPA_MAX_VERTICES];
+ sFace m_fc_store[EPA_MAX_FACES];
+ unsigned int m_nextsv;
+ sList m_hull;
+ sList m_stock;
+ /* Methods */
+ b3EPA()
+ {
+ Initialize();
+ }
+
+
+ static inline void bind(sFace* fa,unsigned int ea,sFace* fb,unsigned int eb)
+ {
+ fa->e[ea]=(unsigned char)eb;fa->f[ea]=fb;
+ fb->e[eb]=(unsigned char)ea;fb->f[eb]=fa;
+ }
+ static inline void append(sList& list,sFace* face)
+ {
+ face->l[0] = 0;
+ face->l[1] = list.root;
+ if(list.root) list.root->l[0]=face;
+ list.root = face;
+ ++list.count;
+ }
+ static inline void remove(sList& list,sFace* face)
+ {
+ if(face->l[1]) face->l[1]->l[0]=face->l[0];
+ if(face->l[0]) face->l[0]->l[1]=face->l[1];
+ if(face==list.root) list.root=face->l[1];
+ --list.count;
+ }
+
+
+ void Initialize()
+ {
+ m_status = eStatus::Failed;
+ m_normal = b3MakeVector3(0,0,0);
+ m_depth = 0;
+ m_nextsv = 0;
+ for(unsigned int i=0;i<EPA_MAX_FACES;++i)
+ {
+ append(m_stock,&m_fc_store[EPA_MAX_FACES-i-1]);
+ }
+ }
+ eStatus::_ Evaluate(b3GJK& gjk,const b3Vector3& guess)
+ {
+ b3GJK::sSimplex& simplex=*gjk.m_simplex;
+ if((simplex.rank>1)&&gjk.EncloseOrigin())
+ {
+
+ /* Clean up */
+ while(m_hull.root)
+ {
+ sFace* f = m_hull.root;
+ remove(m_hull,f);
+ append(m_stock,f);
+ }
+ m_status = eStatus::Valid;
+ m_nextsv = 0;
+ /* Orient simplex */
+ if(gjk.det( simplex.c[0]->w-simplex.c[3]->w,
+ simplex.c[1]->w-simplex.c[3]->w,
+ simplex.c[2]->w-simplex.c[3]->w)<0)
+ {
+ b3Swap(simplex.c[0],simplex.c[1]);
+ b3Swap(simplex.p[0],simplex.p[1]);
+ }
+ /* Build initial hull */
+ sFace* tetra[]={newface(simplex.c[0],simplex.c[1],simplex.c[2],true),
+ newface(simplex.c[1],simplex.c[0],simplex.c[3],true),
+ newface(simplex.c[2],simplex.c[1],simplex.c[3],true),
+ newface(simplex.c[0],simplex.c[2],simplex.c[3],true)};
+ if(m_hull.count==4)
+ {
+ sFace* best=findbest();
+ sFace outer=*best;
+ unsigned int pass=0;
+ unsigned int iterations=0;
+ bind(tetra[0],0,tetra[1],0);
+ bind(tetra[0],1,tetra[2],0);
+ bind(tetra[0],2,tetra[3],0);
+ bind(tetra[1],1,tetra[3],2);
+ bind(tetra[1],2,tetra[2],1);
+ bind(tetra[2],2,tetra[3],1);
+ m_status=eStatus::Valid;
+ for(;iterations<EPA_MAX_ITERATIONS;++iterations)
+ {
+ if(m_nextsv<EPA_MAX_VERTICES)
+ {
+ sHorizon horizon;
+ sSV* w=&m_sv_store[m_nextsv++];
+ bool valid=true;
+ best->pass = (unsigned char)(++pass);
+ gjk.getsupport(best->n,*w);
+ const b3Scalar wdist=b3Dot(best->n,w->w)-best->d;
+ if(wdist>EPA_ACCURACY)
+ {
+ for(unsigned int j=0;(j<3)&&valid;++j)
+ {
+ valid&=expand( pass,w,
+ best->f[j],best->e[j],
+ horizon);
+ }
+ if(valid&&(horizon.nf>=3))
+ {
+ bind(horizon.cf,1,horizon.ff,2);
+ remove(m_hull,best);
+ append(m_stock,best);
+ best=findbest();
+ outer=*best;
+ } else {
+ m_status=eStatus::Failed;
+ //m_status=eStatus::InvalidHull;
+ break; }
+ } else { m_status=eStatus::AccuraryReached;break; }
+ } else { m_status=eStatus::OutOfVertices;break; }
+ }
+ const b3Vector3 projection=outer.n*outer.d;
+ m_normal = outer.n;
+ m_depth = outer.d;
+ m_result.rank = 3;
+ m_result.c[0] = outer.c[0];
+ m_result.c[1] = outer.c[1];
+ m_result.c[2] = outer.c[2];
+ m_result.p[0] = b3Cross( outer.c[1]->w-projection,
+ outer.c[2]->w-projection).length();
+ m_result.p[1] = b3Cross( outer.c[2]->w-projection,
+ outer.c[0]->w-projection).length();
+ m_result.p[2] = b3Cross( outer.c[0]->w-projection,
+ outer.c[1]->w-projection).length();
+ const b3Scalar sum=m_result.p[0]+m_result.p[1]+m_result.p[2];
+ m_result.p[0] /= sum;
+ m_result.p[1] /= sum;
+ m_result.p[2] /= sum;
+ return(m_status);
+ }
+ }
+ /* Fallback */
+ m_status = eStatus::FallBack;
+ m_normal = -guess;
+ const b3Scalar nl=m_normal.length();
+ if(nl>0)
+ m_normal = m_normal/nl;
+ else
+ m_normal = b3MakeVector3(1,0,0);
+ m_depth = 0;
+ m_result.rank=1;
+ m_result.c[0]=simplex.c[0];
+ m_result.p[0]=1;
+ return(m_status);
+ }
+ bool getedgedist(sFace* face, sSV* a, sSV* b, b3Scalar& dist)
+ {
+ const b3Vector3 ba = b->w - a->w;
+ const b3Vector3 n_ab = b3Cross(ba, face->n); // Outward facing edge normal direction, on triangle plane
+ const b3Scalar a_dot_nab = b3Dot(a->w, n_ab); // Only care about the sign to determine inside/outside, so not normalization required
+
+ if(a_dot_nab < 0)
+ {
+ // Outside of edge a->b
+
+ const b3Scalar ba_l2 = ba.length2();
+ const b3Scalar a_dot_ba = b3Dot(a->w, ba);
+ const b3Scalar b_dot_ba = b3Dot(b->w, ba);
+
+ if(a_dot_ba > 0)
+ {
+ // Pick distance vertex a
+ dist = a->w.length();
+ }
+ else if(b_dot_ba < 0)
+ {
+ // Pick distance vertex b
+ dist = b->w.length();
+ }
+ else
+ {
+ // Pick distance to edge a->b
+ const b3Scalar a_dot_b = b3Dot(a->w, b->w);
+ dist = b3Sqrt(b3Max((a->w.length2() * b->w.length2() - a_dot_b * a_dot_b) / ba_l2, (b3Scalar)0));
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+ sFace* newface(sSV* a,sSV* b,sSV* c,bool forced)
+ {
+ if(m_stock.root)
+ {
+ sFace* face=m_stock.root;
+ remove(m_stock,face);
+ append(m_hull,face);
+ face->pass = 0;
+ face->c[0] = a;
+ face->c[1] = b;
+ face->c[2] = c;
+ face->n = b3Cross(b->w-a->w,c->w-a->w);
+ const b3Scalar l=face->n.length();
+ const bool v=l>EPA_ACCURACY;
+
+ if(v)
+ {
+ if(!(getedgedist(face, a, b, face->d) ||
+ getedgedist(face, b, c, face->d) ||
+ getedgedist(face, c, a, face->d)))
+ {
+ // Origin projects to the interior of the triangle
+ // Use distance to triangle plane
+ face->d = b3Dot(a->w, face->n) / l;
+ }
+
+ face->n /= l;
+ if(forced || (face->d >= -EPA_PLANE_EPS))
+ {
+ return face;
+ }
+ else
+ m_status=eStatus::NonConvex;
+ }
+ else
+ m_status=eStatus::Degenerated;
+
+ remove(m_hull, face);
+ append(m_stock, face);
+ return 0;
+
+ }
+ m_status = m_stock.root ? eStatus::OutOfVertices : eStatus::OutOfFaces;
+ return 0;
+ }
+ sFace* findbest()
+ {
+ sFace* minf=m_hull.root;
+ b3Scalar mind=minf->d*minf->d;
+ for(sFace* f=minf->l[1];f;f=f->l[1])
+ {
+ const b3Scalar sqd=f->d*f->d;
+ if(sqd<mind)
+ {
+ minf=f;
+ mind=sqd;
+ }
+ }
+ return(minf);
+ }
+ bool expand(unsigned int pass,sSV* w,sFace* f,unsigned int e,sHorizon& horizon)
+ {
+ static const unsigned int i1m3[]={1,2,0};
+ static const unsigned int i2m3[]={2,0,1};
+ if(f->pass!=pass)
+ {
+ const unsigned int e1=i1m3[e];
+ if((b3Dot(f->n,w->w)-f->d)<-EPA_PLANE_EPS)
+ {
+ sFace* nf=newface(f->c[e1],f->c[e],w,false);
+ if(nf)
+ {
+ bind(nf,0,f,e);
+ if(horizon.cf) bind(horizon.cf,1,nf,2); else horizon.ff=nf;
+ horizon.cf=nf;
+ ++horizon.nf;
+ return(true);
+ }
+ }
+ else
+ {
+ const unsigned int e2=i2m3[e];
+ f->pass = (unsigned char)pass;
+ if( expand(pass,w,f->f[e1],f->e[e1],horizon)&&
+ expand(pass,w,f->f[e2],f->e[e2],horizon))
+ {
+ remove(m_hull,f);
+ append(m_stock,f);
+ return(true);
+ }
+ }
+ }
+ return(false);
+ }
+
+ };
+
+ //
+ static void Initialize(const b3Transform& transA, const b3Transform& transB,
+ const b3ConvexPolyhedronData* hullA, const b3ConvexPolyhedronData* hullB,
+ const b3AlignedObjectArray<b3Vector3>& verticesA,
+ const b3AlignedObjectArray<b3Vector3>& verticesB,
+ b3GjkEpaSolver2::sResults& results,
+ tShape& shape,
+ bool withmargins)
+ {
+ /* Results */
+ results.witnesses[0] =
+ results.witnesses[1] = b3MakeVector3(0,0,0);
+ results.status = b3GjkEpaSolver2::sResults::Separated;
+ /* Shape */
+ shape.m_shapes[0] = hullA;
+ shape.m_shapes[1] = hullB;
+ shape.m_toshape1 = transB.getBasis().transposeTimes(transA.getBasis());
+ shape.m_toshape0 = transA.inverseTimes(transB);
+ shape.EnableMargin(withmargins);
+ }
+
+}
+
+//
+// Api
+//
+
+using namespace gjkepa2_impl2;
+
+//
+int b3GjkEpaSolver2::StackSizeRequirement()
+{
+ return(sizeof(b3GJK)+sizeof(b3EPA));
+}
+
+//
+bool b3GjkEpaSolver2::Distance( const b3Transform& transA, const b3Transform& transB,
+ const b3ConvexPolyhedronData* hullA, const b3ConvexPolyhedronData* hullB,
+ const b3AlignedObjectArray<b3Vector3>& verticesA,
+ const b3AlignedObjectArray<b3Vector3>& verticesB,
+ const b3Vector3& guess,
+ sResults& results)
+{
+ tShape shape;
+ Initialize(transA,transB,hullA,hullB,verticesA,verticesB,results,shape,false);
+ b3GJK gjk(verticesA,verticesB);
+ b3GJK::eStatus::_ gjk_status=gjk.Evaluate(shape,guess);
+ if(gjk_status==b3GJK::eStatus::Valid)
+ {
+ b3Vector3 w0=b3MakeVector3(0,0,0);
+ b3Vector3 w1=b3MakeVector3(0,0,0);
+ for(unsigned int i=0;i<gjk.m_simplex->rank;++i)
+ {
+ const b3Scalar p=gjk.m_simplex->p[i];
+ w0+=shape.Support( gjk.m_simplex->c[i]->d,0,verticesA,verticesB)*p;
+ w1+=shape.Support(-gjk.m_simplex->c[i]->d,1,verticesA,verticesB)*p;
+ }
+ results.witnesses[0] = transA*w0;
+ results.witnesses[1] = transA*w1;
+ results.normal = w0-w1;
+ results.distance = results.normal.length();
+ results.normal /= results.distance>GJK_MIN_DISTANCE?results.distance:1;
+ return(true);
+ }
+ else
+ {
+ results.status = gjk_status==b3GJK::eStatus::Inside?
+ sResults::Penetrating :
+ sResults::GJK_Failed ;
+ return(false);
+ }
+}
+
+//
+bool b3GjkEpaSolver2::Penetration( const b3Transform& transA, const b3Transform& transB,
+ const b3ConvexPolyhedronData* hullA, const b3ConvexPolyhedronData* hullB,
+ const b3AlignedObjectArray<b3Vector3>& verticesA,
+ const b3AlignedObjectArray<b3Vector3>& verticesB,
+ const b3Vector3& guess,
+ sResults& results,
+ bool usemargins)
+{
+
+ tShape shape;
+ Initialize(transA,transB,hullA,hullB,verticesA,verticesB,results,shape,usemargins);
+ b3GJK gjk(verticesA,verticesB);
+ b3GJK::eStatus::_ gjk_status=gjk.Evaluate(shape,guess);
+ switch(gjk_status)
+ {
+ case b3GJK::eStatus::Inside:
+ {
+ b3EPA epa;
+ b3EPA::eStatus::_ epa_status=epa.Evaluate(gjk,-guess);
+ if(epa_status!=b3EPA::eStatus::Failed)
+ {
+ b3Vector3 w0=b3MakeVector3(0,0,0);
+ for(unsigned int i=0;i<epa.m_result.rank;++i)
+ {
+ w0+=shape.Support(epa.m_result.c[i]->d,0,verticesA,verticesB)*epa.m_result.p[i];
+ }
+ results.status = sResults::Penetrating;
+ results.witnesses[0] = transA*w0;
+ results.witnesses[1] = transA*(w0-epa.m_normal*epa.m_depth);
+ results.normal = -epa.m_normal;
+ results.distance = -epa.m_depth;
+ return(true);
+ } else results.status=sResults::EPA_Failed;
+ }
+ break;
+ case b3GJK::eStatus::Failed:
+ results.status=sResults::GJK_Failed;
+ break;
+ default:
+ {
+ }
+ }
+ return(false);
+}
+
+
+#if 0
+//
+b3Scalar b3GjkEpaSolver2::SignedDistance(const b3Vector3& position,
+ b3Scalar margin,
+ const b3Transform& transA,
+ const b3ConvexPolyhedronData& hullA,
+ const b3AlignedObjectArray<b3Vector3>& verticesA,
+ sResults& results)
+{
+ tShape shape;
+ btSphereShape shape1(margin);
+ b3Transform wtrs1(b3Quaternion(0,0,0,1),position);
+ Initialize(shape0,wtrs0,&shape1,wtrs1,results,shape,false);
+ GJK gjk;
+ GJK::eStatus::_ gjk_status=gjk.Evaluate(shape,b3Vector3(1,1,1));
+ if(gjk_status==GJK::eStatus::Valid)
+ {
+ b3Vector3 w0=b3Vector3(0,0,0);
+ b3Vector3 w1=b3Vector3(0,0,0);
+ for(unsigned int i=0;i<gjk.m_simplex->rank;++i)
+ {
+ const b3Scalar p=gjk.m_simplex->p[i];
+ w0+=shape.Support( gjk.m_simplex->c[i]->d,0)*p;
+ w1+=shape.Support(-gjk.m_simplex->c[i]->d,1)*p;
+ }
+ results.witnesses[0] = wtrs0*w0;
+ results.witnesses[1] = wtrs0*w1;
+ const b3Vector3 delta= results.witnesses[1]-
+ results.witnesses[0];
+ const b3Scalar margin= shape0->getMarginNonVirtual()+
+ shape1.getMarginNonVirtual();
+ const b3Scalar length= delta.length();
+ results.normal = delta/length;
+ results.witnesses[0] += results.normal*margin;
+ return(length-margin);
+ }
+ else
+ {
+ if(gjk_status==GJK::eStatus::Inside)
+ {
+ if(Penetration(shape0,wtrs0,&shape1,wtrs1,gjk.m_ray,results))
+ {
+ const b3Vector3 delta= results.witnesses[0]-
+ results.witnesses[1];
+ const b3Scalar length= delta.length();
+ if (length >= B3_EPSILON)
+ results.normal = delta/length;
+ return(-length);
+ }
+ }
+ }
+ return(B3_INFINITY);
+}
+
+//
+bool b3GjkEpaSolver2::SignedDistance(const btConvexShape* shape0,
+ const b3Transform& wtrs0,
+ const btConvexShape* shape1,
+ const b3Transform& wtrs1,
+ const b3Vector3& guess,
+ sResults& results)
+{
+ if(!Distance(shape0,wtrs0,shape1,wtrs1,guess,results))
+ return(Penetration(shape0,wtrs0,shape1,wtrs1,guess,results,false));
+ else
+ return(true);
+}
+#endif
+
+
+/* Symbols cleanup */
+
+#undef GJK_MAX_ITERATIONS
+#undef GJK_ACCURACY
+#undef GJK_MIN_DISTANCE
+#undef GJK_DUPLICATED_EPS
+#undef GJK_SIMPLEX2_EPS
+#undef GJK_SIMPLEX3_EPS
+#undef GJK_SIMPLEX4_EPS
+
+#undef EPA_MAX_VERTICES
+#undef EPA_MAX_FACES
+#undef EPA_MAX_ITERATIONS
+#undef EPA_ACCURACY
+#undef EPA_FALLBACK
+#undef EPA_PLANE_EPS
+#undef EPA_INSIDE_EPS
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3GjkEpa.h b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3GjkEpa.h
new file mode 100644
index 0000000000..976238a04c
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3GjkEpa.h
@@ -0,0 +1,82 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2008 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the
+use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+claim that you wrote the original software. If you use this software in a
+product, an acknowledgment in the product documentation would be appreciated
+but is not required.
+2. Altered source versions must be plainly marked as such, and must not be
+misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+/*
+GJK-EPA collision solver by Nathanael Presson, 2008
+*/
+#ifndef B3_GJK_EPA2_H
+#define B3_GJK_EPA2_H
+
+#include "Bullet3Common/b3AlignedObjectArray.h"
+#include "Bullet3Common/b3Transform.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h"
+
+
+///btGjkEpaSolver contributed under zlib by Nathanael Presson
+struct b3GjkEpaSolver2
+{
+struct sResults
+ {
+ enum eStatus
+ {
+ Separated, /* Shapes doesnt penetrate */
+ Penetrating, /* Shapes are penetrating */
+ GJK_Failed, /* GJK phase fail, no big issue, shapes are probably just 'touching' */
+ EPA_Failed /* EPA phase fail, bigger problem, need to save parameters, and debug */
+ } status;
+ b3Vector3 witnesses[2];
+ b3Vector3 normal;
+ b3Scalar distance;
+ };
+
+static int StackSizeRequirement();
+
+static bool Distance( const b3Transform& transA, const b3Transform& transB,
+ const b3ConvexPolyhedronData* hullA, const b3ConvexPolyhedronData* hullB,
+ const b3AlignedObjectArray<b3Vector3>& verticesA,
+ const b3AlignedObjectArray<b3Vector3>& verticesB,
+ const b3Vector3& guess,
+ sResults& results);
+
+static bool Penetration( const b3Transform& transA, const b3Transform& transB,
+ const b3ConvexPolyhedronData* hullA, const b3ConvexPolyhedronData* hullB,
+ const b3AlignedObjectArray<b3Vector3>& verticesA,
+ const b3AlignedObjectArray<b3Vector3>& verticesB,
+ const b3Vector3& guess,
+ sResults& results,
+ bool usemargins=true);
+#if 0
+static b3Scalar SignedDistance( const b3Vector3& position,
+ b3Scalar margin,
+ const btConvexShape* shape,
+ const btTransform& wtrs,
+ sResults& results);
+
+static bool SignedDistance( const btConvexShape* shape0,const btTransform& wtrs0,
+ const btConvexShape* shape1,const btTransform& wtrs1,
+ const b3Vector3& guess,
+ sResults& results);
+#endif
+
+};
+
+#endif //B3_GJK_EPA2_H
+
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3OptimizedBvh.cpp b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3OptimizedBvh.cpp
new file mode 100644
index 0000000000..e9e51d5a36
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3OptimizedBvh.cpp
@@ -0,0 +1,390 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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 "b3OptimizedBvh.h"
+#include "b3StridingMeshInterface.h"
+#include "Bullet3Geometry/b3AabbUtil.h"
+
+
+b3OptimizedBvh::b3OptimizedBvh()
+{
+}
+
+b3OptimizedBvh::~b3OptimizedBvh()
+{
+}
+
+
+void b3OptimizedBvh::build(b3StridingMeshInterface* triangles, bool useQuantizedAabbCompression, const b3Vector3& bvhAabbMin, const b3Vector3& bvhAabbMax)
+{
+ m_useQuantization = useQuantizedAabbCompression;
+
+
+ // NodeArray triangleNodes;
+
+ struct NodeTriangleCallback : public b3InternalTriangleIndexCallback
+ {
+
+ NodeArray& m_triangleNodes;
+
+ NodeTriangleCallback& operator=(NodeTriangleCallback& other)
+ {
+ m_triangleNodes.copyFromArray(other.m_triangleNodes);
+ return *this;
+ }
+
+ NodeTriangleCallback(NodeArray& triangleNodes)
+ :m_triangleNodes(triangleNodes)
+ {
+ }
+
+ virtual void internalProcessTriangleIndex(b3Vector3* triangle,int partId,int triangleIndex)
+ {
+ b3OptimizedBvhNode node;
+ b3Vector3 aabbMin,aabbMax;
+ aabbMin.setValue(b3Scalar(B3_LARGE_FLOAT),b3Scalar(B3_LARGE_FLOAT),b3Scalar(B3_LARGE_FLOAT));
+ aabbMax.setValue(b3Scalar(-B3_LARGE_FLOAT),b3Scalar(-B3_LARGE_FLOAT),b3Scalar(-B3_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]);
+
+ //with quantization?
+ node.m_aabbMinOrg = aabbMin;
+ node.m_aabbMaxOrg = aabbMax;
+
+ node.m_escapeIndex = -1;
+
+ //for child nodes
+ node.m_subPart = partId;
+ node.m_triangleIndex = triangleIndex;
+ m_triangleNodes.push_back(node);
+ }
+ };
+ struct QuantizedNodeTriangleCallback : public b3InternalTriangleIndexCallback
+ {
+ QuantizedNodeArray& m_triangleNodes;
+ const b3QuantizedBvh* m_optimizedTree; // for quantization
+
+ QuantizedNodeTriangleCallback& operator=(QuantizedNodeTriangleCallback& other)
+ {
+ m_triangleNodes.copyFromArray(other.m_triangleNodes);
+ m_optimizedTree = other.m_optimizedTree;
+ return *this;
+ }
+
+ QuantizedNodeTriangleCallback(QuantizedNodeArray& triangleNodes,const b3QuantizedBvh* tree)
+ :m_triangleNodes(triangleNodes),m_optimizedTree(tree)
+ {
+ }
+
+ virtual void internalProcessTriangleIndex(b3Vector3* triangle,int partId,int triangleIndex)
+ {
+ // The partId and triangle index must fit in the same (positive) integer
+ b3Assert(partId < (1<<MAX_NUM_PARTS_IN_BITS));
+ b3Assert(triangleIndex < (1<<(31-MAX_NUM_PARTS_IN_BITS)));
+ //negative indices are reserved for escapeIndex
+ b3Assert(triangleIndex>=0);
+
+ b3QuantizedBvhNode node;
+ b3Vector3 aabbMin,aabbMax;
+ aabbMin.setValue(b3Scalar(B3_LARGE_FLOAT),b3Scalar(B3_LARGE_FLOAT),b3Scalar(B3_LARGE_FLOAT));
+ aabbMax.setValue(b3Scalar(-B3_LARGE_FLOAT),b3Scalar(-B3_LARGE_FLOAT),b3Scalar(-B3_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]);
+
+ //PCK: add these checks for zero dimensions of aabb
+ const b3Scalar MIN_AABB_DIMENSION = b3Scalar(0.002);
+ const b3Scalar MIN_AABB_HALF_DIMENSION = b3Scalar(0.001);
+ if (aabbMax.getX() - aabbMin.getX() < MIN_AABB_DIMENSION)
+ {
+ aabbMax.setX(aabbMax.getX() + MIN_AABB_HALF_DIMENSION);
+ aabbMin.setX(aabbMin.getX() - MIN_AABB_HALF_DIMENSION);
+ }
+ if (aabbMax.getY() - aabbMin.getY() < MIN_AABB_DIMENSION)
+ {
+ aabbMax.setY(aabbMax.getY() + MIN_AABB_HALF_DIMENSION);
+ aabbMin.setY(aabbMin.getY() - MIN_AABB_HALF_DIMENSION);
+ }
+ if (aabbMax.getZ() - aabbMin.getZ() < MIN_AABB_DIMENSION)
+ {
+ aabbMax.setZ(aabbMax.getZ() + MIN_AABB_HALF_DIMENSION);
+ aabbMin.setZ(aabbMin.getZ() - MIN_AABB_HALF_DIMENSION);
+ }
+
+ m_optimizedTree->quantize(&node.m_quantizedAabbMin[0],aabbMin,0);
+ m_optimizedTree->quantize(&node.m_quantizedAabbMax[0],aabbMax,1);
+
+ node.m_escapeIndexOrTriangleIndex = (partId<<(31-MAX_NUM_PARTS_IN_BITS)) | triangleIndex;
+
+ m_triangleNodes.push_back(node);
+ }
+ };
+
+
+
+ int numLeafNodes = 0;
+
+
+ if (m_useQuantization)
+ {
+
+ //initialize quantization values
+ setQuantizationValues(bvhAabbMin,bvhAabbMax);
+
+ QuantizedNodeTriangleCallback callback(m_quantizedLeafNodes,this);
+
+
+ triangles->InternalProcessAllTriangles(&callback,m_bvhAabbMin,m_bvhAabbMax);
+
+ //now we have an array of leafnodes in m_leafNodes
+ numLeafNodes = m_quantizedLeafNodes.size();
+
+
+ m_quantizedContiguousNodes.resize(2*numLeafNodes);
+
+
+ } else
+ {
+ NodeTriangleCallback callback(m_leafNodes);
+
+ b3Vector3 aabbMin=b3MakeVector3(b3Scalar(-B3_LARGE_FLOAT),b3Scalar(-B3_LARGE_FLOAT),b3Scalar(-B3_LARGE_FLOAT));
+ b3Vector3 aabbMax=b3MakeVector3(b3Scalar(B3_LARGE_FLOAT),b3Scalar(B3_LARGE_FLOAT),b3Scalar(B3_LARGE_FLOAT));
+
+ triangles->InternalProcessAllTriangles(&callback,aabbMin,aabbMax);
+
+ //now we have an array of leafnodes in m_leafNodes
+ numLeafNodes = m_leafNodes.size();
+
+ m_contiguousNodes.resize(2*numLeafNodes);
+ }
+
+ m_curNodeIndex = 0;
+
+ buildTree(0,numLeafNodes);
+
+ ///if the entire tree is small then subtree size, we need to create a header info for the tree
+ if(m_useQuantization && !m_SubtreeHeaders.size())
+ {
+ b3BvhSubtreeInfo& subtree = m_SubtreeHeaders.expand();
+ subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[0]);
+ subtree.m_rootNodeIndex = 0;
+ subtree.m_subtreeSize = m_quantizedContiguousNodes[0].isLeafNode() ? 1 : m_quantizedContiguousNodes[0].getEscapeIndex();
+ }
+
+ //PCK: update the copy of the size
+ m_subtreeHeaderCount = m_SubtreeHeaders.size();
+
+ //PCK: clear m_quantizedLeafNodes and m_leafNodes, they are temporary
+ m_quantizedLeafNodes.clear();
+ m_leafNodes.clear();
+}
+
+
+
+
+void b3OptimizedBvh::refit(b3StridingMeshInterface* meshInterface,const b3Vector3& aabbMin,const b3Vector3& aabbMax)
+{
+ if (m_useQuantization)
+ {
+
+ setQuantizationValues(aabbMin,aabbMax);
+
+ updateBvhNodes(meshInterface,0,m_curNodeIndex,0);
+
+ ///now update all subtree headers
+
+ int i;
+ for (i=0;i<m_SubtreeHeaders.size();i++)
+ {
+ b3BvhSubtreeInfo& subtree = m_SubtreeHeaders[i];
+ subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[subtree.m_rootNodeIndex]);
+ }
+
+ } else
+ {
+
+ }
+}
+
+
+
+
+void b3OptimizedBvh::refitPartial(b3StridingMeshInterface* meshInterface,const b3Vector3& aabbMin,const b3Vector3& aabbMax)
+{
+ //incrementally initialize quantization values
+ b3Assert(m_useQuantization);
+
+ b3Assert(aabbMin.getX() > m_bvhAabbMin.getX());
+ b3Assert(aabbMin.getY() > m_bvhAabbMin.getY());
+ b3Assert(aabbMin.getZ() > m_bvhAabbMin.getZ());
+
+ b3Assert(aabbMax.getX() < m_bvhAabbMax.getX());
+ b3Assert(aabbMax.getY() < m_bvhAabbMax.getY());
+ b3Assert(aabbMax.getZ() < m_bvhAabbMax.getZ());
+
+ ///we should update all quantization values, using updateBvhNodes(meshInterface);
+ ///but we only update chunks that overlap the given aabb
+
+ unsigned short quantizedQueryAabbMin[3];
+ unsigned short quantizedQueryAabbMax[3];
+
+ quantize(&quantizedQueryAabbMin[0],aabbMin,0);
+ quantize(&quantizedQueryAabbMax[0],aabbMax,1);
+
+ int i;
+ for (i=0;i<this->m_SubtreeHeaders.size();i++)
+ {
+ b3BvhSubtreeInfo& subtree = m_SubtreeHeaders[i];
+
+ //PCK: unsigned instead of bool
+ unsigned overlap = b3TestQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax);
+ if (overlap != 0)
+ {
+ updateBvhNodes(meshInterface,subtree.m_rootNodeIndex,subtree.m_rootNodeIndex+subtree.m_subtreeSize,i);
+
+ subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[subtree.m_rootNodeIndex]);
+ }
+ }
+
+}
+
+void b3OptimizedBvh::updateBvhNodes(b3StridingMeshInterface* meshInterface,int firstNode,int endNode,int index)
+{
+ (void)index;
+
+ b3Assert(m_useQuantization);
+
+ int curNodeSubPart=-1;
+
+ //get access info to trianglemesh data
+ const unsigned char *vertexbase = 0;
+ int numverts = 0;
+ PHY_ScalarType type = PHY_INTEGER;
+ int stride = 0;
+ const unsigned char *indexbase = 0;
+ int indexstride = 0;
+ int numfaces = 0;
+ PHY_ScalarType indicestype = PHY_INTEGER;
+
+ b3Vector3 triangleVerts[3];
+ b3Vector3 aabbMin,aabbMax;
+ const b3Vector3& meshScaling = meshInterface->getScaling();
+
+ int i;
+ for (i=endNode-1;i>=firstNode;i--)
+ {
+
+
+ b3QuantizedBvhNode& curNode = m_quantizedContiguousNodes[i];
+ if (curNode.isLeafNode())
+ {
+ //recalc aabb from triangle data
+ int nodeSubPart = curNode.getPartId();
+ int nodeTriangleIndex = curNode.getTriangleIndex();
+ if (nodeSubPart != curNodeSubPart)
+ {
+ if (curNodeSubPart >= 0)
+ meshInterface->unLockReadOnlyVertexBase(curNodeSubPart);
+ meshInterface->getLockedReadOnlyVertexIndexBase(&vertexbase,numverts, type,stride,&indexbase,indexstride,numfaces,indicestype,nodeSubPart);
+
+ curNodeSubPart = nodeSubPart;
+ b3Assert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT);
+ }
+ //triangles->getLockedReadOnlyVertexIndexBase(vertexBase,numVerts,
+
+ unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride);
+
+
+ for (int j=2;j>=0;j--)
+ {
+
+ int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j];
+ if (type == PHY_FLOAT)
+ {
+ float* graphicsbase = (float*)(vertexbase+graphicsindex*stride);
+ triangleVerts[j] = b3MakeVector3(
+ graphicsbase[0]*meshScaling.getX(),
+ graphicsbase[1]*meshScaling.getY(),
+ graphicsbase[2]*meshScaling.getZ());
+ }
+ else
+ {
+ double* graphicsbase = (double*)(vertexbase+graphicsindex*stride);
+ triangleVerts[j] = b3MakeVector3( b3Scalar(graphicsbase[0]*meshScaling.getX()), b3Scalar(graphicsbase[1]*meshScaling.getY()), b3Scalar(graphicsbase[2]*meshScaling.getZ()));
+ }
+ }
+
+
+
+ aabbMin.setValue(b3Scalar(B3_LARGE_FLOAT),b3Scalar(B3_LARGE_FLOAT),b3Scalar(B3_LARGE_FLOAT));
+ aabbMax.setValue(b3Scalar(-B3_LARGE_FLOAT),b3Scalar(-B3_LARGE_FLOAT),b3Scalar(-B3_LARGE_FLOAT));
+ aabbMin.setMin(triangleVerts[0]);
+ aabbMax.setMax(triangleVerts[0]);
+ aabbMin.setMin(triangleVerts[1]);
+ aabbMax.setMax(triangleVerts[1]);
+ aabbMin.setMin(triangleVerts[2]);
+ aabbMax.setMax(triangleVerts[2]);
+
+ quantize(&curNode.m_quantizedAabbMin[0],aabbMin,0);
+ quantize(&curNode.m_quantizedAabbMax[0],aabbMax,1);
+
+ } else
+ {
+ //combine aabb from both children
+
+ b3QuantizedBvhNode* leftChildNode = &m_quantizedContiguousNodes[i+1];
+
+ b3QuantizedBvhNode* rightChildNode = leftChildNode->isLeafNode() ? &m_quantizedContiguousNodes[i+2] :
+ &m_quantizedContiguousNodes[i+1+leftChildNode->getEscapeIndex()];
+
+
+ {
+ for (int i=0;i<3;i++)
+ {
+ curNode.m_quantizedAabbMin[i] = leftChildNode->m_quantizedAabbMin[i];
+ if (curNode.m_quantizedAabbMin[i]>rightChildNode->m_quantizedAabbMin[i])
+ curNode.m_quantizedAabbMin[i]=rightChildNode->m_quantizedAabbMin[i];
+
+ curNode.m_quantizedAabbMax[i] = leftChildNode->m_quantizedAabbMax[i];
+ if (curNode.m_quantizedAabbMax[i] < rightChildNode->m_quantizedAabbMax[i])
+ curNode.m_quantizedAabbMax[i] = rightChildNode->m_quantizedAabbMax[i];
+ }
+ }
+ }
+
+ }
+
+ if (curNodeSubPart >= 0)
+ meshInterface->unLockReadOnlyVertexBase(curNodeSubPart);
+
+
+}
+
+///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place'
+b3OptimizedBvh* b3OptimizedBvh::deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian)
+{
+ b3QuantizedBvh* bvh = b3QuantizedBvh::deSerializeInPlace(i_alignedDataBuffer,i_dataBufferSize,i_swapEndian);
+
+ //we don't add additional data so just do a static upcast
+ return static_cast<b3OptimizedBvh*>(bvh);
+}
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3OptimizedBvh.h b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3OptimizedBvh.h
new file mode 100644
index 0000000000..0272ef83bf
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3OptimizedBvh.h
@@ -0,0 +1,65 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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.
+*/
+
+///Contains contributions from Disney Studio's
+
+#ifndef B3_OPTIMIZED_BVH_H
+#define B3_OPTIMIZED_BVH_H
+
+#include "b3QuantizedBvh.h"
+
+class b3StridingMeshInterface;
+
+
+///The b3OptimizedBvh extends the b3QuantizedBvh to create AABB tree for triangle meshes, through the b3StridingMeshInterface.
+B3_ATTRIBUTE_ALIGNED16(class) b3OptimizedBvh : public b3QuantizedBvh
+{
+
+public:
+ B3_DECLARE_ALIGNED_ALLOCATOR();
+
+protected:
+
+public:
+
+ b3OptimizedBvh();
+
+ virtual ~b3OptimizedBvh();
+
+ void build(b3StridingMeshInterface* triangles,bool useQuantizedAabbCompression, const b3Vector3& bvhAabbMin, const b3Vector3& bvhAabbMax);
+
+ void refit(b3StridingMeshInterface* triangles,const b3Vector3& aabbMin,const b3Vector3& aabbMax);
+
+ void refitPartial(b3StridingMeshInterface* triangles,const b3Vector3& aabbMin, const b3Vector3& aabbMax);
+
+ void updateBvhNodes(b3StridingMeshInterface* meshInterface,int firstNode,int endNode,int index);
+
+ /// Data buffer MUST be 16 byte aligned
+ virtual bool serializeInPlace(void *o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian) const
+ {
+ return b3QuantizedBvh::serialize(o_alignedDataBuffer,i_dataBufferSize,i_swapEndian);
+
+ }
+
+ ///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place'
+ static b3OptimizedBvh *deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian);
+
+
+};
+
+
+#endif //B3_OPTIMIZED_BVH_H
+
+
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3QuantizedBvh.cpp b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3QuantizedBvh.cpp
new file mode 100644
index 0000000000..52027e1118
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3QuantizedBvh.cpp
@@ -0,0 +1,1301 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "b3QuantizedBvh.h"
+
+#include "Bullet3Geometry/b3AabbUtil.h"
+
+
+#define RAYAABB2
+
+b3QuantizedBvh::b3QuantizedBvh() :
+ m_bulletVersion(B3_BULLET_VERSION),
+ m_useQuantization(false),
+ m_traversalMode(TRAVERSAL_STACKLESS_CACHE_FRIENDLY)
+ //m_traversalMode(TRAVERSAL_STACKLESS)
+ //m_traversalMode(TRAVERSAL_RECURSIVE)
+ ,m_subtreeHeaderCount(0) //PCK: add this line
+{
+ m_bvhAabbMin.setValue(-B3_INFINITY,-B3_INFINITY,-B3_INFINITY);
+ m_bvhAabbMax.setValue(B3_INFINITY,B3_INFINITY,B3_INFINITY);
+}
+
+
+
+
+
+void b3QuantizedBvh::buildInternal()
+{
+ ///assumes that caller filled in the m_quantizedLeafNodes
+ m_useQuantization = true;
+ int numLeafNodes = 0;
+
+ if (m_useQuantization)
+ {
+ //now we have an array of leafnodes in m_leafNodes
+ numLeafNodes = m_quantizedLeafNodes.size();
+
+ m_quantizedContiguousNodes.resize(2*numLeafNodes);
+
+ }
+
+ m_curNodeIndex = 0;
+
+ buildTree(0,numLeafNodes);
+
+ ///if the entire tree is small then subtree size, we need to create a header info for the tree
+ if(m_useQuantization && !m_SubtreeHeaders.size())
+ {
+ b3BvhSubtreeInfo& subtree = m_SubtreeHeaders.expand();
+ subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[0]);
+ subtree.m_rootNodeIndex = 0;
+ subtree.m_subtreeSize = m_quantizedContiguousNodes[0].isLeafNode() ? 1 : m_quantizedContiguousNodes[0].getEscapeIndex();
+ }
+
+ //PCK: update the copy of the size
+ m_subtreeHeaderCount = m_SubtreeHeaders.size();
+
+ //PCK: clear m_quantizedLeafNodes and m_leafNodes, they are temporary
+ m_quantizedLeafNodes.clear();
+ m_leafNodes.clear();
+}
+
+
+
+///just for debugging, to visualize the individual patches/subtrees
+#ifdef DEBUG_PATCH_COLORS
+b3Vector3 color[4]=
+{
+ b3Vector3(1,0,0),
+ b3Vector3(0,1,0),
+ b3Vector3(0,0,1),
+ b3Vector3(0,1,1)
+};
+#endif //DEBUG_PATCH_COLORS
+
+
+
+void b3QuantizedBvh::setQuantizationValues(const b3Vector3& bvhAabbMin,const b3Vector3& bvhAabbMax,b3Scalar quantizationMargin)
+{
+ //enlarge the AABB to avoid division by zero when initializing the quantization values
+ b3Vector3 clampValue =b3MakeVector3(quantizationMargin,quantizationMargin,quantizationMargin);
+ m_bvhAabbMin = bvhAabbMin - clampValue;
+ m_bvhAabbMax = bvhAabbMax + clampValue;
+ b3Vector3 aabbSize = m_bvhAabbMax - m_bvhAabbMin;
+ m_bvhQuantization = b3MakeVector3(b3Scalar(65533.0),b3Scalar(65533.0),b3Scalar(65533.0)) / aabbSize;
+ m_useQuantization = true;
+}
+
+
+
+
+b3QuantizedBvh::~b3QuantizedBvh()
+{
+}
+
+#ifdef DEBUG_TREE_BUILDING
+int gStackDepth = 0;
+int gMaxStackDepth = 0;
+#endif //DEBUG_TREE_BUILDING
+
+void b3QuantizedBvh::buildTree (int startIndex,int endIndex)
+{
+#ifdef DEBUG_TREE_BUILDING
+ gStackDepth++;
+ if (gStackDepth > gMaxStackDepth)
+ gMaxStackDepth = gStackDepth;
+#endif //DEBUG_TREE_BUILDING
+
+
+ int splitAxis, splitIndex, i;
+ int numIndices =endIndex-startIndex;
+ int curIndex = m_curNodeIndex;
+
+ b3Assert(numIndices>0);
+
+ if (numIndices==1)
+ {
+#ifdef DEBUG_TREE_BUILDING
+ gStackDepth--;
+#endif //DEBUG_TREE_BUILDING
+
+ assignInternalNodeFromLeafNode(m_curNodeIndex,startIndex);
+
+ m_curNodeIndex++;
+ return;
+ }
+ //calculate Best Splitting Axis and where to split it. Sort the incoming 'leafNodes' array within range 'startIndex/endIndex'.
+
+ splitAxis = calcSplittingAxis(startIndex,endIndex);
+
+ splitIndex = sortAndCalcSplittingIndex(startIndex,endIndex,splitAxis);
+
+ int internalNodeIndex = m_curNodeIndex;
+
+ //set the min aabb to 'inf' or a max value, and set the max aabb to a -inf/minimum value.
+ //the aabb will be expanded during buildTree/mergeInternalNodeAabb with actual node values
+ setInternalNodeAabbMin(m_curNodeIndex,m_bvhAabbMax);//can't use b3Vector3(B3_INFINITY,B3_INFINITY,B3_INFINITY)) because of quantization
+ setInternalNodeAabbMax(m_curNodeIndex,m_bvhAabbMin);//can't use b3Vector3(-B3_INFINITY,-B3_INFINITY,-B3_INFINITY)) because of quantization
+
+
+ for (i=startIndex;i<endIndex;i++)
+ {
+ mergeInternalNodeAabb(m_curNodeIndex,getAabbMin(i),getAabbMax(i));
+ }
+
+ m_curNodeIndex++;
+
+
+ //internalNode->m_escapeIndex;
+
+ int leftChildNodexIndex = m_curNodeIndex;
+
+ //build left child tree
+ buildTree(startIndex,splitIndex);
+
+ int rightChildNodexIndex = m_curNodeIndex;
+ //build right child tree
+ buildTree(splitIndex,endIndex);
+
+#ifdef DEBUG_TREE_BUILDING
+ gStackDepth--;
+#endif //DEBUG_TREE_BUILDING
+
+ int escapeIndex = m_curNodeIndex - curIndex;
+
+ if (m_useQuantization)
+ {
+ //escapeIndex is the number of nodes of this subtree
+ const int sizeQuantizedNode =sizeof(b3QuantizedBvhNode);
+ const int treeSizeInBytes = escapeIndex * sizeQuantizedNode;
+ if (treeSizeInBytes > MAX_SUBTREE_SIZE_IN_BYTES)
+ {
+ updateSubtreeHeaders(leftChildNodexIndex,rightChildNodexIndex);
+ }
+ } else
+ {
+
+ }
+
+ setInternalNodeEscapeIndex(internalNodeIndex,escapeIndex);
+
+}
+
+void b3QuantizedBvh::updateSubtreeHeaders(int leftChildNodexIndex,int rightChildNodexIndex)
+{
+ b3Assert(m_useQuantization);
+
+ b3QuantizedBvhNode& leftChildNode = m_quantizedContiguousNodes[leftChildNodexIndex];
+ int leftSubTreeSize = leftChildNode.isLeafNode() ? 1 : leftChildNode.getEscapeIndex();
+ int leftSubTreeSizeInBytes = leftSubTreeSize * static_cast<int>(sizeof(b3QuantizedBvhNode));
+
+ b3QuantizedBvhNode& rightChildNode = m_quantizedContiguousNodes[rightChildNodexIndex];
+ int rightSubTreeSize = rightChildNode.isLeafNode() ? 1 : rightChildNode.getEscapeIndex();
+ int rightSubTreeSizeInBytes = rightSubTreeSize * static_cast<int>(sizeof(b3QuantizedBvhNode));
+
+ if(leftSubTreeSizeInBytes <= MAX_SUBTREE_SIZE_IN_BYTES)
+ {
+ b3BvhSubtreeInfo& subtree = m_SubtreeHeaders.expand();
+ subtree.setAabbFromQuantizeNode(leftChildNode);
+ subtree.m_rootNodeIndex = leftChildNodexIndex;
+ subtree.m_subtreeSize = leftSubTreeSize;
+ }
+
+ if(rightSubTreeSizeInBytes <= MAX_SUBTREE_SIZE_IN_BYTES)
+ {
+ b3BvhSubtreeInfo& subtree = m_SubtreeHeaders.expand();
+ subtree.setAabbFromQuantizeNode(rightChildNode);
+ subtree.m_rootNodeIndex = rightChildNodexIndex;
+ subtree.m_subtreeSize = rightSubTreeSize;
+ }
+
+ //PCK: update the copy of the size
+ m_subtreeHeaderCount = m_SubtreeHeaders.size();
+}
+
+
+int b3QuantizedBvh::sortAndCalcSplittingIndex(int startIndex,int endIndex,int splitAxis)
+{
+ int i;
+ int splitIndex =startIndex;
+ int numIndices = endIndex - startIndex;
+ b3Scalar splitValue;
+
+ b3Vector3 means=b3MakeVector3(b3Scalar(0.),b3Scalar(0.),b3Scalar(0.));
+ for (i=startIndex;i<endIndex;i++)
+ {
+ b3Vector3 center = b3Scalar(0.5)*(getAabbMax(i)+getAabbMin(i));
+ means+=center;
+ }
+ means *= (b3Scalar(1.)/(b3Scalar)numIndices);
+
+ splitValue = means[splitAxis];
+
+ //sort leafNodes so all values larger then splitValue comes first, and smaller values start from 'splitIndex'.
+ for (i=startIndex;i<endIndex;i++)
+ {
+ b3Vector3 center = b3Scalar(0.5)*(getAabbMax(i)+getAabbMin(i));
+ if (center[splitAxis] > splitValue)
+ {
+ //swap
+ swapLeafNodes(i,splitIndex);
+ splitIndex++;
+ }
+ }
+
+ //if the splitIndex causes unbalanced trees, fix this by using the center in between startIndex and endIndex
+ //otherwise the tree-building might fail due to stack-overflows in certain cases.
+ //unbalanced1 is unsafe: it can cause stack overflows
+ //bool unbalanced1 = ((splitIndex==startIndex) || (splitIndex == (endIndex-1)));
+
+ //unbalanced2 should work too: always use center (perfect balanced trees)
+ //bool unbalanced2 = true;
+
+ //this should be safe too:
+ int rangeBalancedIndices = numIndices/3;
+ bool unbalanced = ((splitIndex<=(startIndex+rangeBalancedIndices)) || (splitIndex >=(endIndex-1-rangeBalancedIndices)));
+
+ if (unbalanced)
+ {
+ splitIndex = startIndex+ (numIndices>>1);
+ }
+
+ bool unbal = (splitIndex==startIndex) || (splitIndex == (endIndex));
+ (void)unbal;
+ b3Assert(!unbal);
+
+ return splitIndex;
+}
+
+
+int b3QuantizedBvh::calcSplittingAxis(int startIndex,int endIndex)
+{
+ int i;
+
+ b3Vector3 means=b3MakeVector3(b3Scalar(0.),b3Scalar(0.),b3Scalar(0.));
+ b3Vector3 variance=b3MakeVector3(b3Scalar(0.),b3Scalar(0.),b3Scalar(0.));
+ int numIndices = endIndex-startIndex;
+
+ for (i=startIndex;i<endIndex;i++)
+ {
+ b3Vector3 center = b3Scalar(0.5)*(getAabbMax(i)+getAabbMin(i));
+ means+=center;
+ }
+ means *= (b3Scalar(1.)/(b3Scalar)numIndices);
+
+ for (i=startIndex;i<endIndex;i++)
+ {
+ b3Vector3 center = b3Scalar(0.5)*(getAabbMax(i)+getAabbMin(i));
+ b3Vector3 diff2 = center-means;
+ diff2 = diff2 * diff2;
+ variance += diff2;
+ }
+ variance *= (b3Scalar(1.)/ ((b3Scalar)numIndices-1) );
+
+ return variance.maxAxis();
+}
+
+
+
+void b3QuantizedBvh::reportAabbOverlappingNodex(b3NodeOverlapCallback* nodeCallback,const b3Vector3& aabbMin,const b3Vector3& aabbMax) const
+{
+ //either choose recursive traversal (walkTree) or stackless (walkStacklessTree)
+
+ if (m_useQuantization)
+ {
+ ///quantize query AABB
+ unsigned short int quantizedQueryAabbMin[3];
+ unsigned short int quantizedQueryAabbMax[3];
+ quantizeWithClamp(quantizedQueryAabbMin,aabbMin,0);
+ quantizeWithClamp(quantizedQueryAabbMax,aabbMax,1);
+
+ switch (m_traversalMode)
+ {
+ case TRAVERSAL_STACKLESS:
+ walkStacklessQuantizedTree(nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax,0,m_curNodeIndex);
+ break;
+ case TRAVERSAL_STACKLESS_CACHE_FRIENDLY:
+ walkStacklessQuantizedTreeCacheFriendly(nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax);
+ break;
+ case TRAVERSAL_RECURSIVE:
+ {
+ const b3QuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[0];
+ walkRecursiveQuantizedTreeAgainstQueryAabb(rootNode,nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax);
+ }
+ break;
+ default:
+ //unsupported
+ b3Assert(0);
+ }
+ } else
+ {
+ walkStacklessTree(nodeCallback,aabbMin,aabbMax);
+ }
+}
+
+
+static int b3s_maxIterations = 0;
+
+
+void b3QuantizedBvh::walkStacklessTree(b3NodeOverlapCallback* nodeCallback,const b3Vector3& aabbMin,const b3Vector3& aabbMax) const
+{
+ b3Assert(!m_useQuantization);
+
+ const b3OptimizedBvhNode* rootNode = &m_contiguousNodes[0];
+ int escapeIndex, curIndex = 0;
+ int walkIterations = 0;
+ bool isLeafNode;
+ //PCK: unsigned instead of bool
+ unsigned aabbOverlap;
+
+ while (curIndex < m_curNodeIndex)
+ {
+ //catch bugs in tree data
+ b3Assert (walkIterations < m_curNodeIndex);
+
+ walkIterations++;
+ aabbOverlap = b3TestAabbAgainstAabb2(aabbMin,aabbMax,rootNode->m_aabbMinOrg,rootNode->m_aabbMaxOrg);
+ isLeafNode = rootNode->m_escapeIndex == -1;
+
+ //PCK: unsigned instead of bool
+ if (isLeafNode && (aabbOverlap != 0))
+ {
+ nodeCallback->processNode(rootNode->m_subPart,rootNode->m_triangleIndex);
+ }
+
+ //PCK: unsigned instead of bool
+ if ((aabbOverlap != 0) || isLeafNode)
+ {
+ rootNode++;
+ curIndex++;
+ } else
+ {
+ escapeIndex = rootNode->m_escapeIndex;
+ rootNode += escapeIndex;
+ curIndex += escapeIndex;
+ }
+ }
+ if (b3s_maxIterations < walkIterations)
+ b3s_maxIterations = walkIterations;
+
+}
+
+/*
+///this was the original recursive traversal, before we optimized towards stackless traversal
+void b3QuantizedBvh::walkTree(b3OptimizedBvhNode* rootNode,b3NodeOverlapCallback* nodeCallback,const b3Vector3& aabbMin,const b3Vector3& aabbMax) const
+{
+ bool isLeafNode, aabbOverlap = TestAabbAgainstAabb2(aabbMin,aabbMax,rootNode->m_aabbMin,rootNode->m_aabbMax);
+ if (aabbOverlap)
+ {
+ isLeafNode = (!rootNode->m_leftChild && !rootNode->m_rightChild);
+ if (isLeafNode)
+ {
+ nodeCallback->processNode(rootNode);
+ } else
+ {
+ walkTree(rootNode->m_leftChild,nodeCallback,aabbMin,aabbMax);
+ walkTree(rootNode->m_rightChild,nodeCallback,aabbMin,aabbMax);
+ }
+ }
+
+}
+*/
+
+void b3QuantizedBvh::walkRecursiveQuantizedTreeAgainstQueryAabb(const b3QuantizedBvhNode* currentNode,b3NodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const
+{
+ b3Assert(m_useQuantization);
+
+ bool isLeafNode;
+ //PCK: unsigned instead of bool
+ unsigned aabbOverlap;
+
+ //PCK: unsigned instead of bool
+ aabbOverlap = b3TestQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,currentNode->m_quantizedAabbMin,currentNode->m_quantizedAabbMax);
+ isLeafNode = currentNode->isLeafNode();
+
+ //PCK: unsigned instead of bool
+ if (aabbOverlap != 0)
+ {
+ if (isLeafNode)
+ {
+ nodeCallback->processNode(currentNode->getPartId(),currentNode->getTriangleIndex());
+ } else
+ {
+ //process left and right children
+ const b3QuantizedBvhNode* leftChildNode = currentNode+1;
+ walkRecursiveQuantizedTreeAgainstQueryAabb(leftChildNode,nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax);
+
+ const b3QuantizedBvhNode* rightChildNode = leftChildNode->isLeafNode() ? leftChildNode+1:leftChildNode+leftChildNode->getEscapeIndex();
+ walkRecursiveQuantizedTreeAgainstQueryAabb(rightChildNode,nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax);
+ }
+ }
+}
+
+
+
+void b3QuantizedBvh::walkStacklessTreeAgainstRay(b3NodeOverlapCallback* nodeCallback, const b3Vector3& raySource, const b3Vector3& rayTarget, const b3Vector3& aabbMin, const b3Vector3& aabbMax, int startNodeIndex,int endNodeIndex) const
+{
+ b3Assert(!m_useQuantization);
+
+ const b3OptimizedBvhNode* rootNode = &m_contiguousNodes[0];
+ int escapeIndex, curIndex = 0;
+ int walkIterations = 0;
+ bool isLeafNode;
+ //PCK: unsigned instead of bool
+ unsigned aabbOverlap=0;
+ unsigned rayBoxOverlap=0;
+ b3Scalar lambda_max = 1.0;
+
+ /* Quick pruning by quantized box */
+ b3Vector3 rayAabbMin = raySource;
+ b3Vector3 rayAabbMax = raySource;
+ rayAabbMin.setMin(rayTarget);
+ rayAabbMax.setMax(rayTarget);
+
+ /* Add box cast extents to bounding box */
+ rayAabbMin += aabbMin;
+ rayAabbMax += aabbMax;
+
+#ifdef RAYAABB2
+ b3Vector3 rayDir = (rayTarget-raySource);
+ rayDir.normalize ();
+ lambda_max = rayDir.dot(rayTarget-raySource);
+ ///what about division by zero? --> just set rayDirection[i] to 1.0
+ b3Vector3 rayDirectionInverse;
+ rayDirectionInverse[0] = rayDir[0] == b3Scalar(0.0) ? b3Scalar(B3_LARGE_FLOAT) : b3Scalar(1.0) / rayDir[0];
+ rayDirectionInverse[1] = rayDir[1] == b3Scalar(0.0) ? b3Scalar(B3_LARGE_FLOAT) : b3Scalar(1.0) / rayDir[1];
+ rayDirectionInverse[2] = rayDir[2] == b3Scalar(0.0) ? b3Scalar(B3_LARGE_FLOAT) : b3Scalar(1.0) / rayDir[2];
+ unsigned int sign[3] = { rayDirectionInverse[0] < 0.0, rayDirectionInverse[1] < 0.0, rayDirectionInverse[2] < 0.0};
+#endif
+
+ b3Vector3 bounds[2];
+
+ while (curIndex < m_curNodeIndex)
+ {
+ b3Scalar param = 1.0;
+ //catch bugs in tree data
+ b3Assert (walkIterations < m_curNodeIndex);
+
+ walkIterations++;
+
+ bounds[0] = rootNode->m_aabbMinOrg;
+ bounds[1] = rootNode->m_aabbMaxOrg;
+ /* Add box cast extents */
+ bounds[0] -= aabbMax;
+ bounds[1] -= aabbMin;
+
+ aabbOverlap = b3TestAabbAgainstAabb2(rayAabbMin,rayAabbMax,rootNode->m_aabbMinOrg,rootNode->m_aabbMaxOrg);
+ //perhaps profile if it is worth doing the aabbOverlap test first
+
+#ifdef RAYAABB2
+ ///careful with this check: need to check division by zero (above) and fix the unQuantize method
+ ///thanks Joerg/hiker for the reproduction case!
+ ///http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1858
+ rayBoxOverlap = aabbOverlap ? b3RayAabb2 (raySource, rayDirectionInverse, sign, bounds, param, 0.0f, lambda_max) : false;
+
+#else
+ b3Vector3 normal;
+ rayBoxOverlap = b3RayAabb(raySource, rayTarget,bounds[0],bounds[1],param, normal);
+#endif
+
+ isLeafNode = rootNode->m_escapeIndex == -1;
+
+ //PCK: unsigned instead of bool
+ if (isLeafNode && (rayBoxOverlap != 0))
+ {
+ nodeCallback->processNode(rootNode->m_subPart,rootNode->m_triangleIndex);
+ }
+
+ //PCK: unsigned instead of bool
+ if ((rayBoxOverlap != 0) || isLeafNode)
+ {
+ rootNode++;
+ curIndex++;
+ } else
+ {
+ escapeIndex = rootNode->m_escapeIndex;
+ rootNode += escapeIndex;
+ curIndex += escapeIndex;
+ }
+ }
+ if (b3s_maxIterations < walkIterations)
+ b3s_maxIterations = walkIterations;
+
+}
+
+
+
+void b3QuantizedBvh::walkStacklessQuantizedTreeAgainstRay(b3NodeOverlapCallback* nodeCallback, const b3Vector3& raySource, const b3Vector3& rayTarget, const b3Vector3& aabbMin, const b3Vector3& aabbMax, int startNodeIndex,int endNodeIndex) const
+{
+ b3Assert(m_useQuantization);
+
+ int curIndex = startNodeIndex;
+ int walkIterations = 0;
+ int subTreeSize = endNodeIndex - startNodeIndex;
+ (void)subTreeSize;
+
+ const b3QuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[startNodeIndex];
+ int escapeIndex;
+
+ bool isLeafNode;
+ //PCK: unsigned instead of bool
+ unsigned boxBoxOverlap = 0;
+ unsigned rayBoxOverlap = 0;
+
+ b3Scalar lambda_max = 1.0;
+
+#ifdef RAYAABB2
+ b3Vector3 rayDirection = (rayTarget-raySource);
+ rayDirection.normalize ();
+ lambda_max = rayDirection.dot(rayTarget-raySource);
+ ///what about division by zero? --> just set rayDirection[i] to 1.0
+ rayDirection[0] = rayDirection[0] == b3Scalar(0.0) ? b3Scalar(B3_LARGE_FLOAT) : b3Scalar(1.0) / rayDirection[0];
+ rayDirection[1] = rayDirection[1] == b3Scalar(0.0) ? b3Scalar(B3_LARGE_FLOAT) : b3Scalar(1.0) / rayDirection[1];
+ rayDirection[2] = rayDirection[2] == b3Scalar(0.0) ? b3Scalar(B3_LARGE_FLOAT) : b3Scalar(1.0) / rayDirection[2];
+ unsigned int sign[3] = { rayDirection[0] < 0.0, rayDirection[1] < 0.0, rayDirection[2] < 0.0};
+#endif
+
+ /* Quick pruning by quantized box */
+ b3Vector3 rayAabbMin = raySource;
+ b3Vector3 rayAabbMax = raySource;
+ rayAabbMin.setMin(rayTarget);
+ rayAabbMax.setMax(rayTarget);
+
+ /* Add box cast extents to bounding box */
+ rayAabbMin += aabbMin;
+ rayAabbMax += aabbMax;
+
+ unsigned short int quantizedQueryAabbMin[3];
+ unsigned short int quantizedQueryAabbMax[3];
+ quantizeWithClamp(quantizedQueryAabbMin,rayAabbMin,0);
+ quantizeWithClamp(quantizedQueryAabbMax,rayAabbMax,1);
+
+ while (curIndex < endNodeIndex)
+ {
+
+//#define VISUALLY_ANALYZE_BVH 1
+#ifdef VISUALLY_ANALYZE_BVH
+ //some code snippet to debugDraw aabb, to visually analyze bvh structure
+ static int drawPatch = 0;
+ //need some global access to a debugDrawer
+ extern b3IDebugDraw* debugDrawerPtr;
+ if (curIndex==drawPatch)
+ {
+ b3Vector3 aabbMin,aabbMax;
+ aabbMin = unQuantize(rootNode->m_quantizedAabbMin);
+ aabbMax = unQuantize(rootNode->m_quantizedAabbMax);
+ b3Vector3 color(1,0,0);
+ debugDrawerPtr->drawAabb(aabbMin,aabbMax,color);
+ }
+#endif//VISUALLY_ANALYZE_BVH
+
+ //catch bugs in tree data
+ b3Assert (walkIterations < subTreeSize);
+
+ walkIterations++;
+ //PCK: unsigned instead of bool
+ // only interested if this is closer than any previous hit
+ b3Scalar param = 1.0;
+ rayBoxOverlap = 0;
+ boxBoxOverlap = b3TestQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,rootNode->m_quantizedAabbMin,rootNode->m_quantizedAabbMax);
+ isLeafNode = rootNode->isLeafNode();
+ if (boxBoxOverlap)
+ {
+ b3Vector3 bounds[2];
+ bounds[0] = unQuantize(rootNode->m_quantizedAabbMin);
+ bounds[1] = unQuantize(rootNode->m_quantizedAabbMax);
+ /* Add box cast extents */
+ bounds[0] -= aabbMax;
+ bounds[1] -= aabbMin;
+#if 0
+ b3Vector3 normal;
+ bool ra2 = b3RayAabb2 (raySource, rayDirection, sign, bounds, param, 0.0, lambda_max);
+ bool ra = b3RayAabb (raySource, rayTarget, bounds[0], bounds[1], param, normal);
+ if (ra2 != ra)
+ {
+ printf("functions don't match\n");
+ }
+#endif
+#ifdef RAYAABB2
+ ///careful with this check: need to check division by zero (above) and fix the unQuantize method
+ ///thanks Joerg/hiker for the reproduction case!
+ ///http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1858
+
+ //B3_PROFILE("b3RayAabb2");
+ rayBoxOverlap = b3RayAabb2 (raySource, rayDirection, sign, bounds, param, 0.0f, lambda_max);
+
+#else
+ rayBoxOverlap = true;//b3RayAabb(raySource, rayTarget, bounds[0], bounds[1], param, normal);
+#endif
+ }
+
+ if (isLeafNode && rayBoxOverlap)
+ {
+ nodeCallback->processNode(rootNode->getPartId(),rootNode->getTriangleIndex());
+ }
+
+ //PCK: unsigned instead of bool
+ if ((rayBoxOverlap != 0) || isLeafNode)
+ {
+ rootNode++;
+ curIndex++;
+ } else
+ {
+ escapeIndex = rootNode->getEscapeIndex();
+ rootNode += escapeIndex;
+ curIndex += escapeIndex;
+ }
+ }
+ if (b3s_maxIterations < walkIterations)
+ b3s_maxIterations = walkIterations;
+
+}
+
+void b3QuantizedBvh::walkStacklessQuantizedTree(b3NodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,int startNodeIndex,int endNodeIndex) const
+{
+ b3Assert(m_useQuantization);
+
+ int curIndex = startNodeIndex;
+ int walkIterations = 0;
+ int subTreeSize = endNodeIndex - startNodeIndex;
+ (void)subTreeSize;
+
+ const b3QuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[startNodeIndex];
+ int escapeIndex;
+
+ bool isLeafNode;
+ //PCK: unsigned instead of bool
+ unsigned aabbOverlap;
+
+ while (curIndex < endNodeIndex)
+ {
+
+//#define VISUALLY_ANALYZE_BVH 1
+#ifdef VISUALLY_ANALYZE_BVH
+ //some code snippet to debugDraw aabb, to visually analyze bvh structure
+ static int drawPatch = 0;
+ //need some global access to a debugDrawer
+ extern b3IDebugDraw* debugDrawerPtr;
+ if (curIndex==drawPatch)
+ {
+ b3Vector3 aabbMin,aabbMax;
+ aabbMin = unQuantize(rootNode->m_quantizedAabbMin);
+ aabbMax = unQuantize(rootNode->m_quantizedAabbMax);
+ b3Vector3 color(1,0,0);
+ debugDrawerPtr->drawAabb(aabbMin,aabbMax,color);
+ }
+#endif//VISUALLY_ANALYZE_BVH
+
+ //catch bugs in tree data
+ b3Assert (walkIterations < subTreeSize);
+
+ walkIterations++;
+ //PCK: unsigned instead of bool
+ aabbOverlap = b3TestQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,rootNode->m_quantizedAabbMin,rootNode->m_quantizedAabbMax);
+ isLeafNode = rootNode->isLeafNode();
+
+ if (isLeafNode && aabbOverlap)
+ {
+ nodeCallback->processNode(rootNode->getPartId(),rootNode->getTriangleIndex());
+ }
+
+ //PCK: unsigned instead of bool
+ if ((aabbOverlap != 0) || isLeafNode)
+ {
+ rootNode++;
+ curIndex++;
+ } else
+ {
+ escapeIndex = rootNode->getEscapeIndex();
+ rootNode += escapeIndex;
+ curIndex += escapeIndex;
+ }
+ }
+ if (b3s_maxIterations < walkIterations)
+ b3s_maxIterations = walkIterations;
+
+}
+
+//This traversal can be called from Playstation 3 SPU
+void b3QuantizedBvh::walkStacklessQuantizedTreeCacheFriendly(b3NodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const
+{
+ b3Assert(m_useQuantization);
+
+ int i;
+
+
+ for (i=0;i<this->m_SubtreeHeaders.size();i++)
+ {
+ const b3BvhSubtreeInfo& subtree = m_SubtreeHeaders[i];
+
+ //PCK: unsigned instead of bool
+ unsigned overlap = b3TestQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax);
+ if (overlap != 0)
+ {
+ walkStacklessQuantizedTree(nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax,
+ subtree.m_rootNodeIndex,
+ subtree.m_rootNodeIndex+subtree.m_subtreeSize);
+ }
+ }
+}
+
+
+void b3QuantizedBvh::reportRayOverlappingNodex (b3NodeOverlapCallback* nodeCallback, const b3Vector3& raySource, const b3Vector3& rayTarget) const
+{
+ reportBoxCastOverlappingNodex(nodeCallback,raySource,rayTarget,b3MakeVector3(0,0,0),b3MakeVector3(0,0,0));
+}
+
+
+void b3QuantizedBvh::reportBoxCastOverlappingNodex(b3NodeOverlapCallback* nodeCallback, const b3Vector3& raySource, const b3Vector3& rayTarget, const b3Vector3& aabbMin,const b3Vector3& aabbMax) const
+{
+ //always use stackless
+
+ if (m_useQuantization)
+ {
+ walkStacklessQuantizedTreeAgainstRay(nodeCallback, raySource, rayTarget, aabbMin, aabbMax, 0, m_curNodeIndex);
+ }
+ else
+ {
+ walkStacklessTreeAgainstRay(nodeCallback, raySource, rayTarget, aabbMin, aabbMax, 0, m_curNodeIndex);
+ }
+ /*
+ {
+ //recursive traversal
+ b3Vector3 qaabbMin = raySource;
+ b3Vector3 qaabbMax = raySource;
+ qaabbMin.setMin(rayTarget);
+ qaabbMax.setMax(rayTarget);
+ qaabbMin += aabbMin;
+ qaabbMax += aabbMax;
+ reportAabbOverlappingNodex(nodeCallback,qaabbMin,qaabbMax);
+ }
+ */
+
+}
+
+
+void b3QuantizedBvh::swapLeafNodes(int i,int splitIndex)
+{
+ if (m_useQuantization)
+ {
+ b3QuantizedBvhNode tmp = m_quantizedLeafNodes[i];
+ m_quantizedLeafNodes[i] = m_quantizedLeafNodes[splitIndex];
+ m_quantizedLeafNodes[splitIndex] = tmp;
+ } else
+ {
+ b3OptimizedBvhNode tmp = m_leafNodes[i];
+ m_leafNodes[i] = m_leafNodes[splitIndex];
+ m_leafNodes[splitIndex] = tmp;
+ }
+}
+
+void b3QuantizedBvh::assignInternalNodeFromLeafNode(int internalNode,int leafNodeIndex)
+{
+ if (m_useQuantization)
+ {
+ m_quantizedContiguousNodes[internalNode] = m_quantizedLeafNodes[leafNodeIndex];
+ } else
+ {
+ m_contiguousNodes[internalNode] = m_leafNodes[leafNodeIndex];
+ }
+}
+
+//PCK: include
+#include <new>
+
+#if 0
+//PCK: consts
+static const unsigned BVH_ALIGNMENT = 16;
+static const unsigned BVH_ALIGNMENT_MASK = BVH_ALIGNMENT-1;
+
+static const unsigned BVH_ALIGNMENT_BLOCKS = 2;
+#endif
+
+
+unsigned int b3QuantizedBvh::getAlignmentSerializationPadding()
+{
+ // I changed this to 0 since the extra padding is not needed or used.
+ return 0;//BVH_ALIGNMENT_BLOCKS * BVH_ALIGNMENT;
+}
+
+unsigned b3QuantizedBvh::calculateSerializeBufferSize() const
+{
+ unsigned baseSize = sizeof(b3QuantizedBvh) + getAlignmentSerializationPadding();
+ baseSize += sizeof(b3BvhSubtreeInfo) * m_subtreeHeaderCount;
+ if (m_useQuantization)
+ {
+ return baseSize + m_curNodeIndex * sizeof(b3QuantizedBvhNode);
+ }
+ return baseSize + m_curNodeIndex * sizeof(b3OptimizedBvhNode);
+}
+
+bool b3QuantizedBvh::serialize(void *o_alignedDataBuffer, unsigned /*i_dataBufferSize */, bool i_swapEndian) const
+{
+ b3Assert(m_subtreeHeaderCount == m_SubtreeHeaders.size());
+ m_subtreeHeaderCount = m_SubtreeHeaders.size();
+
+/* if (i_dataBufferSize < calculateSerializeBufferSize() || o_alignedDataBuffer == NULL || (((unsigned)o_alignedDataBuffer & BVH_ALIGNMENT_MASK) != 0))
+ {
+ ///check alignedment for buffer?
+ b3Assert(0);
+ return false;
+ }
+*/
+
+ b3QuantizedBvh *targetBvh = (b3QuantizedBvh *)o_alignedDataBuffer;
+
+ // construct the class so the virtual function table, etc will be set up
+ // Also, m_leafNodes and m_quantizedLeafNodes will be initialized to default values by the constructor
+ new (targetBvh) b3QuantizedBvh;
+
+ if (i_swapEndian)
+ {
+ targetBvh->m_curNodeIndex = static_cast<int>(b3SwapEndian(m_curNodeIndex));
+
+
+ b3SwapVector3Endian(m_bvhAabbMin,targetBvh->m_bvhAabbMin);
+ b3SwapVector3Endian(m_bvhAabbMax,targetBvh->m_bvhAabbMax);
+ b3SwapVector3Endian(m_bvhQuantization,targetBvh->m_bvhQuantization);
+
+ targetBvh->m_traversalMode = (b3TraversalMode)b3SwapEndian(m_traversalMode);
+ targetBvh->m_subtreeHeaderCount = static_cast<int>(b3SwapEndian(m_subtreeHeaderCount));
+ }
+ else
+ {
+ targetBvh->m_curNodeIndex = m_curNodeIndex;
+ targetBvh->m_bvhAabbMin = m_bvhAabbMin;
+ targetBvh->m_bvhAabbMax = m_bvhAabbMax;
+ targetBvh->m_bvhQuantization = m_bvhQuantization;
+ targetBvh->m_traversalMode = m_traversalMode;
+ targetBvh->m_subtreeHeaderCount = m_subtreeHeaderCount;
+ }
+
+ targetBvh->m_useQuantization = m_useQuantization;
+
+ unsigned char *nodeData = (unsigned char *)targetBvh;
+ nodeData += sizeof(b3QuantizedBvh);
+
+ unsigned sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK;
+ nodeData += sizeToAdd;
+
+ int nodeCount = m_curNodeIndex;
+
+ if (m_useQuantization)
+ {
+ targetBvh->m_quantizedContiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount);
+
+ if (i_swapEndian)
+ {
+ for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
+ {
+ targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] = b3SwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0]);
+ targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1] = b3SwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1]);
+ targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2] = b3SwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2]);
+
+ targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0] = b3SwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0]);
+ targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1] = b3SwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1]);
+ targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2] = b3SwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2]);
+
+ targetBvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = static_cast<int>(b3SwapEndian(m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex));
+ }
+ }
+ else
+ {
+ for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
+ {
+
+ targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0];
+ targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1];
+ targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2];
+
+ targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0];
+ targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1];
+ targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2];
+
+ targetBvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex;
+
+
+ }
+ }
+ nodeData += sizeof(b3QuantizedBvhNode) * nodeCount;
+
+ // this clears the pointer in the member variable it doesn't really do anything to the data
+ // it does call the destructor on the contained objects, but they are all classes with no destructor defined
+ // so the memory (which is not freed) is left alone
+ targetBvh->m_quantizedContiguousNodes.initializeFromBuffer(NULL, 0, 0);
+ }
+ else
+ {
+ targetBvh->m_contiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount);
+
+ if (i_swapEndian)
+ {
+ for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
+ {
+ b3SwapVector3Endian(m_contiguousNodes[nodeIndex].m_aabbMinOrg, targetBvh->m_contiguousNodes[nodeIndex].m_aabbMinOrg);
+ b3SwapVector3Endian(m_contiguousNodes[nodeIndex].m_aabbMaxOrg, targetBvh->m_contiguousNodes[nodeIndex].m_aabbMaxOrg);
+
+ targetBvh->m_contiguousNodes[nodeIndex].m_escapeIndex = static_cast<int>(b3SwapEndian(m_contiguousNodes[nodeIndex].m_escapeIndex));
+ targetBvh->m_contiguousNodes[nodeIndex].m_subPart = static_cast<int>(b3SwapEndian(m_contiguousNodes[nodeIndex].m_subPart));
+ targetBvh->m_contiguousNodes[nodeIndex].m_triangleIndex = static_cast<int>(b3SwapEndian(m_contiguousNodes[nodeIndex].m_triangleIndex));
+ }
+ }
+ else
+ {
+ for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
+ {
+ targetBvh->m_contiguousNodes[nodeIndex].m_aabbMinOrg = m_contiguousNodes[nodeIndex].m_aabbMinOrg;
+ targetBvh->m_contiguousNodes[nodeIndex].m_aabbMaxOrg = m_contiguousNodes[nodeIndex].m_aabbMaxOrg;
+
+ targetBvh->m_contiguousNodes[nodeIndex].m_escapeIndex = m_contiguousNodes[nodeIndex].m_escapeIndex;
+ targetBvh->m_contiguousNodes[nodeIndex].m_subPart = m_contiguousNodes[nodeIndex].m_subPart;
+ targetBvh->m_contiguousNodes[nodeIndex].m_triangleIndex = m_contiguousNodes[nodeIndex].m_triangleIndex;
+ }
+ }
+ nodeData += sizeof(b3OptimizedBvhNode) * nodeCount;
+
+ // this clears the pointer in the member variable it doesn't really do anything to the data
+ // it does call the destructor on the contained objects, but they are all classes with no destructor defined
+ // so the memory (which is not freed) is left alone
+ targetBvh->m_contiguousNodes.initializeFromBuffer(NULL, 0, 0);
+ }
+
+ sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK;
+ nodeData += sizeToAdd;
+
+ // Now serialize the subtree headers
+ targetBvh->m_SubtreeHeaders.initializeFromBuffer(nodeData, m_subtreeHeaderCount, m_subtreeHeaderCount);
+ if (i_swapEndian)
+ {
+ for (int i = 0; i < m_subtreeHeaderCount; i++)
+ {
+ targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0] = b3SwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMin[0]);
+ targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1] = b3SwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMin[1]);
+ targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2] = b3SwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMin[2]);
+
+ targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0] = b3SwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMax[0]);
+ targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1] = b3SwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMax[1]);
+ targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2] = b3SwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMax[2]);
+
+ targetBvh->m_SubtreeHeaders[i].m_rootNodeIndex = static_cast<int>(b3SwapEndian(m_SubtreeHeaders[i].m_rootNodeIndex));
+ targetBvh->m_SubtreeHeaders[i].m_subtreeSize = static_cast<int>(b3SwapEndian(m_SubtreeHeaders[i].m_subtreeSize));
+ }
+ }
+ else
+ {
+ for (int i = 0; i < m_subtreeHeaderCount; i++)
+ {
+ targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0] = (m_SubtreeHeaders[i].m_quantizedAabbMin[0]);
+ targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1] = (m_SubtreeHeaders[i].m_quantizedAabbMin[1]);
+ targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2] = (m_SubtreeHeaders[i].m_quantizedAabbMin[2]);
+
+ targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0] = (m_SubtreeHeaders[i].m_quantizedAabbMax[0]);
+ targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1] = (m_SubtreeHeaders[i].m_quantizedAabbMax[1]);
+ targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2] = (m_SubtreeHeaders[i].m_quantizedAabbMax[2]);
+
+ targetBvh->m_SubtreeHeaders[i].m_rootNodeIndex = (m_SubtreeHeaders[i].m_rootNodeIndex);
+ targetBvh->m_SubtreeHeaders[i].m_subtreeSize = (m_SubtreeHeaders[i].m_subtreeSize);
+
+ // need to clear padding in destination buffer
+ targetBvh->m_SubtreeHeaders[i].m_padding[0] = 0;
+ targetBvh->m_SubtreeHeaders[i].m_padding[1] = 0;
+ targetBvh->m_SubtreeHeaders[i].m_padding[2] = 0;
+ }
+ }
+ nodeData += sizeof(b3BvhSubtreeInfo) * m_subtreeHeaderCount;
+
+ // this clears the pointer in the member variable it doesn't really do anything to the data
+ // it does call the destructor on the contained objects, but they are all classes with no destructor defined
+ // so the memory (which is not freed) is left alone
+ targetBvh->m_SubtreeHeaders.initializeFromBuffer(NULL, 0, 0);
+
+ // this wipes the virtual function table pointer at the start of the buffer for the class
+ *((void**)o_alignedDataBuffer) = NULL;
+
+ return true;
+}
+
+b3QuantizedBvh *b3QuantizedBvh::deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian)
+{
+
+ if (i_alignedDataBuffer == NULL)// || (((unsigned)i_alignedDataBuffer & BVH_ALIGNMENT_MASK) != 0))
+ {
+ return NULL;
+ }
+ b3QuantizedBvh *bvh = (b3QuantizedBvh *)i_alignedDataBuffer;
+
+ if (i_swapEndian)
+ {
+ bvh->m_curNodeIndex = static_cast<int>(b3SwapEndian(bvh->m_curNodeIndex));
+
+ b3UnSwapVector3Endian(bvh->m_bvhAabbMin);
+ b3UnSwapVector3Endian(bvh->m_bvhAabbMax);
+ b3UnSwapVector3Endian(bvh->m_bvhQuantization);
+
+ bvh->m_traversalMode = (b3TraversalMode)b3SwapEndian(bvh->m_traversalMode);
+ bvh->m_subtreeHeaderCount = static_cast<int>(b3SwapEndian(bvh->m_subtreeHeaderCount));
+ }
+
+ unsigned int calculatedBufSize = bvh->calculateSerializeBufferSize();
+ b3Assert(calculatedBufSize <= i_dataBufferSize);
+
+ if (calculatedBufSize > i_dataBufferSize)
+ {
+ return NULL;
+ }
+
+ unsigned char *nodeData = (unsigned char *)bvh;
+ nodeData += sizeof(b3QuantizedBvh);
+
+ unsigned sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK;
+ nodeData += sizeToAdd;
+
+ int nodeCount = bvh->m_curNodeIndex;
+
+ // Must call placement new to fill in virtual function table, etc, but we don't want to overwrite most data, so call a special version of the constructor
+ // Also, m_leafNodes and m_quantizedLeafNodes will be initialized to default values by the constructor
+ new (bvh) b3QuantizedBvh(*bvh, false);
+
+ if (bvh->m_useQuantization)
+ {
+ bvh->m_quantizedContiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount);
+
+ if (i_swapEndian)
+ {
+ for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
+ {
+ bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] = b3SwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0]);
+ bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1] = b3SwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1]);
+ bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2] = b3SwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2]);
+
+ bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0] = b3SwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0]);
+ bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1] = b3SwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1]);
+ bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2] = b3SwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2]);
+
+ bvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = static_cast<int>(b3SwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex));
+ }
+ }
+ nodeData += sizeof(b3QuantizedBvhNode) * nodeCount;
+ }
+ else
+ {
+ bvh->m_contiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount);
+
+ if (i_swapEndian)
+ {
+ for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
+ {
+ b3UnSwapVector3Endian(bvh->m_contiguousNodes[nodeIndex].m_aabbMinOrg);
+ b3UnSwapVector3Endian(bvh->m_contiguousNodes[nodeIndex].m_aabbMaxOrg);
+
+ bvh->m_contiguousNodes[nodeIndex].m_escapeIndex = static_cast<int>(b3SwapEndian(bvh->m_contiguousNodes[nodeIndex].m_escapeIndex));
+ bvh->m_contiguousNodes[nodeIndex].m_subPart = static_cast<int>(b3SwapEndian(bvh->m_contiguousNodes[nodeIndex].m_subPart));
+ bvh->m_contiguousNodes[nodeIndex].m_triangleIndex = static_cast<int>(b3SwapEndian(bvh->m_contiguousNodes[nodeIndex].m_triangleIndex));
+ }
+ }
+ nodeData += sizeof(b3OptimizedBvhNode) * nodeCount;
+ }
+
+ sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK;
+ nodeData += sizeToAdd;
+
+ // Now serialize the subtree headers
+ bvh->m_SubtreeHeaders.initializeFromBuffer(nodeData, bvh->m_subtreeHeaderCount, bvh->m_subtreeHeaderCount);
+ if (i_swapEndian)
+ {
+ for (int i = 0; i < bvh->m_subtreeHeaderCount; i++)
+ {
+ bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0] = b3SwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0]);
+ bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1] = b3SwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1]);
+ bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2] = b3SwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2]);
+
+ bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0] = b3SwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0]);
+ bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1] = b3SwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1]);
+ bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2] = b3SwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2]);
+
+ bvh->m_SubtreeHeaders[i].m_rootNodeIndex = static_cast<int>(b3SwapEndian(bvh->m_SubtreeHeaders[i].m_rootNodeIndex));
+ bvh->m_SubtreeHeaders[i].m_subtreeSize = static_cast<int>(b3SwapEndian(bvh->m_SubtreeHeaders[i].m_subtreeSize));
+ }
+ }
+
+ return bvh;
+}
+
+// Constructor that prevents b3Vector3's default constructor from being called
+b3QuantizedBvh::b3QuantizedBvh(b3QuantizedBvh &self, bool /* ownsMemory */) :
+m_bvhAabbMin(self.m_bvhAabbMin),
+m_bvhAabbMax(self.m_bvhAabbMax),
+m_bvhQuantization(self.m_bvhQuantization),
+m_bulletVersion(B3_BULLET_VERSION)
+{
+
+}
+
+void b3QuantizedBvh::deSerializeFloat(struct b3QuantizedBvhFloatData& quantizedBvhFloatData)
+{
+ m_bvhAabbMax.deSerializeFloat(quantizedBvhFloatData.m_bvhAabbMax);
+ m_bvhAabbMin.deSerializeFloat(quantizedBvhFloatData.m_bvhAabbMin);
+ m_bvhQuantization.deSerializeFloat(quantizedBvhFloatData.m_bvhQuantization);
+
+ m_curNodeIndex = quantizedBvhFloatData.m_curNodeIndex;
+ m_useQuantization = quantizedBvhFloatData.m_useQuantization!=0;
+
+ {
+ int numElem = quantizedBvhFloatData.m_numContiguousLeafNodes;
+ m_contiguousNodes.resize(numElem);
+
+ if (numElem)
+ {
+ b3OptimizedBvhNodeFloatData* memPtr = quantizedBvhFloatData.m_contiguousNodesPtr;
+
+ for (int i=0;i<numElem;i++,memPtr++)
+ {
+ m_contiguousNodes[i].m_aabbMaxOrg.deSerializeFloat(memPtr->m_aabbMaxOrg);
+ m_contiguousNodes[i].m_aabbMinOrg.deSerializeFloat(memPtr->m_aabbMinOrg);
+ m_contiguousNodes[i].m_escapeIndex = memPtr->m_escapeIndex;
+ m_contiguousNodes[i].m_subPart = memPtr->m_subPart;
+ m_contiguousNodes[i].m_triangleIndex = memPtr->m_triangleIndex;
+ }
+ }
+ }
+
+ {
+ int numElem = quantizedBvhFloatData.m_numQuantizedContiguousNodes;
+ m_quantizedContiguousNodes.resize(numElem);
+
+ if (numElem)
+ {
+ b3QuantizedBvhNodeData* memPtr = quantizedBvhFloatData.m_quantizedContiguousNodesPtr;
+ for (int i=0;i<numElem;i++,memPtr++)
+ {
+ m_quantizedContiguousNodes[i].m_escapeIndexOrTriangleIndex = memPtr->m_escapeIndexOrTriangleIndex;
+ m_quantizedContiguousNodes[i].m_quantizedAabbMax[0] = memPtr->m_quantizedAabbMax[0];
+ m_quantizedContiguousNodes[i].m_quantizedAabbMax[1] = memPtr->m_quantizedAabbMax[1];
+ m_quantizedContiguousNodes[i].m_quantizedAabbMax[2] = memPtr->m_quantizedAabbMax[2];
+ m_quantizedContiguousNodes[i].m_quantizedAabbMin[0] = memPtr->m_quantizedAabbMin[0];
+ m_quantizedContiguousNodes[i].m_quantizedAabbMin[1] = memPtr->m_quantizedAabbMin[1];
+ m_quantizedContiguousNodes[i].m_quantizedAabbMin[2] = memPtr->m_quantizedAabbMin[2];
+ }
+ }
+ }
+
+ m_traversalMode = b3TraversalMode(quantizedBvhFloatData.m_traversalMode);
+
+ {
+ int numElem = quantizedBvhFloatData.m_numSubtreeHeaders;
+ m_SubtreeHeaders.resize(numElem);
+ if (numElem)
+ {
+ b3BvhSubtreeInfoData* memPtr = quantizedBvhFloatData.m_subTreeInfoPtr;
+ for (int i=0;i<numElem;i++,memPtr++)
+ {
+ m_SubtreeHeaders[i].m_quantizedAabbMax[0] = memPtr->m_quantizedAabbMax[0] ;
+ m_SubtreeHeaders[i].m_quantizedAabbMax[1] = memPtr->m_quantizedAabbMax[1];
+ m_SubtreeHeaders[i].m_quantizedAabbMax[2] = memPtr->m_quantizedAabbMax[2];
+ m_SubtreeHeaders[i].m_quantizedAabbMin[0] = memPtr->m_quantizedAabbMin[0];
+ m_SubtreeHeaders[i].m_quantizedAabbMin[1] = memPtr->m_quantizedAabbMin[1];
+ m_SubtreeHeaders[i].m_quantizedAabbMin[2] = memPtr->m_quantizedAabbMin[2];
+ m_SubtreeHeaders[i].m_rootNodeIndex = memPtr->m_rootNodeIndex;
+ m_SubtreeHeaders[i].m_subtreeSize = memPtr->m_subtreeSize;
+ }
+ }
+ }
+}
+
+void b3QuantizedBvh::deSerializeDouble(struct b3QuantizedBvhDoubleData& quantizedBvhDoubleData)
+{
+ m_bvhAabbMax.deSerializeDouble(quantizedBvhDoubleData.m_bvhAabbMax);
+ m_bvhAabbMin.deSerializeDouble(quantizedBvhDoubleData.m_bvhAabbMin);
+ m_bvhQuantization.deSerializeDouble(quantizedBvhDoubleData.m_bvhQuantization);
+
+ m_curNodeIndex = quantizedBvhDoubleData.m_curNodeIndex;
+ m_useQuantization = quantizedBvhDoubleData.m_useQuantization!=0;
+
+ {
+ int numElem = quantizedBvhDoubleData.m_numContiguousLeafNodes;
+ m_contiguousNodes.resize(numElem);
+
+ if (numElem)
+ {
+ b3OptimizedBvhNodeDoubleData* memPtr = quantizedBvhDoubleData.m_contiguousNodesPtr;
+
+ for (int i=0;i<numElem;i++,memPtr++)
+ {
+ m_contiguousNodes[i].m_aabbMaxOrg.deSerializeDouble(memPtr->m_aabbMaxOrg);
+ m_contiguousNodes[i].m_aabbMinOrg.deSerializeDouble(memPtr->m_aabbMinOrg);
+ m_contiguousNodes[i].m_escapeIndex = memPtr->m_escapeIndex;
+ m_contiguousNodes[i].m_subPart = memPtr->m_subPart;
+ m_contiguousNodes[i].m_triangleIndex = memPtr->m_triangleIndex;
+ }
+ }
+ }
+
+ {
+ int numElem = quantizedBvhDoubleData.m_numQuantizedContiguousNodes;
+ m_quantizedContiguousNodes.resize(numElem);
+
+ if (numElem)
+ {
+ b3QuantizedBvhNodeData* memPtr = quantizedBvhDoubleData.m_quantizedContiguousNodesPtr;
+ for (int i=0;i<numElem;i++,memPtr++)
+ {
+ m_quantizedContiguousNodes[i].m_escapeIndexOrTriangleIndex = memPtr->m_escapeIndexOrTriangleIndex;
+ m_quantizedContiguousNodes[i].m_quantizedAabbMax[0] = memPtr->m_quantizedAabbMax[0];
+ m_quantizedContiguousNodes[i].m_quantizedAabbMax[1] = memPtr->m_quantizedAabbMax[1];
+ m_quantizedContiguousNodes[i].m_quantizedAabbMax[2] = memPtr->m_quantizedAabbMax[2];
+ m_quantizedContiguousNodes[i].m_quantizedAabbMin[0] = memPtr->m_quantizedAabbMin[0];
+ m_quantizedContiguousNodes[i].m_quantizedAabbMin[1] = memPtr->m_quantizedAabbMin[1];
+ m_quantizedContiguousNodes[i].m_quantizedAabbMin[2] = memPtr->m_quantizedAabbMin[2];
+ }
+ }
+ }
+
+ m_traversalMode = b3TraversalMode(quantizedBvhDoubleData.m_traversalMode);
+
+ {
+ int numElem = quantizedBvhDoubleData.m_numSubtreeHeaders;
+ m_SubtreeHeaders.resize(numElem);
+ if (numElem)
+ {
+ b3BvhSubtreeInfoData* memPtr = quantizedBvhDoubleData.m_subTreeInfoPtr;
+ for (int i=0;i<numElem;i++,memPtr++)
+ {
+ m_SubtreeHeaders[i].m_quantizedAabbMax[0] = memPtr->m_quantizedAabbMax[0] ;
+ m_SubtreeHeaders[i].m_quantizedAabbMax[1] = memPtr->m_quantizedAabbMax[1];
+ m_SubtreeHeaders[i].m_quantizedAabbMax[2] = memPtr->m_quantizedAabbMax[2];
+ m_SubtreeHeaders[i].m_quantizedAabbMin[0] = memPtr->m_quantizedAabbMin[0];
+ m_SubtreeHeaders[i].m_quantizedAabbMin[1] = memPtr->m_quantizedAabbMin[1];
+ m_SubtreeHeaders[i].m_quantizedAabbMin[2] = memPtr->m_quantizedAabbMin[2];
+ m_SubtreeHeaders[i].m_rootNodeIndex = memPtr->m_rootNodeIndex;
+ m_SubtreeHeaders[i].m_subtreeSize = memPtr->m_subtreeSize;
+ }
+ }
+ }
+
+}
+
+
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+const char* b3QuantizedBvh::serialize(void* dataBuffer, b3Serializer* serializer) const
+{
+ b3Assert(0);
+ return 0;
+}
+
+
+
+
+
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3QuantizedBvh.h b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3QuantizedBvh.h
new file mode 100644
index 0000000000..63c523c758
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3QuantizedBvh.h
@@ -0,0 +1,556 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef B3_QUANTIZED_BVH_H
+#define B3_QUANTIZED_BVH_H
+
+class b3Serializer;
+
+//#define DEBUG_CHECK_DEQUANTIZATION 1
+#ifdef DEBUG_CHECK_DEQUANTIZATION
+#ifdef __SPU__
+#define printf spu_printf
+#endif //__SPU__
+
+#include <stdio.h>
+#include <stdlib.h>
+#endif //DEBUG_CHECK_DEQUANTIZATION
+
+#include "Bullet3Common/b3Vector3.h"
+#include "Bullet3Common/b3AlignedAllocator.h"
+
+#ifdef B3_USE_DOUBLE_PRECISION
+#define b3QuantizedBvhData b3QuantizedBvhDoubleData
+#define b3OptimizedBvhNodeData b3OptimizedBvhNodeDoubleData
+#define b3QuantizedBvhDataName "b3QuantizedBvhDoubleData"
+#else
+#define b3QuantizedBvhData b3QuantizedBvhFloatData
+#define b3OptimizedBvhNodeData b3OptimizedBvhNodeFloatData
+#define b3QuantizedBvhDataName "b3QuantizedBvhFloatData"
+#endif
+
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3QuantizedBvhNodeData.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3BvhSubtreeInfoData.h"
+
+
+
+//http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/vclrf__m128.asp
+
+
+//Note: currently we have 16 bytes per quantized node
+#define MAX_SUBTREE_SIZE_IN_BYTES 2048
+
+// 10 gives the potential for 1024 parts, with at most 2^21 (2097152) (minus one
+// actually) triangles each (since the sign bit is reserved
+#define MAX_NUM_PARTS_IN_BITS 10
+
+///b3QuantizedBvhNode is a compressed aabb node, 16 bytes.
+///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range).
+B3_ATTRIBUTE_ALIGNED16 (struct) b3QuantizedBvhNode : public b3QuantizedBvhNodeData
+{
+ B3_DECLARE_ALIGNED_ALLOCATOR();
+
+ bool isLeafNode() const
+ {
+ //skipindex is negative (internal node), triangleindex >=0 (leafnode)
+ return (m_escapeIndexOrTriangleIndex >= 0);
+ }
+ int getEscapeIndex() const
+ {
+ b3Assert(!isLeafNode());
+ return -m_escapeIndexOrTriangleIndex;
+ }
+ int getTriangleIndex() const
+ {
+ b3Assert(isLeafNode());
+ unsigned int x=0;
+ unsigned int y = (~(x&0))<<(31-MAX_NUM_PARTS_IN_BITS);
+ // Get only the lower bits where the triangle index is stored
+ return (m_escapeIndexOrTriangleIndex&~(y));
+ }
+ int getPartId() const
+ {
+ b3Assert(isLeafNode());
+ // Get only the highest bits where the part index is stored
+ return (m_escapeIndexOrTriangleIndex>>(31-MAX_NUM_PARTS_IN_BITS));
+ }
+}
+;
+
+/// b3OptimizedBvhNode contains both internal and leaf node information.
+/// Total node size is 44 bytes / node. You can use the compressed version of 16 bytes.
+B3_ATTRIBUTE_ALIGNED16 (struct) b3OptimizedBvhNode
+{
+ B3_DECLARE_ALIGNED_ALLOCATOR();
+
+ //32 bytes
+ b3Vector3 m_aabbMinOrg;
+ b3Vector3 m_aabbMaxOrg;
+
+ //4
+ int m_escapeIndex;
+
+ //8
+ //for child nodes
+ int m_subPart;
+ int m_triangleIndex;
+
+//pad the size to 64 bytes
+ char m_padding[20];
+};
+
+
+///b3BvhSubtreeInfo provides info to gather a subtree of limited size
+B3_ATTRIBUTE_ALIGNED16(class) b3BvhSubtreeInfo : public b3BvhSubtreeInfoData
+{
+public:
+ B3_DECLARE_ALIGNED_ALLOCATOR();
+
+ b3BvhSubtreeInfo()
+ {
+ //memset(&m_padding[0], 0, sizeof(m_padding));
+ }
+
+
+ void setAabbFromQuantizeNode(const b3QuantizedBvhNode& quantizedNode)
+ {
+ m_quantizedAabbMin[0] = quantizedNode.m_quantizedAabbMin[0];
+ m_quantizedAabbMin[1] = quantizedNode.m_quantizedAabbMin[1];
+ m_quantizedAabbMin[2] = quantizedNode.m_quantizedAabbMin[2];
+ m_quantizedAabbMax[0] = quantizedNode.m_quantizedAabbMax[0];
+ m_quantizedAabbMax[1] = quantizedNode.m_quantizedAabbMax[1];
+ m_quantizedAabbMax[2] = quantizedNode.m_quantizedAabbMax[2];
+ }
+}
+;
+
+
+class b3NodeOverlapCallback
+{
+public:
+ virtual ~b3NodeOverlapCallback() {};
+
+ virtual void processNode(int subPart, int triangleIndex) = 0;
+};
+
+#include "Bullet3Common/b3AlignedAllocator.h"
+#include "Bullet3Common/b3AlignedObjectArray.h"
+
+
+
+///for code readability:
+typedef b3AlignedObjectArray<b3OptimizedBvhNode> NodeArray;
+typedef b3AlignedObjectArray<b3QuantizedBvhNode> QuantizedNodeArray;
+typedef b3AlignedObjectArray<b3BvhSubtreeInfo> BvhSubtreeInfoArray;
+
+
+///The b3QuantizedBvh class stores an AABB tree that can be quickly traversed on CPU and Cell SPU.
+///It is used by the b3BvhTriangleMeshShape as midphase
+///It is recommended to use quantization for better performance and lower memory requirements.
+B3_ATTRIBUTE_ALIGNED16(class) b3QuantizedBvh
+{
+public:
+ enum b3TraversalMode
+ {
+ TRAVERSAL_STACKLESS = 0,
+ TRAVERSAL_STACKLESS_CACHE_FRIENDLY,
+ TRAVERSAL_RECURSIVE
+ };
+
+
+
+
+ b3Vector3 m_bvhAabbMin;
+ b3Vector3 m_bvhAabbMax;
+ b3Vector3 m_bvhQuantization;
+
+protected:
+ int m_bulletVersion; //for serialization versioning. It could also be used to detect endianess.
+
+ int m_curNodeIndex;
+ //quantization data
+ bool m_useQuantization;
+
+
+
+ NodeArray m_leafNodes;
+ NodeArray m_contiguousNodes;
+ QuantizedNodeArray m_quantizedLeafNodes;
+ QuantizedNodeArray m_quantizedContiguousNodes;
+
+ b3TraversalMode m_traversalMode;
+ BvhSubtreeInfoArray m_SubtreeHeaders;
+
+ //This is only used for serialization so we don't have to add serialization directly to b3AlignedObjectArray
+ mutable int m_subtreeHeaderCount;
+
+
+
+
+
+ ///two versions, one for quantized and normal nodes. This allows code-reuse while maintaining readability (no template/macro!)
+ ///this might be refactored into a virtual, it is usually not calculated at run-time
+ void setInternalNodeAabbMin(int nodeIndex, const b3Vector3& aabbMin)
+ {
+ if (m_useQuantization)
+ {
+ quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] ,aabbMin,0);
+ } else
+ {
+ m_contiguousNodes[nodeIndex].m_aabbMinOrg = aabbMin;
+
+ }
+ }
+ void setInternalNodeAabbMax(int nodeIndex,const b3Vector3& aabbMax)
+ {
+ if (m_useQuantization)
+ {
+ quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0],aabbMax,1);
+ } else
+ {
+ m_contiguousNodes[nodeIndex].m_aabbMaxOrg = aabbMax;
+ }
+ }
+
+ b3Vector3 getAabbMin(int nodeIndex) const
+ {
+ if (m_useQuantization)
+ {
+ return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMin[0]);
+ }
+ //non-quantized
+ return m_leafNodes[nodeIndex].m_aabbMinOrg;
+
+ }
+ b3Vector3 getAabbMax(int nodeIndex) const
+ {
+ if (m_useQuantization)
+ {
+ return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMax[0]);
+ }
+ //non-quantized
+ return m_leafNodes[nodeIndex].m_aabbMaxOrg;
+
+ }
+
+
+ void setInternalNodeEscapeIndex(int nodeIndex, int escapeIndex)
+ {
+ if (m_useQuantization)
+ {
+ m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = -escapeIndex;
+ }
+ else
+ {
+ m_contiguousNodes[nodeIndex].m_escapeIndex = escapeIndex;
+ }
+
+ }
+
+ void mergeInternalNodeAabb(int nodeIndex,const b3Vector3& newAabbMin,const b3Vector3& newAabbMax)
+ {
+ if (m_useQuantization)
+ {
+ unsigned short int quantizedAabbMin[3];
+ unsigned short int quantizedAabbMax[3];
+ quantize(quantizedAabbMin,newAabbMin,0);
+ quantize(quantizedAabbMax,newAabbMax,1);
+ for (int i=0;i<3;i++)
+ {
+ if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] > quantizedAabbMin[i])
+ m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] = quantizedAabbMin[i];
+
+ if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] < quantizedAabbMax[i])
+ m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] = quantizedAabbMax[i];
+
+ }
+ } else
+ {
+ //non-quantized
+ m_contiguousNodes[nodeIndex].m_aabbMinOrg.setMin(newAabbMin);
+ m_contiguousNodes[nodeIndex].m_aabbMaxOrg.setMax(newAabbMax);
+ }
+ }
+
+ void swapLeafNodes(int firstIndex,int secondIndex);
+
+ void assignInternalNodeFromLeafNode(int internalNode,int leafNodeIndex);
+
+protected:
+
+
+
+ void buildTree (int startIndex,int endIndex);
+
+ int calcSplittingAxis(int startIndex,int endIndex);
+
+ int sortAndCalcSplittingIndex(int startIndex,int endIndex,int splitAxis);
+
+ void walkStacklessTree(b3NodeOverlapCallback* nodeCallback,const b3Vector3& aabbMin,const b3Vector3& aabbMax) const;
+
+ void walkStacklessQuantizedTreeAgainstRay(b3NodeOverlapCallback* nodeCallback, const b3Vector3& raySource, const b3Vector3& rayTarget, const b3Vector3& aabbMin, const b3Vector3& aabbMax, int startNodeIndex,int endNodeIndex) const;
+ void walkStacklessQuantizedTree(b3NodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,int startNodeIndex,int endNodeIndex) const;
+ void walkStacklessTreeAgainstRay(b3NodeOverlapCallback* nodeCallback, const b3Vector3& raySource, const b3Vector3& rayTarget, const b3Vector3& aabbMin, const b3Vector3& aabbMax, int startNodeIndex,int endNodeIndex) const;
+
+ ///tree traversal designed for small-memory processors like PS3 SPU
+ void walkStacklessQuantizedTreeCacheFriendly(b3NodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const;
+
+ ///use the 16-byte stackless 'skipindex' node tree to do a recursive traversal
+ void walkRecursiveQuantizedTreeAgainstQueryAabb(const b3QuantizedBvhNode* currentNode,b3NodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const;
+
+ ///use the 16-byte stackless 'skipindex' node tree to do a recursive traversal
+ void walkRecursiveQuantizedTreeAgainstQuantizedTree(const b3QuantizedBvhNode* treeNodeA,const b3QuantizedBvhNode* treeNodeB,b3NodeOverlapCallback* nodeCallback) const;
+
+
+
+
+ void updateSubtreeHeaders(int leftChildNodexIndex,int rightChildNodexIndex);
+
+public:
+
+ B3_DECLARE_ALIGNED_ALLOCATOR();
+
+ b3QuantizedBvh();
+
+ virtual ~b3QuantizedBvh();
+
+
+ ///***************************************** expert/internal use only *************************
+ void setQuantizationValues(const b3Vector3& bvhAabbMin,const b3Vector3& bvhAabbMax,b3Scalar quantizationMargin=b3Scalar(1.0));
+ QuantizedNodeArray& getLeafNodeArray() { return m_quantizedLeafNodes; }
+ ///buildInternal is expert use only: assumes that setQuantizationValues and LeafNodeArray are initialized
+ void buildInternal();
+ ///***************************************** expert/internal use only *************************
+
+ void reportAabbOverlappingNodex(b3NodeOverlapCallback* nodeCallback,const b3Vector3& aabbMin,const b3Vector3& aabbMax) const;
+ void reportRayOverlappingNodex (b3NodeOverlapCallback* nodeCallback, const b3Vector3& raySource, const b3Vector3& rayTarget) const;
+ void reportBoxCastOverlappingNodex(b3NodeOverlapCallback* nodeCallback, const b3Vector3& raySource, const b3Vector3& rayTarget, const b3Vector3& aabbMin,const b3Vector3& aabbMax) const;
+
+ B3_FORCE_INLINE void quantize(unsigned short* out, const b3Vector3& point,int isMax) const
+ {
+
+ b3Assert(m_useQuantization);
+
+ b3Assert(point.getX() <= m_bvhAabbMax.getX());
+ b3Assert(point.getY() <= m_bvhAabbMax.getY());
+ b3Assert(point.getZ() <= m_bvhAabbMax.getZ());
+
+ b3Assert(point.getX() >= m_bvhAabbMin.getX());
+ b3Assert(point.getY() >= m_bvhAabbMin.getY());
+ b3Assert(point.getZ() >= m_bvhAabbMin.getZ());
+
+ b3Vector3 v = (point - m_bvhAabbMin) * m_bvhQuantization;
+ ///Make sure rounding is done in a way that unQuantize(quantizeWithClamp(...)) is conservative
+ ///end-points always set the first bit, so that they are sorted properly (so that neighbouring AABBs overlap properly)
+ ///@todo: double-check this
+ if (isMax)
+ {
+ out[0] = (unsigned short) (((unsigned short)(v.getX()+b3Scalar(1.)) | 1));
+ out[1] = (unsigned short) (((unsigned short)(v.getY()+b3Scalar(1.)) | 1));
+ out[2] = (unsigned short) (((unsigned short)(v.getZ()+b3Scalar(1.)) | 1));
+ } else
+ {
+ out[0] = (unsigned short) (((unsigned short)(v.getX()) & 0xfffe));
+ out[1] = (unsigned short) (((unsigned short)(v.getY()) & 0xfffe));
+ out[2] = (unsigned short) (((unsigned short)(v.getZ()) & 0xfffe));
+ }
+
+
+#ifdef DEBUG_CHECK_DEQUANTIZATION
+ b3Vector3 newPoint = unQuantize(out);
+ if (isMax)
+ {
+ if (newPoint.getX() < point.getX())
+ {
+ printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n",newPoint.getX()-point.getX(), newPoint.getX(),point.getX());
+ }
+ if (newPoint.getY() < point.getY())
+ {
+ printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n",newPoint.getY()-point.getY(), newPoint.getY(),point.getY());
+ }
+ if (newPoint.getZ() < point.getZ())
+ {
+
+ printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n",newPoint.getZ()-point.getZ(), newPoint.getZ(),point.getZ());
+ }
+ } else
+ {
+ if (newPoint.getX() > point.getX())
+ {
+ printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n",newPoint.getX()-point.getX(), newPoint.getX(),point.getX());
+ }
+ if (newPoint.getY() > point.getY())
+ {
+ printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n",newPoint.getY()-point.getY(), newPoint.getY(),point.getY());
+ }
+ if (newPoint.getZ() > point.getZ())
+ {
+ printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n",newPoint.getZ()-point.getZ(), newPoint.getZ(),point.getZ());
+ }
+ }
+#endif //DEBUG_CHECK_DEQUANTIZATION
+
+ }
+
+
+ B3_FORCE_INLINE void quantizeWithClamp(unsigned short* out, const b3Vector3& point2,int isMax) const
+ {
+
+ b3Assert(m_useQuantization);
+
+ b3Vector3 clampedPoint(point2);
+ clampedPoint.setMax(m_bvhAabbMin);
+ clampedPoint.setMin(m_bvhAabbMax);
+
+ quantize(out,clampedPoint,isMax);
+
+ }
+
+ B3_FORCE_INLINE b3Vector3 unQuantize(const unsigned short* vecIn) const
+ {
+ b3Vector3 vecOut;
+ vecOut.setValue(
+ (b3Scalar)(vecIn[0]) / (m_bvhQuantization.getX()),
+ (b3Scalar)(vecIn[1]) / (m_bvhQuantization.getY()),
+ (b3Scalar)(vecIn[2]) / (m_bvhQuantization.getZ()));
+ vecOut += m_bvhAabbMin;
+ return vecOut;
+ }
+
+ ///setTraversalMode let's you choose between stackless, recursive or stackless cache friendly tree traversal. Note this is only implemented for quantized trees.
+ void setTraversalMode(b3TraversalMode traversalMode)
+ {
+ m_traversalMode = traversalMode;
+ }
+
+
+ B3_FORCE_INLINE QuantizedNodeArray& getQuantizedNodeArray()
+ {
+ return m_quantizedContiguousNodes;
+ }
+
+
+ B3_FORCE_INLINE BvhSubtreeInfoArray& getSubtreeInfoArray()
+ {
+ return m_SubtreeHeaders;
+ }
+
+////////////////////////////////////////////////////////////////////
+
+ /////Calculate space needed to store BVH for serialization
+ unsigned calculateSerializeBufferSize() const;
+
+ /// Data buffer MUST be 16 byte aligned
+ virtual bool serialize(void *o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian) const;
+
+ ///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place'
+ static b3QuantizedBvh *deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian);
+
+ static unsigned int getAlignmentSerializationPadding();
+//////////////////////////////////////////////////////////////////////
+
+
+ virtual int calculateSerializeBufferSizeNew() const;
+
+ ///fills the dataBuffer and returns the struct name (and 0 on failure)
+ virtual const char* serialize(void* dataBuffer, b3Serializer* serializer) const;
+
+ virtual void deSerializeFloat(struct b3QuantizedBvhFloatData& quantizedBvhFloatData);
+
+ virtual void deSerializeDouble(struct b3QuantizedBvhDoubleData& quantizedBvhDoubleData);
+
+
+////////////////////////////////////////////////////////////////////
+
+ B3_FORCE_INLINE bool isQuantized()
+ {
+ return m_useQuantization;
+ }
+
+private:
+ // Special "copy" constructor that allows for in-place deserialization
+ // Prevents b3Vector3's default constructor from being called, but doesn't inialize much else
+ // ownsMemory should most likely be false if deserializing, and if you are not, don't call this (it also changes the function signature, which we need)
+ b3QuantizedBvh(b3QuantizedBvh &other, bool ownsMemory);
+
+}
+;
+
+
+struct b3OptimizedBvhNodeFloatData
+{
+ b3Vector3FloatData m_aabbMinOrg;
+ b3Vector3FloatData m_aabbMaxOrg;
+ int m_escapeIndex;
+ int m_subPart;
+ int m_triangleIndex;
+ char m_pad[4];
+};
+
+struct b3OptimizedBvhNodeDoubleData
+{
+ b3Vector3DoubleData m_aabbMinOrg;
+ b3Vector3DoubleData m_aabbMaxOrg;
+ int m_escapeIndex;
+ int m_subPart;
+ int m_triangleIndex;
+ char m_pad[4];
+};
+
+
+
+struct b3QuantizedBvhFloatData
+{
+ b3Vector3FloatData m_bvhAabbMin;
+ b3Vector3FloatData m_bvhAabbMax;
+ b3Vector3FloatData m_bvhQuantization;
+ int m_curNodeIndex;
+ int m_useQuantization;
+ int m_numContiguousLeafNodes;
+ int m_numQuantizedContiguousNodes;
+ b3OptimizedBvhNodeFloatData *m_contiguousNodesPtr;
+ b3QuantizedBvhNodeData *m_quantizedContiguousNodesPtr;
+ b3BvhSubtreeInfoData *m_subTreeInfoPtr;
+ int m_traversalMode;
+ int m_numSubtreeHeaders;
+
+};
+
+struct b3QuantizedBvhDoubleData
+{
+ b3Vector3DoubleData m_bvhAabbMin;
+ b3Vector3DoubleData m_bvhAabbMax;
+ b3Vector3DoubleData m_bvhQuantization;
+ int m_curNodeIndex;
+ int m_useQuantization;
+ int m_numContiguousLeafNodes;
+ int m_numQuantizedContiguousNodes;
+ b3OptimizedBvhNodeDoubleData *m_contiguousNodesPtr;
+ b3QuantizedBvhNodeData *m_quantizedContiguousNodesPtr;
+
+ int m_traversalMode;
+ int m_numSubtreeHeaders;
+ b3BvhSubtreeInfoData *m_subTreeInfoPtr;
+};
+
+
+B3_FORCE_INLINE int b3QuantizedBvh::calculateSerializeBufferSizeNew() const
+{
+ return sizeof(b3QuantizedBvhData);
+}
+
+
+
+#endif //B3_QUANTIZED_BVH_H
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3StridingMeshInterface.cpp b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3StridingMeshInterface.cpp
new file mode 100644
index 0000000000..4d97f7f62b
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3StridingMeshInterface.cpp
@@ -0,0 +1,214 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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 "b3StridingMeshInterface.h"
+
+
+b3StridingMeshInterface::~b3StridingMeshInterface()
+{
+
+}
+
+
+void b3StridingMeshInterface::InternalProcessAllTriangles(b3InternalTriangleIndexCallback* callback,const b3Vector3& aabbMin,const b3Vector3& aabbMax) const
+{
+ (void)aabbMin;
+ (void)aabbMax;
+ int numtotalphysicsverts = 0;
+ int part,graphicssubparts = getNumSubParts();
+ const unsigned char * vertexbase;
+ const unsigned char * indexbase;
+ int indexstride;
+ PHY_ScalarType type;
+ PHY_ScalarType gfxindextype;
+ int stride,numverts,numtriangles;
+ int gfxindex;
+ b3Vector3 triangle[3];
+
+ b3Vector3 meshScaling = getScaling();
+
+ ///if the number of parts is big, the performance might drop due to the innerloop switch on indextype
+ for (part=0;part<graphicssubparts ;part++)
+ {
+ getLockedReadOnlyVertexIndexBase(&vertexbase,numverts,type,stride,&indexbase,indexstride,numtriangles,gfxindextype,part);
+ numtotalphysicsverts+=numtriangles*3; //upper bound
+
+ ///unlike that developers want to pass in double-precision meshes in single-precision Bullet build
+ ///so disable this feature by default
+ ///see patch http://code.google.com/p/bullet/issues/detail?id=213
+
+ switch (type)
+ {
+ case PHY_FLOAT:
+ {
+
+ float* graphicsbase;
+
+ switch (gfxindextype)
+ {
+ case PHY_INTEGER:
+ {
+ for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
+ {
+ unsigned int* tri_indices= (unsigned int*)(indexbase+gfxindex*indexstride);
+ graphicsbase = (float*)(vertexbase+tri_indices[0]*stride);
+ triangle[0].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());
+ graphicsbase = (float*)(vertexbase+tri_indices[1]*stride);
+ triangle[1].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(), graphicsbase[2]*meshScaling.getZ());
+ graphicsbase = (float*)(vertexbase+tri_indices[2]*stride);
+ triangle[2].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(), graphicsbase[2]*meshScaling.getZ());
+ callback->internalProcessTriangleIndex(triangle,part,gfxindex);
+ }
+ break;
+ }
+ case PHY_SHORT:
+ {
+ for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
+ {
+ unsigned short int* tri_indices= (unsigned short int*)(indexbase+gfxindex*indexstride);
+ graphicsbase = (float*)(vertexbase+tri_indices[0]*stride);
+ triangle[0].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());
+ graphicsbase = (float*)(vertexbase+tri_indices[1]*stride);
+ triangle[1].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(), graphicsbase[2]*meshScaling.getZ());
+ graphicsbase = (float*)(vertexbase+tri_indices[2]*stride);
+ triangle[2].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(), graphicsbase[2]*meshScaling.getZ());
+ callback->internalProcessTriangleIndex(triangle,part,gfxindex);
+ }
+ break;
+ }
+ case PHY_UCHAR:
+ {
+ for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
+ {
+ unsigned char* tri_indices= (unsigned char*)(indexbase+gfxindex*indexstride);
+ graphicsbase = (float*)(vertexbase+tri_indices[0]*stride);
+ triangle[0].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());
+ graphicsbase = (float*)(vertexbase+tri_indices[1]*stride);
+ triangle[1].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(), graphicsbase[2]*meshScaling.getZ());
+ graphicsbase = (float*)(vertexbase+tri_indices[2]*stride);
+ triangle[2].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(), graphicsbase[2]*meshScaling.getZ());
+ callback->internalProcessTriangleIndex(triangle,part,gfxindex);
+ }
+ break;
+ }
+ default:
+ b3Assert((gfxindextype == PHY_INTEGER) || (gfxindextype == PHY_SHORT));
+ }
+ break;
+ }
+
+ case PHY_DOUBLE:
+ {
+ double* graphicsbase;
+
+ switch (gfxindextype)
+ {
+ case PHY_INTEGER:
+ {
+ for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
+ {
+ unsigned int* tri_indices= (unsigned int*)(indexbase+gfxindex*indexstride);
+ graphicsbase = (double*)(vertexbase+tri_indices[0]*stride);
+ triangle[0].setValue((b3Scalar)graphicsbase[0]*meshScaling.getX(),(b3Scalar)graphicsbase[1]*meshScaling.getY(),(b3Scalar)graphicsbase[2]*meshScaling.getZ());
+ graphicsbase = (double*)(vertexbase+tri_indices[1]*stride);
+ triangle[1].setValue((b3Scalar)graphicsbase[0]*meshScaling.getX(),(b3Scalar)graphicsbase[1]*meshScaling.getY(), (b3Scalar)graphicsbase[2]*meshScaling.getZ());
+ graphicsbase = (double*)(vertexbase+tri_indices[2]*stride);
+ triangle[2].setValue((b3Scalar)graphicsbase[0]*meshScaling.getX(),(b3Scalar)graphicsbase[1]*meshScaling.getY(), (b3Scalar)graphicsbase[2]*meshScaling.getZ());
+ callback->internalProcessTriangleIndex(triangle,part,gfxindex);
+ }
+ break;
+ }
+ case PHY_SHORT:
+ {
+ for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
+ {
+ unsigned short int* tri_indices= (unsigned short int*)(indexbase+gfxindex*indexstride);
+ graphicsbase = (double*)(vertexbase+tri_indices[0]*stride);
+ triangle[0].setValue((b3Scalar)graphicsbase[0]*meshScaling.getX(),(b3Scalar)graphicsbase[1]*meshScaling.getY(),(b3Scalar)graphicsbase[2]*meshScaling.getZ());
+ graphicsbase = (double*)(vertexbase+tri_indices[1]*stride);
+ triangle[1].setValue((b3Scalar)graphicsbase[0]*meshScaling.getX(),(b3Scalar)graphicsbase[1]*meshScaling.getY(), (b3Scalar)graphicsbase[2]*meshScaling.getZ());
+ graphicsbase = (double*)(vertexbase+tri_indices[2]*stride);
+ triangle[2].setValue((b3Scalar)graphicsbase[0]*meshScaling.getX(),(b3Scalar)graphicsbase[1]*meshScaling.getY(), (b3Scalar)graphicsbase[2]*meshScaling.getZ());
+ callback->internalProcessTriangleIndex(triangle,part,gfxindex);
+ }
+ break;
+ }
+ case PHY_UCHAR:
+ {
+ for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
+ {
+ unsigned char* tri_indices= (unsigned char*)(indexbase+gfxindex*indexstride);
+ graphicsbase = (double*)(vertexbase+tri_indices[0]*stride);
+ triangle[0].setValue((b3Scalar)graphicsbase[0]*meshScaling.getX(),(b3Scalar)graphicsbase[1]*meshScaling.getY(),(b3Scalar)graphicsbase[2]*meshScaling.getZ());
+ graphicsbase = (double*)(vertexbase+tri_indices[1]*stride);
+ triangle[1].setValue((b3Scalar)graphicsbase[0]*meshScaling.getX(),(b3Scalar)graphicsbase[1]*meshScaling.getY(), (b3Scalar)graphicsbase[2]*meshScaling.getZ());
+ graphicsbase = (double*)(vertexbase+tri_indices[2]*stride);
+ triangle[2].setValue((b3Scalar)graphicsbase[0]*meshScaling.getX(),(b3Scalar)graphicsbase[1]*meshScaling.getY(), (b3Scalar)graphicsbase[2]*meshScaling.getZ());
+ callback->internalProcessTriangleIndex(triangle,part,gfxindex);
+ }
+ break;
+ }
+ default:
+ b3Assert((gfxindextype == PHY_INTEGER) || (gfxindextype == PHY_SHORT));
+ }
+ break;
+ }
+ default:
+ b3Assert((type == PHY_FLOAT) || (type == PHY_DOUBLE));
+ }
+
+ unLockReadOnlyVertexBase(part);
+ }
+}
+
+void b3StridingMeshInterface::calculateAabbBruteForce(b3Vector3& aabbMin,b3Vector3& aabbMax)
+{
+
+ struct AabbCalculationCallback : public b3InternalTriangleIndexCallback
+ {
+ b3Vector3 m_aabbMin;
+ b3Vector3 m_aabbMax;
+
+ AabbCalculationCallback()
+ {
+ m_aabbMin.setValue(b3Scalar(B3_LARGE_FLOAT),b3Scalar(B3_LARGE_FLOAT),b3Scalar(B3_LARGE_FLOAT));
+ m_aabbMax.setValue(b3Scalar(-B3_LARGE_FLOAT),b3Scalar(-B3_LARGE_FLOAT),b3Scalar(-B3_LARGE_FLOAT));
+ }
+
+ virtual void internalProcessTriangleIndex(b3Vector3* triangle,int partId,int triangleIndex)
+ {
+ (void)partId;
+ (void)triangleIndex;
+
+ m_aabbMin.setMin(triangle[0]);
+ m_aabbMax.setMax(triangle[0]);
+ m_aabbMin.setMin(triangle[1]);
+ m_aabbMax.setMax(triangle[1]);
+ m_aabbMin.setMin(triangle[2]);
+ m_aabbMax.setMax(triangle[2]);
+ }
+ };
+
+ //first calculate the total aabb for all triangles
+ AabbCalculationCallback aabbCallback;
+ aabbMin.setValue(b3Scalar(-B3_LARGE_FLOAT),b3Scalar(-B3_LARGE_FLOAT),b3Scalar(-B3_LARGE_FLOAT));
+ aabbMax.setValue(b3Scalar(B3_LARGE_FLOAT),b3Scalar(B3_LARGE_FLOAT),b3Scalar(B3_LARGE_FLOAT));
+ InternalProcessAllTriangles(&aabbCallback,aabbMin,aabbMax);
+
+ aabbMin = aabbCallback.m_aabbMin;
+ aabbMax = aabbCallback.m_aabbMax;
+}
+
+
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3StridingMeshInterface.h b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3StridingMeshInterface.h
new file mode 100644
index 0000000000..9513f68f77
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3StridingMeshInterface.h
@@ -0,0 +1,167 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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 B3_STRIDING_MESHINTERFACE_H
+#define B3_STRIDING_MESHINTERFACE_H
+
+#include "Bullet3Common/b3Vector3.h"
+#include "b3TriangleCallback.h"
+//#include "b3ConcaveShape.h"
+
+
+enum PHY_ScalarType {
+ PHY_FLOAT, PHY_DOUBLE, PHY_INTEGER, PHY_SHORT,
+ PHY_FIXEDPOINT88, PHY_UCHAR
+};
+
+
+/// The b3StridingMeshInterface is the interface class for high performance generic access to triangle meshes, used in combination with b3BvhTriangleMeshShape and some other collision shapes.
+/// Using index striding of 3*sizeof(integer) it can use triangle arrays, using index striding of 1*sizeof(integer) it can handle triangle strips.
+/// It allows for sharing graphics and collision meshes. Also it provides locking/unlocking of graphics meshes that are in gpu memory.
+B3_ATTRIBUTE_ALIGNED16(class ) b3StridingMeshInterface
+{
+ protected:
+
+ b3Vector3 m_scaling;
+
+ public:
+ B3_DECLARE_ALIGNED_ALLOCATOR();
+
+ b3StridingMeshInterface() :m_scaling(b3MakeVector3(b3Scalar(1.),b3Scalar(1.),b3Scalar(1.)))
+ {
+
+ }
+
+ virtual ~b3StridingMeshInterface();
+
+
+
+ virtual void InternalProcessAllTriangles(b3InternalTriangleIndexCallback* callback,const b3Vector3& aabbMin,const b3Vector3& aabbMax) const;
+
+ ///brute force method to calculate aabb
+ void calculateAabbBruteForce(b3Vector3& aabbMin,b3Vector3& aabbMax);
+
+ /// get read and write access to a subpart of a triangle mesh
+ /// this subpart has a continuous array of vertices and indices
+ /// in this way the mesh can be handled as chunks of memory with striding
+ /// very similar to OpenGL vertexarray support
+ /// make a call to unLockVertexBase when the read and write access is finished
+ virtual void getLockedVertexIndexBase(unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& stride,unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0)=0;
+
+ virtual void getLockedReadOnlyVertexIndexBase(const unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& stride,const unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0) const=0;
+
+ /// unLockVertexBase finishes the access to a subpart of the triangle mesh
+ /// make a call to unLockVertexBase when the read and write access (using getLockedVertexIndexBase) is finished
+ virtual void unLockVertexBase(int subpart)=0;
+
+ virtual void unLockReadOnlyVertexBase(int subpart) const=0;
+
+
+ /// getNumSubParts returns the number of seperate subparts
+ /// each subpart has a continuous array of vertices and indices
+ virtual int getNumSubParts() const=0;
+
+ virtual void preallocateVertices(int numverts)=0;
+ virtual void preallocateIndices(int numindices)=0;
+
+ virtual bool hasPremadeAabb() const { return false; }
+ virtual void setPremadeAabb(const b3Vector3& aabbMin, const b3Vector3& aabbMax ) const
+ {
+ (void) aabbMin;
+ (void) aabbMax;
+ }
+ virtual void getPremadeAabb(b3Vector3* aabbMin, b3Vector3* aabbMax ) const
+ {
+ (void) aabbMin;
+ (void) aabbMax;
+ }
+
+ const b3Vector3& getScaling() const {
+ return m_scaling;
+ }
+ void setScaling(const b3Vector3& scaling)
+ {
+ m_scaling = scaling;
+ }
+
+ virtual int calculateSerializeBufferSize() const;
+
+ ///fills the dataBuffer and returns the struct name (and 0 on failure)
+ //virtual const char* serialize(void* dataBuffer, b3Serializer* serializer) const;
+
+
+};
+
+struct b3IntIndexData
+{
+ int m_value;
+};
+
+struct b3ShortIntIndexData
+{
+ short m_value;
+ char m_pad[2];
+};
+
+struct b3ShortIntIndexTripletData
+{
+ short m_values[3];
+ char m_pad[2];
+};
+
+struct b3CharIndexTripletData
+{
+ unsigned char m_values[3];
+ char m_pad;
+};
+
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct b3MeshPartData
+{
+ b3Vector3FloatData *m_vertices3f;
+ b3Vector3DoubleData *m_vertices3d;
+
+ b3IntIndexData *m_indices32;
+ b3ShortIntIndexTripletData *m_3indices16;
+ b3CharIndexTripletData *m_3indices8;
+
+ b3ShortIntIndexData *m_indices16;//backwards compatibility
+
+ int m_numTriangles;//length of m_indices = m_numTriangles
+ int m_numVertices;
+};
+
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct b3StridingMeshInterfaceData
+{
+ b3MeshPartData *m_meshPartsPtr;
+ b3Vector3FloatData m_scaling;
+ int m_numMeshParts;
+ char m_padding[4];
+};
+
+
+
+
+B3_FORCE_INLINE int b3StridingMeshInterface::calculateSerializeBufferSize() const
+{
+ return sizeof(b3StridingMeshInterfaceData);
+}
+
+
+
+#endif //B3_STRIDING_MESHINTERFACE_H
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3SupportMappings.h b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3SupportMappings.h
new file mode 100644
index 0000000000..d073ee57c3
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3SupportMappings.h
@@ -0,0 +1,38 @@
+
+#ifndef B3_SUPPORT_MAPPINGS_H
+#define B3_SUPPORT_MAPPINGS_H
+
+#include "Bullet3Common/b3Transform.h"
+#include "Bullet3Common/b3AlignedObjectArray.h"
+#include "b3VectorFloat4.h"
+
+
+struct b3GjkPairDetector;
+
+
+
+inline b3Vector3 localGetSupportVertexWithMargin(const float4& supportVec,const struct b3ConvexPolyhedronData* hull,
+ const b3AlignedObjectArray<b3Vector3>& verticesA, b3Scalar margin)
+{
+ b3Vector3 supVec = b3MakeVector3(b3Scalar(0.),b3Scalar(0.),b3Scalar(0.));
+ b3Scalar maxDot = b3Scalar(-B3_LARGE_FLOAT);
+
+ // Here we take advantage of dot(a, b*c) = dot(a*b, c). Note: This is true mathematically, but not numerically.
+ if( 0 < hull->m_numVertices )
+ {
+ const b3Vector3 scaled = supportVec;
+ int index = (int) scaled.maxDot( &verticesA[hull->m_vertexOffset], hull->m_numVertices, maxDot);
+ return verticesA[hull->m_vertexOffset+index];
+ }
+
+ return supVec;
+
+}
+
+inline b3Vector3 localGetSupportVertexWithoutMargin(const float4& supportVec,const struct b3ConvexPolyhedronData* hull,
+ const b3AlignedObjectArray<b3Vector3>& verticesA)
+{
+ return localGetSupportVertexWithMargin(supportVec,hull,verticesA,0.f);
+}
+
+#endif //B3_SUPPORT_MAPPINGS_H
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3TriangleCallback.cpp b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3TriangleCallback.cpp
new file mode 100644
index 0000000000..9066451884
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3TriangleCallback.cpp
@@ -0,0 +1,28 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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 "b3TriangleCallback.h"
+
+b3TriangleCallback::~b3TriangleCallback()
+{
+
+}
+
+
+b3InternalTriangleIndexCallback::~b3InternalTriangleIndexCallback()
+{
+
+}
+
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3TriangleCallback.h b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3TriangleCallback.h
new file mode 100644
index 0000000000..3059fa4f21
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3TriangleCallback.h
@@ -0,0 +1,42 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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 B3_TRIANGLE_CALLBACK_H
+#define B3_TRIANGLE_CALLBACK_H
+
+#include "Bullet3Common/b3Vector3.h"
+
+
+///The b3TriangleCallback provides a callback for each overlapping triangle when calling processAllTriangles.
+///This callback is called by processAllTriangles for all b3ConcaveShape derived class, such as b3BvhTriangleMeshShape, b3StaticPlaneShape and b3HeightfieldTerrainShape.
+class b3TriangleCallback
+{
+public:
+
+ virtual ~b3TriangleCallback();
+ virtual void processTriangle(b3Vector3* triangle, int partId, int triangleIndex) = 0;
+};
+
+class b3InternalTriangleIndexCallback
+{
+public:
+
+ virtual ~b3InternalTriangleIndexCallback();
+ virtual void internalProcessTriangleIndex(b3Vector3* triangle,int partId,int triangleIndex) = 0;
+};
+
+
+
+#endif //B3_TRIANGLE_CALLBACK_H
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3TriangleIndexVertexArray.cpp b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3TriangleIndexVertexArray.cpp
new file mode 100644
index 0000000000..a0f59babbe
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3TriangleIndexVertexArray.cpp
@@ -0,0 +1,95 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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 "b3TriangleIndexVertexArray.h"
+
+b3TriangleIndexVertexArray::b3TriangleIndexVertexArray(int numTriangles,int* triangleIndexBase,int triangleIndexStride,int numVertices,b3Scalar* vertexBase,int vertexStride)
+: m_hasAabb(0)
+{
+ b3IndexedMesh mesh;
+
+ mesh.m_numTriangles = numTriangles;
+ mesh.m_triangleIndexBase = (const unsigned char *)triangleIndexBase;
+ mesh.m_triangleIndexStride = triangleIndexStride;
+ mesh.m_numVertices = numVertices;
+ mesh.m_vertexBase = (const unsigned char *)vertexBase;
+ mesh.m_vertexStride = vertexStride;
+
+ addIndexedMesh(mesh);
+
+}
+
+b3TriangleIndexVertexArray::~b3TriangleIndexVertexArray()
+{
+
+}
+
+void b3TriangleIndexVertexArray::getLockedVertexIndexBase(unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& vertexStride,unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart)
+{
+ b3Assert(subpart< getNumSubParts() );
+
+ b3IndexedMesh& mesh = m_indexedMeshes[subpart];
+
+ numverts = mesh.m_numVertices;
+ (*vertexbase) = (unsigned char *) mesh.m_vertexBase;
+
+ type = mesh.m_vertexType;
+
+ vertexStride = mesh.m_vertexStride;
+
+ numfaces = mesh.m_numTriangles;
+
+ (*indexbase) = (unsigned char *)mesh.m_triangleIndexBase;
+ indexstride = mesh.m_triangleIndexStride;
+ indicestype = mesh.m_indexType;
+}
+
+void b3TriangleIndexVertexArray::getLockedReadOnlyVertexIndexBase(const unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& vertexStride,const unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart) const
+{
+ const b3IndexedMesh& mesh = m_indexedMeshes[subpart];
+
+ numverts = mesh.m_numVertices;
+ (*vertexbase) = (const unsigned char *)mesh.m_vertexBase;
+
+ type = mesh.m_vertexType;
+
+ vertexStride = mesh.m_vertexStride;
+
+ numfaces = mesh.m_numTriangles;
+ (*indexbase) = (const unsigned char *)mesh.m_triangleIndexBase;
+ indexstride = mesh.m_triangleIndexStride;
+ indicestype = mesh.m_indexType;
+}
+
+bool b3TriangleIndexVertexArray::hasPremadeAabb() const
+{
+ return (m_hasAabb == 1);
+}
+
+
+void b3TriangleIndexVertexArray::setPremadeAabb(const b3Vector3& aabbMin, const b3Vector3& aabbMax ) const
+{
+ m_aabbMin = aabbMin;
+ m_aabbMax = aabbMax;
+ m_hasAabb = 1; // this is intentionally an int see notes in header
+}
+
+void b3TriangleIndexVertexArray::getPremadeAabb(b3Vector3* aabbMin, b3Vector3* aabbMax ) const
+{
+ *aabbMin = m_aabbMin;
+ *aabbMax = m_aabbMax;
+}
+
+
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3TriangleIndexVertexArray.h b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3TriangleIndexVertexArray.h
new file mode 100644
index 0000000000..d26b2893bc
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3TriangleIndexVertexArray.h
@@ -0,0 +1,133 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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 B3_TRIANGLE_INDEX_VERTEX_ARRAY_H
+#define B3_TRIANGLE_INDEX_VERTEX_ARRAY_H
+
+#include "b3StridingMeshInterface.h"
+#include "Bullet3Common/b3AlignedObjectArray.h"
+#include "Bullet3Common/b3Scalar.h"
+
+
+///The b3IndexedMesh indexes a single vertex and index array. Multiple b3IndexedMesh objects can be passed into a b3TriangleIndexVertexArray using addIndexedMesh.
+///Instead of the number of indices, we pass the number of triangles.
+B3_ATTRIBUTE_ALIGNED16( struct) b3IndexedMesh
+{
+ B3_DECLARE_ALIGNED_ALLOCATOR();
+
+ int m_numTriangles;
+ const unsigned char * m_triangleIndexBase;
+ // Size in byte of the indices for one triangle (3*sizeof(index_type) if the indices are tightly packed)
+ int m_triangleIndexStride;
+ int m_numVertices;
+ const unsigned char * m_vertexBase;
+ // Size of a vertex, in bytes
+ int m_vertexStride;
+
+ // The index type is set when adding an indexed mesh to the
+ // b3TriangleIndexVertexArray, do not set it manually
+ PHY_ScalarType m_indexType;
+
+ // The vertex type has a default type similar to Bullet's precision mode (float or double)
+ // but can be set manually if you for example run Bullet with double precision but have
+ // mesh data in single precision..
+ PHY_ScalarType m_vertexType;
+
+
+ b3IndexedMesh()
+ :m_indexType(PHY_INTEGER),
+#ifdef B3_USE_DOUBLE_PRECISION
+ m_vertexType(PHY_DOUBLE)
+#else // B3_USE_DOUBLE_PRECISION
+ m_vertexType(PHY_FLOAT)
+#endif // B3_USE_DOUBLE_PRECISION
+ {
+ }
+}
+;
+
+
+typedef b3AlignedObjectArray<b3IndexedMesh> IndexedMeshArray;
+
+///The b3TriangleIndexVertexArray allows to access multiple triangle meshes, by indexing into existing triangle/index arrays.
+///Additional meshes can be added using addIndexedMesh
+///No duplcate is made of the vertex/index data, it only indexes into external vertex/index arrays.
+///So keep those arrays around during the lifetime of this b3TriangleIndexVertexArray.
+B3_ATTRIBUTE_ALIGNED16( class) b3TriangleIndexVertexArray : public b3StridingMeshInterface
+{
+protected:
+ IndexedMeshArray m_indexedMeshes;
+ int m_pad[2];
+ mutable int m_hasAabb; // using int instead of bool to maintain alignment
+ mutable b3Vector3 m_aabbMin;
+ mutable b3Vector3 m_aabbMax;
+
+public:
+
+ B3_DECLARE_ALIGNED_ALLOCATOR();
+
+ b3TriangleIndexVertexArray() : m_hasAabb(0)
+ {
+ }
+
+ virtual ~b3TriangleIndexVertexArray();
+
+ //just to be backwards compatible
+ b3TriangleIndexVertexArray(int numTriangles,int* triangleIndexBase,int triangleIndexStride,int numVertices,b3Scalar* vertexBase,int vertexStride);
+
+ void addIndexedMesh(const b3IndexedMesh& mesh, PHY_ScalarType indexType = PHY_INTEGER)
+ {
+ m_indexedMeshes.push_back(mesh);
+ m_indexedMeshes[m_indexedMeshes.size()-1].m_indexType = indexType;
+ }
+
+
+ virtual void getLockedVertexIndexBase(unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& vertexStride,unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0);
+
+ virtual void getLockedReadOnlyVertexIndexBase(const unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& vertexStride,const unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0) const;
+
+ /// unLockVertexBase finishes the access to a subpart of the triangle mesh
+ /// make a call to unLockVertexBase when the read and write access (using getLockedVertexIndexBase) is finished
+ virtual void unLockVertexBase(int subpart) {(void)subpart;}
+
+ virtual void unLockReadOnlyVertexBase(int subpart) const {(void)subpart;}
+
+ /// getNumSubParts returns the number of seperate subparts
+ /// each subpart has a continuous array of vertices and indices
+ virtual int getNumSubParts() const {
+ return (int)m_indexedMeshes.size();
+ }
+
+ IndexedMeshArray& getIndexedMeshArray()
+ {
+ return m_indexedMeshes;
+ }
+
+ const IndexedMeshArray& getIndexedMeshArray() const
+ {
+ return m_indexedMeshes;
+ }
+
+ virtual void preallocateVertices(int numverts){(void) numverts;}
+ virtual void preallocateIndices(int numindices){(void) numindices;}
+
+ virtual bool hasPremadeAabb() const;
+ virtual void setPremadeAabb(const b3Vector3& aabbMin, const b3Vector3& aabbMax ) const;
+ virtual void getPremadeAabb(b3Vector3* aabbMin, b3Vector3* aabbMax ) const;
+
+}
+;
+
+#endif //B3_TRIANGLE_INDEX_VERTEX_ARRAY_H
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3VectorFloat4.h b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3VectorFloat4.h
new file mode 100644
index 0000000000..f6f65f7719
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3VectorFloat4.h
@@ -0,0 +1,11 @@
+#ifndef B3_VECTOR_FLOAT4_H
+#define B3_VECTOR_FLOAT4_H
+
+#include "Bullet3Common/b3Transform.h"
+
+//#define cross3(a,b) (a.cross(b))
+#define float4 b3Vector3
+//#define make_float4(x,y,z,w) b3Vector4(x,y,z,w)
+
+
+#endif //B3_VECTOR_FLOAT4_H
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3VoronoiSimplexSolver.cpp b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3VoronoiSimplexSolver.cpp
new file mode 100644
index 0000000000..cf3d5ef49d
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3VoronoiSimplexSolver.cpp
@@ -0,0 +1,609 @@
+
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+
+ Elsevier CDROM license agreements grants nonexclusive license to use the software
+ for any purpose, commercial or non-commercial as long as the following credit is included
+ identifying the original source of the software:
+
+ Parts of the source are "from the book Real-Time Collision Detection by
+ Christer Ericson, published by Morgan Kaufmann Publishers,
+ (c) 2005 Elsevier Inc."
+
+*/
+
+
+#include "b3VoronoiSimplexSolver.h"
+
+#define VERTA 0
+#define VERTB 1
+#define VERTC 2
+#define VERTD 3
+
+#define B3_CATCH_DEGENERATE_TETRAHEDRON 1
+void b3VoronoiSimplexSolver::removeVertex(int index)
+{
+
+ b3Assert(m_numVertices>0);
+ m_numVertices--;
+ m_simplexVectorW[index] = m_simplexVectorW[m_numVertices];
+ m_simplexPointsP[index] = m_simplexPointsP[m_numVertices];
+ m_simplexPointsQ[index] = m_simplexPointsQ[m_numVertices];
+}
+
+void b3VoronoiSimplexSolver::reduceVertices (const b3UsageBitfield& usedVerts)
+{
+ if ((numVertices() >= 4) && (!usedVerts.usedVertexD))
+ removeVertex(3);
+
+ if ((numVertices() >= 3) && (!usedVerts.usedVertexC))
+ removeVertex(2);
+
+ if ((numVertices() >= 2) && (!usedVerts.usedVertexB))
+ removeVertex(1);
+
+ if ((numVertices() >= 1) && (!usedVerts.usedVertexA))
+ removeVertex(0);
+
+}
+
+
+
+
+
+//clear the simplex, remove all the vertices
+void b3VoronoiSimplexSolver::reset()
+{
+ m_cachedValidClosest = false;
+ m_numVertices = 0;
+ m_needsUpdate = true;
+ m_lastW = b3MakeVector3(b3Scalar(B3_LARGE_FLOAT),b3Scalar(B3_LARGE_FLOAT),b3Scalar(B3_LARGE_FLOAT));
+ m_cachedBC.reset();
+}
+
+
+
+ //add a vertex
+void b3VoronoiSimplexSolver::addVertex(const b3Vector3& w, const b3Vector3& p, const b3Vector3& q)
+{
+ m_lastW = w;
+ m_needsUpdate = true;
+
+ m_simplexVectorW[m_numVertices] = w;
+ m_simplexPointsP[m_numVertices] = p;
+ m_simplexPointsQ[m_numVertices] = q;
+
+ m_numVertices++;
+}
+
+bool b3VoronoiSimplexSolver::updateClosestVectorAndPoints()
+{
+
+ if (m_needsUpdate)
+ {
+ m_cachedBC.reset();
+
+ m_needsUpdate = false;
+
+ switch (numVertices())
+ {
+ case 0:
+ m_cachedValidClosest = false;
+ break;
+ case 1:
+ {
+ m_cachedP1 = m_simplexPointsP[0];
+ m_cachedP2 = m_simplexPointsQ[0];
+ m_cachedV = m_cachedP1-m_cachedP2; //== m_simplexVectorW[0]
+ m_cachedBC.reset();
+ m_cachedBC.setBarycentricCoordinates(b3Scalar(1.),b3Scalar(0.),b3Scalar(0.),b3Scalar(0.));
+ m_cachedValidClosest = m_cachedBC.isValid();
+ break;
+ };
+ case 2:
+ {
+ //closest point origin from line segment
+ const b3Vector3& from = m_simplexVectorW[0];
+ const b3Vector3& to = m_simplexVectorW[1];
+ b3Vector3 nearest;
+
+ b3Vector3 p =b3MakeVector3(b3Scalar(0.),b3Scalar(0.),b3Scalar(0.));
+ b3Vector3 diff = p - from;
+ b3Vector3 v = to - from;
+ b3Scalar t = v.dot(diff);
+
+ if (t > 0) {
+ b3Scalar dotVV = v.dot(v);
+ if (t < dotVV) {
+ t /= dotVV;
+ diff -= t*v;
+ m_cachedBC.m_usedVertices.usedVertexA = true;
+ m_cachedBC.m_usedVertices.usedVertexB = true;
+ } else {
+ t = 1;
+ diff -= v;
+ //reduce to 1 point
+ m_cachedBC.m_usedVertices.usedVertexB = true;
+ }
+ } else
+ {
+ t = 0;
+ //reduce to 1 point
+ m_cachedBC.m_usedVertices.usedVertexA = true;
+ }
+ m_cachedBC.setBarycentricCoordinates(1-t,t);
+ nearest = from + t*v;
+
+ m_cachedP1 = m_simplexPointsP[0] + t * (m_simplexPointsP[1] - m_simplexPointsP[0]);
+ m_cachedP2 = m_simplexPointsQ[0] + t * (m_simplexPointsQ[1] - m_simplexPointsQ[0]);
+ m_cachedV = m_cachedP1 - m_cachedP2;
+
+ reduceVertices(m_cachedBC.m_usedVertices);
+
+ m_cachedValidClosest = m_cachedBC.isValid();
+ break;
+ }
+ case 3:
+ {
+ //closest point origin from triangle
+ b3Vector3 p =b3MakeVector3(b3Scalar(0.),b3Scalar(0.),b3Scalar(0.));
+
+ const b3Vector3& a = m_simplexVectorW[0];
+ const b3Vector3& b = m_simplexVectorW[1];
+ const b3Vector3& c = m_simplexVectorW[2];
+
+ closestPtPointTriangle(p,a,b,c,m_cachedBC);
+ m_cachedP1 = m_simplexPointsP[0] * m_cachedBC.m_barycentricCoords[0] +
+ m_simplexPointsP[1] * m_cachedBC.m_barycentricCoords[1] +
+ m_simplexPointsP[2] * m_cachedBC.m_barycentricCoords[2];
+
+ m_cachedP2 = m_simplexPointsQ[0] * m_cachedBC.m_barycentricCoords[0] +
+ m_simplexPointsQ[1] * m_cachedBC.m_barycentricCoords[1] +
+ m_simplexPointsQ[2] * m_cachedBC.m_barycentricCoords[2];
+
+ m_cachedV = m_cachedP1-m_cachedP2;
+
+ reduceVertices (m_cachedBC.m_usedVertices);
+ m_cachedValidClosest = m_cachedBC.isValid();
+
+ break;
+ }
+ case 4:
+ {
+
+
+ b3Vector3 p =b3MakeVector3(b3Scalar(0.),b3Scalar(0.),b3Scalar(0.));
+
+ const b3Vector3& a = m_simplexVectorW[0];
+ const b3Vector3& b = m_simplexVectorW[1];
+ const b3Vector3& c = m_simplexVectorW[2];
+ const b3Vector3& d = m_simplexVectorW[3];
+
+ bool hasSeperation = closestPtPointTetrahedron(p,a,b,c,d,m_cachedBC);
+
+ if (hasSeperation)
+ {
+
+ m_cachedP1 = m_simplexPointsP[0] * m_cachedBC.m_barycentricCoords[0] +
+ m_simplexPointsP[1] * m_cachedBC.m_barycentricCoords[1] +
+ m_simplexPointsP[2] * m_cachedBC.m_barycentricCoords[2] +
+ m_simplexPointsP[3] * m_cachedBC.m_barycentricCoords[3];
+
+ m_cachedP2 = m_simplexPointsQ[0] * m_cachedBC.m_barycentricCoords[0] +
+ m_simplexPointsQ[1] * m_cachedBC.m_barycentricCoords[1] +
+ m_simplexPointsQ[2] * m_cachedBC.m_barycentricCoords[2] +
+ m_simplexPointsQ[3] * m_cachedBC.m_barycentricCoords[3];
+
+ m_cachedV = m_cachedP1-m_cachedP2;
+ reduceVertices (m_cachedBC.m_usedVertices);
+ } else
+ {
+// printf("sub distance got penetration\n");
+
+ if (m_cachedBC.m_degenerate)
+ {
+ m_cachedValidClosest = false;
+ } else
+ {
+ m_cachedValidClosest = true;
+ //degenerate case == false, penetration = true + zero
+ m_cachedV.setValue(b3Scalar(0.),b3Scalar(0.),b3Scalar(0.));
+ }
+ break;
+ }
+
+ m_cachedValidClosest = m_cachedBC.isValid();
+
+ //closest point origin from tetrahedron
+ break;
+ }
+ default:
+ {
+ m_cachedValidClosest = false;
+ }
+ };
+ }
+
+ return m_cachedValidClosest;
+
+}
+
+//return/calculate the closest vertex
+bool b3VoronoiSimplexSolver::closest(b3Vector3& v)
+{
+ bool succes = updateClosestVectorAndPoints();
+ v = m_cachedV;
+ return succes;
+}
+
+
+
+b3Scalar b3VoronoiSimplexSolver::maxVertex()
+{
+ int i, numverts = numVertices();
+ b3Scalar maxV = b3Scalar(0.);
+ for (i=0;i<numverts;i++)
+ {
+ b3Scalar curLen2 = m_simplexVectorW[i].length2();
+ if (maxV < curLen2)
+ maxV = curLen2;
+ }
+ return maxV;
+}
+
+
+
+ //return the current simplex
+int b3VoronoiSimplexSolver::getSimplex(b3Vector3 *pBuf, b3Vector3 *qBuf, b3Vector3 *yBuf) const
+{
+ int i;
+ for (i=0;i<numVertices();i++)
+ {
+ yBuf[i] = m_simplexVectorW[i];
+ pBuf[i] = m_simplexPointsP[i];
+ qBuf[i] = m_simplexPointsQ[i];
+ }
+ return numVertices();
+}
+
+
+
+
+bool b3VoronoiSimplexSolver::inSimplex(const b3Vector3& w)
+{
+ bool found = false;
+ int i, numverts = numVertices();
+ //b3Scalar maxV = b3Scalar(0.);
+
+ //w is in the current (reduced) simplex
+ for (i=0;i<numverts;i++)
+ {
+#ifdef BT_USE_EQUAL_VERTEX_THRESHOLD
+ if ( m_simplexVectorW[i].distance2(w) <= m_equalVertexThreshold)
+#else
+ if (m_simplexVectorW[i] == w)
+#endif
+ found = true;
+ }
+
+ //check in case lastW is already removed
+ if (w == m_lastW)
+ return true;
+
+ return found;
+}
+
+void b3VoronoiSimplexSolver::backup_closest(b3Vector3& v)
+{
+ v = m_cachedV;
+}
+
+
+bool b3VoronoiSimplexSolver::emptySimplex() const
+{
+ return (numVertices() == 0);
+
+}
+
+void b3VoronoiSimplexSolver::compute_points(b3Vector3& p1, b3Vector3& p2)
+{
+ updateClosestVectorAndPoints();
+ p1 = m_cachedP1;
+ p2 = m_cachedP2;
+
+}
+
+
+
+
+bool b3VoronoiSimplexSolver::closestPtPointTriangle(const b3Vector3& p, const b3Vector3& a, const b3Vector3& b, const b3Vector3& c,b3SubSimplexClosestResult& result)
+{
+ result.m_usedVertices.reset();
+
+ // Check if P in vertex region outside A
+ b3Vector3 ab = b - a;
+ b3Vector3 ac = c - a;
+ b3Vector3 ap = p - a;
+ b3Scalar d1 = ab.dot(ap);
+ b3Scalar d2 = ac.dot(ap);
+ if (d1 <= b3Scalar(0.0) && d2 <= b3Scalar(0.0))
+ {
+ result.m_closestPointOnSimplex = a;
+ result.m_usedVertices.usedVertexA = true;
+ result.setBarycentricCoordinates(1,0,0);
+ return true;// a; // barycentric coordinates (1,0,0)
+ }
+
+ // Check if P in vertex region outside B
+ b3Vector3 bp = p - b;
+ b3Scalar d3 = ab.dot(bp);
+ b3Scalar d4 = ac.dot(bp);
+ if (d3 >= b3Scalar(0.0) && d4 <= d3)
+ {
+ result.m_closestPointOnSimplex = b;
+ result.m_usedVertices.usedVertexB = true;
+ result.setBarycentricCoordinates(0,1,0);
+
+ return true; // b; // barycentric coordinates (0,1,0)
+ }
+ // Check if P in edge region of AB, if so return projection of P onto AB
+ b3Scalar vc = d1*d4 - d3*d2;
+ if (vc <= b3Scalar(0.0) && d1 >= b3Scalar(0.0) && d3 <= b3Scalar(0.0)) {
+ b3Scalar v = d1 / (d1 - d3);
+ result.m_closestPointOnSimplex = a + v * ab;
+ result.m_usedVertices.usedVertexA = true;
+ result.m_usedVertices.usedVertexB = true;
+ result.setBarycentricCoordinates(1-v,v,0);
+ return true;
+ //return a + v * ab; // barycentric coordinates (1-v,v,0)
+ }
+
+ // Check if P in vertex region outside C
+ b3Vector3 cp = p - c;
+ b3Scalar d5 = ab.dot(cp);
+ b3Scalar d6 = ac.dot(cp);
+ if (d6 >= b3Scalar(0.0) && d5 <= d6)
+ {
+ result.m_closestPointOnSimplex = c;
+ result.m_usedVertices.usedVertexC = true;
+ result.setBarycentricCoordinates(0,0,1);
+ return true;//c; // barycentric coordinates (0,0,1)
+ }
+
+ // Check if P in edge region of AC, if so return projection of P onto AC
+ b3Scalar vb = d5*d2 - d1*d6;
+ if (vb <= b3Scalar(0.0) && d2 >= b3Scalar(0.0) && d6 <= b3Scalar(0.0)) {
+ b3Scalar w = d2 / (d2 - d6);
+ result.m_closestPointOnSimplex = a + w * ac;
+ result.m_usedVertices.usedVertexA = true;
+ result.m_usedVertices.usedVertexC = true;
+ result.setBarycentricCoordinates(1-w,0,w);
+ return true;
+ //return a + w * ac; // barycentric coordinates (1-w,0,w)
+ }
+
+ // Check if P in edge region of BC, if so return projection of P onto BC
+ b3Scalar va = d3*d6 - d5*d4;
+ if (va <= b3Scalar(0.0) && (d4 - d3) >= b3Scalar(0.0) && (d5 - d6) >= b3Scalar(0.0)) {
+ b3Scalar w = (d4 - d3) / ((d4 - d3) + (d5 - d6));
+
+ result.m_closestPointOnSimplex = b + w * (c - b);
+ result.m_usedVertices.usedVertexB = true;
+ result.m_usedVertices.usedVertexC = true;
+ result.setBarycentricCoordinates(0,1-w,w);
+ return true;
+ // return b + w * (c - b); // barycentric coordinates (0,1-w,w)
+ }
+
+ // P inside face region. Compute Q through its barycentric coordinates (u,v,w)
+ b3Scalar denom = b3Scalar(1.0) / (va + vb + vc);
+ b3Scalar v = vb * denom;
+ b3Scalar w = vc * denom;
+
+ result.m_closestPointOnSimplex = a + ab * v + ac * w;
+ result.m_usedVertices.usedVertexA = true;
+ result.m_usedVertices.usedVertexB = true;
+ result.m_usedVertices.usedVertexC = true;
+ result.setBarycentricCoordinates(1-v-w,v,w);
+
+ return true;
+// return a + ab * v + ac * w; // = u*a + v*b + w*c, u = va * denom = b3Scalar(1.0) - v - w
+
+}
+
+
+
+
+
+/// Test if point p and d lie on opposite sides of plane through abc
+int b3VoronoiSimplexSolver::pointOutsideOfPlane(const b3Vector3& p, const b3Vector3& a, const b3Vector3& b, const b3Vector3& c, const b3Vector3& d)
+{
+ b3Vector3 normal = (b-a).cross(c-a);
+
+ b3Scalar signp = (p - a).dot(normal); // [AP AB AC]
+ b3Scalar signd = (d - a).dot( normal); // [AD AB AC]
+
+#ifdef B3_CATCH_DEGENERATE_TETRAHEDRON
+#ifdef BT_USE_DOUBLE_PRECISION
+if (signd * signd < (b3Scalar(1e-8) * b3Scalar(1e-8)))
+ {
+ return -1;
+ }
+#else
+ if (signd * signd < (b3Scalar(1e-4) * b3Scalar(1e-4)))
+ {
+// printf("affine dependent/degenerate\n");//
+ return -1;
+ }
+#endif
+
+#endif
+ // Points on opposite sides if expression signs are opposite
+ return signp * signd < b3Scalar(0.);
+}
+
+
+bool b3VoronoiSimplexSolver::closestPtPointTetrahedron(const b3Vector3& p, const b3Vector3& a, const b3Vector3& b, const b3Vector3& c, const b3Vector3& d, b3SubSimplexClosestResult& finalResult)
+{
+ b3SubSimplexClosestResult tempResult;
+
+ // Start out assuming point inside all halfspaces, so closest to itself
+ finalResult.m_closestPointOnSimplex = p;
+ finalResult.m_usedVertices.reset();
+ finalResult.m_usedVertices.usedVertexA = true;
+ finalResult.m_usedVertices.usedVertexB = true;
+ finalResult.m_usedVertices.usedVertexC = true;
+ finalResult.m_usedVertices.usedVertexD = true;
+
+ int pointOutsideABC = pointOutsideOfPlane(p, a, b, c, d);
+ int pointOutsideACD = pointOutsideOfPlane(p, a, c, d, b);
+ int pointOutsideADB = pointOutsideOfPlane(p, a, d, b, c);
+ int pointOutsideBDC = pointOutsideOfPlane(p, b, d, c, a);
+
+ if (pointOutsideABC < 0 || pointOutsideACD < 0 || pointOutsideADB < 0 || pointOutsideBDC < 0)
+ {
+ finalResult.m_degenerate = true;
+ return false;
+ }
+
+ if (!pointOutsideABC && !pointOutsideACD && !pointOutsideADB && !pointOutsideBDC)
+ {
+ return false;
+ }
+
+
+ b3Scalar bestSqDist = FLT_MAX;
+ // If point outside face abc then compute closest point on abc
+ if (pointOutsideABC)
+ {
+ closestPtPointTriangle(p, a, b, c,tempResult);
+ b3Vector3 q = tempResult.m_closestPointOnSimplex;
+
+ b3Scalar sqDist = (q - p).dot( q - p);
+ // Update best closest point if (squared) distance is less than current best
+ if (sqDist < bestSqDist) {
+ bestSqDist = sqDist;
+ finalResult.m_closestPointOnSimplex = q;
+ //convert result bitmask!
+ finalResult.m_usedVertices.reset();
+ finalResult.m_usedVertices.usedVertexA = tempResult.m_usedVertices.usedVertexA;
+ finalResult.m_usedVertices.usedVertexB = tempResult.m_usedVertices.usedVertexB;
+ finalResult.m_usedVertices.usedVertexC = tempResult.m_usedVertices.usedVertexC;
+ finalResult.setBarycentricCoordinates(
+ tempResult.m_barycentricCoords[VERTA],
+ tempResult.m_barycentricCoords[VERTB],
+ tempResult.m_barycentricCoords[VERTC],
+ 0
+ );
+
+ }
+ }
+
+
+ // Repeat test for face acd
+ if (pointOutsideACD)
+ {
+ closestPtPointTriangle(p, a, c, d,tempResult);
+ b3Vector3 q = tempResult.m_closestPointOnSimplex;
+ //convert result bitmask!
+
+ b3Scalar sqDist = (q - p).dot( q - p);
+ if (sqDist < bestSqDist)
+ {
+ bestSqDist = sqDist;
+ finalResult.m_closestPointOnSimplex = q;
+ finalResult.m_usedVertices.reset();
+ finalResult.m_usedVertices.usedVertexA = tempResult.m_usedVertices.usedVertexA;
+
+ finalResult.m_usedVertices.usedVertexC = tempResult.m_usedVertices.usedVertexB;
+ finalResult.m_usedVertices.usedVertexD = tempResult.m_usedVertices.usedVertexC;
+ finalResult.setBarycentricCoordinates(
+ tempResult.m_barycentricCoords[VERTA],
+ 0,
+ tempResult.m_barycentricCoords[VERTB],
+ tempResult.m_barycentricCoords[VERTC]
+ );
+
+ }
+ }
+ // Repeat test for face adb
+
+
+ if (pointOutsideADB)
+ {
+ closestPtPointTriangle(p, a, d, b,tempResult);
+ b3Vector3 q = tempResult.m_closestPointOnSimplex;
+ //convert result bitmask!
+
+ b3Scalar sqDist = (q - p).dot( q - p);
+ if (sqDist < bestSqDist)
+ {
+ bestSqDist = sqDist;
+ finalResult.m_closestPointOnSimplex = q;
+ finalResult.m_usedVertices.reset();
+ finalResult.m_usedVertices.usedVertexA = tempResult.m_usedVertices.usedVertexA;
+ finalResult.m_usedVertices.usedVertexB = tempResult.m_usedVertices.usedVertexC;
+
+ finalResult.m_usedVertices.usedVertexD = tempResult.m_usedVertices.usedVertexB;
+ finalResult.setBarycentricCoordinates(
+ tempResult.m_barycentricCoords[VERTA],
+ tempResult.m_barycentricCoords[VERTC],
+ 0,
+ tempResult.m_barycentricCoords[VERTB]
+ );
+
+ }
+ }
+ // Repeat test for face bdc
+
+
+ if (pointOutsideBDC)
+ {
+ closestPtPointTriangle(p, b, d, c,tempResult);
+ b3Vector3 q = tempResult.m_closestPointOnSimplex;
+ //convert result bitmask!
+ b3Scalar sqDist = (q - p).dot( q - p);
+ if (sqDist < bestSqDist)
+ {
+ bestSqDist = sqDist;
+ finalResult.m_closestPointOnSimplex = q;
+ finalResult.m_usedVertices.reset();
+ //
+ finalResult.m_usedVertices.usedVertexB = tempResult.m_usedVertices.usedVertexA;
+ finalResult.m_usedVertices.usedVertexC = tempResult.m_usedVertices.usedVertexC;
+ finalResult.m_usedVertices.usedVertexD = tempResult.m_usedVertices.usedVertexB;
+
+ finalResult.setBarycentricCoordinates(
+ 0,
+ tempResult.m_barycentricCoords[VERTA],
+ tempResult.m_barycentricCoords[VERTC],
+ tempResult.m_barycentricCoords[VERTB]
+ );
+
+ }
+ }
+
+ //help! we ended up full !
+
+ if (finalResult.m_usedVertices.usedVertexA &&
+ finalResult.m_usedVertices.usedVertexB &&
+ finalResult.m_usedVertices.usedVertexC &&
+ finalResult.m_usedVertices.usedVertexD)
+ {
+ return true;
+ }
+
+ return true;
+}
+
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3VoronoiSimplexSolver.h b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3VoronoiSimplexSolver.h
new file mode 100644
index 0000000000..a6e27667d8
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/b3VoronoiSimplexSolver.h
@@ -0,0 +1,177 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+#ifndef B3_VORONOI_SIMPLEX_SOLVER_H
+#define B3_VORONOI_SIMPLEX_SOLVER_H
+
+#include "Bullet3Common/b3Vector3.h"
+
+
+#define VORONOI_SIMPLEX_MAX_VERTS 5
+
+///disable next define, or use defaultCollisionConfiguration->getSimplexSolver()->setEqualVertexThreshold(0.f) to disable/configure
+//#define BT_USE_EQUAL_VERTEX_THRESHOLD
+#define VORONOI_DEFAULT_EQUAL_VERTEX_THRESHOLD 0.0001f
+
+
+struct b3UsageBitfield{
+ b3UsageBitfield()
+ {
+ reset();
+ }
+
+ void reset()
+ {
+ usedVertexA = false;
+ usedVertexB = false;
+ usedVertexC = false;
+ usedVertexD = false;
+ }
+ unsigned short usedVertexA : 1;
+ unsigned short usedVertexB : 1;
+ unsigned short usedVertexC : 1;
+ unsigned short usedVertexD : 1;
+ unsigned short unused1 : 1;
+ unsigned short unused2 : 1;
+ unsigned short unused3 : 1;
+ unsigned short unused4 : 1;
+};
+
+
+struct b3SubSimplexClosestResult
+{
+ b3Vector3 m_closestPointOnSimplex;
+ //MASK for m_usedVertices
+ //stores the simplex vertex-usage, using the MASK,
+ // if m_usedVertices & MASK then the related vertex is used
+ b3UsageBitfield m_usedVertices;
+ b3Scalar m_barycentricCoords[4];
+ bool m_degenerate;
+
+ void reset()
+ {
+ m_degenerate = false;
+ setBarycentricCoordinates();
+ m_usedVertices.reset();
+ }
+ bool isValid()
+ {
+ bool valid = (m_barycentricCoords[0] >= b3Scalar(0.)) &&
+ (m_barycentricCoords[1] >= b3Scalar(0.)) &&
+ (m_barycentricCoords[2] >= b3Scalar(0.)) &&
+ (m_barycentricCoords[3] >= b3Scalar(0.));
+
+
+ return valid;
+ }
+ void setBarycentricCoordinates(b3Scalar a=b3Scalar(0.),b3Scalar b=b3Scalar(0.),b3Scalar c=b3Scalar(0.),b3Scalar d=b3Scalar(0.))
+ {
+ m_barycentricCoords[0] = a;
+ m_barycentricCoords[1] = b;
+ m_barycentricCoords[2] = c;
+ m_barycentricCoords[3] = d;
+ }
+
+};
+
+/// b3VoronoiSimplexSolver is an implementation of the closest point distance algorithm from a 1-4 points simplex to the origin.
+/// Can be used with GJK, as an alternative to Johnson distance algorithm.
+
+B3_ATTRIBUTE_ALIGNED16(class) b3VoronoiSimplexSolver
+{
+public:
+
+ B3_DECLARE_ALIGNED_ALLOCATOR();
+
+ int m_numVertices;
+
+ b3Vector3 m_simplexVectorW[VORONOI_SIMPLEX_MAX_VERTS];
+ b3Vector3 m_simplexPointsP[VORONOI_SIMPLEX_MAX_VERTS];
+ b3Vector3 m_simplexPointsQ[VORONOI_SIMPLEX_MAX_VERTS];
+
+
+
+ b3Vector3 m_cachedP1;
+ b3Vector3 m_cachedP2;
+ b3Vector3 m_cachedV;
+ b3Vector3 m_lastW;
+
+ b3Scalar m_equalVertexThreshold;
+ bool m_cachedValidClosest;
+
+
+ b3SubSimplexClosestResult m_cachedBC;
+
+ bool m_needsUpdate;
+
+ void removeVertex(int index);
+ void reduceVertices (const b3UsageBitfield& usedVerts);
+ bool updateClosestVectorAndPoints();
+
+ bool closestPtPointTetrahedron(const b3Vector3& p, const b3Vector3& a, const b3Vector3& b, const b3Vector3& c, const b3Vector3& d, b3SubSimplexClosestResult& finalResult);
+ int pointOutsideOfPlane(const b3Vector3& p, const b3Vector3& a, const b3Vector3& b, const b3Vector3& c, const b3Vector3& d);
+ bool closestPtPointTriangle(const b3Vector3& p, const b3Vector3& a, const b3Vector3& b, const b3Vector3& c,b3SubSimplexClosestResult& result);
+
+public:
+
+ b3VoronoiSimplexSolver()
+ : m_equalVertexThreshold(VORONOI_DEFAULT_EQUAL_VERTEX_THRESHOLD)
+ {
+ }
+ void reset();
+
+ void addVertex(const b3Vector3& w, const b3Vector3& p, const b3Vector3& q);
+
+ void setEqualVertexThreshold(b3Scalar threshold)
+ {
+ m_equalVertexThreshold = threshold;
+ }
+
+ b3Scalar getEqualVertexThreshold() const
+ {
+ return m_equalVertexThreshold;
+ }
+
+ bool closest(b3Vector3& v);
+
+ b3Scalar maxVertex();
+
+ bool fullSimplex() const
+ {
+ return (m_numVertices == 4);
+ }
+
+ int getSimplex(b3Vector3 *pBuf, b3Vector3 *qBuf, b3Vector3 *yBuf) const;
+
+ bool inSimplex(const b3Vector3& w);
+
+ void backup_closest(b3Vector3& v) ;
+
+ bool emptySimplex() const ;
+
+ void compute_points(b3Vector3& p1, b3Vector3& p2) ;
+
+ int numVertices() const
+ {
+ return m_numVertices;
+ }
+
+
+};
+
+#endif //B3_VORONOI_SIMPLEX_SOLVER_H
+
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/kernels/bvhTraversal.cl b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/kernels/bvhTraversal.cl
new file mode 100644
index 0000000000..faa413441c
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/kernels/bvhTraversal.cl
@@ -0,0 +1,283 @@
+//keep this enum in sync with the CPU version (in btCollidable.h)
+//written by Erwin Coumans
+
+#define SHAPE_CONVEX_HULL 3
+#define SHAPE_CONCAVE_TRIMESH 5
+#define TRIANGLE_NUM_CONVEX_FACES 5
+#define SHAPE_COMPOUND_OF_CONVEX_HULLS 6
+#define SHAPE_SPHERE 7
+
+typedef unsigned int u32;
+
+#define MAX_NUM_PARTS_IN_BITS 10
+
+///btQuantizedBvhNode is a compressed aabb node, 16 bytes.
+///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range).
+typedef struct
+{
+ //12 bytes
+ unsigned short int m_quantizedAabbMin[3];
+ unsigned short int m_quantizedAabbMax[3];
+ //4 bytes
+ int m_escapeIndexOrTriangleIndex;
+} btQuantizedBvhNode;
+
+typedef struct
+{
+ float4 m_aabbMin;
+ float4 m_aabbMax;
+ float4 m_quantization;
+ int m_numNodes;
+ int m_numSubTrees;
+ int m_nodeOffset;
+ int m_subTreeOffset;
+
+} b3BvhInfo;
+
+int getTriangleIndex(const btQuantizedBvhNode* rootNode)
+{
+ unsigned int x=0;
+ unsigned int y = (~(x&0))<<(31-MAX_NUM_PARTS_IN_BITS);
+ // Get only the lower bits where the triangle index is stored
+ return (rootNode->m_escapeIndexOrTriangleIndex&~(y));
+}
+
+int isLeaf(const btQuantizedBvhNode* rootNode)
+{
+ //skipindex is negative (internal node), triangleindex >=0 (leafnode)
+ return (rootNode->m_escapeIndexOrTriangleIndex >= 0)? 1 : 0;
+}
+
+int getEscapeIndex(const btQuantizedBvhNode* rootNode)
+{
+ return -rootNode->m_escapeIndexOrTriangleIndex;
+}
+
+typedef struct
+{
+ //12 bytes
+ unsigned short int m_quantizedAabbMin[3];
+ unsigned short int m_quantizedAabbMax[3];
+ //4 bytes, points to the root of the subtree
+ int m_rootNodeIndex;
+ //4 bytes
+ int m_subtreeSize;
+ int m_padding[3];
+} btBvhSubtreeInfo;
+
+///keep this in sync with btCollidable.h
+typedef struct
+{
+ int m_numChildShapes;
+ int blaat2;
+ int m_shapeType;
+ int m_shapeIndex;
+
+} btCollidableGpu;
+
+typedef struct
+{
+ float4 m_childPosition;
+ float4 m_childOrientation;
+ int m_shapeIndex;
+ int m_unused0;
+ int m_unused1;
+ int m_unused2;
+} btGpuChildShape;
+
+
+typedef struct
+{
+ float4 m_pos;
+ float4 m_quat;
+ float4 m_linVel;
+ float4 m_angVel;
+
+ u32 m_collidableIdx;
+ float m_invMass;
+ float m_restituitionCoeff;
+ float m_frictionCoeff;
+} BodyData;
+
+typedef struct
+{
+ union
+ {
+ float4 m_min;
+ float m_minElems[4];
+ int m_minIndices[4];
+ };
+ union
+ {
+ float4 m_max;
+ float m_maxElems[4];
+ int m_maxIndices[4];
+ };
+} btAabbCL;
+
+
+int testQuantizedAabbAgainstQuantizedAabb(
+ const unsigned short int* aabbMin1,
+ const unsigned short int* aabbMax1,
+ const unsigned short int* aabbMin2,
+ const unsigned short int* aabbMax2)
+{
+ //int overlap = 1;
+ if (aabbMin1[0] > aabbMax2[0])
+ return 0;
+ if (aabbMax1[0] < aabbMin2[0])
+ return 0;
+ if (aabbMin1[1] > aabbMax2[1])
+ return 0;
+ if (aabbMax1[1] < aabbMin2[1])
+ return 0;
+ if (aabbMin1[2] > aabbMax2[2])
+ return 0;
+ if (aabbMax1[2] < aabbMin2[2])
+ return 0;
+ return 1;
+ //overlap = ((aabbMin1[0] > aabbMax2[0]) || (aabbMax1[0] < aabbMin2[0])) ? 0 : overlap;
+ //overlap = ((aabbMin1[2] > aabbMax2[2]) || (aabbMax1[2] < aabbMin2[2])) ? 0 : overlap;
+ //overlap = ((aabbMin1[1] > aabbMax2[1]) || (aabbMax1[1] < aabbMin2[1])) ? 0 : overlap;
+ //return overlap;
+}
+
+
+void quantizeWithClamp(unsigned short* out, float4 point2,int isMax, float4 bvhAabbMin, float4 bvhAabbMax, float4 bvhQuantization)
+{
+ float4 clampedPoint = max(point2,bvhAabbMin);
+ clampedPoint = min (clampedPoint, bvhAabbMax);
+
+ float4 v = (clampedPoint - bvhAabbMin) * bvhQuantization;
+ if (isMax)
+ {
+ out[0] = (unsigned short) (((unsigned short)(v.x+1.f) | 1));
+ out[1] = (unsigned short) (((unsigned short)(v.y+1.f) | 1));
+ out[2] = (unsigned short) (((unsigned short)(v.z+1.f) | 1));
+ } else
+ {
+ out[0] = (unsigned short) (((unsigned short)(v.x) & 0xfffe));
+ out[1] = (unsigned short) (((unsigned short)(v.y) & 0xfffe));
+ out[2] = (unsigned short) (((unsigned short)(v.z) & 0xfffe));
+ }
+
+}
+
+
+// work-in-progress
+__kernel void bvhTraversalKernel( __global const int4* pairs,
+ __global const BodyData* rigidBodies,
+ __global const btCollidableGpu* collidables,
+ __global btAabbCL* aabbs,
+ __global int4* concavePairsOut,
+ __global volatile int* numConcavePairsOut,
+ __global const btBvhSubtreeInfo* subtreeHeadersRoot,
+ __global const btQuantizedBvhNode* quantizedNodesRoot,
+ __global const b3BvhInfo* bvhInfos,
+ int numPairs,
+ int maxNumConcavePairsCapacity)
+{
+ int id = get_global_id(0);
+ if (id>=numPairs)
+ return;
+
+ int bodyIndexA = pairs[id].x;
+ int bodyIndexB = pairs[id].y;
+ int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
+ int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
+
+ //once the broadphase avoids static-static pairs, we can remove this test
+ if ((rigidBodies[bodyIndexA].m_invMass==0) &&(rigidBodies[bodyIndexB].m_invMass==0))
+ {
+ return;
+ }
+
+ if (collidables[collidableIndexA].m_shapeType!=SHAPE_CONCAVE_TRIMESH)
+ return;
+
+ int shapeTypeB = collidables[collidableIndexB].m_shapeType;
+
+ if (shapeTypeB!=SHAPE_CONVEX_HULL &&
+ shapeTypeB!=SHAPE_SPHERE &&
+ shapeTypeB!=SHAPE_COMPOUND_OF_CONVEX_HULLS
+ )
+ return;
+
+ b3BvhInfo bvhInfo = bvhInfos[collidables[collidableIndexA].m_numChildShapes];
+
+ float4 bvhAabbMin = bvhInfo.m_aabbMin;
+ float4 bvhAabbMax = bvhInfo.m_aabbMax;
+ float4 bvhQuantization = bvhInfo.m_quantization;
+ int numSubtreeHeaders = bvhInfo.m_numSubTrees;
+ __global const btBvhSubtreeInfo* subtreeHeaders = &subtreeHeadersRoot[bvhInfo.m_subTreeOffset];
+ __global const btQuantizedBvhNode* quantizedNodes = &quantizedNodesRoot[bvhInfo.m_nodeOffset];
+
+
+ unsigned short int quantizedQueryAabbMin[3];
+ unsigned short int quantizedQueryAabbMax[3];
+ quantizeWithClamp(quantizedQueryAabbMin,aabbs[bodyIndexB].m_min,false,bvhAabbMin, bvhAabbMax,bvhQuantization);
+ quantizeWithClamp(quantizedQueryAabbMax,aabbs[bodyIndexB].m_max,true ,bvhAabbMin, bvhAabbMax,bvhQuantization);
+
+ for (int i=0;i<numSubtreeHeaders;i++)
+ {
+ btBvhSubtreeInfo subtree = subtreeHeaders[i];
+
+ int overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax);
+ if (overlap != 0)
+ {
+ int startNodeIndex = subtree.m_rootNodeIndex;
+ int endNodeIndex = subtree.m_rootNodeIndex+subtree.m_subtreeSize;
+ int curIndex = startNodeIndex;
+ int escapeIndex;
+ int isLeafNode;
+ int aabbOverlap;
+ while (curIndex < endNodeIndex)
+ {
+ btQuantizedBvhNode rootNode = quantizedNodes[curIndex];
+ aabbOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,rootNode.m_quantizedAabbMin,rootNode.m_quantizedAabbMax);
+ isLeafNode = isLeaf(&rootNode);
+ if (aabbOverlap)
+ {
+ if (isLeafNode)
+ {
+ int triangleIndex = getTriangleIndex(&rootNode);
+ if (shapeTypeB==SHAPE_COMPOUND_OF_CONVEX_HULLS)
+ {
+ int numChildrenB = collidables[collidableIndexB].m_numChildShapes;
+ int pairIdx = atomic_add(numConcavePairsOut,numChildrenB);
+ for (int b=0;b<numChildrenB;b++)
+ {
+ if ((pairIdx+b)<maxNumConcavePairsCapacity)
+ {
+ int childShapeIndexB = collidables[collidableIndexB].m_shapeIndex+b;
+ int4 newPair = (int4)(bodyIndexA,bodyIndexB,triangleIndex,childShapeIndexB);
+ concavePairsOut[pairIdx+b] = newPair;
+ }
+ }
+ } else
+ {
+ int pairIdx = atomic_inc(numConcavePairsOut);
+ if (pairIdx<maxNumConcavePairsCapacity)
+ {
+ int4 newPair = (int4)(bodyIndexA,bodyIndexB,triangleIndex,0);
+ concavePairsOut[pairIdx] = newPair;
+ }
+ }
+ }
+ curIndex++;
+ } else
+ {
+ if (isLeafNode)
+ {
+ curIndex++;
+ } else
+ {
+ escapeIndex = getEscapeIndex(&rootNode);
+ curIndex += escapeIndex;
+ }
+ }
+ }
+ }
+ }
+
+} \ No newline at end of file
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/kernels/bvhTraversal.h b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/kernels/bvhTraversal.h
new file mode 100644
index 0000000000..4b3b49eae8
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/kernels/bvhTraversal.h
@@ -0,0 +1,258 @@
+//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
+static const char* bvhTraversalKernelCL= \
+"//keep this enum in sync with the CPU version (in btCollidable.h)\n"
+"//written by Erwin Coumans\n"
+"#define SHAPE_CONVEX_HULL 3\n"
+"#define SHAPE_CONCAVE_TRIMESH 5\n"
+"#define TRIANGLE_NUM_CONVEX_FACES 5\n"
+"#define SHAPE_COMPOUND_OF_CONVEX_HULLS 6\n"
+"#define SHAPE_SPHERE 7\n"
+"typedef unsigned int u32;\n"
+"#define MAX_NUM_PARTS_IN_BITS 10\n"
+"///btQuantizedBvhNode is a compressed aabb node, 16 bytes.\n"
+"///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range).\n"
+"typedef struct\n"
+"{\n"
+" //12 bytes\n"
+" unsigned short int m_quantizedAabbMin[3];\n"
+" unsigned short int m_quantizedAabbMax[3];\n"
+" //4 bytes\n"
+" int m_escapeIndexOrTriangleIndex;\n"
+"} btQuantizedBvhNode;\n"
+"typedef struct\n"
+"{\n"
+" float4 m_aabbMin;\n"
+" float4 m_aabbMax;\n"
+" float4 m_quantization;\n"
+" int m_numNodes;\n"
+" int m_numSubTrees;\n"
+" int m_nodeOffset;\n"
+" int m_subTreeOffset;\n"
+"} b3BvhInfo;\n"
+"int getTriangleIndex(const btQuantizedBvhNode* rootNode)\n"
+"{\n"
+" unsigned int x=0;\n"
+" unsigned int y = (~(x&0))<<(31-MAX_NUM_PARTS_IN_BITS);\n"
+" // Get only the lower bits where the triangle index is stored\n"
+" return (rootNode->m_escapeIndexOrTriangleIndex&~(y));\n"
+"}\n"
+"int isLeaf(const btQuantizedBvhNode* rootNode)\n"
+"{\n"
+" //skipindex is negative (internal node), triangleindex >=0 (leafnode)\n"
+" return (rootNode->m_escapeIndexOrTriangleIndex >= 0)? 1 : 0;\n"
+"}\n"
+" \n"
+"int getEscapeIndex(const btQuantizedBvhNode* rootNode)\n"
+"{\n"
+" return -rootNode->m_escapeIndexOrTriangleIndex;\n"
+"}\n"
+"typedef struct\n"
+"{\n"
+" //12 bytes\n"
+" unsigned short int m_quantizedAabbMin[3];\n"
+" unsigned short int m_quantizedAabbMax[3];\n"
+" //4 bytes, points to the root of the subtree\n"
+" int m_rootNodeIndex;\n"
+" //4 bytes\n"
+" int m_subtreeSize;\n"
+" int m_padding[3];\n"
+"} btBvhSubtreeInfo;\n"
+"///keep this in sync with btCollidable.h\n"
+"typedef struct\n"
+"{\n"
+" int m_numChildShapes;\n"
+" int blaat2;\n"
+" int m_shapeType;\n"
+" int m_shapeIndex;\n"
+" \n"
+"} btCollidableGpu;\n"
+"typedef struct\n"
+"{\n"
+" float4 m_childPosition;\n"
+" float4 m_childOrientation;\n"
+" int m_shapeIndex;\n"
+" int m_unused0;\n"
+" int m_unused1;\n"
+" int m_unused2;\n"
+"} btGpuChildShape;\n"
+"typedef struct\n"
+"{\n"
+" float4 m_pos;\n"
+" float4 m_quat;\n"
+" float4 m_linVel;\n"
+" float4 m_angVel;\n"
+" u32 m_collidableIdx;\n"
+" float m_invMass;\n"
+" float m_restituitionCoeff;\n"
+" float m_frictionCoeff;\n"
+"} BodyData;\n"
+"typedef struct \n"
+"{\n"
+" union\n"
+" {\n"
+" float4 m_min;\n"
+" float m_minElems[4];\n"
+" int m_minIndices[4];\n"
+" };\n"
+" union\n"
+" {\n"
+" float4 m_max;\n"
+" float m_maxElems[4];\n"
+" int m_maxIndices[4];\n"
+" };\n"
+"} btAabbCL;\n"
+"int testQuantizedAabbAgainstQuantizedAabb(\n"
+" const unsigned short int* aabbMin1,\n"
+" const unsigned short int* aabbMax1,\n"
+" const unsigned short int* aabbMin2,\n"
+" const unsigned short int* aabbMax2)\n"
+"{\n"
+" //int overlap = 1;\n"
+" if (aabbMin1[0] > aabbMax2[0])\n"
+" return 0;\n"
+" if (aabbMax1[0] < aabbMin2[0])\n"
+" return 0;\n"
+" if (aabbMin1[1] > aabbMax2[1])\n"
+" return 0;\n"
+" if (aabbMax1[1] < aabbMin2[1])\n"
+" return 0;\n"
+" if (aabbMin1[2] > aabbMax2[2])\n"
+" return 0;\n"
+" if (aabbMax1[2] < aabbMin2[2])\n"
+" return 0;\n"
+" return 1;\n"
+" //overlap = ((aabbMin1[0] > aabbMax2[0]) || (aabbMax1[0] < aabbMin2[0])) ? 0 : overlap;\n"
+" //overlap = ((aabbMin1[2] > aabbMax2[2]) || (aabbMax1[2] < aabbMin2[2])) ? 0 : overlap;\n"
+" //overlap = ((aabbMin1[1] > aabbMax2[1]) || (aabbMax1[1] < aabbMin2[1])) ? 0 : overlap;\n"
+" //return overlap;\n"
+"}\n"
+"void quantizeWithClamp(unsigned short* out, float4 point2,int isMax, float4 bvhAabbMin, float4 bvhAabbMax, float4 bvhQuantization)\n"
+"{\n"
+" float4 clampedPoint = max(point2,bvhAabbMin);\n"
+" clampedPoint = min (clampedPoint, bvhAabbMax);\n"
+" float4 v = (clampedPoint - bvhAabbMin) * bvhQuantization;\n"
+" if (isMax)\n"
+" {\n"
+" out[0] = (unsigned short) (((unsigned short)(v.x+1.f) | 1));\n"
+" out[1] = (unsigned short) (((unsigned short)(v.y+1.f) | 1));\n"
+" out[2] = (unsigned short) (((unsigned short)(v.z+1.f) | 1));\n"
+" } else\n"
+" {\n"
+" out[0] = (unsigned short) (((unsigned short)(v.x) & 0xfffe));\n"
+" out[1] = (unsigned short) (((unsigned short)(v.y) & 0xfffe));\n"
+" out[2] = (unsigned short) (((unsigned short)(v.z) & 0xfffe));\n"
+" }\n"
+"}\n"
+"// work-in-progress\n"
+"__kernel void bvhTraversalKernel( __global const int4* pairs, \n"
+" __global const BodyData* rigidBodies, \n"
+" __global const btCollidableGpu* collidables,\n"
+" __global btAabbCL* aabbs,\n"
+" __global int4* concavePairsOut,\n"
+" __global volatile int* numConcavePairsOut,\n"
+" __global const btBvhSubtreeInfo* subtreeHeadersRoot,\n"
+" __global const btQuantizedBvhNode* quantizedNodesRoot,\n"
+" __global const b3BvhInfo* bvhInfos,\n"
+" int numPairs,\n"
+" int maxNumConcavePairsCapacity)\n"
+"{\n"
+" int id = get_global_id(0);\n"
+" if (id>=numPairs)\n"
+" return;\n"
+" \n"
+" int bodyIndexA = pairs[id].x;\n"
+" int bodyIndexB = pairs[id].y;\n"
+" int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
+" int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
+" \n"
+" //once the broadphase avoids static-static pairs, we can remove this test\n"
+" if ((rigidBodies[bodyIndexA].m_invMass==0) &&(rigidBodies[bodyIndexB].m_invMass==0))\n"
+" {\n"
+" return;\n"
+" }\n"
+" \n"
+" if (collidables[collidableIndexA].m_shapeType!=SHAPE_CONCAVE_TRIMESH)\n"
+" return;\n"
+" int shapeTypeB = collidables[collidableIndexB].m_shapeType;\n"
+" \n"
+" if (shapeTypeB!=SHAPE_CONVEX_HULL &&\n"
+" shapeTypeB!=SHAPE_SPHERE &&\n"
+" shapeTypeB!=SHAPE_COMPOUND_OF_CONVEX_HULLS\n"
+" )\n"
+" return;\n"
+" b3BvhInfo bvhInfo = bvhInfos[collidables[collidableIndexA].m_numChildShapes];\n"
+" float4 bvhAabbMin = bvhInfo.m_aabbMin;\n"
+" float4 bvhAabbMax = bvhInfo.m_aabbMax;\n"
+" float4 bvhQuantization = bvhInfo.m_quantization;\n"
+" int numSubtreeHeaders = bvhInfo.m_numSubTrees;\n"
+" __global const btBvhSubtreeInfo* subtreeHeaders = &subtreeHeadersRoot[bvhInfo.m_subTreeOffset];\n"
+" __global const btQuantizedBvhNode* quantizedNodes = &quantizedNodesRoot[bvhInfo.m_nodeOffset];\n"
+" \n"
+" unsigned short int quantizedQueryAabbMin[3];\n"
+" unsigned short int quantizedQueryAabbMax[3];\n"
+" quantizeWithClamp(quantizedQueryAabbMin,aabbs[bodyIndexB].m_min,false,bvhAabbMin, bvhAabbMax,bvhQuantization);\n"
+" quantizeWithClamp(quantizedQueryAabbMax,aabbs[bodyIndexB].m_max,true ,bvhAabbMin, bvhAabbMax,bvhQuantization);\n"
+" \n"
+" for (int i=0;i<numSubtreeHeaders;i++)\n"
+" {\n"
+" btBvhSubtreeInfo subtree = subtreeHeaders[i];\n"
+" \n"
+" int overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax);\n"
+" if (overlap != 0)\n"
+" {\n"
+" int startNodeIndex = subtree.m_rootNodeIndex;\n"
+" int endNodeIndex = subtree.m_rootNodeIndex+subtree.m_subtreeSize;\n"
+" int curIndex = startNodeIndex;\n"
+" int escapeIndex;\n"
+" int isLeafNode;\n"
+" int aabbOverlap;\n"
+" while (curIndex < endNodeIndex)\n"
+" {\n"
+" btQuantizedBvhNode rootNode = quantizedNodes[curIndex];\n"
+" aabbOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,rootNode.m_quantizedAabbMin,rootNode.m_quantizedAabbMax);\n"
+" isLeafNode = isLeaf(&rootNode);\n"
+" if (aabbOverlap)\n"
+" {\n"
+" if (isLeafNode)\n"
+" {\n"
+" int triangleIndex = getTriangleIndex(&rootNode);\n"
+" if (shapeTypeB==SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
+" {\n"
+" int numChildrenB = collidables[collidableIndexB].m_numChildShapes;\n"
+" int pairIdx = atomic_add(numConcavePairsOut,numChildrenB);\n"
+" for (int b=0;b<numChildrenB;b++)\n"
+" {\n"
+" if ((pairIdx+b)<maxNumConcavePairsCapacity)\n"
+" {\n"
+" int childShapeIndexB = collidables[collidableIndexB].m_shapeIndex+b;\n"
+" int4 newPair = (int4)(bodyIndexA,bodyIndexB,triangleIndex,childShapeIndexB);\n"
+" concavePairsOut[pairIdx+b] = newPair;\n"
+" }\n"
+" }\n"
+" } else\n"
+" {\n"
+" int pairIdx = atomic_inc(numConcavePairsOut);\n"
+" if (pairIdx<maxNumConcavePairsCapacity)\n"
+" {\n"
+" int4 newPair = (int4)(bodyIndexA,bodyIndexB,triangleIndex,0);\n"
+" concavePairsOut[pairIdx] = newPair;\n"
+" }\n"
+" }\n"
+" } \n"
+" curIndex++;\n"
+" } else\n"
+" {\n"
+" if (isLeafNode)\n"
+" {\n"
+" curIndex++;\n"
+" } else\n"
+" {\n"
+" escapeIndex = getEscapeIndex(&rootNode);\n"
+" curIndex += escapeIndex;\n"
+" }\n"
+" }\n"
+" }\n"
+" }\n"
+" }\n"
+"}\n"
+;
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/kernels/mpr.cl b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/kernels/mpr.cl
new file mode 100644
index 0000000000..e754f4e1da
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/kernels/mpr.cl
@@ -0,0 +1,311 @@
+
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3MprPenetration.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h"
+
+#define AppendInc(x, out) out = atomic_inc(x)
+#define GET_NPOINTS(x) (x).m_worldNormalOnB.w
+#ifdef cl_ext_atomic_counters_32
+ #pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable
+#else
+ #define counter32_t volatile __global int*
+#endif
+
+
+__kernel void mprPenetrationKernel( __global int4* pairs,
+ __global const b3RigidBodyData_t* rigidBodies,
+ __global const b3Collidable_t* collidables,
+ __global const b3ConvexPolyhedronData_t* convexShapes,
+ __global const float4* vertices,
+ __global float4* separatingNormals,
+ __global int* hasSeparatingAxis,
+ __global struct b3Contact4Data* restrict globalContactsOut,
+ counter32_t nGlobalContactsOut,
+ int contactCapacity,
+ int numPairs)
+{
+ int i = get_global_id(0);
+ int pairIndex = i;
+ if (i<numPairs)
+ {
+ int bodyIndexA = pairs[i].x;
+ int bodyIndexB = pairs[i].y;
+
+ int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
+ int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
+
+ int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
+ int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
+
+
+ //once the broadphase avoids static-static pairs, we can remove this test
+ if ((rigidBodies[bodyIndexA].m_invMass==0) &&(rigidBodies[bodyIndexB].m_invMass==0))
+ {
+ return;
+ }
+
+
+ if ((collidables[collidableIndexA].m_shapeType!=SHAPE_CONVEX_HULL) ||(collidables[collidableIndexB].m_shapeType!=SHAPE_CONVEX_HULL))
+ {
+ return;
+ }
+
+ float depthOut;
+ b3Float4 dirOut;
+ b3Float4 posOut;
+
+
+ int res = b3MprPenetration(pairIndex, bodyIndexA, bodyIndexB,rigidBodies,convexShapes,collidables,vertices,separatingNormals,hasSeparatingAxis,&depthOut, &dirOut, &posOut);
+
+
+
+
+
+ if (res==0)
+ {
+ //add a contact
+
+ int dstIdx;
+ AppendInc( nGlobalContactsOut, dstIdx );
+ if (dstIdx<contactCapacity)
+ {
+ pairs[pairIndex].z = dstIdx;
+ __global struct b3Contact4Data* c = globalContactsOut + dstIdx;
+ c->m_worldNormalOnB = -dirOut;//normal;
+ c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);
+ c->m_batchIdx = pairIndex;
+ int bodyA = pairs[pairIndex].x;
+ int bodyB = pairs[pairIndex].y;
+ c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0 ? -bodyA:bodyA;
+ c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0 ? -bodyB:bodyB;
+ c->m_childIndexA = -1;
+ c->m_childIndexB = -1;
+ //for (int i=0;i<nContacts;i++)
+ posOut.w = -depthOut;
+ c->m_worldPosB[0] = posOut;//localPoints[contactIdx[i]];
+ GET_NPOINTS(*c) = 1;//nContacts;
+ }
+ }
+
+ }
+}
+
+typedef float4 Quaternion;
+#define make_float4 (float4)
+
+__inline
+float dot3F4(float4 a, float4 b)
+{
+ float4 a1 = make_float4(a.xyz,0.f);
+ float4 b1 = make_float4(b.xyz,0.f);
+ return dot(a1, b1);
+}
+
+
+
+
+__inline
+float4 cross3(float4 a, float4 b)
+{
+ return cross(a,b);
+}
+__inline
+Quaternion qtMul(Quaternion a, Quaternion b)
+{
+ Quaternion ans;
+ ans = cross3( a, b );
+ ans += a.w*b+b.w*a;
+// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);
+ ans.w = a.w*b.w - dot3F4(a, b);
+ return ans;
+}
+
+__inline
+Quaternion qtInvert(Quaternion q)
+{
+ return (Quaternion)(-q.xyz, q.w);
+}
+
+__inline
+float4 qtRotate(Quaternion q, float4 vec)
+{
+ Quaternion qInv = qtInvert( q );
+ float4 vcpy = vec;
+ vcpy.w = 0.f;
+ float4 out = qtMul(qtMul(q,vcpy),qInv);
+ return out;
+}
+
+__inline
+float4 transform(const float4* p, const float4* translation, const Quaternion* orientation)
+{
+ return qtRotate( *orientation, *p ) + (*translation);
+}
+
+
+__inline
+float4 qtInvRotate(const Quaternion q, float4 vec)
+{
+ return qtRotate( qtInvert( q ), vec );
+}
+
+
+inline void project(__global const b3ConvexPolyhedronData_t* hull, const float4 pos, const float4 orn,
+const float4* dir, __global const float4* vertices, float* min, float* max)
+{
+ min[0] = FLT_MAX;
+ max[0] = -FLT_MAX;
+ int numVerts = hull->m_numVertices;
+
+ const float4 localDir = qtInvRotate(orn,*dir);
+ float offset = dot(pos,*dir);
+ for(int i=0;i<numVerts;i++)
+ {
+ float dp = dot(vertices[hull->m_vertexOffset+i],localDir);
+ if(dp < min[0])
+ min[0] = dp;
+ if(dp > max[0])
+ max[0] = dp;
+ }
+ if(min[0]>max[0])
+ {
+ float tmp = min[0];
+ min[0] = max[0];
+ max[0] = tmp;
+ }
+ min[0] += offset;
+ max[0] += offset;
+}
+
+
+bool findSeparatingAxisUnitSphere( __global const b3ConvexPolyhedronData_t* hullA, __global const b3ConvexPolyhedronData_t* hullB,
+ const float4 posA1,
+ const float4 ornA,
+ const float4 posB1,
+ const float4 ornB,
+ const float4 DeltaC2,
+ __global const float4* vertices,
+ __global const float4* unitSphereDirections,
+ int numUnitSphereDirections,
+ float4* sep,
+ float* dmin)
+{
+
+ float4 posA = posA1;
+ posA.w = 0.f;
+ float4 posB = posB1;
+ posB.w = 0.f;
+
+ int curPlaneTests=0;
+
+ int curEdgeEdge = 0;
+ // Test unit sphere directions
+ for (int i=0;i<numUnitSphereDirections;i++)
+ {
+
+ float4 crossje;
+ crossje = unitSphereDirections[i];
+
+ if (dot3F4(DeltaC2,crossje)>0)
+ crossje *= -1.f;
+ {
+ float dist;
+ bool result = true;
+ float Min0,Max0;
+ float Min1,Max1;
+ project(hullA,posA,ornA,&crossje,vertices, &Min0, &Max0);
+ project(hullB,posB,ornB,&crossje,vertices, &Min1, &Max1);
+
+ if(Max0<Min1 || Max1<Min0)
+ return false;
+
+ float d0 = Max0 - Min1;
+ float d1 = Max1 - Min0;
+ dist = d0<d1 ? d0:d1;
+ result = true;
+
+ if(dist<*dmin)
+ {
+ *dmin = dist;
+ *sep = crossje;
+ }
+ }
+ }
+
+
+ if((dot3F4(-DeltaC2,*sep))>0.0f)
+ {
+ *sep = -(*sep);
+ }
+ return true;
+}
+
+
+
+__kernel void findSeparatingAxisUnitSphereKernel( __global const int4* pairs,
+ __global const b3RigidBodyData_t* rigidBodies,
+ __global const b3Collidable_t* collidables,
+ __global const b3ConvexPolyhedronData_t* convexShapes,
+ __global const float4* vertices,
+ __global const float4* unitSphereDirections,
+ __global float4* separatingNormals,
+ __global int* hasSeparatingAxis,
+ __global float* dmins,
+ int numUnitSphereDirections,
+ int numPairs
+ )
+{
+
+ int i = get_global_id(0);
+
+ if (i<numPairs)
+ {
+
+ if (hasSeparatingAxis[i])
+ {
+
+ int bodyIndexA = pairs[i].x;
+ int bodyIndexB = pairs[i].y;
+
+ int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
+ int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
+
+ int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
+ int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
+
+
+ int numFacesA = convexShapes[shapeIndexA].m_numFaces;
+
+ float dmin = dmins[i];
+
+ float4 posA = rigidBodies[bodyIndexA].m_pos;
+ posA.w = 0.f;
+ float4 posB = rigidBodies[bodyIndexB].m_pos;
+ posB.w = 0.f;
+ float4 c0local = convexShapes[shapeIndexA].m_localCenter;
+ float4 ornA = rigidBodies[bodyIndexA].m_quat;
+ float4 c0 = transform(&c0local, &posA, &ornA);
+ float4 c1local = convexShapes[shapeIndexB].m_localCenter;
+ float4 ornB =rigidBodies[bodyIndexB].m_quat;
+ float4 c1 = transform(&c1local,&posB,&ornB);
+ const float4 DeltaC2 = c0 - c1;
+ float4 sepNormal = separatingNormals[i];
+
+ int numEdgeEdgeDirections = convexShapes[shapeIndexA].m_numUniqueEdges*convexShapes[shapeIndexB].m_numUniqueEdges;
+ if (numEdgeEdgeDirections>numUnitSphereDirections)
+ {
+ bool sepEE = findSeparatingAxisUnitSphere( &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,
+ posB,ornB,
+ DeltaC2,
+ vertices,unitSphereDirections,numUnitSphereDirections,&sepNormal,&dmin);
+ if (!sepEE)
+ {
+ hasSeparatingAxis[i] = 0;
+ } else
+ {
+ hasSeparatingAxis[i] = 1;
+ separatingNormals[i] = sepNormal;
+ }
+ }
+ } //if (hasSeparatingAxis[i])
+ }//(i<numPairs)
+}
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/kernels/mprKernels.h b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/kernels/mprKernels.h
new file mode 100644
index 0000000000..7ed4b382c3
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/kernels/mprKernels.h
@@ -0,0 +1,1446 @@
+//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
+static const char* mprKernelsCL= \
+"/***\n"
+" * ---------------------------------\n"
+" * Copyright (c)2012 Daniel Fiser <danfis@danfis.cz>\n"
+" *\n"
+" * This file was ported from mpr.c file, part of libccd.\n"
+" * The Minkoski Portal Refinement implementation was ported \n"
+" * to OpenCL by Erwin Coumans for the Bullet 3 Physics library.\n"
+" * at http://github.com/erwincoumans/bullet3\n"
+" *\n"
+" * Distributed under the OSI-approved BSD License (the \"License\");\n"
+" * see <http://www.opensource.org/licenses/bsd-license.php>.\n"
+" * This software is distributed WITHOUT ANY WARRANTY; without even the\n"
+" * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
+" * See the License for more information.\n"
+" */\n"
+"#ifndef B3_MPR_PENETRATION_H\n"
+"#define B3_MPR_PENETRATION_H\n"
+"#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+"#define B3_PLATFORM_DEFINITIONS_H\n"
+"struct MyTest\n"
+"{\n"
+" int bla;\n"
+"};\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
+"#define B3_LARGE_FLOAT 1e18f\n"
+"#define B3_INFINITY 1e18f\n"
+"#define b3Assert(a)\n"
+"#define b3ConstArray(a) __global const a*\n"
+"#define b3AtomicInc atomic_inc\n"
+"#define b3AtomicAdd atomic_add\n"
+"#define b3Fabs fabs\n"
+"#define b3Sqrt native_sqrt\n"
+"#define b3Sin native_sin\n"
+"#define b3Cos native_cos\n"
+"#define B3_STATIC\n"
+"#endif\n"
+"#endif\n"
+"#ifndef B3_FLOAT4_H\n"
+"#define B3_FLOAT4_H\n"
+"#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"#endif\n"
+"#endif\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+" typedef float4 b3Float4;\n"
+" #define b3Float4ConstArg const b3Float4\n"
+" #define b3MakeFloat4 (float4)\n"
+" float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+" {\n"
+" float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+" float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+" return dot(a1, b1);\n"
+" }\n"
+" b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+" {\n"
+" float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+" float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+" return cross(a1, b1);\n"
+" }\n"
+" #define b3MinFloat4 min\n"
+" #define b3MaxFloat4 max\n"
+" #define b3Normalized(a) normalize(a)\n"
+"#endif \n"
+" \n"
+"inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
+"{\n"
+" if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6) \n"
+" return false;\n"
+" return true;\n"
+"}\n"
+"inline int b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
+"{\n"
+" float maxDot = -B3_INFINITY;\n"
+" int i = 0;\n"
+" int ptIndex = -1;\n"
+" for( i = 0; i < vecLen; i++ )\n"
+" {\n"
+" float dot = b3Dot3F4(vecArray[i],vec);\n"
+" \n"
+" if( dot > maxDot )\n"
+" {\n"
+" maxDot = dot;\n"
+" ptIndex = i;\n"
+" }\n"
+" }\n"
+" b3Assert(ptIndex>=0);\n"
+" if (ptIndex<0)\n"
+" {\n"
+" ptIndex = 0;\n"
+" }\n"
+" *dotOut = maxDot;\n"
+" return ptIndex;\n"
+"}\n"
+"#endif //B3_FLOAT4_H\n"
+"#ifndef B3_RIGIDBODY_DATA_H\n"
+"#define B3_RIGIDBODY_DATA_H\n"
+"#ifndef B3_FLOAT4_H\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"#endif \n"
+"#endif //B3_FLOAT4_H\n"
+"#ifndef B3_QUAT_H\n"
+"#define B3_QUAT_H\n"
+"#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"#endif\n"
+"#endif\n"
+"#ifndef B3_FLOAT4_H\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"#endif \n"
+"#endif //B3_FLOAT4_H\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+" typedef float4 b3Quat;\n"
+" #define b3QuatConstArg const b3Quat\n"
+" \n"
+" \n"
+"inline float4 b3FastNormalize4(float4 v)\n"
+"{\n"
+" v = (float4)(v.xyz,0.f);\n"
+" return fast_normalize(v);\n"
+"}\n"
+" \n"
+"inline b3Quat b3QuatMul(b3Quat a, b3Quat b);\n"
+"inline b3Quat b3QuatNormalized(b3QuatConstArg in);\n"
+"inline b3Quat b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec);\n"
+"inline b3Quat b3QuatInvert(b3QuatConstArg q);\n"
+"inline b3Quat b3QuatInverse(b3QuatConstArg q);\n"
+"inline b3Quat b3QuatMul(b3QuatConstArg a, b3QuatConstArg b)\n"
+"{\n"
+" b3Quat ans;\n"
+" ans = b3Cross3( a, b );\n"
+" ans += a.w*b+b.w*a;\n"
+"// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
+" ans.w = a.w*b.w - b3Dot3F4(a, b);\n"
+" return ans;\n"
+"}\n"
+"inline b3Quat b3QuatNormalized(b3QuatConstArg in)\n"
+"{\n"
+" b3Quat q;\n"
+" q=in;\n"
+" //return b3FastNormalize4(in);\n"
+" float len = native_sqrt(dot(q, q));\n"
+" if(len > 0.f)\n"
+" {\n"
+" q *= 1.f / len;\n"
+" }\n"
+" else\n"
+" {\n"
+" q.x = q.y = q.z = 0.f;\n"
+" q.w = 1.f;\n"
+" }\n"
+" return q;\n"
+"}\n"
+"inline float4 b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
+"{\n"
+" b3Quat qInv = b3QuatInvert( q );\n"
+" float4 vcpy = vec;\n"
+" vcpy.w = 0.f;\n"
+" float4 out = b3QuatMul(b3QuatMul(q,vcpy),qInv);\n"
+" return out;\n"
+"}\n"
+"inline b3Quat b3QuatInverse(b3QuatConstArg q)\n"
+"{\n"
+" return (b3Quat)(-q.xyz, q.w);\n"
+"}\n"
+"inline b3Quat b3QuatInvert(b3QuatConstArg q)\n"
+"{\n"
+" return (b3Quat)(-q.xyz, q.w);\n"
+"}\n"
+"inline float4 b3QuatInvRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
+"{\n"
+" return b3QuatRotate( b3QuatInvert( q ), vec );\n"
+"}\n"
+"inline b3Float4 b3TransformPoint(b3Float4ConstArg point, b3Float4ConstArg translation, b3QuatConstArg orientation)\n"
+"{\n"
+" return b3QuatRotate( orientation, point ) + (translation);\n"
+"}\n"
+" \n"
+"#endif \n"
+"#endif //B3_QUAT_H\n"
+"#ifndef B3_MAT3x3_H\n"
+"#define B3_MAT3x3_H\n"
+"#ifndef B3_QUAT_H\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"#endif \n"
+"#endif //B3_QUAT_H\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"typedef struct\n"
+"{\n"
+" b3Float4 m_row[3];\n"
+"}b3Mat3x3;\n"
+"#define b3Mat3x3ConstArg const b3Mat3x3\n"
+"#define b3GetRow(m,row) (m.m_row[row])\n"
+"inline b3Mat3x3 b3QuatGetRotationMatrix(b3Quat quat)\n"
+"{\n"
+" b3Float4 quat2 = (b3Float4)(quat.x*quat.x, quat.y*quat.y, quat.z*quat.z, 0.f);\n"
+" b3Mat3x3 out;\n"
+" out.m_row[0].x=1-2*quat2.y-2*quat2.z;\n"
+" out.m_row[0].y=2*quat.x*quat.y-2*quat.w*quat.z;\n"
+" out.m_row[0].z=2*quat.x*quat.z+2*quat.w*quat.y;\n"
+" out.m_row[0].w = 0.f;\n"
+" out.m_row[1].x=2*quat.x*quat.y+2*quat.w*quat.z;\n"
+" out.m_row[1].y=1-2*quat2.x-2*quat2.z;\n"
+" out.m_row[1].z=2*quat.y*quat.z-2*quat.w*quat.x;\n"
+" out.m_row[1].w = 0.f;\n"
+" out.m_row[2].x=2*quat.x*quat.z-2*quat.w*quat.y;\n"
+" out.m_row[2].y=2*quat.y*quat.z+2*quat.w*quat.x;\n"
+" out.m_row[2].z=1-2*quat2.x-2*quat2.y;\n"
+" out.m_row[2].w = 0.f;\n"
+" return out;\n"
+"}\n"
+"inline b3Mat3x3 b3AbsoluteMat3x3(b3Mat3x3ConstArg matIn)\n"
+"{\n"
+" b3Mat3x3 out;\n"
+" out.m_row[0] = fabs(matIn.m_row[0]);\n"
+" out.m_row[1] = fabs(matIn.m_row[1]);\n"
+" out.m_row[2] = fabs(matIn.m_row[2]);\n"
+" return out;\n"
+"}\n"
+"__inline\n"
+"b3Mat3x3 mtZero();\n"
+"__inline\n"
+"b3Mat3x3 mtIdentity();\n"
+"__inline\n"
+"b3Mat3x3 mtTranspose(b3Mat3x3 m);\n"
+"__inline\n"
+"b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b);\n"
+"__inline\n"
+"b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b);\n"
+"__inline\n"
+"b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b);\n"
+"__inline\n"
+"b3Mat3x3 mtZero()\n"
+"{\n"
+" b3Mat3x3 m;\n"
+" m.m_row[0] = (b3Float4)(0.f);\n"
+" m.m_row[1] = (b3Float4)(0.f);\n"
+" m.m_row[2] = (b3Float4)(0.f);\n"
+" return m;\n"
+"}\n"
+"__inline\n"
+"b3Mat3x3 mtIdentity()\n"
+"{\n"
+" b3Mat3x3 m;\n"
+" m.m_row[0] = (b3Float4)(1,0,0,0);\n"
+" m.m_row[1] = (b3Float4)(0,1,0,0);\n"
+" m.m_row[2] = (b3Float4)(0,0,1,0);\n"
+" return m;\n"
+"}\n"
+"__inline\n"
+"b3Mat3x3 mtTranspose(b3Mat3x3 m)\n"
+"{\n"
+" b3Mat3x3 out;\n"
+" out.m_row[0] = (b3Float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);\n"
+" out.m_row[1] = (b3Float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);\n"
+" out.m_row[2] = (b3Float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);\n"
+" return out;\n"
+"}\n"
+"__inline\n"
+"b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b)\n"
+"{\n"
+" b3Mat3x3 transB;\n"
+" transB = mtTranspose( b );\n"
+" b3Mat3x3 ans;\n"
+" // why this doesn't run when 0ing in the for{}\n"
+" a.m_row[0].w = 0.f;\n"
+" a.m_row[1].w = 0.f;\n"
+" a.m_row[2].w = 0.f;\n"
+" for(int i=0; i<3; i++)\n"
+" {\n"
+"// a.m_row[i].w = 0.f;\n"
+" ans.m_row[i].x = b3Dot3F4(a.m_row[i],transB.m_row[0]);\n"
+" ans.m_row[i].y = b3Dot3F4(a.m_row[i],transB.m_row[1]);\n"
+" ans.m_row[i].z = b3Dot3F4(a.m_row[i],transB.m_row[2]);\n"
+" ans.m_row[i].w = 0.f;\n"
+" }\n"
+" return ans;\n"
+"}\n"
+"__inline\n"
+"b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b)\n"
+"{\n"
+" b3Float4 ans;\n"
+" ans.x = b3Dot3F4( a.m_row[0], b );\n"
+" ans.y = b3Dot3F4( a.m_row[1], b );\n"
+" ans.z = b3Dot3F4( a.m_row[2], b );\n"
+" ans.w = 0.f;\n"
+" return ans;\n"
+"}\n"
+"__inline\n"
+"b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b)\n"
+"{\n"
+" b3Float4 colx = b3MakeFloat4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
+" b3Float4 coly = b3MakeFloat4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
+" b3Float4 colz = b3MakeFloat4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
+" b3Float4 ans;\n"
+" ans.x = b3Dot3F4( a, colx );\n"
+" ans.y = b3Dot3F4( a, coly );\n"
+" ans.z = b3Dot3F4( a, colz );\n"
+" return ans;\n"
+"}\n"
+"#endif\n"
+"#endif //B3_MAT3x3_H\n"
+"typedef struct b3RigidBodyData b3RigidBodyData_t;\n"
+"struct b3RigidBodyData\n"
+"{\n"
+" b3Float4 m_pos;\n"
+" b3Quat m_quat;\n"
+" b3Float4 m_linVel;\n"
+" b3Float4 m_angVel;\n"
+" int m_collidableIdx;\n"
+" float m_invMass;\n"
+" float m_restituitionCoeff;\n"
+" float m_frictionCoeff;\n"
+"};\n"
+"typedef struct b3InertiaData b3InertiaData_t;\n"
+"struct b3InertiaData\n"
+"{\n"
+" b3Mat3x3 m_invInertiaWorld;\n"
+" b3Mat3x3 m_initInvInertia;\n"
+"};\n"
+"#endif //B3_RIGIDBODY_DATA_H\n"
+" \n"
+"#ifndef B3_CONVEX_POLYHEDRON_DATA_H\n"
+"#define B3_CONVEX_POLYHEDRON_DATA_H\n"
+"#ifndef B3_FLOAT4_H\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"#endif \n"
+"#endif //B3_FLOAT4_H\n"
+"#ifndef B3_QUAT_H\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"#endif \n"
+"#endif //B3_QUAT_H\n"
+"typedef struct b3GpuFace b3GpuFace_t;\n"
+"struct b3GpuFace\n"
+"{\n"
+" b3Float4 m_plane;\n"
+" int m_indexOffset;\n"
+" int m_numIndices;\n"
+" int m_unusedPadding1;\n"
+" int m_unusedPadding2;\n"
+"};\n"
+"typedef struct b3ConvexPolyhedronData b3ConvexPolyhedronData_t;\n"
+"struct b3ConvexPolyhedronData\n"
+"{\n"
+" b3Float4 m_localCenter;\n"
+" b3Float4 m_extents;\n"
+" b3Float4 mC;\n"
+" b3Float4 mE;\n"
+" float m_radius;\n"
+" int m_faceOffset;\n"
+" int m_numFaces;\n"
+" int m_numVertices;\n"
+" int m_vertexOffset;\n"
+" int m_uniqueEdgesOffset;\n"
+" int m_numUniqueEdges;\n"
+" int m_unused;\n"
+"};\n"
+"#endif //B3_CONVEX_POLYHEDRON_DATA_H\n"
+"#ifndef B3_COLLIDABLE_H\n"
+"#define B3_COLLIDABLE_H\n"
+"#ifndef B3_FLOAT4_H\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"#endif \n"
+"#endif //B3_FLOAT4_H\n"
+"#ifndef B3_QUAT_H\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"#endif \n"
+"#endif //B3_QUAT_H\n"
+"enum b3ShapeTypes\n"
+"{\n"
+" SHAPE_HEIGHT_FIELD=1,\n"
+" SHAPE_CONVEX_HULL=3,\n"
+" SHAPE_PLANE=4,\n"
+" SHAPE_CONCAVE_TRIMESH=5,\n"
+" SHAPE_COMPOUND_OF_CONVEX_HULLS=6,\n"
+" SHAPE_SPHERE=7,\n"
+" MAX_NUM_SHAPE_TYPES,\n"
+"};\n"
+"typedef struct b3Collidable b3Collidable_t;\n"
+"struct b3Collidable\n"
+"{\n"
+" union {\n"
+" int m_numChildShapes;\n"
+" int m_bvhIndex;\n"
+" };\n"
+" union\n"
+" {\n"
+" float m_radius;\n"
+" int m_compoundBvhIndex;\n"
+" };\n"
+" int m_shapeType;\n"
+" int m_shapeIndex;\n"
+"};\n"
+"typedef struct b3GpuChildShape b3GpuChildShape_t;\n"
+"struct b3GpuChildShape\n"
+"{\n"
+" b3Float4 m_childPosition;\n"
+" b3Quat m_childOrientation;\n"
+" int m_shapeIndex;\n"
+" int m_unused0;\n"
+" int m_unused1;\n"
+" int m_unused2;\n"
+"};\n"
+"struct b3CompoundOverlappingPair\n"
+"{\n"
+" int m_bodyIndexA;\n"
+" int m_bodyIndexB;\n"
+"// int m_pairType;\n"
+" int m_childShapeIndexA;\n"
+" int m_childShapeIndexB;\n"
+"};\n"
+"#endif //B3_COLLIDABLE_H\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"#define B3_MPR_SQRT sqrt\n"
+"#endif\n"
+"#define B3_MPR_FMIN(x, y) ((x) < (y) ? (x) : (y))\n"
+"#define B3_MPR_FABS fabs\n"
+"#define B3_MPR_TOLERANCE 1E-6f\n"
+"#define B3_MPR_MAX_ITERATIONS 1000\n"
+"struct _b3MprSupport_t \n"
+"{\n"
+" b3Float4 v; //!< Support point in minkowski sum\n"
+" b3Float4 v1; //!< Support point in obj1\n"
+" b3Float4 v2; //!< Support point in obj2\n"
+"};\n"
+"typedef struct _b3MprSupport_t b3MprSupport_t;\n"
+"struct _b3MprSimplex_t \n"
+"{\n"
+" b3MprSupport_t ps[4];\n"
+" int last; //!< index of last added point\n"
+"};\n"
+"typedef struct _b3MprSimplex_t b3MprSimplex_t;\n"
+"inline b3MprSupport_t* b3MprSimplexPointW(b3MprSimplex_t *s, int idx)\n"
+"{\n"
+" return &s->ps[idx];\n"
+"}\n"
+"inline void b3MprSimplexSetSize(b3MprSimplex_t *s, int size)\n"
+"{\n"
+" s->last = size - 1;\n"
+"}\n"
+"inline int b3MprSimplexSize(const b3MprSimplex_t *s)\n"
+"{\n"
+" return s->last + 1;\n"
+"}\n"
+"inline const b3MprSupport_t* b3MprSimplexPoint(const b3MprSimplex_t* s, int idx)\n"
+"{\n"
+" // here is no check on boundaries\n"
+" return &s->ps[idx];\n"
+"}\n"
+"inline void b3MprSupportCopy(b3MprSupport_t *d, const b3MprSupport_t *s)\n"
+"{\n"
+" *d = *s;\n"
+"}\n"
+"inline void b3MprSimplexSet(b3MprSimplex_t *s, size_t pos, const b3MprSupport_t *a)\n"
+"{\n"
+" b3MprSupportCopy(s->ps + pos, a);\n"
+"}\n"
+"inline void b3MprSimplexSwap(b3MprSimplex_t *s, size_t pos1, size_t pos2)\n"
+"{\n"
+" b3MprSupport_t supp;\n"
+" b3MprSupportCopy(&supp, &s->ps[pos1]);\n"
+" b3MprSupportCopy(&s->ps[pos1], &s->ps[pos2]);\n"
+" b3MprSupportCopy(&s->ps[pos2], &supp);\n"
+"}\n"
+"inline int b3MprIsZero(float val)\n"
+"{\n"
+" return B3_MPR_FABS(val) < FLT_EPSILON;\n"
+"}\n"
+"inline int b3MprEq(float _a, float _b)\n"
+"{\n"
+" float ab;\n"
+" float a, b;\n"
+" ab = B3_MPR_FABS(_a - _b);\n"
+" if (B3_MPR_FABS(ab) < FLT_EPSILON)\n"
+" return 1;\n"
+" a = B3_MPR_FABS(_a);\n"
+" b = B3_MPR_FABS(_b);\n"
+" if (b > a){\n"
+" return ab < FLT_EPSILON * b;\n"
+" }else{\n"
+" return ab < FLT_EPSILON * a;\n"
+" }\n"
+"}\n"
+"inline int b3MprVec3Eq(const b3Float4* a, const b3Float4 *b)\n"
+"{\n"
+" return b3MprEq((*a).x, (*b).x)\n"
+" && b3MprEq((*a).y, (*b).y)\n"
+" && b3MprEq((*a).z, (*b).z);\n"
+"}\n"
+"inline b3Float4 b3LocalGetSupportVertex(b3Float4ConstArg supportVec,__global const b3ConvexPolyhedronData_t* hull, b3ConstArray(b3Float4) verticesA)\n"
+"{\n"
+" b3Float4 supVec = b3MakeFloat4(0,0,0,0);\n"
+" float maxDot = -B3_LARGE_FLOAT;\n"
+" if( 0 < hull->m_numVertices )\n"
+" {\n"
+" const b3Float4 scaled = supportVec;\n"
+" int index = b3MaxDot(scaled, &verticesA[hull->m_vertexOffset], hull->m_numVertices, &maxDot);\n"
+" return verticesA[hull->m_vertexOffset+index];\n"
+" }\n"
+" return supVec;\n"
+"}\n"
+"B3_STATIC void b3MprConvexSupport(int pairIndex,int bodyIndex, b3ConstArray(b3RigidBodyData_t) cpuBodyBuf, \n"
+" b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData, \n"
+" b3ConstArray(b3Collidable_t) cpuCollidables,\n"
+" b3ConstArray(b3Float4) cpuVertices,\n"
+" __global b3Float4* sepAxis,\n"
+" const b3Float4* _dir, b3Float4* outp, int logme)\n"
+"{\n"
+" //dir is in worldspace, move to local space\n"
+" \n"
+" b3Float4 pos = cpuBodyBuf[bodyIndex].m_pos;\n"
+" b3Quat orn = cpuBodyBuf[bodyIndex].m_quat;\n"
+" \n"
+" b3Float4 dir = b3MakeFloat4((*_dir).x,(*_dir).y,(*_dir).z,0.f);\n"
+" \n"
+" const b3Float4 localDir = b3QuatRotate(b3QuatInverse(orn),dir);\n"
+" \n"
+" //find local support vertex\n"
+" int colIndex = cpuBodyBuf[bodyIndex].m_collidableIdx;\n"
+" \n"
+" b3Assert(cpuCollidables[colIndex].m_shapeType==SHAPE_CONVEX_HULL);\n"
+" __global const b3ConvexPolyhedronData_t* hull = &cpuConvexData[cpuCollidables[colIndex].m_shapeIndex];\n"
+" \n"
+" b3Float4 pInA;\n"
+" if (logme)\n"
+" {\n"
+" b3Float4 supVec = b3MakeFloat4(0,0,0,0);\n"
+" float maxDot = -B3_LARGE_FLOAT;\n"
+" if( 0 < hull->m_numVertices )\n"
+" {\n"
+" const b3Float4 scaled = localDir;\n"
+" int index = b3MaxDot(scaled, &cpuVertices[hull->m_vertexOffset], hull->m_numVertices, &maxDot);\n"
+" pInA = cpuVertices[hull->m_vertexOffset+index];\n"
+" \n"
+" }\n"
+" } else\n"
+" {\n"
+" pInA = b3LocalGetSupportVertex(localDir,hull,cpuVertices);\n"
+" }\n"
+" //move vertex to world space\n"
+" *outp = b3TransformPoint(pInA,pos,orn);\n"
+" \n"
+"}\n"
+"inline void b3MprSupport(int pairIndex,int bodyIndexA, int bodyIndexB, b3ConstArray(b3RigidBodyData_t) cpuBodyBuf, \n"
+" b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData, \n"
+" b3ConstArray(b3Collidable_t) cpuCollidables,\n"
+" b3ConstArray(b3Float4) cpuVertices,\n"
+" __global b3Float4* sepAxis,\n"
+" const b3Float4* _dir, b3MprSupport_t *supp)\n"
+"{\n"
+" b3Float4 dir;\n"
+" dir = *_dir;\n"
+" b3MprConvexSupport(pairIndex,bodyIndexA,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices,sepAxis,&dir, &supp->v1,0);\n"
+" dir = *_dir*-1.f;\n"
+" b3MprConvexSupport(pairIndex,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices,sepAxis,&dir, &supp->v2,0);\n"
+" supp->v = supp->v1 - supp->v2;\n"
+"}\n"
+"inline void b3FindOrigin(int bodyIndexA, int bodyIndexB, b3ConstArray(b3RigidBodyData_t) cpuBodyBuf, b3MprSupport_t *center)\n"
+"{\n"
+" center->v1 = cpuBodyBuf[bodyIndexA].m_pos;\n"
+" center->v2 = cpuBodyBuf[bodyIndexB].m_pos;\n"
+" center->v = center->v1 - center->v2;\n"
+"}\n"
+"inline void b3MprVec3Set(b3Float4 *v, float x, float y, float z)\n"
+"{\n"
+" (*v).x = x;\n"
+" (*v).y = y;\n"
+" (*v).z = z;\n"
+" (*v).w = 0.f;\n"
+"}\n"
+"inline void b3MprVec3Add(b3Float4 *v, const b3Float4 *w)\n"
+"{\n"
+" (*v).x += (*w).x;\n"
+" (*v).y += (*w).y;\n"
+" (*v).z += (*w).z;\n"
+"}\n"
+"inline void b3MprVec3Copy(b3Float4 *v, const b3Float4 *w)\n"
+"{\n"
+" *v = *w;\n"
+"}\n"
+"inline void b3MprVec3Scale(b3Float4 *d, float k)\n"
+"{\n"
+" *d *= k;\n"
+"}\n"
+"inline float b3MprVec3Dot(const b3Float4 *a, const b3Float4 *b)\n"
+"{\n"
+" float dot;\n"
+" dot = b3Dot3F4(*a,*b);\n"
+" return dot;\n"
+"}\n"
+"inline float b3MprVec3Len2(const b3Float4 *v)\n"
+"{\n"
+" return b3MprVec3Dot(v, v);\n"
+"}\n"
+"inline void b3MprVec3Normalize(b3Float4 *d)\n"
+"{\n"
+" float k = 1.f / B3_MPR_SQRT(b3MprVec3Len2(d));\n"
+" b3MprVec3Scale(d, k);\n"
+"}\n"
+"inline void b3MprVec3Cross(b3Float4 *d, const b3Float4 *a, const b3Float4 *b)\n"
+"{\n"
+" *d = b3Cross3(*a,*b);\n"
+" \n"
+"}\n"
+"inline void b3MprVec3Sub2(b3Float4 *d, const b3Float4 *v, const b3Float4 *w)\n"
+"{\n"
+" *d = *v - *w;\n"
+"}\n"
+"inline void b3PortalDir(const b3MprSimplex_t *portal, b3Float4 *dir)\n"
+"{\n"
+" b3Float4 v2v1, v3v1;\n"
+" b3MprVec3Sub2(&v2v1, &b3MprSimplexPoint(portal, 2)->v,\n"
+" &b3MprSimplexPoint(portal, 1)->v);\n"
+" b3MprVec3Sub2(&v3v1, &b3MprSimplexPoint(portal, 3)->v,\n"
+" &b3MprSimplexPoint(portal, 1)->v);\n"
+" b3MprVec3Cross(dir, &v2v1, &v3v1);\n"
+" b3MprVec3Normalize(dir);\n"
+"}\n"
+"inline int portalEncapsulesOrigin(const b3MprSimplex_t *portal,\n"
+" const b3Float4 *dir)\n"
+"{\n"
+" float dot;\n"
+" dot = b3MprVec3Dot(dir, &b3MprSimplexPoint(portal, 1)->v);\n"
+" return b3MprIsZero(dot) || dot > 0.f;\n"
+"}\n"
+"inline int portalReachTolerance(const b3MprSimplex_t *portal,\n"
+" const b3MprSupport_t *v4,\n"
+" const b3Float4 *dir)\n"
+"{\n"
+" float dv1, dv2, dv3, dv4;\n"
+" float dot1, dot2, dot3;\n"
+" // find the smallest dot product of dir and {v1-v4, v2-v4, v3-v4}\n"
+" dv1 = b3MprVec3Dot(&b3MprSimplexPoint(portal, 1)->v, dir);\n"
+" dv2 = b3MprVec3Dot(&b3MprSimplexPoint(portal, 2)->v, dir);\n"
+" dv3 = b3MprVec3Dot(&b3MprSimplexPoint(portal, 3)->v, dir);\n"
+" dv4 = b3MprVec3Dot(&v4->v, dir);\n"
+" dot1 = dv4 - dv1;\n"
+" dot2 = dv4 - dv2;\n"
+" dot3 = dv4 - dv3;\n"
+" dot1 = B3_MPR_FMIN(dot1, dot2);\n"
+" dot1 = B3_MPR_FMIN(dot1, dot3);\n"
+" return b3MprEq(dot1, B3_MPR_TOLERANCE) || dot1 < B3_MPR_TOLERANCE;\n"
+"}\n"
+"inline int portalCanEncapsuleOrigin(const b3MprSimplex_t *portal, \n"
+" const b3MprSupport_t *v4,\n"
+" const b3Float4 *dir)\n"
+"{\n"
+" float dot;\n"
+" dot = b3MprVec3Dot(&v4->v, dir);\n"
+" return b3MprIsZero(dot) || dot > 0.f;\n"
+"}\n"
+"inline void b3ExpandPortal(b3MprSimplex_t *portal,\n"
+" const b3MprSupport_t *v4)\n"
+"{\n"
+" float dot;\n"
+" b3Float4 v4v0;\n"
+" b3MprVec3Cross(&v4v0, &v4->v, &b3MprSimplexPoint(portal, 0)->v);\n"
+" dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 1)->v, &v4v0);\n"
+" if (dot > 0.f){\n"
+" dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 2)->v, &v4v0);\n"
+" if (dot > 0.f){\n"
+" b3MprSimplexSet(portal, 1, v4);\n"
+" }else{\n"
+" b3MprSimplexSet(portal, 3, v4);\n"
+" }\n"
+" }else{\n"
+" dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 3)->v, &v4v0);\n"
+" if (dot > 0.f){\n"
+" b3MprSimplexSet(portal, 2, v4);\n"
+" }else{\n"
+" b3MprSimplexSet(portal, 1, v4);\n"
+" }\n"
+" }\n"
+"}\n"
+"B3_STATIC int b3DiscoverPortal(int pairIndex, int bodyIndexA, int bodyIndexB, b3ConstArray(b3RigidBodyData_t) cpuBodyBuf, \n"
+" b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData, \n"
+" b3ConstArray(b3Collidable_t) cpuCollidables,\n"
+" b3ConstArray(b3Float4) cpuVertices,\n"
+" __global b3Float4* sepAxis,\n"
+" __global int* hasSepAxis,\n"
+" b3MprSimplex_t *portal)\n"
+"{\n"
+" b3Float4 dir, va, vb;\n"
+" float dot;\n"
+" int cont;\n"
+" \n"
+" \n"
+" // vertex 0 is center of portal\n"
+" b3FindOrigin(bodyIndexA,bodyIndexB,cpuBodyBuf, b3MprSimplexPointW(portal, 0));\n"
+" // vertex 0 is center of portal\n"
+" b3MprSimplexSetSize(portal, 1);\n"
+" \n"
+" b3Float4 zero = b3MakeFloat4(0,0,0,0);\n"
+" b3Float4* b3mpr_vec3_origin = &zero;\n"
+" if (b3MprVec3Eq(&b3MprSimplexPoint(portal, 0)->v, b3mpr_vec3_origin)){\n"
+" // Portal's center lies on origin (0,0,0) => we know that objects\n"
+" // intersect but we would need to know penetration info.\n"
+" // So move center little bit...\n"
+" b3MprVec3Set(&va, FLT_EPSILON * 10.f, 0.f, 0.f);\n"
+" b3MprVec3Add(&b3MprSimplexPointW(portal, 0)->v, &va);\n"
+" }\n"
+" // vertex 1 = support in direction of origin\n"
+" b3MprVec3Copy(&dir, &b3MprSimplexPoint(portal, 0)->v);\n"
+" b3MprVec3Scale(&dir, -1.f);\n"
+" b3MprVec3Normalize(&dir);\n"
+" b3MprSupport(pairIndex,bodyIndexA,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices, sepAxis,&dir, b3MprSimplexPointW(portal, 1));\n"
+" b3MprSimplexSetSize(portal, 2);\n"
+" // test if origin isn't outside of v1\n"
+" dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 1)->v, &dir);\n"
+" \n"
+" if (b3MprIsZero(dot) || dot < 0.f)\n"
+" return -1;\n"
+" // vertex 2\n"
+" b3MprVec3Cross(&dir, &b3MprSimplexPoint(portal, 0)->v,\n"
+" &b3MprSimplexPoint(portal, 1)->v);\n"
+" if (b3MprIsZero(b3MprVec3Len2(&dir))){\n"
+" if (b3MprVec3Eq(&b3MprSimplexPoint(portal, 1)->v, b3mpr_vec3_origin)){\n"
+" // origin lies on v1\n"
+" return 1;\n"
+" }else{\n"
+" // origin lies on v0-v1 segment\n"
+" return 2;\n"
+" }\n"
+" }\n"
+" b3MprVec3Normalize(&dir);\n"
+" b3MprSupport(pairIndex,bodyIndexA,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices, sepAxis,&dir, b3MprSimplexPointW(portal, 2));\n"
+" \n"
+" dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 2)->v, &dir);\n"
+" if (b3MprIsZero(dot) || dot < 0.f)\n"
+" return -1;\n"
+" b3MprSimplexSetSize(portal, 3);\n"
+" // vertex 3 direction\n"
+" b3MprVec3Sub2(&va, &b3MprSimplexPoint(portal, 1)->v,\n"
+" &b3MprSimplexPoint(portal, 0)->v);\n"
+" b3MprVec3Sub2(&vb, &b3MprSimplexPoint(portal, 2)->v,\n"
+" &b3MprSimplexPoint(portal, 0)->v);\n"
+" b3MprVec3Cross(&dir, &va, &vb);\n"
+" b3MprVec3Normalize(&dir);\n"
+" // it is better to form portal faces to be oriented \"outside\" origin\n"
+" dot = b3MprVec3Dot(&dir, &b3MprSimplexPoint(portal, 0)->v);\n"
+" if (dot > 0.f){\n"
+" b3MprSimplexSwap(portal, 1, 2);\n"
+" b3MprVec3Scale(&dir, -1.f);\n"
+" }\n"
+" while (b3MprSimplexSize(portal) < 4){\n"
+" b3MprSupport(pairIndex,bodyIndexA,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices, sepAxis,&dir, b3MprSimplexPointW(portal, 3));\n"
+" \n"
+" dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 3)->v, &dir);\n"
+" if (b3MprIsZero(dot) || dot < 0.f)\n"
+" return -1;\n"
+" cont = 0;\n"
+" // test if origin is outside (v1, v0, v3) - set v2 as v3 and\n"
+" // continue\n"
+" b3MprVec3Cross(&va, &b3MprSimplexPoint(portal, 1)->v,\n"
+" &b3MprSimplexPoint(portal, 3)->v);\n"
+" dot = b3MprVec3Dot(&va, &b3MprSimplexPoint(portal, 0)->v);\n"
+" if (dot < 0.f && !b3MprIsZero(dot)){\n"
+" b3MprSimplexSet(portal, 2, b3MprSimplexPoint(portal, 3));\n"
+" cont = 1;\n"
+" }\n"
+" if (!cont){\n"
+" // test if origin is outside (v3, v0, v2) - set v1 as v3 and\n"
+" // continue\n"
+" b3MprVec3Cross(&va, &b3MprSimplexPoint(portal, 3)->v,\n"
+" &b3MprSimplexPoint(portal, 2)->v);\n"
+" dot = b3MprVec3Dot(&va, &b3MprSimplexPoint(portal, 0)->v);\n"
+" if (dot < 0.f && !b3MprIsZero(dot)){\n"
+" b3MprSimplexSet(portal, 1, b3MprSimplexPoint(portal, 3));\n"
+" cont = 1;\n"
+" }\n"
+" }\n"
+" if (cont){\n"
+" b3MprVec3Sub2(&va, &b3MprSimplexPoint(portal, 1)->v,\n"
+" &b3MprSimplexPoint(portal, 0)->v);\n"
+" b3MprVec3Sub2(&vb, &b3MprSimplexPoint(portal, 2)->v,\n"
+" &b3MprSimplexPoint(portal, 0)->v);\n"
+" b3MprVec3Cross(&dir, &va, &vb);\n"
+" b3MprVec3Normalize(&dir);\n"
+" }else{\n"
+" b3MprSimplexSetSize(portal, 4);\n"
+" }\n"
+" }\n"
+" return 0;\n"
+"}\n"
+"B3_STATIC int b3RefinePortal(int pairIndex,int bodyIndexA, int bodyIndexB, b3ConstArray(b3RigidBodyData_t) cpuBodyBuf, \n"
+" b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData, \n"
+" b3ConstArray(b3Collidable_t) cpuCollidables,\n"
+" b3ConstArray(b3Float4) cpuVertices,\n"
+" __global b3Float4* sepAxis,\n"
+" b3MprSimplex_t *portal)\n"
+"{\n"
+" b3Float4 dir;\n"
+" b3MprSupport_t v4;\n"
+" for (int i=0;i<B3_MPR_MAX_ITERATIONS;i++)\n"
+" //while (1)\n"
+" {\n"
+" // compute direction outside the portal (from v0 throught v1,v2,v3\n"
+" // face)\n"
+" b3PortalDir(portal, &dir);\n"
+" // test if origin is inside the portal\n"
+" if (portalEncapsulesOrigin(portal, &dir))\n"
+" return 0;\n"
+" // get next support point\n"
+" \n"
+" b3MprSupport(pairIndex,bodyIndexA,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices, sepAxis,&dir, &v4);\n"
+" // test if v4 can expand portal to contain origin and if portal\n"
+" // expanding doesn't reach given tolerance\n"
+" if (!portalCanEncapsuleOrigin(portal, &v4, &dir)\n"
+" || portalReachTolerance(portal, &v4, &dir))\n"
+" {\n"
+" return -1;\n"
+" }\n"
+" // v1-v2-v3 triangle must be rearranged to face outside Minkowski\n"
+" // difference (direction from v0).\n"
+" b3ExpandPortal(portal, &v4);\n"
+" }\n"
+" return -1;\n"
+"}\n"
+"B3_STATIC void b3FindPos(const b3MprSimplex_t *portal, b3Float4 *pos)\n"
+"{\n"
+" b3Float4 zero = b3MakeFloat4(0,0,0,0);\n"
+" b3Float4* b3mpr_vec3_origin = &zero;\n"
+" b3Float4 dir;\n"
+" size_t i;\n"
+" float b[4], sum, inv;\n"
+" b3Float4 vec, p1, p2;\n"
+" b3PortalDir(portal, &dir);\n"
+" // use barycentric coordinates of tetrahedron to find origin\n"
+" b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 1)->v,\n"
+" &b3MprSimplexPoint(portal, 2)->v);\n"
+" b[0] = b3MprVec3Dot(&vec, &b3MprSimplexPoint(portal, 3)->v);\n"
+" b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 3)->v,\n"
+" &b3MprSimplexPoint(portal, 2)->v);\n"
+" b[1] = b3MprVec3Dot(&vec, &b3MprSimplexPoint(portal, 0)->v);\n"
+" b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 0)->v,\n"
+" &b3MprSimplexPoint(portal, 1)->v);\n"
+" b[2] = b3MprVec3Dot(&vec, &b3MprSimplexPoint(portal, 3)->v);\n"
+" b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 2)->v,\n"
+" &b3MprSimplexPoint(portal, 1)->v);\n"
+" b[3] = b3MprVec3Dot(&vec, &b3MprSimplexPoint(portal, 0)->v);\n"
+" sum = b[0] + b[1] + b[2] + b[3];\n"
+" if (b3MprIsZero(sum) || sum < 0.f){\n"
+" b[0] = 0.f;\n"
+" b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 2)->v,\n"
+" &b3MprSimplexPoint(portal, 3)->v);\n"
+" b[1] = b3MprVec3Dot(&vec, &dir);\n"
+" b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 3)->v,\n"
+" &b3MprSimplexPoint(portal, 1)->v);\n"
+" b[2] = b3MprVec3Dot(&vec, &dir);\n"
+" b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 1)->v,\n"
+" &b3MprSimplexPoint(portal, 2)->v);\n"
+" b[3] = b3MprVec3Dot(&vec, &dir);\n"
+" sum = b[1] + b[2] + b[3];\n"
+" }\n"
+" inv = 1.f / sum;\n"
+" b3MprVec3Copy(&p1, b3mpr_vec3_origin);\n"
+" b3MprVec3Copy(&p2, b3mpr_vec3_origin);\n"
+" for (i = 0; i < 4; i++){\n"
+" b3MprVec3Copy(&vec, &b3MprSimplexPoint(portal, i)->v1);\n"
+" b3MprVec3Scale(&vec, b[i]);\n"
+" b3MprVec3Add(&p1, &vec);\n"
+" b3MprVec3Copy(&vec, &b3MprSimplexPoint(portal, i)->v2);\n"
+" b3MprVec3Scale(&vec, b[i]);\n"
+" b3MprVec3Add(&p2, &vec);\n"
+" }\n"
+" b3MprVec3Scale(&p1, inv);\n"
+" b3MprVec3Scale(&p2, inv);\n"
+" b3MprVec3Copy(pos, &p1);\n"
+" b3MprVec3Add(pos, &p2);\n"
+" b3MprVec3Scale(pos, 0.5);\n"
+"}\n"
+"inline float b3MprVec3Dist2(const b3Float4 *a, const b3Float4 *b)\n"
+"{\n"
+" b3Float4 ab;\n"
+" b3MprVec3Sub2(&ab, a, b);\n"
+" return b3MprVec3Len2(&ab);\n"
+"}\n"
+"inline float _b3MprVec3PointSegmentDist2(const b3Float4 *P,\n"
+" const b3Float4 *x0,\n"
+" const b3Float4 *b,\n"
+" b3Float4 *witness)\n"
+"{\n"
+" // The computation comes from solving equation of segment:\n"
+" // S(t) = x0 + t.d\n"
+" // where - x0 is initial point of segment\n"
+" // - d is direction of segment from x0 (|d| > 0)\n"
+" // - t belongs to <0, 1> interval\n"
+" // \n"
+" // Than, distance from a segment to some point P can be expressed:\n"
+" // D(t) = |x0 + t.d - P|^2\n"
+" // which is distance from any point on segment. Minimization\n"
+" // of this function brings distance from P to segment.\n"
+" // Minimization of D(t) leads to simple quadratic equation that's\n"
+" // solving is straightforward.\n"
+" //\n"
+" // Bonus of this method is witness point for free.\n"
+" float dist, t;\n"
+" b3Float4 d, a;\n"
+" // direction of segment\n"
+" b3MprVec3Sub2(&d, b, x0);\n"
+" // precompute vector from P to x0\n"
+" b3MprVec3Sub2(&a, x0, P);\n"
+" t = -1.f * b3MprVec3Dot(&a, &d);\n"
+" t /= b3MprVec3Len2(&d);\n"
+" if (t < 0.f || b3MprIsZero(t)){\n"
+" dist = b3MprVec3Dist2(x0, P);\n"
+" if (witness)\n"
+" b3MprVec3Copy(witness, x0);\n"
+" }else if (t > 1.f || b3MprEq(t, 1.f)){\n"
+" dist = b3MprVec3Dist2(b, P);\n"
+" if (witness)\n"
+" b3MprVec3Copy(witness, b);\n"
+" }else{\n"
+" if (witness){\n"
+" b3MprVec3Copy(witness, &d);\n"
+" b3MprVec3Scale(witness, t);\n"
+" b3MprVec3Add(witness, x0);\n"
+" dist = b3MprVec3Dist2(witness, P);\n"
+" }else{\n"
+" // recycling variables\n"
+" b3MprVec3Scale(&d, t);\n"
+" b3MprVec3Add(&d, &a);\n"
+" dist = b3MprVec3Len2(&d);\n"
+" }\n"
+" }\n"
+" return dist;\n"
+"}\n"
+"inline float b3MprVec3PointTriDist2(const b3Float4 *P,\n"
+" const b3Float4 *x0, const b3Float4 *B,\n"
+" const b3Float4 *C,\n"
+" b3Float4 *witness)\n"
+"{\n"
+" // Computation comes from analytic expression for triangle (x0, B, C)\n"
+" // T(s, t) = x0 + s.d1 + t.d2, where d1 = B - x0 and d2 = C - x0 and\n"
+" // Then equation for distance is:\n"
+" // D(s, t) = | T(s, t) - P |^2\n"
+" // This leads to minimization of quadratic function of two variables.\n"
+" // The solution from is taken only if s is between 0 and 1, t is\n"
+" // between 0 and 1 and t + s < 1, otherwise distance from segment is\n"
+" // computed.\n"
+" b3Float4 d1, d2, a;\n"
+" float u, v, w, p, q, r;\n"
+" float s, t, dist, dist2;\n"
+" b3Float4 witness2;\n"
+" b3MprVec3Sub2(&d1, B, x0);\n"
+" b3MprVec3Sub2(&d2, C, x0);\n"
+" b3MprVec3Sub2(&a, x0, P);\n"
+" u = b3MprVec3Dot(&a, &a);\n"
+" v = b3MprVec3Dot(&d1, &d1);\n"
+" w = b3MprVec3Dot(&d2, &d2);\n"
+" p = b3MprVec3Dot(&a, &d1);\n"
+" q = b3MprVec3Dot(&a, &d2);\n"
+" r = b3MprVec3Dot(&d1, &d2);\n"
+" s = (q * r - w * p) / (w * v - r * r);\n"
+" t = (-s * r - q) / w;\n"
+" if ((b3MprIsZero(s) || s > 0.f)\n"
+" && (b3MprEq(s, 1.f) || s < 1.f)\n"
+" && (b3MprIsZero(t) || t > 0.f)\n"
+" && (b3MprEq(t, 1.f) || t < 1.f)\n"
+" && (b3MprEq(t + s, 1.f) || t + s < 1.f)){\n"
+" if (witness){\n"
+" b3MprVec3Scale(&d1, s);\n"
+" b3MprVec3Scale(&d2, t);\n"
+" b3MprVec3Copy(witness, x0);\n"
+" b3MprVec3Add(witness, &d1);\n"
+" b3MprVec3Add(witness, &d2);\n"
+" dist = b3MprVec3Dist2(witness, P);\n"
+" }else{\n"
+" dist = s * s * v;\n"
+" dist += t * t * w;\n"
+" dist += 2.f * s * t * r;\n"
+" dist += 2.f * s * p;\n"
+" dist += 2.f * t * q;\n"
+" dist += u;\n"
+" }\n"
+" }else{\n"
+" dist = _b3MprVec3PointSegmentDist2(P, x0, B, witness);\n"
+" dist2 = _b3MprVec3PointSegmentDist2(P, x0, C, &witness2);\n"
+" if (dist2 < dist){\n"
+" dist = dist2;\n"
+" if (witness)\n"
+" b3MprVec3Copy(witness, &witness2);\n"
+" }\n"
+" dist2 = _b3MprVec3PointSegmentDist2(P, B, C, &witness2);\n"
+" if (dist2 < dist){\n"
+" dist = dist2;\n"
+" if (witness)\n"
+" b3MprVec3Copy(witness, &witness2);\n"
+" }\n"
+" }\n"
+" return dist;\n"
+"}\n"
+"B3_STATIC void b3FindPenetr(int pairIndex,int bodyIndexA, int bodyIndexB, b3ConstArray(b3RigidBodyData_t) cpuBodyBuf, \n"
+" b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData, \n"
+" b3ConstArray(b3Collidable_t) cpuCollidables,\n"
+" b3ConstArray(b3Float4) cpuVertices,\n"
+" __global b3Float4* sepAxis,\n"
+" b3MprSimplex_t *portal,\n"
+" float *depth, b3Float4 *pdir, b3Float4 *pos)\n"
+"{\n"
+" b3Float4 dir;\n"
+" b3MprSupport_t v4;\n"
+" unsigned long iterations;\n"
+" b3Float4 zero = b3MakeFloat4(0,0,0,0);\n"
+" b3Float4* b3mpr_vec3_origin = &zero;\n"
+" iterations = 1UL;\n"
+" for (int i=0;i<B3_MPR_MAX_ITERATIONS;i++)\n"
+" //while (1)\n"
+" {\n"
+" // compute portal direction and obtain next support point\n"
+" b3PortalDir(portal, &dir);\n"
+" \n"
+" b3MprSupport(pairIndex,bodyIndexA,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices, sepAxis,&dir, &v4);\n"
+" // reached tolerance -> find penetration info\n"
+" if (portalReachTolerance(portal, &v4, &dir)\n"
+" || iterations ==B3_MPR_MAX_ITERATIONS)\n"
+" {\n"
+" *depth = b3MprVec3PointTriDist2(b3mpr_vec3_origin,&b3MprSimplexPoint(portal, 1)->v,&b3MprSimplexPoint(portal, 2)->v,&b3MprSimplexPoint(portal, 3)->v,pdir);\n"
+" *depth = B3_MPR_SQRT(*depth);\n"
+" \n"
+" if (b3MprIsZero((*pdir).x) && b3MprIsZero((*pdir).y) && b3MprIsZero((*pdir).z))\n"
+" {\n"
+" \n"
+" *pdir = dir;\n"
+" } \n"
+" b3MprVec3Normalize(pdir);\n"
+" \n"
+" // barycentric coordinates:\n"
+" b3FindPos(portal, pos);\n"
+" return;\n"
+" }\n"
+" b3ExpandPortal(portal, &v4);\n"
+" iterations++;\n"
+" }\n"
+"}\n"
+"B3_STATIC void b3FindPenetrTouch(b3MprSimplex_t *portal,float *depth, b3Float4 *dir, b3Float4 *pos)\n"
+"{\n"
+" // Touching contact on portal's v1 - so depth is zero and direction\n"
+" // is unimportant and pos can be guessed\n"
+" *depth = 0.f;\n"
+" b3Float4 zero = b3MakeFloat4(0,0,0,0);\n"
+" b3Float4* b3mpr_vec3_origin = &zero;\n"
+" b3MprVec3Copy(dir, b3mpr_vec3_origin);\n"
+" b3MprVec3Copy(pos, &b3MprSimplexPoint(portal, 1)->v1);\n"
+" b3MprVec3Add(pos, &b3MprSimplexPoint(portal, 1)->v2);\n"
+" b3MprVec3Scale(pos, 0.5);\n"
+"}\n"
+"B3_STATIC void b3FindPenetrSegment(b3MprSimplex_t *portal,\n"
+" float *depth, b3Float4 *dir, b3Float4 *pos)\n"
+"{\n"
+" \n"
+" // Origin lies on v0-v1 segment.\n"
+" // Depth is distance to v1, direction also and position must be\n"
+" // computed\n"
+" b3MprVec3Copy(pos, &b3MprSimplexPoint(portal, 1)->v1);\n"
+" b3MprVec3Add(pos, &b3MprSimplexPoint(portal, 1)->v2);\n"
+" b3MprVec3Scale(pos, 0.5f);\n"
+" \n"
+" b3MprVec3Copy(dir, &b3MprSimplexPoint(portal, 1)->v);\n"
+" *depth = B3_MPR_SQRT(b3MprVec3Len2(dir));\n"
+" b3MprVec3Normalize(dir);\n"
+"}\n"
+"inline int b3MprPenetration(int pairIndex, int bodyIndexA, int bodyIndexB,\n"
+" b3ConstArray(b3RigidBodyData_t) cpuBodyBuf,\n"
+" b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData, \n"
+" b3ConstArray(b3Collidable_t) cpuCollidables,\n"
+" b3ConstArray(b3Float4) cpuVertices,\n"
+" __global b3Float4* sepAxis,\n"
+" __global int* hasSepAxis,\n"
+" float *depthOut, b3Float4* dirOut, b3Float4* posOut)\n"
+"{\n"
+" \n"
+" b3MprSimplex_t portal;\n"
+" \n"
+"// if (!hasSepAxis[pairIndex])\n"
+" // return -1;\n"
+" \n"
+" hasSepAxis[pairIndex] = 0;\n"
+" int res;\n"
+" // Phase 1: Portal discovery\n"
+" res = b3DiscoverPortal(pairIndex,bodyIndexA,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices,sepAxis,hasSepAxis, &portal);\n"
+" \n"
+" \n"
+" //sepAxis[pairIndex] = *pdir;//or -dir?\n"
+" switch (res)\n"
+" {\n"
+" case 0:\n"
+" {\n"
+" // Phase 2: Portal refinement\n"
+" \n"
+" res = b3RefinePortal(pairIndex,bodyIndexA,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices, sepAxis,&portal);\n"
+" if (res < 0)\n"
+" return -1;\n"
+" // Phase 3. Penetration info\n"
+" b3FindPenetr(pairIndex,bodyIndexA,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices, sepAxis,&portal, depthOut, dirOut, posOut);\n"
+" hasSepAxis[pairIndex] = 1;\n"
+" sepAxis[pairIndex] = -*dirOut;\n"
+" break;\n"
+" }\n"
+" case 1:\n"
+" {\n"
+" // Touching contact on portal's v1.\n"
+" b3FindPenetrTouch(&portal, depthOut, dirOut, posOut);\n"
+" break;\n"
+" }\n"
+" case 2:\n"
+" {\n"
+" \n"
+" b3FindPenetrSegment( &portal, depthOut, dirOut, posOut);\n"
+" break;\n"
+" }\n"
+" default:\n"
+" {\n"
+" hasSepAxis[pairIndex]=0;\n"
+" //if (res < 0)\n"
+" //{\n"
+" // Origin isn't inside portal - no collision.\n"
+" return -1;\n"
+" //}\n"
+" }\n"
+" };\n"
+" \n"
+" return 0;\n"
+"};\n"
+"#endif //B3_MPR_PENETRATION_H\n"
+"#ifndef B3_CONTACT4DATA_H\n"
+"#define B3_CONTACT4DATA_H\n"
+"#ifndef B3_FLOAT4_H\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"#endif \n"
+"#endif //B3_FLOAT4_H\n"
+"typedef struct b3Contact4Data b3Contact4Data_t;\n"
+"struct b3Contact4Data\n"
+"{\n"
+" b3Float4 m_worldPosB[4];\n"
+"// b3Float4 m_localPosA[4];\n"
+"// b3Float4 m_localPosB[4];\n"
+" b3Float4 m_worldNormalOnB; // w: m_nPoints\n"
+" unsigned short m_restituitionCoeffCmp;\n"
+" unsigned short m_frictionCoeffCmp;\n"
+" int m_batchIdx;\n"
+" int m_bodyAPtrAndSignBit;//x:m_bodyAPtr, y:m_bodyBPtr\n"
+" int m_bodyBPtrAndSignBit;\n"
+" int m_childIndexA;\n"
+" int m_childIndexB;\n"
+" int m_unused1;\n"
+" int m_unused2;\n"
+"};\n"
+"inline int b3Contact4Data_getNumPoints(const struct b3Contact4Data* contact)\n"
+"{\n"
+" return (int)contact->m_worldNormalOnB.w;\n"
+"};\n"
+"inline void b3Contact4Data_setNumPoints(struct b3Contact4Data* contact, int numPoints)\n"
+"{\n"
+" contact->m_worldNormalOnB.w = (float)numPoints;\n"
+"};\n"
+"#endif //B3_CONTACT4DATA_H\n"
+"#define AppendInc(x, out) out = atomic_inc(x)\n"
+"#define GET_NPOINTS(x) (x).m_worldNormalOnB.w\n"
+"#ifdef cl_ext_atomic_counters_32\n"
+" #pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n"
+"#else\n"
+" #define counter32_t volatile __global int*\n"
+"#endif\n"
+"__kernel void mprPenetrationKernel( __global int4* pairs,\n"
+" __global const b3RigidBodyData_t* rigidBodies, \n"
+" __global const b3Collidable_t* collidables,\n"
+" __global const b3ConvexPolyhedronData_t* convexShapes, \n"
+" __global const float4* vertices,\n"
+" __global float4* separatingNormals,\n"
+" __global int* hasSeparatingAxis,\n"
+" __global struct b3Contact4Data* restrict globalContactsOut,\n"
+" counter32_t nGlobalContactsOut,\n"
+" int contactCapacity,\n"
+" int numPairs)\n"
+"{\n"
+" int i = get_global_id(0);\n"
+" int pairIndex = i;\n"
+" if (i<numPairs)\n"
+" {\n"
+" int bodyIndexA = pairs[i].x;\n"
+" int bodyIndexB = pairs[i].y;\n"
+" int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
+" int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
+" \n"
+" int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
+" int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
+" \n"
+" \n"
+" //once the broadphase avoids static-static pairs, we can remove this test\n"
+" if ((rigidBodies[bodyIndexA].m_invMass==0) &&(rigidBodies[bodyIndexB].m_invMass==0))\n"
+" {\n"
+" return;\n"
+" }\n"
+" \n"
+" if ((collidables[collidableIndexA].m_shapeType!=SHAPE_CONVEX_HULL) ||(collidables[collidableIndexB].m_shapeType!=SHAPE_CONVEX_HULL))\n"
+" {\n"
+" return;\n"
+" }\n"
+" float depthOut;\n"
+" b3Float4 dirOut;\n"
+" b3Float4 posOut;\n"
+" int res = b3MprPenetration(pairIndex, bodyIndexA, bodyIndexB,rigidBodies,convexShapes,collidables,vertices,separatingNormals,hasSeparatingAxis,&depthOut, &dirOut, &posOut);\n"
+" \n"
+" \n"
+" \n"
+" \n"
+" if (res==0)\n"
+" {\n"
+" //add a contact\n"
+" int dstIdx;\n"
+" AppendInc( nGlobalContactsOut, dstIdx );\n"
+" if (dstIdx<contactCapacity)\n"
+" {\n"
+" pairs[pairIndex].z = dstIdx;\n"
+" __global struct b3Contact4Data* c = globalContactsOut + dstIdx;\n"
+" c->m_worldNormalOnB = -dirOut;//normal;\n"
+" c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
+" c->m_batchIdx = pairIndex;\n"
+" int bodyA = pairs[pairIndex].x;\n"
+" int bodyB = pairs[pairIndex].y;\n"
+" c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0 ? -bodyA:bodyA;\n"
+" c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0 ? -bodyB:bodyB;\n"
+" c->m_childIndexA = -1;\n"
+" c->m_childIndexB = -1;\n"
+" //for (int i=0;i<nContacts;i++)\n"
+" posOut.w = -depthOut;\n"
+" c->m_worldPosB[0] = posOut;//localPoints[contactIdx[i]];\n"
+" GET_NPOINTS(*c) = 1;//nContacts;\n"
+" }\n"
+" }\n"
+" }\n"
+"}\n"
+"typedef float4 Quaternion;\n"
+"#define make_float4 (float4)\n"
+"__inline\n"
+"float dot3F4(float4 a, float4 b)\n"
+"{\n"
+" float4 a1 = make_float4(a.xyz,0.f);\n"
+" float4 b1 = make_float4(b.xyz,0.f);\n"
+" return dot(a1, b1);\n"
+"}\n"
+"__inline\n"
+"float4 cross3(float4 a, float4 b)\n"
+"{\n"
+" return cross(a,b);\n"
+"}\n"
+"__inline\n"
+"Quaternion qtMul(Quaternion a, Quaternion b)\n"
+"{\n"
+" Quaternion ans;\n"
+" ans = cross3( a, b );\n"
+" ans += a.w*b+b.w*a;\n"
+"// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
+" ans.w = a.w*b.w - dot3F4(a, b);\n"
+" return ans;\n"
+"}\n"
+"__inline\n"
+"Quaternion qtInvert(Quaternion q)\n"
+"{\n"
+" return (Quaternion)(-q.xyz, q.w);\n"
+"}\n"
+"__inline\n"
+"float4 qtRotate(Quaternion q, float4 vec)\n"
+"{\n"
+" Quaternion qInv = qtInvert( q );\n"
+" float4 vcpy = vec;\n"
+" vcpy.w = 0.f;\n"
+" float4 out = qtMul(qtMul(q,vcpy),qInv);\n"
+" return out;\n"
+"}\n"
+"__inline\n"
+"float4 transform(const float4* p, const float4* translation, const Quaternion* orientation)\n"
+"{\n"
+" return qtRotate( *orientation, *p ) + (*translation);\n"
+"}\n"
+"__inline\n"
+"float4 qtInvRotate(const Quaternion q, float4 vec)\n"
+"{\n"
+" return qtRotate( qtInvert( q ), vec );\n"
+"}\n"
+"inline void project(__global const b3ConvexPolyhedronData_t* hull, const float4 pos, const float4 orn, \n"
+"const float4* dir, __global const float4* vertices, float* min, float* max)\n"
+"{\n"
+" min[0] = FLT_MAX;\n"
+" max[0] = -FLT_MAX;\n"
+" int numVerts = hull->m_numVertices;\n"
+" const float4 localDir = qtInvRotate(orn,*dir);\n"
+" float offset = dot(pos,*dir);\n"
+" for(int i=0;i<numVerts;i++)\n"
+" {\n"
+" float dp = dot(vertices[hull->m_vertexOffset+i],localDir);\n"
+" if(dp < min[0]) \n"
+" min[0] = dp;\n"
+" if(dp > max[0]) \n"
+" max[0] = dp;\n"
+" }\n"
+" if(min[0]>max[0])\n"
+" {\n"
+" float tmp = min[0];\n"
+" min[0] = max[0];\n"
+" max[0] = tmp;\n"
+" }\n"
+" min[0] += offset;\n"
+" max[0] += offset;\n"
+"}\n"
+"bool findSeparatingAxisUnitSphere( __global const b3ConvexPolyhedronData_t* hullA, __global const b3ConvexPolyhedronData_t* hullB, \n"
+" const float4 posA1,\n"
+" const float4 ornA,\n"
+" const float4 posB1,\n"
+" const float4 ornB,\n"
+" const float4 DeltaC2,\n"
+" __global const float4* vertices,\n"
+" __global const float4* unitSphereDirections,\n"
+" int numUnitSphereDirections,\n"
+" float4* sep,\n"
+" float* dmin)\n"
+"{\n"
+" \n"
+" float4 posA = posA1;\n"
+" posA.w = 0.f;\n"
+" float4 posB = posB1;\n"
+" posB.w = 0.f;\n"
+" int curPlaneTests=0;\n"
+" int curEdgeEdge = 0;\n"
+" // Test unit sphere directions\n"
+" for (int i=0;i<numUnitSphereDirections;i++)\n"
+" {\n"
+" float4 crossje;\n"
+" crossje = unitSphereDirections[i]; \n"
+" if (dot3F4(DeltaC2,crossje)>0)\n"
+" crossje *= -1.f;\n"
+" {\n"
+" float dist;\n"
+" bool result = true;\n"
+" float Min0,Max0;\n"
+" float Min1,Max1;\n"
+" project(hullA,posA,ornA,&crossje,vertices, &Min0, &Max0);\n"
+" project(hullB,posB,ornB,&crossje,vertices, &Min1, &Max1);\n"
+" \n"
+" if(Max0<Min1 || Max1<Min0)\n"
+" return false;\n"
+" \n"
+" float d0 = Max0 - Min1;\n"
+" float d1 = Max1 - Min0;\n"
+" dist = d0<d1 ? d0:d1;\n"
+" result = true;\n"
+" \n"
+" if(dist<*dmin)\n"
+" {\n"
+" *dmin = dist;\n"
+" *sep = crossje;\n"
+" }\n"
+" }\n"
+" }\n"
+" \n"
+" if((dot3F4(-DeltaC2,*sep))>0.0f)\n"
+" {\n"
+" *sep = -(*sep);\n"
+" }\n"
+" return true;\n"
+"}\n"
+"__kernel void findSeparatingAxisUnitSphereKernel( __global const int4* pairs, \n"
+" __global const b3RigidBodyData_t* rigidBodies, \n"
+" __global const b3Collidable_t* collidables,\n"
+" __global const b3ConvexPolyhedronData_t* convexShapes, \n"
+" __global const float4* vertices,\n"
+" __global const float4* unitSphereDirections,\n"
+" __global float4* separatingNormals,\n"
+" __global int* hasSeparatingAxis,\n"
+" __global float* dmins,\n"
+" int numUnitSphereDirections,\n"
+" int numPairs\n"
+" )\n"
+"{\n"
+" int i = get_global_id(0);\n"
+" \n"
+" if (i<numPairs)\n"
+" {\n"
+" if (hasSeparatingAxis[i])\n"
+" {\n"
+" \n"
+" int bodyIndexA = pairs[i].x;\n"
+" int bodyIndexB = pairs[i].y;\n"
+" \n"
+" int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
+" int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
+" \n"
+" int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
+" int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
+" \n"
+" \n"
+" int numFacesA = convexShapes[shapeIndexA].m_numFaces;\n"
+" \n"
+" float dmin = dmins[i];\n"
+" \n"
+" float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
+" posA.w = 0.f;\n"
+" float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
+" posB.w = 0.f;\n"
+" float4 c0local = convexShapes[shapeIndexA].m_localCenter;\n"
+" float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
+" float4 c0 = transform(&c0local, &posA, &ornA);\n"
+" float4 c1local = convexShapes[shapeIndexB].m_localCenter;\n"
+" float4 ornB =rigidBodies[bodyIndexB].m_quat;\n"
+" float4 c1 = transform(&c1local,&posB,&ornB);\n"
+" const float4 DeltaC2 = c0 - c1;\n"
+" float4 sepNormal = separatingNormals[i];\n"
+" \n"
+" int numEdgeEdgeDirections = convexShapes[shapeIndexA].m_numUniqueEdges*convexShapes[shapeIndexB].m_numUniqueEdges;\n"
+" if (numEdgeEdgeDirections>numUnitSphereDirections)\n"
+" {\n"
+" bool sepEE = findSeparatingAxisUnitSphere( &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,\n"
+" posB,ornB,\n"
+" DeltaC2,\n"
+" vertices,unitSphereDirections,numUnitSphereDirections,&sepNormal,&dmin);\n"
+" if (!sepEE)\n"
+" {\n"
+" hasSeparatingAxis[i] = 0;\n"
+" } else\n"
+" {\n"
+" hasSeparatingAxis[i] = 1;\n"
+" separatingNormals[i] = sepNormal;\n"
+" }\n"
+" }\n"
+" } //if (hasSeparatingAxis[i])\n"
+" }//(i<numPairs)\n"
+"}\n"
+;
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/kernels/primitiveContacts.cl b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/kernels/primitiveContacts.cl
new file mode 100644
index 0000000000..9c9e920f13
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/kernels/primitiveContacts.cl
@@ -0,0 +1,1374 @@
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h"
+
+#define SHAPE_CONVEX_HULL 3
+#define SHAPE_PLANE 4
+#define SHAPE_CONCAVE_TRIMESH 5
+#define SHAPE_COMPOUND_OF_CONVEX_HULLS 6
+#define SHAPE_SPHERE 7
+
+
+#pragma OPENCL EXTENSION cl_amd_printf : enable
+#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable
+
+#ifdef cl_ext_atomic_counters_32
+#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable
+#else
+#define counter32_t volatile __global int*
+#endif
+
+#define GET_GROUP_IDX get_group_id(0)
+#define GET_LOCAL_IDX get_local_id(0)
+#define GET_GLOBAL_IDX get_global_id(0)
+#define GET_GROUP_SIZE get_local_size(0)
+#define GET_NUM_GROUPS get_num_groups(0)
+#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)
+#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)
+#define AtomInc(x) atom_inc(&(x))
+#define AtomInc1(x, out) out = atom_inc(&(x))
+#define AppendInc(x, out) out = atomic_inc(x)
+#define AtomAdd(x, value) atom_add(&(x), value)
+#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )
+#define AtomXhg(x, value) atom_xchg ( &(x), value )
+
+#define max2 max
+#define min2 min
+
+typedef unsigned int u32;
+
+
+
+
+typedef struct
+{
+ union
+ {
+ float4 m_min;
+ float m_minElems[4];
+ int m_minIndices[4];
+ };
+ union
+ {
+ float4 m_max;
+ float m_maxElems[4];
+ int m_maxIndices[4];
+ };
+} btAabbCL;
+
+///keep this in sync with btCollidable.h
+typedef struct
+{
+ int m_numChildShapes;
+ float m_radius;
+ int m_shapeType;
+ int m_shapeIndex;
+
+} btCollidableGpu;
+
+typedef struct
+{
+ float4 m_childPosition;
+ float4 m_childOrientation;
+ int m_shapeIndex;
+ int m_unused0;
+ int m_unused1;
+ int m_unused2;
+} btGpuChildShape;
+
+#define GET_NPOINTS(x) (x).m_worldNormalOnB.w
+
+typedef struct
+{
+ float4 m_pos;
+ float4 m_quat;
+ float4 m_linVel;
+ float4 m_angVel;
+
+ u32 m_collidableIdx;
+ float m_invMass;
+ float m_restituitionCoeff;
+ float m_frictionCoeff;
+} BodyData;
+
+
+typedef struct
+{
+ float4 m_localCenter;
+ float4 m_extents;
+ float4 mC;
+ float4 mE;
+
+ float m_radius;
+ int m_faceOffset;
+ int m_numFaces;
+ int m_numVertices;
+
+ int m_vertexOffset;
+ int m_uniqueEdgesOffset;
+ int m_numUniqueEdges;
+ int m_unused;
+
+} ConvexPolyhedronCL;
+
+typedef struct
+{
+ float4 m_plane;
+ int m_indexOffset;
+ int m_numIndices;
+} btGpuFace;
+
+#define SELECT_UINT4( b, a, condition ) select( b,a,condition )
+
+#define make_float4 (float4)
+#define make_float2 (float2)
+#define make_uint4 (uint4)
+#define make_int4 (int4)
+#define make_uint2 (uint2)
+#define make_int2 (int2)
+
+
+__inline
+float fastDiv(float numerator, float denominator)
+{
+ return native_divide(numerator, denominator);
+// return numerator/denominator;
+}
+
+__inline
+float4 fastDiv4(float4 numerator, float4 denominator)
+{
+ return native_divide(numerator, denominator);
+}
+
+
+__inline
+float4 cross3(float4 a, float4 b)
+{
+ return cross(a,b);
+}
+
+//#define dot3F4 dot
+
+__inline
+float dot3F4(float4 a, float4 b)
+{
+ float4 a1 = make_float4(a.xyz,0.f);
+ float4 b1 = make_float4(b.xyz,0.f);
+ return dot(a1, b1);
+}
+
+__inline
+float4 fastNormalize4(float4 v)
+{
+ return fast_normalize(v);
+}
+
+
+///////////////////////////////////////
+// Quaternion
+///////////////////////////////////////
+
+typedef float4 Quaternion;
+
+__inline
+Quaternion qtMul(Quaternion a, Quaternion b);
+
+__inline
+Quaternion qtNormalize(Quaternion in);
+
+__inline
+float4 qtRotate(Quaternion q, float4 vec);
+
+__inline
+Quaternion qtInvert(Quaternion q);
+
+
+
+
+__inline
+Quaternion qtMul(Quaternion a, Quaternion b)
+{
+ Quaternion ans;
+ ans = cross3( a, b );
+ ans += a.w*b+b.w*a;
+// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);
+ ans.w = a.w*b.w - dot3F4(a, b);
+ return ans;
+}
+
+__inline
+Quaternion qtNormalize(Quaternion in)
+{
+ return fastNormalize4(in);
+// in /= length( in );
+// return in;
+}
+__inline
+float4 qtRotate(Quaternion q, float4 vec)
+{
+ Quaternion qInv = qtInvert( q );
+ float4 vcpy = vec;
+ vcpy.w = 0.f;
+ float4 out = qtMul(qtMul(q,vcpy),qInv);
+ return out;
+}
+
+__inline
+Quaternion qtInvert(Quaternion q)
+{
+ return (Quaternion)(-q.xyz, q.w);
+}
+
+__inline
+float4 qtInvRotate(const Quaternion q, float4 vec)
+{
+ return qtRotate( qtInvert( q ), vec );
+}
+
+__inline
+float4 transform(const float4* p, const float4* translation, const Quaternion* orientation)
+{
+ return qtRotate( *orientation, *p ) + (*translation);
+}
+
+void trInverse(float4 translationIn, Quaternion orientationIn,
+ float4* translationOut, Quaternion* orientationOut)
+{
+ *orientationOut = qtInvert(orientationIn);
+ *translationOut = qtRotate(*orientationOut, -translationIn);
+}
+
+void trMul(float4 translationA, Quaternion orientationA,
+ float4 translationB, Quaternion orientationB,
+ float4* translationOut, Quaternion* orientationOut)
+{
+ *orientationOut = qtMul(orientationA,orientationB);
+ *translationOut = transform(&translationB,&translationA,&orientationA);
+}
+
+
+
+__inline
+float4 normalize3(const float4 a)
+{
+ float4 n = make_float4(a.x, a.y, a.z, 0.f);
+ return fastNormalize4( n );
+}
+
+
+__inline float4 lerp3(const float4 a,const float4 b, float t)
+{
+ return make_float4( a.x + (b.x - a.x) * t,
+ a.y + (b.y - a.y) * t,
+ a.z + (b.z - a.z) * t,
+ 0.f);
+}
+
+
+float signedDistanceFromPointToPlane(float4 point, float4 planeEqn, float4* closestPointOnFace)
+{
+ float4 n = (float4)(planeEqn.x, planeEqn.y, planeEqn.z, 0);
+ float dist = dot3F4(n, point) + planeEqn.w;
+ *closestPointOnFace = point - dist * n;
+ return dist;
+}
+
+
+
+inline bool IsPointInPolygon(float4 p,
+ const btGpuFace* face,
+ __global const float4* baseVertex,
+ __global const int* convexIndices,
+ float4* out)
+{
+ float4 a;
+ float4 b;
+ float4 ab;
+ float4 ap;
+ float4 v;
+
+ float4 plane = make_float4(face->m_plane.x,face->m_plane.y,face->m_plane.z,0.f);
+
+ if (face->m_numIndices<2)
+ return false;
+
+
+ float4 v0 = baseVertex[convexIndices[face->m_indexOffset + face->m_numIndices-1]];
+
+ b = v0;
+
+ for(unsigned i=0; i != face->m_numIndices; ++i)
+ {
+ a = b;
+ float4 vi = baseVertex[convexIndices[face->m_indexOffset + i]];
+ b = vi;
+ ab = b-a;
+ ap = p-a;
+ v = cross3(ab,plane);
+
+ if (dot(ap, v) > 0.f)
+ {
+ float ab_m2 = dot(ab, ab);
+ float rt = ab_m2 != 0.f ? dot(ab, ap) / ab_m2 : 0.f;
+ if (rt <= 0.f)
+ {
+ *out = a;
+ }
+ else if (rt >= 1.f)
+ {
+ *out = b;
+ }
+ else
+ {
+ float s = 1.f - rt;
+ out[0].x = s * a.x + rt * b.x;
+ out[0].y = s * a.y + rt * b.y;
+ out[0].z = s * a.z + rt * b.z;
+ }
+ return false;
+ }
+ }
+ return true;
+}
+
+
+
+
+void computeContactSphereConvex(int pairIndex,
+ int bodyIndexA, int bodyIndexB,
+ int collidableIndexA, int collidableIndexB,
+ __global const BodyData* rigidBodies,
+ __global const btCollidableGpu* collidables,
+ __global const ConvexPolyhedronCL* convexShapes,
+ __global const float4* convexVertices,
+ __global const int* convexIndices,
+ __global const btGpuFace* faces,
+ __global struct b3Contact4Data* restrict globalContactsOut,
+ counter32_t nGlobalContactsOut,
+ int maxContactCapacity,
+ float4 spherePos2,
+ float radius,
+ float4 pos,
+ float4 quat
+ )
+{
+
+ float4 invPos;
+ float4 invOrn;
+
+ trInverse(pos,quat, &invPos,&invOrn);
+
+ float4 spherePos = transform(&spherePos2,&invPos,&invOrn);
+
+ int shapeIndex = collidables[collidableIndexB].m_shapeIndex;
+ int numFaces = convexShapes[shapeIndex].m_numFaces;
+ float4 closestPnt = (float4)(0, 0, 0, 0);
+ float4 hitNormalWorld = (float4)(0, 0, 0, 0);
+ float minDist = -1000000.f;
+ bool bCollide = true;
+
+ for ( int f = 0; f < numFaces; f++ )
+ {
+ btGpuFace face = faces[convexShapes[shapeIndex].m_faceOffset+f];
+
+ // set up a plane equation
+ float4 planeEqn;
+ float4 n1 = face.m_plane;
+ n1.w = 0.f;
+ planeEqn = n1;
+ planeEqn.w = face.m_plane.w;
+
+
+ // compute a signed distance from the vertex in cloth to the face of rigidbody.
+ float4 pntReturn;
+ float dist = signedDistanceFromPointToPlane(spherePos, planeEqn, &pntReturn);
+
+ // If the distance is positive, the plane is a separating plane.
+ if ( dist > radius )
+ {
+ bCollide = false;
+ break;
+ }
+
+
+ if (dist>0)
+ {
+ //might hit an edge or vertex
+ float4 out;
+ float4 zeroPos = make_float4(0,0,0,0);
+
+ bool isInPoly = IsPointInPolygon(spherePos,
+ &face,
+ &convexVertices[convexShapes[shapeIndex].m_vertexOffset],
+ convexIndices,
+ &out);
+ if (isInPoly)
+ {
+ if (dist>minDist)
+ {
+ minDist = dist;
+ closestPnt = pntReturn;
+ hitNormalWorld = planeEqn;
+
+ }
+ } else
+ {
+ float4 tmp = spherePos-out;
+ float l2 = dot(tmp,tmp);
+ if (l2<radius*radius)
+ {
+ dist = sqrt(l2);
+ if (dist>minDist)
+ {
+ minDist = dist;
+ closestPnt = out;
+ hitNormalWorld = tmp/dist;
+
+ }
+
+ } else
+ {
+ bCollide = false;
+ break;
+ }
+ }
+ } else
+ {
+ if ( dist > minDist )
+ {
+ minDist = dist;
+ closestPnt = pntReturn;
+ hitNormalWorld.xyz = planeEqn.xyz;
+ }
+ }
+
+ }
+
+
+
+ if (bCollide && minDist > -10000)
+ {
+ float4 normalOnSurfaceB1 = qtRotate(quat,-hitNormalWorld);
+ float4 pOnB1 = transform(&closestPnt,&pos,&quat);
+
+ float actualDepth = minDist-radius;
+ if (actualDepth<=0.f)
+ {
+
+
+ pOnB1.w = actualDepth;
+
+ int dstIdx;
+ AppendInc( nGlobalContactsOut, dstIdx );
+
+
+ if (1)//dstIdx < maxContactCapacity)
+ {
+ __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];
+ c->m_worldNormalOnB = -normalOnSurfaceB1;
+ c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);
+ c->m_batchIdx = pairIndex;
+ c->m_bodyAPtrAndSignBit = rigidBodies[bodyIndexA].m_invMass==0?-bodyIndexA:bodyIndexA;
+ c->m_bodyBPtrAndSignBit = rigidBodies[bodyIndexB].m_invMass==0?-bodyIndexB:bodyIndexB;
+ c->m_worldPosB[0] = pOnB1;
+ c->m_childIndexA = -1;
+ c->m_childIndexB = -1;
+
+ GET_NPOINTS(*c) = 1;
+ }
+
+ }
+ }//if (hasCollision)
+
+}
+
+
+
+int extractManifoldSequential(const float4* p, int nPoints, float4 nearNormal, int4* contactIdx)
+{
+ if( nPoints == 0 )
+ return 0;
+
+ if (nPoints <=4)
+ return nPoints;
+
+
+ if (nPoints >64)
+ nPoints = 64;
+
+ float4 center = make_float4(0.f);
+ {
+
+ for (int i=0;i<nPoints;i++)
+ center += p[i];
+ center /= (float)nPoints;
+ }
+
+
+
+ // sample 4 directions
+
+ float4 aVector = p[0] - center;
+ float4 u = cross3( nearNormal, aVector );
+ float4 v = cross3( nearNormal, u );
+ u = normalize3( u );
+ v = normalize3( v );
+
+
+ //keep point with deepest penetration
+ float minW= FLT_MAX;
+
+ int minIndex=-1;
+
+ float4 maxDots;
+ maxDots.x = FLT_MIN;
+ maxDots.y = FLT_MIN;
+ maxDots.z = FLT_MIN;
+ maxDots.w = FLT_MIN;
+
+ // idx, distance
+ for(int ie = 0; ie<nPoints; ie++ )
+ {
+ if (p[ie].w<minW)
+ {
+ minW = p[ie].w;
+ minIndex=ie;
+ }
+ float f;
+ float4 r = p[ie]-center;
+ f = dot3F4( u, r );
+ if (f<maxDots.x)
+ {
+ maxDots.x = f;
+ contactIdx[0].x = ie;
+ }
+
+ f = dot3F4( -u, r );
+ if (f<maxDots.y)
+ {
+ maxDots.y = f;
+ contactIdx[0].y = ie;
+ }
+
+
+ f = dot3F4( v, r );
+ if (f<maxDots.z)
+ {
+ maxDots.z = f;
+ contactIdx[0].z = ie;
+ }
+
+ f = dot3F4( -v, r );
+ if (f<maxDots.w)
+ {
+ maxDots.w = f;
+ contactIdx[0].w = ie;
+ }
+
+ }
+
+ if (contactIdx[0].x != minIndex && contactIdx[0].y != minIndex && contactIdx[0].z != minIndex && contactIdx[0].w != minIndex)
+ {
+ //replace the first contact with minimum (todo: replace contact with least penetration)
+ contactIdx[0].x = minIndex;
+ }
+
+ return 4;
+
+}
+
+#define MAX_PLANE_CONVEX_POINTS 64
+
+int computeContactPlaneConvex(int pairIndex,
+ int bodyIndexA, int bodyIndexB,
+ int collidableIndexA, int collidableIndexB,
+ __global const BodyData* rigidBodies,
+ __global const btCollidableGpu*collidables,
+ __global const ConvexPolyhedronCL* convexShapes,
+ __global const float4* convexVertices,
+ __global const int* convexIndices,
+ __global const btGpuFace* faces,
+ __global struct b3Contact4Data* restrict globalContactsOut,
+ counter32_t nGlobalContactsOut,
+ int maxContactCapacity,
+ float4 posB,
+ Quaternion ornB
+ )
+{
+ int resultIndex=-1;
+
+ int shapeIndex = collidables[collidableIndexB].m_shapeIndex;
+ __global const ConvexPolyhedronCL* hullB = &convexShapes[shapeIndex];
+
+ float4 posA;
+ posA = rigidBodies[bodyIndexA].m_pos;
+ Quaternion ornA;
+ ornA = rigidBodies[bodyIndexA].m_quat;
+
+ int numContactsOut = 0;
+ int numWorldVertsB1= 0;
+
+ float4 planeEq;
+ planeEq = faces[collidables[collidableIndexA].m_shapeIndex].m_plane;
+ float4 planeNormal = make_float4(planeEq.x,planeEq.y,planeEq.z,0.f);
+ float4 planeNormalWorld;
+ planeNormalWorld = qtRotate(ornA,planeNormal);
+ float planeConstant = planeEq.w;
+
+ float4 invPosA;Quaternion invOrnA;
+ float4 convexInPlaneTransPos1; Quaternion convexInPlaneTransOrn1;
+ {
+
+ trInverse(posA,ornA,&invPosA,&invOrnA);
+ trMul(invPosA,invOrnA,posB,ornB,&convexInPlaneTransPos1,&convexInPlaneTransOrn1);
+ }
+ float4 invPosB;Quaternion invOrnB;
+ float4 planeInConvexPos1; Quaternion planeInConvexOrn1;
+ {
+
+ trInverse(posB,ornB,&invPosB,&invOrnB);
+ trMul(invPosB,invOrnB,posA,ornA,&planeInConvexPos1,&planeInConvexOrn1);
+ }
+
+
+ float4 planeNormalInConvex = qtRotate(planeInConvexOrn1,-planeNormal);
+ float maxDot = -1e30;
+ int hitVertex=-1;
+ float4 hitVtx;
+
+
+
+ float4 contactPoints[MAX_PLANE_CONVEX_POINTS];
+ int numPoints = 0;
+
+ int4 contactIdx;
+ contactIdx=make_int4(0,1,2,3);
+
+
+ for (int i=0;i<hullB->m_numVertices;i++)
+ {
+ float4 vtx = convexVertices[hullB->m_vertexOffset+i];
+ float curDot = dot(vtx,planeNormalInConvex);
+
+
+ if (curDot>maxDot)
+ {
+ hitVertex=i;
+ maxDot=curDot;
+ hitVtx = vtx;
+ //make sure the deepest points is always included
+ if (numPoints==MAX_PLANE_CONVEX_POINTS)
+ numPoints--;
+ }
+
+ if (numPoints<MAX_PLANE_CONVEX_POINTS)
+ {
+ float4 vtxWorld = transform(&vtx, &posB, &ornB);
+ float4 vtxInPlane = transform(&vtxWorld, &invPosA, &invOrnA);//oplaneTransform.inverse()*vtxWorld;
+ float dist = dot(planeNormal,vtxInPlane)-planeConstant;
+ if (dist<0.f)
+ {
+ vtxWorld.w = dist;
+ contactPoints[numPoints] = vtxWorld;
+ numPoints++;
+ }
+ }
+
+ }
+
+ int numReducedPoints = numPoints;
+ if (numPoints>4)
+ {
+ numReducedPoints = extractManifoldSequential( contactPoints, numPoints, planeNormalInConvex, &contactIdx);
+ }
+
+ if (numReducedPoints>0)
+ {
+ int dstIdx;
+ AppendInc( nGlobalContactsOut, dstIdx );
+
+ if (dstIdx < maxContactCapacity)
+ {
+ resultIndex = dstIdx;
+ __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];
+ c->m_worldNormalOnB = -planeNormalWorld;
+ //c->setFrictionCoeff(0.7);
+ //c->setRestituitionCoeff(0.f);
+ c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);
+ c->m_batchIdx = pairIndex;
+ c->m_bodyAPtrAndSignBit = rigidBodies[bodyIndexA].m_invMass==0?-bodyIndexA:bodyIndexA;
+ c->m_bodyBPtrAndSignBit = rigidBodies[bodyIndexB].m_invMass==0?-bodyIndexB:bodyIndexB;
+ c->m_childIndexA = -1;
+ c->m_childIndexB = -1;
+
+ switch (numReducedPoints)
+ {
+ case 4:
+ c->m_worldPosB[3] = contactPoints[contactIdx.w];
+ case 3:
+ c->m_worldPosB[2] = contactPoints[contactIdx.z];
+ case 2:
+ c->m_worldPosB[1] = contactPoints[contactIdx.y];
+ case 1:
+ c->m_worldPosB[0] = contactPoints[contactIdx.x];
+ default:
+ {
+ }
+ };
+
+ GET_NPOINTS(*c) = numReducedPoints;
+ }//if (dstIdx < numPairs)
+ }
+
+ return resultIndex;
+}
+
+
+void computeContactPlaneSphere(int pairIndex,
+ int bodyIndexA, int bodyIndexB,
+ int collidableIndexA, int collidableIndexB,
+ __global const BodyData* rigidBodies,
+ __global const btCollidableGpu* collidables,
+ __global const btGpuFace* faces,
+ __global struct b3Contact4Data* restrict globalContactsOut,
+ counter32_t nGlobalContactsOut,
+ int maxContactCapacity)
+{
+ float4 planeEq = faces[collidables[collidableIndexA].m_shapeIndex].m_plane;
+ float radius = collidables[collidableIndexB].m_radius;
+ float4 posA1 = rigidBodies[bodyIndexA].m_pos;
+ float4 ornA1 = rigidBodies[bodyIndexA].m_quat;
+ float4 posB1 = rigidBodies[bodyIndexB].m_pos;
+ float4 ornB1 = rigidBodies[bodyIndexB].m_quat;
+
+ bool hasCollision = false;
+ float4 planeNormal1 = make_float4(planeEq.x,planeEq.y,planeEq.z,0.f);
+ float planeConstant = planeEq.w;
+ float4 convexInPlaneTransPos1; Quaternion convexInPlaneTransOrn1;
+ {
+ float4 invPosA;Quaternion invOrnA;
+ trInverse(posA1,ornA1,&invPosA,&invOrnA);
+ trMul(invPosA,invOrnA,posB1,ornB1,&convexInPlaneTransPos1,&convexInPlaneTransOrn1);
+ }
+ float4 planeInConvexPos1; Quaternion planeInConvexOrn1;
+ {
+ float4 invPosB;Quaternion invOrnB;
+ trInverse(posB1,ornB1,&invPosB,&invOrnB);
+ trMul(invPosB,invOrnB,posA1,ornA1,&planeInConvexPos1,&planeInConvexOrn1);
+ }
+ float4 vtx1 = qtRotate(planeInConvexOrn1,-planeNormal1)*radius;
+ float4 vtxInPlane1 = transform(&vtx1,&convexInPlaneTransPos1,&convexInPlaneTransOrn1);
+ float distance = dot3F4(planeNormal1,vtxInPlane1) - planeConstant;
+ hasCollision = distance < 0.f;//m_manifoldPtr->getContactBreakingThreshold();
+ if (hasCollision)
+ {
+ float4 vtxInPlaneProjected1 = vtxInPlane1 - distance*planeNormal1;
+ float4 vtxInPlaneWorld1 = transform(&vtxInPlaneProjected1,&posA1,&ornA1);
+ float4 normalOnSurfaceB1 = qtRotate(ornA1,planeNormal1);
+ float4 pOnB1 = vtxInPlaneWorld1+normalOnSurfaceB1*distance;
+ pOnB1.w = distance;
+
+ int dstIdx;
+ AppendInc( nGlobalContactsOut, dstIdx );
+
+ if (dstIdx < maxContactCapacity)
+ {
+ __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];
+ c->m_worldNormalOnB = -normalOnSurfaceB1;
+ c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);
+ c->m_batchIdx = pairIndex;
+ c->m_bodyAPtrAndSignBit = rigidBodies[bodyIndexA].m_invMass==0?-bodyIndexA:bodyIndexA;
+ c->m_bodyBPtrAndSignBit = rigidBodies[bodyIndexB].m_invMass==0?-bodyIndexB:bodyIndexB;
+ c->m_worldPosB[0] = pOnB1;
+ c->m_childIndexA = -1;
+ c->m_childIndexB = -1;
+ GET_NPOINTS(*c) = 1;
+ }//if (dstIdx < numPairs)
+ }//if (hasCollision)
+}
+
+
+__kernel void primitiveContactsKernel( __global int4* pairs,
+ __global const BodyData* rigidBodies,
+ __global const btCollidableGpu* collidables,
+ __global const ConvexPolyhedronCL* convexShapes,
+ __global const float4* vertices,
+ __global const float4* uniqueEdges,
+ __global const btGpuFace* faces,
+ __global const int* indices,
+ __global struct b3Contact4Data* restrict globalContactsOut,
+ counter32_t nGlobalContactsOut,
+ int numPairs, int maxContactCapacity)
+{
+
+ int i = get_global_id(0);
+ int pairIndex = i;
+
+ float4 worldVertsB1[64];
+ float4 worldVertsB2[64];
+ int capacityWorldVerts = 64;
+
+ float4 localContactsOut[64];
+ int localContactCapacity=64;
+
+ float minDist = -1e30f;
+ float maxDist = 0.02f;
+
+ if (i<numPairs)
+ {
+
+ int bodyIndexA = pairs[i].x;
+ int bodyIndexB = pairs[i].y;
+
+ int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
+ int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
+
+ if (collidables[collidableIndexA].m_shapeType == SHAPE_PLANE &&
+ collidables[collidableIndexB].m_shapeType == SHAPE_CONVEX_HULL)
+ {
+
+ float4 posB;
+ posB = rigidBodies[bodyIndexB].m_pos;
+ Quaternion ornB;
+ ornB = rigidBodies[bodyIndexB].m_quat;
+ int contactIndex = computeContactPlaneConvex(pairIndex, bodyIndexA, bodyIndexB, collidableIndexA, collidableIndexB,
+ rigidBodies,collidables,convexShapes,vertices,indices,
+ faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity, posB,ornB);
+ if (contactIndex>=0)
+ pairs[pairIndex].z = contactIndex;
+
+ return;
+ }
+
+
+ if (collidables[collidableIndexA].m_shapeType == SHAPE_CONVEX_HULL &&
+ collidables[collidableIndexB].m_shapeType == SHAPE_PLANE)
+ {
+
+ float4 posA;
+ posA = rigidBodies[bodyIndexA].m_pos;
+ Quaternion ornA;
+ ornA = rigidBodies[bodyIndexA].m_quat;
+
+
+ int contactIndex = computeContactPlaneConvex( pairIndex, bodyIndexB,bodyIndexA, collidableIndexB,collidableIndexA,
+ rigidBodies,collidables,convexShapes,vertices,indices,
+ faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity,posA,ornA);
+
+ if (contactIndex>=0)
+ pairs[pairIndex].z = contactIndex;
+
+ return;
+ }
+
+ if (collidables[collidableIndexA].m_shapeType == SHAPE_PLANE &&
+ collidables[collidableIndexB].m_shapeType == SHAPE_SPHERE)
+ {
+ computeContactPlaneSphere(pairIndex, bodyIndexA, bodyIndexB, collidableIndexA, collidableIndexB,
+ rigidBodies,collidables,faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity);
+ return;
+ }
+
+
+ if (collidables[collidableIndexA].m_shapeType == SHAPE_SPHERE &&
+ collidables[collidableIndexB].m_shapeType == SHAPE_PLANE)
+ {
+
+
+ computeContactPlaneSphere( pairIndex, bodyIndexB,bodyIndexA, collidableIndexB,collidableIndexA,
+ rigidBodies,collidables,
+ faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity);
+
+ return;
+ }
+
+
+
+
+ if (collidables[collidableIndexA].m_shapeType == SHAPE_SPHERE &&
+ collidables[collidableIndexB].m_shapeType == SHAPE_CONVEX_HULL)
+ {
+
+ float4 spherePos = rigidBodies[bodyIndexA].m_pos;
+ float sphereRadius = collidables[collidableIndexA].m_radius;
+ float4 convexPos = rigidBodies[bodyIndexB].m_pos;
+ float4 convexOrn = rigidBodies[bodyIndexB].m_quat;
+
+ computeContactSphereConvex(pairIndex, bodyIndexA, bodyIndexB, collidableIndexA, collidableIndexB,
+ rigidBodies,collidables,convexShapes,vertices,indices,faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity,
+ spherePos,sphereRadius,convexPos,convexOrn);
+
+ return;
+ }
+
+ if (collidables[collidableIndexA].m_shapeType == SHAPE_CONVEX_HULL &&
+ collidables[collidableIndexB].m_shapeType == SHAPE_SPHERE)
+ {
+
+ float4 spherePos = rigidBodies[bodyIndexB].m_pos;
+ float sphereRadius = collidables[collidableIndexB].m_radius;
+ float4 convexPos = rigidBodies[bodyIndexA].m_pos;
+ float4 convexOrn = rigidBodies[bodyIndexA].m_quat;
+
+ computeContactSphereConvex(pairIndex, bodyIndexB, bodyIndexA, collidableIndexB, collidableIndexA,
+ rigidBodies,collidables,convexShapes,vertices,indices,faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity,
+ spherePos,sphereRadius,convexPos,convexOrn);
+ return;
+ }
+
+
+
+
+
+
+ if (collidables[collidableIndexA].m_shapeType == SHAPE_SPHERE &&
+ collidables[collidableIndexB].m_shapeType == SHAPE_SPHERE)
+ {
+ //sphere-sphere
+ float radiusA = collidables[collidableIndexA].m_radius;
+ float radiusB = collidables[collidableIndexB].m_radius;
+ float4 posA = rigidBodies[bodyIndexA].m_pos;
+ float4 posB = rigidBodies[bodyIndexB].m_pos;
+
+ float4 diff = posA-posB;
+ float len = length(diff);
+
+ ///iff distance positive, don't generate a new contact
+ if ( len <= (radiusA+radiusB))
+ {
+ ///distance (negative means penetration)
+ float dist = len - (radiusA+radiusB);
+ float4 normalOnSurfaceB = make_float4(1.f,0.f,0.f,0.f);
+ if (len > 0.00001)
+ {
+ normalOnSurfaceB = diff / len;
+ }
+ float4 contactPosB = posB + normalOnSurfaceB*radiusB;
+ contactPosB.w = dist;
+
+ int dstIdx;
+ AppendInc( nGlobalContactsOut, dstIdx );
+
+ if (dstIdx < maxContactCapacity)
+ {
+ __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];
+ c->m_worldNormalOnB = normalOnSurfaceB;
+ c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);
+ c->m_batchIdx = pairIndex;
+ int bodyA = pairs[pairIndex].x;
+ int bodyB = pairs[pairIndex].y;
+ c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0?-bodyA:bodyA;
+ c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0?-bodyB:bodyB;
+ c->m_worldPosB[0] = contactPosB;
+ c->m_childIndexA = -1;
+ c->m_childIndexB = -1;
+ GET_NPOINTS(*c) = 1;
+ }//if (dstIdx < numPairs)
+ }//if ( len <= (radiusA+radiusB))
+
+ return;
+ }//SHAPE_SPHERE SHAPE_SPHERE
+
+ }// if (i<numPairs)
+
+}
+
+
+// work-in-progress
+__kernel void processCompoundPairsPrimitivesKernel( __global const int4* gpuCompoundPairs,
+ __global const BodyData* rigidBodies,
+ __global const btCollidableGpu* collidables,
+ __global const ConvexPolyhedronCL* convexShapes,
+ __global const float4* vertices,
+ __global const float4* uniqueEdges,
+ __global const btGpuFace* faces,
+ __global const int* indices,
+ __global btAabbCL* aabbs,
+ __global const btGpuChildShape* gpuChildShapes,
+ __global struct b3Contact4Data* restrict globalContactsOut,
+ counter32_t nGlobalContactsOut,
+ int numCompoundPairs, int maxContactCapacity
+ )
+{
+
+ int i = get_global_id(0);
+ if (i<numCompoundPairs)
+ {
+ int bodyIndexA = gpuCompoundPairs[i].x;
+ int bodyIndexB = gpuCompoundPairs[i].y;
+
+ int childShapeIndexA = gpuCompoundPairs[i].z;
+ int childShapeIndexB = gpuCompoundPairs[i].w;
+
+ int collidableIndexA = -1;
+ int collidableIndexB = -1;
+
+ float4 ornA = rigidBodies[bodyIndexA].m_quat;
+ float4 posA = rigidBodies[bodyIndexA].m_pos;
+
+ float4 ornB = rigidBodies[bodyIndexB].m_quat;
+ float4 posB = rigidBodies[bodyIndexB].m_pos;
+
+ if (childShapeIndexA >= 0)
+ {
+ collidableIndexA = gpuChildShapes[childShapeIndexA].m_shapeIndex;
+ float4 childPosA = gpuChildShapes[childShapeIndexA].m_childPosition;
+ float4 childOrnA = gpuChildShapes[childShapeIndexA].m_childOrientation;
+ float4 newPosA = qtRotate(ornA,childPosA)+posA;
+ float4 newOrnA = qtMul(ornA,childOrnA);
+ posA = newPosA;
+ ornA = newOrnA;
+ } else
+ {
+ collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
+ }
+
+ if (childShapeIndexB>=0)
+ {
+ collidableIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;
+ float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;
+ float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;
+ float4 newPosB = transform(&childPosB,&posB,&ornB);
+ float4 newOrnB = qtMul(ornB,childOrnB);
+ posB = newPosB;
+ ornB = newOrnB;
+ } else
+ {
+ collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
+ }
+
+ int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
+ int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
+
+ int shapeTypeA = collidables[collidableIndexA].m_shapeType;
+ int shapeTypeB = collidables[collidableIndexB].m_shapeType;
+
+ int pairIndex = i;
+ if ((shapeTypeA == SHAPE_PLANE) && (shapeTypeB==SHAPE_CONVEX_HULL))
+ {
+
+ computeContactPlaneConvex( pairIndex, bodyIndexA,bodyIndexB, collidableIndexA,collidableIndexB,
+ rigidBodies,collidables,convexShapes,vertices,indices,
+ faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity,posB,ornB);
+ return;
+ }
+
+ if ((shapeTypeA == SHAPE_CONVEX_HULL) && (shapeTypeB==SHAPE_PLANE))
+ {
+
+ computeContactPlaneConvex( pairIndex, bodyIndexB,bodyIndexA, collidableIndexB,collidableIndexA,
+ rigidBodies,collidables,convexShapes,vertices,indices,
+ faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity,posA,ornA);
+ return;
+ }
+
+ if ((shapeTypeA == SHAPE_CONVEX_HULL) && (shapeTypeB == SHAPE_SPHERE))
+ {
+ float4 spherePos = rigidBodies[bodyIndexB].m_pos;
+ float sphereRadius = collidables[collidableIndexB].m_radius;
+ float4 convexPos = posA;
+ float4 convexOrn = ornA;
+
+ computeContactSphereConvex(pairIndex, bodyIndexB, bodyIndexA , collidableIndexB,collidableIndexA,
+ rigidBodies,collidables,convexShapes,vertices,indices,faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity,
+ spherePos,sphereRadius,convexPos,convexOrn);
+
+ return;
+ }
+
+ if ((shapeTypeA == SHAPE_SPHERE) && (shapeTypeB == SHAPE_CONVEX_HULL))
+ {
+
+ float4 spherePos = rigidBodies[bodyIndexA].m_pos;
+ float sphereRadius = collidables[collidableIndexA].m_radius;
+ float4 convexPos = posB;
+ float4 convexOrn = ornB;
+
+
+ computeContactSphereConvex(pairIndex, bodyIndexA, bodyIndexB, collidableIndexA, collidableIndexB,
+ rigidBodies,collidables,convexShapes,vertices,indices,faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity,
+ spherePos,sphereRadius,convexPos,convexOrn);
+
+ return;
+ }
+ }// if (i<numCompoundPairs)
+}
+
+
+bool pointInTriangle(const float4* vertices, const float4* normal, float4 *p )
+{
+
+ const float4* p1 = &vertices[0];
+ const float4* p2 = &vertices[1];
+ const float4* p3 = &vertices[2];
+
+ float4 edge1; edge1 = (*p2 - *p1);
+ float4 edge2; edge2 = ( *p3 - *p2 );
+ float4 edge3; edge3 = ( *p1 - *p3 );
+
+
+ float4 p1_to_p; p1_to_p = ( *p - *p1 );
+ float4 p2_to_p; p2_to_p = ( *p - *p2 );
+ float4 p3_to_p; p3_to_p = ( *p - *p3 );
+
+ float4 edge1_normal; edge1_normal = ( cross(edge1,*normal));
+ float4 edge2_normal; edge2_normal = ( cross(edge2,*normal));
+ float4 edge3_normal; edge3_normal = ( cross(edge3,*normal));
+
+
+
+ float r1, r2, r3;
+ r1 = dot(edge1_normal,p1_to_p );
+ r2 = dot(edge2_normal,p2_to_p );
+ r3 = dot(edge3_normal,p3_to_p );
+
+ if ( r1 > 0 && r2 > 0 && r3 > 0 )
+ return true;
+ if ( r1 <= 0 && r2 <= 0 && r3 <= 0 )
+ return true;
+ return false;
+
+}
+
+
+float segmentSqrDistance(float4 from, float4 to,float4 p, float4* nearest)
+{
+ float4 diff = p - from;
+ float4 v = to - from;
+ float t = dot(v,diff);
+
+ if (t > 0)
+ {
+ float dotVV = dot(v,v);
+ if (t < dotVV)
+ {
+ t /= dotVV;
+ diff -= t*v;
+ } else
+ {
+ t = 1;
+ diff -= v;
+ }
+ } else
+ {
+ t = 0;
+ }
+ *nearest = from + t*v;
+ return dot(diff,diff);
+}
+
+
+void computeContactSphereTriangle(int pairIndex,
+ int bodyIndexA, int bodyIndexB,
+ int collidableIndexA, int collidableIndexB,
+ __global const BodyData* rigidBodies,
+ __global const btCollidableGpu* collidables,
+ const float4* triangleVertices,
+ __global struct b3Contact4Data* restrict globalContactsOut,
+ counter32_t nGlobalContactsOut,
+ int maxContactCapacity,
+ float4 spherePos2,
+ float radius,
+ float4 pos,
+ float4 quat,
+ int faceIndex
+ )
+{
+
+ float4 invPos;
+ float4 invOrn;
+
+ trInverse(pos,quat, &invPos,&invOrn);
+ float4 spherePos = transform(&spherePos2,&invPos,&invOrn);
+ int numFaces = 3;
+ float4 closestPnt = (float4)(0, 0, 0, 0);
+ float4 hitNormalWorld = (float4)(0, 0, 0, 0);
+ float minDist = -1000000.f;
+ bool bCollide = false;
+
+
+ //////////////////////////////////////
+
+ float4 sphereCenter;
+ sphereCenter = spherePos;
+
+ const float4* vertices = triangleVertices;
+ float contactBreakingThreshold = 0.f;//todo?
+ float radiusWithThreshold = radius + contactBreakingThreshold;
+ float4 edge10;
+ edge10 = vertices[1]-vertices[0];
+ edge10.w = 0.f;//is this needed?
+ float4 edge20;
+ edge20 = vertices[2]-vertices[0];
+ edge20.w = 0.f;//is this needed?
+ float4 normal = cross3(edge10,edge20);
+ normal = normalize(normal);
+ float4 p1ToCenter;
+ p1ToCenter = sphereCenter - vertices[0];
+
+ float distanceFromPlane = dot(p1ToCenter,normal);
+
+ if (distanceFromPlane < 0.f)
+ {
+ //triangle facing the other way
+ distanceFromPlane *= -1.f;
+ normal *= -1.f;
+ }
+ hitNormalWorld = normal;
+
+ bool isInsideContactPlane = distanceFromPlane < radiusWithThreshold;
+
+ // Check for contact / intersection
+ bool hasContact = false;
+ float4 contactPoint;
+ if (isInsideContactPlane)
+ {
+
+ if (pointInTriangle(vertices,&normal, &sphereCenter))
+ {
+ // Inside the contact wedge - touches a point on the shell plane
+ hasContact = true;
+ contactPoint = sphereCenter - normal*distanceFromPlane;
+
+ } else {
+ // Could be inside one of the contact capsules
+ float contactCapsuleRadiusSqr = radiusWithThreshold*radiusWithThreshold;
+ float4 nearestOnEdge;
+ int numEdges = 3;
+ for (int i = 0; i < numEdges; i++)
+ {
+ float4 pa =vertices[i];
+ float4 pb = vertices[(i+1)%3];
+
+ float distanceSqr = segmentSqrDistance(pa,pb,sphereCenter, &nearestOnEdge);
+ if (distanceSqr < contactCapsuleRadiusSqr)
+ {
+ // Yep, we're inside a capsule
+ hasContact = true;
+ contactPoint = nearestOnEdge;
+
+ }
+
+ }
+ }
+ }
+
+ if (hasContact)
+ {
+
+ closestPnt = contactPoint;
+ float4 contactToCenter = sphereCenter - contactPoint;
+ minDist = length(contactToCenter);
+ if (minDist>FLT_EPSILON)
+ {
+ hitNormalWorld = normalize(contactToCenter);//*(1./minDist);
+ bCollide = true;
+ }
+
+ }
+
+
+ /////////////////////////////////////
+
+ if (bCollide && minDist > -10000)
+ {
+
+ float4 normalOnSurfaceB1 = qtRotate(quat,-hitNormalWorld);
+ float4 pOnB1 = transform(&closestPnt,&pos,&quat);
+ float actualDepth = minDist-radius;
+
+
+ if (actualDepth<=0.f)
+ {
+ pOnB1.w = actualDepth;
+ int dstIdx;
+
+
+ float lenSqr = dot3F4(normalOnSurfaceB1,normalOnSurfaceB1);
+ if (lenSqr>FLT_EPSILON)
+ {
+ AppendInc( nGlobalContactsOut, dstIdx );
+
+ if (dstIdx < maxContactCapacity)
+ {
+ __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];
+ c->m_worldNormalOnB = -normalOnSurfaceB1;
+ c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);
+ c->m_batchIdx = pairIndex;
+ c->m_bodyAPtrAndSignBit = rigidBodies[bodyIndexA].m_invMass==0?-bodyIndexA:bodyIndexA;
+ c->m_bodyBPtrAndSignBit = rigidBodies[bodyIndexB].m_invMass==0?-bodyIndexB:bodyIndexB;
+ c->m_worldPosB[0] = pOnB1;
+
+ c->m_childIndexA = -1;
+ c->m_childIndexB = faceIndex;
+
+ GET_NPOINTS(*c) = 1;
+ }
+ }
+
+ }
+ }//if (hasCollision)
+
+}
+
+
+
+// work-in-progress
+__kernel void findConcaveSphereContactsKernel( __global int4* concavePairs,
+ __global const BodyData* rigidBodies,
+ __global const btCollidableGpu* collidables,
+ __global const ConvexPolyhedronCL* convexShapes,
+ __global const float4* vertices,
+ __global const float4* uniqueEdges,
+ __global const btGpuFace* faces,
+ __global const int* indices,
+ __global btAabbCL* aabbs,
+ __global struct b3Contact4Data* restrict globalContactsOut,
+ counter32_t nGlobalContactsOut,
+ int numConcavePairs, int maxContactCapacity
+ )
+{
+
+ int i = get_global_id(0);
+ if (i>=numConcavePairs)
+ return;
+ int pairIdx = i;
+
+ int bodyIndexA = concavePairs[i].x;
+ int bodyIndexB = concavePairs[i].y;
+
+ int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
+ int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
+
+ int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
+ int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
+
+ if (collidables[collidableIndexB].m_shapeType==SHAPE_SPHERE)
+ {
+ int f = concavePairs[i].z;
+ btGpuFace face = faces[convexShapes[shapeIndexA].m_faceOffset+f];
+
+ float4 verticesA[3];
+ for (int i=0;i<3;i++)
+ {
+ int index = indices[face.m_indexOffset+i];
+ float4 vert = vertices[convexShapes[shapeIndexA].m_vertexOffset+index];
+ verticesA[i] = vert;
+ }
+
+ float4 spherePos = rigidBodies[bodyIndexB].m_pos;
+ float sphereRadius = collidables[collidableIndexB].m_radius;
+ float4 convexPos = rigidBodies[bodyIndexA].m_pos;
+ float4 convexOrn = rigidBodies[bodyIndexA].m_quat;
+
+ computeContactSphereTriangle(i, bodyIndexB, bodyIndexA, collidableIndexB, collidableIndexA,
+ rigidBodies,collidables,
+ verticesA,
+ globalContactsOut, nGlobalContactsOut,maxContactCapacity,
+ spherePos,sphereRadius,convexPos,convexOrn, f);
+
+ return;
+ }
+} \ No newline at end of file
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/kernels/primitiveContacts.h b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/kernels/primitiveContacts.h
new file mode 100644
index 0000000000..b0103fe674
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/kernels/primitiveContacts.h
@@ -0,0 +1,1289 @@
+//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
+static const char* primitiveContactsKernelsCL= \
+"#ifndef B3_CONTACT4DATA_H\n"
+"#define B3_CONTACT4DATA_H\n"
+"#ifndef B3_FLOAT4_H\n"
+"#define B3_FLOAT4_H\n"
+"#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+"#define B3_PLATFORM_DEFINITIONS_H\n"
+"struct MyTest\n"
+"{\n"
+" int bla;\n"
+"};\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
+"#define B3_LARGE_FLOAT 1e18f\n"
+"#define B3_INFINITY 1e18f\n"
+"#define b3Assert(a)\n"
+"#define b3ConstArray(a) __global const a*\n"
+"#define b3AtomicInc atomic_inc\n"
+"#define b3AtomicAdd atomic_add\n"
+"#define b3Fabs fabs\n"
+"#define b3Sqrt native_sqrt\n"
+"#define b3Sin native_sin\n"
+"#define b3Cos native_cos\n"
+"#define B3_STATIC\n"
+"#endif\n"
+"#endif\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+" typedef float4 b3Float4;\n"
+" #define b3Float4ConstArg const b3Float4\n"
+" #define b3MakeFloat4 (float4)\n"
+" float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+" {\n"
+" float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+" float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+" return dot(a1, b1);\n"
+" }\n"
+" b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+" {\n"
+" float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+" float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+" return cross(a1, b1);\n"
+" }\n"
+" #define b3MinFloat4 min\n"
+" #define b3MaxFloat4 max\n"
+" #define b3Normalized(a) normalize(a)\n"
+"#endif \n"
+" \n"
+"inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
+"{\n"
+" if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6) \n"
+" return false;\n"
+" return true;\n"
+"}\n"
+"inline int b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
+"{\n"
+" float maxDot = -B3_INFINITY;\n"
+" int i = 0;\n"
+" int ptIndex = -1;\n"
+" for( i = 0; i < vecLen; i++ )\n"
+" {\n"
+" float dot = b3Dot3F4(vecArray[i],vec);\n"
+" \n"
+" if( dot > maxDot )\n"
+" {\n"
+" maxDot = dot;\n"
+" ptIndex = i;\n"
+" }\n"
+" }\n"
+" b3Assert(ptIndex>=0);\n"
+" if (ptIndex<0)\n"
+" {\n"
+" ptIndex = 0;\n"
+" }\n"
+" *dotOut = maxDot;\n"
+" return ptIndex;\n"
+"}\n"
+"#endif //B3_FLOAT4_H\n"
+"typedef struct b3Contact4Data b3Contact4Data_t;\n"
+"struct b3Contact4Data\n"
+"{\n"
+" b3Float4 m_worldPosB[4];\n"
+"// b3Float4 m_localPosA[4];\n"
+"// b3Float4 m_localPosB[4];\n"
+" b3Float4 m_worldNormalOnB; // w: m_nPoints\n"
+" unsigned short m_restituitionCoeffCmp;\n"
+" unsigned short m_frictionCoeffCmp;\n"
+" int m_batchIdx;\n"
+" int m_bodyAPtrAndSignBit;//x:m_bodyAPtr, y:m_bodyBPtr\n"
+" int m_bodyBPtrAndSignBit;\n"
+" int m_childIndexA;\n"
+" int m_childIndexB;\n"
+" int m_unused1;\n"
+" int m_unused2;\n"
+"};\n"
+"inline int b3Contact4Data_getNumPoints(const struct b3Contact4Data* contact)\n"
+"{\n"
+" return (int)contact->m_worldNormalOnB.w;\n"
+"};\n"
+"inline void b3Contact4Data_setNumPoints(struct b3Contact4Data* contact, int numPoints)\n"
+"{\n"
+" contact->m_worldNormalOnB.w = (float)numPoints;\n"
+"};\n"
+"#endif //B3_CONTACT4DATA_H\n"
+"#define SHAPE_CONVEX_HULL 3\n"
+"#define SHAPE_PLANE 4\n"
+"#define SHAPE_CONCAVE_TRIMESH 5\n"
+"#define SHAPE_COMPOUND_OF_CONVEX_HULLS 6\n"
+"#define SHAPE_SPHERE 7\n"
+"#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
+"#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
+"#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
+"#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n"
+"#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n"
+"#ifdef cl_ext_atomic_counters_32\n"
+"#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n"
+"#else\n"
+"#define counter32_t volatile __global int*\n"
+"#endif\n"
+"#define GET_GROUP_IDX get_group_id(0)\n"
+"#define GET_LOCAL_IDX get_local_id(0)\n"
+"#define GET_GLOBAL_IDX get_global_id(0)\n"
+"#define GET_GROUP_SIZE get_local_size(0)\n"
+"#define GET_NUM_GROUPS get_num_groups(0)\n"
+"#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
+"#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
+"#define AtomInc(x) atom_inc(&(x))\n"
+"#define AtomInc1(x, out) out = atom_inc(&(x))\n"
+"#define AppendInc(x, out) out = atomic_inc(x)\n"
+"#define AtomAdd(x, value) atom_add(&(x), value)\n"
+"#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )\n"
+"#define AtomXhg(x, value) atom_xchg ( &(x), value )\n"
+"#define max2 max\n"
+"#define min2 min\n"
+"typedef unsigned int u32;\n"
+"typedef struct \n"
+"{\n"
+" union\n"
+" {\n"
+" float4 m_min;\n"
+" float m_minElems[4];\n"
+" int m_minIndices[4];\n"
+" };\n"
+" union\n"
+" {\n"
+" float4 m_max;\n"
+" float m_maxElems[4];\n"
+" int m_maxIndices[4];\n"
+" };\n"
+"} btAabbCL;\n"
+"///keep this in sync with btCollidable.h\n"
+"typedef struct\n"
+"{\n"
+" int m_numChildShapes;\n"
+" float m_radius;\n"
+" int m_shapeType;\n"
+" int m_shapeIndex;\n"
+" \n"
+"} btCollidableGpu;\n"
+"typedef struct\n"
+"{\n"
+" float4 m_childPosition;\n"
+" float4 m_childOrientation;\n"
+" int m_shapeIndex;\n"
+" int m_unused0;\n"
+" int m_unused1;\n"
+" int m_unused2;\n"
+"} btGpuChildShape;\n"
+"#define GET_NPOINTS(x) (x).m_worldNormalOnB.w\n"
+"typedef struct\n"
+"{\n"
+" float4 m_pos;\n"
+" float4 m_quat;\n"
+" float4 m_linVel;\n"
+" float4 m_angVel;\n"
+" u32 m_collidableIdx; \n"
+" float m_invMass;\n"
+" float m_restituitionCoeff;\n"
+" float m_frictionCoeff;\n"
+"} BodyData;\n"
+"typedef struct \n"
+"{\n"
+" float4 m_localCenter;\n"
+" float4 m_extents;\n"
+" float4 mC;\n"
+" float4 mE;\n"
+" \n"
+" float m_radius;\n"
+" int m_faceOffset;\n"
+" int m_numFaces;\n"
+" int m_numVertices;\n"
+" \n"
+" int m_vertexOffset;\n"
+" int m_uniqueEdgesOffset;\n"
+" int m_numUniqueEdges;\n"
+" int m_unused;\n"
+"} ConvexPolyhedronCL;\n"
+"typedef struct\n"
+"{\n"
+" float4 m_plane;\n"
+" int m_indexOffset;\n"
+" int m_numIndices;\n"
+"} btGpuFace;\n"
+"#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n"
+"#define make_float4 (float4)\n"
+"#define make_float2 (float2)\n"
+"#define make_uint4 (uint4)\n"
+"#define make_int4 (int4)\n"
+"#define make_uint2 (uint2)\n"
+"#define make_int2 (int2)\n"
+"__inline\n"
+"float fastDiv(float numerator, float denominator)\n"
+"{\n"
+" return native_divide(numerator, denominator); \n"
+"// return numerator/denominator; \n"
+"}\n"
+"__inline\n"
+"float4 fastDiv4(float4 numerator, float4 denominator)\n"
+"{\n"
+" return native_divide(numerator, denominator); \n"
+"}\n"
+"__inline\n"
+"float4 cross3(float4 a, float4 b)\n"
+"{\n"
+" return cross(a,b);\n"
+"}\n"
+"//#define dot3F4 dot\n"
+"__inline\n"
+"float dot3F4(float4 a, float4 b)\n"
+"{\n"
+" float4 a1 = make_float4(a.xyz,0.f);\n"
+" float4 b1 = make_float4(b.xyz,0.f);\n"
+" return dot(a1, b1);\n"
+"}\n"
+"__inline\n"
+"float4 fastNormalize4(float4 v)\n"
+"{\n"
+" return fast_normalize(v);\n"
+"}\n"
+"///////////////////////////////////////\n"
+"// Quaternion\n"
+"///////////////////////////////////////\n"
+"typedef float4 Quaternion;\n"
+"__inline\n"
+"Quaternion qtMul(Quaternion a, Quaternion b);\n"
+"__inline\n"
+"Quaternion qtNormalize(Quaternion in);\n"
+"__inline\n"
+"float4 qtRotate(Quaternion q, float4 vec);\n"
+"__inline\n"
+"Quaternion qtInvert(Quaternion q);\n"
+"__inline\n"
+"Quaternion qtMul(Quaternion a, Quaternion b)\n"
+"{\n"
+" Quaternion ans;\n"
+" ans = cross3( a, b );\n"
+" ans += a.w*b+b.w*a;\n"
+"// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
+" ans.w = a.w*b.w - dot3F4(a, b);\n"
+" return ans;\n"
+"}\n"
+"__inline\n"
+"Quaternion qtNormalize(Quaternion in)\n"
+"{\n"
+" return fastNormalize4(in);\n"
+"// in /= length( in );\n"
+"// return in;\n"
+"}\n"
+"__inline\n"
+"float4 qtRotate(Quaternion q, float4 vec)\n"
+"{\n"
+" Quaternion qInv = qtInvert( q );\n"
+" float4 vcpy = vec;\n"
+" vcpy.w = 0.f;\n"
+" float4 out = qtMul(qtMul(q,vcpy),qInv);\n"
+" return out;\n"
+"}\n"
+"__inline\n"
+"Quaternion qtInvert(Quaternion q)\n"
+"{\n"
+" return (Quaternion)(-q.xyz, q.w);\n"
+"}\n"
+"__inline\n"
+"float4 qtInvRotate(const Quaternion q, float4 vec)\n"
+"{\n"
+" return qtRotate( qtInvert( q ), vec );\n"
+"}\n"
+"__inline\n"
+"float4 transform(const float4* p, const float4* translation, const Quaternion* orientation)\n"
+"{\n"
+" return qtRotate( *orientation, *p ) + (*translation);\n"
+"}\n"
+"void trInverse(float4 translationIn, Quaternion orientationIn,\n"
+" float4* translationOut, Quaternion* orientationOut)\n"
+"{\n"
+" *orientationOut = qtInvert(orientationIn);\n"
+" *translationOut = qtRotate(*orientationOut, -translationIn);\n"
+"}\n"
+"void trMul(float4 translationA, Quaternion orientationA,\n"
+" float4 translationB, Quaternion orientationB,\n"
+" float4* translationOut, Quaternion* orientationOut)\n"
+"{\n"
+" *orientationOut = qtMul(orientationA,orientationB);\n"
+" *translationOut = transform(&translationB,&translationA,&orientationA);\n"
+"}\n"
+"__inline\n"
+"float4 normalize3(const float4 a)\n"
+"{\n"
+" float4 n = make_float4(a.x, a.y, a.z, 0.f);\n"
+" return fastNormalize4( n );\n"
+"}\n"
+"__inline float4 lerp3(const float4 a,const float4 b, float t)\n"
+"{\n"
+" return make_float4( a.x + (b.x - a.x) * t,\n"
+" a.y + (b.y - a.y) * t,\n"
+" a.z + (b.z - a.z) * t,\n"
+" 0.f);\n"
+"}\n"
+"float signedDistanceFromPointToPlane(float4 point, float4 planeEqn, float4* closestPointOnFace)\n"
+"{\n"
+" float4 n = (float4)(planeEqn.x, planeEqn.y, planeEqn.z, 0);\n"
+" float dist = dot3F4(n, point) + planeEqn.w;\n"
+" *closestPointOnFace = point - dist * n;\n"
+" return dist;\n"
+"}\n"
+"inline bool IsPointInPolygon(float4 p, \n"
+" const btGpuFace* face,\n"
+" __global const float4* baseVertex,\n"
+" __global const int* convexIndices,\n"
+" float4* out)\n"
+"{\n"
+" float4 a;\n"
+" float4 b;\n"
+" float4 ab;\n"
+" float4 ap;\n"
+" float4 v;\n"
+" float4 plane = make_float4(face->m_plane.x,face->m_plane.y,face->m_plane.z,0.f);\n"
+" \n"
+" if (face->m_numIndices<2)\n"
+" return false;\n"
+" \n"
+" float4 v0 = baseVertex[convexIndices[face->m_indexOffset + face->m_numIndices-1]];\n"
+" \n"
+" b = v0;\n"
+" for(unsigned i=0; i != face->m_numIndices; ++i)\n"
+" {\n"
+" a = b;\n"
+" float4 vi = baseVertex[convexIndices[face->m_indexOffset + i]];\n"
+" b = vi;\n"
+" ab = b-a;\n"
+" ap = p-a;\n"
+" v = cross3(ab,plane);\n"
+" if (dot(ap, v) > 0.f)\n"
+" {\n"
+" float ab_m2 = dot(ab, ab);\n"
+" float rt = ab_m2 != 0.f ? dot(ab, ap) / ab_m2 : 0.f;\n"
+" if (rt <= 0.f)\n"
+" {\n"
+" *out = a;\n"
+" }\n"
+" else if (rt >= 1.f) \n"
+" {\n"
+" *out = b;\n"
+" }\n"
+" else\n"
+" {\n"
+" float s = 1.f - rt;\n"
+" out[0].x = s * a.x + rt * b.x;\n"
+" out[0].y = s * a.y + rt * b.y;\n"
+" out[0].z = s * a.z + rt * b.z;\n"
+" }\n"
+" return false;\n"
+" }\n"
+" }\n"
+" return true;\n"
+"}\n"
+"void computeContactSphereConvex(int pairIndex,\n"
+" int bodyIndexA, int bodyIndexB, \n"
+" int collidableIndexA, int collidableIndexB, \n"
+" __global const BodyData* rigidBodies, \n"
+" __global const btCollidableGpu* collidables,\n"
+" __global const ConvexPolyhedronCL* convexShapes,\n"
+" __global const float4* convexVertices,\n"
+" __global const int* convexIndices,\n"
+" __global const btGpuFace* faces,\n"
+" __global struct b3Contact4Data* restrict globalContactsOut,\n"
+" counter32_t nGlobalContactsOut,\n"
+" int maxContactCapacity,\n"
+" float4 spherePos2,\n"
+" float radius,\n"
+" float4 pos,\n"
+" float4 quat\n"
+" )\n"
+"{\n"
+" float4 invPos;\n"
+" float4 invOrn;\n"
+" trInverse(pos,quat, &invPos,&invOrn);\n"
+" float4 spherePos = transform(&spherePos2,&invPos,&invOrn);\n"
+" int shapeIndex = collidables[collidableIndexB].m_shapeIndex;\n"
+" int numFaces = convexShapes[shapeIndex].m_numFaces;\n"
+" float4 closestPnt = (float4)(0, 0, 0, 0);\n"
+" float4 hitNormalWorld = (float4)(0, 0, 0, 0);\n"
+" float minDist = -1000000.f;\n"
+" bool bCollide = true;\n"
+" for ( int f = 0; f < numFaces; f++ )\n"
+" {\n"
+" btGpuFace face = faces[convexShapes[shapeIndex].m_faceOffset+f];\n"
+" // set up a plane equation \n"
+" float4 planeEqn;\n"
+" float4 n1 = face.m_plane;\n"
+" n1.w = 0.f;\n"
+" planeEqn = n1;\n"
+" planeEqn.w = face.m_plane.w;\n"
+" \n"
+" \n"
+" // compute a signed distance from the vertex in cloth to the face of rigidbody.\n"
+" float4 pntReturn;\n"
+" float dist = signedDistanceFromPointToPlane(spherePos, planeEqn, &pntReturn);\n"
+" // If the distance is positive, the plane is a separating plane. \n"
+" if ( dist > radius )\n"
+" {\n"
+" bCollide = false;\n"
+" break;\n"
+" }\n"
+" if (dist>0)\n"
+" {\n"
+" //might hit an edge or vertex\n"
+" float4 out;\n"
+" float4 zeroPos = make_float4(0,0,0,0);\n"
+" bool isInPoly = IsPointInPolygon(spherePos,\n"
+" &face,\n"
+" &convexVertices[convexShapes[shapeIndex].m_vertexOffset],\n"
+" convexIndices,\n"
+" &out);\n"
+" if (isInPoly)\n"
+" {\n"
+" if (dist>minDist)\n"
+" {\n"
+" minDist = dist;\n"
+" closestPnt = pntReturn;\n"
+" hitNormalWorld = planeEqn;\n"
+" \n"
+" }\n"
+" } else\n"
+" {\n"
+" float4 tmp = spherePos-out;\n"
+" float l2 = dot(tmp,tmp);\n"
+" if (l2<radius*radius)\n"
+" {\n"
+" dist = sqrt(l2);\n"
+" if (dist>minDist)\n"
+" {\n"
+" minDist = dist;\n"
+" closestPnt = out;\n"
+" hitNormalWorld = tmp/dist;\n"
+" \n"
+" }\n"
+" \n"
+" } else\n"
+" {\n"
+" bCollide = false;\n"
+" break;\n"
+" }\n"
+" }\n"
+" } else\n"
+" {\n"
+" if ( dist > minDist )\n"
+" {\n"
+" minDist = dist;\n"
+" closestPnt = pntReturn;\n"
+" hitNormalWorld.xyz = planeEqn.xyz;\n"
+" }\n"
+" }\n"
+" \n"
+" }\n"
+" \n"
+" if (bCollide && minDist > -10000)\n"
+" {\n"
+" float4 normalOnSurfaceB1 = qtRotate(quat,-hitNormalWorld);\n"
+" float4 pOnB1 = transform(&closestPnt,&pos,&quat);\n"
+" \n"
+" float actualDepth = minDist-radius;\n"
+" if (actualDepth<=0.f)\n"
+" {\n"
+" \n"
+" pOnB1.w = actualDepth;\n"
+" int dstIdx;\n"
+" AppendInc( nGlobalContactsOut, dstIdx );\n"
+" \n"
+" \n"
+" if (1)//dstIdx < maxContactCapacity)\n"
+" {\n"
+" __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];\n"
+" c->m_worldNormalOnB = -normalOnSurfaceB1;\n"
+" c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
+" c->m_batchIdx = pairIndex;\n"
+" c->m_bodyAPtrAndSignBit = rigidBodies[bodyIndexA].m_invMass==0?-bodyIndexA:bodyIndexA;\n"
+" c->m_bodyBPtrAndSignBit = rigidBodies[bodyIndexB].m_invMass==0?-bodyIndexB:bodyIndexB;\n"
+" c->m_worldPosB[0] = pOnB1;\n"
+" c->m_childIndexA = -1;\n"
+" c->m_childIndexB = -1;\n"
+" GET_NPOINTS(*c) = 1;\n"
+" } \n"
+" }\n"
+" }//if (hasCollision)\n"
+"}\n"
+" \n"
+"int extractManifoldSequential(const float4* p, int nPoints, float4 nearNormal, int4* contactIdx)\n"
+"{\n"
+" if( nPoints == 0 )\n"
+" return 0;\n"
+" \n"
+" if (nPoints <=4)\n"
+" return nPoints;\n"
+" \n"
+" \n"
+" if (nPoints >64)\n"
+" nPoints = 64;\n"
+" \n"
+" float4 center = make_float4(0.f);\n"
+" {\n"
+" \n"
+" for (int i=0;i<nPoints;i++)\n"
+" center += p[i];\n"
+" center /= (float)nPoints;\n"
+" }\n"
+" \n"
+" \n"
+" \n"
+" // sample 4 directions\n"
+" \n"
+" float4 aVector = p[0] - center;\n"
+" float4 u = cross3( nearNormal, aVector );\n"
+" float4 v = cross3( nearNormal, u );\n"
+" u = normalize3( u );\n"
+" v = normalize3( v );\n"
+" \n"
+" \n"
+" //keep point with deepest penetration\n"
+" float minW= FLT_MAX;\n"
+" \n"
+" int minIndex=-1;\n"
+" \n"
+" float4 maxDots;\n"
+" maxDots.x = FLT_MIN;\n"
+" maxDots.y = FLT_MIN;\n"
+" maxDots.z = FLT_MIN;\n"
+" maxDots.w = FLT_MIN;\n"
+" \n"
+" // idx, distance\n"
+" for(int ie = 0; ie<nPoints; ie++ )\n"
+" {\n"
+" if (p[ie].w<minW)\n"
+" {\n"
+" minW = p[ie].w;\n"
+" minIndex=ie;\n"
+" }\n"
+" float f;\n"
+" float4 r = p[ie]-center;\n"
+" f = dot3F4( u, r );\n"
+" if (f<maxDots.x)\n"
+" {\n"
+" maxDots.x = f;\n"
+" contactIdx[0].x = ie;\n"
+" }\n"
+" \n"
+" f = dot3F4( -u, r );\n"
+" if (f<maxDots.y)\n"
+" {\n"
+" maxDots.y = f;\n"
+" contactIdx[0].y = ie;\n"
+" }\n"
+" \n"
+" \n"
+" f = dot3F4( v, r );\n"
+" if (f<maxDots.z)\n"
+" {\n"
+" maxDots.z = f;\n"
+" contactIdx[0].z = ie;\n"
+" }\n"
+" \n"
+" f = dot3F4( -v, r );\n"
+" if (f<maxDots.w)\n"
+" {\n"
+" maxDots.w = f;\n"
+" contactIdx[0].w = ie;\n"
+" }\n"
+" \n"
+" }\n"
+" \n"
+" if (contactIdx[0].x != minIndex && contactIdx[0].y != minIndex && contactIdx[0].z != minIndex && contactIdx[0].w != minIndex)\n"
+" {\n"
+" //replace the first contact with minimum (todo: replace contact with least penetration)\n"
+" contactIdx[0].x = minIndex;\n"
+" }\n"
+" \n"
+" return 4;\n"
+" \n"
+"}\n"
+"#define MAX_PLANE_CONVEX_POINTS 64\n"
+"int computeContactPlaneConvex(int pairIndex,\n"
+" int bodyIndexA, int bodyIndexB, \n"
+" int collidableIndexA, int collidableIndexB, \n"
+" __global const BodyData* rigidBodies, \n"
+" __global const btCollidableGpu*collidables,\n"
+" __global const ConvexPolyhedronCL* convexShapes,\n"
+" __global const float4* convexVertices,\n"
+" __global const int* convexIndices,\n"
+" __global const btGpuFace* faces,\n"
+" __global struct b3Contact4Data* restrict globalContactsOut,\n"
+" counter32_t nGlobalContactsOut,\n"
+" int maxContactCapacity,\n"
+" float4 posB,\n"
+" Quaternion ornB\n"
+" )\n"
+"{\n"
+" int resultIndex=-1;\n"
+" int shapeIndex = collidables[collidableIndexB].m_shapeIndex;\n"
+" __global const ConvexPolyhedronCL* hullB = &convexShapes[shapeIndex];\n"
+" \n"
+" float4 posA;\n"
+" posA = rigidBodies[bodyIndexA].m_pos;\n"
+" Quaternion ornA;\n"
+" ornA = rigidBodies[bodyIndexA].m_quat;\n"
+" int numContactsOut = 0;\n"
+" int numWorldVertsB1= 0;\n"
+" float4 planeEq;\n"
+" planeEq = faces[collidables[collidableIndexA].m_shapeIndex].m_plane;\n"
+" float4 planeNormal = make_float4(planeEq.x,planeEq.y,planeEq.z,0.f);\n"
+" float4 planeNormalWorld;\n"
+" planeNormalWorld = qtRotate(ornA,planeNormal);\n"
+" float planeConstant = planeEq.w;\n"
+" \n"
+" float4 invPosA;Quaternion invOrnA;\n"
+" float4 convexInPlaneTransPos1; Quaternion convexInPlaneTransOrn1;\n"
+" {\n"
+" \n"
+" trInverse(posA,ornA,&invPosA,&invOrnA);\n"
+" trMul(invPosA,invOrnA,posB,ornB,&convexInPlaneTransPos1,&convexInPlaneTransOrn1);\n"
+" }\n"
+" float4 invPosB;Quaternion invOrnB;\n"
+" float4 planeInConvexPos1; Quaternion planeInConvexOrn1;\n"
+" {\n"
+" \n"
+" trInverse(posB,ornB,&invPosB,&invOrnB);\n"
+" trMul(invPosB,invOrnB,posA,ornA,&planeInConvexPos1,&planeInConvexOrn1); \n"
+" }\n"
+" \n"
+" float4 planeNormalInConvex = qtRotate(planeInConvexOrn1,-planeNormal);\n"
+" float maxDot = -1e30;\n"
+" int hitVertex=-1;\n"
+" float4 hitVtx;\n"
+" float4 contactPoints[MAX_PLANE_CONVEX_POINTS];\n"
+" int numPoints = 0;\n"
+" int4 contactIdx;\n"
+" contactIdx=make_int4(0,1,2,3);\n"
+" \n"
+" \n"
+" for (int i=0;i<hullB->m_numVertices;i++)\n"
+" {\n"
+" float4 vtx = convexVertices[hullB->m_vertexOffset+i];\n"
+" float curDot = dot(vtx,planeNormalInConvex);\n"
+" if (curDot>maxDot)\n"
+" {\n"
+" hitVertex=i;\n"
+" maxDot=curDot;\n"
+" hitVtx = vtx;\n"
+" //make sure the deepest points is always included\n"
+" if (numPoints==MAX_PLANE_CONVEX_POINTS)\n"
+" numPoints--;\n"
+" }\n"
+" if (numPoints<MAX_PLANE_CONVEX_POINTS)\n"
+" {\n"
+" float4 vtxWorld = transform(&vtx, &posB, &ornB);\n"
+" float4 vtxInPlane = transform(&vtxWorld, &invPosA, &invOrnA);//oplaneTransform.inverse()*vtxWorld;\n"
+" float dist = dot(planeNormal,vtxInPlane)-planeConstant;\n"
+" if (dist<0.f)\n"
+" {\n"
+" vtxWorld.w = dist;\n"
+" contactPoints[numPoints] = vtxWorld;\n"
+" numPoints++;\n"
+" }\n"
+" }\n"
+" }\n"
+" int numReducedPoints = numPoints;\n"
+" if (numPoints>4)\n"
+" {\n"
+" numReducedPoints = extractManifoldSequential( contactPoints, numPoints, planeNormalInConvex, &contactIdx);\n"
+" }\n"
+" if (numReducedPoints>0)\n"
+" {\n"
+" int dstIdx;\n"
+" AppendInc( nGlobalContactsOut, dstIdx );\n"
+" if (dstIdx < maxContactCapacity)\n"
+" {\n"
+" resultIndex = dstIdx;\n"
+" __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];\n"
+" c->m_worldNormalOnB = -planeNormalWorld;\n"
+" //c->setFrictionCoeff(0.7);\n"
+" //c->setRestituitionCoeff(0.f);\n"
+" c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
+" c->m_batchIdx = pairIndex;\n"
+" c->m_bodyAPtrAndSignBit = rigidBodies[bodyIndexA].m_invMass==0?-bodyIndexA:bodyIndexA;\n"
+" c->m_bodyBPtrAndSignBit = rigidBodies[bodyIndexB].m_invMass==0?-bodyIndexB:bodyIndexB;\n"
+" c->m_childIndexA = -1;\n"
+" c->m_childIndexB = -1;\n"
+" switch (numReducedPoints)\n"
+" {\n"
+" case 4:\n"
+" c->m_worldPosB[3] = contactPoints[contactIdx.w];\n"
+" case 3:\n"
+" c->m_worldPosB[2] = contactPoints[contactIdx.z];\n"
+" case 2:\n"
+" c->m_worldPosB[1] = contactPoints[contactIdx.y];\n"
+" case 1:\n"
+" c->m_worldPosB[0] = contactPoints[contactIdx.x];\n"
+" default:\n"
+" {\n"
+" }\n"
+" };\n"
+" \n"
+" GET_NPOINTS(*c) = numReducedPoints;\n"
+" }//if (dstIdx < numPairs)\n"
+" } \n"
+" return resultIndex;\n"
+"}\n"
+"void computeContactPlaneSphere(int pairIndex,\n"
+" int bodyIndexA, int bodyIndexB, \n"
+" int collidableIndexA, int collidableIndexB, \n"
+" __global const BodyData* rigidBodies, \n"
+" __global const btCollidableGpu* collidables,\n"
+" __global const btGpuFace* faces,\n"
+" __global struct b3Contact4Data* restrict globalContactsOut,\n"
+" counter32_t nGlobalContactsOut,\n"
+" int maxContactCapacity)\n"
+"{\n"
+" float4 planeEq = faces[collidables[collidableIndexA].m_shapeIndex].m_plane;\n"
+" float radius = collidables[collidableIndexB].m_radius;\n"
+" float4 posA1 = rigidBodies[bodyIndexA].m_pos;\n"
+" float4 ornA1 = rigidBodies[bodyIndexA].m_quat;\n"
+" float4 posB1 = rigidBodies[bodyIndexB].m_pos;\n"
+" float4 ornB1 = rigidBodies[bodyIndexB].m_quat;\n"
+" \n"
+" bool hasCollision = false;\n"
+" float4 planeNormal1 = make_float4(planeEq.x,planeEq.y,planeEq.z,0.f);\n"
+" float planeConstant = planeEq.w;\n"
+" float4 convexInPlaneTransPos1; Quaternion convexInPlaneTransOrn1;\n"
+" {\n"
+" float4 invPosA;Quaternion invOrnA;\n"
+" trInverse(posA1,ornA1,&invPosA,&invOrnA);\n"
+" trMul(invPosA,invOrnA,posB1,ornB1,&convexInPlaneTransPos1,&convexInPlaneTransOrn1);\n"
+" }\n"
+" float4 planeInConvexPos1; Quaternion planeInConvexOrn1;\n"
+" {\n"
+" float4 invPosB;Quaternion invOrnB;\n"
+" trInverse(posB1,ornB1,&invPosB,&invOrnB);\n"
+" trMul(invPosB,invOrnB,posA1,ornA1,&planeInConvexPos1,&planeInConvexOrn1); \n"
+" }\n"
+" float4 vtx1 = qtRotate(planeInConvexOrn1,-planeNormal1)*radius;\n"
+" float4 vtxInPlane1 = transform(&vtx1,&convexInPlaneTransPos1,&convexInPlaneTransOrn1);\n"
+" float distance = dot3F4(planeNormal1,vtxInPlane1) - planeConstant;\n"
+" hasCollision = distance < 0.f;//m_manifoldPtr->getContactBreakingThreshold();\n"
+" if (hasCollision)\n"
+" {\n"
+" float4 vtxInPlaneProjected1 = vtxInPlane1 - distance*planeNormal1;\n"
+" float4 vtxInPlaneWorld1 = transform(&vtxInPlaneProjected1,&posA1,&ornA1);\n"
+" float4 normalOnSurfaceB1 = qtRotate(ornA1,planeNormal1);\n"
+" float4 pOnB1 = vtxInPlaneWorld1+normalOnSurfaceB1*distance;\n"
+" pOnB1.w = distance;\n"
+" int dstIdx;\n"
+" AppendInc( nGlobalContactsOut, dstIdx );\n"
+" \n"
+" if (dstIdx < maxContactCapacity)\n"
+" {\n"
+" __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];\n"
+" c->m_worldNormalOnB = -normalOnSurfaceB1;\n"
+" c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
+" c->m_batchIdx = pairIndex;\n"
+" c->m_bodyAPtrAndSignBit = rigidBodies[bodyIndexA].m_invMass==0?-bodyIndexA:bodyIndexA;\n"
+" c->m_bodyBPtrAndSignBit = rigidBodies[bodyIndexB].m_invMass==0?-bodyIndexB:bodyIndexB;\n"
+" c->m_worldPosB[0] = pOnB1;\n"
+" c->m_childIndexA = -1;\n"
+" c->m_childIndexB = -1;\n"
+" GET_NPOINTS(*c) = 1;\n"
+" }//if (dstIdx < numPairs)\n"
+" }//if (hasCollision)\n"
+"}\n"
+"__kernel void primitiveContactsKernel( __global int4* pairs, \n"
+" __global const BodyData* rigidBodies, \n"
+" __global const btCollidableGpu* collidables,\n"
+" __global const ConvexPolyhedronCL* convexShapes, \n"
+" __global const float4* vertices,\n"
+" __global const float4* uniqueEdges,\n"
+" __global const btGpuFace* faces,\n"
+" __global const int* indices,\n"
+" __global struct b3Contact4Data* restrict globalContactsOut,\n"
+" counter32_t nGlobalContactsOut,\n"
+" int numPairs, int maxContactCapacity)\n"
+"{\n"
+" int i = get_global_id(0);\n"
+" int pairIndex = i;\n"
+" \n"
+" float4 worldVertsB1[64];\n"
+" float4 worldVertsB2[64];\n"
+" int capacityWorldVerts = 64; \n"
+" float4 localContactsOut[64];\n"
+" int localContactCapacity=64;\n"
+" \n"
+" float minDist = -1e30f;\n"
+" float maxDist = 0.02f;\n"
+" if (i<numPairs)\n"
+" {\n"
+" int bodyIndexA = pairs[i].x;\n"
+" int bodyIndexB = pairs[i].y;\n"
+" \n"
+" int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
+" int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
+" \n"
+" if (collidables[collidableIndexA].m_shapeType == SHAPE_PLANE &&\n"
+" collidables[collidableIndexB].m_shapeType == SHAPE_CONVEX_HULL)\n"
+" {\n"
+" float4 posB;\n"
+" posB = rigidBodies[bodyIndexB].m_pos;\n"
+" Quaternion ornB;\n"
+" ornB = rigidBodies[bodyIndexB].m_quat;\n"
+" int contactIndex = computeContactPlaneConvex(pairIndex, bodyIndexA, bodyIndexB, collidableIndexA, collidableIndexB, \n"
+" rigidBodies,collidables,convexShapes,vertices,indices,\n"
+" faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity, posB,ornB);\n"
+" if (contactIndex>=0)\n"
+" pairs[pairIndex].z = contactIndex;\n"
+" return;\n"
+" }\n"
+" if (collidables[collidableIndexA].m_shapeType == SHAPE_CONVEX_HULL &&\n"
+" collidables[collidableIndexB].m_shapeType == SHAPE_PLANE)\n"
+" {\n"
+" float4 posA;\n"
+" posA = rigidBodies[bodyIndexA].m_pos;\n"
+" Quaternion ornA;\n"
+" ornA = rigidBodies[bodyIndexA].m_quat;\n"
+" int contactIndex = computeContactPlaneConvex( pairIndex, bodyIndexB,bodyIndexA, collidableIndexB,collidableIndexA, \n"
+" rigidBodies,collidables,convexShapes,vertices,indices,\n"
+" faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity,posA,ornA);\n"
+" if (contactIndex>=0)\n"
+" pairs[pairIndex].z = contactIndex;\n"
+" return;\n"
+" }\n"
+" if (collidables[collidableIndexA].m_shapeType == SHAPE_PLANE &&\n"
+" collidables[collidableIndexB].m_shapeType == SHAPE_SPHERE)\n"
+" {\n"
+" computeContactPlaneSphere(pairIndex, bodyIndexA, bodyIndexB, collidableIndexA, collidableIndexB, \n"
+" rigidBodies,collidables,faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity);\n"
+" return;\n"
+" }\n"
+" if (collidables[collidableIndexA].m_shapeType == SHAPE_SPHERE &&\n"
+" collidables[collidableIndexB].m_shapeType == SHAPE_PLANE)\n"
+" {\n"
+" computeContactPlaneSphere( pairIndex, bodyIndexB,bodyIndexA, collidableIndexB,collidableIndexA, \n"
+" rigidBodies,collidables,\n"
+" faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity);\n"
+" return;\n"
+" }\n"
+" \n"
+" \n"
+" if (collidables[collidableIndexA].m_shapeType == SHAPE_SPHERE &&\n"
+" collidables[collidableIndexB].m_shapeType == SHAPE_CONVEX_HULL)\n"
+" {\n"
+" \n"
+" float4 spherePos = rigidBodies[bodyIndexA].m_pos;\n"
+" float sphereRadius = collidables[collidableIndexA].m_radius;\n"
+" float4 convexPos = rigidBodies[bodyIndexB].m_pos;\n"
+" float4 convexOrn = rigidBodies[bodyIndexB].m_quat;\n"
+" computeContactSphereConvex(pairIndex, bodyIndexA, bodyIndexB, collidableIndexA, collidableIndexB, \n"
+" rigidBodies,collidables,convexShapes,vertices,indices,faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity,\n"
+" spherePos,sphereRadius,convexPos,convexOrn);\n"
+" return;\n"
+" }\n"
+" if (collidables[collidableIndexA].m_shapeType == SHAPE_CONVEX_HULL &&\n"
+" collidables[collidableIndexB].m_shapeType == SHAPE_SPHERE)\n"
+" {\n"
+" \n"
+" float4 spherePos = rigidBodies[bodyIndexB].m_pos;\n"
+" float sphereRadius = collidables[collidableIndexB].m_radius;\n"
+" float4 convexPos = rigidBodies[bodyIndexA].m_pos;\n"
+" float4 convexOrn = rigidBodies[bodyIndexA].m_quat;\n"
+" computeContactSphereConvex(pairIndex, bodyIndexB, bodyIndexA, collidableIndexB, collidableIndexA, \n"
+" rigidBodies,collidables,convexShapes,vertices,indices,faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity,\n"
+" spherePos,sphereRadius,convexPos,convexOrn);\n"
+" return;\n"
+" }\n"
+" \n"
+" \n"
+" \n"
+" \n"
+" \n"
+" \n"
+" if (collidables[collidableIndexA].m_shapeType == SHAPE_SPHERE &&\n"
+" collidables[collidableIndexB].m_shapeType == SHAPE_SPHERE)\n"
+" {\n"
+" //sphere-sphere\n"
+" float radiusA = collidables[collidableIndexA].m_radius;\n"
+" float radiusB = collidables[collidableIndexB].m_radius;\n"
+" float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
+" float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
+" float4 diff = posA-posB;\n"
+" float len = length(diff);\n"
+" \n"
+" ///iff distance positive, don't generate a new contact\n"
+" if ( len <= (radiusA+radiusB))\n"
+" {\n"
+" ///distance (negative means penetration)\n"
+" float dist = len - (radiusA+radiusB);\n"
+" float4 normalOnSurfaceB = make_float4(1.f,0.f,0.f,0.f);\n"
+" if (len > 0.00001)\n"
+" {\n"
+" normalOnSurfaceB = diff / len;\n"
+" }\n"
+" float4 contactPosB = posB + normalOnSurfaceB*radiusB;\n"
+" contactPosB.w = dist;\n"
+" \n"
+" int dstIdx;\n"
+" AppendInc( nGlobalContactsOut, dstIdx );\n"
+" \n"
+" if (dstIdx < maxContactCapacity)\n"
+" {\n"
+" __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];\n"
+" c->m_worldNormalOnB = normalOnSurfaceB;\n"
+" c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
+" c->m_batchIdx = pairIndex;\n"
+" int bodyA = pairs[pairIndex].x;\n"
+" int bodyB = pairs[pairIndex].y;\n"
+" c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0?-bodyA:bodyA;\n"
+" c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0?-bodyB:bodyB;\n"
+" c->m_worldPosB[0] = contactPosB;\n"
+" c->m_childIndexA = -1;\n"
+" c->m_childIndexB = -1;\n"
+" GET_NPOINTS(*c) = 1;\n"
+" }//if (dstIdx < numPairs)\n"
+" }//if ( len <= (radiusA+radiusB))\n"
+" return;\n"
+" }//SHAPE_SPHERE SHAPE_SPHERE\n"
+" }// if (i<numPairs)\n"
+"}\n"
+"// work-in-progress\n"
+"__kernel void processCompoundPairsPrimitivesKernel( __global const int4* gpuCompoundPairs,\n"
+" __global const BodyData* rigidBodies, \n"
+" __global const btCollidableGpu* collidables,\n"
+" __global const ConvexPolyhedronCL* convexShapes, \n"
+" __global const float4* vertices,\n"
+" __global const float4* uniqueEdges,\n"
+" __global const btGpuFace* faces,\n"
+" __global const int* indices,\n"
+" __global btAabbCL* aabbs,\n"
+" __global const btGpuChildShape* gpuChildShapes,\n"
+" __global struct b3Contact4Data* restrict globalContactsOut,\n"
+" counter32_t nGlobalContactsOut,\n"
+" int numCompoundPairs, int maxContactCapacity\n"
+" )\n"
+"{\n"
+" int i = get_global_id(0);\n"
+" if (i<numCompoundPairs)\n"
+" {\n"
+" int bodyIndexA = gpuCompoundPairs[i].x;\n"
+" int bodyIndexB = gpuCompoundPairs[i].y;\n"
+" int childShapeIndexA = gpuCompoundPairs[i].z;\n"
+" int childShapeIndexB = gpuCompoundPairs[i].w;\n"
+" \n"
+" int collidableIndexA = -1;\n"
+" int collidableIndexB = -1;\n"
+" \n"
+" float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
+" float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
+" \n"
+" float4 ornB = rigidBodies[bodyIndexB].m_quat;\n"
+" float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
+" \n"
+" if (childShapeIndexA >= 0)\n"
+" {\n"
+" collidableIndexA = gpuChildShapes[childShapeIndexA].m_shapeIndex;\n"
+" float4 childPosA = gpuChildShapes[childShapeIndexA].m_childPosition;\n"
+" float4 childOrnA = gpuChildShapes[childShapeIndexA].m_childOrientation;\n"
+" float4 newPosA = qtRotate(ornA,childPosA)+posA;\n"
+" float4 newOrnA = qtMul(ornA,childOrnA);\n"
+" posA = newPosA;\n"
+" ornA = newOrnA;\n"
+" } else\n"
+" {\n"
+" collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
+" }\n"
+" \n"
+" if (childShapeIndexB>=0)\n"
+" {\n"
+" collidableIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;\n"
+" float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;\n"
+" float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;\n"
+" float4 newPosB = transform(&childPosB,&posB,&ornB);\n"
+" float4 newOrnB = qtMul(ornB,childOrnB);\n"
+" posB = newPosB;\n"
+" ornB = newOrnB;\n"
+" } else\n"
+" {\n"
+" collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx; \n"
+" }\n"
+" \n"
+" int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
+" int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
+" \n"
+" int shapeTypeA = collidables[collidableIndexA].m_shapeType;\n"
+" int shapeTypeB = collidables[collidableIndexB].m_shapeType;\n"
+" int pairIndex = i;\n"
+" if ((shapeTypeA == SHAPE_PLANE) && (shapeTypeB==SHAPE_CONVEX_HULL))\n"
+" {\n"
+" computeContactPlaneConvex( pairIndex, bodyIndexA,bodyIndexB, collidableIndexA,collidableIndexB, \n"
+" rigidBodies,collidables,convexShapes,vertices,indices,\n"
+" faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity,posB,ornB);\n"
+" return;\n"
+" }\n"
+" if ((shapeTypeA == SHAPE_CONVEX_HULL) && (shapeTypeB==SHAPE_PLANE))\n"
+" {\n"
+" computeContactPlaneConvex( pairIndex, bodyIndexB,bodyIndexA, collidableIndexB,collidableIndexA, \n"
+" rigidBodies,collidables,convexShapes,vertices,indices,\n"
+" faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity,posA,ornA);\n"
+" return;\n"
+" }\n"
+" if ((shapeTypeA == SHAPE_CONVEX_HULL) && (shapeTypeB == SHAPE_SPHERE))\n"
+" {\n"
+" float4 spherePos = rigidBodies[bodyIndexB].m_pos;\n"
+" float sphereRadius = collidables[collidableIndexB].m_radius;\n"
+" float4 convexPos = posA;\n"
+" float4 convexOrn = ornA;\n"
+" \n"
+" computeContactSphereConvex(pairIndex, bodyIndexB, bodyIndexA , collidableIndexB,collidableIndexA, \n"
+" rigidBodies,collidables,convexShapes,vertices,indices,faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity,\n"
+" spherePos,sphereRadius,convexPos,convexOrn);\n"
+" \n"
+" return;\n"
+" }\n"
+" if ((shapeTypeA == SHAPE_SPHERE) && (shapeTypeB == SHAPE_CONVEX_HULL))\n"
+" {\n"
+" float4 spherePos = rigidBodies[bodyIndexA].m_pos;\n"
+" float sphereRadius = collidables[collidableIndexA].m_radius;\n"
+" float4 convexPos = posB;\n"
+" float4 convexOrn = ornB;\n"
+" \n"
+" computeContactSphereConvex(pairIndex, bodyIndexA, bodyIndexB, collidableIndexA, collidableIndexB, \n"
+" rigidBodies,collidables,convexShapes,vertices,indices,faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity,\n"
+" spherePos,sphereRadius,convexPos,convexOrn);\n"
+" \n"
+" return;\n"
+" }\n"
+" }// if (i<numCompoundPairs)\n"
+"}\n"
+"bool pointInTriangle(const float4* vertices, const float4* normal, float4 *p )\n"
+"{\n"
+" const float4* p1 = &vertices[0];\n"
+" const float4* p2 = &vertices[1];\n"
+" const float4* p3 = &vertices[2];\n"
+" float4 edge1; edge1 = (*p2 - *p1);\n"
+" float4 edge2; edge2 = ( *p3 - *p2 );\n"
+" float4 edge3; edge3 = ( *p1 - *p3 );\n"
+" \n"
+" float4 p1_to_p; p1_to_p = ( *p - *p1 );\n"
+" float4 p2_to_p; p2_to_p = ( *p - *p2 );\n"
+" float4 p3_to_p; p3_to_p = ( *p - *p3 );\n"
+" float4 edge1_normal; edge1_normal = ( cross(edge1,*normal));\n"
+" float4 edge2_normal; edge2_normal = ( cross(edge2,*normal));\n"
+" float4 edge3_normal; edge3_normal = ( cross(edge3,*normal));\n"
+" \n"
+" \n"
+" float r1, r2, r3;\n"
+" r1 = dot(edge1_normal,p1_to_p );\n"
+" r2 = dot(edge2_normal,p2_to_p );\n"
+" r3 = dot(edge3_normal,p3_to_p );\n"
+" \n"
+" if ( r1 > 0 && r2 > 0 && r3 > 0 )\n"
+" return true;\n"
+" if ( r1 <= 0 && r2 <= 0 && r3 <= 0 ) \n"
+" return true;\n"
+" return false;\n"
+"}\n"
+"float segmentSqrDistance(float4 from, float4 to,float4 p, float4* nearest) \n"
+"{\n"
+" float4 diff = p - from;\n"
+" float4 v = to - from;\n"
+" float t = dot(v,diff);\n"
+" \n"
+" if (t > 0) \n"
+" {\n"
+" float dotVV = dot(v,v);\n"
+" if (t < dotVV) \n"
+" {\n"
+" t /= dotVV;\n"
+" diff -= t*v;\n"
+" } else \n"
+" {\n"
+" t = 1;\n"
+" diff -= v;\n"
+" }\n"
+" } else\n"
+" {\n"
+" t = 0;\n"
+" }\n"
+" *nearest = from + t*v;\n"
+" return dot(diff,diff); \n"
+"}\n"
+"void computeContactSphereTriangle(int pairIndex,\n"
+" int bodyIndexA, int bodyIndexB,\n"
+" int collidableIndexA, int collidableIndexB, \n"
+" __global const BodyData* rigidBodies, \n"
+" __global const btCollidableGpu* collidables,\n"
+" const float4* triangleVertices,\n"
+" __global struct b3Contact4Data* restrict globalContactsOut,\n"
+" counter32_t nGlobalContactsOut,\n"
+" int maxContactCapacity,\n"
+" float4 spherePos2,\n"
+" float radius,\n"
+" float4 pos,\n"
+" float4 quat,\n"
+" int faceIndex\n"
+" )\n"
+"{\n"
+" float4 invPos;\n"
+" float4 invOrn;\n"
+" trInverse(pos,quat, &invPos,&invOrn);\n"
+" float4 spherePos = transform(&spherePos2,&invPos,&invOrn);\n"
+" int numFaces = 3;\n"
+" float4 closestPnt = (float4)(0, 0, 0, 0);\n"
+" float4 hitNormalWorld = (float4)(0, 0, 0, 0);\n"
+" float minDist = -1000000.f;\n"
+" bool bCollide = false;\n"
+" \n"
+" //////////////////////////////////////\n"
+" float4 sphereCenter;\n"
+" sphereCenter = spherePos;\n"
+" const float4* vertices = triangleVertices;\n"
+" float contactBreakingThreshold = 0.f;//todo?\n"
+" float radiusWithThreshold = radius + contactBreakingThreshold;\n"
+" float4 edge10;\n"
+" edge10 = vertices[1]-vertices[0];\n"
+" edge10.w = 0.f;//is this needed?\n"
+" float4 edge20;\n"
+" edge20 = vertices[2]-vertices[0];\n"
+" edge20.w = 0.f;//is this needed?\n"
+" float4 normal = cross3(edge10,edge20);\n"
+" normal = normalize(normal);\n"
+" float4 p1ToCenter;\n"
+" p1ToCenter = sphereCenter - vertices[0];\n"
+" \n"
+" float distanceFromPlane = dot(p1ToCenter,normal);\n"
+" if (distanceFromPlane < 0.f)\n"
+" {\n"
+" //triangle facing the other way\n"
+" distanceFromPlane *= -1.f;\n"
+" normal *= -1.f;\n"
+" }\n"
+" hitNormalWorld = normal;\n"
+" bool isInsideContactPlane = distanceFromPlane < radiusWithThreshold;\n"
+" \n"
+" // Check for contact / intersection\n"
+" bool hasContact = false;\n"
+" float4 contactPoint;\n"
+" if (isInsideContactPlane) \n"
+" {\n"
+" \n"
+" if (pointInTriangle(vertices,&normal, &sphereCenter)) \n"
+" {\n"
+" // Inside the contact wedge - touches a point on the shell plane\n"
+" hasContact = true;\n"
+" contactPoint = sphereCenter - normal*distanceFromPlane;\n"
+" \n"
+" } else {\n"
+" // Could be inside one of the contact capsules\n"
+" float contactCapsuleRadiusSqr = radiusWithThreshold*radiusWithThreshold;\n"
+" float4 nearestOnEdge;\n"
+" int numEdges = 3;\n"
+" for (int i = 0; i < numEdges; i++) \n"
+" {\n"
+" float4 pa =vertices[i];\n"
+" float4 pb = vertices[(i+1)%3];\n"
+" float distanceSqr = segmentSqrDistance(pa,pb,sphereCenter, &nearestOnEdge);\n"
+" if (distanceSqr < contactCapsuleRadiusSqr) \n"
+" {\n"
+" // Yep, we're inside a capsule\n"
+" hasContact = true;\n"
+" contactPoint = nearestOnEdge;\n"
+" \n"
+" }\n"
+" \n"
+" }\n"
+" }\n"
+" }\n"
+" if (hasContact) \n"
+" {\n"
+" closestPnt = contactPoint;\n"
+" float4 contactToCenter = sphereCenter - contactPoint;\n"
+" minDist = length(contactToCenter);\n"
+" if (minDist>FLT_EPSILON)\n"
+" {\n"
+" hitNormalWorld = normalize(contactToCenter);//*(1./minDist);\n"
+" bCollide = true;\n"
+" }\n"
+" \n"
+" }\n"
+" /////////////////////////////////////\n"
+" if (bCollide && minDist > -10000)\n"
+" {\n"
+" \n"
+" float4 normalOnSurfaceB1 = qtRotate(quat,-hitNormalWorld);\n"
+" float4 pOnB1 = transform(&closestPnt,&pos,&quat);\n"
+" float actualDepth = minDist-radius;\n"
+" \n"
+" if (actualDepth<=0.f)\n"
+" {\n"
+" pOnB1.w = actualDepth;\n"
+" int dstIdx;\n"
+" \n"
+" float lenSqr = dot3F4(normalOnSurfaceB1,normalOnSurfaceB1);\n"
+" if (lenSqr>FLT_EPSILON)\n"
+" {\n"
+" AppendInc( nGlobalContactsOut, dstIdx );\n"
+" \n"
+" if (dstIdx < maxContactCapacity)\n"
+" {\n"
+" __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];\n"
+" c->m_worldNormalOnB = -normalOnSurfaceB1;\n"
+" c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
+" c->m_batchIdx = pairIndex;\n"
+" c->m_bodyAPtrAndSignBit = rigidBodies[bodyIndexA].m_invMass==0?-bodyIndexA:bodyIndexA;\n"
+" c->m_bodyBPtrAndSignBit = rigidBodies[bodyIndexB].m_invMass==0?-bodyIndexB:bodyIndexB;\n"
+" c->m_worldPosB[0] = pOnB1;\n"
+" c->m_childIndexA = -1;\n"
+" c->m_childIndexB = faceIndex;\n"
+" GET_NPOINTS(*c) = 1;\n"
+" } \n"
+" }\n"
+" }\n"
+" }//if (hasCollision)\n"
+"}\n"
+"// work-in-progress\n"
+"__kernel void findConcaveSphereContactsKernel( __global int4* concavePairs,\n"
+" __global const BodyData* rigidBodies,\n"
+" __global const btCollidableGpu* collidables,\n"
+" __global const ConvexPolyhedronCL* convexShapes, \n"
+" __global const float4* vertices,\n"
+" __global const float4* uniqueEdges,\n"
+" __global const btGpuFace* faces,\n"
+" __global const int* indices,\n"
+" __global btAabbCL* aabbs,\n"
+" __global struct b3Contact4Data* restrict globalContactsOut,\n"
+" counter32_t nGlobalContactsOut,\n"
+" int numConcavePairs, int maxContactCapacity\n"
+" )\n"
+"{\n"
+" int i = get_global_id(0);\n"
+" if (i>=numConcavePairs)\n"
+" return;\n"
+" int pairIdx = i;\n"
+" int bodyIndexA = concavePairs[i].x;\n"
+" int bodyIndexB = concavePairs[i].y;\n"
+" int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
+" int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
+" int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
+" int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
+" if (collidables[collidableIndexB].m_shapeType==SHAPE_SPHERE)\n"
+" {\n"
+" int f = concavePairs[i].z;\n"
+" btGpuFace face = faces[convexShapes[shapeIndexA].m_faceOffset+f];\n"
+" \n"
+" float4 verticesA[3];\n"
+" for (int i=0;i<3;i++)\n"
+" {\n"
+" int index = indices[face.m_indexOffset+i];\n"
+" float4 vert = vertices[convexShapes[shapeIndexA].m_vertexOffset+index];\n"
+" verticesA[i] = vert;\n"
+" }\n"
+" float4 spherePos = rigidBodies[bodyIndexB].m_pos;\n"
+" float sphereRadius = collidables[collidableIndexB].m_radius;\n"
+" float4 convexPos = rigidBodies[bodyIndexA].m_pos;\n"
+" float4 convexOrn = rigidBodies[bodyIndexA].m_quat;\n"
+" computeContactSphereTriangle(i, bodyIndexB, bodyIndexA, collidableIndexB, collidableIndexA, \n"
+" rigidBodies,collidables,\n"
+" verticesA,\n"
+" globalContactsOut, nGlobalContactsOut,maxContactCapacity,\n"
+" spherePos,sphereRadius,convexPos,convexOrn, f);\n"
+" return;\n"
+" }\n"
+"}\n"
+;
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/kernels/sat.cl b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/kernels/sat.cl
new file mode 100644
index 0000000000..a6565fd6fa
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/kernels/sat.cl
@@ -0,0 +1,2018 @@
+//keep this enum in sync with the CPU version (in btCollidable.h)
+//written by Erwin Coumans
+
+
+#define SHAPE_CONVEX_HULL 3
+#define SHAPE_CONCAVE_TRIMESH 5
+#define TRIANGLE_NUM_CONVEX_FACES 5
+#define SHAPE_COMPOUND_OF_CONVEX_HULLS 6
+
+#define B3_MAX_STACK_DEPTH 256
+
+
+typedef unsigned int u32;
+
+///keep this in sync with btCollidable.h
+typedef struct
+{
+ union {
+ int m_numChildShapes;
+ int m_bvhIndex;
+ };
+ union
+ {
+ float m_radius;
+ int m_compoundBvhIndex;
+ };
+
+ int m_shapeType;
+ int m_shapeIndex;
+
+} btCollidableGpu;
+
+#define MAX_NUM_PARTS_IN_BITS 10
+
+///b3QuantizedBvhNode is a compressed aabb node, 16 bytes.
+///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range).
+typedef struct
+{
+ //12 bytes
+ unsigned short int m_quantizedAabbMin[3];
+ unsigned short int m_quantizedAabbMax[3];
+ //4 bytes
+ int m_escapeIndexOrTriangleIndex;
+} b3QuantizedBvhNode;
+
+typedef struct
+{
+ float4 m_aabbMin;
+ float4 m_aabbMax;
+ float4 m_quantization;
+ int m_numNodes;
+ int m_numSubTrees;
+ int m_nodeOffset;
+ int m_subTreeOffset;
+
+} b3BvhInfo;
+
+
+int getTriangleIndex(const b3QuantizedBvhNode* rootNode)
+{
+ unsigned int x=0;
+ unsigned int y = (~(x&0))<<(31-MAX_NUM_PARTS_IN_BITS);
+ // Get only the lower bits where the triangle index is stored
+ return (rootNode->m_escapeIndexOrTriangleIndex&~(y));
+}
+
+int getTriangleIndexGlobal(__global const b3QuantizedBvhNode* rootNode)
+{
+ unsigned int x=0;
+ unsigned int y = (~(x&0))<<(31-MAX_NUM_PARTS_IN_BITS);
+ // Get only the lower bits where the triangle index is stored
+ return (rootNode->m_escapeIndexOrTriangleIndex&~(y));
+}
+
+int isLeafNode(const b3QuantizedBvhNode* rootNode)
+{
+ //skipindex is negative (internal node), triangleindex >=0 (leafnode)
+ return (rootNode->m_escapeIndexOrTriangleIndex >= 0)? 1 : 0;
+}
+
+int isLeafNodeGlobal(__global const b3QuantizedBvhNode* rootNode)
+{
+ //skipindex is negative (internal node), triangleindex >=0 (leafnode)
+ return (rootNode->m_escapeIndexOrTriangleIndex >= 0)? 1 : 0;
+}
+
+int getEscapeIndex(const b3QuantizedBvhNode* rootNode)
+{
+ return -rootNode->m_escapeIndexOrTriangleIndex;
+}
+
+int getEscapeIndexGlobal(__global const b3QuantizedBvhNode* rootNode)
+{
+ return -rootNode->m_escapeIndexOrTriangleIndex;
+}
+
+
+typedef struct
+{
+ //12 bytes
+ unsigned short int m_quantizedAabbMin[3];
+ unsigned short int m_quantizedAabbMax[3];
+ //4 bytes, points to the root of the subtree
+ int m_rootNodeIndex;
+ //4 bytes
+ int m_subtreeSize;
+ int m_padding[3];
+} b3BvhSubtreeInfo;
+
+
+
+
+
+
+
+typedef struct
+{
+ float4 m_childPosition;
+ float4 m_childOrientation;
+ int m_shapeIndex;
+ int m_unused0;
+ int m_unused1;
+ int m_unused2;
+} btGpuChildShape;
+
+
+typedef struct
+{
+ float4 m_pos;
+ float4 m_quat;
+ float4 m_linVel;
+ float4 m_angVel;
+
+ u32 m_collidableIdx;
+ float m_invMass;
+ float m_restituitionCoeff;
+ float m_frictionCoeff;
+} BodyData;
+
+
+typedef struct
+{
+ float4 m_localCenter;
+ float4 m_extents;
+ float4 mC;
+ float4 mE;
+
+ float m_radius;
+ int m_faceOffset;
+ int m_numFaces;
+ int m_numVertices;
+
+ int m_vertexOffset;
+ int m_uniqueEdgesOffset;
+ int m_numUniqueEdges;
+ int m_unused;
+} ConvexPolyhedronCL;
+
+typedef struct
+{
+ union
+ {
+ float4 m_min;
+ float m_minElems[4];
+ int m_minIndices[4];
+ };
+ union
+ {
+ float4 m_max;
+ float m_maxElems[4];
+ int m_maxIndices[4];
+ };
+} btAabbCL;
+
+#include "Bullet3Collision/BroadPhaseCollision/shared/b3Aabb.h"
+#include "Bullet3Common/shared/b3Int2.h"
+
+
+
+typedef struct
+{
+ float4 m_plane;
+ int m_indexOffset;
+ int m_numIndices;
+} btGpuFace;
+
+#define make_float4 (float4)
+
+
+__inline
+float4 cross3(float4 a, float4 b)
+{
+ return cross(a,b);
+
+
+// float4 a1 = make_float4(a.xyz,0.f);
+// float4 b1 = make_float4(b.xyz,0.f);
+
+// return cross(a1,b1);
+
+//float4 c = make_float4(a.y*b.z - a.z*b.y,a.z*b.x - a.x*b.z,a.x*b.y - a.y*b.x,0.f);
+
+ // float4 c = make_float4(a.y*b.z - a.z*b.y,1.f,a.x*b.y - a.y*b.x,0.f);
+
+ //return c;
+}
+
+__inline
+float dot3F4(float4 a, float4 b)
+{
+ float4 a1 = make_float4(a.xyz,0.f);
+ float4 b1 = make_float4(b.xyz,0.f);
+ return dot(a1, b1);
+}
+
+__inline
+float4 fastNormalize4(float4 v)
+{
+ v = make_float4(v.xyz,0.f);
+ return fast_normalize(v);
+}
+
+
+///////////////////////////////////////
+// Quaternion
+///////////////////////////////////////
+
+typedef float4 Quaternion;
+
+__inline
+Quaternion qtMul(Quaternion a, Quaternion b);
+
+__inline
+Quaternion qtNormalize(Quaternion in);
+
+__inline
+float4 qtRotate(Quaternion q, float4 vec);
+
+__inline
+Quaternion qtInvert(Quaternion q);
+
+
+
+
+__inline
+Quaternion qtMul(Quaternion a, Quaternion b)
+{
+ Quaternion ans;
+ ans = cross3( a, b );
+ ans += a.w*b+b.w*a;
+// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);
+ ans.w = a.w*b.w - dot3F4(a, b);
+ return ans;
+}
+
+__inline
+Quaternion qtNormalize(Quaternion in)
+{
+ return fastNormalize4(in);
+// in /= length( in );
+// return in;
+}
+__inline
+float4 qtRotate(Quaternion q, float4 vec)
+{
+ Quaternion qInv = qtInvert( q );
+ float4 vcpy = vec;
+ vcpy.w = 0.f;
+ float4 out = qtMul(qtMul(q,vcpy),qInv);
+ return out;
+}
+
+__inline
+Quaternion qtInvert(Quaternion q)
+{
+ return (Quaternion)(-q.xyz, q.w);
+}
+
+__inline
+float4 qtInvRotate(const Quaternion q, float4 vec)
+{
+ return qtRotate( qtInvert( q ), vec );
+}
+
+__inline
+float4 transform(const float4* p, const float4* translation, const Quaternion* orientation)
+{
+ return qtRotate( *orientation, *p ) + (*translation);
+}
+
+
+
+__inline
+float4 normalize3(const float4 a)
+{
+ float4 n = make_float4(a.x, a.y, a.z, 0.f);
+ return fastNormalize4( n );
+}
+
+inline void projectLocal(const ConvexPolyhedronCL* hull, const float4 pos, const float4 orn,
+const float4* dir, const float4* vertices, float* min, float* max)
+{
+ min[0] = FLT_MAX;
+ max[0] = -FLT_MAX;
+ int numVerts = hull->m_numVertices;
+
+ const float4 localDir = qtInvRotate(orn,*dir);
+ float offset = dot(pos,*dir);
+ for(int i=0;i<numVerts;i++)
+ {
+ float dp = dot(vertices[hull->m_vertexOffset+i],localDir);
+ if(dp < min[0])
+ min[0] = dp;
+ if(dp > max[0])
+ max[0] = dp;
+ }
+ if(min[0]>max[0])
+ {
+ float tmp = min[0];
+ min[0] = max[0];
+ max[0] = tmp;
+ }
+ min[0] += offset;
+ max[0] += offset;
+}
+
+inline void project(__global const ConvexPolyhedronCL* hull, const float4 pos, const float4 orn,
+const float4* dir, __global const float4* vertices, float* min, float* max)
+{
+ min[0] = FLT_MAX;
+ max[0] = -FLT_MAX;
+ int numVerts = hull->m_numVertices;
+
+ const float4 localDir = qtInvRotate(orn,*dir);
+ float offset = dot(pos,*dir);
+ for(int i=0;i<numVerts;i++)
+ {
+ float dp = dot(vertices[hull->m_vertexOffset+i],localDir);
+ if(dp < min[0])
+ min[0] = dp;
+ if(dp > max[0])
+ max[0] = dp;
+ }
+ if(min[0]>max[0])
+ {
+ float tmp = min[0];
+ min[0] = max[0];
+ max[0] = tmp;
+ }
+ min[0] += offset;
+ max[0] += offset;
+}
+
+inline bool TestSepAxisLocalA(const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB,
+ const float4 posA,const float4 ornA,
+ const float4 posB,const float4 ornB,
+ float4* sep_axis, const float4* verticesA, __global const float4* verticesB,float* depth)
+{
+ float Min0,Max0;
+ float Min1,Max1;
+ projectLocal(hullA,posA,ornA,sep_axis,verticesA, &Min0, &Max0);
+ project(hullB,posB,ornB, sep_axis,verticesB, &Min1, &Max1);
+
+ if(Max0<Min1 || Max1<Min0)
+ return false;
+
+ float d0 = Max0 - Min1;
+ float d1 = Max1 - Min0;
+ *depth = d0<d1 ? d0:d1;
+ return true;
+}
+
+
+
+
+inline bool IsAlmostZero(const float4 v)
+{
+ if(fabs(v.x)>1e-6f || fabs(v.y)>1e-6f || fabs(v.z)>1e-6f)
+ return false;
+ return true;
+}
+
+
+
+bool findSeparatingAxisLocalA( const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB,
+ const float4 posA1,
+ const float4 ornA,
+ const float4 posB1,
+ const float4 ornB,
+ const float4 DeltaC2,
+
+ const float4* verticesA,
+ const float4* uniqueEdgesA,
+ const btGpuFace* facesA,
+ const int* indicesA,
+
+ __global const float4* verticesB,
+ __global const float4* uniqueEdgesB,
+ __global const btGpuFace* facesB,
+ __global const int* indicesB,
+ float4* sep,
+ float* dmin)
+{
+
+
+ float4 posA = posA1;
+ posA.w = 0.f;
+ float4 posB = posB1;
+ posB.w = 0.f;
+ int curPlaneTests=0;
+ {
+ int numFacesA = hullA->m_numFaces;
+ // Test normals from hullA
+ for(int i=0;i<numFacesA;i++)
+ {
+ const float4 normal = facesA[hullA->m_faceOffset+i].m_plane;
+ float4 faceANormalWS = qtRotate(ornA,normal);
+ if (dot3F4(DeltaC2,faceANormalWS)<0)
+ faceANormalWS*=-1.f;
+ curPlaneTests++;
+ float d;
+ if(!TestSepAxisLocalA( hullA, hullB, posA,ornA,posB,ornB,&faceANormalWS, verticesA, verticesB,&d))
+ return false;
+ if(d<*dmin)
+ {
+ *dmin = d;
+ *sep = faceANormalWS;
+ }
+ }
+ }
+ if((dot3F4(-DeltaC2,*sep))>0.0f)
+ {
+ *sep = -(*sep);
+ }
+ return true;
+}
+
+bool findSeparatingAxisLocalB( __global const ConvexPolyhedronCL* hullA, const ConvexPolyhedronCL* hullB,
+ const float4 posA1,
+ const float4 ornA,
+ const float4 posB1,
+ const float4 ornB,
+ const float4 DeltaC2,
+ __global const float4* verticesA,
+ __global const float4* uniqueEdgesA,
+ __global const btGpuFace* facesA,
+ __global const int* indicesA,
+ const float4* verticesB,
+ const float4* uniqueEdgesB,
+ const btGpuFace* facesB,
+ const int* indicesB,
+ float4* sep,
+ float* dmin)
+{
+
+
+ float4 posA = posA1;
+ posA.w = 0.f;
+ float4 posB = posB1;
+ posB.w = 0.f;
+ int curPlaneTests=0;
+ {
+ int numFacesA = hullA->m_numFaces;
+ // Test normals from hullA
+ for(int i=0;i<numFacesA;i++)
+ {
+ const float4 normal = facesA[hullA->m_faceOffset+i].m_plane;
+ float4 faceANormalWS = qtRotate(ornA,normal);
+ if (dot3F4(DeltaC2,faceANormalWS)<0)
+ faceANormalWS *= -1.f;
+ curPlaneTests++;
+ float d;
+ if(!TestSepAxisLocalA( hullB, hullA, posB,ornB,posA,ornA, &faceANormalWS, verticesB,verticesA, &d))
+ return false;
+ if(d<*dmin)
+ {
+ *dmin = d;
+ *sep = faceANormalWS;
+ }
+ }
+ }
+ if((dot3F4(-DeltaC2,*sep))>0.0f)
+ {
+ *sep = -(*sep);
+ }
+ return true;
+}
+
+
+
+bool findSeparatingAxisEdgeEdgeLocalA( const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB,
+ const float4 posA1,
+ const float4 ornA,
+ const float4 posB1,
+ const float4 ornB,
+ const float4 DeltaC2,
+ const float4* verticesA,
+ const float4* uniqueEdgesA,
+ const btGpuFace* facesA,
+ const int* indicesA,
+ __global const float4* verticesB,
+ __global const float4* uniqueEdgesB,
+ __global const btGpuFace* facesB,
+ __global const int* indicesB,
+ float4* sep,
+ float* dmin)
+{
+
+
+ float4 posA = posA1;
+ posA.w = 0.f;
+ float4 posB = posB1;
+ posB.w = 0.f;
+
+ int curPlaneTests=0;
+
+ int curEdgeEdge = 0;
+ // Test edges
+ for(int e0=0;e0<hullA->m_numUniqueEdges;e0++)
+ {
+ const float4 edge0 = uniqueEdgesA[hullA->m_uniqueEdgesOffset+e0];
+ float4 edge0World = qtRotate(ornA,edge0);
+
+ for(int e1=0;e1<hullB->m_numUniqueEdges;e1++)
+ {
+ const float4 edge1 = uniqueEdgesB[hullB->m_uniqueEdgesOffset+e1];
+ float4 edge1World = qtRotate(ornB,edge1);
+
+
+ float4 crossje = cross3(edge0World,edge1World);
+
+ curEdgeEdge++;
+ if(!IsAlmostZero(crossje))
+ {
+ crossje = normalize3(crossje);
+ if (dot3F4(DeltaC2,crossje)<0)
+ crossje *= -1.f;
+
+ float dist;
+ bool result = true;
+ {
+ float Min0,Max0;
+ float Min1,Max1;
+ projectLocal(hullA,posA,ornA,&crossje,verticesA, &Min0, &Max0);
+ project(hullB,posB,ornB,&crossje,verticesB, &Min1, &Max1);
+
+ if(Max0<Min1 || Max1<Min0)
+ result = false;
+
+ float d0 = Max0 - Min1;
+ float d1 = Max1 - Min0;
+ dist = d0<d1 ? d0:d1;
+ result = true;
+
+ }
+
+
+ if(dist<*dmin)
+ {
+ *dmin = dist;
+ *sep = crossje;
+ }
+ }
+ }
+
+ }
+
+
+ if((dot3F4(-DeltaC2,*sep))>0.0f)
+ {
+ *sep = -(*sep);
+ }
+ return true;
+}
+
+
+inline bool TestSepAxis(__global const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB,
+ const float4 posA,const float4 ornA,
+ const float4 posB,const float4 ornB,
+ float4* sep_axis, __global const float4* vertices,float* depth)
+{
+ float Min0,Max0;
+ float Min1,Max1;
+ project(hullA,posA,ornA,sep_axis,vertices, &Min0, &Max0);
+ project(hullB,posB,ornB, sep_axis,vertices, &Min1, &Max1);
+
+ if(Max0<Min1 || Max1<Min0)
+ return false;
+
+ float d0 = Max0 - Min1;
+ float d1 = Max1 - Min0;
+ *depth = d0<d1 ? d0:d1;
+ return true;
+}
+
+
+bool findSeparatingAxis( __global const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB,
+ const float4 posA1,
+ const float4 ornA,
+ const float4 posB1,
+ const float4 ornB,
+ const float4 DeltaC2,
+ __global const float4* vertices,
+ __global const float4* uniqueEdges,
+ __global const btGpuFace* faces,
+ __global const int* indices,
+ float4* sep,
+ float* dmin)
+{
+
+
+ float4 posA = posA1;
+ posA.w = 0.f;
+ float4 posB = posB1;
+ posB.w = 0.f;
+
+ int curPlaneTests=0;
+
+ {
+ int numFacesA = hullA->m_numFaces;
+ // Test normals from hullA
+ for(int i=0;i<numFacesA;i++)
+ {
+ const float4 normal = faces[hullA->m_faceOffset+i].m_plane;
+ float4 faceANormalWS = qtRotate(ornA,normal);
+
+ if (dot3F4(DeltaC2,faceANormalWS)<0)
+ faceANormalWS*=-1.f;
+
+ curPlaneTests++;
+
+ float d;
+ if(!TestSepAxis( hullA, hullB, posA,ornA,posB,ornB,&faceANormalWS, vertices,&d))
+ return false;
+
+ if(d<*dmin)
+ {
+ *dmin = d;
+ *sep = faceANormalWS;
+ }
+ }
+ }
+
+
+ if((dot3F4(-DeltaC2,*sep))>0.0f)
+ {
+ *sep = -(*sep);
+ }
+
+ return true;
+}
+
+
+
+
+bool findSeparatingAxisUnitSphere( __global const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB,
+ const float4 posA1,
+ const float4 ornA,
+ const float4 posB1,
+ const float4 ornB,
+ const float4 DeltaC2,
+ __global const float4* vertices,
+ __global const float4* unitSphereDirections,
+ int numUnitSphereDirections,
+ float4* sep,
+ float* dmin)
+{
+
+ float4 posA = posA1;
+ posA.w = 0.f;
+ float4 posB = posB1;
+ posB.w = 0.f;
+
+ int curPlaneTests=0;
+
+ int curEdgeEdge = 0;
+ // Test unit sphere directions
+ for (int i=0;i<numUnitSphereDirections;i++)
+ {
+
+ float4 crossje;
+ crossje = unitSphereDirections[i];
+
+ if (dot3F4(DeltaC2,crossje)>0)
+ crossje *= -1.f;
+ {
+ float dist;
+ bool result = true;
+ float Min0,Max0;
+ float Min1,Max1;
+ project(hullA,posA,ornA,&crossje,vertices, &Min0, &Max0);
+ project(hullB,posB,ornB,&crossje,vertices, &Min1, &Max1);
+
+ if(Max0<Min1 || Max1<Min0)
+ return false;
+
+ float d0 = Max0 - Min1;
+ float d1 = Max1 - Min0;
+ dist = d0<d1 ? d0:d1;
+ result = true;
+
+ if(dist<*dmin)
+ {
+ *dmin = dist;
+ *sep = crossje;
+ }
+ }
+ }
+
+
+ if((dot3F4(-DeltaC2,*sep))>0.0f)
+ {
+ *sep = -(*sep);
+ }
+ return true;
+}
+
+
+bool findSeparatingAxisEdgeEdge( __global const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB,
+ const float4 posA1,
+ const float4 ornA,
+ const float4 posB1,
+ const float4 ornB,
+ const float4 DeltaC2,
+ __global const float4* vertices,
+ __global const float4* uniqueEdges,
+ __global const btGpuFace* faces,
+ __global const int* indices,
+ float4* sep,
+ float* dmin)
+{
+
+
+ float4 posA = posA1;
+ posA.w = 0.f;
+ float4 posB = posB1;
+ posB.w = 0.f;
+
+ int curPlaneTests=0;
+
+ int curEdgeEdge = 0;
+ // Test edges
+ for(int e0=0;e0<hullA->m_numUniqueEdges;e0++)
+ {
+ const float4 edge0 = uniqueEdges[hullA->m_uniqueEdgesOffset+e0];
+ float4 edge0World = qtRotate(ornA,edge0);
+
+ for(int e1=0;e1<hullB->m_numUniqueEdges;e1++)
+ {
+ const float4 edge1 = uniqueEdges[hullB->m_uniqueEdgesOffset+e1];
+ float4 edge1World = qtRotate(ornB,edge1);
+
+
+ float4 crossje = cross3(edge0World,edge1World);
+
+ curEdgeEdge++;
+ if(!IsAlmostZero(crossje))
+ {
+ crossje = normalize3(crossje);
+ if (dot3F4(DeltaC2,crossje)<0)
+ crossje*=-1.f;
+
+ float dist;
+ bool result = true;
+ {
+ float Min0,Max0;
+ float Min1,Max1;
+ project(hullA,posA,ornA,&crossje,vertices, &Min0, &Max0);
+ project(hullB,posB,ornB,&crossje,vertices, &Min1, &Max1);
+
+ if(Max0<Min1 || Max1<Min0)
+ return false;
+
+ float d0 = Max0 - Min1;
+ float d1 = Max1 - Min0;
+ dist = d0<d1 ? d0:d1;
+ result = true;
+
+ }
+
+
+ if(dist<*dmin)
+ {
+ *dmin = dist;
+ *sep = crossje;
+ }
+ }
+ }
+
+ }
+
+
+ if((dot3F4(-DeltaC2,*sep))>0.0f)
+ {
+ *sep = -(*sep);
+ }
+ return true;
+}
+
+
+// work-in-progress
+__kernel void processCompoundPairsKernel( __global const int4* gpuCompoundPairs,
+ __global const BodyData* rigidBodies,
+ __global const btCollidableGpu* collidables,
+ __global const ConvexPolyhedronCL* convexShapes,
+ __global const float4* vertices,
+ __global const float4* uniqueEdges,
+ __global const btGpuFace* faces,
+ __global const int* indices,
+ __global btAabbCL* aabbs,
+ __global const btGpuChildShape* gpuChildShapes,
+ __global volatile float4* gpuCompoundSepNormalsOut,
+ __global volatile int* gpuHasCompoundSepNormalsOut,
+ int numCompoundPairs
+ )
+{
+
+ int i = get_global_id(0);
+ if (i<numCompoundPairs)
+ {
+ int bodyIndexA = gpuCompoundPairs[i].x;
+ int bodyIndexB = gpuCompoundPairs[i].y;
+
+ int childShapeIndexA = gpuCompoundPairs[i].z;
+ int childShapeIndexB = gpuCompoundPairs[i].w;
+
+ int collidableIndexA = -1;
+ int collidableIndexB = -1;
+
+ float4 ornA = rigidBodies[bodyIndexA].m_quat;
+ float4 posA = rigidBodies[bodyIndexA].m_pos;
+
+ float4 ornB = rigidBodies[bodyIndexB].m_quat;
+ float4 posB = rigidBodies[bodyIndexB].m_pos;
+
+ if (childShapeIndexA >= 0)
+ {
+ collidableIndexA = gpuChildShapes[childShapeIndexA].m_shapeIndex;
+ float4 childPosA = gpuChildShapes[childShapeIndexA].m_childPosition;
+ float4 childOrnA = gpuChildShapes[childShapeIndexA].m_childOrientation;
+ float4 newPosA = qtRotate(ornA,childPosA)+posA;
+ float4 newOrnA = qtMul(ornA,childOrnA);
+ posA = newPosA;
+ ornA = newOrnA;
+ } else
+ {
+ collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
+ }
+
+ if (childShapeIndexB>=0)
+ {
+ collidableIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;
+ float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;
+ float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;
+ float4 newPosB = transform(&childPosB,&posB,&ornB);
+ float4 newOrnB = qtMul(ornB,childOrnB);
+ posB = newPosB;
+ ornB = newOrnB;
+ } else
+ {
+ collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
+ }
+
+ gpuHasCompoundSepNormalsOut[i] = 0;
+
+ int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
+ int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
+
+ int shapeTypeA = collidables[collidableIndexA].m_shapeType;
+ int shapeTypeB = collidables[collidableIndexB].m_shapeType;
+
+
+ if ((shapeTypeA != SHAPE_CONVEX_HULL) || (shapeTypeB != SHAPE_CONVEX_HULL))
+ {
+ return;
+ }
+
+ int hasSeparatingAxis = 5;
+
+ int numFacesA = convexShapes[shapeIndexA].m_numFaces;
+ float dmin = FLT_MAX;
+ posA.w = 0.f;
+ posB.w = 0.f;
+ float4 c0local = convexShapes[shapeIndexA].m_localCenter;
+ float4 c0 = transform(&c0local, &posA, &ornA);
+ float4 c1local = convexShapes[shapeIndexB].m_localCenter;
+ float4 c1 = transform(&c1local,&posB,&ornB);
+ const float4 DeltaC2 = c0 - c1;
+ float4 sepNormal = make_float4(1,0,0,0);
+ bool sepA = findSeparatingAxis( &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,posB,ornB,DeltaC2,vertices,uniqueEdges,faces,indices,&sepNormal,&dmin);
+ hasSeparatingAxis = 4;
+ if (!sepA)
+ {
+ hasSeparatingAxis = 0;
+ } else
+ {
+ bool sepB = findSeparatingAxis( &convexShapes[shapeIndexB],&convexShapes[shapeIndexA],posB,ornB,posA,ornA,DeltaC2,vertices,uniqueEdges,faces,indices,&sepNormal,&dmin);
+
+ if (!sepB)
+ {
+ hasSeparatingAxis = 0;
+ } else//(!sepB)
+ {
+ bool sepEE = findSeparatingAxisEdgeEdge( &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,posB,ornB,DeltaC2,vertices,uniqueEdges,faces,indices,&sepNormal,&dmin);
+ if (sepEE)
+ {
+ gpuCompoundSepNormalsOut[i] = sepNormal;//fastNormalize4(sepNormal);
+ gpuHasCompoundSepNormalsOut[i] = 1;
+ }//sepEE
+ }//(!sepB)
+ }//(!sepA)
+
+
+ }
+
+}
+
+
+inline b3Float4 MyUnQuantize(const unsigned short* vecIn, b3Float4 quantization, b3Float4 bvhAabbMin)
+{
+ b3Float4 vecOut;
+ vecOut = b3MakeFloat4(
+ (float)(vecIn[0]) / (quantization.x),
+ (float)(vecIn[1]) / (quantization.y),
+ (float)(vecIn[2]) / (quantization.z),
+ 0.f);
+
+ vecOut += bvhAabbMin;
+ return vecOut;
+}
+
+inline b3Float4 MyUnQuantizeGlobal(__global const unsigned short* vecIn, b3Float4 quantization, b3Float4 bvhAabbMin)
+{
+ b3Float4 vecOut;
+ vecOut = b3MakeFloat4(
+ (float)(vecIn[0]) / (quantization.x),
+ (float)(vecIn[1]) / (quantization.y),
+ (float)(vecIn[2]) / (quantization.z),
+ 0.f);
+
+ vecOut += bvhAabbMin;
+ return vecOut;
+}
+
+
+// work-in-progress
+__kernel void findCompoundPairsKernel( __global const int4* pairs,
+ __global const BodyData* rigidBodies,
+ __global const btCollidableGpu* collidables,
+ __global const ConvexPolyhedronCL* convexShapes,
+ __global const float4* vertices,
+ __global const float4* uniqueEdges,
+ __global const btGpuFace* faces,
+ __global const int* indices,
+ __global b3Aabb_t* aabbLocalSpace,
+ __global const btGpuChildShape* gpuChildShapes,
+ __global volatile int4* gpuCompoundPairsOut,
+ __global volatile int* numCompoundPairsOut,
+ __global const b3BvhSubtreeInfo* subtrees,
+ __global const b3QuantizedBvhNode* quantizedNodes,
+ __global const b3BvhInfo* bvhInfos,
+ int numPairs,
+ int maxNumCompoundPairsCapacity
+ )
+{
+
+ int i = get_global_id(0);
+
+ if (i<numPairs)
+ {
+ int bodyIndexA = pairs[i].x;
+ int bodyIndexB = pairs[i].y;
+
+ int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
+ int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
+
+ int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
+ int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
+
+
+ //once the broadphase avoids static-static pairs, we can remove this test
+ if ((rigidBodies[bodyIndexA].m_invMass==0) &&(rigidBodies[bodyIndexB].m_invMass==0))
+ {
+ return;
+ }
+
+ if ((collidables[collidableIndexA].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS) &&(collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS))
+ {
+ int bvhA = collidables[collidableIndexA].m_compoundBvhIndex;
+ int bvhB = collidables[collidableIndexB].m_compoundBvhIndex;
+ int numSubTreesA = bvhInfos[bvhA].m_numSubTrees;
+ int subTreesOffsetA = bvhInfos[bvhA].m_subTreeOffset;
+ int subTreesOffsetB = bvhInfos[bvhB].m_subTreeOffset;
+
+
+ int numSubTreesB = bvhInfos[bvhB].m_numSubTrees;
+
+ float4 posA = rigidBodies[bodyIndexA].m_pos;
+ b3Quat ornA = rigidBodies[bodyIndexA].m_quat;
+
+ b3Quat ornB = rigidBodies[bodyIndexB].m_quat;
+ float4 posB = rigidBodies[bodyIndexB].m_pos;
+
+
+ for (int p=0;p<numSubTreesA;p++)
+ {
+ b3BvhSubtreeInfo subtreeA = subtrees[subTreesOffsetA+p];
+ //bvhInfos[bvhA].m_quantization
+ b3Float4 treeAminLocal = MyUnQuantize(subtreeA.m_quantizedAabbMin,bvhInfos[bvhA].m_quantization,bvhInfos[bvhA].m_aabbMin);
+ b3Float4 treeAmaxLocal = MyUnQuantize(subtreeA.m_quantizedAabbMax,bvhInfos[bvhA].m_quantization,bvhInfos[bvhA].m_aabbMin);
+
+ b3Float4 aabbAMinOut,aabbAMaxOut;
+ float margin=0.f;
+ b3TransformAabb2(treeAminLocal,treeAmaxLocal, margin,posA,ornA,&aabbAMinOut,&aabbAMaxOut);
+
+ for (int q=0;q<numSubTreesB;q++)
+ {
+ b3BvhSubtreeInfo subtreeB = subtrees[subTreesOffsetB+q];
+
+ b3Float4 treeBminLocal = MyUnQuantize(subtreeB.m_quantizedAabbMin,bvhInfos[bvhB].m_quantization,bvhInfos[bvhB].m_aabbMin);
+ b3Float4 treeBmaxLocal = MyUnQuantize(subtreeB.m_quantizedAabbMax,bvhInfos[bvhB].m_quantization,bvhInfos[bvhB].m_aabbMin);
+
+ b3Float4 aabbBMinOut,aabbBMaxOut;
+ float margin=0.f;
+ b3TransformAabb2(treeBminLocal,treeBmaxLocal, margin,posB,ornB,&aabbBMinOut,&aabbBMaxOut);
+
+
+
+ bool aabbOverlap = b3TestAabbAgainstAabb(aabbAMinOut,aabbAMaxOut,aabbBMinOut,aabbBMaxOut);
+ if (aabbOverlap)
+ {
+
+ int startNodeIndexA = subtreeA.m_rootNodeIndex+bvhInfos[bvhA].m_nodeOffset;
+ int endNodeIndexA = startNodeIndexA+subtreeA.m_subtreeSize;
+
+ int startNodeIndexB = subtreeB.m_rootNodeIndex+bvhInfos[bvhB].m_nodeOffset;
+ int endNodeIndexB = startNodeIndexB+subtreeB.m_subtreeSize;
+
+
+ b3Int2 nodeStack[B3_MAX_STACK_DEPTH];
+ b3Int2 node0;
+ node0.x = startNodeIndexA;
+ node0.y = startNodeIndexB;
+ int maxStackDepth = B3_MAX_STACK_DEPTH;
+ int depth=0;
+ nodeStack[depth++]=node0;
+
+ do
+ {
+ b3Int2 node = nodeStack[--depth];
+
+ b3Float4 aMinLocal = MyUnQuantizeGlobal(quantizedNodes[node.x].m_quantizedAabbMin,bvhInfos[bvhA].m_quantization,bvhInfos[bvhA].m_aabbMin);
+ b3Float4 aMaxLocal = MyUnQuantizeGlobal(quantizedNodes[node.x].m_quantizedAabbMax,bvhInfos[bvhA].m_quantization,bvhInfos[bvhA].m_aabbMin);
+
+ b3Float4 bMinLocal = MyUnQuantizeGlobal(quantizedNodes[node.y].m_quantizedAabbMin,bvhInfos[bvhB].m_quantization,bvhInfos[bvhB].m_aabbMin);
+ b3Float4 bMaxLocal = MyUnQuantizeGlobal(quantizedNodes[node.y].m_quantizedAabbMax,bvhInfos[bvhB].m_quantization,bvhInfos[bvhB].m_aabbMin);
+
+ float margin=0.f;
+ b3Float4 aabbAMinOut,aabbAMaxOut;
+ b3TransformAabb2(aMinLocal,aMaxLocal, margin,posA,ornA,&aabbAMinOut,&aabbAMaxOut);
+
+ b3Float4 aabbBMinOut,aabbBMaxOut;
+ b3TransformAabb2(bMinLocal,bMaxLocal, margin,posB,ornB,&aabbBMinOut,&aabbBMaxOut);
+
+
+ bool nodeOverlap = b3TestAabbAgainstAabb(aabbAMinOut,aabbAMaxOut,aabbBMinOut,aabbBMaxOut);
+ if (nodeOverlap)
+ {
+ bool isLeafA = isLeafNodeGlobal(&quantizedNodes[node.x]);
+ bool isLeafB = isLeafNodeGlobal(&quantizedNodes[node.y]);
+ bool isInternalA = !isLeafA;
+ bool isInternalB = !isLeafB;
+
+ //fail, even though it might hit two leaf nodes
+ if (depth+4>maxStackDepth && !(isLeafA && isLeafB))
+ {
+ //printf("Error: traversal exceeded maxStackDepth");
+ continue;
+ }
+
+ if(isInternalA)
+ {
+ int nodeAleftChild = node.x+1;
+ bool isNodeALeftChildLeaf = isLeafNodeGlobal(&quantizedNodes[node.x+1]);
+ int nodeArightChild = isNodeALeftChildLeaf? node.x+2 : node.x+1 + getEscapeIndexGlobal(&quantizedNodes[node.x+1]);
+
+ if(isInternalB)
+ {
+ int nodeBleftChild = node.y+1;
+ bool isNodeBLeftChildLeaf = isLeafNodeGlobal(&quantizedNodes[node.y+1]);
+ int nodeBrightChild = isNodeBLeftChildLeaf? node.y+2 : node.y+1 + getEscapeIndexGlobal(&quantizedNodes[node.y+1]);
+
+ nodeStack[depth++] = b3MakeInt2(nodeAleftChild, nodeBleftChild);
+ nodeStack[depth++] = b3MakeInt2(nodeArightChild, nodeBleftChild);
+ nodeStack[depth++] = b3MakeInt2(nodeAleftChild, nodeBrightChild);
+ nodeStack[depth++] = b3MakeInt2(nodeArightChild, nodeBrightChild);
+ }
+ else
+ {
+ nodeStack[depth++] = b3MakeInt2(nodeAleftChild,node.y);
+ nodeStack[depth++] = b3MakeInt2(nodeArightChild,node.y);
+ }
+ }
+ else
+ {
+ if(isInternalB)
+ {
+ int nodeBleftChild = node.y+1;
+ bool isNodeBLeftChildLeaf = isLeafNodeGlobal(&quantizedNodes[node.y+1]);
+ int nodeBrightChild = isNodeBLeftChildLeaf? node.y+2 : node.y+1 + getEscapeIndexGlobal(&quantizedNodes[node.y+1]);
+ nodeStack[depth++] = b3MakeInt2(node.x,nodeBleftChild);
+ nodeStack[depth++] = b3MakeInt2(node.x,nodeBrightChild);
+ }
+ else
+ {
+ int compoundPairIdx = atomic_inc(numCompoundPairsOut);
+ if (compoundPairIdx<maxNumCompoundPairsCapacity)
+ {
+ int childShapeIndexA = getTriangleIndexGlobal(&quantizedNodes[node.x]);
+ int childShapeIndexB = getTriangleIndexGlobal(&quantizedNodes[node.y]);
+ gpuCompoundPairsOut[compoundPairIdx] = (int4)(bodyIndexA,bodyIndexB,childShapeIndexA,childShapeIndexB);
+ }
+ }
+ }
+ }
+ } while (depth);
+ }
+ }
+ }
+
+ return;
+ }
+
+
+
+
+
+ if ((collidables[collidableIndexA].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS) ||(collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS))
+ {
+
+ if (collidables[collidableIndexA].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)
+ {
+
+ int numChildrenA = collidables[collidableIndexA].m_numChildShapes;
+ for (int c=0;c<numChildrenA;c++)
+ {
+ int childShapeIndexA = collidables[collidableIndexA].m_shapeIndex+c;
+ int childColIndexA = gpuChildShapes[childShapeIndexA].m_shapeIndex;
+
+ float4 posA = rigidBodies[bodyIndexA].m_pos;
+ float4 ornA = rigidBodies[bodyIndexA].m_quat;
+ float4 childPosA = gpuChildShapes[childShapeIndexA].m_childPosition;
+ float4 childOrnA = gpuChildShapes[childShapeIndexA].m_childOrientation;
+ float4 newPosA = qtRotate(ornA,childPosA)+posA;
+ float4 newOrnA = qtMul(ornA,childOrnA);
+
+ int shapeIndexA = collidables[childColIndexA].m_shapeIndex;
+ b3Aabb_t aabbAlocal = aabbLocalSpace[shapeIndexA];
+ float margin = 0.f;
+
+ b3Float4 aabbAMinWS;
+ b3Float4 aabbAMaxWS;
+
+ b3TransformAabb2(aabbAlocal.m_minVec,aabbAlocal.m_maxVec,margin,
+ newPosA,
+ newOrnA,
+ &aabbAMinWS,&aabbAMaxWS);
+
+
+ if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)
+ {
+ int numChildrenB = collidables[collidableIndexB].m_numChildShapes;
+ for (int b=0;b<numChildrenB;b++)
+ {
+ int childShapeIndexB = collidables[collidableIndexB].m_shapeIndex+b;
+ int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;
+ float4 ornB = rigidBodies[bodyIndexB].m_quat;
+ float4 posB = rigidBodies[bodyIndexB].m_pos;
+ float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;
+ float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;
+ float4 newPosB = transform(&childPosB,&posB,&ornB);
+ float4 newOrnB = qtMul(ornB,childOrnB);
+
+ int shapeIndexB = collidables[childColIndexB].m_shapeIndex;
+ b3Aabb_t aabbBlocal = aabbLocalSpace[shapeIndexB];
+
+ b3Float4 aabbBMinWS;
+ b3Float4 aabbBMaxWS;
+
+ b3TransformAabb2(aabbBlocal.m_minVec,aabbBlocal.m_maxVec,margin,
+ newPosB,
+ newOrnB,
+ &aabbBMinWS,&aabbBMaxWS);
+
+
+
+ bool aabbOverlap = b3TestAabbAgainstAabb(aabbAMinWS,aabbAMaxWS,aabbBMinWS,aabbBMaxWS);
+ if (aabbOverlap)
+ {
+ int numFacesA = convexShapes[shapeIndexA].m_numFaces;
+ float dmin = FLT_MAX;
+ float4 posA = newPosA;
+ posA.w = 0.f;
+ float4 posB = newPosB;
+ posB.w = 0.f;
+ float4 c0local = convexShapes[shapeIndexA].m_localCenter;
+ float4 ornA = newOrnA;
+ float4 c0 = transform(&c0local, &posA, &ornA);
+ float4 c1local = convexShapes[shapeIndexB].m_localCenter;
+ float4 ornB =newOrnB;
+ float4 c1 = transform(&c1local,&posB,&ornB);
+ const float4 DeltaC2 = c0 - c1;
+
+ {//
+ int compoundPairIdx = atomic_inc(numCompoundPairsOut);
+ if (compoundPairIdx<maxNumCompoundPairsCapacity)
+ {
+ gpuCompoundPairsOut[compoundPairIdx] = (int4)(bodyIndexA,bodyIndexB,childShapeIndexA,childShapeIndexB);
+ }
+ }//
+ }//fi(1)
+ } //for (int b=0
+ }//if (collidables[collidableIndexB].
+ else//if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)
+ {
+ if (1)
+ {
+ int numFacesA = convexShapes[shapeIndexA].m_numFaces;
+ float dmin = FLT_MAX;
+ float4 posA = newPosA;
+ posA.w = 0.f;
+ float4 posB = rigidBodies[bodyIndexB].m_pos;
+ posB.w = 0.f;
+ float4 c0local = convexShapes[shapeIndexA].m_localCenter;
+ float4 ornA = newOrnA;
+ float4 c0 = transform(&c0local, &posA, &ornA);
+ float4 c1local = convexShapes[shapeIndexB].m_localCenter;
+ float4 ornB = rigidBodies[bodyIndexB].m_quat;
+ float4 c1 = transform(&c1local,&posB,&ornB);
+ const float4 DeltaC2 = c0 - c1;
+
+ {
+ int compoundPairIdx = atomic_inc(numCompoundPairsOut);
+ if (compoundPairIdx<maxNumCompoundPairsCapacity)
+ {
+ gpuCompoundPairsOut[compoundPairIdx] = (int4)(bodyIndexA,bodyIndexB,childShapeIndexA,-1);
+ }//if (compoundPairIdx<maxNumCompoundPairsCapacity)
+ }//
+ }//fi (1)
+ }//if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)
+ }//for (int b=0;b<numChildrenB;b++)
+ return;
+ }//if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)
+ if ((collidables[collidableIndexA].m_shapeType!=SHAPE_CONCAVE_TRIMESH)
+ && (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS))
+ {
+ int numChildrenB = collidables[collidableIndexB].m_numChildShapes;
+ for (int b=0;b<numChildrenB;b++)
+ {
+ int childShapeIndexB = collidables[collidableIndexB].m_shapeIndex+b;
+ int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;
+ float4 ornB = rigidBodies[bodyIndexB].m_quat;
+ float4 posB = rigidBodies[bodyIndexB].m_pos;
+ float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;
+ float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;
+ float4 newPosB = qtRotate(ornB,childPosB)+posB;
+ float4 newOrnB = qtMul(ornB,childOrnB);
+
+ int shapeIndexB = collidables[childColIndexB].m_shapeIndex;
+
+
+ //////////////////////////////////////
+
+ if (1)
+ {
+ int numFacesA = convexShapes[shapeIndexA].m_numFaces;
+ float dmin = FLT_MAX;
+ float4 posA = rigidBodies[bodyIndexA].m_pos;
+ posA.w = 0.f;
+ float4 posB = newPosB;
+ posB.w = 0.f;
+ float4 c0local = convexShapes[shapeIndexA].m_localCenter;
+ float4 ornA = rigidBodies[bodyIndexA].m_quat;
+ float4 c0 = transform(&c0local, &posA, &ornA);
+ float4 c1local = convexShapes[shapeIndexB].m_localCenter;
+ float4 ornB =newOrnB;
+ float4 c1 = transform(&c1local,&posB,&ornB);
+ const float4 DeltaC2 = c0 - c1;
+ {//
+ int compoundPairIdx = atomic_inc(numCompoundPairsOut);
+ if (compoundPairIdx<maxNumCompoundPairsCapacity)
+ {
+ gpuCompoundPairsOut[compoundPairIdx] = (int4)(bodyIndexA,bodyIndexB,-1,childShapeIndexB);
+ }//fi (compoundPairIdx<maxNumCompoundPairsCapacity)
+ }//
+ }//fi (1)
+ }//for (int b=0;b<numChildrenB;b++)
+ return;
+ }//if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)
+ return;
+ }//fi ((collidables[collidableIndexA].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS) ||(collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS))
+ }//i<numPairs
+}
+
+// work-in-progress
+__kernel void findSeparatingAxisKernel( __global const int4* pairs,
+ __global const BodyData* rigidBodies,
+ __global const btCollidableGpu* collidables,
+ __global const ConvexPolyhedronCL* convexShapes,
+ __global const float4* vertices,
+ __global const float4* uniqueEdges,
+ __global const btGpuFace* faces,
+ __global const int* indices,
+ __global btAabbCL* aabbs,
+ __global volatile float4* separatingNormals,
+ __global volatile int* hasSeparatingAxis,
+ int numPairs
+ )
+{
+
+ int i = get_global_id(0);
+
+ if (i<numPairs)
+ {
+
+
+ int bodyIndexA = pairs[i].x;
+ int bodyIndexB = pairs[i].y;
+
+ int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
+ int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
+
+ int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
+ int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
+
+
+ //once the broadphase avoids static-static pairs, we can remove this test
+ if ((rigidBodies[bodyIndexA].m_invMass==0) &&(rigidBodies[bodyIndexB].m_invMass==0))
+ {
+ hasSeparatingAxis[i] = 0;
+ return;
+ }
+
+
+ if ((collidables[collidableIndexA].m_shapeType!=SHAPE_CONVEX_HULL) ||(collidables[collidableIndexB].m_shapeType!=SHAPE_CONVEX_HULL))
+ {
+ hasSeparatingAxis[i] = 0;
+ return;
+ }
+
+ if ((collidables[collidableIndexA].m_shapeType==SHAPE_CONCAVE_TRIMESH))
+ {
+ hasSeparatingAxis[i] = 0;
+ return;
+ }
+
+ int numFacesA = convexShapes[shapeIndexA].m_numFaces;
+
+ float dmin = FLT_MAX;
+
+ float4 posA = rigidBodies[bodyIndexA].m_pos;
+ posA.w = 0.f;
+ float4 posB = rigidBodies[bodyIndexB].m_pos;
+ posB.w = 0.f;
+ float4 c0local = convexShapes[shapeIndexA].m_localCenter;
+ float4 ornA = rigidBodies[bodyIndexA].m_quat;
+ float4 c0 = transform(&c0local, &posA, &ornA);
+ float4 c1local = convexShapes[shapeIndexB].m_localCenter;
+ float4 ornB =rigidBodies[bodyIndexB].m_quat;
+ float4 c1 = transform(&c1local,&posB,&ornB);
+ const float4 DeltaC2 = c0 - c1;
+ float4 sepNormal;
+
+ bool sepA = findSeparatingAxis( &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,
+ posB,ornB,
+ DeltaC2,
+ vertices,uniqueEdges,faces,
+ indices,&sepNormal,&dmin);
+ hasSeparatingAxis[i] = 4;
+ if (!sepA)
+ {
+ hasSeparatingAxis[i] = 0;
+ } else
+ {
+ bool sepB = findSeparatingAxis( &convexShapes[shapeIndexB],&convexShapes[shapeIndexA],posB,ornB,
+ posA,ornA,
+ DeltaC2,
+ vertices,uniqueEdges,faces,
+ indices,&sepNormal,&dmin);
+
+ if (!sepB)
+ {
+ hasSeparatingAxis[i] = 0;
+ } else
+ {
+ bool sepEE = findSeparatingAxisEdgeEdge( &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,
+ posB,ornB,
+ DeltaC2,
+ vertices,uniqueEdges,faces,
+ indices,&sepNormal,&dmin);
+ if (!sepEE)
+ {
+ hasSeparatingAxis[i] = 0;
+ } else
+ {
+ hasSeparatingAxis[i] = 1;
+ separatingNormals[i] = sepNormal;
+ }
+ }
+ }
+
+ }
+
+}
+
+
+__kernel void findSeparatingAxisVertexFaceKernel( __global const int4* pairs,
+ __global const BodyData* rigidBodies,
+ __global const btCollidableGpu* collidables,
+ __global const ConvexPolyhedronCL* convexShapes,
+ __global const float4* vertices,
+ __global const float4* uniqueEdges,
+ __global const btGpuFace* faces,
+ __global const int* indices,
+ __global btAabbCL* aabbs,
+ __global volatile float4* separatingNormals,
+ __global volatile int* hasSeparatingAxis,
+ __global float* dmins,
+ int numPairs
+ )
+{
+
+ int i = get_global_id(0);
+
+ if (i<numPairs)
+ {
+
+
+ int bodyIndexA = pairs[i].x;
+ int bodyIndexB = pairs[i].y;
+
+ int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
+ int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
+
+ int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
+ int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
+
+ hasSeparatingAxis[i] = 0;
+
+ //once the broadphase avoids static-static pairs, we can remove this test
+ if ((rigidBodies[bodyIndexA].m_invMass==0) &&(rigidBodies[bodyIndexB].m_invMass==0))
+ {
+ return;
+ }
+
+
+ if ((collidables[collidableIndexA].m_shapeType!=SHAPE_CONVEX_HULL) ||(collidables[collidableIndexB].m_shapeType!=SHAPE_CONVEX_HULL))
+ {
+ return;
+ }
+
+
+ int numFacesA = convexShapes[shapeIndexA].m_numFaces;
+
+ float dmin = FLT_MAX;
+
+ dmins[i] = dmin;
+
+ float4 posA = rigidBodies[bodyIndexA].m_pos;
+ posA.w = 0.f;
+ float4 posB = rigidBodies[bodyIndexB].m_pos;
+ posB.w = 0.f;
+ float4 c0local = convexShapes[shapeIndexA].m_localCenter;
+ float4 ornA = rigidBodies[bodyIndexA].m_quat;
+ float4 c0 = transform(&c0local, &posA, &ornA);
+ float4 c1local = convexShapes[shapeIndexB].m_localCenter;
+ float4 ornB =rigidBodies[bodyIndexB].m_quat;
+ float4 c1 = transform(&c1local,&posB,&ornB);
+ const float4 DeltaC2 = c0 - c1;
+ float4 sepNormal;
+
+ bool sepA = findSeparatingAxis( &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,
+ posB,ornB,
+ DeltaC2,
+ vertices,uniqueEdges,faces,
+ indices,&sepNormal,&dmin);
+ hasSeparatingAxis[i] = 4;
+ if (!sepA)
+ {
+ hasSeparatingAxis[i] = 0;
+ } else
+ {
+ bool sepB = findSeparatingAxis( &convexShapes[shapeIndexB],&convexShapes[shapeIndexA],posB,ornB,
+ posA,ornA,
+ DeltaC2,
+ vertices,uniqueEdges,faces,
+ indices,&sepNormal,&dmin);
+
+ if (sepB)
+ {
+ dmins[i] = dmin;
+ hasSeparatingAxis[i] = 1;
+ separatingNormals[i] = sepNormal;
+ }
+ }
+
+ }
+
+}
+
+
+__kernel void findSeparatingAxisEdgeEdgeKernel( __global const int4* pairs,
+ __global const BodyData* rigidBodies,
+ __global const btCollidableGpu* collidables,
+ __global const ConvexPolyhedronCL* convexShapes,
+ __global const float4* vertices,
+ __global const float4* uniqueEdges,
+ __global const btGpuFace* faces,
+ __global const int* indices,
+ __global btAabbCL* aabbs,
+ __global float4* separatingNormals,
+ __global int* hasSeparatingAxis,
+ __global float* dmins,
+ __global const float4* unitSphereDirections,
+ int numUnitSphereDirections,
+ int numPairs
+ )
+{
+
+ int i = get_global_id(0);
+
+ if (i<numPairs)
+ {
+
+ if (hasSeparatingAxis[i])
+ {
+
+ int bodyIndexA = pairs[i].x;
+ int bodyIndexB = pairs[i].y;
+
+ int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
+ int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
+
+ int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
+ int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
+
+
+ int numFacesA = convexShapes[shapeIndexA].m_numFaces;
+
+ float dmin = dmins[i];
+
+ float4 posA = rigidBodies[bodyIndexA].m_pos;
+ posA.w = 0.f;
+ float4 posB = rigidBodies[bodyIndexB].m_pos;
+ posB.w = 0.f;
+ float4 c0local = convexShapes[shapeIndexA].m_localCenter;
+ float4 ornA = rigidBodies[bodyIndexA].m_quat;
+ float4 c0 = transform(&c0local, &posA, &ornA);
+ float4 c1local = convexShapes[shapeIndexB].m_localCenter;
+ float4 ornB =rigidBodies[bodyIndexB].m_quat;
+ float4 c1 = transform(&c1local,&posB,&ornB);
+ const float4 DeltaC2 = c0 - c1;
+ float4 sepNormal = separatingNormals[i];
+
+
+
+ bool sepEE = false;
+ int numEdgeEdgeDirections = convexShapes[shapeIndexA].m_numUniqueEdges*convexShapes[shapeIndexB].m_numUniqueEdges;
+ if (numEdgeEdgeDirections<=numUnitSphereDirections)
+ {
+ sepEE = findSeparatingAxisEdgeEdge( &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,
+ posB,ornB,
+ DeltaC2,
+ vertices,uniqueEdges,faces,
+ indices,&sepNormal,&dmin);
+
+ if (!sepEE)
+ {
+ hasSeparatingAxis[i] = 0;
+ } else
+ {
+ hasSeparatingAxis[i] = 1;
+ separatingNormals[i] = sepNormal;
+ }
+ }
+ /*
+ ///else case is a separate kernel, to make Mac OSX OpenCL compiler happy
+ else
+ {
+ sepEE = findSeparatingAxisUnitSphere(&convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,
+ posB,ornB,
+ DeltaC2,
+ vertices,unitSphereDirections,numUnitSphereDirections,
+ &sepNormal,&dmin);
+ if (!sepEE)
+ {
+ hasSeparatingAxis[i] = 0;
+ } else
+ {
+ hasSeparatingAxis[i] = 1;
+ separatingNormals[i] = sepNormal;
+ }
+ }
+ */
+ } //if (hasSeparatingAxis[i])
+ }//(i<numPairs)
+}
+
+
+
+
+
+inline int findClippingFaces(const float4 separatingNormal,
+ const ConvexPolyhedronCL* hullA,
+ __global const ConvexPolyhedronCL* hullB,
+ const float4 posA, const Quaternion ornA,const float4 posB, const Quaternion ornB,
+ __global float4* worldVertsA1,
+ __global float4* worldNormalsA1,
+ __global float4* worldVertsB1,
+ int capacityWorldVerts,
+ const float minDist, float maxDist,
+ const float4* verticesA,
+ const btGpuFace* facesA,
+ const int* indicesA,
+ __global const float4* verticesB,
+ __global const btGpuFace* facesB,
+ __global const int* indicesB,
+ __global int4* clippingFaces, int pairIndex)
+{
+ int numContactsOut = 0;
+ int numWorldVertsB1= 0;
+
+
+ int closestFaceB=0;
+ float dmax = -FLT_MAX;
+
+ {
+ for(int face=0;face<hullB->m_numFaces;face++)
+ {
+ const float4 Normal = make_float4(facesB[hullB->m_faceOffset+face].m_plane.x,
+ facesB[hullB->m_faceOffset+face].m_plane.y, facesB[hullB->m_faceOffset+face].m_plane.z,0.f);
+ const float4 WorldNormal = qtRotate(ornB, Normal);
+ float d = dot3F4(WorldNormal,separatingNormal);
+ if (d > dmax)
+ {
+ dmax = d;
+ closestFaceB = face;
+ }
+ }
+ }
+
+ {
+ const btGpuFace polyB = facesB[hullB->m_faceOffset+closestFaceB];
+ int numVertices = polyB.m_numIndices;
+ if (numVertices>capacityWorldVerts)
+ numVertices = capacityWorldVerts;
+
+ for(int e0=0;e0<numVertices;e0++)
+ {
+ if (e0<capacityWorldVerts)
+ {
+ const float4 b = verticesB[hullB->m_vertexOffset+indicesB[polyB.m_indexOffset+e0]];
+ worldVertsB1[pairIndex*capacityWorldVerts+numWorldVertsB1++] = transform(&b,&posB,&ornB);
+ }
+ }
+ }
+
+ int closestFaceA=0;
+ {
+ float dmin = FLT_MAX;
+ for(int face=0;face<hullA->m_numFaces;face++)
+ {
+ const float4 Normal = make_float4(
+ facesA[hullA->m_faceOffset+face].m_plane.x,
+ facesA[hullA->m_faceOffset+face].m_plane.y,
+ facesA[hullA->m_faceOffset+face].m_plane.z,
+ 0.f);
+ const float4 faceANormalWS = qtRotate(ornA,Normal);
+
+ float d = dot3F4(faceANormalWS,separatingNormal);
+ if (d < dmin)
+ {
+ dmin = d;
+ closestFaceA = face;
+ worldNormalsA1[pairIndex] = faceANormalWS;
+ }
+ }
+ }
+
+ int numVerticesA = facesA[hullA->m_faceOffset+closestFaceA].m_numIndices;
+ if (numVerticesA>capacityWorldVerts)
+ numVerticesA = capacityWorldVerts;
+
+ for(int e0=0;e0<numVerticesA;e0++)
+ {
+ if (e0<capacityWorldVerts)
+ {
+ const float4 a = verticesA[hullA->m_vertexOffset+indicesA[facesA[hullA->m_faceOffset+closestFaceA].m_indexOffset+e0]];
+ worldVertsA1[pairIndex*capacityWorldVerts+e0] = transform(&a, &posA,&ornA);
+ }
+ }
+
+ clippingFaces[pairIndex].x = closestFaceA;
+ clippingFaces[pairIndex].y = closestFaceB;
+ clippingFaces[pairIndex].z = numVerticesA;
+ clippingFaces[pairIndex].w = numWorldVertsB1;
+
+
+ return numContactsOut;
+}
+
+
+
+
+// work-in-progress
+__kernel void findConcaveSeparatingAxisKernel( __global int4* concavePairs,
+ __global const BodyData* rigidBodies,
+ __global const btCollidableGpu* collidables,
+ __global const ConvexPolyhedronCL* convexShapes,
+ __global const float4* vertices,
+ __global const float4* uniqueEdges,
+ __global const btGpuFace* faces,
+ __global const int* indices,
+ __global const btGpuChildShape* gpuChildShapes,
+ __global btAabbCL* aabbs,
+ __global float4* concaveSeparatingNormalsOut,
+ __global int* concaveHasSeparatingNormals,
+ __global int4* clippingFacesOut,
+ __global float4* worldVertsA1GPU,
+ __global float4* worldNormalsAGPU,
+ __global float4* worldVertsB1GPU,
+ int vertexFaceCapacity,
+ int numConcavePairs
+ )
+{
+
+ int i = get_global_id(0);
+ if (i>=numConcavePairs)
+ return;
+
+ concaveHasSeparatingNormals[i] = 0;
+
+ int pairIdx = i;
+
+ int bodyIndexA = concavePairs[i].x;
+ int bodyIndexB = concavePairs[i].y;
+
+ int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
+ int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
+
+ int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
+ int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
+
+ if (collidables[collidableIndexB].m_shapeType!=SHAPE_CONVEX_HULL&&
+ collidables[collidableIndexB].m_shapeType!=SHAPE_COMPOUND_OF_CONVEX_HULLS)
+ {
+ concavePairs[pairIdx].w = -1;
+ return;
+ }
+
+
+
+ int numFacesA = convexShapes[shapeIndexA].m_numFaces;
+ int numActualConcaveConvexTests = 0;
+
+ int f = concavePairs[i].z;
+
+ bool overlap = false;
+
+ ConvexPolyhedronCL convexPolyhedronA;
+
+ //add 3 vertices of the triangle
+ convexPolyhedronA.m_numVertices = 3;
+ convexPolyhedronA.m_vertexOffset = 0;
+ float4 localCenter = make_float4(0.f,0.f,0.f,0.f);
+
+ btGpuFace face = faces[convexShapes[shapeIndexA].m_faceOffset+f];
+ float4 triMinAabb, triMaxAabb;
+ btAabbCL triAabb;
+ triAabb.m_min = make_float4(1e30f,1e30f,1e30f,0.f);
+ triAabb.m_max = make_float4(-1e30f,-1e30f,-1e30f,0.f);
+
+ float4 verticesA[3];
+ for (int i=0;i<3;i++)
+ {
+ int index = indices[face.m_indexOffset+i];
+ float4 vert = vertices[convexShapes[shapeIndexA].m_vertexOffset+index];
+ verticesA[i] = vert;
+ localCenter += vert;
+
+ triAabb.m_min = min(triAabb.m_min,vert);
+ triAabb.m_max = max(triAabb.m_max,vert);
+
+ }
+
+ overlap = true;
+ overlap = (triAabb.m_min.x > aabbs[bodyIndexB].m_max.x || triAabb.m_max.x < aabbs[bodyIndexB].m_min.x) ? false : overlap;
+ overlap = (triAabb.m_min.z > aabbs[bodyIndexB].m_max.z || triAabb.m_max.z < aabbs[bodyIndexB].m_min.z) ? false : overlap;
+ overlap = (triAabb.m_min.y > aabbs[bodyIndexB].m_max.y || triAabb.m_max.y < aabbs[bodyIndexB].m_min.y) ? false : overlap;
+
+ if (overlap)
+ {
+ float dmin = FLT_MAX;
+ int hasSeparatingAxis=5;
+ float4 sepAxis=make_float4(1,2,3,4);
+
+ int localCC=0;
+ numActualConcaveConvexTests++;
+
+ //a triangle has 3 unique edges
+ convexPolyhedronA.m_numUniqueEdges = 3;
+ convexPolyhedronA.m_uniqueEdgesOffset = 0;
+ float4 uniqueEdgesA[3];
+
+ uniqueEdgesA[0] = (verticesA[1]-verticesA[0]);
+ uniqueEdgesA[1] = (verticesA[2]-verticesA[1]);
+ uniqueEdgesA[2] = (verticesA[0]-verticesA[2]);
+
+
+ convexPolyhedronA.m_faceOffset = 0;
+
+ float4 normal = make_float4(face.m_plane.x,face.m_plane.y,face.m_plane.z,0.f);
+
+ btGpuFace facesA[TRIANGLE_NUM_CONVEX_FACES];
+ int indicesA[3+3+2+2+2];
+ int curUsedIndices=0;
+ int fidx=0;
+
+ //front size of triangle
+ {
+ facesA[fidx].m_indexOffset=curUsedIndices;
+ indicesA[0] = 0;
+ indicesA[1] = 1;
+ indicesA[2] = 2;
+ curUsedIndices+=3;
+ float c = face.m_plane.w;
+ facesA[fidx].m_plane.x = normal.x;
+ facesA[fidx].m_plane.y = normal.y;
+ facesA[fidx].m_plane.z = normal.z;
+ facesA[fidx].m_plane.w = c;
+ facesA[fidx].m_numIndices=3;
+ }
+ fidx++;
+ //back size of triangle
+ {
+ facesA[fidx].m_indexOffset=curUsedIndices;
+ indicesA[3]=2;
+ indicesA[4]=1;
+ indicesA[5]=0;
+ curUsedIndices+=3;
+ float c = dot(normal,verticesA[0]);
+ float c1 = -face.m_plane.w;
+ facesA[fidx].m_plane.x = -normal.x;
+ facesA[fidx].m_plane.y = -normal.y;
+ facesA[fidx].m_plane.z = -normal.z;
+ facesA[fidx].m_plane.w = c;
+ facesA[fidx].m_numIndices=3;
+ }
+ fidx++;
+
+ bool addEdgePlanes = true;
+ if (addEdgePlanes)
+ {
+ int numVertices=3;
+ int prevVertex = numVertices-1;
+ for (int i=0;i<numVertices;i++)
+ {
+ float4 v0 = verticesA[i];
+ float4 v1 = verticesA[prevVertex];
+
+ float4 edgeNormal = normalize(cross(normal,v1-v0));
+ float c = -dot(edgeNormal,v0);
+
+ facesA[fidx].m_numIndices = 2;
+ facesA[fidx].m_indexOffset=curUsedIndices;
+ indicesA[curUsedIndices++]=i;
+ indicesA[curUsedIndices++]=prevVertex;
+
+ facesA[fidx].m_plane.x = edgeNormal.x;
+ facesA[fidx].m_plane.y = edgeNormal.y;
+ facesA[fidx].m_plane.z = edgeNormal.z;
+ facesA[fidx].m_plane.w = c;
+ fidx++;
+ prevVertex = i;
+ }
+ }
+ convexPolyhedronA.m_numFaces = TRIANGLE_NUM_CONVEX_FACES;
+ convexPolyhedronA.m_localCenter = localCenter*(1.f/3.f);
+
+
+ float4 posA = rigidBodies[bodyIndexA].m_pos;
+ posA.w = 0.f;
+ float4 posB = rigidBodies[bodyIndexB].m_pos;
+ posB.w = 0.f;
+
+ float4 ornA = rigidBodies[bodyIndexA].m_quat;
+ float4 ornB =rigidBodies[bodyIndexB].m_quat;
+
+
+
+
+ ///////////////////
+ ///compound shape support
+
+ if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)
+ {
+ int compoundChild = concavePairs[pairIdx].w;
+ int childShapeIndexB = compoundChild;//collidables[collidableIndexB].m_shapeIndex+compoundChild;
+ int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;
+ float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;
+ float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;
+ float4 newPosB = transform(&childPosB,&posB,&ornB);
+ float4 newOrnB = qtMul(ornB,childOrnB);
+ posB = newPosB;
+ ornB = newOrnB;
+ shapeIndexB = collidables[childColIndexB].m_shapeIndex;
+ }
+ //////////////////
+
+ float4 c0local = convexPolyhedronA.m_localCenter;
+ float4 c0 = transform(&c0local, &posA, &ornA);
+ float4 c1local = convexShapes[shapeIndexB].m_localCenter;
+ float4 c1 = transform(&c1local,&posB,&ornB);
+ const float4 DeltaC2 = c0 - c1;
+
+
+ bool sepA = findSeparatingAxisLocalA( &convexPolyhedronA, &convexShapes[shapeIndexB],
+ posA,ornA,
+ posB,ornB,
+ DeltaC2,
+ verticesA,uniqueEdgesA,facesA,indicesA,
+ vertices,uniqueEdges,faces,indices,
+ &sepAxis,&dmin);
+ hasSeparatingAxis = 4;
+ if (!sepA)
+ {
+ hasSeparatingAxis = 0;
+ } else
+ {
+ bool sepB = findSeparatingAxisLocalB( &convexShapes[shapeIndexB],&convexPolyhedronA,
+ posB,ornB,
+ posA,ornA,
+ DeltaC2,
+ vertices,uniqueEdges,faces,indices,
+ verticesA,uniqueEdgesA,facesA,indicesA,
+ &sepAxis,&dmin);
+
+ if (!sepB)
+ {
+ hasSeparatingAxis = 0;
+ } else
+ {
+ bool sepEE = findSeparatingAxisEdgeEdgeLocalA( &convexPolyhedronA, &convexShapes[shapeIndexB],
+ posA,ornA,
+ posB,ornB,
+ DeltaC2,
+ verticesA,uniqueEdgesA,facesA,indicesA,
+ vertices,uniqueEdges,faces,indices,
+ &sepAxis,&dmin);
+
+ if (!sepEE)
+ {
+ hasSeparatingAxis = 0;
+ } else
+ {
+ hasSeparatingAxis = 1;
+ }
+ }
+ }
+
+ if (hasSeparatingAxis)
+ {
+ sepAxis.w = dmin;
+ concaveSeparatingNormalsOut[pairIdx]=sepAxis;
+ concaveHasSeparatingNormals[i]=1;
+
+
+ float minDist = -1e30f;
+ float maxDist = 0.02f;
+
+
+
+ findClippingFaces(sepAxis,
+ &convexPolyhedronA,
+ &convexShapes[shapeIndexB],
+ posA,ornA,
+ posB,ornB,
+ worldVertsA1GPU,
+ worldNormalsAGPU,
+ worldVertsB1GPU,
+ vertexFaceCapacity,
+ minDist, maxDist,
+ verticesA,
+ facesA,
+ indicesA,
+ vertices,
+ faces,
+ indices,
+ clippingFacesOut, pairIdx);
+
+
+ } else
+ {
+ //mark this pair as in-active
+ concavePairs[pairIdx].w = -1;
+ }
+ }
+ else
+ {
+ //mark this pair as in-active
+ concavePairs[pairIdx].w = -1;
+ }
+
+ concavePairs[pairIdx].z = -1;//now z is used for existing/persistent contacts
+}
+
+
+
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/kernels/satClipHullContacts.cl b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/kernels/satClipHullContacts.cl
new file mode 100644
index 0000000000..f433971741
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/kernels/satClipHullContacts.cl
@@ -0,0 +1,1888 @@
+
+#define TRIANGLE_NUM_CONVEX_FACES 5
+
+
+
+#pragma OPENCL EXTENSION cl_amd_printf : enable
+#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable
+
+#ifdef cl_ext_atomic_counters_32
+#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable
+#else
+#define counter32_t volatile __global int*
+#endif
+
+#define GET_GROUP_IDX get_group_id(0)
+#define GET_LOCAL_IDX get_local_id(0)
+#define GET_GLOBAL_IDX get_global_id(0)
+#define GET_GROUP_SIZE get_local_size(0)
+#define GET_NUM_GROUPS get_num_groups(0)
+#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)
+#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)
+#define AtomInc(x) atom_inc(&(x))
+#define AtomInc1(x, out) out = atom_inc(&(x))
+#define AppendInc(x, out) out = atomic_inc(x)
+#define AtomAdd(x, value) atom_add(&(x), value)
+#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )
+#define AtomXhg(x, value) atom_xchg ( &(x), value )
+
+#define max2 max
+#define min2 min
+
+typedef unsigned int u32;
+
+
+
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
+
+
+
+#define GET_NPOINTS(x) (x).m_worldNormalOnB.w
+
+
+
+#define SELECT_UINT4( b, a, condition ) select( b,a,condition )
+
+#define make_float4 (float4)
+#define make_float2 (float2)
+#define make_uint4 (uint4)
+#define make_int4 (int4)
+#define make_uint2 (uint2)
+#define make_int2 (int2)
+
+
+__inline
+float fastDiv(float numerator, float denominator)
+{
+ return native_divide(numerator, denominator);
+// return numerator/denominator;
+}
+
+__inline
+float4 fastDiv4(float4 numerator, float4 denominator)
+{
+ return native_divide(numerator, denominator);
+}
+
+
+__inline
+float4 cross3(float4 a, float4 b)
+{
+ return cross(a,b);
+}
+
+//#define dot3F4 dot
+
+__inline
+float dot3F4(float4 a, float4 b)
+{
+ float4 a1 = make_float4(a.xyz,0.f);
+ float4 b1 = make_float4(b.xyz,0.f);
+ return dot(a1, b1);
+}
+
+__inline
+float4 fastNormalize4(float4 v)
+{
+ return fast_normalize(v);
+}
+
+
+///////////////////////////////////////
+// Quaternion
+///////////////////////////////////////
+
+typedef float4 Quaternion;
+
+__inline
+Quaternion qtMul(Quaternion a, Quaternion b);
+
+__inline
+Quaternion qtNormalize(Quaternion in);
+
+__inline
+float4 qtRotate(Quaternion q, float4 vec);
+
+__inline
+Quaternion qtInvert(Quaternion q);
+
+
+
+
+__inline
+Quaternion qtMul(Quaternion a, Quaternion b)
+{
+ Quaternion ans;
+ ans = cross3( a, b );
+ ans += a.w*b+b.w*a;
+// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);
+ ans.w = a.w*b.w - dot3F4(a, b);
+ return ans;
+}
+
+__inline
+Quaternion qtNormalize(Quaternion in)
+{
+ return fastNormalize4(in);
+// in /= length( in );
+// return in;
+}
+__inline
+float4 qtRotate(Quaternion q, float4 vec)
+{
+ Quaternion qInv = qtInvert( q );
+ float4 vcpy = vec;
+ vcpy.w = 0.f;
+ float4 out = qtMul(qtMul(q,vcpy),qInv);
+ return out;
+}
+
+__inline
+Quaternion qtInvert(Quaternion q)
+{
+ return (Quaternion)(-q.xyz, q.w);
+}
+
+__inline
+float4 qtInvRotate(const Quaternion q, float4 vec)
+{
+ return qtRotate( qtInvert( q ), vec );
+}
+
+__inline
+float4 transform(const float4* p, const float4* translation, const Quaternion* orientation)
+{
+ return qtRotate( *orientation, *p ) + (*translation);
+}
+
+
+
+__inline
+float4 normalize3(const float4 a)
+{
+ float4 n = make_float4(a.x, a.y, a.z, 0.f);
+ return fastNormalize4( n );
+}
+
+
+__inline float4 lerp3(const float4 a,const float4 b, float t)
+{
+ return make_float4( a.x + (b.x - a.x) * t,
+ a.y + (b.y - a.y) * t,
+ a.z + (b.z - a.z) * t,
+ 0.f);
+}
+
+
+
+// Clips a face to the back of a plane, return the number of vertices out, stored in ppVtxOut
+int clipFaceGlobal(__global const float4* pVtxIn, int numVertsIn, float4 planeNormalWS,float planeEqWS, __global float4* ppVtxOut)
+{
+
+ int ve;
+ float ds, de;
+ int numVertsOut = 0;
+ //double-check next test
+ if (numVertsIn < 2)
+ return 0;
+
+ float4 firstVertex=pVtxIn[numVertsIn-1];
+ float4 endVertex = pVtxIn[0];
+
+ ds = dot3F4(planeNormalWS,firstVertex)+planeEqWS;
+
+ for (ve = 0; ve < numVertsIn; ve++)
+ {
+ endVertex=pVtxIn[ve];
+ de = dot3F4(planeNormalWS,endVertex)+planeEqWS;
+ if (ds<0)
+ {
+ if (de<0)
+ {
+ // Start < 0, end < 0, so output endVertex
+ ppVtxOut[numVertsOut++] = endVertex;
+ }
+ else
+ {
+ // Start < 0, end >= 0, so output intersection
+ ppVtxOut[numVertsOut++] = lerp3(firstVertex, endVertex,(ds * 1.f/(ds - de)) );
+ }
+ }
+ else
+ {
+ if (de<0)
+ {
+ // Start >= 0, end < 0 so output intersection and end
+ ppVtxOut[numVertsOut++] = lerp3(firstVertex, endVertex,(ds * 1.f/(ds - de)) );
+ ppVtxOut[numVertsOut++] = endVertex;
+ }
+ }
+ firstVertex = endVertex;
+ ds = de;
+ }
+ return numVertsOut;
+}
+
+
+
+// Clips a face to the back of a plane, return the number of vertices out, stored in ppVtxOut
+int clipFace(const float4* pVtxIn, int numVertsIn, float4 planeNormalWS,float planeEqWS, float4* ppVtxOut)
+{
+
+ int ve;
+ float ds, de;
+ int numVertsOut = 0;
+//double-check next test
+ if (numVertsIn < 2)
+ return 0;
+
+ float4 firstVertex=pVtxIn[numVertsIn-1];
+ float4 endVertex = pVtxIn[0];
+
+ ds = dot3F4(planeNormalWS,firstVertex)+planeEqWS;
+
+ for (ve = 0; ve < numVertsIn; ve++)
+ {
+ endVertex=pVtxIn[ve];
+
+ de = dot3F4(planeNormalWS,endVertex)+planeEqWS;
+
+ if (ds<0)
+ {
+ if (de<0)
+ {
+ // Start < 0, end < 0, so output endVertex
+ ppVtxOut[numVertsOut++] = endVertex;
+ }
+ else
+ {
+ // Start < 0, end >= 0, so output intersection
+ ppVtxOut[numVertsOut++] = lerp3(firstVertex, endVertex,(ds * 1.f/(ds - de)) );
+ }
+ }
+ else
+ {
+ if (de<0)
+ {
+ // Start >= 0, end < 0 so output intersection and end
+ ppVtxOut[numVertsOut++] = lerp3(firstVertex, endVertex,(ds * 1.f/(ds - de)) );
+ ppVtxOut[numVertsOut++] = endVertex;
+ }
+ }
+ firstVertex = endVertex;
+ ds = de;
+ }
+ return numVertsOut;
+}
+
+
+int clipFaceAgainstHull(const float4 separatingNormal, __global const b3ConvexPolyhedronData_t* hullA,
+ const float4 posA, const Quaternion ornA, float4* worldVertsB1, int numWorldVertsB1,
+ float4* worldVertsB2, int capacityWorldVertsB2,
+ const float minDist, float maxDist,
+ __global const float4* vertices,
+ __global const b3GpuFace_t* faces,
+ __global const int* indices,
+ float4* contactsOut,
+ int contactCapacity)
+{
+ int numContactsOut = 0;
+
+ float4* pVtxIn = worldVertsB1;
+ float4* pVtxOut = worldVertsB2;
+
+ int numVertsIn = numWorldVertsB1;
+ int numVertsOut = 0;
+
+ int closestFaceA=-1;
+ {
+ float dmin = FLT_MAX;
+ for(int face=0;face<hullA->m_numFaces;face++)
+ {
+ const float4 Normal = make_float4(
+ faces[hullA->m_faceOffset+face].m_plane.x,
+ faces[hullA->m_faceOffset+face].m_plane.y,
+ faces[hullA->m_faceOffset+face].m_plane.z,0.f);
+ const float4 faceANormalWS = qtRotate(ornA,Normal);
+
+ float d = dot3F4(faceANormalWS,separatingNormal);
+ if (d < dmin)
+ {
+ dmin = d;
+ closestFaceA = face;
+ }
+ }
+ }
+ if (closestFaceA<0)
+ return numContactsOut;
+
+ b3GpuFace_t polyA = faces[hullA->m_faceOffset+closestFaceA];
+
+ // clip polygon to back of planes of all faces of hull A that are adjacent to witness face
+ int numVerticesA = polyA.m_numIndices;
+ for(int e0=0;e0<numVerticesA;e0++)
+ {
+ const float4 a = vertices[hullA->m_vertexOffset+indices[polyA.m_indexOffset+e0]];
+ const float4 b = vertices[hullA->m_vertexOffset+indices[polyA.m_indexOffset+((e0+1)%numVerticesA)]];
+ const float4 edge0 = a - b;
+ const float4 WorldEdge0 = qtRotate(ornA,edge0);
+ float4 planeNormalA = make_float4(polyA.m_plane.x,polyA.m_plane.y,polyA.m_plane.z,0.f);
+ float4 worldPlaneAnormal1 = qtRotate(ornA,planeNormalA);
+
+ float4 planeNormalWS1 = -cross3(WorldEdge0,worldPlaneAnormal1);
+ float4 worldA1 = transform(&a,&posA,&ornA);
+ float planeEqWS1 = -dot3F4(worldA1,planeNormalWS1);
+
+ float4 planeNormalWS = planeNormalWS1;
+ float planeEqWS=planeEqWS1;
+
+ //clip face
+ //clipFace(*pVtxIn, *pVtxOut,planeNormalWS,planeEqWS);
+ numVertsOut = clipFace(pVtxIn, numVertsIn, planeNormalWS,planeEqWS, pVtxOut);
+
+ //btSwap(pVtxIn,pVtxOut);
+ float4* tmp = pVtxOut;
+ pVtxOut = pVtxIn;
+ pVtxIn = tmp;
+ numVertsIn = numVertsOut;
+ numVertsOut = 0;
+ }
+
+
+ // only keep points that are behind the witness face
+ {
+ float4 localPlaneNormal = make_float4(polyA.m_plane.x,polyA.m_plane.y,polyA.m_plane.z,0.f);
+ float localPlaneEq = polyA.m_plane.w;
+ float4 planeNormalWS = qtRotate(ornA,localPlaneNormal);
+ float planeEqWS=localPlaneEq-dot3F4(planeNormalWS,posA);
+ for (int i=0;i<numVertsIn;i++)
+ {
+ float depth = dot3F4(planeNormalWS,pVtxIn[i])+planeEqWS;
+ if (depth <=minDist)
+ {
+ depth = minDist;
+ }
+
+ if (depth <=maxDist)
+ {
+ float4 pointInWorld = pVtxIn[i];
+ //resultOut.addContactPoint(separatingNormal,point,depth);
+ contactsOut[numContactsOut++] = make_float4(pointInWorld.x,pointInWorld.y,pointInWorld.z,depth);
+ }
+ }
+ }
+
+ return numContactsOut;
+}
+
+
+
+int clipFaceAgainstHullLocalA(const float4 separatingNormal, const b3ConvexPolyhedronData_t* hullA,
+ const float4 posA, const Quaternion ornA, float4* worldVertsB1, int numWorldVertsB1,
+ float4* worldVertsB2, int capacityWorldVertsB2,
+ const float minDist, float maxDist,
+ const float4* verticesA,
+ const b3GpuFace_t* facesA,
+ const int* indicesA,
+ __global const float4* verticesB,
+ __global const b3GpuFace_t* facesB,
+ __global const int* indicesB,
+ float4* contactsOut,
+ int contactCapacity)
+{
+ int numContactsOut = 0;
+
+ float4* pVtxIn = worldVertsB1;
+ float4* pVtxOut = worldVertsB2;
+
+ int numVertsIn = numWorldVertsB1;
+ int numVertsOut = 0;
+
+ int closestFaceA=-1;
+ {
+ float dmin = FLT_MAX;
+ for(int face=0;face<hullA->m_numFaces;face++)
+ {
+ const float4 Normal = make_float4(
+ facesA[hullA->m_faceOffset+face].m_plane.x,
+ facesA[hullA->m_faceOffset+face].m_plane.y,
+ facesA[hullA->m_faceOffset+face].m_plane.z,0.f);
+ const float4 faceANormalWS = qtRotate(ornA,Normal);
+
+ float d = dot3F4(faceANormalWS,separatingNormal);
+ if (d < dmin)
+ {
+ dmin = d;
+ closestFaceA = face;
+ }
+ }
+ }
+ if (closestFaceA<0)
+ return numContactsOut;
+
+ b3GpuFace_t polyA = facesA[hullA->m_faceOffset+closestFaceA];
+
+ // clip polygon to back of planes of all faces of hull A that are adjacent to witness face
+ int numVerticesA = polyA.m_numIndices;
+ for(int e0=0;e0<numVerticesA;e0++)
+ {
+ const float4 a = verticesA[hullA->m_vertexOffset+indicesA[polyA.m_indexOffset+e0]];
+ const float4 b = verticesA[hullA->m_vertexOffset+indicesA[polyA.m_indexOffset+((e0+1)%numVerticesA)]];
+ const float4 edge0 = a - b;
+ const float4 WorldEdge0 = qtRotate(ornA,edge0);
+ float4 planeNormalA = make_float4(polyA.m_plane.x,polyA.m_plane.y,polyA.m_plane.z,0.f);
+ float4 worldPlaneAnormal1 = qtRotate(ornA,planeNormalA);
+
+ float4 planeNormalWS1 = -cross3(WorldEdge0,worldPlaneAnormal1);
+ float4 worldA1 = transform(&a,&posA,&ornA);
+ float planeEqWS1 = -dot3F4(worldA1,planeNormalWS1);
+
+ float4 planeNormalWS = planeNormalWS1;
+ float planeEqWS=planeEqWS1;
+
+ //clip face
+ //clipFace(*pVtxIn, *pVtxOut,planeNormalWS,planeEqWS);
+ numVertsOut = clipFace(pVtxIn, numVertsIn, planeNormalWS,planeEqWS, pVtxOut);
+
+ //btSwap(pVtxIn,pVtxOut);
+ float4* tmp = pVtxOut;
+ pVtxOut = pVtxIn;
+ pVtxIn = tmp;
+ numVertsIn = numVertsOut;
+ numVertsOut = 0;
+ }
+
+
+ // only keep points that are behind the witness face
+ {
+ float4 localPlaneNormal = make_float4(polyA.m_plane.x,polyA.m_plane.y,polyA.m_plane.z,0.f);
+ float localPlaneEq = polyA.m_plane.w;
+ float4 planeNormalWS = qtRotate(ornA,localPlaneNormal);
+ float planeEqWS=localPlaneEq-dot3F4(planeNormalWS,posA);
+ for (int i=0;i<numVertsIn;i++)
+ {
+ float depth = dot3F4(planeNormalWS,pVtxIn[i])+planeEqWS;
+ if (depth <=minDist)
+ {
+ depth = minDist;
+ }
+
+ if (depth <=maxDist)
+ {
+ float4 pointInWorld = pVtxIn[i];
+ //resultOut.addContactPoint(separatingNormal,point,depth);
+ contactsOut[numContactsOut++] = make_float4(pointInWorld.x,pointInWorld.y,pointInWorld.z,depth);
+ }
+ }
+ }
+
+ return numContactsOut;
+}
+
+int clipHullAgainstHull(const float4 separatingNormal,
+ __global const b3ConvexPolyhedronData_t* hullA, __global const b3ConvexPolyhedronData_t* hullB,
+ const float4 posA, const Quaternion ornA,const float4 posB, const Quaternion ornB,
+ float4* worldVertsB1, float4* worldVertsB2, int capacityWorldVerts,
+ const float minDist, float maxDist,
+ __global const float4* vertices,
+ __global const b3GpuFace_t* faces,
+ __global const int* indices,
+ float4* localContactsOut,
+ int localContactCapacity)
+{
+ int numContactsOut = 0;
+ int numWorldVertsB1= 0;
+
+
+ int closestFaceB=-1;
+ float dmax = -FLT_MAX;
+
+ {
+ for(int face=0;face<hullB->m_numFaces;face++)
+ {
+ const float4 Normal = make_float4(faces[hullB->m_faceOffset+face].m_plane.x,
+ faces[hullB->m_faceOffset+face].m_plane.y, faces[hullB->m_faceOffset+face].m_plane.z,0.f);
+ const float4 WorldNormal = qtRotate(ornB, Normal);
+ float d = dot3F4(WorldNormal,separatingNormal);
+ if (d > dmax)
+ {
+ dmax = d;
+ closestFaceB = face;
+ }
+ }
+ }
+
+ {
+ const b3GpuFace_t polyB = faces[hullB->m_faceOffset+closestFaceB];
+ const int numVertices = polyB.m_numIndices;
+ for(int e0=0;e0<numVertices;e0++)
+ {
+ const float4 b = vertices[hullB->m_vertexOffset+indices[polyB.m_indexOffset+e0]];
+ worldVertsB1[numWorldVertsB1++] = transform(&b,&posB,&ornB);
+ }
+ }
+
+ if (closestFaceB>=0)
+ {
+ numContactsOut = clipFaceAgainstHull(separatingNormal, hullA,
+ posA,ornA,
+ worldVertsB1,numWorldVertsB1,worldVertsB2,capacityWorldVerts, minDist, maxDist,vertices,
+ faces,
+ indices,localContactsOut,localContactCapacity);
+ }
+
+ return numContactsOut;
+}
+
+
+int clipHullAgainstHullLocalA(const float4 separatingNormal,
+ const b3ConvexPolyhedronData_t* hullA, __global const b3ConvexPolyhedronData_t* hullB,
+ const float4 posA, const Quaternion ornA,const float4 posB, const Quaternion ornB,
+ float4* worldVertsB1, float4* worldVertsB2, int capacityWorldVerts,
+ const float minDist, float maxDist,
+ const float4* verticesA,
+ const b3GpuFace_t* facesA,
+ const int* indicesA,
+ __global const float4* verticesB,
+ __global const b3GpuFace_t* facesB,
+ __global const int* indicesB,
+ float4* localContactsOut,
+ int localContactCapacity)
+{
+ int numContactsOut = 0;
+ int numWorldVertsB1= 0;
+
+
+ int closestFaceB=-1;
+ float dmax = -FLT_MAX;
+
+ {
+ for(int face=0;face<hullB->m_numFaces;face++)
+ {
+ const float4 Normal = make_float4(facesB[hullB->m_faceOffset+face].m_plane.x,
+ facesB[hullB->m_faceOffset+face].m_plane.y, facesB[hullB->m_faceOffset+face].m_plane.z,0.f);
+ const float4 WorldNormal = qtRotate(ornB, Normal);
+ float d = dot3F4(WorldNormal,separatingNormal);
+ if (d > dmax)
+ {
+ dmax = d;
+ closestFaceB = face;
+ }
+ }
+ }
+
+ {
+ const b3GpuFace_t polyB = facesB[hullB->m_faceOffset+closestFaceB];
+ const int numVertices = polyB.m_numIndices;
+ for(int e0=0;e0<numVertices;e0++)
+ {
+ const float4 b = verticesB[hullB->m_vertexOffset+indicesB[polyB.m_indexOffset+e0]];
+ worldVertsB1[numWorldVertsB1++] = transform(&b,&posB,&ornB);
+ }
+ }
+
+ if (closestFaceB>=0)
+ {
+ numContactsOut = clipFaceAgainstHullLocalA(separatingNormal, hullA,
+ posA,ornA,
+ worldVertsB1,numWorldVertsB1,worldVertsB2,capacityWorldVerts, minDist, maxDist,
+ verticesA,facesA,indicesA,
+ verticesB,facesB,indicesB,
+ localContactsOut,localContactCapacity);
+ }
+
+ return numContactsOut;
+}
+
+#define PARALLEL_SUM(v, n) for(int j=1; j<n; j++) v[0] += v[j];
+#define PARALLEL_DO(execution, n) for(int ie=0; ie<n; ie++){execution;}
+#define REDUCE_MAX(v, n) {int i=0;\
+for(int offset=0; offset<n; offset++) v[i] = (v[i].y > v[i+offset].y)? v[i]: v[i+offset]; }
+#define REDUCE_MIN(v, n) {int i=0;\
+for(int offset=0; offset<n; offset++) v[i] = (v[i].y < v[i+offset].y)? v[i]: v[i+offset]; }
+
+int extractManifoldSequentialGlobal(__global const float4* p, int nPoints, float4 nearNormal, int4* contactIdx)
+{
+ if( nPoints == 0 )
+ return 0;
+
+ if (nPoints <=4)
+ return nPoints;
+
+
+ if (nPoints >64)
+ nPoints = 64;
+
+ float4 center = make_float4(0.f);
+ {
+
+ for (int i=0;i<nPoints;i++)
+ center += p[i];
+ center /= (float)nPoints;
+ }
+
+
+
+ // sample 4 directions
+
+ float4 aVector = p[0] - center;
+ float4 u = cross3( nearNormal, aVector );
+ float4 v = cross3( nearNormal, u );
+ u = normalize3( u );
+ v = normalize3( v );
+
+
+ //keep point with deepest penetration
+ float minW= FLT_MAX;
+
+ int minIndex=-1;
+
+ float4 maxDots;
+ maxDots.x = FLT_MIN;
+ maxDots.y = FLT_MIN;
+ maxDots.z = FLT_MIN;
+ maxDots.w = FLT_MIN;
+
+ // idx, distance
+ for(int ie = 0; ie<nPoints; ie++ )
+ {
+ if (p[ie].w<minW)
+ {
+ minW = p[ie].w;
+ minIndex=ie;
+ }
+ float f;
+ float4 r = p[ie]-center;
+ f = dot3F4( u, r );
+ if (f<maxDots.x)
+ {
+ maxDots.x = f;
+ contactIdx[0].x = ie;
+ }
+
+ f = dot3F4( -u, r );
+ if (f<maxDots.y)
+ {
+ maxDots.y = f;
+ contactIdx[0].y = ie;
+ }
+
+
+ f = dot3F4( v, r );
+ if (f<maxDots.z)
+ {
+ maxDots.z = f;
+ contactIdx[0].z = ie;
+ }
+
+ f = dot3F4( -v, r );
+ if (f<maxDots.w)
+ {
+ maxDots.w = f;
+ contactIdx[0].w = ie;
+ }
+
+ }
+
+ if (contactIdx[0].x != minIndex && contactIdx[0].y != minIndex && contactIdx[0].z != minIndex && contactIdx[0].w != minIndex)
+ {
+ //replace the first contact with minimum (todo: replace contact with least penetration)
+ contactIdx[0].x = minIndex;
+ }
+
+ return 4;
+
+}
+
+
+int extractManifoldSequentialGlobalFake(__global const float4* p, int nPoints, float4 nearNormal, int* contactIdx)
+{
+ contactIdx[0] = 0;
+ contactIdx[1] = 1;
+ contactIdx[2] = 2;
+ contactIdx[3] = 3;
+
+ if( nPoints == 0 ) return 0;
+
+ nPoints = min2( nPoints, 4 );
+ return nPoints;
+
+}
+
+
+
+int extractManifoldSequential(const float4* p, int nPoints, float4 nearNormal, int* contactIdx)
+{
+ if( nPoints == 0 ) return 0;
+
+ nPoints = min2( nPoints, 64 );
+
+ float4 center = make_float4(0.f);
+ {
+ float4 v[64];
+ for (int i=0;i<nPoints;i++)
+ v[i] = p[i];
+ //memcpy( v, p, nPoints*sizeof(float4) );
+ PARALLEL_SUM( v, nPoints );
+ center = v[0]/(float)nPoints;
+ }
+
+
+
+ { // sample 4 directions
+ if( nPoints < 4 )
+ {
+ for(int i=0; i<nPoints; i++)
+ contactIdx[i] = i;
+ return nPoints;
+ }
+
+ float4 aVector = p[0] - center;
+ float4 u = cross3( nearNormal, aVector );
+ float4 v = cross3( nearNormal, u );
+ u = normalize3( u );
+ v = normalize3( v );
+
+ int idx[4];
+
+ float2 max00 = make_float2(0,FLT_MAX);
+ {
+ // idx, distance
+ {
+ {
+ int4 a[64];
+ for(int ie = 0; ie<nPoints; ie++ )
+ {
+
+
+ float f;
+ float4 r = p[ie]-center;
+ f = dot3F4( u, r );
+ a[ie].x = ((*(u32*)&f) & 0xffffff00) | (0xff & ie);
+
+ f = dot3F4( -u, r );
+ a[ie].y = ((*(u32*)&f) & 0xffffff00) | (0xff & ie);
+
+ f = dot3F4( v, r );
+ a[ie].z = ((*(u32*)&f) & 0xffffff00) | (0xff & ie);
+
+ f = dot3F4( -v, r );
+ a[ie].w = ((*(u32*)&f) & 0xffffff00) | (0xff & ie);
+ }
+
+ for(int ie=0; ie<nPoints; ie++)
+ {
+ a[0].x = (a[0].x > a[ie].x )? a[0].x: a[ie].x;
+ a[0].y = (a[0].y > a[ie].y )? a[0].y: a[ie].y;
+ a[0].z = (a[0].z > a[ie].z )? a[0].z: a[ie].z;
+ a[0].w = (a[0].w > a[ie].w )? a[0].w: a[ie].w;
+ }
+
+ idx[0] = (int)a[0].x & 0xff;
+ idx[1] = (int)a[0].y & 0xff;
+ idx[2] = (int)a[0].z & 0xff;
+ idx[3] = (int)a[0].w & 0xff;
+ }
+ }
+
+ {
+ float2 h[64];
+ PARALLEL_DO( h[ie] = make_float2((float)ie, p[ie].w), nPoints );
+ REDUCE_MIN( h, nPoints );
+ max00 = h[0];
+ }
+ }
+
+ contactIdx[0] = idx[0];
+ contactIdx[1] = idx[1];
+ contactIdx[2] = idx[2];
+ contactIdx[3] = idx[3];
+
+
+ return 4;
+ }
+}
+
+
+
+__kernel void extractManifoldAndAddContactKernel(__global const int4* pairs,
+ __global const b3RigidBodyData_t* rigidBodies,
+ __global const float4* closestPointsWorld,
+ __global const float4* separatingNormalsWorld,
+ __global const int* contactCounts,
+ __global const int* contactOffsets,
+ __global struct b3Contact4Data* restrict contactsOut,
+ counter32_t nContactsOut,
+ int contactCapacity,
+ int numPairs,
+ int pairIndex
+ )
+{
+ int idx = get_global_id(0);
+
+ if (idx<numPairs)
+ {
+ float4 normal = separatingNormalsWorld[idx];
+ int nPoints = contactCounts[idx];
+ __global const float4* pointsIn = &closestPointsWorld[contactOffsets[idx]];
+ float4 localPoints[64];
+ for (int i=0;i<nPoints;i++)
+ {
+ localPoints[i] = pointsIn[i];
+ }
+
+ int contactIdx[4];// = {-1,-1,-1,-1};
+ contactIdx[0] = -1;
+ contactIdx[1] = -1;
+ contactIdx[2] = -1;
+ contactIdx[3] = -1;
+
+ int nContacts = extractManifoldSequential(localPoints, nPoints, normal, contactIdx);
+
+ int dstIdx;
+ AppendInc( nContactsOut, dstIdx );
+ if (dstIdx<contactCapacity)
+ {
+ __global struct b3Contact4Data* c = contactsOut + dstIdx;
+ c->m_worldNormalOnB = -normal;
+ c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);
+ c->m_batchIdx = idx;
+ int bodyA = pairs[pairIndex].x;
+ int bodyB = pairs[pairIndex].y;
+ c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0 ? -bodyA:bodyA;
+ c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0 ? -bodyB:bodyB;
+ c->m_childIndexA = -1;
+ c->m_childIndexB = -1;
+ for (int i=0;i<nContacts;i++)
+ {
+ c->m_worldPosB[i] = localPoints[contactIdx[i]];
+ }
+ GET_NPOINTS(*c) = nContacts;
+ }
+ }
+}
+
+
+void trInverse(float4 translationIn, Quaternion orientationIn,
+ float4* translationOut, Quaternion* orientationOut)
+{
+ *orientationOut = qtInvert(orientationIn);
+ *translationOut = qtRotate(*orientationOut, -translationIn);
+}
+
+void trMul(float4 translationA, Quaternion orientationA,
+ float4 translationB, Quaternion orientationB,
+ float4* translationOut, Quaternion* orientationOut)
+{
+ *orientationOut = qtMul(orientationA,orientationB);
+ *translationOut = transform(&translationB,&translationA,&orientationA);
+}
+
+
+
+
+__kernel void clipHullHullKernel( __global int4* pairs,
+ __global const b3RigidBodyData_t* rigidBodies,
+ __global const b3Collidable_t* collidables,
+ __global const b3ConvexPolyhedronData_t* convexShapes,
+ __global const float4* vertices,
+ __global const float4* uniqueEdges,
+ __global const b3GpuFace_t* faces,
+ __global const int* indices,
+ __global const float4* separatingNormals,
+ __global const int* hasSeparatingAxis,
+ __global struct b3Contact4Data* restrict globalContactsOut,
+ counter32_t nGlobalContactsOut,
+ int numPairs,
+ int contactCapacity)
+{
+
+ int i = get_global_id(0);
+ int pairIndex = i;
+
+ float4 worldVertsB1[64];
+ float4 worldVertsB2[64];
+ int capacityWorldVerts = 64;
+
+ float4 localContactsOut[64];
+ int localContactCapacity=64;
+
+ float minDist = -1e30f;
+ float maxDist = 0.02f;
+
+ if (i<numPairs)
+ {
+
+ int bodyIndexA = pairs[i].x;
+ int bodyIndexB = pairs[i].y;
+
+ int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
+ int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
+
+ if (hasSeparatingAxis[i])
+ {
+
+
+ int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
+ int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
+
+
+
+
+ int numLocalContactsOut = clipHullAgainstHull(separatingNormals[i],
+ &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],
+ rigidBodies[bodyIndexA].m_pos,rigidBodies[bodyIndexA].m_quat,
+ rigidBodies[bodyIndexB].m_pos,rigidBodies[bodyIndexB].m_quat,
+ worldVertsB1,worldVertsB2,capacityWorldVerts,
+ minDist, maxDist,
+ vertices,faces,indices,
+ localContactsOut,localContactCapacity);
+
+ if (numLocalContactsOut>0)
+ {
+ float4 normal = -separatingNormals[i];
+ int nPoints = numLocalContactsOut;
+ float4* pointsIn = localContactsOut;
+ int contactIdx[4];// = {-1,-1,-1,-1};
+
+ contactIdx[0] = -1;
+ contactIdx[1] = -1;
+ contactIdx[2] = -1;
+ contactIdx[3] = -1;
+
+ int nReducedContacts = extractManifoldSequential(pointsIn, nPoints, normal, contactIdx);
+
+
+ int mprContactIndex = pairs[pairIndex].z;
+
+ int dstIdx = mprContactIndex;
+ if (dstIdx<0)
+ {
+ AppendInc( nGlobalContactsOut, dstIdx );
+ }
+
+ if (dstIdx<contactCapacity)
+ {
+ pairs[pairIndex].z = dstIdx;
+
+ __global struct b3Contact4Data* c = globalContactsOut+ dstIdx;
+ c->m_worldNormalOnB = -normal;
+ c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);
+ c->m_batchIdx = pairIndex;
+ int bodyA = pairs[pairIndex].x;
+ int bodyB = pairs[pairIndex].y;
+ c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0?-bodyA:bodyA;
+ c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0?-bodyB:bodyB;
+ c->m_childIndexA = -1;
+ c->m_childIndexB = -1;
+
+ for (int i=0;i<nReducedContacts;i++)
+ {
+ //this condition means: overwrite contact point, unless at index i==0 we have a valid 'mpr' contact
+ if (i>0||(mprContactIndex<0))
+ {
+ c->m_worldPosB[i] = pointsIn[contactIdx[i]];
+ }
+ }
+ GET_NPOINTS(*c) = nReducedContacts;
+ }
+
+ }// if (numContactsOut>0)
+ }// if (hasSeparatingAxis[i])
+ }// if (i<numPairs)
+
+}
+
+
+__kernel void clipCompoundsHullHullKernel( __global const int4* gpuCompoundPairs,
+ __global const b3RigidBodyData_t* rigidBodies,
+ __global const b3Collidable_t* collidables,
+ __global const b3ConvexPolyhedronData_t* convexShapes,
+ __global const float4* vertices,
+ __global const float4* uniqueEdges,
+ __global const b3GpuFace_t* faces,
+ __global const int* indices,
+ __global const b3GpuChildShape_t* gpuChildShapes,
+ __global const float4* gpuCompoundSepNormalsOut,
+ __global const int* gpuHasCompoundSepNormalsOut,
+ __global struct b3Contact4Data* restrict globalContactsOut,
+ counter32_t nGlobalContactsOut,
+ int numCompoundPairs, int maxContactCapacity)
+{
+
+ int i = get_global_id(0);
+ int pairIndex = i;
+
+ float4 worldVertsB1[64];
+ float4 worldVertsB2[64];
+ int capacityWorldVerts = 64;
+
+ float4 localContactsOut[64];
+ int localContactCapacity=64;
+
+ float minDist = -1e30f;
+ float maxDist = 0.02f;
+
+ if (i<numCompoundPairs)
+ {
+
+ if (gpuHasCompoundSepNormalsOut[i])
+ {
+
+ int bodyIndexA = gpuCompoundPairs[i].x;
+ int bodyIndexB = gpuCompoundPairs[i].y;
+
+ int childShapeIndexA = gpuCompoundPairs[i].z;
+ int childShapeIndexB = gpuCompoundPairs[i].w;
+
+ int collidableIndexA = -1;
+ int collidableIndexB = -1;
+
+ float4 ornA = rigidBodies[bodyIndexA].m_quat;
+ float4 posA = rigidBodies[bodyIndexA].m_pos;
+
+ float4 ornB = rigidBodies[bodyIndexB].m_quat;
+ float4 posB = rigidBodies[bodyIndexB].m_pos;
+
+ if (childShapeIndexA >= 0)
+ {
+ collidableIndexA = gpuChildShapes[childShapeIndexA].m_shapeIndex;
+ float4 childPosA = gpuChildShapes[childShapeIndexA].m_childPosition;
+ float4 childOrnA = gpuChildShapes[childShapeIndexA].m_childOrientation;
+ float4 newPosA = qtRotate(ornA,childPosA)+posA;
+ float4 newOrnA = qtMul(ornA,childOrnA);
+ posA = newPosA;
+ ornA = newOrnA;
+ } else
+ {
+ collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
+ }
+
+ if (childShapeIndexB>=0)
+ {
+ collidableIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;
+ float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;
+ float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;
+ float4 newPosB = transform(&childPosB,&posB,&ornB);
+ float4 newOrnB = qtMul(ornB,childOrnB);
+ posB = newPosB;
+ ornB = newOrnB;
+ } else
+ {
+ collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
+ }
+
+ int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
+ int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
+
+ int numLocalContactsOut = clipHullAgainstHull(gpuCompoundSepNormalsOut[i],
+ &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],
+ posA,ornA,
+ posB,ornB,
+ worldVertsB1,worldVertsB2,capacityWorldVerts,
+ minDist, maxDist,
+ vertices,faces,indices,
+ localContactsOut,localContactCapacity);
+
+ if (numLocalContactsOut>0)
+ {
+ float4 normal = -gpuCompoundSepNormalsOut[i];
+ int nPoints = numLocalContactsOut;
+ float4* pointsIn = localContactsOut;
+ int contactIdx[4];// = {-1,-1,-1,-1};
+
+ contactIdx[0] = -1;
+ contactIdx[1] = -1;
+ contactIdx[2] = -1;
+ contactIdx[3] = -1;
+
+ int nReducedContacts = extractManifoldSequential(pointsIn, nPoints, normal, contactIdx);
+
+ int dstIdx;
+ AppendInc( nGlobalContactsOut, dstIdx );
+ if ((dstIdx+nReducedContacts) < maxContactCapacity)
+ {
+ __global struct b3Contact4Data* c = globalContactsOut+ dstIdx;
+ c->m_worldNormalOnB = -normal;
+ c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);
+ c->m_batchIdx = pairIndex;
+ int bodyA = gpuCompoundPairs[pairIndex].x;
+ int bodyB = gpuCompoundPairs[pairIndex].y;
+ c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0?-bodyA:bodyA;
+ c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0?-bodyB:bodyB;
+ c->m_childIndexA = childShapeIndexA;
+ c->m_childIndexB = childShapeIndexB;
+ for (int i=0;i<nReducedContacts;i++)
+ {
+ c->m_worldPosB[i] = pointsIn[contactIdx[i]];
+ }
+ GET_NPOINTS(*c) = nReducedContacts;
+ }
+
+ }// if (numContactsOut>0)
+ }// if (gpuHasCompoundSepNormalsOut[i])
+ }// if (i<numCompoundPairs)
+
+}
+
+
+
+__kernel void sphereSphereCollisionKernel( __global const int4* pairs,
+ __global const b3RigidBodyData_t* rigidBodies,
+ __global const b3Collidable_t* collidables,
+ __global const float4* separatingNormals,
+ __global const int* hasSeparatingAxis,
+ __global struct b3Contact4Data* restrict globalContactsOut,
+ counter32_t nGlobalContactsOut,
+ int contactCapacity,
+ int numPairs)
+{
+
+ int i = get_global_id(0);
+ int pairIndex = i;
+
+ if (i<numPairs)
+ {
+ int bodyIndexA = pairs[i].x;
+ int bodyIndexB = pairs[i].y;
+
+ int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
+ int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
+
+ if (collidables[collidableIndexA].m_shapeType == SHAPE_SPHERE &&
+ collidables[collidableIndexB].m_shapeType == SHAPE_SPHERE)
+ {
+ //sphere-sphere
+ float radiusA = collidables[collidableIndexA].m_radius;
+ float radiusB = collidables[collidableIndexB].m_radius;
+ float4 posA = rigidBodies[bodyIndexA].m_pos;
+ float4 posB = rigidBodies[bodyIndexB].m_pos;
+
+ float4 diff = posA-posB;
+ float len = length(diff);
+
+ ///iff distance positive, don't generate a new contact
+ if ( len <= (radiusA+radiusB))
+ {
+ ///distance (negative means penetration)
+ float dist = len - (radiusA+radiusB);
+ float4 normalOnSurfaceB = make_float4(1.f,0.f,0.f,0.f);
+ if (len > 0.00001)
+ {
+ normalOnSurfaceB = diff / len;
+ }
+ float4 contactPosB = posB + normalOnSurfaceB*radiusB;
+ contactPosB.w = dist;
+
+ int dstIdx;
+ AppendInc( nGlobalContactsOut, dstIdx );
+ if (dstIdx < contactCapacity)
+ {
+ __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];
+ c->m_worldNormalOnB = -normalOnSurfaceB;
+ c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);
+ c->m_batchIdx = pairIndex;
+ int bodyA = pairs[pairIndex].x;
+ int bodyB = pairs[pairIndex].y;
+ c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0?-bodyA:bodyA;
+ c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0?-bodyB:bodyB;
+ c->m_worldPosB[0] = contactPosB;
+ c->m_childIndexA = -1;
+ c->m_childIndexB = -1;
+
+ GET_NPOINTS(*c) = 1;
+ }//if (dstIdx < numPairs)
+ }//if ( len <= (radiusA+radiusB))
+ }//SHAPE_SPHERE SHAPE_SPHERE
+ }//if (i<numPairs)
+}
+
+__kernel void clipHullHullConcaveConvexKernel( __global int4* concavePairsIn,
+ __global const b3RigidBodyData_t* rigidBodies,
+ __global const b3Collidable_t* collidables,
+ __global const b3ConvexPolyhedronData_t* convexShapes,
+ __global const float4* vertices,
+ __global const float4* uniqueEdges,
+ __global const b3GpuFace_t* faces,
+ __global const int* indices,
+ __global const b3GpuChildShape_t* gpuChildShapes,
+ __global const float4* separatingNormals,
+ __global struct b3Contact4Data* restrict globalContactsOut,
+ counter32_t nGlobalContactsOut,
+ int contactCapacity,
+ int numConcavePairs)
+{
+
+ int i = get_global_id(0);
+ int pairIndex = i;
+
+ float4 worldVertsB1[64];
+ float4 worldVertsB2[64];
+ int capacityWorldVerts = 64;
+
+ float4 localContactsOut[64];
+ int localContactCapacity=64;
+
+ float minDist = -1e30f;
+ float maxDist = 0.02f;
+
+ if (i<numConcavePairs)
+ {
+ //negative value means that the pair is invalid
+ if (concavePairsIn[i].w<0)
+ return;
+
+ int bodyIndexA = concavePairsIn[i].x;
+ int bodyIndexB = concavePairsIn[i].y;
+ int f = concavePairsIn[i].z;
+ int childShapeIndexA = f;
+
+ int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
+ int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
+
+ int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
+ int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
+
+ ///////////////////////////////////////////////////////////////
+
+
+ bool overlap = false;
+
+ b3ConvexPolyhedronData_t convexPolyhedronA;
+
+ //add 3 vertices of the triangle
+ convexPolyhedronA.m_numVertices = 3;
+ convexPolyhedronA.m_vertexOffset = 0;
+ float4 localCenter = make_float4(0.f,0.f,0.f,0.f);
+
+ b3GpuFace_t face = faces[convexShapes[shapeIndexA].m_faceOffset+f];
+
+ float4 verticesA[3];
+ for (int i=0;i<3;i++)
+ {
+ int index = indices[face.m_indexOffset+i];
+ float4 vert = vertices[convexShapes[shapeIndexA].m_vertexOffset+index];
+ verticesA[i] = vert;
+ localCenter += vert;
+ }
+
+ float dmin = FLT_MAX;
+
+ int localCC=0;
+
+ //a triangle has 3 unique edges
+ convexPolyhedronA.m_numUniqueEdges = 3;
+ convexPolyhedronA.m_uniqueEdgesOffset = 0;
+ float4 uniqueEdgesA[3];
+
+ uniqueEdgesA[0] = (verticesA[1]-verticesA[0]);
+ uniqueEdgesA[1] = (verticesA[2]-verticesA[1]);
+ uniqueEdgesA[2] = (verticesA[0]-verticesA[2]);
+
+
+ convexPolyhedronA.m_faceOffset = 0;
+
+ float4 normal = make_float4(face.m_plane.x,face.m_plane.y,face.m_plane.z,0.f);
+
+ b3GpuFace_t facesA[TRIANGLE_NUM_CONVEX_FACES];
+ int indicesA[3+3+2+2+2];
+ int curUsedIndices=0;
+ int fidx=0;
+
+ //front size of triangle
+ {
+ facesA[fidx].m_indexOffset=curUsedIndices;
+ indicesA[0] = 0;
+ indicesA[1] = 1;
+ indicesA[2] = 2;
+ curUsedIndices+=3;
+ float c = face.m_plane.w;
+ facesA[fidx].m_plane.x = normal.x;
+ facesA[fidx].m_plane.y = normal.y;
+ facesA[fidx].m_plane.z = normal.z;
+ facesA[fidx].m_plane.w = c;
+ facesA[fidx].m_numIndices=3;
+ }
+ fidx++;
+ //back size of triangle
+ {
+ facesA[fidx].m_indexOffset=curUsedIndices;
+ indicesA[3]=2;
+ indicesA[4]=1;
+ indicesA[5]=0;
+ curUsedIndices+=3;
+ float c = dot3F4(normal,verticesA[0]);
+ float c1 = -face.m_plane.w;
+ facesA[fidx].m_plane.x = -normal.x;
+ facesA[fidx].m_plane.y = -normal.y;
+ facesA[fidx].m_plane.z = -normal.z;
+ facesA[fidx].m_plane.w = c;
+ facesA[fidx].m_numIndices=3;
+ }
+ fidx++;
+
+ bool addEdgePlanes = true;
+ if (addEdgePlanes)
+ {
+ int numVertices=3;
+ int prevVertex = numVertices-1;
+ for (int i=0;i<numVertices;i++)
+ {
+ float4 v0 = verticesA[i];
+ float4 v1 = verticesA[prevVertex];
+
+ float4 edgeNormal = normalize(cross(normal,v1-v0));
+ float c = -dot3F4(edgeNormal,v0);
+
+ facesA[fidx].m_numIndices = 2;
+ facesA[fidx].m_indexOffset=curUsedIndices;
+ indicesA[curUsedIndices++]=i;
+ indicesA[curUsedIndices++]=prevVertex;
+
+ facesA[fidx].m_plane.x = edgeNormal.x;
+ facesA[fidx].m_plane.y = edgeNormal.y;
+ facesA[fidx].m_plane.z = edgeNormal.z;
+ facesA[fidx].m_plane.w = c;
+ fidx++;
+ prevVertex = i;
+ }
+ }
+ convexPolyhedronA.m_numFaces = TRIANGLE_NUM_CONVEX_FACES;
+ convexPolyhedronA.m_localCenter = localCenter*(1.f/3.f);
+
+
+ float4 posA = rigidBodies[bodyIndexA].m_pos;
+ posA.w = 0.f;
+ float4 posB = rigidBodies[bodyIndexB].m_pos;
+ posB.w = 0.f;
+ float4 ornA = rigidBodies[bodyIndexA].m_quat;
+ float4 ornB =rigidBodies[bodyIndexB].m_quat;
+
+
+ float4 sepAxis = separatingNormals[i];
+
+ int shapeTypeB = collidables[collidableIndexB].m_shapeType;
+ int childShapeIndexB =-1;
+ if (shapeTypeB==SHAPE_COMPOUND_OF_CONVEX_HULLS)
+ {
+ ///////////////////
+ ///compound shape support
+
+ childShapeIndexB = concavePairsIn[pairIndex].w;
+ int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;
+ shapeIndexB = collidables[childColIndexB].m_shapeIndex;
+ float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;
+ float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;
+ float4 newPosB = transform(&childPosB,&posB,&ornB);
+ float4 newOrnB = qtMul(ornB,childOrnB);
+ posB = newPosB;
+ ornB = newOrnB;
+
+ }
+
+ ////////////////////////////////////////
+
+
+
+ int numLocalContactsOut = clipHullAgainstHullLocalA(sepAxis,
+ &convexPolyhedronA, &convexShapes[shapeIndexB],
+ posA,ornA,
+ posB,ornB,
+ worldVertsB1,worldVertsB2,capacityWorldVerts,
+ minDist, maxDist,
+ &verticesA,&facesA,&indicesA,
+ vertices,faces,indices,
+ localContactsOut,localContactCapacity);
+
+ if (numLocalContactsOut>0)
+ {
+ float4 normal = -separatingNormals[i];
+ int nPoints = numLocalContactsOut;
+ float4* pointsIn = localContactsOut;
+ int contactIdx[4];// = {-1,-1,-1,-1};
+
+ contactIdx[0] = -1;
+ contactIdx[1] = -1;
+ contactIdx[2] = -1;
+ contactIdx[3] = -1;
+
+ int nReducedContacts = extractManifoldSequential(pointsIn, nPoints, normal, contactIdx);
+
+ int dstIdx;
+ AppendInc( nGlobalContactsOut, dstIdx );
+ if (dstIdx<contactCapacity)
+ {
+ __global struct b3Contact4Data* c = globalContactsOut+ dstIdx;
+ c->m_worldNormalOnB = -normal;
+ c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);
+ c->m_batchIdx = pairIndex;
+ int bodyA = concavePairsIn[pairIndex].x;
+ int bodyB = concavePairsIn[pairIndex].y;
+ c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0?-bodyA:bodyA;
+ c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0?-bodyB:bodyB;
+ c->m_childIndexA = childShapeIndexA;
+ c->m_childIndexB = childShapeIndexB;
+ for (int i=0;i<nReducedContacts;i++)
+ {
+ c->m_worldPosB[i] = pointsIn[contactIdx[i]];
+ }
+ GET_NPOINTS(*c) = nReducedContacts;
+ }
+
+ }// if (numContactsOut>0)
+ }// if (i<numPairs)
+}
+
+
+
+
+
+
+int findClippingFaces(const float4 separatingNormal,
+ __global const b3ConvexPolyhedronData_t* hullA, __global const b3ConvexPolyhedronData_t* hullB,
+ const float4 posA, const Quaternion ornA,const float4 posB, const Quaternion ornB,
+ __global float4* worldVertsA1,
+ __global float4* worldNormalsA1,
+ __global float4* worldVertsB1,
+ int capacityWorldVerts,
+ const float minDist, float maxDist,
+ __global const float4* vertices,
+ __global const b3GpuFace_t* faces,
+ __global const int* indices,
+ __global int4* clippingFaces, int pairIndex)
+{
+ int numContactsOut = 0;
+ int numWorldVertsB1= 0;
+
+
+ int closestFaceB=-1;
+ float dmax = -FLT_MAX;
+
+ {
+ for(int face=0;face<hullB->m_numFaces;face++)
+ {
+ const float4 Normal = make_float4(faces[hullB->m_faceOffset+face].m_plane.x,
+ faces[hullB->m_faceOffset+face].m_plane.y, faces[hullB->m_faceOffset+face].m_plane.z,0.f);
+ const float4 WorldNormal = qtRotate(ornB, Normal);
+ float d = dot3F4(WorldNormal,separatingNormal);
+ if (d > dmax)
+ {
+ dmax = d;
+ closestFaceB = face;
+ }
+ }
+ }
+
+ {
+ const b3GpuFace_t polyB = faces[hullB->m_faceOffset+closestFaceB];
+ const int numVertices = polyB.m_numIndices;
+ for(int e0=0;e0<numVertices;e0++)
+ {
+ const float4 b = vertices[hullB->m_vertexOffset+indices[polyB.m_indexOffset+e0]];
+ worldVertsB1[pairIndex*capacityWorldVerts+numWorldVertsB1++] = transform(&b,&posB,&ornB);
+ }
+ }
+
+ int closestFaceA=-1;
+ {
+ float dmin = FLT_MAX;
+ for(int face=0;face<hullA->m_numFaces;face++)
+ {
+ const float4 Normal = make_float4(
+ faces[hullA->m_faceOffset+face].m_plane.x,
+ faces[hullA->m_faceOffset+face].m_plane.y,
+ faces[hullA->m_faceOffset+face].m_plane.z,
+ 0.f);
+ const float4 faceANormalWS = qtRotate(ornA,Normal);
+
+ float d = dot3F4(faceANormalWS,separatingNormal);
+ if (d < dmin)
+ {
+ dmin = d;
+ closestFaceA = face;
+ worldNormalsA1[pairIndex] = faceANormalWS;
+ }
+ }
+ }
+
+ int numVerticesA = faces[hullA->m_faceOffset+closestFaceA].m_numIndices;
+ for(int e0=0;e0<numVerticesA;e0++)
+ {
+ const float4 a = vertices[hullA->m_vertexOffset+indices[faces[hullA->m_faceOffset+closestFaceA].m_indexOffset+e0]];
+ worldVertsA1[pairIndex*capacityWorldVerts+e0] = transform(&a, &posA,&ornA);
+ }
+
+ clippingFaces[pairIndex].x = closestFaceA;
+ clippingFaces[pairIndex].y = closestFaceB;
+ clippingFaces[pairIndex].z = numVerticesA;
+ clippingFaces[pairIndex].w = numWorldVertsB1;
+
+
+ return numContactsOut;
+}
+
+
+
+int clipFaces(__global float4* worldVertsA1,
+ __global float4* worldNormalsA1,
+ __global float4* worldVertsB1,
+ __global float4* worldVertsB2,
+ int capacityWorldVertsB2,
+ const float minDist, float maxDist,
+ __global int4* clippingFaces,
+ int pairIndex)
+{
+ int numContactsOut = 0;
+
+ int closestFaceA = clippingFaces[pairIndex].x;
+ int closestFaceB = clippingFaces[pairIndex].y;
+ int numVertsInA = clippingFaces[pairIndex].z;
+ int numVertsInB = clippingFaces[pairIndex].w;
+
+ int numVertsOut = 0;
+
+ if (closestFaceA<0)
+ return numContactsOut;
+
+ __global float4* pVtxIn = &worldVertsB1[pairIndex*capacityWorldVertsB2];
+ __global float4* pVtxOut = &worldVertsB2[pairIndex*capacityWorldVertsB2];
+
+
+
+ // clip polygon to back of planes of all faces of hull A that are adjacent to witness face
+
+ for(int e0=0;e0<numVertsInA;e0++)
+ {
+ const float4 aw = worldVertsA1[pairIndex*capacityWorldVertsB2+e0];
+ const float4 bw = worldVertsA1[pairIndex*capacityWorldVertsB2+((e0+1)%numVertsInA)];
+ const float4 WorldEdge0 = aw - bw;
+ float4 worldPlaneAnormal1 = worldNormalsA1[pairIndex];
+ float4 planeNormalWS1 = -cross3(WorldEdge0,worldPlaneAnormal1);
+ float4 worldA1 = aw;
+ float planeEqWS1 = -dot3F4(worldA1,planeNormalWS1);
+ float4 planeNormalWS = planeNormalWS1;
+ float planeEqWS=planeEqWS1;
+ numVertsOut = clipFaceGlobal(pVtxIn, numVertsInB, planeNormalWS,planeEqWS, pVtxOut);
+ __global float4* tmp = pVtxOut;
+ pVtxOut = pVtxIn;
+ pVtxIn = tmp;
+ numVertsInB = numVertsOut;
+ numVertsOut = 0;
+ }
+
+ //float4 planeNormalWS = worldNormalsA1[pairIndex];
+ //float planeEqWS=-dot3F4(planeNormalWS,worldVertsA1[pairIndex*capacityWorldVertsB2]);
+
+
+
+ /*for (int i=0;i<numVertsInB;i++)
+ {
+ pVtxOut[i] = pVtxIn[i];
+ }*/
+
+
+
+
+ //numVertsInB=0;
+
+ float4 planeNormalWS = worldNormalsA1[pairIndex];
+ float planeEqWS=-dot3F4(planeNormalWS,worldVertsA1[pairIndex*capacityWorldVertsB2]);
+
+ for (int i=0;i<numVertsInB;i++)
+ {
+ float depth = dot3F4(planeNormalWS,pVtxIn[i])+planeEqWS;
+ if (depth <=minDist)
+ {
+ depth = minDist;
+ }
+
+ if (depth <=maxDist)
+ {
+ float4 pointInWorld = pVtxIn[i];
+ pVtxOut[numContactsOut++] = make_float4(pointInWorld.x,pointInWorld.y,pointInWorld.z,depth);
+ }
+ }
+
+ clippingFaces[pairIndex].w =numContactsOut;
+
+
+ return numContactsOut;
+
+}
+
+
+
+
+__kernel void findClippingFacesKernel( __global const int4* pairs,
+ __global const b3RigidBodyData_t* rigidBodies,
+ __global const b3Collidable_t* collidables,
+ __global const b3ConvexPolyhedronData_t* convexShapes,
+ __global const float4* vertices,
+ __global const float4* uniqueEdges,
+ __global const b3GpuFace_t* faces,
+ __global const int* indices,
+ __global const float4* separatingNormals,
+ __global const int* hasSeparatingAxis,
+ __global int4* clippingFacesOut,
+ __global float4* worldVertsA1,
+ __global float4* worldNormalsA1,
+ __global float4* worldVertsB1,
+ int capacityWorldVerts,
+ int numPairs
+ )
+{
+
+ int i = get_global_id(0);
+ int pairIndex = i;
+
+
+ float minDist = -1e30f;
+ float maxDist = 0.02f;
+
+ if (i<numPairs)
+ {
+
+ if (hasSeparatingAxis[i])
+ {
+
+ int bodyIndexA = pairs[i].x;
+ int bodyIndexB = pairs[i].y;
+
+ int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
+ int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
+
+ int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
+ int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
+
+
+
+ int numLocalContactsOut = findClippingFaces(separatingNormals[i],
+ &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],
+ rigidBodies[bodyIndexA].m_pos,rigidBodies[bodyIndexA].m_quat,
+ rigidBodies[bodyIndexB].m_pos,rigidBodies[bodyIndexB].m_quat,
+ worldVertsA1,
+ worldNormalsA1,
+ worldVertsB1,capacityWorldVerts,
+ minDist, maxDist,
+ vertices,faces,indices,
+ clippingFacesOut,i);
+
+
+ }// if (hasSeparatingAxis[i])
+ }// if (i<numPairs)
+
+}
+
+
+
+
+__kernel void clipFacesAndFindContactsKernel( __global const float4* separatingNormals,
+ __global const int* hasSeparatingAxis,
+ __global int4* clippingFacesOut,
+ __global float4* worldVertsA1,
+ __global float4* worldNormalsA1,
+ __global float4* worldVertsB1,
+ __global float4* worldVertsB2,
+ int vertexFaceCapacity,
+ int numPairs,
+ int debugMode
+ )
+{
+ int i = get_global_id(0);
+ int pairIndex = i;
+
+
+ float minDist = -1e30f;
+ float maxDist = 0.02f;
+
+ if (i<numPairs)
+ {
+
+ if (hasSeparatingAxis[i])
+ {
+
+// int bodyIndexA = pairs[i].x;
+ // int bodyIndexB = pairs[i].y;
+
+ int numLocalContactsOut = 0;
+
+ int capacityWorldVertsB2 = vertexFaceCapacity;
+
+ __global float4* pVtxIn = &worldVertsB1[pairIndex*capacityWorldVertsB2];
+ __global float4* pVtxOut = &worldVertsB2[pairIndex*capacityWorldVertsB2];
+
+
+ {
+ __global int4* clippingFaces = clippingFacesOut;
+
+
+ int closestFaceA = clippingFaces[pairIndex].x;
+ int closestFaceB = clippingFaces[pairIndex].y;
+ int numVertsInA = clippingFaces[pairIndex].z;
+ int numVertsInB = clippingFaces[pairIndex].w;
+
+ int numVertsOut = 0;
+
+ if (closestFaceA>=0)
+ {
+
+
+
+ // clip polygon to back of planes of all faces of hull A that are adjacent to witness face
+
+ for(int e0=0;e0<numVertsInA;e0++)
+ {
+ const float4 aw = worldVertsA1[pairIndex*capacityWorldVertsB2+e0];
+ const float4 bw = worldVertsA1[pairIndex*capacityWorldVertsB2+((e0+1)%numVertsInA)];
+ const float4 WorldEdge0 = aw - bw;
+ float4 worldPlaneAnormal1 = worldNormalsA1[pairIndex];
+ float4 planeNormalWS1 = -cross3(WorldEdge0,worldPlaneAnormal1);
+ float4 worldA1 = aw;
+ float planeEqWS1 = -dot3F4(worldA1,planeNormalWS1);
+ float4 planeNormalWS = planeNormalWS1;
+ float planeEqWS=planeEqWS1;
+ numVertsOut = clipFaceGlobal(pVtxIn, numVertsInB, planeNormalWS,planeEqWS, pVtxOut);
+ __global float4* tmp = pVtxOut;
+ pVtxOut = pVtxIn;
+ pVtxIn = tmp;
+ numVertsInB = numVertsOut;
+ numVertsOut = 0;
+ }
+
+ float4 planeNormalWS = worldNormalsA1[pairIndex];
+ float planeEqWS=-dot3F4(planeNormalWS,worldVertsA1[pairIndex*capacityWorldVertsB2]);
+
+ for (int i=0;i<numVertsInB;i++)
+ {
+ float depth = dot3F4(planeNormalWS,pVtxIn[i])+planeEqWS;
+ if (depth <=minDist)
+ {
+ depth = minDist;
+ }
+
+ if (depth <=maxDist)
+ {
+ float4 pointInWorld = pVtxIn[i];
+ pVtxOut[numLocalContactsOut++] = make_float4(pointInWorld.x,pointInWorld.y,pointInWorld.z,depth);
+ }
+ }
+
+ }
+ clippingFaces[pairIndex].w =numLocalContactsOut;
+
+
+ }
+
+ for (int i=0;i<numLocalContactsOut;i++)
+ pVtxIn[i] = pVtxOut[i];
+
+ }// if (hasSeparatingAxis[i])
+ }// if (i<numPairs)
+
+}
+
+
+
+
+
+__kernel void newContactReductionKernel( __global int4* pairs,
+ __global const b3RigidBodyData_t* rigidBodies,
+ __global const float4* separatingNormals,
+ __global const int* hasSeparatingAxis,
+ __global struct b3Contact4Data* globalContactsOut,
+ __global int4* clippingFaces,
+ __global float4* worldVertsB2,
+ volatile __global int* nGlobalContactsOut,
+ int vertexFaceCapacity,
+ int contactCapacity,
+ int numPairs
+ )
+{
+ int i = get_global_id(0);
+ int pairIndex = i;
+
+ int4 contactIdx;
+ contactIdx=make_int4(0,1,2,3);
+
+ if (i<numPairs)
+ {
+
+ if (hasSeparatingAxis[i])
+ {
+
+
+
+
+ int nPoints = clippingFaces[pairIndex].w;
+
+ if (nPoints>0)
+ {
+
+ __global float4* pointsIn = &worldVertsB2[pairIndex*vertexFaceCapacity];
+ float4 normal = -separatingNormals[i];
+
+ int nReducedContacts = extractManifoldSequentialGlobal(pointsIn, nPoints, normal, &contactIdx);
+
+ int mprContactIndex = pairs[pairIndex].z;
+
+ int dstIdx = mprContactIndex;
+
+ if (dstIdx<0)
+ {
+ AppendInc( nGlobalContactsOut, dstIdx );
+ }
+//#if 0
+
+ if (dstIdx < contactCapacity)
+ {
+
+ __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];
+ c->m_worldNormalOnB = -normal;
+ c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);
+ c->m_batchIdx = pairIndex;
+ int bodyA = pairs[pairIndex].x;
+ int bodyB = pairs[pairIndex].y;
+
+ pairs[pairIndex].w = dstIdx;
+
+ c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0?-bodyA:bodyA;
+ c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0?-bodyB:bodyB;
+ c->m_childIndexA =-1;
+ c->m_childIndexB =-1;
+
+ switch (nReducedContacts)
+ {
+ case 4:
+ c->m_worldPosB[3] = pointsIn[contactIdx.w];
+ case 3:
+ c->m_worldPosB[2] = pointsIn[contactIdx.z];
+ case 2:
+ c->m_worldPosB[1] = pointsIn[contactIdx.y];
+ case 1:
+ if (mprContactIndex<0)//test
+ c->m_worldPosB[0] = pointsIn[contactIdx.x];
+ default:
+ {
+ }
+ };
+
+ GET_NPOINTS(*c) = nReducedContacts;
+
+ }
+
+
+//#endif
+
+ }// if (numContactsOut>0)
+ }// if (hasSeparatingAxis[i])
+ }// if (i<numPairs)
+
+
+
+}
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/kernels/satClipHullContacts.h b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/kernels/satClipHullContacts.h
new file mode 100644
index 0000000000..f0ecfc7851
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/kernels/satClipHullContacts.h
@@ -0,0 +1,2099 @@
+//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
+static const char* satClipKernelsCL= \
+"#define TRIANGLE_NUM_CONVEX_FACES 5\n"
+"#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
+"#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
+"#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
+"#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n"
+"#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n"
+"#ifdef cl_ext_atomic_counters_32\n"
+"#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n"
+"#else\n"
+"#define counter32_t volatile __global int*\n"
+"#endif\n"
+"#define GET_GROUP_IDX get_group_id(0)\n"
+"#define GET_LOCAL_IDX get_local_id(0)\n"
+"#define GET_GLOBAL_IDX get_global_id(0)\n"
+"#define GET_GROUP_SIZE get_local_size(0)\n"
+"#define GET_NUM_GROUPS get_num_groups(0)\n"
+"#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
+"#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
+"#define AtomInc(x) atom_inc(&(x))\n"
+"#define AtomInc1(x, out) out = atom_inc(&(x))\n"
+"#define AppendInc(x, out) out = atomic_inc(x)\n"
+"#define AtomAdd(x, value) atom_add(&(x), value)\n"
+"#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )\n"
+"#define AtomXhg(x, value) atom_xchg ( &(x), value )\n"
+"#define max2 max\n"
+"#define min2 min\n"
+"typedef unsigned int u32;\n"
+"#ifndef B3_CONTACT4DATA_H\n"
+"#define B3_CONTACT4DATA_H\n"
+"#ifndef B3_FLOAT4_H\n"
+"#define B3_FLOAT4_H\n"
+"#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+"#define B3_PLATFORM_DEFINITIONS_H\n"
+"struct MyTest\n"
+"{\n"
+" int bla;\n"
+"};\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
+"#define B3_LARGE_FLOAT 1e18f\n"
+"#define B3_INFINITY 1e18f\n"
+"#define b3Assert(a)\n"
+"#define b3ConstArray(a) __global const a*\n"
+"#define b3AtomicInc atomic_inc\n"
+"#define b3AtomicAdd atomic_add\n"
+"#define b3Fabs fabs\n"
+"#define b3Sqrt native_sqrt\n"
+"#define b3Sin native_sin\n"
+"#define b3Cos native_cos\n"
+"#define B3_STATIC\n"
+"#endif\n"
+"#endif\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+" typedef float4 b3Float4;\n"
+" #define b3Float4ConstArg const b3Float4\n"
+" #define b3MakeFloat4 (float4)\n"
+" float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+" {\n"
+" float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+" float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+" return dot(a1, b1);\n"
+" }\n"
+" b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+" {\n"
+" float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+" float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+" return cross(a1, b1);\n"
+" }\n"
+" #define b3MinFloat4 min\n"
+" #define b3MaxFloat4 max\n"
+" #define b3Normalized(a) normalize(a)\n"
+"#endif \n"
+" \n"
+"inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
+"{\n"
+" if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6) \n"
+" return false;\n"
+" return true;\n"
+"}\n"
+"inline int b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
+"{\n"
+" float maxDot = -B3_INFINITY;\n"
+" int i = 0;\n"
+" int ptIndex = -1;\n"
+" for( i = 0; i < vecLen; i++ )\n"
+" {\n"
+" float dot = b3Dot3F4(vecArray[i],vec);\n"
+" \n"
+" if( dot > maxDot )\n"
+" {\n"
+" maxDot = dot;\n"
+" ptIndex = i;\n"
+" }\n"
+" }\n"
+" b3Assert(ptIndex>=0);\n"
+" if (ptIndex<0)\n"
+" {\n"
+" ptIndex = 0;\n"
+" }\n"
+" *dotOut = maxDot;\n"
+" return ptIndex;\n"
+"}\n"
+"#endif //B3_FLOAT4_H\n"
+"typedef struct b3Contact4Data b3Contact4Data_t;\n"
+"struct b3Contact4Data\n"
+"{\n"
+" b3Float4 m_worldPosB[4];\n"
+"// b3Float4 m_localPosA[4];\n"
+"// b3Float4 m_localPosB[4];\n"
+" b3Float4 m_worldNormalOnB; // w: m_nPoints\n"
+" unsigned short m_restituitionCoeffCmp;\n"
+" unsigned short m_frictionCoeffCmp;\n"
+" int m_batchIdx;\n"
+" int m_bodyAPtrAndSignBit;//x:m_bodyAPtr, y:m_bodyBPtr\n"
+" int m_bodyBPtrAndSignBit;\n"
+" int m_childIndexA;\n"
+" int m_childIndexB;\n"
+" int m_unused1;\n"
+" int m_unused2;\n"
+"};\n"
+"inline int b3Contact4Data_getNumPoints(const struct b3Contact4Data* contact)\n"
+"{\n"
+" return (int)contact->m_worldNormalOnB.w;\n"
+"};\n"
+"inline void b3Contact4Data_setNumPoints(struct b3Contact4Data* contact, int numPoints)\n"
+"{\n"
+" contact->m_worldNormalOnB.w = (float)numPoints;\n"
+"};\n"
+"#endif //B3_CONTACT4DATA_H\n"
+"#ifndef B3_CONVEX_POLYHEDRON_DATA_H\n"
+"#define B3_CONVEX_POLYHEDRON_DATA_H\n"
+"#ifndef B3_FLOAT4_H\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"#endif \n"
+"#endif //B3_FLOAT4_H\n"
+"#ifndef B3_QUAT_H\n"
+"#define B3_QUAT_H\n"
+"#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"#endif\n"
+"#endif\n"
+"#ifndef B3_FLOAT4_H\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"#endif \n"
+"#endif //B3_FLOAT4_H\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+" typedef float4 b3Quat;\n"
+" #define b3QuatConstArg const b3Quat\n"
+" \n"
+" \n"
+"inline float4 b3FastNormalize4(float4 v)\n"
+"{\n"
+" v = (float4)(v.xyz,0.f);\n"
+" return fast_normalize(v);\n"
+"}\n"
+" \n"
+"inline b3Quat b3QuatMul(b3Quat a, b3Quat b);\n"
+"inline b3Quat b3QuatNormalized(b3QuatConstArg in);\n"
+"inline b3Quat b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec);\n"
+"inline b3Quat b3QuatInvert(b3QuatConstArg q);\n"
+"inline b3Quat b3QuatInverse(b3QuatConstArg q);\n"
+"inline b3Quat b3QuatMul(b3QuatConstArg a, b3QuatConstArg b)\n"
+"{\n"
+" b3Quat ans;\n"
+" ans = b3Cross3( a, b );\n"
+" ans += a.w*b+b.w*a;\n"
+"// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
+" ans.w = a.w*b.w - b3Dot3F4(a, b);\n"
+" return ans;\n"
+"}\n"
+"inline b3Quat b3QuatNormalized(b3QuatConstArg in)\n"
+"{\n"
+" b3Quat q;\n"
+" q=in;\n"
+" //return b3FastNormalize4(in);\n"
+" float len = native_sqrt(dot(q, q));\n"
+" if(len > 0.f)\n"
+" {\n"
+" q *= 1.f / len;\n"
+" }\n"
+" else\n"
+" {\n"
+" q.x = q.y = q.z = 0.f;\n"
+" q.w = 1.f;\n"
+" }\n"
+" return q;\n"
+"}\n"
+"inline float4 b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
+"{\n"
+" b3Quat qInv = b3QuatInvert( q );\n"
+" float4 vcpy = vec;\n"
+" vcpy.w = 0.f;\n"
+" float4 out = b3QuatMul(b3QuatMul(q,vcpy),qInv);\n"
+" return out;\n"
+"}\n"
+"inline b3Quat b3QuatInverse(b3QuatConstArg q)\n"
+"{\n"
+" return (b3Quat)(-q.xyz, q.w);\n"
+"}\n"
+"inline b3Quat b3QuatInvert(b3QuatConstArg q)\n"
+"{\n"
+" return (b3Quat)(-q.xyz, q.w);\n"
+"}\n"
+"inline float4 b3QuatInvRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
+"{\n"
+" return b3QuatRotate( b3QuatInvert( q ), vec );\n"
+"}\n"
+"inline b3Float4 b3TransformPoint(b3Float4ConstArg point, b3Float4ConstArg translation, b3QuatConstArg orientation)\n"
+"{\n"
+" return b3QuatRotate( orientation, point ) + (translation);\n"
+"}\n"
+" \n"
+"#endif \n"
+"#endif //B3_QUAT_H\n"
+"typedef struct b3GpuFace b3GpuFace_t;\n"
+"struct b3GpuFace\n"
+"{\n"
+" b3Float4 m_plane;\n"
+" int m_indexOffset;\n"
+" int m_numIndices;\n"
+" int m_unusedPadding1;\n"
+" int m_unusedPadding2;\n"
+"};\n"
+"typedef struct b3ConvexPolyhedronData b3ConvexPolyhedronData_t;\n"
+"struct b3ConvexPolyhedronData\n"
+"{\n"
+" b3Float4 m_localCenter;\n"
+" b3Float4 m_extents;\n"
+" b3Float4 mC;\n"
+" b3Float4 mE;\n"
+" float m_radius;\n"
+" int m_faceOffset;\n"
+" int m_numFaces;\n"
+" int m_numVertices;\n"
+" int m_vertexOffset;\n"
+" int m_uniqueEdgesOffset;\n"
+" int m_numUniqueEdges;\n"
+" int m_unused;\n"
+"};\n"
+"#endif //B3_CONVEX_POLYHEDRON_DATA_H\n"
+"#ifndef B3_COLLIDABLE_H\n"
+"#define B3_COLLIDABLE_H\n"
+"#ifndef B3_FLOAT4_H\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"#endif \n"
+"#endif //B3_FLOAT4_H\n"
+"#ifndef B3_QUAT_H\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"#endif \n"
+"#endif //B3_QUAT_H\n"
+"enum b3ShapeTypes\n"
+"{\n"
+" SHAPE_HEIGHT_FIELD=1,\n"
+" SHAPE_CONVEX_HULL=3,\n"
+" SHAPE_PLANE=4,\n"
+" SHAPE_CONCAVE_TRIMESH=5,\n"
+" SHAPE_COMPOUND_OF_CONVEX_HULLS=6,\n"
+" SHAPE_SPHERE=7,\n"
+" MAX_NUM_SHAPE_TYPES,\n"
+"};\n"
+"typedef struct b3Collidable b3Collidable_t;\n"
+"struct b3Collidable\n"
+"{\n"
+" union {\n"
+" int m_numChildShapes;\n"
+" int m_bvhIndex;\n"
+" };\n"
+" union\n"
+" {\n"
+" float m_radius;\n"
+" int m_compoundBvhIndex;\n"
+" };\n"
+" int m_shapeType;\n"
+" int m_shapeIndex;\n"
+"};\n"
+"typedef struct b3GpuChildShape b3GpuChildShape_t;\n"
+"struct b3GpuChildShape\n"
+"{\n"
+" b3Float4 m_childPosition;\n"
+" b3Quat m_childOrientation;\n"
+" int m_shapeIndex;\n"
+" int m_unused0;\n"
+" int m_unused1;\n"
+" int m_unused2;\n"
+"};\n"
+"struct b3CompoundOverlappingPair\n"
+"{\n"
+" int m_bodyIndexA;\n"
+" int m_bodyIndexB;\n"
+"// int m_pairType;\n"
+" int m_childShapeIndexA;\n"
+" int m_childShapeIndexB;\n"
+"};\n"
+"#endif //B3_COLLIDABLE_H\n"
+"#ifndef B3_RIGIDBODY_DATA_H\n"
+"#define B3_RIGIDBODY_DATA_H\n"
+"#ifndef B3_FLOAT4_H\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"#endif \n"
+"#endif //B3_FLOAT4_H\n"
+"#ifndef B3_QUAT_H\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"#endif \n"
+"#endif //B3_QUAT_H\n"
+"#ifndef B3_MAT3x3_H\n"
+"#define B3_MAT3x3_H\n"
+"#ifndef B3_QUAT_H\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"#endif \n"
+"#endif //B3_QUAT_H\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"typedef struct\n"
+"{\n"
+" b3Float4 m_row[3];\n"
+"}b3Mat3x3;\n"
+"#define b3Mat3x3ConstArg const b3Mat3x3\n"
+"#define b3GetRow(m,row) (m.m_row[row])\n"
+"inline b3Mat3x3 b3QuatGetRotationMatrix(b3Quat quat)\n"
+"{\n"
+" b3Float4 quat2 = (b3Float4)(quat.x*quat.x, quat.y*quat.y, quat.z*quat.z, 0.f);\n"
+" b3Mat3x3 out;\n"
+" out.m_row[0].x=1-2*quat2.y-2*quat2.z;\n"
+" out.m_row[0].y=2*quat.x*quat.y-2*quat.w*quat.z;\n"
+" out.m_row[0].z=2*quat.x*quat.z+2*quat.w*quat.y;\n"
+" out.m_row[0].w = 0.f;\n"
+" out.m_row[1].x=2*quat.x*quat.y+2*quat.w*quat.z;\n"
+" out.m_row[1].y=1-2*quat2.x-2*quat2.z;\n"
+" out.m_row[1].z=2*quat.y*quat.z-2*quat.w*quat.x;\n"
+" out.m_row[1].w = 0.f;\n"
+" out.m_row[2].x=2*quat.x*quat.z-2*quat.w*quat.y;\n"
+" out.m_row[2].y=2*quat.y*quat.z+2*quat.w*quat.x;\n"
+" out.m_row[2].z=1-2*quat2.x-2*quat2.y;\n"
+" out.m_row[2].w = 0.f;\n"
+" return out;\n"
+"}\n"
+"inline b3Mat3x3 b3AbsoluteMat3x3(b3Mat3x3ConstArg matIn)\n"
+"{\n"
+" b3Mat3x3 out;\n"
+" out.m_row[0] = fabs(matIn.m_row[0]);\n"
+" out.m_row[1] = fabs(matIn.m_row[1]);\n"
+" out.m_row[2] = fabs(matIn.m_row[2]);\n"
+" return out;\n"
+"}\n"
+"__inline\n"
+"b3Mat3x3 mtZero();\n"
+"__inline\n"
+"b3Mat3x3 mtIdentity();\n"
+"__inline\n"
+"b3Mat3x3 mtTranspose(b3Mat3x3 m);\n"
+"__inline\n"
+"b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b);\n"
+"__inline\n"
+"b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b);\n"
+"__inline\n"
+"b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b);\n"
+"__inline\n"
+"b3Mat3x3 mtZero()\n"
+"{\n"
+" b3Mat3x3 m;\n"
+" m.m_row[0] = (b3Float4)(0.f);\n"
+" m.m_row[1] = (b3Float4)(0.f);\n"
+" m.m_row[2] = (b3Float4)(0.f);\n"
+" return m;\n"
+"}\n"
+"__inline\n"
+"b3Mat3x3 mtIdentity()\n"
+"{\n"
+" b3Mat3x3 m;\n"
+" m.m_row[0] = (b3Float4)(1,0,0,0);\n"
+" m.m_row[1] = (b3Float4)(0,1,0,0);\n"
+" m.m_row[2] = (b3Float4)(0,0,1,0);\n"
+" return m;\n"
+"}\n"
+"__inline\n"
+"b3Mat3x3 mtTranspose(b3Mat3x3 m)\n"
+"{\n"
+" b3Mat3x3 out;\n"
+" out.m_row[0] = (b3Float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);\n"
+" out.m_row[1] = (b3Float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);\n"
+" out.m_row[2] = (b3Float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);\n"
+" return out;\n"
+"}\n"
+"__inline\n"
+"b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b)\n"
+"{\n"
+" b3Mat3x3 transB;\n"
+" transB = mtTranspose( b );\n"
+" b3Mat3x3 ans;\n"
+" // why this doesn't run when 0ing in the for{}\n"
+" a.m_row[0].w = 0.f;\n"
+" a.m_row[1].w = 0.f;\n"
+" a.m_row[2].w = 0.f;\n"
+" for(int i=0; i<3; i++)\n"
+" {\n"
+"// a.m_row[i].w = 0.f;\n"
+" ans.m_row[i].x = b3Dot3F4(a.m_row[i],transB.m_row[0]);\n"
+" ans.m_row[i].y = b3Dot3F4(a.m_row[i],transB.m_row[1]);\n"
+" ans.m_row[i].z = b3Dot3F4(a.m_row[i],transB.m_row[2]);\n"
+" ans.m_row[i].w = 0.f;\n"
+" }\n"
+" return ans;\n"
+"}\n"
+"__inline\n"
+"b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b)\n"
+"{\n"
+" b3Float4 ans;\n"
+" ans.x = b3Dot3F4( a.m_row[0], b );\n"
+" ans.y = b3Dot3F4( a.m_row[1], b );\n"
+" ans.z = b3Dot3F4( a.m_row[2], b );\n"
+" ans.w = 0.f;\n"
+" return ans;\n"
+"}\n"
+"__inline\n"
+"b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b)\n"
+"{\n"
+" b3Float4 colx = b3MakeFloat4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
+" b3Float4 coly = b3MakeFloat4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
+" b3Float4 colz = b3MakeFloat4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
+" b3Float4 ans;\n"
+" ans.x = b3Dot3F4( a, colx );\n"
+" ans.y = b3Dot3F4( a, coly );\n"
+" ans.z = b3Dot3F4( a, colz );\n"
+" return ans;\n"
+"}\n"
+"#endif\n"
+"#endif //B3_MAT3x3_H\n"
+"typedef struct b3RigidBodyData b3RigidBodyData_t;\n"
+"struct b3RigidBodyData\n"
+"{\n"
+" b3Float4 m_pos;\n"
+" b3Quat m_quat;\n"
+" b3Float4 m_linVel;\n"
+" b3Float4 m_angVel;\n"
+" int m_collidableIdx;\n"
+" float m_invMass;\n"
+" float m_restituitionCoeff;\n"
+" float m_frictionCoeff;\n"
+"};\n"
+"typedef struct b3InertiaData b3InertiaData_t;\n"
+"struct b3InertiaData\n"
+"{\n"
+" b3Mat3x3 m_invInertiaWorld;\n"
+" b3Mat3x3 m_initInvInertia;\n"
+"};\n"
+"#endif //B3_RIGIDBODY_DATA_H\n"
+" \n"
+"#define GET_NPOINTS(x) (x).m_worldNormalOnB.w\n"
+"#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n"
+"#define make_float4 (float4)\n"
+"#define make_float2 (float2)\n"
+"#define make_uint4 (uint4)\n"
+"#define make_int4 (int4)\n"
+"#define make_uint2 (uint2)\n"
+"#define make_int2 (int2)\n"
+"__inline\n"
+"float fastDiv(float numerator, float denominator)\n"
+"{\n"
+" return native_divide(numerator, denominator); \n"
+"// return numerator/denominator; \n"
+"}\n"
+"__inline\n"
+"float4 fastDiv4(float4 numerator, float4 denominator)\n"
+"{\n"
+" return native_divide(numerator, denominator); \n"
+"}\n"
+"__inline\n"
+"float4 cross3(float4 a, float4 b)\n"
+"{\n"
+" return cross(a,b);\n"
+"}\n"
+"//#define dot3F4 dot\n"
+"__inline\n"
+"float dot3F4(float4 a, float4 b)\n"
+"{\n"
+" float4 a1 = make_float4(a.xyz,0.f);\n"
+" float4 b1 = make_float4(b.xyz,0.f);\n"
+" return dot(a1, b1);\n"
+"}\n"
+"__inline\n"
+"float4 fastNormalize4(float4 v)\n"
+"{\n"
+" return fast_normalize(v);\n"
+"}\n"
+"///////////////////////////////////////\n"
+"// Quaternion\n"
+"///////////////////////////////////////\n"
+"typedef float4 Quaternion;\n"
+"__inline\n"
+"Quaternion qtMul(Quaternion a, Quaternion b);\n"
+"__inline\n"
+"Quaternion qtNormalize(Quaternion in);\n"
+"__inline\n"
+"float4 qtRotate(Quaternion q, float4 vec);\n"
+"__inline\n"
+"Quaternion qtInvert(Quaternion q);\n"
+"__inline\n"
+"Quaternion qtMul(Quaternion a, Quaternion b)\n"
+"{\n"
+" Quaternion ans;\n"
+" ans = cross3( a, b );\n"
+" ans += a.w*b+b.w*a;\n"
+"// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
+" ans.w = a.w*b.w - dot3F4(a, b);\n"
+" return ans;\n"
+"}\n"
+"__inline\n"
+"Quaternion qtNormalize(Quaternion in)\n"
+"{\n"
+" return fastNormalize4(in);\n"
+"// in /= length( in );\n"
+"// return in;\n"
+"}\n"
+"__inline\n"
+"float4 qtRotate(Quaternion q, float4 vec)\n"
+"{\n"
+" Quaternion qInv = qtInvert( q );\n"
+" float4 vcpy = vec;\n"
+" vcpy.w = 0.f;\n"
+" float4 out = qtMul(qtMul(q,vcpy),qInv);\n"
+" return out;\n"
+"}\n"
+"__inline\n"
+"Quaternion qtInvert(Quaternion q)\n"
+"{\n"
+" return (Quaternion)(-q.xyz, q.w);\n"
+"}\n"
+"__inline\n"
+"float4 qtInvRotate(const Quaternion q, float4 vec)\n"
+"{\n"
+" return qtRotate( qtInvert( q ), vec );\n"
+"}\n"
+"__inline\n"
+"float4 transform(const float4* p, const float4* translation, const Quaternion* orientation)\n"
+"{\n"
+" return qtRotate( *orientation, *p ) + (*translation);\n"
+"}\n"
+"__inline\n"
+"float4 normalize3(const float4 a)\n"
+"{\n"
+" float4 n = make_float4(a.x, a.y, a.z, 0.f);\n"
+" return fastNormalize4( n );\n"
+"}\n"
+"__inline float4 lerp3(const float4 a,const float4 b, float t)\n"
+"{\n"
+" return make_float4( a.x + (b.x - a.x) * t,\n"
+" a.y + (b.y - a.y) * t,\n"
+" a.z + (b.z - a.z) * t,\n"
+" 0.f);\n"
+"}\n"
+"// Clips a face to the back of a plane, return the number of vertices out, stored in ppVtxOut\n"
+"int clipFaceGlobal(__global const float4* pVtxIn, int numVertsIn, float4 planeNormalWS,float planeEqWS, __global float4* ppVtxOut)\n"
+"{\n"
+" \n"
+" int ve;\n"
+" float ds, de;\n"
+" int numVertsOut = 0;\n"
+" //double-check next test\n"
+" if (numVertsIn < 2)\n"
+" return 0;\n"
+" \n"
+" float4 firstVertex=pVtxIn[numVertsIn-1];\n"
+" float4 endVertex = pVtxIn[0];\n"
+" \n"
+" ds = dot3F4(planeNormalWS,firstVertex)+planeEqWS;\n"
+" \n"
+" for (ve = 0; ve < numVertsIn; ve++)\n"
+" {\n"
+" endVertex=pVtxIn[ve];\n"
+" de = dot3F4(planeNormalWS,endVertex)+planeEqWS;\n"
+" if (ds<0)\n"
+" {\n"
+" if (de<0)\n"
+" {\n"
+" // Start < 0, end < 0, so output endVertex\n"
+" ppVtxOut[numVertsOut++] = endVertex;\n"
+" }\n"
+" else\n"
+" {\n"
+" // Start < 0, end >= 0, so output intersection\n"
+" ppVtxOut[numVertsOut++] = lerp3(firstVertex, endVertex,(ds * 1.f/(ds - de)) );\n"
+" }\n"
+" }\n"
+" else\n"
+" {\n"
+" if (de<0)\n"
+" {\n"
+" // Start >= 0, end < 0 so output intersection and end\n"
+" ppVtxOut[numVertsOut++] = lerp3(firstVertex, endVertex,(ds * 1.f/(ds - de)) );\n"
+" ppVtxOut[numVertsOut++] = endVertex;\n"
+" }\n"
+" }\n"
+" firstVertex = endVertex;\n"
+" ds = de;\n"
+" }\n"
+" return numVertsOut;\n"
+"}\n"
+"// Clips a face to the back of a plane, return the number of vertices out, stored in ppVtxOut\n"
+"int clipFace(const float4* pVtxIn, int numVertsIn, float4 planeNormalWS,float planeEqWS, float4* ppVtxOut)\n"
+"{\n"
+" \n"
+" int ve;\n"
+" float ds, de;\n"
+" int numVertsOut = 0;\n"
+"//double-check next test\n"
+" if (numVertsIn < 2)\n"
+" return 0;\n"
+" float4 firstVertex=pVtxIn[numVertsIn-1];\n"
+" float4 endVertex = pVtxIn[0];\n"
+" \n"
+" ds = dot3F4(planeNormalWS,firstVertex)+planeEqWS;\n"
+" for (ve = 0; ve < numVertsIn; ve++)\n"
+" {\n"
+" endVertex=pVtxIn[ve];\n"
+" de = dot3F4(planeNormalWS,endVertex)+planeEqWS;\n"
+" if (ds<0)\n"
+" {\n"
+" if (de<0)\n"
+" {\n"
+" // Start < 0, end < 0, so output endVertex\n"
+" ppVtxOut[numVertsOut++] = endVertex;\n"
+" }\n"
+" else\n"
+" {\n"
+" // Start < 0, end >= 0, so output intersection\n"
+" ppVtxOut[numVertsOut++] = lerp3(firstVertex, endVertex,(ds * 1.f/(ds - de)) );\n"
+" }\n"
+" }\n"
+" else\n"
+" {\n"
+" if (de<0)\n"
+" {\n"
+" // Start >= 0, end < 0 so output intersection and end\n"
+" ppVtxOut[numVertsOut++] = lerp3(firstVertex, endVertex,(ds * 1.f/(ds - de)) );\n"
+" ppVtxOut[numVertsOut++] = endVertex;\n"
+" }\n"
+" }\n"
+" firstVertex = endVertex;\n"
+" ds = de;\n"
+" }\n"
+" return numVertsOut;\n"
+"}\n"
+"int clipFaceAgainstHull(const float4 separatingNormal, __global const b3ConvexPolyhedronData_t* hullA, \n"
+" const float4 posA, const Quaternion ornA, float4* worldVertsB1, int numWorldVertsB1,\n"
+" float4* worldVertsB2, int capacityWorldVertsB2,\n"
+" const float minDist, float maxDist,\n"
+" __global const float4* vertices,\n"
+" __global const b3GpuFace_t* faces,\n"
+" __global const int* indices,\n"
+" float4* contactsOut,\n"
+" int contactCapacity)\n"
+"{\n"
+" int numContactsOut = 0;\n"
+" float4* pVtxIn = worldVertsB1;\n"
+" float4* pVtxOut = worldVertsB2;\n"
+" \n"
+" int numVertsIn = numWorldVertsB1;\n"
+" int numVertsOut = 0;\n"
+" int closestFaceA=-1;\n"
+" {\n"
+" float dmin = FLT_MAX;\n"
+" for(int face=0;face<hullA->m_numFaces;face++)\n"
+" {\n"
+" const float4 Normal = make_float4(\n"
+" faces[hullA->m_faceOffset+face].m_plane.x, \n"
+" faces[hullA->m_faceOffset+face].m_plane.y, \n"
+" faces[hullA->m_faceOffset+face].m_plane.z,0.f);\n"
+" const float4 faceANormalWS = qtRotate(ornA,Normal);\n"
+" \n"
+" float d = dot3F4(faceANormalWS,separatingNormal);\n"
+" if (d < dmin)\n"
+" {\n"
+" dmin = d;\n"
+" closestFaceA = face;\n"
+" }\n"
+" }\n"
+" }\n"
+" if (closestFaceA<0)\n"
+" return numContactsOut;\n"
+" b3GpuFace_t polyA = faces[hullA->m_faceOffset+closestFaceA];\n"
+" // clip polygon to back of planes of all faces of hull A that are adjacent to witness face\n"
+" int numVerticesA = polyA.m_numIndices;\n"
+" for(int e0=0;e0<numVerticesA;e0++)\n"
+" {\n"
+" const float4 a = vertices[hullA->m_vertexOffset+indices[polyA.m_indexOffset+e0]];\n"
+" const float4 b = vertices[hullA->m_vertexOffset+indices[polyA.m_indexOffset+((e0+1)%numVerticesA)]];\n"
+" const float4 edge0 = a - b;\n"
+" const float4 WorldEdge0 = qtRotate(ornA,edge0);\n"
+" float4 planeNormalA = make_float4(polyA.m_plane.x,polyA.m_plane.y,polyA.m_plane.z,0.f);\n"
+" float4 worldPlaneAnormal1 = qtRotate(ornA,planeNormalA);\n"
+" float4 planeNormalWS1 = -cross3(WorldEdge0,worldPlaneAnormal1);\n"
+" float4 worldA1 = transform(&a,&posA,&ornA);\n"
+" float planeEqWS1 = -dot3F4(worldA1,planeNormalWS1);\n"
+" \n"
+" float4 planeNormalWS = planeNormalWS1;\n"
+" float planeEqWS=planeEqWS1;\n"
+" \n"
+" //clip face\n"
+" //clipFace(*pVtxIn, *pVtxOut,planeNormalWS,planeEqWS);\n"
+" numVertsOut = clipFace(pVtxIn, numVertsIn, planeNormalWS,planeEqWS, pVtxOut);\n"
+" //btSwap(pVtxIn,pVtxOut);\n"
+" float4* tmp = pVtxOut;\n"
+" pVtxOut = pVtxIn;\n"
+" pVtxIn = tmp;\n"
+" numVertsIn = numVertsOut;\n"
+" numVertsOut = 0;\n"
+" }\n"
+" \n"
+" // only keep points that are behind the witness face\n"
+" {\n"
+" float4 localPlaneNormal = make_float4(polyA.m_plane.x,polyA.m_plane.y,polyA.m_plane.z,0.f);\n"
+" float localPlaneEq = polyA.m_plane.w;\n"
+" float4 planeNormalWS = qtRotate(ornA,localPlaneNormal);\n"
+" float planeEqWS=localPlaneEq-dot3F4(planeNormalWS,posA);\n"
+" for (int i=0;i<numVertsIn;i++)\n"
+" {\n"
+" float depth = dot3F4(planeNormalWS,pVtxIn[i])+planeEqWS;\n"
+" if (depth <=minDist)\n"
+" {\n"
+" depth = minDist;\n"
+" }\n"
+" if (depth <=maxDist)\n"
+" {\n"
+" float4 pointInWorld = pVtxIn[i];\n"
+" //resultOut.addContactPoint(separatingNormal,point,depth);\n"
+" contactsOut[numContactsOut++] = make_float4(pointInWorld.x,pointInWorld.y,pointInWorld.z,depth);\n"
+" }\n"
+" }\n"
+" }\n"
+" return numContactsOut;\n"
+"}\n"
+"int clipFaceAgainstHullLocalA(const float4 separatingNormal, const b3ConvexPolyhedronData_t* hullA, \n"
+" const float4 posA, const Quaternion ornA, float4* worldVertsB1, int numWorldVertsB1,\n"
+" float4* worldVertsB2, int capacityWorldVertsB2,\n"
+" const float minDist, float maxDist,\n"
+" const float4* verticesA,\n"
+" const b3GpuFace_t* facesA,\n"
+" const int* indicesA,\n"
+" __global const float4* verticesB,\n"
+" __global const b3GpuFace_t* facesB,\n"
+" __global const int* indicesB,\n"
+" float4* contactsOut,\n"
+" int contactCapacity)\n"
+"{\n"
+" int numContactsOut = 0;\n"
+" float4* pVtxIn = worldVertsB1;\n"
+" float4* pVtxOut = worldVertsB2;\n"
+" \n"
+" int numVertsIn = numWorldVertsB1;\n"
+" int numVertsOut = 0;\n"
+" int closestFaceA=-1;\n"
+" {\n"
+" float dmin = FLT_MAX;\n"
+" for(int face=0;face<hullA->m_numFaces;face++)\n"
+" {\n"
+" const float4 Normal = make_float4(\n"
+" facesA[hullA->m_faceOffset+face].m_plane.x, \n"
+" facesA[hullA->m_faceOffset+face].m_plane.y, \n"
+" facesA[hullA->m_faceOffset+face].m_plane.z,0.f);\n"
+" const float4 faceANormalWS = qtRotate(ornA,Normal);\n"
+" \n"
+" float d = dot3F4(faceANormalWS,separatingNormal);\n"
+" if (d < dmin)\n"
+" {\n"
+" dmin = d;\n"
+" closestFaceA = face;\n"
+" }\n"
+" }\n"
+" }\n"
+" if (closestFaceA<0)\n"
+" return numContactsOut;\n"
+" b3GpuFace_t polyA = facesA[hullA->m_faceOffset+closestFaceA];\n"
+" // clip polygon to back of planes of all faces of hull A that are adjacent to witness face\n"
+" int numVerticesA = polyA.m_numIndices;\n"
+" for(int e0=0;e0<numVerticesA;e0++)\n"
+" {\n"
+" const float4 a = verticesA[hullA->m_vertexOffset+indicesA[polyA.m_indexOffset+e0]];\n"
+" const float4 b = verticesA[hullA->m_vertexOffset+indicesA[polyA.m_indexOffset+((e0+1)%numVerticesA)]];\n"
+" const float4 edge0 = a - b;\n"
+" const float4 WorldEdge0 = qtRotate(ornA,edge0);\n"
+" float4 planeNormalA = make_float4(polyA.m_plane.x,polyA.m_plane.y,polyA.m_plane.z,0.f);\n"
+" float4 worldPlaneAnormal1 = qtRotate(ornA,planeNormalA);\n"
+" float4 planeNormalWS1 = -cross3(WorldEdge0,worldPlaneAnormal1);\n"
+" float4 worldA1 = transform(&a,&posA,&ornA);\n"
+" float planeEqWS1 = -dot3F4(worldA1,planeNormalWS1);\n"
+" \n"
+" float4 planeNormalWS = planeNormalWS1;\n"
+" float planeEqWS=planeEqWS1;\n"
+" \n"
+" //clip face\n"
+" //clipFace(*pVtxIn, *pVtxOut,planeNormalWS,planeEqWS);\n"
+" numVertsOut = clipFace(pVtxIn, numVertsIn, planeNormalWS,planeEqWS, pVtxOut);\n"
+" //btSwap(pVtxIn,pVtxOut);\n"
+" float4* tmp = pVtxOut;\n"
+" pVtxOut = pVtxIn;\n"
+" pVtxIn = tmp;\n"
+" numVertsIn = numVertsOut;\n"
+" numVertsOut = 0;\n"
+" }\n"
+" \n"
+" // only keep points that are behind the witness face\n"
+" {\n"
+" float4 localPlaneNormal = make_float4(polyA.m_plane.x,polyA.m_plane.y,polyA.m_plane.z,0.f);\n"
+" float localPlaneEq = polyA.m_plane.w;\n"
+" float4 planeNormalWS = qtRotate(ornA,localPlaneNormal);\n"
+" float planeEqWS=localPlaneEq-dot3F4(planeNormalWS,posA);\n"
+" for (int i=0;i<numVertsIn;i++)\n"
+" {\n"
+" float depth = dot3F4(planeNormalWS,pVtxIn[i])+planeEqWS;\n"
+" if (depth <=minDist)\n"
+" {\n"
+" depth = minDist;\n"
+" }\n"
+" if (depth <=maxDist)\n"
+" {\n"
+" float4 pointInWorld = pVtxIn[i];\n"
+" //resultOut.addContactPoint(separatingNormal,point,depth);\n"
+" contactsOut[numContactsOut++] = make_float4(pointInWorld.x,pointInWorld.y,pointInWorld.z,depth);\n"
+" }\n"
+" }\n"
+" }\n"
+" return numContactsOut;\n"
+"}\n"
+"int clipHullAgainstHull(const float4 separatingNormal,\n"
+" __global const b3ConvexPolyhedronData_t* hullA, __global const b3ConvexPolyhedronData_t* hullB, \n"
+" const float4 posA, const Quaternion ornA,const float4 posB, const Quaternion ornB, \n"
+" float4* worldVertsB1, float4* worldVertsB2, int capacityWorldVerts,\n"
+" const float minDist, float maxDist,\n"
+" __global const float4* vertices,\n"
+" __global const b3GpuFace_t* faces,\n"
+" __global const int* indices,\n"
+" float4* localContactsOut,\n"
+" int localContactCapacity)\n"
+"{\n"
+" int numContactsOut = 0;\n"
+" int numWorldVertsB1= 0;\n"
+" int closestFaceB=-1;\n"
+" float dmax = -FLT_MAX;\n"
+" {\n"
+" for(int face=0;face<hullB->m_numFaces;face++)\n"
+" {\n"
+" const float4 Normal = make_float4(faces[hullB->m_faceOffset+face].m_plane.x, \n"
+" faces[hullB->m_faceOffset+face].m_plane.y, faces[hullB->m_faceOffset+face].m_plane.z,0.f);\n"
+" const float4 WorldNormal = qtRotate(ornB, Normal);\n"
+" float d = dot3F4(WorldNormal,separatingNormal);\n"
+" if (d > dmax)\n"
+" {\n"
+" dmax = d;\n"
+" closestFaceB = face;\n"
+" }\n"
+" }\n"
+" }\n"
+" {\n"
+" const b3GpuFace_t polyB = faces[hullB->m_faceOffset+closestFaceB];\n"
+" const int numVertices = polyB.m_numIndices;\n"
+" for(int e0=0;e0<numVertices;e0++)\n"
+" {\n"
+" const float4 b = vertices[hullB->m_vertexOffset+indices[polyB.m_indexOffset+e0]];\n"
+" worldVertsB1[numWorldVertsB1++] = transform(&b,&posB,&ornB);\n"
+" }\n"
+" }\n"
+" if (closestFaceB>=0)\n"
+" {\n"
+" numContactsOut = clipFaceAgainstHull(separatingNormal, hullA, \n"
+" posA,ornA,\n"
+" worldVertsB1,numWorldVertsB1,worldVertsB2,capacityWorldVerts, minDist, maxDist,vertices,\n"
+" faces,\n"
+" indices,localContactsOut,localContactCapacity);\n"
+" }\n"
+" return numContactsOut;\n"
+"}\n"
+"int clipHullAgainstHullLocalA(const float4 separatingNormal,\n"
+" const b3ConvexPolyhedronData_t* hullA, __global const b3ConvexPolyhedronData_t* hullB, \n"
+" const float4 posA, const Quaternion ornA,const float4 posB, const Quaternion ornB, \n"
+" float4* worldVertsB1, float4* worldVertsB2, int capacityWorldVerts,\n"
+" const float minDist, float maxDist,\n"
+" const float4* verticesA,\n"
+" const b3GpuFace_t* facesA,\n"
+" const int* indicesA,\n"
+" __global const float4* verticesB,\n"
+" __global const b3GpuFace_t* facesB,\n"
+" __global const int* indicesB,\n"
+" float4* localContactsOut,\n"
+" int localContactCapacity)\n"
+"{\n"
+" int numContactsOut = 0;\n"
+" int numWorldVertsB1= 0;\n"
+" int closestFaceB=-1;\n"
+" float dmax = -FLT_MAX;\n"
+" {\n"
+" for(int face=0;face<hullB->m_numFaces;face++)\n"
+" {\n"
+" const float4 Normal = make_float4(facesB[hullB->m_faceOffset+face].m_plane.x, \n"
+" facesB[hullB->m_faceOffset+face].m_plane.y, facesB[hullB->m_faceOffset+face].m_plane.z,0.f);\n"
+" const float4 WorldNormal = qtRotate(ornB, Normal);\n"
+" float d = dot3F4(WorldNormal,separatingNormal);\n"
+" if (d > dmax)\n"
+" {\n"
+" dmax = d;\n"
+" closestFaceB = face;\n"
+" }\n"
+" }\n"
+" }\n"
+" {\n"
+" const b3GpuFace_t polyB = facesB[hullB->m_faceOffset+closestFaceB];\n"
+" const int numVertices = polyB.m_numIndices;\n"
+" for(int e0=0;e0<numVertices;e0++)\n"
+" {\n"
+" const float4 b = verticesB[hullB->m_vertexOffset+indicesB[polyB.m_indexOffset+e0]];\n"
+" worldVertsB1[numWorldVertsB1++] = transform(&b,&posB,&ornB);\n"
+" }\n"
+" }\n"
+" if (closestFaceB>=0)\n"
+" {\n"
+" numContactsOut = clipFaceAgainstHullLocalA(separatingNormal, hullA, \n"
+" posA,ornA,\n"
+" worldVertsB1,numWorldVertsB1,worldVertsB2,capacityWorldVerts, minDist, maxDist,\n"
+" verticesA,facesA,indicesA,\n"
+" verticesB,facesB,indicesB,\n"
+" localContactsOut,localContactCapacity);\n"
+" }\n"
+" return numContactsOut;\n"
+"}\n"
+"#define PARALLEL_SUM(v, n) for(int j=1; j<n; j++) v[0] += v[j];\n"
+"#define PARALLEL_DO(execution, n) for(int ie=0; ie<n; ie++){execution;}\n"
+"#define REDUCE_MAX(v, n) {int i=0; for(int offset=0; offset<n; offset++) v[i] = (v[i].y > v[i+offset].y)? v[i]: v[i+offset]; }\n"
+"#define REDUCE_MIN(v, n) {int i=0; for(int offset=0; offset<n; offset++) v[i] = (v[i].y < v[i+offset].y)? v[i]: v[i+offset]; }\n"
+"int extractManifoldSequentialGlobal(__global const float4* p, int nPoints, float4 nearNormal, int4* contactIdx)\n"
+"{\n"
+" if( nPoints == 0 )\n"
+" return 0;\n"
+" \n"
+" if (nPoints <=4)\n"
+" return nPoints;\n"
+" \n"
+" \n"
+" if (nPoints >64)\n"
+" nPoints = 64;\n"
+" \n"
+" float4 center = make_float4(0.f);\n"
+" {\n"
+" \n"
+" for (int i=0;i<nPoints;i++)\n"
+" center += p[i];\n"
+" center /= (float)nPoints;\n"
+" }\n"
+" \n"
+" \n"
+" \n"
+" // sample 4 directions\n"
+" \n"
+" float4 aVector = p[0] - center;\n"
+" float4 u = cross3( nearNormal, aVector );\n"
+" float4 v = cross3( nearNormal, u );\n"
+" u = normalize3( u );\n"
+" v = normalize3( v );\n"
+" \n"
+" \n"
+" //keep point with deepest penetration\n"
+" float minW= FLT_MAX;\n"
+" \n"
+" int minIndex=-1;\n"
+" \n"
+" float4 maxDots;\n"
+" maxDots.x = FLT_MIN;\n"
+" maxDots.y = FLT_MIN;\n"
+" maxDots.z = FLT_MIN;\n"
+" maxDots.w = FLT_MIN;\n"
+" \n"
+" // idx, distance\n"
+" for(int ie = 0; ie<nPoints; ie++ )\n"
+" {\n"
+" if (p[ie].w<minW)\n"
+" {\n"
+" minW = p[ie].w;\n"
+" minIndex=ie;\n"
+" }\n"
+" float f;\n"
+" float4 r = p[ie]-center;\n"
+" f = dot3F4( u, r );\n"
+" if (f<maxDots.x)\n"
+" {\n"
+" maxDots.x = f;\n"
+" contactIdx[0].x = ie;\n"
+" }\n"
+" \n"
+" f = dot3F4( -u, r );\n"
+" if (f<maxDots.y)\n"
+" {\n"
+" maxDots.y = f;\n"
+" contactIdx[0].y = ie;\n"
+" }\n"
+" \n"
+" \n"
+" f = dot3F4( v, r );\n"
+" if (f<maxDots.z)\n"
+" {\n"
+" maxDots.z = f;\n"
+" contactIdx[0].z = ie;\n"
+" }\n"
+" \n"
+" f = dot3F4( -v, r );\n"
+" if (f<maxDots.w)\n"
+" {\n"
+" maxDots.w = f;\n"
+" contactIdx[0].w = ie;\n"
+" }\n"
+" \n"
+" }\n"
+" \n"
+" if (contactIdx[0].x != minIndex && contactIdx[0].y != minIndex && contactIdx[0].z != minIndex && contactIdx[0].w != minIndex)\n"
+" {\n"
+" //replace the first contact with minimum (todo: replace contact with least penetration)\n"
+" contactIdx[0].x = minIndex;\n"
+" }\n"
+" \n"
+" return 4;\n"
+" \n"
+"}\n"
+"int extractManifoldSequentialGlobalFake(__global const float4* p, int nPoints, float4 nearNormal, int* contactIdx)\n"
+"{\n"
+" contactIdx[0] = 0;\n"
+" contactIdx[1] = 1;\n"
+" contactIdx[2] = 2;\n"
+" contactIdx[3] = 3;\n"
+" \n"
+" if( nPoints == 0 ) return 0;\n"
+" \n"
+" nPoints = min2( nPoints, 4 );\n"
+" return nPoints;\n"
+" \n"
+"}\n"
+"int extractManifoldSequential(const float4* p, int nPoints, float4 nearNormal, int* contactIdx)\n"
+"{\n"
+" if( nPoints == 0 ) return 0;\n"
+" nPoints = min2( nPoints, 64 );\n"
+" float4 center = make_float4(0.f);\n"
+" {\n"
+" float4 v[64];\n"
+" for (int i=0;i<nPoints;i++)\n"
+" v[i] = p[i];\n"
+" //memcpy( v, p, nPoints*sizeof(float4) );\n"
+" PARALLEL_SUM( v, nPoints );\n"
+" center = v[0]/(float)nPoints;\n"
+" }\n"
+" \n"
+" { // sample 4 directions\n"
+" if( nPoints < 4 )\n"
+" {\n"
+" for(int i=0; i<nPoints; i++) \n"
+" contactIdx[i] = i;\n"
+" return nPoints;\n"
+" }\n"
+" float4 aVector = p[0] - center;\n"
+" float4 u = cross3( nearNormal, aVector );\n"
+" float4 v = cross3( nearNormal, u );\n"
+" u = normalize3( u );\n"
+" v = normalize3( v );\n"
+" int idx[4];\n"
+" float2 max00 = make_float2(0,FLT_MAX);\n"
+" {\n"
+" // idx, distance\n"
+" {\n"
+" {\n"
+" int4 a[64];\n"
+" for(int ie = 0; ie<nPoints; ie++ )\n"
+" {\n"
+" \n"
+" \n"
+" float f;\n"
+" float4 r = p[ie]-center;\n"
+" f = dot3F4( u, r );\n"
+" a[ie].x = ((*(u32*)&f) & 0xffffff00) | (0xff & ie);\n"
+" f = dot3F4( -u, r );\n"
+" a[ie].y = ((*(u32*)&f) & 0xffffff00) | (0xff & ie);\n"
+" f = dot3F4( v, r );\n"
+" a[ie].z = ((*(u32*)&f) & 0xffffff00) | (0xff & ie);\n"
+" f = dot3F4( -v, r );\n"
+" a[ie].w = ((*(u32*)&f) & 0xffffff00) | (0xff & ie);\n"
+" }\n"
+" for(int ie=0; ie<nPoints; ie++)\n"
+" {\n"
+" a[0].x = (a[0].x > a[ie].x )? a[0].x: a[ie].x;\n"
+" a[0].y = (a[0].y > a[ie].y )? a[0].y: a[ie].y;\n"
+" a[0].z = (a[0].z > a[ie].z )? a[0].z: a[ie].z;\n"
+" a[0].w = (a[0].w > a[ie].w )? a[0].w: a[ie].w;\n"
+" }\n"
+" idx[0] = (int)a[0].x & 0xff;\n"
+" idx[1] = (int)a[0].y & 0xff;\n"
+" idx[2] = (int)a[0].z & 0xff;\n"
+" idx[3] = (int)a[0].w & 0xff;\n"
+" }\n"
+" }\n"
+" {\n"
+" float2 h[64];\n"
+" PARALLEL_DO( h[ie] = make_float2((float)ie, p[ie].w), nPoints );\n"
+" REDUCE_MIN( h, nPoints );\n"
+" max00 = h[0];\n"
+" }\n"
+" }\n"
+" contactIdx[0] = idx[0];\n"
+" contactIdx[1] = idx[1];\n"
+" contactIdx[2] = idx[2];\n"
+" contactIdx[3] = idx[3];\n"
+" return 4;\n"
+" }\n"
+"}\n"
+"__kernel void extractManifoldAndAddContactKernel(__global const int4* pairs, \n"
+" __global const b3RigidBodyData_t* rigidBodies, \n"
+" __global const float4* closestPointsWorld,\n"
+" __global const float4* separatingNormalsWorld,\n"
+" __global const int* contactCounts,\n"
+" __global const int* contactOffsets,\n"
+" __global struct b3Contact4Data* restrict contactsOut,\n"
+" counter32_t nContactsOut,\n"
+" int contactCapacity,\n"
+" int numPairs,\n"
+" int pairIndex\n"
+" )\n"
+"{\n"
+" int idx = get_global_id(0);\n"
+" \n"
+" if (idx<numPairs)\n"
+" {\n"
+" float4 normal = separatingNormalsWorld[idx];\n"
+" int nPoints = contactCounts[idx];\n"
+" __global const float4* pointsIn = &closestPointsWorld[contactOffsets[idx]];\n"
+" float4 localPoints[64];\n"
+" for (int i=0;i<nPoints;i++)\n"
+" {\n"
+" localPoints[i] = pointsIn[i];\n"
+" }\n"
+" int contactIdx[4];// = {-1,-1,-1,-1};\n"
+" contactIdx[0] = -1;\n"
+" contactIdx[1] = -1;\n"
+" contactIdx[2] = -1;\n"
+" contactIdx[3] = -1;\n"
+" int nContacts = extractManifoldSequential(localPoints, nPoints, normal, contactIdx);\n"
+" int dstIdx;\n"
+" AppendInc( nContactsOut, dstIdx );\n"
+" if (dstIdx<contactCapacity)\n"
+" {\n"
+" __global struct b3Contact4Data* c = contactsOut + dstIdx;\n"
+" c->m_worldNormalOnB = -normal;\n"
+" c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
+" c->m_batchIdx = idx;\n"
+" int bodyA = pairs[pairIndex].x;\n"
+" int bodyB = pairs[pairIndex].y;\n"
+" c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0 ? -bodyA:bodyA;\n"
+" c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0 ? -bodyB:bodyB;\n"
+" c->m_childIndexA = -1;\n"
+" c->m_childIndexB = -1;\n"
+" for (int i=0;i<nContacts;i++)\n"
+" {\n"
+" c->m_worldPosB[i] = localPoints[contactIdx[i]];\n"
+" }\n"
+" GET_NPOINTS(*c) = nContacts;\n"
+" }\n"
+" }\n"
+"}\n"
+"void trInverse(float4 translationIn, Quaternion orientationIn,\n"
+" float4* translationOut, Quaternion* orientationOut)\n"
+"{\n"
+" *orientationOut = qtInvert(orientationIn);\n"
+" *translationOut = qtRotate(*orientationOut, -translationIn);\n"
+"}\n"
+"void trMul(float4 translationA, Quaternion orientationA,\n"
+" float4 translationB, Quaternion orientationB,\n"
+" float4* translationOut, Quaternion* orientationOut)\n"
+"{\n"
+" *orientationOut = qtMul(orientationA,orientationB);\n"
+" *translationOut = transform(&translationB,&translationA,&orientationA);\n"
+"}\n"
+"__kernel void clipHullHullKernel( __global int4* pairs, \n"
+" __global const b3RigidBodyData_t* rigidBodies, \n"
+" __global const b3Collidable_t* collidables,\n"
+" __global const b3ConvexPolyhedronData_t* convexShapes, \n"
+" __global const float4* vertices,\n"
+" __global const float4* uniqueEdges,\n"
+" __global const b3GpuFace_t* faces,\n"
+" __global const int* indices,\n"
+" __global const float4* separatingNormals,\n"
+" __global const int* hasSeparatingAxis,\n"
+" __global struct b3Contact4Data* restrict globalContactsOut,\n"
+" counter32_t nGlobalContactsOut,\n"
+" int numPairs,\n"
+" int contactCapacity)\n"
+"{\n"
+" int i = get_global_id(0);\n"
+" int pairIndex = i;\n"
+" \n"
+" float4 worldVertsB1[64];\n"
+" float4 worldVertsB2[64];\n"
+" int capacityWorldVerts = 64; \n"
+" float4 localContactsOut[64];\n"
+" int localContactCapacity=64;\n"
+" \n"
+" float minDist = -1e30f;\n"
+" float maxDist = 0.02f;\n"
+" if (i<numPairs)\n"
+" {\n"
+" int bodyIndexA = pairs[i].x;\n"
+" int bodyIndexB = pairs[i].y;\n"
+" \n"
+" int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
+" int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
+" if (hasSeparatingAxis[i])\n"
+" {\n"
+" \n"
+" int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
+" int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
+" \n"
+" \n"
+" int numLocalContactsOut = clipHullAgainstHull(separatingNormals[i],\n"
+" &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],\n"
+" rigidBodies[bodyIndexA].m_pos,rigidBodies[bodyIndexA].m_quat,\n"
+" rigidBodies[bodyIndexB].m_pos,rigidBodies[bodyIndexB].m_quat,\n"
+" worldVertsB1,worldVertsB2,capacityWorldVerts,\n"
+" minDist, maxDist,\n"
+" vertices,faces,indices,\n"
+" localContactsOut,localContactCapacity);\n"
+" \n"
+" if (numLocalContactsOut>0)\n"
+" {\n"
+" float4 normal = -separatingNormals[i];\n"
+" int nPoints = numLocalContactsOut;\n"
+" float4* pointsIn = localContactsOut;\n"
+" int contactIdx[4];// = {-1,-1,-1,-1};\n"
+" contactIdx[0] = -1;\n"
+" contactIdx[1] = -1;\n"
+" contactIdx[2] = -1;\n"
+" contactIdx[3] = -1;\n"
+" \n"
+" int nReducedContacts = extractManifoldSequential(pointsIn, nPoints, normal, contactIdx);\n"
+" \n"
+" \n"
+" int mprContactIndex = pairs[pairIndex].z;\n"
+" int dstIdx = mprContactIndex;\n"
+" if (dstIdx<0)\n"
+" {\n"
+" AppendInc( nGlobalContactsOut, dstIdx );\n"
+" }\n"
+" if (dstIdx<contactCapacity)\n"
+" {\n"
+" pairs[pairIndex].z = dstIdx;\n"
+" __global struct b3Contact4Data* c = globalContactsOut+ dstIdx;\n"
+" c->m_worldNormalOnB = -normal;\n"
+" c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
+" c->m_batchIdx = pairIndex;\n"
+" int bodyA = pairs[pairIndex].x;\n"
+" int bodyB = pairs[pairIndex].y;\n"
+" c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0?-bodyA:bodyA;\n"
+" c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0?-bodyB:bodyB;\n"
+" c->m_childIndexA = -1;\n"
+" c->m_childIndexB = -1;\n"
+" for (int i=0;i<nReducedContacts;i++)\n"
+" {\n"
+" //this condition means: overwrite contact point, unless at index i==0 we have a valid 'mpr' contact\n"
+" if (i>0||(mprContactIndex<0))\n"
+" {\n"
+" c->m_worldPosB[i] = pointsIn[contactIdx[i]];\n"
+" }\n"
+" }\n"
+" GET_NPOINTS(*c) = nReducedContacts;\n"
+" }\n"
+" \n"
+" }// if (numContactsOut>0)\n"
+" }// if (hasSeparatingAxis[i])\n"
+" }// if (i<numPairs)\n"
+"}\n"
+"__kernel void clipCompoundsHullHullKernel( __global const int4* gpuCompoundPairs, \n"
+" __global const b3RigidBodyData_t* rigidBodies, \n"
+" __global const b3Collidable_t* collidables,\n"
+" __global const b3ConvexPolyhedronData_t* convexShapes, \n"
+" __global const float4* vertices,\n"
+" __global const float4* uniqueEdges,\n"
+" __global const b3GpuFace_t* faces,\n"
+" __global const int* indices,\n"
+" __global const b3GpuChildShape_t* gpuChildShapes,\n"
+" __global const float4* gpuCompoundSepNormalsOut,\n"
+" __global const int* gpuHasCompoundSepNormalsOut,\n"
+" __global struct b3Contact4Data* restrict globalContactsOut,\n"
+" counter32_t nGlobalContactsOut,\n"
+" int numCompoundPairs, int maxContactCapacity)\n"
+"{\n"
+" int i = get_global_id(0);\n"
+" int pairIndex = i;\n"
+" \n"
+" float4 worldVertsB1[64];\n"
+" float4 worldVertsB2[64];\n"
+" int capacityWorldVerts = 64; \n"
+" float4 localContactsOut[64];\n"
+" int localContactCapacity=64;\n"
+" \n"
+" float minDist = -1e30f;\n"
+" float maxDist = 0.02f;\n"
+" if (i<numCompoundPairs)\n"
+" {\n"
+" if (gpuHasCompoundSepNormalsOut[i])\n"
+" {\n"
+" int bodyIndexA = gpuCompoundPairs[i].x;\n"
+" int bodyIndexB = gpuCompoundPairs[i].y;\n"
+" \n"
+" int childShapeIndexA = gpuCompoundPairs[i].z;\n"
+" int childShapeIndexB = gpuCompoundPairs[i].w;\n"
+" \n"
+" int collidableIndexA = -1;\n"
+" int collidableIndexB = -1;\n"
+" \n"
+" float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
+" float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
+" \n"
+" float4 ornB = rigidBodies[bodyIndexB].m_quat;\n"
+" float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
+" \n"
+" if (childShapeIndexA >= 0)\n"
+" {\n"
+" collidableIndexA = gpuChildShapes[childShapeIndexA].m_shapeIndex;\n"
+" float4 childPosA = gpuChildShapes[childShapeIndexA].m_childPosition;\n"
+" float4 childOrnA = gpuChildShapes[childShapeIndexA].m_childOrientation;\n"
+" float4 newPosA = qtRotate(ornA,childPosA)+posA;\n"
+" float4 newOrnA = qtMul(ornA,childOrnA);\n"
+" posA = newPosA;\n"
+" ornA = newOrnA;\n"
+" } else\n"
+" {\n"
+" collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
+" }\n"
+" \n"
+" if (childShapeIndexB>=0)\n"
+" {\n"
+" collidableIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;\n"
+" float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;\n"
+" float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;\n"
+" float4 newPosB = transform(&childPosB,&posB,&ornB);\n"
+" float4 newOrnB = qtMul(ornB,childOrnB);\n"
+" posB = newPosB;\n"
+" ornB = newOrnB;\n"
+" } else\n"
+" {\n"
+" collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx; \n"
+" }\n"
+" \n"
+" int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
+" int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
+" \n"
+" int numLocalContactsOut = clipHullAgainstHull(gpuCompoundSepNormalsOut[i],\n"
+" &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],\n"
+" posA,ornA,\n"
+" posB,ornB,\n"
+" worldVertsB1,worldVertsB2,capacityWorldVerts,\n"
+" minDist, maxDist,\n"
+" vertices,faces,indices,\n"
+" localContactsOut,localContactCapacity);\n"
+" \n"
+" if (numLocalContactsOut>0)\n"
+" {\n"
+" float4 normal = -gpuCompoundSepNormalsOut[i];\n"
+" int nPoints = numLocalContactsOut;\n"
+" float4* pointsIn = localContactsOut;\n"
+" int contactIdx[4];// = {-1,-1,-1,-1};\n"
+" contactIdx[0] = -1;\n"
+" contactIdx[1] = -1;\n"
+" contactIdx[2] = -1;\n"
+" contactIdx[3] = -1;\n"
+" \n"
+" int nReducedContacts = extractManifoldSequential(pointsIn, nPoints, normal, contactIdx);\n"
+" \n"
+" int dstIdx;\n"
+" AppendInc( nGlobalContactsOut, dstIdx );\n"
+" if ((dstIdx+nReducedContacts) < maxContactCapacity)\n"
+" {\n"
+" __global struct b3Contact4Data* c = globalContactsOut+ dstIdx;\n"
+" c->m_worldNormalOnB = -normal;\n"
+" c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
+" c->m_batchIdx = pairIndex;\n"
+" int bodyA = gpuCompoundPairs[pairIndex].x;\n"
+" int bodyB = gpuCompoundPairs[pairIndex].y;\n"
+" c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0?-bodyA:bodyA;\n"
+" c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0?-bodyB:bodyB;\n"
+" c->m_childIndexA = childShapeIndexA;\n"
+" c->m_childIndexB = childShapeIndexB;\n"
+" for (int i=0;i<nReducedContacts;i++)\n"
+" {\n"
+" c->m_worldPosB[i] = pointsIn[contactIdx[i]];\n"
+" }\n"
+" GET_NPOINTS(*c) = nReducedContacts;\n"
+" }\n"
+" \n"
+" }// if (numContactsOut>0)\n"
+" }// if (gpuHasCompoundSepNormalsOut[i])\n"
+" }// if (i<numCompoundPairs)\n"
+"}\n"
+"__kernel void sphereSphereCollisionKernel( __global const int4* pairs, \n"
+" __global const b3RigidBodyData_t* rigidBodies, \n"
+" __global const b3Collidable_t* collidables,\n"
+" __global const float4* separatingNormals,\n"
+" __global const int* hasSeparatingAxis,\n"
+" __global struct b3Contact4Data* restrict globalContactsOut,\n"
+" counter32_t nGlobalContactsOut,\n"
+" int contactCapacity,\n"
+" int numPairs)\n"
+"{\n"
+" int i = get_global_id(0);\n"
+" int pairIndex = i;\n"
+" \n"
+" if (i<numPairs)\n"
+" {\n"
+" int bodyIndexA = pairs[i].x;\n"
+" int bodyIndexB = pairs[i].y;\n"
+" \n"
+" int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
+" int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
+" if (collidables[collidableIndexA].m_shapeType == SHAPE_SPHERE &&\n"
+" collidables[collidableIndexB].m_shapeType == SHAPE_SPHERE)\n"
+" {\n"
+" //sphere-sphere\n"
+" float radiusA = collidables[collidableIndexA].m_radius;\n"
+" float radiusB = collidables[collidableIndexB].m_radius;\n"
+" float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
+" float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
+" float4 diff = posA-posB;\n"
+" float len = length(diff);\n"
+" \n"
+" ///iff distance positive, don't generate a new contact\n"
+" if ( len <= (radiusA+radiusB))\n"
+" {\n"
+" ///distance (negative means penetration)\n"
+" float dist = len - (radiusA+radiusB);\n"
+" float4 normalOnSurfaceB = make_float4(1.f,0.f,0.f,0.f);\n"
+" if (len > 0.00001)\n"
+" {\n"
+" normalOnSurfaceB = diff / len;\n"
+" }\n"
+" float4 contactPosB = posB + normalOnSurfaceB*radiusB;\n"
+" contactPosB.w = dist;\n"
+" \n"
+" int dstIdx;\n"
+" AppendInc( nGlobalContactsOut, dstIdx );\n"
+" if (dstIdx < contactCapacity)\n"
+" {\n"
+" __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];\n"
+" c->m_worldNormalOnB = -normalOnSurfaceB;\n"
+" c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
+" c->m_batchIdx = pairIndex;\n"
+" int bodyA = pairs[pairIndex].x;\n"
+" int bodyB = pairs[pairIndex].y;\n"
+" c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0?-bodyA:bodyA;\n"
+" c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0?-bodyB:bodyB;\n"
+" c->m_worldPosB[0] = contactPosB;\n"
+" c->m_childIndexA = -1;\n"
+" c->m_childIndexB = -1;\n"
+" GET_NPOINTS(*c) = 1;\n"
+" }//if (dstIdx < numPairs)\n"
+" }//if ( len <= (radiusA+radiusB))\n"
+" }//SHAPE_SPHERE SHAPE_SPHERE\n"
+" }//if (i<numPairs)\n"
+"} \n"
+"__kernel void clipHullHullConcaveConvexKernel( __global int4* concavePairsIn,\n"
+" __global const b3RigidBodyData_t* rigidBodies, \n"
+" __global const b3Collidable_t* collidables,\n"
+" __global const b3ConvexPolyhedronData_t* convexShapes, \n"
+" __global const float4* vertices,\n"
+" __global const float4* uniqueEdges,\n"
+" __global const b3GpuFace_t* faces,\n"
+" __global const int* indices,\n"
+" __global const b3GpuChildShape_t* gpuChildShapes,\n"
+" __global const float4* separatingNormals,\n"
+" __global struct b3Contact4Data* restrict globalContactsOut,\n"
+" counter32_t nGlobalContactsOut,\n"
+" int contactCapacity,\n"
+" int numConcavePairs)\n"
+"{\n"
+" int i = get_global_id(0);\n"
+" int pairIndex = i;\n"
+" \n"
+" float4 worldVertsB1[64];\n"
+" float4 worldVertsB2[64];\n"
+" int capacityWorldVerts = 64; \n"
+" float4 localContactsOut[64];\n"
+" int localContactCapacity=64;\n"
+" \n"
+" float minDist = -1e30f;\n"
+" float maxDist = 0.02f;\n"
+" if (i<numConcavePairs)\n"
+" {\n"
+" //negative value means that the pair is invalid\n"
+" if (concavePairsIn[i].w<0)\n"
+" return;\n"
+" int bodyIndexA = concavePairsIn[i].x;\n"
+" int bodyIndexB = concavePairsIn[i].y;\n"
+" int f = concavePairsIn[i].z;\n"
+" int childShapeIndexA = f;\n"
+" \n"
+" int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
+" int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
+" \n"
+" int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
+" int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
+" \n"
+" ///////////////////////////////////////////////////////////////\n"
+" \n"
+" \n"
+" bool overlap = false;\n"
+" \n"
+" b3ConvexPolyhedronData_t convexPolyhedronA;\n"
+" //add 3 vertices of the triangle\n"
+" convexPolyhedronA.m_numVertices = 3;\n"
+" convexPolyhedronA.m_vertexOffset = 0;\n"
+" float4 localCenter = make_float4(0.f,0.f,0.f,0.f);\n"
+" b3GpuFace_t face = faces[convexShapes[shapeIndexA].m_faceOffset+f];\n"
+" \n"
+" float4 verticesA[3];\n"
+" for (int i=0;i<3;i++)\n"
+" {\n"
+" int index = indices[face.m_indexOffset+i];\n"
+" float4 vert = vertices[convexShapes[shapeIndexA].m_vertexOffset+index];\n"
+" verticesA[i] = vert;\n"
+" localCenter += vert;\n"
+" }\n"
+" float dmin = FLT_MAX;\n"
+" int localCC=0;\n"
+" //a triangle has 3 unique edges\n"
+" convexPolyhedronA.m_numUniqueEdges = 3;\n"
+" convexPolyhedronA.m_uniqueEdgesOffset = 0;\n"
+" float4 uniqueEdgesA[3];\n"
+" \n"
+" uniqueEdgesA[0] = (verticesA[1]-verticesA[0]);\n"
+" uniqueEdgesA[1] = (verticesA[2]-verticesA[1]);\n"
+" uniqueEdgesA[2] = (verticesA[0]-verticesA[2]);\n"
+" convexPolyhedronA.m_faceOffset = 0;\n"
+" \n"
+" float4 normal = make_float4(face.m_plane.x,face.m_plane.y,face.m_plane.z,0.f);\n"
+" \n"
+" b3GpuFace_t facesA[TRIANGLE_NUM_CONVEX_FACES];\n"
+" int indicesA[3+3+2+2+2];\n"
+" int curUsedIndices=0;\n"
+" int fidx=0;\n"
+" //front size of triangle\n"
+" {\n"
+" facesA[fidx].m_indexOffset=curUsedIndices;\n"
+" indicesA[0] = 0;\n"
+" indicesA[1] = 1;\n"
+" indicesA[2] = 2;\n"
+" curUsedIndices+=3;\n"
+" float c = face.m_plane.w;\n"
+" facesA[fidx].m_plane.x = normal.x;\n"
+" facesA[fidx].m_plane.y = normal.y;\n"
+" facesA[fidx].m_plane.z = normal.z;\n"
+" facesA[fidx].m_plane.w = c;\n"
+" facesA[fidx].m_numIndices=3;\n"
+" }\n"
+" fidx++;\n"
+" //back size of triangle\n"
+" {\n"
+" facesA[fidx].m_indexOffset=curUsedIndices;\n"
+" indicesA[3]=2;\n"
+" indicesA[4]=1;\n"
+" indicesA[5]=0;\n"
+" curUsedIndices+=3;\n"
+" float c = dot3F4(normal,verticesA[0]);\n"
+" float c1 = -face.m_plane.w;\n"
+" facesA[fidx].m_plane.x = -normal.x;\n"
+" facesA[fidx].m_plane.y = -normal.y;\n"
+" facesA[fidx].m_plane.z = -normal.z;\n"
+" facesA[fidx].m_plane.w = c;\n"
+" facesA[fidx].m_numIndices=3;\n"
+" }\n"
+" fidx++;\n"
+" bool addEdgePlanes = true;\n"
+" if (addEdgePlanes)\n"
+" {\n"
+" int numVertices=3;\n"
+" int prevVertex = numVertices-1;\n"
+" for (int i=0;i<numVertices;i++)\n"
+" {\n"
+" float4 v0 = verticesA[i];\n"
+" float4 v1 = verticesA[prevVertex];\n"
+" \n"
+" float4 edgeNormal = normalize(cross(normal,v1-v0));\n"
+" float c = -dot3F4(edgeNormal,v0);\n"
+" facesA[fidx].m_numIndices = 2;\n"
+" facesA[fidx].m_indexOffset=curUsedIndices;\n"
+" indicesA[curUsedIndices++]=i;\n"
+" indicesA[curUsedIndices++]=prevVertex;\n"
+" \n"
+" facesA[fidx].m_plane.x = edgeNormal.x;\n"
+" facesA[fidx].m_plane.y = edgeNormal.y;\n"
+" facesA[fidx].m_plane.z = edgeNormal.z;\n"
+" facesA[fidx].m_plane.w = c;\n"
+" fidx++;\n"
+" prevVertex = i;\n"
+" }\n"
+" }\n"
+" convexPolyhedronA.m_numFaces = TRIANGLE_NUM_CONVEX_FACES;\n"
+" convexPolyhedronA.m_localCenter = localCenter*(1.f/3.f);\n"
+" float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
+" posA.w = 0.f;\n"
+" float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
+" posB.w = 0.f;\n"
+" float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
+" float4 ornB =rigidBodies[bodyIndexB].m_quat;\n"
+" float4 sepAxis = separatingNormals[i];\n"
+" \n"
+" int shapeTypeB = collidables[collidableIndexB].m_shapeType;\n"
+" int childShapeIndexB =-1;\n"
+" if (shapeTypeB==SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
+" {\n"
+" ///////////////////\n"
+" ///compound shape support\n"
+" \n"
+" childShapeIndexB = concavePairsIn[pairIndex].w;\n"
+" int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;\n"
+" shapeIndexB = collidables[childColIndexB].m_shapeIndex;\n"
+" float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;\n"
+" float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;\n"
+" float4 newPosB = transform(&childPosB,&posB,&ornB);\n"
+" float4 newOrnB = qtMul(ornB,childOrnB);\n"
+" posB = newPosB;\n"
+" ornB = newOrnB;\n"
+" \n"
+" }\n"
+" \n"
+" ////////////////////////////////////////\n"
+" \n"
+" \n"
+" \n"
+" int numLocalContactsOut = clipHullAgainstHullLocalA(sepAxis,\n"
+" &convexPolyhedronA, &convexShapes[shapeIndexB],\n"
+" posA,ornA,\n"
+" posB,ornB,\n"
+" worldVertsB1,worldVertsB2,capacityWorldVerts,\n"
+" minDist, maxDist,\n"
+" &verticesA,&facesA,&indicesA,\n"
+" vertices,faces,indices,\n"
+" localContactsOut,localContactCapacity);\n"
+" \n"
+" if (numLocalContactsOut>0)\n"
+" {\n"
+" float4 normal = -separatingNormals[i];\n"
+" int nPoints = numLocalContactsOut;\n"
+" float4* pointsIn = localContactsOut;\n"
+" int contactIdx[4];// = {-1,-1,-1,-1};\n"
+" contactIdx[0] = -1;\n"
+" contactIdx[1] = -1;\n"
+" contactIdx[2] = -1;\n"
+" contactIdx[3] = -1;\n"
+" \n"
+" int nReducedContacts = extractManifoldSequential(pointsIn, nPoints, normal, contactIdx);\n"
+" \n"
+" int dstIdx;\n"
+" AppendInc( nGlobalContactsOut, dstIdx );\n"
+" if (dstIdx<contactCapacity)\n"
+" {\n"
+" __global struct b3Contact4Data* c = globalContactsOut+ dstIdx;\n"
+" c->m_worldNormalOnB = -normal;\n"
+" c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
+" c->m_batchIdx = pairIndex;\n"
+" int bodyA = concavePairsIn[pairIndex].x;\n"
+" int bodyB = concavePairsIn[pairIndex].y;\n"
+" c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0?-bodyA:bodyA;\n"
+" c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0?-bodyB:bodyB;\n"
+" c->m_childIndexA = childShapeIndexA;\n"
+" c->m_childIndexB = childShapeIndexB;\n"
+" for (int i=0;i<nReducedContacts;i++)\n"
+" {\n"
+" c->m_worldPosB[i] = pointsIn[contactIdx[i]];\n"
+" }\n"
+" GET_NPOINTS(*c) = nReducedContacts;\n"
+" }\n"
+" \n"
+" }// if (numContactsOut>0)\n"
+" }// if (i<numPairs)\n"
+"}\n"
+"int findClippingFaces(const float4 separatingNormal,\n"
+" __global const b3ConvexPolyhedronData_t* hullA, __global const b3ConvexPolyhedronData_t* hullB,\n"
+" const float4 posA, const Quaternion ornA,const float4 posB, const Quaternion ornB,\n"
+" __global float4* worldVertsA1,\n"
+" __global float4* worldNormalsA1,\n"
+" __global float4* worldVertsB1,\n"
+" int capacityWorldVerts,\n"
+" const float minDist, float maxDist,\n"
+" __global const float4* vertices,\n"
+" __global const b3GpuFace_t* faces,\n"
+" __global const int* indices,\n"
+" __global int4* clippingFaces, int pairIndex)\n"
+"{\n"
+" int numContactsOut = 0;\n"
+" int numWorldVertsB1= 0;\n"
+" \n"
+" \n"
+" int closestFaceB=-1;\n"
+" float dmax = -FLT_MAX;\n"
+" \n"
+" {\n"
+" for(int face=0;face<hullB->m_numFaces;face++)\n"
+" {\n"
+" const float4 Normal = make_float4(faces[hullB->m_faceOffset+face].m_plane.x,\n"
+" faces[hullB->m_faceOffset+face].m_plane.y, faces[hullB->m_faceOffset+face].m_plane.z,0.f);\n"
+" const float4 WorldNormal = qtRotate(ornB, Normal);\n"
+" float d = dot3F4(WorldNormal,separatingNormal);\n"
+" if (d > dmax)\n"
+" {\n"
+" dmax = d;\n"
+" closestFaceB = face;\n"
+" }\n"
+" }\n"
+" }\n"
+" \n"
+" {\n"
+" const b3GpuFace_t polyB = faces[hullB->m_faceOffset+closestFaceB];\n"
+" const int numVertices = polyB.m_numIndices;\n"
+" for(int e0=0;e0<numVertices;e0++)\n"
+" {\n"
+" const float4 b = vertices[hullB->m_vertexOffset+indices[polyB.m_indexOffset+e0]];\n"
+" worldVertsB1[pairIndex*capacityWorldVerts+numWorldVertsB1++] = transform(&b,&posB,&ornB);\n"
+" }\n"
+" }\n"
+" \n"
+" int closestFaceA=-1;\n"
+" {\n"
+" float dmin = FLT_MAX;\n"
+" for(int face=0;face<hullA->m_numFaces;face++)\n"
+" {\n"
+" const float4 Normal = make_float4(\n"
+" faces[hullA->m_faceOffset+face].m_plane.x,\n"
+" faces[hullA->m_faceOffset+face].m_plane.y,\n"
+" faces[hullA->m_faceOffset+face].m_plane.z,\n"
+" 0.f);\n"
+" const float4 faceANormalWS = qtRotate(ornA,Normal);\n"
+" \n"
+" float d = dot3F4(faceANormalWS,separatingNormal);\n"
+" if (d < dmin)\n"
+" {\n"
+" dmin = d;\n"
+" closestFaceA = face;\n"
+" worldNormalsA1[pairIndex] = faceANormalWS;\n"
+" }\n"
+" }\n"
+" }\n"
+" \n"
+" int numVerticesA = faces[hullA->m_faceOffset+closestFaceA].m_numIndices;\n"
+" for(int e0=0;e0<numVerticesA;e0++)\n"
+" {\n"
+" const float4 a = vertices[hullA->m_vertexOffset+indices[faces[hullA->m_faceOffset+closestFaceA].m_indexOffset+e0]];\n"
+" worldVertsA1[pairIndex*capacityWorldVerts+e0] = transform(&a, &posA,&ornA);\n"
+" }\n"
+" \n"
+" clippingFaces[pairIndex].x = closestFaceA;\n"
+" clippingFaces[pairIndex].y = closestFaceB;\n"
+" clippingFaces[pairIndex].z = numVerticesA;\n"
+" clippingFaces[pairIndex].w = numWorldVertsB1;\n"
+" \n"
+" \n"
+" return numContactsOut;\n"
+"}\n"
+"int clipFaces(__global float4* worldVertsA1,\n"
+" __global float4* worldNormalsA1,\n"
+" __global float4* worldVertsB1,\n"
+" __global float4* worldVertsB2, \n"
+" int capacityWorldVertsB2,\n"
+" const float minDist, float maxDist,\n"
+" __global int4* clippingFaces,\n"
+" int pairIndex)\n"
+"{\n"
+" int numContactsOut = 0;\n"
+" \n"
+" int closestFaceA = clippingFaces[pairIndex].x;\n"
+" int closestFaceB = clippingFaces[pairIndex].y;\n"
+" int numVertsInA = clippingFaces[pairIndex].z;\n"
+" int numVertsInB = clippingFaces[pairIndex].w;\n"
+" \n"
+" int numVertsOut = 0;\n"
+" \n"
+" if (closestFaceA<0)\n"
+" return numContactsOut;\n"
+" \n"
+" __global float4* pVtxIn = &worldVertsB1[pairIndex*capacityWorldVertsB2];\n"
+" __global float4* pVtxOut = &worldVertsB2[pairIndex*capacityWorldVertsB2];\n"
+" \n"
+" \n"
+" \n"
+" // clip polygon to back of planes of all faces of hull A that are adjacent to witness face\n"
+" \n"
+" for(int e0=0;e0<numVertsInA;e0++)\n"
+" {\n"
+" const float4 aw = worldVertsA1[pairIndex*capacityWorldVertsB2+e0];\n"
+" const float4 bw = worldVertsA1[pairIndex*capacityWorldVertsB2+((e0+1)%numVertsInA)];\n"
+" const float4 WorldEdge0 = aw - bw;\n"
+" float4 worldPlaneAnormal1 = worldNormalsA1[pairIndex];\n"
+" float4 planeNormalWS1 = -cross3(WorldEdge0,worldPlaneAnormal1);\n"
+" float4 worldA1 = aw;\n"
+" float planeEqWS1 = -dot3F4(worldA1,planeNormalWS1);\n"
+" float4 planeNormalWS = planeNormalWS1;\n"
+" float planeEqWS=planeEqWS1;\n"
+" numVertsOut = clipFaceGlobal(pVtxIn, numVertsInB, planeNormalWS,planeEqWS, pVtxOut);\n"
+" __global float4* tmp = pVtxOut;\n"
+" pVtxOut = pVtxIn;\n"
+" pVtxIn = tmp;\n"
+" numVertsInB = numVertsOut;\n"
+" numVertsOut = 0;\n"
+" }\n"
+" \n"
+" //float4 planeNormalWS = worldNormalsA1[pairIndex];\n"
+" //float planeEqWS=-dot3F4(planeNormalWS,worldVertsA1[pairIndex*capacityWorldVertsB2]);\n"
+" \n"
+" /*for (int i=0;i<numVertsInB;i++)\n"
+" {\n"
+" pVtxOut[i] = pVtxIn[i];\n"
+" }*/\n"
+" \n"
+" \n"
+" \n"
+" \n"
+" //numVertsInB=0;\n"
+" \n"
+" float4 planeNormalWS = worldNormalsA1[pairIndex];\n"
+" float planeEqWS=-dot3F4(planeNormalWS,worldVertsA1[pairIndex*capacityWorldVertsB2]);\n"
+" for (int i=0;i<numVertsInB;i++)\n"
+" {\n"
+" float depth = dot3F4(planeNormalWS,pVtxIn[i])+planeEqWS;\n"
+" if (depth <=minDist)\n"
+" {\n"
+" depth = minDist;\n"
+" }\n"
+" \n"
+" if (depth <=maxDist)\n"
+" {\n"
+" float4 pointInWorld = pVtxIn[i];\n"
+" pVtxOut[numContactsOut++] = make_float4(pointInWorld.x,pointInWorld.y,pointInWorld.z,depth);\n"
+" }\n"
+" }\n"
+" \n"
+" clippingFaces[pairIndex].w =numContactsOut;\n"
+" \n"
+" \n"
+" return numContactsOut;\n"
+"}\n"
+"__kernel void findClippingFacesKernel( __global const int4* pairs,\n"
+" __global const b3RigidBodyData_t* rigidBodies,\n"
+" __global const b3Collidable_t* collidables,\n"
+" __global const b3ConvexPolyhedronData_t* convexShapes,\n"
+" __global const float4* vertices,\n"
+" __global const float4* uniqueEdges,\n"
+" __global const b3GpuFace_t* faces,\n"
+" __global const int* indices,\n"
+" __global const float4* separatingNormals,\n"
+" __global const int* hasSeparatingAxis,\n"
+" __global int4* clippingFacesOut,\n"
+" __global float4* worldVertsA1,\n"
+" __global float4* worldNormalsA1,\n"
+" __global float4* worldVertsB1,\n"
+" int capacityWorldVerts,\n"
+" int numPairs\n"
+" )\n"
+"{\n"
+" \n"
+" int i = get_global_id(0);\n"
+" int pairIndex = i;\n"
+" \n"
+" \n"
+" float minDist = -1e30f;\n"
+" float maxDist = 0.02f;\n"
+" \n"
+" if (i<numPairs)\n"
+" {\n"
+" \n"
+" if (hasSeparatingAxis[i])\n"
+" {\n"
+" \n"
+" int bodyIndexA = pairs[i].x;\n"
+" int bodyIndexB = pairs[i].y;\n"
+" \n"
+" int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
+" int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
+" \n"
+" int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
+" int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
+" \n"
+" \n"
+" \n"
+" int numLocalContactsOut = findClippingFaces(separatingNormals[i],\n"
+" &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],\n"
+" rigidBodies[bodyIndexA].m_pos,rigidBodies[bodyIndexA].m_quat,\n"
+" rigidBodies[bodyIndexB].m_pos,rigidBodies[bodyIndexB].m_quat,\n"
+" worldVertsA1,\n"
+" worldNormalsA1,\n"
+" worldVertsB1,capacityWorldVerts,\n"
+" minDist, maxDist,\n"
+" vertices,faces,indices,\n"
+" clippingFacesOut,i);\n"
+" \n"
+" \n"
+" }// if (hasSeparatingAxis[i])\n"
+" }// if (i<numPairs)\n"
+" \n"
+"}\n"
+"__kernel void clipFacesAndFindContactsKernel( __global const float4* separatingNormals,\n"
+" __global const int* hasSeparatingAxis,\n"
+" __global int4* clippingFacesOut,\n"
+" __global float4* worldVertsA1,\n"
+" __global float4* worldNormalsA1,\n"
+" __global float4* worldVertsB1,\n"
+" __global float4* worldVertsB2,\n"
+" int vertexFaceCapacity,\n"
+" int numPairs,\n"
+" int debugMode\n"
+" )\n"
+"{\n"
+" int i = get_global_id(0);\n"
+" int pairIndex = i;\n"
+" \n"
+" \n"
+" float minDist = -1e30f;\n"
+" float maxDist = 0.02f;\n"
+" \n"
+" if (i<numPairs)\n"
+" {\n"
+" \n"
+" if (hasSeparatingAxis[i])\n"
+" {\n"
+" \n"
+"// int bodyIndexA = pairs[i].x;\n"
+" // int bodyIndexB = pairs[i].y;\n"
+" \n"
+" int numLocalContactsOut = 0;\n"
+" int capacityWorldVertsB2 = vertexFaceCapacity;\n"
+" \n"
+" __global float4* pVtxIn = &worldVertsB1[pairIndex*capacityWorldVertsB2];\n"
+" __global float4* pVtxOut = &worldVertsB2[pairIndex*capacityWorldVertsB2];\n"
+" \n"
+" {\n"
+" __global int4* clippingFaces = clippingFacesOut;\n"
+" \n"
+" \n"
+" int closestFaceA = clippingFaces[pairIndex].x;\n"
+" int closestFaceB = clippingFaces[pairIndex].y;\n"
+" int numVertsInA = clippingFaces[pairIndex].z;\n"
+" int numVertsInB = clippingFaces[pairIndex].w;\n"
+" \n"
+" int numVertsOut = 0;\n"
+" \n"
+" if (closestFaceA>=0)\n"
+" {\n"
+" \n"
+" \n"
+" \n"
+" // clip polygon to back of planes of all faces of hull A that are adjacent to witness face\n"
+" \n"
+" for(int e0=0;e0<numVertsInA;e0++)\n"
+" {\n"
+" const float4 aw = worldVertsA1[pairIndex*capacityWorldVertsB2+e0];\n"
+" const float4 bw = worldVertsA1[pairIndex*capacityWorldVertsB2+((e0+1)%numVertsInA)];\n"
+" const float4 WorldEdge0 = aw - bw;\n"
+" float4 worldPlaneAnormal1 = worldNormalsA1[pairIndex];\n"
+" float4 planeNormalWS1 = -cross3(WorldEdge0,worldPlaneAnormal1);\n"
+" float4 worldA1 = aw;\n"
+" float planeEqWS1 = -dot3F4(worldA1,planeNormalWS1);\n"
+" float4 planeNormalWS = planeNormalWS1;\n"
+" float planeEqWS=planeEqWS1;\n"
+" numVertsOut = clipFaceGlobal(pVtxIn, numVertsInB, planeNormalWS,planeEqWS, pVtxOut);\n"
+" __global float4* tmp = pVtxOut;\n"
+" pVtxOut = pVtxIn;\n"
+" pVtxIn = tmp;\n"
+" numVertsInB = numVertsOut;\n"
+" numVertsOut = 0;\n"
+" }\n"
+" \n"
+" float4 planeNormalWS = worldNormalsA1[pairIndex];\n"
+" float planeEqWS=-dot3F4(planeNormalWS,worldVertsA1[pairIndex*capacityWorldVertsB2]);\n"
+" \n"
+" for (int i=0;i<numVertsInB;i++)\n"
+" {\n"
+" float depth = dot3F4(planeNormalWS,pVtxIn[i])+planeEqWS;\n"
+" if (depth <=minDist)\n"
+" {\n"
+" depth = minDist;\n"
+" }\n"
+" \n"
+" if (depth <=maxDist)\n"
+" {\n"
+" float4 pointInWorld = pVtxIn[i];\n"
+" pVtxOut[numLocalContactsOut++] = make_float4(pointInWorld.x,pointInWorld.y,pointInWorld.z,depth);\n"
+" }\n"
+" }\n"
+" \n"
+" }\n"
+" clippingFaces[pairIndex].w =numLocalContactsOut;\n"
+" \n"
+" }\n"
+" \n"
+" for (int i=0;i<numLocalContactsOut;i++)\n"
+" pVtxIn[i] = pVtxOut[i];\n"
+" \n"
+" }// if (hasSeparatingAxis[i])\n"
+" }// if (i<numPairs)\n"
+" \n"
+"}\n"
+"__kernel void newContactReductionKernel( __global int4* pairs,\n"
+" __global const b3RigidBodyData_t* rigidBodies,\n"
+" __global const float4* separatingNormals,\n"
+" __global const int* hasSeparatingAxis,\n"
+" __global struct b3Contact4Data* globalContactsOut,\n"
+" __global int4* clippingFaces,\n"
+" __global float4* worldVertsB2,\n"
+" volatile __global int* nGlobalContactsOut,\n"
+" int vertexFaceCapacity,\n"
+" int contactCapacity,\n"
+" int numPairs\n"
+" )\n"
+"{\n"
+" int i = get_global_id(0);\n"
+" int pairIndex = i;\n"
+" \n"
+" int4 contactIdx;\n"
+" contactIdx=make_int4(0,1,2,3);\n"
+" \n"
+" if (i<numPairs)\n"
+" {\n"
+" \n"
+" if (hasSeparatingAxis[i])\n"
+" {\n"
+" \n"
+" \n"
+" \n"
+" \n"
+" int nPoints = clippingFaces[pairIndex].w;\n"
+" \n"
+" if (nPoints>0)\n"
+" {\n"
+" __global float4* pointsIn = &worldVertsB2[pairIndex*vertexFaceCapacity];\n"
+" float4 normal = -separatingNormals[i];\n"
+" \n"
+" int nReducedContacts = extractManifoldSequentialGlobal(pointsIn, nPoints, normal, &contactIdx);\n"
+" \n"
+" int mprContactIndex = pairs[pairIndex].z;\n"
+" int dstIdx = mprContactIndex;\n"
+" if (dstIdx<0)\n"
+" {\n"
+" AppendInc( nGlobalContactsOut, dstIdx );\n"
+" }\n"
+"//#if 0\n"
+" \n"
+" if (dstIdx < contactCapacity)\n"
+" {\n"
+" __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];\n"
+" c->m_worldNormalOnB = -normal;\n"
+" c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
+" c->m_batchIdx = pairIndex;\n"
+" int bodyA = pairs[pairIndex].x;\n"
+" int bodyB = pairs[pairIndex].y;\n"
+" pairs[pairIndex].w = dstIdx;\n"
+" c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0?-bodyA:bodyA;\n"
+" c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0?-bodyB:bodyB;\n"
+" c->m_childIndexA =-1;\n"
+" c->m_childIndexB =-1;\n"
+" switch (nReducedContacts)\n"
+" {\n"
+" case 4:\n"
+" c->m_worldPosB[3] = pointsIn[contactIdx.w];\n"
+" case 3:\n"
+" c->m_worldPosB[2] = pointsIn[contactIdx.z];\n"
+" case 2:\n"
+" c->m_worldPosB[1] = pointsIn[contactIdx.y];\n"
+" case 1:\n"
+" if (mprContactIndex<0)//test\n"
+" c->m_worldPosB[0] = pointsIn[contactIdx.x];\n"
+" default:\n"
+" {\n"
+" }\n"
+" };\n"
+" \n"
+" GET_NPOINTS(*c) = nReducedContacts;\n"
+" \n"
+" }\n"
+" \n"
+" \n"
+"//#endif\n"
+" \n"
+" }// if (numContactsOut>0)\n"
+" }// if (hasSeparatingAxis[i])\n"
+" }// if (i<numPairs)\n"
+" \n"
+" \n"
+"}\n"
+;
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/kernels/satConcave.cl b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/kernels/satConcave.cl
new file mode 100644
index 0000000000..31ca43b8cd
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/kernels/satConcave.cl
@@ -0,0 +1,1220 @@
+
+//keep this enum in sync with the CPU version (in btCollidable.h)
+//written by Erwin Coumans
+
+
+#define SHAPE_CONVEX_HULL 3
+#define SHAPE_CONCAVE_TRIMESH 5
+#define TRIANGLE_NUM_CONVEX_FACES 5
+#define SHAPE_COMPOUND_OF_CONVEX_HULLS 6
+
+#define B3_MAX_STACK_DEPTH 256
+
+
+typedef unsigned int u32;
+
+///keep this in sync with btCollidable.h
+typedef struct
+{
+ union {
+ int m_numChildShapes;
+ int m_bvhIndex;
+ };
+ union
+ {
+ float m_radius;
+ int m_compoundBvhIndex;
+ };
+
+ int m_shapeType;
+ int m_shapeIndex;
+
+} btCollidableGpu;
+
+#define MAX_NUM_PARTS_IN_BITS 10
+
+///b3QuantizedBvhNode is a compressed aabb node, 16 bytes.
+///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range).
+typedef struct
+{
+ //12 bytes
+ unsigned short int m_quantizedAabbMin[3];
+ unsigned short int m_quantizedAabbMax[3];
+ //4 bytes
+ int m_escapeIndexOrTriangleIndex;
+} b3QuantizedBvhNode;
+
+typedef struct
+{
+ float4 m_aabbMin;
+ float4 m_aabbMax;
+ float4 m_quantization;
+ int m_numNodes;
+ int m_numSubTrees;
+ int m_nodeOffset;
+ int m_subTreeOffset;
+
+} b3BvhInfo;
+
+
+int getTriangleIndex(const b3QuantizedBvhNode* rootNode)
+{
+ unsigned int x=0;
+ unsigned int y = (~(x&0))<<(31-MAX_NUM_PARTS_IN_BITS);
+ // Get only the lower bits where the triangle index is stored
+ return (rootNode->m_escapeIndexOrTriangleIndex&~(y));
+}
+
+int getTriangleIndexGlobal(__global const b3QuantizedBvhNode* rootNode)
+{
+ unsigned int x=0;
+ unsigned int y = (~(x&0))<<(31-MAX_NUM_PARTS_IN_BITS);
+ // Get only the lower bits where the triangle index is stored
+ return (rootNode->m_escapeIndexOrTriangleIndex&~(y));
+}
+
+int isLeafNode(const b3QuantizedBvhNode* rootNode)
+{
+ //skipindex is negative (internal node), triangleindex >=0 (leafnode)
+ return (rootNode->m_escapeIndexOrTriangleIndex >= 0)? 1 : 0;
+}
+
+int isLeafNodeGlobal(__global const b3QuantizedBvhNode* rootNode)
+{
+ //skipindex is negative (internal node), triangleindex >=0 (leafnode)
+ return (rootNode->m_escapeIndexOrTriangleIndex >= 0)? 1 : 0;
+}
+
+int getEscapeIndex(const b3QuantizedBvhNode* rootNode)
+{
+ return -rootNode->m_escapeIndexOrTriangleIndex;
+}
+
+int getEscapeIndexGlobal(__global const b3QuantizedBvhNode* rootNode)
+{
+ return -rootNode->m_escapeIndexOrTriangleIndex;
+}
+
+
+typedef struct
+{
+ //12 bytes
+ unsigned short int m_quantizedAabbMin[3];
+ unsigned short int m_quantizedAabbMax[3];
+ //4 bytes, points to the root of the subtree
+ int m_rootNodeIndex;
+ //4 bytes
+ int m_subtreeSize;
+ int m_padding[3];
+} b3BvhSubtreeInfo;
+
+
+
+
+
+
+
+typedef struct
+{
+ float4 m_childPosition;
+ float4 m_childOrientation;
+ int m_shapeIndex;
+ int m_unused0;
+ int m_unused1;
+ int m_unused2;
+} btGpuChildShape;
+
+
+typedef struct
+{
+ float4 m_pos;
+ float4 m_quat;
+ float4 m_linVel;
+ float4 m_angVel;
+
+ u32 m_collidableIdx;
+ float m_invMass;
+ float m_restituitionCoeff;
+ float m_frictionCoeff;
+} BodyData;
+
+
+typedef struct
+{
+ float4 m_localCenter;
+ float4 m_extents;
+ float4 mC;
+ float4 mE;
+
+ float m_radius;
+ int m_faceOffset;
+ int m_numFaces;
+ int m_numVertices;
+
+ int m_vertexOffset;
+ int m_uniqueEdgesOffset;
+ int m_numUniqueEdges;
+ int m_unused;
+} ConvexPolyhedronCL;
+
+typedef struct
+{
+ union
+ {
+ float4 m_min;
+ float m_minElems[4];
+ int m_minIndices[4];
+ };
+ union
+ {
+ float4 m_max;
+ float m_maxElems[4];
+ int m_maxIndices[4];
+ };
+} btAabbCL;
+
+#include "Bullet3Collision/BroadPhaseCollision/shared/b3Aabb.h"
+#include "Bullet3Common/shared/b3Int2.h"
+
+
+
+typedef struct
+{
+ float4 m_plane;
+ int m_indexOffset;
+ int m_numIndices;
+} btGpuFace;
+
+#define make_float4 (float4)
+
+
+__inline
+float4 cross3(float4 a, float4 b)
+{
+ return cross(a,b);
+
+
+// float4 a1 = make_float4(a.xyz,0.f);
+// float4 b1 = make_float4(b.xyz,0.f);
+
+// return cross(a1,b1);
+
+//float4 c = make_float4(a.y*b.z - a.z*b.y,a.z*b.x - a.x*b.z,a.x*b.y - a.y*b.x,0.f);
+
+ // float4 c = make_float4(a.y*b.z - a.z*b.y,1.f,a.x*b.y - a.y*b.x,0.f);
+
+ //return c;
+}
+
+__inline
+float dot3F4(float4 a, float4 b)
+{
+ float4 a1 = make_float4(a.xyz,0.f);
+ float4 b1 = make_float4(b.xyz,0.f);
+ return dot(a1, b1);
+}
+
+__inline
+float4 fastNormalize4(float4 v)
+{
+ v = make_float4(v.xyz,0.f);
+ return fast_normalize(v);
+}
+
+
+///////////////////////////////////////
+// Quaternion
+///////////////////////////////////////
+
+typedef float4 Quaternion;
+
+__inline
+Quaternion qtMul(Quaternion a, Quaternion b);
+
+__inline
+Quaternion qtNormalize(Quaternion in);
+
+__inline
+float4 qtRotate(Quaternion q, float4 vec);
+
+__inline
+Quaternion qtInvert(Quaternion q);
+
+
+
+
+__inline
+Quaternion qtMul(Quaternion a, Quaternion b)
+{
+ Quaternion ans;
+ ans = cross3( a, b );
+ ans += a.w*b+b.w*a;
+// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);
+ ans.w = a.w*b.w - dot3F4(a, b);
+ return ans;
+}
+
+__inline
+Quaternion qtNormalize(Quaternion in)
+{
+ return fastNormalize4(in);
+// in /= length( in );
+// return in;
+}
+__inline
+float4 qtRotate(Quaternion q, float4 vec)
+{
+ Quaternion qInv = qtInvert( q );
+ float4 vcpy = vec;
+ vcpy.w = 0.f;
+ float4 out = qtMul(qtMul(q,vcpy),qInv);
+ return out;
+}
+
+__inline
+Quaternion qtInvert(Quaternion q)
+{
+ return (Quaternion)(-q.xyz, q.w);
+}
+
+__inline
+float4 qtInvRotate(const Quaternion q, float4 vec)
+{
+ return qtRotate( qtInvert( q ), vec );
+}
+
+__inline
+float4 transform(const float4* p, const float4* translation, const Quaternion* orientation)
+{
+ return qtRotate( *orientation, *p ) + (*translation);
+}
+
+
+
+__inline
+float4 normalize3(const float4 a)
+{
+ float4 n = make_float4(a.x, a.y, a.z, 0.f);
+ return fastNormalize4( n );
+}
+
+inline void projectLocal(const ConvexPolyhedronCL* hull, const float4 pos, const float4 orn,
+const float4* dir, const float4* vertices, float* min, float* max)
+{
+ min[0] = FLT_MAX;
+ max[0] = -FLT_MAX;
+ int numVerts = hull->m_numVertices;
+
+ const float4 localDir = qtInvRotate(orn,*dir);
+ float offset = dot(pos,*dir);
+ for(int i=0;i<numVerts;i++)
+ {
+ float dp = dot(vertices[hull->m_vertexOffset+i],localDir);
+ if(dp < min[0])
+ min[0] = dp;
+ if(dp > max[0])
+ max[0] = dp;
+ }
+ if(min[0]>max[0])
+ {
+ float tmp = min[0];
+ min[0] = max[0];
+ max[0] = tmp;
+ }
+ min[0] += offset;
+ max[0] += offset;
+}
+
+inline void project(__global const ConvexPolyhedronCL* hull, const float4 pos, const float4 orn,
+const float4* dir, __global const float4* vertices, float* min, float* max)
+{
+ min[0] = FLT_MAX;
+ max[0] = -FLT_MAX;
+ int numVerts = hull->m_numVertices;
+
+ const float4 localDir = qtInvRotate(orn,*dir);
+ float offset = dot(pos,*dir);
+ for(int i=0;i<numVerts;i++)
+ {
+ float dp = dot(vertices[hull->m_vertexOffset+i],localDir);
+ if(dp < min[0])
+ min[0] = dp;
+ if(dp > max[0])
+ max[0] = dp;
+ }
+ if(min[0]>max[0])
+ {
+ float tmp = min[0];
+ min[0] = max[0];
+ max[0] = tmp;
+ }
+ min[0] += offset;
+ max[0] += offset;
+}
+
+inline bool TestSepAxisLocalA(const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB,
+ const float4 posA,const float4 ornA,
+ const float4 posB,const float4 ornB,
+ float4* sep_axis, const float4* verticesA, __global const float4* verticesB,float* depth)
+{
+ float Min0,Max0;
+ float Min1,Max1;
+ projectLocal(hullA,posA,ornA,sep_axis,verticesA, &Min0, &Max0);
+ project(hullB,posB,ornB, sep_axis,verticesB, &Min1, &Max1);
+
+ if(Max0<Min1 || Max1<Min0)
+ return false;
+
+ float d0 = Max0 - Min1;
+ float d1 = Max1 - Min0;
+ *depth = d0<d1 ? d0:d1;
+ return true;
+}
+
+
+
+
+inline bool IsAlmostZero(const float4 v)
+{
+ if(fabs(v.x)>1e-6f || fabs(v.y)>1e-6f || fabs(v.z)>1e-6f)
+ return false;
+ return true;
+}
+
+
+
+bool findSeparatingAxisLocalA( const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB,
+ const float4 posA1,
+ const float4 ornA,
+ const float4 posB1,
+ const float4 ornB,
+ const float4 DeltaC2,
+
+ const float4* verticesA,
+ const float4* uniqueEdgesA,
+ const btGpuFace* facesA,
+ const int* indicesA,
+
+ __global const float4* verticesB,
+ __global const float4* uniqueEdgesB,
+ __global const btGpuFace* facesB,
+ __global const int* indicesB,
+ float4* sep,
+ float* dmin)
+{
+
+
+ float4 posA = posA1;
+ posA.w = 0.f;
+ float4 posB = posB1;
+ posB.w = 0.f;
+ int curPlaneTests=0;
+ {
+ int numFacesA = hullA->m_numFaces;
+ // Test normals from hullA
+ for(int i=0;i<numFacesA;i++)
+ {
+ const float4 normal = facesA[hullA->m_faceOffset+i].m_plane;
+ float4 faceANormalWS = qtRotate(ornA,normal);
+ if (dot3F4(DeltaC2,faceANormalWS)<0)
+ faceANormalWS*=-1.f;
+ curPlaneTests++;
+ float d;
+ if(!TestSepAxisLocalA( hullA, hullB, posA,ornA,posB,ornB,&faceANormalWS, verticesA, verticesB,&d))
+ return false;
+ if(d<*dmin)
+ {
+ *dmin = d;
+ *sep = faceANormalWS;
+ }
+ }
+ }
+ if((dot3F4(-DeltaC2,*sep))>0.0f)
+ {
+ *sep = -(*sep);
+ }
+ return true;
+}
+
+bool findSeparatingAxisLocalB( __global const ConvexPolyhedronCL* hullA, const ConvexPolyhedronCL* hullB,
+ const float4 posA1,
+ const float4 ornA,
+ const float4 posB1,
+ const float4 ornB,
+ const float4 DeltaC2,
+ __global const float4* verticesA,
+ __global const float4* uniqueEdgesA,
+ __global const btGpuFace* facesA,
+ __global const int* indicesA,
+ const float4* verticesB,
+ const float4* uniqueEdgesB,
+ const btGpuFace* facesB,
+ const int* indicesB,
+ float4* sep,
+ float* dmin)
+{
+
+
+ float4 posA = posA1;
+ posA.w = 0.f;
+ float4 posB = posB1;
+ posB.w = 0.f;
+ int curPlaneTests=0;
+ {
+ int numFacesA = hullA->m_numFaces;
+ // Test normals from hullA
+ for(int i=0;i<numFacesA;i++)
+ {
+ const float4 normal = facesA[hullA->m_faceOffset+i].m_plane;
+ float4 faceANormalWS = qtRotate(ornA,normal);
+ if (dot3F4(DeltaC2,faceANormalWS)<0)
+ faceANormalWS *= -1.f;
+ curPlaneTests++;
+ float d;
+ if(!TestSepAxisLocalA( hullB, hullA, posB,ornB,posA,ornA, &faceANormalWS, verticesB,verticesA, &d))
+ return false;
+ if(d<*dmin)
+ {
+ *dmin = d;
+ *sep = faceANormalWS;
+ }
+ }
+ }
+ if((dot3F4(-DeltaC2,*sep))>0.0f)
+ {
+ *sep = -(*sep);
+ }
+ return true;
+}
+
+
+
+bool findSeparatingAxisEdgeEdgeLocalA( const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB,
+ const float4 posA1,
+ const float4 ornA,
+ const float4 posB1,
+ const float4 ornB,
+ const float4 DeltaC2,
+ const float4* verticesA,
+ const float4* uniqueEdgesA,
+ const btGpuFace* facesA,
+ const int* indicesA,
+ __global const float4* verticesB,
+ __global const float4* uniqueEdgesB,
+ __global const btGpuFace* facesB,
+ __global const int* indicesB,
+ float4* sep,
+ float* dmin)
+{
+
+
+ float4 posA = posA1;
+ posA.w = 0.f;
+ float4 posB = posB1;
+ posB.w = 0.f;
+
+ int curPlaneTests=0;
+
+ int curEdgeEdge = 0;
+ // Test edges
+ for(int e0=0;e0<hullA->m_numUniqueEdges;e0++)
+ {
+ const float4 edge0 = uniqueEdgesA[hullA->m_uniqueEdgesOffset+e0];
+ float4 edge0World = qtRotate(ornA,edge0);
+
+ for(int e1=0;e1<hullB->m_numUniqueEdges;e1++)
+ {
+ const float4 edge1 = uniqueEdgesB[hullB->m_uniqueEdgesOffset+e1];
+ float4 edge1World = qtRotate(ornB,edge1);
+
+
+ float4 crossje = cross3(edge0World,edge1World);
+
+ curEdgeEdge++;
+ if(!IsAlmostZero(crossje))
+ {
+ crossje = normalize3(crossje);
+ if (dot3F4(DeltaC2,crossje)<0)
+ crossje *= -1.f;
+
+ float dist;
+ bool result = true;
+ {
+ float Min0,Max0;
+ float Min1,Max1;
+ projectLocal(hullA,posA,ornA,&crossje,verticesA, &Min0, &Max0);
+ project(hullB,posB,ornB,&crossje,verticesB, &Min1, &Max1);
+
+ if(Max0<Min1 || Max1<Min0)
+ result = false;
+
+ float d0 = Max0 - Min1;
+ float d1 = Max1 - Min0;
+ dist = d0<d1 ? d0:d1;
+ result = true;
+
+ }
+
+
+ if(dist<*dmin)
+ {
+ *dmin = dist;
+ *sep = crossje;
+ }
+ }
+ }
+
+ }
+
+
+ if((dot3F4(-DeltaC2,*sep))>0.0f)
+ {
+ *sep = -(*sep);
+ }
+ return true;
+}
+
+
+
+inline int findClippingFaces(const float4 separatingNormal,
+ const ConvexPolyhedronCL* hullA,
+ __global const ConvexPolyhedronCL* hullB,
+ const float4 posA, const Quaternion ornA,const float4 posB, const Quaternion ornB,
+ __global float4* worldVertsA1,
+ __global float4* worldNormalsA1,
+ __global float4* worldVertsB1,
+ int capacityWorldVerts,
+ const float minDist, float maxDist,
+ const float4* verticesA,
+ const btGpuFace* facesA,
+ const int* indicesA,
+ __global const float4* verticesB,
+ __global const btGpuFace* facesB,
+ __global const int* indicesB,
+ __global int4* clippingFaces, int pairIndex)
+{
+ int numContactsOut = 0;
+ int numWorldVertsB1= 0;
+
+
+ int closestFaceB=0;
+ float dmax = -FLT_MAX;
+
+ {
+ for(int face=0;face<hullB->m_numFaces;face++)
+ {
+ const float4 Normal = make_float4(facesB[hullB->m_faceOffset+face].m_plane.x,
+ facesB[hullB->m_faceOffset+face].m_plane.y, facesB[hullB->m_faceOffset+face].m_plane.z,0.f);
+ const float4 WorldNormal = qtRotate(ornB, Normal);
+ float d = dot3F4(WorldNormal,separatingNormal);
+ if (d > dmax)
+ {
+ dmax = d;
+ closestFaceB = face;
+ }
+ }
+ }
+
+ {
+ const btGpuFace polyB = facesB[hullB->m_faceOffset+closestFaceB];
+ int numVertices = polyB.m_numIndices;
+ if (numVertices>capacityWorldVerts)
+ numVertices = capacityWorldVerts;
+ if (numVertices<0)
+ numVertices = 0;
+
+ for(int e0=0;e0<numVertices;e0++)
+ {
+ if (e0<capacityWorldVerts)
+ {
+ const float4 b = verticesB[hullB->m_vertexOffset+indicesB[polyB.m_indexOffset+e0]];
+ worldVertsB1[pairIndex*capacityWorldVerts+numWorldVertsB1++] = transform(&b,&posB,&ornB);
+ }
+ }
+ }
+
+ int closestFaceA=0;
+ {
+ float dmin = FLT_MAX;
+ for(int face=0;face<hullA->m_numFaces;face++)
+ {
+ const float4 Normal = make_float4(
+ facesA[hullA->m_faceOffset+face].m_plane.x,
+ facesA[hullA->m_faceOffset+face].m_plane.y,
+ facesA[hullA->m_faceOffset+face].m_plane.z,
+ 0.f);
+ const float4 faceANormalWS = qtRotate(ornA,Normal);
+
+ float d = dot3F4(faceANormalWS,separatingNormal);
+ if (d < dmin)
+ {
+ dmin = d;
+ closestFaceA = face;
+ worldNormalsA1[pairIndex] = faceANormalWS;
+ }
+ }
+ }
+
+ int numVerticesA = facesA[hullA->m_faceOffset+closestFaceA].m_numIndices;
+ if (numVerticesA>capacityWorldVerts)
+ numVerticesA = capacityWorldVerts;
+ if (numVerticesA<0)
+ numVerticesA=0;
+
+ for(int e0=0;e0<numVerticesA;e0++)
+ {
+ if (e0<capacityWorldVerts)
+ {
+ const float4 a = verticesA[hullA->m_vertexOffset+indicesA[facesA[hullA->m_faceOffset+closestFaceA].m_indexOffset+e0]];
+ worldVertsA1[pairIndex*capacityWorldVerts+e0] = transform(&a, &posA,&ornA);
+ }
+ }
+
+ clippingFaces[pairIndex].x = closestFaceA;
+ clippingFaces[pairIndex].y = closestFaceB;
+ clippingFaces[pairIndex].z = numVerticesA;
+ clippingFaces[pairIndex].w = numWorldVertsB1;
+
+
+ return numContactsOut;
+}
+
+
+
+
+// work-in-progress
+__kernel void findConcaveSeparatingAxisVertexFaceKernel( __global int4* concavePairs,
+ __global const BodyData* rigidBodies,
+ __global const btCollidableGpu* collidables,
+ __global const ConvexPolyhedronCL* convexShapes,
+ __global const float4* vertices,
+ __global const float4* uniqueEdges,
+ __global const btGpuFace* faces,
+ __global const int* indices,
+ __global const btGpuChildShape* gpuChildShapes,
+ __global btAabbCL* aabbs,
+ __global float4* concaveSeparatingNormalsOut,
+ __global int* concaveHasSeparatingNormals,
+ __global int4* clippingFacesOut,
+ __global float4* worldVertsA1GPU,
+ __global float4* worldNormalsAGPU,
+ __global float4* worldVertsB1GPU,
+ __global float* dmins,
+ int vertexFaceCapacity,
+ int numConcavePairs
+ )
+{
+
+ int i = get_global_id(0);
+ if (i>=numConcavePairs)
+ return;
+
+ concaveHasSeparatingNormals[i] = 0;
+
+ int pairIdx = i;
+
+ int bodyIndexA = concavePairs[i].x;
+ int bodyIndexB = concavePairs[i].y;
+
+ int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
+ int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
+
+ int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
+ int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
+
+ if (collidables[collidableIndexB].m_shapeType!=SHAPE_CONVEX_HULL&&
+ collidables[collidableIndexB].m_shapeType!=SHAPE_COMPOUND_OF_CONVEX_HULLS)
+ {
+ concavePairs[pairIdx].w = -1;
+ return;
+ }
+
+
+
+ int numFacesA = convexShapes[shapeIndexA].m_numFaces;
+ int numActualConcaveConvexTests = 0;
+
+ int f = concavePairs[i].z;
+
+ bool overlap = false;
+
+ ConvexPolyhedronCL convexPolyhedronA;
+
+ //add 3 vertices of the triangle
+ convexPolyhedronA.m_numVertices = 3;
+ convexPolyhedronA.m_vertexOffset = 0;
+ float4 localCenter = make_float4(0.f,0.f,0.f,0.f);
+
+ btGpuFace face = faces[convexShapes[shapeIndexA].m_faceOffset+f];
+ float4 triMinAabb, triMaxAabb;
+ btAabbCL triAabb;
+ triAabb.m_min = make_float4(1e30f,1e30f,1e30f,0.f);
+ triAabb.m_max = make_float4(-1e30f,-1e30f,-1e30f,0.f);
+
+ float4 verticesA[3];
+ for (int i=0;i<3;i++)
+ {
+ int index = indices[face.m_indexOffset+i];
+ float4 vert = vertices[convexShapes[shapeIndexA].m_vertexOffset+index];
+ verticesA[i] = vert;
+ localCenter += vert;
+
+ triAabb.m_min = min(triAabb.m_min,vert);
+ triAabb.m_max = max(triAabb.m_max,vert);
+
+ }
+
+ overlap = true;
+ overlap = (triAabb.m_min.x > aabbs[bodyIndexB].m_max.x || triAabb.m_max.x < aabbs[bodyIndexB].m_min.x) ? false : overlap;
+ overlap = (triAabb.m_min.z > aabbs[bodyIndexB].m_max.z || triAabb.m_max.z < aabbs[bodyIndexB].m_min.z) ? false : overlap;
+ overlap = (triAabb.m_min.y > aabbs[bodyIndexB].m_max.y || triAabb.m_max.y < aabbs[bodyIndexB].m_min.y) ? false : overlap;
+
+ if (overlap)
+ {
+ float dmin = FLT_MAX;
+ int hasSeparatingAxis=5;
+ float4 sepAxis=make_float4(1,2,3,4);
+
+ int localCC=0;
+ numActualConcaveConvexTests++;
+
+ //a triangle has 3 unique edges
+ convexPolyhedronA.m_numUniqueEdges = 3;
+ convexPolyhedronA.m_uniqueEdgesOffset = 0;
+ float4 uniqueEdgesA[3];
+
+ uniqueEdgesA[0] = (verticesA[1]-verticesA[0]);
+ uniqueEdgesA[1] = (verticesA[2]-verticesA[1]);
+ uniqueEdgesA[2] = (verticesA[0]-verticesA[2]);
+
+
+ convexPolyhedronA.m_faceOffset = 0;
+
+ float4 normal = make_float4(face.m_plane.x,face.m_plane.y,face.m_plane.z,0.f);
+
+ btGpuFace facesA[TRIANGLE_NUM_CONVEX_FACES];
+ int indicesA[3+3+2+2+2];
+ int curUsedIndices=0;
+ int fidx=0;
+
+ //front size of triangle
+ {
+ facesA[fidx].m_indexOffset=curUsedIndices;
+ indicesA[0] = 0;
+ indicesA[1] = 1;
+ indicesA[2] = 2;
+ curUsedIndices+=3;
+ float c = face.m_plane.w;
+ facesA[fidx].m_plane.x = normal.x;
+ facesA[fidx].m_plane.y = normal.y;
+ facesA[fidx].m_plane.z = normal.z;
+ facesA[fidx].m_plane.w = c;
+ facesA[fidx].m_numIndices=3;
+ }
+ fidx++;
+ //back size of triangle
+ {
+ facesA[fidx].m_indexOffset=curUsedIndices;
+ indicesA[3]=2;
+ indicesA[4]=1;
+ indicesA[5]=0;
+ curUsedIndices+=3;
+ float c = dot(normal,verticesA[0]);
+ float c1 = -face.m_plane.w;
+ facesA[fidx].m_plane.x = -normal.x;
+ facesA[fidx].m_plane.y = -normal.y;
+ facesA[fidx].m_plane.z = -normal.z;
+ facesA[fidx].m_plane.w = c;
+ facesA[fidx].m_numIndices=3;
+ }
+ fidx++;
+
+ bool addEdgePlanes = true;
+ if (addEdgePlanes)
+ {
+ int numVertices=3;
+ int prevVertex = numVertices-1;
+ for (int i=0;i<numVertices;i++)
+ {
+ float4 v0 = verticesA[i];
+ float4 v1 = verticesA[prevVertex];
+
+ float4 edgeNormal = normalize(cross(normal,v1-v0));
+ float c = -dot(edgeNormal,v0);
+
+ facesA[fidx].m_numIndices = 2;
+ facesA[fidx].m_indexOffset=curUsedIndices;
+ indicesA[curUsedIndices++]=i;
+ indicesA[curUsedIndices++]=prevVertex;
+
+ facesA[fidx].m_plane.x = edgeNormal.x;
+ facesA[fidx].m_plane.y = edgeNormal.y;
+ facesA[fidx].m_plane.z = edgeNormal.z;
+ facesA[fidx].m_plane.w = c;
+ fidx++;
+ prevVertex = i;
+ }
+ }
+ convexPolyhedronA.m_numFaces = TRIANGLE_NUM_CONVEX_FACES;
+ convexPolyhedronA.m_localCenter = localCenter*(1.f/3.f);
+
+
+ float4 posA = rigidBodies[bodyIndexA].m_pos;
+ posA.w = 0.f;
+ float4 posB = rigidBodies[bodyIndexB].m_pos;
+ posB.w = 0.f;
+
+ float4 ornA = rigidBodies[bodyIndexA].m_quat;
+ float4 ornB =rigidBodies[bodyIndexB].m_quat;
+
+
+
+
+ ///////////////////
+ ///compound shape support
+
+ if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)
+ {
+ int compoundChild = concavePairs[pairIdx].w;
+ int childShapeIndexB = compoundChild;//collidables[collidableIndexB].m_shapeIndex+compoundChild;
+ int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;
+ float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;
+ float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;
+ float4 newPosB = transform(&childPosB,&posB,&ornB);
+ float4 newOrnB = qtMul(ornB,childOrnB);
+ posB = newPosB;
+ ornB = newOrnB;
+ shapeIndexB = collidables[childColIndexB].m_shapeIndex;
+ }
+ //////////////////
+
+ float4 c0local = convexPolyhedronA.m_localCenter;
+ float4 c0 = transform(&c0local, &posA, &ornA);
+ float4 c1local = convexShapes[shapeIndexB].m_localCenter;
+ float4 c1 = transform(&c1local,&posB,&ornB);
+ const float4 DeltaC2 = c0 - c1;
+
+
+ bool sepA = findSeparatingAxisLocalA( &convexPolyhedronA, &convexShapes[shapeIndexB],
+ posA,ornA,
+ posB,ornB,
+ DeltaC2,
+ verticesA,uniqueEdgesA,facesA,indicesA,
+ vertices,uniqueEdges,faces,indices,
+ &sepAxis,&dmin);
+ hasSeparatingAxis = 4;
+ if (!sepA)
+ {
+ hasSeparatingAxis = 0;
+ } else
+ {
+ bool sepB = findSeparatingAxisLocalB( &convexShapes[shapeIndexB],&convexPolyhedronA,
+ posB,ornB,
+ posA,ornA,
+ DeltaC2,
+ vertices,uniqueEdges,faces,indices,
+ verticesA,uniqueEdgesA,facesA,indicesA,
+ &sepAxis,&dmin);
+
+ if (!sepB)
+ {
+ hasSeparatingAxis = 0;
+ } else
+ {
+ hasSeparatingAxis = 1;
+ }
+ }
+
+ if (hasSeparatingAxis)
+ {
+ dmins[i] = dmin;
+ concaveSeparatingNormalsOut[pairIdx]=sepAxis;
+ concaveHasSeparatingNormals[i]=1;
+
+ } else
+ {
+ //mark this pair as in-active
+ concavePairs[pairIdx].w = -1;
+ }
+ }
+ else
+ {
+ //mark this pair as in-active
+ concavePairs[pairIdx].w = -1;
+ }
+}
+
+
+
+
+// work-in-progress
+__kernel void findConcaveSeparatingAxisEdgeEdgeKernel( __global int4* concavePairs,
+ __global const BodyData* rigidBodies,
+ __global const btCollidableGpu* collidables,
+ __global const ConvexPolyhedronCL* convexShapes,
+ __global const float4* vertices,
+ __global const float4* uniqueEdges,
+ __global const btGpuFace* faces,
+ __global const int* indices,
+ __global const btGpuChildShape* gpuChildShapes,
+ __global btAabbCL* aabbs,
+ __global float4* concaveSeparatingNormalsOut,
+ __global int* concaveHasSeparatingNormals,
+ __global int4* clippingFacesOut,
+ __global float4* worldVertsA1GPU,
+ __global float4* worldNormalsAGPU,
+ __global float4* worldVertsB1GPU,
+ __global float* dmins,
+ int vertexFaceCapacity,
+ int numConcavePairs
+ )
+{
+
+ int i = get_global_id(0);
+ if (i>=numConcavePairs)
+ return;
+
+ if (!concaveHasSeparatingNormals[i])
+ return;
+
+ int pairIdx = i;
+
+ int bodyIndexA = concavePairs[i].x;
+ int bodyIndexB = concavePairs[i].y;
+
+ int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
+ int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
+
+ int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
+ int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
+
+
+ int numFacesA = convexShapes[shapeIndexA].m_numFaces;
+ int numActualConcaveConvexTests = 0;
+
+ int f = concavePairs[i].z;
+
+ bool overlap = false;
+
+ ConvexPolyhedronCL convexPolyhedronA;
+
+ //add 3 vertices of the triangle
+ convexPolyhedronA.m_numVertices = 3;
+ convexPolyhedronA.m_vertexOffset = 0;
+ float4 localCenter = make_float4(0.f,0.f,0.f,0.f);
+
+ btGpuFace face = faces[convexShapes[shapeIndexA].m_faceOffset+f];
+ float4 triMinAabb, triMaxAabb;
+ btAabbCL triAabb;
+ triAabb.m_min = make_float4(1e30f,1e30f,1e30f,0.f);
+ triAabb.m_max = make_float4(-1e30f,-1e30f,-1e30f,0.f);
+
+ float4 verticesA[3];
+ for (int i=0;i<3;i++)
+ {
+ int index = indices[face.m_indexOffset+i];
+ float4 vert = vertices[convexShapes[shapeIndexA].m_vertexOffset+index];
+ verticesA[i] = vert;
+ localCenter += vert;
+
+ triAabb.m_min = min(triAabb.m_min,vert);
+ triAabb.m_max = max(triAabb.m_max,vert);
+
+ }
+
+ overlap = true;
+ overlap = (triAabb.m_min.x > aabbs[bodyIndexB].m_max.x || triAabb.m_max.x < aabbs[bodyIndexB].m_min.x) ? false : overlap;
+ overlap = (triAabb.m_min.z > aabbs[bodyIndexB].m_max.z || triAabb.m_max.z < aabbs[bodyIndexB].m_min.z) ? false : overlap;
+ overlap = (triAabb.m_min.y > aabbs[bodyIndexB].m_max.y || triAabb.m_max.y < aabbs[bodyIndexB].m_min.y) ? false : overlap;
+
+ if (overlap)
+ {
+ float dmin = dmins[i];
+ int hasSeparatingAxis=5;
+ float4 sepAxis=make_float4(1,2,3,4);
+ sepAxis = concaveSeparatingNormalsOut[pairIdx];
+
+ int localCC=0;
+ numActualConcaveConvexTests++;
+
+ //a triangle has 3 unique edges
+ convexPolyhedronA.m_numUniqueEdges = 3;
+ convexPolyhedronA.m_uniqueEdgesOffset = 0;
+ float4 uniqueEdgesA[3];
+
+ uniqueEdgesA[0] = (verticesA[1]-verticesA[0]);
+ uniqueEdgesA[1] = (verticesA[2]-verticesA[1]);
+ uniqueEdgesA[2] = (verticesA[0]-verticesA[2]);
+
+
+ convexPolyhedronA.m_faceOffset = 0;
+
+ float4 normal = make_float4(face.m_plane.x,face.m_plane.y,face.m_plane.z,0.f);
+
+ btGpuFace facesA[TRIANGLE_NUM_CONVEX_FACES];
+ int indicesA[3+3+2+2+2];
+ int curUsedIndices=0;
+ int fidx=0;
+
+ //front size of triangle
+ {
+ facesA[fidx].m_indexOffset=curUsedIndices;
+ indicesA[0] = 0;
+ indicesA[1] = 1;
+ indicesA[2] = 2;
+ curUsedIndices+=3;
+ float c = face.m_plane.w;
+ facesA[fidx].m_plane.x = normal.x;
+ facesA[fidx].m_plane.y = normal.y;
+ facesA[fidx].m_plane.z = normal.z;
+ facesA[fidx].m_plane.w = c;
+ facesA[fidx].m_numIndices=3;
+ }
+ fidx++;
+ //back size of triangle
+ {
+ facesA[fidx].m_indexOffset=curUsedIndices;
+ indicesA[3]=2;
+ indicesA[4]=1;
+ indicesA[5]=0;
+ curUsedIndices+=3;
+ float c = dot(normal,verticesA[0]);
+ float c1 = -face.m_plane.w;
+ facesA[fidx].m_plane.x = -normal.x;
+ facesA[fidx].m_plane.y = -normal.y;
+ facesA[fidx].m_plane.z = -normal.z;
+ facesA[fidx].m_plane.w = c;
+ facesA[fidx].m_numIndices=3;
+ }
+ fidx++;
+
+ bool addEdgePlanes = true;
+ if (addEdgePlanes)
+ {
+ int numVertices=3;
+ int prevVertex = numVertices-1;
+ for (int i=0;i<numVertices;i++)
+ {
+ float4 v0 = verticesA[i];
+ float4 v1 = verticesA[prevVertex];
+
+ float4 edgeNormal = normalize(cross(normal,v1-v0));
+ float c = -dot(edgeNormal,v0);
+
+ facesA[fidx].m_numIndices = 2;
+ facesA[fidx].m_indexOffset=curUsedIndices;
+ indicesA[curUsedIndices++]=i;
+ indicesA[curUsedIndices++]=prevVertex;
+
+ facesA[fidx].m_plane.x = edgeNormal.x;
+ facesA[fidx].m_plane.y = edgeNormal.y;
+ facesA[fidx].m_plane.z = edgeNormal.z;
+ facesA[fidx].m_plane.w = c;
+ fidx++;
+ prevVertex = i;
+ }
+ }
+ convexPolyhedronA.m_numFaces = TRIANGLE_NUM_CONVEX_FACES;
+ convexPolyhedronA.m_localCenter = localCenter*(1.f/3.f);
+
+
+ float4 posA = rigidBodies[bodyIndexA].m_pos;
+ posA.w = 0.f;
+ float4 posB = rigidBodies[bodyIndexB].m_pos;
+ posB.w = 0.f;
+
+ float4 ornA = rigidBodies[bodyIndexA].m_quat;
+ float4 ornB =rigidBodies[bodyIndexB].m_quat;
+
+
+
+
+ ///////////////////
+ ///compound shape support
+
+ if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)
+ {
+ int compoundChild = concavePairs[pairIdx].w;
+ int childShapeIndexB = compoundChild;//collidables[collidableIndexB].m_shapeIndex+compoundChild;
+ int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;
+ float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;
+ float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;
+ float4 newPosB = transform(&childPosB,&posB,&ornB);
+ float4 newOrnB = qtMul(ornB,childOrnB);
+ posB = newPosB;
+ ornB = newOrnB;
+ shapeIndexB = collidables[childColIndexB].m_shapeIndex;
+ }
+ //////////////////
+
+ float4 c0local = convexPolyhedronA.m_localCenter;
+ float4 c0 = transform(&c0local, &posA, &ornA);
+ float4 c1local = convexShapes[shapeIndexB].m_localCenter;
+ float4 c1 = transform(&c1local,&posB,&ornB);
+ const float4 DeltaC2 = c0 - c1;
+
+
+ {
+ bool sepEE = findSeparatingAxisEdgeEdgeLocalA( &convexPolyhedronA, &convexShapes[shapeIndexB],
+ posA,ornA,
+ posB,ornB,
+ DeltaC2,
+ verticesA,uniqueEdgesA,facesA,indicesA,
+ vertices,uniqueEdges,faces,indices,
+ &sepAxis,&dmin);
+
+ if (!sepEE)
+ {
+ hasSeparatingAxis = 0;
+ } else
+ {
+ hasSeparatingAxis = 1;
+ }
+ }
+
+
+ if (hasSeparatingAxis)
+ {
+ sepAxis.w = dmin;
+ dmins[i] = dmin;
+ concaveSeparatingNormalsOut[pairIdx]=sepAxis;
+ concaveHasSeparatingNormals[i]=1;
+
+ float minDist = -1e30f;
+ float maxDist = 0.02f;
+
+
+ findClippingFaces(sepAxis,
+ &convexPolyhedronA,
+ &convexShapes[shapeIndexB],
+ posA,ornA,
+ posB,ornB,
+ worldVertsA1GPU,
+ worldNormalsAGPU,
+ worldVertsB1GPU,
+ vertexFaceCapacity,
+ minDist, maxDist,
+ verticesA,
+ facesA,
+ indicesA,
+ vertices,
+ faces,
+ indices,
+ clippingFacesOut, pairIdx);
+
+
+ } else
+ {
+ //mark this pair as in-active
+ concavePairs[pairIdx].w = -1;
+ }
+ }
+ else
+ {
+ //mark this pair as in-active
+ concavePairs[pairIdx].w = -1;
+ }
+
+ concavePairs[i].z = -1;//for the next stage, z is used to determine existing contact points
+}
+
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/kernels/satConcaveKernels.h b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/kernels/satConcaveKernels.h
new file mode 100644
index 0000000000..611569cacf
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/kernels/satConcaveKernels.h
@@ -0,0 +1,1457 @@
+//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
+static const char* satConcaveKernelsCL= \
+"//keep this enum in sync with the CPU version (in btCollidable.h)\n"
+"//written by Erwin Coumans\n"
+"#define SHAPE_CONVEX_HULL 3\n"
+"#define SHAPE_CONCAVE_TRIMESH 5\n"
+"#define TRIANGLE_NUM_CONVEX_FACES 5\n"
+"#define SHAPE_COMPOUND_OF_CONVEX_HULLS 6\n"
+"#define B3_MAX_STACK_DEPTH 256\n"
+"typedef unsigned int u32;\n"
+"///keep this in sync with btCollidable.h\n"
+"typedef struct\n"
+"{\n"
+" union {\n"
+" int m_numChildShapes;\n"
+" int m_bvhIndex;\n"
+" };\n"
+" union\n"
+" {\n"
+" float m_radius;\n"
+" int m_compoundBvhIndex;\n"
+" };\n"
+" \n"
+" int m_shapeType;\n"
+" int m_shapeIndex;\n"
+" \n"
+"} btCollidableGpu;\n"
+"#define MAX_NUM_PARTS_IN_BITS 10\n"
+"///b3QuantizedBvhNode is a compressed aabb node, 16 bytes.\n"
+"///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range).\n"
+"typedef struct\n"
+"{\n"
+" //12 bytes\n"
+" unsigned short int m_quantizedAabbMin[3];\n"
+" unsigned short int m_quantizedAabbMax[3];\n"
+" //4 bytes\n"
+" int m_escapeIndexOrTriangleIndex;\n"
+"} b3QuantizedBvhNode;\n"
+"typedef struct\n"
+"{\n"
+" float4 m_aabbMin;\n"
+" float4 m_aabbMax;\n"
+" float4 m_quantization;\n"
+" int m_numNodes;\n"
+" int m_numSubTrees;\n"
+" int m_nodeOffset;\n"
+" int m_subTreeOffset;\n"
+"} b3BvhInfo;\n"
+"int getTriangleIndex(const b3QuantizedBvhNode* rootNode)\n"
+"{\n"
+" unsigned int x=0;\n"
+" unsigned int y = (~(x&0))<<(31-MAX_NUM_PARTS_IN_BITS);\n"
+" // Get only the lower bits where the triangle index is stored\n"
+" return (rootNode->m_escapeIndexOrTriangleIndex&~(y));\n"
+"}\n"
+"int getTriangleIndexGlobal(__global const b3QuantizedBvhNode* rootNode)\n"
+"{\n"
+" unsigned int x=0;\n"
+" unsigned int y = (~(x&0))<<(31-MAX_NUM_PARTS_IN_BITS);\n"
+" // Get only the lower bits where the triangle index is stored\n"
+" return (rootNode->m_escapeIndexOrTriangleIndex&~(y));\n"
+"}\n"
+"int isLeafNode(const b3QuantizedBvhNode* rootNode)\n"
+"{\n"
+" //skipindex is negative (internal node), triangleindex >=0 (leafnode)\n"
+" return (rootNode->m_escapeIndexOrTriangleIndex >= 0)? 1 : 0;\n"
+"}\n"
+"int isLeafNodeGlobal(__global const b3QuantizedBvhNode* rootNode)\n"
+"{\n"
+" //skipindex is negative (internal node), triangleindex >=0 (leafnode)\n"
+" return (rootNode->m_escapeIndexOrTriangleIndex >= 0)? 1 : 0;\n"
+"}\n"
+" \n"
+"int getEscapeIndex(const b3QuantizedBvhNode* rootNode)\n"
+"{\n"
+" return -rootNode->m_escapeIndexOrTriangleIndex;\n"
+"}\n"
+"int getEscapeIndexGlobal(__global const b3QuantizedBvhNode* rootNode)\n"
+"{\n"
+" return -rootNode->m_escapeIndexOrTriangleIndex;\n"
+"}\n"
+"typedef struct\n"
+"{\n"
+" //12 bytes\n"
+" unsigned short int m_quantizedAabbMin[3];\n"
+" unsigned short int m_quantizedAabbMax[3];\n"
+" //4 bytes, points to the root of the subtree\n"
+" int m_rootNodeIndex;\n"
+" //4 bytes\n"
+" int m_subtreeSize;\n"
+" int m_padding[3];\n"
+"} b3BvhSubtreeInfo;\n"
+"typedef struct\n"
+"{\n"
+" float4 m_childPosition;\n"
+" float4 m_childOrientation;\n"
+" int m_shapeIndex;\n"
+" int m_unused0;\n"
+" int m_unused1;\n"
+" int m_unused2;\n"
+"} btGpuChildShape;\n"
+"typedef struct\n"
+"{\n"
+" float4 m_pos;\n"
+" float4 m_quat;\n"
+" float4 m_linVel;\n"
+" float4 m_angVel;\n"
+" u32 m_collidableIdx;\n"
+" float m_invMass;\n"
+" float m_restituitionCoeff;\n"
+" float m_frictionCoeff;\n"
+"} BodyData;\n"
+"typedef struct \n"
+"{\n"
+" float4 m_localCenter;\n"
+" float4 m_extents;\n"
+" float4 mC;\n"
+" float4 mE;\n"
+" \n"
+" float m_radius;\n"
+" int m_faceOffset;\n"
+" int m_numFaces;\n"
+" int m_numVertices;\n"
+" int m_vertexOffset;\n"
+" int m_uniqueEdgesOffset;\n"
+" int m_numUniqueEdges;\n"
+" int m_unused;\n"
+"} ConvexPolyhedronCL;\n"
+"typedef struct \n"
+"{\n"
+" union\n"
+" {\n"
+" float4 m_min;\n"
+" float m_minElems[4];\n"
+" int m_minIndices[4];\n"
+" };\n"
+" union\n"
+" {\n"
+" float4 m_max;\n"
+" float m_maxElems[4];\n"
+" int m_maxIndices[4];\n"
+" };\n"
+"} btAabbCL;\n"
+"#ifndef B3_AABB_H\n"
+"#define B3_AABB_H\n"
+"#ifndef B3_FLOAT4_H\n"
+"#define B3_FLOAT4_H\n"
+"#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+"#define B3_PLATFORM_DEFINITIONS_H\n"
+"struct MyTest\n"
+"{\n"
+" int bla;\n"
+"};\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
+"#define B3_LARGE_FLOAT 1e18f\n"
+"#define B3_INFINITY 1e18f\n"
+"#define b3Assert(a)\n"
+"#define b3ConstArray(a) __global const a*\n"
+"#define b3AtomicInc atomic_inc\n"
+"#define b3AtomicAdd atomic_add\n"
+"#define b3Fabs fabs\n"
+"#define b3Sqrt native_sqrt\n"
+"#define b3Sin native_sin\n"
+"#define b3Cos native_cos\n"
+"#define B3_STATIC\n"
+"#endif\n"
+"#endif\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+" typedef float4 b3Float4;\n"
+" #define b3Float4ConstArg const b3Float4\n"
+" #define b3MakeFloat4 (float4)\n"
+" float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+" {\n"
+" float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+" float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+" return dot(a1, b1);\n"
+" }\n"
+" b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+" {\n"
+" float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+" float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+" return cross(a1, b1);\n"
+" }\n"
+" #define b3MinFloat4 min\n"
+" #define b3MaxFloat4 max\n"
+" #define b3Normalized(a) normalize(a)\n"
+"#endif \n"
+" \n"
+"inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
+"{\n"
+" if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6) \n"
+" return false;\n"
+" return true;\n"
+"}\n"
+"inline int b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
+"{\n"
+" float maxDot = -B3_INFINITY;\n"
+" int i = 0;\n"
+" int ptIndex = -1;\n"
+" for( i = 0; i < vecLen; i++ )\n"
+" {\n"
+" float dot = b3Dot3F4(vecArray[i],vec);\n"
+" \n"
+" if( dot > maxDot )\n"
+" {\n"
+" maxDot = dot;\n"
+" ptIndex = i;\n"
+" }\n"
+" }\n"
+" b3Assert(ptIndex>=0);\n"
+" if (ptIndex<0)\n"
+" {\n"
+" ptIndex = 0;\n"
+" }\n"
+" *dotOut = maxDot;\n"
+" return ptIndex;\n"
+"}\n"
+"#endif //B3_FLOAT4_H\n"
+"#ifndef B3_MAT3x3_H\n"
+"#define B3_MAT3x3_H\n"
+"#ifndef B3_QUAT_H\n"
+"#define B3_QUAT_H\n"
+"#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"#endif\n"
+"#endif\n"
+"#ifndef B3_FLOAT4_H\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"#endif \n"
+"#endif //B3_FLOAT4_H\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+" typedef float4 b3Quat;\n"
+" #define b3QuatConstArg const b3Quat\n"
+" \n"
+" \n"
+"inline float4 b3FastNormalize4(float4 v)\n"
+"{\n"
+" v = (float4)(v.xyz,0.f);\n"
+" return fast_normalize(v);\n"
+"}\n"
+" \n"
+"inline b3Quat b3QuatMul(b3Quat a, b3Quat b);\n"
+"inline b3Quat b3QuatNormalized(b3QuatConstArg in);\n"
+"inline b3Quat b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec);\n"
+"inline b3Quat b3QuatInvert(b3QuatConstArg q);\n"
+"inline b3Quat b3QuatInverse(b3QuatConstArg q);\n"
+"inline b3Quat b3QuatMul(b3QuatConstArg a, b3QuatConstArg b)\n"
+"{\n"
+" b3Quat ans;\n"
+" ans = b3Cross3( a, b );\n"
+" ans += a.w*b+b.w*a;\n"
+"// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
+" ans.w = a.w*b.w - b3Dot3F4(a, b);\n"
+" return ans;\n"
+"}\n"
+"inline b3Quat b3QuatNormalized(b3QuatConstArg in)\n"
+"{\n"
+" b3Quat q;\n"
+" q=in;\n"
+" //return b3FastNormalize4(in);\n"
+" float len = native_sqrt(dot(q, q));\n"
+" if(len > 0.f)\n"
+" {\n"
+" q *= 1.f / len;\n"
+" }\n"
+" else\n"
+" {\n"
+" q.x = q.y = q.z = 0.f;\n"
+" q.w = 1.f;\n"
+" }\n"
+" return q;\n"
+"}\n"
+"inline float4 b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
+"{\n"
+" b3Quat qInv = b3QuatInvert( q );\n"
+" float4 vcpy = vec;\n"
+" vcpy.w = 0.f;\n"
+" float4 out = b3QuatMul(b3QuatMul(q,vcpy),qInv);\n"
+" return out;\n"
+"}\n"
+"inline b3Quat b3QuatInverse(b3QuatConstArg q)\n"
+"{\n"
+" return (b3Quat)(-q.xyz, q.w);\n"
+"}\n"
+"inline b3Quat b3QuatInvert(b3QuatConstArg q)\n"
+"{\n"
+" return (b3Quat)(-q.xyz, q.w);\n"
+"}\n"
+"inline float4 b3QuatInvRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
+"{\n"
+" return b3QuatRotate( b3QuatInvert( q ), vec );\n"
+"}\n"
+"inline b3Float4 b3TransformPoint(b3Float4ConstArg point, b3Float4ConstArg translation, b3QuatConstArg orientation)\n"
+"{\n"
+" return b3QuatRotate( orientation, point ) + (translation);\n"
+"}\n"
+" \n"
+"#endif \n"
+"#endif //B3_QUAT_H\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"typedef struct\n"
+"{\n"
+" b3Float4 m_row[3];\n"
+"}b3Mat3x3;\n"
+"#define b3Mat3x3ConstArg const b3Mat3x3\n"
+"#define b3GetRow(m,row) (m.m_row[row])\n"
+"inline b3Mat3x3 b3QuatGetRotationMatrix(b3Quat quat)\n"
+"{\n"
+" b3Float4 quat2 = (b3Float4)(quat.x*quat.x, quat.y*quat.y, quat.z*quat.z, 0.f);\n"
+" b3Mat3x3 out;\n"
+" out.m_row[0].x=1-2*quat2.y-2*quat2.z;\n"
+" out.m_row[0].y=2*quat.x*quat.y-2*quat.w*quat.z;\n"
+" out.m_row[0].z=2*quat.x*quat.z+2*quat.w*quat.y;\n"
+" out.m_row[0].w = 0.f;\n"
+" out.m_row[1].x=2*quat.x*quat.y+2*quat.w*quat.z;\n"
+" out.m_row[1].y=1-2*quat2.x-2*quat2.z;\n"
+" out.m_row[1].z=2*quat.y*quat.z-2*quat.w*quat.x;\n"
+" out.m_row[1].w = 0.f;\n"
+" out.m_row[2].x=2*quat.x*quat.z-2*quat.w*quat.y;\n"
+" out.m_row[2].y=2*quat.y*quat.z+2*quat.w*quat.x;\n"
+" out.m_row[2].z=1-2*quat2.x-2*quat2.y;\n"
+" out.m_row[2].w = 0.f;\n"
+" return out;\n"
+"}\n"
+"inline b3Mat3x3 b3AbsoluteMat3x3(b3Mat3x3ConstArg matIn)\n"
+"{\n"
+" b3Mat3x3 out;\n"
+" out.m_row[0] = fabs(matIn.m_row[0]);\n"
+" out.m_row[1] = fabs(matIn.m_row[1]);\n"
+" out.m_row[2] = fabs(matIn.m_row[2]);\n"
+" return out;\n"
+"}\n"
+"__inline\n"
+"b3Mat3x3 mtZero();\n"
+"__inline\n"
+"b3Mat3x3 mtIdentity();\n"
+"__inline\n"
+"b3Mat3x3 mtTranspose(b3Mat3x3 m);\n"
+"__inline\n"
+"b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b);\n"
+"__inline\n"
+"b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b);\n"
+"__inline\n"
+"b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b);\n"
+"__inline\n"
+"b3Mat3x3 mtZero()\n"
+"{\n"
+" b3Mat3x3 m;\n"
+" m.m_row[0] = (b3Float4)(0.f);\n"
+" m.m_row[1] = (b3Float4)(0.f);\n"
+" m.m_row[2] = (b3Float4)(0.f);\n"
+" return m;\n"
+"}\n"
+"__inline\n"
+"b3Mat3x3 mtIdentity()\n"
+"{\n"
+" b3Mat3x3 m;\n"
+" m.m_row[0] = (b3Float4)(1,0,0,0);\n"
+" m.m_row[1] = (b3Float4)(0,1,0,0);\n"
+" m.m_row[2] = (b3Float4)(0,0,1,0);\n"
+" return m;\n"
+"}\n"
+"__inline\n"
+"b3Mat3x3 mtTranspose(b3Mat3x3 m)\n"
+"{\n"
+" b3Mat3x3 out;\n"
+" out.m_row[0] = (b3Float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);\n"
+" out.m_row[1] = (b3Float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);\n"
+" out.m_row[2] = (b3Float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);\n"
+" return out;\n"
+"}\n"
+"__inline\n"
+"b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b)\n"
+"{\n"
+" b3Mat3x3 transB;\n"
+" transB = mtTranspose( b );\n"
+" b3Mat3x3 ans;\n"
+" // why this doesn't run when 0ing in the for{}\n"
+" a.m_row[0].w = 0.f;\n"
+" a.m_row[1].w = 0.f;\n"
+" a.m_row[2].w = 0.f;\n"
+" for(int i=0; i<3; i++)\n"
+" {\n"
+"// a.m_row[i].w = 0.f;\n"
+" ans.m_row[i].x = b3Dot3F4(a.m_row[i],transB.m_row[0]);\n"
+" ans.m_row[i].y = b3Dot3F4(a.m_row[i],transB.m_row[1]);\n"
+" ans.m_row[i].z = b3Dot3F4(a.m_row[i],transB.m_row[2]);\n"
+" ans.m_row[i].w = 0.f;\n"
+" }\n"
+" return ans;\n"
+"}\n"
+"__inline\n"
+"b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b)\n"
+"{\n"
+" b3Float4 ans;\n"
+" ans.x = b3Dot3F4( a.m_row[0], b );\n"
+" ans.y = b3Dot3F4( a.m_row[1], b );\n"
+" ans.z = b3Dot3F4( a.m_row[2], b );\n"
+" ans.w = 0.f;\n"
+" return ans;\n"
+"}\n"
+"__inline\n"
+"b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b)\n"
+"{\n"
+" b3Float4 colx = b3MakeFloat4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
+" b3Float4 coly = b3MakeFloat4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
+" b3Float4 colz = b3MakeFloat4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
+" b3Float4 ans;\n"
+" ans.x = b3Dot3F4( a, colx );\n"
+" ans.y = b3Dot3F4( a, coly );\n"
+" ans.z = b3Dot3F4( a, colz );\n"
+" return ans;\n"
+"}\n"
+"#endif\n"
+"#endif //B3_MAT3x3_H\n"
+"typedef struct b3Aabb b3Aabb_t;\n"
+"struct b3Aabb\n"
+"{\n"
+" union\n"
+" {\n"
+" float m_min[4];\n"
+" b3Float4 m_minVec;\n"
+" int m_minIndices[4];\n"
+" };\n"
+" union\n"
+" {\n"
+" float m_max[4];\n"
+" b3Float4 m_maxVec;\n"
+" int m_signedMaxIndices[4];\n"
+" };\n"
+"};\n"
+"inline void b3TransformAabb2(b3Float4ConstArg localAabbMin,b3Float4ConstArg localAabbMax, float margin,\n"
+" b3Float4ConstArg pos,\n"
+" b3QuatConstArg orn,\n"
+" b3Float4* aabbMinOut,b3Float4* aabbMaxOut)\n"
+"{\n"
+" b3Float4 localHalfExtents = 0.5f*(localAabbMax-localAabbMin);\n"
+" localHalfExtents+=b3MakeFloat4(margin,margin,margin,0.f);\n"
+" b3Float4 localCenter = 0.5f*(localAabbMax+localAabbMin);\n"
+" b3Mat3x3 m;\n"
+" m = b3QuatGetRotationMatrix(orn);\n"
+" b3Mat3x3 abs_b = b3AbsoluteMat3x3(m);\n"
+" b3Float4 center = b3TransformPoint(localCenter,pos,orn);\n"
+" \n"
+" b3Float4 extent = b3MakeFloat4(b3Dot3F4(localHalfExtents,b3GetRow(abs_b,0)),\n"
+" b3Dot3F4(localHalfExtents,b3GetRow(abs_b,1)),\n"
+" b3Dot3F4(localHalfExtents,b3GetRow(abs_b,2)),\n"
+" 0.f);\n"
+" *aabbMinOut = center-extent;\n"
+" *aabbMaxOut = center+extent;\n"
+"}\n"
+"/// conservative test for overlap between two aabbs\n"
+"inline bool b3TestAabbAgainstAabb(b3Float4ConstArg aabbMin1,b3Float4ConstArg aabbMax1,\n"
+" b3Float4ConstArg aabbMin2, b3Float4ConstArg aabbMax2)\n"
+"{\n"
+" bool overlap = true;\n"
+" overlap = (aabbMin1.x > aabbMax2.x || aabbMax1.x < aabbMin2.x) ? false : overlap;\n"
+" overlap = (aabbMin1.z > aabbMax2.z || aabbMax1.z < aabbMin2.z) ? false : overlap;\n"
+" overlap = (aabbMin1.y > aabbMax2.y || aabbMax1.y < aabbMin2.y) ? false : overlap;\n"
+" return overlap;\n"
+"}\n"
+"#endif //B3_AABB_H\n"
+"/*\n"
+"Bullet Continuous Collision Detection and Physics Library\n"
+"Copyright (c) 2003-2013 Erwin Coumans http://bulletphysics.org\n"
+"This software is provided 'as-is', without any express or implied warranty.\n"
+"In no event will the authors be held liable for any damages arising from the use of this software.\n"
+"Permission is granted to anyone to use this software for any purpose,\n"
+"including commercial applications, and to alter it and redistribute it freely,\n"
+"subject to the following restrictions:\n"
+"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.\n"
+"2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
+"3. This notice may not be removed or altered from any source distribution.\n"
+"*/\n"
+"#ifndef B3_INT2_H\n"
+"#define B3_INT2_H\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"#define b3UnsignedInt2 uint2\n"
+"#define b3Int2 int2\n"
+"#define b3MakeInt2 (int2)\n"
+"#endif //__cplusplus\n"
+"#endif\n"
+"typedef struct\n"
+"{\n"
+" float4 m_plane;\n"
+" int m_indexOffset;\n"
+" int m_numIndices;\n"
+"} btGpuFace;\n"
+"#define make_float4 (float4)\n"
+"__inline\n"
+"float4 cross3(float4 a, float4 b)\n"
+"{\n"
+" return cross(a,b);\n"
+" \n"
+"// float4 a1 = make_float4(a.xyz,0.f);\n"
+"// float4 b1 = make_float4(b.xyz,0.f);\n"
+"// return cross(a1,b1);\n"
+"//float4 c = make_float4(a.y*b.z - a.z*b.y,a.z*b.x - a.x*b.z,a.x*b.y - a.y*b.x,0.f);\n"
+" \n"
+" // float4 c = make_float4(a.y*b.z - a.z*b.y,1.f,a.x*b.y - a.y*b.x,0.f);\n"
+" \n"
+" //return c;\n"
+"}\n"
+"__inline\n"
+"float dot3F4(float4 a, float4 b)\n"
+"{\n"
+" float4 a1 = make_float4(a.xyz,0.f);\n"
+" float4 b1 = make_float4(b.xyz,0.f);\n"
+" return dot(a1, b1);\n"
+"}\n"
+"__inline\n"
+"float4 fastNormalize4(float4 v)\n"
+"{\n"
+" v = make_float4(v.xyz,0.f);\n"
+" return fast_normalize(v);\n"
+"}\n"
+"///////////////////////////////////////\n"
+"// Quaternion\n"
+"///////////////////////////////////////\n"
+"typedef float4 Quaternion;\n"
+"__inline\n"
+"Quaternion qtMul(Quaternion a, Quaternion b);\n"
+"__inline\n"
+"Quaternion qtNormalize(Quaternion in);\n"
+"__inline\n"
+"float4 qtRotate(Quaternion q, float4 vec);\n"
+"__inline\n"
+"Quaternion qtInvert(Quaternion q);\n"
+"__inline\n"
+"Quaternion qtMul(Quaternion a, Quaternion b)\n"
+"{\n"
+" Quaternion ans;\n"
+" ans = cross3( a, b );\n"
+" ans += a.w*b+b.w*a;\n"
+"// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
+" ans.w = a.w*b.w - dot3F4(a, b);\n"
+" return ans;\n"
+"}\n"
+"__inline\n"
+"Quaternion qtNormalize(Quaternion in)\n"
+"{\n"
+" return fastNormalize4(in);\n"
+"// in /= length( in );\n"
+"// return in;\n"
+"}\n"
+"__inline\n"
+"float4 qtRotate(Quaternion q, float4 vec)\n"
+"{\n"
+" Quaternion qInv = qtInvert( q );\n"
+" float4 vcpy = vec;\n"
+" vcpy.w = 0.f;\n"
+" float4 out = qtMul(qtMul(q,vcpy),qInv);\n"
+" return out;\n"
+"}\n"
+"__inline\n"
+"Quaternion qtInvert(Quaternion q)\n"
+"{\n"
+" return (Quaternion)(-q.xyz, q.w);\n"
+"}\n"
+"__inline\n"
+"float4 qtInvRotate(const Quaternion q, float4 vec)\n"
+"{\n"
+" return qtRotate( qtInvert( q ), vec );\n"
+"}\n"
+"__inline\n"
+"float4 transform(const float4* p, const float4* translation, const Quaternion* orientation)\n"
+"{\n"
+" return qtRotate( *orientation, *p ) + (*translation);\n"
+"}\n"
+"__inline\n"
+"float4 normalize3(const float4 a)\n"
+"{\n"
+" float4 n = make_float4(a.x, a.y, a.z, 0.f);\n"
+" return fastNormalize4( n );\n"
+"}\n"
+"inline void projectLocal(const ConvexPolyhedronCL* hull, const float4 pos, const float4 orn, \n"
+"const float4* dir, const float4* vertices, float* min, float* max)\n"
+"{\n"
+" min[0] = FLT_MAX;\n"
+" max[0] = -FLT_MAX;\n"
+" int numVerts = hull->m_numVertices;\n"
+" const float4 localDir = qtInvRotate(orn,*dir);\n"
+" float offset = dot(pos,*dir);\n"
+" for(int i=0;i<numVerts;i++)\n"
+" {\n"
+" float dp = dot(vertices[hull->m_vertexOffset+i],localDir);\n"
+" if(dp < min[0]) \n"
+" min[0] = dp;\n"
+" if(dp > max[0]) \n"
+" max[0] = dp;\n"
+" }\n"
+" if(min[0]>max[0])\n"
+" {\n"
+" float tmp = min[0];\n"
+" min[0] = max[0];\n"
+" max[0] = tmp;\n"
+" }\n"
+" min[0] += offset;\n"
+" max[0] += offset;\n"
+"}\n"
+"inline void project(__global const ConvexPolyhedronCL* hull, const float4 pos, const float4 orn, \n"
+"const float4* dir, __global const float4* vertices, float* min, float* max)\n"
+"{\n"
+" min[0] = FLT_MAX;\n"
+" max[0] = -FLT_MAX;\n"
+" int numVerts = hull->m_numVertices;\n"
+" const float4 localDir = qtInvRotate(orn,*dir);\n"
+" float offset = dot(pos,*dir);\n"
+" for(int i=0;i<numVerts;i++)\n"
+" {\n"
+" float dp = dot(vertices[hull->m_vertexOffset+i],localDir);\n"
+" if(dp < min[0]) \n"
+" min[0] = dp;\n"
+" if(dp > max[0]) \n"
+" max[0] = dp;\n"
+" }\n"
+" if(min[0]>max[0])\n"
+" {\n"
+" float tmp = min[0];\n"
+" min[0] = max[0];\n"
+" max[0] = tmp;\n"
+" }\n"
+" min[0] += offset;\n"
+" max[0] += offset;\n"
+"}\n"
+"inline bool TestSepAxisLocalA(const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, \n"
+" const float4 posA,const float4 ornA,\n"
+" const float4 posB,const float4 ornB,\n"
+" float4* sep_axis, const float4* verticesA, __global const float4* verticesB,float* depth)\n"
+"{\n"
+" float Min0,Max0;\n"
+" float Min1,Max1;\n"
+" projectLocal(hullA,posA,ornA,sep_axis,verticesA, &Min0, &Max0);\n"
+" project(hullB,posB,ornB, sep_axis,verticesB, &Min1, &Max1);\n"
+" if(Max0<Min1 || Max1<Min0)\n"
+" return false;\n"
+" float d0 = Max0 - Min1;\n"
+" float d1 = Max1 - Min0;\n"
+" *depth = d0<d1 ? d0:d1;\n"
+" return true;\n"
+"}\n"
+"inline bool IsAlmostZero(const float4 v)\n"
+"{\n"
+" if(fabs(v.x)>1e-6f || fabs(v.y)>1e-6f || fabs(v.z)>1e-6f)\n"
+" return false;\n"
+" return true;\n"
+"}\n"
+"bool findSeparatingAxisLocalA( const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, \n"
+" const float4 posA1,\n"
+" const float4 ornA,\n"
+" const float4 posB1,\n"
+" const float4 ornB,\n"
+" const float4 DeltaC2,\n"
+" \n"
+" const float4* verticesA, \n"
+" const float4* uniqueEdgesA, \n"
+" const btGpuFace* facesA,\n"
+" const int* indicesA,\n"
+" __global const float4* verticesB, \n"
+" __global const float4* uniqueEdgesB, \n"
+" __global const btGpuFace* facesB,\n"
+" __global const int* indicesB,\n"
+" float4* sep,\n"
+" float* dmin)\n"
+"{\n"
+" \n"
+" float4 posA = posA1;\n"
+" posA.w = 0.f;\n"
+" float4 posB = posB1;\n"
+" posB.w = 0.f;\n"
+" int curPlaneTests=0;\n"
+" {\n"
+" int numFacesA = hullA->m_numFaces;\n"
+" // Test normals from hullA\n"
+" for(int i=0;i<numFacesA;i++)\n"
+" {\n"
+" const float4 normal = facesA[hullA->m_faceOffset+i].m_plane;\n"
+" float4 faceANormalWS = qtRotate(ornA,normal);\n"
+" if (dot3F4(DeltaC2,faceANormalWS)<0)\n"
+" faceANormalWS*=-1.f;\n"
+" curPlaneTests++;\n"
+" float d;\n"
+" if(!TestSepAxisLocalA( hullA, hullB, posA,ornA,posB,ornB,&faceANormalWS, verticesA, verticesB,&d))\n"
+" return false;\n"
+" if(d<*dmin)\n"
+" {\n"
+" *dmin = d;\n"
+" *sep = faceANormalWS;\n"
+" }\n"
+" }\n"
+" }\n"
+" if((dot3F4(-DeltaC2,*sep))>0.0f)\n"
+" {\n"
+" *sep = -(*sep);\n"
+" }\n"
+" return true;\n"
+"}\n"
+"bool findSeparatingAxisLocalB( __global const ConvexPolyhedronCL* hullA, const ConvexPolyhedronCL* hullB, \n"
+" const float4 posA1,\n"
+" const float4 ornA,\n"
+" const float4 posB1,\n"
+" const float4 ornB,\n"
+" const float4 DeltaC2,\n"
+" __global const float4* verticesA, \n"
+" __global const float4* uniqueEdgesA, \n"
+" __global const btGpuFace* facesA,\n"
+" __global const int* indicesA,\n"
+" const float4* verticesB,\n"
+" const float4* uniqueEdgesB, \n"
+" const btGpuFace* facesB,\n"
+" const int* indicesB,\n"
+" float4* sep,\n"
+" float* dmin)\n"
+"{\n"
+" float4 posA = posA1;\n"
+" posA.w = 0.f;\n"
+" float4 posB = posB1;\n"
+" posB.w = 0.f;\n"
+" int curPlaneTests=0;\n"
+" {\n"
+" int numFacesA = hullA->m_numFaces;\n"
+" // Test normals from hullA\n"
+" for(int i=0;i<numFacesA;i++)\n"
+" {\n"
+" const float4 normal = facesA[hullA->m_faceOffset+i].m_plane;\n"
+" float4 faceANormalWS = qtRotate(ornA,normal);\n"
+" if (dot3F4(DeltaC2,faceANormalWS)<0)\n"
+" faceANormalWS *= -1.f;\n"
+" curPlaneTests++;\n"
+" float d;\n"
+" if(!TestSepAxisLocalA( hullB, hullA, posB,ornB,posA,ornA, &faceANormalWS, verticesB,verticesA, &d))\n"
+" return false;\n"
+" if(d<*dmin)\n"
+" {\n"
+" *dmin = d;\n"
+" *sep = faceANormalWS;\n"
+" }\n"
+" }\n"
+" }\n"
+" if((dot3F4(-DeltaC2,*sep))>0.0f)\n"
+" {\n"
+" *sep = -(*sep);\n"
+" }\n"
+" return true;\n"
+"}\n"
+"bool findSeparatingAxisEdgeEdgeLocalA( const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, \n"
+" const float4 posA1,\n"
+" const float4 ornA,\n"
+" const float4 posB1,\n"
+" const float4 ornB,\n"
+" const float4 DeltaC2,\n"
+" const float4* verticesA, \n"
+" const float4* uniqueEdgesA, \n"
+" const btGpuFace* facesA,\n"
+" const int* indicesA,\n"
+" __global const float4* verticesB, \n"
+" __global const float4* uniqueEdgesB, \n"
+" __global const btGpuFace* facesB,\n"
+" __global const int* indicesB,\n"
+" float4* sep,\n"
+" float* dmin)\n"
+"{\n"
+" float4 posA = posA1;\n"
+" posA.w = 0.f;\n"
+" float4 posB = posB1;\n"
+" posB.w = 0.f;\n"
+" int curPlaneTests=0;\n"
+" int curEdgeEdge = 0;\n"
+" // Test edges\n"
+" for(int e0=0;e0<hullA->m_numUniqueEdges;e0++)\n"
+" {\n"
+" const float4 edge0 = uniqueEdgesA[hullA->m_uniqueEdgesOffset+e0];\n"
+" float4 edge0World = qtRotate(ornA,edge0);\n"
+" for(int e1=0;e1<hullB->m_numUniqueEdges;e1++)\n"
+" {\n"
+" const float4 edge1 = uniqueEdgesB[hullB->m_uniqueEdgesOffset+e1];\n"
+" float4 edge1World = qtRotate(ornB,edge1);\n"
+" float4 crossje = cross3(edge0World,edge1World);\n"
+" curEdgeEdge++;\n"
+" if(!IsAlmostZero(crossje))\n"
+" {\n"
+" crossje = normalize3(crossje);\n"
+" if (dot3F4(DeltaC2,crossje)<0)\n"
+" crossje *= -1.f;\n"
+" float dist;\n"
+" bool result = true;\n"
+" {\n"
+" float Min0,Max0;\n"
+" float Min1,Max1;\n"
+" projectLocal(hullA,posA,ornA,&crossje,verticesA, &Min0, &Max0);\n"
+" project(hullB,posB,ornB,&crossje,verticesB, &Min1, &Max1);\n"
+" \n"
+" if(Max0<Min1 || Max1<Min0)\n"
+" result = false;\n"
+" \n"
+" float d0 = Max0 - Min1;\n"
+" float d1 = Max1 - Min0;\n"
+" dist = d0<d1 ? d0:d1;\n"
+" result = true;\n"
+" }\n"
+" \n"
+" if(dist<*dmin)\n"
+" {\n"
+" *dmin = dist;\n"
+" *sep = crossje;\n"
+" }\n"
+" }\n"
+" }\n"
+" }\n"
+" \n"
+" if((dot3F4(-DeltaC2,*sep))>0.0f)\n"
+" {\n"
+" *sep = -(*sep);\n"
+" }\n"
+" return true;\n"
+"}\n"
+"inline int findClippingFaces(const float4 separatingNormal,\n"
+" const ConvexPolyhedronCL* hullA, \n"
+" __global const ConvexPolyhedronCL* hullB,\n"
+" const float4 posA, const Quaternion ornA,const float4 posB, const Quaternion ornB,\n"
+" __global float4* worldVertsA1,\n"
+" __global float4* worldNormalsA1,\n"
+" __global float4* worldVertsB1,\n"
+" int capacityWorldVerts,\n"
+" const float minDist, float maxDist,\n"
+" const float4* verticesA,\n"
+" const btGpuFace* facesA,\n"
+" const int* indicesA,\n"
+" __global const float4* verticesB,\n"
+" __global const btGpuFace* facesB,\n"
+" __global const int* indicesB,\n"
+" __global int4* clippingFaces, int pairIndex)\n"
+"{\n"
+" int numContactsOut = 0;\n"
+" int numWorldVertsB1= 0;\n"
+" \n"
+" \n"
+" int closestFaceB=0;\n"
+" float dmax = -FLT_MAX;\n"
+" \n"
+" {\n"
+" for(int face=0;face<hullB->m_numFaces;face++)\n"
+" {\n"
+" const float4 Normal = make_float4(facesB[hullB->m_faceOffset+face].m_plane.x,\n"
+" facesB[hullB->m_faceOffset+face].m_plane.y, facesB[hullB->m_faceOffset+face].m_plane.z,0.f);\n"
+" const float4 WorldNormal = qtRotate(ornB, Normal);\n"
+" float d = dot3F4(WorldNormal,separatingNormal);\n"
+" if (d > dmax)\n"
+" {\n"
+" dmax = d;\n"
+" closestFaceB = face;\n"
+" }\n"
+" }\n"
+" }\n"
+" \n"
+" {\n"
+" const btGpuFace polyB = facesB[hullB->m_faceOffset+closestFaceB];\n"
+" int numVertices = polyB.m_numIndices;\n"
+" if (numVertices>capacityWorldVerts)\n"
+" numVertices = capacityWorldVerts;\n"
+" if (numVertices<0)\n"
+" numVertices = 0;\n"
+" \n"
+" for(int e0=0;e0<numVertices;e0++)\n"
+" {\n"
+" if (e0<capacityWorldVerts)\n"
+" {\n"
+" const float4 b = verticesB[hullB->m_vertexOffset+indicesB[polyB.m_indexOffset+e0]];\n"
+" worldVertsB1[pairIndex*capacityWorldVerts+numWorldVertsB1++] = transform(&b,&posB,&ornB);\n"
+" }\n"
+" }\n"
+" }\n"
+" \n"
+" int closestFaceA=0;\n"
+" {\n"
+" float dmin = FLT_MAX;\n"
+" for(int face=0;face<hullA->m_numFaces;face++)\n"
+" {\n"
+" const float4 Normal = make_float4(\n"
+" facesA[hullA->m_faceOffset+face].m_plane.x,\n"
+" facesA[hullA->m_faceOffset+face].m_plane.y,\n"
+" facesA[hullA->m_faceOffset+face].m_plane.z,\n"
+" 0.f);\n"
+" const float4 faceANormalWS = qtRotate(ornA,Normal);\n"
+" \n"
+" float d = dot3F4(faceANormalWS,separatingNormal);\n"
+" if (d < dmin)\n"
+" {\n"
+" dmin = d;\n"
+" closestFaceA = face;\n"
+" worldNormalsA1[pairIndex] = faceANormalWS;\n"
+" }\n"
+" }\n"
+" }\n"
+" \n"
+" int numVerticesA = facesA[hullA->m_faceOffset+closestFaceA].m_numIndices;\n"
+" if (numVerticesA>capacityWorldVerts)\n"
+" numVerticesA = capacityWorldVerts;\n"
+" if (numVerticesA<0)\n"
+" numVerticesA=0;\n"
+" \n"
+" for(int e0=0;e0<numVerticesA;e0++)\n"
+" {\n"
+" if (e0<capacityWorldVerts)\n"
+" {\n"
+" const float4 a = verticesA[hullA->m_vertexOffset+indicesA[facesA[hullA->m_faceOffset+closestFaceA].m_indexOffset+e0]];\n"
+" worldVertsA1[pairIndex*capacityWorldVerts+e0] = transform(&a, &posA,&ornA);\n"
+" }\n"
+" }\n"
+" \n"
+" clippingFaces[pairIndex].x = closestFaceA;\n"
+" clippingFaces[pairIndex].y = closestFaceB;\n"
+" clippingFaces[pairIndex].z = numVerticesA;\n"
+" clippingFaces[pairIndex].w = numWorldVertsB1;\n"
+" \n"
+" \n"
+" return numContactsOut;\n"
+"}\n"
+"// work-in-progress\n"
+"__kernel void findConcaveSeparatingAxisVertexFaceKernel( __global int4* concavePairs,\n"
+" __global const BodyData* rigidBodies,\n"
+" __global const btCollidableGpu* collidables,\n"
+" __global const ConvexPolyhedronCL* convexShapes,\n"
+" __global const float4* vertices,\n"
+" __global const float4* uniqueEdges,\n"
+" __global const btGpuFace* faces,\n"
+" __global const int* indices,\n"
+" __global const btGpuChildShape* gpuChildShapes,\n"
+" __global btAabbCL* aabbs,\n"
+" __global float4* concaveSeparatingNormalsOut,\n"
+" __global int* concaveHasSeparatingNormals,\n"
+" __global int4* clippingFacesOut,\n"
+" __global float4* worldVertsA1GPU,\n"
+" __global float4* worldNormalsAGPU,\n"
+" __global float4* worldVertsB1GPU,\n"
+" __global float* dmins,\n"
+" int vertexFaceCapacity,\n"
+" int numConcavePairs\n"
+" )\n"
+"{\n"
+" \n"
+" int i = get_global_id(0);\n"
+" if (i>=numConcavePairs)\n"
+" return;\n"
+" \n"
+" concaveHasSeparatingNormals[i] = 0;\n"
+" \n"
+" int pairIdx = i;\n"
+" \n"
+" int bodyIndexA = concavePairs[i].x;\n"
+" int bodyIndexB = concavePairs[i].y;\n"
+" \n"
+" int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
+" int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
+" \n"
+" int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
+" int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
+" \n"
+" if (collidables[collidableIndexB].m_shapeType!=SHAPE_CONVEX_HULL&&\n"
+" collidables[collidableIndexB].m_shapeType!=SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
+" {\n"
+" concavePairs[pairIdx].w = -1;\n"
+" return;\n"
+" }\n"
+" \n"
+" \n"
+" \n"
+" int numFacesA = convexShapes[shapeIndexA].m_numFaces;\n"
+" int numActualConcaveConvexTests = 0;\n"
+" \n"
+" int f = concavePairs[i].z;\n"
+" \n"
+" bool overlap = false;\n"
+" \n"
+" ConvexPolyhedronCL convexPolyhedronA;\n"
+" \n"
+" //add 3 vertices of the triangle\n"
+" convexPolyhedronA.m_numVertices = 3;\n"
+" convexPolyhedronA.m_vertexOffset = 0;\n"
+" float4 localCenter = make_float4(0.f,0.f,0.f,0.f);\n"
+" \n"
+" btGpuFace face = faces[convexShapes[shapeIndexA].m_faceOffset+f];\n"
+" float4 triMinAabb, triMaxAabb;\n"
+" btAabbCL triAabb;\n"
+" triAabb.m_min = make_float4(1e30f,1e30f,1e30f,0.f);\n"
+" triAabb.m_max = make_float4(-1e30f,-1e30f,-1e30f,0.f);\n"
+" \n"
+" float4 verticesA[3];\n"
+" for (int i=0;i<3;i++)\n"
+" {\n"
+" int index = indices[face.m_indexOffset+i];\n"
+" float4 vert = vertices[convexShapes[shapeIndexA].m_vertexOffset+index];\n"
+" verticesA[i] = vert;\n"
+" localCenter += vert;\n"
+" \n"
+" triAabb.m_min = min(triAabb.m_min,vert);\n"
+" triAabb.m_max = max(triAabb.m_max,vert);\n"
+" \n"
+" }\n"
+" \n"
+" overlap = true;\n"
+" overlap = (triAabb.m_min.x > aabbs[bodyIndexB].m_max.x || triAabb.m_max.x < aabbs[bodyIndexB].m_min.x) ? false : overlap;\n"
+" overlap = (triAabb.m_min.z > aabbs[bodyIndexB].m_max.z || triAabb.m_max.z < aabbs[bodyIndexB].m_min.z) ? false : overlap;\n"
+" overlap = (triAabb.m_min.y > aabbs[bodyIndexB].m_max.y || triAabb.m_max.y < aabbs[bodyIndexB].m_min.y) ? false : overlap;\n"
+" \n"
+" if (overlap)\n"
+" {\n"
+" float dmin = FLT_MAX;\n"
+" int hasSeparatingAxis=5;\n"
+" float4 sepAxis=make_float4(1,2,3,4);\n"
+" \n"
+" int localCC=0;\n"
+" numActualConcaveConvexTests++;\n"
+" \n"
+" //a triangle has 3 unique edges\n"
+" convexPolyhedronA.m_numUniqueEdges = 3;\n"
+" convexPolyhedronA.m_uniqueEdgesOffset = 0;\n"
+" float4 uniqueEdgesA[3];\n"
+" \n"
+" uniqueEdgesA[0] = (verticesA[1]-verticesA[0]);\n"
+" uniqueEdgesA[1] = (verticesA[2]-verticesA[1]);\n"
+" uniqueEdgesA[2] = (verticesA[0]-verticesA[2]);\n"
+" \n"
+" \n"
+" convexPolyhedronA.m_faceOffset = 0;\n"
+" \n"
+" float4 normal = make_float4(face.m_plane.x,face.m_plane.y,face.m_plane.z,0.f);\n"
+" \n"
+" btGpuFace facesA[TRIANGLE_NUM_CONVEX_FACES];\n"
+" int indicesA[3+3+2+2+2];\n"
+" int curUsedIndices=0;\n"
+" int fidx=0;\n"
+" \n"
+" //front size of triangle\n"
+" {\n"
+" facesA[fidx].m_indexOffset=curUsedIndices;\n"
+" indicesA[0] = 0;\n"
+" indicesA[1] = 1;\n"
+" indicesA[2] = 2;\n"
+" curUsedIndices+=3;\n"
+" float c = face.m_plane.w;\n"
+" facesA[fidx].m_plane.x = normal.x;\n"
+" facesA[fidx].m_plane.y = normal.y;\n"
+" facesA[fidx].m_plane.z = normal.z;\n"
+" facesA[fidx].m_plane.w = c;\n"
+" facesA[fidx].m_numIndices=3;\n"
+" }\n"
+" fidx++;\n"
+" //back size of triangle\n"
+" {\n"
+" facesA[fidx].m_indexOffset=curUsedIndices;\n"
+" indicesA[3]=2;\n"
+" indicesA[4]=1;\n"
+" indicesA[5]=0;\n"
+" curUsedIndices+=3;\n"
+" float c = dot(normal,verticesA[0]);\n"
+" float c1 = -face.m_plane.w;\n"
+" facesA[fidx].m_plane.x = -normal.x;\n"
+" facesA[fidx].m_plane.y = -normal.y;\n"
+" facesA[fidx].m_plane.z = -normal.z;\n"
+" facesA[fidx].m_plane.w = c;\n"
+" facesA[fidx].m_numIndices=3;\n"
+" }\n"
+" fidx++;\n"
+" \n"
+" bool addEdgePlanes = true;\n"
+" if (addEdgePlanes)\n"
+" {\n"
+" int numVertices=3;\n"
+" int prevVertex = numVertices-1;\n"
+" for (int i=0;i<numVertices;i++)\n"
+" {\n"
+" float4 v0 = verticesA[i];\n"
+" float4 v1 = verticesA[prevVertex];\n"
+" \n"
+" float4 edgeNormal = normalize(cross(normal,v1-v0));\n"
+" float c = -dot(edgeNormal,v0);\n"
+" \n"
+" facesA[fidx].m_numIndices = 2;\n"
+" facesA[fidx].m_indexOffset=curUsedIndices;\n"
+" indicesA[curUsedIndices++]=i;\n"
+" indicesA[curUsedIndices++]=prevVertex;\n"
+" \n"
+" facesA[fidx].m_plane.x = edgeNormal.x;\n"
+" facesA[fidx].m_plane.y = edgeNormal.y;\n"
+" facesA[fidx].m_plane.z = edgeNormal.z;\n"
+" facesA[fidx].m_plane.w = c;\n"
+" fidx++;\n"
+" prevVertex = i;\n"
+" }\n"
+" }\n"
+" convexPolyhedronA.m_numFaces = TRIANGLE_NUM_CONVEX_FACES;\n"
+" convexPolyhedronA.m_localCenter = localCenter*(1.f/3.f);\n"
+" \n"
+" \n"
+" float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
+" posA.w = 0.f;\n"
+" float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
+" posB.w = 0.f;\n"
+" \n"
+" float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
+" float4 ornB =rigidBodies[bodyIndexB].m_quat;\n"
+" \n"
+" \n"
+" \n"
+" \n"
+" ///////////////////\n"
+" ///compound shape support\n"
+" \n"
+" if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
+" {\n"
+" int compoundChild = concavePairs[pairIdx].w;\n"
+" int childShapeIndexB = compoundChild;//collidables[collidableIndexB].m_shapeIndex+compoundChild;\n"
+" int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;\n"
+" float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;\n"
+" float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;\n"
+" float4 newPosB = transform(&childPosB,&posB,&ornB);\n"
+" float4 newOrnB = qtMul(ornB,childOrnB);\n"
+" posB = newPosB;\n"
+" ornB = newOrnB;\n"
+" shapeIndexB = collidables[childColIndexB].m_shapeIndex;\n"
+" }\n"
+" //////////////////\n"
+" \n"
+" float4 c0local = convexPolyhedronA.m_localCenter;\n"
+" float4 c0 = transform(&c0local, &posA, &ornA);\n"
+" float4 c1local = convexShapes[shapeIndexB].m_localCenter;\n"
+" float4 c1 = transform(&c1local,&posB,&ornB);\n"
+" const float4 DeltaC2 = c0 - c1;\n"
+" \n"
+" \n"
+" bool sepA = findSeparatingAxisLocalA( &convexPolyhedronA, &convexShapes[shapeIndexB],\n"
+" posA,ornA,\n"
+" posB,ornB,\n"
+" DeltaC2,\n"
+" verticesA,uniqueEdgesA,facesA,indicesA,\n"
+" vertices,uniqueEdges,faces,indices,\n"
+" &sepAxis,&dmin);\n"
+" hasSeparatingAxis = 4;\n"
+" if (!sepA)\n"
+" {\n"
+" hasSeparatingAxis = 0;\n"
+" } else\n"
+" {\n"
+" bool sepB = findSeparatingAxisLocalB( &convexShapes[shapeIndexB],&convexPolyhedronA,\n"
+" posB,ornB,\n"
+" posA,ornA,\n"
+" DeltaC2,\n"
+" vertices,uniqueEdges,faces,indices,\n"
+" verticesA,uniqueEdgesA,facesA,indicesA,\n"
+" &sepAxis,&dmin);\n"
+" \n"
+" if (!sepB)\n"
+" {\n"
+" hasSeparatingAxis = 0;\n"
+" } else\n"
+" {\n"
+" hasSeparatingAxis = 1;\n"
+" }\n"
+" } \n"
+" \n"
+" if (hasSeparatingAxis)\n"
+" {\n"
+" dmins[i] = dmin;\n"
+" concaveSeparatingNormalsOut[pairIdx]=sepAxis;\n"
+" concaveHasSeparatingNormals[i]=1;\n"
+" \n"
+" } else\n"
+" { \n"
+" //mark this pair as in-active\n"
+" concavePairs[pairIdx].w = -1;\n"
+" }\n"
+" }\n"
+" else\n"
+" { \n"
+" //mark this pair as in-active\n"
+" concavePairs[pairIdx].w = -1;\n"
+" }\n"
+"}\n"
+"// work-in-progress\n"
+"__kernel void findConcaveSeparatingAxisEdgeEdgeKernel( __global int4* concavePairs,\n"
+" __global const BodyData* rigidBodies,\n"
+" __global const btCollidableGpu* collidables,\n"
+" __global const ConvexPolyhedronCL* convexShapes,\n"
+" __global const float4* vertices,\n"
+" __global const float4* uniqueEdges,\n"
+" __global const btGpuFace* faces,\n"
+" __global const int* indices,\n"
+" __global const btGpuChildShape* gpuChildShapes,\n"
+" __global btAabbCL* aabbs,\n"
+" __global float4* concaveSeparatingNormalsOut,\n"
+" __global int* concaveHasSeparatingNormals,\n"
+" __global int4* clippingFacesOut,\n"
+" __global float4* worldVertsA1GPU,\n"
+" __global float4* worldNormalsAGPU,\n"
+" __global float4* worldVertsB1GPU,\n"
+" __global float* dmins,\n"
+" int vertexFaceCapacity,\n"
+" int numConcavePairs\n"
+" )\n"
+"{\n"
+" \n"
+" int i = get_global_id(0);\n"
+" if (i>=numConcavePairs)\n"
+" return;\n"
+" \n"
+" if (!concaveHasSeparatingNormals[i])\n"
+" return;\n"
+" \n"
+" int pairIdx = i;\n"
+" \n"
+" int bodyIndexA = concavePairs[i].x;\n"
+" int bodyIndexB = concavePairs[i].y;\n"
+" \n"
+" int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
+" int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
+" \n"
+" int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
+" int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
+" \n"
+" \n"
+" int numFacesA = convexShapes[shapeIndexA].m_numFaces;\n"
+" int numActualConcaveConvexTests = 0;\n"
+" \n"
+" int f = concavePairs[i].z;\n"
+" \n"
+" bool overlap = false;\n"
+" \n"
+" ConvexPolyhedronCL convexPolyhedronA;\n"
+" \n"
+" //add 3 vertices of the triangle\n"
+" convexPolyhedronA.m_numVertices = 3;\n"
+" convexPolyhedronA.m_vertexOffset = 0;\n"
+" float4 localCenter = make_float4(0.f,0.f,0.f,0.f);\n"
+" \n"
+" btGpuFace face = faces[convexShapes[shapeIndexA].m_faceOffset+f];\n"
+" float4 triMinAabb, triMaxAabb;\n"
+" btAabbCL triAabb;\n"
+" triAabb.m_min = make_float4(1e30f,1e30f,1e30f,0.f);\n"
+" triAabb.m_max = make_float4(-1e30f,-1e30f,-1e30f,0.f);\n"
+" \n"
+" float4 verticesA[3];\n"
+" for (int i=0;i<3;i++)\n"
+" {\n"
+" int index = indices[face.m_indexOffset+i];\n"
+" float4 vert = vertices[convexShapes[shapeIndexA].m_vertexOffset+index];\n"
+" verticesA[i] = vert;\n"
+" localCenter += vert;\n"
+" \n"
+" triAabb.m_min = min(triAabb.m_min,vert);\n"
+" triAabb.m_max = max(triAabb.m_max,vert);\n"
+" \n"
+" }\n"
+" \n"
+" overlap = true;\n"
+" overlap = (triAabb.m_min.x > aabbs[bodyIndexB].m_max.x || triAabb.m_max.x < aabbs[bodyIndexB].m_min.x) ? false : overlap;\n"
+" overlap = (triAabb.m_min.z > aabbs[bodyIndexB].m_max.z || triAabb.m_max.z < aabbs[bodyIndexB].m_min.z) ? false : overlap;\n"
+" overlap = (triAabb.m_min.y > aabbs[bodyIndexB].m_max.y || triAabb.m_max.y < aabbs[bodyIndexB].m_min.y) ? false : overlap;\n"
+" \n"
+" if (overlap)\n"
+" {\n"
+" float dmin = dmins[i];\n"
+" int hasSeparatingAxis=5;\n"
+" float4 sepAxis=make_float4(1,2,3,4);\n"
+" sepAxis = concaveSeparatingNormalsOut[pairIdx];\n"
+" \n"
+" int localCC=0;\n"
+" numActualConcaveConvexTests++;\n"
+" \n"
+" //a triangle has 3 unique edges\n"
+" convexPolyhedronA.m_numUniqueEdges = 3;\n"
+" convexPolyhedronA.m_uniqueEdgesOffset = 0;\n"
+" float4 uniqueEdgesA[3];\n"
+" \n"
+" uniqueEdgesA[0] = (verticesA[1]-verticesA[0]);\n"
+" uniqueEdgesA[1] = (verticesA[2]-verticesA[1]);\n"
+" uniqueEdgesA[2] = (verticesA[0]-verticesA[2]);\n"
+" \n"
+" \n"
+" convexPolyhedronA.m_faceOffset = 0;\n"
+" \n"
+" float4 normal = make_float4(face.m_plane.x,face.m_plane.y,face.m_plane.z,0.f);\n"
+" \n"
+" btGpuFace facesA[TRIANGLE_NUM_CONVEX_FACES];\n"
+" int indicesA[3+3+2+2+2];\n"
+" int curUsedIndices=0;\n"
+" int fidx=0;\n"
+" \n"
+" //front size of triangle\n"
+" {\n"
+" facesA[fidx].m_indexOffset=curUsedIndices;\n"
+" indicesA[0] = 0;\n"
+" indicesA[1] = 1;\n"
+" indicesA[2] = 2;\n"
+" curUsedIndices+=3;\n"
+" float c = face.m_plane.w;\n"
+" facesA[fidx].m_plane.x = normal.x;\n"
+" facesA[fidx].m_plane.y = normal.y;\n"
+" facesA[fidx].m_plane.z = normal.z;\n"
+" facesA[fidx].m_plane.w = c;\n"
+" facesA[fidx].m_numIndices=3;\n"
+" }\n"
+" fidx++;\n"
+" //back size of triangle\n"
+" {\n"
+" facesA[fidx].m_indexOffset=curUsedIndices;\n"
+" indicesA[3]=2;\n"
+" indicesA[4]=1;\n"
+" indicesA[5]=0;\n"
+" curUsedIndices+=3;\n"
+" float c = dot(normal,verticesA[0]);\n"
+" float c1 = -face.m_plane.w;\n"
+" facesA[fidx].m_plane.x = -normal.x;\n"
+" facesA[fidx].m_plane.y = -normal.y;\n"
+" facesA[fidx].m_plane.z = -normal.z;\n"
+" facesA[fidx].m_plane.w = c;\n"
+" facesA[fidx].m_numIndices=3;\n"
+" }\n"
+" fidx++;\n"
+" \n"
+" bool addEdgePlanes = true;\n"
+" if (addEdgePlanes)\n"
+" {\n"
+" int numVertices=3;\n"
+" int prevVertex = numVertices-1;\n"
+" for (int i=0;i<numVertices;i++)\n"
+" {\n"
+" float4 v0 = verticesA[i];\n"
+" float4 v1 = verticesA[prevVertex];\n"
+" \n"
+" float4 edgeNormal = normalize(cross(normal,v1-v0));\n"
+" float c = -dot(edgeNormal,v0);\n"
+" \n"
+" facesA[fidx].m_numIndices = 2;\n"
+" facesA[fidx].m_indexOffset=curUsedIndices;\n"
+" indicesA[curUsedIndices++]=i;\n"
+" indicesA[curUsedIndices++]=prevVertex;\n"
+" \n"
+" facesA[fidx].m_plane.x = edgeNormal.x;\n"
+" facesA[fidx].m_plane.y = edgeNormal.y;\n"
+" facesA[fidx].m_plane.z = edgeNormal.z;\n"
+" facesA[fidx].m_plane.w = c;\n"
+" fidx++;\n"
+" prevVertex = i;\n"
+" }\n"
+" }\n"
+" convexPolyhedronA.m_numFaces = TRIANGLE_NUM_CONVEX_FACES;\n"
+" convexPolyhedronA.m_localCenter = localCenter*(1.f/3.f);\n"
+" \n"
+" \n"
+" float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
+" posA.w = 0.f;\n"
+" float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
+" posB.w = 0.f;\n"
+" \n"
+" float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
+" float4 ornB =rigidBodies[bodyIndexB].m_quat;\n"
+" \n"
+" \n"
+" \n"
+" \n"
+" ///////////////////\n"
+" ///compound shape support\n"
+" \n"
+" if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
+" {\n"
+" int compoundChild = concavePairs[pairIdx].w;\n"
+" int childShapeIndexB = compoundChild;//collidables[collidableIndexB].m_shapeIndex+compoundChild;\n"
+" int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;\n"
+" float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;\n"
+" float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;\n"
+" float4 newPosB = transform(&childPosB,&posB,&ornB);\n"
+" float4 newOrnB = qtMul(ornB,childOrnB);\n"
+" posB = newPosB;\n"
+" ornB = newOrnB;\n"
+" shapeIndexB = collidables[childColIndexB].m_shapeIndex;\n"
+" }\n"
+" //////////////////\n"
+" \n"
+" float4 c0local = convexPolyhedronA.m_localCenter;\n"
+" float4 c0 = transform(&c0local, &posA, &ornA);\n"
+" float4 c1local = convexShapes[shapeIndexB].m_localCenter;\n"
+" float4 c1 = transform(&c1local,&posB,&ornB);\n"
+" const float4 DeltaC2 = c0 - c1;\n"
+" \n"
+" \n"
+" {\n"
+" bool sepEE = findSeparatingAxisEdgeEdgeLocalA( &convexPolyhedronA, &convexShapes[shapeIndexB],\n"
+" posA,ornA,\n"
+" posB,ornB,\n"
+" DeltaC2,\n"
+" verticesA,uniqueEdgesA,facesA,indicesA,\n"
+" vertices,uniqueEdges,faces,indices,\n"
+" &sepAxis,&dmin);\n"
+" \n"
+" if (!sepEE)\n"
+" {\n"
+" hasSeparatingAxis = 0;\n"
+" } else\n"
+" {\n"
+" hasSeparatingAxis = 1;\n"
+" }\n"
+" }\n"
+" \n"
+" \n"
+" if (hasSeparatingAxis)\n"
+" {\n"
+" sepAxis.w = dmin;\n"
+" dmins[i] = dmin;\n"
+" concaveSeparatingNormalsOut[pairIdx]=sepAxis;\n"
+" concaveHasSeparatingNormals[i]=1;\n"
+" \n"
+" float minDist = -1e30f;\n"
+" float maxDist = 0.02f;\n"
+" \n"
+" findClippingFaces(sepAxis,\n"
+" &convexPolyhedronA,\n"
+" &convexShapes[shapeIndexB],\n"
+" posA,ornA,\n"
+" posB,ornB,\n"
+" worldVertsA1GPU,\n"
+" worldNormalsAGPU,\n"
+" worldVertsB1GPU,\n"
+" vertexFaceCapacity,\n"
+" minDist, maxDist,\n"
+" verticesA,\n"
+" facesA,\n"
+" indicesA,\n"
+" vertices,\n"
+" faces,\n"
+" indices,\n"
+" clippingFacesOut, pairIdx);\n"
+" \n"
+" \n"
+" } else\n"
+" { \n"
+" //mark this pair as in-active\n"
+" concavePairs[pairIdx].w = -1;\n"
+" }\n"
+" }\n"
+" else\n"
+" { \n"
+" //mark this pair as in-active\n"
+" concavePairs[pairIdx].w = -1;\n"
+" }\n"
+" \n"
+" concavePairs[i].z = -1;//for the next stage, z is used to determine existing contact points\n"
+"}\n"
+;
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/kernels/satKernels.h b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/kernels/satKernels.h
new file mode 100644
index 0000000000..6f8b0a90db
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/NarrowphaseCollision/kernels/satKernels.h
@@ -0,0 +1,2104 @@
+//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
+static const char* satKernelsCL= \
+"//keep this enum in sync with the CPU version (in btCollidable.h)\n"
+"//written by Erwin Coumans\n"
+"#define SHAPE_CONVEX_HULL 3\n"
+"#define SHAPE_CONCAVE_TRIMESH 5\n"
+"#define TRIANGLE_NUM_CONVEX_FACES 5\n"
+"#define SHAPE_COMPOUND_OF_CONVEX_HULLS 6\n"
+"#define B3_MAX_STACK_DEPTH 256\n"
+"typedef unsigned int u32;\n"
+"///keep this in sync with btCollidable.h\n"
+"typedef struct\n"
+"{\n"
+" union {\n"
+" int m_numChildShapes;\n"
+" int m_bvhIndex;\n"
+" };\n"
+" union\n"
+" {\n"
+" float m_radius;\n"
+" int m_compoundBvhIndex;\n"
+" };\n"
+" \n"
+" int m_shapeType;\n"
+" int m_shapeIndex;\n"
+" \n"
+"} btCollidableGpu;\n"
+"#define MAX_NUM_PARTS_IN_BITS 10\n"
+"///b3QuantizedBvhNode is a compressed aabb node, 16 bytes.\n"
+"///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range).\n"
+"typedef struct\n"
+"{\n"
+" //12 bytes\n"
+" unsigned short int m_quantizedAabbMin[3];\n"
+" unsigned short int m_quantizedAabbMax[3];\n"
+" //4 bytes\n"
+" int m_escapeIndexOrTriangleIndex;\n"
+"} b3QuantizedBvhNode;\n"
+"typedef struct\n"
+"{\n"
+" float4 m_aabbMin;\n"
+" float4 m_aabbMax;\n"
+" float4 m_quantization;\n"
+" int m_numNodes;\n"
+" int m_numSubTrees;\n"
+" int m_nodeOffset;\n"
+" int m_subTreeOffset;\n"
+"} b3BvhInfo;\n"
+"int getTriangleIndex(const b3QuantizedBvhNode* rootNode)\n"
+"{\n"
+" unsigned int x=0;\n"
+" unsigned int y = (~(x&0))<<(31-MAX_NUM_PARTS_IN_BITS);\n"
+" // Get only the lower bits where the triangle index is stored\n"
+" return (rootNode->m_escapeIndexOrTriangleIndex&~(y));\n"
+"}\n"
+"int getTriangleIndexGlobal(__global const b3QuantizedBvhNode* rootNode)\n"
+"{\n"
+" unsigned int x=0;\n"
+" unsigned int y = (~(x&0))<<(31-MAX_NUM_PARTS_IN_BITS);\n"
+" // Get only the lower bits where the triangle index is stored\n"
+" return (rootNode->m_escapeIndexOrTriangleIndex&~(y));\n"
+"}\n"
+"int isLeafNode(const b3QuantizedBvhNode* rootNode)\n"
+"{\n"
+" //skipindex is negative (internal node), triangleindex >=0 (leafnode)\n"
+" return (rootNode->m_escapeIndexOrTriangleIndex >= 0)? 1 : 0;\n"
+"}\n"
+"int isLeafNodeGlobal(__global const b3QuantizedBvhNode* rootNode)\n"
+"{\n"
+" //skipindex is negative (internal node), triangleindex >=0 (leafnode)\n"
+" return (rootNode->m_escapeIndexOrTriangleIndex >= 0)? 1 : 0;\n"
+"}\n"
+" \n"
+"int getEscapeIndex(const b3QuantizedBvhNode* rootNode)\n"
+"{\n"
+" return -rootNode->m_escapeIndexOrTriangleIndex;\n"
+"}\n"
+"int getEscapeIndexGlobal(__global const b3QuantizedBvhNode* rootNode)\n"
+"{\n"
+" return -rootNode->m_escapeIndexOrTriangleIndex;\n"
+"}\n"
+"typedef struct\n"
+"{\n"
+" //12 bytes\n"
+" unsigned short int m_quantizedAabbMin[3];\n"
+" unsigned short int m_quantizedAabbMax[3];\n"
+" //4 bytes, points to the root of the subtree\n"
+" int m_rootNodeIndex;\n"
+" //4 bytes\n"
+" int m_subtreeSize;\n"
+" int m_padding[3];\n"
+"} b3BvhSubtreeInfo;\n"
+"typedef struct\n"
+"{\n"
+" float4 m_childPosition;\n"
+" float4 m_childOrientation;\n"
+" int m_shapeIndex;\n"
+" int m_unused0;\n"
+" int m_unused1;\n"
+" int m_unused2;\n"
+"} btGpuChildShape;\n"
+"typedef struct\n"
+"{\n"
+" float4 m_pos;\n"
+" float4 m_quat;\n"
+" float4 m_linVel;\n"
+" float4 m_angVel;\n"
+" u32 m_collidableIdx;\n"
+" float m_invMass;\n"
+" float m_restituitionCoeff;\n"
+" float m_frictionCoeff;\n"
+"} BodyData;\n"
+"typedef struct \n"
+"{\n"
+" float4 m_localCenter;\n"
+" float4 m_extents;\n"
+" float4 mC;\n"
+" float4 mE;\n"
+" \n"
+" float m_radius;\n"
+" int m_faceOffset;\n"
+" int m_numFaces;\n"
+" int m_numVertices;\n"
+" int m_vertexOffset;\n"
+" int m_uniqueEdgesOffset;\n"
+" int m_numUniqueEdges;\n"
+" int m_unused;\n"
+"} ConvexPolyhedronCL;\n"
+"typedef struct \n"
+"{\n"
+" union\n"
+" {\n"
+" float4 m_min;\n"
+" float m_minElems[4];\n"
+" int m_minIndices[4];\n"
+" };\n"
+" union\n"
+" {\n"
+" float4 m_max;\n"
+" float m_maxElems[4];\n"
+" int m_maxIndices[4];\n"
+" };\n"
+"} btAabbCL;\n"
+"#ifndef B3_AABB_H\n"
+"#define B3_AABB_H\n"
+"#ifndef B3_FLOAT4_H\n"
+"#define B3_FLOAT4_H\n"
+"#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+"#define B3_PLATFORM_DEFINITIONS_H\n"
+"struct MyTest\n"
+"{\n"
+" int bla;\n"
+"};\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
+"#define B3_LARGE_FLOAT 1e18f\n"
+"#define B3_INFINITY 1e18f\n"
+"#define b3Assert(a)\n"
+"#define b3ConstArray(a) __global const a*\n"
+"#define b3AtomicInc atomic_inc\n"
+"#define b3AtomicAdd atomic_add\n"
+"#define b3Fabs fabs\n"
+"#define b3Sqrt native_sqrt\n"
+"#define b3Sin native_sin\n"
+"#define b3Cos native_cos\n"
+"#define B3_STATIC\n"
+"#endif\n"
+"#endif\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+" typedef float4 b3Float4;\n"
+" #define b3Float4ConstArg const b3Float4\n"
+" #define b3MakeFloat4 (float4)\n"
+" float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+" {\n"
+" float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+" float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+" return dot(a1, b1);\n"
+" }\n"
+" b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+" {\n"
+" float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+" float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+" return cross(a1, b1);\n"
+" }\n"
+" #define b3MinFloat4 min\n"
+" #define b3MaxFloat4 max\n"
+" #define b3Normalized(a) normalize(a)\n"
+"#endif \n"
+" \n"
+"inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
+"{\n"
+" if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6) \n"
+" return false;\n"
+" return true;\n"
+"}\n"
+"inline int b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
+"{\n"
+" float maxDot = -B3_INFINITY;\n"
+" int i = 0;\n"
+" int ptIndex = -1;\n"
+" for( i = 0; i < vecLen; i++ )\n"
+" {\n"
+" float dot = b3Dot3F4(vecArray[i],vec);\n"
+" \n"
+" if( dot > maxDot )\n"
+" {\n"
+" maxDot = dot;\n"
+" ptIndex = i;\n"
+" }\n"
+" }\n"
+" b3Assert(ptIndex>=0);\n"
+" if (ptIndex<0)\n"
+" {\n"
+" ptIndex = 0;\n"
+" }\n"
+" *dotOut = maxDot;\n"
+" return ptIndex;\n"
+"}\n"
+"#endif //B3_FLOAT4_H\n"
+"#ifndef B3_MAT3x3_H\n"
+"#define B3_MAT3x3_H\n"
+"#ifndef B3_QUAT_H\n"
+"#define B3_QUAT_H\n"
+"#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"#endif\n"
+"#endif\n"
+"#ifndef B3_FLOAT4_H\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"#endif \n"
+"#endif //B3_FLOAT4_H\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+" typedef float4 b3Quat;\n"
+" #define b3QuatConstArg const b3Quat\n"
+" \n"
+" \n"
+"inline float4 b3FastNormalize4(float4 v)\n"
+"{\n"
+" v = (float4)(v.xyz,0.f);\n"
+" return fast_normalize(v);\n"
+"}\n"
+" \n"
+"inline b3Quat b3QuatMul(b3Quat a, b3Quat b);\n"
+"inline b3Quat b3QuatNormalized(b3QuatConstArg in);\n"
+"inline b3Quat b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec);\n"
+"inline b3Quat b3QuatInvert(b3QuatConstArg q);\n"
+"inline b3Quat b3QuatInverse(b3QuatConstArg q);\n"
+"inline b3Quat b3QuatMul(b3QuatConstArg a, b3QuatConstArg b)\n"
+"{\n"
+" b3Quat ans;\n"
+" ans = b3Cross3( a, b );\n"
+" ans += a.w*b+b.w*a;\n"
+"// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
+" ans.w = a.w*b.w - b3Dot3F4(a, b);\n"
+" return ans;\n"
+"}\n"
+"inline b3Quat b3QuatNormalized(b3QuatConstArg in)\n"
+"{\n"
+" b3Quat q;\n"
+" q=in;\n"
+" //return b3FastNormalize4(in);\n"
+" float len = native_sqrt(dot(q, q));\n"
+" if(len > 0.f)\n"
+" {\n"
+" q *= 1.f / len;\n"
+" }\n"
+" else\n"
+" {\n"
+" q.x = q.y = q.z = 0.f;\n"
+" q.w = 1.f;\n"
+" }\n"
+" return q;\n"
+"}\n"
+"inline float4 b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
+"{\n"
+" b3Quat qInv = b3QuatInvert( q );\n"
+" float4 vcpy = vec;\n"
+" vcpy.w = 0.f;\n"
+" float4 out = b3QuatMul(b3QuatMul(q,vcpy),qInv);\n"
+" return out;\n"
+"}\n"
+"inline b3Quat b3QuatInverse(b3QuatConstArg q)\n"
+"{\n"
+" return (b3Quat)(-q.xyz, q.w);\n"
+"}\n"
+"inline b3Quat b3QuatInvert(b3QuatConstArg q)\n"
+"{\n"
+" return (b3Quat)(-q.xyz, q.w);\n"
+"}\n"
+"inline float4 b3QuatInvRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
+"{\n"
+" return b3QuatRotate( b3QuatInvert( q ), vec );\n"
+"}\n"
+"inline b3Float4 b3TransformPoint(b3Float4ConstArg point, b3Float4ConstArg translation, b3QuatConstArg orientation)\n"
+"{\n"
+" return b3QuatRotate( orientation, point ) + (translation);\n"
+"}\n"
+" \n"
+"#endif \n"
+"#endif //B3_QUAT_H\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"typedef struct\n"
+"{\n"
+" b3Float4 m_row[3];\n"
+"}b3Mat3x3;\n"
+"#define b3Mat3x3ConstArg const b3Mat3x3\n"
+"#define b3GetRow(m,row) (m.m_row[row])\n"
+"inline b3Mat3x3 b3QuatGetRotationMatrix(b3Quat quat)\n"
+"{\n"
+" b3Float4 quat2 = (b3Float4)(quat.x*quat.x, quat.y*quat.y, quat.z*quat.z, 0.f);\n"
+" b3Mat3x3 out;\n"
+" out.m_row[0].x=1-2*quat2.y-2*quat2.z;\n"
+" out.m_row[0].y=2*quat.x*quat.y-2*quat.w*quat.z;\n"
+" out.m_row[0].z=2*quat.x*quat.z+2*quat.w*quat.y;\n"
+" out.m_row[0].w = 0.f;\n"
+" out.m_row[1].x=2*quat.x*quat.y+2*quat.w*quat.z;\n"
+" out.m_row[1].y=1-2*quat2.x-2*quat2.z;\n"
+" out.m_row[1].z=2*quat.y*quat.z-2*quat.w*quat.x;\n"
+" out.m_row[1].w = 0.f;\n"
+" out.m_row[2].x=2*quat.x*quat.z-2*quat.w*quat.y;\n"
+" out.m_row[2].y=2*quat.y*quat.z+2*quat.w*quat.x;\n"
+" out.m_row[2].z=1-2*quat2.x-2*quat2.y;\n"
+" out.m_row[2].w = 0.f;\n"
+" return out;\n"
+"}\n"
+"inline b3Mat3x3 b3AbsoluteMat3x3(b3Mat3x3ConstArg matIn)\n"
+"{\n"
+" b3Mat3x3 out;\n"
+" out.m_row[0] = fabs(matIn.m_row[0]);\n"
+" out.m_row[1] = fabs(matIn.m_row[1]);\n"
+" out.m_row[2] = fabs(matIn.m_row[2]);\n"
+" return out;\n"
+"}\n"
+"__inline\n"
+"b3Mat3x3 mtZero();\n"
+"__inline\n"
+"b3Mat3x3 mtIdentity();\n"
+"__inline\n"
+"b3Mat3x3 mtTranspose(b3Mat3x3 m);\n"
+"__inline\n"
+"b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b);\n"
+"__inline\n"
+"b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b);\n"
+"__inline\n"
+"b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b);\n"
+"__inline\n"
+"b3Mat3x3 mtZero()\n"
+"{\n"
+" b3Mat3x3 m;\n"
+" m.m_row[0] = (b3Float4)(0.f);\n"
+" m.m_row[1] = (b3Float4)(0.f);\n"
+" m.m_row[2] = (b3Float4)(0.f);\n"
+" return m;\n"
+"}\n"
+"__inline\n"
+"b3Mat3x3 mtIdentity()\n"
+"{\n"
+" b3Mat3x3 m;\n"
+" m.m_row[0] = (b3Float4)(1,0,0,0);\n"
+" m.m_row[1] = (b3Float4)(0,1,0,0);\n"
+" m.m_row[2] = (b3Float4)(0,0,1,0);\n"
+" return m;\n"
+"}\n"
+"__inline\n"
+"b3Mat3x3 mtTranspose(b3Mat3x3 m)\n"
+"{\n"
+" b3Mat3x3 out;\n"
+" out.m_row[0] = (b3Float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);\n"
+" out.m_row[1] = (b3Float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);\n"
+" out.m_row[2] = (b3Float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);\n"
+" return out;\n"
+"}\n"
+"__inline\n"
+"b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b)\n"
+"{\n"
+" b3Mat3x3 transB;\n"
+" transB = mtTranspose( b );\n"
+" b3Mat3x3 ans;\n"
+" // why this doesn't run when 0ing in the for{}\n"
+" a.m_row[0].w = 0.f;\n"
+" a.m_row[1].w = 0.f;\n"
+" a.m_row[2].w = 0.f;\n"
+" for(int i=0; i<3; i++)\n"
+" {\n"
+"// a.m_row[i].w = 0.f;\n"
+" ans.m_row[i].x = b3Dot3F4(a.m_row[i],transB.m_row[0]);\n"
+" ans.m_row[i].y = b3Dot3F4(a.m_row[i],transB.m_row[1]);\n"
+" ans.m_row[i].z = b3Dot3F4(a.m_row[i],transB.m_row[2]);\n"
+" ans.m_row[i].w = 0.f;\n"
+" }\n"
+" return ans;\n"
+"}\n"
+"__inline\n"
+"b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b)\n"
+"{\n"
+" b3Float4 ans;\n"
+" ans.x = b3Dot3F4( a.m_row[0], b );\n"
+" ans.y = b3Dot3F4( a.m_row[1], b );\n"
+" ans.z = b3Dot3F4( a.m_row[2], b );\n"
+" ans.w = 0.f;\n"
+" return ans;\n"
+"}\n"
+"__inline\n"
+"b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b)\n"
+"{\n"
+" b3Float4 colx = b3MakeFloat4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
+" b3Float4 coly = b3MakeFloat4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
+" b3Float4 colz = b3MakeFloat4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
+" b3Float4 ans;\n"
+" ans.x = b3Dot3F4( a, colx );\n"
+" ans.y = b3Dot3F4( a, coly );\n"
+" ans.z = b3Dot3F4( a, colz );\n"
+" return ans;\n"
+"}\n"
+"#endif\n"
+"#endif //B3_MAT3x3_H\n"
+"typedef struct b3Aabb b3Aabb_t;\n"
+"struct b3Aabb\n"
+"{\n"
+" union\n"
+" {\n"
+" float m_min[4];\n"
+" b3Float4 m_minVec;\n"
+" int m_minIndices[4];\n"
+" };\n"
+" union\n"
+" {\n"
+" float m_max[4];\n"
+" b3Float4 m_maxVec;\n"
+" int m_signedMaxIndices[4];\n"
+" };\n"
+"};\n"
+"inline void b3TransformAabb2(b3Float4ConstArg localAabbMin,b3Float4ConstArg localAabbMax, float margin,\n"
+" b3Float4ConstArg pos,\n"
+" b3QuatConstArg orn,\n"
+" b3Float4* aabbMinOut,b3Float4* aabbMaxOut)\n"
+"{\n"
+" b3Float4 localHalfExtents = 0.5f*(localAabbMax-localAabbMin);\n"
+" localHalfExtents+=b3MakeFloat4(margin,margin,margin,0.f);\n"
+" b3Float4 localCenter = 0.5f*(localAabbMax+localAabbMin);\n"
+" b3Mat3x3 m;\n"
+" m = b3QuatGetRotationMatrix(orn);\n"
+" b3Mat3x3 abs_b = b3AbsoluteMat3x3(m);\n"
+" b3Float4 center = b3TransformPoint(localCenter,pos,orn);\n"
+" \n"
+" b3Float4 extent = b3MakeFloat4(b3Dot3F4(localHalfExtents,b3GetRow(abs_b,0)),\n"
+" b3Dot3F4(localHalfExtents,b3GetRow(abs_b,1)),\n"
+" b3Dot3F4(localHalfExtents,b3GetRow(abs_b,2)),\n"
+" 0.f);\n"
+" *aabbMinOut = center-extent;\n"
+" *aabbMaxOut = center+extent;\n"
+"}\n"
+"/// conservative test for overlap between two aabbs\n"
+"inline bool b3TestAabbAgainstAabb(b3Float4ConstArg aabbMin1,b3Float4ConstArg aabbMax1,\n"
+" b3Float4ConstArg aabbMin2, b3Float4ConstArg aabbMax2)\n"
+"{\n"
+" bool overlap = true;\n"
+" overlap = (aabbMin1.x > aabbMax2.x || aabbMax1.x < aabbMin2.x) ? false : overlap;\n"
+" overlap = (aabbMin1.z > aabbMax2.z || aabbMax1.z < aabbMin2.z) ? false : overlap;\n"
+" overlap = (aabbMin1.y > aabbMax2.y || aabbMax1.y < aabbMin2.y) ? false : overlap;\n"
+" return overlap;\n"
+"}\n"
+"#endif //B3_AABB_H\n"
+"/*\n"
+"Bullet Continuous Collision Detection and Physics Library\n"
+"Copyright (c) 2003-2013 Erwin Coumans http://bulletphysics.org\n"
+"This software is provided 'as-is', without any express or implied warranty.\n"
+"In no event will the authors be held liable for any damages arising from the use of this software.\n"
+"Permission is granted to anyone to use this software for any purpose,\n"
+"including commercial applications, and to alter it and redistribute it freely,\n"
+"subject to the following restrictions:\n"
+"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.\n"
+"2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
+"3. This notice may not be removed or altered from any source distribution.\n"
+"*/\n"
+"#ifndef B3_INT2_H\n"
+"#define B3_INT2_H\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"#define b3UnsignedInt2 uint2\n"
+"#define b3Int2 int2\n"
+"#define b3MakeInt2 (int2)\n"
+"#endif //__cplusplus\n"
+"#endif\n"
+"typedef struct\n"
+"{\n"
+" float4 m_plane;\n"
+" int m_indexOffset;\n"
+" int m_numIndices;\n"
+"} btGpuFace;\n"
+"#define make_float4 (float4)\n"
+"__inline\n"
+"float4 cross3(float4 a, float4 b)\n"
+"{\n"
+" return cross(a,b);\n"
+" \n"
+"// float4 a1 = make_float4(a.xyz,0.f);\n"
+"// float4 b1 = make_float4(b.xyz,0.f);\n"
+"// return cross(a1,b1);\n"
+"//float4 c = make_float4(a.y*b.z - a.z*b.y,a.z*b.x - a.x*b.z,a.x*b.y - a.y*b.x,0.f);\n"
+" \n"
+" // float4 c = make_float4(a.y*b.z - a.z*b.y,1.f,a.x*b.y - a.y*b.x,0.f);\n"
+" \n"
+" //return c;\n"
+"}\n"
+"__inline\n"
+"float dot3F4(float4 a, float4 b)\n"
+"{\n"
+" float4 a1 = make_float4(a.xyz,0.f);\n"
+" float4 b1 = make_float4(b.xyz,0.f);\n"
+" return dot(a1, b1);\n"
+"}\n"
+"__inline\n"
+"float4 fastNormalize4(float4 v)\n"
+"{\n"
+" v = make_float4(v.xyz,0.f);\n"
+" return fast_normalize(v);\n"
+"}\n"
+"///////////////////////////////////////\n"
+"// Quaternion\n"
+"///////////////////////////////////////\n"
+"typedef float4 Quaternion;\n"
+"__inline\n"
+"Quaternion qtMul(Quaternion a, Quaternion b);\n"
+"__inline\n"
+"Quaternion qtNormalize(Quaternion in);\n"
+"__inline\n"
+"float4 qtRotate(Quaternion q, float4 vec);\n"
+"__inline\n"
+"Quaternion qtInvert(Quaternion q);\n"
+"__inline\n"
+"Quaternion qtMul(Quaternion a, Quaternion b)\n"
+"{\n"
+" Quaternion ans;\n"
+" ans = cross3( a, b );\n"
+" ans += a.w*b+b.w*a;\n"
+"// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
+" ans.w = a.w*b.w - dot3F4(a, b);\n"
+" return ans;\n"
+"}\n"
+"__inline\n"
+"Quaternion qtNormalize(Quaternion in)\n"
+"{\n"
+" return fastNormalize4(in);\n"
+"// in /= length( in );\n"
+"// return in;\n"
+"}\n"
+"__inline\n"
+"float4 qtRotate(Quaternion q, float4 vec)\n"
+"{\n"
+" Quaternion qInv = qtInvert( q );\n"
+" float4 vcpy = vec;\n"
+" vcpy.w = 0.f;\n"
+" float4 out = qtMul(qtMul(q,vcpy),qInv);\n"
+" return out;\n"
+"}\n"
+"__inline\n"
+"Quaternion qtInvert(Quaternion q)\n"
+"{\n"
+" return (Quaternion)(-q.xyz, q.w);\n"
+"}\n"
+"__inline\n"
+"float4 qtInvRotate(const Quaternion q, float4 vec)\n"
+"{\n"
+" return qtRotate( qtInvert( q ), vec );\n"
+"}\n"
+"__inline\n"
+"float4 transform(const float4* p, const float4* translation, const Quaternion* orientation)\n"
+"{\n"
+" return qtRotate( *orientation, *p ) + (*translation);\n"
+"}\n"
+"__inline\n"
+"float4 normalize3(const float4 a)\n"
+"{\n"
+" float4 n = make_float4(a.x, a.y, a.z, 0.f);\n"
+" return fastNormalize4( n );\n"
+"}\n"
+"inline void projectLocal(const ConvexPolyhedronCL* hull, const float4 pos, const float4 orn, \n"
+"const float4* dir, const float4* vertices, float* min, float* max)\n"
+"{\n"
+" min[0] = FLT_MAX;\n"
+" max[0] = -FLT_MAX;\n"
+" int numVerts = hull->m_numVertices;\n"
+" const float4 localDir = qtInvRotate(orn,*dir);\n"
+" float offset = dot(pos,*dir);\n"
+" for(int i=0;i<numVerts;i++)\n"
+" {\n"
+" float dp = dot(vertices[hull->m_vertexOffset+i],localDir);\n"
+" if(dp < min[0]) \n"
+" min[0] = dp;\n"
+" if(dp > max[0]) \n"
+" max[0] = dp;\n"
+" }\n"
+" if(min[0]>max[0])\n"
+" {\n"
+" float tmp = min[0];\n"
+" min[0] = max[0];\n"
+" max[0] = tmp;\n"
+" }\n"
+" min[0] += offset;\n"
+" max[0] += offset;\n"
+"}\n"
+"inline void project(__global const ConvexPolyhedronCL* hull, const float4 pos, const float4 orn, \n"
+"const float4* dir, __global const float4* vertices, float* min, float* max)\n"
+"{\n"
+" min[0] = FLT_MAX;\n"
+" max[0] = -FLT_MAX;\n"
+" int numVerts = hull->m_numVertices;\n"
+" const float4 localDir = qtInvRotate(orn,*dir);\n"
+" float offset = dot(pos,*dir);\n"
+" for(int i=0;i<numVerts;i++)\n"
+" {\n"
+" float dp = dot(vertices[hull->m_vertexOffset+i],localDir);\n"
+" if(dp < min[0]) \n"
+" min[0] = dp;\n"
+" if(dp > max[0]) \n"
+" max[0] = dp;\n"
+" }\n"
+" if(min[0]>max[0])\n"
+" {\n"
+" float tmp = min[0];\n"
+" min[0] = max[0];\n"
+" max[0] = tmp;\n"
+" }\n"
+" min[0] += offset;\n"
+" max[0] += offset;\n"
+"}\n"
+"inline bool TestSepAxisLocalA(const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, \n"
+" const float4 posA,const float4 ornA,\n"
+" const float4 posB,const float4 ornB,\n"
+" float4* sep_axis, const float4* verticesA, __global const float4* verticesB,float* depth)\n"
+"{\n"
+" float Min0,Max0;\n"
+" float Min1,Max1;\n"
+" projectLocal(hullA,posA,ornA,sep_axis,verticesA, &Min0, &Max0);\n"
+" project(hullB,posB,ornB, sep_axis,verticesB, &Min1, &Max1);\n"
+" if(Max0<Min1 || Max1<Min0)\n"
+" return false;\n"
+" float d0 = Max0 - Min1;\n"
+" float d1 = Max1 - Min0;\n"
+" *depth = d0<d1 ? d0:d1;\n"
+" return true;\n"
+"}\n"
+"inline bool IsAlmostZero(const float4 v)\n"
+"{\n"
+" if(fabs(v.x)>1e-6f || fabs(v.y)>1e-6f || fabs(v.z)>1e-6f)\n"
+" return false;\n"
+" return true;\n"
+"}\n"
+"bool findSeparatingAxisLocalA( const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, \n"
+" const float4 posA1,\n"
+" const float4 ornA,\n"
+" const float4 posB1,\n"
+" const float4 ornB,\n"
+" const float4 DeltaC2,\n"
+" \n"
+" const float4* verticesA, \n"
+" const float4* uniqueEdgesA, \n"
+" const btGpuFace* facesA,\n"
+" const int* indicesA,\n"
+" __global const float4* verticesB, \n"
+" __global const float4* uniqueEdgesB, \n"
+" __global const btGpuFace* facesB,\n"
+" __global const int* indicesB,\n"
+" float4* sep,\n"
+" float* dmin)\n"
+"{\n"
+" \n"
+" float4 posA = posA1;\n"
+" posA.w = 0.f;\n"
+" float4 posB = posB1;\n"
+" posB.w = 0.f;\n"
+" int curPlaneTests=0;\n"
+" {\n"
+" int numFacesA = hullA->m_numFaces;\n"
+" // Test normals from hullA\n"
+" for(int i=0;i<numFacesA;i++)\n"
+" {\n"
+" const float4 normal = facesA[hullA->m_faceOffset+i].m_plane;\n"
+" float4 faceANormalWS = qtRotate(ornA,normal);\n"
+" if (dot3F4(DeltaC2,faceANormalWS)<0)\n"
+" faceANormalWS*=-1.f;\n"
+" curPlaneTests++;\n"
+" float d;\n"
+" if(!TestSepAxisLocalA( hullA, hullB, posA,ornA,posB,ornB,&faceANormalWS, verticesA, verticesB,&d))\n"
+" return false;\n"
+" if(d<*dmin)\n"
+" {\n"
+" *dmin = d;\n"
+" *sep = faceANormalWS;\n"
+" }\n"
+" }\n"
+" }\n"
+" if((dot3F4(-DeltaC2,*sep))>0.0f)\n"
+" {\n"
+" *sep = -(*sep);\n"
+" }\n"
+" return true;\n"
+"}\n"
+"bool findSeparatingAxisLocalB( __global const ConvexPolyhedronCL* hullA, const ConvexPolyhedronCL* hullB, \n"
+" const float4 posA1,\n"
+" const float4 ornA,\n"
+" const float4 posB1,\n"
+" const float4 ornB,\n"
+" const float4 DeltaC2,\n"
+" __global const float4* verticesA, \n"
+" __global const float4* uniqueEdgesA, \n"
+" __global const btGpuFace* facesA,\n"
+" __global const int* indicesA,\n"
+" const float4* verticesB,\n"
+" const float4* uniqueEdgesB, \n"
+" const btGpuFace* facesB,\n"
+" const int* indicesB,\n"
+" float4* sep,\n"
+" float* dmin)\n"
+"{\n"
+" float4 posA = posA1;\n"
+" posA.w = 0.f;\n"
+" float4 posB = posB1;\n"
+" posB.w = 0.f;\n"
+" int curPlaneTests=0;\n"
+" {\n"
+" int numFacesA = hullA->m_numFaces;\n"
+" // Test normals from hullA\n"
+" for(int i=0;i<numFacesA;i++)\n"
+" {\n"
+" const float4 normal = facesA[hullA->m_faceOffset+i].m_plane;\n"
+" float4 faceANormalWS = qtRotate(ornA,normal);\n"
+" if (dot3F4(DeltaC2,faceANormalWS)<0)\n"
+" faceANormalWS *= -1.f;\n"
+" curPlaneTests++;\n"
+" float d;\n"
+" if(!TestSepAxisLocalA( hullB, hullA, posB,ornB,posA,ornA, &faceANormalWS, verticesB,verticesA, &d))\n"
+" return false;\n"
+" if(d<*dmin)\n"
+" {\n"
+" *dmin = d;\n"
+" *sep = faceANormalWS;\n"
+" }\n"
+" }\n"
+" }\n"
+" if((dot3F4(-DeltaC2,*sep))>0.0f)\n"
+" {\n"
+" *sep = -(*sep);\n"
+" }\n"
+" return true;\n"
+"}\n"
+"bool findSeparatingAxisEdgeEdgeLocalA( const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, \n"
+" const float4 posA1,\n"
+" const float4 ornA,\n"
+" const float4 posB1,\n"
+" const float4 ornB,\n"
+" const float4 DeltaC2,\n"
+" const float4* verticesA, \n"
+" const float4* uniqueEdgesA, \n"
+" const btGpuFace* facesA,\n"
+" const int* indicesA,\n"
+" __global const float4* verticesB, \n"
+" __global const float4* uniqueEdgesB, \n"
+" __global const btGpuFace* facesB,\n"
+" __global const int* indicesB,\n"
+" float4* sep,\n"
+" float* dmin)\n"
+"{\n"
+" float4 posA = posA1;\n"
+" posA.w = 0.f;\n"
+" float4 posB = posB1;\n"
+" posB.w = 0.f;\n"
+" int curPlaneTests=0;\n"
+" int curEdgeEdge = 0;\n"
+" // Test edges\n"
+" for(int e0=0;e0<hullA->m_numUniqueEdges;e0++)\n"
+" {\n"
+" const float4 edge0 = uniqueEdgesA[hullA->m_uniqueEdgesOffset+e0];\n"
+" float4 edge0World = qtRotate(ornA,edge0);\n"
+" for(int e1=0;e1<hullB->m_numUniqueEdges;e1++)\n"
+" {\n"
+" const float4 edge1 = uniqueEdgesB[hullB->m_uniqueEdgesOffset+e1];\n"
+" float4 edge1World = qtRotate(ornB,edge1);\n"
+" float4 crossje = cross3(edge0World,edge1World);\n"
+" curEdgeEdge++;\n"
+" if(!IsAlmostZero(crossje))\n"
+" {\n"
+" crossje = normalize3(crossje);\n"
+" if (dot3F4(DeltaC2,crossje)<0)\n"
+" crossje *= -1.f;\n"
+" float dist;\n"
+" bool result = true;\n"
+" {\n"
+" float Min0,Max0;\n"
+" float Min1,Max1;\n"
+" projectLocal(hullA,posA,ornA,&crossje,verticesA, &Min0, &Max0);\n"
+" project(hullB,posB,ornB,&crossje,verticesB, &Min1, &Max1);\n"
+" \n"
+" if(Max0<Min1 || Max1<Min0)\n"
+" result = false;\n"
+" \n"
+" float d0 = Max0 - Min1;\n"
+" float d1 = Max1 - Min0;\n"
+" dist = d0<d1 ? d0:d1;\n"
+" result = true;\n"
+" }\n"
+" \n"
+" if(dist<*dmin)\n"
+" {\n"
+" *dmin = dist;\n"
+" *sep = crossje;\n"
+" }\n"
+" }\n"
+" }\n"
+" }\n"
+" \n"
+" if((dot3F4(-DeltaC2,*sep))>0.0f)\n"
+" {\n"
+" *sep = -(*sep);\n"
+" }\n"
+" return true;\n"
+"}\n"
+"inline bool TestSepAxis(__global const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, \n"
+" const float4 posA,const float4 ornA,\n"
+" const float4 posB,const float4 ornB,\n"
+" float4* sep_axis, __global const float4* vertices,float* depth)\n"
+"{\n"
+" float Min0,Max0;\n"
+" float Min1,Max1;\n"
+" project(hullA,posA,ornA,sep_axis,vertices, &Min0, &Max0);\n"
+" project(hullB,posB,ornB, sep_axis,vertices, &Min1, &Max1);\n"
+" if(Max0<Min1 || Max1<Min0)\n"
+" return false;\n"
+" float d0 = Max0 - Min1;\n"
+" float d1 = Max1 - Min0;\n"
+" *depth = d0<d1 ? d0:d1;\n"
+" return true;\n"
+"}\n"
+"bool findSeparatingAxis( __global const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, \n"
+" const float4 posA1,\n"
+" const float4 ornA,\n"
+" const float4 posB1,\n"
+" const float4 ornB,\n"
+" const float4 DeltaC2,\n"
+" __global const float4* vertices, \n"
+" __global const float4* uniqueEdges, \n"
+" __global const btGpuFace* faces,\n"
+" __global const int* indices,\n"
+" float4* sep,\n"
+" float* dmin)\n"
+"{\n"
+" \n"
+" float4 posA = posA1;\n"
+" posA.w = 0.f;\n"
+" float4 posB = posB1;\n"
+" posB.w = 0.f;\n"
+" \n"
+" int curPlaneTests=0;\n"
+" {\n"
+" int numFacesA = hullA->m_numFaces;\n"
+" // Test normals from hullA\n"
+" for(int i=0;i<numFacesA;i++)\n"
+" {\n"
+" const float4 normal = faces[hullA->m_faceOffset+i].m_plane;\n"
+" float4 faceANormalWS = qtRotate(ornA,normal);\n"
+" \n"
+" if (dot3F4(DeltaC2,faceANormalWS)<0)\n"
+" faceANormalWS*=-1.f;\n"
+" \n"
+" curPlaneTests++;\n"
+" \n"
+" float d;\n"
+" if(!TestSepAxis( hullA, hullB, posA,ornA,posB,ornB,&faceANormalWS, vertices,&d))\n"
+" return false;\n"
+" \n"
+" if(d<*dmin)\n"
+" {\n"
+" *dmin = d;\n"
+" *sep = faceANormalWS;\n"
+" }\n"
+" }\n"
+" }\n"
+" if((dot3F4(-DeltaC2,*sep))>0.0f)\n"
+" {\n"
+" *sep = -(*sep);\n"
+" }\n"
+" \n"
+" return true;\n"
+"}\n"
+"bool findSeparatingAxisUnitSphere( __global const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, \n"
+" const float4 posA1,\n"
+" const float4 ornA,\n"
+" const float4 posB1,\n"
+" const float4 ornB,\n"
+" const float4 DeltaC2,\n"
+" __global const float4* vertices,\n"
+" __global const float4* unitSphereDirections,\n"
+" int numUnitSphereDirections,\n"
+" float4* sep,\n"
+" float* dmin)\n"
+"{\n"
+" \n"
+" float4 posA = posA1;\n"
+" posA.w = 0.f;\n"
+" float4 posB = posB1;\n"
+" posB.w = 0.f;\n"
+" int curPlaneTests=0;\n"
+" int curEdgeEdge = 0;\n"
+" // Test unit sphere directions\n"
+" for (int i=0;i<numUnitSphereDirections;i++)\n"
+" {\n"
+" float4 crossje;\n"
+" crossje = unitSphereDirections[i]; \n"
+" if (dot3F4(DeltaC2,crossje)>0)\n"
+" crossje *= -1.f;\n"
+" {\n"
+" float dist;\n"
+" bool result = true;\n"
+" float Min0,Max0;\n"
+" float Min1,Max1;\n"
+" project(hullA,posA,ornA,&crossje,vertices, &Min0, &Max0);\n"
+" project(hullB,posB,ornB,&crossje,vertices, &Min1, &Max1);\n"
+" \n"
+" if(Max0<Min1 || Max1<Min0)\n"
+" return false;\n"
+" \n"
+" float d0 = Max0 - Min1;\n"
+" float d1 = Max1 - Min0;\n"
+" dist = d0<d1 ? d0:d1;\n"
+" result = true;\n"
+" \n"
+" if(dist<*dmin)\n"
+" {\n"
+" *dmin = dist;\n"
+" *sep = crossje;\n"
+" }\n"
+" }\n"
+" }\n"
+" \n"
+" if((dot3F4(-DeltaC2,*sep))>0.0f)\n"
+" {\n"
+" *sep = -(*sep);\n"
+" }\n"
+" return true;\n"
+"}\n"
+"bool findSeparatingAxisEdgeEdge( __global const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, \n"
+" const float4 posA1,\n"
+" const float4 ornA,\n"
+" const float4 posB1,\n"
+" const float4 ornB,\n"
+" const float4 DeltaC2,\n"
+" __global const float4* vertices, \n"
+" __global const float4* uniqueEdges, \n"
+" __global const btGpuFace* faces,\n"
+" __global const int* indices,\n"
+" float4* sep,\n"
+" float* dmin)\n"
+"{\n"
+" \n"
+" float4 posA = posA1;\n"
+" posA.w = 0.f;\n"
+" float4 posB = posB1;\n"
+" posB.w = 0.f;\n"
+" int curPlaneTests=0;\n"
+" int curEdgeEdge = 0;\n"
+" // Test edges\n"
+" for(int e0=0;e0<hullA->m_numUniqueEdges;e0++)\n"
+" {\n"
+" const float4 edge0 = uniqueEdges[hullA->m_uniqueEdgesOffset+e0];\n"
+" float4 edge0World = qtRotate(ornA,edge0);\n"
+" for(int e1=0;e1<hullB->m_numUniqueEdges;e1++)\n"
+" {\n"
+" const float4 edge1 = uniqueEdges[hullB->m_uniqueEdgesOffset+e1];\n"
+" float4 edge1World = qtRotate(ornB,edge1);\n"
+" float4 crossje = cross3(edge0World,edge1World);\n"
+" curEdgeEdge++;\n"
+" if(!IsAlmostZero(crossje))\n"
+" {\n"
+" crossje = normalize3(crossje);\n"
+" if (dot3F4(DeltaC2,crossje)<0)\n"
+" crossje*=-1.f;\n"
+" \n"
+" float dist;\n"
+" bool result = true;\n"
+" {\n"
+" float Min0,Max0;\n"
+" float Min1,Max1;\n"
+" project(hullA,posA,ornA,&crossje,vertices, &Min0, &Max0);\n"
+" project(hullB,posB,ornB,&crossje,vertices, &Min1, &Max1);\n"
+" \n"
+" if(Max0<Min1 || Max1<Min0)\n"
+" return false;\n"
+" \n"
+" float d0 = Max0 - Min1;\n"
+" float d1 = Max1 - Min0;\n"
+" dist = d0<d1 ? d0:d1;\n"
+" result = true;\n"
+" }\n"
+" \n"
+" if(dist<*dmin)\n"
+" {\n"
+" *dmin = dist;\n"
+" *sep = crossje;\n"
+" }\n"
+" }\n"
+" }\n"
+" }\n"
+" \n"
+" if((dot3F4(-DeltaC2,*sep))>0.0f)\n"
+" {\n"
+" *sep = -(*sep);\n"
+" }\n"
+" return true;\n"
+"}\n"
+"// work-in-progress\n"
+"__kernel void processCompoundPairsKernel( __global const int4* gpuCompoundPairs,\n"
+" __global const BodyData* rigidBodies, \n"
+" __global const btCollidableGpu* collidables,\n"
+" __global const ConvexPolyhedronCL* convexShapes, \n"
+" __global const float4* vertices,\n"
+" __global const float4* uniqueEdges,\n"
+" __global const btGpuFace* faces,\n"
+" __global const int* indices,\n"
+" __global btAabbCL* aabbs,\n"
+" __global const btGpuChildShape* gpuChildShapes,\n"
+" __global volatile float4* gpuCompoundSepNormalsOut,\n"
+" __global volatile int* gpuHasCompoundSepNormalsOut,\n"
+" int numCompoundPairs\n"
+" )\n"
+"{\n"
+" int i = get_global_id(0);\n"
+" if (i<numCompoundPairs)\n"
+" {\n"
+" int bodyIndexA = gpuCompoundPairs[i].x;\n"
+" int bodyIndexB = gpuCompoundPairs[i].y;\n"
+" int childShapeIndexA = gpuCompoundPairs[i].z;\n"
+" int childShapeIndexB = gpuCompoundPairs[i].w;\n"
+" \n"
+" int collidableIndexA = -1;\n"
+" int collidableIndexB = -1;\n"
+" \n"
+" float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
+" float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
+" \n"
+" float4 ornB = rigidBodies[bodyIndexB].m_quat;\n"
+" float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
+" \n"
+" if (childShapeIndexA >= 0)\n"
+" {\n"
+" collidableIndexA = gpuChildShapes[childShapeIndexA].m_shapeIndex;\n"
+" float4 childPosA = gpuChildShapes[childShapeIndexA].m_childPosition;\n"
+" float4 childOrnA = gpuChildShapes[childShapeIndexA].m_childOrientation;\n"
+" float4 newPosA = qtRotate(ornA,childPosA)+posA;\n"
+" float4 newOrnA = qtMul(ornA,childOrnA);\n"
+" posA = newPosA;\n"
+" ornA = newOrnA;\n"
+" } else\n"
+" {\n"
+" collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
+" }\n"
+" \n"
+" if (childShapeIndexB>=0)\n"
+" {\n"
+" collidableIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;\n"
+" float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;\n"
+" float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;\n"
+" float4 newPosB = transform(&childPosB,&posB,&ornB);\n"
+" float4 newOrnB = qtMul(ornB,childOrnB);\n"
+" posB = newPosB;\n"
+" ornB = newOrnB;\n"
+" } else\n"
+" {\n"
+" collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx; \n"
+" }\n"
+" \n"
+" gpuHasCompoundSepNormalsOut[i] = 0;\n"
+" \n"
+" int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
+" int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
+" \n"
+" int shapeTypeA = collidables[collidableIndexA].m_shapeType;\n"
+" int shapeTypeB = collidables[collidableIndexB].m_shapeType;\n"
+" \n"
+" if ((shapeTypeA != SHAPE_CONVEX_HULL) || (shapeTypeB != SHAPE_CONVEX_HULL))\n"
+" {\n"
+" return;\n"
+" }\n"
+" int hasSeparatingAxis = 5;\n"
+" \n"
+" int numFacesA = convexShapes[shapeIndexA].m_numFaces;\n"
+" float dmin = FLT_MAX;\n"
+" posA.w = 0.f;\n"
+" posB.w = 0.f;\n"
+" float4 c0local = convexShapes[shapeIndexA].m_localCenter;\n"
+" float4 c0 = transform(&c0local, &posA, &ornA);\n"
+" float4 c1local = convexShapes[shapeIndexB].m_localCenter;\n"
+" float4 c1 = transform(&c1local,&posB,&ornB);\n"
+" const float4 DeltaC2 = c0 - c1;\n"
+" float4 sepNormal = make_float4(1,0,0,0);\n"
+" bool sepA = findSeparatingAxis( &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,posB,ornB,DeltaC2,vertices,uniqueEdges,faces,indices,&sepNormal,&dmin);\n"
+" hasSeparatingAxis = 4;\n"
+" if (!sepA)\n"
+" {\n"
+" hasSeparatingAxis = 0;\n"
+" } else\n"
+" {\n"
+" bool sepB = findSeparatingAxis( &convexShapes[shapeIndexB],&convexShapes[shapeIndexA],posB,ornB,posA,ornA,DeltaC2,vertices,uniqueEdges,faces,indices,&sepNormal,&dmin);\n"
+" if (!sepB)\n"
+" {\n"
+" hasSeparatingAxis = 0;\n"
+" } else//(!sepB)\n"
+" {\n"
+" bool sepEE = findSeparatingAxisEdgeEdge( &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,posB,ornB,DeltaC2,vertices,uniqueEdges,faces,indices,&sepNormal,&dmin);\n"
+" if (sepEE)\n"
+" {\n"
+" gpuCompoundSepNormalsOut[i] = sepNormal;//fastNormalize4(sepNormal);\n"
+" gpuHasCompoundSepNormalsOut[i] = 1;\n"
+" }//sepEE\n"
+" }//(!sepB)\n"
+" }//(!sepA)\n"
+" \n"
+" \n"
+" }\n"
+" \n"
+"}\n"
+"inline b3Float4 MyUnQuantize(const unsigned short* vecIn, b3Float4 quantization, b3Float4 bvhAabbMin)\n"
+"{\n"
+" b3Float4 vecOut;\n"
+" vecOut = b3MakeFloat4(\n"
+" (float)(vecIn[0]) / (quantization.x),\n"
+" (float)(vecIn[1]) / (quantization.y),\n"
+" (float)(vecIn[2]) / (quantization.z),\n"
+" 0.f);\n"
+" vecOut += bvhAabbMin;\n"
+" return vecOut;\n"
+"}\n"
+"inline b3Float4 MyUnQuantizeGlobal(__global const unsigned short* vecIn, b3Float4 quantization, b3Float4 bvhAabbMin)\n"
+"{\n"
+" b3Float4 vecOut;\n"
+" vecOut = b3MakeFloat4(\n"
+" (float)(vecIn[0]) / (quantization.x),\n"
+" (float)(vecIn[1]) / (quantization.y),\n"
+" (float)(vecIn[2]) / (quantization.z),\n"
+" 0.f);\n"
+" vecOut += bvhAabbMin;\n"
+" return vecOut;\n"
+"}\n"
+"// work-in-progress\n"
+"__kernel void findCompoundPairsKernel( __global const int4* pairs, \n"
+" __global const BodyData* rigidBodies, \n"
+" __global const btCollidableGpu* collidables,\n"
+" __global const ConvexPolyhedronCL* convexShapes, \n"
+" __global const float4* vertices,\n"
+" __global const float4* uniqueEdges,\n"
+" __global const btGpuFace* faces,\n"
+" __global const int* indices,\n"
+" __global b3Aabb_t* aabbLocalSpace,\n"
+" __global const btGpuChildShape* gpuChildShapes,\n"
+" __global volatile int4* gpuCompoundPairsOut,\n"
+" __global volatile int* numCompoundPairsOut,\n"
+" __global const b3BvhSubtreeInfo* subtrees,\n"
+" __global const b3QuantizedBvhNode* quantizedNodes,\n"
+" __global const b3BvhInfo* bvhInfos,\n"
+" int numPairs,\n"
+" int maxNumCompoundPairsCapacity\n"
+" )\n"
+"{\n"
+" int i = get_global_id(0);\n"
+" if (i<numPairs)\n"
+" {\n"
+" int bodyIndexA = pairs[i].x;\n"
+" int bodyIndexB = pairs[i].y;\n"
+" int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
+" int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
+" int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
+" int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
+" //once the broadphase avoids static-static pairs, we can remove this test\n"
+" if ((rigidBodies[bodyIndexA].m_invMass==0) &&(rigidBodies[bodyIndexB].m_invMass==0))\n"
+" {\n"
+" return;\n"
+" }\n"
+" if ((collidables[collidableIndexA].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS) &&(collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS))\n"
+" {\n"
+" int bvhA = collidables[collidableIndexA].m_compoundBvhIndex;\n"
+" int bvhB = collidables[collidableIndexB].m_compoundBvhIndex;\n"
+" int numSubTreesA = bvhInfos[bvhA].m_numSubTrees;\n"
+" int subTreesOffsetA = bvhInfos[bvhA].m_subTreeOffset;\n"
+" int subTreesOffsetB = bvhInfos[bvhB].m_subTreeOffset;\n"
+" int numSubTreesB = bvhInfos[bvhB].m_numSubTrees;\n"
+" \n"
+" float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
+" b3Quat ornA = rigidBodies[bodyIndexA].m_quat;\n"
+" b3Quat ornB = rigidBodies[bodyIndexB].m_quat;\n"
+" float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
+" \n"
+" for (int p=0;p<numSubTreesA;p++)\n"
+" {\n"
+" b3BvhSubtreeInfo subtreeA = subtrees[subTreesOffsetA+p];\n"
+" //bvhInfos[bvhA].m_quantization\n"
+" b3Float4 treeAminLocal = MyUnQuantize(subtreeA.m_quantizedAabbMin,bvhInfos[bvhA].m_quantization,bvhInfos[bvhA].m_aabbMin);\n"
+" b3Float4 treeAmaxLocal = MyUnQuantize(subtreeA.m_quantizedAabbMax,bvhInfos[bvhA].m_quantization,bvhInfos[bvhA].m_aabbMin);\n"
+" b3Float4 aabbAMinOut,aabbAMaxOut;\n"
+" float margin=0.f;\n"
+" b3TransformAabb2(treeAminLocal,treeAmaxLocal, margin,posA,ornA,&aabbAMinOut,&aabbAMaxOut);\n"
+" \n"
+" for (int q=0;q<numSubTreesB;q++)\n"
+" {\n"
+" b3BvhSubtreeInfo subtreeB = subtrees[subTreesOffsetB+q];\n"
+" b3Float4 treeBminLocal = MyUnQuantize(subtreeB.m_quantizedAabbMin,bvhInfos[bvhB].m_quantization,bvhInfos[bvhB].m_aabbMin);\n"
+" b3Float4 treeBmaxLocal = MyUnQuantize(subtreeB.m_quantizedAabbMax,bvhInfos[bvhB].m_quantization,bvhInfos[bvhB].m_aabbMin);\n"
+" b3Float4 aabbBMinOut,aabbBMaxOut;\n"
+" float margin=0.f;\n"
+" b3TransformAabb2(treeBminLocal,treeBmaxLocal, margin,posB,ornB,&aabbBMinOut,&aabbBMaxOut);\n"
+" \n"
+" \n"
+" bool aabbOverlap = b3TestAabbAgainstAabb(aabbAMinOut,aabbAMaxOut,aabbBMinOut,aabbBMaxOut);\n"
+" if (aabbOverlap)\n"
+" {\n"
+" \n"
+" int startNodeIndexA = subtreeA.m_rootNodeIndex+bvhInfos[bvhA].m_nodeOffset;\n"
+" int endNodeIndexA = startNodeIndexA+subtreeA.m_subtreeSize;\n"
+" int startNodeIndexB = subtreeB.m_rootNodeIndex+bvhInfos[bvhB].m_nodeOffset;\n"
+" int endNodeIndexB = startNodeIndexB+subtreeB.m_subtreeSize;\n"
+" b3Int2 nodeStack[B3_MAX_STACK_DEPTH];\n"
+" b3Int2 node0;\n"
+" node0.x = startNodeIndexA;\n"
+" node0.y = startNodeIndexB;\n"
+" int maxStackDepth = B3_MAX_STACK_DEPTH;\n"
+" int depth=0;\n"
+" nodeStack[depth++]=node0;\n"
+" do\n"
+" {\n"
+" b3Int2 node = nodeStack[--depth];\n"
+" b3Float4 aMinLocal = MyUnQuantizeGlobal(quantizedNodes[node.x].m_quantizedAabbMin,bvhInfos[bvhA].m_quantization,bvhInfos[bvhA].m_aabbMin);\n"
+" b3Float4 aMaxLocal = MyUnQuantizeGlobal(quantizedNodes[node.x].m_quantizedAabbMax,bvhInfos[bvhA].m_quantization,bvhInfos[bvhA].m_aabbMin);\n"
+" b3Float4 bMinLocal = MyUnQuantizeGlobal(quantizedNodes[node.y].m_quantizedAabbMin,bvhInfos[bvhB].m_quantization,bvhInfos[bvhB].m_aabbMin);\n"
+" b3Float4 bMaxLocal = MyUnQuantizeGlobal(quantizedNodes[node.y].m_quantizedAabbMax,bvhInfos[bvhB].m_quantization,bvhInfos[bvhB].m_aabbMin);\n"
+" float margin=0.f;\n"
+" b3Float4 aabbAMinOut,aabbAMaxOut;\n"
+" b3TransformAabb2(aMinLocal,aMaxLocal, margin,posA,ornA,&aabbAMinOut,&aabbAMaxOut);\n"
+" b3Float4 aabbBMinOut,aabbBMaxOut;\n"
+" b3TransformAabb2(bMinLocal,bMaxLocal, margin,posB,ornB,&aabbBMinOut,&aabbBMaxOut);\n"
+" \n"
+" bool nodeOverlap = b3TestAabbAgainstAabb(aabbAMinOut,aabbAMaxOut,aabbBMinOut,aabbBMaxOut);\n"
+" if (nodeOverlap)\n"
+" {\n"
+" bool isLeafA = isLeafNodeGlobal(&quantizedNodes[node.x]);\n"
+" bool isLeafB = isLeafNodeGlobal(&quantizedNodes[node.y]);\n"
+" bool isInternalA = !isLeafA;\n"
+" bool isInternalB = !isLeafB;\n"
+" //fail, even though it might hit two leaf nodes\n"
+" if (depth+4>maxStackDepth && !(isLeafA && isLeafB))\n"
+" {\n"
+" //printf(\"Error: traversal exceeded maxStackDepth\");\n"
+" continue;\n"
+" }\n"
+" if(isInternalA)\n"
+" {\n"
+" int nodeAleftChild = node.x+1;\n"
+" bool isNodeALeftChildLeaf = isLeafNodeGlobal(&quantizedNodes[node.x+1]);\n"
+" int nodeArightChild = isNodeALeftChildLeaf? node.x+2 : node.x+1 + getEscapeIndexGlobal(&quantizedNodes[node.x+1]);\n"
+" if(isInternalB)\n"
+" { \n"
+" int nodeBleftChild = node.y+1;\n"
+" bool isNodeBLeftChildLeaf = isLeafNodeGlobal(&quantizedNodes[node.y+1]);\n"
+" int nodeBrightChild = isNodeBLeftChildLeaf? node.y+2 : node.y+1 + getEscapeIndexGlobal(&quantizedNodes[node.y+1]);\n"
+" nodeStack[depth++] = b3MakeInt2(nodeAleftChild, nodeBleftChild);\n"
+" nodeStack[depth++] = b3MakeInt2(nodeArightChild, nodeBleftChild);\n"
+" nodeStack[depth++] = b3MakeInt2(nodeAleftChild, nodeBrightChild);\n"
+" nodeStack[depth++] = b3MakeInt2(nodeArightChild, nodeBrightChild);\n"
+" }\n"
+" else\n"
+" {\n"
+" nodeStack[depth++] = b3MakeInt2(nodeAleftChild,node.y);\n"
+" nodeStack[depth++] = b3MakeInt2(nodeArightChild,node.y);\n"
+" }\n"
+" }\n"
+" else\n"
+" {\n"
+" if(isInternalB)\n"
+" {\n"
+" int nodeBleftChild = node.y+1;\n"
+" bool isNodeBLeftChildLeaf = isLeafNodeGlobal(&quantizedNodes[node.y+1]);\n"
+" int nodeBrightChild = isNodeBLeftChildLeaf? node.y+2 : node.y+1 + getEscapeIndexGlobal(&quantizedNodes[node.y+1]);\n"
+" nodeStack[depth++] = b3MakeInt2(node.x,nodeBleftChild);\n"
+" nodeStack[depth++] = b3MakeInt2(node.x,nodeBrightChild);\n"
+" }\n"
+" else\n"
+" {\n"
+" int compoundPairIdx = atomic_inc(numCompoundPairsOut);\n"
+" if (compoundPairIdx<maxNumCompoundPairsCapacity)\n"
+" {\n"
+" int childShapeIndexA = getTriangleIndexGlobal(&quantizedNodes[node.x]);\n"
+" int childShapeIndexB = getTriangleIndexGlobal(&quantizedNodes[node.y]);\n"
+" gpuCompoundPairsOut[compoundPairIdx] = (int4)(bodyIndexA,bodyIndexB,childShapeIndexA,childShapeIndexB);\n"
+" }\n"
+" }\n"
+" }\n"
+" }\n"
+" } while (depth);\n"
+" }\n"
+" }\n"
+" }\n"
+" \n"
+" return;\n"
+" }\n"
+" if ((collidables[collidableIndexA].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS) ||(collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS))\n"
+" {\n"
+" if (collidables[collidableIndexA].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS) \n"
+" {\n"
+" int numChildrenA = collidables[collidableIndexA].m_numChildShapes;\n"
+" for (int c=0;c<numChildrenA;c++)\n"
+" {\n"
+" int childShapeIndexA = collidables[collidableIndexA].m_shapeIndex+c;\n"
+" int childColIndexA = gpuChildShapes[childShapeIndexA].m_shapeIndex;\n"
+" float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
+" float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
+" float4 childPosA = gpuChildShapes[childShapeIndexA].m_childPosition;\n"
+" float4 childOrnA = gpuChildShapes[childShapeIndexA].m_childOrientation;\n"
+" float4 newPosA = qtRotate(ornA,childPosA)+posA;\n"
+" float4 newOrnA = qtMul(ornA,childOrnA);\n"
+" int shapeIndexA = collidables[childColIndexA].m_shapeIndex;\n"
+" b3Aabb_t aabbAlocal = aabbLocalSpace[shapeIndexA];\n"
+" float margin = 0.f;\n"
+" \n"
+" b3Float4 aabbAMinWS;\n"
+" b3Float4 aabbAMaxWS;\n"
+" \n"
+" b3TransformAabb2(aabbAlocal.m_minVec,aabbAlocal.m_maxVec,margin,\n"
+" newPosA,\n"
+" newOrnA,\n"
+" &aabbAMinWS,&aabbAMaxWS);\n"
+" \n"
+" \n"
+" if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
+" {\n"
+" int numChildrenB = collidables[collidableIndexB].m_numChildShapes;\n"
+" for (int b=0;b<numChildrenB;b++)\n"
+" {\n"
+" int childShapeIndexB = collidables[collidableIndexB].m_shapeIndex+b;\n"
+" int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;\n"
+" float4 ornB = rigidBodies[bodyIndexB].m_quat;\n"
+" float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
+" float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;\n"
+" float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;\n"
+" float4 newPosB = transform(&childPosB,&posB,&ornB);\n"
+" float4 newOrnB = qtMul(ornB,childOrnB);\n"
+" int shapeIndexB = collidables[childColIndexB].m_shapeIndex;\n"
+" b3Aabb_t aabbBlocal = aabbLocalSpace[shapeIndexB];\n"
+" \n"
+" b3Float4 aabbBMinWS;\n"
+" b3Float4 aabbBMaxWS;\n"
+" \n"
+" b3TransformAabb2(aabbBlocal.m_minVec,aabbBlocal.m_maxVec,margin,\n"
+" newPosB,\n"
+" newOrnB,\n"
+" &aabbBMinWS,&aabbBMaxWS);\n"
+" \n"
+" \n"
+" \n"
+" bool aabbOverlap = b3TestAabbAgainstAabb(aabbAMinWS,aabbAMaxWS,aabbBMinWS,aabbBMaxWS);\n"
+" if (aabbOverlap)\n"
+" {\n"
+" int numFacesA = convexShapes[shapeIndexA].m_numFaces;\n"
+" float dmin = FLT_MAX;\n"
+" float4 posA = newPosA;\n"
+" posA.w = 0.f;\n"
+" float4 posB = newPosB;\n"
+" posB.w = 0.f;\n"
+" float4 c0local = convexShapes[shapeIndexA].m_localCenter;\n"
+" float4 ornA = newOrnA;\n"
+" float4 c0 = transform(&c0local, &posA, &ornA);\n"
+" float4 c1local = convexShapes[shapeIndexB].m_localCenter;\n"
+" float4 ornB =newOrnB;\n"
+" float4 c1 = transform(&c1local,&posB,&ornB);\n"
+" const float4 DeltaC2 = c0 - c1;\n"
+" {//\n"
+" int compoundPairIdx = atomic_inc(numCompoundPairsOut);\n"
+" if (compoundPairIdx<maxNumCompoundPairsCapacity)\n"
+" {\n"
+" gpuCompoundPairsOut[compoundPairIdx] = (int4)(bodyIndexA,bodyIndexB,childShapeIndexA,childShapeIndexB);\n"
+" }\n"
+" }//\n"
+" }//fi(1)\n"
+" } //for (int b=0\n"
+" }//if (collidables[collidableIndexB].\n"
+" else//if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
+" {\n"
+" if (1)\n"
+" {\n"
+" int numFacesA = convexShapes[shapeIndexA].m_numFaces;\n"
+" float dmin = FLT_MAX;\n"
+" float4 posA = newPosA;\n"
+" posA.w = 0.f;\n"
+" float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
+" posB.w = 0.f;\n"
+" float4 c0local = convexShapes[shapeIndexA].m_localCenter;\n"
+" float4 ornA = newOrnA;\n"
+" float4 c0 = transform(&c0local, &posA, &ornA);\n"
+" float4 c1local = convexShapes[shapeIndexB].m_localCenter;\n"
+" float4 ornB = rigidBodies[bodyIndexB].m_quat;\n"
+" float4 c1 = transform(&c1local,&posB,&ornB);\n"
+" const float4 DeltaC2 = c0 - c1;\n"
+" {\n"
+" int compoundPairIdx = atomic_inc(numCompoundPairsOut);\n"
+" if (compoundPairIdx<maxNumCompoundPairsCapacity)\n"
+" {\n"
+" gpuCompoundPairsOut[compoundPairIdx] = (int4)(bodyIndexA,bodyIndexB,childShapeIndexA,-1);\n"
+" }//if (compoundPairIdx<maxNumCompoundPairsCapacity)\n"
+" }//\n"
+" }//fi (1)\n"
+" }//if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
+" }//for (int b=0;b<numChildrenB;b++) \n"
+" return;\n"
+" }//if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
+" if ((collidables[collidableIndexA].m_shapeType!=SHAPE_CONCAVE_TRIMESH) \n"
+" && (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS))\n"
+" {\n"
+" int numChildrenB = collidables[collidableIndexB].m_numChildShapes;\n"
+" for (int b=0;b<numChildrenB;b++)\n"
+" {\n"
+" int childShapeIndexB = collidables[collidableIndexB].m_shapeIndex+b;\n"
+" int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;\n"
+" float4 ornB = rigidBodies[bodyIndexB].m_quat;\n"
+" float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
+" float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;\n"
+" float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;\n"
+" float4 newPosB = qtRotate(ornB,childPosB)+posB;\n"
+" float4 newOrnB = qtMul(ornB,childOrnB);\n"
+" int shapeIndexB = collidables[childColIndexB].m_shapeIndex;\n"
+" //////////////////////////////////////\n"
+" if (1)\n"
+" {\n"
+" int numFacesA = convexShapes[shapeIndexA].m_numFaces;\n"
+" float dmin = FLT_MAX;\n"
+" float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
+" posA.w = 0.f;\n"
+" float4 posB = newPosB;\n"
+" posB.w = 0.f;\n"
+" float4 c0local = convexShapes[shapeIndexA].m_localCenter;\n"
+" float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
+" float4 c0 = transform(&c0local, &posA, &ornA);\n"
+" float4 c1local = convexShapes[shapeIndexB].m_localCenter;\n"
+" float4 ornB =newOrnB;\n"
+" float4 c1 = transform(&c1local,&posB,&ornB);\n"
+" const float4 DeltaC2 = c0 - c1;\n"
+" {//\n"
+" int compoundPairIdx = atomic_inc(numCompoundPairsOut);\n"
+" if (compoundPairIdx<maxNumCompoundPairsCapacity)\n"
+" {\n"
+" gpuCompoundPairsOut[compoundPairIdx] = (int4)(bodyIndexA,bodyIndexB,-1,childShapeIndexB);\n"
+" }//fi (compoundPairIdx<maxNumCompoundPairsCapacity)\n"
+" }//\n"
+" }//fi (1) \n"
+" }//for (int b=0;b<numChildrenB;b++)\n"
+" return;\n"
+" }//if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
+" return;\n"
+" }//fi ((collidables[collidableIndexA].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS) ||(collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS))\n"
+" }//i<numPairs\n"
+"}\n"
+"// work-in-progress\n"
+"__kernel void findSeparatingAxisKernel( __global const int4* pairs, \n"
+" __global const BodyData* rigidBodies, \n"
+" __global const btCollidableGpu* collidables,\n"
+" __global const ConvexPolyhedronCL* convexShapes, \n"
+" __global const float4* vertices,\n"
+" __global const float4* uniqueEdges,\n"
+" __global const btGpuFace* faces,\n"
+" __global const int* indices,\n"
+" __global btAabbCL* aabbs,\n"
+" __global volatile float4* separatingNormals,\n"
+" __global volatile int* hasSeparatingAxis,\n"
+" int numPairs\n"
+" )\n"
+"{\n"
+" int i = get_global_id(0);\n"
+" \n"
+" if (i<numPairs)\n"
+" {\n"
+" \n"
+" int bodyIndexA = pairs[i].x;\n"
+" int bodyIndexB = pairs[i].y;\n"
+" int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
+" int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
+" \n"
+" int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
+" int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
+" \n"
+" \n"
+" //once the broadphase avoids static-static pairs, we can remove this test\n"
+" if ((rigidBodies[bodyIndexA].m_invMass==0) &&(rigidBodies[bodyIndexB].m_invMass==0))\n"
+" {\n"
+" hasSeparatingAxis[i] = 0;\n"
+" return;\n"
+" }\n"
+" \n"
+" if ((collidables[collidableIndexA].m_shapeType!=SHAPE_CONVEX_HULL) ||(collidables[collidableIndexB].m_shapeType!=SHAPE_CONVEX_HULL))\n"
+" {\n"
+" hasSeparatingAxis[i] = 0;\n"
+" return;\n"
+" }\n"
+" \n"
+" if ((collidables[collidableIndexA].m_shapeType==SHAPE_CONCAVE_TRIMESH))\n"
+" {\n"
+" hasSeparatingAxis[i] = 0;\n"
+" return;\n"
+" }\n"
+" int numFacesA = convexShapes[shapeIndexA].m_numFaces;\n"
+" float dmin = FLT_MAX;\n"
+" float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
+" posA.w = 0.f;\n"
+" float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
+" posB.w = 0.f;\n"
+" float4 c0local = convexShapes[shapeIndexA].m_localCenter;\n"
+" float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
+" float4 c0 = transform(&c0local, &posA, &ornA);\n"
+" float4 c1local = convexShapes[shapeIndexB].m_localCenter;\n"
+" float4 ornB =rigidBodies[bodyIndexB].m_quat;\n"
+" float4 c1 = transform(&c1local,&posB,&ornB);\n"
+" const float4 DeltaC2 = c0 - c1;\n"
+" float4 sepNormal;\n"
+" \n"
+" bool sepA = findSeparatingAxis( &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,\n"
+" posB,ornB,\n"
+" DeltaC2,\n"
+" vertices,uniqueEdges,faces,\n"
+" indices,&sepNormal,&dmin);\n"
+" hasSeparatingAxis[i] = 4;\n"
+" if (!sepA)\n"
+" {\n"
+" hasSeparatingAxis[i] = 0;\n"
+" } else\n"
+" {\n"
+" bool sepB = findSeparatingAxis( &convexShapes[shapeIndexB],&convexShapes[shapeIndexA],posB,ornB,\n"
+" posA,ornA,\n"
+" DeltaC2,\n"
+" vertices,uniqueEdges,faces,\n"
+" indices,&sepNormal,&dmin);\n"
+" if (!sepB)\n"
+" {\n"
+" hasSeparatingAxis[i] = 0;\n"
+" } else\n"
+" {\n"
+" bool sepEE = findSeparatingAxisEdgeEdge( &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,\n"
+" posB,ornB,\n"
+" DeltaC2,\n"
+" vertices,uniqueEdges,faces,\n"
+" indices,&sepNormal,&dmin);\n"
+" if (!sepEE)\n"
+" {\n"
+" hasSeparatingAxis[i] = 0;\n"
+" } else\n"
+" {\n"
+" hasSeparatingAxis[i] = 1;\n"
+" separatingNormals[i] = sepNormal;\n"
+" }\n"
+" }\n"
+" }\n"
+" \n"
+" }\n"
+"}\n"
+"__kernel void findSeparatingAxisVertexFaceKernel( __global const int4* pairs, \n"
+" __global const BodyData* rigidBodies, \n"
+" __global const btCollidableGpu* collidables,\n"
+" __global const ConvexPolyhedronCL* convexShapes, \n"
+" __global const float4* vertices,\n"
+" __global const float4* uniqueEdges,\n"
+" __global const btGpuFace* faces,\n"
+" __global const int* indices,\n"
+" __global btAabbCL* aabbs,\n"
+" __global volatile float4* separatingNormals,\n"
+" __global volatile int* hasSeparatingAxis,\n"
+" __global float* dmins,\n"
+" int numPairs\n"
+" )\n"
+"{\n"
+" int i = get_global_id(0);\n"
+" \n"
+" if (i<numPairs)\n"
+" {\n"
+" \n"
+" int bodyIndexA = pairs[i].x;\n"
+" int bodyIndexB = pairs[i].y;\n"
+" int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
+" int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
+" \n"
+" int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
+" int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
+" \n"
+" hasSeparatingAxis[i] = 0; \n"
+" \n"
+" //once the broadphase avoids static-static pairs, we can remove this test\n"
+" if ((rigidBodies[bodyIndexA].m_invMass==0) &&(rigidBodies[bodyIndexB].m_invMass==0))\n"
+" {\n"
+" return;\n"
+" }\n"
+" \n"
+" if ((collidables[collidableIndexA].m_shapeType!=SHAPE_CONVEX_HULL) ||(collidables[collidableIndexB].m_shapeType!=SHAPE_CONVEX_HULL))\n"
+" {\n"
+" return;\n"
+" }\n"
+" \n"
+" int numFacesA = convexShapes[shapeIndexA].m_numFaces;\n"
+" float dmin = FLT_MAX;\n"
+" dmins[i] = dmin;\n"
+" \n"
+" float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
+" posA.w = 0.f;\n"
+" float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
+" posB.w = 0.f;\n"
+" float4 c0local = convexShapes[shapeIndexA].m_localCenter;\n"
+" float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
+" float4 c0 = transform(&c0local, &posA, &ornA);\n"
+" float4 c1local = convexShapes[shapeIndexB].m_localCenter;\n"
+" float4 ornB =rigidBodies[bodyIndexB].m_quat;\n"
+" float4 c1 = transform(&c1local,&posB,&ornB);\n"
+" const float4 DeltaC2 = c0 - c1;\n"
+" float4 sepNormal;\n"
+" \n"
+" bool sepA = findSeparatingAxis( &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,\n"
+" posB,ornB,\n"
+" DeltaC2,\n"
+" vertices,uniqueEdges,faces,\n"
+" indices,&sepNormal,&dmin);\n"
+" hasSeparatingAxis[i] = 4;\n"
+" if (!sepA)\n"
+" {\n"
+" hasSeparatingAxis[i] = 0;\n"
+" } else\n"
+" {\n"
+" bool sepB = findSeparatingAxis( &convexShapes[shapeIndexB],&convexShapes[shapeIndexA],posB,ornB,\n"
+" posA,ornA,\n"
+" DeltaC2,\n"
+" vertices,uniqueEdges,faces,\n"
+" indices,&sepNormal,&dmin);\n"
+" if (sepB)\n"
+" {\n"
+" dmins[i] = dmin;\n"
+" hasSeparatingAxis[i] = 1;\n"
+" separatingNormals[i] = sepNormal;\n"
+" }\n"
+" }\n"
+" \n"
+" }\n"
+"}\n"
+"__kernel void findSeparatingAxisEdgeEdgeKernel( __global const int4* pairs, \n"
+" __global const BodyData* rigidBodies, \n"
+" __global const btCollidableGpu* collidables,\n"
+" __global const ConvexPolyhedronCL* convexShapes, \n"
+" __global const float4* vertices,\n"
+" __global const float4* uniqueEdges,\n"
+" __global const btGpuFace* faces,\n"
+" __global const int* indices,\n"
+" __global btAabbCL* aabbs,\n"
+" __global float4* separatingNormals,\n"
+" __global int* hasSeparatingAxis,\n"
+" __global float* dmins,\n"
+" __global const float4* unitSphereDirections,\n"
+" int numUnitSphereDirections,\n"
+" int numPairs\n"
+" )\n"
+"{\n"
+" int i = get_global_id(0);\n"
+" \n"
+" if (i<numPairs)\n"
+" {\n"
+" if (hasSeparatingAxis[i])\n"
+" {\n"
+" \n"
+" int bodyIndexA = pairs[i].x;\n"
+" int bodyIndexB = pairs[i].y;\n"
+" \n"
+" int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
+" int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
+" \n"
+" int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
+" int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
+" \n"
+" \n"
+" int numFacesA = convexShapes[shapeIndexA].m_numFaces;\n"
+" \n"
+" float dmin = dmins[i];\n"
+" \n"
+" float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
+" posA.w = 0.f;\n"
+" float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
+" posB.w = 0.f;\n"
+" float4 c0local = convexShapes[shapeIndexA].m_localCenter;\n"
+" float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
+" float4 c0 = transform(&c0local, &posA, &ornA);\n"
+" float4 c1local = convexShapes[shapeIndexB].m_localCenter;\n"
+" float4 ornB =rigidBodies[bodyIndexB].m_quat;\n"
+" float4 c1 = transform(&c1local,&posB,&ornB);\n"
+" const float4 DeltaC2 = c0 - c1;\n"
+" float4 sepNormal = separatingNormals[i];\n"
+" \n"
+" \n"
+" \n"
+" bool sepEE = false;\n"
+" int numEdgeEdgeDirections = convexShapes[shapeIndexA].m_numUniqueEdges*convexShapes[shapeIndexB].m_numUniqueEdges;\n"
+" if (numEdgeEdgeDirections<=numUnitSphereDirections)\n"
+" {\n"
+" sepEE = findSeparatingAxisEdgeEdge( &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,\n"
+" posB,ornB,\n"
+" DeltaC2,\n"
+" vertices,uniqueEdges,faces,\n"
+" indices,&sepNormal,&dmin);\n"
+" \n"
+" if (!sepEE)\n"
+" {\n"
+" hasSeparatingAxis[i] = 0;\n"
+" } else\n"
+" {\n"
+" hasSeparatingAxis[i] = 1;\n"
+" separatingNormals[i] = sepNormal;\n"
+" }\n"
+" }\n"
+" /*\n"
+" ///else case is a separate kernel, to make Mac OSX OpenCL compiler happy\n"
+" else\n"
+" {\n"
+" sepEE = findSeparatingAxisUnitSphere(&convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,\n"
+" posB,ornB,\n"
+" DeltaC2,\n"
+" vertices,unitSphereDirections,numUnitSphereDirections,\n"
+" &sepNormal,&dmin);\n"
+" if (!sepEE)\n"
+" {\n"
+" hasSeparatingAxis[i] = 0;\n"
+" } else\n"
+" {\n"
+" hasSeparatingAxis[i] = 1;\n"
+" separatingNormals[i] = sepNormal;\n"
+" }\n"
+" }\n"
+" */\n"
+" } //if (hasSeparatingAxis[i])\n"
+" }//(i<numPairs)\n"
+"}\n"
+"inline int findClippingFaces(const float4 separatingNormal,\n"
+" const ConvexPolyhedronCL* hullA, \n"
+" __global const ConvexPolyhedronCL* hullB,\n"
+" const float4 posA, const Quaternion ornA,const float4 posB, const Quaternion ornB,\n"
+" __global float4* worldVertsA1,\n"
+" __global float4* worldNormalsA1,\n"
+" __global float4* worldVertsB1,\n"
+" int capacityWorldVerts,\n"
+" const float minDist, float maxDist,\n"
+" const float4* verticesA,\n"
+" const btGpuFace* facesA,\n"
+" const int* indicesA,\n"
+" __global const float4* verticesB,\n"
+" __global const btGpuFace* facesB,\n"
+" __global const int* indicesB,\n"
+" __global int4* clippingFaces, int pairIndex)\n"
+"{\n"
+" int numContactsOut = 0;\n"
+" int numWorldVertsB1= 0;\n"
+" \n"
+" \n"
+" int closestFaceB=0;\n"
+" float dmax = -FLT_MAX;\n"
+" \n"
+" {\n"
+" for(int face=0;face<hullB->m_numFaces;face++)\n"
+" {\n"
+" const float4 Normal = make_float4(facesB[hullB->m_faceOffset+face].m_plane.x,\n"
+" facesB[hullB->m_faceOffset+face].m_plane.y, facesB[hullB->m_faceOffset+face].m_plane.z,0.f);\n"
+" const float4 WorldNormal = qtRotate(ornB, Normal);\n"
+" float d = dot3F4(WorldNormal,separatingNormal);\n"
+" if (d > dmax)\n"
+" {\n"
+" dmax = d;\n"
+" closestFaceB = face;\n"
+" }\n"
+" }\n"
+" }\n"
+" \n"
+" {\n"
+" const btGpuFace polyB = facesB[hullB->m_faceOffset+closestFaceB];\n"
+" int numVertices = polyB.m_numIndices;\n"
+" if (numVertices>capacityWorldVerts)\n"
+" numVertices = capacityWorldVerts;\n"
+" \n"
+" for(int e0=0;e0<numVertices;e0++)\n"
+" {\n"
+" if (e0<capacityWorldVerts)\n"
+" {\n"
+" const float4 b = verticesB[hullB->m_vertexOffset+indicesB[polyB.m_indexOffset+e0]];\n"
+" worldVertsB1[pairIndex*capacityWorldVerts+numWorldVertsB1++] = transform(&b,&posB,&ornB);\n"
+" }\n"
+" }\n"
+" }\n"
+" \n"
+" int closestFaceA=0;\n"
+" {\n"
+" float dmin = FLT_MAX;\n"
+" for(int face=0;face<hullA->m_numFaces;face++)\n"
+" {\n"
+" const float4 Normal = make_float4(\n"
+" facesA[hullA->m_faceOffset+face].m_plane.x,\n"
+" facesA[hullA->m_faceOffset+face].m_plane.y,\n"
+" facesA[hullA->m_faceOffset+face].m_plane.z,\n"
+" 0.f);\n"
+" const float4 faceANormalWS = qtRotate(ornA,Normal);\n"
+" \n"
+" float d = dot3F4(faceANormalWS,separatingNormal);\n"
+" if (d < dmin)\n"
+" {\n"
+" dmin = d;\n"
+" closestFaceA = face;\n"
+" worldNormalsA1[pairIndex] = faceANormalWS;\n"
+" }\n"
+" }\n"
+" }\n"
+" \n"
+" int numVerticesA = facesA[hullA->m_faceOffset+closestFaceA].m_numIndices;\n"
+" if (numVerticesA>capacityWorldVerts)\n"
+" numVerticesA = capacityWorldVerts;\n"
+" \n"
+" for(int e0=0;e0<numVerticesA;e0++)\n"
+" {\n"
+" if (e0<capacityWorldVerts)\n"
+" {\n"
+" const float4 a = verticesA[hullA->m_vertexOffset+indicesA[facesA[hullA->m_faceOffset+closestFaceA].m_indexOffset+e0]];\n"
+" worldVertsA1[pairIndex*capacityWorldVerts+e0] = transform(&a, &posA,&ornA);\n"
+" }\n"
+" }\n"
+" \n"
+" clippingFaces[pairIndex].x = closestFaceA;\n"
+" clippingFaces[pairIndex].y = closestFaceB;\n"
+" clippingFaces[pairIndex].z = numVerticesA;\n"
+" clippingFaces[pairIndex].w = numWorldVertsB1;\n"
+" \n"
+" \n"
+" return numContactsOut;\n"
+"}\n"
+"// work-in-progress\n"
+"__kernel void findConcaveSeparatingAxisKernel( __global int4* concavePairs,\n"
+" __global const BodyData* rigidBodies,\n"
+" __global const btCollidableGpu* collidables,\n"
+" __global const ConvexPolyhedronCL* convexShapes, \n"
+" __global const float4* vertices,\n"
+" __global const float4* uniqueEdges,\n"
+" __global const btGpuFace* faces,\n"
+" __global const int* indices,\n"
+" __global const btGpuChildShape* gpuChildShapes,\n"
+" __global btAabbCL* aabbs,\n"
+" __global float4* concaveSeparatingNormalsOut,\n"
+" __global int* concaveHasSeparatingNormals,\n"
+" __global int4* clippingFacesOut,\n"
+" __global float4* worldVertsA1GPU,\n"
+" __global float4* worldNormalsAGPU,\n"
+" __global float4* worldVertsB1GPU,\n"
+" int vertexFaceCapacity,\n"
+" int numConcavePairs\n"
+" )\n"
+"{\n"
+" int i = get_global_id(0);\n"
+" if (i>=numConcavePairs)\n"
+" return;\n"
+" concaveHasSeparatingNormals[i] = 0;\n"
+" int pairIdx = i;\n"
+" int bodyIndexA = concavePairs[i].x;\n"
+" int bodyIndexB = concavePairs[i].y;\n"
+" int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
+" int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
+" int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
+" int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
+" if (collidables[collidableIndexB].m_shapeType!=SHAPE_CONVEX_HULL&&\n"
+" collidables[collidableIndexB].m_shapeType!=SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
+" {\n"
+" concavePairs[pairIdx].w = -1;\n"
+" return;\n"
+" }\n"
+" int numFacesA = convexShapes[shapeIndexA].m_numFaces;\n"
+" int numActualConcaveConvexTests = 0;\n"
+" \n"
+" int f = concavePairs[i].z;\n"
+" \n"
+" bool overlap = false;\n"
+" \n"
+" ConvexPolyhedronCL convexPolyhedronA;\n"
+" //add 3 vertices of the triangle\n"
+" convexPolyhedronA.m_numVertices = 3;\n"
+" convexPolyhedronA.m_vertexOffset = 0;\n"
+" float4 localCenter = make_float4(0.f,0.f,0.f,0.f);\n"
+" btGpuFace face = faces[convexShapes[shapeIndexA].m_faceOffset+f];\n"
+" float4 triMinAabb, triMaxAabb;\n"
+" btAabbCL triAabb;\n"
+" triAabb.m_min = make_float4(1e30f,1e30f,1e30f,0.f);\n"
+" triAabb.m_max = make_float4(-1e30f,-1e30f,-1e30f,0.f);\n"
+" \n"
+" float4 verticesA[3];\n"
+" for (int i=0;i<3;i++)\n"
+" {\n"
+" int index = indices[face.m_indexOffset+i];\n"
+" float4 vert = vertices[convexShapes[shapeIndexA].m_vertexOffset+index];\n"
+" verticesA[i] = vert;\n"
+" localCenter += vert;\n"
+" \n"
+" triAabb.m_min = min(triAabb.m_min,vert); \n"
+" triAabb.m_max = max(triAabb.m_max,vert); \n"
+" }\n"
+" overlap = true;\n"
+" overlap = (triAabb.m_min.x > aabbs[bodyIndexB].m_max.x || triAabb.m_max.x < aabbs[bodyIndexB].m_min.x) ? false : overlap;\n"
+" overlap = (triAabb.m_min.z > aabbs[bodyIndexB].m_max.z || triAabb.m_max.z < aabbs[bodyIndexB].m_min.z) ? false : overlap;\n"
+" overlap = (triAabb.m_min.y > aabbs[bodyIndexB].m_max.y || triAabb.m_max.y < aabbs[bodyIndexB].m_min.y) ? false : overlap;\n"
+" \n"
+" if (overlap)\n"
+" {\n"
+" float dmin = FLT_MAX;\n"
+" int hasSeparatingAxis=5;\n"
+" float4 sepAxis=make_float4(1,2,3,4);\n"
+" int localCC=0;\n"
+" numActualConcaveConvexTests++;\n"
+" //a triangle has 3 unique edges\n"
+" convexPolyhedronA.m_numUniqueEdges = 3;\n"
+" convexPolyhedronA.m_uniqueEdgesOffset = 0;\n"
+" float4 uniqueEdgesA[3];\n"
+" \n"
+" uniqueEdgesA[0] = (verticesA[1]-verticesA[0]);\n"
+" uniqueEdgesA[1] = (verticesA[2]-verticesA[1]);\n"
+" uniqueEdgesA[2] = (verticesA[0]-verticesA[2]);\n"
+" convexPolyhedronA.m_faceOffset = 0;\n"
+" \n"
+" float4 normal = make_float4(face.m_plane.x,face.m_plane.y,face.m_plane.z,0.f);\n"
+" \n"
+" btGpuFace facesA[TRIANGLE_NUM_CONVEX_FACES];\n"
+" int indicesA[3+3+2+2+2];\n"
+" int curUsedIndices=0;\n"
+" int fidx=0;\n"
+" //front size of triangle\n"
+" {\n"
+" facesA[fidx].m_indexOffset=curUsedIndices;\n"
+" indicesA[0] = 0;\n"
+" indicesA[1] = 1;\n"
+" indicesA[2] = 2;\n"
+" curUsedIndices+=3;\n"
+" float c = face.m_plane.w;\n"
+" facesA[fidx].m_plane.x = normal.x;\n"
+" facesA[fidx].m_plane.y = normal.y;\n"
+" facesA[fidx].m_plane.z = normal.z;\n"
+" facesA[fidx].m_plane.w = c;\n"
+" facesA[fidx].m_numIndices=3;\n"
+" }\n"
+" fidx++;\n"
+" //back size of triangle\n"
+" {\n"
+" facesA[fidx].m_indexOffset=curUsedIndices;\n"
+" indicesA[3]=2;\n"
+" indicesA[4]=1;\n"
+" indicesA[5]=0;\n"
+" curUsedIndices+=3;\n"
+" float c = dot(normal,verticesA[0]);\n"
+" float c1 = -face.m_plane.w;\n"
+" facesA[fidx].m_plane.x = -normal.x;\n"
+" facesA[fidx].m_plane.y = -normal.y;\n"
+" facesA[fidx].m_plane.z = -normal.z;\n"
+" facesA[fidx].m_plane.w = c;\n"
+" facesA[fidx].m_numIndices=3;\n"
+" }\n"
+" fidx++;\n"
+" bool addEdgePlanes = true;\n"
+" if (addEdgePlanes)\n"
+" {\n"
+" int numVertices=3;\n"
+" int prevVertex = numVertices-1;\n"
+" for (int i=0;i<numVertices;i++)\n"
+" {\n"
+" float4 v0 = verticesA[i];\n"
+" float4 v1 = verticesA[prevVertex];\n"
+" \n"
+" float4 edgeNormal = normalize(cross(normal,v1-v0));\n"
+" float c = -dot(edgeNormal,v0);\n"
+" facesA[fidx].m_numIndices = 2;\n"
+" facesA[fidx].m_indexOffset=curUsedIndices;\n"
+" indicesA[curUsedIndices++]=i;\n"
+" indicesA[curUsedIndices++]=prevVertex;\n"
+" \n"
+" facesA[fidx].m_plane.x = edgeNormal.x;\n"
+" facesA[fidx].m_plane.y = edgeNormal.y;\n"
+" facesA[fidx].m_plane.z = edgeNormal.z;\n"
+" facesA[fidx].m_plane.w = c;\n"
+" fidx++;\n"
+" prevVertex = i;\n"
+" }\n"
+" }\n"
+" convexPolyhedronA.m_numFaces = TRIANGLE_NUM_CONVEX_FACES;\n"
+" convexPolyhedronA.m_localCenter = localCenter*(1.f/3.f);\n"
+" float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
+" posA.w = 0.f;\n"
+" float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
+" posB.w = 0.f;\n"
+" float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
+" float4 ornB =rigidBodies[bodyIndexB].m_quat;\n"
+" \n"
+" ///////////////////\n"
+" ///compound shape support\n"
+" if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
+" {\n"
+" int compoundChild = concavePairs[pairIdx].w;\n"
+" int childShapeIndexB = compoundChild;//collidables[collidableIndexB].m_shapeIndex+compoundChild;\n"
+" int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;\n"
+" float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;\n"
+" float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;\n"
+" float4 newPosB = transform(&childPosB,&posB,&ornB);\n"
+" float4 newOrnB = qtMul(ornB,childOrnB);\n"
+" posB = newPosB;\n"
+" ornB = newOrnB;\n"
+" shapeIndexB = collidables[childColIndexB].m_shapeIndex;\n"
+" }\n"
+" //////////////////\n"
+" float4 c0local = convexPolyhedronA.m_localCenter;\n"
+" float4 c0 = transform(&c0local, &posA, &ornA);\n"
+" float4 c1local = convexShapes[shapeIndexB].m_localCenter;\n"
+" float4 c1 = transform(&c1local,&posB,&ornB);\n"
+" const float4 DeltaC2 = c0 - c1;\n"
+" bool sepA = findSeparatingAxisLocalA( &convexPolyhedronA, &convexShapes[shapeIndexB],\n"
+" posA,ornA,\n"
+" posB,ornB,\n"
+" DeltaC2,\n"
+" verticesA,uniqueEdgesA,facesA,indicesA,\n"
+" vertices,uniqueEdges,faces,indices,\n"
+" &sepAxis,&dmin);\n"
+" hasSeparatingAxis = 4;\n"
+" if (!sepA)\n"
+" {\n"
+" hasSeparatingAxis = 0;\n"
+" } else\n"
+" {\n"
+" bool sepB = findSeparatingAxisLocalB( &convexShapes[shapeIndexB],&convexPolyhedronA,\n"
+" posB,ornB,\n"
+" posA,ornA,\n"
+" DeltaC2,\n"
+" vertices,uniqueEdges,faces,indices,\n"
+" verticesA,uniqueEdgesA,facesA,indicesA,\n"
+" &sepAxis,&dmin);\n"
+" if (!sepB)\n"
+" {\n"
+" hasSeparatingAxis = 0;\n"
+" } else\n"
+" {\n"
+" bool sepEE = findSeparatingAxisEdgeEdgeLocalA( &convexPolyhedronA, &convexShapes[shapeIndexB],\n"
+" posA,ornA,\n"
+" posB,ornB,\n"
+" DeltaC2,\n"
+" verticesA,uniqueEdgesA,facesA,indicesA,\n"
+" vertices,uniqueEdges,faces,indices,\n"
+" &sepAxis,&dmin);\n"
+" \n"
+" if (!sepEE)\n"
+" {\n"
+" hasSeparatingAxis = 0;\n"
+" } else\n"
+" {\n"
+" hasSeparatingAxis = 1;\n"
+" }\n"
+" }\n"
+" } \n"
+" \n"
+" if (hasSeparatingAxis)\n"
+" {\n"
+" sepAxis.w = dmin;\n"
+" concaveSeparatingNormalsOut[pairIdx]=sepAxis;\n"
+" concaveHasSeparatingNormals[i]=1;\n"
+" float minDist = -1e30f;\n"
+" float maxDist = 0.02f;\n"
+" \n"
+" findClippingFaces(sepAxis,\n"
+" &convexPolyhedronA,\n"
+" &convexShapes[shapeIndexB],\n"
+" posA,ornA,\n"
+" posB,ornB,\n"
+" worldVertsA1GPU,\n"
+" worldNormalsAGPU,\n"
+" worldVertsB1GPU,\n"
+" vertexFaceCapacity,\n"
+" minDist, maxDist,\n"
+" verticesA,\n"
+" facesA,\n"
+" indicesA,\n"
+" vertices,\n"
+" faces,\n"
+" indices,\n"
+" clippingFacesOut, pairIdx);\n"
+" } else\n"
+" { \n"
+" //mark this pair as in-active\n"
+" concavePairs[pairIdx].w = -1;\n"
+" }\n"
+" }\n"
+" else\n"
+" { \n"
+" //mark this pair as in-active\n"
+" concavePairs[pairIdx].w = -1;\n"
+" }\n"
+" \n"
+" concavePairs[pairIdx].z = -1;//now z is used for existing/persistent contacts\n"
+"}\n"
+;
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/b3BoundSearchCL.cpp b/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/b3BoundSearchCL.cpp
new file mode 100644
index 0000000000..a4980f71e1
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/b3BoundSearchCL.cpp
@@ -0,0 +1,213 @@
+/*
+Copyright (c) 2012 Advanced Micro Devices, Inc.
+
+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.
+*/
+//Originally written by Takahiro Harada
+//Host-code rewritten by Erwin Coumans
+
+#define BOUNDSEARCH_PATH "src/Bullet3OpenCL/ParallelPrimitives/kernels/BoundSearchKernels.cl"
+#define KERNEL0 "SearchSortDataLowerKernel"
+#define KERNEL1 "SearchSortDataUpperKernel"
+#define KERNEL2 "SubtractKernel"
+
+
+#include "b3BoundSearchCL.h"
+#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
+#include "b3LauncherCL.h"
+#include "kernels/BoundSearchKernelsCL.h"
+
+b3BoundSearchCL::b3BoundSearchCL(cl_context ctx, cl_device_id device, cl_command_queue queue, int maxSize)
+ :m_context(ctx),
+ m_device(device),
+ m_queue(queue)
+{
+
+ const char* additionalMacros = "";
+ //const char* srcFileNameForCaching="";
+
+ cl_int pErrNum;
+ const char* kernelSource = boundSearchKernelsCL;
+
+ cl_program boundSearchProg = b3OpenCLUtils::compileCLProgramFromString( ctx, device, kernelSource, &pErrNum,additionalMacros, BOUNDSEARCH_PATH);
+ b3Assert(boundSearchProg);
+
+ m_lowerSortDataKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, kernelSource, "SearchSortDataLowerKernel", &pErrNum, boundSearchProg,additionalMacros );
+ b3Assert(m_lowerSortDataKernel );
+
+ m_upperSortDataKernel= b3OpenCLUtils::compileCLKernelFromString( ctx, device, kernelSource, "SearchSortDataUpperKernel", &pErrNum, boundSearchProg,additionalMacros );
+ b3Assert(m_upperSortDataKernel);
+
+ m_subtractKernel = 0;
+
+ if( maxSize )
+ {
+ m_subtractKernel= b3OpenCLUtils::compileCLKernelFromString( ctx, device, kernelSource, "SubtractKernel", &pErrNum, boundSearchProg,additionalMacros );
+ b3Assert(m_subtractKernel);
+ }
+
+ //m_constBuffer = new b3OpenCLArray<b3Int4>( device, 1, BufferBase::BUFFER_CONST );
+
+ m_lower = (maxSize == 0)? 0: new b3OpenCLArray<unsigned int>(ctx,queue,maxSize );
+ m_upper = (maxSize == 0)? 0: new b3OpenCLArray<unsigned int>(ctx,queue, maxSize );
+
+ m_filler = new b3FillCL(ctx,device,queue);
+}
+
+b3BoundSearchCL::~b3BoundSearchCL()
+{
+
+ delete m_lower;
+ delete m_upper;
+ delete m_filler;
+
+ clReleaseKernel(m_lowerSortDataKernel);
+ clReleaseKernel(m_upperSortDataKernel);
+ clReleaseKernel(m_subtractKernel);
+
+
+}
+
+
+void b3BoundSearchCL::execute(b3OpenCLArray<b3SortData>& src, int nSrc, b3OpenCLArray<unsigned int>& dst, int nDst, Option option )
+{
+ b3Int4 constBuffer;
+ constBuffer.x = nSrc;
+ constBuffer.y = nDst;
+
+ if( option == BOUND_LOWER )
+ {
+ b3BufferInfoCL bInfo[] = { b3BufferInfoCL( src.getBufferCL(), true ), b3BufferInfoCL( dst.getBufferCL()) };
+
+ b3LauncherCL launcher( m_queue, m_lowerSortDataKernel,"m_lowerSortDataKernel" );
+ launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst( nSrc );
+ launcher.setConst( nDst );
+
+ launcher.launch1D( nSrc, 64 );
+ }
+ else if( option == BOUND_UPPER )
+ {
+ b3BufferInfoCL bInfo[] = { b3BufferInfoCL( src.getBufferCL(), true ), b3BufferInfoCL( dst.getBufferCL() ) };
+
+ b3LauncherCL launcher(m_queue, m_upperSortDataKernel,"m_upperSortDataKernel" );
+ launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst( nSrc );
+ launcher.setConst( nDst );
+
+ launcher.launch1D( nSrc, 64 );
+ }
+ else if( option == COUNT )
+ {
+ b3Assert( m_lower );
+ b3Assert( m_upper );
+ b3Assert( m_lower->capacity() <= (int)nDst );
+ b3Assert( m_upper->capacity() <= (int)nDst );
+
+ int zero = 0;
+ m_filler->execute( *m_lower, zero, nDst );
+ m_filler->execute( *m_upper, zero, nDst );
+
+ execute( src, nSrc, *m_lower, nDst, BOUND_LOWER );
+ execute( src, nSrc, *m_upper, nDst, BOUND_UPPER );
+
+ {
+ b3BufferInfoCL bInfo[] = { b3BufferInfoCL( m_upper->getBufferCL(), true ), b3BufferInfoCL( m_lower->getBufferCL(), true ), b3BufferInfoCL( dst.getBufferCL() ) };
+
+ b3LauncherCL launcher( m_queue, m_subtractKernel ,"m_subtractKernel");
+ launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst( nSrc );
+ launcher.setConst( nDst );
+
+ launcher.launch1D( nDst, 64 );
+ }
+ }
+ else
+ {
+ b3Assert( 0 );
+ }
+
+}
+
+
+void b3BoundSearchCL::executeHost( b3AlignedObjectArray<b3SortData>& src, int nSrc,
+ b3AlignedObjectArray<unsigned int>& dst, int nDst, Option option )
+{
+
+
+ for(int i=0; i<nSrc-1; i++)
+ b3Assert( src[i].m_key <= src[i+1].m_key );
+
+ b3SortData minData,zeroData,maxData;
+ minData.m_key = -1;
+ minData.m_value = -1;
+ zeroData.m_key=0;
+ zeroData.m_value=0;
+ maxData.m_key = nDst;
+ maxData.m_value = nDst;
+
+ if( option == BOUND_LOWER )
+ {
+ for(int i=0; i<nSrc; i++)
+ {
+ b3SortData& iData = (i==0)? minData: src[i-1];
+ b3SortData& jData = (i==nSrc)? maxData: src[i];
+
+ if( iData.m_key != jData.m_key )
+ {
+ int k = jData.m_key;
+ {
+ dst[k] = i;
+ }
+ }
+ }
+ }
+ else if( option == BOUND_UPPER )
+ {
+ for(int i=1; i<nSrc+1; i++)
+ {
+ b3SortData& iData = src[i-1];
+ b3SortData& jData = (i==nSrc)? maxData: src[i];
+
+ if( iData.m_key != jData.m_key )
+ {
+ int k = iData.m_key;
+ {
+ dst[k] = i;
+ }
+ }
+ }
+ }
+ else if( option == COUNT )
+ {
+ b3AlignedObjectArray<unsigned int> lower;
+ lower.resize(nDst );
+ b3AlignedObjectArray<unsigned int> upper;
+ upper.resize(nDst );
+
+ for(int i=0; i<nDst; i++)
+ {
+ lower[i] = upper[i] = 0;
+ }
+
+ executeHost( src, nSrc, lower, nDst, BOUND_LOWER );
+ executeHost( src, nSrc, upper, nDst, BOUND_UPPER );
+
+ for( int i=0; i<nDst; i++)
+ {
+ dst[i] = upper[i] - lower[i];
+ }
+ }
+ else
+ {
+ b3Assert( 0 );
+ }
+}
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/b3BoundSearchCL.h b/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/b3BoundSearchCL.h
new file mode 100644
index 0000000000..7e2940965c
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/b3BoundSearchCL.h
@@ -0,0 +1,67 @@
+/*
+Copyright (c) 2012 Advanced Micro Devices, Inc.
+
+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.
+*/
+//Originally written by Takahiro Harada
+
+#ifndef B3_BOUNDSEARCH_H
+#define B3_BOUNDSEARCH_H
+
+#pragma once
+
+/*#include <Adl/Adl.h>
+#include <AdlPrimitives/Math/Math.h>
+#include <AdlPrimitives/Sort/SortData.h>
+#include <AdlPrimitives/Fill/Fill.h>
+*/
+
+#include "b3OpenCLArray.h"
+#include "b3FillCL.h"
+#include "b3RadixSort32CL.h" //for b3SortData (perhaps move it?)
+class b3BoundSearchCL
+{
+ public:
+
+ enum Option
+ {
+ BOUND_LOWER,
+ BOUND_UPPER,
+ COUNT,
+ };
+
+ cl_context m_context;
+ cl_device_id m_device;
+ cl_command_queue m_queue;
+
+
+ cl_kernel m_lowerSortDataKernel;
+ cl_kernel m_upperSortDataKernel;
+ cl_kernel m_subtractKernel;
+
+ b3OpenCLArray<b3Int4>* m_constbtOpenCLArray;
+ b3OpenCLArray<unsigned int>* m_lower;
+ b3OpenCLArray<unsigned int>* m_upper;
+
+ b3FillCL* m_filler;
+
+ b3BoundSearchCL(cl_context context, cl_device_id device, cl_command_queue queue, int size);
+
+ virtual ~b3BoundSearchCL();
+
+ // src has to be src[i].m_key <= src[i+1].m_key
+ void execute( b3OpenCLArray<b3SortData>& src, int nSrc, b3OpenCLArray<unsigned int>& dst, int nDst, Option option = BOUND_LOWER );
+
+ void executeHost( b3AlignedObjectArray<b3SortData>& src, int nSrc, b3AlignedObjectArray<unsigned int>& dst, int nDst, Option option = BOUND_LOWER);
+};
+
+
+#endif //B3_BOUNDSEARCH_H
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/b3BufferInfoCL.h b/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/b3BufferInfoCL.h
new file mode 100644
index 0000000000..52f219ae3f
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/b3BufferInfoCL.h
@@ -0,0 +1,19 @@
+
+#ifndef B3_BUFFER_INFO_CL_H
+#define B3_BUFFER_INFO_CL_H
+
+#include "b3OpenCLArray.h"
+
+
+struct b3BufferInfoCL
+{
+ //b3BufferInfoCL(){}
+
+// template<typename T>
+ b3BufferInfoCL(cl_mem buff, bool isReadOnly = false): m_clBuffer(buff), m_isReadOnly(isReadOnly){}
+
+ cl_mem m_clBuffer;
+ bool m_isReadOnly;
+};
+
+#endif //B3_BUFFER_INFO_CL_H
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/b3FillCL.cpp b/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/b3FillCL.cpp
new file mode 100644
index 0000000000..f05c2648f1
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/b3FillCL.cpp
@@ -0,0 +1,126 @@
+#include "b3FillCL.h"
+#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
+#include "b3BufferInfoCL.h"
+#include "b3LauncherCL.h"
+
+#define FILL_CL_PROGRAM_PATH "src/Bullet3OpenCL/ParallelPrimitives/kernels/FillKernels.cl"
+
+#include "kernels/FillKernelsCL.h"
+
+b3FillCL::b3FillCL(cl_context ctx, cl_device_id device, cl_command_queue queue)
+:m_commandQueue(queue)
+{
+ const char* kernelSource = fillKernelsCL;
+ cl_int pErrNum;
+ const char* additionalMacros = "";
+
+ cl_program fillProg = b3OpenCLUtils::compileCLProgramFromString( ctx, device, kernelSource, &pErrNum,additionalMacros, FILL_CL_PROGRAM_PATH);
+ b3Assert(fillProg);
+
+ m_fillIntKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, kernelSource, "FillIntKernel", &pErrNum, fillProg,additionalMacros );
+ b3Assert(m_fillIntKernel);
+
+ m_fillUnsignedIntKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, kernelSource, "FillUnsignedIntKernel", &pErrNum, fillProg,additionalMacros );
+ b3Assert(m_fillIntKernel);
+
+ m_fillFloatKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, kernelSource, "FillFloatKernel", &pErrNum, fillProg,additionalMacros );
+ b3Assert(m_fillFloatKernel);
+
+
+
+ m_fillKernelInt2 = b3OpenCLUtils::compileCLKernelFromString( ctx, device, kernelSource, "FillInt2Kernel", &pErrNum, fillProg,additionalMacros );
+ b3Assert(m_fillKernelInt2);
+
+}
+
+b3FillCL::~b3FillCL()
+{
+ clReleaseKernel(m_fillKernelInt2);
+ clReleaseKernel(m_fillIntKernel);
+ clReleaseKernel(m_fillUnsignedIntKernel);
+ clReleaseKernel(m_fillFloatKernel);
+
+}
+
+void b3FillCL::execute(b3OpenCLArray<float>& src, const float value, int n, int offset)
+{
+ b3Assert( n>0 );
+
+ {
+ b3LauncherCL launcher( m_commandQueue, m_fillFloatKernel,"m_fillFloatKernel" );
+ launcher.setBuffer( src.getBufferCL());
+ launcher.setConst( n );
+ launcher.setConst( value );
+ launcher.setConst( offset);
+
+ launcher.launch1D( n );
+ }
+}
+
+void b3FillCL::execute(b3OpenCLArray<int>& src, const int value, int n, int offset)
+{
+ b3Assert( n>0 );
+
+
+ {
+ b3LauncherCL launcher( m_commandQueue, m_fillIntKernel ,"m_fillIntKernel");
+ launcher.setBuffer(src.getBufferCL());
+ launcher.setConst( n);
+ launcher.setConst( value);
+ launcher.setConst( offset);
+ launcher.launch1D( n );
+ }
+}
+
+
+void b3FillCL::execute(b3OpenCLArray<unsigned int>& src, const unsigned int value, int n, int offset)
+{
+ b3Assert( n>0 );
+
+ {
+ b3BufferInfoCL bInfo[] = { b3BufferInfoCL( src.getBufferCL() ) };
+
+ b3LauncherCL launcher( m_commandQueue, m_fillUnsignedIntKernel,"m_fillUnsignedIntKernel" );
+ launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst( n );
+ launcher.setConst(value);
+ launcher.setConst(offset);
+
+ launcher.launch1D( n );
+ }
+}
+
+void b3FillCL::executeHost(b3AlignedObjectArray<b3Int2> &src, const b3Int2 &value, int n, int offset)
+{
+ for (int i=0;i<n;i++)
+ {
+ src[i+offset]=value;
+ }
+}
+
+void b3FillCL::executeHost(b3AlignedObjectArray<int> &src, const int value, int n, int offset)
+{
+ for (int i=0;i<n;i++)
+ {
+ src[i+offset]=value;
+ }
+}
+
+void b3FillCL::execute(b3OpenCLArray<b3Int2> &src, const b3Int2 &value, int n, int offset)
+{
+ b3Assert( n>0 );
+
+
+ {
+ b3BufferInfoCL bInfo[] = { b3BufferInfoCL( src.getBufferCL() ) };
+
+ b3LauncherCL launcher(m_commandQueue, m_fillKernelInt2,"m_fillKernelInt2");
+ launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst(n);
+ launcher.setConst(value);
+ launcher.setConst(offset);
+
+ //( constBuffer );
+ launcher.launch1D( n );
+ }
+}
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/b3FillCL.h b/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/b3FillCL.h
new file mode 100644
index 0000000000..1609676b9d
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/b3FillCL.h
@@ -0,0 +1,63 @@
+#ifndef B3_FILL_CL_H
+#define B3_FILL_CL_H
+
+#include "b3OpenCLArray.h"
+#include "Bullet3Common/b3Scalar.h"
+
+#include "Bullet3Common/shared/b3Int2.h"
+#include "Bullet3Common/shared/b3Int4.h"
+
+
+class b3FillCL
+{
+
+ cl_command_queue m_commandQueue;
+
+ cl_kernel m_fillKernelInt2;
+ cl_kernel m_fillIntKernel;
+ cl_kernel m_fillUnsignedIntKernel;
+ cl_kernel m_fillFloatKernel;
+
+ public:
+
+ struct b3ConstData
+ {
+ union
+ {
+ b3Int4 m_data;
+ b3UnsignedInt4 m_UnsignedData;
+ };
+ int m_offset;
+ int m_n;
+ int m_padding[2];
+ };
+
+protected:
+
+public:
+
+ b3FillCL(cl_context ctx, cl_device_id device, cl_command_queue queue);
+
+ virtual ~b3FillCL();
+
+ void execute(b3OpenCLArray<unsigned int>& src, const unsigned int value, int n, int offset = 0);
+
+ void execute(b3OpenCLArray<int>& src, const int value, int n, int offset = 0);
+
+ void execute(b3OpenCLArray<float>& src, const float value, int n, int offset = 0);
+
+ void execute(b3OpenCLArray<b3Int2>& src, const b3Int2& value, int n, int offset = 0);
+
+ void executeHost(b3AlignedObjectArray<b3Int2> &src, const b3Int2 &value, int n, int offset);
+
+ void executeHost(b3AlignedObjectArray<int> &src, const int value, int n, int offset);
+
+ // void execute(b3OpenCLArray<b3Int4>& src, const b3Int4& value, int n, int offset = 0);
+
+};
+
+
+
+
+
+#endif //B3_FILL_CL_H
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.cpp b/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.cpp
new file mode 100644
index 0000000000..94590d11ca
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.cpp
@@ -0,0 +1,308 @@
+#include "b3LauncherCL.h"
+
+bool gDebugLauncherCL = false;
+
+b3LauncherCL::b3LauncherCL(cl_command_queue queue, cl_kernel kernel, const char* name)
+:m_commandQueue(queue),
+m_kernel(kernel),
+m_idx(0),
+m_enableSerialization(false),
+m_name(name)
+{
+ if (gDebugLauncherCL)
+ {
+ static int counter = 0;
+ printf("[%d] Prepare to launch OpenCL kernel %s\n", counter++, name);
+ }
+
+ m_serializationSizeInBytes = sizeof(int);
+}
+
+b3LauncherCL::~b3LauncherCL()
+ {
+ for (int i=0;i<m_arrays.size();i++)
+ {
+ delete (m_arrays[i]);
+ }
+
+ m_arrays.clear();
+ if (gDebugLauncherCL)
+ {
+ static int counter = 0;
+ printf("[%d] Finished launching OpenCL kernel %s\n", counter++,m_name);
+ }
+ }
+
+void b3LauncherCL::setBuffer( cl_mem clBuffer)
+{
+ if (m_enableSerialization)
+ {
+ b3KernelArgData kernelArg;
+ kernelArg.m_argIndex = m_idx;
+ kernelArg.m_isBuffer = 1;
+ kernelArg.m_clBuffer = clBuffer;
+
+ cl_mem_info param_name = CL_MEM_SIZE;
+ size_t param_value;
+ size_t sizeInBytes = sizeof(size_t);
+ size_t actualSizeInBytes;
+ cl_int err;
+ err = clGetMemObjectInfo ( kernelArg.m_clBuffer,
+ param_name,
+ sizeInBytes,
+ &param_value,
+ &actualSizeInBytes);
+
+ b3Assert( err == CL_SUCCESS );
+ kernelArg.m_argSizeInBytes = param_value;
+
+ m_kernelArguments.push_back(kernelArg);
+ m_serializationSizeInBytes+= sizeof(b3KernelArgData);
+ m_serializationSizeInBytes+=param_value;
+ }
+ cl_int status = clSetKernelArg( m_kernel, m_idx++, sizeof(cl_mem), &clBuffer);
+ b3Assert( status == CL_SUCCESS );
+}
+
+
+void b3LauncherCL::setBuffers( b3BufferInfoCL* buffInfo, int n )
+{
+ for(int i=0; i<n; i++)
+ {
+ if (m_enableSerialization)
+ {
+ b3KernelArgData kernelArg;
+ kernelArg.m_argIndex = m_idx;
+ kernelArg.m_isBuffer = 1;
+ kernelArg.m_clBuffer = buffInfo[i].m_clBuffer;
+
+ cl_mem_info param_name = CL_MEM_SIZE;
+ size_t param_value;
+ size_t sizeInBytes = sizeof(size_t);
+ size_t actualSizeInBytes;
+ cl_int err;
+ err = clGetMemObjectInfo ( kernelArg.m_clBuffer,
+ param_name,
+ sizeInBytes,
+ &param_value,
+ &actualSizeInBytes);
+
+ b3Assert( err == CL_SUCCESS );
+ kernelArg.m_argSizeInBytes = param_value;
+
+ m_kernelArguments.push_back(kernelArg);
+ m_serializationSizeInBytes+= sizeof(b3KernelArgData);
+ m_serializationSizeInBytes+=param_value;
+ }
+ cl_int status = clSetKernelArg( m_kernel, m_idx++, sizeof(cl_mem), &buffInfo[i].m_clBuffer);
+ b3Assert( status == CL_SUCCESS );
+ }
+}
+
+struct b3KernelArgDataUnaligned
+{
+ int m_isBuffer;
+ int m_argIndex;
+ int m_argSizeInBytes;
+ int m_unusedPadding;
+ union
+ {
+ cl_mem m_clBuffer;
+ unsigned char m_argData[B3_CL_MAX_ARG_SIZE];
+ };
+
+};
+#include <string.h>
+
+
+
+int b3LauncherCL::deserializeArgs(unsigned char* buf, int bufSize, cl_context ctx)
+{
+ int index=0;
+
+ int numArguments = *(int*) &buf[index];
+ index+=sizeof(int);
+
+ for (int i=0;i<numArguments;i++)
+ {
+ b3KernelArgDataUnaligned* arg = (b3KernelArgDataUnaligned*)&buf[index];
+
+ index+=sizeof(b3KernelArgData);
+ if (arg->m_isBuffer)
+ {
+ b3OpenCLArray<unsigned char>* clData = new b3OpenCLArray<unsigned char>(ctx,m_commandQueue, arg->m_argSizeInBytes);
+ clData->resize(arg->m_argSizeInBytes);
+
+ clData->copyFromHostPointer(&buf[index], arg->m_argSizeInBytes);
+
+ arg->m_clBuffer = clData->getBufferCL();
+
+ m_arrays.push_back(clData);
+
+ cl_int status = clSetKernelArg( m_kernel, m_idx++, sizeof(cl_mem), &arg->m_clBuffer);
+ b3Assert( status == CL_SUCCESS );
+ index+=arg->m_argSizeInBytes;
+ } else
+ {
+ cl_int status = clSetKernelArg( m_kernel, m_idx++, arg->m_argSizeInBytes, &arg->m_argData);
+ b3Assert( status == CL_SUCCESS );
+ }
+ b3KernelArgData b;
+ memcpy(&b,arg,sizeof(b3KernelArgDataUnaligned));
+ m_kernelArguments.push_back(b);
+ }
+m_serializationSizeInBytes = index;
+ return index;
+}
+
+int b3LauncherCL::validateResults(unsigned char* goldBuffer, int goldBufferCapacity, cl_context ctx)
+ {
+ int index=0;
+
+ int numArguments = *(int*) &goldBuffer[index];
+ index+=sizeof(int);
+
+ if (numArguments != m_kernelArguments.size())
+ {
+ printf("failed validation: expected %d arguments, found %d\n",numArguments, m_kernelArguments.size());
+ return -1;
+ }
+
+ for (int ii=0;ii<numArguments;ii++)
+ {
+ b3KernelArgData* argGold = (b3KernelArgData*)&goldBuffer[index];
+
+ if (m_kernelArguments[ii].m_argSizeInBytes != argGold->m_argSizeInBytes)
+ {
+ printf("failed validation: argument %d sizeInBytes expected: %d, found %d\n",ii, argGold->m_argSizeInBytes, m_kernelArguments[ii].m_argSizeInBytes);
+ return -2;
+ }
+
+ {
+ int expected = argGold->m_isBuffer;
+ int found = m_kernelArguments[ii].m_isBuffer;
+
+ if (expected != found)
+ {
+ printf("failed validation: argument %d isBuffer expected: %d, found %d\n",ii,expected, found);
+ return -3;
+ }
+ }
+ index+=sizeof(b3KernelArgData);
+
+ if (argGold->m_isBuffer)
+ {
+
+ unsigned char* memBuf= (unsigned char*) malloc(m_kernelArguments[ii].m_argSizeInBytes);
+ unsigned char* goldBuf = &goldBuffer[index];
+ for (int j=0;j<m_kernelArguments[j].m_argSizeInBytes;j++)
+ {
+ memBuf[j] = 0xaa;
+ }
+
+ cl_int status = 0;
+ status = clEnqueueReadBuffer( m_commandQueue, m_kernelArguments[ii].m_clBuffer, CL_TRUE, 0, m_kernelArguments[ii].m_argSizeInBytes,
+ memBuf, 0,0,0 );
+ b3Assert( status==CL_SUCCESS );
+ clFinish(m_commandQueue);
+
+ for (int b=0;b<m_kernelArguments[ii].m_argSizeInBytes;b++)
+ {
+ int expected = goldBuf[b];
+ int found = memBuf[b];
+ if (expected != found)
+ {
+ printf("failed validation: argument %d OpenCL data at byte position %d expected: %d, found %d\n",
+ ii, b, expected, found);
+ return -4;
+ }
+ }
+
+
+ index+=argGold->m_argSizeInBytes;
+ } else
+ {
+
+ //compare content
+ for (int b=0;b<m_kernelArguments[ii].m_argSizeInBytes;b++)
+ {
+ int expected = argGold->m_argData[b];
+ int found =m_kernelArguments[ii].m_argData[b];
+ if (expected != found)
+ {
+ printf("failed validation: argument %d const data at byte position %d expected: %d, found %d\n",
+ ii, b, expected, found);
+ return -5;
+ }
+ }
+
+ }
+ }
+ return index;
+
+}
+
+int b3LauncherCL::serializeArguments(unsigned char* destBuffer, int destBufferCapacity)
+{
+//initialize to known values
+for (int i=0;i<destBufferCapacity;i++)
+ destBuffer[i] = 0xec;
+
+ assert(destBufferCapacity>=m_serializationSizeInBytes);
+
+ //todo: use the b3Serializer for this to allow for 32/64bit, endianness etc
+ int numArguments = m_kernelArguments.size();
+ int curBufferSize = 0;
+ int* dest = (int*)&destBuffer[curBufferSize];
+ *dest = numArguments;
+ curBufferSize += sizeof(int);
+
+
+
+ for (int i=0;i<this->m_kernelArguments.size();i++)
+ {
+ b3KernelArgData* arg = (b3KernelArgData*) &destBuffer[curBufferSize];
+ *arg = m_kernelArguments[i];
+ curBufferSize+=sizeof(b3KernelArgData);
+ if (arg->m_isBuffer==1)
+ {
+ //copy the OpenCL buffer content
+ cl_int status = 0;
+ status = clEnqueueReadBuffer( m_commandQueue, arg->m_clBuffer, 0, 0, arg->m_argSizeInBytes,
+ &destBuffer[curBufferSize], 0,0,0 );
+ b3Assert( status==CL_SUCCESS );
+ clFinish(m_commandQueue);
+ curBufferSize+=arg->m_argSizeInBytes;
+ }
+
+ }
+ return curBufferSize;
+}
+
+void b3LauncherCL::serializeToFile(const char* fileName, int numWorkItems)
+{
+ int num = numWorkItems;
+ int buffSize = getSerializationBufferSize();
+ unsigned char* buf = new unsigned char[buffSize+sizeof(int)];
+ for (int i=0;i<buffSize+1;i++)
+ {
+ unsigned char* ptr = (unsigned char*)&buf[i];
+ *ptr = 0xff;
+ }
+// int actualWrite = serializeArguments(buf,buffSize);
+
+// unsigned char* cptr = (unsigned char*)&buf[buffSize];
+// printf("buf[buffSize] = %d\n",*cptr);
+
+ assert(buf[buffSize]==0xff);//check for buffer overrun
+ int* ptr = (int*)&buf[buffSize];
+
+ *ptr = num;
+
+ FILE* f = fopen(fileName,"wb");
+ fwrite(buf,buffSize+sizeof(int),1,f);
+ fclose(f);
+
+ delete[] buf;
+}
+
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.h b/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.h
new file mode 100644
index 0000000000..1b267b31ef
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.h
@@ -0,0 +1,135 @@
+
+#ifndef B3_LAUNCHER_CL_H
+#define B3_LAUNCHER_CL_H
+
+#include "b3BufferInfoCL.h"
+#include "Bullet3Common/b3MinMax.h"
+#include "b3OpenCLArray.h"
+#include <stdio.h>
+
+#define B3_DEBUG_SERIALIZE_CL
+
+
+#ifdef _WIN32
+#pragma warning(disable :4996)
+#endif
+#define B3_CL_MAX_ARG_SIZE 16
+B3_ATTRIBUTE_ALIGNED16(struct) b3KernelArgData
+{
+ int m_isBuffer;
+ int m_argIndex;
+ int m_argSizeInBytes;
+ int m_unusedPadding;
+ union
+ {
+ cl_mem m_clBuffer;
+ unsigned char m_argData[B3_CL_MAX_ARG_SIZE];
+ };
+
+};
+
+class b3LauncherCL
+{
+
+ cl_command_queue m_commandQueue;
+ cl_kernel m_kernel;
+ int m_idx;
+
+ b3AlignedObjectArray<b3KernelArgData> m_kernelArguments;
+ int m_serializationSizeInBytes;
+ bool m_enableSerialization;
+
+ const char* m_name;
+ public:
+
+ b3AlignedObjectArray<b3OpenCLArray<unsigned char>* > m_arrays;
+
+ b3LauncherCL(cl_command_queue queue, cl_kernel kernel, const char* name);
+
+ virtual ~b3LauncherCL();
+
+ void setBuffer( cl_mem clBuffer);
+
+ void setBuffers( b3BufferInfoCL* buffInfo, int n );
+
+ int getSerializationBufferSize() const
+ {
+ return m_serializationSizeInBytes;
+ }
+
+ int deserializeArgs(unsigned char* buf, int bufSize, cl_context ctx);
+
+ inline int validateResults(unsigned char* goldBuffer, int goldBufferCapacity, cl_context ctx);
+
+ int serializeArguments(unsigned char* destBuffer, int destBufferCapacity);
+
+ int getNumArguments() const
+ {
+ return m_kernelArguments.size();
+ }
+
+ b3KernelArgData getArgument(int index)
+ {
+ return m_kernelArguments[index];
+ }
+
+ void serializeToFile(const char* fileName, int numWorkItems);
+
+ template<typename T>
+ inline void setConst( const T& consts )
+ {
+ int sz=sizeof(T);
+ b3Assert(sz<=B3_CL_MAX_ARG_SIZE);
+
+ if (m_enableSerialization)
+ {
+ b3KernelArgData kernelArg;
+ kernelArg.m_argIndex = m_idx;
+ kernelArg.m_isBuffer = 0;
+ T* destArg = (T*)kernelArg.m_argData;
+ *destArg = consts;
+ kernelArg.m_argSizeInBytes = sizeof(T);
+ m_kernelArguments.push_back(kernelArg);
+ m_serializationSizeInBytes+=sizeof(b3KernelArgData);
+ }
+
+ cl_int status = clSetKernelArg( m_kernel, m_idx++, sz, &consts );
+ b3Assert( status == CL_SUCCESS );
+ }
+
+ inline void launch1D( int numThreads, int localSize = 64)
+ {
+ launch2D( numThreads, 1, localSize, 1 );
+ }
+
+ inline void launch2D( int numThreadsX, int numThreadsY, int localSizeX, int localSizeY )
+ {
+ size_t gRange[3] = {1,1,1};
+ size_t lRange[3] = {1,1,1};
+ lRange[0] = localSizeX;
+ lRange[1] = localSizeY;
+ gRange[0] = b3Max((size_t)1, (numThreadsX/lRange[0])+(!(numThreadsX%lRange[0])?0:1));
+ gRange[0] *= lRange[0];
+ gRange[1] = b3Max((size_t)1, (numThreadsY/lRange[1])+(!(numThreadsY%lRange[1])?0:1));
+ gRange[1] *= lRange[1];
+
+ cl_int status = clEnqueueNDRangeKernel( m_commandQueue,
+ m_kernel, 2, NULL, gRange, lRange, 0,0,0 );
+ if (status != CL_SUCCESS)
+ {
+ printf("Error: OpenCL status = %d\n",status);
+ }
+ b3Assert( status == CL_SUCCESS );
+
+ }
+
+ void enableSerialization(bool serialize)
+ {
+ m_enableSerialization = serialize;
+ }
+
+};
+
+
+
+#endif //B3_LAUNCHER_CL_H
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h b/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h
new file mode 100644
index 0000000000..d70c30f53f
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h
@@ -0,0 +1,306 @@
+#ifndef B3_OPENCL_ARRAY_H
+#define B3_OPENCL_ARRAY_H
+
+#include "Bullet3Common/b3AlignedObjectArray.h"
+#include "Bullet3OpenCL/Initialize/b3OpenCLInclude.h"
+
+template <typename T>
+class b3OpenCLArray
+{
+ size_t m_size;
+ size_t m_capacity;
+ cl_mem m_clBuffer;
+
+ cl_context m_clContext;
+ cl_command_queue m_commandQueue;
+
+ bool m_ownsMemory;
+
+ bool m_allowGrowingCapacity;
+
+ void deallocate()
+ {
+ if (m_clBuffer && m_ownsMemory)
+ {
+ clReleaseMemObject(m_clBuffer);
+ }
+ m_clBuffer = 0;
+ m_capacity=0;
+ }
+
+ b3OpenCLArray<T>& operator=(const b3OpenCLArray<T>& src);
+
+ B3_FORCE_INLINE size_t allocSize(size_t size)
+ {
+ return (size ? size*2 : 1);
+ }
+
+public:
+
+ b3OpenCLArray(cl_context ctx, cl_command_queue queue, size_t initialCapacity=0, bool allowGrowingCapacity=true)
+ :m_size(0), m_capacity(0),m_clBuffer(0),
+ m_clContext(ctx),m_commandQueue(queue),
+ m_ownsMemory(true),m_allowGrowingCapacity(true)
+ {
+ if (initialCapacity)
+ {
+ reserve(initialCapacity);
+ }
+ m_allowGrowingCapacity = allowGrowingCapacity;
+ }
+
+ ///this is an error-prone method with no error checking, be careful!
+ void setFromOpenCLBuffer(cl_mem buffer, size_t sizeInElements)
+ {
+ deallocate();
+ m_ownsMemory = false;
+ m_allowGrowingCapacity = false;
+ m_clBuffer = buffer;
+ m_size = sizeInElements;
+ m_capacity = sizeInElements;
+ }
+
+// we could enable this assignment, but need to make sure to avoid accidental deep copies
+// b3OpenCLArray<T>& operator=(const b3AlignedObjectArray<T>& src)
+// {
+// copyFromArray(src);
+// return *this;
+// }
+
+
+ cl_mem getBufferCL() const
+ {
+ return m_clBuffer;
+ }
+
+
+ virtual ~b3OpenCLArray()
+ {
+ deallocate();
+ m_size=0;
+ m_capacity=0;
+ }
+
+ B3_FORCE_INLINE bool push_back(const T& _Val,bool waitForCompletion=true)
+ {
+ bool result = true;
+ size_t sz = size();
+ if( sz == capacity() )
+ {
+ result = reserve( allocSize(size()) );
+ }
+ copyFromHostPointer(&_Val, 1, sz, waitForCompletion);
+ m_size++;
+ return result;
+ }
+
+ B3_FORCE_INLINE T forcedAt(size_t n) const
+ {
+ b3Assert(n>=0);
+ b3Assert(n<capacity());
+ T elem;
+ copyToHostPointer(&elem,1,n,true);
+ return elem;
+ }
+
+ B3_FORCE_INLINE T at(size_t n) const
+ {
+ b3Assert(n>=0);
+ b3Assert(n<size());
+ T elem;
+ copyToHostPointer(&elem,1,n,true);
+ return elem;
+ }
+
+ B3_FORCE_INLINE bool resize(size_t newsize, bool copyOldContents=true)
+ {
+ bool result = true;
+ size_t curSize = size();
+
+ if (newsize < curSize)
+ {
+ //leave the OpenCL memory for now
+ } else
+ {
+ if (newsize > size())
+ {
+ result = reserve(newsize,copyOldContents);
+ }
+
+ //leave new data uninitialized (init in debug mode?)
+ //for (size_t i=curSize;i<newsize;i++) ...
+ }
+
+ if (result)
+ {
+ m_size = newsize;
+ } else
+ {
+ m_size = 0;
+ }
+ return result;
+ }
+
+ B3_FORCE_INLINE size_t size() const
+ {
+ return m_size;
+ }
+
+ B3_FORCE_INLINE size_t capacity() const
+ {
+ return m_capacity;
+ }
+
+ B3_FORCE_INLINE bool reserve(size_t _Count, bool copyOldContents=true)
+ {
+ bool result=true;
+ // determine new minimum length of allocated storage
+ if (capacity() < _Count)
+ { // not enough room, reallocate
+
+ if (m_allowGrowingCapacity)
+ {
+ cl_int ciErrNum;
+ //create a new OpenCL buffer
+ size_t memSizeInBytes = sizeof(T)*_Count;
+ cl_mem buf = clCreateBuffer(m_clContext, CL_MEM_READ_WRITE, memSizeInBytes, NULL, &ciErrNum);
+ if (ciErrNum!=CL_SUCCESS)
+ {
+ b3Error("OpenCL out-of-memory\n");
+ _Count = 0;
+ result = false;
+ }
+//#define B3_ALWAYS_INITIALIZE_OPENCL_BUFFERS
+#ifdef B3_ALWAYS_INITIALIZE_OPENCL_BUFFERS
+ unsigned char* src = (unsigned char*)malloc(memSizeInBytes);
+ for (size_t i=0;i<memSizeInBytes;i++)
+ src[i] = 0xbb;
+ ciErrNum = clEnqueueWriteBuffer( m_commandQueue, buf, CL_TRUE, 0, memSizeInBytes, src, 0,0,0 );
+ b3Assert(ciErrNum==CL_SUCCESS);
+ clFinish(m_commandQueue);
+ free(src);
+#endif //B3_ALWAYS_INITIALIZE_OPENCL_BUFFERS
+
+ if (result)
+ {
+ if (copyOldContents)
+ copyToCL(buf, size());
+ }
+
+ //deallocate the old buffer
+ deallocate();
+
+ m_clBuffer = buf;
+
+ m_capacity = _Count;
+ } else
+ {
+ //fail: assert and
+ b3Assert(0);
+ deallocate();
+ result=false;
+ }
+ }
+ return result;
+ }
+
+
+ void copyToCL(cl_mem destination, size_t numElements, size_t firstElem=0, size_t dstOffsetInElems=0) const
+ {
+ if (numElements<=0)
+ return;
+
+ b3Assert(m_clBuffer);
+ b3Assert(destination);
+
+ //likely some error, destination is same as source
+ b3Assert(m_clBuffer != destination);
+
+ b3Assert((firstElem+numElements)<=m_size);
+
+ cl_int status = 0;
+
+
+ b3Assert(numElements>0);
+ b3Assert(numElements<=m_size);
+
+ size_t srcOffsetBytes = sizeof(T)*firstElem;
+ size_t dstOffsetInBytes = sizeof(T)*dstOffsetInElems;
+
+ status = clEnqueueCopyBuffer( m_commandQueue, m_clBuffer, destination,
+ srcOffsetBytes, dstOffsetInBytes, sizeof(T)*numElements, 0, 0, 0 );
+
+ b3Assert( status == CL_SUCCESS );
+ }
+
+ void copyFromHost(const b3AlignedObjectArray<T>& srcArray, bool waitForCompletion=true)
+ {
+ size_t newSize = srcArray.size();
+
+ bool copyOldContents = false;
+ resize (newSize,copyOldContents);
+ if (newSize)
+ copyFromHostPointer(&srcArray[0],newSize,0,waitForCompletion);
+
+ }
+
+ void copyFromHostPointer(const T* src, size_t numElems, size_t destFirstElem= 0, bool waitForCompletion=true)
+ {
+ b3Assert(numElems+destFirstElem <= capacity());
+
+ if (numElems+destFirstElem)
+ {
+ cl_int status = 0;
+ size_t sizeInBytes=sizeof(T)*numElems;
+ status = clEnqueueWriteBuffer( m_commandQueue, m_clBuffer, 0, sizeof(T)*destFirstElem, sizeInBytes,
+ src, 0,0,0 );
+ b3Assert(status == CL_SUCCESS );
+ if (waitForCompletion)
+ clFinish(m_commandQueue);
+ } else
+ {
+ b3Error("copyFromHostPointer invalid range\n");
+ }
+ }
+
+
+ void copyToHost(b3AlignedObjectArray<T>& destArray, bool waitForCompletion=true) const
+ {
+ destArray.resize(this->size());
+ if (size())
+ copyToHostPointer(&destArray[0], size(),0,waitForCompletion);
+ }
+
+ void copyToHostPointer(T* destPtr, size_t numElem, size_t srcFirstElem=0, bool waitForCompletion=true) const
+ {
+ b3Assert(numElem+srcFirstElem <= capacity());
+
+ if(numElem+srcFirstElem <= capacity())
+ {
+ cl_int status = 0;
+ status = clEnqueueReadBuffer( m_commandQueue, m_clBuffer, 0, sizeof(T)*srcFirstElem, sizeof(T)*numElem,
+ destPtr, 0,0,0 );
+ b3Assert( status==CL_SUCCESS );
+
+ if (waitForCompletion)
+ clFinish(m_commandQueue);
+ } else
+ {
+ b3Error("copyToHostPointer invalid range\n");
+ }
+ }
+
+ void copyFromOpenCLArray(const b3OpenCLArray& src)
+ {
+ size_t newSize = src.size();
+ resize(newSize);
+ if (size())
+ {
+ src.copyToCL(m_clBuffer,size());
+ }
+ }
+
+};
+
+
+#endif //B3_OPENCL_ARRAY_H
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanCL.cpp b/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanCL.cpp
new file mode 100644
index 0000000000..42cd197740
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanCL.cpp
@@ -0,0 +1,126 @@
+#include "b3PrefixScanCL.h"
+#include "b3FillCL.h"
+#define B3_PREFIXSCAN_PROG_PATH "src/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanKernels.cl"
+
+#include "b3LauncherCL.h"
+#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
+#include "kernels/PrefixScanKernelsCL.h"
+
+b3PrefixScanCL::b3PrefixScanCL(cl_context ctx, cl_device_id device, cl_command_queue queue, int size)
+:m_commandQueue(queue)
+{
+ const char* scanKernelSource = prefixScanKernelsCL;
+ cl_int pErrNum;
+ char* additionalMacros=0;
+
+ m_workBuffer = new b3OpenCLArray<unsigned int>(ctx,queue,size);
+ cl_program scanProg = b3OpenCLUtils::compileCLProgramFromString( ctx, device, scanKernelSource, &pErrNum,additionalMacros, B3_PREFIXSCAN_PROG_PATH);
+ b3Assert(scanProg);
+
+ m_localScanKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, scanKernelSource, "LocalScanKernel", &pErrNum, scanProg,additionalMacros );
+ b3Assert(m_localScanKernel );
+ m_blockSumKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, scanKernelSource, "TopLevelScanKernel", &pErrNum, scanProg,additionalMacros );
+ b3Assert(m_blockSumKernel );
+ m_propagationKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, scanKernelSource, "AddOffsetKernel", &pErrNum, scanProg,additionalMacros );
+ b3Assert(m_propagationKernel );
+}
+
+
+b3PrefixScanCL::~b3PrefixScanCL()
+{
+ delete m_workBuffer;
+ clReleaseKernel(m_localScanKernel);
+ clReleaseKernel(m_blockSumKernel);
+ clReleaseKernel(m_propagationKernel);
+}
+
+template<class T>
+T b3NextPowerOf2(T n)
+{
+ n -= 1;
+ for(int i=0; i<sizeof(T)*8; i++)
+ n = n | (n>>i);
+ return n+1;
+}
+
+void b3PrefixScanCL::execute(b3OpenCLArray<unsigned int>& src, b3OpenCLArray<unsigned int>& dst, int n, unsigned int* sum)
+{
+
+// b3Assert( data->m_option == EXCLUSIVE );
+ const unsigned int numBlocks = (const unsigned int)( (n+BLOCK_SIZE*2-1)/(BLOCK_SIZE*2) );
+
+ dst.resize(src.size());
+ m_workBuffer->resize(src.size());
+
+ b3Int4 constBuffer;
+ constBuffer.x = n;
+ constBuffer.y = numBlocks;
+ constBuffer.z = (int)b3NextPowerOf2( numBlocks );
+
+ b3OpenCLArray<unsigned int>* srcNative = &src;
+ b3OpenCLArray<unsigned int>* dstNative = &dst;
+
+ {
+ b3BufferInfoCL bInfo[] = { b3BufferInfoCL( dstNative->getBufferCL() ), b3BufferInfoCL( srcNative->getBufferCL() ), b3BufferInfoCL( m_workBuffer->getBufferCL() ) };
+
+ b3LauncherCL launcher( m_commandQueue, m_localScanKernel,"m_localScanKernel" );
+ launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst( constBuffer );
+ launcher.launch1D( numBlocks*BLOCK_SIZE, BLOCK_SIZE );
+ }
+
+ {
+ b3BufferInfoCL bInfo[] = { b3BufferInfoCL( m_workBuffer->getBufferCL() ) };
+
+ b3LauncherCL launcher( m_commandQueue, m_blockSumKernel,"m_blockSumKernel" );
+ launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst( constBuffer );
+ launcher.launch1D( BLOCK_SIZE, BLOCK_SIZE );
+ }
+
+
+ if( numBlocks > 1 )
+ {
+ b3BufferInfoCL bInfo[] = { b3BufferInfoCL( dstNative->getBufferCL() ), b3BufferInfoCL( m_workBuffer->getBufferCL() ) };
+ b3LauncherCL launcher( m_commandQueue, m_propagationKernel,"m_propagationKernel" );
+ launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst( constBuffer );
+ launcher.launch1D( (numBlocks-1)*BLOCK_SIZE, BLOCK_SIZE );
+ }
+
+
+ if( sum )
+ {
+ clFinish(m_commandQueue);
+ dstNative->copyToHostPointer(sum,1,n-1,true);
+ }
+
+}
+
+
+void b3PrefixScanCL::executeHost(b3AlignedObjectArray<unsigned int>& src, b3AlignedObjectArray<unsigned int>& dst, int n, unsigned int* sum)
+{
+ unsigned int s = 0;
+ //if( data->m_option == EXCLUSIVE )
+ {
+ for(int i=0; i<n; i++)
+ {
+ dst[i] = s;
+ s += src[i];
+ }
+ }
+ /*else
+ {
+ for(int i=0; i<n; i++)
+ {
+ s += hSrc[i];
+ hDst[i] = s;
+ }
+ }
+ */
+
+ if( sum )
+ {
+ *sum = dst[n-1];
+ }
+} \ No newline at end of file
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanCL.h b/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanCL.h
new file mode 100644
index 0000000000..a9a2e61b9e
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanCL.h
@@ -0,0 +1,37 @@
+
+#ifndef B3_PREFIX_SCAN_CL_H
+#define B3_PREFIX_SCAN_CL_H
+
+#include "b3OpenCLArray.h"
+#include "b3BufferInfoCL.h"
+#include "Bullet3Common/b3AlignedObjectArray.h"
+
+class b3PrefixScanCL
+{
+ enum
+ {
+ BLOCK_SIZE = 128
+ };
+
+// Option m_option;
+
+ cl_command_queue m_commandQueue;
+
+ cl_kernel m_localScanKernel;
+ cl_kernel m_blockSumKernel;
+ cl_kernel m_propagationKernel;
+
+ b3OpenCLArray<unsigned int>* m_workBuffer;
+
+
+ public:
+
+ b3PrefixScanCL(cl_context ctx, cl_device_id device, cl_command_queue queue,int size=0);
+
+ virtual ~b3PrefixScanCL();
+
+ void execute(b3OpenCLArray<unsigned int>& src, b3OpenCLArray<unsigned int>& dst, int n, unsigned int* sum = 0);
+ void executeHost(b3AlignedObjectArray<unsigned int>& src, b3AlignedObjectArray<unsigned int>& dst, int n, unsigned int* sum=0);
+};
+
+#endif //B3_PREFIX_SCAN_CL_H
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanFloat4CL.cpp b/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanFloat4CL.cpp
new file mode 100644
index 0000000000..80560d793d
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanFloat4CL.cpp
@@ -0,0 +1,126 @@
+#include "b3PrefixScanFloat4CL.h"
+#include "b3FillCL.h"
+#define B3_PREFIXSCAN_FLOAT4_PROG_PATH "src/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanFloat4Kernels.cl"
+
+#include "b3LauncherCL.h"
+#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
+#include "kernels/PrefixScanKernelsFloat4CL.h"
+
+b3PrefixScanFloat4CL::b3PrefixScanFloat4CL(cl_context ctx, cl_device_id device, cl_command_queue queue, int size)
+:m_commandQueue(queue)
+{
+ const char* scanKernelSource = prefixScanKernelsFloat4CL;
+ cl_int pErrNum;
+ char* additionalMacros=0;
+
+ m_workBuffer = new b3OpenCLArray<b3Vector3>(ctx,queue,size);
+ cl_program scanProg = b3OpenCLUtils::compileCLProgramFromString( ctx, device, scanKernelSource, &pErrNum,additionalMacros, B3_PREFIXSCAN_FLOAT4_PROG_PATH);
+ b3Assert(scanProg);
+
+ m_localScanKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, scanKernelSource, "LocalScanKernel", &pErrNum, scanProg,additionalMacros );
+ b3Assert(m_localScanKernel );
+ m_blockSumKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, scanKernelSource, "TopLevelScanKernel", &pErrNum, scanProg,additionalMacros );
+ b3Assert(m_blockSumKernel );
+ m_propagationKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, scanKernelSource, "AddOffsetKernel", &pErrNum, scanProg,additionalMacros );
+ b3Assert(m_propagationKernel );
+}
+
+
+b3PrefixScanFloat4CL::~b3PrefixScanFloat4CL()
+{
+ delete m_workBuffer;
+ clReleaseKernel(m_localScanKernel);
+ clReleaseKernel(m_blockSumKernel);
+ clReleaseKernel(m_propagationKernel);
+}
+
+template<class T>
+T b3NextPowerOf2(T n)
+{
+ n -= 1;
+ for(int i=0; i<sizeof(T)*8; i++)
+ n = n | (n>>i);
+ return n+1;
+}
+
+void b3PrefixScanFloat4CL::execute(b3OpenCLArray<b3Vector3>& src, b3OpenCLArray<b3Vector3>& dst, int n, b3Vector3* sum)
+{
+
+// b3Assert( data->m_option == EXCLUSIVE );
+ const unsigned int numBlocks = (const unsigned int)( (n+BLOCK_SIZE*2-1)/(BLOCK_SIZE*2) );
+
+ dst.resize(src.size());
+ m_workBuffer->resize(src.size());
+
+ b3Int4 constBuffer;
+ constBuffer.x = n;
+ constBuffer.y = numBlocks;
+ constBuffer.z = (int)b3NextPowerOf2( numBlocks );
+
+ b3OpenCLArray<b3Vector3>* srcNative = &src;
+ b3OpenCLArray<b3Vector3>* dstNative = &dst;
+
+ {
+ b3BufferInfoCL bInfo[] = { b3BufferInfoCL( dstNative->getBufferCL() ), b3BufferInfoCL( srcNative->getBufferCL() ), b3BufferInfoCL( m_workBuffer->getBufferCL() ) };
+
+ b3LauncherCL launcher( m_commandQueue, m_localScanKernel ,"m_localScanKernel");
+ launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst( constBuffer );
+ launcher.launch1D( numBlocks*BLOCK_SIZE, BLOCK_SIZE );
+ }
+
+ {
+ b3BufferInfoCL bInfo[] = { b3BufferInfoCL( m_workBuffer->getBufferCL() ) };
+
+ b3LauncherCL launcher( m_commandQueue, m_blockSumKernel ,"m_blockSumKernel");
+ launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst( constBuffer );
+ launcher.launch1D( BLOCK_SIZE, BLOCK_SIZE );
+ }
+
+
+ if( numBlocks > 1 )
+ {
+ b3BufferInfoCL bInfo[] = { b3BufferInfoCL( dstNative->getBufferCL() ), b3BufferInfoCL( m_workBuffer->getBufferCL() ) };
+ b3LauncherCL launcher( m_commandQueue, m_propagationKernel ,"m_propagationKernel");
+ launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst( constBuffer );
+ launcher.launch1D( (numBlocks-1)*BLOCK_SIZE, BLOCK_SIZE );
+ }
+
+
+ if( sum )
+ {
+ clFinish(m_commandQueue);
+ dstNative->copyToHostPointer(sum,1,n-1,true);
+ }
+
+}
+
+
+void b3PrefixScanFloat4CL::executeHost(b3AlignedObjectArray<b3Vector3>& src, b3AlignedObjectArray<b3Vector3>& dst, int n, b3Vector3* sum)
+{
+ b3Vector3 s=b3MakeVector3(0,0,0);
+ //if( data->m_option == EXCLUSIVE )
+ {
+ for(int i=0; i<n; i++)
+ {
+ dst[i] = s;
+ s += src[i];
+ }
+ }
+ /*else
+ {
+ for(int i=0; i<n; i++)
+ {
+ s += hSrc[i];
+ hDst[i] = s;
+ }
+ }
+ */
+
+ if( sum )
+ {
+ *sum = dst[n-1];
+ }
+} \ No newline at end of file
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanFloat4CL.h b/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanFloat4CL.h
new file mode 100644
index 0000000000..2c8003c1bb
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanFloat4CL.h
@@ -0,0 +1,38 @@
+
+#ifndef B3_PREFIX_SCAN_CL_H
+#define B3_PREFIX_SCAN_CL_H
+
+#include "b3OpenCLArray.h"
+#include "b3BufferInfoCL.h"
+#include "Bullet3Common/b3AlignedObjectArray.h"
+#include "Bullet3Common/b3Vector3.h"
+
+class b3PrefixScanFloat4CL
+{
+ enum
+ {
+ BLOCK_SIZE = 128
+ };
+
+// Option m_option;
+
+ cl_command_queue m_commandQueue;
+
+ cl_kernel m_localScanKernel;
+ cl_kernel m_blockSumKernel;
+ cl_kernel m_propagationKernel;
+
+ b3OpenCLArray<b3Vector3>* m_workBuffer;
+
+
+ public:
+
+ b3PrefixScanFloat4CL(cl_context ctx, cl_device_id device, cl_command_queue queue,int size=0);
+
+ virtual ~b3PrefixScanFloat4CL();
+
+ void execute(b3OpenCLArray<b3Vector3>& src, b3OpenCLArray<b3Vector3>& dst, int n, b3Vector3* sum = 0);
+ void executeHost(b3AlignedObjectArray<b3Vector3>& src, b3AlignedObjectArray<b3Vector3>& dst, int n, b3Vector3* sum);
+};
+
+#endif //B3_PREFIX_SCAN_CL_H
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.cpp b/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.cpp
new file mode 100644
index 0000000000..f11ae4bcdb
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.cpp
@@ -0,0 +1,710 @@
+
+#include "b3RadixSort32CL.h"
+#include "b3LauncherCL.h"
+#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
+#include "b3PrefixScanCL.h"
+#include "b3FillCL.h"
+
+#define RADIXSORT32_PATH "src/Bullet3OpenCL/ParallelPrimitives/kernels/RadixSort32Kernels.cl"
+
+#include "kernels/RadixSort32KernelsCL.h"
+
+b3RadixSort32CL::b3RadixSort32CL(cl_context ctx, cl_device_id device, cl_command_queue queue, int initialCapacity)
+:m_commandQueue(queue)
+{
+ b3OpenCLDeviceInfo info;
+ b3OpenCLUtils::getDeviceInfo(device,&info);
+ m_deviceCPU = (info.m_deviceType & CL_DEVICE_TYPE_CPU)!=0;
+
+ m_workBuffer1 = new b3OpenCLArray<unsigned int>(ctx,queue);
+ m_workBuffer2 = new b3OpenCLArray<unsigned int>(ctx,queue);
+ m_workBuffer3 = new b3OpenCLArray<b3SortData>(ctx,queue);
+ m_workBuffer3a = new b3OpenCLArray<unsigned int>(ctx,queue);
+ m_workBuffer4 = new b3OpenCLArray<b3SortData>(ctx,queue);
+ m_workBuffer4a = new b3OpenCLArray<unsigned int>(ctx,queue);
+
+
+ if (initialCapacity>0)
+ {
+ m_workBuffer1->resize(initialCapacity);
+ m_workBuffer3->resize(initialCapacity);
+ m_workBuffer3a->resize(initialCapacity);
+ m_workBuffer4->resize(initialCapacity);
+ m_workBuffer4a->resize(initialCapacity);
+ }
+
+ m_scan = new b3PrefixScanCL(ctx,device,queue);
+ m_fill = new b3FillCL(ctx,device,queue);
+
+ const char* additionalMacros = "";
+
+ cl_int pErrNum;
+ const char* kernelSource = radixSort32KernelsCL;
+
+ cl_program sortProg = b3OpenCLUtils::compileCLProgramFromString( ctx, device, kernelSource, &pErrNum,additionalMacros, RADIXSORT32_PATH);
+ b3Assert(sortProg);
+
+ m_streamCountSortDataKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, kernelSource, "StreamCountSortDataKernel", &pErrNum, sortProg,additionalMacros );
+ b3Assert(m_streamCountSortDataKernel );
+
+
+
+ m_streamCountKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, kernelSource, "StreamCountKernel", &pErrNum, sortProg,additionalMacros );
+ b3Assert(m_streamCountKernel);
+
+
+
+ if (m_deviceCPU)
+ {
+
+ m_sortAndScatterSortDataKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, kernelSource, "SortAndScatterSortDataKernelSerial", &pErrNum, sortProg,additionalMacros );
+ b3Assert(m_sortAndScatterSortDataKernel);
+ m_sortAndScatterKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, kernelSource, "SortAndScatterKernelSerial", &pErrNum, sortProg,additionalMacros );
+ b3Assert(m_sortAndScatterKernel);
+ } else
+ {
+ m_sortAndScatterSortDataKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, kernelSource, "SortAndScatterSortDataKernel", &pErrNum, sortProg,additionalMacros );
+ b3Assert(m_sortAndScatterSortDataKernel);
+ m_sortAndScatterKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, kernelSource, "SortAndScatterKernel", &pErrNum, sortProg,additionalMacros );
+ b3Assert(m_sortAndScatterKernel);
+ }
+
+ m_prefixScanKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, kernelSource, "PrefixScanKernel", &pErrNum, sortProg,additionalMacros );
+ b3Assert(m_prefixScanKernel);
+
+}
+
+b3RadixSort32CL::~b3RadixSort32CL()
+{
+ delete m_scan;
+ delete m_fill;
+ delete m_workBuffer1;
+ delete m_workBuffer2;
+ delete m_workBuffer3;
+ delete m_workBuffer3a;
+ delete m_workBuffer4;
+ delete m_workBuffer4a;
+
+ clReleaseKernel(m_streamCountSortDataKernel);
+ clReleaseKernel(m_streamCountKernel);
+ clReleaseKernel(m_sortAndScatterSortDataKernel);
+ clReleaseKernel(m_sortAndScatterKernel);
+ clReleaseKernel(m_prefixScanKernel);
+}
+
+void b3RadixSort32CL::executeHost(b3AlignedObjectArray<b3SortData>& inout, int sortBits /* = 32 */)
+{
+ int n = inout.size();
+ const int BITS_PER_PASS = 8;
+ const int NUM_TABLES = (1<<BITS_PER_PASS);
+
+
+ int tables[NUM_TABLES];
+ int counter[NUM_TABLES];
+
+ b3SortData* src = &inout[0];
+ b3AlignedObjectArray<b3SortData> workbuffer;
+ workbuffer.resize(inout.size());
+ b3SortData* dst = &workbuffer[0];
+
+ int count=0;
+ for(int startBit=0; startBit<sortBits; startBit+=BITS_PER_PASS)
+ {
+ for(int i=0; i<NUM_TABLES; i++)
+ {
+ tables[i] = 0;
+ }
+
+ for(int i=0; i<n; i++)
+ {
+ int tableIdx = (src[i].m_key >> startBit) & (NUM_TABLES-1);
+ tables[tableIdx]++;
+ }
+//#define TEST
+#ifdef TEST
+ printf("histogram size=%d\n",NUM_TABLES);
+ for (int i=0;i<NUM_TABLES;i++)
+ {
+ if (tables[i]!=0)
+ {
+ printf("tables[%d]=%d]\n",i,tables[i]);
+ }
+
+ }
+#endif //TEST
+ // prefix scan
+ int sum = 0;
+ for(int i=0; i<NUM_TABLES; i++)
+ {
+ int iData = tables[i];
+ tables[i] = sum;
+ sum += iData;
+ counter[i] = 0;
+ }
+
+ // distribute
+ for(int i=0; i<n; i++)
+ {
+ int tableIdx = (src[i].m_key >> startBit) & (NUM_TABLES-1);
+
+ dst[tables[tableIdx] + counter[tableIdx]] = src[i];
+ counter[tableIdx] ++;
+ }
+
+ b3Swap( src, dst );
+ count++;
+ }
+
+ if (count&1)
+ {
+ b3Assert(0);//need to copy
+
+ }
+}
+
+void b3RadixSort32CL::executeHost(b3OpenCLArray<b3SortData>& keyValuesInOut, int sortBits /* = 32 */)
+{
+
+ b3AlignedObjectArray<b3SortData> inout;
+ keyValuesInOut.copyToHost(inout);
+
+ executeHost(inout,sortBits);
+
+ keyValuesInOut.copyFromHost(inout);
+}
+
+void b3RadixSort32CL::execute(b3OpenCLArray<unsigned int>& keysIn, b3OpenCLArray<unsigned int>& keysOut, b3OpenCLArray<unsigned int>& valuesIn,
+ b3OpenCLArray<unsigned int>& valuesOut, int n, int sortBits)
+{
+
+}
+
+//#define DEBUG_RADIXSORT
+//#define DEBUG_RADIXSORT2
+
+
+void b3RadixSort32CL::execute(b3OpenCLArray<b3SortData>& keyValuesInOut, int sortBits /* = 32 */)
+{
+
+ int originalSize = keyValuesInOut.size();
+ int workingSize = originalSize;
+
+
+ int dataAlignment = DATA_ALIGNMENT;
+
+#ifdef DEBUG_RADIXSORT2
+ b3AlignedObjectArray<b3SortData> test2;
+ keyValuesInOut.copyToHost(test2);
+ printf("numElem = %d\n",test2.size());
+ for (int i=0;i<test2.size();i++)
+ {
+ printf("test2[%d].m_key=%d\n",i,test2[i].m_key);
+ printf("test2[%d].m_value=%d\n",i,test2[i].m_value);
+ }
+#endif //DEBUG_RADIXSORT2
+
+ b3OpenCLArray<b3SortData>* src = 0;
+
+ if (workingSize%dataAlignment)
+ {
+ workingSize += dataAlignment-(workingSize%dataAlignment);
+ m_workBuffer4->copyFromOpenCLArray(keyValuesInOut);
+ m_workBuffer4->resize(workingSize);
+ b3SortData fillValue;
+ fillValue.m_key = 0xffffffff;
+ fillValue.m_value = 0xffffffff;
+
+#define USE_BTFILL
+#ifdef USE_BTFILL
+ m_fill->execute((b3OpenCLArray<b3Int2>&)*m_workBuffer4,(b3Int2&)fillValue,workingSize-originalSize,originalSize);
+#else
+ //fill the remaining bits (very slow way, todo: fill on GPU/OpenCL side)
+
+ for (int i=originalSize; i<workingSize;i++)
+ {
+ m_workBuffer4->copyFromHostPointer(&fillValue,1,i);
+ }
+#endif//USE_BTFILL
+
+ src = m_workBuffer4;
+ } else
+ {
+ src = &keyValuesInOut;
+ m_workBuffer4->resize(0);
+ }
+
+ b3Assert( workingSize%DATA_ALIGNMENT == 0 );
+ int minCap = NUM_BUCKET*NUM_WGS;
+
+
+ int n = workingSize;
+
+ m_workBuffer1->resize(minCap);
+ m_workBuffer3->resize(workingSize);
+
+
+// ADLASSERT( ELEMENTS_PER_WORK_ITEM == 4 );
+ b3Assert( BITS_PER_PASS == 4 );
+ b3Assert( WG_SIZE == 64 );
+ b3Assert( (sortBits&0x3) == 0 );
+
+
+
+ b3OpenCLArray<b3SortData>* dst = m_workBuffer3;
+
+ b3OpenCLArray<unsigned int>* srcHisto = m_workBuffer1;
+ b3OpenCLArray<unsigned int>* destHisto = m_workBuffer2;
+
+
+ int nWGs = NUM_WGS;
+ b3ConstData cdata;
+
+ {
+ int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE;//set at 256
+ int nBlocks = (n+blockSize-1)/(blockSize);
+ cdata.m_n = n;
+ cdata.m_nWGs = NUM_WGS;
+ cdata.m_startBit = 0;
+ cdata.m_nBlocksPerWG = (nBlocks + cdata.m_nWGs - 1)/cdata.m_nWGs;
+ if( nBlocks < NUM_WGS )
+ {
+ cdata.m_nBlocksPerWG = 1;
+ nWGs = nBlocks;
+ }
+ }
+
+ int count=0;
+ for(int ib=0; ib<sortBits; ib+=4)
+ {
+#ifdef DEBUG_RADIXSORT2
+ keyValuesInOut.copyToHost(test2);
+ printf("numElem = %d\n",test2.size());
+ for (int i=0;i<test2.size();i++)
+ {
+ if (test2[i].m_key != test2[i].m_value)
+ {
+ printf("test2[%d].m_key=%d\n",i,test2[i].m_key);
+ printf("test2[%d].m_value=%d\n",i,test2[i].m_value);
+ }
+ }
+#endif //DEBUG_RADIXSORT2
+
+ cdata.m_startBit = ib;
+
+ if (src->size())
+ {
+ b3BufferInfoCL bInfo[] = { b3BufferInfoCL( src->getBufferCL(), true ), b3BufferInfoCL( srcHisto->getBufferCL() ) };
+ b3LauncherCL launcher(m_commandQueue, m_streamCountSortDataKernel,"m_streamCountSortDataKernel");
+
+ launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst( cdata );
+
+ int num = NUM_WGS*WG_SIZE;
+ launcher.launch1D( num, WG_SIZE );
+ }
+
+
+
+#ifdef DEBUG_RADIXSORT
+ b3AlignedObjectArray<unsigned int> testHist;
+ srcHisto->copyToHost(testHist);
+ printf("ib = %d, testHist size = %d, non zero elements:\n",ib, testHist.size());
+ for (int i=0;i<testHist.size();i++)
+ {
+ if (testHist[i]!=0)
+ printf("testHist[%d]=%d\n",i,testHist[i]);
+ }
+#endif //DEBUG_RADIXSORT
+
+
+
+//fast prefix scan is not working properly on Mac OSX yet
+#ifdef __APPLE__
+ bool fastScan=false;
+#else
+ bool fastScan=!m_deviceCPU;//only use fast scan on GPU
+#endif
+
+ if (fastScan)
+ {// prefix scan group histogram
+ b3BufferInfoCL bInfo[] = { b3BufferInfoCL( srcHisto->getBufferCL() ) };
+ b3LauncherCL launcher( m_commandQueue, m_prefixScanKernel,"m_prefixScanKernel" );
+ launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst( cdata );
+ launcher.launch1D( 128, 128 );
+ destHisto = srcHisto;
+ }else
+ {
+ //unsigned int sum; //for debugging
+ m_scan->execute(*srcHisto,*destHisto,1920,0);//,&sum);
+ }
+
+
+#ifdef DEBUG_RADIXSORT
+ destHisto->copyToHost(testHist);
+ printf("ib = %d, testHist size = %d, non zero elements:\n",ib, testHist.size());
+ for (int i=0;i<testHist.size();i++)
+ {
+ if (testHist[i]!=0)
+ printf("testHist[%d]=%d\n",i,testHist[i]);
+ }
+
+ for (int i=0;i<testHist.size();i+=NUM_WGS)
+ {
+ printf("testHist[%d]=%d\n",i/NUM_WGS,testHist[i]);
+ }
+
+#endif //DEBUG_RADIXSORT
+
+#define USE_GPU
+#ifdef USE_GPU
+
+ if (src->size())
+ {// local sort and distribute
+ b3BufferInfoCL bInfo[] = { b3BufferInfoCL( src->getBufferCL(), true ), b3BufferInfoCL( destHisto->getBufferCL(), true ), b3BufferInfoCL( dst->getBufferCL() )};
+ b3LauncherCL launcher( m_commandQueue, m_sortAndScatterSortDataKernel,"m_sortAndScatterSortDataKernel" );
+ launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst( cdata );
+ launcher.launch1D( nWGs*WG_SIZE, WG_SIZE );
+
+ }
+#else
+ {
+#define NUM_TABLES 16
+//#define SEQUENTIAL
+#ifdef SEQUENTIAL
+ int counter2[NUM_TABLES]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+ int tables[NUM_TABLES];
+ int startBit = ib;
+
+ destHisto->copyToHost(testHist);
+ b3AlignedObjectArray<b3SortData> srcHost;
+ b3AlignedObjectArray<b3SortData> dstHost;
+ dstHost.resize(src->size());
+
+ src->copyToHost(srcHost);
+
+ for (int i=0;i<NUM_TABLES;i++)
+ {
+ tables[i] = testHist[i*NUM_WGS];
+ }
+
+ // distribute
+ for(int i=0; i<n; i++)
+ {
+ int tableIdx = (srcHost[i].m_key >> startBit) & (NUM_TABLES-1);
+
+ dstHost[tables[tableIdx] + counter2[tableIdx]] = srcHost[i];
+ counter2[tableIdx] ++;
+ }
+
+
+#else
+
+ int counter2[NUM_TABLES]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+
+ int tables[NUM_TABLES];
+ b3AlignedObjectArray<b3SortData> dstHostOK;
+ dstHostOK.resize(src->size());
+
+ destHisto->copyToHost(testHist);
+ b3AlignedObjectArray<b3SortData> srcHost;
+ src->copyToHost(srcHost);
+
+ int blockSize = 256;
+ int nBlocksPerWG = cdata.m_nBlocksPerWG;
+ int startBit = ib;
+
+ {
+ for (int i=0;i<NUM_TABLES;i++)
+ {
+ tables[i] = testHist[i*NUM_WGS];
+ }
+
+ // distribute
+ for(int i=0; i<n; i++)
+ {
+ int tableIdx = (srcHost[i].m_key >> startBit) & (NUM_TABLES-1);
+
+ dstHostOK[tables[tableIdx] + counter2[tableIdx]] = srcHost[i];
+ counter2[tableIdx] ++;
+ }
+
+
+ }
+
+
+ b3AlignedObjectArray<b3SortData> dstHost;
+ dstHost.resize(src->size());
+
+
+ int counter[NUM_TABLES]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+
+
+
+ for (int wgIdx=0;wgIdx<NUM_WGS;wgIdx++)
+ {
+ int counter[NUM_TABLES]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+
+ int nBlocks = (n)/blockSize - nBlocksPerWG*wgIdx;
+
+ for(int iblock=0; iblock<b3Min(cdata.m_nBlocksPerWG, nBlocks); iblock++)
+ {
+ for (int lIdx = 0;lIdx < 64;lIdx++)
+ {
+ int addr = iblock*blockSize + blockSize*cdata.m_nBlocksPerWG*wgIdx + ELEMENTS_PER_WORK_ITEM*lIdx;
+
+ // MY_HISTOGRAM( localKeys.x ) ++ is much expensive than atomic add as it requires read and write while atomics can just add on AMD
+ // Using registers didn't perform well. It seems like use localKeys to address requires a lot of alu ops
+ // AMD: AtomInc performs better while NV prefers ++
+ for(int j=0; j<ELEMENTS_PER_WORK_ITEM; j++)
+ {
+ if( addr+j < n )
+ {
+ // printf ("addr+j=%d\n", addr+j);
+
+ int i = addr+j;
+
+ int tableIdx = (srcHost[i].m_key >> startBit) & (NUM_TABLES-1);
+
+ int destIndex = testHist[tableIdx*NUM_WGS+wgIdx] + counter[tableIdx];
+
+ b3SortData ok = dstHostOK[destIndex];
+
+ if (ok.m_key != srcHost[i].m_key)
+ {
+ printf("ok.m_key = %d, srcHost[i].m_key = %d\n", ok.m_key,srcHost[i].m_key );
+ printf("(ok.m_value = %d, srcHost[i].m_value = %d)\n", ok.m_value,srcHost[i].m_value );
+ }
+ if (ok.m_value != srcHost[i].m_value)
+ {
+
+ printf("ok.m_value = %d, srcHost[i].m_value = %d\n", ok.m_value,srcHost[i].m_value );
+ printf("(ok.m_key = %d, srcHost[i].m_key = %d)\n", ok.m_key,srcHost[i].m_key );
+
+ }
+
+ dstHost[destIndex] = srcHost[i];
+ counter[tableIdx] ++;
+
+ }
+ }
+ }
+ }
+ }
+
+
+#endif //SEQUENTIAL
+
+ dst->copyFromHost(dstHost);
+ }
+#endif//USE_GPU
+
+
+
+#ifdef DEBUG_RADIXSORT
+ destHisto->copyToHost(testHist);
+ printf("ib = %d, testHist size = %d, non zero elements:\n",ib, testHist.size());
+ for (int i=0;i<testHist.size();i++)
+ {
+ if (testHist[i]!=0)
+ printf("testHist[%d]=%d\n",i,testHist[i]);
+ }
+#endif //DEBUG_RADIXSORT
+ b3Swap(src, dst );
+ b3Swap(srcHisto,destHisto);
+
+#ifdef DEBUG_RADIXSORT2
+ keyValuesInOut.copyToHost(test2);
+ printf("numElem = %d\n",test2.size());
+ for (int i=0;i<test2.size();i++)
+ {
+ if (test2[i].m_key != test2[i].m_value)
+ {
+ printf("test2[%d].m_key=%d\n",i,test2[i].m_key);
+ printf("test2[%d].m_value=%d\n",i,test2[i].m_value);
+ }
+ }
+#endif //DEBUG_RADIXSORT2
+
+ count++;
+
+
+ }
+
+
+
+ if (count&1)
+ {
+ b3Assert(0);//need to copy from workbuffer to keyValuesInOut
+ }
+
+ if (m_workBuffer4->size())
+ {
+ m_workBuffer4->resize(originalSize);
+ keyValuesInOut.copyFromOpenCLArray(*m_workBuffer4);
+ }
+
+
+#ifdef DEBUG_RADIXSORT
+ keyValuesInOut.copyToHost(test2);
+
+ printf("numElem = %d\n",test2.size());
+ for (int i=0;i<test2.size();i++)
+ {
+ printf("test2[%d].m_key=%d\n",i,test2[i].m_key);
+ printf("test2[%d].m_value=%d\n",i,test2[i].m_value);
+ }
+#endif
+
+}
+
+
+
+
+
+
+void b3RadixSort32CL::execute(b3OpenCLArray<unsigned int>& keysInOut, int sortBits /* = 32 */)
+{
+ int originalSize = keysInOut.size();
+ int workingSize = originalSize;
+
+
+ int dataAlignment = DATA_ALIGNMENT;
+
+ b3OpenCLArray<unsigned int>* src = 0;
+
+ if (workingSize%dataAlignment)
+ {
+ workingSize += dataAlignment-(workingSize%dataAlignment);
+ m_workBuffer4a->copyFromOpenCLArray(keysInOut);
+ m_workBuffer4a->resize(workingSize);
+ unsigned int fillValue = 0xffffffff;
+
+ m_fill->execute(*m_workBuffer4a,fillValue,workingSize-originalSize,originalSize);
+
+ src = m_workBuffer4a;
+ } else
+ {
+ src = &keysInOut;
+ m_workBuffer4a->resize(0);
+ }
+
+
+
+ b3Assert( workingSize%DATA_ALIGNMENT == 0 );
+ int minCap = NUM_BUCKET*NUM_WGS;
+
+
+ int n = workingSize;
+
+
+ m_workBuffer1->resize(minCap);
+ m_workBuffer3->resize(workingSize);
+ m_workBuffer3a->resize(workingSize);
+
+// ADLASSERT( ELEMENTS_PER_WORK_ITEM == 4 );
+ b3Assert( BITS_PER_PASS == 4 );
+ b3Assert( WG_SIZE == 64 );
+ b3Assert( (sortBits&0x3) == 0 );
+
+
+
+ b3OpenCLArray<unsigned int>* dst = m_workBuffer3a;
+
+ b3OpenCLArray<unsigned int>* srcHisto = m_workBuffer1;
+ b3OpenCLArray<unsigned int>* destHisto = m_workBuffer2;
+
+
+ int nWGs = NUM_WGS;
+ b3ConstData cdata;
+
+ {
+ int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE;//set at 256
+ int nBlocks = (n+blockSize-1)/(blockSize);
+ cdata.m_n = n;
+ cdata.m_nWGs = NUM_WGS;
+ cdata.m_startBit = 0;
+ cdata.m_nBlocksPerWG = (nBlocks + cdata.m_nWGs - 1)/cdata.m_nWGs;
+ if( nBlocks < NUM_WGS )
+ {
+ cdata.m_nBlocksPerWG = 1;
+ nWGs = nBlocks;
+ }
+ }
+
+ int count=0;
+ for(int ib=0; ib<sortBits; ib+=4)
+ {
+ cdata.m_startBit = ib;
+
+ if (src->size())
+ {
+ b3BufferInfoCL bInfo[] = { b3BufferInfoCL( src->getBufferCL(), true ), b3BufferInfoCL( srcHisto->getBufferCL() ) };
+ b3LauncherCL launcher(m_commandQueue, m_streamCountKernel,"m_streamCountKernel");
+
+ launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst( cdata );
+
+ int num = NUM_WGS*WG_SIZE;
+ launcher.launch1D( num, WG_SIZE );
+ }
+
+
+
+//fast prefix scan is not working properly on Mac OSX yet
+#ifdef __APPLE__
+ bool fastScan=false;
+#else
+ bool fastScan=!m_deviceCPU;
+#endif
+
+ if (fastScan)
+ {// prefix scan group histogram
+ b3BufferInfoCL bInfo[] = { b3BufferInfoCL( srcHisto->getBufferCL() ) };
+ b3LauncherCL launcher( m_commandQueue, m_prefixScanKernel,"m_prefixScanKernel" );
+ launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst( cdata );
+ launcher.launch1D( 128, 128 );
+ destHisto = srcHisto;
+ }else
+ {
+ //unsigned int sum; //for debugging
+ m_scan->execute(*srcHisto,*destHisto,1920,0);//,&sum);
+ }
+
+ if (src->size())
+ {// local sort and distribute
+ b3BufferInfoCL bInfo[] = { b3BufferInfoCL( src->getBufferCL(), true ), b3BufferInfoCL( destHisto->getBufferCL(), true ), b3BufferInfoCL( dst->getBufferCL() )};
+ b3LauncherCL launcher( m_commandQueue, m_sortAndScatterKernel ,"m_sortAndScatterKernel");
+ launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst( cdata );
+ launcher.launch1D( nWGs*WG_SIZE, WG_SIZE );
+
+ }
+
+ b3Swap(src, dst );
+ b3Swap(srcHisto,destHisto);
+
+ count++;
+ }
+
+ if (count&1)
+ {
+ b3Assert(0);//need to copy from workbuffer to keyValuesInOut
+ }
+
+ if (m_workBuffer4a->size())
+ {
+ m_workBuffer4a->resize(originalSize);
+ keysInOut.copyFromOpenCLArray(*m_workBuffer4a);
+ }
+
+}
+
+
+
+
+
+
+
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.h b/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.h
new file mode 100644
index 0000000000..975bd80e53
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.h
@@ -0,0 +1,95 @@
+
+#ifndef B3_RADIXSORT32_H
+#define B3_RADIXSORT32_H
+
+#include "b3OpenCLArray.h"
+
+struct b3SortData
+{
+ union
+ {
+ unsigned int m_key;
+ unsigned int x;
+ };
+
+ union
+ {
+ unsigned int m_value;
+ unsigned int y;
+
+ };
+};
+#include "b3BufferInfoCL.h"
+
+class b3RadixSort32CL
+{
+
+ b3OpenCLArray<unsigned int>* m_workBuffer1;
+ b3OpenCLArray<unsigned int>* m_workBuffer2;
+
+ b3OpenCLArray<b3SortData>* m_workBuffer3;
+ b3OpenCLArray<b3SortData>* m_workBuffer4;
+
+ b3OpenCLArray<unsigned int>* m_workBuffer3a;
+ b3OpenCLArray<unsigned int>* m_workBuffer4a;
+
+ cl_command_queue m_commandQueue;
+
+ cl_kernel m_streamCountSortDataKernel;
+ cl_kernel m_streamCountKernel;
+
+ cl_kernel m_prefixScanKernel;
+ cl_kernel m_sortAndScatterSortDataKernel;
+ cl_kernel m_sortAndScatterKernel;
+
+
+ bool m_deviceCPU;
+
+ class b3PrefixScanCL* m_scan;
+ class b3FillCL* m_fill;
+
+public:
+ struct b3ConstData
+ {
+ int m_n;
+ int m_nWGs;
+ int m_startBit;
+ int m_nBlocksPerWG;
+ };
+ enum
+ {
+ DATA_ALIGNMENT = 256,
+ WG_SIZE = 64,
+ BLOCK_SIZE = 256,
+ ELEMENTS_PER_WORK_ITEM = (BLOCK_SIZE/WG_SIZE),
+ BITS_PER_PASS = 4,
+ NUM_BUCKET=(1<<BITS_PER_PASS),
+ // if you change this, change nPerWI in kernel as well
+ NUM_WGS = 20*6, // cypress
+// NUM_WGS = 24*6, // cayman
+// NUM_WGS = 32*4, // nv
+ };
+
+
+private:
+
+
+public:
+
+ b3RadixSort32CL(cl_context ctx, cl_device_id device, cl_command_queue queue, int initialCapacity =0);
+
+ virtual ~b3RadixSort32CL();
+
+ void execute(b3OpenCLArray<unsigned int>& keysIn, b3OpenCLArray<unsigned int>& keysOut, b3OpenCLArray<unsigned int>& valuesIn,
+ b3OpenCLArray<unsigned int>& valuesOut, int n, int sortBits = 32);
+
+ ///keys only
+ void execute(b3OpenCLArray<unsigned int>& keysInOut, int sortBits = 32 );
+
+ void execute(b3OpenCLArray<b3SortData>& keyValuesInOut, int sortBits = 32 );
+ void executeHost(b3OpenCLArray<b3SortData>& keyValuesInOut, int sortBits = 32);
+ void executeHost(b3AlignedObjectArray<b3SortData>& keyValuesInOut, int sortBits = 32);
+
+};
+#endif //B3_RADIXSORT32_H
+
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/kernels/BoundSearchKernels.cl b/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/kernels/BoundSearchKernels.cl
new file mode 100644
index 0000000000..f3b4a1e8a7
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/kernels/BoundSearchKernels.cl
@@ -0,0 +1,106 @@
+/*
+Copyright (c) 2012 Advanced Micro Devices, Inc.
+
+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.
+*/
+//Originally written by Takahiro Harada
+
+
+typedef unsigned int u32;
+#define GET_GROUP_IDX get_group_id(0)
+#define GET_LOCAL_IDX get_local_id(0)
+#define GET_GLOBAL_IDX get_global_id(0)
+#define GET_GROUP_SIZE get_local_size(0)
+#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)
+
+typedef struct
+{
+ u32 m_key;
+ u32 m_value;
+}SortData;
+
+
+
+typedef struct
+{
+ u32 m_nSrc;
+ u32 m_nDst;
+ u32 m_padding[2];
+} ConstBuffer;
+
+
+
+__attribute__((reqd_work_group_size(64,1,1)))
+__kernel
+void SearchSortDataLowerKernel(__global SortData* src, __global u32 *dst,
+ unsigned int nSrc, unsigned int nDst)
+{
+ int gIdx = GET_GLOBAL_IDX;
+
+ if( gIdx < nSrc )
+ {
+ SortData first; first.m_key = (u32)(-1); first.m_value = (u32)(-1);
+ SortData end; end.m_key = nDst; end.m_value = nDst;
+
+ SortData iData = (gIdx==0)? first: src[gIdx-1];
+ SortData jData = (gIdx==nSrc)? end: src[gIdx];
+
+ if( iData.m_key != jData.m_key )
+ {
+// for(u32 k=iData.m_key+1; k<=min(jData.m_key, nDst-1); k++)
+ u32 k = jData.m_key;
+ {
+ dst[k] = gIdx;
+ }
+ }
+ }
+}
+
+
+__attribute__((reqd_work_group_size(64,1,1)))
+__kernel
+void SearchSortDataUpperKernel(__global SortData* src, __global u32 *dst,
+ unsigned int nSrc, unsigned int nDst)
+{
+ int gIdx = GET_GLOBAL_IDX+1;
+
+ if( gIdx < nSrc+1 )
+ {
+ SortData first; first.m_key = 0; first.m_value = 0;
+ SortData end; end.m_key = nDst; end.m_value = nDst;
+
+ SortData iData = src[gIdx-1];
+ SortData jData = (gIdx==nSrc)? end: src[gIdx];
+
+ if( iData.m_key != jData.m_key )
+ {
+ u32 k = iData.m_key;
+ {
+ dst[k] = gIdx;
+ }
+ }
+ }
+}
+
+__attribute__((reqd_work_group_size(64,1,1)))
+__kernel
+void SubtractKernel(__global u32* A, __global u32 *B, __global u32 *C,
+ unsigned int nSrc, unsigned int nDst)
+{
+ int gIdx = GET_GLOBAL_IDX;
+
+
+ if( gIdx < nDst )
+ {
+ C[gIdx] = A[gIdx] - B[gIdx];
+ }
+}
+
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/kernels/BoundSearchKernelsCL.h b/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/kernels/BoundSearchKernelsCL.h
new file mode 100644
index 0000000000..9c9e847138
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/kernels/BoundSearchKernelsCL.h
@@ -0,0 +1,87 @@
+//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
+static const char* boundSearchKernelsCL= \
+"/*\n"
+"Copyright (c) 2012 Advanced Micro Devices, Inc. \n"
+"This software is provided 'as-is', without any express or implied warranty.\n"
+"In no event will the authors be held liable for any damages arising from the use of this software.\n"
+"Permission is granted to anyone to use this software for any purpose, \n"
+"including commercial applications, and to alter it and redistribute it freely, \n"
+"subject to the following restrictions:\n"
+"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.\n"
+"2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
+"3. This notice may not be removed or altered from any source distribution.\n"
+"*/\n"
+"//Originally written by Takahiro Harada\n"
+"typedef unsigned int u32;\n"
+"#define GET_GROUP_IDX get_group_id(0)\n"
+"#define GET_LOCAL_IDX get_local_id(0)\n"
+"#define GET_GLOBAL_IDX get_global_id(0)\n"
+"#define GET_GROUP_SIZE get_local_size(0)\n"
+"#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
+"typedef struct\n"
+"{\n"
+" u32 m_key; \n"
+" u32 m_value;\n"
+"}SortData;\n"
+"typedef struct\n"
+"{\n"
+" u32 m_nSrc;\n"
+" u32 m_nDst;\n"
+" u32 m_padding[2];\n"
+"} ConstBuffer;\n"
+"__attribute__((reqd_work_group_size(64,1,1)))\n"
+"__kernel\n"
+"void SearchSortDataLowerKernel(__global SortData* src, __global u32 *dst, \n"
+" unsigned int nSrc, unsigned int nDst)\n"
+"{\n"
+" int gIdx = GET_GLOBAL_IDX;\n"
+" if( gIdx < nSrc )\n"
+" {\n"
+" SortData first; first.m_key = (u32)(-1); first.m_value = (u32)(-1);\n"
+" SortData end; end.m_key = nDst; end.m_value = nDst;\n"
+" SortData iData = (gIdx==0)? first: src[gIdx-1];\n"
+" SortData jData = (gIdx==nSrc)? end: src[gIdx];\n"
+" if( iData.m_key != jData.m_key )\n"
+" {\n"
+"// for(u32 k=iData.m_key+1; k<=min(jData.m_key, nDst-1); k++)\n"
+" u32 k = jData.m_key;\n"
+" {\n"
+" dst[k] = gIdx;\n"
+" }\n"
+" }\n"
+" }\n"
+"}\n"
+"__attribute__((reqd_work_group_size(64,1,1)))\n"
+"__kernel\n"
+"void SearchSortDataUpperKernel(__global SortData* src, __global u32 *dst, \n"
+" unsigned int nSrc, unsigned int nDst)\n"
+"{\n"
+" int gIdx = GET_GLOBAL_IDX+1;\n"
+" if( gIdx < nSrc+1 )\n"
+" {\n"
+" SortData first; first.m_key = 0; first.m_value = 0;\n"
+" SortData end; end.m_key = nDst; end.m_value = nDst;\n"
+" SortData iData = src[gIdx-1];\n"
+" SortData jData = (gIdx==nSrc)? end: src[gIdx];\n"
+" if( iData.m_key != jData.m_key )\n"
+" {\n"
+" u32 k = iData.m_key;\n"
+" {\n"
+" dst[k] = gIdx;\n"
+" }\n"
+" }\n"
+" }\n"
+"}\n"
+"__attribute__((reqd_work_group_size(64,1,1)))\n"
+"__kernel\n"
+"void SubtractKernel(__global u32* A, __global u32 *B, __global u32 *C, \n"
+" unsigned int nSrc, unsigned int nDst)\n"
+"{\n"
+" int gIdx = GET_GLOBAL_IDX;\n"
+" \n"
+" if( gIdx < nDst )\n"
+" {\n"
+" C[gIdx] = A[gIdx] - B[gIdx];\n"
+" }\n"
+"}\n"
+;
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/kernels/CopyKernels.cl b/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/kernels/CopyKernels.cl
new file mode 100644
index 0000000000..2eee5752ec
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/kernels/CopyKernels.cl
@@ -0,0 +1,128 @@
+/*
+Copyright (c) 2012 Advanced Micro Devices, Inc.
+
+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.
+*/
+//Originally written by Takahiro Harada
+
+#pragma OPENCL EXTENSION cl_amd_printf : enable
+#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable
+
+typedef unsigned int u32;
+#define GET_GROUP_IDX get_group_id(0)
+#define GET_LOCAL_IDX get_local_id(0)
+#define GET_GLOBAL_IDX get_global_id(0)
+#define GET_GROUP_SIZE get_local_size(0)
+#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)
+#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)
+#define AtomInc(x) atom_inc(&(x))
+#define AtomInc1(x, out) out = atom_inc(&(x))
+
+#define make_uint4 (uint4)
+#define make_uint2 (uint2)
+#define make_int2 (int2)
+
+typedef struct
+{
+ int m_n;
+ int m_padding[3];
+} ConstBuffer;
+
+
+
+__kernel
+__attribute__((reqd_work_group_size(64,1,1)))
+void Copy1F4Kernel(__global float4* dst, __global float4* src,
+ ConstBuffer cb)
+{
+ int gIdx = GET_GLOBAL_IDX;
+
+ if( gIdx < cb.m_n )
+ {
+ float4 a0 = src[gIdx];
+
+ dst[ gIdx ] = a0;
+ }
+}
+
+__kernel
+__attribute__((reqd_work_group_size(64,1,1)))
+void Copy2F4Kernel(__global float4* dst, __global float4* src,
+ ConstBuffer cb)
+{
+ int gIdx = GET_GLOBAL_IDX;
+
+ if( 2*gIdx <= cb.m_n )
+ {
+ float4 a0 = src[gIdx*2+0];
+ float4 a1 = src[gIdx*2+1];
+
+ dst[ gIdx*2+0 ] = a0;
+ dst[ gIdx*2+1 ] = a1;
+ }
+}
+
+__kernel
+__attribute__((reqd_work_group_size(64,1,1)))
+void Copy4F4Kernel(__global float4* dst, __global float4* src,
+ ConstBuffer cb)
+{
+ int gIdx = GET_GLOBAL_IDX;
+
+ if( 4*gIdx <= cb.m_n )
+ {
+ int idx0 = gIdx*4+0;
+ int idx1 = gIdx*4+1;
+ int idx2 = gIdx*4+2;
+ int idx3 = gIdx*4+3;
+
+ float4 a0 = src[idx0];
+ float4 a1 = src[idx1];
+ float4 a2 = src[idx2];
+ float4 a3 = src[idx3];
+
+ dst[ idx0 ] = a0;
+ dst[ idx1 ] = a1;
+ dst[ idx2 ] = a2;
+ dst[ idx3 ] = a3;
+ }
+}
+
+__kernel
+__attribute__((reqd_work_group_size(64,1,1)))
+void CopyF1Kernel(__global float* dstF1, __global float* srcF1,
+ ConstBuffer cb)
+{
+ int gIdx = GET_GLOBAL_IDX;
+
+ if( gIdx < cb.m_n )
+ {
+ float a0 = srcF1[gIdx];
+
+ dstF1[ gIdx ] = a0;
+ }
+}
+
+__kernel
+__attribute__((reqd_work_group_size(64,1,1)))
+void CopyF2Kernel(__global float2* dstF2, __global float2* srcF2,
+ ConstBuffer cb)
+{
+ int gIdx = GET_GLOBAL_IDX;
+
+ if( gIdx < cb.m_n )
+ {
+ float2 a0 = srcF2[gIdx];
+
+ dstF2[ gIdx ] = a0;
+ }
+}
+
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/kernels/CopyKernelsCL.h b/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/kernels/CopyKernelsCL.h
new file mode 100644
index 0000000000..e5670e3cd3
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/kernels/CopyKernelsCL.h
@@ -0,0 +1,132 @@
+//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
+static const char* copyKernelsCL= \
+"/*\n"
+"Copyright (c) 2012 Advanced Micro Devices, Inc. \n"
+"\n"
+"This software is provided 'as-is', without any express or implied warranty.\n"
+"In no event will the authors be held liable for any damages arising from the use of this software.\n"
+"Permission is granted to anyone to use this software for any purpose, \n"
+"including commercial applications, and to alter it and redistribute it freely, \n"
+"subject to the following restrictions:\n"
+"\n"
+"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.\n"
+"2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
+"3. This notice may not be removed or altered from any source distribution.\n"
+"*/\n"
+"//Originally written by Takahiro Harada\n"
+"\n"
+"#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
+"#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
+"\n"
+"typedef unsigned int u32;\n"
+"#define GET_GROUP_IDX get_group_id(0)\n"
+"#define GET_LOCAL_IDX get_local_id(0)\n"
+"#define GET_GLOBAL_IDX get_global_id(0)\n"
+"#define GET_GROUP_SIZE get_local_size(0)\n"
+"#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
+"#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
+"#define AtomInc(x) atom_inc(&(x))\n"
+"#define AtomInc1(x, out) out = atom_inc(&(x))\n"
+"\n"
+"#define make_uint4 (uint4)\n"
+"#define make_uint2 (uint2)\n"
+"#define make_int2 (int2)\n"
+"\n"
+"typedef struct\n"
+"{\n"
+" int m_n;\n"
+" int m_padding[3];\n"
+"} ConstBuffer;\n"
+"\n"
+"\n"
+"\n"
+"__kernel\n"
+"__attribute__((reqd_work_group_size(64,1,1)))\n"
+"void Copy1F4Kernel(__global float4* dst, __global float4* src, \n"
+" ConstBuffer cb)\n"
+"{\n"
+" int gIdx = GET_GLOBAL_IDX;\n"
+"\n"
+" if( gIdx < cb.m_n )\n"
+" {\n"
+" float4 a0 = src[gIdx];\n"
+"\n"
+" dst[ gIdx ] = a0;\n"
+" }\n"
+"}\n"
+"\n"
+"__kernel\n"
+"__attribute__((reqd_work_group_size(64,1,1)))\n"
+"void Copy2F4Kernel(__global float4* dst, __global float4* src, \n"
+" ConstBuffer cb)\n"
+"{\n"
+" int gIdx = GET_GLOBAL_IDX;\n"
+"\n"
+" if( 2*gIdx <= cb.m_n )\n"
+" {\n"
+" float4 a0 = src[gIdx*2+0];\n"
+" float4 a1 = src[gIdx*2+1];\n"
+"\n"
+" dst[ gIdx*2+0 ] = a0;\n"
+" dst[ gIdx*2+1 ] = a1;\n"
+" }\n"
+"}\n"
+"\n"
+"__kernel\n"
+"__attribute__((reqd_work_group_size(64,1,1)))\n"
+"void Copy4F4Kernel(__global float4* dst, __global float4* src, \n"
+" ConstBuffer cb)\n"
+"{\n"
+" int gIdx = GET_GLOBAL_IDX;\n"
+"\n"
+" if( 4*gIdx <= cb.m_n )\n"
+" {\n"
+" int idx0 = gIdx*4+0;\n"
+" int idx1 = gIdx*4+1;\n"
+" int idx2 = gIdx*4+2;\n"
+" int idx3 = gIdx*4+3;\n"
+"\n"
+" float4 a0 = src[idx0];\n"
+" float4 a1 = src[idx1];\n"
+" float4 a2 = src[idx2];\n"
+" float4 a3 = src[idx3];\n"
+"\n"
+" dst[ idx0 ] = a0;\n"
+" dst[ idx1 ] = a1;\n"
+" dst[ idx2 ] = a2;\n"
+" dst[ idx3 ] = a3;\n"
+" }\n"
+"}\n"
+"\n"
+"__kernel\n"
+"__attribute__((reqd_work_group_size(64,1,1)))\n"
+"void CopyF1Kernel(__global float* dstF1, __global float* srcF1, \n"
+" ConstBuffer cb)\n"
+"{\n"
+" int gIdx = GET_GLOBAL_IDX;\n"
+"\n"
+" if( gIdx < cb.m_n )\n"
+" {\n"
+" float a0 = srcF1[gIdx];\n"
+"\n"
+" dstF1[ gIdx ] = a0;\n"
+" }\n"
+"}\n"
+"\n"
+"__kernel\n"
+"__attribute__((reqd_work_group_size(64,1,1)))\n"
+"void CopyF2Kernel(__global float2* dstF2, __global float2* srcF2, \n"
+" ConstBuffer cb)\n"
+"{\n"
+" int gIdx = GET_GLOBAL_IDX;\n"
+"\n"
+" if( gIdx < cb.m_n )\n"
+" {\n"
+" float2 a0 = srcF2[gIdx];\n"
+"\n"
+" dstF2[ gIdx ] = a0;\n"
+" }\n"
+"}\n"
+"\n"
+"\n"
+;
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/kernels/FillKernels.cl b/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/kernels/FillKernels.cl
new file mode 100644
index 0000000000..71c31075dd
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/kernels/FillKernels.cl
@@ -0,0 +1,107 @@
+/*
+Copyright (c) 2012 Advanced Micro Devices, Inc.
+
+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.
+*/
+//Originally written by Takahiro Harada
+
+
+#pragma OPENCL EXTENSION cl_amd_printf : enable
+#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable
+
+typedef unsigned int u32;
+#define GET_GROUP_IDX get_group_id(0)
+#define GET_LOCAL_IDX get_local_id(0)
+#define GET_GLOBAL_IDX get_global_id(0)
+#define GET_GROUP_SIZE get_local_size(0)
+#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)
+#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)
+#define AtomInc(x) atom_inc(&(x))
+#define AtomInc1(x, out) out = atom_inc(&(x))
+
+#define make_uint4 (uint4)
+#define make_uint2 (uint2)
+#define make_int2 (int2)
+
+typedef struct
+{
+ union
+ {
+ int4 m_data;
+ uint4 m_unsignedData;
+ float m_floatData;
+ };
+ int m_offset;
+ int m_n;
+ int m_padding[2];
+} ConstBuffer;
+
+
+__kernel
+__attribute__((reqd_work_group_size(64,1,1)))
+void FillIntKernel(__global int* dstInt, int num_elements, int value, const int offset)
+{
+ int gIdx = GET_GLOBAL_IDX;
+
+ if( gIdx < num_elements )
+ {
+ dstInt[ offset+gIdx ] = value;
+ }
+}
+
+__kernel
+__attribute__((reqd_work_group_size(64,1,1)))
+void FillFloatKernel(__global float* dstFloat, int num_elements, float value, const int offset)
+{
+ int gIdx = GET_GLOBAL_IDX;
+
+ if( gIdx < num_elements )
+ {
+ dstFloat[ offset+gIdx ] = value;
+ }
+}
+
+__kernel
+__attribute__((reqd_work_group_size(64,1,1)))
+void FillUnsignedIntKernel(__global unsigned int* dstInt, const int num, const unsigned int value, const int offset)
+{
+ int gIdx = GET_GLOBAL_IDX;
+
+ if( gIdx < num )
+ {
+ dstInt[ offset+gIdx ] = value;
+ }
+}
+
+__kernel
+__attribute__((reqd_work_group_size(64,1,1)))
+void FillInt2Kernel(__global int2* dstInt2, const int num, const int2 value, const int offset)
+{
+ int gIdx = GET_GLOBAL_IDX;
+
+ if( gIdx < num )
+ {
+ dstInt2[ gIdx + offset] = make_int2( value.x, value.y );
+ }
+}
+
+__kernel
+__attribute__((reqd_work_group_size(64,1,1)))
+void FillInt4Kernel(__global int4* dstInt4, const int num, const int4 value, const int offset)
+{
+ int gIdx = GET_GLOBAL_IDX;
+
+ if( gIdx < num )
+ {
+ dstInt4[ offset+gIdx ] = value;
+ }
+}
+
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/kernels/FillKernelsCL.h b/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/kernels/FillKernelsCL.h
new file mode 100644
index 0000000000..4f8b96e489
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/kernels/FillKernelsCL.h
@@ -0,0 +1,91 @@
+//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
+static const char* fillKernelsCL= \
+"/*\n"
+"Copyright (c) 2012 Advanced Micro Devices, Inc. \n"
+"This software is provided 'as-is', without any express or implied warranty.\n"
+"In no event will the authors be held liable for any damages arising from the use of this software.\n"
+"Permission is granted to anyone to use this software for any purpose, \n"
+"including commercial applications, and to alter it and redistribute it freely, \n"
+"subject to the following restrictions:\n"
+"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.\n"
+"2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
+"3. This notice may not be removed or altered from any source distribution.\n"
+"*/\n"
+"//Originally written by Takahiro Harada\n"
+"#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
+"#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
+"typedef unsigned int u32;\n"
+"#define GET_GROUP_IDX get_group_id(0)\n"
+"#define GET_LOCAL_IDX get_local_id(0)\n"
+"#define GET_GLOBAL_IDX get_global_id(0)\n"
+"#define GET_GROUP_SIZE get_local_size(0)\n"
+"#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
+"#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
+"#define AtomInc(x) atom_inc(&(x))\n"
+"#define AtomInc1(x, out) out = atom_inc(&(x))\n"
+"#define make_uint4 (uint4)\n"
+"#define make_uint2 (uint2)\n"
+"#define make_int2 (int2)\n"
+"typedef struct\n"
+"{\n"
+" union\n"
+" {\n"
+" int4 m_data;\n"
+" uint4 m_unsignedData;\n"
+" float m_floatData;\n"
+" };\n"
+" int m_offset;\n"
+" int m_n;\n"
+" int m_padding[2];\n"
+"} ConstBuffer;\n"
+"__kernel\n"
+"__attribute__((reqd_work_group_size(64,1,1)))\n"
+"void FillIntKernel(__global int* dstInt, int num_elements, int value, const int offset)\n"
+"{\n"
+" int gIdx = GET_GLOBAL_IDX;\n"
+" if( gIdx < num_elements )\n"
+" {\n"
+" dstInt[ offset+gIdx ] = value;\n"
+" }\n"
+"}\n"
+"__kernel\n"
+"__attribute__((reqd_work_group_size(64,1,1)))\n"
+"void FillFloatKernel(__global float* dstFloat, int num_elements, float value, const int offset)\n"
+"{\n"
+" int gIdx = GET_GLOBAL_IDX;\n"
+" if( gIdx < num_elements )\n"
+" {\n"
+" dstFloat[ offset+gIdx ] = value;\n"
+" }\n"
+"}\n"
+"__kernel\n"
+"__attribute__((reqd_work_group_size(64,1,1)))\n"
+"void FillUnsignedIntKernel(__global unsigned int* dstInt, const int num, const unsigned int value, const int offset)\n"
+"{\n"
+" int gIdx = GET_GLOBAL_IDX;\n"
+" if( gIdx < num )\n"
+" {\n"
+" dstInt[ offset+gIdx ] = value;\n"
+" }\n"
+"}\n"
+"__kernel\n"
+"__attribute__((reqd_work_group_size(64,1,1)))\n"
+"void FillInt2Kernel(__global int2* dstInt2, const int num, const int2 value, const int offset)\n"
+"{\n"
+" int gIdx = GET_GLOBAL_IDX;\n"
+" if( gIdx < num )\n"
+" {\n"
+" dstInt2[ gIdx + offset] = make_int2( value.x, value.y );\n"
+" }\n"
+"}\n"
+"__kernel\n"
+"__attribute__((reqd_work_group_size(64,1,1)))\n"
+"void FillInt4Kernel(__global int4* dstInt4, const int num, const int4 value, const int offset)\n"
+"{\n"
+" int gIdx = GET_GLOBAL_IDX;\n"
+" if( gIdx < num )\n"
+" {\n"
+" dstInt4[ offset+gIdx ] = value;\n"
+" }\n"
+"}\n"
+;
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanFloat4Kernels.cl b/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanFloat4Kernels.cl
new file mode 100644
index 0000000000..c9da79854a
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanFloat4Kernels.cl
@@ -0,0 +1,154 @@
+/*
+Copyright (c) 2012 Advanced Micro Devices, Inc.
+
+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.
+*/
+//Originally written by Takahiro Harada
+
+
+typedef unsigned int u32;
+#define GET_GROUP_IDX get_group_id(0)
+#define GET_LOCAL_IDX get_local_id(0)
+#define GET_GLOBAL_IDX get_global_id(0)
+#define GET_GROUP_SIZE get_local_size(0)
+#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)
+
+// takahiro end
+#define WG_SIZE 128
+#define m_numElems x
+#define m_numBlocks y
+#define m_numScanBlocks z
+
+/*typedef struct
+{
+ uint m_numElems;
+ uint m_numBlocks;
+ uint m_numScanBlocks;
+ uint m_padding[1];
+} ConstBuffer;
+*/
+
+float4 ScanExclusiveFloat4(__local float4* data, u32 n, int lIdx, int lSize)
+{
+ float4 blocksum;
+ int offset = 1;
+ for(int nActive=n>>1; nActive>0; nActive>>=1, offset<<=1)
+ {
+ GROUP_LDS_BARRIER;
+ for(int iIdx=lIdx; iIdx<nActive; iIdx+=lSize)
+ {
+ int ai = offset*(2*iIdx+1)-1;
+ int bi = offset*(2*iIdx+2)-1;
+ data[bi] += data[ai];
+ }
+ }
+
+ GROUP_LDS_BARRIER;
+
+ if( lIdx == 0 )
+ {
+ blocksum = data[ n-1 ];
+ data[ n-1 ] = 0;
+ }
+
+ GROUP_LDS_BARRIER;
+
+ offset >>= 1;
+ for(int nActive=1; nActive<n; nActive<<=1, offset>>=1 )
+ {
+ GROUP_LDS_BARRIER;
+ for( int iIdx = lIdx; iIdx<nActive; iIdx += lSize )
+ {
+ int ai = offset*(2*iIdx+1)-1;
+ int bi = offset*(2*iIdx+2)-1;
+ float4 temp = data[ai];
+ data[ai] = data[bi];
+ data[bi] += temp;
+ }
+ }
+ GROUP_LDS_BARRIER;
+
+ return blocksum;
+}
+
+__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
+__kernel
+void LocalScanKernel(__global float4* dst, __global float4* src, __global float4* sumBuffer, uint4 cb)
+{
+ __local float4 ldsData[WG_SIZE*2];
+
+ int gIdx = GET_GLOBAL_IDX;
+ int lIdx = GET_LOCAL_IDX;
+
+ ldsData[2*lIdx] = ( 2*gIdx < cb.m_numElems )? src[2*gIdx]: 0;
+ ldsData[2*lIdx + 1] = ( 2*gIdx+1 < cb.m_numElems )? src[2*gIdx + 1]: 0;
+
+ float4 sum = ScanExclusiveFloat4(ldsData, WG_SIZE*2, GET_LOCAL_IDX, GET_GROUP_SIZE);
+
+ if( lIdx == 0 )
+ sumBuffer[GET_GROUP_IDX] = sum;
+
+ if( (2*gIdx) < cb.m_numElems )
+ {
+ dst[2*gIdx] = ldsData[2*lIdx];
+ }
+ if( (2*gIdx + 1) < cb.m_numElems )
+ {
+ dst[2*gIdx + 1] = ldsData[2*lIdx + 1];
+ }
+}
+
+__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
+__kernel
+void AddOffsetKernel(__global float4* dst, __global float4* blockSum, uint4 cb)
+{
+ const u32 blockSize = WG_SIZE*2;
+
+ int myIdx = GET_GROUP_IDX+1;
+ int lIdx = GET_LOCAL_IDX;
+
+ float4 iBlockSum = blockSum[myIdx];
+
+ int endValue = min((myIdx+1)*(blockSize), cb.m_numElems);
+ for(int i=myIdx*blockSize+lIdx; i<endValue; i+=GET_GROUP_SIZE)
+ {
+ dst[i] += iBlockSum;
+ }
+}
+
+__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
+__kernel
+void TopLevelScanKernel(__global float4* dst, uint4 cb)
+{
+ __local float4 ldsData[2048];
+ int gIdx = GET_GLOBAL_IDX;
+ int lIdx = GET_LOCAL_IDX;
+ int lSize = GET_GROUP_SIZE;
+
+ for(int i=lIdx; i<cb.m_numScanBlocks; i+=lSize )
+ {
+ ldsData[i] = (i<cb.m_numBlocks)? dst[i]:0;
+ }
+
+ GROUP_LDS_BARRIER;
+
+ float4 sum = ScanExclusiveFloat4(ldsData, cb.m_numScanBlocks, GET_LOCAL_IDX, GET_GROUP_SIZE);
+
+ for(int i=lIdx; i<cb.m_numBlocks; i+=lSize )
+ {
+ dst[i] = ldsData[i];
+ }
+
+ if( gIdx == 0 )
+ {
+ dst[cb.m_numBlocks] = sum;
+ }
+}
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanKernels.cl b/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanKernels.cl
new file mode 100644
index 0000000000..963cc1e48e
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanKernels.cl
@@ -0,0 +1,154 @@
+/*
+Copyright (c) 2012 Advanced Micro Devices, Inc.
+
+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.
+*/
+//Originally written by Takahiro Harada
+
+
+typedef unsigned int u32;
+#define GET_GROUP_IDX get_group_id(0)
+#define GET_LOCAL_IDX get_local_id(0)
+#define GET_GLOBAL_IDX get_global_id(0)
+#define GET_GROUP_SIZE get_local_size(0)
+#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)
+
+// takahiro end
+#define WG_SIZE 128
+#define m_numElems x
+#define m_numBlocks y
+#define m_numScanBlocks z
+
+/*typedef struct
+{
+ uint m_numElems;
+ uint m_numBlocks;
+ uint m_numScanBlocks;
+ uint m_padding[1];
+} ConstBuffer;
+*/
+
+u32 ScanExclusive(__local u32* data, u32 n, int lIdx, int lSize)
+{
+ u32 blocksum;
+ int offset = 1;
+ for(int nActive=n>>1; nActive>0; nActive>>=1, offset<<=1)
+ {
+ GROUP_LDS_BARRIER;
+ for(int iIdx=lIdx; iIdx<nActive; iIdx+=lSize)
+ {
+ int ai = offset*(2*iIdx+1)-1;
+ int bi = offset*(2*iIdx+2)-1;
+ data[bi] += data[ai];
+ }
+ }
+
+ GROUP_LDS_BARRIER;
+
+ if( lIdx == 0 )
+ {
+ blocksum = data[ n-1 ];
+ data[ n-1 ] = 0;
+ }
+
+ GROUP_LDS_BARRIER;
+
+ offset >>= 1;
+ for(int nActive=1; nActive<n; nActive<<=1, offset>>=1 )
+ {
+ GROUP_LDS_BARRIER;
+ for( int iIdx = lIdx; iIdx<nActive; iIdx += lSize )
+ {
+ int ai = offset*(2*iIdx+1)-1;
+ int bi = offset*(2*iIdx+2)-1;
+ u32 temp = data[ai];
+ data[ai] = data[bi];
+ data[bi] += temp;
+ }
+ }
+ GROUP_LDS_BARRIER;
+
+ return blocksum;
+}
+
+__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
+__kernel
+void LocalScanKernel(__global u32* dst, __global u32 *src, __global u32 *sumBuffer,
+ uint4 cb)
+{
+ __local u32 ldsData[WG_SIZE*2];
+
+ int gIdx = GET_GLOBAL_IDX;
+ int lIdx = GET_LOCAL_IDX;
+
+ ldsData[2*lIdx] = ( 2*gIdx < cb.m_numElems )? src[2*gIdx]: 0;
+ ldsData[2*lIdx + 1] = ( 2*gIdx+1 < cb.m_numElems )? src[2*gIdx + 1]: 0;
+
+ u32 sum = ScanExclusive(ldsData, WG_SIZE*2, GET_LOCAL_IDX, GET_GROUP_SIZE);
+
+ if( lIdx == 0 ) sumBuffer[GET_GROUP_IDX] = sum;
+
+ if( (2*gIdx) < cb.m_numElems )
+ {
+ dst[2*gIdx] = ldsData[2*lIdx];
+ }
+ if( (2*gIdx + 1) < cb.m_numElems )
+ {
+ dst[2*gIdx + 1] = ldsData[2*lIdx + 1];
+ }
+}
+
+__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
+__kernel
+void AddOffsetKernel(__global u32 *dst, __global u32 *blockSum, uint4 cb)
+{
+ const u32 blockSize = WG_SIZE*2;
+
+ int myIdx = GET_GROUP_IDX+1;
+ int lIdx = GET_LOCAL_IDX;
+
+ u32 iBlockSum = blockSum[myIdx];
+
+ int endValue = min((myIdx+1)*(blockSize), cb.m_numElems);
+ for(int i=myIdx*blockSize+lIdx; i<endValue; i+=GET_GROUP_SIZE)
+ {
+ dst[i] += iBlockSum;
+ }
+}
+
+__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
+__kernel
+void TopLevelScanKernel(__global u32* dst, uint4 cb)
+{
+ __local u32 ldsData[2048];
+ int gIdx = GET_GLOBAL_IDX;
+ int lIdx = GET_LOCAL_IDX;
+ int lSize = GET_GROUP_SIZE;
+
+ for(int i=lIdx; i<cb.m_numScanBlocks; i+=lSize )
+ {
+ ldsData[i] = (i<cb.m_numBlocks)? dst[i]:0;
+ }
+
+ GROUP_LDS_BARRIER;
+
+ u32 sum = ScanExclusive(ldsData, cb.m_numScanBlocks, GET_LOCAL_IDX, GET_GROUP_SIZE);
+
+ for(int i=lIdx; i<cb.m_numBlocks; i+=lSize )
+ {
+ dst[i] = ldsData[i];
+ }
+
+ if( gIdx == 0 )
+ {
+ dst[cb.m_numBlocks] = sum;
+ }
+}
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanKernelsCL.h b/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanKernelsCL.h
new file mode 100644
index 0000000000..27baab8331
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanKernelsCL.h
@@ -0,0 +1,129 @@
+//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
+static const char* prefixScanKernelsCL= \
+"/*\n"
+"Copyright (c) 2012 Advanced Micro Devices, Inc. \n"
+"This software is provided 'as-is', without any express or implied warranty.\n"
+"In no event will the authors be held liable for any damages arising from the use of this software.\n"
+"Permission is granted to anyone to use this software for any purpose, \n"
+"including commercial applications, and to alter it and redistribute it freely, \n"
+"subject to the following restrictions:\n"
+"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.\n"
+"2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
+"3. This notice may not be removed or altered from any source distribution.\n"
+"*/\n"
+"//Originally written by Takahiro Harada\n"
+"typedef unsigned int u32;\n"
+"#define GET_GROUP_IDX get_group_id(0)\n"
+"#define GET_LOCAL_IDX get_local_id(0)\n"
+"#define GET_GLOBAL_IDX get_global_id(0)\n"
+"#define GET_GROUP_SIZE get_local_size(0)\n"
+"#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
+"// takahiro end\n"
+"#define WG_SIZE 128 \n"
+"#define m_numElems x\n"
+"#define m_numBlocks y\n"
+"#define m_numScanBlocks z\n"
+"/*typedef struct\n"
+"{\n"
+" uint m_numElems;\n"
+" uint m_numBlocks;\n"
+" uint m_numScanBlocks;\n"
+" uint m_padding[1];\n"
+"} ConstBuffer;\n"
+"*/\n"
+"u32 ScanExclusive(__local u32* data, u32 n, int lIdx, int lSize)\n"
+"{\n"
+" u32 blocksum;\n"
+" int offset = 1;\n"
+" for(int nActive=n>>1; nActive>0; nActive>>=1, offset<<=1)\n"
+" {\n"
+" GROUP_LDS_BARRIER;\n"
+" for(int iIdx=lIdx; iIdx<nActive; iIdx+=lSize)\n"
+" {\n"
+" int ai = offset*(2*iIdx+1)-1;\n"
+" int bi = offset*(2*iIdx+2)-1;\n"
+" data[bi] += data[ai];\n"
+" }\n"
+" }\n"
+" GROUP_LDS_BARRIER;\n"
+" if( lIdx == 0 )\n"
+" {\n"
+" blocksum = data[ n-1 ];\n"
+" data[ n-1 ] = 0;\n"
+" }\n"
+" GROUP_LDS_BARRIER;\n"
+" offset >>= 1;\n"
+" for(int nActive=1; nActive<n; nActive<<=1, offset>>=1 )\n"
+" {\n"
+" GROUP_LDS_BARRIER;\n"
+" for( int iIdx = lIdx; iIdx<nActive; iIdx += lSize )\n"
+" {\n"
+" int ai = offset*(2*iIdx+1)-1;\n"
+" int bi = offset*(2*iIdx+2)-1;\n"
+" u32 temp = data[ai];\n"
+" data[ai] = data[bi];\n"
+" data[bi] += temp;\n"
+" }\n"
+" }\n"
+" GROUP_LDS_BARRIER;\n"
+" return blocksum;\n"
+"}\n"
+"__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+"__kernel\n"
+"void LocalScanKernel(__global u32* dst, __global u32 *src, __global u32 *sumBuffer,\n"
+" uint4 cb)\n"
+"{\n"
+" __local u32 ldsData[WG_SIZE*2];\n"
+" int gIdx = GET_GLOBAL_IDX;\n"
+" int lIdx = GET_LOCAL_IDX;\n"
+" ldsData[2*lIdx] = ( 2*gIdx < cb.m_numElems )? src[2*gIdx]: 0;\n"
+" ldsData[2*lIdx + 1] = ( 2*gIdx+1 < cb.m_numElems )? src[2*gIdx + 1]: 0;\n"
+" u32 sum = ScanExclusive(ldsData, WG_SIZE*2, GET_LOCAL_IDX, GET_GROUP_SIZE);\n"
+" if( lIdx == 0 ) sumBuffer[GET_GROUP_IDX] = sum;\n"
+" if( (2*gIdx) < cb.m_numElems )\n"
+" {\n"
+" dst[2*gIdx] = ldsData[2*lIdx];\n"
+" }\n"
+" if( (2*gIdx + 1) < cb.m_numElems )\n"
+" {\n"
+" dst[2*gIdx + 1] = ldsData[2*lIdx + 1];\n"
+" }\n"
+"}\n"
+"__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+"__kernel\n"
+"void AddOffsetKernel(__global u32 *dst, __global u32 *blockSum, uint4 cb)\n"
+"{\n"
+" const u32 blockSize = WG_SIZE*2;\n"
+" int myIdx = GET_GROUP_IDX+1;\n"
+" int lIdx = GET_LOCAL_IDX;\n"
+" u32 iBlockSum = blockSum[myIdx];\n"
+" int endValue = min((myIdx+1)*(blockSize), cb.m_numElems);\n"
+" for(int i=myIdx*blockSize+lIdx; i<endValue; i+=GET_GROUP_SIZE)\n"
+" {\n"
+" dst[i] += iBlockSum;\n"
+" }\n"
+"}\n"
+"__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+"__kernel\n"
+"void TopLevelScanKernel(__global u32* dst, uint4 cb)\n"
+"{\n"
+" __local u32 ldsData[2048];\n"
+" int gIdx = GET_GLOBAL_IDX;\n"
+" int lIdx = GET_LOCAL_IDX;\n"
+" int lSize = GET_GROUP_SIZE;\n"
+" for(int i=lIdx; i<cb.m_numScanBlocks; i+=lSize )\n"
+" {\n"
+" ldsData[i] = (i<cb.m_numBlocks)? dst[i]:0;\n"
+" }\n"
+" GROUP_LDS_BARRIER;\n"
+" u32 sum = ScanExclusive(ldsData, cb.m_numScanBlocks, GET_LOCAL_IDX, GET_GROUP_SIZE);\n"
+" for(int i=lIdx; i<cb.m_numBlocks; i+=lSize )\n"
+" {\n"
+" dst[i] = ldsData[i];\n"
+" }\n"
+" if( gIdx == 0 )\n"
+" {\n"
+" dst[cb.m_numBlocks] = sum;\n"
+" }\n"
+"}\n"
+;
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanKernelsFloat4CL.h b/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanKernelsFloat4CL.h
new file mode 100644
index 0000000000..5b13254796
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanKernelsFloat4CL.h
@@ -0,0 +1,129 @@
+//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
+static const char* prefixScanKernelsFloat4CL= \
+"/*\n"
+"Copyright (c) 2012 Advanced Micro Devices, Inc. \n"
+"This software is provided 'as-is', without any express or implied warranty.\n"
+"In no event will the authors be held liable for any damages arising from the use of this software.\n"
+"Permission is granted to anyone to use this software for any purpose, \n"
+"including commercial applications, and to alter it and redistribute it freely, \n"
+"subject to the following restrictions:\n"
+"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.\n"
+"2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
+"3. This notice may not be removed or altered from any source distribution.\n"
+"*/\n"
+"//Originally written by Takahiro Harada\n"
+"typedef unsigned int u32;\n"
+"#define GET_GROUP_IDX get_group_id(0)\n"
+"#define GET_LOCAL_IDX get_local_id(0)\n"
+"#define GET_GLOBAL_IDX get_global_id(0)\n"
+"#define GET_GROUP_SIZE get_local_size(0)\n"
+"#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
+"// takahiro end\n"
+"#define WG_SIZE 128 \n"
+"#define m_numElems x\n"
+"#define m_numBlocks y\n"
+"#define m_numScanBlocks z\n"
+"/*typedef struct\n"
+"{\n"
+" uint m_numElems;\n"
+" uint m_numBlocks;\n"
+" uint m_numScanBlocks;\n"
+" uint m_padding[1];\n"
+"} ConstBuffer;\n"
+"*/\n"
+"float4 ScanExclusiveFloat4(__local float4* data, u32 n, int lIdx, int lSize)\n"
+"{\n"
+" float4 blocksum;\n"
+" int offset = 1;\n"
+" for(int nActive=n>>1; nActive>0; nActive>>=1, offset<<=1)\n"
+" {\n"
+" GROUP_LDS_BARRIER;\n"
+" for(int iIdx=lIdx; iIdx<nActive; iIdx+=lSize)\n"
+" {\n"
+" int ai = offset*(2*iIdx+1)-1;\n"
+" int bi = offset*(2*iIdx+2)-1;\n"
+" data[bi] += data[ai];\n"
+" }\n"
+" }\n"
+" GROUP_LDS_BARRIER;\n"
+" if( lIdx == 0 )\n"
+" {\n"
+" blocksum = data[ n-1 ];\n"
+" data[ n-1 ] = 0;\n"
+" }\n"
+" GROUP_LDS_BARRIER;\n"
+" offset >>= 1;\n"
+" for(int nActive=1; nActive<n; nActive<<=1, offset>>=1 )\n"
+" {\n"
+" GROUP_LDS_BARRIER;\n"
+" for( int iIdx = lIdx; iIdx<nActive; iIdx += lSize )\n"
+" {\n"
+" int ai = offset*(2*iIdx+1)-1;\n"
+" int bi = offset*(2*iIdx+2)-1;\n"
+" float4 temp = data[ai];\n"
+" data[ai] = data[bi];\n"
+" data[bi] += temp;\n"
+" }\n"
+" }\n"
+" GROUP_LDS_BARRIER;\n"
+" return blocksum;\n"
+"}\n"
+"__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+"__kernel\n"
+"void LocalScanKernel(__global float4* dst, __global float4* src, __global float4* sumBuffer, uint4 cb)\n"
+"{\n"
+" __local float4 ldsData[WG_SIZE*2];\n"
+" int gIdx = GET_GLOBAL_IDX;\n"
+" int lIdx = GET_LOCAL_IDX;\n"
+" ldsData[2*lIdx] = ( 2*gIdx < cb.m_numElems )? src[2*gIdx]: 0;\n"
+" ldsData[2*lIdx + 1] = ( 2*gIdx+1 < cb.m_numElems )? src[2*gIdx + 1]: 0;\n"
+" float4 sum = ScanExclusiveFloat4(ldsData, WG_SIZE*2, GET_LOCAL_IDX, GET_GROUP_SIZE);\n"
+" if( lIdx == 0 ) \n"
+" sumBuffer[GET_GROUP_IDX] = sum;\n"
+" if( (2*gIdx) < cb.m_numElems )\n"
+" {\n"
+" dst[2*gIdx] = ldsData[2*lIdx];\n"
+" }\n"
+" if( (2*gIdx + 1) < cb.m_numElems )\n"
+" {\n"
+" dst[2*gIdx + 1] = ldsData[2*lIdx + 1];\n"
+" }\n"
+"}\n"
+"__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+"__kernel\n"
+"void AddOffsetKernel(__global float4* dst, __global float4* blockSum, uint4 cb)\n"
+"{\n"
+" const u32 blockSize = WG_SIZE*2;\n"
+" int myIdx = GET_GROUP_IDX+1;\n"
+" int lIdx = GET_LOCAL_IDX;\n"
+" float4 iBlockSum = blockSum[myIdx];\n"
+" int endValue = min((myIdx+1)*(blockSize), cb.m_numElems);\n"
+" for(int i=myIdx*blockSize+lIdx; i<endValue; i+=GET_GROUP_SIZE)\n"
+" {\n"
+" dst[i] += iBlockSum;\n"
+" }\n"
+"}\n"
+"__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+"__kernel\n"
+"void TopLevelScanKernel(__global float4* dst, uint4 cb)\n"
+"{\n"
+" __local float4 ldsData[2048];\n"
+" int gIdx = GET_GLOBAL_IDX;\n"
+" int lIdx = GET_LOCAL_IDX;\n"
+" int lSize = GET_GROUP_SIZE;\n"
+" for(int i=lIdx; i<cb.m_numScanBlocks; i+=lSize )\n"
+" {\n"
+" ldsData[i] = (i<cb.m_numBlocks)? dst[i]:0;\n"
+" }\n"
+" GROUP_LDS_BARRIER;\n"
+" float4 sum = ScanExclusiveFloat4(ldsData, cb.m_numScanBlocks, GET_LOCAL_IDX, GET_GROUP_SIZE);\n"
+" for(int i=lIdx; i<cb.m_numBlocks; i+=lSize )\n"
+" {\n"
+" dst[i] = ldsData[i];\n"
+" }\n"
+" if( gIdx == 0 )\n"
+" {\n"
+" dst[cb.m_numBlocks] = sum;\n"
+" }\n"
+"}\n"
+;
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/kernels/RadixSort32Kernels.cl b/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/kernels/RadixSort32Kernels.cl
new file mode 100644
index 0000000000..7402e2f3b3
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/kernels/RadixSort32Kernels.cl
@@ -0,0 +1,1071 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2011 Advanced Micro Devices, 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.
+*/
+//Author Takahiro Harada
+
+
+//#pragma OPENCL EXTENSION cl_amd_printf : enable
+#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable
+
+typedef unsigned int u32;
+#define GET_GROUP_IDX get_group_id(0)
+#define GET_LOCAL_IDX get_local_id(0)
+#define GET_GLOBAL_IDX get_global_id(0)
+#define GET_GROUP_SIZE get_local_size(0)
+#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)
+#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)
+#define AtomInc(x) atom_inc(&(x))
+#define AtomInc1(x, out) out = atom_inc(&(x))
+#define AtomAdd(x, value) atom_add(&(x), value)
+
+#define SELECT_UINT4( b, a, condition ) select( b,a,condition )
+
+
+#define make_uint4 (uint4)
+#define make_uint2 (uint2)
+#define make_int2 (int2)
+
+#define WG_SIZE 64
+#define ELEMENTS_PER_WORK_ITEM (256/WG_SIZE)
+#define BITS_PER_PASS 4
+#define NUM_BUCKET (1<<BITS_PER_PASS)
+typedef uchar u8;
+
+// this isn't optimization for VLIW. But just reducing writes.
+#define USE_2LEVEL_REDUCE 1
+
+//#define CHECK_BOUNDARY 1
+
+//#define NV_GPU 1
+
+
+// Cypress
+#define nPerWI 16
+// Cayman
+//#define nPerWI 20
+
+#define m_n x
+#define m_nWGs y
+#define m_startBit z
+#define m_nBlocksPerWG w
+
+/*
+typedef struct
+{
+ int m_n;
+ int m_nWGs;
+ int m_startBit;
+ int m_nBlocksPerWG;
+} ConstBuffer;
+*/
+
+typedef struct
+{
+ unsigned int m_key;
+ unsigned int m_value;
+} SortDataCL;
+
+
+uint prefixScanVectorEx( uint4* data )
+{
+ u32 sum = 0;
+ u32 tmp = data[0].x;
+ data[0].x = sum;
+ sum += tmp;
+ tmp = data[0].y;
+ data[0].y = sum;
+ sum += tmp;
+ tmp = data[0].z;
+ data[0].z = sum;
+ sum += tmp;
+ tmp = data[0].w;
+ data[0].w = sum;
+ sum += tmp;
+ return sum;
+}
+
+u32 localPrefixSum( u32 pData, uint lIdx, uint* totalSum, __local u32* sorterSharedMemory, int wgSize /*64 or 128*/ )
+{
+ { // Set data
+ sorterSharedMemory[lIdx] = 0;
+ sorterSharedMemory[lIdx+wgSize] = pData;
+ }
+
+ GROUP_LDS_BARRIER;
+
+ { // Prefix sum
+ int idx = 2*lIdx + (wgSize+1);
+#if defined(USE_2LEVEL_REDUCE)
+ if( lIdx < 64 )
+ {
+ u32 u0, u1, u2;
+ u0 = sorterSharedMemory[idx-3];
+ u1 = sorterSharedMemory[idx-2];
+ u2 = sorterSharedMemory[idx-1];
+ AtomAdd( sorterSharedMemory[idx], u0+u1+u2 );
+ GROUP_MEM_FENCE;
+
+ u0 = sorterSharedMemory[idx-12];
+ u1 = sorterSharedMemory[idx-8];
+ u2 = sorterSharedMemory[idx-4];
+ AtomAdd( sorterSharedMemory[idx], u0+u1+u2 );
+ GROUP_MEM_FENCE;
+
+ u0 = sorterSharedMemory[idx-48];
+ u1 = sorterSharedMemory[idx-32];
+ u2 = sorterSharedMemory[idx-16];
+ AtomAdd( sorterSharedMemory[idx], u0+u1+u2 );
+ GROUP_MEM_FENCE;
+ if( wgSize > 64 )
+ {
+ sorterSharedMemory[idx] += sorterSharedMemory[idx-64];
+ GROUP_MEM_FENCE;
+ }
+
+ sorterSharedMemory[idx-1] += sorterSharedMemory[idx-2];
+ GROUP_MEM_FENCE;
+ }
+#else
+ if( lIdx < 64 )
+ {
+ sorterSharedMemory[idx] += sorterSharedMemory[idx-1];
+ GROUP_MEM_FENCE;
+ sorterSharedMemory[idx] += sorterSharedMemory[idx-2];
+ GROUP_MEM_FENCE;
+ sorterSharedMemory[idx] += sorterSharedMemory[idx-4];
+ GROUP_MEM_FENCE;
+ sorterSharedMemory[idx] += sorterSharedMemory[idx-8];
+ GROUP_MEM_FENCE;
+ sorterSharedMemory[idx] += sorterSharedMemory[idx-16];
+ GROUP_MEM_FENCE;
+ sorterSharedMemory[idx] += sorterSharedMemory[idx-32];
+ GROUP_MEM_FENCE;
+ if( wgSize > 64 )
+ {
+ sorterSharedMemory[idx] += sorterSharedMemory[idx-64];
+ GROUP_MEM_FENCE;
+ }
+
+ sorterSharedMemory[idx-1] += sorterSharedMemory[idx-2];
+ GROUP_MEM_FENCE;
+ }
+#endif
+ }
+
+ GROUP_LDS_BARRIER;
+
+ *totalSum = sorterSharedMemory[wgSize*2-1];
+ u32 addValue = sorterSharedMemory[lIdx+wgSize-1];
+ return addValue;
+}
+
+//__attribute__((reqd_work_group_size(128,1,1)))
+uint4 localPrefixSum128V( uint4 pData, uint lIdx, uint* totalSum, __local u32* sorterSharedMemory )
+{
+ u32 s4 = prefixScanVectorEx( &pData );
+ u32 rank = localPrefixSum( s4, lIdx, totalSum, sorterSharedMemory, 128 );
+ return pData + make_uint4( rank, rank, rank, rank );
+}
+
+
+//__attribute__((reqd_work_group_size(64,1,1)))
+uint4 localPrefixSum64V( uint4 pData, uint lIdx, uint* totalSum, __local u32* sorterSharedMemory )
+{
+ u32 s4 = prefixScanVectorEx( &pData );
+ u32 rank = localPrefixSum( s4, lIdx, totalSum, sorterSharedMemory, 64 );
+ return pData + make_uint4( rank, rank, rank, rank );
+}
+
+u32 unpack4Key( u32 key, int keyIdx ){ return (key>>(keyIdx*8)) & 0xff;}
+
+u32 bit8Scan(u32 v)
+{
+ return (v<<8) + (v<<16) + (v<<24);
+}
+
+//===
+
+
+
+
+#define MY_HISTOGRAM(idx) localHistogramMat[(idx)*WG_SIZE+lIdx]
+
+
+__kernel
+__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
+void StreamCountKernel( __global u32* gSrc, __global u32* histogramOut, int4 cb )
+{
+ __local u32 localHistogramMat[NUM_BUCKET*WG_SIZE];
+
+ u32 gIdx = GET_GLOBAL_IDX;
+ u32 lIdx = GET_LOCAL_IDX;
+ u32 wgIdx = GET_GROUP_IDX;
+ u32 wgSize = GET_GROUP_SIZE;
+ const int startBit = cb.m_startBit;
+ const int n = cb.m_n;
+ const int nWGs = cb.m_nWGs;
+ const int nBlocksPerWG = cb.m_nBlocksPerWG;
+
+ for(int i=0; i<NUM_BUCKET; i++)
+ {
+ MY_HISTOGRAM(i) = 0;
+ }
+
+ GROUP_LDS_BARRIER;
+
+ const int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE;
+ u32 localKey;
+
+ int nBlocks = (n)/blockSize - nBlocksPerWG*wgIdx;
+
+ int addr = blockSize*nBlocksPerWG*wgIdx + ELEMENTS_PER_WORK_ITEM*lIdx;
+
+ for(int iblock=0; iblock<min(nBlocksPerWG, nBlocks); iblock++, addr+=blockSize)
+ {
+ // MY_HISTOGRAM( localKeys.x ) ++ is much expensive than atomic add as it requires read and write while atomics can just add on AMD
+ // Using registers didn't perform well. It seems like use localKeys to address requires a lot of alu ops
+ // AMD: AtomInc performs better while NV prefers ++
+ for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)
+ {
+#if defined(CHECK_BOUNDARY)
+ if( addr+i < n )
+#endif
+ {
+ localKey = (gSrc[addr+i]>>startBit) & 0xf;
+#if defined(NV_GPU)
+ MY_HISTOGRAM( localKey )++;
+#else
+ AtomInc( MY_HISTOGRAM( localKey ) );
+#endif
+ }
+ }
+ }
+
+ GROUP_LDS_BARRIER;
+
+ if( lIdx < NUM_BUCKET )
+ {
+ u32 sum = 0;
+ for(int i=0; i<GET_GROUP_SIZE; i++)
+ {
+ sum += localHistogramMat[lIdx*WG_SIZE+(i+lIdx)%GET_GROUP_SIZE];
+ }
+ histogramOut[lIdx*nWGs+wgIdx] = sum;
+ }
+}
+
+__kernel
+__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
+void StreamCountSortDataKernel( __global SortDataCL* gSrc, __global u32* histogramOut, int4 cb )
+{
+ __local u32 localHistogramMat[NUM_BUCKET*WG_SIZE];
+
+ u32 gIdx = GET_GLOBAL_IDX;
+ u32 lIdx = GET_LOCAL_IDX;
+ u32 wgIdx = GET_GROUP_IDX;
+ u32 wgSize = GET_GROUP_SIZE;
+ const int startBit = cb.m_startBit;
+ const int n = cb.m_n;
+ const int nWGs = cb.m_nWGs;
+ const int nBlocksPerWG = cb.m_nBlocksPerWG;
+
+ for(int i=0; i<NUM_BUCKET; i++)
+ {
+ MY_HISTOGRAM(i) = 0;
+ }
+
+ GROUP_LDS_BARRIER;
+
+ const int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE;
+ u32 localKey;
+
+ int nBlocks = (n)/blockSize - nBlocksPerWG*wgIdx;
+
+ int addr = blockSize*nBlocksPerWG*wgIdx + ELEMENTS_PER_WORK_ITEM*lIdx;
+
+ for(int iblock=0; iblock<min(nBlocksPerWG, nBlocks); iblock++, addr+=blockSize)
+ {
+ // MY_HISTOGRAM( localKeys.x ) ++ is much expensive than atomic add as it requires read and write while atomics can just add on AMD
+ // Using registers didn't perform well. It seems like use localKeys to address requires a lot of alu ops
+ // AMD: AtomInc performs better while NV prefers ++
+ for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)
+ {
+#if defined(CHECK_BOUNDARY)
+ if( addr+i < n )
+#endif
+ {
+ localKey = (gSrc[addr+i].m_key>>startBit) & 0xf;
+#if defined(NV_GPU)
+ MY_HISTOGRAM( localKey )++;
+#else
+ AtomInc( MY_HISTOGRAM( localKey ) );
+#endif
+ }
+ }
+ }
+
+ GROUP_LDS_BARRIER;
+
+ if( lIdx < NUM_BUCKET )
+ {
+ u32 sum = 0;
+ for(int i=0; i<GET_GROUP_SIZE; i++)
+ {
+ sum += localHistogramMat[lIdx*WG_SIZE+(i+lIdx)%GET_GROUP_SIZE];
+ }
+ histogramOut[lIdx*nWGs+wgIdx] = sum;
+ }
+}
+
+#define nPerLane (nPerWI/4)
+
+// NUM_BUCKET*nWGs < 128*nPerWI
+__kernel
+__attribute__((reqd_work_group_size(128,1,1)))
+void PrefixScanKernel( __global u32* wHistogram1, int4 cb )
+{
+ __local u32 ldsTopScanData[128*2];
+
+ u32 lIdx = GET_LOCAL_IDX;
+ u32 wgIdx = GET_GROUP_IDX;
+ const int nWGs = cb.m_nWGs;
+
+ u32 data[nPerWI];
+ for(int i=0; i<nPerWI; i++)
+ {
+ data[i] = 0;
+ if( (nPerWI*lIdx+i) < NUM_BUCKET*nWGs )
+ data[i] = wHistogram1[nPerWI*lIdx+i];
+ }
+
+ uint4 myData = make_uint4(0,0,0,0);
+
+ for(int i=0; i<nPerLane; i++)
+ {
+ myData.x += data[nPerLane*0+i];
+ myData.y += data[nPerLane*1+i];
+ myData.z += data[nPerLane*2+i];
+ myData.w += data[nPerLane*3+i];
+ }
+
+ uint totalSum;
+ uint4 scanned = localPrefixSum128V( myData, lIdx, &totalSum, ldsTopScanData );
+
+// for(int j=0; j<4; j++) // somehow it introduces a lot of branches
+ { int j = 0;
+ u32 sum = 0;
+ for(int i=0; i<nPerLane; i++)
+ {
+ u32 tmp = data[nPerLane*j+i];
+ data[nPerLane*j+i] = sum;
+ sum += tmp;
+ }
+ }
+ { int j = 1;
+ u32 sum = 0;
+ for(int i=0; i<nPerLane; i++)
+ {
+ u32 tmp = data[nPerLane*j+i];
+ data[nPerLane*j+i] = sum;
+ sum += tmp;
+ }
+ }
+ { int j = 2;
+ u32 sum = 0;
+ for(int i=0; i<nPerLane; i++)
+ {
+ u32 tmp = data[nPerLane*j+i];
+ data[nPerLane*j+i] = sum;
+ sum += tmp;
+ }
+ }
+ { int j = 3;
+ u32 sum = 0;
+ for(int i=0; i<nPerLane; i++)
+ {
+ u32 tmp = data[nPerLane*j+i];
+ data[nPerLane*j+i] = sum;
+ sum += tmp;
+ }
+ }
+
+ for(int i=0; i<nPerLane; i++)
+ {
+ data[nPerLane*0+i] += scanned.x;
+ data[nPerLane*1+i] += scanned.y;
+ data[nPerLane*2+i] += scanned.z;
+ data[nPerLane*3+i] += scanned.w;
+ }
+
+ for(int i=0; i<nPerWI; i++)
+ {
+ int index = nPerWI*lIdx+i;
+ if (index < NUM_BUCKET*nWGs)
+ wHistogram1[nPerWI*lIdx+i] = data[i];
+ }
+}
+
+// 4 scan, 4 exchange
+void sort4Bits(u32 sortData[4], int startBit, int lIdx, __local u32* ldsSortData)
+{
+ for(int bitIdx=0; bitIdx<BITS_PER_PASS; bitIdx++)
+ {
+ u32 mask = (1<<bitIdx);
+ uint4 cmpResult = make_uint4( (sortData[0]>>startBit) & mask, (sortData[1]>>startBit) & mask, (sortData[2]>>startBit) & mask, (sortData[3]>>startBit) & mask );
+ uint4 prefixSum = SELECT_UINT4( make_uint4(1,1,1,1), make_uint4(0,0,0,0), cmpResult != make_uint4(0,0,0,0) );
+ u32 total;
+ prefixSum = localPrefixSum64V( prefixSum, lIdx, &total, ldsSortData );
+ {
+ uint4 localAddr = make_uint4(lIdx*4+0,lIdx*4+1,lIdx*4+2,lIdx*4+3);
+ uint4 dstAddr = localAddr - prefixSum + make_uint4( total, total, total, total );
+ dstAddr = SELECT_UINT4( prefixSum, dstAddr, cmpResult != make_uint4(0, 0, 0, 0) );
+
+ GROUP_LDS_BARRIER;
+
+ ldsSortData[dstAddr.x] = sortData[0];
+ ldsSortData[dstAddr.y] = sortData[1];
+ ldsSortData[dstAddr.z] = sortData[2];
+ ldsSortData[dstAddr.w] = sortData[3];
+
+ GROUP_LDS_BARRIER;
+
+ sortData[0] = ldsSortData[localAddr.x];
+ sortData[1] = ldsSortData[localAddr.y];
+ sortData[2] = ldsSortData[localAddr.z];
+ sortData[3] = ldsSortData[localAddr.w];
+
+ GROUP_LDS_BARRIER;
+ }
+ }
+}
+
+// 2 scan, 2 exchange
+void sort4Bits1(u32 sortData[4], int startBit, int lIdx, __local u32* ldsSortData)
+{
+ for(uint ibit=0; ibit<BITS_PER_PASS; ibit+=2)
+ {
+ uint4 b = make_uint4((sortData[0]>>(startBit+ibit)) & 0x3,
+ (sortData[1]>>(startBit+ibit)) & 0x3,
+ (sortData[2]>>(startBit+ibit)) & 0x3,
+ (sortData[3]>>(startBit+ibit)) & 0x3);
+
+ u32 key4;
+ u32 sKeyPacked[4] = { 0, 0, 0, 0 };
+ {
+ sKeyPacked[0] |= 1<<(8*b.x);
+ sKeyPacked[1] |= 1<<(8*b.y);
+ sKeyPacked[2] |= 1<<(8*b.z);
+ sKeyPacked[3] |= 1<<(8*b.w);
+
+ key4 = sKeyPacked[0] + sKeyPacked[1] + sKeyPacked[2] + sKeyPacked[3];
+ }
+
+ u32 rankPacked;
+ u32 sumPacked;
+ {
+ rankPacked = localPrefixSum( key4, lIdx, &sumPacked, ldsSortData, WG_SIZE );
+ }
+
+ GROUP_LDS_BARRIER;
+
+ u32 newOffset[4] = { 0,0,0,0 };
+ {
+ u32 sumScanned = bit8Scan( sumPacked );
+
+ u32 scannedKeys[4];
+ scannedKeys[0] = 1<<(8*b.x);
+ scannedKeys[1] = 1<<(8*b.y);
+ scannedKeys[2] = 1<<(8*b.z);
+ scannedKeys[3] = 1<<(8*b.w);
+ { // 4 scans at once
+ u32 sum4 = 0;
+ for(int ie=0; ie<4; ie++)
+ {
+ u32 tmp = scannedKeys[ie];
+ scannedKeys[ie] = sum4;
+ sum4 += tmp;
+ }
+ }
+
+ {
+ u32 sumPlusRank = sumScanned + rankPacked;
+ { u32 ie = b.x;
+ scannedKeys[0] += sumPlusRank;
+ newOffset[0] = unpack4Key( scannedKeys[0], ie );
+ }
+ { u32 ie = b.y;
+ scannedKeys[1] += sumPlusRank;
+ newOffset[1] = unpack4Key( scannedKeys[1], ie );
+ }
+ { u32 ie = b.z;
+ scannedKeys[2] += sumPlusRank;
+ newOffset[2] = unpack4Key( scannedKeys[2], ie );
+ }
+ { u32 ie = b.w;
+ scannedKeys[3] += sumPlusRank;
+ newOffset[3] = unpack4Key( scannedKeys[3], ie );
+ }
+ }
+ }
+
+
+ GROUP_LDS_BARRIER;
+
+ {
+ ldsSortData[newOffset[0]] = sortData[0];
+ ldsSortData[newOffset[1]] = sortData[1];
+ ldsSortData[newOffset[2]] = sortData[2];
+ ldsSortData[newOffset[3]] = sortData[3];
+
+ GROUP_LDS_BARRIER;
+
+ u32 dstAddr = 4*lIdx;
+ sortData[0] = ldsSortData[dstAddr+0];
+ sortData[1] = ldsSortData[dstAddr+1];
+ sortData[2] = ldsSortData[dstAddr+2];
+ sortData[3] = ldsSortData[dstAddr+3];
+
+ GROUP_LDS_BARRIER;
+ }
+ }
+}
+
+#define SET_HISTOGRAM(setIdx, key) ldsSortData[(setIdx)*NUM_BUCKET+key]
+
+__kernel
+__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
+void SortAndScatterKernel( __global const u32* restrict gSrc, __global const u32* rHistogram, __global u32* restrict gDst, int4 cb )
+{
+ __local u32 ldsSortData[WG_SIZE*ELEMENTS_PER_WORK_ITEM+16];
+ __local u32 localHistogramToCarry[NUM_BUCKET];
+ __local u32 localHistogram[NUM_BUCKET*2];
+
+ u32 gIdx = GET_GLOBAL_IDX;
+ u32 lIdx = GET_LOCAL_IDX;
+ u32 wgIdx = GET_GROUP_IDX;
+ u32 wgSize = GET_GROUP_SIZE;
+
+ const int n = cb.m_n;
+ const int nWGs = cb.m_nWGs;
+ const int startBit = cb.m_startBit;
+ const int nBlocksPerWG = cb.m_nBlocksPerWG;
+
+ if( lIdx < (NUM_BUCKET) )
+ {
+ localHistogramToCarry[lIdx] = rHistogram[lIdx*nWGs + wgIdx];
+ }
+
+ GROUP_LDS_BARRIER;
+
+ const int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE;
+
+ int nBlocks = n/blockSize - nBlocksPerWG*wgIdx;
+
+ int addr = blockSize*nBlocksPerWG*wgIdx + ELEMENTS_PER_WORK_ITEM*lIdx;
+
+ for(int iblock=0; iblock<min(nBlocksPerWG, nBlocks); iblock++, addr+=blockSize)
+ {
+ u32 myHistogram = 0;
+
+ u32 sortData[ELEMENTS_PER_WORK_ITEM];
+ for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)
+#if defined(CHECK_BOUNDARY)
+ sortData[i] = ( addr+i < n )? gSrc[ addr+i ] : 0xffffffff;
+#else
+ sortData[i] = gSrc[ addr+i ];
+#endif
+
+ sort4Bits(sortData, startBit, lIdx, ldsSortData);
+
+ u32 keys[ELEMENTS_PER_WORK_ITEM];
+ for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)
+ keys[i] = (sortData[i]>>startBit) & 0xf;
+
+ { // create histogram
+ u32 setIdx = lIdx/16;
+ if( lIdx < NUM_BUCKET )
+ {
+ localHistogram[lIdx] = 0;
+ }
+ ldsSortData[lIdx] = 0;
+ GROUP_LDS_BARRIER;
+
+ for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)
+#if defined(CHECK_BOUNDARY)
+ if( addr+i < n )
+#endif
+
+#if defined(NV_GPU)
+ SET_HISTOGRAM( setIdx, keys[i] )++;
+#else
+ AtomInc( SET_HISTOGRAM( setIdx, keys[i] ) );
+#endif
+
+ GROUP_LDS_BARRIER;
+
+ uint hIdx = NUM_BUCKET+lIdx;
+ if( lIdx < NUM_BUCKET )
+ {
+ u32 sum = 0;
+ for(int i=0; i<WG_SIZE/16; i++)
+ {
+ sum += SET_HISTOGRAM( i, lIdx );
+ }
+ myHistogram = sum;
+ localHistogram[hIdx] = sum;
+ }
+ GROUP_LDS_BARRIER;
+
+#if defined(USE_2LEVEL_REDUCE)
+ if( lIdx < NUM_BUCKET )
+ {
+ localHistogram[hIdx] = localHistogram[hIdx-1];
+ GROUP_MEM_FENCE;
+
+ u32 u0, u1, u2;
+ u0 = localHistogram[hIdx-3];
+ u1 = localHistogram[hIdx-2];
+ u2 = localHistogram[hIdx-1];
+ AtomAdd( localHistogram[hIdx], u0 + u1 + u2 );
+ GROUP_MEM_FENCE;
+ u0 = localHistogram[hIdx-12];
+ u1 = localHistogram[hIdx-8];
+ u2 = localHistogram[hIdx-4];
+ AtomAdd( localHistogram[hIdx], u0 + u1 + u2 );
+ GROUP_MEM_FENCE;
+ }
+#else
+ if( lIdx < NUM_BUCKET )
+ {
+ localHistogram[hIdx] = localHistogram[hIdx-1];
+ GROUP_MEM_FENCE;
+ localHistogram[hIdx] += localHistogram[hIdx-1];
+ GROUP_MEM_FENCE;
+ localHistogram[hIdx] += localHistogram[hIdx-2];
+ GROUP_MEM_FENCE;
+ localHistogram[hIdx] += localHistogram[hIdx-4];
+ GROUP_MEM_FENCE;
+ localHistogram[hIdx] += localHistogram[hIdx-8];
+ GROUP_MEM_FENCE;
+ }
+#endif
+ GROUP_LDS_BARRIER;
+ }
+
+ {
+ for(int ie=0; ie<ELEMENTS_PER_WORK_ITEM; ie++)
+ {
+ int dataIdx = ELEMENTS_PER_WORK_ITEM*lIdx+ie;
+ int binIdx = keys[ie];
+ int groupOffset = localHistogramToCarry[binIdx];
+ int myIdx = dataIdx - localHistogram[NUM_BUCKET+binIdx];
+#if defined(CHECK_BOUNDARY)
+ if( addr+ie < n )
+#endif
+ gDst[ groupOffset + myIdx ] = sortData[ie];
+ }
+ }
+
+ GROUP_LDS_BARRIER;
+
+ if( lIdx < NUM_BUCKET )
+ {
+ localHistogramToCarry[lIdx] += myHistogram;
+ }
+ GROUP_LDS_BARRIER;
+ }
+}
+
+// 2 scan, 2 exchange
+void sort4Bits1KeyValue(u32 sortData[4], int sortVal[4], int startBit, int lIdx, __local u32* ldsSortData, __local int *ldsSortVal)
+{
+ for(uint ibit=0; ibit<BITS_PER_PASS; ibit+=2)
+ {
+ uint4 b = make_uint4((sortData[0]>>(startBit+ibit)) & 0x3,
+ (sortData[1]>>(startBit+ibit)) & 0x3,
+ (sortData[2]>>(startBit+ibit)) & 0x3,
+ (sortData[3]>>(startBit+ibit)) & 0x3);
+
+ u32 key4;
+ u32 sKeyPacked[4] = { 0, 0, 0, 0 };
+ {
+ sKeyPacked[0] |= 1<<(8*b.x);
+ sKeyPacked[1] |= 1<<(8*b.y);
+ sKeyPacked[2] |= 1<<(8*b.z);
+ sKeyPacked[3] |= 1<<(8*b.w);
+
+ key4 = sKeyPacked[0] + sKeyPacked[1] + sKeyPacked[2] + sKeyPacked[3];
+ }
+
+ u32 rankPacked;
+ u32 sumPacked;
+ {
+ rankPacked = localPrefixSum( key4, lIdx, &sumPacked, ldsSortData, WG_SIZE );
+ }
+
+ GROUP_LDS_BARRIER;
+
+ u32 newOffset[4] = { 0,0,0,0 };
+ {
+ u32 sumScanned = bit8Scan( sumPacked );
+
+ u32 scannedKeys[4];
+ scannedKeys[0] = 1<<(8*b.x);
+ scannedKeys[1] = 1<<(8*b.y);
+ scannedKeys[2] = 1<<(8*b.z);
+ scannedKeys[3] = 1<<(8*b.w);
+ { // 4 scans at once
+ u32 sum4 = 0;
+ for(int ie=0; ie<4; ie++)
+ {
+ u32 tmp = scannedKeys[ie];
+ scannedKeys[ie] = sum4;
+ sum4 += tmp;
+ }
+ }
+
+ {
+ u32 sumPlusRank = sumScanned + rankPacked;
+ { u32 ie = b.x;
+ scannedKeys[0] += sumPlusRank;
+ newOffset[0] = unpack4Key( scannedKeys[0], ie );
+ }
+ { u32 ie = b.y;
+ scannedKeys[1] += sumPlusRank;
+ newOffset[1] = unpack4Key( scannedKeys[1], ie );
+ }
+ { u32 ie = b.z;
+ scannedKeys[2] += sumPlusRank;
+ newOffset[2] = unpack4Key( scannedKeys[2], ie );
+ }
+ { u32 ie = b.w;
+ scannedKeys[3] += sumPlusRank;
+ newOffset[3] = unpack4Key( scannedKeys[3], ie );
+ }
+ }
+ }
+
+
+ GROUP_LDS_BARRIER;
+
+ {
+ ldsSortData[newOffset[0]] = sortData[0];
+ ldsSortData[newOffset[1]] = sortData[1];
+ ldsSortData[newOffset[2]] = sortData[2];
+ ldsSortData[newOffset[3]] = sortData[3];
+
+ ldsSortVal[newOffset[0]] = sortVal[0];
+ ldsSortVal[newOffset[1]] = sortVal[1];
+ ldsSortVal[newOffset[2]] = sortVal[2];
+ ldsSortVal[newOffset[3]] = sortVal[3];
+
+ GROUP_LDS_BARRIER;
+
+ u32 dstAddr = 4*lIdx;
+ sortData[0] = ldsSortData[dstAddr+0];
+ sortData[1] = ldsSortData[dstAddr+1];
+ sortData[2] = ldsSortData[dstAddr+2];
+ sortData[3] = ldsSortData[dstAddr+3];
+
+ sortVal[0] = ldsSortVal[dstAddr+0];
+ sortVal[1] = ldsSortVal[dstAddr+1];
+ sortVal[2] = ldsSortVal[dstAddr+2];
+ sortVal[3] = ldsSortVal[dstAddr+3];
+
+ GROUP_LDS_BARRIER;
+ }
+ }
+}
+
+
+
+
+__kernel
+__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
+void SortAndScatterSortDataKernel( __global const SortDataCL* restrict gSrc, __global const u32* rHistogram, __global SortDataCL* restrict gDst, int4 cb)
+{
+ __local int ldsSortData[WG_SIZE*ELEMENTS_PER_WORK_ITEM+16];
+ __local int ldsSortVal[WG_SIZE*ELEMENTS_PER_WORK_ITEM+16];
+ __local u32 localHistogramToCarry[NUM_BUCKET];
+ __local u32 localHistogram[NUM_BUCKET*2];
+
+ u32 gIdx = GET_GLOBAL_IDX;
+ u32 lIdx = GET_LOCAL_IDX;
+ u32 wgIdx = GET_GROUP_IDX;
+ u32 wgSize = GET_GROUP_SIZE;
+
+ const int n = cb.m_n;
+ const int nWGs = cb.m_nWGs;
+ const int startBit = cb.m_startBit;
+ const int nBlocksPerWG = cb.m_nBlocksPerWG;
+
+ if( lIdx < (NUM_BUCKET) )
+ {
+ localHistogramToCarry[lIdx] = rHistogram[lIdx*nWGs + wgIdx];
+ }
+
+ GROUP_LDS_BARRIER;
+
+
+ const int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE;
+
+ int nBlocks = n/blockSize - nBlocksPerWG*wgIdx;
+
+ int addr = blockSize*nBlocksPerWG*wgIdx + ELEMENTS_PER_WORK_ITEM*lIdx;
+
+ for(int iblock=0; iblock<min(nBlocksPerWG, nBlocks); iblock++, addr+=blockSize)
+ {
+
+ u32 myHistogram = 0;
+
+ int sortData[ELEMENTS_PER_WORK_ITEM];
+ int sortVal[ELEMENTS_PER_WORK_ITEM];
+
+ for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)
+#if defined(CHECK_BOUNDARY)
+ {
+ sortData[i] = ( addr+i < n )? gSrc[ addr+i ].m_key : 0xffffffff;
+ sortVal[i] = ( addr+i < n )? gSrc[ addr+i ].m_value : 0xffffffff;
+ }
+#else
+ {
+ sortData[i] = gSrc[ addr+i ].m_key;
+ sortVal[i] = gSrc[ addr+i ].m_value;
+ }
+#endif
+
+ sort4Bits1KeyValue(sortData, sortVal, startBit, lIdx, ldsSortData, ldsSortVal);
+
+ u32 keys[ELEMENTS_PER_WORK_ITEM];
+ for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)
+ keys[i] = (sortData[i]>>startBit) & 0xf;
+
+ { // create histogram
+ u32 setIdx = lIdx/16;
+ if( lIdx < NUM_BUCKET )
+ {
+ localHistogram[lIdx] = 0;
+ }
+ ldsSortData[lIdx] = 0;
+ GROUP_LDS_BARRIER;
+
+ for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)
+#if defined(CHECK_BOUNDARY)
+ if( addr+i < n )
+#endif
+
+#if defined(NV_GPU)
+ SET_HISTOGRAM( setIdx, keys[i] )++;
+#else
+ AtomInc( SET_HISTOGRAM( setIdx, keys[i] ) );
+#endif
+
+ GROUP_LDS_BARRIER;
+
+ uint hIdx = NUM_BUCKET+lIdx;
+ if( lIdx < NUM_BUCKET )
+ {
+ u32 sum = 0;
+ for(int i=0; i<WG_SIZE/16; i++)
+ {
+ sum += SET_HISTOGRAM( i, lIdx );
+ }
+ myHistogram = sum;
+ localHistogram[hIdx] = sum;
+ }
+ GROUP_LDS_BARRIER;
+
+#if defined(USE_2LEVEL_REDUCE)
+ if( lIdx < NUM_BUCKET )
+ {
+ localHistogram[hIdx] = localHistogram[hIdx-1];
+ GROUP_MEM_FENCE;
+
+ u32 u0, u1, u2;
+ u0 = localHistogram[hIdx-3];
+ u1 = localHistogram[hIdx-2];
+ u2 = localHistogram[hIdx-1];
+ AtomAdd( localHistogram[hIdx], u0 + u1 + u2 );
+ GROUP_MEM_FENCE;
+ u0 = localHistogram[hIdx-12];
+ u1 = localHistogram[hIdx-8];
+ u2 = localHistogram[hIdx-4];
+ AtomAdd( localHistogram[hIdx], u0 + u1 + u2 );
+ GROUP_MEM_FENCE;
+ }
+#else
+ if( lIdx < NUM_BUCKET )
+ {
+ localHistogram[hIdx] = localHistogram[hIdx-1];
+ GROUP_MEM_FENCE;
+ localHistogram[hIdx] += localHistogram[hIdx-1];
+ GROUP_MEM_FENCE;
+ localHistogram[hIdx] += localHistogram[hIdx-2];
+ GROUP_MEM_FENCE;
+ localHistogram[hIdx] += localHistogram[hIdx-4];
+ GROUP_MEM_FENCE;
+ localHistogram[hIdx] += localHistogram[hIdx-8];
+ GROUP_MEM_FENCE;
+ }
+#endif
+ GROUP_LDS_BARRIER;
+ }
+
+ {
+ for(int ie=0; ie<ELEMENTS_PER_WORK_ITEM; ie++)
+ {
+ int dataIdx = ELEMENTS_PER_WORK_ITEM*lIdx+ie;
+ int binIdx = keys[ie];
+ int groupOffset = localHistogramToCarry[binIdx];
+ int myIdx = dataIdx - localHistogram[NUM_BUCKET+binIdx];
+#if defined(CHECK_BOUNDARY)
+ if( addr+ie < n )
+ {
+ if ((groupOffset + myIdx)<n)
+ {
+ if (sortData[ie]==sortVal[ie])
+ {
+
+ SortDataCL tmp;
+ tmp.m_key = sortData[ie];
+ tmp.m_value = sortVal[ie];
+ if (tmp.m_key == tmp.m_value)
+ gDst[groupOffset + myIdx ] = tmp;
+ }
+
+ }
+ }
+#else
+ if ((groupOffset + myIdx)<n)
+ {
+ gDst[ groupOffset + myIdx ].m_key = sortData[ie];
+ gDst[ groupOffset + myIdx ].m_value = sortVal[ie];
+ }
+#endif
+ }
+ }
+
+ GROUP_LDS_BARRIER;
+
+ if( lIdx < NUM_BUCKET )
+ {
+ localHistogramToCarry[lIdx] += myHistogram;
+ }
+ GROUP_LDS_BARRIER;
+ }
+}
+
+
+
+
+
+
+
+__kernel
+__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
+void SortAndScatterSortDataKernelSerial( __global const SortDataCL* restrict gSrc, __global const u32* rHistogram, __global SortDataCL* restrict gDst, int4 cb)
+{
+
+ u32 gIdx = GET_GLOBAL_IDX;
+ u32 realLocalIdx = GET_LOCAL_IDX;
+ u32 wgIdx = GET_GROUP_IDX;
+ u32 wgSize = GET_GROUP_SIZE;
+ const int startBit = cb.m_startBit;
+ const int n = cb.m_n;
+ const int nWGs = cb.m_nWGs;
+ const int nBlocksPerWG = cb.m_nBlocksPerWG;
+
+ int counter[NUM_BUCKET];
+
+ if (realLocalIdx>0)
+ return;
+
+ for (int c=0;c<NUM_BUCKET;c++)
+ counter[c]=0;
+
+ const int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE;
+
+ int nBlocks = (n)/blockSize - nBlocksPerWG*wgIdx;
+
+ for(int iblock=0; iblock<min(nBlocksPerWG, nBlocks); iblock++)
+ {
+ for (int lIdx=0;lIdx<WG_SIZE;lIdx++)
+ {
+ int addr2 = iblock*blockSize + blockSize*nBlocksPerWG*wgIdx + ELEMENTS_PER_WORK_ITEM*lIdx;
+
+ for(int j=0; j<ELEMENTS_PER_WORK_ITEM; j++)
+ {
+ int i = addr2+j;
+ if( i < n )
+ {
+ int tableIdx;
+ tableIdx = (gSrc[i].m_key>>startBit) & 0xf;//0xf = NUM_TABLES-1
+ gDst[rHistogram[tableIdx*nWGs+wgIdx] + counter[tableIdx]] = gSrc[i];
+ counter[tableIdx] ++;
+ }
+ }
+ }
+ }
+
+}
+
+
+__kernel
+__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
+void SortAndScatterKernelSerial( __global const u32* restrict gSrc, __global const u32* rHistogram, __global u32* restrict gDst, int4 cb )
+{
+
+ u32 gIdx = GET_GLOBAL_IDX;
+ u32 realLocalIdx = GET_LOCAL_IDX;
+ u32 wgIdx = GET_GROUP_IDX;
+ u32 wgSize = GET_GROUP_SIZE;
+ const int startBit = cb.m_startBit;
+ const int n = cb.m_n;
+ const int nWGs = cb.m_nWGs;
+ const int nBlocksPerWG = cb.m_nBlocksPerWG;
+
+ int counter[NUM_BUCKET];
+
+ if (realLocalIdx>0)
+ return;
+
+ for (int c=0;c<NUM_BUCKET;c++)
+ counter[c]=0;
+
+ const int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE;
+
+ int nBlocks = (n)/blockSize - nBlocksPerWG*wgIdx;
+
+ for(int iblock=0; iblock<min(nBlocksPerWG, nBlocks); iblock++)
+ {
+ for (int lIdx=0;lIdx<WG_SIZE;lIdx++)
+ {
+ int addr2 = iblock*blockSize + blockSize*nBlocksPerWG*wgIdx + ELEMENTS_PER_WORK_ITEM*lIdx;
+
+ for(int j=0; j<ELEMENTS_PER_WORK_ITEM; j++)
+ {
+ int i = addr2+j;
+ if( i < n )
+ {
+ int tableIdx;
+ tableIdx = (gSrc[i]>>startBit) & 0xf;//0xf = NUM_TABLES-1
+ gDst[rHistogram[tableIdx*nWGs+wgIdx] + counter[tableIdx]] = gSrc[i];
+ counter[tableIdx] ++;
+ }
+ }
+ }
+ }
+
+} \ No newline at end of file
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/kernels/RadixSort32KernelsCL.h b/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/kernels/RadixSort32KernelsCL.h
new file mode 100644
index 0000000000..8876c16aa6
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/ParallelPrimitives/kernels/RadixSort32KernelsCL.h
@@ -0,0 +1,910 @@
+//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
+static const char* radixSort32KernelsCL= \
+"/*\n"
+"Bullet Continuous Collision Detection and Physics Library\n"
+"Copyright (c) 2011 Advanced Micro Devices, Inc. http://bulletphysics.org\n"
+"This software is provided 'as-is', without any express or implied warranty.\n"
+"In no event will the authors be held liable for any damages arising from the use of this software.\n"
+"Permission is granted to anyone to use this software for any purpose, \n"
+"including commercial applications, and to alter it and redistribute it freely, \n"
+"subject to the following restrictions:\n"
+"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.\n"
+"2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
+"3. This notice may not be removed or altered from any source distribution.\n"
+"*/\n"
+"//Author Takahiro Harada\n"
+"//#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
+"#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
+"#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
+"typedef unsigned int u32;\n"
+"#define GET_GROUP_IDX get_group_id(0)\n"
+"#define GET_LOCAL_IDX get_local_id(0)\n"
+"#define GET_GLOBAL_IDX get_global_id(0)\n"
+"#define GET_GROUP_SIZE get_local_size(0)\n"
+"#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
+"#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
+"#define AtomInc(x) atom_inc(&(x))\n"
+"#define AtomInc1(x, out) out = atom_inc(&(x))\n"
+"#define AtomAdd(x, value) atom_add(&(x), value)\n"
+"#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n"
+"#define make_uint4 (uint4)\n"
+"#define make_uint2 (uint2)\n"
+"#define make_int2 (int2)\n"
+"#define WG_SIZE 64\n"
+"#define ELEMENTS_PER_WORK_ITEM (256/WG_SIZE)\n"
+"#define BITS_PER_PASS 4\n"
+"#define NUM_BUCKET (1<<BITS_PER_PASS)\n"
+"typedef uchar u8;\n"
+"// this isn't optimization for VLIW. But just reducing writes. \n"
+"#define USE_2LEVEL_REDUCE 1\n"
+"//#define CHECK_BOUNDARY 1\n"
+"//#define NV_GPU 1\n"
+"// Cypress\n"
+"#define nPerWI 16\n"
+"// Cayman\n"
+"//#define nPerWI 20\n"
+"#define m_n x\n"
+"#define m_nWGs y\n"
+"#define m_startBit z\n"
+"#define m_nBlocksPerWG w\n"
+"/*\n"
+"typedef struct\n"
+"{\n"
+" int m_n;\n"
+" int m_nWGs;\n"
+" int m_startBit;\n"
+" int m_nBlocksPerWG;\n"
+"} ConstBuffer;\n"
+"*/\n"
+"typedef struct\n"
+"{\n"
+" unsigned int m_key;\n"
+" unsigned int m_value;\n"
+"} SortDataCL;\n"
+"uint prefixScanVectorEx( uint4* data )\n"
+"{\n"
+" u32 sum = 0;\n"
+" u32 tmp = data[0].x;\n"
+" data[0].x = sum;\n"
+" sum += tmp;\n"
+" tmp = data[0].y;\n"
+" data[0].y = sum;\n"
+" sum += tmp;\n"
+" tmp = data[0].z;\n"
+" data[0].z = sum;\n"
+" sum += tmp;\n"
+" tmp = data[0].w;\n"
+" data[0].w = sum;\n"
+" sum += tmp;\n"
+" return sum;\n"
+"}\n"
+"u32 localPrefixSum( u32 pData, uint lIdx, uint* totalSum, __local u32* sorterSharedMemory, int wgSize /*64 or 128*/ )\n"
+"{\n"
+" { // Set data\n"
+" sorterSharedMemory[lIdx] = 0;\n"
+" sorterSharedMemory[lIdx+wgSize] = pData;\n"
+" }\n"
+" GROUP_LDS_BARRIER;\n"
+" { // Prefix sum\n"
+" int idx = 2*lIdx + (wgSize+1);\n"
+"#if defined(USE_2LEVEL_REDUCE)\n"
+" if( lIdx < 64 )\n"
+" {\n"
+" u32 u0, u1, u2;\n"
+" u0 = sorterSharedMemory[idx-3];\n"
+" u1 = sorterSharedMemory[idx-2];\n"
+" u2 = sorterSharedMemory[idx-1];\n"
+" AtomAdd( sorterSharedMemory[idx], u0+u1+u2 ); \n"
+" GROUP_MEM_FENCE;\n"
+" u0 = sorterSharedMemory[idx-12];\n"
+" u1 = sorterSharedMemory[idx-8];\n"
+" u2 = sorterSharedMemory[idx-4];\n"
+" AtomAdd( sorterSharedMemory[idx], u0+u1+u2 ); \n"
+" GROUP_MEM_FENCE;\n"
+" u0 = sorterSharedMemory[idx-48];\n"
+" u1 = sorterSharedMemory[idx-32];\n"
+" u2 = sorterSharedMemory[idx-16];\n"
+" AtomAdd( sorterSharedMemory[idx], u0+u1+u2 ); \n"
+" GROUP_MEM_FENCE;\n"
+" if( wgSize > 64 )\n"
+" {\n"
+" sorterSharedMemory[idx] += sorterSharedMemory[idx-64];\n"
+" GROUP_MEM_FENCE;\n"
+" }\n"
+" sorterSharedMemory[idx-1] += sorterSharedMemory[idx-2];\n"
+" GROUP_MEM_FENCE;\n"
+" }\n"
+"#else\n"
+" if( lIdx < 64 )\n"
+" {\n"
+" sorterSharedMemory[idx] += sorterSharedMemory[idx-1];\n"
+" GROUP_MEM_FENCE;\n"
+" sorterSharedMemory[idx] += sorterSharedMemory[idx-2]; \n"
+" GROUP_MEM_FENCE;\n"
+" sorterSharedMemory[idx] += sorterSharedMemory[idx-4];\n"
+" GROUP_MEM_FENCE;\n"
+" sorterSharedMemory[idx] += sorterSharedMemory[idx-8];\n"
+" GROUP_MEM_FENCE;\n"
+" sorterSharedMemory[idx] += sorterSharedMemory[idx-16];\n"
+" GROUP_MEM_FENCE;\n"
+" sorterSharedMemory[idx] += sorterSharedMemory[idx-32];\n"
+" GROUP_MEM_FENCE;\n"
+" if( wgSize > 64 )\n"
+" {\n"
+" sorterSharedMemory[idx] += sorterSharedMemory[idx-64];\n"
+" GROUP_MEM_FENCE;\n"
+" }\n"
+" sorterSharedMemory[idx-1] += sorterSharedMemory[idx-2];\n"
+" GROUP_MEM_FENCE;\n"
+" }\n"
+"#endif\n"
+" }\n"
+" GROUP_LDS_BARRIER;\n"
+" *totalSum = sorterSharedMemory[wgSize*2-1];\n"
+" u32 addValue = sorterSharedMemory[lIdx+wgSize-1];\n"
+" return addValue;\n"
+"}\n"
+"//__attribute__((reqd_work_group_size(128,1,1)))\n"
+"uint4 localPrefixSum128V( uint4 pData, uint lIdx, uint* totalSum, __local u32* sorterSharedMemory )\n"
+"{\n"
+" u32 s4 = prefixScanVectorEx( &pData );\n"
+" u32 rank = localPrefixSum( s4, lIdx, totalSum, sorterSharedMemory, 128 );\n"
+" return pData + make_uint4( rank, rank, rank, rank );\n"
+"}\n"
+"//__attribute__((reqd_work_group_size(64,1,1)))\n"
+"uint4 localPrefixSum64V( uint4 pData, uint lIdx, uint* totalSum, __local u32* sorterSharedMemory )\n"
+"{\n"
+" u32 s4 = prefixScanVectorEx( &pData );\n"
+" u32 rank = localPrefixSum( s4, lIdx, totalSum, sorterSharedMemory, 64 );\n"
+" return pData + make_uint4( rank, rank, rank, rank );\n"
+"}\n"
+"u32 unpack4Key( u32 key, int keyIdx ){ return (key>>(keyIdx*8)) & 0xff;}\n"
+"u32 bit8Scan(u32 v)\n"
+"{\n"
+" return (v<<8) + (v<<16) + (v<<24);\n"
+"}\n"
+"//===\n"
+"#define MY_HISTOGRAM(idx) localHistogramMat[(idx)*WG_SIZE+lIdx]\n"
+"__kernel\n"
+"__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+"void StreamCountKernel( __global u32* gSrc, __global u32* histogramOut, int4 cb )\n"
+"{\n"
+" __local u32 localHistogramMat[NUM_BUCKET*WG_SIZE];\n"
+" u32 gIdx = GET_GLOBAL_IDX;\n"
+" u32 lIdx = GET_LOCAL_IDX;\n"
+" u32 wgIdx = GET_GROUP_IDX;\n"
+" u32 wgSize = GET_GROUP_SIZE;\n"
+" const int startBit = cb.m_startBit;\n"
+" const int n = cb.m_n;\n"
+" const int nWGs = cb.m_nWGs;\n"
+" const int nBlocksPerWG = cb.m_nBlocksPerWG;\n"
+" for(int i=0; i<NUM_BUCKET; i++)\n"
+" {\n"
+" MY_HISTOGRAM(i) = 0;\n"
+" }\n"
+" GROUP_LDS_BARRIER;\n"
+" const int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE;\n"
+" u32 localKey;\n"
+" int nBlocks = (n)/blockSize - nBlocksPerWG*wgIdx;\n"
+" int addr = blockSize*nBlocksPerWG*wgIdx + ELEMENTS_PER_WORK_ITEM*lIdx;\n"
+" for(int iblock=0; iblock<min(nBlocksPerWG, nBlocks); iblock++, addr+=blockSize)\n"
+" {\n"
+" // MY_HISTOGRAM( localKeys.x ) ++ is much expensive than atomic add as it requires read and write while atomics can just add on AMD\n"
+" // Using registers didn't perform well. It seems like use localKeys to address requires a lot of alu ops\n"
+" // AMD: AtomInc performs better while NV prefers ++\n"
+" for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)\n"
+" {\n"
+"#if defined(CHECK_BOUNDARY)\n"
+" if( addr+i < n )\n"
+"#endif\n"
+" {\n"
+" localKey = (gSrc[addr+i]>>startBit) & 0xf;\n"
+"#if defined(NV_GPU)\n"
+" MY_HISTOGRAM( localKey )++;\n"
+"#else\n"
+" AtomInc( MY_HISTOGRAM( localKey ) );\n"
+"#endif\n"
+" }\n"
+" }\n"
+" }\n"
+" GROUP_LDS_BARRIER;\n"
+" \n"
+" if( lIdx < NUM_BUCKET )\n"
+" {\n"
+" u32 sum = 0;\n"
+" for(int i=0; i<GET_GROUP_SIZE; i++)\n"
+" {\n"
+" sum += localHistogramMat[lIdx*WG_SIZE+(i+lIdx)%GET_GROUP_SIZE];\n"
+" }\n"
+" histogramOut[lIdx*nWGs+wgIdx] = sum;\n"
+" }\n"
+"}\n"
+"__kernel\n"
+"__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+"void StreamCountSortDataKernel( __global SortDataCL* gSrc, __global u32* histogramOut, int4 cb )\n"
+"{\n"
+" __local u32 localHistogramMat[NUM_BUCKET*WG_SIZE];\n"
+" u32 gIdx = GET_GLOBAL_IDX;\n"
+" u32 lIdx = GET_LOCAL_IDX;\n"
+" u32 wgIdx = GET_GROUP_IDX;\n"
+" u32 wgSize = GET_GROUP_SIZE;\n"
+" const int startBit = cb.m_startBit;\n"
+" const int n = cb.m_n;\n"
+" const int nWGs = cb.m_nWGs;\n"
+" const int nBlocksPerWG = cb.m_nBlocksPerWG;\n"
+" for(int i=0; i<NUM_BUCKET; i++)\n"
+" {\n"
+" MY_HISTOGRAM(i) = 0;\n"
+" }\n"
+" GROUP_LDS_BARRIER;\n"
+" const int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE;\n"
+" u32 localKey;\n"
+" int nBlocks = (n)/blockSize - nBlocksPerWG*wgIdx;\n"
+" int addr = blockSize*nBlocksPerWG*wgIdx + ELEMENTS_PER_WORK_ITEM*lIdx;\n"
+" for(int iblock=0; iblock<min(nBlocksPerWG, nBlocks); iblock++, addr+=blockSize)\n"
+" {\n"
+" // MY_HISTOGRAM( localKeys.x ) ++ is much expensive than atomic add as it requires read and write while atomics can just add on AMD\n"
+" // Using registers didn't perform well. It seems like use localKeys to address requires a lot of alu ops\n"
+" // AMD: AtomInc performs better while NV prefers ++\n"
+" for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)\n"
+" {\n"
+"#if defined(CHECK_BOUNDARY)\n"
+" if( addr+i < n )\n"
+"#endif\n"
+" {\n"
+" localKey = (gSrc[addr+i].m_key>>startBit) & 0xf;\n"
+"#if defined(NV_GPU)\n"
+" MY_HISTOGRAM( localKey )++;\n"
+"#else\n"
+" AtomInc( MY_HISTOGRAM( localKey ) );\n"
+"#endif\n"
+" }\n"
+" }\n"
+" }\n"
+" GROUP_LDS_BARRIER;\n"
+" \n"
+" if( lIdx < NUM_BUCKET )\n"
+" {\n"
+" u32 sum = 0;\n"
+" for(int i=0; i<GET_GROUP_SIZE; i++)\n"
+" {\n"
+" sum += localHistogramMat[lIdx*WG_SIZE+(i+lIdx)%GET_GROUP_SIZE];\n"
+" }\n"
+" histogramOut[lIdx*nWGs+wgIdx] = sum;\n"
+" }\n"
+"}\n"
+"#define nPerLane (nPerWI/4)\n"
+"// NUM_BUCKET*nWGs < 128*nPerWI\n"
+"__kernel\n"
+"__attribute__((reqd_work_group_size(128,1,1)))\n"
+"void PrefixScanKernel( __global u32* wHistogram1, int4 cb )\n"
+"{\n"
+" __local u32 ldsTopScanData[128*2];\n"
+" u32 lIdx = GET_LOCAL_IDX;\n"
+" u32 wgIdx = GET_GROUP_IDX;\n"
+" const int nWGs = cb.m_nWGs;\n"
+" u32 data[nPerWI];\n"
+" for(int i=0; i<nPerWI; i++)\n"
+" {\n"
+" data[i] = 0;\n"
+" if( (nPerWI*lIdx+i) < NUM_BUCKET*nWGs )\n"
+" data[i] = wHistogram1[nPerWI*lIdx+i];\n"
+" }\n"
+" uint4 myData = make_uint4(0,0,0,0);\n"
+" for(int i=0; i<nPerLane; i++)\n"
+" {\n"
+" myData.x += data[nPerLane*0+i];\n"
+" myData.y += data[nPerLane*1+i];\n"
+" myData.z += data[nPerLane*2+i];\n"
+" myData.w += data[nPerLane*3+i];\n"
+" }\n"
+" uint totalSum;\n"
+" uint4 scanned = localPrefixSum128V( myData, lIdx, &totalSum, ldsTopScanData );\n"
+"// for(int j=0; j<4; j++) // somehow it introduces a lot of branches\n"
+" { int j = 0;\n"
+" u32 sum = 0;\n"
+" for(int i=0; i<nPerLane; i++)\n"
+" {\n"
+" u32 tmp = data[nPerLane*j+i];\n"
+" data[nPerLane*j+i] = sum;\n"
+" sum += tmp;\n"
+" }\n"
+" }\n"
+" { int j = 1;\n"
+" u32 sum = 0;\n"
+" for(int i=0; i<nPerLane; i++)\n"
+" {\n"
+" u32 tmp = data[nPerLane*j+i];\n"
+" data[nPerLane*j+i] = sum;\n"
+" sum += tmp;\n"
+" }\n"
+" }\n"
+" { int j = 2;\n"
+" u32 sum = 0;\n"
+" for(int i=0; i<nPerLane; i++)\n"
+" {\n"
+" u32 tmp = data[nPerLane*j+i];\n"
+" data[nPerLane*j+i] = sum;\n"
+" sum += tmp;\n"
+" }\n"
+" }\n"
+" { int j = 3;\n"
+" u32 sum = 0;\n"
+" for(int i=0; i<nPerLane; i++)\n"
+" {\n"
+" u32 tmp = data[nPerLane*j+i];\n"
+" data[nPerLane*j+i] = sum;\n"
+" sum += tmp;\n"
+" }\n"
+" }\n"
+" for(int i=0; i<nPerLane; i++)\n"
+" {\n"
+" data[nPerLane*0+i] += scanned.x;\n"
+" data[nPerLane*1+i] += scanned.y;\n"
+" data[nPerLane*2+i] += scanned.z;\n"
+" data[nPerLane*3+i] += scanned.w;\n"
+" }\n"
+" for(int i=0; i<nPerWI; i++)\n"
+" {\n"
+" int index = nPerWI*lIdx+i;\n"
+" if (index < NUM_BUCKET*nWGs)\n"
+" wHistogram1[nPerWI*lIdx+i] = data[i];\n"
+" }\n"
+"}\n"
+"// 4 scan, 4 exchange\n"
+"void sort4Bits(u32 sortData[4], int startBit, int lIdx, __local u32* ldsSortData)\n"
+"{\n"
+" for(int bitIdx=0; bitIdx<BITS_PER_PASS; bitIdx++)\n"
+" {\n"
+" u32 mask = (1<<bitIdx);\n"
+" uint4 cmpResult = make_uint4( (sortData[0]>>startBit) & mask, (sortData[1]>>startBit) & mask, (sortData[2]>>startBit) & mask, (sortData[3]>>startBit) & mask );\n"
+" uint4 prefixSum = SELECT_UINT4( make_uint4(1,1,1,1), make_uint4(0,0,0,0), cmpResult != make_uint4(0,0,0,0) );\n"
+" u32 total;\n"
+" prefixSum = localPrefixSum64V( prefixSum, lIdx, &total, ldsSortData );\n"
+" {\n"
+" uint4 localAddr = make_uint4(lIdx*4+0,lIdx*4+1,lIdx*4+2,lIdx*4+3);\n"
+" uint4 dstAddr = localAddr - prefixSum + make_uint4( total, total, total, total );\n"
+" dstAddr = SELECT_UINT4( prefixSum, dstAddr, cmpResult != make_uint4(0, 0, 0, 0) );\n"
+" GROUP_LDS_BARRIER;\n"
+" ldsSortData[dstAddr.x] = sortData[0];\n"
+" ldsSortData[dstAddr.y] = sortData[1];\n"
+" ldsSortData[dstAddr.z] = sortData[2];\n"
+" ldsSortData[dstAddr.w] = sortData[3];\n"
+" GROUP_LDS_BARRIER;\n"
+" sortData[0] = ldsSortData[localAddr.x];\n"
+" sortData[1] = ldsSortData[localAddr.y];\n"
+" sortData[2] = ldsSortData[localAddr.z];\n"
+" sortData[3] = ldsSortData[localAddr.w];\n"
+" GROUP_LDS_BARRIER;\n"
+" }\n"
+" }\n"
+"}\n"
+"// 2 scan, 2 exchange\n"
+"void sort4Bits1(u32 sortData[4], int startBit, int lIdx, __local u32* ldsSortData)\n"
+"{\n"
+" for(uint ibit=0; ibit<BITS_PER_PASS; ibit+=2)\n"
+" {\n"
+" uint4 b = make_uint4((sortData[0]>>(startBit+ibit)) & 0x3, \n"
+" (sortData[1]>>(startBit+ibit)) & 0x3, \n"
+" (sortData[2]>>(startBit+ibit)) & 0x3, \n"
+" (sortData[3]>>(startBit+ibit)) & 0x3);\n"
+" u32 key4;\n"
+" u32 sKeyPacked[4] = { 0, 0, 0, 0 };\n"
+" {\n"
+" sKeyPacked[0] |= 1<<(8*b.x);\n"
+" sKeyPacked[1] |= 1<<(8*b.y);\n"
+" sKeyPacked[2] |= 1<<(8*b.z);\n"
+" sKeyPacked[3] |= 1<<(8*b.w);\n"
+" key4 = sKeyPacked[0] + sKeyPacked[1] + sKeyPacked[2] + sKeyPacked[3];\n"
+" }\n"
+" u32 rankPacked;\n"
+" u32 sumPacked;\n"
+" {\n"
+" rankPacked = localPrefixSum( key4, lIdx, &sumPacked, ldsSortData, WG_SIZE );\n"
+" }\n"
+" GROUP_LDS_BARRIER;\n"
+" u32 newOffset[4] = { 0,0,0,0 };\n"
+" {\n"
+" u32 sumScanned = bit8Scan( sumPacked );\n"
+" u32 scannedKeys[4];\n"
+" scannedKeys[0] = 1<<(8*b.x);\n"
+" scannedKeys[1] = 1<<(8*b.y);\n"
+" scannedKeys[2] = 1<<(8*b.z);\n"
+" scannedKeys[3] = 1<<(8*b.w);\n"
+" { // 4 scans at once\n"
+" u32 sum4 = 0;\n"
+" for(int ie=0; ie<4; ie++)\n"
+" {\n"
+" u32 tmp = scannedKeys[ie];\n"
+" scannedKeys[ie] = sum4;\n"
+" sum4 += tmp;\n"
+" }\n"
+" }\n"
+" {\n"
+" u32 sumPlusRank = sumScanned + rankPacked;\n"
+" { u32 ie = b.x;\n"
+" scannedKeys[0] += sumPlusRank;\n"
+" newOffset[0] = unpack4Key( scannedKeys[0], ie );\n"
+" }\n"
+" { u32 ie = b.y;\n"
+" scannedKeys[1] += sumPlusRank;\n"
+" newOffset[1] = unpack4Key( scannedKeys[1], ie );\n"
+" }\n"
+" { u32 ie = b.z;\n"
+" scannedKeys[2] += sumPlusRank;\n"
+" newOffset[2] = unpack4Key( scannedKeys[2], ie );\n"
+" }\n"
+" { u32 ie = b.w;\n"
+" scannedKeys[3] += sumPlusRank;\n"
+" newOffset[3] = unpack4Key( scannedKeys[3], ie );\n"
+" }\n"
+" }\n"
+" }\n"
+" GROUP_LDS_BARRIER;\n"
+" {\n"
+" ldsSortData[newOffset[0]] = sortData[0];\n"
+" ldsSortData[newOffset[1]] = sortData[1];\n"
+" ldsSortData[newOffset[2]] = sortData[2];\n"
+" ldsSortData[newOffset[3]] = sortData[3];\n"
+" GROUP_LDS_BARRIER;\n"
+" u32 dstAddr = 4*lIdx;\n"
+" sortData[0] = ldsSortData[dstAddr+0];\n"
+" sortData[1] = ldsSortData[dstAddr+1];\n"
+" sortData[2] = ldsSortData[dstAddr+2];\n"
+" sortData[3] = ldsSortData[dstAddr+3];\n"
+" GROUP_LDS_BARRIER;\n"
+" }\n"
+" }\n"
+"}\n"
+"#define SET_HISTOGRAM(setIdx, key) ldsSortData[(setIdx)*NUM_BUCKET+key]\n"
+"__kernel\n"
+"__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+"void SortAndScatterKernel( __global const u32* restrict gSrc, __global const u32* rHistogram, __global u32* restrict gDst, int4 cb )\n"
+"{\n"
+" __local u32 ldsSortData[WG_SIZE*ELEMENTS_PER_WORK_ITEM+16];\n"
+" __local u32 localHistogramToCarry[NUM_BUCKET];\n"
+" __local u32 localHistogram[NUM_BUCKET*2];\n"
+" u32 gIdx = GET_GLOBAL_IDX;\n"
+" u32 lIdx = GET_LOCAL_IDX;\n"
+" u32 wgIdx = GET_GROUP_IDX;\n"
+" u32 wgSize = GET_GROUP_SIZE;\n"
+" const int n = cb.m_n;\n"
+" const int nWGs = cb.m_nWGs;\n"
+" const int startBit = cb.m_startBit;\n"
+" const int nBlocksPerWG = cb.m_nBlocksPerWG;\n"
+" if( lIdx < (NUM_BUCKET) )\n"
+" {\n"
+" localHistogramToCarry[lIdx] = rHistogram[lIdx*nWGs + wgIdx];\n"
+" }\n"
+" GROUP_LDS_BARRIER;\n"
+" const int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE;\n"
+" int nBlocks = n/blockSize - nBlocksPerWG*wgIdx;\n"
+" int addr = blockSize*nBlocksPerWG*wgIdx + ELEMENTS_PER_WORK_ITEM*lIdx;\n"
+" for(int iblock=0; iblock<min(nBlocksPerWG, nBlocks); iblock++, addr+=blockSize)\n"
+" {\n"
+" u32 myHistogram = 0;\n"
+" u32 sortData[ELEMENTS_PER_WORK_ITEM];\n"
+" for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)\n"
+"#if defined(CHECK_BOUNDARY)\n"
+" sortData[i] = ( addr+i < n )? gSrc[ addr+i ] : 0xffffffff;\n"
+"#else\n"
+" sortData[i] = gSrc[ addr+i ];\n"
+"#endif\n"
+" sort4Bits(sortData, startBit, lIdx, ldsSortData);\n"
+" u32 keys[ELEMENTS_PER_WORK_ITEM];\n"
+" for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)\n"
+" keys[i] = (sortData[i]>>startBit) & 0xf;\n"
+" { // create histogram\n"
+" u32 setIdx = lIdx/16;\n"
+" if( lIdx < NUM_BUCKET )\n"
+" {\n"
+" localHistogram[lIdx] = 0;\n"
+" }\n"
+" ldsSortData[lIdx] = 0;\n"
+" GROUP_LDS_BARRIER;\n"
+" for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)\n"
+"#if defined(CHECK_BOUNDARY)\n"
+" if( addr+i < n )\n"
+"#endif\n"
+"#if defined(NV_GPU)\n"
+" SET_HISTOGRAM( setIdx, keys[i] )++;\n"
+"#else\n"
+" AtomInc( SET_HISTOGRAM( setIdx, keys[i] ) );\n"
+"#endif\n"
+" \n"
+" GROUP_LDS_BARRIER;\n"
+" \n"
+" uint hIdx = NUM_BUCKET+lIdx;\n"
+" if( lIdx < NUM_BUCKET )\n"
+" {\n"
+" u32 sum = 0;\n"
+" for(int i=0; i<WG_SIZE/16; i++)\n"
+" {\n"
+" sum += SET_HISTOGRAM( i, lIdx );\n"
+" }\n"
+" myHistogram = sum;\n"
+" localHistogram[hIdx] = sum;\n"
+" }\n"
+" GROUP_LDS_BARRIER;\n"
+"#if defined(USE_2LEVEL_REDUCE)\n"
+" if( lIdx < NUM_BUCKET )\n"
+" {\n"
+" localHistogram[hIdx] = localHistogram[hIdx-1];\n"
+" GROUP_MEM_FENCE;\n"
+" u32 u0, u1, u2;\n"
+" u0 = localHistogram[hIdx-3];\n"
+" u1 = localHistogram[hIdx-2];\n"
+" u2 = localHistogram[hIdx-1];\n"
+" AtomAdd( localHistogram[hIdx], u0 + u1 + u2 );\n"
+" GROUP_MEM_FENCE;\n"
+" u0 = localHistogram[hIdx-12];\n"
+" u1 = localHistogram[hIdx-8];\n"
+" u2 = localHistogram[hIdx-4];\n"
+" AtomAdd( localHistogram[hIdx], u0 + u1 + u2 );\n"
+" GROUP_MEM_FENCE;\n"
+" }\n"
+"#else\n"
+" if( lIdx < NUM_BUCKET )\n"
+" {\n"
+" localHistogram[hIdx] = localHistogram[hIdx-1];\n"
+" GROUP_MEM_FENCE;\n"
+" localHistogram[hIdx] += localHistogram[hIdx-1];\n"
+" GROUP_MEM_FENCE;\n"
+" localHistogram[hIdx] += localHistogram[hIdx-2];\n"
+" GROUP_MEM_FENCE;\n"
+" localHistogram[hIdx] += localHistogram[hIdx-4];\n"
+" GROUP_MEM_FENCE;\n"
+" localHistogram[hIdx] += localHistogram[hIdx-8];\n"
+" GROUP_MEM_FENCE;\n"
+" }\n"
+"#endif\n"
+" GROUP_LDS_BARRIER;\n"
+" }\n"
+" {\n"
+" for(int ie=0; ie<ELEMENTS_PER_WORK_ITEM; ie++)\n"
+" {\n"
+" int dataIdx = ELEMENTS_PER_WORK_ITEM*lIdx+ie;\n"
+" int binIdx = keys[ie];\n"
+" int groupOffset = localHistogramToCarry[binIdx];\n"
+" int myIdx = dataIdx - localHistogram[NUM_BUCKET+binIdx];\n"
+"#if defined(CHECK_BOUNDARY)\n"
+" if( addr+ie < n )\n"
+"#endif\n"
+" gDst[ groupOffset + myIdx ] = sortData[ie];\n"
+" }\n"
+" }\n"
+" GROUP_LDS_BARRIER;\n"
+" if( lIdx < NUM_BUCKET )\n"
+" {\n"
+" localHistogramToCarry[lIdx] += myHistogram;\n"
+" }\n"
+" GROUP_LDS_BARRIER;\n"
+" }\n"
+"}\n"
+"// 2 scan, 2 exchange\n"
+"void sort4Bits1KeyValue(u32 sortData[4], int sortVal[4], int startBit, int lIdx, __local u32* ldsSortData, __local int *ldsSortVal)\n"
+"{\n"
+" for(uint ibit=0; ibit<BITS_PER_PASS; ibit+=2)\n"
+" {\n"
+" uint4 b = make_uint4((sortData[0]>>(startBit+ibit)) & 0x3, \n"
+" (sortData[1]>>(startBit+ibit)) & 0x3, \n"
+" (sortData[2]>>(startBit+ibit)) & 0x3, \n"
+" (sortData[3]>>(startBit+ibit)) & 0x3);\n"
+" u32 key4;\n"
+" u32 sKeyPacked[4] = { 0, 0, 0, 0 };\n"
+" {\n"
+" sKeyPacked[0] |= 1<<(8*b.x);\n"
+" sKeyPacked[1] |= 1<<(8*b.y);\n"
+" sKeyPacked[2] |= 1<<(8*b.z);\n"
+" sKeyPacked[3] |= 1<<(8*b.w);\n"
+" key4 = sKeyPacked[0] + sKeyPacked[1] + sKeyPacked[2] + sKeyPacked[3];\n"
+" }\n"
+" u32 rankPacked;\n"
+" u32 sumPacked;\n"
+" {\n"
+" rankPacked = localPrefixSum( key4, lIdx, &sumPacked, ldsSortData, WG_SIZE );\n"
+" }\n"
+" GROUP_LDS_BARRIER;\n"
+" u32 newOffset[4] = { 0,0,0,0 };\n"
+" {\n"
+" u32 sumScanned = bit8Scan( sumPacked );\n"
+" u32 scannedKeys[4];\n"
+" scannedKeys[0] = 1<<(8*b.x);\n"
+" scannedKeys[1] = 1<<(8*b.y);\n"
+" scannedKeys[2] = 1<<(8*b.z);\n"
+" scannedKeys[3] = 1<<(8*b.w);\n"
+" { // 4 scans at once\n"
+" u32 sum4 = 0;\n"
+" for(int ie=0; ie<4; ie++)\n"
+" {\n"
+" u32 tmp = scannedKeys[ie];\n"
+" scannedKeys[ie] = sum4;\n"
+" sum4 += tmp;\n"
+" }\n"
+" }\n"
+" {\n"
+" u32 sumPlusRank = sumScanned + rankPacked;\n"
+" { u32 ie = b.x;\n"
+" scannedKeys[0] += sumPlusRank;\n"
+" newOffset[0] = unpack4Key( scannedKeys[0], ie );\n"
+" }\n"
+" { u32 ie = b.y;\n"
+" scannedKeys[1] += sumPlusRank;\n"
+" newOffset[1] = unpack4Key( scannedKeys[1], ie );\n"
+" }\n"
+" { u32 ie = b.z;\n"
+" scannedKeys[2] += sumPlusRank;\n"
+" newOffset[2] = unpack4Key( scannedKeys[2], ie );\n"
+" }\n"
+" { u32 ie = b.w;\n"
+" scannedKeys[3] += sumPlusRank;\n"
+" newOffset[3] = unpack4Key( scannedKeys[3], ie );\n"
+" }\n"
+" }\n"
+" }\n"
+" GROUP_LDS_BARRIER;\n"
+" {\n"
+" ldsSortData[newOffset[0]] = sortData[0];\n"
+" ldsSortData[newOffset[1]] = sortData[1];\n"
+" ldsSortData[newOffset[2]] = sortData[2];\n"
+" ldsSortData[newOffset[3]] = sortData[3];\n"
+" ldsSortVal[newOffset[0]] = sortVal[0];\n"
+" ldsSortVal[newOffset[1]] = sortVal[1];\n"
+" ldsSortVal[newOffset[2]] = sortVal[2];\n"
+" ldsSortVal[newOffset[3]] = sortVal[3];\n"
+" GROUP_LDS_BARRIER;\n"
+" u32 dstAddr = 4*lIdx;\n"
+" sortData[0] = ldsSortData[dstAddr+0];\n"
+" sortData[1] = ldsSortData[dstAddr+1];\n"
+" sortData[2] = ldsSortData[dstAddr+2];\n"
+" sortData[3] = ldsSortData[dstAddr+3];\n"
+" sortVal[0] = ldsSortVal[dstAddr+0];\n"
+" sortVal[1] = ldsSortVal[dstAddr+1];\n"
+" sortVal[2] = ldsSortVal[dstAddr+2];\n"
+" sortVal[3] = ldsSortVal[dstAddr+3];\n"
+" GROUP_LDS_BARRIER;\n"
+" }\n"
+" }\n"
+"}\n"
+"__kernel\n"
+"__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+"void SortAndScatterSortDataKernel( __global const SortDataCL* restrict gSrc, __global const u32* rHistogram, __global SortDataCL* restrict gDst, int4 cb)\n"
+"{\n"
+" __local int ldsSortData[WG_SIZE*ELEMENTS_PER_WORK_ITEM+16];\n"
+" __local int ldsSortVal[WG_SIZE*ELEMENTS_PER_WORK_ITEM+16];\n"
+" __local u32 localHistogramToCarry[NUM_BUCKET];\n"
+" __local u32 localHistogram[NUM_BUCKET*2];\n"
+" u32 gIdx = GET_GLOBAL_IDX;\n"
+" u32 lIdx = GET_LOCAL_IDX;\n"
+" u32 wgIdx = GET_GROUP_IDX;\n"
+" u32 wgSize = GET_GROUP_SIZE;\n"
+" const int n = cb.m_n;\n"
+" const int nWGs = cb.m_nWGs;\n"
+" const int startBit = cb.m_startBit;\n"
+" const int nBlocksPerWG = cb.m_nBlocksPerWG;\n"
+" if( lIdx < (NUM_BUCKET) )\n"
+" {\n"
+" localHistogramToCarry[lIdx] = rHistogram[lIdx*nWGs + wgIdx];\n"
+" }\n"
+" GROUP_LDS_BARRIER;\n"
+" \n"
+" const int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE;\n"
+" int nBlocks = n/blockSize - nBlocksPerWG*wgIdx;\n"
+" int addr = blockSize*nBlocksPerWG*wgIdx + ELEMENTS_PER_WORK_ITEM*lIdx;\n"
+" for(int iblock=0; iblock<min(nBlocksPerWG, nBlocks); iblock++, addr+=blockSize)\n"
+" {\n"
+" u32 myHistogram = 0;\n"
+" int sortData[ELEMENTS_PER_WORK_ITEM];\n"
+" int sortVal[ELEMENTS_PER_WORK_ITEM];\n"
+" for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)\n"
+"#if defined(CHECK_BOUNDARY)\n"
+" {\n"
+" sortData[i] = ( addr+i < n )? gSrc[ addr+i ].m_key : 0xffffffff;\n"
+" sortVal[i] = ( addr+i < n )? gSrc[ addr+i ].m_value : 0xffffffff;\n"
+" }\n"
+"#else\n"
+" {\n"
+" sortData[i] = gSrc[ addr+i ].m_key;\n"
+" sortVal[i] = gSrc[ addr+i ].m_value;\n"
+" }\n"
+"#endif\n"
+" sort4Bits1KeyValue(sortData, sortVal, startBit, lIdx, ldsSortData, ldsSortVal);\n"
+" u32 keys[ELEMENTS_PER_WORK_ITEM];\n"
+" for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)\n"
+" keys[i] = (sortData[i]>>startBit) & 0xf;\n"
+" { // create histogram\n"
+" u32 setIdx = lIdx/16;\n"
+" if( lIdx < NUM_BUCKET )\n"
+" {\n"
+" localHistogram[lIdx] = 0;\n"
+" }\n"
+" ldsSortData[lIdx] = 0;\n"
+" GROUP_LDS_BARRIER;\n"
+" for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)\n"
+"#if defined(CHECK_BOUNDARY)\n"
+" if( addr+i < n )\n"
+"#endif\n"
+"#if defined(NV_GPU)\n"
+" SET_HISTOGRAM( setIdx, keys[i] )++;\n"
+"#else\n"
+" AtomInc( SET_HISTOGRAM( setIdx, keys[i] ) );\n"
+"#endif\n"
+" \n"
+" GROUP_LDS_BARRIER;\n"
+" \n"
+" uint hIdx = NUM_BUCKET+lIdx;\n"
+" if( lIdx < NUM_BUCKET )\n"
+" {\n"
+" u32 sum = 0;\n"
+" for(int i=0; i<WG_SIZE/16; i++)\n"
+" {\n"
+" sum += SET_HISTOGRAM( i, lIdx );\n"
+" }\n"
+" myHistogram = sum;\n"
+" localHistogram[hIdx] = sum;\n"
+" }\n"
+" GROUP_LDS_BARRIER;\n"
+"#if defined(USE_2LEVEL_REDUCE)\n"
+" if( lIdx < NUM_BUCKET )\n"
+" {\n"
+" localHistogram[hIdx] = localHistogram[hIdx-1];\n"
+" GROUP_MEM_FENCE;\n"
+" u32 u0, u1, u2;\n"
+" u0 = localHistogram[hIdx-3];\n"
+" u1 = localHistogram[hIdx-2];\n"
+" u2 = localHistogram[hIdx-1];\n"
+" AtomAdd( localHistogram[hIdx], u0 + u1 + u2 );\n"
+" GROUP_MEM_FENCE;\n"
+" u0 = localHistogram[hIdx-12];\n"
+" u1 = localHistogram[hIdx-8];\n"
+" u2 = localHistogram[hIdx-4];\n"
+" AtomAdd( localHistogram[hIdx], u0 + u1 + u2 );\n"
+" GROUP_MEM_FENCE;\n"
+" }\n"
+"#else\n"
+" if( lIdx < NUM_BUCKET )\n"
+" {\n"
+" localHistogram[hIdx] = localHistogram[hIdx-1];\n"
+" GROUP_MEM_FENCE;\n"
+" localHistogram[hIdx] += localHistogram[hIdx-1];\n"
+" GROUP_MEM_FENCE;\n"
+" localHistogram[hIdx] += localHistogram[hIdx-2];\n"
+" GROUP_MEM_FENCE;\n"
+" localHistogram[hIdx] += localHistogram[hIdx-4];\n"
+" GROUP_MEM_FENCE;\n"
+" localHistogram[hIdx] += localHistogram[hIdx-8];\n"
+" GROUP_MEM_FENCE;\n"
+" }\n"
+"#endif\n"
+" GROUP_LDS_BARRIER;\n"
+" }\n"
+" {\n"
+" for(int ie=0; ie<ELEMENTS_PER_WORK_ITEM; ie++)\n"
+" {\n"
+" int dataIdx = ELEMENTS_PER_WORK_ITEM*lIdx+ie;\n"
+" int binIdx = keys[ie];\n"
+" int groupOffset = localHistogramToCarry[binIdx];\n"
+" int myIdx = dataIdx - localHistogram[NUM_BUCKET+binIdx];\n"
+"#if defined(CHECK_BOUNDARY)\n"
+" if( addr+ie < n )\n"
+" {\n"
+" if ((groupOffset + myIdx)<n)\n"
+" {\n"
+" if (sortData[ie]==sortVal[ie])\n"
+" {\n"
+" \n"
+" SortDataCL tmp;\n"
+" tmp.m_key = sortData[ie];\n"
+" tmp.m_value = sortVal[ie];\n"
+" if (tmp.m_key == tmp.m_value)\n"
+" gDst[groupOffset + myIdx ] = tmp;\n"
+" }\n"
+" \n"
+" }\n"
+" }\n"
+"#else\n"
+" if ((groupOffset + myIdx)<n)\n"
+" {\n"
+" gDst[ groupOffset + myIdx ].m_key = sortData[ie];\n"
+" gDst[ groupOffset + myIdx ].m_value = sortVal[ie];\n"
+" }\n"
+"#endif\n"
+" }\n"
+" }\n"
+" GROUP_LDS_BARRIER;\n"
+" if( lIdx < NUM_BUCKET )\n"
+" {\n"
+" localHistogramToCarry[lIdx] += myHistogram;\n"
+" }\n"
+" GROUP_LDS_BARRIER;\n"
+" }\n"
+"}\n"
+"__kernel\n"
+"__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+"void SortAndScatterSortDataKernelSerial( __global const SortDataCL* restrict gSrc, __global const u32* rHistogram, __global SortDataCL* restrict gDst, int4 cb)\n"
+"{\n"
+" \n"
+" u32 gIdx = GET_GLOBAL_IDX;\n"
+" u32 realLocalIdx = GET_LOCAL_IDX;\n"
+" u32 wgIdx = GET_GROUP_IDX;\n"
+" u32 wgSize = GET_GROUP_SIZE;\n"
+" const int startBit = cb.m_startBit;\n"
+" const int n = cb.m_n;\n"
+" const int nWGs = cb.m_nWGs;\n"
+" const int nBlocksPerWG = cb.m_nBlocksPerWG;\n"
+" int counter[NUM_BUCKET];\n"
+" \n"
+" if (realLocalIdx>0)\n"
+" return;\n"
+" \n"
+" for (int c=0;c<NUM_BUCKET;c++)\n"
+" counter[c]=0;\n"
+" const int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE;\n"
+" \n"
+" int nBlocks = (n)/blockSize - nBlocksPerWG*wgIdx;\n"
+" for(int iblock=0; iblock<min(nBlocksPerWG, nBlocks); iblock++)\n"
+" {\n"
+" for (int lIdx=0;lIdx<WG_SIZE;lIdx++)\n"
+" {\n"
+" int addr2 = iblock*blockSize + blockSize*nBlocksPerWG*wgIdx + ELEMENTS_PER_WORK_ITEM*lIdx;\n"
+" \n"
+" for(int j=0; j<ELEMENTS_PER_WORK_ITEM; j++)\n"
+" {\n"
+" int i = addr2+j;\n"
+" if( i < n )\n"
+" {\n"
+" int tableIdx;\n"
+" tableIdx = (gSrc[i].m_key>>startBit) & 0xf;//0xf = NUM_TABLES-1\n"
+" gDst[rHistogram[tableIdx*nWGs+wgIdx] + counter[tableIdx]] = gSrc[i];\n"
+" counter[tableIdx] ++;\n"
+" }\n"
+" }\n"
+" }\n"
+" }\n"
+" \n"
+"}\n"
+"__kernel\n"
+"__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+"void SortAndScatterKernelSerial( __global const u32* restrict gSrc, __global const u32* rHistogram, __global u32* restrict gDst, int4 cb )\n"
+"{\n"
+" \n"
+" u32 gIdx = GET_GLOBAL_IDX;\n"
+" u32 realLocalIdx = GET_LOCAL_IDX;\n"
+" u32 wgIdx = GET_GROUP_IDX;\n"
+" u32 wgSize = GET_GROUP_SIZE;\n"
+" const int startBit = cb.m_startBit;\n"
+" const int n = cb.m_n;\n"
+" const int nWGs = cb.m_nWGs;\n"
+" const int nBlocksPerWG = cb.m_nBlocksPerWG;\n"
+" int counter[NUM_BUCKET];\n"
+" \n"
+" if (realLocalIdx>0)\n"
+" return;\n"
+" \n"
+" for (int c=0;c<NUM_BUCKET;c++)\n"
+" counter[c]=0;\n"
+" const int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE;\n"
+" \n"
+" int nBlocks = (n)/blockSize - nBlocksPerWG*wgIdx;\n"
+" for(int iblock=0; iblock<min(nBlocksPerWG, nBlocks); iblock++)\n"
+" {\n"
+" for (int lIdx=0;lIdx<WG_SIZE;lIdx++)\n"
+" {\n"
+" int addr2 = iblock*blockSize + blockSize*nBlocksPerWG*wgIdx + ELEMENTS_PER_WORK_ITEM*lIdx;\n"
+" \n"
+" for(int j=0; j<ELEMENTS_PER_WORK_ITEM; j++)\n"
+" {\n"
+" int i = addr2+j;\n"
+" if( i < n )\n"
+" {\n"
+" int tableIdx;\n"
+" tableIdx = (gSrc[i]>>startBit) & 0xf;//0xf = NUM_TABLES-1\n"
+" gDst[rHistogram[tableIdx*nWGs+wgIdx] + counter[tableIdx]] = gSrc[i];\n"
+" counter[tableIdx] ++;\n"
+" }\n"
+" }\n"
+" }\n"
+" }\n"
+" \n"
+"}\n"
+;
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/Raycast/b3GpuRaycast.cpp b/thirdparty/bullet/src/Bullet3OpenCL/Raycast/b3GpuRaycast.cpp
new file mode 100644
index 0000000000..161e304f09
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/Raycast/b3GpuRaycast.cpp
@@ -0,0 +1,391 @@
+
+#include "b3GpuRaycast.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
+#include "Bullet3OpenCL/RigidBody/b3GpuNarrowPhaseInternalData.h"
+
+
+#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
+#include "Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h"
+#include "Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.h"
+#include "Bullet3OpenCL/ParallelPrimitives/b3FillCL.h"
+#include "Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.h"
+#include "Bullet3OpenCL/BroadphaseCollision/b3GpuBroadphaseInterface.h"
+#include "Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvh.h"
+
+#include "Bullet3OpenCL/Raycast/kernels/rayCastKernels.h"
+
+
+#define B3_RAYCAST_PATH "src/Bullet3OpenCL/Raycast/kernels/rayCastKernels.cl"
+
+
+
+struct b3GpuRaycastInternalData
+{
+ cl_context m_context;
+ cl_device_id m_device;
+ cl_command_queue m_q;
+ cl_kernel m_raytraceKernel;
+ cl_kernel m_raytracePairsKernel;
+ cl_kernel m_findRayRigidPairIndexRanges;
+
+ b3GpuParallelLinearBvh* m_plbvh;
+ b3RadixSort32CL* m_radixSorter;
+ b3FillCL* m_fill;
+
+ //1 element per ray
+ b3OpenCLArray<b3RayInfo>* m_gpuRays;
+ b3OpenCLArray<b3RayHit>* m_gpuHitResults;
+ b3OpenCLArray<int>* m_firstRayRigidPairIndexPerRay;
+ b3OpenCLArray<int>* m_numRayRigidPairsPerRay;
+
+ //1 element per (ray index, rigid index) pair, where the ray intersects with the rigid's AABB
+ b3OpenCLArray<int>* m_gpuNumRayRigidPairs;
+ b3OpenCLArray<b3Int2>* m_gpuRayRigidPairs; //x == ray index, y == rigid index
+
+ int m_test;
+};
+
+b3GpuRaycast::b3GpuRaycast(cl_context ctx,cl_device_id device, cl_command_queue q)
+{
+ m_data = new b3GpuRaycastInternalData;
+ m_data->m_context = ctx;
+ m_data->m_device = device;
+ m_data->m_q = q;
+ m_data->m_raytraceKernel = 0;
+ m_data->m_raytracePairsKernel = 0;
+ m_data->m_findRayRigidPairIndexRanges = 0;
+
+ m_data->m_plbvh = new b3GpuParallelLinearBvh(ctx, device, q);
+ m_data->m_radixSorter = new b3RadixSort32CL(ctx, device, q);
+ m_data->m_fill = new b3FillCL(ctx, device, q);
+
+ m_data->m_gpuRays = new b3OpenCLArray<b3RayInfo>(ctx, q);
+ m_data->m_gpuHitResults = new b3OpenCLArray<b3RayHit>(ctx, q);
+ m_data->m_firstRayRigidPairIndexPerRay = new b3OpenCLArray<int>(ctx, q);
+ m_data->m_numRayRigidPairsPerRay = new b3OpenCLArray<int>(ctx, q);
+ m_data->m_gpuNumRayRigidPairs = new b3OpenCLArray<int>(ctx, q);
+ m_data->m_gpuRayRigidPairs = new b3OpenCLArray<b3Int2>(ctx, q);
+
+ {
+ cl_int errNum=0;
+ cl_program prog = b3OpenCLUtils::compileCLProgramFromString(m_data->m_context,m_data->m_device,rayCastKernelCL,&errNum,"",B3_RAYCAST_PATH);
+ b3Assert(errNum==CL_SUCCESS);
+ m_data->m_raytraceKernel = b3OpenCLUtils::compileCLKernelFromString(m_data->m_context, m_data->m_device,rayCastKernelCL, "rayCastKernel",&errNum,prog);
+ b3Assert(errNum==CL_SUCCESS);
+ m_data->m_raytracePairsKernel = b3OpenCLUtils::compileCLKernelFromString(m_data->m_context, m_data->m_device,rayCastKernelCL, "rayCastPairsKernel",&errNum,prog);
+ b3Assert(errNum==CL_SUCCESS);
+ m_data->m_findRayRigidPairIndexRanges = b3OpenCLUtils::compileCLKernelFromString(m_data->m_context, m_data->m_device,rayCastKernelCL, "findRayRigidPairIndexRanges",&errNum,prog);
+ b3Assert(errNum==CL_SUCCESS);
+ clReleaseProgram(prog);
+ }
+
+
+}
+
+b3GpuRaycast::~b3GpuRaycast()
+{
+ clReleaseKernel(m_data->m_raytraceKernel);
+ clReleaseKernel(m_data->m_raytracePairsKernel);
+ clReleaseKernel(m_data->m_findRayRigidPairIndexRanges);
+
+ delete m_data->m_plbvh;
+ delete m_data->m_radixSorter;
+ delete m_data->m_fill;
+
+ delete m_data->m_gpuRays;
+ delete m_data->m_gpuHitResults;
+ delete m_data->m_firstRayRigidPairIndexPerRay;
+ delete m_data->m_numRayRigidPairsPerRay;
+ delete m_data->m_gpuNumRayRigidPairs;
+ delete m_data->m_gpuRayRigidPairs;
+
+ delete m_data;
+}
+
+bool sphere_intersect(const b3Vector3& spherePos, b3Scalar radius, const b3Vector3& rayFrom, const b3Vector3& rayTo, float& hitFraction)
+{
+ b3Vector3 rs = rayFrom - spherePos;
+ b3Vector3 rayDir = rayTo-rayFrom;
+
+ float A = b3Dot(rayDir,rayDir);
+ float B = b3Dot(rs, rayDir);
+ float C = b3Dot(rs, rs) - (radius * radius);
+
+ float D = B * B - A*C;
+
+ if (D > 0.0)
+ {
+ float t = (-B - sqrt(D))/A;
+
+ if ( (t >= 0.0f) && (t < hitFraction) )
+ {
+ hitFraction = t;
+ return true;
+ }
+ }
+ return false;
+}
+
+bool rayConvex(const b3Vector3& rayFromLocal, const b3Vector3& rayToLocal, const b3ConvexPolyhedronData& poly,
+ const b3AlignedObjectArray<b3GpuFace>& faces, float& hitFraction, b3Vector3& hitNormal)
+{
+ float exitFraction = hitFraction;
+ float enterFraction = -0.1f;
+ b3Vector3 curHitNormal=b3MakeVector3(0,0,0);
+ for (int i=0;i<poly.m_numFaces;i++)
+ {
+ const b3GpuFace& face = faces[poly.m_faceOffset+i];
+ float fromPlaneDist = b3Dot(rayFromLocal,face.m_plane)+face.m_plane.w;
+ float toPlaneDist = b3Dot(rayToLocal,face.m_plane)+face.m_plane.w;
+ if (fromPlaneDist<0.f)
+ {
+ if (toPlaneDist >= 0.f)
+ {
+ float fraction = fromPlaneDist / (fromPlaneDist-toPlaneDist);
+ if (exitFraction>fraction)
+ {
+ exitFraction = fraction;
+ }
+ }
+ } else
+ {
+ if (toPlaneDist<0.f)
+ {
+ float fraction = fromPlaneDist / (fromPlaneDist-toPlaneDist);
+ if (enterFraction <= fraction)
+ {
+ enterFraction = fraction;
+ curHitNormal = face.m_plane;
+ curHitNormal.w = 0.f;
+ }
+ } else
+ {
+ return false;
+ }
+ }
+ if (exitFraction <= enterFraction)
+ return false;
+ }
+
+ if (enterFraction < 0.f)
+ return false;
+
+ hitFraction = enterFraction;
+ hitNormal = curHitNormal;
+ return true;
+}
+
+void b3GpuRaycast::castRaysHost(const b3AlignedObjectArray<b3RayInfo>& rays, b3AlignedObjectArray<b3RayHit>& hitResults,
+ int numBodies,const struct b3RigidBodyData* bodies, int numCollidables,const struct b3Collidable* collidables, const struct b3GpuNarrowPhaseInternalData* narrowphaseData)
+{
+
+// return castRays(rays,hitResults,numBodies,bodies,numCollidables,collidables);
+
+ B3_PROFILE("castRaysHost");
+ for (int r=0;r<rays.size();r++)
+ {
+ b3Vector3 rayFrom = rays[r].m_from;
+ b3Vector3 rayTo = rays[r].m_to;
+ float hitFraction = hitResults[r].m_hitFraction;
+
+ int hitBodyIndex= -1;
+ b3Vector3 hitNormal;
+
+ for (int b=0;b<numBodies;b++)
+ {
+
+ const b3Vector3& pos = bodies[b].m_pos;
+ //const b3Quaternion& orn = bodies[b].m_quat;
+
+ switch (collidables[bodies[b].m_collidableIdx].m_shapeType)
+ {
+ case SHAPE_SPHERE:
+ {
+ b3Scalar radius = collidables[bodies[b].m_collidableIdx].m_radius;
+ if (sphere_intersect(pos, radius, rayFrom, rayTo,hitFraction))
+ {
+ hitBodyIndex = b;
+ b3Vector3 hitPoint;
+ hitPoint.setInterpolate3(rays[r].m_from, rays[r].m_to,hitFraction);
+ hitNormal = (hitPoint-bodies[b].m_pos).normalize();
+ }
+ }
+ case SHAPE_CONVEX_HULL:
+ {
+
+ b3Transform convexWorldTransform;
+ convexWorldTransform.setIdentity();
+ convexWorldTransform.setOrigin(bodies[b].m_pos);
+ convexWorldTransform.setRotation(bodies[b].m_quat);
+ b3Transform convexWorld2Local = convexWorldTransform.inverse();
+
+ b3Vector3 rayFromLocal = convexWorld2Local(rayFrom);
+ b3Vector3 rayToLocal = convexWorld2Local(rayTo);
+
+
+ int shapeIndex = collidables[bodies[b].m_collidableIdx].m_shapeIndex;
+ const b3ConvexPolyhedronData& poly = narrowphaseData->m_convexPolyhedra[shapeIndex];
+ if (rayConvex(rayFromLocal, rayToLocal,poly,narrowphaseData->m_convexFaces, hitFraction, hitNormal))
+ {
+ hitBodyIndex = b;
+ }
+
+
+ break;
+ }
+ default:
+ {
+ static bool once=true;
+ if (once)
+ {
+ once=false;
+ b3Warning("Raytest: unsupported shape type\n");
+ }
+ }
+ }
+ }
+ if (hitBodyIndex>=0)
+ {
+
+ hitResults[r].m_hitFraction = hitFraction;
+ hitResults[r].m_hitPoint.setInterpolate3(rays[r].m_from, rays[r].m_to,hitFraction);
+ hitResults[r].m_hitNormal = hitNormal;
+ hitResults[r].m_hitBody = hitBodyIndex;
+ }
+
+ }
+}
+///todo: add some acceleration structure (AABBs, tree etc)
+void b3GpuRaycast::castRays(const b3AlignedObjectArray<b3RayInfo>& rays, b3AlignedObjectArray<b3RayHit>& hitResults,
+ int numBodies,const struct b3RigidBodyData* bodies, int numCollidables, const struct b3Collidable* collidables,
+ const struct b3GpuNarrowPhaseInternalData* narrowphaseData, class b3GpuBroadphaseInterface* broadphase)
+{
+ //castRaysHost(rays,hitResults,numBodies,bodies,numCollidables,collidables,narrowphaseData);
+
+ B3_PROFILE("castRaysGPU");
+
+ {
+ B3_PROFILE("raycast copyFromHost");
+ m_data->m_gpuRays->copyFromHost(rays);
+ m_data->m_gpuHitResults->copyFromHost(hitResults);
+
+ }
+
+ int numRays = hitResults.size();
+ {
+ m_data->m_firstRayRigidPairIndexPerRay->resize(numRays);
+ m_data->m_numRayRigidPairsPerRay->resize(numRays);
+
+ m_data->m_gpuNumRayRigidPairs->resize(1);
+ m_data->m_gpuRayRigidPairs->resize(numRays * 16);
+ }
+
+ //run kernel
+ const bool USE_BRUTE_FORCE_RAYCAST = false;
+ if(USE_BRUTE_FORCE_RAYCAST)
+ {
+ B3_PROFILE("raycast launch1D");
+
+ b3LauncherCL launcher(m_data->m_q,m_data->m_raytraceKernel,"m_raytraceKernel");
+ int numRays = rays.size();
+ launcher.setConst(numRays);
+
+ launcher.setBuffer(m_data->m_gpuRays->getBufferCL());
+ launcher.setBuffer(m_data->m_gpuHitResults->getBufferCL());
+
+ launcher.setConst(numBodies);
+ launcher.setBuffer(narrowphaseData->m_bodyBufferGPU->getBufferCL());
+ launcher.setBuffer(narrowphaseData->m_collidablesGPU->getBufferCL());
+ launcher.setBuffer(narrowphaseData->m_convexFacesGPU->getBufferCL());
+ launcher.setBuffer(narrowphaseData->m_convexPolyhedraGPU->getBufferCL());
+
+ launcher.launch1D(numRays);
+ clFinish(m_data->m_q);
+ }
+ else
+ {
+ m_data->m_plbvh->build( broadphase->getAllAabbsGPU(), broadphase->getSmallAabbIndicesGPU(), broadphase->getLargeAabbIndicesGPU() );
+
+ m_data->m_plbvh->testRaysAgainstBvhAabbs(*m_data->m_gpuRays, *m_data->m_gpuNumRayRigidPairs, *m_data->m_gpuRayRigidPairs);
+
+ int numRayRigidPairs = -1;
+ m_data->m_gpuNumRayRigidPairs->copyToHostPointer(&numRayRigidPairs, 1);
+ if( numRayRigidPairs > m_data->m_gpuRayRigidPairs->size() )
+ {
+ numRayRigidPairs = m_data->m_gpuRayRigidPairs->size();
+ m_data->m_gpuNumRayRigidPairs->copyFromHostPointer(&numRayRigidPairs, 1);
+ }
+
+ m_data->m_gpuRayRigidPairs->resize(numRayRigidPairs); //Radix sort needs b3OpenCLArray::size() to be correct
+
+ //Sort ray-rigid pairs by ray index
+ {
+ B3_PROFILE("sort ray-rigid pairs");
+ m_data->m_radixSorter->execute( *reinterpret_cast< b3OpenCLArray<b3SortData>* >(m_data->m_gpuRayRigidPairs) );
+ }
+
+ //detect start,count of each ray pair
+ {
+ B3_PROFILE("detect ray-rigid pair index ranges");
+
+ {
+ B3_PROFILE("reset ray-rigid pair index ranges");
+
+ m_data->m_fill->execute(*m_data->m_firstRayRigidPairIndexPerRay, numRayRigidPairs, numRays); //atomic_min used to find first index
+ m_data->m_fill->execute(*m_data->m_numRayRigidPairsPerRay, 0, numRays);
+ clFinish(m_data->m_q);
+ }
+
+ b3BufferInfoCL bufferInfo[] =
+ {
+ b3BufferInfoCL( m_data->m_gpuRayRigidPairs->getBufferCL() ),
+
+ b3BufferInfoCL( m_data->m_firstRayRigidPairIndexPerRay->getBufferCL() ),
+ b3BufferInfoCL( m_data->m_numRayRigidPairsPerRay->getBufferCL() )
+ };
+
+ b3LauncherCL launcher(m_data->m_q, m_data->m_findRayRigidPairIndexRanges, "m_findRayRigidPairIndexRanges");
+ launcher.setBuffers( bufferInfo, sizeof(bufferInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst(numRayRigidPairs);
+
+ launcher.launch1D(numRayRigidPairs);
+ clFinish(m_data->m_q);
+ }
+
+ {
+ B3_PROFILE("ray-rigid intersection");
+
+ b3BufferInfoCL bufferInfo[] =
+ {
+ b3BufferInfoCL( m_data->m_gpuRays->getBufferCL() ),
+ b3BufferInfoCL( m_data->m_gpuHitResults->getBufferCL() ),
+ b3BufferInfoCL( m_data->m_firstRayRigidPairIndexPerRay->getBufferCL() ),
+ b3BufferInfoCL( m_data->m_numRayRigidPairsPerRay->getBufferCL() ),
+
+ b3BufferInfoCL( narrowphaseData->m_bodyBufferGPU->getBufferCL() ),
+ b3BufferInfoCL( narrowphaseData->m_collidablesGPU->getBufferCL() ),
+ b3BufferInfoCL( narrowphaseData->m_convexFacesGPU->getBufferCL() ),
+ b3BufferInfoCL( narrowphaseData->m_convexPolyhedraGPU->getBufferCL() ),
+
+ b3BufferInfoCL( m_data->m_gpuRayRigidPairs->getBufferCL() )
+ };
+
+ b3LauncherCL launcher(m_data->m_q, m_data->m_raytracePairsKernel, "m_raytracePairsKernel");
+ launcher.setBuffers( bufferInfo, sizeof(bufferInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst(numRays);
+
+ launcher.launch1D(numRays);
+ clFinish(m_data->m_q);
+ }
+ }
+
+
+
+ //copy results
+ {
+ B3_PROFILE("raycast copyToHost");
+ m_data->m_gpuHitResults->copyToHost(hitResults);
+ }
+
+} \ No newline at end of file
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/Raycast/b3GpuRaycast.h b/thirdparty/bullet/src/Bullet3OpenCL/Raycast/b3GpuRaycast.h
new file mode 100644
index 0000000000..3a5cf44b79
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/Raycast/b3GpuRaycast.h
@@ -0,0 +1,32 @@
+#ifndef B3_GPU_RAYCAST_H
+#define B3_GPU_RAYCAST_H
+
+#include "Bullet3Common/b3Vector3.h"
+#include "Bullet3OpenCL/Initialize/b3OpenCLInclude.h"
+
+#include "Bullet3Common/b3AlignedObjectArray.h"
+#include "Bullet3Collision/NarrowPhaseCollision/b3RaycastInfo.h"
+
+
+
+class b3GpuRaycast
+{
+protected:
+ struct b3GpuRaycastInternalData* m_data;
+public:
+ b3GpuRaycast(cl_context ctx,cl_device_id device, cl_command_queue q);
+ virtual ~b3GpuRaycast();
+
+ void castRaysHost(const b3AlignedObjectArray<b3RayInfo>& raysIn, b3AlignedObjectArray<b3RayHit>& hitResults,
+ int numBodies, const struct b3RigidBodyData* bodies, int numCollidables, const struct b3Collidable* collidables,
+ const struct b3GpuNarrowPhaseInternalData* narrowphaseData);
+
+ void castRays(const b3AlignedObjectArray<b3RayInfo>& rays, b3AlignedObjectArray<b3RayHit>& hitResults,
+ int numBodies,const struct b3RigidBodyData* bodies, int numCollidables, const struct b3Collidable* collidables,
+ const struct b3GpuNarrowPhaseInternalData* narrowphaseData, class b3GpuBroadphaseInterface* broadphase);
+
+
+
+};
+
+#endif //B3_GPU_RAYCAST_H
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/Raycast/kernels/rayCastKernels.cl b/thirdparty/bullet/src/Bullet3OpenCL/Raycast/kernels/rayCastKernels.cl
new file mode 100644
index 0000000000..e72d96876b
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/Raycast/kernels/rayCastKernels.cl
@@ -0,0 +1,439 @@
+
+#define SHAPE_CONVEX_HULL 3
+#define SHAPE_PLANE 4
+#define SHAPE_CONCAVE_TRIMESH 5
+#define SHAPE_COMPOUND_OF_CONVEX_HULLS 6
+#define SHAPE_SPHERE 7
+
+
+typedef struct
+{
+ float4 m_from;
+ float4 m_to;
+} b3RayInfo;
+
+typedef struct
+{
+ float m_hitFraction;
+ int m_hitResult0;
+ int m_hitResult1;
+ int m_hitResult2;
+ float4 m_hitPoint;
+ float4 m_hitNormal;
+} b3RayHit;
+
+typedef struct
+{
+ float4 m_pos;
+ float4 m_quat;
+ float4 m_linVel;
+ float4 m_angVel;
+
+ unsigned int m_collidableIdx;
+ float m_invMass;
+ float m_restituitionCoeff;
+ float m_frictionCoeff;
+} Body;
+
+typedef struct Collidable
+{
+ union {
+ int m_numChildShapes;
+ int m_bvhIndex;
+ };
+ float m_radius;
+ int m_shapeType;
+ int m_shapeIndex;
+} Collidable;
+
+
+typedef struct
+{
+ float4 m_localCenter;
+ float4 m_extents;
+ float4 mC;
+ float4 mE;
+
+ float m_radius;
+ int m_faceOffset;
+ int m_numFaces;
+ int m_numVertices;
+
+ int m_vertexOffset;
+ int m_uniqueEdgesOffset;
+ int m_numUniqueEdges;
+ int m_unused;
+
+} ConvexPolyhedronCL;
+
+typedef struct
+{
+ float4 m_plane;
+ int m_indexOffset;
+ int m_numIndices;
+} b3GpuFace;
+
+
+
+///////////////////////////////////////
+// Quaternion
+///////////////////////////////////////
+
+typedef float4 Quaternion;
+
+__inline
+ Quaternion qtMul(Quaternion a, Quaternion b);
+
+__inline
+ Quaternion qtNormalize(Quaternion in);
+
+
+__inline
+ Quaternion qtInvert(Quaternion q);
+
+
+__inline
+ float dot3F4(float4 a, float4 b)
+{
+ float4 a1 = (float4)(a.xyz,0.f);
+ float4 b1 = (float4)(b.xyz,0.f);
+ return dot(a1, b1);
+}
+
+
+__inline
+ Quaternion qtMul(Quaternion a, Quaternion b)
+{
+ Quaternion ans;
+ ans = cross( a, b );
+ ans += a.w*b+b.w*a;
+ // ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);
+ ans.w = a.w*b.w - dot3F4(a, b);
+ return ans;
+}
+
+__inline
+ Quaternion qtNormalize(Quaternion in)
+{
+ return fast_normalize(in);
+ // in /= length( in );
+ // return in;
+}
+__inline
+ float4 qtRotate(Quaternion q, float4 vec)
+{
+ Quaternion qInv = qtInvert( q );
+ float4 vcpy = vec;
+ vcpy.w = 0.f;
+ float4 out = qtMul(q,vcpy);
+ out = qtMul(out,qInv);
+ return out;
+}
+
+__inline
+ Quaternion qtInvert(Quaternion q)
+{
+ return (Quaternion)(-q.xyz, q.w);
+}
+
+__inline
+ float4 qtInvRotate(const Quaternion q, float4 vec)
+{
+ return qtRotate( qtInvert( q ), vec );
+}
+
+
+
+void trInverse(float4 translationIn, Quaternion orientationIn,
+ float4* translationOut, Quaternion* orientationOut)
+{
+ *orientationOut = qtInvert(orientationIn);
+ *translationOut = qtRotate(*orientationOut, -translationIn);
+}
+
+
+
+
+
+bool rayConvex(float4 rayFromLocal, float4 rayToLocal, int numFaces, int faceOffset,
+ __global const b3GpuFace* faces, float* hitFraction, float4* hitNormal)
+{
+ rayFromLocal.w = 0.f;
+ rayToLocal.w = 0.f;
+ bool result = true;
+
+ float exitFraction = hitFraction[0];
+ float enterFraction = -0.3f;
+ float4 curHitNormal = (float4)(0,0,0,0);
+ for (int i=0;i<numFaces && result;i++)
+ {
+ b3GpuFace face = faces[faceOffset+i];
+ float fromPlaneDist = dot(rayFromLocal,face.m_plane)+face.m_plane.w;
+ float toPlaneDist = dot(rayToLocal,face.m_plane)+face.m_plane.w;
+ if (fromPlaneDist<0.f)
+ {
+ if (toPlaneDist >= 0.f)
+ {
+ float fraction = fromPlaneDist / (fromPlaneDist-toPlaneDist);
+ if (exitFraction>fraction)
+ {
+ exitFraction = fraction;
+ }
+ }
+ } else
+ {
+ if (toPlaneDist<0.f)
+ {
+ float fraction = fromPlaneDist / (fromPlaneDist-toPlaneDist);
+ if (enterFraction <= fraction)
+ {
+ enterFraction = fraction;
+ curHitNormal = face.m_plane;
+ curHitNormal.w = 0.f;
+ }
+ } else
+ {
+ result = false;
+ }
+ }
+ if (exitFraction <= enterFraction)
+ result = false;
+ }
+
+ if (enterFraction < 0.f)
+ {
+ result = false;
+ }
+
+ if (result)
+ {
+ hitFraction[0] = enterFraction;
+ hitNormal[0] = curHitNormal;
+ }
+ return result;
+}
+
+
+
+
+
+
+bool sphere_intersect(float4 spherePos, float radius, float4 rayFrom, float4 rayTo, float* hitFraction)
+{
+ float4 rs = rayFrom - spherePos;
+ rs.w = 0.f;
+ float4 rayDir = rayTo-rayFrom;
+ rayDir.w = 0.f;
+ float A = dot(rayDir,rayDir);
+ float B = dot(rs, rayDir);
+ float C = dot(rs, rs) - (radius * radius);
+
+ float D = B * B - A*C;
+
+ if (D > 0.0f)
+ {
+ float t = (-B - sqrt(D))/A;
+
+ if ( (t >= 0.0f) && (t < (*hitFraction)) )
+ {
+ *hitFraction = t;
+ return true;
+ }
+ }
+ return false;
+}
+
+float4 setInterpolate3(float4 from, float4 to, float t)
+{
+ float s = 1.0f - t;
+ float4 result;
+ result = s * from + t * to;
+ result.w = 0.f;
+ return result;
+}
+
+__kernel void rayCastKernel(
+ int numRays,
+ const __global b3RayInfo* rays,
+ __global b3RayHit* hitResults,
+ const int numBodies,
+ __global Body* bodies,
+ __global Collidable* collidables,
+ __global const b3GpuFace* faces,
+ __global const ConvexPolyhedronCL* convexShapes )
+{
+
+ int i = get_global_id(0);
+ if (i>=numRays)
+ return;
+
+ hitResults[i].m_hitFraction = 1.f;
+
+ float4 rayFrom = rays[i].m_from;
+ float4 rayTo = rays[i].m_to;
+ float hitFraction = 1.f;
+ float4 hitPoint;
+ float4 hitNormal;
+ int hitBodyIndex= -1;
+
+ int cachedCollidableIndex = -1;
+ Collidable cachedCollidable;
+
+ for (int b=0;b<numBodies;b++)
+ {
+ if (hitResults[i].m_hitResult2==b)
+ continue;
+ Body body = bodies[b];
+ float4 pos = body.m_pos;
+ float4 orn = body.m_quat;
+ if (cachedCollidableIndex != body.m_collidableIdx)
+ {
+ cachedCollidableIndex = body.m_collidableIdx;
+ cachedCollidable = collidables[cachedCollidableIndex];
+ }
+ if (cachedCollidable.m_shapeType == SHAPE_CONVEX_HULL)
+ {
+
+ float4 invPos = (float4)(0,0,0,0);
+ float4 invOrn = (float4)(0,0,0,0);
+ float4 rayFromLocal = (float4)(0,0,0,0);
+ float4 rayToLocal = (float4)(0,0,0,0);
+ invOrn = qtInvert(orn);
+ invPos = qtRotate(invOrn, -pos);
+ rayFromLocal = qtRotate( invOrn, rayFrom ) + invPos;
+ rayToLocal = qtRotate( invOrn, rayTo) + invPos;
+ rayFromLocal.w = 0.f;
+ rayToLocal.w = 0.f;
+ int numFaces = convexShapes[cachedCollidable.m_shapeIndex].m_numFaces;
+ int faceOffset = convexShapes[cachedCollidable.m_shapeIndex].m_faceOffset;
+ if (numFaces)
+ {
+ if (rayConvex(rayFromLocal, rayToLocal, numFaces, faceOffset,faces, &hitFraction, &hitNormal))
+ {
+ hitBodyIndex = b;
+
+ }
+ }
+ }
+ if (cachedCollidable.m_shapeType == SHAPE_SPHERE)
+ {
+ float radius = cachedCollidable.m_radius;
+
+ if (sphere_intersect(pos, radius, rayFrom, rayTo, &hitFraction))
+ {
+ hitBodyIndex = b;
+ hitNormal = (float4) (hitPoint-bodies[b].m_pos);
+ }
+ }
+ }
+
+ if (hitBodyIndex>=0)
+ {
+ hitPoint = setInterpolate3(rayFrom, rayTo,hitFraction);
+ hitResults[i].m_hitFraction = hitFraction;
+ hitResults[i].m_hitPoint = hitPoint;
+ hitResults[i].m_hitNormal = normalize(hitNormal);
+ hitResults[i].m_hitResult0 = hitBodyIndex;
+ }
+
+}
+
+
+__kernel void findRayRigidPairIndexRanges(__global int2* rayRigidPairs,
+ __global int* out_firstRayRigidPairIndexPerRay,
+ __global int* out_numRayRigidPairsPerRay,
+ int numRayRigidPairs)
+{
+ int rayRigidPairIndex = get_global_id(0);
+ if (rayRigidPairIndex >= numRayRigidPairs) return;
+
+ int rayIndex = rayRigidPairs[rayRigidPairIndex].x;
+
+ atomic_min(&out_firstRayRigidPairIndexPerRay[rayIndex], rayRigidPairIndex);
+ atomic_inc(&out_numRayRigidPairsPerRay[rayIndex]);
+}
+
+__kernel void rayCastPairsKernel(const __global b3RayInfo* rays,
+ __global b3RayHit* hitResults,
+ __global int* firstRayRigidPairIndexPerRay,
+ __global int* numRayRigidPairsPerRay,
+
+ __global Body* bodies,
+ __global Collidable* collidables,
+ __global const b3GpuFace* faces,
+ __global const ConvexPolyhedronCL* convexShapes,
+
+ __global int2* rayRigidPairs,
+ int numRays)
+{
+ int i = get_global_id(0);
+ if (i >= numRays) return;
+
+ float4 rayFrom = rays[i].m_from;
+ float4 rayTo = rays[i].m_to;
+
+ hitResults[i].m_hitFraction = 1.f;
+
+ float hitFraction = 1.f;
+ float4 hitPoint;
+ float4 hitNormal;
+ int hitBodyIndex = -1;
+
+ //
+ for(int pair = 0; pair < numRayRigidPairsPerRay[i]; ++pair)
+ {
+ int rayRigidPairIndex = pair + firstRayRigidPairIndexPerRay[i];
+ int b = rayRigidPairs[rayRigidPairIndex].y;
+
+ if (hitResults[i].m_hitResult2 == b) continue;
+
+ Body body = bodies[b];
+ Collidable rigidCollidable = collidables[body.m_collidableIdx];
+
+ float4 pos = body.m_pos;
+ float4 orn = body.m_quat;
+
+ if (rigidCollidable.m_shapeType == SHAPE_CONVEX_HULL)
+ {
+ float4 invPos = (float4)(0,0,0,0);
+ float4 invOrn = (float4)(0,0,0,0);
+ float4 rayFromLocal = (float4)(0,0,0,0);
+ float4 rayToLocal = (float4)(0,0,0,0);
+ invOrn = qtInvert(orn);
+ invPos = qtRotate(invOrn, -pos);
+ rayFromLocal = qtRotate( invOrn, rayFrom ) + invPos;
+ rayToLocal = qtRotate( invOrn, rayTo) + invPos;
+ rayFromLocal.w = 0.f;
+ rayToLocal.w = 0.f;
+ int numFaces = convexShapes[rigidCollidable.m_shapeIndex].m_numFaces;
+ int faceOffset = convexShapes[rigidCollidable.m_shapeIndex].m_faceOffset;
+
+ if (numFaces && rayConvex(rayFromLocal, rayToLocal, numFaces, faceOffset,faces, &hitFraction, &hitNormal))
+ {
+ hitBodyIndex = b;
+ hitPoint = setInterpolate3(rayFrom, rayTo, hitFraction);
+ }
+ }
+
+ if (rigidCollidable.m_shapeType == SHAPE_SPHERE)
+ {
+ float radius = rigidCollidable.m_radius;
+
+ if (sphere_intersect(pos, radius, rayFrom, rayTo, &hitFraction))
+ {
+ hitBodyIndex = b;
+ hitPoint = setInterpolate3(rayFrom, rayTo, hitFraction);
+ hitNormal = (float4) (hitPoint - bodies[b].m_pos);
+ }
+ }
+ }
+
+ if (hitBodyIndex >= 0)
+ {
+ hitResults[i].m_hitFraction = hitFraction;
+ hitResults[i].m_hitPoint = hitPoint;
+ hitResults[i].m_hitNormal = normalize(hitNormal);
+ hitResults[i].m_hitResult0 = hitBodyIndex;
+ }
+
+}
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/Raycast/kernels/rayCastKernels.h b/thirdparty/bullet/src/Bullet3OpenCL/Raycast/kernels/rayCastKernels.h
new file mode 100644
index 0000000000..6257909a4d
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/Raycast/kernels/rayCastKernels.h
@@ -0,0 +1,381 @@
+//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
+static const char* rayCastKernelCL= \
+"#define SHAPE_CONVEX_HULL 3\n"
+"#define SHAPE_PLANE 4\n"
+"#define SHAPE_CONCAVE_TRIMESH 5\n"
+"#define SHAPE_COMPOUND_OF_CONVEX_HULLS 6\n"
+"#define SHAPE_SPHERE 7\n"
+"typedef struct\n"
+"{\n"
+" float4 m_from;\n"
+" float4 m_to;\n"
+"} b3RayInfo;\n"
+"typedef struct\n"
+"{\n"
+" float m_hitFraction;\n"
+" int m_hitResult0;\n"
+" int m_hitResult1;\n"
+" int m_hitResult2;\n"
+" float4 m_hitPoint;\n"
+" float4 m_hitNormal;\n"
+"} b3RayHit;\n"
+"typedef struct\n"
+"{\n"
+" float4 m_pos;\n"
+" float4 m_quat;\n"
+" float4 m_linVel;\n"
+" float4 m_angVel;\n"
+" unsigned int m_collidableIdx;\n"
+" float m_invMass;\n"
+" float m_restituitionCoeff;\n"
+" float m_frictionCoeff;\n"
+"} Body;\n"
+"typedef struct Collidable\n"
+"{\n"
+" union {\n"
+" int m_numChildShapes;\n"
+" int m_bvhIndex;\n"
+" };\n"
+" float m_radius;\n"
+" int m_shapeType;\n"
+" int m_shapeIndex;\n"
+"} Collidable;\n"
+"typedef struct \n"
+"{\n"
+" float4 m_localCenter;\n"
+" float4 m_extents;\n"
+" float4 mC;\n"
+" float4 mE;\n"
+" float m_radius;\n"
+" int m_faceOffset;\n"
+" int m_numFaces;\n"
+" int m_numVertices;\n"
+" int m_vertexOffset;\n"
+" int m_uniqueEdgesOffset;\n"
+" int m_numUniqueEdges;\n"
+" int m_unused;\n"
+"} ConvexPolyhedronCL;\n"
+"typedef struct\n"
+"{\n"
+" float4 m_plane;\n"
+" int m_indexOffset;\n"
+" int m_numIndices;\n"
+"} b3GpuFace;\n"
+"///////////////////////////////////////\n"
+"// Quaternion\n"
+"///////////////////////////////////////\n"
+"typedef float4 Quaternion;\n"
+"__inline\n"
+" Quaternion qtMul(Quaternion a, Quaternion b);\n"
+"__inline\n"
+" Quaternion qtNormalize(Quaternion in);\n"
+"__inline\n"
+" Quaternion qtInvert(Quaternion q);\n"
+"__inline\n"
+" float dot3F4(float4 a, float4 b)\n"
+"{\n"
+" float4 a1 = (float4)(a.xyz,0.f);\n"
+" float4 b1 = (float4)(b.xyz,0.f);\n"
+" return dot(a1, b1);\n"
+"}\n"
+"__inline\n"
+" Quaternion qtMul(Quaternion a, Quaternion b)\n"
+"{\n"
+" Quaternion ans;\n"
+" ans = cross( a, b );\n"
+" ans += a.w*b+b.w*a;\n"
+" // ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
+" ans.w = a.w*b.w - dot3F4(a, b);\n"
+" return ans;\n"
+"}\n"
+"__inline\n"
+" Quaternion qtNormalize(Quaternion in)\n"
+"{\n"
+" return fast_normalize(in);\n"
+" // in /= length( in );\n"
+" // return in;\n"
+"}\n"
+"__inline\n"
+" float4 qtRotate(Quaternion q, float4 vec)\n"
+"{\n"
+" Quaternion qInv = qtInvert( q );\n"
+" float4 vcpy = vec;\n"
+" vcpy.w = 0.f;\n"
+" float4 out = qtMul(q,vcpy);\n"
+" out = qtMul(out,qInv);\n"
+" return out;\n"
+"}\n"
+"__inline\n"
+" Quaternion qtInvert(Quaternion q)\n"
+"{\n"
+" return (Quaternion)(-q.xyz, q.w);\n"
+"}\n"
+"__inline\n"
+" float4 qtInvRotate(const Quaternion q, float4 vec)\n"
+"{\n"
+" return qtRotate( qtInvert( q ), vec );\n"
+"}\n"
+"void trInverse(float4 translationIn, Quaternion orientationIn,\n"
+" float4* translationOut, Quaternion* orientationOut)\n"
+"{\n"
+" *orientationOut = qtInvert(orientationIn);\n"
+" *translationOut = qtRotate(*orientationOut, -translationIn);\n"
+"}\n"
+"bool rayConvex(float4 rayFromLocal, float4 rayToLocal, int numFaces, int faceOffset,\n"
+" __global const b3GpuFace* faces, float* hitFraction, float4* hitNormal)\n"
+"{\n"
+" rayFromLocal.w = 0.f;\n"
+" rayToLocal.w = 0.f;\n"
+" bool result = true;\n"
+" float exitFraction = hitFraction[0];\n"
+" float enterFraction = -0.3f;\n"
+" float4 curHitNormal = (float4)(0,0,0,0);\n"
+" for (int i=0;i<numFaces && result;i++)\n"
+" {\n"
+" b3GpuFace face = faces[faceOffset+i];\n"
+" float fromPlaneDist = dot(rayFromLocal,face.m_plane)+face.m_plane.w;\n"
+" float toPlaneDist = dot(rayToLocal,face.m_plane)+face.m_plane.w;\n"
+" if (fromPlaneDist<0.f)\n"
+" {\n"
+" if (toPlaneDist >= 0.f)\n"
+" {\n"
+" float fraction = fromPlaneDist / (fromPlaneDist-toPlaneDist);\n"
+" if (exitFraction>fraction)\n"
+" {\n"
+" exitFraction = fraction;\n"
+" }\n"
+" } \n"
+" } else\n"
+" {\n"
+" if (toPlaneDist<0.f)\n"
+" {\n"
+" float fraction = fromPlaneDist / (fromPlaneDist-toPlaneDist);\n"
+" if (enterFraction <= fraction)\n"
+" {\n"
+" enterFraction = fraction;\n"
+" curHitNormal = face.m_plane;\n"
+" curHitNormal.w = 0.f;\n"
+" }\n"
+" } else\n"
+" {\n"
+" result = false;\n"
+" }\n"
+" }\n"
+" if (exitFraction <= enterFraction)\n"
+" result = false;\n"
+" }\n"
+" if (enterFraction < 0.f)\n"
+" {\n"
+" result = false;\n"
+" }\n"
+" if (result)\n"
+" { \n"
+" hitFraction[0] = enterFraction;\n"
+" hitNormal[0] = curHitNormal;\n"
+" }\n"
+" return result;\n"
+"}\n"
+"bool sphere_intersect(float4 spherePos, float radius, float4 rayFrom, float4 rayTo, float* hitFraction)\n"
+"{\n"
+" float4 rs = rayFrom - spherePos;\n"
+" rs.w = 0.f;\n"
+" float4 rayDir = rayTo-rayFrom;\n"
+" rayDir.w = 0.f;\n"
+" float A = dot(rayDir,rayDir);\n"
+" float B = dot(rs, rayDir);\n"
+" float C = dot(rs, rs) - (radius * radius);\n"
+" float D = B * B - A*C;\n"
+" if (D > 0.0f)\n"
+" {\n"
+" float t = (-B - sqrt(D))/A;\n"
+" if ( (t >= 0.0f) && (t < (*hitFraction)) )\n"
+" {\n"
+" *hitFraction = t;\n"
+" return true;\n"
+" }\n"
+" }\n"
+" return false;\n"
+"}\n"
+"float4 setInterpolate3(float4 from, float4 to, float t)\n"
+"{\n"
+" float s = 1.0f - t;\n"
+" float4 result;\n"
+" result = s * from + t * to;\n"
+" result.w = 0.f; \n"
+" return result; \n"
+"}\n"
+"__kernel void rayCastKernel( \n"
+" int numRays, \n"
+" const __global b3RayInfo* rays, \n"
+" __global b3RayHit* hitResults, \n"
+" const int numBodies, \n"
+" __global Body* bodies,\n"
+" __global Collidable* collidables,\n"
+" __global const b3GpuFace* faces,\n"
+" __global const ConvexPolyhedronCL* convexShapes )\n"
+"{\n"
+" int i = get_global_id(0);\n"
+" if (i>=numRays)\n"
+" return;\n"
+" hitResults[i].m_hitFraction = 1.f;\n"
+" float4 rayFrom = rays[i].m_from;\n"
+" float4 rayTo = rays[i].m_to;\n"
+" float hitFraction = 1.f;\n"
+" float4 hitPoint;\n"
+" float4 hitNormal;\n"
+" int hitBodyIndex= -1;\n"
+" int cachedCollidableIndex = -1;\n"
+" Collidable cachedCollidable;\n"
+" for (int b=0;b<numBodies;b++)\n"
+" {\n"
+" if (hitResults[i].m_hitResult2==b)\n"
+" continue;\n"
+" Body body = bodies[b];\n"
+" float4 pos = body.m_pos;\n"
+" float4 orn = body.m_quat;\n"
+" if (cachedCollidableIndex != body.m_collidableIdx)\n"
+" {\n"
+" cachedCollidableIndex = body.m_collidableIdx;\n"
+" cachedCollidable = collidables[cachedCollidableIndex];\n"
+" }\n"
+" if (cachedCollidable.m_shapeType == SHAPE_CONVEX_HULL)\n"
+" {\n"
+" float4 invPos = (float4)(0,0,0,0);\n"
+" float4 invOrn = (float4)(0,0,0,0);\n"
+" float4 rayFromLocal = (float4)(0,0,0,0);\n"
+" float4 rayToLocal = (float4)(0,0,0,0);\n"
+" invOrn = qtInvert(orn);\n"
+" invPos = qtRotate(invOrn, -pos);\n"
+" rayFromLocal = qtRotate( invOrn, rayFrom ) + invPos;\n"
+" rayToLocal = qtRotate( invOrn, rayTo) + invPos;\n"
+" rayFromLocal.w = 0.f;\n"
+" rayToLocal.w = 0.f;\n"
+" int numFaces = convexShapes[cachedCollidable.m_shapeIndex].m_numFaces;\n"
+" int faceOffset = convexShapes[cachedCollidable.m_shapeIndex].m_faceOffset;\n"
+" if (numFaces)\n"
+" {\n"
+" if (rayConvex(rayFromLocal, rayToLocal, numFaces, faceOffset,faces, &hitFraction, &hitNormal))\n"
+" {\n"
+" hitBodyIndex = b;\n"
+" \n"
+" }\n"
+" }\n"
+" }\n"
+" if (cachedCollidable.m_shapeType == SHAPE_SPHERE)\n"
+" {\n"
+" float radius = cachedCollidable.m_radius;\n"
+" \n"
+" if (sphere_intersect(pos, radius, rayFrom, rayTo, &hitFraction))\n"
+" {\n"
+" hitBodyIndex = b;\n"
+" hitNormal = (float4) (hitPoint-bodies[b].m_pos);\n"
+" }\n"
+" }\n"
+" }\n"
+" if (hitBodyIndex>=0)\n"
+" {\n"
+" hitPoint = setInterpolate3(rayFrom, rayTo,hitFraction);\n"
+" hitResults[i].m_hitFraction = hitFraction;\n"
+" hitResults[i].m_hitPoint = hitPoint;\n"
+" hitResults[i].m_hitNormal = normalize(hitNormal);\n"
+" hitResults[i].m_hitResult0 = hitBodyIndex;\n"
+" }\n"
+"}\n"
+"__kernel void findRayRigidPairIndexRanges(__global int2* rayRigidPairs, \n"
+" __global int* out_firstRayRigidPairIndexPerRay,\n"
+" __global int* out_numRayRigidPairsPerRay,\n"
+" int numRayRigidPairs)\n"
+"{\n"
+" int rayRigidPairIndex = get_global_id(0);\n"
+" if (rayRigidPairIndex >= numRayRigidPairs) return;\n"
+" \n"
+" int rayIndex = rayRigidPairs[rayRigidPairIndex].x;\n"
+" \n"
+" atomic_min(&out_firstRayRigidPairIndexPerRay[rayIndex], rayRigidPairIndex);\n"
+" atomic_inc(&out_numRayRigidPairsPerRay[rayIndex]);\n"
+"}\n"
+"__kernel void rayCastPairsKernel(const __global b3RayInfo* rays, \n"
+" __global b3RayHit* hitResults, \n"
+" __global int* firstRayRigidPairIndexPerRay,\n"
+" __global int* numRayRigidPairsPerRay,\n"
+" \n"
+" __global Body* bodies,\n"
+" __global Collidable* collidables,\n"
+" __global const b3GpuFace* faces,\n"
+" __global const ConvexPolyhedronCL* convexShapes,\n"
+" \n"
+" __global int2* rayRigidPairs,\n"
+" int numRays)\n"
+"{\n"
+" int i = get_global_id(0);\n"
+" if (i >= numRays) return;\n"
+" \n"
+" float4 rayFrom = rays[i].m_from;\n"
+" float4 rayTo = rays[i].m_to;\n"
+" \n"
+" hitResults[i].m_hitFraction = 1.f;\n"
+" \n"
+" float hitFraction = 1.f;\n"
+" float4 hitPoint;\n"
+" float4 hitNormal;\n"
+" int hitBodyIndex = -1;\n"
+" \n"
+" //\n"
+" for(int pair = 0; pair < numRayRigidPairsPerRay[i]; ++pair)\n"
+" {\n"
+" int rayRigidPairIndex = pair + firstRayRigidPairIndexPerRay[i];\n"
+" int b = rayRigidPairs[rayRigidPairIndex].y;\n"
+" \n"
+" if (hitResults[i].m_hitResult2 == b) continue;\n"
+" \n"
+" Body body = bodies[b];\n"
+" Collidable rigidCollidable = collidables[body.m_collidableIdx];\n"
+" \n"
+" float4 pos = body.m_pos;\n"
+" float4 orn = body.m_quat;\n"
+" \n"
+" if (rigidCollidable.m_shapeType == SHAPE_CONVEX_HULL)\n"
+" {\n"
+" float4 invPos = (float4)(0,0,0,0);\n"
+" float4 invOrn = (float4)(0,0,0,0);\n"
+" float4 rayFromLocal = (float4)(0,0,0,0);\n"
+" float4 rayToLocal = (float4)(0,0,0,0);\n"
+" invOrn = qtInvert(orn);\n"
+" invPos = qtRotate(invOrn, -pos);\n"
+" rayFromLocal = qtRotate( invOrn, rayFrom ) + invPos;\n"
+" rayToLocal = qtRotate( invOrn, rayTo) + invPos;\n"
+" rayFromLocal.w = 0.f;\n"
+" rayToLocal.w = 0.f;\n"
+" int numFaces = convexShapes[rigidCollidable.m_shapeIndex].m_numFaces;\n"
+" int faceOffset = convexShapes[rigidCollidable.m_shapeIndex].m_faceOffset;\n"
+" \n"
+" if (numFaces && rayConvex(rayFromLocal, rayToLocal, numFaces, faceOffset,faces, &hitFraction, &hitNormal))\n"
+" {\n"
+" hitBodyIndex = b;\n"
+" hitPoint = setInterpolate3(rayFrom, rayTo, hitFraction);\n"
+" }\n"
+" }\n"
+" \n"
+" if (rigidCollidable.m_shapeType == SHAPE_SPHERE)\n"
+" {\n"
+" float radius = rigidCollidable.m_radius;\n"
+" \n"
+" if (sphere_intersect(pos, radius, rayFrom, rayTo, &hitFraction))\n"
+" {\n"
+" hitBodyIndex = b;\n"
+" hitPoint = setInterpolate3(rayFrom, rayTo, hitFraction);\n"
+" hitNormal = (float4) (hitPoint - bodies[b].m_pos);\n"
+" }\n"
+" }\n"
+" }\n"
+" \n"
+" if (hitBodyIndex >= 0)\n"
+" {\n"
+" hitResults[i].m_hitFraction = hitFraction;\n"
+" hitResults[i].m_hitPoint = hitPoint;\n"
+" hitResults[i].m_hitNormal = normalize(hitNormal);\n"
+" hitResults[i].m_hitResult0 = hitBodyIndex;\n"
+" }\n"
+" \n"
+"}\n"
+;
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuConstraint4.h b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuConstraint4.h
new file mode 100644
index 0000000000..c7478f54a1
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuConstraint4.h
@@ -0,0 +1,18 @@
+
+#ifndef B3_CONSTRAINT4_h
+#define B3_CONSTRAINT4_h
+#include "Bullet3Common/b3Vector3.h"
+
+#include "Bullet3Dynamics/shared/b3ContactConstraint4.h"
+
+
+B3_ATTRIBUTE_ALIGNED16(struct) b3GpuConstraint4 : public b3ContactConstraint4
+{
+ B3_DECLARE_ALIGNED_ALLOCATOR();
+
+ inline void setFrictionCoeff(float value) { m_linear[3] = value; }
+ inline float getFrictionCoeff() const { return m_linear[3]; }
+};
+
+#endif //B3_CONSTRAINT4_h
+
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuGenericConstraint.cpp b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuGenericConstraint.cpp
new file mode 100644
index 0000000000..af687b54e9
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuGenericConstraint.cpp
@@ -0,0 +1,137 @@
+/*
+Copyright (c) 2012 Advanced Micro Devices, Inc.
+
+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.
+*/
+//Originally written by Erwin Coumans
+
+#include "b3GpuGenericConstraint.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
+
+#include <new>
+#include "Bullet3Common/b3Transform.h"
+
+void b3GpuGenericConstraint::getInfo1 (unsigned int* info,const b3RigidBodyData* bodies)
+{
+ switch (m_constraintType)
+ {
+ case B3_GPU_POINT2POINT_CONSTRAINT_TYPE:
+ {
+ *info = 3;
+ break;
+ };
+ default:
+ {
+ b3Assert(0);
+ }
+ };
+}
+
+void getInfo2Point2Point(b3GpuGenericConstraint* constraint, b3GpuConstraintInfo2* info, const b3RigidBodyData* bodies)
+{
+ b3Transform trA;
+ trA.setIdentity();
+ trA.setOrigin(bodies[constraint->m_rbA].m_pos);
+ trA.setRotation(bodies[constraint->m_rbA].m_quat);
+
+ b3Transform trB;
+ trB.setIdentity();
+ trB.setOrigin(bodies[constraint->m_rbB].m_pos);
+ trB.setRotation(bodies[constraint->m_rbB].m_quat);
+
+ // anchor points in global coordinates with respect to body PORs.
+
+ // set jacobian
+ info->m_J1linearAxis[0] = 1;
+ info->m_J1linearAxis[info->rowskip+1] = 1;
+ info->m_J1linearAxis[2*info->rowskip+2] = 1;
+
+ b3Vector3 a1 = trA.getBasis()*constraint->getPivotInA();
+ //b3Vector3 a1a = b3QuatRotate(trA.getRotation(),constraint->getPivotInA());
+
+ {
+ b3Vector3* angular0 = (b3Vector3*)(info->m_J1angularAxis);
+ b3Vector3* angular1 = (b3Vector3*)(info->m_J1angularAxis+info->rowskip);
+ b3Vector3* angular2 = (b3Vector3*)(info->m_J1angularAxis+2*info->rowskip);
+ b3Vector3 a1neg = -a1;
+ a1neg.getSkewSymmetricMatrix(angular0,angular1,angular2);
+ }
+
+ if (info->m_J2linearAxis)
+ {
+ info->m_J2linearAxis[0] = -1;
+ info->m_J2linearAxis[info->rowskip+1] = -1;
+ info->m_J2linearAxis[2*info->rowskip+2] = -1;
+ }
+
+ b3Vector3 a2 = trB.getBasis()*constraint->getPivotInB();
+
+ {
+ // b3Vector3 a2n = -a2;
+ b3Vector3* angular0 = (b3Vector3*)(info->m_J2angularAxis);
+ b3Vector3* angular1 = (b3Vector3*)(info->m_J2angularAxis+info->rowskip);
+ b3Vector3* angular2 = (b3Vector3*)(info->m_J2angularAxis+2*info->rowskip);
+ a2.getSkewSymmetricMatrix(angular0,angular1,angular2);
+ }
+
+
+
+ // set right hand side
+// b3Scalar currERP = (m_flags & B3_P2P_FLAGS_ERP) ? m_erp : info->erp;
+ b3Scalar currERP = info->erp;
+
+ b3Scalar k = info->fps * currERP;
+ int j;
+ for (j=0; j<3; j++)
+ {
+ info->m_constraintError[j*info->rowskip] = k * (a2[j] + trB.getOrigin()[j] - a1[j] - trA.getOrigin()[j]);
+ //printf("info->m_constraintError[%d]=%f\n",j,info->m_constraintError[j]);
+ }
+#if 0
+ if(m_flags & B3_P2P_FLAGS_CFM)
+ {
+ for (j=0; j<3; j++)
+ {
+ info->cfm[j*info->rowskip] = m_cfm;
+ }
+ }
+#endif
+
+#if 0
+ b3Scalar impulseClamp = m_setting.m_impulseClamp;//
+ for (j=0; j<3; j++)
+ {
+ if (m_setting.m_impulseClamp > 0)
+ {
+ info->m_lowerLimit[j*info->rowskip] = -impulseClamp;
+ info->m_upperLimit[j*info->rowskip] = impulseClamp;
+ }
+ }
+ info->m_damping = m_setting.m_damping;
+#endif
+
+}
+
+void b3GpuGenericConstraint::getInfo2 (b3GpuConstraintInfo2* info, const b3RigidBodyData* bodies)
+{
+ switch (m_constraintType)
+ {
+ case B3_GPU_POINT2POINT_CONSTRAINT_TYPE:
+ {
+ getInfo2Point2Point(this,info,bodies);
+ break;
+ };
+ default:
+ {
+ b3Assert(0);
+ }
+ };
+}
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuGenericConstraint.h b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuGenericConstraint.h
new file mode 100644
index 0000000000..14b3ba7fec
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuGenericConstraint.h
@@ -0,0 +1,132 @@
+/*
+Copyright (c) 2013 Advanced Micro Devices, Inc.
+
+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.
+*/
+//Originally written by Erwin Coumans
+
+#ifndef B3_GPU_GENERIC_CONSTRAINT_H
+#define B3_GPU_GENERIC_CONSTRAINT_H
+
+#include "Bullet3Common/b3Quaternion.h"
+struct b3RigidBodyData;
+enum B3_CONSTRAINT_FLAGS
+{
+ B3_CONSTRAINT_FLAG_ENABLED=1,
+};
+
+enum b3GpuGenericConstraintType
+{
+ B3_GPU_POINT2POINT_CONSTRAINT_TYPE=3,
+ B3_GPU_FIXED_CONSTRAINT_TYPE=4,
+// B3_HINGE_CONSTRAINT_TYPE,
+// B3_CONETWIST_CONSTRAINT_TYPE,
+// B3_D6_CONSTRAINT_TYPE,
+// B3_SLIDER_CONSTRAINT_TYPE,
+// B3_CONTACT_CONSTRAINT_TYPE,
+// B3_D6_SPRING_CONSTRAINT_TYPE,
+// B3_GEAR_CONSTRAINT_TYPE,
+
+ B3_GPU_MAX_CONSTRAINT_TYPE
+};
+
+
+
+struct b3GpuConstraintInfo2
+{
+ // integrator parameters: frames per second (1/stepsize), default error
+ // reduction parameter (0..1).
+ b3Scalar fps,erp;
+
+ // for the first and second body, pointers to two (linear and angular)
+ // n*3 jacobian sub matrices, stored by rows. these matrices will have
+ // been initialized to 0 on entry. if the second body is zero then the
+ // J2xx pointers may be 0.
+ b3Scalar *m_J1linearAxis,*m_J1angularAxis,*m_J2linearAxis,*m_J2angularAxis;
+
+ // elements to jump from one row to the next in J's
+ int rowskip;
+
+ // right hand sides of the equation J*v = c + cfm * lambda. cfm is the
+ // "constraint force mixing" vector. c is set to zero on entry, cfm is
+ // set to a constant value (typically very small or zero) value on entry.
+ b3Scalar *m_constraintError,*cfm;
+
+ // lo and hi limits for variables (set to -/+ infinity on entry).
+ b3Scalar *m_lowerLimit,*m_upperLimit;
+
+ // findex vector for variables. see the LCP solver interface for a
+ // description of what this does. this is set to -1 on entry.
+ // note that the returned indexes are relative to the first index of
+ // the constraint.
+ int *findex;
+ // number of solver iterations
+ int m_numIterations;
+
+ //damping of the velocity
+ b3Scalar m_damping;
+};
+
+
+B3_ATTRIBUTE_ALIGNED16(struct) b3GpuGenericConstraint
+{
+ int m_constraintType;
+ int m_rbA;
+ int m_rbB;
+ float m_breakingImpulseThreshold;
+
+ b3Vector3 m_pivotInA;
+ b3Vector3 m_pivotInB;
+ b3Quaternion m_relTargetAB;
+
+ int m_flags;
+ int m_uid;
+ int m_padding[2];
+
+ int getRigidBodyA() const
+ {
+ return m_rbA;
+ }
+ int getRigidBodyB() const
+ {
+ return m_rbB;
+ }
+
+ const b3Vector3& getPivotInA() const
+ {
+ return m_pivotInA;
+ }
+
+ const b3Vector3& getPivotInB() const
+ {
+ return m_pivotInB;
+ }
+
+ int isEnabled() const
+ {
+ return m_flags & B3_CONSTRAINT_FLAG_ENABLED;
+ }
+
+ float getBreakingImpulseThreshold() const
+ {
+ return m_breakingImpulseThreshold;
+ }
+
+ ///internal method used by the constraint solver, don't use them directly
+ void getInfo1 (unsigned int* info,const b3RigidBodyData* bodies);
+
+ ///internal method used by the constraint solver, don't use them directly
+ void getInfo2 (b3GpuConstraintInfo2* info, const b3RigidBodyData* bodies);
+
+
+};
+
+#endif //B3_GPU_GENERIC_CONSTRAINT_H \ No newline at end of file
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuJacobiContactSolver.cpp b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuJacobiContactSolver.cpp
new file mode 100644
index 0000000000..179dfc4f26
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuJacobiContactSolver.cpp
@@ -0,0 +1,1382 @@
+
+#include "b3GpuJacobiContactSolver.h"
+#include "Bullet3Collision/NarrowPhaseCollision/b3Contact4.h"
+#include "Bullet3Common/b3AlignedObjectArray.h"
+#include "Bullet3OpenCL/ParallelPrimitives/b3FillCL.h" //b3Int2
+class b3Vector3;
+#include "Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.h"
+#include "Bullet3OpenCL/ParallelPrimitives/b3PrefixScanCL.h"
+#include "Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.h"
+#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
+#include "Bullet3OpenCL/RigidBody/kernels/solverUtils.h"
+#include "Bullet3Common/b3Logging.h"
+#include "b3GpuConstraint4.h"
+#include "Bullet3Common/shared/b3Int2.h"
+#include "Bullet3Common/shared/b3Int4.h"
+#define SOLVER_UTILS_KERNEL_PATH "src/Bullet3OpenCL/RigidBody/kernels/solverUtils.cl"
+
+
+struct b3GpuJacobiSolverInternalData
+{
+ //btRadixSort32CL* m_sort32;
+ //btBoundSearchCL* m_search;
+ b3PrefixScanCL* m_scan;
+
+ b3OpenCLArray<unsigned int>* m_bodyCount;
+ b3OpenCLArray<b3Int2>* m_contactConstraintOffsets;
+ b3OpenCLArray<unsigned int>* m_offsetSplitBodies;
+
+ b3OpenCLArray<b3Vector3>* m_deltaLinearVelocities;
+ b3OpenCLArray<b3Vector3>* m_deltaAngularVelocities;
+
+ b3AlignedObjectArray<b3Vector3> m_deltaLinearVelocitiesCPU;
+ b3AlignedObjectArray<b3Vector3> m_deltaAngularVelocitiesCPU;
+
+
+
+ b3OpenCLArray<b3GpuConstraint4>* m_contactConstraints;
+
+ b3FillCL* m_filler;
+
+
+ cl_kernel m_countBodiesKernel;
+ cl_kernel m_contactToConstraintSplitKernel;
+ cl_kernel m_clearVelocitiesKernel;
+ cl_kernel m_averageVelocitiesKernel;
+ cl_kernel m_updateBodyVelocitiesKernel;
+ cl_kernel m_solveContactKernel;
+ cl_kernel m_solveFrictionKernel;
+
+
+
+};
+
+
+b3GpuJacobiContactSolver::b3GpuJacobiContactSolver(cl_context ctx, cl_device_id device, cl_command_queue queue, int pairCapacity)
+ :m_context(ctx),
+ m_device(device),
+ m_queue(queue)
+{
+ m_data = new b3GpuJacobiSolverInternalData;
+ m_data->m_scan = new b3PrefixScanCL(m_context,m_device,m_queue);
+ m_data->m_bodyCount = new b3OpenCLArray<unsigned int>(m_context,m_queue);
+ m_data->m_filler = new b3FillCL(m_context,m_device,m_queue);
+ m_data->m_contactConstraintOffsets = new b3OpenCLArray<b3Int2>(m_context,m_queue);
+ m_data->m_offsetSplitBodies = new b3OpenCLArray<unsigned int>(m_context,m_queue);
+ m_data->m_contactConstraints = new b3OpenCLArray<b3GpuConstraint4>(m_context,m_queue);
+ m_data->m_deltaLinearVelocities = new b3OpenCLArray<b3Vector3>(m_context,m_queue);
+ m_data->m_deltaAngularVelocities = new b3OpenCLArray<b3Vector3>(m_context,m_queue);
+
+ cl_int pErrNum;
+ const char* additionalMacros="";
+ const char* solverUtilsSource = solverUtilsCL;
+ {
+ cl_program solverUtilsProg= b3OpenCLUtils::compileCLProgramFromString( ctx, device, solverUtilsSource, &pErrNum,additionalMacros, SOLVER_UTILS_KERNEL_PATH);
+ b3Assert(solverUtilsProg);
+ m_data->m_countBodiesKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, solverUtilsSource, "CountBodiesKernel", &pErrNum, solverUtilsProg,additionalMacros );
+ b3Assert(m_data->m_countBodiesKernel);
+
+ m_data->m_contactToConstraintSplitKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, solverUtilsSource, "ContactToConstraintSplitKernel", &pErrNum, solverUtilsProg,additionalMacros );
+ b3Assert(m_data->m_contactToConstraintSplitKernel);
+ m_data->m_clearVelocitiesKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, solverUtilsSource, "ClearVelocitiesKernel", &pErrNum, solverUtilsProg,additionalMacros );
+ b3Assert(m_data->m_clearVelocitiesKernel);
+
+ m_data->m_averageVelocitiesKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, solverUtilsSource, "AverageVelocitiesKernel", &pErrNum, solverUtilsProg,additionalMacros );
+ b3Assert(m_data->m_averageVelocitiesKernel);
+
+ m_data->m_updateBodyVelocitiesKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, solverUtilsSource, "UpdateBodyVelocitiesKernel", &pErrNum, solverUtilsProg,additionalMacros );
+ b3Assert(m_data->m_updateBodyVelocitiesKernel);
+
+
+ m_data->m_solveContactKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, solverUtilsSource, "SolveContactJacobiKernel", &pErrNum, solverUtilsProg,additionalMacros );
+ b3Assert(m_data->m_solveContactKernel );
+
+ m_data->m_solveFrictionKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, solverUtilsSource, "SolveFrictionJacobiKernel", &pErrNum, solverUtilsProg,additionalMacros );
+ b3Assert(m_data->m_solveFrictionKernel);
+ }
+
+}
+
+
+b3GpuJacobiContactSolver::~b3GpuJacobiContactSolver()
+{
+ clReleaseKernel(m_data->m_solveContactKernel);
+ clReleaseKernel(m_data->m_solveFrictionKernel);
+ clReleaseKernel(m_data->m_countBodiesKernel);
+ clReleaseKernel(m_data->m_contactToConstraintSplitKernel);
+ clReleaseKernel(m_data->m_averageVelocitiesKernel);
+ clReleaseKernel(m_data->m_updateBodyVelocitiesKernel);
+ clReleaseKernel(m_data->m_clearVelocitiesKernel );
+
+ delete m_data->m_deltaLinearVelocities;
+ delete m_data->m_deltaAngularVelocities;
+ delete m_data->m_contactConstraints;
+ delete m_data->m_offsetSplitBodies;
+ delete m_data->m_contactConstraintOffsets;
+ delete m_data->m_bodyCount;
+ delete m_data->m_filler;
+ delete m_data->m_scan;
+ delete m_data;
+}
+
+
+
+b3Vector3 make_float4(float v)
+{
+ return b3MakeVector3 (v,v,v);
+}
+
+b3Vector4 make_float4(float x,float y, float z, float w)
+{
+ return b3MakeVector4 (x,y,z,w);
+}
+
+
+ static
+ inline
+ float calcRelVel(const b3Vector3& l0, const b3Vector3& l1, const b3Vector3& a0, const b3Vector3& a1,
+ const b3Vector3& linVel0, const b3Vector3& angVel0, const b3Vector3& linVel1, const b3Vector3& angVel1)
+ {
+ return b3Dot(l0, linVel0) + b3Dot(a0, angVel0) + b3Dot(l1, linVel1) + b3Dot(a1, angVel1);
+ }
+
+
+ static
+ inline
+ void setLinearAndAngular(const b3Vector3& n, const b3Vector3& r0, const b3Vector3& r1,
+ b3Vector3& linear, b3Vector3& angular0, b3Vector3& angular1)
+ {
+ linear = n;
+ angular0 = b3Cross(r0, n);
+ angular1 = -b3Cross(r1, n);
+ }
+
+
+static __inline void solveContact(b3GpuConstraint4& cs,
+ const b3Vector3& posA, const b3Vector3& linVelARO, const b3Vector3& angVelARO, float invMassA, const b3Matrix3x3& invInertiaA,
+ const b3Vector3& posB, const b3Vector3& linVelBRO, const b3Vector3& angVelBRO, float invMassB, const b3Matrix3x3& invInertiaB,
+ float maxRambdaDt[4], float minRambdaDt[4], b3Vector3& dLinVelA, b3Vector3& dAngVelA, b3Vector3& dLinVelB, b3Vector3& dAngVelB)
+{
+
+
+ for(int ic=0; ic<4; ic++)
+ {
+ // dont necessary because this makes change to 0
+ if( cs.m_jacCoeffInv[ic] == 0.f ) continue;
+
+ {
+ b3Vector3 angular0, angular1, linear;
+ b3Vector3 r0 = cs.m_worldPos[ic] - (b3Vector3&)posA;
+ b3Vector3 r1 = cs.m_worldPos[ic] - (b3Vector3&)posB;
+ setLinearAndAngular( (const b3Vector3 &)cs.m_linear, (const b3Vector3 &)r0, (const b3Vector3 &)r1, linear, angular0, angular1 );
+
+ float rambdaDt = calcRelVel((const b3Vector3 &)cs.m_linear,(const b3Vector3 &) -cs.m_linear, angular0, angular1,
+ linVelARO+dLinVelA, angVelARO+dAngVelA, linVelBRO+dLinVelB, angVelBRO+dAngVelB ) + cs.m_b[ic];
+ rambdaDt *= cs.m_jacCoeffInv[ic];
+
+ {
+ float prevSum = cs.m_appliedRambdaDt[ic];
+ float updated = prevSum;
+ updated += rambdaDt;
+ updated = b3Max( updated, minRambdaDt[ic] );
+ updated = b3Min( updated, maxRambdaDt[ic] );
+ rambdaDt = updated - prevSum;
+ cs.m_appliedRambdaDt[ic] = updated;
+ }
+
+ b3Vector3 linImp0 = invMassA*linear*rambdaDt;
+ b3Vector3 linImp1 = invMassB*(-linear)*rambdaDt;
+ b3Vector3 angImp0 = (invInertiaA* angular0)*rambdaDt;
+ b3Vector3 angImp1 = (invInertiaB* angular1)*rambdaDt;
+#ifdef _WIN32
+ b3Assert(_finite(linImp0.getX()));
+ b3Assert(_finite(linImp1.getX()));
+#endif
+
+ if (invMassA)
+ {
+ dLinVelA += linImp0;
+ dAngVelA += angImp0;
+ }
+ if (invMassB)
+ {
+ dLinVelB += linImp1;
+ dAngVelB += angImp1;
+ }
+ }
+ }
+}
+
+
+
+void solveContact3(b3GpuConstraint4* cs,
+ b3Vector3* posAPtr, b3Vector3* linVelA, b3Vector3* angVelA, float invMassA, const b3Matrix3x3& invInertiaA,
+ b3Vector3* posBPtr, b3Vector3* linVelB, b3Vector3* angVelB, float invMassB, const b3Matrix3x3& invInertiaB,
+ b3Vector3* dLinVelA, b3Vector3* dAngVelA, b3Vector3* dLinVelB, b3Vector3* dAngVelB)
+{
+ float minRambdaDt = 0;
+ float maxRambdaDt = FLT_MAX;
+
+ for(int ic=0; ic<4; ic++)
+ {
+ if( cs->m_jacCoeffInv[ic] == 0.f ) continue;
+
+ b3Vector3 angular0, angular1, linear;
+ b3Vector3 r0 = cs->m_worldPos[ic] - *posAPtr;
+ b3Vector3 r1 = cs->m_worldPos[ic] - *posBPtr;
+ setLinearAndAngular( cs->m_linear, r0, r1, linear, angular0, angular1 );
+
+ float rambdaDt = calcRelVel( cs->m_linear, -cs->m_linear, angular0, angular1,
+ *linVelA+*dLinVelA, *angVelA+*dAngVelA, *linVelB+*dLinVelB, *angVelB+*dAngVelB ) + cs->m_b[ic];
+ rambdaDt *= cs->m_jacCoeffInv[ic];
+
+ {
+ float prevSum = cs->m_appliedRambdaDt[ic];
+ float updated = prevSum;
+ updated += rambdaDt;
+ updated = b3Max( updated, minRambdaDt );
+ updated = b3Min( updated, maxRambdaDt );
+ rambdaDt = updated - prevSum;
+ cs->m_appliedRambdaDt[ic] = updated;
+ }
+
+ b3Vector3 linImp0 = invMassA*linear*rambdaDt;
+ b3Vector3 linImp1 = invMassB*(-linear)*rambdaDt;
+ b3Vector3 angImp0 = (invInertiaA* angular0)*rambdaDt;
+ b3Vector3 angImp1 = (invInertiaB* angular1)*rambdaDt;
+
+ if (invMassA)
+ {
+ *dLinVelA += linImp0;
+ *dAngVelA += angImp0;
+ }
+ if (invMassB)
+ {
+ *dLinVelB += linImp1;
+ *dAngVelB += angImp1;
+ }
+ }
+}
+
+
+static inline void solveFriction(b3GpuConstraint4& cs,
+ const b3Vector3& posA, const b3Vector3& linVelARO, const b3Vector3& angVelARO, float invMassA, const b3Matrix3x3& invInertiaA,
+ const b3Vector3& posB, const b3Vector3& linVelBRO, const b3Vector3& angVelBRO, float invMassB, const b3Matrix3x3& invInertiaB,
+ float maxRambdaDt[4], float minRambdaDt[4], b3Vector3& dLinVelA, b3Vector3& dAngVelA, b3Vector3& dLinVelB, b3Vector3& dAngVelB)
+{
+
+ b3Vector3 linVelA = linVelARO+dLinVelA;
+ b3Vector3 linVelB = linVelBRO+dLinVelB;
+ b3Vector3 angVelA = angVelARO+dAngVelA;
+ b3Vector3 angVelB = angVelBRO+dAngVelB;
+
+ if( cs.m_fJacCoeffInv[0] == 0 && cs.m_fJacCoeffInv[0] == 0 ) return;
+ const b3Vector3& center = (const b3Vector3&)cs.m_center;
+
+ b3Vector3 n = -(const b3Vector3&)cs.m_linear;
+
+ b3Vector3 tangent[2];
+#if 1
+ b3PlaneSpace1 (n, tangent[0],tangent[1]);
+#else
+ b3Vector3 r = cs.m_worldPos[0]-center;
+ tangent[0] = cross3( n, r );
+ tangent[1] = cross3( tangent[0], n );
+ tangent[0] = normalize3( tangent[0] );
+ tangent[1] = normalize3( tangent[1] );
+#endif
+
+ b3Vector3 angular0, angular1, linear;
+ b3Vector3 r0 = center - posA;
+ b3Vector3 r1 = center - posB;
+ for(int i=0; i<2; i++)
+ {
+ setLinearAndAngular( tangent[i], r0, r1, linear, angular0, angular1 );
+ float rambdaDt = calcRelVel(linear, -linear, angular0, angular1,
+ linVelA, angVelA, linVelB, angVelB );
+ rambdaDt *= cs.m_fJacCoeffInv[i];
+
+ {
+ float prevSum = cs.m_fAppliedRambdaDt[i];
+ float updated = prevSum;
+ updated += rambdaDt;
+ updated = b3Max( updated, minRambdaDt[i] );
+ updated = b3Min( updated, maxRambdaDt[i] );
+ rambdaDt = updated - prevSum;
+ cs.m_fAppliedRambdaDt[i] = updated;
+ }
+
+ b3Vector3 linImp0 = invMassA*linear*rambdaDt;
+ b3Vector3 linImp1 = invMassB*(-linear)*rambdaDt;
+ b3Vector3 angImp0 = (invInertiaA* angular0)*rambdaDt;
+ b3Vector3 angImp1 = (invInertiaB* angular1)*rambdaDt;
+#ifdef _WIN32
+ b3Assert(_finite(linImp0.getX()));
+ b3Assert(_finite(linImp1.getX()));
+#endif
+ if (invMassA)
+ {
+ dLinVelA += linImp0;
+ dAngVelA += angImp0;
+ }
+ if (invMassB)
+ {
+ dLinVelB += linImp1;
+ dAngVelB += angImp1;
+ }
+ }
+
+ { // angular damping for point constraint
+ b3Vector3 ab = ( posB - posA ).normalized();
+ b3Vector3 ac = ( center - posA ).normalized();
+ if( b3Dot( ab, ac ) > 0.95f || (invMassA == 0.f || invMassB == 0.f))
+ {
+ float angNA = b3Dot( n, angVelA );
+ float angNB = b3Dot( n, angVelB );
+
+ if (invMassA)
+ dAngVelA -= (angNA*0.1f)*n;
+ if (invMassB)
+ dAngVelB -= (angNB*0.1f)*n;
+ }
+ }
+
+}
+
+
+
+
+float calcJacCoeff(const b3Vector3& linear0, const b3Vector3& linear1, const b3Vector3& angular0, const b3Vector3& angular1,
+ float invMass0, const b3Matrix3x3* invInertia0, float invMass1, const b3Matrix3x3* invInertia1, float countA, float countB)
+{
+ // linear0,1 are normlized
+ float jmj0 = invMass0;//dot3F4(linear0, linear0)*invMass0;
+
+ float jmj1 = b3Dot(mtMul3(angular0,*invInertia0), angular0);
+ float jmj2 = invMass1;//dot3F4(linear1, linear1)*invMass1;
+ float jmj3 = b3Dot(mtMul3(angular1,*invInertia1), angular1);
+ return -1.f/((jmj0+jmj1)*countA+(jmj2+jmj3)*countB);
+// return -1.f/((jmj0+jmj1)+(jmj2+jmj3));
+
+}
+
+
+void setConstraint4( const b3Vector3& posA, const b3Vector3& linVelA, const b3Vector3& angVelA, float invMassA, const b3Matrix3x3& invInertiaA,
+ const b3Vector3& posB, const b3Vector3& linVelB, const b3Vector3& angVelB, float invMassB, const b3Matrix3x3& invInertiaB,
+ b3Contact4* src, float dt, float positionDrift, float positionConstraintCoeff, float countA, float countB,
+ b3GpuConstraint4* dstC )
+{
+ dstC->m_bodyA = abs(src->m_bodyAPtrAndSignBit);
+ dstC->m_bodyB = abs(src->m_bodyBPtrAndSignBit);
+
+ float dtInv = 1.f/dt;
+ for(int ic=0; ic<4; ic++)
+ {
+ dstC->m_appliedRambdaDt[ic] = 0.f;
+ }
+ dstC->m_fJacCoeffInv[0] = dstC->m_fJacCoeffInv[1] = 0.f;
+
+
+ dstC->m_linear = src->m_worldNormalOnB;
+ dstC->m_linear[3] = 0.7f ;//src->getFrictionCoeff() );
+ for(int ic=0; ic<4; ic++)
+ {
+ b3Vector3 r0 = src->m_worldPosB[ic] - posA;
+ b3Vector3 r1 = src->m_worldPosB[ic] - posB;
+
+ if( ic >= src->m_worldNormalOnB[3] )//npoints
+ {
+ dstC->m_jacCoeffInv[ic] = 0.f;
+ continue;
+ }
+
+ float relVelN;
+ {
+ b3Vector3 linear, angular0, angular1;
+ setLinearAndAngular(src->m_worldNormalOnB, r0, r1, linear, angular0, angular1);
+
+ dstC->m_jacCoeffInv[ic] = calcJacCoeff(linear, -linear, angular0, angular1,
+ invMassA, &invInertiaA, invMassB, &invInertiaB ,countA,countB);
+
+ relVelN = calcRelVel(linear, -linear, angular0, angular1,
+ linVelA, angVelA, linVelB, angVelB);
+
+ float e = 0.f;//src->getRestituitionCoeff();
+ if( relVelN*relVelN < 0.004f )
+ {
+ e = 0.f;
+ }
+
+ dstC->m_b[ic] = e*relVelN;
+ //float penetration = src->m_worldPos[ic].w;
+ dstC->m_b[ic] += (src->m_worldPosB[ic][3] + positionDrift)*positionConstraintCoeff*dtInv;
+ dstC->m_appliedRambdaDt[ic] = 0.f;
+ }
+ }
+
+ if( src->m_worldNormalOnB[3] > 0 )//npoints
+ { // prepare friction
+ b3Vector3 center = make_float4(0.f);
+ for(int i=0; i<src->m_worldNormalOnB[3]; i++)
+ center += src->m_worldPosB[i];
+ center /= (float)src->m_worldNormalOnB[3];
+
+ b3Vector3 tangent[2];
+ b3PlaneSpace1(src->m_worldNormalOnB,tangent[0],tangent[1]);
+
+ b3Vector3 r[2];
+ r[0] = center - posA;
+ r[1] = center - posB;
+
+ for(int i=0; i<2; i++)
+ {
+ b3Vector3 linear, angular0, angular1;
+ setLinearAndAngular(tangent[i], r[0], r[1], linear, angular0, angular1);
+
+ dstC->m_fJacCoeffInv[i] = calcJacCoeff(linear, -linear, angular0, angular1,
+ invMassA, &invInertiaA, invMassB, &invInertiaB ,countA,countB);
+ dstC->m_fAppliedRambdaDt[i] = 0.f;
+ }
+ dstC->m_center = center;
+ }
+
+ for(int i=0; i<4; i++)
+ {
+ if( i<src->m_worldNormalOnB[3] )
+ {
+ dstC->m_worldPos[i] = src->m_worldPosB[i];
+ }
+ else
+ {
+ dstC->m_worldPos[i] = make_float4(0.f);
+ }
+ }
+}
+
+
+
+void ContactToConstraintKernel(b3Contact4* gContact, b3RigidBodyData* gBodies, b3InertiaData* gShapes, b3GpuConstraint4* gConstraintOut, int nContacts,
+float dt,
+float positionDrift,
+float positionConstraintCoeff, int gIdx, b3AlignedObjectArray<unsigned int>& bodyCount
+)
+{
+ //int gIdx = 0;//GET_GLOBAL_IDX;
+
+ if( gIdx < nContacts )
+ {
+ int aIdx = abs(gContact[gIdx].m_bodyAPtrAndSignBit);
+ int bIdx = abs(gContact[gIdx].m_bodyBPtrAndSignBit);
+
+ b3Vector3 posA = gBodies[aIdx].m_pos;
+ b3Vector3 linVelA = gBodies[aIdx].m_linVel;
+ b3Vector3 angVelA = gBodies[aIdx].m_angVel;
+ float invMassA = gBodies[aIdx].m_invMass;
+ b3Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertiaWorld;//.m_invInertia;
+
+ b3Vector3 posB = gBodies[bIdx].m_pos;
+ b3Vector3 linVelB = gBodies[bIdx].m_linVel;
+ b3Vector3 angVelB = gBodies[bIdx].m_angVel;
+ float invMassB = gBodies[bIdx].m_invMass;
+ b3Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertiaWorld;//m_invInertia;
+
+ b3GpuConstraint4 cs;
+ float countA = invMassA ? (float)(bodyCount[aIdx]) : 1;
+ float countB = invMassB ? (float)(bodyCount[bIdx]) : 1;
+ setConstraint4( posA, linVelA, angVelA, invMassA, invInertiaA, posB, linVelB, angVelB, invMassB, invInertiaB,
+ &gContact[gIdx], dt, positionDrift, positionConstraintCoeff,countA,countB,
+ &cs );
+
+
+
+ cs.m_batchIdx = gContact[gIdx].m_batchIdx;
+
+ gConstraintOut[gIdx] = cs;
+ }
+}
+
+
+void b3GpuJacobiContactSolver::solveGroupHost(b3RigidBodyData* bodies,b3InertiaData* inertias,int numBodies,b3Contact4* manifoldPtr, int numManifolds,const b3JacobiSolverInfo& solverInfo)
+{
+ B3_PROFILE("b3GpuJacobiContactSolver::solveGroup");
+
+ b3AlignedObjectArray<unsigned int> bodyCount;
+ bodyCount.resize(numBodies);
+ for (int i=0;i<numBodies;i++)
+ bodyCount[i] = 0;
+
+ b3AlignedObjectArray<b3Int2> contactConstraintOffsets;
+ contactConstraintOffsets.resize(numManifolds);
+
+
+ for (int i=0;i<numManifolds;i++)
+ {
+ int pa = manifoldPtr[i].m_bodyAPtrAndSignBit;
+ int pb = manifoldPtr[i].m_bodyBPtrAndSignBit;
+
+ bool isFixedA = (pa <0) || (pa == solverInfo.m_fixedBodyIndex);
+ bool isFixedB = (pb <0) || (pb == solverInfo.m_fixedBodyIndex);
+
+ int bodyIndexA = manifoldPtr[i].getBodyA();
+ int bodyIndexB = manifoldPtr[i].getBodyB();
+
+ if (!isFixedA)
+ {
+ contactConstraintOffsets[i].x = bodyCount[bodyIndexA];
+ bodyCount[bodyIndexA]++;
+ }
+ if (!isFixedB)
+ {
+ contactConstraintOffsets[i].y = bodyCount[bodyIndexB];
+ bodyCount[bodyIndexB]++;
+ }
+ }
+
+ b3AlignedObjectArray<unsigned int> offsetSplitBodies;
+ offsetSplitBodies.resize(numBodies);
+ unsigned int totalNumSplitBodies;
+ m_data->m_scan->executeHost(bodyCount,offsetSplitBodies,numBodies,&totalNumSplitBodies);
+ int numlastBody = bodyCount[numBodies-1];
+ totalNumSplitBodies += numlastBody;
+ printf("totalNumSplitBodies = %d\n",totalNumSplitBodies);
+
+
+
+
+
+ b3AlignedObjectArray<b3GpuConstraint4> contactConstraints;
+ contactConstraints.resize(numManifolds);
+
+ for (int i=0;i<numManifolds;i++)
+ {
+ ContactToConstraintKernel(&manifoldPtr[0],bodies,inertias,&contactConstraints[0],numManifolds,
+ solverInfo.m_deltaTime,
+ solverInfo.m_positionDrift,
+ solverInfo.m_positionConstraintCoeff,
+ i, bodyCount);
+ }
+ int maxIter = solverInfo.m_numIterations;
+
+
+ b3AlignedObjectArray<b3Vector3> deltaLinearVelocities;
+ b3AlignedObjectArray<b3Vector3> deltaAngularVelocities;
+ deltaLinearVelocities.resize(totalNumSplitBodies);
+ deltaAngularVelocities.resize(totalNumSplitBodies);
+ for (unsigned int i=0;i<totalNumSplitBodies;i++)
+ {
+ deltaLinearVelocities[i].setZero();
+ deltaAngularVelocities[i].setZero();
+ }
+
+
+
+ for (int iter = 0;iter<maxIter;iter++)
+ {
+ int i=0;
+ for( i=0; i<numManifolds; i++)
+ {
+
+ //float frictionCoeff = contactConstraints[i].getFrictionCoeff();
+ int aIdx = (int)contactConstraints[i].m_bodyA;
+ int bIdx = (int)contactConstraints[i].m_bodyB;
+ b3RigidBodyData& bodyA = bodies[aIdx];
+ b3RigidBodyData& bodyB = bodies[bIdx];
+
+ b3Vector3 zero = b3MakeVector3(0,0,0);
+
+ b3Vector3* dlvAPtr=&zero;
+ b3Vector3* davAPtr=&zero;
+ b3Vector3* dlvBPtr=&zero;
+ b3Vector3* davBPtr=&zero;
+
+ if (bodyA.m_invMass)
+ {
+ int bodyOffsetA = offsetSplitBodies[aIdx];
+ int constraintOffsetA = contactConstraintOffsets[i].x;
+ int splitIndexA = bodyOffsetA+constraintOffsetA;
+ dlvAPtr = &deltaLinearVelocities[splitIndexA];
+ davAPtr = &deltaAngularVelocities[splitIndexA];
+ }
+
+ if (bodyB.m_invMass)
+ {
+ int bodyOffsetB = offsetSplitBodies[bIdx];
+ int constraintOffsetB = contactConstraintOffsets[i].y;
+ int splitIndexB= bodyOffsetB+constraintOffsetB;
+ dlvBPtr =&deltaLinearVelocities[splitIndexB];
+ davBPtr = &deltaAngularVelocities[splitIndexB];
+ }
+
+
+
+ {
+ float maxRambdaDt[4] = {FLT_MAX,FLT_MAX,FLT_MAX,FLT_MAX};
+ float minRambdaDt[4] = {0.f,0.f,0.f,0.f};
+
+ solveContact( contactConstraints[i], (b3Vector3&)bodyA.m_pos, (b3Vector3&)bodyA.m_linVel, (b3Vector3&)bodyA.m_angVel, bodyA.m_invMass, inertias[aIdx].m_invInertiaWorld,
+ (b3Vector3&)bodyB.m_pos, (b3Vector3&)bodyB.m_linVel, (b3Vector3&)bodyB.m_angVel, bodyB.m_invMass, inertias[bIdx].m_invInertiaWorld,
+ maxRambdaDt, minRambdaDt , *dlvAPtr,*davAPtr,*dlvBPtr,*davBPtr );
+
+
+ }
+
+ }
+
+
+ //easy
+ for (int i=0;i<numBodies;i++)
+ {
+ if (bodies[i].m_invMass)
+ {
+ int bodyOffset = offsetSplitBodies[i];
+ int count = bodyCount[i];
+ float factor = 1.f/float(count);
+ b3Vector3 averageLinVel;
+ averageLinVel.setZero();
+ b3Vector3 averageAngVel;
+ averageAngVel.setZero();
+ for (int j=0;j<count;j++)
+ {
+ averageLinVel += deltaLinearVelocities[bodyOffset+j]*factor;
+ averageAngVel += deltaAngularVelocities[bodyOffset+j]*factor;
+ }
+ for (int j=0;j<count;j++)
+ {
+ deltaLinearVelocities[bodyOffset+j] = averageLinVel;
+ deltaAngularVelocities[bodyOffset+j] = averageAngVel;
+ }
+ }
+ }
+ }
+ for (int iter = 0;iter<maxIter;iter++)
+ {
+ //int i=0;
+
+ //solve friction
+
+ for(int i=0; i<numManifolds; i++)
+ {
+ float maxRambdaDt[4] = {FLT_MAX,FLT_MAX,FLT_MAX,FLT_MAX};
+ float minRambdaDt[4] = {0.f,0.f,0.f,0.f};
+
+ float sum = 0;
+ for(int j=0; j<4; j++)
+ {
+ sum +=contactConstraints[i].m_appliedRambdaDt[j];
+ }
+ float frictionCoeff = contactConstraints[i].getFrictionCoeff();
+ int aIdx = (int)contactConstraints[i].m_bodyA;
+ int bIdx = (int)contactConstraints[i].m_bodyB;
+ b3RigidBodyData& bodyA = bodies[aIdx];
+ b3RigidBodyData& bodyB = bodies[bIdx];
+
+ b3Vector3 zero = b3MakeVector3(0,0,0);
+
+ b3Vector3* dlvAPtr=&zero;
+ b3Vector3* davAPtr=&zero;
+ b3Vector3* dlvBPtr=&zero;
+ b3Vector3* davBPtr=&zero;
+
+ if (bodyA.m_invMass)
+ {
+ int bodyOffsetA = offsetSplitBodies[aIdx];
+ int constraintOffsetA = contactConstraintOffsets[i].x;
+ int splitIndexA = bodyOffsetA+constraintOffsetA;
+ dlvAPtr = &deltaLinearVelocities[splitIndexA];
+ davAPtr = &deltaAngularVelocities[splitIndexA];
+ }
+
+ if (bodyB.m_invMass)
+ {
+ int bodyOffsetB = offsetSplitBodies[bIdx];
+ int constraintOffsetB = contactConstraintOffsets[i].y;
+ int splitIndexB= bodyOffsetB+constraintOffsetB;
+ dlvBPtr =&deltaLinearVelocities[splitIndexB];
+ davBPtr = &deltaAngularVelocities[splitIndexB];
+ }
+
+ for(int j=0; j<4; j++)
+ {
+ maxRambdaDt[j] = frictionCoeff*sum;
+ minRambdaDt[j] = -maxRambdaDt[j];
+ }
+
+ solveFriction( contactConstraints[i], (b3Vector3&)bodyA.m_pos, (b3Vector3&)bodyA.m_linVel, (b3Vector3&)bodyA.m_angVel, bodyA.m_invMass,inertias[aIdx].m_invInertiaWorld,
+ (b3Vector3&)bodyB.m_pos, (b3Vector3&)bodyB.m_linVel, (b3Vector3&)bodyB.m_angVel, bodyB.m_invMass, inertias[bIdx].m_invInertiaWorld,
+ maxRambdaDt, minRambdaDt , *dlvAPtr,*davAPtr,*dlvBPtr,*davBPtr);
+
+ }
+
+ //easy
+ for (int i=0;i<numBodies;i++)
+ {
+ if (bodies[i].m_invMass)
+ {
+ int bodyOffset = offsetSplitBodies[i];
+ int count = bodyCount[i];
+ float factor = 1.f/float(count);
+ b3Vector3 averageLinVel;
+ averageLinVel.setZero();
+ b3Vector3 averageAngVel;
+ averageAngVel.setZero();
+ for (int j=0;j<count;j++)
+ {
+ averageLinVel += deltaLinearVelocities[bodyOffset+j]*factor;
+ averageAngVel += deltaAngularVelocities[bodyOffset+j]*factor;
+ }
+ for (int j=0;j<count;j++)
+ {
+ deltaLinearVelocities[bodyOffset+j] = averageLinVel;
+ deltaAngularVelocities[bodyOffset+j] = averageAngVel;
+ }
+ }
+ }
+
+
+
+ }
+
+
+ //easy
+ for (int i=0;i<numBodies;i++)
+ {
+ if (bodies[i].m_invMass)
+ {
+ int bodyOffset = offsetSplitBodies[i];
+ int count = bodyCount[i];
+ if (count)
+ {
+ bodies[i].m_linVel += deltaLinearVelocities[bodyOffset];
+ bodies[i].m_angVel += deltaAngularVelocities[bodyOffset];
+ }
+ }
+ }
+}
+
+
+
+void b3GpuJacobiContactSolver::solveContacts(int numBodies, cl_mem bodyBuf, cl_mem inertiaBuf, int numContacts, cl_mem contactBuf, const struct b3Config& config, int static0Index)
+//
+//
+//void b3GpuJacobiContactSolver::solveGroup(b3OpenCLArray<b3RigidBodyData>* bodies,b3OpenCLArray<b3InertiaData>* inertias,b3OpenCLArray<b3Contact4>* manifoldPtr,const btJacobiSolverInfo& solverInfo)
+{
+ b3JacobiSolverInfo solverInfo;
+ solverInfo.m_fixedBodyIndex = static0Index;
+
+
+ B3_PROFILE("b3GpuJacobiContactSolver::solveGroup");
+
+ //int numBodies = bodies->size();
+ int numManifolds = numContacts;//manifoldPtr->size();
+
+ {
+ B3_PROFILE("resize");
+ m_data->m_bodyCount->resize(numBodies);
+ }
+
+ unsigned int val=0;
+ b3Int2 val2;
+ val2.x=0;
+ val2.y=0;
+
+ {
+ B3_PROFILE("m_filler");
+ m_data->m_contactConstraintOffsets->resize(numManifolds);
+ m_data->m_filler->execute(*m_data->m_bodyCount,val,numBodies);
+
+
+ m_data->m_filler->execute(*m_data->m_contactConstraintOffsets,val2,numManifolds);
+ }
+
+ {
+ B3_PROFILE("m_countBodiesKernel");
+ b3LauncherCL launcher(this->m_queue,m_data->m_countBodiesKernel,"m_countBodiesKernel");
+ launcher.setBuffer(contactBuf);//manifoldPtr->getBufferCL());
+ launcher.setBuffer(m_data->m_bodyCount->getBufferCL());
+ launcher.setBuffer(m_data->m_contactConstraintOffsets->getBufferCL());
+ launcher.setConst(numManifolds);
+ launcher.setConst(solverInfo.m_fixedBodyIndex);
+ launcher.launch1D(numManifolds);
+ }
+ unsigned int totalNumSplitBodies=0;
+ {
+ B3_PROFILE("m_scan->execute");
+
+ m_data->m_offsetSplitBodies->resize(numBodies);
+ m_data->m_scan->execute(*m_data->m_bodyCount,*m_data->m_offsetSplitBodies,numBodies,&totalNumSplitBodies);
+ totalNumSplitBodies+=m_data->m_bodyCount->at(numBodies-1);
+ }
+
+ {
+ B3_PROFILE("m_data->m_contactConstraints->resize");
+ //int numContacts = manifoldPtr->size();
+ m_data->m_contactConstraints->resize(numContacts);
+ }
+
+ {
+ B3_PROFILE("contactToConstraintSplitKernel");
+ b3LauncherCL launcher( m_queue, m_data->m_contactToConstraintSplitKernel,"m_contactToConstraintSplitKernel");
+ launcher.setBuffer(contactBuf);
+ launcher.setBuffer(bodyBuf);
+ launcher.setBuffer(inertiaBuf);
+ launcher.setBuffer(m_data->m_contactConstraints->getBufferCL());
+ launcher.setBuffer(m_data->m_bodyCount->getBufferCL());
+ launcher.setConst(numContacts);
+ launcher.setConst(solverInfo.m_deltaTime);
+ launcher.setConst(solverInfo.m_positionDrift);
+ launcher.setConst(solverInfo.m_positionConstraintCoeff);
+ launcher.launch1D( numContacts, 64 );
+
+ }
+
+
+ {
+ B3_PROFILE("m_data->m_deltaLinearVelocities->resize");
+ m_data->m_deltaLinearVelocities->resize(totalNumSplitBodies);
+ m_data->m_deltaAngularVelocities->resize(totalNumSplitBodies);
+ }
+
+
+
+ {
+ B3_PROFILE("m_clearVelocitiesKernel");
+ b3LauncherCL launch(m_queue,m_data->m_clearVelocitiesKernel,"m_clearVelocitiesKernel");
+ launch.setBuffer(m_data->m_deltaAngularVelocities->getBufferCL());
+ launch.setBuffer(m_data->m_deltaLinearVelocities->getBufferCL());
+ launch.setConst(totalNumSplitBodies);
+ launch.launch1D(totalNumSplitBodies);
+ clFinish(m_queue);
+ }
+
+
+ int maxIter = solverInfo.m_numIterations;
+
+ for (int iter = 0;iter<maxIter;iter++)
+ {
+ {
+ B3_PROFILE("m_solveContactKernel");
+ b3LauncherCL launcher( m_queue, m_data->m_solveContactKernel,"m_solveContactKernel" );
+ launcher.setBuffer(m_data->m_contactConstraints->getBufferCL());
+ launcher.setBuffer(bodyBuf);
+ launcher.setBuffer(inertiaBuf);
+ launcher.setBuffer(m_data->m_contactConstraintOffsets->getBufferCL());
+ launcher.setBuffer(m_data->m_offsetSplitBodies->getBufferCL());
+ launcher.setBuffer(m_data->m_deltaLinearVelocities->getBufferCL());
+ launcher.setBuffer(m_data->m_deltaAngularVelocities->getBufferCL());
+ launcher.setConst(solverInfo.m_deltaTime);
+ launcher.setConst(solverInfo.m_positionDrift);
+ launcher.setConst(solverInfo.m_positionConstraintCoeff);
+ launcher.setConst(solverInfo.m_fixedBodyIndex);
+ launcher.setConst(numManifolds);
+
+ launcher.launch1D(numManifolds);
+ clFinish(m_queue);
+ }
+
+
+
+ {
+ B3_PROFILE("average velocities");
+ b3LauncherCL launcher( m_queue, m_data->m_averageVelocitiesKernel,"m_averageVelocitiesKernel");
+ launcher.setBuffer(bodyBuf);
+ launcher.setBuffer(m_data->m_offsetSplitBodies->getBufferCL());
+ launcher.setBuffer(m_data->m_bodyCount->getBufferCL());
+ launcher.setBuffer(m_data->m_deltaLinearVelocities->getBufferCL());
+ launcher.setBuffer(m_data->m_deltaAngularVelocities->getBufferCL());
+ launcher.setConst(numBodies);
+ launcher.launch1D(numBodies);
+ clFinish(m_queue);
+ }
+
+
+ {
+ B3_PROFILE("m_solveFrictionKernel");
+ b3LauncherCL launcher( m_queue, m_data->m_solveFrictionKernel,"m_solveFrictionKernel");
+ launcher.setBuffer(m_data->m_contactConstraints->getBufferCL());
+ launcher.setBuffer(bodyBuf);
+ launcher.setBuffer(inertiaBuf);
+ launcher.setBuffer(m_data->m_contactConstraintOffsets->getBufferCL());
+ launcher.setBuffer(m_data->m_offsetSplitBodies->getBufferCL());
+ launcher.setBuffer(m_data->m_deltaLinearVelocities->getBufferCL());
+ launcher.setBuffer(m_data->m_deltaAngularVelocities->getBufferCL());
+ launcher.setConst(solverInfo.m_deltaTime);
+ launcher.setConst(solverInfo.m_positionDrift);
+ launcher.setConst(solverInfo.m_positionConstraintCoeff);
+ launcher.setConst(solverInfo.m_fixedBodyIndex);
+ launcher.setConst(numManifolds);
+
+ launcher.launch1D(numManifolds);
+ clFinish(m_queue);
+ }
+
+
+ {
+ B3_PROFILE("average velocities");
+ b3LauncherCL launcher( m_queue, m_data->m_averageVelocitiesKernel,"m_averageVelocitiesKernel");
+ launcher.setBuffer(bodyBuf);
+ launcher.setBuffer(m_data->m_offsetSplitBodies->getBufferCL());
+ launcher.setBuffer(m_data->m_bodyCount->getBufferCL());
+ launcher.setBuffer(m_data->m_deltaLinearVelocities->getBufferCL());
+ launcher.setBuffer(m_data->m_deltaAngularVelocities->getBufferCL());
+ launcher.setConst(numBodies);
+ launcher.launch1D(numBodies);
+ clFinish(m_queue);
+ }
+
+
+
+ }
+
+
+ {
+ B3_PROFILE("update body velocities");
+ b3LauncherCL launcher( m_queue, m_data->m_updateBodyVelocitiesKernel,"m_updateBodyVelocitiesKernel");
+ launcher.setBuffer(bodyBuf);
+ launcher.setBuffer(m_data->m_offsetSplitBodies->getBufferCL());
+ launcher.setBuffer(m_data->m_bodyCount->getBufferCL());
+ launcher.setBuffer(m_data->m_deltaLinearVelocities->getBufferCL());
+ launcher.setBuffer(m_data->m_deltaAngularVelocities->getBufferCL());
+ launcher.setConst(numBodies);
+ launcher.launch1D(numBodies);
+ clFinish(m_queue);
+ }
+
+
+
+}
+
+#if 0
+
+void b3GpuJacobiContactSolver::solveGroupMixed(b3OpenCLArray<b3RigidBodyData>* bodiesGPU,b3OpenCLArray<b3InertiaData>* inertiasGPU,b3OpenCLArray<b3Contact4>* manifoldPtrGPU,const btJacobiSolverInfo& solverInfo)
+{
+
+ b3AlignedObjectArray<b3RigidBodyData> bodiesCPU;
+ bodiesGPU->copyToHost(bodiesCPU);
+ b3AlignedObjectArray<b3InertiaData> inertiasCPU;
+ inertiasGPU->copyToHost(inertiasCPU);
+ b3AlignedObjectArray<b3Contact4> manifoldPtrCPU;
+ manifoldPtrGPU->copyToHost(manifoldPtrCPU);
+
+ int numBodiesCPU = bodiesGPU->size();
+ int numManifoldsCPU = manifoldPtrGPU->size();
+ B3_PROFILE("b3GpuJacobiContactSolver::solveGroupMixed");
+
+ b3AlignedObjectArray<unsigned int> bodyCount;
+ bodyCount.resize(numBodiesCPU);
+ for (int i=0;i<numBodiesCPU;i++)
+ bodyCount[i] = 0;
+
+ b3AlignedObjectArray<b3Int2> contactConstraintOffsets;
+ contactConstraintOffsets.resize(numManifoldsCPU);
+
+
+ for (int i=0;i<numManifoldsCPU;i++)
+ {
+ int pa = manifoldPtrCPU[i].m_bodyAPtrAndSignBit;
+ int pb = manifoldPtrCPU[i].m_bodyBPtrAndSignBit;
+
+ bool isFixedA = (pa <0) || (pa == solverInfo.m_fixedBodyIndex);
+ bool isFixedB = (pb <0) || (pb == solverInfo.m_fixedBodyIndex);
+
+ int bodyIndexA = manifoldPtrCPU[i].getBodyA();
+ int bodyIndexB = manifoldPtrCPU[i].getBodyB();
+
+ if (!isFixedA)
+ {
+ contactConstraintOffsets[i].x = bodyCount[bodyIndexA];
+ bodyCount[bodyIndexA]++;
+ }
+ if (!isFixedB)
+ {
+ contactConstraintOffsets[i].y = bodyCount[bodyIndexB];
+ bodyCount[bodyIndexB]++;
+ }
+ }
+
+ b3AlignedObjectArray<unsigned int> offsetSplitBodies;
+ offsetSplitBodies.resize(numBodiesCPU);
+ unsigned int totalNumSplitBodiesCPU;
+ m_data->m_scan->executeHost(bodyCount,offsetSplitBodies,numBodiesCPU,&totalNumSplitBodiesCPU);
+ int numlastBody = bodyCount[numBodiesCPU-1];
+ totalNumSplitBodiesCPU += numlastBody;
+
+ int numBodies = bodiesGPU->size();
+ int numManifolds = manifoldPtrGPU->size();
+
+ m_data->m_bodyCount->resize(numBodies);
+
+ unsigned int val=0;
+ b3Int2 val2;
+ val2.x=0;
+ val2.y=0;
+
+ {
+ B3_PROFILE("m_filler");
+ m_data->m_contactConstraintOffsets->resize(numManifolds);
+ m_data->m_filler->execute(*m_data->m_bodyCount,val,numBodies);
+
+
+ m_data->m_filler->execute(*m_data->m_contactConstraintOffsets,val2,numManifolds);
+ }
+
+ {
+ B3_PROFILE("m_countBodiesKernel");
+ b3LauncherCL launcher(this->m_queue,m_data->m_countBodiesKernel);
+ launcher.setBuffer(manifoldPtrGPU->getBufferCL());
+ launcher.setBuffer(m_data->m_bodyCount->getBufferCL());
+ launcher.setBuffer(m_data->m_contactConstraintOffsets->getBufferCL());
+ launcher.setConst(numManifolds);
+ launcher.setConst(solverInfo.m_fixedBodyIndex);
+ launcher.launch1D(numManifolds);
+ }
+
+ unsigned int totalNumSplitBodies=0;
+ m_data->m_offsetSplitBodies->resize(numBodies);
+ m_data->m_scan->execute(*m_data->m_bodyCount,*m_data->m_offsetSplitBodies,numBodies,&totalNumSplitBodies);
+ totalNumSplitBodies+=m_data->m_bodyCount->at(numBodies-1);
+
+ if (totalNumSplitBodies != totalNumSplitBodiesCPU)
+ {
+ printf("error in totalNumSplitBodies!\n");
+ }
+
+ int numContacts = manifoldPtrGPU->size();
+ m_data->m_contactConstraints->resize(numContacts);
+
+
+ {
+ B3_PROFILE("contactToConstraintSplitKernel");
+ b3LauncherCL launcher( m_queue, m_data->m_contactToConstraintSplitKernel);
+ launcher.setBuffer(manifoldPtrGPU->getBufferCL());
+ launcher.setBuffer(bodiesGPU->getBufferCL());
+ launcher.setBuffer(inertiasGPU->getBufferCL());
+ launcher.setBuffer(m_data->m_contactConstraints->getBufferCL());
+ launcher.setBuffer(m_data->m_bodyCount->getBufferCL());
+ launcher.setConst(numContacts);
+ launcher.setConst(solverInfo.m_deltaTime);
+ launcher.setConst(solverInfo.m_positionDrift);
+ launcher.setConst(solverInfo.m_positionConstraintCoeff);
+ launcher.launch1D( numContacts, 64 );
+ clFinish(m_queue);
+ }
+
+
+
+ b3AlignedObjectArray<b3GpuConstraint4> contactConstraints;
+ contactConstraints.resize(numManifoldsCPU);
+
+ for (int i=0;i<numManifoldsCPU;i++)
+ {
+ ContactToConstraintKernel(&manifoldPtrCPU[0],&bodiesCPU[0],&inertiasCPU[0],&contactConstraints[0],numManifoldsCPU,
+ solverInfo.m_deltaTime,
+ solverInfo.m_positionDrift,
+ solverInfo.m_positionConstraintCoeff,
+ i, bodyCount);
+ }
+ int maxIter = solverInfo.m_numIterations;
+
+
+ b3AlignedObjectArray<b3Vector3> deltaLinearVelocities;
+ b3AlignedObjectArray<b3Vector3> deltaAngularVelocities;
+ deltaLinearVelocities.resize(totalNumSplitBodiesCPU);
+ deltaAngularVelocities.resize(totalNumSplitBodiesCPU);
+ for (int i=0;i<totalNumSplitBodiesCPU;i++)
+ {
+ deltaLinearVelocities[i].setZero();
+ deltaAngularVelocities[i].setZero();
+ }
+
+ m_data->m_deltaLinearVelocities->resize(totalNumSplitBodies);
+ m_data->m_deltaAngularVelocities->resize(totalNumSplitBodies);
+
+
+
+ {
+ B3_PROFILE("m_clearVelocitiesKernel");
+ b3LauncherCL launch(m_queue,m_data->m_clearVelocitiesKernel);
+ launch.setBuffer(m_data->m_deltaAngularVelocities->getBufferCL());
+ launch.setBuffer(m_data->m_deltaLinearVelocities->getBufferCL());
+ launch.setConst(totalNumSplitBodies);
+ launch.launch1D(totalNumSplitBodies);
+ }
+
+
+ ///!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+
+ m_data->m_contactConstraints->copyToHost(contactConstraints);
+ m_data->m_offsetSplitBodies->copyToHost(offsetSplitBodies);
+ m_data->m_contactConstraintOffsets->copyToHost(contactConstraintOffsets);
+ m_data->m_deltaLinearVelocities->copyToHost(deltaLinearVelocities);
+ m_data->m_deltaAngularVelocities->copyToHost(deltaAngularVelocities);
+
+ for (int iter = 0;iter<maxIter;iter++)
+ {
+
+ {
+ B3_PROFILE("m_solveContactKernel");
+ b3LauncherCL launcher( m_queue, m_data->m_solveContactKernel );
+ launcher.setBuffer(m_data->m_contactConstraints->getBufferCL());
+ launcher.setBuffer(bodiesGPU->getBufferCL());
+ launcher.setBuffer(inertiasGPU->getBufferCL());
+ launcher.setBuffer(m_data->m_contactConstraintOffsets->getBufferCL());
+ launcher.setBuffer(m_data->m_offsetSplitBodies->getBufferCL());
+ launcher.setBuffer(m_data->m_deltaLinearVelocities->getBufferCL());
+ launcher.setBuffer(m_data->m_deltaAngularVelocities->getBufferCL());
+ launcher.setConst(solverInfo.m_deltaTime);
+ launcher.setConst(solverInfo.m_positionDrift);
+ launcher.setConst(solverInfo.m_positionConstraintCoeff);
+ launcher.setConst(solverInfo.m_fixedBodyIndex);
+ launcher.setConst(numManifolds);
+
+ launcher.launch1D(numManifolds);
+ clFinish(m_queue);
+ }
+
+
+ int i=0;
+ for( i=0; i<numManifoldsCPU; i++)
+ {
+
+ float frictionCoeff = contactConstraints[i].getFrictionCoeff();
+ int aIdx = (int)contactConstraints[i].m_bodyA;
+ int bIdx = (int)contactConstraints[i].m_bodyB;
+ b3RigidBodyData& bodyA = bodiesCPU[aIdx];
+ b3RigidBodyData& bodyB = bodiesCPU[bIdx];
+
+ b3Vector3 zero(0,0,0);
+
+ b3Vector3* dlvAPtr=&zero;
+ b3Vector3* davAPtr=&zero;
+ b3Vector3* dlvBPtr=&zero;
+ b3Vector3* davBPtr=&zero;
+
+ if (bodyA.m_invMass)
+ {
+ int bodyOffsetA = offsetSplitBodies[aIdx];
+ int constraintOffsetA = contactConstraintOffsets[i].x;
+ int splitIndexA = bodyOffsetA+constraintOffsetA;
+ dlvAPtr = &deltaLinearVelocities[splitIndexA];
+ davAPtr = &deltaAngularVelocities[splitIndexA];
+ }
+
+ if (bodyB.m_invMass)
+ {
+ int bodyOffsetB = offsetSplitBodies[bIdx];
+ int constraintOffsetB = contactConstraintOffsets[i].y;
+ int splitIndexB= bodyOffsetB+constraintOffsetB;
+ dlvBPtr =&deltaLinearVelocities[splitIndexB];
+ davBPtr = &deltaAngularVelocities[splitIndexB];
+ }
+
+
+
+ {
+ float maxRambdaDt[4] = {FLT_MAX,FLT_MAX,FLT_MAX,FLT_MAX};
+ float minRambdaDt[4] = {0.f,0.f,0.f,0.f};
+
+ solveContact( contactConstraints[i], (b3Vector3&)bodyA.m_pos, (b3Vector3&)bodyA.m_linVel, (b3Vector3&)bodyA.m_angVel, bodyA.m_invMass, inertiasCPU[aIdx].m_invInertiaWorld,
+ (b3Vector3&)bodyB.m_pos, (b3Vector3&)bodyB.m_linVel, (b3Vector3&)bodyB.m_angVel, bodyB.m_invMass, inertiasCPU[bIdx].m_invInertiaWorld,
+ maxRambdaDt, minRambdaDt , *dlvAPtr,*davAPtr,*dlvBPtr,*davBPtr );
+
+
+ }
+ }
+
+
+ {
+ B3_PROFILE("average velocities");
+ b3LauncherCL launcher( m_queue, m_data->m_averageVelocitiesKernel);
+ launcher.setBuffer(bodiesGPU->getBufferCL());
+ launcher.setBuffer(m_data->m_offsetSplitBodies->getBufferCL());
+ launcher.setBuffer(m_data->m_bodyCount->getBufferCL());
+ launcher.setBuffer(m_data->m_deltaLinearVelocities->getBufferCL());
+ launcher.setBuffer(m_data->m_deltaAngularVelocities->getBufferCL());
+ launcher.setConst(numBodies);
+ launcher.launch1D(numBodies);
+ clFinish(m_queue);
+ }
+
+ //easy
+ for (int i=0;i<numBodiesCPU;i++)
+ {
+ if (bodiesCPU[i].m_invMass)
+ {
+ int bodyOffset = offsetSplitBodies[i];
+ int count = bodyCount[i];
+ float factor = 1.f/float(count);
+ b3Vector3 averageLinVel;
+ averageLinVel.setZero();
+ b3Vector3 averageAngVel;
+ averageAngVel.setZero();
+ for (int j=0;j<count;j++)
+ {
+ averageLinVel += deltaLinearVelocities[bodyOffset+j]*factor;
+ averageAngVel += deltaAngularVelocities[bodyOffset+j]*factor;
+ }
+ for (int j=0;j<count;j++)
+ {
+ deltaLinearVelocities[bodyOffset+j] = averageLinVel;
+ deltaAngularVelocities[bodyOffset+j] = averageAngVel;
+ }
+ }
+ }
+// m_data->m_deltaAngularVelocities->copyFromHost(deltaAngularVelocities);
+ //m_data->m_deltaLinearVelocities->copyFromHost(deltaLinearVelocities);
+ m_data->m_deltaAngularVelocities->copyToHost(deltaAngularVelocities);
+ m_data->m_deltaLinearVelocities->copyToHost(deltaLinearVelocities);
+
+#if 0
+
+ {
+ B3_PROFILE("m_solveFrictionKernel");
+ b3LauncherCL launcher( m_queue, m_data->m_solveFrictionKernel);
+ launcher.setBuffer(m_data->m_contactConstraints->getBufferCL());
+ launcher.setBuffer(bodiesGPU->getBufferCL());
+ launcher.setBuffer(inertiasGPU->getBufferCL());
+ launcher.setBuffer(m_data->m_contactConstraintOffsets->getBufferCL());
+ launcher.setBuffer(m_data->m_offsetSplitBodies->getBufferCL());
+ launcher.setBuffer(m_data->m_deltaLinearVelocities->getBufferCL());
+ launcher.setBuffer(m_data->m_deltaAngularVelocities->getBufferCL());
+ launcher.setConst(solverInfo.m_deltaTime);
+ launcher.setConst(solverInfo.m_positionDrift);
+ launcher.setConst(solverInfo.m_positionConstraintCoeff);
+ launcher.setConst(solverInfo.m_fixedBodyIndex);
+ launcher.setConst(numManifolds);
+
+ launcher.launch1D(numManifolds);
+ clFinish(m_queue);
+ }
+
+ //solve friction
+
+ for(int i=0; i<numManifoldsCPU; i++)
+ {
+ float maxRambdaDt[4] = {FLT_MAX,FLT_MAX,FLT_MAX,FLT_MAX};
+ float minRambdaDt[4] = {0.f,0.f,0.f,0.f};
+
+ float sum = 0;
+ for(int j=0; j<4; j++)
+ {
+ sum +=contactConstraints[i].m_appliedRambdaDt[j];
+ }
+ float frictionCoeff = contactConstraints[i].getFrictionCoeff();
+ int aIdx = (int)contactConstraints[i].m_bodyA;
+ int bIdx = (int)contactConstraints[i].m_bodyB;
+ b3RigidBodyData& bodyA = bodiesCPU[aIdx];
+ b3RigidBodyData& bodyB = bodiesCPU[bIdx];
+
+ b3Vector3 zero(0,0,0);
+
+ b3Vector3* dlvAPtr=&zero;
+ b3Vector3* davAPtr=&zero;
+ b3Vector3* dlvBPtr=&zero;
+ b3Vector3* davBPtr=&zero;
+
+ if (bodyA.m_invMass)
+ {
+ int bodyOffsetA = offsetSplitBodies[aIdx];
+ int constraintOffsetA = contactConstraintOffsets[i].x;
+ int splitIndexA = bodyOffsetA+constraintOffsetA;
+ dlvAPtr = &deltaLinearVelocities[splitIndexA];
+ davAPtr = &deltaAngularVelocities[splitIndexA];
+ }
+
+ if (bodyB.m_invMass)
+ {
+ int bodyOffsetB = offsetSplitBodies[bIdx];
+ int constraintOffsetB = contactConstraintOffsets[i].y;
+ int splitIndexB= bodyOffsetB+constraintOffsetB;
+ dlvBPtr =&deltaLinearVelocities[splitIndexB];
+ davBPtr = &deltaAngularVelocities[splitIndexB];
+ }
+
+ for(int j=0; j<4; j++)
+ {
+ maxRambdaDt[j] = frictionCoeff*sum;
+ minRambdaDt[j] = -maxRambdaDt[j];
+ }
+
+ solveFriction( contactConstraints[i], (b3Vector3&)bodyA.m_pos, (b3Vector3&)bodyA.m_linVel, (b3Vector3&)bodyA.m_angVel, bodyA.m_invMass,inertiasCPU[aIdx].m_invInertiaWorld,
+ (b3Vector3&)bodyB.m_pos, (b3Vector3&)bodyB.m_linVel, (b3Vector3&)bodyB.m_angVel, bodyB.m_invMass, inertiasCPU[bIdx].m_invInertiaWorld,
+ maxRambdaDt, minRambdaDt , *dlvAPtr,*davAPtr,*dlvBPtr,*davBPtr);
+
+ }
+
+ {
+ B3_PROFILE("average velocities");
+ b3LauncherCL launcher( m_queue, m_data->m_averageVelocitiesKernel);
+ launcher.setBuffer(bodiesGPU->getBufferCL());
+ launcher.setBuffer(m_data->m_offsetSplitBodies->getBufferCL());
+ launcher.setBuffer(m_data->m_bodyCount->getBufferCL());
+ launcher.setBuffer(m_data->m_deltaLinearVelocities->getBufferCL());
+ launcher.setBuffer(m_data->m_deltaAngularVelocities->getBufferCL());
+ launcher.setConst(numBodies);
+ launcher.launch1D(numBodies);
+ clFinish(m_queue);
+ }
+
+ //easy
+ for (int i=0;i<numBodiesCPU;i++)
+ {
+ if (bodiesCPU[i].m_invMass)
+ {
+ int bodyOffset = offsetSplitBodies[i];
+ int count = bodyCount[i];
+ float factor = 1.f/float(count);
+ b3Vector3 averageLinVel;
+ averageLinVel.setZero();
+ b3Vector3 averageAngVel;
+ averageAngVel.setZero();
+ for (int j=0;j<count;j++)
+ {
+ averageLinVel += deltaLinearVelocities[bodyOffset+j]*factor;
+ averageAngVel += deltaAngularVelocities[bodyOffset+j]*factor;
+ }
+ for (int j=0;j<count;j++)
+ {
+ deltaLinearVelocities[bodyOffset+j] = averageLinVel;
+ deltaAngularVelocities[bodyOffset+j] = averageAngVel;
+ }
+ }
+ }
+
+#endif
+
+ }
+
+ {
+ B3_PROFILE("update body velocities");
+ b3LauncherCL launcher( m_queue, m_data->m_updateBodyVelocitiesKernel);
+ launcher.setBuffer(bodiesGPU->getBufferCL());
+ launcher.setBuffer(m_data->m_offsetSplitBodies->getBufferCL());
+ launcher.setBuffer(m_data->m_bodyCount->getBufferCL());
+ launcher.setBuffer(m_data->m_deltaLinearVelocities->getBufferCL());
+ launcher.setBuffer(m_data->m_deltaAngularVelocities->getBufferCL());
+ launcher.setConst(numBodies);
+ launcher.launch1D(numBodies);
+ clFinish(m_queue);
+ }
+
+
+ //easy
+ for (int i=0;i<numBodiesCPU;i++)
+ {
+ if (bodiesCPU[i].m_invMass)
+ {
+ int bodyOffset = offsetSplitBodies[i];
+ int count = bodyCount[i];
+ if (count)
+ {
+ bodiesCPU[i].m_linVel += deltaLinearVelocities[bodyOffset];
+ bodiesCPU[i].m_angVel += deltaAngularVelocities[bodyOffset];
+ }
+ }
+ }
+
+
+// bodiesGPU->copyFromHost(bodiesCPU);
+
+
+}
+#endif
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuJacobiContactSolver.h b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuJacobiContactSolver.h
new file mode 100644
index 0000000000..b418f29ec4
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuJacobiContactSolver.h
@@ -0,0 +1,62 @@
+
+#ifndef B3_GPU_JACOBI_CONTACT_SOLVER_H
+#define B3_GPU_JACOBI_CONTACT_SOLVER_H
+#include "Bullet3OpenCL/Initialize/b3OpenCLInclude.h"
+//#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
+
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h"
+#include "Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h"
+
+
+//struct b3InertiaData;
+//b3InertiaData
+
+class b3TypedConstraint;
+
+struct b3JacobiSolverInfo
+{
+ int m_fixedBodyIndex;
+
+ float m_deltaTime;
+ float m_positionDrift;
+ float m_positionConstraintCoeff;
+ int m_numIterations;
+
+ b3JacobiSolverInfo()
+ :m_fixedBodyIndex(0),
+ m_deltaTime(1./60.f),
+ m_positionDrift( 0.005f ),
+ m_positionConstraintCoeff( 0.99f ),
+ m_numIterations(7)
+ {
+ }
+};
+class b3GpuJacobiContactSolver
+{
+protected:
+
+ struct b3GpuJacobiSolverInternalData* m_data;
+
+ cl_context m_context;
+ cl_device_id m_device;
+ cl_command_queue m_queue;
+
+public:
+
+ b3GpuJacobiContactSolver(cl_context ctx, cl_device_id device, cl_command_queue queue, int pairCapacity);
+ virtual ~b3GpuJacobiContactSolver();
+
+
+ void solveContacts(int numBodies, cl_mem bodyBuf, cl_mem inertiaBuf, int numContacts, cl_mem contactBuf, const struct b3Config& config, int static0Index);
+ void solveGroupHost(b3RigidBodyData* bodies,b3InertiaData* inertias,int numBodies,struct b3Contact4* manifoldPtr, int numManifolds,const b3JacobiSolverInfo& solverInfo);
+ //void solveGroupHost(btRigidBodyCL* bodies,b3InertiaData* inertias,int numBodies,btContact4* manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btJacobiSolverInfo& solverInfo);
+
+ //b3Scalar solveGroup(b3OpenCLArray<b3RigidBodyData>* gpuBodies,b3OpenCLArray<b3InertiaData>* gpuInertias, int numBodies,b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints,int numConstraints,const b3ContactSolverInfo& infoGlobal);
+
+ //void solveGroup(btOpenCLArray<btRigidBodyCL>* bodies,btOpenCLArray<btInertiaCL>* inertias,btOpenCLArray<btContact4>* manifoldPtr,const btJacobiSolverInfo& solverInfo);
+ //void solveGroupMixed(btOpenCLArray<btRigidBodyCL>* bodies,btOpenCLArray<btInertiaCL>* inertias,btOpenCLArray<btContact4>* manifoldPtr,const btJacobiSolverInfo& solverInfo);
+
+};
+#endif //B3_GPU_JACOBI_CONTACT_SOLVER_H
+
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuNarrowPhase.cpp b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuNarrowPhase.cpp
new file mode 100644
index 0000000000..698fa15f96
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuNarrowPhase.cpp
@@ -0,0 +1,1107 @@
+#include "b3GpuNarrowPhase.h"
+
+
+#include "Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h"
+#include "Bullet3OpenCL/NarrowphaseCollision/b3ConvexHullContact.h"
+#include "Bullet3OpenCL/BroadphaseCollision/b3SapAabb.h"
+#include <string.h>
+#include "Bullet3Collision/NarrowPhaseCollision/b3Config.h"
+#include "Bullet3OpenCL/NarrowphaseCollision/b3OptimizedBvh.h"
+#include "Bullet3OpenCL/NarrowphaseCollision/b3TriangleIndexVertexArray.h"
+#include "Bullet3Geometry/b3AabbUtil.h"
+#include "Bullet3OpenCL/NarrowphaseCollision/b3BvhInfo.h"
+
+#include "b3GpuNarrowPhaseInternalData.h"
+#include "Bullet3OpenCL/NarrowphaseCollision/b3QuantizedBvh.h"
+#include "Bullet3Collision/NarrowPhaseCollision/b3ConvexUtility.h"
+
+
+
+
+b3GpuNarrowPhase::b3GpuNarrowPhase(cl_context ctx, cl_device_id device, cl_command_queue queue, const b3Config& config)
+:m_data(0) ,m_planeBodyIndex(-1),m_static0Index(-1),
+m_context(ctx),
+m_device(device),
+m_queue(queue)
+{
+
+ m_data = new b3GpuNarrowPhaseInternalData();
+ m_data->m_currentContactBuffer = 0;
+
+ memset(m_data,0,sizeof(b3GpuNarrowPhaseInternalData));
+
+
+ m_data->m_config = config;
+
+ m_data->m_gpuSatCollision = new GpuSatCollision(ctx,device,queue);
+
+
+ m_data->m_triangleConvexPairs = new b3OpenCLArray<b3Int4>(m_context,m_queue, config.m_maxTriConvexPairCapacity);
+
+
+ //m_data->m_convexPairsOutGPU = new b3OpenCLArray<b3Int2>(ctx,queue,config.m_maxBroadphasePairs,false);
+ //m_data->m_planePairs = new b3OpenCLArray<b3Int2>(ctx,queue,config.m_maxBroadphasePairs,false);
+
+ m_data->m_pBufContactOutCPU = new b3AlignedObjectArray<b3Contact4>();
+ m_data->m_pBufContactOutCPU->resize(config.m_maxBroadphasePairs);
+ m_data->m_bodyBufferCPU = new b3AlignedObjectArray<b3RigidBodyData>();
+ m_data->m_bodyBufferCPU->resize(config.m_maxConvexBodies);
+
+ m_data->m_inertiaBufferCPU = new b3AlignedObjectArray<b3InertiaData>();
+ m_data->m_inertiaBufferCPU->resize(config.m_maxConvexBodies);
+
+ m_data->m_pBufContactBuffersGPU[0] = new b3OpenCLArray<b3Contact4>(ctx,queue, config.m_maxContactCapacity,true);
+ m_data->m_pBufContactBuffersGPU[1] = new b3OpenCLArray<b3Contact4>(ctx,queue, config.m_maxContactCapacity,true);
+
+ m_data->m_inertiaBufferGPU = new b3OpenCLArray<b3InertiaData>(ctx,queue,config.m_maxConvexBodies,false);
+ m_data->m_collidablesGPU = new b3OpenCLArray<b3Collidable>(ctx,queue,config.m_maxConvexShapes);
+ m_data->m_collidablesCPU.reserve(config.m_maxConvexShapes);
+
+ m_data->m_localShapeAABBCPU = new b3AlignedObjectArray<b3SapAabb>;
+ m_data->m_localShapeAABBGPU = new b3OpenCLArray<b3SapAabb>(ctx,queue,config.m_maxConvexShapes);
+
+
+ //m_data->m_solverDataGPU = adl::Solver<adl::TYPE_CL>::allocate(ctx,queue, config.m_maxBroadphasePairs,false);
+ m_data->m_bodyBufferGPU = new b3OpenCLArray<b3RigidBodyData>(ctx,queue, config.m_maxConvexBodies,false);
+
+ m_data->m_convexFacesGPU = new b3OpenCLArray<b3GpuFace>(ctx,queue,config.m_maxConvexShapes*config.m_maxFacesPerShape,false);
+ m_data->m_convexFaces.reserve(config.m_maxConvexShapes*config.m_maxFacesPerShape);
+
+ m_data->m_gpuChildShapes = new b3OpenCLArray<b3GpuChildShape>(ctx,queue,config.m_maxCompoundChildShapes,false);
+
+ m_data->m_convexPolyhedraGPU = new b3OpenCLArray<b3ConvexPolyhedronData>(ctx,queue,config.m_maxConvexShapes,false);
+ m_data->m_convexPolyhedra.reserve(config.m_maxConvexShapes);
+
+ m_data->m_uniqueEdgesGPU = new b3OpenCLArray<b3Vector3>(ctx,queue,config.m_maxConvexUniqueEdges,true);
+ m_data->m_uniqueEdges.reserve(config.m_maxConvexUniqueEdges);
+
+
+
+ m_data->m_convexVerticesGPU = new b3OpenCLArray<b3Vector3>(ctx,queue,config.m_maxConvexVertices,true);
+ m_data->m_convexVertices.reserve(config.m_maxConvexVertices);
+
+ m_data->m_convexIndicesGPU = new b3OpenCLArray<int>(ctx,queue,config.m_maxConvexIndices,true);
+ m_data->m_convexIndices.reserve(config.m_maxConvexIndices);
+
+ m_data->m_worldVertsB1GPU = new b3OpenCLArray<b3Vector3>(ctx,queue,config.m_maxConvexBodies*config.m_maxVerticesPerFace);
+ m_data->m_clippingFacesOutGPU = new b3OpenCLArray<b3Int4>(ctx,queue,config.m_maxConvexBodies);
+ m_data->m_worldNormalsAGPU = new b3OpenCLArray<b3Vector3>(ctx,queue,config.m_maxConvexBodies);
+ m_data->m_worldVertsA1GPU = new b3OpenCLArray<b3Vector3>(ctx,queue,config.m_maxConvexBodies*config.m_maxVerticesPerFace);
+ m_data->m_worldVertsB2GPU = new b3OpenCLArray<b3Vector3>(ctx,queue,config.m_maxConvexBodies*config.m_maxVerticesPerFace);
+
+
+
+ m_data->m_convexData = new b3AlignedObjectArray<b3ConvexUtility* >();
+
+ m_data->m_convexData->resize(config.m_maxConvexShapes);
+ m_data->m_convexPolyhedra.resize(config.m_maxConvexShapes);
+
+ m_data->m_numAcceleratedShapes = 0;
+ m_data->m_numAcceleratedRigidBodies = 0;
+
+
+ m_data->m_subTreesGPU = new b3OpenCLArray<b3BvhSubtreeInfo>(this->m_context,this->m_queue);
+ m_data->m_treeNodesGPU = new b3OpenCLArray<b3QuantizedBvhNode>(this->m_context,this->m_queue);
+ m_data->m_bvhInfoGPU = new b3OpenCLArray<b3BvhInfo>(this->m_context,this->m_queue);
+
+ //m_data->m_contactCGPU = new b3OpenCLArray<Constraint4>(ctx,queue,config.m_maxBroadphasePairs,false);
+ //m_data->m_frictionCGPU = new b3OpenCLArray<adl::Solver<adl::TYPE_CL>::allocateFrictionConstraint( m_data->m_deviceCL, config.m_maxBroadphasePairs);
+
+
+
+}
+
+
+b3GpuNarrowPhase::~b3GpuNarrowPhase()
+{
+ delete m_data->m_gpuSatCollision;
+
+ delete m_data->m_triangleConvexPairs;
+ //delete m_data->m_convexPairsOutGPU;
+ //delete m_data->m_planePairs;
+ delete m_data->m_pBufContactOutCPU;
+ delete m_data->m_bodyBufferCPU;
+ delete m_data->m_inertiaBufferCPU;
+ delete m_data->m_pBufContactBuffersGPU[0];
+ delete m_data->m_pBufContactBuffersGPU[1];
+
+
+ delete m_data->m_inertiaBufferGPU;
+ delete m_data->m_collidablesGPU;
+ delete m_data->m_localShapeAABBCPU;
+ delete m_data->m_localShapeAABBGPU;
+ delete m_data->m_bodyBufferGPU;
+ delete m_data->m_convexFacesGPU;
+ delete m_data->m_gpuChildShapes;
+ delete m_data->m_convexPolyhedraGPU;
+ delete m_data->m_uniqueEdgesGPU;
+ delete m_data->m_convexVerticesGPU;
+ delete m_data->m_convexIndicesGPU;
+ delete m_data->m_worldVertsB1GPU;
+ delete m_data->m_clippingFacesOutGPU;
+ delete m_data->m_worldNormalsAGPU;
+ delete m_data->m_worldVertsA1GPU;
+ delete m_data->m_worldVertsB2GPU;
+
+ delete m_data->m_bvhInfoGPU;
+
+ for (int i=0;i<m_data->m_bvhData.size();i++)
+ {
+ delete m_data->m_bvhData[i];
+ }
+ for (int i=0;i<m_data->m_meshInterfaces.size();i++)
+ {
+ delete m_data->m_meshInterfaces[i];
+ }
+ m_data->m_meshInterfaces.clear();
+ m_data->m_bvhData.clear();
+ delete m_data->m_treeNodesGPU;
+ delete m_data->m_subTreesGPU;
+
+
+ delete m_data->m_convexData;
+ delete m_data;
+}
+
+
+int b3GpuNarrowPhase::allocateCollidable()
+{
+ int curSize = m_data->m_collidablesCPU.size();
+ if (curSize<m_data->m_config.m_maxConvexShapes)
+ {
+ m_data->m_collidablesCPU.expand();
+ return curSize;
+ }
+ else
+ {
+ b3Error("allocateCollidable out-of-range %d\n",m_data->m_config.m_maxConvexShapes);
+ }
+ return -1;
+
+}
+
+
+
+
+
+int b3GpuNarrowPhase::registerSphereShape(float radius)
+{
+ int collidableIndex = allocateCollidable();
+ if (collidableIndex<0)
+ return collidableIndex;
+
+
+ b3Collidable& col = getCollidableCpu(collidableIndex);
+ col.m_shapeType = SHAPE_SPHERE;
+ col.m_shapeIndex = 0;
+ col.m_radius = radius;
+
+ if (col.m_shapeIndex>=0)
+ {
+ b3SapAabb aabb;
+ b3Vector3 myAabbMin=b3MakeVector3(-radius,-radius,-radius);
+ b3Vector3 myAabbMax=b3MakeVector3(radius,radius,radius);
+
+ aabb.m_min[0] = myAabbMin[0];//s_convexHeightField->m_aabb.m_min.x;
+ aabb.m_min[1] = myAabbMin[1];//s_convexHeightField->m_aabb.m_min.y;
+ aabb.m_min[2] = myAabbMin[2];//s_convexHeightField->m_aabb.m_min.z;
+ aabb.m_minIndices[3] = 0;
+
+ aabb.m_max[0] = myAabbMax[0];//s_convexHeightField->m_aabb.m_max.x;
+ aabb.m_max[1] = myAabbMax[1];//s_convexHeightField->m_aabb.m_max.y;
+ aabb.m_max[2] = myAabbMax[2];//s_convexHeightField->m_aabb.m_max.z;
+ aabb.m_signedMaxIndices[3] = 0;
+
+ m_data->m_localShapeAABBCPU->push_back(aabb);
+// m_data->m_localShapeAABBGPU->push_back(aabb);
+ clFinish(m_queue);
+ }
+
+ return collidableIndex;
+}
+
+
+int b3GpuNarrowPhase::registerFace(const b3Vector3& faceNormal, float faceConstant)
+{
+ int faceOffset = m_data->m_convexFaces.size();
+ b3GpuFace& face = m_data->m_convexFaces.expand();
+ face.m_plane = b3MakeVector3(faceNormal.x,faceNormal.y,faceNormal.z,faceConstant);
+ return faceOffset;
+}
+
+int b3GpuNarrowPhase::registerPlaneShape(const b3Vector3& planeNormal, float planeConstant)
+{
+ int collidableIndex = allocateCollidable();
+ if (collidableIndex<0)
+ return collidableIndex;
+
+
+ b3Collidable& col = getCollidableCpu(collidableIndex);
+ col.m_shapeType = SHAPE_PLANE;
+ col.m_shapeIndex = registerFace(planeNormal,planeConstant);
+ col.m_radius = planeConstant;
+
+ if (col.m_shapeIndex>=0)
+ {
+ b3SapAabb aabb;
+ aabb.m_min[0] = -1e30f;
+ aabb.m_min[1] = -1e30f;
+ aabb.m_min[2] = -1e30f;
+ aabb.m_minIndices[3] = 0;
+
+ aabb.m_max[0] = 1e30f;
+ aabb.m_max[1] = 1e30f;
+ aabb.m_max[2] = 1e30f;
+ aabb.m_signedMaxIndices[3] = 0;
+
+ m_data->m_localShapeAABBCPU->push_back(aabb);
+// m_data->m_localShapeAABBGPU->push_back(aabb);
+ clFinish(m_queue);
+ }
+
+ return collidableIndex;
+}
+
+
+int b3GpuNarrowPhase::registerConvexHullShapeInternal(b3ConvexUtility* convexPtr,b3Collidable& col)
+{
+
+ m_data->m_convexData->resize(m_data->m_numAcceleratedShapes+1);
+ m_data->m_convexPolyhedra.resize(m_data->m_numAcceleratedShapes+1);
+
+
+ b3ConvexPolyhedronData& convex = m_data->m_convexPolyhedra.at(m_data->m_convexPolyhedra.size()-1);
+ convex.mC = convexPtr->mC;
+ convex.mE = convexPtr->mE;
+ convex.m_extents= convexPtr->m_extents;
+ convex.m_localCenter = convexPtr->m_localCenter;
+ convex.m_radius = convexPtr->m_radius;
+
+ convex.m_numUniqueEdges = convexPtr->m_uniqueEdges.size();
+ int edgeOffset = m_data->m_uniqueEdges.size();
+ convex.m_uniqueEdgesOffset = edgeOffset;
+
+ m_data->m_uniqueEdges.resize(edgeOffset+convex.m_numUniqueEdges);
+
+ //convex data here
+ int i;
+ for ( i=0;i<convexPtr->m_uniqueEdges.size();i++)
+ {
+ m_data->m_uniqueEdges[edgeOffset+i] = convexPtr->m_uniqueEdges[i];
+ }
+
+ int faceOffset = m_data->m_convexFaces.size();
+ convex.m_faceOffset = faceOffset;
+ convex.m_numFaces = convexPtr->m_faces.size();
+
+ m_data->m_convexFaces.resize(faceOffset+convex.m_numFaces);
+
+
+ for (i=0;i<convexPtr->m_faces.size();i++)
+ {
+ m_data->m_convexFaces[convex.m_faceOffset+i].m_plane = b3MakeVector3(convexPtr->m_faces[i].m_plane[0],
+ convexPtr->m_faces[i].m_plane[1],
+ convexPtr->m_faces[i].m_plane[2],
+ convexPtr->m_faces[i].m_plane[3]);
+
+
+ int indexOffset = m_data->m_convexIndices.size();
+ int numIndices = convexPtr->m_faces[i].m_indices.size();
+ m_data->m_convexFaces[convex.m_faceOffset+i].m_numIndices = numIndices;
+ m_data->m_convexFaces[convex.m_faceOffset+i].m_indexOffset = indexOffset;
+ m_data->m_convexIndices.resize(indexOffset+numIndices);
+ for (int p=0;p<numIndices;p++)
+ {
+ m_data->m_convexIndices[indexOffset+p] = convexPtr->m_faces[i].m_indices[p];
+ }
+ }
+
+ convex.m_numVertices = convexPtr->m_vertices.size();
+ int vertexOffset = m_data->m_convexVertices.size();
+ convex.m_vertexOffset =vertexOffset;
+
+ m_data->m_convexVertices.resize(vertexOffset+convex.m_numVertices);
+ for (int i=0;i<convexPtr->m_vertices.size();i++)
+ {
+ m_data->m_convexVertices[vertexOffset+i] = convexPtr->m_vertices[i];
+ }
+
+ (*m_data->m_convexData)[m_data->m_numAcceleratedShapes] = convexPtr;
+
+
+
+ return m_data->m_numAcceleratedShapes++;
+}
+
+
+int b3GpuNarrowPhase::registerConvexHullShape(const float* vertices, int strideInBytes, int numVertices, const float* scaling)
+{
+ b3AlignedObjectArray<b3Vector3> verts;
+
+ unsigned char* vts = (unsigned char*) vertices;
+ for (int i=0;i<numVertices;i++)
+ {
+ float* vertex = (float*) &vts[i*strideInBytes];
+ verts.push_back(b3MakeVector3(vertex[0]*scaling[0],vertex[1]*scaling[1],vertex[2]*scaling[2]));
+ }
+
+ b3ConvexUtility* utilPtr = new b3ConvexUtility();
+ bool merge = true;
+ if (numVertices)
+ {
+ utilPtr->initializePolyhedralFeatures(&verts[0],verts.size(),merge);
+ }
+
+ int collidableIndex = registerConvexHullShape(utilPtr);
+ delete utilPtr;
+ return collidableIndex;
+}
+
+int b3GpuNarrowPhase::registerConvexHullShape(b3ConvexUtility* utilPtr)
+{
+ int collidableIndex = allocateCollidable();
+ if (collidableIndex<0)
+ return collidableIndex;
+
+ b3Collidable& col = getCollidableCpu(collidableIndex);
+ col.m_shapeType = SHAPE_CONVEX_HULL;
+ col.m_shapeIndex = -1;
+
+
+ {
+ b3Vector3 localCenter=b3MakeVector3(0,0,0);
+ for (int i=0;i<utilPtr->m_vertices.size();i++)
+ localCenter+=utilPtr->m_vertices[i];
+ localCenter*= (1.f/utilPtr->m_vertices.size());
+ utilPtr->m_localCenter = localCenter;
+
+ col.m_shapeIndex = registerConvexHullShapeInternal(utilPtr,col);
+ }
+
+ if (col.m_shapeIndex>=0)
+ {
+ b3SapAabb aabb;
+
+ b3Vector3 myAabbMin=b3MakeVector3(1e30f,1e30f,1e30f);
+ b3Vector3 myAabbMax=b3MakeVector3(-1e30f,-1e30f,-1e30f);
+
+ for (int i=0;i<utilPtr->m_vertices.size();i++)
+ {
+ myAabbMin.setMin(utilPtr->m_vertices[i]);
+ myAabbMax.setMax(utilPtr->m_vertices[i]);
+ }
+ aabb.m_min[0] = myAabbMin[0];
+ aabb.m_min[1] = myAabbMin[1];
+ aabb.m_min[2] = myAabbMin[2];
+ aabb.m_minIndices[3] = 0;
+
+ aabb.m_max[0] = myAabbMax[0];
+ aabb.m_max[1] = myAabbMax[1];
+ aabb.m_max[2] = myAabbMax[2];
+ aabb.m_signedMaxIndices[3] = 0;
+
+ m_data->m_localShapeAABBCPU->push_back(aabb);
+// m_data->m_localShapeAABBGPU->push_back(aabb);
+ }
+
+ return collidableIndex;
+
+}
+
+int b3GpuNarrowPhase::registerCompoundShape(b3AlignedObjectArray<b3GpuChildShape>* childShapes)
+{
+
+ int collidableIndex = allocateCollidable();
+ if (collidableIndex<0)
+ return collidableIndex;
+
+ b3Collidable& col = getCollidableCpu(collidableIndex);
+ col.m_shapeType = SHAPE_COMPOUND_OF_CONVEX_HULLS;
+ col.m_shapeIndex = m_data->m_cpuChildShapes.size();
+ col.m_compoundBvhIndex = m_data->m_bvhInfoCPU.size();
+
+ {
+ b3Assert(col.m_shapeIndex+childShapes->size()<m_data->m_config.m_maxCompoundChildShapes);
+ for (int i=0;i<childShapes->size();i++)
+ {
+ m_data->m_cpuChildShapes.push_back(childShapes->at(i));
+ }
+ }
+
+
+
+ col.m_numChildShapes = childShapes->size();
+
+
+ b3SapAabb aabbLocalSpace;
+ b3Vector3 myAabbMin=b3MakeVector3(1e30f,1e30f,1e30f);
+ b3Vector3 myAabbMax=b3MakeVector3(-1e30f,-1e30f,-1e30f);
+
+ b3AlignedObjectArray<b3Aabb> childLocalAabbs;
+ childLocalAabbs.resize(childShapes->size());
+
+ //compute local AABB of the compound of all children
+ for (int i=0;i<childShapes->size();i++)
+ {
+ int childColIndex = childShapes->at(i).m_shapeIndex;
+ //b3Collidable& childCol = getCollidableCpu(childColIndex);
+ b3SapAabb aabbLoc =m_data->m_localShapeAABBCPU->at(childColIndex);
+
+ b3Vector3 childLocalAabbMin=b3MakeVector3(aabbLoc.m_min[0],aabbLoc.m_min[1],aabbLoc.m_min[2]);
+ b3Vector3 childLocalAabbMax=b3MakeVector3(aabbLoc.m_max[0],aabbLoc.m_max[1],aabbLoc.m_max[2]);
+ b3Vector3 aMin,aMax;
+ b3Scalar margin(0.f);
+ b3Transform childTr;
+ childTr.setIdentity();
+
+ childTr.setOrigin(childShapes->at(i).m_childPosition);
+ childTr.setRotation(b3Quaternion(childShapes->at(i).m_childOrientation));
+ b3TransformAabb(childLocalAabbMin,childLocalAabbMax,margin,childTr,aMin,aMax);
+ myAabbMin.setMin(aMin);
+ myAabbMax.setMax(aMax);
+ childLocalAabbs[i].m_min[0] = aMin[0];
+ childLocalAabbs[i].m_min[1] = aMin[1];
+ childLocalAabbs[i].m_min[2] = aMin[2];
+ childLocalAabbs[i].m_min[3] = 0;
+ childLocalAabbs[i].m_max[0] = aMax[0];
+ childLocalAabbs[i].m_max[1] = aMax[1];
+ childLocalAabbs[i].m_max[2] = aMax[2];
+ childLocalAabbs[i].m_max[3] = 0;
+ }
+
+ aabbLocalSpace.m_min[0] = myAabbMin[0];//s_convexHeightField->m_aabb.m_min.x;
+ aabbLocalSpace.m_min[1]= myAabbMin[1];//s_convexHeightField->m_aabb.m_min.y;
+ aabbLocalSpace.m_min[2]= myAabbMin[2];//s_convexHeightField->m_aabb.m_min.z;
+ aabbLocalSpace.m_minIndices[3] = 0;
+
+ aabbLocalSpace.m_max[0] = myAabbMax[0];//s_convexHeightField->m_aabb.m_max.x;
+ aabbLocalSpace.m_max[1]= myAabbMax[1];//s_convexHeightField->m_aabb.m_max.y;
+ aabbLocalSpace.m_max[2]= myAabbMax[2];//s_convexHeightField->m_aabb.m_max.z;
+ aabbLocalSpace.m_signedMaxIndices[3] = 0;
+
+ m_data->m_localShapeAABBCPU->push_back(aabbLocalSpace);
+
+
+ b3QuantizedBvh* bvh = new b3QuantizedBvh;
+ bvh->setQuantizationValues(myAabbMin,myAabbMax);
+ QuantizedNodeArray& nodes = bvh->getLeafNodeArray();
+ int numNodes = childShapes->size();
+
+ for (int i=0;i<numNodes;i++)
+ {
+ b3QuantizedBvhNode node;
+ b3Vector3 aabbMin,aabbMax;
+ aabbMin = (b3Vector3&) childLocalAabbs[i].m_min;
+ aabbMax = (b3Vector3&) childLocalAabbs[i].m_max;
+
+ bvh->quantize(&node.m_quantizedAabbMin[0],aabbMin,0);
+ bvh->quantize(&node.m_quantizedAabbMax[0],aabbMax,1);
+ int partId = 0;
+ node.m_escapeIndexOrTriangleIndex = (partId<<(31-MAX_NUM_PARTS_IN_BITS)) | i;
+ nodes.push_back(node);
+ }
+ bvh->buildInternal();
+
+ int numSubTrees = bvh->getSubtreeInfoArray().size();
+
+ //void setQuantizationValues(const b3Vector3& bvhAabbMin,const b3Vector3& bvhAabbMax,b3Scalar quantizationMargin=b3Scalar(1.0));
+ //QuantizedNodeArray& getLeafNodeArray() { return m_quantizedLeafNodes; }
+ ///buildInternal is expert use only: assumes that setQuantizationValues and LeafNodeArray are initialized
+ //void buildInternal();
+
+ b3BvhInfo bvhInfo;
+
+ bvhInfo.m_aabbMin = bvh->m_bvhAabbMin;
+ bvhInfo.m_aabbMax = bvh->m_bvhAabbMax;
+ bvhInfo.m_quantization = bvh->m_bvhQuantization;
+ bvhInfo.m_numNodes = numNodes;
+ bvhInfo.m_numSubTrees = numSubTrees;
+ bvhInfo.m_nodeOffset = m_data->m_treeNodesCPU.size();
+ bvhInfo.m_subTreeOffset = m_data->m_subTreesCPU.size();
+
+ int numNewNodes = bvh->getQuantizedNodeArray().size();
+
+ for (int i=0;i<numNewNodes-1;i++)
+ {
+
+ if (bvh->getQuantizedNodeArray()[i].isLeafNode())
+ {
+ int orgIndex = bvh->getQuantizedNodeArray()[i].getTriangleIndex();
+
+ b3Vector3 nodeMinVec = bvh->unQuantize(bvh->getQuantizedNodeArray()[i].m_quantizedAabbMin);
+ b3Vector3 nodeMaxVec = bvh->unQuantize(bvh->getQuantizedNodeArray()[i].m_quantizedAabbMax);
+
+ for (int c=0;c<3;c++)
+ {
+ if (childLocalAabbs[orgIndex].m_min[c] < nodeMinVec[c])
+ {
+ printf("min org (%f) and new (%f) ? at i:%d,c:%d\n",childLocalAabbs[i].m_min[c],nodeMinVec[c],i,c);
+ }
+ if (childLocalAabbs[orgIndex].m_max[c] > nodeMaxVec[c])
+ {
+ printf("max org (%f) and new (%f) ? at i:%d,c:%d\n",childLocalAabbs[i].m_max[c],nodeMaxVec[c],i,c);
+ }
+
+ }
+ }
+
+ }
+
+ m_data->m_bvhInfoCPU.push_back(bvhInfo);
+
+ int numNewSubtrees = bvh->getSubtreeInfoArray().size();
+ m_data->m_subTreesCPU.reserve(m_data->m_subTreesCPU.size()+numNewSubtrees);
+ for (int i=0;i<numNewSubtrees;i++)
+ {
+ m_data->m_subTreesCPU.push_back(bvh->getSubtreeInfoArray()[i]);
+ }
+ int numNewTreeNodes = bvh->getQuantizedNodeArray().size();
+
+ for (int i=0;i<numNewTreeNodes;i++)
+ {
+ m_data->m_treeNodesCPU.push_back(bvh->getQuantizedNodeArray()[i]);
+ }
+
+// m_data->m_localShapeAABBGPU->push_back(aabbWS);
+ clFinish(m_queue);
+ return collidableIndex;
+
+}
+
+
+int b3GpuNarrowPhase::registerConcaveMesh(b3AlignedObjectArray<b3Vector3>* vertices, b3AlignedObjectArray<int>* indices,const float* scaling1)
+{
+
+
+ b3Vector3 scaling=b3MakeVector3(scaling1[0],scaling1[1],scaling1[2]);
+
+ int collidableIndex = allocateCollidable();
+ if (collidableIndex<0)
+ return collidableIndex;
+
+ b3Collidable& col = getCollidableCpu(collidableIndex);
+
+ col.m_shapeType = SHAPE_CONCAVE_TRIMESH;
+ col.m_shapeIndex = registerConcaveMeshShape(vertices,indices,col,scaling);
+ col.m_bvhIndex = m_data->m_bvhInfoCPU.size();
+
+
+ b3SapAabb aabb;
+ b3Vector3 myAabbMin=b3MakeVector3(1e30f,1e30f,1e30f);
+ b3Vector3 myAabbMax=b3MakeVector3(-1e30f,-1e30f,-1e30f);
+
+ for (int i=0;i<vertices->size();i++)
+ {
+ b3Vector3 vtx(vertices->at(i)*scaling);
+ myAabbMin.setMin(vtx);
+ myAabbMax.setMax(vtx);
+ }
+ aabb.m_min[0] = myAabbMin[0];
+ aabb.m_min[1] = myAabbMin[1];
+ aabb.m_min[2] = myAabbMin[2];
+ aabb.m_minIndices[3] = 0;
+
+ aabb.m_max[0] = myAabbMax[0];
+ aabb.m_max[1]= myAabbMax[1];
+ aabb.m_max[2]= myAabbMax[2];
+ aabb.m_signedMaxIndices[3]= 0;
+
+ m_data->m_localShapeAABBCPU->push_back(aabb);
+// m_data->m_localShapeAABBGPU->push_back(aabb);
+
+ b3OptimizedBvh* bvh = new b3OptimizedBvh();
+ //void b3OptimizedBvh::build(b3StridingMeshInterface* triangles, bool useQuantizedAabbCompression, const b3Vector3& bvhAabbMin, const b3Vector3& bvhAabbMax)
+
+ bool useQuantizedAabbCompression = true;
+ b3TriangleIndexVertexArray* meshInterface=new b3TriangleIndexVertexArray();
+ m_data->m_meshInterfaces.push_back(meshInterface);
+ b3IndexedMesh mesh;
+ mesh.m_numTriangles = indices->size()/3;
+ mesh.m_numVertices = vertices->size();
+ mesh.m_vertexBase = (const unsigned char *)&vertices->at(0).x;
+ mesh.m_vertexStride = sizeof(b3Vector3);
+ mesh.m_triangleIndexStride = 3 * sizeof(int);// or sizeof(int)
+ mesh.m_triangleIndexBase = (const unsigned char *)&indices->at(0);
+
+ meshInterface->addIndexedMesh(mesh);
+ bvh->build(meshInterface, useQuantizedAabbCompression, (b3Vector3&)aabb.m_min, (b3Vector3&)aabb.m_max);
+ m_data->m_bvhData.push_back(bvh);
+ int numNodes = bvh->getQuantizedNodeArray().size();
+ //b3OpenCLArray<b3QuantizedBvhNode>* treeNodesGPU = new b3OpenCLArray<b3QuantizedBvhNode>(this->m_context,this->m_queue,numNodes);
+ int numSubTrees = bvh->getSubtreeInfoArray().size();
+
+ b3BvhInfo bvhInfo;
+
+ bvhInfo.m_aabbMin = bvh->m_bvhAabbMin;
+ bvhInfo.m_aabbMax = bvh->m_bvhAabbMax;
+ bvhInfo.m_quantization = bvh->m_bvhQuantization;
+ bvhInfo.m_numNodes = numNodes;
+ bvhInfo.m_numSubTrees = numSubTrees;
+ bvhInfo.m_nodeOffset = m_data->m_treeNodesCPU.size();
+ bvhInfo.m_subTreeOffset = m_data->m_subTreesCPU.size();
+
+ m_data->m_bvhInfoCPU.push_back(bvhInfo);
+
+
+ int numNewSubtrees = bvh->getSubtreeInfoArray().size();
+ m_data->m_subTreesCPU.reserve(m_data->m_subTreesCPU.size()+numNewSubtrees);
+ for (int i=0;i<numNewSubtrees;i++)
+ {
+ m_data->m_subTreesCPU.push_back(bvh->getSubtreeInfoArray()[i]);
+ }
+ int numNewTreeNodes = bvh->getQuantizedNodeArray().size();
+
+ for (int i=0;i<numNewTreeNodes;i++)
+ {
+ m_data->m_treeNodesCPU.push_back(bvh->getQuantizedNodeArray()[i]);
+ }
+
+
+
+
+ return collidableIndex;
+}
+
+int b3GpuNarrowPhase::registerConcaveMeshShape(b3AlignedObjectArray<b3Vector3>* vertices, b3AlignedObjectArray<int>* indices,b3Collidable& col, const float* scaling1)
+{
+
+
+ b3Vector3 scaling=b3MakeVector3(scaling1[0],scaling1[1],scaling1[2]);
+
+ m_data->m_convexData->resize(m_data->m_numAcceleratedShapes+1);
+ m_data->m_convexPolyhedra.resize(m_data->m_numAcceleratedShapes+1);
+
+
+ b3ConvexPolyhedronData& convex = m_data->m_convexPolyhedra.at(m_data->m_convexPolyhedra.size()-1);
+ convex.mC = b3MakeVector3(0,0,0);
+ convex.mE = b3MakeVector3(0,0,0);
+ convex.m_extents= b3MakeVector3(0,0,0);
+ convex.m_localCenter = b3MakeVector3(0,0,0);
+ convex.m_radius = 0.f;
+
+ convex.m_numUniqueEdges = 0;
+ int edgeOffset = m_data->m_uniqueEdges.size();
+ convex.m_uniqueEdgesOffset = edgeOffset;
+
+ int faceOffset = m_data->m_convexFaces.size();
+ convex.m_faceOffset = faceOffset;
+
+ convex.m_numFaces = indices->size()/3;
+ m_data->m_convexFaces.resize(faceOffset+convex.m_numFaces);
+ m_data->m_convexIndices.reserve(convex.m_numFaces*3);
+ for (int i=0;i<convex.m_numFaces;i++)
+ {
+ if (i%256==0)
+ {
+ //printf("i=%d out of %d", i,convex.m_numFaces);
+ }
+ b3Vector3 vert0(vertices->at(indices->at(i*3))*scaling);
+ b3Vector3 vert1(vertices->at(indices->at(i*3+1))*scaling);
+ b3Vector3 vert2(vertices->at(indices->at(i*3+2))*scaling);
+
+ b3Vector3 normal = ((vert1-vert0).cross(vert2-vert0)).normalize();
+ b3Scalar c = -(normal.dot(vert0));
+
+ m_data->m_convexFaces[convex.m_faceOffset+i].m_plane = b3MakeVector4(normal.x,normal.y,normal.z,c);
+ int indexOffset = m_data->m_convexIndices.size();
+ int numIndices = 3;
+ m_data->m_convexFaces[convex.m_faceOffset+i].m_numIndices = numIndices;
+ m_data->m_convexFaces[convex.m_faceOffset+i].m_indexOffset = indexOffset;
+ m_data->m_convexIndices.resize(indexOffset+numIndices);
+ for (int p=0;p<numIndices;p++)
+ {
+ int vi = indices->at(i*3+p);
+ m_data->m_convexIndices[indexOffset+p] = vi;//convexPtr->m_faces[i].m_indices[p];
+ }
+ }
+
+ convex.m_numVertices = vertices->size();
+ int vertexOffset = m_data->m_convexVertices.size();
+ convex.m_vertexOffset =vertexOffset;
+ m_data->m_convexVertices.resize(vertexOffset+convex.m_numVertices);
+ for (int i=0;i<vertices->size();i++)
+ {
+ m_data->m_convexVertices[vertexOffset+i] = vertices->at(i)*scaling;
+ }
+
+ (*m_data->m_convexData)[m_data->m_numAcceleratedShapes] = 0;
+
+
+ return m_data->m_numAcceleratedShapes++;
+}
+
+
+
+cl_mem b3GpuNarrowPhase::getBodiesGpu()
+{
+ return (cl_mem)m_data->m_bodyBufferGPU->getBufferCL();
+}
+
+const struct b3RigidBodyData* b3GpuNarrowPhase::getBodiesCpu() const
+{
+ return &m_data->m_bodyBufferCPU->at(0);
+};
+
+
+
+
+int b3GpuNarrowPhase::getNumBodiesGpu() const
+{
+ return m_data->m_bodyBufferGPU->size();
+}
+
+cl_mem b3GpuNarrowPhase::getBodyInertiasGpu()
+{
+ return (cl_mem)m_data->m_inertiaBufferGPU->getBufferCL();
+}
+
+int b3GpuNarrowPhase::getNumBodyInertiasGpu() const
+{
+ return m_data->m_inertiaBufferGPU->size();
+}
+
+
+b3Collidable& b3GpuNarrowPhase::getCollidableCpu(int collidableIndex)
+{
+ return m_data->m_collidablesCPU[collidableIndex];
+}
+
+const b3Collidable& b3GpuNarrowPhase::getCollidableCpu(int collidableIndex) const
+{
+ return m_data->m_collidablesCPU[collidableIndex];
+}
+
+cl_mem b3GpuNarrowPhase::getCollidablesGpu()
+{
+ return m_data->m_collidablesGPU->getBufferCL();
+}
+
+const struct b3Collidable* b3GpuNarrowPhase::getCollidablesCpu() const
+{
+ if (m_data->m_collidablesCPU.size())
+ return &m_data->m_collidablesCPU[0];
+ return 0;
+}
+
+const struct b3SapAabb* b3GpuNarrowPhase::getLocalSpaceAabbsCpu() const
+{
+ if (m_data->m_localShapeAABBCPU->size())
+ {
+ return &m_data->m_localShapeAABBCPU->at(0);
+ }
+ return 0;
+}
+
+
+cl_mem b3GpuNarrowPhase::getAabbLocalSpaceBufferGpu()
+{
+ return m_data->m_localShapeAABBGPU->getBufferCL();
+}
+int b3GpuNarrowPhase::getNumCollidablesGpu() const
+{
+ return m_data->m_collidablesGPU->size();
+}
+
+
+
+
+
+int b3GpuNarrowPhase::getNumContactsGpu() const
+{
+ return m_data->m_pBufContactBuffersGPU[m_data->m_currentContactBuffer]->size();
+}
+cl_mem b3GpuNarrowPhase::getContactsGpu()
+{
+ return m_data->m_pBufContactBuffersGPU[m_data->m_currentContactBuffer]->getBufferCL();
+}
+
+const b3Contact4* b3GpuNarrowPhase::getContactsCPU() const
+{
+ m_data->m_pBufContactBuffersGPU[m_data->m_currentContactBuffer]->copyToHost(*m_data->m_pBufContactOutCPU);
+ return &m_data->m_pBufContactOutCPU->at(0);
+}
+
+void b3GpuNarrowPhase::computeContacts(cl_mem broadphasePairs, int numBroadphasePairs, cl_mem aabbsWorldSpace, int numObjects)
+{
+
+ cl_mem aabbsLocalSpace = m_data->m_localShapeAABBGPU->getBufferCL();
+
+ int nContactOut = 0;
+
+ //swap buffer
+ m_data->m_currentContactBuffer=1-m_data->m_currentContactBuffer;
+
+ //int curSize = m_data->m_pBufContactBuffersGPU[m_data->m_currentContactBuffer]->size();
+
+ int maxTriConvexPairCapacity = m_data->m_config.m_maxTriConvexPairCapacity;
+ int numTriConvexPairsOut=0;
+
+ b3OpenCLArray<b3Int4> broadphasePairsGPU(m_context,m_queue);
+ broadphasePairsGPU.setFromOpenCLBuffer(broadphasePairs,numBroadphasePairs);
+
+
+
+
+ b3OpenCLArray<b3Aabb> clAabbArrayWorldSpace(this->m_context,this->m_queue);
+ clAabbArrayWorldSpace.setFromOpenCLBuffer(aabbsWorldSpace,numObjects);
+
+ b3OpenCLArray<b3Aabb> clAabbArrayLocalSpace(this->m_context,this->m_queue);
+ clAabbArrayLocalSpace.setFromOpenCLBuffer(aabbsLocalSpace,numObjects);
+
+ m_data->m_gpuSatCollision->computeConvexConvexContactsGPUSAT(
+ &broadphasePairsGPU, numBroadphasePairs,
+ m_data->m_bodyBufferGPU,
+ m_data->m_pBufContactBuffersGPU[m_data->m_currentContactBuffer],
+ nContactOut,
+ m_data->m_pBufContactBuffersGPU[1-m_data->m_currentContactBuffer],
+ m_data->m_config.m_maxContactCapacity,
+ m_data->m_config.m_compoundPairCapacity,
+ *m_data->m_convexPolyhedraGPU,
+ *m_data->m_convexVerticesGPU,
+ *m_data->m_uniqueEdgesGPU,
+ *m_data->m_convexFacesGPU,
+ *m_data->m_convexIndicesGPU,
+ *m_data->m_collidablesGPU,
+ *m_data->m_gpuChildShapes,
+ clAabbArrayWorldSpace,
+ clAabbArrayLocalSpace,
+ *m_data->m_worldVertsB1GPU,
+ *m_data->m_clippingFacesOutGPU,
+ *m_data->m_worldNormalsAGPU,
+ *m_data->m_worldVertsA1GPU,
+ *m_data->m_worldVertsB2GPU,
+ m_data->m_bvhData,
+ m_data->m_treeNodesGPU,
+ m_data->m_subTreesGPU,
+ m_data->m_bvhInfoGPU,
+ numObjects,
+ maxTriConvexPairCapacity,
+ *m_data->m_triangleConvexPairs,
+ numTriConvexPairsOut
+ );
+
+ /*b3AlignedObjectArray<b3Int4> broadphasePairsCPU;
+ broadphasePairsGPU.copyToHost(broadphasePairsCPU);
+ printf("checking pairs\n");
+ */
+}
+
+const b3SapAabb& b3GpuNarrowPhase::getLocalSpaceAabb(int collidableIndex) const
+{
+ return m_data->m_localShapeAABBCPU->at(collidableIndex);
+}
+
+
+
+
+
+int b3GpuNarrowPhase::registerRigidBody(int collidableIndex, float mass, const float* position, const float* orientation , const float* aabbMinPtr, const float* aabbMaxPtr,bool writeToGpu)
+{
+ b3Vector3 aabbMin=b3MakeVector3(aabbMinPtr[0],aabbMinPtr[1],aabbMinPtr[2]);
+ b3Vector3 aabbMax=b3MakeVector3(aabbMaxPtr[0],aabbMaxPtr[1],aabbMaxPtr[2]);
+
+
+ if (m_data->m_numAcceleratedRigidBodies >= (m_data->m_config.m_maxConvexBodies))
+ {
+ b3Error("registerRigidBody: exceeding the number of rigid bodies, %d > %d \n",m_data->m_numAcceleratedRigidBodies,m_data->m_config.m_maxConvexBodies);
+ return -1;
+ }
+
+ m_data->m_bodyBufferCPU->resize(m_data->m_numAcceleratedRigidBodies+1);
+
+ b3RigidBodyData& body = m_data->m_bodyBufferCPU->at(m_data->m_numAcceleratedRigidBodies);
+
+ float friction = 1.f;
+ float restitution = 0.f;
+
+ body.m_frictionCoeff = friction;
+ body.m_restituitionCoeff = restitution;
+ body.m_angVel = b3MakeVector3(0,0,0);
+ body.m_linVel=b3MakeVector3(0,0,0);//.setZero();
+ body.m_pos =b3MakeVector3(position[0],position[1],position[2]);
+ body.m_quat.setValue(orientation[0],orientation[1],orientation[2],orientation[3]);
+ body.m_collidableIdx = collidableIndex;
+ if (collidableIndex>=0)
+ {
+// body.m_shapeType = m_data->m_collidablesCPU.at(collidableIndex).m_shapeType;
+ } else
+ {
+ // body.m_shapeType = CollisionShape::SHAPE_PLANE;
+ m_planeBodyIndex = m_data->m_numAcceleratedRigidBodies;
+ }
+ //body.m_shapeType = shapeType;
+
+
+ body.m_invMass = mass? 1.f/mass : 0.f;
+
+ if (writeToGpu)
+ {
+ m_data->m_bodyBufferGPU->copyFromHostPointer(&body,1,m_data->m_numAcceleratedRigidBodies);
+ }
+
+ b3InertiaData& shapeInfo = m_data->m_inertiaBufferCPU->at(m_data->m_numAcceleratedRigidBodies);
+
+ if (mass==0.f)
+ {
+ if (m_data->m_numAcceleratedRigidBodies==0)
+ m_static0Index = 0;
+
+ shapeInfo.m_initInvInertia.setValue(0,0,0,0,0,0,0,0,0);
+ shapeInfo.m_invInertiaWorld.setValue(0,0,0,0,0,0,0,0,0);
+ } else
+ {
+
+ b3Assert(body.m_collidableIdx>=0);
+
+ //approximate using the aabb of the shape
+
+ //Aabb aabb = (*m_data->m_shapePointers)[shapeIndex]->m_aabb;
+ b3Vector3 halfExtents = (aabbMax-aabbMin);//*0.5f;//fake larger inertia makes demos more stable ;-)
+
+ b3Vector3 localInertia;
+
+ float lx=2.f*halfExtents[0];
+ float ly=2.f*halfExtents[1];
+ float lz=2.f*halfExtents[2];
+
+ localInertia.setValue( (mass/12.0f) * (ly*ly + lz*lz),
+ (mass/12.0f) * (lx*lx + lz*lz),
+ (mass/12.0f) * (lx*lx + ly*ly));
+
+ b3Vector3 invLocalInertia;
+ invLocalInertia[0] = 1.f/localInertia[0];
+ invLocalInertia[1] = 1.f/localInertia[1];
+ invLocalInertia[2] = 1.f/localInertia[2];
+ invLocalInertia[3] = 0.f;
+
+ shapeInfo.m_initInvInertia.setValue(
+ invLocalInertia[0], 0, 0,
+ 0, invLocalInertia[1], 0,
+ 0, 0, invLocalInertia[2]);
+
+ b3Matrix3x3 m (body.m_quat);
+
+ shapeInfo.m_invInertiaWorld = m.scaled(invLocalInertia) * m.transpose();
+
+ }
+
+ if (writeToGpu)
+ m_data->m_inertiaBufferGPU->copyFromHostPointer(&shapeInfo,1,m_data->m_numAcceleratedRigidBodies);
+
+
+
+ return m_data->m_numAcceleratedRigidBodies++;
+}
+
+int b3GpuNarrowPhase::getNumRigidBodies() const
+{
+ return m_data->m_numAcceleratedRigidBodies;
+}
+
+void b3GpuNarrowPhase::writeAllBodiesToGpu()
+{
+
+ if (m_data->m_localShapeAABBCPU->size())
+ {
+ m_data->m_localShapeAABBGPU->copyFromHost(*m_data->m_localShapeAABBCPU);
+ }
+
+
+ m_data->m_gpuChildShapes->copyFromHost(m_data->m_cpuChildShapes);
+ m_data->m_convexFacesGPU->copyFromHost(m_data->m_convexFaces);
+ m_data->m_convexPolyhedraGPU->copyFromHost(m_data->m_convexPolyhedra);
+ m_data->m_uniqueEdgesGPU->copyFromHost(m_data->m_uniqueEdges);
+ m_data->m_convexVerticesGPU->copyFromHost(m_data->m_convexVertices);
+ m_data->m_convexIndicesGPU->copyFromHost(m_data->m_convexIndices);
+ m_data->m_bvhInfoGPU->copyFromHost(m_data->m_bvhInfoCPU);
+ m_data->m_treeNodesGPU->copyFromHost(m_data->m_treeNodesCPU);
+ m_data->m_subTreesGPU->copyFromHost(m_data->m_subTreesCPU);
+
+
+ m_data->m_bodyBufferGPU->resize(m_data->m_numAcceleratedRigidBodies);
+ m_data->m_inertiaBufferGPU->resize(m_data->m_numAcceleratedRigidBodies);
+
+ if (m_data->m_numAcceleratedRigidBodies)
+ {
+ m_data->m_bodyBufferGPU->copyFromHostPointer(&m_data->m_bodyBufferCPU->at(0),m_data->m_numAcceleratedRigidBodies);
+ m_data->m_inertiaBufferGPU->copyFromHostPointer(&m_data->m_inertiaBufferCPU->at(0),m_data->m_numAcceleratedRigidBodies);
+ }
+ if (m_data->m_collidablesCPU.size())
+ {
+ m_data->m_collidablesGPU->copyFromHost(m_data->m_collidablesCPU);
+ }
+
+
+}
+
+
+void b3GpuNarrowPhase::reset()
+{
+ m_data->m_numAcceleratedShapes = 0;
+ m_data->m_numAcceleratedRigidBodies = 0;
+ this->m_static0Index = -1;
+ m_data->m_uniqueEdges.resize(0);
+ m_data->m_convexVertices.resize(0);
+ m_data->m_convexPolyhedra.resize(0);
+ m_data->m_convexIndices.resize(0);
+ m_data->m_cpuChildShapes.resize(0);
+ m_data->m_convexFaces.resize(0);
+ m_data->m_collidablesCPU.resize(0);
+ m_data->m_localShapeAABBCPU->resize(0);
+ m_data->m_bvhData.resize(0);
+ m_data->m_treeNodesCPU.resize(0);
+ m_data->m_subTreesCPU.resize(0);
+ m_data->m_bvhInfoCPU.resize(0);
+
+}
+
+
+void b3GpuNarrowPhase::readbackAllBodiesToCpu()
+{
+ m_data->m_bodyBufferGPU->copyToHostPointer(&m_data->m_bodyBufferCPU->at(0),m_data->m_numAcceleratedRigidBodies);
+}
+
+void b3GpuNarrowPhase::setObjectTransformCpu(float* position, float* orientation , int bodyIndex)
+{
+ if (bodyIndex>=0 && bodyIndex<m_data->m_bodyBufferCPU->size())
+ {
+ m_data->m_bodyBufferCPU->at(bodyIndex).m_pos=b3MakeVector3(position[0],position[1],position[2]);
+ m_data->m_bodyBufferCPU->at(bodyIndex).m_quat.setValue(orientation[0],orientation[1],orientation[2],orientation[3]);
+ }
+ else
+ {
+ b3Warning("setObjectVelocityCpu out of range.\n");
+ }
+}
+void b3GpuNarrowPhase::setObjectVelocityCpu(float* linVel, float* angVel, int bodyIndex)
+{
+ if (bodyIndex>=0 && bodyIndex<m_data->m_bodyBufferCPU->size())
+ {
+ m_data->m_bodyBufferCPU->at(bodyIndex).m_linVel=b3MakeVector3(linVel[0],linVel[1],linVel[2]);
+ m_data->m_bodyBufferCPU->at(bodyIndex).m_angVel=b3MakeVector3(angVel[0],angVel[1],angVel[2]);
+ } else
+ {
+ b3Warning("setObjectVelocityCpu out of range.\n");
+ }
+}
+
+bool b3GpuNarrowPhase::getObjectTransformFromCpu(float* position, float* orientation , int bodyIndex) const
+{
+ if (bodyIndex>=0 && bodyIndex<m_data->m_bodyBufferCPU->size())
+ {
+ position[0] = m_data->m_bodyBufferCPU->at(bodyIndex).m_pos.x;
+ position[1] = m_data->m_bodyBufferCPU->at(bodyIndex).m_pos.y;
+ position[2] = m_data->m_bodyBufferCPU->at(bodyIndex).m_pos.z;
+ position[3] = 1.f;//or 1
+
+ orientation[0] = m_data->m_bodyBufferCPU->at(bodyIndex).m_quat.x;
+ orientation[1] = m_data->m_bodyBufferCPU->at(bodyIndex).m_quat.y;
+ orientation[2] = m_data->m_bodyBufferCPU->at(bodyIndex).m_quat.z;
+ orientation[3] = m_data->m_bodyBufferCPU->at(bodyIndex).m_quat.w;
+ return true;
+ }
+
+ b3Warning("getObjectTransformFromCpu out of range.\n");
+ return false;
+}
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuNarrowPhase.h b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuNarrowPhase.h
new file mode 100644
index 0000000000..05ff3fd09e
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuNarrowPhase.h
@@ -0,0 +1,109 @@
+#ifndef B3_GPU_NARROWPHASE_H
+#define B3_GPU_NARROWPHASE_H
+
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h"
+#include "Bullet3OpenCL/Initialize/b3OpenCLInclude.h"
+#include "Bullet3Common/b3AlignedObjectArray.h"
+#include "Bullet3Common/b3Vector3.h"
+
+class b3GpuNarrowPhase
+{
+protected:
+
+ struct b3GpuNarrowPhaseInternalData* m_data;
+ int m_acceleratedCompanionShapeIndex;
+ int m_planeBodyIndex;
+ int m_static0Index;
+
+ cl_context m_context;
+ cl_device_id m_device;
+ cl_command_queue m_queue;
+
+ int registerConvexHullShapeInternal(class b3ConvexUtility* convexPtr, b3Collidable& col);
+ int registerConcaveMeshShape(b3AlignedObjectArray<b3Vector3>* vertices, b3AlignedObjectArray<int>* indices, b3Collidable& col, const float* scaling);
+
+public:
+
+
+
+
+ b3GpuNarrowPhase(cl_context vtx, cl_device_id dev, cl_command_queue q, const struct b3Config& config);
+
+ virtual ~b3GpuNarrowPhase(void);
+
+ int registerSphereShape(float radius);
+ int registerPlaneShape(const b3Vector3& planeNormal, float planeConstant);
+
+ int registerCompoundShape(b3AlignedObjectArray<b3GpuChildShape>* childShapes);
+ int registerFace(const b3Vector3& faceNormal, float faceConstant);
+
+ int registerConcaveMesh(b3AlignedObjectArray<b3Vector3>* vertices, b3AlignedObjectArray<int>* indices,const float* scaling);
+
+ //do they need to be merged?
+
+ int registerConvexHullShape(b3ConvexUtility* utilPtr);
+ int registerConvexHullShape(const float* vertices, int strideInBytes, int numVertices, const float* scaling);
+
+ int registerRigidBody(int collidableIndex, float mass, const float* position, const float* orientation, const float* aabbMin, const float* aabbMax,bool writeToGpu);
+ void setObjectTransform(const float* position, const float* orientation , int bodyIndex);
+
+ void writeAllBodiesToGpu();
+ void reset();
+ void readbackAllBodiesToCpu();
+ bool getObjectTransformFromCpu(float* position, float* orientation , int bodyIndex) const;
+
+ void setObjectTransformCpu(float* position, float* orientation , int bodyIndex);
+ void setObjectVelocityCpu(float* linVel, float* angVel, int bodyIndex);
+
+
+ virtual void computeContacts(cl_mem broadphasePairs, int numBroadphasePairs, cl_mem aabbsWorldSpace, int numObjects);
+
+
+ cl_mem getBodiesGpu();
+ const struct b3RigidBodyData* getBodiesCpu() const;
+ //struct b3RigidBodyData* getBodiesCpu();
+
+ int getNumBodiesGpu() const;
+
+ cl_mem getBodyInertiasGpu();
+ int getNumBodyInertiasGpu() const;
+
+ cl_mem getCollidablesGpu();
+ const struct b3Collidable* getCollidablesCpu() const;
+ int getNumCollidablesGpu() const;
+
+ const struct b3SapAabb* getLocalSpaceAabbsCpu() const;
+
+ const struct b3Contact4* getContactsCPU() const;
+
+ cl_mem getContactsGpu();
+ int getNumContactsGpu() const;
+
+ cl_mem getAabbLocalSpaceBufferGpu();
+
+ int getNumRigidBodies() const;
+
+ int allocateCollidable();
+
+ int getStatic0Index() const
+ {
+ return m_static0Index;
+ }
+ b3Collidable& getCollidableCpu(int collidableIndex);
+ const b3Collidable& getCollidableCpu(int collidableIndex) const;
+
+ const b3GpuNarrowPhaseInternalData* getInternalData() const
+ {
+ return m_data;
+ }
+
+ b3GpuNarrowPhaseInternalData* getInternalData()
+ {
+ return m_data;
+ }
+
+ const struct b3SapAabb& getLocalSpaceAabb(int collidableIndex) const;
+};
+
+#endif //B3_GPU_NARROWPHASE_H
+
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuNarrowPhaseInternalData.h b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuNarrowPhaseInternalData.h
new file mode 100644
index 0000000000..8a7f1ea859
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuNarrowPhaseInternalData.h
@@ -0,0 +1,95 @@
+
+#ifndef B3_GPU_NARROWPHASE_INTERNAL_DATA_H
+#define B3_GPU_NARROWPHASE_INTERNAL_DATA_H
+
+#include "Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h"
+#include "Bullet3Collision/NarrowPhaseCollision/b3Config.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h"
+
+#include "Bullet3OpenCL/Initialize/b3OpenCLInclude.h"
+#include "Bullet3Common/b3AlignedObjectArray.h"
+#include "Bullet3Common/b3Vector3.h"
+
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
+#include "Bullet3Collision/NarrowPhaseCollision/b3Contact4.h"
+#include "Bullet3OpenCL/BroadphaseCollision/b3SapAabb.h"
+
+#include "Bullet3OpenCL/NarrowphaseCollision/b3QuantizedBvh.h"
+#include "Bullet3OpenCL/NarrowphaseCollision/b3BvhInfo.h"
+#include "Bullet3Common/shared/b3Int4.h"
+#include "Bullet3Common/shared/b3Int2.h"
+
+
+class b3ConvexUtility;
+
+struct b3GpuNarrowPhaseInternalData
+{
+ b3AlignedObjectArray<b3ConvexUtility*>* m_convexData;
+
+ b3AlignedObjectArray<b3ConvexPolyhedronData> m_convexPolyhedra;
+ b3AlignedObjectArray<b3Vector3> m_uniqueEdges;
+ b3AlignedObjectArray<b3Vector3> m_convexVertices;
+ b3AlignedObjectArray<int> m_convexIndices;
+
+ b3OpenCLArray<b3ConvexPolyhedronData>* m_convexPolyhedraGPU;
+ b3OpenCLArray<b3Vector3>* m_uniqueEdgesGPU;
+ b3OpenCLArray<b3Vector3>* m_convexVerticesGPU;
+ b3OpenCLArray<int>* m_convexIndicesGPU;
+
+ b3OpenCLArray<b3Vector3>* m_worldVertsB1GPU;
+ b3OpenCLArray<b3Int4>* m_clippingFacesOutGPU;
+ b3OpenCLArray<b3Vector3>* m_worldNormalsAGPU;
+ b3OpenCLArray<b3Vector3>* m_worldVertsA1GPU;
+ b3OpenCLArray<b3Vector3>* m_worldVertsB2GPU;
+
+ b3AlignedObjectArray<b3GpuChildShape> m_cpuChildShapes;
+ b3OpenCLArray<b3GpuChildShape>* m_gpuChildShapes;
+
+ b3AlignedObjectArray<b3GpuFace> m_convexFaces;
+ b3OpenCLArray<b3GpuFace>* m_convexFacesGPU;
+
+ struct GpuSatCollision* m_gpuSatCollision;
+
+
+ b3OpenCLArray<b3Int4>* m_triangleConvexPairs;
+
+
+ b3OpenCLArray<b3Contact4>* m_pBufContactBuffersGPU[2];
+ int m_currentContactBuffer;
+ b3AlignedObjectArray<b3Contact4>* m_pBufContactOutCPU;
+
+
+ b3AlignedObjectArray<b3RigidBodyData>* m_bodyBufferCPU;
+ b3OpenCLArray<b3RigidBodyData>* m_bodyBufferGPU;
+
+ b3AlignedObjectArray<b3InertiaData>* m_inertiaBufferCPU;
+ b3OpenCLArray<b3InertiaData>* m_inertiaBufferGPU;
+
+ int m_numAcceleratedShapes;
+ int m_numAcceleratedRigidBodies;
+
+ b3AlignedObjectArray<b3Collidable> m_collidablesCPU;
+ b3OpenCLArray<b3Collidable>* m_collidablesGPU;
+
+ b3OpenCLArray<b3SapAabb>* m_localShapeAABBGPU;
+ b3AlignedObjectArray<b3SapAabb>* m_localShapeAABBCPU;
+
+ b3AlignedObjectArray<class b3OptimizedBvh*> m_bvhData;
+ b3AlignedObjectArray<class b3TriangleIndexVertexArray*> m_meshInterfaces;
+
+ b3AlignedObjectArray<b3QuantizedBvhNode> m_treeNodesCPU;
+ b3AlignedObjectArray<b3BvhSubtreeInfo> m_subTreesCPU;
+
+ b3AlignedObjectArray<b3BvhInfo> m_bvhInfoCPU;
+ b3OpenCLArray<b3BvhInfo>* m_bvhInfoGPU;
+
+ b3OpenCLArray<b3QuantizedBvhNode>* m_treeNodesGPU;
+ b3OpenCLArray<b3BvhSubtreeInfo>* m_subTreesGPU;
+
+
+ b3Config m_config;
+
+};
+
+#endif //B3_GPU_NARROWPHASE_INTERNAL_DATA_H
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuPgsConstraintSolver.cpp b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuPgsConstraintSolver.cpp
new file mode 100644
index 0000000000..0d3d50c548
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuPgsConstraintSolver.cpp
@@ -0,0 +1,1158 @@
+
+/*
+Copyright (c) 2013 Advanced Micro Devices, Inc.
+
+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.
+*/
+//Originally written by Erwin Coumans
+
+
+bool useGpuInitSolverBodies = true;
+bool useGpuInfo1 = true;
+bool useGpuInfo2= true;
+bool useGpuSolveJointConstraintRows=true;
+bool useGpuWriteBackVelocities = true;
+bool gpuBreakConstraints = true;
+
+#include "b3GpuPgsConstraintSolver.h"
+
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
+
+#include "Bullet3Dynamics/ConstraintSolver/b3TypedConstraint.h"
+#include <new>
+#include "Bullet3Common/b3AlignedObjectArray.h"
+#include <string.h> //for memset
+#include "Bullet3Collision/NarrowPhaseCollision/b3Contact4.h"
+#include "Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h"
+#include "Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.h"
+
+#include "Bullet3OpenCL/ParallelPrimitives/b3PrefixScanCL.h"
+
+#include "Bullet3OpenCL/RigidBody/kernels/jointSolver.h" //solveConstraintRowsCL
+#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
+
+#define B3_JOINT_SOLVER_PATH "src/Bullet3OpenCL/RigidBody/kernels/jointSolver.cl"
+
+
+struct b3GpuPgsJacobiSolverInternalData
+{
+
+ cl_context m_context;
+ cl_device_id m_device;
+ cl_command_queue m_queue;
+
+ b3PrefixScanCL* m_prefixScan;
+
+ cl_kernel m_solveJointConstraintRowsKernels;
+ cl_kernel m_initSolverBodiesKernel;
+ cl_kernel m_getInfo1Kernel;
+ cl_kernel m_initBatchConstraintsKernel;
+ cl_kernel m_getInfo2Kernel;
+ cl_kernel m_writeBackVelocitiesKernel;
+ cl_kernel m_breakViolatedConstraintsKernel;
+
+ b3OpenCLArray<unsigned int>* m_gpuConstraintRowOffsets;
+
+ b3OpenCLArray<b3GpuSolverBody>* m_gpuSolverBodies;
+ b3OpenCLArray<b3BatchConstraint>* m_gpuBatchConstraints;
+ b3OpenCLArray<b3GpuSolverConstraint>* m_gpuConstraintRows;
+ b3OpenCLArray<unsigned int>* m_gpuConstraintInfo1;
+
+// b3AlignedObjectArray<b3GpuSolverBody> m_cpuSolverBodies;
+ b3AlignedObjectArray<b3BatchConstraint> m_cpuBatchConstraints;
+ b3AlignedObjectArray<b3GpuSolverConstraint> m_cpuConstraintRows;
+ b3AlignedObjectArray<unsigned int> m_cpuConstraintInfo1;
+ b3AlignedObjectArray<unsigned int> m_cpuConstraintRowOffsets;
+
+ b3AlignedObjectArray<b3RigidBodyData> m_cpuBodies;
+ b3AlignedObjectArray<b3InertiaData> m_cpuInertias;
+
+
+ b3AlignedObjectArray<b3GpuGenericConstraint> m_cpuConstraints;
+
+ b3AlignedObjectArray<int> m_batchSizes;
+
+
+};
+
+
+/*
+static b3Transform getWorldTransform(b3RigidBodyData* rb)
+{
+ b3Transform newTrans;
+ newTrans.setOrigin(rb->m_pos);
+ newTrans.setRotation(rb->m_quat);
+ return newTrans;
+}
+
+static const b3Matrix3x3& getInvInertiaTensorWorld(b3InertiaData* inertia)
+{
+ return inertia->m_invInertiaWorld;
+}
+
+*/
+
+static const b3Vector3& getLinearVelocity(b3RigidBodyData* rb)
+{
+ return rb->m_linVel;
+}
+
+static const b3Vector3& getAngularVelocity(b3RigidBodyData* rb)
+{
+ return rb->m_angVel;
+}
+
+b3Vector3 getVelocityInLocalPoint(b3RigidBodyData* rb, const b3Vector3& rel_pos)
+{
+ //we also calculate lin/ang velocity for kinematic objects
+ return getLinearVelocity(rb) + getAngularVelocity(rb).cross(rel_pos);
+
+}
+
+
+
+b3GpuPgsConstraintSolver::b3GpuPgsConstraintSolver (cl_context ctx, cl_device_id device, cl_command_queue queue,bool usePgs)
+{
+ m_usePgs = usePgs;
+ m_gpuData = new b3GpuPgsJacobiSolverInternalData();
+ m_gpuData->m_context = ctx;
+ m_gpuData->m_device = device;
+ m_gpuData->m_queue = queue;
+
+ m_gpuData->m_prefixScan = new b3PrefixScanCL(ctx,device,queue);
+
+ m_gpuData->m_gpuConstraintRowOffsets = new b3OpenCLArray<unsigned int>(m_gpuData->m_context,m_gpuData->m_queue);
+
+ m_gpuData->m_gpuSolverBodies = new b3OpenCLArray<b3GpuSolverBody>(m_gpuData->m_context,m_gpuData->m_queue);
+ m_gpuData->m_gpuBatchConstraints = new b3OpenCLArray<b3BatchConstraint>(m_gpuData->m_context,m_gpuData->m_queue);
+ m_gpuData->m_gpuConstraintRows = new b3OpenCLArray<b3GpuSolverConstraint>(m_gpuData->m_context,m_gpuData->m_queue);
+ m_gpuData->m_gpuConstraintInfo1 = new b3OpenCLArray<unsigned int>(m_gpuData->m_context,m_gpuData->m_queue);
+ cl_int errNum=0;
+
+ {
+ cl_program prog = b3OpenCLUtils::compileCLProgramFromString(m_gpuData->m_context,m_gpuData->m_device,solveConstraintRowsCL,&errNum,"",B3_JOINT_SOLVER_PATH);
+ //cl_program prog = b3OpenCLUtils::compileCLProgramFromString(m_gpuData->m_context,m_gpuData->m_device,0,&errNum,"",B3_JOINT_SOLVER_PATH,true);
+ b3Assert(errNum==CL_SUCCESS);
+ m_gpuData->m_solveJointConstraintRowsKernels = b3OpenCLUtils::compileCLKernelFromString(m_gpuData->m_context, m_gpuData->m_device,solveConstraintRowsCL, "solveJointConstraintRows",&errNum,prog);
+ b3Assert(errNum==CL_SUCCESS);
+ m_gpuData->m_initSolverBodiesKernel = b3OpenCLUtils::compileCLKernelFromString(m_gpuData->m_context,m_gpuData->m_device,solveConstraintRowsCL,"initSolverBodies",&errNum,prog);
+ b3Assert(errNum==CL_SUCCESS);
+ m_gpuData->m_getInfo1Kernel = b3OpenCLUtils::compileCLKernelFromString(m_gpuData->m_context,m_gpuData->m_device,solveConstraintRowsCL,"getInfo1Kernel",&errNum,prog);
+ b3Assert(errNum==CL_SUCCESS);
+ m_gpuData->m_initBatchConstraintsKernel = b3OpenCLUtils::compileCLKernelFromString(m_gpuData->m_context,m_gpuData->m_device,solveConstraintRowsCL,"initBatchConstraintsKernel",&errNum,prog);
+ b3Assert(errNum==CL_SUCCESS);
+ m_gpuData->m_getInfo2Kernel= b3OpenCLUtils::compileCLKernelFromString(m_gpuData->m_context,m_gpuData->m_device,solveConstraintRowsCL,"getInfo2Kernel",&errNum,prog);
+ b3Assert(errNum==CL_SUCCESS);
+ m_gpuData->m_writeBackVelocitiesKernel = b3OpenCLUtils::compileCLKernelFromString(m_gpuData->m_context,m_gpuData->m_device,solveConstraintRowsCL,"writeBackVelocitiesKernel",&errNum,prog);
+ b3Assert(errNum==CL_SUCCESS);
+ m_gpuData->m_breakViolatedConstraintsKernel = b3OpenCLUtils::compileCLKernelFromString(m_gpuData->m_context,m_gpuData->m_device,solveConstraintRowsCL,"breakViolatedConstraintsKernel",&errNum,prog);
+ b3Assert(errNum==CL_SUCCESS);
+
+
+
+
+ clReleaseProgram(prog);
+ }
+
+
+}
+
+b3GpuPgsConstraintSolver::~b3GpuPgsConstraintSolver ()
+{
+ clReleaseKernel(m_gpuData->m_solveJointConstraintRowsKernels);
+ clReleaseKernel(m_gpuData->m_initSolverBodiesKernel);
+ clReleaseKernel(m_gpuData->m_getInfo1Kernel);
+ clReleaseKernel(m_gpuData->m_initBatchConstraintsKernel);
+ clReleaseKernel(m_gpuData->m_getInfo2Kernel);
+ clReleaseKernel(m_gpuData->m_writeBackVelocitiesKernel);
+ clReleaseKernel(m_gpuData->m_breakViolatedConstraintsKernel);
+
+ delete m_gpuData->m_prefixScan;
+ delete m_gpuData->m_gpuConstraintRowOffsets;
+ delete m_gpuData->m_gpuSolverBodies;
+ delete m_gpuData->m_gpuBatchConstraints;
+ delete m_gpuData->m_gpuConstraintRows;
+ delete m_gpuData->m_gpuConstraintInfo1;
+
+ delete m_gpuData;
+}
+
+struct b3BatchConstraint
+{
+ int m_bodyAPtrAndSignBit;
+ int m_bodyBPtrAndSignBit;
+ int m_originalConstraintIndex;
+ int m_batchId;
+};
+
+static b3AlignedObjectArray<b3BatchConstraint> batchConstraints;
+
+
+void b3GpuPgsConstraintSolver::recomputeBatches()
+{
+ m_gpuData->m_batchSizes.clear();
+}
+
+
+
+
+b3Scalar b3GpuPgsConstraintSolver::solveGroupCacheFriendlySetup(b3OpenCLArray<b3RigidBodyData>* gpuBodies, b3OpenCLArray<b3InertiaData>* gpuInertias, int numBodies, b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints,int numConstraints,const b3ContactSolverInfo& infoGlobal)
+{
+ B3_PROFILE("GPU solveGroupCacheFriendlySetup");
+ batchConstraints.resize(numConstraints);
+ m_gpuData->m_gpuBatchConstraints->resize(numConstraints);
+ m_staticIdx = -1;
+ m_maxOverrideNumSolverIterations = 0;
+
+
+ /* m_gpuData->m_gpuBodies->resize(numBodies);
+ m_gpuData->m_gpuBodies->copyFromHostPointer(bodies,numBodies);
+
+ b3OpenCLArray<b3InertiaData> gpuInertias(m_gpuData->m_context,m_gpuData->m_queue);
+ gpuInertias.resize(numBodies);
+ gpuInertias.copyFromHostPointer(inertias,numBodies);
+ */
+
+ m_gpuData->m_gpuSolverBodies->resize(numBodies);
+
+
+ m_tmpSolverBodyPool.resize(numBodies);
+ {
+
+ if (useGpuInitSolverBodies)
+ {
+ B3_PROFILE("m_initSolverBodiesKernel");
+
+ b3LauncherCL launcher(m_gpuData->m_queue,m_gpuData->m_initSolverBodiesKernel,"m_initSolverBodiesKernel");
+ launcher.setBuffer(m_gpuData->m_gpuSolverBodies->getBufferCL());
+ launcher.setBuffer(gpuBodies->getBufferCL());
+ launcher.setConst(numBodies);
+ launcher.launch1D(numBodies);
+ clFinish(m_gpuData->m_queue);
+
+ // m_gpuData->m_gpuSolverBodies->copyToHost(m_tmpSolverBodyPool);
+ } else
+ {
+ gpuBodies->copyToHost(m_gpuData->m_cpuBodies);
+ for (int i=0;i<numBodies;i++)
+ {
+
+ b3RigidBodyData& body = m_gpuData->m_cpuBodies[i];
+ b3GpuSolverBody& solverBody = m_tmpSolverBodyPool[i];
+ initSolverBody(i,&solverBody,&body);
+ solverBody.m_originalBodyIndex = i;
+ }
+ m_gpuData->m_gpuSolverBodies->copyFromHost(m_tmpSolverBodyPool);
+ }
+ }
+
+// int totalBodies = 0;
+ int totalNumRows = 0;
+ //b3RigidBody* rb0=0,*rb1=0;
+ //if (1)
+ {
+ {
+
+
+ // int i;
+
+ m_tmpConstraintSizesPool.resizeNoInitialize(numConstraints);
+
+ // b3OpenCLArray<b3GpuGenericConstraint> gpuConstraints(m_gpuData->m_context,m_gpuData->m_queue);
+
+
+ if (useGpuInfo1)
+ {
+ B3_PROFILE("info1 and init batchConstraint");
+
+ m_gpuData->m_gpuConstraintInfo1->resize(numConstraints);
+
+
+ if (1)
+ {
+ B3_PROFILE("getInfo1Kernel");
+
+ b3LauncherCL launcher(m_gpuData->m_queue,m_gpuData->m_getInfo1Kernel,"m_getInfo1Kernel");
+ launcher.setBuffer(m_gpuData->m_gpuConstraintInfo1->getBufferCL());
+ launcher.setBuffer(gpuConstraints->getBufferCL());
+ launcher.setConst(numConstraints);
+ launcher.launch1D(numConstraints);
+ clFinish(m_gpuData->m_queue);
+ }
+
+ if (m_gpuData->m_batchSizes.size()==0)
+ {
+ B3_PROFILE("initBatchConstraintsKernel");
+
+ m_gpuData->m_gpuConstraintRowOffsets->resize(numConstraints);
+ unsigned int total=0;
+ m_gpuData->m_prefixScan->execute(*m_gpuData->m_gpuConstraintInfo1,*m_gpuData->m_gpuConstraintRowOffsets,numConstraints,&total);
+ unsigned int lastElem = m_gpuData->m_gpuConstraintInfo1->at(numConstraints-1);
+ totalNumRows = total+lastElem;
+
+ {
+ B3_PROFILE("init batch constraints");
+ b3LauncherCL launcher(m_gpuData->m_queue,m_gpuData->m_initBatchConstraintsKernel,"m_initBatchConstraintsKernel");
+ launcher.setBuffer(m_gpuData->m_gpuConstraintInfo1->getBufferCL());
+ launcher.setBuffer(m_gpuData->m_gpuConstraintRowOffsets->getBufferCL());
+ launcher.setBuffer(m_gpuData->m_gpuBatchConstraints->getBufferCL());
+ launcher.setBuffer(gpuConstraints->getBufferCL());
+ launcher.setBuffer(gpuBodies->getBufferCL());
+ launcher.setConst(numConstraints);
+ launcher.launch1D(numConstraints);
+ clFinish(m_gpuData->m_queue);
+ }
+ //assume the batching happens on CPU, so copy the data
+ m_gpuData->m_gpuBatchConstraints->copyToHost(batchConstraints);
+ }
+ }
+ else
+ {
+ totalNumRows = 0;
+ gpuConstraints->copyToHost(m_gpuData->m_cpuConstraints);
+ //calculate the total number of contraint rows
+ for (int i=0;i<numConstraints;i++)
+ {
+ unsigned int& info1= m_tmpConstraintSizesPool[i];
+ // unsigned int info1;
+ if (m_gpuData->m_cpuConstraints[i].isEnabled())
+ {
+
+ m_gpuData->m_cpuConstraints[i].getInfo1(&info1,&m_gpuData->m_cpuBodies[0]);
+ } else
+ {
+ info1 = 0;
+ }
+
+ totalNumRows += info1;
+ }
+
+ m_gpuData->m_gpuBatchConstraints->copyFromHost(batchConstraints);
+ m_gpuData->m_gpuConstraintInfo1->copyFromHost(m_tmpConstraintSizesPool);
+
+ }
+ m_tmpSolverNonContactConstraintPool.resizeNoInitialize(totalNumRows);
+ m_gpuData->m_gpuConstraintRows->resize(totalNumRows);
+
+ // b3GpuConstraintArray verify;
+
+ if (useGpuInfo2)
+ {
+ {
+ B3_PROFILE("getInfo2Kernel");
+ b3LauncherCL launcher(m_gpuData->m_queue,m_gpuData->m_getInfo2Kernel,"m_getInfo2Kernel");
+ launcher.setBuffer(m_gpuData->m_gpuConstraintRows->getBufferCL());
+ launcher.setBuffer(m_gpuData->m_gpuConstraintInfo1->getBufferCL());
+ launcher.setBuffer(m_gpuData->m_gpuConstraintRowOffsets->getBufferCL());
+ launcher.setBuffer(gpuConstraints->getBufferCL());
+ launcher.setBuffer(m_gpuData->m_gpuBatchConstraints->getBufferCL());
+ launcher.setBuffer(gpuBodies->getBufferCL());
+ launcher.setBuffer(gpuInertias->getBufferCL());
+ launcher.setBuffer(m_gpuData->m_gpuSolverBodies->getBufferCL());
+ launcher.setConst(infoGlobal.m_timeStep);
+ launcher.setConst(infoGlobal.m_erp);
+ launcher.setConst(infoGlobal.m_globalCfm);
+ launcher.setConst(infoGlobal.m_damping);
+ launcher.setConst(infoGlobal.m_numIterations);
+ launcher.setConst(numConstraints);
+ launcher.launch1D(numConstraints);
+ clFinish(m_gpuData->m_queue);
+
+ if (m_gpuData->m_batchSizes.size()==0)
+ m_gpuData->m_gpuBatchConstraints->copyToHost(batchConstraints);
+ //m_gpuData->m_gpuConstraintRows->copyToHost(verify);
+ //m_gpuData->m_gpuConstraintRows->copyToHost(m_tmpSolverNonContactConstraintPool);
+
+
+
+ }
+ }
+ else
+ {
+
+ gpuInertias->copyToHost(m_gpuData->m_cpuInertias);
+
+ ///setup the b3SolverConstraints
+
+ for (int i=0;i<numConstraints;i++)
+ {
+ const int& info1 = m_tmpConstraintSizesPool[i];
+
+ if (info1)
+ {
+ int constraintIndex = batchConstraints[i].m_originalConstraintIndex;
+ int constraintRowOffset = m_gpuData->m_cpuConstraintRowOffsets[constraintIndex];
+
+ b3GpuSolverConstraint* currentConstraintRow = &m_tmpSolverNonContactConstraintPool[constraintRowOffset];
+ b3GpuGenericConstraint& constraint = m_gpuData->m_cpuConstraints[i];
+
+ b3RigidBodyData& rbA = m_gpuData->m_cpuBodies[ constraint.getRigidBodyA()];
+ //b3RigidBody& rbA = constraint.getRigidBodyA();
+ // b3RigidBody& rbB = constraint.getRigidBodyB();
+ b3RigidBodyData& rbB = m_gpuData->m_cpuBodies[ constraint.getRigidBodyB()];
+
+
+
+ int solverBodyIdA = constraint.getRigidBodyA();//getOrInitSolverBody(constraint.getRigidBodyA(),bodies,inertias);
+ int solverBodyIdB = constraint.getRigidBodyB();//getOrInitSolverBody(constraint.getRigidBodyB(),bodies,inertias);
+
+ b3GpuSolverBody* bodyAPtr = &m_tmpSolverBodyPool[solverBodyIdA];
+ b3GpuSolverBody* bodyBPtr = &m_tmpSolverBodyPool[solverBodyIdB];
+
+ if (rbA.m_invMass)
+ {
+ batchConstraints[i].m_bodyAPtrAndSignBit = solverBodyIdA;
+ } else
+ {
+ if (!solverBodyIdA)
+ m_staticIdx = 0;
+ batchConstraints[i].m_bodyAPtrAndSignBit = -solverBodyIdA;
+ }
+
+ if (rbB.m_invMass)
+ {
+ batchConstraints[i].m_bodyBPtrAndSignBit = solverBodyIdB;
+ } else
+ {
+ if (!solverBodyIdB)
+ m_staticIdx = 0;
+ batchConstraints[i].m_bodyBPtrAndSignBit = -solverBodyIdB;
+ }
+
+
+ int overrideNumSolverIterations = 0;//constraint->getOverrideNumSolverIterations() > 0 ? constraint->getOverrideNumSolverIterations() : infoGlobal.m_numIterations;
+ if (overrideNumSolverIterations>m_maxOverrideNumSolverIterations)
+ m_maxOverrideNumSolverIterations = overrideNumSolverIterations;
+
+
+ int j;
+ for ( j=0;j<info1;j++)
+ {
+ memset(&currentConstraintRow[j],0,sizeof(b3GpuSolverConstraint));
+ currentConstraintRow[j].m_angularComponentA.setValue(0,0,0);
+ currentConstraintRow[j].m_angularComponentB.setValue(0,0,0);
+ currentConstraintRow[j].m_appliedImpulse = 0.f;
+ currentConstraintRow[j].m_appliedPushImpulse = 0.f;
+ currentConstraintRow[j].m_cfm = 0.f;
+ currentConstraintRow[j].m_contactNormal.setValue(0,0,0);
+ currentConstraintRow[j].m_friction = 0.f;
+ currentConstraintRow[j].m_frictionIndex = 0;
+ currentConstraintRow[j].m_jacDiagABInv = 0.f;
+ currentConstraintRow[j].m_lowerLimit = 0.f;
+ currentConstraintRow[j].m_upperLimit = 0.f;
+
+ currentConstraintRow[j].m_originalContactPoint = 0;
+ currentConstraintRow[j].m_overrideNumSolverIterations = 0;
+ currentConstraintRow[j].m_relpos1CrossNormal.setValue(0,0,0);
+ currentConstraintRow[j].m_relpos2CrossNormal.setValue(0,0,0);
+ currentConstraintRow[j].m_rhs = 0.f;
+ currentConstraintRow[j].m_rhsPenetration = 0.f;
+ currentConstraintRow[j].m_solverBodyIdA = 0;
+ currentConstraintRow[j].m_solverBodyIdB = 0;
+
+ currentConstraintRow[j].m_lowerLimit = -B3_INFINITY;
+ currentConstraintRow[j].m_upperLimit = B3_INFINITY;
+ currentConstraintRow[j].m_appliedImpulse = 0.f;
+ currentConstraintRow[j].m_appliedPushImpulse = 0.f;
+ currentConstraintRow[j].m_solverBodyIdA = solverBodyIdA;
+ currentConstraintRow[j].m_solverBodyIdB = solverBodyIdB;
+ currentConstraintRow[j].m_overrideNumSolverIterations = overrideNumSolverIterations;
+ }
+
+ bodyAPtr->internalGetDeltaLinearVelocity().setValue(0.f,0.f,0.f);
+ bodyAPtr->internalGetDeltaAngularVelocity().setValue(0.f,0.f,0.f);
+ bodyAPtr->internalGetPushVelocity().setValue(0.f,0.f,0.f);
+ bodyAPtr->internalGetTurnVelocity().setValue(0.f,0.f,0.f);
+ bodyBPtr->internalGetDeltaLinearVelocity().setValue(0.f,0.f,0.f);
+ bodyBPtr->internalGetDeltaAngularVelocity().setValue(0.f,0.f,0.f);
+ bodyBPtr->internalGetPushVelocity().setValue(0.f,0.f,0.f);
+ bodyBPtr->internalGetTurnVelocity().setValue(0.f,0.f,0.f);
+
+
+ b3GpuConstraintInfo2 info2;
+ info2.fps = 1.f/infoGlobal.m_timeStep;
+ info2.erp = infoGlobal.m_erp;
+ info2.m_J1linearAxis = currentConstraintRow->m_contactNormal;
+ info2.m_J1angularAxis = currentConstraintRow->m_relpos1CrossNormal;
+ info2.m_J2linearAxis = 0;
+ info2.m_J2angularAxis = currentConstraintRow->m_relpos2CrossNormal;
+ info2.rowskip = sizeof(b3GpuSolverConstraint)/sizeof(b3Scalar);//check this
+ ///the size of b3GpuSolverConstraint needs be a multiple of b3Scalar
+ b3Assert(info2.rowskip*sizeof(b3Scalar)== sizeof(b3GpuSolverConstraint));
+ info2.m_constraintError = &currentConstraintRow->m_rhs;
+ currentConstraintRow->m_cfm = infoGlobal.m_globalCfm;
+ info2.m_damping = infoGlobal.m_damping;
+ info2.cfm = &currentConstraintRow->m_cfm;
+ info2.m_lowerLimit = &currentConstraintRow->m_lowerLimit;
+ info2.m_upperLimit = &currentConstraintRow->m_upperLimit;
+ info2.m_numIterations = infoGlobal.m_numIterations;
+ m_gpuData->m_cpuConstraints[i].getInfo2(&info2,&m_gpuData->m_cpuBodies[0]);
+
+ ///finalize the constraint setup
+ for ( j=0;j<info1;j++)
+ {
+ b3GpuSolverConstraint& solverConstraint = currentConstraintRow[j];
+
+ if (solverConstraint.m_upperLimit>=m_gpuData->m_cpuConstraints[i].getBreakingImpulseThreshold())
+ {
+ solverConstraint.m_upperLimit = m_gpuData->m_cpuConstraints[i].getBreakingImpulseThreshold();
+ }
+
+ if (solverConstraint.m_lowerLimit<=-m_gpuData->m_cpuConstraints[i].getBreakingImpulseThreshold())
+ {
+ solverConstraint.m_lowerLimit = -m_gpuData->m_cpuConstraints[i].getBreakingImpulseThreshold();
+ }
+
+ // solverConstraint.m_originalContactPoint = constraint;
+
+ b3Matrix3x3& invInertiaWorldA= m_gpuData->m_cpuInertias[constraint.getRigidBodyA()].m_invInertiaWorld;
+ {
+
+ //b3Vector3 angularFactorA(1,1,1);
+ const b3Vector3& ftorqueAxis1 = solverConstraint.m_relpos1CrossNormal;
+ solverConstraint.m_angularComponentA = invInertiaWorldA*ftorqueAxis1;//*angularFactorA;
+ }
+
+ b3Matrix3x3& invInertiaWorldB= m_gpuData->m_cpuInertias[constraint.getRigidBodyB()].m_invInertiaWorld;
+ {
+
+ const b3Vector3& ftorqueAxis2 = solverConstraint.m_relpos2CrossNormal;
+ solverConstraint.m_angularComponentB = invInertiaWorldB*ftorqueAxis2;//*constraint.getRigidBodyB().getAngularFactor();
+ }
+
+ {
+ //it is ok to use solverConstraint.m_contactNormal instead of -solverConstraint.m_contactNormal
+ //because it gets multiplied iMJlB
+ b3Vector3 iMJlA = solverConstraint.m_contactNormal*rbA.m_invMass;
+ b3Vector3 iMJaA = invInertiaWorldA*solverConstraint.m_relpos1CrossNormal;
+ b3Vector3 iMJlB = solverConstraint.m_contactNormal*rbB.m_invMass;//sign of normal?
+ b3Vector3 iMJaB = invInertiaWorldB*solverConstraint.m_relpos2CrossNormal;
+
+ b3Scalar sum = iMJlA.dot(solverConstraint.m_contactNormal);
+ sum += iMJaA.dot(solverConstraint.m_relpos1CrossNormal);
+ sum += iMJlB.dot(solverConstraint.m_contactNormal);
+ sum += iMJaB.dot(solverConstraint.m_relpos2CrossNormal);
+ b3Scalar fsum = b3Fabs(sum);
+ b3Assert(fsum > B3_EPSILON);
+ solverConstraint.m_jacDiagABInv = fsum>B3_EPSILON?b3Scalar(1.)/sum : 0.f;
+ }
+
+
+ ///fix rhs
+ ///todo: add force/torque accelerators
+ {
+ b3Scalar rel_vel;
+ b3Scalar vel1Dotn = solverConstraint.m_contactNormal.dot(rbA.m_linVel) + solverConstraint.m_relpos1CrossNormal.dot(rbA.m_angVel);
+ b3Scalar vel2Dotn = -solverConstraint.m_contactNormal.dot(rbB.m_linVel) + solverConstraint.m_relpos2CrossNormal.dot(rbB.m_angVel);
+
+ rel_vel = vel1Dotn+vel2Dotn;
+
+ b3Scalar restitution = 0.f;
+ b3Scalar positionalError = solverConstraint.m_rhs;//already filled in by getConstraintInfo2
+ b3Scalar velocityError = restitution - rel_vel * info2.m_damping;
+ b3Scalar penetrationImpulse = positionalError*solverConstraint.m_jacDiagABInv;
+ b3Scalar velocityImpulse = velocityError *solverConstraint.m_jacDiagABInv;
+ solverConstraint.m_rhs = penetrationImpulse+velocityImpulse;
+ solverConstraint.m_appliedImpulse = 0.f;
+
+ }
+ }
+
+ }
+ }
+
+
+
+ m_gpuData->m_gpuConstraintRows->copyFromHost(m_tmpSolverNonContactConstraintPool);
+ m_gpuData->m_gpuConstraintInfo1->copyFromHost(m_tmpConstraintSizesPool);
+
+ if (m_gpuData->m_batchSizes.size()==0)
+ m_gpuData->m_gpuBatchConstraints->copyFromHost(batchConstraints);
+ else
+ m_gpuData->m_gpuBatchConstraints->copyToHost(batchConstraints);
+
+ m_gpuData->m_gpuSolverBodies->copyFromHost(m_tmpSolverBodyPool);
+
+
+
+ }//end useGpuInfo2
+
+
+ }
+
+#ifdef B3_SUPPORT_CONTACT_CONSTRAINTS
+ {
+ int i;
+
+ for (i=0;i<numManifolds;i++)
+ {
+ b3Contact4& manifold = manifoldPtr[i];
+ convertContact(bodies,inertias,&manifold,infoGlobal);
+ }
+ }
+#endif //B3_SUPPORT_CONTACT_CONSTRAINTS
+ }
+
+// b3ContactSolverInfo info = infoGlobal;
+
+
+// int numNonContactPool = m_tmpSolverNonContactConstraintPool.size();
+// int numConstraintPool = m_tmpSolverContactConstraintPool.size();
+// int numFrictionPool = m_tmpSolverContactFrictionConstraintPool.size();
+
+
+ return 0.f;
+
+}
+
+
+
+///a straight copy from GPU/OpenCL kernel, for debugging
+__inline void internalApplyImpulse( b3GpuSolverBody* body, const b3Vector3& linearComponent, const b3Vector3& angularComponent,float impulseMagnitude)
+{
+ body->m_deltaLinearVelocity += linearComponent*impulseMagnitude*body->m_linearFactor;
+ body->m_deltaAngularVelocity += angularComponent*(impulseMagnitude*body->m_angularFactor);
+}
+
+
+void resolveSingleConstraintRowGeneric2( b3GpuSolverBody* body1, b3GpuSolverBody* body2, b3GpuSolverConstraint* c)
+{
+ float deltaImpulse = c->m_rhs-b3Scalar(c->m_appliedImpulse)*c->m_cfm;
+ float deltaVel1Dotn = b3Dot(c->m_contactNormal,body1->m_deltaLinearVelocity) + b3Dot(c->m_relpos1CrossNormal,body1->m_deltaAngularVelocity);
+ float deltaVel2Dotn = -b3Dot(c->m_contactNormal,body2->m_deltaLinearVelocity) + b3Dot(c->m_relpos2CrossNormal,body2->m_deltaAngularVelocity);
+
+ deltaImpulse -= deltaVel1Dotn*c->m_jacDiagABInv;
+ deltaImpulse -= deltaVel2Dotn*c->m_jacDiagABInv;
+
+ float sum = b3Scalar(c->m_appliedImpulse) + deltaImpulse;
+ if (sum < c->m_lowerLimit)
+ {
+ deltaImpulse = c->m_lowerLimit-b3Scalar(c->m_appliedImpulse);
+ c->m_appliedImpulse = c->m_lowerLimit;
+ }
+ else if (sum > c->m_upperLimit)
+ {
+ deltaImpulse = c->m_upperLimit-b3Scalar(c->m_appliedImpulse);
+ c->m_appliedImpulse = c->m_upperLimit;
+ }
+ else
+ {
+ c->m_appliedImpulse = sum;
+ }
+
+ internalApplyImpulse(body1,c->m_contactNormal*body1->m_invMass,c->m_angularComponentA,deltaImpulse);
+ internalApplyImpulse(body2,-c->m_contactNormal*body2->m_invMass,c->m_angularComponentB,deltaImpulse);
+
+}
+
+
+
+void b3GpuPgsConstraintSolver::initSolverBody(int bodyIndex, b3GpuSolverBody* solverBody, b3RigidBodyData* rb)
+{
+
+ solverBody->m_deltaLinearVelocity.setValue(0.f,0.f,0.f);
+ solverBody->m_deltaAngularVelocity.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);
+
+ b3Assert(rb);
+// solverBody->m_worldTransform = getWorldTransform(rb);
+ solverBody->internalSetInvMass(b3MakeVector3(rb->m_invMass,rb->m_invMass,rb->m_invMass));
+ solverBody->m_originalBodyIndex = bodyIndex;
+ solverBody->m_angularFactor = b3MakeVector3(1,1,1);
+ solverBody->m_linearFactor = b3MakeVector3(1,1,1);
+ solverBody->m_linearVelocity = getLinearVelocity(rb);
+ solverBody->m_angularVelocity = getAngularVelocity(rb);
+}
+
+
+void b3GpuPgsConstraintSolver::averageVelocities()
+{
+}
+
+
+b3Scalar b3GpuPgsConstraintSolver::solveGroupCacheFriendlyIterations(b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints1,int numConstraints,const b3ContactSolverInfo& infoGlobal)
+{
+ //only create the batches once.
+ //@todo: incrementally update batches when constraints are added/activated and/or removed/deactivated
+ B3_PROFILE("GpuSolveGroupCacheFriendlyIterations");
+
+ bool createBatches = m_gpuData->m_batchSizes.size()==0;
+ {
+
+ if (createBatches)
+ {
+
+ m_gpuData->m_batchSizes.resize(0);
+
+ {
+ m_gpuData->m_gpuBatchConstraints->copyToHost(batchConstraints);
+
+ B3_PROFILE("batch joints");
+ b3Assert(batchConstraints.size()==numConstraints);
+ int simdWidth =numConstraints+1;
+ int numBodies = m_tmpSolverBodyPool.size();
+ sortConstraintByBatch3( &batchConstraints[0], numConstraints, simdWidth , m_staticIdx, numBodies);
+
+ m_gpuData->m_gpuBatchConstraints->copyFromHost(batchConstraints);
+
+ }
+ } else
+ {
+ /*b3AlignedObjectArray<b3BatchConstraint> cpuCheckBatches;
+ m_gpuData->m_gpuBatchConstraints->copyToHost(cpuCheckBatches);
+ b3Assert(cpuCheckBatches.size()==batchConstraints.size());
+ printf(".\n");
+ */
+ //>copyFromHost(batchConstraints);
+ }
+ int maxIterations = infoGlobal.m_numIterations;
+
+ bool useBatching = true;
+
+ if (useBatching )
+ {
+
+ if (!useGpuSolveJointConstraintRows)
+ {
+ B3_PROFILE("copy to host");
+ m_gpuData->m_gpuSolverBodies->copyToHost(m_tmpSolverBodyPool);
+ m_gpuData->m_gpuBatchConstraints->copyToHost(batchConstraints);
+ m_gpuData->m_gpuConstraintRows->copyToHost(m_tmpSolverNonContactConstraintPool);
+ m_gpuData->m_gpuConstraintInfo1->copyToHost(m_gpuData->m_cpuConstraintInfo1);
+ m_gpuData->m_gpuConstraintRowOffsets->copyToHost(m_gpuData->m_cpuConstraintRowOffsets);
+ gpuConstraints1->copyToHost(m_gpuData->m_cpuConstraints);
+
+ }
+
+ for ( int iteration = 0 ; iteration< maxIterations ; iteration++)
+ {
+
+ int batchOffset = 0;
+ int constraintOffset=0;
+ int numBatches = m_gpuData->m_batchSizes.size();
+ for (int bb=0;bb<numBatches;bb++)
+ {
+ int numConstraintsInBatch = m_gpuData->m_batchSizes[bb];
+
+
+ if (useGpuSolveJointConstraintRows)
+ {
+ B3_PROFILE("solveJointConstraintRowsKernels");
+
+ /*
+ __kernel void solveJointConstraintRows(__global b3GpuSolverBody* solverBodies,
+ __global b3BatchConstraint* batchConstraints,
+ __global b3SolverConstraint* rows,
+ __global unsigned int* numConstraintRowsInfo1,
+ __global unsigned int* rowOffsets,
+ __global b3GpuGenericConstraint* constraints,
+ int batchOffset,
+ int numConstraintsInBatch*/
+
+
+ b3LauncherCL launcher(m_gpuData->m_queue,m_gpuData->m_solveJointConstraintRowsKernels,"m_solveJointConstraintRowsKernels");
+ launcher.setBuffer(m_gpuData->m_gpuSolverBodies->getBufferCL());
+ launcher.setBuffer(m_gpuData->m_gpuBatchConstraints->getBufferCL());
+ launcher.setBuffer(m_gpuData->m_gpuConstraintRows->getBufferCL());
+ launcher.setBuffer(m_gpuData->m_gpuConstraintInfo1->getBufferCL());
+ launcher.setBuffer(m_gpuData->m_gpuConstraintRowOffsets->getBufferCL());
+ launcher.setBuffer(gpuConstraints1->getBufferCL());//to detect disabled constraints
+ launcher.setConst(batchOffset);
+ launcher.setConst(numConstraintsInBatch);
+
+ launcher.launch1D(numConstraintsInBatch);
+
+
+ } else//useGpu
+ {
+
+
+
+ for (int b=0;b<numConstraintsInBatch;b++)
+ {
+ const b3BatchConstraint& c = batchConstraints[batchOffset+b];
+ /*printf("-----------\n");
+ printf("bb=%d\n",bb);
+ printf("c.batchId = %d\n", c.m_batchId);
+ */
+ b3Assert(c.m_batchId==bb);
+ b3GpuGenericConstraint* constraint = &m_gpuData->m_cpuConstraints[c.m_originalConstraintIndex];
+ if (constraint->m_flags&B3_CONSTRAINT_FLAG_ENABLED)
+ {
+ int numConstraintRows = m_gpuData->m_cpuConstraintInfo1[c.m_originalConstraintIndex];
+ int constraintOffset = m_gpuData->m_cpuConstraintRowOffsets[c.m_originalConstraintIndex];
+
+ for (int jj=0;jj<numConstraintRows;jj++)
+ {
+ //
+ b3GpuSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[constraintOffset+jj];
+ //resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[constraint.m_solverBodyIdA],m_tmpSolverBodyPool[constraint.m_solverBodyIdB],constraint);
+ resolveSingleConstraintRowGeneric2(&m_tmpSolverBodyPool[constraint.m_solverBodyIdA],&m_tmpSolverBodyPool[constraint.m_solverBodyIdB],&constraint);
+ }
+ }
+ }
+ }//useGpu
+ batchOffset+=numConstraintsInBatch;
+ constraintOffset+=numConstraintsInBatch;
+ }
+ }//for (int iteration...
+
+ if (!useGpuSolveJointConstraintRows)
+ {
+ {
+ B3_PROFILE("copy from host");
+ m_gpuData->m_gpuSolverBodies->copyFromHost(m_tmpSolverBodyPool);
+ m_gpuData->m_gpuBatchConstraints->copyFromHost(batchConstraints);
+ m_gpuData->m_gpuConstraintRows->copyFromHost(m_tmpSolverNonContactConstraintPool);
+ }
+
+ //B3_PROFILE("copy to host");
+ //m_gpuData->m_gpuSolverBodies->copyToHost(m_tmpSolverBodyPool);
+ }
+ //int sz = sizeof(b3GpuSolverBody);
+ //printf("cpu sizeof(b3GpuSolverBody)=%d\n",sz);
+
+
+
+
+
+ } else
+ {
+ for ( int iteration = 0 ; iteration< maxIterations ; iteration++)
+ {
+ int numJoints = m_tmpSolverNonContactConstraintPool.size();
+ for (int j=0;j<numJoints;j++)
+ {
+ b3GpuSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[j];
+ resolveSingleConstraintRowGeneric2(&m_tmpSolverBodyPool[constraint.m_solverBodyIdA],&m_tmpSolverBodyPool[constraint.m_solverBodyIdB],&constraint);
+ }
+
+ if (!m_usePgs)
+ {
+ averageVelocities();
+ }
+ }
+ }
+
+ }
+ clFinish(m_gpuData->m_queue);
+ return 0.f;
+}
+
+
+
+
+static b3AlignedObjectArray<int> bodyUsed;
+static b3AlignedObjectArray<int> curUsed;
+
+
+
+inline int b3GpuPgsConstraintSolver::sortConstraintByBatch3( b3BatchConstraint* cs, int numConstraints, int simdWidth , int staticIdx, int numBodies)
+{
+ //int sz = sizeof(b3BatchConstraint);
+
+ B3_PROFILE("sortConstraintByBatch3");
+
+ static int maxSwaps = 0;
+ int numSwaps = 0;
+
+ curUsed.resize(2*simdWidth);
+
+ static int maxNumConstraints = 0;
+ if (maxNumConstraints<numConstraints)
+ {
+ maxNumConstraints = numConstraints;
+ //printf("maxNumConstraints = %d\n",maxNumConstraints );
+ }
+
+ int numUsedArray = numBodies/32+1;
+ bodyUsed.resize(numUsedArray);
+
+ for (int q=0;q<numUsedArray;q++)
+ bodyUsed[q]=0;
+
+
+ int curBodyUsed = 0;
+
+ int numIter = 0;
+
+
+#if defined(_DEBUG)
+ for(int i=0; i<numConstraints; i++)
+ cs[i].m_batchId = -1;
+#endif
+
+ int numValidConstraints = 0;
+// int unprocessedConstraintIndex = 0;
+
+ int batchIdx = 0;
+
+
+ {
+ B3_PROFILE("cpu batch innerloop");
+
+ while( numValidConstraints < numConstraints)
+ {
+ numIter++;
+ int nCurrentBatch = 0;
+ // clear flag
+ for(int i=0; i<curBodyUsed; i++)
+ bodyUsed[curUsed[i]/32] = 0;
+
+ curBodyUsed = 0;
+
+ for(int i=numValidConstraints; i<numConstraints; i++)
+ {
+ int idx = i;
+ b3Assert( idx < numConstraints );
+ // check if it can go
+ int bodyAS = cs[idx].m_bodyAPtrAndSignBit;
+ int bodyBS = cs[idx].m_bodyBPtrAndSignBit;
+ int bodyA = abs(bodyAS);
+ int bodyB = abs(bodyBS);
+ bool aIsStatic = (bodyAS<0) || bodyAS==staticIdx;
+ bool bIsStatic = (bodyBS<0) || bodyBS==staticIdx;
+ int aUnavailable = 0;
+ int bUnavailable = 0;
+ if (!aIsStatic)
+ {
+ aUnavailable = bodyUsed[ bodyA/32 ] & (1<<(bodyA&31));
+ }
+ if (!aUnavailable)
+ if (!bIsStatic)
+ {
+ bUnavailable = bodyUsed[ bodyB/32 ] & (1<<(bodyB&31));
+ }
+
+ if( aUnavailable==0 && bUnavailable==0 ) // ok
+ {
+ if (!aIsStatic)
+ {
+ bodyUsed[ bodyA/32 ] |= (1<<(bodyA&31));
+ curUsed[curBodyUsed++]=bodyA;
+ }
+ if (!bIsStatic)
+ {
+ bodyUsed[ bodyB/32 ] |= (1<<(bodyB&31));
+ curUsed[curBodyUsed++]=bodyB;
+ }
+
+ cs[idx].m_batchId = batchIdx;
+
+ if (i!=numValidConstraints)
+ {
+ b3Swap(cs[i],cs[numValidConstraints]);
+ numSwaps++;
+ }
+
+ numValidConstraints++;
+ {
+ nCurrentBatch++;
+ if( nCurrentBatch == simdWidth )
+ {
+ nCurrentBatch = 0;
+ for(int i=0; i<curBodyUsed; i++)
+ bodyUsed[curUsed[i]/32] = 0;
+ curBodyUsed = 0;
+ }
+ }
+ }
+ }
+ m_gpuData->m_batchSizes.push_back(nCurrentBatch);
+ batchIdx ++;
+ }
+ }
+
+#if defined(_DEBUG)
+ // debugPrintf( "nBatches: %d\n", batchIdx );
+ for(int i=0; i<numConstraints; i++)
+ {
+ b3Assert( cs[i].m_batchId != -1 );
+ }
+#endif
+
+ if (maxSwaps<numSwaps)
+ {
+ maxSwaps = numSwaps;
+ //printf("maxSwaps = %d\n", maxSwaps);
+ }
+
+ return batchIdx;
+}
+
+
+/// b3PgsJacobiSolver Sequentially applies impulses
+b3Scalar b3GpuPgsConstraintSolver::solveGroup(b3OpenCLArray<b3RigidBodyData>* gpuBodies, b3OpenCLArray<b3InertiaData>* gpuInertias,
+ int numBodies, b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints,int numConstraints, const b3ContactSolverInfo& infoGlobal)
+{
+
+ B3_PROFILE("solveJoints");
+ //you need to provide at least some bodies
+
+ solveGroupCacheFriendlySetup( gpuBodies, gpuInertias,numBodies,gpuConstraints, numConstraints,infoGlobal);
+
+ solveGroupCacheFriendlyIterations(gpuConstraints, numConstraints,infoGlobal);
+
+ solveGroupCacheFriendlyFinish(gpuBodies, gpuInertias,numBodies, gpuConstraints, numConstraints, infoGlobal);
+
+ return 0.f;
+}
+
+void b3GpuPgsConstraintSolver::solveJoints(int numBodies, b3OpenCLArray<b3RigidBodyData>* gpuBodies, b3OpenCLArray<b3InertiaData>* gpuInertias,
+ int numConstraints, b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints)
+{
+ b3ContactSolverInfo infoGlobal;
+ infoGlobal.m_splitImpulse = false;
+ infoGlobal.m_timeStep = 1.f/60.f;
+ infoGlobal.m_numIterations = 4;//4;
+// infoGlobal.m_solverMode|=B3_SOLVER_USE_2_FRICTION_DIRECTIONS|B3_SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS|B3_SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION;
+ //infoGlobal.m_solverMode|=B3_SOLVER_USE_2_FRICTION_DIRECTIONS|B3_SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS;
+ infoGlobal.m_solverMode|=B3_SOLVER_USE_2_FRICTION_DIRECTIONS;
+
+ //if (infoGlobal.m_solverMode & B3_SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS)
+ //if ((infoGlobal.m_solverMode & B3_SOLVER_USE_2_FRICTION_DIRECTIONS) && (infoGlobal.m_solverMode & B3_SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION))
+
+
+ solveGroup(gpuBodies,gpuInertias,numBodies,gpuConstraints,numConstraints,infoGlobal);
+
+}
+
+//b3AlignedObjectArray<b3RigidBodyData> testBodies;
+
+
+b3Scalar b3GpuPgsConstraintSolver::solveGroupCacheFriendlyFinish(b3OpenCLArray<b3RigidBodyData>* gpuBodies,b3OpenCLArray<b3InertiaData>* gpuInertias,int numBodies,b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints,int numConstraints,const b3ContactSolverInfo& infoGlobal)
+{
+ B3_PROFILE("solveGroupCacheFriendlyFinish");
+// int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
+// int i,j;
+
+
+ {
+ if (gpuBreakConstraints)
+ {
+ B3_PROFILE("breakViolatedConstraintsKernel");
+ b3LauncherCL launcher(m_gpuData->m_queue,m_gpuData->m_breakViolatedConstraintsKernel,"m_breakViolatedConstraintsKernel");
+ launcher.setBuffer(gpuConstraints->getBufferCL());
+ launcher.setBuffer(m_gpuData->m_gpuConstraintInfo1->getBufferCL());
+ launcher.setBuffer(m_gpuData->m_gpuConstraintRowOffsets->getBufferCL());
+ launcher.setBuffer(m_gpuData->m_gpuConstraintRows->getBufferCL());
+ launcher.setConst(numConstraints);
+ launcher.launch1D(numConstraints);
+ } else
+ {
+ gpuConstraints->copyToHost(m_gpuData->m_cpuConstraints);
+ m_gpuData->m_gpuBatchConstraints->copyToHost(m_gpuData->m_cpuBatchConstraints);
+ m_gpuData->m_gpuConstraintRows->copyToHost(m_gpuData->m_cpuConstraintRows);
+ gpuConstraints->copyToHost(m_gpuData->m_cpuConstraints);
+ m_gpuData->m_gpuConstraintInfo1->copyToHost(m_gpuData->m_cpuConstraintInfo1);
+ m_gpuData->m_gpuConstraintRowOffsets->copyToHost(m_gpuData->m_cpuConstraintRowOffsets);
+
+ for (int cid=0;cid<numConstraints;cid++)
+ {
+ int originalConstraintIndex = batchConstraints[cid].m_originalConstraintIndex;
+ int constraintRowOffset = m_gpuData->m_cpuConstraintRowOffsets[originalConstraintIndex];
+ int numRows = m_gpuData->m_cpuConstraintInfo1[originalConstraintIndex];
+ if (numRows)
+ {
+
+ // printf("cid=%d, breakingThreshold =%f\n",cid,breakingThreshold);
+ for (int i=0;i<numRows;i++)
+ {
+ int rowIndex =constraintRowOffset+i;
+ int orgConstraintIndex = m_gpuData->m_cpuConstraintRows[rowIndex].m_originalConstraintIndex;
+ float breakingThreshold = m_gpuData->m_cpuConstraints[orgConstraintIndex].m_breakingImpulseThreshold;
+ // printf("rows[%d].m_appliedImpulse=%f\n",rowIndex,rows[rowIndex].m_appliedImpulse);
+ if (b3Fabs(m_gpuData->m_cpuConstraintRows[rowIndex].m_appliedImpulse) >= breakingThreshold)
+ {
+
+ m_gpuData->m_cpuConstraints[orgConstraintIndex].m_flags =0;//&= ~B3_CONSTRAINT_FLAG_ENABLED;
+ }
+ }
+ }
+ }
+
+
+ gpuConstraints->copyFromHost(m_gpuData->m_cpuConstraints);
+ }
+ }
+
+ {
+ if (useGpuWriteBackVelocities)
+ {
+ B3_PROFILE("GPU write back velocities and transforms");
+
+ b3LauncherCL launcher(m_gpuData->m_queue,m_gpuData->m_writeBackVelocitiesKernel,"m_writeBackVelocitiesKernel");
+ launcher.setBuffer(gpuBodies->getBufferCL());
+ launcher.setBuffer(m_gpuData->m_gpuSolverBodies->getBufferCL());
+ launcher.setConst(numBodies);
+ launcher.launch1D(numBodies);
+ clFinish(m_gpuData->m_queue);
+// m_gpuData->m_gpuSolverBodies->copyToHost(m_tmpSolverBodyPool);
+// m_gpuData->m_gpuBodies->copyToHostPointer(bodies,numBodies);
+ //m_gpuData->m_gpuBodies->copyToHost(testBodies);
+
+ }
+ else
+ {
+ B3_PROFILE("CPU write back velocities and transforms");
+
+ m_gpuData->m_gpuSolverBodies->copyToHost(m_tmpSolverBodyPool);
+ gpuBodies->copyToHost(m_gpuData->m_cpuBodies);
+ for ( int i=0;i<m_tmpSolverBodyPool.size();i++)
+ {
+ int bodyIndex = m_tmpSolverBodyPool[i].m_originalBodyIndex;
+ //printf("bodyIndex=%d\n",bodyIndex);
+ b3Assert(i==bodyIndex);
+
+ b3RigidBodyData* body = &m_gpuData->m_cpuBodies[bodyIndex];
+ if (body->m_invMass)
+ {
+ if (infoGlobal.m_splitImpulse)
+ m_tmpSolverBodyPool[i].writebackVelocityAndTransform(infoGlobal.m_timeStep, infoGlobal.m_splitImpulseTurnErp);
+ else
+ m_tmpSolverBodyPool[i].writebackVelocity();
+
+ if (m_usePgs)
+ {
+ body->m_linVel = m_tmpSolverBodyPool[i].m_linearVelocity;
+ body->m_angVel = m_tmpSolverBodyPool[i].m_angularVelocity;
+ } else
+ {
+ b3Assert(0);
+ }
+ /*
+ if (infoGlobal.m_splitImpulse)
+ {
+ body->m_pos = m_tmpSolverBodyPool[i].m_worldTransform.getOrigin();
+ b3Quaternion orn;
+ orn = m_tmpSolverBodyPool[i].m_worldTransform.getRotation();
+ body->m_quat = orn;
+ }
+ */
+ }
+ }//for
+
+ gpuBodies->copyFromHost(m_gpuData->m_cpuBodies);
+
+ }
+ }
+
+ clFinish(m_gpuData->m_queue);
+
+ m_tmpSolverContactConstraintPool.resizeNoInitialize(0);
+ m_tmpSolverNonContactConstraintPool.resizeNoInitialize(0);
+ m_tmpSolverContactFrictionConstraintPool.resizeNoInitialize(0);
+ m_tmpSolverContactRollingFrictionConstraintPool.resizeNoInitialize(0);
+
+ m_tmpSolverBodyPool.resizeNoInitialize(0);
+ return 0.f;
+}
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuPgsConstraintSolver.h b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuPgsConstraintSolver.h
new file mode 100644
index 0000000000..ec0e3f73d6
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuPgsConstraintSolver.h
@@ -0,0 +1,78 @@
+/*
+Copyright (c) 2013 Advanced Micro Devices, Inc.
+
+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.
+*/
+//Originally written by Erwin Coumans
+
+#ifndef B3_GPU_PGS_CONSTRAINT_SOLVER_H
+#define B3_GPU_PGS_CONSTRAINT_SOLVER_H
+
+struct b3Contact4;
+struct b3ContactPoint;
+
+
+class b3Dispatcher;
+
+#include "Bullet3Dynamics/ConstraintSolver/b3TypedConstraint.h"
+#include "Bullet3Dynamics/ConstraintSolver/b3ContactSolverInfo.h"
+#include "b3GpuSolverBody.h"
+#include "b3GpuSolverConstraint.h"
+#include "Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h"
+struct b3RigidBodyData;
+struct b3InertiaData;
+
+#include "Bullet3OpenCL/Initialize/b3OpenCLInclude.h"
+#include "b3GpuGenericConstraint.h"
+
+class b3GpuPgsConstraintSolver
+{
+protected:
+ int m_staticIdx;
+ struct b3GpuPgsJacobiSolverInternalData* m_gpuData;
+ protected:
+ b3AlignedObjectArray<b3GpuSolverBody> m_tmpSolverBodyPool;
+ b3GpuConstraintArray m_tmpSolverContactConstraintPool;
+ b3GpuConstraintArray m_tmpSolverNonContactConstraintPool;
+ b3GpuConstraintArray m_tmpSolverContactFrictionConstraintPool;
+ b3GpuConstraintArray m_tmpSolverContactRollingFrictionConstraintPool;
+
+ b3AlignedObjectArray<unsigned int> m_tmpConstraintSizesPool;
+
+
+ bool m_usePgs;
+ void averageVelocities();
+
+ int m_maxOverrideNumSolverIterations;
+
+ int m_numSplitImpulseRecoveries;
+
+// int getOrInitSolverBody(int bodyIndex, b3RigidBodyData* bodies,b3InertiaData* inertias);
+ void initSolverBody(int bodyIndex, b3GpuSolverBody* solverBody, b3RigidBodyData* rb);
+
+public:
+ b3GpuPgsConstraintSolver (cl_context ctx, cl_device_id device, cl_command_queue queue,bool usePgs);
+ virtual~b3GpuPgsConstraintSolver ();
+
+ virtual b3Scalar solveGroupCacheFriendlyIterations(b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints1,int numConstraints,const b3ContactSolverInfo& infoGlobal);
+ virtual b3Scalar solveGroupCacheFriendlySetup(b3OpenCLArray<b3RigidBodyData>* gpuBodies, b3OpenCLArray<b3InertiaData>* gpuInertias, int numBodies,b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints,int numConstraints,const b3ContactSolverInfo& infoGlobal);
+ b3Scalar solveGroupCacheFriendlyFinish(b3OpenCLArray<b3RigidBodyData>* gpuBodies,b3OpenCLArray<b3InertiaData>* gpuInertias,int numBodies,b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints,int numConstraints,const b3ContactSolverInfo& infoGlobal);
+
+
+ b3Scalar solveGroup(b3OpenCLArray<b3RigidBodyData>* gpuBodies,b3OpenCLArray<b3InertiaData>* gpuInertias, int numBodies,b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints,int numConstraints,const b3ContactSolverInfo& infoGlobal);
+ void solveJoints(int numBodies, b3OpenCLArray<b3RigidBodyData>* gpuBodies, b3OpenCLArray<b3InertiaData>* gpuInertias,
+ int numConstraints, b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints);
+
+ int sortConstraintByBatch3( struct b3BatchConstraint* cs, int numConstraints, int simdWidth , int staticIdx, int numBodies);
+ void recomputeBatches();
+};
+
+#endif //B3_GPU_PGS_CONSTRAINT_SOLVER_H
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuPgsContactSolver.cpp b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuPgsContactSolver.cpp
new file mode 100644
index 0000000000..f0b0abd5e0
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuPgsContactSolver.cpp
@@ -0,0 +1,1708 @@
+
+bool gUseLargeBatches = false;
+bool gCpuBatchContacts = false;
+bool gCpuSolveConstraint = false;
+bool gCpuRadixSort=false;
+bool gCpuSetSortData = false;
+bool gCpuSortContactsDeterminism = false;
+bool gUseCpuCopyConstraints = false;
+bool gUseScanHost = false;
+bool gReorderContactsOnCpu = false;
+
+bool optionalSortContactsDeterminism = true;
+
+
+#include "b3GpuPgsContactSolver.h"
+#include "Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.h"
+
+#include "Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.h"
+#include "Bullet3OpenCL/ParallelPrimitives/b3BoundSearchCL.h"
+#include "Bullet3OpenCL/ParallelPrimitives/b3PrefixScanCL.h"
+#include <string.h>
+#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
+#include "Bullet3Collision/NarrowPhaseCollision/b3Config.h"
+#include "b3Solver.h"
+
+
+#define B3_SOLVER_SETUP_KERNEL_PATH "src/Bullet3OpenCL/RigidBody/kernels/solverSetup.cl"
+#define B3_SOLVER_SETUP2_KERNEL_PATH "src/Bullet3OpenCL/RigidBody/kernels/solverSetup2.cl"
+#define B3_SOLVER_CONTACT_KERNEL_PATH "src/Bullet3OpenCL/RigidBody/kernels/solveContact.cl"
+#define B3_SOLVER_FRICTION_KERNEL_PATH "src/Bullet3OpenCL/RigidBody/kernels/solveFriction.cl"
+#define B3_BATCHING_PATH "src/Bullet3OpenCL/RigidBody/kernels/batchingKernels.cl"
+#define B3_BATCHING_NEW_PATH "src/Bullet3OpenCL/RigidBody/kernels/batchingKernelsNew.cl"
+
+#include "kernels/solverSetup.h"
+#include "kernels/solverSetup2.h"
+#include "kernels/solveContact.h"
+#include "kernels/solveFriction.h"
+#include "kernels/batchingKernels.h"
+#include "kernels/batchingKernelsNew.h"
+
+
+
+
+
+struct b3GpuBatchingPgsSolverInternalData
+{
+ cl_context m_context;
+ cl_device_id m_device;
+ cl_command_queue m_queue;
+ int m_pairCapacity;
+ int m_nIterations;
+
+ b3OpenCLArray<b3GpuConstraint4>* m_contactCGPU;
+ b3OpenCLArray<unsigned int>* m_numConstraints;
+ b3OpenCLArray<unsigned int>* m_offsets;
+
+ b3Solver* m_solverGPU;
+
+ cl_kernel m_batchingKernel;
+ cl_kernel m_batchingKernelNew;
+ cl_kernel m_solveContactKernel;
+ cl_kernel m_solveSingleContactKernel;
+ cl_kernel m_solveSingleFrictionKernel;
+ cl_kernel m_solveFrictionKernel;
+ cl_kernel m_contactToConstraintKernel;
+ cl_kernel m_setSortDataKernel;
+ cl_kernel m_reorderContactKernel;
+ cl_kernel m_copyConstraintKernel;
+
+ cl_kernel m_setDeterminismSortDataBodyAKernel;
+ cl_kernel m_setDeterminismSortDataBodyBKernel;
+ cl_kernel m_setDeterminismSortDataChildShapeAKernel;
+ cl_kernel m_setDeterminismSortDataChildShapeBKernel;
+
+
+
+
+ class b3RadixSort32CL* m_sort32;
+ class b3BoundSearchCL* m_search;
+ class b3PrefixScanCL* m_scan;
+
+ b3OpenCLArray<b3SortData>* m_sortDataBuffer;
+ b3OpenCLArray<b3Contact4>* m_contactBuffer;
+
+ b3OpenCLArray<b3RigidBodyData>* m_bodyBufferGPU;
+ b3OpenCLArray<b3InertiaData>* m_inertiaBufferGPU;
+ b3OpenCLArray<b3Contact4>* m_pBufContactOutGPU;
+
+ b3OpenCLArray<b3Contact4>* m_pBufContactOutGPUCopy;
+ b3OpenCLArray<b3SortData>* m_contactKeyValues;
+
+
+ b3AlignedObjectArray<unsigned int> m_idxBuffer;
+ b3AlignedObjectArray<b3SortData> m_sortData;
+ b3AlignedObjectArray<b3Contact4> m_old;
+
+ b3AlignedObjectArray<int> m_batchSizes;
+ b3OpenCLArray<int>* m_batchSizesGpu;
+
+};
+
+
+
+b3GpuPgsContactSolver::b3GpuPgsContactSolver(cl_context ctx,cl_device_id device, cl_command_queue q,int pairCapacity)
+{
+ m_debugOutput=0;
+ m_data = new b3GpuBatchingPgsSolverInternalData;
+ m_data->m_context = ctx;
+ m_data->m_device = device;
+ m_data->m_queue = q;
+ m_data->m_pairCapacity = pairCapacity;
+ m_data->m_nIterations = 4;
+ m_data->m_batchSizesGpu = new b3OpenCLArray<int>(ctx,q);
+ m_data->m_bodyBufferGPU = new b3OpenCLArray<b3RigidBodyData>(ctx,q);
+ m_data->m_inertiaBufferGPU = new b3OpenCLArray<b3InertiaData>(ctx,q);
+ m_data->m_pBufContactOutGPU = new b3OpenCLArray<b3Contact4>(ctx,q);
+
+ m_data->m_pBufContactOutGPUCopy = new b3OpenCLArray<b3Contact4>(ctx,q);
+ m_data->m_contactKeyValues = new b3OpenCLArray<b3SortData>(ctx,q);
+
+
+ m_data->m_solverGPU = new b3Solver(ctx,device,q,512*1024);
+
+ m_data->m_sort32 = new b3RadixSort32CL(ctx,device,m_data->m_queue);
+ m_data->m_scan = new b3PrefixScanCL(ctx,device,m_data->m_queue,B3_SOLVER_N_CELLS);
+ m_data->m_search = new b3BoundSearchCL(ctx,device,m_data->m_queue,B3_SOLVER_N_CELLS);
+
+ const int sortSize = B3NEXTMULTIPLEOF( pairCapacity, 512 );
+
+ m_data->m_sortDataBuffer = new b3OpenCLArray<b3SortData>(ctx,m_data->m_queue,sortSize);
+ m_data->m_contactBuffer = new b3OpenCLArray<b3Contact4>(ctx,m_data->m_queue);
+
+ m_data->m_numConstraints = new b3OpenCLArray<unsigned int>(ctx,m_data->m_queue,B3_SOLVER_N_CELLS);
+ m_data->m_numConstraints->resize(B3_SOLVER_N_CELLS);
+
+ m_data->m_contactCGPU = new b3OpenCLArray<b3GpuConstraint4>(ctx,q,pairCapacity);
+
+ m_data->m_offsets = new b3OpenCLArray<unsigned int>( ctx,m_data->m_queue,B3_SOLVER_N_CELLS);
+ m_data->m_offsets->resize(B3_SOLVER_N_CELLS);
+ const char* additionalMacros = "";
+ //const char* srcFileNameForCaching="";
+
+
+
+ cl_int pErrNum;
+ const char* batchKernelSource = batchingKernelsCL;
+ const char* batchKernelNewSource = batchingKernelsNewCL;
+ const char* solverSetupSource = solverSetupCL;
+ const char* solverSetup2Source = solverSetup2CL;
+ const char* solveContactSource = solveContactCL;
+ const char* solveFrictionSource = solveFrictionCL;
+
+
+ {
+
+ cl_program solveContactProg= b3OpenCLUtils::compileCLProgramFromString( ctx, device, solveContactSource, &pErrNum,additionalMacros, B3_SOLVER_CONTACT_KERNEL_PATH);
+ b3Assert(solveContactProg);
+
+ cl_program solveFrictionProg= b3OpenCLUtils::compileCLProgramFromString( ctx, device, solveFrictionSource, &pErrNum,additionalMacros, B3_SOLVER_FRICTION_KERNEL_PATH);
+ b3Assert(solveFrictionProg);
+
+ cl_program solverSetup2Prog= b3OpenCLUtils::compileCLProgramFromString( ctx, device, solverSetup2Source, &pErrNum,additionalMacros, B3_SOLVER_SETUP2_KERNEL_PATH);
+
+
+ b3Assert(solverSetup2Prog);
+
+
+ cl_program solverSetupProg= b3OpenCLUtils::compileCLProgramFromString( ctx, device, solverSetupSource, &pErrNum,additionalMacros, B3_SOLVER_SETUP_KERNEL_PATH);
+ b3Assert(solverSetupProg);
+
+
+ m_data->m_solveFrictionKernel= b3OpenCLUtils::compileCLKernelFromString( ctx, device, solveFrictionSource, "BatchSolveKernelFriction", &pErrNum, solveFrictionProg,additionalMacros );
+ b3Assert(m_data->m_solveFrictionKernel);
+
+ m_data->m_solveContactKernel= b3OpenCLUtils::compileCLKernelFromString( ctx, device, solveContactSource, "BatchSolveKernelContact", &pErrNum, solveContactProg,additionalMacros );
+ b3Assert(m_data->m_solveContactKernel);
+
+ m_data->m_solveSingleContactKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, solveContactSource, "solveSingleContactKernel", &pErrNum, solveContactProg,additionalMacros );
+ b3Assert(m_data->m_solveSingleContactKernel);
+
+ m_data->m_solveSingleFrictionKernel =b3OpenCLUtils::compileCLKernelFromString( ctx, device, solveFrictionSource, "solveSingleFrictionKernel", &pErrNum, solveFrictionProg,additionalMacros );
+ b3Assert(m_data->m_solveSingleFrictionKernel);
+
+ m_data->m_contactToConstraintKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, solverSetupSource, "ContactToConstraintKernel", &pErrNum, solverSetupProg,additionalMacros );
+ b3Assert(m_data->m_contactToConstraintKernel);
+
+ m_data->m_setSortDataKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, solverSetup2Source, "SetSortDataKernel", &pErrNum, solverSetup2Prog,additionalMacros );
+ b3Assert(m_data->m_setSortDataKernel);
+
+ m_data->m_setDeterminismSortDataBodyAKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, solverSetup2Source, "SetDeterminismSortDataBodyA", &pErrNum, solverSetup2Prog,additionalMacros );
+ b3Assert(m_data->m_setDeterminismSortDataBodyAKernel);
+
+ m_data->m_setDeterminismSortDataBodyBKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, solverSetup2Source, "SetDeterminismSortDataBodyB", &pErrNum, solverSetup2Prog,additionalMacros );
+ b3Assert(m_data->m_setDeterminismSortDataBodyBKernel);
+
+ m_data->m_setDeterminismSortDataChildShapeAKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, solverSetup2Source, "SetDeterminismSortDataChildShapeA", &pErrNum, solverSetup2Prog,additionalMacros );
+ b3Assert(m_data->m_setDeterminismSortDataChildShapeAKernel);
+
+ m_data->m_setDeterminismSortDataChildShapeBKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, solverSetup2Source, "SetDeterminismSortDataChildShapeB", &pErrNum, solverSetup2Prog,additionalMacros );
+ b3Assert(m_data->m_setDeterminismSortDataChildShapeBKernel);
+
+
+ m_data->m_reorderContactKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, solverSetup2Source, "ReorderContactKernel", &pErrNum, solverSetup2Prog,additionalMacros );
+ b3Assert(m_data->m_reorderContactKernel);
+
+
+ m_data->m_copyConstraintKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, solverSetup2Source, "CopyConstraintKernel", &pErrNum, solverSetup2Prog,additionalMacros );
+ b3Assert(m_data->m_copyConstraintKernel);
+
+ }
+
+ {
+ cl_program batchingProg = b3OpenCLUtils::compileCLProgramFromString( ctx, device, batchKernelSource, &pErrNum,additionalMacros, B3_BATCHING_PATH);
+ b3Assert(batchingProg);
+
+ m_data->m_batchingKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, batchKernelSource, "CreateBatches", &pErrNum, batchingProg,additionalMacros );
+ b3Assert(m_data->m_batchingKernel);
+ }
+
+ {
+ cl_program batchingNewProg = b3OpenCLUtils::compileCLProgramFromString( ctx, device, batchKernelNewSource, &pErrNum,additionalMacros, B3_BATCHING_NEW_PATH);
+ b3Assert(batchingNewProg);
+
+ m_data->m_batchingKernelNew = b3OpenCLUtils::compileCLKernelFromString( ctx, device, batchKernelNewSource, "CreateBatchesNew", &pErrNum, batchingNewProg,additionalMacros );
+ b3Assert(m_data->m_batchingKernelNew);
+ }
+
+
+
+
+
+
+
+}
+
+b3GpuPgsContactSolver::~b3GpuPgsContactSolver()
+{
+ delete m_data->m_batchSizesGpu;
+ delete m_data->m_bodyBufferGPU;
+ delete m_data->m_inertiaBufferGPU;
+ delete m_data->m_pBufContactOutGPU;
+ delete m_data->m_pBufContactOutGPUCopy;
+ delete m_data->m_contactKeyValues;
+
+
+
+ delete m_data->m_contactCGPU;
+ delete m_data->m_numConstraints;
+ delete m_data->m_offsets;
+ delete m_data->m_sortDataBuffer;
+ delete m_data->m_contactBuffer;
+
+ delete m_data->m_sort32;
+ delete m_data->m_scan;
+ delete m_data->m_search;
+ delete m_data->m_solverGPU;
+
+ clReleaseKernel(m_data->m_batchingKernel);
+ clReleaseKernel(m_data->m_batchingKernelNew);
+ clReleaseKernel(m_data->m_solveSingleContactKernel);
+ clReleaseKernel(m_data->m_solveSingleFrictionKernel);
+ clReleaseKernel( m_data->m_solveContactKernel);
+ clReleaseKernel( m_data->m_solveFrictionKernel);
+
+ clReleaseKernel( m_data->m_contactToConstraintKernel);
+ clReleaseKernel( m_data->m_setSortDataKernel);
+ clReleaseKernel( m_data->m_reorderContactKernel);
+ clReleaseKernel( m_data->m_copyConstraintKernel);
+
+ clReleaseKernel(m_data->m_setDeterminismSortDataBodyAKernel);
+ clReleaseKernel(m_data->m_setDeterminismSortDataBodyBKernel);
+ clReleaseKernel(m_data->m_setDeterminismSortDataChildShapeAKernel);
+ clReleaseKernel(m_data->m_setDeterminismSortDataChildShapeBKernel);
+
+
+
+ delete m_data;
+}
+
+
+
+struct b3ConstraintCfg
+{
+ b3ConstraintCfg( float dt = 0.f ): m_positionDrift( 0.005f ), m_positionConstraintCoeff( 0.2f ), m_dt(dt), m_staticIdx(0) {}
+
+ float m_positionDrift;
+ float m_positionConstraintCoeff;
+ float m_dt;
+ bool m_enableParallelSolve;
+ float m_batchCellSize;
+ int m_staticIdx;
+};
+
+
+
+void b3GpuPgsContactSolver::solveContactConstraintBatchSizes( const b3OpenCLArray<b3RigidBodyData>* bodyBuf, const b3OpenCLArray<b3InertiaData>* shapeBuf,
+ b3OpenCLArray<b3GpuConstraint4>* constraint, void* additionalData, int n ,int maxNumBatches,int numIterations, const b3AlignedObjectArray<int>* batchSizes)//const b3OpenCLArray<int>* gpuBatchSizes)
+{
+ B3_PROFILE("solveContactConstraintBatchSizes");
+ int numBatches = batchSizes->size()/B3_MAX_NUM_BATCHES;
+ for(int iter=0; iter<numIterations; iter++)
+ {
+
+ for (int cellId=0;cellId<numBatches;cellId++)
+ {
+ int offset = 0;
+ for (int ii=0;ii<B3_MAX_NUM_BATCHES;ii++)
+ {
+ int numInBatch = batchSizes->at(cellId*B3_MAX_NUM_BATCHES+ii);
+ if (!numInBatch)
+ break;
+
+ {
+ b3LauncherCL launcher( m_data->m_queue, m_data->m_solveSingleContactKernel,"m_solveSingleContactKernel" );
+ launcher.setBuffer(bodyBuf->getBufferCL() );
+ launcher.setBuffer(shapeBuf->getBufferCL() );
+ launcher.setBuffer( constraint->getBufferCL() );
+ launcher.setConst(cellId);
+ launcher.setConst(offset);
+ launcher.setConst(numInBatch);
+ launcher.launch1D(numInBatch);
+ offset+=numInBatch;
+ }
+ }
+ }
+ }
+
+
+ for(int iter=0; iter<numIterations; iter++)
+ {
+ for (int cellId=0;cellId<numBatches;cellId++)
+ {
+ int offset = 0;
+ for (int ii=0;ii<B3_MAX_NUM_BATCHES;ii++)
+ {
+ int numInBatch = batchSizes->at(cellId*B3_MAX_NUM_BATCHES+ii);
+ if (!numInBatch)
+ break;
+
+ {
+ b3LauncherCL launcher( m_data->m_queue, m_data->m_solveSingleFrictionKernel,"m_solveSingleFrictionKernel" );
+ launcher.setBuffer(bodyBuf->getBufferCL() );
+ launcher.setBuffer(shapeBuf->getBufferCL() );
+ launcher.setBuffer( constraint->getBufferCL() );
+ launcher.setConst(cellId);
+ launcher.setConst(offset);
+ launcher.setConst(numInBatch);
+ launcher.launch1D(numInBatch);
+ offset+=numInBatch;
+ }
+ }
+ }
+ }
+}
+
+void b3GpuPgsContactSolver::solveContactConstraint( const b3OpenCLArray<b3RigidBodyData>* bodyBuf, const b3OpenCLArray<b3InertiaData>* shapeBuf,
+ b3OpenCLArray<b3GpuConstraint4>* constraint, void* additionalData, int n ,int maxNumBatches,int numIterations, const b3AlignedObjectArray<int>* batchSizes)//,const b3OpenCLArray<int>* gpuBatchSizes)
+{
+
+ //sort the contacts
+
+
+ b3Int4 cdata = b3MakeInt4( n, 0, 0, 0 );
+ {
+
+ const int nn = B3_SOLVER_N_CELLS;
+
+ cdata.x = 0;
+ cdata.y = maxNumBatches;//250;
+
+
+ int numWorkItems = 64*nn/B3_SOLVER_N_BATCHES;
+#ifdef DEBUG_ME
+ SolverDebugInfo* debugInfo = new SolverDebugInfo[numWorkItems];
+ adl::b3OpenCLArray<SolverDebugInfo> gpuDebugInfo(data->m_device,numWorkItems);
+#endif
+
+
+
+ {
+
+ B3_PROFILE("m_batchSolveKernel iterations");
+ for(int iter=0; iter<numIterations; iter++)
+ {
+ for(int ib=0; ib<B3_SOLVER_N_BATCHES; ib++)
+ {
+#ifdef DEBUG_ME
+ memset(debugInfo,0,sizeof(SolverDebugInfo)*numWorkItems);
+ gpuDebugInfo.write(debugInfo,numWorkItems);
+#endif
+
+
+ cdata.z = ib;
+
+
+ b3LauncherCL launcher( m_data->m_queue, m_data->m_solveContactKernel,"m_solveContactKernel" );
+#if 1
+
+ b3BufferInfoCL bInfo[] = {
+
+ b3BufferInfoCL( bodyBuf->getBufferCL() ),
+ b3BufferInfoCL( shapeBuf->getBufferCL() ),
+ b3BufferInfoCL( constraint->getBufferCL() ),
+ b3BufferInfoCL( m_data->m_solverGPU->m_numConstraints->getBufferCL() ),
+ b3BufferInfoCL( m_data->m_solverGPU->m_offsets->getBufferCL() )
+#ifdef DEBUG_ME
+ , b3BufferInfoCL(&gpuDebugInfo)
+#endif
+ };
+
+
+
+ launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setBuffer( m_data->m_solverGPU->m_batchSizes.getBufferCL());
+ //launcher.setConst( cdata.x );
+ launcher.setConst( cdata.y );
+ launcher.setConst( cdata.z );
+ b3Int4 nSplit;
+ nSplit.x = B3_SOLVER_N_SPLIT_X;
+ nSplit.y = B3_SOLVER_N_SPLIT_Y;
+ nSplit.z = B3_SOLVER_N_SPLIT_Z;
+
+ launcher.setConst( nSplit );
+ launcher.launch1D( numWorkItems, 64 );
+
+
+#else
+ const char* fileName = "m_batchSolveKernel.bin";
+ FILE* f = fopen(fileName,"rb");
+ if (f)
+ {
+ int sizeInBytes=0;
+ if (fseek(f, 0, SEEK_END) || (sizeInBytes = ftell(f)) == EOF || fseek(f, 0, SEEK_SET))
+ {
+ printf("error, cannot get file size\n");
+ exit(0);
+ }
+
+ unsigned char* buf = (unsigned char*) malloc(sizeInBytes);
+ fread(buf,sizeInBytes,1,f);
+ int serializedBytes = launcher.deserializeArgs(buf, sizeInBytes,m_context);
+ int num = *(int*)&buf[serializedBytes];
+
+ launcher.launch1D( num);
+
+ //this clFinish is for testing on errors
+ clFinish(m_queue);
+ }
+
+#endif
+
+
+#ifdef DEBUG_ME
+ clFinish(m_queue);
+ gpuDebugInfo.read(debugInfo,numWorkItems);
+ clFinish(m_queue);
+ for (int i=0;i<numWorkItems;i++)
+ {
+ if (debugInfo[i].m_valInt2>0)
+ {
+ printf("debugInfo[i].m_valInt2 = %d\n",i,debugInfo[i].m_valInt2);
+ }
+
+ if (debugInfo[i].m_valInt3>0)
+ {
+ printf("debugInfo[i].m_valInt3 = %d\n",i,debugInfo[i].m_valInt3);
+ }
+ }
+#endif //DEBUG_ME
+
+
+ }
+ }
+
+ clFinish(m_data->m_queue);
+
+
+ }
+
+ cdata.x = 1;
+ bool applyFriction=true;
+ if (applyFriction)
+ {
+ B3_PROFILE("m_batchSolveKernel iterations2");
+ for(int iter=0; iter<numIterations; iter++)
+ {
+ for(int ib=0; ib<B3_SOLVER_N_BATCHES; ib++)
+ {
+ cdata.z = ib;
+
+
+ b3BufferInfoCL bInfo[] = {
+ b3BufferInfoCL( bodyBuf->getBufferCL() ),
+ b3BufferInfoCL( shapeBuf->getBufferCL() ),
+ b3BufferInfoCL( constraint->getBufferCL() ),
+ b3BufferInfoCL( m_data->m_solverGPU->m_numConstraints->getBufferCL() ),
+ b3BufferInfoCL( m_data->m_solverGPU->m_offsets->getBufferCL() )
+#ifdef DEBUG_ME
+ ,b3BufferInfoCL(&gpuDebugInfo)
+#endif //DEBUG_ME
+ };
+ b3LauncherCL launcher( m_data->m_queue, m_data->m_solveFrictionKernel,"m_solveFrictionKernel" );
+ launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setBuffer( m_data->m_solverGPU->m_batchSizes.getBufferCL());
+ //launcher.setConst( cdata.x );
+ launcher.setConst( cdata.y );
+ launcher.setConst( cdata.z );
+
+ b3Int4 nSplit;
+ nSplit.x = B3_SOLVER_N_SPLIT_X;
+ nSplit.y = B3_SOLVER_N_SPLIT_Y;
+ nSplit.z = B3_SOLVER_N_SPLIT_Z;
+
+ launcher.setConst( nSplit );
+
+ launcher.launch1D( 64*nn/B3_SOLVER_N_BATCHES, 64 );
+ }
+ }
+ clFinish(m_data->m_queue);
+
+ }
+#ifdef DEBUG_ME
+ delete[] debugInfo;
+#endif //DEBUG_ME
+ }
+
+
+}
+
+
+
+
+
+
+
+
+
+
+
+static bool sortfnc(const b3SortData& a,const b3SortData& b)
+{
+ return (a.m_key<b.m_key);
+}
+
+static bool b3ContactCmp(const b3Contact4& p, const b3Contact4& q)
+{
+ return ((p.m_bodyAPtrAndSignBit<q.m_bodyAPtrAndSignBit) ||
+ ((p.m_bodyAPtrAndSignBit==q.m_bodyAPtrAndSignBit) && (p.m_bodyBPtrAndSignBit<q.m_bodyBPtrAndSignBit)) ||
+ ((p.m_bodyAPtrAndSignBit==q.m_bodyAPtrAndSignBit) && (p.m_bodyBPtrAndSignBit==q.m_bodyBPtrAndSignBit) && p.m_childIndexA<q.m_childIndexA ) ||
+ ((p.m_bodyAPtrAndSignBit==q.m_bodyAPtrAndSignBit) && (p.m_bodyBPtrAndSignBit==q.m_bodyBPtrAndSignBit) && p.m_childIndexA<q.m_childIndexA ) ||
+ ((p.m_bodyAPtrAndSignBit==q.m_bodyAPtrAndSignBit) && (p.m_bodyBPtrAndSignBit==q.m_bodyBPtrAndSignBit) && p.m_childIndexA==q.m_childIndexA && p.m_childIndexB<q.m_childIndexB)
+ );
+}
+
+
+
+
+
+
+
+
+
+
+
+#define USE_SPATIAL_BATCHING 1
+#define USE_4x4_GRID 1
+
+#ifndef USE_SPATIAL_BATCHING
+static const int gridTable4x4[] =
+{
+ 0,1,17,16,
+ 1,2,18,19,
+ 17,18,32,3,
+ 16,19,3,34
+};
+static const int gridTable8x8[] =
+{
+ 0, 2, 3, 16, 17, 18, 19, 1,
+ 66, 64, 80, 67, 82, 81, 65, 83,
+ 131,144,128,130,147,129,145,146,
+ 208,195,194,192,193,211,210,209,
+ 21, 22, 23, 5, 4, 6, 7, 20,
+ 86, 85, 69, 87, 70, 68, 84, 71,
+ 151,133,149,150,135,148,132,134,
+ 197,27,214,213,212,199,198,196
+
+};
+
+
+#endif
+
+
+void SetSortDataCPU(b3Contact4* gContact, b3RigidBodyData* gBodies, b3SortData* gSortDataOut, int nContacts,float scale,const b3Int4& nSplit,int staticIdx)
+{
+ for (int gIdx=0;gIdx<nContacts;gIdx++)
+ {
+ if( gIdx < nContacts )
+ {
+ int aPtrAndSignBit = gContact[gIdx].m_bodyAPtrAndSignBit;
+ int bPtrAndSignBit = gContact[gIdx].m_bodyBPtrAndSignBit;
+
+ int aIdx = abs(aPtrAndSignBit );
+ int bIdx = abs(bPtrAndSignBit);
+
+ bool aStatic = (aPtrAndSignBit<0) ||(aPtrAndSignBit==staticIdx);
+
+ #if USE_SPATIAL_BATCHING
+ int idx = (aStatic)? bIdx: aIdx;
+ b3Vector3 p = gBodies[idx].m_pos;
+ int xIdx = (int)((p.x-((p.x<0.f)?1.f:0.f))*scale) & (nSplit.x-1);
+ int yIdx = (int)((p.y-((p.y<0.f)?1.f:0.f))*scale) & (nSplit.y-1);
+ int zIdx = (int)((p.z-((p.z<0.f)?1.f:0.f))*scale) & (nSplit.z-1);
+
+ int newIndex = (xIdx+yIdx*nSplit.x+zIdx*nSplit.x*nSplit.y);
+
+ #else//USE_SPATIAL_BATCHING
+ bool bStatic = (bPtrAndSignBit<0) ||(bPtrAndSignBit==staticIdx);
+
+ #if USE_4x4_GRID
+ int aa = aIdx&3;
+ int bb = bIdx&3;
+ if (aStatic)
+ aa = bb;
+ if (bStatic)
+ bb = aa;
+
+ int gridIndex = aa + bb*4;
+ int newIndex = gridTable4x4[gridIndex];
+ #else//USE_4x4_GRID
+ int aa = aIdx&7;
+ int bb = bIdx&7;
+ if (aStatic)
+ aa = bb;
+ if (bStatic)
+ bb = aa;
+
+ int gridIndex = aa + bb*8;
+ int newIndex = gridTable8x8[gridIndex];
+ #endif//USE_4x4_GRID
+ #endif//USE_SPATIAL_BATCHING
+
+
+ gSortDataOut[gIdx].x = newIndex;
+ gSortDataOut[gIdx].y = gIdx;
+ }
+ else
+ {
+ gSortDataOut[gIdx].x = 0xffffffff;
+ }
+ }
+}
+
+
+
+
+
+
+void b3GpuPgsContactSolver::solveContacts(int numBodies, cl_mem bodyBuf, cl_mem inertiaBuf, int numContacts, cl_mem contactBuf, const b3Config& config, int static0Index)
+{
+ B3_PROFILE("solveContacts");
+ m_data->m_bodyBufferGPU->setFromOpenCLBuffer(bodyBuf,numBodies);
+ m_data->m_inertiaBufferGPU->setFromOpenCLBuffer(inertiaBuf,numBodies);
+ m_data->m_pBufContactOutGPU->setFromOpenCLBuffer(contactBuf,numContacts);
+
+ if (optionalSortContactsDeterminism)
+ {
+ if (!gCpuSortContactsDeterminism)
+ {
+ B3_PROFILE("GPU Sort contact constraints (determinism)");
+
+ m_data->m_pBufContactOutGPUCopy->resize(numContacts);
+ m_data->m_contactKeyValues->resize(numContacts);
+
+ m_data->m_pBufContactOutGPU->copyToCL(m_data->m_pBufContactOutGPUCopy->getBufferCL(),numContacts,0,0);
+
+ {
+ b3LauncherCL launcher(m_data->m_queue, m_data->m_setDeterminismSortDataChildShapeBKernel,"m_setDeterminismSortDataChildShapeBKernel");
+ launcher.setBuffer(m_data->m_pBufContactOutGPUCopy->getBufferCL());
+ launcher.setBuffer(m_data->m_contactKeyValues->getBufferCL());
+ launcher.setConst(numContacts);
+ launcher.launch1D( numContacts, 64 );
+ }
+ m_data->m_solverGPU->m_sort32->execute(*m_data->m_contactKeyValues);
+ {
+ b3LauncherCL launcher(m_data->m_queue, m_data->m_setDeterminismSortDataChildShapeAKernel,"m_setDeterminismSortDataChildShapeAKernel");
+ launcher.setBuffer(m_data->m_pBufContactOutGPUCopy->getBufferCL());
+ launcher.setBuffer(m_data->m_contactKeyValues->getBufferCL());
+ launcher.setConst(numContacts);
+ launcher.launch1D( numContacts, 64 );
+ }
+ m_data->m_solverGPU->m_sort32->execute(*m_data->m_contactKeyValues);
+ {
+ b3LauncherCL launcher(m_data->m_queue, m_data->m_setDeterminismSortDataBodyBKernel,"m_setDeterminismSortDataBodyBKernel");
+ launcher.setBuffer(m_data->m_pBufContactOutGPUCopy->getBufferCL());
+ launcher.setBuffer(m_data->m_contactKeyValues->getBufferCL());
+ launcher.setConst(numContacts);
+ launcher.launch1D( numContacts, 64 );
+ }
+
+ m_data->m_solverGPU->m_sort32->execute(*m_data->m_contactKeyValues);
+
+ {
+ b3LauncherCL launcher(m_data->m_queue, m_data->m_setDeterminismSortDataBodyAKernel,"m_setDeterminismSortDataBodyAKernel");
+ launcher.setBuffer(m_data->m_pBufContactOutGPUCopy->getBufferCL());
+ launcher.setBuffer(m_data->m_contactKeyValues->getBufferCL());
+ launcher.setConst(numContacts);
+ launcher.launch1D( numContacts, 64 );
+ }
+
+ m_data->m_solverGPU->m_sort32->execute(*m_data->m_contactKeyValues);
+
+ {
+ B3_PROFILE("gpu reorderContactKernel (determinism)");
+
+ b3Int4 cdata;
+ cdata.x = numContacts;
+
+ //b3BufferInfoCL bInfo[] = { b3BufferInfoCL( m_data->m_pBufContactOutGPU->getBufferCL() ), b3BufferInfoCL( m_data->m_solverGPU->m_contactBuffer2->getBufferCL())
+ // , b3BufferInfoCL( m_data->m_solverGPU->m_sortDataBuffer->getBufferCL()) };
+ b3LauncherCL launcher(m_data->m_queue,m_data->m_solverGPU->m_reorderContactKernel,"m_reorderContactKernel");
+ launcher.setBuffer(m_data->m_pBufContactOutGPUCopy->getBufferCL());
+ launcher.setBuffer(m_data->m_pBufContactOutGPU->getBufferCL());
+ launcher.setBuffer(m_data->m_contactKeyValues->getBufferCL());
+ launcher.setConst( cdata );
+ launcher.launch1D( numContacts, 64 );
+ }
+
+ } else
+ {
+ B3_PROFILE("CPU Sort contact constraints (determinism)");
+ b3AlignedObjectArray<b3Contact4> cpuConstraints;
+ m_data->m_pBufContactOutGPU->copyToHost(cpuConstraints);
+ bool sort = true;
+ if (sort)
+ {
+ cpuConstraints.quickSort(b3ContactCmp);
+
+ for (int i=0;i<cpuConstraints.size();i++)
+ {
+ cpuConstraints[i].m_batchIdx = i;
+ }
+ }
+ m_data->m_pBufContactOutGPU->copyFromHost(cpuConstraints);
+ if (m_debugOutput==100)
+ {
+ for (int i=0;i<cpuConstraints.size();i++)
+ {
+ printf("c[%d].m_bodyA = %d, m_bodyB = %d, batchId = %d\n",i,cpuConstraints[i].m_bodyAPtrAndSignBit,cpuConstraints[i].m_bodyBPtrAndSignBit, cpuConstraints[i].m_batchIdx);
+ }
+ }
+
+ m_debugOutput++;
+ }
+ }
+
+
+
+
+ int nContactOut = m_data->m_pBufContactOutGPU->size();
+
+ bool useSolver = true;
+
+
+ if (useSolver)
+ {
+ float dt=1./60.;
+ b3ConstraintCfg csCfg( dt );
+ csCfg.m_enableParallelSolve = true;
+ csCfg.m_batchCellSize = 6;
+ csCfg.m_staticIdx = static0Index;
+
+
+ b3OpenCLArray<b3RigidBodyData>* bodyBuf = m_data->m_bodyBufferGPU;
+
+ void* additionalData = 0;//m_data->m_frictionCGPU;
+ const b3OpenCLArray<b3InertiaData>* shapeBuf = m_data->m_inertiaBufferGPU;
+ b3OpenCLArray<b3GpuConstraint4>* contactConstraintOut = m_data->m_contactCGPU;
+ int nContacts = nContactOut;
+
+
+ int maxNumBatches = 0;
+
+ if (!gUseLargeBatches)
+ {
+
+ if( m_data->m_solverGPU->m_contactBuffer2)
+ {
+ m_data->m_solverGPU->m_contactBuffer2->resize(nContacts);
+ }
+
+ if( m_data->m_solverGPU->m_contactBuffer2 == 0 )
+ {
+ m_data->m_solverGPU->m_contactBuffer2 = new b3OpenCLArray<b3Contact4>(m_data->m_context,m_data->m_queue, nContacts );
+ m_data->m_solverGPU->m_contactBuffer2->resize(nContacts);
+ }
+
+ //clFinish(m_data->m_queue);
+
+
+
+ {
+ B3_PROFILE("batching");
+ //@todo: just reserve it, without copy of original contact (unless we use warmstarting)
+
+
+
+ //const b3OpenCLArray<b3RigidBodyData>* bodyNative = bodyBuf;
+
+
+ {
+
+ //b3OpenCLArray<b3RigidBodyData>* bodyNative = b3OpenCLArrayUtils::map<adl::TYPE_CL, true>( data->m_device, bodyBuf );
+ //b3OpenCLArray<b3Contact4>* contactNative = b3OpenCLArrayUtils::map<adl::TYPE_CL, true>( data->m_device, contactsIn );
+
+ const int sortAlignment = 512; // todo. get this out of sort
+ if( csCfg.m_enableParallelSolve )
+ {
+
+
+ int sortSize = B3NEXTMULTIPLEOF( nContacts, sortAlignment );
+
+ b3OpenCLArray<unsigned int>* countsNative = m_data->m_solverGPU->m_numConstraints;
+ b3OpenCLArray<unsigned int>* offsetsNative = m_data->m_solverGPU->m_offsets;
+
+
+ if (!gCpuSetSortData)
+ { // 2. set cell idx
+ B3_PROFILE("GPU set cell idx");
+ struct CB
+ {
+ int m_nContacts;
+ int m_staticIdx;
+ float m_scale;
+ b3Int4 m_nSplit;
+ };
+
+ b3Assert( sortSize%64 == 0 );
+ CB cdata;
+ cdata.m_nContacts = nContacts;
+ cdata.m_staticIdx = csCfg.m_staticIdx;
+ cdata.m_scale = 1.f/csCfg.m_batchCellSize;
+ cdata.m_nSplit.x = B3_SOLVER_N_SPLIT_X;
+ cdata.m_nSplit.y = B3_SOLVER_N_SPLIT_Y;
+ cdata.m_nSplit.z = B3_SOLVER_N_SPLIT_Z;
+
+ m_data->m_solverGPU->m_sortDataBuffer->resize(nContacts);
+
+
+ b3BufferInfoCL bInfo[] = { b3BufferInfoCL( m_data->m_pBufContactOutGPU->getBufferCL() ), b3BufferInfoCL( bodyBuf->getBufferCL()), b3BufferInfoCL( m_data->m_solverGPU->m_sortDataBuffer->getBufferCL()) };
+ b3LauncherCL launcher(m_data->m_queue, m_data->m_solverGPU->m_setSortDataKernel,"m_setSortDataKernel" );
+ launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst( cdata.m_nContacts );
+ launcher.setConst( cdata.m_scale );
+ launcher.setConst(cdata.m_nSplit);
+ launcher.setConst(cdata.m_staticIdx);
+
+
+ launcher.launch1D( sortSize, 64 );
+ } else
+ {
+ m_data->m_solverGPU->m_sortDataBuffer->resize(nContacts);
+ b3AlignedObjectArray<b3SortData> sortDataCPU;
+ m_data->m_solverGPU->m_sortDataBuffer->copyToHost(sortDataCPU);
+
+ b3AlignedObjectArray<b3Contact4> contactCPU;
+ m_data->m_pBufContactOutGPU->copyToHost(contactCPU);
+ b3AlignedObjectArray<b3RigidBodyData> bodiesCPU;
+ bodyBuf->copyToHost(bodiesCPU);
+ float scale = 1.f/csCfg.m_batchCellSize;
+ b3Int4 nSplit;
+ nSplit.x = B3_SOLVER_N_SPLIT_X;
+ nSplit.y = B3_SOLVER_N_SPLIT_Y;
+ nSplit.z = B3_SOLVER_N_SPLIT_Z;
+
+ SetSortDataCPU(&contactCPU[0], &bodiesCPU[0], &sortDataCPU[0], nContacts,scale,nSplit,csCfg.m_staticIdx);
+
+
+ m_data->m_solverGPU->m_sortDataBuffer->copyFromHost(sortDataCPU);
+ }
+
+
+
+ if (!gCpuRadixSort)
+ { // 3. sort by cell idx
+ B3_PROFILE("gpuRadixSort");
+ //int n = B3_SOLVER_N_SPLIT*B3_SOLVER_N_SPLIT;
+ //int sortBit = 32;
+ //if( n <= 0xffff ) sortBit = 16;
+ //if( n <= 0xff ) sortBit = 8;
+ //adl::RadixSort<adl::TYPE_CL>::execute( data->m_sort, *data->m_sortDataBuffer, sortSize );
+ //adl::RadixSort32<adl::TYPE_CL>::execute( data->m_sort32, *data->m_sortDataBuffer, sortSize );
+ b3OpenCLArray<b3SortData>& keyValuesInOut = *(m_data->m_solverGPU->m_sortDataBuffer);
+ this->m_data->m_solverGPU->m_sort32->execute(keyValuesInOut);
+
+
+
+ } else
+ {
+ b3OpenCLArray<b3SortData>& keyValuesInOut = *(m_data->m_solverGPU->m_sortDataBuffer);
+ b3AlignedObjectArray<b3SortData> hostValues;
+ keyValuesInOut.copyToHost(hostValues);
+ hostValues.quickSort(sortfnc);
+ keyValuesInOut.copyFromHost(hostValues);
+ }
+
+
+ if (gUseScanHost)
+ {
+ // 4. find entries
+ B3_PROFILE("cpuBoundSearch");
+ b3AlignedObjectArray<unsigned int> countsHost;
+ countsNative->copyToHost(countsHost);
+
+ b3AlignedObjectArray<b3SortData> sortDataHost;
+ m_data->m_solverGPU->m_sortDataBuffer->copyToHost(sortDataHost);
+
+
+ //m_data->m_solverGPU->m_search->executeHost(*m_data->m_solverGPU->m_sortDataBuffer,nContacts,*countsNative,B3_SOLVER_N_CELLS,b3BoundSearchCL::COUNT);
+ m_data->m_solverGPU->m_search->executeHost(sortDataHost,nContacts,countsHost,B3_SOLVER_N_CELLS,b3BoundSearchCL::COUNT);
+
+ countsNative->copyFromHost(countsHost);
+
+
+ //adl::BoundSearch<adl::TYPE_CL>::execute( data->m_search, *data->m_sortDataBuffer, nContacts, *countsNative,
+ // B3_SOLVER_N_SPLIT*B3_SOLVER_N_SPLIT, adl::BoundSearchBase::COUNT );
+
+ //unsigned int sum;
+ //m_data->m_solverGPU->m_scan->execute(*countsNative,*offsetsNative, B3_SOLVER_N_CELLS);//,&sum );
+ b3AlignedObjectArray<unsigned int> offsetsHost;
+ offsetsHost.resize(offsetsNative->size());
+
+
+ m_data->m_solverGPU->m_scan->executeHost(countsHost,offsetsHost, B3_SOLVER_N_CELLS);//,&sum );
+ offsetsNative->copyFromHost(offsetsHost);
+
+ //printf("sum = %d\n",sum);
+ } else
+ {
+ // 4. find entries
+ B3_PROFILE("gpuBoundSearch");
+ m_data->m_solverGPU->m_search->execute(*m_data->m_solverGPU->m_sortDataBuffer,nContacts,*countsNative,B3_SOLVER_N_CELLS,b3BoundSearchCL::COUNT);
+ m_data->m_solverGPU->m_scan->execute(*countsNative,*offsetsNative, B3_SOLVER_N_CELLS);//,&sum );
+ }
+
+
+
+
+ if (nContacts)
+ { // 5. sort constraints by cellIdx
+ if (gReorderContactsOnCpu)
+ {
+ B3_PROFILE("cpu m_reorderContactKernel");
+ b3AlignedObjectArray<b3SortData> sortDataHost;
+ m_data->m_solverGPU->m_sortDataBuffer->copyToHost(sortDataHost);
+ b3AlignedObjectArray<b3Contact4> inContacts;
+ b3AlignedObjectArray<b3Contact4> outContacts;
+ m_data->m_pBufContactOutGPU->copyToHost(inContacts);
+ outContacts.resize(inContacts.size());
+ for (int i=0;i<nContacts;i++)
+ {
+ int srcIdx = sortDataHost[i].y;
+ outContacts[i] = inContacts[srcIdx];
+ }
+ m_data->m_solverGPU->m_contactBuffer2->copyFromHost(outContacts);
+
+ /* "void ReorderContactKernel(__global struct b3Contact4Data* in, __global struct b3Contact4Data* out, __global int2* sortData, int4 cb )\n"
+ "{\n"
+ " int nContacts = cb.x;\n"
+ " int gIdx = GET_GLOBAL_IDX;\n"
+ " if( gIdx < nContacts )\n"
+ " {\n"
+ " int srcIdx = sortData[gIdx].y;\n"
+ " out[gIdx] = in[srcIdx];\n"
+ " }\n"
+ "}\n"
+ */
+ } else
+ {
+ B3_PROFILE("gpu m_reorderContactKernel");
+
+ b3Int4 cdata;
+ cdata.x = nContacts;
+
+ b3BufferInfoCL bInfo[] = {
+ b3BufferInfoCL( m_data->m_pBufContactOutGPU->getBufferCL() ),
+ b3BufferInfoCL( m_data->m_solverGPU->m_contactBuffer2->getBufferCL())
+ , b3BufferInfoCL( m_data->m_solverGPU->m_sortDataBuffer->getBufferCL()) };
+
+ b3LauncherCL launcher(m_data->m_queue,m_data->m_solverGPU->m_reorderContactKernel,"m_reorderContactKernel");
+ launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst( cdata );
+ launcher.launch1D( nContacts, 64 );
+ }
+ }
+
+
+
+
+ }
+
+ }
+
+ //clFinish(m_data->m_queue);
+
+ // {
+ // b3AlignedObjectArray<unsigned int> histogram;
+ // m_data->m_solverGPU->m_numConstraints->copyToHost(histogram);
+ // printf(",,,\n");
+ // }
+
+
+ if (nContacts)
+ {
+
+ if (gUseCpuCopyConstraints)
+ {
+ for (int i=0;i<nContacts;i++)
+ {
+ m_data->m_pBufContactOutGPU->copyFromOpenCLArray(*m_data->m_solverGPU->m_contactBuffer2);
+ // m_data->m_solverGPU->m_contactBuffer2->getBufferCL();
+ // m_data->m_pBufContactOutGPU->getBufferCL()
+ }
+
+ } else
+ {
+ B3_PROFILE("gpu m_copyConstraintKernel");
+ b3Int4 cdata; cdata.x = nContacts;
+ b3BufferInfoCL bInfo[] = {
+ b3BufferInfoCL( m_data->m_solverGPU->m_contactBuffer2->getBufferCL() ),
+ b3BufferInfoCL( m_data->m_pBufContactOutGPU->getBufferCL() )
+ };
+
+ b3LauncherCL launcher(m_data->m_queue, m_data->m_solverGPU->m_copyConstraintKernel,"m_copyConstraintKernel" );
+ launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst( cdata );
+ launcher.launch1D( nContacts, 64 );
+ //we use the clFinish for proper benchmark/profile
+ clFinish(m_data->m_queue);
+ }
+ }
+
+
+// bool compareGPU = false;
+ if (nContacts)
+ {
+ if (!gCpuBatchContacts)
+ {
+ B3_PROFILE("gpu batchContacts");
+ maxNumBatches = 250;//250;
+ m_data->m_solverGPU->batchContacts( m_data->m_pBufContactOutGPU, nContacts, m_data->m_solverGPU->m_numConstraints, m_data->m_solverGPU->m_offsets, csCfg.m_staticIdx );
+ clFinish(m_data->m_queue);
+ } else
+ {
+ B3_PROFILE("cpu batchContacts");
+ static b3AlignedObjectArray<b3Contact4> cpuContacts;
+ b3OpenCLArray<b3Contact4>* contactsIn = m_data->m_solverGPU->m_contactBuffer2;
+ {
+ B3_PROFILE("copyToHost");
+ contactsIn->copyToHost(cpuContacts);
+ }
+ b3OpenCLArray<unsigned int>* countsNative = m_data->m_solverGPU->m_numConstraints;
+ b3OpenCLArray<unsigned int>* offsetsNative = m_data->m_solverGPU->m_offsets;
+
+ b3AlignedObjectArray<unsigned int> nNativeHost;
+ b3AlignedObjectArray<unsigned int> offsetsNativeHost;
+
+ {
+ B3_PROFILE("countsNative/offsetsNative copyToHost");
+ countsNative->copyToHost(nNativeHost);
+ offsetsNative->copyToHost(offsetsNativeHost);
+ }
+
+
+ int numNonzeroGrid=0;
+
+ if (gUseLargeBatches)
+ {
+ m_data->m_batchSizes.resize(B3_MAX_NUM_BATCHES);
+ int totalNumConstraints = cpuContacts.size();
+ //int simdWidth =numBodies+1;//-1;//64;//-1;//32;
+ int numBatches = sortConstraintByBatch3( &cpuContacts[0], totalNumConstraints, totalNumConstraints+1,csCfg.m_staticIdx ,numBodies,&m_data->m_batchSizes[0]); // on GPU
+ maxNumBatches = b3Max(numBatches,maxNumBatches);
+ static int globalMaxBatch = 0;
+ if (maxNumBatches>globalMaxBatch )
+ {
+ globalMaxBatch = maxNumBatches;
+ b3Printf("maxNumBatches = %d\n",maxNumBatches);
+ }
+
+ } else
+ {
+ m_data->m_batchSizes.resize(B3_SOLVER_N_CELLS*B3_MAX_NUM_BATCHES);
+ B3_PROFILE("cpu batch grid");
+ for(int i=0; i<B3_SOLVER_N_CELLS; i++)
+ {
+ int n = (nNativeHost)[i];
+ int offset = (offsetsNativeHost)[i];
+ if( n )
+ {
+ numNonzeroGrid++;
+ int simdWidth =numBodies+1;//-1;//64;//-1;//32;
+ int numBatches = sortConstraintByBatch3( &cpuContacts[0]+offset, n, simdWidth,csCfg.m_staticIdx ,numBodies,&m_data->m_batchSizes[i*B3_MAX_NUM_BATCHES]); // on GPU
+ maxNumBatches = b3Max(numBatches,maxNumBatches);
+ static int globalMaxBatch = 0;
+ if (maxNumBatches>globalMaxBatch )
+ {
+ globalMaxBatch = maxNumBatches;
+ b3Printf("maxNumBatches = %d\n",maxNumBatches);
+ }
+ //we use the clFinish for proper benchmark/profile
+
+ }
+ }
+ //clFinish(m_data->m_queue);
+ }
+ {
+ B3_PROFILE("m_contactBuffer->copyFromHost");
+ m_data->m_solverGPU->m_contactBuffer2->copyFromHost((b3AlignedObjectArray<b3Contact4>&)cpuContacts);
+ }
+
+ }
+
+ }
+
+
+
+
+
+ }
+
+
+ }
+
+
+ //printf("maxNumBatches = %d\n", maxNumBatches);
+
+ if (gUseLargeBatches)
+ {
+ if (nContacts)
+ {
+ B3_PROFILE("cpu batchContacts");
+ static b3AlignedObjectArray<b3Contact4> cpuContacts;
+// b3OpenCLArray<b3Contact4>* contactsIn = m_data->m_solverGPU->m_contactBuffer2;
+ {
+ B3_PROFILE("copyToHost");
+ m_data->m_pBufContactOutGPU->copyToHost(cpuContacts);
+ }
+// b3OpenCLArray<unsigned int>* countsNative = m_data->m_solverGPU->m_numConstraints;
+// b3OpenCLArray<unsigned int>* offsetsNative = m_data->m_solverGPU->m_offsets;
+
+
+
+// int numNonzeroGrid=0;
+
+ {
+ m_data->m_batchSizes.resize(B3_MAX_NUM_BATCHES);
+ int totalNumConstraints = cpuContacts.size();
+ // int simdWidth =numBodies+1;//-1;//64;//-1;//32;
+ int numBatches = sortConstraintByBatch3( &cpuContacts[0], totalNumConstraints, totalNumConstraints+1,csCfg.m_staticIdx ,numBodies,&m_data->m_batchSizes[0]); // on GPU
+ maxNumBatches = b3Max(numBatches,maxNumBatches);
+ static int globalMaxBatch = 0;
+ if (maxNumBatches>globalMaxBatch )
+ {
+ globalMaxBatch = maxNumBatches;
+ b3Printf("maxNumBatches = %d\n",maxNumBatches);
+ }
+
+ }
+ {
+ B3_PROFILE("m_contactBuffer->copyFromHost");
+ m_data->m_solverGPU->m_contactBuffer2->copyFromHost((b3AlignedObjectArray<b3Contact4>&)cpuContacts);
+ }
+
+ }
+
+ }
+
+ if (nContacts)
+ {
+ B3_PROFILE("gpu convertToConstraints");
+ m_data->m_solverGPU->convertToConstraints( bodyBuf,
+ shapeBuf, m_data->m_solverGPU->m_contactBuffer2,
+ contactConstraintOut,
+ additionalData, nContacts,
+ (b3SolverBase::ConstraintCfg&) csCfg );
+ clFinish(m_data->m_queue);
+ }
+
+
+ if (1)
+ {
+ int numIter = 4;
+
+ m_data->m_solverGPU->m_nIterations = numIter;//10
+ if (!gCpuSolveConstraint)
+ {
+ B3_PROFILE("GPU solveContactConstraint");
+
+ /*m_data->m_solverGPU->solveContactConstraint(
+ m_data->m_bodyBufferGPU,
+ m_data->m_inertiaBufferGPU,
+ m_data->m_contactCGPU,0,
+ nContactOut ,
+ maxNumBatches);
+ */
+
+ //m_data->m_batchSizesGpu->copyFromHost(m_data->m_batchSizes);
+
+ if (gUseLargeBatches)
+ {
+ solveContactConstraintBatchSizes(m_data->m_bodyBufferGPU,
+ m_data->m_inertiaBufferGPU,
+ m_data->m_contactCGPU,0,
+ nContactOut ,
+ maxNumBatches,numIter,&m_data->m_batchSizes);
+ } else
+ {
+ solveContactConstraint(
+ m_data->m_bodyBufferGPU,
+ m_data->m_inertiaBufferGPU,
+ m_data->m_contactCGPU,0,
+ nContactOut ,
+ maxNumBatches,numIter,&m_data->m_batchSizes);//m_data->m_batchSizesGpu);
+ }
+ }
+ else
+ {
+ B3_PROFILE("Host solveContactConstraint");
+
+ m_data->m_solverGPU->solveContactConstraintHost(m_data->m_bodyBufferGPU, m_data->m_inertiaBufferGPU, m_data->m_contactCGPU,0, nContactOut ,maxNumBatches,&m_data->m_batchSizes);
+ }
+
+
+ }
+
+
+#if 0
+ if (0)
+ {
+ B3_PROFILE("read body velocities back to CPU");
+ //read body updated linear/angular velocities back to CPU
+ m_data->m_bodyBufferGPU->read(
+ m_data->m_bodyBufferCPU->m_ptr,numOfConvexRBodies);
+ adl::DeviceUtils::waitForCompletion( m_data->m_deviceCL );
+ }
+#endif
+
+ }
+
+}
+
+
+void b3GpuPgsContactSolver::batchContacts( b3OpenCLArray<b3Contact4>* contacts, int nContacts, b3OpenCLArray<unsigned int>* n, b3OpenCLArray<unsigned int>* offsets, int staticIdx )
+{
+}
+
+
+
+
+
+
+
+
+
+
+
+b3AlignedObjectArray<unsigned int> idxBuffer;
+b3AlignedObjectArray<b3SortData> sortData;
+b3AlignedObjectArray<b3Contact4> old;
+
+
+inline int b3GpuPgsContactSolver::sortConstraintByBatch( b3Contact4* cs, int n, int simdWidth , int staticIdx, int numBodies)
+{
+
+ B3_PROFILE("sortConstraintByBatch");
+ int numIter = 0;
+
+ sortData.resize(n);
+ idxBuffer.resize(n);
+ old.resize(n);
+
+ unsigned int* idxSrc = &idxBuffer[0];
+ unsigned int* idxDst = &idxBuffer[0];
+ int nIdxSrc, nIdxDst;
+
+ const int N_FLG = 256;
+ const int FLG_MASK = N_FLG-1;
+ unsigned int flg[N_FLG/32];
+#if defined(_DEBUG)
+ for(int i=0; i<n; i++)
+ cs[i].getBatchIdx() = -1;
+#endif
+ for(int i=0; i<n; i++)
+ idxSrc[i] = i;
+ nIdxSrc = n;
+
+ int batchIdx = 0;
+
+ {
+ B3_PROFILE("cpu batch innerloop");
+ while( nIdxSrc )
+ {
+ numIter++;
+ nIdxDst = 0;
+ int nCurrentBatch = 0;
+
+ // clear flag
+ for(int i=0; i<N_FLG/32; i++) flg[i] = 0;
+
+ for(int i=0; i<nIdxSrc; i++)
+ {
+ int idx = idxSrc[i];
+
+
+ b3Assert( idx < n );
+ // check if it can go
+ int bodyAS = cs[idx].m_bodyAPtrAndSignBit;
+ int bodyBS = cs[idx].m_bodyBPtrAndSignBit;
+
+
+
+ int bodyA = abs(bodyAS);
+ int bodyB = abs(bodyBS);
+
+ int aIdx = bodyA & FLG_MASK;
+ int bIdx = bodyB & FLG_MASK;
+
+ unsigned int aUnavailable = flg[ aIdx/32 ] & (1<<(aIdx&31));
+ unsigned int bUnavailable = flg[ bIdx/32 ] & (1<<(bIdx&31));
+
+ bool aIsStatic = (bodyAS<0) || bodyAS==staticIdx;
+ bool bIsStatic = (bodyBS<0) || bodyBS==staticIdx;
+
+ //use inv_mass!
+ aUnavailable = !aIsStatic? aUnavailable:0;//
+ bUnavailable = !bIsStatic? bUnavailable:0;
+
+ if( aUnavailable==0 && bUnavailable==0 ) // ok
+ {
+ if (!aIsStatic)
+ flg[ aIdx/32 ] |= (1<<(aIdx&31));
+ if (!bIsStatic)
+ flg[ bIdx/32 ] |= (1<<(bIdx&31));
+
+ cs[idx].getBatchIdx() = batchIdx;
+ sortData[idx].m_key = batchIdx;
+ sortData[idx].m_value = idx;
+
+ {
+ nCurrentBatch++;
+ if( nCurrentBatch == simdWidth )
+ {
+ nCurrentBatch = 0;
+ for(int i=0; i<N_FLG/32; i++) flg[i] = 0;
+ }
+ }
+ }
+ else
+ {
+ idxDst[nIdxDst++] = idx;
+ }
+ }
+ b3Swap( idxSrc, idxDst );
+ b3Swap( nIdxSrc, nIdxDst );
+ batchIdx ++;
+ }
+ }
+ {
+ B3_PROFILE("quickSort");
+ sortData.quickSort(sortfnc);
+ }
+
+
+ {
+ B3_PROFILE("reorder");
+ // reorder
+
+ memcpy( &old[0], cs, sizeof(b3Contact4)*n);
+ for(int i=0; i<n; i++)
+ {
+ int idx = sortData[i].m_value;
+ cs[i] = old[idx];
+ }
+ }
+
+
+#if defined(_DEBUG)
+ // debugPrintf( "nBatches: %d\n", batchIdx );
+ for(int i=0; i<n; i++)
+ {
+ b3Assert( cs[i].getBatchIdx() != -1 );
+ }
+#endif
+ return batchIdx;
+}
+
+
+b3AlignedObjectArray<int> bodyUsed2;
+
+inline int b3GpuPgsContactSolver::sortConstraintByBatch2( b3Contact4* cs, int numConstraints, int simdWidth , int staticIdx, int numBodies)
+{
+
+ B3_PROFILE("sortConstraintByBatch2");
+
+
+
+ bodyUsed2.resize(2*simdWidth);
+
+ for (int q=0;q<2*simdWidth;q++)
+ bodyUsed2[q]=0;
+
+ int curBodyUsed = 0;
+
+ int numIter = 0;
+
+ m_data->m_sortData.resize(numConstraints);
+ m_data->m_idxBuffer.resize(numConstraints);
+ m_data->m_old.resize(numConstraints);
+
+ unsigned int* idxSrc = &m_data->m_idxBuffer[0];
+
+#if defined(_DEBUG)
+ for(int i=0; i<numConstraints; i++)
+ cs[i].getBatchIdx() = -1;
+#endif
+ for(int i=0; i<numConstraints; i++)
+ idxSrc[i] = i;
+
+ int numValidConstraints = 0;
+// int unprocessedConstraintIndex = 0;
+
+ int batchIdx = 0;
+
+
+ {
+ B3_PROFILE("cpu batch innerloop");
+
+ while( numValidConstraints < numConstraints)
+ {
+ numIter++;
+ int nCurrentBatch = 0;
+ // clear flag
+ for(int i=0; i<curBodyUsed; i++)
+ bodyUsed2[i] = 0;
+ curBodyUsed = 0;
+
+ for(int i=numValidConstraints; i<numConstraints; i++)
+ {
+ int idx = idxSrc[i];
+ b3Assert( idx < numConstraints );
+ // check if it can go
+ int bodyAS = cs[idx].m_bodyAPtrAndSignBit;
+ int bodyBS = cs[idx].m_bodyBPtrAndSignBit;
+ int bodyA = abs(bodyAS);
+ int bodyB = abs(bodyBS);
+ bool aIsStatic = (bodyAS<0) || bodyAS==staticIdx;
+ bool bIsStatic = (bodyBS<0) || bodyBS==staticIdx;
+ int aUnavailable = 0;
+ int bUnavailable = 0;
+ if (!aIsStatic)
+ {
+ for (int j=0;j<curBodyUsed;j++)
+ {
+ if (bodyA == bodyUsed2[j])
+ {
+ aUnavailable=1;
+ break;
+ }
+ }
+ }
+ if (!aUnavailable)
+ if (!bIsStatic)
+ {
+ for (int j=0;j<curBodyUsed;j++)
+ {
+ if (bodyB == bodyUsed2[j])
+ {
+ bUnavailable=1;
+ break;
+ }
+ }
+ }
+
+ if( aUnavailable==0 && bUnavailable==0 ) // ok
+ {
+ if (!aIsStatic)
+ {
+ bodyUsed2[curBodyUsed++] = bodyA;
+ }
+ if (!bIsStatic)
+ {
+ bodyUsed2[curBodyUsed++] = bodyB;
+ }
+
+ cs[idx].getBatchIdx() = batchIdx;
+ m_data->m_sortData[idx].m_key = batchIdx;
+ m_data->m_sortData[idx].m_value = idx;
+
+ if (i!=numValidConstraints)
+ {
+ b3Swap(idxSrc[i], idxSrc[numValidConstraints]);
+ }
+
+ numValidConstraints++;
+ {
+ nCurrentBatch++;
+ if( nCurrentBatch == simdWidth )
+ {
+ nCurrentBatch = 0;
+ for(int i=0; i<curBodyUsed; i++)
+ bodyUsed2[i] = 0;
+
+
+ curBodyUsed = 0;
+ }
+ }
+ }
+ }
+
+ batchIdx ++;
+ }
+ }
+ {
+ B3_PROFILE("quickSort");
+ //m_data->m_sortData.quickSort(sortfnc);
+ }
+
+ {
+ B3_PROFILE("reorder");
+ // reorder
+
+ memcpy( &m_data->m_old[0], cs, sizeof(b3Contact4)*numConstraints);
+
+ for(int i=0; i<numConstraints; i++)
+ {
+ b3Assert(m_data->m_sortData[idxSrc[i]].m_value == idxSrc[i]);
+ int idx = m_data->m_sortData[idxSrc[i]].m_value;
+ cs[i] = m_data->m_old[idx];
+ }
+ }
+
+#if defined(_DEBUG)
+ // debugPrintf( "nBatches: %d\n", batchIdx );
+ for(int i=0; i<numConstraints; i++)
+ {
+ b3Assert( cs[i].getBatchIdx() != -1 );
+ }
+#endif
+
+
+ return batchIdx;
+}
+
+
+b3AlignedObjectArray<int> bodyUsed;
+b3AlignedObjectArray<int> curUsed;
+
+
+inline int b3GpuPgsContactSolver::sortConstraintByBatch3( b3Contact4* cs, int numConstraints, int simdWidth , int staticIdx, int numBodies, int* batchSizes)
+{
+
+ B3_PROFILE("sortConstraintByBatch3");
+
+ static int maxSwaps = 0;
+ int numSwaps = 0;
+
+ curUsed.resize(2*simdWidth);
+
+ static int maxNumConstraints = 0;
+ if (maxNumConstraints<numConstraints)
+ {
+ maxNumConstraints = numConstraints;
+ //printf("maxNumConstraints = %d\n",maxNumConstraints );
+ }
+
+ int numUsedArray = numBodies/32+1;
+ bodyUsed.resize(numUsedArray);
+
+ for (int q=0;q<numUsedArray;q++)
+ bodyUsed[q]=0;
+
+
+ int curBodyUsed = 0;
+
+ int numIter = 0;
+
+ m_data->m_sortData.resize(0);
+ m_data->m_idxBuffer.resize(0);
+ m_data->m_old.resize(0);
+
+
+#if defined(_DEBUG)
+ for(int i=0; i<numConstraints; i++)
+ cs[i].getBatchIdx() = -1;
+#endif
+
+ int numValidConstraints = 0;
+// int unprocessedConstraintIndex = 0;
+
+ int batchIdx = 0;
+
+
+ {
+ B3_PROFILE("cpu batch innerloop");
+
+ while( numValidConstraints < numConstraints)
+ {
+ numIter++;
+ int nCurrentBatch = 0;
+ batchSizes[batchIdx] = 0;
+
+ // clear flag
+ for(int i=0; i<curBodyUsed; i++)
+ bodyUsed[curUsed[i]/32] = 0;
+
+ curBodyUsed = 0;
+
+ for(int i=numValidConstraints; i<numConstraints; i++)
+ {
+ int idx = i;
+ b3Assert( idx < numConstraints );
+ // check if it can go
+ int bodyAS = cs[idx].m_bodyAPtrAndSignBit;
+ int bodyBS = cs[idx].m_bodyBPtrAndSignBit;
+ int bodyA = abs(bodyAS);
+ int bodyB = abs(bodyBS);
+ bool aIsStatic = (bodyAS<0) || bodyAS==staticIdx;
+ bool bIsStatic = (bodyBS<0) || bodyBS==staticIdx;
+ int aUnavailable = 0;
+ int bUnavailable = 0;
+ if (!aIsStatic)
+ {
+ aUnavailable = bodyUsed[ bodyA/32 ] & (1<<(bodyA&31));
+ }
+ if (!aUnavailable)
+ if (!bIsStatic)
+ {
+ bUnavailable = bodyUsed[ bodyB/32 ] & (1<<(bodyB&31));
+ }
+
+ if( aUnavailable==0 && bUnavailable==0 ) // ok
+ {
+ if (!aIsStatic)
+ {
+ bodyUsed[ bodyA/32 ] |= (1<<(bodyA&31));
+ curUsed[curBodyUsed++]=bodyA;
+ }
+ if (!bIsStatic)
+ {
+ bodyUsed[ bodyB/32 ] |= (1<<(bodyB&31));
+ curUsed[curBodyUsed++]=bodyB;
+ }
+
+ cs[idx].getBatchIdx() = batchIdx;
+
+ if (i!=numValidConstraints)
+ {
+ b3Swap(cs[i],cs[numValidConstraints]);
+ numSwaps++;
+ }
+
+ numValidConstraints++;
+ {
+ nCurrentBatch++;
+ if( nCurrentBatch == simdWidth )
+ {
+ batchSizes[batchIdx] += simdWidth;
+ nCurrentBatch = 0;
+ for(int i=0; i<curBodyUsed; i++)
+ bodyUsed[curUsed[i]/32] = 0;
+ curBodyUsed = 0;
+ }
+ }
+ }
+ }
+
+ if (batchIdx>=B3_MAX_NUM_BATCHES)
+ {
+ b3Error("batchIdx>=B3_MAX_NUM_BATCHES");
+ b3Assert(0);
+ break;
+ }
+
+ batchSizes[batchIdx] += nCurrentBatch;
+
+ batchIdx ++;
+
+ }
+ }
+
+#if defined(_DEBUG)
+ // debugPrintf( "nBatches: %d\n", batchIdx );
+ for(int i=0; i<numConstraints; i++)
+ {
+ b3Assert( cs[i].getBatchIdx() != -1 );
+ }
+#endif
+
+ batchSizes[batchIdx] =0;
+
+ if (maxSwaps<numSwaps)
+ {
+ maxSwaps = numSwaps;
+ //printf("maxSwaps = %d\n", maxSwaps);
+ }
+
+ return batchIdx;
+}
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuPgsContactSolver.h b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuPgsContactSolver.h
new file mode 100644
index 0000000000..98e2a5b8c4
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuPgsContactSolver.h
@@ -0,0 +1,43 @@
+
+#ifndef B3_GPU_BATCHING_PGS_SOLVER_H
+#define B3_GPU_BATCHING_PGS_SOLVER_H
+
+#include "Bullet3OpenCL/Initialize/b3OpenCLInclude.h"
+#include "Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
+#include "Bullet3Collision/NarrowPhaseCollision/b3Contact4.h"
+#include "b3GpuConstraint4.h"
+
+class b3GpuPgsContactSolver
+{
+protected:
+
+ int m_debugOutput;
+
+ struct b3GpuBatchingPgsSolverInternalData* m_data;
+
+ void batchContacts( b3OpenCLArray<b3Contact4>* contacts, int nContacts, b3OpenCLArray<unsigned int>* n, b3OpenCLArray<unsigned int>* offsets, int staticIdx );
+
+ inline int sortConstraintByBatch( b3Contact4* cs, int n, int simdWidth , int staticIdx, int numBodies);
+ inline int sortConstraintByBatch2( b3Contact4* cs, int n, int simdWidth , int staticIdx, int numBodies);
+ inline int sortConstraintByBatch3( b3Contact4* cs, int n, int simdWidth , int staticIdx, int numBodies, int* batchSizes);
+
+
+
+ void solveContactConstraintBatchSizes( const b3OpenCLArray<b3RigidBodyData>* bodyBuf, const b3OpenCLArray<b3InertiaData>* shapeBuf,
+ b3OpenCLArray<b3GpuConstraint4>* constraint, void* additionalData, int n ,int maxNumBatches, int numIterations, const b3AlignedObjectArray<int>* batchSizes);//const b3OpenCLArray<int>* gpuBatchSizes);
+
+ void solveContactConstraint( const b3OpenCLArray<b3RigidBodyData>* bodyBuf, const b3OpenCLArray<b3InertiaData>* shapeBuf,
+ b3OpenCLArray<b3GpuConstraint4>* constraint, void* additionalData, int n ,int maxNumBatches, int numIterations, const b3AlignedObjectArray<int>* batchSizes);//const b3OpenCLArray<int>* gpuBatchSizes);
+
+public:
+
+ b3GpuPgsContactSolver(cl_context ctx,cl_device_id device, cl_command_queue q,int pairCapacity);
+ virtual ~b3GpuPgsContactSolver();
+
+ void solveContacts(int numBodies, cl_mem bodyBuf, cl_mem inertiaBuf, int numContacts, cl_mem contactBuf, const struct b3Config& config, int static0Index);
+
+};
+
+#endif //B3_GPU_BATCHING_PGS_SOLVER_H
+
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuRigidBodyPipeline.cpp b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuRigidBodyPipeline.cpp
new file mode 100644
index 0000000000..783e443060
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuRigidBodyPipeline.cpp
@@ -0,0 +1,708 @@
+/*
+Copyright (c) 2013 Advanced Micro Devices, Inc.
+
+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.
+*/
+//Originally written by Erwin Coumans
+
+#include "b3GpuRigidBodyPipeline.h"
+#include "b3GpuRigidBodyPipelineInternalData.h"
+#include "kernels/integrateKernel.h"
+#include "kernels/updateAabbsKernel.h"
+
+#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
+#include "b3GpuNarrowPhase.h"
+#include "Bullet3Geometry/b3AabbUtil.h"
+#include "Bullet3OpenCL/BroadphaseCollision/b3SapAabb.h"
+#include "Bullet3OpenCL/BroadphaseCollision/b3GpuBroadphaseInterface.h"
+#include "Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.h"
+#include "Bullet3Dynamics/ConstraintSolver/b3PgsJacobiSolver.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3UpdateAabbs.h"
+#include "Bullet3Collision/BroadPhaseCollision/b3DynamicBvhBroadphase.h"
+
+//#define TEST_OTHER_GPU_SOLVER
+
+#define B3_RIGIDBODY_INTEGRATE_PATH "src/Bullet3OpenCL/RigidBody/kernels/integrateKernel.cl"
+#define B3_RIGIDBODY_UPDATEAABB_PATH "src/Bullet3OpenCL/RigidBody/kernels/updateAabbsKernel.cl"
+
+bool useBullet2CpuSolver = true;
+
+//choice of contact solver
+bool gUseJacobi = false;
+bool gUseDbvt = false;
+bool gDumpContactStats = false;
+bool gCalcWorldSpaceAabbOnCpu = false;
+bool gUseCalculateOverlappingPairsHost = false;
+bool gIntegrateOnCpu = false;
+bool gClearPairsOnGpu = true;
+
+#define TEST_OTHER_GPU_SOLVER 1
+#ifdef TEST_OTHER_GPU_SOLVER
+#include "b3GpuJacobiContactSolver.h"
+#endif //TEST_OTHER_GPU_SOLVER
+
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
+#include "Bullet3Collision/NarrowPhaseCollision/b3Contact4.h"
+#include "Bullet3OpenCL/RigidBody/b3GpuPgsConstraintSolver.h"
+
+#include "b3GpuPgsContactSolver.h"
+#include "b3Solver.h"
+
+#include "Bullet3Collision/NarrowPhaseCollision/b3Config.h"
+#include "Bullet3OpenCL/Raycast/b3GpuRaycast.h"
+
+
+#include "Bullet3Dynamics/shared/b3IntegrateTransforms.h"
+#include "Bullet3OpenCL/RigidBody/b3GpuNarrowPhaseInternalData.h"
+
+b3GpuRigidBodyPipeline::b3GpuRigidBodyPipeline(cl_context ctx,cl_device_id device, cl_command_queue q,class b3GpuNarrowPhase* narrowphase, class b3GpuBroadphaseInterface* broadphaseSap , struct b3DynamicBvhBroadphase* broadphaseDbvt, const b3Config& config)
+{
+ m_data = new b3GpuRigidBodyPipelineInternalData;
+ m_data->m_constraintUid=0;
+ m_data->m_config = config;
+ m_data->m_context = ctx;
+ m_data->m_device = device;
+ m_data->m_queue = q;
+
+ m_data->m_solver = new b3PgsJacobiSolver(true);//new b3PgsJacobiSolver(true);
+ m_data->m_gpuSolver = new b3GpuPgsConstraintSolver(ctx,device,q,true);//new b3PgsJacobiSolver(true);
+
+ m_data->m_allAabbsGPU = new b3OpenCLArray<b3SapAabb>(ctx,q,config.m_maxConvexBodies);
+ m_data->m_overlappingPairsGPU = new b3OpenCLArray<b3BroadphasePair>(ctx,q,config.m_maxBroadphasePairs);
+
+ m_data->m_gpuConstraints = new b3OpenCLArray<b3GpuGenericConstraint>(ctx,q);
+#ifdef TEST_OTHER_GPU_SOLVER
+ m_data->m_solver3 = new b3GpuJacobiContactSolver(ctx,device,q,config.m_maxBroadphasePairs);
+#endif // TEST_OTHER_GPU_SOLVER
+
+ m_data->m_solver2 = new b3GpuPgsContactSolver(ctx,device,q,config.m_maxBroadphasePairs);
+
+ m_data->m_raycaster = new b3GpuRaycast(ctx,device,q);
+
+
+ m_data->m_broadphaseDbvt = broadphaseDbvt;
+ m_data->m_broadphaseSap = broadphaseSap;
+ m_data->m_narrowphase = narrowphase;
+ m_data->m_gravity.setValue(0.f,-9.8f,0.f);
+
+ cl_int errNum=0;
+
+ {
+ cl_program prog = b3OpenCLUtils::compileCLProgramFromString(m_data->m_context,m_data->m_device,integrateKernelCL,&errNum,"",B3_RIGIDBODY_INTEGRATE_PATH);
+ b3Assert(errNum==CL_SUCCESS);
+ m_data->m_integrateTransformsKernel = b3OpenCLUtils::compileCLKernelFromString(m_data->m_context, m_data->m_device,integrateKernelCL, "integrateTransformsKernel",&errNum,prog);
+ b3Assert(errNum==CL_SUCCESS);
+ clReleaseProgram(prog);
+ }
+ {
+ cl_program prog = b3OpenCLUtils::compileCLProgramFromString(m_data->m_context,m_data->m_device,updateAabbsKernelCL,&errNum,"",B3_RIGIDBODY_UPDATEAABB_PATH);
+ b3Assert(errNum==CL_SUCCESS);
+ m_data->m_updateAabbsKernel = b3OpenCLUtils::compileCLKernelFromString(m_data->m_context, m_data->m_device,updateAabbsKernelCL, "initializeGpuAabbsFull",&errNum,prog);
+ b3Assert(errNum==CL_SUCCESS);
+
+
+ m_data->m_clearOverlappingPairsKernel = b3OpenCLUtils::compileCLKernelFromString(m_data->m_context, m_data->m_device,updateAabbsKernelCL, "clearOverlappingPairsKernel",&errNum,prog);
+ b3Assert(errNum==CL_SUCCESS);
+
+ clReleaseProgram(prog);
+ }
+
+
+}
+
+b3GpuRigidBodyPipeline::~b3GpuRigidBodyPipeline()
+{
+ if (m_data->m_integrateTransformsKernel)
+ clReleaseKernel(m_data->m_integrateTransformsKernel);
+
+ if (m_data->m_updateAabbsKernel)
+ clReleaseKernel(m_data->m_updateAabbsKernel);
+
+ if (m_data->m_clearOverlappingPairsKernel)
+ clReleaseKernel(m_data->m_clearOverlappingPairsKernel);
+ delete m_data->m_raycaster;
+ delete m_data->m_solver;
+ delete m_data->m_allAabbsGPU;
+ delete m_data->m_gpuConstraints;
+ delete m_data->m_overlappingPairsGPU;
+
+#ifdef TEST_OTHER_GPU_SOLVER
+ delete m_data->m_solver3;
+#endif //TEST_OTHER_GPU_SOLVER
+
+ delete m_data->m_solver2;
+
+
+ delete m_data;
+}
+
+void b3GpuRigidBodyPipeline::reset()
+{
+ m_data->m_gpuConstraints->resize(0);
+ m_data->m_cpuConstraints.resize(0);
+ m_data->m_allAabbsGPU->resize(0);
+ m_data->m_allAabbsCPU.resize(0);
+}
+
+void b3GpuRigidBodyPipeline::addConstraint(b3TypedConstraint* constraint)
+{
+ m_data->m_joints.push_back(constraint);
+}
+
+void b3GpuRigidBodyPipeline::removeConstraint(b3TypedConstraint* constraint)
+{
+ m_data->m_joints.remove(constraint);
+}
+
+
+
+void b3GpuRigidBodyPipeline::removeConstraintByUid(int uid)
+{
+ m_data->m_gpuSolver->recomputeBatches();
+ //slow linear search
+ m_data->m_gpuConstraints->copyToHost(m_data->m_cpuConstraints);
+ //remove
+ for (int i=0;i<m_data->m_cpuConstraints.size();i++)
+ {
+ if (m_data->m_cpuConstraints[i].m_uid == uid)
+ {
+ //m_data->m_cpuConstraints.remove(m_data->m_cpuConstraints[i]);
+ m_data->m_cpuConstraints.swap(i,m_data->m_cpuConstraints.size()-1);
+ m_data->m_cpuConstraints.pop_back();
+
+ break;
+ }
+ }
+
+ if (m_data->m_cpuConstraints.size())
+ {
+ m_data->m_gpuConstraints->copyFromHost(m_data->m_cpuConstraints);
+ } else
+ {
+ m_data->m_gpuConstraints->resize(0);
+ }
+
+}
+int b3GpuRigidBodyPipeline::createPoint2PointConstraint(int bodyA, int bodyB, const float* pivotInA, const float* pivotInB,float breakingThreshold)
+{
+ m_data->m_gpuSolver->recomputeBatches();
+ b3GpuGenericConstraint c;
+ c.m_uid = m_data->m_constraintUid;
+ m_data->m_constraintUid++;
+ c.m_flags = B3_CONSTRAINT_FLAG_ENABLED;
+ c.m_rbA = bodyA;
+ c.m_rbB = bodyB;
+ c.m_pivotInA.setValue(pivotInA[0],pivotInA[1],pivotInA[2]);
+ c.m_pivotInB.setValue(pivotInB[0],pivotInB[1],pivotInB[2]);
+ c.m_breakingImpulseThreshold = breakingThreshold;
+ c.m_constraintType = B3_GPU_POINT2POINT_CONSTRAINT_TYPE;
+ m_data->m_cpuConstraints.push_back(c);
+ return c.m_uid;
+}
+int b3GpuRigidBodyPipeline::createFixedConstraint(int bodyA, int bodyB, const float* pivotInA, const float* pivotInB, const float* relTargetAB,float breakingThreshold)
+{
+ m_data->m_gpuSolver->recomputeBatches();
+ b3GpuGenericConstraint c;
+ c.m_uid = m_data->m_constraintUid;
+ m_data->m_constraintUid++;
+ c.m_flags = B3_CONSTRAINT_FLAG_ENABLED;
+ c.m_rbA = bodyA;
+ c.m_rbB = bodyB;
+ c.m_pivotInA.setValue(pivotInA[0],pivotInA[1],pivotInA[2]);
+ c.m_pivotInB.setValue(pivotInB[0],pivotInB[1],pivotInB[2]);
+ c.m_relTargetAB.setValue(relTargetAB[0],relTargetAB[1],relTargetAB[2],relTargetAB[3]);
+ c.m_breakingImpulseThreshold = breakingThreshold;
+ c.m_constraintType = B3_GPU_FIXED_CONSTRAINT_TYPE;
+
+ m_data->m_cpuConstraints.push_back(c);
+ return c.m_uid;
+}
+
+
+void b3GpuRigidBodyPipeline::stepSimulation(float deltaTime)
+{
+
+ //update worldspace AABBs from local AABB/worldtransform
+ {
+ B3_PROFILE("setupGpuAabbs");
+ setupGpuAabbsFull();
+ }
+
+ int numPairs =0;
+
+ //compute overlapping pairs
+ {
+
+ if (gUseDbvt)
+ {
+ {
+ B3_PROFILE("setAabb");
+ m_data->m_allAabbsGPU->copyToHost(m_data->m_allAabbsCPU);
+ for (int i=0;i<m_data->m_allAabbsCPU.size();i++)
+ {
+ b3Vector3 aabbMin=b3MakeVector3(m_data->m_allAabbsCPU[i].m_min[0],m_data->m_allAabbsCPU[i].m_min[1],m_data->m_allAabbsCPU[i].m_min[2]);
+ b3Vector3 aabbMax=b3MakeVector3(m_data->m_allAabbsCPU[i].m_max[0],m_data->m_allAabbsCPU[i].m_max[1],m_data->m_allAabbsCPU[i].m_max[2]);
+ m_data->m_broadphaseDbvt->setAabb(i,aabbMin,aabbMax,0);
+ }
+ }
+
+ {
+ B3_PROFILE("calculateOverlappingPairs");
+ m_data->m_broadphaseDbvt->calculateOverlappingPairs();
+ }
+ numPairs = m_data->m_broadphaseDbvt->getOverlappingPairCache()->getNumOverlappingPairs();
+
+ } else
+ {
+ if (gUseCalculateOverlappingPairsHost)
+ {
+ m_data->m_broadphaseSap->calculateOverlappingPairsHost(m_data->m_config.m_maxBroadphasePairs);
+ } else
+ {
+ m_data->m_broadphaseSap->calculateOverlappingPairs(m_data->m_config.m_maxBroadphasePairs);
+ }
+ numPairs = m_data->m_broadphaseSap->getNumOverlap();
+ }
+ }
+
+ //compute contact points
+// printf("numPairs=%d\n",numPairs);
+
+ int numContacts = 0;
+
+
+ int numBodies = m_data->m_narrowphase->getNumRigidBodies();
+
+ if (numPairs)
+ {
+ cl_mem pairs =0;
+ cl_mem aabbsWS =0;
+ if (gUseDbvt)
+ {
+ B3_PROFILE("m_overlappingPairsGPU->copyFromHost");
+ m_data->m_overlappingPairsGPU->copyFromHost(m_data->m_broadphaseDbvt->getOverlappingPairCache()->getOverlappingPairArray());
+ pairs = m_data->m_overlappingPairsGPU->getBufferCL();
+ aabbsWS = m_data->m_allAabbsGPU->getBufferCL();
+ } else
+ {
+ pairs = m_data->m_broadphaseSap->getOverlappingPairBuffer();
+ aabbsWS = m_data->m_broadphaseSap->getAabbBufferWS();
+ }
+
+ m_data->m_overlappingPairsGPU->resize(numPairs);
+
+ //mark the contacts for each pair as 'unused'
+ if (numPairs)
+ {
+ b3OpenCLArray<b3BroadphasePair> gpuPairs(this->m_data->m_context,m_data->m_queue);
+ gpuPairs.setFromOpenCLBuffer(pairs,numPairs);
+
+ if (gClearPairsOnGpu)
+ {
+
+
+ //b3AlignedObjectArray<b3BroadphasePair> hostPairs;//just for debugging
+ //gpuPairs.copyToHost(hostPairs);
+
+ b3LauncherCL launcher(m_data->m_queue,m_data->m_clearOverlappingPairsKernel,"clearOverlappingPairsKernel");
+ launcher.setBuffer(pairs);
+ launcher.setConst(numPairs);
+ launcher.launch1D(numPairs);
+
+
+ //gpuPairs.copyToHost(hostPairs);
+
+
+ } else
+ {
+ b3AlignedObjectArray<b3BroadphasePair> hostPairs;
+ gpuPairs.copyToHost(hostPairs);
+
+ for (int i=0;i<hostPairs.size();i++)
+ {
+ hostPairs[i].z = 0xffffffff;
+ }
+
+ gpuPairs.copyFromHost(hostPairs);
+ }
+ }
+
+ m_data->m_narrowphase->computeContacts(pairs,numPairs,aabbsWS,numBodies);
+ numContacts = m_data->m_narrowphase->getNumContactsGpu();
+
+ if (gUseDbvt)
+ {
+ ///store the cached information (contact locations in the 'z' component)
+ B3_PROFILE("m_overlappingPairsGPU->copyToHost");
+ m_data->m_overlappingPairsGPU->copyToHost(m_data->m_broadphaseDbvt->getOverlappingPairCache()->getOverlappingPairArray());
+ }
+ if (gDumpContactStats && numContacts)
+ {
+ m_data->m_narrowphase->getContactsGpu();
+
+ printf("numContacts = %d\n", numContacts);
+
+ int totalPoints = 0;
+ const b3Contact4* contacts = m_data->m_narrowphase->getContactsCPU();
+
+ for (int i=0;i<numContacts;i++)
+ {
+ totalPoints += contacts->getNPoints();
+ }
+ printf("totalPoints=%d\n",totalPoints);
+
+ }
+ }
+
+
+ //convert contact points to contact constraints
+
+ //solve constraints
+
+ b3OpenCLArray<b3RigidBodyData> gpuBodies(m_data->m_context,m_data->m_queue,0,true);
+ gpuBodies.setFromOpenCLBuffer(m_data->m_narrowphase->getBodiesGpu(),m_data->m_narrowphase->getNumRigidBodies());
+ b3OpenCLArray<b3InertiaData> gpuInertias(m_data->m_context,m_data->m_queue,0,true);
+ gpuInertias.setFromOpenCLBuffer(m_data->m_narrowphase->getBodyInertiasGpu(),m_data->m_narrowphase->getNumRigidBodies());
+ b3OpenCLArray<b3Contact4> gpuContacts(m_data->m_context,m_data->m_queue,0,true);
+ gpuContacts.setFromOpenCLBuffer(m_data->m_narrowphase->getContactsGpu(),m_data->m_narrowphase->getNumContactsGpu());
+
+ int numJoints = m_data->m_joints.size() ? m_data->m_joints.size() : m_data->m_cpuConstraints.size();
+ if (useBullet2CpuSolver && numJoints)
+ {
+
+ // b3AlignedObjectArray<b3Contact4> hostContacts;
+ //gpuContacts.copyToHost(hostContacts);
+ {
+ bool useGpu = m_data->m_joints.size()==0;
+
+// b3Contact4* contacts = numContacts? &hostContacts[0]: 0;
+ //m_data->m_solver->solveContacts(m_data->m_narrowphase->getNumBodiesGpu(),&hostBodies[0],&hostInertias[0],numContacts,contacts,numJoints, joints);
+ if (useGpu)
+ {
+ m_data->m_gpuSolver->solveJoints(m_data->m_narrowphase->getNumRigidBodies(),&gpuBodies,&gpuInertias,numJoints, m_data->m_gpuConstraints);
+ } else
+ {
+ b3AlignedObjectArray<b3RigidBodyData> hostBodies;
+ gpuBodies.copyToHost(hostBodies);
+ b3AlignedObjectArray<b3InertiaData> hostInertias;
+ gpuInertias.copyToHost(hostInertias);
+
+ b3TypedConstraint** joints = numJoints? &m_data->m_joints[0] : 0;
+ m_data->m_solver->solveContacts(m_data->m_narrowphase->getNumRigidBodies(),&hostBodies[0],&hostInertias[0],0,0,numJoints, joints);
+ gpuBodies.copyFromHost(hostBodies);
+ }
+ }
+ }
+
+ if (numContacts)
+ {
+
+#ifdef TEST_OTHER_GPU_SOLVER
+
+ if (gUseJacobi)
+ {
+ bool useGpu = true;
+ if (useGpu)
+ {
+
+ bool forceHost = false;
+ if (forceHost)
+ {
+ b3AlignedObjectArray<b3RigidBodyData> hostBodies;
+ b3AlignedObjectArray<b3InertiaData> hostInertias;
+ b3AlignedObjectArray<b3Contact4> hostContacts;
+
+ {
+ B3_PROFILE("copyToHost");
+ gpuBodies.copyToHost(hostBodies);
+ gpuInertias.copyToHost(hostInertias);
+ gpuContacts.copyToHost(hostContacts);
+ }
+
+ {
+ b3JacobiSolverInfo solverInfo;
+ m_data->m_solver3->solveGroupHost(&hostBodies[0], &hostInertias[0], hostBodies.size(),&hostContacts[0],hostContacts.size(),solverInfo);
+
+
+ }
+ {
+ B3_PROFILE("copyFromHost");
+ gpuBodies.copyFromHost(hostBodies);
+ }
+ } else
+
+
+ {
+ int static0Index = m_data->m_narrowphase->getStatic0Index();
+ b3JacobiSolverInfo solverInfo;
+ //m_data->m_solver3->solveContacts( >solveGroup(&gpuBodies, &gpuInertias, &gpuContacts,solverInfo);
+ //m_data->m_solver3->solveContacts(m_data->m_narrowphase->getNumBodiesGpu(),&hostBodies[0],&hostInertias[0],numContacts,&hostContacts[0]);
+ m_data->m_solver3->solveContacts(numBodies, gpuBodies.getBufferCL(),gpuInertias.getBufferCL(),numContacts, gpuContacts.getBufferCL(),m_data->m_config, static0Index);
+ }
+ } else
+ {
+ b3AlignedObjectArray<b3RigidBodyData> hostBodies;
+ gpuBodies.copyToHost(hostBodies);
+ b3AlignedObjectArray<b3InertiaData> hostInertias;
+ gpuInertias.copyToHost(hostInertias);
+ b3AlignedObjectArray<b3Contact4> hostContacts;
+ gpuContacts.copyToHost(hostContacts);
+ {
+ //m_data->m_solver->solveContacts(m_data->m_narrowphase->getNumBodiesGpu(),&hostBodies[0],&hostInertias[0],numContacts,&hostContacts[0]);
+ }
+ gpuBodies.copyFromHost(hostBodies);
+ }
+
+ } else
+#endif //TEST_OTHER_GPU_SOLVER
+ {
+
+ int static0Index = m_data->m_narrowphase->getStatic0Index();
+ m_data->m_solver2->solveContacts(numBodies, gpuBodies.getBufferCL(),gpuInertias.getBufferCL(),numContacts, gpuContacts.getBufferCL(),m_data->m_config, static0Index);
+
+ //m_data->m_solver4->solveContacts(m_data->m_narrowphase->getNumBodiesGpu(), gpuBodies.getBufferCL(), gpuInertias.getBufferCL(), numContacts, gpuContacts.getBufferCL());
+
+
+ /*m_data->m_solver3->solveContactConstraintHost(
+ (b3OpenCLArray<RigidBodyBase::Body>*)&gpuBodies,
+ (b3OpenCLArray<RigidBodyBase::Inertia>*)&gpuInertias,
+ (b3OpenCLArray<Constraint4>*) &gpuContacts,
+ 0,numContacts,256);
+ */
+ }
+ }
+
+ integrate(deltaTime);
+
+}
+
+
+void b3GpuRigidBodyPipeline::integrate(float timeStep)
+{
+ //integrate
+ int numBodies = m_data->m_narrowphase->getNumRigidBodies();
+ float angularDamp = 0.99f;
+
+ if (gIntegrateOnCpu)
+ {
+ if(numBodies)
+ {
+ b3GpuNarrowPhaseInternalData* npData = m_data->m_narrowphase->getInternalData();
+ npData->m_bodyBufferGPU->copyToHost(*npData->m_bodyBufferCPU);
+
+ b3RigidBodyData_t* bodies = &npData->m_bodyBufferCPU->at(0);
+
+ for (int nodeID=0;nodeID<numBodies;nodeID++)
+ {
+ integrateSingleTransform( bodies,nodeID, timeStep, angularDamp, m_data->m_gravity);
+ }
+ npData->m_bodyBufferGPU->copyFromHost(*npData->m_bodyBufferCPU);
+ }
+ } else
+ {
+ b3LauncherCL launcher(m_data->m_queue,m_data->m_integrateTransformsKernel,"m_integrateTransformsKernel");
+ launcher.setBuffer(m_data->m_narrowphase->getBodiesGpu());
+
+ launcher.setConst(numBodies);
+ launcher.setConst(timeStep);
+ launcher.setConst(angularDamp);
+ launcher.setConst(m_data->m_gravity);
+ launcher.launch1D(numBodies);
+ }
+}
+
+
+
+
+void b3GpuRigidBodyPipeline::setupGpuAabbsFull()
+{
+ cl_int ciErrNum=0;
+
+ int numBodies = m_data->m_narrowphase->getNumRigidBodies();
+ if (!numBodies)
+ return;
+
+ if (gCalcWorldSpaceAabbOnCpu)
+ {
+
+ if (numBodies)
+ {
+ if (gUseDbvt)
+ {
+ m_data->m_allAabbsCPU.resize(numBodies);
+ m_data->m_narrowphase->readbackAllBodiesToCpu();
+ for (int i=0;i<numBodies;i++)
+ {
+ b3ComputeWorldAabb( i, m_data->m_narrowphase->getBodiesCpu(), m_data->m_narrowphase->getCollidablesCpu(), m_data->m_narrowphase->getLocalSpaceAabbsCpu(),&m_data->m_allAabbsCPU[0]);
+ }
+ m_data->m_allAabbsGPU->copyFromHost(m_data->m_allAabbsCPU);
+ } else
+ {
+ m_data->m_broadphaseSap->getAllAabbsCPU().resize(numBodies);
+ m_data->m_narrowphase->readbackAllBodiesToCpu();
+ for (int i=0;i<numBodies;i++)
+ {
+ b3ComputeWorldAabb( i, m_data->m_narrowphase->getBodiesCpu(), m_data->m_narrowphase->getCollidablesCpu(), m_data->m_narrowphase->getLocalSpaceAabbsCpu(),&m_data->m_broadphaseSap->getAllAabbsCPU()[0]);
+ }
+ m_data->m_broadphaseSap->getAllAabbsGPU().copyFromHost(m_data->m_broadphaseSap->getAllAabbsCPU());
+ //m_data->m_broadphaseSap->writeAabbsToGpu();
+ }
+ }
+ } else
+ {
+ //__kernel void initializeGpuAabbsFull( const int numNodes, __global Body* gBodies,__global Collidable* collidables, __global b3AABBCL* plocalShapeAABB, __global b3AABBCL* pAABB)
+ b3LauncherCL launcher(m_data->m_queue,m_data->m_updateAabbsKernel,"m_updateAabbsKernel");
+ launcher.setConst(numBodies);
+ cl_mem bodies = m_data->m_narrowphase->getBodiesGpu();
+ launcher.setBuffer(bodies);
+ cl_mem collidables = m_data->m_narrowphase->getCollidablesGpu();
+ launcher.setBuffer(collidables);
+ cl_mem localAabbs = m_data->m_narrowphase->getAabbLocalSpaceBufferGpu();
+ launcher.setBuffer(localAabbs);
+
+ cl_mem worldAabbs =0;
+ if (gUseDbvt)
+ {
+ worldAabbs = m_data->m_allAabbsGPU->getBufferCL();
+ } else
+ {
+ worldAabbs = m_data->m_broadphaseSap->getAabbBufferWS();
+ }
+ launcher.setBuffer(worldAabbs);
+ launcher.launch1D(numBodies);
+
+ oclCHECKERROR(ciErrNum, CL_SUCCESS);
+ }
+
+ /*
+ b3AlignedObjectArray<b3SapAabb> aabbs;
+ m_data->m_broadphaseSap->m_allAabbsGPU.copyToHost(aabbs);
+
+ printf("numAabbs = %d\n", aabbs.size());
+
+ for (int i=0;i<aabbs.size();i++)
+ {
+ printf("aabb[%d].m_min=%f,%f,%f,%d\n",i,aabbs[i].m_minVec[0],aabbs[i].m_minVec[1],aabbs[i].m_minVec[2],aabbs[i].m_minIndices[3]);
+ printf("aabb[%d].m_max=%f,%f,%f,%d\n",i,aabbs[i].m_maxVec[0],aabbs[i].m_maxVec[1],aabbs[i].m_maxVec[2],aabbs[i].m_signedMaxIndices[3]);
+
+ };
+ */
+
+
+
+
+
+}
+
+
+
+cl_mem b3GpuRigidBodyPipeline::getBodyBuffer()
+{
+ return m_data->m_narrowphase->getBodiesGpu();
+}
+
+int b3GpuRigidBodyPipeline::getNumBodies() const
+{
+ return m_data->m_narrowphase->getNumRigidBodies();
+}
+
+void b3GpuRigidBodyPipeline::setGravity(const float* grav)
+{
+ m_data->m_gravity.setValue(grav[0],grav[1],grav[2]);
+}
+
+void b3GpuRigidBodyPipeline::copyConstraintsToHost()
+{
+ m_data->m_gpuConstraints->copyToHost(m_data->m_cpuConstraints);
+}
+
+void b3GpuRigidBodyPipeline::writeAllInstancesToGpu()
+{
+ m_data->m_allAabbsGPU->copyFromHost(m_data->m_allAabbsCPU);
+ m_data->m_gpuConstraints->copyFromHost(m_data->m_cpuConstraints);
+}
+
+
+int b3GpuRigidBodyPipeline::registerPhysicsInstance(float mass, const float* position, const float* orientation, int collidableIndex, int userIndex, bool writeInstanceToGpu)
+{
+
+ b3Vector3 aabbMin=b3MakeVector3(0,0,0),aabbMax=b3MakeVector3(0,0,0);
+
+
+ if (collidableIndex>=0)
+ {
+ b3SapAabb localAabb = m_data->m_narrowphase->getLocalSpaceAabb(collidableIndex);
+ b3Vector3 localAabbMin=b3MakeVector3(localAabb.m_min[0],localAabb.m_min[1],localAabb.m_min[2]);
+ b3Vector3 localAabbMax=b3MakeVector3(localAabb.m_max[0],localAabb.m_max[1],localAabb.m_max[2]);
+
+ b3Scalar margin = 0.01f;
+ b3Transform t;
+ t.setIdentity();
+ t.setOrigin(b3MakeVector3(position[0],position[1],position[2]));
+ t.setRotation(b3Quaternion(orientation[0],orientation[1],orientation[2],orientation[3]));
+ b3TransformAabb(localAabbMin,localAabbMax, margin,t,aabbMin,aabbMax);
+ } else
+ {
+ b3Error("registerPhysicsInstance using invalid collidableIndex\n");
+ return -1;
+ }
+
+
+ bool writeToGpu = false;
+ int bodyIndex = m_data->m_narrowphase->getNumRigidBodies();
+ bodyIndex = m_data->m_narrowphase->registerRigidBody(collidableIndex,mass,position,orientation,&aabbMin.getX(),&aabbMax.getX(),writeToGpu);
+
+ if (bodyIndex>=0)
+ {
+ if (gUseDbvt)
+ {
+ m_data->m_broadphaseDbvt->createProxy(aabbMin,aabbMax,bodyIndex,0,1,1);
+ b3SapAabb aabb;
+ for (int i=0;i<3;i++)
+ {
+ aabb.m_min[i] = aabbMin[i];
+ aabb.m_max[i] = aabbMax[i];
+ aabb.m_minIndices[3] = bodyIndex;
+ }
+ m_data->m_allAabbsCPU.push_back(aabb);
+ if (writeInstanceToGpu)
+ {
+ m_data->m_allAabbsGPU->copyFromHost(m_data->m_allAabbsCPU);
+ }
+ } else
+ {
+ if (mass)
+ {
+ m_data->m_broadphaseSap->createProxy(aabbMin,aabbMax,bodyIndex,1,1);//m_dispatcher);
+ } else
+ {
+ m_data->m_broadphaseSap->createLargeProxy(aabbMin,aabbMax,bodyIndex,1,1);//m_dispatcher);
+ }
+ }
+ }
+
+ /*
+ if (mass>0.f)
+ m_numDynamicPhysicsInstances++;
+
+ m_numPhysicsInstances++;
+ */
+
+ return bodyIndex;
+}
+
+void b3GpuRigidBodyPipeline::castRays(const b3AlignedObjectArray<b3RayInfo>& rays, b3AlignedObjectArray<b3RayHit>& hitResults)
+{
+ this->m_data->m_raycaster->castRays(rays,hitResults,
+ getNumBodies(),this->m_data->m_narrowphase->getBodiesCpu(),
+ m_data->m_narrowphase->getNumCollidablesGpu(), m_data->m_narrowphase->getCollidablesCpu(),
+ m_data->m_narrowphase->getInternalData(), m_data->m_broadphaseSap);
+}
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuRigidBodyPipeline.h b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuRigidBodyPipeline.h
new file mode 100644
index 0000000000..b4eac6841a
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuRigidBodyPipeline.h
@@ -0,0 +1,74 @@
+/*
+Copyright (c) 2013 Advanced Micro Devices, Inc.
+
+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.
+*/
+//Originally written by Erwin Coumans
+
+#ifndef B3_GPU_RIGIDBODY_PIPELINE_H
+#define B3_GPU_RIGIDBODY_PIPELINE_H
+
+#include "Bullet3OpenCL/Initialize/b3OpenCLInclude.h"
+#include "Bullet3Collision/NarrowPhaseCollision/b3Config.h"
+
+#include "Bullet3Common/b3AlignedObjectArray.h"
+#include "Bullet3Collision/NarrowPhaseCollision/b3RaycastInfo.h"
+
+class b3GpuRigidBodyPipeline
+{
+protected:
+ struct b3GpuRigidBodyPipelineInternalData* m_data;
+
+ int allocateCollidable();
+
+public:
+
+
+ b3GpuRigidBodyPipeline(cl_context ctx,cl_device_id device, cl_command_queue q , class b3GpuNarrowPhase* narrowphase, class b3GpuBroadphaseInterface* broadphaseSap, struct b3DynamicBvhBroadphase* broadphaseDbvt, const b3Config& config);
+ virtual ~b3GpuRigidBodyPipeline();
+
+ void stepSimulation(float deltaTime);
+ void integrate(float timeStep);
+ void setupGpuAabbsFull();
+
+ int registerConvexPolyhedron(class b3ConvexUtility* convex);
+
+ //int registerConvexPolyhedron(const float* vertices, int strideInBytes, int numVertices, const float* scaling);
+ //int registerSphereShape(float radius);
+ //int registerPlaneShape(const b3Vector3& planeNormal, float planeConstant);
+
+ //int registerConcaveMesh(b3AlignedObjectArray<b3Vector3>* vertices, b3AlignedObjectArray<int>* indices, const float* scaling);
+ //int registerCompoundShape(b3AlignedObjectArray<b3GpuChildShape>* childShapes);
+
+
+ int registerPhysicsInstance(float mass, const float* position, const float* orientation, int collisionShapeIndex, int userData, bool writeInstanceToGpu);
+ //if you passed "writeInstanceToGpu" false in the registerPhysicsInstance method (for performance) you need to call writeAllInstancesToGpu after all instances are registered
+ void writeAllInstancesToGpu();
+ void copyConstraintsToHost();
+ void setGravity(const float* grav);
+ void reset();
+
+ int createPoint2PointConstraint(int bodyA, int bodyB, const float* pivotInA, const float* pivotInB,float breakingThreshold);
+ int createFixedConstraint(int bodyA, int bodyB, const float* pivotInA, const float* pivotInB, const float* relTargetAB, float breakingThreshold);
+ void removeConstraintByUid(int uid);
+
+ void addConstraint(class b3TypedConstraint* constraint);
+ void removeConstraint(b3TypedConstraint* constraint);
+
+ void castRays(const b3AlignedObjectArray<b3RayInfo>& rays, b3AlignedObjectArray<b3RayHit>& hitResults);
+
+ cl_mem getBodyBuffer();
+
+ int getNumBodies() const;
+
+};
+
+#endif //B3_GPU_RIGIDBODY_PIPELINE_H \ No newline at end of file
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuRigidBodyPipelineInternalData.h b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuRigidBodyPipelineInternalData.h
new file mode 100644
index 0000000000..5ac92f97d6
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuRigidBodyPipelineInternalData.h
@@ -0,0 +1,73 @@
+/*
+Copyright (c) 2013 Advanced Micro Devices, Inc.
+
+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.
+*/
+//Originally written by Erwin Coumans
+
+#ifndef B3_GPU_RIGIDBODY_PIPELINE_INTERNAL_DATA_H
+#define B3_GPU_RIGIDBODY_PIPELINE_INTERNAL_DATA_H
+
+#include "Bullet3OpenCL/Initialize/b3OpenCLInclude.h"
+#include "Bullet3Common/b3AlignedObjectArray.h"
+
+#include "Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h"
+
+
+#include "Bullet3OpenCL/BroadphaseCollision/b3SapAabb.h"
+#include "Bullet3Dynamics/ConstraintSolver/b3TypedConstraint.h"
+#include "Bullet3Collision/NarrowPhaseCollision/b3Config.h"
+
+
+
+#include "Bullet3Collision/BroadPhaseCollision/b3OverlappingPair.h"
+#include "Bullet3OpenCL/RigidBody/b3GpuGenericConstraint.h"
+
+struct b3GpuRigidBodyPipelineInternalData
+{
+
+ cl_context m_context;
+ cl_device_id m_device;
+ cl_command_queue m_queue;
+
+ cl_kernel m_integrateTransformsKernel;
+ cl_kernel m_updateAabbsKernel;
+ cl_kernel m_clearOverlappingPairsKernel;
+
+ class b3PgsJacobiSolver* m_solver;
+
+ class b3GpuPgsConstraintSolver* m_gpuSolver;
+
+ class b3GpuPgsContactSolver* m_solver2;
+ class b3GpuJacobiContactSolver* m_solver3;
+ class b3GpuRaycast* m_raycaster;
+
+ class b3GpuBroadphaseInterface* m_broadphaseSap;
+
+ struct b3DynamicBvhBroadphase* m_broadphaseDbvt;
+ b3OpenCLArray<b3SapAabb>* m_allAabbsGPU;
+ b3AlignedObjectArray<b3SapAabb> m_allAabbsCPU;
+ b3OpenCLArray<b3BroadphasePair>* m_overlappingPairsGPU;
+
+ b3OpenCLArray<b3GpuGenericConstraint>* m_gpuConstraints;
+ b3AlignedObjectArray<b3GpuGenericConstraint> m_cpuConstraints;
+
+ b3AlignedObjectArray<b3TypedConstraint*> m_joints;
+ int m_constraintUid;
+ class b3GpuNarrowPhase* m_narrowphase;
+ b3Vector3 m_gravity;
+
+ b3Config m_config;
+};
+
+#endif //B3_GPU_RIGIDBODY_PIPELINE_INTERNAL_DATA_H
+
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuSolverBody.h b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuSolverBody.h
new file mode 100644
index 0000000000..f2a61801ac
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuSolverBody.h
@@ -0,0 +1,228 @@
+/*
+Copyright (c) 2013 Advanced Micro Devices, Inc.
+
+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.
+*/
+//Originally written by Erwin Coumans
+
+
+#ifndef B3_GPU_SOLVER_BODY_H
+#define B3_GPU_SOLVER_BODY_H
+
+
+#include "Bullet3Common/b3Vector3.h"
+#include "Bullet3Common/b3Matrix3x3.h"
+
+#include "Bullet3Common/b3AlignedAllocator.h"
+#include "Bullet3Common/b3TransformUtil.h"
+
+///Until we get other contributions, only use SIMD on Windows, when using Visual Studio 2008 or later, and not double precision
+#ifdef B3_USE_SSE
+#define USE_SIMD 1
+#endif //
+
+
+
+///The b3SolverBody is an internal datastructure for the constraint solver. Only necessary data is packed to increase cache coherence/performance.
+B3_ATTRIBUTE_ALIGNED16 (struct) b3GpuSolverBody
+{
+ B3_DECLARE_ALIGNED_ALLOCATOR();
+// b3Transform m_worldTransformUnused;
+ b3Vector3 m_deltaLinearVelocity;
+ b3Vector3 m_deltaAngularVelocity;
+ b3Vector3 m_angularFactor;
+ b3Vector3 m_linearFactor;
+ b3Vector3 m_invMass;
+ b3Vector3 m_pushVelocity;
+ b3Vector3 m_turnVelocity;
+ b3Vector3 m_linearVelocity;
+ b3Vector3 m_angularVelocity;
+
+ union
+ {
+ void* m_originalBody;
+ int m_originalBodyIndex;
+ };
+
+ int padding[3];
+
+ /*
+ void setWorldTransform(const b3Transform& worldTransform)
+ {
+ m_worldTransform = worldTransform;
+ }
+
+ const b3Transform& getWorldTransform() const
+ {
+ return m_worldTransform;
+ }
+ */
+ B3_FORCE_INLINE void getVelocityInLocalPointObsolete(const b3Vector3& rel_pos, b3Vector3& velocity ) const
+ {
+ if (m_originalBody)
+ velocity = m_linearVelocity+m_deltaLinearVelocity + (m_angularVelocity+m_deltaAngularVelocity).cross(rel_pos);
+ else
+ velocity.setValue(0,0,0);
+ }
+
+ B3_FORCE_INLINE void getAngularVelocity(b3Vector3& angVel) const
+ {
+ if (m_originalBody)
+ angVel =m_angularVelocity+m_deltaAngularVelocity;
+ else
+ angVel.setValue(0,0,0);
+ }
+
+
+ //Optimization for the iterative solver: avoid calculating constant terms involving inertia, normal, relative position
+ B3_FORCE_INLINE void applyImpulse(const b3Vector3& linearComponent, const b3Vector3& angularComponent,const b3Scalar impulseMagnitude)
+ {
+ if (m_originalBody)
+ {
+ m_deltaLinearVelocity += linearComponent*impulseMagnitude*m_linearFactor;
+ m_deltaAngularVelocity += angularComponent*(impulseMagnitude*m_angularFactor);
+ }
+ }
+
+ B3_FORCE_INLINE void internalApplyPushImpulse(const b3Vector3& linearComponent, const b3Vector3& angularComponent,b3Scalar impulseMagnitude)
+ {
+ if (m_originalBody)
+ {
+ m_pushVelocity += linearComponent*impulseMagnitude*m_linearFactor;
+ m_turnVelocity += angularComponent*(impulseMagnitude*m_angularFactor);
+ }
+ }
+
+
+
+ const b3Vector3& getDeltaLinearVelocity() const
+ {
+ return m_deltaLinearVelocity;
+ }
+
+ const b3Vector3& getDeltaAngularVelocity() const
+ {
+ return m_deltaAngularVelocity;
+ }
+
+ const b3Vector3& getPushVelocity() const
+ {
+ return m_pushVelocity;
+ }
+
+ const b3Vector3& getTurnVelocity() const
+ {
+ return m_turnVelocity;
+ }
+
+
+ ////////////////////////////////////////////////
+ ///some internal methods, don't use them
+
+ b3Vector3& internalGetDeltaLinearVelocity()
+ {
+ return m_deltaLinearVelocity;
+ }
+
+ b3Vector3& internalGetDeltaAngularVelocity()
+ {
+ return m_deltaAngularVelocity;
+ }
+
+ const b3Vector3& internalGetAngularFactor() const
+ {
+ return m_angularFactor;
+ }
+
+ const b3Vector3& internalGetInvMass() const
+ {
+ return m_invMass;
+ }
+
+ void internalSetInvMass(const b3Vector3& invMass)
+ {
+ m_invMass = invMass;
+ }
+
+ b3Vector3& internalGetPushVelocity()
+ {
+ return m_pushVelocity;
+ }
+
+ b3Vector3& internalGetTurnVelocity()
+ {
+ return m_turnVelocity;
+ }
+
+ B3_FORCE_INLINE void internalGetVelocityInLocalPointObsolete(const b3Vector3& rel_pos, b3Vector3& velocity ) const
+ {
+ velocity = m_linearVelocity+m_deltaLinearVelocity + (m_angularVelocity+m_deltaAngularVelocity).cross(rel_pos);
+ }
+
+ B3_FORCE_INLINE void internalGetAngularVelocity(b3Vector3& angVel) const
+ {
+ angVel = m_angularVelocity+m_deltaAngularVelocity;
+ }
+
+
+ //Optimization for the iterative solver: avoid calculating constant terms involving inertia, normal, relative position
+ B3_FORCE_INLINE void internalApplyImpulse(const b3Vector3& linearComponent, const b3Vector3& angularComponent,const b3Scalar impulseMagnitude)
+ {
+ //if (m_originalBody)
+ {
+ m_deltaLinearVelocity += linearComponent*impulseMagnitude*m_linearFactor;
+ m_deltaAngularVelocity += angularComponent*(impulseMagnitude*m_angularFactor);
+ }
+ }
+
+
+
+
+ void writebackVelocity()
+ {
+ //if (m_originalBody>=0)
+ {
+ m_linearVelocity +=m_deltaLinearVelocity;
+ m_angularVelocity += m_deltaAngularVelocity;
+
+ //m_originalBody->setCompanionId(-1);
+ }
+ }
+
+
+ void writebackVelocityAndTransform(b3Scalar timeStep, b3Scalar splitImpulseTurnErp)
+ {
+ (void) timeStep;
+ if (m_originalBody)
+ {
+ m_linearVelocity += m_deltaLinearVelocity;
+ m_angularVelocity += m_deltaAngularVelocity;
+
+ //correct the position/orientation based on push/turn recovery
+ b3Transform newTransform;
+ if (m_pushVelocity[0]!=0.f || m_pushVelocity[1]!=0 || m_pushVelocity[2]!=0 || m_turnVelocity[0]!=0.f || m_turnVelocity[1]!=0 || m_turnVelocity[2]!=0)
+ {
+ // b3Quaternion orn = m_worldTransform.getRotation();
+// b3TransformUtil::integrateTransform(m_worldTransform,m_pushVelocity,m_turnVelocity*splitImpulseTurnErp,timeStep,newTransform);
+// m_worldTransform = newTransform;
+ }
+ //m_worldTransform.setRotation(orn);
+ //m_originalBody->setCompanionId(-1);
+ }
+ }
+
+
+
+};
+
+#endif //B3_SOLVER_BODY_H
+
+
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuSolverConstraint.h b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuSolverConstraint.h
new file mode 100644
index 0000000000..60d235baab
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3GpuSolverConstraint.h
@@ -0,0 +1,82 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2013 Erwin Coumans http://github.com/erwincoumans/bullet3
+
+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 B3_GPU_SOLVER_CONSTRAINT_H
+#define B3_GPU_SOLVER_CONSTRAINT_H
+
+
+#include "Bullet3Common/b3Vector3.h"
+#include "Bullet3Common/b3Matrix3x3.h"
+//#include "b3JacobianEntry.h"
+#include "Bullet3Common/b3AlignedObjectArray.h"
+
+//#define NO_FRICTION_TANGENTIALS 1
+
+
+
+///1D constraint along a normal axis between bodyA and bodyB. It can be combined to solve contact and friction constraints.
+B3_ATTRIBUTE_ALIGNED16 (struct) b3GpuSolverConstraint
+{
+ B3_DECLARE_ALIGNED_ALLOCATOR();
+
+ b3Vector3 m_relpos1CrossNormal;
+ b3Vector3 m_contactNormal;
+
+ b3Vector3 m_relpos2CrossNormal;
+ //b3Vector3 m_contactNormal2;//usually m_contactNormal2 == -m_contactNormal
+
+ b3Vector3 m_angularComponentA;
+ b3Vector3 m_angularComponentB;
+
+ mutable b3Scalar m_appliedPushImpulse;
+ mutable b3Scalar m_appliedImpulse;
+ int m_padding1;
+ int m_padding2;
+ b3Scalar m_friction;
+ b3Scalar m_jacDiagABInv;
+ b3Scalar m_rhs;
+ b3Scalar m_cfm;
+
+ b3Scalar m_lowerLimit;
+ b3Scalar m_upperLimit;
+ b3Scalar m_rhsPenetration;
+ union
+ {
+ void* m_originalContactPoint;
+ int m_originalConstraintIndex;
+ b3Scalar m_unusedPadding4;
+ };
+
+ int m_overrideNumSolverIterations;
+ int m_frictionIndex;
+ int m_solverBodyIdA;
+ int m_solverBodyIdB;
+
+
+ enum b3SolverConstraintType
+ {
+ B3_SOLVER_CONTACT_1D = 0,
+ B3_SOLVER_FRICTION_1D
+ };
+};
+
+typedef b3AlignedObjectArray<b3GpuSolverConstraint> b3GpuConstraintArray;
+
+
+#endif //B3_GPU_SOLVER_CONSTRAINT_H
+
+
+
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3Solver.cpp b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3Solver.cpp
new file mode 100644
index 0000000000..20bf6d47c5
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3Solver.cpp
@@ -0,0 +1,1225 @@
+/*
+Copyright (c) 2012 Advanced Micro Devices, Inc.
+
+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.
+*/
+//Originally written by Takahiro Harada
+
+
+#include "b3Solver.h"
+
+///useNewBatchingKernel is a rewritten kernel using just a single thread of the warp, for experiments
+bool useNewBatchingKernel = true;
+bool gConvertConstraintOnCpu = false;
+
+#define B3_SOLVER_SETUP_KERNEL_PATH "src/Bullet3OpenCL/RigidBody/kernels/solverSetup.cl"
+#define B3_SOLVER_SETUP2_KERNEL_PATH "src/Bullet3OpenCL/RigidBody/kernels/solverSetup2.cl"
+#define B3_SOLVER_CONTACT_KERNEL_PATH "src/Bullet3OpenCL/RigidBody/kernels/solveContact.cl"
+#define B3_SOLVER_FRICTION_KERNEL_PATH "src/Bullet3OpenCL/RigidBody/kernels/solveFriction.cl"
+#define B3_BATCHING_PATH "src/Bullet3OpenCL/RigidBody/kernels/batchingKernels.cl"
+#define B3_BATCHING_NEW_PATH "src/Bullet3OpenCL/RigidBody/kernels/batchingKernelsNew.cl"
+
+#include "Bullet3Dynamics/shared/b3ConvertConstraint4.h"
+
+#include "kernels/solverSetup.h"
+#include "kernels/solverSetup2.h"
+
+#include "kernels/solveContact.h"
+#include "kernels/solveFriction.h"
+
+#include "kernels/batchingKernels.h"
+#include "kernels/batchingKernelsNew.h"
+
+
+#include "Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.h"
+#include "Bullet3Common/b3Vector3.h"
+
+struct SolverDebugInfo
+{
+ int m_valInt0;
+ int m_valInt1;
+ int m_valInt2;
+ int m_valInt3;
+
+ int m_valInt4;
+ int m_valInt5;
+ int m_valInt6;
+ int m_valInt7;
+
+ int m_valInt8;
+ int m_valInt9;
+ int m_valInt10;
+ int m_valInt11;
+
+ int m_valInt12;
+ int m_valInt13;
+ int m_valInt14;
+ int m_valInt15;
+
+
+ float m_val0;
+ float m_val1;
+ float m_val2;
+ float m_val3;
+};
+
+
+
+
+class SolverDeviceInl
+{
+public:
+ struct ParallelSolveData
+ {
+ b3OpenCLArray<unsigned int>* m_numConstraints;
+ b3OpenCLArray<unsigned int>* m_offsets;
+ };
+};
+
+
+
+b3Solver::b3Solver(cl_context ctx, cl_device_id device, cl_command_queue queue, int pairCapacity)
+ :
+ m_context(ctx),
+ m_device(device),
+ m_queue(queue),
+ m_batchSizes(ctx,queue),
+ m_nIterations(4)
+{
+ m_sort32 = new b3RadixSort32CL(ctx,device,queue);
+ m_scan = new b3PrefixScanCL(ctx,device,queue,B3_SOLVER_N_CELLS);
+ m_search = new b3BoundSearchCL(ctx,device,queue,B3_SOLVER_N_CELLS);
+
+ const int sortSize = B3NEXTMULTIPLEOF( pairCapacity, 512 );
+
+ m_sortDataBuffer = new b3OpenCLArray<b3SortData>(ctx,queue,sortSize);
+ m_contactBuffer2 = new b3OpenCLArray<b3Contact4>(ctx,queue);
+
+ m_numConstraints = new b3OpenCLArray<unsigned int>(ctx,queue,B3_SOLVER_N_CELLS );
+ m_numConstraints->resize(B3_SOLVER_N_CELLS);
+
+ m_offsets = new b3OpenCLArray<unsigned int>( ctx,queue,B3_SOLVER_N_CELLS);
+ m_offsets->resize(B3_SOLVER_N_CELLS);
+ const char* additionalMacros = "";
+// const char* srcFileNameForCaching="";
+
+
+
+ cl_int pErrNum;
+ const char* batchKernelSource = batchingKernelsCL;
+ const char* batchKernelNewSource = batchingKernelsNewCL;
+
+ const char* solverSetupSource = solverSetupCL;
+ const char* solverSetup2Source = solverSetup2CL;
+ const char* solveContactSource = solveContactCL;
+ const char* solveFrictionSource = solveFrictionCL;
+
+
+
+ {
+
+ cl_program solveContactProg= b3OpenCLUtils::compileCLProgramFromString( ctx, device, solveContactSource, &pErrNum,additionalMacros, B3_SOLVER_CONTACT_KERNEL_PATH);
+ b3Assert(solveContactProg);
+
+ cl_program solveFrictionProg= b3OpenCLUtils::compileCLProgramFromString( ctx, device, solveFrictionSource, &pErrNum,additionalMacros, B3_SOLVER_FRICTION_KERNEL_PATH);
+ b3Assert(solveFrictionProg);
+
+ cl_program solverSetup2Prog= b3OpenCLUtils::compileCLProgramFromString( ctx, device, solverSetup2Source, &pErrNum,additionalMacros, B3_SOLVER_SETUP2_KERNEL_PATH);
+ b3Assert(solverSetup2Prog);
+
+
+ cl_program solverSetupProg= b3OpenCLUtils::compileCLProgramFromString( ctx, device, solverSetupSource, &pErrNum,additionalMacros, B3_SOLVER_SETUP_KERNEL_PATH);
+ b3Assert(solverSetupProg);
+
+
+ m_solveFrictionKernel= b3OpenCLUtils::compileCLKernelFromString( ctx, device, solveFrictionSource, "BatchSolveKernelFriction", &pErrNum, solveFrictionProg,additionalMacros );
+ b3Assert(m_solveFrictionKernel);
+
+ m_solveContactKernel= b3OpenCLUtils::compileCLKernelFromString( ctx, device, solveContactSource, "BatchSolveKernelContact", &pErrNum, solveContactProg,additionalMacros );
+ b3Assert(m_solveContactKernel);
+
+ m_contactToConstraintKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, solverSetupSource, "ContactToConstraintKernel", &pErrNum, solverSetupProg,additionalMacros );
+ b3Assert(m_contactToConstraintKernel);
+
+ m_setSortDataKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, solverSetup2Source, "SetSortDataKernel", &pErrNum, solverSetup2Prog,additionalMacros );
+ b3Assert(m_setSortDataKernel);
+
+ m_reorderContactKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, solverSetup2Source, "ReorderContactKernel", &pErrNum, solverSetup2Prog,additionalMacros );
+ b3Assert(m_reorderContactKernel);
+
+
+ m_copyConstraintKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, solverSetup2Source, "CopyConstraintKernel", &pErrNum, solverSetup2Prog,additionalMacros );
+ b3Assert(m_copyConstraintKernel);
+
+ }
+
+ {
+ cl_program batchingProg = b3OpenCLUtils::compileCLProgramFromString( ctx, device, batchKernelSource, &pErrNum,additionalMacros, B3_BATCHING_PATH);
+ //cl_program batchingProg = b3OpenCLUtils::compileCLProgramFromString( ctx, device, 0, &pErrNum,additionalMacros, B3_BATCHING_PATH,true);
+ b3Assert(batchingProg);
+
+ m_batchingKernel = b3OpenCLUtils::compileCLKernelFromString( ctx, device, batchKernelSource, "CreateBatches", &pErrNum, batchingProg,additionalMacros );
+ b3Assert(m_batchingKernel);
+ }
+ {
+ cl_program batchingNewProg = b3OpenCLUtils::compileCLProgramFromString( ctx, device, batchKernelNewSource, &pErrNum,additionalMacros, B3_BATCHING_NEW_PATH);
+ b3Assert(batchingNewProg);
+
+ m_batchingKernelNew = b3OpenCLUtils::compileCLKernelFromString( ctx, device, batchKernelNewSource, "CreateBatchesNew", &pErrNum, batchingNewProg,additionalMacros );
+ //m_batchingKernelNew = b3OpenCLUtils::compileCLKernelFromString( ctx, device, batchKernelNewSource, "CreateBatchesBruteForce", &pErrNum, batchingNewProg,additionalMacros );
+ b3Assert(m_batchingKernelNew);
+ }
+}
+
+b3Solver::~b3Solver()
+{
+ delete m_offsets;
+ delete m_numConstraints;
+ delete m_sortDataBuffer;
+ delete m_contactBuffer2;
+
+ delete m_sort32;
+ delete m_scan;
+ delete m_search;
+
+
+ clReleaseKernel(m_batchingKernel);
+ clReleaseKernel(m_batchingKernelNew);
+
+ clReleaseKernel( m_solveContactKernel);
+ clReleaseKernel( m_solveFrictionKernel);
+
+ clReleaseKernel( m_contactToConstraintKernel);
+ clReleaseKernel( m_setSortDataKernel);
+ clReleaseKernel( m_reorderContactKernel);
+ clReleaseKernel( m_copyConstraintKernel);
+
+}
+
+
+
+
+template<bool JACOBI>
+static
+__inline
+void solveContact(b3GpuConstraint4& cs,
+ const b3Vector3& posA, b3Vector3& linVelA, b3Vector3& angVelA, float invMassA, const b3Matrix3x3& invInertiaA,
+ const b3Vector3& posB, b3Vector3& linVelB, b3Vector3& angVelB, float invMassB, const b3Matrix3x3& invInertiaB,
+ float maxRambdaDt[4], float minRambdaDt[4])
+{
+
+ b3Vector3 dLinVelA; dLinVelA.setZero();
+ b3Vector3 dAngVelA; dAngVelA.setZero();
+ b3Vector3 dLinVelB; dLinVelB.setZero();
+ b3Vector3 dAngVelB; dAngVelB.setZero();
+
+ for(int ic=0; ic<4; ic++)
+ {
+ // dont necessary because this makes change to 0
+ if( cs.m_jacCoeffInv[ic] == 0.f ) continue;
+
+ {
+ b3Vector3 angular0, angular1, linear;
+ b3Vector3 r0 = cs.m_worldPos[ic] - (b3Vector3&)posA;
+ b3Vector3 r1 = cs.m_worldPos[ic] - (b3Vector3&)posB;
+ setLinearAndAngular( (const b3Vector3 &)cs.m_linear, (const b3Vector3 &)r0, (const b3Vector3 &)r1, &linear, &angular0, &angular1 );
+
+ float rambdaDt = calcRelVel((const b3Vector3 &)cs.m_linear,(const b3Vector3 &) -cs.m_linear, angular0, angular1,
+ linVelA, angVelA, linVelB, angVelB ) + cs.m_b[ic];
+ rambdaDt *= cs.m_jacCoeffInv[ic];
+
+ {
+ float prevSum = cs.m_appliedRambdaDt[ic];
+ float updated = prevSum;
+ updated += rambdaDt;
+ updated = b3Max( updated, minRambdaDt[ic] );
+ updated = b3Min( updated, maxRambdaDt[ic] );
+ rambdaDt = updated - prevSum;
+ cs.m_appliedRambdaDt[ic] = updated;
+ }
+
+ b3Vector3 linImp0 = invMassA*linear*rambdaDt;
+ b3Vector3 linImp1 = invMassB*(-linear)*rambdaDt;
+ b3Vector3 angImp0 = (invInertiaA* angular0)*rambdaDt;
+ b3Vector3 angImp1 = (invInertiaB* angular1)*rambdaDt;
+#ifdef _WIN32
+ b3Assert(_finite(linImp0.getX()));
+ b3Assert(_finite(linImp1.getX()));
+#endif
+ if( JACOBI )
+ {
+ dLinVelA += linImp0;
+ dAngVelA += angImp0;
+ dLinVelB += linImp1;
+ dAngVelB += angImp1;
+ }
+ else
+ {
+ linVelA += linImp0;
+ angVelA += angImp0;
+ linVelB += linImp1;
+ angVelB += angImp1;
+ }
+ }
+ }
+
+ if( JACOBI )
+ {
+ linVelA += dLinVelA;
+ angVelA += dAngVelA;
+ linVelB += dLinVelB;
+ angVelB += dAngVelB;
+ }
+
+}
+
+
+
+
+
+ static
+ __inline
+ void solveFriction(b3GpuConstraint4& cs,
+ const b3Vector3& posA, b3Vector3& linVelA, b3Vector3& angVelA, float invMassA, const b3Matrix3x3& invInertiaA,
+ const b3Vector3& posB, b3Vector3& linVelB, b3Vector3& angVelB, float invMassB, const b3Matrix3x3& invInertiaB,
+ float maxRambdaDt[4], float minRambdaDt[4])
+ {
+
+ if( cs.m_fJacCoeffInv[0] == 0 && cs.m_fJacCoeffInv[0] == 0 ) return;
+ const b3Vector3& center = (const b3Vector3&)cs.m_center;
+
+ b3Vector3 n = -(const b3Vector3&)cs.m_linear;
+
+ b3Vector3 tangent[2];
+#if 1
+ b3PlaneSpace1 (n, tangent[0],tangent[1]);
+#else
+ b3Vector3 r = cs.m_worldPos[0]-center;
+ tangent[0] = cross3( n, r );
+ tangent[1] = cross3( tangent[0], n );
+ tangent[0] = normalize3( tangent[0] );
+ tangent[1] = normalize3( tangent[1] );
+#endif
+
+ b3Vector3 angular0, angular1, linear;
+ b3Vector3 r0 = center - posA;
+ b3Vector3 r1 = center - posB;
+ for(int i=0; i<2; i++)
+ {
+ setLinearAndAngular( tangent[i], r0, r1, &linear, &angular0, &angular1 );
+ float rambdaDt = calcRelVel(linear, -linear, angular0, angular1,
+ linVelA, angVelA, linVelB, angVelB );
+ rambdaDt *= cs.m_fJacCoeffInv[i];
+
+ {
+ float prevSum = cs.m_fAppliedRambdaDt[i];
+ float updated = prevSum;
+ updated += rambdaDt;
+ updated = b3Max( updated, minRambdaDt[i] );
+ updated = b3Min( updated, maxRambdaDt[i] );
+ rambdaDt = updated - prevSum;
+ cs.m_fAppliedRambdaDt[i] = updated;
+ }
+
+ b3Vector3 linImp0 = invMassA*linear*rambdaDt;
+ b3Vector3 linImp1 = invMassB*(-linear)*rambdaDt;
+ b3Vector3 angImp0 = (invInertiaA* angular0)*rambdaDt;
+ b3Vector3 angImp1 = (invInertiaB* angular1)*rambdaDt;
+#ifdef _WIN32
+ b3Assert(_finite(linImp0.getX()));
+ b3Assert(_finite(linImp1.getX()));
+#endif
+ linVelA += linImp0;
+ angVelA += angImp0;
+ linVelB += linImp1;
+ angVelB += angImp1;
+ }
+
+ { // angular damping for point constraint
+ b3Vector3 ab = ( posB - posA ).normalized();
+ b3Vector3 ac = ( center - posA ).normalized();
+ if( b3Dot( ab, ac ) > 0.95f || (invMassA == 0.f || invMassB == 0.f))
+ {
+ float angNA = b3Dot( n, angVelA );
+ float angNB = b3Dot( n, angVelB );
+
+ angVelA -= (angNA*0.1f)*n;
+ angVelB -= (angNB*0.1f)*n;
+ }
+ }
+
+ }
+/*
+ b3AlignedObjectArray<b3RigidBodyData>& m_bodies;
+ b3AlignedObjectArray<b3InertiaData>& m_shapes;
+ b3AlignedObjectArray<b3GpuConstraint4>& m_constraints;
+ b3AlignedObjectArray<int>* m_batchSizes;
+ int m_cellIndex;
+ int m_curWgidx;
+ int m_start;
+ int m_nConstraints;
+ bool m_solveFriction;
+ int m_maxNumBatches;
+ */
+
+struct SolveTask// : public ThreadPool::Task
+{
+ SolveTask(b3AlignedObjectArray<b3RigidBodyData>& bodies, b3AlignedObjectArray<b3InertiaData>& shapes, b3AlignedObjectArray<b3GpuConstraint4>& constraints,
+ int start, int nConstraints,int maxNumBatches,b3AlignedObjectArray<int>* wgUsedBodies, int curWgidx, b3AlignedObjectArray<int>* batchSizes, int cellIndex)
+ : m_bodies( bodies ), m_shapes( shapes ),
+ m_constraints( constraints ),
+ m_batchSizes(batchSizes),
+ m_cellIndex(cellIndex),
+ m_curWgidx(curWgidx),
+ m_start( start ),
+ m_nConstraints( nConstraints ),
+ m_solveFriction( true ),
+ m_maxNumBatches(maxNumBatches)
+ {}
+
+ unsigned short int getType(){ return 0; }
+
+ void run(int tIdx)
+ {
+ int offset = 0;
+ for (int ii=0;ii<B3_MAX_NUM_BATCHES;ii++)
+ {
+ int numInBatch = m_batchSizes->at(m_cellIndex*B3_MAX_NUM_BATCHES+ii);
+ if (!numInBatch)
+ break;
+
+ for (int jj=0;jj<numInBatch;jj++)
+ {
+ int i = m_start + offset+jj;
+ int batchId = m_constraints[i].m_batchIdx;
+ b3Assert(batchId==ii);
+ float frictionCoeff = m_constraints[i].getFrictionCoeff();
+ int aIdx = (int)m_constraints[i].m_bodyA;
+ int bIdx = (int)m_constraints[i].m_bodyB;
+// int localBatch = m_constraints[i].m_batchIdx;
+ b3RigidBodyData& bodyA = m_bodies[aIdx];
+ b3RigidBodyData& bodyB = m_bodies[bIdx];
+
+ if( !m_solveFriction )
+ {
+ float maxRambdaDt[4] = {FLT_MAX,FLT_MAX,FLT_MAX,FLT_MAX};
+ float minRambdaDt[4] = {0.f,0.f,0.f,0.f};
+
+ solveContact<false>( m_constraints[i], (b3Vector3&)bodyA.m_pos, (b3Vector3&)bodyA.m_linVel, (b3Vector3&)bodyA.m_angVel, bodyA.m_invMass, (const b3Matrix3x3 &)m_shapes[aIdx].m_invInertiaWorld,
+ (b3Vector3&)bodyB.m_pos, (b3Vector3&)bodyB.m_linVel, (b3Vector3&)bodyB.m_angVel, bodyB.m_invMass, (const b3Matrix3x3 &)m_shapes[bIdx].m_invInertiaWorld,
+ maxRambdaDt, minRambdaDt );
+ }
+ else
+ {
+ float maxRambdaDt[4] = {FLT_MAX,FLT_MAX,FLT_MAX,FLT_MAX};
+ float minRambdaDt[4] = {0.f,0.f,0.f,0.f};
+ float sum = 0;
+ for(int j=0; j<4; j++)
+ {
+ sum +=m_constraints[i].m_appliedRambdaDt[j];
+ }
+ frictionCoeff = 0.7f;
+ for(int j=0; j<4; j++)
+ {
+ maxRambdaDt[j] = frictionCoeff*sum;
+ minRambdaDt[j] = -maxRambdaDt[j];
+ }
+ solveFriction( m_constraints[i], (b3Vector3&)bodyA.m_pos, (b3Vector3&)bodyA.m_linVel, (b3Vector3&)bodyA.m_angVel, bodyA.m_invMass,(const b3Matrix3x3 &) m_shapes[aIdx].m_invInertiaWorld,
+ (b3Vector3&)bodyB.m_pos, (b3Vector3&)bodyB.m_linVel, (b3Vector3&)bodyB.m_angVel, bodyB.m_invMass,(const b3Matrix3x3 &) m_shapes[bIdx].m_invInertiaWorld,
+ maxRambdaDt, minRambdaDt );
+
+ }
+ }
+ offset+=numInBatch;
+
+
+ }
+/* for (int bb=0;bb<m_maxNumBatches;bb++)
+ {
+ //for(int ic=m_nConstraints-1; ic>=0; ic--)
+ for(int ic=0; ic<m_nConstraints; ic++)
+ {
+
+ int i = m_start + ic;
+ if (m_constraints[i].m_batchIdx != bb)
+ continue;
+
+ float frictionCoeff = m_constraints[i].getFrictionCoeff();
+ int aIdx = (int)m_constraints[i].m_bodyA;
+ int bIdx = (int)m_constraints[i].m_bodyB;
+ int localBatch = m_constraints[i].m_batchIdx;
+ b3RigidBodyData& bodyA = m_bodies[aIdx];
+ b3RigidBodyData& bodyB = m_bodies[bIdx];
+
+ if( !m_solveFriction )
+ {
+ float maxRambdaDt[4] = {FLT_MAX,FLT_MAX,FLT_MAX,FLT_MAX};
+ float minRambdaDt[4] = {0.f,0.f,0.f,0.f};
+
+ solveContact<false>( m_constraints[i], (b3Vector3&)bodyA.m_pos, (b3Vector3&)bodyA.m_linVel, (b3Vector3&)bodyA.m_angVel, bodyA.m_invMass, (const b3Matrix3x3 &)m_shapes[aIdx].m_invInertiaWorld,
+ (b3Vector3&)bodyB.m_pos, (b3Vector3&)bodyB.m_linVel, (b3Vector3&)bodyB.m_angVel, bodyB.m_invMass, (const b3Matrix3x3 &)m_shapes[bIdx].m_invInertiaWorld,
+ maxRambdaDt, minRambdaDt );
+ }
+ else
+ {
+ float maxRambdaDt[4] = {FLT_MAX,FLT_MAX,FLT_MAX,FLT_MAX};
+ float minRambdaDt[4] = {0.f,0.f,0.f,0.f};
+ float sum = 0;
+ for(int j=0; j<4; j++)
+ {
+ sum +=m_constraints[i].m_appliedRambdaDt[j];
+ }
+ frictionCoeff = 0.7f;
+ for(int j=0; j<4; j++)
+ {
+ maxRambdaDt[j] = frictionCoeff*sum;
+ minRambdaDt[j] = -maxRambdaDt[j];
+ }
+ solveFriction( m_constraints[i], (b3Vector3&)bodyA.m_pos, (b3Vector3&)bodyA.m_linVel, (b3Vector3&)bodyA.m_angVel, bodyA.m_invMass,(const b3Matrix3x3 &) m_shapes[aIdx].m_invInertiaWorld,
+ (b3Vector3&)bodyB.m_pos, (b3Vector3&)bodyB.m_linVel, (b3Vector3&)bodyB.m_angVel, bodyB.m_invMass,(const b3Matrix3x3 &) m_shapes[bIdx].m_invInertiaWorld,
+ maxRambdaDt, minRambdaDt );
+
+ }
+ }
+ }
+ */
+
+
+
+ }
+
+ b3AlignedObjectArray<b3RigidBodyData>& m_bodies;
+ b3AlignedObjectArray<b3InertiaData>& m_shapes;
+ b3AlignedObjectArray<b3GpuConstraint4>& m_constraints;
+ b3AlignedObjectArray<int>* m_batchSizes;
+ int m_cellIndex;
+ int m_curWgidx;
+ int m_start;
+ int m_nConstraints;
+ bool m_solveFriction;
+ int m_maxNumBatches;
+};
+
+
+void b3Solver::solveContactConstraintHost( b3OpenCLArray<b3RigidBodyData>* bodyBuf, b3OpenCLArray<b3InertiaData>* shapeBuf,
+ b3OpenCLArray<b3GpuConstraint4>* constraint, void* additionalData, int n ,int maxNumBatches,b3AlignedObjectArray<int>* batchSizes)
+{
+
+#if 0
+ {
+ int nSplitX = B3_SOLVER_N_SPLIT_X;
+ int nSplitY = B3_SOLVER_N_SPLIT_Y;
+ int numWorkgroups = B3_SOLVER_N_CELLS/B3_SOLVER_N_BATCHES;
+ for (int z=0;z<4;z++)
+ {
+ for (int y=0;y<4;y++)
+ {
+ for (int x=0;x<4;x++)
+ {
+ int newIndex = (x+y*nSplitX+z*nSplitX*nSplitY);
+ // printf("newIndex=%d\n",newIndex);
+
+ int zIdx = newIndex/(nSplitX*nSplitY);
+ int remain = newIndex%(nSplitX*nSplitY);
+ int yIdx = remain/nSplitX;
+ int xIdx = remain%nSplitX;
+ // printf("newIndex=%d\n",newIndex);
+ }
+ }
+ }
+
+ //for (int wgIdx=numWorkgroups-1;wgIdx>=0;wgIdx--)
+ for (int cellBatch=0;cellBatch<B3_SOLVER_N_BATCHES;cellBatch++)
+ {
+ for (int wgIdx=0;wgIdx<numWorkgroups;wgIdx++)
+ {
+ int zIdx = (wgIdx/((nSplitX*nSplitY)/4))*2+((cellBatch&4)>>2);
+ int remain= (wgIdx%((nSplitX*nSplitY)/4));
+ int yIdx = (remain/(nSplitX/2))*2 + ((cellBatch&2)>>1);
+ int xIdx = (remain%(nSplitX/2))*2 + (cellBatch&1);
+
+ /*int zIdx = newIndex/(nSplitX*nSplitY);
+ int remain = newIndex%(nSplitX*nSplitY);
+ int yIdx = remain/nSplitX;
+ int xIdx = remain%nSplitX;
+ */
+ int cellIdx = xIdx+yIdx*nSplitX+zIdx*(nSplitX*nSplitY);
+ // printf("wgIdx %d: xIdx=%d, yIdx=%d, zIdx=%d, cellIdx=%d, cell Batch %d\n",wgIdx,xIdx,yIdx,zIdx,cellIdx,cellBatch);
+ }
+ }
+ }
+#endif
+
+ b3AlignedObjectArray<b3RigidBodyData> bodyNative;
+ bodyBuf->copyToHost(bodyNative);
+ b3AlignedObjectArray<b3InertiaData> shapeNative;
+ shapeBuf->copyToHost(shapeNative);
+ b3AlignedObjectArray<b3GpuConstraint4> constraintNative;
+ constraint->copyToHost(constraintNative);
+
+ b3AlignedObjectArray<unsigned int> numConstraintsHost;
+ m_numConstraints->copyToHost(numConstraintsHost);
+
+ //printf("------------------------\n");
+ b3AlignedObjectArray<unsigned int> offsetsHost;
+ m_offsets->copyToHost(offsetsHost);
+ static int frame=0;
+ bool useBatches=true;
+ if (useBatches)
+ {
+ for(int iter=0; iter<m_nIterations; iter++)
+ {
+ for (int cellBatch=0;cellBatch<B3_SOLVER_N_BATCHES;cellBatch++)
+ {
+
+ int nSplitX = B3_SOLVER_N_SPLIT_X;
+ int nSplitY = B3_SOLVER_N_SPLIT_Y;
+ int numWorkgroups = B3_SOLVER_N_CELLS/B3_SOLVER_N_BATCHES;
+ //printf("cell Batch %d\n",cellBatch);
+ b3AlignedObjectArray<int> usedBodies[B3_SOLVER_N_CELLS];
+ for (int i=0;i<B3_SOLVER_N_CELLS;i++)
+ {
+ usedBodies[i].resize(0);
+ }
+
+
+
+
+ //for (int wgIdx=numWorkgroups-1;wgIdx>=0;wgIdx--)
+ for (int wgIdx=0;wgIdx<numWorkgroups;wgIdx++)
+ {
+ int zIdx = (wgIdx/((nSplitX*nSplitY)/4))*2+((cellBatch&4)>>2);
+ int remain= (wgIdx%((nSplitX*nSplitY)/4));
+ int yIdx = (remain/(nSplitX/2))*2 + ((cellBatch&2)>>1);
+ int xIdx = (remain%(nSplitX/2))*2 + (cellBatch&1);
+ int cellIdx = xIdx+yIdx*nSplitX+zIdx*(nSplitX*nSplitY);
+
+
+ if( numConstraintsHost[cellIdx] == 0 )
+ continue;
+
+ //printf("wgIdx %d: xIdx=%d, yIdx=%d, zIdx=%d, cellIdx=%d, cell Batch %d\n",wgIdx,xIdx,yIdx,zIdx,cellIdx,cellBatch);
+ //printf("cell %d has %d constraints\n", cellIdx,numConstraintsHost[cellIdx]);
+ if (zIdx)
+ {
+ //printf("?\n");
+ }
+
+ if (iter==0)
+ {
+ //printf("frame=%d, Cell xIdx=%x, yIdx=%d ",frame, xIdx,yIdx);
+ //printf("cellBatch=%d, wgIdx=%d, #constraints in cell=%d\n",cellBatch,wgIdx,numConstraintsHost[cellIdx]);
+ }
+ const int start = offsetsHost[cellIdx];
+ int numConstraintsInCell = numConstraintsHost[cellIdx];
+ // const int end = start + numConstraintsInCell;
+
+ SolveTask task( bodyNative, shapeNative, constraintNative, start, numConstraintsInCell ,maxNumBatches,usedBodies,wgIdx,batchSizes,cellIdx);
+ task.m_solveFriction = false;
+ task.run(0);
+
+ }
+ }
+ }
+
+ for(int iter=0; iter<m_nIterations; iter++)
+ {
+ for (int cellBatch=0;cellBatch<B3_SOLVER_N_BATCHES;cellBatch++)
+ {
+ int nSplitX = B3_SOLVER_N_SPLIT_X;
+ int nSplitY = B3_SOLVER_N_SPLIT_Y;
+
+
+ int numWorkgroups = B3_SOLVER_N_CELLS/B3_SOLVER_N_BATCHES;
+
+ for (int wgIdx=0;wgIdx<numWorkgroups;wgIdx++)
+ {
+ int zIdx = (wgIdx/((nSplitX*nSplitY)/4))*2+((cellBatch&4)>>2);
+ int remain= (wgIdx%((nSplitX*nSplitY)/4));
+ int yIdx = (remain/(nSplitX/2))*2 + ((cellBatch&2)>>1);
+ int xIdx = (remain%(nSplitX/2))*2 + (cellBatch&1);
+
+ int cellIdx = xIdx+yIdx*nSplitX+zIdx*(nSplitX*nSplitY);
+
+ if( numConstraintsHost[cellIdx] == 0 )
+ continue;
+
+ //printf("yIdx=%d\n",yIdx);
+
+ const int start = offsetsHost[cellIdx];
+ int numConstraintsInCell = numConstraintsHost[cellIdx];
+ // const int end = start + numConstraintsInCell;
+
+ SolveTask task( bodyNative, shapeNative, constraintNative, start, numConstraintsInCell,maxNumBatches, 0,0,batchSizes,cellIdx);
+ task.m_solveFriction = true;
+ task.run(0);
+
+ }
+ }
+ }
+
+
+ } else
+ {
+ for(int iter=0; iter<m_nIterations; iter++)
+ {
+ SolveTask task( bodyNative, shapeNative, constraintNative, 0, n ,maxNumBatches,0,0,0,0);
+ task.m_solveFriction = false;
+ task.run(0);
+ }
+
+ for(int iter=0; iter<m_nIterations; iter++)
+ {
+ SolveTask task( bodyNative, shapeNative, constraintNative, 0, n ,maxNumBatches,0,0,0,0);
+ task.m_solveFriction = true;
+ task.run(0);
+ }
+ }
+
+ bodyBuf->copyFromHost(bodyNative);
+ shapeBuf->copyFromHost(shapeNative);
+ constraint->copyFromHost(constraintNative);
+ frame++;
+
+}
+
+void checkConstraintBatch(const b3OpenCLArray<b3RigidBodyData>* bodyBuf,
+ const b3OpenCLArray<b3InertiaData>* shapeBuf,
+ b3OpenCLArray<b3GpuConstraint4>* constraint,
+ b3OpenCLArray<unsigned int>* m_numConstraints,
+ b3OpenCLArray<unsigned int>* m_offsets,
+ int batchId
+ )
+{
+// b3BufferInfoCL( m_numConstraints->getBufferCL() ),
+// b3BufferInfoCL( m_offsets->getBufferCL() )
+
+ int cellBatch = batchId;
+ const int nn = B3_SOLVER_N_CELLS;
+// int numWorkItems = 64*nn/B3_SOLVER_N_BATCHES;
+
+ b3AlignedObjectArray<unsigned int> gN;
+ m_numConstraints->copyToHost(gN);
+ b3AlignedObjectArray<unsigned int> gOffsets;
+ m_offsets->copyToHost(gOffsets);
+ int nSplitX = B3_SOLVER_N_SPLIT_X;
+ int nSplitY = B3_SOLVER_N_SPLIT_Y;
+
+// int bIdx = batchId;
+
+ b3AlignedObjectArray<b3GpuConstraint4> cpuConstraints;
+ constraint->copyToHost(cpuConstraints);
+
+ printf("batch = %d\n", batchId);
+
+ int numWorkgroups = nn/B3_SOLVER_N_BATCHES;
+ b3AlignedObjectArray<int> usedBodies;
+
+
+ for (int wgIdx=0;wgIdx<numWorkgroups;wgIdx++)
+ {
+ printf("wgIdx = %d ", wgIdx);
+
+ int zIdx = (wgIdx/((nSplitX*nSplitY))/2)*2+((cellBatch&4)>>2);
+ int remain = wgIdx%((nSplitX*nSplitY));
+ int yIdx = (remain%(nSplitX/2))*2 + ((cellBatch&2)>>1);
+ int xIdx = (remain/(nSplitX/2))*2 + (cellBatch&1);
+
+
+ int cellIdx = xIdx+yIdx*nSplitX+zIdx*(nSplitX*nSplitY);
+ printf("cellIdx=%d\n",cellIdx);
+ if( gN[cellIdx] == 0 )
+ continue;
+
+ const int start = gOffsets[cellIdx];
+ const int end = start + gN[cellIdx];
+
+ for (int c=start;c<end;c++)
+ {
+ b3GpuConstraint4& constraint = cpuConstraints[c];
+ //printf("constraint (%d,%d)\n", constraint.m_bodyA,constraint.m_bodyB);
+ if (usedBodies.findLinearSearch(constraint.m_bodyA)< usedBodies.size())
+ {
+ printf("error?\n");
+ }
+ if (usedBodies.findLinearSearch(constraint.m_bodyB)< usedBodies.size())
+ {
+ printf("error?\n");
+ }
+ }
+
+ for (int c=start;c<end;c++)
+ {
+ b3GpuConstraint4& constraint = cpuConstraints[c];
+ usedBodies.push_back(constraint.m_bodyA);
+ usedBodies.push_back(constraint.m_bodyB);
+ }
+
+ }
+}
+
+static bool verify=false;
+
+void b3Solver::solveContactConstraint( const b3OpenCLArray<b3RigidBodyData>* bodyBuf, const b3OpenCLArray<b3InertiaData>* shapeBuf,
+ b3OpenCLArray<b3GpuConstraint4>* constraint, void* additionalData, int n ,int maxNumBatches)
+{
+
+
+ b3Int4 cdata = b3MakeInt4( n, 0, 0, 0 );
+ {
+
+ const int nn = B3_SOLVER_N_CELLS;
+
+ cdata.x = 0;
+ cdata.y = maxNumBatches;//250;
+
+
+ int numWorkItems = 64*nn/B3_SOLVER_N_BATCHES;
+#ifdef DEBUG_ME
+ SolverDebugInfo* debugInfo = new SolverDebugInfo[numWorkItems];
+ adl::b3OpenCLArray<SolverDebugInfo> gpuDebugInfo(data->m_device,numWorkItems);
+#endif
+
+
+
+ {
+
+ B3_PROFILE("m_batchSolveKernel iterations");
+ for(int iter=0; iter<m_nIterations; iter++)
+ {
+ for(int ib=0; ib<B3_SOLVER_N_BATCHES; ib++)
+ {
+
+ if (verify)
+ {
+ checkConstraintBatch(bodyBuf,shapeBuf,constraint,m_numConstraints,m_offsets,ib);
+ }
+
+#ifdef DEBUG_ME
+ memset(debugInfo,0,sizeof(SolverDebugInfo)*numWorkItems);
+ gpuDebugInfo.write(debugInfo,numWorkItems);
+#endif
+
+
+ cdata.z = ib;
+
+
+ b3LauncherCL launcher( m_queue, m_solveContactKernel ,"m_solveContactKernel");
+#if 1
+
+ b3BufferInfoCL bInfo[] = {
+
+ b3BufferInfoCL( bodyBuf->getBufferCL() ),
+ b3BufferInfoCL( shapeBuf->getBufferCL() ),
+ b3BufferInfoCL( constraint->getBufferCL() ),
+ b3BufferInfoCL( m_numConstraints->getBufferCL() ),
+ b3BufferInfoCL( m_offsets->getBufferCL() )
+#ifdef DEBUG_ME
+ , b3BufferInfoCL(&gpuDebugInfo)
+#endif
+ };
+
+
+
+ launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ //launcher.setConst( cdata.x );
+ launcher.setConst( cdata.y );
+ launcher.setConst( cdata.z );
+ b3Int4 nSplit;
+ nSplit.x = B3_SOLVER_N_SPLIT_X;
+ nSplit.y = B3_SOLVER_N_SPLIT_Y;
+ nSplit.z = B3_SOLVER_N_SPLIT_Z;
+
+ launcher.setConst( nSplit );
+ launcher.launch1D( numWorkItems, 64 );
+
+
+#else
+ const char* fileName = "m_batchSolveKernel.bin";
+ FILE* f = fopen(fileName,"rb");
+ if (f)
+ {
+ int sizeInBytes=0;
+ if (fseek(f, 0, SEEK_END) || (sizeInBytes = ftell(f)) == EOF || fseek(f, 0, SEEK_SET))
+ {
+ printf("error, cannot get file size\n");
+ exit(0);
+ }
+
+ unsigned char* buf = (unsigned char*) malloc(sizeInBytes);
+ fread(buf,sizeInBytes,1,f);
+ int serializedBytes = launcher.deserializeArgs(buf, sizeInBytes,m_context);
+ int num = *(int*)&buf[serializedBytes];
+
+ launcher.launch1D( num);
+
+ //this clFinish is for testing on errors
+ clFinish(m_queue);
+ }
+
+#endif
+
+
+#ifdef DEBUG_ME
+ clFinish(m_queue);
+ gpuDebugInfo.read(debugInfo,numWorkItems);
+ clFinish(m_queue);
+ for (int i=0;i<numWorkItems;i++)
+ {
+ if (debugInfo[i].m_valInt2>0)
+ {
+ printf("debugInfo[i].m_valInt2 = %d\n",i,debugInfo[i].m_valInt2);
+ }
+
+ if (debugInfo[i].m_valInt3>0)
+ {
+ printf("debugInfo[i].m_valInt3 = %d\n",i,debugInfo[i].m_valInt3);
+ }
+ }
+#endif //DEBUG_ME
+
+
+ }
+ }
+
+ clFinish(m_queue);
+
+
+ }
+
+ cdata.x = 1;
+ bool applyFriction=true;
+ if (applyFriction)
+ {
+ B3_PROFILE("m_batchSolveKernel iterations2");
+ for(int iter=0; iter<m_nIterations; iter++)
+ {
+ for(int ib=0; ib<B3_SOLVER_N_BATCHES; ib++)
+ {
+ cdata.z = ib;
+
+
+ b3BufferInfoCL bInfo[] = {
+ b3BufferInfoCL( bodyBuf->getBufferCL() ),
+ b3BufferInfoCL( shapeBuf->getBufferCL() ),
+ b3BufferInfoCL( constraint->getBufferCL() ),
+ b3BufferInfoCL( m_numConstraints->getBufferCL() ),
+ b3BufferInfoCL( m_offsets->getBufferCL() )
+#ifdef DEBUG_ME
+ ,b3BufferInfoCL(&gpuDebugInfo)
+#endif //DEBUG_ME
+ };
+ b3LauncherCL launcher( m_queue, m_solveFrictionKernel,"m_solveFrictionKernel" );
+ launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ //launcher.setConst( cdata.x );
+ launcher.setConst( cdata.y );
+ launcher.setConst( cdata.z );
+ b3Int4 nSplit;
+ nSplit.x = B3_SOLVER_N_SPLIT_X;
+ nSplit.y = B3_SOLVER_N_SPLIT_Y;
+ nSplit.z = B3_SOLVER_N_SPLIT_Z;
+
+ launcher.setConst( nSplit );
+
+ launcher.launch1D( 64*nn/B3_SOLVER_N_BATCHES, 64 );
+ }
+ }
+ clFinish(m_queue);
+
+ }
+#ifdef DEBUG_ME
+ delete[] debugInfo;
+#endif //DEBUG_ME
+ }
+
+
+}
+
+void b3Solver::convertToConstraints( const b3OpenCLArray<b3RigidBodyData>* bodyBuf,
+ const b3OpenCLArray<b3InertiaData>* shapeBuf,
+ b3OpenCLArray<b3Contact4>* contactsIn, b3OpenCLArray<b3GpuConstraint4>* contactCOut, void* additionalData,
+ int nContacts, const ConstraintCfg& cfg )
+{
+// b3OpenCLArray<b3GpuConstraint4>* constraintNative =0;
+ contactCOut->resize(nContacts);
+ struct CB
+ {
+ int m_nContacts;
+ float m_dt;
+ float m_positionDrift;
+ float m_positionConstraintCoeff;
+ };
+
+ {
+
+ CB cdata;
+ cdata.m_nContacts = nContacts;
+ cdata.m_dt = cfg.m_dt;
+ cdata.m_positionDrift = cfg.m_positionDrift;
+ cdata.m_positionConstraintCoeff = cfg.m_positionConstraintCoeff;
+
+
+ if (gConvertConstraintOnCpu)
+ {
+ b3AlignedObjectArray<b3RigidBodyData> gBodies;
+ bodyBuf->copyToHost(gBodies);
+
+ b3AlignedObjectArray<b3Contact4> gContact;
+ contactsIn->copyToHost(gContact);
+
+ b3AlignedObjectArray<b3InertiaData> gShapes;
+ shapeBuf->copyToHost(gShapes);
+
+ b3AlignedObjectArray<b3GpuConstraint4> gConstraintOut;
+ gConstraintOut.resize(nContacts);
+
+ B3_PROFILE("cpu contactToConstraintKernel");
+ for (int gIdx=0;gIdx<nContacts;gIdx++)
+ {
+ int aIdx = abs(gContact[gIdx].m_bodyAPtrAndSignBit);
+ int bIdx = abs(gContact[gIdx].m_bodyBPtrAndSignBit);
+
+ b3Float4 posA = gBodies[aIdx].m_pos;
+ b3Float4 linVelA = gBodies[aIdx].m_linVel;
+ b3Float4 angVelA = gBodies[aIdx].m_angVel;
+ float invMassA = gBodies[aIdx].m_invMass;
+ b3Mat3x3 invInertiaA = gShapes[aIdx].m_initInvInertia;
+
+ b3Float4 posB = gBodies[bIdx].m_pos;
+ b3Float4 linVelB = gBodies[bIdx].m_linVel;
+ b3Float4 angVelB = gBodies[bIdx].m_angVel;
+ float invMassB = gBodies[bIdx].m_invMass;
+ b3Mat3x3 invInertiaB = gShapes[bIdx].m_initInvInertia;
+
+ b3ContactConstraint4_t cs;
+
+ setConstraint4( posA, linVelA, angVelA, invMassA, invInertiaA, posB, linVelB, angVelB, invMassB, invInertiaB,
+ &gContact[gIdx], cdata.m_dt, cdata.m_positionDrift, cdata.m_positionConstraintCoeff,
+ &cs );
+
+ cs.m_batchIdx = gContact[gIdx].m_batchIdx;
+
+ gConstraintOut[gIdx] = (b3GpuConstraint4&)cs;
+ }
+
+ contactCOut->copyFromHost(gConstraintOut);
+
+ } else
+ {
+ B3_PROFILE("gpu m_contactToConstraintKernel");
+
+
+ b3BufferInfoCL bInfo[] = { b3BufferInfoCL( contactsIn->getBufferCL() ), b3BufferInfoCL( bodyBuf->getBufferCL() ), b3BufferInfoCL( shapeBuf->getBufferCL()),
+ b3BufferInfoCL( contactCOut->getBufferCL() )};
+ b3LauncherCL launcher( m_queue, m_contactToConstraintKernel,"m_contactToConstraintKernel" );
+ launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ //launcher.setConst( cdata );
+
+ launcher.setConst(cdata.m_nContacts);
+ launcher.setConst(cdata.m_dt);
+ launcher.setConst(cdata.m_positionDrift);
+ launcher.setConst(cdata.m_positionConstraintCoeff);
+
+ launcher.launch1D( nContacts, 64 );
+ clFinish(m_queue);
+
+ }
+ }
+
+
+}
+
+/*
+void b3Solver::sortContacts( const b3OpenCLArray<b3RigidBodyData>* bodyBuf,
+ b3OpenCLArray<b3Contact4>* contactsIn, void* additionalData,
+ int nContacts, const b3Solver::ConstraintCfg& cfg )
+{
+
+
+
+ const int sortAlignment = 512; // todo. get this out of sort
+ if( cfg.m_enableParallelSolve )
+ {
+
+
+ int sortSize = NEXTMULTIPLEOF( nContacts, sortAlignment );
+
+ b3OpenCLArray<unsigned int>* countsNative = m_numConstraints;//BufferUtils::map<TYPE_CL, false>( data->m_device, &countsHost );
+ b3OpenCLArray<unsigned int>* offsetsNative = m_offsets;//BufferUtils::map<TYPE_CL, false>( data->m_device, &offsetsHost );
+
+ { // 2. set cell idx
+ struct CB
+ {
+ int m_nContacts;
+ int m_staticIdx;
+ float m_scale;
+ int m_nSplit;
+ };
+
+ b3Assert( sortSize%64 == 0 );
+ CB cdata;
+ cdata.m_nContacts = nContacts;
+ cdata.m_staticIdx = cfg.m_staticIdx;
+ cdata.m_scale = 1.f/(N_OBJ_PER_SPLIT*cfg.m_averageExtent);
+ cdata.m_nSplit = B3_SOLVER_N_SPLIT;
+
+
+ b3BufferInfoCL bInfo[] = { b3BufferInfoCL( contactsIn->getBufferCL() ), b3BufferInfoCL( bodyBuf->getBufferCL() ), b3BufferInfoCL( m_sortDataBuffer->getBufferCL() ) };
+ b3LauncherCL launcher( m_queue, m_setSortDataKernel );
+ launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst( cdata );
+ launcher.launch1D( sortSize, 64 );
+ }
+
+ { // 3. sort by cell idx
+ int n = B3_SOLVER_N_SPLIT*B3_SOLVER_N_SPLIT;
+ int sortBit = 32;
+ //if( n <= 0xffff ) sortBit = 16;
+ //if( n <= 0xff ) sortBit = 8;
+ m_sort32->execute(*m_sortDataBuffer,sortSize);
+ }
+ { // 4. find entries
+ m_search->execute( *m_sortDataBuffer, nContacts, *countsNative, B3_SOLVER_N_SPLIT*B3_SOLVER_N_SPLIT, b3BoundSearchCL::COUNT);
+
+ m_scan->execute( *countsNative, *offsetsNative, B3_SOLVER_N_SPLIT*B3_SOLVER_N_SPLIT );
+ }
+
+ { // 5. sort constraints by cellIdx
+ // todo. preallocate this
+// b3Assert( contactsIn->getType() == TYPE_HOST );
+// b3OpenCLArray<b3Contact4>* out = BufferUtils::map<TYPE_CL, false>( data->m_device, contactsIn ); // copying contacts to this buffer
+
+ {
+
+
+ b3Int4 cdata; cdata.x = nContacts;
+ b3BufferInfoCL bInfo[] = { b3BufferInfoCL( contactsIn->getBufferCL() ), b3BufferInfoCL( m_contactBuffer->getBufferCL() ), b3BufferInfoCL( m_sortDataBuffer->getBufferCL() ) };
+ b3LauncherCL launcher( m_queue, m_reorderContactKernel );
+ launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+ launcher.setConst( cdata );
+ launcher.launch1D( nContacts, 64 );
+ }
+// BufferUtils::unmap<true>( out, contactsIn, nContacts );
+ }
+ }
+
+
+}
+
+*/
+void b3Solver::batchContacts( b3OpenCLArray<b3Contact4>* contacts, int nContacts, b3OpenCLArray<unsigned int>* nNative, b3OpenCLArray<unsigned int>* offsetsNative, int staticIdx )
+{
+
+ int numWorkItems = 64*B3_SOLVER_N_CELLS;
+ {
+ B3_PROFILE("batch generation");
+
+ b3Int4 cdata;
+ cdata.x = nContacts;
+ cdata.y = 0;
+ cdata.z = staticIdx;
+
+
+#ifdef BATCH_DEBUG
+ SolverDebugInfo* debugInfo = new SolverDebugInfo[numWorkItems];
+ adl::b3OpenCLArray<SolverDebugInfo> gpuDebugInfo(data->m_device,numWorkItems);
+ memset(debugInfo,0,sizeof(SolverDebugInfo)*numWorkItems);
+ gpuDebugInfo.write(debugInfo,numWorkItems);
+#endif
+
+
+
+#if 0
+ b3BufferInfoCL bInfo[] = {
+ b3BufferInfoCL( contacts->getBufferCL() ),
+ b3BufferInfoCL( m_contactBuffer2->getBufferCL()),
+ b3BufferInfoCL( nNative->getBufferCL() ),
+ b3BufferInfoCL( offsetsNative->getBufferCL() ),
+#ifdef BATCH_DEBUG
+ , b3BufferInfoCL(&gpuDebugInfo)
+#endif
+ };
+#endif
+
+
+
+ {
+ m_batchSizes.resize(nNative->size());
+ B3_PROFILE("batchingKernel");
+ //b3LauncherCL launcher( m_queue, m_batchingKernel);
+ cl_kernel k = useNewBatchingKernel ? m_batchingKernelNew : m_batchingKernel;
+
+ b3LauncherCL launcher( m_queue, k,"*batchingKernel");
+ if (!useNewBatchingKernel )
+ {
+ launcher.setBuffer( contacts->getBufferCL() );
+ }
+ launcher.setBuffer( m_contactBuffer2->getBufferCL() );
+ launcher.setBuffer( nNative->getBufferCL());
+ launcher.setBuffer( offsetsNative->getBufferCL());
+
+ launcher.setBuffer(m_batchSizes.getBufferCL());
+
+
+ //launcher.setConst( cdata );
+ launcher.setConst(staticIdx);
+
+ launcher.launch1D( numWorkItems, 64 );
+ //clFinish(m_queue);
+ //b3AlignedObjectArray<int> batchSizesCPU;
+ //m_batchSizes.copyToHost(batchSizesCPU);
+ //printf(".\n");
+ }
+
+#ifdef BATCH_DEBUG
+ aaaa
+ b3Contact4* hostContacts = new b3Contact4[nContacts];
+ m_contactBuffer->read(hostContacts,nContacts);
+ clFinish(m_queue);
+
+ gpuDebugInfo.read(debugInfo,numWorkItems);
+ clFinish(m_queue);
+
+ for (int i=0;i<numWorkItems;i++)
+ {
+ if (debugInfo[i].m_valInt1>0)
+ {
+ printf("catch\n");
+ }
+ if (debugInfo[i].m_valInt2>0)
+ {
+ printf("catch22\n");
+ }
+
+ if (debugInfo[i].m_valInt3>0)
+ {
+ printf("catch666\n");
+ }
+
+ if (debugInfo[i].m_valInt4>0)
+ {
+ printf("catch777\n");
+ }
+ }
+ delete[] debugInfo;
+#endif //BATCH_DEBUG
+
+ }
+
+// copy buffer to buffer
+ //b3Assert(m_contactBuffer->size()==nContacts);
+ //contacts->copyFromOpenCLArray( *m_contactBuffer);
+ //clFinish(m_queue);//needed?
+
+
+
+}
+
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3Solver.h b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3Solver.h
new file mode 100644
index 0000000000..b37f2f1bec
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/b3Solver.h
@@ -0,0 +1,126 @@
+/*
+Copyright (c) 2012 Advanced Micro Devices, Inc.
+
+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.
+*/
+//Originally written by Takahiro Harada
+
+
+#ifndef __ADL_SOLVER_H
+#define __ADL_SOLVER_H
+
+#include "Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h"
+#include "b3GpuConstraint4.h"
+
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
+#include "Bullet3Collision/NarrowPhaseCollision/b3Contact4.h"
+
+#include "Bullet3OpenCL/ParallelPrimitives/b3PrefixScanCL.h"
+#include "Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.h"
+#include "Bullet3OpenCL/ParallelPrimitives/b3BoundSearchCL.h"
+
+#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
+
+
+#define B3NEXTMULTIPLEOF(num, alignment) (((num)/(alignment) + (((num)%(alignment)==0)?0:1))*(alignment))
+
+enum
+{
+ B3_SOLVER_N_SPLIT_X = 8,//16,//4,
+ B3_SOLVER_N_SPLIT_Y = 4,//16,//4,
+ B3_SOLVER_N_SPLIT_Z = 8,//,
+ B3_SOLVER_N_CELLS = B3_SOLVER_N_SPLIT_X*B3_SOLVER_N_SPLIT_Y*B3_SOLVER_N_SPLIT_Z,
+ B3_SOLVER_N_BATCHES = 8,//4,//8,//4,
+ B3_MAX_NUM_BATCHES = 128,
+};
+
+class b3SolverBase
+{
+ public:
+
+
+ struct ConstraintCfg
+ {
+ ConstraintCfg( float dt = 0.f ): m_positionDrift( 0.005f ), m_positionConstraintCoeff( 0.2f ), m_dt(dt), m_staticIdx(-1) {}
+
+ float m_positionDrift;
+ float m_positionConstraintCoeff;
+ float m_dt;
+ bool m_enableParallelSolve;
+ float m_batchCellSize;
+ int m_staticIdx;
+ };
+
+};
+
+class b3Solver : public b3SolverBase
+{
+ public:
+
+ cl_context m_context;
+ cl_device_id m_device;
+ cl_command_queue m_queue;
+
+
+ b3OpenCLArray<unsigned int>* m_numConstraints;
+ b3OpenCLArray<unsigned int>* m_offsets;
+ b3OpenCLArray<int> m_batchSizes;
+
+
+ int m_nIterations;
+ cl_kernel m_batchingKernel;
+ cl_kernel m_batchingKernelNew;
+ cl_kernel m_solveContactKernel;
+ cl_kernel m_solveFrictionKernel;
+ cl_kernel m_contactToConstraintKernel;
+ cl_kernel m_setSortDataKernel;
+ cl_kernel m_reorderContactKernel;
+ cl_kernel m_copyConstraintKernel;
+
+ class b3RadixSort32CL* m_sort32;
+ class b3BoundSearchCL* m_search;
+ class b3PrefixScanCL* m_scan;
+
+ b3OpenCLArray<b3SortData>* m_sortDataBuffer;
+ b3OpenCLArray<b3Contact4>* m_contactBuffer2;
+
+ enum
+ {
+ DYNAMIC_CONTACT_ALLOCATION_THRESHOLD = 2000000,
+ };
+
+
+
+
+ b3Solver(cl_context ctx, cl_device_id device, cl_command_queue queue, int pairCapacity);
+
+ virtual ~b3Solver();
+
+ void solveContactConstraint( const b3OpenCLArray<b3RigidBodyData>* bodyBuf, const b3OpenCLArray<b3InertiaData>* inertiaBuf,
+ b3OpenCLArray<b3GpuConstraint4>* constraint, void* additionalData, int n ,int maxNumBatches);
+
+ void solveContactConstraintHost( b3OpenCLArray<b3RigidBodyData>* bodyBuf, b3OpenCLArray<b3InertiaData>* shapeBuf,
+ b3OpenCLArray<b3GpuConstraint4>* constraint, void* additionalData, int n ,int maxNumBatches, b3AlignedObjectArray<int>* batchSizes);
+
+
+ void convertToConstraints( const b3OpenCLArray<b3RigidBodyData>* bodyBuf,
+ const b3OpenCLArray<b3InertiaData>* shapeBuf,
+ b3OpenCLArray<b3Contact4>* contactsIn, b3OpenCLArray<b3GpuConstraint4>* contactCOut, void* additionalData,
+ int nContacts, const ConstraintCfg& cfg );
+
+ void batchContacts( b3OpenCLArray<b3Contact4>* contacts, int nContacts, b3OpenCLArray<unsigned int>* n, b3OpenCLArray<unsigned int>* offsets, int staticIdx );
+
+};
+
+
+
+
+#endif //__ADL_SOLVER_H
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/batchingKernels.cl b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/batchingKernels.cl
new file mode 100644
index 0000000000..3b891b863d
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/batchingKernels.cl
@@ -0,0 +1,353 @@
+/*
+Copyright (c) 2012 Advanced Micro Devices, Inc.
+
+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.
+*/
+//Originally written by Takahiro Harada
+
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h"
+
+#pragma OPENCL EXTENSION cl_amd_printf : enable
+#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable
+
+#ifdef cl_ext_atomic_counters_32
+#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable
+#else
+#define counter32_t volatile __global int*
+#endif
+
+
+typedef unsigned int u32;
+typedef unsigned short u16;
+typedef unsigned char u8;
+
+#define GET_GROUP_IDX get_group_id(0)
+#define GET_LOCAL_IDX get_local_id(0)
+#define GET_GLOBAL_IDX get_global_id(0)
+#define GET_GROUP_SIZE get_local_size(0)
+#define GET_NUM_GROUPS get_num_groups(0)
+#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)
+#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)
+#define AtomInc(x) atom_inc(&(x))
+#define AtomInc1(x, out) out = atom_inc(&(x))
+#define AppendInc(x, out) out = atomic_inc(x)
+#define AtomAdd(x, value) atom_add(&(x), value)
+#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )
+#define AtomXhg(x, value) atom_xchg ( &(x), value )
+
+
+#define SELECT_UINT4( b, a, condition ) select( b,a,condition )
+
+#define make_float4 (float4)
+#define make_float2 (float2)
+#define make_uint4 (uint4)
+#define make_int4 (int4)
+#define make_uint2 (uint2)
+#define make_int2 (int2)
+
+
+#define max2 max
+#define min2 min
+
+
+#define WG_SIZE 64
+
+
+
+
+
+typedef struct
+{
+ int m_n;
+ int m_start;
+ int m_staticIdx;
+ int m_paddings[1];
+} ConstBuffer;
+
+typedef struct
+{
+ int m_a;
+ int m_b;
+ u32 m_idx;
+}Elem;
+
+#define STACK_SIZE (WG_SIZE*10)
+//#define STACK_SIZE (WG_SIZE)
+#define RING_SIZE 1024
+#define RING_SIZE_MASK (RING_SIZE-1)
+#define CHECK_SIZE (WG_SIZE)
+
+
+#define GET_RING_CAPACITY (RING_SIZE - ldsRingEnd)
+#define RING_END ldsTmp
+
+u32 readBuf(__local u32* buff, int idx)
+{
+ idx = idx % (32*CHECK_SIZE);
+ int bitIdx = idx%32;
+ int bufIdx = idx/32;
+ return buff[bufIdx] & (1<<bitIdx);
+}
+
+void writeBuf(__local u32* buff, int idx)
+{
+ idx = idx % (32*CHECK_SIZE);
+ int bitIdx = idx%32;
+ int bufIdx = idx/32;
+// buff[bufIdx] |= (1<<bitIdx);
+ atom_or( &buff[bufIdx], (1<<bitIdx) );
+}
+
+u32 tryWrite(__local u32* buff, int idx)
+{
+ idx = idx % (32*CHECK_SIZE);
+ int bitIdx = idx%32;
+ int bufIdx = idx/32;
+ u32 ans = (u32)atom_or( &buff[bufIdx], (1<<bitIdx) );
+ return ((ans >> bitIdx)&1) == 0;
+}
+
+// batching on the GPU
+__kernel void CreateBatches( __global const struct b3Contact4Data* gConstraints, __global struct b3Contact4Data* gConstraintsOut,
+ __global const u32* gN, __global const u32* gStart, __global int* batchSizes,
+ int m_staticIdx )
+{
+ __local u32 ldsStackIdx[STACK_SIZE];
+ __local u32 ldsStackEnd;
+ __local Elem ldsRingElem[RING_SIZE];
+ __local u32 ldsRingEnd;
+ __local u32 ldsTmp;
+ __local u32 ldsCheckBuffer[CHECK_SIZE];
+ __local u32 ldsFixedBuffer[CHECK_SIZE];
+ __local u32 ldsGEnd;
+ __local u32 ldsDstEnd;
+
+ int wgIdx = GET_GROUP_IDX;
+ int lIdx = GET_LOCAL_IDX;
+
+ const int m_n = gN[wgIdx];
+ const int m_start = gStart[wgIdx];
+
+ if( lIdx == 0 )
+ {
+ ldsRingEnd = 0;
+ ldsGEnd = 0;
+ ldsStackEnd = 0;
+ ldsDstEnd = m_start;
+ }
+
+
+
+// while(1)
+//was 250
+ int ie=0;
+ int maxBatch = 0;
+ for(ie=0; ie<50; ie++)
+ {
+ ldsFixedBuffer[lIdx] = 0;
+
+ for(int giter=0; giter<4; giter++)
+ {
+ int ringCap = GET_RING_CAPACITY;
+
+ // 1. fill ring
+ if( ldsGEnd < m_n )
+ {
+ while( ringCap > WG_SIZE )
+ {
+ if( ldsGEnd >= m_n ) break;
+ if( lIdx < ringCap - WG_SIZE )
+ {
+ int srcIdx;
+ AtomInc1( ldsGEnd, srcIdx );
+ if( srcIdx < m_n )
+ {
+ int dstIdx;
+ AtomInc1( ldsRingEnd, dstIdx );
+
+ int a = gConstraints[m_start+srcIdx].m_bodyAPtrAndSignBit;
+ int b = gConstraints[m_start+srcIdx].m_bodyBPtrAndSignBit;
+ ldsRingElem[dstIdx].m_a = (a>b)? b:a;
+ ldsRingElem[dstIdx].m_b = (a>b)? a:b;
+ ldsRingElem[dstIdx].m_idx = srcIdx;
+ }
+ }
+ ringCap = GET_RING_CAPACITY;
+ }
+ }
+
+ GROUP_LDS_BARRIER;
+
+ // 2. fill stack
+ __local Elem* dst = ldsRingElem;
+ if( lIdx == 0 ) RING_END = 0;
+
+ int srcIdx=lIdx;
+ int end = ldsRingEnd;
+
+ {
+ for(int ii=0; ii<end; ii+=WG_SIZE, srcIdx+=WG_SIZE)
+ {
+ Elem e;
+ if(srcIdx<end) e = ldsRingElem[srcIdx];
+ bool done = (srcIdx<end)?false:true;
+
+ for(int i=lIdx; i<CHECK_SIZE; i+=WG_SIZE) ldsCheckBuffer[lIdx] = 0;
+
+ if( !done )
+ {
+ int aUsed = readBuf( ldsFixedBuffer, abs(e.m_a));
+ int bUsed = readBuf( ldsFixedBuffer, abs(e.m_b));
+
+ if( aUsed==0 && bUsed==0 )
+ {
+ int aAvailable=1;
+ int bAvailable=1;
+ int ea = abs(e.m_a);
+ int eb = abs(e.m_b);
+
+ bool aStatic = (e.m_a<0) ||(ea==m_staticIdx);
+ bool bStatic = (e.m_b<0) ||(eb==m_staticIdx);
+
+ if (!aStatic)
+ aAvailable = tryWrite( ldsCheckBuffer, ea );
+ if (!bStatic)
+ bAvailable = tryWrite( ldsCheckBuffer, eb );
+
+ //aAvailable = aStatic? 1: aAvailable;
+ //bAvailable = bStatic? 1: bAvailable;
+
+ bool success = (aAvailable && bAvailable);
+ if(success)
+ {
+
+ if (!aStatic)
+ writeBuf( ldsFixedBuffer, ea );
+ if (!bStatic)
+ writeBuf( ldsFixedBuffer, eb );
+ }
+ done = success;
+ }
+ }
+
+ // put it aside
+ if(srcIdx<end)
+ {
+ if( done )
+ {
+ int dstIdx; AtomInc1( ldsStackEnd, dstIdx );
+ if( dstIdx < STACK_SIZE )
+ ldsStackIdx[dstIdx] = e.m_idx;
+ else{
+ done = false;
+ AtomAdd( ldsStackEnd, -1 );
+ }
+ }
+ if( !done )
+ {
+ int dstIdx; AtomInc1( RING_END, dstIdx );
+ dst[dstIdx] = e;
+ }
+ }
+
+ // if filled, flush
+ if( ldsStackEnd == STACK_SIZE )
+ {
+ for(int i=lIdx; i<STACK_SIZE; i+=WG_SIZE)
+ {
+ int idx = m_start + ldsStackIdx[i];
+ int dstIdx; AtomInc1( ldsDstEnd, dstIdx );
+ gConstraintsOut[ dstIdx ] = gConstraints[ idx ];
+ gConstraintsOut[ dstIdx ].m_batchIdx = ie;
+ }
+ if( lIdx == 0 ) ldsStackEnd = 0;
+
+ //for(int i=lIdx; i<CHECK_SIZE; i+=WG_SIZE)
+ ldsFixedBuffer[lIdx] = 0;
+ }
+ }
+ }
+
+ if( lIdx == 0 ) ldsRingEnd = RING_END;
+ }
+
+ GROUP_LDS_BARRIER;
+
+ for(int i=lIdx; i<ldsStackEnd; i+=WG_SIZE)
+ {
+ int idx = m_start + ldsStackIdx[i];
+ int dstIdx; AtomInc1( ldsDstEnd, dstIdx );
+ gConstraintsOut[ dstIdx ] = gConstraints[ idx ];
+ gConstraintsOut[ dstIdx ].m_batchIdx = ie;
+ }
+
+ // in case it couldn't consume any pair. Flush them
+ // todo. Serial batch worth while?
+ if( ldsStackEnd == 0 )
+ {
+ for(int i=lIdx; i<ldsRingEnd; i+=WG_SIZE)
+ {
+ int idx = m_start + ldsRingElem[i].m_idx;
+ int dstIdx; AtomInc1( ldsDstEnd, dstIdx );
+ gConstraintsOut[ dstIdx ] = gConstraints[ idx ];
+ int curBatch = 100+i;
+ if (maxBatch < curBatch)
+ maxBatch = curBatch;
+
+ gConstraintsOut[ dstIdx ].m_batchIdx = curBatch;
+
+ }
+ GROUP_LDS_BARRIER;
+ if( lIdx == 0 ) ldsRingEnd = 0;
+ }
+
+ if( lIdx == 0 ) ldsStackEnd = 0;
+
+ GROUP_LDS_BARRIER;
+
+ // termination
+ if( ldsGEnd == m_n && ldsRingEnd == 0 )
+ break;
+ }
+
+ if( lIdx == 0 )
+ {
+ if (maxBatch < ie)
+ maxBatch=ie;
+ batchSizes[wgIdx]=maxBatch;
+ }
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/batchingKernels.h b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/batchingKernels.h
new file mode 100644
index 0000000000..150eedc94b
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/batchingKernels.h
@@ -0,0 +1,388 @@
+//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
+static const char* batchingKernelsCL= \
+"/*\n"
+"Copyright (c) 2012 Advanced Micro Devices, Inc. \n"
+"This software is provided 'as-is', without any express or implied warranty.\n"
+"In no event will the authors be held liable for any damages arising from the use of this software.\n"
+"Permission is granted to anyone to use this software for any purpose, \n"
+"including commercial applications, and to alter it and redistribute it freely, \n"
+"subject to the following restrictions:\n"
+"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.\n"
+"2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
+"3. This notice may not be removed or altered from any source distribution.\n"
+"*/\n"
+"//Originally written by Takahiro Harada\n"
+"#ifndef B3_CONTACT4DATA_H\n"
+"#define B3_CONTACT4DATA_H\n"
+"#ifndef B3_FLOAT4_H\n"
+"#define B3_FLOAT4_H\n"
+"#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+"#define B3_PLATFORM_DEFINITIONS_H\n"
+"struct MyTest\n"
+"{\n"
+" int bla;\n"
+"};\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
+"#define B3_LARGE_FLOAT 1e18f\n"
+"#define B3_INFINITY 1e18f\n"
+"#define b3Assert(a)\n"
+"#define b3ConstArray(a) __global const a*\n"
+"#define b3AtomicInc atomic_inc\n"
+"#define b3AtomicAdd atomic_add\n"
+"#define b3Fabs fabs\n"
+"#define b3Sqrt native_sqrt\n"
+"#define b3Sin native_sin\n"
+"#define b3Cos native_cos\n"
+"#define B3_STATIC\n"
+"#endif\n"
+"#endif\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+" typedef float4 b3Float4;\n"
+" #define b3Float4ConstArg const b3Float4\n"
+" #define b3MakeFloat4 (float4)\n"
+" float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+" {\n"
+" float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+" float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+" return dot(a1, b1);\n"
+" }\n"
+" b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+" {\n"
+" float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+" float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+" return cross(a1, b1);\n"
+" }\n"
+" #define b3MinFloat4 min\n"
+" #define b3MaxFloat4 max\n"
+" #define b3Normalized(a) normalize(a)\n"
+"#endif \n"
+" \n"
+"inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
+"{\n"
+" if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6) \n"
+" return false;\n"
+" return true;\n"
+"}\n"
+"inline int b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
+"{\n"
+" float maxDot = -B3_INFINITY;\n"
+" int i = 0;\n"
+" int ptIndex = -1;\n"
+" for( i = 0; i < vecLen; i++ )\n"
+" {\n"
+" float dot = b3Dot3F4(vecArray[i],vec);\n"
+" \n"
+" if( dot > maxDot )\n"
+" {\n"
+" maxDot = dot;\n"
+" ptIndex = i;\n"
+" }\n"
+" }\n"
+" b3Assert(ptIndex>=0);\n"
+" if (ptIndex<0)\n"
+" {\n"
+" ptIndex = 0;\n"
+" }\n"
+" *dotOut = maxDot;\n"
+" return ptIndex;\n"
+"}\n"
+"#endif //B3_FLOAT4_H\n"
+"typedef struct b3Contact4Data b3Contact4Data_t;\n"
+"struct b3Contact4Data\n"
+"{\n"
+" b3Float4 m_worldPosB[4];\n"
+"// b3Float4 m_localPosA[4];\n"
+"// b3Float4 m_localPosB[4];\n"
+" b3Float4 m_worldNormalOnB; // w: m_nPoints\n"
+" unsigned short m_restituitionCoeffCmp;\n"
+" unsigned short m_frictionCoeffCmp;\n"
+" int m_batchIdx;\n"
+" int m_bodyAPtrAndSignBit;//x:m_bodyAPtr, y:m_bodyBPtr\n"
+" int m_bodyBPtrAndSignBit;\n"
+" int m_childIndexA;\n"
+" int m_childIndexB;\n"
+" int m_unused1;\n"
+" int m_unused2;\n"
+"};\n"
+"inline int b3Contact4Data_getNumPoints(const struct b3Contact4Data* contact)\n"
+"{\n"
+" return (int)contact->m_worldNormalOnB.w;\n"
+"};\n"
+"inline void b3Contact4Data_setNumPoints(struct b3Contact4Data* contact, int numPoints)\n"
+"{\n"
+" contact->m_worldNormalOnB.w = (float)numPoints;\n"
+"};\n"
+"#endif //B3_CONTACT4DATA_H\n"
+"#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
+"#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
+"#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
+"#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n"
+"#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n"
+"#ifdef cl_ext_atomic_counters_32\n"
+"#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n"
+"#else\n"
+"#define counter32_t volatile __global int*\n"
+"#endif\n"
+"typedef unsigned int u32;\n"
+"typedef unsigned short u16;\n"
+"typedef unsigned char u8;\n"
+"#define GET_GROUP_IDX get_group_id(0)\n"
+"#define GET_LOCAL_IDX get_local_id(0)\n"
+"#define GET_GLOBAL_IDX get_global_id(0)\n"
+"#define GET_GROUP_SIZE get_local_size(0)\n"
+"#define GET_NUM_GROUPS get_num_groups(0)\n"
+"#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
+"#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
+"#define AtomInc(x) atom_inc(&(x))\n"
+"#define AtomInc1(x, out) out = atom_inc(&(x))\n"
+"#define AppendInc(x, out) out = atomic_inc(x)\n"
+"#define AtomAdd(x, value) atom_add(&(x), value)\n"
+"#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )\n"
+"#define AtomXhg(x, value) atom_xchg ( &(x), value )\n"
+"#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n"
+"#define make_float4 (float4)\n"
+"#define make_float2 (float2)\n"
+"#define make_uint4 (uint4)\n"
+"#define make_int4 (int4)\n"
+"#define make_uint2 (uint2)\n"
+"#define make_int2 (int2)\n"
+"#define max2 max\n"
+"#define min2 min\n"
+"#define WG_SIZE 64\n"
+"typedef struct \n"
+"{\n"
+" int m_n;\n"
+" int m_start;\n"
+" int m_staticIdx;\n"
+" int m_paddings[1];\n"
+"} ConstBuffer;\n"
+"typedef struct \n"
+"{\n"
+" int m_a;\n"
+" int m_b;\n"
+" u32 m_idx;\n"
+"}Elem;\n"
+"#define STACK_SIZE (WG_SIZE*10)\n"
+"//#define STACK_SIZE (WG_SIZE)\n"
+"#define RING_SIZE 1024\n"
+"#define RING_SIZE_MASK (RING_SIZE-1)\n"
+"#define CHECK_SIZE (WG_SIZE)\n"
+"#define GET_RING_CAPACITY (RING_SIZE - ldsRingEnd)\n"
+"#define RING_END ldsTmp\n"
+"u32 readBuf(__local u32* buff, int idx)\n"
+"{\n"
+" idx = idx % (32*CHECK_SIZE);\n"
+" int bitIdx = idx%32;\n"
+" int bufIdx = idx/32;\n"
+" return buff[bufIdx] & (1<<bitIdx);\n"
+"}\n"
+"void writeBuf(__local u32* buff, int idx)\n"
+"{\n"
+" idx = idx % (32*CHECK_SIZE);\n"
+" int bitIdx = idx%32;\n"
+" int bufIdx = idx/32;\n"
+"// buff[bufIdx] |= (1<<bitIdx);\n"
+" atom_or( &buff[bufIdx], (1<<bitIdx) );\n"
+"}\n"
+"u32 tryWrite(__local u32* buff, int idx)\n"
+"{\n"
+" idx = idx % (32*CHECK_SIZE);\n"
+" int bitIdx = idx%32;\n"
+" int bufIdx = idx/32;\n"
+" u32 ans = (u32)atom_or( &buff[bufIdx], (1<<bitIdx) );\n"
+" return ((ans >> bitIdx)&1) == 0;\n"
+"}\n"
+"// batching on the GPU\n"
+"__kernel void CreateBatches( __global const struct b3Contact4Data* gConstraints, __global struct b3Contact4Data* gConstraintsOut,\n"
+" __global const u32* gN, __global const u32* gStart, __global int* batchSizes, \n"
+" int m_staticIdx )\n"
+"{\n"
+" __local u32 ldsStackIdx[STACK_SIZE];\n"
+" __local u32 ldsStackEnd;\n"
+" __local Elem ldsRingElem[RING_SIZE];\n"
+" __local u32 ldsRingEnd;\n"
+" __local u32 ldsTmp;\n"
+" __local u32 ldsCheckBuffer[CHECK_SIZE];\n"
+" __local u32 ldsFixedBuffer[CHECK_SIZE];\n"
+" __local u32 ldsGEnd;\n"
+" __local u32 ldsDstEnd;\n"
+" int wgIdx = GET_GROUP_IDX;\n"
+" int lIdx = GET_LOCAL_IDX;\n"
+" \n"
+" const int m_n = gN[wgIdx];\n"
+" const int m_start = gStart[wgIdx];\n"
+" \n"
+" if( lIdx == 0 )\n"
+" {\n"
+" ldsRingEnd = 0;\n"
+" ldsGEnd = 0;\n"
+" ldsStackEnd = 0;\n"
+" ldsDstEnd = m_start;\n"
+" }\n"
+" \n"
+" \n"
+" \n"
+"// while(1)\n"
+"//was 250\n"
+" int ie=0;\n"
+" int maxBatch = 0;\n"
+" for(ie=0; ie<50; ie++)\n"
+" {\n"
+" ldsFixedBuffer[lIdx] = 0;\n"
+" for(int giter=0; giter<4; giter++)\n"
+" {\n"
+" int ringCap = GET_RING_CAPACITY;\n"
+" \n"
+" // 1. fill ring\n"
+" if( ldsGEnd < m_n )\n"
+" {\n"
+" while( ringCap > WG_SIZE )\n"
+" {\n"
+" if( ldsGEnd >= m_n ) break;\n"
+" if( lIdx < ringCap - WG_SIZE )\n"
+" {\n"
+" int srcIdx;\n"
+" AtomInc1( ldsGEnd, srcIdx );\n"
+" if( srcIdx < m_n )\n"
+" {\n"
+" int dstIdx;\n"
+" AtomInc1( ldsRingEnd, dstIdx );\n"
+" \n"
+" int a = gConstraints[m_start+srcIdx].m_bodyAPtrAndSignBit;\n"
+" int b = gConstraints[m_start+srcIdx].m_bodyBPtrAndSignBit;\n"
+" ldsRingElem[dstIdx].m_a = (a>b)? b:a;\n"
+" ldsRingElem[dstIdx].m_b = (a>b)? a:b;\n"
+" ldsRingElem[dstIdx].m_idx = srcIdx;\n"
+" }\n"
+" }\n"
+" ringCap = GET_RING_CAPACITY;\n"
+" }\n"
+" }\n"
+" GROUP_LDS_BARRIER;\n"
+" \n"
+" // 2. fill stack\n"
+" __local Elem* dst = ldsRingElem;\n"
+" if( lIdx == 0 ) RING_END = 0;\n"
+" int srcIdx=lIdx;\n"
+" int end = ldsRingEnd;\n"
+" {\n"
+" for(int ii=0; ii<end; ii+=WG_SIZE, srcIdx+=WG_SIZE)\n"
+" {\n"
+" Elem e;\n"
+" if(srcIdx<end) e = ldsRingElem[srcIdx];\n"
+" bool done = (srcIdx<end)?false:true;\n"
+" for(int i=lIdx; i<CHECK_SIZE; i+=WG_SIZE) ldsCheckBuffer[lIdx] = 0;\n"
+" \n"
+" if( !done )\n"
+" {\n"
+" int aUsed = readBuf( ldsFixedBuffer, abs(e.m_a));\n"
+" int bUsed = readBuf( ldsFixedBuffer, abs(e.m_b));\n"
+" if( aUsed==0 && bUsed==0 )\n"
+" {\n"
+" int aAvailable=1;\n"
+" int bAvailable=1;\n"
+" int ea = abs(e.m_a);\n"
+" int eb = abs(e.m_b);\n"
+" bool aStatic = (e.m_a<0) ||(ea==m_staticIdx);\n"
+" bool bStatic = (e.m_b<0) ||(eb==m_staticIdx);\n"
+" \n"
+" if (!aStatic)\n"
+" aAvailable = tryWrite( ldsCheckBuffer, ea );\n"
+" if (!bStatic)\n"
+" bAvailable = tryWrite( ldsCheckBuffer, eb );\n"
+" \n"
+" //aAvailable = aStatic? 1: aAvailable;\n"
+" //bAvailable = bStatic? 1: bAvailable;\n"
+" bool success = (aAvailable && bAvailable);\n"
+" if(success)\n"
+" {\n"
+" \n"
+" if (!aStatic)\n"
+" writeBuf( ldsFixedBuffer, ea );\n"
+" if (!bStatic)\n"
+" writeBuf( ldsFixedBuffer, eb );\n"
+" }\n"
+" done = success;\n"
+" }\n"
+" }\n"
+" // put it aside\n"
+" if(srcIdx<end)\n"
+" {\n"
+" if( done )\n"
+" {\n"
+" int dstIdx; AtomInc1( ldsStackEnd, dstIdx );\n"
+" if( dstIdx < STACK_SIZE )\n"
+" ldsStackIdx[dstIdx] = e.m_idx;\n"
+" else{\n"
+" done = false;\n"
+" AtomAdd( ldsStackEnd, -1 );\n"
+" }\n"
+" }\n"
+" if( !done )\n"
+" {\n"
+" int dstIdx; AtomInc1( RING_END, dstIdx );\n"
+" dst[dstIdx] = e;\n"
+" }\n"
+" }\n"
+" // if filled, flush\n"
+" if( ldsStackEnd == STACK_SIZE )\n"
+" {\n"
+" for(int i=lIdx; i<STACK_SIZE; i+=WG_SIZE)\n"
+" {\n"
+" int idx = m_start + ldsStackIdx[i];\n"
+" int dstIdx; AtomInc1( ldsDstEnd, dstIdx );\n"
+" gConstraintsOut[ dstIdx ] = gConstraints[ idx ];\n"
+" gConstraintsOut[ dstIdx ].m_batchIdx = ie;\n"
+" }\n"
+" if( lIdx == 0 ) ldsStackEnd = 0;\n"
+" //for(int i=lIdx; i<CHECK_SIZE; i+=WG_SIZE) \n"
+" ldsFixedBuffer[lIdx] = 0;\n"
+" }\n"
+" }\n"
+" }\n"
+" if( lIdx == 0 ) ldsRingEnd = RING_END;\n"
+" }\n"
+" GROUP_LDS_BARRIER;\n"
+" for(int i=lIdx; i<ldsStackEnd; i+=WG_SIZE)\n"
+" {\n"
+" int idx = m_start + ldsStackIdx[i];\n"
+" int dstIdx; AtomInc1( ldsDstEnd, dstIdx );\n"
+" gConstraintsOut[ dstIdx ] = gConstraints[ idx ];\n"
+" gConstraintsOut[ dstIdx ].m_batchIdx = ie;\n"
+" }\n"
+" // in case it couldn't consume any pair. Flush them\n"
+" // todo. Serial batch worth while?\n"
+" if( ldsStackEnd == 0 )\n"
+" {\n"
+" for(int i=lIdx; i<ldsRingEnd; i+=WG_SIZE)\n"
+" {\n"
+" int idx = m_start + ldsRingElem[i].m_idx;\n"
+" int dstIdx; AtomInc1( ldsDstEnd, dstIdx );\n"
+" gConstraintsOut[ dstIdx ] = gConstraints[ idx ];\n"
+" int curBatch = 100+i;\n"
+" if (maxBatch < curBatch)\n"
+" maxBatch = curBatch;\n"
+" \n"
+" gConstraintsOut[ dstIdx ].m_batchIdx = curBatch;\n"
+" \n"
+" }\n"
+" GROUP_LDS_BARRIER;\n"
+" if( lIdx == 0 ) ldsRingEnd = 0;\n"
+" }\n"
+" if( lIdx == 0 ) ldsStackEnd = 0;\n"
+" GROUP_LDS_BARRIER;\n"
+" // termination\n"
+" if( ldsGEnd == m_n && ldsRingEnd == 0 )\n"
+" break;\n"
+" }\n"
+" if( lIdx == 0 )\n"
+" {\n"
+" if (maxBatch < ie)\n"
+" maxBatch=ie;\n"
+" batchSizes[wgIdx]=maxBatch;\n"
+" }\n"
+"}\n"
+;
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/batchingKernelsNew.cl b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/batchingKernelsNew.cl
new file mode 100644
index 0000000000..ba1b66d2c3
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/batchingKernelsNew.cl
@@ -0,0 +1,231 @@
+/*
+Copyright (c) 2012 Advanced Micro Devices, Inc.
+
+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.
+*/
+//Originally written by Erwin Coumans
+
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h"
+
+#pragma OPENCL EXTENSION cl_amd_printf : enable
+#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable
+
+#ifdef cl_ext_atomic_counters_32
+#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable
+#else
+#define counter32_t volatile __global int*
+#endif
+
+#define SIMD_WIDTH 64
+
+typedef unsigned int u32;
+typedef unsigned short u16;
+typedef unsigned char u8;
+
+#define GET_GROUP_IDX get_group_id(0)
+#define GET_LOCAL_IDX get_local_id(0)
+#define GET_GLOBAL_IDX get_global_id(0)
+#define GET_GROUP_SIZE get_local_size(0)
+#define GET_NUM_GROUPS get_num_groups(0)
+#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)
+#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)
+#define AtomInc(x) atom_inc(&(x))
+#define AtomInc1(x, out) out = atom_inc(&(x))
+#define AppendInc(x, out) out = atomic_inc(x)
+#define AtomAdd(x, value) atom_add(&(x), value)
+#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )
+#define AtomXhg(x, value) atom_xchg ( &(x), value )
+
+
+#define SELECT_UINT4( b, a, condition ) select( b,a,condition )
+
+#define make_float4 (float4)
+#define make_float2 (float2)
+#define make_uint4 (uint4)
+#define make_int4 (int4)
+#define make_uint2 (uint2)
+#define make_int2 (int2)
+
+
+#define max2 max
+#define min2 min
+
+
+#define WG_SIZE 64
+
+
+
+
+
+typedef struct
+{
+ int m_n;
+ int m_start;
+ int m_staticIdx;
+ int m_paddings[1];
+} ConstBuffer;
+
+typedef struct
+{
+ int m_a;
+ int m_b;
+ u32 m_idx;
+}Elem;
+
+
+
+
+
+// batching on the GPU
+__kernel void CreateBatchesBruteForce( __global struct b3Contact4Data* gConstraints, __global const u32* gN, __global const u32* gStart, int m_staticIdx )
+{
+ int wgIdx = GET_GROUP_IDX;
+ int lIdx = GET_LOCAL_IDX;
+
+ const int m_n = gN[wgIdx];
+ const int m_start = gStart[wgIdx];
+
+ if( lIdx == 0 )
+ {
+ for (int i=0;i<m_n;i++)
+ {
+ int srcIdx = i+m_start;
+ int batchIndex = i;
+ gConstraints[ srcIdx ].m_batchIdx = batchIndex;
+ }
+ }
+}
+
+
+#define CHECK_SIZE (WG_SIZE)
+
+
+
+
+u32 readBuf(__local u32* buff, int idx)
+{
+ idx = idx % (32*CHECK_SIZE);
+ int bitIdx = idx%32;
+ int bufIdx = idx/32;
+ return buff[bufIdx] & (1<<bitIdx);
+}
+
+void writeBuf(__local u32* buff, int idx)
+{
+ idx = idx % (32*CHECK_SIZE);
+ int bitIdx = idx%32;
+ int bufIdx = idx/32;
+ buff[bufIdx] |= (1<<bitIdx);
+ //atom_or( &buff[bufIdx], (1<<bitIdx) );
+}
+
+u32 tryWrite(__local u32* buff, int idx)
+{
+ idx = idx % (32*CHECK_SIZE);
+ int bitIdx = idx%32;
+ int bufIdx = idx/32;
+ u32 ans = (u32)atom_or( &buff[bufIdx], (1<<bitIdx) );
+ return ((ans >> bitIdx)&1) == 0;
+}
+
+
+// batching on the GPU
+__kernel void CreateBatchesNew( __global struct b3Contact4Data* gConstraints, __global const u32* gN, __global const u32* gStart, __global int* batchSizes, int staticIdx )
+{
+ int wgIdx = GET_GROUP_IDX;
+ int lIdx = GET_LOCAL_IDX;
+ const int numConstraints = gN[wgIdx];
+ const int m_start = gStart[wgIdx];
+ b3Contact4Data_t tmp;
+
+ __local u32 ldsFixedBuffer[CHECK_SIZE];
+
+
+
+
+
+ if( lIdx == 0 )
+ {
+
+
+ __global struct b3Contact4Data* cs = &gConstraints[m_start];
+
+
+ int numValidConstraints = 0;
+ int batchIdx = 0;
+
+ while( numValidConstraints < numConstraints)
+ {
+ int nCurrentBatch = 0;
+ // clear flag
+
+ for(int i=0; i<CHECK_SIZE; i++)
+ ldsFixedBuffer[i] = 0;
+
+ for(int i=numValidConstraints; i<numConstraints; i++)
+ {
+
+ int bodyAS = cs[i].m_bodyAPtrAndSignBit;
+ int bodyBS = cs[i].m_bodyBPtrAndSignBit;
+ int bodyA = abs(bodyAS);
+ int bodyB = abs(bodyBS);
+ bool aIsStatic = (bodyAS<0) || bodyAS==staticIdx;
+ bool bIsStatic = (bodyBS<0) || bodyBS==staticIdx;
+ int aUnavailable = aIsStatic ? 0 : readBuf( ldsFixedBuffer, bodyA);
+ int bUnavailable = bIsStatic ? 0 : readBuf( ldsFixedBuffer, bodyB);
+
+ if( aUnavailable==0 && bUnavailable==0 ) // ok
+ {
+ if (!aIsStatic)
+ {
+ writeBuf( ldsFixedBuffer, bodyA );
+ }
+ if (!bIsStatic)
+ {
+ writeBuf( ldsFixedBuffer, bodyB );
+ }
+
+ cs[i].m_batchIdx = batchIdx;
+
+ if (i!=numValidConstraints)
+ {
+
+ tmp = cs[i];
+ cs[i] = cs[numValidConstraints];
+ cs[numValidConstraints] = tmp;
+
+
+ }
+
+ numValidConstraints++;
+
+ nCurrentBatch++;
+ if( nCurrentBatch == SIMD_WIDTH)
+ {
+ nCurrentBatch = 0;
+ for(int i=0; i<CHECK_SIZE; i++)
+ ldsFixedBuffer[i] = 0;
+
+ }
+ }
+ }//for
+ batchIdx ++;
+ }//while
+
+ batchSizes[wgIdx] = batchIdx;
+
+ }//if( lIdx == 0 )
+
+ //return batchIdx;
+}
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/batchingKernelsNew.h b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/batchingKernelsNew.h
new file mode 100644
index 0000000000..1e5957adae
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/batchingKernelsNew.h
@@ -0,0 +1,291 @@
+//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
+static const char* batchingKernelsNewCL= \
+"/*\n"
+"Copyright (c) 2012 Advanced Micro Devices, Inc. \n"
+"This software is provided 'as-is', without any express or implied warranty.\n"
+"In no event will the authors be held liable for any damages arising from the use of this software.\n"
+"Permission is granted to anyone to use this software for any purpose, \n"
+"including commercial applications, and to alter it and redistribute it freely, \n"
+"subject to the following restrictions:\n"
+"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.\n"
+"2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
+"3. This notice may not be removed or altered from any source distribution.\n"
+"*/\n"
+"//Originally written by Erwin Coumans\n"
+"#ifndef B3_CONTACT4DATA_H\n"
+"#define B3_CONTACT4DATA_H\n"
+"#ifndef B3_FLOAT4_H\n"
+"#define B3_FLOAT4_H\n"
+"#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+"#define B3_PLATFORM_DEFINITIONS_H\n"
+"struct MyTest\n"
+"{\n"
+" int bla;\n"
+"};\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
+"#define B3_LARGE_FLOAT 1e18f\n"
+"#define B3_INFINITY 1e18f\n"
+"#define b3Assert(a)\n"
+"#define b3ConstArray(a) __global const a*\n"
+"#define b3AtomicInc atomic_inc\n"
+"#define b3AtomicAdd atomic_add\n"
+"#define b3Fabs fabs\n"
+"#define b3Sqrt native_sqrt\n"
+"#define b3Sin native_sin\n"
+"#define b3Cos native_cos\n"
+"#define B3_STATIC\n"
+"#endif\n"
+"#endif\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+" typedef float4 b3Float4;\n"
+" #define b3Float4ConstArg const b3Float4\n"
+" #define b3MakeFloat4 (float4)\n"
+" float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+" {\n"
+" float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+" float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+" return dot(a1, b1);\n"
+" }\n"
+" b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+" {\n"
+" float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+" float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+" return cross(a1, b1);\n"
+" }\n"
+" #define b3MinFloat4 min\n"
+" #define b3MaxFloat4 max\n"
+" #define b3Normalized(a) normalize(a)\n"
+"#endif \n"
+" \n"
+"inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
+"{\n"
+" if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6) \n"
+" return false;\n"
+" return true;\n"
+"}\n"
+"inline int b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
+"{\n"
+" float maxDot = -B3_INFINITY;\n"
+" int i = 0;\n"
+" int ptIndex = -1;\n"
+" for( i = 0; i < vecLen; i++ )\n"
+" {\n"
+" float dot = b3Dot3F4(vecArray[i],vec);\n"
+" \n"
+" if( dot > maxDot )\n"
+" {\n"
+" maxDot = dot;\n"
+" ptIndex = i;\n"
+" }\n"
+" }\n"
+" b3Assert(ptIndex>=0);\n"
+" if (ptIndex<0)\n"
+" {\n"
+" ptIndex = 0;\n"
+" }\n"
+" *dotOut = maxDot;\n"
+" return ptIndex;\n"
+"}\n"
+"#endif //B3_FLOAT4_H\n"
+"typedef struct b3Contact4Data b3Contact4Data_t;\n"
+"struct b3Contact4Data\n"
+"{\n"
+" b3Float4 m_worldPosB[4];\n"
+"// b3Float4 m_localPosA[4];\n"
+"// b3Float4 m_localPosB[4];\n"
+" b3Float4 m_worldNormalOnB; // w: m_nPoints\n"
+" unsigned short m_restituitionCoeffCmp;\n"
+" unsigned short m_frictionCoeffCmp;\n"
+" int m_batchIdx;\n"
+" int m_bodyAPtrAndSignBit;//x:m_bodyAPtr, y:m_bodyBPtr\n"
+" int m_bodyBPtrAndSignBit;\n"
+" int m_childIndexA;\n"
+" int m_childIndexB;\n"
+" int m_unused1;\n"
+" int m_unused2;\n"
+"};\n"
+"inline int b3Contact4Data_getNumPoints(const struct b3Contact4Data* contact)\n"
+"{\n"
+" return (int)contact->m_worldNormalOnB.w;\n"
+"};\n"
+"inline void b3Contact4Data_setNumPoints(struct b3Contact4Data* contact, int numPoints)\n"
+"{\n"
+" contact->m_worldNormalOnB.w = (float)numPoints;\n"
+"};\n"
+"#endif //B3_CONTACT4DATA_H\n"
+"#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
+"#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
+"#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
+"#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n"
+"#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n"
+"#ifdef cl_ext_atomic_counters_32\n"
+"#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n"
+"#else\n"
+"#define counter32_t volatile __global int*\n"
+"#endif\n"
+"#define SIMD_WIDTH 64\n"
+"typedef unsigned int u32;\n"
+"typedef unsigned short u16;\n"
+"typedef unsigned char u8;\n"
+"#define GET_GROUP_IDX get_group_id(0)\n"
+"#define GET_LOCAL_IDX get_local_id(0)\n"
+"#define GET_GLOBAL_IDX get_global_id(0)\n"
+"#define GET_GROUP_SIZE get_local_size(0)\n"
+"#define GET_NUM_GROUPS get_num_groups(0)\n"
+"#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
+"#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
+"#define AtomInc(x) atom_inc(&(x))\n"
+"#define AtomInc1(x, out) out = atom_inc(&(x))\n"
+"#define AppendInc(x, out) out = atomic_inc(x)\n"
+"#define AtomAdd(x, value) atom_add(&(x), value)\n"
+"#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )\n"
+"#define AtomXhg(x, value) atom_xchg ( &(x), value )\n"
+"#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n"
+"#define make_float4 (float4)\n"
+"#define make_float2 (float2)\n"
+"#define make_uint4 (uint4)\n"
+"#define make_int4 (int4)\n"
+"#define make_uint2 (uint2)\n"
+"#define make_int2 (int2)\n"
+"#define max2 max\n"
+"#define min2 min\n"
+"#define WG_SIZE 64\n"
+"typedef struct \n"
+"{\n"
+" int m_n;\n"
+" int m_start;\n"
+" int m_staticIdx;\n"
+" int m_paddings[1];\n"
+"} ConstBuffer;\n"
+"typedef struct \n"
+"{\n"
+" int m_a;\n"
+" int m_b;\n"
+" u32 m_idx;\n"
+"}Elem;\n"
+"// batching on the GPU\n"
+"__kernel void CreateBatchesBruteForce( __global struct b3Contact4Data* gConstraints, __global const u32* gN, __global const u32* gStart, int m_staticIdx )\n"
+"{\n"
+" int wgIdx = GET_GROUP_IDX;\n"
+" int lIdx = GET_LOCAL_IDX;\n"
+" \n"
+" const int m_n = gN[wgIdx];\n"
+" const int m_start = gStart[wgIdx];\n"
+" \n"
+" if( lIdx == 0 )\n"
+" {\n"
+" for (int i=0;i<m_n;i++)\n"
+" {\n"
+" int srcIdx = i+m_start;\n"
+" int batchIndex = i;\n"
+" gConstraints[ srcIdx ].m_batchIdx = batchIndex; \n"
+" }\n"
+" }\n"
+"}\n"
+"#define CHECK_SIZE (WG_SIZE)\n"
+"u32 readBuf(__local u32* buff, int idx)\n"
+"{\n"
+" idx = idx % (32*CHECK_SIZE);\n"
+" int bitIdx = idx%32;\n"
+" int bufIdx = idx/32;\n"
+" return buff[bufIdx] & (1<<bitIdx);\n"
+"}\n"
+"void writeBuf(__local u32* buff, int idx)\n"
+"{\n"
+" idx = idx % (32*CHECK_SIZE);\n"
+" int bitIdx = idx%32;\n"
+" int bufIdx = idx/32;\n"
+" buff[bufIdx] |= (1<<bitIdx);\n"
+" //atom_or( &buff[bufIdx], (1<<bitIdx) );\n"
+"}\n"
+"u32 tryWrite(__local u32* buff, int idx)\n"
+"{\n"
+" idx = idx % (32*CHECK_SIZE);\n"
+" int bitIdx = idx%32;\n"
+" int bufIdx = idx/32;\n"
+" u32 ans = (u32)atom_or( &buff[bufIdx], (1<<bitIdx) );\n"
+" return ((ans >> bitIdx)&1) == 0;\n"
+"}\n"
+"// batching on the GPU\n"
+"__kernel void CreateBatchesNew( __global struct b3Contact4Data* gConstraints, __global const u32* gN, __global const u32* gStart, __global int* batchSizes, int staticIdx )\n"
+"{\n"
+" int wgIdx = GET_GROUP_IDX;\n"
+" int lIdx = GET_LOCAL_IDX;\n"
+" const int numConstraints = gN[wgIdx];\n"
+" const int m_start = gStart[wgIdx];\n"
+" b3Contact4Data_t tmp;\n"
+" \n"
+" __local u32 ldsFixedBuffer[CHECK_SIZE];\n"
+" \n"
+" \n"
+" \n"
+" \n"
+" \n"
+" if( lIdx == 0 )\n"
+" {\n"
+" \n"
+" \n"
+" __global struct b3Contact4Data* cs = &gConstraints[m_start]; \n"
+" \n"
+" \n"
+" int numValidConstraints = 0;\n"
+" int batchIdx = 0;\n"
+" while( numValidConstraints < numConstraints)\n"
+" {\n"
+" int nCurrentBatch = 0;\n"
+" // clear flag\n"
+" \n"
+" for(int i=0; i<CHECK_SIZE; i++) \n"
+" ldsFixedBuffer[i] = 0; \n"
+" for(int i=numValidConstraints; i<numConstraints; i++)\n"
+" {\n"
+" int bodyAS = cs[i].m_bodyAPtrAndSignBit;\n"
+" int bodyBS = cs[i].m_bodyBPtrAndSignBit;\n"
+" int bodyA = abs(bodyAS);\n"
+" int bodyB = abs(bodyBS);\n"
+" bool aIsStatic = (bodyAS<0) || bodyAS==staticIdx;\n"
+" bool bIsStatic = (bodyBS<0) || bodyBS==staticIdx;\n"
+" int aUnavailable = aIsStatic ? 0 : readBuf( ldsFixedBuffer, bodyA);\n"
+" int bUnavailable = bIsStatic ? 0 : readBuf( ldsFixedBuffer, bodyB);\n"
+" \n"
+" if( aUnavailable==0 && bUnavailable==0 ) // ok\n"
+" {\n"
+" if (!aIsStatic)\n"
+" {\n"
+" writeBuf( ldsFixedBuffer, bodyA );\n"
+" }\n"
+" if (!bIsStatic)\n"
+" {\n"
+" writeBuf( ldsFixedBuffer, bodyB );\n"
+" }\n"
+" cs[i].m_batchIdx = batchIdx;\n"
+" if (i!=numValidConstraints)\n"
+" {\n"
+" tmp = cs[i];\n"
+" cs[i] = cs[numValidConstraints];\n"
+" cs[numValidConstraints] = tmp;\n"
+" }\n"
+" numValidConstraints++;\n"
+" \n"
+" nCurrentBatch++;\n"
+" if( nCurrentBatch == SIMD_WIDTH)\n"
+" {\n"
+" nCurrentBatch = 0;\n"
+" for(int i=0; i<CHECK_SIZE; i++) \n"
+" ldsFixedBuffer[i] = 0;\n"
+" \n"
+" }\n"
+" }\n"
+" }//for\n"
+" batchIdx ++;\n"
+" }//while\n"
+" \n"
+" batchSizes[wgIdx] = batchIdx;\n"
+" }//if( lIdx == 0 )\n"
+" \n"
+" //return batchIdx;\n"
+"}\n"
+;
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/integrateKernel.cl b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/integrateKernel.cl
new file mode 100644
index 0000000000..e22bc9bc33
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/integrateKernel.cl
@@ -0,0 +1,32 @@
+/*
+Copyright (c) 2013 Advanced Micro Devices, Inc.
+
+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.
+*/
+//Originally written by Erwin Coumans
+
+
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
+
+#include "Bullet3Dynamics/shared/b3IntegrateTransforms.h"
+
+
+
+__kernel void
+ integrateTransformsKernel( __global b3RigidBodyData_t* bodies,const int numNodes, float timeStep, float angularDamping, float4 gravityAcceleration)
+{
+ int nodeID = get_global_id(0);
+
+ if( nodeID < numNodes)
+ {
+ integrateSingleTransform(bodies,nodeID, timeStep, angularDamping,gravityAcceleration);
+ }
+}
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/integrateKernel.h b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/integrateKernel.h
new file mode 100644
index 0000000000..a5a432947c
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/integrateKernel.h
@@ -0,0 +1,433 @@
+//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
+static const char* integrateKernelCL= \
+"/*\n"
+"Copyright (c) 2013 Advanced Micro Devices, Inc. \n"
+"This software is provided 'as-is', without any express or implied warranty.\n"
+"In no event will the authors be held liable for any damages arising from the use of this software.\n"
+"Permission is granted to anyone to use this software for any purpose, \n"
+"including commercial applications, and to alter it and redistribute it freely, \n"
+"subject to the following restrictions:\n"
+"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.\n"
+"2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
+"3. This notice may not be removed or altered from any source distribution.\n"
+"*/\n"
+"//Originally written by Erwin Coumans\n"
+"#ifndef B3_RIGIDBODY_DATA_H\n"
+"#define B3_RIGIDBODY_DATA_H\n"
+"#ifndef B3_FLOAT4_H\n"
+"#define B3_FLOAT4_H\n"
+"#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+"#define B3_PLATFORM_DEFINITIONS_H\n"
+"struct MyTest\n"
+"{\n"
+" int bla;\n"
+"};\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
+"#define B3_LARGE_FLOAT 1e18f\n"
+"#define B3_INFINITY 1e18f\n"
+"#define b3Assert(a)\n"
+"#define b3ConstArray(a) __global const a*\n"
+"#define b3AtomicInc atomic_inc\n"
+"#define b3AtomicAdd atomic_add\n"
+"#define b3Fabs fabs\n"
+"#define b3Sqrt native_sqrt\n"
+"#define b3Sin native_sin\n"
+"#define b3Cos native_cos\n"
+"#define B3_STATIC\n"
+"#endif\n"
+"#endif\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+" typedef float4 b3Float4;\n"
+" #define b3Float4ConstArg const b3Float4\n"
+" #define b3MakeFloat4 (float4)\n"
+" float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+" {\n"
+" float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+" float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+" return dot(a1, b1);\n"
+" }\n"
+" b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+" {\n"
+" float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+" float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+" return cross(a1, b1);\n"
+" }\n"
+" #define b3MinFloat4 min\n"
+" #define b3MaxFloat4 max\n"
+" #define b3Normalized(a) normalize(a)\n"
+"#endif \n"
+" \n"
+"inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
+"{\n"
+" if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6) \n"
+" return false;\n"
+" return true;\n"
+"}\n"
+"inline int b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
+"{\n"
+" float maxDot = -B3_INFINITY;\n"
+" int i = 0;\n"
+" int ptIndex = -1;\n"
+" for( i = 0; i < vecLen; i++ )\n"
+" {\n"
+" float dot = b3Dot3F4(vecArray[i],vec);\n"
+" \n"
+" if( dot > maxDot )\n"
+" {\n"
+" maxDot = dot;\n"
+" ptIndex = i;\n"
+" }\n"
+" }\n"
+" b3Assert(ptIndex>=0);\n"
+" if (ptIndex<0)\n"
+" {\n"
+" ptIndex = 0;\n"
+" }\n"
+" *dotOut = maxDot;\n"
+" return ptIndex;\n"
+"}\n"
+"#endif //B3_FLOAT4_H\n"
+"#ifndef B3_QUAT_H\n"
+"#define B3_QUAT_H\n"
+"#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"#endif\n"
+"#endif\n"
+"#ifndef B3_FLOAT4_H\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"#endif \n"
+"#endif //B3_FLOAT4_H\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+" typedef float4 b3Quat;\n"
+" #define b3QuatConstArg const b3Quat\n"
+" \n"
+" \n"
+"inline float4 b3FastNormalize4(float4 v)\n"
+"{\n"
+" v = (float4)(v.xyz,0.f);\n"
+" return fast_normalize(v);\n"
+"}\n"
+" \n"
+"inline b3Quat b3QuatMul(b3Quat a, b3Quat b);\n"
+"inline b3Quat b3QuatNormalized(b3QuatConstArg in);\n"
+"inline b3Quat b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec);\n"
+"inline b3Quat b3QuatInvert(b3QuatConstArg q);\n"
+"inline b3Quat b3QuatInverse(b3QuatConstArg q);\n"
+"inline b3Quat b3QuatMul(b3QuatConstArg a, b3QuatConstArg b)\n"
+"{\n"
+" b3Quat ans;\n"
+" ans = b3Cross3( a, b );\n"
+" ans += a.w*b+b.w*a;\n"
+"// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
+" ans.w = a.w*b.w - b3Dot3F4(a, b);\n"
+" return ans;\n"
+"}\n"
+"inline b3Quat b3QuatNormalized(b3QuatConstArg in)\n"
+"{\n"
+" b3Quat q;\n"
+" q=in;\n"
+" //return b3FastNormalize4(in);\n"
+" float len = native_sqrt(dot(q, q));\n"
+" if(len > 0.f)\n"
+" {\n"
+" q *= 1.f / len;\n"
+" }\n"
+" else\n"
+" {\n"
+" q.x = q.y = q.z = 0.f;\n"
+" q.w = 1.f;\n"
+" }\n"
+" return q;\n"
+"}\n"
+"inline float4 b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
+"{\n"
+" b3Quat qInv = b3QuatInvert( q );\n"
+" float4 vcpy = vec;\n"
+" vcpy.w = 0.f;\n"
+" float4 out = b3QuatMul(b3QuatMul(q,vcpy),qInv);\n"
+" return out;\n"
+"}\n"
+"inline b3Quat b3QuatInverse(b3QuatConstArg q)\n"
+"{\n"
+" return (b3Quat)(-q.xyz, q.w);\n"
+"}\n"
+"inline b3Quat b3QuatInvert(b3QuatConstArg q)\n"
+"{\n"
+" return (b3Quat)(-q.xyz, q.w);\n"
+"}\n"
+"inline float4 b3QuatInvRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
+"{\n"
+" return b3QuatRotate( b3QuatInvert( q ), vec );\n"
+"}\n"
+"inline b3Float4 b3TransformPoint(b3Float4ConstArg point, b3Float4ConstArg translation, b3QuatConstArg orientation)\n"
+"{\n"
+" return b3QuatRotate( orientation, point ) + (translation);\n"
+"}\n"
+" \n"
+"#endif \n"
+"#endif //B3_QUAT_H\n"
+"#ifndef B3_MAT3x3_H\n"
+"#define B3_MAT3x3_H\n"
+"#ifndef B3_QUAT_H\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"#endif \n"
+"#endif //B3_QUAT_H\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"typedef struct\n"
+"{\n"
+" b3Float4 m_row[3];\n"
+"}b3Mat3x3;\n"
+"#define b3Mat3x3ConstArg const b3Mat3x3\n"
+"#define b3GetRow(m,row) (m.m_row[row])\n"
+"inline b3Mat3x3 b3QuatGetRotationMatrix(b3Quat quat)\n"
+"{\n"
+" b3Float4 quat2 = (b3Float4)(quat.x*quat.x, quat.y*quat.y, quat.z*quat.z, 0.f);\n"
+" b3Mat3x3 out;\n"
+" out.m_row[0].x=1-2*quat2.y-2*quat2.z;\n"
+" out.m_row[0].y=2*quat.x*quat.y-2*quat.w*quat.z;\n"
+" out.m_row[0].z=2*quat.x*quat.z+2*quat.w*quat.y;\n"
+" out.m_row[0].w = 0.f;\n"
+" out.m_row[1].x=2*quat.x*quat.y+2*quat.w*quat.z;\n"
+" out.m_row[1].y=1-2*quat2.x-2*quat2.z;\n"
+" out.m_row[1].z=2*quat.y*quat.z-2*quat.w*quat.x;\n"
+" out.m_row[1].w = 0.f;\n"
+" out.m_row[2].x=2*quat.x*quat.z-2*quat.w*quat.y;\n"
+" out.m_row[2].y=2*quat.y*quat.z+2*quat.w*quat.x;\n"
+" out.m_row[2].z=1-2*quat2.x-2*quat2.y;\n"
+" out.m_row[2].w = 0.f;\n"
+" return out;\n"
+"}\n"
+"inline b3Mat3x3 b3AbsoluteMat3x3(b3Mat3x3ConstArg matIn)\n"
+"{\n"
+" b3Mat3x3 out;\n"
+" out.m_row[0] = fabs(matIn.m_row[0]);\n"
+" out.m_row[1] = fabs(matIn.m_row[1]);\n"
+" out.m_row[2] = fabs(matIn.m_row[2]);\n"
+" return out;\n"
+"}\n"
+"__inline\n"
+"b3Mat3x3 mtZero();\n"
+"__inline\n"
+"b3Mat3x3 mtIdentity();\n"
+"__inline\n"
+"b3Mat3x3 mtTranspose(b3Mat3x3 m);\n"
+"__inline\n"
+"b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b);\n"
+"__inline\n"
+"b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b);\n"
+"__inline\n"
+"b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b);\n"
+"__inline\n"
+"b3Mat3x3 mtZero()\n"
+"{\n"
+" b3Mat3x3 m;\n"
+" m.m_row[0] = (b3Float4)(0.f);\n"
+" m.m_row[1] = (b3Float4)(0.f);\n"
+" m.m_row[2] = (b3Float4)(0.f);\n"
+" return m;\n"
+"}\n"
+"__inline\n"
+"b3Mat3x3 mtIdentity()\n"
+"{\n"
+" b3Mat3x3 m;\n"
+" m.m_row[0] = (b3Float4)(1,0,0,0);\n"
+" m.m_row[1] = (b3Float4)(0,1,0,0);\n"
+" m.m_row[2] = (b3Float4)(0,0,1,0);\n"
+" return m;\n"
+"}\n"
+"__inline\n"
+"b3Mat3x3 mtTranspose(b3Mat3x3 m)\n"
+"{\n"
+" b3Mat3x3 out;\n"
+" out.m_row[0] = (b3Float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);\n"
+" out.m_row[1] = (b3Float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);\n"
+" out.m_row[2] = (b3Float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);\n"
+" return out;\n"
+"}\n"
+"__inline\n"
+"b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b)\n"
+"{\n"
+" b3Mat3x3 transB;\n"
+" transB = mtTranspose( b );\n"
+" b3Mat3x3 ans;\n"
+" // why this doesn't run when 0ing in the for{}\n"
+" a.m_row[0].w = 0.f;\n"
+" a.m_row[1].w = 0.f;\n"
+" a.m_row[2].w = 0.f;\n"
+" for(int i=0; i<3; i++)\n"
+" {\n"
+"// a.m_row[i].w = 0.f;\n"
+" ans.m_row[i].x = b3Dot3F4(a.m_row[i],transB.m_row[0]);\n"
+" ans.m_row[i].y = b3Dot3F4(a.m_row[i],transB.m_row[1]);\n"
+" ans.m_row[i].z = b3Dot3F4(a.m_row[i],transB.m_row[2]);\n"
+" ans.m_row[i].w = 0.f;\n"
+" }\n"
+" return ans;\n"
+"}\n"
+"__inline\n"
+"b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b)\n"
+"{\n"
+" b3Float4 ans;\n"
+" ans.x = b3Dot3F4( a.m_row[0], b );\n"
+" ans.y = b3Dot3F4( a.m_row[1], b );\n"
+" ans.z = b3Dot3F4( a.m_row[2], b );\n"
+" ans.w = 0.f;\n"
+" return ans;\n"
+"}\n"
+"__inline\n"
+"b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b)\n"
+"{\n"
+" b3Float4 colx = b3MakeFloat4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
+" b3Float4 coly = b3MakeFloat4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
+" b3Float4 colz = b3MakeFloat4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
+" b3Float4 ans;\n"
+" ans.x = b3Dot3F4( a, colx );\n"
+" ans.y = b3Dot3F4( a, coly );\n"
+" ans.z = b3Dot3F4( a, colz );\n"
+" return ans;\n"
+"}\n"
+"#endif\n"
+"#endif //B3_MAT3x3_H\n"
+"typedef struct b3RigidBodyData b3RigidBodyData_t;\n"
+"struct b3RigidBodyData\n"
+"{\n"
+" b3Float4 m_pos;\n"
+" b3Quat m_quat;\n"
+" b3Float4 m_linVel;\n"
+" b3Float4 m_angVel;\n"
+" int m_collidableIdx;\n"
+" float m_invMass;\n"
+" float m_restituitionCoeff;\n"
+" float m_frictionCoeff;\n"
+"};\n"
+"typedef struct b3InertiaData b3InertiaData_t;\n"
+"struct b3InertiaData\n"
+"{\n"
+" b3Mat3x3 m_invInertiaWorld;\n"
+" b3Mat3x3 m_initInvInertia;\n"
+"};\n"
+"#endif //B3_RIGIDBODY_DATA_H\n"
+" \n"
+"#ifndef B3_RIGIDBODY_DATA_H\n"
+"#endif //B3_RIGIDBODY_DATA_H\n"
+" \n"
+"inline void integrateSingleTransform( __global b3RigidBodyData_t* bodies,int nodeID, float timeStep, float angularDamping, b3Float4ConstArg gravityAcceleration)\n"
+"{\n"
+" \n"
+" if (bodies[nodeID].m_invMass != 0.f)\n"
+" {\n"
+" float BT_GPU_ANGULAR_MOTION_THRESHOLD = (0.25f * 3.14159254f);\n"
+" //angular velocity\n"
+" {\n"
+" b3Float4 axis;\n"
+" //add some hardcoded angular damping\n"
+" bodies[nodeID].m_angVel.x *= angularDamping;\n"
+" bodies[nodeID].m_angVel.y *= angularDamping;\n"
+" bodies[nodeID].m_angVel.z *= angularDamping;\n"
+" \n"
+" b3Float4 angvel = bodies[nodeID].m_angVel;\n"
+" float fAngle = b3Sqrt(b3Dot3F4(angvel, angvel));\n"
+" \n"
+" //limit the angular motion\n"
+" if(fAngle*timeStep > BT_GPU_ANGULAR_MOTION_THRESHOLD)\n"
+" {\n"
+" fAngle = BT_GPU_ANGULAR_MOTION_THRESHOLD / timeStep;\n"
+" }\n"
+" if(fAngle < 0.001f)\n"
+" {\n"
+" // use Taylor's expansions of sync function\n"
+" axis = angvel * (0.5f*timeStep-(timeStep*timeStep*timeStep)*0.020833333333f * fAngle * fAngle);\n"
+" }\n"
+" else\n"
+" {\n"
+" // sync(fAngle) = sin(c*fAngle)/t\n"
+" axis = angvel * ( b3Sin(0.5f * fAngle * timeStep) / fAngle);\n"
+" }\n"
+" \n"
+" b3Quat dorn;\n"
+" dorn.x = axis.x;\n"
+" dorn.y = axis.y;\n"
+" dorn.z = axis.z;\n"
+" dorn.w = b3Cos(fAngle * timeStep * 0.5f);\n"
+" b3Quat orn0 = bodies[nodeID].m_quat;\n"
+" b3Quat predictedOrn = b3QuatMul(dorn, orn0);\n"
+" predictedOrn = b3QuatNormalized(predictedOrn);\n"
+" bodies[nodeID].m_quat=predictedOrn;\n"
+" }\n"
+" //linear velocity \n"
+" bodies[nodeID].m_pos += bodies[nodeID].m_linVel * timeStep;\n"
+" \n"
+" //apply gravity\n"
+" bodies[nodeID].m_linVel += gravityAcceleration * timeStep;\n"
+" \n"
+" }\n"
+" \n"
+"}\n"
+"inline void b3IntegrateTransform( __global b3RigidBodyData_t* body, float timeStep, float angularDamping, b3Float4ConstArg gravityAcceleration)\n"
+"{\n"
+" float BT_GPU_ANGULAR_MOTION_THRESHOLD = (0.25f * 3.14159254f);\n"
+" \n"
+" if( (body->m_invMass != 0.f))\n"
+" {\n"
+" //angular velocity\n"
+" {\n"
+" b3Float4 axis;\n"
+" //add some hardcoded angular damping\n"
+" body->m_angVel.x *= angularDamping;\n"
+" body->m_angVel.y *= angularDamping;\n"
+" body->m_angVel.z *= angularDamping;\n"
+" \n"
+" b3Float4 angvel = body->m_angVel;\n"
+" float fAngle = b3Sqrt(b3Dot3F4(angvel, angvel));\n"
+" //limit the angular motion\n"
+" if(fAngle*timeStep > BT_GPU_ANGULAR_MOTION_THRESHOLD)\n"
+" {\n"
+" fAngle = BT_GPU_ANGULAR_MOTION_THRESHOLD / timeStep;\n"
+" }\n"
+" if(fAngle < 0.001f)\n"
+" {\n"
+" // use Taylor's expansions of sync function\n"
+" axis = angvel * (0.5f*timeStep-(timeStep*timeStep*timeStep)*0.020833333333f * fAngle * fAngle);\n"
+" }\n"
+" else\n"
+" {\n"
+" // sync(fAngle) = sin(c*fAngle)/t\n"
+" axis = angvel * ( b3Sin(0.5f * fAngle * timeStep) / fAngle);\n"
+" }\n"
+" b3Quat dorn;\n"
+" dorn.x = axis.x;\n"
+" dorn.y = axis.y;\n"
+" dorn.z = axis.z;\n"
+" dorn.w = b3Cos(fAngle * timeStep * 0.5f);\n"
+" b3Quat orn0 = body->m_quat;\n"
+" b3Quat predictedOrn = b3QuatMul(dorn, orn0);\n"
+" predictedOrn = b3QuatNormalized(predictedOrn);\n"
+" body->m_quat=predictedOrn;\n"
+" }\n"
+" //apply gravity\n"
+" body->m_linVel += gravityAcceleration * timeStep;\n"
+" //linear velocity \n"
+" body->m_pos += body->m_linVel * timeStep;\n"
+" \n"
+" }\n"
+" \n"
+"}\n"
+"__kernel void \n"
+" integrateTransformsKernel( __global b3RigidBodyData_t* bodies,const int numNodes, float timeStep, float angularDamping, float4 gravityAcceleration)\n"
+"{\n"
+" int nodeID = get_global_id(0);\n"
+" \n"
+" if( nodeID < numNodes)\n"
+" {\n"
+" integrateSingleTransform(bodies,nodeID, timeStep, angularDamping,gravityAcceleration);\n"
+" }\n"
+"}\n"
+;
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/jointSolver.cl b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/jointSolver.cl
new file mode 100644
index 0000000000..7f5dabe274
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/jointSolver.cl
@@ -0,0 +1,877 @@
+/*
+Copyright (c) 2013 Advanced Micro Devices, Inc.
+
+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.
+*/
+//Originally written by Erwin Coumans
+
+#define B3_CONSTRAINT_FLAG_ENABLED 1
+
+#define B3_GPU_POINT2POINT_CONSTRAINT_TYPE 3
+#define B3_GPU_FIXED_CONSTRAINT_TYPE 4
+
+#define MOTIONCLAMP 100000 //unused, for debugging/safety in case constraint solver fails
+#define B3_INFINITY 1e30f
+
+#define mymake_float4 (float4)
+
+
+__inline float dot3F4(float4 a, float4 b)
+{
+ float4 a1 = mymake_float4(a.xyz,0.f);
+ float4 b1 = mymake_float4(b.xyz,0.f);
+ return dot(a1, b1);
+}
+
+
+typedef float4 Quaternion;
+
+
+typedef struct
+{
+ float4 m_row[3];
+}Matrix3x3;
+
+__inline
+float4 mtMul1(Matrix3x3 a, float4 b);
+
+__inline
+float4 mtMul3(float4 a, Matrix3x3 b);
+
+
+
+
+
+__inline
+float4 mtMul1(Matrix3x3 a, float4 b)
+{
+ float4 ans;
+ ans.x = dot3F4( a.m_row[0], b );
+ ans.y = dot3F4( a.m_row[1], b );
+ ans.z = dot3F4( a.m_row[2], b );
+ ans.w = 0.f;
+ return ans;
+}
+
+__inline
+float4 mtMul3(float4 a, Matrix3x3 b)
+{
+ float4 colx = mymake_float4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);
+ float4 coly = mymake_float4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);
+ float4 colz = mymake_float4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);
+
+ float4 ans;
+ ans.x = dot3F4( a, colx );
+ ans.y = dot3F4( a, coly );
+ ans.z = dot3F4( a, colz );
+ return ans;
+}
+
+
+
+typedef struct
+{
+ Matrix3x3 m_invInertiaWorld;
+ Matrix3x3 m_initInvInertia;
+} BodyInertia;
+
+
+typedef struct
+{
+ Matrix3x3 m_basis;//orientation
+ float4 m_origin;//transform
+}b3Transform;
+
+typedef struct
+{
+// b3Transform m_worldTransformUnused;
+ float4 m_deltaLinearVelocity;
+ float4 m_deltaAngularVelocity;
+ float4 m_angularFactor;
+ float4 m_linearFactor;
+ float4 m_invMass;
+ float4 m_pushVelocity;
+ float4 m_turnVelocity;
+ float4 m_linearVelocity;
+ float4 m_angularVelocity;
+
+ union
+ {
+ void* m_originalBody;
+ int m_originalBodyIndex;
+ };
+ int padding[3];
+
+} b3GpuSolverBody;
+
+typedef struct
+{
+ float4 m_pos;
+ Quaternion m_quat;
+ float4 m_linVel;
+ float4 m_angVel;
+
+ unsigned int m_shapeIdx;
+ float m_invMass;
+ float m_restituitionCoeff;
+ float m_frictionCoeff;
+} b3RigidBodyCL;
+
+typedef struct
+{
+
+ float4 m_relpos1CrossNormal;
+ float4 m_contactNormal;
+
+ float4 m_relpos2CrossNormal;
+ //float4 m_contactNormal2;//usually m_contactNormal2 == -m_contactNormal
+
+ float4 m_angularComponentA;
+ float4 m_angularComponentB;
+
+ float m_appliedPushImpulse;
+ float m_appliedImpulse;
+ int m_padding1;
+ int m_padding2;
+ float m_friction;
+ float m_jacDiagABInv;
+ float m_rhs;
+ float m_cfm;
+
+ float m_lowerLimit;
+ float m_upperLimit;
+ float m_rhsPenetration;
+ int m_originalConstraint;
+
+
+ int m_overrideNumSolverIterations;
+ int m_frictionIndex;
+ int m_solverBodyIdA;
+ int m_solverBodyIdB;
+
+} b3SolverConstraint;
+
+typedef struct
+{
+ int m_bodyAPtrAndSignBit;
+ int m_bodyBPtrAndSignBit;
+ int m_originalConstraintIndex;
+ int m_batchId;
+} b3BatchConstraint;
+
+
+
+
+
+
+typedef struct
+{
+ int m_constraintType;
+ int m_rbA;
+ int m_rbB;
+ float m_breakingImpulseThreshold;
+
+ float4 m_pivotInA;
+ float4 m_pivotInB;
+ Quaternion m_relTargetAB;
+
+ int m_flags;
+ int m_padding[3];
+} b3GpuGenericConstraint;
+
+
+/*b3Transform getWorldTransform(b3RigidBodyCL* rb)
+{
+ b3Transform newTrans;
+ newTrans.setOrigin(rb->m_pos);
+ newTrans.setRotation(rb->m_quat);
+ return newTrans;
+}*/
+
+
+
+
+__inline
+float4 cross3(float4 a, float4 b)
+{
+ return cross(a,b);
+}
+
+__inline
+float4 fastNormalize4(float4 v)
+{
+ v = mymake_float4(v.xyz,0.f);
+ return fast_normalize(v);
+}
+
+
+__inline
+Quaternion qtMul(Quaternion a, Quaternion b);
+
+__inline
+Quaternion qtNormalize(Quaternion in);
+
+__inline
+float4 qtRotate(Quaternion q, float4 vec);
+
+__inline
+Quaternion qtInvert(Quaternion q);
+
+
+
+
+__inline
+Quaternion qtMul(Quaternion a, Quaternion b)
+{
+ Quaternion ans;
+ ans = cross3( a, b );
+ ans += a.w*b+b.w*a;
+// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);
+ ans.w = a.w*b.w - dot3F4(a, b);
+ return ans;
+}
+
+__inline
+Quaternion qtNormalize(Quaternion in)
+{
+ return fastNormalize4(in);
+// in /= length( in );
+// return in;
+}
+__inline
+float4 qtRotate(Quaternion q, float4 vec)
+{
+ Quaternion qInv = qtInvert( q );
+ float4 vcpy = vec;
+ vcpy.w = 0.f;
+ float4 out = qtMul(qtMul(q,vcpy),qInv);
+ return out;
+}
+
+__inline
+Quaternion qtInvert(Quaternion q)
+{
+ return (Quaternion)(-q.xyz, q.w);
+}
+
+
+__inline void internalApplyImpulse(__global b3GpuSolverBody* body, float4 linearComponent, float4 angularComponent,float impulseMagnitude)
+{
+ body->m_deltaLinearVelocity += linearComponent*impulseMagnitude*body->m_linearFactor;
+ body->m_deltaAngularVelocity += angularComponent*(impulseMagnitude*body->m_angularFactor);
+}
+
+
+void resolveSingleConstraintRowGeneric(__global b3GpuSolverBody* body1, __global b3GpuSolverBody* body2, __global b3SolverConstraint* c)
+{
+ float deltaImpulse = c->m_rhs-c->m_appliedImpulse*c->m_cfm;
+ float deltaVel1Dotn = dot3F4(c->m_contactNormal,body1->m_deltaLinearVelocity) + dot3F4(c->m_relpos1CrossNormal,body1->m_deltaAngularVelocity);
+ float deltaVel2Dotn = -dot3F4(c->m_contactNormal,body2->m_deltaLinearVelocity) + dot3F4(c->m_relpos2CrossNormal,body2->m_deltaAngularVelocity);
+
+ deltaImpulse -= deltaVel1Dotn*c->m_jacDiagABInv;
+ deltaImpulse -= deltaVel2Dotn*c->m_jacDiagABInv;
+
+ float sum = c->m_appliedImpulse + deltaImpulse;
+ if (sum < c->m_lowerLimit)
+ {
+ deltaImpulse = c->m_lowerLimit-c->m_appliedImpulse;
+ c->m_appliedImpulse = c->m_lowerLimit;
+ }
+ else if (sum > c->m_upperLimit)
+ {
+ deltaImpulse = c->m_upperLimit-c->m_appliedImpulse;
+ c->m_appliedImpulse = c->m_upperLimit;
+ }
+ else
+ {
+ c->m_appliedImpulse = sum;
+ }
+
+ internalApplyImpulse(body1,c->m_contactNormal*body1->m_invMass,c->m_angularComponentA,deltaImpulse);
+ internalApplyImpulse(body2,-c->m_contactNormal*body2->m_invMass,c->m_angularComponentB,deltaImpulse);
+
+}
+
+__kernel void solveJointConstraintRows(__global b3GpuSolverBody* solverBodies,
+ __global b3BatchConstraint* batchConstraints,
+ __global b3SolverConstraint* rows,
+ __global unsigned int* numConstraintRowsInfo1,
+ __global unsigned int* rowOffsets,
+ __global b3GpuGenericConstraint* constraints,
+ int batchOffset,
+ int numConstraintsInBatch
+ )
+{
+ int b = get_global_id(0);
+ if (b>=numConstraintsInBatch)
+ return;
+
+ __global b3BatchConstraint* c = &batchConstraints[b+batchOffset];
+ int originalConstraintIndex = c->m_originalConstraintIndex;
+ if (constraints[originalConstraintIndex].m_flags&B3_CONSTRAINT_FLAG_ENABLED)
+ {
+ int numConstraintRows = numConstraintRowsInfo1[originalConstraintIndex];
+ int rowOffset = rowOffsets[originalConstraintIndex];
+ for (int jj=0;jj<numConstraintRows;jj++)
+ {
+ __global b3SolverConstraint* constraint = &rows[rowOffset+jj];
+ resolveSingleConstraintRowGeneric(&solverBodies[constraint->m_solverBodyIdA],&solverBodies[constraint->m_solverBodyIdB],constraint);
+ }
+ }
+};
+
+__kernel void initSolverBodies(__global b3GpuSolverBody* solverBodies,__global b3RigidBodyCL* bodiesCL, int numBodies)
+{
+ int i = get_global_id(0);
+ if (i>=numBodies)
+ return;
+
+ __global b3GpuSolverBody* solverBody = &solverBodies[i];
+ __global b3RigidBodyCL* bodyCL = &bodiesCL[i];
+
+ solverBody->m_deltaLinearVelocity = (float4)(0.f,0.f,0.f,0.f);
+ solverBody->m_deltaAngularVelocity = (float4)(0.f,0.f,0.f,0.f);
+ solverBody->m_pushVelocity = (float4)(0.f,0.f,0.f,0.f);
+ solverBody->m_pushVelocity = (float4)(0.f,0.f,0.f,0.f);
+ solverBody->m_invMass = (float4)(bodyCL->m_invMass,bodyCL->m_invMass,bodyCL->m_invMass,0.f);
+ solverBody->m_originalBodyIndex = i;
+ solverBody->m_angularFactor = (float4)(1,1,1,0);
+ solverBody->m_linearFactor = (float4) (1,1,1,0);
+ solverBody->m_linearVelocity = bodyCL->m_linVel;
+ solverBody->m_angularVelocity = bodyCL->m_angVel;
+}
+
+__kernel void breakViolatedConstraintsKernel(__global b3GpuGenericConstraint* constraints, __global unsigned int* numConstraintRows, __global unsigned int* rowOffsets, __global b3SolverConstraint* rows, int numConstraints)
+{
+ int cid = get_global_id(0);
+ if (cid>=numConstraints)
+ return;
+ int numRows = numConstraintRows[cid];
+ if (numRows)
+ {
+ for (int i=0;i<numRows;i++)
+ {
+ int rowIndex = rowOffsets[cid]+i;
+ float breakingThreshold = constraints[cid].m_breakingImpulseThreshold;
+ if (fabs(rows[rowIndex].m_appliedImpulse) >= breakingThreshold)
+ {
+ constraints[cid].m_flags =0;//&= ~B3_CONSTRAINT_FLAG_ENABLED;
+ }
+ }
+ }
+}
+
+
+
+__kernel void getInfo1Kernel(__global unsigned int* infos, __global b3GpuGenericConstraint* constraints, int numConstraints)
+{
+ int i = get_global_id(0);
+ if (i>=numConstraints)
+ return;
+
+ __global b3GpuGenericConstraint* constraint = &constraints[i];
+
+ switch (constraint->m_constraintType)
+ {
+ case B3_GPU_POINT2POINT_CONSTRAINT_TYPE:
+ {
+ infos[i] = 3;
+ break;
+ }
+ case B3_GPU_FIXED_CONSTRAINT_TYPE:
+ {
+ infos[i] = 6;
+ break;
+ }
+ default:
+ {
+ }
+ }
+}
+
+__kernel void initBatchConstraintsKernel(__global unsigned int* numConstraintRows, __global unsigned int* rowOffsets,
+ __global b3BatchConstraint* batchConstraints,
+ __global b3GpuGenericConstraint* constraints,
+ __global b3RigidBodyCL* bodies,
+ int numConstraints)
+{
+ int i = get_global_id(0);
+ if (i>=numConstraints)
+ return;
+
+ int rbA = constraints[i].m_rbA;
+ int rbB = constraints[i].m_rbB;
+
+ batchConstraints[i].m_bodyAPtrAndSignBit = bodies[rbA].m_invMass != 0.f ? rbA : -rbA;
+ batchConstraints[i].m_bodyBPtrAndSignBit = bodies[rbB].m_invMass != 0.f ? rbB : -rbB;
+ batchConstraints[i].m_batchId = -1;
+ batchConstraints[i].m_originalConstraintIndex = i;
+
+}
+
+
+
+
+typedef struct
+{
+ // integrator parameters: frames per second (1/stepsize), default error
+ // reduction parameter (0..1).
+ float fps,erp;
+
+ // for the first and second body, pointers to two (linear and angular)
+ // n*3 jacobian sub matrices, stored by rows. these matrices will have
+ // been initialized to 0 on entry. if the second body is zero then the
+ // J2xx pointers may be 0.
+ union
+ {
+ __global float4* m_J1linearAxisFloat4;
+ __global float* m_J1linearAxis;
+ };
+ union
+ {
+ __global float4* m_J1angularAxisFloat4;
+ __global float* m_J1angularAxis;
+
+ };
+ union
+ {
+ __global float4* m_J2linearAxisFloat4;
+ __global float* m_J2linearAxis;
+ };
+ union
+ {
+ __global float4* m_J2angularAxisFloat4;
+ __global float* m_J2angularAxis;
+ };
+ // elements to jump from one row to the next in J's
+ int rowskip;
+
+ // right hand sides of the equation J*v = c + cfm * lambda. cfm is the
+ // "constraint force mixing" vector. c is set to zero on entry, cfm is
+ // set to a constant value (typically very small or zero) value on entry.
+ __global float* m_constraintError;
+ __global float* cfm;
+
+ // lo and hi limits for variables (set to -/+ infinity on entry).
+ __global float* m_lowerLimit;
+ __global float* m_upperLimit;
+
+ // findex vector for variables. see the LCP solver interface for a
+ // description of what this does. this is set to -1 on entry.
+ // note that the returned indexes are relative to the first index of
+ // the constraint.
+ __global int *findex;
+ // number of solver iterations
+ int m_numIterations;
+
+ //damping of the velocity
+ float m_damping;
+} b3GpuConstraintInfo2;
+
+
+void getSkewSymmetricMatrix(float4 vecIn, __global float4* v0,__global float4* v1,__global float4* v2)
+{
+ *v0 = (float4)(0. ,-vecIn.z ,vecIn.y,0.f);
+ *v1 = (float4)(vecIn.z ,0. ,-vecIn.x,0.f);
+ *v2 = (float4)(-vecIn.y ,vecIn.x ,0.f,0.f);
+}
+
+
+void getInfo2Point2Point(__global b3GpuGenericConstraint* constraint,b3GpuConstraintInfo2* info,__global b3RigidBodyCL* bodies)
+{
+ float4 posA = bodies[constraint->m_rbA].m_pos;
+ Quaternion rotA = bodies[constraint->m_rbA].m_quat;
+
+ float4 posB = bodies[constraint->m_rbB].m_pos;
+ Quaternion rotB = bodies[constraint->m_rbB].m_quat;
+
+
+
+ // anchor points in global coordinates with respect to body PORs.
+
+ // set jacobian
+ info->m_J1linearAxis[0] = 1;
+ info->m_J1linearAxis[info->rowskip+1] = 1;
+ info->m_J1linearAxis[2*info->rowskip+2] = 1;
+
+ float4 a1 = qtRotate(rotA,constraint->m_pivotInA);
+
+ {
+ __global float4* angular0 = (__global float4*)(info->m_J1angularAxis);
+ __global float4* angular1 = (__global float4*)(info->m_J1angularAxis+info->rowskip);
+ __global float4* angular2 = (__global float4*)(info->m_J1angularAxis+2*info->rowskip);
+ float4 a1neg = -a1;
+ getSkewSymmetricMatrix(a1neg,angular0,angular1,angular2);
+ }
+ if (info->m_J2linearAxis)
+ {
+ info->m_J2linearAxis[0] = -1;
+ info->m_J2linearAxis[info->rowskip+1] = -1;
+ info->m_J2linearAxis[2*info->rowskip+2] = -1;
+ }
+
+ float4 a2 = qtRotate(rotB,constraint->m_pivotInB);
+
+ {
+ // float4 a2n = -a2;
+ __global float4* angular0 = (__global float4*)(info->m_J2angularAxis);
+ __global float4* angular1 = (__global float4*)(info->m_J2angularAxis+info->rowskip);
+ __global float4* angular2 = (__global float4*)(info->m_J2angularAxis+2*info->rowskip);
+ getSkewSymmetricMatrix(a2,angular0,angular1,angular2);
+ }
+
+ // set right hand side
+// float currERP = (m_flags & B3_P2P_FLAGS_ERP) ? m_erp : info->erp;
+ float currERP = info->erp;
+
+ float k = info->fps * currERP;
+ int j;
+ float4 result = a2 + posB - a1 - posA;
+ float* resultPtr = &result;
+
+ for (j=0; j<3; j++)
+ {
+ info->m_constraintError[j*info->rowskip] = k * (resultPtr[j]);
+ }
+}
+
+Quaternion nearest( Quaternion first, Quaternion qd)
+{
+ Quaternion diff,sum;
+ diff = first- qd;
+ sum = first + qd;
+
+ if( dot(diff,diff) < dot(sum,sum) )
+ return qd;
+ return (-qd);
+}
+
+float b3Acos(float x)
+{
+ if (x<-1)
+ x=-1;
+ if (x>1)
+ x=1;
+ return acos(x);
+}
+
+float getAngle(Quaternion orn)
+{
+ if (orn.w>=1.f)
+ orn.w=1.f;
+ float s = 2.f * b3Acos(orn.w);
+ return s;
+}
+
+void calculateDiffAxisAngleQuaternion( Quaternion orn0,Quaternion orn1a,float4* axis,float* angle)
+{
+ Quaternion orn1 = nearest(orn0,orn1a);
+
+ Quaternion dorn = qtMul(orn1,qtInvert(orn0));
+ *angle = getAngle(dorn);
+ *axis = (float4)(dorn.x,dorn.y,dorn.z,0.f);
+
+ //check for axis length
+ float len = dot3F4(*axis,*axis);
+ if (len < FLT_EPSILON*FLT_EPSILON)
+ *axis = (float4)(1,0,0,0);
+ else
+ *axis /= sqrt(len);
+}
+
+
+
+void getInfo2FixedOrientation(__global b3GpuGenericConstraint* constraint,b3GpuConstraintInfo2* info,__global b3RigidBodyCL* bodies, int start_row)
+{
+ Quaternion worldOrnA = bodies[constraint->m_rbA].m_quat;
+ Quaternion worldOrnB = bodies[constraint->m_rbB].m_quat;
+
+ int s = info->rowskip;
+ int start_index = start_row * s;
+
+ // 3 rows to make body rotations equal
+ info->m_J1angularAxis[start_index] = 1;
+ info->m_J1angularAxis[start_index + s + 1] = 1;
+ info->m_J1angularAxis[start_index + s*2+2] = 1;
+ if ( info->m_J2angularAxis)
+ {
+ info->m_J2angularAxis[start_index] = -1;
+ info->m_J2angularAxis[start_index + s+1] = -1;
+ info->m_J2angularAxis[start_index + s*2+2] = -1;
+ }
+
+ float currERP = info->erp;
+ float k = info->fps * currERP;
+ float4 diff;
+ float angle;
+ float4 qrelCur = qtMul(worldOrnA,qtInvert(worldOrnB));
+
+ calculateDiffAxisAngleQuaternion(constraint->m_relTargetAB,qrelCur,&diff,&angle);
+ diff*=-angle;
+
+ float* resultPtr = &diff;
+
+ for (int j=0; j<3; j++)
+ {
+ info->m_constraintError[(3+j)*info->rowskip] = k * resultPtr[j];
+ }
+
+
+}
+
+
+__kernel void writeBackVelocitiesKernel(__global b3RigidBodyCL* bodies,__global b3GpuSolverBody* solverBodies,int numBodies)
+{
+ int i = get_global_id(0);
+ if (i>=numBodies)
+ return;
+
+ if (bodies[i].m_invMass)
+ {
+// if (length(solverBodies[i].m_deltaLinearVelocity)<MOTIONCLAMP)
+ {
+ bodies[i].m_linVel += solverBodies[i].m_deltaLinearVelocity;
+ }
+// if (length(solverBodies[i].m_deltaAngularVelocity)<MOTIONCLAMP)
+ {
+ bodies[i].m_angVel += solverBodies[i].m_deltaAngularVelocity;
+ }
+ }
+}
+
+
+__kernel void getInfo2Kernel(__global b3SolverConstraint* solverConstraintRows,
+ __global unsigned int* infos,
+ __global unsigned int* constraintRowOffsets,
+ __global b3GpuGenericConstraint* constraints,
+ __global b3BatchConstraint* batchConstraints,
+ __global b3RigidBodyCL* bodies,
+ __global BodyInertia* inertias,
+ __global b3GpuSolverBody* solverBodies,
+ float timeStep,
+ float globalErp,
+ float globalCfm,
+ float globalDamping,
+ int globalNumIterations,
+ int numConstraints)
+{
+
+ int i = get_global_id(0);
+ if (i>=numConstraints)
+ return;
+
+ //for now, always initialize the batch info
+ int info1 = infos[i];
+
+ __global b3SolverConstraint* currentConstraintRow = &solverConstraintRows[constraintRowOffsets[i]];
+ __global b3GpuGenericConstraint* constraint = &constraints[i];
+
+ __global b3RigidBodyCL* rbA = &bodies[ constraint->m_rbA];
+ __global b3RigidBodyCL* rbB = &bodies[ constraint->m_rbB];
+
+ int solverBodyIdA = constraint->m_rbA;
+ int solverBodyIdB = constraint->m_rbB;
+
+ __global b3GpuSolverBody* bodyAPtr = &solverBodies[solverBodyIdA];
+ __global b3GpuSolverBody* bodyBPtr = &solverBodies[solverBodyIdB];
+
+
+ if (rbA->m_invMass)
+ {
+ batchConstraints[i].m_bodyAPtrAndSignBit = solverBodyIdA;
+ } else
+ {
+// if (!solverBodyIdA)
+// m_staticIdx = 0;
+ batchConstraints[i].m_bodyAPtrAndSignBit = -solverBodyIdA;
+ }
+
+ if (rbB->m_invMass)
+ {
+ batchConstraints[i].m_bodyBPtrAndSignBit = solverBodyIdB;
+ } else
+ {
+// if (!solverBodyIdB)
+// m_staticIdx = 0;
+ batchConstraints[i].m_bodyBPtrAndSignBit = -solverBodyIdB;
+ }
+
+ if (info1)
+ {
+ int overrideNumSolverIterations = 0;//constraint->getOverrideNumSolverIterations() > 0 ? constraint->getOverrideNumSolverIterations() : infoGlobal.m_numIterations;
+// if (overrideNumSolverIterations>m_maxOverrideNumSolverIterations)
+ // m_maxOverrideNumSolverIterations = overrideNumSolverIterations;
+
+
+ int j;
+ for ( j=0;j<info1;j++)
+ {
+// memset(&currentConstraintRow[j],0,sizeof(b3SolverConstraint));
+ currentConstraintRow[j].m_angularComponentA = (float4)(0,0,0,0);
+ currentConstraintRow[j].m_angularComponentB = (float4)(0,0,0,0);
+ currentConstraintRow[j].m_appliedImpulse = 0.f;
+ currentConstraintRow[j].m_appliedPushImpulse = 0.f;
+ currentConstraintRow[j].m_cfm = 0.f;
+ currentConstraintRow[j].m_contactNormal = (float4)(0,0,0,0);
+ currentConstraintRow[j].m_friction = 0.f;
+ currentConstraintRow[j].m_frictionIndex = 0;
+ currentConstraintRow[j].m_jacDiagABInv = 0.f;
+ currentConstraintRow[j].m_lowerLimit = 0.f;
+ currentConstraintRow[j].m_upperLimit = 0.f;
+
+ currentConstraintRow[j].m_originalConstraint = i;
+ currentConstraintRow[j].m_overrideNumSolverIterations = 0;
+ currentConstraintRow[j].m_relpos1CrossNormal = (float4)(0,0,0,0);
+ currentConstraintRow[j].m_relpos2CrossNormal = (float4)(0,0,0,0);
+ currentConstraintRow[j].m_rhs = 0.f;
+ currentConstraintRow[j].m_rhsPenetration = 0.f;
+ currentConstraintRow[j].m_solverBodyIdA = 0;
+ currentConstraintRow[j].m_solverBodyIdB = 0;
+
+ currentConstraintRow[j].m_lowerLimit = -B3_INFINITY;
+ currentConstraintRow[j].m_upperLimit = B3_INFINITY;
+ currentConstraintRow[j].m_appliedImpulse = 0.f;
+ currentConstraintRow[j].m_appliedPushImpulse = 0.f;
+ currentConstraintRow[j].m_solverBodyIdA = solverBodyIdA;
+ currentConstraintRow[j].m_solverBodyIdB = solverBodyIdB;
+ currentConstraintRow[j].m_overrideNumSolverIterations = overrideNumSolverIterations;
+ }
+
+ bodyAPtr->m_deltaLinearVelocity = (float4)(0,0,0,0);
+ bodyAPtr->m_deltaAngularVelocity = (float4)(0,0,0,0);
+ bodyAPtr->m_pushVelocity = (float4)(0,0,0,0);
+ bodyAPtr->m_turnVelocity = (float4)(0,0,0,0);
+ bodyBPtr->m_deltaLinearVelocity = (float4)(0,0,0,0);
+ bodyBPtr->m_deltaAngularVelocity = (float4)(0,0,0,0);
+ bodyBPtr->m_pushVelocity = (float4)(0,0,0,0);
+ bodyBPtr->m_turnVelocity = (float4)(0,0,0,0);
+
+ int rowskip = sizeof(b3SolverConstraint)/sizeof(float);//check this
+
+
+
+
+ b3GpuConstraintInfo2 info2;
+ info2.fps = 1.f/timeStep;
+ info2.erp = globalErp;
+ info2.m_J1linearAxisFloat4 = &currentConstraintRow->m_contactNormal;
+ info2.m_J1angularAxisFloat4 = &currentConstraintRow->m_relpos1CrossNormal;
+ info2.m_J2linearAxisFloat4 = 0;
+ info2.m_J2angularAxisFloat4 = &currentConstraintRow->m_relpos2CrossNormal;
+ info2.rowskip = sizeof(b3SolverConstraint)/sizeof(float);//check this
+
+ ///the size of b3SolverConstraint needs be a multiple of float
+// b3Assert(info2.rowskip*sizeof(float)== sizeof(b3SolverConstraint));
+ info2.m_constraintError = &currentConstraintRow->m_rhs;
+ currentConstraintRow->m_cfm = globalCfm;
+ info2.m_damping = globalDamping;
+ info2.cfm = &currentConstraintRow->m_cfm;
+ info2.m_lowerLimit = &currentConstraintRow->m_lowerLimit;
+ info2.m_upperLimit = &currentConstraintRow->m_upperLimit;
+ info2.m_numIterations = globalNumIterations;
+
+ switch (constraint->m_constraintType)
+ {
+ case B3_GPU_POINT2POINT_CONSTRAINT_TYPE:
+ {
+ getInfo2Point2Point(constraint,&info2,bodies);
+ break;
+ }
+ case B3_GPU_FIXED_CONSTRAINT_TYPE:
+ {
+ getInfo2Point2Point(constraint,&info2,bodies);
+
+ getInfo2FixedOrientation(constraint,&info2,bodies,3);
+
+ break;
+ }
+
+ default:
+ {
+ }
+ }
+
+ ///finalize the constraint setup
+ for ( j=0;j<info1;j++)
+ {
+ __global b3SolverConstraint* solverConstraint = &currentConstraintRow[j];
+
+ if (solverConstraint->m_upperLimit>=constraint->m_breakingImpulseThreshold)
+ {
+ solverConstraint->m_upperLimit = constraint->m_breakingImpulseThreshold;
+ }
+
+ if (solverConstraint->m_lowerLimit<=-constraint->m_breakingImpulseThreshold)
+ {
+ solverConstraint->m_lowerLimit = -constraint->m_breakingImpulseThreshold;
+ }
+
+// solverConstraint->m_originalContactPoint = constraint;
+
+ Matrix3x3 invInertiaWorldA= inertias[constraint->m_rbA].m_invInertiaWorld;
+ {
+
+ //float4 angularFactorA(1,1,1);
+ float4 ftorqueAxis1 = solverConstraint->m_relpos1CrossNormal;
+ solverConstraint->m_angularComponentA = mtMul1(invInertiaWorldA,ftorqueAxis1);//*angularFactorA;
+ }
+
+ Matrix3x3 invInertiaWorldB= inertias[constraint->m_rbB].m_invInertiaWorld;
+ {
+
+ float4 ftorqueAxis2 = solverConstraint->m_relpos2CrossNormal;
+ solverConstraint->m_angularComponentB = mtMul1(invInertiaWorldB,ftorqueAxis2);//*constraint->m_rbB.getAngularFactor();
+ }
+
+ {
+ //it is ok to use solverConstraint->m_contactNormal instead of -solverConstraint->m_contactNormal
+ //because it gets multiplied iMJlB
+ float4 iMJlA = solverConstraint->m_contactNormal*rbA->m_invMass;
+ float4 iMJaA = mtMul3(solverConstraint->m_relpos1CrossNormal,invInertiaWorldA);
+ float4 iMJlB = solverConstraint->m_contactNormal*rbB->m_invMass;//sign of normal?
+ float4 iMJaB = mtMul3(solverConstraint->m_relpos2CrossNormal,invInertiaWorldB);
+
+ float sum = dot3F4(iMJlA,solverConstraint->m_contactNormal);
+ sum += dot3F4(iMJaA,solverConstraint->m_relpos1CrossNormal);
+ sum += dot3F4(iMJlB,solverConstraint->m_contactNormal);
+ sum += dot3F4(iMJaB,solverConstraint->m_relpos2CrossNormal);
+ float fsum = fabs(sum);
+ if (fsum>FLT_EPSILON)
+ {
+ solverConstraint->m_jacDiagABInv = 1.f/sum;
+ } else
+ {
+ solverConstraint->m_jacDiagABInv = 0.f;
+ }
+ }
+
+
+ ///fix rhs
+ ///todo: add force/torque accelerators
+ {
+ float rel_vel;
+ float vel1Dotn = dot3F4(solverConstraint->m_contactNormal,rbA->m_linVel) + dot3F4(solverConstraint->m_relpos1CrossNormal,rbA->m_angVel);
+ float vel2Dotn = -dot3F4(solverConstraint->m_contactNormal,rbB->m_linVel) + dot3F4(solverConstraint->m_relpos2CrossNormal,rbB->m_angVel);
+
+ rel_vel = vel1Dotn+vel2Dotn;
+
+ float restitution = 0.f;
+ float positionalError = solverConstraint->m_rhs;//already filled in by getConstraintInfo2
+ float velocityError = restitution - rel_vel * info2.m_damping;
+ float penetrationImpulse = positionalError*solverConstraint->m_jacDiagABInv;
+ float velocityImpulse = velocityError *solverConstraint->m_jacDiagABInv;
+ solverConstraint->m_rhs = penetrationImpulse+velocityImpulse;
+ solverConstraint->m_appliedImpulse = 0.f;
+
+ }
+ }
+ }
+}
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/jointSolver.h b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/jointSolver.h
new file mode 100644
index 0000000000..d48ecf6ea6
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/jointSolver.h
@@ -0,0 +1,721 @@
+//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
+static const char* solveConstraintRowsCL= \
+"/*\n"
+"Copyright (c) 2013 Advanced Micro Devices, Inc. \n"
+"This software is provided 'as-is', without any express or implied warranty.\n"
+"In no event will the authors be held liable for any damages arising from the use of this software.\n"
+"Permission is granted to anyone to use this software for any purpose, \n"
+"including commercial applications, and to alter it and redistribute it freely, \n"
+"subject to the following restrictions:\n"
+"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.\n"
+"2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
+"3. This notice may not be removed or altered from any source distribution.\n"
+"*/\n"
+"//Originally written by Erwin Coumans\n"
+"#define B3_CONSTRAINT_FLAG_ENABLED 1\n"
+"#define B3_GPU_POINT2POINT_CONSTRAINT_TYPE 3\n"
+"#define B3_GPU_FIXED_CONSTRAINT_TYPE 4\n"
+"#define MOTIONCLAMP 100000 //unused, for debugging/safety in case constraint solver fails\n"
+"#define B3_INFINITY 1e30f\n"
+"#define mymake_float4 (float4)\n"
+"__inline float dot3F4(float4 a, float4 b)\n"
+"{\n"
+" float4 a1 = mymake_float4(a.xyz,0.f);\n"
+" float4 b1 = mymake_float4(b.xyz,0.f);\n"
+" return dot(a1, b1);\n"
+"}\n"
+"typedef float4 Quaternion;\n"
+"typedef struct\n"
+"{\n"
+" float4 m_row[3];\n"
+"}Matrix3x3;\n"
+"__inline\n"
+"float4 mtMul1(Matrix3x3 a, float4 b);\n"
+"__inline\n"
+"float4 mtMul3(float4 a, Matrix3x3 b);\n"
+"__inline\n"
+"float4 mtMul1(Matrix3x3 a, float4 b)\n"
+"{\n"
+" float4 ans;\n"
+" ans.x = dot3F4( a.m_row[0], b );\n"
+" ans.y = dot3F4( a.m_row[1], b );\n"
+" ans.z = dot3F4( a.m_row[2], b );\n"
+" ans.w = 0.f;\n"
+" return ans;\n"
+"}\n"
+"__inline\n"
+"float4 mtMul3(float4 a, Matrix3x3 b)\n"
+"{\n"
+" float4 colx = mymake_float4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
+" float4 coly = mymake_float4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
+" float4 colz = mymake_float4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
+" float4 ans;\n"
+" ans.x = dot3F4( a, colx );\n"
+" ans.y = dot3F4( a, coly );\n"
+" ans.z = dot3F4( a, colz );\n"
+" return ans;\n"
+"}\n"
+"typedef struct\n"
+"{\n"
+" Matrix3x3 m_invInertiaWorld;\n"
+" Matrix3x3 m_initInvInertia;\n"
+"} BodyInertia;\n"
+"typedef struct\n"
+"{\n"
+" Matrix3x3 m_basis;//orientation\n"
+" float4 m_origin;//transform\n"
+"}b3Transform;\n"
+"typedef struct\n"
+"{\n"
+"// b3Transform m_worldTransformUnused;\n"
+" float4 m_deltaLinearVelocity;\n"
+" float4 m_deltaAngularVelocity;\n"
+" float4 m_angularFactor;\n"
+" float4 m_linearFactor;\n"
+" float4 m_invMass;\n"
+" float4 m_pushVelocity;\n"
+" float4 m_turnVelocity;\n"
+" float4 m_linearVelocity;\n"
+" float4 m_angularVelocity;\n"
+" union \n"
+" {\n"
+" void* m_originalBody;\n"
+" int m_originalBodyIndex;\n"
+" };\n"
+" int padding[3];\n"
+"} b3GpuSolverBody;\n"
+"typedef struct\n"
+"{\n"
+" float4 m_pos;\n"
+" Quaternion m_quat;\n"
+" float4 m_linVel;\n"
+" float4 m_angVel;\n"
+" unsigned int m_shapeIdx;\n"
+" float m_invMass;\n"
+" float m_restituitionCoeff;\n"
+" float m_frictionCoeff;\n"
+"} b3RigidBodyCL;\n"
+"typedef struct\n"
+"{\n"
+" float4 m_relpos1CrossNormal;\n"
+" float4 m_contactNormal;\n"
+" float4 m_relpos2CrossNormal;\n"
+" //float4 m_contactNormal2;//usually m_contactNormal2 == -m_contactNormal\n"
+" float4 m_angularComponentA;\n"
+" float4 m_angularComponentB;\n"
+" \n"
+" float m_appliedPushImpulse;\n"
+" float m_appliedImpulse;\n"
+" int m_padding1;\n"
+" int m_padding2;\n"
+" float m_friction;\n"
+" float m_jacDiagABInv;\n"
+" float m_rhs;\n"
+" float m_cfm;\n"
+" \n"
+" float m_lowerLimit;\n"
+" float m_upperLimit;\n"
+" float m_rhsPenetration;\n"
+" int m_originalConstraint;\n"
+" int m_overrideNumSolverIterations;\n"
+" int m_frictionIndex;\n"
+" int m_solverBodyIdA;\n"
+" int m_solverBodyIdB;\n"
+"} b3SolverConstraint;\n"
+"typedef struct \n"
+"{\n"
+" int m_bodyAPtrAndSignBit;\n"
+" int m_bodyBPtrAndSignBit;\n"
+" int m_originalConstraintIndex;\n"
+" int m_batchId;\n"
+"} b3BatchConstraint;\n"
+"typedef struct \n"
+"{\n"
+" int m_constraintType;\n"
+" int m_rbA;\n"
+" int m_rbB;\n"
+" float m_breakingImpulseThreshold;\n"
+" float4 m_pivotInA;\n"
+" float4 m_pivotInB;\n"
+" Quaternion m_relTargetAB;\n"
+" int m_flags;\n"
+" int m_padding[3];\n"
+"} b3GpuGenericConstraint;\n"
+"/*b3Transform getWorldTransform(b3RigidBodyCL* rb)\n"
+"{\n"
+" b3Transform newTrans;\n"
+" newTrans.setOrigin(rb->m_pos);\n"
+" newTrans.setRotation(rb->m_quat);\n"
+" return newTrans;\n"
+"}*/\n"
+"__inline\n"
+"float4 cross3(float4 a, float4 b)\n"
+"{\n"
+" return cross(a,b);\n"
+"}\n"
+"__inline\n"
+"float4 fastNormalize4(float4 v)\n"
+"{\n"
+" v = mymake_float4(v.xyz,0.f);\n"
+" return fast_normalize(v);\n"
+"}\n"
+"__inline\n"
+"Quaternion qtMul(Quaternion a, Quaternion b);\n"
+"__inline\n"
+"Quaternion qtNormalize(Quaternion in);\n"
+"__inline\n"
+"float4 qtRotate(Quaternion q, float4 vec);\n"
+"__inline\n"
+"Quaternion qtInvert(Quaternion q);\n"
+"__inline\n"
+"Quaternion qtMul(Quaternion a, Quaternion b)\n"
+"{\n"
+" Quaternion ans;\n"
+" ans = cross3( a, b );\n"
+" ans += a.w*b+b.w*a;\n"
+"// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
+" ans.w = a.w*b.w - dot3F4(a, b);\n"
+" return ans;\n"
+"}\n"
+"__inline\n"
+"Quaternion qtNormalize(Quaternion in)\n"
+"{\n"
+" return fastNormalize4(in);\n"
+"// in /= length( in );\n"
+"// return in;\n"
+"}\n"
+"__inline\n"
+"float4 qtRotate(Quaternion q, float4 vec)\n"
+"{\n"
+" Quaternion qInv = qtInvert( q );\n"
+" float4 vcpy = vec;\n"
+" vcpy.w = 0.f;\n"
+" float4 out = qtMul(qtMul(q,vcpy),qInv);\n"
+" return out;\n"
+"}\n"
+"__inline\n"
+"Quaternion qtInvert(Quaternion q)\n"
+"{\n"
+" return (Quaternion)(-q.xyz, q.w);\n"
+"}\n"
+"__inline void internalApplyImpulse(__global b3GpuSolverBody* body, float4 linearComponent, float4 angularComponent,float impulseMagnitude)\n"
+"{\n"
+" body->m_deltaLinearVelocity += linearComponent*impulseMagnitude*body->m_linearFactor;\n"
+" body->m_deltaAngularVelocity += angularComponent*(impulseMagnitude*body->m_angularFactor);\n"
+"}\n"
+"void resolveSingleConstraintRowGeneric(__global b3GpuSolverBody* body1, __global b3GpuSolverBody* body2, __global b3SolverConstraint* c)\n"
+"{\n"
+" float deltaImpulse = c->m_rhs-c->m_appliedImpulse*c->m_cfm;\n"
+" float deltaVel1Dotn = dot3F4(c->m_contactNormal,body1->m_deltaLinearVelocity) + dot3F4(c->m_relpos1CrossNormal,body1->m_deltaAngularVelocity);\n"
+" float deltaVel2Dotn = -dot3F4(c->m_contactNormal,body2->m_deltaLinearVelocity) + dot3F4(c->m_relpos2CrossNormal,body2->m_deltaAngularVelocity);\n"
+" deltaImpulse -= deltaVel1Dotn*c->m_jacDiagABInv;\n"
+" deltaImpulse -= deltaVel2Dotn*c->m_jacDiagABInv;\n"
+" float sum = c->m_appliedImpulse + deltaImpulse;\n"
+" if (sum < c->m_lowerLimit)\n"
+" {\n"
+" deltaImpulse = c->m_lowerLimit-c->m_appliedImpulse;\n"
+" c->m_appliedImpulse = c->m_lowerLimit;\n"
+" }\n"
+" else if (sum > c->m_upperLimit) \n"
+" {\n"
+" deltaImpulse = c->m_upperLimit-c->m_appliedImpulse;\n"
+" c->m_appliedImpulse = c->m_upperLimit;\n"
+" }\n"
+" else\n"
+" {\n"
+" c->m_appliedImpulse = sum;\n"
+" }\n"
+" internalApplyImpulse(body1,c->m_contactNormal*body1->m_invMass,c->m_angularComponentA,deltaImpulse);\n"
+" internalApplyImpulse(body2,-c->m_contactNormal*body2->m_invMass,c->m_angularComponentB,deltaImpulse);\n"
+"}\n"
+"__kernel void solveJointConstraintRows(__global b3GpuSolverBody* solverBodies,\n"
+" __global b3BatchConstraint* batchConstraints,\n"
+" __global b3SolverConstraint* rows,\n"
+" __global unsigned int* numConstraintRowsInfo1, \n"
+" __global unsigned int* rowOffsets,\n"
+" __global b3GpuGenericConstraint* constraints,\n"
+" int batchOffset,\n"
+" int numConstraintsInBatch\n"
+" )\n"
+"{\n"
+" int b = get_global_id(0);\n"
+" if (b>=numConstraintsInBatch)\n"
+" return;\n"
+" __global b3BatchConstraint* c = &batchConstraints[b+batchOffset];\n"
+" int originalConstraintIndex = c->m_originalConstraintIndex;\n"
+" if (constraints[originalConstraintIndex].m_flags&B3_CONSTRAINT_FLAG_ENABLED)\n"
+" {\n"
+" int numConstraintRows = numConstraintRowsInfo1[originalConstraintIndex];\n"
+" int rowOffset = rowOffsets[originalConstraintIndex];\n"
+" for (int jj=0;jj<numConstraintRows;jj++)\n"
+" {\n"
+" __global b3SolverConstraint* constraint = &rows[rowOffset+jj];\n"
+" resolveSingleConstraintRowGeneric(&solverBodies[constraint->m_solverBodyIdA],&solverBodies[constraint->m_solverBodyIdB],constraint);\n"
+" }\n"
+" }\n"
+"};\n"
+"__kernel void initSolverBodies(__global b3GpuSolverBody* solverBodies,__global b3RigidBodyCL* bodiesCL, int numBodies)\n"
+"{\n"
+" int i = get_global_id(0);\n"
+" if (i>=numBodies)\n"
+" return;\n"
+" __global b3GpuSolverBody* solverBody = &solverBodies[i];\n"
+" __global b3RigidBodyCL* bodyCL = &bodiesCL[i];\n"
+" solverBody->m_deltaLinearVelocity = (float4)(0.f,0.f,0.f,0.f);\n"
+" solverBody->m_deltaAngularVelocity = (float4)(0.f,0.f,0.f,0.f);\n"
+" solverBody->m_pushVelocity = (float4)(0.f,0.f,0.f,0.f);\n"
+" solverBody->m_pushVelocity = (float4)(0.f,0.f,0.f,0.f);\n"
+" solverBody->m_invMass = (float4)(bodyCL->m_invMass,bodyCL->m_invMass,bodyCL->m_invMass,0.f);\n"
+" solverBody->m_originalBodyIndex = i;\n"
+" solverBody->m_angularFactor = (float4)(1,1,1,0);\n"
+" solverBody->m_linearFactor = (float4) (1,1,1,0);\n"
+" solverBody->m_linearVelocity = bodyCL->m_linVel;\n"
+" solverBody->m_angularVelocity = bodyCL->m_angVel;\n"
+"}\n"
+"__kernel void breakViolatedConstraintsKernel(__global b3GpuGenericConstraint* constraints, __global unsigned int* numConstraintRows, __global unsigned int* rowOffsets, __global b3SolverConstraint* rows, int numConstraints)\n"
+"{\n"
+" int cid = get_global_id(0);\n"
+" if (cid>=numConstraints)\n"
+" return;\n"
+" int numRows = numConstraintRows[cid];\n"
+" if (numRows)\n"
+" {\n"
+" for (int i=0;i<numRows;i++)\n"
+" {\n"
+" int rowIndex = rowOffsets[cid]+i;\n"
+" float breakingThreshold = constraints[cid].m_breakingImpulseThreshold;\n"
+" if (fabs(rows[rowIndex].m_appliedImpulse) >= breakingThreshold)\n"
+" {\n"
+" constraints[cid].m_flags =0;//&= ~B3_CONSTRAINT_FLAG_ENABLED;\n"
+" }\n"
+" }\n"
+" }\n"
+"}\n"
+"__kernel void getInfo1Kernel(__global unsigned int* infos, __global b3GpuGenericConstraint* constraints, int numConstraints)\n"
+"{\n"
+" int i = get_global_id(0);\n"
+" if (i>=numConstraints)\n"
+" return;\n"
+" __global b3GpuGenericConstraint* constraint = &constraints[i];\n"
+" switch (constraint->m_constraintType)\n"
+" {\n"
+" case B3_GPU_POINT2POINT_CONSTRAINT_TYPE:\n"
+" {\n"
+" infos[i] = 3;\n"
+" break;\n"
+" }\n"
+" case B3_GPU_FIXED_CONSTRAINT_TYPE:\n"
+" {\n"
+" infos[i] = 6;\n"
+" break;\n"
+" }\n"
+" default:\n"
+" {\n"
+" }\n"
+" }\n"
+"}\n"
+"__kernel void initBatchConstraintsKernel(__global unsigned int* numConstraintRows, __global unsigned int* rowOffsets, \n"
+" __global b3BatchConstraint* batchConstraints, \n"
+" __global b3GpuGenericConstraint* constraints,\n"
+" __global b3RigidBodyCL* bodies,\n"
+" int numConstraints)\n"
+"{\n"
+" int i = get_global_id(0);\n"
+" if (i>=numConstraints)\n"
+" return;\n"
+" int rbA = constraints[i].m_rbA;\n"
+" int rbB = constraints[i].m_rbB;\n"
+" batchConstraints[i].m_bodyAPtrAndSignBit = bodies[rbA].m_invMass != 0.f ? rbA : -rbA;\n"
+" batchConstraints[i].m_bodyBPtrAndSignBit = bodies[rbB].m_invMass != 0.f ? rbB : -rbB;\n"
+" batchConstraints[i].m_batchId = -1;\n"
+" batchConstraints[i].m_originalConstraintIndex = i;\n"
+"}\n"
+"typedef struct\n"
+"{\n"
+" // integrator parameters: frames per second (1/stepsize), default error\n"
+" // reduction parameter (0..1).\n"
+" float fps,erp;\n"
+" // for the first and second body, pointers to two (linear and angular)\n"
+" // n*3 jacobian sub matrices, stored by rows. these matrices will have\n"
+" // been initialized to 0 on entry. if the second body is zero then the\n"
+" // J2xx pointers may be 0.\n"
+" union \n"
+" {\n"
+" __global float4* m_J1linearAxisFloat4;\n"
+" __global float* m_J1linearAxis;\n"
+" };\n"
+" union\n"
+" {\n"
+" __global float4* m_J1angularAxisFloat4;\n"
+" __global float* m_J1angularAxis;\n"
+" };\n"
+" union\n"
+" {\n"
+" __global float4* m_J2linearAxisFloat4;\n"
+" __global float* m_J2linearAxis;\n"
+" };\n"
+" union\n"
+" {\n"
+" __global float4* m_J2angularAxisFloat4;\n"
+" __global float* m_J2angularAxis;\n"
+" };\n"
+" // elements to jump from one row to the next in J's\n"
+" int rowskip;\n"
+" // right hand sides of the equation J*v = c + cfm * lambda. cfm is the\n"
+" // \"constraint force mixing\" vector. c is set to zero on entry, cfm is\n"
+" // set to a constant value (typically very small or zero) value on entry.\n"
+" __global float* m_constraintError;\n"
+" __global float* cfm;\n"
+" // lo and hi limits for variables (set to -/+ infinity on entry).\n"
+" __global float* m_lowerLimit;\n"
+" __global float* m_upperLimit;\n"
+" // findex vector for variables. see the LCP solver interface for a\n"
+" // description of what this does. this is set to -1 on entry.\n"
+" // note that the returned indexes are relative to the first index of\n"
+" // the constraint.\n"
+" __global int *findex;\n"
+" // number of solver iterations\n"
+" int m_numIterations;\n"
+" //damping of the velocity\n"
+" float m_damping;\n"
+"} b3GpuConstraintInfo2;\n"
+"void getSkewSymmetricMatrix(float4 vecIn, __global float4* v0,__global float4* v1,__global float4* v2)\n"
+"{\n"
+" *v0 = (float4)(0. ,-vecIn.z ,vecIn.y,0.f);\n"
+" *v1 = (float4)(vecIn.z ,0. ,-vecIn.x,0.f);\n"
+" *v2 = (float4)(-vecIn.y ,vecIn.x ,0.f,0.f);\n"
+"}\n"
+"void getInfo2Point2Point(__global b3GpuGenericConstraint* constraint,b3GpuConstraintInfo2* info,__global b3RigidBodyCL* bodies)\n"
+"{\n"
+" float4 posA = bodies[constraint->m_rbA].m_pos;\n"
+" Quaternion rotA = bodies[constraint->m_rbA].m_quat;\n"
+" float4 posB = bodies[constraint->m_rbB].m_pos;\n"
+" Quaternion rotB = bodies[constraint->m_rbB].m_quat;\n"
+" // anchor points in global coordinates with respect to body PORs.\n"
+" \n"
+" // set jacobian\n"
+" info->m_J1linearAxis[0] = 1;\n"
+" info->m_J1linearAxis[info->rowskip+1] = 1;\n"
+" info->m_J1linearAxis[2*info->rowskip+2] = 1;\n"
+" float4 a1 = qtRotate(rotA,constraint->m_pivotInA);\n"
+" {\n"
+" __global float4* angular0 = (__global float4*)(info->m_J1angularAxis);\n"
+" __global float4* angular1 = (__global float4*)(info->m_J1angularAxis+info->rowskip);\n"
+" __global float4* angular2 = (__global float4*)(info->m_J1angularAxis+2*info->rowskip);\n"
+" float4 a1neg = -a1;\n"
+" getSkewSymmetricMatrix(a1neg,angular0,angular1,angular2);\n"
+" }\n"
+" if (info->m_J2linearAxis)\n"
+" {\n"
+" info->m_J2linearAxis[0] = -1;\n"
+" info->m_J2linearAxis[info->rowskip+1] = -1;\n"
+" info->m_J2linearAxis[2*info->rowskip+2] = -1;\n"
+" }\n"
+" \n"
+" float4 a2 = qtRotate(rotB,constraint->m_pivotInB);\n"
+" \n"
+" {\n"
+" // float4 a2n = -a2;\n"
+" __global float4* angular0 = (__global float4*)(info->m_J2angularAxis);\n"
+" __global float4* angular1 = (__global float4*)(info->m_J2angularAxis+info->rowskip);\n"
+" __global float4* angular2 = (__global float4*)(info->m_J2angularAxis+2*info->rowskip);\n"
+" getSkewSymmetricMatrix(a2,angular0,angular1,angular2);\n"
+" }\n"
+" \n"
+" // set right hand side\n"
+"// float currERP = (m_flags & B3_P2P_FLAGS_ERP) ? m_erp : info->erp;\n"
+" float currERP = info->erp;\n"
+" float k = info->fps * currERP;\n"
+" int j;\n"
+" float4 result = a2 + posB - a1 - posA;\n"
+" float* resultPtr = &result;\n"
+" for (j=0; j<3; j++)\n"
+" {\n"
+" info->m_constraintError[j*info->rowskip] = k * (resultPtr[j]);\n"
+" }\n"
+"}\n"
+"Quaternion nearest( Quaternion first, Quaternion qd)\n"
+"{\n"
+" Quaternion diff,sum;\n"
+" diff = first- qd;\n"
+" sum = first + qd;\n"
+" \n"
+" if( dot(diff,diff) < dot(sum,sum) )\n"
+" return qd;\n"
+" return (-qd);\n"
+"}\n"
+"float b3Acos(float x) \n"
+"{ \n"
+" if (x<-1) \n"
+" x=-1; \n"
+" if (x>1) \n"
+" x=1;\n"
+" return acos(x); \n"
+"}\n"
+"float getAngle(Quaternion orn)\n"
+"{\n"
+" if (orn.w>=1.f)\n"
+" orn.w=1.f;\n"
+" float s = 2.f * b3Acos(orn.w);\n"
+" return s;\n"
+"}\n"
+"void calculateDiffAxisAngleQuaternion( Quaternion orn0,Quaternion orn1a,float4* axis,float* angle)\n"
+"{\n"
+" Quaternion orn1 = nearest(orn0,orn1a);\n"
+" \n"
+" Quaternion dorn = qtMul(orn1,qtInvert(orn0));\n"
+" *angle = getAngle(dorn);\n"
+" *axis = (float4)(dorn.x,dorn.y,dorn.z,0.f);\n"
+" \n"
+" //check for axis length\n"
+" float len = dot3F4(*axis,*axis);\n"
+" if (len < FLT_EPSILON*FLT_EPSILON)\n"
+" *axis = (float4)(1,0,0,0);\n"
+" else\n"
+" *axis /= sqrt(len);\n"
+"}\n"
+"void getInfo2FixedOrientation(__global b3GpuGenericConstraint* constraint,b3GpuConstraintInfo2* info,__global b3RigidBodyCL* bodies, int start_row)\n"
+"{\n"
+" Quaternion worldOrnA = bodies[constraint->m_rbA].m_quat;\n"
+" Quaternion worldOrnB = bodies[constraint->m_rbB].m_quat;\n"
+" int s = info->rowskip;\n"
+" int start_index = start_row * s;\n"
+" // 3 rows to make body rotations equal\n"
+" info->m_J1angularAxis[start_index] = 1;\n"
+" info->m_J1angularAxis[start_index + s + 1] = 1;\n"
+" info->m_J1angularAxis[start_index + s*2+2] = 1;\n"
+" if ( info->m_J2angularAxis)\n"
+" {\n"
+" info->m_J2angularAxis[start_index] = -1;\n"
+" info->m_J2angularAxis[start_index + s+1] = -1;\n"
+" info->m_J2angularAxis[start_index + s*2+2] = -1;\n"
+" }\n"
+" \n"
+" float currERP = info->erp;\n"
+" float k = info->fps * currERP;\n"
+" float4 diff;\n"
+" float angle;\n"
+" float4 qrelCur = qtMul(worldOrnA,qtInvert(worldOrnB));\n"
+" \n"
+" calculateDiffAxisAngleQuaternion(constraint->m_relTargetAB,qrelCur,&diff,&angle);\n"
+" diff*=-angle;\n"
+" \n"
+" float* resultPtr = &diff;\n"
+" \n"
+" for (int j=0; j<3; j++)\n"
+" {\n"
+" info->m_constraintError[(3+j)*info->rowskip] = k * resultPtr[j];\n"
+" }\n"
+" \n"
+"}\n"
+"__kernel void writeBackVelocitiesKernel(__global b3RigidBodyCL* bodies,__global b3GpuSolverBody* solverBodies,int numBodies)\n"
+"{\n"
+" int i = get_global_id(0);\n"
+" if (i>=numBodies)\n"
+" return;\n"
+" if (bodies[i].m_invMass)\n"
+" {\n"
+"// if (length(solverBodies[i].m_deltaLinearVelocity)<MOTIONCLAMP)\n"
+" {\n"
+" bodies[i].m_linVel += solverBodies[i].m_deltaLinearVelocity;\n"
+" }\n"
+"// if (length(solverBodies[i].m_deltaAngularVelocity)<MOTIONCLAMP)\n"
+" {\n"
+" bodies[i].m_angVel += solverBodies[i].m_deltaAngularVelocity;\n"
+" } \n"
+" }\n"
+"}\n"
+"__kernel void getInfo2Kernel(__global b3SolverConstraint* solverConstraintRows, \n"
+" __global unsigned int* infos, \n"
+" __global unsigned int* constraintRowOffsets, \n"
+" __global b3GpuGenericConstraint* constraints, \n"
+" __global b3BatchConstraint* batchConstraints, \n"
+" __global b3RigidBodyCL* bodies,\n"
+" __global BodyInertia* inertias,\n"
+" __global b3GpuSolverBody* solverBodies,\n"
+" float timeStep,\n"
+" float globalErp,\n"
+" float globalCfm,\n"
+" float globalDamping,\n"
+" int globalNumIterations,\n"
+" int numConstraints)\n"
+"{\n"
+" int i = get_global_id(0);\n"
+" if (i>=numConstraints)\n"
+" return;\n"
+" \n"
+" //for now, always initialize the batch info\n"
+" int info1 = infos[i];\n"
+" \n"
+" __global b3SolverConstraint* currentConstraintRow = &solverConstraintRows[constraintRowOffsets[i]];\n"
+" __global b3GpuGenericConstraint* constraint = &constraints[i];\n"
+" __global b3RigidBodyCL* rbA = &bodies[ constraint->m_rbA];\n"
+" __global b3RigidBodyCL* rbB = &bodies[ constraint->m_rbB];\n"
+" int solverBodyIdA = constraint->m_rbA;\n"
+" int solverBodyIdB = constraint->m_rbB;\n"
+" __global b3GpuSolverBody* bodyAPtr = &solverBodies[solverBodyIdA];\n"
+" __global b3GpuSolverBody* bodyBPtr = &solverBodies[solverBodyIdB];\n"
+" if (rbA->m_invMass)\n"
+" {\n"
+" batchConstraints[i].m_bodyAPtrAndSignBit = solverBodyIdA;\n"
+" } else\n"
+" {\n"
+"// if (!solverBodyIdA)\n"
+"// m_staticIdx = 0;\n"
+" batchConstraints[i].m_bodyAPtrAndSignBit = -solverBodyIdA;\n"
+" }\n"
+" if (rbB->m_invMass)\n"
+" {\n"
+" batchConstraints[i].m_bodyBPtrAndSignBit = solverBodyIdB;\n"
+" } else\n"
+" {\n"
+"// if (!solverBodyIdB)\n"
+"// m_staticIdx = 0;\n"
+" batchConstraints[i].m_bodyBPtrAndSignBit = -solverBodyIdB;\n"
+" }\n"
+" if (info1)\n"
+" {\n"
+" int overrideNumSolverIterations = 0;//constraint->getOverrideNumSolverIterations() > 0 ? constraint->getOverrideNumSolverIterations() : infoGlobal.m_numIterations;\n"
+"// if (overrideNumSolverIterations>m_maxOverrideNumSolverIterations)\n"
+" // m_maxOverrideNumSolverIterations = overrideNumSolverIterations;\n"
+" int j;\n"
+" for ( j=0;j<info1;j++)\n"
+" {\n"
+"// memset(&currentConstraintRow[j],0,sizeof(b3SolverConstraint));\n"
+" currentConstraintRow[j].m_angularComponentA = (float4)(0,0,0,0);\n"
+" currentConstraintRow[j].m_angularComponentB = (float4)(0,0,0,0);\n"
+" currentConstraintRow[j].m_appliedImpulse = 0.f;\n"
+" currentConstraintRow[j].m_appliedPushImpulse = 0.f;\n"
+" currentConstraintRow[j].m_cfm = 0.f;\n"
+" currentConstraintRow[j].m_contactNormal = (float4)(0,0,0,0);\n"
+" currentConstraintRow[j].m_friction = 0.f;\n"
+" currentConstraintRow[j].m_frictionIndex = 0;\n"
+" currentConstraintRow[j].m_jacDiagABInv = 0.f;\n"
+" currentConstraintRow[j].m_lowerLimit = 0.f;\n"
+" currentConstraintRow[j].m_upperLimit = 0.f;\n"
+" currentConstraintRow[j].m_originalConstraint = i;\n"
+" currentConstraintRow[j].m_overrideNumSolverIterations = 0;\n"
+" currentConstraintRow[j].m_relpos1CrossNormal = (float4)(0,0,0,0);\n"
+" currentConstraintRow[j].m_relpos2CrossNormal = (float4)(0,0,0,0);\n"
+" currentConstraintRow[j].m_rhs = 0.f;\n"
+" currentConstraintRow[j].m_rhsPenetration = 0.f;\n"
+" currentConstraintRow[j].m_solverBodyIdA = 0;\n"
+" currentConstraintRow[j].m_solverBodyIdB = 0;\n"
+" \n"
+" currentConstraintRow[j].m_lowerLimit = -B3_INFINITY;\n"
+" currentConstraintRow[j].m_upperLimit = B3_INFINITY;\n"
+" currentConstraintRow[j].m_appliedImpulse = 0.f;\n"
+" currentConstraintRow[j].m_appliedPushImpulse = 0.f;\n"
+" currentConstraintRow[j].m_solverBodyIdA = solverBodyIdA;\n"
+" currentConstraintRow[j].m_solverBodyIdB = solverBodyIdB;\n"
+" currentConstraintRow[j].m_overrideNumSolverIterations = overrideNumSolverIterations; \n"
+" }\n"
+" bodyAPtr->m_deltaLinearVelocity = (float4)(0,0,0,0);\n"
+" bodyAPtr->m_deltaAngularVelocity = (float4)(0,0,0,0);\n"
+" bodyAPtr->m_pushVelocity = (float4)(0,0,0,0);\n"
+" bodyAPtr->m_turnVelocity = (float4)(0,0,0,0);\n"
+" bodyBPtr->m_deltaLinearVelocity = (float4)(0,0,0,0);\n"
+" bodyBPtr->m_deltaAngularVelocity = (float4)(0,0,0,0);\n"
+" bodyBPtr->m_pushVelocity = (float4)(0,0,0,0);\n"
+" bodyBPtr->m_turnVelocity = (float4)(0,0,0,0);\n"
+" int rowskip = sizeof(b3SolverConstraint)/sizeof(float);//check this\n"
+" \n"
+" b3GpuConstraintInfo2 info2;\n"
+" info2.fps = 1.f/timeStep;\n"
+" info2.erp = globalErp;\n"
+" info2.m_J1linearAxisFloat4 = &currentConstraintRow->m_contactNormal;\n"
+" info2.m_J1angularAxisFloat4 = &currentConstraintRow->m_relpos1CrossNormal;\n"
+" info2.m_J2linearAxisFloat4 = 0;\n"
+" info2.m_J2angularAxisFloat4 = &currentConstraintRow->m_relpos2CrossNormal;\n"
+" info2.rowskip = sizeof(b3SolverConstraint)/sizeof(float);//check this\n"
+" ///the size of b3SolverConstraint needs be a multiple of float\n"
+"// b3Assert(info2.rowskip*sizeof(float)== sizeof(b3SolverConstraint));\n"
+" info2.m_constraintError = &currentConstraintRow->m_rhs;\n"
+" currentConstraintRow->m_cfm = globalCfm;\n"
+" info2.m_damping = globalDamping;\n"
+" info2.cfm = &currentConstraintRow->m_cfm;\n"
+" info2.m_lowerLimit = &currentConstraintRow->m_lowerLimit;\n"
+" info2.m_upperLimit = &currentConstraintRow->m_upperLimit;\n"
+" info2.m_numIterations = globalNumIterations;\n"
+" switch (constraint->m_constraintType)\n"
+" {\n"
+" case B3_GPU_POINT2POINT_CONSTRAINT_TYPE:\n"
+" {\n"
+" getInfo2Point2Point(constraint,&info2,bodies);\n"
+" break;\n"
+" }\n"
+" case B3_GPU_FIXED_CONSTRAINT_TYPE:\n"
+" {\n"
+" getInfo2Point2Point(constraint,&info2,bodies);\n"
+" getInfo2FixedOrientation(constraint,&info2,bodies,3);\n"
+" break;\n"
+" }\n"
+" default:\n"
+" {\n"
+" }\n"
+" }\n"
+" ///finalize the constraint setup\n"
+" for ( j=0;j<info1;j++)\n"
+" {\n"
+" __global b3SolverConstraint* solverConstraint = &currentConstraintRow[j];\n"
+" if (solverConstraint->m_upperLimit>=constraint->m_breakingImpulseThreshold)\n"
+" {\n"
+" solverConstraint->m_upperLimit = constraint->m_breakingImpulseThreshold;\n"
+" }\n"
+" if (solverConstraint->m_lowerLimit<=-constraint->m_breakingImpulseThreshold)\n"
+" {\n"
+" solverConstraint->m_lowerLimit = -constraint->m_breakingImpulseThreshold;\n"
+" }\n"
+"// solverConstraint->m_originalContactPoint = constraint;\n"
+" \n"
+" Matrix3x3 invInertiaWorldA= inertias[constraint->m_rbA].m_invInertiaWorld;\n"
+" {\n"
+" //float4 angularFactorA(1,1,1);\n"
+" float4 ftorqueAxis1 = solverConstraint->m_relpos1CrossNormal;\n"
+" solverConstraint->m_angularComponentA = mtMul1(invInertiaWorldA,ftorqueAxis1);//*angularFactorA;\n"
+" }\n"
+" \n"
+" Matrix3x3 invInertiaWorldB= inertias[constraint->m_rbB].m_invInertiaWorld;\n"
+" {\n"
+" float4 ftorqueAxis2 = solverConstraint->m_relpos2CrossNormal;\n"
+" solverConstraint->m_angularComponentB = mtMul1(invInertiaWorldB,ftorqueAxis2);//*constraint->m_rbB.getAngularFactor();\n"
+" }\n"
+" {\n"
+" //it is ok to use solverConstraint->m_contactNormal instead of -solverConstraint->m_contactNormal\n"
+" //because it gets multiplied iMJlB\n"
+" float4 iMJlA = solverConstraint->m_contactNormal*rbA->m_invMass;\n"
+" float4 iMJaA = mtMul3(solverConstraint->m_relpos1CrossNormal,invInertiaWorldA);\n"
+" float4 iMJlB = solverConstraint->m_contactNormal*rbB->m_invMass;//sign of normal?\n"
+" float4 iMJaB = mtMul3(solverConstraint->m_relpos2CrossNormal,invInertiaWorldB);\n"
+" float sum = dot3F4(iMJlA,solverConstraint->m_contactNormal);\n"
+" sum += dot3F4(iMJaA,solverConstraint->m_relpos1CrossNormal);\n"
+" sum += dot3F4(iMJlB,solverConstraint->m_contactNormal);\n"
+" sum += dot3F4(iMJaB,solverConstraint->m_relpos2CrossNormal);\n"
+" float fsum = fabs(sum);\n"
+" if (fsum>FLT_EPSILON)\n"
+" {\n"
+" solverConstraint->m_jacDiagABInv = 1.f/sum;\n"
+" } else\n"
+" {\n"
+" solverConstraint->m_jacDiagABInv = 0.f;\n"
+" }\n"
+" }\n"
+" ///fix rhs\n"
+" ///todo: add force/torque accelerators\n"
+" {\n"
+" float rel_vel;\n"
+" float vel1Dotn = dot3F4(solverConstraint->m_contactNormal,rbA->m_linVel) + dot3F4(solverConstraint->m_relpos1CrossNormal,rbA->m_angVel);\n"
+" float vel2Dotn = -dot3F4(solverConstraint->m_contactNormal,rbB->m_linVel) + dot3F4(solverConstraint->m_relpos2CrossNormal,rbB->m_angVel);\n"
+" rel_vel = vel1Dotn+vel2Dotn;\n"
+" float restitution = 0.f;\n"
+" float positionalError = solverConstraint->m_rhs;//already filled in by getConstraintInfo2\n"
+" float velocityError = restitution - rel_vel * info2.m_damping;\n"
+" float penetrationImpulse = positionalError*solverConstraint->m_jacDiagABInv;\n"
+" float velocityImpulse = velocityError *solverConstraint->m_jacDiagABInv;\n"
+" solverConstraint->m_rhs = penetrationImpulse+velocityImpulse;\n"
+" solverConstraint->m_appliedImpulse = 0.f;\n"
+" }\n"
+" }\n"
+" }\n"
+"}\n"
+;
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/solveContact.cl b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/solveContact.cl
new file mode 100644
index 0000000000..5c4d62e4ec
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/solveContact.cl
@@ -0,0 +1,501 @@
+/*
+Copyright (c) 2012 Advanced Micro Devices, Inc.
+
+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.
+*/
+//Originally written by Takahiro Harada
+
+
+//#pragma OPENCL EXTENSION cl_amd_printf : enable
+#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable
+
+
+#ifdef cl_ext_atomic_counters_32
+#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable
+#else
+#define counter32_t volatile global int*
+#endif
+
+typedef unsigned int u32;
+typedef unsigned short u16;
+typedef unsigned char u8;
+
+#define GET_GROUP_IDX get_group_id(0)
+#define GET_LOCAL_IDX get_local_id(0)
+#define GET_GLOBAL_IDX get_global_id(0)
+#define GET_GROUP_SIZE get_local_size(0)
+#define GET_NUM_GROUPS get_num_groups(0)
+#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)
+#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)
+#define AtomInc(x) atom_inc(&(x))
+#define AtomInc1(x, out) out = atom_inc(&(x))
+#define AppendInc(x, out) out = atomic_inc(x)
+#define AtomAdd(x, value) atom_add(&(x), value)
+#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )
+#define AtomXhg(x, value) atom_xchg ( &(x), value )
+
+
+#define SELECT_UINT4( b, a, condition ) select( b,a,condition )
+
+#define mymake_float4 (float4)
+//#define make_float2 (float2)
+//#define make_uint4 (uint4)
+//#define make_int4 (int4)
+//#define make_uint2 (uint2)
+//#define make_int2 (int2)
+
+
+#define max2 max
+#define min2 min
+
+
+///////////////////////////////////////
+// Vector
+///////////////////////////////////////
+
+
+
+
+__inline
+float4 fastNormalize4(float4 v)
+{
+ return fast_normalize(v);
+}
+
+
+
+__inline
+float4 cross3(float4 a, float4 b)
+{
+ return cross(a,b);
+}
+
+__inline
+float dot3F4(float4 a, float4 b)
+{
+ float4 a1 = mymake_float4(a.xyz,0.f);
+ float4 b1 = mymake_float4(b.xyz,0.f);
+ return dot(a1, b1);
+}
+
+
+
+
+__inline
+float4 normalize3(const float4 a)
+{
+ float4 n = mymake_float4(a.x, a.y, a.z, 0.f);
+ return fastNormalize4( n );
+// float length = sqrtf(dot3F4(a, a));
+// return 1.f/length * a;
+}
+
+
+
+
+///////////////////////////////////////
+// Matrix3x3
+///////////////////////////////////////
+
+typedef struct
+{
+ float4 m_row[3];
+}Matrix3x3;
+
+
+
+
+
+
+__inline
+float4 mtMul1(Matrix3x3 a, float4 b);
+
+__inline
+float4 mtMul3(float4 a, Matrix3x3 b);
+
+
+
+
+__inline
+float4 mtMul1(Matrix3x3 a, float4 b)
+{
+ float4 ans;
+ ans.x = dot3F4( a.m_row[0], b );
+ ans.y = dot3F4( a.m_row[1], b );
+ ans.z = dot3F4( a.m_row[2], b );
+ ans.w = 0.f;
+ return ans;
+}
+
+__inline
+float4 mtMul3(float4 a, Matrix3x3 b)
+{
+ float4 colx = mymake_float4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);
+ float4 coly = mymake_float4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);
+ float4 colz = mymake_float4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);
+
+ float4 ans;
+ ans.x = dot3F4( a, colx );
+ ans.y = dot3F4( a, coly );
+ ans.z = dot3F4( a, colz );
+ return ans;
+}
+
+///////////////////////////////////////
+// Quaternion
+///////////////////////////////////////
+
+typedef float4 Quaternion;
+
+
+
+
+
+
+
+#define WG_SIZE 64
+
+typedef struct
+{
+ float4 m_pos;
+ Quaternion m_quat;
+ float4 m_linVel;
+ float4 m_angVel;
+
+ u32 m_shapeIdx;
+ float m_invMass;
+ float m_restituitionCoeff;
+ float m_frictionCoeff;
+} Body;
+
+typedef struct
+{
+ Matrix3x3 m_invInertia;
+ Matrix3x3 m_initInvInertia;
+} Shape;
+
+typedef struct
+{
+ float4 m_linear;
+ float4 m_worldPos[4];
+ float4 m_center;
+ float m_jacCoeffInv[4];
+ float m_b[4];
+ float m_appliedRambdaDt[4];
+
+ float m_fJacCoeffInv[2];
+ float m_fAppliedRambdaDt[2];
+
+ u32 m_bodyA;
+ u32 m_bodyB;
+
+ int m_batchIdx;
+ u32 m_paddings[1];
+} Constraint4;
+
+
+
+typedef struct
+{
+ int m_nConstraints;
+ int m_start;
+ int m_batchIdx;
+ int m_nSplit;
+// int m_paddings[1];
+} ConstBuffer;
+
+typedef struct
+{
+ int m_solveFriction;
+ int m_maxBatch; // long batch really kills the performance
+ int m_batchIdx;
+ int m_nSplit;
+// int m_paddings[1];
+} ConstBufferBatchSolve;
+
+void setLinearAndAngular( float4 n, float4 r0, float4 r1, float4* linear, float4* angular0, float4* angular1);
+
+void setLinearAndAngular( float4 n, float4 r0, float4 r1, float4* linear, float4* angular0, float4* angular1)
+{
+ *linear = mymake_float4(-n.xyz,0.f);
+ *angular0 = -cross3(r0, n);
+ *angular1 = cross3(r1, n);
+}
+
+float calcRelVel( float4 l0, float4 l1, float4 a0, float4 a1, float4 linVel0, float4 angVel0, float4 linVel1, float4 angVel1 );
+
+float calcRelVel( float4 l0, float4 l1, float4 a0, float4 a1, float4 linVel0, float4 angVel0, float4 linVel1, float4 angVel1 )
+{
+ return dot3F4(l0, linVel0) + dot3F4(a0, angVel0) + dot3F4(l1, linVel1) + dot3F4(a1, angVel1);
+}
+
+
+float calcJacCoeff(const float4 linear0, const float4 linear1, const float4 angular0, const float4 angular1,
+ float invMass0, const Matrix3x3* invInertia0, float invMass1, const Matrix3x3* invInertia1);
+
+float calcJacCoeff(const float4 linear0, const float4 linear1, const float4 angular0, const float4 angular1,
+ float invMass0, const Matrix3x3* invInertia0, float invMass1, const Matrix3x3* invInertia1)
+{
+ // linear0,1 are normlized
+ float jmj0 = invMass0;//dot3F4(linear0, linear0)*invMass0;
+ float jmj1 = dot3F4(mtMul3(angular0,*invInertia0), angular0);
+ float jmj2 = invMass1;//dot3F4(linear1, linear1)*invMass1;
+ float jmj3 = dot3F4(mtMul3(angular1,*invInertia1), angular1);
+ return -1.f/(jmj0+jmj1+jmj2+jmj3);
+}
+
+
+void solveContact(__global Constraint4* cs,
+ float4 posA, float4* linVelA, float4* angVelA, float invMassA, Matrix3x3 invInertiaA,
+ float4 posB, float4* linVelB, float4* angVelB, float invMassB, Matrix3x3 invInertiaB);
+
+void solveContact(__global Constraint4* cs,
+ float4 posA, float4* linVelA, float4* angVelA, float invMassA, Matrix3x3 invInertiaA,
+ float4 posB, float4* linVelB, float4* angVelB, float invMassB, Matrix3x3 invInertiaB)
+{
+ float minRambdaDt = 0;
+ float maxRambdaDt = FLT_MAX;
+
+ for(int ic=0; ic<4; ic++)
+ {
+ if( cs->m_jacCoeffInv[ic] == 0.f ) continue;
+
+ float4 angular0, angular1, linear;
+ float4 r0 = cs->m_worldPos[ic] - posA;
+ float4 r1 = cs->m_worldPos[ic] - posB;
+ setLinearAndAngular( -cs->m_linear, r0, r1, &linear, &angular0, &angular1 );
+
+ float rambdaDt = calcRelVel( cs->m_linear, -cs->m_linear, angular0, angular1,
+ *linVelA, *angVelA, *linVelB, *angVelB ) + cs->m_b[ic];
+ rambdaDt *= cs->m_jacCoeffInv[ic];
+
+ {
+ float prevSum = cs->m_appliedRambdaDt[ic];
+ float updated = prevSum;
+ updated += rambdaDt;
+ updated = max2( updated, minRambdaDt );
+ updated = min2( updated, maxRambdaDt );
+ rambdaDt = updated - prevSum;
+ cs->m_appliedRambdaDt[ic] = updated;
+ }
+
+ float4 linImp0 = invMassA*linear*rambdaDt;
+ float4 linImp1 = invMassB*(-linear)*rambdaDt;
+ float4 angImp0 = mtMul1(invInertiaA, angular0)*rambdaDt;
+ float4 angImp1 = mtMul1(invInertiaB, angular1)*rambdaDt;
+
+ *linVelA += linImp0;
+ *angVelA += angImp0;
+ *linVelB += linImp1;
+ *angVelB += angImp1;
+ }
+}
+
+void btPlaneSpace1 (const float4* n, float4* p, float4* q);
+ void btPlaneSpace1 (const float4* n, float4* p, float4* q)
+{
+ if (fabs(n[0].z) > 0.70710678f) {
+ // choose p in y-z plane
+ float a = n[0].y*n[0].y + n[0].z*n[0].z;
+ float k = 1.f/sqrt(a);
+ p[0].x = 0;
+ p[0].y = -n[0].z*k;
+ p[0].z = n[0].y*k;
+ // set q = n x p
+ q[0].x = a*k;
+ q[0].y = -n[0].x*p[0].z;
+ q[0].z = n[0].x*p[0].y;
+ }
+ else {
+ // choose p in x-y plane
+ float a = n[0].x*n[0].x + n[0].y*n[0].y;
+ float k = 1.f/sqrt(a);
+ p[0].x = -n[0].y*k;
+ p[0].y = n[0].x*k;
+ p[0].z = 0;
+ // set q = n x p
+ q[0].x = -n[0].z*p[0].y;
+ q[0].y = n[0].z*p[0].x;
+ q[0].z = a*k;
+ }
+}
+
+void solveContactConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs);
+void solveContactConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs)
+{
+ //float frictionCoeff = ldsCs[0].m_linear.w;
+ int aIdx = ldsCs[0].m_bodyA;
+ int bIdx = ldsCs[0].m_bodyB;
+
+ float4 posA = gBodies[aIdx].m_pos;
+ float4 linVelA = gBodies[aIdx].m_linVel;
+ float4 angVelA = gBodies[aIdx].m_angVel;
+ float invMassA = gBodies[aIdx].m_invMass;
+ Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia;
+
+ float4 posB = gBodies[bIdx].m_pos;
+ float4 linVelB = gBodies[bIdx].m_linVel;
+ float4 angVelB = gBodies[bIdx].m_angVel;
+ float invMassB = gBodies[bIdx].m_invMass;
+ Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia;
+
+ solveContact( ldsCs, posA, &linVelA, &angVelA, invMassA, invInertiaA,
+ posB, &linVelB, &angVelB, invMassB, invInertiaB );
+
+ if (gBodies[aIdx].m_invMass)
+ {
+ gBodies[aIdx].m_linVel = linVelA;
+ gBodies[aIdx].m_angVel = angVelA;
+ } else
+ {
+ gBodies[aIdx].m_linVel = mymake_float4(0,0,0,0);
+ gBodies[aIdx].m_angVel = mymake_float4(0,0,0,0);
+
+ }
+ if (gBodies[bIdx].m_invMass)
+ {
+ gBodies[bIdx].m_linVel = linVelB;
+ gBodies[bIdx].m_angVel = angVelB;
+ } else
+ {
+ gBodies[bIdx].m_linVel = mymake_float4(0,0,0,0);
+ gBodies[bIdx].m_angVel = mymake_float4(0,0,0,0);
+
+ }
+
+}
+
+
+
+typedef struct
+{
+ int m_valInt0;
+ int m_valInt1;
+ int m_valInt2;
+ int m_valInt3;
+
+ float m_val0;
+ float m_val1;
+ float m_val2;
+ float m_val3;
+} SolverDebugInfo;
+
+
+
+
+__kernel
+__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
+void BatchSolveKernelContact(__global Body* gBodies,
+ __global Shape* gShapes,
+ __global Constraint4* gConstraints,
+ __global int* gN,
+ __global int* gOffsets,
+ __global int* batchSizes,
+ int maxBatch1,
+ int cellBatch,
+ int4 nSplit
+ )
+{
+ //__local int ldsBatchIdx[WG_SIZE+1];
+ __local int ldsCurBatch;
+ __local int ldsNextBatch;
+ __local int ldsStart;
+
+ int lIdx = GET_LOCAL_IDX;
+ int wgIdx = GET_GROUP_IDX;
+
+// int gIdx = GET_GLOBAL_IDX;
+// debugInfo[gIdx].m_valInt0 = gIdx;
+ //debugInfo[gIdx].m_valInt1 = GET_GROUP_SIZE;
+
+
+
+
+ int zIdx = (wgIdx/((nSplit.x*nSplit.y)/4))*2+((cellBatch&4)>>2);
+ int remain= (wgIdx%((nSplit.x*nSplit.y)/4));
+ int yIdx = (remain/(nSplit.x/2))*2 + ((cellBatch&2)>>1);
+ int xIdx = (remain%(nSplit.x/2))*2 + (cellBatch&1);
+ int cellIdx = xIdx+yIdx*nSplit.x+zIdx*(nSplit.x*nSplit.y);
+
+ //int xIdx = (wgIdx/(nSplit/2))*2 + (bIdx&1);
+ //int yIdx = (wgIdx%(nSplit/2))*2 + (bIdx>>1);
+ //int cellIdx = xIdx+yIdx*nSplit;
+
+ if( gN[cellIdx] == 0 )
+ return;
+
+ int maxBatch = batchSizes[cellIdx];
+
+
+ const int start = gOffsets[cellIdx];
+ const int end = start + gN[cellIdx];
+
+
+
+
+ if( lIdx == 0 )
+ {
+ ldsCurBatch = 0;
+ ldsNextBatch = 0;
+ ldsStart = start;
+ }
+
+
+ GROUP_LDS_BARRIER;
+
+ int idx=ldsStart+lIdx;
+ while (ldsCurBatch < maxBatch)
+ {
+ for(; idx<end; )
+ {
+ if (gConstraints[idx].m_batchIdx == ldsCurBatch)
+ {
+ solveContactConstraint( gBodies, gShapes, &gConstraints[idx] );
+
+ idx+=64;
+ } else
+ {
+ break;
+ }
+ }
+ GROUP_LDS_BARRIER;
+
+ if( lIdx == 0 )
+ {
+ ldsCurBatch++;
+ }
+ GROUP_LDS_BARRIER;
+ }
+
+
+}
+
+
+
+__kernel void solveSingleContactKernel(__global Body* gBodies,
+ __global Shape* gShapes,
+ __global Constraint4* gConstraints,
+ int cellIdx,
+ int batchOffset,
+ int numConstraintsInBatch
+ )
+{
+
+ int index = get_global_id(0);
+ if (index < numConstraintsInBatch)
+ {
+ int idx=batchOffset+index;
+ solveContactConstraint( gBodies, gShapes, &gConstraints[idx] );
+ }
+}
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/solveContact.h b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/solveContact.h
new file mode 100644
index 0000000000..15a049992b
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/solveContact.h
@@ -0,0 +1,393 @@
+//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
+static const char* solveContactCL= \
+"/*\n"
+"Copyright (c) 2012 Advanced Micro Devices, Inc. \n"
+"This software is provided 'as-is', without any express or implied warranty.\n"
+"In no event will the authors be held liable for any damages arising from the use of this software.\n"
+"Permission is granted to anyone to use this software for any purpose, \n"
+"including commercial applications, and to alter it and redistribute it freely, \n"
+"subject to the following restrictions:\n"
+"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.\n"
+"2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
+"3. This notice may not be removed or altered from any source distribution.\n"
+"*/\n"
+"//Originally written by Takahiro Harada\n"
+"//#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
+"#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
+"#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
+"#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n"
+"#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n"
+"#ifdef cl_ext_atomic_counters_32\n"
+"#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n"
+"#else\n"
+"#define counter32_t volatile global int*\n"
+"#endif\n"
+"typedef unsigned int u32;\n"
+"typedef unsigned short u16;\n"
+"typedef unsigned char u8;\n"
+"#define GET_GROUP_IDX get_group_id(0)\n"
+"#define GET_LOCAL_IDX get_local_id(0)\n"
+"#define GET_GLOBAL_IDX get_global_id(0)\n"
+"#define GET_GROUP_SIZE get_local_size(0)\n"
+"#define GET_NUM_GROUPS get_num_groups(0)\n"
+"#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
+"#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
+"#define AtomInc(x) atom_inc(&(x))\n"
+"#define AtomInc1(x, out) out = atom_inc(&(x))\n"
+"#define AppendInc(x, out) out = atomic_inc(x)\n"
+"#define AtomAdd(x, value) atom_add(&(x), value)\n"
+"#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )\n"
+"#define AtomXhg(x, value) atom_xchg ( &(x), value )\n"
+"#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n"
+"#define mymake_float4 (float4)\n"
+"//#define make_float2 (float2)\n"
+"//#define make_uint4 (uint4)\n"
+"//#define make_int4 (int4)\n"
+"//#define make_uint2 (uint2)\n"
+"//#define make_int2 (int2)\n"
+"#define max2 max\n"
+"#define min2 min\n"
+"///////////////////////////////////////\n"
+"// Vector\n"
+"///////////////////////////////////////\n"
+"__inline\n"
+"float4 fastNormalize4(float4 v)\n"
+"{\n"
+" return fast_normalize(v);\n"
+"}\n"
+"__inline\n"
+"float4 cross3(float4 a, float4 b)\n"
+"{\n"
+" return cross(a,b);\n"
+"}\n"
+"__inline\n"
+"float dot3F4(float4 a, float4 b)\n"
+"{\n"
+" float4 a1 = mymake_float4(a.xyz,0.f);\n"
+" float4 b1 = mymake_float4(b.xyz,0.f);\n"
+" return dot(a1, b1);\n"
+"}\n"
+"__inline\n"
+"float4 normalize3(const float4 a)\n"
+"{\n"
+" float4 n = mymake_float4(a.x, a.y, a.z, 0.f);\n"
+" return fastNormalize4( n );\n"
+"// float length = sqrtf(dot3F4(a, a));\n"
+"// return 1.f/length * a;\n"
+"}\n"
+"///////////////////////////////////////\n"
+"// Matrix3x3\n"
+"///////////////////////////////////////\n"
+"typedef struct\n"
+"{\n"
+" float4 m_row[3];\n"
+"}Matrix3x3;\n"
+"__inline\n"
+"float4 mtMul1(Matrix3x3 a, float4 b);\n"
+"__inline\n"
+"float4 mtMul3(float4 a, Matrix3x3 b);\n"
+"__inline\n"
+"float4 mtMul1(Matrix3x3 a, float4 b)\n"
+"{\n"
+" float4 ans;\n"
+" ans.x = dot3F4( a.m_row[0], b );\n"
+" ans.y = dot3F4( a.m_row[1], b );\n"
+" ans.z = dot3F4( a.m_row[2], b );\n"
+" ans.w = 0.f;\n"
+" return ans;\n"
+"}\n"
+"__inline\n"
+"float4 mtMul3(float4 a, Matrix3x3 b)\n"
+"{\n"
+" float4 colx = mymake_float4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
+" float4 coly = mymake_float4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
+" float4 colz = mymake_float4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
+" float4 ans;\n"
+" ans.x = dot3F4( a, colx );\n"
+" ans.y = dot3F4( a, coly );\n"
+" ans.z = dot3F4( a, colz );\n"
+" return ans;\n"
+"}\n"
+"///////////////////////////////////////\n"
+"// Quaternion\n"
+"///////////////////////////////////////\n"
+"typedef float4 Quaternion;\n"
+"#define WG_SIZE 64\n"
+"typedef struct\n"
+"{\n"
+" float4 m_pos;\n"
+" Quaternion m_quat;\n"
+" float4 m_linVel;\n"
+" float4 m_angVel;\n"
+" u32 m_shapeIdx;\n"
+" float m_invMass;\n"
+" float m_restituitionCoeff;\n"
+" float m_frictionCoeff;\n"
+"} Body;\n"
+"typedef struct\n"
+"{\n"
+" Matrix3x3 m_invInertia;\n"
+" Matrix3x3 m_initInvInertia;\n"
+"} Shape;\n"
+"typedef struct\n"
+"{\n"
+" float4 m_linear;\n"
+" float4 m_worldPos[4];\n"
+" float4 m_center; \n"
+" float m_jacCoeffInv[4];\n"
+" float m_b[4];\n"
+" float m_appliedRambdaDt[4];\n"
+" float m_fJacCoeffInv[2]; \n"
+" float m_fAppliedRambdaDt[2]; \n"
+" u32 m_bodyA;\n"
+" u32 m_bodyB;\n"
+" int m_batchIdx;\n"
+" u32 m_paddings[1];\n"
+"} Constraint4;\n"
+"typedef struct\n"
+"{\n"
+" int m_nConstraints;\n"
+" int m_start;\n"
+" int m_batchIdx;\n"
+" int m_nSplit;\n"
+"// int m_paddings[1];\n"
+"} ConstBuffer;\n"
+"typedef struct\n"
+"{\n"
+" int m_solveFriction;\n"
+" int m_maxBatch; // long batch really kills the performance\n"
+" int m_batchIdx;\n"
+" int m_nSplit;\n"
+"// int m_paddings[1];\n"
+"} ConstBufferBatchSolve;\n"
+"void setLinearAndAngular( float4 n, float4 r0, float4 r1, float4* linear, float4* angular0, float4* angular1);\n"
+"void setLinearAndAngular( float4 n, float4 r0, float4 r1, float4* linear, float4* angular0, float4* angular1)\n"
+"{\n"
+" *linear = mymake_float4(-n.xyz,0.f);\n"
+" *angular0 = -cross3(r0, n);\n"
+" *angular1 = cross3(r1, n);\n"
+"}\n"
+"float calcRelVel( float4 l0, float4 l1, float4 a0, float4 a1, float4 linVel0, float4 angVel0, float4 linVel1, float4 angVel1 );\n"
+"float calcRelVel( float4 l0, float4 l1, float4 a0, float4 a1, float4 linVel0, float4 angVel0, float4 linVel1, float4 angVel1 )\n"
+"{\n"
+" return dot3F4(l0, linVel0) + dot3F4(a0, angVel0) + dot3F4(l1, linVel1) + dot3F4(a1, angVel1);\n"
+"}\n"
+"float calcJacCoeff(const float4 linear0, const float4 linear1, const float4 angular0, const float4 angular1,\n"
+" float invMass0, const Matrix3x3* invInertia0, float invMass1, const Matrix3x3* invInertia1);\n"
+"float calcJacCoeff(const float4 linear0, const float4 linear1, const float4 angular0, const float4 angular1,\n"
+" float invMass0, const Matrix3x3* invInertia0, float invMass1, const Matrix3x3* invInertia1)\n"
+"{\n"
+" // linear0,1 are normlized\n"
+" float jmj0 = invMass0;//dot3F4(linear0, linear0)*invMass0;\n"
+" float jmj1 = dot3F4(mtMul3(angular0,*invInertia0), angular0);\n"
+" float jmj2 = invMass1;//dot3F4(linear1, linear1)*invMass1;\n"
+" float jmj3 = dot3F4(mtMul3(angular1,*invInertia1), angular1);\n"
+" return -1.f/(jmj0+jmj1+jmj2+jmj3);\n"
+"}\n"
+"void solveContact(__global Constraint4* cs,\n"
+" float4 posA, float4* linVelA, float4* angVelA, float invMassA, Matrix3x3 invInertiaA,\n"
+" float4 posB, float4* linVelB, float4* angVelB, float invMassB, Matrix3x3 invInertiaB);\n"
+"void solveContact(__global Constraint4* cs,\n"
+" float4 posA, float4* linVelA, float4* angVelA, float invMassA, Matrix3x3 invInertiaA,\n"
+" float4 posB, float4* linVelB, float4* angVelB, float invMassB, Matrix3x3 invInertiaB)\n"
+"{\n"
+" float minRambdaDt = 0;\n"
+" float maxRambdaDt = FLT_MAX;\n"
+" for(int ic=0; ic<4; ic++)\n"
+" {\n"
+" if( cs->m_jacCoeffInv[ic] == 0.f ) continue;\n"
+" float4 angular0, angular1, linear;\n"
+" float4 r0 = cs->m_worldPos[ic] - posA;\n"
+" float4 r1 = cs->m_worldPos[ic] - posB;\n"
+" setLinearAndAngular( -cs->m_linear, r0, r1, &linear, &angular0, &angular1 );\n"
+" float rambdaDt = calcRelVel( cs->m_linear, -cs->m_linear, angular0, angular1, \n"
+" *linVelA, *angVelA, *linVelB, *angVelB ) + cs->m_b[ic];\n"
+" rambdaDt *= cs->m_jacCoeffInv[ic];\n"
+" {\n"
+" float prevSum = cs->m_appliedRambdaDt[ic];\n"
+" float updated = prevSum;\n"
+" updated += rambdaDt;\n"
+" updated = max2( updated, minRambdaDt );\n"
+" updated = min2( updated, maxRambdaDt );\n"
+" rambdaDt = updated - prevSum;\n"
+" cs->m_appliedRambdaDt[ic] = updated;\n"
+" }\n"
+" float4 linImp0 = invMassA*linear*rambdaDt;\n"
+" float4 linImp1 = invMassB*(-linear)*rambdaDt;\n"
+" float4 angImp0 = mtMul1(invInertiaA, angular0)*rambdaDt;\n"
+" float4 angImp1 = mtMul1(invInertiaB, angular1)*rambdaDt;\n"
+" *linVelA += linImp0;\n"
+" *angVelA += angImp0;\n"
+" *linVelB += linImp1;\n"
+" *angVelB += angImp1;\n"
+" }\n"
+"}\n"
+"void btPlaneSpace1 (const float4* n, float4* p, float4* q);\n"
+" void btPlaneSpace1 (const float4* n, float4* p, float4* q)\n"
+"{\n"
+" if (fabs(n[0].z) > 0.70710678f) {\n"
+" // choose p in y-z plane\n"
+" float a = n[0].y*n[0].y + n[0].z*n[0].z;\n"
+" float k = 1.f/sqrt(a);\n"
+" p[0].x = 0;\n"
+" p[0].y = -n[0].z*k;\n"
+" p[0].z = n[0].y*k;\n"
+" // set q = n x p\n"
+" q[0].x = a*k;\n"
+" q[0].y = -n[0].x*p[0].z;\n"
+" q[0].z = n[0].x*p[0].y;\n"
+" }\n"
+" else {\n"
+" // choose p in x-y plane\n"
+" float a = n[0].x*n[0].x + n[0].y*n[0].y;\n"
+" float k = 1.f/sqrt(a);\n"
+" p[0].x = -n[0].y*k;\n"
+" p[0].y = n[0].x*k;\n"
+" p[0].z = 0;\n"
+" // set q = n x p\n"
+" q[0].x = -n[0].z*p[0].y;\n"
+" q[0].y = n[0].z*p[0].x;\n"
+" q[0].z = a*k;\n"
+" }\n"
+"}\n"
+"void solveContactConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs);\n"
+"void solveContactConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs)\n"
+"{\n"
+" //float frictionCoeff = ldsCs[0].m_linear.w;\n"
+" int aIdx = ldsCs[0].m_bodyA;\n"
+" int bIdx = ldsCs[0].m_bodyB;\n"
+" float4 posA = gBodies[aIdx].m_pos;\n"
+" float4 linVelA = gBodies[aIdx].m_linVel;\n"
+" float4 angVelA = gBodies[aIdx].m_angVel;\n"
+" float invMassA = gBodies[aIdx].m_invMass;\n"
+" Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia;\n"
+" float4 posB = gBodies[bIdx].m_pos;\n"
+" float4 linVelB = gBodies[bIdx].m_linVel;\n"
+" float4 angVelB = gBodies[bIdx].m_angVel;\n"
+" float invMassB = gBodies[bIdx].m_invMass;\n"
+" Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia;\n"
+" solveContact( ldsCs, posA, &linVelA, &angVelA, invMassA, invInertiaA,\n"
+" posB, &linVelB, &angVelB, invMassB, invInertiaB );\n"
+" if (gBodies[aIdx].m_invMass)\n"
+" {\n"
+" gBodies[aIdx].m_linVel = linVelA;\n"
+" gBodies[aIdx].m_angVel = angVelA;\n"
+" } else\n"
+" {\n"
+" gBodies[aIdx].m_linVel = mymake_float4(0,0,0,0);\n"
+" gBodies[aIdx].m_angVel = mymake_float4(0,0,0,0);\n"
+" \n"
+" }\n"
+" if (gBodies[bIdx].m_invMass)\n"
+" {\n"
+" gBodies[bIdx].m_linVel = linVelB;\n"
+" gBodies[bIdx].m_angVel = angVelB;\n"
+" } else\n"
+" {\n"
+" gBodies[bIdx].m_linVel = mymake_float4(0,0,0,0);\n"
+" gBodies[bIdx].m_angVel = mymake_float4(0,0,0,0);\n"
+" \n"
+" }\n"
+"}\n"
+"typedef struct \n"
+"{\n"
+" int m_valInt0;\n"
+" int m_valInt1;\n"
+" int m_valInt2;\n"
+" int m_valInt3;\n"
+" float m_val0;\n"
+" float m_val1;\n"
+" float m_val2;\n"
+" float m_val3;\n"
+"} SolverDebugInfo;\n"
+"__kernel\n"
+"__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+"void BatchSolveKernelContact(__global Body* gBodies,\n"
+" __global Shape* gShapes,\n"
+" __global Constraint4* gConstraints,\n"
+" __global int* gN,\n"
+" __global int* gOffsets,\n"
+" __global int* batchSizes,\n"
+" int maxBatch1,\n"
+" int cellBatch,\n"
+" int4 nSplit\n"
+" )\n"
+"{\n"
+" //__local int ldsBatchIdx[WG_SIZE+1];\n"
+" __local int ldsCurBatch;\n"
+" __local int ldsNextBatch;\n"
+" __local int ldsStart;\n"
+" int lIdx = GET_LOCAL_IDX;\n"
+" int wgIdx = GET_GROUP_IDX;\n"
+"// int gIdx = GET_GLOBAL_IDX;\n"
+"// debugInfo[gIdx].m_valInt0 = gIdx;\n"
+" //debugInfo[gIdx].m_valInt1 = GET_GROUP_SIZE;\n"
+" \n"
+" \n"
+" int zIdx = (wgIdx/((nSplit.x*nSplit.y)/4))*2+((cellBatch&4)>>2);\n"
+" int remain= (wgIdx%((nSplit.x*nSplit.y)/4));\n"
+" int yIdx = (remain/(nSplit.x/2))*2 + ((cellBatch&2)>>1);\n"
+" int xIdx = (remain%(nSplit.x/2))*2 + (cellBatch&1);\n"
+" int cellIdx = xIdx+yIdx*nSplit.x+zIdx*(nSplit.x*nSplit.y);\n"
+" //int xIdx = (wgIdx/(nSplit/2))*2 + (bIdx&1);\n"
+" //int yIdx = (wgIdx%(nSplit/2))*2 + (bIdx>>1);\n"
+" //int cellIdx = xIdx+yIdx*nSplit;\n"
+" \n"
+" if( gN[cellIdx] == 0 ) \n"
+" return;\n"
+" int maxBatch = batchSizes[cellIdx];\n"
+" \n"
+" \n"
+" const int start = gOffsets[cellIdx];\n"
+" const int end = start + gN[cellIdx];\n"
+" \n"
+" \n"
+" \n"
+" if( lIdx == 0 )\n"
+" {\n"
+" ldsCurBatch = 0;\n"
+" ldsNextBatch = 0;\n"
+" ldsStart = start;\n"
+" }\n"
+" GROUP_LDS_BARRIER;\n"
+" int idx=ldsStart+lIdx;\n"
+" while (ldsCurBatch < maxBatch)\n"
+" {\n"
+" for(; idx<end; )\n"
+" {\n"
+" if (gConstraints[idx].m_batchIdx == ldsCurBatch)\n"
+" {\n"
+" solveContactConstraint( gBodies, gShapes, &gConstraints[idx] );\n"
+" idx+=64;\n"
+" } else\n"
+" {\n"
+" break;\n"
+" }\n"
+" }\n"
+" GROUP_LDS_BARRIER;\n"
+" \n"
+" if( lIdx == 0 )\n"
+" {\n"
+" ldsCurBatch++;\n"
+" }\n"
+" GROUP_LDS_BARRIER;\n"
+" }\n"
+" \n"
+" \n"
+"}\n"
+"__kernel void solveSingleContactKernel(__global Body* gBodies,\n"
+" __global Shape* gShapes,\n"
+" __global Constraint4* gConstraints,\n"
+" int cellIdx,\n"
+" int batchOffset,\n"
+" int numConstraintsInBatch\n"
+" )\n"
+"{\n"
+" int index = get_global_id(0);\n"
+" if (index < numConstraintsInBatch)\n"
+" {\n"
+" int idx=batchOffset+index;\n"
+" solveContactConstraint( gBodies, gShapes, &gConstraints[idx] );\n"
+" } \n"
+"}\n"
+;
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/solveFriction.cl b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/solveFriction.cl
new file mode 100644
index 0000000000..1d70fbbae3
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/solveFriction.cl
@@ -0,0 +1,527 @@
+/*
+Copyright (c) 2012 Advanced Micro Devices, Inc.
+
+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.
+*/
+//Originally written by Takahiro Harada
+
+
+//#pragma OPENCL EXTENSION cl_amd_printf : enable
+#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable
+
+
+#ifdef cl_ext_atomic_counters_32
+#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable
+#else
+#define counter32_t volatile global int*
+#endif
+
+typedef unsigned int u32;
+typedef unsigned short u16;
+typedef unsigned char u8;
+
+#define GET_GROUP_IDX get_group_id(0)
+#define GET_LOCAL_IDX get_local_id(0)
+#define GET_GLOBAL_IDX get_global_id(0)
+#define GET_GROUP_SIZE get_local_size(0)
+#define GET_NUM_GROUPS get_num_groups(0)
+#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)
+#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)
+#define AtomInc(x) atom_inc(&(x))
+#define AtomInc1(x, out) out = atom_inc(&(x))
+#define AppendInc(x, out) out = atomic_inc(x)
+#define AtomAdd(x, value) atom_add(&(x), value)
+#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )
+#define AtomXhg(x, value) atom_xchg ( &(x), value )
+
+
+#define SELECT_UINT4( b, a, condition ) select( b,a,condition )
+
+#define mymake_float4 (float4)
+//#define make_float2 (float2)
+//#define make_uint4 (uint4)
+//#define make_int4 (int4)
+//#define make_uint2 (uint2)
+//#define make_int2 (int2)
+
+
+#define max2 max
+#define min2 min
+
+
+///////////////////////////////////////
+// Vector
+///////////////////////////////////////
+
+
+
+
+__inline
+float4 fastNormalize4(float4 v)
+{
+ return fast_normalize(v);
+}
+
+
+
+__inline
+float4 cross3(float4 a, float4 b)
+{
+ return cross(a,b);
+}
+
+__inline
+float dot3F4(float4 a, float4 b)
+{
+ float4 a1 = mymake_float4(a.xyz,0.f);
+ float4 b1 = mymake_float4(b.xyz,0.f);
+ return dot(a1, b1);
+}
+
+
+
+
+__inline
+float4 normalize3(const float4 a)
+{
+ float4 n = mymake_float4(a.x, a.y, a.z, 0.f);
+ return fastNormalize4( n );
+// float length = sqrtf(dot3F4(a, a));
+// return 1.f/length * a;
+}
+
+
+
+
+///////////////////////////////////////
+// Matrix3x3
+///////////////////////////////////////
+
+typedef struct
+{
+ float4 m_row[3];
+}Matrix3x3;
+
+
+
+
+
+
+__inline
+float4 mtMul1(Matrix3x3 a, float4 b);
+
+__inline
+float4 mtMul3(float4 a, Matrix3x3 b);
+
+
+
+
+__inline
+float4 mtMul1(Matrix3x3 a, float4 b)
+{
+ float4 ans;
+ ans.x = dot3F4( a.m_row[0], b );
+ ans.y = dot3F4( a.m_row[1], b );
+ ans.z = dot3F4( a.m_row[2], b );
+ ans.w = 0.f;
+ return ans;
+}
+
+__inline
+float4 mtMul3(float4 a, Matrix3x3 b)
+{
+ float4 colx = mymake_float4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);
+ float4 coly = mymake_float4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);
+ float4 colz = mymake_float4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);
+
+ float4 ans;
+ ans.x = dot3F4( a, colx );
+ ans.y = dot3F4( a, coly );
+ ans.z = dot3F4( a, colz );
+ return ans;
+}
+
+///////////////////////////////////////
+// Quaternion
+///////////////////////////////////////
+
+typedef float4 Quaternion;
+
+
+
+
+
+
+
+#define WG_SIZE 64
+
+typedef struct
+{
+ float4 m_pos;
+ Quaternion m_quat;
+ float4 m_linVel;
+ float4 m_angVel;
+
+ u32 m_shapeIdx;
+ float m_invMass;
+ float m_restituitionCoeff;
+ float m_frictionCoeff;
+} Body;
+
+typedef struct
+{
+ Matrix3x3 m_invInertia;
+ Matrix3x3 m_initInvInertia;
+} Shape;
+
+typedef struct
+{
+ float4 m_linear;
+ float4 m_worldPos[4];
+ float4 m_center;
+ float m_jacCoeffInv[4];
+ float m_b[4];
+ float m_appliedRambdaDt[4];
+
+ float m_fJacCoeffInv[2];
+ float m_fAppliedRambdaDt[2];
+
+ u32 m_bodyA;
+ u32 m_bodyB;
+
+ int m_batchIdx;
+ u32 m_paddings[1];
+} Constraint4;
+
+
+
+typedef struct
+{
+ int m_nConstraints;
+ int m_start;
+ int m_batchIdx;
+ int m_nSplit;
+// int m_paddings[1];
+} ConstBuffer;
+
+typedef struct
+{
+ int m_solveFriction;
+ int m_maxBatch; // long batch really kills the performance
+ int m_batchIdx;
+ int m_nSplit;
+// int m_paddings[1];
+} ConstBufferBatchSolve;
+
+void setLinearAndAngular( float4 n, float4 r0, float4 r1, float4* linear, float4* angular0, float4* angular1);
+
+void setLinearAndAngular( float4 n, float4 r0, float4 r1, float4* linear, float4* angular0, float4* angular1)
+{
+ *linear = mymake_float4(-n.xyz,0.f);
+ *angular0 = -cross3(r0, n);
+ *angular1 = cross3(r1, n);
+}
+
+float calcRelVel( float4 l0, float4 l1, float4 a0, float4 a1, float4 linVel0, float4 angVel0, float4 linVel1, float4 angVel1 );
+
+float calcRelVel( float4 l0, float4 l1, float4 a0, float4 a1, float4 linVel0, float4 angVel0, float4 linVel1, float4 angVel1 )
+{
+ return dot3F4(l0, linVel0) + dot3F4(a0, angVel0) + dot3F4(l1, linVel1) + dot3F4(a1, angVel1);
+}
+
+
+float calcJacCoeff(const float4 linear0, const float4 linear1, const float4 angular0, const float4 angular1,
+ float invMass0, const Matrix3x3* invInertia0, float invMass1, const Matrix3x3* invInertia1);
+
+float calcJacCoeff(const float4 linear0, const float4 linear1, const float4 angular0, const float4 angular1,
+ float invMass0, const Matrix3x3* invInertia0, float invMass1, const Matrix3x3* invInertia1)
+{
+ // linear0,1 are normlized
+ float jmj0 = invMass0;//dot3F4(linear0, linear0)*invMass0;
+ float jmj1 = dot3F4(mtMul3(angular0,*invInertia0), angular0);
+ float jmj2 = invMass1;//dot3F4(linear1, linear1)*invMass1;
+ float jmj3 = dot3F4(mtMul3(angular1,*invInertia1), angular1);
+ return -1.f/(jmj0+jmj1+jmj2+jmj3);
+}
+void btPlaneSpace1 (const float4* n, float4* p, float4* q);
+ void btPlaneSpace1 (const float4* n, float4* p, float4* q)
+{
+ if (fabs(n[0].z) > 0.70710678f) {
+ // choose p in y-z plane
+ float a = n[0].y*n[0].y + n[0].z*n[0].z;
+ float k = 1.f/sqrt(a);
+ p[0].x = 0;
+ p[0].y = -n[0].z*k;
+ p[0].z = n[0].y*k;
+ // set q = n x p
+ q[0].x = a*k;
+ q[0].y = -n[0].x*p[0].z;
+ q[0].z = n[0].x*p[0].y;
+ }
+ else {
+ // choose p in x-y plane
+ float a = n[0].x*n[0].x + n[0].y*n[0].y;
+ float k = 1.f/sqrt(a);
+ p[0].x = -n[0].y*k;
+ p[0].y = n[0].x*k;
+ p[0].z = 0;
+ // set q = n x p
+ q[0].x = -n[0].z*p[0].y;
+ q[0].y = n[0].z*p[0].x;
+ q[0].z = a*k;
+ }
+}
+
+
+void solveFrictionConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs);
+void solveFrictionConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs)
+{
+ float frictionCoeff = ldsCs[0].m_linear.w;
+ int aIdx = ldsCs[0].m_bodyA;
+ int bIdx = ldsCs[0].m_bodyB;
+
+
+ float4 posA = gBodies[aIdx].m_pos;
+ float4 linVelA = gBodies[aIdx].m_linVel;
+ float4 angVelA = gBodies[aIdx].m_angVel;
+ float invMassA = gBodies[aIdx].m_invMass;
+ Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia;
+
+ float4 posB = gBodies[bIdx].m_pos;
+ float4 linVelB = gBodies[bIdx].m_linVel;
+ float4 angVelB = gBodies[bIdx].m_angVel;
+ float invMassB = gBodies[bIdx].m_invMass;
+ Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia;
+
+
+ {
+ float maxRambdaDt[4] = {FLT_MAX,FLT_MAX,FLT_MAX,FLT_MAX};
+ float minRambdaDt[4] = {0.f,0.f,0.f,0.f};
+
+ float sum = 0;
+ for(int j=0; j<4; j++)
+ {
+ sum +=ldsCs[0].m_appliedRambdaDt[j];
+ }
+ frictionCoeff = 0.7f;
+ for(int j=0; j<4; j++)
+ {
+ maxRambdaDt[j] = frictionCoeff*sum;
+ minRambdaDt[j] = -maxRambdaDt[j];
+ }
+
+
+// solveFriction( ldsCs, posA, &linVelA, &angVelA, invMassA, invInertiaA,
+// posB, &linVelB, &angVelB, invMassB, invInertiaB, maxRambdaDt, minRambdaDt );
+
+
+ {
+
+ __global Constraint4* cs = ldsCs;
+
+ if( cs->m_fJacCoeffInv[0] == 0 && cs->m_fJacCoeffInv[0] == 0 ) return;
+ const float4 center = cs->m_center;
+
+ float4 n = -cs->m_linear;
+
+ float4 tangent[2];
+ btPlaneSpace1(&n,&tangent[0],&tangent[1]);
+ float4 angular0, angular1, linear;
+ float4 r0 = center - posA;
+ float4 r1 = center - posB;
+ for(int i=0; i<2; i++)
+ {
+ setLinearAndAngular( tangent[i], r0, r1, &linear, &angular0, &angular1 );
+ float rambdaDt = calcRelVel(linear, -linear, angular0, angular1,
+ linVelA, angVelA, linVelB, angVelB );
+ rambdaDt *= cs->m_fJacCoeffInv[i];
+
+ {
+ float prevSum = cs->m_fAppliedRambdaDt[i];
+ float updated = prevSum;
+ updated += rambdaDt;
+ updated = max2( updated, minRambdaDt[i] );
+ updated = min2( updated, maxRambdaDt[i] );
+ rambdaDt = updated - prevSum;
+ cs->m_fAppliedRambdaDt[i] = updated;
+ }
+
+ float4 linImp0 = invMassA*linear*rambdaDt;
+ float4 linImp1 = invMassB*(-linear)*rambdaDt;
+ float4 angImp0 = mtMul1(invInertiaA, angular0)*rambdaDt;
+ float4 angImp1 = mtMul1(invInertiaB, angular1)*rambdaDt;
+
+ linVelA += linImp0;
+ angVelA += angImp0;
+ linVelB += linImp1;
+ angVelB += angImp1;
+ }
+ { // angular damping for point constraint
+ float4 ab = normalize3( posB - posA );
+ float4 ac = normalize3( center - posA );
+ if( dot3F4( ab, ac ) > 0.95f || (invMassA == 0.f || invMassB == 0.f))
+ {
+ float angNA = dot3F4( n, angVelA );
+ float angNB = dot3F4( n, angVelB );
+
+ angVelA -= (angNA*0.1f)*n;
+ angVelB -= (angNB*0.1f)*n;
+ }
+ }
+ }
+
+
+
+ }
+
+ if (gBodies[aIdx].m_invMass)
+ {
+ gBodies[aIdx].m_linVel = linVelA;
+ gBodies[aIdx].m_angVel = angVelA;
+ } else
+ {
+ gBodies[aIdx].m_linVel = mymake_float4(0,0,0,0);
+ gBodies[aIdx].m_angVel = mymake_float4(0,0,0,0);
+ }
+ if (gBodies[bIdx].m_invMass)
+ {
+ gBodies[bIdx].m_linVel = linVelB;
+ gBodies[bIdx].m_angVel = angVelB;
+ } else
+ {
+ gBodies[bIdx].m_linVel = mymake_float4(0,0,0,0);
+ gBodies[bIdx].m_angVel = mymake_float4(0,0,0,0);
+ }
+
+
+}
+
+typedef struct
+{
+ int m_valInt0;
+ int m_valInt1;
+ int m_valInt2;
+ int m_valInt3;
+
+ float m_val0;
+ float m_val1;
+ float m_val2;
+ float m_val3;
+} SolverDebugInfo;
+
+
+
+
+__kernel
+__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
+void BatchSolveKernelFriction(__global Body* gBodies,
+ __global Shape* gShapes,
+ __global Constraint4* gConstraints,
+ __global int* gN,
+ __global int* gOffsets,
+ __global int* batchSizes,
+ int maxBatch1,
+ int cellBatch,
+ int4 nSplit
+ )
+{
+ //__local int ldsBatchIdx[WG_SIZE+1];
+ __local int ldsCurBatch;
+ __local int ldsNextBatch;
+ __local int ldsStart;
+
+ int lIdx = GET_LOCAL_IDX;
+ int wgIdx = GET_GROUP_IDX;
+
+// int gIdx = GET_GLOBAL_IDX;
+// debugInfo[gIdx].m_valInt0 = gIdx;
+ //debugInfo[gIdx].m_valInt1 = GET_GROUP_SIZE;
+
+
+ int zIdx = (wgIdx/((nSplit.x*nSplit.y)/4))*2+((cellBatch&4)>>2);
+ int remain= (wgIdx%((nSplit.x*nSplit.y)/4));
+ int yIdx = (remain/(nSplit.x/2))*2 + ((cellBatch&2)>>1);
+ int xIdx = (remain%(nSplit.x/2))*2 + (cellBatch&1);
+ int cellIdx = xIdx+yIdx*nSplit.x+zIdx*(nSplit.x*nSplit.y);
+
+
+ if( gN[cellIdx] == 0 )
+ return;
+
+ int maxBatch = batchSizes[cellIdx];
+
+ const int start = gOffsets[cellIdx];
+ const int end = start + gN[cellIdx];
+
+
+ if( lIdx == 0 )
+ {
+ ldsCurBatch = 0;
+ ldsNextBatch = 0;
+ ldsStart = start;
+ }
+
+
+ GROUP_LDS_BARRIER;
+
+ int idx=ldsStart+lIdx;
+ while (ldsCurBatch < maxBatch)
+ {
+ for(; idx<end; )
+ {
+ if (gConstraints[idx].m_batchIdx == ldsCurBatch)
+ {
+
+ solveFrictionConstraint( gBodies, gShapes, &gConstraints[idx] );
+
+ idx+=64;
+ } else
+ {
+ break;
+ }
+ }
+ GROUP_LDS_BARRIER;
+ if( lIdx == 0 )
+ {
+ ldsCurBatch++;
+ }
+ GROUP_LDS_BARRIER;
+ }
+
+
+}
+
+
+
+
+
+
+__kernel void solveSingleFrictionKernel(__global Body* gBodies,
+ __global Shape* gShapes,
+ __global Constraint4* gConstraints,
+ int cellIdx,
+ int batchOffset,
+ int numConstraintsInBatch
+ )
+{
+
+ int index = get_global_id(0);
+ if (index < numConstraintsInBatch)
+ {
+
+ int idx=batchOffset+index;
+
+ solveFrictionConstraint( gBodies, gShapes, &gConstraints[idx] );
+ }
+} \ No newline at end of file
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/solveFriction.h b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/solveFriction.h
new file mode 100644
index 0000000000..eb58674f22
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/solveFriction.h
@@ -0,0 +1,421 @@
+//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
+static const char* solveFrictionCL= \
+"/*\n"
+"Copyright (c) 2012 Advanced Micro Devices, Inc. \n"
+"This software is provided 'as-is', without any express or implied warranty.\n"
+"In no event will the authors be held liable for any damages arising from the use of this software.\n"
+"Permission is granted to anyone to use this software for any purpose, \n"
+"including commercial applications, and to alter it and redistribute it freely, \n"
+"subject to the following restrictions:\n"
+"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.\n"
+"2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
+"3. This notice may not be removed or altered from any source distribution.\n"
+"*/\n"
+"//Originally written by Takahiro Harada\n"
+"//#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
+"#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
+"#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
+"#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n"
+"#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n"
+"#ifdef cl_ext_atomic_counters_32\n"
+"#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n"
+"#else\n"
+"#define counter32_t volatile global int*\n"
+"#endif\n"
+"typedef unsigned int u32;\n"
+"typedef unsigned short u16;\n"
+"typedef unsigned char u8;\n"
+"#define GET_GROUP_IDX get_group_id(0)\n"
+"#define GET_LOCAL_IDX get_local_id(0)\n"
+"#define GET_GLOBAL_IDX get_global_id(0)\n"
+"#define GET_GROUP_SIZE get_local_size(0)\n"
+"#define GET_NUM_GROUPS get_num_groups(0)\n"
+"#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
+"#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
+"#define AtomInc(x) atom_inc(&(x))\n"
+"#define AtomInc1(x, out) out = atom_inc(&(x))\n"
+"#define AppendInc(x, out) out = atomic_inc(x)\n"
+"#define AtomAdd(x, value) atom_add(&(x), value)\n"
+"#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )\n"
+"#define AtomXhg(x, value) atom_xchg ( &(x), value )\n"
+"#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n"
+"#define mymake_float4 (float4)\n"
+"//#define make_float2 (float2)\n"
+"//#define make_uint4 (uint4)\n"
+"//#define make_int4 (int4)\n"
+"//#define make_uint2 (uint2)\n"
+"//#define make_int2 (int2)\n"
+"#define max2 max\n"
+"#define min2 min\n"
+"///////////////////////////////////////\n"
+"// Vector\n"
+"///////////////////////////////////////\n"
+"__inline\n"
+"float4 fastNormalize4(float4 v)\n"
+"{\n"
+" return fast_normalize(v);\n"
+"}\n"
+"__inline\n"
+"float4 cross3(float4 a, float4 b)\n"
+"{\n"
+" return cross(a,b);\n"
+"}\n"
+"__inline\n"
+"float dot3F4(float4 a, float4 b)\n"
+"{\n"
+" float4 a1 = mymake_float4(a.xyz,0.f);\n"
+" float4 b1 = mymake_float4(b.xyz,0.f);\n"
+" return dot(a1, b1);\n"
+"}\n"
+"__inline\n"
+"float4 normalize3(const float4 a)\n"
+"{\n"
+" float4 n = mymake_float4(a.x, a.y, a.z, 0.f);\n"
+" return fastNormalize4( n );\n"
+"// float length = sqrtf(dot3F4(a, a));\n"
+"// return 1.f/length * a;\n"
+"}\n"
+"///////////////////////////////////////\n"
+"// Matrix3x3\n"
+"///////////////////////////////////////\n"
+"typedef struct\n"
+"{\n"
+" float4 m_row[3];\n"
+"}Matrix3x3;\n"
+"__inline\n"
+"float4 mtMul1(Matrix3x3 a, float4 b);\n"
+"__inline\n"
+"float4 mtMul3(float4 a, Matrix3x3 b);\n"
+"__inline\n"
+"float4 mtMul1(Matrix3x3 a, float4 b)\n"
+"{\n"
+" float4 ans;\n"
+" ans.x = dot3F4( a.m_row[0], b );\n"
+" ans.y = dot3F4( a.m_row[1], b );\n"
+" ans.z = dot3F4( a.m_row[2], b );\n"
+" ans.w = 0.f;\n"
+" return ans;\n"
+"}\n"
+"__inline\n"
+"float4 mtMul3(float4 a, Matrix3x3 b)\n"
+"{\n"
+" float4 colx = mymake_float4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
+" float4 coly = mymake_float4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
+" float4 colz = mymake_float4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
+" float4 ans;\n"
+" ans.x = dot3F4( a, colx );\n"
+" ans.y = dot3F4( a, coly );\n"
+" ans.z = dot3F4( a, colz );\n"
+" return ans;\n"
+"}\n"
+"///////////////////////////////////////\n"
+"// Quaternion\n"
+"///////////////////////////////////////\n"
+"typedef float4 Quaternion;\n"
+"#define WG_SIZE 64\n"
+"typedef struct\n"
+"{\n"
+" float4 m_pos;\n"
+" Quaternion m_quat;\n"
+" float4 m_linVel;\n"
+" float4 m_angVel;\n"
+" u32 m_shapeIdx;\n"
+" float m_invMass;\n"
+" float m_restituitionCoeff;\n"
+" float m_frictionCoeff;\n"
+"} Body;\n"
+"typedef struct\n"
+"{\n"
+" Matrix3x3 m_invInertia;\n"
+" Matrix3x3 m_initInvInertia;\n"
+"} Shape;\n"
+"typedef struct\n"
+"{\n"
+" float4 m_linear;\n"
+" float4 m_worldPos[4];\n"
+" float4 m_center; \n"
+" float m_jacCoeffInv[4];\n"
+" float m_b[4];\n"
+" float m_appliedRambdaDt[4];\n"
+" float m_fJacCoeffInv[2]; \n"
+" float m_fAppliedRambdaDt[2]; \n"
+" u32 m_bodyA;\n"
+" u32 m_bodyB;\n"
+" int m_batchIdx;\n"
+" u32 m_paddings[1];\n"
+"} Constraint4;\n"
+"typedef struct\n"
+"{\n"
+" int m_nConstraints;\n"
+" int m_start;\n"
+" int m_batchIdx;\n"
+" int m_nSplit;\n"
+"// int m_paddings[1];\n"
+"} ConstBuffer;\n"
+"typedef struct\n"
+"{\n"
+" int m_solveFriction;\n"
+" int m_maxBatch; // long batch really kills the performance\n"
+" int m_batchIdx;\n"
+" int m_nSplit;\n"
+"// int m_paddings[1];\n"
+"} ConstBufferBatchSolve;\n"
+"void setLinearAndAngular( float4 n, float4 r0, float4 r1, float4* linear, float4* angular0, float4* angular1);\n"
+"void setLinearAndAngular( float4 n, float4 r0, float4 r1, float4* linear, float4* angular0, float4* angular1)\n"
+"{\n"
+" *linear = mymake_float4(-n.xyz,0.f);\n"
+" *angular0 = -cross3(r0, n);\n"
+" *angular1 = cross3(r1, n);\n"
+"}\n"
+"float calcRelVel( float4 l0, float4 l1, float4 a0, float4 a1, float4 linVel0, float4 angVel0, float4 linVel1, float4 angVel1 );\n"
+"float calcRelVel( float4 l0, float4 l1, float4 a0, float4 a1, float4 linVel0, float4 angVel0, float4 linVel1, float4 angVel1 )\n"
+"{\n"
+" return dot3F4(l0, linVel0) + dot3F4(a0, angVel0) + dot3F4(l1, linVel1) + dot3F4(a1, angVel1);\n"
+"}\n"
+"float calcJacCoeff(const float4 linear0, const float4 linear1, const float4 angular0, const float4 angular1,\n"
+" float invMass0, const Matrix3x3* invInertia0, float invMass1, const Matrix3x3* invInertia1);\n"
+"float calcJacCoeff(const float4 linear0, const float4 linear1, const float4 angular0, const float4 angular1,\n"
+" float invMass0, const Matrix3x3* invInertia0, float invMass1, const Matrix3x3* invInertia1)\n"
+"{\n"
+" // linear0,1 are normlized\n"
+" float jmj0 = invMass0;//dot3F4(linear0, linear0)*invMass0;\n"
+" float jmj1 = dot3F4(mtMul3(angular0,*invInertia0), angular0);\n"
+" float jmj2 = invMass1;//dot3F4(linear1, linear1)*invMass1;\n"
+" float jmj3 = dot3F4(mtMul3(angular1,*invInertia1), angular1);\n"
+" return -1.f/(jmj0+jmj1+jmj2+jmj3);\n"
+"}\n"
+"void btPlaneSpace1 (const float4* n, float4* p, float4* q);\n"
+" void btPlaneSpace1 (const float4* n, float4* p, float4* q)\n"
+"{\n"
+" if (fabs(n[0].z) > 0.70710678f) {\n"
+" // choose p in y-z plane\n"
+" float a = n[0].y*n[0].y + n[0].z*n[0].z;\n"
+" float k = 1.f/sqrt(a);\n"
+" p[0].x = 0;\n"
+" p[0].y = -n[0].z*k;\n"
+" p[0].z = n[0].y*k;\n"
+" // set q = n x p\n"
+" q[0].x = a*k;\n"
+" q[0].y = -n[0].x*p[0].z;\n"
+" q[0].z = n[0].x*p[0].y;\n"
+" }\n"
+" else {\n"
+" // choose p in x-y plane\n"
+" float a = n[0].x*n[0].x + n[0].y*n[0].y;\n"
+" float k = 1.f/sqrt(a);\n"
+" p[0].x = -n[0].y*k;\n"
+" p[0].y = n[0].x*k;\n"
+" p[0].z = 0;\n"
+" // set q = n x p\n"
+" q[0].x = -n[0].z*p[0].y;\n"
+" q[0].y = n[0].z*p[0].x;\n"
+" q[0].z = a*k;\n"
+" }\n"
+"}\n"
+"void solveFrictionConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs);\n"
+"void solveFrictionConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs)\n"
+"{\n"
+" float frictionCoeff = ldsCs[0].m_linear.w;\n"
+" int aIdx = ldsCs[0].m_bodyA;\n"
+" int bIdx = ldsCs[0].m_bodyB;\n"
+" float4 posA = gBodies[aIdx].m_pos;\n"
+" float4 linVelA = gBodies[aIdx].m_linVel;\n"
+" float4 angVelA = gBodies[aIdx].m_angVel;\n"
+" float invMassA = gBodies[aIdx].m_invMass;\n"
+" Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia;\n"
+" float4 posB = gBodies[bIdx].m_pos;\n"
+" float4 linVelB = gBodies[bIdx].m_linVel;\n"
+" float4 angVelB = gBodies[bIdx].m_angVel;\n"
+" float invMassB = gBodies[bIdx].m_invMass;\n"
+" Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia;\n"
+" \n"
+" {\n"
+" float maxRambdaDt[4] = {FLT_MAX,FLT_MAX,FLT_MAX,FLT_MAX};\n"
+" float minRambdaDt[4] = {0.f,0.f,0.f,0.f};\n"
+" float sum = 0;\n"
+" for(int j=0; j<4; j++)\n"
+" {\n"
+" sum +=ldsCs[0].m_appliedRambdaDt[j];\n"
+" }\n"
+" frictionCoeff = 0.7f;\n"
+" for(int j=0; j<4; j++)\n"
+" {\n"
+" maxRambdaDt[j] = frictionCoeff*sum;\n"
+" minRambdaDt[j] = -maxRambdaDt[j];\n"
+" }\n"
+" \n"
+"// solveFriction( ldsCs, posA, &linVelA, &angVelA, invMassA, invInertiaA,\n"
+"// posB, &linVelB, &angVelB, invMassB, invInertiaB, maxRambdaDt, minRambdaDt );\n"
+" \n"
+" \n"
+" {\n"
+" \n"
+" __global Constraint4* cs = ldsCs;\n"
+" \n"
+" if( cs->m_fJacCoeffInv[0] == 0 && cs->m_fJacCoeffInv[0] == 0 ) return;\n"
+" const float4 center = cs->m_center;\n"
+" \n"
+" float4 n = -cs->m_linear;\n"
+" \n"
+" float4 tangent[2];\n"
+" btPlaneSpace1(&n,&tangent[0],&tangent[1]);\n"
+" float4 angular0, angular1, linear;\n"
+" float4 r0 = center - posA;\n"
+" float4 r1 = center - posB;\n"
+" for(int i=0; i<2; i++)\n"
+" {\n"
+" setLinearAndAngular( tangent[i], r0, r1, &linear, &angular0, &angular1 );\n"
+" float rambdaDt = calcRelVel(linear, -linear, angular0, angular1,\n"
+" linVelA, angVelA, linVelB, angVelB );\n"
+" rambdaDt *= cs->m_fJacCoeffInv[i];\n"
+" \n"
+" {\n"
+" float prevSum = cs->m_fAppliedRambdaDt[i];\n"
+" float updated = prevSum;\n"
+" updated += rambdaDt;\n"
+" updated = max2( updated, minRambdaDt[i] );\n"
+" updated = min2( updated, maxRambdaDt[i] );\n"
+" rambdaDt = updated - prevSum;\n"
+" cs->m_fAppliedRambdaDt[i] = updated;\n"
+" }\n"
+" \n"
+" float4 linImp0 = invMassA*linear*rambdaDt;\n"
+" float4 linImp1 = invMassB*(-linear)*rambdaDt;\n"
+" float4 angImp0 = mtMul1(invInertiaA, angular0)*rambdaDt;\n"
+" float4 angImp1 = mtMul1(invInertiaB, angular1)*rambdaDt;\n"
+" \n"
+" linVelA += linImp0;\n"
+" angVelA += angImp0;\n"
+" linVelB += linImp1;\n"
+" angVelB += angImp1;\n"
+" }\n"
+" { // angular damping for point constraint\n"
+" float4 ab = normalize3( posB - posA );\n"
+" float4 ac = normalize3( center - posA );\n"
+" if( dot3F4( ab, ac ) > 0.95f || (invMassA == 0.f || invMassB == 0.f))\n"
+" {\n"
+" float angNA = dot3F4( n, angVelA );\n"
+" float angNB = dot3F4( n, angVelB );\n"
+" \n"
+" angVelA -= (angNA*0.1f)*n;\n"
+" angVelB -= (angNB*0.1f)*n;\n"
+" }\n"
+" }\n"
+" }\n"
+" \n"
+" \n"
+" }\n"
+" if (gBodies[aIdx].m_invMass)\n"
+" {\n"
+" gBodies[aIdx].m_linVel = linVelA;\n"
+" gBodies[aIdx].m_angVel = angVelA;\n"
+" } else\n"
+" {\n"
+" gBodies[aIdx].m_linVel = mymake_float4(0,0,0,0);\n"
+" gBodies[aIdx].m_angVel = mymake_float4(0,0,0,0);\n"
+" }\n"
+" if (gBodies[bIdx].m_invMass)\n"
+" {\n"
+" gBodies[bIdx].m_linVel = linVelB;\n"
+" gBodies[bIdx].m_angVel = angVelB;\n"
+" } else\n"
+" {\n"
+" gBodies[bIdx].m_linVel = mymake_float4(0,0,0,0);\n"
+" gBodies[bIdx].m_angVel = mymake_float4(0,0,0,0);\n"
+" }\n"
+" \n"
+"}\n"
+"typedef struct \n"
+"{\n"
+" int m_valInt0;\n"
+" int m_valInt1;\n"
+" int m_valInt2;\n"
+" int m_valInt3;\n"
+" float m_val0;\n"
+" float m_val1;\n"
+" float m_val2;\n"
+" float m_val3;\n"
+"} SolverDebugInfo;\n"
+"__kernel\n"
+"__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+"void BatchSolveKernelFriction(__global Body* gBodies,\n"
+" __global Shape* gShapes,\n"
+" __global Constraint4* gConstraints,\n"
+" __global int* gN,\n"
+" __global int* gOffsets,\n"
+" __global int* batchSizes,\n"
+" int maxBatch1,\n"
+" int cellBatch,\n"
+" int4 nSplit\n"
+" )\n"
+"{\n"
+" //__local int ldsBatchIdx[WG_SIZE+1];\n"
+" __local int ldsCurBatch;\n"
+" __local int ldsNextBatch;\n"
+" __local int ldsStart;\n"
+" int lIdx = GET_LOCAL_IDX;\n"
+" int wgIdx = GET_GROUP_IDX;\n"
+"// int gIdx = GET_GLOBAL_IDX;\n"
+"// debugInfo[gIdx].m_valInt0 = gIdx;\n"
+" //debugInfo[gIdx].m_valInt1 = GET_GROUP_SIZE;\n"
+" int zIdx = (wgIdx/((nSplit.x*nSplit.y)/4))*2+((cellBatch&4)>>2);\n"
+" int remain= (wgIdx%((nSplit.x*nSplit.y)/4));\n"
+" int yIdx = (remain/(nSplit.x/2))*2 + ((cellBatch&2)>>1);\n"
+" int xIdx = (remain%(nSplit.x/2))*2 + (cellBatch&1);\n"
+" int cellIdx = xIdx+yIdx*nSplit.x+zIdx*(nSplit.x*nSplit.y);\n"
+" \n"
+" if( gN[cellIdx] == 0 ) \n"
+" return;\n"
+" int maxBatch = batchSizes[cellIdx];\n"
+" const int start = gOffsets[cellIdx];\n"
+" const int end = start + gN[cellIdx];\n"
+" \n"
+" if( lIdx == 0 )\n"
+" {\n"
+" ldsCurBatch = 0;\n"
+" ldsNextBatch = 0;\n"
+" ldsStart = start;\n"
+" }\n"
+" GROUP_LDS_BARRIER;\n"
+" int idx=ldsStart+lIdx;\n"
+" while (ldsCurBatch < maxBatch)\n"
+" {\n"
+" for(; idx<end; )\n"
+" {\n"
+" if (gConstraints[idx].m_batchIdx == ldsCurBatch)\n"
+" {\n"
+" solveFrictionConstraint( gBodies, gShapes, &gConstraints[idx] );\n"
+" idx+=64;\n"
+" } else\n"
+" {\n"
+" break;\n"
+" }\n"
+" }\n"
+" GROUP_LDS_BARRIER;\n"
+" if( lIdx == 0 )\n"
+" {\n"
+" ldsCurBatch++;\n"
+" }\n"
+" GROUP_LDS_BARRIER;\n"
+" }\n"
+" \n"
+" \n"
+"}\n"
+"__kernel void solveSingleFrictionKernel(__global Body* gBodies,\n"
+" __global Shape* gShapes,\n"
+" __global Constraint4* gConstraints,\n"
+" int cellIdx,\n"
+" int batchOffset,\n"
+" int numConstraintsInBatch\n"
+" )\n"
+"{\n"
+" int index = get_global_id(0);\n"
+" if (index < numConstraintsInBatch)\n"
+" {\n"
+" \n"
+" int idx=batchOffset+index;\n"
+" \n"
+" solveFrictionConstraint( gBodies, gShapes, &gConstraints[idx] );\n"
+" } \n"
+"}\n"
+;
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/solverSetup.cl b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/solverSetup.cl
new file mode 100644
index 0000000000..8e2de7b5a6
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/solverSetup.cl
@@ -0,0 +1,277 @@
+
+/*
+Copyright (c) 2012 Advanced Micro Devices, Inc.
+
+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.
+*/
+//Originally written by Takahiro Harada
+
+#include "Bullet3Dynamics/shared/b3ConvertConstraint4.h"
+
+#pragma OPENCL EXTENSION cl_amd_printf : enable
+#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable
+
+
+#ifdef cl_ext_atomic_counters_32
+#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable
+#else
+#define counter32_t volatile global int*
+#endif
+
+typedef unsigned int u32;
+typedef unsigned short u16;
+typedef unsigned char u8;
+
+#define GET_GROUP_IDX get_group_id(0)
+#define GET_LOCAL_IDX get_local_id(0)
+#define GET_GLOBAL_IDX get_global_id(0)
+#define GET_GROUP_SIZE get_local_size(0)
+#define GET_NUM_GROUPS get_num_groups(0)
+#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)
+#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)
+#define AtomInc(x) atom_inc(&(x))
+#define AtomInc1(x, out) out = atom_inc(&(x))
+#define AppendInc(x, out) out = atomic_inc(x)
+#define AtomAdd(x, value) atom_add(&(x), value)
+#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )
+#define AtomXhg(x, value) atom_xchg ( &(x), value )
+
+
+#define SELECT_UINT4( b, a, condition ) select( b,a,condition )
+
+#define make_float4 (float4)
+#define make_float2 (float2)
+#define make_uint4 (uint4)
+#define make_int4 (int4)
+#define make_uint2 (uint2)
+#define make_int2 (int2)
+
+
+#define max2 max
+#define min2 min
+
+
+///////////////////////////////////////
+// Vector
+///////////////////////////////////////
+__inline
+float fastDiv(float numerator, float denominator)
+{
+ return native_divide(numerator, denominator);
+// return numerator/denominator;
+}
+
+__inline
+float4 fastDiv4(float4 numerator, float4 denominator)
+{
+ return native_divide(numerator, denominator);
+}
+
+__inline
+float fastSqrtf(float f2)
+{
+ return native_sqrt(f2);
+// return sqrt(f2);
+}
+
+__inline
+float fastRSqrt(float f2)
+{
+ return native_rsqrt(f2);
+}
+
+__inline
+float fastLength4(float4 v)
+{
+ return fast_length(v);
+}
+
+__inline
+float4 fastNormalize4(float4 v)
+{
+ return fast_normalize(v);
+}
+
+
+__inline
+float sqrtf(float a)
+{
+// return sqrt(a);
+ return native_sqrt(a);
+}
+
+__inline
+float4 cross3(float4 a, float4 b)
+{
+ return cross(a,b);
+}
+
+__inline
+float dot3F4(float4 a, float4 b)
+{
+ float4 a1 = make_float4(a.xyz,0.f);
+ float4 b1 = make_float4(b.xyz,0.f);
+ return dot(a1, b1);
+}
+
+__inline
+float length3(const float4 a)
+{
+ return sqrtf(dot3F4(a,a));
+}
+
+__inline
+float dot4(const float4 a, const float4 b)
+{
+ return dot( a, b );
+}
+
+// for height
+__inline
+float dot3w1(const float4 point, const float4 eqn)
+{
+ return dot3F4(point,eqn) + eqn.w;
+}
+
+__inline
+float4 normalize3(const float4 a)
+{
+ float4 n = make_float4(a.x, a.y, a.z, 0.f);
+ return fastNormalize4( n );
+// float length = sqrtf(dot3F4(a, a));
+// return 1.f/length * a;
+}
+
+__inline
+float4 normalize4(const float4 a)
+{
+ float length = sqrtf(dot4(a, a));
+ return 1.f/length * a;
+}
+
+__inline
+float4 createEquation(const float4 a, const float4 b, const float4 c)
+{
+ float4 eqn;
+ float4 ab = b-a;
+ float4 ac = c-a;
+ eqn = normalize3( cross3(ab, ac) );
+ eqn.w = -dot3F4(eqn,a);
+ return eqn;
+}
+
+
+
+#define WG_SIZE 64
+
+
+
+
+
+
+
+typedef struct
+{
+ int m_nConstraints;
+ int m_start;
+ int m_batchIdx;
+ int m_nSplit;
+// int m_paddings[1];
+} ConstBuffer;
+
+typedef struct
+{
+ int m_solveFriction;
+ int m_maxBatch; // long batch really kills the performance
+ int m_batchIdx;
+ int m_nSplit;
+// int m_paddings[1];
+} ConstBufferBatchSolve;
+
+
+
+
+
+
+
+typedef struct
+{
+ int m_valInt0;
+ int m_valInt1;
+ int m_valInt2;
+ int m_valInt3;
+
+ float m_val0;
+ float m_val1;
+ float m_val2;
+ float m_val3;
+} SolverDebugInfo;
+
+
+
+
+
+
+typedef struct
+{
+ int m_nContacts;
+ float m_dt;
+ float m_positionDrift;
+ float m_positionConstraintCoeff;
+} ConstBufferCTC;
+
+__kernel
+__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
+void ContactToConstraintKernel(__global struct b3Contact4Data* gContact, __global b3RigidBodyData_t* gBodies, __global b3InertiaData_t* gShapes, __global b3ContactConstraint4_t* gConstraintOut,
+int nContacts,
+float dt,
+float positionDrift,
+float positionConstraintCoeff
+)
+{
+ int gIdx = GET_GLOBAL_IDX;
+
+ if( gIdx < nContacts )
+ {
+ int aIdx = abs(gContact[gIdx].m_bodyAPtrAndSignBit);
+ int bIdx = abs(gContact[gIdx].m_bodyBPtrAndSignBit);
+
+ float4 posA = gBodies[aIdx].m_pos;
+ float4 linVelA = gBodies[aIdx].m_linVel;
+ float4 angVelA = gBodies[aIdx].m_angVel;
+ float invMassA = gBodies[aIdx].m_invMass;
+ b3Mat3x3 invInertiaA = gShapes[aIdx].m_initInvInertia;
+
+ float4 posB = gBodies[bIdx].m_pos;
+ float4 linVelB = gBodies[bIdx].m_linVel;
+ float4 angVelB = gBodies[bIdx].m_angVel;
+ float invMassB = gBodies[bIdx].m_invMass;
+ b3Mat3x3 invInertiaB = gShapes[bIdx].m_initInvInertia;
+
+ b3ContactConstraint4_t cs;
+
+ setConstraint4( posA, linVelA, angVelA, invMassA, invInertiaA, posB, linVelB, angVelB, invMassB, invInertiaB,
+ &gContact[gIdx], dt, positionDrift, positionConstraintCoeff,
+ &cs );
+
+ cs.m_batchIdx = gContact[gIdx].m_batchIdx;
+
+ gConstraintOut[gIdx] = cs;
+ }
+}
+
+
+
+
+
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/solverSetup.h b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/solverSetup.h
new file mode 100644
index 0000000000..eb1834ee00
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/solverSetup.h
@@ -0,0 +1,703 @@
+//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
+static const char* solverSetupCL= \
+"/*\n"
+"Copyright (c) 2012 Advanced Micro Devices, Inc. \n"
+"This software is provided 'as-is', without any express or implied warranty.\n"
+"In no event will the authors be held liable for any damages arising from the use of this software.\n"
+"Permission is granted to anyone to use this software for any purpose, \n"
+"including commercial applications, and to alter it and redistribute it freely, \n"
+"subject to the following restrictions:\n"
+"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.\n"
+"2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
+"3. This notice may not be removed or altered from any source distribution.\n"
+"*/\n"
+"//Originally written by Takahiro Harada\n"
+"#ifndef B3_CONTACT4DATA_H\n"
+"#define B3_CONTACT4DATA_H\n"
+"#ifndef B3_FLOAT4_H\n"
+"#define B3_FLOAT4_H\n"
+"#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+"#define B3_PLATFORM_DEFINITIONS_H\n"
+"struct MyTest\n"
+"{\n"
+" int bla;\n"
+"};\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
+"#define B3_LARGE_FLOAT 1e18f\n"
+"#define B3_INFINITY 1e18f\n"
+"#define b3Assert(a)\n"
+"#define b3ConstArray(a) __global const a*\n"
+"#define b3AtomicInc atomic_inc\n"
+"#define b3AtomicAdd atomic_add\n"
+"#define b3Fabs fabs\n"
+"#define b3Sqrt native_sqrt\n"
+"#define b3Sin native_sin\n"
+"#define b3Cos native_cos\n"
+"#define B3_STATIC\n"
+"#endif\n"
+"#endif\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+" typedef float4 b3Float4;\n"
+" #define b3Float4ConstArg const b3Float4\n"
+" #define b3MakeFloat4 (float4)\n"
+" float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+" {\n"
+" float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+" float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+" return dot(a1, b1);\n"
+" }\n"
+" b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+" {\n"
+" float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+" float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+" return cross(a1, b1);\n"
+" }\n"
+" #define b3MinFloat4 min\n"
+" #define b3MaxFloat4 max\n"
+" #define b3Normalized(a) normalize(a)\n"
+"#endif \n"
+" \n"
+"inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
+"{\n"
+" if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6) \n"
+" return false;\n"
+" return true;\n"
+"}\n"
+"inline int b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
+"{\n"
+" float maxDot = -B3_INFINITY;\n"
+" int i = 0;\n"
+" int ptIndex = -1;\n"
+" for( i = 0; i < vecLen; i++ )\n"
+" {\n"
+" float dot = b3Dot3F4(vecArray[i],vec);\n"
+" \n"
+" if( dot > maxDot )\n"
+" {\n"
+" maxDot = dot;\n"
+" ptIndex = i;\n"
+" }\n"
+" }\n"
+" b3Assert(ptIndex>=0);\n"
+" if (ptIndex<0)\n"
+" {\n"
+" ptIndex = 0;\n"
+" }\n"
+" *dotOut = maxDot;\n"
+" return ptIndex;\n"
+"}\n"
+"#endif //B3_FLOAT4_H\n"
+"typedef struct b3Contact4Data b3Contact4Data_t;\n"
+"struct b3Contact4Data\n"
+"{\n"
+" b3Float4 m_worldPosB[4];\n"
+"// b3Float4 m_localPosA[4];\n"
+"// b3Float4 m_localPosB[4];\n"
+" b3Float4 m_worldNormalOnB; // w: m_nPoints\n"
+" unsigned short m_restituitionCoeffCmp;\n"
+" unsigned short m_frictionCoeffCmp;\n"
+" int m_batchIdx;\n"
+" int m_bodyAPtrAndSignBit;//x:m_bodyAPtr, y:m_bodyBPtr\n"
+" int m_bodyBPtrAndSignBit;\n"
+" int m_childIndexA;\n"
+" int m_childIndexB;\n"
+" int m_unused1;\n"
+" int m_unused2;\n"
+"};\n"
+"inline int b3Contact4Data_getNumPoints(const struct b3Contact4Data* contact)\n"
+"{\n"
+" return (int)contact->m_worldNormalOnB.w;\n"
+"};\n"
+"inline void b3Contact4Data_setNumPoints(struct b3Contact4Data* contact, int numPoints)\n"
+"{\n"
+" contact->m_worldNormalOnB.w = (float)numPoints;\n"
+"};\n"
+"#endif //B3_CONTACT4DATA_H\n"
+"#ifndef B3_CONTACT_CONSTRAINT5_H\n"
+"#define B3_CONTACT_CONSTRAINT5_H\n"
+"#ifndef B3_FLOAT4_H\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"#endif \n"
+"#endif //B3_FLOAT4_H\n"
+"typedef struct b3ContactConstraint4 b3ContactConstraint4_t;\n"
+"struct b3ContactConstraint4\n"
+"{\n"
+" b3Float4 m_linear;//normal?\n"
+" b3Float4 m_worldPos[4];\n"
+" b3Float4 m_center; // friction\n"
+" float m_jacCoeffInv[4];\n"
+" float m_b[4];\n"
+" float m_appliedRambdaDt[4];\n"
+" float m_fJacCoeffInv[2]; // friction\n"
+" float m_fAppliedRambdaDt[2]; // friction\n"
+" unsigned int m_bodyA;\n"
+" unsigned int m_bodyB;\n"
+" int m_batchIdx;\n"
+" unsigned int m_paddings;\n"
+"};\n"
+"//inline void setFrictionCoeff(float value) { m_linear[3] = value; }\n"
+"inline float b3GetFrictionCoeff(b3ContactConstraint4_t* constraint) \n"
+"{\n"
+" return constraint->m_linear.w; \n"
+"}\n"
+"#endif //B3_CONTACT_CONSTRAINT5_H\n"
+"#ifndef B3_RIGIDBODY_DATA_H\n"
+"#define B3_RIGIDBODY_DATA_H\n"
+"#ifndef B3_FLOAT4_H\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"#endif \n"
+"#endif //B3_FLOAT4_H\n"
+"#ifndef B3_QUAT_H\n"
+"#define B3_QUAT_H\n"
+"#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"#endif\n"
+"#endif\n"
+"#ifndef B3_FLOAT4_H\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"#endif \n"
+"#endif //B3_FLOAT4_H\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+" typedef float4 b3Quat;\n"
+" #define b3QuatConstArg const b3Quat\n"
+" \n"
+" \n"
+"inline float4 b3FastNormalize4(float4 v)\n"
+"{\n"
+" v = (float4)(v.xyz,0.f);\n"
+" return fast_normalize(v);\n"
+"}\n"
+" \n"
+"inline b3Quat b3QuatMul(b3Quat a, b3Quat b);\n"
+"inline b3Quat b3QuatNormalized(b3QuatConstArg in);\n"
+"inline b3Quat b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec);\n"
+"inline b3Quat b3QuatInvert(b3QuatConstArg q);\n"
+"inline b3Quat b3QuatInverse(b3QuatConstArg q);\n"
+"inline b3Quat b3QuatMul(b3QuatConstArg a, b3QuatConstArg b)\n"
+"{\n"
+" b3Quat ans;\n"
+" ans = b3Cross3( a, b );\n"
+" ans += a.w*b+b.w*a;\n"
+"// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
+" ans.w = a.w*b.w - b3Dot3F4(a, b);\n"
+" return ans;\n"
+"}\n"
+"inline b3Quat b3QuatNormalized(b3QuatConstArg in)\n"
+"{\n"
+" b3Quat q;\n"
+" q=in;\n"
+" //return b3FastNormalize4(in);\n"
+" float len = native_sqrt(dot(q, q));\n"
+" if(len > 0.f)\n"
+" {\n"
+" q *= 1.f / len;\n"
+" }\n"
+" else\n"
+" {\n"
+" q.x = q.y = q.z = 0.f;\n"
+" q.w = 1.f;\n"
+" }\n"
+" return q;\n"
+"}\n"
+"inline float4 b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
+"{\n"
+" b3Quat qInv = b3QuatInvert( q );\n"
+" float4 vcpy = vec;\n"
+" vcpy.w = 0.f;\n"
+" float4 out = b3QuatMul(b3QuatMul(q,vcpy),qInv);\n"
+" return out;\n"
+"}\n"
+"inline b3Quat b3QuatInverse(b3QuatConstArg q)\n"
+"{\n"
+" return (b3Quat)(-q.xyz, q.w);\n"
+"}\n"
+"inline b3Quat b3QuatInvert(b3QuatConstArg q)\n"
+"{\n"
+" return (b3Quat)(-q.xyz, q.w);\n"
+"}\n"
+"inline float4 b3QuatInvRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
+"{\n"
+" return b3QuatRotate( b3QuatInvert( q ), vec );\n"
+"}\n"
+"inline b3Float4 b3TransformPoint(b3Float4ConstArg point, b3Float4ConstArg translation, b3QuatConstArg orientation)\n"
+"{\n"
+" return b3QuatRotate( orientation, point ) + (translation);\n"
+"}\n"
+" \n"
+"#endif \n"
+"#endif //B3_QUAT_H\n"
+"#ifndef B3_MAT3x3_H\n"
+"#define B3_MAT3x3_H\n"
+"#ifndef B3_QUAT_H\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"#endif \n"
+"#endif //B3_QUAT_H\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"typedef struct\n"
+"{\n"
+" b3Float4 m_row[3];\n"
+"}b3Mat3x3;\n"
+"#define b3Mat3x3ConstArg const b3Mat3x3\n"
+"#define b3GetRow(m,row) (m.m_row[row])\n"
+"inline b3Mat3x3 b3QuatGetRotationMatrix(b3Quat quat)\n"
+"{\n"
+" b3Float4 quat2 = (b3Float4)(quat.x*quat.x, quat.y*quat.y, quat.z*quat.z, 0.f);\n"
+" b3Mat3x3 out;\n"
+" out.m_row[0].x=1-2*quat2.y-2*quat2.z;\n"
+" out.m_row[0].y=2*quat.x*quat.y-2*quat.w*quat.z;\n"
+" out.m_row[0].z=2*quat.x*quat.z+2*quat.w*quat.y;\n"
+" out.m_row[0].w = 0.f;\n"
+" out.m_row[1].x=2*quat.x*quat.y+2*quat.w*quat.z;\n"
+" out.m_row[1].y=1-2*quat2.x-2*quat2.z;\n"
+" out.m_row[1].z=2*quat.y*quat.z-2*quat.w*quat.x;\n"
+" out.m_row[1].w = 0.f;\n"
+" out.m_row[2].x=2*quat.x*quat.z-2*quat.w*quat.y;\n"
+" out.m_row[2].y=2*quat.y*quat.z+2*quat.w*quat.x;\n"
+" out.m_row[2].z=1-2*quat2.x-2*quat2.y;\n"
+" out.m_row[2].w = 0.f;\n"
+" return out;\n"
+"}\n"
+"inline b3Mat3x3 b3AbsoluteMat3x3(b3Mat3x3ConstArg matIn)\n"
+"{\n"
+" b3Mat3x3 out;\n"
+" out.m_row[0] = fabs(matIn.m_row[0]);\n"
+" out.m_row[1] = fabs(matIn.m_row[1]);\n"
+" out.m_row[2] = fabs(matIn.m_row[2]);\n"
+" return out;\n"
+"}\n"
+"__inline\n"
+"b3Mat3x3 mtZero();\n"
+"__inline\n"
+"b3Mat3x3 mtIdentity();\n"
+"__inline\n"
+"b3Mat3x3 mtTranspose(b3Mat3x3 m);\n"
+"__inline\n"
+"b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b);\n"
+"__inline\n"
+"b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b);\n"
+"__inline\n"
+"b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b);\n"
+"__inline\n"
+"b3Mat3x3 mtZero()\n"
+"{\n"
+" b3Mat3x3 m;\n"
+" m.m_row[0] = (b3Float4)(0.f);\n"
+" m.m_row[1] = (b3Float4)(0.f);\n"
+" m.m_row[2] = (b3Float4)(0.f);\n"
+" return m;\n"
+"}\n"
+"__inline\n"
+"b3Mat3x3 mtIdentity()\n"
+"{\n"
+" b3Mat3x3 m;\n"
+" m.m_row[0] = (b3Float4)(1,0,0,0);\n"
+" m.m_row[1] = (b3Float4)(0,1,0,0);\n"
+" m.m_row[2] = (b3Float4)(0,0,1,0);\n"
+" return m;\n"
+"}\n"
+"__inline\n"
+"b3Mat3x3 mtTranspose(b3Mat3x3 m)\n"
+"{\n"
+" b3Mat3x3 out;\n"
+" out.m_row[0] = (b3Float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);\n"
+" out.m_row[1] = (b3Float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);\n"
+" out.m_row[2] = (b3Float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);\n"
+" return out;\n"
+"}\n"
+"__inline\n"
+"b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b)\n"
+"{\n"
+" b3Mat3x3 transB;\n"
+" transB = mtTranspose( b );\n"
+" b3Mat3x3 ans;\n"
+" // why this doesn't run when 0ing in the for{}\n"
+" a.m_row[0].w = 0.f;\n"
+" a.m_row[1].w = 0.f;\n"
+" a.m_row[2].w = 0.f;\n"
+" for(int i=0; i<3; i++)\n"
+" {\n"
+"// a.m_row[i].w = 0.f;\n"
+" ans.m_row[i].x = b3Dot3F4(a.m_row[i],transB.m_row[0]);\n"
+" ans.m_row[i].y = b3Dot3F4(a.m_row[i],transB.m_row[1]);\n"
+" ans.m_row[i].z = b3Dot3F4(a.m_row[i],transB.m_row[2]);\n"
+" ans.m_row[i].w = 0.f;\n"
+" }\n"
+" return ans;\n"
+"}\n"
+"__inline\n"
+"b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b)\n"
+"{\n"
+" b3Float4 ans;\n"
+" ans.x = b3Dot3F4( a.m_row[0], b );\n"
+" ans.y = b3Dot3F4( a.m_row[1], b );\n"
+" ans.z = b3Dot3F4( a.m_row[2], b );\n"
+" ans.w = 0.f;\n"
+" return ans;\n"
+"}\n"
+"__inline\n"
+"b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b)\n"
+"{\n"
+" b3Float4 colx = b3MakeFloat4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
+" b3Float4 coly = b3MakeFloat4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
+" b3Float4 colz = b3MakeFloat4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
+" b3Float4 ans;\n"
+" ans.x = b3Dot3F4( a, colx );\n"
+" ans.y = b3Dot3F4( a, coly );\n"
+" ans.z = b3Dot3F4( a, colz );\n"
+" return ans;\n"
+"}\n"
+"#endif\n"
+"#endif //B3_MAT3x3_H\n"
+"typedef struct b3RigidBodyData b3RigidBodyData_t;\n"
+"struct b3RigidBodyData\n"
+"{\n"
+" b3Float4 m_pos;\n"
+" b3Quat m_quat;\n"
+" b3Float4 m_linVel;\n"
+" b3Float4 m_angVel;\n"
+" int m_collidableIdx;\n"
+" float m_invMass;\n"
+" float m_restituitionCoeff;\n"
+" float m_frictionCoeff;\n"
+"};\n"
+"typedef struct b3InertiaData b3InertiaData_t;\n"
+"struct b3InertiaData\n"
+"{\n"
+" b3Mat3x3 m_invInertiaWorld;\n"
+" b3Mat3x3 m_initInvInertia;\n"
+"};\n"
+"#endif //B3_RIGIDBODY_DATA_H\n"
+" \n"
+"void b3PlaneSpace1 (b3Float4ConstArg n, b3Float4* p, b3Float4* q);\n"
+" void b3PlaneSpace1 (b3Float4ConstArg n, b3Float4* p, b3Float4* q)\n"
+"{\n"
+" if (b3Fabs(n.z) > 0.70710678f) {\n"
+" // choose p in y-z plane\n"
+" float a = n.y*n.y + n.z*n.z;\n"
+" float k = 1.f/sqrt(a);\n"
+" p[0].x = 0;\n"
+" p[0].y = -n.z*k;\n"
+" p[0].z = n.y*k;\n"
+" // set q = n x p\n"
+" q[0].x = a*k;\n"
+" q[0].y = -n.x*p[0].z;\n"
+" q[0].z = n.x*p[0].y;\n"
+" }\n"
+" else {\n"
+" // choose p in x-y plane\n"
+" float a = n.x*n.x + n.y*n.y;\n"
+" float k = 1.f/sqrt(a);\n"
+" p[0].x = -n.y*k;\n"
+" p[0].y = n.x*k;\n"
+" p[0].z = 0;\n"
+" // set q = n x p\n"
+" q[0].x = -n.z*p[0].y;\n"
+" q[0].y = n.z*p[0].x;\n"
+" q[0].z = a*k;\n"
+" }\n"
+"}\n"
+" \n"
+"void setLinearAndAngular( b3Float4ConstArg n, b3Float4ConstArg r0, b3Float4ConstArg r1, b3Float4* linear, b3Float4* angular0, b3Float4* angular1)\n"
+"{\n"
+" *linear = b3MakeFloat4(n.x,n.y,n.z,0.f);\n"
+" *angular0 = b3Cross3(r0, n);\n"
+" *angular1 = -b3Cross3(r1, n);\n"
+"}\n"
+"float calcRelVel( b3Float4ConstArg l0, b3Float4ConstArg l1, b3Float4ConstArg a0, b3Float4ConstArg a1, b3Float4ConstArg linVel0,\n"
+" b3Float4ConstArg angVel0, b3Float4ConstArg linVel1, b3Float4ConstArg angVel1 )\n"
+"{\n"
+" return b3Dot3F4(l0, linVel0) + b3Dot3F4(a0, angVel0) + b3Dot3F4(l1, linVel1) + b3Dot3F4(a1, angVel1);\n"
+"}\n"
+"float calcJacCoeff(b3Float4ConstArg linear0, b3Float4ConstArg linear1, b3Float4ConstArg angular0, b3Float4ConstArg angular1,\n"
+" float invMass0, const b3Mat3x3* invInertia0, float invMass1, const b3Mat3x3* invInertia1)\n"
+"{\n"
+" // linear0,1 are normlized\n"
+" float jmj0 = invMass0;//b3Dot3F4(linear0, linear0)*invMass0;\n"
+" float jmj1 = b3Dot3F4(mtMul3(angular0,*invInertia0), angular0);\n"
+" float jmj2 = invMass1;//b3Dot3F4(linear1, linear1)*invMass1;\n"
+" float jmj3 = b3Dot3F4(mtMul3(angular1,*invInertia1), angular1);\n"
+" return -1.f/(jmj0+jmj1+jmj2+jmj3);\n"
+"}\n"
+"void setConstraint4( b3Float4ConstArg posA, b3Float4ConstArg linVelA, b3Float4ConstArg angVelA, float invMassA, b3Mat3x3ConstArg invInertiaA,\n"
+" b3Float4ConstArg posB, b3Float4ConstArg linVelB, b3Float4ConstArg angVelB, float invMassB, b3Mat3x3ConstArg invInertiaB, \n"
+" __global struct b3Contact4Data* src, float dt, float positionDrift, float positionConstraintCoeff,\n"
+" b3ContactConstraint4_t* dstC )\n"
+"{\n"
+" dstC->m_bodyA = abs(src->m_bodyAPtrAndSignBit);\n"
+" dstC->m_bodyB = abs(src->m_bodyBPtrAndSignBit);\n"
+" float dtInv = 1.f/dt;\n"
+" for(int ic=0; ic<4; ic++)\n"
+" {\n"
+" dstC->m_appliedRambdaDt[ic] = 0.f;\n"
+" }\n"
+" dstC->m_fJacCoeffInv[0] = dstC->m_fJacCoeffInv[1] = 0.f;\n"
+" dstC->m_linear = src->m_worldNormalOnB;\n"
+" dstC->m_linear.w = 0.7f ;//src->getFrictionCoeff() );\n"
+" for(int ic=0; ic<4; ic++)\n"
+" {\n"
+" b3Float4 r0 = src->m_worldPosB[ic] - posA;\n"
+" b3Float4 r1 = src->m_worldPosB[ic] - posB;\n"
+" if( ic >= src->m_worldNormalOnB.w )//npoints\n"
+" {\n"
+" dstC->m_jacCoeffInv[ic] = 0.f;\n"
+" continue;\n"
+" }\n"
+" float relVelN;\n"
+" {\n"
+" b3Float4 linear, angular0, angular1;\n"
+" setLinearAndAngular(src->m_worldNormalOnB, r0, r1, &linear, &angular0, &angular1);\n"
+" dstC->m_jacCoeffInv[ic] = calcJacCoeff(linear, -linear, angular0, angular1,\n"
+" invMassA, &invInertiaA, invMassB, &invInertiaB );\n"
+" relVelN = calcRelVel(linear, -linear, angular0, angular1,\n"
+" linVelA, angVelA, linVelB, angVelB);\n"
+" float e = 0.f;//src->getRestituitionCoeff();\n"
+" if( relVelN*relVelN < 0.004f ) e = 0.f;\n"
+" dstC->m_b[ic] = e*relVelN;\n"
+" //float penetration = src->m_worldPosB[ic].w;\n"
+" dstC->m_b[ic] += (src->m_worldPosB[ic].w + positionDrift)*positionConstraintCoeff*dtInv;\n"
+" dstC->m_appliedRambdaDt[ic] = 0.f;\n"
+" }\n"
+" }\n"
+" if( src->m_worldNormalOnB.w > 0 )//npoints\n"
+" { // prepare friction\n"
+" b3Float4 center = b3MakeFloat4(0.f,0.f,0.f,0.f);\n"
+" for(int i=0; i<src->m_worldNormalOnB.w; i++) \n"
+" center += src->m_worldPosB[i];\n"
+" center /= (float)src->m_worldNormalOnB.w;\n"
+" b3Float4 tangent[2];\n"
+" b3PlaneSpace1(src->m_worldNormalOnB,&tangent[0],&tangent[1]);\n"
+" \n"
+" b3Float4 r[2];\n"
+" r[0] = center - posA;\n"
+" r[1] = center - posB;\n"
+" for(int i=0; i<2; i++)\n"
+" {\n"
+" b3Float4 linear, angular0, angular1;\n"
+" setLinearAndAngular(tangent[i], r[0], r[1], &linear, &angular0, &angular1);\n"
+" dstC->m_fJacCoeffInv[i] = calcJacCoeff(linear, -linear, angular0, angular1,\n"
+" invMassA, &invInertiaA, invMassB, &invInertiaB );\n"
+" dstC->m_fAppliedRambdaDt[i] = 0.f;\n"
+" }\n"
+" dstC->m_center = center;\n"
+" }\n"
+" for(int i=0; i<4; i++)\n"
+" {\n"
+" if( i<src->m_worldNormalOnB.w )\n"
+" {\n"
+" dstC->m_worldPos[i] = src->m_worldPosB[i];\n"
+" }\n"
+" else\n"
+" {\n"
+" dstC->m_worldPos[i] = b3MakeFloat4(0.f,0.f,0.f,0.f);\n"
+" }\n"
+" }\n"
+"}\n"
+"#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
+"#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
+"#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
+"#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n"
+"#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n"
+"#ifdef cl_ext_atomic_counters_32\n"
+"#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n"
+"#else\n"
+"#define counter32_t volatile global int*\n"
+"#endif\n"
+"typedef unsigned int u32;\n"
+"typedef unsigned short u16;\n"
+"typedef unsigned char u8;\n"
+"#define GET_GROUP_IDX get_group_id(0)\n"
+"#define GET_LOCAL_IDX get_local_id(0)\n"
+"#define GET_GLOBAL_IDX get_global_id(0)\n"
+"#define GET_GROUP_SIZE get_local_size(0)\n"
+"#define GET_NUM_GROUPS get_num_groups(0)\n"
+"#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
+"#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
+"#define AtomInc(x) atom_inc(&(x))\n"
+"#define AtomInc1(x, out) out = atom_inc(&(x))\n"
+"#define AppendInc(x, out) out = atomic_inc(x)\n"
+"#define AtomAdd(x, value) atom_add(&(x), value)\n"
+"#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )\n"
+"#define AtomXhg(x, value) atom_xchg ( &(x), value )\n"
+"#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n"
+"#define make_float4 (float4)\n"
+"#define make_float2 (float2)\n"
+"#define make_uint4 (uint4)\n"
+"#define make_int4 (int4)\n"
+"#define make_uint2 (uint2)\n"
+"#define make_int2 (int2)\n"
+"#define max2 max\n"
+"#define min2 min\n"
+"///////////////////////////////////////\n"
+"// Vector\n"
+"///////////////////////////////////////\n"
+"__inline\n"
+"float fastDiv(float numerator, float denominator)\n"
+"{\n"
+" return native_divide(numerator, denominator); \n"
+"// return numerator/denominator; \n"
+"}\n"
+"__inline\n"
+"float4 fastDiv4(float4 numerator, float4 denominator)\n"
+"{\n"
+" return native_divide(numerator, denominator); \n"
+"}\n"
+"__inline\n"
+"float fastSqrtf(float f2)\n"
+"{\n"
+" return native_sqrt(f2);\n"
+"// return sqrt(f2);\n"
+"}\n"
+"__inline\n"
+"float fastRSqrt(float f2)\n"
+"{\n"
+" return native_rsqrt(f2);\n"
+"}\n"
+"__inline\n"
+"float fastLength4(float4 v)\n"
+"{\n"
+" return fast_length(v);\n"
+"}\n"
+"__inline\n"
+"float4 fastNormalize4(float4 v)\n"
+"{\n"
+" return fast_normalize(v);\n"
+"}\n"
+"__inline\n"
+"float sqrtf(float a)\n"
+"{\n"
+"// return sqrt(a);\n"
+" return native_sqrt(a);\n"
+"}\n"
+"__inline\n"
+"float4 cross3(float4 a, float4 b)\n"
+"{\n"
+" return cross(a,b);\n"
+"}\n"
+"__inline\n"
+"float dot3F4(float4 a, float4 b)\n"
+"{\n"
+" float4 a1 = make_float4(a.xyz,0.f);\n"
+" float4 b1 = make_float4(b.xyz,0.f);\n"
+" return dot(a1, b1);\n"
+"}\n"
+"__inline\n"
+"float length3(const float4 a)\n"
+"{\n"
+" return sqrtf(dot3F4(a,a));\n"
+"}\n"
+"__inline\n"
+"float dot4(const float4 a, const float4 b)\n"
+"{\n"
+" return dot( a, b );\n"
+"}\n"
+"// for height\n"
+"__inline\n"
+"float dot3w1(const float4 point, const float4 eqn)\n"
+"{\n"
+" return dot3F4(point,eqn) + eqn.w;\n"
+"}\n"
+"__inline\n"
+"float4 normalize3(const float4 a)\n"
+"{\n"
+" float4 n = make_float4(a.x, a.y, a.z, 0.f);\n"
+" return fastNormalize4( n );\n"
+"// float length = sqrtf(dot3F4(a, a));\n"
+"// return 1.f/length * a;\n"
+"}\n"
+"__inline\n"
+"float4 normalize4(const float4 a)\n"
+"{\n"
+" float length = sqrtf(dot4(a, a));\n"
+" return 1.f/length * a;\n"
+"}\n"
+"__inline\n"
+"float4 createEquation(const float4 a, const float4 b, const float4 c)\n"
+"{\n"
+" float4 eqn;\n"
+" float4 ab = b-a;\n"
+" float4 ac = c-a;\n"
+" eqn = normalize3( cross3(ab, ac) );\n"
+" eqn.w = -dot3F4(eqn,a);\n"
+" return eqn;\n"
+"}\n"
+"#define WG_SIZE 64\n"
+"typedef struct\n"
+"{\n"
+" int m_nConstraints;\n"
+" int m_start;\n"
+" int m_batchIdx;\n"
+" int m_nSplit;\n"
+"// int m_paddings[1];\n"
+"} ConstBuffer;\n"
+"typedef struct\n"
+"{\n"
+" int m_solveFriction;\n"
+" int m_maxBatch; // long batch really kills the performance\n"
+" int m_batchIdx;\n"
+" int m_nSplit;\n"
+"// int m_paddings[1];\n"
+"} ConstBufferBatchSolve;\n"
+" \n"
+"typedef struct \n"
+"{\n"
+" int m_valInt0;\n"
+" int m_valInt1;\n"
+" int m_valInt2;\n"
+" int m_valInt3;\n"
+" float m_val0;\n"
+" float m_val1;\n"
+" float m_val2;\n"
+" float m_val3;\n"
+"} SolverDebugInfo;\n"
+"typedef struct\n"
+"{\n"
+" int m_nContacts;\n"
+" float m_dt;\n"
+" float m_positionDrift;\n"
+" float m_positionConstraintCoeff;\n"
+"} ConstBufferCTC;\n"
+"__kernel\n"
+"__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+"void ContactToConstraintKernel(__global struct b3Contact4Data* gContact, __global b3RigidBodyData_t* gBodies, __global b3InertiaData_t* gShapes, __global b3ContactConstraint4_t* gConstraintOut, \n"
+"int nContacts,\n"
+"float dt,\n"
+"float positionDrift,\n"
+"float positionConstraintCoeff\n"
+")\n"
+"{\n"
+" int gIdx = GET_GLOBAL_IDX;\n"
+" \n"
+" if( gIdx < nContacts )\n"
+" {\n"
+" int aIdx = abs(gContact[gIdx].m_bodyAPtrAndSignBit);\n"
+" int bIdx = abs(gContact[gIdx].m_bodyBPtrAndSignBit);\n"
+" float4 posA = gBodies[aIdx].m_pos;\n"
+" float4 linVelA = gBodies[aIdx].m_linVel;\n"
+" float4 angVelA = gBodies[aIdx].m_angVel;\n"
+" float invMassA = gBodies[aIdx].m_invMass;\n"
+" b3Mat3x3 invInertiaA = gShapes[aIdx].m_initInvInertia;\n"
+" float4 posB = gBodies[bIdx].m_pos;\n"
+" float4 linVelB = gBodies[bIdx].m_linVel;\n"
+" float4 angVelB = gBodies[bIdx].m_angVel;\n"
+" float invMassB = gBodies[bIdx].m_invMass;\n"
+" b3Mat3x3 invInertiaB = gShapes[bIdx].m_initInvInertia;\n"
+" b3ContactConstraint4_t cs;\n"
+" setConstraint4( posA, linVelA, angVelA, invMassA, invInertiaA, posB, linVelB, angVelB, invMassB, invInertiaB,\n"
+" &gContact[gIdx], dt, positionDrift, positionConstraintCoeff,\n"
+" &cs );\n"
+" \n"
+" cs.m_batchIdx = gContact[gIdx].m_batchIdx;\n"
+" gConstraintOut[gIdx] = cs;\n"
+" }\n"
+"}\n"
+;
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/solverSetup2.cl b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/solverSetup2.cl
new file mode 100644
index 0000000000..3dc48d4350
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/solverSetup2.cl
@@ -0,0 +1,613 @@
+/*
+Copyright (c) 2012 Advanced Micro Devices, Inc.
+
+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.
+*/
+//Originally written by Takahiro Harada
+
+
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h"
+
+#pragma OPENCL EXTENSION cl_amd_printf : enable
+#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable
+
+
+#ifdef cl_ext_atomic_counters_32
+#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable
+#else
+#define counter32_t volatile global int*
+#endif
+
+typedef unsigned int u32;
+typedef unsigned short u16;
+typedef unsigned char u8;
+
+#define GET_GROUP_IDX get_group_id(0)
+#define GET_LOCAL_IDX get_local_id(0)
+#define GET_GLOBAL_IDX get_global_id(0)
+#define GET_GROUP_SIZE get_local_size(0)
+#define GET_NUM_GROUPS get_num_groups(0)
+#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)
+#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)
+#define AtomInc(x) atom_inc(&(x))
+#define AtomInc1(x, out) out = atom_inc(&(x))
+#define AppendInc(x, out) out = atomic_inc(x)
+#define AtomAdd(x, value) atom_add(&(x), value)
+#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )
+#define AtomXhg(x, value) atom_xchg ( &(x), value )
+
+
+#define SELECT_UINT4( b, a, condition ) select( b,a,condition )
+
+#define make_float4 (float4)
+#define make_float2 (float2)
+#define make_uint4 (uint4)
+#define make_int4 (int4)
+#define make_uint2 (uint2)
+#define make_int2 (int2)
+
+
+#define max2 max
+#define min2 min
+
+
+///////////////////////////////////////
+// Vector
+///////////////////////////////////////
+__inline
+float fastDiv(float numerator, float denominator)
+{
+ return native_divide(numerator, denominator);
+// return numerator/denominator;
+}
+
+__inline
+float4 fastDiv4(float4 numerator, float4 denominator)
+{
+ return native_divide(numerator, denominator);
+}
+
+__inline
+float fastSqrtf(float f2)
+{
+ return native_sqrt(f2);
+// return sqrt(f2);
+}
+
+__inline
+float fastRSqrt(float f2)
+{
+ return native_rsqrt(f2);
+}
+
+__inline
+float fastLength4(float4 v)
+{
+ return fast_length(v);
+}
+
+__inline
+float4 fastNormalize4(float4 v)
+{
+ return fast_normalize(v);
+}
+
+
+__inline
+float sqrtf(float a)
+{
+// return sqrt(a);
+ return native_sqrt(a);
+}
+
+__inline
+float4 cross3(float4 a, float4 b)
+{
+ return cross(a,b);
+}
+
+__inline
+float dot3F4(float4 a, float4 b)
+{
+ float4 a1 = make_float4(a.xyz,0.f);
+ float4 b1 = make_float4(b.xyz,0.f);
+ return dot(a1, b1);
+}
+
+__inline
+float length3(const float4 a)
+{
+ return sqrtf(dot3F4(a,a));
+}
+
+__inline
+float dot4(const float4 a, const float4 b)
+{
+ return dot( a, b );
+}
+
+// for height
+__inline
+float dot3w1(const float4 point, const float4 eqn)
+{
+ return dot3F4(point,eqn) + eqn.w;
+}
+
+__inline
+float4 normalize3(const float4 a)
+{
+ float4 n = make_float4(a.x, a.y, a.z, 0.f);
+ return fastNormalize4( n );
+// float length = sqrtf(dot3F4(a, a));
+// return 1.f/length * a;
+}
+
+__inline
+float4 normalize4(const float4 a)
+{
+ float length = sqrtf(dot4(a, a));
+ return 1.f/length * a;
+}
+
+__inline
+float4 createEquation(const float4 a, const float4 b, const float4 c)
+{
+ float4 eqn;
+ float4 ab = b-a;
+ float4 ac = c-a;
+ eqn = normalize3( cross3(ab, ac) );
+ eqn.w = -dot3F4(eqn,a);
+ return eqn;
+}
+
+///////////////////////////////////////
+// Matrix3x3
+///////////////////////////////////////
+
+typedef struct
+{
+ float4 m_row[3];
+}Matrix3x3;
+
+__inline
+Matrix3x3 mtZero();
+
+__inline
+Matrix3x3 mtIdentity();
+
+__inline
+Matrix3x3 mtTranspose(Matrix3x3 m);
+
+__inline
+Matrix3x3 mtMul(Matrix3x3 a, Matrix3x3 b);
+
+__inline
+float4 mtMul1(Matrix3x3 a, float4 b);
+
+__inline
+float4 mtMul3(float4 a, Matrix3x3 b);
+
+__inline
+Matrix3x3 mtZero()
+{
+ Matrix3x3 m;
+ m.m_row[0] = (float4)(0.f);
+ m.m_row[1] = (float4)(0.f);
+ m.m_row[2] = (float4)(0.f);
+ return m;
+}
+
+__inline
+Matrix3x3 mtIdentity()
+{
+ Matrix3x3 m;
+ m.m_row[0] = (float4)(1,0,0,0);
+ m.m_row[1] = (float4)(0,1,0,0);
+ m.m_row[2] = (float4)(0,0,1,0);
+ return m;
+}
+
+__inline
+Matrix3x3 mtTranspose(Matrix3x3 m)
+{
+ Matrix3x3 out;
+ out.m_row[0] = (float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);
+ out.m_row[1] = (float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);
+ out.m_row[2] = (float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);
+ return out;
+}
+
+__inline
+Matrix3x3 mtMul(Matrix3x3 a, Matrix3x3 b)
+{
+ Matrix3x3 transB;
+ transB = mtTranspose( b );
+ Matrix3x3 ans;
+ // why this doesn't run when 0ing in the for{}
+ a.m_row[0].w = 0.f;
+ a.m_row[1].w = 0.f;
+ a.m_row[2].w = 0.f;
+ for(int i=0; i<3; i++)
+ {
+// a.m_row[i].w = 0.f;
+ ans.m_row[i].x = dot3F4(a.m_row[i],transB.m_row[0]);
+ ans.m_row[i].y = dot3F4(a.m_row[i],transB.m_row[1]);
+ ans.m_row[i].z = dot3F4(a.m_row[i],transB.m_row[2]);
+ ans.m_row[i].w = 0.f;
+ }
+ return ans;
+}
+
+__inline
+float4 mtMul1(Matrix3x3 a, float4 b)
+{
+ float4 ans;
+ ans.x = dot3F4( a.m_row[0], b );
+ ans.y = dot3F4( a.m_row[1], b );
+ ans.z = dot3F4( a.m_row[2], b );
+ ans.w = 0.f;
+ return ans;
+}
+
+__inline
+float4 mtMul3(float4 a, Matrix3x3 b)
+{
+ float4 colx = make_float4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);
+ float4 coly = make_float4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);
+ float4 colz = make_float4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);
+
+ float4 ans;
+ ans.x = dot3F4( a, colx );
+ ans.y = dot3F4( a, coly );
+ ans.z = dot3F4( a, colz );
+ return ans;
+}
+
+///////////////////////////////////////
+// Quaternion
+///////////////////////////////////////
+
+typedef float4 Quaternion;
+
+__inline
+Quaternion qtMul(Quaternion a, Quaternion b);
+
+__inline
+Quaternion qtNormalize(Quaternion in);
+
+__inline
+float4 qtRotate(Quaternion q, float4 vec);
+
+__inline
+Quaternion qtInvert(Quaternion q);
+
+
+
+
+
+__inline
+Quaternion qtMul(Quaternion a, Quaternion b)
+{
+ Quaternion ans;
+ ans = cross3( a, b );
+ ans += a.w*b+b.w*a;
+// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);
+ ans.w = a.w*b.w - dot3F4(a, b);
+ return ans;
+}
+
+__inline
+Quaternion qtNormalize(Quaternion in)
+{
+ return fastNormalize4(in);
+// in /= length( in );
+// return in;
+}
+__inline
+float4 qtRotate(Quaternion q, float4 vec)
+{
+ Quaternion qInv = qtInvert( q );
+ float4 vcpy = vec;
+ vcpy.w = 0.f;
+ float4 out = qtMul(qtMul(q,vcpy),qInv);
+ return out;
+}
+
+__inline
+Quaternion qtInvert(Quaternion q)
+{
+ return (Quaternion)(-q.xyz, q.w);
+}
+
+__inline
+float4 qtInvRotate(const Quaternion q, float4 vec)
+{
+ return qtRotate( qtInvert( q ), vec );
+}
+
+
+
+
+#define WG_SIZE 64
+
+typedef struct
+{
+ float4 m_pos;
+ Quaternion m_quat;
+ float4 m_linVel;
+ float4 m_angVel;
+
+ u32 m_shapeIdx;
+ float m_invMass;
+ float m_restituitionCoeff;
+ float m_frictionCoeff;
+} Body;
+
+typedef struct
+{
+ Matrix3x3 m_invInertia;
+ Matrix3x3 m_initInvInertia;
+} Shape;
+
+typedef struct
+{
+ float4 m_linear;
+ float4 m_worldPos[4];
+ float4 m_center;
+ float m_jacCoeffInv[4];
+ float m_b[4];
+ float m_appliedRambdaDt[4];
+
+ float m_fJacCoeffInv[2];
+ float m_fAppliedRambdaDt[2];
+
+ u32 m_bodyA;
+ u32 m_bodyB;
+
+ int m_batchIdx;
+ u32 m_paddings[1];
+} Constraint4;
+
+
+
+typedef struct
+{
+ int m_nConstraints;
+ int m_start;
+ int m_batchIdx;
+ int m_nSplit;
+// int m_paddings[1];
+} ConstBuffer;
+
+typedef struct
+{
+ int m_solveFriction;
+ int m_maxBatch; // long batch really kills the performance
+ int m_batchIdx;
+ int m_nSplit;
+// int m_paddings[1];
+} ConstBufferBatchSolve;
+
+
+
+
+
+typedef struct
+{
+ int m_valInt0;
+ int m_valInt1;
+ int m_valInt2;
+ int m_valInt3;
+
+ float m_val0;
+ float m_val1;
+ float m_val2;
+ float m_val3;
+} SolverDebugInfo;
+
+
+
+
+// others
+__kernel
+__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
+void ReorderContactKernel(__global struct b3Contact4Data* in, __global struct b3Contact4Data* out, __global int2* sortData, int4 cb )
+{
+ int nContacts = cb.x;
+ int gIdx = GET_GLOBAL_IDX;
+
+ if( gIdx < nContacts )
+ {
+ int srcIdx = sortData[gIdx].y;
+ out[gIdx] = in[srcIdx];
+ }
+}
+
+__kernel __attribute__((reqd_work_group_size(WG_SIZE,1,1)))
+void SetDeterminismSortDataChildShapeB(__global struct b3Contact4Data* contactsIn, __global int2* sortDataOut, int nContacts)
+{
+ int gIdx = GET_GLOBAL_IDX;
+
+ if( gIdx < nContacts )
+ {
+ int2 sd;
+ sd.x = contactsIn[gIdx].m_childIndexB;
+ sd.y = gIdx;
+ sortDataOut[gIdx] = sd;
+ }
+}
+
+__kernel __attribute__((reqd_work_group_size(WG_SIZE,1,1)))
+void SetDeterminismSortDataChildShapeA(__global struct b3Contact4Data* contactsIn, __global int2* sortDataInOut, int nContacts)
+{
+ int gIdx = GET_GLOBAL_IDX;
+
+ if( gIdx < nContacts )
+ {
+ int2 sdIn;
+ sdIn = sortDataInOut[gIdx];
+ int2 sdOut;
+ sdOut.x = contactsIn[sdIn.y].m_childIndexA;
+ sdOut.y = sdIn.y;
+ sortDataInOut[gIdx] = sdOut;
+ }
+}
+
+__kernel __attribute__((reqd_work_group_size(WG_SIZE,1,1)))
+void SetDeterminismSortDataBodyA(__global struct b3Contact4Data* contactsIn, __global int2* sortDataInOut, int nContacts)
+{
+ int gIdx = GET_GLOBAL_IDX;
+
+ if( gIdx < nContacts )
+ {
+ int2 sdIn;
+ sdIn = sortDataInOut[gIdx];
+ int2 sdOut;
+ sdOut.x = contactsIn[sdIn.y].m_bodyAPtrAndSignBit;
+ sdOut.y = sdIn.y;
+ sortDataInOut[gIdx] = sdOut;
+ }
+}
+
+
+__kernel
+__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
+void SetDeterminismSortDataBodyB(__global struct b3Contact4Data* contactsIn, __global int2* sortDataInOut, int nContacts)
+{
+ int gIdx = GET_GLOBAL_IDX;
+
+ if( gIdx < nContacts )
+ {
+ int2 sdIn;
+ sdIn = sortDataInOut[gIdx];
+ int2 sdOut;
+ sdOut.x = contactsIn[sdIn.y].m_bodyBPtrAndSignBit;
+ sdOut.y = sdIn.y;
+ sortDataInOut[gIdx] = sdOut;
+ }
+}
+
+
+
+
+typedef struct
+{
+ int m_nContacts;
+ int m_staticIdx;
+ float m_scale;
+ int m_nSplit;
+} ConstBufferSSD;
+
+
+__constant const int gridTable4x4[] =
+{
+ 0,1,17,16,
+ 1,2,18,19,
+ 17,18,32,3,
+ 16,19,3,34
+};
+
+__constant const int gridTable8x8[] =
+{
+ 0, 2, 3, 16, 17, 18, 19, 1,
+ 66, 64, 80, 67, 82, 81, 65, 83,
+ 131,144,128,130,147,129,145,146,
+ 208,195,194,192,193,211,210,209,
+ 21, 22, 23, 5, 4, 6, 7, 20,
+ 86, 85, 69, 87, 70, 68, 84, 71,
+ 151,133,149,150,135,148,132,134,
+ 197,27,214,213,212,199,198,196
+
+};
+
+
+
+
+#define USE_SPATIAL_BATCHING 1
+#define USE_4x4_GRID 1
+
+__kernel
+__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
+void SetSortDataKernel(__global struct b3Contact4Data* gContact, __global Body* gBodies, __global int2* gSortDataOut,
+int nContacts,float scale,int4 nSplit,int staticIdx)
+
+{
+ int gIdx = GET_GLOBAL_IDX;
+
+ if( gIdx < nContacts )
+ {
+ int aPtrAndSignBit = gContact[gIdx].m_bodyAPtrAndSignBit;
+ int bPtrAndSignBit = gContact[gIdx].m_bodyBPtrAndSignBit;
+
+ int aIdx = abs(aPtrAndSignBit );
+ int bIdx = abs(bPtrAndSignBit);
+
+ bool aStatic = (aPtrAndSignBit<0) ||(aPtrAndSignBit==staticIdx);
+ bool bStatic = (bPtrAndSignBit<0) ||(bPtrAndSignBit==staticIdx);
+
+#if USE_SPATIAL_BATCHING
+ int idx = (aStatic)? bIdx: aIdx;
+ float4 p = gBodies[idx].m_pos;
+ int xIdx = (int)((p.x-((p.x<0.f)?1.f:0.f))*scale) & (nSplit.x-1);
+ int yIdx = (int)((p.y-((p.y<0.f)?1.f:0.f))*scale) & (nSplit.y-1);
+ int zIdx = (int)((p.z-((p.z<0.f)?1.f:0.f))*scale) & (nSplit.z-1);
+ int newIndex = (xIdx+yIdx*nSplit.x+zIdx*nSplit.x*nSplit.y);
+
+#else//USE_SPATIAL_BATCHING
+ #if USE_4x4_GRID
+ int aa = aIdx&3;
+ int bb = bIdx&3;
+ if (aStatic)
+ aa = bb;
+ if (bStatic)
+ bb = aa;
+
+ int gridIndex = aa + bb*4;
+ int newIndex = gridTable4x4[gridIndex];
+ #else//USE_4x4_GRID
+ int aa = aIdx&7;
+ int bb = bIdx&7;
+ if (aStatic)
+ aa = bb;
+ if (bStatic)
+ bb = aa;
+
+ int gridIndex = aa + bb*8;
+ int newIndex = gridTable8x8[gridIndex];
+ #endif//USE_4x4_GRID
+#endif//USE_SPATIAL_BATCHING
+
+
+ gSortDataOut[gIdx].x = newIndex;
+ gSortDataOut[gIdx].y = gIdx;
+ }
+ else
+ {
+ gSortDataOut[gIdx].x = 0xffffffff;
+ }
+}
+
+__kernel
+__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
+void CopyConstraintKernel(__global struct b3Contact4Data* gIn, __global struct b3Contact4Data* gOut, int4 cb )
+{
+ int gIdx = GET_GLOBAL_IDX;
+ if( gIdx < cb.x )
+ {
+ gOut[gIdx] = gIn[gIdx];
+ }
+}
+
+
+
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/solverSetup2.h b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/solverSetup2.h
new file mode 100644
index 0000000000..1b5819f6cf
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/solverSetup2.h
@@ -0,0 +1,601 @@
+//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
+static const char* solverSetup2CL= \
+"/*\n"
+"Copyright (c) 2012 Advanced Micro Devices, Inc. \n"
+"This software is provided 'as-is', without any express or implied warranty.\n"
+"In no event will the authors be held liable for any damages arising from the use of this software.\n"
+"Permission is granted to anyone to use this software for any purpose, \n"
+"including commercial applications, and to alter it and redistribute it freely, \n"
+"subject to the following restrictions:\n"
+"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.\n"
+"2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
+"3. This notice may not be removed or altered from any source distribution.\n"
+"*/\n"
+"//Originally written by Takahiro Harada\n"
+"#ifndef B3_CONTACT4DATA_H\n"
+"#define B3_CONTACT4DATA_H\n"
+"#ifndef B3_FLOAT4_H\n"
+"#define B3_FLOAT4_H\n"
+"#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+"#define B3_PLATFORM_DEFINITIONS_H\n"
+"struct MyTest\n"
+"{\n"
+" int bla;\n"
+"};\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
+"#define B3_LARGE_FLOAT 1e18f\n"
+"#define B3_INFINITY 1e18f\n"
+"#define b3Assert(a)\n"
+"#define b3ConstArray(a) __global const a*\n"
+"#define b3AtomicInc atomic_inc\n"
+"#define b3AtomicAdd atomic_add\n"
+"#define b3Fabs fabs\n"
+"#define b3Sqrt native_sqrt\n"
+"#define b3Sin native_sin\n"
+"#define b3Cos native_cos\n"
+"#define B3_STATIC\n"
+"#endif\n"
+"#endif\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+" typedef float4 b3Float4;\n"
+" #define b3Float4ConstArg const b3Float4\n"
+" #define b3MakeFloat4 (float4)\n"
+" float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+" {\n"
+" float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+" float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+" return dot(a1, b1);\n"
+" }\n"
+" b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+" {\n"
+" float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+" float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+" return cross(a1, b1);\n"
+" }\n"
+" #define b3MinFloat4 min\n"
+" #define b3MaxFloat4 max\n"
+" #define b3Normalized(a) normalize(a)\n"
+"#endif \n"
+" \n"
+"inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
+"{\n"
+" if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6) \n"
+" return false;\n"
+" return true;\n"
+"}\n"
+"inline int b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
+"{\n"
+" float maxDot = -B3_INFINITY;\n"
+" int i = 0;\n"
+" int ptIndex = -1;\n"
+" for( i = 0; i < vecLen; i++ )\n"
+" {\n"
+" float dot = b3Dot3F4(vecArray[i],vec);\n"
+" \n"
+" if( dot > maxDot )\n"
+" {\n"
+" maxDot = dot;\n"
+" ptIndex = i;\n"
+" }\n"
+" }\n"
+" b3Assert(ptIndex>=0);\n"
+" if (ptIndex<0)\n"
+" {\n"
+" ptIndex = 0;\n"
+" }\n"
+" *dotOut = maxDot;\n"
+" return ptIndex;\n"
+"}\n"
+"#endif //B3_FLOAT4_H\n"
+"typedef struct b3Contact4Data b3Contact4Data_t;\n"
+"struct b3Contact4Data\n"
+"{\n"
+" b3Float4 m_worldPosB[4];\n"
+"// b3Float4 m_localPosA[4];\n"
+"// b3Float4 m_localPosB[4];\n"
+" b3Float4 m_worldNormalOnB; // w: m_nPoints\n"
+" unsigned short m_restituitionCoeffCmp;\n"
+" unsigned short m_frictionCoeffCmp;\n"
+" int m_batchIdx;\n"
+" int m_bodyAPtrAndSignBit;//x:m_bodyAPtr, y:m_bodyBPtr\n"
+" int m_bodyBPtrAndSignBit;\n"
+" int m_childIndexA;\n"
+" int m_childIndexB;\n"
+" int m_unused1;\n"
+" int m_unused2;\n"
+"};\n"
+"inline int b3Contact4Data_getNumPoints(const struct b3Contact4Data* contact)\n"
+"{\n"
+" return (int)contact->m_worldNormalOnB.w;\n"
+"};\n"
+"inline void b3Contact4Data_setNumPoints(struct b3Contact4Data* contact, int numPoints)\n"
+"{\n"
+" contact->m_worldNormalOnB.w = (float)numPoints;\n"
+"};\n"
+"#endif //B3_CONTACT4DATA_H\n"
+"#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
+"#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
+"#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
+"#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n"
+"#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n"
+"#ifdef cl_ext_atomic_counters_32\n"
+"#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n"
+"#else\n"
+"#define counter32_t volatile global int*\n"
+"#endif\n"
+"typedef unsigned int u32;\n"
+"typedef unsigned short u16;\n"
+"typedef unsigned char u8;\n"
+"#define GET_GROUP_IDX get_group_id(0)\n"
+"#define GET_LOCAL_IDX get_local_id(0)\n"
+"#define GET_GLOBAL_IDX get_global_id(0)\n"
+"#define GET_GROUP_SIZE get_local_size(0)\n"
+"#define GET_NUM_GROUPS get_num_groups(0)\n"
+"#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
+"#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
+"#define AtomInc(x) atom_inc(&(x))\n"
+"#define AtomInc1(x, out) out = atom_inc(&(x))\n"
+"#define AppendInc(x, out) out = atomic_inc(x)\n"
+"#define AtomAdd(x, value) atom_add(&(x), value)\n"
+"#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )\n"
+"#define AtomXhg(x, value) atom_xchg ( &(x), value )\n"
+"#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n"
+"#define make_float4 (float4)\n"
+"#define make_float2 (float2)\n"
+"#define make_uint4 (uint4)\n"
+"#define make_int4 (int4)\n"
+"#define make_uint2 (uint2)\n"
+"#define make_int2 (int2)\n"
+"#define max2 max\n"
+"#define min2 min\n"
+"///////////////////////////////////////\n"
+"// Vector\n"
+"///////////////////////////////////////\n"
+"__inline\n"
+"float fastDiv(float numerator, float denominator)\n"
+"{\n"
+" return native_divide(numerator, denominator); \n"
+"// return numerator/denominator; \n"
+"}\n"
+"__inline\n"
+"float4 fastDiv4(float4 numerator, float4 denominator)\n"
+"{\n"
+" return native_divide(numerator, denominator); \n"
+"}\n"
+"__inline\n"
+"float fastSqrtf(float f2)\n"
+"{\n"
+" return native_sqrt(f2);\n"
+"// return sqrt(f2);\n"
+"}\n"
+"__inline\n"
+"float fastRSqrt(float f2)\n"
+"{\n"
+" return native_rsqrt(f2);\n"
+"}\n"
+"__inline\n"
+"float fastLength4(float4 v)\n"
+"{\n"
+" return fast_length(v);\n"
+"}\n"
+"__inline\n"
+"float4 fastNormalize4(float4 v)\n"
+"{\n"
+" return fast_normalize(v);\n"
+"}\n"
+"__inline\n"
+"float sqrtf(float a)\n"
+"{\n"
+"// return sqrt(a);\n"
+" return native_sqrt(a);\n"
+"}\n"
+"__inline\n"
+"float4 cross3(float4 a, float4 b)\n"
+"{\n"
+" return cross(a,b);\n"
+"}\n"
+"__inline\n"
+"float dot3F4(float4 a, float4 b)\n"
+"{\n"
+" float4 a1 = make_float4(a.xyz,0.f);\n"
+" float4 b1 = make_float4(b.xyz,0.f);\n"
+" return dot(a1, b1);\n"
+"}\n"
+"__inline\n"
+"float length3(const float4 a)\n"
+"{\n"
+" return sqrtf(dot3F4(a,a));\n"
+"}\n"
+"__inline\n"
+"float dot4(const float4 a, const float4 b)\n"
+"{\n"
+" return dot( a, b );\n"
+"}\n"
+"// for height\n"
+"__inline\n"
+"float dot3w1(const float4 point, const float4 eqn)\n"
+"{\n"
+" return dot3F4(point,eqn) + eqn.w;\n"
+"}\n"
+"__inline\n"
+"float4 normalize3(const float4 a)\n"
+"{\n"
+" float4 n = make_float4(a.x, a.y, a.z, 0.f);\n"
+" return fastNormalize4( n );\n"
+"// float length = sqrtf(dot3F4(a, a));\n"
+"// return 1.f/length * a;\n"
+"}\n"
+"__inline\n"
+"float4 normalize4(const float4 a)\n"
+"{\n"
+" float length = sqrtf(dot4(a, a));\n"
+" return 1.f/length * a;\n"
+"}\n"
+"__inline\n"
+"float4 createEquation(const float4 a, const float4 b, const float4 c)\n"
+"{\n"
+" float4 eqn;\n"
+" float4 ab = b-a;\n"
+" float4 ac = c-a;\n"
+" eqn = normalize3( cross3(ab, ac) );\n"
+" eqn.w = -dot3F4(eqn,a);\n"
+" return eqn;\n"
+"}\n"
+"///////////////////////////////////////\n"
+"// Matrix3x3\n"
+"///////////////////////////////////////\n"
+"typedef struct\n"
+"{\n"
+" float4 m_row[3];\n"
+"}Matrix3x3;\n"
+"__inline\n"
+"Matrix3x3 mtZero();\n"
+"__inline\n"
+"Matrix3x3 mtIdentity();\n"
+"__inline\n"
+"Matrix3x3 mtTranspose(Matrix3x3 m);\n"
+"__inline\n"
+"Matrix3x3 mtMul(Matrix3x3 a, Matrix3x3 b);\n"
+"__inline\n"
+"float4 mtMul1(Matrix3x3 a, float4 b);\n"
+"__inline\n"
+"float4 mtMul3(float4 a, Matrix3x3 b);\n"
+"__inline\n"
+"Matrix3x3 mtZero()\n"
+"{\n"
+" Matrix3x3 m;\n"
+" m.m_row[0] = (float4)(0.f);\n"
+" m.m_row[1] = (float4)(0.f);\n"
+" m.m_row[2] = (float4)(0.f);\n"
+" return m;\n"
+"}\n"
+"__inline\n"
+"Matrix3x3 mtIdentity()\n"
+"{\n"
+" Matrix3x3 m;\n"
+" m.m_row[0] = (float4)(1,0,0,0);\n"
+" m.m_row[1] = (float4)(0,1,0,0);\n"
+" m.m_row[2] = (float4)(0,0,1,0);\n"
+" return m;\n"
+"}\n"
+"__inline\n"
+"Matrix3x3 mtTranspose(Matrix3x3 m)\n"
+"{\n"
+" Matrix3x3 out;\n"
+" out.m_row[0] = (float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);\n"
+" out.m_row[1] = (float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);\n"
+" out.m_row[2] = (float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);\n"
+" return out;\n"
+"}\n"
+"__inline\n"
+"Matrix3x3 mtMul(Matrix3x3 a, Matrix3x3 b)\n"
+"{\n"
+" Matrix3x3 transB;\n"
+" transB = mtTranspose( b );\n"
+" Matrix3x3 ans;\n"
+" // why this doesn't run when 0ing in the for{}\n"
+" a.m_row[0].w = 0.f;\n"
+" a.m_row[1].w = 0.f;\n"
+" a.m_row[2].w = 0.f;\n"
+" for(int i=0; i<3; i++)\n"
+" {\n"
+"// a.m_row[i].w = 0.f;\n"
+" ans.m_row[i].x = dot3F4(a.m_row[i],transB.m_row[0]);\n"
+" ans.m_row[i].y = dot3F4(a.m_row[i],transB.m_row[1]);\n"
+" ans.m_row[i].z = dot3F4(a.m_row[i],transB.m_row[2]);\n"
+" ans.m_row[i].w = 0.f;\n"
+" }\n"
+" return ans;\n"
+"}\n"
+"__inline\n"
+"float4 mtMul1(Matrix3x3 a, float4 b)\n"
+"{\n"
+" float4 ans;\n"
+" ans.x = dot3F4( a.m_row[0], b );\n"
+" ans.y = dot3F4( a.m_row[1], b );\n"
+" ans.z = dot3F4( a.m_row[2], b );\n"
+" ans.w = 0.f;\n"
+" return ans;\n"
+"}\n"
+"__inline\n"
+"float4 mtMul3(float4 a, Matrix3x3 b)\n"
+"{\n"
+" float4 colx = make_float4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
+" float4 coly = make_float4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
+" float4 colz = make_float4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
+" float4 ans;\n"
+" ans.x = dot3F4( a, colx );\n"
+" ans.y = dot3F4( a, coly );\n"
+" ans.z = dot3F4( a, colz );\n"
+" return ans;\n"
+"}\n"
+"///////////////////////////////////////\n"
+"// Quaternion\n"
+"///////////////////////////////////////\n"
+"typedef float4 Quaternion;\n"
+"__inline\n"
+"Quaternion qtMul(Quaternion a, Quaternion b);\n"
+"__inline\n"
+"Quaternion qtNormalize(Quaternion in);\n"
+"__inline\n"
+"float4 qtRotate(Quaternion q, float4 vec);\n"
+"__inline\n"
+"Quaternion qtInvert(Quaternion q);\n"
+"__inline\n"
+"Quaternion qtMul(Quaternion a, Quaternion b)\n"
+"{\n"
+" Quaternion ans;\n"
+" ans = cross3( a, b );\n"
+" ans += a.w*b+b.w*a;\n"
+"// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
+" ans.w = a.w*b.w - dot3F4(a, b);\n"
+" return ans;\n"
+"}\n"
+"__inline\n"
+"Quaternion qtNormalize(Quaternion in)\n"
+"{\n"
+" return fastNormalize4(in);\n"
+"// in /= length( in );\n"
+"// return in;\n"
+"}\n"
+"__inline\n"
+"float4 qtRotate(Quaternion q, float4 vec)\n"
+"{\n"
+" Quaternion qInv = qtInvert( q );\n"
+" float4 vcpy = vec;\n"
+" vcpy.w = 0.f;\n"
+" float4 out = qtMul(qtMul(q,vcpy),qInv);\n"
+" return out;\n"
+"}\n"
+"__inline\n"
+"Quaternion qtInvert(Quaternion q)\n"
+"{\n"
+" return (Quaternion)(-q.xyz, q.w);\n"
+"}\n"
+"__inline\n"
+"float4 qtInvRotate(const Quaternion q, float4 vec)\n"
+"{\n"
+" return qtRotate( qtInvert( q ), vec );\n"
+"}\n"
+"#define WG_SIZE 64\n"
+"typedef struct\n"
+"{\n"
+" float4 m_pos;\n"
+" Quaternion m_quat;\n"
+" float4 m_linVel;\n"
+" float4 m_angVel;\n"
+" u32 m_shapeIdx;\n"
+" float m_invMass;\n"
+" float m_restituitionCoeff;\n"
+" float m_frictionCoeff;\n"
+"} Body;\n"
+"typedef struct\n"
+"{\n"
+" Matrix3x3 m_invInertia;\n"
+" Matrix3x3 m_initInvInertia;\n"
+"} Shape;\n"
+"typedef struct\n"
+"{\n"
+" float4 m_linear;\n"
+" float4 m_worldPos[4];\n"
+" float4 m_center; \n"
+" float m_jacCoeffInv[4];\n"
+" float m_b[4];\n"
+" float m_appliedRambdaDt[4];\n"
+" float m_fJacCoeffInv[2]; \n"
+" float m_fAppliedRambdaDt[2]; \n"
+" u32 m_bodyA;\n"
+" u32 m_bodyB;\n"
+" int m_batchIdx;\n"
+" u32 m_paddings[1];\n"
+"} Constraint4;\n"
+"typedef struct\n"
+"{\n"
+" int m_nConstraints;\n"
+" int m_start;\n"
+" int m_batchIdx;\n"
+" int m_nSplit;\n"
+"// int m_paddings[1];\n"
+"} ConstBuffer;\n"
+"typedef struct\n"
+"{\n"
+" int m_solveFriction;\n"
+" int m_maxBatch; // long batch really kills the performance\n"
+" int m_batchIdx;\n"
+" int m_nSplit;\n"
+"// int m_paddings[1];\n"
+"} ConstBufferBatchSolve;\n"
+" \n"
+"typedef struct \n"
+"{\n"
+" int m_valInt0;\n"
+" int m_valInt1;\n"
+" int m_valInt2;\n"
+" int m_valInt3;\n"
+" float m_val0;\n"
+" float m_val1;\n"
+" float m_val2;\n"
+" float m_val3;\n"
+"} SolverDebugInfo;\n"
+"// others\n"
+"__kernel\n"
+"__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+"void ReorderContactKernel(__global struct b3Contact4Data* in, __global struct b3Contact4Data* out, __global int2* sortData, int4 cb )\n"
+"{\n"
+" int nContacts = cb.x;\n"
+" int gIdx = GET_GLOBAL_IDX;\n"
+" if( gIdx < nContacts )\n"
+" {\n"
+" int srcIdx = sortData[gIdx].y;\n"
+" out[gIdx] = in[srcIdx];\n"
+" }\n"
+"}\n"
+"__kernel __attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+"void SetDeterminismSortDataChildShapeB(__global struct b3Contact4Data* contactsIn, __global int2* sortDataOut, int nContacts)\n"
+"{\n"
+" int gIdx = GET_GLOBAL_IDX;\n"
+" if( gIdx < nContacts )\n"
+" {\n"
+" int2 sd;\n"
+" sd.x = contactsIn[gIdx].m_childIndexB;\n"
+" sd.y = gIdx;\n"
+" sortDataOut[gIdx] = sd;\n"
+" }\n"
+"}\n"
+"__kernel __attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+"void SetDeterminismSortDataChildShapeA(__global struct b3Contact4Data* contactsIn, __global int2* sortDataInOut, int nContacts)\n"
+"{\n"
+" int gIdx = GET_GLOBAL_IDX;\n"
+" if( gIdx < nContacts )\n"
+" {\n"
+" int2 sdIn;\n"
+" sdIn = sortDataInOut[gIdx];\n"
+" int2 sdOut;\n"
+" sdOut.x = contactsIn[sdIn.y].m_childIndexA;\n"
+" sdOut.y = sdIn.y;\n"
+" sortDataInOut[gIdx] = sdOut;\n"
+" }\n"
+"}\n"
+"__kernel __attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+"void SetDeterminismSortDataBodyA(__global struct b3Contact4Data* contactsIn, __global int2* sortDataInOut, int nContacts)\n"
+"{\n"
+" int gIdx = GET_GLOBAL_IDX;\n"
+" if( gIdx < nContacts )\n"
+" {\n"
+" int2 sdIn;\n"
+" sdIn = sortDataInOut[gIdx];\n"
+" int2 sdOut;\n"
+" sdOut.x = contactsIn[sdIn.y].m_bodyAPtrAndSignBit;\n"
+" sdOut.y = sdIn.y;\n"
+" sortDataInOut[gIdx] = sdOut;\n"
+" }\n"
+"}\n"
+"__kernel\n"
+"__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+"void SetDeterminismSortDataBodyB(__global struct b3Contact4Data* contactsIn, __global int2* sortDataInOut, int nContacts)\n"
+"{\n"
+" int gIdx = GET_GLOBAL_IDX;\n"
+" if( gIdx < nContacts )\n"
+" {\n"
+" int2 sdIn;\n"
+" sdIn = sortDataInOut[gIdx];\n"
+" int2 sdOut;\n"
+" sdOut.x = contactsIn[sdIn.y].m_bodyBPtrAndSignBit;\n"
+" sdOut.y = sdIn.y;\n"
+" sortDataInOut[gIdx] = sdOut;\n"
+" }\n"
+"}\n"
+"typedef struct\n"
+"{\n"
+" int m_nContacts;\n"
+" int m_staticIdx;\n"
+" float m_scale;\n"
+" int m_nSplit;\n"
+"} ConstBufferSSD;\n"
+"__constant const int gridTable4x4[] = \n"
+"{\n"
+" 0,1,17,16,\n"
+" 1,2,18,19,\n"
+" 17,18,32,3,\n"
+" 16,19,3,34\n"
+"};\n"
+"__constant const int gridTable8x8[] = \n"
+"{\n"
+" 0, 2, 3, 16, 17, 18, 19, 1,\n"
+" 66, 64, 80, 67, 82, 81, 65, 83,\n"
+" 131,144,128,130,147,129,145,146,\n"
+" 208,195,194,192,193,211,210,209,\n"
+" 21, 22, 23, 5, 4, 6, 7, 20,\n"
+" 86, 85, 69, 87, 70, 68, 84, 71,\n"
+" 151,133,149,150,135,148,132,134,\n"
+" 197,27,214,213,212,199,198,196\n"
+" \n"
+"};\n"
+"#define USE_SPATIAL_BATCHING 1\n"
+"#define USE_4x4_GRID 1\n"
+"__kernel\n"
+"__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+"void SetSortDataKernel(__global struct b3Contact4Data* gContact, __global Body* gBodies, __global int2* gSortDataOut, \n"
+"int nContacts,float scale,int4 nSplit,int staticIdx)\n"
+"{\n"
+" int gIdx = GET_GLOBAL_IDX;\n"
+" \n"
+" if( gIdx < nContacts )\n"
+" {\n"
+" int aPtrAndSignBit = gContact[gIdx].m_bodyAPtrAndSignBit;\n"
+" int bPtrAndSignBit = gContact[gIdx].m_bodyBPtrAndSignBit;\n"
+" int aIdx = abs(aPtrAndSignBit );\n"
+" int bIdx = abs(bPtrAndSignBit);\n"
+" bool aStatic = (aPtrAndSignBit<0) ||(aPtrAndSignBit==staticIdx);\n"
+" bool bStatic = (bPtrAndSignBit<0) ||(bPtrAndSignBit==staticIdx);\n"
+"#if USE_SPATIAL_BATCHING \n"
+" int idx = (aStatic)? bIdx: aIdx;\n"
+" float4 p = gBodies[idx].m_pos;\n"
+" int xIdx = (int)((p.x-((p.x<0.f)?1.f:0.f))*scale) & (nSplit.x-1);\n"
+" int yIdx = (int)((p.y-((p.y<0.f)?1.f:0.f))*scale) & (nSplit.y-1);\n"
+" int zIdx = (int)((p.z-((p.z<0.f)?1.f:0.f))*scale) & (nSplit.z-1);\n"
+" int newIndex = (xIdx+yIdx*nSplit.x+zIdx*nSplit.x*nSplit.y);\n"
+" \n"
+"#else//USE_SPATIAL_BATCHING\n"
+" #if USE_4x4_GRID\n"
+" int aa = aIdx&3;\n"
+" int bb = bIdx&3;\n"
+" if (aStatic)\n"
+" aa = bb;\n"
+" if (bStatic)\n"
+" bb = aa;\n"
+" int gridIndex = aa + bb*4;\n"
+" int newIndex = gridTable4x4[gridIndex];\n"
+" #else//USE_4x4_GRID\n"
+" int aa = aIdx&7;\n"
+" int bb = bIdx&7;\n"
+" if (aStatic)\n"
+" aa = bb;\n"
+" if (bStatic)\n"
+" bb = aa;\n"
+" int gridIndex = aa + bb*8;\n"
+" int newIndex = gridTable8x8[gridIndex];\n"
+" #endif//USE_4x4_GRID\n"
+"#endif//USE_SPATIAL_BATCHING\n"
+" gSortDataOut[gIdx].x = newIndex;\n"
+" gSortDataOut[gIdx].y = gIdx;\n"
+" }\n"
+" else\n"
+" {\n"
+" gSortDataOut[gIdx].x = 0xffffffff;\n"
+" }\n"
+"}\n"
+"__kernel\n"
+"__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+"void CopyConstraintKernel(__global struct b3Contact4Data* gIn, __global struct b3Contact4Data* gOut, int4 cb )\n"
+"{\n"
+" int gIdx = GET_GLOBAL_IDX;\n"
+" if( gIdx < cb.x )\n"
+" {\n"
+" gOut[gIdx] = gIn[gIdx];\n"
+" }\n"
+"}\n"
+;
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/solverUtils.cl b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/solverUtils.cl
new file mode 100644
index 0000000000..a21a08c3b4
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/solverUtils.cl
@@ -0,0 +1,968 @@
+/*
+Copyright (c) 2013 Advanced Micro Devices, Inc.
+
+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.
+*/
+//Originally written by Erwin Coumans
+
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h"
+
+#pragma OPENCL EXTENSION cl_amd_printf : enable
+#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable
+
+
+#ifdef cl_ext_atomic_counters_32
+#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable
+#else
+#define counter32_t volatile global int*
+#endif
+
+typedef unsigned int u32;
+typedef unsigned short u16;
+typedef unsigned char u8;
+
+#define GET_GROUP_IDX get_group_id(0)
+#define GET_LOCAL_IDX get_local_id(0)
+#define GET_GLOBAL_IDX get_global_id(0)
+#define GET_GROUP_SIZE get_local_size(0)
+#define GET_NUM_GROUPS get_num_groups(0)
+#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)
+#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)
+#define AtomInc(x) atom_inc(&(x))
+#define AtomInc1(x, out) out = atom_inc(&(x))
+#define AppendInc(x, out) out = atomic_inc(x)
+#define AtomAdd(x, value) atom_add(&(x), value)
+#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )
+#define AtomXhg(x, value) atom_xchg ( &(x), value )
+
+
+#define SELECT_UINT4( b, a, condition ) select( b,a,condition )
+
+#define make_float4 (float4)
+#define make_float2 (float2)
+#define make_uint4 (uint4)
+#define make_int4 (int4)
+#define make_uint2 (uint2)
+#define make_int2 (int2)
+
+
+#define max2 max
+#define min2 min
+
+
+///////////////////////////////////////
+// Vector
+///////////////////////////////////////
+__inline
+float fastDiv(float numerator, float denominator)
+{
+ return native_divide(numerator, denominator);
+// return numerator/denominator;
+}
+
+__inline
+float4 fastDiv4(float4 numerator, float4 denominator)
+{
+ return native_divide(numerator, denominator);
+}
+
+__inline
+float fastSqrtf(float f2)
+{
+ return native_sqrt(f2);
+// return sqrt(f2);
+}
+
+__inline
+float fastRSqrt(float f2)
+{
+ return native_rsqrt(f2);
+}
+
+__inline
+float fastLength4(float4 v)
+{
+ return fast_length(v);
+}
+
+__inline
+float4 fastNormalize4(float4 v)
+{
+ return fast_normalize(v);
+}
+
+
+__inline
+float sqrtf(float a)
+{
+// return sqrt(a);
+ return native_sqrt(a);
+}
+
+__inline
+float4 cross3(float4 a1, float4 b1)
+{
+
+ float4 a=make_float4(a1.xyz,0.f);
+ float4 b=make_float4(b1.xyz,0.f);
+ //float4 a=a1;
+ //float4 b=b1;
+ return cross(a,b);
+}
+
+__inline
+float dot3F4(float4 a, float4 b)
+{
+ float4 a1 = make_float4(a.xyz,0.f);
+ float4 b1 = make_float4(b.xyz,0.f);
+ return dot(a1, b1);
+}
+
+__inline
+float length3(const float4 a)
+{
+ return sqrtf(dot3F4(a,a));
+}
+
+__inline
+float dot4(const float4 a, const float4 b)
+{
+ return dot( a, b );
+}
+
+// for height
+__inline
+float dot3w1(const float4 point, const float4 eqn)
+{
+ return dot3F4(point,eqn) + eqn.w;
+}
+
+__inline
+float4 normalize3(const float4 a)
+{
+ float4 n = make_float4(a.x, a.y, a.z, 0.f);
+ return fastNormalize4( n );
+// float length = sqrtf(dot3F4(a, a));
+// return 1.f/length * a;
+}
+
+__inline
+float4 normalize4(const float4 a)
+{
+ float length = sqrtf(dot4(a, a));
+ return 1.f/length * a;
+}
+
+__inline
+float4 createEquation(const float4 a, const float4 b, const float4 c)
+{
+ float4 eqn;
+ float4 ab = b-a;
+ float4 ac = c-a;
+ eqn = normalize3( cross3(ab, ac) );
+ eqn.w = -dot3F4(eqn,a);
+ return eqn;
+}
+
+///////////////////////////////////////
+// Matrix3x3
+///////////////////////////////////////
+
+typedef struct
+{
+ float4 m_row[3];
+}Matrix3x3;
+
+__inline
+Matrix3x3 mtZero();
+
+__inline
+Matrix3x3 mtIdentity();
+
+__inline
+Matrix3x3 mtTranspose(Matrix3x3 m);
+
+__inline
+Matrix3x3 mtMul(Matrix3x3 a, Matrix3x3 b);
+
+__inline
+float4 mtMul1(Matrix3x3 a, float4 b);
+
+__inline
+float4 mtMul3(float4 a, Matrix3x3 b);
+
+__inline
+Matrix3x3 mtZero()
+{
+ Matrix3x3 m;
+ m.m_row[0] = (float4)(0.f);
+ m.m_row[1] = (float4)(0.f);
+ m.m_row[2] = (float4)(0.f);
+ return m;
+}
+
+__inline
+Matrix3x3 mtIdentity()
+{
+ Matrix3x3 m;
+ m.m_row[0] = (float4)(1,0,0,0);
+ m.m_row[1] = (float4)(0,1,0,0);
+ m.m_row[2] = (float4)(0,0,1,0);
+ return m;
+}
+
+__inline
+Matrix3x3 mtTranspose(Matrix3x3 m)
+{
+ Matrix3x3 out;
+ out.m_row[0] = (float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);
+ out.m_row[1] = (float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);
+ out.m_row[2] = (float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);
+ return out;
+}
+
+__inline
+Matrix3x3 mtMul(Matrix3x3 a, Matrix3x3 b)
+{
+ Matrix3x3 transB;
+ transB = mtTranspose( b );
+ Matrix3x3 ans;
+ // why this doesn't run when 0ing in the for{}
+ a.m_row[0].w = 0.f;
+ a.m_row[1].w = 0.f;
+ a.m_row[2].w = 0.f;
+ for(int i=0; i<3; i++)
+ {
+// a.m_row[i].w = 0.f;
+ ans.m_row[i].x = dot3F4(a.m_row[i],transB.m_row[0]);
+ ans.m_row[i].y = dot3F4(a.m_row[i],transB.m_row[1]);
+ ans.m_row[i].z = dot3F4(a.m_row[i],transB.m_row[2]);
+ ans.m_row[i].w = 0.f;
+ }
+ return ans;
+}
+
+__inline
+float4 mtMul1(Matrix3x3 a, float4 b)
+{
+ float4 ans;
+ ans.x = dot3F4( a.m_row[0], b );
+ ans.y = dot3F4( a.m_row[1], b );
+ ans.z = dot3F4( a.m_row[2], b );
+ ans.w = 0.f;
+ return ans;
+}
+
+__inline
+float4 mtMul3(float4 a, Matrix3x3 b)
+{
+ float4 colx = make_float4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);
+ float4 coly = make_float4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);
+ float4 colz = make_float4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);
+
+ float4 ans;
+ ans.x = dot3F4( a, colx );
+ ans.y = dot3F4( a, coly );
+ ans.z = dot3F4( a, colz );
+ return ans;
+}
+
+///////////////////////////////////////
+// Quaternion
+///////////////////////////////////////
+
+typedef float4 Quaternion;
+
+__inline
+Quaternion qtMul(Quaternion a, Quaternion b);
+
+__inline
+Quaternion qtNormalize(Quaternion in);
+
+__inline
+float4 qtRotate(Quaternion q, float4 vec);
+
+__inline
+Quaternion qtInvert(Quaternion q);
+
+
+
+
+
+__inline
+Quaternion qtMul(Quaternion a, Quaternion b)
+{
+ Quaternion ans;
+ ans = cross3( a, b );
+ ans += a.w*b+b.w*a;
+// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);
+ ans.w = a.w*b.w - dot3F4(a, b);
+ return ans;
+}
+
+__inline
+Quaternion qtNormalize(Quaternion in)
+{
+ return fastNormalize4(in);
+// in /= length( in );
+// return in;
+}
+__inline
+float4 qtRotate(Quaternion q, float4 vec)
+{
+ Quaternion qInv = qtInvert( q );
+ float4 vcpy = vec;
+ vcpy.w = 0.f;
+ float4 out = qtMul(qtMul(q,vcpy),qInv);
+ return out;
+}
+
+__inline
+Quaternion qtInvert(Quaternion q)
+{
+ return (Quaternion)(-q.xyz, q.w);
+}
+
+__inline
+float4 qtInvRotate(const Quaternion q, float4 vec)
+{
+ return qtRotate( qtInvert( q ), vec );
+}
+
+
+
+
+#define WG_SIZE 64
+
+typedef struct
+{
+ float4 m_pos;
+ Quaternion m_quat;
+ float4 m_linVel;
+ float4 m_angVel;
+
+ u32 m_shapeIdx;
+ float m_invMass;
+ float m_restituitionCoeff;
+ float m_frictionCoeff;
+} Body;
+
+
+
+typedef struct
+{
+ Matrix3x3 m_invInertia;
+ Matrix3x3 m_initInvInertia;
+} Shape;
+
+typedef struct
+{
+ float4 m_linear;
+ float4 m_worldPos[4];
+ float4 m_center;
+ float m_jacCoeffInv[4];
+ float m_b[4];
+ float m_appliedRambdaDt[4];
+
+ float m_fJacCoeffInv[2];
+ float m_fAppliedRambdaDt[2];
+
+ u32 m_bodyA;
+ u32 m_bodyB;
+ int m_batchIdx;
+ u32 m_paddings;
+} Constraint4;
+
+
+
+
+
+
+__kernel void CountBodiesKernel(__global struct b3Contact4Data* manifoldPtr, __global unsigned int* bodyCount, __global int2* contactConstraintOffsets, int numContactManifolds, int fixedBodyIndex)
+{
+ int i = GET_GLOBAL_IDX;
+
+ if( i < numContactManifolds)
+ {
+ int pa = manifoldPtr[i].m_bodyAPtrAndSignBit;
+ bool isFixedA = (pa <0) || (pa == fixedBodyIndex);
+ int bodyIndexA = abs(pa);
+ if (!isFixedA)
+ {
+ AtomInc1(bodyCount[bodyIndexA],contactConstraintOffsets[i].x);
+ }
+ barrier(CLK_GLOBAL_MEM_FENCE);
+ int pb = manifoldPtr[i].m_bodyBPtrAndSignBit;
+ bool isFixedB = (pb <0) || (pb == fixedBodyIndex);
+ int bodyIndexB = abs(pb);
+ if (!isFixedB)
+ {
+ AtomInc1(bodyCount[bodyIndexB],contactConstraintOffsets[i].y);
+ }
+ }
+}
+
+__kernel void ClearVelocitiesKernel(__global float4* linearVelocities,__global float4* angularVelocities, int numSplitBodies)
+{
+ int i = GET_GLOBAL_IDX;
+
+ if( i < numSplitBodies)
+ {
+ linearVelocities[i] = make_float4(0);
+ angularVelocities[i] = make_float4(0);
+ }
+}
+
+
+__kernel void AverageVelocitiesKernel(__global Body* gBodies,__global int* offsetSplitBodies,__global const unsigned int* bodyCount,
+__global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities, int numBodies)
+{
+ int i = GET_GLOBAL_IDX;
+ if (i<numBodies)
+ {
+ if (gBodies[i].m_invMass)
+ {
+ int bodyOffset = offsetSplitBodies[i];
+ int count = bodyCount[i];
+ float factor = 1.f/((float)count);
+ float4 averageLinVel = make_float4(0.f);
+ float4 averageAngVel = make_float4(0.f);
+
+ for (int j=0;j<count;j++)
+ {
+ averageLinVel += deltaLinearVelocities[bodyOffset+j]*factor;
+ averageAngVel += deltaAngularVelocities[bodyOffset+j]*factor;
+ }
+
+ for (int j=0;j<count;j++)
+ {
+ deltaLinearVelocities[bodyOffset+j] = averageLinVel;
+ deltaAngularVelocities[bodyOffset+j] = averageAngVel;
+ }
+
+ }//bodies[i].m_invMass
+ }//i<numBodies
+}
+
+
+
+void setLinearAndAngular( float4 n, float4 r0, float4 r1, float4* linear, float4* angular0, float4* angular1)
+{
+ *linear = make_float4(n.xyz,0.f);
+ *angular0 = cross3(r0, n);
+ *angular1 = -cross3(r1, n);
+}
+
+
+float calcRelVel( float4 l0, float4 l1, float4 a0, float4 a1, float4 linVel0, float4 angVel0, float4 linVel1, float4 angVel1 )
+{
+ return dot3F4(l0, linVel0) + dot3F4(a0, angVel0) + dot3F4(l1, linVel1) + dot3F4(a1, angVel1);
+}
+
+
+float calcJacCoeff(const float4 linear0, const float4 linear1, const float4 angular0, const float4 angular1,
+ float invMass0, const Matrix3x3* invInertia0, float invMass1, const Matrix3x3* invInertia1, float countA, float countB)
+{
+ // linear0,1 are normlized
+ float jmj0 = invMass0;//dot3F4(linear0, linear0)*invMass0;
+ float jmj1 = dot3F4(mtMul3(angular0,*invInertia0), angular0);
+ float jmj2 = invMass1;//dot3F4(linear1, linear1)*invMass1;
+ float jmj3 = dot3F4(mtMul3(angular1,*invInertia1), angular1);
+ return -1.f/((jmj0+jmj1)*countA+(jmj2+jmj3)*countB);
+}
+
+
+void btPlaneSpace1 (float4 n, float4* p, float4* q);
+ void btPlaneSpace1 (float4 n, float4* p, float4* q)
+{
+ if (fabs(n.z) > 0.70710678f) {
+ // choose p in y-z plane
+ float a = n.y*n.y + n.z*n.z;
+ float k = 1.f/sqrt(a);
+ p[0].x = 0;
+ p[0].y = -n.z*k;
+ p[0].z = n.y*k;
+ // set q = n x p
+ q[0].x = a*k;
+ q[0].y = -n.x*p[0].z;
+ q[0].z = n.x*p[0].y;
+ }
+ else {
+ // choose p in x-y plane
+ float a = n.x*n.x + n.y*n.y;
+ float k = 1.f/sqrt(a);
+ p[0].x = -n.y*k;
+ p[0].y = n.x*k;
+ p[0].z = 0;
+ // set q = n x p
+ q[0].x = -n.z*p[0].y;
+ q[0].y = n.z*p[0].x;
+ q[0].z = a*k;
+ }
+}
+
+
+
+
+
+void solveContact(__global Constraint4* cs,
+ float4 posA, float4* linVelA, float4* angVelA, float invMassA, Matrix3x3 invInertiaA,
+ float4 posB, float4* linVelB, float4* angVelB, float invMassB, Matrix3x3 invInertiaB,
+ float4* dLinVelA, float4* dAngVelA, float4* dLinVelB, float4* dAngVelB)
+{
+ float minRambdaDt = 0;
+ float maxRambdaDt = FLT_MAX;
+
+ for(int ic=0; ic<4; ic++)
+ {
+ if( cs->m_jacCoeffInv[ic] == 0.f ) continue;
+
+ float4 angular0, angular1, linear;
+ float4 r0 = cs->m_worldPos[ic] - posA;
+ float4 r1 = cs->m_worldPos[ic] - posB;
+ setLinearAndAngular( cs->m_linear, r0, r1, &linear, &angular0, &angular1 );
+
+
+
+ float rambdaDt = calcRelVel( cs->m_linear, -cs->m_linear, angular0, angular1,
+ *linVelA+*dLinVelA, *angVelA+*dAngVelA, *linVelB+*dLinVelB, *angVelB+*dAngVelB ) + cs->m_b[ic];
+ rambdaDt *= cs->m_jacCoeffInv[ic];
+
+
+ {
+ float prevSum = cs->m_appliedRambdaDt[ic];
+ float updated = prevSum;
+ updated += rambdaDt;
+ updated = max2( updated, minRambdaDt );
+ updated = min2( updated, maxRambdaDt );
+ rambdaDt = updated - prevSum;
+ cs->m_appliedRambdaDt[ic] = updated;
+ }
+
+
+ float4 linImp0 = invMassA*linear*rambdaDt;
+ float4 linImp1 = invMassB*(-linear)*rambdaDt;
+ float4 angImp0 = mtMul1(invInertiaA, angular0)*rambdaDt;
+ float4 angImp1 = mtMul1(invInertiaB, angular1)*rambdaDt;
+
+
+ if (invMassA)
+ {
+ *dLinVelA += linImp0;
+ *dAngVelA += angImp0;
+ }
+ if (invMassB)
+ {
+ *dLinVelB += linImp1;
+ *dAngVelB += angImp1;
+ }
+ }
+}
+
+
+// solveContactConstraint( gBodies, gShapes, &gConstraints[i] ,contactConstraintOffsets,offsetSplitBodies, deltaLinearVelocities, deltaAngularVelocities);
+
+
+void solveContactConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs,
+__global int2* contactConstraintOffsets,__global unsigned int* offsetSplitBodies,
+__global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities)
+{
+
+ //float frictionCoeff = ldsCs[0].m_linear.w;
+ int aIdx = ldsCs[0].m_bodyA;
+ int bIdx = ldsCs[0].m_bodyB;
+
+ float4 posA = gBodies[aIdx].m_pos;
+ float4 linVelA = gBodies[aIdx].m_linVel;
+ float4 angVelA = gBodies[aIdx].m_angVel;
+ float invMassA = gBodies[aIdx].m_invMass;
+ Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia;
+
+ float4 posB = gBodies[bIdx].m_pos;
+ float4 linVelB = gBodies[bIdx].m_linVel;
+ float4 angVelB = gBodies[bIdx].m_angVel;
+ float invMassB = gBodies[bIdx].m_invMass;
+ Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia;
+
+
+ float4 dLinVelA = make_float4(0,0,0,0);
+ float4 dAngVelA = make_float4(0,0,0,0);
+ float4 dLinVelB = make_float4(0,0,0,0);
+ float4 dAngVelB = make_float4(0,0,0,0);
+
+ int bodyOffsetA = offsetSplitBodies[aIdx];
+ int constraintOffsetA = contactConstraintOffsets[0].x;
+ int splitIndexA = bodyOffsetA+constraintOffsetA;
+
+ if (invMassA)
+ {
+ dLinVelA = deltaLinearVelocities[splitIndexA];
+ dAngVelA = deltaAngularVelocities[splitIndexA];
+ }
+
+ int bodyOffsetB = offsetSplitBodies[bIdx];
+ int constraintOffsetB = contactConstraintOffsets[0].y;
+ int splitIndexB= bodyOffsetB+constraintOffsetB;
+
+ if (invMassB)
+ {
+ dLinVelB = deltaLinearVelocities[splitIndexB];
+ dAngVelB = deltaAngularVelocities[splitIndexB];
+ }
+
+ solveContact( ldsCs, posA, &linVelA, &angVelA, invMassA, invInertiaA,
+ posB, &linVelB, &angVelB, invMassB, invInertiaB ,&dLinVelA, &dAngVelA, &dLinVelB, &dAngVelB);
+
+ if (invMassA)
+ {
+ deltaLinearVelocities[splitIndexA] = dLinVelA;
+ deltaAngularVelocities[splitIndexA] = dAngVelA;
+ }
+ if (invMassB)
+ {
+ deltaLinearVelocities[splitIndexB] = dLinVelB;
+ deltaAngularVelocities[splitIndexB] = dAngVelB;
+ }
+
+}
+
+
+__kernel void SolveContactJacobiKernel(__global Constraint4* gConstraints, __global Body* gBodies, __global Shape* gShapes ,
+__global int2* contactConstraintOffsets,__global unsigned int* offsetSplitBodies,__global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities,
+float deltaTime, float positionDrift, float positionConstraintCoeff, int fixedBodyIndex, int numManifolds
+)
+{
+ int i = GET_GLOBAL_IDX;
+ if (i<numManifolds)
+ {
+ solveContactConstraint( gBodies, gShapes, &gConstraints[i] ,&contactConstraintOffsets[i],offsetSplitBodies, deltaLinearVelocities, deltaAngularVelocities);
+ }
+}
+
+
+
+
+void solveFrictionConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs,
+ __global int2* contactConstraintOffsets,__global unsigned int* offsetSplitBodies,
+ __global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities)
+{
+ float frictionCoeff = 0.7f;//ldsCs[0].m_linear.w;
+ int aIdx = ldsCs[0].m_bodyA;
+ int bIdx = ldsCs[0].m_bodyB;
+
+
+ float4 posA = gBodies[aIdx].m_pos;
+ float4 linVelA = gBodies[aIdx].m_linVel;
+ float4 angVelA = gBodies[aIdx].m_angVel;
+ float invMassA = gBodies[aIdx].m_invMass;
+ Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia;
+
+ float4 posB = gBodies[bIdx].m_pos;
+ float4 linVelB = gBodies[bIdx].m_linVel;
+ float4 angVelB = gBodies[bIdx].m_angVel;
+ float invMassB = gBodies[bIdx].m_invMass;
+ Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia;
+
+
+ float4 dLinVelA = make_float4(0,0,0,0);
+ float4 dAngVelA = make_float4(0,0,0,0);
+ float4 dLinVelB = make_float4(0,0,0,0);
+ float4 dAngVelB = make_float4(0,0,0,0);
+
+ int bodyOffsetA = offsetSplitBodies[aIdx];
+ int constraintOffsetA = contactConstraintOffsets[0].x;
+ int splitIndexA = bodyOffsetA+constraintOffsetA;
+
+ if (invMassA)
+ {
+ dLinVelA = deltaLinearVelocities[splitIndexA];
+ dAngVelA = deltaAngularVelocities[splitIndexA];
+ }
+
+ int bodyOffsetB = offsetSplitBodies[bIdx];
+ int constraintOffsetB = contactConstraintOffsets[0].y;
+ int splitIndexB= bodyOffsetB+constraintOffsetB;
+
+ if (invMassB)
+ {
+ dLinVelB = deltaLinearVelocities[splitIndexB];
+ dAngVelB = deltaAngularVelocities[splitIndexB];
+ }
+
+
+
+
+ {
+ float maxRambdaDt[4] = {FLT_MAX,FLT_MAX,FLT_MAX,FLT_MAX};
+ float minRambdaDt[4] = {0.f,0.f,0.f,0.f};
+
+ float sum = 0;
+ for(int j=0; j<4; j++)
+ {
+ sum +=ldsCs[0].m_appliedRambdaDt[j];
+ }
+ frictionCoeff = 0.7f;
+ for(int j=0; j<4; j++)
+ {
+ maxRambdaDt[j] = frictionCoeff*sum;
+ minRambdaDt[j] = -maxRambdaDt[j];
+ }
+
+
+// solveFriction( ldsCs, posA, &linVelA, &angVelA, invMassA, invInertiaA,
+// posB, &linVelB, &angVelB, invMassB, invInertiaB, maxRambdaDt, minRambdaDt );
+
+
+ {
+
+ __global Constraint4* cs = ldsCs;
+
+ if( cs->m_fJacCoeffInv[0] == 0 && cs->m_fJacCoeffInv[0] == 0 ) return;
+ const float4 center = cs->m_center;
+
+ float4 n = -cs->m_linear;
+
+ float4 tangent[2];
+ btPlaneSpace1(n,&tangent[0],&tangent[1]);
+ float4 angular0, angular1, linear;
+ float4 r0 = center - posA;
+ float4 r1 = center - posB;
+ for(int i=0; i<2; i++)
+ {
+ setLinearAndAngular( tangent[i], r0, r1, &linear, &angular0, &angular1 );
+ float rambdaDt = calcRelVel(linear, -linear, angular0, angular1,
+ linVelA+dLinVelA, angVelA+dAngVelA, linVelB+dLinVelB, angVelB+dAngVelB );
+ rambdaDt *= cs->m_fJacCoeffInv[i];
+
+ {
+ float prevSum = cs->m_fAppliedRambdaDt[i];
+ float updated = prevSum;
+ updated += rambdaDt;
+ updated = max2( updated, minRambdaDt[i] );
+ updated = min2( updated, maxRambdaDt[i] );
+ rambdaDt = updated - prevSum;
+ cs->m_fAppliedRambdaDt[i] = updated;
+ }
+
+ float4 linImp0 = invMassA*linear*rambdaDt;
+ float4 linImp1 = invMassB*(-linear)*rambdaDt;
+ float4 angImp0 = mtMul1(invInertiaA, angular0)*rambdaDt;
+ float4 angImp1 = mtMul1(invInertiaB, angular1)*rambdaDt;
+
+ dLinVelA += linImp0;
+ dAngVelA += angImp0;
+ dLinVelB += linImp1;
+ dAngVelB += angImp1;
+ }
+ { // angular damping for point constraint
+ float4 ab = normalize3( posB - posA );
+ float4 ac = normalize3( center - posA );
+ if( dot3F4( ab, ac ) > 0.95f || (invMassA == 0.f || invMassB == 0.f))
+ {
+ float angNA = dot3F4( n, angVelA );
+ float angNB = dot3F4( n, angVelB );
+
+ dAngVelA -= (angNA*0.1f)*n;
+ dAngVelB -= (angNB*0.1f)*n;
+ }
+ }
+ }
+
+
+
+ }
+
+ if (invMassA)
+ {
+ deltaLinearVelocities[splitIndexA] = dLinVelA;
+ deltaAngularVelocities[splitIndexA] = dAngVelA;
+ }
+ if (invMassB)
+ {
+ deltaLinearVelocities[splitIndexB] = dLinVelB;
+ deltaAngularVelocities[splitIndexB] = dAngVelB;
+ }
+
+
+}
+
+
+__kernel void SolveFrictionJacobiKernel(__global Constraint4* gConstraints, __global Body* gBodies, __global Shape* gShapes ,
+ __global int2* contactConstraintOffsets,__global unsigned int* offsetSplitBodies,
+ __global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities,
+ float deltaTime, float positionDrift, float positionConstraintCoeff, int fixedBodyIndex, int numManifolds
+)
+{
+ int i = GET_GLOBAL_IDX;
+ if (i<numManifolds)
+ {
+ solveFrictionConstraint( gBodies, gShapes, &gConstraints[i] ,&contactConstraintOffsets[i],offsetSplitBodies, deltaLinearVelocities, deltaAngularVelocities);
+ }
+}
+
+
+__kernel void UpdateBodyVelocitiesKernel(__global Body* gBodies,__global int* offsetSplitBodies,__global const unsigned int* bodyCount,
+ __global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities, int numBodies)
+{
+ int i = GET_GLOBAL_IDX;
+ if (i<numBodies)
+ {
+ if (gBodies[i].m_invMass)
+ {
+ int bodyOffset = offsetSplitBodies[i];
+ int count = bodyCount[i];
+ if (count)
+ {
+ gBodies[i].m_linVel += deltaLinearVelocities[bodyOffset];
+ gBodies[i].m_angVel += deltaAngularVelocities[bodyOffset];
+ }
+ }
+ }
+}
+
+
+
+void setConstraint4( const float4 posA, const float4 linVelA, const float4 angVelA, float invMassA, const Matrix3x3 invInertiaA,
+ const float4 posB, const float4 linVelB, const float4 angVelB, float invMassB, const Matrix3x3 invInertiaB,
+ __global struct b3Contact4Data* src, float dt, float positionDrift, float positionConstraintCoeff,float countA, float countB,
+ Constraint4* dstC )
+{
+ dstC->m_bodyA = abs(src->m_bodyAPtrAndSignBit);
+ dstC->m_bodyB = abs(src->m_bodyBPtrAndSignBit);
+
+ float dtInv = 1.f/dt;
+ for(int ic=0; ic<4; ic++)
+ {
+ dstC->m_appliedRambdaDt[ic] = 0.f;
+ }
+ dstC->m_fJacCoeffInv[0] = dstC->m_fJacCoeffInv[1] = 0.f;
+
+
+ dstC->m_linear = src->m_worldNormalOnB;
+ dstC->m_linear.w = 0.7f ;//src->getFrictionCoeff() );
+ for(int ic=0; ic<4; ic++)
+ {
+ float4 r0 = src->m_worldPosB[ic] - posA;
+ float4 r1 = src->m_worldPosB[ic] - posB;
+
+ if( ic >= src->m_worldNormalOnB.w )//npoints
+ {
+ dstC->m_jacCoeffInv[ic] = 0.f;
+ continue;
+ }
+
+ float relVelN;
+ {
+ float4 linear, angular0, angular1;
+ setLinearAndAngular(src->m_worldNormalOnB, r0, r1, &linear, &angular0, &angular1);
+
+ dstC->m_jacCoeffInv[ic] = calcJacCoeff(linear, -linear, angular0, angular1,
+ invMassA, &invInertiaA, invMassB, &invInertiaB , countA, countB);
+
+ relVelN = calcRelVel(linear, -linear, angular0, angular1,
+ linVelA, angVelA, linVelB, angVelB);
+
+ float e = 0.f;//src->getRestituitionCoeff();
+ if( relVelN*relVelN < 0.004f ) e = 0.f;
+
+ dstC->m_b[ic] = e*relVelN;
+ //float penetration = src->m_worldPosB[ic].w;
+ dstC->m_b[ic] += (src->m_worldPosB[ic].w + positionDrift)*positionConstraintCoeff*dtInv;
+ dstC->m_appliedRambdaDt[ic] = 0.f;
+ }
+ }
+
+ if( src->m_worldNormalOnB.w > 0 )//npoints
+ { // prepare friction
+ float4 center = make_float4(0.f);
+ for(int i=0; i<src->m_worldNormalOnB.w; i++)
+ center += src->m_worldPosB[i];
+ center /= (float)src->m_worldNormalOnB.w;
+
+ float4 tangent[2];
+ btPlaneSpace1(-src->m_worldNormalOnB,&tangent[0],&tangent[1]);
+
+ float4 r[2];
+ r[0] = center - posA;
+ r[1] = center - posB;
+
+ for(int i=0; i<2; i++)
+ {
+ float4 linear, angular0, angular1;
+ setLinearAndAngular(tangent[i], r[0], r[1], &linear, &angular0, &angular1);
+
+ dstC->m_fJacCoeffInv[i] = calcJacCoeff(linear, -linear, angular0, angular1,
+ invMassA, &invInertiaA, invMassB, &invInertiaB ,countA, countB);
+ dstC->m_fAppliedRambdaDt[i] = 0.f;
+ }
+ dstC->m_center = center;
+ }
+
+ for(int i=0; i<4; i++)
+ {
+ if( i<src->m_worldNormalOnB.w )
+ {
+ dstC->m_worldPos[i] = src->m_worldPosB[i];
+ }
+ else
+ {
+ dstC->m_worldPos[i] = make_float4(0.f);
+ }
+ }
+}
+
+
+__kernel
+__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
+void ContactToConstraintSplitKernel(__global const struct b3Contact4Data* gContact, __global const Body* gBodies, __global const Shape* gShapes, __global Constraint4* gConstraintOut,
+__global const unsigned int* bodyCount,
+int nContacts,
+float dt,
+float positionDrift,
+float positionConstraintCoeff
+)
+{
+ int gIdx = GET_GLOBAL_IDX;
+
+ if( gIdx < nContacts )
+ {
+ int aIdx = abs(gContact[gIdx].m_bodyAPtrAndSignBit);
+ int bIdx = abs(gContact[gIdx].m_bodyBPtrAndSignBit);
+
+ float4 posA = gBodies[aIdx].m_pos;
+ float4 linVelA = gBodies[aIdx].m_linVel;
+ float4 angVelA = gBodies[aIdx].m_angVel;
+ float invMassA = gBodies[aIdx].m_invMass;
+ Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia;
+
+ float4 posB = gBodies[bIdx].m_pos;
+ float4 linVelB = gBodies[bIdx].m_linVel;
+ float4 angVelB = gBodies[bIdx].m_angVel;
+ float invMassB = gBodies[bIdx].m_invMass;
+ Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia;
+
+ Constraint4 cs;
+
+ float countA = invMassA != 0.f ? (float)bodyCount[aIdx] : 1;
+ float countB = invMassB != 0.f ? (float)bodyCount[bIdx] : 1;
+
+ setConstraint4( posA, linVelA, angVelA, invMassA, invInertiaA, posB, linVelB, angVelB, invMassB, invInertiaB,
+ &gContact[gIdx], dt, positionDrift, positionConstraintCoeff,countA,countB,
+ &cs );
+
+ cs.m_batchIdx = gContact[gIdx].m_batchIdx;
+
+ gConstraintOut[gIdx] = cs;
+ }
+} \ No newline at end of file
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/solverUtils.h b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/solverUtils.h
new file mode 100644
index 0000000000..c0173ad9f4
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/solverUtils.h
@@ -0,0 +1,909 @@
+//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
+static const char* solverUtilsCL= \
+"/*\n"
+"Copyright (c) 2013 Advanced Micro Devices, Inc. \n"
+"This software is provided 'as-is', without any express or implied warranty.\n"
+"In no event will the authors be held liable for any damages arising from the use of this software.\n"
+"Permission is granted to anyone to use this software for any purpose, \n"
+"including commercial applications, and to alter it and redistribute it freely, \n"
+"subject to the following restrictions:\n"
+"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.\n"
+"2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
+"3. This notice may not be removed or altered from any source distribution.\n"
+"*/\n"
+"//Originally written by Erwin Coumans\n"
+"#ifndef B3_CONTACT4DATA_H\n"
+"#define B3_CONTACT4DATA_H\n"
+"#ifndef B3_FLOAT4_H\n"
+"#define B3_FLOAT4_H\n"
+"#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+"#define B3_PLATFORM_DEFINITIONS_H\n"
+"struct MyTest\n"
+"{\n"
+" int bla;\n"
+"};\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
+"#define B3_LARGE_FLOAT 1e18f\n"
+"#define B3_INFINITY 1e18f\n"
+"#define b3Assert(a)\n"
+"#define b3ConstArray(a) __global const a*\n"
+"#define b3AtomicInc atomic_inc\n"
+"#define b3AtomicAdd atomic_add\n"
+"#define b3Fabs fabs\n"
+"#define b3Sqrt native_sqrt\n"
+"#define b3Sin native_sin\n"
+"#define b3Cos native_cos\n"
+"#define B3_STATIC\n"
+"#endif\n"
+"#endif\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+" typedef float4 b3Float4;\n"
+" #define b3Float4ConstArg const b3Float4\n"
+" #define b3MakeFloat4 (float4)\n"
+" float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+" {\n"
+" float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+" float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+" return dot(a1, b1);\n"
+" }\n"
+" b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+" {\n"
+" float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+" float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+" return cross(a1, b1);\n"
+" }\n"
+" #define b3MinFloat4 min\n"
+" #define b3MaxFloat4 max\n"
+" #define b3Normalized(a) normalize(a)\n"
+"#endif \n"
+" \n"
+"inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
+"{\n"
+" if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6) \n"
+" return false;\n"
+" return true;\n"
+"}\n"
+"inline int b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
+"{\n"
+" float maxDot = -B3_INFINITY;\n"
+" int i = 0;\n"
+" int ptIndex = -1;\n"
+" for( i = 0; i < vecLen; i++ )\n"
+" {\n"
+" float dot = b3Dot3F4(vecArray[i],vec);\n"
+" \n"
+" if( dot > maxDot )\n"
+" {\n"
+" maxDot = dot;\n"
+" ptIndex = i;\n"
+" }\n"
+" }\n"
+" b3Assert(ptIndex>=0);\n"
+" if (ptIndex<0)\n"
+" {\n"
+" ptIndex = 0;\n"
+" }\n"
+" *dotOut = maxDot;\n"
+" return ptIndex;\n"
+"}\n"
+"#endif //B3_FLOAT4_H\n"
+"typedef struct b3Contact4Data b3Contact4Data_t;\n"
+"struct b3Contact4Data\n"
+"{\n"
+" b3Float4 m_worldPosB[4];\n"
+"// b3Float4 m_localPosA[4];\n"
+"// b3Float4 m_localPosB[4];\n"
+" b3Float4 m_worldNormalOnB; // w: m_nPoints\n"
+" unsigned short m_restituitionCoeffCmp;\n"
+" unsigned short m_frictionCoeffCmp;\n"
+" int m_batchIdx;\n"
+" int m_bodyAPtrAndSignBit;//x:m_bodyAPtr, y:m_bodyBPtr\n"
+" int m_bodyBPtrAndSignBit;\n"
+" int m_childIndexA;\n"
+" int m_childIndexB;\n"
+" int m_unused1;\n"
+" int m_unused2;\n"
+"};\n"
+"inline int b3Contact4Data_getNumPoints(const struct b3Contact4Data* contact)\n"
+"{\n"
+" return (int)contact->m_worldNormalOnB.w;\n"
+"};\n"
+"inline void b3Contact4Data_setNumPoints(struct b3Contact4Data* contact, int numPoints)\n"
+"{\n"
+" contact->m_worldNormalOnB.w = (float)numPoints;\n"
+"};\n"
+"#endif //B3_CONTACT4DATA_H\n"
+"#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
+"#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
+"#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
+"#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n"
+"#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n"
+"#ifdef cl_ext_atomic_counters_32\n"
+"#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n"
+"#else\n"
+"#define counter32_t volatile global int*\n"
+"#endif\n"
+"typedef unsigned int u32;\n"
+"typedef unsigned short u16;\n"
+"typedef unsigned char u8;\n"
+"#define GET_GROUP_IDX get_group_id(0)\n"
+"#define GET_LOCAL_IDX get_local_id(0)\n"
+"#define GET_GLOBAL_IDX get_global_id(0)\n"
+"#define GET_GROUP_SIZE get_local_size(0)\n"
+"#define GET_NUM_GROUPS get_num_groups(0)\n"
+"#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
+"#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
+"#define AtomInc(x) atom_inc(&(x))\n"
+"#define AtomInc1(x, out) out = atom_inc(&(x))\n"
+"#define AppendInc(x, out) out = atomic_inc(x)\n"
+"#define AtomAdd(x, value) atom_add(&(x), value)\n"
+"#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )\n"
+"#define AtomXhg(x, value) atom_xchg ( &(x), value )\n"
+"#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n"
+"#define make_float4 (float4)\n"
+"#define make_float2 (float2)\n"
+"#define make_uint4 (uint4)\n"
+"#define make_int4 (int4)\n"
+"#define make_uint2 (uint2)\n"
+"#define make_int2 (int2)\n"
+"#define max2 max\n"
+"#define min2 min\n"
+"///////////////////////////////////////\n"
+"// Vector\n"
+"///////////////////////////////////////\n"
+"__inline\n"
+"float fastDiv(float numerator, float denominator)\n"
+"{\n"
+" return native_divide(numerator, denominator); \n"
+"// return numerator/denominator; \n"
+"}\n"
+"__inline\n"
+"float4 fastDiv4(float4 numerator, float4 denominator)\n"
+"{\n"
+" return native_divide(numerator, denominator); \n"
+"}\n"
+"__inline\n"
+"float fastSqrtf(float f2)\n"
+"{\n"
+" return native_sqrt(f2);\n"
+"// return sqrt(f2);\n"
+"}\n"
+"__inline\n"
+"float fastRSqrt(float f2)\n"
+"{\n"
+" return native_rsqrt(f2);\n"
+"}\n"
+"__inline\n"
+"float fastLength4(float4 v)\n"
+"{\n"
+" return fast_length(v);\n"
+"}\n"
+"__inline\n"
+"float4 fastNormalize4(float4 v)\n"
+"{\n"
+" return fast_normalize(v);\n"
+"}\n"
+"__inline\n"
+"float sqrtf(float a)\n"
+"{\n"
+"// return sqrt(a);\n"
+" return native_sqrt(a);\n"
+"}\n"
+"__inline\n"
+"float4 cross3(float4 a1, float4 b1)\n"
+"{\n"
+" float4 a=make_float4(a1.xyz,0.f);\n"
+" float4 b=make_float4(b1.xyz,0.f);\n"
+" //float4 a=a1;\n"
+" //float4 b=b1;\n"
+" return cross(a,b);\n"
+"}\n"
+"__inline\n"
+"float dot3F4(float4 a, float4 b)\n"
+"{\n"
+" float4 a1 = make_float4(a.xyz,0.f);\n"
+" float4 b1 = make_float4(b.xyz,0.f);\n"
+" return dot(a1, b1);\n"
+"}\n"
+"__inline\n"
+"float length3(const float4 a)\n"
+"{\n"
+" return sqrtf(dot3F4(a,a));\n"
+"}\n"
+"__inline\n"
+"float dot4(const float4 a, const float4 b)\n"
+"{\n"
+" return dot( a, b );\n"
+"}\n"
+"// for height\n"
+"__inline\n"
+"float dot3w1(const float4 point, const float4 eqn)\n"
+"{\n"
+" return dot3F4(point,eqn) + eqn.w;\n"
+"}\n"
+"__inline\n"
+"float4 normalize3(const float4 a)\n"
+"{\n"
+" float4 n = make_float4(a.x, a.y, a.z, 0.f);\n"
+" return fastNormalize4( n );\n"
+"// float length = sqrtf(dot3F4(a, a));\n"
+"// return 1.f/length * a;\n"
+"}\n"
+"__inline\n"
+"float4 normalize4(const float4 a)\n"
+"{\n"
+" float length = sqrtf(dot4(a, a));\n"
+" return 1.f/length * a;\n"
+"}\n"
+"__inline\n"
+"float4 createEquation(const float4 a, const float4 b, const float4 c)\n"
+"{\n"
+" float4 eqn;\n"
+" float4 ab = b-a;\n"
+" float4 ac = c-a;\n"
+" eqn = normalize3( cross3(ab, ac) );\n"
+" eqn.w = -dot3F4(eqn,a);\n"
+" return eqn;\n"
+"}\n"
+"///////////////////////////////////////\n"
+"// Matrix3x3\n"
+"///////////////////////////////////////\n"
+"typedef struct\n"
+"{\n"
+" float4 m_row[3];\n"
+"}Matrix3x3;\n"
+"__inline\n"
+"Matrix3x3 mtZero();\n"
+"__inline\n"
+"Matrix3x3 mtIdentity();\n"
+"__inline\n"
+"Matrix3x3 mtTranspose(Matrix3x3 m);\n"
+"__inline\n"
+"Matrix3x3 mtMul(Matrix3x3 a, Matrix3x3 b);\n"
+"__inline\n"
+"float4 mtMul1(Matrix3x3 a, float4 b);\n"
+"__inline\n"
+"float4 mtMul3(float4 a, Matrix3x3 b);\n"
+"__inline\n"
+"Matrix3x3 mtZero()\n"
+"{\n"
+" Matrix3x3 m;\n"
+" m.m_row[0] = (float4)(0.f);\n"
+" m.m_row[1] = (float4)(0.f);\n"
+" m.m_row[2] = (float4)(0.f);\n"
+" return m;\n"
+"}\n"
+"__inline\n"
+"Matrix3x3 mtIdentity()\n"
+"{\n"
+" Matrix3x3 m;\n"
+" m.m_row[0] = (float4)(1,0,0,0);\n"
+" m.m_row[1] = (float4)(0,1,0,0);\n"
+" m.m_row[2] = (float4)(0,0,1,0);\n"
+" return m;\n"
+"}\n"
+"__inline\n"
+"Matrix3x3 mtTranspose(Matrix3x3 m)\n"
+"{\n"
+" Matrix3x3 out;\n"
+" out.m_row[0] = (float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);\n"
+" out.m_row[1] = (float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);\n"
+" out.m_row[2] = (float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);\n"
+" return out;\n"
+"}\n"
+"__inline\n"
+"Matrix3x3 mtMul(Matrix3x3 a, Matrix3x3 b)\n"
+"{\n"
+" Matrix3x3 transB;\n"
+" transB = mtTranspose( b );\n"
+" Matrix3x3 ans;\n"
+" // why this doesn't run when 0ing in the for{}\n"
+" a.m_row[0].w = 0.f;\n"
+" a.m_row[1].w = 0.f;\n"
+" a.m_row[2].w = 0.f;\n"
+" for(int i=0; i<3; i++)\n"
+" {\n"
+"// a.m_row[i].w = 0.f;\n"
+" ans.m_row[i].x = dot3F4(a.m_row[i],transB.m_row[0]);\n"
+" ans.m_row[i].y = dot3F4(a.m_row[i],transB.m_row[1]);\n"
+" ans.m_row[i].z = dot3F4(a.m_row[i],transB.m_row[2]);\n"
+" ans.m_row[i].w = 0.f;\n"
+" }\n"
+" return ans;\n"
+"}\n"
+"__inline\n"
+"float4 mtMul1(Matrix3x3 a, float4 b)\n"
+"{\n"
+" float4 ans;\n"
+" ans.x = dot3F4( a.m_row[0], b );\n"
+" ans.y = dot3F4( a.m_row[1], b );\n"
+" ans.z = dot3F4( a.m_row[2], b );\n"
+" ans.w = 0.f;\n"
+" return ans;\n"
+"}\n"
+"__inline\n"
+"float4 mtMul3(float4 a, Matrix3x3 b)\n"
+"{\n"
+" float4 colx = make_float4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
+" float4 coly = make_float4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
+" float4 colz = make_float4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
+" float4 ans;\n"
+" ans.x = dot3F4( a, colx );\n"
+" ans.y = dot3F4( a, coly );\n"
+" ans.z = dot3F4( a, colz );\n"
+" return ans;\n"
+"}\n"
+"///////////////////////////////////////\n"
+"// Quaternion\n"
+"///////////////////////////////////////\n"
+"typedef float4 Quaternion;\n"
+"__inline\n"
+"Quaternion qtMul(Quaternion a, Quaternion b);\n"
+"__inline\n"
+"Quaternion qtNormalize(Quaternion in);\n"
+"__inline\n"
+"float4 qtRotate(Quaternion q, float4 vec);\n"
+"__inline\n"
+"Quaternion qtInvert(Quaternion q);\n"
+"__inline\n"
+"Quaternion qtMul(Quaternion a, Quaternion b)\n"
+"{\n"
+" Quaternion ans;\n"
+" ans = cross3( a, b );\n"
+" ans += a.w*b+b.w*a;\n"
+"// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
+" ans.w = a.w*b.w - dot3F4(a, b);\n"
+" return ans;\n"
+"}\n"
+"__inline\n"
+"Quaternion qtNormalize(Quaternion in)\n"
+"{\n"
+" return fastNormalize4(in);\n"
+"// in /= length( in );\n"
+"// return in;\n"
+"}\n"
+"__inline\n"
+"float4 qtRotate(Quaternion q, float4 vec)\n"
+"{\n"
+" Quaternion qInv = qtInvert( q );\n"
+" float4 vcpy = vec;\n"
+" vcpy.w = 0.f;\n"
+" float4 out = qtMul(qtMul(q,vcpy),qInv);\n"
+" return out;\n"
+"}\n"
+"__inline\n"
+"Quaternion qtInvert(Quaternion q)\n"
+"{\n"
+" return (Quaternion)(-q.xyz, q.w);\n"
+"}\n"
+"__inline\n"
+"float4 qtInvRotate(const Quaternion q, float4 vec)\n"
+"{\n"
+" return qtRotate( qtInvert( q ), vec );\n"
+"}\n"
+"#define WG_SIZE 64\n"
+"typedef struct\n"
+"{\n"
+" float4 m_pos;\n"
+" Quaternion m_quat;\n"
+" float4 m_linVel;\n"
+" float4 m_angVel;\n"
+" u32 m_shapeIdx;\n"
+" float m_invMass;\n"
+" float m_restituitionCoeff;\n"
+" float m_frictionCoeff;\n"
+"} Body;\n"
+"typedef struct\n"
+"{\n"
+" Matrix3x3 m_invInertia;\n"
+" Matrix3x3 m_initInvInertia;\n"
+"} Shape;\n"
+"typedef struct\n"
+"{\n"
+" float4 m_linear;\n"
+" float4 m_worldPos[4];\n"
+" float4 m_center; \n"
+" float m_jacCoeffInv[4];\n"
+" float m_b[4];\n"
+" float m_appliedRambdaDt[4];\n"
+" float m_fJacCoeffInv[2]; \n"
+" float m_fAppliedRambdaDt[2]; \n"
+" u32 m_bodyA;\n"
+" u32 m_bodyB;\n"
+" int m_batchIdx;\n"
+" u32 m_paddings;\n"
+"} Constraint4;\n"
+"__kernel void CountBodiesKernel(__global struct b3Contact4Data* manifoldPtr, __global unsigned int* bodyCount, __global int2* contactConstraintOffsets, int numContactManifolds, int fixedBodyIndex)\n"
+"{\n"
+" int i = GET_GLOBAL_IDX;\n"
+" \n"
+" if( i < numContactManifolds)\n"
+" {\n"
+" int pa = manifoldPtr[i].m_bodyAPtrAndSignBit;\n"
+" bool isFixedA = (pa <0) || (pa == fixedBodyIndex);\n"
+" int bodyIndexA = abs(pa);\n"
+" if (!isFixedA)\n"
+" {\n"
+" AtomInc1(bodyCount[bodyIndexA],contactConstraintOffsets[i].x);\n"
+" }\n"
+" barrier(CLK_GLOBAL_MEM_FENCE);\n"
+" int pb = manifoldPtr[i].m_bodyBPtrAndSignBit;\n"
+" bool isFixedB = (pb <0) || (pb == fixedBodyIndex);\n"
+" int bodyIndexB = abs(pb);\n"
+" if (!isFixedB)\n"
+" {\n"
+" AtomInc1(bodyCount[bodyIndexB],contactConstraintOffsets[i].y);\n"
+" } \n"
+" }\n"
+"}\n"
+"__kernel void ClearVelocitiesKernel(__global float4* linearVelocities,__global float4* angularVelocities, int numSplitBodies)\n"
+"{\n"
+" int i = GET_GLOBAL_IDX;\n"
+" \n"
+" if( i < numSplitBodies)\n"
+" {\n"
+" linearVelocities[i] = make_float4(0);\n"
+" angularVelocities[i] = make_float4(0);\n"
+" }\n"
+"}\n"
+"__kernel void AverageVelocitiesKernel(__global Body* gBodies,__global int* offsetSplitBodies,__global const unsigned int* bodyCount,\n"
+"__global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities, int numBodies)\n"
+"{\n"
+" int i = GET_GLOBAL_IDX;\n"
+" if (i<numBodies)\n"
+" {\n"
+" if (gBodies[i].m_invMass)\n"
+" {\n"
+" int bodyOffset = offsetSplitBodies[i];\n"
+" int count = bodyCount[i];\n"
+" float factor = 1.f/((float)count);\n"
+" float4 averageLinVel = make_float4(0.f);\n"
+" float4 averageAngVel = make_float4(0.f);\n"
+" \n"
+" for (int j=0;j<count;j++)\n"
+" {\n"
+" averageLinVel += deltaLinearVelocities[bodyOffset+j]*factor;\n"
+" averageAngVel += deltaAngularVelocities[bodyOffset+j]*factor;\n"
+" }\n"
+" \n"
+" for (int j=0;j<count;j++)\n"
+" {\n"
+" deltaLinearVelocities[bodyOffset+j] = averageLinVel;\n"
+" deltaAngularVelocities[bodyOffset+j] = averageAngVel;\n"
+" }\n"
+" \n"
+" }//bodies[i].m_invMass\n"
+" }//i<numBodies\n"
+"}\n"
+"void setLinearAndAngular( float4 n, float4 r0, float4 r1, float4* linear, float4* angular0, float4* angular1)\n"
+"{\n"
+" *linear = make_float4(n.xyz,0.f);\n"
+" *angular0 = cross3(r0, n);\n"
+" *angular1 = -cross3(r1, n);\n"
+"}\n"
+"float calcRelVel( float4 l0, float4 l1, float4 a0, float4 a1, float4 linVel0, float4 angVel0, float4 linVel1, float4 angVel1 )\n"
+"{\n"
+" return dot3F4(l0, linVel0) + dot3F4(a0, angVel0) + dot3F4(l1, linVel1) + dot3F4(a1, angVel1);\n"
+"}\n"
+"float calcJacCoeff(const float4 linear0, const float4 linear1, const float4 angular0, const float4 angular1,\n"
+" float invMass0, const Matrix3x3* invInertia0, float invMass1, const Matrix3x3* invInertia1, float countA, float countB)\n"
+"{\n"
+" // linear0,1 are normlized\n"
+" float jmj0 = invMass0;//dot3F4(linear0, linear0)*invMass0;\n"
+" float jmj1 = dot3F4(mtMul3(angular0,*invInertia0), angular0);\n"
+" float jmj2 = invMass1;//dot3F4(linear1, linear1)*invMass1;\n"
+" float jmj3 = dot3F4(mtMul3(angular1,*invInertia1), angular1);\n"
+" return -1.f/((jmj0+jmj1)*countA+(jmj2+jmj3)*countB);\n"
+"}\n"
+"void btPlaneSpace1 (float4 n, float4* p, float4* q);\n"
+" void btPlaneSpace1 (float4 n, float4* p, float4* q)\n"
+"{\n"
+" if (fabs(n.z) > 0.70710678f) {\n"
+" // choose p in y-z plane\n"
+" float a = n.y*n.y + n.z*n.z;\n"
+" float k = 1.f/sqrt(a);\n"
+" p[0].x = 0;\n"
+" p[0].y = -n.z*k;\n"
+" p[0].z = n.y*k;\n"
+" // set q = n x p\n"
+" q[0].x = a*k;\n"
+" q[0].y = -n.x*p[0].z;\n"
+" q[0].z = n.x*p[0].y;\n"
+" }\n"
+" else {\n"
+" // choose p in x-y plane\n"
+" float a = n.x*n.x + n.y*n.y;\n"
+" float k = 1.f/sqrt(a);\n"
+" p[0].x = -n.y*k;\n"
+" p[0].y = n.x*k;\n"
+" p[0].z = 0;\n"
+" // set q = n x p\n"
+" q[0].x = -n.z*p[0].y;\n"
+" q[0].y = n.z*p[0].x;\n"
+" q[0].z = a*k;\n"
+" }\n"
+"}\n"
+"void solveContact(__global Constraint4* cs,\n"
+" float4 posA, float4* linVelA, float4* angVelA, float invMassA, Matrix3x3 invInertiaA,\n"
+" float4 posB, float4* linVelB, float4* angVelB, float invMassB, Matrix3x3 invInertiaB,\n"
+" float4* dLinVelA, float4* dAngVelA, float4* dLinVelB, float4* dAngVelB)\n"
+"{\n"
+" float minRambdaDt = 0;\n"
+" float maxRambdaDt = FLT_MAX;\n"
+" for(int ic=0; ic<4; ic++)\n"
+" {\n"
+" if( cs->m_jacCoeffInv[ic] == 0.f ) continue;\n"
+" float4 angular0, angular1, linear;\n"
+" float4 r0 = cs->m_worldPos[ic] - posA;\n"
+" float4 r1 = cs->m_worldPos[ic] - posB;\n"
+" setLinearAndAngular( cs->m_linear, r0, r1, &linear, &angular0, &angular1 );\n"
+" \n"
+" float rambdaDt = calcRelVel( cs->m_linear, -cs->m_linear, angular0, angular1, \n"
+" *linVelA+*dLinVelA, *angVelA+*dAngVelA, *linVelB+*dLinVelB, *angVelB+*dAngVelB ) + cs->m_b[ic];\n"
+" rambdaDt *= cs->m_jacCoeffInv[ic];\n"
+" \n"
+" {\n"
+" float prevSum = cs->m_appliedRambdaDt[ic];\n"
+" float updated = prevSum;\n"
+" updated += rambdaDt;\n"
+" updated = max2( updated, minRambdaDt );\n"
+" updated = min2( updated, maxRambdaDt );\n"
+" rambdaDt = updated - prevSum;\n"
+" cs->m_appliedRambdaDt[ic] = updated;\n"
+" }\n"
+" \n"
+" float4 linImp0 = invMassA*linear*rambdaDt;\n"
+" float4 linImp1 = invMassB*(-linear)*rambdaDt;\n"
+" float4 angImp0 = mtMul1(invInertiaA, angular0)*rambdaDt;\n"
+" float4 angImp1 = mtMul1(invInertiaB, angular1)*rambdaDt;\n"
+" \n"
+" if (invMassA)\n"
+" {\n"
+" *dLinVelA += linImp0;\n"
+" *dAngVelA += angImp0;\n"
+" }\n"
+" if (invMassB)\n"
+" {\n"
+" *dLinVelB += linImp1;\n"
+" *dAngVelB += angImp1;\n"
+" }\n"
+" }\n"
+"}\n"
+"// solveContactConstraint( gBodies, gShapes, &gConstraints[i] ,contactConstraintOffsets,offsetSplitBodies, deltaLinearVelocities, deltaAngularVelocities);\n"
+"void solveContactConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs, \n"
+"__global int2* contactConstraintOffsets,__global unsigned int* offsetSplitBodies,\n"
+"__global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities)\n"
+"{\n"
+" //float frictionCoeff = ldsCs[0].m_linear.w;\n"
+" int aIdx = ldsCs[0].m_bodyA;\n"
+" int bIdx = ldsCs[0].m_bodyB;\n"
+" float4 posA = gBodies[aIdx].m_pos;\n"
+" float4 linVelA = gBodies[aIdx].m_linVel;\n"
+" float4 angVelA = gBodies[aIdx].m_angVel;\n"
+" float invMassA = gBodies[aIdx].m_invMass;\n"
+" Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia;\n"
+" float4 posB = gBodies[bIdx].m_pos;\n"
+" float4 linVelB = gBodies[bIdx].m_linVel;\n"
+" float4 angVelB = gBodies[bIdx].m_angVel;\n"
+" float invMassB = gBodies[bIdx].m_invMass;\n"
+" Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia;\n"
+" \n"
+" float4 dLinVelA = make_float4(0,0,0,0);\n"
+" float4 dAngVelA = make_float4(0,0,0,0);\n"
+" float4 dLinVelB = make_float4(0,0,0,0);\n"
+" float4 dAngVelB = make_float4(0,0,0,0);\n"
+" \n"
+" int bodyOffsetA = offsetSplitBodies[aIdx];\n"
+" int constraintOffsetA = contactConstraintOffsets[0].x;\n"
+" int splitIndexA = bodyOffsetA+constraintOffsetA;\n"
+" \n"
+" if (invMassA)\n"
+" {\n"
+" dLinVelA = deltaLinearVelocities[splitIndexA];\n"
+" dAngVelA = deltaAngularVelocities[splitIndexA];\n"
+" }\n"
+" int bodyOffsetB = offsetSplitBodies[bIdx];\n"
+" int constraintOffsetB = contactConstraintOffsets[0].y;\n"
+" int splitIndexB= bodyOffsetB+constraintOffsetB;\n"
+" if (invMassB)\n"
+" {\n"
+" dLinVelB = deltaLinearVelocities[splitIndexB];\n"
+" dAngVelB = deltaAngularVelocities[splitIndexB];\n"
+" }\n"
+" solveContact( ldsCs, posA, &linVelA, &angVelA, invMassA, invInertiaA,\n"
+" posB, &linVelB, &angVelB, invMassB, invInertiaB ,&dLinVelA, &dAngVelA, &dLinVelB, &dAngVelB);\n"
+" if (invMassA)\n"
+" {\n"
+" deltaLinearVelocities[splitIndexA] = dLinVelA;\n"
+" deltaAngularVelocities[splitIndexA] = dAngVelA;\n"
+" } \n"
+" if (invMassB)\n"
+" {\n"
+" deltaLinearVelocities[splitIndexB] = dLinVelB;\n"
+" deltaAngularVelocities[splitIndexB] = dAngVelB;\n"
+" }\n"
+"}\n"
+"__kernel void SolveContactJacobiKernel(__global Constraint4* gConstraints, __global Body* gBodies, __global Shape* gShapes ,\n"
+"__global int2* contactConstraintOffsets,__global unsigned int* offsetSplitBodies,__global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities,\n"
+"float deltaTime, float positionDrift, float positionConstraintCoeff, int fixedBodyIndex, int numManifolds\n"
+")\n"
+"{\n"
+" int i = GET_GLOBAL_IDX;\n"
+" if (i<numManifolds)\n"
+" {\n"
+" solveContactConstraint( gBodies, gShapes, &gConstraints[i] ,&contactConstraintOffsets[i],offsetSplitBodies, deltaLinearVelocities, deltaAngularVelocities);\n"
+" }\n"
+"}\n"
+"void solveFrictionConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs,\n"
+" __global int2* contactConstraintOffsets,__global unsigned int* offsetSplitBodies,\n"
+" __global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities)\n"
+"{\n"
+" float frictionCoeff = 0.7f;//ldsCs[0].m_linear.w;\n"
+" int aIdx = ldsCs[0].m_bodyA;\n"
+" int bIdx = ldsCs[0].m_bodyB;\n"
+" float4 posA = gBodies[aIdx].m_pos;\n"
+" float4 linVelA = gBodies[aIdx].m_linVel;\n"
+" float4 angVelA = gBodies[aIdx].m_angVel;\n"
+" float invMassA = gBodies[aIdx].m_invMass;\n"
+" Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia;\n"
+" float4 posB = gBodies[bIdx].m_pos;\n"
+" float4 linVelB = gBodies[bIdx].m_linVel;\n"
+" float4 angVelB = gBodies[bIdx].m_angVel;\n"
+" float invMassB = gBodies[bIdx].m_invMass;\n"
+" Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia;\n"
+" \n"
+" float4 dLinVelA = make_float4(0,0,0,0);\n"
+" float4 dAngVelA = make_float4(0,0,0,0);\n"
+" float4 dLinVelB = make_float4(0,0,0,0);\n"
+" float4 dAngVelB = make_float4(0,0,0,0);\n"
+" \n"
+" int bodyOffsetA = offsetSplitBodies[aIdx];\n"
+" int constraintOffsetA = contactConstraintOffsets[0].x;\n"
+" int splitIndexA = bodyOffsetA+constraintOffsetA;\n"
+" \n"
+" if (invMassA)\n"
+" {\n"
+" dLinVelA = deltaLinearVelocities[splitIndexA];\n"
+" dAngVelA = deltaAngularVelocities[splitIndexA];\n"
+" }\n"
+" int bodyOffsetB = offsetSplitBodies[bIdx];\n"
+" int constraintOffsetB = contactConstraintOffsets[0].y;\n"
+" int splitIndexB= bodyOffsetB+constraintOffsetB;\n"
+" if (invMassB)\n"
+" {\n"
+" dLinVelB = deltaLinearVelocities[splitIndexB];\n"
+" dAngVelB = deltaAngularVelocities[splitIndexB];\n"
+" }\n"
+" {\n"
+" float maxRambdaDt[4] = {FLT_MAX,FLT_MAX,FLT_MAX,FLT_MAX};\n"
+" float minRambdaDt[4] = {0.f,0.f,0.f,0.f};\n"
+" float sum = 0;\n"
+" for(int j=0; j<4; j++)\n"
+" {\n"
+" sum +=ldsCs[0].m_appliedRambdaDt[j];\n"
+" }\n"
+" frictionCoeff = 0.7f;\n"
+" for(int j=0; j<4; j++)\n"
+" {\n"
+" maxRambdaDt[j] = frictionCoeff*sum;\n"
+" minRambdaDt[j] = -maxRambdaDt[j];\n"
+" }\n"
+" \n"
+"// solveFriction( ldsCs, posA, &linVelA, &angVelA, invMassA, invInertiaA,\n"
+"// posB, &linVelB, &angVelB, invMassB, invInertiaB, maxRambdaDt, minRambdaDt );\n"
+" \n"
+" \n"
+" {\n"
+" \n"
+" __global Constraint4* cs = ldsCs;\n"
+" \n"
+" if( cs->m_fJacCoeffInv[0] == 0 && cs->m_fJacCoeffInv[0] == 0 ) return;\n"
+" const float4 center = cs->m_center;\n"
+" \n"
+" float4 n = -cs->m_linear;\n"
+" \n"
+" float4 tangent[2];\n"
+" btPlaneSpace1(n,&tangent[0],&tangent[1]);\n"
+" float4 angular0, angular1, linear;\n"
+" float4 r0 = center - posA;\n"
+" float4 r1 = center - posB;\n"
+" for(int i=0; i<2; i++)\n"
+" {\n"
+" setLinearAndAngular( tangent[i], r0, r1, &linear, &angular0, &angular1 );\n"
+" float rambdaDt = calcRelVel(linear, -linear, angular0, angular1,\n"
+" linVelA+dLinVelA, angVelA+dAngVelA, linVelB+dLinVelB, angVelB+dAngVelB );\n"
+" rambdaDt *= cs->m_fJacCoeffInv[i];\n"
+" \n"
+" {\n"
+" float prevSum = cs->m_fAppliedRambdaDt[i];\n"
+" float updated = prevSum;\n"
+" updated += rambdaDt;\n"
+" updated = max2( updated, minRambdaDt[i] );\n"
+" updated = min2( updated, maxRambdaDt[i] );\n"
+" rambdaDt = updated - prevSum;\n"
+" cs->m_fAppliedRambdaDt[i] = updated;\n"
+" }\n"
+" \n"
+" float4 linImp0 = invMassA*linear*rambdaDt;\n"
+" float4 linImp1 = invMassB*(-linear)*rambdaDt;\n"
+" float4 angImp0 = mtMul1(invInertiaA, angular0)*rambdaDt;\n"
+" float4 angImp1 = mtMul1(invInertiaB, angular1)*rambdaDt;\n"
+" \n"
+" dLinVelA += linImp0;\n"
+" dAngVelA += angImp0;\n"
+" dLinVelB += linImp1;\n"
+" dAngVelB += angImp1;\n"
+" }\n"
+" { // angular damping for point constraint\n"
+" float4 ab = normalize3( posB - posA );\n"
+" float4 ac = normalize3( center - posA );\n"
+" if( dot3F4( ab, ac ) > 0.95f || (invMassA == 0.f || invMassB == 0.f))\n"
+" {\n"
+" float angNA = dot3F4( n, angVelA );\n"
+" float angNB = dot3F4( n, angVelB );\n"
+" \n"
+" dAngVelA -= (angNA*0.1f)*n;\n"
+" dAngVelB -= (angNB*0.1f)*n;\n"
+" }\n"
+" }\n"
+" }\n"
+" \n"
+" \n"
+" }\n"
+" if (invMassA)\n"
+" {\n"
+" deltaLinearVelocities[splitIndexA] = dLinVelA;\n"
+" deltaAngularVelocities[splitIndexA] = dAngVelA;\n"
+" } \n"
+" if (invMassB)\n"
+" {\n"
+" deltaLinearVelocities[splitIndexB] = dLinVelB;\n"
+" deltaAngularVelocities[splitIndexB] = dAngVelB;\n"
+" }\n"
+" \n"
+"}\n"
+"__kernel void SolveFrictionJacobiKernel(__global Constraint4* gConstraints, __global Body* gBodies, __global Shape* gShapes ,\n"
+" __global int2* contactConstraintOffsets,__global unsigned int* offsetSplitBodies,\n"
+" __global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities,\n"
+" float deltaTime, float positionDrift, float positionConstraintCoeff, int fixedBodyIndex, int numManifolds\n"
+")\n"
+"{\n"
+" int i = GET_GLOBAL_IDX;\n"
+" if (i<numManifolds)\n"
+" {\n"
+" solveFrictionConstraint( gBodies, gShapes, &gConstraints[i] ,&contactConstraintOffsets[i],offsetSplitBodies, deltaLinearVelocities, deltaAngularVelocities);\n"
+" }\n"
+"}\n"
+"__kernel void UpdateBodyVelocitiesKernel(__global Body* gBodies,__global int* offsetSplitBodies,__global const unsigned int* bodyCount,\n"
+" __global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities, int numBodies)\n"
+"{\n"
+" int i = GET_GLOBAL_IDX;\n"
+" if (i<numBodies)\n"
+" {\n"
+" if (gBodies[i].m_invMass)\n"
+" {\n"
+" int bodyOffset = offsetSplitBodies[i];\n"
+" int count = bodyCount[i];\n"
+" if (count)\n"
+" {\n"
+" gBodies[i].m_linVel += deltaLinearVelocities[bodyOffset];\n"
+" gBodies[i].m_angVel += deltaAngularVelocities[bodyOffset];\n"
+" }\n"
+" }\n"
+" }\n"
+"}\n"
+"void setConstraint4( const float4 posA, const float4 linVelA, const float4 angVelA, float invMassA, const Matrix3x3 invInertiaA,\n"
+" const float4 posB, const float4 linVelB, const float4 angVelB, float invMassB, const Matrix3x3 invInertiaB, \n"
+" __global struct b3Contact4Data* src, float dt, float positionDrift, float positionConstraintCoeff,float countA, float countB,\n"
+" Constraint4* dstC )\n"
+"{\n"
+" dstC->m_bodyA = abs(src->m_bodyAPtrAndSignBit);\n"
+" dstC->m_bodyB = abs(src->m_bodyBPtrAndSignBit);\n"
+" float dtInv = 1.f/dt;\n"
+" for(int ic=0; ic<4; ic++)\n"
+" {\n"
+" dstC->m_appliedRambdaDt[ic] = 0.f;\n"
+" }\n"
+" dstC->m_fJacCoeffInv[0] = dstC->m_fJacCoeffInv[1] = 0.f;\n"
+" dstC->m_linear = src->m_worldNormalOnB;\n"
+" dstC->m_linear.w = 0.7f ;//src->getFrictionCoeff() );\n"
+" for(int ic=0; ic<4; ic++)\n"
+" {\n"
+" float4 r0 = src->m_worldPosB[ic] - posA;\n"
+" float4 r1 = src->m_worldPosB[ic] - posB;\n"
+" if( ic >= src->m_worldNormalOnB.w )//npoints\n"
+" {\n"
+" dstC->m_jacCoeffInv[ic] = 0.f;\n"
+" continue;\n"
+" }\n"
+" float relVelN;\n"
+" {\n"
+" float4 linear, angular0, angular1;\n"
+" setLinearAndAngular(src->m_worldNormalOnB, r0, r1, &linear, &angular0, &angular1);\n"
+" dstC->m_jacCoeffInv[ic] = calcJacCoeff(linear, -linear, angular0, angular1,\n"
+" invMassA, &invInertiaA, invMassB, &invInertiaB , countA, countB);\n"
+" relVelN = calcRelVel(linear, -linear, angular0, angular1,\n"
+" linVelA, angVelA, linVelB, angVelB);\n"
+" float e = 0.f;//src->getRestituitionCoeff();\n"
+" if( relVelN*relVelN < 0.004f ) e = 0.f;\n"
+" dstC->m_b[ic] = e*relVelN;\n"
+" //float penetration = src->m_worldPosB[ic].w;\n"
+" dstC->m_b[ic] += (src->m_worldPosB[ic].w + positionDrift)*positionConstraintCoeff*dtInv;\n"
+" dstC->m_appliedRambdaDt[ic] = 0.f;\n"
+" }\n"
+" }\n"
+" if( src->m_worldNormalOnB.w > 0 )//npoints\n"
+" { // prepare friction\n"
+" float4 center = make_float4(0.f);\n"
+" for(int i=0; i<src->m_worldNormalOnB.w; i++) \n"
+" center += src->m_worldPosB[i];\n"
+" center /= (float)src->m_worldNormalOnB.w;\n"
+" float4 tangent[2];\n"
+" btPlaneSpace1(-src->m_worldNormalOnB,&tangent[0],&tangent[1]);\n"
+" \n"
+" float4 r[2];\n"
+" r[0] = center - posA;\n"
+" r[1] = center - posB;\n"
+" for(int i=0; i<2; i++)\n"
+" {\n"
+" float4 linear, angular0, angular1;\n"
+" setLinearAndAngular(tangent[i], r[0], r[1], &linear, &angular0, &angular1);\n"
+" dstC->m_fJacCoeffInv[i] = calcJacCoeff(linear, -linear, angular0, angular1,\n"
+" invMassA, &invInertiaA, invMassB, &invInertiaB ,countA, countB);\n"
+" dstC->m_fAppliedRambdaDt[i] = 0.f;\n"
+" }\n"
+" dstC->m_center = center;\n"
+" }\n"
+" for(int i=0; i<4; i++)\n"
+" {\n"
+" if( i<src->m_worldNormalOnB.w )\n"
+" {\n"
+" dstC->m_worldPos[i] = src->m_worldPosB[i];\n"
+" }\n"
+" else\n"
+" {\n"
+" dstC->m_worldPos[i] = make_float4(0.f);\n"
+" }\n"
+" }\n"
+"}\n"
+"__kernel\n"
+"__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+"void ContactToConstraintSplitKernel(__global const struct b3Contact4Data* gContact, __global const Body* gBodies, __global const Shape* gShapes, __global Constraint4* gConstraintOut, \n"
+"__global const unsigned int* bodyCount,\n"
+"int nContacts,\n"
+"float dt,\n"
+"float positionDrift,\n"
+"float positionConstraintCoeff\n"
+")\n"
+"{\n"
+" int gIdx = GET_GLOBAL_IDX;\n"
+" \n"
+" if( gIdx < nContacts )\n"
+" {\n"
+" int aIdx = abs(gContact[gIdx].m_bodyAPtrAndSignBit);\n"
+" int bIdx = abs(gContact[gIdx].m_bodyBPtrAndSignBit);\n"
+" float4 posA = gBodies[aIdx].m_pos;\n"
+" float4 linVelA = gBodies[aIdx].m_linVel;\n"
+" float4 angVelA = gBodies[aIdx].m_angVel;\n"
+" float invMassA = gBodies[aIdx].m_invMass;\n"
+" Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia;\n"
+" float4 posB = gBodies[bIdx].m_pos;\n"
+" float4 linVelB = gBodies[bIdx].m_linVel;\n"
+" float4 angVelB = gBodies[bIdx].m_angVel;\n"
+" float invMassB = gBodies[bIdx].m_invMass;\n"
+" Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia;\n"
+" Constraint4 cs;\n"
+" float countA = invMassA != 0.f ? (float)bodyCount[aIdx] : 1;\n"
+" float countB = invMassB != 0.f ? (float)bodyCount[bIdx] : 1;\n"
+" setConstraint4( posA, linVelA, angVelA, invMassA, invInertiaA, posB, linVelB, angVelB, invMassB, invInertiaB,\n"
+" &gContact[gIdx], dt, positionDrift, positionConstraintCoeff,countA,countB,\n"
+" &cs );\n"
+" \n"
+" cs.m_batchIdx = gContact[gIdx].m_batchIdx;\n"
+" gConstraintOut[gIdx] = cs;\n"
+" }\n"
+"}\n"
+;
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/updateAabbsKernel.cl b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/updateAabbsKernel.cl
new file mode 100644
index 0000000000..ba8ba735d0
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/updateAabbsKernel.cl
@@ -0,0 +1,22 @@
+
+
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3UpdateAabbs.h"
+
+
+__kernel void initializeGpuAabbsFull( const int numNodes, __global b3RigidBodyData_t* gBodies,__global b3Collidable_t* collidables, __global b3Aabb_t* plocalShapeAABB, __global b3Aabb_t* pAABB)
+{
+ int nodeID = get_global_id(0);
+ if( nodeID < numNodes )
+ {
+ b3ComputeWorldAabb(nodeID, gBodies, collidables, plocalShapeAABB,pAABB);
+ }
+}
+
+__kernel void clearOverlappingPairsKernel( __global int4* pairs, int numPairs)
+{
+ int pairId = get_global_id(0);
+ if( pairId< numPairs )
+ {
+ pairs[pairId].z = 0xffffffff;
+ }
+} \ No newline at end of file
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/updateAabbsKernel.h b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/updateAabbsKernel.h
new file mode 100644
index 0000000000..d70e74017a
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/RigidBody/kernels/updateAabbsKernel.h
@@ -0,0 +1,483 @@
+//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
+static const char* updateAabbsKernelCL= \
+"#ifndef B3_UPDATE_AABBS_H\n"
+"#define B3_UPDATE_AABBS_H\n"
+"#ifndef B3_AABB_H\n"
+"#define B3_AABB_H\n"
+"#ifndef B3_FLOAT4_H\n"
+"#define B3_FLOAT4_H\n"
+"#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+"#define B3_PLATFORM_DEFINITIONS_H\n"
+"struct MyTest\n"
+"{\n"
+" int bla;\n"
+"};\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
+"#define B3_LARGE_FLOAT 1e18f\n"
+"#define B3_INFINITY 1e18f\n"
+"#define b3Assert(a)\n"
+"#define b3ConstArray(a) __global const a*\n"
+"#define b3AtomicInc atomic_inc\n"
+"#define b3AtomicAdd atomic_add\n"
+"#define b3Fabs fabs\n"
+"#define b3Sqrt native_sqrt\n"
+"#define b3Sin native_sin\n"
+"#define b3Cos native_cos\n"
+"#define B3_STATIC\n"
+"#endif\n"
+"#endif\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+" typedef float4 b3Float4;\n"
+" #define b3Float4ConstArg const b3Float4\n"
+" #define b3MakeFloat4 (float4)\n"
+" float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+" {\n"
+" float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+" float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+" return dot(a1, b1);\n"
+" }\n"
+" b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+" {\n"
+" float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+" float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+" return cross(a1, b1);\n"
+" }\n"
+" #define b3MinFloat4 min\n"
+" #define b3MaxFloat4 max\n"
+" #define b3Normalized(a) normalize(a)\n"
+"#endif \n"
+" \n"
+"inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
+"{\n"
+" if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6) \n"
+" return false;\n"
+" return true;\n"
+"}\n"
+"inline int b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
+"{\n"
+" float maxDot = -B3_INFINITY;\n"
+" int i = 0;\n"
+" int ptIndex = -1;\n"
+" for( i = 0; i < vecLen; i++ )\n"
+" {\n"
+" float dot = b3Dot3F4(vecArray[i],vec);\n"
+" \n"
+" if( dot > maxDot )\n"
+" {\n"
+" maxDot = dot;\n"
+" ptIndex = i;\n"
+" }\n"
+" }\n"
+" b3Assert(ptIndex>=0);\n"
+" if (ptIndex<0)\n"
+" {\n"
+" ptIndex = 0;\n"
+" }\n"
+" *dotOut = maxDot;\n"
+" return ptIndex;\n"
+"}\n"
+"#endif //B3_FLOAT4_H\n"
+"#ifndef B3_MAT3x3_H\n"
+"#define B3_MAT3x3_H\n"
+"#ifndef B3_QUAT_H\n"
+"#define B3_QUAT_H\n"
+"#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"#endif\n"
+"#endif\n"
+"#ifndef B3_FLOAT4_H\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"#endif \n"
+"#endif //B3_FLOAT4_H\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+" typedef float4 b3Quat;\n"
+" #define b3QuatConstArg const b3Quat\n"
+" \n"
+" \n"
+"inline float4 b3FastNormalize4(float4 v)\n"
+"{\n"
+" v = (float4)(v.xyz,0.f);\n"
+" return fast_normalize(v);\n"
+"}\n"
+" \n"
+"inline b3Quat b3QuatMul(b3Quat a, b3Quat b);\n"
+"inline b3Quat b3QuatNormalized(b3QuatConstArg in);\n"
+"inline b3Quat b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec);\n"
+"inline b3Quat b3QuatInvert(b3QuatConstArg q);\n"
+"inline b3Quat b3QuatInverse(b3QuatConstArg q);\n"
+"inline b3Quat b3QuatMul(b3QuatConstArg a, b3QuatConstArg b)\n"
+"{\n"
+" b3Quat ans;\n"
+" ans = b3Cross3( a, b );\n"
+" ans += a.w*b+b.w*a;\n"
+"// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
+" ans.w = a.w*b.w - b3Dot3F4(a, b);\n"
+" return ans;\n"
+"}\n"
+"inline b3Quat b3QuatNormalized(b3QuatConstArg in)\n"
+"{\n"
+" b3Quat q;\n"
+" q=in;\n"
+" //return b3FastNormalize4(in);\n"
+" float len = native_sqrt(dot(q, q));\n"
+" if(len > 0.f)\n"
+" {\n"
+" q *= 1.f / len;\n"
+" }\n"
+" else\n"
+" {\n"
+" q.x = q.y = q.z = 0.f;\n"
+" q.w = 1.f;\n"
+" }\n"
+" return q;\n"
+"}\n"
+"inline float4 b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
+"{\n"
+" b3Quat qInv = b3QuatInvert( q );\n"
+" float4 vcpy = vec;\n"
+" vcpy.w = 0.f;\n"
+" float4 out = b3QuatMul(b3QuatMul(q,vcpy),qInv);\n"
+" return out;\n"
+"}\n"
+"inline b3Quat b3QuatInverse(b3QuatConstArg q)\n"
+"{\n"
+" return (b3Quat)(-q.xyz, q.w);\n"
+"}\n"
+"inline b3Quat b3QuatInvert(b3QuatConstArg q)\n"
+"{\n"
+" return (b3Quat)(-q.xyz, q.w);\n"
+"}\n"
+"inline float4 b3QuatInvRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
+"{\n"
+" return b3QuatRotate( b3QuatInvert( q ), vec );\n"
+"}\n"
+"inline b3Float4 b3TransformPoint(b3Float4ConstArg point, b3Float4ConstArg translation, b3QuatConstArg orientation)\n"
+"{\n"
+" return b3QuatRotate( orientation, point ) + (translation);\n"
+"}\n"
+" \n"
+"#endif \n"
+"#endif //B3_QUAT_H\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"typedef struct\n"
+"{\n"
+" b3Float4 m_row[3];\n"
+"}b3Mat3x3;\n"
+"#define b3Mat3x3ConstArg const b3Mat3x3\n"
+"#define b3GetRow(m,row) (m.m_row[row])\n"
+"inline b3Mat3x3 b3QuatGetRotationMatrix(b3Quat quat)\n"
+"{\n"
+" b3Float4 quat2 = (b3Float4)(quat.x*quat.x, quat.y*quat.y, quat.z*quat.z, 0.f);\n"
+" b3Mat3x3 out;\n"
+" out.m_row[0].x=1-2*quat2.y-2*quat2.z;\n"
+" out.m_row[0].y=2*quat.x*quat.y-2*quat.w*quat.z;\n"
+" out.m_row[0].z=2*quat.x*quat.z+2*quat.w*quat.y;\n"
+" out.m_row[0].w = 0.f;\n"
+" out.m_row[1].x=2*quat.x*quat.y+2*quat.w*quat.z;\n"
+" out.m_row[1].y=1-2*quat2.x-2*quat2.z;\n"
+" out.m_row[1].z=2*quat.y*quat.z-2*quat.w*quat.x;\n"
+" out.m_row[1].w = 0.f;\n"
+" out.m_row[2].x=2*quat.x*quat.z-2*quat.w*quat.y;\n"
+" out.m_row[2].y=2*quat.y*quat.z+2*quat.w*quat.x;\n"
+" out.m_row[2].z=1-2*quat2.x-2*quat2.y;\n"
+" out.m_row[2].w = 0.f;\n"
+" return out;\n"
+"}\n"
+"inline b3Mat3x3 b3AbsoluteMat3x3(b3Mat3x3ConstArg matIn)\n"
+"{\n"
+" b3Mat3x3 out;\n"
+" out.m_row[0] = fabs(matIn.m_row[0]);\n"
+" out.m_row[1] = fabs(matIn.m_row[1]);\n"
+" out.m_row[2] = fabs(matIn.m_row[2]);\n"
+" return out;\n"
+"}\n"
+"__inline\n"
+"b3Mat3x3 mtZero();\n"
+"__inline\n"
+"b3Mat3x3 mtIdentity();\n"
+"__inline\n"
+"b3Mat3x3 mtTranspose(b3Mat3x3 m);\n"
+"__inline\n"
+"b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b);\n"
+"__inline\n"
+"b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b);\n"
+"__inline\n"
+"b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b);\n"
+"__inline\n"
+"b3Mat3x3 mtZero()\n"
+"{\n"
+" b3Mat3x3 m;\n"
+" m.m_row[0] = (b3Float4)(0.f);\n"
+" m.m_row[1] = (b3Float4)(0.f);\n"
+" m.m_row[2] = (b3Float4)(0.f);\n"
+" return m;\n"
+"}\n"
+"__inline\n"
+"b3Mat3x3 mtIdentity()\n"
+"{\n"
+" b3Mat3x3 m;\n"
+" m.m_row[0] = (b3Float4)(1,0,0,0);\n"
+" m.m_row[1] = (b3Float4)(0,1,0,0);\n"
+" m.m_row[2] = (b3Float4)(0,0,1,0);\n"
+" return m;\n"
+"}\n"
+"__inline\n"
+"b3Mat3x3 mtTranspose(b3Mat3x3 m)\n"
+"{\n"
+" b3Mat3x3 out;\n"
+" out.m_row[0] = (b3Float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);\n"
+" out.m_row[1] = (b3Float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);\n"
+" out.m_row[2] = (b3Float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);\n"
+" return out;\n"
+"}\n"
+"__inline\n"
+"b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b)\n"
+"{\n"
+" b3Mat3x3 transB;\n"
+" transB = mtTranspose( b );\n"
+" b3Mat3x3 ans;\n"
+" // why this doesn't run when 0ing in the for{}\n"
+" a.m_row[0].w = 0.f;\n"
+" a.m_row[1].w = 0.f;\n"
+" a.m_row[2].w = 0.f;\n"
+" for(int i=0; i<3; i++)\n"
+" {\n"
+"// a.m_row[i].w = 0.f;\n"
+" ans.m_row[i].x = b3Dot3F4(a.m_row[i],transB.m_row[0]);\n"
+" ans.m_row[i].y = b3Dot3F4(a.m_row[i],transB.m_row[1]);\n"
+" ans.m_row[i].z = b3Dot3F4(a.m_row[i],transB.m_row[2]);\n"
+" ans.m_row[i].w = 0.f;\n"
+" }\n"
+" return ans;\n"
+"}\n"
+"__inline\n"
+"b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b)\n"
+"{\n"
+" b3Float4 ans;\n"
+" ans.x = b3Dot3F4( a.m_row[0], b );\n"
+" ans.y = b3Dot3F4( a.m_row[1], b );\n"
+" ans.z = b3Dot3F4( a.m_row[2], b );\n"
+" ans.w = 0.f;\n"
+" return ans;\n"
+"}\n"
+"__inline\n"
+"b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b)\n"
+"{\n"
+" b3Float4 colx = b3MakeFloat4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
+" b3Float4 coly = b3MakeFloat4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
+" b3Float4 colz = b3MakeFloat4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
+" b3Float4 ans;\n"
+" ans.x = b3Dot3F4( a, colx );\n"
+" ans.y = b3Dot3F4( a, coly );\n"
+" ans.z = b3Dot3F4( a, colz );\n"
+" return ans;\n"
+"}\n"
+"#endif\n"
+"#endif //B3_MAT3x3_H\n"
+"typedef struct b3Aabb b3Aabb_t;\n"
+"struct b3Aabb\n"
+"{\n"
+" union\n"
+" {\n"
+" float m_min[4];\n"
+" b3Float4 m_minVec;\n"
+" int m_minIndices[4];\n"
+" };\n"
+" union\n"
+" {\n"
+" float m_max[4];\n"
+" b3Float4 m_maxVec;\n"
+" int m_signedMaxIndices[4];\n"
+" };\n"
+"};\n"
+"inline void b3TransformAabb2(b3Float4ConstArg localAabbMin,b3Float4ConstArg localAabbMax, float margin,\n"
+" b3Float4ConstArg pos,\n"
+" b3QuatConstArg orn,\n"
+" b3Float4* aabbMinOut,b3Float4* aabbMaxOut)\n"
+"{\n"
+" b3Float4 localHalfExtents = 0.5f*(localAabbMax-localAabbMin);\n"
+" localHalfExtents+=b3MakeFloat4(margin,margin,margin,0.f);\n"
+" b3Float4 localCenter = 0.5f*(localAabbMax+localAabbMin);\n"
+" b3Mat3x3 m;\n"
+" m = b3QuatGetRotationMatrix(orn);\n"
+" b3Mat3x3 abs_b = b3AbsoluteMat3x3(m);\n"
+" b3Float4 center = b3TransformPoint(localCenter,pos,orn);\n"
+" \n"
+" b3Float4 extent = b3MakeFloat4(b3Dot3F4(localHalfExtents,b3GetRow(abs_b,0)),\n"
+" b3Dot3F4(localHalfExtents,b3GetRow(abs_b,1)),\n"
+" b3Dot3F4(localHalfExtents,b3GetRow(abs_b,2)),\n"
+" 0.f);\n"
+" *aabbMinOut = center-extent;\n"
+" *aabbMaxOut = center+extent;\n"
+"}\n"
+"/// conservative test for overlap between two aabbs\n"
+"inline bool b3TestAabbAgainstAabb(b3Float4ConstArg aabbMin1,b3Float4ConstArg aabbMax1,\n"
+" b3Float4ConstArg aabbMin2, b3Float4ConstArg aabbMax2)\n"
+"{\n"
+" bool overlap = true;\n"
+" overlap = (aabbMin1.x > aabbMax2.x || aabbMax1.x < aabbMin2.x) ? false : overlap;\n"
+" overlap = (aabbMin1.z > aabbMax2.z || aabbMax1.z < aabbMin2.z) ? false : overlap;\n"
+" overlap = (aabbMin1.y > aabbMax2.y || aabbMax1.y < aabbMin2.y) ? false : overlap;\n"
+" return overlap;\n"
+"}\n"
+"#endif //B3_AABB_H\n"
+"#ifndef B3_COLLIDABLE_H\n"
+"#define B3_COLLIDABLE_H\n"
+"#ifndef B3_FLOAT4_H\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"#endif \n"
+"#endif //B3_FLOAT4_H\n"
+"#ifndef B3_QUAT_H\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"#endif \n"
+"#endif //B3_QUAT_H\n"
+"enum b3ShapeTypes\n"
+"{\n"
+" SHAPE_HEIGHT_FIELD=1,\n"
+" SHAPE_CONVEX_HULL=3,\n"
+" SHAPE_PLANE=4,\n"
+" SHAPE_CONCAVE_TRIMESH=5,\n"
+" SHAPE_COMPOUND_OF_CONVEX_HULLS=6,\n"
+" SHAPE_SPHERE=7,\n"
+" MAX_NUM_SHAPE_TYPES,\n"
+"};\n"
+"typedef struct b3Collidable b3Collidable_t;\n"
+"struct b3Collidable\n"
+"{\n"
+" union {\n"
+" int m_numChildShapes;\n"
+" int m_bvhIndex;\n"
+" };\n"
+" union\n"
+" {\n"
+" float m_radius;\n"
+" int m_compoundBvhIndex;\n"
+" };\n"
+" int m_shapeType;\n"
+" union\n"
+" {\n"
+" int m_shapeIndex;\n"
+" float m_height;\n"
+" };\n"
+"};\n"
+"typedef struct b3GpuChildShape b3GpuChildShape_t;\n"
+"struct b3GpuChildShape\n"
+"{\n"
+" b3Float4 m_childPosition;\n"
+" b3Quat m_childOrientation;\n"
+" union\n"
+" {\n"
+" int m_shapeIndex;//used for SHAPE_COMPOUND_OF_CONVEX_HULLS\n"
+" int m_capsuleAxis;\n"
+" };\n"
+" union \n"
+" {\n"
+" float m_radius;//used for childshape of SHAPE_COMPOUND_OF_SPHERES or SHAPE_COMPOUND_OF_CAPSULES\n"
+" int m_numChildShapes;//used for compound shape\n"
+" };\n"
+" union \n"
+" {\n"
+" float m_height;//used for childshape of SHAPE_COMPOUND_OF_CAPSULES\n"
+" int m_collidableShapeIndex;\n"
+" };\n"
+" int m_shapeType;\n"
+"};\n"
+"struct b3CompoundOverlappingPair\n"
+"{\n"
+" int m_bodyIndexA;\n"
+" int m_bodyIndexB;\n"
+"// int m_pairType;\n"
+" int m_childShapeIndexA;\n"
+" int m_childShapeIndexB;\n"
+"};\n"
+"#endif //B3_COLLIDABLE_H\n"
+"#ifndef B3_RIGIDBODY_DATA_H\n"
+"#define B3_RIGIDBODY_DATA_H\n"
+"#ifndef B3_FLOAT4_H\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"#endif \n"
+"#endif //B3_FLOAT4_H\n"
+"#ifndef B3_QUAT_H\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"#endif \n"
+"#endif //B3_QUAT_H\n"
+"#ifndef B3_MAT3x3_H\n"
+"#ifdef __cplusplus\n"
+"#else\n"
+"#endif\n"
+"#endif //B3_MAT3x3_H\n"
+"typedef struct b3RigidBodyData b3RigidBodyData_t;\n"
+"struct b3RigidBodyData\n"
+"{\n"
+" b3Float4 m_pos;\n"
+" b3Quat m_quat;\n"
+" b3Float4 m_linVel;\n"
+" b3Float4 m_angVel;\n"
+" int m_collidableIdx;\n"
+" float m_invMass;\n"
+" float m_restituitionCoeff;\n"
+" float m_frictionCoeff;\n"
+"};\n"
+"typedef struct b3InertiaData b3InertiaData_t;\n"
+"struct b3InertiaData\n"
+"{\n"
+" b3Mat3x3 m_invInertiaWorld;\n"
+" b3Mat3x3 m_initInvInertia;\n"
+"};\n"
+"#endif //B3_RIGIDBODY_DATA_H\n"
+" \n"
+"void b3ComputeWorldAabb( int bodyId, __global const b3RigidBodyData_t* bodies, __global const b3Collidable_t* collidables, __global const b3Aabb_t* localShapeAABB, __global b3Aabb_t* worldAabbs)\n"
+"{\n"
+" __global const b3RigidBodyData_t* body = &bodies[bodyId];\n"
+" b3Float4 position = body->m_pos;\n"
+" b3Quat orientation = body->m_quat;\n"
+" \n"
+" int collidableIndex = body->m_collidableIdx;\n"
+" int shapeIndex = collidables[collidableIndex].m_shapeIndex;\n"
+" \n"
+" if (shapeIndex>=0)\n"
+" {\n"
+" \n"
+" b3Aabb_t localAabb = localShapeAABB[collidableIndex];\n"
+" b3Aabb_t worldAabb;\n"
+" \n"
+" b3Float4 aabbAMinOut,aabbAMaxOut; \n"
+" float margin = 0.f;\n"
+" b3TransformAabb2(localAabb.m_minVec,localAabb.m_maxVec,margin,position,orientation,&aabbAMinOut,&aabbAMaxOut);\n"
+" \n"
+" worldAabb.m_minVec =aabbAMinOut;\n"
+" worldAabb.m_minIndices[3] = bodyId;\n"
+" worldAabb.m_maxVec = aabbAMaxOut;\n"
+" worldAabb.m_signedMaxIndices[3] = body[bodyId].m_invMass==0.f? 0 : 1;\n"
+" worldAabbs[bodyId] = worldAabb;\n"
+" }\n"
+"}\n"
+"#endif //B3_UPDATE_AABBS_H\n"
+"__kernel void initializeGpuAabbsFull( const int numNodes, __global b3RigidBodyData_t* gBodies,__global b3Collidable_t* collidables, __global b3Aabb_t* plocalShapeAABB, __global b3Aabb_t* pAABB)\n"
+"{\n"
+" int nodeID = get_global_id(0);\n"
+" if( nodeID < numNodes )\n"
+" {\n"
+" b3ComputeWorldAabb(nodeID, gBodies, collidables, plocalShapeAABB,pAABB);\n"
+" }\n"
+"}\n"
+"__kernel void clearOverlappingPairsKernel( __global int4* pairs, int numPairs)\n"
+"{\n"
+" int pairId = get_global_id(0);\n"
+" if( pairId< numPairs )\n"
+" {\n"
+" pairs[pairId].z = 0xffffffff;\n"
+" }\n"
+"}\n"
+;
diff --git a/thirdparty/bullet/src/Bullet3OpenCL/premake4.lua b/thirdparty/bullet/src/Bullet3OpenCL/premake4.lua
new file mode 100644
index 0000000000..55a8613634
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3OpenCL/premake4.lua
@@ -0,0 +1,29 @@
+function createProject(vendor)
+ hasCL = findOpenCL(vendor)
+
+ if (hasCL) then
+
+ project ("Bullet3OpenCL_" .. vendor)
+
+ initOpenCL(vendor)
+
+ kind "StaticLib"
+
+
+ includedirs {
+ ".",".."
+ }
+
+ files {
+ "**.cpp",
+ "**.h"
+ }
+
+ end
+end
+
+createProject("clew")
+createProject("AMD")
+createProject("Intel")
+createProject("NVIDIA")
+createProject("Apple")
diff --git a/thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/CMakeLists.txt b/thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/CMakeLists.txt
new file mode 100644
index 0000000000..125576634f
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/CMakeLists.txt
@@ -0,0 +1,55 @@
+
+INCLUDE_DIRECTORIES(
+ ${BULLET_PHYSICS_SOURCE_DIR}/src
+)
+
+SET(Bullet2FileLoader_SRCS
+ b3BulletFile.cpp
+ b3Chunk.cpp
+ b3DNA.cpp
+ b3File.cpp
+ b3Serializer.cpp
+)
+
+
+SET(Bullet2FileLoader_HDRS
+ b3BulletFile.h
+ b3Chunk.h
+ b3Common.h
+ b3Defines.h
+ b3DNA.h
+ b3File.h
+ b3Serializer.h
+ autogenerated/bullet2.h
+)
+
+ADD_LIBRARY(Bullet2FileLoader ${Bullet2FileLoader_SRCS} ${Bullet2FileLoader_HDRS})
+if (BUILD_SHARED_LIBS)
+ target_link_libraries(Bullet2FileLoader Bullet3Common)
+endif ()
+SET_TARGET_PROPERTIES(Bullet2FileLoader PROPERTIES VERSION ${BULLET_VERSION})
+SET_TARGET_PROPERTIES(Bullet2FileLoader PROPERTIES SOVERSION ${BULLET_VERSION})
+
+IF (INSTALL_LIBS)
+ IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
+ #FILES_MATCHING requires CMake 2.6
+ IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
+ IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+ INSTALL(TARGETS Bullet2FileLoader DESTINATION .)
+ ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+ INSTALL(TARGETS Bullet2FileLoader
+ RUNTIME DESTINATION bin
+ LIBRARY DESTINATION lib${LIB_SUFFIX}
+ ARCHIVE DESTINATION lib${LIB_SUFFIX})
+ INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.h" PATTERN
+".svn" EXCLUDE PATTERN "CMakeFiles" EXCLUDE)
+ ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+ ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
+
+ IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+ SET_TARGET_PROPERTIES(Bullet2FileLoader PROPERTIES FRAMEWORK true)
+ SET_TARGET_PROPERTIES(Bullet2FileLoader PROPERTIES PUBLIC_HEADER "${Bullet2FileLoader_HDRS}")
+ ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+ ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
+ENDIF (INSTALL_LIBS)
diff --git a/thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/autogenerated/bullet2.h b/thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/autogenerated/bullet2.h
new file mode 100644
index 0000000000..a6b57b1a12
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/autogenerated/bullet2.h
@@ -0,0 +1,1053 @@
+/* Copyright (C) 2011 Erwin Coumans & Charlie C
+*
+* 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.
+*/
+// Auto generated from Bullet/Extras/HeaderGenerator/bulletGenerate.py
+#ifndef __BULLET2_H__
+#define __BULLET2_H__
+namespace Bullet3SerializeBullet2 {
+
+// put an empty struct in the case
+typedef struct bInvalidHandle {
+ int unused;
+}bInvalidHandle;
+
+ class PointerArray;
+ class b3PhysicsSystem;
+ class ListBase;
+ class b3Vector3FloatData;
+ class b3Vector3DoubleData;
+ class b3Matrix3x3FloatData;
+ class b3Matrix3x3DoubleData;
+ class b3TransformFloatData;
+ class b3TransformDoubleData;
+ class b3BvhSubtreeInfoData;
+ class b3OptimizedBvhNodeFloatData;
+ class b3OptimizedBvhNodeDoubleData;
+ class b3QuantizedBvhNodeData;
+ class b3QuantizedBvhFloatData;
+ class b3QuantizedBvhDoubleData;
+ class b3CollisionShapeData;
+ class b3StaticPlaneShapeData;
+ class b3ConvexInternalShapeData;
+ class b3PositionAndRadius;
+ class b3MultiSphereShapeData;
+ class b3IntIndexData;
+ class b3ShortIntIndexData;
+ class b3ShortIntIndexTripletData;
+ class b3CharIndexTripletData;
+ class b3MeshPartData;
+ class b3StridingMeshInterfaceData;
+ class b3TriangleMeshShapeData;
+ class b3ScaledTriangleMeshShapeData;
+ class b3CompoundShapeChildData;
+ class b3CompoundShapeData;
+ class b3CylinderShapeData;
+ class b3CapsuleShapeData;
+ class b3TriangleInfoData;
+ class b3TriangleInfoMapData;
+ class b3GImpactMeshShapeData;
+ class b3ConvexHullShapeData;
+ class b3CollisionObjectDoubleData;
+ class b3CollisionObjectFloatData;
+ class b3DynamicsWorldDoubleData;
+ class b3DynamicsWorldFloatData;
+ class b3RigidBodyFloatData;
+ class b3RigidBodyDoubleData;
+ class b3ConstraintInfo1;
+ class b3TypedConstraintData;
+ class b3Point2PointConstraintFloatData;
+ class b3Point2PointConstraintDoubleData;
+ class b3HingeConstraintDoubleData;
+ class b3HingeConstraintFloatData;
+ class b3ConeTwistConstraintData;
+ class b3Generic6DofConstraintData;
+ class b3Generic6DofSpringConstraintData;
+ class b3SliderConstraintData;
+ class b3ContactSolverInfoDoubleData;
+ class b3ContactSolverInfoFloatData;
+ class SoftBodyMaterialData;
+ class SoftBodyNodeData;
+ class SoftBodyLinkData;
+ class SoftBodyFaceData;
+ class SoftBodyTetraData;
+ class SoftRigidAnchorData;
+ class SoftBodyConfigData;
+ class SoftBodyPoseData;
+ class SoftBodyClusterData;
+ class b3SoftBodyJointData;
+ class b3SoftBodyFloatData;
+// -------------------------------------------------- //
+ class PointerArray
+ {
+ public:
+ int m_size;
+ int m_capacity;
+ void *m_data;
+ };
+
+
+// -------------------------------------------------- //
+ class b3PhysicsSystem
+ {
+ public:
+ PointerArray m_collisionShapes;
+ PointerArray m_collisionObjects;
+ PointerArray m_constraints;
+ };
+
+
+// -------------------------------------------------- //
+ class ListBase
+ {
+ public:
+ void *first;
+ void *last;
+ };
+
+
+// -------------------------------------------------- //
+ class b3Vector3FloatData
+ {
+ public:
+ float m_floats[4];
+ };
+
+
+// -------------------------------------------------- //
+ class b3Vector3DoubleData
+ {
+ public:
+ double m_floats[4];
+ };
+
+
+// -------------------------------------------------- //
+ class b3Matrix3x3FloatData
+ {
+ public:
+ b3Vector3FloatData m_el[3];
+ };
+
+
+// -------------------------------------------------- //
+ class b3Matrix3x3DoubleData
+ {
+ public:
+ b3Vector3DoubleData m_el[3];
+ };
+
+
+// -------------------------------------------------- //
+ class b3TransformFloatData
+ {
+ public:
+ b3Matrix3x3FloatData m_basis;
+ b3Vector3FloatData m_origin;
+ };
+
+
+// -------------------------------------------------- //
+ class b3TransformDoubleData
+ {
+ public:
+ b3Matrix3x3DoubleData m_basis;
+ b3Vector3DoubleData m_origin;
+ };
+
+
+// -------------------------------------------------- //
+ class b3BvhSubtreeInfoData
+ {
+ public:
+ int m_rootNodeIndex;
+ int m_subtreeSize;
+ short m_quantizedAabbMin[3];
+ short m_quantizedAabbMax[3];
+ };
+
+
+// -------------------------------------------------- //
+ class b3OptimizedBvhNodeFloatData
+ {
+ public:
+ b3Vector3FloatData m_aabbMinOrg;
+ b3Vector3FloatData m_aabbMaxOrg;
+ int m_escapeIndex;
+ int m_subPart;
+ int m_triangleIndex;
+ char m_pad[4];
+ };
+
+
+// -------------------------------------------------- //
+ class b3OptimizedBvhNodeDoubleData
+ {
+ public:
+ b3Vector3DoubleData m_aabbMinOrg;
+ b3Vector3DoubleData m_aabbMaxOrg;
+ int m_escapeIndex;
+ int m_subPart;
+ int m_triangleIndex;
+ char m_pad[4];
+ };
+
+
+// -------------------------------------------------- //
+ class b3QuantizedBvhNodeData
+ {
+ public:
+ short m_quantizedAabbMin[3];
+ short m_quantizedAabbMax[3];
+ int m_escapeIndexOrTriangleIndex;
+ };
+
+
+// -------------------------------------------------- //
+ class b3QuantizedBvhFloatData
+ {
+ public:
+ b3Vector3FloatData m_bvhAabbMin;
+ b3Vector3FloatData m_bvhAabbMax;
+ b3Vector3FloatData m_bvhQuantization;
+ int m_curNodeIndex;
+ int m_useQuantization;
+ int m_numContiguousLeafNodes;
+ int m_numQuantizedContiguousNodes;
+ b3OptimizedBvhNodeFloatData *m_contiguousNodesPtr;
+ b3QuantizedBvhNodeData *m_quantizedContiguousNodesPtr;
+ b3BvhSubtreeInfoData *m_subTreeInfoPtr;
+ int m_traversalMode;
+ int m_numSubtreeHeaders;
+ };
+
+
+// -------------------------------------------------- //
+ class b3QuantizedBvhDoubleData
+ {
+ public:
+ b3Vector3DoubleData m_bvhAabbMin;
+ b3Vector3DoubleData m_bvhAabbMax;
+ b3Vector3DoubleData m_bvhQuantization;
+ int m_curNodeIndex;
+ int m_useQuantization;
+ int m_numContiguousLeafNodes;
+ int m_numQuantizedContiguousNodes;
+ b3OptimizedBvhNodeDoubleData *m_contiguousNodesPtr;
+ b3QuantizedBvhNodeData *m_quantizedContiguousNodesPtr;
+ int m_traversalMode;
+ int m_numSubtreeHeaders;
+ b3BvhSubtreeInfoData *m_subTreeInfoPtr;
+ };
+
+
+// -------------------------------------------------- //
+ class b3CollisionShapeData
+ {
+ public:
+ char *m_name;
+ int m_shapeType;
+ char m_padding[4];
+ };
+
+
+// -------------------------------------------------- //
+ class b3StaticPlaneShapeData
+ {
+ public:
+ b3CollisionShapeData m_collisionShapeData;
+ b3Vector3FloatData m_localScaling;
+ b3Vector3FloatData m_planeNormal;
+ float m_planeConstant;
+ char m_pad[4];
+ };
+
+
+// -------------------------------------------------- //
+ class b3ConvexInternalShapeData
+ {
+ public:
+ b3CollisionShapeData m_collisionShapeData;
+ b3Vector3FloatData m_localScaling;
+ b3Vector3FloatData m_implicitShapeDimensions;
+ float m_collisionMargin;
+ int m_padding;
+ };
+
+
+// -------------------------------------------------- //
+ class b3PositionAndRadius
+ {
+ public:
+ b3Vector3FloatData m_pos;
+ float m_radius;
+ };
+
+
+// -------------------------------------------------- //
+ class b3MultiSphereShapeData
+ {
+ public:
+ b3ConvexInternalShapeData m_convexInternalShapeData;
+ b3PositionAndRadius *m_localPositionArrayPtr;
+ int m_localPositionArraySize;
+ char m_padding[4];
+ };
+
+
+// -------------------------------------------------- //
+ class b3IntIndexData
+ {
+ public:
+ int m_value;
+ };
+
+
+// -------------------------------------------------- //
+ class b3ShortIntIndexData
+ {
+ public:
+ short m_value;
+ char m_pad[2];
+ };
+
+
+// -------------------------------------------------- //
+ class b3ShortIntIndexTripletData
+ {
+ public:
+ short m_values[3];
+ char m_pad[2];
+ };
+
+
+// -------------------------------------------------- //
+ class b3CharIndexTripletData
+ {
+ public:
+ char m_values[3];
+ char m_pad;
+ };
+
+
+// -------------------------------------------------- //
+ class b3MeshPartData
+ {
+ public:
+ b3Vector3FloatData *m_vertices3f;
+ b3Vector3DoubleData *m_vertices3d;
+ b3IntIndexData *m_indices32;
+ b3ShortIntIndexTripletData *m_3indices16;
+ b3CharIndexTripletData *m_3indices8;
+ b3ShortIntIndexData *m_indices16;
+ int m_numTriangles;
+ int m_numVertices;
+ };
+
+
+// -------------------------------------------------- //
+ class b3StridingMeshInterfaceData
+ {
+ public:
+ b3MeshPartData *m_meshPartsPtr;
+ b3Vector3FloatData m_scaling;
+ int m_numMeshParts;
+ char m_padding[4];
+ };
+
+
+// -------------------------------------------------- //
+ class b3TriangleMeshShapeData
+ {
+ public:
+ b3CollisionShapeData m_collisionShapeData;
+ b3StridingMeshInterfaceData m_meshInterface;
+ b3QuantizedBvhFloatData *m_quantizedFloatBvh;
+ b3QuantizedBvhDoubleData *m_quantizedDoubleBvh;
+ b3TriangleInfoMapData *m_triangleInfoMap;
+ float m_collisionMargin;
+ char m_pad3[4];
+ };
+
+
+// -------------------------------------------------- //
+ class b3ScaledTriangleMeshShapeData
+ {
+ public:
+ b3TriangleMeshShapeData m_trimeshShapeData;
+ b3Vector3FloatData m_localScaling;
+ };
+
+
+// -------------------------------------------------- //
+ class b3CompoundShapeChildData
+ {
+ public:
+ b3TransformFloatData m_transform;
+ b3CollisionShapeData *m_childShape;
+ int m_childShapeType;
+ float m_childMargin;
+ };
+
+
+// -------------------------------------------------- //
+ class b3CompoundShapeData
+ {
+ public:
+ b3CollisionShapeData m_collisionShapeData;
+ b3CompoundShapeChildData *m_childShapePtr;
+ int m_numChildShapes;
+ float m_collisionMargin;
+ };
+
+
+// -------------------------------------------------- //
+ class b3CylinderShapeData
+ {
+ public:
+ b3ConvexInternalShapeData m_convexInternalShapeData;
+ int m_upAxis;
+ char m_padding[4];
+ };
+
+
+// -------------------------------------------------- //
+ class b3CapsuleShapeData
+ {
+ public:
+ b3ConvexInternalShapeData m_convexInternalShapeData;
+ int m_upAxis;
+ char m_padding[4];
+ };
+
+
+// -------------------------------------------------- //
+ class b3TriangleInfoData
+ {
+ public:
+ int m_flags;
+ float m_edgeV0V1Angle;
+ float m_edgeV1V2Angle;
+ float m_edgeV2V0Angle;
+ };
+
+
+// -------------------------------------------------- //
+ class b3TriangleInfoMapData
+ {
+ public:
+ int *m_hashTablePtr;
+ int *m_nextPtr;
+ b3TriangleInfoData *m_valueArrayPtr;
+ int *m_keyArrayPtr;
+ float m_convexEpsilon;
+ float m_planarEpsilon;
+ float m_equalVertexThreshold;
+ float m_edgeDistanceThreshold;
+ float m_zeroAreaThreshold;
+ int m_nextSize;
+ int m_hashTableSize;
+ int m_numValues;
+ int m_numKeys;
+ char m_padding[4];
+ };
+
+
+// -------------------------------------------------- //
+ class b3GImpactMeshShapeData
+ {
+ public:
+ b3CollisionShapeData m_collisionShapeData;
+ b3StridingMeshInterfaceData m_meshInterface;
+ b3Vector3FloatData m_localScaling;
+ float m_collisionMargin;
+ int m_gimpactSubType;
+ };
+
+
+// -------------------------------------------------- //
+ class b3ConvexHullShapeData
+ {
+ public:
+ b3ConvexInternalShapeData m_convexInternalShapeData;
+ b3Vector3FloatData *m_unscaledPointsFloatPtr;
+ b3Vector3DoubleData *m_unscaledPointsDoublePtr;
+ int m_numUnscaledPoints;
+ char m_padding3[4];
+ };
+
+
+// -------------------------------------------------- //
+ class b3CollisionObjectDoubleData
+ {
+ public:
+ void *m_broadphaseHandle;
+ void *m_collisionShape;
+ b3CollisionShapeData *m_rootCollisionShape;
+ char *m_name;
+ b3TransformDoubleData m_worldTransform;
+ b3TransformDoubleData m_interpolationWorldTransform;
+ b3Vector3DoubleData m_interpolationLinearVelocity;
+ b3Vector3DoubleData m_interpolationAngularVelocity;
+ b3Vector3DoubleData m_anisotropicFriction;
+ double m_contactProcessingThreshold;
+ double m_deactivationTime;
+ double m_friction;
+ double m_rollingFriction;
+ double m_restitution;
+ double m_hitFraction;
+ double m_ccdSweptSphereRadius;
+ double m_ccdMotionThreshold;
+ int m_hasAnisotropicFriction;
+ int m_collisionFlags;
+ int m_islandTag1;
+ int m_companionId;
+ int m_activationState1;
+ int m_internalType;
+ int m_checkCollideWith;
+ char m_padding[4];
+ };
+
+
+// -------------------------------------------------- //
+ class b3CollisionObjectFloatData
+ {
+ public:
+ void *m_broadphaseHandle;
+ void *m_collisionShape;
+ b3CollisionShapeData *m_rootCollisionShape;
+ char *m_name;
+ b3TransformFloatData m_worldTransform;
+ b3TransformFloatData m_interpolationWorldTransform;
+ b3Vector3FloatData m_interpolationLinearVelocity;
+ b3Vector3FloatData m_interpolationAngularVelocity;
+ b3Vector3FloatData m_anisotropicFriction;
+ float m_contactProcessingThreshold;
+ float m_deactivationTime;
+ float m_friction;
+ float m_rollingFriction;
+ float m_restitution;
+ float m_hitFraction;
+ float m_ccdSweptSphereRadius;
+ float m_ccdMotionThreshold;
+ int m_hasAnisotropicFriction;
+ int m_collisionFlags;
+ int m_islandTag1;
+ int m_companionId;
+ int m_activationState1;
+ int m_internalType;
+ int m_checkCollideWith;
+ char m_padding[4];
+ };
+
+
+
+// -------------------------------------------------- //
+ class b3RigidBodyFloatData
+ {
+ public:
+ b3CollisionObjectFloatData m_collisionObjectData;
+ b3Matrix3x3FloatData m_invInertiaTensorWorld;
+ b3Vector3FloatData m_linearVelocity;
+ b3Vector3FloatData m_angularVelocity;
+ b3Vector3FloatData m_angularFactor;
+ b3Vector3FloatData m_linearFactor;
+ b3Vector3FloatData m_gravity;
+ b3Vector3FloatData m_gravity_acceleration;
+ b3Vector3FloatData m_invInertiaLocal;
+ b3Vector3FloatData m_totalForce;
+ b3Vector3FloatData m_totalTorque;
+ float m_inverseMass;
+ float m_linearDamping;
+ float m_angularDamping;
+ float m_additionalDampingFactor;
+ float m_additionalLinearDampingThresholdSqr;
+ float m_additionalAngularDampingThresholdSqr;
+ float m_additionalAngularDampingFactor;
+ float m_linearSleepingThreshold;
+ float m_angularSleepingThreshold;
+ int m_additionalDamping;
+ };
+
+
+// -------------------------------------------------- //
+ class b3RigidBodyDoubleData
+ {
+ public:
+ b3CollisionObjectDoubleData m_collisionObjectData;
+ b3Matrix3x3DoubleData m_invInertiaTensorWorld;
+ b3Vector3DoubleData m_linearVelocity;
+ b3Vector3DoubleData m_angularVelocity;
+ b3Vector3DoubleData m_angularFactor;
+ b3Vector3DoubleData m_linearFactor;
+ b3Vector3DoubleData m_gravity;
+ b3Vector3DoubleData m_gravity_acceleration;
+ b3Vector3DoubleData m_invInertiaLocal;
+ b3Vector3DoubleData m_totalForce;
+ b3Vector3DoubleData m_totalTorque;
+ double m_inverseMass;
+ double m_linearDamping;
+ double m_angularDamping;
+ double m_additionalDampingFactor;
+ double m_additionalLinearDampingThresholdSqr;
+ double m_additionalAngularDampingThresholdSqr;
+ double m_additionalAngularDampingFactor;
+ double m_linearSleepingThreshold;
+ double m_angularSleepingThreshold;
+ int m_additionalDamping;
+ char m_padding[4];
+ };
+
+
+// -------------------------------------------------- //
+ class b3ConstraintInfo1
+ {
+ public:
+ int m_numConstraintRows;
+ int nub;
+ };
+
+
+// -------------------------------------------------- //
+ class b3TypedConstraintData
+ {
+ public:
+ bInvalidHandle *m_rbA;
+ bInvalidHandle *m_rbB;
+ char *m_name;
+ int m_objectType;
+ int m_userConstraintType;
+ int m_userConstraintId;
+ int m_needsFeedback;
+ float m_appliedImpulse;
+ float m_dbgDrawSize;
+ int m_disableCollisionsBetweenLinkedBodies;
+ int m_overrideNumSolverIterations;
+ float m_breakingImpulseThreshold;
+ int m_isEnabled;
+ };
+
+
+// -------------------------------------------------- //
+ class b3Point2PointConstraintFloatData
+ {
+ public:
+ b3TypedConstraintData m_typeConstraintData;
+ b3Vector3FloatData m_pivotInA;
+ b3Vector3FloatData m_pivotInB;
+ };
+
+
+// -------------------------------------------------- //
+ class b3Point2PointConstraintDoubleData
+ {
+ public:
+ b3TypedConstraintData m_typeConstraintData;
+ b3Vector3DoubleData m_pivotInA;
+ b3Vector3DoubleData m_pivotInB;
+ };
+
+
+// -------------------------------------------------- //
+ class b3HingeConstraintDoubleData
+ {
+ public:
+ b3TypedConstraintData m_typeConstraintData;
+ b3TransformDoubleData m_rbAFrame;
+ b3TransformDoubleData m_rbBFrame;
+ int m_useReferenceFrameA;
+ int m_angularOnly;
+ int m_enableAngularMotor;
+ float m_motorTargetVelocity;
+ float m_maxMotorImpulse;
+ float m_lowerLimit;
+ float m_upperLimit;
+ float m_limitSoftness;
+ float m_biasFactor;
+ float m_relaxationFactor;
+ };
+
+
+// -------------------------------------------------- //
+ class b3HingeConstraintFloatData
+ {
+ public:
+ b3TypedConstraintData m_typeConstraintData;
+ b3TransformFloatData m_rbAFrame;
+ b3TransformFloatData m_rbBFrame;
+ int m_useReferenceFrameA;
+ int m_angularOnly;
+ int m_enableAngularMotor;
+ float m_motorTargetVelocity;
+ float m_maxMotorImpulse;
+ float m_lowerLimit;
+ float m_upperLimit;
+ float m_limitSoftness;
+ float m_biasFactor;
+ float m_relaxationFactor;
+ };
+
+
+// -------------------------------------------------- //
+ class b3ConeTwistConstraintData
+ {
+ public:
+ b3TypedConstraintData m_typeConstraintData;
+ b3TransformFloatData m_rbAFrame;
+ b3TransformFloatData m_rbBFrame;
+ float m_swingSpan1;
+ float m_swingSpan2;
+ float m_twistSpan;
+ float m_limitSoftness;
+ float m_biasFactor;
+ float m_relaxationFactor;
+ float m_damping;
+ char m_pad[4];
+ };
+
+
+// -------------------------------------------------- //
+ class b3Generic6DofConstraintData
+ {
+ public:
+ b3TypedConstraintData m_typeConstraintData;
+ b3TransformFloatData m_rbAFrame;
+ b3TransformFloatData m_rbBFrame;
+ b3Vector3FloatData m_linearUpperLimit;
+ b3Vector3FloatData m_linearLowerLimit;
+ b3Vector3FloatData m_angularUpperLimit;
+ b3Vector3FloatData m_angularLowerLimit;
+ int m_useLinearReferenceFrameA;
+ int m_useOffsetForConstraintFrame;
+ };
+
+
+// -------------------------------------------------- //
+ class b3Generic6DofSpringConstraintData
+ {
+ public:
+ b3Generic6DofConstraintData m_6dofData;
+ int m_springEnabled[6];
+ float m_equilibriumPoint[6];
+ float m_springStiffness[6];
+ float m_springDamping[6];
+ };
+
+
+// -------------------------------------------------- //
+ class b3SliderConstraintData
+ {
+ public:
+ b3TypedConstraintData m_typeConstraintData;
+ b3TransformFloatData m_rbAFrame;
+ b3TransformFloatData m_rbBFrame;
+ float m_linearUpperLimit;
+ float m_linearLowerLimit;
+ float m_angularUpperLimit;
+ float m_angularLowerLimit;
+ int m_useLinearReferenceFrameA;
+ int m_useOffsetForConstraintFrame;
+ };
+
+
+// -------------------------------------------------- //
+ class b3ContactSolverInfoDoubleData
+ {
+ public:
+ double m_tau;
+ double m_damping;
+ double m_friction;
+ double m_timeStep;
+ double m_restitution;
+ double m_maxErrorReduction;
+ double m_sor;
+ double m_erp;
+ double m_erp2;
+ double m_globalCfm;
+ double m_splitImpulsePenetrationThreshold;
+ double m_splitImpulseTurnErp;
+ double m_linearSlop;
+ double m_warmstartingFactor;
+ double m_maxGyroscopicForce;
+ double m_singleAxisRollingFrictionThreshold;
+ int m_numIterations;
+ int m_solverMode;
+ int m_restingContactRestitutionThreshold;
+ int m_minimumSolverBatchSize;
+ int m_splitImpulse;
+ char m_padding[4];
+ };
+
+
+// -------------------------------------------------- //
+ class b3ContactSolverInfoFloatData
+ {
+ public:
+ float m_tau;
+ float m_damping;
+ float m_friction;
+ float m_timeStep;
+ float m_restitution;
+ float m_maxErrorReduction;
+ float m_sor;
+ float m_erp;
+ float m_erp2;
+ float m_globalCfm;
+ float m_splitImpulsePenetrationThreshold;
+ float m_splitImpulseTurnErp;
+ float m_linearSlop;
+ float m_warmstartingFactor;
+ float m_maxGyroscopicForce;
+ float m_singleAxisRollingFrictionThreshold;
+ int m_numIterations;
+ int m_solverMode;
+ int m_restingContactRestitutionThreshold;
+ int m_minimumSolverBatchSize;
+ int m_splitImpulse;
+ char m_padding[4];
+ };
+
+
+ // -------------------------------------------------- //
+ class b3DynamicsWorldDoubleData
+ {
+ public:
+ b3ContactSolverInfoDoubleData m_solverInfo;
+ b3Vector3DoubleData m_gravity;
+ };
+
+
+// -------------------------------------------------- //
+ class b3DynamicsWorldFloatData
+ {
+ public:
+ b3ContactSolverInfoFloatData m_solverInfo;
+ b3Vector3FloatData m_gravity;
+ };
+
+
+
+// -------------------------------------------------- //
+ class SoftBodyMaterialData
+ {
+ public:
+ float m_linearStiffness;
+ float m_angularStiffness;
+ float m_volumeStiffness;
+ int m_flags;
+ };
+
+
+// -------------------------------------------------- //
+ class SoftBodyNodeData
+ {
+ public:
+ SoftBodyMaterialData *m_material;
+ b3Vector3FloatData m_position;
+ b3Vector3FloatData m_previousPosition;
+ b3Vector3FloatData m_velocity;
+ b3Vector3FloatData m_accumulatedForce;
+ b3Vector3FloatData m_normal;
+ float m_inverseMass;
+ float m_area;
+ int m_attach;
+ int m_pad;
+ };
+
+
+// -------------------------------------------------- //
+ class SoftBodyLinkData
+ {
+ public:
+ SoftBodyMaterialData *m_material;
+ int m_nodeIndices[2];
+ float m_restLength;
+ int m_bbending;
+ };
+
+
+// -------------------------------------------------- //
+ class SoftBodyFaceData
+ {
+ public:
+ b3Vector3FloatData m_normal;
+ SoftBodyMaterialData *m_material;
+ int m_nodeIndices[3];
+ float m_restArea;
+ };
+
+
+// -------------------------------------------------- //
+ class SoftBodyTetraData
+ {
+ public:
+ b3Vector3FloatData m_c0[4];
+ SoftBodyMaterialData *m_material;
+ int m_nodeIndices[4];
+ float m_restVolume;
+ float m_c1;
+ float m_c2;
+ int m_pad;
+ };
+
+
+// -------------------------------------------------- //
+ class SoftRigidAnchorData
+ {
+ public:
+ b3Matrix3x3FloatData m_c0;
+ b3Vector3FloatData m_c1;
+ b3Vector3FloatData m_localFrame;
+ bInvalidHandle *m_rigidBody;
+ int m_nodeIndex;
+ float m_c2;
+ };
+
+
+// -------------------------------------------------- //
+ class SoftBodyConfigData
+ {
+ public:
+ int m_aeroModel;
+ float m_baumgarte;
+ float m_damping;
+ float m_drag;
+ float m_lift;
+ float m_pressure;
+ float m_volume;
+ float m_dynamicFriction;
+ float m_poseMatch;
+ float m_rigidContactHardness;
+ float m_kineticContactHardness;
+ float m_softContactHardness;
+ float m_anchorHardness;
+ float m_softRigidClusterHardness;
+ float m_softKineticClusterHardness;
+ float m_softSoftClusterHardness;
+ float m_softRigidClusterImpulseSplit;
+ float m_softKineticClusterImpulseSplit;
+ float m_softSoftClusterImpulseSplit;
+ float m_maxVolume;
+ float m_timeScale;
+ int m_velocityIterations;
+ int m_positionIterations;
+ int m_driftIterations;
+ int m_clusterIterations;
+ int m_collisionFlags;
+ };
+
+
+// -------------------------------------------------- //
+ class SoftBodyPoseData
+ {
+ public:
+ b3Matrix3x3FloatData m_rot;
+ b3Matrix3x3FloatData m_scale;
+ b3Matrix3x3FloatData m_aqq;
+ b3Vector3FloatData m_com;
+ b3Vector3FloatData *m_positions;
+ float *m_weights;
+ int m_numPositions;
+ int m_numWeigts;
+ int m_bvolume;
+ int m_bframe;
+ float m_restVolume;
+ int m_pad;
+ };
+
+
+// -------------------------------------------------- //
+ class SoftBodyClusterData
+ {
+ public:
+ b3TransformFloatData m_framexform;
+ b3Matrix3x3FloatData m_locii;
+ b3Matrix3x3FloatData m_invwi;
+ b3Vector3FloatData m_com;
+ b3Vector3FloatData m_vimpulses[2];
+ b3Vector3FloatData m_dimpulses[2];
+ b3Vector3FloatData m_lv;
+ b3Vector3FloatData m_av;
+ b3Vector3FloatData *m_framerefs;
+ int *m_nodeIndices;
+ float *m_masses;
+ int m_numFrameRefs;
+ int m_numNodes;
+ int m_numMasses;
+ float m_idmass;
+ float m_imass;
+ int m_nvimpulses;
+ int m_ndimpulses;
+ float m_ndamping;
+ float m_ldamping;
+ float m_adamping;
+ float m_matching;
+ float m_maxSelfCollisionImpulse;
+ float m_selfCollisionImpulseFactor;
+ int m_containsAnchor;
+ int m_collide;
+ int m_clusterIndex;
+ };
+
+
+// -------------------------------------------------- //
+ class b3SoftBodyJointData
+ {
+ public:
+ void *m_bodyA;
+ void *m_bodyB;
+ b3Vector3FloatData m_refs[2];
+ float m_cfm;
+ float m_erp;
+ float m_split;
+ int m_delete;
+ b3Vector3FloatData m_relPosition[2];
+ int m_bodyAtype;
+ int m_bodyBtype;
+ int m_jointType;
+ int m_pad;
+ };
+
+
+// -------------------------------------------------- //
+ class b3SoftBodyFloatData
+ {
+ public:
+ b3CollisionObjectFloatData m_collisionObjectData;
+ SoftBodyPoseData *m_pose;
+ SoftBodyMaterialData **m_materials;
+ SoftBodyNodeData *m_nodes;
+ SoftBodyLinkData *m_links;
+ SoftBodyFaceData *m_faces;
+ SoftBodyTetraData *m_tetrahedra;
+ SoftRigidAnchorData *m_anchors;
+ SoftBodyClusterData *m_clusters;
+ b3SoftBodyJointData *m_joints;
+ int m_numMaterials;
+ int m_numNodes;
+ int m_numLinks;
+ int m_numFaces;
+ int m_numTetrahedra;
+ int m_numAnchors;
+ int m_numClusters;
+ int m_numJoints;
+ SoftBodyConfigData m_config;
+ };
+
+
+}
+#endif//__BULLET2_H__ \ No newline at end of file
diff --git a/thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/b3BulletFile.cpp b/thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/b3BulletFile.cpp
new file mode 100644
index 0000000000..c3ceb8388c
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/b3BulletFile.cpp
@@ -0,0 +1,423 @@
+/*
+bParse
+Copyright (c) 2006-2010 Erwin Coumans http://gamekit.googlecode.com
+
+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 "b3BulletFile.h"
+#include "b3Defines.h"
+#include "b3DNA.h"
+
+#if !defined( __CELLOS_LV2__) && !defined(__MWERKS__)
+#include <memory.h>
+#endif
+#include <string.h>
+
+
+// 32 && 64 bit versions
+#ifdef B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+#ifdef _WIN64
+extern char b3s_bulletDNAstr64[];
+extern int b3s_bulletDNAlen64;
+#else
+extern char b3s_bulletDNAstr[];
+extern int b3s_bulletDNAlen;
+#endif //_WIN64
+#else//B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+
+extern char b3s_bulletDNAstr64[];
+extern int b3s_bulletDNAlen64;
+extern char b3s_bulletDNAstr[];
+extern int b3s_bulletDNAlen;
+
+#endif //B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+
+using namespace bParse;
+
+b3BulletFile::b3BulletFile()
+:bFile("", "BULLET ")
+{
+ mMemoryDNA = new bDNA(); //this memory gets released in the bFile::~bFile destructor,@todo not consistent with the rule 'who allocates it, has to deallocate it"
+
+ m_DnaCopy = 0;
+
+
+#ifdef B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+#ifdef _WIN64
+ m_DnaCopy = (char*)b3AlignedAlloc(b3s_bulletDNAlen64,16);
+ memcpy(m_DnaCopy,b3s_bulletDNAstr64,b3s_bulletDNAlen64);
+ mMemoryDNA->init(m_DnaCopy,b3s_bulletDNAlen64);
+#else//_WIN64
+ m_DnaCopy = (char*)b3AlignedAlloc(b3s_bulletDNAlen,16);
+ memcpy(m_DnaCopy,b3s_bulletDNAstr,b3s_bulletDNAlen);
+ mMemoryDNA->init(m_DnaCopy,b3s_bulletDNAlen);
+#endif//_WIN64
+#else//B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+ if (VOID_IS_8)
+ {
+ m_DnaCopy = (char*) b3AlignedAlloc(b3s_bulletDNAlen64,16);
+ memcpy(m_DnaCopy,b3s_bulletDNAstr64,b3s_bulletDNAlen64);
+ mMemoryDNA->init(m_DnaCopy,b3s_bulletDNAlen64);
+ }
+ else
+ {
+ m_DnaCopy =(char*) b3AlignedAlloc(b3s_bulletDNAlen,16);
+ memcpy(m_DnaCopy,b3s_bulletDNAstr,b3s_bulletDNAlen);
+ mMemoryDNA->init(m_DnaCopy,b3s_bulletDNAlen);
+ }
+#endif//B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+}
+
+
+
+b3BulletFile::b3BulletFile(const char* fileName)
+:bFile(fileName, "BULLET ")
+{
+ m_DnaCopy = 0;
+}
+
+
+
+b3BulletFile::b3BulletFile(char *memoryBuffer, int len)
+:bFile(memoryBuffer,len, "BULLET ")
+{
+ m_DnaCopy = 0;
+}
+
+
+b3BulletFile::~b3BulletFile()
+{
+ if (m_DnaCopy)
+ b3AlignedFree(m_DnaCopy);
+
+
+ while (m_dataBlocks.size())
+ {
+ char* dataBlock = m_dataBlocks[m_dataBlocks.size()-1];
+ delete[] dataBlock;
+ m_dataBlocks.pop_back();
+ }
+
+}
+
+
+
+// ----------------------------------------------------- //
+void b3BulletFile::parseData()
+{
+// printf ("Building datablocks");
+// printf ("Chunk size = %d",CHUNK_HEADER_LEN);
+// printf ("File chunk size = %d",ChunkUtils::getOffset(mFlags));
+
+ const bool brokenDNA = (mFlags&FD_BROKEN_DNA)!=0;
+
+ //const bool swap = (mFlags&FD_ENDIAN_SWAP)!=0;
+
+
+ mDataStart = 12;
+
+ char *dataPtr = mFileBuffer+mDataStart;
+
+ bChunkInd dataChunk;
+ dataChunk.code = 0;
+
+
+ //dataPtr += ChunkUtils::getNextBlock(&dataChunk, dataPtr, mFlags);
+ int seek = getNextBlock(&dataChunk, dataPtr, mFlags);
+
+
+ if (mFlags &FD_ENDIAN_SWAP)
+ swapLen(dataPtr);
+
+ //dataPtr += ChunkUtils::getOffset(mFlags);
+ char *dataPtrHead = 0;
+
+ while (dataChunk.code != B3_DNA1)
+ {
+ if (!brokenDNA || (dataChunk.code != B3_QUANTIZED_BVH_CODE) )
+ {
+
+ // one behind
+ if (dataChunk.code == B3_SDNA) break;
+ //if (dataChunk.code == DNA1) break;
+
+ // same as (BHEAD+DATA dependency)
+ dataPtrHead = dataPtr+ChunkUtils::getOffset(mFlags);
+ if (dataChunk.dna_nr>=0)
+ {
+ char *id = readStruct(dataPtrHead, dataChunk);
+
+ // lookup maps
+ if (id)
+ {
+ m_chunkPtrPtrMap.insert(dataChunk.oldPtr, dataChunk);
+ mLibPointers.insert(dataChunk.oldPtr, (bStructHandle*)id);
+
+ m_chunks.push_back(dataChunk);
+ // block it
+ //bListBasePtr *listID = mMain->getListBasePtr(dataChunk.code);
+ //if (listID)
+ // listID->push_back((bStructHandle*)id);
+ }
+
+ if (dataChunk.code == B3_SOFTBODY_CODE)
+ {
+ m_softBodies.push_back((bStructHandle*) id);
+ }
+
+ if (dataChunk.code == B3_RIGIDBODY_CODE)
+ {
+ m_rigidBodies.push_back((bStructHandle*) id);
+ }
+
+ if (dataChunk.code == B3_DYNAMICSWORLD_CODE)
+ {
+ m_dynamicsWorldInfo.push_back((bStructHandle*) id);
+ }
+
+ if (dataChunk.code == B3_CONSTRAINT_CODE)
+ {
+ m_constraints.push_back((bStructHandle*) id);
+ }
+
+ if (dataChunk.code == B3_QUANTIZED_BVH_CODE)
+ {
+ m_bvhs.push_back((bStructHandle*) id);
+ }
+
+ if (dataChunk.code == B3_TRIANLGE_INFO_MAP)
+ {
+ m_triangleInfoMaps.push_back((bStructHandle*) id);
+ }
+
+ if (dataChunk.code == B3_COLLISIONOBJECT_CODE)
+ {
+ m_collisionObjects.push_back((bStructHandle*) id);
+ }
+
+ if (dataChunk.code == B3_SHAPE_CODE)
+ {
+ m_collisionShapes.push_back((bStructHandle*) id);
+ }
+
+ // if (dataChunk.code == GLOB)
+ // {
+ // m_glob = (bStructHandle*) id;
+ // }
+ } else
+ {
+ //printf("unknown chunk\n");
+
+ mLibPointers.insert(dataChunk.oldPtr, (bStructHandle*)dataPtrHead);
+ }
+ } else
+ {
+ printf("skipping B3_QUANTIZED_BVH_CODE due to broken DNA\n");
+ }
+
+
+ dataPtr += seek;
+
+ seek = getNextBlock(&dataChunk, dataPtr, mFlags);
+ if (mFlags &FD_ENDIAN_SWAP)
+ swapLen(dataPtr);
+
+ if (seek < 0)
+ break;
+ }
+
+}
+
+void b3BulletFile::addDataBlock(char* dataBlock)
+{
+ m_dataBlocks.push_back(dataBlock);
+
+}
+
+
+
+
+void b3BulletFile::writeDNA(FILE* fp)
+{
+
+ bChunkInd dataChunk;
+ dataChunk.code = B3_DNA1;
+ dataChunk.dna_nr = 0;
+ dataChunk.nr = 1;
+#ifdef B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+ if (VOID_IS_8)
+ {
+#ifdef _WIN64
+ dataChunk.len = b3s_bulletDNAlen64;
+ dataChunk.oldPtr = b3s_bulletDNAstr64;
+ fwrite(&dataChunk,sizeof(bChunkInd),1,fp);
+ fwrite(b3s_bulletDNAstr64, b3s_bulletDNAlen64,1,fp);
+#else
+ b3Assert(0);
+#endif
+ }
+ else
+ {
+#ifndef _WIN64
+ dataChunk.len = b3s_bulletDNAlen;
+ dataChunk.oldPtr = b3s_bulletDNAstr;
+ fwrite(&dataChunk,sizeof(bChunkInd),1,fp);
+ fwrite(b3s_bulletDNAstr, b3s_bulletDNAlen,1,fp);
+#else//_WIN64
+ b3Assert(0);
+#endif//_WIN64
+ }
+#else//B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+ if (VOID_IS_8)
+ {
+ dataChunk.len = b3s_bulletDNAlen64;
+ dataChunk.oldPtr = b3s_bulletDNAstr64;
+ fwrite(&dataChunk,sizeof(bChunkInd),1,fp);
+ fwrite(b3s_bulletDNAstr64, b3s_bulletDNAlen64,1,fp);
+ }
+ else
+ {
+ dataChunk.len = b3s_bulletDNAlen;
+ dataChunk.oldPtr = b3s_bulletDNAstr;
+ fwrite(&dataChunk,sizeof(bChunkInd),1,fp);
+ fwrite(b3s_bulletDNAstr, b3s_bulletDNAlen,1,fp);
+ }
+#endif//B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+}
+
+
+void b3BulletFile::parse(int verboseMode)
+{
+#ifdef B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+ if (VOID_IS_8)
+ {
+#ifdef _WIN64
+
+ if (m_DnaCopy)
+ delete m_DnaCopy;
+ m_DnaCopy = (char*)b3AlignedAlloc(b3s_bulletDNAlen64,16);
+ memcpy(m_DnaCopy,b3s_bulletDNAstr64,b3s_bulletDNAlen64);
+ parseInternal(verboseMode,(char*)b3s_bulletDNAstr64,b3s_bulletDNAlen64);
+#else
+ b3Assert(0);
+#endif
+ }
+ else
+ {
+#ifndef _WIN64
+
+ if (m_DnaCopy)
+ delete m_DnaCopy;
+ m_DnaCopy = (char*)b3AlignedAlloc(b3s_bulletDNAlen,16);
+ memcpy(m_DnaCopy,b3s_bulletDNAstr,b3s_bulletDNAlen);
+ parseInternal(verboseMode,m_DnaCopy,b3s_bulletDNAlen);
+#else
+ b3Assert(0);
+#endif
+ }
+#else//B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+ if (VOID_IS_8)
+ {
+ if (m_DnaCopy)
+ delete m_DnaCopy;
+ m_DnaCopy = (char*)b3AlignedAlloc(b3s_bulletDNAlen64,16);
+ memcpy(m_DnaCopy,b3s_bulletDNAstr64,b3s_bulletDNAlen64);
+ parseInternal(verboseMode,m_DnaCopy,b3s_bulletDNAlen64);
+ }
+ else
+ {
+ if (m_DnaCopy)
+ delete m_DnaCopy;
+ m_DnaCopy = (char*)b3AlignedAlloc(b3s_bulletDNAlen,16);
+ memcpy(m_DnaCopy,b3s_bulletDNAstr,b3s_bulletDNAlen);
+ parseInternal(verboseMode,m_DnaCopy,b3s_bulletDNAlen);
+ }
+#endif//B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+
+ //the parsing will convert to cpu endian
+ mFlags &=~FD_ENDIAN_SWAP;
+
+ int littleEndian= 1;
+ littleEndian= ((char*)&littleEndian)[0];
+
+ mFileBuffer[8] = littleEndian?'v':'V';
+
+}
+
+// experimental
+int b3BulletFile::write(const char* fileName, bool fixupPointers)
+{
+ FILE *fp = fopen(fileName, "wb");
+ if (fp)
+ {
+ char header[B3_SIZEOFBLENDERHEADER] ;
+ memcpy(header, m_headerString, 7);
+ int endian= 1;
+ endian= ((char*)&endian)[0];
+
+ if (endian)
+ {
+ header[7] = '_';
+ } else
+ {
+ header[7] = '-';
+ }
+ if (VOID_IS_8)
+ {
+ header[8]='V';
+ } else
+ {
+ header[8]='v';
+ }
+
+ header[9] = '2';
+ header[10] = '7';
+ header[11] = '5';
+
+ fwrite(header,B3_SIZEOFBLENDERHEADER,1,fp);
+
+ writeChunks(fp, fixupPointers);
+
+ writeDNA(fp);
+
+ fclose(fp);
+
+ } else
+ {
+ printf("Error: cannot open file %s for writing\n",fileName);
+ return 0;
+ }
+ return 1;
+}
+
+
+
+void b3BulletFile::addStruct(const char* structType,void* data, int len, void* oldPtr, int code)
+{
+
+ bParse::bChunkInd dataChunk;
+ dataChunk.code = code;
+ dataChunk.nr = 1;
+ dataChunk.len = len;
+ dataChunk.dna_nr = mMemoryDNA->getReverseType(structType);
+ dataChunk.oldPtr = oldPtr;
+
+ ///Perform structure size validation
+ short* structInfo= mMemoryDNA->getStruct(dataChunk.dna_nr);
+ int elemBytes;
+ elemBytes= mMemoryDNA->getLength(structInfo[0]);
+// int elemBytes = mMemoryDNA->getElementSize(structInfo[0],structInfo[1]);
+ assert(len==elemBytes);
+
+ mLibPointers.insert(dataChunk.oldPtr, (bStructHandle*)data);
+ m_chunks.push_back(dataChunk);
+}
diff --git a/thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/b3BulletFile.h b/thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/b3BulletFile.h
new file mode 100644
index 0000000000..fb1b9b0dde
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/b3BulletFile.h
@@ -0,0 +1,83 @@
+/*
+bParse
+Copyright (c) 2006-2010 Charlie C & Erwin Coumans http://gamekit.googlecode.com
+
+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 B3_BULLET_FILE_H
+#define B3_BULLET_FILE_H
+
+
+#include "b3File.h"
+#include "Bullet3Common/b3AlignedObjectArray.h"
+#include "b3Defines.h"
+
+#include "Bullet3Serialize/Bullet2FileLoader/b3Serializer.h"
+
+
+
+namespace bParse {
+
+ // ----------------------------------------------------- //
+ class b3BulletFile : public bFile
+ {
+
+
+ protected:
+
+ char* m_DnaCopy;
+
+ public:
+
+ b3AlignedObjectArray<bStructHandle*> m_softBodies;
+
+ b3AlignedObjectArray<bStructHandle*> m_rigidBodies;
+
+ b3AlignedObjectArray<bStructHandle*> m_collisionObjects;
+
+ b3AlignedObjectArray<bStructHandle*> m_collisionShapes;
+
+ b3AlignedObjectArray<bStructHandle*> m_constraints;
+
+ b3AlignedObjectArray<bStructHandle*> m_bvhs;
+
+ b3AlignedObjectArray<bStructHandle*> m_triangleInfoMaps;
+
+ b3AlignedObjectArray<bStructHandle*> m_dynamicsWorldInfo;
+
+ b3AlignedObjectArray<char*> m_dataBlocks;
+ b3BulletFile();
+
+ b3BulletFile(const char* fileName);
+
+ b3BulletFile(char *memoryBuffer, int len);
+
+ virtual ~b3BulletFile();
+
+ virtual void addDataBlock(char* dataBlock);
+
+
+ // experimental
+ virtual int write(const char* fileName, bool fixupPointers=false);
+
+ virtual void parse(int verboseMode);
+
+ virtual void parseData();
+
+ virtual void writeDNA(FILE* fp);
+
+ void addStruct(const char* structType,void* data, int len, void* oldPtr, int code);
+
+ };
+};
+
+#endif //B3_BULLET_FILE_H
diff --git a/thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/b3Chunk.cpp b/thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/b3Chunk.cpp
new file mode 100644
index 0000000000..c0e1bb708c
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/b3Chunk.cpp
@@ -0,0 +1,75 @@
+/*
+bParse
+Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com
+
+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 "b3Chunk.h"
+#include "b3Defines.h"
+#include "b3File.h"
+
+#if !defined( __CELLOS_LV2__) && !defined(__MWERKS__)
+#include <memory.h>
+#endif
+#include <string.h>
+
+
+using namespace bParse;
+
+
+// ----------------------------------------------------- //
+short ChunkUtils::swapShort(short sht)
+{
+ B3_SWITCH_SHORT(sht);
+ return sht;
+}
+
+// ----------------------------------------------------- //
+int ChunkUtils::swapInt(int inte)
+{
+ B3_SWITCH_INT(inte);
+ return inte;
+}
+
+// ----------------------------------------------------- //
+b3Long64 ChunkUtils::swapLong64(b3Long64 lng)
+{
+ B3_SWITCH_LONGINT(lng);
+ return lng;
+}
+
+// ----------------------------------------------------- //
+int ChunkUtils::getOffset(int flags)
+{
+ // if the file is saved in a
+ // different format, get the
+ // file's chunk size
+ int res = CHUNK_HEADER_LEN;
+
+ if (VOID_IS_8)
+ {
+ if (flags &FD_BITS_VARIES)
+ res = sizeof(bChunkPtr4);
+ }
+ else
+ {
+ if (flags &FD_BITS_VARIES)
+ res = sizeof(bChunkPtr8);
+ }
+ return res;
+}
+
+
+
+
+
+//eof
diff --git a/thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/b3Chunk.h b/thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/b3Chunk.h
new file mode 100644
index 0000000000..03ecb6b4fa
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/b3Chunk.h
@@ -0,0 +1,92 @@
+/*
+bParse
+Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com
+
+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 __BCHUNK_H__
+#define __BCHUNK_H__
+
+#if defined (_WIN32) && ! defined (__MINGW32__)
+ #define b3Long64 __int64
+#elif defined (__MINGW32__)
+ #include <stdint.h>
+ #define b3Long64 int64_t
+#else
+ #define b3Long64 long long
+#endif
+
+
+namespace bParse {
+
+
+ // ----------------------------------------------------- //
+ class bChunkPtr4
+ {
+ public:
+ bChunkPtr4(){}
+ int code;
+ int len;
+ union
+ {
+ int m_uniqueInt;
+ };
+ int dna_nr;
+ int nr;
+ };
+
+ // ----------------------------------------------------- //
+ class bChunkPtr8
+ {
+ public:
+ bChunkPtr8(){}
+ int code, len;
+ union
+ {
+ b3Long64 oldPrev;
+ int m_uniqueInts[2];
+ };
+ int dna_nr, nr;
+ };
+
+ // ----------------------------------------------------- //
+ class bChunkInd
+ {
+ public:
+ bChunkInd(){}
+ int code, len;
+ void *oldPtr;
+ int dna_nr, nr;
+ };
+
+
+ // ----------------------------------------------------- //
+ class ChunkUtils
+ {
+ public:
+
+ // file chunk offset
+ static int getOffset(int flags);
+
+ // endian utils
+ static short swapShort(short sht);
+ static int swapInt(int inte);
+ static b3Long64 swapLong64(b3Long64 lng);
+
+ };
+
+
+ const int CHUNK_HEADER_LEN = ((sizeof(bChunkInd)));
+ const bool VOID_IS_8 = ((sizeof(void*)==8));
+}
+
+#endif//__BCHUNK_H__
diff --git a/thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/b3Common.h b/thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/b3Common.h
new file mode 100644
index 0000000000..2792d84033
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/b3Common.h
@@ -0,0 +1,39 @@
+/*
+bParse
+Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com
+
+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 __BCOMMON_H__
+#define __BCOMMON_H__
+
+
+#include <assert.h>
+//#include "bLog.h"
+#include "Bullet3Common/b3AlignedObjectArray.h"
+#include "Bullet3Common/b3HashMap.h"
+
+namespace bParse {
+
+ class bMain;
+ class bFileData;
+ class bFile;
+ class bDNA;
+
+ // delete void* undefined
+ typedef struct bStructHandle {int unused;}bStructHandle;
+ typedef b3AlignedObjectArray<bStructHandle*> bListBasePtr;
+ typedef b3HashMap<b3HashPtr, bStructHandle*> bPtrMap;
+}
+
+
+#endif//__BCOMMON_H__
diff --git a/thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/b3DNA.cpp b/thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/b3DNA.cpp
new file mode 100644
index 0000000000..0fe5056922
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/b3DNA.cpp
@@ -0,0 +1,629 @@
+/*
+bParse
+Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com
+
+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 <assert.h>
+
+#include "b3DNA.h"
+#include "b3Chunk.h"
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+//this define will force traversal of structures, to check backward (and forward) compatibility
+//#define TEST_BACKWARD_FORWARD_COMPATIBILITY
+
+
+using namespace bParse;
+
+
+// ----------------------------------------------------- //
+bDNA::bDNA()
+ : mPtrLen(0)
+{
+ // --
+}
+
+// ----------------------------------------------------- //
+bDNA::~bDNA()
+{
+ // --
+}
+
+// ----------------------------------------------------- //
+bool bDNA::lessThan(bDNA *file)
+{
+ return ( m_Names.size() < file->m_Names.size());
+}
+
+// ----------------------------------------------------- //
+char *bDNA::getName(int ind)
+{
+ assert(ind <= (int)m_Names.size());
+ return m_Names[ind].m_name;
+}
+
+
+// ----------------------------------------------------- //
+char *bDNA::getType(int ind)
+{
+ assert(ind<= (int)mTypes.size());
+ return mTypes[ind];
+}
+
+
+// ----------------------------------------------------- //
+short *bDNA::getStruct(int ind)
+{
+ assert(ind <= (int)mStructs.size());
+ return mStructs[ind];
+}
+
+
+// ----------------------------------------------------- //
+short bDNA::getLength(int ind)
+{
+ assert(ind <= (int)mTlens.size());
+ return mTlens[ind];
+}
+
+
+// ----------------------------------------------------- //
+int bDNA::getReverseType(short type)
+{
+
+ int* intPtr = mStructReverse.find(type);
+ if (intPtr)
+ return *intPtr;
+
+ return -1;
+}
+
+// ----------------------------------------------------- //
+int bDNA::getReverseType(const char *type)
+{
+
+ b3HashString key(type);
+ int* valuePtr = mTypeLookup.find(key);
+ if (valuePtr)
+ return *valuePtr;
+
+ return -1;
+}
+
+// ----------------------------------------------------- //
+int bDNA::getNumStructs()
+{
+ return (int)mStructs.size();
+}
+
+// ----------------------------------------------------- //
+bool bDNA::flagNotEqual(int dna_nr)
+{
+ assert(dna_nr <= (int)mCMPFlags.size());
+ return mCMPFlags[dna_nr] == FDF_STRUCT_NEQU;
+}
+
+// ----------------------------------------------------- //
+bool bDNA::flagEqual(int dna_nr)
+{
+ assert(dna_nr <= (int)mCMPFlags.size());
+ int flag = mCMPFlags[dna_nr];
+ return flag == FDF_STRUCT_EQU;
+}
+
+// ----------------------------------------------------- //
+bool bDNA::flagNone(int dna_nr)
+{
+ assert(dna_nr <= (int)mCMPFlags.size());
+ return mCMPFlags[dna_nr] == FDF_NONE;
+}
+
+// ----------------------------------------------------- //
+int bDNA::getPointerSize()
+{
+ return mPtrLen;
+}
+
+// ----------------------------------------------------- //
+void bDNA::initRecurseCmpFlags(int iter)
+{
+ // iter is FDF_STRUCT_NEQU
+
+ short *oldStrc = mStructs[iter];
+ short type = oldStrc[0];
+
+ for (int i=0; i<(int)mStructs.size(); i++)
+ {
+ if (i != iter && mCMPFlags[i] == FDF_STRUCT_EQU )
+ {
+ short *curStruct = mStructs[i];
+ int eleLen = curStruct[1];
+ curStruct+=2;
+
+ for (int j=0; j<eleLen; j++, curStruct+=2)
+ {
+ if (curStruct[0] == type)
+ {
+ //char *name = m_Names[curStruct[1]].m_name;
+ //if (name[0] != '*')
+ if (m_Names[curStruct[1]].m_isPointer)
+ {
+ mCMPFlags[i] = FDF_STRUCT_NEQU;
+ initRecurseCmpFlags(i);
+ }
+ }
+ }
+ }
+ }
+}
+
+// ----------------------------------------------------- //
+void bDNA::initCmpFlags(bDNA *memDNA)
+{
+
+ // compare the file to memory
+ // this ptr should be the file data
+
+
+ assert(!(m_Names.size() == 0));// && "SDNA empty!");
+ mCMPFlags.resize(mStructs.size(), FDF_NONE);
+
+
+
+ int i;
+ for ( i=0; i<(int)mStructs.size(); i++)
+ {
+ short *oldStruct = mStructs[i];
+
+ int oldLookup = getReverseType(oldStruct[0]);
+ if (oldLookup == -1)
+ {
+ mCMPFlags[i] = FDF_NONE;
+ continue;
+ }
+ //char* typeName = mTypes[oldStruct[0]];
+
+//#define SLOW_FORWARD_COMPATIBLE 1
+#ifdef SLOW_FORWARD_COMPATIBLE
+ char* typeName = mTypes[oldLookup];
+ int newLookup = memDNA->getReverseType(typeName);
+ if (newLookup == -1)
+ {
+ mCMPFlags[i] = FDF_NONE;
+ continue;
+ }
+ short *curStruct = memDNA->mStructs[newLookup];
+#else
+ // memory for file
+
+ if (oldLookup < memDNA->mStructs.size())
+ {
+ short *curStruct = memDNA->mStructs[oldLookup];
+#endif
+
+
+
+ // rebuild...
+ mCMPFlags[i] = FDF_STRUCT_NEQU;
+
+#ifndef TEST_BACKWARD_FORWARD_COMPATIBILITY
+
+ if (curStruct[1] == oldStruct[1])
+ {
+ // type len same ...
+ if (mTlens[oldStruct[0]] == memDNA->mTlens[curStruct[0]])
+ {
+ bool isSame = true;
+ int elementLength = oldStruct[1];
+
+
+ curStruct+=2;
+ oldStruct+=2;
+
+
+ for (int j=0; j<elementLength; j++, curStruct+=2, oldStruct+=2)
+ {
+ // type the same
+ //const char* typeFileDNA = mTypes[oldStruct[0]];
+ //const char* typeMemDNA = mTypes[curStruct[0]];
+ if (strcmp(mTypes[oldStruct[0]], memDNA->mTypes[curStruct[0]])!=0)
+ {
+ isSame=false;
+ break;
+ }
+
+ // name the same
+ if (strcmp(m_Names[oldStruct[1]].m_name, memDNA->m_Names[curStruct[1]].m_name)!=0)
+ {
+ isSame=false;
+ break;
+ }
+ }
+ // flag valid ==
+ if (isSame)
+ mCMPFlags[i] = FDF_STRUCT_EQU;
+ }
+ }
+#endif
+ }
+ }
+
+
+
+
+
+ // recurse in
+ for ( i=0; i<(int)mStructs.size(); i++)
+ {
+ if (mCMPFlags[i] == FDF_STRUCT_NEQU)
+ initRecurseCmpFlags(i);
+ }
+}
+
+
+
+
+static int name_is_array(char* name, int* dim1, int* dim2) {
+ int len = strlen(name);
+ /*fprintf(stderr,"[%s]",name);*/
+ /*if (len >= 1) {
+ if (name[len-1] != ']')
+ return 1;
+ }
+ return 0;*/
+ char *bp;
+ int num;
+ if (dim1) {
+ *dim1 = 1;
+ }
+ if (dim2) {
+ *dim2 = 1;
+ }
+ bp = strchr(name, '[');
+ if (!bp) {
+ return 0;
+ }
+ num = 0;
+ while (++bp < name+len-1) {
+ const char c = *bp;
+ if (c == ']') {
+ break;
+ }
+ if (c <= '9' && c >= '0') {
+ num *= 10;
+ num += (c - '0');
+ } else {
+ printf("array parse error.\n");
+ return 0;
+ }
+ }
+ if (dim2) {
+ *dim2 = num;
+ }
+
+ /* find second dim, if any. */
+ bp = strchr(bp, '[');
+ if (!bp) {
+ return 1; /* at least we got the first dim. */
+ }
+ num = 0;
+ while (++bp < name+len-1) {
+ const char c = *bp;
+ if (c == ']') {
+ break;
+ }
+ if (c <= '9' && c >= '0') {
+ num *= 10;
+ num += (c - '0');
+ } else {
+ printf("array2 parse error.\n");
+ return 1;
+ }
+ }
+ if (dim1) {
+ if (dim2) {
+ *dim1 = *dim2;
+ *dim2 = num;
+ } else {
+ *dim1 = num;
+ }
+ }
+
+ return 1;
+}
+
+
+// ----------------------------------------------------- //
+void bDNA::init(char *data, int len, bool swap)
+{
+ int *intPtr=0;short *shtPtr=0;
+ char *cp = 0;int dataLen =0;
+ //long nr=0;
+ intPtr = (int*)data;
+
+ /*
+ SDNA (4 bytes) (magic number)
+ NAME (4 bytes)
+ <nr> (4 bytes) amount of names (int)
+ <string>
+ <string>
+ */
+
+ if (strncmp(data, "SDNA", 4)==0)
+ {
+ // skip ++ NAME
+ intPtr++; intPtr++;
+ }
+
+
+
+ // Parse names
+ if (swap)
+ {
+ *intPtr = ChunkUtils::swapInt(*intPtr);
+ }
+ dataLen = *intPtr;
+ intPtr++;
+
+ cp = (char*)intPtr;
+ int i;
+ for ( i=0; i<dataLen; i++)
+ {
+ bNameInfo info;
+ info.m_name = cp;
+ info.m_isPointer = (info.m_name[0] == '*') || (info.m_name[1] == '*');
+ name_is_array(info.m_name,&info.m_dim0,&info.m_dim1);
+ m_Names.push_back(info);
+ while (*cp)cp++;
+ cp++;
+ }
+
+
+ cp = b3AlignPointer(cp,4);
+
+
+ /*
+ TYPE (4 bytes)
+ <nr> amount of types (int)
+ <string>
+ <string>
+ */
+
+ intPtr = (int*)cp;
+ assert(strncmp(cp, "TYPE", 4)==0); intPtr++;
+
+ if (swap)
+ {
+ *intPtr = ChunkUtils::swapInt(*intPtr);
+ }
+ dataLen = *intPtr;
+ intPtr++;
+
+ cp = (char*)intPtr;
+ for ( i=0; i<dataLen; i++)
+ {
+ mTypes.push_back(cp);
+ while (*cp)cp++;
+ cp++;
+ }
+
+
+ cp = b3AlignPointer(cp,4);
+
+ /*
+ TLEN (4 bytes)
+ <len> (short) the lengths of types
+ <len>
+ */
+
+ // Parse type lens
+ intPtr = (int*)cp;
+ assert(strncmp(cp, "TLEN", 4)==0); intPtr++;
+
+ dataLen = (int)mTypes.size();
+
+ shtPtr = (short*)intPtr;
+ for ( i=0; i<dataLen; i++, shtPtr++)
+ {
+ if (swap)
+ shtPtr[0] = ChunkUtils::swapShort(shtPtr[0]);
+ mTlens.push_back(shtPtr[0]);
+ }
+
+ if (dataLen & 1) shtPtr++;
+
+ /*
+ STRC (4 bytes)
+ <nr> amount of structs (int)
+ <typenr>
+ <nr_of_elems>
+ <typenr>
+ <namenr>
+ <typenr>
+ <namenr>
+ */
+
+ intPtr = (int*)shtPtr;
+ cp = (char*)intPtr;
+ assert(strncmp(cp, "STRC", 4)==0); intPtr++;
+
+ if (swap)
+ {
+ *intPtr = ChunkUtils::swapInt(*intPtr);
+ }
+ dataLen = *intPtr;
+ intPtr++;
+
+
+ shtPtr = (short*)intPtr;
+ for ( i=0; i<dataLen; i++)
+ {
+ mStructs.push_back (shtPtr);
+ if (swap)
+ {
+ shtPtr[0]= ChunkUtils::swapShort(shtPtr[0]);
+ shtPtr[1]= ChunkUtils::swapShort(shtPtr[1]);
+
+ int len = shtPtr[1];
+ shtPtr+= 2;
+
+ for (int a=0; a<len; a++, shtPtr+=2)
+ {
+ shtPtr[0]= ChunkUtils::swapShort(shtPtr[0]);
+ shtPtr[1]= ChunkUtils::swapShort(shtPtr[1]);
+ }
+ }
+ else
+ shtPtr+= (2*shtPtr[1])+2;
+ }
+
+
+ // build reverse lookups
+ for ( i=0; i<(int)mStructs.size(); i++)
+ {
+ short *strc = mStructs.at(i);
+ if (!mPtrLen && strcmp(mTypes[strc[0]],"ListBase")==0)
+ {
+ mPtrLen = mTlens[strc[0]]/2;
+ }
+
+ mStructReverse.insert(strc[0], i);
+ mTypeLookup.insert(b3HashString(mTypes[strc[0]]),i);
+ }
+}
+
+
+// ----------------------------------------------------- //
+int bDNA::getArraySize(char* string)
+{
+ int ret = 1;
+ int len = strlen(string);
+
+
+ char* next = 0;
+ for (int i=0; i<len; i++)
+ {
+ char c = string[i];
+
+ if (c == '[')
+ next = &string[i+1];
+ else if (c==']')
+ if (next)
+ ret *= atoi(next);
+ }
+
+// print (string << ' ' << ret);
+ return ret;
+}
+
+
+void bDNA::dumpTypeDefinitions()
+{
+ int i;
+
+ int numTypes = mTypes.size();
+
+ for (i=0;i<numTypes;i++)
+ {
+
+ }
+
+ for ( i=0; i<(int)mStructs.size(); i++)
+ {
+ int totalBytes=0;
+ short *oldStruct = mStructs[i];
+
+ int oldLookup = getReverseType(oldStruct[0]);
+ if (oldLookup == -1)
+ {
+ mCMPFlags[i] = FDF_NONE;
+ continue;
+ }
+
+ short* newStruct = mStructs[oldLookup];
+ char* typeName = mTypes[newStruct[0]];
+ printf("%3d: %s ",i,typeName);
+
+ //char *name = mNames[oldStruct[1]];
+ int len = oldStruct[1];
+ printf(" (%d fields) ",len);
+ oldStruct+=2;
+
+ printf("{");
+ int j;
+ for (j=0; j<len; ++j,oldStruct+=2) {
+ const char* name = m_Names[oldStruct[1]].m_name;
+ printf("%s %s", mTypes[oldStruct[0]],name);
+ int elemNumBytes= 0;
+ int arrayDimensions = getArraySizeNew(oldStruct[1]);
+
+ if (m_Names[oldStruct[1]].m_isPointer)
+ {
+ elemNumBytes = VOID_IS_8 ? 8 : 4;
+ } else
+ {
+ elemNumBytes = getLength(oldStruct[0]);
+ }
+ printf(" /* %d bytes */",elemNumBytes*arrayDimensions);
+
+ if (j == len-1) {
+ printf(";}");
+ } else {
+ printf("; ");
+ }
+ totalBytes+=elemNumBytes*arrayDimensions;
+ }
+ printf("\ntotalBytes=%d\n\n",totalBytes);
+
+ }
+
+
+
+#if 0
+ /* dump out display of types and their sizes */
+ for (i=0; i<bf->types_count; ++i) {
+ /* if (!bf->types[i].is_struct)*/
+ {
+ printf("%3d: sizeof(%s%s)=%d",
+ i,
+ bf->types[i].is_struct ? "struct " : "atomic ",
+ bf->types[i].name, bf->types[i].size);
+ if (bf->types[i].is_struct) {
+ int j;
+ printf(", %d fields: { ", bf->types[i].fieldtypes_count);
+ for (j=0; j<bf->types[i].fieldtypes_count; ++j) {
+ printf("%s %s",
+ bf->types[bf->types[i].fieldtypes[j]].name,
+ bf->names[bf->types[i].fieldnames[j]]);
+ if (j == bf->types[i].fieldtypes_count-1) {
+ printf(";}");
+ } else {
+ printf("; ");
+ }
+ }
+ }
+ printf("\n\n");
+
+ }
+ }
+#endif
+
+}
+
+
+
+
+//eof
+
+
diff --git a/thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/b3DNA.h b/thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/b3DNA.h
new file mode 100644
index 0000000000..6e60087cce
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/b3DNA.h
@@ -0,0 +1,110 @@
+/*
+bParse
+Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com
+
+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 __BDNA_H__
+#define __BDNA_H__
+
+
+#include "b3Common.h"
+
+namespace bParse {
+
+ struct bNameInfo
+ {
+ char* m_name;
+ bool m_isPointer;
+ int m_dim0;
+ int m_dim1;
+ };
+
+ class bDNA
+ {
+ public:
+ bDNA();
+ ~bDNA();
+
+ void init(char *data, int len, bool swap=false);
+
+ int getArraySize(char* str);
+ int getArraySizeNew(short name)
+ {
+ const bNameInfo& nameInfo = m_Names[name];
+ return nameInfo.m_dim0*nameInfo.m_dim1;
+ }
+ int getElementSize(short type, short name)
+ {
+ const bNameInfo& nameInfo = m_Names[name];
+ int size = nameInfo.m_isPointer ? mPtrLen*nameInfo.m_dim0*nameInfo.m_dim1 : mTlens[type]*nameInfo.m_dim0*nameInfo.m_dim1;
+ return size;
+ }
+
+ int getNumNames() const
+ {
+ return m_Names.size();
+ }
+
+ char *getName(int ind);
+ char *getType(int ind);
+ short *getStruct(int ind);
+ short getLength(int ind);
+ int getReverseType(short type);
+ int getReverseType(const char *type);
+
+
+ int getNumStructs();
+
+ //
+ bool lessThan(bDNA* other);
+
+ void initCmpFlags(bDNA *memDNA);
+ bool flagNotEqual(int dna_nr);
+ bool flagEqual(int dna_nr);
+ bool flagNone(int dna_nr);
+
+
+ int getPointerSize();
+
+ void dumpTypeDefinitions();
+
+
+ private:
+ enum FileDNAFlags
+ {
+ FDF_NONE=0,
+ FDF_STRUCT_NEQU,
+ FDF_STRUCT_EQU
+ };
+
+ void initRecurseCmpFlags(int i);
+
+ b3AlignedObjectArray<int> mCMPFlags;
+
+ b3AlignedObjectArray<bNameInfo> m_Names;
+ b3AlignedObjectArray<char*> mTypes;
+ b3AlignedObjectArray<short*> mStructs;
+ b3AlignedObjectArray<short> mTlens;
+ b3HashMap<b3HashInt, int> mStructReverse;
+ b3HashMap<b3HashString,int> mTypeLookup;
+
+ int mPtrLen;
+
+
+
+
+ };
+}
+
+
+#endif//__BDNA_H__
diff --git a/thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/b3Defines.h b/thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/b3Defines.h
new file mode 100644
index 0000000000..8f28d3c441
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/b3Defines.h
@@ -0,0 +1,136 @@
+/* Copyright (C) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com
+*
+* 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 __B_DEFINES_H__
+#define __B_DEFINES_H__
+
+
+// MISC defines, see BKE_global.h, BKE_utildefines.h
+#define B3_SIZEOFBLENDERHEADER 12
+
+
+// ------------------------------------------------------------
+#if defined(__sgi) || defined (__sparc) || defined (__sparc__) || defined (__PPC__) || defined (__ppc__) || defined (__BIG_ENDIAN__)
+# define B3_MAKE_ID(a,b,c,d) ( (int)(a)<<24 | (int)(b)<<16 | (c)<<8 | (d) )
+#else
+# define B3_MAKE_ID(a,b,c,d) ( (int)(d)<<24 | (int)(c)<<16 | (b)<<8 | (a) )
+#endif
+
+
+// ------------------------------------------------------------
+#if defined(__sgi) || defined(__sparc) || defined(__sparc__) || defined (__PPC__) || defined (__ppc__) || defined (__BIG_ENDIAN__)
+# define B3_MAKE_ID2(c, d) ( (c)<<8 | (d) )
+#else
+# define B3_MAKE_ID2(c, d) ( (d)<<8 | (c) )
+#endif
+
+// ------------------------------------------------------------
+#define B3_ID_SCE B3_MAKE_ID2('S', 'C')
+#define B3_ID_LI B3_MAKE_ID2('L', 'I')
+#define B3_ID_OB B3_MAKE_ID2('O', 'B')
+#define B3_ID_ME B3_MAKE_ID2('M', 'E')
+#define B3_ID_CU B3_MAKE_ID2('C', 'U')
+#define B3_ID_MB B3_MAKE_ID2('M', 'B')
+#define B3_ID_MA B3_MAKE_ID2('M', 'A')
+#define B3_ID_TE B3_MAKE_ID2('T', 'E')
+#define B3_ID_IM B3_MAKE_ID2('I', 'M')
+#define B3_ID_IK B3_MAKE_ID2('I', 'K')
+#define B3_ID_WV B3_MAKE_ID2('W', 'V')
+#define B3_ID_LT B3_MAKE_ID2('L', 'T')
+#define B3_ID_SE B3_MAKE_ID2('S', 'E')
+#define B3_ID_LF B3_MAKE_ID2('L', 'F')
+#define B3_ID_LA B3_MAKE_ID2('L', 'A')
+#define B3_ID_CA B3_MAKE_ID2('C', 'A')
+#define B3_ID_IP B3_MAKE_ID2('I', 'P')
+#define B3_ID_KE B3_MAKE_ID2('K', 'E')
+#define B3_ID_WO B3_MAKE_ID2('W', 'O')
+#define B3_ID_SCR B3_MAKE_ID2('S', 'R')
+#define B3_ID_VF B3_MAKE_ID2('V', 'F')
+#define B3_ID_TXT B3_MAKE_ID2('T', 'X')
+#define B3_ID_SO B3_MAKE_ID2('S', 'O')
+#define B3_ID_SAMPLE B3_MAKE_ID2('S', 'A')
+#define B3_ID_GR B3_MAKE_ID2('G', 'R')
+#define B3_ID_ID B3_MAKE_ID2('I', 'D')
+#define B3_ID_AR B3_MAKE_ID2('A', 'R')
+#define B3_ID_AC B3_MAKE_ID2('A', 'C')
+#define B3_ID_SCRIPT B3_MAKE_ID2('P', 'Y')
+#define B3_ID_FLUIDSIM B3_MAKE_ID2('F', 'S')
+#define B3_ID_NT B3_MAKE_ID2('N', 'T')
+#define B3_ID_BR B3_MAKE_ID2('B', 'R')
+
+
+#define B3_ID_SEQ B3_MAKE_ID2('S', 'Q')
+#define B3_ID_CO B3_MAKE_ID2('C', 'O')
+#define B3_ID_PO B3_MAKE_ID2('A', 'C')
+#define B3_ID_NLA B3_MAKE_ID2('N', 'L')
+
+#define B3_ID_VS B3_MAKE_ID2('V', 'S')
+#define B3_ID_VN B3_MAKE_ID2('V', 'N')
+
+
+// ------------------------------------------------------------
+#define B3_FORM B3_MAKE_ID('F','O','R','M')
+#define B3_DDG1 B3_MAKE_ID('3','D','G','1')
+#define B3_DDG2 B3_MAKE_ID('3','D','G','2')
+#define B3_DDG3 B3_MAKE_ID('3','D','G','3')
+#define B3_DDG4 B3_MAKE_ID('3','D','G','4')
+#define B3_GOUR B3_MAKE_ID('G','O','U','R')
+#define B3_BLEN B3_MAKE_ID('B','L','E','N')
+#define B3_DER_ B3_MAKE_ID('D','E','R','_')
+#define B3_V100 B3_MAKE_ID('V','1','0','0')
+#define B3_DATA B3_MAKE_ID('D','A','T','A')
+#define B3_GLOB B3_MAKE_ID('G','L','O','B')
+#define B3_IMAG B3_MAKE_ID('I','M','A','G')
+#define B3_TEST B3_MAKE_ID('T','E','S','T')
+#define B3_USER B3_MAKE_ID('U','S','E','R')
+
+
+// ------------------------------------------------------------
+#define B3_DNA1 B3_MAKE_ID('D','N','A','1')
+#define B3_REND B3_MAKE_ID('R','E','N','D')
+#define B3_ENDB B3_MAKE_ID('E','N','D','B')
+#define B3_NAME B3_MAKE_ID('N','A','M','E')
+#define B3_SDNA B3_MAKE_ID('S','D','N','A')
+#define B3_TYPE B3_MAKE_ID('T','Y','P','E')
+#define B3_TLEN B3_MAKE_ID('T','L','E','N')
+#define B3_STRC B3_MAKE_ID('S','T','R','C')
+
+
+// ------------------------------------------------------------
+#define B3_SWITCH_INT(a) { \
+ char s_i, *p_i; \
+ p_i= (char *)&(a); \
+ s_i=p_i[0]; p_i[0]=p_i[3]; p_i[3]=s_i; \
+ s_i=p_i[1]; p_i[1]=p_i[2]; p_i[2]=s_i; }
+
+// ------------------------------------------------------------
+#define B3_SWITCH_SHORT(a) { \
+ char s_i, *p_i; \
+ p_i= (char *)&(a); \
+ s_i=p_i[0]; p_i[0]=p_i[1]; p_i[1]=s_i; }
+
+// ------------------------------------------------------------
+#define B3_SWITCH_LONGINT(a) { \
+ char s_i, *p_i; \
+ p_i= (char *)&(a); \
+ s_i=p_i[0]; p_i[0]=p_i[7]; p_i[7]=s_i; \
+ s_i=p_i[1]; p_i[1]=p_i[6]; p_i[6]=s_i; \
+ s_i=p_i[2]; p_i[2]=p_i[5]; p_i[5]=s_i; \
+ s_i=p_i[3]; p_i[3]=p_i[4]; p_i[4]=s_i; }
+
+#endif//__B_DEFINES_H__
diff --git a/thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/b3File.cpp b/thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/b3File.cpp
new file mode 100644
index 0000000000..432f7fc2b4
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/b3File.cpp
@@ -0,0 +1,1739 @@
+/*
+bParse
+Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com
+
+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 "b3File.h"
+#include "b3Common.h"
+#include "b3Chunk.h"
+#include "b3DNA.h"
+#include <math.h>
+#include <string.h>
+#include <stdlib.h>
+#include "b3Defines.h"
+#include "Bullet3Serialize/Bullet2FileLoader/b3Serializer.h"
+#include "Bullet3Common/b3AlignedAllocator.h"
+#include "Bullet3Common/b3MinMax.h"
+
+#define B3_SIZEOFBLENDERHEADER 12
+#define MAX_ARRAY_LENGTH 512
+using namespace bParse;
+#define MAX_STRLEN 1024
+
+const char* getCleanName(const char* memName, char* buffer)
+{
+ int slen = strlen(memName);
+ assert(slen<MAX_STRLEN);
+ slen=b3Min(slen,MAX_STRLEN);
+ for (int i=0;i<slen;i++)
+ {
+ if (memName[i]==']'||memName[i]=='[')
+ {
+ buffer[i] = 0;//'_';
+ } else
+ {
+ buffer[i] = memName[i];
+ }
+ }
+ buffer[slen]=0;
+ return buffer;
+}
+
+
+
+// ----------------------------------------------------- //
+bFile::bFile(const char *filename, const char headerString[7])
+ : mOwnsBuffer(true),
+ mFileBuffer(0),
+ mFileLen(0),
+ mVersion(0),
+ mDataStart(0),
+ mFileDNA(0),
+ mMemoryDNA(0),
+ mFlags(FD_INVALID)
+{
+ for (int i=0;i<7;i++)
+ {
+ m_headerString[i] = headerString[i];
+ }
+
+ FILE *fp = fopen(filename, "rb");
+ if (fp)
+ {
+ fseek(fp, 0L, SEEK_END);
+ mFileLen = ftell(fp);
+ fseek(fp, 0L, SEEK_SET);
+
+ mFileBuffer = (char*)malloc(mFileLen+1);
+ int bytesRead;
+ bytesRead = fread(mFileBuffer, mFileLen, 1, fp);
+
+ fclose(fp);
+
+ //
+ parseHeader();
+
+ }
+}
+
+// ----------------------------------------------------- //
+bFile::bFile( char *memoryBuffer, int len, const char headerString[7])
+: mOwnsBuffer(false),
+ mFileBuffer(0),
+ mFileLen(0),
+ mVersion(0),
+ mDataStart(0),
+ mFileDNA(0),
+ mMemoryDNA(0),
+ mFlags(FD_INVALID)
+{
+ for (int i=0;i<7;i++)
+ {
+ m_headerString[i] = headerString[i];
+ }
+ mFileBuffer = memoryBuffer;
+ mFileLen = len;
+
+ parseHeader();
+
+}
+
+
+// ----------------------------------------------------- //
+bFile::~bFile()
+{
+ if (mOwnsBuffer && mFileBuffer)
+ {
+ free(mFileBuffer);
+ mFileBuffer = 0;
+ }
+
+
+ delete mMemoryDNA;
+ delete mFileDNA;
+}
+
+
+
+
+
+// ----------------------------------------------------- //
+void bFile::parseHeader()
+{
+ if (!mFileLen || !mFileBuffer)
+ return;
+
+ char *blenderBuf = mFileBuffer;
+ char header[B3_SIZEOFBLENDERHEADER+1] ;
+ memcpy(header, blenderBuf, B3_SIZEOFBLENDERHEADER);
+ header[B3_SIZEOFBLENDERHEADER]='\0';
+
+ if (strncmp(header, m_headerString, 6)!=0)
+ {
+ memcpy(header, m_headerString, B3_SIZEOFBLENDERHEADER);
+ return;
+ }
+
+ if (header[6] == 'd')
+ {
+ mFlags |= FD_DOUBLE_PRECISION;
+ }
+
+ char *ver = header+9;
+ mVersion = atoi(ver);
+ if (mVersion <= 241)
+ {
+ //printf("Warning, %d not fully tested : <= 242\n", mVersion);
+ }
+
+ int littleEndian= 1;
+ littleEndian= ((char*)&littleEndian)[0];
+
+ // swap ptr sizes...
+ if (header[7]=='-')
+ {
+ mFlags |= FD_FILE_64;
+ if (!VOID_IS_8)
+ mFlags |= FD_BITS_VARIES;
+ }
+ else if (VOID_IS_8) mFlags |= FD_BITS_VARIES;
+
+ // swap endian...
+ if (header[8]=='V')
+ {
+ if (littleEndian ==1)
+ mFlags |= FD_ENDIAN_SWAP;
+ }
+ else
+ if (littleEndian==0)
+ mFlags |= FD_ENDIAN_SWAP;
+
+
+ mFlags |= FD_OK;
+}
+
+// ----------------------------------------------------- //
+bool bFile::ok()
+{
+ return (mFlags &FD_OK)!=0;
+}
+
+// ----------------------------------------------------- //
+void bFile::parseInternal(int verboseMode, char* memDna,int memDnaLength)
+{
+ if ( (mFlags &FD_OK) ==0)
+ return;
+
+ char *blenderData = mFileBuffer;
+ bChunkInd dna;
+ dna.oldPtr = 0;
+
+ char *tempBuffer = blenderData;
+ for (int i=0; i<mFileLen; i++)
+ {
+ // looking for the data's starting position
+ // and the start of SDNA decls
+
+ if (!mDataStart && strncmp(tempBuffer, "REND", 4)==0)
+ mDataStart = i;
+
+ if (strncmp(tempBuffer, "DNA1", 4)==0)
+ {
+ // read the DNA1 block and extract SDNA
+ if (getNextBlock(&dna, tempBuffer, mFlags) > 0)
+ {
+ if (strncmp((tempBuffer + ChunkUtils::getOffset(mFlags)), "SDNANAME", 8) ==0)
+ dna.oldPtr = (tempBuffer + ChunkUtils::getOffset(mFlags));
+ else dna.oldPtr = 0;
+ }
+ else dna.oldPtr = 0;
+ }
+ // Some Bullet files are missing the DNA1 block
+ // In Blender it's DNA1 + ChunkUtils::getOffset() + SDNA + NAME
+ // In Bullet tests its SDNA + NAME
+ else if (strncmp(tempBuffer, "SDNANAME", 8) ==0)
+ {
+ dna.oldPtr = blenderData + i;
+ dna.len = mFileLen-i;
+
+ // Also no REND block, so exit now.
+ if (mVersion==276) break;
+ }
+
+ if (mDataStart && dna.oldPtr) break;
+ tempBuffer++;
+ }
+ if (!dna.oldPtr || !dna.len)
+ {
+ //printf("Failed to find DNA1+SDNA pair\n");
+ mFlags &= ~FD_OK;
+ return;
+ }
+
+
+ mFileDNA = new bDNA();
+
+
+ ///mFileDNA->init will convert part of DNA file endianness to current CPU endianness if necessary
+ mFileDNA->init((char*)dna.oldPtr, dna.len, (mFlags & FD_ENDIAN_SWAP)!=0);
+
+
+ if (mVersion==276)
+ {
+ int i;
+ for (i=0;i<mFileDNA->getNumNames();i++)
+ {
+ if (strcmp(mFileDNA->getName(i),"int")==0)
+ {
+ mFlags |= FD_BROKEN_DNA;
+ }
+ }
+ if ((mFlags&FD_BROKEN_DNA)!=0)
+ {
+ //printf("warning: fixing some broken DNA version\n");
+ }
+ }
+
+
+
+ if (verboseMode & FD_VERBOSE_DUMP_DNA_TYPE_DEFINITIONS)
+ mFileDNA->dumpTypeDefinitions();
+
+ mMemoryDNA = new bDNA();
+ int littleEndian= 1;
+ littleEndian= ((char*)&littleEndian)[0];
+
+ mMemoryDNA->init(memDna,memDnaLength,littleEndian==0);
+
+
+
+
+ ///@todo we need a better version check, add version/sub version info from FileGlobal into memory DNA/header files
+ if (mMemoryDNA->getNumNames() != mFileDNA->getNumNames())
+ {
+ mFlags |= FD_VERSION_VARIES;
+ //printf ("Warning, file DNA is different than built in, performance is reduced. Best to re-export file with a matching version/platform");
+ }
+
+ // as long as it kept up to date it will be ok!!
+ if (mMemoryDNA->lessThan(mFileDNA))
+ {
+ //printf ("Warning, file DNA is newer than built in.");
+ }
+
+
+ mFileDNA->initCmpFlags(mMemoryDNA);
+
+ parseData();
+
+ resolvePointers(verboseMode);
+
+ updateOldPointers();
+
+
+}
+
+
+
+// ----------------------------------------------------- //
+void bFile::swap(char *head, bChunkInd& dataChunk, bool ignoreEndianFlag)
+{
+ char *data = head;
+ short *strc = mFileDNA->getStruct(dataChunk.dna_nr);
+
+
+
+ const char s[] = "SoftBodyMaterialData";
+ int szs = sizeof(s);
+ if (strncmp((char*)&dataChunk.code,"ARAY",4)==0)
+ {
+ short *oldStruct = mFileDNA->getStruct(dataChunk.dna_nr);
+ char *oldType = mFileDNA->getType(oldStruct[0]);
+ if (strncmp(oldType,s,szs)==0)
+ {
+ return;
+ }
+ }
+
+
+ int len = mFileDNA->getLength(strc[0]);
+
+ for (int i=0; i<dataChunk.nr; i++)
+ {
+ swapStruct(dataChunk.dna_nr, data,ignoreEndianFlag);
+ data+=len;
+ }
+}
+
+void bFile::swapLen(char *dataPtr)
+{
+ const bool VOID_IS_8 = ((sizeof(void*)==8));
+ if (VOID_IS_8)
+ {
+ if (mFlags &FD_BITS_VARIES)
+ {
+ bChunkPtr4*c = (bChunkPtr4*) dataPtr;
+ if ((c->code & 0xFFFF)==0)
+ c->code >>=16;
+ B3_SWITCH_INT(c->len);
+ B3_SWITCH_INT(c->dna_nr);
+ B3_SWITCH_INT(c->nr);
+ } else
+ {
+ bChunkPtr8* c = (bChunkPtr8*) dataPtr;
+ if ((c->code & 0xFFFF)==0)
+ c->code >>=16;
+ B3_SWITCH_INT(c->len);
+ B3_SWITCH_INT(c->dna_nr);
+ B3_SWITCH_INT(c->nr);
+
+ }
+ } else
+ {
+ if (mFlags &FD_BITS_VARIES)
+ {
+ bChunkPtr8*c = (bChunkPtr8*) dataPtr;
+ if ((c->code & 0xFFFF)==0)
+ c->code >>=16;
+ B3_SWITCH_INT(c->len);
+ B3_SWITCH_INT(c->dna_nr);
+ B3_SWITCH_INT(c->nr);
+
+ } else
+ {
+ bChunkPtr4* c = (bChunkPtr4*) dataPtr;
+ if ((c->code & 0xFFFF)==0)
+ c->code >>=16;
+ B3_SWITCH_INT(c->len);
+
+ B3_SWITCH_INT(c->dna_nr);
+ B3_SWITCH_INT(c->nr);
+
+ }
+ }
+
+}
+
+
+void bFile::swapDNA(char* ptr)
+{
+ bool swap = ((mFlags & FD_ENDIAN_SWAP)!=0);
+
+ char* data = &ptr[20];
+// void bDNA::init(char *data, int len, bool swap)
+ int *intPtr=0;short *shtPtr=0;
+ char *cp = 0;int dataLen =0;
+ //long nr=0;
+ intPtr = (int*)data;
+
+ /*
+ SDNA (4 bytes) (magic number)
+ NAME (4 bytes)
+ <nr> (4 bytes) amount of names (int)
+ <string>
+ <string>
+ */
+
+ if (strncmp(data, "SDNA", 4)==0)
+ {
+ // skip ++ NAME
+ intPtr++; intPtr++;
+ }
+
+
+
+ // Parse names
+ if (swap)
+ dataLen = ChunkUtils::swapInt(*intPtr);
+ else
+ dataLen = *intPtr;
+
+ *intPtr = ChunkUtils::swapInt(*intPtr);
+ intPtr++;
+
+ cp = (char*)intPtr;
+ int i;
+ for ( i=0; i<dataLen; i++)
+ {
+ while (*cp)cp++;
+ cp++;
+ }
+
+
+ cp = b3AlignPointer(cp,4);
+
+ /*
+ TYPE (4 bytes)
+ <nr> amount of types (int)
+ <string>
+ <string>
+ */
+
+ intPtr = (int*)cp;
+ assert(strncmp(cp, "TYPE", 4)==0); intPtr++;
+
+ if (swap)
+ dataLen = ChunkUtils::swapInt(*intPtr);
+ else
+ dataLen = *intPtr;
+
+ *intPtr = ChunkUtils::swapInt(*intPtr);
+
+ intPtr++;
+
+ cp = (char*)intPtr;
+ for ( i=0; i<dataLen; i++)
+ {
+ while (*cp)cp++;
+ cp++;
+ }
+
+ cp = b3AlignPointer(cp,4);
+
+ /*
+ TLEN (4 bytes)
+ <len> (short) the lengths of types
+ <len>
+ */
+
+ // Parse type lens
+ intPtr = (int*)cp;
+ assert(strncmp(cp, "TLEN", 4)==0); intPtr++;
+
+
+ shtPtr = (short*)intPtr;
+ for ( i=0; i<dataLen; i++, shtPtr++)
+ {
+ //??????if (swap)
+ shtPtr[0] = ChunkUtils::swapShort(shtPtr[0]);
+ }
+
+ if (dataLen & 1)
+ shtPtr++;
+
+ /*
+ STRC (4 bytes)
+ <nr> amount of structs (int)
+ <typenr>
+ <nr_of_elems>
+ <typenr>
+ <namenr>
+ <typenr>
+ <namenr>
+ */
+
+ intPtr = (int*)shtPtr;
+ cp = (char*)intPtr;
+ assert(strncmp(cp, "STRC", 4)==0);
+ intPtr++;
+
+ if (swap)
+ dataLen = ChunkUtils::swapInt(*intPtr);
+ else
+ dataLen = *intPtr;
+
+ *intPtr = ChunkUtils::swapInt(*intPtr);
+
+ intPtr++;
+
+
+ shtPtr = (short*)intPtr;
+ for ( i=0; i<dataLen; i++)
+ {
+
+ //if (swap)
+ {
+ int len = shtPtr[1];
+
+ shtPtr[0]= ChunkUtils::swapShort(shtPtr[0]);
+ shtPtr[1]= ChunkUtils::swapShort(shtPtr[1]);
+
+ shtPtr+= 2;
+
+ for (int a=0; a<len; a++, shtPtr+=2)
+ {
+ shtPtr[0]= ChunkUtils::swapShort(shtPtr[0]);
+ shtPtr[1]= ChunkUtils::swapShort(shtPtr[1]);
+ }
+ }
+// else
+// shtPtr+= (2*shtPtr[1])+2;
+ }
+
+}
+
+void bFile::writeFile(const char* fileName)
+{
+ FILE* f = fopen(fileName,"wb");
+ fwrite(mFileBuffer,1,mFileLen,f);
+ fclose(f);
+}
+
+void bFile::preSwap()
+{
+
+ //const bool brokenDNA = (mFlags&FD_BROKEN_DNA)!=0;
+ //FD_ENDIAN_SWAP
+ //byte 8 determines the endianness of the file, little (v) versus big (V)
+ int littleEndian= 1;
+ littleEndian= ((char*)&littleEndian)[0];
+
+
+ if (mFileBuffer[8]=='V')
+ {
+ mFileBuffer[8]='v';
+ }
+ else
+ {
+ mFileBuffer[8]='V';
+ }
+
+
+
+
+
+
+ mDataStart = 12;
+
+ char *dataPtr = mFileBuffer+mDataStart;
+
+ bChunkInd dataChunk;
+ dataChunk.code = 0;
+ bool ignoreEndianFlag = true;
+
+ //we always want to swap here
+
+ int seek = getNextBlock(&dataChunk, dataPtr, mFlags);
+ //dataPtr += ChunkUtils::getOffset(mFlags);
+ char *dataPtrHead = 0;
+
+ while (1)
+ {
+ // one behind
+ if (dataChunk.code == B3_SDNA || dataChunk.code==B3_DNA1 || dataChunk.code == B3_TYPE || dataChunk.code == B3_TLEN || dataChunk.code==B3_STRC)
+ {
+
+ swapDNA(dataPtr);
+ break;
+ } else
+ {
+ //if (dataChunk.code == DNA1) break;
+ dataPtrHead = dataPtr+ChunkUtils::getOffset(mFlags);
+
+ swapLen(dataPtr);
+ if (dataChunk.dna_nr>=0)
+ {
+ swap(dataPtrHead, dataChunk,ignoreEndianFlag);
+ } else
+ {
+ //printf("unknown chunk\n");
+ }
+ }
+
+ // next please!
+ dataPtr += seek;
+
+ seek = getNextBlock(&dataChunk, dataPtr, mFlags);
+ if (seek < 0)
+ break;
+ }
+
+ if (mFlags & FD_ENDIAN_SWAP)
+ {
+ mFlags &= ~FD_ENDIAN_SWAP;
+ } else
+ {
+ mFlags |= FD_ENDIAN_SWAP;
+ }
+
+
+
+}
+
+
+// ----------------------------------------------------- //
+char* bFile::readStruct(char *head, bChunkInd& dataChunk)
+{
+ bool ignoreEndianFlag = false;
+
+ if (mFlags & FD_ENDIAN_SWAP)
+ swap(head, dataChunk, ignoreEndianFlag);
+
+
+
+ if (!mFileDNA->flagEqual(dataChunk.dna_nr))
+ {
+ // Ouch! need to rebuild the struct
+ short *oldStruct,*curStruct;
+ char *oldType, *newType;
+ int oldLen, curLen, reverseOld;
+
+
+ oldStruct = mFileDNA->getStruct(dataChunk.dna_nr);
+ oldType = mFileDNA->getType(oldStruct[0]);
+
+ oldLen = mFileDNA->getLength(oldStruct[0]);
+
+ if ((mFlags&FD_BROKEN_DNA)!=0)
+ {
+ if ((strcmp(oldType,"b3QuantizedBvhNodeData")==0)&&oldLen==20)
+ {
+ return 0;
+ }
+ if ((strcmp(oldType,"b3ShortIntIndexData")==0))
+ {
+ int allocLen = 2;
+ char *dataAlloc = new char[(dataChunk.nr*allocLen)+1];
+ memset(dataAlloc, 0, (dataChunk.nr*allocLen)+1);
+ short* dest = (short*) dataAlloc;
+ const short* src = (short*) head;
+ for (int i=0;i<dataChunk.nr;i++)
+ {
+ dest[i] = src[i];
+ if (mFlags &FD_ENDIAN_SWAP)
+ {
+ B3_SWITCH_SHORT(dest[i]);
+ }
+ }
+ addDataBlock(dataAlloc);
+ return dataAlloc;
+ }
+ }
+
+
+
+ ///don't try to convert Link block data, just memcpy it. Other data can be converted.
+ if (strcmp("Link",oldType)!=0)
+ {
+ reverseOld = mMemoryDNA->getReverseType(oldType);
+
+ if ((reverseOld!=-1))
+ {
+ // make sure it's here
+ //assert(reverseOld!= -1 && "getReverseType() returned -1, struct required!");
+
+ //
+ curStruct = mMemoryDNA->getStruct(reverseOld);
+ newType = mMemoryDNA->getType(curStruct[0]);
+ curLen = mMemoryDNA->getLength(curStruct[0]);
+
+
+
+ // make sure it's the same
+ assert((strcmp(oldType, newType)==0) && "internal error, struct mismatch!");
+
+
+ // numBlocks * length
+
+ int allocLen = (curLen);
+ char *dataAlloc = new char[(dataChunk.nr*allocLen)+1];
+ memset(dataAlloc, 0, (dataChunk.nr*allocLen));
+
+ // track allocated
+ addDataBlock(dataAlloc);
+
+ char *cur = dataAlloc;
+ char *old = head;
+ for (int block=0; block<dataChunk.nr; block++)
+ {
+ bool fixupPointers = true;
+ parseStruct(cur, old, dataChunk.dna_nr, reverseOld, fixupPointers);
+ mLibPointers.insert(old,(bStructHandle*)cur);
+
+ cur += curLen;
+ old += oldLen;
+ }
+ return dataAlloc;
+ }
+ } else
+ {
+ //printf("Link found\n");
+ }
+ } else
+ {
+//#define DEBUG_EQUAL_STRUCTS
+#ifdef DEBUG_EQUAL_STRUCTS
+ short *oldStruct;
+ char *oldType;
+ oldStruct = mFileDNA->getStruct(dataChunk.dna_nr);
+ oldType = mFileDNA->getType(oldStruct[0]);
+ printf("%s equal structure, just memcpy\n",oldType);
+#endif //
+ }
+
+
+ char *dataAlloc = new char[(dataChunk.len)+1];
+ memset(dataAlloc, 0, dataChunk.len+1);
+
+
+ // track allocated
+ addDataBlock(dataAlloc);
+
+ memcpy(dataAlloc, head, dataChunk.len);
+ return dataAlloc;
+
+}
+
+
+// ----------------------------------------------------- //
+void bFile::parseStruct(char *strcPtr, char *dtPtr, int old_dna, int new_dna, bool fixupPointers)
+{
+ if (old_dna == -1) return;
+ if (new_dna == -1) return;
+
+ //disable this, because we need to fixup pointers/ListBase
+ if (0)//mFileDNA->flagEqual(old_dna))
+ {
+ short *strc = mFileDNA->getStruct(old_dna);
+ int len = mFileDNA->getLength(strc[0]);
+
+ memcpy(strcPtr, dtPtr, len);
+ return;
+ }
+
+ // Ok, now build the struct
+ char *memType, *memName, *cpc, *cpo;
+ short *fileStruct, *filePtrOld, *memoryStruct, *firstStruct;
+ int elementLength, size, revType, old_nr, new_nr, fpLen;
+ short firstStructType;
+
+
+ // File to memory lookup
+ memoryStruct = mMemoryDNA->getStruct(new_dna);
+ fileStruct = mFileDNA->getStruct(old_dna);
+ firstStruct = fileStruct;
+
+
+ filePtrOld = fileStruct;
+ firstStructType = mMemoryDNA->getStruct(0)[0];
+
+ // Get number of elements
+ elementLength = memoryStruct[1];
+ memoryStruct+=2;
+
+ cpc = strcPtr; cpo = 0;
+ for (int ele=0; ele<elementLength; ele++, memoryStruct+=2)
+ {
+ memType = mMemoryDNA->getType(memoryStruct[0]);
+ memName = mMemoryDNA->getName(memoryStruct[1]);
+
+
+ size = mMemoryDNA->getElementSize(memoryStruct[0], memoryStruct[1]);
+ revType = mMemoryDNA->getReverseType(memoryStruct[0]);
+
+ if (revType != -1 && memoryStruct[0]>=firstStructType && memName[0] != '*')
+ {
+ cpo = getFileElement(firstStruct, memName, memType, dtPtr, &filePtrOld);
+ if (cpo)
+ {
+ int arrayLen = mFileDNA->getArraySizeNew(filePtrOld[1]);
+ old_nr = mFileDNA->getReverseType(memType);
+ new_nr = revType;
+ fpLen = mFileDNA->getElementSize(filePtrOld[0], filePtrOld[1]);
+ if (arrayLen==1)
+ {
+ parseStruct(cpc, cpo, old_nr, new_nr,fixupPointers);
+ } else
+ {
+ char* tmpCpc = cpc;
+ char* tmpCpo = cpo;
+
+ for (int i=0;i<arrayLen;i++)
+ {
+ parseStruct(tmpCpc, tmpCpo, old_nr, new_nr,fixupPointers);
+ tmpCpc += size/arrayLen;
+ tmpCpo += fpLen/arrayLen;
+ }
+ }
+ cpc+=size;
+ cpo+=fpLen;
+ }
+ else
+ cpc+=size;
+ }
+ else
+ {
+ getMatchingFileDNA(fileStruct, memName, memType, cpc, dtPtr,fixupPointers);
+ cpc+=size;
+ }
+
+ }
+}
+
+
+// ----------------------------------------------------- //
+static void getElement(int arrayLen, const char *cur, const char *old, char *oldPtr, char *curData)
+{
+#define b3GetEle(value, current, type, cast, size, ptr)\
+ if (strcmp(current, type)==0)\
+ {\
+ value = (*(cast*)ptr);\
+ ptr += size;\
+ }
+
+#define b3SetEle(value, current, type, cast, size, ptr)\
+ if (strcmp(current, type)==0)\
+ {\
+ (*(cast*)ptr) = (cast)value;\
+ ptr += size;\
+ }
+ double value = 0.0;
+
+ for (int i=0; i<arrayLen; i++)
+ {
+ b3GetEle(value, old, "char", char, sizeof(char), oldPtr);
+ b3SetEle(value, cur, "char", char, sizeof(char), curData);
+ b3GetEle(value, old, "short", short, sizeof(short), oldPtr);
+ b3SetEle(value, cur, "short", short, sizeof(short), curData);
+ b3GetEle(value, old, "ushort", unsigned short, sizeof(unsigned short), oldPtr);
+ b3SetEle(value, cur, "ushort", unsigned short, sizeof(unsigned short), curData);
+ b3GetEle(value, old, "int", int, sizeof(int), oldPtr);
+ b3SetEle(value, cur, "int", int, sizeof(int), curData);
+ b3GetEle(value, old, "long", int, sizeof(int), oldPtr);
+ b3SetEle(value, cur, "long", int, sizeof(int), curData);
+ b3GetEle(value, old, "float", float, sizeof(float), oldPtr);
+ b3SetEle(value, cur, "float", float, sizeof(float), curData);
+ b3GetEle(value, old, "double", double, sizeof(double), oldPtr);
+ b3SetEle(value, cur, "double", double, sizeof(double), curData);
+ }
+}
+
+
+// ----------------------------------------------------- //
+void bFile::swapData(char *data, short type, int arraySize,bool ignoreEndianFlag)
+{
+ if (ignoreEndianFlag || (mFlags &FD_ENDIAN_SWAP))
+ {
+ if (type == 2 || type == 3)
+ {
+ short *sp = (short*)data;
+ for (int i=0; i<arraySize; i++)
+ {
+ sp[0] = ChunkUtils::swapShort(sp[0]);
+ sp++;
+ }
+ }
+ if (type>3 && type <8)
+ {
+ char c;
+ char *cp = data;
+ for (int i=0; i<arraySize; i++)
+ {
+ c = cp[0];
+ cp[0] = cp[3];
+ cp[3] = c;
+ c = cp[1];
+ cp[1] = cp[2];
+ cp[2] = c;
+ cp+=4;
+ }
+ }
+ }
+}
+
+
+
+void bFile::safeSwapPtr(char *dst, const char *src)
+{
+ int ptrFile = mFileDNA->getPointerSize();
+ int ptrMem = mMemoryDNA->getPointerSize();
+
+ if (!src && !dst)
+ return;
+
+
+ if (ptrFile == ptrMem)
+ {
+ memcpy(dst, src, ptrMem);
+ }
+ else if (ptrMem==4 && ptrFile==8)
+ {
+ b3PointerUid* oldPtr = (b3PointerUid*)src;
+ b3PointerUid* newPtr = (b3PointerUid*)dst;
+
+ if (oldPtr->m_uniqueIds[0] == oldPtr->m_uniqueIds[1])
+ {
+ //Bullet stores the 32bit unique ID in both upper and lower part of 64bit pointers
+ //so it can be used to distinguish between .blend and .bullet
+ newPtr->m_uniqueIds[0] = oldPtr->m_uniqueIds[0];
+ } else
+ {
+ //deal with pointers the Blender .blend style way, see
+ //readfile.c in the Blender source tree
+ b3Long64 longValue = *((b3Long64*)src);
+ //endian swap for 64bit pointer otherwise truncation will fail due to trailing zeros
+ if (mFlags & FD_ENDIAN_SWAP)
+ B3_SWITCH_LONGINT(longValue);
+ *((int*)dst) = (int)(longValue>>3);
+ }
+
+ }
+ else if (ptrMem==8 && ptrFile==4)
+ {
+ b3PointerUid* oldPtr = (b3PointerUid*)src;
+ b3PointerUid* newPtr = (b3PointerUid*)dst;
+ if (oldPtr->m_uniqueIds[0] == oldPtr->m_uniqueIds[1])
+ {
+ newPtr->m_uniqueIds[0] = oldPtr->m_uniqueIds[0];
+ newPtr->m_uniqueIds[1] = 0;
+ } else
+ {
+ *((b3Long64*)dst)= *((int*)src);
+ }
+ }
+ else
+ {
+ printf ("%d %d\n", ptrFile,ptrMem);
+ assert(0 && "Invalid pointer len");
+ }
+
+
+}
+
+
+// ----------------------------------------------------- //
+void bFile::getMatchingFileDNA(short* dna_addr, const char* lookupName, const char* lookupType, char *strcData, char *data, bool fixupPointers)
+{
+ // find the matching memory dna data
+ // to the file being loaded. Fill the
+ // memory with the file data...
+
+ int len = dna_addr[1];
+ dna_addr+=2;
+
+ for (int i=0; i<len; i++, dna_addr+=2)
+ {
+ const char* type = mFileDNA->getType(dna_addr[0]);
+ const char* name = mFileDNA->getName(dna_addr[1]);
+
+
+
+ int eleLen = mFileDNA->getElementSize(dna_addr[0], dna_addr[1]);
+
+ if ((mFlags&FD_BROKEN_DNA)!=0)
+ {
+ if ((strcmp(type,"short")==0)&&(strcmp(name,"int")==0))
+ {
+ eleLen = 0;
+ }
+ }
+
+ if (strcmp(lookupName, name)==0)
+ {
+ //int arrayLenold = mFileDNA->getArraySize((char*)name.c_str());
+ int arrayLen = mFileDNA->getArraySizeNew(dna_addr[1]);
+ //assert(arrayLenold == arrayLen);
+
+ if (name[0] == '*')
+ {
+ // cast pointers
+ int ptrFile = mFileDNA->getPointerSize();
+ int ptrMem = mMemoryDNA->getPointerSize();
+ safeSwapPtr(strcData,data);
+
+ if (fixupPointers)
+ {
+ if (arrayLen > 1)
+ {
+ //void **sarray = (void**)strcData;
+ //void **darray = (void**)data;
+
+ char *cpc, *cpo;
+ cpc = (char*)strcData;
+ cpo = (char*)data;
+
+ for (int a=0; a<arrayLen; a++)
+ {
+ safeSwapPtr(cpc, cpo);
+ m_pointerFixupArray.push_back(cpc);
+ cpc += ptrMem;
+ cpo += ptrFile;
+ }
+ }
+ else
+ {
+ if (name[1] == '*')
+ m_pointerPtrFixupArray.push_back(strcData);
+ else
+ m_pointerFixupArray.push_back(strcData);
+ }
+ }
+ else
+ {
+// printf("skipped %s %s : %x\n",type.c_str(),name.c_str(),strcData);
+ }
+
+ }
+
+ else if (strcmp(type, lookupType)==0)
+ memcpy(strcData, data, eleLen);
+ else
+ getElement(arrayLen, lookupType, type, data, strcData);
+
+ // --
+ return;
+ }
+ data+=eleLen;
+ }
+}
+
+
+// ----------------------------------------------------- //
+char* bFile::getFileElement(short *firstStruct, char *lookupName, char *lookupType, char *data, short **foundPos)
+{
+ short *old = firstStruct;//mFileDNA->getStruct(old_nr);
+ int elementLength = old[1];
+ old+=2;
+
+ for (int i=0; i<elementLength; i++, old+=2)
+ {
+ char* type = mFileDNA->getType(old[0]);
+ char* name = mFileDNA->getName(old[1]);
+ int len = mFileDNA->getElementSize(old[0], old[1]);
+
+ if (strcmp(lookupName, name)==0)
+ {
+ if (strcmp(type, lookupType)==0)
+ {
+ if (foundPos)
+ *foundPos = old;
+ return data;
+ }
+ return 0;
+ }
+ data+=len;
+ }
+ return 0;
+}
+
+
+// ----------------------------------------------------- //
+void bFile::swapStruct(int dna_nr, char *data,bool ignoreEndianFlag)
+{
+ if (dna_nr == -1) return;
+
+ short *strc = mFileDNA->getStruct(dna_nr);
+ //short *firstStrc = strc;
+
+ int elementLen= strc[1];
+ strc+=2;
+
+ short first = mFileDNA->getStruct(0)[0];
+
+ char *buf = data;
+ for (int i=0; i<elementLen; i++, strc+=2)
+ {
+ char *type = mFileDNA->getType(strc[0]);
+ char *name = mFileDNA->getName(strc[1]);
+
+ int size = mFileDNA->getElementSize(strc[0], strc[1]);
+ if (strc[0] >= first && name[0]!='*')
+ {
+ int old_nr = mFileDNA->getReverseType(type);
+ int arrayLen = mFileDNA->getArraySizeNew(strc[1]);
+ if (arrayLen==1)
+ {
+ swapStruct(old_nr,buf,ignoreEndianFlag);
+ } else
+ {
+ char* tmpBuf = buf;
+ for (int i=0;i<arrayLen;i++)
+ {
+ swapStruct(old_nr,tmpBuf,ignoreEndianFlag);
+ tmpBuf+=size/arrayLen;
+ }
+ }
+ }
+ else
+ {
+ //int arrayLenOld = mFileDNA->getArraySize(name);
+ int arrayLen = mFileDNA->getArraySizeNew(strc[1]);
+ //assert(arrayLenOld == arrayLen);
+ swapData(buf, strc[0], arrayLen,ignoreEndianFlag);
+ }
+ buf+=size;
+ }
+}
+
+void bFile::resolvePointersMismatch()
+{
+// printf("resolvePointersStructMismatch\n");
+
+ int i;
+
+ for (i=0;i< m_pointerFixupArray.size();i++)
+ {
+ char* cur = m_pointerFixupArray.at(i);
+ void** ptrptr = (void**) cur;
+ void* ptr = *ptrptr;
+ ptr = findLibPointer(ptr);
+ if (ptr)
+ {
+ //printf("Fixup pointer!\n");
+ *(ptrptr) = ptr;
+ } else
+ {
+// printf("pointer not found: %x\n",cur);
+ }
+ }
+
+
+ for (i=0; i<m_pointerPtrFixupArray.size(); i++)
+ {
+ char* cur= m_pointerPtrFixupArray.at(i);
+ void** ptrptr = (void**)cur;
+
+ bChunkInd *block = m_chunkPtrPtrMap.find(*ptrptr);
+ if (block)
+ {
+ int ptrMem = mMemoryDNA->getPointerSize();
+ int ptrFile = mFileDNA->getPointerSize();
+
+
+ int blockLen = block->len / ptrFile;
+
+ void *onptr = findLibPointer(*ptrptr);
+ if (onptr)
+ {
+ char *newPtr = new char[blockLen * ptrMem];
+ addDataBlock(newPtr);
+ memset(newPtr, 0, blockLen * ptrMem);
+
+ void **onarray = (void**)onptr;
+ char *oldPtr = (char*)onarray;
+
+ int p = 0;
+ while (blockLen-- > 0)
+ {
+ b3PointerUid dp = {{0}};
+ safeSwapPtr((char*)dp.m_uniqueIds, oldPtr);
+
+ void **tptr = (void**)(newPtr + p * ptrMem);
+ *tptr = findLibPointer(dp.m_ptr);
+
+ oldPtr += ptrFile;
+ ++p;
+ }
+
+ *ptrptr = newPtr;
+ }
+ }
+ }
+}
+
+
+///this loop only works fine if the Blender DNA structure of the file matches the headerfiles
+void bFile::resolvePointersChunk(const bChunkInd& dataChunk, int verboseMode)
+{
+ bParse::bDNA* fileDna = mFileDNA ? mFileDNA : mMemoryDNA;
+
+ short int* oldStruct = fileDna->getStruct(dataChunk.dna_nr);
+ short oldLen = fileDna->getLength(oldStruct[0]);
+ //char* structType = fileDna->getType(oldStruct[0]);
+
+ char* cur = (char*)findLibPointer(dataChunk.oldPtr);
+ for (int block=0; block<dataChunk.nr; block++)
+ {
+ resolvePointersStructRecursive(cur,dataChunk.dna_nr, verboseMode,1);
+ cur += oldLen;
+ }
+}
+
+
+int bFile::resolvePointersStructRecursive(char *strcPtr, int dna_nr, int verboseMode,int recursion)
+{
+
+ bParse::bDNA* fileDna = mFileDNA ? mFileDNA : mMemoryDNA;
+
+ char* memType;
+ char* memName;
+ short firstStructType = fileDna->getStruct(0)[0];
+
+
+ char* elemPtr= strcPtr;
+
+ short int* oldStruct = fileDna->getStruct(dna_nr);
+
+ int elementLength = oldStruct[1];
+ oldStruct+=2;
+
+ int totalSize = 0;
+
+ for (int ele=0; ele<elementLength; ele++, oldStruct+=2)
+ {
+
+ memType = fileDna->getType(oldStruct[0]);
+ memName = fileDna->getName(oldStruct[1]);
+
+
+
+ int arrayLen = fileDna->getArraySizeNew(oldStruct[1]);
+ if (memName[0] == '*')
+ {
+ if (arrayLen > 1)
+ {
+ void **array= (void**)elemPtr;
+ for (int a=0; a<arrayLen; a++)
+ {
+ if (verboseMode & FD_VERBOSE_EXPORT_XML)
+ {
+ for (int i=0;i<recursion;i++)
+ {
+ printf(" ");
+ }
+ //skip the *
+ printf("<%s type=\"pointer\"> ",&memName[1]);
+ printf("%p ", array[a]);
+ printf("</%s>\n",&memName[1]);
+ }
+
+ array[a] = findLibPointer(array[a]);
+ }
+ }
+ else
+ {
+ void** ptrptr = (void**) elemPtr;
+ void* ptr = *ptrptr;
+ if (verboseMode & FD_VERBOSE_EXPORT_XML)
+ {
+ for (int i=0;i<recursion;i++)
+ {
+ printf(" ");
+ }
+ printf("<%s type=\"pointer\"> ",&memName[1]);
+ printf("%p ", ptr);
+ printf("</%s>\n",&memName[1]);
+ }
+ ptr = findLibPointer(ptr);
+
+ if (ptr)
+ {
+ // printf("Fixup pointer at 0x%x from 0x%x to 0x%x!\n",ptrptr,*ptrptr,ptr);
+ *(ptrptr) = ptr;
+ if (memName[1] == '*' && ptrptr && *ptrptr)
+ {
+ // This will only work if the given **array is continuous
+ void **array= (void**)*(ptrptr);
+ void *np= array[0];
+ int n=0;
+ while (np)
+ {
+ np= findLibPointer(array[n]);
+ if (np) array[n]= np;
+ n++;
+ }
+ }
+ } else
+ {
+ // printf("Cannot fixup pointer at 0x%x from 0x%x to 0x%x!\n",ptrptr,*ptrptr,ptr);
+ }
+ }
+ } else
+ {
+ int revType = fileDna->getReverseType(oldStruct[0]);
+ if (oldStruct[0]>=firstStructType) //revType != -1 &&
+ {
+ char cleanName[MAX_STRLEN];
+ getCleanName(memName,cleanName);
+
+ int arrayLen = fileDna->getArraySizeNew(oldStruct[1]);
+ int byteOffset = 0;
+
+ if (verboseMode & FD_VERBOSE_EXPORT_XML)
+ {
+ for (int i=0;i<recursion;i++)
+ {
+ printf(" ");
+ }
+
+ if (arrayLen>1)
+ {
+ printf("<%s type=\"%s\" count=%d>\n",cleanName,memType, arrayLen);
+ } else
+ {
+ printf("<%s type=\"%s\">\n",cleanName,memType);
+ }
+ }
+
+ for (int i=0;i<arrayLen;i++)
+ {
+ byteOffset += resolvePointersStructRecursive(elemPtr+byteOffset,revType, verboseMode,recursion+1);
+ }
+ if (verboseMode & FD_VERBOSE_EXPORT_XML)
+ {
+ for (int i=0;i<recursion;i++)
+ {
+ printf(" ");
+ }
+ printf("</%s>\n",cleanName);
+ }
+ } else
+ {
+ //export a simple type
+ if (verboseMode & FD_VERBOSE_EXPORT_XML)
+ {
+
+ if (arrayLen>MAX_ARRAY_LENGTH)
+ {
+ printf("too long\n");
+ } else
+ {
+ //printf("%s %s\n",memType,memName);
+
+ bool isIntegerType = (strcmp(memType,"char")==0) || (strcmp(memType,"int")==0) || (strcmp(memType,"short")==0);
+
+ if (isIntegerType)
+ {
+ const char* newtype="int";
+ int dbarray[MAX_ARRAY_LENGTH];
+ int* dbPtr = 0;
+ char* tmp = elemPtr;
+ dbPtr = &dbarray[0];
+ if (dbPtr)
+ {
+ char cleanName[MAX_STRLEN];
+ getCleanName(memName,cleanName);
+
+ int i;
+ getElement(arrayLen, newtype,memType, tmp, (char*)dbPtr);
+ for (i=0;i<recursion;i++)
+ printf(" ");
+ if (arrayLen==1)
+ printf("<%s type=\"%s\">",cleanName,memType);
+ else
+ printf("<%s type=\"%s\" count=%d>",cleanName,memType,arrayLen);
+ for (i=0;i<arrayLen;i++)
+ printf(" %d ",dbPtr[i]);
+ printf("</%s>\n",cleanName);
+ }
+ } else
+ {
+ const char* newtype="double";
+ double dbarray[MAX_ARRAY_LENGTH];
+ double* dbPtr = 0;
+ char* tmp = elemPtr;
+ dbPtr = &dbarray[0];
+ if (dbPtr)
+ {
+ int i;
+ getElement(arrayLen, newtype,memType, tmp, (char*)dbPtr);
+ for (i=0;i<recursion;i++)
+ printf(" ");
+ char cleanName[MAX_STRLEN];
+ getCleanName(memName,cleanName);
+
+ if (arrayLen==1)
+ {
+ printf("<%s type=\"%s\">",memName,memType);
+ }
+ else
+ {
+ printf("<%s type=\"%s\" count=%d>",cleanName,memType,arrayLen);
+ }
+ for (i=0;i<arrayLen;i++)
+ printf(" %f ",dbPtr[i]);
+ printf("</%s>\n",cleanName);
+ }
+ }
+ }
+
+ }
+ }
+ }
+
+ int size = fileDna->getElementSize(oldStruct[0], oldStruct[1]);
+ totalSize += size;
+ elemPtr+=size;
+
+ }
+
+ return totalSize;
+}
+
+
+///Resolve pointers replaces the original pointers in structures, and linked lists by the new in-memory structures
+void bFile::resolvePointers(int verboseMode)
+{
+ bParse::bDNA* fileDna = mFileDNA ? mFileDNA : mMemoryDNA;
+
+ //char *dataPtr = mFileBuffer+mDataStart;
+
+ if (1) //mFlags & (FD_BITS_VARIES | FD_VERSION_VARIES))
+ {
+ resolvePointersMismatch();
+ }
+
+ {
+
+ if (verboseMode & FD_VERBOSE_EXPORT_XML)
+ {
+ printf("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
+ int numitems = m_chunks.size();
+ printf("<bullet_physics version=%d itemcount = %d>\n", b3GetVersion(), numitems);
+ }
+ for (int i=0;i<m_chunks.size();i++)
+ {
+ const bChunkInd& dataChunk = m_chunks.at(i);
+
+ if (!mFileDNA || fileDna->flagEqual(dataChunk.dna_nr))
+ {
+ //dataChunk.len
+ short int* oldStruct = fileDna->getStruct(dataChunk.dna_nr);
+ char* oldType = fileDna->getType(oldStruct[0]);
+
+ if (verboseMode & FD_VERBOSE_EXPORT_XML)
+ printf(" <%s pointer=%p>\n",oldType,dataChunk.oldPtr);
+
+ resolvePointersChunk(dataChunk, verboseMode);
+
+ if (verboseMode & FD_VERBOSE_EXPORT_XML)
+ printf(" </%s>\n",oldType);
+ } else
+ {
+ //printf("skipping mStruct\n");
+ }
+ }
+ if (verboseMode & FD_VERBOSE_EXPORT_XML)
+ {
+ printf("</bullet_physics>\n");
+ }
+ }
+
+
+}
+
+
+// ----------------------------------------------------- //
+void* bFile::findLibPointer(void *ptr)
+{
+
+ bStructHandle** ptrptr = getLibPointers().find(ptr);
+ if (ptrptr)
+ return *ptrptr;
+ return 0;
+}
+
+
+void bFile::updateOldPointers()
+{
+ int i;
+
+ for (i=0;i<m_chunks.size();i++)
+ {
+ bChunkInd& dataChunk = m_chunks[i];
+ dataChunk.oldPtr = findLibPointer(dataChunk.oldPtr);
+ }
+}
+void bFile::dumpChunks(bParse::bDNA* dna)
+{
+ int i;
+
+ for (i=0;i<m_chunks.size();i++)
+ {
+ bChunkInd& dataChunk = m_chunks[i];
+ char* codeptr = (char*)&dataChunk.code;
+ char codestr[5] = {codeptr[0],codeptr[1],codeptr[2],codeptr[3],0};
+
+ short* newStruct = dna->getStruct(dataChunk.dna_nr);
+ char* typeName = dna->getType(newStruct[0]);
+ printf("%3d: %s ",i,typeName);
+
+ printf("code=%s ",codestr);
+
+ printf("ptr=%p ",dataChunk.oldPtr);
+ printf("len=%d ",dataChunk.len);
+ printf("nr=%d ",dataChunk.nr);
+ if (dataChunk.nr!=1)
+ {
+ printf("not 1\n");
+ }
+ printf("\n");
+
+
+
+
+ }
+
+#if 0
+ IDFinderData ifd;
+ ifd.success = 0;
+ ifd.IDname = NULL;
+ ifd.just_print_it = 1;
+ for (i=0; i<bf->m_blocks.size(); ++i)
+ {
+ BlendBlock* bb = bf->m_blocks[i];
+ printf("tag='%s'\tptr=%p\ttype=%s\t[%4d]", bb->tag, bb,bf->types[bb->type_index].name,bb->m_array_entries_.size());
+ block_ID_finder(bb, bf, &ifd);
+ printf("\n");
+ }
+#endif
+
+}
+
+
+void bFile::writeChunks(FILE* fp, bool fixupPointers)
+{
+ bParse::bDNA* fileDna = mFileDNA ? mFileDNA : mMemoryDNA;
+
+ for (int i=0;i<m_chunks.size();i++)
+ {
+ bChunkInd& dataChunk = m_chunks.at(i);
+
+ // Ouch! need to rebuild the struct
+ short *oldStruct,*curStruct;
+ char *oldType, *newType;
+ int oldLen, curLen, reverseOld;
+
+ oldStruct = fileDna->getStruct(dataChunk.dna_nr);
+ oldType = fileDna->getType(oldStruct[0]);
+ oldLen = fileDna->getLength(oldStruct[0]);
+ ///don't try to convert Link block data, just memcpy it. Other data can be converted.
+ reverseOld = mMemoryDNA->getReverseType(oldType);
+
+
+ if ((reverseOld!=-1))
+ {
+ // make sure it's here
+ //assert(reverseOld!= -1 && "getReverseType() returned -1, struct required!");
+ //
+ curStruct = mMemoryDNA->getStruct(reverseOld);
+ newType = mMemoryDNA->getType(curStruct[0]);
+ // make sure it's the same
+ assert((strcmp(oldType, newType)==0) && "internal error, struct mismatch!");
+
+
+ curLen = mMemoryDNA->getLength(curStruct[0]);
+ dataChunk.dna_nr = reverseOld;
+ if (strcmp("Link",oldType)!=0)
+ {
+ dataChunk.len = curLen * dataChunk.nr;
+ } else
+ {
+// printf("keep length of link = %d\n",dataChunk.len);
+ }
+
+ //write the structure header
+ fwrite(&dataChunk,sizeof(bChunkInd),1,fp);
+
+
+
+ short int* curStruct1;
+ curStruct1 = mMemoryDNA->getStruct(dataChunk.dna_nr);
+ assert(curStruct1 == curStruct);
+
+ char* cur = fixupPointers ? (char*)findLibPointer(dataChunk.oldPtr) : (char*)dataChunk.oldPtr;
+
+ //write the actual contents of the structure(s)
+ fwrite(cur,dataChunk.len,1,fp);
+ } else
+ {
+ printf("serious error, struct mismatch: don't write\n");
+ }
+ }
+
+}
+
+
+// ----------------------------------------------------- //
+int bFile::getNextBlock(bChunkInd *dataChunk, const char *dataPtr, const int flags)
+{
+ bool swap = false;
+ bool varies = false;
+
+ if (flags &FD_ENDIAN_SWAP)
+ swap = true;
+ if (flags &FD_BITS_VARIES)
+ varies = true;
+
+ if (VOID_IS_8)
+ {
+ if (varies)
+ {
+ bChunkPtr4 head;
+ memcpy(&head, dataPtr, sizeof(bChunkPtr4));
+
+
+ bChunkPtr8 chunk;
+
+ chunk.code = head.code;
+ chunk.len = head.len;
+ chunk.m_uniqueInts[0] = head.m_uniqueInt;
+ chunk.m_uniqueInts[1] = 0;
+ chunk.dna_nr = head.dna_nr;
+ chunk.nr = head.nr;
+
+ if (swap)
+ {
+ if ((chunk.code & 0xFFFF)==0)
+ chunk.code >>=16;
+
+ B3_SWITCH_INT(chunk.len);
+ B3_SWITCH_INT(chunk.dna_nr);
+ B3_SWITCH_INT(chunk.nr);
+ }
+
+
+ memcpy(dataChunk, &chunk, sizeof(bChunkInd));
+ }
+ else
+ {
+ bChunkPtr8 c;
+ memcpy(&c, dataPtr, sizeof(bChunkPtr8));
+
+ if (swap)
+ {
+ if ((c.code & 0xFFFF)==0)
+ c.code >>=16;
+
+ B3_SWITCH_INT(c.len);
+ B3_SWITCH_INT(c.dna_nr);
+ B3_SWITCH_INT(c.nr);
+ }
+
+ memcpy(dataChunk, &c, sizeof(bChunkInd));
+ }
+ }
+ else
+ {
+ if (varies)
+ {
+ bChunkPtr8 head;
+ memcpy(&head, dataPtr, sizeof(bChunkPtr8));
+
+
+ bChunkPtr4 chunk;
+ chunk.code = head.code;
+ chunk.len = head.len;
+
+ if (head.m_uniqueInts[0]==head.m_uniqueInts[1])
+ {
+ chunk.m_uniqueInt = head.m_uniqueInts[0];
+ } else
+ {
+ b3Long64 oldPtr =0;
+ memcpy(&oldPtr, &head.m_uniqueInts[0], 8);
+ if (swap)
+ B3_SWITCH_LONGINT(oldPtr);
+ chunk.m_uniqueInt = (int)(oldPtr >> 3);
+ }
+
+
+ chunk.dna_nr = head.dna_nr;
+ chunk.nr = head.nr;
+
+ if (swap)
+ {
+ if ((chunk.code & 0xFFFF)==0)
+ chunk.code >>=16;
+
+ B3_SWITCH_INT(chunk.len);
+ B3_SWITCH_INT(chunk.dna_nr);
+ B3_SWITCH_INT(chunk.nr);
+ }
+
+ memcpy(dataChunk, &chunk, sizeof(bChunkInd));
+ }
+ else
+ {
+ bChunkPtr4 c;
+ memcpy(&c, dataPtr, sizeof(bChunkPtr4));
+
+ if (swap)
+ {
+ if ((c.code & 0xFFFF)==0)
+ c.code >>=16;
+
+ B3_SWITCH_INT(c.len);
+ B3_SWITCH_INT(c.dna_nr);
+ B3_SWITCH_INT(c.nr);
+ }
+ memcpy(dataChunk, &c, sizeof(bChunkInd));
+ }
+ }
+
+ if (dataChunk->len < 0)
+ return -1;
+
+#if 0
+ print ("----------");
+ print (dataChunk->code);
+ print (dataChunk->len);
+ print (dataChunk->old);
+ print (dataChunk->dna_nr);
+ print (dataChunk->nr);
+#endif
+ return (dataChunk->len+ChunkUtils::getOffset(flags));
+}
+
+
+
+//eof
diff --git a/thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/b3File.h b/thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/b3File.h
new file mode 100644
index 0000000000..861056806d
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/b3File.h
@@ -0,0 +1,165 @@
+/*
+bParse
+Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com
+
+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 __BFILE_H__
+#define __BFILE_H__
+
+#include "b3Common.h"
+#include "b3Chunk.h"
+#include <stdio.h>
+
+namespace bParse {
+
+ // ----------------------------------------------------- //
+ enum bFileFlags
+ {
+ FD_INVALID =0,
+ FD_OK =1,
+ FD_VOID_IS_8 =2,
+ FD_ENDIAN_SWAP =4,
+ FD_FILE_64 =8,
+ FD_BITS_VARIES =16,
+ FD_VERSION_VARIES = 32,
+ FD_DOUBLE_PRECISION =64,
+ FD_BROKEN_DNA = 128
+ };
+
+ enum bFileVerboseMode
+ {
+ FD_VERBOSE_EXPORT_XML = 1,
+ FD_VERBOSE_DUMP_DNA_TYPE_DEFINITIONS = 2,
+ FD_VERBOSE_DUMP_CHUNKS = 4,
+ FD_VERBOSE_DUMP_FILE_INFO=8,
+ };
+ // ----------------------------------------------------- //
+ class bFile
+ {
+ protected:
+
+ char m_headerString[7];
+
+ bool mOwnsBuffer;
+ char* mFileBuffer;
+ int mFileLen;
+ int mVersion;
+
+
+ bPtrMap mLibPointers;
+
+ int mDataStart;
+ bDNA* mFileDNA;
+ bDNA* mMemoryDNA;
+
+ b3AlignedObjectArray<char*> m_pointerFixupArray;
+ b3AlignedObjectArray<char*> m_pointerPtrFixupArray;
+
+ b3AlignedObjectArray<bChunkInd> m_chunks;
+ b3HashMap<b3HashPtr, bChunkInd> m_chunkPtrPtrMap;
+
+ //
+
+ bPtrMap mDataPointers;
+
+
+ int mFlags;
+
+ // ////////////////////////////////////////////////////////////////////////////
+
+ // buffer offset util
+ int getNextBlock(bChunkInd *dataChunk, const char *dataPtr, const int flags);
+ void safeSwapPtr(char *dst, const char *src);
+
+ virtual void parseHeader();
+
+ virtual void parseData() = 0;
+
+ void resolvePointersMismatch();
+ void resolvePointersChunk(const bChunkInd& dataChunk, int verboseMode);
+
+ int resolvePointersStructRecursive(char *strcPtr, int old_dna, int verboseMode, int recursion);
+ //void swapPtr(char *dst, char *src);
+
+ void parseStruct(char *strcPtr, char *dtPtr, int old_dna, int new_dna, bool fixupPointers);
+ void getMatchingFileDNA(short* old, const char* lookupName, const char* lookupType, char *strcData, char *data, bool fixupPointers);
+ char* getFileElement(short *firstStruct, char *lookupName, char *lookupType, char *data, short **foundPos);
+
+
+ void swap(char *head, class bChunkInd& ch, bool ignoreEndianFlag);
+ void swapData(char *data, short type, int arraySize, bool ignoreEndianFlag);
+ void swapStruct(int dna_nr, char *data, bool ignoreEndianFlag);
+ void swapLen(char *dataPtr);
+ void swapDNA(char* ptr);
+
+
+ char* readStruct(char *head, class bChunkInd& chunk);
+ char *getAsString(int code);
+
+ void parseInternal(int verboseMode, char* memDna,int memDnaLength);
+
+ public:
+ bFile(const char *filename, const char headerString[7]);
+
+ //todo: make memoryBuffer const char
+ //bFile( const char *memoryBuffer, int len);
+ bFile( char *memoryBuffer, int len, const char headerString[7]);
+ virtual ~bFile();
+
+ bDNA* getFileDNA()
+ {
+ return mFileDNA;
+ }
+
+ virtual void addDataBlock(char* dataBlock) = 0;
+
+ int getFlags() const
+ {
+ return mFlags;
+ }
+
+ bPtrMap& getLibPointers()
+ {
+ return mLibPointers;
+ }
+
+ void* findLibPointer(void *ptr);
+
+ bool ok();
+
+ virtual void parse(int verboseMode) = 0;
+
+ virtual int write(const char* fileName, bool fixupPointers=false) = 0;
+
+ virtual void writeChunks(FILE* fp, bool fixupPointers );
+
+ virtual void writeDNA(FILE* fp) = 0;
+
+ void updateOldPointers();
+ void resolvePointers(int verboseMode);
+
+ void dumpChunks(bDNA* dna);
+
+ int getVersion() const
+ {
+ return mVersion;
+ }
+ //pre-swap the endianness, so that data loaded on a target with different endianness doesn't need to be swapped
+ void preSwap();
+ void writeFile(const char* fileName);
+
+ };
+}
+
+
+#endif//__BFILE_H__
diff --git a/thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/b3Serializer.cpp b/thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/b3Serializer.cpp
new file mode 100644
index 0000000000..c6a2a832ad
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/b3Serializer.cpp
@@ -0,0 +1,908 @@
+char b3s_bulletDNAstr[]= {
+char(83),char(68),char(78),char(65),char(78),char(65),char(77),char(69),char(63),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),
+char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(115),char(0),char(42),char(102),char(105),char(114),char(115),char(116),char(0),char(42),char(108),char(97),char(115),
+char(116),char(0),char(109),char(95),char(102),char(108),char(111),char(97),char(116),char(115),char(91),char(52),char(93),char(0),char(109),char(95),char(101),char(108),char(91),char(51),
+char(93),char(0),char(109),char(95),char(98),char(97),char(115),char(105),char(115),char(0),char(109),char(95),char(111),char(114),char(105),char(103),char(105),char(110),char(0),char(109),
+char(95),char(114),char(111),char(111),char(116),char(78),char(111),char(100),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(115),char(117),char(98),
+char(116),char(114),char(101),char(101),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),
+char(65),char(97),char(98),char(98),char(77),char(105),char(110),char(91),char(51),char(93),char(0),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),char(122),
+char(101),char(100),char(65),char(97),char(98),char(98),char(77),char(97),char(120),char(91),char(51),char(93),char(0),char(109),char(95),char(97),char(97),char(98),char(98),char(77),
+char(105),char(110),char(79),char(114),char(103),char(0),char(109),char(95),char(97),char(97),char(98),char(98),char(77),char(97),char(120),char(79),char(114),char(103),char(0),char(109),
+char(95),char(101),char(115),char(99),char(97),char(112),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(115),char(117),char(98),char(80),char(97),
+char(114),char(116),char(0),char(109),char(95),char(116),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),
+char(95),char(112),char(97),char(100),char(91),char(52),char(93),char(0),char(109),char(95),char(101),char(115),char(99),char(97),char(112),char(101),char(73),char(110),char(100),char(101),
+char(120),char(79),char(114),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(98),
+char(118),char(104),char(65),char(97),char(98),char(98),char(77),char(105),char(110),char(0),char(109),char(95),char(98),char(118),char(104),char(65),char(97),char(98),char(98),char(77),
+char(97),char(120),char(0),char(109),char(95),char(98),char(118),char(104),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(97),char(116),char(105),char(111),char(110),
+char(0),char(109),char(95),char(99),char(117),char(114),char(78),char(111),char(100),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(117),char(115),
+char(101),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(97),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(110),char(117),char(109),char(67),
+char(111),char(110),char(116),char(105),char(103),char(117),char(111),char(117),char(115),char(76),char(101),char(97),char(102),char(78),char(111),char(100),char(101),char(115),char(0),char(109),
+char(95),char(110),char(117),char(109),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(67),char(111),char(110),char(116),char(105),char(103),char(117),
+char(111),char(117),char(115),char(78),char(111),char(100),char(101),char(115),char(0),char(42),char(109),char(95),char(99),char(111),char(110),char(116),char(105),char(103),char(117),char(111),
+char(117),char(115),char(78),char(111),char(100),char(101),char(115),char(80),char(116),char(114),char(0),char(42),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),
+char(122),char(101),char(100),char(67),char(111),char(110),char(116),char(105),char(103),char(117),char(111),char(117),char(115),char(78),char(111),char(100),char(101),char(115),char(80),char(116),
+char(114),char(0),char(42),char(109),char(95),char(115),char(117),char(98),char(84),char(114),char(101),char(101),char(73),char(110),char(102),char(111),char(80),char(116),char(114),char(0),
+char(109),char(95),char(116),char(114),char(97),char(118),char(101),char(114),char(115),char(97),char(108),char(77),char(111),char(100),char(101),char(0),char(109),char(95),char(110),char(117),
+char(109),char(83),char(117),char(98),char(116),char(114),char(101),char(101),char(72),char(101),char(97),char(100),char(101),char(114),char(115),char(0),char(42),char(109),char(95),char(110),
+char(97),char(109),char(101),char(0),char(109),char(95),char(115),char(104),char(97),char(112),char(101),char(84),char(121),char(112),char(101),char(0),char(109),char(95),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(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(68),char(97),char(116),char(97),char(0),char(109),char(95),char(108),char(111),char(99),char(97),char(108),char(83),char(99),char(97),
+char(108),char(105),char(110),char(103),char(0),char(109),char(95),char(112),char(108),char(97),char(110),char(101),char(78),char(111),char(114),char(109),char(97),char(108),char(0),char(109),
+char(95),char(112),char(108),char(97),char(110),char(101),char(67),char(111),char(110),char(115),char(116),char(97),char(110),char(116),char(0),char(109),char(95),char(105),char(109),char(112),
+char(108),char(105),char(99),char(105),char(116),char(83),char(104),char(97),char(112),char(101),char(68),char(105),char(109),char(101),char(110),char(115),char(105),char(111),char(110),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(77),char(97),char(114),char(103),char(105),char(110),char(0),char(109),
+char(95),char(112),char(97),char(100),char(100),char(105),char(110),char(103),char(0),char(109),char(95),char(112),char(111),char(115),char(0),char(109),char(95),char(114),char(97),char(100),
+char(105),char(117),char(115),char(0),char(109),char(95),char(99),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(42),char(109),char(95),char(108),char(111),char(99),char(97),char(108),char(80),char(111),
+char(115),char(105),char(116),char(105),char(111),char(110),char(65),char(114),char(114),char(97),char(121),char(80),char(116),char(114),char(0),char(109),char(95),char(108),char(111),char(99),
+char(97),char(108),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(65),char(114),char(114),char(97),char(121),char(83),char(105),char(122),char(101),char(0),
+char(109),char(95),char(118),char(97),char(108),char(117),char(101),char(0),char(109),char(95),char(112),char(97),char(100),char(91),char(50),char(93),char(0),char(109),char(95),char(118),
+char(97),char(108),char(117),char(101),char(115),char(91),char(51),char(93),char(0),char(109),char(95),char(112),char(97),char(100),char(0),char(42),char(109),char(95),char(118),char(101),
+char(114),char(116),char(105),char(99),char(101),char(115),char(51),char(102),char(0),char(42),char(109),char(95),char(118),char(101),char(114),char(116),char(105),char(99),char(101),char(115),
+char(51),char(100),char(0),char(42),char(109),char(95),char(105),char(110),char(100),char(105),char(99),char(101),char(115),char(51),char(50),char(0),char(42),char(109),char(95),char(51),
+char(105),char(110),char(100),char(105),char(99),char(101),char(115),char(49),char(54),char(0),char(42),char(109),char(95),char(51),char(105),char(110),char(100),char(105),char(99),char(101),
+char(115),char(56),char(0),char(42),char(109),char(95),char(105),char(110),char(100),char(105),char(99),char(101),char(115),char(49),char(54),char(0),char(109),char(95),char(110),char(117),
+char(109),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(86),char(101),char(114),char(116),
+char(105),char(99),char(101),char(115),char(0),char(42),char(109),char(95),char(109),char(101),char(115),char(104),char(80),char(97),char(114),char(116),char(115),char(80),char(116),char(114),
+char(0),char(109),char(95),char(115),char(99),char(97),char(108),char(105),char(110),char(103),char(0),char(109),char(95),char(110),char(117),char(109),char(77),char(101),char(115),char(104),
+char(80),char(97),char(114),char(116),char(115),char(0),char(109),char(95),char(109),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(0),char(42),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(70),char(108),char(111),char(97),char(116),char(66),
+char(118),char(104),char(0),char(42),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(68),char(111),char(117),char(98),char(108),
+char(101),char(66),char(118),char(104),char(0),char(42),char(109),char(95),char(116),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(0),char(109),char(95),char(112),char(97),char(100),char(51),char(91),char(52),char(93),char(0),char(109),char(95),char(116),char(114),char(105),char(109),
+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(109),char(95),char(116),char(114),char(97),char(110),char(115),
+char(102),char(111),char(114),char(109),char(0),char(42),char(109),char(95),char(99),char(104),char(105),char(108),char(100),char(83),char(104),char(97),char(112),char(101),char(0),char(109),
+char(95),char(99),char(104),char(105),char(108),char(100),char(83),char(104),char(97),char(112),char(101),char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(99),char(104),
+char(105),char(108),char(100),char(77),char(97),char(114),char(103),char(105),char(110),char(0),char(42),char(109),char(95),char(99),char(104),char(105),char(108),char(100),char(83),char(104),
+char(97),char(112),char(101),char(80),char(116),char(114),char(0),char(109),char(95),char(110),char(117),char(109),char(67),char(104),char(105),char(108),char(100),char(83),char(104),char(97),
+char(112),char(101),char(115),char(0),char(109),char(95),char(117),char(112),char(65),char(120),char(105),char(115),char(0),char(109),char(95),char(102),char(108),char(97),char(103),char(115),
+char(0),char(109),char(95),char(101),char(100),char(103),char(101),char(86),char(48),char(86),char(49),char(65),char(110),char(103),char(108),char(101),char(0),char(109),char(95),char(101),
+char(100),char(103),char(101),char(86),char(49),char(86),char(50),char(65),char(110),char(103),char(108),char(101),char(0),char(109),char(95),char(101),char(100),char(103),char(101),char(86),
+char(50),char(86),char(48),char(65),char(110),char(103),char(108),char(101),char(0),char(42),char(109),char(95),char(104),char(97),char(115),char(104),char(84),char(97),char(98),char(108),
+char(101),char(80),char(116),char(114),char(0),char(42),char(109),char(95),char(110),char(101),char(120),char(116),char(80),char(116),char(114),char(0),char(42),char(109),char(95),char(118),
+char(97),char(108),char(117),char(101),char(65),char(114),char(114),char(97),char(121),char(80),char(116),char(114),char(0),char(42),char(109),char(95),char(107),char(101),char(121),char(65),
+char(114),char(114),char(97),char(121),char(80),char(116),char(114),char(0),char(109),char(95),char(99),char(111),char(110),char(118),char(101),char(120),char(69),char(112),char(115),char(105),
+char(108),char(111),char(110),char(0),char(109),char(95),char(112),char(108),char(97),char(110),char(97),char(114),char(69),char(112),char(115),char(105),char(108),char(111),char(110),char(0),
+char(109),char(95),char(101),char(113),char(117),char(97),char(108),char(86),char(101),char(114),char(116),char(101),char(120),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(101),char(100),char(103),char(101),char(68),char(105),char(115),char(116),char(97),char(110),char(99),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(122),char(101),char(114),char(111),char(65),char(114),char(101),char(97),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(101),char(120),char(116),char(83),char(105),char(122),char(101),char(0),char(109),char(95),
+char(104),char(97),char(115),char(104),char(84),char(97),char(98),char(108),char(101),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(110),char(117),char(109),char(86),
+char(97),char(108),char(117),char(101),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(75),char(101),char(121),char(115),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(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(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(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(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(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(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(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(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(100),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(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(116),char(97),
+char(117),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(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(84),char(89),char(80),char(69),char(76),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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(16),char(0),char(64),char(0),char(68),char(0),char(-48),char(1),char(0),char(1),
+char(-72),char(0),char(-104),char(0),char(104),char(0),char(88),char(0),char(-24),char(1),char(-96),char(3),char(8),char(0),char(52),char(0),char(0),char(0),char(84),char(0),
+char(116),char(0),char(92),char(1),char(-36),char(0),char(-44),char(0),char(-4),char(0),char(92),char(1),char(-52),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(-84),char(1),char(83),char(84),char(82),char(67),
+char(65),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(13),char(0),char(9),char(0),char(16),char(0),char(1),char(0),char(14),char(0),char(9),char(0),
+char(17),char(0),char(2),char(0),char(15),char(0),char(10),char(0),char(13),char(0),char(11),char(0),char(18),char(0),char(2),char(0),char(16),char(0),char(10),char(0),
+char(14),char(0),char(11),char(0),char(19),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(20),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(21),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(22),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(23),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(20),char(0),char(30),char(0),char(22),char(0),char(31),char(0),char(19),char(0),char(32),char(0),
+char(4),char(0),char(33),char(0),char(4),char(0),char(34),char(0),char(24),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(21),char(0),char(30),char(0),char(22),char(0),char(31),char(0),char(4),char(0),char(33),char(0),char(4),char(0),char(34),char(0),char(19),char(0),char(32),char(0),
+char(25),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(26),char(0),char(5),char(0),
+char(25),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(27),char(0),char(5),char(0),char(25),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(28),char(0),char(2),char(0),char(13),char(0),char(45),char(0),char(7),char(0),char(46),char(0),char(29),char(0),char(4),char(0),
+char(27),char(0),char(47),char(0),char(28),char(0),char(48),char(0),char(4),char(0),char(49),char(0),char(0),char(0),char(37),char(0),char(30),char(0),char(1),char(0),
+char(4),char(0),char(50),char(0),char(31),char(0),char(2),char(0),char(2),char(0),char(50),char(0),char(0),char(0),char(51),char(0),char(32),char(0),char(2),char(0),
+char(2),char(0),char(52),char(0),char(0),char(0),char(51),char(0),char(33),char(0),char(2),char(0),char(0),char(0),char(52),char(0),char(0),char(0),char(53),char(0),
+char(34),char(0),char(8),char(0),char(13),char(0),char(54),char(0),char(14),char(0),char(55),char(0),char(30),char(0),char(56),char(0),char(32),char(0),char(57),char(0),
+char(33),char(0),char(58),char(0),char(31),char(0),char(59),char(0),char(4),char(0),char(60),char(0),char(4),char(0),char(61),char(0),char(35),char(0),char(4),char(0),
+char(34),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(36),char(0),char(7),char(0),
+char(25),char(0),char(38),char(0),char(35),char(0),char(65),char(0),char(23),char(0),char(66),char(0),char(24),char(0),char(67),char(0),char(37),char(0),char(68),char(0),
+char(7),char(0),char(43),char(0),char(0),char(0),char(69),char(0),char(38),char(0),char(2),char(0),char(36),char(0),char(70),char(0),char(13),char(0),char(39),char(0),
+char(39),char(0),char(4),char(0),char(17),char(0),char(71),char(0),char(25),char(0),char(72),char(0),char(4),char(0),char(73),char(0),char(7),char(0),char(74),char(0),
+char(40),char(0),char(4),char(0),char(25),char(0),char(38),char(0),char(39),char(0),char(75),char(0),char(4),char(0),char(76),char(0),char(7),char(0),char(43),char(0),
+char(41),char(0),char(3),char(0),char(27),char(0),char(47),char(0),char(4),char(0),char(77),char(0),char(0),char(0),char(37),char(0),char(42),char(0),char(3),char(0),
+char(27),char(0),char(47),char(0),char(4),char(0),char(77),char(0),char(0),char(0),char(37),char(0),char(43),char(0),char(4),char(0),char(4),char(0),char(78),char(0),
+char(7),char(0),char(79),char(0),char(7),char(0),char(80),char(0),char(7),char(0),char(81),char(0),char(37),char(0),char(14),char(0),char(4),char(0),char(82),char(0),
+char(4),char(0),char(83),char(0),char(43),char(0),char(84),char(0),char(4),char(0),char(85),char(0),char(7),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(4),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(0),char(0),char(37),char(0),char(44),char(0),char(5),char(0),char(25),char(0),char(38),char(0),
+char(35),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(95),char(0),char(45),char(0),char(5),char(0),
+char(27),char(0),char(47),char(0),char(13),char(0),char(96),char(0),char(14),char(0),char(97),char(0),char(4),char(0),char(98),char(0),char(0),char(0),char(99),char(0),
+char(46),char(0),char(25),char(0),char(9),char(0),char(100),char(0),char(9),char(0),char(101),char(0),char(25),char(0),char(102),char(0),char(0),char(0),char(35),char(0),
+char(18),char(0),char(103),char(0),char(18),char(0),char(104),char(0),char(14),char(0),char(105),char(0),char(14),char(0),char(106),char(0),char(14),char(0),char(107),char(0),
+char(8),char(0),char(108),char(0),char(8),char(0),char(109),char(0),char(8),char(0),char(110),char(0),char(8),char(0),char(111),char(0),char(8),char(0),char(112),char(0),
+char(8),char(0),char(113),char(0),char(8),char(0),char(114),char(0),char(8),char(0),char(115),char(0),char(4),char(0),char(116),char(0),char(4),char(0),char(117),char(0),
+char(4),char(0),char(118),char(0),char(4),char(0),char(119),char(0),char(4),char(0),char(120),char(0),char(4),char(0),char(121),char(0),char(4),char(0),char(122),char(0),
+char(0),char(0),char(37),char(0),char(47),char(0),char(25),char(0),char(9),char(0),char(100),char(0),char(9),char(0),char(101),char(0),char(25),char(0),char(102),char(0),
+char(0),char(0),char(35),char(0),char(17),char(0),char(103),char(0),char(17),char(0),char(104),char(0),char(13),char(0),char(105),char(0),char(13),char(0),char(106),char(0),
+char(13),char(0),char(107),char(0),char(7),char(0),char(108),char(0),char(7),char(0),char(109),char(0),char(7),char(0),char(110),char(0),char(7),char(0),char(111),char(0),
+char(7),char(0),char(112),char(0),char(7),char(0),char(113),char(0),char(7),char(0),char(114),char(0),char(7),char(0),char(115),char(0),char(4),char(0),char(116),char(0),
+char(4),char(0),char(117),char(0),char(4),char(0),char(118),char(0),char(4),char(0),char(119),char(0),char(4),char(0),char(120),char(0),char(4),char(0),char(121),char(0),
+char(4),char(0),char(122),char(0),char(0),char(0),char(37),char(0),char(48),char(0),char(2),char(0),char(49),char(0),char(123),char(0),char(14),char(0),char(124),char(0),
+char(50),char(0),char(2),char(0),char(51),char(0),char(123),char(0),char(13),char(0),char(124),char(0),char(52),char(0),char(21),char(0),char(47),char(0),char(125),char(0),
+char(15),char(0),char(126),char(0),char(13),char(0),char(127),char(0),char(13),char(0),char(-128),char(0),char(13),char(0),char(-127),char(0),char(13),char(0),char(-126),char(0),
+char(13),char(0),char(124),char(0),char(13),char(0),char(-125),char(0),char(13),char(0),char(-124),char(0),char(13),char(0),char(-123),char(0),char(13),char(0),char(-122),char(0),
+char(7),char(0),char(-121),char(0),char(7),char(0),char(-120),char(0),char(7),char(0),char(-119),char(0),char(7),char(0),char(-118),char(0),char(7),char(0),char(-117),char(0),
+char(7),char(0),char(-116),char(0),char(7),char(0),char(-115),char(0),char(7),char(0),char(-114),char(0),char(7),char(0),char(-113),char(0),char(4),char(0),char(-112),char(0),
+char(53),char(0),char(22),char(0),char(46),char(0),char(125),char(0),char(16),char(0),char(126),char(0),char(14),char(0),char(127),char(0),char(14),char(0),char(-128),char(0),
+char(14),char(0),char(-127),char(0),char(14),char(0),char(-126),char(0),char(14),char(0),char(124),char(0),char(14),char(0),char(-125),char(0),char(14),char(0),char(-124),char(0),
+char(14),char(0),char(-123),char(0),char(14),char(0),char(-122),char(0),char(8),char(0),char(-121),char(0),char(8),char(0),char(-120),char(0),char(8),char(0),char(-119),char(0),
+char(8),char(0),char(-118),char(0),char(8),char(0),char(-117),char(0),char(8),char(0),char(-116),char(0),char(8),char(0),char(-115),char(0),char(8),char(0),char(-114),char(0),
+char(8),char(0),char(-113),char(0),char(4),char(0),char(-112),char(0),char(0),char(0),char(37),char(0),char(54),char(0),char(2),char(0),char(4),char(0),char(-111),char(0),
+char(4),char(0),char(-110),char(0),char(55),char(0),char(13),char(0),char(56),char(0),char(-109),char(0),char(56),char(0),char(-108),char(0),char(0),char(0),char(35),char(0),
+char(4),char(0),char(-107),char(0),char(4),char(0),char(-106),char(0),char(4),char(0),char(-105),char(0),char(4),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(7),char(0),char(-99),char(0),char(4),char(0),char(-98),char(0),
+char(57),char(0),char(3),char(0),char(55),char(0),char(-97),char(0),char(13),char(0),char(-96),char(0),char(13),char(0),char(-95),char(0),char(58),char(0),char(3),char(0),
+char(55),char(0),char(-97),char(0),char(14),char(0),char(-96),char(0),char(14),char(0),char(-95),char(0),char(59),char(0),char(13),char(0),char(55),char(0),char(-97),char(0),
+char(18),char(0),char(-94),char(0),char(18),char(0),char(-93),char(0),char(4),char(0),char(-92),char(0),char(4),char(0),char(-91),char(0),char(4),char(0),char(-90),char(0),
+char(7),char(0),char(-89),char(0),char(7),char(0),char(-88),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(60),char(0),char(13),char(0),char(55),char(0),char(-97),char(0),char(17),char(0),char(-94),char(0),
+char(17),char(0),char(-93),char(0),char(4),char(0),char(-92),char(0),char(4),char(0),char(-91),char(0),char(4),char(0),char(-90),char(0),char(7),char(0),char(-89),char(0),
+char(7),char(0),char(-88),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(61),char(0),char(11),char(0),char(55),char(0),char(-97),char(0),char(17),char(0),char(-94),char(0),char(17),char(0),char(-93),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(-85),char(0),char(7),char(0),char(-84),char(0),
+char(7),char(0),char(-83),char(0),char(7),char(0),char(-79),char(0),char(0),char(0),char(21),char(0),char(62),char(0),char(9),char(0),char(55),char(0),char(-97),char(0),
+char(17),char(0),char(-94),char(0),char(17),char(0),char(-93),char(0),char(13),char(0),char(-78),char(0),char(13),char(0),char(-77),char(0),char(13),char(0),char(-76),char(0),
+char(13),char(0),char(-75),char(0),char(4),char(0),char(-74),char(0),char(4),char(0),char(-73),char(0),char(63),char(0),char(5),char(0),char(62),char(0),char(-72),char(0),
+char(4),char(0),char(-71),char(0),char(7),char(0),char(-70),char(0),char(7),char(0),char(-69),char(0),char(7),char(0),char(-68),char(0),char(64),char(0),char(9),char(0),
+char(55),char(0),char(-97),char(0),char(17),char(0),char(-94),char(0),char(17),char(0),char(-93),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(7),char(0),char(-75),char(0),char(4),char(0),char(-74),char(0),char(4),char(0),char(-73),char(0),char(49),char(0),char(22),char(0),
+char(8),char(0),char(-67),char(0),char(8),char(0),char(-79),char(0),char(8),char(0),char(110),char(0),char(8),char(0),char(-66),char(0),char(8),char(0),char(112),char(0),
+char(8),char(0),char(-65),char(0),char(8),char(0),char(-64),char(0),char(8),char(0),char(-63),char(0),char(8),char(0),char(-62),char(0),char(8),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(4),char(0),char(-54),char(0),char(4),char(0),char(-53),char(0),char(4),char(0),char(-52),char(0),char(4),char(0),char(-51),char(0),
+char(4),char(0),char(-50),char(0),char(0),char(0),char(37),char(0),char(51),char(0),char(22),char(0),char(7),char(0),char(-67),char(0),char(7),char(0),char(-79),char(0),
+char(7),char(0),char(110),char(0),char(7),char(0),char(-66),char(0),char(7),char(0),char(112),char(0),char(7),char(0),char(-65),char(0),char(7),char(0),char(-64),char(0),
+char(7),char(0),char(-63),char(0),char(7),char(0),char(-62),char(0),char(7),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(4),char(0),char(-54),char(0),
+char(4),char(0),char(-53),char(0),char(4),char(0),char(-52),char(0),char(4),char(0),char(-51),char(0),char(4),char(0),char(-50),char(0),char(0),char(0),char(37),char(0),
+char(65),char(0),char(4),char(0),char(7),char(0),char(-49),char(0),char(7),char(0),char(-48),char(0),char(7),char(0),char(-47),char(0),char(4),char(0),char(78),char(0),
+char(66),char(0),char(10),char(0),char(65),char(0),char(-46),char(0),char(13),char(0),char(-45),char(0),char(13),char(0),char(-44),char(0),char(13),char(0),char(-43),char(0),
+char(13),char(0),char(-42),char(0),char(13),char(0),char(-41),char(0),char(7),char(0),char(-121),char(0),char(7),char(0),char(-40),char(0),char(4),char(0),char(-39),char(0),
+char(4),char(0),char(53),char(0),char(67),char(0),char(4),char(0),char(65),char(0),char(-46),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(68),char(0),char(4),char(0),char(13),char(0),char(-41),char(0),char(65),char(0),char(-46),char(0),char(4),char(0),char(-35),char(0),
+char(7),char(0),char(-34),char(0),char(69),char(0),char(7),char(0),char(13),char(0),char(-33),char(0),char(65),char(0),char(-46),char(0),char(4),char(0),char(-32),char(0),
+char(7),char(0),char(-31),char(0),char(7),char(0),char(-30),char(0),char(7),char(0),char(-29),char(0),char(4),char(0),char(53),char(0),char(70),char(0),char(6),char(0),
+char(15),char(0),char(-28),char(0),char(13),char(0),char(-30),char(0),char(13),char(0),char(-27),char(0),char(56),char(0),char(-26),char(0),char(4),char(0),char(-25),char(0),
+char(7),char(0),char(-29),char(0),char(71),char(0),char(26),char(0),char(4),char(0),char(-24),char(0),char(7),char(0),char(-23),char(0),char(7),char(0),char(-79),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(-19),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(-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(7),char(0),char(-11),char(0),char(7),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(7),char(0),char(-6),char(0),char(7),char(0),char(-5),char(0),char(4),char(0),char(-4),char(0),char(4),char(0),char(-3),char(0),
+char(4),char(0),char(-2),char(0),char(4),char(0),char(-1),char(0),char(4),char(0),char(117),char(0),char(72),char(0),char(12),char(0),char(15),char(0),char(0),char(1),
+char(15),char(0),char(1),char(1),char(15),char(0),char(2),char(1),char(13),char(0),char(3),char(1),char(13),char(0),char(4),char(1),char(7),char(0),char(5),char(1),
+char(4),char(0),char(6),char(1),char(4),char(0),char(7),char(1),char(4),char(0),char(8),char(1),char(4),char(0),char(9),char(1),char(7),char(0),char(-31),char(0),
+char(4),char(0),char(53),char(0),char(73),char(0),char(27),char(0),char(17),char(0),char(10),char(1),char(15),char(0),char(11),char(1),char(15),char(0),char(12),char(1),
+char(13),char(0),char(3),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(4),char(0),char(18),char(1),char(7),char(0),char(19),char(1),char(4),char(0),char(20),char(1),char(4),char(0),char(21),char(1),
+char(4),char(0),char(22),char(1),char(7),char(0),char(23),char(1),char(7),char(0),char(24),char(1),char(4),char(0),char(25),char(1),char(4),char(0),char(26),char(1),
+char(7),char(0),char(27),char(1),char(7),char(0),char(28),char(1),char(7),char(0),char(29),char(1),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(33),char(1),char(4),char(0),char(34),char(1),char(4),char(0),char(35),char(1),char(74),char(0),char(12),char(0),
+char(9),char(0),char(36),char(1),char(9),char(0),char(37),char(1),char(13),char(0),char(38),char(1),char(7),char(0),char(39),char(1),char(7),char(0),char(-63),char(0),
+char(7),char(0),char(40),char(1),char(4),char(0),char(41),char(1),char(13),char(0),char(42),char(1),char(4),char(0),char(43),char(1),char(4),char(0),char(44),char(1),
+char(4),char(0),char(45),char(1),char(4),char(0),char(53),char(0),char(75),char(0),char(19),char(0),char(47),char(0),char(125),char(0),char(72),char(0),char(46),char(1),
+char(65),char(0),char(47),char(1),char(66),char(0),char(48),char(1),char(67),char(0),char(49),char(1),char(68),char(0),char(50),char(1),char(69),char(0),char(51),char(1),
+char(70),char(0),char(52),char(1),char(73),char(0),char(53),char(1),char(74),char(0),char(54),char(1),char(4),char(0),char(55),char(1),char(4),char(0),char(21),char(1),
+char(4),char(0),char(56),char(1),char(4),char(0),char(57),char(1),char(4),char(0),char(58),char(1),char(4),char(0),char(59),char(1),char(4),char(0),char(60),char(1),
+char(4),char(0),char(61),char(1),char(71),char(0),char(62),char(1),};
+int b3s_bulletDNAlen= sizeof(b3s_bulletDNAstr);
+char b3s_bulletDNAstr64[]= {
+char(83),char(68),char(78),char(65),char(78),char(65),char(77),char(69),char(63),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),
+char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(115),char(0),char(42),char(102),char(105),char(114),char(115),char(116),char(0),char(42),char(108),char(97),char(115),
+char(116),char(0),char(109),char(95),char(102),char(108),char(111),char(97),char(116),char(115),char(91),char(52),char(93),char(0),char(109),char(95),char(101),char(108),char(91),char(51),
+char(93),char(0),char(109),char(95),char(98),char(97),char(115),char(105),char(115),char(0),char(109),char(95),char(111),char(114),char(105),char(103),char(105),char(110),char(0),char(109),
+char(95),char(114),char(111),char(111),char(116),char(78),char(111),char(100),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(115),char(117),char(98),
+char(116),char(114),char(101),char(101),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),
+char(65),char(97),char(98),char(98),char(77),char(105),char(110),char(91),char(51),char(93),char(0),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),char(122),
+char(101),char(100),char(65),char(97),char(98),char(98),char(77),char(97),char(120),char(91),char(51),char(93),char(0),char(109),char(95),char(97),char(97),char(98),char(98),char(77),
+char(105),char(110),char(79),char(114),char(103),char(0),char(109),char(95),char(97),char(97),char(98),char(98),char(77),char(97),char(120),char(79),char(114),char(103),char(0),char(109),
+char(95),char(101),char(115),char(99),char(97),char(112),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(115),char(117),char(98),char(80),char(97),
+char(114),char(116),char(0),char(109),char(95),char(116),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),
+char(95),char(112),char(97),char(100),char(91),char(52),char(93),char(0),char(109),char(95),char(101),char(115),char(99),char(97),char(112),char(101),char(73),char(110),char(100),char(101),
+char(120),char(79),char(114),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(98),
+char(118),char(104),char(65),char(97),char(98),char(98),char(77),char(105),char(110),char(0),char(109),char(95),char(98),char(118),char(104),char(65),char(97),char(98),char(98),char(77),
+char(97),char(120),char(0),char(109),char(95),char(98),char(118),char(104),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(97),char(116),char(105),char(111),char(110),
+char(0),char(109),char(95),char(99),char(117),char(114),char(78),char(111),char(100),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(117),char(115),
+char(101),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(97),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(110),char(117),char(109),char(67),
+char(111),char(110),char(116),char(105),char(103),char(117),char(111),char(117),char(115),char(76),char(101),char(97),char(102),char(78),char(111),char(100),char(101),char(115),char(0),char(109),
+char(95),char(110),char(117),char(109),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(67),char(111),char(110),char(116),char(105),char(103),char(117),
+char(111),char(117),char(115),char(78),char(111),char(100),char(101),char(115),char(0),char(42),char(109),char(95),char(99),char(111),char(110),char(116),char(105),char(103),char(117),char(111),
+char(117),char(115),char(78),char(111),char(100),char(101),char(115),char(80),char(116),char(114),char(0),char(42),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),
+char(122),char(101),char(100),char(67),char(111),char(110),char(116),char(105),char(103),char(117),char(111),char(117),char(115),char(78),char(111),char(100),char(101),char(115),char(80),char(116),
+char(114),char(0),char(42),char(109),char(95),char(115),char(117),char(98),char(84),char(114),char(101),char(101),char(73),char(110),char(102),char(111),char(80),char(116),char(114),char(0),
+char(109),char(95),char(116),char(114),char(97),char(118),char(101),char(114),char(115),char(97),char(108),char(77),char(111),char(100),char(101),char(0),char(109),char(95),char(110),char(117),
+char(109),char(83),char(117),char(98),char(116),char(114),char(101),char(101),char(72),char(101),char(97),char(100),char(101),char(114),char(115),char(0),char(42),char(109),char(95),char(110),
+char(97),char(109),char(101),char(0),char(109),char(95),char(115),char(104),char(97),char(112),char(101),char(84),char(121),char(112),char(101),char(0),char(109),char(95),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(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(68),char(97),char(116),char(97),char(0),char(109),char(95),char(108),char(111),char(99),char(97),char(108),char(83),char(99),char(97),
+char(108),char(105),char(110),char(103),char(0),char(109),char(95),char(112),char(108),char(97),char(110),char(101),char(78),char(111),char(114),char(109),char(97),char(108),char(0),char(109),
+char(95),char(112),char(108),char(97),char(110),char(101),char(67),char(111),char(110),char(115),char(116),char(97),char(110),char(116),char(0),char(109),char(95),char(105),char(109),char(112),
+char(108),char(105),char(99),char(105),char(116),char(83),char(104),char(97),char(112),char(101),char(68),char(105),char(109),char(101),char(110),char(115),char(105),char(111),char(110),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(77),char(97),char(114),char(103),char(105),char(110),char(0),char(109),
+char(95),char(112),char(97),char(100),char(100),char(105),char(110),char(103),char(0),char(109),char(95),char(112),char(111),char(115),char(0),char(109),char(95),char(114),char(97),char(100),
+char(105),char(117),char(115),char(0),char(109),char(95),char(99),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(42),char(109),char(95),char(108),char(111),char(99),char(97),char(108),char(80),char(111),
+char(115),char(105),char(116),char(105),char(111),char(110),char(65),char(114),char(114),char(97),char(121),char(80),char(116),char(114),char(0),char(109),char(95),char(108),char(111),char(99),
+char(97),char(108),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(65),char(114),char(114),char(97),char(121),char(83),char(105),char(122),char(101),char(0),
+char(109),char(95),char(118),char(97),char(108),char(117),char(101),char(0),char(109),char(95),char(112),char(97),char(100),char(91),char(50),char(93),char(0),char(109),char(95),char(118),
+char(97),char(108),char(117),char(101),char(115),char(91),char(51),char(93),char(0),char(109),char(95),char(112),char(97),char(100),char(0),char(42),char(109),char(95),char(118),char(101),
+char(114),char(116),char(105),char(99),char(101),char(115),char(51),char(102),char(0),char(42),char(109),char(95),char(118),char(101),char(114),char(116),char(105),char(99),char(101),char(115),
+char(51),char(100),char(0),char(42),char(109),char(95),char(105),char(110),char(100),char(105),char(99),char(101),char(115),char(51),char(50),char(0),char(42),char(109),char(95),char(51),
+char(105),char(110),char(100),char(105),char(99),char(101),char(115),char(49),char(54),char(0),char(42),char(109),char(95),char(51),char(105),char(110),char(100),char(105),char(99),char(101),
+char(115),char(56),char(0),char(42),char(109),char(95),char(105),char(110),char(100),char(105),char(99),char(101),char(115),char(49),char(54),char(0),char(109),char(95),char(110),char(117),
+char(109),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(86),char(101),char(114),char(116),
+char(105),char(99),char(101),char(115),char(0),char(42),char(109),char(95),char(109),char(101),char(115),char(104),char(80),char(97),char(114),char(116),char(115),char(80),char(116),char(114),
+char(0),char(109),char(95),char(115),char(99),char(97),char(108),char(105),char(110),char(103),char(0),char(109),char(95),char(110),char(117),char(109),char(77),char(101),char(115),char(104),
+char(80),char(97),char(114),char(116),char(115),char(0),char(109),char(95),char(109),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(0),char(42),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(70),char(108),char(111),char(97),char(116),char(66),
+char(118),char(104),char(0),char(42),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(68),char(111),char(117),char(98),char(108),
+char(101),char(66),char(118),char(104),char(0),char(42),char(109),char(95),char(116),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(0),char(109),char(95),char(112),char(97),char(100),char(51),char(91),char(52),char(93),char(0),char(109),char(95),char(116),char(114),char(105),char(109),
+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(109),char(95),char(116),char(114),char(97),char(110),char(115),
+char(102),char(111),char(114),char(109),char(0),char(42),char(109),char(95),char(99),char(104),char(105),char(108),char(100),char(83),char(104),char(97),char(112),char(101),char(0),char(109),
+char(95),char(99),char(104),char(105),char(108),char(100),char(83),char(104),char(97),char(112),char(101),char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(99),char(104),
+char(105),char(108),char(100),char(77),char(97),char(114),char(103),char(105),char(110),char(0),char(42),char(109),char(95),char(99),char(104),char(105),char(108),char(100),char(83),char(104),
+char(97),char(112),char(101),char(80),char(116),char(114),char(0),char(109),char(95),char(110),char(117),char(109),char(67),char(104),char(105),char(108),char(100),char(83),char(104),char(97),
+char(112),char(101),char(115),char(0),char(109),char(95),char(117),char(112),char(65),char(120),char(105),char(115),char(0),char(109),char(95),char(102),char(108),char(97),char(103),char(115),
+char(0),char(109),char(95),char(101),char(100),char(103),char(101),char(86),char(48),char(86),char(49),char(65),char(110),char(103),char(108),char(101),char(0),char(109),char(95),char(101),
+char(100),char(103),char(101),char(86),char(49),char(86),char(50),char(65),char(110),char(103),char(108),char(101),char(0),char(109),char(95),char(101),char(100),char(103),char(101),char(86),
+char(50),char(86),char(48),char(65),char(110),char(103),char(108),char(101),char(0),char(42),char(109),char(95),char(104),char(97),char(115),char(104),char(84),char(97),char(98),char(108),
+char(101),char(80),char(116),char(114),char(0),char(42),char(109),char(95),char(110),char(101),char(120),char(116),char(80),char(116),char(114),char(0),char(42),char(109),char(95),char(118),
+char(97),char(108),char(117),char(101),char(65),char(114),char(114),char(97),char(121),char(80),char(116),char(114),char(0),char(42),char(109),char(95),char(107),char(101),char(121),char(65),
+char(114),char(114),char(97),char(121),char(80),char(116),char(114),char(0),char(109),char(95),char(99),char(111),char(110),char(118),char(101),char(120),char(69),char(112),char(115),char(105),
+char(108),char(111),char(110),char(0),char(109),char(95),char(112),char(108),char(97),char(110),char(97),char(114),char(69),char(112),char(115),char(105),char(108),char(111),char(110),char(0),
+char(109),char(95),char(101),char(113),char(117),char(97),char(108),char(86),char(101),char(114),char(116),char(101),char(120),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(101),char(100),char(103),char(101),char(68),char(105),char(115),char(116),char(97),char(110),char(99),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(122),char(101),char(114),char(111),char(65),char(114),char(101),char(97),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(101),char(120),char(116),char(83),char(105),char(122),char(101),char(0),char(109),char(95),
+char(104),char(97),char(115),char(104),char(84),char(97),char(98),char(108),char(101),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(110),char(117),char(109),char(86),
+char(97),char(108),char(117),char(101),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(75),char(101),char(121),char(115),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(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(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(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(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(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(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(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(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(100),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(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(116),char(97),
+char(117),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(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(84),char(89),char(80),char(69),char(76),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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(16),char(0),char(72),char(0),char(80),char(0),char(-32),char(1),char(16),char(1),
+char(-72),char(0),char(-104),char(0),char(104),char(0),char(88),char(0),char(-8),char(1),char(-80),char(3),char(8),char(0),char(64),char(0),char(0),char(0),char(96),char(0),
+char(-128),char(0),char(104),char(1),char(-24),char(0),char(-32),char(0),char(8),char(1),char(104),char(1),char(-40),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(-32),char(1),char(83),char(84),char(82),char(67),
+char(65),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(13),char(0),char(9),char(0),char(16),char(0),char(1),char(0),char(14),char(0),char(9),char(0),
+char(17),char(0),char(2),char(0),char(15),char(0),char(10),char(0),char(13),char(0),char(11),char(0),char(18),char(0),char(2),char(0),char(16),char(0),char(10),char(0),
+char(14),char(0),char(11),char(0),char(19),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(20),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(21),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(22),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(23),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(20),char(0),char(30),char(0),char(22),char(0),char(31),char(0),char(19),char(0),char(32),char(0),
+char(4),char(0),char(33),char(0),char(4),char(0),char(34),char(0),char(24),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(21),char(0),char(30),char(0),char(22),char(0),char(31),char(0),char(4),char(0),char(33),char(0),char(4),char(0),char(34),char(0),char(19),char(0),char(32),char(0),
+char(25),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(26),char(0),char(5),char(0),
+char(25),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(27),char(0),char(5),char(0),char(25),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(28),char(0),char(2),char(0),char(13),char(0),char(45),char(0),char(7),char(0),char(46),char(0),char(29),char(0),char(4),char(0),
+char(27),char(0),char(47),char(0),char(28),char(0),char(48),char(0),char(4),char(0),char(49),char(0),char(0),char(0),char(37),char(0),char(30),char(0),char(1),char(0),
+char(4),char(0),char(50),char(0),char(31),char(0),char(2),char(0),char(2),char(0),char(50),char(0),char(0),char(0),char(51),char(0),char(32),char(0),char(2),char(0),
+char(2),char(0),char(52),char(0),char(0),char(0),char(51),char(0),char(33),char(0),char(2),char(0),char(0),char(0),char(52),char(0),char(0),char(0),char(53),char(0),
+char(34),char(0),char(8),char(0),char(13),char(0),char(54),char(0),char(14),char(0),char(55),char(0),char(30),char(0),char(56),char(0),char(32),char(0),char(57),char(0),
+char(33),char(0),char(58),char(0),char(31),char(0),char(59),char(0),char(4),char(0),char(60),char(0),char(4),char(0),char(61),char(0),char(35),char(0),char(4),char(0),
+char(34),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(36),char(0),char(7),char(0),
+char(25),char(0),char(38),char(0),char(35),char(0),char(65),char(0),char(23),char(0),char(66),char(0),char(24),char(0),char(67),char(0),char(37),char(0),char(68),char(0),
+char(7),char(0),char(43),char(0),char(0),char(0),char(69),char(0),char(38),char(0),char(2),char(0),char(36),char(0),char(70),char(0),char(13),char(0),char(39),char(0),
+char(39),char(0),char(4),char(0),char(17),char(0),char(71),char(0),char(25),char(0),char(72),char(0),char(4),char(0),char(73),char(0),char(7),char(0),char(74),char(0),
+char(40),char(0),char(4),char(0),char(25),char(0),char(38),char(0),char(39),char(0),char(75),char(0),char(4),char(0),char(76),char(0),char(7),char(0),char(43),char(0),
+char(41),char(0),char(3),char(0),char(27),char(0),char(47),char(0),char(4),char(0),char(77),char(0),char(0),char(0),char(37),char(0),char(42),char(0),char(3),char(0),
+char(27),char(0),char(47),char(0),char(4),char(0),char(77),char(0),char(0),char(0),char(37),char(0),char(43),char(0),char(4),char(0),char(4),char(0),char(78),char(0),
+char(7),char(0),char(79),char(0),char(7),char(0),char(80),char(0),char(7),char(0),char(81),char(0),char(37),char(0),char(14),char(0),char(4),char(0),char(82),char(0),
+char(4),char(0),char(83),char(0),char(43),char(0),char(84),char(0),char(4),char(0),char(85),char(0),char(7),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(4),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(0),char(0),char(37),char(0),char(44),char(0),char(5),char(0),char(25),char(0),char(38),char(0),
+char(35),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(95),char(0),char(45),char(0),char(5),char(0),
+char(27),char(0),char(47),char(0),char(13),char(0),char(96),char(0),char(14),char(0),char(97),char(0),char(4),char(0),char(98),char(0),char(0),char(0),char(99),char(0),
+char(46),char(0),char(25),char(0),char(9),char(0),char(100),char(0),char(9),char(0),char(101),char(0),char(25),char(0),char(102),char(0),char(0),char(0),char(35),char(0),
+char(18),char(0),char(103),char(0),char(18),char(0),char(104),char(0),char(14),char(0),char(105),char(0),char(14),char(0),char(106),char(0),char(14),char(0),char(107),char(0),
+char(8),char(0),char(108),char(0),char(8),char(0),char(109),char(0),char(8),char(0),char(110),char(0),char(8),char(0),char(111),char(0),char(8),char(0),char(112),char(0),
+char(8),char(0),char(113),char(0),char(8),char(0),char(114),char(0),char(8),char(0),char(115),char(0),char(4),char(0),char(116),char(0),char(4),char(0),char(117),char(0),
+char(4),char(0),char(118),char(0),char(4),char(0),char(119),char(0),char(4),char(0),char(120),char(0),char(4),char(0),char(121),char(0),char(4),char(0),char(122),char(0),
+char(0),char(0),char(37),char(0),char(47),char(0),char(25),char(0),char(9),char(0),char(100),char(0),char(9),char(0),char(101),char(0),char(25),char(0),char(102),char(0),
+char(0),char(0),char(35),char(0),char(17),char(0),char(103),char(0),char(17),char(0),char(104),char(0),char(13),char(0),char(105),char(0),char(13),char(0),char(106),char(0),
+char(13),char(0),char(107),char(0),char(7),char(0),char(108),char(0),char(7),char(0),char(109),char(0),char(7),char(0),char(110),char(0),char(7),char(0),char(111),char(0),
+char(7),char(0),char(112),char(0),char(7),char(0),char(113),char(0),char(7),char(0),char(114),char(0),char(7),char(0),char(115),char(0),char(4),char(0),char(116),char(0),
+char(4),char(0),char(117),char(0),char(4),char(0),char(118),char(0),char(4),char(0),char(119),char(0),char(4),char(0),char(120),char(0),char(4),char(0),char(121),char(0),
+char(4),char(0),char(122),char(0),char(0),char(0),char(37),char(0),char(48),char(0),char(2),char(0),char(49),char(0),char(123),char(0),char(14),char(0),char(124),char(0),
+char(50),char(0),char(2),char(0),char(51),char(0),char(123),char(0),char(13),char(0),char(124),char(0),char(52),char(0),char(21),char(0),char(47),char(0),char(125),char(0),
+char(15),char(0),char(126),char(0),char(13),char(0),char(127),char(0),char(13),char(0),char(-128),char(0),char(13),char(0),char(-127),char(0),char(13),char(0),char(-126),char(0),
+char(13),char(0),char(124),char(0),char(13),char(0),char(-125),char(0),char(13),char(0),char(-124),char(0),char(13),char(0),char(-123),char(0),char(13),char(0),char(-122),char(0),
+char(7),char(0),char(-121),char(0),char(7),char(0),char(-120),char(0),char(7),char(0),char(-119),char(0),char(7),char(0),char(-118),char(0),char(7),char(0),char(-117),char(0),
+char(7),char(0),char(-116),char(0),char(7),char(0),char(-115),char(0),char(7),char(0),char(-114),char(0),char(7),char(0),char(-113),char(0),char(4),char(0),char(-112),char(0),
+char(53),char(0),char(22),char(0),char(46),char(0),char(125),char(0),char(16),char(0),char(126),char(0),char(14),char(0),char(127),char(0),char(14),char(0),char(-128),char(0),
+char(14),char(0),char(-127),char(0),char(14),char(0),char(-126),char(0),char(14),char(0),char(124),char(0),char(14),char(0),char(-125),char(0),char(14),char(0),char(-124),char(0),
+char(14),char(0),char(-123),char(0),char(14),char(0),char(-122),char(0),char(8),char(0),char(-121),char(0),char(8),char(0),char(-120),char(0),char(8),char(0),char(-119),char(0),
+char(8),char(0),char(-118),char(0),char(8),char(0),char(-117),char(0),char(8),char(0),char(-116),char(0),char(8),char(0),char(-115),char(0),char(8),char(0),char(-114),char(0),
+char(8),char(0),char(-113),char(0),char(4),char(0),char(-112),char(0),char(0),char(0),char(37),char(0),char(54),char(0),char(2),char(0),char(4),char(0),char(-111),char(0),
+char(4),char(0),char(-110),char(0),char(55),char(0),char(13),char(0),char(56),char(0),char(-109),char(0),char(56),char(0),char(-108),char(0),char(0),char(0),char(35),char(0),
+char(4),char(0),char(-107),char(0),char(4),char(0),char(-106),char(0),char(4),char(0),char(-105),char(0),char(4),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(7),char(0),char(-99),char(0),char(4),char(0),char(-98),char(0),
+char(57),char(0),char(3),char(0),char(55),char(0),char(-97),char(0),char(13),char(0),char(-96),char(0),char(13),char(0),char(-95),char(0),char(58),char(0),char(3),char(0),
+char(55),char(0),char(-97),char(0),char(14),char(0),char(-96),char(0),char(14),char(0),char(-95),char(0),char(59),char(0),char(13),char(0),char(55),char(0),char(-97),char(0),
+char(18),char(0),char(-94),char(0),char(18),char(0),char(-93),char(0),char(4),char(0),char(-92),char(0),char(4),char(0),char(-91),char(0),char(4),char(0),char(-90),char(0),
+char(7),char(0),char(-89),char(0),char(7),char(0),char(-88),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(60),char(0),char(13),char(0),char(55),char(0),char(-97),char(0),char(17),char(0),char(-94),char(0),
+char(17),char(0),char(-93),char(0),char(4),char(0),char(-92),char(0),char(4),char(0),char(-91),char(0),char(4),char(0),char(-90),char(0),char(7),char(0),char(-89),char(0),
+char(7),char(0),char(-88),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(61),char(0),char(11),char(0),char(55),char(0),char(-97),char(0),char(17),char(0),char(-94),char(0),char(17),char(0),char(-93),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(-85),char(0),char(7),char(0),char(-84),char(0),
+char(7),char(0),char(-83),char(0),char(7),char(0),char(-79),char(0),char(0),char(0),char(21),char(0),char(62),char(0),char(9),char(0),char(55),char(0),char(-97),char(0),
+char(17),char(0),char(-94),char(0),char(17),char(0),char(-93),char(0),char(13),char(0),char(-78),char(0),char(13),char(0),char(-77),char(0),char(13),char(0),char(-76),char(0),
+char(13),char(0),char(-75),char(0),char(4),char(0),char(-74),char(0),char(4),char(0),char(-73),char(0),char(63),char(0),char(5),char(0),char(62),char(0),char(-72),char(0),
+char(4),char(0),char(-71),char(0),char(7),char(0),char(-70),char(0),char(7),char(0),char(-69),char(0),char(7),char(0),char(-68),char(0),char(64),char(0),char(9),char(0),
+char(55),char(0),char(-97),char(0),char(17),char(0),char(-94),char(0),char(17),char(0),char(-93),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(7),char(0),char(-75),char(0),char(4),char(0),char(-74),char(0),char(4),char(0),char(-73),char(0),char(49),char(0),char(22),char(0),
+char(8),char(0),char(-67),char(0),char(8),char(0),char(-79),char(0),char(8),char(0),char(110),char(0),char(8),char(0),char(-66),char(0),char(8),char(0),char(112),char(0),
+char(8),char(0),char(-65),char(0),char(8),char(0),char(-64),char(0),char(8),char(0),char(-63),char(0),char(8),char(0),char(-62),char(0),char(8),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(4),char(0),char(-54),char(0),char(4),char(0),char(-53),char(0),char(4),char(0),char(-52),char(0),char(4),char(0),char(-51),char(0),
+char(4),char(0),char(-50),char(0),char(0),char(0),char(37),char(0),char(51),char(0),char(22),char(0),char(7),char(0),char(-67),char(0),char(7),char(0),char(-79),char(0),
+char(7),char(0),char(110),char(0),char(7),char(0),char(-66),char(0),char(7),char(0),char(112),char(0),char(7),char(0),char(-65),char(0),char(7),char(0),char(-64),char(0),
+char(7),char(0),char(-63),char(0),char(7),char(0),char(-62),char(0),char(7),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(4),char(0),char(-54),char(0),
+char(4),char(0),char(-53),char(0),char(4),char(0),char(-52),char(0),char(4),char(0),char(-51),char(0),char(4),char(0),char(-50),char(0),char(0),char(0),char(37),char(0),
+char(65),char(0),char(4),char(0),char(7),char(0),char(-49),char(0),char(7),char(0),char(-48),char(0),char(7),char(0),char(-47),char(0),char(4),char(0),char(78),char(0),
+char(66),char(0),char(10),char(0),char(65),char(0),char(-46),char(0),char(13),char(0),char(-45),char(0),char(13),char(0),char(-44),char(0),char(13),char(0),char(-43),char(0),
+char(13),char(0),char(-42),char(0),char(13),char(0),char(-41),char(0),char(7),char(0),char(-121),char(0),char(7),char(0),char(-40),char(0),char(4),char(0),char(-39),char(0),
+char(4),char(0),char(53),char(0),char(67),char(0),char(4),char(0),char(65),char(0),char(-46),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(68),char(0),char(4),char(0),char(13),char(0),char(-41),char(0),char(65),char(0),char(-46),char(0),char(4),char(0),char(-35),char(0),
+char(7),char(0),char(-34),char(0),char(69),char(0),char(7),char(0),char(13),char(0),char(-33),char(0),char(65),char(0),char(-46),char(0),char(4),char(0),char(-32),char(0),
+char(7),char(0),char(-31),char(0),char(7),char(0),char(-30),char(0),char(7),char(0),char(-29),char(0),char(4),char(0),char(53),char(0),char(70),char(0),char(6),char(0),
+char(15),char(0),char(-28),char(0),char(13),char(0),char(-30),char(0),char(13),char(0),char(-27),char(0),char(56),char(0),char(-26),char(0),char(4),char(0),char(-25),char(0),
+char(7),char(0),char(-29),char(0),char(71),char(0),char(26),char(0),char(4),char(0),char(-24),char(0),char(7),char(0),char(-23),char(0),char(7),char(0),char(-79),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(-19),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(-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(7),char(0),char(-11),char(0),char(7),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(7),char(0),char(-6),char(0),char(7),char(0),char(-5),char(0),char(4),char(0),char(-4),char(0),char(4),char(0),char(-3),char(0),
+char(4),char(0),char(-2),char(0),char(4),char(0),char(-1),char(0),char(4),char(0),char(117),char(0),char(72),char(0),char(12),char(0),char(15),char(0),char(0),char(1),
+char(15),char(0),char(1),char(1),char(15),char(0),char(2),char(1),char(13),char(0),char(3),char(1),char(13),char(0),char(4),char(1),char(7),char(0),char(5),char(1),
+char(4),char(0),char(6),char(1),char(4),char(0),char(7),char(1),char(4),char(0),char(8),char(1),char(4),char(0),char(9),char(1),char(7),char(0),char(-31),char(0),
+char(4),char(0),char(53),char(0),char(73),char(0),char(27),char(0),char(17),char(0),char(10),char(1),char(15),char(0),char(11),char(1),char(15),char(0),char(12),char(1),
+char(13),char(0),char(3),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(4),char(0),char(18),char(1),char(7),char(0),char(19),char(1),char(4),char(0),char(20),char(1),char(4),char(0),char(21),char(1),
+char(4),char(0),char(22),char(1),char(7),char(0),char(23),char(1),char(7),char(0),char(24),char(1),char(4),char(0),char(25),char(1),char(4),char(0),char(26),char(1),
+char(7),char(0),char(27),char(1),char(7),char(0),char(28),char(1),char(7),char(0),char(29),char(1),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(33),char(1),char(4),char(0),char(34),char(1),char(4),char(0),char(35),char(1),char(74),char(0),char(12),char(0),
+char(9),char(0),char(36),char(1),char(9),char(0),char(37),char(1),char(13),char(0),char(38),char(1),char(7),char(0),char(39),char(1),char(7),char(0),char(-63),char(0),
+char(7),char(0),char(40),char(1),char(4),char(0),char(41),char(1),char(13),char(0),char(42),char(1),char(4),char(0),char(43),char(1),char(4),char(0),char(44),char(1),
+char(4),char(0),char(45),char(1),char(4),char(0),char(53),char(0),char(75),char(0),char(19),char(0),char(47),char(0),char(125),char(0),char(72),char(0),char(46),char(1),
+char(65),char(0),char(47),char(1),char(66),char(0),char(48),char(1),char(67),char(0),char(49),char(1),char(68),char(0),char(50),char(1),char(69),char(0),char(51),char(1),
+char(70),char(0),char(52),char(1),char(73),char(0),char(53),char(1),char(74),char(0),char(54),char(1),char(4),char(0),char(55),char(1),char(4),char(0),char(21),char(1),
+char(4),char(0),char(56),char(1),char(4),char(0),char(57),char(1),char(4),char(0),char(58),char(1),char(4),char(0),char(59),char(1),char(4),char(0),char(60),char(1),
+char(4),char(0),char(61),char(1),char(71),char(0),char(62),char(1),};
+int b3s_bulletDNAlen64= sizeof(b3s_bulletDNAstr64);
diff --git a/thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/b3Serializer.h b/thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/b3Serializer.h
new file mode 100644
index 0000000000..1c1ce43764
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/b3Serializer.h
@@ -0,0 +1,639 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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 B3_SERIALIZER_H
+#define B3_SERIALIZER_H
+
+#include "Bullet3Common/b3Scalar.h" // has definitions like B3_FORCE_INLINE
+#include "Bullet3Common/b3StackAlloc.h"
+#include "Bullet3Common/b3HashMap.h"
+
+#if !defined( __CELLOS_LV2__) && !defined(__MWERKS__)
+#include <memory.h>
+#endif
+#include <string.h>
+
+
+
+extern char b3s_bulletDNAstr[];
+extern int b3s_bulletDNAlen;
+extern char b3s_bulletDNAstr64[];
+extern int b3s_bulletDNAlen64;
+
+B3_FORCE_INLINE int b3StrLen(const char* str)
+{
+ if (!str)
+ return(0);
+ int len = 0;
+
+ while (*str != 0)
+ {
+ str++;
+ len++;
+ }
+
+ return len;
+}
+
+
+class b3Chunk
+{
+public:
+ int m_chunkCode;
+ int m_length;
+ void *m_oldPtr;
+ int m_dna_nr;
+ int m_number;
+};
+
+enum b3SerializationFlags
+{
+ B3_SERIALIZE_NO_BVH = 1,
+ B3_SERIALIZE_NO_TRIANGLEINFOMAP = 2,
+ B3_SERIALIZE_NO_DUPLICATE_ASSERT = 4
+};
+
+class b3Serializer
+{
+
+public:
+
+ virtual ~b3Serializer() {}
+
+ virtual const unsigned char* getBufferPointer() const = 0;
+
+ virtual int getCurrentBufferSize() const = 0;
+
+ virtual b3Chunk* allocate(size_t size, int numElements) = 0;
+
+ virtual void finalizeChunk(b3Chunk* chunk, const char* structType, int chunkCode,void* oldPtr)= 0;
+
+ virtual void* findPointer(void* oldPtr) = 0;
+
+ virtual void* getUniquePointer(void*oldPtr) = 0;
+
+ virtual void startSerialization() = 0;
+
+ virtual void finishSerialization() = 0;
+
+ virtual const char* findNameForPointer(const void* ptr) const = 0;
+
+ virtual void registerNameForPointer(const void* ptr, const char* name) = 0;
+
+ virtual void serializeName(const char* ptr) = 0;
+
+ virtual int getSerializationFlags() const = 0;
+
+ virtual void setSerializationFlags(int flags) = 0;
+
+
+};
+
+
+
+#define B3_HEADER_LENGTH 12
+#if defined(__sgi) || defined (__sparc) || defined (__sparc__) || defined (__PPC__) || defined (__ppc__) || defined (__BIG_ENDIAN__)
+# define B3_MAKE_ID(a,b,c,d) ( (int)(a)<<24 | (int)(b)<<16 | (c)<<8 | (d) )
+#else
+# define B3_MAKE_ID(a,b,c,d) ( (int)(d)<<24 | (int)(c)<<16 | (b)<<8 | (a) )
+#endif
+
+#define B3_SOFTBODY_CODE B3_MAKE_ID('S','B','D','Y')
+#define B3_COLLISIONOBJECT_CODE B3_MAKE_ID('C','O','B','J')
+#define B3_RIGIDBODY_CODE B3_MAKE_ID('R','B','D','Y')
+#define B3_CONSTRAINT_CODE B3_MAKE_ID('C','O','N','S')
+#define B3_BOXSHAPE_CODE B3_MAKE_ID('B','O','X','S')
+#define B3_QUANTIZED_BVH_CODE B3_MAKE_ID('Q','B','V','H')
+#define B3_TRIANLGE_INFO_MAP B3_MAKE_ID('T','M','A','P')
+#define B3_SHAPE_CODE B3_MAKE_ID('S','H','A','P')
+#define B3_ARRAY_CODE B3_MAKE_ID('A','R','A','Y')
+#define B3_SBMATERIAL_CODE B3_MAKE_ID('S','B','M','T')
+#define B3_SBNODE_CODE B3_MAKE_ID('S','B','N','D')
+#define B3_DYNAMICSWORLD_CODE B3_MAKE_ID('D','W','L','D')
+#define B3_DNA_CODE B3_MAKE_ID('D','N','A','1')
+
+
+struct b3PointerUid
+{
+ union
+ {
+ void* m_ptr;
+ int m_uniqueIds[2];
+ };
+};
+
+///The b3DefaultSerializer is the main Bullet serialization class.
+///The constructor takes an optional argument for backwards compatibility, it is recommended to leave this empty/zero.
+class b3DefaultSerializer : public b3Serializer
+{
+
+
+ b3AlignedObjectArray<char*> mTypes;
+ b3AlignedObjectArray<short*> mStructs;
+ b3AlignedObjectArray<short> mTlens;
+ b3HashMap<b3HashInt, int> mStructReverse;
+ b3HashMap<b3HashString,int> mTypeLookup;
+
+
+ b3HashMap<b3HashPtr,void*> m_chunkP;
+
+ b3HashMap<b3HashPtr,const char*> m_nameMap;
+
+ b3HashMap<b3HashPtr,b3PointerUid> m_uniquePointers;
+ int m_uniqueIdGenerator;
+
+ int m_totalSize;
+ unsigned char* m_buffer;
+ int m_currentSize;
+ void* m_dna;
+ int m_dnaLength;
+
+ int m_serializationFlags;
+
+
+ b3AlignedObjectArray<b3Chunk*> m_chunkPtrs;
+
+protected:
+
+ virtual void* findPointer(void* oldPtr)
+ {
+ void** ptr = m_chunkP.find(oldPtr);
+ if (ptr && *ptr)
+ return *ptr;
+ return 0;
+ }
+
+
+
+
+
+ void writeDNA()
+ {
+ b3Chunk* dnaChunk = allocate(m_dnaLength,1);
+ memcpy(dnaChunk->m_oldPtr,m_dna,m_dnaLength);
+ finalizeChunk(dnaChunk,"DNA1",B3_DNA_CODE, m_dna);
+ }
+
+ int getReverseType(const char *type) const
+ {
+
+ b3HashString key(type);
+ const int* valuePtr = mTypeLookup.find(key);
+ if (valuePtr)
+ return *valuePtr;
+
+ return -1;
+ }
+
+ void initDNA(const char* bdnaOrg,int dnalen)
+ {
+ ///was already initialized
+ if (m_dna)
+ return;
+
+ int littleEndian= 1;
+ littleEndian= ((char*)&littleEndian)[0];
+
+
+ m_dna = b3AlignedAlloc(dnalen,16);
+ memcpy(m_dna,bdnaOrg,dnalen);
+ m_dnaLength = dnalen;
+
+ int *intPtr=0;
+ short *shtPtr=0;
+ char *cp = 0;int dataLen =0;
+ intPtr = (int*)m_dna;
+
+ /*
+ SDNA (4 bytes) (magic number)
+ NAME (4 bytes)
+ <nr> (4 bytes) amount of names (int)
+ <string>
+ <string>
+ */
+
+ if (strncmp((const char*)m_dna, "SDNA", 4)==0)
+ {
+ // skip ++ NAME
+ intPtr++; intPtr++;
+ }
+
+ // Parse names
+ if (!littleEndian)
+ *intPtr = b3SwapEndian(*intPtr);
+
+ dataLen = *intPtr;
+
+ intPtr++;
+
+ cp = (char*)intPtr;
+ int i;
+ for ( i=0; i<dataLen; i++)
+ {
+
+ while (*cp)cp++;
+ cp++;
+ }
+ cp = b3AlignPointer(cp,4);
+
+ /*
+ TYPE (4 bytes)
+ <nr> amount of types (int)
+ <string>
+ <string>
+ */
+
+ intPtr = (int*)cp;
+ b3Assert(strncmp(cp, "TYPE", 4)==0); intPtr++;
+
+ if (!littleEndian)
+ *intPtr = b3SwapEndian(*intPtr);
+
+ dataLen = *intPtr;
+ intPtr++;
+
+
+ cp = (char*)intPtr;
+ for (i=0; i<dataLen; i++)
+ {
+ mTypes.push_back(cp);
+ while (*cp)cp++;
+ cp++;
+ }
+
+ cp = b3AlignPointer(cp,4);
+
+
+ /*
+ TLEN (4 bytes)
+ <len> (short) the lengths of types
+ <len>
+ */
+
+ // Parse type lens
+ intPtr = (int*)cp;
+ b3Assert(strncmp(cp, "TLEN", 4)==0); intPtr++;
+
+ dataLen = (int)mTypes.size();
+
+ shtPtr = (short*)intPtr;
+ for (i=0; i<dataLen; i++, shtPtr++)
+ {
+ if (!littleEndian)
+ shtPtr[0] = b3SwapEndian(shtPtr[0]);
+ mTlens.push_back(shtPtr[0]);
+ }
+
+ if (dataLen & 1) shtPtr++;
+
+ /*
+ STRC (4 bytes)
+ <nr> amount of structs (int)
+ <typenr>
+ <nr_of_elems>
+ <typenr>
+ <namenr>
+ <typenr>
+ <namenr>
+ */
+
+ intPtr = (int*)shtPtr;
+ cp = (char*)intPtr;
+ b3Assert(strncmp(cp, "STRC", 4)==0); intPtr++;
+
+ if (!littleEndian)
+ *intPtr = b3SwapEndian(*intPtr);
+ dataLen = *intPtr ;
+ intPtr++;
+
+
+ shtPtr = (short*)intPtr;
+ for (i=0; i<dataLen; i++)
+ {
+ mStructs.push_back (shtPtr);
+
+ if (!littleEndian)
+ {
+ shtPtr[0]= b3SwapEndian(shtPtr[0]);
+ shtPtr[1]= b3SwapEndian(shtPtr[1]);
+
+ int len = shtPtr[1];
+ shtPtr+= 2;
+
+ for (int a=0; a<len; a++, shtPtr+=2)
+ {
+ shtPtr[0]= b3SwapEndian(shtPtr[0]);
+ shtPtr[1]= b3SwapEndian(shtPtr[1]);
+ }
+
+ } else
+ {
+ shtPtr+= (2*shtPtr[1])+2;
+ }
+ }
+
+ // build reverse lookups
+ for (i=0; i<(int)mStructs.size(); i++)
+ {
+ short *strc = mStructs.at(i);
+ mStructReverse.insert(strc[0], i);
+ mTypeLookup.insert(b3HashString(mTypes[strc[0]]),i);
+ }
+ }
+
+public:
+
+
+
+
+ b3DefaultSerializer(int totalSize=0)
+ :m_totalSize(totalSize),
+ m_currentSize(0),
+ m_dna(0),
+ m_dnaLength(0),
+ m_serializationFlags(0)
+ {
+ m_buffer = m_totalSize?(unsigned char*)b3AlignedAlloc(totalSize,16):0;
+
+ const bool VOID_IS_8 = ((sizeof(void*)==8));
+
+#ifdef B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+ if (VOID_IS_8)
+ {
+#if _WIN64
+ initDNA((const char*)b3s_bulletDNAstr64,b3s_bulletDNAlen64);
+#else
+ b3Assert(0);
+#endif
+ } else
+ {
+#ifndef _WIN64
+ initDNA((const char*)b3s_bulletDNAstr,b3s_bulletDNAlen);
+#else
+ b3Assert(0);
+#endif
+ }
+
+#else //B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+ if (VOID_IS_8)
+ {
+ initDNA((const char*)b3s_bulletDNAstr64,b3s_bulletDNAlen64);
+ } else
+ {
+ initDNA((const char*)b3s_bulletDNAstr,b3s_bulletDNAlen);
+ }
+#endif //B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+
+ }
+
+ virtual ~b3DefaultSerializer()
+ {
+ if (m_buffer)
+ b3AlignedFree(m_buffer);
+ if (m_dna)
+ b3AlignedFree(m_dna);
+ }
+
+ void writeHeader(unsigned char* buffer) const
+ {
+
+
+#ifdef B3_USE_DOUBLE_PRECISION
+ memcpy(buffer, "BULLETd", 7);
+#else
+ memcpy(buffer, "BULLETf", 7);
+#endif //B3_USE_DOUBLE_PRECISION
+
+ int littleEndian= 1;
+ littleEndian= ((char*)&littleEndian)[0];
+
+ if (sizeof(void*)==8)
+ {
+ buffer[7] = '-';
+ } else
+ {
+ buffer[7] = '_';
+ }
+
+ if (littleEndian)
+ {
+ buffer[8]='v';
+ } else
+ {
+ buffer[8]='V';
+ }
+
+
+ buffer[9] = '2';
+ buffer[10] = '8';
+ buffer[11] = '1';
+
+ }
+
+ virtual void startSerialization()
+ {
+ m_uniqueIdGenerator= 1;
+ if (m_totalSize)
+ {
+ unsigned char* buffer = internalAlloc(B3_HEADER_LENGTH);
+ writeHeader(buffer);
+ }
+
+ }
+
+ virtual void finishSerialization()
+ {
+ writeDNA();
+
+ //if we didn't pre-allocate a buffer, we need to create a contiguous buffer now
+ int mysize = 0;
+ if (!m_totalSize)
+ {
+ if (m_buffer)
+ b3AlignedFree(m_buffer);
+
+ m_currentSize += B3_HEADER_LENGTH;
+ m_buffer = (unsigned char*)b3AlignedAlloc(m_currentSize,16);
+
+ unsigned char* currentPtr = m_buffer;
+ writeHeader(m_buffer);
+ currentPtr += B3_HEADER_LENGTH;
+ mysize+=B3_HEADER_LENGTH;
+ for (int i=0;i< m_chunkPtrs.size();i++)
+ {
+ int curLength = sizeof(b3Chunk)+m_chunkPtrs[i]->m_length;
+ memcpy(currentPtr,m_chunkPtrs[i], curLength);
+ b3AlignedFree(m_chunkPtrs[i]);
+ currentPtr+=curLength;
+ mysize+=curLength;
+ }
+ }
+
+ mTypes.clear();
+ mStructs.clear();
+ mTlens.clear();
+ mStructReverse.clear();
+ mTypeLookup.clear();
+ m_chunkP.clear();
+ m_nameMap.clear();
+ m_uniquePointers.clear();
+ m_chunkPtrs.clear();
+ }
+
+ virtual void* getUniquePointer(void*oldPtr)
+ {
+ if (!oldPtr)
+ return 0;
+
+ b3PointerUid* uptr = (b3PointerUid*)m_uniquePointers.find(oldPtr);
+ if (uptr)
+ {
+ return uptr->m_ptr;
+ }
+ m_uniqueIdGenerator++;
+
+ b3PointerUid uid;
+ uid.m_uniqueIds[0] = m_uniqueIdGenerator;
+ uid.m_uniqueIds[1] = m_uniqueIdGenerator;
+ m_uniquePointers.insert(oldPtr,uid);
+ return uid.m_ptr;
+
+ }
+
+ virtual const unsigned char* getBufferPointer() const
+ {
+ return m_buffer;
+ }
+
+ virtual int getCurrentBufferSize() const
+ {
+ return m_currentSize;
+ }
+
+ virtual void finalizeChunk(b3Chunk* chunk, const char* structType, int chunkCode,void* oldPtr)
+ {
+ if (!(m_serializationFlags&B3_SERIALIZE_NO_DUPLICATE_ASSERT))
+ {
+ b3Assert(!findPointer(oldPtr));
+ }
+
+ chunk->m_dna_nr = getReverseType(structType);
+
+ chunk->m_chunkCode = chunkCode;
+
+ void* uniquePtr = getUniquePointer(oldPtr);
+
+ m_chunkP.insert(oldPtr,uniquePtr);//chunk->m_oldPtr);
+ chunk->m_oldPtr = uniquePtr;//oldPtr;
+
+ }
+
+
+ virtual unsigned char* internalAlloc(size_t size)
+ {
+ unsigned char* ptr = 0;
+
+ if (m_totalSize)
+ {
+ ptr = m_buffer+m_currentSize;
+ m_currentSize += int(size);
+ b3Assert(m_currentSize<m_totalSize);
+ } else
+ {
+ ptr = (unsigned char*)b3AlignedAlloc(size,16);
+ m_currentSize += int(size);
+ }
+ return ptr;
+ }
+
+
+
+ virtual b3Chunk* allocate(size_t size, int numElements)
+ {
+
+ unsigned char* ptr = internalAlloc(int(size)*numElements+sizeof(b3Chunk));
+
+ unsigned char* data = ptr + sizeof(b3Chunk);
+
+ b3Chunk* chunk = (b3Chunk*)ptr;
+ chunk->m_chunkCode = 0;
+ chunk->m_oldPtr = data;
+ chunk->m_length = int(size)*numElements;
+ chunk->m_number = numElements;
+
+ m_chunkPtrs.push_back(chunk);
+
+
+ return chunk;
+ }
+
+ virtual const char* findNameForPointer(const void* ptr) const
+ {
+ const char*const * namePtr = m_nameMap.find(ptr);
+ if (namePtr && *namePtr)
+ return *namePtr;
+ return 0;
+
+ }
+
+ virtual void registerNameForPointer(const void* ptr, const char* name)
+ {
+ m_nameMap.insert(ptr,name);
+ }
+
+ virtual void serializeName(const char* name)
+ {
+ if (name)
+ {
+ //don't serialize name twice
+ if (findPointer((void*)name))
+ return;
+
+ int len = b3StrLen(name);
+ if (len)
+ {
+
+ int newLen = len+1;
+ int padding = ((newLen+3)&~3)-newLen;
+ newLen += padding;
+
+ //serialize name string now
+ b3Chunk* chunk = allocate(sizeof(char),newLen);
+ char* destinationName = (char*)chunk->m_oldPtr;
+ for (int i=0;i<len;i++)
+ {
+ destinationName[i] = name[i];
+ }
+ destinationName[len] = 0;
+ finalizeChunk(chunk,"char",B3_ARRAY_CODE,(void*)name);
+ }
+ }
+ }
+
+ virtual int getSerializationFlags() const
+ {
+ return m_serializationFlags;
+ }
+
+ virtual void setSerializationFlags(int flags)
+ {
+ m_serializationFlags = flags;
+ }
+
+};
+
+
+#endif //B3_SERIALIZER_H
+
diff --git a/thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/premake4.lua b/thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/premake4.lua
new file mode 100644
index 0000000000..ec2f0a51ae
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/premake4.lua
@@ -0,0 +1,12 @@
+ project "Bullet2FileLoader"
+
+ kind "StaticLib"
+
+ includedirs {
+ "../../../src"
+ }
+
+ files {
+ "**.cpp",
+ "**.h"
+ } \ No newline at end of file
diff --git a/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp b/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp
new file mode 100644
index 0000000000..77763305b1
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp
@@ -0,0 +1,37 @@
+
+//Bullet Continuous Collision Detection and Physics Library
+//Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+
+//
+// btAxisSweep3
+//
+// Copyright (c) 2006 Simon Hobbs
+//
+// 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 "btAxisSweep3.h"
+
+
+btAxisSweep3::btAxisSweep3(const btVector3& worldAabbMin,const btVector3& worldAabbMax, unsigned short int maxHandles, btOverlappingPairCache* pairCache, bool disableRaycastAccelerator)
+:btAxisSweep3Internal<unsigned short int>(worldAabbMin,worldAabbMax,0xfffe,0xffff,maxHandles,pairCache,disableRaycastAccelerator)
+{
+ // 1 handle is reserved as sentinel
+ btAssert(maxHandles > 1 && maxHandles < 32767);
+
+}
+
+
+bt32BitAxisSweep3::bt32BitAxisSweep3(const btVector3& worldAabbMin,const btVector3& worldAabbMax, unsigned int maxHandles , btOverlappingPairCache* pairCache , bool disableRaycastAccelerator)
+:btAxisSweep3Internal<unsigned int>(worldAabbMin,worldAabbMax,0xfffffffe,0x7fffffff,maxHandles,pairCache,disableRaycastAccelerator)
+{
+ // 1 handle is reserved as sentinel
+ btAssert(maxHandles > 1 && maxHandles < 2147483647);
+}
diff --git a/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h b/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h
new file mode 100644
index 0000000000..a3648df1af
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h
@@ -0,0 +1,52 @@
+//Bullet Continuous Collision Detection and Physics Library
+//Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+//
+// btAxisSweep3.h
+//
+// Copyright (c) 2006 Simon Hobbs
+//
+// 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_AXIS_SWEEP_3_H
+#define BT_AXIS_SWEEP_3_H
+
+#include "LinearMath/btVector3.h"
+#include "btOverlappingPairCache.h"
+#include "btBroadphaseInterface.h"
+#include "btBroadphaseProxy.h"
+#include "btOverlappingPairCallback.h"
+#include "btDbvtBroadphase.h"
+#include "btAxisSweep3Internal.h"
+
+/// The btAxisSweep3 is an efficient implementation of the 3d axis sweep and prune broadphase.
+/// It uses arrays rather then lists for storage of the 3 axis. Also it operates using 16 bit integer coordinates instead of floats.
+/// For large worlds and many objects, use bt32BitAxisSweep3 or btDbvtBroadphase instead. bt32BitAxisSweep3 has higher precision and allows more then 16384 objects at the cost of more memory and bit of performance.
+class btAxisSweep3 : public btAxisSweep3Internal<unsigned short int>
+{
+public:
+
+ btAxisSweep3(const btVector3& worldAabbMin,const btVector3& worldAabbMax, unsigned short int maxHandles = 16384, btOverlappingPairCache* pairCache = 0, bool disableRaycastAccelerator = false);
+
+};
+
+/// The bt32BitAxisSweep3 allows higher precision quantization and more objects compared to the btAxisSweep3 sweep and prune.
+/// This comes at the cost of more memory per handle, and a bit slower performance.
+/// It uses arrays rather then lists for storage of the 3 axis.
+class bt32BitAxisSweep3 : public btAxisSweep3Internal<unsigned int>
+{
+public:
+
+ bt32BitAxisSweep3(const btVector3& worldAabbMin,const btVector3& worldAabbMax, unsigned int maxHandles = 1500000, btOverlappingPairCache* pairCache = 0, bool disableRaycastAccelerator = false);
+
+};
+
+#endif
diff --git a/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btAxisSweep3Internal.h b/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btAxisSweep3Internal.h
new file mode 100644
index 0000000000..2c4d41bc04
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btAxisSweep3Internal.h
@@ -0,0 +1,1022 @@
+//Bullet Continuous Collision Detection and Physics Library
+//Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+//
+// btAxisSweep3.h
+//
+// Copyright (c) 2006 Simon Hobbs
+//
+// 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_AXIS_SWEEP_3_INTERNAL_H
+#define BT_AXIS_SWEEP_3_INTERNAL_H
+
+#include "LinearMath/btVector3.h"
+#include "btOverlappingPairCache.h"
+#include "btBroadphaseInterface.h"
+#include "btBroadphaseProxy.h"
+#include "btOverlappingPairCallback.h"
+#include "btDbvtBroadphase.h"
+
+//#define DEBUG_BROADPHASE 1
+#define USE_OVERLAP_TEST_ON_REMOVES 1
+
+/// The internal templace class btAxisSweep3Internal implements the sweep and prune broadphase.
+/// It uses quantized integers to represent the begin and end points for each of the 3 axis.
+/// Dont use this class directly, use btAxisSweep3 or bt32BitAxisSweep3 instead.
+template <typename BP_FP_INT_TYPE>
+class btAxisSweep3Internal : public btBroadphaseInterface
+{
+protected:
+
+ BP_FP_INT_TYPE m_bpHandleMask;
+ BP_FP_INT_TYPE m_handleSentinel;
+
+public:
+
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ class Edge
+ {
+ public:
+ BP_FP_INT_TYPE m_pos; // low bit is min/max
+ BP_FP_INT_TYPE m_handle;
+
+ BP_FP_INT_TYPE IsMax() const {return static_cast<BP_FP_INT_TYPE>(m_pos & 1);}
+ };
+
+public:
+ class Handle : public btBroadphaseProxy
+ {
+ public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ // indexes into the edge arrays
+ BP_FP_INT_TYPE m_minEdges[3], m_maxEdges[3]; // 6 * 2 = 12
+// BP_FP_INT_TYPE m_uniqueId;
+ btBroadphaseProxy* m_dbvtProxy;//for faster raycast
+ //void* m_pOwner; this is now in btBroadphaseProxy.m_clientObject
+
+ SIMD_FORCE_INLINE void SetNextFree(BP_FP_INT_TYPE next) {m_minEdges[0] = next;}
+ SIMD_FORCE_INLINE BP_FP_INT_TYPE GetNextFree() const {return m_minEdges[0];}
+ }; // 24 bytes + 24 for Edge structures = 44 bytes total per entry
+
+
+protected:
+ btVector3 m_worldAabbMin; // overall system bounds
+ btVector3 m_worldAabbMax; // overall system bounds
+
+ btVector3 m_quantize; // scaling factor for quantization
+
+ BP_FP_INT_TYPE m_numHandles; // number of active handles
+ BP_FP_INT_TYPE m_maxHandles; // max number of handles
+ Handle* m_pHandles; // handles pool
+
+ BP_FP_INT_TYPE m_firstFreeHandle; // free handles list
+
+ Edge* m_pEdges[3]; // edge arrays for the 3 axes (each array has m_maxHandles * 2 + 2 sentinel entries)
+ void* m_pEdgesRawPtr[3];
+
+ btOverlappingPairCache* m_pairCache;
+
+ ///btOverlappingPairCallback is an additional optional user callback for adding/removing overlapping pairs, similar interface to btOverlappingPairCache.
+ btOverlappingPairCallback* m_userPairCallback;
+
+ bool m_ownsPairCache;
+
+ int m_invalidPair;
+
+ ///additional dynamic aabb structure, used to accelerate ray cast queries.
+ ///can be disabled using a optional argument in the constructor
+ btDbvtBroadphase* m_raycastAccelerator;
+ btOverlappingPairCache* m_nullPairCache;
+
+
+ // allocation/deallocation
+ BP_FP_INT_TYPE allocHandle();
+ void freeHandle(BP_FP_INT_TYPE handle);
+
+
+ bool testOverlap2D(const Handle* pHandleA, const Handle* pHandleB,int axis0,int axis1);
+
+#ifdef DEBUG_BROADPHASE
+ void debugPrintAxis(int axis,bool checkCardinality=true);
+#endif //DEBUG_BROADPHASE
+
+ //Overlap* AddOverlap(BP_FP_INT_TYPE handleA, BP_FP_INT_TYPE handleB);
+ //void RemoveOverlap(BP_FP_INT_TYPE handleA, BP_FP_INT_TYPE handleB);
+
+
+
+ void sortMinDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps );
+ void sortMinUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps );
+ void sortMaxDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps );
+ void sortMaxUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps );
+
+public:
+
+ btAxisSweep3Internal(const btVector3& worldAabbMin,const btVector3& worldAabbMax, BP_FP_INT_TYPE handleMask, BP_FP_INT_TYPE handleSentinel, BP_FP_INT_TYPE maxHandles = 16384, btOverlappingPairCache* pairCache=0,bool disableRaycastAccelerator = false);
+
+ virtual ~btAxisSweep3Internal();
+
+ BP_FP_INT_TYPE getNumHandles() const
+ {
+ return m_numHandles;
+ }
+
+ virtual void calculateOverlappingPairs(btDispatcher* dispatcher);
+
+ BP_FP_INT_TYPE addHandle(const btVector3& aabbMin,const btVector3& aabbMax, void* pOwner, int collisionFilterGroup, int collisionFilterMask,btDispatcher* dispatcher);
+ void removeHandle(BP_FP_INT_TYPE handle,btDispatcher* dispatcher);
+ void updateHandle(BP_FP_INT_TYPE handle, const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher);
+ SIMD_FORCE_INLINE Handle* getHandle(BP_FP_INT_TYPE index) const {return m_pHandles + index;}
+
+ virtual void resetPool(btDispatcher* dispatcher);
+
+ void processAllOverlappingPairs(btOverlapCallback* callback);
+
+ //Broadphase Interface
+ virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr , int collisionFilterGroup, int collisionFilterMask,btDispatcher* dispatcher);
+ virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
+ virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher);
+ virtual void getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const;
+
+ virtual void rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin=btVector3(0,0,0), const btVector3& aabbMax = btVector3(0,0,0));
+ virtual void aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback);
+
+
+ void quantize(BP_FP_INT_TYPE* out, const btVector3& point, int isMax) const;
+ ///unQuantize should be conservative: aabbMin/aabbMax should be larger then 'getAabb' result
+ void unQuantize(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const;
+
+ bool testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
+
+ btOverlappingPairCache* getOverlappingPairCache()
+ {
+ return m_pairCache;
+ }
+ const btOverlappingPairCache* getOverlappingPairCache() const
+ {
+ return m_pairCache;
+ }
+
+ void setOverlappingPairUserCallback(btOverlappingPairCallback* pairCallback)
+ {
+ m_userPairCallback = pairCallback;
+ }
+ const btOverlappingPairCallback* getOverlappingPairUserCallback() const
+ {
+ return m_userPairCallback;
+ }
+
+ ///getAabb returns the axis aligned bounding box in the 'global' coordinate frame
+ ///will add some transform later
+ virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const
+ {
+ aabbMin = m_worldAabbMin;
+ aabbMax = m_worldAabbMax;
+ }
+
+ virtual void printStats()
+ {
+/* printf("btAxisSweep3.h\n");
+ printf("numHandles = %d, maxHandles = %d\n",m_numHandles,m_maxHandles);
+ printf("aabbMin=%f,%f,%f,aabbMax=%f,%f,%f\n",m_worldAabbMin.getX(),m_worldAabbMin.getY(),m_worldAabbMin.getZ(),
+ m_worldAabbMax.getX(),m_worldAabbMax.getY(),m_worldAabbMax.getZ());
+ */
+
+ }
+
+};
+
+////////////////////////////////////////////////////////////////////
+
+
+
+
+#ifdef DEBUG_BROADPHASE
+#include <stdio.h>
+
+template <typename BP_FP_INT_TYPE>
+void btAxisSweep3<BP_FP_INT_TYPE>::debugPrintAxis(int axis, bool checkCardinality)
+{
+ int numEdges = m_pHandles[0].m_maxEdges[axis];
+ printf("SAP Axis %d, numEdges=%d\n",axis,numEdges);
+
+ int i;
+ for (i=0;i<numEdges+1;i++)
+ {
+ Edge* pEdge = m_pEdges[axis] + i;
+ Handle* pHandlePrev = getHandle(pEdge->m_handle);
+ int handleIndex = pEdge->IsMax()? pHandlePrev->m_maxEdges[axis] : pHandlePrev->m_minEdges[axis];
+ char beginOrEnd;
+ beginOrEnd=pEdge->IsMax()?'E':'B';
+ printf(" [%c,h=%d,p=%x,i=%d]\n",beginOrEnd,pEdge->m_handle,pEdge->m_pos,handleIndex);
+ }
+
+ if (checkCardinality)
+ btAssert(numEdges == m_numHandles*2+1);
+}
+#endif //DEBUG_BROADPHASE
+
+template <typename BP_FP_INT_TYPE>
+btBroadphaseProxy* btAxisSweep3Internal<BP_FP_INT_TYPE>::createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, int collisionFilterGroup, int collisionFilterMask,btDispatcher* dispatcher)
+{
+ (void)shapeType;
+ BP_FP_INT_TYPE handleId = addHandle(aabbMin,aabbMax, userPtr,collisionFilterGroup,collisionFilterMask,dispatcher);
+
+ Handle* handle = getHandle(handleId);
+
+ if (m_raycastAccelerator)
+ {
+ btBroadphaseProxy* rayProxy = m_raycastAccelerator->createProxy(aabbMin,aabbMax,shapeType,userPtr,collisionFilterGroup,collisionFilterMask,dispatcher);
+ handle->m_dbvtProxy = rayProxy;
+ }
+ return handle;
+}
+
+
+
+template <typename BP_FP_INT_TYPE>
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
+{
+ Handle* handle = static_cast<Handle*>(proxy);
+ if (m_raycastAccelerator)
+ m_raycastAccelerator->destroyProxy(handle->m_dbvtProxy,dispatcher);
+ removeHandle(static_cast<BP_FP_INT_TYPE>(handle->m_uniqueId), dispatcher);
+}
+
+template <typename BP_FP_INT_TYPE>
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher)
+{
+ Handle* handle = static_cast<Handle*>(proxy);
+ handle->m_aabbMin = aabbMin;
+ handle->m_aabbMax = aabbMax;
+ updateHandle(static_cast<BP_FP_INT_TYPE>(handle->m_uniqueId), aabbMin, aabbMax,dispatcher);
+ if (m_raycastAccelerator)
+ m_raycastAccelerator->setAabb(handle->m_dbvtProxy,aabbMin,aabbMax,dispatcher);
+
+}
+
+template <typename BP_FP_INT_TYPE>
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback,const btVector3& aabbMin,const btVector3& aabbMax)
+{
+ if (m_raycastAccelerator)
+ {
+ m_raycastAccelerator->rayTest(rayFrom,rayTo,rayCallback,aabbMin,aabbMax);
+ } else
+ {
+ //choose axis?
+ BP_FP_INT_TYPE axis = 0;
+ //for each proxy
+ for (BP_FP_INT_TYPE i=1;i<m_numHandles*2+1;i++)
+ {
+ if (m_pEdges[axis][i].IsMax())
+ {
+ rayCallback.process(getHandle(m_pEdges[axis][i].m_handle));
+ }
+ }
+ }
+}
+
+template <typename BP_FP_INT_TYPE>
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback)
+{
+ if (m_raycastAccelerator)
+ {
+ m_raycastAccelerator->aabbTest(aabbMin,aabbMax,callback);
+ } else
+ {
+ //choose axis?
+ BP_FP_INT_TYPE axis = 0;
+ //for each proxy
+ for (BP_FP_INT_TYPE i=1;i<m_numHandles*2+1;i++)
+ {
+ if (m_pEdges[axis][i].IsMax())
+ {
+ Handle* handle = getHandle(m_pEdges[axis][i].m_handle);
+ if (TestAabbAgainstAabb2(aabbMin,aabbMax,handle->m_aabbMin,handle->m_aabbMax))
+ {
+ callback.process(handle);
+ }
+ }
+ }
+ }
+}
+
+
+
+template <typename BP_FP_INT_TYPE>
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const
+{
+ Handle* pHandle = static_cast<Handle*>(proxy);
+ aabbMin = pHandle->m_aabbMin;
+ aabbMax = pHandle->m_aabbMax;
+}
+
+
+template <typename BP_FP_INT_TYPE>
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::unQuantize(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const
+{
+ Handle* pHandle = static_cast<Handle*>(proxy);
+
+ unsigned short vecInMin[3];
+ unsigned short vecInMax[3];
+
+ vecInMin[0] = m_pEdges[0][pHandle->m_minEdges[0]].m_pos ;
+ vecInMax[0] = m_pEdges[0][pHandle->m_maxEdges[0]].m_pos +1 ;
+ vecInMin[1] = m_pEdges[1][pHandle->m_minEdges[1]].m_pos ;
+ vecInMax[1] = m_pEdges[1][pHandle->m_maxEdges[1]].m_pos +1 ;
+ vecInMin[2] = m_pEdges[2][pHandle->m_minEdges[2]].m_pos ;
+ vecInMax[2] = m_pEdges[2][pHandle->m_maxEdges[2]].m_pos +1 ;
+
+ aabbMin.setValue((btScalar)(vecInMin[0]) / (m_quantize.getX()),(btScalar)(vecInMin[1]) / (m_quantize.getY()),(btScalar)(vecInMin[2]) / (m_quantize.getZ()));
+ aabbMin += m_worldAabbMin;
+
+ aabbMax.setValue((btScalar)(vecInMax[0]) / (m_quantize.getX()),(btScalar)(vecInMax[1]) / (m_quantize.getY()),(btScalar)(vecInMax[2]) / (m_quantize.getZ()));
+ aabbMax += m_worldAabbMin;
+}
+
+
+
+
+template <typename BP_FP_INT_TYPE>
+btAxisSweep3Internal<BP_FP_INT_TYPE>::btAxisSweep3Internal(const btVector3& worldAabbMin,const btVector3& worldAabbMax, BP_FP_INT_TYPE handleMask, BP_FP_INT_TYPE handleSentinel,BP_FP_INT_TYPE userMaxHandles, btOverlappingPairCache* pairCache , bool disableRaycastAccelerator)
+:m_bpHandleMask(handleMask),
+m_handleSentinel(handleSentinel),
+m_pairCache(pairCache),
+m_userPairCallback(0),
+m_ownsPairCache(false),
+m_invalidPair(0),
+m_raycastAccelerator(0)
+{
+ BP_FP_INT_TYPE maxHandles = static_cast<BP_FP_INT_TYPE>(userMaxHandles+1);//need to add one sentinel handle
+
+ if (!m_pairCache)
+ {
+ void* ptr = btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16);
+ m_pairCache = new(ptr) btHashedOverlappingPairCache();
+ m_ownsPairCache = true;
+ }
+
+ if (!disableRaycastAccelerator)
+ {
+ m_nullPairCache = new (btAlignedAlloc(sizeof(btNullPairCache),16)) btNullPairCache();
+ m_raycastAccelerator = new (btAlignedAlloc(sizeof(btDbvtBroadphase),16)) btDbvtBroadphase(m_nullPairCache);//m_pairCache);
+ m_raycastAccelerator->m_deferedcollide = true;//don't add/remove pairs
+ }
+
+ //btAssert(bounds.HasVolume());
+
+ // init bounds
+ m_worldAabbMin = worldAabbMin;
+ m_worldAabbMax = worldAabbMax;
+
+ btVector3 aabbSize = m_worldAabbMax - m_worldAabbMin;
+
+ BP_FP_INT_TYPE maxInt = m_handleSentinel;
+
+ m_quantize = btVector3(btScalar(maxInt),btScalar(maxInt),btScalar(maxInt)) / aabbSize;
+
+ // allocate handles buffer, using btAlignedAlloc, and put all handles on free list
+ m_pHandles = new Handle[maxHandles];
+
+ m_maxHandles = maxHandles;
+ m_numHandles = 0;
+
+ // handle 0 is reserved as the null index, and is also used as the sentinel
+ m_firstFreeHandle = 1;
+ {
+ for (BP_FP_INT_TYPE i = m_firstFreeHandle; i < maxHandles; i++)
+ m_pHandles[i].SetNextFree(static_cast<BP_FP_INT_TYPE>(i + 1));
+ m_pHandles[maxHandles - 1].SetNextFree(0);
+ }
+
+ {
+ // allocate edge buffers
+ for (int i = 0; i < 3; i++)
+ {
+ m_pEdgesRawPtr[i] = btAlignedAlloc(sizeof(Edge)*maxHandles*2,16);
+ m_pEdges[i] = new(m_pEdgesRawPtr[i]) Edge[maxHandles * 2];
+ }
+ }
+ //removed overlap management
+
+ // make boundary sentinels
+
+ m_pHandles[0].m_clientObject = 0;
+
+ for (int axis = 0; axis < 3; axis++)
+ {
+ m_pHandles[0].m_minEdges[axis] = 0;
+ m_pHandles[0].m_maxEdges[axis] = 1;
+
+ m_pEdges[axis][0].m_pos = 0;
+ m_pEdges[axis][0].m_handle = 0;
+ m_pEdges[axis][1].m_pos = m_handleSentinel;
+ m_pEdges[axis][1].m_handle = 0;
+#ifdef DEBUG_BROADPHASE
+ debugPrintAxis(axis);
+#endif //DEBUG_BROADPHASE
+
+ }
+
+}
+
+template <typename BP_FP_INT_TYPE>
+btAxisSweep3Internal<BP_FP_INT_TYPE>::~btAxisSweep3Internal()
+{
+ if (m_raycastAccelerator)
+ {
+ m_nullPairCache->~btOverlappingPairCache();
+ btAlignedFree(m_nullPairCache);
+ m_raycastAccelerator->~btDbvtBroadphase();
+ btAlignedFree (m_raycastAccelerator);
+ }
+
+ for (int i = 2; i >= 0; i--)
+ {
+ btAlignedFree(m_pEdgesRawPtr[i]);
+ }
+ delete [] m_pHandles;
+
+ if (m_ownsPairCache)
+ {
+ m_pairCache->~btOverlappingPairCache();
+ btAlignedFree(m_pairCache);
+ }
+}
+
+template <typename BP_FP_INT_TYPE>
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::quantize(BP_FP_INT_TYPE* out, const btVector3& point, int isMax) const
+{
+#ifdef OLD_CLAMPING_METHOD
+ ///problem with this clamping method is that the floating point during quantization might still go outside the range [(0|isMax) .. (m_handleSentinel&m_bpHandleMask]|isMax]
+ ///see http://code.google.com/p/bullet/issues/detail?id=87
+ btVector3 clampedPoint(point);
+ clampedPoint.setMax(m_worldAabbMin);
+ clampedPoint.setMin(m_worldAabbMax);
+ btVector3 v = (clampedPoint - m_worldAabbMin) * m_quantize;
+ out[0] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getX() & m_bpHandleMask) | isMax);
+ out[1] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getY() & m_bpHandleMask) | isMax);
+ out[2] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getZ() & m_bpHandleMask) | isMax);
+#else
+ btVector3 v = (point - m_worldAabbMin) * m_quantize;
+ out[0]=(v[0]<=0)?(BP_FP_INT_TYPE)isMax:(v[0]>=m_handleSentinel)?(BP_FP_INT_TYPE)((m_handleSentinel&m_bpHandleMask)|isMax):(BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v[0]&m_bpHandleMask)|isMax);
+ out[1]=(v[1]<=0)?(BP_FP_INT_TYPE)isMax:(v[1]>=m_handleSentinel)?(BP_FP_INT_TYPE)((m_handleSentinel&m_bpHandleMask)|isMax):(BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v[1]&m_bpHandleMask)|isMax);
+ out[2]=(v[2]<=0)?(BP_FP_INT_TYPE)isMax:(v[2]>=m_handleSentinel)?(BP_FP_INT_TYPE)((m_handleSentinel&m_bpHandleMask)|isMax):(BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v[2]&m_bpHandleMask)|isMax);
+#endif //OLD_CLAMPING_METHOD
+}
+
+
+template <typename BP_FP_INT_TYPE>
+BP_FP_INT_TYPE btAxisSweep3Internal<BP_FP_INT_TYPE>::allocHandle()
+{
+ btAssert(m_firstFreeHandle);
+
+ BP_FP_INT_TYPE handle = m_firstFreeHandle;
+ m_firstFreeHandle = getHandle(handle)->GetNextFree();
+ m_numHandles++;
+
+ return handle;
+}
+
+template <typename BP_FP_INT_TYPE>
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::freeHandle(BP_FP_INT_TYPE handle)
+{
+ btAssert(handle > 0 && handle < m_maxHandles);
+
+ getHandle(handle)->SetNextFree(m_firstFreeHandle);
+ m_firstFreeHandle = handle;
+
+ m_numHandles--;
+}
+
+
+template <typename BP_FP_INT_TYPE>
+BP_FP_INT_TYPE btAxisSweep3Internal<BP_FP_INT_TYPE>::addHandle(const btVector3& aabbMin,const btVector3& aabbMax, void* pOwner, int collisionFilterGroup, int collisionFilterMask,btDispatcher* dispatcher)
+{
+ // quantize the bounds
+ BP_FP_INT_TYPE min[3], max[3];
+ quantize(min, aabbMin, 0);
+ quantize(max, aabbMax, 1);
+
+ // allocate a handle
+ BP_FP_INT_TYPE handle = allocHandle();
+
+
+ Handle* pHandle = getHandle(handle);
+
+ pHandle->m_uniqueId = static_cast<int>(handle);
+ //pHandle->m_pOverlaps = 0;
+ pHandle->m_clientObject = pOwner;
+ pHandle->m_collisionFilterGroup = collisionFilterGroup;
+ pHandle->m_collisionFilterMask = collisionFilterMask;
+
+ // compute current limit of edge arrays
+ BP_FP_INT_TYPE limit = static_cast<BP_FP_INT_TYPE>(m_numHandles * 2);
+
+
+ // insert new edges just inside the max boundary edge
+ for (BP_FP_INT_TYPE axis = 0; axis < 3; axis++)
+ {
+
+ m_pHandles[0].m_maxEdges[axis] += 2;
+
+ m_pEdges[axis][limit + 1] = m_pEdges[axis][limit - 1];
+
+ m_pEdges[axis][limit - 1].m_pos = min[axis];
+ m_pEdges[axis][limit - 1].m_handle = handle;
+
+ m_pEdges[axis][limit].m_pos = max[axis];
+ m_pEdges[axis][limit].m_handle = handle;
+
+ pHandle->m_minEdges[axis] = static_cast<BP_FP_INT_TYPE>(limit - 1);
+ pHandle->m_maxEdges[axis] = limit;
+ }
+
+ // now sort the new edges to their correct position
+ sortMinDown(0, pHandle->m_minEdges[0], dispatcher,false);
+ sortMaxDown(0, pHandle->m_maxEdges[0], dispatcher,false);
+ sortMinDown(1, pHandle->m_minEdges[1], dispatcher,false);
+ sortMaxDown(1, pHandle->m_maxEdges[1], dispatcher,false);
+ sortMinDown(2, pHandle->m_minEdges[2], dispatcher,true);
+ sortMaxDown(2, pHandle->m_maxEdges[2], dispatcher,true);
+
+
+ return handle;
+}
+
+
+template <typename BP_FP_INT_TYPE>
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::removeHandle(BP_FP_INT_TYPE handle,btDispatcher* dispatcher)
+{
+
+ Handle* pHandle = getHandle(handle);
+
+ //explicitly remove the pairs containing the proxy
+ //we could do it also in the sortMinUp (passing true)
+ ///@todo: compare performance
+ if (!m_pairCache->hasDeferredRemoval())
+ {
+ m_pairCache->removeOverlappingPairsContainingProxy(pHandle,dispatcher);
+ }
+
+ // compute current limit of edge arrays
+ int limit = static_cast<int>(m_numHandles * 2);
+
+ int axis;
+
+ for (axis = 0;axis<3;axis++)
+ {
+ m_pHandles[0].m_maxEdges[axis] -= 2;
+ }
+
+ // remove the edges by sorting them up to the end of the list
+ for ( axis = 0; axis < 3; axis++)
+ {
+ Edge* pEdges = m_pEdges[axis];
+ BP_FP_INT_TYPE max = pHandle->m_maxEdges[axis];
+ pEdges[max].m_pos = m_handleSentinel;
+
+ sortMaxUp(axis,max,dispatcher,false);
+
+
+ BP_FP_INT_TYPE i = pHandle->m_minEdges[axis];
+ pEdges[i].m_pos = m_handleSentinel;
+
+
+ sortMinUp(axis,i,dispatcher,false);
+
+ pEdges[limit-1].m_handle = 0;
+ pEdges[limit-1].m_pos = m_handleSentinel;
+
+#ifdef DEBUG_BROADPHASE
+ debugPrintAxis(axis,false);
+#endif //DEBUG_BROADPHASE
+
+
+ }
+
+
+ // free the handle
+ freeHandle(handle);
+
+
+}
+
+template <typename BP_FP_INT_TYPE>
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::resetPool(btDispatcher* /*dispatcher*/)
+{
+ if (m_numHandles == 0)
+ {
+ m_firstFreeHandle = 1;
+ {
+ for (BP_FP_INT_TYPE i = m_firstFreeHandle; i < m_maxHandles; i++)
+ m_pHandles[i].SetNextFree(static_cast<BP_FP_INT_TYPE>(i + 1));
+ m_pHandles[m_maxHandles - 1].SetNextFree(0);
+ }
+ }
+}
+
+
+extern int gOverlappingPairs;
+//#include <stdio.h>
+
+template <typename BP_FP_INT_TYPE>
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::calculateOverlappingPairs(btDispatcher* dispatcher)
+{
+
+ if (m_pairCache->hasDeferredRemoval())
+ {
+
+ btBroadphasePairArray& overlappingPairArray = m_pairCache->getOverlappingPairArray();
+
+ //perform a sort, to find duplicates and to sort 'invalid' pairs to the end
+ overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
+
+ overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
+ m_invalidPair = 0;
+
+
+ int i;
+
+ btBroadphasePair previousPair;
+ previousPair.m_pProxy0 = 0;
+ previousPair.m_pProxy1 = 0;
+ previousPair.m_algorithm = 0;
+
+
+ for (i=0;i<overlappingPairArray.size();i++)
+ {
+
+ btBroadphasePair& pair = overlappingPairArray[i];
+
+ bool isDuplicate = (pair == previousPair);
+
+ previousPair = pair;
+
+ bool needsRemoval = false;
+
+ if (!isDuplicate)
+ {
+ ///important to use an AABB test that is consistent with the broadphase
+ bool hasOverlap = testAabbOverlap(pair.m_pProxy0,pair.m_pProxy1);
+
+ if (hasOverlap)
+ {
+ needsRemoval = false;//callback->processOverlap(pair);
+ } else
+ {
+ needsRemoval = true;
+ }
+ } else
+ {
+ //remove duplicate
+ needsRemoval = true;
+ //should have no algorithm
+ btAssert(!pair.m_algorithm);
+ }
+
+ if (needsRemoval)
+ {
+ m_pairCache->cleanOverlappingPair(pair,dispatcher);
+
+ // m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1);
+ // m_overlappingPairArray.pop_back();
+ pair.m_pProxy0 = 0;
+ pair.m_pProxy1 = 0;
+ m_invalidPair++;
+ gOverlappingPairs--;
+ }
+
+ }
+
+ ///if you don't like to skip the invalid pairs in the array, execute following code:
+ #define CLEAN_INVALID_PAIRS 1
+ #ifdef CLEAN_INVALID_PAIRS
+
+ //perform a sort, to sort 'invalid' pairs to the end
+ overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
+
+ overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
+ m_invalidPair = 0;
+ #endif//CLEAN_INVALID_PAIRS
+
+ //printf("overlappingPairArray.size()=%d\n",overlappingPairArray.size());
+ }
+
+}
+
+
+template <typename BP_FP_INT_TYPE>
+bool btAxisSweep3Internal<BP_FP_INT_TYPE>::testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
+{
+ const Handle* pHandleA = static_cast<Handle*>(proxy0);
+ const Handle* pHandleB = static_cast<Handle*>(proxy1);
+
+ //optimization 1: check the array index (memory address), instead of the m_pos
+
+ for (int axis = 0; axis < 3; axis++)
+ {
+ if (pHandleA->m_maxEdges[axis] < pHandleB->m_minEdges[axis] ||
+ pHandleB->m_maxEdges[axis] < pHandleA->m_minEdges[axis])
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+template <typename BP_FP_INT_TYPE>
+bool btAxisSweep3Internal<BP_FP_INT_TYPE>::testOverlap2D(const Handle* pHandleA, const Handle* pHandleB,int axis0,int axis1)
+{
+ //optimization 1: check the array index (memory address), instead of the m_pos
+
+ if (pHandleA->m_maxEdges[axis0] < pHandleB->m_minEdges[axis0] ||
+ pHandleB->m_maxEdges[axis0] < pHandleA->m_minEdges[axis0] ||
+ pHandleA->m_maxEdges[axis1] < pHandleB->m_minEdges[axis1] ||
+ pHandleB->m_maxEdges[axis1] < pHandleA->m_minEdges[axis1])
+ {
+ return false;
+ }
+ return true;
+}
+
+template <typename BP_FP_INT_TYPE>
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::updateHandle(BP_FP_INT_TYPE handle, const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher)
+{
+// btAssert(bounds.IsFinite());
+ //btAssert(bounds.HasVolume());
+
+ Handle* pHandle = getHandle(handle);
+
+ // quantize the new bounds
+ BP_FP_INT_TYPE min[3], max[3];
+ quantize(min, aabbMin, 0);
+ quantize(max, aabbMax, 1);
+
+ // update changed edges
+ for (int axis = 0; axis < 3; axis++)
+ {
+ BP_FP_INT_TYPE emin = pHandle->m_minEdges[axis];
+ BP_FP_INT_TYPE emax = pHandle->m_maxEdges[axis];
+
+ int dmin = (int)min[axis] - (int)m_pEdges[axis][emin].m_pos;
+ int dmax = (int)max[axis] - (int)m_pEdges[axis][emax].m_pos;
+
+ m_pEdges[axis][emin].m_pos = min[axis];
+ m_pEdges[axis][emax].m_pos = max[axis];
+
+ // expand (only adds overlaps)
+ if (dmin < 0)
+ sortMinDown(axis, emin,dispatcher,true);
+
+ if (dmax > 0)
+ sortMaxUp(axis, emax,dispatcher,true);
+
+ // shrink (only removes overlaps)
+ if (dmin > 0)
+ sortMinUp(axis, emin,dispatcher,true);
+
+ if (dmax < 0)
+ sortMaxDown(axis, emax,dispatcher,true);
+
+#ifdef DEBUG_BROADPHASE
+ debugPrintAxis(axis);
+#endif //DEBUG_BROADPHASE
+ }
+
+
+}
+
+
+
+
+// sorting a min edge downwards can only ever *add* overlaps
+template <typename BP_FP_INT_TYPE>
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::sortMinDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* /* dispatcher */, bool updateOverlaps)
+{
+
+ Edge* pEdge = m_pEdges[axis] + edge;
+ Edge* pPrev = pEdge - 1;
+ Handle* pHandleEdge = getHandle(pEdge->m_handle);
+
+ while (pEdge->m_pos < pPrev->m_pos)
+ {
+ Handle* pHandlePrev = getHandle(pPrev->m_handle);
+
+ if (pPrev->IsMax())
+ {
+ // if previous edge is a maximum check the bounds and add an overlap if necessary
+ const int axis1 = (1 << axis) & 3;
+ const int axis2 = (1 << axis1) & 3;
+ if (updateOverlaps && testOverlap2D(pHandleEdge, pHandlePrev,axis1,axis2))
+ {
+ m_pairCache->addOverlappingPair(pHandleEdge,pHandlePrev);
+ if (m_userPairCallback)
+ m_userPairCallback->addOverlappingPair(pHandleEdge,pHandlePrev);
+
+ //AddOverlap(pEdge->m_handle, pPrev->m_handle);
+
+ }
+
+ // update edge reference in other handle
+ pHandlePrev->m_maxEdges[axis]++;
+ }
+ else
+ pHandlePrev->m_minEdges[axis]++;
+
+ pHandleEdge->m_minEdges[axis]--;
+
+ // swap the edges
+ Edge swap = *pEdge;
+ *pEdge = *pPrev;
+ *pPrev = swap;
+
+ // decrement
+ pEdge--;
+ pPrev--;
+ }
+
+#ifdef DEBUG_BROADPHASE
+ debugPrintAxis(axis);
+#endif //DEBUG_BROADPHASE
+
+}
+
+// sorting a min edge upwards can only ever *remove* overlaps
+template <typename BP_FP_INT_TYPE>
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::sortMinUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps)
+{
+ Edge* pEdge = m_pEdges[axis] + edge;
+ Edge* pNext = pEdge + 1;
+ Handle* pHandleEdge = getHandle(pEdge->m_handle);
+
+ while (pNext->m_handle && (pEdge->m_pos >= pNext->m_pos))
+ {
+ Handle* pHandleNext = getHandle(pNext->m_handle);
+
+ if (pNext->IsMax())
+ {
+ Handle* handle0 = getHandle(pEdge->m_handle);
+ Handle* handle1 = getHandle(pNext->m_handle);
+ const int axis1 = (1 << axis) & 3;
+ const int axis2 = (1 << axis1) & 3;
+
+ // if next edge is maximum remove any overlap between the two handles
+ if (updateOverlaps
+#ifdef USE_OVERLAP_TEST_ON_REMOVES
+ && testOverlap2D(handle0,handle1,axis1,axis2)
+#endif //USE_OVERLAP_TEST_ON_REMOVES
+ )
+ {
+
+
+ m_pairCache->removeOverlappingPair(handle0,handle1,dispatcher);
+ if (m_userPairCallback)
+ m_userPairCallback->removeOverlappingPair(handle0,handle1,dispatcher);
+
+ }
+
+
+ // update edge reference in other handle
+ pHandleNext->m_maxEdges[axis]--;
+ }
+ else
+ pHandleNext->m_minEdges[axis]--;
+
+ pHandleEdge->m_minEdges[axis]++;
+
+ // swap the edges
+ Edge swap = *pEdge;
+ *pEdge = *pNext;
+ *pNext = swap;
+
+ // increment
+ pEdge++;
+ pNext++;
+ }
+
+
+}
+
+// sorting a max edge downwards can only ever *remove* overlaps
+template <typename BP_FP_INT_TYPE>
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::sortMaxDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps)
+{
+
+ Edge* pEdge = m_pEdges[axis] + edge;
+ Edge* pPrev = pEdge - 1;
+ Handle* pHandleEdge = getHandle(pEdge->m_handle);
+
+ while (pEdge->m_pos < pPrev->m_pos)
+ {
+ Handle* pHandlePrev = getHandle(pPrev->m_handle);
+
+ if (!pPrev->IsMax())
+ {
+ // if previous edge was a minimum remove any overlap between the two handles
+ Handle* handle0 = getHandle(pEdge->m_handle);
+ Handle* handle1 = getHandle(pPrev->m_handle);
+ const int axis1 = (1 << axis) & 3;
+ const int axis2 = (1 << axis1) & 3;
+
+ if (updateOverlaps
+#ifdef USE_OVERLAP_TEST_ON_REMOVES
+ && testOverlap2D(handle0,handle1,axis1,axis2)
+#endif //USE_OVERLAP_TEST_ON_REMOVES
+ )
+ {
+ //this is done during the overlappingpairarray iteration/narrowphase collision
+
+
+ m_pairCache->removeOverlappingPair(handle0,handle1,dispatcher);
+ if (m_userPairCallback)
+ m_userPairCallback->removeOverlappingPair(handle0,handle1,dispatcher);
+
+
+
+ }
+
+ // update edge reference in other handle
+ pHandlePrev->m_minEdges[axis]++;;
+ }
+ else
+ pHandlePrev->m_maxEdges[axis]++;
+
+ pHandleEdge->m_maxEdges[axis]--;
+
+ // swap the edges
+ Edge swap = *pEdge;
+ *pEdge = *pPrev;
+ *pPrev = swap;
+
+ // decrement
+ pEdge--;
+ pPrev--;
+ }
+
+
+#ifdef DEBUG_BROADPHASE
+ debugPrintAxis(axis);
+#endif //DEBUG_BROADPHASE
+
+}
+
+// sorting a max edge upwards can only ever *add* overlaps
+template <typename BP_FP_INT_TYPE>
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::sortMaxUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* /* dispatcher */, bool updateOverlaps)
+{
+ Edge* pEdge = m_pEdges[axis] + edge;
+ Edge* pNext = pEdge + 1;
+ Handle* pHandleEdge = getHandle(pEdge->m_handle);
+
+ while (pNext->m_handle && (pEdge->m_pos >= pNext->m_pos))
+ {
+ Handle* pHandleNext = getHandle(pNext->m_handle);
+
+ const int axis1 = (1 << axis) & 3;
+ const int axis2 = (1 << axis1) & 3;
+
+ if (!pNext->IsMax())
+ {
+ // if next edge is a minimum check the bounds and add an overlap if necessary
+ if (updateOverlaps && testOverlap2D(pHandleEdge, pHandleNext,axis1,axis2))
+ {
+ Handle* handle0 = getHandle(pEdge->m_handle);
+ Handle* handle1 = getHandle(pNext->m_handle);
+ m_pairCache->addOverlappingPair(handle0,handle1);
+ if (m_userPairCallback)
+ m_userPairCallback->addOverlappingPair(handle0,handle1);
+ }
+
+ // update edge reference in other handle
+ pHandleNext->m_minEdges[axis]--;
+ }
+ else
+ pHandleNext->m_maxEdges[axis]--;
+
+ pHandleEdge->m_maxEdges[axis]++;
+
+ // swap the edges
+ Edge swap = *pEdge;
+ *pEdge = *pNext;
+ *pNext = swap;
+
+ // increment
+ pEdge++;
+ pNext++;
+ }
+
+}
+
+#endif
diff --git a/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h b/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h
new file mode 100644
index 0000000000..fb68e0024e
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h
@@ -0,0 +1,86 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_BROADPHASE_INTERFACE_H
+#define BT_BROADPHASE_INTERFACE_H
+
+
+
+struct btDispatcherInfo;
+class btDispatcher;
+#include "btBroadphaseProxy.h"
+
+class btOverlappingPairCache;
+
+
+
+struct btBroadphaseAabbCallback
+{
+ virtual ~btBroadphaseAabbCallback() {}
+ virtual bool process(const btBroadphaseProxy* proxy) = 0;
+};
+
+
+struct btBroadphaseRayCallback : public btBroadphaseAabbCallback
+{
+ ///added some cached data to accelerate ray-AABB tests
+ btVector3 m_rayDirectionInverse;
+ unsigned int m_signs[3];
+ btScalar m_lambda_max;
+
+ virtual ~btBroadphaseRayCallback() {}
+
+protected:
+
+ btBroadphaseRayCallback() {}
+};
+
+#include "LinearMath/btVector3.h"
+
+///The btBroadphaseInterface class provides an interface to detect aabb-overlapping object pairs.
+///Some implementations for this broadphase interface include btAxisSweep3, bt32BitAxisSweep3 and btDbvtBroadphase.
+///The actual overlapping pair management, storage, adding and removing of pairs is dealt by the btOverlappingPairCache class.
+class btBroadphaseInterface
+{
+public:
+ virtual ~btBroadphaseInterface() {}
+
+ virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, int collisionFilterGroup, int collisionFilterMask, btDispatcher* dispatcher) =0;
+ virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)=0;
+ virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher)=0;
+ virtual void getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const =0;
+
+ virtual void rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin=btVector3(0,0,0), const btVector3& aabbMax = btVector3(0,0,0)) = 0;
+
+ virtual void aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback) = 0;
+
+ ///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb
+ virtual void calculateOverlappingPairs(btDispatcher* dispatcher)=0;
+
+ virtual btOverlappingPairCache* getOverlappingPairCache()=0;
+ virtual const btOverlappingPairCache* getOverlappingPairCache() const =0;
+
+ ///getAabb returns the axis aligned bounding box in the 'global' coordinate frame
+ ///will add some transform later
+ virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const =0;
+
+ ///reset broadphase internal structures, to ensure determinism/reproducability
+ virtual void resetPool(btDispatcher* dispatcher) { (void) dispatcher; };
+
+ virtual void printStats() = 0;
+
+};
+
+#endif //BT_BROADPHASE_INTERFACE_H
diff --git a/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp b/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp
new file mode 100644
index 0000000000..0fd4ef46be
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp
@@ -0,0 +1,18 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btBroadphaseProxy.h"
+
+BT_NOT_EMPTY_FILE // fix warning LNK4221: This object file does not define any previously undefined public symbols, so it will not be used by any link operation that consumes this library
diff --git a/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h b/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h
new file mode 100644
index 0000000000..adaf083a21
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h
@@ -0,0 +1,269 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_BROADPHASE_PROXY_H
+#define BT_BROADPHASE_PROXY_H
+
+#include "LinearMath/btScalar.h" //for SIMD_FORCE_INLINE
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btAlignedAllocator.h"
+
+
+/// btDispatcher uses these types
+/// IMPORTANT NOTE:The types are ordered polyhedral, implicit convex and concave
+/// to facilitate type checking
+/// CUSTOM_POLYHEDRAL_SHAPE_TYPE,CUSTOM_CONVEX_SHAPE_TYPE and CUSTOM_CONCAVE_SHAPE_TYPE can be used to extend Bullet without modifying source code
+enum BroadphaseNativeTypes
+{
+ // polyhedral convex shapes
+ BOX_SHAPE_PROXYTYPE,
+ TRIANGLE_SHAPE_PROXYTYPE,
+ TETRAHEDRAL_SHAPE_PROXYTYPE,
+ CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE,
+ CONVEX_HULL_SHAPE_PROXYTYPE,
+ CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE,
+ CUSTOM_POLYHEDRAL_SHAPE_TYPE,
+//implicit convex shapes
+IMPLICIT_CONVEX_SHAPES_START_HERE,
+ SPHERE_SHAPE_PROXYTYPE,
+ MULTI_SPHERE_SHAPE_PROXYTYPE,
+ CAPSULE_SHAPE_PROXYTYPE,
+ CONE_SHAPE_PROXYTYPE,
+ CONVEX_SHAPE_PROXYTYPE,
+ CYLINDER_SHAPE_PROXYTYPE,
+ UNIFORM_SCALING_SHAPE_PROXYTYPE,
+ MINKOWSKI_SUM_SHAPE_PROXYTYPE,
+ MINKOWSKI_DIFFERENCE_SHAPE_PROXYTYPE,
+ BOX_2D_SHAPE_PROXYTYPE,
+ CONVEX_2D_SHAPE_PROXYTYPE,
+ CUSTOM_CONVEX_SHAPE_TYPE,
+//concave shapes
+CONCAVE_SHAPES_START_HERE,
+ //keep all the convex shapetype below here, for the check IsConvexShape in broadphase proxy!
+ TRIANGLE_MESH_SHAPE_PROXYTYPE,
+ SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE,
+ ///used for demo integration FAST/Swift collision library and Bullet
+ FAST_CONCAVE_MESH_PROXYTYPE,
+ //terrain
+ TERRAIN_SHAPE_PROXYTYPE,
+///Used for GIMPACT Trimesh integration
+ GIMPACT_SHAPE_PROXYTYPE,
+///Multimaterial mesh
+ MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE,
+
+ EMPTY_SHAPE_PROXYTYPE,
+ STATIC_PLANE_PROXYTYPE,
+ CUSTOM_CONCAVE_SHAPE_TYPE,
+CONCAVE_SHAPES_END_HERE,
+
+ COMPOUND_SHAPE_PROXYTYPE,
+
+ SOFTBODY_SHAPE_PROXYTYPE,
+ HFFLUID_SHAPE_PROXYTYPE,
+ HFFLUID_BUOYANT_CONVEX_SHAPE_PROXYTYPE,
+ INVALID_SHAPE_PROXYTYPE,
+
+ MAX_BROADPHASE_COLLISION_TYPES
+
+};
+
+
+///The btBroadphaseProxy is the main class that can be used with the Bullet broadphases.
+///It stores collision shape type information, collision filter information and a client object, typically a btCollisionObject or btRigidBody.
+ATTRIBUTE_ALIGNED16(struct) btBroadphaseProxy
+{
+
+BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ ///optional filtering to cull potential collisions
+ enum CollisionFilterGroups
+ {
+ DefaultFilter = 1,
+ StaticFilter = 2,
+ KinematicFilter = 4,
+ DebrisFilter = 8,
+ SensorTrigger = 16,
+ CharacterFilter = 32,
+ AllFilter = -1 //all bits sets: DefaultFilter | StaticFilter | KinematicFilter | DebrisFilter | SensorTrigger
+ };
+
+ //Usually the client btCollisionObject or Rigidbody class
+ void* m_clientObject;
+ int m_collisionFilterGroup;
+ int m_collisionFilterMask;
+
+ int m_uniqueId;//m_uniqueId is introduced for paircache. could get rid of this, by calculating the address offset etc.
+
+ btVector3 m_aabbMin;
+ btVector3 m_aabbMax;
+
+ SIMD_FORCE_INLINE int getUid() const
+ {
+ return m_uniqueId;
+ }
+
+ //used for memory pools
+ btBroadphaseProxy() :m_clientObject(0)
+ {
+ }
+
+ btBroadphaseProxy(const btVector3& aabbMin,const btVector3& aabbMax,void* userPtr, int collisionFilterGroup, int collisionFilterMask)
+ :m_clientObject(userPtr),
+ m_collisionFilterGroup(collisionFilterGroup),
+ m_collisionFilterMask(collisionFilterMask),
+ m_aabbMin(aabbMin),
+ m_aabbMax(aabbMax)
+ {
+ }
+
+
+
+ static SIMD_FORCE_INLINE bool isPolyhedral(int proxyType)
+ {
+ return (proxyType < IMPLICIT_CONVEX_SHAPES_START_HERE);
+ }
+
+ static SIMD_FORCE_INLINE bool isConvex(int proxyType)
+ {
+ return (proxyType < CONCAVE_SHAPES_START_HERE);
+ }
+
+ static SIMD_FORCE_INLINE bool isNonMoving(int proxyType)
+ {
+ return (isConcave(proxyType) && !(proxyType==GIMPACT_SHAPE_PROXYTYPE));
+ }
+
+ static SIMD_FORCE_INLINE bool isConcave(int proxyType)
+ {
+ return ((proxyType > CONCAVE_SHAPES_START_HERE) &&
+ (proxyType < CONCAVE_SHAPES_END_HERE));
+ }
+ static SIMD_FORCE_INLINE bool isCompound(int proxyType)
+ {
+ return (proxyType == COMPOUND_SHAPE_PROXYTYPE);
+ }
+
+ static SIMD_FORCE_INLINE bool isSoftBody(int proxyType)
+ {
+ return (proxyType == SOFTBODY_SHAPE_PROXYTYPE);
+ }
+
+ static SIMD_FORCE_INLINE bool isInfinite(int proxyType)
+ {
+ return (proxyType == STATIC_PLANE_PROXYTYPE);
+ }
+
+ static SIMD_FORCE_INLINE bool isConvex2d(int proxyType)
+ {
+ return (proxyType == BOX_2D_SHAPE_PROXYTYPE) || (proxyType == CONVEX_2D_SHAPE_PROXYTYPE);
+ }
+
+
+}
+;
+
+class btCollisionAlgorithm;
+
+struct btBroadphaseProxy;
+
+
+
+///The btBroadphasePair class contains a pair of aabb-overlapping objects.
+///A btDispatcher can search a btCollisionAlgorithm that performs exact/narrowphase collision detection on the actual collision shapes.
+ATTRIBUTE_ALIGNED16(struct) btBroadphasePair
+{
+ btBroadphasePair ()
+ :
+ m_pProxy0(0),
+ m_pProxy1(0),
+ m_algorithm(0),
+ m_internalInfo1(0)
+ {
+ }
+
+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
+ if (proxy0.m_uniqueId < proxy1.m_uniqueId)
+ {
+ m_pProxy0 = &proxy0;
+ m_pProxy1 = &proxy1;
+ }
+ else
+ {
+ m_pProxy0 = &proxy1;
+ m_pProxy1 = &proxy0;
+ }
+
+ m_algorithm = 0;
+ m_internalInfo1 = 0;
+
+ }
+
+ btBroadphaseProxy* m_pProxy0;
+ btBroadphaseProxy* m_pProxy1;
+
+ mutable btCollisionAlgorithm* m_algorithm;
+ union { void* m_internalInfo1; int m_internalTmpValue;};//don't use this data, it will be removed in future version.
+
+};
+
+/*
+//comparison for set operation, see Solid DT_Encounter
+SIMD_FORCE_INLINE bool operator<(const btBroadphasePair& a, const btBroadphasePair& b)
+{
+ return a.m_pProxy0 < b.m_pProxy0 ||
+ (a.m_pProxy0 == b.m_pProxy0 && a.m_pProxy1 < b.m_pProxy1);
+}
+*/
+
+
+
+class btBroadphasePairSortPredicate
+{
+ public:
+
+ bool operator() ( const btBroadphasePair& a, const btBroadphasePair& b ) const
+ {
+ const int uidA0 = a.m_pProxy0 ? a.m_pProxy0->m_uniqueId : -1;
+ const int uidB0 = b.m_pProxy0 ? b.m_pProxy0->m_uniqueId : -1;
+ const int uidA1 = a.m_pProxy1 ? a.m_pProxy1->m_uniqueId : -1;
+ const int uidB1 = b.m_pProxy1 ? b.m_pProxy1->m_uniqueId : -1;
+
+ return uidA0 > uidB0 ||
+ (a.m_pProxy0 == b.m_pProxy0 && uidA1 > uidB1) ||
+ (a.m_pProxy0 == b.m_pProxy0 && a.m_pProxy1 == b.m_pProxy1 && a.m_algorithm > b.m_algorithm);
+ }
+};
+
+
+SIMD_FORCE_INLINE bool operator==(const btBroadphasePair& a, const btBroadphasePair& b)
+{
+ return (a.m_pProxy0 == b.m_pProxy0) && (a.m_pProxy1 == b.m_pProxy1);
+}
+
+
+#endif //BT_BROADPHASE_PROXY_H
+
diff --git a/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp b/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp
new file mode 100644
index 0000000000..c95d1be0f2
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp
@@ -0,0 +1,23 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btCollisionAlgorithm.h"
+#include "btDispatcher.h"
+
+btCollisionAlgorithm::btCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
+{
+ m_dispatcher = ci.m_dispatcher1;
+}
+
diff --git a/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h b/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h
new file mode 100644
index 0000000000..405656236b
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h
@@ -0,0 +1,81 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_COLLISION_ALGORITHM_H
+#define BT_COLLISION_ALGORITHM_H
+
+#include "LinearMath/btScalar.h"
+#include "LinearMath/btAlignedObjectArray.h"
+
+struct btBroadphaseProxy;
+class btDispatcher;
+class btManifoldResult;
+class btCollisionObject;
+struct btCollisionObjectWrapper;
+struct btDispatcherInfo;
+class btPersistentManifold;
+
+typedef btAlignedObjectArray<btPersistentManifold*> btManifoldArray;
+
+struct btCollisionAlgorithmConstructionInfo
+{
+ btCollisionAlgorithmConstructionInfo()
+ :m_dispatcher1(0),
+ m_manifold(0)
+ {
+ }
+ btCollisionAlgorithmConstructionInfo(btDispatcher* dispatcher,int temp)
+ :m_dispatcher1(dispatcher)
+ {
+ (void)temp;
+ }
+
+ btDispatcher* m_dispatcher1;
+ btPersistentManifold* m_manifold;
+
+// int getDispatcherId();
+
+};
+
+
+///btCollisionAlgorithm is an collision interface that is compatible with the Broadphase and btDispatcher.
+///It is persistent over frames
+class btCollisionAlgorithm
+{
+
+protected:
+
+ btDispatcher* m_dispatcher;
+
+protected:
+// int getDispatcherId();
+
+public:
+
+ btCollisionAlgorithm() {};
+
+ btCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci);
+
+ virtual ~btCollisionAlgorithm() {};
+
+ virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) = 0;
+
+ virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) = 0;
+
+ virtual void getAllContactManifolds(btManifoldArray& manifoldArray) = 0;
+};
+
+
+#endif //BT_COLLISION_ALGORITHM_H
diff --git a/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btDbvt.cpp b/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btDbvt.cpp
new file mode 100644
index 0000000000..d791d07418
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btDbvt.cpp
@@ -0,0 +1,1329 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+///btDbvt implementation by Nathanael Presson
+
+#include "btDbvt.h"
+
+//
+typedef btAlignedObjectArray<btDbvtNode*> tNodeArray;
+typedef btAlignedObjectArray<const btDbvtNode*> tConstNodeArray;
+
+//
+struct btDbvtNodeEnumerator : btDbvt::ICollide
+{
+ tConstNodeArray nodes;
+ void Process(const btDbvtNode* n) { nodes.push_back(n); }
+};
+
+//
+static DBVT_INLINE int indexof(const btDbvtNode* node)
+{
+ return(node->parent->childs[1]==node);
+}
+
+//
+static DBVT_INLINE btDbvtVolume merge( const btDbvtVolume& a,
+ const btDbvtVolume& b)
+{
+#if (DBVT_MERGE_IMPL==DBVT_IMPL_SSE)
+ ATTRIBUTE_ALIGNED16( char locals[sizeof(btDbvtAabbMm)]);
+ btDbvtVolume* ptr = (btDbvtVolume*) locals;
+ btDbvtVolume& res=*ptr;
+#else
+ btDbvtVolume res;
+#endif
+ Merge(a,b,res);
+ return(res);
+}
+
+// volume+edge lengths
+static DBVT_INLINE btScalar size(const btDbvtVolume& a)
+{
+ const btVector3 edges=a.Lengths();
+ return( edges.x()*edges.y()*edges.z()+
+ edges.x()+edges.y()+edges.z());
+}
+
+//
+static void getmaxdepth(const btDbvtNode* node,int depth,int& maxdepth)
+{
+ if(node->isinternal())
+ {
+ getmaxdepth(node->childs[0],depth+1,maxdepth);
+ getmaxdepth(node->childs[1],depth+1,maxdepth);
+ } else maxdepth=btMax(maxdepth,depth);
+}
+
+//
+static DBVT_INLINE void deletenode( btDbvt* pdbvt,
+ btDbvtNode* node)
+{
+ btAlignedFree(pdbvt->m_free);
+ pdbvt->m_free=node;
+}
+
+//
+static void recursedeletenode( btDbvt* pdbvt,
+ btDbvtNode* node)
+{
+ if(!node->isleaf())
+ {
+ recursedeletenode(pdbvt,node->childs[0]);
+ recursedeletenode(pdbvt,node->childs[1]);
+ }
+ if(node==pdbvt->m_root) pdbvt->m_root=0;
+ deletenode(pdbvt,node);
+}
+
+//
+static DBVT_INLINE btDbvtNode* createnode( btDbvt* pdbvt,
+ btDbvtNode* parent,
+ void* data)
+{
+ btDbvtNode* node;
+ if(pdbvt->m_free)
+ { node=pdbvt->m_free;pdbvt->m_free=0; }
+ else
+ { node=new(btAlignedAlloc(sizeof(btDbvtNode),16)) btDbvtNode(); }
+ node->parent = parent;
+ node->data = data;
+ node->childs[1] = 0;
+ return(node);
+}
+
+//
+static DBVT_INLINE btDbvtNode* createnode( btDbvt* pdbvt,
+ btDbvtNode* parent,
+ const btDbvtVolume& volume,
+ void* data)
+{
+ btDbvtNode* node=createnode(pdbvt,parent,data);
+ node->volume=volume;
+ return(node);
+}
+
+//
+static DBVT_INLINE btDbvtNode* createnode( btDbvt* pdbvt,
+ btDbvtNode* parent,
+ const btDbvtVolume& volume0,
+ const btDbvtVolume& volume1,
+ void* data)
+{
+ btDbvtNode* node=createnode(pdbvt,parent,data);
+ Merge(volume0,volume1,node->volume);
+ return(node);
+}
+
+//
+static void insertleaf( btDbvt* pdbvt,
+ btDbvtNode* root,
+ btDbvtNode* leaf)
+{
+ if(!pdbvt->m_root)
+ {
+ pdbvt->m_root = leaf;
+ leaf->parent = 0;
+ }
+ else
+ {
+ if(!root->isleaf())
+ {
+ do {
+ root=root->childs[Select( leaf->volume,
+ root->childs[0]->volume,
+ root->childs[1]->volume)];
+ } while(!root->isleaf());
+ }
+ btDbvtNode* prev=root->parent;
+ btDbvtNode* node=createnode(pdbvt,prev,leaf->volume,root->volume,0);
+ if(prev)
+ {
+ prev->childs[indexof(root)] = node;
+ node->childs[0] = root;root->parent=node;
+ node->childs[1] = leaf;leaf->parent=node;
+ do {
+ if(!prev->volume.Contain(node->volume))
+ Merge(prev->childs[0]->volume,prev->childs[1]->volume,prev->volume);
+ else
+ break;
+ node=prev;
+ } while(0!=(prev=node->parent));
+ }
+ else
+ {
+ node->childs[0] = root;root->parent=node;
+ node->childs[1] = leaf;leaf->parent=node;
+ pdbvt->m_root = node;
+ }
+ }
+}
+
+//
+static btDbvtNode* removeleaf( btDbvt* pdbvt,
+ btDbvtNode* leaf)
+{
+ if(leaf==pdbvt->m_root)
+ {
+ pdbvt->m_root=0;
+ return(0);
+ }
+ else
+ {
+ btDbvtNode* parent=leaf->parent;
+ btDbvtNode* prev=parent->parent;
+ btDbvtNode* sibling=parent->childs[1-indexof(leaf)];
+ if(prev)
+ {
+ prev->childs[indexof(parent)]=sibling;
+ sibling->parent=prev;
+ deletenode(pdbvt,parent);
+ while(prev)
+ {
+ const btDbvtVolume pb=prev->volume;
+ Merge(prev->childs[0]->volume,prev->childs[1]->volume,prev->volume);
+ if(NotEqual(pb,prev->volume))
+ {
+ prev=prev->parent;
+ } else break;
+ }
+ return(prev?prev:pdbvt->m_root);
+ }
+ else
+ {
+ pdbvt->m_root=sibling;
+ sibling->parent=0;
+ deletenode(pdbvt,parent);
+ return(pdbvt->m_root);
+ }
+ }
+}
+
+//
+static void fetchleaves(btDbvt* pdbvt,
+ btDbvtNode* root,
+ tNodeArray& leaves,
+ int depth=-1)
+{
+ if(root->isinternal()&&depth)
+ {
+ fetchleaves(pdbvt,root->childs[0],leaves,depth-1);
+ fetchleaves(pdbvt,root->childs[1],leaves,depth-1);
+ deletenode(pdbvt,root);
+ }
+ else
+ {
+ leaves.push_back(root);
+ }
+}
+
+//
+static bool leftOfAxis( const btDbvtNode* node,
+ const btVector3& org,
+ const btVector3& axis)
+{
+ return btDot(axis, node->volume.Center() - org) <= 0;
+}
+
+
+// Partitions leaves such that leaves[0, n) are on the
+// left of axis, and leaves[n, count) are on the right
+// of axis. returns N.
+static int split( btDbvtNode** leaves,
+ int count,
+ const btVector3& org,
+ const btVector3& axis)
+{
+ int begin=0;
+ int end=count;
+ for(;;)
+ {
+ while(begin!=end && leftOfAxis(leaves[begin],org,axis))
+ {
+ ++begin;
+ }
+
+ if(begin==end)
+ {
+ break;
+ }
+
+ while(begin!=end && !leftOfAxis(leaves[end-1],org,axis))
+ {
+ --end;
+ }
+
+ if(begin==end)
+ {
+ break;
+ }
+
+ // swap out of place nodes
+ --end;
+ btDbvtNode* temp=leaves[begin];
+ leaves[begin]=leaves[end];
+ leaves[end]=temp;
+ ++begin;
+ }
+
+ return begin;
+}
+
+//
+static btDbvtVolume bounds( btDbvtNode** leaves,
+ int count)
+{
+#if DBVT_MERGE_IMPL==DBVT_IMPL_SSE
+ ATTRIBUTE_ALIGNED16(char locals[sizeof(btDbvtVolume)]);
+ btDbvtVolume* ptr = (btDbvtVolume*) locals;
+ btDbvtVolume& volume=*ptr;
+ volume=leaves[0]->volume;
+#else
+ btDbvtVolume volume=leaves[0]->volume;
+#endif
+ for(int i=1,ni=count;i<ni;++i)
+ {
+ Merge(volume,leaves[i]->volume,volume);
+ }
+ return(volume);
+}
+
+//
+static void bottomup( btDbvt* pdbvt,
+ btDbvtNode** leaves,
+ int count)
+{
+ while(count>1)
+ {
+ btScalar minsize=SIMD_INFINITY;
+ int minidx[2]={-1,-1};
+ for(int i=0;i<count;++i)
+ {
+ for(int j=i+1;j<count;++j)
+ {
+ const btScalar sz=size(merge(leaves[i]->volume,leaves[j]->volume));
+ if(sz<minsize)
+ {
+ minsize = sz;
+ minidx[0] = i;
+ minidx[1] = j;
+ }
+ }
+ }
+ btDbvtNode* n[] = {leaves[minidx[0]],leaves[minidx[1]]};
+ btDbvtNode* p = createnode(pdbvt,0,n[0]->volume,n[1]->volume,0);
+ p->childs[0] = n[0];
+ p->childs[1] = n[1];
+ n[0]->parent = p;
+ n[1]->parent = p;
+ leaves[minidx[0]] = p;
+ leaves[minidx[1]] = leaves[count-1];
+ --count;
+ }
+}
+
+//
+static btDbvtNode* topdown(btDbvt* pdbvt,
+ btDbvtNode** leaves,
+ int count,
+ int bu_treshold)
+{
+ static const btVector3 axis[]={btVector3(1,0,0),
+ btVector3(0,1,0),
+ btVector3(0,0,1)};
+ btAssert(bu_treshold>2);
+ if(count>1)
+ {
+ if(count>bu_treshold)
+ {
+ const btDbvtVolume vol=bounds(leaves,count);
+ const btVector3 org=vol.Center();
+ int partition;
+ int bestaxis=-1;
+ int bestmidp=count;
+ int splitcount[3][2]={{0,0},{0,0},{0,0}};
+ int i;
+ for( i=0;i<count;++i)
+ {
+ const btVector3 x=leaves[i]->volume.Center()-org;
+ for(int j=0;j<3;++j)
+ {
+ ++splitcount[j][btDot(x,axis[j])>0?1:0];
+ }
+ }
+ for( i=0;i<3;++i)
+ {
+ if((splitcount[i][0]>0)&&(splitcount[i][1]>0))
+ {
+ const int midp=(int)btFabs(btScalar(splitcount[i][0]-splitcount[i][1]));
+ if(midp<bestmidp)
+ {
+ bestaxis=i;
+ bestmidp=midp;
+ }
+ }
+ }
+ if(bestaxis>=0)
+ {
+ partition=split(leaves,count,org,axis[bestaxis]);
+ btAssert(partition!=0 && partition!=count);
+ }
+ else
+ {
+ partition=count/2+1;
+ }
+ btDbvtNode* node=createnode(pdbvt,0,vol,0);
+ node->childs[0]=topdown(pdbvt,&leaves[0],partition,bu_treshold);
+ node->childs[1]=topdown(pdbvt,&leaves[partition],count-partition,bu_treshold);
+ node->childs[0]->parent=node;
+ node->childs[1]->parent=node;
+ return(node);
+ }
+ else
+ {
+ bottomup(pdbvt,leaves,count);
+ return(leaves[0]);
+ }
+ }
+ return(leaves[0]);
+}
+
+//
+static DBVT_INLINE btDbvtNode* sort(btDbvtNode* n,btDbvtNode*& r)
+{
+ btDbvtNode* p=n->parent;
+ btAssert(n->isinternal());
+ if(p>n)
+ {
+ const int i=indexof(n);
+ const int j=1-i;
+ btDbvtNode* s=p->childs[j];
+ btDbvtNode* q=p->parent;
+ btAssert(n==p->childs[i]);
+ if(q) q->childs[indexof(p)]=n; else r=n;
+ s->parent=n;
+ p->parent=n;
+ n->parent=q;
+ p->childs[0]=n->childs[0];
+ p->childs[1]=n->childs[1];
+ n->childs[0]->parent=p;
+ n->childs[1]->parent=p;
+ n->childs[i]=p;
+ n->childs[j]=s;
+ btSwap(p->volume,n->volume);
+ return(p);
+ }
+ return(n);
+}
+
+#if 0
+static DBVT_INLINE btDbvtNode* walkup(btDbvtNode* n,int count)
+{
+ while(n&&(count--)) n=n->parent;
+ return(n);
+}
+#endif
+
+//
+// Api
+//
+
+//
+btDbvt::btDbvt()
+{
+ m_root = 0;
+ m_free = 0;
+ m_lkhd = -1;
+ m_leaves = 0;
+ m_opath = 0;
+}
+
+//
+btDbvt::~btDbvt()
+{
+ clear();
+}
+
+//
+void btDbvt::clear()
+{
+ if(m_root)
+ recursedeletenode(this,m_root);
+ btAlignedFree(m_free);
+ m_free=0;
+ m_lkhd = -1;
+ m_stkStack.clear();
+ m_opath = 0;
+
+}
+
+//
+void btDbvt::optimizeBottomUp()
+{
+ if(m_root)
+ {
+ tNodeArray leaves;
+ leaves.reserve(m_leaves);
+ fetchleaves(this,m_root,leaves);
+ bottomup(this,&leaves[0],leaves.size());
+ m_root=leaves[0];
+ }
+}
+
+//
+void btDbvt::optimizeTopDown(int bu_treshold)
+{
+ if(m_root)
+ {
+ tNodeArray leaves;
+ leaves.reserve(m_leaves);
+ fetchleaves(this,m_root,leaves);
+ m_root=topdown(this,&leaves[0],leaves.size(),bu_treshold);
+ }
+}
+
+//
+void btDbvt::optimizeIncremental(int passes)
+{
+ if(passes<0) passes=m_leaves;
+ if(m_root&&(passes>0))
+ {
+ do {
+ btDbvtNode* node=m_root;
+ unsigned bit=0;
+ while(node->isinternal())
+ {
+ node=sort(node,m_root)->childs[(m_opath>>bit)&1];
+ bit=(bit+1)&(sizeof(unsigned)*8-1);
+ }
+ update(node);
+ ++m_opath;
+ } while(--passes);
+ }
+}
+
+//
+btDbvtNode* btDbvt::insert(const btDbvtVolume& volume,void* data)
+{
+ btDbvtNode* leaf=createnode(this,0,volume,data);
+ insertleaf(this,m_root,leaf);
+ ++m_leaves;
+ return(leaf);
+}
+
+//
+void btDbvt::update(btDbvtNode* leaf,int lookahead)
+{
+ btDbvtNode* root=removeleaf(this,leaf);
+ if(root)
+ {
+ if(lookahead>=0)
+ {
+ for(int i=0;(i<lookahead)&&root->parent;++i)
+ {
+ root=root->parent;
+ }
+ } else root=m_root;
+ }
+ insertleaf(this,root,leaf);
+}
+
+//
+void btDbvt::update(btDbvtNode* leaf,btDbvtVolume& volume)
+{
+ btDbvtNode* root=removeleaf(this,leaf);
+ if(root)
+ {
+ if(m_lkhd>=0)
+ {
+ for(int i=0;(i<m_lkhd)&&root->parent;++i)
+ {
+ root=root->parent;
+ }
+ } else root=m_root;
+ }
+ leaf->volume=volume;
+ insertleaf(this,root,leaf);
+}
+
+//
+bool btDbvt::update(btDbvtNode* leaf,btDbvtVolume& volume,const btVector3& velocity,btScalar margin)
+{
+ if(leaf->volume.Contain(volume)) return(false);
+ volume.Expand(btVector3(margin,margin,margin));
+ volume.SignedExpand(velocity);
+ update(leaf,volume);
+ return(true);
+}
+
+//
+bool btDbvt::update(btDbvtNode* leaf,btDbvtVolume& volume,const btVector3& velocity)
+{
+ if(leaf->volume.Contain(volume)) return(false);
+ volume.SignedExpand(velocity);
+ update(leaf,volume);
+ return(true);
+}
+
+//
+bool btDbvt::update(btDbvtNode* leaf,btDbvtVolume& volume,btScalar margin)
+{
+ if(leaf->volume.Contain(volume)) return(false);
+ volume.Expand(btVector3(margin,margin,margin));
+ update(leaf,volume);
+ return(true);
+}
+
+//
+void btDbvt::remove(btDbvtNode* leaf)
+{
+ removeleaf(this,leaf);
+ deletenode(this,leaf);
+ --m_leaves;
+}
+
+//
+void btDbvt::write(IWriter* iwriter) const
+{
+ btDbvtNodeEnumerator nodes;
+ nodes.nodes.reserve(m_leaves*2);
+ enumNodes(m_root,nodes);
+ iwriter->Prepare(m_root,nodes.nodes.size());
+ for(int i=0;i<nodes.nodes.size();++i)
+ {
+ const btDbvtNode* n=nodes.nodes[i];
+ int p=-1;
+ if(n->parent) p=nodes.nodes.findLinearSearch(n->parent);
+ if(n->isinternal())
+ {
+ const int c0=nodes.nodes.findLinearSearch(n->childs[0]);
+ const int c1=nodes.nodes.findLinearSearch(n->childs[1]);
+ iwriter->WriteNode(n,i,p,c0,c1);
+ }
+ else
+ {
+ iwriter->WriteLeaf(n,i,p);
+ }
+ }
+}
+
+//
+void btDbvt::clone(btDbvt& dest,IClone* iclone) const
+{
+ dest.clear();
+ if(m_root!=0)
+ {
+ btAlignedObjectArray<sStkCLN> stack;
+ stack.reserve(m_leaves);
+ stack.push_back(sStkCLN(m_root,0));
+ do {
+ const int i=stack.size()-1;
+ const sStkCLN e=stack[i];
+ btDbvtNode* n=createnode(&dest,e.parent,e.node->volume,e.node->data);
+ stack.pop_back();
+ if(e.parent!=0)
+ e.parent->childs[i&1]=n;
+ else
+ dest.m_root=n;
+ if(e.node->isinternal())
+ {
+ stack.push_back(sStkCLN(e.node->childs[0],n));
+ stack.push_back(sStkCLN(e.node->childs[1],n));
+ }
+ else
+ {
+ iclone->CloneLeaf(n);
+ }
+ } while(stack.size()>0);
+ }
+}
+
+//
+int btDbvt::maxdepth(const btDbvtNode* node)
+{
+ int depth=0;
+ if(node) getmaxdepth(node,1,depth);
+ return(depth);
+}
+
+//
+int btDbvt::countLeaves(const btDbvtNode* node)
+{
+ if(node->isinternal())
+ return(countLeaves(node->childs[0])+countLeaves(node->childs[1]));
+ else
+ return(1);
+}
+
+//
+void btDbvt::extractLeaves(const btDbvtNode* node,btAlignedObjectArray<const btDbvtNode*>& leaves)
+{
+ if(node->isinternal())
+ {
+ extractLeaves(node->childs[0],leaves);
+ extractLeaves(node->childs[1],leaves);
+ }
+ else
+ {
+ leaves.push_back(node);
+ }
+}
+
+//
+#if DBVT_ENABLE_BENCHMARK
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "LinearMath/btQuickProf.h"
+
+/*
+q6600,2.4ghz
+
+/Ox /Ob2 /Oi /Ot /I "." /I "..\.." /I "..\..\src" /D "NDEBUG" /D "_LIB" /D "_WINDOWS" /D "_CRT_SECURE_NO_DEPRECATE" /D "_CRT_NONSTDC_NO_DEPRECATE" /D "WIN32"
+/GF /FD /MT /GS- /Gy /arch:SSE2 /Zc:wchar_t- /Fp"..\..\out\release8\build\libbulletcollision\libbulletcollision.pch"
+/Fo"..\..\out\release8\build\libbulletcollision\\"
+/Fd"..\..\out\release8\build\libbulletcollision\bulletcollision.pdb"
+/W3 /nologo /c /Wp64 /Zi /errorReport:prompt
+
+Benchmarking dbvt...
+World scale: 100.000000
+Extents base: 1.000000
+Extents range: 4.000000
+Leaves: 8192
+sizeof(btDbvtVolume): 32 bytes
+sizeof(btDbvtNode): 44 bytes
+[1] btDbvtVolume intersections: 3499 ms (-1%)
+[2] btDbvtVolume merges: 1934 ms (0%)
+[3] btDbvt::collideTT: 5485 ms (-21%)
+[4] btDbvt::collideTT self: 2814 ms (-20%)
+[5] btDbvt::collideTT xform: 7379 ms (-1%)
+[6] btDbvt::collideTT xform,self: 7270 ms (-2%)
+[7] btDbvt::rayTest: 6314 ms (0%),(332143 r/s)
+[8] insert/remove: 2093 ms (0%),(1001983 ir/s)
+[9] updates (teleport): 1879 ms (-3%),(1116100 u/s)
+[10] updates (jitter): 1244 ms (-4%),(1685813 u/s)
+[11] optimize (incremental): 2514 ms (0%),(1668000 o/s)
+[12] btDbvtVolume notequal: 3659 ms (0%)
+[13] culling(OCL+fullsort): 2218 ms (0%),(461 t/s)
+[14] culling(OCL+qsort): 3688 ms (5%),(2221 t/s)
+[15] culling(KDOP+qsort): 1139 ms (-1%),(7192 t/s)
+[16] insert/remove batch(256): 5092 ms (0%),(823704 bir/s)
+[17] btDbvtVolume select: 3419 ms (0%)
+*/
+
+struct btDbvtBenchmark
+{
+ struct NilPolicy : btDbvt::ICollide
+ {
+ NilPolicy() : m_pcount(0),m_depth(-SIMD_INFINITY),m_checksort(true) {}
+ void Process(const btDbvtNode*,const btDbvtNode*) { ++m_pcount; }
+ void Process(const btDbvtNode*) { ++m_pcount; }
+ void Process(const btDbvtNode*,btScalar depth)
+ {
+ ++m_pcount;
+ if(m_checksort)
+ { if(depth>=m_depth) m_depth=depth; else printf("wrong depth: %f (should be >= %f)\r\n",depth,m_depth); }
+ }
+ int m_pcount;
+ btScalar m_depth;
+ bool m_checksort;
+ };
+ struct P14 : btDbvt::ICollide
+ {
+ struct Node
+ {
+ const btDbvtNode* leaf;
+ btScalar depth;
+ };
+ void Process(const btDbvtNode* leaf,btScalar depth)
+ {
+ Node n;
+ n.leaf = leaf;
+ n.depth = depth;
+ }
+ static int sortfnc(const Node& a,const Node& b)
+ {
+ if(a.depth<b.depth) return(+1);
+ if(a.depth>b.depth) return(-1);
+ return(0);
+ }
+ btAlignedObjectArray<Node> m_nodes;
+ };
+ struct P15 : btDbvt::ICollide
+ {
+ struct Node
+ {
+ const btDbvtNode* leaf;
+ btScalar depth;
+ };
+ void Process(const btDbvtNode* leaf)
+ {
+ Node n;
+ n.leaf = leaf;
+ n.depth = dot(leaf->volume.Center(),m_axis);
+ }
+ static int sortfnc(const Node& a,const Node& b)
+ {
+ if(a.depth<b.depth) return(+1);
+ if(a.depth>b.depth) return(-1);
+ return(0);
+ }
+ btAlignedObjectArray<Node> m_nodes;
+ btVector3 m_axis;
+ };
+ static btScalar RandUnit()
+ {
+ return(rand()/(btScalar)RAND_MAX);
+ }
+ static btVector3 RandVector3()
+ {
+ return(btVector3(RandUnit(),RandUnit(),RandUnit()));
+ }
+ static btVector3 RandVector3(btScalar cs)
+ {
+ return(RandVector3()*cs-btVector3(cs,cs,cs)/2);
+ }
+ static btDbvtVolume RandVolume(btScalar cs,btScalar eb,btScalar es)
+ {
+ return(btDbvtVolume::FromCE(RandVector3(cs),btVector3(eb,eb,eb)+RandVector3()*es));
+ }
+ static btTransform RandTransform(btScalar cs)
+ {
+ btTransform t;
+ t.setOrigin(RandVector3(cs));
+ t.setRotation(btQuaternion(RandUnit()*SIMD_PI*2,RandUnit()*SIMD_PI*2,RandUnit()*SIMD_PI*2).normalized());
+ return(t);
+ }
+ static void RandTree(btScalar cs,btScalar eb,btScalar es,int leaves,btDbvt& dbvt)
+ {
+ dbvt.clear();
+ for(int i=0;i<leaves;++i)
+ {
+ dbvt.insert(RandVolume(cs,eb,es),0);
+ }
+ }
+};
+
+void btDbvt::benchmark()
+{
+ static const btScalar cfgVolumeCenterScale = 100;
+ static const btScalar cfgVolumeExentsBase = 1;
+ static const btScalar cfgVolumeExentsScale = 4;
+ static const int cfgLeaves = 8192;
+ static const bool cfgEnable = true;
+
+ //[1] btDbvtVolume intersections
+ bool cfgBenchmark1_Enable = cfgEnable;
+ static const int cfgBenchmark1_Iterations = 8;
+ static const int cfgBenchmark1_Reference = 3499;
+ //[2] btDbvtVolume merges
+ bool cfgBenchmark2_Enable = cfgEnable;
+ static const int cfgBenchmark2_Iterations = 4;
+ static const int cfgBenchmark2_Reference = 1945;
+ //[3] btDbvt::collideTT
+ bool cfgBenchmark3_Enable = cfgEnable;
+ static const int cfgBenchmark3_Iterations = 512;
+ static const int cfgBenchmark3_Reference = 5485;
+ //[4] btDbvt::collideTT self
+ bool cfgBenchmark4_Enable = cfgEnable;
+ static const int cfgBenchmark4_Iterations = 512;
+ static const int cfgBenchmark4_Reference = 2814;
+ //[5] btDbvt::collideTT xform
+ bool cfgBenchmark5_Enable = cfgEnable;
+ static const int cfgBenchmark5_Iterations = 512;
+ static const btScalar cfgBenchmark5_OffsetScale = 2;
+ static const int cfgBenchmark5_Reference = 7379;
+ //[6] btDbvt::collideTT xform,self
+ bool cfgBenchmark6_Enable = cfgEnable;
+ static const int cfgBenchmark6_Iterations = 512;
+ static const btScalar cfgBenchmark6_OffsetScale = 2;
+ static const int cfgBenchmark6_Reference = 7270;
+ //[7] btDbvt::rayTest
+ bool cfgBenchmark7_Enable = cfgEnable;
+ static const int cfgBenchmark7_Passes = 32;
+ static const int cfgBenchmark7_Iterations = 65536;
+ static const int cfgBenchmark7_Reference = 6307;
+ //[8] insert/remove
+ bool cfgBenchmark8_Enable = cfgEnable;
+ static const int cfgBenchmark8_Passes = 32;
+ static const int cfgBenchmark8_Iterations = 65536;
+ static const int cfgBenchmark8_Reference = 2105;
+ //[9] updates (teleport)
+ bool cfgBenchmark9_Enable = cfgEnable;
+ static const int cfgBenchmark9_Passes = 32;
+ static const int cfgBenchmark9_Iterations = 65536;
+ static const int cfgBenchmark9_Reference = 1879;
+ //[10] updates (jitter)
+ bool cfgBenchmark10_Enable = cfgEnable;
+ static const btScalar cfgBenchmark10_Scale = cfgVolumeCenterScale/10000;
+ static const int cfgBenchmark10_Passes = 32;
+ static const int cfgBenchmark10_Iterations = 65536;
+ static const int cfgBenchmark10_Reference = 1244;
+ //[11] optimize (incremental)
+ bool cfgBenchmark11_Enable = cfgEnable;
+ static const int cfgBenchmark11_Passes = 64;
+ static const int cfgBenchmark11_Iterations = 65536;
+ static const int cfgBenchmark11_Reference = 2510;
+ //[12] btDbvtVolume notequal
+ bool cfgBenchmark12_Enable = cfgEnable;
+ static const int cfgBenchmark12_Iterations = 32;
+ static const int cfgBenchmark12_Reference = 3677;
+ //[13] culling(OCL+fullsort)
+ bool cfgBenchmark13_Enable = cfgEnable;
+ static const int cfgBenchmark13_Iterations = 1024;
+ static const int cfgBenchmark13_Reference = 2231;
+ //[14] culling(OCL+qsort)
+ bool cfgBenchmark14_Enable = cfgEnable;
+ static const int cfgBenchmark14_Iterations = 8192;
+ static const int cfgBenchmark14_Reference = 3500;
+ //[15] culling(KDOP+qsort)
+ bool cfgBenchmark15_Enable = cfgEnable;
+ static const int cfgBenchmark15_Iterations = 8192;
+ static const int cfgBenchmark15_Reference = 1151;
+ //[16] insert/remove batch
+ bool cfgBenchmark16_Enable = cfgEnable;
+ static const int cfgBenchmark16_BatchCount = 256;
+ static const int cfgBenchmark16_Passes = 16384;
+ static const int cfgBenchmark16_Reference = 5138;
+ //[17] select
+ bool cfgBenchmark17_Enable = cfgEnable;
+ static const int cfgBenchmark17_Iterations = 4;
+ static const int cfgBenchmark17_Reference = 3390;
+
+ btClock wallclock;
+ printf("Benchmarking dbvt...\r\n");
+ printf("\tWorld scale: %f\r\n",cfgVolumeCenterScale);
+ printf("\tExtents base: %f\r\n",cfgVolumeExentsBase);
+ printf("\tExtents range: %f\r\n",cfgVolumeExentsScale);
+ printf("\tLeaves: %u\r\n",cfgLeaves);
+ printf("\tsizeof(btDbvtVolume): %u bytes\r\n",sizeof(btDbvtVolume));
+ printf("\tsizeof(btDbvtNode): %u bytes\r\n",sizeof(btDbvtNode));
+ if(cfgBenchmark1_Enable)
+ {// Benchmark 1
+ srand(380843);
+ btAlignedObjectArray<btDbvtVolume> volumes;
+ btAlignedObjectArray<bool> results;
+ volumes.resize(cfgLeaves);
+ results.resize(cfgLeaves);
+ for(int i=0;i<cfgLeaves;++i)
+ {
+ volumes[i]=btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale);
+ }
+ printf("[1] btDbvtVolume intersections: ");
+ wallclock.reset();
+ for(int i=0;i<cfgBenchmark1_Iterations;++i)
+ {
+ for(int j=0;j<cfgLeaves;++j)
+ {
+ for(int k=0;k<cfgLeaves;++k)
+ {
+ results[k]=Intersect(volumes[j],volumes[k]);
+ }
+ }
+ }
+ const int time=(int)wallclock.getTimeMilliseconds();
+ printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark1_Reference)*100/time);
+ }
+ if(cfgBenchmark2_Enable)
+ {// Benchmark 2
+ srand(380843);
+ btAlignedObjectArray<btDbvtVolume> volumes;
+ btAlignedObjectArray<btDbvtVolume> results;
+ volumes.resize(cfgLeaves);
+ results.resize(cfgLeaves);
+ for(int i=0;i<cfgLeaves;++i)
+ {
+ volumes[i]=btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale);
+ }
+ printf("[2] btDbvtVolume merges: ");
+ wallclock.reset();
+ for(int i=0;i<cfgBenchmark2_Iterations;++i)
+ {
+ for(int j=0;j<cfgLeaves;++j)
+ {
+ for(int k=0;k<cfgLeaves;++k)
+ {
+ Merge(volumes[j],volumes[k],results[k]);
+ }
+ }
+ }
+ const int time=(int)wallclock.getTimeMilliseconds();
+ printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark2_Reference)*100/time);
+ }
+ if(cfgBenchmark3_Enable)
+ {// Benchmark 3
+ srand(380843);
+ btDbvt dbvt[2];
+ btDbvtBenchmark::NilPolicy policy;
+ btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt[0]);
+ btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt[1]);
+ dbvt[0].optimizeTopDown();
+ dbvt[1].optimizeTopDown();
+ printf("[3] btDbvt::collideTT: ");
+ wallclock.reset();
+ for(int i=0;i<cfgBenchmark3_Iterations;++i)
+ {
+ btDbvt::collideTT(dbvt[0].m_root,dbvt[1].m_root,policy);
+ }
+ const int time=(int)wallclock.getTimeMilliseconds();
+ printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark3_Reference)*100/time);
+ }
+ if(cfgBenchmark4_Enable)
+ {// Benchmark 4
+ srand(380843);
+ btDbvt dbvt;
+ btDbvtBenchmark::NilPolicy policy;
+ btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ dbvt.optimizeTopDown();
+ printf("[4] btDbvt::collideTT self: ");
+ wallclock.reset();
+ for(int i=0;i<cfgBenchmark4_Iterations;++i)
+ {
+ btDbvt::collideTT(dbvt.m_root,dbvt.m_root,policy);
+ }
+ const int time=(int)wallclock.getTimeMilliseconds();
+ printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark4_Reference)*100/time);
+ }
+ if(cfgBenchmark5_Enable)
+ {// Benchmark 5
+ srand(380843);
+ btDbvt dbvt[2];
+ btAlignedObjectArray<btTransform> transforms;
+ btDbvtBenchmark::NilPolicy policy;
+ transforms.resize(cfgBenchmark5_Iterations);
+ for(int i=0;i<transforms.size();++i)
+ {
+ transforms[i]=btDbvtBenchmark::RandTransform(cfgVolumeCenterScale*cfgBenchmark5_OffsetScale);
+ }
+ btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt[0]);
+ btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt[1]);
+ dbvt[0].optimizeTopDown();
+ dbvt[1].optimizeTopDown();
+ printf("[5] btDbvt::collideTT xform: ");
+ wallclock.reset();
+ for(int i=0;i<cfgBenchmark5_Iterations;++i)
+ {
+ btDbvt::collideTT(dbvt[0].m_root,dbvt[1].m_root,transforms[i],policy);
+ }
+ const int time=(int)wallclock.getTimeMilliseconds();
+ printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark5_Reference)*100/time);
+ }
+ if(cfgBenchmark6_Enable)
+ {// Benchmark 6
+ srand(380843);
+ btDbvt dbvt;
+ btAlignedObjectArray<btTransform> transforms;
+ btDbvtBenchmark::NilPolicy policy;
+ transforms.resize(cfgBenchmark6_Iterations);
+ for(int i=0;i<transforms.size();++i)
+ {
+ transforms[i]=btDbvtBenchmark::RandTransform(cfgVolumeCenterScale*cfgBenchmark6_OffsetScale);
+ }
+ btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ dbvt.optimizeTopDown();
+ printf("[6] btDbvt::collideTT xform,self: ");
+ wallclock.reset();
+ for(int i=0;i<cfgBenchmark6_Iterations;++i)
+ {
+ btDbvt::collideTT(dbvt.m_root,dbvt.m_root,transforms[i],policy);
+ }
+ const int time=(int)wallclock.getTimeMilliseconds();
+ printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark6_Reference)*100/time);
+ }
+ if(cfgBenchmark7_Enable)
+ {// Benchmark 7
+ srand(380843);
+ btDbvt dbvt;
+ btAlignedObjectArray<btVector3> rayorg;
+ btAlignedObjectArray<btVector3> raydir;
+ btDbvtBenchmark::NilPolicy policy;
+ rayorg.resize(cfgBenchmark7_Iterations);
+ raydir.resize(cfgBenchmark7_Iterations);
+ for(int i=0;i<rayorg.size();++i)
+ {
+ rayorg[i]=btDbvtBenchmark::RandVector3(cfgVolumeCenterScale*2);
+ raydir[i]=btDbvtBenchmark::RandVector3(cfgVolumeCenterScale*2);
+ }
+ btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ dbvt.optimizeTopDown();
+ printf("[7] btDbvt::rayTest: ");
+ wallclock.reset();
+ for(int i=0;i<cfgBenchmark7_Passes;++i)
+ {
+ for(int j=0;j<cfgBenchmark7_Iterations;++j)
+ {
+ btDbvt::rayTest(dbvt.m_root,rayorg[j],rayorg[j]+raydir[j],policy);
+ }
+ }
+ const int time=(int)wallclock.getTimeMilliseconds();
+ unsigned rays=cfgBenchmark7_Passes*cfgBenchmark7_Iterations;
+ printf("%u ms (%i%%),(%u r/s)\r\n",time,(time-cfgBenchmark7_Reference)*100/time,(rays*1000)/time);
+ }
+ if(cfgBenchmark8_Enable)
+ {// Benchmark 8
+ srand(380843);
+ btDbvt dbvt;
+ btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ dbvt.optimizeTopDown();
+ printf("[8] insert/remove: ");
+ wallclock.reset();
+ for(int i=0;i<cfgBenchmark8_Passes;++i)
+ {
+ for(int j=0;j<cfgBenchmark8_Iterations;++j)
+ {
+ dbvt.remove(dbvt.insert(btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale),0));
+ }
+ }
+ const int time=(int)wallclock.getTimeMilliseconds();
+ const int ir=cfgBenchmark8_Passes*cfgBenchmark8_Iterations;
+ printf("%u ms (%i%%),(%u ir/s)\r\n",time,(time-cfgBenchmark8_Reference)*100/time,ir*1000/time);
+ }
+ if(cfgBenchmark9_Enable)
+ {// Benchmark 9
+ srand(380843);
+ btDbvt dbvt;
+ btAlignedObjectArray<const btDbvtNode*> leaves;
+ btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ dbvt.optimizeTopDown();
+ dbvt.extractLeaves(dbvt.m_root,leaves);
+ printf("[9] updates (teleport): ");
+ wallclock.reset();
+ for(int i=0;i<cfgBenchmark9_Passes;++i)
+ {
+ for(int j=0;j<cfgBenchmark9_Iterations;++j)
+ {
+ dbvt.update(const_cast<btDbvtNode*>(leaves[rand()%cfgLeaves]),
+ btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale));
+ }
+ }
+ const int time=(int)wallclock.getTimeMilliseconds();
+ const int up=cfgBenchmark9_Passes*cfgBenchmark9_Iterations;
+ printf("%u ms (%i%%),(%u u/s)\r\n",time,(time-cfgBenchmark9_Reference)*100/time,up*1000/time);
+ }
+ if(cfgBenchmark10_Enable)
+ {// Benchmark 10
+ srand(380843);
+ btDbvt dbvt;
+ btAlignedObjectArray<const btDbvtNode*> leaves;
+ btAlignedObjectArray<btVector3> vectors;
+ vectors.resize(cfgBenchmark10_Iterations);
+ for(int i=0;i<vectors.size();++i)
+ {
+ vectors[i]=(btDbvtBenchmark::RandVector3()*2-btVector3(1,1,1))*cfgBenchmark10_Scale;
+ }
+ btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ dbvt.optimizeTopDown();
+ dbvt.extractLeaves(dbvt.m_root,leaves);
+ printf("[10] updates (jitter): ");
+ wallclock.reset();
+
+ for(int i=0;i<cfgBenchmark10_Passes;++i)
+ {
+ for(int j=0;j<cfgBenchmark10_Iterations;++j)
+ {
+ const btVector3& d=vectors[j];
+ btDbvtNode* l=const_cast<btDbvtNode*>(leaves[rand()%cfgLeaves]);
+ btDbvtVolume v=btDbvtVolume::FromMM(l->volume.Mins()+d,l->volume.Maxs()+d);
+ dbvt.update(l,v);
+ }
+ }
+ const int time=(int)wallclock.getTimeMilliseconds();
+ const int up=cfgBenchmark10_Passes*cfgBenchmark10_Iterations;
+ printf("%u ms (%i%%),(%u u/s)\r\n",time,(time-cfgBenchmark10_Reference)*100/time,up*1000/time);
+ }
+ if(cfgBenchmark11_Enable)
+ {// Benchmark 11
+ srand(380843);
+ btDbvt dbvt;
+ btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ dbvt.optimizeTopDown();
+ printf("[11] optimize (incremental): ");
+ wallclock.reset();
+ for(int i=0;i<cfgBenchmark11_Passes;++i)
+ {
+ dbvt.optimizeIncremental(cfgBenchmark11_Iterations);
+ }
+ const int time=(int)wallclock.getTimeMilliseconds();
+ const int op=cfgBenchmark11_Passes*cfgBenchmark11_Iterations;
+ printf("%u ms (%i%%),(%u o/s)\r\n",time,(time-cfgBenchmark11_Reference)*100/time,op/time*1000);
+ }
+ if(cfgBenchmark12_Enable)
+ {// Benchmark 12
+ srand(380843);
+ btAlignedObjectArray<btDbvtVolume> volumes;
+ btAlignedObjectArray<bool> results;
+ volumes.resize(cfgLeaves);
+ results.resize(cfgLeaves);
+ for(int i=0;i<cfgLeaves;++i)
+ {
+ volumes[i]=btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale);
+ }
+ printf("[12] btDbvtVolume notequal: ");
+ wallclock.reset();
+ for(int i=0;i<cfgBenchmark12_Iterations;++i)
+ {
+ for(int j=0;j<cfgLeaves;++j)
+ {
+ for(int k=0;k<cfgLeaves;++k)
+ {
+ results[k]=NotEqual(volumes[j],volumes[k]);
+ }
+ }
+ }
+ const int time=(int)wallclock.getTimeMilliseconds();
+ printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark12_Reference)*100/time);
+ }
+ if(cfgBenchmark13_Enable)
+ {// Benchmark 13
+ srand(380843);
+ btDbvt dbvt;
+ btAlignedObjectArray<btVector3> vectors;
+ btDbvtBenchmark::NilPolicy policy;
+ vectors.resize(cfgBenchmark13_Iterations);
+ for(int i=0;i<vectors.size();++i)
+ {
+ vectors[i]=(btDbvtBenchmark::RandVector3()*2-btVector3(1,1,1)).normalized();
+ }
+ btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ dbvt.optimizeTopDown();
+ printf("[13] culling(OCL+fullsort): ");
+ wallclock.reset();
+ for(int i=0;i<cfgBenchmark13_Iterations;++i)
+ {
+ static const btScalar offset=0;
+ policy.m_depth=-SIMD_INFINITY;
+ dbvt.collideOCL(dbvt.m_root,&vectors[i],&offset,vectors[i],1,policy);
+ }
+ const int time=(int)wallclock.getTimeMilliseconds();
+ const int t=cfgBenchmark13_Iterations;
+ printf("%u ms (%i%%),(%u t/s)\r\n",time,(time-cfgBenchmark13_Reference)*100/time,(t*1000)/time);
+ }
+ if(cfgBenchmark14_Enable)
+ {// Benchmark 14
+ srand(380843);
+ btDbvt dbvt;
+ btAlignedObjectArray<btVector3> vectors;
+ btDbvtBenchmark::P14 policy;
+ vectors.resize(cfgBenchmark14_Iterations);
+ for(int i=0;i<vectors.size();++i)
+ {
+ vectors[i]=(btDbvtBenchmark::RandVector3()*2-btVector3(1,1,1)).normalized();
+ }
+ btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ dbvt.optimizeTopDown();
+ policy.m_nodes.reserve(cfgLeaves);
+ printf("[14] culling(OCL+qsort): ");
+ wallclock.reset();
+ for(int i=0;i<cfgBenchmark14_Iterations;++i)
+ {
+ static const btScalar offset=0;
+ policy.m_nodes.resize(0);
+ dbvt.collideOCL(dbvt.m_root,&vectors[i],&offset,vectors[i],1,policy,false);
+ policy.m_nodes.quickSort(btDbvtBenchmark::P14::sortfnc);
+ }
+ const int time=(int)wallclock.getTimeMilliseconds();
+ const int t=cfgBenchmark14_Iterations;
+ printf("%u ms (%i%%),(%u t/s)\r\n",time,(time-cfgBenchmark14_Reference)*100/time,(t*1000)/time);
+ }
+ if(cfgBenchmark15_Enable)
+ {// Benchmark 15
+ srand(380843);
+ btDbvt dbvt;
+ btAlignedObjectArray<btVector3> vectors;
+ btDbvtBenchmark::P15 policy;
+ vectors.resize(cfgBenchmark15_Iterations);
+ for(int i=0;i<vectors.size();++i)
+ {
+ vectors[i]=(btDbvtBenchmark::RandVector3()*2-btVector3(1,1,1)).normalized();
+ }
+ btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ dbvt.optimizeTopDown();
+ policy.m_nodes.reserve(cfgLeaves);
+ printf("[15] culling(KDOP+qsort): ");
+ wallclock.reset();
+ for(int i=0;i<cfgBenchmark15_Iterations;++i)
+ {
+ static const btScalar offset=0;
+ policy.m_nodes.resize(0);
+ policy.m_axis=vectors[i];
+ dbvt.collideKDOP(dbvt.m_root,&vectors[i],&offset,1,policy);
+ policy.m_nodes.quickSort(btDbvtBenchmark::P15::sortfnc);
+ }
+ const int time=(int)wallclock.getTimeMilliseconds();
+ const int t=cfgBenchmark15_Iterations;
+ printf("%u ms (%i%%),(%u t/s)\r\n",time,(time-cfgBenchmark15_Reference)*100/time,(t*1000)/time);
+ }
+ if(cfgBenchmark16_Enable)
+ {// Benchmark 16
+ srand(380843);
+ btDbvt dbvt;
+ btAlignedObjectArray<btDbvtNode*> batch;
+ btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ dbvt.optimizeTopDown();
+ batch.reserve(cfgBenchmark16_BatchCount);
+ printf("[16] insert/remove batch(%u): ",cfgBenchmark16_BatchCount);
+ wallclock.reset();
+ for(int i=0;i<cfgBenchmark16_Passes;++i)
+ {
+ for(int j=0;j<cfgBenchmark16_BatchCount;++j)
+ {
+ batch.push_back(dbvt.insert(btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale),0));
+ }
+ for(int j=0;j<cfgBenchmark16_BatchCount;++j)
+ {
+ dbvt.remove(batch[j]);
+ }
+ batch.resize(0);
+ }
+ const int time=(int)wallclock.getTimeMilliseconds();
+ const int ir=cfgBenchmark16_Passes*cfgBenchmark16_BatchCount;
+ printf("%u ms (%i%%),(%u bir/s)\r\n",time,(time-cfgBenchmark16_Reference)*100/time,int(ir*1000.0/time));
+ }
+ if(cfgBenchmark17_Enable)
+ {// Benchmark 17
+ srand(380843);
+ btAlignedObjectArray<btDbvtVolume> volumes;
+ btAlignedObjectArray<int> results;
+ btAlignedObjectArray<int> indices;
+ volumes.resize(cfgLeaves);
+ results.resize(cfgLeaves);
+ indices.resize(cfgLeaves);
+ for(int i=0;i<cfgLeaves;++i)
+ {
+ indices[i]=i;
+ volumes[i]=btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale);
+ }
+ for(int i=0;i<cfgLeaves;++i)
+ {
+ btSwap(indices[i],indices[rand()%cfgLeaves]);
+ }
+ printf("[17] btDbvtVolume select: ");
+ wallclock.reset();
+ for(int i=0;i<cfgBenchmark17_Iterations;++i)
+ {
+ for(int j=0;j<cfgLeaves;++j)
+ {
+ for(int k=0;k<cfgLeaves;++k)
+ {
+ const int idx=indices[k];
+ results[idx]=Select(volumes[idx],volumes[j],volumes[k]);
+ }
+ }
+ }
+ const int time=(int)wallclock.getTimeMilliseconds();
+ printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark17_Reference)*100/time);
+ }
+ printf("\r\n\r\n");
+}
+#endif
diff --git a/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btDbvt.h b/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btDbvt.h
new file mode 100644
index 0000000000..b5a0014580
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btDbvt.h
@@ -0,0 +1,1343 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2007 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+///btDbvt implementation by Nathanael Presson
+
+#ifndef BT_DYNAMIC_BOUNDING_VOLUME_TREE_H
+#define BT_DYNAMIC_BOUNDING_VOLUME_TREE_H
+
+#include "LinearMath/btAlignedObjectArray.h"
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btTransform.h"
+#include "LinearMath/btAabbUtil2.h"
+
+//
+// Compile time configuration
+//
+
+
+// Implementation profiles
+#define DBVT_IMPL_GENERIC 0 // Generic implementation
+#define DBVT_IMPL_SSE 1 // SSE
+
+// Template implementation of ICollide
+#ifdef _WIN32
+#if (defined (_MSC_VER) && _MSC_VER >= 1400)
+#define DBVT_USE_TEMPLATE 1
+#else
+#define DBVT_USE_TEMPLATE 0
+#endif
+#else
+#define DBVT_USE_TEMPLATE 0
+#endif
+
+// Use only intrinsics instead of inline asm
+#define DBVT_USE_INTRINSIC_SSE 1
+
+// Using memmov for collideOCL
+#define DBVT_USE_MEMMOVE 1
+
+// Enable benchmarking code
+#define DBVT_ENABLE_BENCHMARK 0
+
+// Inlining
+#define DBVT_INLINE SIMD_FORCE_INLINE
+
+// Specific methods implementation
+
+//SSE gives errors on a MSVC 7.1
+#if defined (BT_USE_SSE) //&& defined (_WIN32)
+#define DBVT_SELECT_IMPL DBVT_IMPL_SSE
+#define DBVT_MERGE_IMPL DBVT_IMPL_SSE
+#define DBVT_INT0_IMPL DBVT_IMPL_SSE
+#else
+#define DBVT_SELECT_IMPL DBVT_IMPL_GENERIC
+#define DBVT_MERGE_IMPL DBVT_IMPL_GENERIC
+#define DBVT_INT0_IMPL DBVT_IMPL_GENERIC
+#endif
+
+#if (DBVT_SELECT_IMPL==DBVT_IMPL_SSE)|| \
+ (DBVT_MERGE_IMPL==DBVT_IMPL_SSE)|| \
+ (DBVT_INT0_IMPL==DBVT_IMPL_SSE)
+#include <emmintrin.h>
+#endif
+
+//
+// Auto config and checks
+//
+
+#if DBVT_USE_TEMPLATE
+#define DBVT_VIRTUAL
+#define DBVT_VIRTUAL_DTOR(a)
+#define DBVT_PREFIX template <typename T>
+#define DBVT_IPOLICY T& policy
+#define DBVT_CHECKTYPE static const ICollide& typechecker=*(T*)1;(void)typechecker;
+#else
+#define DBVT_VIRTUAL_DTOR(a) virtual ~a() {}
+#define DBVT_VIRTUAL virtual
+#define DBVT_PREFIX
+#define DBVT_IPOLICY ICollide& policy
+#define DBVT_CHECKTYPE
+#endif
+
+#if DBVT_USE_MEMMOVE
+#if !defined( __CELLOS_LV2__) && !defined(__MWERKS__)
+#include <memory.h>
+#endif
+#include <string.h>
+#endif
+
+#ifndef DBVT_USE_TEMPLATE
+#error "DBVT_USE_TEMPLATE undefined"
+#endif
+
+#ifndef DBVT_USE_MEMMOVE
+#error "DBVT_USE_MEMMOVE undefined"
+#endif
+
+#ifndef DBVT_ENABLE_BENCHMARK
+#error "DBVT_ENABLE_BENCHMARK undefined"
+#endif
+
+#ifndef DBVT_SELECT_IMPL
+#error "DBVT_SELECT_IMPL undefined"
+#endif
+
+#ifndef DBVT_MERGE_IMPL
+#error "DBVT_MERGE_IMPL undefined"
+#endif
+
+#ifndef DBVT_INT0_IMPL
+#error "DBVT_INT0_IMPL undefined"
+#endif
+
+
+//
+// Defaults volumes
+//
+
+/* btDbvtAabbMm */
+struct 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); }
+ DBVT_INLINE const btVector3& Mins() const { return(mi); }
+ DBVT_INLINE const btVector3& Maxs() const { return(mx); }
+ static inline btDbvtAabbMm FromCE(const btVector3& c,const btVector3& e);
+ static inline btDbvtAabbMm FromCR(const btVector3& c,btScalar r);
+ static inline btDbvtAabbMm FromMM(const btVector3& mi,const btVector3& mx);
+ static inline btDbvtAabbMm FromPoints(const btVector3* pts,int n);
+ static inline btDbvtAabbMm FromPoints(const btVector3** ppts,int n);
+ DBVT_INLINE void Expand(const btVector3& e);
+ DBVT_INLINE void SignedExpand(const btVector3& e);
+ DBVT_INLINE bool Contain(const btDbvtAabbMm& a) const;
+ DBVT_INLINE int Classify(const btVector3& n,btScalar o,int s) const;
+ DBVT_INLINE btScalar ProjectMinimum(const btVector3& v,unsigned signs) const;
+ DBVT_INLINE friend bool Intersect( const btDbvtAabbMm& a,
+ const btDbvtAabbMm& b);
+
+ DBVT_INLINE friend bool Intersect( const btDbvtAabbMm& a,
+ const btVector3& b);
+
+ DBVT_INLINE friend btScalar Proximity( const btDbvtAabbMm& a,
+ const btDbvtAabbMm& b);
+ DBVT_INLINE friend int Select( const btDbvtAabbMm& o,
+ const btDbvtAabbMm& a,
+ const btDbvtAabbMm& b);
+ DBVT_INLINE friend void Merge( const btDbvtAabbMm& a,
+ const btDbvtAabbMm& b,
+ btDbvtAabbMm& r);
+ DBVT_INLINE friend bool NotEqual( const btDbvtAabbMm& a,
+ const btDbvtAabbMm& b);
+
+ DBVT_INLINE btVector3& tMins() { return(mi); }
+ DBVT_INLINE btVector3& tMaxs() { return(mx); }
+
+private:
+ DBVT_INLINE void AddSpan(const btVector3& d,btScalar& smi,btScalar& smx) const;
+private:
+ btVector3 mi,mx;
+};
+
+// Types
+typedef btDbvtAabbMm btDbvtVolume;
+
+/* btDbvtNode */
+struct btDbvtNode
+{
+ btDbvtVolume volume;
+ btDbvtNode* parent;
+ DBVT_INLINE bool isleaf() const { return(childs[1]==0); }
+ DBVT_INLINE bool isinternal() const { return(!isleaf()); }
+ union
+ {
+ btDbvtNode* childs[2];
+ void* data;
+ int dataAsInt;
+ };
+};
+
+typedef btAlignedObjectArray<const btDbvtNode*> btNodeStack;
+
+
+///The btDbvt class implements a fast dynamic bounding volume tree based on axis aligned bounding boxes (aabb tree).
+///This btDbvt is used for soft body collision detection and for the btDbvtBroadphase. It has a fast insert, remove and update of nodes.
+///Unlike the btQuantizedBvh, nodes can be dynamically moved around, which allows for change in topology of the underlying data structure.
+struct btDbvt
+{
+ /* Stack element */
+ struct sStkNN
+ {
+ const btDbvtNode* a;
+ const btDbvtNode* b;
+ sStkNN() {}
+ sStkNN(const btDbvtNode* na,const btDbvtNode* nb) : a(na),b(nb) {}
+ };
+ struct sStkNP
+ {
+ const btDbvtNode* node;
+ int mask;
+ sStkNP(const btDbvtNode* n,unsigned m) : node(n),mask(m) {}
+ };
+ struct sStkNPS
+ {
+ const btDbvtNode* node;
+ int mask;
+ btScalar value;
+ sStkNPS() {}
+ sStkNPS(const btDbvtNode* n,unsigned m,btScalar v) : node(n),mask(m),value(v) {}
+ };
+ struct sStkCLN
+ {
+ const btDbvtNode* node;
+ btDbvtNode* parent;
+ sStkCLN(const btDbvtNode* n,btDbvtNode* p) : node(n),parent(p) {}
+ };
+ // Policies/Interfaces
+
+ /* ICollide */
+ struct ICollide
+ {
+ DBVT_VIRTUAL_DTOR(ICollide)
+ 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 bool Descent(const btDbvtNode*) { return(true); }
+ DBVT_VIRTUAL bool AllLeaves(const btDbvtNode*) { return(true); }
+ };
+ /* IWriter */
+ struct IWriter
+ {
+ virtual ~IWriter() {}
+ virtual void Prepare(const btDbvtNode* root,int numnodes)=0;
+ virtual void WriteNode(const btDbvtNode*,int index,int parent,int child0,int child1)=0;
+ virtual void WriteLeaf(const btDbvtNode*,int index,int parent)=0;
+ };
+ /* IClone */
+ struct IClone
+ {
+ virtual ~IClone() {}
+ virtual void CloneLeaf(btDbvtNode*) {}
+ };
+
+ // Constants
+ enum {
+ SIMPLE_STACKSIZE = 64,
+ DOUBLE_STACKSIZE = SIMPLE_STACKSIZE*2
+ };
+
+ // Fields
+ btDbvtNode* m_root;
+ btDbvtNode* m_free;
+ int m_lkhd;
+ int m_leaves;
+ unsigned m_opath;
+
+
+ btAlignedObjectArray<sStkNN> m_stkStack;
+
+
+ // Methods
+ btDbvt();
+ ~btDbvt();
+ void clear();
+ bool empty() const { return(0==m_root); }
+ void optimizeBottomUp();
+ void optimizeTopDown(int bu_treshold=128);
+ void optimizeIncremental(int passes);
+ btDbvtNode* insert(const btDbvtVolume& box,void* data);
+ void update(btDbvtNode* leaf,int lookahead=-1);
+ void update(btDbvtNode* leaf,btDbvtVolume& volume);
+ bool update(btDbvtNode* leaf,btDbvtVolume& volume,const btVector3& velocity,btScalar margin);
+ bool update(btDbvtNode* leaf,btDbvtVolume& volume,const btVector3& velocity);
+ bool update(btDbvtNode* leaf,btDbvtVolume& volume,btScalar margin);
+ void remove(btDbvtNode* leaf);
+ void write(IWriter* iwriter) const;
+ void clone(btDbvt& dest,IClone* iclone=0) const;
+ static int maxdepth(const btDbvtNode* node);
+ static int countLeaves(const btDbvtNode* node);
+ static void extractLeaves(const btDbvtNode* node,btAlignedObjectArray<const btDbvtNode*>& leaves);
+#if DBVT_ENABLE_BENCHMARK
+ static void benchmark();
+#else
+ static void benchmark(){}
+#endif
+ // DBVT_IPOLICY must support ICollide policy/interface
+ DBVT_PREFIX
+ static void enumNodes( const btDbvtNode* root,
+ DBVT_IPOLICY);
+ DBVT_PREFIX
+ static void enumLeaves( const btDbvtNode* root,
+ DBVT_IPOLICY);
+ DBVT_PREFIX
+ void collideTT( const btDbvtNode* root0,
+ const btDbvtNode* root1,
+ DBVT_IPOLICY);
+
+ DBVT_PREFIX
+ void collideTTpersistentStack( const btDbvtNode* root0,
+ const btDbvtNode* root1,
+ DBVT_IPOLICY);
+#if 0
+ DBVT_PREFIX
+ void collideTT( const btDbvtNode* root0,
+ const btDbvtNode* root1,
+ const btTransform& xform,
+ DBVT_IPOLICY);
+ DBVT_PREFIX
+ void collideTT( const btDbvtNode* root0,
+ const btTransform& xform0,
+ const btDbvtNode* root1,
+ const btTransform& xform1,
+ DBVT_IPOLICY);
+#endif
+
+ DBVT_PREFIX
+ void collideTV( const btDbvtNode* root,
+ const btDbvtVolume& volume,
+ DBVT_IPOLICY) const;
+
+ DBVT_PREFIX
+ void collideTVNoStackAlloc( const btDbvtNode* root,
+ const btDbvtVolume& volume,
+ btNodeStack& stack,
+ DBVT_IPOLICY) const;
+
+
+
+
+ ///rayTest is a re-entrant ray test, and can be called in parallel as long as the btAlignedAlloc is thread-safe (uses locking etc)
+ ///rayTest is slower than rayTestInternal, because it builds a local stack, using memory allocations, and it recomputes signs/rayDirectionInverses each time
+ DBVT_PREFIX
+ static void rayTest( const btDbvtNode* root,
+ const btVector3& rayFrom,
+ const btVector3& rayTo,
+ DBVT_IPOLICY);
+ ///rayTestInternal is faster than rayTest, because it uses a persistent stack (to reduce dynamic memory allocations to a minimum) and it uses precomputed signs/rayInverseDirections
+ ///rayTestInternal is used by btDbvtBroadphase to accelerate world ray casts
+ DBVT_PREFIX
+ void rayTestInternal( const btDbvtNode* root,
+ const btVector3& rayFrom,
+ const btVector3& rayTo,
+ const btVector3& rayDirectionInverse,
+ unsigned int signs[3],
+ btScalar lambda_max,
+ const btVector3& aabbMin,
+ const btVector3& aabbMax,
+ btAlignedObjectArray<const btDbvtNode*>& stack,
+ DBVT_IPOLICY) const;
+
+ DBVT_PREFIX
+ static void collideKDOP(const btDbvtNode* root,
+ const btVector3* normals,
+ const btScalar* offsets,
+ int count,
+ DBVT_IPOLICY);
+ DBVT_PREFIX
+ static void collideOCL( const btDbvtNode* root,
+ const btVector3* normals,
+ const btScalar* offsets,
+ const btVector3& sortaxis,
+ int count,
+ DBVT_IPOLICY,
+ bool fullsort=true);
+ DBVT_PREFIX
+ static void collideTU( const btDbvtNode* root,
+ DBVT_IPOLICY);
+ // Helpers
+ static DBVT_INLINE int nearest(const int* i,const btDbvt::sStkNPS* a,btScalar v,int l,int h)
+ {
+ int m=0;
+ while(l<h)
+ {
+ m=(l+h)>>1;
+ if(a[i[m]].value>=v) l=m+1; else h=m;
+ }
+ return(h);
+ }
+ static DBVT_INLINE int allocate( btAlignedObjectArray<int>& ifree,
+ btAlignedObjectArray<sStkNPS>& stock,
+ const sStkNPS& value)
+ {
+ int i;
+ if(ifree.size()>0)
+ { i=ifree[ifree.size()-1];ifree.pop_back();stock[i]=value; }
+ else
+ { i=stock.size();stock.push_back(value); }
+ return(i);
+ }
+ //
+private:
+ btDbvt(const btDbvt&) {}
+};
+
+//
+// Inline's
+//
+
+//
+inline btDbvtAabbMm btDbvtAabbMm::FromCE(const btVector3& c,const btVector3& e)
+{
+ btDbvtAabbMm box;
+ box.mi=c-e;box.mx=c+e;
+ return(box);
+}
+
+//
+inline btDbvtAabbMm btDbvtAabbMm::FromCR(const btVector3& c,btScalar r)
+{
+ return(FromCE(c,btVector3(r,r,r)));
+}
+
+//
+inline btDbvtAabbMm btDbvtAabbMm::FromMM(const btVector3& mi,const btVector3& mx)
+{
+ btDbvtAabbMm box;
+ box.mi=mi;box.mx=mx;
+ return(box);
+}
+
+//
+inline btDbvtAabbMm btDbvtAabbMm::FromPoints(const btVector3* pts,int n)
+{
+ btDbvtAabbMm box;
+ box.mi=box.mx=pts[0];
+ for(int i=1;i<n;++i)
+ {
+ box.mi.setMin(pts[i]);
+ box.mx.setMax(pts[i]);
+ }
+ return(box);
+}
+
+//
+inline btDbvtAabbMm btDbvtAabbMm::FromPoints(const btVector3** ppts,int n)
+{
+ btDbvtAabbMm box;
+ box.mi=box.mx=*ppts[0];
+ for(int i=1;i<n;++i)
+ {
+ box.mi.setMin(*ppts[i]);
+ box.mx.setMax(*ppts[i]);
+ }
+ return(box);
+}
+
+//
+DBVT_INLINE void btDbvtAabbMm::Expand(const btVector3& e)
+{
+ mi-=e;mx+=e;
+}
+
+//
+DBVT_INLINE void btDbvtAabbMm::SignedExpand(const btVector3& e)
+{
+ if(e.x()>0) mx.setX(mx.x()+e[0]); else mi.setX(mi.x()+e[0]);
+ if(e.y()>0) mx.setY(mx.y()+e[1]); else mi.setY(mi.y()+e[1]);
+ if(e.z()>0) mx.setZ(mx.z()+e[2]); else mi.setZ(mi.z()+e[2]);
+}
+
+//
+DBVT_INLINE bool btDbvtAabbMm::Contain(const btDbvtAabbMm& a) const
+{
+ return( (mi.x()<=a.mi.x())&&
+ (mi.y()<=a.mi.y())&&
+ (mi.z()<=a.mi.z())&&
+ (mx.x()>=a.mx.x())&&
+ (mx.y()>=a.mx.y())&&
+ (mx.z()>=a.mx.z()));
+}
+
+//
+DBVT_INLINE int btDbvtAabbMm::Classify(const btVector3& n,btScalar o,int s) const
+{
+ btVector3 pi,px;
+ switch(s)
+ {
+ case (0+0+0): px=btVector3(mi.x(),mi.y(),mi.z());
+ pi=btVector3(mx.x(),mx.y(),mx.z());break;
+ case (1+0+0): px=btVector3(mx.x(),mi.y(),mi.z());
+ pi=btVector3(mi.x(),mx.y(),mx.z());break;
+ case (0+2+0): px=btVector3(mi.x(),mx.y(),mi.z());
+ pi=btVector3(mx.x(),mi.y(),mx.z());break;
+ case (1+2+0): px=btVector3(mx.x(),mx.y(),mi.z());
+ pi=btVector3(mi.x(),mi.y(),mx.z());break;
+ case (0+0+4): px=btVector3(mi.x(),mi.y(),mx.z());
+ pi=btVector3(mx.x(),mx.y(),mi.z());break;
+ case (1+0+4): px=btVector3(mx.x(),mi.y(),mx.z());
+ pi=btVector3(mi.x(),mx.y(),mi.z());break;
+ case (0+2+4): px=btVector3(mi.x(),mx.y(),mx.z());
+ pi=btVector3(mx.x(),mi.y(),mi.z());break;
+ case (1+2+4): px=btVector3(mx.x(),mx.y(),mx.z());
+ pi=btVector3(mi.x(),mi.y(),mi.z());break;
+ }
+ if((btDot(n,px)+o)<0) return(-1);
+ if((btDot(n,pi)+o)>=0) return(+1);
+ return(0);
+}
+
+//
+DBVT_INLINE btScalar btDbvtAabbMm::ProjectMinimum(const btVector3& v,unsigned signs) const
+{
+ const btVector3* b[]={&mx,&mi};
+ const btVector3 p( b[(signs>>0)&1]->x(),
+ b[(signs>>1)&1]->y(),
+ b[(signs>>2)&1]->z());
+ return(btDot(p,v));
+}
+
+//
+DBVT_INLINE void btDbvtAabbMm::AddSpan(const btVector3& d,btScalar& smi,btScalar& smx) const
+{
+ for(int i=0;i<3;++i)
+ {
+ if(d[i]<0)
+ { smi+=mx[i]*d[i];smx+=mi[i]*d[i]; }
+ else
+ { smi+=mi[i]*d[i];smx+=mx[i]*d[i]; }
+ }
+}
+
+//
+DBVT_INLINE bool Intersect( const btDbvtAabbMm& a,
+ const btDbvtAabbMm& b)
+{
+#if DBVT_INT0_IMPL == DBVT_IMPL_SSE
+ const __m128 rt(_mm_or_ps( _mm_cmplt_ps(_mm_load_ps(b.mx),_mm_load_ps(a.mi)),
+ _mm_cmplt_ps(_mm_load_ps(a.mx),_mm_load_ps(b.mi))));
+#if defined (_WIN32)
+ const __int32* pu((const __int32*)&rt);
+#else
+ const int* pu((const int*)&rt);
+#endif
+ return((pu[0]|pu[1]|pu[2])==0);
+#else
+ return( (a.mi.x()<=b.mx.x())&&
+ (a.mx.x()>=b.mi.x())&&
+ (a.mi.y()<=b.mx.y())&&
+ (a.mx.y()>=b.mi.y())&&
+ (a.mi.z()<=b.mx.z())&&
+ (a.mx.z()>=b.mi.z()));
+#endif
+}
+
+
+
+//
+DBVT_INLINE bool Intersect( const btDbvtAabbMm& a,
+ const btVector3& b)
+{
+ return( (b.x()>=a.mi.x())&&
+ (b.y()>=a.mi.y())&&
+ (b.z()>=a.mi.z())&&
+ (b.x()<=a.mx.x())&&
+ (b.y()<=a.mx.y())&&
+ (b.z()<=a.mx.z()));
+}
+
+
+
+
+
+//////////////////////////////////////
+
+
+//
+DBVT_INLINE btScalar Proximity( const btDbvtAabbMm& a,
+ const btDbvtAabbMm& b)
+{
+ const btVector3 d=(a.mi+a.mx)-(b.mi+b.mx);
+ return(btFabs(d.x())+btFabs(d.y())+btFabs(d.z()));
+}
+
+
+
+//
+DBVT_INLINE int Select( const btDbvtAabbMm& o,
+ const btDbvtAabbMm& a,
+ const btDbvtAabbMm& b)
+{
+#if DBVT_SELECT_IMPL == DBVT_IMPL_SSE
+
+#if defined (_WIN32)
+ static ATTRIBUTE_ALIGNED16(const unsigned __int32) mask[]={0x7fffffff,0x7fffffff,0x7fffffff,0x7fffffff};
+#else
+ static ATTRIBUTE_ALIGNED16(const unsigned int) mask[]={0x7fffffff,0x7fffffff,0x7fffffff,0x00000000 /*0x7fffffff*/};
+#endif
+ ///@todo: the intrinsic version is 11% slower
+#if DBVT_USE_INTRINSIC_SSE
+
+ union btSSEUnion ///NOTE: if we use more intrinsics, move btSSEUnion into the LinearMath directory
+ {
+ __m128 ssereg;
+ float floats[4];
+ int ints[4];
+ };
+
+ __m128 omi(_mm_load_ps(o.mi));
+ omi=_mm_add_ps(omi,_mm_load_ps(o.mx));
+ __m128 ami(_mm_load_ps(a.mi));
+ ami=_mm_add_ps(ami,_mm_load_ps(a.mx));
+ ami=_mm_sub_ps(ami,omi);
+ ami=_mm_and_ps(ami,_mm_load_ps((const float*)mask));
+ __m128 bmi(_mm_load_ps(b.mi));
+ bmi=_mm_add_ps(bmi,_mm_load_ps(b.mx));
+ bmi=_mm_sub_ps(bmi,omi);
+ bmi=_mm_and_ps(bmi,_mm_load_ps((const float*)mask));
+ __m128 t0(_mm_movehl_ps(ami,ami));
+ ami=_mm_add_ps(ami,t0);
+ ami=_mm_add_ss(ami,_mm_shuffle_ps(ami,ami,1));
+ __m128 t1(_mm_movehl_ps(bmi,bmi));
+ bmi=_mm_add_ps(bmi,t1);
+ bmi=_mm_add_ss(bmi,_mm_shuffle_ps(bmi,bmi,1));
+
+ btSSEUnion tmp;
+ tmp.ssereg = _mm_cmple_ss(bmi,ami);
+ return tmp.ints[0]&1;
+
+#else
+ ATTRIBUTE_ALIGNED16(__int32 r[1]);
+ __asm
+ {
+ mov eax,o
+ mov ecx,a
+ mov edx,b
+ movaps xmm0,[eax]
+ movaps xmm5,mask
+ addps xmm0,[eax+16]
+ movaps xmm1,[ecx]
+ movaps xmm2,[edx]
+ addps xmm1,[ecx+16]
+ addps xmm2,[edx+16]
+ subps xmm1,xmm0
+ subps xmm2,xmm0
+ andps xmm1,xmm5
+ andps xmm2,xmm5
+ movhlps xmm3,xmm1
+ movhlps xmm4,xmm2
+ addps xmm1,xmm3
+ addps xmm2,xmm4
+ pshufd xmm3,xmm1,1
+ pshufd xmm4,xmm2,1
+ addss xmm1,xmm3
+ addss xmm2,xmm4
+ cmpless xmm2,xmm1
+ movss r,xmm2
+ }
+ return(r[0]&1);
+#endif
+#else
+ return(Proximity(o,a)<Proximity(o,b)?0:1);
+#endif
+}
+
+//
+DBVT_INLINE void Merge( const btDbvtAabbMm& a,
+ const btDbvtAabbMm& b,
+ btDbvtAabbMm& r)
+{
+#if DBVT_MERGE_IMPL==DBVT_IMPL_SSE
+ __m128 ami(_mm_load_ps(a.mi));
+ __m128 amx(_mm_load_ps(a.mx));
+ __m128 bmi(_mm_load_ps(b.mi));
+ __m128 bmx(_mm_load_ps(b.mx));
+ ami=_mm_min_ps(ami,bmi);
+ amx=_mm_max_ps(amx,bmx);
+ _mm_store_ps(r.mi,ami);
+ _mm_store_ps(r.mx,amx);
+#else
+ for(int i=0;i<3;++i)
+ {
+ if(a.mi[i]<b.mi[i]) r.mi[i]=a.mi[i]; else r.mi[i]=b.mi[i];
+ if(a.mx[i]>b.mx[i]) r.mx[i]=a.mx[i]; else r.mx[i]=b.mx[i];
+ }
+#endif
+}
+
+//
+DBVT_INLINE bool NotEqual( const btDbvtAabbMm& a,
+ const btDbvtAabbMm& b)
+{
+ return( (a.mi.x()!=b.mi.x())||
+ (a.mi.y()!=b.mi.y())||
+ (a.mi.z()!=b.mi.z())||
+ (a.mx.x()!=b.mx.x())||
+ (a.mx.y()!=b.mx.y())||
+ (a.mx.z()!=b.mx.z()));
+}
+
+//
+// Inline's
+//
+
+//
+DBVT_PREFIX
+inline void btDbvt::enumNodes( const btDbvtNode* root,
+ DBVT_IPOLICY)
+{
+ DBVT_CHECKTYPE
+ policy.Process(root);
+ if(root->isinternal())
+ {
+ enumNodes(root->childs[0],policy);
+ enumNodes(root->childs[1],policy);
+ }
+}
+
+//
+DBVT_PREFIX
+inline void btDbvt::enumLeaves( const btDbvtNode* root,
+ DBVT_IPOLICY)
+{
+ DBVT_CHECKTYPE
+ if(root->isinternal())
+ {
+ enumLeaves(root->childs[0],policy);
+ enumLeaves(root->childs[1],policy);
+ }
+ else
+ {
+ policy.Process(root);
+ }
+}
+
+//
+DBVT_PREFIX
+inline void btDbvt::collideTT( const btDbvtNode* root0,
+ const btDbvtNode* root1,
+ DBVT_IPOLICY)
+{
+ DBVT_CHECKTYPE
+ if(root0&&root1)
+ {
+ int depth=1;
+ int treshold=DOUBLE_STACKSIZE-4;
+ btAlignedObjectArray<sStkNN> stkStack;
+ stkStack.resize(DOUBLE_STACKSIZE);
+ stkStack[0]=sStkNN(root0,root1);
+ 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,
+ DBVT_IPOLICY)
+{
+ DBVT_CHECKTYPE
+ if(root0&&root1)
+ {
+ int depth=1;
+ int treshold=DOUBLE_STACKSIZE-4;
+
+ m_stkStack.resize(DOUBLE_STACKSIZE);
+ m_stkStack[0]=sStkNN(root0,root1);
+ do {
+ sStkNN p=m_stkStack[--depth];
+ if(depth>treshold)
+ {
+ m_stkStack.resize(m_stkStack.size()*2);
+ treshold=m_stkStack.size()-4;
+ }
+ if(p.a==p.b)
+ {
+ if(p.a->isinternal())
+ {
+ m_stkStack[depth++]=sStkNN(p.a->childs[0],p.a->childs[0]);
+ m_stkStack[depth++]=sStkNN(p.a->childs[1],p.a->childs[1]);
+ m_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())
+ {
+ m_stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[0]);
+ m_stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[0]);
+ m_stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[1]);
+ m_stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[1]);
+ }
+ else
+ {
+ m_stkStack[depth++]=sStkNN(p.a->childs[0],p.b);
+ m_stkStack[depth++]=sStkNN(p.a->childs[1],p.b);
+ }
+ }
+ else
+ {
+ if(p.b->isinternal())
+ {
+ m_stkStack[depth++]=sStkNN(p.a,p.b->childs[0]);
+ m_stkStack[depth++]=sStkNN(p.a,p.b->childs[1]);
+ }
+ else
+ {
+ policy.Process(p.a,p.b);
+ }
+ }
+ }
+ } while(depth);
+ }
+}
+
+#if 0
+//
+DBVT_PREFIX
+inline void btDbvt::collideTT( const btDbvtNode* root0,
+ const btDbvtNode* root1,
+ const btTransform& xform,
+ DBVT_IPOLICY)
+{
+ DBVT_CHECKTYPE
+ if(root0&&root1)
+ {
+ int depth=1;
+ int treshold=DOUBLE_STACKSIZE-4;
+ btAlignedObjectArray<sStkNN> stkStack;
+ stkStack.resize(DOUBLE_STACKSIZE);
+ stkStack[0]=sStkNN(root0,root1);
+ do {
+ sStkNN p=stkStack[--depth];
+ if(Intersect(p.a->volume,p.b->volume,xform))
+ {
+ if(depth>treshold)
+ {
+ stkStack.resize(stkStack.size()*2);
+ treshold=stkStack.size()-4;
+ }
+ 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::collideTT( const btDbvtNode* root0,
+ const btTransform& xform0,
+ const btDbvtNode* root1,
+ const btTransform& xform1,
+ DBVT_IPOLICY)
+{
+ const btTransform xform=xform0.inverse()*xform1;
+ collideTT(root0,root1,xform,policy);
+}
+#endif
+
+DBVT_PREFIX
+inline void btDbvt::collideTV( const btDbvtNode* root,
+ const btDbvtVolume& vol,
+ DBVT_IPOLICY) const
+{
+ DBVT_CHECKTYPE
+ if(root)
+ {
+ ATTRIBUTE_ALIGNED16(btDbvtVolume) volume(vol);
+ btAlignedObjectArray<const btDbvtNode*> stack;
+ stack.resize(0);
+#ifndef BT_DISABLE_STACK_TEMP_MEMORY
+ char tempmemory[SIMPLE_STACKSIZE*sizeof(const btDbvtNode*)];
+ stack.initializeFromBuffer(tempmemory, 0, SIMPLE_STACKSIZE);
+#else
+ stack.reserve(SIMPLE_STACKSIZE);
+#endif //BT_DISABLE_STACK_TEMP_MEMORY
+
+ stack.push_back(root);
+ do {
+ const btDbvtNode* n=stack[stack.size()-1];
+ stack.pop_back();
+ if(Intersect(n->volume,volume))
+ {
+ if(n->isinternal())
+ {
+ stack.push_back(n->childs[0]);
+ stack.push_back(n->childs[1]);
+ }
+ else
+ {
+ policy.Process(n);
+ }
+ }
+ } while(stack.size()>0);
+ }
+}
+
+//
+DBVT_PREFIX
+inline void btDbvt::collideTVNoStackAlloc( const btDbvtNode* root,
+ const btDbvtVolume& vol,
+ btNodeStack& stack,
+ DBVT_IPOLICY) const
+{
+ DBVT_CHECKTYPE
+ if(root)
+ {
+ ATTRIBUTE_ALIGNED16(btDbvtVolume) volume(vol);
+ stack.resize(0);
+ stack.reserve(SIMPLE_STACKSIZE);
+ stack.push_back(root);
+ do {
+ const btDbvtNode* n=stack[stack.size()-1];
+ stack.pop_back();
+ if(Intersect(n->volume,volume))
+ {
+ if(n->isinternal())
+ {
+ stack.push_back(n->childs[0]);
+ stack.push_back(n->childs[1]);
+ }
+ else
+ {
+ policy.Process(n);
+ }
+ }
+ } while(stack.size()>0);
+ }
+}
+
+
+DBVT_PREFIX
+inline void btDbvt::rayTestInternal( const btDbvtNode* root,
+ const btVector3& rayFrom,
+ const btVector3& rayTo,
+ const btVector3& rayDirectionInverse,
+ unsigned int signs[3],
+ btScalar lambda_max,
+ const btVector3& aabbMin,
+ const btVector3& aabbMax,
+ btAlignedObjectArray<const btDbvtNode*>& stack,
+ DBVT_IPOLICY ) const
+{
+ (void) rayTo;
+ DBVT_CHECKTYPE
+ if(root)
+ {
+ btVector3 resultNormal;
+
+ int depth=1;
+ int treshold=DOUBLE_STACKSIZE-2;
+ stack.resize(DOUBLE_STACKSIZE);
+ stack[0]=root;
+ btVector3 bounds[2];
+ do
+ {
+ const btDbvtNode* node=stack[--depth];
+ bounds[0] = node->volume.Mins()-aabbMax;
+ bounds[1] = node->volume.Maxs()-aabbMin;
+ btScalar tmin=1.f,lambda_min=0.f;
+ unsigned int result1=false;
+ result1 = btRayAabb2(rayFrom,rayDirectionInverse,signs,bounds,tmin,lambda_min,lambda_max);
+ if(result1)
+ {
+ if(node->isinternal())
+ {
+ if(depth>treshold)
+ {
+ stack.resize(stack.size()*2);
+ treshold=stack.size()-2;
+ }
+ stack[depth++]=node->childs[0];
+ stack[depth++]=node->childs[1];
+ }
+ else
+ {
+ policy.Process(node);
+ }
+ }
+ } while(depth);
+ }
+}
+
+//
+DBVT_PREFIX
+inline void btDbvt::rayTest( const btDbvtNode* root,
+ const btVector3& rayFrom,
+ const btVector3& rayTo,
+ DBVT_IPOLICY)
+{
+ DBVT_CHECKTYPE
+ if(root)
+ {
+ btVector3 rayDir = (rayTo-rayFrom);
+ rayDir.normalize ();
+
+ ///what about division by zero? --> just set rayDirection[i] to INF/BT_LARGE_FLOAT
+ btVector3 rayDirectionInverse;
+ rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[0];
+ rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[1];
+ rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[2];
+ unsigned int signs[3] = { rayDirectionInverse[0] < 0.0, rayDirectionInverse[1] < 0.0, rayDirectionInverse[2] < 0.0};
+
+ btScalar lambda_max = rayDir.dot(rayTo-rayFrom);
+
+ btVector3 resultNormal;
+
+ btAlignedObjectArray<const btDbvtNode*> stack;
+
+ int depth=1;
+ int treshold=DOUBLE_STACKSIZE-2;
+
+ char tempmemory[DOUBLE_STACKSIZE * sizeof(const btDbvtNode*)];
+#ifndef BT_DISABLE_STACK_TEMP_MEMORY
+ stack.initializeFromBuffer(tempmemory, DOUBLE_STACKSIZE, DOUBLE_STACKSIZE);
+#else//BT_DISABLE_STACK_TEMP_MEMORY
+ stack.resize(DOUBLE_STACKSIZE);
+#endif //BT_DISABLE_STACK_TEMP_MEMORY
+ stack[0]=root;
+ btVector3 bounds[2];
+ do {
+ const btDbvtNode* node=stack[--depth];
+
+ bounds[0] = node->volume.Mins();
+ bounds[1] = node->volume.Maxs();
+
+ btScalar tmin=1.f,lambda_min=0.f;
+ unsigned int result1 = btRayAabb2(rayFrom,rayDirectionInverse,signs,bounds,tmin,lambda_min,lambda_max);
+
+#ifdef COMPARE_BTRAY_AABB2
+ btScalar param=1.f;
+ bool result2 = btRayAabb(rayFrom,rayTo,node->volume.Mins(),node->volume.Maxs(),param,resultNormal);
+ btAssert(result1 == result2);
+#endif //TEST_BTRAY_AABB2
+
+ if(result1)
+ {
+ if(node->isinternal())
+ {
+ if(depth>treshold)
+ {
+ stack.resize(stack.size()*2);
+ treshold=stack.size()-2;
+ }
+ stack[depth++]=node->childs[0];
+ stack[depth++]=node->childs[1];
+ }
+ else
+ {
+ policy.Process(node);
+ }
+ }
+ } while(depth);
+
+ }
+}
+
+//
+DBVT_PREFIX
+inline void btDbvt::collideKDOP(const btDbvtNode* root,
+ const btVector3* normals,
+ const btScalar* offsets,
+ int count,
+ DBVT_IPOLICY)
+{
+ DBVT_CHECKTYPE
+ if(root)
+ {
+ const int inside=(1<<count)-1;
+ btAlignedObjectArray<sStkNP> stack;
+ int signs[sizeof(unsigned)*8];
+ btAssert(count<int (sizeof(signs)/sizeof(signs[0])));
+ for(int i=0;i<count;++i)
+ {
+ signs[i]= ((normals[i].x()>=0)?1:0)+
+ ((normals[i].y()>=0)?2:0)+
+ ((normals[i].z()>=0)?4:0);
+ }
+ stack.reserve(SIMPLE_STACKSIZE);
+ stack.push_back(sStkNP(root,0));
+ do {
+ sStkNP se=stack[stack.size()-1];
+ bool out=false;
+ stack.pop_back();
+ for(int i=0,j=1;(!out)&&(i<count);++i,j<<=1)
+ {
+ if(0==(se.mask&j))
+ {
+ const int side=se.node->volume.Classify(normals[i],offsets[i],signs[i]);
+ switch(side)
+ {
+ case -1: out=true;break;
+ case +1: se.mask|=j;break;
+ }
+ }
+ }
+ if(!out)
+ {
+ if((se.mask!=inside)&&(se.node->isinternal()))
+ {
+ stack.push_back(sStkNP(se.node->childs[0],se.mask));
+ stack.push_back(sStkNP(se.node->childs[1],se.mask));
+ }
+ else
+ {
+ if(policy.AllLeaves(se.node)) enumLeaves(se.node,policy);
+ }
+ }
+ } while(stack.size());
+ }
+}
+
+//
+DBVT_PREFIX
+inline void btDbvt::collideOCL( const btDbvtNode* root,
+ const btVector3* normals,
+ const btScalar* offsets,
+ const btVector3& sortaxis,
+ int count,
+ DBVT_IPOLICY,
+ bool fsort)
+{
+ DBVT_CHECKTYPE
+ if(root)
+ {
+ const unsigned srtsgns=(sortaxis[0]>=0?1:0)+
+ (sortaxis[1]>=0?2:0)+
+ (sortaxis[2]>=0?4:0);
+ const int inside=(1<<count)-1;
+ btAlignedObjectArray<sStkNPS> stock;
+ btAlignedObjectArray<int> ifree;
+ btAlignedObjectArray<int> stack;
+ int signs[sizeof(unsigned)*8];
+ btAssert(count<int (sizeof(signs)/sizeof(signs[0])));
+ for(int i=0;i<count;++i)
+ {
+ signs[i]= ((normals[i].x()>=0)?1:0)+
+ ((normals[i].y()>=0)?2:0)+
+ ((normals[i].z()>=0)?4:0);
+ }
+ stock.reserve(SIMPLE_STACKSIZE);
+ stack.reserve(SIMPLE_STACKSIZE);
+ ifree.reserve(SIMPLE_STACKSIZE);
+ stack.push_back(allocate(ifree,stock,sStkNPS(root,0,root->volume.ProjectMinimum(sortaxis,srtsgns))));
+ do {
+ const int id=stack[stack.size()-1];
+ sStkNPS se=stock[id];
+ stack.pop_back();ifree.push_back(id);
+ if(se.mask!=inside)
+ {
+ bool out=false;
+ for(int i=0,j=1;(!out)&&(i<count);++i,j<<=1)
+ {
+ if(0==(se.mask&j))
+ {
+ const int side=se.node->volume.Classify(normals[i],offsets[i],signs[i]);
+ switch(side)
+ {
+ case -1: out=true;break;
+ case +1: se.mask|=j;break;
+ }
+ }
+ }
+ if(out) continue;
+ }
+ if(policy.Descent(se.node))
+ {
+ if(se.node->isinternal())
+ {
+ const btDbvtNode* pns[]={ se.node->childs[0],se.node->childs[1]};
+ sStkNPS nes[]={ sStkNPS(pns[0],se.mask,pns[0]->volume.ProjectMinimum(sortaxis,srtsgns)),
+ sStkNPS(pns[1],se.mask,pns[1]->volume.ProjectMinimum(sortaxis,srtsgns))};
+ const int q=nes[0].value<nes[1].value?1:0;
+ int j=stack.size();
+ if(fsort&&(j>0))
+ {
+ /* Insert 0 */
+ j=nearest(&stack[0],&stock[0],nes[q].value,0,stack.size());
+ stack.push_back(0);
+
+ //void * memmove ( void * destination, const void * source, size_t num );
+
+#if DBVT_USE_MEMMOVE
+ {
+ int num_items_to_move = stack.size()-1-j;
+ if(num_items_to_move > 0)
+ memmove(&stack[j+1],&stack[j],sizeof(int)*num_items_to_move);
+ }
+#else
+ for(int k=stack.size()-1;k>j;--k) {
+ stack[k]=stack[k-1];
+ }
+#endif
+ stack[j]=allocate(ifree,stock,nes[q]);
+ /* Insert 1 */
+ j=nearest(&stack[0],&stock[0],nes[1-q].value,j,stack.size());
+ stack.push_back(0);
+#if DBVT_USE_MEMMOVE
+ {
+ int num_items_to_move = stack.size()-1-j;
+ if(num_items_to_move > 0)
+ memmove(&stack[j+1],&stack[j],sizeof(int)*num_items_to_move);
+ }
+#else
+ for(int k=stack.size()-1;k>j;--k) {
+ stack[k]=stack[k-1];
+ }
+#endif
+ stack[j]=allocate(ifree,stock,nes[1-q]);
+ }
+ else
+ {
+ stack.push_back(allocate(ifree,stock,nes[q]));
+ stack.push_back(allocate(ifree,stock,nes[1-q]));
+ }
+ }
+ else
+ {
+ policy.Process(se.node,se.value);
+ }
+ }
+ } while(stack.size());
+ }
+}
+
+//
+DBVT_PREFIX
+inline void btDbvt::collideTU( const btDbvtNode* root,
+ DBVT_IPOLICY)
+{
+ DBVT_CHECKTYPE
+ if(root)
+ {
+ btAlignedObjectArray<const btDbvtNode*> stack;
+ stack.reserve(SIMPLE_STACKSIZE);
+ stack.push_back(root);
+ do {
+ const btDbvtNode* n=stack[stack.size()-1];
+ stack.pop_back();
+ if(policy.Descent(n))
+ {
+ if(n->isinternal())
+ { stack.push_back(n->childs[0]);stack.push_back(n->childs[1]); }
+ else
+ { policy.Process(n); }
+ }
+ } while(stack.size()>0);
+ }
+}
+
+//
+// PP Cleanup
+//
+
+#undef DBVT_USE_MEMMOVE
+#undef DBVT_USE_TEMPLATE
+#undef DBVT_VIRTUAL_DTOR
+#undef DBVT_VIRTUAL
+#undef DBVT_PREFIX
+#undef DBVT_IPOLICY
+#undef DBVT_CHECKTYPE
+#undef DBVT_IMPL_GENERIC
+#undef DBVT_IMPL_SSE
+#undef DBVT_USE_INTRINSIC_SSE
+#undef DBVT_SELECT_IMPL
+#undef DBVT_MERGE_IMPL
+#undef DBVT_INT0_IMPL
+
+#endif
diff --git a/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp b/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp
new file mode 100644
index 0000000000..4d12b1c9c7
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp
@@ -0,0 +1,822 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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.
+*/
+
+///btDbvtBroadphase implementation by Nathanael Presson
+
+#include "btDbvtBroadphase.h"
+#include "LinearMath/btThreads.h"
+
+//
+// Profiling
+//
+
+#if DBVT_BP_PROFILE||DBVT_BP_ENABLE_BENCHMARK
+#include <stdio.h>
+#endif
+
+#if DBVT_BP_PROFILE
+struct ProfileScope
+{
+ __forceinline ProfileScope(btClock& clock,unsigned long& value) :
+ m_clock(&clock),m_value(&value),m_base(clock.getTimeMicroseconds())
+ {
+ }
+ __forceinline ~ProfileScope()
+ {
+ (*m_value)+=m_clock->getTimeMicroseconds()-m_base;
+ }
+ btClock* m_clock;
+ unsigned long* m_value;
+ unsigned long m_base;
+};
+#define SPC(_value_) ProfileScope spc_scope(m_clock,_value_)
+#else
+#define SPC(_value_)
+#endif
+
+//
+// Helpers
+//
+
+//
+template <typename T>
+static inline void listappend(T* item,T*& list)
+{
+ item->links[0]=0;
+ item->links[1]=list;
+ if(list) list->links[0]=item;
+ list=item;
+}
+
+//
+template <typename T>
+static inline void listremove(T* item,T*& list)
+{
+ if(item->links[0]) item->links[0]->links[1]=item->links[1]; else list=item->links[1];
+ if(item->links[1]) item->links[1]->links[0]=item->links[0];
+}
+
+//
+template <typename T>
+static inline int listcount(T* root)
+{
+ int n=0;
+ while(root) { ++n;root=root->links[1]; }
+ return(n);
+}
+
+//
+template <typename T>
+static inline void clear(T& value)
+{
+ static const struct ZeroDummy : T {} zerodummy;
+ value=zerodummy;
+}
+
+//
+// Colliders
+//
+
+/* Tree collider */
+struct btDbvtTreeCollider : btDbvt::ICollide
+{
+ btDbvtBroadphase* pbp;
+ btDbvtProxy* proxy;
+ btDbvtTreeCollider(btDbvtBroadphase* p) : pbp(p) {}
+ void Process(const btDbvtNode* na,const btDbvtNode* nb)
+ {
+ if(na!=nb)
+ {
+ btDbvtProxy* pa=(btDbvtProxy*)na->data;
+ btDbvtProxy* pb=(btDbvtProxy*)nb->data;
+#if DBVT_BP_SORTPAIRS
+ if(pa->m_uniqueId>pb->m_uniqueId)
+ btSwap(pa,pb);
+#endif
+ pbp->m_paircache->addOverlappingPair(pa,pb);
+ ++pbp->m_newpairs;
+ }
+ }
+ void Process(const btDbvtNode* n)
+ {
+ Process(n,proxy->leaf);
+ }
+};
+
+//
+// btDbvtBroadphase
+//
+
+//
+btDbvtBroadphase::btDbvtBroadphase(btOverlappingPairCache* paircache)
+{
+ m_deferedcollide = false;
+ m_needcleanup = true;
+ m_releasepaircache = (paircache!=0)?false:true;
+ m_prediction = 0;
+ m_stageCurrent = 0;
+ m_fixedleft = 0;
+ m_fupdates = 1;
+ m_dupdates = 0;
+ m_cupdates = 10;
+ m_newpairs = 1;
+ m_updates_call = 0;
+ m_updates_done = 0;
+ m_updates_ratio = 0;
+ m_paircache = paircache? paircache : new(btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16)) btHashedOverlappingPairCache();
+ m_gid = 0;
+ m_pid = 0;
+ m_cid = 0;
+ for(int i=0;i<=STAGECOUNT;++i)
+ {
+ m_stageRoots[i]=0;
+ }
+#if BT_THREADSAFE
+ m_rayTestStacks.resize(BT_MAX_THREAD_COUNT);
+#else
+ m_rayTestStacks.resize(1);
+#endif
+#if DBVT_BP_PROFILE
+ clear(m_profiling);
+#endif
+}
+
+//
+btDbvtBroadphase::~btDbvtBroadphase()
+{
+ if(m_releasepaircache)
+ {
+ m_paircache->~btOverlappingPairCache();
+ btAlignedFree(m_paircache);
+ }
+}
+
+//
+btBroadphaseProxy* btDbvtBroadphase::createProxy( const btVector3& aabbMin,
+ const btVector3& aabbMax,
+ int /*shapeType*/,
+ void* userPtr,
+ int collisionFilterGroup,
+ int collisionFilterMask,
+ btDispatcher* /*dispatcher*/)
+{
+ btDbvtProxy* proxy=new(btAlignedAlloc(sizeof(btDbvtProxy),16)) btDbvtProxy( aabbMin,aabbMax,userPtr,
+ collisionFilterGroup,
+ collisionFilterMask);
+
+ btDbvtAabbMm aabb = btDbvtVolume::FromMM(aabbMin,aabbMax);
+
+ //bproxy->aabb = btDbvtVolume::FromMM(aabbMin,aabbMax);
+ proxy->stage = m_stageCurrent;
+ proxy->m_uniqueId = ++m_gid;
+ proxy->leaf = m_sets[0].insert(aabb,proxy);
+ listappend(proxy,m_stageRoots[m_stageCurrent]);
+ if(!m_deferedcollide)
+ {
+ btDbvtTreeCollider collider(this);
+ collider.proxy=proxy;
+ m_sets[0].collideTV(m_sets[0].m_root,aabb,collider);
+ m_sets[1].collideTV(m_sets[1].m_root,aabb,collider);
+ }
+ return(proxy);
+}
+
+//
+void btDbvtBroadphase::destroyProxy( btBroadphaseProxy* absproxy,
+ btDispatcher* dispatcher)
+{
+ btDbvtProxy* proxy=(btDbvtProxy*)absproxy;
+ if(proxy->stage==STAGECOUNT)
+ m_sets[1].remove(proxy->leaf);
+ else
+ m_sets[0].remove(proxy->leaf);
+ listremove(proxy,m_stageRoots[proxy->stage]);
+ m_paircache->removeOverlappingPairsContainingProxy(proxy,dispatcher);
+ btAlignedFree(proxy);
+ m_needcleanup=true;
+}
+
+void btDbvtBroadphase::getAabb(btBroadphaseProxy* absproxy,btVector3& aabbMin, btVector3& aabbMax ) const
+{
+ btDbvtProxy* proxy=(btDbvtProxy*)absproxy;
+ aabbMin = proxy->m_aabbMin;
+ aabbMax = proxy->m_aabbMax;
+}
+
+struct BroadphaseRayTester : btDbvt::ICollide
+{
+ btBroadphaseRayCallback& m_rayCallback;
+ BroadphaseRayTester(btBroadphaseRayCallback& orgCallback)
+ :m_rayCallback(orgCallback)
+ {
+ }
+ void Process(const btDbvtNode* leaf)
+ {
+ btDbvtProxy* proxy=(btDbvtProxy*)leaf->data;
+ m_rayCallback.process(proxy);
+ }
+};
+
+void btDbvtBroadphase::rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback,const btVector3& aabbMin,const btVector3& aabbMax)
+{
+ BroadphaseRayTester callback(rayCallback);
+ btAlignedObjectArray<const btDbvtNode*>* stack = &m_rayTestStacks[0];
+#if BT_THREADSAFE
+ // for this function to be threadsafe, each thread must have a separate copy
+ // of this stack. This could be thread-local static to avoid dynamic allocations,
+ // instead of just a local.
+ int threadIndex = btGetCurrentThreadIndex();
+ btAlignedObjectArray<const btDbvtNode*> localStack;
+ if (threadIndex < m_rayTestStacks.size())
+ {
+ // use per-thread preallocated stack if possible to avoid dynamic allocations
+ stack = &m_rayTestStacks[threadIndex];
+ }
+ else
+ {
+ stack = &localStack;
+ }
+#endif
+
+ m_sets[0].rayTestInternal( m_sets[0].m_root,
+ rayFrom,
+ rayTo,
+ rayCallback.m_rayDirectionInverse,
+ rayCallback.m_signs,
+ rayCallback.m_lambda_max,
+ aabbMin,
+ aabbMax,
+ *stack,
+ callback);
+
+ m_sets[1].rayTestInternal( m_sets[1].m_root,
+ rayFrom,
+ rayTo,
+ rayCallback.m_rayDirectionInverse,
+ rayCallback.m_signs,
+ rayCallback.m_lambda_max,
+ aabbMin,
+ aabbMax,
+ *stack,
+ callback);
+
+}
+
+
+struct BroadphaseAabbTester : btDbvt::ICollide
+{
+ btBroadphaseAabbCallback& m_aabbCallback;
+ BroadphaseAabbTester(btBroadphaseAabbCallback& orgCallback)
+ :m_aabbCallback(orgCallback)
+ {
+ }
+ void Process(const btDbvtNode* leaf)
+ {
+ btDbvtProxy* proxy=(btDbvtProxy*)leaf->data;
+ m_aabbCallback.process(proxy);
+ }
+};
+
+void btDbvtBroadphase::aabbTest(const btVector3& aabbMin,const btVector3& aabbMax,btBroadphaseAabbCallback& aabbCallback)
+{
+ BroadphaseAabbTester callback(aabbCallback);
+
+ const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds=btDbvtVolume::FromMM(aabbMin,aabbMax);
+ //process all children, that overlap with the given AABB bounds
+ m_sets[0].collideTV(m_sets[0].m_root,bounds,callback);
+ m_sets[1].collideTV(m_sets[1].m_root,bounds,callback);
+
+}
+
+
+
+//
+void btDbvtBroadphase::setAabb( btBroadphaseProxy* absproxy,
+ const btVector3& aabbMin,
+ const btVector3& aabbMax,
+ btDispatcher* /*dispatcher*/)
+{
+ btDbvtProxy* proxy=(btDbvtProxy*)absproxy;
+ ATTRIBUTE_ALIGNED16(btDbvtVolume) aabb=btDbvtVolume::FromMM(aabbMin,aabbMax);
+#if DBVT_BP_PREVENTFALSEUPDATE
+ if(NotEqual(aabb,proxy->leaf->volume))
+#endif
+ {
+ bool docollide=false;
+ if(proxy->stage==STAGECOUNT)
+ {/* fixed -> dynamic set */
+ m_sets[1].remove(proxy->leaf);
+ proxy->leaf=m_sets[0].insert(aabb,proxy);
+ docollide=true;
+ }
+ else
+ {/* dynamic set */
+ ++m_updates_call;
+ if(Intersect(proxy->leaf->volume,aabb))
+ {/* Moving */
+
+ const btVector3 delta=aabbMin-proxy->m_aabbMin;
+ btVector3 velocity(((proxy->m_aabbMax-proxy->m_aabbMin)/2)*m_prediction);
+ if(delta[0]<0) velocity[0]=-velocity[0];
+ if(delta[1]<0) velocity[1]=-velocity[1];
+ if(delta[2]<0) velocity[2]=-velocity[2];
+ if (
+#ifdef DBVT_BP_MARGIN
+ m_sets[0].update(proxy->leaf,aabb,velocity,DBVT_BP_MARGIN)
+#else
+ m_sets[0].update(proxy->leaf,aabb,velocity)
+#endif
+ )
+ {
+ ++m_updates_done;
+ docollide=true;
+ }
+ }
+ else
+ {/* Teleporting */
+ m_sets[0].update(proxy->leaf,aabb);
+ ++m_updates_done;
+ docollide=true;
+ }
+ }
+ listremove(proxy,m_stageRoots[proxy->stage]);
+ proxy->m_aabbMin = aabbMin;
+ proxy->m_aabbMax = aabbMax;
+ proxy->stage = m_stageCurrent;
+ listappend(proxy,m_stageRoots[m_stageCurrent]);
+ if(docollide)
+ {
+ m_needcleanup=true;
+ if(!m_deferedcollide)
+ {
+ btDbvtTreeCollider collider(this);
+ m_sets[1].collideTTpersistentStack(m_sets[1].m_root,proxy->leaf,collider);
+ m_sets[0].collideTTpersistentStack(m_sets[0].m_root,proxy->leaf,collider);
+ }
+ }
+ }
+}
+
+
+//
+void btDbvtBroadphase::setAabbForceUpdate( btBroadphaseProxy* absproxy,
+ const btVector3& aabbMin,
+ const btVector3& aabbMax,
+ btDispatcher* /*dispatcher*/)
+{
+ btDbvtProxy* proxy=(btDbvtProxy*)absproxy;
+ ATTRIBUTE_ALIGNED16(btDbvtVolume) aabb=btDbvtVolume::FromMM(aabbMin,aabbMax);
+ bool docollide=false;
+ if(proxy->stage==STAGECOUNT)
+ {/* fixed -> dynamic set */
+ m_sets[1].remove(proxy->leaf);
+ proxy->leaf=m_sets[0].insert(aabb,proxy);
+ docollide=true;
+ }
+ else
+ {/* dynamic set */
+ ++m_updates_call;
+ /* Teleporting */
+ m_sets[0].update(proxy->leaf,aabb);
+ ++m_updates_done;
+ docollide=true;
+ }
+ listremove(proxy,m_stageRoots[proxy->stage]);
+ proxy->m_aabbMin = aabbMin;
+ proxy->m_aabbMax = aabbMax;
+ proxy->stage = m_stageCurrent;
+ listappend(proxy,m_stageRoots[m_stageCurrent]);
+ if(docollide)
+ {
+ m_needcleanup=true;
+ if(!m_deferedcollide)
+ {
+ btDbvtTreeCollider collider(this);
+ m_sets[1].collideTTpersistentStack(m_sets[1].m_root,proxy->leaf,collider);
+ m_sets[0].collideTTpersistentStack(m_sets[0].m_root,proxy->leaf,collider);
+ }
+ }
+}
+
+//
+void btDbvtBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
+{
+ collide(dispatcher);
+#if DBVT_BP_PROFILE
+ if(0==(m_pid%DBVT_BP_PROFILING_RATE))
+ {
+ printf("fixed(%u) dynamics(%u) pairs(%u)\r\n",m_sets[1].m_leaves,m_sets[0].m_leaves,m_paircache->getNumOverlappingPairs());
+ unsigned int total=m_profiling.m_total;
+ if(total<=0) total=1;
+ printf("ddcollide: %u%% (%uus)\r\n",(50+m_profiling.m_ddcollide*100)/total,m_profiling.m_ddcollide/DBVT_BP_PROFILING_RATE);
+ printf("fdcollide: %u%% (%uus)\r\n",(50+m_profiling.m_fdcollide*100)/total,m_profiling.m_fdcollide/DBVT_BP_PROFILING_RATE);
+ printf("cleanup: %u%% (%uus)\r\n",(50+m_profiling.m_cleanup*100)/total,m_profiling.m_cleanup/DBVT_BP_PROFILING_RATE);
+ printf("total: %uus\r\n",total/DBVT_BP_PROFILING_RATE);
+ const unsigned long sum=m_profiling.m_ddcollide+
+ m_profiling.m_fdcollide+
+ m_profiling.m_cleanup;
+ printf("leaked: %u%% (%uus)\r\n",100-((50+sum*100)/total),(total-sum)/DBVT_BP_PROFILING_RATE);
+ printf("job counts: %u%%\r\n",(m_profiling.m_jobcount*100)/((m_sets[0].m_leaves+m_sets[1].m_leaves)*DBVT_BP_PROFILING_RATE));
+ clear(m_profiling);
+ m_clock.reset();
+ }
+#endif
+
+ performDeferredRemoval(dispatcher);
+
+}
+
+void btDbvtBroadphase::performDeferredRemoval(btDispatcher* dispatcher)
+{
+
+ if (m_paircache->hasDeferredRemoval())
+ {
+
+ btBroadphasePairArray& overlappingPairArray = m_paircache->getOverlappingPairArray();
+
+ //perform a sort, to find duplicates and to sort 'invalid' pairs to the end
+ overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
+
+ int invalidPair = 0;
+
+
+ int i;
+
+ btBroadphasePair previousPair;
+ previousPair.m_pProxy0 = 0;
+ previousPair.m_pProxy1 = 0;
+ previousPair.m_algorithm = 0;
+
+
+ for (i=0;i<overlappingPairArray.size();i++)
+ {
+
+ btBroadphasePair& pair = overlappingPairArray[i];
+
+ bool isDuplicate = (pair == previousPair);
+
+ previousPair = pair;
+
+ bool needsRemoval = false;
+
+ if (!isDuplicate)
+ {
+ //important to perform AABB check that is consistent with the broadphase
+ btDbvtProxy* pa=(btDbvtProxy*)pair.m_pProxy0;
+ btDbvtProxy* pb=(btDbvtProxy*)pair.m_pProxy1;
+ bool hasOverlap = Intersect(pa->leaf->volume,pb->leaf->volume);
+
+ if (hasOverlap)
+ {
+ needsRemoval = false;
+ } else
+ {
+ needsRemoval = true;
+ }
+ } else
+ {
+ //remove duplicate
+ needsRemoval = true;
+ //should have no algorithm
+ btAssert(!pair.m_algorithm);
+ }
+
+ if (needsRemoval)
+ {
+ m_paircache->cleanOverlappingPair(pair,dispatcher);
+
+ pair.m_pProxy0 = 0;
+ pair.m_pProxy1 = 0;
+ invalidPair++;
+ }
+
+ }
+
+ //perform a sort, to sort 'invalid' pairs to the end
+ overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
+ overlappingPairArray.resize(overlappingPairArray.size() - invalidPair);
+ }
+}
+
+//
+void btDbvtBroadphase::collide(btDispatcher* dispatcher)
+{
+ /*printf("---------------------------------------------------------\n");
+ printf("m_sets[0].m_leaves=%d\n",m_sets[0].m_leaves);
+ printf("m_sets[1].m_leaves=%d\n",m_sets[1].m_leaves);
+ printf("numPairs = %d\n",getOverlappingPairCache()->getNumOverlappingPairs());
+ {
+ int i;
+ for (i=0;i<getOverlappingPairCache()->getNumOverlappingPairs();i++)
+ {
+ printf("pair[%d]=(%d,%d),",i,getOverlappingPairCache()->getOverlappingPairArray()[i].m_pProxy0->getUid(),
+ getOverlappingPairCache()->getOverlappingPairArray()[i].m_pProxy1->getUid());
+ }
+ printf("\n");
+ }
+*/
+
+
+
+ SPC(m_profiling.m_total);
+ /* optimize */
+ m_sets[0].optimizeIncremental(1+(m_sets[0].m_leaves*m_dupdates)/100);
+ if(m_fixedleft)
+ {
+ const int count=1+(m_sets[1].m_leaves*m_fupdates)/100;
+ m_sets[1].optimizeIncremental(1+(m_sets[1].m_leaves*m_fupdates)/100);
+ m_fixedleft=btMax<int>(0,m_fixedleft-count);
+ }
+ /* dynamic -> fixed set */
+ m_stageCurrent=(m_stageCurrent+1)%STAGECOUNT;
+ btDbvtProxy* current=m_stageRoots[m_stageCurrent];
+ if(current)
+ {
+#if DBVT_BP_ACCURATESLEEPING
+ btDbvtTreeCollider collider(this);
+#endif
+ do {
+ btDbvtProxy* next=current->links[1];
+ listremove(current,m_stageRoots[current->stage]);
+ listappend(current,m_stageRoots[STAGECOUNT]);
+#if DBVT_BP_ACCURATESLEEPING
+ m_paircache->removeOverlappingPairsContainingProxy(current,dispatcher);
+ collider.proxy=current;
+ btDbvt::collideTV(m_sets[0].m_root,current->aabb,collider);
+ btDbvt::collideTV(m_sets[1].m_root,current->aabb,collider);
+#endif
+ m_sets[0].remove(current->leaf);
+ ATTRIBUTE_ALIGNED16(btDbvtVolume) curAabb=btDbvtVolume::FromMM(current->m_aabbMin,current->m_aabbMax);
+ current->leaf = m_sets[1].insert(curAabb,current);
+ current->stage = STAGECOUNT;
+ current = next;
+ } while(current);
+ m_fixedleft=m_sets[1].m_leaves;
+ m_needcleanup=true;
+ }
+ /* collide dynamics */
+ {
+ btDbvtTreeCollider collider(this);
+ if(m_deferedcollide)
+ {
+ SPC(m_profiling.m_fdcollide);
+ m_sets[0].collideTTpersistentStack(m_sets[0].m_root,m_sets[1].m_root,collider);
+ }
+ if(m_deferedcollide)
+ {
+ SPC(m_profiling.m_ddcollide);
+ m_sets[0].collideTTpersistentStack(m_sets[0].m_root,m_sets[0].m_root,collider);
+ }
+ }
+ /* clean up */
+ if(m_needcleanup)
+ {
+ SPC(m_profiling.m_cleanup);
+ btBroadphasePairArray& pairs=m_paircache->getOverlappingPairArray();
+ if(pairs.size()>0)
+ {
+
+ int ni=btMin(pairs.size(),btMax<int>(m_newpairs,(pairs.size()*m_cupdates)/100));
+ for(int i=0;i<ni;++i)
+ {
+ btBroadphasePair& p=pairs[(m_cid+i)%pairs.size()];
+ btDbvtProxy* pa=(btDbvtProxy*)p.m_pProxy0;
+ btDbvtProxy* pb=(btDbvtProxy*)p.m_pProxy1;
+ if(!Intersect(pa->leaf->volume,pb->leaf->volume))
+ {
+#if DBVT_BP_SORTPAIRS
+ if(pa->m_uniqueId>pb->m_uniqueId)
+ btSwap(pa,pb);
+#endif
+ m_paircache->removeOverlappingPair(pa,pb,dispatcher);
+ --ni;--i;
+ }
+ }
+ if(pairs.size()>0) m_cid=(m_cid+ni)%pairs.size(); else m_cid=0;
+ }
+ }
+ ++m_pid;
+ m_newpairs=1;
+ m_needcleanup=false;
+ if(m_updates_call>0)
+ { m_updates_ratio=m_updates_done/(btScalar)m_updates_call; }
+ else
+ { m_updates_ratio=0; }
+ m_updates_done/=2;
+ m_updates_call/=2;
+}
+
+//
+void btDbvtBroadphase::optimize()
+{
+ m_sets[0].optimizeTopDown();
+ m_sets[1].optimizeTopDown();
+}
+
+//
+btOverlappingPairCache* btDbvtBroadphase::getOverlappingPairCache()
+{
+ return(m_paircache);
+}
+
+//
+const btOverlappingPairCache* btDbvtBroadphase::getOverlappingPairCache() const
+{
+ return(m_paircache);
+}
+
+//
+void btDbvtBroadphase::getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const
+{
+
+ ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds;
+
+ if(!m_sets[0].empty())
+ if(!m_sets[1].empty()) Merge( m_sets[0].m_root->volume,
+ m_sets[1].m_root->volume,bounds);
+ else
+ bounds=m_sets[0].m_root->volume;
+ else if(!m_sets[1].empty()) bounds=m_sets[1].m_root->volume;
+ else
+ bounds=btDbvtVolume::FromCR(btVector3(0,0,0),0);
+ aabbMin=bounds.Mins();
+ aabbMax=bounds.Maxs();
+}
+
+void btDbvtBroadphase::resetPool(btDispatcher* dispatcher)
+{
+
+ int totalObjects = m_sets[0].m_leaves + m_sets[1].m_leaves;
+ if (!totalObjects)
+ {
+ //reset internal dynamic tree data structures
+ m_sets[0].clear();
+ m_sets[1].clear();
+
+ m_deferedcollide = false;
+ m_needcleanup = true;
+ m_stageCurrent = 0;
+ m_fixedleft = 0;
+ m_fupdates = 1;
+ m_dupdates = 0;
+ m_cupdates = 10;
+ m_newpairs = 1;
+ m_updates_call = 0;
+ m_updates_done = 0;
+ m_updates_ratio = 0;
+
+ m_gid = 0;
+ m_pid = 0;
+ m_cid = 0;
+ for(int i=0;i<=STAGECOUNT;++i)
+ {
+ m_stageRoots[i]=0;
+ }
+ }
+}
+
+//
+void btDbvtBroadphase::printStats()
+{}
+
+//
+#if DBVT_BP_ENABLE_BENCHMARK
+
+struct btBroadphaseBenchmark
+{
+ struct Experiment
+ {
+ const char* name;
+ int object_count;
+ int update_count;
+ int spawn_count;
+ int iterations;
+ btScalar speed;
+ btScalar amplitude;
+ };
+ struct Object
+ {
+ btVector3 center;
+ btVector3 extents;
+ btBroadphaseProxy* proxy;
+ btScalar time;
+ void update(btScalar speed,btScalar amplitude,btBroadphaseInterface* pbi)
+ {
+ time += speed;
+ center[0] = btCos(time*(btScalar)2.17)*amplitude+
+ btSin(time)*amplitude/2;
+ center[1] = btCos(time*(btScalar)1.38)*amplitude+
+ btSin(time)*amplitude;
+ center[2] = btSin(time*(btScalar)0.777)*amplitude;
+ pbi->setAabb(proxy,center-extents,center+extents,0);
+ }
+ };
+ static int UnsignedRand(int range=RAND_MAX-1) { return(rand()%(range+1)); }
+ static btScalar UnitRand() { return(UnsignedRand(16384)/(btScalar)16384); }
+ static void OutputTime(const char* name,btClock& c,unsigned count=0)
+ {
+ const unsigned long us=c.getTimeMicroseconds();
+ const unsigned long ms=(us+500)/1000;
+ const btScalar sec=us/(btScalar)(1000*1000);
+ if(count>0)
+ printf("%s : %u us (%u ms), %.2f/s\r\n",name,us,ms,count/sec);
+ else
+ printf("%s : %u us (%u ms)\r\n",name,us,ms);
+ }
+};
+
+void btDbvtBroadphase::benchmark(btBroadphaseInterface* pbi)
+{
+ static const btBroadphaseBenchmark::Experiment experiments[]=
+ {
+ {"1024o.10%",1024,10,0,8192,(btScalar)0.005,(btScalar)100},
+ /*{"4096o.10%",4096,10,0,8192,(btScalar)0.005,(btScalar)100},
+ {"8192o.10%",8192,10,0,8192,(btScalar)0.005,(btScalar)100},*/
+ };
+ static const int nexperiments=sizeof(experiments)/sizeof(experiments[0]);
+ btAlignedObjectArray<btBroadphaseBenchmark::Object*> objects;
+ btClock wallclock;
+ /* Begin */
+ for(int iexp=0;iexp<nexperiments;++iexp)
+ {
+ const btBroadphaseBenchmark::Experiment& experiment=experiments[iexp];
+ const int object_count=experiment.object_count;
+ const int update_count=(object_count*experiment.update_count)/100;
+ const int spawn_count=(object_count*experiment.spawn_count)/100;
+ const btScalar speed=experiment.speed;
+ const btScalar amplitude=experiment.amplitude;
+ printf("Experiment #%u '%s':\r\n",iexp,experiment.name);
+ printf("\tObjects: %u\r\n",object_count);
+ printf("\tUpdate: %u\r\n",update_count);
+ printf("\tSpawn: %u\r\n",spawn_count);
+ printf("\tSpeed: %f\r\n",speed);
+ printf("\tAmplitude: %f\r\n",amplitude);
+ srand(180673);
+ /* Create objects */
+ wallclock.reset();
+ objects.reserve(object_count);
+ for(int i=0;i<object_count;++i)
+ {
+ btBroadphaseBenchmark::Object* po=new btBroadphaseBenchmark::Object();
+ po->center[0]=btBroadphaseBenchmark::UnitRand()*50;
+ po->center[1]=btBroadphaseBenchmark::UnitRand()*50;
+ po->center[2]=btBroadphaseBenchmark::UnitRand()*50;
+ po->extents[0]=btBroadphaseBenchmark::UnitRand()*2+2;
+ po->extents[1]=btBroadphaseBenchmark::UnitRand()*2+2;
+ po->extents[2]=btBroadphaseBenchmark::UnitRand()*2+2;
+ po->time=btBroadphaseBenchmark::UnitRand()*2000;
+ po->proxy=pbi->createProxy(po->center-po->extents,po->center+po->extents,0,po,1,1,0,0);
+ objects.push_back(po);
+ }
+ btBroadphaseBenchmark::OutputTime("\tInitialization",wallclock);
+ /* First update */
+ wallclock.reset();
+ for(int i=0;i<objects.size();++i)
+ {
+ objects[i]->update(speed,amplitude,pbi);
+ }
+ btBroadphaseBenchmark::OutputTime("\tFirst update",wallclock);
+ /* Updates */
+ wallclock.reset();
+ for(int i=0;i<experiment.iterations;++i)
+ {
+ for(int j=0;j<update_count;++j)
+ {
+ objects[j]->update(speed,amplitude,pbi);
+ }
+ pbi->calculateOverlappingPairs(0);
+ }
+ btBroadphaseBenchmark::OutputTime("\tUpdate",wallclock,experiment.iterations);
+ /* Clean up */
+ wallclock.reset();
+ for(int i=0;i<objects.size();++i)
+ {
+ pbi->destroyProxy(objects[i]->proxy,0);
+ delete objects[i];
+ }
+ objects.resize(0);
+ btBroadphaseBenchmark::OutputTime("\tRelease",wallclock);
+ }
+
+}
+#else
+void btDbvtBroadphase::benchmark(btBroadphaseInterface*)
+{}
+#endif
+
+#if DBVT_BP_PROFILE
+#undef SPC
+#endif
+
diff --git a/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h b/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h
new file mode 100644
index 0000000000..8feb95d51f
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h
@@ -0,0 +1,147 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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.
+*/
+
+///btDbvtBroadphase implementation by Nathanael Presson
+#ifndef BT_DBVT_BROADPHASE_H
+#define BT_DBVT_BROADPHASE_H
+
+#include "BulletCollision/BroadphaseCollision/btDbvt.h"
+#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
+
+//
+// Compile time config
+//
+
+#define DBVT_BP_PROFILE 0
+//#define DBVT_BP_SORTPAIRS 1
+#define DBVT_BP_PREVENTFALSEUPDATE 0
+#define DBVT_BP_ACCURATESLEEPING 0
+#define DBVT_BP_ENABLE_BENCHMARK 0
+#define DBVT_BP_MARGIN (btScalar)0.05
+
+#if DBVT_BP_PROFILE
+#define DBVT_BP_PROFILING_RATE 256
+#include "LinearMath/btQuickprof.h"
+#endif
+
+//
+// btDbvtProxy
+//
+struct btDbvtProxy : btBroadphaseProxy
+{
+ /* Fields */
+ //btDbvtAabbMm aabb;
+ btDbvtNode* leaf;
+ btDbvtProxy* links[2];
+ int stage;
+ /* ctor */
+ btDbvtProxy(const btVector3& aabbMin,const btVector3& aabbMax,void* userPtr, int collisionFilterGroup, int collisionFilterMask) :
+ btBroadphaseProxy(aabbMin,aabbMax,userPtr,collisionFilterGroup,collisionFilterMask)
+ {
+ links[0]=links[1]=0;
+ }
+};
+
+typedef btAlignedObjectArray<btDbvtProxy*> btDbvtProxyArray;
+
+///The btDbvtBroadphase implements a broadphase using two dynamic AABB bounding volume hierarchies/trees (see btDbvt).
+///One tree is used for static/non-moving objects, and another tree is used for dynamic objects. Objects can move from one tree to the other.
+///This is a very fast broadphase, especially for very dynamic worlds where many objects are moving. Its insert/add and remove of objects is generally faster than the sweep and prune broadphases btAxisSweep3 and bt32BitAxisSweep3.
+struct btDbvtBroadphase : btBroadphaseInterface
+{
+ /* Config */
+ enum {
+ DYNAMIC_SET = 0, /* Dynamic set index */
+ FIXED_SET = 1, /* Fixed set index */
+ STAGECOUNT = 2 /* Number of stages */
+ };
+ /* Fields */
+ btDbvt m_sets[2]; // Dbvt sets
+ btDbvtProxy* m_stageRoots[STAGECOUNT+1]; // Stages list
+ btOverlappingPairCache* m_paircache; // Pair cache
+ btScalar m_prediction; // Velocity prediction
+ int m_stageCurrent; // Current stage
+ int m_fupdates; // % of fixed updates per frame
+ int m_dupdates; // % of dynamic updates per frame
+ int m_cupdates; // % of cleanup updates per frame
+ int m_newpairs; // Number of pairs created
+ int m_fixedleft; // Fixed optimization left
+ unsigned m_updates_call; // Number of updates call
+ unsigned m_updates_done; // Number of updates done
+ btScalar m_updates_ratio; // m_updates_done/m_updates_call
+ int m_pid; // Parse id
+ int m_cid; // Cleanup index
+ int m_gid; // Gen id
+ bool m_releasepaircache; // Release pair cache on delete
+ bool m_deferedcollide; // Defere dynamic/static collision to collide call
+ bool m_needcleanup; // Need to run cleanup?
+ btAlignedObjectArray< btAlignedObjectArray<const btDbvtNode*> > m_rayTestStacks;
+#if DBVT_BP_PROFILE
+ btClock m_clock;
+ struct {
+ unsigned long m_total;
+ unsigned long m_ddcollide;
+ unsigned long m_fdcollide;
+ unsigned long m_cleanup;
+ unsigned long m_jobcount;
+ } m_profiling;
+#endif
+ /* Methods */
+ btDbvtBroadphase(btOverlappingPairCache* paircache=0);
+ ~btDbvtBroadphase();
+ void collide(btDispatcher* dispatcher);
+ void optimize();
+
+ /* btBroadphaseInterface Implementation */
+ btBroadphaseProxy* createProxy(const btVector3& aabbMin,const btVector3& aabbMax,int shapeType,void* userPtr, int collisionFilterGroup, int collisionFilterMask,btDispatcher* dispatcher);
+ virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
+ virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher);
+ virtual void rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin=btVector3(0,0,0), const btVector3& aabbMax = btVector3(0,0,0));
+ virtual void aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback);
+
+ virtual void getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const;
+ virtual void calculateOverlappingPairs(btDispatcher* dispatcher);
+ virtual btOverlappingPairCache* getOverlappingPairCache();
+ virtual const btOverlappingPairCache* getOverlappingPairCache() const;
+ virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const;
+ virtual void printStats();
+
+
+ ///reset broadphase internal structures, to ensure determinism/reproducability
+ virtual void resetPool(btDispatcher* dispatcher);
+
+ void performDeferredRemoval(btDispatcher* dispatcher);
+
+ void setVelocityPrediction(btScalar prediction)
+ {
+ m_prediction = prediction;
+ }
+ btScalar getVelocityPrediction() const
+ {
+ return m_prediction;
+ }
+
+ ///this setAabbForceUpdate is similar to setAabb but always forces the aabb update.
+ ///it is not part of the btBroadphaseInterface but specific to btDbvtBroadphase.
+ ///it bypasses certain optimizations that prevent aabb updates (when the aabb shrinks), see
+ ///http://code.google.com/p/bullet/issues/detail?id=223
+ void setAabbForceUpdate( btBroadphaseProxy* absproxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* /*dispatcher*/);
+
+ static void benchmark(btBroadphaseInterface*);
+
+
+};
+
+#endif
diff --git a/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btDispatcher.cpp b/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btDispatcher.cpp
new file mode 100644
index 0000000000..20768225b3
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btDispatcher.cpp
@@ -0,0 +1,22 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btDispatcher.h"
+
+btDispatcher::~btDispatcher()
+{
+
+}
+
diff --git a/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btDispatcher.h b/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btDispatcher.h
new file mode 100644
index 0000000000..7b0f9489af
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btDispatcher.h
@@ -0,0 +1,113 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_DISPATCHER_H
+#define BT_DISPATCHER_H
+#include "LinearMath/btScalar.h"
+
+class btCollisionAlgorithm;
+struct btBroadphaseProxy;
+class btRigidBody;
+class btCollisionObject;
+class btOverlappingPairCache;
+struct btCollisionObjectWrapper;
+
+class btPersistentManifold;
+class btPoolAllocator;
+
+struct btDispatcherInfo
+{
+ enum DispatchFunc
+ {
+ DISPATCH_DISCRETE = 1,
+ DISPATCH_CONTINUOUS
+ };
+ btDispatcherInfo()
+ :m_timeStep(btScalar(0.)),
+ m_stepCount(0),
+ m_dispatchFunc(DISPATCH_DISCRETE),
+ m_timeOfImpact(btScalar(1.)),
+ m_useContinuous(true),
+ m_debugDraw(0),
+ m_enableSatConvex(false),
+ m_enableSPU(true),
+ m_useEpa(true),
+ m_allowedCcdPenetration(btScalar(0.04)),
+ m_useConvexConservativeDistanceUtil(false),
+ m_convexConservativeDistanceThreshold(0.0f)
+ {
+
+ }
+ btScalar m_timeStep;
+ int m_stepCount;
+ int m_dispatchFunc;
+ mutable btScalar m_timeOfImpact;
+ bool m_useContinuous;
+ class btIDebugDraw* m_debugDraw;
+ bool m_enableSatConvex;
+ bool m_enableSPU;
+ bool m_useEpa;
+ btScalar m_allowedCcdPenetration;
+ bool m_useConvexConservativeDistanceUtil;
+ btScalar m_convexConservativeDistanceThreshold;
+};
+
+enum ebtDispatcherQueryType
+{
+ BT_CONTACT_POINT_ALGORITHMS = 1,
+ BT_CLOSEST_POINT_ALGORITHMS = 2
+};
+
+///The btDispatcher interface class can be used in combination with broadphase to dispatch calculations for overlapping pairs.
+///For example for pairwise collision detection, calculating contact points stored in btPersistentManifold or user callbacks (game logic).
+class btDispatcher
+{
+
+
+public:
+ virtual ~btDispatcher() ;
+
+ virtual btCollisionAlgorithm* findAlgorithm(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,btPersistentManifold* sharedManifold, ebtDispatcherQueryType queryType) = 0;
+
+ virtual btPersistentManifold* getNewManifold(const btCollisionObject* b0,const btCollisionObject* b1)=0;
+
+ virtual void releaseManifold(btPersistentManifold* manifold)=0;
+
+ virtual void clearManifold(btPersistentManifold* manifold)=0;
+
+ virtual bool needsCollision(const btCollisionObject* body0,const btCollisionObject* body1) = 0;
+
+ virtual bool needsResponse(const btCollisionObject* body0,const btCollisionObject* body1)=0;
+
+ virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) =0;
+
+ virtual int getNumManifolds() const = 0;
+
+ virtual btPersistentManifold* getManifoldByIndexInternal(int index) = 0;
+
+ virtual btPersistentManifold** getInternalManifoldPointer() = 0;
+
+ virtual btPoolAllocator* getInternalManifoldPool() = 0;
+
+ virtual const btPoolAllocator* getInternalManifoldPool() const = 0;
+
+ virtual void* allocateCollisionAlgorithm(int size) = 0;
+
+ virtual void freeCollisionAlgorithm(void* ptr) = 0;
+
+};
+
+
+#endif //BT_DISPATCHER_H
diff --git a/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp b/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp
new file mode 100644
index 0000000000..55ebf06f1e
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp
@@ -0,0 +1,632 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+#include "btOverlappingPairCache.h"
+
+#include "btDispatcher.h"
+#include "btCollisionAlgorithm.h"
+#include "LinearMath/btAabbUtil2.h"
+
+#include <stdio.h>
+
+int gOverlappingPairs = 0;
+
+int gRemovePairs =0;
+int gAddedPairs =0;
+int gFindPairs =0;
+
+
+
+
+btHashedOverlappingPairCache::btHashedOverlappingPairCache():
+ m_overlapFilterCallback(0),
+ m_ghostPairCallback(0)
+{
+ int initialAllocatedSize= 2;
+ m_overlappingPairArray.reserve(initialAllocatedSize);
+ growTables();
+}
+
+
+
+
+btHashedOverlappingPairCache::~btHashedOverlappingPairCache()
+{
+}
+
+
+
+void btHashedOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher)
+{
+ if (pair.m_algorithm && dispatcher)
+ {
+ {
+ pair.m_algorithm->~btCollisionAlgorithm();
+ dispatcher->freeCollisionAlgorithm(pair.m_algorithm);
+ pair.m_algorithm=0;
+ }
+ }
+}
+
+
+
+
+void btHashedOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
+{
+
+ class CleanPairCallback : public btOverlapCallback
+ {
+ btBroadphaseProxy* m_cleanProxy;
+ btOverlappingPairCache* m_pairCache;
+ btDispatcher* m_dispatcher;
+
+ public:
+ CleanPairCallback(btBroadphaseProxy* cleanProxy,btOverlappingPairCache* pairCache,btDispatcher* dispatcher)
+ :m_cleanProxy(cleanProxy),
+ m_pairCache(pairCache),
+ m_dispatcher(dispatcher)
+ {
+ }
+ virtual bool processOverlap(btBroadphasePair& pair)
+ {
+ if ((pair.m_pProxy0 == m_cleanProxy) ||
+ (pair.m_pProxy1 == m_cleanProxy))
+ {
+ m_pairCache->cleanOverlappingPair(pair,m_dispatcher);
+ }
+ return false;
+ }
+
+ };
+
+ CleanPairCallback cleanPairs(proxy,this,dispatcher);
+
+ processAllOverlappingPairs(&cleanPairs,dispatcher);
+
+}
+
+
+
+
+void btHashedOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
+{
+
+ class RemovePairCallback : public btOverlapCallback
+ {
+ btBroadphaseProxy* m_obsoleteProxy;
+
+ public:
+ RemovePairCallback(btBroadphaseProxy* obsoleteProxy)
+ :m_obsoleteProxy(obsoleteProxy)
+ {
+ }
+ virtual bool processOverlap(btBroadphasePair& pair)
+ {
+ return ((pair.m_pProxy0 == m_obsoleteProxy) ||
+ (pair.m_pProxy1 == m_obsoleteProxy));
+ }
+
+ };
+
+
+ RemovePairCallback removeCallback(proxy);
+
+ processAllOverlappingPairs(&removeCallback,dispatcher);
+}
+
+
+
+
+
+btBroadphasePair* btHashedOverlappingPairCache::findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1)
+{
+ gFindPairs++;
+ if(proxy0->m_uniqueId>proxy1->m_uniqueId)
+ btSwap(proxy0,proxy1);
+ int proxyId1 = proxy0->getUid();
+ int proxyId2 = proxy1->getUid();
+
+ /*if (proxyId1 > proxyId2)
+ btSwap(proxyId1, proxyId2);*/
+
+ int hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1), static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity()-1));
+
+ if (hash >= m_hashTable.size())
+ {
+ return NULL;
+ }
+
+ int index = m_hashTable[hash];
+ while (index != BT_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyId1, proxyId2) == false)
+ {
+ index = m_next[index];
+ }
+
+ if (index == BT_NULL_PAIR)
+ {
+ return NULL;
+ }
+
+ btAssert(index < m_overlappingPairArray.size());
+
+ return &m_overlappingPairArray[index];
+}
+
+//#include <stdio.h>
+
+void btHashedOverlappingPairCache::growTables()
+{
+
+ int newCapacity = m_overlappingPairArray.capacity();
+
+ if (m_hashTable.size() < newCapacity)
+ {
+ //grow hashtable and next table
+ int curHashtableSize = m_hashTable.size();
+
+ m_hashTable.resize(newCapacity);
+ m_next.resize(newCapacity);
+
+
+ int i;
+
+ for (i= 0; i < newCapacity; ++i)
+ {
+ m_hashTable[i] = BT_NULL_PAIR;
+ }
+ for (i = 0; i < newCapacity; ++i)
+ {
+ m_next[i] = BT_NULL_PAIR;
+ }
+
+ for(i=0;i<curHashtableSize;i++)
+ {
+
+ const btBroadphasePair& pair = m_overlappingPairArray[i];
+ int proxyId1 = pair.m_pProxy0->getUid();
+ int proxyId2 = pair.m_pProxy1->getUid();
+ /*if (proxyId1 > proxyId2)
+ btSwap(proxyId1, proxyId2);*/
+ int hashValue = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1),static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity()-1)); // New hash value with new mask
+ m_next[i] = m_hashTable[hashValue];
+ m_hashTable[hashValue] = i;
+ }
+
+
+ }
+}
+
+btBroadphasePair* btHashedOverlappingPairCache::internalAddPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1)
+{
+ if(proxy0->m_uniqueId>proxy1->m_uniqueId)
+ btSwap(proxy0,proxy1);
+ int proxyId1 = proxy0->getUid();
+ int proxyId2 = proxy1->getUid();
+
+ /*if (proxyId1 > proxyId2)
+ btSwap(proxyId1, proxyId2);*/
+
+ int hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1),static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity()-1)); // New hash value with new mask
+
+
+ btBroadphasePair* pair = internalFindPair(proxy0, proxy1, hash);
+ if (pair != NULL)
+ {
+ return pair;
+ }
+ /*for(int i=0;i<m_overlappingPairArray.size();++i)
+ {
+ if( (m_overlappingPairArray[i].m_pProxy0==proxy0)&&
+ (m_overlappingPairArray[i].m_pProxy1==proxy1))
+ {
+ printf("Adding duplicated %u<>%u\r\n",proxyId1,proxyId2);
+ internalFindPair(proxy0, proxy1, hash);
+ }
+ }*/
+ int count = m_overlappingPairArray.size();
+ int oldCapacity = m_overlappingPairArray.capacity();
+ void* mem = &m_overlappingPairArray.expandNonInitializing();
+
+ //this is where we add an actual pair, so also call the 'ghost'
+ if (m_ghostPairCallback)
+ m_ghostPairCallback->addOverlappingPair(proxy0,proxy1);
+
+ int newCapacity = m_overlappingPairArray.capacity();
+
+ if (oldCapacity < newCapacity)
+ {
+ growTables();
+ //hash with new capacity
+ hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1),static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity()-1));
+ }
+
+ pair = new (mem) btBroadphasePair(*proxy0,*proxy1);
+// pair->m_pProxy0 = proxy0;
+// pair->m_pProxy1 = proxy1;
+ pair->m_algorithm = 0;
+ pair->m_internalTmpValue = 0;
+
+
+ m_next[count] = m_hashTable[hash];
+ m_hashTable[hash] = count;
+
+ return pair;
+}
+
+
+
+void* btHashedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1,btDispatcher* dispatcher)
+{
+ gRemovePairs++;
+ if(proxy0->m_uniqueId>proxy1->m_uniqueId)
+ btSwap(proxy0,proxy1);
+ int proxyId1 = proxy0->getUid();
+ int proxyId2 = proxy1->getUid();
+
+ /*if (proxyId1 > proxyId2)
+ btSwap(proxyId1, proxyId2);*/
+
+ int hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1),static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity()-1));
+
+ btBroadphasePair* pair = internalFindPair(proxy0, proxy1, hash);
+ if (pair == NULL)
+ {
+ return 0;
+ }
+
+ cleanOverlappingPair(*pair,dispatcher);
+
+ void* userData = pair->m_internalInfo1;
+
+ btAssert(pair->m_pProxy0->getUid() == proxyId1);
+ btAssert(pair->m_pProxy1->getUid() == proxyId2);
+
+ int pairIndex = int(pair - &m_overlappingPairArray[0]);
+ btAssert(pairIndex < m_overlappingPairArray.size());
+
+ // Remove the pair from the hash table.
+ int index = m_hashTable[hash];
+ btAssert(index != BT_NULL_PAIR);
+
+ int previous = BT_NULL_PAIR;
+ while (index != pairIndex)
+ {
+ previous = index;
+ index = m_next[index];
+ }
+
+ if (previous != BT_NULL_PAIR)
+ {
+ btAssert(m_next[previous] == pairIndex);
+ m_next[previous] = m_next[pairIndex];
+ }
+ else
+ {
+ m_hashTable[hash] = m_next[pairIndex];
+ }
+
+ // We now move the last pair into spot of the
+ // pair being removed. We need to fix the hash
+ // table indices to support the move.
+
+ int lastPairIndex = m_overlappingPairArray.size() - 1;
+
+ if (m_ghostPairCallback)
+ m_ghostPairCallback->removeOverlappingPair(proxy0, proxy1,dispatcher);
+
+ // If the removed pair is the last pair, we are done.
+ if (lastPairIndex == pairIndex)
+ {
+ m_overlappingPairArray.pop_back();
+ return userData;
+ }
+
+ // Remove the last pair from the hash table.
+ const btBroadphasePair* last = &m_overlappingPairArray[lastPairIndex];
+ /* missing swap here too, Nat. */
+ int lastHash = static_cast<int>(getHash(static_cast<unsigned int>(last->m_pProxy0->getUid()), static_cast<unsigned int>(last->m_pProxy1->getUid())) & (m_overlappingPairArray.capacity()-1));
+
+ index = m_hashTable[lastHash];
+ btAssert(index != BT_NULL_PAIR);
+
+ previous = BT_NULL_PAIR;
+ while (index != lastPairIndex)
+ {
+ previous = index;
+ index = m_next[index];
+ }
+
+ if (previous != BT_NULL_PAIR)
+ {
+ btAssert(m_next[previous] == lastPairIndex);
+ m_next[previous] = m_next[lastPairIndex];
+ }
+ else
+ {
+ m_hashTable[lastHash] = m_next[lastPairIndex];
+ }
+
+ // Copy the last pair into the remove pair's spot.
+ m_overlappingPairArray[pairIndex] = m_overlappingPairArray[lastPairIndex];
+
+ // Insert the last pair into the hash table
+ m_next[pairIndex] = m_hashTable[lastHash];
+ m_hashTable[lastHash] = pairIndex;
+
+ m_overlappingPairArray.pop_back();
+
+ return userData;
+}
+//#include <stdio.h>
+#include "LinearMath/btQuickprof.h"
+void btHashedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback,btDispatcher* dispatcher)
+{
+ BT_PROFILE("btHashedOverlappingPairCache::processAllOverlappingPairs");
+ int i;
+
+// printf("m_overlappingPairArray.size()=%d\n",m_overlappingPairArray.size());
+ for (i=0;i<m_overlappingPairArray.size();)
+ {
+
+ btBroadphasePair* pair = &m_overlappingPairArray[i];
+ if (callback->processOverlap(*pair))
+ {
+ removeOverlappingPair(pair->m_pProxy0,pair->m_pProxy1,dispatcher);
+
+ gOverlappingPairs--;
+ } else
+ {
+ i++;
+ }
+ }
+}
+
+void btHashedOverlappingPairCache::sortOverlappingPairs(btDispatcher* dispatcher)
+{
+ ///need to keep hashmap in sync with pair address, so rebuild all
+ btBroadphasePairArray tmpPairs;
+ int i;
+ for (i=0;i<m_overlappingPairArray.size();i++)
+ {
+ tmpPairs.push_back(m_overlappingPairArray[i]);
+ }
+
+ for (i=0;i<tmpPairs.size();i++)
+ {
+ removeOverlappingPair(tmpPairs[i].m_pProxy0,tmpPairs[i].m_pProxy1,dispatcher);
+ }
+
+ for (i = 0; i < m_next.size(); i++)
+ {
+ m_next[i] = BT_NULL_PAIR;
+ }
+
+ tmpPairs.quickSort(btBroadphasePairSortPredicate());
+
+ for (i=0;i<tmpPairs.size();i++)
+ {
+ addOverlappingPair(tmpPairs[i].m_pProxy0,tmpPairs[i].m_pProxy1);
+ }
+
+
+}
+
+
+void* btSortedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1, btDispatcher* dispatcher )
+{
+ if (!hasDeferredRemoval())
+ {
+ btBroadphasePair findPair(*proxy0,*proxy1);
+
+ int findIndex = m_overlappingPairArray.findLinearSearch(findPair);
+ if (findIndex < m_overlappingPairArray.size())
+ {
+ gOverlappingPairs--;
+ btBroadphasePair& pair = m_overlappingPairArray[findIndex];
+ void* userData = pair.m_internalInfo1;
+ cleanOverlappingPair(pair,dispatcher);
+ if (m_ghostPairCallback)
+ m_ghostPairCallback->removeOverlappingPair(proxy0, proxy1,dispatcher);
+
+ m_overlappingPairArray.swap(findIndex,m_overlappingPairArray.capacity()-1);
+ m_overlappingPairArray.pop_back();
+ return userData;
+ }
+ }
+
+ return 0;
+}
+
+
+
+
+
+
+
+
+btBroadphasePair* btSortedOverlappingPairCache::addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
+{
+ //don't add overlap with own
+ btAssert(proxy0 != proxy1);
+
+ if (!needsBroadphaseCollision(proxy0,proxy1))
+ return 0;
+
+ void* mem = &m_overlappingPairArray.expandNonInitializing();
+ btBroadphasePair* pair = new (mem) btBroadphasePair(*proxy0,*proxy1);
+
+ gOverlappingPairs++;
+ gAddedPairs++;
+
+ if (m_ghostPairCallback)
+ m_ghostPairCallback->addOverlappingPair(proxy0, proxy1);
+ return pair;
+
+}
+
+///this findPair becomes really slow. Either sort the list to speedup the query, or
+///use a different solution. It is mainly used for Removing overlapping pairs. Removal could be delayed.
+///we could keep a linked list in each proxy, and store pair in one of the proxies (with lowest memory address)
+///Also we can use a 2D bitmap, which can be useful for a future GPU implementation
+ btBroadphasePair* btSortedOverlappingPairCache::findPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
+{
+ if (!needsBroadphaseCollision(proxy0,proxy1))
+ return 0;
+
+ btBroadphasePair tmpPair(*proxy0,*proxy1);
+ int findIndex = m_overlappingPairArray.findLinearSearch(tmpPair);
+
+ if (findIndex < m_overlappingPairArray.size())
+ {
+ //btAssert(it != m_overlappingPairSet.end());
+ btBroadphasePair* pair = &m_overlappingPairArray[findIndex];
+ return pair;
+ }
+ return 0;
+}
+
+
+
+
+
+
+
+
+
+
+//#include <stdio.h>
+
+void btSortedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback,btDispatcher* dispatcher)
+{
+
+ int i;
+
+ for (i=0;i<m_overlappingPairArray.size();)
+ {
+
+ btBroadphasePair* pair = &m_overlappingPairArray[i];
+ if (callback->processOverlap(*pair))
+ {
+ cleanOverlappingPair(*pair,dispatcher);
+ pair->m_pProxy0 = 0;
+ pair->m_pProxy1 = 0;
+ m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1);
+ m_overlappingPairArray.pop_back();
+ gOverlappingPairs--;
+ } else
+ {
+ i++;
+ }
+ }
+}
+
+
+
+
+btSortedOverlappingPairCache::btSortedOverlappingPairCache():
+ m_blockedForChanges(false),
+ m_hasDeferredRemoval(true),
+ m_overlapFilterCallback(0),
+ m_ghostPairCallback(0)
+{
+ int initialAllocatedSize= 2;
+ m_overlappingPairArray.reserve(initialAllocatedSize);
+}
+
+btSortedOverlappingPairCache::~btSortedOverlappingPairCache()
+{
+}
+
+void btSortedOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher)
+{
+ if (pair.m_algorithm)
+ {
+ {
+ pair.m_algorithm->~btCollisionAlgorithm();
+ dispatcher->freeCollisionAlgorithm(pair.m_algorithm);
+ pair.m_algorithm=0;
+ gRemovePairs--;
+ }
+ }
+}
+
+
+void btSortedOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
+{
+
+ class CleanPairCallback : public btOverlapCallback
+ {
+ btBroadphaseProxy* m_cleanProxy;
+ btOverlappingPairCache* m_pairCache;
+ btDispatcher* m_dispatcher;
+
+ public:
+ CleanPairCallback(btBroadphaseProxy* cleanProxy,btOverlappingPairCache* pairCache,btDispatcher* dispatcher)
+ :m_cleanProxy(cleanProxy),
+ m_pairCache(pairCache),
+ m_dispatcher(dispatcher)
+ {
+ }
+ virtual bool processOverlap(btBroadphasePair& pair)
+ {
+ if ((pair.m_pProxy0 == m_cleanProxy) ||
+ (pair.m_pProxy1 == m_cleanProxy))
+ {
+ m_pairCache->cleanOverlappingPair(pair,m_dispatcher);
+ }
+ return false;
+ }
+
+ };
+
+ CleanPairCallback cleanPairs(proxy,this,dispatcher);
+
+ processAllOverlappingPairs(&cleanPairs,dispatcher);
+
+}
+
+
+void btSortedOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
+{
+
+ class RemovePairCallback : public btOverlapCallback
+ {
+ btBroadphaseProxy* m_obsoleteProxy;
+
+ public:
+ RemovePairCallback(btBroadphaseProxy* obsoleteProxy)
+ :m_obsoleteProxy(obsoleteProxy)
+ {
+ }
+ virtual bool processOverlap(btBroadphasePair& pair)
+ {
+ return ((pair.m_pProxy0 == m_obsoleteProxy) ||
+ (pair.m_pProxy1 == m_obsoleteProxy));
+ }
+
+ };
+
+ RemovePairCallback removeCallback(proxy);
+
+ processAllOverlappingPairs(&removeCallback,dispatcher);
+}
+
+void btSortedOverlappingPairCache::sortOverlappingPairs(btDispatcher* dispatcher)
+{
+ //should already be sorted
+}
+
diff --git a/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h b/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h
new file mode 100644
index 0000000000..f7be7d45b3
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h
@@ -0,0 +1,469 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_OVERLAPPING_PAIR_CACHE_H
+#define BT_OVERLAPPING_PAIR_CACHE_H
+
+
+#include "btBroadphaseInterface.h"
+#include "btBroadphaseProxy.h"
+#include "btOverlappingPairCallback.h"
+
+#include "LinearMath/btAlignedObjectArray.h"
+class btDispatcher;
+
+typedef btAlignedObjectArray<btBroadphasePair> btBroadphasePairArray;
+
+struct btOverlapCallback
+{
+ virtual ~btOverlapCallback()
+ {}
+ //return true for deletion of the pair
+ virtual bool processOverlap(btBroadphasePair& pair) = 0;
+
+};
+
+struct btOverlapFilterCallback
+{
+ virtual ~btOverlapFilterCallback()
+ {}
+ // return true when pairs need collision
+ virtual bool needBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const = 0;
+};
+
+
+
+
+
+
+
+extern int gRemovePairs;
+extern int gAddedPairs;
+extern int gFindPairs;
+
+const int BT_NULL_PAIR=0xffffffff;
+
+///The btOverlappingPairCache provides an interface for overlapping pair management (add, remove, storage), used by the btBroadphaseInterface broadphases.
+///The btHashedOverlappingPairCache and btSortedOverlappingPairCache classes are two implementations.
+class btOverlappingPairCache : public btOverlappingPairCallback
+{
+public:
+ virtual ~btOverlappingPairCache() {} // this is needed so we can get to the derived class destructor
+
+ virtual btBroadphasePair* getOverlappingPairArrayPtr() = 0;
+
+ virtual const btBroadphasePair* getOverlappingPairArrayPtr() const = 0;
+
+ virtual btBroadphasePairArray& getOverlappingPairArray() = 0;
+
+ virtual void cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher) = 0;
+
+ virtual int getNumOverlappingPairs() const = 0;
+
+ virtual void cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher) = 0;
+
+ virtual void setOverlapFilterCallback(btOverlapFilterCallback* callback) = 0;
+
+ virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher) = 0;
+
+ virtual btBroadphasePair* findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) = 0;
+
+ virtual bool hasDeferredRemoval() = 0;
+
+ virtual void setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback)=0;
+
+ virtual void sortOverlappingPairs(btDispatcher* dispatcher) = 0;
+
+
+};
+
+/// Hash-space based Pair Cache, thanks to Erin Catto, Box2D, http://www.box2d.org, and Pierre Terdiman, Codercorner, http://codercorner.com
+
+ATTRIBUTE_ALIGNED16(class) btHashedOverlappingPairCache : public btOverlappingPairCache
+{
+ btBroadphasePairArray m_overlappingPairArray;
+ btOverlapFilterCallback* m_overlapFilterCallback;
+
+protected:
+
+ btAlignedObjectArray<int> m_hashTable;
+ btAlignedObjectArray<int> m_next;
+ btOverlappingPairCallback* m_ghostPairCallback;
+
+
+public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ btHashedOverlappingPairCache();
+ virtual ~btHashedOverlappingPairCache();
+
+
+ void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
+
+ virtual void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher);
+
+ SIMD_FORCE_INLINE bool needsBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const
+ {
+ if (m_overlapFilterCallback)
+ return m_overlapFilterCallback->needBroadphaseCollision(proxy0,proxy1);
+
+ bool collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0;
+ collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask);
+
+ return collides;
+ }
+
+ // Add a pair and return the new pair. If the pair already exists,
+ // no new pair is created and the old one is returned.
+ virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
+ {
+ gAddedPairs++;
+
+ if (!needsBroadphaseCollision(proxy0,proxy1))
+ return 0;
+
+ return internalAddPair(proxy0,proxy1);
+ }
+
+
+
+ void cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
+
+
+ virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher);
+
+ virtual btBroadphasePair* getOverlappingPairArrayPtr()
+ {
+ return &m_overlappingPairArray[0];
+ }
+
+ const btBroadphasePair* getOverlappingPairArrayPtr() const
+ {
+ return &m_overlappingPairArray[0];
+ }
+
+ btBroadphasePairArray& getOverlappingPairArray()
+ {
+ return m_overlappingPairArray;
+ }
+
+ const btBroadphasePairArray& getOverlappingPairArray() const
+ {
+ return m_overlappingPairArray;
+ }
+
+ void cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher);
+
+
+
+ btBroadphasePair* findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1);
+
+ int GetCount() const { return m_overlappingPairArray.size(); }
+// btBroadphasePair* GetPairs() { return m_pairs; }
+
+ btOverlapFilterCallback* getOverlapFilterCallback()
+ {
+ return m_overlapFilterCallback;
+ }
+
+ void setOverlapFilterCallback(btOverlapFilterCallback* callback)
+ {
+ m_overlapFilterCallback = callback;
+ }
+
+ int getNumOverlappingPairs() const
+ {
+ return m_overlappingPairArray.size();
+ }
+private:
+
+ btBroadphasePair* internalAddPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
+
+ void growTables();
+
+ SIMD_FORCE_INLINE bool equalsPair(const btBroadphasePair& pair, int proxyId1, int proxyId2)
+ {
+ return pair.m_pProxy0->getUid() == proxyId1 && pair.m_pProxy1->getUid() == proxyId2;
+ }
+
+ /*
+ // Thomas Wang's hash, see: http://www.concentric.net/~Ttwang/tech/inthash.htm
+ // This assumes proxyId1 and proxyId2 are 16-bit.
+ SIMD_FORCE_INLINE int getHash(int proxyId1, int proxyId2)
+ {
+ int key = (proxyId2 << 16) | proxyId1;
+ key = ~key + (key << 15);
+ key = key ^ (key >> 12);
+ key = key + (key << 2);
+ key = key ^ (key >> 4);
+ key = key * 2057;
+ key = key ^ (key >> 16);
+ return key;
+ }
+ */
+
+
+ SIMD_FORCE_INLINE unsigned int getHash(unsigned int proxyId1, unsigned int proxyId2)
+ {
+ unsigned int key = proxyId1 | (proxyId2 << 16);
+ // Thomas Wang's hash
+
+ key += ~(key << 15);
+ key ^= (key >> 10);
+ key += (key << 3);
+ key ^= (key >> 6);
+ key += ~(key << 11);
+ key ^= (key >> 16);
+ return key;
+ }
+
+
+
+ SIMD_FORCE_INLINE btBroadphasePair* internalFindPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1, int hash)
+ {
+ int proxyId1 = proxy0->getUid();
+ int proxyId2 = proxy1->getUid();
+ #if 0 // wrong, 'equalsPair' use unsorted uids, copy-past devil striked again. Nat.
+ if (proxyId1 > proxyId2)
+ btSwap(proxyId1, proxyId2);
+ #endif
+
+ int index = m_hashTable[hash];
+
+ while( index != BT_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyId1, proxyId2) == false)
+ {
+ index = m_next[index];
+ }
+
+ if ( index == BT_NULL_PAIR )
+ {
+ return NULL;
+ }
+
+ btAssert(index < m_overlappingPairArray.size());
+
+ return &m_overlappingPairArray[index];
+ }
+
+ virtual bool hasDeferredRemoval()
+ {
+ return false;
+ }
+
+ virtual void setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback)
+ {
+ m_ghostPairCallback = ghostPairCallback;
+ }
+
+ virtual void sortOverlappingPairs(btDispatcher* dispatcher);
+
+
+
+};
+
+
+
+
+///btSortedOverlappingPairCache maintains the objects with overlapping AABB
+///Typically managed by the Broadphase, Axis3Sweep or btSimpleBroadphase
+class btSortedOverlappingPairCache : public btOverlappingPairCache
+{
+ protected:
+ //avoid brute-force finding all the time
+ btBroadphasePairArray m_overlappingPairArray;
+
+ //during the dispatch, check that user doesn't destroy/create proxy
+ bool m_blockedForChanges;
+
+ ///by default, do the removal during the pair traversal
+ bool m_hasDeferredRemoval;
+
+ //if set, use the callback instead of the built in filter in needBroadphaseCollision
+ btOverlapFilterCallback* m_overlapFilterCallback;
+
+ btOverlappingPairCallback* m_ghostPairCallback;
+
+ public:
+
+ btSortedOverlappingPairCache();
+ virtual ~btSortedOverlappingPairCache();
+
+ virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher);
+
+ void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher);
+
+ void cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher);
+
+ btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
+
+ btBroadphasePair* findPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
+
+
+ void cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
+
+ void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
+
+
+ inline bool needsBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const
+ {
+ if (m_overlapFilterCallback)
+ return m_overlapFilterCallback->needBroadphaseCollision(proxy0,proxy1);
+
+ bool collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0;
+ collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask);
+
+ return collides;
+ }
+
+ btBroadphasePairArray& getOverlappingPairArray()
+ {
+ return m_overlappingPairArray;
+ }
+
+ const btBroadphasePairArray& getOverlappingPairArray() const
+ {
+ return m_overlappingPairArray;
+ }
+
+
+
+
+ btBroadphasePair* getOverlappingPairArrayPtr()
+ {
+ return &m_overlappingPairArray[0];
+ }
+
+ const btBroadphasePair* getOverlappingPairArrayPtr() const
+ {
+ return &m_overlappingPairArray[0];
+ }
+
+ int getNumOverlappingPairs() const
+ {
+ return m_overlappingPairArray.size();
+ }
+
+ btOverlapFilterCallback* getOverlapFilterCallback()
+ {
+ return m_overlapFilterCallback;
+ }
+
+ void setOverlapFilterCallback(btOverlapFilterCallback* callback)
+ {
+ m_overlapFilterCallback = callback;
+ }
+
+ virtual bool hasDeferredRemoval()
+ {
+ return m_hasDeferredRemoval;
+ }
+
+ virtual void setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback)
+ {
+ m_ghostPairCallback = ghostPairCallback;
+ }
+
+ virtual void sortOverlappingPairs(btDispatcher* dispatcher);
+
+
+};
+
+
+
+///btNullPairCache skips add/removal of overlapping pairs. Userful for benchmarking and unit testing.
+class btNullPairCache : public btOverlappingPairCache
+{
+
+ btBroadphasePairArray m_overlappingPairArray;
+
+public:
+
+ virtual btBroadphasePair* getOverlappingPairArrayPtr()
+ {
+ return &m_overlappingPairArray[0];
+ }
+ const btBroadphasePair* getOverlappingPairArrayPtr() const
+ {
+ return &m_overlappingPairArray[0];
+ }
+ btBroadphasePairArray& getOverlappingPairArray()
+ {
+ return m_overlappingPairArray;
+ }
+
+ virtual void cleanOverlappingPair(btBroadphasePair& /*pair*/,btDispatcher* /*dispatcher*/)
+ {
+
+ }
+
+ virtual int getNumOverlappingPairs() const
+ {
+ return 0;
+ }
+
+ virtual void cleanProxyFromPairs(btBroadphaseProxy* /*proxy*/,btDispatcher* /*dispatcher*/)
+ {
+
+ }
+
+ virtual void setOverlapFilterCallback(btOverlapFilterCallback* /*callback*/)
+ {
+ }
+
+ virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* /*dispatcher*/)
+ {
+ }
+
+ virtual btBroadphasePair* findPair(btBroadphaseProxy* /*proxy0*/, btBroadphaseProxy* /*proxy1*/)
+ {
+ return 0;
+ }
+
+ virtual bool hasDeferredRemoval()
+ {
+ return true;
+ }
+
+ virtual void setInternalGhostPairCallback(btOverlappingPairCallback* /* ghostPairCallback */)
+ {
+
+ }
+
+ virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* /*proxy0*/,btBroadphaseProxy* /*proxy1*/)
+ {
+ return 0;
+ }
+
+ virtual void* removeOverlappingPair(btBroadphaseProxy* /*proxy0*/,btBroadphaseProxy* /*proxy1*/,btDispatcher* /*dispatcher*/)
+ {
+ return 0;
+ }
+
+ virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* /*proxy0*/,btDispatcher* /*dispatcher*/)
+ {
+ }
+
+ virtual void sortOverlappingPairs(btDispatcher* dispatcher)
+ {
+ (void) dispatcher;
+ }
+
+
+};
+
+
+#endif //BT_OVERLAPPING_PAIR_CACHE_H
+
+
diff --git a/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h b/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h
new file mode 100644
index 0000000000..3e069fa5e2
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h
@@ -0,0 +1,43 @@
+
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef OVERLAPPING_PAIR_CALLBACK_H
+#define OVERLAPPING_PAIR_CALLBACK_H
+
+class btDispatcher;
+struct btBroadphasePair;
+
+///The btOverlappingPairCallback class is an additional optional broadphase user callback for adding/removing overlapping pairs, similar interface to btOverlappingPairCache.
+class btOverlappingPairCallback
+{
+protected:
+ btOverlappingPairCallback() {}
+
+public:
+ virtual ~btOverlappingPairCallback()
+ {
+
+ }
+
+ virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) = 0;
+
+ virtual void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher) = 0;
+
+ virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy0,btDispatcher* dispatcher) = 0;
+
+};
+
+#endif //OVERLAPPING_PAIR_CALLBACK_H
diff --git a/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp b/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp
new file mode 100644
index 0000000000..875d89c53e
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp
@@ -0,0 +1,1397 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btQuantizedBvh.h"
+
+#include "LinearMath/btAabbUtil2.h"
+#include "LinearMath/btIDebugDraw.h"
+#include "LinearMath/btSerializer.h"
+
+#define RAYAABB2
+
+btQuantizedBvh::btQuantizedBvh() :
+ m_bulletVersion(BT_BULLET_VERSION),
+ m_useQuantization(false),
+ //m_traversalMode(TRAVERSAL_STACKLESS_CACHE_FRIENDLY)
+ m_traversalMode(TRAVERSAL_STACKLESS)
+ //m_traversalMode(TRAVERSAL_RECURSIVE)
+ ,m_subtreeHeaderCount(0) //PCK: add this line
+{
+ m_bvhAabbMin.setValue(-SIMD_INFINITY,-SIMD_INFINITY,-SIMD_INFINITY);
+ m_bvhAabbMax.setValue(SIMD_INFINITY,SIMD_INFINITY,SIMD_INFINITY);
+}
+
+
+
+
+
+void btQuantizedBvh::buildInternal()
+{
+ ///assumes that caller filled in the m_quantizedLeafNodes
+ m_useQuantization = true;
+ int numLeafNodes = 0;
+
+ if (m_useQuantization)
+ {
+ //now we have an array of leafnodes in m_leafNodes
+ numLeafNodes = m_quantizedLeafNodes.size();
+
+ m_quantizedContiguousNodes.resize(2*numLeafNodes);
+
+ }
+
+ m_curNodeIndex = 0;
+
+ buildTree(0,numLeafNodes);
+
+ ///if the entire tree is small then subtree size, we need to create a header info for the tree
+ if(m_useQuantization && !m_SubtreeHeaders.size())
+ {
+ btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand();
+ subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[0]);
+ subtree.m_rootNodeIndex = 0;
+ subtree.m_subtreeSize = m_quantizedContiguousNodes[0].isLeafNode() ? 1 : m_quantizedContiguousNodes[0].getEscapeIndex();
+ }
+
+ //PCK: update the copy of the size
+ m_subtreeHeaderCount = m_SubtreeHeaders.size();
+
+ //PCK: clear m_quantizedLeafNodes and m_leafNodes, they are temporary
+ m_quantizedLeafNodes.clear();
+ m_leafNodes.clear();
+}
+
+
+
+///just for debugging, to visualize the individual patches/subtrees
+#ifdef DEBUG_PATCH_COLORS
+btVector3 color[4]=
+{
+ btVector3(1,0,0),
+ btVector3(0,1,0),
+ btVector3(0,0,1),
+ btVector3(0,1,1)
+};
+#endif //DEBUG_PATCH_COLORS
+
+
+
+void btQuantizedBvh::setQuantizationValues(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,btScalar quantizationMargin)
+{
+ //enlarge the AABB to avoid division by zero when initializing the quantization values
+ btVector3 clampValue(quantizationMargin,quantizationMargin,quantizationMargin);
+ m_bvhAabbMin = bvhAabbMin - clampValue;
+ m_bvhAabbMax = bvhAabbMax + clampValue;
+ btVector3 aabbSize = m_bvhAabbMax - m_bvhAabbMin;
+ m_bvhQuantization = btVector3(btScalar(65533.0),btScalar(65533.0),btScalar(65533.0)) / aabbSize;
+
+ m_useQuantization = true;
+
+ {
+ unsigned short vecIn[3];
+ btVector3 v;
+ {
+ quantize(vecIn,m_bvhAabbMin,false);
+ v = unQuantize(vecIn);
+ m_bvhAabbMin.setMin(v-clampValue);
+ }
+ aabbSize = m_bvhAabbMax - m_bvhAabbMin;
+ m_bvhQuantization = btVector3(btScalar(65533.0),btScalar(65533.0),btScalar(65533.0)) / aabbSize;
+ {
+ quantize(vecIn,m_bvhAabbMax,true);
+ v = unQuantize(vecIn);
+ m_bvhAabbMax.setMax(v+clampValue);
+ }
+ aabbSize = m_bvhAabbMax - m_bvhAabbMin;
+ m_bvhQuantization = btVector3(btScalar(65533.0),btScalar(65533.0),btScalar(65533.0)) / aabbSize;
+ }
+}
+
+
+
+
+btQuantizedBvh::~btQuantizedBvh()
+{
+}
+
+#ifdef DEBUG_TREE_BUILDING
+int gStackDepth = 0;
+int gMaxStackDepth = 0;
+#endif //DEBUG_TREE_BUILDING
+
+void btQuantizedBvh::buildTree (int startIndex,int endIndex)
+{
+#ifdef DEBUG_TREE_BUILDING
+ gStackDepth++;
+ if (gStackDepth > gMaxStackDepth)
+ gMaxStackDepth = gStackDepth;
+#endif //DEBUG_TREE_BUILDING
+
+
+ int splitAxis, splitIndex, i;
+ int numIndices =endIndex-startIndex;
+ int curIndex = m_curNodeIndex;
+
+ btAssert(numIndices>0);
+
+ if (numIndices==1)
+ {
+#ifdef DEBUG_TREE_BUILDING
+ gStackDepth--;
+#endif //DEBUG_TREE_BUILDING
+
+ assignInternalNodeFromLeafNode(m_curNodeIndex,startIndex);
+
+ m_curNodeIndex++;
+ return;
+ }
+ //calculate Best Splitting Axis and where to split it. Sort the incoming 'leafNodes' array within range 'startIndex/endIndex'.
+
+ splitAxis = calcSplittingAxis(startIndex,endIndex);
+
+ splitIndex = sortAndCalcSplittingIndex(startIndex,endIndex,splitAxis);
+
+ int internalNodeIndex = m_curNodeIndex;
+
+ //set the min aabb to 'inf' or a max value, and set the max aabb to a -inf/minimum value.
+ //the aabb will be expanded during buildTree/mergeInternalNodeAabb with actual node values
+ setInternalNodeAabbMin(m_curNodeIndex,m_bvhAabbMax);//can't use btVector3(SIMD_INFINITY,SIMD_INFINITY,SIMD_INFINITY)) because of quantization
+ setInternalNodeAabbMax(m_curNodeIndex,m_bvhAabbMin);//can't use btVector3(-SIMD_INFINITY,-SIMD_INFINITY,-SIMD_INFINITY)) because of quantization
+
+
+ for (i=startIndex;i<endIndex;i++)
+ {
+ mergeInternalNodeAabb(m_curNodeIndex,getAabbMin(i),getAabbMax(i));
+ }
+
+ m_curNodeIndex++;
+
+
+ //internalNode->m_escapeIndex;
+
+ int leftChildNodexIndex = m_curNodeIndex;
+
+ //build left child tree
+ buildTree(startIndex,splitIndex);
+
+ int rightChildNodexIndex = m_curNodeIndex;
+ //build right child tree
+ buildTree(splitIndex,endIndex);
+
+#ifdef DEBUG_TREE_BUILDING
+ gStackDepth--;
+#endif //DEBUG_TREE_BUILDING
+
+ int escapeIndex = m_curNodeIndex - curIndex;
+
+ if (m_useQuantization)
+ {
+ //escapeIndex is the number of nodes of this subtree
+ const int sizeQuantizedNode =sizeof(btQuantizedBvhNode);
+ const int treeSizeInBytes = escapeIndex * sizeQuantizedNode;
+ if (treeSizeInBytes > MAX_SUBTREE_SIZE_IN_BYTES)
+ {
+ updateSubtreeHeaders(leftChildNodexIndex,rightChildNodexIndex);
+ }
+ } else
+ {
+
+ }
+
+ setInternalNodeEscapeIndex(internalNodeIndex,escapeIndex);
+
+}
+
+void btQuantizedBvh::updateSubtreeHeaders(int leftChildNodexIndex,int rightChildNodexIndex)
+{
+ btAssert(m_useQuantization);
+
+ btQuantizedBvhNode& leftChildNode = m_quantizedContiguousNodes[leftChildNodexIndex];
+ int leftSubTreeSize = leftChildNode.isLeafNode() ? 1 : leftChildNode.getEscapeIndex();
+ int leftSubTreeSizeInBytes = leftSubTreeSize * static_cast<int>(sizeof(btQuantizedBvhNode));
+
+ btQuantizedBvhNode& rightChildNode = m_quantizedContiguousNodes[rightChildNodexIndex];
+ int rightSubTreeSize = rightChildNode.isLeafNode() ? 1 : rightChildNode.getEscapeIndex();
+ int rightSubTreeSizeInBytes = rightSubTreeSize * static_cast<int>(sizeof(btQuantizedBvhNode));
+
+ if(leftSubTreeSizeInBytes <= MAX_SUBTREE_SIZE_IN_BYTES)
+ {
+ btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand();
+ subtree.setAabbFromQuantizeNode(leftChildNode);
+ subtree.m_rootNodeIndex = leftChildNodexIndex;
+ subtree.m_subtreeSize = leftSubTreeSize;
+ }
+
+ if(rightSubTreeSizeInBytes <= MAX_SUBTREE_SIZE_IN_BYTES)
+ {
+ btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand();
+ subtree.setAabbFromQuantizeNode(rightChildNode);
+ subtree.m_rootNodeIndex = rightChildNodexIndex;
+ subtree.m_subtreeSize = rightSubTreeSize;
+ }
+
+ //PCK: update the copy of the size
+ m_subtreeHeaderCount = m_SubtreeHeaders.size();
+}
+
+
+int btQuantizedBvh::sortAndCalcSplittingIndex(int startIndex,int endIndex,int splitAxis)
+{
+ int i;
+ int splitIndex =startIndex;
+ int numIndices = endIndex - startIndex;
+ btScalar splitValue;
+
+ btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.));
+ for (i=startIndex;i<endIndex;i++)
+ {
+ btVector3 center = btScalar(0.5)*(getAabbMax(i)+getAabbMin(i));
+ means+=center;
+ }
+ means *= (btScalar(1.)/(btScalar)numIndices);
+
+ splitValue = means[splitAxis];
+
+ //sort leafNodes so all values larger then splitValue comes first, and smaller values start from 'splitIndex'.
+ for (i=startIndex;i<endIndex;i++)
+ {
+ btVector3 center = btScalar(0.5)*(getAabbMax(i)+getAabbMin(i));
+ if (center[splitAxis] > splitValue)
+ {
+ //swap
+ swapLeafNodes(i,splitIndex);
+ splitIndex++;
+ }
+ }
+
+ //if the splitIndex causes unbalanced trees, fix this by using the center in between startIndex and endIndex
+ //otherwise the tree-building might fail due to stack-overflows in certain cases.
+ //unbalanced1 is unsafe: it can cause stack overflows
+ //bool unbalanced1 = ((splitIndex==startIndex) || (splitIndex == (endIndex-1)));
+
+ //unbalanced2 should work too: always use center (perfect balanced trees)
+ //bool unbalanced2 = true;
+
+ //this should be safe too:
+ int rangeBalancedIndices = numIndices/3;
+ bool unbalanced = ((splitIndex<=(startIndex+rangeBalancedIndices)) || (splitIndex >=(endIndex-1-rangeBalancedIndices)));
+
+ if (unbalanced)
+ {
+ splitIndex = startIndex+ (numIndices>>1);
+ }
+
+ bool unbal = (splitIndex==startIndex) || (splitIndex == (endIndex));
+ (void)unbal;
+ btAssert(!unbal);
+
+ return splitIndex;
+}
+
+
+int btQuantizedBvh::calcSplittingAxis(int startIndex,int endIndex)
+{
+ int i;
+
+ btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.));
+ btVector3 variance(btScalar(0.),btScalar(0.),btScalar(0.));
+ int numIndices = endIndex-startIndex;
+
+ for (i=startIndex;i<endIndex;i++)
+ {
+ btVector3 center = btScalar(0.5)*(getAabbMax(i)+getAabbMin(i));
+ means+=center;
+ }
+ means *= (btScalar(1.)/(btScalar)numIndices);
+
+ for (i=startIndex;i<endIndex;i++)
+ {
+ btVector3 center = btScalar(0.5)*(getAabbMax(i)+getAabbMin(i));
+ btVector3 diff2 = center-means;
+ diff2 = diff2 * diff2;
+ variance += diff2;
+ }
+ variance *= (btScalar(1.)/ ((btScalar)numIndices-1) );
+
+ return variance.maxAxis();
+}
+
+
+
+void btQuantizedBvh::reportAabbOverlappingNodex(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const
+{
+ //either choose recursive traversal (walkTree) or stackless (walkStacklessTree)
+
+ if (m_useQuantization)
+ {
+ ///quantize query AABB
+ unsigned short int quantizedQueryAabbMin[3];
+ unsigned short int quantizedQueryAabbMax[3];
+ quantizeWithClamp(quantizedQueryAabbMin,aabbMin,0);
+ quantizeWithClamp(quantizedQueryAabbMax,aabbMax,1);
+
+ switch (m_traversalMode)
+ {
+ case TRAVERSAL_STACKLESS:
+ walkStacklessQuantizedTree(nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax,0,m_curNodeIndex);
+ break;
+ case TRAVERSAL_STACKLESS_CACHE_FRIENDLY:
+ walkStacklessQuantizedTreeCacheFriendly(nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax);
+ break;
+ case TRAVERSAL_RECURSIVE:
+ {
+ const btQuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[0];
+ walkRecursiveQuantizedTreeAgainstQueryAabb(rootNode,nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax);
+ }
+ break;
+ default:
+ //unsupported
+ btAssert(0);
+ }
+ } else
+ {
+ walkStacklessTree(nodeCallback,aabbMin,aabbMax);
+ }
+}
+
+
+int maxIterations = 0;
+
+
+void btQuantizedBvh::walkStacklessTree(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const
+{
+ btAssert(!m_useQuantization);
+
+ const btOptimizedBvhNode* rootNode = &m_contiguousNodes[0];
+ int escapeIndex, curIndex = 0;
+ int walkIterations = 0;
+ bool isLeafNode;
+ //PCK: unsigned instead of bool
+ unsigned aabbOverlap;
+
+ while (curIndex < m_curNodeIndex)
+ {
+ //catch bugs in tree data
+ btAssert (walkIterations < m_curNodeIndex);
+
+ walkIterations++;
+ aabbOverlap = TestAabbAgainstAabb2(aabbMin,aabbMax,rootNode->m_aabbMinOrg,rootNode->m_aabbMaxOrg);
+ isLeafNode = rootNode->m_escapeIndex == -1;
+
+ //PCK: unsigned instead of bool
+ if (isLeafNode && (aabbOverlap != 0))
+ {
+ nodeCallback->processNode(rootNode->m_subPart,rootNode->m_triangleIndex);
+ }
+
+ //PCK: unsigned instead of bool
+ if ((aabbOverlap != 0) || isLeafNode)
+ {
+ rootNode++;
+ curIndex++;
+ } else
+ {
+ escapeIndex = rootNode->m_escapeIndex;
+ rootNode += escapeIndex;
+ curIndex += escapeIndex;
+ }
+ }
+ if (maxIterations < walkIterations)
+ maxIterations = walkIterations;
+
+}
+
+/*
+///this was the original recursive traversal, before we optimized towards stackless traversal
+void btQuantizedBvh::walkTree(btOptimizedBvhNode* rootNode,btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const
+{
+ bool isLeafNode, aabbOverlap = TestAabbAgainstAabb2(aabbMin,aabbMax,rootNode->m_aabbMin,rootNode->m_aabbMax);
+ if (aabbOverlap)
+ {
+ isLeafNode = (!rootNode->m_leftChild && !rootNode->m_rightChild);
+ if (isLeafNode)
+ {
+ nodeCallback->processNode(rootNode);
+ } else
+ {
+ walkTree(rootNode->m_leftChild,nodeCallback,aabbMin,aabbMax);
+ walkTree(rootNode->m_rightChild,nodeCallback,aabbMin,aabbMax);
+ }
+ }
+
+}
+*/
+
+void btQuantizedBvh::walkRecursiveQuantizedTreeAgainstQueryAabb(const btQuantizedBvhNode* currentNode,btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const
+{
+ btAssert(m_useQuantization);
+
+ bool isLeafNode;
+ //PCK: unsigned instead of bool
+ unsigned aabbOverlap;
+
+ //PCK: unsigned instead of bool
+ aabbOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,currentNode->m_quantizedAabbMin,currentNode->m_quantizedAabbMax);
+ isLeafNode = currentNode->isLeafNode();
+
+ //PCK: unsigned instead of bool
+ if (aabbOverlap != 0)
+ {
+ if (isLeafNode)
+ {
+ nodeCallback->processNode(currentNode->getPartId(),currentNode->getTriangleIndex());
+ } else
+ {
+ //process left and right children
+ const btQuantizedBvhNode* leftChildNode = currentNode+1;
+ walkRecursiveQuantizedTreeAgainstQueryAabb(leftChildNode,nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax);
+
+ const btQuantizedBvhNode* rightChildNode = leftChildNode->isLeafNode() ? leftChildNode+1:leftChildNode+leftChildNode->getEscapeIndex();
+ walkRecursiveQuantizedTreeAgainstQueryAabb(rightChildNode,nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax);
+ }
+ }
+}
+
+
+
+void btQuantizedBvh::walkStacklessTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex,int endNodeIndex) const
+{
+ btAssert(!m_useQuantization);
+
+ const btOptimizedBvhNode* rootNode = &m_contiguousNodes[0];
+ int escapeIndex, curIndex = 0;
+ int walkIterations = 0;
+ bool isLeafNode;
+ //PCK: unsigned instead of bool
+ unsigned aabbOverlap=0;
+ unsigned rayBoxOverlap=0;
+ btScalar lambda_max = 1.0;
+
+ /* Quick pruning by quantized box */
+ btVector3 rayAabbMin = raySource;
+ btVector3 rayAabbMax = raySource;
+ rayAabbMin.setMin(rayTarget);
+ rayAabbMax.setMax(rayTarget);
+
+ /* Add box cast extents to bounding box */
+ rayAabbMin += aabbMin;
+ rayAabbMax += aabbMax;
+
+#ifdef RAYAABB2
+ btVector3 rayDir = (rayTarget-raySource);
+ rayDir.normalize ();
+ lambda_max = rayDir.dot(rayTarget-raySource);
+ ///what about division by zero? --> just set rayDirection[i] to 1.0
+ btVector3 rayDirectionInverse;
+ rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[0];
+ rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[1];
+ rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[2];
+ unsigned int sign[3] = { rayDirectionInverse[0] < 0.0, rayDirectionInverse[1] < 0.0, rayDirectionInverse[2] < 0.0};
+#endif
+
+ btVector3 bounds[2];
+
+ while (curIndex < m_curNodeIndex)
+ {
+ btScalar param = 1.0;
+ //catch bugs in tree data
+ btAssert (walkIterations < m_curNodeIndex);
+
+ walkIterations++;
+
+ bounds[0] = rootNode->m_aabbMinOrg;
+ bounds[1] = rootNode->m_aabbMaxOrg;
+ /* Add box cast extents */
+ bounds[0] -= aabbMax;
+ bounds[1] -= aabbMin;
+
+ aabbOverlap = TestAabbAgainstAabb2(rayAabbMin,rayAabbMax,rootNode->m_aabbMinOrg,rootNode->m_aabbMaxOrg);
+ //perhaps profile if it is worth doing the aabbOverlap test first
+
+#ifdef RAYAABB2
+ ///careful with this check: need to check division by zero (above) and fix the unQuantize method
+ ///thanks Joerg/hiker for the reproduction case!
+ ///http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1858
+ rayBoxOverlap = aabbOverlap ? btRayAabb2 (raySource, rayDirectionInverse, sign, bounds, param, 0.0f, lambda_max) : false;
+
+#else
+ btVector3 normal;
+ rayBoxOverlap = btRayAabb(raySource, rayTarget,bounds[0],bounds[1],param, normal);
+#endif
+
+ isLeafNode = rootNode->m_escapeIndex == -1;
+
+ //PCK: unsigned instead of bool
+ if (isLeafNode && (rayBoxOverlap != 0))
+ {
+ nodeCallback->processNode(rootNode->m_subPart,rootNode->m_triangleIndex);
+ }
+
+ //PCK: unsigned instead of bool
+ if ((rayBoxOverlap != 0) || isLeafNode)
+ {
+ rootNode++;
+ curIndex++;
+ } else
+ {
+ escapeIndex = rootNode->m_escapeIndex;
+ rootNode += escapeIndex;
+ curIndex += escapeIndex;
+ }
+ }
+ if (maxIterations < walkIterations)
+ maxIterations = walkIterations;
+
+}
+
+
+
+void btQuantizedBvh::walkStacklessQuantizedTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex,int endNodeIndex) const
+{
+ btAssert(m_useQuantization);
+
+ int curIndex = startNodeIndex;
+ int walkIterations = 0;
+ int subTreeSize = endNodeIndex - startNodeIndex;
+ (void)subTreeSize;
+
+ const btQuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[startNodeIndex];
+ int escapeIndex;
+
+ bool isLeafNode;
+ //PCK: unsigned instead of bool
+ unsigned boxBoxOverlap = 0;
+ unsigned rayBoxOverlap = 0;
+
+ btScalar lambda_max = 1.0;
+
+#ifdef RAYAABB2
+ btVector3 rayDirection = (rayTarget-raySource);
+ rayDirection.normalize ();
+ lambda_max = rayDirection.dot(rayTarget-raySource);
+ ///what about division by zero? --> just set rayDirection[i] to 1.0
+ rayDirection[0] = rayDirection[0] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDirection[0];
+ rayDirection[1] = rayDirection[1] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDirection[1];
+ rayDirection[2] = rayDirection[2] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDirection[2];
+ unsigned int sign[3] = { rayDirection[0] < 0.0, rayDirection[1] < 0.0, rayDirection[2] < 0.0};
+#endif
+
+ /* Quick pruning by quantized box */
+ btVector3 rayAabbMin = raySource;
+ btVector3 rayAabbMax = raySource;
+ rayAabbMin.setMin(rayTarget);
+ rayAabbMax.setMax(rayTarget);
+
+ /* Add box cast extents to bounding box */
+ rayAabbMin += aabbMin;
+ rayAabbMax += aabbMax;
+
+ unsigned short int quantizedQueryAabbMin[3];
+ unsigned short int quantizedQueryAabbMax[3];
+ quantizeWithClamp(quantizedQueryAabbMin,rayAabbMin,0);
+ quantizeWithClamp(quantizedQueryAabbMax,rayAabbMax,1);
+
+ while (curIndex < endNodeIndex)
+ {
+
+//#define VISUALLY_ANALYZE_BVH 1
+#ifdef VISUALLY_ANALYZE_BVH
+ //some code snippet to debugDraw aabb, to visually analyze bvh structure
+ static int drawPatch = 0;
+ //need some global access to a debugDrawer
+ extern btIDebugDraw* debugDrawerPtr;
+ if (curIndex==drawPatch)
+ {
+ btVector3 aabbMin,aabbMax;
+ aabbMin = unQuantize(rootNode->m_quantizedAabbMin);
+ aabbMax = unQuantize(rootNode->m_quantizedAabbMax);
+ btVector3 color(1,0,0);
+ debugDrawerPtr->drawAabb(aabbMin,aabbMax,color);
+ }
+#endif//VISUALLY_ANALYZE_BVH
+
+ //catch bugs in tree data
+ btAssert (walkIterations < subTreeSize);
+
+ walkIterations++;
+ //PCK: unsigned instead of bool
+ // only interested if this is closer than any previous hit
+ btScalar param = 1.0;
+ rayBoxOverlap = 0;
+ boxBoxOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,rootNode->m_quantizedAabbMin,rootNode->m_quantizedAabbMax);
+ isLeafNode = rootNode->isLeafNode();
+ if (boxBoxOverlap)
+ {
+ btVector3 bounds[2];
+ bounds[0] = unQuantize(rootNode->m_quantizedAabbMin);
+ bounds[1] = unQuantize(rootNode->m_quantizedAabbMax);
+ /* Add box cast extents */
+ bounds[0] -= aabbMax;
+ bounds[1] -= aabbMin;
+ btVector3 normal;
+#if 0
+ bool ra2 = btRayAabb2 (raySource, rayDirection, sign, bounds, param, 0.0, lambda_max);
+ bool ra = btRayAabb (raySource, rayTarget, bounds[0], bounds[1], param, normal);
+ if (ra2 != ra)
+ {
+ printf("functions don't match\n");
+ }
+#endif
+#ifdef RAYAABB2
+ ///careful with this check: need to check division by zero (above) and fix the unQuantize method
+ ///thanks Joerg/hiker for the reproduction case!
+ ///http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1858
+
+ //BT_PROFILE("btRayAabb2");
+ rayBoxOverlap = btRayAabb2 (raySource, rayDirection, sign, bounds, param, 0.0f, lambda_max);
+
+#else
+ rayBoxOverlap = true;//btRayAabb(raySource, rayTarget, bounds[0], bounds[1], param, normal);
+#endif
+ }
+
+ if (isLeafNode && rayBoxOverlap)
+ {
+ nodeCallback->processNode(rootNode->getPartId(),rootNode->getTriangleIndex());
+ }
+
+ //PCK: unsigned instead of bool
+ if ((rayBoxOverlap != 0) || isLeafNode)
+ {
+ rootNode++;
+ curIndex++;
+ } else
+ {
+ escapeIndex = rootNode->getEscapeIndex();
+ rootNode += escapeIndex;
+ curIndex += escapeIndex;
+ }
+ }
+ if (maxIterations < walkIterations)
+ maxIterations = walkIterations;
+
+}
+
+void btQuantizedBvh::walkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,int startNodeIndex,int endNodeIndex) const
+{
+ btAssert(m_useQuantization);
+
+ int curIndex = startNodeIndex;
+ int walkIterations = 0;
+ int subTreeSize = endNodeIndex - startNodeIndex;
+ (void)subTreeSize;
+
+ const btQuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[startNodeIndex];
+ int escapeIndex;
+
+ bool isLeafNode;
+ //PCK: unsigned instead of bool
+ unsigned aabbOverlap;
+
+ while (curIndex < endNodeIndex)
+ {
+
+//#define VISUALLY_ANALYZE_BVH 1
+#ifdef VISUALLY_ANALYZE_BVH
+ //some code snippet to debugDraw aabb, to visually analyze bvh structure
+ static int drawPatch = 0;
+ //need some global access to a debugDrawer
+ extern btIDebugDraw* debugDrawerPtr;
+ if (curIndex==drawPatch)
+ {
+ btVector3 aabbMin,aabbMax;
+ aabbMin = unQuantize(rootNode->m_quantizedAabbMin);
+ aabbMax = unQuantize(rootNode->m_quantizedAabbMax);
+ btVector3 color(1,0,0);
+ debugDrawerPtr->drawAabb(aabbMin,aabbMax,color);
+ }
+#endif//VISUALLY_ANALYZE_BVH
+
+ //catch bugs in tree data
+ btAssert (walkIterations < subTreeSize);
+
+ walkIterations++;
+ //PCK: unsigned instead of bool
+ aabbOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,rootNode->m_quantizedAabbMin,rootNode->m_quantizedAabbMax);
+ isLeafNode = rootNode->isLeafNode();
+
+ if (isLeafNode && aabbOverlap)
+ {
+ nodeCallback->processNode(rootNode->getPartId(),rootNode->getTriangleIndex());
+ }
+
+ //PCK: unsigned instead of bool
+ if ((aabbOverlap != 0) || isLeafNode)
+ {
+ rootNode++;
+ curIndex++;
+ } else
+ {
+ escapeIndex = rootNode->getEscapeIndex();
+ rootNode += escapeIndex;
+ curIndex += escapeIndex;
+ }
+ }
+ if (maxIterations < walkIterations)
+ maxIterations = walkIterations;
+
+}
+
+//This traversal can be called from Playstation 3 SPU
+void btQuantizedBvh::walkStacklessQuantizedTreeCacheFriendly(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const
+{
+ btAssert(m_useQuantization);
+
+ int i;
+
+
+ for (i=0;i<this->m_SubtreeHeaders.size();i++)
+ {
+ const btBvhSubtreeInfo& subtree = m_SubtreeHeaders[i];
+
+ //PCK: unsigned instead of bool
+ unsigned overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax);
+ if (overlap != 0)
+ {
+ walkStacklessQuantizedTree(nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax,
+ subtree.m_rootNodeIndex,
+ subtree.m_rootNodeIndex+subtree.m_subtreeSize);
+ }
+ }
+}
+
+
+void btQuantizedBvh::reportRayOverlappingNodex (btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget) const
+{
+ reportBoxCastOverlappingNodex(nodeCallback,raySource,rayTarget,btVector3(0,0,0),btVector3(0,0,0));
+}
+
+
+void btQuantizedBvh::reportBoxCastOverlappingNodex(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin,const btVector3& aabbMax) const
+{
+ //always use stackless
+
+ if (m_useQuantization)
+ {
+ walkStacklessQuantizedTreeAgainstRay(nodeCallback, raySource, rayTarget, aabbMin, aabbMax, 0, m_curNodeIndex);
+ }
+ else
+ {
+ walkStacklessTreeAgainstRay(nodeCallback, raySource, rayTarget, aabbMin, aabbMax, 0, m_curNodeIndex);
+ }
+ /*
+ {
+ //recursive traversal
+ btVector3 qaabbMin = raySource;
+ btVector3 qaabbMax = raySource;
+ qaabbMin.setMin(rayTarget);
+ qaabbMax.setMax(rayTarget);
+ qaabbMin += aabbMin;
+ qaabbMax += aabbMax;
+ reportAabbOverlappingNodex(nodeCallback,qaabbMin,qaabbMax);
+ }
+ */
+
+}
+
+
+void btQuantizedBvh::swapLeafNodes(int i,int splitIndex)
+{
+ if (m_useQuantization)
+ {
+ btQuantizedBvhNode tmp = m_quantizedLeafNodes[i];
+ m_quantizedLeafNodes[i] = m_quantizedLeafNodes[splitIndex];
+ m_quantizedLeafNodes[splitIndex] = tmp;
+ } else
+ {
+ btOptimizedBvhNode tmp = m_leafNodes[i];
+ m_leafNodes[i] = m_leafNodes[splitIndex];
+ m_leafNodes[splitIndex] = tmp;
+ }
+}
+
+void btQuantizedBvh::assignInternalNodeFromLeafNode(int internalNode,int leafNodeIndex)
+{
+ if (m_useQuantization)
+ {
+ m_quantizedContiguousNodes[internalNode] = m_quantizedLeafNodes[leafNodeIndex];
+ } else
+ {
+ m_contiguousNodes[internalNode] = m_leafNodes[leafNodeIndex];
+ }
+}
+
+//PCK: include
+#include <new>
+
+#if 0
+//PCK: consts
+static const unsigned BVH_ALIGNMENT = 16;
+static const unsigned BVH_ALIGNMENT_MASK = BVH_ALIGNMENT-1;
+
+static const unsigned BVH_ALIGNMENT_BLOCKS = 2;
+#endif
+
+
+unsigned int btQuantizedBvh::getAlignmentSerializationPadding()
+{
+ // I changed this to 0 since the extra padding is not needed or used.
+ return 0;//BVH_ALIGNMENT_BLOCKS * BVH_ALIGNMENT;
+}
+
+unsigned btQuantizedBvh::calculateSerializeBufferSize() const
+{
+ unsigned baseSize = sizeof(btQuantizedBvh) + getAlignmentSerializationPadding();
+ baseSize += sizeof(btBvhSubtreeInfo) * m_subtreeHeaderCount;
+ if (m_useQuantization)
+ {
+ return baseSize + m_curNodeIndex * sizeof(btQuantizedBvhNode);
+ }
+ return baseSize + m_curNodeIndex * sizeof(btOptimizedBvhNode);
+}
+
+bool btQuantizedBvh::serialize(void *o_alignedDataBuffer, unsigned /*i_dataBufferSize */, bool i_swapEndian) const
+{
+ btAssert(m_subtreeHeaderCount == m_SubtreeHeaders.size());
+ m_subtreeHeaderCount = m_SubtreeHeaders.size();
+
+/* if (i_dataBufferSize < calculateSerializeBufferSize() || o_alignedDataBuffer == NULL || (((unsigned)o_alignedDataBuffer & BVH_ALIGNMENT_MASK) != 0))
+ {
+ ///check alignedment for buffer?
+ btAssert(0);
+ return false;
+ }
+*/
+
+ btQuantizedBvh *targetBvh = (btQuantizedBvh *)o_alignedDataBuffer;
+
+ // construct the class so the virtual function table, etc will be set up
+ // Also, m_leafNodes and m_quantizedLeafNodes will be initialized to default values by the constructor
+ new (targetBvh) btQuantizedBvh;
+
+ if (i_swapEndian)
+ {
+ targetBvh->m_curNodeIndex = static_cast<int>(btSwapEndian(m_curNodeIndex));
+
+
+ btSwapVector3Endian(m_bvhAabbMin,targetBvh->m_bvhAabbMin);
+ btSwapVector3Endian(m_bvhAabbMax,targetBvh->m_bvhAabbMax);
+ btSwapVector3Endian(m_bvhQuantization,targetBvh->m_bvhQuantization);
+
+ targetBvh->m_traversalMode = (btTraversalMode)btSwapEndian(m_traversalMode);
+ targetBvh->m_subtreeHeaderCount = static_cast<int>(btSwapEndian(m_subtreeHeaderCount));
+ }
+ else
+ {
+ targetBvh->m_curNodeIndex = m_curNodeIndex;
+ targetBvh->m_bvhAabbMin = m_bvhAabbMin;
+ targetBvh->m_bvhAabbMax = m_bvhAabbMax;
+ targetBvh->m_bvhQuantization = m_bvhQuantization;
+ targetBvh->m_traversalMode = m_traversalMode;
+ targetBvh->m_subtreeHeaderCount = m_subtreeHeaderCount;
+ }
+
+ targetBvh->m_useQuantization = m_useQuantization;
+
+ unsigned char *nodeData = (unsigned char *)targetBvh;
+ nodeData += sizeof(btQuantizedBvh);
+
+ unsigned sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK;
+ nodeData += sizeToAdd;
+
+ int nodeCount = m_curNodeIndex;
+
+ if (m_useQuantization)
+ {
+ targetBvh->m_quantizedContiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount);
+
+ if (i_swapEndian)
+ {
+ for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
+ {
+ targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0]);
+ targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1]);
+ targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2]);
+
+ targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0]);
+ targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1]);
+ targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2]);
+
+ targetBvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = static_cast<int>(btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex));
+ }
+ }
+ else
+ {
+ for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
+ {
+
+ targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0];
+ targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1];
+ targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2];
+
+ targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0];
+ targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1];
+ targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2];
+
+ targetBvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex;
+
+
+ }
+ }
+ nodeData += sizeof(btQuantizedBvhNode) * nodeCount;
+
+ // this clears the pointer in the member variable it doesn't really do anything to the data
+ // it does call the destructor on the contained objects, but they are all classes with no destructor defined
+ // so the memory (which is not freed) is left alone
+ targetBvh->m_quantizedContiguousNodes.initializeFromBuffer(NULL, 0, 0);
+ }
+ else
+ {
+ targetBvh->m_contiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount);
+
+ if (i_swapEndian)
+ {
+ for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
+ {
+ btSwapVector3Endian(m_contiguousNodes[nodeIndex].m_aabbMinOrg, targetBvh->m_contiguousNodes[nodeIndex].m_aabbMinOrg);
+ btSwapVector3Endian(m_contiguousNodes[nodeIndex].m_aabbMaxOrg, targetBvh->m_contiguousNodes[nodeIndex].m_aabbMaxOrg);
+
+ targetBvh->m_contiguousNodes[nodeIndex].m_escapeIndex = static_cast<int>(btSwapEndian(m_contiguousNodes[nodeIndex].m_escapeIndex));
+ targetBvh->m_contiguousNodes[nodeIndex].m_subPart = static_cast<int>(btSwapEndian(m_contiguousNodes[nodeIndex].m_subPart));
+ targetBvh->m_contiguousNodes[nodeIndex].m_triangleIndex = static_cast<int>(btSwapEndian(m_contiguousNodes[nodeIndex].m_triangleIndex));
+ }
+ }
+ else
+ {
+ for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
+ {
+ targetBvh->m_contiguousNodes[nodeIndex].m_aabbMinOrg = m_contiguousNodes[nodeIndex].m_aabbMinOrg;
+ targetBvh->m_contiguousNodes[nodeIndex].m_aabbMaxOrg = m_contiguousNodes[nodeIndex].m_aabbMaxOrg;
+
+ targetBvh->m_contiguousNodes[nodeIndex].m_escapeIndex = m_contiguousNodes[nodeIndex].m_escapeIndex;
+ targetBvh->m_contiguousNodes[nodeIndex].m_subPart = m_contiguousNodes[nodeIndex].m_subPart;
+ targetBvh->m_contiguousNodes[nodeIndex].m_triangleIndex = m_contiguousNodes[nodeIndex].m_triangleIndex;
+ }
+ }
+ nodeData += sizeof(btOptimizedBvhNode) * nodeCount;
+
+ // this clears the pointer in the member variable it doesn't really do anything to the data
+ // it does call the destructor on the contained objects, but they are all classes with no destructor defined
+ // so the memory (which is not freed) is left alone
+ targetBvh->m_contiguousNodes.initializeFromBuffer(NULL, 0, 0);
+ }
+
+ sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK;
+ nodeData += sizeToAdd;
+
+ // Now serialize the subtree headers
+ targetBvh->m_SubtreeHeaders.initializeFromBuffer(nodeData, m_subtreeHeaderCount, m_subtreeHeaderCount);
+ if (i_swapEndian)
+ {
+ for (int i = 0; i < m_subtreeHeaderCount; i++)
+ {
+ targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMin[0]);
+ targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMin[1]);
+ targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMin[2]);
+
+ targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMax[0]);
+ targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMax[1]);
+ targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMax[2]);
+
+ targetBvh->m_SubtreeHeaders[i].m_rootNodeIndex = static_cast<int>(btSwapEndian(m_SubtreeHeaders[i].m_rootNodeIndex));
+ targetBvh->m_SubtreeHeaders[i].m_subtreeSize = static_cast<int>(btSwapEndian(m_SubtreeHeaders[i].m_subtreeSize));
+ }
+ }
+ else
+ {
+ for (int i = 0; i < m_subtreeHeaderCount; i++)
+ {
+ targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0] = (m_SubtreeHeaders[i].m_quantizedAabbMin[0]);
+ targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1] = (m_SubtreeHeaders[i].m_quantizedAabbMin[1]);
+ targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2] = (m_SubtreeHeaders[i].m_quantizedAabbMin[2]);
+
+ targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0] = (m_SubtreeHeaders[i].m_quantizedAabbMax[0]);
+ targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1] = (m_SubtreeHeaders[i].m_quantizedAabbMax[1]);
+ targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2] = (m_SubtreeHeaders[i].m_quantizedAabbMax[2]);
+
+ targetBvh->m_SubtreeHeaders[i].m_rootNodeIndex = (m_SubtreeHeaders[i].m_rootNodeIndex);
+ targetBvh->m_SubtreeHeaders[i].m_subtreeSize = (m_SubtreeHeaders[i].m_subtreeSize);
+
+ // need to clear padding in destination buffer
+ targetBvh->m_SubtreeHeaders[i].m_padding[0] = 0;
+ targetBvh->m_SubtreeHeaders[i].m_padding[1] = 0;
+ targetBvh->m_SubtreeHeaders[i].m_padding[2] = 0;
+ }
+ }
+ nodeData += sizeof(btBvhSubtreeInfo) * m_subtreeHeaderCount;
+
+ // this clears the pointer in the member variable it doesn't really do anything to the data
+ // it does call the destructor on the contained objects, but they are all classes with no destructor defined
+ // so the memory (which is not freed) is left alone
+ targetBvh->m_SubtreeHeaders.initializeFromBuffer(NULL, 0, 0);
+
+ // this wipes the virtual function table pointer at the start of the buffer for the class
+ *((void**)o_alignedDataBuffer) = NULL;
+
+ return true;
+}
+
+btQuantizedBvh *btQuantizedBvh::deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian)
+{
+
+ if (i_alignedDataBuffer == NULL)// || (((unsigned)i_alignedDataBuffer & BVH_ALIGNMENT_MASK) != 0))
+ {
+ return NULL;
+ }
+ btQuantizedBvh *bvh = (btQuantizedBvh *)i_alignedDataBuffer;
+
+ if (i_swapEndian)
+ {
+ bvh->m_curNodeIndex = static_cast<int>(btSwapEndian(bvh->m_curNodeIndex));
+
+ btUnSwapVector3Endian(bvh->m_bvhAabbMin);
+ btUnSwapVector3Endian(bvh->m_bvhAabbMax);
+ btUnSwapVector3Endian(bvh->m_bvhQuantization);
+
+ bvh->m_traversalMode = (btTraversalMode)btSwapEndian(bvh->m_traversalMode);
+ bvh->m_subtreeHeaderCount = static_cast<int>(btSwapEndian(bvh->m_subtreeHeaderCount));
+ }
+
+ unsigned int calculatedBufSize = bvh->calculateSerializeBufferSize();
+ btAssert(calculatedBufSize <= i_dataBufferSize);
+
+ if (calculatedBufSize > i_dataBufferSize)
+ {
+ return NULL;
+ }
+
+ unsigned char *nodeData = (unsigned char *)bvh;
+ nodeData += sizeof(btQuantizedBvh);
+
+ unsigned sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK;
+ nodeData += sizeToAdd;
+
+ int nodeCount = bvh->m_curNodeIndex;
+
+ // Must call placement new to fill in virtual function table, etc, but we don't want to overwrite most data, so call a special version of the constructor
+ // Also, m_leafNodes and m_quantizedLeafNodes will be initialized to default values by the constructor
+ new (bvh) btQuantizedBvh(*bvh, false);
+
+ if (bvh->m_useQuantization)
+ {
+ bvh->m_quantizedContiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount);
+
+ if (i_swapEndian)
+ {
+ for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
+ {
+ bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0]);
+ bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1]);
+ bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2]);
+
+ bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0]);
+ bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1]);
+ bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2]);
+
+ bvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = static_cast<int>(btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex));
+ }
+ }
+ nodeData += sizeof(btQuantizedBvhNode) * nodeCount;
+ }
+ else
+ {
+ bvh->m_contiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount);
+
+ if (i_swapEndian)
+ {
+ for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
+ {
+ btUnSwapVector3Endian(bvh->m_contiguousNodes[nodeIndex].m_aabbMinOrg);
+ btUnSwapVector3Endian(bvh->m_contiguousNodes[nodeIndex].m_aabbMaxOrg);
+
+ bvh->m_contiguousNodes[nodeIndex].m_escapeIndex = static_cast<int>(btSwapEndian(bvh->m_contiguousNodes[nodeIndex].m_escapeIndex));
+ bvh->m_contiguousNodes[nodeIndex].m_subPart = static_cast<int>(btSwapEndian(bvh->m_contiguousNodes[nodeIndex].m_subPart));
+ bvh->m_contiguousNodes[nodeIndex].m_triangleIndex = static_cast<int>(btSwapEndian(bvh->m_contiguousNodes[nodeIndex].m_triangleIndex));
+ }
+ }
+ nodeData += sizeof(btOptimizedBvhNode) * nodeCount;
+ }
+
+ sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK;
+ nodeData += sizeToAdd;
+
+ // Now serialize the subtree headers
+ bvh->m_SubtreeHeaders.initializeFromBuffer(nodeData, bvh->m_subtreeHeaderCount, bvh->m_subtreeHeaderCount);
+ if (i_swapEndian)
+ {
+ for (int i = 0; i < bvh->m_subtreeHeaderCount; i++)
+ {
+ bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0]);
+ bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1]);
+ bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2]);
+
+ bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0]);
+ bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1]);
+ bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2]);
+
+ bvh->m_SubtreeHeaders[i].m_rootNodeIndex = static_cast<int>(btSwapEndian(bvh->m_SubtreeHeaders[i].m_rootNodeIndex));
+ bvh->m_SubtreeHeaders[i].m_subtreeSize = static_cast<int>(btSwapEndian(bvh->m_SubtreeHeaders[i].m_subtreeSize));
+ }
+ }
+
+ return bvh;
+}
+
+// Constructor that prevents btVector3's default constructor from being called
+btQuantizedBvh::btQuantizedBvh(btQuantizedBvh &self, bool /* ownsMemory */) :
+m_bvhAabbMin(self.m_bvhAabbMin),
+m_bvhAabbMax(self.m_bvhAabbMax),
+m_bvhQuantization(self.m_bvhQuantization),
+m_bulletVersion(BT_BULLET_VERSION)
+{
+
+}
+
+void btQuantizedBvh::deSerializeFloat(struct btQuantizedBvhFloatData& quantizedBvhFloatData)
+{
+ m_bvhAabbMax.deSerializeFloat(quantizedBvhFloatData.m_bvhAabbMax);
+ m_bvhAabbMin.deSerializeFloat(quantizedBvhFloatData.m_bvhAabbMin);
+ m_bvhQuantization.deSerializeFloat(quantizedBvhFloatData.m_bvhQuantization);
+
+ m_curNodeIndex = quantizedBvhFloatData.m_curNodeIndex;
+ m_useQuantization = quantizedBvhFloatData.m_useQuantization!=0;
+
+ {
+ int numElem = quantizedBvhFloatData.m_numContiguousLeafNodes;
+ m_contiguousNodes.resize(numElem);
+
+ if (numElem)
+ {
+ btOptimizedBvhNodeFloatData* memPtr = quantizedBvhFloatData.m_contiguousNodesPtr;
+
+ for (int i=0;i<numElem;i++,memPtr++)
+ {
+ m_contiguousNodes[i].m_aabbMaxOrg.deSerializeFloat(memPtr->m_aabbMaxOrg);
+ m_contiguousNodes[i].m_aabbMinOrg.deSerializeFloat(memPtr->m_aabbMinOrg);
+ m_contiguousNodes[i].m_escapeIndex = memPtr->m_escapeIndex;
+ m_contiguousNodes[i].m_subPart = memPtr->m_subPart;
+ m_contiguousNodes[i].m_triangleIndex = memPtr->m_triangleIndex;
+ }
+ }
+ }
+
+ {
+ int numElem = quantizedBvhFloatData.m_numQuantizedContiguousNodes;
+ m_quantizedContiguousNodes.resize(numElem);
+
+ if (numElem)
+ {
+ btQuantizedBvhNodeData* memPtr = quantizedBvhFloatData.m_quantizedContiguousNodesPtr;
+ for (int i=0;i<numElem;i++,memPtr++)
+ {
+ m_quantizedContiguousNodes[i].m_escapeIndexOrTriangleIndex = memPtr->m_escapeIndexOrTriangleIndex;
+ m_quantizedContiguousNodes[i].m_quantizedAabbMax[0] = memPtr->m_quantizedAabbMax[0];
+ m_quantizedContiguousNodes[i].m_quantizedAabbMax[1] = memPtr->m_quantizedAabbMax[1];
+ m_quantizedContiguousNodes[i].m_quantizedAabbMax[2] = memPtr->m_quantizedAabbMax[2];
+ m_quantizedContiguousNodes[i].m_quantizedAabbMin[0] = memPtr->m_quantizedAabbMin[0];
+ m_quantizedContiguousNodes[i].m_quantizedAabbMin[1] = memPtr->m_quantizedAabbMin[1];
+ m_quantizedContiguousNodes[i].m_quantizedAabbMin[2] = memPtr->m_quantizedAabbMin[2];
+ }
+ }
+ }
+
+ m_traversalMode = btTraversalMode(quantizedBvhFloatData.m_traversalMode);
+
+ {
+ int numElem = quantizedBvhFloatData.m_numSubtreeHeaders;
+ m_SubtreeHeaders.resize(numElem);
+ if (numElem)
+ {
+ btBvhSubtreeInfoData* memPtr = quantizedBvhFloatData.m_subTreeInfoPtr;
+ for (int i=0;i<numElem;i++,memPtr++)
+ {
+ m_SubtreeHeaders[i].m_quantizedAabbMax[0] = memPtr->m_quantizedAabbMax[0] ;
+ m_SubtreeHeaders[i].m_quantizedAabbMax[1] = memPtr->m_quantizedAabbMax[1];
+ m_SubtreeHeaders[i].m_quantizedAabbMax[2] = memPtr->m_quantizedAabbMax[2];
+ m_SubtreeHeaders[i].m_quantizedAabbMin[0] = memPtr->m_quantizedAabbMin[0];
+ m_SubtreeHeaders[i].m_quantizedAabbMin[1] = memPtr->m_quantizedAabbMin[1];
+ m_SubtreeHeaders[i].m_quantizedAabbMin[2] = memPtr->m_quantizedAabbMin[2];
+ m_SubtreeHeaders[i].m_rootNodeIndex = memPtr->m_rootNodeIndex;
+ m_SubtreeHeaders[i].m_subtreeSize = memPtr->m_subtreeSize;
+ }
+ }
+ }
+}
+
+void btQuantizedBvh::deSerializeDouble(struct btQuantizedBvhDoubleData& quantizedBvhDoubleData)
+{
+ m_bvhAabbMax.deSerializeDouble(quantizedBvhDoubleData.m_bvhAabbMax);
+ m_bvhAabbMin.deSerializeDouble(quantizedBvhDoubleData.m_bvhAabbMin);
+ m_bvhQuantization.deSerializeDouble(quantizedBvhDoubleData.m_bvhQuantization);
+
+ m_curNodeIndex = quantizedBvhDoubleData.m_curNodeIndex;
+ m_useQuantization = quantizedBvhDoubleData.m_useQuantization!=0;
+
+ {
+ int numElem = quantizedBvhDoubleData.m_numContiguousLeafNodes;
+ m_contiguousNodes.resize(numElem);
+
+ if (numElem)
+ {
+ btOptimizedBvhNodeDoubleData* memPtr = quantizedBvhDoubleData.m_contiguousNodesPtr;
+
+ for (int i=0;i<numElem;i++,memPtr++)
+ {
+ m_contiguousNodes[i].m_aabbMaxOrg.deSerializeDouble(memPtr->m_aabbMaxOrg);
+ m_contiguousNodes[i].m_aabbMinOrg.deSerializeDouble(memPtr->m_aabbMinOrg);
+ m_contiguousNodes[i].m_escapeIndex = memPtr->m_escapeIndex;
+ m_contiguousNodes[i].m_subPart = memPtr->m_subPart;
+ m_contiguousNodes[i].m_triangleIndex = memPtr->m_triangleIndex;
+ }
+ }
+ }
+
+ {
+ int numElem = quantizedBvhDoubleData.m_numQuantizedContiguousNodes;
+ m_quantizedContiguousNodes.resize(numElem);
+
+ if (numElem)
+ {
+ btQuantizedBvhNodeData* memPtr = quantizedBvhDoubleData.m_quantizedContiguousNodesPtr;
+ for (int i=0;i<numElem;i++,memPtr++)
+ {
+ m_quantizedContiguousNodes[i].m_escapeIndexOrTriangleIndex = memPtr->m_escapeIndexOrTriangleIndex;
+ m_quantizedContiguousNodes[i].m_quantizedAabbMax[0] = memPtr->m_quantizedAabbMax[0];
+ m_quantizedContiguousNodes[i].m_quantizedAabbMax[1] = memPtr->m_quantizedAabbMax[1];
+ m_quantizedContiguousNodes[i].m_quantizedAabbMax[2] = memPtr->m_quantizedAabbMax[2];
+ m_quantizedContiguousNodes[i].m_quantizedAabbMin[0] = memPtr->m_quantizedAabbMin[0];
+ m_quantizedContiguousNodes[i].m_quantizedAabbMin[1] = memPtr->m_quantizedAabbMin[1];
+ m_quantizedContiguousNodes[i].m_quantizedAabbMin[2] = memPtr->m_quantizedAabbMin[2];
+ }
+ }
+ }
+
+ m_traversalMode = btTraversalMode(quantizedBvhDoubleData.m_traversalMode);
+
+ {
+ int numElem = quantizedBvhDoubleData.m_numSubtreeHeaders;
+ m_SubtreeHeaders.resize(numElem);
+ if (numElem)
+ {
+ btBvhSubtreeInfoData* memPtr = quantizedBvhDoubleData.m_subTreeInfoPtr;
+ for (int i=0;i<numElem;i++,memPtr++)
+ {
+ m_SubtreeHeaders[i].m_quantizedAabbMax[0] = memPtr->m_quantizedAabbMax[0] ;
+ m_SubtreeHeaders[i].m_quantizedAabbMax[1] = memPtr->m_quantizedAabbMax[1];
+ m_SubtreeHeaders[i].m_quantizedAabbMax[2] = memPtr->m_quantizedAabbMax[2];
+ m_SubtreeHeaders[i].m_quantizedAabbMin[0] = memPtr->m_quantizedAabbMin[0];
+ m_SubtreeHeaders[i].m_quantizedAabbMin[1] = memPtr->m_quantizedAabbMin[1];
+ m_SubtreeHeaders[i].m_quantizedAabbMin[2] = memPtr->m_quantizedAabbMin[2];
+ m_SubtreeHeaders[i].m_rootNodeIndex = memPtr->m_rootNodeIndex;
+ m_SubtreeHeaders[i].m_subtreeSize = memPtr->m_subtreeSize;
+ }
+ }
+ }
+
+}
+
+
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+const char* btQuantizedBvh::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+ btQuantizedBvhData* quantizedData = (btQuantizedBvhData*)dataBuffer;
+
+ m_bvhAabbMax.serialize(quantizedData->m_bvhAabbMax);
+ m_bvhAabbMin.serialize(quantizedData->m_bvhAabbMin);
+ m_bvhQuantization.serialize(quantizedData->m_bvhQuantization);
+
+ quantizedData->m_curNodeIndex = m_curNodeIndex;
+ quantizedData->m_useQuantization = m_useQuantization;
+
+ quantizedData->m_numContiguousLeafNodes = m_contiguousNodes.size();
+ quantizedData->m_contiguousNodesPtr = (btOptimizedBvhNodeData*) (m_contiguousNodes.size() ? serializer->getUniquePointer((void*)&m_contiguousNodes[0]) : 0);
+ if (quantizedData->m_contiguousNodesPtr)
+ {
+ int sz = sizeof(btOptimizedBvhNodeData);
+ int numElem = m_contiguousNodes.size();
+ btChunk* chunk = serializer->allocate(sz,numElem);
+ btOptimizedBvhNodeData* memPtr = (btOptimizedBvhNodeData*)chunk->m_oldPtr;
+ for (int i=0;i<numElem;i++,memPtr++)
+ {
+ m_contiguousNodes[i].m_aabbMaxOrg.serialize(memPtr->m_aabbMaxOrg);
+ m_contiguousNodes[i].m_aabbMinOrg.serialize(memPtr->m_aabbMinOrg);
+ memPtr->m_escapeIndex = m_contiguousNodes[i].m_escapeIndex;
+ memPtr->m_subPart = m_contiguousNodes[i].m_subPart;
+ memPtr->m_triangleIndex = m_contiguousNodes[i].m_triangleIndex;
+ // Fill padding with zeros to appease msan.
+ memset(memPtr->m_pad, 0, sizeof(memPtr->m_pad));
+ }
+ serializer->finalizeChunk(chunk,"btOptimizedBvhNodeData",BT_ARRAY_CODE,(void*)&m_contiguousNodes[0]);
+ }
+
+ quantizedData->m_numQuantizedContiguousNodes = m_quantizedContiguousNodes.size();
+// printf("quantizedData->m_numQuantizedContiguousNodes=%d\n",quantizedData->m_numQuantizedContiguousNodes);
+ quantizedData->m_quantizedContiguousNodesPtr =(btQuantizedBvhNodeData*) (m_quantizedContiguousNodes.size() ? serializer->getUniquePointer((void*)&m_quantizedContiguousNodes[0]) : 0);
+ if (quantizedData->m_quantizedContiguousNodesPtr)
+ {
+ int sz = sizeof(btQuantizedBvhNodeData);
+ int numElem = m_quantizedContiguousNodes.size();
+ btChunk* chunk = serializer->allocate(sz,numElem);
+ btQuantizedBvhNodeData* memPtr = (btQuantizedBvhNodeData*)chunk->m_oldPtr;
+ for (int i=0;i<numElem;i++,memPtr++)
+ {
+ memPtr->m_escapeIndexOrTriangleIndex = m_quantizedContiguousNodes[i].m_escapeIndexOrTriangleIndex;
+ memPtr->m_quantizedAabbMax[0] = m_quantizedContiguousNodes[i].m_quantizedAabbMax[0];
+ memPtr->m_quantizedAabbMax[1] = m_quantizedContiguousNodes[i].m_quantizedAabbMax[1];
+ memPtr->m_quantizedAabbMax[2] = m_quantizedContiguousNodes[i].m_quantizedAabbMax[2];
+ memPtr->m_quantizedAabbMin[0] = m_quantizedContiguousNodes[i].m_quantizedAabbMin[0];
+ memPtr->m_quantizedAabbMin[1] = m_quantizedContiguousNodes[i].m_quantizedAabbMin[1];
+ memPtr->m_quantizedAabbMin[2] = m_quantizedContiguousNodes[i].m_quantizedAabbMin[2];
+ }
+ serializer->finalizeChunk(chunk,"btQuantizedBvhNodeData",BT_ARRAY_CODE,(void*)&m_quantizedContiguousNodes[0]);
+ }
+
+ quantizedData->m_traversalMode = int(m_traversalMode);
+ quantizedData->m_numSubtreeHeaders = m_SubtreeHeaders.size();
+
+ quantizedData->m_subTreeInfoPtr = (btBvhSubtreeInfoData*) (m_SubtreeHeaders.size() ? serializer->getUniquePointer((void*)&m_SubtreeHeaders[0]) : 0);
+ if (quantizedData->m_subTreeInfoPtr)
+ {
+ int sz = sizeof(btBvhSubtreeInfoData);
+ int numElem = m_SubtreeHeaders.size();
+ btChunk* chunk = serializer->allocate(sz,numElem);
+ btBvhSubtreeInfoData* memPtr = (btBvhSubtreeInfoData*)chunk->m_oldPtr;
+ for (int i=0;i<numElem;i++,memPtr++)
+ {
+ memPtr->m_quantizedAabbMax[0] = m_SubtreeHeaders[i].m_quantizedAabbMax[0];
+ memPtr->m_quantizedAabbMax[1] = m_SubtreeHeaders[i].m_quantizedAabbMax[1];
+ memPtr->m_quantizedAabbMax[2] = m_SubtreeHeaders[i].m_quantizedAabbMax[2];
+ memPtr->m_quantizedAabbMin[0] = m_SubtreeHeaders[i].m_quantizedAabbMin[0];
+ memPtr->m_quantizedAabbMin[1] = m_SubtreeHeaders[i].m_quantizedAabbMin[1];
+ memPtr->m_quantizedAabbMin[2] = m_SubtreeHeaders[i].m_quantizedAabbMin[2];
+
+ memPtr->m_rootNodeIndex = m_SubtreeHeaders[i].m_rootNodeIndex;
+ memPtr->m_subtreeSize = m_SubtreeHeaders[i].m_subtreeSize;
+ }
+ serializer->finalizeChunk(chunk,"btBvhSubtreeInfoData",BT_ARRAY_CODE,(void*)&m_SubtreeHeaders[0]);
+ }
+ return btQuantizedBvhDataName;
+}
+
+
+
+
+
diff --git a/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h b/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h
new file mode 100644
index 0000000000..3dd5ac9bb6
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h
@@ -0,0 +1,581 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_QUANTIZED_BVH_H
+#define BT_QUANTIZED_BVH_H
+
+class btSerializer;
+
+//#define DEBUG_CHECK_DEQUANTIZATION 1
+#ifdef DEBUG_CHECK_DEQUANTIZATION
+#ifdef __SPU__
+#define printf spu_printf
+#endif //__SPU__
+
+#include <stdio.h>
+#include <stdlib.h>
+#endif //DEBUG_CHECK_DEQUANTIZATION
+
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btAlignedAllocator.h"
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define btQuantizedBvhData btQuantizedBvhDoubleData
+#define btOptimizedBvhNodeData btOptimizedBvhNodeDoubleData
+#define btQuantizedBvhDataName "btQuantizedBvhDoubleData"
+#else
+#define btQuantizedBvhData btQuantizedBvhFloatData
+#define btOptimizedBvhNodeData btOptimizedBvhNodeFloatData
+#define btQuantizedBvhDataName "btQuantizedBvhFloatData"
+#endif
+
+
+
+//http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/vclrf__m128.asp
+
+
+//Note: currently we have 16 bytes per quantized node
+#define MAX_SUBTREE_SIZE_IN_BYTES 2048
+
+// 10 gives the potential for 1024 parts, with at most 2^21 (2097152) (minus one
+// actually) triangles each (since the sign bit is reserved
+#define MAX_NUM_PARTS_IN_BITS 10
+
+///btQuantizedBvhNode is a compressed aabb node, 16 bytes.
+///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range).
+ATTRIBUTE_ALIGNED16 (struct) btQuantizedBvhNode
+{
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ //12 bytes
+ unsigned short int m_quantizedAabbMin[3];
+ unsigned short int m_quantizedAabbMax[3];
+ //4 bytes
+ int m_escapeIndexOrTriangleIndex;
+
+ bool isLeafNode() const
+ {
+ //skipindex is negative (internal node), triangleindex >=0 (leafnode)
+ return (m_escapeIndexOrTriangleIndex >= 0);
+ }
+ int getEscapeIndex() const
+ {
+ btAssert(!isLeafNode());
+ return -m_escapeIndexOrTriangleIndex;
+ }
+ int getTriangleIndex() const
+ {
+ btAssert(isLeafNode());
+ unsigned int x=0;
+ unsigned int y = (~(x&0))<<(31-MAX_NUM_PARTS_IN_BITS);
+ // Get only the lower bits where the triangle index is stored
+ return (m_escapeIndexOrTriangleIndex&~(y));
+ }
+ int getPartId() const
+ {
+ btAssert(isLeafNode());
+ // Get only the highest bits where the part index is stored
+ return (m_escapeIndexOrTriangleIndex>>(31-MAX_NUM_PARTS_IN_BITS));
+ }
+}
+;
+
+/// btOptimizedBvhNode contains both internal and leaf node information.
+/// Total node size is 44 bytes / node. You can use the compressed version of 16 bytes.
+ATTRIBUTE_ALIGNED16 (struct) btOptimizedBvhNode
+{
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ //32 bytes
+ btVector3 m_aabbMinOrg;
+ btVector3 m_aabbMaxOrg;
+
+ //4
+ int m_escapeIndex;
+
+ //8
+ //for child nodes
+ int m_subPart;
+ int m_triangleIndex;
+
+//pad the size to 64 bytes
+ char m_padding[20];
+};
+
+
+///btBvhSubtreeInfo provides info to gather a subtree of limited size
+ATTRIBUTE_ALIGNED16(class) btBvhSubtreeInfo
+{
+public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ //12 bytes
+ unsigned short int m_quantizedAabbMin[3];
+ unsigned short int m_quantizedAabbMax[3];
+ //4 bytes, points to the root of the subtree
+ int m_rootNodeIndex;
+ //4 bytes
+ int m_subtreeSize;
+ int m_padding[3];
+
+ btBvhSubtreeInfo()
+ {
+ //memset(&m_padding[0], 0, sizeof(m_padding));
+ }
+
+
+ void setAabbFromQuantizeNode(const btQuantizedBvhNode& quantizedNode)
+ {
+ m_quantizedAabbMin[0] = quantizedNode.m_quantizedAabbMin[0];
+ m_quantizedAabbMin[1] = quantizedNode.m_quantizedAabbMin[1];
+ m_quantizedAabbMin[2] = quantizedNode.m_quantizedAabbMin[2];
+ m_quantizedAabbMax[0] = quantizedNode.m_quantizedAabbMax[0];
+ m_quantizedAabbMax[1] = quantizedNode.m_quantizedAabbMax[1];
+ m_quantizedAabbMax[2] = quantizedNode.m_quantizedAabbMax[2];
+ }
+}
+;
+
+
+class btNodeOverlapCallback
+{
+public:
+ virtual ~btNodeOverlapCallback() {};
+
+ virtual void processNode(int subPart, int triangleIndex) = 0;
+};
+
+#include "LinearMath/btAlignedAllocator.h"
+#include "LinearMath/btAlignedObjectArray.h"
+
+
+
+///for code readability:
+typedef btAlignedObjectArray<btOptimizedBvhNode> NodeArray;
+typedef btAlignedObjectArray<btQuantizedBvhNode> QuantizedNodeArray;
+typedef btAlignedObjectArray<btBvhSubtreeInfo> BvhSubtreeInfoArray;
+
+
+///The btQuantizedBvh class stores an AABB tree that can be quickly traversed on CPU and Cell SPU.
+///It is used by the btBvhTriangleMeshShape as midphase.
+///It is recommended to use quantization for better performance and lower memory requirements.
+ATTRIBUTE_ALIGNED16(class) btQuantizedBvh
+{
+public:
+ enum btTraversalMode
+ {
+ TRAVERSAL_STACKLESS = 0,
+ TRAVERSAL_STACKLESS_CACHE_FRIENDLY,
+ TRAVERSAL_RECURSIVE
+ };
+
+protected:
+
+
+ btVector3 m_bvhAabbMin;
+ btVector3 m_bvhAabbMax;
+ btVector3 m_bvhQuantization;
+
+ int m_bulletVersion; //for serialization versioning. It could also be used to detect endianess.
+
+ int m_curNodeIndex;
+ //quantization data
+ bool m_useQuantization;
+
+
+
+ NodeArray m_leafNodes;
+ NodeArray m_contiguousNodes;
+ QuantizedNodeArray m_quantizedLeafNodes;
+ QuantizedNodeArray m_quantizedContiguousNodes;
+
+ btTraversalMode m_traversalMode;
+ BvhSubtreeInfoArray m_SubtreeHeaders;
+
+ //This is only used for serialization so we don't have to add serialization directly to btAlignedObjectArray
+ mutable int m_subtreeHeaderCount;
+
+
+
+
+
+ ///two versions, one for quantized and normal nodes. This allows code-reuse while maintaining readability (no template/macro!)
+ ///this might be refactored into a virtual, it is usually not calculated at run-time
+ void setInternalNodeAabbMin(int nodeIndex, const btVector3& aabbMin)
+ {
+ if (m_useQuantization)
+ {
+ quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] ,aabbMin,0);
+ } else
+ {
+ m_contiguousNodes[nodeIndex].m_aabbMinOrg = aabbMin;
+
+ }
+ }
+ void setInternalNodeAabbMax(int nodeIndex,const btVector3& aabbMax)
+ {
+ if (m_useQuantization)
+ {
+ quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0],aabbMax,1);
+ } else
+ {
+ m_contiguousNodes[nodeIndex].m_aabbMaxOrg = aabbMax;
+ }
+ }
+
+ btVector3 getAabbMin(int nodeIndex) const
+ {
+ if (m_useQuantization)
+ {
+ return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMin[0]);
+ }
+ //non-quantized
+ return m_leafNodes[nodeIndex].m_aabbMinOrg;
+
+ }
+ btVector3 getAabbMax(int nodeIndex) const
+ {
+ if (m_useQuantization)
+ {
+ return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMax[0]);
+ }
+ //non-quantized
+ return m_leafNodes[nodeIndex].m_aabbMaxOrg;
+
+ }
+
+
+ void setInternalNodeEscapeIndex(int nodeIndex, int escapeIndex)
+ {
+ if (m_useQuantization)
+ {
+ m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = -escapeIndex;
+ }
+ else
+ {
+ m_contiguousNodes[nodeIndex].m_escapeIndex = escapeIndex;
+ }
+
+ }
+
+ void mergeInternalNodeAabb(int nodeIndex,const btVector3& newAabbMin,const btVector3& newAabbMax)
+ {
+ if (m_useQuantization)
+ {
+ unsigned short int quantizedAabbMin[3];
+ unsigned short int quantizedAabbMax[3];
+ quantize(quantizedAabbMin,newAabbMin,0);
+ quantize(quantizedAabbMax,newAabbMax,1);
+ for (int i=0;i<3;i++)
+ {
+ if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] > quantizedAabbMin[i])
+ m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] = quantizedAabbMin[i];
+
+ if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] < quantizedAabbMax[i])
+ m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] = quantizedAabbMax[i];
+
+ }
+ } else
+ {
+ //non-quantized
+ m_contiguousNodes[nodeIndex].m_aabbMinOrg.setMin(newAabbMin);
+ m_contiguousNodes[nodeIndex].m_aabbMaxOrg.setMax(newAabbMax);
+ }
+ }
+
+ void swapLeafNodes(int firstIndex,int secondIndex);
+
+ void assignInternalNodeFromLeafNode(int internalNode,int leafNodeIndex);
+
+protected:
+
+
+
+ void buildTree (int startIndex,int endIndex);
+
+ int calcSplittingAxis(int startIndex,int endIndex);
+
+ int sortAndCalcSplittingIndex(int startIndex,int endIndex,int splitAxis);
+
+ void walkStacklessTree(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const;
+
+ void walkStacklessQuantizedTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex,int endNodeIndex) const;
+ void walkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,int startNodeIndex,int endNodeIndex) const;
+ void walkStacklessTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex,int endNodeIndex) const;
+
+ ///tree traversal designed for small-memory processors like PS3 SPU
+ void walkStacklessQuantizedTreeCacheFriendly(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const;
+
+ ///use the 16-byte stackless 'skipindex' node tree to do a recursive traversal
+ void walkRecursiveQuantizedTreeAgainstQueryAabb(const btQuantizedBvhNode* currentNode,btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const;
+
+ ///use the 16-byte stackless 'skipindex' node tree to do a recursive traversal
+ void walkRecursiveQuantizedTreeAgainstQuantizedTree(const btQuantizedBvhNode* treeNodeA,const btQuantizedBvhNode* treeNodeB,btNodeOverlapCallback* nodeCallback) const;
+
+
+
+
+ void updateSubtreeHeaders(int leftChildNodexIndex,int rightChildNodexIndex);
+
+public:
+
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ btQuantizedBvh();
+
+ virtual ~btQuantizedBvh();
+
+
+ ///***************************************** expert/internal use only *************************
+ void setQuantizationValues(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,btScalar quantizationMargin=btScalar(1.0));
+ QuantizedNodeArray& getLeafNodeArray() { return m_quantizedLeafNodes; }
+ ///buildInternal is expert use only: assumes that setQuantizationValues and LeafNodeArray are initialized
+ void buildInternal();
+ ///***************************************** expert/internal use only *************************
+
+ void reportAabbOverlappingNodex(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const;
+ void reportRayOverlappingNodex (btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget) const;
+ void reportBoxCastOverlappingNodex(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin,const btVector3& aabbMax) const;
+
+ SIMD_FORCE_INLINE void quantize(unsigned short* out, const btVector3& point,int isMax) const
+ {
+
+ btAssert(m_useQuantization);
+
+ btAssert(point.getX() <= m_bvhAabbMax.getX());
+ btAssert(point.getY() <= m_bvhAabbMax.getY());
+ btAssert(point.getZ() <= m_bvhAabbMax.getZ());
+
+ btAssert(point.getX() >= m_bvhAabbMin.getX());
+ btAssert(point.getY() >= m_bvhAabbMin.getY());
+ btAssert(point.getZ() >= m_bvhAabbMin.getZ());
+
+ btVector3 v = (point - m_bvhAabbMin) * m_bvhQuantization;
+ ///Make sure rounding is done in a way that unQuantize(quantizeWithClamp(...)) is conservative
+ ///end-points always set the first bit, so that they are sorted properly (so that neighbouring AABBs overlap properly)
+ ///@todo: double-check this
+ if (isMax)
+ {
+ out[0] = (unsigned short) (((unsigned short)(v.getX()+btScalar(1.)) | 1));
+ out[1] = (unsigned short) (((unsigned short)(v.getY()+btScalar(1.)) | 1));
+ out[2] = (unsigned short) (((unsigned short)(v.getZ()+btScalar(1.)) | 1));
+ } else
+ {
+ out[0] = (unsigned short) (((unsigned short)(v.getX()) & 0xfffe));
+ out[1] = (unsigned short) (((unsigned short)(v.getY()) & 0xfffe));
+ out[2] = (unsigned short) (((unsigned short)(v.getZ()) & 0xfffe));
+ }
+
+
+#ifdef DEBUG_CHECK_DEQUANTIZATION
+ btVector3 newPoint = unQuantize(out);
+ if (isMax)
+ {
+ if (newPoint.getX() < point.getX())
+ {
+ printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n",newPoint.getX()-point.getX(), newPoint.getX(),point.getX());
+ }
+ if (newPoint.getY() < point.getY())
+ {
+ printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n",newPoint.getY()-point.getY(), newPoint.getY(),point.getY());
+ }
+ if (newPoint.getZ() < point.getZ())
+ {
+
+ printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n",newPoint.getZ()-point.getZ(), newPoint.getZ(),point.getZ());
+ }
+ } else
+ {
+ if (newPoint.getX() > point.getX())
+ {
+ printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n",newPoint.getX()-point.getX(), newPoint.getX(),point.getX());
+ }
+ if (newPoint.getY() > point.getY())
+ {
+ printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n",newPoint.getY()-point.getY(), newPoint.getY(),point.getY());
+ }
+ if (newPoint.getZ() > point.getZ())
+ {
+ printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n",newPoint.getZ()-point.getZ(), newPoint.getZ(),point.getZ());
+ }
+ }
+#endif //DEBUG_CHECK_DEQUANTIZATION
+
+ }
+
+
+ SIMD_FORCE_INLINE void quantizeWithClamp(unsigned short* out, const btVector3& point2,int isMax) const
+ {
+
+ btAssert(m_useQuantization);
+
+ btVector3 clampedPoint(point2);
+ clampedPoint.setMax(m_bvhAabbMin);
+ clampedPoint.setMin(m_bvhAabbMax);
+
+ quantize(out,clampedPoint,isMax);
+
+ }
+
+ SIMD_FORCE_INLINE btVector3 unQuantize(const unsigned short* vecIn) const
+ {
+ btVector3 vecOut;
+ vecOut.setValue(
+ (btScalar)(vecIn[0]) / (m_bvhQuantization.getX()),
+ (btScalar)(vecIn[1]) / (m_bvhQuantization.getY()),
+ (btScalar)(vecIn[2]) / (m_bvhQuantization.getZ()));
+ vecOut += m_bvhAabbMin;
+ return vecOut;
+ }
+
+ ///setTraversalMode let's you choose between stackless, recursive or stackless cache friendly tree traversal. Note this is only implemented for quantized trees.
+ void setTraversalMode(btTraversalMode traversalMode)
+ {
+ m_traversalMode = traversalMode;
+ }
+
+
+ SIMD_FORCE_INLINE QuantizedNodeArray& getQuantizedNodeArray()
+ {
+ return m_quantizedContiguousNodes;
+ }
+
+
+ SIMD_FORCE_INLINE BvhSubtreeInfoArray& getSubtreeInfoArray()
+ {
+ return m_SubtreeHeaders;
+ }
+
+////////////////////////////////////////////////////////////////////
+
+ /////Calculate space needed to store BVH for serialization
+ unsigned calculateSerializeBufferSize() const;
+
+ /// Data buffer MUST be 16 byte aligned
+ virtual bool serialize(void *o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian) const;
+
+ ///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place'
+ static btQuantizedBvh *deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian);
+
+ static unsigned int getAlignmentSerializationPadding();
+//////////////////////////////////////////////////////////////////////
+
+
+ virtual int calculateSerializeBufferSizeNew() const;
+
+ ///fills the dataBuffer and returns the struct name (and 0 on failure)
+ virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
+
+ virtual void deSerializeFloat(struct btQuantizedBvhFloatData& quantizedBvhFloatData);
+
+ virtual void deSerializeDouble(struct btQuantizedBvhDoubleData& quantizedBvhDoubleData);
+
+
+////////////////////////////////////////////////////////////////////
+
+ SIMD_FORCE_INLINE bool isQuantized()
+ {
+ return m_useQuantization;
+ }
+
+private:
+ // Special "copy" constructor that allows for in-place deserialization
+ // Prevents btVector3's default constructor from being called, but doesn't inialize much else
+ // ownsMemory should most likely be false if deserializing, and if you are not, don't call this (it also changes the function signature, which we need)
+ btQuantizedBvh(btQuantizedBvh &other, bool ownsMemory);
+
+}
+;
+
+
+struct btBvhSubtreeInfoData
+{
+ int m_rootNodeIndex;
+ int m_subtreeSize;
+ unsigned short m_quantizedAabbMin[3];
+ unsigned short m_quantizedAabbMax[3];
+};
+
+struct btOptimizedBvhNodeFloatData
+{
+ btVector3FloatData m_aabbMinOrg;
+ btVector3FloatData m_aabbMaxOrg;
+ int m_escapeIndex;
+ int m_subPart;
+ int m_triangleIndex;
+ char m_pad[4];
+};
+
+struct btOptimizedBvhNodeDoubleData
+{
+ btVector3DoubleData m_aabbMinOrg;
+ btVector3DoubleData m_aabbMaxOrg;
+ int m_escapeIndex;
+ int m_subPart;
+ int m_triangleIndex;
+ char m_pad[4];
+};
+
+
+struct btQuantizedBvhNodeData
+{
+ unsigned short m_quantizedAabbMin[3];
+ unsigned short m_quantizedAabbMax[3];
+ int m_escapeIndexOrTriangleIndex;
+};
+
+struct btQuantizedBvhFloatData
+{
+ btVector3FloatData m_bvhAabbMin;
+ btVector3FloatData m_bvhAabbMax;
+ btVector3FloatData m_bvhQuantization;
+ int m_curNodeIndex;
+ int m_useQuantization;
+ int m_numContiguousLeafNodes;
+ int m_numQuantizedContiguousNodes;
+ btOptimizedBvhNodeFloatData *m_contiguousNodesPtr;
+ btQuantizedBvhNodeData *m_quantizedContiguousNodesPtr;
+ btBvhSubtreeInfoData *m_subTreeInfoPtr;
+ int m_traversalMode;
+ int m_numSubtreeHeaders;
+
+};
+
+struct btQuantizedBvhDoubleData
+{
+ btVector3DoubleData m_bvhAabbMin;
+ btVector3DoubleData m_bvhAabbMax;
+ btVector3DoubleData m_bvhQuantization;
+ int m_curNodeIndex;
+ int m_useQuantization;
+ int m_numContiguousLeafNodes;
+ int m_numQuantizedContiguousNodes;
+ btOptimizedBvhNodeDoubleData *m_contiguousNodesPtr;
+ btQuantizedBvhNodeData *m_quantizedContiguousNodesPtr;
+
+ int m_traversalMode;
+ int m_numSubtreeHeaders;
+ btBvhSubtreeInfoData *m_subTreeInfoPtr;
+};
+
+
+SIMD_FORCE_INLINE int btQuantizedBvh::calculateSerializeBufferSizeNew() const
+{
+ return sizeof(btQuantizedBvhData);
+}
+
+
+
+#endif //BT_QUANTIZED_BVH_H
diff --git a/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp b/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp
new file mode 100644
index 0000000000..f1d5f5476e
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp
@@ -0,0 +1,349 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btSimpleBroadphase.h"
+#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
+#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
+
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btTransform.h"
+#include "LinearMath/btMatrix3x3.h"
+#include "LinearMath/btAabbUtil2.h"
+
+#include <new>
+
+extern int gOverlappingPairs;
+
+void btSimpleBroadphase::validate()
+{
+ for (int i=0;i<m_numHandles;i++)
+ {
+ for (int j=i+1;j<m_numHandles;j++)
+ {
+ btAssert(&m_pHandles[i] != &m_pHandles[j]);
+ }
+ }
+
+}
+
+btSimpleBroadphase::btSimpleBroadphase(int maxProxies, btOverlappingPairCache* overlappingPairCache)
+ :m_pairCache(overlappingPairCache),
+ m_ownsPairCache(false),
+ m_invalidPair(0)
+{
+
+ if (!overlappingPairCache)
+ {
+ void* mem = btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16);
+ m_pairCache = new (mem)btHashedOverlappingPairCache();
+ m_ownsPairCache = true;
+ }
+
+ // allocate handles buffer and put all handles on free list
+ m_pHandlesRawPtr = btAlignedAlloc(sizeof(btSimpleBroadphaseProxy)*maxProxies,16);
+ m_pHandles = new(m_pHandlesRawPtr) btSimpleBroadphaseProxy[maxProxies];
+ m_maxHandles = maxProxies;
+ m_numHandles = 0;
+ m_firstFreeHandle = 0;
+ m_LastHandleIndex = -1;
+
+
+ {
+ for (int i = m_firstFreeHandle; i < maxProxies; i++)
+ {
+ m_pHandles[i].SetNextFree(i + 1);
+ m_pHandles[i].m_uniqueId = i+2;//any UID will do, we just avoid too trivial values (0,1) for debugging purposes
+ }
+ m_pHandles[maxProxies - 1].SetNextFree(0);
+
+ }
+
+}
+
+btSimpleBroadphase::~btSimpleBroadphase()
+{
+ btAlignedFree(m_pHandlesRawPtr);
+
+ if (m_ownsPairCache)
+ {
+ m_pairCache->~btOverlappingPairCache();
+ btAlignedFree(m_pairCache);
+ }
+}
+
+
+btBroadphaseProxy* btSimpleBroadphase::createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr , int collisionFilterGroup, int collisionFilterMask, btDispatcher* /*dispatcher*/)
+{
+ if (m_numHandles >= m_maxHandles)
+ {
+ btAssert(0);
+ return 0; //should never happen, but don't let the game crash ;-)
+ }
+ btAssert(aabbMin[0]<= aabbMax[0] && aabbMin[1]<= aabbMax[1] && aabbMin[2]<= aabbMax[2]);
+
+ int newHandleIndex = allocHandle();
+ btSimpleBroadphaseProxy* proxy = new (&m_pHandles[newHandleIndex])btSimpleBroadphaseProxy(aabbMin,aabbMax,shapeType,userPtr,collisionFilterGroup,collisionFilterMask);
+
+ return proxy;
+}
+
+class RemovingOverlapCallback : public btOverlapCallback
+{
+protected:
+ virtual bool processOverlap(btBroadphasePair& pair)
+ {
+ (void)pair;
+ btAssert(0);
+ return false;
+ }
+};
+
+class RemovePairContainingProxy
+{
+
+ btBroadphaseProxy* m_targetProxy;
+ public:
+ virtual ~RemovePairContainingProxy()
+ {
+ }
+protected:
+ virtual bool processOverlap(btBroadphasePair& pair)
+ {
+ btSimpleBroadphaseProxy* proxy0 = static_cast<btSimpleBroadphaseProxy*>(pair.m_pProxy0);
+ btSimpleBroadphaseProxy* proxy1 = static_cast<btSimpleBroadphaseProxy*>(pair.m_pProxy1);
+
+ return ((m_targetProxy == proxy0 || m_targetProxy == proxy1));
+ };
+};
+
+void btSimpleBroadphase::destroyProxy(btBroadphaseProxy* proxyOrg,btDispatcher* dispatcher)
+{
+
+ btSimpleBroadphaseProxy* proxy0 = static_cast<btSimpleBroadphaseProxy*>(proxyOrg);
+ freeHandle(proxy0);
+
+ m_pairCache->removeOverlappingPairsContainingProxy(proxyOrg,dispatcher);
+
+ //validate();
+
+}
+
+void btSimpleBroadphase::getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const
+{
+ const btSimpleBroadphaseProxy* sbp = getSimpleProxyFromProxy(proxy);
+ aabbMin = sbp->m_aabbMin;
+ aabbMax = sbp->m_aabbMax;
+}
+
+void btSimpleBroadphase::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* /*dispatcher*/)
+{
+ btSimpleBroadphaseProxy* sbp = getSimpleProxyFromProxy(proxy);
+ sbp->m_aabbMin = aabbMin;
+ sbp->m_aabbMax = aabbMax;
+}
+
+void btSimpleBroadphase::rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin,const btVector3& aabbMax)
+{
+ for (int i=0; i <= m_LastHandleIndex; i++)
+ {
+ btSimpleBroadphaseProxy* proxy = &m_pHandles[i];
+ if(!proxy->m_clientObject)
+ {
+ continue;
+ }
+ rayCallback.process(proxy);
+ }
+}
+
+
+void btSimpleBroadphase::aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback)
+{
+ for (int i=0; i <= m_LastHandleIndex; i++)
+ {
+ btSimpleBroadphaseProxy* proxy = &m_pHandles[i];
+ if(!proxy->m_clientObject)
+ {
+ continue;
+ }
+ if (TestAabbAgainstAabb2(aabbMin,aabbMax,proxy->m_aabbMin,proxy->m_aabbMax))
+ {
+ callback.process(proxy);
+ }
+ }
+}
+
+
+
+
+
+
+
+bool btSimpleBroadphase::aabbOverlap(btSimpleBroadphaseProxy* proxy0,btSimpleBroadphaseProxy* proxy1)
+{
+ return proxy0->m_aabbMin[0] <= proxy1->m_aabbMax[0] && proxy1->m_aabbMin[0] <= proxy0->m_aabbMax[0] &&
+ proxy0->m_aabbMin[1] <= proxy1->m_aabbMax[1] && proxy1->m_aabbMin[1] <= proxy0->m_aabbMax[1] &&
+ proxy0->m_aabbMin[2] <= proxy1->m_aabbMax[2] && proxy1->m_aabbMin[2] <= proxy0->m_aabbMax[2];
+
+}
+
+
+
+//then remove non-overlapping ones
+class CheckOverlapCallback : public btOverlapCallback
+{
+public:
+ virtual bool processOverlap(btBroadphasePair& pair)
+ {
+ return (!btSimpleBroadphase::aabbOverlap(static_cast<btSimpleBroadphaseProxy*>(pair.m_pProxy0),static_cast<btSimpleBroadphaseProxy*>(pair.m_pProxy1)));
+ }
+};
+
+void btSimpleBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
+{
+ //first check for new overlapping pairs
+ int i,j;
+ if (m_numHandles >= 0)
+ {
+ int new_largest_index = -1;
+ for (i=0; i <= m_LastHandleIndex; i++)
+ {
+ btSimpleBroadphaseProxy* proxy0 = &m_pHandles[i];
+ if(!proxy0->m_clientObject)
+ {
+ continue;
+ }
+ new_largest_index = i;
+ for (j=i+1; j <= m_LastHandleIndex; j++)
+ {
+ btSimpleBroadphaseProxy* proxy1 = &m_pHandles[j];
+ btAssert(proxy0 != proxy1);
+ if(!proxy1->m_clientObject)
+ {
+ continue;
+ }
+
+ btSimpleBroadphaseProxy* p0 = getSimpleProxyFromProxy(proxy0);
+ btSimpleBroadphaseProxy* p1 = getSimpleProxyFromProxy(proxy1);
+
+ if (aabbOverlap(p0,p1))
+ {
+ if ( !m_pairCache->findPair(proxy0,proxy1))
+ {
+ m_pairCache->addOverlappingPair(proxy0,proxy1);
+ }
+ } else
+ {
+ if (!m_pairCache->hasDeferredRemoval())
+ {
+ if ( m_pairCache->findPair(proxy0,proxy1))
+ {
+ m_pairCache->removeOverlappingPair(proxy0,proxy1,dispatcher);
+ }
+ }
+ }
+ }
+ }
+
+ m_LastHandleIndex = new_largest_index;
+
+ if (m_ownsPairCache && m_pairCache->hasDeferredRemoval())
+ {
+
+ btBroadphasePairArray& overlappingPairArray = m_pairCache->getOverlappingPairArray();
+
+ //perform a sort, to find duplicates and to sort 'invalid' pairs to the end
+ overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
+
+ overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
+ m_invalidPair = 0;
+
+
+ btBroadphasePair previousPair;
+ previousPair.m_pProxy0 = 0;
+ previousPair.m_pProxy1 = 0;
+ previousPair.m_algorithm = 0;
+
+
+ for (i=0;i<overlappingPairArray.size();i++)
+ {
+
+ btBroadphasePair& pair = overlappingPairArray[i];
+
+ bool isDuplicate = (pair == previousPair);
+
+ previousPair = pair;
+
+ bool needsRemoval = false;
+
+ if (!isDuplicate)
+ {
+ bool hasOverlap = testAabbOverlap(pair.m_pProxy0,pair.m_pProxy1);
+
+ if (hasOverlap)
+ {
+ needsRemoval = false;//callback->processOverlap(pair);
+ } else
+ {
+ needsRemoval = true;
+ }
+ } else
+ {
+ //remove duplicate
+ needsRemoval = true;
+ //should have no algorithm
+ btAssert(!pair.m_algorithm);
+ }
+
+ if (needsRemoval)
+ {
+ m_pairCache->cleanOverlappingPair(pair,dispatcher);
+
+ // m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1);
+ // m_overlappingPairArray.pop_back();
+ pair.m_pProxy0 = 0;
+ pair.m_pProxy1 = 0;
+ m_invalidPair++;
+ gOverlappingPairs--;
+ }
+
+ }
+
+ ///if you don't like to skip the invalid pairs in the array, execute following code:
+#define CLEAN_INVALID_PAIRS 1
+#ifdef CLEAN_INVALID_PAIRS
+
+ //perform a sort, to sort 'invalid' pairs to the end
+ overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
+
+ overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
+ m_invalidPair = 0;
+#endif//CLEAN_INVALID_PAIRS
+
+ }
+ }
+}
+
+
+bool btSimpleBroadphase::testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
+{
+ btSimpleBroadphaseProxy* p0 = getSimpleProxyFromProxy(proxy0);
+ btSimpleBroadphaseProxy* p1 = getSimpleProxyFromProxy(proxy1);
+ return aabbOverlap(p0,p1);
+}
+
+void btSimpleBroadphase::resetPool(btDispatcher* dispatcher)
+{
+ //not yet
+}
diff --git a/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h b/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h
new file mode 100644
index 0000000000..d7a18e400a
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h
@@ -0,0 +1,171 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_SIMPLE_BROADPHASE_H
+#define BT_SIMPLE_BROADPHASE_H
+
+
+#include "btOverlappingPairCache.h"
+
+
+struct btSimpleBroadphaseProxy : public btBroadphaseProxy
+{
+ int m_nextFree;
+
+// int m_handleId;
+
+
+ btSimpleBroadphaseProxy() {};
+
+ btSimpleBroadphaseProxy(const btVector3& minpt,const btVector3& maxpt,int shapeType,void* userPtr, int collisionFilterGroup, int collisionFilterMask)
+ :btBroadphaseProxy(minpt,maxpt,userPtr,collisionFilterGroup,collisionFilterMask)
+ {
+ (void)shapeType;
+ }
+
+
+ SIMD_FORCE_INLINE void SetNextFree(int next) {m_nextFree = next;}
+ SIMD_FORCE_INLINE int GetNextFree() const {return m_nextFree;}
+
+
+
+
+};
+
+///The SimpleBroadphase is just a unit-test for btAxisSweep3, bt32BitAxisSweep3, or btDbvtBroadphase, so use those classes instead.
+///It is a brute force aabb culling broadphase based on O(n^2) aabb checks
+class btSimpleBroadphase : public btBroadphaseInterface
+{
+
+protected:
+
+ int m_numHandles; // number of active handles
+ int m_maxHandles; // max number of handles
+ int m_LastHandleIndex;
+
+ btSimpleBroadphaseProxy* m_pHandles; // handles pool
+
+ void* m_pHandlesRawPtr;
+ int m_firstFreeHandle; // free handles list
+
+ int allocHandle()
+ {
+ btAssert(m_numHandles < m_maxHandles);
+ int freeHandle = m_firstFreeHandle;
+ m_firstFreeHandle = m_pHandles[freeHandle].GetNextFree();
+ m_numHandles++;
+ if(freeHandle > m_LastHandleIndex)
+ {
+ m_LastHandleIndex = freeHandle;
+ }
+ return freeHandle;
+ }
+
+ void freeHandle(btSimpleBroadphaseProxy* proxy)
+ {
+ int handle = int(proxy-m_pHandles);
+ btAssert(handle >= 0 && handle < m_maxHandles);
+ if(handle == m_LastHandleIndex)
+ {
+ m_LastHandleIndex--;
+ }
+ proxy->SetNextFree(m_firstFreeHandle);
+ m_firstFreeHandle = handle;
+
+ proxy->m_clientObject = 0;
+
+ m_numHandles--;
+ }
+
+ btOverlappingPairCache* m_pairCache;
+ bool m_ownsPairCache;
+
+ int m_invalidPair;
+
+
+
+ inline btSimpleBroadphaseProxy* getSimpleProxyFromProxy(btBroadphaseProxy* proxy)
+ {
+ btSimpleBroadphaseProxy* proxy0 = static_cast<btSimpleBroadphaseProxy*>(proxy);
+ return proxy0;
+ }
+
+ inline const btSimpleBroadphaseProxy* getSimpleProxyFromProxy(btBroadphaseProxy* proxy) const
+ {
+ const btSimpleBroadphaseProxy* proxy0 = static_cast<const btSimpleBroadphaseProxy*>(proxy);
+ return proxy0;
+ }
+
+ ///reset broadphase internal structures, to ensure determinism/reproducability
+ virtual void resetPool(btDispatcher* dispatcher);
+
+
+ void validate();
+
+protected:
+
+
+
+
+public:
+ btSimpleBroadphase(int maxProxies=16384,btOverlappingPairCache* overlappingPairCache=0);
+ virtual ~btSimpleBroadphase();
+
+
+ static bool aabbOverlap(btSimpleBroadphaseProxy* proxy0,btSimpleBroadphaseProxy* proxy1);
+
+
+ virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr , int collisionFilterGroup, int collisionFilterMask, btDispatcher* dispatcher);
+
+ virtual void calculateOverlappingPairs(btDispatcher* dispatcher);
+
+ virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
+ virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher);
+ virtual void getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const;
+
+ virtual void rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin=btVector3(0,0,0),const btVector3& aabbMax=btVector3(0,0,0));
+ virtual void aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback);
+
+ btOverlappingPairCache* getOverlappingPairCache()
+ {
+ return m_pairCache;
+ }
+ const btOverlappingPairCache* getOverlappingPairCache() const
+ {
+ return m_pairCache;
+ }
+
+ bool testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
+
+
+ ///getAabb returns the axis aligned bounding box in the 'global' coordinate frame
+ ///will add some transform later
+ virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const
+ {
+ aabbMin.setValue(-BT_LARGE_FLOAT,-BT_LARGE_FLOAT,-BT_LARGE_FLOAT);
+ aabbMax.setValue(BT_LARGE_FLOAT,BT_LARGE_FLOAT,BT_LARGE_FLOAT);
+ }
+
+ virtual void printStats()
+ {
+// printf("btSimpleBroadphase.h\n");
+// printf("numHandles = %d, maxHandles = %d\n",m_numHandles,m_maxHandles);
+ }
+};
+
+
+
+#endif //BT_SIMPLE_BROADPHASE_H
+
diff --git a/thirdparty/bullet/src/BulletCollision/CMakeLists.txt b/thirdparty/bullet/src/BulletCollision/CMakeLists.txt
new file mode 100644
index 0000000000..85c5fc8b64
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CMakeLists.txt
@@ -0,0 +1,292 @@
+INCLUDE_DIRECTORIES( ${BULLET_PHYSICS_SOURCE_DIR}/src )
+
+SET(BulletCollision_SRCS
+ BroadphaseCollision/btAxisSweep3.cpp
+ BroadphaseCollision/btBroadphaseProxy.cpp
+ BroadphaseCollision/btCollisionAlgorithm.cpp
+ BroadphaseCollision/btDbvt.cpp
+ BroadphaseCollision/btDbvtBroadphase.cpp
+ BroadphaseCollision/btDispatcher.cpp
+ BroadphaseCollision/btOverlappingPairCache.cpp
+ BroadphaseCollision/btQuantizedBvh.cpp
+ BroadphaseCollision/btSimpleBroadphase.cpp
+ CollisionDispatch/btActivatingCollisionAlgorithm.cpp
+ CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp
+ CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp
+ CollisionDispatch/btBoxBoxDetector.cpp
+ CollisionDispatch/btCollisionDispatcher.cpp
+ CollisionDispatch/btCollisionDispatcherMt.cpp
+ CollisionDispatch/btCollisionObject.cpp
+ CollisionDispatch/btCollisionWorld.cpp
+ CollisionDispatch/btCollisionWorldImporter.cpp
+ CollisionDispatch/btCompoundCollisionAlgorithm.cpp
+ CollisionDispatch/btCompoundCompoundCollisionAlgorithm.cpp
+ CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp
+ CollisionDispatch/btConvexConvexAlgorithm.cpp
+ CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp
+ CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp
+ CollisionDispatch/btDefaultCollisionConfiguration.cpp
+ CollisionDispatch/btEmptyCollisionAlgorithm.cpp
+ CollisionDispatch/btGhostObject.cpp
+ CollisionDispatch/btHashedSimplePairCache.cpp
+ CollisionDispatch/btInternalEdgeUtility.cpp
+ CollisionDispatch/btInternalEdgeUtility.h
+ CollisionDispatch/btManifoldResult.cpp
+ CollisionDispatch/btSimulationIslandManager.cpp
+ CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp
+ CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp
+ CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp
+ CollisionDispatch/btUnionFind.cpp
+ CollisionDispatch/SphereTriangleDetector.cpp
+ CollisionShapes/btBoxShape.cpp
+ CollisionShapes/btBox2dShape.cpp
+ CollisionShapes/btBvhTriangleMeshShape.cpp
+ CollisionShapes/btCapsuleShape.cpp
+ CollisionShapes/btCollisionShape.cpp
+ CollisionShapes/btCompoundShape.cpp
+ CollisionShapes/btConcaveShape.cpp
+ CollisionShapes/btConeShape.cpp
+ CollisionShapes/btConvexHullShape.cpp
+ CollisionShapes/btConvexInternalShape.cpp
+ CollisionShapes/btConvexPointCloudShape.cpp
+ CollisionShapes/btConvexPolyhedron.cpp
+ CollisionShapes/btConvexShape.cpp
+ CollisionShapes/btConvex2dShape.cpp
+ CollisionShapes/btConvexTriangleMeshShape.cpp
+ CollisionShapes/btCylinderShape.cpp
+ CollisionShapes/btEmptyShape.cpp
+ CollisionShapes/btHeightfieldTerrainShape.cpp
+ CollisionShapes/btMinkowskiSumShape.cpp
+ CollisionShapes/btMultimaterialTriangleMeshShape.cpp
+ CollisionShapes/btMultiSphereShape.cpp
+ CollisionShapes/btOptimizedBvh.cpp
+ CollisionShapes/btPolyhedralConvexShape.cpp
+ CollisionShapes/btScaledBvhTriangleMeshShape.cpp
+ CollisionShapes/btShapeHull.cpp
+ CollisionShapes/btSphereShape.cpp
+ CollisionShapes/btStaticPlaneShape.cpp
+ CollisionShapes/btStridingMeshInterface.cpp
+ CollisionShapes/btTetrahedronShape.cpp
+ CollisionShapes/btTriangleBuffer.cpp
+ CollisionShapes/btTriangleCallback.cpp
+ CollisionShapes/btTriangleIndexVertexArray.cpp
+ CollisionShapes/btTriangleIndexVertexMaterialArray.cpp
+ CollisionShapes/btTriangleMesh.cpp
+ CollisionShapes/btTriangleMeshShape.cpp
+ CollisionShapes/btUniformScalingShape.cpp
+ Gimpact/btContactProcessing.cpp
+ Gimpact/btGenericPoolAllocator.cpp
+ Gimpact/btGImpactBvh.cpp
+ Gimpact/btGImpactCollisionAlgorithm.cpp
+ Gimpact/btGImpactQuantizedBvh.cpp
+ Gimpact/btGImpactShape.cpp
+ Gimpact/btTriangleShapeEx.cpp
+ Gimpact/gim_box_set.cpp
+ Gimpact/gim_contact.cpp
+ Gimpact/gim_memory.cpp
+ Gimpact/gim_tri_collision.cpp
+ NarrowPhaseCollision/btContinuousConvexCollision.cpp
+ NarrowPhaseCollision/btConvexCast.cpp
+ NarrowPhaseCollision/btGjkConvexCast.cpp
+ NarrowPhaseCollision/btGjkEpa2.cpp
+ NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp
+ NarrowPhaseCollision/btGjkPairDetector.cpp
+ NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp
+ NarrowPhaseCollision/btPersistentManifold.cpp
+ NarrowPhaseCollision/btRaycastCallback.cpp
+ NarrowPhaseCollision/btSubSimplexConvexCast.cpp
+ NarrowPhaseCollision/btVoronoiSimplexSolver.cpp
+ NarrowPhaseCollision/btPolyhedralContactClipping.cpp
+)
+
+SET(Root_HDRS
+ ../btBulletCollisionCommon.h
+)
+SET(BroadphaseCollision_HDRS
+ BroadphaseCollision/btAxisSweep3Internal.h
+ BroadphaseCollision/btAxisSweep3.h
+ BroadphaseCollision/btBroadphaseInterface.h
+ BroadphaseCollision/btBroadphaseProxy.h
+ BroadphaseCollision/btCollisionAlgorithm.h
+ BroadphaseCollision/btDbvt.h
+ BroadphaseCollision/btDbvtBroadphase.h
+ BroadphaseCollision/btDispatcher.h
+ BroadphaseCollision/btOverlappingPairCache.h
+ BroadphaseCollision/btOverlappingPairCallback.h
+ BroadphaseCollision/btQuantizedBvh.h
+ BroadphaseCollision/btSimpleBroadphase.h
+)
+SET(CollisionDispatch_HDRS
+ CollisionDispatch/btActivatingCollisionAlgorithm.h
+ CollisionDispatch/btBoxBoxCollisionAlgorithm.h
+ CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h
+ CollisionDispatch/btBoxBoxDetector.h
+ CollisionDispatch/btCollisionConfiguration.h
+ CollisionDispatch/btCollisionCreateFunc.h
+ CollisionDispatch/btCollisionDispatcher.h
+ CollisionDispatch/btCollisionDispatcherMt.h
+ CollisionDispatch/btCollisionObject.h
+ CollisionDispatch/btCollisionObjectWrapper.h
+ CollisionDispatch/btCollisionWorld.h
+ CollisionDispatch/btCollisionWorldImporter.h
+ CollisionDispatch/btCompoundCollisionAlgorithm.h
+ CollisionDispatch/btCompoundCompoundCollisionAlgorithm.h
+ CollisionDispatch/btConvexConcaveCollisionAlgorithm.h
+ CollisionDispatch/btConvexConvexAlgorithm.h
+ CollisionDispatch/btConvex2dConvex2dAlgorithm.h
+ CollisionDispatch/btConvexPlaneCollisionAlgorithm.h
+ CollisionDispatch/btDefaultCollisionConfiguration.h
+ CollisionDispatch/btEmptyCollisionAlgorithm.h
+ CollisionDispatch/btGhostObject.h
+ CollisionDispatch/btHashedSimplePairCache.h
+ CollisionDispatch/btManifoldResult.h
+ CollisionDispatch/btSimulationIslandManager.h
+ CollisionDispatch/btSphereBoxCollisionAlgorithm.h
+ CollisionDispatch/btSphereSphereCollisionAlgorithm.h
+ CollisionDispatch/btSphereTriangleCollisionAlgorithm.h
+ CollisionDispatch/btUnionFind.h
+ CollisionDispatch/SphereTriangleDetector.h
+)
+SET(CollisionShapes_HDRS
+ CollisionShapes/btBoxShape.h
+ CollisionShapes/btBox2dShape.h
+ CollisionShapes/btBvhTriangleMeshShape.h
+ CollisionShapes/btCapsuleShape.h
+ CollisionShapes/btCollisionMargin.h
+ CollisionShapes/btCollisionShape.h
+ CollisionShapes/btCompoundShape.h
+ CollisionShapes/btConcaveShape.h
+ CollisionShapes/btConeShape.h
+ CollisionShapes/btConvexHullShape.h
+ CollisionShapes/btConvexInternalShape.h
+ CollisionShapes/btConvexPointCloudShape.h
+ CollisionShapes/btConvexPolyhedron.h
+ CollisionShapes/btConvexShape.h
+ CollisionShapes/btConvex2dShape.h
+ CollisionShapes/btConvexTriangleMeshShape.h
+ CollisionShapes/btCylinderShape.h
+ CollisionShapes/btEmptyShape.h
+ CollisionShapes/btHeightfieldTerrainShape.h
+ CollisionShapes/btMaterial.h
+ CollisionShapes/btMinkowskiSumShape.h
+ CollisionShapes/btMultimaterialTriangleMeshShape.h
+ CollisionShapes/btMultiSphereShape.h
+ CollisionShapes/btOptimizedBvh.h
+ CollisionShapes/btPolyhedralConvexShape.h
+ CollisionShapes/btScaledBvhTriangleMeshShape.h
+ CollisionShapes/btShapeHull.h
+ CollisionShapes/btSphereShape.h
+ CollisionShapes/btStaticPlaneShape.h
+ CollisionShapes/btStridingMeshInterface.h
+ CollisionShapes/btTetrahedronShape.h
+ CollisionShapes/btTriangleBuffer.h
+ CollisionShapes/btTriangleCallback.h
+ CollisionShapes/btTriangleIndexVertexArray.h
+ CollisionShapes/btTriangleIndexVertexMaterialArray.h
+ CollisionShapes/btTriangleInfoMap.h
+ CollisionShapes/btTriangleMesh.h
+ CollisionShapes/btTriangleMeshShape.h
+ CollisionShapes/btTriangleShape.h
+ CollisionShapes/btUniformScalingShape.h
+)
+SET(Gimpact_HDRS
+ Gimpact/btBoxCollision.h
+ Gimpact/btClipPolygon.h
+ Gimpact/btContactProcessingStructs.h
+ Gimpact/btContactProcessing.h
+ Gimpact/btGenericPoolAllocator.h
+ Gimpact/btGeometryOperations.h
+ Gimpact/btGImpactBvhStructs.h
+ Gimpact/btGImpactBvh.h
+ Gimpact/btGImpactCollisionAlgorithm.h
+ Gimpact/btGImpactMassUtil.h
+ Gimpact/btGImpactQuantizedBvhStructs.h
+ Gimpact/btGImpactQuantizedBvh.h
+ Gimpact/btGImpactShape.h
+ Gimpact/btQuantization.h
+ Gimpact/btTriangleShapeEx.h
+ Gimpact/gim_array.h
+ Gimpact/gim_basic_geometry_operations.h
+ Gimpact/gim_bitset.h
+ Gimpact/gim_box_collision.h
+ Gimpact/gim_box_set.h
+ Gimpact/gim_clip_polygon.h
+ Gimpact/gim_contact.h
+ Gimpact/gim_geom_types.h
+ Gimpact/gim_geometry.h
+ Gimpact/gim_hash_table.h
+ Gimpact/gim_linear_math.h
+ Gimpact/gim_math.h
+ Gimpact/gim_memory.h
+ Gimpact/gim_radixsort.h
+ Gimpact/gim_tri_collision.h
+)
+SET(NarrowPhaseCollision_HDRS
+ NarrowPhaseCollision/btContinuousConvexCollision.h
+ NarrowPhaseCollision/btConvexCast.h
+ NarrowPhaseCollision/btConvexPenetrationDepthSolver.h
+ NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h
+ NarrowPhaseCollision/btGjkConvexCast.h
+ NarrowPhaseCollision/btGjkEpa2.h
+ NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h
+ NarrowPhaseCollision/btGjkPairDetector.h
+ NarrowPhaseCollision/btManifoldPoint.h
+ NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h
+ NarrowPhaseCollision/btPersistentManifold.h
+ NarrowPhaseCollision/btPointCollector.h
+ NarrowPhaseCollision/btRaycastCallback.h
+ NarrowPhaseCollision/btSimplexSolverInterface.h
+ NarrowPhaseCollision/btSubSimplexConvexCast.h
+ NarrowPhaseCollision/btVoronoiSimplexSolver.h
+ NarrowPhaseCollision/btPolyhedralContactClipping.h
+)
+
+SET(BulletCollision_HDRS
+ ${Root_HDRS}
+ ${BroadphaseCollision_HDRS}
+ ${CollisionDispatch_HDRS}
+ ${CollisionShapes_HDRS}
+ ${Gimpact_HDRS}
+ ${NarrowPhaseCollision_HDRS}
+)
+
+
+ADD_LIBRARY(BulletCollision ${BulletCollision_SRCS} ${BulletCollision_HDRS})
+SET_TARGET_PROPERTIES(BulletCollision PROPERTIES VERSION ${BULLET_VERSION})
+SET_TARGET_PROPERTIES(BulletCollision PROPERTIES SOVERSION ${BULLET_VERSION})
+IF (BUILD_SHARED_LIBS)
+ TARGET_LINK_LIBRARIES(BulletCollision LinearMath)
+ENDIF (BUILD_SHARED_LIBS)
+
+
+IF (INSTALL_LIBS)
+ IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
+ #INSTALL of other files requires CMake 2.6
+ IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
+ IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+ INSTALL(TARGETS BulletCollision DESTINATION .)
+ ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+ INSTALL(TARGETS BulletCollision RUNTIME DESTINATION bin
+ LIBRARY DESTINATION lib${LIB_SUFFIX}
+ ARCHIVE DESTINATION lib${LIB_SUFFIX})
+ INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.h" PATTERN ".svn" EXCLUDE PATTERN "CMakeFiles" EXCLUDE)
+ INSTALL(FILES ../btBulletCollisionCommon.h
+DESTINATION ${INCLUDE_INSTALL_DIR}/BulletCollision)
+ ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+ ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
+
+ IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+ SET_TARGET_PROPERTIES(BulletCollision PROPERTIES FRAMEWORK true)
+
+ SET_TARGET_PROPERTIES(BulletCollision PROPERTIES PUBLIC_HEADER "${Root_HDRS}")
+ # Have to list out sub-directories manually:
+ SET_PROPERTY(SOURCE ${BroadphaseCollision_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/BroadphaseCollision)
+ SET_PROPERTY(SOURCE ${CollisionDispatch_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/CollisionDispatch)
+ SET_PROPERTY(SOURCE ${CollisionShapes_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/CollisionShapes)
+ SET_PROPERTY(SOURCE ${Gimpact_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/Gimpact)
+ SET_PROPERTY(SOURCE ${NarrowPhaseCollision_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/NarrowPhaseCollision)
+
+ ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+ ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
+ENDIF (INSTALL_LIBS)
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp
new file mode 100644
index 0000000000..c81af95672
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp
@@ -0,0 +1,209 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "LinearMath/btScalar.h"
+#include "SphereTriangleDetector.h"
+#include "BulletCollision/CollisionShapes/btTriangleShape.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"
+
+
+SphereTriangleDetector::SphereTriangleDetector(btSphereShape* sphere,btTriangleShape* triangle,btScalar contactBreakingThreshold)
+:m_sphere(sphere),
+m_triangle(triangle),
+m_contactBreakingThreshold(contactBreakingThreshold)
+{
+
+}
+
+void SphereTriangleDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults)
+{
+
+ (void)debugDraw;
+ const btTransform& transformA = input.m_transformA;
+ const btTransform& transformB = input.m_transformB;
+
+ btVector3 point,normal;
+ btScalar timeOfImpact = btScalar(1.);
+ btScalar depth = btScalar(0.);
+// output.m_distance = btScalar(BT_LARGE_FLOAT);
+ //move sphere into triangle space
+ btTransform sphereInTr = transformB.inverseTimes(transformA);
+
+ if (collide(sphereInTr.getOrigin(),point,normal,depth,timeOfImpact,m_contactBreakingThreshold))
+ {
+ if (swapResults)
+ {
+ btVector3 normalOnB = transformB.getBasis()*normal;
+ btVector3 normalOnA = -normalOnB;
+ btVector3 pointOnA = transformB*point+normalOnB*depth;
+ output.addContactPoint(normalOnA,pointOnA,depth);
+ } else
+ {
+ output.addContactPoint(transformB.getBasis()*normal,transformB*point,depth);
+ }
+ }
+
+}
+
+
+
+// See also geometrictools.com
+// Basic idea: D = |p - (lo + t0*lv)| where t0 = lv . (p - lo) / lv . lv
+btScalar SegmentSqrDistance(const btVector3& from, const btVector3& to,const btVector3 &p, btVector3 &nearest);
+
+btScalar SegmentSqrDistance(const btVector3& from, const btVector3& to,const btVector3 &p, btVector3 &nearest) {
+ btVector3 diff = p - from;
+ btVector3 v = to - from;
+ btScalar t = v.dot(diff);
+
+ if (t > 0) {
+ btScalar dotVV = v.dot(v);
+ if (t < dotVV) {
+ t /= dotVV;
+ diff -= t*v;
+ } else {
+ t = 1;
+ diff -= v;
+ }
+ } else
+ t = 0;
+
+ nearest = from + t*v;
+ return diff.dot(diff);
+}
+
+bool SphereTriangleDetector::facecontains(const btVector3 &p,const btVector3* vertices,btVector3& normal) {
+ btVector3 lp(p);
+ btVector3 lnormal(normal);
+
+ return pointInTriangle(vertices, lnormal, &lp);
+}
+
+bool SphereTriangleDetector::collide(const btVector3& sphereCenter,btVector3 &point, btVector3& resultNormal, btScalar& depth, btScalar &timeOfImpact, btScalar contactBreakingThreshold)
+{
+
+ const btVector3* vertices = &m_triangle->getVertexPtr(0);
+
+ btScalar radius = m_sphere->getRadius();
+ btScalar radiusWithThreshold = radius + contactBreakingThreshold;
+
+ btVector3 normal = (vertices[1]-vertices[0]).cross(vertices[2]-vertices[0]);
+
+ btScalar l2 = normal.length2();
+ bool hasContact = false;
+ btVector3 contactPoint;
+
+ if (l2 >= SIMD_EPSILON*SIMD_EPSILON)
+ {
+ normal /= btSqrt(l2);
+
+ btVector3 p1ToCentre = sphereCenter - vertices[0];
+ btScalar distanceFromPlane = p1ToCentre.dot(normal);
+
+ if (distanceFromPlane < btScalar(0.))
+ {
+ //triangle facing the other way
+ distanceFromPlane *= btScalar(-1.);
+ normal *= btScalar(-1.);
+ }
+
+ bool isInsideContactPlane = distanceFromPlane < radiusWithThreshold;
+
+ // Check for contact / intersection
+
+ if (isInsideContactPlane) {
+ if (facecontains(sphereCenter, vertices, normal)) {
+ // Inside the contact wedge - touches a point on the shell plane
+ hasContact = true;
+ contactPoint = sphereCenter - normal*distanceFromPlane;
+ }
+ else {
+ // Could be inside one of the contact capsules
+ btScalar contactCapsuleRadiusSqr = radiusWithThreshold*radiusWithThreshold;
+ btVector3 nearestOnEdge;
+ for (int i = 0; i < m_triangle->getNumEdges(); i++) {
+
+ btVector3 pa;
+ btVector3 pb;
+
+ m_triangle->getEdge(i, pa, pb);
+
+ btScalar distanceSqr = SegmentSqrDistance(pa, pb, sphereCenter, nearestOnEdge);
+ if (distanceSqr < contactCapsuleRadiusSqr) {
+ // Yep, we're inside a capsule
+ hasContact = true;
+ contactPoint = nearestOnEdge;
+ }
+
+ }
+ }
+ }
+ }
+
+ if (hasContact) {
+ btVector3 contactToCentre = sphereCenter - contactPoint;
+ btScalar distanceSqr = contactToCentre.length2();
+
+ if (distanceSqr < radiusWithThreshold*radiusWithThreshold)
+ {
+ if (distanceSqr>SIMD_EPSILON)
+ {
+ btScalar distance = btSqrt(distanceSqr);
+ resultNormal = contactToCentre;
+ resultNormal.normalize();
+ point = contactPoint;
+ depth = -(radius-distance);
+ } else
+ {
+ resultNormal = normal;
+ point = contactPoint;
+ depth = -radius;
+ }
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+bool SphereTriangleDetector::pointInTriangle(const btVector3 vertices[], const btVector3 &normal, btVector3 *p )
+{
+ const btVector3* p1 = &vertices[0];
+ const btVector3* p2 = &vertices[1];
+ const btVector3* p3 = &vertices[2];
+
+ btVector3 edge1( *p2 - *p1 );
+ btVector3 edge2( *p3 - *p2 );
+ btVector3 edge3( *p1 - *p3 );
+
+ btVector3 p1_to_p( *p - *p1 );
+ btVector3 p2_to_p( *p - *p2 );
+ btVector3 p3_to_p( *p - *p3 );
+
+ btVector3 edge1_normal( edge1.cross(normal));
+ btVector3 edge2_normal( edge2.cross(normal));
+ btVector3 edge3_normal( edge3.cross(normal));
+
+ btScalar r1, r2, r3;
+ r1 = edge1_normal.dot( p1_to_p );
+ r2 = edge2_normal.dot( p2_to_p );
+ r3 = edge3_normal.dot( p3_to_p );
+ if ( ( r1 > 0 && r2 > 0 && r3 > 0 ) ||
+ ( r1 <= 0 && r2 <= 0 && r3 <= 0 ) )
+ return true;
+ return false;
+
+}
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h
new file mode 100644
index 0000000000..22953af43f
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h
@@ -0,0 +1,51 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_SPHERE_TRIANGLE_DETECTOR_H
+#define BT_SPHERE_TRIANGLE_DETECTOR_H
+
+#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
+
+
+
+class btSphereShape;
+class btTriangleShape;
+
+
+
+/// sphere-triangle to match the btDiscreteCollisionDetectorInterface
+struct SphereTriangleDetector : public btDiscreteCollisionDetectorInterface
+{
+ virtual void getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults=false);
+
+ SphereTriangleDetector(btSphereShape* sphere,btTriangleShape* triangle, btScalar contactBreakingThreshold);
+
+ virtual ~SphereTriangleDetector() {};
+
+ bool collide(const btVector3& sphereCenter,btVector3 &point, btVector3& resultNormal, btScalar& depth, btScalar &timeOfImpact, btScalar contactBreakingThreshold);
+
+private:
+
+
+ bool pointInTriangle(const btVector3 vertices[], const btVector3 &normal, btVector3 *p );
+ bool facecontains(const btVector3 &p,const btVector3* vertices,btVector3& normal);
+
+ btSphereShape* m_sphere;
+ btTriangleShape* m_triangle;
+ btScalar m_contactBreakingThreshold;
+
+};
+#endif //BT_SPHERE_TRIANGLE_DETECTOR_H
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp
new file mode 100644
index 0000000000..57f1464935
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp
@@ -0,0 +1,47 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com
+
+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 "btActivatingCollisionAlgorithm.h"
+#include "btCollisionDispatcher.h"
+#include "btCollisionObject.h"
+
+btActivatingCollisionAlgorithm::btActivatingCollisionAlgorithm (const btCollisionAlgorithmConstructionInfo& ci)
+:btCollisionAlgorithm(ci)
+//,
+//m_colObj0(0),
+//m_colObj1(0)
+{
+}
+btActivatingCollisionAlgorithm::btActivatingCollisionAlgorithm (const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* ,const btCollisionObjectWrapper* )
+:btCollisionAlgorithm(ci)
+//,
+//m_colObj0(0),
+//m_colObj1(0)
+{
+// if (ci.m_dispatcher1->needsCollision(colObj0,colObj1))
+// {
+// m_colObj0 = colObj0;
+// m_colObj1 = colObj1;
+//
+// m_colObj0->activate();
+// m_colObj1->activate();
+// }
+}
+
+btActivatingCollisionAlgorithm::~btActivatingCollisionAlgorithm()
+{
+// m_colObj0->activate();
+// m_colObj1->activate();
+}
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h
new file mode 100644
index 0000000000..0e19f1ea35
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h
@@ -0,0 +1,37 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com
+
+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_ACTIVATING_COLLISION_ALGORITHM_H
+#define __BT_ACTIVATING_COLLISION_ALGORITHM_H
+
+#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
+
+///This class is not enabled yet (work-in-progress) to more aggressively activate objects.
+class btActivatingCollisionAlgorithm : public btCollisionAlgorithm
+{
+// btCollisionObject* m_colObj0;
+// btCollisionObject* m_colObj1;
+
+protected:
+
+ btActivatingCollisionAlgorithm (const btCollisionAlgorithmConstructionInfo& ci);
+
+ btActivatingCollisionAlgorithm (const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap);
+
+public:
+ virtual ~btActivatingCollisionAlgorithm();
+
+};
+#endif //__BT_ACTIVATING_COLLISION_ALGORITHM_H
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp
new file mode 100644
index 0000000000..2c36277821
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp
@@ -0,0 +1,421 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+* The b2CollidePolygons routines are Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
+
+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.
+*/
+
+///btBox2dBox2dCollisionAlgorithm, with modified b2CollidePolygons routines from the Box2D library.
+///The modifications include: switching from b2Vec to btVector3, redefinition of b2Dot, b2Cross
+
+#include "btBox2dBox2dCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/CollisionShapes/btBoxShape.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/CollisionDispatch/btBoxBoxDetector.h"
+#include "BulletCollision/CollisionShapes/btBox2dShape.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
+
+#define USE_PERSISTENT_CONTACTS 1
+
+btBox2dBox2dCollisionAlgorithm::btBox2dBox2dCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* obj0Wrap,const btCollisionObjectWrapper* obj1Wrap)
+: btActivatingCollisionAlgorithm(ci,obj0Wrap,obj1Wrap),
+m_ownManifold(false),
+m_manifoldPtr(mf)
+{
+ if (!m_manifoldPtr && m_dispatcher->needsCollision(obj0Wrap->getCollisionObject(),obj1Wrap->getCollisionObject()))
+ {
+ m_manifoldPtr = m_dispatcher->getNewManifold(obj0Wrap->getCollisionObject(),obj1Wrap->getCollisionObject());
+ m_ownManifold = true;
+ }
+}
+
+btBox2dBox2dCollisionAlgorithm::~btBox2dBox2dCollisionAlgorithm()
+{
+
+ if (m_ownManifold)
+ {
+ if (m_manifoldPtr)
+ m_dispatcher->releaseManifold(m_manifoldPtr);
+ }
+
+}
+
+
+void b2CollidePolygons(btManifoldResult* manifold, const btBox2dShape* polyA, const btTransform& xfA, const btBox2dShape* polyB, const btTransform& xfB);
+
+//#include <stdio.h>
+void btBox2dBox2dCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+ if (!m_manifoldPtr)
+ return;
+
+
+ const btBox2dShape* box0 = (const btBox2dShape*)body0Wrap->getCollisionShape();
+ const btBox2dShape* box1 = (const btBox2dShape*)body1Wrap->getCollisionShape();
+
+ resultOut->setPersistentManifold(m_manifoldPtr);
+
+ b2CollidePolygons(resultOut,box0,body0Wrap->getWorldTransform(),box1,body1Wrap->getWorldTransform());
+
+ // refreshContactPoints is only necessary when using persistent contact points. otherwise all points are newly added
+ if (m_ownManifold)
+ {
+ resultOut->refreshContactPoints();
+ }
+
+}
+
+btScalar btBox2dBox2dCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* /*body0*/,btCollisionObject* /*body1*/,const btDispatcherInfo& /*dispatchInfo*/,btManifoldResult* /*resultOut*/)
+{
+ //not yet
+ return 1.f;
+}
+
+
+struct ClipVertex
+{
+ btVector3 v;
+ int id;
+ //b2ContactID id;
+ //b2ContactID id;
+};
+
+#define b2Dot(a,b) (a).dot(b)
+#define b2Mul(a,b) (a)*(b)
+#define b2MulT(a,b) (a).transpose()*(b)
+#define b2Cross(a,b) (a).cross(b)
+#define btCrossS(a,s) btVector3(s * a.getY(), -s * a.getX(),0.f)
+
+int b2_maxManifoldPoints =2;
+
+static int ClipSegmentToLine(ClipVertex vOut[2], ClipVertex vIn[2],
+ const btVector3& normal, btScalar offset)
+{
+ // Start with no output points
+ int numOut = 0;
+
+ // Calculate the distance of end points to the line
+ btScalar distance0 = b2Dot(normal, vIn[0].v) - offset;
+ btScalar distance1 = b2Dot(normal, vIn[1].v) - offset;
+
+ // If the points are behind the plane
+ if (distance0 <= 0.0f) vOut[numOut++] = vIn[0];
+ if (distance1 <= 0.0f) vOut[numOut++] = vIn[1];
+
+ // If the points are on different sides of the plane
+ if (distance0 * distance1 < 0.0f)
+ {
+ // Find intersection point of edge and plane
+ btScalar interp = distance0 / (distance0 - distance1);
+ vOut[numOut].v = vIn[0].v + interp * (vIn[1].v - vIn[0].v);
+ if (distance0 > 0.0f)
+ {
+ vOut[numOut].id = vIn[0].id;
+ }
+ else
+ {
+ vOut[numOut].id = vIn[1].id;
+ }
+ ++numOut;
+ }
+
+ return numOut;
+}
+
+// Find the separation between poly1 and poly2 for a give edge normal on poly1.
+static btScalar EdgeSeparation(const btBox2dShape* poly1, const btTransform& xf1, int edge1,
+ const btBox2dShape* poly2, const btTransform& xf2)
+{
+ const btVector3* vertices1 = poly1->getVertices();
+ const btVector3* normals1 = poly1->getNormals();
+
+ int count2 = poly2->getVertexCount();
+ const btVector3* vertices2 = poly2->getVertices();
+
+ btAssert(0 <= edge1 && edge1 < poly1->getVertexCount());
+
+ // Convert normal from poly1's frame into poly2's frame.
+ btVector3 normal1World = b2Mul(xf1.getBasis(), normals1[edge1]);
+ btVector3 normal1 = b2MulT(xf2.getBasis(), normal1World);
+
+ // Find support vertex on poly2 for -normal.
+ int index = 0;
+ btScalar minDot = BT_LARGE_FLOAT;
+
+ if( count2 > 0 )
+ index = (int) normal1.minDot( vertices2, count2, minDot);
+
+ btVector3 v1 = b2Mul(xf1, vertices1[edge1]);
+ btVector3 v2 = b2Mul(xf2, vertices2[index]);
+ btScalar separation = b2Dot(v2 - v1, normal1World);
+ return separation;
+}
+
+// Find the max separation between poly1 and poly2 using edge normals from poly1.
+static btScalar FindMaxSeparation(int* edgeIndex,
+ const btBox2dShape* poly1, const btTransform& xf1,
+ const btBox2dShape* poly2, const btTransform& xf2)
+{
+ int count1 = poly1->getVertexCount();
+ const btVector3* normals1 = poly1->getNormals();
+
+ // Vector pointing from the centroid of poly1 to the centroid of poly2.
+ btVector3 d = b2Mul(xf2, poly2->getCentroid()) - b2Mul(xf1, poly1->getCentroid());
+ btVector3 dLocal1 = b2MulT(xf1.getBasis(), d);
+
+ // Find edge normal on poly1 that has the largest projection onto d.
+ int edge = 0;
+ btScalar maxDot;
+ if( count1 > 0 )
+ edge = (int) dLocal1.maxDot( normals1, count1, maxDot);
+
+ // Get the separation for the edge normal.
+ btScalar s = EdgeSeparation(poly1, xf1, edge, poly2, xf2);
+ if (s > 0.0f)
+ {
+ return s;
+ }
+
+ // Check the separation for the previous edge normal.
+ int prevEdge = edge - 1 >= 0 ? edge - 1 : count1 - 1;
+ btScalar sPrev = EdgeSeparation(poly1, xf1, prevEdge, poly2, xf2);
+ if (sPrev > 0.0f)
+ {
+ return sPrev;
+ }
+
+ // Check the separation for the next edge normal.
+ int nextEdge = edge + 1 < count1 ? edge + 1 : 0;
+ btScalar sNext = EdgeSeparation(poly1, xf1, nextEdge, poly2, xf2);
+ if (sNext > 0.0f)
+ {
+ return sNext;
+ }
+
+ // Find the best edge and the search direction.
+ int bestEdge;
+ btScalar bestSeparation;
+ int increment;
+ if (sPrev > s && sPrev > sNext)
+ {
+ increment = -1;
+ bestEdge = prevEdge;
+ bestSeparation = sPrev;
+ }
+ else if (sNext > s)
+ {
+ increment = 1;
+ bestEdge = nextEdge;
+ bestSeparation = sNext;
+ }
+ else
+ {
+ *edgeIndex = edge;
+ return s;
+ }
+
+ // Perform a local search for the best edge normal.
+ for ( ; ; )
+ {
+ if (increment == -1)
+ edge = bestEdge - 1 >= 0 ? bestEdge - 1 : count1 - 1;
+ else
+ edge = bestEdge + 1 < count1 ? bestEdge + 1 : 0;
+
+ s = EdgeSeparation(poly1, xf1, edge, poly2, xf2);
+ if (s > 0.0f)
+ {
+ return s;
+ }
+
+ if (s > bestSeparation)
+ {
+ bestEdge = edge;
+ bestSeparation = s;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ *edgeIndex = bestEdge;
+ return bestSeparation;
+}
+
+static void FindIncidentEdge(ClipVertex c[2],
+ const btBox2dShape* poly1, const btTransform& xf1, int edge1,
+ const btBox2dShape* poly2, const btTransform& xf2)
+{
+ const btVector3* normals1 = poly1->getNormals();
+
+ int count2 = poly2->getVertexCount();
+ const btVector3* vertices2 = poly2->getVertices();
+ const btVector3* normals2 = poly2->getNormals();
+
+ btAssert(0 <= edge1 && edge1 < poly1->getVertexCount());
+
+ // Get the normal of the reference edge in poly2's frame.
+ btVector3 normal1 = b2MulT(xf2.getBasis(), b2Mul(xf1.getBasis(), normals1[edge1]));
+
+ // Find the incident edge on poly2.
+ int index = 0;
+ btScalar minDot = BT_LARGE_FLOAT;
+ for (int i = 0; i < count2; ++i)
+ {
+ btScalar dot = b2Dot(normal1, normals2[i]);
+ if (dot < minDot)
+ {
+ minDot = dot;
+ index = i;
+ }
+ }
+
+ // Build the clip vertices for the incident edge.
+ int i1 = index;
+ int i2 = i1 + 1 < count2 ? i1 + 1 : 0;
+
+ c[0].v = b2Mul(xf2, vertices2[i1]);
+// c[0].id.features.referenceEdge = (unsigned char)edge1;
+// c[0].id.features.incidentEdge = (unsigned char)i1;
+// c[0].id.features.incidentVertex = 0;
+
+ c[1].v = b2Mul(xf2, vertices2[i2]);
+// c[1].id.features.referenceEdge = (unsigned char)edge1;
+// c[1].id.features.incidentEdge = (unsigned char)i2;
+// c[1].id.features.incidentVertex = 1;
+}
+
+// Find edge normal of max separation on A - return if separating axis is found
+// Find edge normal of max separation on B - return if separation axis is found
+// Choose reference edge as min(minA, minB)
+// Find incident edge
+// Clip
+
+// The normal points from 1 to 2
+void b2CollidePolygons(btManifoldResult* manifold,
+ const btBox2dShape* polyA, const btTransform& xfA,
+ const btBox2dShape* polyB, const btTransform& xfB)
+{
+
+ int edgeA = 0;
+ btScalar separationA = FindMaxSeparation(&edgeA, polyA, xfA, polyB, xfB);
+ if (separationA > 0.0f)
+ return;
+
+ int edgeB = 0;
+ btScalar separationB = FindMaxSeparation(&edgeB, polyB, xfB, polyA, xfA);
+ if (separationB > 0.0f)
+ return;
+
+ const btBox2dShape* poly1; // reference poly
+ const btBox2dShape* poly2; // incident poly
+ btTransform xf1, xf2;
+ int edge1; // reference edge
+ unsigned char flip;
+ const btScalar k_relativeTol = 0.98f;
+ const btScalar k_absoluteTol = 0.001f;
+
+ // TODO_ERIN use "radius" of poly for absolute tolerance.
+ if (separationB > k_relativeTol * separationA + k_absoluteTol)
+ {
+ poly1 = polyB;
+ poly2 = polyA;
+ xf1 = xfB;
+ xf2 = xfA;
+ edge1 = edgeB;
+ flip = 1;
+ }
+ else
+ {
+ poly1 = polyA;
+ poly2 = polyB;
+ xf1 = xfA;
+ xf2 = xfB;
+ edge1 = edgeA;
+ flip = 0;
+ }
+
+ ClipVertex incidentEdge[2];
+ FindIncidentEdge(incidentEdge, poly1, xf1, edge1, poly2, xf2);
+
+ int count1 = poly1->getVertexCount();
+ const btVector3* vertices1 = poly1->getVertices();
+
+ btVector3 v11 = vertices1[edge1];
+ btVector3 v12 = edge1 + 1 < count1 ? vertices1[edge1+1] : vertices1[0];
+
+ //btVector3 dv = v12 - v11;
+ btVector3 sideNormal = b2Mul(xf1.getBasis(), v12 - v11);
+ sideNormal.normalize();
+ btVector3 frontNormal = btCrossS(sideNormal, 1.0f);
+
+
+ v11 = b2Mul(xf1, v11);
+ v12 = b2Mul(xf1, v12);
+
+ btScalar frontOffset = b2Dot(frontNormal, v11);
+ btScalar sideOffset1 = -b2Dot(sideNormal, v11);
+ btScalar sideOffset2 = b2Dot(sideNormal, v12);
+
+ // Clip incident edge against extruded edge1 side edges.
+ ClipVertex clipPoints1[2];
+ clipPoints1[0].v.setValue(0,0,0);
+ clipPoints1[1].v.setValue(0,0,0);
+
+ ClipVertex clipPoints2[2];
+ clipPoints2[0].v.setValue(0,0,0);
+ clipPoints2[1].v.setValue(0,0,0);
+
+
+ int np;
+
+ // Clip to box side 1
+ np = ClipSegmentToLine(clipPoints1, incidentEdge, -sideNormal, sideOffset1);
+
+ if (np < 2)
+ return;
+
+ // Clip to negative box side 1
+ np = ClipSegmentToLine(clipPoints2, clipPoints1, sideNormal, sideOffset2);
+
+ if (np < 2)
+ {
+ return;
+ }
+
+ // Now clipPoints2 contains the clipped points.
+ btVector3 manifoldNormal = flip ? -frontNormal : frontNormal;
+
+ int pointCount = 0;
+ for (int i = 0; i < b2_maxManifoldPoints; ++i)
+ {
+ btScalar separation = b2Dot(frontNormal, clipPoints2[i].v) - frontOffset;
+
+ if (separation <= 0.0f)
+ {
+
+ //b2ManifoldPoint* cp = manifold->points + pointCount;
+ //btScalar separation = separation;
+ //cp->localPoint1 = b2MulT(xfA, clipPoints2[i].v);
+ //cp->localPoint2 = b2MulT(xfB, clipPoints2[i].v);
+
+ manifold->addContactPoint(-manifoldNormal,clipPoints2[i].v,separation);
+
+// cp->id = clipPoints2[i].id;
+// cp->id.features.flip = flip;
+ ++pointCount;
+ }
+ }
+
+// manifold->pointCount = pointCount;}
+}
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h
new file mode 100644
index 0000000000..6ea6e89bda
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h
@@ -0,0 +1,66 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_BOX_2D_BOX_2D__COLLISION_ALGORITHM_H
+#define BT_BOX_2D_BOX_2D__COLLISION_ALGORITHM_H
+
+#include "BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
+#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
+
+class btPersistentManifold;
+
+///box-box collision detection
+class btBox2dBox2dCollisionAlgorithm : public btActivatingCollisionAlgorithm
+{
+ bool m_ownManifold;
+ btPersistentManifold* m_manifoldPtr;
+
+public:
+ btBox2dBox2dCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
+ : btActivatingCollisionAlgorithm(ci) {}
+
+ virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+ virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+ btBox2dBox2dCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap);
+
+ virtual ~btBox2dBox2dCollisionAlgorithm();
+
+ virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
+ {
+ if (m_manifoldPtr && m_ownManifold)
+ {
+ manifoldArray.push_back(m_manifoldPtr);
+ }
+ }
+
+
+ struct CreateFunc :public btCollisionAlgorithmCreateFunc
+ {
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
+ {
+ int bbsize = sizeof(btBox2dBox2dCollisionAlgorithm);
+ void* ptr = ci.m_dispatcher1->allocateCollisionAlgorithm(bbsize);
+ return new(ptr) btBox2dBox2dCollisionAlgorithm(0,ci,body0Wrap,body1Wrap);
+ }
+ };
+
+};
+
+#endif //BT_BOX_2D_BOX_2D__COLLISION_ALGORITHM_H
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp
new file mode 100644
index 0000000000..ac68968f59
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp
@@ -0,0 +1,84 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btBoxBoxCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/CollisionShapes/btBoxShape.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "btBoxBoxDetector.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
+#define USE_PERSISTENT_CONTACTS 1
+
+btBoxBoxCollisionAlgorithm::btBoxBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
+: btActivatingCollisionAlgorithm(ci,body0Wrap,body1Wrap),
+m_ownManifold(false),
+m_manifoldPtr(mf)
+{
+ if (!m_manifoldPtr && m_dispatcher->needsCollision(body0Wrap->getCollisionObject(),body1Wrap->getCollisionObject()))
+ {
+ m_manifoldPtr = m_dispatcher->getNewManifold(body0Wrap->getCollisionObject(),body1Wrap->getCollisionObject());
+ m_ownManifold = true;
+ }
+}
+
+btBoxBoxCollisionAlgorithm::~btBoxBoxCollisionAlgorithm()
+{
+ if (m_ownManifold)
+ {
+ if (m_manifoldPtr)
+ m_dispatcher->releaseManifold(m_manifoldPtr);
+ }
+}
+
+void btBoxBoxCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+ if (!m_manifoldPtr)
+ return;
+
+
+ const btBoxShape* box0 = (btBoxShape*)body0Wrap->getCollisionShape();
+ const btBoxShape* box1 = (btBoxShape*)body1Wrap->getCollisionShape();
+
+
+
+ /// report a contact. internally this will be kept persistent, and contact reduction is done
+ resultOut->setPersistentManifold(m_manifoldPtr);
+#ifndef USE_PERSISTENT_CONTACTS
+ m_manifoldPtr->clearManifold();
+#endif //USE_PERSISTENT_CONTACTS
+
+ btDiscreteCollisionDetectorInterface::ClosestPointInput input;
+ input.m_maximumDistanceSquared = BT_LARGE_FLOAT;
+ input.m_transformA = body0Wrap->getWorldTransform();
+ input.m_transformB = body1Wrap->getWorldTransform();
+
+ btBoxBoxDetector detector(box0,box1);
+ detector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw);
+
+#ifdef USE_PERSISTENT_CONTACTS
+ // refreshContactPoints is only necessary when using persistent contact points. otherwise all points are newly added
+ if (m_ownManifold)
+ {
+ resultOut->refreshContactPoints();
+ }
+#endif //USE_PERSISTENT_CONTACTS
+
+}
+
+btScalar btBoxBoxCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* /*body0*/,btCollisionObject* /*body1*/,const btDispatcherInfo& /*dispatchInfo*/,btManifoldResult* /*resultOut*/)
+{
+ //not yet
+ return 1.f;
+}
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h
new file mode 100644
index 0000000000..59808df5a9
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h
@@ -0,0 +1,66 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_BOX_BOX__COLLISION_ALGORITHM_H
+#define BT_BOX_BOX__COLLISION_ALGORITHM_H
+
+#include "btActivatingCollisionAlgorithm.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
+#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
+
+class btPersistentManifold;
+
+///box-box collision detection
+class btBoxBoxCollisionAlgorithm : public btActivatingCollisionAlgorithm
+{
+ bool m_ownManifold;
+ btPersistentManifold* m_manifoldPtr;
+
+public:
+ btBoxBoxCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
+ : btActivatingCollisionAlgorithm(ci) {}
+
+ virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+ virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+ btBoxBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap);
+
+ virtual ~btBoxBoxCollisionAlgorithm();
+
+ virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
+ {
+ if (m_manifoldPtr && m_ownManifold)
+ {
+ manifoldArray.push_back(m_manifoldPtr);
+ }
+ }
+
+
+ struct CreateFunc :public btCollisionAlgorithmCreateFunc
+ {
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
+ {
+ int bbsize = sizeof(btBoxBoxCollisionAlgorithm);
+ void* ptr = ci.m_dispatcher1->allocateCollisionAlgorithm(bbsize);
+ return new(ptr) btBoxBoxCollisionAlgorithm(0,ci,body0Wrap,body1Wrap);
+ }
+ };
+
+};
+
+#endif //BT_BOX_BOX__COLLISION_ALGORITHM_H
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp
new file mode 100644
index 0000000000..7043bde34f
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp
@@ -0,0 +1,718 @@
+/*
+ * Box-Box collision detection re-distributed under the ZLib license with permission from Russell L. Smith
+ * Original version is from Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.
+ * All rights reserved. Email: russ@q12.org Web: www.q12.org
+ Bullet Continuous Collision Detection and Physics Library
+ Bullet is Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+///ODE box-box collision detection is adapted to work with Bullet
+
+#include "btBoxBoxDetector.h"
+#include "BulletCollision/CollisionShapes/btBoxShape.h"
+
+#include <float.h>
+#include <string.h>
+
+btBoxBoxDetector::btBoxBoxDetector(const btBoxShape* box1,const btBoxShape* box2)
+: m_box1(box1),
+m_box2(box2)
+{
+
+}
+
+
+// given two boxes (p1,R1,side1) and (p2,R2,side2), collide them together and
+// generate contact points. this returns 0 if there is no contact otherwise
+// it returns the number of contacts generated.
+// `normal' returns the contact normal.
+// `depth' returns the maximum penetration depth along that normal.
+// `return_code' returns a number indicating the type of contact that was
+// detected:
+// 1,2,3 = box 2 intersects with a face of box 1
+// 4,5,6 = box 1 intersects with a face of box 2
+// 7..15 = edge-edge contact
+// `maxc' is the maximum number of contacts allowed to be generated, i.e.
+// the size of the `contact' array.
+// `contact' and `skip' are the contact array information provided to the
+// collision functions. this function only fills in the position and depth
+// fields.
+struct dContactGeom;
+#define dDOTpq(a,b,p,q) ((a)[0]*(b)[0] + (a)[p]*(b)[q] + (a)[2*(p)]*(b)[2*(q)])
+#define dInfinity FLT_MAX
+
+
+/*PURE_INLINE btScalar dDOT (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,1); }
+PURE_INLINE btScalar dDOT13 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,3); }
+PURE_INLINE btScalar dDOT31 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,3,1); }
+PURE_INLINE btScalar dDOT33 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,3,3); }
+*/
+static btScalar dDOT (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,1); }
+static btScalar dDOT44 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,4,4); }
+static btScalar dDOT41 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,4,1); }
+static btScalar dDOT14 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,4); }
+#define dMULTIPLYOP1_331(A,op,B,C) \
+{\
+ (A)[0] op dDOT41((B),(C)); \
+ (A)[1] op dDOT41((B+1),(C)); \
+ (A)[2] op dDOT41((B+2),(C)); \
+}
+
+#define dMULTIPLYOP0_331(A,op,B,C) \
+{ \
+ (A)[0] op dDOT((B),(C)); \
+ (A)[1] op dDOT((B+4),(C)); \
+ (A)[2] op dDOT((B+8),(C)); \
+}
+
+#define dMULTIPLY1_331(A,B,C) dMULTIPLYOP1_331(A,=,B,C)
+#define dMULTIPLY0_331(A,B,C) dMULTIPLYOP0_331(A,=,B,C)
+
+typedef btScalar dMatrix3[4*3];
+
+void dLineClosestApproach (const btVector3& pa, const btVector3& ua,
+ const btVector3& pb, const btVector3& ub,
+ btScalar *alpha, btScalar *beta);
+void dLineClosestApproach (const btVector3& pa, const btVector3& ua,
+ const btVector3& pb, const btVector3& ub,
+ btScalar *alpha, btScalar *beta)
+{
+ btVector3 p;
+ p[0] = pb[0] - pa[0];
+ p[1] = pb[1] - pa[1];
+ p[2] = pb[2] - pa[2];
+ btScalar uaub = dDOT(ua,ub);
+ btScalar q1 = dDOT(ua,p);
+ btScalar q2 = -dDOT(ub,p);
+ btScalar d = 1-uaub*uaub;
+ if (d <= btScalar(0.0001f)) {
+ // @@@ this needs to be made more robust
+ *alpha = 0;
+ *beta = 0;
+ }
+ else {
+ d = 1.f/d;
+ *alpha = (q1 + uaub*q2)*d;
+ *beta = (uaub*q1 + q2)*d;
+ }
+}
+
+
+
+// find all the intersection points between the 2D rectangle with vertices
+// at (+/-h[0],+/-h[1]) and the 2D quadrilateral with vertices (p[0],p[1]),
+// (p[2],p[3]),(p[4],p[5]),(p[6],p[7]).
+//
+// the intersection points are returned as x,y pairs in the 'ret' array.
+// the number of intersection points is returned by the function (this will
+// be in the range 0 to 8).
+
+static int intersectRectQuad2 (btScalar h[2], btScalar p[8], btScalar ret[16])
+{
+ // q (and r) contain nq (and nr) coordinate points for the current (and
+ // chopped) polygons
+ int nq=4,nr=0;
+ btScalar buffer[16];
+ btScalar *q = p;
+ btScalar *r = ret;
+ for (int dir=0; dir <= 1; dir++) {
+ // direction notation: xy[0] = x axis, xy[1] = y axis
+ for (int sign=-1; sign <= 1; sign += 2) {
+ // chop q along the line xy[dir] = sign*h[dir]
+ btScalar *pq = q;
+ btScalar *pr = r;
+ nr = 0;
+ for (int i=nq; i > 0; i--) {
+ // go through all points in q and all lines between adjacent points
+ if (sign*pq[dir] < h[dir]) {
+ // this point is inside the chopping line
+ pr[0] = pq[0];
+ pr[1] = pq[1];
+ pr += 2;
+ nr++;
+ if (nr & 8) {
+ q = r;
+ goto done;
+ }
+ }
+ btScalar *nextq = (i > 1) ? pq+2 : q;
+ if ((sign*pq[dir] < h[dir]) ^ (sign*nextq[dir] < h[dir])) {
+ // this line crosses the chopping line
+ pr[1-dir] = pq[1-dir] + (nextq[1-dir]-pq[1-dir]) /
+ (nextq[dir]-pq[dir]) * (sign*h[dir]-pq[dir]);
+ pr[dir] = sign*h[dir];
+ pr += 2;
+ nr++;
+ if (nr & 8) {
+ q = r;
+ goto done;
+ }
+ }
+ pq += 2;
+ }
+ q = r;
+ r = (q==ret) ? buffer : ret;
+ nq = nr;
+ }
+ }
+ done:
+ if (q != ret) memcpy (ret,q,nr*2*sizeof(btScalar));
+ return nr;
+}
+
+
+#define M__PI 3.14159265f
+
+// given n points in the plane (array p, of size 2*n), generate m points that
+// best represent the whole set. the definition of 'best' here is not
+// predetermined - the idea is to select points that give good box-box
+// collision detection behavior. the chosen point indexes are returned in the
+// array iret (of size m). 'i0' is always the first entry in the array.
+// n must be in the range [1..8]. m must be in the range [1..n]. i0 must be
+// in the range [0..n-1].
+
+void cullPoints2 (int n, btScalar p[], int m, int i0, int iret[]);
+void cullPoints2 (int n, btScalar p[], int m, int i0, int iret[])
+{
+ // compute the centroid of the polygon in cx,cy
+ int i,j;
+ btScalar a,cx,cy,q;
+ if (n==1) {
+ cx = p[0];
+ cy = p[1];
+ }
+ else if (n==2) {
+ cx = btScalar(0.5)*(p[0] + p[2]);
+ cy = btScalar(0.5)*(p[1] + p[3]);
+ }
+ else {
+ a = 0;
+ cx = 0;
+ cy = 0;
+ for (i=0; i<(n-1); i++) {
+ q = p[i*2]*p[i*2+3] - p[i*2+2]*p[i*2+1];
+ a += q;
+ cx += q*(p[i*2]+p[i*2+2]);
+ cy += q*(p[i*2+1]+p[i*2+3]);
+ }
+ q = p[n*2-2]*p[1] - p[0]*p[n*2-1];
+ if (btFabs(a+q) > SIMD_EPSILON)
+ {
+ a = 1.f/(btScalar(3.0)*(a+q));
+ } else
+ {
+ a=BT_LARGE_FLOAT;
+ }
+ cx = a*(cx + q*(p[n*2-2]+p[0]));
+ cy = a*(cy + q*(p[n*2-1]+p[1]));
+ }
+
+ // compute the angle of each point w.r.t. the centroid
+ btScalar A[8];
+ for (i=0; i<n; i++) A[i] = btAtan2(p[i*2+1]-cy,p[i*2]-cx);
+
+ // search for points that have angles closest to A[i0] + i*(2*pi/m).
+ int avail[8];
+ for (i=0; i<n; i++) avail[i] = 1;
+ avail[i0] = 0;
+ iret[0] = i0;
+ iret++;
+ for (j=1; j<m; j++) {
+ a = btScalar(j)*(2*M__PI/m) + A[i0];
+ if (a > M__PI) a -= 2*M__PI;
+ btScalar maxdiff=1e9,diff;
+
+ *iret = i0; // iret is not allowed to keep this value, but it sometimes does, when diff=#QNAN0
+
+ for (i=0; i<n; i++) {
+ if (avail[i]) {
+ diff = btFabs (A[i]-a);
+ if (diff > M__PI) diff = 2*M__PI - diff;
+ if (diff < maxdiff) {
+ maxdiff = diff;
+ *iret = i;
+ }
+ }
+ }
+#if defined(DEBUG) || defined (_DEBUG)
+ btAssert (*iret != i0); // ensure iret got set
+#endif
+ avail[*iret] = 0;
+ iret++;
+ }
+}
+
+
+
+int dBoxBox2 (const btVector3& p1, const dMatrix3 R1,
+ const btVector3& side1, const btVector3& p2,
+ const dMatrix3 R2, const btVector3& side2,
+ btVector3& normal, btScalar *depth, int *return_code,
+ int maxc, dContactGeom * /*contact*/, int /*skip*/,btDiscreteCollisionDetectorInterface::Result& output);
+int dBoxBox2 (const btVector3& p1, const dMatrix3 R1,
+ const btVector3& side1, const btVector3& p2,
+ const dMatrix3 R2, const btVector3& side2,
+ btVector3& normal, btScalar *depth, int *return_code,
+ int maxc, dContactGeom * /*contact*/, int /*skip*/,btDiscreteCollisionDetectorInterface::Result& output)
+{
+ const btScalar fudge_factor = btScalar(1.05);
+ btVector3 p,pp,normalC(0.f,0.f,0.f);
+ const btScalar *normalR = 0;
+ btScalar A[3],B[3],R11,R12,R13,R21,R22,R23,R31,R32,R33,
+ Q11,Q12,Q13,Q21,Q22,Q23,Q31,Q32,Q33,s,s2,l;
+ int i,j,invert_normal,code;
+
+ // get vector from centers of box 1 to box 2, relative to box 1
+ p = p2 - p1;
+ dMULTIPLY1_331 (pp,R1,p); // get pp = p relative to body 1
+
+ // get side lengths / 2
+ A[0] = side1[0]*btScalar(0.5);
+ A[1] = side1[1]*btScalar(0.5);
+ A[2] = side1[2]*btScalar(0.5);
+ B[0] = side2[0]*btScalar(0.5);
+ B[1] = side2[1]*btScalar(0.5);
+ B[2] = side2[2]*btScalar(0.5);
+
+ // Rij is R1'*R2, i.e. the relative rotation between R1 and R2
+ R11 = dDOT44(R1+0,R2+0); R12 = dDOT44(R1+0,R2+1); R13 = dDOT44(R1+0,R2+2);
+ R21 = dDOT44(R1+1,R2+0); R22 = dDOT44(R1+1,R2+1); R23 = dDOT44(R1+1,R2+2);
+ R31 = dDOT44(R1+2,R2+0); R32 = dDOT44(R1+2,R2+1); R33 = dDOT44(R1+2,R2+2);
+
+ Q11 = btFabs(R11); Q12 = btFabs(R12); Q13 = btFabs(R13);
+ Q21 = btFabs(R21); Q22 = btFabs(R22); Q23 = btFabs(R23);
+ Q31 = btFabs(R31); Q32 = btFabs(R32); Q33 = btFabs(R33);
+
+ // for all 15 possible separating axes:
+ // * see if the axis separates the boxes. if so, return 0.
+ // * find the depth of the penetration along the separating axis (s2)
+ // * if this is the largest depth so far, record it.
+ // the normal vector will be set to the separating axis with the smallest
+ // depth. note: normalR is set to point to a column of R1 or R2 if that is
+ // the smallest depth normal so far. otherwise normalR is 0 and normalC is
+ // set to a vector relative to body 1. invert_normal is 1 if the sign of
+ // the normal should be flipped.
+
+#define TST(expr1,expr2,norm,cc) \
+ s2 = btFabs(expr1) - (expr2); \
+ if (s2 > 0) return 0; \
+ if (s2 > s) { \
+ s = s2; \
+ normalR = norm; \
+ invert_normal = ((expr1) < 0); \
+ code = (cc); \
+ }
+
+ s = -dInfinity;
+ invert_normal = 0;
+ code = 0;
+
+ // separating axis = u1,u2,u3
+ TST (pp[0],(A[0] + B[0]*Q11 + B[1]*Q12 + B[2]*Q13),R1+0,1);
+ TST (pp[1],(A[1] + B[0]*Q21 + B[1]*Q22 + B[2]*Q23),R1+1,2);
+ TST (pp[2],(A[2] + B[0]*Q31 + B[1]*Q32 + B[2]*Q33),R1+2,3);
+
+ // separating axis = v1,v2,v3
+ TST (dDOT41(R2+0,p),(A[0]*Q11 + A[1]*Q21 + A[2]*Q31 + B[0]),R2+0,4);
+ TST (dDOT41(R2+1,p),(A[0]*Q12 + A[1]*Q22 + A[2]*Q32 + B[1]),R2+1,5);
+ TST (dDOT41(R2+2,p),(A[0]*Q13 + A[1]*Q23 + A[2]*Q33 + B[2]),R2+2,6);
+
+ // note: cross product axes need to be scaled when s is computed.
+ // normal (n1,n2,n3) is relative to box 1.
+#undef TST
+#define TST(expr1,expr2,n1,n2,n3,cc) \
+ s2 = btFabs(expr1) - (expr2); \
+ if (s2 > SIMD_EPSILON) return 0; \
+ l = btSqrt((n1)*(n1) + (n2)*(n2) + (n3)*(n3)); \
+ if (l > SIMD_EPSILON) { \
+ s2 /= l; \
+ if (s2*fudge_factor > s) { \
+ s = s2; \
+ normalR = 0; \
+ normalC[0] = (n1)/l; normalC[1] = (n2)/l; normalC[2] = (n3)/l; \
+ invert_normal = ((expr1) < 0); \
+ code = (cc); \
+ } \
+ }
+
+ btScalar fudge2 (1.0e-5f);
+
+ Q11 += fudge2;
+ Q12 += fudge2;
+ Q13 += fudge2;
+
+ Q21 += fudge2;
+ Q22 += fudge2;
+ Q23 += fudge2;
+
+ Q31 += fudge2;
+ Q32 += fudge2;
+ Q33 += fudge2;
+
+ // separating axis = u1 x (v1,v2,v3)
+ TST(pp[2]*R21-pp[1]*R31,(A[1]*Q31+A[2]*Q21+B[1]*Q13+B[2]*Q12),0,-R31,R21,7);
+ TST(pp[2]*R22-pp[1]*R32,(A[1]*Q32+A[2]*Q22+B[0]*Q13+B[2]*Q11),0,-R32,R22,8);
+ TST(pp[2]*R23-pp[1]*R33,(A[1]*Q33+A[2]*Q23+B[0]*Q12+B[1]*Q11),0,-R33,R23,9);
+
+ // separating axis = u2 x (v1,v2,v3)
+ TST(pp[0]*R31-pp[2]*R11,(A[0]*Q31+A[2]*Q11+B[1]*Q23+B[2]*Q22),R31,0,-R11,10);
+ TST(pp[0]*R32-pp[2]*R12,(A[0]*Q32+A[2]*Q12+B[0]*Q23+B[2]*Q21),R32,0,-R12,11);
+ TST(pp[0]*R33-pp[2]*R13,(A[0]*Q33+A[2]*Q13+B[0]*Q22+B[1]*Q21),R33,0,-R13,12);
+
+ // separating axis = u3 x (v1,v2,v3)
+ TST(pp[1]*R11-pp[0]*R21,(A[0]*Q21+A[1]*Q11+B[1]*Q33+B[2]*Q32),-R21,R11,0,13);
+ TST(pp[1]*R12-pp[0]*R22,(A[0]*Q22+A[1]*Q12+B[0]*Q33+B[2]*Q31),-R22,R12,0,14);
+ TST(pp[1]*R13-pp[0]*R23,(A[0]*Q23+A[1]*Q13+B[0]*Q32+B[1]*Q31),-R23,R13,0,15);
+
+#undef TST
+
+ if (!code) return 0;
+
+ // if we get to this point, the boxes interpenetrate. compute the normal
+ // in global coordinates.
+ if (normalR) {
+ normal[0] = normalR[0];
+ normal[1] = normalR[4];
+ normal[2] = normalR[8];
+ }
+ else {
+ dMULTIPLY0_331 (normal,R1,normalC);
+ }
+ if (invert_normal) {
+ normal[0] = -normal[0];
+ normal[1] = -normal[1];
+ normal[2] = -normal[2];
+ }
+ *depth = -s;
+
+ // compute contact point(s)
+
+ if (code > 6) {
+ // an edge from box 1 touches an edge from box 2.
+ // find a point pa on the intersecting edge of box 1
+ btVector3 pa;
+ btScalar sign;
+ for (i=0; i<3; i++) pa[i] = p1[i];
+ for (j=0; j<3; j++) {
+ sign = (dDOT14(normal,R1+j) > 0) ? btScalar(1.0) : btScalar(-1.0);
+ for (i=0; i<3; i++) pa[i] += sign * A[j] * R1[i*4+j];
+ }
+
+ // find a point pb on the intersecting edge of box 2
+ btVector3 pb;
+ for (i=0; i<3; i++) pb[i] = p2[i];
+ for (j=0; j<3; j++) {
+ sign = (dDOT14(normal,R2+j) > 0) ? btScalar(-1.0) : btScalar(1.0);
+ for (i=0; i<3; i++) pb[i] += sign * B[j] * R2[i*4+j];
+ }
+
+ btScalar alpha,beta;
+ btVector3 ua,ub;
+ for (i=0; i<3; i++) ua[i] = R1[((code)-7)/3 + i*4];
+ for (i=0; i<3; i++) ub[i] = R2[((code)-7)%3 + i*4];
+
+ dLineClosestApproach (pa,ua,pb,ub,&alpha,&beta);
+ for (i=0; i<3; i++) pa[i] += ua[i]*alpha;
+ for (i=0; i<3; i++) pb[i] += ub[i]*beta;
+
+ {
+
+ //contact[0].pos[i] = btScalar(0.5)*(pa[i]+pb[i]);
+ //contact[0].depth = *depth;
+ btVector3 pointInWorld;
+
+#ifdef USE_CENTER_POINT
+ for (i=0; i<3; i++)
+ pointInWorld[i] = (pa[i]+pb[i])*btScalar(0.5);
+ output.addContactPoint(-normal,pointInWorld,-*depth);
+#else
+ output.addContactPoint(-normal,pb,-*depth);
+
+#endif //
+ *return_code = code;
+ }
+ return 1;
+ }
+
+ // okay, we have a face-something intersection (because the separating
+ // axis is perpendicular to a face). define face 'a' to be the reference
+ // face (i.e. the normal vector is perpendicular to this) and face 'b' to be
+ // the incident face (the closest face of the other box).
+
+ const btScalar *Ra,*Rb,*pa,*pb,*Sa,*Sb;
+ if (code <= 3) {
+ Ra = R1;
+ Rb = R2;
+ pa = p1;
+ pb = p2;
+ Sa = A;
+ Sb = B;
+ }
+ else {
+ Ra = R2;
+ Rb = R1;
+ pa = p2;
+ pb = p1;
+ Sa = B;
+ Sb = A;
+ }
+
+ // nr = normal vector of reference face dotted with axes of incident box.
+ // anr = absolute values of nr.
+ btVector3 normal2,nr,anr;
+ if (code <= 3) {
+ normal2[0] = normal[0];
+ normal2[1] = normal[1];
+ normal2[2] = normal[2];
+ }
+ else {
+ normal2[0] = -normal[0];
+ normal2[1] = -normal[1];
+ normal2[2] = -normal[2];
+ }
+ dMULTIPLY1_331 (nr,Rb,normal2);
+ anr[0] = btFabs (nr[0]);
+ anr[1] = btFabs (nr[1]);
+ anr[2] = btFabs (nr[2]);
+
+ // find the largest compontent of anr: this corresponds to the normal
+ // for the indident face. the other axis numbers of the indicent face
+ // are stored in a1,a2.
+ int lanr,a1,a2;
+ if (anr[1] > anr[0]) {
+ if (anr[1] > anr[2]) {
+ a1 = 0;
+ lanr = 1;
+ a2 = 2;
+ }
+ else {
+ a1 = 0;
+ a2 = 1;
+ lanr = 2;
+ }
+ }
+ else {
+ if (anr[0] > anr[2]) {
+ lanr = 0;
+ a1 = 1;
+ a2 = 2;
+ }
+ else {
+ a1 = 0;
+ a2 = 1;
+ lanr = 2;
+ }
+ }
+
+ // compute center point of incident face, in reference-face coordinates
+ btVector3 center;
+ if (nr[lanr] < 0) {
+ for (i=0; i<3; i++) center[i] = pb[i] - pa[i] + Sb[lanr] * Rb[i*4+lanr];
+ }
+ else {
+ for (i=0; i<3; i++) center[i] = pb[i] - pa[i] - Sb[lanr] * Rb[i*4+lanr];
+ }
+
+ // find the normal and non-normal axis numbers of the reference box
+ int codeN,code1,code2;
+ if (code <= 3) codeN = code-1; else codeN = code-4;
+ if (codeN==0) {
+ code1 = 1;
+ code2 = 2;
+ }
+ else if (codeN==1) {
+ code1 = 0;
+ code2 = 2;
+ }
+ else {
+ code1 = 0;
+ code2 = 1;
+ }
+
+ // find the four corners of the incident face, in reference-face coordinates
+ btScalar quad[8]; // 2D coordinate of incident face (x,y pairs)
+ btScalar c1,c2,m11,m12,m21,m22;
+ c1 = dDOT14 (center,Ra+code1);
+ c2 = dDOT14 (center,Ra+code2);
+ // optimize this? - we have already computed this data above, but it is not
+ // stored in an easy-to-index format. for now it's quicker just to recompute
+ // the four dot products.
+ m11 = dDOT44 (Ra+code1,Rb+a1);
+ m12 = dDOT44 (Ra+code1,Rb+a2);
+ m21 = dDOT44 (Ra+code2,Rb+a1);
+ m22 = dDOT44 (Ra+code2,Rb+a2);
+ {
+ btScalar k1 = m11*Sb[a1];
+ btScalar k2 = m21*Sb[a1];
+ btScalar k3 = m12*Sb[a2];
+ btScalar k4 = m22*Sb[a2];
+ quad[0] = c1 - k1 - k3;
+ quad[1] = c2 - k2 - k4;
+ quad[2] = c1 - k1 + k3;
+ quad[3] = c2 - k2 + k4;
+ quad[4] = c1 + k1 + k3;
+ quad[5] = c2 + k2 + k4;
+ quad[6] = c1 + k1 - k3;
+ quad[7] = c2 + k2 - k4;
+ }
+
+ // find the size of the reference face
+ btScalar rect[2];
+ rect[0] = Sa[code1];
+ rect[1] = Sa[code2];
+
+ // intersect the incident and reference faces
+ btScalar ret[16];
+ int n = intersectRectQuad2 (rect,quad,ret);
+ if (n < 1) return 0; // this should never happen
+
+ // convert the intersection points into reference-face coordinates,
+ // and compute the contact position and depth for each point. only keep
+ // those points that have a positive (penetrating) depth. delete points in
+ // the 'ret' array as necessary so that 'point' and 'ret' correspond.
+ btScalar point[3*8]; // penetrating contact points
+ btScalar dep[8]; // depths for those points
+ btScalar det1 = 1.f/(m11*m22 - m12*m21);
+ m11 *= det1;
+ m12 *= det1;
+ m21 *= det1;
+ m22 *= det1;
+ int cnum = 0; // number of penetrating contact points found
+ for (j=0; j < n; j++) {
+ btScalar k1 = m22*(ret[j*2]-c1) - m12*(ret[j*2+1]-c2);
+ btScalar k2 = -m21*(ret[j*2]-c1) + m11*(ret[j*2+1]-c2);
+ for (i=0; i<3; i++) point[cnum*3+i] =
+ center[i] + k1*Rb[i*4+a1] + k2*Rb[i*4+a2];
+ dep[cnum] = Sa[codeN] - dDOT(normal2,point+cnum*3);
+ if (dep[cnum] >= 0) {
+ ret[cnum*2] = ret[j*2];
+ ret[cnum*2+1] = ret[j*2+1];
+ cnum++;
+ }
+ }
+ if (cnum < 1) return 0; // this should never happen
+
+ // we can't generate more contacts than we actually have
+ if (maxc > cnum) maxc = cnum;
+ if (maxc < 1) maxc = 1;
+
+ if (cnum <= maxc) {
+
+ if (code<4)
+ {
+ // we have less contacts than we need, so we use them all
+ for (j=0; j < cnum; j++)
+ {
+ btVector3 pointInWorld;
+ for (i=0; i<3; i++)
+ pointInWorld[i] = point[j*3+i] + pa[i];
+ output.addContactPoint(-normal,pointInWorld,-dep[j]);
+
+ }
+ } else
+ {
+ // we have less contacts than we need, so we use them all
+ for (j=0; j < cnum; j++)
+ {
+ btVector3 pointInWorld;
+ for (i=0; i<3; i++)
+ pointInWorld[i] = point[j*3+i] + pa[i]-normal[i]*dep[j];
+ //pointInWorld[i] = point[j*3+i] + pa[i];
+ output.addContactPoint(-normal,pointInWorld,-dep[j]);
+ }
+ }
+ }
+ else {
+ // we have more contacts than are wanted, some of them must be culled.
+ // find the deepest point, it is always the first contact.
+ int i1 = 0;
+ btScalar maxdepth = dep[0];
+ for (i=1; i<cnum; i++) {
+ if (dep[i] > maxdepth) {
+ maxdepth = dep[i];
+ i1 = i;
+ }
+ }
+
+ int iret[8];
+ cullPoints2 (cnum,ret,maxc,i1,iret);
+
+ for (j=0; j < maxc; j++) {
+// dContactGeom *con = CONTACT(contact,skip*j);
+ // for (i=0; i<3; i++) con->pos[i] = point[iret[j]*3+i] + pa[i];
+ // con->depth = dep[iret[j]];
+
+ btVector3 posInWorld;
+ for (i=0; i<3; i++)
+ posInWorld[i] = point[iret[j]*3+i] + pa[i];
+ if (code<4)
+ {
+ output.addContactPoint(-normal,posInWorld,-dep[iret[j]]);
+ } else
+ {
+ output.addContactPoint(-normal,posInWorld-normal*dep[iret[j]],-dep[iret[j]]);
+ }
+ }
+ cnum = maxc;
+ }
+
+ *return_code = code;
+ return cnum;
+}
+
+void btBoxBoxDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* /*debugDraw*/,bool /*swapResults*/)
+{
+
+ const btTransform& transformA = input.m_transformA;
+ const btTransform& transformB = input.m_transformB;
+
+ int skip = 0;
+ dContactGeom *contact = 0;
+
+ dMatrix3 R1;
+ dMatrix3 R2;
+
+ for (int j=0;j<3;j++)
+ {
+ R1[0+4*j] = transformA.getBasis()[j].x();
+ R2[0+4*j] = transformB.getBasis()[j].x();
+
+ R1[1+4*j] = transformA.getBasis()[j].y();
+ R2[1+4*j] = transformB.getBasis()[j].y();
+
+
+ R1[2+4*j] = transformA.getBasis()[j].z();
+ R2[2+4*j] = transformB.getBasis()[j].z();
+
+ }
+
+
+
+ btVector3 normal;
+ btScalar depth;
+ int return_code;
+ int maxc = 4;
+
+
+ dBoxBox2 (transformA.getOrigin(),
+ R1,
+ 2.f*m_box1->getHalfExtentsWithMargin(),
+ transformB.getOrigin(),
+ R2,
+ 2.f*m_box2->getHalfExtentsWithMargin(),
+ normal, &depth, &return_code,
+ maxc, contact, skip,
+ output
+ );
+
+}
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.h b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.h
new file mode 100644
index 0000000000..3924377705
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.h
@@ -0,0 +1,44 @@
+/*
+ * Box-Box collision detection re-distributed under the ZLib license with permission from Russell L. Smith
+ * Original version is from Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.
+ * All rights reserved. Email: russ@q12.org Web: www.q12.org
+
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+#ifndef BT_BOX_BOX_DETECTOR_H
+#define BT_BOX_BOX_DETECTOR_H
+
+
+class btBoxShape;
+#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
+
+
+/// btBoxBoxDetector wraps the ODE box-box collision detector
+/// re-distributed under the Zlib license with permission from Russell L. Smith
+struct btBoxBoxDetector : public btDiscreteCollisionDetectorInterface
+{
+ const btBoxShape* m_box1;
+ const btBoxShape* m_box2;
+
+public:
+
+ btBoxBoxDetector(const btBoxShape* box1,const btBoxShape* box2);
+
+ virtual ~btBoxBoxDetector() {};
+
+ virtual void getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults=false);
+
+};
+
+#endif //BT_BOX_BOX_DETECTOR_H
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h
new file mode 100644
index 0000000000..35f77d4e65
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h
@@ -0,0 +1,49 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_COLLISION_CONFIGURATION
+#define BT_COLLISION_CONFIGURATION
+
+struct btCollisionAlgorithmCreateFunc;
+
+class btPoolAllocator;
+
+///btCollisionConfiguration allows to configure Bullet collision detection
+///stack allocator size, default collision algorithms and persistent manifold pool size
+///@todo: describe the meaning
+class btCollisionConfiguration
+{
+
+public:
+
+ virtual ~btCollisionConfiguration()
+ {
+ }
+
+ ///memory pools
+ virtual btPoolAllocator* getPersistentManifoldPool() = 0;
+
+ virtual btPoolAllocator* getCollisionAlgorithmPool() = 0;
+
+
+ virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1) =0;
+
+ virtual btCollisionAlgorithmCreateFunc* getClosestPointsAlgorithmCreateFunc(int proxyType0, int proxyType1) = 0;
+
+
+};
+
+#endif //BT_COLLISION_CONFIGURATION
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h
new file mode 100644
index 0000000000..62ee66c4e9
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h
@@ -0,0 +1,45 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_COLLISION_CREATE_FUNC
+#define BT_COLLISION_CREATE_FUNC
+
+#include "LinearMath/btAlignedObjectArray.h"
+class btCollisionAlgorithm;
+class btCollisionObject;
+struct btCollisionObjectWrapper;
+struct btCollisionAlgorithmConstructionInfo;
+
+///Used by the btCollisionDispatcher to register and create instances for btCollisionAlgorithm
+struct btCollisionAlgorithmCreateFunc
+{
+ bool m_swapped;
+
+ btCollisionAlgorithmCreateFunc()
+ :m_swapped(false)
+ {
+ }
+ virtual ~btCollisionAlgorithmCreateFunc(){};
+
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& , const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
+ {
+
+ (void)body0Wrap;
+ (void)body1Wrap;
+ return 0;
+ }
+};
+#endif //BT_COLLISION_CREATE_FUNC
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp
new file mode 100644
index 0000000000..5739a1ef01
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp
@@ -0,0 +1,324 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+#include "btCollisionDispatcher.h"
+#include "LinearMath/btQuickprof.h"
+
+#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
+
+#include "BulletCollision/CollisionShapes/btCollisionShape.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
+#include "LinearMath/btPoolAllocator.h"
+#include "BulletCollision/CollisionDispatch/btCollisionConfiguration.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
+
+int gNumManifold = 0;
+
+#ifdef BT_DEBUG
+#include <stdio.h>
+#endif
+
+
+btCollisionDispatcher::btCollisionDispatcher (btCollisionConfiguration* collisionConfiguration):
+m_dispatcherFlags(btCollisionDispatcher::CD_USE_RELATIVE_CONTACT_BREAKING_THRESHOLD),
+ m_collisionConfiguration(collisionConfiguration)
+{
+ int i;
+
+ setNearCallback(defaultNearCallback);
+
+ m_collisionAlgorithmPoolAllocator = collisionConfiguration->getCollisionAlgorithmPool();
+
+ m_persistentManifoldPoolAllocator = collisionConfiguration->getPersistentManifoldPool();
+
+ for (i=0;i<MAX_BROADPHASE_COLLISION_TYPES;i++)
+ {
+ for (int j=0;j<MAX_BROADPHASE_COLLISION_TYPES;j++)
+ {
+ m_doubleDispatchContactPoints[i][j] = m_collisionConfiguration->getCollisionAlgorithmCreateFunc(i,j);
+ btAssert(m_doubleDispatchContactPoints[i][j]);
+ m_doubleDispatchClosestPoints[i][j] = m_collisionConfiguration->getClosestPointsAlgorithmCreateFunc(i, j);
+
+ }
+ }
+
+
+}
+
+
+void btCollisionDispatcher::registerCollisionCreateFunc(int proxyType0, int proxyType1, btCollisionAlgorithmCreateFunc *createFunc)
+{
+ m_doubleDispatchContactPoints[proxyType0][proxyType1] = createFunc;
+}
+
+void btCollisionDispatcher::registerClosestPointsCreateFunc(int proxyType0, int proxyType1, btCollisionAlgorithmCreateFunc *createFunc)
+{
+ m_doubleDispatchClosestPoints[proxyType0][proxyType1] = createFunc;
+}
+
+btCollisionDispatcher::~btCollisionDispatcher()
+{
+}
+
+btPersistentManifold* btCollisionDispatcher::getNewManifold(const btCollisionObject* body0,const btCollisionObject* body1)
+{
+ gNumManifold++;
+
+ //btAssert(gNumManifold < 65535);
+
+
+
+ //optional relative contact breaking threshold, turned on by default (use setDispatcherFlags to switch off feature for improved performance)
+
+ btScalar contactBreakingThreshold = (m_dispatcherFlags & btCollisionDispatcher::CD_USE_RELATIVE_CONTACT_BREAKING_THRESHOLD) ?
+ btMin(body0->getCollisionShape()->getContactBreakingThreshold(gContactBreakingThreshold) , body1->getCollisionShape()->getContactBreakingThreshold(gContactBreakingThreshold))
+ : gContactBreakingThreshold ;
+
+ btScalar contactProcessingThreshold = btMin(body0->getContactProcessingThreshold(),body1->getContactProcessingThreshold());
+
+ void* mem = m_persistentManifoldPoolAllocator->allocate( sizeof( btPersistentManifold ) );
+ if (NULL == mem)
+ {
+ //we got a pool memory overflow, by default we fallback to dynamically allocate memory. If we require a contiguous contact pool then assert.
+ if ((m_dispatcherFlags&CD_DISABLE_CONTACTPOOL_DYNAMIC_ALLOCATION)==0)
+ {
+ mem = btAlignedAlloc(sizeof(btPersistentManifold),16);
+ } else
+ {
+ btAssert(0);
+ //make sure to increase the m_defaultMaxPersistentManifoldPoolSize in the btDefaultCollisionConstructionInfo/btDefaultCollisionConfiguration
+ return 0;
+ }
+ }
+ btPersistentManifold* manifold = new(mem) btPersistentManifold (body0,body1,0,contactBreakingThreshold,contactProcessingThreshold);
+ manifold->m_index1a = m_manifoldsPtr.size();
+ m_manifoldsPtr.push_back(manifold);
+
+ return manifold;
+}
+
+void btCollisionDispatcher::clearManifold(btPersistentManifold* manifold)
+{
+ manifold->clearManifold();
+}
+
+
+void btCollisionDispatcher::releaseManifold(btPersistentManifold* manifold)
+{
+
+ gNumManifold--;
+
+ //printf("releaseManifold: gNumManifold %d\n",gNumManifold);
+ clearManifold(manifold);
+
+ int findIndex = manifold->m_index1a;
+ btAssert(findIndex < m_manifoldsPtr.size());
+ m_manifoldsPtr.swap(findIndex,m_manifoldsPtr.size()-1);
+ m_manifoldsPtr[findIndex]->m_index1a = findIndex;
+ m_manifoldsPtr.pop_back();
+
+ manifold->~btPersistentManifold();
+ if (m_persistentManifoldPoolAllocator->validPtr(manifold))
+ {
+ m_persistentManifoldPoolAllocator->freeMemory(manifold);
+ } else
+ {
+ btAlignedFree(manifold);
+ }
+
+}
+
+
+
+
+btCollisionAlgorithm* btCollisionDispatcher::findAlgorithm(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,btPersistentManifold* sharedManifold, ebtDispatcherQueryType algoType)
+{
+
+ btCollisionAlgorithmConstructionInfo ci;
+
+ ci.m_dispatcher1 = this;
+ ci.m_manifold = sharedManifold;
+ btCollisionAlgorithm* algo = 0;
+ if (algoType == BT_CONTACT_POINT_ALGORITHMS)
+ {
+ algo = m_doubleDispatchContactPoints[body0Wrap->getCollisionShape()->getShapeType()][body1Wrap->getCollisionShape()->getShapeType()]->CreateCollisionAlgorithm(ci, body0Wrap, body1Wrap);
+ }
+ else
+ {
+ algo = m_doubleDispatchClosestPoints[body0Wrap->getCollisionShape()->getShapeType()][body1Wrap->getCollisionShape()->getShapeType()]->CreateCollisionAlgorithm(ci, body0Wrap, body1Wrap);
+ }
+
+ return algo;
+}
+
+
+
+
+bool btCollisionDispatcher::needsResponse(const btCollisionObject* body0,const btCollisionObject* body1)
+{
+ //here you can do filtering
+ bool hasResponse =
+ (body0->hasContactResponse() && body1->hasContactResponse());
+ //no response between two static/kinematic bodies:
+ hasResponse = hasResponse &&
+ ((!body0->isStaticOrKinematicObject()) ||(! body1->isStaticOrKinematicObject()));
+ return hasResponse;
+}
+
+bool btCollisionDispatcher::needsCollision(const btCollisionObject* body0,const btCollisionObject* body1)
+{
+ btAssert(body0);
+ btAssert(body1);
+
+ bool needsCollision = true;
+
+#ifdef BT_DEBUG
+ if (!(m_dispatcherFlags & btCollisionDispatcher::CD_STATIC_STATIC_REPORTED))
+ {
+ //broadphase filtering already deals with this
+ if (body0->isStaticOrKinematicObject() && body1->isStaticOrKinematicObject())
+ {
+ m_dispatcherFlags |= btCollisionDispatcher::CD_STATIC_STATIC_REPORTED;
+ printf("warning btCollisionDispatcher::needsCollision: static-static collision!\n");
+ }
+ }
+#endif //BT_DEBUG
+
+ if ((!body0->isActive()) && (!body1->isActive()))
+ needsCollision = false;
+ else if ((!body0->checkCollideWith(body1)) || (!body1->checkCollideWith(body0)))
+ needsCollision = false;
+
+ return needsCollision ;
+
+}
+
+
+
+///interface for iterating all overlapping collision pairs, no matter how those pairs are stored (array, set, map etc)
+///this is useful for the collision dispatcher.
+class btCollisionPairCallback : public btOverlapCallback
+{
+ const btDispatcherInfo& m_dispatchInfo;
+ btCollisionDispatcher* m_dispatcher;
+
+public:
+
+ btCollisionPairCallback(const btDispatcherInfo& dispatchInfo,btCollisionDispatcher* dispatcher)
+ :m_dispatchInfo(dispatchInfo),
+ m_dispatcher(dispatcher)
+ {
+ }
+
+ /*btCollisionPairCallback& operator=(btCollisionPairCallback& other)
+ {
+ m_dispatchInfo = other.m_dispatchInfo;
+ m_dispatcher = other.m_dispatcher;
+ return *this;
+ }
+ */
+
+
+ virtual ~btCollisionPairCallback() {}
+
+
+ virtual bool processOverlap(btBroadphasePair& pair)
+ {
+ (*m_dispatcher->getNearCallback())(pair,*m_dispatcher,m_dispatchInfo);
+ return false;
+ }
+};
+
+
+
+void btCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher)
+{
+ //m_blockedForChanges = true;
+
+ btCollisionPairCallback collisionCallback(dispatchInfo,this);
+
+ pairCache->processAllOverlappingPairs(&collisionCallback,dispatcher);
+
+ //m_blockedForChanges = false;
+
+}
+
+
+
+//by default, Bullet will use this near callback
+void btCollisionDispatcher::defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo)
+{
+ btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
+ btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;
+
+ if (dispatcher.needsCollision(colObj0,colObj1))
+ {
+ btCollisionObjectWrapper obj0Wrap(0,colObj0->getCollisionShape(),colObj0,colObj0->getWorldTransform(),-1,-1);
+ btCollisionObjectWrapper obj1Wrap(0,colObj1->getCollisionShape(),colObj1,colObj1->getWorldTransform(),-1,-1);
+
+
+ //dispatcher will keep algorithms persistent in the collision pair
+ if (!collisionPair.m_algorithm)
+ {
+ collisionPair.m_algorithm = dispatcher.findAlgorithm(&obj0Wrap,&obj1Wrap,0, BT_CONTACT_POINT_ALGORITHMS);
+ }
+
+ if (collisionPair.m_algorithm)
+ {
+ btManifoldResult contactPointResult(&obj0Wrap,&obj1Wrap);
+
+ if (dispatchInfo.m_dispatchFunc == btDispatcherInfo::DISPATCH_DISCRETE)
+ {
+ //discrete collision detection query
+
+ collisionPair.m_algorithm->processCollision(&obj0Wrap,&obj1Wrap,dispatchInfo,&contactPointResult);
+ } else
+ {
+ //continuous collision detection query, time of impact (toi)
+ btScalar toi = collisionPair.m_algorithm->calculateTimeOfImpact(colObj0,colObj1,dispatchInfo,&contactPointResult);
+ if (dispatchInfo.m_timeOfImpact > toi)
+ dispatchInfo.m_timeOfImpact = toi;
+
+ }
+ }
+ }
+
+}
+
+
+void* btCollisionDispatcher::allocateCollisionAlgorithm(int size)
+{
+ void* mem = m_collisionAlgorithmPoolAllocator->allocate( size );
+ if (NULL == mem)
+ {
+ //warn user for overflow?
+ return btAlignedAlloc(static_cast<size_t>(size), 16);
+ }
+ return mem;
+}
+
+void btCollisionDispatcher::freeCollisionAlgorithm(void* ptr)
+{
+ if (m_collisionAlgorithmPoolAllocator->validPtr(ptr))
+ {
+ m_collisionAlgorithmPoolAllocator->freeMemory(ptr);
+ } else
+ {
+ btAlignedFree(ptr);
+ }
+}
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h
new file mode 100644
index 0000000000..b97ee3c1ba
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h
@@ -0,0 +1,175 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_COLLISION__DISPATCHER_H
+#define BT_COLLISION__DISPATCHER_H
+
+#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
+#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
+
+#include "BulletCollision/CollisionDispatch/btManifoldResult.h"
+
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "LinearMath/btAlignedObjectArray.h"
+
+class btIDebugDraw;
+class btOverlappingPairCache;
+class btPoolAllocator;
+class btCollisionConfiguration;
+
+#include "btCollisionCreateFunc.h"
+
+#define USE_DISPATCH_REGISTRY_ARRAY 1
+
+class btCollisionDispatcher;
+///user can override this nearcallback for collision filtering and more finegrained control over collision detection
+typedef void (*btNearCallback)(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo);
+
+
+///btCollisionDispatcher supports algorithms that handle ConvexConvex and ConvexConcave collision pairs.
+///Time of Impact, Closest Points and Penetration Depth.
+class btCollisionDispatcher : public btDispatcher
+{
+
+protected:
+
+ int m_dispatcherFlags;
+
+ btAlignedObjectArray<btPersistentManifold*> m_manifoldsPtr;
+
+ btManifoldResult m_defaultManifoldResult;
+
+ btNearCallback m_nearCallback;
+
+ btPoolAllocator* m_collisionAlgorithmPoolAllocator;
+
+ btPoolAllocator* m_persistentManifoldPoolAllocator;
+
+ btCollisionAlgorithmCreateFunc* m_doubleDispatchContactPoints[MAX_BROADPHASE_COLLISION_TYPES][MAX_BROADPHASE_COLLISION_TYPES];
+
+ btCollisionAlgorithmCreateFunc* m_doubleDispatchClosestPoints[MAX_BROADPHASE_COLLISION_TYPES][MAX_BROADPHASE_COLLISION_TYPES];
+
+ btCollisionConfiguration* m_collisionConfiguration;
+
+
+public:
+
+ enum DispatcherFlags
+ {
+ CD_STATIC_STATIC_REPORTED = 1,
+ CD_USE_RELATIVE_CONTACT_BREAKING_THRESHOLD = 2,
+ CD_DISABLE_CONTACTPOOL_DYNAMIC_ALLOCATION = 4
+ };
+
+ int getDispatcherFlags() const
+ {
+ return m_dispatcherFlags;
+ }
+
+ void setDispatcherFlags(int flags)
+ {
+ m_dispatcherFlags = flags;
+ }
+
+ ///registerCollisionCreateFunc allows registration of custom/alternative collision create functions
+ void registerCollisionCreateFunc(int proxyType0,int proxyType1, btCollisionAlgorithmCreateFunc* createFunc);
+
+ void registerClosestPointsCreateFunc(int proxyType0, int proxyType1, btCollisionAlgorithmCreateFunc *createFunc);
+
+ int getNumManifolds() const
+ {
+ return int( m_manifoldsPtr.size());
+ }
+
+ btPersistentManifold** getInternalManifoldPointer()
+ {
+ return m_manifoldsPtr.size()? &m_manifoldsPtr[0] : 0;
+ }
+
+ btPersistentManifold* getManifoldByIndexInternal(int index)
+ {
+ return m_manifoldsPtr[index];
+ }
+
+ const btPersistentManifold* getManifoldByIndexInternal(int index) const
+ {
+ return m_manifoldsPtr[index];
+ }
+
+ btCollisionDispatcher (btCollisionConfiguration* collisionConfiguration);
+
+ virtual ~btCollisionDispatcher();
+
+ virtual btPersistentManifold* getNewManifold(const btCollisionObject* b0,const btCollisionObject* b1);
+
+ virtual void releaseManifold(btPersistentManifold* manifold);
+
+
+ virtual void clearManifold(btPersistentManifold* manifold);
+
+ btCollisionAlgorithm* findAlgorithm(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,btPersistentManifold* sharedManifold, ebtDispatcherQueryType queryType);
+
+ virtual bool needsCollision(const btCollisionObject* body0,const btCollisionObject* body1);
+
+ virtual bool needsResponse(const btCollisionObject* body0,const btCollisionObject* body1);
+
+ virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) ;
+
+ void setNearCallback(btNearCallback nearCallback)
+ {
+ m_nearCallback = nearCallback;
+ }
+
+ btNearCallback getNearCallback() const
+ {
+ return m_nearCallback;
+ }
+
+ //by default, Bullet will use this near callback
+ static void defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo);
+
+ virtual void* allocateCollisionAlgorithm(int size);
+
+ virtual void freeCollisionAlgorithm(void* ptr);
+
+ btCollisionConfiguration* getCollisionConfiguration()
+ {
+ return m_collisionConfiguration;
+ }
+
+ const btCollisionConfiguration* getCollisionConfiguration() const
+ {
+ return m_collisionConfiguration;
+ }
+
+ void setCollisionConfiguration(btCollisionConfiguration* config)
+ {
+ m_collisionConfiguration = config;
+ }
+
+ virtual btPoolAllocator* getInternalManifoldPool()
+ {
+ return m_persistentManifoldPoolAllocator;
+ }
+
+ virtual const btPoolAllocator* getInternalManifoldPool() const
+ {
+ return m_persistentManifoldPoolAllocator;
+ }
+
+};
+
+#endif //BT_COLLISION__DISPATCHER_H
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCollisionDispatcherMt.cpp b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCollisionDispatcherMt.cpp
new file mode 100644
index 0000000000..075860c503
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCollisionDispatcherMt.cpp
@@ -0,0 +1,164 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+#include "btCollisionDispatcherMt.h"
+#include "LinearMath/btQuickprof.h"
+
+#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
+
+#include "BulletCollision/CollisionShapes/btCollisionShape.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
+#include "LinearMath/btPoolAllocator.h"
+#include "BulletCollision/CollisionDispatch/btCollisionConfiguration.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
+
+
+btCollisionDispatcherMt::btCollisionDispatcherMt( btCollisionConfiguration* config, int grainSize )
+ : btCollisionDispatcher( config )
+{
+ m_batchUpdating = false;
+ m_grainSize = grainSize; // iterations per task
+}
+
+
+btPersistentManifold* btCollisionDispatcherMt::getNewManifold( const btCollisionObject* body0, const btCollisionObject* body1 )
+{
+ //optional relative contact breaking threshold, turned on by default (use setDispatcherFlags to switch off feature for improved performance)
+
+ btScalar contactBreakingThreshold = ( m_dispatcherFlags & btCollisionDispatcher::CD_USE_RELATIVE_CONTACT_BREAKING_THRESHOLD ) ?
+ btMin( body0->getCollisionShape()->getContactBreakingThreshold( gContactBreakingThreshold ), body1->getCollisionShape()->getContactBreakingThreshold( gContactBreakingThreshold ) )
+ : gContactBreakingThreshold;
+
+ btScalar contactProcessingThreshold = btMin( body0->getContactProcessingThreshold(), body1->getContactProcessingThreshold() );
+
+ void* mem = m_persistentManifoldPoolAllocator->allocate( sizeof( btPersistentManifold ) );
+ if ( NULL == mem )
+ {
+ //we got a pool memory overflow, by default we fallback to dynamically allocate memory. If we require a contiguous contact pool then assert.
+ if ( ( m_dispatcherFlags&CD_DISABLE_CONTACTPOOL_DYNAMIC_ALLOCATION ) == 0 )
+ {
+ mem = btAlignedAlloc( sizeof( btPersistentManifold ), 16 );
+ }
+ else
+ {
+ btAssert( 0 );
+ //make sure to increase the m_defaultMaxPersistentManifoldPoolSize in the btDefaultCollisionConstructionInfo/btDefaultCollisionConfiguration
+ return 0;
+ }
+ }
+ btPersistentManifold* manifold = new( mem ) btPersistentManifold( body0, body1, 0, contactBreakingThreshold, contactProcessingThreshold );
+ if ( !m_batchUpdating )
+ {
+ // batch updater will update manifold pointers array after finishing, so
+ // only need to update array when not batch-updating
+ //btAssert( !btThreadsAreRunning() );
+ manifold->m_index1a = m_manifoldsPtr.size();
+ m_manifoldsPtr.push_back( manifold );
+ }
+
+ return manifold;
+}
+
+void btCollisionDispatcherMt::releaseManifold( btPersistentManifold* manifold )
+{
+ clearManifold( manifold );
+ //btAssert( !btThreadsAreRunning() );
+ if ( !m_batchUpdating )
+ {
+ // batch updater will update manifold pointers array after finishing, so
+ // only need to update array when not batch-updating
+ int findIndex = manifold->m_index1a;
+ btAssert( findIndex < m_manifoldsPtr.size() );
+ m_manifoldsPtr.swap( findIndex, m_manifoldsPtr.size() - 1 );
+ m_manifoldsPtr[ findIndex ]->m_index1a = findIndex;
+ m_manifoldsPtr.pop_back();
+ }
+
+ manifold->~btPersistentManifold();
+ if ( m_persistentManifoldPoolAllocator->validPtr( manifold ) )
+ {
+ m_persistentManifoldPoolAllocator->freeMemory( manifold );
+ }
+ else
+ {
+ btAlignedFree( manifold );
+ }
+}
+
+struct CollisionDispatcherUpdater : public btIParallelForBody
+{
+ btBroadphasePair* mPairArray;
+ btNearCallback mCallback;
+ btCollisionDispatcher* mDispatcher;
+ const btDispatcherInfo* mInfo;
+
+ CollisionDispatcherUpdater()
+ {
+ mPairArray = NULL;
+ mCallback = NULL;
+ mDispatcher = NULL;
+ mInfo = NULL;
+ }
+ void forLoop( int iBegin, int iEnd ) const
+ {
+ for ( int i = iBegin; i < iEnd; ++i )
+ {
+ btBroadphasePair* pair = &mPairArray[ i ];
+ mCallback( *pair, *mDispatcher, *mInfo );
+ }
+ }
+};
+
+
+void btCollisionDispatcherMt::dispatchAllCollisionPairs( btOverlappingPairCache* pairCache, const btDispatcherInfo& info, btDispatcher* dispatcher )
+{
+ int pairCount = pairCache->getNumOverlappingPairs();
+ if ( pairCount == 0 )
+ {
+ return;
+ }
+ CollisionDispatcherUpdater updater;
+ updater.mCallback = getNearCallback();
+ updater.mPairArray = pairCache->getOverlappingPairArrayPtr();
+ updater.mDispatcher = this;
+ updater.mInfo = &info;
+
+ m_batchUpdating = true;
+ btParallelFor( 0, pairCount, m_grainSize, updater );
+ m_batchUpdating = false;
+
+ // reconstruct the manifolds array to ensure determinism
+ m_manifoldsPtr.resizeNoInitialize( 0 );
+
+ btBroadphasePair* pairs = pairCache->getOverlappingPairArrayPtr();
+ for ( int i = 0; i < pairCount; ++i )
+ {
+ if (btCollisionAlgorithm* algo = pairs[ i ].m_algorithm)
+ {
+ algo->getAllContactManifolds( m_manifoldsPtr );
+ }
+ }
+
+ // update the indices (used when releasing manifolds)
+ for ( int i = 0; i < m_manifoldsPtr.size(); ++i )
+ {
+ m_manifoldsPtr[ i ]->m_index1a = i;
+ }
+}
+
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCollisionDispatcherMt.h b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCollisionDispatcherMt.h
new file mode 100644
index 0000000000..f1d7eafdc9
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCollisionDispatcherMt.h
@@ -0,0 +1,39 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_COLLISION_DISPATCHER_MT_H
+#define BT_COLLISION_DISPATCHER_MT_H
+
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "LinearMath/btThreads.h"
+
+
+class btCollisionDispatcherMt : public btCollisionDispatcher
+{
+public:
+ btCollisionDispatcherMt( btCollisionConfiguration* config, int grainSize = 40 );
+
+ virtual btPersistentManifold* getNewManifold( const btCollisionObject* body0, const btCollisionObject* body1 ) BT_OVERRIDE;
+ virtual void releaseManifold( btPersistentManifold* manifold ) BT_OVERRIDE;
+
+ virtual void dispatchAllCollisionPairs( btOverlappingPairCache* pairCache, const btDispatcherInfo& info, btDispatcher* dispatcher ) BT_OVERRIDE;
+
+protected:
+ bool m_batchUpdating;
+ int m_grainSize;
+};
+
+#endif //BT_COLLISION_DISPATCHER_MT_H
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp
new file mode 100644
index 0000000000..b595c56bc5
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp
@@ -0,0 +1,131 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "btCollisionObject.h"
+#include "LinearMath/btSerializer.h"
+
+btCollisionObject::btCollisionObject()
+ : m_interpolationLinearVelocity(0.f, 0.f, 0.f),
+ m_interpolationAngularVelocity(0.f, 0.f, 0.f),
+ m_anisotropicFriction(1.f,1.f,1.f),
+ m_hasAnisotropicFriction(false),
+ m_contactProcessingThreshold(BT_LARGE_FLOAT),
+ m_broadphaseHandle(0),
+ m_collisionShape(0),
+ m_extensionPointer(0),
+ m_rootCollisionShape(0),
+ m_collisionFlags(btCollisionObject::CF_STATIC_OBJECT),
+ m_islandTag1(-1),
+ m_companionId(-1),
+ m_worldArrayIndex(-1),
+ m_activationState1(1),
+ m_deactivationTime(btScalar(0.)),
+ m_friction(btScalar(0.5)),
+ m_restitution(btScalar(0.)),
+ m_rollingFriction(0.0f),
+ m_spinningFriction(0.f),
+ m_contactDamping(.1),
+ m_contactStiffness(1e4),
+ m_internalType(CO_COLLISION_OBJECT),
+ m_userObjectPointer(0),
+ m_userIndex2(-1),
+ m_userIndex(-1),
+ m_hitFraction(btScalar(1.)),
+ m_ccdSweptSphereRadius(btScalar(0.)),
+ m_ccdMotionThreshold(btScalar(0.)),
+ m_checkCollideWith(false),
+ m_updateRevision(0)
+{
+ m_worldTransform.setIdentity();
+ m_interpolationWorldTransform.setIdentity();
+}
+
+btCollisionObject::~btCollisionObject()
+{
+}
+
+void btCollisionObject::setActivationState(int newState) const
+{
+ if ( (m_activationState1 != DISABLE_DEACTIVATION) && (m_activationState1 != DISABLE_SIMULATION))
+ m_activationState1 = newState;
+}
+
+void btCollisionObject::forceActivationState(int newState) const
+{
+ m_activationState1 = newState;
+}
+
+void btCollisionObject::activate(bool forceActivation) const
+{
+ if (forceActivation || !(m_collisionFlags & (CF_STATIC_OBJECT|CF_KINEMATIC_OBJECT)))
+ {
+ setActivationState(ACTIVE_TAG);
+ m_deactivationTime = btScalar(0.);
+ }
+}
+
+const char* btCollisionObject::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+
+ btCollisionObjectData* dataOut = (btCollisionObjectData*)dataBuffer;
+
+ m_worldTransform.serialize(dataOut->m_worldTransform);
+ m_interpolationWorldTransform.serialize(dataOut->m_interpolationWorldTransform);
+ m_interpolationLinearVelocity.serialize(dataOut->m_interpolationLinearVelocity);
+ m_interpolationAngularVelocity.serialize(dataOut->m_interpolationAngularVelocity);
+ m_anisotropicFriction.serialize(dataOut->m_anisotropicFriction);
+ dataOut->m_hasAnisotropicFriction = m_hasAnisotropicFriction;
+ dataOut->m_contactProcessingThreshold = m_contactProcessingThreshold;
+ dataOut->m_broadphaseHandle = 0;
+ dataOut->m_collisionShape = serializer->getUniquePointer(m_collisionShape);
+ dataOut->m_rootCollisionShape = 0;//@todo
+ dataOut->m_collisionFlags = m_collisionFlags;
+ dataOut->m_islandTag1 = m_islandTag1;
+ dataOut->m_companionId = m_companionId;
+ dataOut->m_activationState1 = m_activationState1;
+ dataOut->m_deactivationTime = m_deactivationTime;
+ dataOut->m_friction = m_friction;
+ dataOut->m_rollingFriction = m_rollingFriction;
+ dataOut->m_contactDamping = m_contactDamping;
+ dataOut->m_contactStiffness = m_contactStiffness;
+ dataOut->m_restitution = m_restitution;
+ dataOut->m_internalType = m_internalType;
+
+ char* name = (char*) serializer->findNameForPointer(this);
+ dataOut->m_name = (char*)serializer->getUniquePointer(name);
+ if (dataOut->m_name)
+ {
+ serializer->serializeName(name);
+ }
+ dataOut->m_hitFraction = m_hitFraction;
+ dataOut->m_ccdSweptSphereRadius = m_ccdSweptSphereRadius;
+ dataOut->m_ccdMotionThreshold = m_ccdMotionThreshold;
+ dataOut->m_checkCollideWith = m_checkCollideWith;
+
+ // Fill padding with zeros to appease msan.
+ memset(dataOut->m_padding, 0, sizeof(dataOut->m_padding));
+
+ return btCollisionObjectDataName;
+}
+
+
+void btCollisionObject::serializeSingleObject(class btSerializer* serializer) const
+{
+ int len = calculateSerializeBufferSize();
+ btChunk* chunk = serializer->allocate(len,1);
+ const char* structType = serialize(chunk->m_oldPtr, serializer);
+ serializer->finalizeChunk(chunk,structType,BT_COLLISIONOBJECT_CODE,(void*)this);
+}
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCollisionObject.h b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCollisionObject.h
new file mode 100644
index 0000000000..fec831bffc
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCollisionObject.h
@@ -0,0 +1,679 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_COLLISION_OBJECT_H
+#define BT_COLLISION_OBJECT_H
+
+#include "LinearMath/btTransform.h"
+
+//island management, m_activationState1
+#define ACTIVE_TAG 1
+#define ISLAND_SLEEPING 2
+#define WANTS_DEACTIVATION 3
+#define DISABLE_DEACTIVATION 4
+#define DISABLE_SIMULATION 5
+
+struct btBroadphaseProxy;
+class btCollisionShape;
+struct btCollisionShapeData;
+#include "LinearMath/btMotionState.h"
+#include "LinearMath/btAlignedAllocator.h"
+#include "LinearMath/btAlignedObjectArray.h"
+
+typedef btAlignedObjectArray<class btCollisionObject*> btCollisionObjectArray;
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define btCollisionObjectData btCollisionObjectDoubleData
+#define btCollisionObjectDataName "btCollisionObjectDoubleData"
+#else
+#define btCollisionObjectData btCollisionObjectFloatData
+#define btCollisionObjectDataName "btCollisionObjectFloatData"
+#endif
+
+
+/// btCollisionObject can be used to manage collision detection objects.
+/// btCollisionObject maintains all information that is needed for a collision detection: Shape, Transform and AABB proxy.
+/// They can be added to the btCollisionWorld.
+ATTRIBUTE_ALIGNED16(class) btCollisionObject
+{
+
+protected:
+
+ btTransform m_worldTransform;
+
+ ///m_interpolationWorldTransform is used for CCD and interpolation
+ ///it can be either previous or future (predicted) transform
+ btTransform m_interpolationWorldTransform;
+ //those two are experimental: just added for bullet time effect, so you can still apply impulses (directly modifying velocities)
+ //without destroying the continuous interpolated motion (which uses this interpolation velocities)
+ btVector3 m_interpolationLinearVelocity;
+ btVector3 m_interpolationAngularVelocity;
+
+ btVector3 m_anisotropicFriction;
+ int m_hasAnisotropicFriction;
+ btScalar m_contactProcessingThreshold;
+
+ btBroadphaseProxy* m_broadphaseHandle;
+ btCollisionShape* m_collisionShape;
+ ///m_extensionPointer is used by some internal low-level Bullet extensions.
+ void* m_extensionPointer;
+
+ ///m_rootCollisionShape is temporarily used to store the original collision shape
+ ///The m_collisionShape might be temporarily replaced by a child collision shape during collision detection purposes
+ ///If it is NULL, the m_collisionShape is not temporarily replaced.
+ btCollisionShape* m_rootCollisionShape;
+
+ int m_collisionFlags;
+
+ int m_islandTag1;
+ int m_companionId;
+ int m_worldArrayIndex; // index of object in world's collisionObjects array
+
+ mutable int m_activationState1;
+ mutable btScalar m_deactivationTime;
+
+ btScalar m_friction;
+ btScalar m_restitution;
+ btScalar m_rollingFriction;//torsional friction orthogonal to contact normal (useful to stop spheres rolling forever)
+ btScalar m_spinningFriction; // torsional friction around the contact normal (useful for grasping)
+ btScalar m_contactDamping;
+ btScalar m_contactStiffness;
+
+
+
+ ///m_internalType is reserved to distinguish Bullet's btCollisionObject, btRigidBody, btSoftBody, btGhostObject etc.
+ ///do not assign your own m_internalType unless you write a new dynamics object class.
+ int m_internalType;
+
+ ///users can point to their objects, m_userPointer is not used by Bullet, see setUserPointer/getUserPointer
+
+ void* m_userObjectPointer;
+
+ int m_userIndex2;
+
+ int m_userIndex;
+
+ ///time of impact calculation
+ btScalar m_hitFraction;
+
+ ///Swept sphere radius (0.0 by default), see btConvexConvexAlgorithm::
+ btScalar m_ccdSweptSphereRadius;
+
+ /// Don't do continuous collision detection if the motion (in one step) is less then m_ccdMotionThreshold
+ btScalar m_ccdMotionThreshold;
+
+ /// If some object should have elaborate collision filtering by sub-classes
+ int m_checkCollideWith;
+
+ btAlignedObjectArray<const btCollisionObject*> m_objectsWithoutCollisionCheck;
+
+ ///internal update revision number. It will be increased when the object changes. This allows some subsystems to perform lazy evaluation.
+ int m_updateRevision;
+
+ btVector3 m_customDebugColorRGB;
+
+public:
+
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ enum CollisionFlags
+ {
+ CF_STATIC_OBJECT= 1,
+ CF_KINEMATIC_OBJECT= 2,
+ CF_NO_CONTACT_RESPONSE = 4,
+ CF_CUSTOM_MATERIAL_CALLBACK = 8,//this allows per-triangle material (friction/restitution)
+ CF_CHARACTER_OBJECT = 16,
+ CF_DISABLE_VISUALIZE_OBJECT = 32, //disable debug drawing
+ CF_DISABLE_SPU_COLLISION_PROCESSING = 64,//disable parallel/SPU processing
+ CF_HAS_CONTACT_STIFFNESS_DAMPING = 128,
+ CF_HAS_CUSTOM_DEBUG_RENDERING_COLOR = 256,
+ CF_HAS_FRICTION_ANCHOR = 512,
+ CF_HAS_COLLISION_SOUND_TRIGGER = 1024
+ };
+
+ enum CollisionObjectTypes
+ {
+ CO_COLLISION_OBJECT =1,
+ CO_RIGID_BODY=2,
+ ///CO_GHOST_OBJECT keeps track of all objects overlapping its AABB and that pass its collision filter
+ ///It is useful for collision sensors, explosion objects, character controller etc.
+ CO_GHOST_OBJECT=4,
+ CO_SOFT_BODY=8,
+ CO_HF_FLUID=16,
+ CO_USER_TYPE=32,
+ CO_FEATHERSTONE_LINK=64
+ };
+
+ enum AnisotropicFrictionFlags
+ {
+ CF_ANISOTROPIC_FRICTION_DISABLED=0,
+ CF_ANISOTROPIC_FRICTION = 1,
+ CF_ANISOTROPIC_ROLLING_FRICTION = 2
+ };
+
+ SIMD_FORCE_INLINE bool mergesSimulationIslands() const
+ {
+ ///static objects, kinematic and object without contact response don't merge islands
+ return ((m_collisionFlags & (CF_STATIC_OBJECT | CF_KINEMATIC_OBJECT | CF_NO_CONTACT_RESPONSE) )==0);
+ }
+
+ const btVector3& getAnisotropicFriction() const
+ {
+ return m_anisotropicFriction;
+ }
+ void setAnisotropicFriction(const btVector3& anisotropicFriction, int frictionMode = CF_ANISOTROPIC_FRICTION)
+ {
+ m_anisotropicFriction = anisotropicFriction;
+ bool isUnity = (anisotropicFriction[0]!=1.f) || (anisotropicFriction[1]!=1.f) || (anisotropicFriction[2]!=1.f);
+ m_hasAnisotropicFriction = isUnity?frictionMode : 0;
+ }
+ bool hasAnisotropicFriction(int frictionMode = CF_ANISOTROPIC_FRICTION) const
+ {
+ return (m_hasAnisotropicFriction&frictionMode)!=0;
+ }
+
+ ///the constraint solver can discard solving contacts, if the distance is above this threshold. 0 by default.
+ ///Note that using contacts with positive distance can improve stability. It increases, however, the chance of colliding with degerate contacts, such as 'interior' triangle edges
+ void setContactProcessingThreshold( btScalar contactProcessingThreshold)
+ {
+ m_contactProcessingThreshold = contactProcessingThreshold;
+ }
+ btScalar getContactProcessingThreshold() const
+ {
+ return m_contactProcessingThreshold;
+ }
+
+ SIMD_FORCE_INLINE bool isStaticObject() const {
+ return (m_collisionFlags & CF_STATIC_OBJECT) != 0;
+ }
+
+ SIMD_FORCE_INLINE bool isKinematicObject() const
+ {
+ return (m_collisionFlags & CF_KINEMATIC_OBJECT) != 0;
+ }
+
+ SIMD_FORCE_INLINE bool isStaticOrKinematicObject() const
+ {
+ return (m_collisionFlags & (CF_KINEMATIC_OBJECT | CF_STATIC_OBJECT)) != 0 ;
+ }
+
+ SIMD_FORCE_INLINE bool hasContactResponse() const {
+ return (m_collisionFlags & CF_NO_CONTACT_RESPONSE)==0;
+ }
+
+
+ btCollisionObject();
+
+ virtual ~btCollisionObject();
+
+ virtual void setCollisionShape(btCollisionShape* collisionShape)
+ {
+ m_updateRevision++;
+ m_collisionShape = collisionShape;
+ m_rootCollisionShape = collisionShape;
+ }
+
+ SIMD_FORCE_INLINE const btCollisionShape* getCollisionShape() const
+ {
+ return m_collisionShape;
+ }
+
+ SIMD_FORCE_INLINE btCollisionShape* getCollisionShape()
+ {
+ return m_collisionShape;
+ }
+
+ void setIgnoreCollisionCheck(const btCollisionObject* co, bool ignoreCollisionCheck)
+ {
+ if (ignoreCollisionCheck)
+ {
+ //We don't check for duplicates. Is it ok to leave that up to the user of this API?
+ //int index = m_objectsWithoutCollisionCheck.findLinearSearch(co);
+ //if (index == m_objectsWithoutCollisionCheck.size())
+ //{
+ m_objectsWithoutCollisionCheck.push_back(co);
+ //}
+ }
+ else
+ {
+ m_objectsWithoutCollisionCheck.remove(co);
+ }
+ m_checkCollideWith = m_objectsWithoutCollisionCheck.size() > 0;
+ }
+
+ virtual bool checkCollideWithOverride(const btCollisionObject* co) const
+ {
+ int index = m_objectsWithoutCollisionCheck.findLinearSearch(co);
+ if (index < m_objectsWithoutCollisionCheck.size())
+ {
+ return false;
+ }
+ return true;
+ }
+
+
+
+
+ ///Avoid using this internal API call, the extension pointer is used by some Bullet extensions.
+ ///If you need to store your own user pointer, use 'setUserPointer/getUserPointer' instead.
+ void* internalGetExtensionPointer() const
+ {
+ return m_extensionPointer;
+ }
+ ///Avoid using this internal API call, the extension pointer is used by some Bullet extensions
+ ///If you need to store your own user pointer, use 'setUserPointer/getUserPointer' instead.
+ void internalSetExtensionPointer(void* pointer)
+ {
+ m_extensionPointer = pointer;
+ }
+
+ SIMD_FORCE_INLINE int getActivationState() const { return m_activationState1;}
+
+ void setActivationState(int newState) const;
+
+ void setDeactivationTime(btScalar time)
+ {
+ m_deactivationTime = time;
+ }
+ btScalar getDeactivationTime() const
+ {
+ return m_deactivationTime;
+ }
+
+ void forceActivationState(int newState) const;
+
+ void activate(bool forceActivation = false) const;
+
+ SIMD_FORCE_INLINE bool isActive() const
+ {
+ return ((getActivationState() != ISLAND_SLEEPING) && (getActivationState() != DISABLE_SIMULATION));
+ }
+
+ void setRestitution(btScalar rest)
+ {
+ m_updateRevision++;
+ m_restitution = rest;
+ }
+ btScalar getRestitution() const
+ {
+ return m_restitution;
+ }
+ void setFriction(btScalar frict)
+ {
+ m_updateRevision++;
+ m_friction = frict;
+ }
+ btScalar getFriction() const
+ {
+ return m_friction;
+ }
+
+ void setRollingFriction(btScalar frict)
+ {
+ m_updateRevision++;
+ m_rollingFriction = frict;
+ }
+ btScalar getRollingFriction() const
+ {
+ return m_rollingFriction;
+ }
+ void setSpinningFriction(btScalar frict)
+ {
+ m_updateRevision++;
+ m_spinningFriction = frict;
+ }
+ btScalar getSpinningFriction() const
+ {
+ return m_spinningFriction;
+ }
+ void setContactStiffnessAndDamping(btScalar stiffness, btScalar damping)
+ {
+ m_updateRevision++;
+ m_contactStiffness = stiffness;
+ m_contactDamping = damping;
+
+ m_collisionFlags |=CF_HAS_CONTACT_STIFFNESS_DAMPING;
+
+ //avoid divisions by zero...
+ if (m_contactStiffness< SIMD_EPSILON)
+ {
+ m_contactStiffness = SIMD_EPSILON;
+ }
+ }
+
+ btScalar getContactStiffness() const
+ {
+ return m_contactStiffness;
+ }
+
+ btScalar getContactDamping() const
+ {
+ return m_contactDamping;
+ }
+
+ ///reserved for Bullet internal usage
+ int getInternalType() const
+ {
+ return m_internalType;
+ }
+
+ btTransform& getWorldTransform()
+ {
+ return m_worldTransform;
+ }
+
+ const btTransform& getWorldTransform() const
+ {
+ return m_worldTransform;
+ }
+
+ void setWorldTransform(const btTransform& worldTrans)
+ {
+ m_updateRevision++;
+ m_worldTransform = worldTrans;
+ }
+
+
+ SIMD_FORCE_INLINE btBroadphaseProxy* getBroadphaseHandle()
+ {
+ return m_broadphaseHandle;
+ }
+
+ SIMD_FORCE_INLINE const btBroadphaseProxy* getBroadphaseHandle() const
+ {
+ return m_broadphaseHandle;
+ }
+
+ void setBroadphaseHandle(btBroadphaseProxy* handle)
+ {
+ m_broadphaseHandle = handle;
+ }
+
+
+ const btTransform& getInterpolationWorldTransform() const
+ {
+ return m_interpolationWorldTransform;
+ }
+
+ btTransform& getInterpolationWorldTransform()
+ {
+ return m_interpolationWorldTransform;
+ }
+
+ void setInterpolationWorldTransform(const btTransform& trans)
+ {
+ m_updateRevision++;
+ m_interpolationWorldTransform = trans;
+ }
+
+ void setInterpolationLinearVelocity(const btVector3& linvel)
+ {
+ m_updateRevision++;
+ m_interpolationLinearVelocity = linvel;
+ }
+
+ void setInterpolationAngularVelocity(const btVector3& angvel)
+ {
+ m_updateRevision++;
+ m_interpolationAngularVelocity = angvel;
+ }
+
+ const btVector3& getInterpolationLinearVelocity() const
+ {
+ return m_interpolationLinearVelocity;
+ }
+
+ const btVector3& getInterpolationAngularVelocity() const
+ {
+ return m_interpolationAngularVelocity;
+ }
+
+ SIMD_FORCE_INLINE int getIslandTag() const
+ {
+ return m_islandTag1;
+ }
+
+ void setIslandTag(int tag)
+ {
+ m_islandTag1 = tag;
+ }
+
+ SIMD_FORCE_INLINE int getCompanionId() const
+ {
+ return m_companionId;
+ }
+
+ void setCompanionId(int id)
+ {
+ m_companionId = id;
+ }
+
+ SIMD_FORCE_INLINE int getWorldArrayIndex() const
+ {
+ return m_worldArrayIndex;
+ }
+
+ // only should be called by CollisionWorld
+ void setWorldArrayIndex(int ix)
+ {
+ m_worldArrayIndex = ix;
+ }
+
+ SIMD_FORCE_INLINE btScalar getHitFraction() const
+ {
+ return m_hitFraction;
+ }
+
+ void setHitFraction(btScalar hitFraction)
+ {
+ m_hitFraction = hitFraction;
+ }
+
+
+ SIMD_FORCE_INLINE int getCollisionFlags() const
+ {
+ return m_collisionFlags;
+ }
+
+ void setCollisionFlags(int flags)
+ {
+ m_collisionFlags = flags;
+ }
+
+ ///Swept sphere radius (0.0 by default), see btConvexConvexAlgorithm::
+ btScalar getCcdSweptSphereRadius() const
+ {
+ return m_ccdSweptSphereRadius;
+ }
+
+ ///Swept sphere radius (0.0 by default), see btConvexConvexAlgorithm::
+ void setCcdSweptSphereRadius(btScalar radius)
+ {
+ m_ccdSweptSphereRadius = radius;
+ }
+
+ btScalar getCcdMotionThreshold() const
+ {
+ return m_ccdMotionThreshold;
+ }
+
+ btScalar getCcdSquareMotionThreshold() const
+ {
+ return m_ccdMotionThreshold*m_ccdMotionThreshold;
+ }
+
+
+
+ /// Don't do continuous collision detection if the motion (in one step) is less then m_ccdMotionThreshold
+ void setCcdMotionThreshold(btScalar ccdMotionThreshold)
+ {
+ m_ccdMotionThreshold = ccdMotionThreshold;
+ }
+
+ ///users can point to their objects, userPointer is not used by Bullet
+ void* getUserPointer() const
+ {
+ return m_userObjectPointer;
+ }
+
+ int getUserIndex() const
+ {
+ return m_userIndex;
+ }
+
+ int getUserIndex2() const
+ {
+ return m_userIndex2;
+ }
+
+ ///users can point to their objects, userPointer is not used by Bullet
+ void setUserPointer(void* userPointer)
+ {
+ m_userObjectPointer = userPointer;
+ }
+
+ ///users can point to their objects, userPointer is not used by Bullet
+ void setUserIndex(int index)
+ {
+ m_userIndex = index;
+ }
+
+ void setUserIndex2(int index)
+ {
+ m_userIndex2 = index;
+ }
+
+ int getUpdateRevisionInternal() const
+ {
+ return m_updateRevision;
+ }
+
+ void setCustomDebugColor(const btVector3& colorRGB)
+ {
+ m_customDebugColorRGB = colorRGB;
+ m_collisionFlags |= CF_HAS_CUSTOM_DEBUG_RENDERING_COLOR;
+ }
+
+ void removeCustomDebugColor()
+ {
+ m_collisionFlags &= ~CF_HAS_CUSTOM_DEBUG_RENDERING_COLOR;
+ }
+
+ bool getCustomDebugColor(btVector3& colorRGB) const
+ {
+ bool hasCustomColor = (0!=(m_collisionFlags&CF_HAS_CUSTOM_DEBUG_RENDERING_COLOR));
+ if (hasCustomColor)
+ {
+ colorRGB = m_customDebugColorRGB;
+ }
+ return hasCustomColor;
+ }
+
+ inline bool checkCollideWith(const btCollisionObject* co) const
+ {
+ if (m_checkCollideWith)
+ return checkCollideWithOverride(co);
+
+ return true;
+ }
+
+ 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;
+
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btCollisionObjectDoubleData
+{
+ void *m_broadphaseHandle;
+ void *m_collisionShape;
+ btCollisionShapeData *m_rootCollisionShape;
+ char *m_name;
+
+ btTransformDoubleData m_worldTransform;
+ btTransformDoubleData m_interpolationWorldTransform;
+ btVector3DoubleData m_interpolationLinearVelocity;
+ btVector3DoubleData m_interpolationAngularVelocity;
+ btVector3DoubleData m_anisotropicFriction;
+ double m_contactProcessingThreshold;
+ double m_deactivationTime;
+ double m_friction;
+ double m_rollingFriction;
+ double m_contactDamping;
+ double m_contactStiffness;
+ double m_restitution;
+ double m_hitFraction;
+ double m_ccdSweptSphereRadius;
+ double m_ccdMotionThreshold;
+
+ int m_hasAnisotropicFriction;
+ int m_collisionFlags;
+ int m_islandTag1;
+ int m_companionId;
+ int m_activationState1;
+ int m_internalType;
+ int m_checkCollideWith;
+
+ char m_padding[4];
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btCollisionObjectFloatData
+{
+ void *m_broadphaseHandle;
+ void *m_collisionShape;
+ btCollisionShapeData *m_rootCollisionShape;
+ char *m_name;
+
+ btTransformFloatData m_worldTransform;
+ btTransformFloatData m_interpolationWorldTransform;
+ btVector3FloatData m_interpolationLinearVelocity;
+ btVector3FloatData m_interpolationAngularVelocity;
+ btVector3FloatData m_anisotropicFriction;
+ float m_contactProcessingThreshold;
+ float m_deactivationTime;
+ float m_friction;
+ float m_rollingFriction;
+ float m_contactDamping;
+ float m_contactStiffness;
+ float m_restitution;
+ float m_hitFraction;
+ float m_ccdSweptSphereRadius;
+ float m_ccdMotionThreshold;
+
+ int m_hasAnisotropicFriction;
+ int m_collisionFlags;
+ int m_islandTag1;
+ int m_companionId;
+ int m_activationState1;
+ int m_internalType;
+ int m_checkCollideWith;
+ char m_padding[4];
+};
+
+
+
+SIMD_FORCE_INLINE int btCollisionObject::calculateSerializeBufferSize() const
+{
+ return sizeof(btCollisionObjectData);
+}
+
+
+
+#endif //BT_COLLISION_OBJECT_H
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h
new file mode 100644
index 0000000000..952440b7de
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h
@@ -0,0 +1,43 @@
+#ifndef BT_COLLISION_OBJECT_WRAPPER_H
+#define BT_COLLISION_OBJECT_WRAPPER_H
+
+///btCollisionObjectWrapperis an internal data structure.
+///Most users can ignore this and use btCollisionObject and btCollisionShape instead
+class btCollisionShape;
+class btCollisionObject;
+class btTransform;
+#include "LinearMath/btScalar.h" // for SIMD_FORCE_INLINE definition
+
+#define BT_DECLARE_STACK_ONLY_OBJECT \
+ private: \
+ void* operator new(size_t size); \
+ void operator delete(void*);
+
+struct btCollisionObjectWrapper;
+struct btCollisionObjectWrapper
+{
+BT_DECLARE_STACK_ONLY_OBJECT
+
+private:
+ btCollisionObjectWrapper(const btCollisionObjectWrapper&); // not implemented. Not allowed.
+ btCollisionObjectWrapper* operator=(const btCollisionObjectWrapper&);
+
+public:
+ const btCollisionObjectWrapper* m_parent;
+ const btCollisionShape* m_shape;
+ const btCollisionObject* m_collisionObject;
+ const btTransform& m_worldTransform;
+ 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)
+ {}
+
+ SIMD_FORCE_INLINE const btTransform& getWorldTransform() const { return m_worldTransform; }
+ SIMD_FORCE_INLINE const btCollisionObject* getCollisionObject() const { return m_collisionObject; }
+ SIMD_FORCE_INLINE const btCollisionShape* getCollisionShape() const { return m_shape; }
+};
+
+#endif //BT_COLLISION_OBJECT_WRAPPER_H
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp
new file mode 100644
index 0000000000..c3e912fdca
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp
@@ -0,0 +1,1666 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btCollisionWorld.h"
+#include "btCollisionDispatcher.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/CollisionShapes/btCollisionShape.h"
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h" //for raycasting
+#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h" //for raycasting
+#include "BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h" //for raycasting
+#include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h"
+#include "BulletCollision/CollisionShapes/btCompoundShape.h"
+#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h"
+#include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h"
+#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
+#include "BulletCollision/BroadphaseCollision/btDbvt.h"
+#include "LinearMath/btAabbUtil2.h"
+#include "LinearMath/btQuickprof.h"
+#include "LinearMath/btSerializer.h"
+#include "BulletCollision/CollisionShapes/btConvexPolyhedron.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
+
+//#define DISABLE_DBVT_COMPOUNDSHAPE_RAYCAST_ACCELERATION
+
+
+//#define USE_BRUTEFORCE_RAYBROADPHASE 1
+//RECALCULATE_AABB is slower, but benefit is that you don't need to call 'stepSimulation' or 'updateAabbs' before using a rayTest
+//#define RECALCULATE_AABB_RAYCAST 1
+
+//When the user doesn't provide dispatcher or broadphase, create basic versions (and delete them in destructor)
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h"
+#include "BulletCollision/CollisionDispatch/btCollisionConfiguration.h"
+
+
+///for debug drawing
+
+//for debug rendering
+#include "BulletCollision/CollisionShapes/btBoxShape.h"
+#include "BulletCollision/CollisionShapes/btCapsuleShape.h"
+#include "BulletCollision/CollisionShapes/btCompoundShape.h"
+#include "BulletCollision/CollisionShapes/btConeShape.h"
+#include "BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h"
+#include "BulletCollision/CollisionShapes/btCylinderShape.h"
+#include "BulletCollision/CollisionShapes/btMultiSphereShape.h"
+#include "BulletCollision/CollisionShapes/btPolyhedralConvexShape.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"
+#include "BulletCollision/CollisionShapes/btTriangleCallback.h"
+#include "BulletCollision/CollisionShapes/btTriangleMeshShape.h"
+#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h"
+
+
+
+btCollisionWorld::btCollisionWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache, btCollisionConfiguration* collisionConfiguration)
+:m_dispatcher1(dispatcher),
+m_broadphasePairCache(pairCache),
+m_debugDrawer(0),
+m_forceUpdateAllAabbs(true)
+{
+}
+
+
+btCollisionWorld::~btCollisionWorld()
+{
+
+ //clean up remaining objects
+ int i;
+ for (i=0;i<m_collisionObjects.size();i++)
+ {
+ btCollisionObject* collisionObject= m_collisionObjects[i];
+
+ btBroadphaseProxy* bp = collisionObject->getBroadphaseHandle();
+ if (bp)
+ {
+ //
+ // only clear the cached algorithms
+ //
+ getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bp,m_dispatcher1);
+ getBroadphase()->destroyProxy(bp,m_dispatcher1);
+ collisionObject->setBroadphaseHandle(0);
+ }
+ }
+
+
+}
+
+
+
+
+
+
+
+
+
+
+void btCollisionWorld::addCollisionObject(btCollisionObject* collisionObject, int collisionFilterGroup, int collisionFilterMask)
+{
+
+ btAssert(collisionObject);
+
+ //check that the object isn't already added
+ btAssert( m_collisionObjects.findLinearSearch(collisionObject) == m_collisionObjects.size());
+ btAssert(collisionObject->getWorldArrayIndex() == -1); // do not add the same object to more than one collision world
+
+ collisionObject->setWorldArrayIndex(m_collisionObjects.size());
+ m_collisionObjects.push_back(collisionObject);
+
+ //calculate new AABB
+ btTransform trans = collisionObject->getWorldTransform();
+
+ btVector3 minAabb;
+ btVector3 maxAabb;
+ collisionObject->getCollisionShape()->getAabb(trans,minAabb,maxAabb);
+
+ int type = collisionObject->getCollisionShape()->getShapeType();
+ collisionObject->setBroadphaseHandle( getBroadphase()->createProxy(
+ minAabb,
+ maxAabb,
+ type,
+ collisionObject,
+ collisionFilterGroup,
+ collisionFilterMask,
+ m_dispatcher1)) ;
+
+
+
+
+
+}
+
+
+
+void btCollisionWorld::updateSingleAabb(btCollisionObject* colObj)
+{
+ btVector3 minAabb,maxAabb;
+ colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb,maxAabb);
+ //need to increase the aabb for contact thresholds
+ btVector3 contactThreshold(gContactBreakingThreshold,gContactBreakingThreshold,gContactBreakingThreshold);
+ minAabb -= contactThreshold;
+ maxAabb += contactThreshold;
+
+ if(getDispatchInfo().m_useContinuous && colObj->getInternalType()==btCollisionObject::CO_RIGID_BODY && !colObj->isStaticOrKinematicObject())
+ {
+ btVector3 minAabb2,maxAabb2;
+ colObj->getCollisionShape()->getAabb(colObj->getInterpolationWorldTransform(),minAabb2,maxAabb2);
+ minAabb2 -= contactThreshold;
+ maxAabb2 += contactThreshold;
+ minAabb.setMin(minAabb2);
+ maxAabb.setMax(maxAabb2);
+ }
+
+ btBroadphaseInterface* bp = (btBroadphaseInterface*)m_broadphasePairCache;
+
+ //moving objects should be moderately sized, probably something wrong if not
+ if ( colObj->isStaticObject() || ((maxAabb-minAabb).length2() < btScalar(1e12)))
+ {
+ bp->setAabb(colObj->getBroadphaseHandle(),minAabb,maxAabb, m_dispatcher1);
+ } else
+ {
+ //something went wrong, investigate
+ //this assert is unwanted in 3D modelers (danger of loosing work)
+ colObj->setActivationState(DISABLE_SIMULATION);
+
+ static bool reportMe = true;
+ if (reportMe && m_debugDrawer)
+ {
+ reportMe = false;
+ m_debugDrawer->reportErrorWarning("Overflow in AABB, object removed from simulation");
+ m_debugDrawer->reportErrorWarning("If you can reproduce this, please email bugs@continuousphysics.com\n");
+ m_debugDrawer->reportErrorWarning("Please include above information, your Platform, version of OS.\n");
+ m_debugDrawer->reportErrorWarning("Thanks.\n");
+ }
+ }
+}
+
+void btCollisionWorld::updateAabbs()
+{
+ BT_PROFILE("updateAabbs");
+
+ btTransform predictedTrans;
+ for ( int i=0;i<m_collisionObjects.size();i++)
+ {
+ btCollisionObject* colObj = m_collisionObjects[i];
+ btAssert(colObj->getWorldArrayIndex() == i);
+
+ //only update aabb of active objects
+ if (m_forceUpdateAllAabbs || colObj->isActive())
+ {
+ updateSingleAabb(colObj);
+ }
+ }
+}
+
+
+void btCollisionWorld::computeOverlappingPairs()
+{
+ BT_PROFILE("calculateOverlappingPairs");
+ m_broadphasePairCache->calculateOverlappingPairs(m_dispatcher1);
+}
+
+void btCollisionWorld::performDiscreteCollisionDetection()
+{
+ BT_PROFILE("performDiscreteCollisionDetection");
+
+ btDispatcherInfo& dispatchInfo = getDispatchInfo();
+
+ updateAabbs();
+
+ computeOverlappingPairs();
+
+ btDispatcher* dispatcher = getDispatcher();
+ {
+ BT_PROFILE("dispatchAllCollisionPairs");
+ if (dispatcher)
+ dispatcher->dispatchAllCollisionPairs(m_broadphasePairCache->getOverlappingPairCache(),dispatchInfo,m_dispatcher1);
+ }
+
+}
+
+
+
+void btCollisionWorld::removeCollisionObject(btCollisionObject* collisionObject)
+{
+
+
+ //bool removeFromBroadphase = false;
+
+ {
+
+ btBroadphaseProxy* bp = collisionObject->getBroadphaseHandle();
+ if (bp)
+ {
+ //
+ // only clear the cached algorithms
+ //
+ getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bp,m_dispatcher1);
+ getBroadphase()->destroyProxy(bp,m_dispatcher1);
+ collisionObject->setBroadphaseHandle(0);
+ }
+ }
+
+
+ int iObj = collisionObject->getWorldArrayIndex();
+// btAssert(iObj >= 0 && iObj < m_collisionObjects.size()); // trying to remove an object that was never added or already removed previously?
+ if (iObj >= 0 && iObj < m_collisionObjects.size())
+ {
+ btAssert(collisionObject == m_collisionObjects[iObj]);
+ m_collisionObjects.swap(iObj, m_collisionObjects.size()-1);
+ m_collisionObjects.pop_back();
+ if (iObj < m_collisionObjects.size())
+ {
+ m_collisionObjects[iObj]->setWorldArrayIndex(iObj);
+ }
+ }
+ else
+ {
+ // slow linear search
+ //swapremove
+ m_collisionObjects.remove(collisionObject);
+ }
+ collisionObject->setWorldArrayIndex(-1);
+}
+
+
+void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTransform& rayToTrans,
+ btCollisionObject* collisionObject,
+ const btCollisionShape* collisionShape,
+ const btTransform& colObjWorldTransform,
+ RayResultCallback& resultCallback)
+{
+ btCollisionObjectWrapper colObWrap(0,collisionShape,collisionObject,colObjWorldTransform,-1,-1);
+ btCollisionWorld::rayTestSingleInternal(rayFromTrans,rayToTrans,&colObWrap,resultCallback);
+}
+
+void btCollisionWorld::rayTestSingleInternal(const btTransform& rayFromTrans,const btTransform& rayToTrans,
+ const btCollisionObjectWrapper* collisionObjectWrap,
+ RayResultCallback& resultCallback)
+{
+ btSphereShape pointShape(btScalar(0.0));
+ pointShape.setMargin(0.f);
+ const btConvexShape* castShape = &pointShape;
+ const btCollisionShape* collisionShape = collisionObjectWrap->getCollisionShape();
+ const btTransform& colObjWorldTransform = collisionObjectWrap->getWorldTransform();
+
+ if (collisionShape->isConvex())
+ {
+ // BT_PROFILE("rayTestConvex");
+ btConvexCast::CastResult castResult;
+ castResult.m_fraction = resultCallback.m_closestHitFraction;
+
+ btConvexShape* convexShape = (btConvexShape*) collisionShape;
+ btVoronoiSimplexSolver simplexSolver;
+ btSubsimplexConvexCast subSimplexConvexCaster(castShape,convexShape,&simplexSolver);
+
+ btGjkConvexCast gjkConvexCaster(castShape,convexShape,&simplexSolver);
+
+ //btContinuousConvexCollision convexCaster(castShape,convexShape,&simplexSolver,0);
+
+ btConvexCast* convexCasterPtr = 0;
+ //use kF_UseSubSimplexConvexCastRaytest by default
+ if (resultCallback.m_flags & btTriangleRaycastCallback::kF_UseGjkConvexCastRaytest)
+ convexCasterPtr = &gjkConvexCaster;
+ else
+ convexCasterPtr = &subSimplexConvexCaster;
+
+ btConvexCast& convexCaster = *convexCasterPtr;
+
+ if (convexCaster.calcTimeOfImpact(rayFromTrans,rayToTrans,colObjWorldTransform,colObjWorldTransform,castResult))
+ {
+ //add hit
+ if (castResult.m_normal.length2() > btScalar(0.0001))
+ {
+ if (castResult.m_fraction < resultCallback.m_closestHitFraction)
+ {
+ //todo: figure out what this is about. When is rayFromTest.getBasis() not identity?
+#ifdef USE_SUBSIMPLEX_CONVEX_CAST
+ //rotate normal into worldspace
+ castResult.m_normal = rayFromTrans.getBasis() * castResult.m_normal;
+#endif //USE_SUBSIMPLEX_CONVEX_CAST
+
+ castResult.m_normal.normalize();
+ btCollisionWorld::LocalRayResult localRayResult
+ (
+ collisionObjectWrap->getCollisionObject(),
+ 0,
+ castResult.m_normal,
+ castResult.m_fraction
+ );
+
+ bool normalInWorldSpace = true;
+ resultCallback.addSingleResult(localRayResult, normalInWorldSpace);
+
+ }
+ }
+ }
+ } else {
+ if (collisionShape->isConcave())
+ {
+
+ //ConvexCast::CastResult
+ struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback
+ {
+ btCollisionWorld::RayResultCallback* m_resultCallback;
+ const btCollisionObject* m_collisionObject;
+ const btConcaveShape* m_triangleMesh;
+
+ btTransform m_colObjWorldTransform;
+
+ BridgeTriangleRaycastCallback( const btVector3& from,const btVector3& to,
+ btCollisionWorld::RayResultCallback* resultCallback, const btCollisionObject* collisionObject,const btConcaveShape* triangleMesh,const btTransform& colObjWorldTransform):
+ //@BP Mod
+ btTriangleRaycastCallback(from,to, resultCallback->m_flags),
+ m_resultCallback(resultCallback),
+ m_collisionObject(collisionObject),
+ m_triangleMesh(triangleMesh),
+ m_colObjWorldTransform(colObjWorldTransform)
+ {
+ }
+
+
+ virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex )
+ {
+ btCollisionWorld::LocalShapeInfo shapeInfo;
+ shapeInfo.m_shapePart = partId;
+ shapeInfo.m_triangleIndex = triangleIndex;
+
+ btVector3 hitNormalWorld = m_colObjWorldTransform.getBasis() * hitNormalLocal;
+
+ btCollisionWorld::LocalRayResult rayResult
+ (m_collisionObject,
+ &shapeInfo,
+ hitNormalWorld,
+ hitFraction);
+
+ bool normalInWorldSpace = true;
+ return m_resultCallback->addSingleResult(rayResult,normalInWorldSpace);
+ }
+
+ };
+
+ btTransform worldTocollisionObject = colObjWorldTransform.inverse();
+ btVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin();
+ btVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin();
+
+ // BT_PROFILE("rayTestConcave");
+ if (collisionShape->getShapeType()==TRIANGLE_MESH_SHAPE_PROXYTYPE)
+ {
+ ///optimized version for btBvhTriangleMeshShape
+ btBvhTriangleMeshShape* triangleMesh = (btBvhTriangleMeshShape*)collisionShape;
+
+ BridgeTriangleRaycastCallback rcb(rayFromLocal,rayToLocal,&resultCallback,collisionObjectWrap->getCollisionObject(),triangleMesh,colObjWorldTransform);
+ rcb.m_hitFraction = resultCallback.m_closestHitFraction;
+ triangleMesh->performRaycast(&rcb,rayFromLocal,rayToLocal);
+ }
+ else if (collisionShape->getShapeType() == SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE)
+ {
+ ///optimized version for btScaledBvhTriangleMeshShape
+ btScaledBvhTriangleMeshShape* scaledTriangleMesh = (btScaledBvhTriangleMeshShape*)collisionShape;
+ btBvhTriangleMeshShape* triangleMesh = (btBvhTriangleMeshShape*)scaledTriangleMesh->getChildShape();
+
+ //scale the ray positions
+ btVector3 scale = scaledTriangleMesh->getLocalScaling();
+ btVector3 rayFromLocalScaled = rayFromLocal / scale;
+ btVector3 rayToLocalScaled = rayToLocal / scale;
+
+ //perform raycast in the underlying btBvhTriangleMeshShape
+ BridgeTriangleRaycastCallback rcb(rayFromLocalScaled, rayToLocalScaled, &resultCallback, collisionObjectWrap->getCollisionObject(), triangleMesh, colObjWorldTransform);
+ rcb.m_hitFraction = resultCallback.m_closestHitFraction;
+ triangleMesh->performRaycast(&rcb, rayFromLocalScaled, rayToLocalScaled);
+ }
+ else
+ {
+ //generic (slower) case
+ btConcaveShape* concaveShape = (btConcaveShape*)collisionShape;
+
+ btTransform worldTocollisionObject = colObjWorldTransform.inverse();
+
+ btVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin();
+ btVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin();
+
+ //ConvexCast::CastResult
+
+ struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback
+ {
+ btCollisionWorld::RayResultCallback* m_resultCallback;
+ const btCollisionObject* m_collisionObject;
+ btConcaveShape* m_triangleMesh;
+
+ btTransform m_colObjWorldTransform;
+
+ BridgeTriangleRaycastCallback( const btVector3& from,const btVector3& to,
+ btCollisionWorld::RayResultCallback* resultCallback, const btCollisionObject* collisionObject,btConcaveShape* triangleMesh, const btTransform& colObjWorldTransform):
+ //@BP Mod
+ btTriangleRaycastCallback(from,to, resultCallback->m_flags),
+ m_resultCallback(resultCallback),
+ m_collisionObject(collisionObject),
+ m_triangleMesh(triangleMesh),
+ m_colObjWorldTransform(colObjWorldTransform)
+ {
+ }
+
+
+ virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex )
+ {
+ btCollisionWorld::LocalShapeInfo shapeInfo;
+ shapeInfo.m_shapePart = partId;
+ shapeInfo.m_triangleIndex = triangleIndex;
+
+ btVector3 hitNormalWorld = m_colObjWorldTransform.getBasis() * hitNormalLocal;
+
+ btCollisionWorld::LocalRayResult rayResult
+ (m_collisionObject,
+ &shapeInfo,
+ hitNormalWorld,
+ hitFraction);
+
+ bool normalInWorldSpace = true;
+ return m_resultCallback->addSingleResult(rayResult,normalInWorldSpace);
+ }
+
+ };
+
+
+ BridgeTriangleRaycastCallback rcb(rayFromLocal,rayToLocal,&resultCallback,collisionObjectWrap->getCollisionObject(),concaveShape, colObjWorldTransform);
+ rcb.m_hitFraction = resultCallback.m_closestHitFraction;
+
+ btVector3 rayAabbMinLocal = rayFromLocal;
+ rayAabbMinLocal.setMin(rayToLocal);
+ btVector3 rayAabbMaxLocal = rayFromLocal;
+ rayAabbMaxLocal.setMax(rayToLocal);
+
+ concaveShape->processAllTriangles(&rcb,rayAabbMinLocal,rayAabbMaxLocal);
+ }
+ } else {
+ // BT_PROFILE("rayTestCompound");
+ if (collisionShape->isCompound())
+ {
+ struct LocalInfoAdder2 : public RayResultCallback
+ {
+ RayResultCallback* m_userCallback;
+ int m_i;
+
+ LocalInfoAdder2 (int i, RayResultCallback *user)
+ : m_userCallback(user), m_i(i)
+ {
+ m_closestHitFraction = m_userCallback->m_closestHitFraction;
+ m_flags = m_userCallback->m_flags;
+ }
+ virtual bool needsCollision(btBroadphaseProxy* p) const
+ {
+ return m_userCallback->needsCollision(p);
+ }
+
+ virtual btScalar addSingleResult (btCollisionWorld::LocalRayResult &r, bool b)
+ {
+ btCollisionWorld::LocalShapeInfo shapeInfo;
+ shapeInfo.m_shapePart = -1;
+ shapeInfo.m_triangleIndex = m_i;
+ if (r.m_localShapeInfo == NULL)
+ r.m_localShapeInfo = &shapeInfo;
+
+ const btScalar result = m_userCallback->addSingleResult(r, b);
+ m_closestHitFraction = m_userCallback->m_closestHitFraction;
+ return result;
+ }
+ };
+
+ struct RayTester : btDbvt::ICollide
+ {
+ const btCollisionObject* m_collisionObject;
+ const btCompoundShape* m_compoundShape;
+ const btTransform& m_colObjWorldTransform;
+ const btTransform& m_rayFromTrans;
+ const btTransform& m_rayToTrans;
+ RayResultCallback& m_resultCallback;
+
+ RayTester(const btCollisionObject* collisionObject,
+ const btCompoundShape* compoundShape,
+ const btTransform& colObjWorldTransform,
+ const btTransform& rayFromTrans,
+ const btTransform& rayToTrans,
+ RayResultCallback& resultCallback):
+ m_collisionObject(collisionObject),
+ m_compoundShape(compoundShape),
+ m_colObjWorldTransform(colObjWorldTransform),
+ m_rayFromTrans(rayFromTrans),
+ m_rayToTrans(rayToTrans),
+ m_resultCallback(resultCallback)
+ {
+
+ }
+
+ void ProcessLeaf(int i)
+ {
+ const btCollisionShape* childCollisionShape = m_compoundShape->getChildShape(i);
+ const btTransform& childTrans = m_compoundShape->getChildTransform(i);
+ btTransform childWorldTrans = m_colObjWorldTransform * childTrans;
+
+ btCollisionObjectWrapper tmpOb(0,childCollisionShape,m_collisionObject,childWorldTrans,-1,i);
+ // replace collision shape so that callback can determine the triangle
+
+
+
+ LocalInfoAdder2 my_cb(i, &m_resultCallback);
+
+ rayTestSingleInternal(
+ m_rayFromTrans,
+ m_rayToTrans,
+ &tmpOb,
+ my_cb);
+
+ }
+
+ void Process(const btDbvtNode* leaf)
+ {
+ ProcessLeaf(leaf->dataAsInt);
+ }
+ };
+
+ const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(collisionShape);
+ const btDbvt* dbvt = compoundShape->getDynamicAabbTree();
+
+
+ RayTester rayCB(
+ collisionObjectWrap->getCollisionObject(),
+ compoundShape,
+ colObjWorldTransform,
+ rayFromTrans,
+ rayToTrans,
+ resultCallback);
+#ifndef DISABLE_DBVT_COMPOUNDSHAPE_RAYCAST_ACCELERATION
+ if (dbvt)
+ {
+ btVector3 localRayFrom = colObjWorldTransform.inverseTimes(rayFromTrans).getOrigin();
+ btVector3 localRayTo = colObjWorldTransform.inverseTimes(rayToTrans).getOrigin();
+ btDbvt::rayTest(dbvt->m_root, localRayFrom , localRayTo, rayCB);
+ }
+ else
+#endif //DISABLE_DBVT_COMPOUNDSHAPE_RAYCAST_ACCELERATION
+ {
+ for (int i = 0, n = compoundShape->getNumChildShapes(); i < n; ++i)
+ {
+ rayCB.ProcessLeaf(i);
+ }
+ }
+ }
+ }
+ }
+}
+
+void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const btTransform& convexFromTrans,const btTransform& convexToTrans,
+ btCollisionObject* collisionObject,
+ const btCollisionShape* collisionShape,
+ const btTransform& colObjWorldTransform,
+ ConvexResultCallback& resultCallback, btScalar allowedPenetration)
+{
+ btCollisionObjectWrapper tmpOb(0,collisionShape,collisionObject,colObjWorldTransform,-1,-1);
+ btCollisionWorld::objectQuerySingleInternal(castShape,convexFromTrans,convexToTrans,&tmpOb,resultCallback,allowedPenetration);
+}
+
+void btCollisionWorld::objectQuerySingleInternal(const btConvexShape* castShape,const btTransform& convexFromTrans,const btTransform& convexToTrans,
+ const btCollisionObjectWrapper* colObjWrap,
+ ConvexResultCallback& resultCallback, btScalar allowedPenetration)
+{
+ const btCollisionShape* collisionShape = colObjWrap->getCollisionShape();
+ const btTransform& colObjWorldTransform = colObjWrap->getWorldTransform();
+
+ if (collisionShape->isConvex())
+ {
+ //BT_PROFILE("convexSweepConvex");
+ btConvexCast::CastResult castResult;
+ castResult.m_allowedPenetration = allowedPenetration;
+ castResult.m_fraction = resultCallback.m_closestHitFraction;//btScalar(1.);//??
+
+ btConvexShape* convexShape = (btConvexShape*) collisionShape;
+ btVoronoiSimplexSolver simplexSolver;
+ btGjkEpaPenetrationDepthSolver gjkEpaPenetrationSolver;
+
+ btContinuousConvexCollision convexCaster1(castShape,convexShape,&simplexSolver,&gjkEpaPenetrationSolver);
+ //btGjkConvexCast convexCaster2(castShape,convexShape,&simplexSolver);
+ //btSubsimplexConvexCast convexCaster3(castShape,convexShape,&simplexSolver);
+
+ btConvexCast* castPtr = &convexCaster1;
+
+
+
+ if (castPtr->calcTimeOfImpact(convexFromTrans,convexToTrans,colObjWorldTransform,colObjWorldTransform,castResult))
+ {
+ //add hit
+ if (castResult.m_normal.length2() > btScalar(0.0001))
+ {
+ if (castResult.m_fraction < resultCallback.m_closestHitFraction)
+ {
+ castResult.m_normal.normalize();
+ btCollisionWorld::LocalConvexResult localConvexResult
+ (
+ colObjWrap->getCollisionObject(),
+ 0,
+ castResult.m_normal,
+ castResult.m_hitPoint,
+ castResult.m_fraction
+ );
+
+ bool normalInWorldSpace = true;
+ resultCallback.addSingleResult(localConvexResult, normalInWorldSpace);
+
+ }
+ }
+ }
+ } else {
+ if (collisionShape->isConcave())
+ {
+ if (collisionShape->getShapeType()==TRIANGLE_MESH_SHAPE_PROXYTYPE)
+ {
+ //BT_PROFILE("convexSweepbtBvhTriangleMesh");
+ btBvhTriangleMeshShape* triangleMesh = (btBvhTriangleMeshShape*)collisionShape;
+ btTransform worldTocollisionObject = colObjWorldTransform.inverse();
+ btVector3 convexFromLocal = worldTocollisionObject * convexFromTrans.getOrigin();
+ btVector3 convexToLocal = worldTocollisionObject * convexToTrans.getOrigin();
+ // rotation of box in local mesh space = MeshRotation^-1 * ConvexToRotation
+ btTransform rotationXform = btTransform(worldTocollisionObject.getBasis() * convexToTrans.getBasis());
+
+ //ConvexCast::CastResult
+ struct BridgeTriangleConvexcastCallback : public btTriangleConvexcastCallback
+ {
+ btCollisionWorld::ConvexResultCallback* m_resultCallback;
+ const btCollisionObject* m_collisionObject;
+ btTriangleMeshShape* m_triangleMesh;
+
+ BridgeTriangleConvexcastCallback(const btConvexShape* castShape, const btTransform& from,const btTransform& to,
+ btCollisionWorld::ConvexResultCallback* resultCallback, const btCollisionObject* collisionObject,btTriangleMeshShape* triangleMesh, const btTransform& triangleToWorld):
+ btTriangleConvexcastCallback(castShape, from,to, triangleToWorld, triangleMesh->getMargin()),
+ m_resultCallback(resultCallback),
+ m_collisionObject(collisionObject),
+ m_triangleMesh(triangleMesh)
+ {
+ }
+
+
+ virtual btScalar reportHit(const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex )
+ {
+ btCollisionWorld::LocalShapeInfo shapeInfo;
+ shapeInfo.m_shapePart = partId;
+ shapeInfo.m_triangleIndex = triangleIndex;
+ if (hitFraction <= m_resultCallback->m_closestHitFraction)
+ {
+
+ btCollisionWorld::LocalConvexResult convexResult
+ (m_collisionObject,
+ &shapeInfo,
+ hitNormalLocal,
+ hitPointLocal,
+ hitFraction);
+
+ bool normalInWorldSpace = true;
+
+
+ return m_resultCallback->addSingleResult(convexResult,normalInWorldSpace);
+ }
+ return hitFraction;
+ }
+
+ };
+
+ BridgeTriangleConvexcastCallback tccb(castShape, convexFromTrans,convexToTrans,&resultCallback,colObjWrap->getCollisionObject(),triangleMesh, colObjWorldTransform);
+ tccb.m_hitFraction = resultCallback.m_closestHitFraction;
+ tccb.m_allowedPenetration = allowedPenetration;
+ btVector3 boxMinLocal, boxMaxLocal;
+ castShape->getAabb(rotationXform, boxMinLocal, boxMaxLocal);
+ triangleMesh->performConvexcast(&tccb,convexFromLocal,convexToLocal,boxMinLocal, boxMaxLocal);
+ } else
+ {
+ if (collisionShape->getShapeType()==STATIC_PLANE_PROXYTYPE)
+ {
+ btConvexCast::CastResult castResult;
+ castResult.m_allowedPenetration = allowedPenetration;
+ castResult.m_fraction = resultCallback.m_closestHitFraction;
+ btStaticPlaneShape* planeShape = (btStaticPlaneShape*) collisionShape;
+ btContinuousConvexCollision convexCaster1(castShape,planeShape);
+ btConvexCast* castPtr = &convexCaster1;
+
+ if (castPtr->calcTimeOfImpact(convexFromTrans,convexToTrans,colObjWorldTransform,colObjWorldTransform,castResult))
+ {
+ //add hit
+ if (castResult.m_normal.length2() > btScalar(0.0001))
+ {
+ if (castResult.m_fraction < resultCallback.m_closestHitFraction)
+ {
+ castResult.m_normal.normalize();
+ btCollisionWorld::LocalConvexResult localConvexResult
+ (
+ colObjWrap->getCollisionObject(),
+ 0,
+ castResult.m_normal,
+ castResult.m_hitPoint,
+ castResult.m_fraction
+ );
+
+ bool normalInWorldSpace = true;
+ resultCallback.addSingleResult(localConvexResult, normalInWorldSpace);
+ }
+ }
+ }
+
+ } else
+ {
+ //BT_PROFILE("convexSweepConcave");
+ btConcaveShape* concaveShape = (btConcaveShape*)collisionShape;
+ btTransform worldTocollisionObject = colObjWorldTransform.inverse();
+ btVector3 convexFromLocal = worldTocollisionObject * convexFromTrans.getOrigin();
+ btVector3 convexToLocal = worldTocollisionObject * convexToTrans.getOrigin();
+ // rotation of box in local mesh space = MeshRotation^-1 * ConvexToRotation
+ btTransform rotationXform = btTransform(worldTocollisionObject.getBasis() * convexToTrans.getBasis());
+
+ //ConvexCast::CastResult
+ struct BridgeTriangleConvexcastCallback : public btTriangleConvexcastCallback
+ {
+ btCollisionWorld::ConvexResultCallback* m_resultCallback;
+ const btCollisionObject* m_collisionObject;
+ btConcaveShape* m_triangleMesh;
+
+ BridgeTriangleConvexcastCallback(const btConvexShape* castShape, const btTransform& from,const btTransform& to,
+ btCollisionWorld::ConvexResultCallback* resultCallback, const btCollisionObject* collisionObject,btConcaveShape* triangleMesh, const btTransform& triangleToWorld):
+ btTriangleConvexcastCallback(castShape, from,to, triangleToWorld, triangleMesh->getMargin()),
+ m_resultCallback(resultCallback),
+ m_collisionObject(collisionObject),
+ m_triangleMesh(triangleMesh)
+ {
+ }
+
+
+ virtual btScalar reportHit(const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex )
+ {
+ btCollisionWorld::LocalShapeInfo shapeInfo;
+ shapeInfo.m_shapePart = partId;
+ shapeInfo.m_triangleIndex = triangleIndex;
+ if (hitFraction <= m_resultCallback->m_closestHitFraction)
+ {
+
+ btCollisionWorld::LocalConvexResult convexResult
+ (m_collisionObject,
+ &shapeInfo,
+ hitNormalLocal,
+ hitPointLocal,
+ hitFraction);
+
+ bool normalInWorldSpace = true;
+
+ return m_resultCallback->addSingleResult(convexResult,normalInWorldSpace);
+ }
+ return hitFraction;
+ }
+
+ };
+
+ BridgeTriangleConvexcastCallback tccb(castShape, convexFromTrans,convexToTrans,&resultCallback,colObjWrap->getCollisionObject(),concaveShape, colObjWorldTransform);
+ tccb.m_hitFraction = resultCallback.m_closestHitFraction;
+ tccb.m_allowedPenetration = allowedPenetration;
+ btVector3 boxMinLocal, boxMaxLocal;
+ castShape->getAabb(rotationXform, boxMinLocal, boxMaxLocal);
+
+ btVector3 rayAabbMinLocal = convexFromLocal;
+ rayAabbMinLocal.setMin(convexToLocal);
+ btVector3 rayAabbMaxLocal = convexFromLocal;
+ rayAabbMaxLocal.setMax(convexToLocal);
+ rayAabbMinLocal += boxMinLocal;
+ rayAabbMaxLocal += boxMaxLocal;
+ concaveShape->processAllTriangles(&tccb,rayAabbMinLocal,rayAabbMaxLocal);
+ }
+ }
+ } else {
+ if (collisionShape->isCompound())
+ {
+ struct btCompoundLeafCallback : btDbvt::ICollide
+ {
+ btCompoundLeafCallback(
+ const btCollisionObjectWrapper* colObjWrap,
+ const btConvexShape* castShape,
+ const btTransform& convexFromTrans,
+ const btTransform& convexToTrans,
+ btScalar allowedPenetration,
+ const btCompoundShape* compoundShape,
+ const btTransform& colObjWorldTransform,
+ ConvexResultCallback& resultCallback)
+ :
+ m_colObjWrap(colObjWrap),
+ m_castShape(castShape),
+ m_convexFromTrans(convexFromTrans),
+ m_convexToTrans(convexToTrans),
+ m_allowedPenetration(allowedPenetration),
+ m_compoundShape(compoundShape),
+ m_colObjWorldTransform(colObjWorldTransform),
+ m_resultCallback(resultCallback) {
+ }
+
+ const btCollisionObjectWrapper* m_colObjWrap;
+ const btConvexShape* m_castShape;
+ const btTransform& m_convexFromTrans;
+ const btTransform& m_convexToTrans;
+ btScalar m_allowedPenetration;
+ const btCompoundShape* m_compoundShape;
+ const btTransform& m_colObjWorldTransform;
+ ConvexResultCallback& m_resultCallback;
+
+ public:
+
+ void ProcessChild(int index, const btTransform& childTrans, const btCollisionShape* childCollisionShape)
+ {
+ btTransform childWorldTrans = m_colObjWorldTransform * childTrans;
+
+ struct LocalInfoAdder : public ConvexResultCallback {
+ ConvexResultCallback* m_userCallback;
+ int m_i;
+
+ LocalInfoAdder(int i, ConvexResultCallback *user)
+ : m_userCallback(user), m_i(i)
+ {
+ m_closestHitFraction = m_userCallback->m_closestHitFraction;
+ }
+ virtual bool needsCollision(btBroadphaseProxy* p) const
+ {
+ return m_userCallback->needsCollision(p);
+ }
+ virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& r, bool b)
+ {
+ btCollisionWorld::LocalShapeInfo shapeInfo;
+ shapeInfo.m_shapePart = -1;
+ shapeInfo.m_triangleIndex = m_i;
+ if (r.m_localShapeInfo == NULL)
+ r.m_localShapeInfo = &shapeInfo;
+ const btScalar result = m_userCallback->addSingleResult(r, b);
+ m_closestHitFraction = m_userCallback->m_closestHitFraction;
+ return result;
+
+ }
+ };
+
+ LocalInfoAdder my_cb(index, &m_resultCallback);
+
+ btCollisionObjectWrapper tmpObj(m_colObjWrap, childCollisionShape, m_colObjWrap->getCollisionObject(), childWorldTrans, -1, index);
+
+ objectQuerySingleInternal(m_castShape, m_convexFromTrans, m_convexToTrans, &tmpObj, my_cb, m_allowedPenetration);
+ }
+
+ void Process(const btDbvtNode* leaf)
+ {
+ // Processing leaf node
+ int index = leaf->dataAsInt;
+
+ btTransform childTrans = m_compoundShape->getChildTransform(index);
+ const btCollisionShape* childCollisionShape = m_compoundShape->getChildShape(index);
+
+ ProcessChild(index, childTrans, childCollisionShape);
+ }
+ };
+
+ BT_PROFILE("convexSweepCompound");
+ const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(collisionShape);
+
+ btVector3 fromLocalAabbMin, fromLocalAabbMax;
+ btVector3 toLocalAabbMin, toLocalAabbMax;
+
+ castShape->getAabb(colObjWorldTransform.inverse() * convexFromTrans, fromLocalAabbMin, fromLocalAabbMax);
+ castShape->getAabb(colObjWorldTransform.inverse() * convexToTrans, toLocalAabbMin, toLocalAabbMax);
+
+ fromLocalAabbMin.setMin(toLocalAabbMin);
+ fromLocalAabbMax.setMax(toLocalAabbMax);
+
+ btCompoundLeafCallback callback(colObjWrap, castShape, convexFromTrans, convexToTrans,
+ allowedPenetration, compoundShape, colObjWorldTransform, resultCallback);
+
+ const btDbvt* tree = compoundShape->getDynamicAabbTree();
+ if (tree) {
+ const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds = btDbvtVolume::FromMM(fromLocalAabbMin, fromLocalAabbMax);
+ tree->collideTV(tree->m_root, bounds, callback);
+ } else {
+ int i;
+ for (i=0;i<compoundShape->getNumChildShapes();i++)
+ {
+ const btCollisionShape* childCollisionShape = compoundShape->getChildShape(i);
+ btTransform childTrans = compoundShape->getChildTransform(i);
+ callback.ProcessChild(i, childTrans, childCollisionShape);
+ }
+ }
+ }
+ }
+ }
+}
+
+
+struct btSingleRayCallback : public btBroadphaseRayCallback
+{
+
+ btVector3 m_rayFromWorld;
+ btVector3 m_rayToWorld;
+ btTransform m_rayFromTrans;
+ btTransform m_rayToTrans;
+ btVector3 m_hitNormal;
+
+ const btCollisionWorld* m_world;
+ btCollisionWorld::RayResultCallback& m_resultCallback;
+
+ btSingleRayCallback(const btVector3& rayFromWorld,const btVector3& rayToWorld,const btCollisionWorld* world,btCollisionWorld::RayResultCallback& resultCallback)
+ :m_rayFromWorld(rayFromWorld),
+ m_rayToWorld(rayToWorld),
+ m_world(world),
+ m_resultCallback(resultCallback)
+ {
+ m_rayFromTrans.setIdentity();
+ m_rayFromTrans.setOrigin(m_rayFromWorld);
+ m_rayToTrans.setIdentity();
+ m_rayToTrans.setOrigin(m_rayToWorld);
+
+ btVector3 rayDir = (rayToWorld-rayFromWorld);
+
+ rayDir.normalize ();
+ ///what about division by zero? --> just set rayDirection[i] to INF/BT_LARGE_FLOAT
+ m_rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[0];
+ m_rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[1];
+ m_rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[2];
+ m_signs[0] = m_rayDirectionInverse[0] < 0.0;
+ m_signs[1] = m_rayDirectionInverse[1] < 0.0;
+ m_signs[2] = m_rayDirectionInverse[2] < 0.0;
+
+ m_lambda_max = rayDir.dot(m_rayToWorld-m_rayFromWorld);
+
+ }
+
+
+
+ virtual bool process(const btBroadphaseProxy* proxy)
+ {
+ ///terminate further ray tests, once the closestHitFraction reached zero
+ if (m_resultCallback.m_closestHitFraction == btScalar(0.f))
+ return false;
+
+ btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject;
+
+ //only perform raycast if filterMask matches
+ if(m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
+ {
+ //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
+ //btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
+#if 0
+#ifdef RECALCULATE_AABB
+ btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
+ collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax);
+#else
+ //getBroadphase()->getAabb(collisionObject->getBroadphaseHandle(),collisionObjectAabbMin,collisionObjectAabbMax);
+ const btVector3& collisionObjectAabbMin = collisionObject->getBroadphaseHandle()->m_aabbMin;
+ const btVector3& collisionObjectAabbMax = collisionObject->getBroadphaseHandle()->m_aabbMax;
+#endif
+#endif
+ //btScalar hitLambda = m_resultCallback.m_closestHitFraction;
+ //culling already done by broadphase
+ //if (btRayAabb(m_rayFromWorld,m_rayToWorld,collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,m_hitNormal))
+ {
+ m_world->rayTestSingle(m_rayFromTrans,m_rayToTrans,
+ collisionObject,
+ collisionObject->getCollisionShape(),
+ collisionObject->getWorldTransform(),
+ m_resultCallback);
+ }
+ }
+ return true;
+ }
+};
+
+void btCollisionWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const
+{
+ //BT_PROFILE("rayTest");
+ /// use the broadphase to accelerate the search for objects, based on their aabb
+ /// and for each object with ray-aabb overlap, perform an exact ray test
+ btSingleRayCallback rayCB(rayFromWorld,rayToWorld,this,resultCallback);
+
+#ifndef USE_BRUTEFORCE_RAYBROADPHASE
+ m_broadphasePairCache->rayTest(rayFromWorld,rayToWorld,rayCB);
+#else
+ for (int i=0;i<this->getNumCollisionObjects();i++)
+ {
+ rayCB.process(m_collisionObjects[i]->getBroadphaseHandle());
+ }
+#endif //USE_BRUTEFORCE_RAYBROADPHASE
+
+}
+
+
+struct btSingleSweepCallback : public btBroadphaseRayCallback
+{
+
+ btTransform m_convexFromTrans;
+ btTransform m_convexToTrans;
+ btVector3 m_hitNormal;
+ const btCollisionWorld* m_world;
+ btCollisionWorld::ConvexResultCallback& m_resultCallback;
+ btScalar m_allowedCcdPenetration;
+ const btConvexShape* m_castShape;
+
+
+ btSingleSweepCallback(const btConvexShape* castShape, const btTransform& convexFromTrans,const btTransform& convexToTrans,const btCollisionWorld* world,btCollisionWorld::ConvexResultCallback& resultCallback,btScalar allowedPenetration)
+ :m_convexFromTrans(convexFromTrans),
+ m_convexToTrans(convexToTrans),
+ m_world(world),
+ m_resultCallback(resultCallback),
+ m_allowedCcdPenetration(allowedPenetration),
+ m_castShape(castShape)
+ {
+ btVector3 unnormalizedRayDir = (m_convexToTrans.getOrigin()-m_convexFromTrans.getOrigin());
+ btVector3 rayDir = unnormalizedRayDir.normalized();
+ ///what about division by zero? --> just set rayDirection[i] to INF/BT_LARGE_FLOAT
+ m_rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[0];
+ m_rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[1];
+ m_rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[2];
+ m_signs[0] = m_rayDirectionInverse[0] < 0.0;
+ m_signs[1] = m_rayDirectionInverse[1] < 0.0;
+ m_signs[2] = m_rayDirectionInverse[2] < 0.0;
+
+ m_lambda_max = rayDir.dot(unnormalizedRayDir);
+
+ }
+
+ virtual bool process(const btBroadphaseProxy* proxy)
+ {
+ ///terminate further convex sweep tests, once the closestHitFraction reached zero
+ if (m_resultCallback.m_closestHitFraction == btScalar(0.f))
+ return false;
+
+ btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject;
+
+ //only perform raycast if filterMask matches
+ if(m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle())) {
+ //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
+ m_world->objectQuerySingle(m_castShape, m_convexFromTrans,m_convexToTrans,
+ collisionObject,
+ collisionObject->getCollisionShape(),
+ collisionObject->getWorldTransform(),
+ m_resultCallback,
+ m_allowedCcdPenetration);
+ }
+
+ return true;
+ }
+};
+
+
+
+void btCollisionWorld::convexSweepTest(const btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration) const
+{
+
+ BT_PROFILE("convexSweepTest");
+ /// use the broadphase to accelerate the search for objects, based on their aabb
+ /// and for each object with ray-aabb overlap, perform an exact ray test
+ /// unfortunately the implementation for rayTest and convexSweepTest duplicated, albeit practically identical
+
+
+
+ btTransform convexFromTrans,convexToTrans;
+ convexFromTrans = convexFromWorld;
+ convexToTrans = convexToWorld;
+ btVector3 castShapeAabbMin, castShapeAabbMax;
+ /* Compute AABB that encompasses angular movement */
+ {
+ btVector3 linVel, angVel;
+ btTransformUtil::calculateVelocity (convexFromTrans, convexToTrans, 1.0f, linVel, angVel);
+ btVector3 zeroLinVel;
+ zeroLinVel.setValue(0,0,0);
+ btTransform R;
+ R.setIdentity ();
+ R.setRotation (convexFromTrans.getRotation());
+ castShape->calculateTemporalAabb (R, zeroLinVel, angVel, 1.0f, castShapeAabbMin, castShapeAabbMax);
+ }
+
+#ifndef USE_BRUTEFORCE_RAYBROADPHASE
+
+ btSingleSweepCallback convexCB(castShape,convexFromWorld,convexToWorld,this,resultCallback,allowedCcdPenetration);
+
+ m_broadphasePairCache->rayTest(convexFromTrans.getOrigin(),convexToTrans.getOrigin(),convexCB,castShapeAabbMin,castShapeAabbMax);
+
+#else
+ /// go over all objects, and if the ray intersects their aabb + cast shape aabb,
+ // do a ray-shape query using convexCaster (CCD)
+ int i;
+ for (i=0;i<m_collisionObjects.size();i++)
+ {
+ btCollisionObject* collisionObject= m_collisionObjects[i];
+ //only perform raycast if filterMask matches
+ if(resultCallback.needsCollision(collisionObject->getBroadphaseHandle())) {
+ //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
+ btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
+ collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax);
+ AabbExpand (collisionObjectAabbMin, collisionObjectAabbMax, castShapeAabbMin, castShapeAabbMax);
+ btScalar hitLambda = btScalar(1.); //could use resultCallback.m_closestHitFraction, but needs testing
+ btVector3 hitNormal;
+ if (btRayAabb(convexFromWorld.getOrigin(),convexToWorld.getOrigin(),collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,hitNormal))
+ {
+ objectQuerySingle(castShape, convexFromTrans,convexToTrans,
+ collisionObject,
+ collisionObject->getCollisionShape(),
+ collisionObject->getWorldTransform(),
+ resultCallback,
+ allowedCcdPenetration);
+ }
+ }
+ }
+#endif //USE_BRUTEFORCE_RAYBROADPHASE
+}
+
+
+
+struct btBridgedManifoldResult : public btManifoldResult
+{
+
+ btCollisionWorld::ContactResultCallback& m_resultCallback;
+
+ btBridgedManifoldResult( const btCollisionObjectWrapper* obj0Wrap,const btCollisionObjectWrapper* obj1Wrap,btCollisionWorld::ContactResultCallback& resultCallback )
+ :btManifoldResult(obj0Wrap,obj1Wrap),
+ m_resultCallback(resultCallback)
+ {
+ }
+
+ virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth)
+ {
+ bool isSwapped = m_manifoldPtr->getBody0() != m_body0Wrap->getCollisionObject();
+ btVector3 pointA = pointInWorld + normalOnBInWorld * depth;
+ btVector3 localA;
+ btVector3 localB;
+ if (isSwapped)
+ {
+ localA = m_body1Wrap->getCollisionObject()->getWorldTransform().invXform(pointA );
+ localB = m_body0Wrap->getCollisionObject()->getWorldTransform().invXform(pointInWorld);
+ } else
+ {
+ localA = m_body0Wrap->getCollisionObject()->getWorldTransform().invXform(pointA );
+ localB = m_body1Wrap->getCollisionObject()->getWorldTransform().invXform(pointInWorld);
+ }
+
+ btManifoldPoint newPt(localA,localB,normalOnBInWorld,depth);
+ newPt.m_positionWorldOnA = pointA;
+ newPt.m_positionWorldOnB = pointInWorld;
+
+ //BP mod, store contact triangles.
+ if (isSwapped)
+ {
+ newPt.m_partId0 = m_partId1;
+ newPt.m_partId1 = m_partId0;
+ newPt.m_index0 = m_index1;
+ newPt.m_index1 = m_index0;
+ } else
+ {
+ newPt.m_partId0 = m_partId0;
+ newPt.m_partId1 = m_partId1;
+ newPt.m_index0 = m_index0;
+ newPt.m_index1 = m_index1;
+ }
+
+ //experimental feature info, for per-triangle material etc.
+ const btCollisionObjectWrapper* obj0Wrap = isSwapped? m_body1Wrap : m_body0Wrap;
+ const btCollisionObjectWrapper* obj1Wrap = isSwapped? m_body0Wrap : m_body1Wrap;
+ m_resultCallback.addSingleResult(newPt,obj0Wrap,newPt.m_partId0,newPt.m_index0,obj1Wrap,newPt.m_partId1,newPt.m_index1);
+
+ }
+
+};
+
+
+
+struct btSingleContactCallback : public btBroadphaseAabbCallback
+{
+
+ btCollisionObject* m_collisionObject;
+ btCollisionWorld* m_world;
+ btCollisionWorld::ContactResultCallback& m_resultCallback;
+
+
+ btSingleContactCallback(btCollisionObject* collisionObject, btCollisionWorld* world,btCollisionWorld::ContactResultCallback& resultCallback)
+ :m_collisionObject(collisionObject),
+ m_world(world),
+ m_resultCallback(resultCallback)
+ {
+ }
+
+ virtual bool process(const btBroadphaseProxy* proxy)
+ {
+ btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject;
+ if (collisionObject == m_collisionObject)
+ return true;
+
+ //only perform raycast if filterMask matches
+ if(m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
+ {
+ btCollisionObjectWrapper ob0(0,m_collisionObject->getCollisionShape(),m_collisionObject,m_collisionObject->getWorldTransform(),-1,-1);
+ btCollisionObjectWrapper ob1(0,collisionObject->getCollisionShape(),collisionObject,collisionObject->getWorldTransform(),-1,-1);
+
+ btCollisionAlgorithm* algorithm = m_world->getDispatcher()->findAlgorithm(&ob0,&ob1,0, BT_CLOSEST_POINT_ALGORITHMS);
+ if (algorithm)
+ {
+ btBridgedManifoldResult contactPointResult(&ob0,&ob1, m_resultCallback);
+ //discrete collision detection query
+
+ algorithm->processCollision(&ob0,&ob1, m_world->getDispatchInfo(),&contactPointResult);
+
+ algorithm->~btCollisionAlgorithm();
+ m_world->getDispatcher()->freeCollisionAlgorithm(algorithm);
+ }
+ }
+ return true;
+ }
+};
+
+
+///contactTest performs a discrete collision test against all objects in the btCollisionWorld, and calls the resultCallback.
+///it reports one or more contact points for every overlapping object (including the one with deepest penetration)
+void btCollisionWorld::contactTest( btCollisionObject* colObj, ContactResultCallback& resultCallback)
+{
+ btVector3 aabbMin,aabbMax;
+ colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(),aabbMin,aabbMax);
+ btSingleContactCallback contactCB(colObj,this,resultCallback);
+
+ m_broadphasePairCache->aabbTest(aabbMin,aabbMax,contactCB);
+}
+
+
+///contactTest performs a discrete collision test between two collision objects and calls the resultCallback if overlap if detected.
+///it reports one or more contact points (including the one with deepest penetration)
+void btCollisionWorld::contactPairTest(btCollisionObject* colObjA, btCollisionObject* colObjB, ContactResultCallback& resultCallback)
+{
+ btCollisionObjectWrapper obA(0,colObjA->getCollisionShape(),colObjA,colObjA->getWorldTransform(),-1,-1);
+ btCollisionObjectWrapper obB(0,colObjB->getCollisionShape(),colObjB,colObjB->getWorldTransform(),-1,-1);
+
+ btCollisionAlgorithm* algorithm = getDispatcher()->findAlgorithm(&obA,&obB, 0, BT_CLOSEST_POINT_ALGORITHMS);
+ if (algorithm)
+ {
+ btBridgedManifoldResult contactPointResult(&obA,&obB, resultCallback);
+ contactPointResult.m_closestPointDistanceThreshold = resultCallback.m_closestDistanceThreshold;
+ //discrete collision detection query
+ algorithm->processCollision(&obA,&obB, getDispatchInfo(),&contactPointResult);
+
+ algorithm->~btCollisionAlgorithm();
+ getDispatcher()->freeCollisionAlgorithm(algorithm);
+ }
+
+}
+
+
+
+
+class DebugDrawcallback : public btTriangleCallback, public btInternalTriangleIndexCallback
+{
+ btIDebugDraw* m_debugDrawer;
+ btVector3 m_color;
+ btTransform m_worldTrans;
+
+public:
+
+ DebugDrawcallback(btIDebugDraw* debugDrawer,const btTransform& worldTrans,const btVector3& color) :
+ m_debugDrawer(debugDrawer),
+ m_color(color),
+ m_worldTrans(worldTrans)
+ {
+ }
+
+ virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex)
+ {
+ processTriangle(triangle,partId,triangleIndex);
+ }
+
+ virtual void processTriangle(btVector3* triangle,int partId, int triangleIndex)
+ {
+ (void)partId;
+ (void)triangleIndex;
+
+ btVector3 wv0,wv1,wv2;
+ wv0 = m_worldTrans*triangle[0];
+ wv1 = m_worldTrans*triangle[1];
+ wv2 = m_worldTrans*triangle[2];
+ btVector3 center = (wv0+wv1+wv2)*btScalar(1./3.);
+
+ if (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawNormals )
+ {
+ btVector3 normal = (wv1-wv0).cross(wv2-wv0);
+ normal.normalize();
+ btVector3 normalColor(1,1,0);
+ m_debugDrawer->drawLine(center,center+normal,normalColor);
+ }
+ m_debugDrawer->drawLine(wv0,wv1,m_color);
+ m_debugDrawer->drawLine(wv1,wv2,m_color);
+ m_debugDrawer->drawLine(wv2,wv0,m_color);
+ }
+};
+
+
+void btCollisionWorld::debugDrawObject(const btTransform& worldTransform, const btCollisionShape* shape, const btVector3& color)
+{
+ // Draw a small simplex at the center of the object
+ if (getDebugDrawer() && getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawFrames)
+ {
+ getDebugDrawer()->drawTransform(worldTransform,.1);
+ }
+
+ if (shape->getShapeType() == COMPOUND_SHAPE_PROXYTYPE)
+ {
+ const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(shape);
+ for (int i=compoundShape->getNumChildShapes()-1;i>=0;i--)
+ {
+ btTransform childTrans = compoundShape->getChildTransform(i);
+ const btCollisionShape* colShape = compoundShape->getChildShape(i);
+ debugDrawObject(worldTransform*childTrans,colShape,color);
+ }
+
+ } else
+ {
+
+ switch (shape->getShapeType())
+ {
+
+ case BOX_SHAPE_PROXYTYPE:
+ {
+ const btBoxShape* boxShape = static_cast<const btBoxShape*>(shape);
+ btVector3 halfExtents = boxShape->getHalfExtentsWithMargin();
+ getDebugDrawer()->drawBox(-halfExtents,halfExtents,worldTransform,color);
+ break;
+ }
+
+ case SPHERE_SHAPE_PROXYTYPE:
+ {
+ const btSphereShape* sphereShape = static_cast<const btSphereShape*>(shape);
+ btScalar radius = sphereShape->getMargin();//radius doesn't include the margin, so draw with margin
+
+ getDebugDrawer()->drawSphere(radius, worldTransform, color);
+ break;
+ }
+ case MULTI_SPHERE_SHAPE_PROXYTYPE:
+ {
+ const btMultiSphereShape* multiSphereShape = static_cast<const btMultiSphereShape*>(shape);
+
+ btTransform childTransform;
+ childTransform.setIdentity();
+
+ for (int i = multiSphereShape->getSphereCount()-1; i>=0;i--)
+ {
+ childTransform.setOrigin(multiSphereShape->getSpherePosition(i));
+ getDebugDrawer()->drawSphere(multiSphereShape->getSphereRadius(i), worldTransform*childTransform, color);
+ }
+
+ break;
+ }
+ case CAPSULE_SHAPE_PROXYTYPE:
+ {
+ const btCapsuleShape* capsuleShape = static_cast<const btCapsuleShape*>(shape);
+
+ btScalar radius = capsuleShape->getRadius();
+ btScalar halfHeight = capsuleShape->getHalfHeight();
+
+ int upAxis = capsuleShape->getUpAxis();
+ getDebugDrawer()->drawCapsule(radius, halfHeight, upAxis, worldTransform, color);
+ break;
+ }
+ case CONE_SHAPE_PROXYTYPE:
+ {
+ const btConeShape* coneShape = static_cast<const btConeShape*>(shape);
+ btScalar radius = coneShape->getRadius();//+coneShape->getMargin();
+ btScalar height = coneShape->getHeight();//+coneShape->getMargin();
+
+ int upAxis= coneShape->getConeUpIndex();
+ getDebugDrawer()->drawCone(radius, height, upAxis, worldTransform, color);
+ break;
+
+ }
+ case CYLINDER_SHAPE_PROXYTYPE:
+ {
+ const btCylinderShape* cylinder = static_cast<const btCylinderShape*>(shape);
+ int upAxis = cylinder->getUpAxis();
+ btScalar radius = cylinder->getRadius();
+ btScalar halfHeight = cylinder->getHalfExtentsWithMargin()[upAxis];
+ getDebugDrawer()->drawCylinder(radius, halfHeight, upAxis, worldTransform, color);
+ break;
+ }
+
+ case STATIC_PLANE_PROXYTYPE:
+ {
+ const btStaticPlaneShape* staticPlaneShape = static_cast<const btStaticPlaneShape*>(shape);
+ btScalar planeConst = staticPlaneShape->getPlaneConstant();
+ const btVector3& planeNormal = staticPlaneShape->getPlaneNormal();
+ getDebugDrawer()->drawPlane(planeNormal, planeConst,worldTransform, color);
+ break;
+
+ }
+ default:
+ {
+
+ /// for polyhedral shapes
+ if (shape->isPolyhedral())
+ {
+ btPolyhedralConvexShape* polyshape = (btPolyhedralConvexShape*) shape;
+
+ int i;
+ if (polyshape->getConvexPolyhedron())
+ {
+ const btConvexPolyhedron* poly = polyshape->getConvexPolyhedron();
+ for (i=0;i<poly->m_faces.size();i++)
+ {
+ btVector3 centroid(0,0,0);
+ int numVerts = poly->m_faces[i].m_indices.size();
+ if (numVerts)
+ {
+ int lastV = poly->m_faces[i].m_indices[numVerts-1];
+ for (int v=0;v<poly->m_faces[i].m_indices.size();v++)
+ {
+ int curVert = poly->m_faces[i].m_indices[v];
+ centroid+=poly->m_vertices[curVert];
+ getDebugDrawer()->drawLine(worldTransform*poly->m_vertices[lastV],worldTransform*poly->m_vertices[curVert],color);
+ lastV = curVert;
+ }
+ }
+ centroid*= btScalar(1.f)/btScalar(numVerts);
+ if (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawNormals)
+ {
+ btVector3 normalColor(1,1,0);
+ btVector3 faceNormal(poly->m_faces[i].m_plane[0],poly->m_faces[i].m_plane[1],poly->m_faces[i].m_plane[2]);
+ getDebugDrawer()->drawLine(worldTransform*centroid,worldTransform*(centroid+faceNormal),normalColor);
+ }
+
+ }
+
+
+ } else
+ {
+ for (i=0;i<polyshape->getNumEdges();i++)
+ {
+ btVector3 a,b;
+ polyshape->getEdge(i,a,b);
+ btVector3 wa = worldTransform * a;
+ btVector3 wb = worldTransform * b;
+ getDebugDrawer()->drawLine(wa,wb,color);
+ }
+ }
+
+
+ }
+
+ if (shape->isConcave())
+ {
+ btConcaveShape* concaveMesh = (btConcaveShape*) shape;
+
+ ///@todo pass camera, for some culling? no -> we are not a graphics lib
+ btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
+ btVector3 aabbMin(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT));
+
+ DebugDrawcallback drawCallback(getDebugDrawer(),worldTransform,color);
+ concaveMesh->processAllTriangles(&drawCallback,aabbMin,aabbMax);
+
+ }
+
+ if (shape->getShapeType() == CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE)
+ {
+ btConvexTriangleMeshShape* convexMesh = (btConvexTriangleMeshShape*) shape;
+ //todo: pass camera for some culling
+ btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
+ btVector3 aabbMin(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT));
+ //DebugDrawcallback drawCallback;
+ DebugDrawcallback drawCallback(getDebugDrawer(),worldTransform,color);
+ convexMesh->getMeshInterface()->InternalProcessAllTriangles(&drawCallback,aabbMin,aabbMax);
+ }
+
+
+
+ }
+
+ }
+ }
+}
+
+
+void btCollisionWorld::debugDrawWorld()
+{
+ if (getDebugDrawer())
+ {
+ getDebugDrawer()->clearLines();
+
+ btIDebugDraw::DefaultColors defaultColors = getDebugDrawer()->getDefaultColors();
+
+ if ( getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawContactPoints)
+ {
+
+
+ if (getDispatcher())
+ {
+ int numManifolds = getDispatcher()->getNumManifolds();
+
+ for (int i=0;i<numManifolds;i++)
+ {
+ btPersistentManifold* contactManifold = getDispatcher()->getManifoldByIndexInternal(i);
+ //btCollisionObject* obA = static_cast<btCollisionObject*>(contactManifold->getBody0());
+ //btCollisionObject* obB = static_cast<btCollisionObject*>(contactManifold->getBody1());
+
+ int numContacts = contactManifold->getNumContacts();
+ for (int j=0;j<numContacts;j++)
+ {
+ btManifoldPoint& cp = contactManifold->getContactPoint(j);
+ getDebugDrawer()->drawContactPoint(cp.m_positionWorldOnB,cp.m_normalWorldOnB,cp.getDistance(),cp.getLifeTime(),defaultColors.m_contactPoint);
+ }
+ }
+ }
+ }
+
+ if ((getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe | btIDebugDraw::DBG_DrawAabb)))
+ {
+ int i;
+
+ for ( i=0;i<m_collisionObjects.size();i++)
+ {
+ btCollisionObject* colObj = m_collisionObjects[i];
+ if ((colObj->getCollisionFlags() & btCollisionObject::CF_DISABLE_VISUALIZE_OBJECT)==0)
+ {
+ if (getDebugDrawer() && (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawWireframe))
+ {
+ btVector3 color(btScalar(0.4),btScalar(0.4),btScalar(0.4));
+
+ switch(colObj->getActivationState())
+ {
+ case ACTIVE_TAG:
+ color = defaultColors.m_activeObject; break;
+ case ISLAND_SLEEPING:
+ color = defaultColors.m_deactivatedObject;break;
+ case WANTS_DEACTIVATION:
+ color = defaultColors.m_wantsDeactivationObject;break;
+ case DISABLE_DEACTIVATION:
+ color = defaultColors.m_disabledDeactivationObject;break;
+ case DISABLE_SIMULATION:
+ color = defaultColors.m_disabledSimulationObject;break;
+ default:
+ {
+ color = btVector3(btScalar(.3),btScalar(0.3),btScalar(0.3));
+ }
+ };
+
+ colObj->getCustomDebugColor(color);
+
+ debugDrawObject(colObj->getWorldTransform(),colObj->getCollisionShape(),color);
+ }
+ if (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawAabb))
+ {
+ btVector3 minAabb,maxAabb;
+ btVector3 colorvec = defaultColors.m_aabb;
+ colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb,maxAabb);
+ btVector3 contactThreshold(gContactBreakingThreshold,gContactBreakingThreshold,gContactBreakingThreshold);
+ minAabb -= contactThreshold;
+ maxAabb += contactThreshold;
+
+ btVector3 minAabb2,maxAabb2;
+
+ if(getDispatchInfo().m_useContinuous && colObj->getInternalType()==btCollisionObject::CO_RIGID_BODY && !colObj->isStaticOrKinematicObject())
+ {
+ colObj->getCollisionShape()->getAabb(colObj->getInterpolationWorldTransform(),minAabb2,maxAabb2);
+ minAabb2 -= contactThreshold;
+ maxAabb2 += contactThreshold;
+ minAabb.setMin(minAabb2);
+ maxAabb.setMax(maxAabb2);
+ }
+
+ m_debugDrawer->drawAabb(minAabb,maxAabb,colorvec);
+ }
+ }
+ }
+ }
+ }
+}
+
+
+void btCollisionWorld::serializeCollisionObjects(btSerializer* serializer)
+{
+ int i;
+
+ ///keep track of shapes already serialized
+ btHashMap<btHashPtr,btCollisionShape*> serializedShapes;
+
+ for (i=0;i<m_collisionObjects.size();i++)
+ {
+ btCollisionObject* colObj = m_collisionObjects[i];
+ btCollisionShape* shape = colObj->getCollisionShape();
+
+ if (!serializedShapes.find(shape))
+ {
+ serializedShapes.insert(shape,shape);
+ shape->serializeSingleShape(serializer);
+ }
+ }
+
+ //serialize all collision objects
+ for (i=0;i<m_collisionObjects.size();i++)
+ {
+ btCollisionObject* colObj = m_collisionObjects[i];
+ if ((colObj->getInternalType() == btCollisionObject::CO_COLLISION_OBJECT) || (colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK))
+ {
+ colObj->serializeSingleObject(serializer);
+ }
+ }
+}
+
+
+void btCollisionWorld::serialize(btSerializer* serializer)
+{
+
+ serializer->startSerialization();
+
+ serializeCollisionObjects(serializer);
+
+ serializer->finishSerialization();
+}
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCollisionWorld.h b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCollisionWorld.h
new file mode 100644
index 0000000000..eede2b28ca
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCollisionWorld.h
@@ -0,0 +1,528 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2013 Erwin Coumans 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.
+*/
+
+
+/**
+ * @mainpage Bullet Documentation
+ *
+ * @section intro_sec Introduction
+ * Bullet is a Collision Detection and Rigid Body Dynamics Library. The Library is Open Source and free for commercial use, under the ZLib license ( http://opensource.org/licenses/zlib-license.php ).
+ *
+ * The main documentation is Bullet_User_Manual.pdf, included in the source code distribution.
+ * There is the Physics Forum for feedback and general Collision Detection and Physics discussions.
+ * Please visit http://www.bulletphysics.org
+ *
+ * @section install_sec Installation
+ *
+ * @subsection step1 Step 1: Download
+ * You can download the Bullet Physics Library from the github repository: https://github.com/bulletphysics/bullet3/releases
+ *
+ * @subsection step2 Step 2: Building
+ * Bullet has multiple build systems, including premake, cmake and autotools. Premake and cmake support all platforms.
+ * Premake is included in the Bullet/build folder for Windows, Mac OSX and Linux.
+ * Under Windows you can click on Bullet/build/vs2010.bat to create Microsoft Visual Studio projects.
+ * On Mac OSX and Linux you can open a terminal and generate Makefile, codeblocks or Xcode4 projects:
+ * cd Bullet/build
+ * ./premake4_osx gmake or ./premake4_linux gmake or ./premake4_linux64 gmake or (for Mac) ./premake4_osx xcode4
+ * cd Bullet/build/gmake
+ * make
+ *
+ * An alternative to premake is cmake. You can download cmake from http://www.cmake.org
+ * cmake can autogenerate projectfiles for Microsoft Visual Studio, Apple Xcode, KDevelop and Unix Makefiles.
+ * The easiest is to run the CMake cmake-gui graphical user interface and choose the options and generate projectfiles.
+ * You can also use cmake in the command-line. Here are some examples for various platforms:
+ * cmake . -G "Visual Studio 9 2008"
+ * cmake . -G Xcode
+ * cmake . -G "Unix Makefiles"
+ * Although cmake is recommended, you can also use autotools for UNIX: ./autogen.sh ./configure to create a Makefile and then run make.
+ *
+ * @subsection step3 Step 3: Testing demos
+ * Try to run and experiment with BasicDemo executable as a starting point.
+ * Bullet can be used in several ways, as Full Rigid Body simulation, as Collision Detector Library or Low Level / Snippets like the GJK Closest Point calculation.
+ * The Dependencies can be seen in this documentation under Directories
+ *
+ * @subsection step4 Step 4: Integrating in your application, full Rigid Body and Soft Body simulation
+ * Check out BasicDemo how to create a btDynamicsWorld, btRigidBody and btCollisionShape, Stepping the simulation and synchronizing your graphics object transform.
+ * Check out SoftDemo how to use soft body dynamics, using btSoftRigidDynamicsWorld.
+ * @subsection step5 Step 5 : Integrate the Collision Detection Library (without Dynamics and other Extras)
+ * Bullet Collision Detection can also be used without the Dynamics/Extras.
+ * Check out btCollisionWorld and btCollisionObject, and the CollisionInterfaceDemo.
+ * @subsection step6 Step 6 : Use Snippets like the GJK Closest Point calculation.
+ * Bullet has been designed in a modular way keeping dependencies to a minimum. The ConvexHullDistance demo demonstrates direct use of btGjkPairDetector.
+ *
+ * @section copyright Copyright
+ * For up-to-data information and copyright and contributors list check out the Bullet_User_Manual.pdf
+ *
+ */
+
+
+
+#ifndef BT_COLLISION_WORLD_H
+#define BT_COLLISION_WORLD_H
+
+class btCollisionShape;
+class btConvexShape;
+class btBroadphaseInterface;
+class btSerializer;
+
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btTransform.h"
+#include "btCollisionObject.h"
+#include "btCollisionDispatcher.h"
+#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
+#include "LinearMath/btAlignedObjectArray.h"
+
+///CollisionWorld is interface and container for the collision detection
+class btCollisionWorld
+{
+
+
+protected:
+
+ btAlignedObjectArray<btCollisionObject*> m_collisionObjects;
+
+ btDispatcher* m_dispatcher1;
+
+ btDispatcherInfo m_dispatchInfo;
+
+ btBroadphaseInterface* m_broadphasePairCache;
+
+ btIDebugDraw* m_debugDrawer;
+
+ ///m_forceUpdateAllAabbs can be set to false as an optimization to only update active object AABBs
+ ///it is true by default, because it is error-prone (setting the position of static objects wouldn't update their AABB)
+ bool m_forceUpdateAllAabbs;
+
+ void serializeCollisionObjects(btSerializer* serializer);
+
+public:
+
+ //this constructor doesn't own the dispatcher and paircache/broadphase
+ btCollisionWorld(btDispatcher* dispatcher,btBroadphaseInterface* broadphasePairCache, btCollisionConfiguration* collisionConfiguration);
+
+ virtual ~btCollisionWorld();
+
+ void setBroadphase(btBroadphaseInterface* pairCache)
+ {
+ m_broadphasePairCache = pairCache;
+ }
+
+ const btBroadphaseInterface* getBroadphase() const
+ {
+ return m_broadphasePairCache;
+ }
+
+ btBroadphaseInterface* getBroadphase()
+ {
+ return m_broadphasePairCache;
+ }
+
+ btOverlappingPairCache* getPairCache()
+ {
+ return m_broadphasePairCache->getOverlappingPairCache();
+ }
+
+
+ btDispatcher* getDispatcher()
+ {
+ return m_dispatcher1;
+ }
+
+ const btDispatcher* getDispatcher() const
+ {
+ return m_dispatcher1;
+ }
+
+ void updateSingleAabb(btCollisionObject* colObj);
+
+ virtual void updateAabbs();
+
+ ///the computeOverlappingPairs is usually already called by performDiscreteCollisionDetection (or stepSimulation)
+ ///it can be useful to use if you perform ray tests without collision detection/simulation
+ virtual void computeOverlappingPairs();
+
+
+ virtual void setDebugDrawer(btIDebugDraw* debugDrawer)
+ {
+ m_debugDrawer = debugDrawer;
+ }
+
+ virtual btIDebugDraw* getDebugDrawer()
+ {
+ return m_debugDrawer;
+ }
+
+ virtual void debugDrawWorld();
+
+ virtual void debugDrawObject(const btTransform& worldTransform, const btCollisionShape* shape, const btVector3& color);
+
+
+ ///LocalShapeInfo gives extra information for complex shapes
+ ///Currently, only btTriangleMeshShape is available, so it just contains triangleIndex and subpart
+ struct LocalShapeInfo
+ {
+ int m_shapePart;
+ int m_triangleIndex;
+
+ //const btCollisionShape* m_shapeTemp;
+ //const btTransform* m_shapeLocalTransform;
+ };
+
+ struct LocalRayResult
+ {
+ LocalRayResult(const btCollisionObject* collisionObject,
+ LocalShapeInfo* localShapeInfo,
+ const btVector3& hitNormalLocal,
+ btScalar hitFraction)
+ :m_collisionObject(collisionObject),
+ m_localShapeInfo(localShapeInfo),
+ m_hitNormalLocal(hitNormalLocal),
+ m_hitFraction(hitFraction)
+ {
+ }
+
+ const btCollisionObject* m_collisionObject;
+ LocalShapeInfo* m_localShapeInfo;
+ btVector3 m_hitNormalLocal;
+ btScalar m_hitFraction;
+
+ };
+
+ ///RayResultCallback is used to report new raycast results
+ struct RayResultCallback
+ {
+ btScalar m_closestHitFraction;
+ const btCollisionObject* m_collisionObject;
+ int m_collisionFilterGroup;
+ int m_collisionFilterMask;
+ //@BP Mod - Custom flags, currently used to enable backface culling on tri-meshes, see btRaycastCallback.h. Apply any of the EFlags defined there on m_flags here to invoke.
+ unsigned int m_flags;
+
+ virtual ~RayResultCallback()
+ {
+ }
+ bool hasHit() const
+ {
+ return (m_collisionObject != 0);
+ }
+
+ RayResultCallback()
+ :m_closestHitFraction(btScalar(1.)),
+ m_collisionObject(0),
+ m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter),
+ m_collisionFilterMask(btBroadphaseProxy::AllFilter),
+ //@BP Mod
+ m_flags(0)
+ {
+ }
+
+ virtual bool needsCollision(btBroadphaseProxy* proxy0) const
+ {
+ bool collides = (proxy0->m_collisionFilterGroup & m_collisionFilterMask) != 0;
+ collides = collides && (m_collisionFilterGroup & proxy0->m_collisionFilterMask);
+ return collides;
+ }
+
+
+ virtual btScalar addSingleResult(LocalRayResult& rayResult,bool normalInWorldSpace) = 0;
+ };
+
+ struct ClosestRayResultCallback : public RayResultCallback
+ {
+ ClosestRayResultCallback(const btVector3& rayFromWorld,const btVector3& rayToWorld)
+ :m_rayFromWorld(rayFromWorld),
+ m_rayToWorld(rayToWorld)
+ {
+ }
+
+ btVector3 m_rayFromWorld;//used to calculate hitPointWorld from hitFraction
+ btVector3 m_rayToWorld;
+
+ btVector3 m_hitNormalWorld;
+ btVector3 m_hitPointWorld;
+
+ virtual btScalar addSingleResult(LocalRayResult& rayResult,bool normalInWorldSpace)
+ {
+ //caller already does the filter on the m_closestHitFraction
+ btAssert(rayResult.m_hitFraction <= m_closestHitFraction);
+
+ m_closestHitFraction = rayResult.m_hitFraction;
+ m_collisionObject = rayResult.m_collisionObject;
+ if (normalInWorldSpace)
+ {
+ m_hitNormalWorld = rayResult.m_hitNormalLocal;
+ } else
+ {
+ ///need to transform normal into worldspace
+ m_hitNormalWorld = m_collisionObject->getWorldTransform().getBasis()*rayResult.m_hitNormalLocal;
+ }
+ m_hitPointWorld.setInterpolate3(m_rayFromWorld,m_rayToWorld,rayResult.m_hitFraction);
+ return rayResult.m_hitFraction;
+ }
+ };
+
+ struct AllHitsRayResultCallback : public RayResultCallback
+ {
+ AllHitsRayResultCallback(const btVector3& rayFromWorld,const btVector3& rayToWorld)
+ :m_rayFromWorld(rayFromWorld),
+ m_rayToWorld(rayToWorld)
+ {
+ }
+
+ btAlignedObjectArray<const btCollisionObject*> m_collisionObjects;
+
+ btVector3 m_rayFromWorld;//used to calculate hitPointWorld from hitFraction
+ btVector3 m_rayToWorld;
+
+ btAlignedObjectArray<btVector3> m_hitNormalWorld;
+ btAlignedObjectArray<btVector3> m_hitPointWorld;
+ btAlignedObjectArray<btScalar> m_hitFractions;
+
+ virtual btScalar addSingleResult(LocalRayResult& rayResult,bool normalInWorldSpace)
+ {
+ m_collisionObject = rayResult.m_collisionObject;
+ m_collisionObjects.push_back(rayResult.m_collisionObject);
+ btVector3 hitNormalWorld;
+ if (normalInWorldSpace)
+ {
+ hitNormalWorld = rayResult.m_hitNormalLocal;
+ } else
+ {
+ ///need to transform normal into worldspace
+ hitNormalWorld = m_collisionObject->getWorldTransform().getBasis()*rayResult.m_hitNormalLocal;
+ }
+ m_hitNormalWorld.push_back(hitNormalWorld);
+ btVector3 hitPointWorld;
+ hitPointWorld.setInterpolate3(m_rayFromWorld,m_rayToWorld,rayResult.m_hitFraction);
+ m_hitPointWorld.push_back(hitPointWorld);
+ m_hitFractions.push_back(rayResult.m_hitFraction);
+ return m_closestHitFraction;
+ }
+ };
+
+
+ struct LocalConvexResult
+ {
+ LocalConvexResult(const btCollisionObject* hitCollisionObject,
+ LocalShapeInfo* localShapeInfo,
+ const btVector3& hitNormalLocal,
+ const btVector3& hitPointLocal,
+ btScalar hitFraction
+ )
+ :m_hitCollisionObject(hitCollisionObject),
+ m_localShapeInfo(localShapeInfo),
+ m_hitNormalLocal(hitNormalLocal),
+ m_hitPointLocal(hitPointLocal),
+ m_hitFraction(hitFraction)
+ {
+ }
+
+ const btCollisionObject* m_hitCollisionObject;
+ LocalShapeInfo* m_localShapeInfo;
+ btVector3 m_hitNormalLocal;
+ btVector3 m_hitPointLocal;
+ btScalar m_hitFraction;
+ };
+
+ ///RayResultCallback is used to report new raycast results
+ struct ConvexResultCallback
+ {
+ btScalar m_closestHitFraction;
+ int m_collisionFilterGroup;
+ int m_collisionFilterMask;
+
+ ConvexResultCallback()
+ :m_closestHitFraction(btScalar(1.)),
+ m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter),
+ m_collisionFilterMask(btBroadphaseProxy::AllFilter)
+ {
+ }
+
+ virtual ~ConvexResultCallback()
+ {
+ }
+
+ bool hasHit() const
+ {
+ return (m_closestHitFraction < btScalar(1.));
+ }
+
+
+
+ virtual bool needsCollision(btBroadphaseProxy* proxy0) const
+ {
+ bool collides = (proxy0->m_collisionFilterGroup & m_collisionFilterMask) != 0;
+ collides = collides && (m_collisionFilterGroup & proxy0->m_collisionFilterMask);
+ return collides;
+ }
+
+ virtual btScalar addSingleResult(LocalConvexResult& convexResult,bool normalInWorldSpace) = 0;
+ };
+
+ struct ClosestConvexResultCallback : public ConvexResultCallback
+ {
+ ClosestConvexResultCallback(const btVector3& convexFromWorld,const btVector3& convexToWorld)
+ :m_convexFromWorld(convexFromWorld),
+ m_convexToWorld(convexToWorld),
+ m_hitCollisionObject(0)
+ {
+ }
+
+ btVector3 m_convexFromWorld;//used to calculate hitPointWorld from hitFraction
+ btVector3 m_convexToWorld;
+
+ btVector3 m_hitNormalWorld;
+ btVector3 m_hitPointWorld;
+ const btCollisionObject* m_hitCollisionObject;
+
+ virtual btScalar addSingleResult(LocalConvexResult& convexResult,bool normalInWorldSpace)
+ {
+//caller already does the filter on the m_closestHitFraction
+ btAssert(convexResult.m_hitFraction <= m_closestHitFraction);
+
+ m_closestHitFraction = convexResult.m_hitFraction;
+ m_hitCollisionObject = convexResult.m_hitCollisionObject;
+ if (normalInWorldSpace)
+ {
+ m_hitNormalWorld = convexResult.m_hitNormalLocal;
+ } else
+ {
+ ///need to transform normal into worldspace
+ m_hitNormalWorld = m_hitCollisionObject->getWorldTransform().getBasis()*convexResult.m_hitNormalLocal;
+ }
+ m_hitPointWorld = convexResult.m_hitPointLocal;
+ return convexResult.m_hitFraction;
+ }
+ };
+
+ ///ContactResultCallback is used to report contact points
+ struct ContactResultCallback
+ {
+ int m_collisionFilterGroup;
+ int m_collisionFilterMask;
+ btScalar m_closestDistanceThreshold;
+
+ ContactResultCallback()
+ :m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter),
+ m_collisionFilterMask(btBroadphaseProxy::AllFilter),
+ m_closestDistanceThreshold(0)
+ {
+ }
+
+ virtual ~ContactResultCallback()
+ {
+ }
+
+ virtual bool needsCollision(btBroadphaseProxy* proxy0) const
+ {
+ bool collides = (proxy0->m_collisionFilterGroup & m_collisionFilterMask) != 0;
+ collides = collides && (m_collisionFilterGroup & proxy0->m_collisionFilterMask);
+ return collides;
+ }
+
+ virtual btScalar addSingleResult(btManifoldPoint& cp, const btCollisionObjectWrapper* colObj0Wrap,int partId0,int index0,const btCollisionObjectWrapper* colObj1Wrap,int partId1,int index1) = 0;
+ };
+
+
+
+ int getNumCollisionObjects() const
+ {
+ return int(m_collisionObjects.size());
+ }
+
+ /// rayTest performs a raycast on all objects in the btCollisionWorld, and calls the resultCallback
+ /// This allows for several queries: first hit, all hits, any hit, dependent on the value returned by the callback.
+ virtual void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const;
+
+ /// convexTest performs a swept convex cast on all objects in the btCollisionWorld, and calls the resultCallback
+ /// This allows for several queries: first hit, all hits, any hit, dependent on the value return by the callback.
+ void convexSweepTest (const btConvexShape* castShape, const btTransform& from, const btTransform& to, ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration = btScalar(0.)) const;
+
+ ///contactTest performs a discrete collision test between colObj against all objects in the btCollisionWorld, and calls the resultCallback.
+ ///it reports one or more contact points for every overlapping object (including the one with deepest penetration)
+ void contactTest(btCollisionObject* colObj, ContactResultCallback& resultCallback);
+
+ ///contactTest performs a discrete collision test between two collision objects and calls the resultCallback if overlap if detected.
+ ///it reports one or more contact points (including the one with deepest penetration)
+ void contactPairTest(btCollisionObject* colObjA, btCollisionObject* colObjB, ContactResultCallback& resultCallback);
+
+
+ /// rayTestSingle performs a raycast call and calls the resultCallback. It is used internally by rayTest.
+ /// In a future implementation, we consider moving the ray test as a virtual method in btCollisionShape.
+ /// This allows more customization.
+ static void rayTestSingle(const btTransform& rayFromTrans,const btTransform& rayToTrans,
+ btCollisionObject* collisionObject,
+ const btCollisionShape* collisionShape,
+ const btTransform& colObjWorldTransform,
+ RayResultCallback& resultCallback);
+
+ static void rayTestSingleInternal(const btTransform& rayFromTrans,const btTransform& rayToTrans,
+ const btCollisionObjectWrapper* collisionObjectWrap,
+ RayResultCallback& resultCallback);
+
+ /// objectQuerySingle performs a collision detection query and calls the resultCallback. It is used internally by rayTest.
+ static void objectQuerySingle(const btConvexShape* castShape, const btTransform& rayFromTrans,const btTransform& rayToTrans,
+ btCollisionObject* collisionObject,
+ const btCollisionShape* collisionShape,
+ const btTransform& colObjWorldTransform,
+ ConvexResultCallback& resultCallback, btScalar allowedPenetration);
+
+ static void objectQuerySingleInternal(const btConvexShape* castShape,const btTransform& convexFromTrans,const btTransform& convexToTrans,
+ const btCollisionObjectWrapper* colObjWrap,
+ ConvexResultCallback& resultCallback, btScalar allowedPenetration);
+
+ virtual void addCollisionObject(btCollisionObject* collisionObject, int collisionFilterGroup=btBroadphaseProxy::DefaultFilter, int collisionFilterMask=btBroadphaseProxy::AllFilter);
+
+ btCollisionObjectArray& getCollisionObjectArray()
+ {
+ return m_collisionObjects;
+ }
+
+ const btCollisionObjectArray& getCollisionObjectArray() const
+ {
+ return m_collisionObjects;
+ }
+
+
+ virtual void removeCollisionObject(btCollisionObject* collisionObject);
+
+ virtual void performDiscreteCollisionDetection();
+
+ btDispatcherInfo& getDispatchInfo()
+ {
+ return m_dispatchInfo;
+ }
+
+ const btDispatcherInfo& getDispatchInfo() const
+ {
+ return m_dispatchInfo;
+ }
+
+ bool getForceUpdateAllAabbs() const
+ {
+ return m_forceUpdateAllAabbs;
+ }
+ void setForceUpdateAllAabbs( bool forceUpdateAllAabbs)
+ {
+ m_forceUpdateAllAabbs = forceUpdateAllAabbs;
+ }
+
+ ///Preliminary serialization test for Bullet 2.76. Loading those files requires a separate parser (Bullet/Demos/SerializeDemo)
+ virtual void serialize(btSerializer* serializer);
+
+};
+
+
+#endif //BT_COLLISION_WORLD_H
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCollisionWorldImporter.cpp b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCollisionWorldImporter.cpp
new file mode 100644
index 0000000000..f2b0837808
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCollisionWorldImporter.cpp
@@ -0,0 +1,1147 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2014 Erwin Coumans 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 "btCollisionWorldImporter.h"
+#include "btBulletCollisionCommon.h"
+#include "LinearMath/btSerializer.h" //for btBulletSerializedArrays definition
+
+#ifdef SUPPORT_GIMPACT_SHAPE_IMPORT
+#include "BulletCollision/Gimpact/btGImpactShape.h"
+#endif //SUPPORT_GIMPACT_SHAPE_IMPORT
+
+btCollisionWorldImporter::btCollisionWorldImporter(btCollisionWorld* world)
+:m_collisionWorld(world),
+m_verboseMode(0)
+{
+
+}
+
+btCollisionWorldImporter::~btCollisionWorldImporter()
+{
+}
+
+
+
+
+
+bool btCollisionWorldImporter::convertAllObjects( btBulletSerializedArrays* arrays)
+{
+
+ m_shapeMap.clear();
+ m_bodyMap.clear();
+
+ int i;
+
+ for (i=0;i<arrays->m_bvhsDouble.size();i++)
+ {
+ btOptimizedBvh* bvh = createOptimizedBvh();
+ btQuantizedBvhDoubleData* bvhData = arrays->m_bvhsDouble[i];
+ bvh->deSerializeDouble(*bvhData);
+ m_bvhMap.insert(arrays->m_bvhsDouble[i],bvh);
+ }
+ for (i=0;i<arrays->m_bvhsFloat.size();i++)
+ {
+ btOptimizedBvh* bvh = createOptimizedBvh();
+ btQuantizedBvhFloatData* bvhData = arrays->m_bvhsFloat[i];
+ bvh->deSerializeFloat(*bvhData);
+ m_bvhMap.insert(arrays->m_bvhsFloat[i],bvh);
+ }
+
+
+
+
+
+ for (i=0;i<arrays->m_colShapeData.size();i++)
+ {
+ btCollisionShapeData* shapeData = arrays->m_colShapeData[i];
+ btCollisionShape* shape = convertCollisionShape(shapeData);
+ if (shape)
+ {
+ // printf("shapeMap.insert(%x,%x)\n",shapeData,shape);
+ m_shapeMap.insert(shapeData,shape);
+ }
+
+ if (shape&& shapeData->m_name)
+ {
+ char* newname = duplicateName(shapeData->m_name);
+ m_objectNameMap.insert(shape,newname);
+ m_nameShapeMap.insert(newname,shape);
+ }
+ }
+
+
+ for (i=0;i<arrays->m_collisionObjectDataDouble.size();i++)
+ {
+ btCollisionObjectDoubleData* colObjData = arrays->m_collisionObjectDataDouble[i];
+ btCollisionShape** shapePtr = m_shapeMap.find(colObjData->m_collisionShape);
+ if (shapePtr && *shapePtr)
+ {
+ btTransform startTransform;
+ colObjData->m_worldTransform.m_origin.m_floats[3] = 0.f;
+ startTransform.deSerializeDouble(colObjData->m_worldTransform);
+
+ btCollisionShape* shape = (btCollisionShape*)*shapePtr;
+ btCollisionObject* body = createCollisionObject(startTransform,shape,colObjData->m_name);
+ body->setFriction(btScalar(colObjData->m_friction));
+ body->setRestitution(btScalar(colObjData->m_restitution));
+
+#ifdef USE_INTERNAL_EDGE_UTILITY
+ if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE)
+ {
+ btBvhTriangleMeshShape* trimesh = (btBvhTriangleMeshShape*)shape;
+ if (trimesh->getTriangleInfoMap())
+ {
+ body->setCollisionFlags(body->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK);
+ }
+ }
+#endif //USE_INTERNAL_EDGE_UTILITY
+ m_bodyMap.insert(colObjData,body);
+ } else
+ {
+ printf("error: no shape found\n");
+ }
+ }
+ for (i=0;i<arrays->m_collisionObjectDataFloat.size();i++)
+ {
+ btCollisionObjectFloatData* colObjData = arrays->m_collisionObjectDataFloat[i];
+ btCollisionShape** shapePtr = m_shapeMap.find(colObjData->m_collisionShape);
+ if (shapePtr && *shapePtr)
+ {
+ btTransform startTransform;
+ colObjData->m_worldTransform.m_origin.m_floats[3] = 0.f;
+ startTransform.deSerializeFloat(colObjData->m_worldTransform);
+
+ btCollisionShape* shape = (btCollisionShape*)*shapePtr;
+ btCollisionObject* body = createCollisionObject(startTransform,shape,colObjData->m_name);
+
+#ifdef USE_INTERNAL_EDGE_UTILITY
+ if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE)
+ {
+ btBvhTriangleMeshShape* trimesh = (btBvhTriangleMeshShape*)shape;
+ if (trimesh->getTriangleInfoMap())
+ {
+ body->setCollisionFlags(body->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK);
+ }
+ }
+#endif //USE_INTERNAL_EDGE_UTILITY
+ m_bodyMap.insert(colObjData,body);
+ } else
+ {
+ printf("error: no shape found\n");
+ }
+ }
+
+ return true;
+}
+
+
+
+void btCollisionWorldImporter::deleteAllData()
+{
+ int i;
+
+ for (i=0;i<m_allocatedCollisionObjects.size();i++)
+ {
+ if(m_collisionWorld)
+ m_collisionWorld->removeCollisionObject(m_allocatedCollisionObjects[i]);
+ delete m_allocatedCollisionObjects[i];
+ }
+
+ m_allocatedCollisionObjects.clear();
+
+
+ for (i=0;i<m_allocatedCollisionShapes.size();i++)
+ {
+ delete m_allocatedCollisionShapes[i];
+ }
+ m_allocatedCollisionShapes.clear();
+
+
+ for (i=0;i<m_allocatedBvhs.size();i++)
+ {
+ delete m_allocatedBvhs[i];
+ }
+ m_allocatedBvhs.clear();
+
+ for (i=0;i<m_allocatedTriangleInfoMaps.size();i++)
+ {
+ delete m_allocatedTriangleInfoMaps[i];
+ }
+ m_allocatedTriangleInfoMaps.clear();
+ for (i=0;i<m_allocatedTriangleIndexArrays.size();i++)
+ {
+ delete m_allocatedTriangleIndexArrays[i];
+ }
+ m_allocatedTriangleIndexArrays.clear();
+ for (i=0;i<m_allocatedNames.size();i++)
+ {
+ delete[] m_allocatedNames[i];
+ }
+ m_allocatedNames.clear();
+
+ for (i=0;i<m_allocatedbtStridingMeshInterfaceDatas.size();i++)
+ {
+ btStridingMeshInterfaceData* curData = m_allocatedbtStridingMeshInterfaceDatas[i];
+
+ for(int a = 0;a < curData->m_numMeshParts;a++)
+ {
+ btMeshPartData* curPart = &curData->m_meshPartsPtr[a];
+ if(curPart->m_vertices3f)
+ delete [] curPart->m_vertices3f;
+
+ if(curPart->m_vertices3d)
+ delete [] curPart->m_vertices3d;
+
+ if(curPart->m_indices32)
+ delete [] curPart->m_indices32;
+
+ if(curPart->m_3indices16)
+ delete [] curPart->m_3indices16;
+
+ if(curPart->m_indices16)
+ delete [] curPart->m_indices16;
+
+ if (curPart->m_3indices8)
+ delete [] curPart->m_3indices8;
+
+ }
+ delete [] curData->m_meshPartsPtr;
+ delete curData;
+ }
+ m_allocatedbtStridingMeshInterfaceDatas.clear();
+
+ for (i=0;i<m_indexArrays.size();i++)
+ {
+ btAlignedFree(m_indexArrays[i]);
+ }
+ m_indexArrays.clear();
+
+ for (i=0;i<m_shortIndexArrays.size();i++)
+ {
+ btAlignedFree(m_shortIndexArrays[i]);
+ }
+ m_shortIndexArrays.clear();
+
+ for (i=0;i<m_charIndexArrays.size();i++)
+ {
+ btAlignedFree(m_charIndexArrays[i]);
+ }
+ m_charIndexArrays.clear();
+
+ for (i=0;i<m_floatVertexArrays.size();i++)
+ {
+ btAlignedFree(m_floatVertexArrays[i]);
+ }
+ m_floatVertexArrays.clear();
+
+ for (i=0;i<m_doubleVertexArrays.size();i++)
+ {
+ btAlignedFree(m_doubleVertexArrays[i]);
+ }
+ m_doubleVertexArrays.clear();
+
+
+}
+
+
+
+btCollisionShape* btCollisionWorldImporter::convertCollisionShape( btCollisionShapeData* shapeData )
+{
+ btCollisionShape* shape = 0;
+
+ switch (shapeData->m_shapeType)
+ {
+ case STATIC_PLANE_PROXYTYPE:
+ {
+ btStaticPlaneShapeData* planeData = (btStaticPlaneShapeData*)shapeData;
+ btVector3 planeNormal,localScaling;
+ planeNormal.deSerializeFloat(planeData->m_planeNormal);
+ localScaling.deSerializeFloat(planeData->m_localScaling);
+ shape = createPlaneShape(planeNormal,planeData->m_planeConstant);
+ shape->setLocalScaling(localScaling);
+
+ break;
+ }
+ case SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE:
+ {
+ btScaledTriangleMeshShapeData* scaledMesh = (btScaledTriangleMeshShapeData*) shapeData;
+ btCollisionShapeData* colShapeData = (btCollisionShapeData*) &scaledMesh->m_trimeshShapeData;
+ colShapeData->m_shapeType = TRIANGLE_MESH_SHAPE_PROXYTYPE;
+ btCollisionShape* childShape = convertCollisionShape(colShapeData);
+ btBvhTriangleMeshShape* meshShape = (btBvhTriangleMeshShape*)childShape;
+ btVector3 localScaling;
+ localScaling.deSerializeFloat(scaledMesh->m_localScaling);
+
+ shape = createScaledTrangleMeshShape(meshShape, localScaling);
+ break;
+ }
+#ifdef SUPPORT_GIMPACT_SHAPE_IMPORT
+ case GIMPACT_SHAPE_PROXYTYPE:
+ {
+ btGImpactMeshShapeData* gimpactData = (btGImpactMeshShapeData*) shapeData;
+ if (gimpactData->m_gimpactSubType == CONST_GIMPACT_TRIMESH_SHAPE)
+ {
+ btStridingMeshInterfaceData* interfaceData = createStridingMeshInterfaceData(&gimpactData->m_meshInterface);
+ btTriangleIndexVertexArray* meshInterface = createMeshInterface(*interfaceData);
+
+
+ btGImpactMeshShape* gimpactShape = createGimpactShape(meshInterface);
+ btVector3 localScaling;
+ localScaling.deSerializeFloat(gimpactData->m_localScaling);
+ gimpactShape->setLocalScaling(localScaling);
+ gimpactShape->setMargin(btScalar(gimpactData->m_collisionMargin));
+ gimpactShape->updateBound();
+ shape = gimpactShape;
+ } else
+ {
+ printf("unsupported gimpact sub type\n");
+ }
+ break;
+ }
+#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:
+ {
+ btCapsuleShapeData* capData = (btCapsuleShapeData*)shapeData;
+
+
+ switch (capData->m_upAxis)
+ {
+ case 0:
+ {
+ shape = createCapsuleShapeX(1,1);
+ break;
+ }
+ case 1:
+ {
+ shape = createCapsuleShapeY(1,1);
+ break;
+ }
+ case 2:
+ {
+ shape = createCapsuleShapeZ(1,1);
+ break;
+ }
+ default:
+ {
+ printf("error: wrong up axis for btCapsuleShape\n");
+ }
+
+
+ };
+ if (shape)
+ {
+ btCapsuleShape* cap = (btCapsuleShape*) shape;
+ cap->deSerializeFloat(capData);
+ }
+ break;
+ }
+ case CYLINDER_SHAPE_PROXYTYPE:
+ case CONE_SHAPE_PROXYTYPE:
+ case BOX_SHAPE_PROXYTYPE:
+ case SPHERE_SHAPE_PROXYTYPE:
+ case MULTI_SPHERE_SHAPE_PROXYTYPE:
+ case CONVEX_HULL_SHAPE_PROXYTYPE:
+ {
+ btConvexInternalShapeData* bsd = (btConvexInternalShapeData*)shapeData;
+ btVector3 implicitShapeDimensions;
+ implicitShapeDimensions.deSerializeFloat(bsd->m_implicitShapeDimensions);
+ btVector3 localScaling;
+ localScaling.deSerializeFloat(bsd->m_localScaling);
+ btVector3 margin(bsd->m_collisionMargin,bsd->m_collisionMargin,bsd->m_collisionMargin);
+ switch (shapeData->m_shapeType)
+ {
+ case BOX_SHAPE_PROXYTYPE:
+ {
+ btBoxShape* box= (btBoxShape*)createBoxShape(implicitShapeDimensions/localScaling+margin);
+ //box->initializePolyhedralFeatures();
+ shape = box;
+
+ break;
+ }
+ case SPHERE_SHAPE_PROXYTYPE:
+ {
+ shape = createSphereShape(implicitShapeDimensions.getX());
+ break;
+ }
+
+ case CYLINDER_SHAPE_PROXYTYPE:
+ {
+ btCylinderShapeData* cylData = (btCylinderShapeData*) shapeData;
+ btVector3 halfExtents = implicitShapeDimensions+margin;
+ switch (cylData->m_upAxis)
+ {
+ case 0:
+ {
+ shape = createCylinderShapeX(halfExtents.getY(),halfExtents.getX());
+ break;
+ }
+ case 1:
+ {
+ shape = createCylinderShapeY(halfExtents.getX(),halfExtents.getY());
+ break;
+ }
+ case 2:
+ {
+ shape = createCylinderShapeZ(halfExtents.getX(),halfExtents.getZ());
+ break;
+ }
+ default:
+ {
+ printf("unknown Cylinder up axis\n");
+ }
+
+ };
+
+
+
+ break;
+ }
+ case CONE_SHAPE_PROXYTYPE:
+ {
+ btConeShapeData* conData = (btConeShapeData*) shapeData;
+ btVector3 halfExtents = implicitShapeDimensions;//+margin;
+ switch (conData->m_upIndex)
+ {
+ case 0:
+ {
+ shape = createConeShapeX(halfExtents.getY(),halfExtents.getX());
+ break;
+ }
+ case 1:
+ {
+ shape = createConeShapeY(halfExtents.getX(),halfExtents.getY());
+ break;
+ }
+ case 2:
+ {
+ shape = createConeShapeZ(halfExtents.getX(),halfExtents.getZ());
+ break;
+ }
+ default:
+ {
+ printf("unknown Cone up axis\n");
+ }
+
+ };
+
+
+
+ break;
+ }
+ case MULTI_SPHERE_SHAPE_PROXYTYPE:
+ {
+ btMultiSphereShapeData* mss = (btMultiSphereShapeData*)bsd;
+ int numSpheres = mss->m_localPositionArraySize;
+
+ btAlignedObjectArray<btVector3> tmpPos;
+ btAlignedObjectArray<btScalar> radii;
+ radii.resize(numSpheres);
+ tmpPos.resize(numSpheres);
+ int i;
+ for ( i=0;i<numSpheres;i++)
+ {
+ tmpPos[i].deSerializeFloat(mss->m_localPositionArrayPtr[i].m_pos);
+ radii[i] = mss->m_localPositionArrayPtr[i].m_radius;
+ }
+ shape = createMultiSphereShape(&tmpPos[0],&radii[0],numSpheres);
+ break;
+ }
+ case CONVEX_HULL_SHAPE_PROXYTYPE:
+ {
+ // int sz = sizeof(btConvexHullShapeData);
+ // int sz2 = sizeof(btConvexInternalShapeData);
+ // int sz3 = sizeof(btCollisionShapeData);
+ btConvexHullShapeData* convexData = (btConvexHullShapeData*)bsd;
+ int numPoints = convexData->m_numUnscaledPoints;
+
+ btAlignedObjectArray<btVector3> tmpPoints;
+ tmpPoints.resize(numPoints);
+ int i;
+ for ( i=0;i<numPoints;i++)
+ {
+#ifdef BT_USE_DOUBLE_PRECISION
+ if (convexData->m_unscaledPointsDoublePtr)
+ tmpPoints[i].deSerialize(convexData->m_unscaledPointsDoublePtr[i]);
+ if (convexData->m_unscaledPointsFloatPtr)
+ tmpPoints[i].deSerializeFloat(convexData->m_unscaledPointsFloatPtr[i]);
+#else
+ if (convexData->m_unscaledPointsFloatPtr)
+ tmpPoints[i].deSerialize(convexData->m_unscaledPointsFloatPtr[i]);
+ if (convexData->m_unscaledPointsDoublePtr)
+ tmpPoints[i].deSerializeDouble(convexData->m_unscaledPointsDoublePtr[i]);
+#endif //BT_USE_DOUBLE_PRECISION
+ }
+ btConvexHullShape* hullShape = createConvexHullShape();
+ for (i=0;i<numPoints;i++)
+ {
+ hullShape->addPoint(tmpPoints[i]);
+ }
+ hullShape->setMargin(bsd->m_collisionMargin);
+ //hullShape->initializePolyhedralFeatures();
+ shape = hullShape;
+ break;
+ }
+ default:
+ {
+ printf("error: cannot create shape type (%d)\n",shapeData->m_shapeType);
+ }
+ }
+
+ if (shape)
+ {
+ shape->setMargin(bsd->m_collisionMargin);
+
+ btVector3 localScaling;
+ localScaling.deSerializeFloat(bsd->m_localScaling);
+ shape->setLocalScaling(localScaling);
+
+ }
+ break;
+ }
+ case TRIANGLE_MESH_SHAPE_PROXYTYPE:
+ {
+ btTriangleMeshShapeData* trimesh = (btTriangleMeshShapeData*)shapeData;
+ btStridingMeshInterfaceData* interfaceData = createStridingMeshInterfaceData(&trimesh->m_meshInterface);
+ btTriangleIndexVertexArray* meshInterface = createMeshInterface(*interfaceData);
+ if (!meshInterface->getNumSubParts())
+ {
+ return 0;
+ }
+
+ btVector3 scaling; scaling.deSerializeFloat(trimesh->m_meshInterface.m_scaling);
+ meshInterface->setScaling(scaling);
+
+
+ btOptimizedBvh* bvh = 0;
+#if 1
+ if (trimesh->m_quantizedFloatBvh)
+ {
+ btOptimizedBvh** bvhPtr = m_bvhMap.find(trimesh->m_quantizedFloatBvh);
+ if (bvhPtr && *bvhPtr)
+ {
+ bvh = *bvhPtr;
+ } else
+ {
+ bvh = createOptimizedBvh();
+ bvh->deSerializeFloat(*trimesh->m_quantizedFloatBvh);
+ }
+ }
+ if (trimesh->m_quantizedDoubleBvh)
+ {
+ btOptimizedBvh** bvhPtr = m_bvhMap.find(trimesh->m_quantizedDoubleBvh);
+ if (bvhPtr && *bvhPtr)
+ {
+ bvh = *bvhPtr;
+ } else
+ {
+ bvh = createOptimizedBvh();
+ bvh->deSerializeDouble(*trimesh->m_quantizedDoubleBvh);
+ }
+ }
+#endif
+
+
+ btBvhTriangleMeshShape* trimeshShape = createBvhTriangleMeshShape(meshInterface,bvh);
+ trimeshShape->setMargin(trimesh->m_collisionMargin);
+ shape = trimeshShape;
+
+ if (trimesh->m_triangleInfoMap)
+ {
+ btTriangleInfoMap* map = createTriangleInfoMap();
+ map->deSerialize(*trimesh->m_triangleInfoMap);
+ trimeshShape->setTriangleInfoMap(map);
+
+#ifdef USE_INTERNAL_EDGE_UTILITY
+ gContactAddedCallback = btAdjustInternalEdgeContactsCallback;
+#endif //USE_INTERNAL_EDGE_UTILITY
+
+ }
+
+ //printf("trimesh->m_collisionMargin=%f\n",trimesh->m_collisionMargin);
+ break;
+ }
+ case COMPOUND_SHAPE_PROXYTYPE:
+ {
+ btCompoundShapeData* compoundData = (btCompoundShapeData*)shapeData;
+ btCompoundShape* compoundShape = createCompoundShape();
+
+ //btCompoundShapeChildData* childShapeDataArray = &compoundData->m_childShapePtr[0];
+
+
+ btAlignedObjectArray<btCollisionShape*> childShapes;
+ for (int i=0;i<compoundData->m_numChildShapes;i++)
+ {
+ //btCompoundShapeChildData* ptr = &compoundData->m_childShapePtr[i];
+
+ btCollisionShapeData* cd = compoundData->m_childShapePtr[i].m_childShape;
+
+ btCollisionShape* childShape = convertCollisionShape(cd);
+ if (childShape)
+ {
+ btTransform localTransform;
+ localTransform.deSerializeFloat(compoundData->m_childShapePtr[i].m_transform);
+ compoundShape->addChildShape(localTransform,childShape);
+ } else
+ {
+#ifdef _DEBUG
+ printf("error: couldn't create childShape for compoundShape\n");
+#endif
+ }
+
+ }
+ shape = compoundShape;
+
+ break;
+ }
+ case SOFTBODY_SHAPE_PROXYTYPE:
+ {
+ return 0;
+ }
+ default:
+ {
+#ifdef _DEBUG
+ printf("unsupported shape type (%d)\n",shapeData->m_shapeType);
+#endif
+ }
+ }
+
+ return shape;
+
+}
+
+
+
+char* btCollisionWorldImporter::duplicateName(const char* name)
+{
+ if (name)
+ {
+ int l = (int)strlen(name);
+ char* newName = new char[l+1];
+ memcpy(newName,name,l);
+ newName[l] = 0;
+ m_allocatedNames.push_back(newName);
+ return newName;
+ }
+ return 0;
+}
+
+
+
+
+
+
+
+
+
+
+
+btTriangleIndexVertexArray* btCollisionWorldImporter::createMeshInterface(btStridingMeshInterfaceData& meshData)
+{
+ btTriangleIndexVertexArray* meshInterface = createTriangleMeshContainer();
+
+ for (int i=0;i<meshData.m_numMeshParts;i++)
+ {
+ btIndexedMesh meshPart;
+ meshPart.m_numTriangles = meshData.m_meshPartsPtr[i].m_numTriangles;
+ meshPart.m_numVertices = meshData.m_meshPartsPtr[i].m_numVertices;
+
+
+ if (meshData.m_meshPartsPtr[i].m_indices32)
+ {
+ meshPart.m_indexType = PHY_INTEGER;
+ meshPart.m_triangleIndexStride = 3*sizeof(int);
+ int* indexArray = (int*)btAlignedAlloc(sizeof(int)*3*meshPart.m_numTriangles,16);
+ m_indexArrays.push_back(indexArray);
+ for (int j=0;j<3*meshPart.m_numTriangles;j++)
+ {
+ indexArray[j] = meshData.m_meshPartsPtr[i].m_indices32[j].m_value;
+ }
+ meshPart.m_triangleIndexBase = (const unsigned char*)indexArray;
+ } else
+ {
+ if (meshData.m_meshPartsPtr[i].m_3indices16)
+ {
+ meshPart.m_indexType = PHY_SHORT;
+ meshPart.m_triangleIndexStride = sizeof(short int)*3;//sizeof(btShortIntIndexTripletData);
+
+ short int* indexArray = (short int*)btAlignedAlloc(sizeof(short int)*3*meshPart.m_numTriangles,16);
+ m_shortIndexArrays.push_back(indexArray);
+
+ for (int j=0;j<meshPart.m_numTriangles;j++)
+ {
+ indexArray[3*j] = meshData.m_meshPartsPtr[i].m_3indices16[j].m_values[0];
+ indexArray[3*j+1] = meshData.m_meshPartsPtr[i].m_3indices16[j].m_values[1];
+ indexArray[3*j+2] = meshData.m_meshPartsPtr[i].m_3indices16[j].m_values[2];
+ }
+
+ meshPart.m_triangleIndexBase = (const unsigned char*)indexArray;
+ }
+ if (meshData.m_meshPartsPtr[i].m_indices16)
+ {
+ meshPart.m_indexType = PHY_SHORT;
+ meshPart.m_triangleIndexStride = 3*sizeof(short int);
+ short int* indexArray = (short int*)btAlignedAlloc(sizeof(short int)*3*meshPart.m_numTriangles,16);
+ m_shortIndexArrays.push_back(indexArray);
+ for (int j=0;j<3*meshPart.m_numTriangles;j++)
+ {
+ indexArray[j] = meshData.m_meshPartsPtr[i].m_indices16[j].m_value;
+ }
+
+ meshPart.m_triangleIndexBase = (const unsigned char*)indexArray;
+ }
+
+ if (meshData.m_meshPartsPtr[i].m_3indices8)
+ {
+ meshPart.m_indexType = PHY_UCHAR;
+ meshPart.m_triangleIndexStride = sizeof(unsigned char)*3;
+
+ unsigned char* indexArray = (unsigned char*)btAlignedAlloc(sizeof(unsigned char)*3*meshPart.m_numTriangles,16);
+ m_charIndexArrays.push_back(indexArray);
+
+ for (int j=0;j<meshPart.m_numTriangles;j++)
+ {
+ indexArray[3*j] = meshData.m_meshPartsPtr[i].m_3indices8[j].m_values[0];
+ indexArray[3*j+1] = meshData.m_meshPartsPtr[i].m_3indices8[j].m_values[1];
+ indexArray[3*j+2] = meshData.m_meshPartsPtr[i].m_3indices8[j].m_values[2];
+ }
+
+ meshPart.m_triangleIndexBase = (const unsigned char*)indexArray;
+ }
+ }
+
+ if (meshData.m_meshPartsPtr[i].m_vertices3f)
+ {
+ meshPart.m_vertexType = PHY_FLOAT;
+ meshPart.m_vertexStride = sizeof(btVector3FloatData);
+ btVector3FloatData* vertices = (btVector3FloatData*) btAlignedAlloc(sizeof(btVector3FloatData)*meshPart.m_numVertices,16);
+ m_floatVertexArrays.push_back(vertices);
+
+ for (int j=0;j<meshPart.m_numVertices;j++)
+ {
+ vertices[j].m_floats[0] = meshData.m_meshPartsPtr[i].m_vertices3f[j].m_floats[0];
+ vertices[j].m_floats[1] = meshData.m_meshPartsPtr[i].m_vertices3f[j].m_floats[1];
+ vertices[j].m_floats[2] = meshData.m_meshPartsPtr[i].m_vertices3f[j].m_floats[2];
+ vertices[j].m_floats[3] = meshData.m_meshPartsPtr[i].m_vertices3f[j].m_floats[3];
+ }
+ meshPart.m_vertexBase = (const unsigned char*)vertices;
+ } else
+ {
+ meshPart.m_vertexType = PHY_DOUBLE;
+ meshPart.m_vertexStride = sizeof(btVector3DoubleData);
+
+
+ btVector3DoubleData* vertices = (btVector3DoubleData*) btAlignedAlloc(sizeof(btVector3DoubleData)*meshPart.m_numVertices,16);
+ m_doubleVertexArrays.push_back(vertices);
+
+ for (int j=0;j<meshPart.m_numVertices;j++)
+ {
+ vertices[j].m_floats[0] = meshData.m_meshPartsPtr[i].m_vertices3d[j].m_floats[0];
+ vertices[j].m_floats[1] = meshData.m_meshPartsPtr[i].m_vertices3d[j].m_floats[1];
+ vertices[j].m_floats[2] = meshData.m_meshPartsPtr[i].m_vertices3d[j].m_floats[2];
+ vertices[j].m_floats[3] = meshData.m_meshPartsPtr[i].m_vertices3d[j].m_floats[3];
+ }
+ meshPart.m_vertexBase = (const unsigned char*)vertices;
+ }
+
+ if (meshPart.m_triangleIndexBase && meshPart.m_vertexBase)
+ {
+ meshInterface->addIndexedMesh(meshPart,meshPart.m_indexType);
+ }
+ }
+
+ return meshInterface;
+}
+
+
+btStridingMeshInterfaceData* btCollisionWorldImporter::createStridingMeshInterfaceData(btStridingMeshInterfaceData* interfaceData)
+{
+ //create a new btStridingMeshInterfaceData that is an exact copy of shapedata and store it in the WorldImporter
+ btStridingMeshInterfaceData* newData = new btStridingMeshInterfaceData;
+
+ newData->m_scaling = interfaceData->m_scaling;
+ newData->m_numMeshParts = interfaceData->m_numMeshParts;
+ newData->m_meshPartsPtr = new btMeshPartData[newData->m_numMeshParts];
+
+ for(int i = 0;i < newData->m_numMeshParts;i++)
+ {
+ btMeshPartData* curPart = &interfaceData->m_meshPartsPtr[i];
+ btMeshPartData* curNewPart = &newData->m_meshPartsPtr[i];
+
+ curNewPart->m_numTriangles = curPart->m_numTriangles;
+ curNewPart->m_numVertices = curPart->m_numVertices;
+
+ if(curPart->m_vertices3f)
+ {
+ curNewPart->m_vertices3f = new btVector3FloatData[curNewPart->m_numVertices];
+ memcpy(curNewPart->m_vertices3f,curPart->m_vertices3f,sizeof(btVector3FloatData) * curNewPart->m_numVertices);
+ }
+ else
+ curNewPart->m_vertices3f = NULL;
+
+ if(curPart->m_vertices3d)
+ {
+ curNewPart->m_vertices3d = new btVector3DoubleData[curNewPart->m_numVertices];
+ memcpy(curNewPart->m_vertices3d,curPart->m_vertices3d,sizeof(btVector3DoubleData) * curNewPart->m_numVertices);
+ }
+ else
+ curNewPart->m_vertices3d = NULL;
+
+ int numIndices = curNewPart->m_numTriangles * 3;
+ ///the m_3indices8 was not initialized in some Bullet versions, this can cause crashes at loading time
+ ///we catch it by only dealing with m_3indices8 if none of the other indices are initialized
+ bool uninitialized3indices8Workaround =false;
+
+ if(curPart->m_indices32)
+ {
+ uninitialized3indices8Workaround=true;
+ curNewPart->m_indices32 = new btIntIndexData[numIndices];
+ memcpy(curNewPart->m_indices32,curPart->m_indices32,sizeof(btIntIndexData) * numIndices);
+ }
+ else
+ curNewPart->m_indices32 = NULL;
+
+ if(curPart->m_3indices16)
+ {
+ uninitialized3indices8Workaround=true;
+ curNewPart->m_3indices16 = new btShortIntIndexTripletData[curNewPart->m_numTriangles];
+ memcpy(curNewPart->m_3indices16,curPart->m_3indices16,sizeof(btShortIntIndexTripletData) * curNewPart->m_numTriangles);
+ }
+ else
+ curNewPart->m_3indices16 = NULL;
+
+ if(curPart->m_indices16)
+ {
+ uninitialized3indices8Workaround=true;
+ curNewPart->m_indices16 = new btShortIntIndexData[numIndices];
+ memcpy(curNewPart->m_indices16,curPart->m_indices16,sizeof(btShortIntIndexData) * numIndices);
+ }
+ else
+ curNewPart->m_indices16 = NULL;
+
+ if(!uninitialized3indices8Workaround && curPart->m_3indices8)
+ {
+ curNewPart->m_3indices8 = new btCharIndexTripletData[curNewPart->m_numTriangles];
+ memcpy(curNewPart->m_3indices8,curPart->m_3indices8,sizeof(btCharIndexTripletData) * curNewPart->m_numTriangles);
+ }
+ else
+ curNewPart->m_3indices8 = NULL;
+
+ }
+
+ m_allocatedbtStridingMeshInterfaceDatas.push_back(newData);
+
+ return(newData);
+}
+
+#ifdef USE_INTERNAL_EDGE_UTILITY
+extern ContactAddedCallback gContactAddedCallback;
+
+static bool btAdjustInternalEdgeContactsCallback(btManifoldPoint& cp, const btCollisionObject* colObj0,int partId0,int index0,const btCollisionObject* colObj1,int partId1,int index1)
+{
+
+ btAdjustInternalEdgeContacts(cp,colObj1,colObj0, partId1,index1);
+ //btAdjustInternalEdgeContacts(cp,colObj1,colObj0, partId1,index1, BT_TRIANGLE_CONVEX_BACKFACE_MODE);
+ //btAdjustInternalEdgeContacts(cp,colObj1,colObj0, partId1,index1, BT_TRIANGLE_CONVEX_DOUBLE_SIDED+BT_TRIANGLE_CONCAVE_DOUBLE_SIDED);
+ return true;
+}
+#endif //USE_INTERNAL_EDGE_UTILITY
+
+
+/*
+btRigidBody* btWorldImporter::createRigidBody(bool isDynamic, btScalar mass, const btTransform& startTransform,btCollisionShape* shape,const char* bodyName)
+{
+ btVector3 localInertia;
+ localInertia.setZero();
+
+ if (mass)
+ shape->calculateLocalInertia(mass,localInertia);
+
+ btRigidBody* body = new btRigidBody(mass,0,shape,localInertia);
+ body->setWorldTransform(startTransform);
+
+ if (m_dynamicsWorld)
+ m_dynamicsWorld->addRigidBody(body);
+
+ if (bodyName)
+ {
+ char* newname = duplicateName(bodyName);
+ m_objectNameMap.insert(body,newname);
+ m_nameBodyMap.insert(newname,body);
+ }
+ m_allocatedRigidBodies.push_back(body);
+ return body;
+
+}
+*/
+
+btCollisionObject* btCollisionWorldImporter::getCollisionObjectByName(const char* name)
+{
+ btCollisionObject** bodyPtr = m_nameColObjMap.find(name);
+ if (bodyPtr && *bodyPtr)
+ {
+ return *bodyPtr;
+ }
+ return 0;
+}
+
+btCollisionObject* btCollisionWorldImporter::createCollisionObject(const btTransform& startTransform,btCollisionShape* shape, const char* bodyName)
+{
+ btCollisionObject* colObj = new btCollisionObject();
+ colObj->setWorldTransform(startTransform);
+ colObj->setCollisionShape(shape);
+ m_collisionWorld->addCollisionObject(colObj);//todo: flags etc
+
+ if (bodyName)
+ {
+ char* newname = duplicateName(bodyName);
+ m_objectNameMap.insert(colObj,newname);
+ m_nameColObjMap.insert(newname,colObj);
+ }
+ m_allocatedCollisionObjects.push_back(colObj);
+
+ return colObj;
+}
+
+
+
+btCollisionShape* btCollisionWorldImporter::createPlaneShape(const btVector3& planeNormal,btScalar planeConstant)
+{
+ btStaticPlaneShape* shape = new btStaticPlaneShape(planeNormal,planeConstant);
+ m_allocatedCollisionShapes.push_back(shape);
+ return shape;
+}
+btCollisionShape* btCollisionWorldImporter::createBoxShape(const btVector3& halfExtents)
+{
+ btBoxShape* shape = new btBoxShape(halfExtents);
+ m_allocatedCollisionShapes.push_back(shape);
+ return shape;
+}
+btCollisionShape* btCollisionWorldImporter::createSphereShape(btScalar radius)
+{
+ btSphereShape* shape = new btSphereShape(radius);
+ m_allocatedCollisionShapes.push_back(shape);
+ return shape;
+}
+
+
+btCollisionShape* btCollisionWorldImporter::createCapsuleShapeX(btScalar radius, btScalar height)
+{
+ btCapsuleShapeX* shape = new btCapsuleShapeX(radius,height);
+ m_allocatedCollisionShapes.push_back(shape);
+ return shape;
+}
+
+btCollisionShape* btCollisionWorldImporter::createCapsuleShapeY(btScalar radius, btScalar height)
+{
+ btCapsuleShape* shape = new btCapsuleShape(radius,height);
+ m_allocatedCollisionShapes.push_back(shape);
+ return shape;
+}
+
+btCollisionShape* btCollisionWorldImporter::createCapsuleShapeZ(btScalar radius, btScalar height)
+{
+ btCapsuleShapeZ* shape = new btCapsuleShapeZ(radius,height);
+ m_allocatedCollisionShapes.push_back(shape);
+ return shape;
+}
+
+btCollisionShape* btCollisionWorldImporter::createCylinderShapeX(btScalar radius,btScalar height)
+{
+ btCylinderShapeX* shape = new btCylinderShapeX(btVector3(height,radius,radius));
+ m_allocatedCollisionShapes.push_back(shape);
+ return shape;
+}
+
+btCollisionShape* btCollisionWorldImporter::createCylinderShapeY(btScalar radius,btScalar height)
+{
+ btCylinderShape* shape = new btCylinderShape(btVector3(radius,height,radius));
+ m_allocatedCollisionShapes.push_back(shape);
+ return shape;
+}
+
+btCollisionShape* btCollisionWorldImporter::createCylinderShapeZ(btScalar radius,btScalar height)
+{
+ btCylinderShapeZ* shape = new btCylinderShapeZ(btVector3(radius,radius,height));
+ m_allocatedCollisionShapes.push_back(shape);
+ return shape;
+}
+
+btCollisionShape* btCollisionWorldImporter::createConeShapeX(btScalar radius,btScalar height)
+{
+ btConeShapeX* shape = new btConeShapeX(radius,height);
+ m_allocatedCollisionShapes.push_back(shape);
+ return shape;
+}
+
+btCollisionShape* btCollisionWorldImporter::createConeShapeY(btScalar radius,btScalar height)
+{
+ btConeShape* shape = new btConeShape(radius,height);
+ m_allocatedCollisionShapes.push_back(shape);
+ return shape;
+}
+
+btCollisionShape* btCollisionWorldImporter::createConeShapeZ(btScalar radius,btScalar height)
+{
+ btConeShapeZ* shape = new btConeShapeZ(radius,height);
+ m_allocatedCollisionShapes.push_back(shape);
+ return shape;
+}
+
+btTriangleIndexVertexArray* btCollisionWorldImporter::createTriangleMeshContainer()
+{
+ btTriangleIndexVertexArray* in = new btTriangleIndexVertexArray();
+ m_allocatedTriangleIndexArrays.push_back(in);
+ return in;
+}
+
+btOptimizedBvh* btCollisionWorldImporter::createOptimizedBvh()
+{
+ btOptimizedBvh* bvh = new btOptimizedBvh();
+ m_allocatedBvhs.push_back(bvh);
+ return bvh;
+}
+
+
+btTriangleInfoMap* btCollisionWorldImporter::createTriangleInfoMap()
+{
+ btTriangleInfoMap* tim = new btTriangleInfoMap();
+ m_allocatedTriangleInfoMaps.push_back(tim);
+ return tim;
+}
+
+btBvhTriangleMeshShape* btCollisionWorldImporter::createBvhTriangleMeshShape(btStridingMeshInterface* trimesh, btOptimizedBvh* bvh)
+{
+ if (bvh)
+ {
+ btBvhTriangleMeshShape* bvhTriMesh = new btBvhTriangleMeshShape(trimesh,bvh->isQuantized(), false);
+ bvhTriMesh->setOptimizedBvh(bvh);
+ m_allocatedCollisionShapes.push_back(bvhTriMesh);
+ return bvhTriMesh;
+ }
+
+ btBvhTriangleMeshShape* ts = new btBvhTriangleMeshShape(trimesh,true);
+ m_allocatedCollisionShapes.push_back(ts);
+ return ts;
+
+}
+btCollisionShape* btCollisionWorldImporter::createConvexTriangleMeshShape(btStridingMeshInterface* trimesh)
+{
+ return 0;
+}
+#ifdef SUPPORT_GIMPACT_SHAPE_IMPORT
+btGImpactMeshShape* btCollisionWorldImporter::createGimpactShape(btStridingMeshInterface* trimesh)
+{
+ btGImpactMeshShape* shape = new btGImpactMeshShape(trimesh);
+ m_allocatedCollisionShapes.push_back(shape);
+ return shape;
+
+}
+#endif //SUPPORT_GIMPACT_SHAPE_IMPORT
+
+btConvexHullShape* btCollisionWorldImporter::createConvexHullShape()
+{
+ btConvexHullShape* shape = new btConvexHullShape();
+ m_allocatedCollisionShapes.push_back(shape);
+ return shape;
+}
+
+btCompoundShape* btCollisionWorldImporter::createCompoundShape()
+{
+ btCompoundShape* shape = new btCompoundShape();
+ m_allocatedCollisionShapes.push_back(shape);
+ return shape;
+}
+
+
+btScaledBvhTriangleMeshShape* btCollisionWorldImporter::createScaledTrangleMeshShape(btBvhTriangleMeshShape* meshShape,const btVector3& localScaling)
+{
+ btScaledBvhTriangleMeshShape* shape = new btScaledBvhTriangleMeshShape(meshShape,localScaling);
+ m_allocatedCollisionShapes.push_back(shape);
+ return shape;
+}
+
+btMultiSphereShape* btCollisionWorldImporter::createMultiSphereShape(const btVector3* positions,const btScalar* radi,int numSpheres)
+{
+ btMultiSphereShape* shape = new btMultiSphereShape(positions, radi, numSpheres);
+ m_allocatedCollisionShapes.push_back(shape);
+ return shape;
+}
+
+
+
+ // query for data
+int btCollisionWorldImporter::getNumCollisionShapes() const
+{
+ return m_allocatedCollisionShapes.size();
+}
+
+btCollisionShape* btCollisionWorldImporter::getCollisionShapeByIndex(int index)
+{
+ return m_allocatedCollisionShapes[index];
+}
+
+btCollisionShape* btCollisionWorldImporter::getCollisionShapeByName(const char* name)
+{
+ btCollisionShape** shapePtr = m_nameShapeMap.find(name);
+ if (shapePtr&& *shapePtr)
+ {
+ return *shapePtr;
+ }
+ return 0;
+}
+
+
+const char* btCollisionWorldImporter::getNameForPointer(const void* ptr) const
+{
+ const char*const * namePtr = m_objectNameMap.find(ptr);
+ if (namePtr && *namePtr)
+ return *namePtr;
+ return 0;
+}
+
+
+int btCollisionWorldImporter::getNumRigidBodies() const
+{
+ return m_allocatedRigidBodies.size();
+}
+
+btCollisionObject* btCollisionWorldImporter::getRigidBodyByIndex(int index) const
+{
+ return m_allocatedRigidBodies[index];
+}
+
+
+int btCollisionWorldImporter::getNumBvhs() const
+{
+ return m_allocatedBvhs.size();
+}
+ btOptimizedBvh* btCollisionWorldImporter::getBvhByIndex(int index) const
+{
+ return m_allocatedBvhs[index];
+}
+
+int btCollisionWorldImporter::getNumTriangleInfoMaps() const
+{
+ return m_allocatedTriangleInfoMaps.size();
+}
+
+btTriangleInfoMap* btCollisionWorldImporter::getTriangleInfoMapByIndex(int index) const
+{
+ return m_allocatedTriangleInfoMaps[index];
+}
+
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCollisionWorldImporter.h b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCollisionWorldImporter.h
new file mode 100644
index 0000000000..81c6142726
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCollisionWorldImporter.h
@@ -0,0 +1,189 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2014 Erwin Coumans 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_COLLISION_WORLD_IMPORTER_H
+#define BT_COLLISION_WORLD_IMPORTER_H
+
+#include "LinearMath/btTransform.h"
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btAlignedObjectArray.h"
+#include "LinearMath/btHashMap.h"
+
+class btCollisionShape;
+class btCollisionObject;
+struct btBulletSerializedArrays;
+
+
+struct ConstraintInput;
+class btCollisionWorld;
+struct btCollisionShapeData;
+class btTriangleIndexVertexArray;
+class btStridingMeshInterface;
+struct btStridingMeshInterfaceData;
+class btGImpactMeshShape;
+class btOptimizedBvh;
+struct btTriangleInfoMap;
+class btBvhTriangleMeshShape;
+class btPoint2PointConstraint;
+class btHingeConstraint;
+class btConeTwistConstraint;
+class btGeneric6DofConstraint;
+class btGeneric6DofSpringConstraint;
+class btSliderConstraint;
+class btGearConstraint;
+struct btContactSolverInfo;
+
+
+
+
+class btCollisionWorldImporter
+{
+protected:
+ btCollisionWorld* m_collisionWorld;
+
+ int m_verboseMode;
+
+ btAlignedObjectArray<btCollisionShape*> m_allocatedCollisionShapes;
+ btAlignedObjectArray<btCollisionObject*> m_allocatedRigidBodies;
+
+ btAlignedObjectArray<btOptimizedBvh*> m_allocatedBvhs;
+ btAlignedObjectArray<btTriangleInfoMap*> m_allocatedTriangleInfoMaps;
+ btAlignedObjectArray<btTriangleIndexVertexArray*> m_allocatedTriangleIndexArrays;
+ btAlignedObjectArray<btStridingMeshInterfaceData*> m_allocatedbtStridingMeshInterfaceDatas;
+ btAlignedObjectArray<btCollisionObject*> m_allocatedCollisionObjects;
+
+
+ btAlignedObjectArray<char*> m_allocatedNames;
+
+ btAlignedObjectArray<int*> m_indexArrays;
+ btAlignedObjectArray<short int*> m_shortIndexArrays;
+ btAlignedObjectArray<unsigned char*> m_charIndexArrays;
+
+ btAlignedObjectArray<btVector3FloatData*> m_floatVertexArrays;
+ btAlignedObjectArray<btVector3DoubleData*> m_doubleVertexArrays;
+
+
+ btHashMap<btHashPtr,btOptimizedBvh*> m_bvhMap;
+ btHashMap<btHashPtr,btTriangleInfoMap*> m_timMap;
+
+ btHashMap<btHashString,btCollisionShape*> m_nameShapeMap;
+ btHashMap<btHashString,btCollisionObject*> m_nameColObjMap;
+
+ btHashMap<btHashPtr,const char*> m_objectNameMap;
+
+ btHashMap<btHashPtr,btCollisionShape*> m_shapeMap;
+ btHashMap<btHashPtr,btCollisionObject*> m_bodyMap;
+
+
+ //methods
+
+
+
+ char* duplicateName(const char* name);
+
+ btCollisionShape* convertCollisionShape( btCollisionShapeData* shapeData );
+
+
+public:
+
+ btCollisionWorldImporter(btCollisionWorld* world);
+
+ virtual ~btCollisionWorldImporter();
+
+ bool convertAllObjects( btBulletSerializedArrays* arrays);
+
+ ///delete all memory collision shapes, rigid bodies, constraints etc. allocated during the load.
+ ///make sure you don't use the dynamics world containing objects after you call this method
+ virtual void deleteAllData();
+
+ void setVerboseMode(int verboseMode)
+ {
+ m_verboseMode = verboseMode;
+ }
+
+ int getVerboseMode() const
+ {
+ return m_verboseMode;
+ }
+
+ // query for data
+ int getNumCollisionShapes() const;
+ btCollisionShape* getCollisionShapeByIndex(int index);
+ int getNumRigidBodies() const;
+ btCollisionObject* getRigidBodyByIndex(int index) const;
+
+ int getNumBvhs() const;
+ btOptimizedBvh* getBvhByIndex(int index) const;
+ int getNumTriangleInfoMaps() const;
+ btTriangleInfoMap* getTriangleInfoMapByIndex(int index) const;
+
+ // queris involving named objects
+ btCollisionShape* getCollisionShapeByName(const char* name);
+ btCollisionObject* getCollisionObjectByName(const char* name);
+
+
+ const char* getNameForPointer(const void* ptr) const;
+
+ ///those virtuals are called by load and can be overridden by the user
+
+
+
+ //bodies
+
+ virtual btCollisionObject* createCollisionObject( const btTransform& startTransform, btCollisionShape* shape,const char* bodyName);
+
+ ///shapes
+
+ virtual btCollisionShape* createPlaneShape(const btVector3& planeNormal,btScalar planeConstant);
+ virtual btCollisionShape* createBoxShape(const btVector3& halfExtents);
+ virtual btCollisionShape* createSphereShape(btScalar radius);
+ virtual btCollisionShape* createCapsuleShapeX(btScalar radius, btScalar height);
+ virtual btCollisionShape* createCapsuleShapeY(btScalar radius, btScalar height);
+ virtual btCollisionShape* createCapsuleShapeZ(btScalar radius, btScalar height);
+
+ virtual btCollisionShape* createCylinderShapeX(btScalar radius,btScalar height);
+ virtual btCollisionShape* createCylinderShapeY(btScalar radius,btScalar height);
+ virtual btCollisionShape* createCylinderShapeZ(btScalar radius,btScalar height);
+ virtual btCollisionShape* createConeShapeX(btScalar radius,btScalar height);
+ virtual btCollisionShape* createConeShapeY(btScalar radius,btScalar height);
+ virtual btCollisionShape* createConeShapeZ(btScalar radius,btScalar height);
+ virtual class btTriangleIndexVertexArray* createTriangleMeshContainer();
+ virtual btBvhTriangleMeshShape* createBvhTriangleMeshShape(btStridingMeshInterface* trimesh, btOptimizedBvh* bvh);
+ virtual btCollisionShape* createConvexTriangleMeshShape(btStridingMeshInterface* trimesh);
+#ifdef SUPPORT_GIMPACT_SHAPE_IMPORT
+ virtual btGImpactMeshShape* createGimpactShape(btStridingMeshInterface* trimesh);
+#endif //SUPPORT_GIMPACT_SHAPE_IMPORT
+ virtual btStridingMeshInterfaceData* createStridingMeshInterfaceData(btStridingMeshInterfaceData* interfaceData);
+
+ virtual class btConvexHullShape* createConvexHullShape();
+ virtual class btCompoundShape* createCompoundShape();
+ virtual class btScaledBvhTriangleMeshShape* createScaledTrangleMeshShape(btBvhTriangleMeshShape* meshShape,const btVector3& localScalingbtBvhTriangleMeshShape);
+
+ virtual class btMultiSphereShape* createMultiSphereShape(const btVector3* positions,const btScalar* radi,int numSpheres);
+
+ virtual btTriangleIndexVertexArray* createMeshInterface(btStridingMeshInterfaceData& meshData);
+
+ ///acceleration and connectivity structures
+ virtual btOptimizedBvh* createOptimizedBvh();
+ virtual btTriangleInfoMap* createTriangleInfoMap();
+
+
+
+
+};
+
+
+#endif //BT_WORLD_IMPORTER_H
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp
new file mode 100644
index 0000000000..7f4dea1c6d
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp
@@ -0,0 +1,402 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+
+*/
+
+#include "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/CollisionShapes/btCompoundShape.h"
+#include "BulletCollision/BroadphaseCollision/btDbvt.h"
+#include "LinearMath/btIDebugDraw.h"
+#include "LinearMath/btAabbUtil2.h"
+#include "btManifoldResult.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
+
+btShapePairCallback gCompoundChildShapePairCallback = 0;
+
+btCompoundCollisionAlgorithm::btCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped)
+:btActivatingCollisionAlgorithm(ci,body0Wrap,body1Wrap),
+m_isSwapped(isSwapped),
+m_sharedManifold(ci.m_manifold)
+{
+ m_ownsManifold = false;
+
+ const btCollisionObjectWrapper* colObjWrap = m_isSwapped? body1Wrap : body0Wrap;
+ btAssert (colObjWrap->getCollisionShape()->isCompound());
+
+ const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(colObjWrap->getCollisionShape());
+ m_compoundShapeRevision = compoundShape->getUpdateRevision();
+
+
+ preallocateChildAlgorithms(body0Wrap,body1Wrap);
+}
+
+void btCompoundCollisionAlgorithm::preallocateChildAlgorithms(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
+{
+ const btCollisionObjectWrapper* colObjWrap = m_isSwapped? body1Wrap : body0Wrap;
+ const btCollisionObjectWrapper* otherObjWrap = m_isSwapped? body0Wrap : body1Wrap;
+ btAssert (colObjWrap->getCollisionShape()->isCompound());
+
+ const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(colObjWrap->getCollisionShape());
+
+ int numChildren = compoundShape->getNumChildShapes();
+ int i;
+
+ m_childCollisionAlgorithms.resize(numChildren);
+ for (i=0;i<numChildren;i++)
+ {
+ if (compoundShape->getDynamicAabbTree())
+ {
+ m_childCollisionAlgorithms[i] = 0;
+ } else
+ {
+
+ const btCollisionShape* childShape = compoundShape->getChildShape(i);
+
+ btCollisionObjectWrapper childWrap(colObjWrap,childShape,colObjWrap->getCollisionObject(),colObjWrap->getWorldTransform(),-1,i);//wrong child trans, but unused (hopefully)
+ m_childCollisionAlgorithms[i] = m_dispatcher->findAlgorithm(&childWrap,otherObjWrap,m_sharedManifold, BT_CONTACT_POINT_ALGORITHMS);
+
+
+ btAlignedObjectArray<btCollisionAlgorithm*> m_childCollisionAlgorithmsContact;
+ btAlignedObjectArray<btCollisionAlgorithm*> m_childCollisionAlgorithmsClosestPoints;
+
+
+ }
+ }
+}
+
+void btCompoundCollisionAlgorithm::removeChildAlgorithms()
+{
+ int numChildren = m_childCollisionAlgorithms.size();
+ int i;
+ for (i=0;i<numChildren;i++)
+ {
+ if (m_childCollisionAlgorithms[i])
+ {
+ m_childCollisionAlgorithms[i]->~btCollisionAlgorithm();
+ m_dispatcher->freeCollisionAlgorithm(m_childCollisionAlgorithms[i]);
+ }
+ }
+}
+
+btCompoundCollisionAlgorithm::~btCompoundCollisionAlgorithm()
+{
+ removeChildAlgorithms();
+}
+
+
+
+
+struct btCompoundLeafCallback : btDbvt::ICollide
+{
+
+public:
+
+ const btCollisionObjectWrapper* m_compoundColObjWrap;
+ const btCollisionObjectWrapper* m_otherObjWrap;
+ btDispatcher* m_dispatcher;
+ const btDispatcherInfo& m_dispatchInfo;
+ btManifoldResult* m_resultOut;
+ btCollisionAlgorithm** m_childCollisionAlgorithms;
+ btPersistentManifold* m_sharedManifold;
+
+ btCompoundLeafCallback (const btCollisionObjectWrapper* compoundObjWrap,const btCollisionObjectWrapper* otherObjWrap,btDispatcher* dispatcher,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut,btCollisionAlgorithm** childCollisionAlgorithms,btPersistentManifold* sharedManifold)
+ :m_compoundColObjWrap(compoundObjWrap),m_otherObjWrap(otherObjWrap),m_dispatcher(dispatcher),m_dispatchInfo(dispatchInfo),m_resultOut(resultOut),
+ m_childCollisionAlgorithms(childCollisionAlgorithms),
+ m_sharedManifold(sharedManifold)
+ {
+
+ }
+
+
+ void ProcessChildShape(const btCollisionShape* childShape,int index)
+ {
+ btAssert(index>=0);
+ const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(m_compoundColObjWrap->getCollisionShape());
+ btAssert(index<compoundShape->getNumChildShapes());
+
+
+ //backup
+ btTransform orgTrans = m_compoundColObjWrap->getWorldTransform();
+
+ const btTransform& childTrans = compoundShape->getChildTransform(index);
+ btTransform newChildWorldTrans = orgTrans*childTrans ;
+
+ //perform an AABB check first
+ btVector3 aabbMin0,aabbMax0;
+ childShape->getAabb(newChildWorldTrans,aabbMin0,aabbMax0);
+
+ btVector3 extendAabb(m_resultOut->m_closestPointDistanceThreshold, m_resultOut->m_closestPointDistanceThreshold, m_resultOut->m_closestPointDistanceThreshold);
+ aabbMin0 -= extendAabb;
+ aabbMax0 += extendAabb;
+
+ btVector3 aabbMin1, aabbMax1;
+ m_otherObjWrap->getCollisionShape()->getAabb(m_otherObjWrap->getWorldTransform(),aabbMin1,aabbMax1);
+
+ if (gCompoundChildShapePairCallback)
+ {
+ if (!gCompoundChildShapePairCallback(m_otherObjWrap->getCollisionShape(), childShape))
+ return;
+ }
+
+ if (TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1))
+ {
+
+ btCollisionObjectWrapper compoundWrap(this->m_compoundColObjWrap,childShape,m_compoundColObjWrap->getCollisionObject(),newChildWorldTrans,-1,index);
+
+ btCollisionAlgorithm* algo = 0;
+
+ if (m_resultOut->m_closestPointDistanceThreshold > 0)
+ {
+ algo = m_dispatcher->findAlgorithm(&compoundWrap, m_otherObjWrap, 0, BT_CLOSEST_POINT_ALGORITHMS);
+ }
+ else
+ {
+ //the contactpoint is still projected back using the original inverted worldtrans
+ if (!m_childCollisionAlgorithms[index])
+ {
+ m_childCollisionAlgorithms[index] = m_dispatcher->findAlgorithm(&compoundWrap, m_otherObjWrap, m_sharedManifold, BT_CONTACT_POINT_ALGORITHMS);
+ }
+ algo = m_childCollisionAlgorithms[index];
+ }
+
+ const btCollisionObjectWrapper* tmpWrap = 0;
+
+ ///detect swapping case
+ if (m_resultOut->getBody0Internal() == m_compoundColObjWrap->getCollisionObject())
+ {
+ tmpWrap = m_resultOut->getBody0Wrap();
+ m_resultOut->setBody0Wrap(&compoundWrap);
+ m_resultOut->setShapeIdentifiersA(-1,index);
+ } else
+ {
+ tmpWrap = m_resultOut->getBody1Wrap();
+ m_resultOut->setBody1Wrap(&compoundWrap);
+ m_resultOut->setShapeIdentifiersB(-1,index);
+ }
+
+ algo->processCollision(&compoundWrap,m_otherObjWrap,m_dispatchInfo,m_resultOut);
+
+#if 0
+ if (m_dispatchInfo.m_debugDraw && (m_dispatchInfo.m_debugDraw->getDebugMode() & btIDebugDraw::DBG_DrawAabb))
+ {
+ btVector3 worldAabbMin,worldAabbMax;
+ m_dispatchInfo.m_debugDraw->drawAabb(aabbMin0,aabbMax0,btVector3(1,1,1));
+ m_dispatchInfo.m_debugDraw->drawAabb(aabbMin1,aabbMax1,btVector3(1,1,1));
+ }
+#endif
+
+ if (m_resultOut->getBody0Internal() == m_compoundColObjWrap->getCollisionObject())
+ {
+ m_resultOut->setBody0Wrap(tmpWrap);
+ } else
+ {
+ m_resultOut->setBody1Wrap(tmpWrap);
+ }
+
+ }
+ }
+ void Process(const btDbvtNode* leaf)
+ {
+ int index = leaf->dataAsInt;
+
+ const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(m_compoundColObjWrap->getCollisionShape());
+ const btCollisionShape* childShape = compoundShape->getChildShape(index);
+
+#if 0
+ if (m_dispatchInfo.m_debugDraw && (m_dispatchInfo.m_debugDraw->getDebugMode() & btIDebugDraw::DBG_DrawAabb))
+ {
+ btVector3 worldAabbMin,worldAabbMax;
+ btTransform orgTrans = m_compoundColObjWrap->getWorldTransform();
+ btTransformAabb(leaf->volume.Mins(),leaf->volume.Maxs(),0.,orgTrans,worldAabbMin,worldAabbMax);
+ m_dispatchInfo.m_debugDraw->drawAabb(worldAabbMin,worldAabbMax,btVector3(1,0,0));
+ }
+#endif
+
+ ProcessChildShape(childShape,index);
+
+ }
+};
+
+
+
+
+
+
+void btCompoundCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+ const btCollisionObjectWrapper* colObjWrap = m_isSwapped? body1Wrap : body0Wrap;
+ const btCollisionObjectWrapper* otherObjWrap = m_isSwapped? body0Wrap : body1Wrap;
+
+ btAssert (colObjWrap->getCollisionShape()->isCompound());
+ const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(colObjWrap->getCollisionShape());
+
+ ///btCompoundShape might have changed:
+ ////make sure the internal child collision algorithm caches are still valid
+ if (compoundShape->getUpdateRevision() != m_compoundShapeRevision)
+ {
+ ///clear and update all
+ removeChildAlgorithms();
+
+ preallocateChildAlgorithms(body0Wrap,body1Wrap);
+ m_compoundShapeRevision = compoundShape->getUpdateRevision();
+ }
+
+ if (m_childCollisionAlgorithms.size()==0)
+ return;
+
+ const btDbvt* tree = compoundShape->getDynamicAabbTree();
+ //use a dynamic aabb tree to cull potential child-overlaps
+ btCompoundLeafCallback callback(colObjWrap,otherObjWrap,m_dispatcher,dispatchInfo,resultOut,&m_childCollisionAlgorithms[0],m_sharedManifold);
+
+ ///we need to refresh all contact manifolds
+ ///note that we should actually recursively traverse all children, btCompoundShape can nested more then 1 level deep
+ ///so we should add a 'refreshManifolds' in the btCollisionAlgorithm
+ {
+ int i;
+ manifoldArray.resize(0);
+ for (i=0;i<m_childCollisionAlgorithms.size();i++)
+ {
+ if (m_childCollisionAlgorithms[i])
+ {
+ m_childCollisionAlgorithms[i]->getAllContactManifolds(manifoldArray);
+ for (int m=0;m<manifoldArray.size();m++)
+ {
+ if (manifoldArray[m]->getNumContacts())
+ {
+ resultOut->setPersistentManifold(manifoldArray[m]);
+ resultOut->refreshContactPoints();
+ resultOut->setPersistentManifold(0);//??necessary?
+ }
+ }
+ manifoldArray.resize(0);
+ }
+ }
+ }
+
+ if (tree)
+ {
+
+ btVector3 localAabbMin,localAabbMax;
+ btTransform otherInCompoundSpace;
+ otherInCompoundSpace = colObjWrap->getWorldTransform().inverse() * otherObjWrap->getWorldTransform();
+ otherObjWrap->getCollisionShape()->getAabb(otherInCompoundSpace,localAabbMin,localAabbMax);
+ btVector3 extraExtends(resultOut->m_closestPointDistanceThreshold, resultOut->m_closestPointDistanceThreshold, resultOut->m_closestPointDistanceThreshold);
+ localAabbMin -= extraExtends;
+ localAabbMax += extraExtends;
+
+ const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax);
+ //process all children, that overlap with the given AABB bounds
+ tree->collideTVNoStackAlloc(tree->m_root,bounds,stack2,callback);
+
+ } else
+ {
+ //iterate over all children, perform an AABB check inside ProcessChildShape
+ int numChildren = m_childCollisionAlgorithms.size();
+ int i;
+ for (i=0;i<numChildren;i++)
+ {
+ callback.ProcessChildShape(compoundShape->getChildShape(i),i);
+ }
+ }
+
+ {
+ //iterate over all children, perform an AABB check inside ProcessChildShape
+ int numChildren = m_childCollisionAlgorithms.size();
+ int i;
+ manifoldArray.resize(0);
+ const btCollisionShape* childShape = 0;
+ btTransform orgTrans;
+
+ btTransform newChildWorldTrans;
+ btVector3 aabbMin0,aabbMax0,aabbMin1,aabbMax1;
+
+ for (i=0;i<numChildren;i++)
+ {
+ if (m_childCollisionAlgorithms[i])
+ {
+ childShape = compoundShape->getChildShape(i);
+ //if not longer overlapping, remove the algorithm
+ orgTrans = colObjWrap->getWorldTransform();
+
+ const btTransform& childTrans = compoundShape->getChildTransform(i);
+ newChildWorldTrans = orgTrans*childTrans ;
+
+ //perform an AABB check first
+ childShape->getAabb(newChildWorldTrans,aabbMin0,aabbMax0);
+ otherObjWrap->getCollisionShape()->getAabb(otherObjWrap->getWorldTransform(),aabbMin1,aabbMax1);
+
+ if (!TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1))
+ {
+ m_childCollisionAlgorithms[i]->~btCollisionAlgorithm();
+ m_dispatcher->freeCollisionAlgorithm(m_childCollisionAlgorithms[i]);
+ m_childCollisionAlgorithms[i] = 0;
+ }
+ }
+ }
+ }
+}
+
+btScalar btCompoundCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+ btAssert(0);
+ //needs to be fixed, using btCollisionObjectWrapper and NOT modifying internal data structures
+ btCollisionObject* colObj = m_isSwapped? body1 : body0;
+ btCollisionObject* otherObj = m_isSwapped? body0 : body1;
+
+ btAssert (colObj->getCollisionShape()->isCompound());
+
+ btCompoundShape* compoundShape = static_cast<btCompoundShape*>(colObj->getCollisionShape());
+
+ //We will use the OptimizedBVH, AABB tree to cull potential child-overlaps
+ //If both proxies are Compound, we will deal with that directly, by performing sequential/parallel tree traversals
+ //given Proxy0 and Proxy1, if both have a tree, Tree0 and Tree1, this means:
+ //determine overlapping nodes of Proxy1 using Proxy0 AABB against Tree1
+ //then use each overlapping node AABB against Tree0
+ //and vise versa.
+
+ btScalar hitFraction = btScalar(1.);
+
+ int numChildren = m_childCollisionAlgorithms.size();
+ int i;
+ btTransform orgTrans;
+ btScalar frac;
+ for (i=0;i<numChildren;i++)
+ {
+ //btCollisionShape* childShape = compoundShape->getChildShape(i);
+
+ //backup
+ orgTrans = colObj->getWorldTransform();
+
+ const btTransform& childTrans = compoundShape->getChildTransform(i);
+ //btTransform newChildWorldTrans = orgTrans*childTrans ;
+ colObj->setWorldTransform( orgTrans*childTrans );
+
+ //btCollisionShape* tmpShape = colObj->getCollisionShape();
+ //colObj->internalSetTemporaryCollisionShape( childShape );
+ frac = m_childCollisionAlgorithms[i]->calculateTimeOfImpact(colObj,otherObj,dispatchInfo,resultOut);
+ if (frac<hitFraction)
+ {
+ hitFraction = frac;
+ }
+ //revert back
+ //colObj->internalSetTemporaryCollisionShape( tmpShape);
+ colObj->setWorldTransform( orgTrans);
+ }
+ return hitFraction;
+
+}
+
+
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h
new file mode 100644
index 0000000000..d2086fbc02
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h
@@ -0,0 +1,104 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+
+*/
+
+#ifndef BT_COMPOUND_COLLISION_ALGORITHM_H
+#define BT_COMPOUND_COLLISION_ALGORITHM_H
+
+#include "btActivatingCollisionAlgorithm.h"
+#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
+
+#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
+class btDispatcher;
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "btCollisionCreateFunc.h"
+#include "LinearMath/btAlignedObjectArray.h"
+#include "BulletCollision/BroadphaseCollision/btDbvt.h"
+class btDispatcher;
+class btCollisionObject;
+
+class btCollisionShape;
+typedef bool (*btShapePairCallback)(const btCollisionShape* pShape0, const btCollisionShape* pShape1);
+extern btShapePairCallback gCompoundChildShapePairCallback;
+
+/// btCompoundCollisionAlgorithm supports collision between CompoundCollisionShapes and other collision shapes
+class btCompoundCollisionAlgorithm : public btActivatingCollisionAlgorithm
+{
+ btNodeStack stack2;
+ btManifoldArray manifoldArray;
+
+protected:
+ btAlignedObjectArray<btCollisionAlgorithm*> m_childCollisionAlgorithms;
+ bool m_isSwapped;
+
+ class btPersistentManifold* m_sharedManifold;
+ bool m_ownsManifold;
+
+
+ int m_compoundShapeRevision;//to keep track of changes, so that childAlgorithm array can be updated
+
+ void removeChildAlgorithms();
+
+ void preallocateChildAlgorithms(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap);
+
+public:
+
+ btCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped);
+
+ virtual ~btCompoundCollisionAlgorithm();
+
+ btCollisionAlgorithm* getChildAlgorithm (int n) const
+ {
+ return m_childCollisionAlgorithms[n];
+ }
+
+
+ virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+ btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+ virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
+ {
+ int i;
+ for (i=0;i<m_childCollisionAlgorithms.size();i++)
+ {
+ if (m_childCollisionAlgorithms[i])
+ m_childCollisionAlgorithms[i]->getAllContactManifolds(manifoldArray);
+ }
+ }
+
+
+ struct CreateFunc :public btCollisionAlgorithmCreateFunc
+ {
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
+ {
+ void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btCompoundCollisionAlgorithm));
+ return new(mem) btCompoundCollisionAlgorithm(ci,body0Wrap,body1Wrap,false);
+ }
+ };
+
+ struct SwappedCreateFunc :public btCollisionAlgorithmCreateFunc
+ {
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
+ {
+ void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btCompoundCollisionAlgorithm));
+ return new(mem) btCompoundCollisionAlgorithm(ci,body0Wrap,body1Wrap,true);
+ }
+ };
+
+};
+
+#endif //BT_COMPOUND_COLLISION_ALGORITHM_H
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.cpp b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.cpp
new file mode 100644
index 0000000000..d4a1aa78e4
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.cpp
@@ -0,0 +1,456 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2013 Erwin Coumans 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 "btCompoundCompoundCollisionAlgorithm.h"
+#include "LinearMath/btQuickprof.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/CollisionShapes/btCompoundShape.h"
+#include "BulletCollision/BroadphaseCollision/btDbvt.h"
+#include "LinearMath/btIDebugDraw.h"
+#include "LinearMath/btAabbUtil2.h"
+#include "BulletCollision/CollisionDispatch/btManifoldResult.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
+
+//USE_LOCAL_STACK will avoid most (often all) dynamic memory allocations due to resizing in processCollision and MycollideTT
+#define USE_LOCAL_STACK 1
+
+btShapePairCallback gCompoundCompoundChildShapePairCallback = 0;
+
+btCompoundCompoundCollisionAlgorithm::btCompoundCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped)
+:btCompoundCollisionAlgorithm(ci,body0Wrap,body1Wrap,isSwapped)
+{
+
+ void* ptr = btAlignedAlloc(sizeof(btHashedSimplePairCache),16);
+ m_childCollisionAlgorithmCache= new(ptr) btHashedSimplePairCache();
+
+ const btCollisionObjectWrapper* col0ObjWrap = body0Wrap;
+ btAssert (col0ObjWrap->getCollisionShape()->isCompound());
+
+ const btCollisionObjectWrapper* col1ObjWrap = body1Wrap;
+ btAssert (col1ObjWrap->getCollisionShape()->isCompound());
+
+ const btCompoundShape* compoundShape0 = static_cast<const btCompoundShape*>(col0ObjWrap->getCollisionShape());
+ m_compoundShapeRevision0 = compoundShape0->getUpdateRevision();
+
+ const btCompoundShape* compoundShape1 = static_cast<const btCompoundShape*>(col1ObjWrap->getCollisionShape());
+ m_compoundShapeRevision1 = compoundShape1->getUpdateRevision();
+
+
+}
+
+
+btCompoundCompoundCollisionAlgorithm::~btCompoundCompoundCollisionAlgorithm()
+{
+ removeChildAlgorithms();
+ m_childCollisionAlgorithmCache->~btHashedSimplePairCache();
+ btAlignedFree(m_childCollisionAlgorithmCache);
+}
+
+void btCompoundCompoundCollisionAlgorithm::getAllContactManifolds(btManifoldArray& manifoldArray)
+{
+ int i;
+ btSimplePairArray& pairs = m_childCollisionAlgorithmCache->getOverlappingPairArray();
+ for (i=0;i<pairs.size();i++)
+ {
+ if (pairs[i].m_userPointer)
+ {
+
+ ((btCollisionAlgorithm*)pairs[i].m_userPointer)->getAllContactManifolds(manifoldArray);
+ }
+ }
+}
+
+
+void btCompoundCompoundCollisionAlgorithm::removeChildAlgorithms()
+{
+ btSimplePairArray& pairs = m_childCollisionAlgorithmCache->getOverlappingPairArray();
+
+ int numChildren = pairs.size();
+ int i;
+ for (i=0;i<numChildren;i++)
+ {
+ if (pairs[i].m_userPointer)
+ {
+ btCollisionAlgorithm* algo = (btCollisionAlgorithm*) pairs[i].m_userPointer;
+ algo->~btCollisionAlgorithm();
+ m_dispatcher->freeCollisionAlgorithm(algo);
+ }
+ }
+ m_childCollisionAlgorithmCache->removeAllPairs();
+}
+
+struct btCompoundCompoundLeafCallback : btDbvt::ICollide
+{
+ int m_numOverlapPairs;
+
+
+ const btCollisionObjectWrapper* m_compound0ColObjWrap;
+ const btCollisionObjectWrapper* m_compound1ColObjWrap;
+ btDispatcher* m_dispatcher;
+ const btDispatcherInfo& m_dispatchInfo;
+ btManifoldResult* m_resultOut;
+
+
+ class btHashedSimplePairCache* m_childCollisionAlgorithmCache;
+
+ btPersistentManifold* m_sharedManifold;
+
+ btCompoundCompoundLeafCallback (const btCollisionObjectWrapper* compound1ObjWrap,
+ const btCollisionObjectWrapper* compound0ObjWrap,
+ btDispatcher* dispatcher,
+ const btDispatcherInfo& dispatchInfo,
+ btManifoldResult* resultOut,
+ btHashedSimplePairCache* childAlgorithmsCache,
+ btPersistentManifold* sharedManifold)
+ :m_numOverlapPairs(0),m_compound0ColObjWrap(compound1ObjWrap),m_compound1ColObjWrap(compound0ObjWrap),m_dispatcher(dispatcher),m_dispatchInfo(dispatchInfo),m_resultOut(resultOut),
+ m_childCollisionAlgorithmCache(childAlgorithmsCache),
+ m_sharedManifold(sharedManifold)
+ {
+
+ }
+
+
+
+
+ void Process(const btDbvtNode* leaf0,const btDbvtNode* leaf1)
+ {
+ BT_PROFILE("btCompoundCompoundLeafCallback::Process");
+ m_numOverlapPairs++;
+
+
+ int childIndex0 = leaf0->dataAsInt;
+ int childIndex1 = leaf1->dataAsInt;
+
+
+ btAssert(childIndex0>=0);
+ btAssert(childIndex1>=0);
+
+
+ const btCompoundShape* compoundShape0 = static_cast<const btCompoundShape*>(m_compound0ColObjWrap->getCollisionShape());
+ btAssert(childIndex0<compoundShape0->getNumChildShapes());
+
+ const btCompoundShape* compoundShape1 = static_cast<const btCompoundShape*>(m_compound1ColObjWrap->getCollisionShape());
+ btAssert(childIndex1<compoundShape1->getNumChildShapes());
+
+ const btCollisionShape* childShape0 = compoundShape0->getChildShape(childIndex0);
+ const btCollisionShape* childShape1 = compoundShape1->getChildShape(childIndex1);
+
+ //backup
+ btTransform orgTrans0 = m_compound0ColObjWrap->getWorldTransform();
+ const btTransform& childTrans0 = compoundShape0->getChildTransform(childIndex0);
+ btTransform newChildWorldTrans0 = orgTrans0*childTrans0 ;
+
+ btTransform orgTrans1 = m_compound1ColObjWrap->getWorldTransform();
+ const btTransform& childTrans1 = compoundShape1->getChildTransform(childIndex1);
+ btTransform newChildWorldTrans1 = orgTrans1*childTrans1 ;
+
+
+ //perform an AABB check first
+ btVector3 aabbMin0,aabbMax0,aabbMin1,aabbMax1;
+ childShape0->getAabb(newChildWorldTrans0,aabbMin0,aabbMax0);
+ childShape1->getAabb(newChildWorldTrans1,aabbMin1,aabbMax1);
+
+ btVector3 thresholdVec(m_resultOut->m_closestPointDistanceThreshold, m_resultOut->m_closestPointDistanceThreshold, m_resultOut->m_closestPointDistanceThreshold);
+
+ aabbMin0 -= thresholdVec;
+ aabbMax0 += thresholdVec;
+
+ if (gCompoundCompoundChildShapePairCallback)
+ {
+ if (!gCompoundCompoundChildShapePairCallback(childShape0,childShape1))
+ return;
+ }
+
+ if (TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1))
+ {
+ btCollisionObjectWrapper compoundWrap0(this->m_compound0ColObjWrap,childShape0, m_compound0ColObjWrap->getCollisionObject(),newChildWorldTrans0,-1,childIndex0);
+ btCollisionObjectWrapper compoundWrap1(this->m_compound1ColObjWrap,childShape1,m_compound1ColObjWrap->getCollisionObject(),newChildWorldTrans1,-1,childIndex1);
+
+
+ btSimplePair* pair = m_childCollisionAlgorithmCache->findPair(childIndex0,childIndex1);
+
+ btCollisionAlgorithm* colAlgo = 0;
+ if (m_resultOut->m_closestPointDistanceThreshold > 0)
+ {
+ colAlgo = m_dispatcher->findAlgorithm(&compoundWrap0, &compoundWrap1, 0, BT_CLOSEST_POINT_ALGORITHMS);
+ }
+ else
+ {
+ if (pair)
+ {
+ colAlgo = (btCollisionAlgorithm*)pair->m_userPointer;
+
+ }
+ else
+ {
+ colAlgo = m_dispatcher->findAlgorithm(&compoundWrap0, &compoundWrap1, m_sharedManifold, BT_CONTACT_POINT_ALGORITHMS);
+ pair = m_childCollisionAlgorithmCache->addOverlappingPair(childIndex0, childIndex1);
+ btAssert(pair);
+ pair->m_userPointer = colAlgo;
+ }
+ }
+
+ btAssert(colAlgo);
+
+ const btCollisionObjectWrapper* tmpWrap0 = 0;
+ const btCollisionObjectWrapper* tmpWrap1 = 0;
+
+ tmpWrap0 = m_resultOut->getBody0Wrap();
+ tmpWrap1 = m_resultOut->getBody1Wrap();
+
+ m_resultOut->setBody0Wrap(&compoundWrap0);
+ m_resultOut->setBody1Wrap(&compoundWrap1);
+
+ m_resultOut->setShapeIdentifiersA(-1,childIndex0);
+ m_resultOut->setShapeIdentifiersB(-1,childIndex1);
+
+
+ colAlgo->processCollision(&compoundWrap0,&compoundWrap1,m_dispatchInfo,m_resultOut);
+
+ m_resultOut->setBody0Wrap(tmpWrap0);
+ m_resultOut->setBody1Wrap(tmpWrap1);
+
+
+
+ }
+ }
+};
+
+
+static DBVT_INLINE bool MyIntersect( const btDbvtAabbMm& a,
+ const btDbvtAabbMm& b, const btTransform& xform, btScalar distanceThreshold)
+{
+ btVector3 newmin,newmax;
+ btTransformAabb(b.Mins(),b.Maxs(),0.f,xform,newmin,newmax);
+ newmin -= btVector3(distanceThreshold, distanceThreshold, distanceThreshold);
+ newmax += btVector3(distanceThreshold, distanceThreshold, distanceThreshold);
+ btDbvtAabbMm newb = btDbvtAabbMm::FromMM(newmin,newmax);
+ return Intersect(a,newb);
+}
+
+
+static inline void MycollideTT( const btDbvtNode* root0,
+ const btDbvtNode* root1,
+ const btTransform& xform,
+ btCompoundCompoundLeafCallback* callback, btScalar distanceThreshold)
+{
+
+ if(root0&&root1)
+ {
+ int depth=1;
+ int treshold=btDbvt::DOUBLE_STACKSIZE-4;
+ btAlignedObjectArray<btDbvt::sStkNN> stkStack;
+#ifdef USE_LOCAL_STACK
+ ATTRIBUTE_ALIGNED16(btDbvt::sStkNN localStack[btDbvt::DOUBLE_STACKSIZE]);
+ stkStack.initializeFromBuffer(&localStack,btDbvt::DOUBLE_STACKSIZE,btDbvt::DOUBLE_STACKSIZE);
+#else
+ stkStack.resize(btDbvt::DOUBLE_STACKSIZE);
+#endif
+ stkStack[0]=btDbvt::sStkNN(root0,root1);
+ do {
+ btDbvt::sStkNN p=stkStack[--depth];
+ if(MyIntersect(p.a->volume,p.b->volume,xform, distanceThreshold))
+ {
+ if(depth>treshold)
+ {
+ stkStack.resize(stkStack.size()*2);
+ treshold=stkStack.size()-4;
+ }
+ if(p.a->isinternal())
+ {
+ if(p.b->isinternal())
+ {
+ stkStack[depth++]=btDbvt::sStkNN(p.a->childs[0],p.b->childs[0]);
+ stkStack[depth++]=btDbvt::sStkNN(p.a->childs[1],p.b->childs[0]);
+ stkStack[depth++]=btDbvt::sStkNN(p.a->childs[0],p.b->childs[1]);
+ stkStack[depth++]=btDbvt::sStkNN(p.a->childs[1],p.b->childs[1]);
+ }
+ else
+ {
+ stkStack[depth++]=btDbvt::sStkNN(p.a->childs[0],p.b);
+ stkStack[depth++]=btDbvt::sStkNN(p.a->childs[1],p.b);
+ }
+ }
+ else
+ {
+ if(p.b->isinternal())
+ {
+ stkStack[depth++]=btDbvt::sStkNN(p.a,p.b->childs[0]);
+ stkStack[depth++]=btDbvt::sStkNN(p.a,p.b->childs[1]);
+ }
+ else
+ {
+ callback->Process(p.a,p.b);
+ }
+ }
+ }
+ } while(depth);
+ }
+}
+
+void btCompoundCompoundCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+
+ const btCollisionObjectWrapper* col0ObjWrap = body0Wrap;
+ const btCollisionObjectWrapper* col1ObjWrap= body1Wrap;
+
+ btAssert (col0ObjWrap->getCollisionShape()->isCompound());
+ btAssert (col1ObjWrap->getCollisionShape()->isCompound());
+ const btCompoundShape* compoundShape0 = static_cast<const btCompoundShape*>(col0ObjWrap->getCollisionShape());
+ const btCompoundShape* compoundShape1 = static_cast<const btCompoundShape*>(col1ObjWrap->getCollisionShape());
+
+ const btDbvt* tree0 = compoundShape0->getDynamicAabbTree();
+ const btDbvt* tree1 = compoundShape1->getDynamicAabbTree();
+ if (!tree0 || !tree1)
+ {
+ return btCompoundCollisionAlgorithm::processCollision(body0Wrap,body1Wrap,dispatchInfo,resultOut);
+ }
+ ///btCompoundShape might have changed:
+ ////make sure the internal child collision algorithm caches are still valid
+ if ((compoundShape0->getUpdateRevision() != m_compoundShapeRevision0) || (compoundShape1->getUpdateRevision() != m_compoundShapeRevision1))
+ {
+ ///clear all
+ removeChildAlgorithms();
+ m_compoundShapeRevision0 = compoundShape0->getUpdateRevision();
+ m_compoundShapeRevision1 = compoundShape1->getUpdateRevision();
+
+ }
+
+
+ ///we need to refresh all contact manifolds
+ ///note that we should actually recursively traverse all children, btCompoundShape can nested more then 1 level deep
+ ///so we should add a 'refreshManifolds' in the btCollisionAlgorithm
+ {
+ int i;
+ btManifoldArray manifoldArray;
+#ifdef USE_LOCAL_STACK
+ btPersistentManifold localManifolds[4];
+ manifoldArray.initializeFromBuffer(&localManifolds,0,4);
+#endif
+ btSimplePairArray& pairs = m_childCollisionAlgorithmCache->getOverlappingPairArray();
+ for (i=0;i<pairs.size();i++)
+ {
+ if (pairs[i].m_userPointer)
+ {
+ btCollisionAlgorithm* algo = (btCollisionAlgorithm*) pairs[i].m_userPointer;
+ algo->getAllContactManifolds(manifoldArray);
+ for (int m=0;m<manifoldArray.size();m++)
+ {
+ if (manifoldArray[m]->getNumContacts())
+ {
+ resultOut->setPersistentManifold(manifoldArray[m]);
+ resultOut->refreshContactPoints();
+ resultOut->setPersistentManifold(0);
+ }
+ }
+ manifoldArray.resize(0);
+ }
+ }
+ }
+
+
+
+
+ btCompoundCompoundLeafCallback callback(col0ObjWrap,col1ObjWrap,this->m_dispatcher,dispatchInfo,resultOut,this->m_childCollisionAlgorithmCache,m_sharedManifold);
+
+
+ const btTransform xform=col0ObjWrap->getWorldTransform().inverse()*col1ObjWrap->getWorldTransform();
+ MycollideTT(tree0->m_root,tree1->m_root,xform,&callback, resultOut->m_closestPointDistanceThreshold);
+
+ //printf("#compound-compound child/leaf overlap =%d \r",callback.m_numOverlapPairs);
+
+ //remove non-overlapping child pairs
+
+ {
+ btAssert(m_removePairs.size()==0);
+
+ //iterate over all children, perform an AABB check inside ProcessChildShape
+ btSimplePairArray& pairs = m_childCollisionAlgorithmCache->getOverlappingPairArray();
+
+ int i;
+ btManifoldArray manifoldArray;
+
+
+
+
+
+ btVector3 aabbMin0,aabbMax0,aabbMin1,aabbMax1;
+
+ for (i=0;i<pairs.size();i++)
+ {
+ if (pairs[i].m_userPointer)
+ {
+ btCollisionAlgorithm* algo = (btCollisionAlgorithm*)pairs[i].m_userPointer;
+
+ {
+ btTransform orgTrans0;
+ const btCollisionShape* childShape0 = 0;
+
+ btTransform newChildWorldTrans0;
+ btTransform orgInterpolationTrans0;
+ childShape0 = compoundShape0->getChildShape(pairs[i].m_indexA);
+ orgTrans0 = col0ObjWrap->getWorldTransform();
+ orgInterpolationTrans0 = col0ObjWrap->getWorldTransform();
+ const btTransform& childTrans0 = compoundShape0->getChildTransform(pairs[i].m_indexA);
+ newChildWorldTrans0 = orgTrans0*childTrans0 ;
+ childShape0->getAabb(newChildWorldTrans0,aabbMin0,aabbMax0);
+ }
+ btVector3 thresholdVec(resultOut->m_closestPointDistanceThreshold, resultOut->m_closestPointDistanceThreshold, resultOut->m_closestPointDistanceThreshold);
+ aabbMin0 -= thresholdVec;
+ aabbMax0 += thresholdVec;
+ {
+ btTransform orgInterpolationTrans1;
+ const btCollisionShape* childShape1 = 0;
+ btTransform orgTrans1;
+ btTransform newChildWorldTrans1;
+
+ childShape1 = compoundShape1->getChildShape(pairs[i].m_indexB);
+ orgTrans1 = col1ObjWrap->getWorldTransform();
+ orgInterpolationTrans1 = col1ObjWrap->getWorldTransform();
+ const btTransform& childTrans1 = compoundShape1->getChildTransform(pairs[i].m_indexB);
+ newChildWorldTrans1 = orgTrans1*childTrans1 ;
+ childShape1->getAabb(newChildWorldTrans1,aabbMin1,aabbMax1);
+ }
+
+ aabbMin1 -= thresholdVec;
+ aabbMax1 += thresholdVec;
+
+ if (!TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1))
+ {
+ algo->~btCollisionAlgorithm();
+ m_dispatcher->freeCollisionAlgorithm(algo);
+ m_removePairs.push_back(btSimplePair(pairs[i].m_indexA,pairs[i].m_indexB));
+ }
+ }
+ }
+ for (int i=0;i<m_removePairs.size();i++)
+ {
+ m_childCollisionAlgorithmCache->removeOverlappingPair(m_removePairs[i].m_indexA,m_removePairs[i].m_indexB);
+ }
+ m_removePairs.clear();
+ }
+
+}
+
+btScalar btCompoundCompoundCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+ btAssert(0);
+ return 0.f;
+
+}
+
+
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.h b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.h
new file mode 100644
index 0000000000..f29f7a709a
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.h
@@ -0,0 +1,87 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2013 Erwin Coumans 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_COMPOUND_COMPOUND_COLLISION_ALGORITHM_H
+#define BT_COMPOUND_COMPOUND_COLLISION_ALGORITHM_H
+
+#include "btCompoundCollisionAlgorithm.h"
+
+#include "BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h"
+#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
+
+#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
+class btDispatcher;
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
+#include "LinearMath/btAlignedObjectArray.h"
+#include "BulletCollision/CollisionDispatch/btHashedSimplePairCache.h"
+class btDispatcher;
+class btCollisionObject;
+
+class btCollisionShape;
+
+/// btCompoundCompoundCollisionAlgorithm supports collision between two btCompoundCollisionShape shapes
+class btCompoundCompoundCollisionAlgorithm : public btCompoundCollisionAlgorithm
+{
+
+ class btHashedSimplePairCache* m_childCollisionAlgorithmCache;
+ btSimplePairArray m_removePairs;
+
+
+ int m_compoundShapeRevision0;//to keep track of changes, so that childAlgorithm array can be updated
+ int m_compoundShapeRevision1;
+
+ void removeChildAlgorithms();
+
+// void preallocateChildAlgorithms(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap);
+
+public:
+
+ btCompoundCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped);
+
+ virtual ~btCompoundCompoundCollisionAlgorithm();
+
+
+
+ virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+ btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+ virtual void getAllContactManifolds(btManifoldArray& manifoldArray);
+
+
+ struct CreateFunc :public btCollisionAlgorithmCreateFunc
+ {
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
+ {
+ void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btCompoundCompoundCollisionAlgorithm));
+ return new(mem) btCompoundCompoundCollisionAlgorithm(ci,body0Wrap,body1Wrap,false);
+ }
+ };
+
+ struct SwappedCreateFunc :public btCollisionAlgorithmCreateFunc
+ {
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
+ {
+ void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btCompoundCompoundCollisionAlgorithm));
+ return new(mem) btCompoundCompoundCollisionAlgorithm(ci,body0Wrap,body1Wrap,true);
+ }
+ };
+
+};
+
+#endif //BT_COMPOUND_COMPOUND_COLLISION_ALGORITHM_H
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp
new file mode 100644
index 0000000000..1cb3d2e7a1
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp
@@ -0,0 +1,242 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btConvex2dConvex2dAlgorithm.h"
+
+//#include <stdio.h>
+#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+#include "BulletCollision/CollisionShapes/btCapsuleShape.h"
+
+
+#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/CollisionShapes/btBoxShape.h"
+#include "BulletCollision/CollisionDispatch/btManifoldResult.h"
+
+#include "BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h"
+#include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h"
+#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h"
+
+
+
+#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"
+
+#include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h"
+
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
+
+btConvex2dConvex2dAlgorithm::CreateFunc::CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver)
+{
+ m_simplexSolver = simplexSolver;
+ m_pdSolver = pdSolver;
+}
+
+btConvex2dConvex2dAlgorithm::CreateFunc::~CreateFunc()
+{
+}
+
+btConvex2dConvex2dAlgorithm::btConvex2dConvex2dAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver,int /* numPerturbationIterations */, int /* minimumPointsPerturbationThreshold */)
+: btActivatingCollisionAlgorithm(ci,body0Wrap,body1Wrap),
+m_simplexSolver(simplexSolver),
+m_pdSolver(pdSolver),
+m_ownManifold (false),
+m_manifoldPtr(mf),
+m_lowLevelOfDetail(false)
+{
+ (void)body0Wrap;
+ (void)body1Wrap;
+}
+
+
+
+
+btConvex2dConvex2dAlgorithm::~btConvex2dConvex2dAlgorithm()
+{
+ if (m_ownManifold)
+ {
+ if (m_manifoldPtr)
+ m_dispatcher->releaseManifold(m_manifoldPtr);
+ }
+}
+
+void btConvex2dConvex2dAlgorithm ::setLowLevelOfDetail(bool useLowLevel)
+{
+ m_lowLevelOfDetail = useLowLevel;
+}
+
+
+
+extern btScalar gContactBreakingThreshold;
+
+
+//
+// Convex-Convex collision algorithm
+//
+void btConvex2dConvex2dAlgorithm ::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+
+ if (!m_manifoldPtr)
+ {
+ //swapped?
+ m_manifoldPtr = m_dispatcher->getNewManifold(body0Wrap->getCollisionObject(),body1Wrap->getCollisionObject());
+ m_ownManifold = true;
+ }
+ resultOut->setPersistentManifold(m_manifoldPtr);
+
+ //comment-out next line to test multi-contact generation
+ //resultOut->getPersistentManifold()->clearManifold();
+
+
+ const btConvexShape* min0 = static_cast<const btConvexShape*>(body0Wrap->getCollisionShape());
+ const btConvexShape* min1 = static_cast<const btConvexShape*>(body1Wrap->getCollisionShape());
+
+ btVector3 normalOnB;
+ btVector3 pointOnBWorld;
+
+ {
+
+
+ btGjkPairDetector::ClosestPointInput input;
+
+ btGjkPairDetector gjkPairDetector(min0,min1,m_simplexSolver,m_pdSolver);
+ //TODO: if (dispatchInfo.m_useContinuous)
+ gjkPairDetector.setMinkowskiA(min0);
+ gjkPairDetector.setMinkowskiB(min1);
+
+ {
+ input.m_maximumDistanceSquared = min0->getMargin() + min1->getMargin() + m_manifoldPtr->getContactBreakingThreshold();
+ input.m_maximumDistanceSquared*= input.m_maximumDistanceSquared;
+ }
+
+ input.m_transformA = body0Wrap->getWorldTransform();
+ input.m_transformB = body1Wrap->getWorldTransform();
+
+ gjkPairDetector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw);
+
+ btVector3 v0,v1;
+ btVector3 sepNormalWorldSpace;
+
+ }
+
+ if (m_ownManifold)
+ {
+ resultOut->refreshContactPoints();
+ }
+
+}
+
+
+
+
+btScalar btConvex2dConvex2dAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+ (void)resultOut;
+ (void)dispatchInfo;
+ ///Rather then checking ALL pairs, only calculate TOI when motion exceeds threshold
+
+ ///Linear motion for one of objects needs to exceed m_ccdSquareMotionThreshold
+ ///col0->m_worldTransform,
+ btScalar resultFraction = btScalar(1.);
+
+
+ btScalar squareMot0 = (col0->getInterpolationWorldTransform().getOrigin() - col0->getWorldTransform().getOrigin()).length2();
+ btScalar squareMot1 = (col1->getInterpolationWorldTransform().getOrigin() - col1->getWorldTransform().getOrigin()).length2();
+
+ if (squareMot0 < col0->getCcdSquareMotionThreshold() &&
+ squareMot1 < col1->getCcdSquareMotionThreshold())
+ return resultFraction;
+
+
+ //An adhoc way of testing the Continuous Collision Detection algorithms
+ //One object is approximated as a sphere, to simplify things
+ //Starting in penetration should report no time of impact
+ //For proper CCD, better accuracy and handling of 'allowed' penetration should be added
+ //also the mainloop of the physics should have a kind of toi queue (something like Brian Mirtich's application of Timewarp for Rigidbodies)
+
+
+ /// Convex0 against sphere for Convex1
+ {
+ btConvexShape* convex0 = static_cast<btConvexShape*>(col0->getCollisionShape());
+
+ btSphereShape sphere1(col1->getCcdSweptSphereRadius()); //todo: allow non-zero sphere sizes, for better approximation
+ btConvexCast::CastResult result;
+ btVoronoiSimplexSolver voronoiSimplex;
+ //SubsimplexConvexCast ccd0(&sphere,min0,&voronoiSimplex);
+ ///Simplification, one object is simplified as a sphere
+ btGjkConvexCast ccd1( convex0 ,&sphere1,&voronoiSimplex);
+ //ContinuousConvexCollision ccd(min0,min1,&voronoiSimplex,0);
+ if (ccd1.calcTimeOfImpact(col0->getWorldTransform(),col0->getInterpolationWorldTransform(),
+ col1->getWorldTransform(),col1->getInterpolationWorldTransform(),result))
+ {
+
+ //store result.m_fraction in both bodies
+
+ if (col0->getHitFraction()> result.m_fraction)
+ col0->setHitFraction( result.m_fraction );
+
+ if (col1->getHitFraction() > result.m_fraction)
+ col1->setHitFraction( result.m_fraction);
+
+ if (resultFraction > result.m_fraction)
+ resultFraction = result.m_fraction;
+
+ }
+
+
+
+
+ }
+
+ /// Sphere (for convex0) against Convex1
+ {
+ btConvexShape* convex1 = static_cast<btConvexShape*>(col1->getCollisionShape());
+
+ btSphereShape sphere0(col0->getCcdSweptSphereRadius()); //todo: allow non-zero sphere sizes, for better approximation
+ btConvexCast::CastResult result;
+ btVoronoiSimplexSolver voronoiSimplex;
+ //SubsimplexConvexCast ccd0(&sphere,min0,&voronoiSimplex);
+ ///Simplification, one object is simplified as a sphere
+ btGjkConvexCast ccd1(&sphere0,convex1,&voronoiSimplex);
+ //ContinuousConvexCollision ccd(min0,min1,&voronoiSimplex,0);
+ if (ccd1.calcTimeOfImpact(col0->getWorldTransform(),col0->getInterpolationWorldTransform(),
+ col1->getWorldTransform(),col1->getInterpolationWorldTransform(),result))
+ {
+
+ //store result.m_fraction in both bodies
+
+ if (col0->getHitFraction() > result.m_fraction)
+ col0->setHitFraction( result.m_fraction);
+
+ if (col1->getHitFraction() > result.m_fraction)
+ col1->setHitFraction( result.m_fraction);
+
+ if (resultFraction > result.m_fraction)
+ resultFraction = result.m_fraction;
+
+ }
+ }
+
+ return resultFraction;
+
+}
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h
new file mode 100644
index 0000000000..24d1336778
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h
@@ -0,0 +1,92 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_CONVEX_2D_CONVEX_2D_ALGORITHM_H
+#define BT_CONVEX_2D_CONVEX_2D_ALGORITHM_H
+
+#include "BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h"
+#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
+#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "LinearMath/btTransformUtil.h" //for btConvexSeparatingDistanceUtil
+
+class btConvexPenetrationDepthSolver;
+
+
+///The convex2dConvex2dAlgorithm collision algorithm support 2d collision detection for btConvex2dShape
+///Currently it requires the btMinkowskiPenetrationDepthSolver, it has support for 2d penetration depth computation
+class btConvex2dConvex2dAlgorithm : public btActivatingCollisionAlgorithm
+{
+ btSimplexSolverInterface* m_simplexSolver;
+ btConvexPenetrationDepthSolver* m_pdSolver;
+
+
+ bool m_ownManifold;
+ btPersistentManifold* m_manifoldPtr;
+ bool m_lowLevelOfDetail;
+
+public:
+
+ btConvex2dConvex2dAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap, btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver, int numPerturbationIterations, int minimumPointsPerturbationThreshold);
+
+
+ virtual ~btConvex2dConvex2dAlgorithm();
+
+ virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+ virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+ virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
+ {
+ ///should we use m_ownManifold to avoid adding duplicates?
+ if (m_manifoldPtr && m_ownManifold)
+ manifoldArray.push_back(m_manifoldPtr);
+ }
+
+
+ void setLowLevelOfDetail(bool useLowLevel);
+
+
+ const btPersistentManifold* getManifold()
+ {
+ return m_manifoldPtr;
+ }
+
+ struct CreateFunc :public btCollisionAlgorithmCreateFunc
+ {
+
+ btConvexPenetrationDepthSolver* m_pdSolver;
+ btSimplexSolverInterface* m_simplexSolver;
+ int m_numPerturbationIterations;
+ int m_minimumPointsPerturbationThreshold;
+
+ CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver);
+
+ virtual ~CreateFunc();
+
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
+ {
+ void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvex2dConvex2dAlgorithm));
+ return new(mem) btConvex2dConvex2dAlgorithm(ci.m_manifold,ci,body0Wrap,body1Wrap,m_simplexSolver,m_pdSolver,m_numPerturbationIterations,m_minimumPointsPerturbationThreshold);
+ }
+ };
+
+
+};
+
+#endif //BT_CONVEX_2D_CONVEX_2D_ALGORITHM_H
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp
new file mode 100644
index 0000000000..39ff7934d9
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp
@@ -0,0 +1,346 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "btConvexConcaveCollisionAlgorithm.h"
+#include "LinearMath/btQuickprof.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/CollisionShapes/btMultiSphereShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/CollisionShapes/btConcaveShape.h"
+#include "BulletCollision/CollisionDispatch/btManifoldResult.h"
+#include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h"
+#include "BulletCollision/CollisionShapes/btTriangleShape.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"
+#include "LinearMath/btIDebugDraw.h"
+#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
+
+btConvexConcaveCollisionAlgorithm::btConvexConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped)
+: btActivatingCollisionAlgorithm(ci,body0Wrap,body1Wrap),
+m_btConvexTriangleCallback(ci.m_dispatcher1,body0Wrap,body1Wrap,isSwapped),
+m_isSwapped(isSwapped)
+{
+}
+
+btConvexConcaveCollisionAlgorithm::~btConvexConcaveCollisionAlgorithm()
+{
+}
+
+void btConvexConcaveCollisionAlgorithm::getAllContactManifolds(btManifoldArray& manifoldArray)
+{
+ if (m_btConvexTriangleCallback.m_manifoldPtr)
+ {
+ manifoldArray.push_back(m_btConvexTriangleCallback.m_manifoldPtr);
+ }
+}
+
+
+btConvexTriangleCallback::btConvexTriangleCallback(btDispatcher* dispatcher,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped):
+ m_dispatcher(dispatcher),
+ m_dispatchInfoPtr(0)
+{
+ m_convexBodyWrap = isSwapped? body1Wrap:body0Wrap;
+ m_triBodyWrap = isSwapped? body0Wrap:body1Wrap;
+
+ //
+ // create the manifold from the dispatcher 'manifold pool'
+ //
+ m_manifoldPtr = m_dispatcher->getNewManifold(m_convexBodyWrap->getCollisionObject(),m_triBodyWrap->getCollisionObject());
+
+ clearCache();
+}
+
+btConvexTriangleCallback::~btConvexTriangleCallback()
+{
+ clearCache();
+ m_dispatcher->releaseManifold( m_manifoldPtr );
+
+}
+
+
+void btConvexTriangleCallback::clearCache()
+{
+ m_dispatcher->clearManifold(m_manifoldPtr);
+}
+
+
+void btConvexTriangleCallback::processTriangle(btVector3* triangle,int
+partId, int triangleIndex)
+{
+ BT_PROFILE("btConvexTriangleCallback::processTriangle");
+
+ if (!TestTriangleAgainstAabb2(triangle, m_aabbMin, m_aabbMax))
+ {
+ return;
+ }
+
+ //just for debugging purposes
+ //printf("triangle %d",m_triangleCount++);
+
+
+
+ btCollisionAlgorithmConstructionInfo ci;
+ ci.m_dispatcher1 = m_dispatcher;
+
+
+
+#if 0
+
+ ///debug drawing of the overlapping triangles
+ if (m_dispatchInfoPtr && m_dispatchInfoPtr->m_debugDraw && (m_dispatchInfoPtr->m_debugDraw->getDebugMode() &btIDebugDraw::DBG_DrawWireframe ))
+ {
+ const btCollisionObject* ob = const_cast<btCollisionObject*>(m_triBodyWrap->getCollisionObject());
+ btVector3 color(1,1,0);
+ btTransform& tr = ob->getWorldTransform();
+ m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[0]),tr(triangle[1]),color);
+ m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[1]),tr(triangle[2]),color);
+ m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[2]),tr(triangle[0]),color);
+ }
+#endif
+
+ if (m_convexBodyWrap->getCollisionShape()->isConvex())
+ {
+ btTriangleShape tm(triangle[0],triangle[1],triangle[2]);
+ tm.setMargin(m_collisionMarginTriangle);
+
+
+ btCollisionObjectWrapper triObWrap(m_triBodyWrap,&tm,m_triBodyWrap->getCollisionObject(),m_triBodyWrap->getWorldTransform(),partId,triangleIndex);//correct transform?
+ btCollisionAlgorithm* colAlgo = 0;
+
+ if (m_resultOut->m_closestPointDistanceThreshold > 0)
+ {
+ colAlgo = ci.m_dispatcher1->findAlgorithm(m_convexBodyWrap, &triObWrap, 0, BT_CLOSEST_POINT_ALGORITHMS);
+ }
+ else
+ {
+ colAlgo = ci.m_dispatcher1->findAlgorithm(m_convexBodyWrap, &triObWrap, m_manifoldPtr, BT_CONTACT_POINT_ALGORITHMS);
+ }
+ const btCollisionObjectWrapper* tmpWrap = 0;
+
+ if (m_resultOut->getBody0Internal() == m_triBodyWrap->getCollisionObject())
+ {
+ tmpWrap = m_resultOut->getBody0Wrap();
+ m_resultOut->setBody0Wrap(&triObWrap);
+ m_resultOut->setShapeIdentifiersA(partId,triangleIndex);
+ }
+ else
+ {
+ tmpWrap = m_resultOut->getBody1Wrap();
+ m_resultOut->setBody1Wrap(&triObWrap);
+ m_resultOut->setShapeIdentifiersB(partId,triangleIndex);
+ }
+
+ colAlgo->processCollision(m_convexBodyWrap,&triObWrap,*m_dispatchInfoPtr,m_resultOut);
+
+ if (m_resultOut->getBody0Internal() == m_triBodyWrap->getCollisionObject())
+ {
+ m_resultOut->setBody0Wrap(tmpWrap);
+ } else
+ {
+ m_resultOut->setBody1Wrap(tmpWrap);
+ }
+
+
+
+ colAlgo->~btCollisionAlgorithm();
+ ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo);
+ }
+
+}
+
+
+
+void btConvexTriangleCallback::setTimeStepAndCounters(btScalar collisionMarginTriangle,const btDispatcherInfo& dispatchInfo,const btCollisionObjectWrapper* convexBodyWrap, const btCollisionObjectWrapper* triBodyWrap, btManifoldResult* resultOut)
+{
+ m_convexBodyWrap = convexBodyWrap;
+ m_triBodyWrap = triBodyWrap;
+
+ m_dispatchInfoPtr = &dispatchInfo;
+ m_collisionMarginTriangle = collisionMarginTriangle;
+ m_resultOut = resultOut;
+
+ //recalc aabbs
+ btTransform convexInTriangleSpace;
+ convexInTriangleSpace = m_triBodyWrap->getWorldTransform().inverse() * m_convexBodyWrap->getWorldTransform();
+ const btCollisionShape* convexShape = static_cast<const btCollisionShape*>(m_convexBodyWrap->getCollisionShape());
+ //CollisionShape* triangleShape = static_cast<btCollisionShape*>(triBody->m_collisionShape);
+ convexShape->getAabb(convexInTriangleSpace,m_aabbMin,m_aabbMax);
+ btScalar extraMargin = collisionMarginTriangle+ resultOut->m_closestPointDistanceThreshold;
+
+ btVector3 extra(extraMargin,extraMargin,extraMargin);
+
+ m_aabbMax += extra;
+ m_aabbMin -= extra;
+
+}
+
+void btConvexConcaveCollisionAlgorithm::clearCache()
+{
+ m_btConvexTriangleCallback.clearCache();
+
+}
+
+void btConvexConcaveCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+ BT_PROFILE("btConvexConcaveCollisionAlgorithm::processCollision");
+
+ const btCollisionObjectWrapper* convexBodyWrap = m_isSwapped ? body1Wrap : body0Wrap;
+ const btCollisionObjectWrapper* triBodyWrap = m_isSwapped ? body0Wrap : body1Wrap;
+
+ if (triBodyWrap->getCollisionShape()->isConcave())
+ {
+
+
+
+ const btConcaveShape* concaveShape = static_cast<const btConcaveShape*>( triBodyWrap->getCollisionShape());
+
+ if (convexBodyWrap->getCollisionShape()->isConvex())
+ {
+ btScalar collisionMarginTriangle = concaveShape->getMargin();
+
+ resultOut->setPersistentManifold(m_btConvexTriangleCallback.m_manifoldPtr);
+ m_btConvexTriangleCallback.setTimeStepAndCounters(collisionMarginTriangle,dispatchInfo,convexBodyWrap,triBodyWrap,resultOut);
+
+ m_btConvexTriangleCallback.m_manifoldPtr->setBodies(convexBodyWrap->getCollisionObject(),triBodyWrap->getCollisionObject());
+
+ concaveShape->processAllTriangles( &m_btConvexTriangleCallback,m_btConvexTriangleCallback.getAabbMin(),m_btConvexTriangleCallback.getAabbMax());
+
+ resultOut->refreshContactPoints();
+
+ m_btConvexTriangleCallback.clearWrapperData();
+
+ }
+
+ }
+
+}
+
+
+btScalar btConvexConcaveCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+ (void)resultOut;
+ (void)dispatchInfo;
+ btCollisionObject* convexbody = m_isSwapped ? body1 : body0;
+ btCollisionObject* triBody = m_isSwapped ? body0 : body1;
+
+
+ //quick approximation using raycast, todo: hook up to the continuous collision detection (one of the btConvexCast)
+
+ //only perform CCD above a certain threshold, this prevents blocking on the long run
+ //because object in a blocked ccd state (hitfraction<1) get their linear velocity halved each frame...
+ btScalar squareMot0 = (convexbody->getInterpolationWorldTransform().getOrigin() - convexbody->getWorldTransform().getOrigin()).length2();
+ if (squareMot0 < convexbody->getCcdSquareMotionThreshold())
+ {
+ return btScalar(1.);
+ }
+
+ //const btVector3& from = convexbody->m_worldTransform.getOrigin();
+ //btVector3 to = convexbody->m_interpolationWorldTransform.getOrigin();
+ //todo: only do if the motion exceeds the 'radius'
+
+ btTransform triInv = triBody->getWorldTransform().inverse();
+ btTransform convexFromLocal = triInv * convexbody->getWorldTransform();
+ btTransform convexToLocal = triInv * convexbody->getInterpolationWorldTransform();
+
+ struct LocalTriangleSphereCastCallback : public btTriangleCallback
+ {
+ btTransform m_ccdSphereFromTrans;
+ btTransform m_ccdSphereToTrans;
+ btTransform m_meshTransform;
+
+ btScalar m_ccdSphereRadius;
+ btScalar m_hitFraction;
+
+
+ LocalTriangleSphereCastCallback(const btTransform& from,const btTransform& to,btScalar ccdSphereRadius,btScalar hitFraction)
+ :m_ccdSphereFromTrans(from),
+ m_ccdSphereToTrans(to),
+ m_ccdSphereRadius(ccdSphereRadius),
+ m_hitFraction(hitFraction)
+ {
+ }
+
+
+ virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
+ {
+ BT_PROFILE("processTriangle");
+ (void)partId;
+ (void)triangleIndex;
+ //do a swept sphere for now
+ btTransform ident;
+ ident.setIdentity();
+ btConvexCast::CastResult castResult;
+ castResult.m_fraction = m_hitFraction;
+ btSphereShape pointShape(m_ccdSphereRadius);
+ btTriangleShape triShape(triangle[0],triangle[1],triangle[2]);
+ btVoronoiSimplexSolver simplexSolver;
+ btSubsimplexConvexCast convexCaster(&pointShape,&triShape,&simplexSolver);
+ //GjkConvexCast convexCaster(&pointShape,convexShape,&simplexSolver);
+ //ContinuousConvexCollision convexCaster(&pointShape,convexShape,&simplexSolver,0);
+ //local space?
+
+ if (convexCaster.calcTimeOfImpact(m_ccdSphereFromTrans,m_ccdSphereToTrans,
+ ident,ident,castResult))
+ {
+ if (m_hitFraction > castResult.m_fraction)
+ m_hitFraction = castResult.m_fraction;
+ }
+
+ }
+
+ };
+
+
+
+
+
+ if (triBody->getCollisionShape()->isConcave())
+ {
+ btVector3 rayAabbMin = convexFromLocal.getOrigin();
+ rayAabbMin.setMin(convexToLocal.getOrigin());
+ btVector3 rayAabbMax = convexFromLocal.getOrigin();
+ rayAabbMax.setMax(convexToLocal.getOrigin());
+ btScalar ccdRadius0 = convexbody->getCcdSweptSphereRadius();
+ rayAabbMin -= btVector3(ccdRadius0,ccdRadius0,ccdRadius0);
+ rayAabbMax += btVector3(ccdRadius0,ccdRadius0,ccdRadius0);
+
+ btScalar curHitFraction = btScalar(1.); //is this available?
+ LocalTriangleSphereCastCallback raycastCallback(convexFromLocal,convexToLocal,
+ convexbody->getCcdSweptSphereRadius(),curHitFraction);
+
+ raycastCallback.m_hitFraction = convexbody->getHitFraction();
+
+ btCollisionObject* concavebody = triBody;
+
+ btConcaveShape* triangleMesh = (btConcaveShape*) concavebody->getCollisionShape();
+
+ if (triangleMesh)
+ {
+ triangleMesh->processAllTriangles(&raycastCallback,rayAabbMin,rayAabbMax);
+ }
+
+
+
+ if (raycastCallback.m_hitFraction < convexbody->getHitFraction())
+ {
+ convexbody->setHitFraction( raycastCallback.m_hitFraction);
+ return raycastCallback.m_hitFraction;
+ }
+ }
+
+ return btScalar(1.);
+
+}
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h
new file mode 100644
index 0000000000..93d842ef50
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h
@@ -0,0 +1,127 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_CONVEX_CONCAVE_COLLISION_ALGORITHM_H
+#define BT_CONVEX_CONCAVE_COLLISION_ALGORITHM_H
+
+#include "btActivatingCollisionAlgorithm.h"
+#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
+#include "BulletCollision/CollisionShapes/btTriangleCallback.h"
+#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
+class btDispatcher;
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "btCollisionCreateFunc.h"
+
+///For each triangle in the concave mesh that overlaps with the AABB of a convex (m_convexProxy), processTriangle is called.
+ATTRIBUTE_ALIGNED16(class) btConvexTriangleCallback : public btTriangleCallback
+{
+
+ btVector3 m_aabbMin;
+ btVector3 m_aabbMax ;
+
+ const btCollisionObjectWrapper* m_convexBodyWrap;
+ const btCollisionObjectWrapper* m_triBodyWrap;
+
+
+
+ btManifoldResult* m_resultOut;
+ btDispatcher* m_dispatcher;
+ const btDispatcherInfo* m_dispatchInfoPtr;
+ btScalar m_collisionMarginTriangle;
+
+public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+int m_triangleCount;
+
+ btPersistentManifold* m_manifoldPtr;
+
+ btConvexTriangleCallback(btDispatcher* dispatcher,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped);
+
+ void setTimeStepAndCounters(btScalar collisionMarginTriangle,const btDispatcherInfo& dispatchInfo,const btCollisionObjectWrapper* convexBodyWrap, const btCollisionObjectWrapper* triBodyWrap, btManifoldResult* resultOut);
+
+ void clearWrapperData()
+ {
+ m_convexBodyWrap = 0;
+ m_triBodyWrap = 0;
+ }
+ virtual ~btConvexTriangleCallback();
+
+ virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex);
+
+ void clearCache();
+
+ SIMD_FORCE_INLINE const btVector3& getAabbMin() const
+ {
+ return m_aabbMin;
+ }
+ SIMD_FORCE_INLINE const btVector3& getAabbMax() const
+ {
+ return m_aabbMax;
+ }
+
+};
+
+
+
+
+/// btConvexConcaveCollisionAlgorithm supports collision between convex shapes and (concave) trianges meshes.
+ATTRIBUTE_ALIGNED16(class) btConvexConcaveCollisionAlgorithm : public btActivatingCollisionAlgorithm
+{
+
+ btConvexTriangleCallback m_btConvexTriangleCallback;
+
+ bool m_isSwapped;
+
+
+
+public:
+
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ btConvexConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped);
+
+ virtual ~btConvexConcaveCollisionAlgorithm();
+
+ virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+ btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+ virtual void getAllContactManifolds(btManifoldArray& manifoldArray);
+
+ void clearCache();
+
+ struct CreateFunc :public btCollisionAlgorithmCreateFunc
+ {
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
+ {
+ void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConcaveCollisionAlgorithm));
+ return new(mem) btConvexConcaveCollisionAlgorithm(ci,body0Wrap,body1Wrap,false);
+ }
+ };
+
+ struct SwappedCreateFunc :public btCollisionAlgorithmCreateFunc
+ {
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
+ {
+ void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConcaveCollisionAlgorithm));
+ return new(mem) btConvexConcaveCollisionAlgorithm(ci,body0Wrap,body1Wrap,true);
+ }
+ };
+
+};
+
+#endif //BT_CONVEX_CONCAVE_COLLISION_ALGORITHM_H
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp
new file mode 100644
index 0000000000..b54bd48932
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp
@@ -0,0 +1,828 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+///Specialized capsule-capsule collision algorithm has been added for Bullet 2.75 release to increase ragdoll performance
+///If you experience problems with capsule-capsule collision, try to define BT_DISABLE_CAPSULE_CAPSULE_COLLIDER and report it in the Bullet forums
+///with reproduction case
+//#define BT_DISABLE_CAPSULE_CAPSULE_COLLIDER 1
+//#define ZERO_MARGIN
+
+#include "btConvexConvexAlgorithm.h"
+
+//#include <stdio.h>
+#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+#include "BulletCollision/CollisionShapes/btCapsuleShape.h"
+#include "BulletCollision/CollisionShapes/btTriangleShape.h"
+
+
+
+#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/CollisionShapes/btBoxShape.h"
+#include "BulletCollision/CollisionDispatch/btManifoldResult.h"
+
+#include "BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h"
+#include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h"
+#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h"
+
+
+
+#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"
+
+#include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h"
+
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
+#include "BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
+
+///////////
+
+
+
+static SIMD_FORCE_INLINE void segmentsClosestPoints(
+ btVector3& ptsVector,
+ btVector3& offsetA,
+ btVector3& offsetB,
+ btScalar& tA, btScalar& tB,
+ const btVector3& translation,
+ const btVector3& dirA, btScalar hlenA,
+ const btVector3& dirB, btScalar hlenB )
+{
+ // compute the parameters of the closest points on each line segment
+
+ btScalar dirA_dot_dirB = btDot(dirA,dirB);
+ btScalar dirA_dot_trans = btDot(dirA,translation);
+ btScalar dirB_dot_trans = btDot(dirB,translation);
+
+ btScalar denom = 1.0f - dirA_dot_dirB * dirA_dot_dirB;
+
+ if ( denom == 0.0f ) {
+ tA = 0.0f;
+ } else {
+ tA = ( dirA_dot_trans - dirB_dot_trans * dirA_dot_dirB ) / denom;
+ if ( tA < -hlenA )
+ tA = -hlenA;
+ else if ( tA > hlenA )
+ tA = hlenA;
+ }
+
+ tB = tA * dirA_dot_dirB - dirB_dot_trans;
+
+ if ( tB < -hlenB ) {
+ tB = -hlenB;
+ tA = tB * dirA_dot_dirB + dirA_dot_trans;
+
+ if ( tA < -hlenA )
+ tA = -hlenA;
+ else if ( tA > hlenA )
+ tA = hlenA;
+ } else if ( tB > hlenB ) {
+ tB = hlenB;
+ tA = tB * dirA_dot_dirB + dirA_dot_trans;
+
+ if ( tA < -hlenA )
+ tA = -hlenA;
+ else if ( tA > hlenA )
+ tA = hlenA;
+ }
+
+ // compute the closest points relative to segment centers.
+
+ offsetA = dirA * tA;
+ offsetB = dirB * tB;
+
+ ptsVector = translation - offsetA + offsetB;
+}
+
+
+static SIMD_FORCE_INLINE btScalar capsuleCapsuleDistance(
+ btVector3& normalOnB,
+ btVector3& pointOnB,
+ btScalar capsuleLengthA,
+ btScalar capsuleRadiusA,
+ btScalar capsuleLengthB,
+ btScalar capsuleRadiusB,
+ int capsuleAxisA,
+ int capsuleAxisB,
+ const btTransform& transformA,
+ const btTransform& transformB,
+ btScalar distanceThreshold )
+{
+ btVector3 directionA = transformA.getBasis().getColumn(capsuleAxisA);
+ btVector3 translationA = transformA.getOrigin();
+ btVector3 directionB = transformB.getBasis().getColumn(capsuleAxisB);
+ btVector3 translationB = transformB.getOrigin();
+
+ // translation between centers
+
+ btVector3 translation = translationB - translationA;
+
+ // compute the closest points of the capsule line segments
+
+ btVector3 ptsVector; // the vector between the closest points
+
+ btVector3 offsetA, offsetB; // offsets from segment centers to their closest points
+ btScalar tA, tB; // parameters on line segment
+
+ segmentsClosestPoints( ptsVector, offsetA, offsetB, tA, tB, translation,
+ directionA, capsuleLengthA, directionB, capsuleLengthB );
+
+ btScalar distance = ptsVector.length() - capsuleRadiusA - capsuleRadiusB;
+
+ if ( distance > distanceThreshold )
+ return distance;
+
+ btScalar lenSqr = ptsVector.length2();
+ if (lenSqr<= (SIMD_EPSILON*SIMD_EPSILON))
+ {
+ //degenerate case where 2 capsules are likely at the same location: take a vector tangential to 'directionA'
+ btVector3 q;
+ btPlaneSpace1(directionA,normalOnB,q);
+ } else
+ {
+ // compute the contact normal
+ normalOnB = ptsVector*-btRecipSqrt(lenSqr);
+ }
+ pointOnB = transformB.getOrigin()+offsetB + normalOnB * capsuleRadiusB;
+
+ return distance;
+}
+
+
+
+
+
+
+
+//////////
+
+
+
+
+
+btConvexConvexAlgorithm::CreateFunc::CreateFunc(btConvexPenetrationDepthSolver* pdSolver)
+{
+ m_numPerturbationIterations = 0;
+ m_minimumPointsPerturbationThreshold = 3;
+ m_pdSolver = pdSolver;
+}
+
+btConvexConvexAlgorithm::CreateFunc::~CreateFunc()
+{
+}
+
+btConvexConvexAlgorithm::btConvexConvexAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,btConvexPenetrationDepthSolver* pdSolver,int numPerturbationIterations, int minimumPointsPerturbationThreshold)
+: btActivatingCollisionAlgorithm(ci,body0Wrap,body1Wrap),
+m_pdSolver(pdSolver),
+m_ownManifold (false),
+m_manifoldPtr(mf),
+m_lowLevelOfDetail(false),
+#ifdef USE_SEPDISTANCE_UTIL2
+m_sepDistance((static_cast<btConvexShape*>(body0->getCollisionShape()))->getAngularMotionDisc(),
+ (static_cast<btConvexShape*>(body1->getCollisionShape()))->getAngularMotionDisc()),
+#endif
+m_numPerturbationIterations(numPerturbationIterations),
+m_minimumPointsPerturbationThreshold(minimumPointsPerturbationThreshold)
+{
+ (void)body0Wrap;
+ (void)body1Wrap;
+}
+
+
+
+
+btConvexConvexAlgorithm::~btConvexConvexAlgorithm()
+{
+ if (m_ownManifold)
+ {
+ if (m_manifoldPtr)
+ m_dispatcher->releaseManifold(m_manifoldPtr);
+ }
+}
+
+void btConvexConvexAlgorithm ::setLowLevelOfDetail(bool useLowLevel)
+{
+ m_lowLevelOfDetail = useLowLevel;
+}
+
+
+struct btPerturbedContactResult : public btManifoldResult
+{
+ btManifoldResult* m_originalManifoldResult;
+ btTransform m_transformA;
+ btTransform m_transformB;
+ btTransform m_unPerturbedTransform;
+ bool m_perturbA;
+ btIDebugDraw* m_debugDrawer;
+
+
+ btPerturbedContactResult(btManifoldResult* originalResult,const btTransform& transformA,const btTransform& transformB,const btTransform& unPerturbedTransform,bool perturbA,btIDebugDraw* debugDrawer)
+ :m_originalManifoldResult(originalResult),
+ m_transformA(transformA),
+ m_transformB(transformB),
+ m_unPerturbedTransform(unPerturbedTransform),
+ m_perturbA(perturbA),
+ m_debugDrawer(debugDrawer)
+ {
+ }
+ virtual ~ btPerturbedContactResult()
+ {
+ }
+
+ virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar orgDepth)
+ {
+ btVector3 endPt,startPt;
+ btScalar newDepth;
+ btVector3 newNormal;
+
+ if (m_perturbA)
+ {
+ btVector3 endPtOrg = pointInWorld + normalOnBInWorld*orgDepth;
+ endPt = (m_unPerturbedTransform*m_transformA.inverse())(endPtOrg);
+ newDepth = (endPt - pointInWorld).dot(normalOnBInWorld);
+ startPt = endPt+normalOnBInWorld*newDepth;
+ } else
+ {
+ endPt = pointInWorld + normalOnBInWorld*orgDepth;
+ startPt = (m_unPerturbedTransform*m_transformB.inverse())(pointInWorld);
+ newDepth = (endPt - startPt).dot(normalOnBInWorld);
+
+ }
+
+//#define DEBUG_CONTACTS 1
+#ifdef DEBUG_CONTACTS
+ m_debugDrawer->drawLine(startPt,endPt,btVector3(1,0,0));
+ m_debugDrawer->drawSphere(startPt,0.05,btVector3(0,1,0));
+ m_debugDrawer->drawSphere(endPt,0.05,btVector3(0,0,1));
+#endif //DEBUG_CONTACTS
+
+
+ m_originalManifoldResult->addContactPoint(normalOnBInWorld,startPt,newDepth);
+ }
+
+};
+
+extern btScalar gContactBreakingThreshold;
+
+
+//
+// Convex-Convex collision algorithm
+//
+void btConvexConvexAlgorithm ::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+
+ if (!m_manifoldPtr)
+ {
+ //swapped?
+ m_manifoldPtr = m_dispatcher->getNewManifold(body0Wrap->getCollisionObject(),body1Wrap->getCollisionObject());
+ m_ownManifold = true;
+ }
+ resultOut->setPersistentManifold(m_manifoldPtr);
+
+ //comment-out next line to test multi-contact generation
+ //resultOut->getPersistentManifold()->clearManifold();
+
+
+ const btConvexShape* min0 = static_cast<const btConvexShape*>(body0Wrap->getCollisionShape());
+ const btConvexShape* min1 = static_cast<const btConvexShape*>(body1Wrap->getCollisionShape());
+
+ btVector3 normalOnB;
+ btVector3 pointOnBWorld;
+#ifndef BT_DISABLE_CAPSULE_CAPSULE_COLLIDER
+ if ((min0->getShapeType() == CAPSULE_SHAPE_PROXYTYPE) && (min1->getShapeType() == CAPSULE_SHAPE_PROXYTYPE))
+ {
+ //m_manifoldPtr->clearManifold();
+
+ btCapsuleShape* capsuleA = (btCapsuleShape*) min0;
+ btCapsuleShape* capsuleB = (btCapsuleShape*) min1;
+
+ btScalar threshold = m_manifoldPtr->getContactBreakingThreshold();
+
+ btScalar dist = capsuleCapsuleDistance(normalOnB, pointOnBWorld,capsuleA->getHalfHeight(),capsuleA->getRadius(),
+ capsuleB->getHalfHeight(),capsuleB->getRadius(),capsuleA->getUpAxis(),capsuleB->getUpAxis(),
+ body0Wrap->getWorldTransform(),body1Wrap->getWorldTransform(),threshold);
+
+ if (dist<threshold)
+ {
+ btAssert(normalOnB.length2()>=(SIMD_EPSILON*SIMD_EPSILON));
+ resultOut->addContactPoint(normalOnB,pointOnBWorld,dist);
+ }
+ resultOut->refreshContactPoints();
+ return;
+ }
+
+ if ((min0->getShapeType() == CAPSULE_SHAPE_PROXYTYPE) && (min1->getShapeType() == SPHERE_SHAPE_PROXYTYPE))
+ {
+ //m_manifoldPtr->clearManifold();
+
+ btCapsuleShape* capsuleA = (btCapsuleShape*) min0;
+ btSphereShape* capsuleB = (btSphereShape*) min1;
+
+ btScalar threshold = m_manifoldPtr->getContactBreakingThreshold();
+
+ btScalar dist = capsuleCapsuleDistance(normalOnB, pointOnBWorld,capsuleA->getHalfHeight(),capsuleA->getRadius(),
+ 0.,capsuleB->getRadius(),capsuleA->getUpAxis(),1,
+ body0Wrap->getWorldTransform(),body1Wrap->getWorldTransform(),threshold);
+
+ if (dist<threshold)
+ {
+ btAssert(normalOnB.length2()>=(SIMD_EPSILON*SIMD_EPSILON));
+ resultOut->addContactPoint(normalOnB,pointOnBWorld,dist);
+ }
+ resultOut->refreshContactPoints();
+ return;
+ }
+
+ if ((min0->getShapeType() == SPHERE_SHAPE_PROXYTYPE) && (min1->getShapeType() == CAPSULE_SHAPE_PROXYTYPE))
+ {
+ //m_manifoldPtr->clearManifold();
+
+ btSphereShape* capsuleA = (btSphereShape*) min0;
+ btCapsuleShape* capsuleB = (btCapsuleShape*) min1;
+
+ btScalar threshold = m_manifoldPtr->getContactBreakingThreshold();
+
+ btScalar dist = capsuleCapsuleDistance(normalOnB, pointOnBWorld,0.,capsuleA->getRadius(),
+ capsuleB->getHalfHeight(),capsuleB->getRadius(),1,capsuleB->getUpAxis(),
+ body0Wrap->getWorldTransform(),body1Wrap->getWorldTransform(),threshold);
+
+ if (dist<threshold)
+ {
+ btAssert(normalOnB.length2()>=(SIMD_EPSILON*SIMD_EPSILON));
+ resultOut->addContactPoint(normalOnB,pointOnBWorld,dist);
+ }
+ resultOut->refreshContactPoints();
+ return;
+ }
+#endif //BT_DISABLE_CAPSULE_CAPSULE_COLLIDER
+
+
+
+
+#ifdef USE_SEPDISTANCE_UTIL2
+ if (dispatchInfo.m_useConvexConservativeDistanceUtil)
+ {
+ m_sepDistance.updateSeparatingDistance(body0->getWorldTransform(),body1->getWorldTransform());
+ }
+
+ if (!dispatchInfo.m_useConvexConservativeDistanceUtil || m_sepDistance.getConservativeSeparatingDistance()<=0.f)
+#endif //USE_SEPDISTANCE_UTIL2
+
+ {
+
+
+ btGjkPairDetector::ClosestPointInput input;
+ btVoronoiSimplexSolver simplexSolver;
+ btGjkPairDetector gjkPairDetector( min0, min1, &simplexSolver, m_pdSolver );
+ //TODO: if (dispatchInfo.m_useContinuous)
+ gjkPairDetector.setMinkowskiA(min0);
+ gjkPairDetector.setMinkowskiB(min1);
+
+#ifdef USE_SEPDISTANCE_UTIL2
+ if (dispatchInfo.m_useConvexConservativeDistanceUtil)
+ {
+ input.m_maximumDistanceSquared = BT_LARGE_FLOAT;
+ } else
+#endif //USE_SEPDISTANCE_UTIL2
+ {
+ //if (dispatchInfo.m_convexMaxDistanceUseCPT)
+ //{
+ // input.m_maximumDistanceSquared = min0->getMargin() + min1->getMargin() + m_manifoldPtr->getContactProcessingThreshold();
+ //} else
+ //{
+ input.m_maximumDistanceSquared = min0->getMargin() + min1->getMargin() + m_manifoldPtr->getContactBreakingThreshold()+resultOut->m_closestPointDistanceThreshold;
+// }
+
+ input.m_maximumDistanceSquared*= input.m_maximumDistanceSquared;
+ }
+
+ input.m_transformA = body0Wrap->getWorldTransform();
+ input.m_transformB = body1Wrap->getWorldTransform();
+
+
+
+
+
+#ifdef USE_SEPDISTANCE_UTIL2
+ btScalar sepDist = 0.f;
+ if (dispatchInfo.m_useConvexConservativeDistanceUtil)
+ {
+ sepDist = gjkPairDetector.getCachedSeparatingDistance();
+ if (sepDist>SIMD_EPSILON)
+ {
+ sepDist += dispatchInfo.m_convexConservativeDistanceThreshold;
+ //now perturbe directions to get multiple contact points
+
+ }
+ }
+#endif //USE_SEPDISTANCE_UTIL2
+
+ if (min0->isPolyhedral() && min1->isPolyhedral())
+ {
+
+
+ struct btDummyResult : public btDiscreteCollisionDetectorInterface::Result
+ {
+ virtual void setShapeIdentifiersA(int partId0,int index0){}
+ virtual void setShapeIdentifiersB(int partId1,int index1){}
+ virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth)
+ {
+ }
+ };
+
+
+ struct btWithoutMarginResult : public btDiscreteCollisionDetectorInterface::Result
+ {
+ btDiscreteCollisionDetectorInterface::Result* m_originalResult;
+ btVector3 m_reportedNormalOnWorld;
+ btScalar m_marginOnA;
+ btScalar m_marginOnB;
+ btScalar m_reportedDistance;
+
+ bool m_foundResult;
+ btWithoutMarginResult(btDiscreteCollisionDetectorInterface::Result* result, btScalar marginOnA, btScalar marginOnB)
+ :m_originalResult(result),
+ m_marginOnA(marginOnA),
+ m_marginOnB(marginOnB),
+ m_foundResult(false)
+ {
+ }
+
+ virtual void setShapeIdentifiersA(int partId0,int index0){}
+ virtual void setShapeIdentifiersB(int partId1,int index1){}
+ virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorldOrg,btScalar depthOrg)
+ {
+ m_reportedDistance = depthOrg;
+ m_reportedNormalOnWorld = normalOnBInWorld;
+
+ btVector3 adjustedPointB = pointInWorldOrg - normalOnBInWorld*m_marginOnB;
+ m_reportedDistance = depthOrg+(m_marginOnA+m_marginOnB);
+ if (m_reportedDistance<0.f)
+ {
+ m_foundResult = true;
+ }
+ m_originalResult->addContactPoint(normalOnBInWorld,adjustedPointB,m_reportedDistance);
+ }
+ };
+
+
+ btDummyResult dummy;
+
+///btBoxShape is an exception: its vertices are created WITH margin so don't subtract it
+
+ btScalar min0Margin = min0->getShapeType()==BOX_SHAPE_PROXYTYPE? 0.f : min0->getMargin();
+ btScalar min1Margin = min1->getShapeType()==BOX_SHAPE_PROXYTYPE? 0.f : min1->getMargin();
+
+ btWithoutMarginResult withoutMargin(resultOut, min0Margin,min1Margin);
+
+ btPolyhedralConvexShape* polyhedronA = (btPolyhedralConvexShape*) min0;
+ btPolyhedralConvexShape* polyhedronB = (btPolyhedralConvexShape*) min1;
+ if (polyhedronA->getConvexPolyhedron() && polyhedronB->getConvexPolyhedron())
+ {
+
+
+
+
+ btScalar threshold = m_manifoldPtr->getContactBreakingThreshold();
+
+ btScalar minDist = -1e30f;
+ btVector3 sepNormalWorldSpace;
+ bool foundSepAxis = true;
+
+ if (dispatchInfo.m_enableSatConvex)
+ {
+ foundSepAxis = btPolyhedralContactClipping::findSeparatingAxis(
+ *polyhedronA->getConvexPolyhedron(), *polyhedronB->getConvexPolyhedron(),
+ body0Wrap->getWorldTransform(),
+ body1Wrap->getWorldTransform(),
+ sepNormalWorldSpace,*resultOut);
+ } else
+ {
+#ifdef ZERO_MARGIN
+ gjkPairDetector.setIgnoreMargin(true);
+ gjkPairDetector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw);
+#else
+
+
+ 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)
+ {
+ sepNormalWorldSpace = withoutMargin.m_reportedNormalOnWorld;//gjkPairDetector.getCachedSeparatingAxis()*(1.f/l2);
+ //minDist = -1e30f;//gjkPairDetector.getCachedSeparatingDistance();
+ minDist = withoutMargin.m_reportedDistance;//gjkPairDetector.getCachedSeparatingDistance()+min0->getMargin()+min1->getMargin();
+
+#ifdef ZERO_MARGIN
+ foundSepAxis = true;//gjkPairDetector.getCachedSeparatingDistance()<0.f;
+#else
+ foundSepAxis = withoutMargin.m_foundResult && minDist<0;//-(min0->getMargin()+min1->getMargin());
+#endif
+ }
+ }
+ if (foundSepAxis)
+ {
+
+// printf("sepNormalWorldSpace=%f,%f,%f\n",sepNormalWorldSpace.getX(),sepNormalWorldSpace.getY(),sepNormalWorldSpace.getZ());
+
+ worldVertsB1.resize(0);
+ btPolyhedralContactClipping::clipHullAgainstHull(sepNormalWorldSpace, *polyhedronA->getConvexPolyhedron(), *polyhedronB->getConvexPolyhedron(),
+ body0Wrap->getWorldTransform(),
+ body1Wrap->getWorldTransform(), minDist-threshold, threshold, worldVertsB1,worldVertsB2,
+ *resultOut);
+
+ }
+ if (m_ownManifold)
+ {
+ resultOut->refreshContactPoints();
+ }
+ return;
+
+ } else
+ {
+ //we can also deal with convex versus triangle (without connectivity data)
+ if (polyhedronA->getConvexPolyhedron() && polyhedronB->getShapeType()==TRIANGLE_SHAPE_PROXYTYPE)
+ {
+
+ btVertexArray vertices;
+ btTriangleShape* tri = (btTriangleShape*)polyhedronB;
+ vertices.push_back( body1Wrap->getWorldTransform()*tri->m_vertices1[0]);
+ vertices.push_back( body1Wrap->getWorldTransform()*tri->m_vertices1[1]);
+ vertices.push_back( body1Wrap->getWorldTransform()*tri->m_vertices1[2]);
+
+ //tri->initializePolyhedralFeatures();
+
+ btScalar threshold = m_manifoldPtr->getContactBreakingThreshold();
+
+ btVector3 sepNormalWorldSpace;
+ btScalar minDist =-1e30f;
+ btScalar maxDist = threshold;
+
+ bool foundSepAxis = false;
+ if (0)
+ {
+ polyhedronB->initializePolyhedralFeatures();
+ foundSepAxis = btPolyhedralContactClipping::findSeparatingAxis(
+ *polyhedronA->getConvexPolyhedron(), *polyhedronB->getConvexPolyhedron(),
+ body0Wrap->getWorldTransform(),
+ body1Wrap->getWorldTransform(),
+ sepNormalWorldSpace,*resultOut);
+ // printf("sepNormalWorldSpace=%f,%f,%f\n",sepNormalWorldSpace.getX(),sepNormalWorldSpace.getY(),sepNormalWorldSpace.getZ());
+
+ } else
+ {
+#ifdef ZERO_MARGIN
+ gjkPairDetector.setIgnoreMargin(true);
+ gjkPairDetector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw);
+#else
+ gjkPairDetector.getClosestPoints(input,dummy,dispatchInfo.m_debugDraw);
+#endif//ZERO_MARGIN
+
+ btScalar l2 = gjkPairDetector.getCachedSeparatingAxis().length2();
+ if (l2>SIMD_EPSILON)
+ {
+ sepNormalWorldSpace = gjkPairDetector.getCachedSeparatingAxis()*(1.f/l2);
+ //minDist = gjkPairDetector.getCachedSeparatingDistance();
+ //maxDist = threshold;
+ minDist = gjkPairDetector.getCachedSeparatingDistance()-min0->getMargin()-min1->getMargin();
+ foundSepAxis = true;
+ }
+ }
+
+
+ if (foundSepAxis)
+ {
+ worldVertsB2.resize(0);
+ btPolyhedralContactClipping::clipFaceAgainstHull(sepNormalWorldSpace, *polyhedronA->getConvexPolyhedron(),
+ body0Wrap->getWorldTransform(), vertices, worldVertsB2,minDist-threshold, maxDist, *resultOut);
+ }
+
+
+ if (m_ownManifold)
+ {
+ resultOut->refreshContactPoints();
+ }
+
+ return;
+ }
+
+ }
+
+
+ }
+
+ gjkPairDetector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw);
+
+ //now perform 'm_numPerturbationIterations' collision queries with the perturbated collision objects
+
+ //perform perturbation when more then 'm_minimumPointsPerturbationThreshold' points
+ if (m_numPerturbationIterations && resultOut->getPersistentManifold()->getNumContacts() < m_minimumPointsPerturbationThreshold)
+ {
+
+ int i;
+ btVector3 v0,v1;
+ btVector3 sepNormalWorldSpace;
+ btScalar l2 = gjkPairDetector.getCachedSeparatingAxis().length2();
+
+ if (l2>SIMD_EPSILON)
+ {
+ sepNormalWorldSpace = gjkPairDetector.getCachedSeparatingAxis()*(1.f/l2);
+
+ btPlaneSpace1(sepNormalWorldSpace,v0,v1);
+
+
+ bool perturbeA = true;
+ const btScalar angleLimit = 0.125f * SIMD_PI;
+ btScalar perturbeAngle;
+ btScalar radiusA = min0->getAngularMotionDisc();
+ btScalar radiusB = min1->getAngularMotionDisc();
+ if (radiusA < radiusB)
+ {
+ perturbeAngle = gContactBreakingThreshold /radiusA;
+ perturbeA = true;
+ } else
+ {
+ perturbeAngle = gContactBreakingThreshold / radiusB;
+ perturbeA = false;
+ }
+ if ( perturbeAngle > angleLimit )
+ perturbeAngle = angleLimit;
+
+ btTransform unPerturbedTransform;
+ if (perturbeA)
+ {
+ unPerturbedTransform = input.m_transformA;
+ } else
+ {
+ unPerturbedTransform = input.m_transformB;
+ }
+
+ for ( i=0;i<m_numPerturbationIterations;i++)
+ {
+ if (v0.length2()>SIMD_EPSILON)
+ {
+ btQuaternion perturbeRot(v0,perturbeAngle);
+ btScalar iterationAngle = i*(SIMD_2_PI/btScalar(m_numPerturbationIterations));
+ btQuaternion rotq(sepNormalWorldSpace,iterationAngle);
+
+
+ if (perturbeA)
+ {
+ input.m_transformA.setBasis( btMatrix3x3(rotq.inverse()*perturbeRot*rotq)*body0Wrap->getWorldTransform().getBasis());
+ input.m_transformB = body1Wrap->getWorldTransform();
+ #ifdef DEBUG_CONTACTS
+ dispatchInfo.m_debugDraw->drawTransform(input.m_transformA,10.0);
+ #endif //DEBUG_CONTACTS
+ } else
+ {
+ input.m_transformA = body0Wrap->getWorldTransform();
+ input.m_transformB.setBasis( btMatrix3x3(rotq.inverse()*perturbeRot*rotq)*body1Wrap->getWorldTransform().getBasis());
+ #ifdef DEBUG_CONTACTS
+ dispatchInfo.m_debugDraw->drawTransform(input.m_transformB,10.0);
+ #endif
+ }
+
+ btPerturbedContactResult perturbedResultOut(resultOut,input.m_transformA,input.m_transformB,unPerturbedTransform,perturbeA,dispatchInfo.m_debugDraw);
+ gjkPairDetector.getClosestPoints(input,perturbedResultOut,dispatchInfo.m_debugDraw);
+ }
+ }
+ }
+ }
+
+
+
+#ifdef USE_SEPDISTANCE_UTIL2
+ if (dispatchInfo.m_useConvexConservativeDistanceUtil && (sepDist>SIMD_EPSILON))
+ {
+ m_sepDistance.initSeparatingDistance(gjkPairDetector.getCachedSeparatingAxis(),sepDist,body0->getWorldTransform(),body1->getWorldTransform());
+ }
+#endif //USE_SEPDISTANCE_UTIL2
+
+
+ }
+
+ if (m_ownManifold)
+ {
+ resultOut->refreshContactPoints();
+ }
+
+}
+
+
+
+bool disableCcd = false;
+btScalar btConvexConvexAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+ (void)resultOut;
+ (void)dispatchInfo;
+ ///Rather then checking ALL pairs, only calculate TOI when motion exceeds threshold
+
+ ///Linear motion for one of objects needs to exceed m_ccdSquareMotionThreshold
+ ///col0->m_worldTransform,
+ btScalar resultFraction = btScalar(1.);
+
+
+ btScalar squareMot0 = (col0->getInterpolationWorldTransform().getOrigin() - col0->getWorldTransform().getOrigin()).length2();
+ btScalar squareMot1 = (col1->getInterpolationWorldTransform().getOrigin() - col1->getWorldTransform().getOrigin()).length2();
+
+ if (squareMot0 < col0->getCcdSquareMotionThreshold() &&
+ squareMot1 < col1->getCcdSquareMotionThreshold())
+ return resultFraction;
+
+ if (disableCcd)
+ return btScalar(1.);
+
+
+ //An adhoc way of testing the Continuous Collision Detection algorithms
+ //One object is approximated as a sphere, to simplify things
+ //Starting in penetration should report no time of impact
+ //For proper CCD, better accuracy and handling of 'allowed' penetration should be added
+ //also the mainloop of the physics should have a kind of toi queue (something like Brian Mirtich's application of Timewarp for Rigidbodies)
+
+
+ /// Convex0 against sphere for Convex1
+ {
+ btConvexShape* convex0 = static_cast<btConvexShape*>(col0->getCollisionShape());
+
+ btSphereShape sphere1(col1->getCcdSweptSphereRadius()); //todo: allow non-zero sphere sizes, for better approximation
+ btConvexCast::CastResult result;
+ btVoronoiSimplexSolver voronoiSimplex;
+ //SubsimplexConvexCast ccd0(&sphere,min0,&voronoiSimplex);
+ ///Simplification, one object is simplified as a sphere
+ btGjkConvexCast ccd1( convex0 ,&sphere1,&voronoiSimplex);
+ //ContinuousConvexCollision ccd(min0,min1,&voronoiSimplex,0);
+ if (ccd1.calcTimeOfImpact(col0->getWorldTransform(),col0->getInterpolationWorldTransform(),
+ col1->getWorldTransform(),col1->getInterpolationWorldTransform(),result))
+ {
+
+ //store result.m_fraction in both bodies
+
+ if (col0->getHitFraction()> result.m_fraction)
+ col0->setHitFraction( result.m_fraction );
+
+ if (col1->getHitFraction() > result.m_fraction)
+ col1->setHitFraction( result.m_fraction);
+
+ if (resultFraction > result.m_fraction)
+ resultFraction = result.m_fraction;
+
+ }
+
+
+
+
+ }
+
+ /// Sphere (for convex0) against Convex1
+ {
+ btConvexShape* convex1 = static_cast<btConvexShape*>(col1->getCollisionShape());
+
+ btSphereShape sphere0(col0->getCcdSweptSphereRadius()); //todo: allow non-zero sphere sizes, for better approximation
+ btConvexCast::CastResult result;
+ btVoronoiSimplexSolver voronoiSimplex;
+ //SubsimplexConvexCast ccd0(&sphere,min0,&voronoiSimplex);
+ ///Simplification, one object is simplified as a sphere
+ btGjkConvexCast ccd1(&sphere0,convex1,&voronoiSimplex);
+ //ContinuousConvexCollision ccd(min0,min1,&voronoiSimplex,0);
+ if (ccd1.calcTimeOfImpact(col0->getWorldTransform(),col0->getInterpolationWorldTransform(),
+ col1->getWorldTransform(),col1->getInterpolationWorldTransform(),result))
+ {
+
+ //store result.m_fraction in both bodies
+
+ if (col0->getHitFraction() > result.m_fraction)
+ col0->setHitFraction( result.m_fraction);
+
+ if (col1->getHitFraction() > result.m_fraction)
+ col1->setHitFraction( result.m_fraction);
+
+ if (resultFraction > result.m_fraction)
+ resultFraction = result.m_fraction;
+
+ }
+ }
+
+ return resultFraction;
+
+}
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h
new file mode 100644
index 0000000000..cd75ba12d7
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h
@@ -0,0 +1,109 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_CONVEX_CONVEX_ALGORITHM_H
+#define BT_CONVEX_CONVEX_ALGORITHM_H
+
+#include "btActivatingCollisionAlgorithm.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h"
+#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
+#include "btCollisionCreateFunc.h"
+#include "btCollisionDispatcher.h"
+#include "LinearMath/btTransformUtil.h" //for btConvexSeparatingDistanceUtil
+#include "BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h"
+
+class btConvexPenetrationDepthSolver;
+
+///Enabling USE_SEPDISTANCE_UTIL2 requires 100% reliable distance computation. However, when using large size ratios GJK can be imprecise
+///so the distance is not conservative. In that case, enabling this USE_SEPDISTANCE_UTIL2 would result in failing/missing collisions.
+///Either improve GJK for large size ratios (testing a 100 units versus a 0.1 unit object) or only enable the util
+///for certain pairs that have a small size ratio
+
+//#define USE_SEPDISTANCE_UTIL2 1
+
+///The convexConvexAlgorithm collision algorithm implements time of impact, convex closest points and penetration depth calculations between two convex objects.
+///Multiple contact points are calculated by perturbing the orientation of the smallest object orthogonal to the separating normal.
+///This idea was described by Gino van den Bergen in this forum topic http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=4&t=288&p=888#p888
+class btConvexConvexAlgorithm : public btActivatingCollisionAlgorithm
+{
+#ifdef USE_SEPDISTANCE_UTIL2
+ btConvexSeparatingDistanceUtil m_sepDistance;
+#endif
+ btConvexPenetrationDepthSolver* m_pdSolver;
+
+ btVertexArray worldVertsB1;
+ btVertexArray worldVertsB2;
+
+ bool m_ownManifold;
+ btPersistentManifold* m_manifoldPtr;
+ bool m_lowLevelOfDetail;
+
+ int m_numPerturbationIterations;
+ int m_minimumPointsPerturbationThreshold;
+
+
+ ///cache separating vector to speedup collision detection
+
+
+public:
+
+ btConvexConvexAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap, btConvexPenetrationDepthSolver* pdSolver, int numPerturbationIterations, int minimumPointsPerturbationThreshold);
+
+ virtual ~btConvexConvexAlgorithm();
+
+ virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+ virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+ virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
+ {
+ ///should we use m_ownManifold to avoid adding duplicates?
+ if (m_manifoldPtr && m_ownManifold)
+ manifoldArray.push_back(m_manifoldPtr);
+ }
+
+
+ void setLowLevelOfDetail(bool useLowLevel);
+
+
+ const btPersistentManifold* getManifold()
+ {
+ return m_manifoldPtr;
+ }
+
+ struct CreateFunc :public btCollisionAlgorithmCreateFunc
+ {
+
+ btConvexPenetrationDepthSolver* m_pdSolver;
+ int m_numPerturbationIterations;
+ int m_minimumPointsPerturbationThreshold;
+
+ CreateFunc(btConvexPenetrationDepthSolver* pdSolver);
+
+ virtual ~CreateFunc();
+
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
+ {
+ void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConvexAlgorithm));
+ return new(mem) btConvexConvexAlgorithm(ci.m_manifold,ci,body0Wrap,body1Wrap,m_pdSolver,m_numPerturbationIterations,m_minimumPointsPerturbationThreshold);
+ }
+ };
+
+
+};
+
+#endif //BT_CONVEX_CONVEX_ALGORITHM_H
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp
new file mode 100644
index 0000000000..cce2d95bcf
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp
@@ -0,0 +1,174 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btConvexPlaneCollisionAlgorithm.h"
+
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
+
+//#include <stdio.h>
+
+btConvexPlaneCollisionAlgorithm::btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* col0Wrap,const btCollisionObjectWrapper* col1Wrap, bool isSwapped, int numPerturbationIterations,int minimumPointsPerturbationThreshold)
+: btCollisionAlgorithm(ci),
+m_ownManifold(false),
+m_manifoldPtr(mf),
+m_isSwapped(isSwapped),
+m_numPerturbationIterations(numPerturbationIterations),
+m_minimumPointsPerturbationThreshold(minimumPointsPerturbationThreshold)
+{
+ const btCollisionObjectWrapper* convexObjWrap = m_isSwapped? col1Wrap : col0Wrap;
+ const btCollisionObjectWrapper* planeObjWrap = m_isSwapped? col0Wrap : col1Wrap;
+
+ if (!m_manifoldPtr && m_dispatcher->needsCollision(convexObjWrap->getCollisionObject(),planeObjWrap->getCollisionObject()))
+ {
+ m_manifoldPtr = m_dispatcher->getNewManifold(convexObjWrap->getCollisionObject(),planeObjWrap->getCollisionObject());
+ m_ownManifold = true;
+ }
+}
+
+
+btConvexPlaneCollisionAlgorithm::~btConvexPlaneCollisionAlgorithm()
+{
+ if (m_ownManifold)
+ {
+ if (m_manifoldPtr)
+ m_dispatcher->releaseManifold(m_manifoldPtr);
+ }
+}
+
+void btConvexPlaneCollisionAlgorithm::collideSingleContact (const btQuaternion& perturbeRot, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+ const btCollisionObjectWrapper* convexObjWrap = m_isSwapped? body1Wrap : body0Wrap;
+ const btCollisionObjectWrapper* planeObjWrap = m_isSwapped? body0Wrap: body1Wrap;
+
+ btConvexShape* convexShape = (btConvexShape*) convexObjWrap->getCollisionShape();
+ btStaticPlaneShape* planeShape = (btStaticPlaneShape*) planeObjWrap->getCollisionShape();
+
+ bool hasCollision = false;
+ const btVector3& planeNormal = planeShape->getPlaneNormal();
+ const btScalar& planeConstant = planeShape->getPlaneConstant();
+
+ btTransform convexWorldTransform = convexObjWrap->getWorldTransform();
+ btTransform convexInPlaneTrans;
+ convexInPlaneTrans= planeObjWrap->getWorldTransform().inverse() * convexWorldTransform;
+ //now perturbe the convex-world transform
+ convexWorldTransform.getBasis()*=btMatrix3x3(perturbeRot);
+ btTransform planeInConvex;
+ planeInConvex= convexWorldTransform.inverse() * planeObjWrap->getWorldTransform();
+
+ btVector3 vtx = convexShape->localGetSupportingVertex(planeInConvex.getBasis()*-planeNormal);
+
+ btVector3 vtxInPlane = convexInPlaneTrans(vtx);
+ btScalar distance = (planeNormal.dot(vtxInPlane) - planeConstant);
+
+ btVector3 vtxInPlaneProjected = vtxInPlane - distance*planeNormal;
+ btVector3 vtxInPlaneWorld = planeObjWrap->getWorldTransform() * vtxInPlaneProjected;
+
+ hasCollision = distance < m_manifoldPtr->getContactBreakingThreshold();
+ resultOut->setPersistentManifold(m_manifoldPtr);
+ if (hasCollision)
+ {
+ /// report a contact. internally this will be kept persistent, and contact reduction is done
+ btVector3 normalOnSurfaceB = planeObjWrap->getWorldTransform().getBasis() * planeNormal;
+ btVector3 pOnB = vtxInPlaneWorld;
+ resultOut->addContactPoint(normalOnSurfaceB,pOnB,distance);
+ }
+}
+
+
+void btConvexPlaneCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+ (void)dispatchInfo;
+ if (!m_manifoldPtr)
+ return;
+
+ const btCollisionObjectWrapper* convexObjWrap = m_isSwapped? body1Wrap : body0Wrap;
+ const btCollisionObjectWrapper* planeObjWrap = m_isSwapped? body0Wrap: body1Wrap;
+
+ btConvexShape* convexShape = (btConvexShape*) convexObjWrap->getCollisionShape();
+ btStaticPlaneShape* planeShape = (btStaticPlaneShape*) planeObjWrap->getCollisionShape();
+
+ bool hasCollision = false;
+ const btVector3& planeNormal = planeShape->getPlaneNormal();
+ const btScalar& planeConstant = planeShape->getPlaneConstant();
+ btTransform planeInConvex;
+ planeInConvex= convexObjWrap->getWorldTransform().inverse() * planeObjWrap->getWorldTransform();
+ btTransform convexInPlaneTrans;
+ convexInPlaneTrans= planeObjWrap->getWorldTransform().inverse() * convexObjWrap->getWorldTransform();
+
+ btVector3 vtx = convexShape->localGetSupportingVertex(planeInConvex.getBasis()*-planeNormal);
+ btVector3 vtxInPlane = convexInPlaneTrans(vtx);
+ btScalar distance = (planeNormal.dot(vtxInPlane) - planeConstant);
+
+ btVector3 vtxInPlaneProjected = vtxInPlane - distance*planeNormal;
+ btVector3 vtxInPlaneWorld = planeObjWrap->getWorldTransform() * vtxInPlaneProjected;
+
+ hasCollision = distance < m_manifoldPtr->getContactBreakingThreshold();
+ resultOut->setPersistentManifold(m_manifoldPtr);
+ if (hasCollision)
+ {
+ /// report a contact. internally this will be kept persistent, and contact reduction is done
+ btVector3 normalOnSurfaceB = planeObjWrap->getWorldTransform().getBasis() * planeNormal;
+ btVector3 pOnB = vtxInPlaneWorld;
+ resultOut->addContactPoint(normalOnSurfaceB,pOnB,distance);
+ }
+
+ //the perturbation algorithm doesn't work well with implicit surfaces such as spheres, cylinder and cones:
+ //they keep on rolling forever because of the additional off-center contact points
+ //so only enable the feature for polyhedral shapes (btBoxShape, btConvexHullShape etc)
+ if (convexShape->isPolyhedral() && resultOut->getPersistentManifold()->getNumContacts()<m_minimumPointsPerturbationThreshold)
+ {
+ btVector3 v0,v1;
+ btPlaneSpace1(planeNormal,v0,v1);
+ //now perform 'm_numPerturbationIterations' collision queries with the perturbated collision objects
+
+ const btScalar angleLimit = 0.125f * SIMD_PI;
+ btScalar perturbeAngle;
+ btScalar radius = convexShape->getAngularMotionDisc();
+ perturbeAngle = gContactBreakingThreshold / radius;
+ if ( perturbeAngle > angleLimit )
+ perturbeAngle = angleLimit;
+
+ btQuaternion perturbeRot(v0,perturbeAngle);
+ for (int i=0;i<m_numPerturbationIterations;i++)
+ {
+ btScalar iterationAngle = i*(SIMD_2_PI/btScalar(m_numPerturbationIterations));
+ btQuaternion rotq(planeNormal,iterationAngle);
+ collideSingleContact(rotq.inverse()*perturbeRot*rotq,body0Wrap,body1Wrap,dispatchInfo,resultOut);
+ }
+ }
+
+ if (m_ownManifold)
+ {
+ if (m_manifoldPtr->getNumContacts())
+ {
+ resultOut->refreshContactPoints();
+ }
+ }
+}
+
+btScalar btConvexPlaneCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+ (void)resultOut;
+ (void)dispatchInfo;
+ (void)col0;
+ (void)col1;
+
+ //not yet
+ return btScalar(1.);
+}
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h
new file mode 100644
index 0000000000..d28c430c4c
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h
@@ -0,0 +1,84 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_CONVEX_PLANE_COLLISION_ALGORITHM_H
+#define BT_CONVEX_PLANE_COLLISION_ALGORITHM_H
+
+#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
+class btPersistentManifold;
+#include "btCollisionDispatcher.h"
+
+#include "LinearMath/btVector3.h"
+
+/// btSphereBoxCollisionAlgorithm provides sphere-box collision detection.
+/// Other features are frame-coherency (persistent data) and collision response.
+class btConvexPlaneCollisionAlgorithm : public btCollisionAlgorithm
+{
+ bool m_ownManifold;
+ btPersistentManifold* m_manifoldPtr;
+ bool m_isSwapped;
+ int m_numPerturbationIterations;
+ int m_minimumPointsPerturbationThreshold;
+
+public:
+
+ btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap, bool isSwapped, int numPerturbationIterations,int minimumPointsPerturbationThreshold);
+
+ virtual ~btConvexPlaneCollisionAlgorithm();
+
+ virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+ void collideSingleContact (const btQuaternion& perturbeRot, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+ virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+ virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
+ {
+ if (m_manifoldPtr && m_ownManifold)
+ {
+ manifoldArray.push_back(m_manifoldPtr);
+ }
+ }
+
+ struct CreateFunc :public btCollisionAlgorithmCreateFunc
+ {
+ int m_numPerturbationIterations;
+ int m_minimumPointsPerturbationThreshold;
+
+ CreateFunc()
+ : m_numPerturbationIterations(1),
+ m_minimumPointsPerturbationThreshold(0)
+ {
+ }
+
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
+ {
+ void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexPlaneCollisionAlgorithm));
+ if (!m_swapped)
+ {
+ return new(mem) btConvexPlaneCollisionAlgorithm(0,ci,body0Wrap,body1Wrap,false,m_numPerturbationIterations,m_minimumPointsPerturbationThreshold);
+ } else
+ {
+ return new(mem) btConvexPlaneCollisionAlgorithm(0,ci,body0Wrap,body1Wrap,true,m_numPerturbationIterations,m_minimumPointsPerturbationThreshold);
+ }
+ }
+ };
+
+};
+
+#endif //BT_CONVEX_PLANE_COLLISION_ALGORITHM_H
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp
new file mode 100644
index 0000000000..f6e4e57b0a
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp
@@ -0,0 +1,383 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btDefaultCollisionConfiguration.h"
+
+#include "BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.h"
+
+#include "BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h"
+#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM
+#include "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h"
+#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
+#include "BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
+#include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h"
+#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
+
+
+
+#include "LinearMath/btPoolAllocator.h"
+
+
+
+
+
+btDefaultCollisionConfiguration::btDefaultCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo)
+//btDefaultCollisionConfiguration::btDefaultCollisionConfiguration(btStackAlloc* stackAlloc,btPoolAllocator* persistentManifoldPool,btPoolAllocator* collisionAlgorithmPool)
+{
+
+ void* mem = NULL;
+ if (constructionInfo.m_useEpaPenetrationAlgorithm)
+ {
+ mem = btAlignedAlloc(sizeof(btGjkEpaPenetrationDepthSolver),16);
+ m_pdSolver = new (mem)btGjkEpaPenetrationDepthSolver;
+ }else
+ {
+ mem = btAlignedAlloc(sizeof(btMinkowskiPenetrationDepthSolver),16);
+ m_pdSolver = new (mem)btMinkowskiPenetrationDepthSolver;
+ }
+
+ //default CreationFunctions, filling the m_doubleDispatch table
+ mem = btAlignedAlloc(sizeof(btConvexConvexAlgorithm::CreateFunc),16);
+ m_convexConvexCreateFunc = new(mem) btConvexConvexAlgorithm::CreateFunc(m_pdSolver);
+ mem = btAlignedAlloc(sizeof(btConvexConcaveCollisionAlgorithm::CreateFunc),16);
+ m_convexConcaveCreateFunc = new (mem)btConvexConcaveCollisionAlgorithm::CreateFunc;
+ mem = btAlignedAlloc(sizeof(btConvexConcaveCollisionAlgorithm::CreateFunc),16);
+ m_swappedConvexConcaveCreateFunc = new (mem)btConvexConcaveCollisionAlgorithm::SwappedCreateFunc;
+ mem = btAlignedAlloc(sizeof(btCompoundCollisionAlgorithm::CreateFunc),16);
+ m_compoundCreateFunc = new (mem)btCompoundCollisionAlgorithm::CreateFunc;
+
+ mem = btAlignedAlloc(sizeof(btCompoundCompoundCollisionAlgorithm::CreateFunc),16);
+ m_compoundCompoundCreateFunc = new (mem)btCompoundCompoundCollisionAlgorithm::CreateFunc;
+
+ mem = btAlignedAlloc(sizeof(btCompoundCollisionAlgorithm::SwappedCreateFunc),16);
+ m_swappedCompoundCreateFunc = new (mem)btCompoundCollisionAlgorithm::SwappedCreateFunc;
+ mem = btAlignedAlloc(sizeof(btEmptyAlgorithm::CreateFunc),16);
+ m_emptyCreateFunc = new(mem) btEmptyAlgorithm::CreateFunc;
+
+ mem = btAlignedAlloc(sizeof(btSphereSphereCollisionAlgorithm::CreateFunc),16);
+ m_sphereSphereCF = new(mem) btSphereSphereCollisionAlgorithm::CreateFunc;
+#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM
+ mem = btAlignedAlloc(sizeof(btSphereBoxCollisionAlgorithm::CreateFunc),16);
+ m_sphereBoxCF = new(mem) btSphereBoxCollisionAlgorithm::CreateFunc;
+ mem = btAlignedAlloc(sizeof(btSphereBoxCollisionAlgorithm::CreateFunc),16);
+ m_boxSphereCF = new (mem)btSphereBoxCollisionAlgorithm::CreateFunc;
+ m_boxSphereCF->m_swapped = true;
+#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
+
+ mem = btAlignedAlloc(sizeof(btSphereTriangleCollisionAlgorithm::CreateFunc),16);
+ m_sphereTriangleCF = new (mem)btSphereTriangleCollisionAlgorithm::CreateFunc;
+ mem = btAlignedAlloc(sizeof(btSphereTriangleCollisionAlgorithm::CreateFunc),16);
+ m_triangleSphereCF = new (mem)btSphereTriangleCollisionAlgorithm::CreateFunc;
+ m_triangleSphereCF->m_swapped = true;
+
+ mem = btAlignedAlloc(sizeof(btBoxBoxCollisionAlgorithm::CreateFunc),16);
+ m_boxBoxCF = new(mem)btBoxBoxCollisionAlgorithm::CreateFunc;
+
+ //convex versus plane
+ mem = btAlignedAlloc (sizeof(btConvexPlaneCollisionAlgorithm::CreateFunc),16);
+ m_convexPlaneCF = new (mem) btConvexPlaneCollisionAlgorithm::CreateFunc;
+ mem = btAlignedAlloc (sizeof(btConvexPlaneCollisionAlgorithm::CreateFunc),16);
+ m_planeConvexCF = new (mem) btConvexPlaneCollisionAlgorithm::CreateFunc;
+ m_planeConvexCF->m_swapped = true;
+
+ ///calculate maximum element size, big enough to fit any collision algorithm in the memory pool
+ int maxSize = sizeof(btConvexConvexAlgorithm);
+ int maxSize2 = sizeof(btConvexConcaveCollisionAlgorithm);
+ int maxSize3 = sizeof(btCompoundCollisionAlgorithm);
+ int maxSize4 = sizeof(btCompoundCompoundCollisionAlgorithm);
+
+ int collisionAlgorithmMaxElementSize = btMax(maxSize,constructionInfo.m_customCollisionAlgorithmMaxElementSize);
+ collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize,maxSize2);
+ collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize,maxSize3);
+ collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize,maxSize4);
+
+ if (constructionInfo.m_persistentManifoldPool)
+ {
+ m_ownsPersistentManifoldPool = false;
+ m_persistentManifoldPool = constructionInfo.m_persistentManifoldPool;
+ } else
+ {
+ m_ownsPersistentManifoldPool = true;
+ void* mem = btAlignedAlloc(sizeof(btPoolAllocator),16);
+ m_persistentManifoldPool = new (mem) btPoolAllocator(sizeof(btPersistentManifold),constructionInfo.m_defaultMaxPersistentManifoldPoolSize);
+ }
+
+ collisionAlgorithmMaxElementSize = (collisionAlgorithmMaxElementSize+16)&0xffffffffffff0;
+ if (constructionInfo.m_collisionAlgorithmPool)
+ {
+ m_ownsCollisionAlgorithmPool = false;
+ m_collisionAlgorithmPool = constructionInfo.m_collisionAlgorithmPool;
+ } else
+ {
+ m_ownsCollisionAlgorithmPool = true;
+ void* mem = btAlignedAlloc(sizeof(btPoolAllocator),16);
+ m_collisionAlgorithmPool = new(mem) btPoolAllocator(collisionAlgorithmMaxElementSize,constructionInfo.m_defaultMaxCollisionAlgorithmPoolSize);
+ }
+
+
+}
+
+btDefaultCollisionConfiguration::~btDefaultCollisionConfiguration()
+{
+ if (m_ownsCollisionAlgorithmPool)
+ {
+ m_collisionAlgorithmPool->~btPoolAllocator();
+ btAlignedFree(m_collisionAlgorithmPool);
+ }
+ if (m_ownsPersistentManifoldPool)
+ {
+ m_persistentManifoldPool->~btPoolAllocator();
+ btAlignedFree(m_persistentManifoldPool);
+ }
+
+ m_convexConvexCreateFunc->~btCollisionAlgorithmCreateFunc();
+ btAlignedFree( m_convexConvexCreateFunc);
+
+ m_convexConcaveCreateFunc->~btCollisionAlgorithmCreateFunc();
+ btAlignedFree( m_convexConcaveCreateFunc);
+ m_swappedConvexConcaveCreateFunc->~btCollisionAlgorithmCreateFunc();
+ btAlignedFree( m_swappedConvexConcaveCreateFunc);
+
+ m_compoundCreateFunc->~btCollisionAlgorithmCreateFunc();
+ btAlignedFree( m_compoundCreateFunc);
+
+ m_compoundCompoundCreateFunc->~btCollisionAlgorithmCreateFunc();
+ btAlignedFree(m_compoundCompoundCreateFunc);
+
+ m_swappedCompoundCreateFunc->~btCollisionAlgorithmCreateFunc();
+ btAlignedFree( m_swappedCompoundCreateFunc);
+
+ m_emptyCreateFunc->~btCollisionAlgorithmCreateFunc();
+ btAlignedFree( m_emptyCreateFunc);
+
+ m_sphereSphereCF->~btCollisionAlgorithmCreateFunc();
+ btAlignedFree( m_sphereSphereCF);
+
+#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM
+ m_sphereBoxCF->~btCollisionAlgorithmCreateFunc();
+ btAlignedFree( m_sphereBoxCF);
+ m_boxSphereCF->~btCollisionAlgorithmCreateFunc();
+ btAlignedFree( m_boxSphereCF);
+#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
+
+ m_sphereTriangleCF->~btCollisionAlgorithmCreateFunc();
+ btAlignedFree( m_sphereTriangleCF);
+ m_triangleSphereCF->~btCollisionAlgorithmCreateFunc();
+ btAlignedFree( m_triangleSphereCF);
+ m_boxBoxCF->~btCollisionAlgorithmCreateFunc();
+ btAlignedFree( m_boxBoxCF);
+
+ m_convexPlaneCF->~btCollisionAlgorithmCreateFunc();
+ btAlignedFree( m_convexPlaneCF);
+ m_planeConvexCF->~btCollisionAlgorithmCreateFunc();
+ btAlignedFree( m_planeConvexCF);
+
+ m_pdSolver->~btConvexPenetrationDepthSolver();
+
+ btAlignedFree(m_pdSolver);
+
+
+}
+
+btCollisionAlgorithmCreateFunc* btDefaultCollisionConfiguration::getClosestPointsAlgorithmCreateFunc(int proxyType0, int proxyType1)
+{
+
+
+ if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1 == SPHERE_SHAPE_PROXYTYPE))
+ {
+ return m_sphereSphereCF;
+ }
+#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM
+ if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1 == BOX_SHAPE_PROXYTYPE))
+ {
+ return m_sphereBoxCF;
+ }
+
+ if ((proxyType0 == BOX_SHAPE_PROXYTYPE) && (proxyType1 == SPHERE_SHAPE_PROXYTYPE))
+ {
+ return m_boxSphereCF;
+ }
+#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
+
+
+ if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1 == TRIANGLE_SHAPE_PROXYTYPE))
+ {
+ return m_sphereTriangleCF;
+ }
+
+ if ((proxyType0 == TRIANGLE_SHAPE_PROXYTYPE) && (proxyType1 == SPHERE_SHAPE_PROXYTYPE))
+ {
+ return m_triangleSphereCF;
+ }
+
+ if (btBroadphaseProxy::isConvex(proxyType0) && (proxyType1 == STATIC_PLANE_PROXYTYPE))
+ {
+ return m_convexPlaneCF;
+ }
+
+ if (btBroadphaseProxy::isConvex(proxyType1) && (proxyType0 == STATIC_PLANE_PROXYTYPE))
+ {
+ return m_planeConvexCF;
+ }
+
+
+
+ if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConvex(proxyType1))
+ {
+ return m_convexConvexCreateFunc;
+ }
+
+ if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConcave(proxyType1))
+ {
+ return m_convexConcaveCreateFunc;
+ }
+
+ if (btBroadphaseProxy::isConvex(proxyType1) && btBroadphaseProxy::isConcave(proxyType0))
+ {
+ return m_swappedConvexConcaveCreateFunc;
+ }
+
+
+ if (btBroadphaseProxy::isCompound(proxyType0) && btBroadphaseProxy::isCompound(proxyType1))
+ {
+ return m_compoundCompoundCreateFunc;
+ }
+
+ if (btBroadphaseProxy::isCompound(proxyType0))
+ {
+ return m_compoundCreateFunc;
+ }
+ else
+ {
+ if (btBroadphaseProxy::isCompound(proxyType1))
+ {
+ return m_swappedCompoundCreateFunc;
+ }
+ }
+
+ //failed to find an algorithm
+ return m_emptyCreateFunc;
+
+}
+
+btCollisionAlgorithmCreateFunc* btDefaultCollisionConfiguration::getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1)
+{
+
+
+
+ if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1==SPHERE_SHAPE_PROXYTYPE))
+ {
+ return m_sphereSphereCF;
+ }
+#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM
+ if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1==BOX_SHAPE_PROXYTYPE))
+ {
+ return m_sphereBoxCF;
+ }
+
+ if ((proxyType0 == BOX_SHAPE_PROXYTYPE ) && (proxyType1==SPHERE_SHAPE_PROXYTYPE))
+ {
+ return m_boxSphereCF;
+ }
+#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
+
+
+ if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE ) && (proxyType1==TRIANGLE_SHAPE_PROXYTYPE))
+ {
+ return m_sphereTriangleCF;
+ }
+
+ if ((proxyType0 == TRIANGLE_SHAPE_PROXYTYPE ) && (proxyType1==SPHERE_SHAPE_PROXYTYPE))
+ {
+ return m_triangleSphereCF;
+ }
+
+ if ((proxyType0 == BOX_SHAPE_PROXYTYPE) && (proxyType1 == BOX_SHAPE_PROXYTYPE))
+ {
+ return m_boxBoxCF;
+ }
+
+ if (btBroadphaseProxy::isConvex(proxyType0) && (proxyType1 == STATIC_PLANE_PROXYTYPE))
+ {
+ return m_convexPlaneCF;
+ }
+
+ if (btBroadphaseProxy::isConvex(proxyType1) && (proxyType0 == STATIC_PLANE_PROXYTYPE))
+ {
+ return m_planeConvexCF;
+ }
+
+
+
+ if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConvex(proxyType1))
+ {
+ return m_convexConvexCreateFunc;
+ }
+
+ if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConcave(proxyType1))
+ {
+ return m_convexConcaveCreateFunc;
+ }
+
+ if (btBroadphaseProxy::isConvex(proxyType1) && btBroadphaseProxy::isConcave(proxyType0))
+ {
+ return m_swappedConvexConcaveCreateFunc;
+ }
+
+
+ if (btBroadphaseProxy::isCompound(proxyType0) && btBroadphaseProxy::isCompound(proxyType1))
+ {
+ return m_compoundCompoundCreateFunc;
+ }
+
+ if (btBroadphaseProxy::isCompound(proxyType0))
+ {
+ return m_compoundCreateFunc;
+ } else
+ {
+ if (btBroadphaseProxy::isCompound(proxyType1))
+ {
+ return m_swappedCompoundCreateFunc;
+ }
+ }
+
+ //failed to find an algorithm
+ return m_emptyCreateFunc;
+}
+
+void btDefaultCollisionConfiguration::setConvexConvexMultipointIterations(int numPerturbationIterations, int minimumPointsPerturbationThreshold)
+{
+ btConvexConvexAlgorithm::CreateFunc* convexConvex = (btConvexConvexAlgorithm::CreateFunc*) m_convexConvexCreateFunc;
+ convexConvex->m_numPerturbationIterations = numPerturbationIterations;
+ convexConvex->m_minimumPointsPerturbationThreshold = minimumPointsPerturbationThreshold;
+}
+
+void btDefaultCollisionConfiguration::setPlaneConvexMultipointIterations(int numPerturbationIterations, int minimumPointsPerturbationThreshold)
+{
+ btConvexPlaneCollisionAlgorithm::CreateFunc* cpCF = (btConvexPlaneCollisionAlgorithm::CreateFunc*)m_convexPlaneCF;
+ cpCF->m_numPerturbationIterations = numPerturbationIterations;
+ cpCF->m_minimumPointsPerturbationThreshold = minimumPointsPerturbationThreshold;
+
+ btConvexPlaneCollisionAlgorithm::CreateFunc* pcCF = (btConvexPlaneCollisionAlgorithm::CreateFunc*)m_planeConvexCF;
+ pcCF->m_numPerturbationIterations = numPerturbationIterations;
+ pcCF->m_minimumPointsPerturbationThreshold = minimumPointsPerturbationThreshold;
+}
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h
new file mode 100644
index 0000000000..17c7596cff
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h
@@ -0,0 +1,122 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_DEFAULT_COLLISION_CONFIGURATION
+#define BT_DEFAULT_COLLISION_CONFIGURATION
+
+#include "btCollisionConfiguration.h"
+class btVoronoiSimplexSolver;
+class btConvexPenetrationDepthSolver;
+
+struct btDefaultCollisionConstructionInfo
+{
+ btPoolAllocator* m_persistentManifoldPool;
+ btPoolAllocator* m_collisionAlgorithmPool;
+ int m_defaultMaxPersistentManifoldPoolSize;
+ int m_defaultMaxCollisionAlgorithmPoolSize;
+ int m_customCollisionAlgorithmMaxElementSize;
+ int m_useEpaPenetrationAlgorithm;
+
+ btDefaultCollisionConstructionInfo()
+ :m_persistentManifoldPool(0),
+ m_collisionAlgorithmPool(0),
+ m_defaultMaxPersistentManifoldPoolSize(4096),
+ m_defaultMaxCollisionAlgorithmPoolSize(4096),
+ m_customCollisionAlgorithmMaxElementSize(0),
+ m_useEpaPenetrationAlgorithm(true)
+ {
+ }
+};
+
+
+
+///btCollisionConfiguration allows to configure Bullet collision detection
+///stack allocator, pool memory allocators
+///@todo: describe the meaning
+class btDefaultCollisionConfiguration : public btCollisionConfiguration
+{
+
+protected:
+
+ int m_persistentManifoldPoolSize;
+
+
+ btPoolAllocator* m_persistentManifoldPool;
+ bool m_ownsPersistentManifoldPool;
+
+
+ btPoolAllocator* m_collisionAlgorithmPool;
+ bool m_ownsCollisionAlgorithmPool;
+
+ //default penetration depth solver
+ btConvexPenetrationDepthSolver* m_pdSolver;
+
+ //default CreationFunctions, filling the m_doubleDispatch table
+ btCollisionAlgorithmCreateFunc* m_convexConvexCreateFunc;
+ btCollisionAlgorithmCreateFunc* m_convexConcaveCreateFunc;
+ btCollisionAlgorithmCreateFunc* m_swappedConvexConcaveCreateFunc;
+ btCollisionAlgorithmCreateFunc* m_compoundCreateFunc;
+ btCollisionAlgorithmCreateFunc* m_compoundCompoundCreateFunc;
+
+ btCollisionAlgorithmCreateFunc* m_swappedCompoundCreateFunc;
+ btCollisionAlgorithmCreateFunc* m_emptyCreateFunc;
+ btCollisionAlgorithmCreateFunc* m_sphereSphereCF;
+ btCollisionAlgorithmCreateFunc* m_sphereBoxCF;
+ btCollisionAlgorithmCreateFunc* m_boxSphereCF;
+
+ btCollisionAlgorithmCreateFunc* m_boxBoxCF;
+ btCollisionAlgorithmCreateFunc* m_sphereTriangleCF;
+ btCollisionAlgorithmCreateFunc* m_triangleSphereCF;
+ btCollisionAlgorithmCreateFunc* m_planeConvexCF;
+ btCollisionAlgorithmCreateFunc* m_convexPlaneCF;
+
+public:
+
+
+ btDefaultCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo = btDefaultCollisionConstructionInfo());
+
+ virtual ~btDefaultCollisionConfiguration();
+
+ ///memory pools
+ virtual btPoolAllocator* getPersistentManifoldPool()
+ {
+ return m_persistentManifoldPool;
+ }
+
+ virtual btPoolAllocator* getCollisionAlgorithmPool()
+ {
+ return m_collisionAlgorithmPool;
+ }
+
+
+ virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1);
+
+ virtual btCollisionAlgorithmCreateFunc* getClosestPointsAlgorithmCreateFunc(int proxyType0, int proxyType1);
+
+ ///Use this method to allow to generate multiple contact points between at once, between two objects using the generic convex-convex algorithm.
+ ///By default, this feature is disabled for best performance.
+ ///@param numPerturbationIterations controls the number of collision queries. Set it to zero to disable the feature.
+ ///@param minimumPointsPerturbationThreshold is the minimum number of points in the contact cache, above which the feature is disabled
+ ///3 is a good value for both params, if you want to enable the feature. This is because the default contact cache contains a maximum of 4 points, and one collision query at the unperturbed orientation is performed first.
+ ///See Bullet/Demos/CollisionDemo for an example how this feature gathers multiple points.
+ ///@todo we could add a per-object setting of those parameters, for level-of-detail collision detection.
+ void setConvexConvexMultipointIterations(int numPerturbationIterations=3, int minimumPointsPerturbationThreshold = 3);
+
+ void setPlaneConvexMultipointIterations(int numPerturbationIterations=3, int minimumPointsPerturbationThreshold = 3);
+
+};
+
+#endif //BT_DEFAULT_COLLISION_CONFIGURATION
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp
new file mode 100644
index 0000000000..5fa1c8be5e
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp
@@ -0,0 +1,34 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btEmptyCollisionAlgorithm.h"
+
+
+
+btEmptyAlgorithm::btEmptyAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
+ : btCollisionAlgorithm(ci)
+{
+}
+
+void btEmptyAlgorithm::processCollision (const btCollisionObjectWrapper* ,const btCollisionObjectWrapper* ,const btDispatcherInfo& ,btManifoldResult* )
+{
+}
+
+btScalar btEmptyAlgorithm::calculateTimeOfImpact(btCollisionObject* ,btCollisionObject* ,const btDispatcherInfo& ,btManifoldResult* )
+{
+ return btScalar(1.);
+}
+
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h
new file mode 100644
index 0000000000..cb0f152183
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h
@@ -0,0 +1,54 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_EMPTY_ALGORITH
+#define BT_EMPTY_ALGORITH
+#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
+#include "btCollisionCreateFunc.h"
+#include "btCollisionDispatcher.h"
+
+#define ATTRIBUTE_ALIGNED(a)
+
+///EmptyAlgorithm is a stub for unsupported collision pairs.
+///The dispatcher can dispatch a persistent btEmptyAlgorithm to avoid a search every frame.
+class btEmptyAlgorithm : public btCollisionAlgorithm
+{
+
+public:
+
+ btEmptyAlgorithm(const btCollisionAlgorithmConstructionInfo& ci);
+
+ virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+ virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+ virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
+ {
+ }
+
+ struct CreateFunc :public btCollisionAlgorithmCreateFunc
+ {
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
+ {
+ (void)body0Wrap;
+ (void)body1Wrap;
+ void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btEmptyAlgorithm));
+ return new(mem) btEmptyAlgorithm(ci);
+ }
+ };
+
+} ATTRIBUTE_ALIGNED(16);
+
+#endif //BT_EMPTY_ALGORITH
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btGhostObject.cpp b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btGhostObject.cpp
new file mode 100644
index 0000000000..86141fa689
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btGhostObject.cpp
@@ -0,0 +1,171 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com
+
+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 "btGhostObject.h"
+#include "btCollisionWorld.h"
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+#include "LinearMath/btAabbUtil2.h"
+
+btGhostObject::btGhostObject()
+{
+ m_internalType = CO_GHOST_OBJECT;
+}
+
+btGhostObject::~btGhostObject()
+{
+ ///btGhostObject should have been removed from the world, so no overlapping objects
+ btAssert(!m_overlappingObjects.size());
+}
+
+
+void btGhostObject::addOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btBroadphaseProxy* thisProxy)
+{
+ btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject;
+ btAssert(otherObject);
+ ///if this linearSearch becomes too slow (too many overlapping objects) we should add a more appropriate data structure
+ int index = m_overlappingObjects.findLinearSearch(otherObject);
+ if (index==m_overlappingObjects.size())
+ {
+ //not found
+ m_overlappingObjects.push_back(otherObject);
+ }
+}
+
+void btGhostObject::removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btDispatcher* dispatcher,btBroadphaseProxy* thisProxy)
+{
+ btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject;
+ btAssert(otherObject);
+ int index = m_overlappingObjects.findLinearSearch(otherObject);
+ if (index<m_overlappingObjects.size())
+ {
+ m_overlappingObjects[index] = m_overlappingObjects[m_overlappingObjects.size()-1];
+ m_overlappingObjects.pop_back();
+ }
+}
+
+
+btPairCachingGhostObject::btPairCachingGhostObject()
+{
+ m_hashPairCache = new (btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16)) btHashedOverlappingPairCache();
+}
+
+btPairCachingGhostObject::~btPairCachingGhostObject()
+{
+ m_hashPairCache->~btHashedOverlappingPairCache();
+ btAlignedFree( m_hashPairCache );
+}
+
+void btPairCachingGhostObject::addOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btBroadphaseProxy* thisProxy)
+{
+ btBroadphaseProxy*actualThisProxy = thisProxy ? thisProxy : getBroadphaseHandle();
+ btAssert(actualThisProxy);
+
+ btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject;
+ btAssert(otherObject);
+ int index = m_overlappingObjects.findLinearSearch(otherObject);
+ if (index==m_overlappingObjects.size())
+ {
+ m_overlappingObjects.push_back(otherObject);
+ m_hashPairCache->addOverlappingPair(actualThisProxy,otherProxy);
+ }
+}
+
+void btPairCachingGhostObject::removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btDispatcher* dispatcher,btBroadphaseProxy* thisProxy1)
+{
+ btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject;
+ btBroadphaseProxy* actualThisProxy = thisProxy1 ? thisProxy1 : getBroadphaseHandle();
+ btAssert(actualThisProxy);
+
+ btAssert(otherObject);
+ int index = m_overlappingObjects.findLinearSearch(otherObject);
+ if (index<m_overlappingObjects.size())
+ {
+ m_overlappingObjects[index] = m_overlappingObjects[m_overlappingObjects.size()-1];
+ m_overlappingObjects.pop_back();
+ m_hashPairCache->removeOverlappingPair(actualThisProxy,otherProxy,dispatcher);
+ }
+}
+
+
+void btGhostObject::convexSweepTest(const btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, btCollisionWorld::ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration) const
+{
+ btTransform convexFromTrans,convexToTrans;
+ convexFromTrans = convexFromWorld;
+ convexToTrans = convexToWorld;
+ btVector3 castShapeAabbMin, castShapeAabbMax;
+ /* Compute AABB that encompasses angular movement */
+ {
+ btVector3 linVel, angVel;
+ btTransformUtil::calculateVelocity (convexFromTrans, convexToTrans, 1.0, linVel, angVel);
+ btTransform R;
+ R.setIdentity ();
+ R.setRotation (convexFromTrans.getRotation());
+ castShape->calculateTemporalAabb (R, linVel, angVel, 1.0, castShapeAabbMin, castShapeAabbMax);
+ }
+
+ /// go over all objects, and if the ray intersects their aabb + cast shape aabb,
+ // do a ray-shape query using convexCaster (CCD)
+ int i;
+ for (i=0;i<m_overlappingObjects.size();i++)
+ {
+ btCollisionObject* collisionObject= m_overlappingObjects[i];
+ //only perform raycast if filterMask matches
+ if(resultCallback.needsCollision(collisionObject->getBroadphaseHandle())) {
+ //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
+ btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
+ collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax);
+ AabbExpand (collisionObjectAabbMin, collisionObjectAabbMax, castShapeAabbMin, castShapeAabbMax);
+ btScalar hitLambda = btScalar(1.); //could use resultCallback.m_closestHitFraction, but needs testing
+ btVector3 hitNormal;
+ if (btRayAabb(convexFromWorld.getOrigin(),convexToWorld.getOrigin(),collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,hitNormal))
+ {
+ btCollisionWorld::objectQuerySingle(castShape, convexFromTrans,convexToTrans,
+ collisionObject,
+ collisionObject->getCollisionShape(),
+ collisionObject->getWorldTransform(),
+ resultCallback,
+ allowedCcdPenetration);
+ }
+ }
+ }
+
+}
+
+void btGhostObject::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, btCollisionWorld::RayResultCallback& resultCallback) const
+{
+ btTransform rayFromTrans;
+ rayFromTrans.setIdentity();
+ rayFromTrans.setOrigin(rayFromWorld);
+ btTransform rayToTrans;
+ rayToTrans.setIdentity();
+ rayToTrans.setOrigin(rayToWorld);
+
+
+ int i;
+ for (i=0;i<m_overlappingObjects.size();i++)
+ {
+ btCollisionObject* collisionObject= m_overlappingObjects[i];
+ //only perform raycast if filterMask matches
+ if(resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
+ {
+ btCollisionWorld::rayTestSingle(rayFromTrans,rayToTrans,
+ collisionObject,
+ collisionObject->getCollisionShape(),
+ collisionObject->getWorldTransform(),
+ resultCallback);
+ }
+ }
+}
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btGhostObject.h b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btGhostObject.h
new file mode 100644
index 0000000000..8ec8613857
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btGhostObject.h
@@ -0,0 +1,175 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com
+
+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_GHOST_OBJECT_H
+#define BT_GHOST_OBJECT_H
+
+
+#include "btCollisionObject.h"
+#include "BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h"
+#include "LinearMath/btAlignedAllocator.h"
+#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
+#include "btCollisionWorld.h"
+
+class btConvexShape;
+
+class btDispatcher;
+
+///The btGhostObject can keep track of all objects that are overlapping
+///By default, this overlap is based on the AABB
+///This is useful for creating a character controller, collision sensors/triggers, explosions etc.
+///We plan on adding rayTest and other queries for the btGhostObject
+ATTRIBUTE_ALIGNED16(class) btGhostObject : public btCollisionObject
+{
+protected:
+
+ btAlignedObjectArray<btCollisionObject*> m_overlappingObjects;
+
+public:
+
+ btGhostObject();
+
+ virtual ~btGhostObject();
+
+ void convexSweepTest(const class btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, btCollisionWorld::ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration = 0.f) const;
+
+ void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, btCollisionWorld::RayResultCallback& resultCallback) const;
+
+ ///this method is mainly for expert/internal use only.
+ virtual void addOverlappingObjectInternal(btBroadphaseProxy* otherProxy, btBroadphaseProxy* thisProxy=0);
+ ///this method is mainly for expert/internal use only.
+ virtual void removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btDispatcher* dispatcher,btBroadphaseProxy* thisProxy=0);
+
+ int getNumOverlappingObjects() const
+ {
+ return m_overlappingObjects.size();
+ }
+
+ btCollisionObject* getOverlappingObject(int index)
+ {
+ return m_overlappingObjects[index];
+ }
+
+ const btCollisionObject* getOverlappingObject(int index) const
+ {
+ return m_overlappingObjects[index];
+ }
+
+ btAlignedObjectArray<btCollisionObject*>& getOverlappingPairs()
+ {
+ return m_overlappingObjects;
+ }
+
+ const btAlignedObjectArray<btCollisionObject*> getOverlappingPairs() const
+ {
+ return m_overlappingObjects;
+ }
+
+ //
+ // internal cast
+ //
+
+ static const btGhostObject* upcast(const btCollisionObject* colObj)
+ {
+ if (colObj->getInternalType()==CO_GHOST_OBJECT)
+ return (const btGhostObject*)colObj;
+ return 0;
+ }
+ static btGhostObject* upcast(btCollisionObject* colObj)
+ {
+ if (colObj->getInternalType()==CO_GHOST_OBJECT)
+ return (btGhostObject*)colObj;
+ return 0;
+ }
+
+};
+
+class btPairCachingGhostObject : public btGhostObject
+{
+ btHashedOverlappingPairCache* m_hashPairCache;
+
+public:
+
+ btPairCachingGhostObject();
+
+ virtual ~btPairCachingGhostObject();
+
+ ///this method is mainly for expert/internal use only.
+ virtual void addOverlappingObjectInternal(btBroadphaseProxy* otherProxy, btBroadphaseProxy* thisProxy=0);
+
+ virtual void removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btDispatcher* dispatcher,btBroadphaseProxy* thisProxy=0);
+
+ btHashedOverlappingPairCache* getOverlappingPairCache()
+ {
+ return m_hashPairCache;
+ }
+
+};
+
+
+
+///The btGhostPairCallback interfaces and forwards adding and removal of overlapping pairs from the btBroadphaseInterface to btGhostObject.
+class btGhostPairCallback : public btOverlappingPairCallback
+{
+
+public:
+ btGhostPairCallback()
+ {
+ }
+
+ virtual ~btGhostPairCallback()
+ {
+
+ }
+
+ virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
+ {
+ btCollisionObject* colObj0 = (btCollisionObject*) proxy0->m_clientObject;
+ btCollisionObject* colObj1 = (btCollisionObject*) proxy1->m_clientObject;
+ btGhostObject* ghost0 = btGhostObject::upcast(colObj0);
+ btGhostObject* ghost1 = btGhostObject::upcast(colObj1);
+ if (ghost0)
+ ghost0->addOverlappingObjectInternal(proxy1, proxy0);
+ if (ghost1)
+ ghost1->addOverlappingObjectInternal(proxy0, proxy1);
+ return 0;
+ }
+
+ virtual void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher)
+ {
+ btCollisionObject* colObj0 = (btCollisionObject*) proxy0->m_clientObject;
+ btCollisionObject* colObj1 = (btCollisionObject*) proxy1->m_clientObject;
+ btGhostObject* ghost0 = btGhostObject::upcast(colObj0);
+ btGhostObject* ghost1 = btGhostObject::upcast(colObj1);
+ if (ghost0)
+ ghost0->removeOverlappingObjectInternal(proxy1,dispatcher,proxy0);
+ if (ghost1)
+ ghost1->removeOverlappingObjectInternal(proxy0,dispatcher,proxy1);
+ return 0;
+ }
+
+ virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* /*proxy0*/,btDispatcher* /*dispatcher*/)
+ {
+ btAssert(0);
+ //need to keep track of all ghost objects and call them here
+ //m_hashPairCache->removeOverlappingPairsContainingProxy(proxy0,dispatcher);
+ }
+
+
+
+};
+
+#endif
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btHashedSimplePairCache.cpp b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btHashedSimplePairCache.cpp
new file mode 100644
index 0000000000..8c8a7c3c1e
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btHashedSimplePairCache.cpp
@@ -0,0 +1,276 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+#include "btHashedSimplePairCache.h"
+
+
+#include <stdio.h>
+
+int gOverlappingSimplePairs = 0;
+int gRemoveSimplePairs =0;
+int gAddedSimplePairs =0;
+int gFindSimplePairs =0;
+
+
+
+
+btHashedSimplePairCache::btHashedSimplePairCache() {
+ int initialAllocatedSize= 2;
+ m_overlappingPairArray.reserve(initialAllocatedSize);
+ growTables();
+}
+
+
+
+
+btHashedSimplePairCache::~btHashedSimplePairCache()
+{
+}
+
+
+
+
+
+
+void btHashedSimplePairCache::removeAllPairs()
+{
+ m_overlappingPairArray.clear();
+ m_hashTable.clear();
+ m_next.clear();
+
+ int initialAllocatedSize= 2;
+ m_overlappingPairArray.reserve(initialAllocatedSize);
+ growTables();
+}
+
+
+
+btSimplePair* btHashedSimplePairCache::findPair(int indexA, int indexB)
+{
+ gFindSimplePairs++;
+
+
+ /*if (indexA > indexB)
+ btSwap(indexA, indexB);*/
+
+ int hash = static_cast<int>(getHash(static_cast<unsigned int>(indexA), static_cast<unsigned int>(indexB)) & (m_overlappingPairArray.capacity()-1));
+
+ if (hash >= m_hashTable.size())
+ {
+ return NULL;
+ }
+
+ int index = m_hashTable[hash];
+ while (index != BT_SIMPLE_NULL_PAIR && equalsPair(m_overlappingPairArray[index], indexA, indexB) == false)
+ {
+ index = m_next[index];
+ }
+
+ if (index == BT_SIMPLE_NULL_PAIR)
+ {
+ return NULL;
+ }
+
+ btAssert(index < m_overlappingPairArray.size());
+
+ return &m_overlappingPairArray[index];
+}
+
+//#include <stdio.h>
+
+void btHashedSimplePairCache::growTables()
+{
+
+ int newCapacity = m_overlappingPairArray.capacity();
+
+ if (m_hashTable.size() < newCapacity)
+ {
+ //grow hashtable and next table
+ int curHashtableSize = m_hashTable.size();
+
+ m_hashTable.resize(newCapacity);
+ m_next.resize(newCapacity);
+
+
+ int i;
+
+ for (i= 0; i < newCapacity; ++i)
+ {
+ m_hashTable[i] = BT_SIMPLE_NULL_PAIR;
+ }
+ for (i = 0; i < newCapacity; ++i)
+ {
+ m_next[i] = BT_SIMPLE_NULL_PAIR;
+ }
+
+ for(i=0;i<curHashtableSize;i++)
+ {
+
+ const btSimplePair& pair = m_overlappingPairArray[i];
+ int indexA = pair.m_indexA;
+ int indexB = pair.m_indexB;
+
+ int hashValue = static_cast<int>(getHash(static_cast<unsigned int>(indexA),static_cast<unsigned int>(indexB)) & (m_overlappingPairArray.capacity()-1)); // New hash value with new mask
+ m_next[i] = m_hashTable[hashValue];
+ m_hashTable[hashValue] = i;
+ }
+
+
+ }
+}
+
+btSimplePair* btHashedSimplePairCache::internalAddPair(int indexA, int indexB)
+{
+
+ int hash = static_cast<int>(getHash(static_cast<unsigned int>(indexA),static_cast<unsigned int>(indexB)) & (m_overlappingPairArray.capacity()-1)); // New hash value with new mask
+
+
+ btSimplePair* pair = internalFindPair(indexA, indexB, hash);
+ if (pair != NULL)
+ {
+ return pair;
+ }
+
+ int count = m_overlappingPairArray.size();
+ int oldCapacity = m_overlappingPairArray.capacity();
+ void* mem = &m_overlappingPairArray.expandNonInitializing();
+
+ int newCapacity = m_overlappingPairArray.capacity();
+
+ if (oldCapacity < newCapacity)
+ {
+ growTables();
+ //hash with new capacity
+ hash = static_cast<int>(getHash(static_cast<unsigned int>(indexA),static_cast<unsigned int>(indexB)) & (m_overlappingPairArray.capacity()-1));
+ }
+
+ pair = new (mem) btSimplePair(indexA,indexB);
+
+ pair->m_userPointer = 0;
+
+ m_next[count] = m_hashTable[hash];
+ m_hashTable[hash] = count;
+
+ return pair;
+}
+
+
+
+void* btHashedSimplePairCache::removeOverlappingPair(int indexA, int indexB)
+{
+ gRemoveSimplePairs++;
+
+
+ /*if (indexA > indexB)
+ btSwap(indexA, indexB);*/
+
+ int hash = static_cast<int>(getHash(static_cast<unsigned int>(indexA),static_cast<unsigned int>(indexB)) & (m_overlappingPairArray.capacity()-1));
+
+ btSimplePair* pair = internalFindPair(indexA, indexB, hash);
+ if (pair == NULL)
+ {
+ return 0;
+ }
+
+
+ void* userData = pair->m_userPointer;
+
+
+ int pairIndex = int(pair - &m_overlappingPairArray[0]);
+ btAssert(pairIndex < m_overlappingPairArray.size());
+
+ // Remove the pair from the hash table.
+ int index = m_hashTable[hash];
+ btAssert(index != BT_SIMPLE_NULL_PAIR);
+
+ int previous = BT_SIMPLE_NULL_PAIR;
+ while (index != pairIndex)
+ {
+ previous = index;
+ index = m_next[index];
+ }
+
+ if (previous != BT_SIMPLE_NULL_PAIR)
+ {
+ btAssert(m_next[previous] == pairIndex);
+ m_next[previous] = m_next[pairIndex];
+ }
+ else
+ {
+ m_hashTable[hash] = m_next[pairIndex];
+ }
+
+ // We now move the last pair into spot of the
+ // pair being removed. We need to fix the hash
+ // table indices to support the move.
+
+ int lastPairIndex = m_overlappingPairArray.size() - 1;
+
+ // If the removed pair is the last pair, we are done.
+ if (lastPairIndex == pairIndex)
+ {
+ m_overlappingPairArray.pop_back();
+ return userData;
+ }
+
+ // Remove the last pair from the hash table.
+ const btSimplePair* last = &m_overlappingPairArray[lastPairIndex];
+ /* missing swap here too, Nat. */
+ int lastHash = static_cast<int>(getHash(static_cast<unsigned int>(last->m_indexA), static_cast<unsigned int>(last->m_indexB)) & (m_overlappingPairArray.capacity()-1));
+
+ index = m_hashTable[lastHash];
+ btAssert(index != BT_SIMPLE_NULL_PAIR);
+
+ previous = BT_SIMPLE_NULL_PAIR;
+ while (index != lastPairIndex)
+ {
+ previous = index;
+ index = m_next[index];
+ }
+
+ if (previous != BT_SIMPLE_NULL_PAIR)
+ {
+ btAssert(m_next[previous] == lastPairIndex);
+ m_next[previous] = m_next[lastPairIndex];
+ }
+ else
+ {
+ m_hashTable[lastHash] = m_next[lastPairIndex];
+ }
+
+ // Copy the last pair into the remove pair's spot.
+ m_overlappingPairArray[pairIndex] = m_overlappingPairArray[lastPairIndex];
+
+ // Insert the last pair into the hash table
+ m_next[pairIndex] = m_hashTable[lastHash];
+ m_hashTable[lastHash] = pairIndex;
+
+ m_overlappingPairArray.pop_back();
+
+ return userData;
+}
+//#include <stdio.h>
+
+
+
+
+
+
+
+
+
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btHashedSimplePairCache.h b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btHashedSimplePairCache.h
new file mode 100644
index 0000000000..2aaf6201f3
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btHashedSimplePairCache.h
@@ -0,0 +1,172 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_HASHED_SIMPLE_PAIR_CACHE_H
+#define BT_HASHED_SIMPLE_PAIR_CACHE_H
+
+
+
+#include "LinearMath/btAlignedObjectArray.h"
+
+const int BT_SIMPLE_NULL_PAIR=0xffffffff;
+
+struct btSimplePair
+{
+ btSimplePair(int indexA,int indexB)
+ :m_indexA(indexA),
+ m_indexB(indexB),
+ m_userPointer(0)
+ {
+ }
+
+ int m_indexA;
+ int m_indexB;
+ union
+ {
+ void* m_userPointer;
+ int m_userValue;
+ };
+};
+
+typedef btAlignedObjectArray<btSimplePair> btSimplePairArray;
+
+
+
+extern int gOverlappingSimplePairs;
+extern int gRemoveSimplePairs;
+extern int gAddedSimplePairs;
+extern int gFindSimplePairs;
+
+
+
+
+class btHashedSimplePairCache
+{
+ btSimplePairArray m_overlappingPairArray;
+
+
+protected:
+
+ btAlignedObjectArray<int> m_hashTable;
+ btAlignedObjectArray<int> m_next;
+
+
+public:
+ btHashedSimplePairCache();
+ virtual ~btHashedSimplePairCache();
+
+ void removeAllPairs();
+
+ virtual void* removeOverlappingPair(int indexA,int indexB);
+
+ // Add a pair and return the new pair. If the pair already exists,
+ // no new pair is created and the old one is returned.
+ virtual btSimplePair* addOverlappingPair(int indexA,int indexB)
+ {
+ gAddedSimplePairs++;
+
+ return internalAddPair(indexA,indexB);
+ }
+
+
+ virtual btSimplePair* getOverlappingPairArrayPtr()
+ {
+ return &m_overlappingPairArray[0];
+ }
+
+ const btSimplePair* getOverlappingPairArrayPtr() const
+ {
+ return &m_overlappingPairArray[0];
+ }
+
+ btSimplePairArray& getOverlappingPairArray()
+ {
+ return m_overlappingPairArray;
+ }
+
+ const btSimplePairArray& getOverlappingPairArray() const
+ {
+ return m_overlappingPairArray;
+ }
+
+
+ btSimplePair* findPair(int indexA,int indexB);
+
+ int GetCount() const { return m_overlappingPairArray.size(); }
+
+ int getNumOverlappingPairs() const
+ {
+ return m_overlappingPairArray.size();
+ }
+private:
+
+ btSimplePair* internalAddPair(int indexA, int indexB);
+
+ void growTables();
+
+ SIMD_FORCE_INLINE bool equalsPair(const btSimplePair& pair, int indexA, int indexB)
+ {
+ return pair.m_indexA == indexA && pair.m_indexB == indexB;
+ }
+
+
+
+ SIMD_FORCE_INLINE unsigned int getHash(unsigned int indexA, unsigned int indexB)
+ {
+ unsigned int key = indexA | (indexB << 16);
+ // Thomas Wang's hash
+
+ key += ~(key << 15);
+ key ^= (key >> 10);
+ key += (key << 3);
+ key ^= (key >> 6);
+ key += ~(key << 11);
+ key ^= (key >> 16);
+ return key;
+ }
+
+
+
+
+
+ SIMD_FORCE_INLINE btSimplePair* internalFindPair(int proxyIdA , int proxyIdB, int hash)
+ {
+
+ int index = m_hashTable[hash];
+
+ while( index != BT_SIMPLE_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyIdA, proxyIdB) == false)
+ {
+ index = m_next[index];
+ }
+
+ if ( index == BT_SIMPLE_NULL_PAIR )
+ {
+ return NULL;
+ }
+
+ btAssert(index < m_overlappingPairArray.size());
+
+ return &m_overlappingPairArray[index];
+ }
+
+
+};
+
+
+
+
+#endif //BT_HASHED_SIMPLE_PAIR_CACHE_H
+
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp
new file mode 100644
index 0000000000..6cba442ca5
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp
@@ -0,0 +1,838 @@
+#include "btInternalEdgeUtility.h"
+
+#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h"
+#include "BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h"
+#include "BulletCollision/CollisionShapes/btTriangleShape.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/NarrowPhaseCollision/btManifoldPoint.h"
+#include "LinearMath/btIDebugDraw.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
+
+//#define DEBUG_INTERNAL_EDGE
+
+#ifdef DEBUG_INTERNAL_EDGE
+#include <stdio.h>
+#endif //DEBUG_INTERNAL_EDGE
+
+
+#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+static btIDebugDraw* gDebugDrawer = 0;
+
+void btSetDebugDrawer(btIDebugDraw* debugDrawer)
+{
+ gDebugDrawer = debugDrawer;
+}
+
+static void btDebugDrawLine(const btVector3& from,const btVector3& to, const btVector3& color)
+{
+ if (gDebugDrawer)
+ gDebugDrawer->drawLine(from,to,color);
+}
+#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
+
+
+static int btGetHash(int partId, int triangleIndex)
+{
+ int hash = (partId<<(31-MAX_NUM_PARTS_IN_BITS)) | triangleIndex;
+ return hash;
+}
+
+
+
+static btScalar btGetAngle(const btVector3& edgeA, const btVector3& normalA,const btVector3& normalB)
+{
+ const btVector3 refAxis0 = edgeA;
+ const btVector3 refAxis1 = normalA;
+ const btVector3 swingAxis = normalB;
+ btScalar angle = btAtan2(swingAxis.dot(refAxis0), swingAxis.dot(refAxis1));
+ return angle;
+}
+
+
+struct btConnectivityProcessor : public btTriangleCallback
+{
+ int m_partIdA;
+ int m_triangleIndexA;
+ btVector3* m_triangleVerticesA;
+ btTriangleInfoMap* m_triangleInfoMap;
+
+
+ virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
+ {
+ //skip self-collisions
+ if ((m_partIdA == partId) && (m_triangleIndexA == triangleIndex))
+ return;
+
+ //skip duplicates (disabled for now)
+ //if ((m_partIdA <= partId) && (m_triangleIndexA <= triangleIndex))
+ // return;
+
+ //search for shared vertices and edges
+ int numshared = 0;
+ int sharedVertsA[3]={-1,-1,-1};
+ int sharedVertsB[3]={-1,-1,-1};
+
+ ///skip degenerate triangles
+ btScalar crossBSqr = ((triangle[1]-triangle[0]).cross(triangle[2]-triangle[0])).length2();
+ if (crossBSqr < m_triangleInfoMap->m_equalVertexThreshold)
+ return;
+
+
+ btScalar crossASqr = ((m_triangleVerticesA[1]-m_triangleVerticesA[0]).cross(m_triangleVerticesA[2]-m_triangleVerticesA[0])).length2();
+ ///skip degenerate triangles
+ if (crossASqr< m_triangleInfoMap->m_equalVertexThreshold)
+ return;
+
+#if 0
+ printf("triangle A[0] = (%f,%f,%f)\ntriangle A[1] = (%f,%f,%f)\ntriangle A[2] = (%f,%f,%f)\n",
+ m_triangleVerticesA[0].getX(),m_triangleVerticesA[0].getY(),m_triangleVerticesA[0].getZ(),
+ m_triangleVerticesA[1].getX(),m_triangleVerticesA[1].getY(),m_triangleVerticesA[1].getZ(),
+ m_triangleVerticesA[2].getX(),m_triangleVerticesA[2].getY(),m_triangleVerticesA[2].getZ());
+
+ printf("partId=%d, triangleIndex=%d\n",partId,triangleIndex);
+ printf("triangle B[0] = (%f,%f,%f)\ntriangle B[1] = (%f,%f,%f)\ntriangle B[2] = (%f,%f,%f)\n",
+ triangle[0].getX(),triangle[0].getY(),triangle[0].getZ(),
+ triangle[1].getX(),triangle[1].getY(),triangle[1].getZ(),
+ triangle[2].getX(),triangle[2].getY(),triangle[2].getZ());
+#endif
+
+ for (int i=0;i<3;i++)
+ {
+ for (int j=0;j<3;j++)
+ {
+ if ( (m_triangleVerticesA[i]-triangle[j]).length2() < m_triangleInfoMap->m_equalVertexThreshold)
+ {
+ sharedVertsA[numshared] = i;
+ sharedVertsB[numshared] = j;
+ numshared++;
+ ///degenerate case
+ if(numshared >= 3)
+ return;
+ }
+ }
+ ///degenerate case
+ if(numshared >= 3)
+ return;
+ }
+ switch (numshared)
+ {
+ case 0:
+ {
+ break;
+ }
+ case 1:
+ {
+ //shared vertex
+ break;
+ }
+ case 2:
+ {
+ //shared edge
+ //we need to make sure the edge is in the order V2V0 and not V0V2 so that the signs are correct
+ if (sharedVertsA[0] == 0 && sharedVertsA[1] == 2)
+ {
+ sharedVertsA[0] = 2;
+ sharedVertsA[1] = 0;
+ int tmp = sharedVertsB[1];
+ sharedVertsB[1] = sharedVertsB[0];
+ sharedVertsB[0] = tmp;
+ }
+
+ int hash = btGetHash(m_partIdA,m_triangleIndexA);
+
+ btTriangleInfo* info = m_triangleInfoMap->find(hash);
+ if (!info)
+ {
+ btTriangleInfo tmp;
+ m_triangleInfoMap->insert(hash,tmp);
+ info = m_triangleInfoMap->find(hash);
+ }
+
+ int sumvertsA = sharedVertsA[0]+sharedVertsA[1];
+ int otherIndexA = 3-sumvertsA;
+
+
+ btVector3 edge(m_triangleVerticesA[sharedVertsA[1]]-m_triangleVerticesA[sharedVertsA[0]]);
+
+ btTriangleShape tA(m_triangleVerticesA[0],m_triangleVerticesA[1],m_triangleVerticesA[2]);
+ int otherIndexB = 3-(sharedVertsB[0]+sharedVertsB[1]);
+
+ btTriangleShape tB(triangle[sharedVertsB[1]],triangle[sharedVertsB[0]],triangle[otherIndexB]);
+ //btTriangleShape tB(triangle[0],triangle[1],triangle[2]);
+
+ btVector3 normalA;
+ btVector3 normalB;
+ tA.calcNormal(normalA);
+ tB.calcNormal(normalB);
+ edge.normalize();
+ btVector3 edgeCrossA = edge.cross(normalA).normalize();
+
+ {
+ btVector3 tmp = m_triangleVerticesA[otherIndexA]-m_triangleVerticesA[sharedVertsA[0]];
+ if (edgeCrossA.dot(tmp) < 0)
+ {
+ edgeCrossA*=-1;
+ }
+ }
+
+ btVector3 edgeCrossB = edge.cross(normalB).normalize();
+
+ {
+ btVector3 tmp = triangle[otherIndexB]-triangle[sharedVertsB[0]];
+ if (edgeCrossB.dot(tmp) < 0)
+ {
+ edgeCrossB*=-1;
+ }
+ }
+
+ btScalar angle2 = 0;
+ btScalar ang4 = 0.f;
+
+
+ btVector3 calculatedEdge = edgeCrossA.cross(edgeCrossB);
+ btScalar len2 = calculatedEdge.length2();
+
+ btScalar correctedAngle(0);
+ //btVector3 calculatedNormalB = normalA;
+ bool isConvex = false;
+
+ if (len2<m_triangleInfoMap->m_planarEpsilon)
+ {
+ angle2 = 0.f;
+ ang4 = 0.f;
+ } else
+ {
+
+ calculatedEdge.normalize();
+ btVector3 calculatedNormalA = calculatedEdge.cross(edgeCrossA);
+ calculatedNormalA.normalize();
+ angle2 = btGetAngle(calculatedNormalA,edgeCrossA,edgeCrossB);
+ ang4 = SIMD_PI-angle2;
+ btScalar dotA = normalA.dot(edgeCrossB);
+ ///@todo: check if we need some epsilon, due to floating point imprecision
+ isConvex = (dotA<0.);
+
+ correctedAngle = isConvex ? ang4 : -ang4;
+ }
+
+
+
+
+
+ //alternatively use
+ //btVector3 calculatedNormalB2 = quatRotate(orn,normalA);
+
+
+ switch (sumvertsA)
+ {
+ case 1:
+ {
+ btVector3 edge = m_triangleVerticesA[0]-m_triangleVerticesA[1];
+ btQuaternion orn(edge,-correctedAngle);
+ btVector3 computedNormalB = quatRotate(orn,normalA);
+ btScalar bla = computedNormalB.dot(normalB);
+ if (bla<0)
+ {
+ computedNormalB*=-1;
+ info->m_flags |= TRI_INFO_V0V1_SWAP_NORMALB;
+ }
+#ifdef DEBUG_INTERNAL_EDGE
+ if ((computedNormalB-normalB).length()>0.0001)
+ {
+ printf("warning: normals not identical\n");
+ }
+#endif//DEBUG_INTERNAL_EDGE
+
+ info->m_edgeV0V1Angle = -correctedAngle;
+
+ if (isConvex)
+ info->m_flags |= TRI_INFO_V0V1_CONVEX;
+ break;
+ }
+ case 2:
+ {
+ btVector3 edge = m_triangleVerticesA[2]-m_triangleVerticesA[0];
+ btQuaternion orn(edge,-correctedAngle);
+ btVector3 computedNormalB = quatRotate(orn,normalA);
+ if (computedNormalB.dot(normalB)<0)
+ {
+ computedNormalB*=-1;
+ info->m_flags |= TRI_INFO_V2V0_SWAP_NORMALB;
+ }
+
+#ifdef DEBUG_INTERNAL_EDGE
+ if ((computedNormalB-normalB).length()>0.0001)
+ {
+ printf("warning: normals not identical\n");
+ }
+#endif //DEBUG_INTERNAL_EDGE
+ info->m_edgeV2V0Angle = -correctedAngle;
+ if (isConvex)
+ info->m_flags |= TRI_INFO_V2V0_CONVEX;
+ break;
+ }
+ case 3:
+ {
+ btVector3 edge = m_triangleVerticesA[1]-m_triangleVerticesA[2];
+ btQuaternion orn(edge,-correctedAngle);
+ btVector3 computedNormalB = quatRotate(orn,normalA);
+ if (computedNormalB.dot(normalB)<0)
+ {
+ info->m_flags |= TRI_INFO_V1V2_SWAP_NORMALB;
+ computedNormalB*=-1;
+ }
+#ifdef DEBUG_INTERNAL_EDGE
+ if ((computedNormalB-normalB).length()>0.0001)
+ {
+ printf("warning: normals not identical\n");
+ }
+#endif //DEBUG_INTERNAL_EDGE
+ info->m_edgeV1V2Angle = -correctedAngle;
+
+ if (isConvex)
+ info->m_flags |= TRI_INFO_V1V2_CONVEX;
+ break;
+ }
+ }
+
+ break;
+ }
+ default:
+ {
+ // printf("warning: duplicate triangle\n");
+ }
+
+ }
+ }
+};
+/////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////
+
+void btGenerateInternalEdgeInfo (btBvhTriangleMeshShape*trimeshShape, btTriangleInfoMap* triangleInfoMap)
+{
+ //the user pointer shouldn't already be used for other purposes, we intend to store connectivity info there!
+ if (trimeshShape->getTriangleInfoMap())
+ return;
+
+ trimeshShape->setTriangleInfoMap(triangleInfoMap);
+
+ btStridingMeshInterface* meshInterface = trimeshShape->getMeshInterface();
+ const btVector3& meshScaling = meshInterface->getScaling();
+
+ for (int partId = 0; partId< meshInterface->getNumSubParts();partId++)
+ {
+ const unsigned char *vertexbase = 0;
+ int numverts = 0;
+ PHY_ScalarType type = PHY_INTEGER;
+ int stride = 0;
+ const unsigned char *indexbase = 0;
+ int indexstride = 0;
+ int numfaces = 0;
+ PHY_ScalarType indicestype = PHY_INTEGER;
+ //PHY_ScalarType indexType=0;
+
+ btVector3 triangleVerts[3];
+ meshInterface->getLockedReadOnlyVertexIndexBase(&vertexbase,numverts, type,stride,&indexbase,indexstride,numfaces,indicestype,partId);
+ btVector3 aabbMin,aabbMax;
+
+ for (int triangleIndex = 0 ; triangleIndex < numfaces;triangleIndex++)
+ {
+ unsigned int* gfxbase = (unsigned int*)(indexbase+triangleIndex*indexstride);
+
+ for (int j=2;j>=0;j--)
+ {
+
+ int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j];
+ if (type == PHY_FLOAT)
+ {
+ float* graphicsbase = (float*)(vertexbase+graphicsindex*stride);
+ triangleVerts[j] = btVector3(
+ graphicsbase[0]*meshScaling.getX(),
+ graphicsbase[1]*meshScaling.getY(),
+ graphicsbase[2]*meshScaling.getZ());
+ }
+ else
+ {
+ double* graphicsbase = (double*)(vertexbase+graphicsindex*stride);
+ triangleVerts[j] = btVector3( btScalar(graphicsbase[0]*meshScaling.getX()), btScalar(graphicsbase[1]*meshScaling.getY()), btScalar(graphicsbase[2]*meshScaling.getZ()));
+ }
+ }
+ 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(triangleVerts[0]);
+ aabbMax.setMax(triangleVerts[0]);
+ aabbMin.setMin(triangleVerts[1]);
+ aabbMax.setMax(triangleVerts[1]);
+ aabbMin.setMin(triangleVerts[2]);
+ aabbMax.setMax(triangleVerts[2]);
+
+ btConnectivityProcessor connectivityProcessor;
+ connectivityProcessor.m_partIdA = partId;
+ connectivityProcessor.m_triangleIndexA = triangleIndex;
+ connectivityProcessor.m_triangleVerticesA = &triangleVerts[0];
+ connectivityProcessor.m_triangleInfoMap = triangleInfoMap;
+
+ trimeshShape->processAllTriangles(&connectivityProcessor,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)
+{
+ btVector3 lineDelta = line1 - line0;
+
+ // Handle degenerate lines
+ if ( lineDelta.fuzzyZero())
+ {
+ nearestPoint = line0;
+ }
+ else
+ {
+ btScalar delta = (point-line0).dot(lineDelta) / (lineDelta).dot(lineDelta);
+
+ // Clamp the point to conform to the segment's endpoints
+ if ( delta < 0 )
+ delta = 0;
+ else if ( delta > 1 )
+ delta = 1;
+
+ nearestPoint = line0 + lineDelta*delta;
+ }
+}
+
+
+
+
+bool btClampNormal(const btVector3& edge,const btVector3& tri_normal_org,const btVector3& localContactNormalOnB, btScalar correctedEdgeAngle, btVector3 & clampedLocalNormal)
+{
+ btVector3 tri_normal = tri_normal_org;
+ //we only have a local triangle normal, not a local contact normal -> only normal in world space...
+ //either compute the current angle all in local space, or all in world space
+
+ btVector3 edgeCross = edge.cross(tri_normal).normalize();
+ btScalar curAngle = btGetAngle(edgeCross,tri_normal,localContactNormalOnB);
+
+ if (correctedEdgeAngle<0)
+ {
+ if (curAngle < correctedEdgeAngle)
+ {
+ btScalar diffAngle = correctedEdgeAngle-curAngle;
+ btQuaternion rotation(edge,diffAngle );
+ clampedLocalNormal = btMatrix3x3(rotation)*localContactNormalOnB;
+ return true;
+ }
+ }
+
+ if (correctedEdgeAngle>=0)
+ {
+ if (curAngle > correctedEdgeAngle)
+ {
+ btScalar diffAngle = correctedEdgeAngle-curAngle;
+ btQuaternion rotation(edge,diffAngle );
+ clampedLocalNormal = btMatrix3x3(rotation)*localContactNormalOnB;
+ return true;
+ }
+ }
+ return false;
+}
+
+
+
+/// Changes a btManifoldPoint collision normal to the normal from the mesh.
+void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObjectWrapper* colObj0Wrap,const btCollisionObjectWrapper* colObj1Wrap, int partId0, int index0, int normalAdjustFlags)
+{
+ //btAssert(colObj0->getCollisionShape()->getShapeType() == TRIANGLE_SHAPE_PROXYTYPE);
+ if (colObj0Wrap->getCollisionShape()->getShapeType() != TRIANGLE_SHAPE_PROXYTYPE)
+ return;
+
+ btBvhTriangleMeshShape* trimesh = 0;
+
+ if( colObj0Wrap->getCollisionObject()->getCollisionShape()->getShapeType() == SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE )
+ trimesh = ((btScaledBvhTriangleMeshShape*)colObj0Wrap->getCollisionObject()->getCollisionShape())->getChildShape();
+ else
+ trimesh = (btBvhTriangleMeshShape*)colObj0Wrap->getCollisionObject()->getCollisionShape();
+
+ btTriangleInfoMap* triangleInfoMapPtr = (btTriangleInfoMap*) trimesh->getTriangleInfoMap();
+ if (!triangleInfoMapPtr)
+ return;
+
+ int hash = btGetHash(partId0,index0);
+
+
+ btTriangleInfo* info = triangleInfoMapPtr->find(hash);
+ if (!info)
+ return;
+
+ btScalar frontFacing = (normalAdjustFlags & BT_TRIANGLE_CONVEX_BACKFACE_MODE)==0? 1.f : -1.f;
+
+ const btTriangleShape* tri_shape = static_cast<const btTriangleShape*>(colObj0Wrap->getCollisionShape());
+ btVector3 v0,v1,v2;
+ tri_shape->getVertex(0,v0);
+ tri_shape->getVertex(1,v1);
+ tri_shape->getVertex(2,v2);
+
+ //btVector3 center = (v0+v1+v2)*btScalar(1./3.);
+
+ btVector3 red(1,0,0), green(0,1,0),blue(0,0,1),white(1,1,1),black(0,0,0);
+ btVector3 tri_normal;
+ tri_shape->calcNormal(tri_normal);
+
+ //btScalar dot = tri_normal.dot(cp.m_normalWorldOnB);
+ btVector3 nearest;
+ btNearestPointInLineSegment(cp.m_localPointB,v0,v1,nearest);
+
+ btVector3 contact = cp.m_localPointB;
+#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+ const btTransform& tr = colObj0->getWorldTransform();
+ btDebugDrawLine(tr*nearest,tr*cp.m_localPointB,red);
+#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
+
+
+
+ bool isNearEdge = false;
+
+ int numConcaveEdgeHits = 0;
+ int numConvexEdgeHits = 0;
+
+ btVector3 localContactNormalOnB = colObj0Wrap->getWorldTransform().getBasis().transpose() * cp.m_normalWorldOnB;
+ localContactNormalOnB.normalize();//is this necessary?
+
+ // Get closest edge
+ int bestedge=-1;
+ btScalar disttobestedge=BT_LARGE_FLOAT;
+ //
+ // Edge 0 -> 1
+ if (btFabs(info->m_edgeV0V1Angle)< triangleInfoMapPtr->m_maxEdgeAngleThreshold)
+ {
+ btVector3 nearest;
+ btNearestPointInLineSegment( cp.m_localPointB, v0, v1, nearest );
+ btScalar len=(contact-nearest).length();
+ //
+ if( len < disttobestedge )
+ {
+ bestedge=0;
+ disttobestedge=len;
+ }
+ }
+ // Edge 1 -> 2
+ if (btFabs(info->m_edgeV1V2Angle)< triangleInfoMapPtr->m_maxEdgeAngleThreshold)
+ {
+ btVector3 nearest;
+ btNearestPointInLineSegment( cp.m_localPointB, v1, v2, nearest );
+ btScalar len=(contact-nearest).length();
+ //
+ if( len < disttobestedge )
+ {
+ bestedge=1;
+ disttobestedge=len;
+ }
+ }
+ // Edge 2 -> 0
+ if (btFabs(info->m_edgeV2V0Angle)< triangleInfoMapPtr->m_maxEdgeAngleThreshold)
+ {
+ btVector3 nearest;
+ btNearestPointInLineSegment( cp.m_localPointB, v2, v0, nearest );
+ btScalar len=(contact-nearest).length();
+ //
+ if( len < disttobestedge )
+ {
+ bestedge=2;
+ disttobestedge=len;
+ }
+ }
+
+#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+ btVector3 upfix=tri_normal * btVector3(0.1f,0.1f,0.1f);
+ btDebugDrawLine(tr * v0 + upfix, tr * v1 + upfix, red );
+#endif
+ if (btFabs(info->m_edgeV0V1Angle)< triangleInfoMapPtr->m_maxEdgeAngleThreshold)
+ {
+#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+ btDebugDrawLine(tr*contact,tr*(contact+cp.m_normalWorldOnB*10),black);
+#endif
+ btScalar len = (contact-nearest).length();
+ if(len<triangleInfoMapPtr->m_edgeDistanceThreshold)
+ if( bestedge==0 )
+ {
+ btVector3 edge(v0-v1);
+ isNearEdge = true;
+
+ if (info->m_edgeV0V1Angle==btScalar(0))
+ {
+ numConcaveEdgeHits++;
+ } else
+ {
+
+ bool isEdgeConvex = (info->m_flags & TRI_INFO_V0V1_CONVEX);
+ btScalar swapFactor = isEdgeConvex ? btScalar(1) : btScalar(-1);
+ #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+ btDebugDrawLine(tr*nearest,tr*(nearest+swapFactor*tri_normal*10),white);
+ #endif //BT_INTERNAL_EDGE_DEBUG_DRAW
+
+ btVector3 nA = swapFactor * tri_normal;
+
+ btQuaternion orn(edge,info->m_edgeV0V1Angle);
+ btVector3 computedNormalB = quatRotate(orn,tri_normal);
+ if (info->m_flags & TRI_INFO_V0V1_SWAP_NORMALB)
+ computedNormalB*=-1;
+ btVector3 nB = swapFactor*computedNormalB;
+
+ btScalar NdotA = localContactNormalOnB.dot(nA);
+ btScalar NdotB = localContactNormalOnB.dot(nB);
+ bool backFacingNormal = (NdotA< triangleInfoMapPtr->m_convexEpsilon) && (NdotB<triangleInfoMapPtr->m_convexEpsilon);
+
+#ifdef DEBUG_INTERNAL_EDGE
+ {
+
+ btDebugDrawLine(cp.getPositionWorldOnB(),cp.getPositionWorldOnB()+tr.getBasis()*(nB*20),red);
+ }
+#endif //DEBUG_INTERNAL_EDGE
+
+
+ if (backFacingNormal)
+ {
+ numConcaveEdgeHits++;
+ }
+ else
+ {
+ numConvexEdgeHits++;
+ btVector3 clampedLocalNormal;
+ bool isClamped = btClampNormal(edge,swapFactor*tri_normal,localContactNormalOnB, info->m_edgeV0V1Angle,clampedLocalNormal);
+ if (isClamped)
+ {
+ if (((normalAdjustFlags & BT_TRIANGLE_CONVEX_DOUBLE_SIDED)!=0) || (clampedLocalNormal.dot(frontFacing*tri_normal)>0))
+ {
+ btVector3 newNormal = colObj0Wrap->getWorldTransform().getBasis() * clampedLocalNormal;
+ // 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);
+
+ }
+ }
+ }
+ }
+ }
+ }
+
+ btNearestPointInLineSegment(contact,v1,v2,nearest);
+#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+ btDebugDrawLine(tr*nearest,tr*cp.m_localPointB,green);
+#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
+
+#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+ btDebugDrawLine(tr * v1 + upfix, tr * v2 + upfix , green );
+#endif
+
+ if (btFabs(info->m_edgeV1V2Angle)< triangleInfoMapPtr->m_maxEdgeAngleThreshold)
+ {
+#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+ btDebugDrawLine(tr*contact,tr*(contact+cp.m_normalWorldOnB*10),black);
+#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
+
+
+
+ btScalar len = (contact-nearest).length();
+ if(len<triangleInfoMapPtr->m_edgeDistanceThreshold)
+ if( bestedge==1 )
+ {
+ isNearEdge = true;
+#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+ btDebugDrawLine(tr*nearest,tr*(nearest+tri_normal*10),white);
+#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
+
+ btVector3 edge(v1-v2);
+
+ isNearEdge = true;
+
+ if (info->m_edgeV1V2Angle == btScalar(0))
+ {
+ numConcaveEdgeHits++;
+ } else
+ {
+ bool isEdgeConvex = (info->m_flags & TRI_INFO_V1V2_CONVEX)!=0;
+ btScalar swapFactor = isEdgeConvex ? btScalar(1) : btScalar(-1);
+ #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+ btDebugDrawLine(tr*nearest,tr*(nearest+swapFactor*tri_normal*10),white);
+ #endif //BT_INTERNAL_EDGE_DEBUG_DRAW
+
+ btVector3 nA = swapFactor * tri_normal;
+
+ btQuaternion orn(edge,info->m_edgeV1V2Angle);
+ btVector3 computedNormalB = quatRotate(orn,tri_normal);
+ if (info->m_flags & TRI_INFO_V1V2_SWAP_NORMALB)
+ computedNormalB*=-1;
+ btVector3 nB = swapFactor*computedNormalB;
+
+#ifdef DEBUG_INTERNAL_EDGE
+ {
+ btDebugDrawLine(cp.getPositionWorldOnB(),cp.getPositionWorldOnB()+tr.getBasis()*(nB*20),red);
+ }
+#endif //DEBUG_INTERNAL_EDGE
+
+
+ btScalar NdotA = localContactNormalOnB.dot(nA);
+ btScalar NdotB = localContactNormalOnB.dot(nB);
+ bool backFacingNormal = (NdotA< triangleInfoMapPtr->m_convexEpsilon) && (NdotB<triangleInfoMapPtr->m_convexEpsilon);
+
+ if (backFacingNormal)
+ {
+ numConcaveEdgeHits++;
+ }
+ else
+ {
+ numConvexEdgeHits++;
+ btVector3 localContactNormalOnB = colObj0Wrap->getWorldTransform().getBasis().transpose() * cp.m_normalWorldOnB;
+ btVector3 clampedLocalNormal;
+ bool isClamped = btClampNormal(edge,swapFactor*tri_normal,localContactNormalOnB, info->m_edgeV1V2Angle,clampedLocalNormal);
+ if (isClamped)
+ {
+ if (((normalAdjustFlags & BT_TRIANGLE_CONVEX_DOUBLE_SIDED)!=0) || (clampedLocalNormal.dot(frontFacing*tri_normal)>0))
+ {
+ btVector3 newNormal = colObj0Wrap->getWorldTransform().getBasis() * clampedLocalNormal;
+ // cp.m_distance1 = cp.m_distance1 * newNormal.dot(cp.m_normalWorldOnB);
+ cp.m_normalWorldOnB = newNormal;
+ // Reproject collision point along normal.
+ cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1;
+ cp.m_localPointB = colObj0Wrap->getWorldTransform().invXform(cp.m_positionWorldOnB);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ btNearestPointInLineSegment(contact,v2,v0,nearest);
+#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+ btDebugDrawLine(tr*nearest,tr*cp.m_localPointB,blue);
+#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
+#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+ btDebugDrawLine(tr * v2 + upfix, tr * v0 + upfix , blue );
+#endif
+
+ if (btFabs(info->m_edgeV2V0Angle)< triangleInfoMapPtr->m_maxEdgeAngleThreshold)
+ {
+
+#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+ btDebugDrawLine(tr*contact,tr*(contact+cp.m_normalWorldOnB*10),black);
+#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
+
+ btScalar len = (contact-nearest).length();
+ if(len<triangleInfoMapPtr->m_edgeDistanceThreshold)
+ if( bestedge==2 )
+ {
+ isNearEdge = true;
+#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+ btDebugDrawLine(tr*nearest,tr*(nearest+tri_normal*10),white);
+#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
+
+ btVector3 edge(v2-v0);
+
+ if (info->m_edgeV2V0Angle==btScalar(0))
+ {
+ numConcaveEdgeHits++;
+ } else
+ {
+
+ bool isEdgeConvex = (info->m_flags & TRI_INFO_V2V0_CONVEX)!=0;
+ btScalar swapFactor = isEdgeConvex ? btScalar(1) : btScalar(-1);
+ #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+ btDebugDrawLine(tr*nearest,tr*(nearest+swapFactor*tri_normal*10),white);
+ #endif //BT_INTERNAL_EDGE_DEBUG_DRAW
+
+ btVector3 nA = swapFactor * tri_normal;
+ btQuaternion orn(edge,info->m_edgeV2V0Angle);
+ btVector3 computedNormalB = quatRotate(orn,tri_normal);
+ if (info->m_flags & TRI_INFO_V2V0_SWAP_NORMALB)
+ computedNormalB*=-1;
+ btVector3 nB = swapFactor*computedNormalB;
+
+#ifdef DEBUG_INTERNAL_EDGE
+ {
+ btDebugDrawLine(cp.getPositionWorldOnB(),cp.getPositionWorldOnB()+tr.getBasis()*(nB*20),red);
+ }
+#endif //DEBUG_INTERNAL_EDGE
+
+ btScalar NdotA = localContactNormalOnB.dot(nA);
+ btScalar NdotB = localContactNormalOnB.dot(nB);
+ bool backFacingNormal = (NdotA< triangleInfoMapPtr->m_convexEpsilon) && (NdotB<triangleInfoMapPtr->m_convexEpsilon);
+
+ if (backFacingNormal)
+ {
+ numConcaveEdgeHits++;
+ }
+ else
+ {
+ numConvexEdgeHits++;
+ // printf("hitting convex edge\n");
+
+
+ btVector3 localContactNormalOnB = colObj0Wrap->getWorldTransform().getBasis().transpose() * cp.m_normalWorldOnB;
+ btVector3 clampedLocalNormal;
+ bool isClamped = btClampNormal(edge,swapFactor*tri_normal,localContactNormalOnB,info->m_edgeV2V0Angle,clampedLocalNormal);
+ if (isClamped)
+ {
+ if (((normalAdjustFlags & BT_TRIANGLE_CONVEX_DOUBLE_SIDED)!=0) || (clampedLocalNormal.dot(frontFacing*tri_normal)>0))
+ {
+ btVector3 newNormal = colObj0Wrap->getWorldTransform().getBasis() * clampedLocalNormal;
+ // cp.m_distance1 = cp.m_distance1 * newNormal.dot(cp.m_normalWorldOnB);
+ cp.m_normalWorldOnB = newNormal;
+ // Reproject collision point along normal.
+ cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1;
+ cp.m_localPointB = colObj0Wrap->getWorldTransform().invXform(cp.m_positionWorldOnB);
+ }
+ }
+ }
+ }
+
+
+ }
+ }
+
+#ifdef DEBUG_INTERNAL_EDGE
+ {
+ btVector3 color(0,1,1);
+ btDebugDrawLine(cp.getPositionWorldOnB(),cp.getPositionWorldOnB()+cp.m_normalWorldOnB*10,color);
+ }
+#endif //DEBUG_INTERNAL_EDGE
+
+ if (isNearEdge)
+ {
+
+ if (numConcaveEdgeHits>0)
+ {
+ if ((normalAdjustFlags & BT_TRIANGLE_CONCAVE_DOUBLE_SIDED)!=0)
+ {
+ //fix tri_normal so it pointing the same direction as the current local contact normal
+ if (tri_normal.dot(localContactNormalOnB) < 0)
+ {
+ tri_normal *= -1;
+ }
+ cp.m_normalWorldOnB = colObj0Wrap->getWorldTransform().getBasis()*tri_normal;
+ } else
+ {
+ btVector3 newNormal = tri_normal *frontFacing;
+ //if the tri_normal is pointing opposite direction as the current local contact normal, skip it
+ btScalar d = newNormal.dot(localContactNormalOnB) ;
+ if (d< 0)
+ {
+ return;
+ }
+ //modify the normal to be the triangle normal (or backfacing normal)
+ cp.m_normalWorldOnB = colObj0Wrap->getWorldTransform().getBasis() *newNormal;
+ }
+
+ // Reproject collision point along normal.
+ cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1;
+ cp.m_localPointB = colObj0Wrap->getWorldTransform().invXform(cp.m_positionWorldOnB);
+ }
+ }
+}
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h
new file mode 100644
index 0000000000..7d9aafeee6
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h
@@ -0,0 +1,47 @@
+
+#ifndef BT_INTERNAL_EDGE_UTILITY_H
+#define BT_INTERNAL_EDGE_UTILITY_H
+
+#include "LinearMath/btHashMap.h"
+#include "LinearMath/btVector3.h"
+
+#include "BulletCollision/CollisionShapes/btTriangleInfoMap.h"
+
+///The btInternalEdgeUtility helps to avoid or reduce artifacts due to wrong collision normals caused by internal edges.
+///See also http://code.google.com/p/bullet/issues/detail?id=27
+
+class btBvhTriangleMeshShape;
+class btCollisionObject;
+struct btCollisionObjectWrapper;
+class btManifoldPoint;
+class btIDebugDraw;
+
+
+
+enum btInternalEdgeAdjustFlags
+{
+ BT_TRIANGLE_CONVEX_BACKFACE_MODE = 1,
+ BT_TRIANGLE_CONCAVE_DOUBLE_SIDED = 2, //double sided options are experimental, single sided is recommended
+ BT_TRIANGLE_CONVEX_DOUBLE_SIDED = 4
+};
+
+
+///Call btGenerateInternalEdgeInfo to create triangle info, store in the shape 'userInfo'
+void btGenerateInternalEdgeInfo (btBvhTriangleMeshShape*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);
+
+///Enable the BT_INTERNAL_EDGE_DEBUG_DRAW define and call btSetDebugDrawer, to get visual info to see if the internal edge utility works properly.
+///If the utility doesn't work properly, you might have to adjust the threshold values in btTriangleInfoMap
+//#define BT_INTERNAL_EDGE_DEBUG_DRAW
+
+#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+void btSetDebugDrawer(btIDebugDraw* debugDrawer);
+#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
+
+
+#endif //BT_INTERNAL_EDGE_UTILITY_H
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp
new file mode 100644
index 0000000000..23c73c8825
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp
@@ -0,0 +1,207 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "btManifoldResult.h"
+#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
+
+///This is to allow MaterialCombiner/Custom Friction/Restitution values
+ContactAddedCallback gContactAddedCallback=0;
+
+CalculateCombinedCallback gCalculateCombinedRestitutionCallback = &btManifoldResult::calculateCombinedRestitution;
+CalculateCombinedCallback gCalculateCombinedFrictionCallback = &btManifoldResult::calculateCombinedFriction;
+CalculateCombinedCallback gCalculateCombinedRollingFrictionCallback = &btManifoldResult::calculateCombinedRollingFriction;
+CalculateCombinedCallback gCalculateCombinedSpinningFrictionCallback = &btManifoldResult::calculateCombinedSpinningFriction;
+CalculateCombinedCallback gCalculateCombinedContactDampingCallback = &btManifoldResult::calculateCombinedContactDamping;
+CalculateCombinedCallback gCalculateCombinedContactStiffnessCallback = &btManifoldResult::calculateCombinedContactStiffness;
+
+btScalar btManifoldResult::calculateCombinedRollingFriction(const btCollisionObject* body0,const btCollisionObject* body1)
+{
+ btScalar friction = body0->getRollingFriction() * body1->getFriction() + body1->getRollingFriction() * body0->getFriction();
+
+ const btScalar MAX_FRICTION = btScalar(10.);
+ if (friction < -MAX_FRICTION)
+ friction = -MAX_FRICTION;
+ if (friction > MAX_FRICTION)
+ friction = MAX_FRICTION;
+ return friction;
+
+}
+
+btScalar btManifoldResult::calculateCombinedSpinningFriction(const btCollisionObject* body0,const btCollisionObject* body1)
+{
+ btScalar friction = body0->getSpinningFriction() * body1->getFriction() + body1->getSpinningFriction() * body0->getFriction();
+
+ const btScalar MAX_FRICTION = btScalar(10.);
+ if (friction < -MAX_FRICTION)
+ friction = -MAX_FRICTION;
+ if (friction > MAX_FRICTION)
+ friction = MAX_FRICTION;
+ return friction;
+}
+
+///User can override this material combiner by implementing gContactAddedCallback and setting body0->m_collisionFlags |= btCollisionObject::customMaterialCallback;
+btScalar btManifoldResult::calculateCombinedFriction(const btCollisionObject* body0,const btCollisionObject* body1)
+{
+ btScalar friction = body0->getFriction() * body1->getFriction();
+
+ const btScalar MAX_FRICTION = btScalar(10.);
+ if (friction < -MAX_FRICTION)
+ friction = -MAX_FRICTION;
+ if (friction > MAX_FRICTION)
+ friction = MAX_FRICTION;
+ return friction;
+
+}
+
+btScalar btManifoldResult::calculateCombinedRestitution(const btCollisionObject* body0,const btCollisionObject* body1)
+{
+ return body0->getRestitution() * body1->getRestitution();
+}
+
+btScalar btManifoldResult::calculateCombinedContactDamping(const btCollisionObject* body0,const btCollisionObject* body1)
+{
+ return body0->getContactDamping() + body1->getContactDamping();
+}
+
+btScalar btManifoldResult::calculateCombinedContactStiffness(const btCollisionObject* body0,const btCollisionObject* body1)
+{
+
+ btScalar s0 = body0->getContactStiffness();
+ btScalar s1 = body1->getContactStiffness();
+
+ btScalar tmp0 = btScalar(1)/s0;
+ btScalar tmp1 = btScalar(1)/s1;
+ btScalar combinedStiffness = btScalar(1) / (tmp0+tmp1);
+ return combinedStiffness;
+}
+
+
+btManifoldResult::btManifoldResult(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
+ :m_manifoldPtr(0),
+ m_body0Wrap(body0Wrap),
+ m_body1Wrap(body1Wrap)
+#ifdef DEBUG_PART_INDEX
+ ,m_partId0(-1),
+ m_partId1(-1),
+ m_index0(-1),
+ m_index1(-1)
+#endif //DEBUG_PART_INDEX
+ , m_closestPointDistanceThreshold(0)
+{
+}
+
+
+void btManifoldResult::addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth)
+{
+ btAssert(m_manifoldPtr);
+ //order in manifold needs to match
+
+ if (depth > m_manifoldPtr->getContactBreakingThreshold())
+// if (depth > m_manifoldPtr->getContactProcessingThreshold())
+ return;
+
+ bool isSwapped = m_manifoldPtr->getBody0() != m_body0Wrap->getCollisionObject();
+ bool isNewCollision = m_manifoldPtr->getNumContacts() == 0;
+
+ btVector3 pointA = pointInWorld + normalOnBInWorld * depth;
+
+ btVector3 localA;
+ btVector3 localB;
+
+ if (isSwapped)
+ {
+ localA = m_body1Wrap->getCollisionObject()->getWorldTransform().invXform(pointA );
+ localB = m_body0Wrap->getCollisionObject()->getWorldTransform().invXform(pointInWorld);
+ } else
+ {
+ localA = m_body0Wrap->getCollisionObject()->getWorldTransform().invXform(pointA );
+ localB = m_body1Wrap->getCollisionObject()->getWorldTransform().invXform(pointInWorld);
+ }
+
+ btManifoldPoint newPt(localA,localB,normalOnBInWorld,depth);
+ newPt.m_positionWorldOnA = pointA;
+ newPt.m_positionWorldOnB = pointInWorld;
+
+ int insertIndex = m_manifoldPtr->getCacheEntry(newPt);
+
+ newPt.m_combinedFriction = gCalculateCombinedFrictionCallback(m_body0Wrap->getCollisionObject(),m_body1Wrap->getCollisionObject());
+ newPt.m_combinedRestitution = gCalculateCombinedRestitutionCallback(m_body0Wrap->getCollisionObject(),m_body1Wrap->getCollisionObject());
+ newPt.m_combinedRollingFriction = gCalculateCombinedRollingFrictionCallback(m_body0Wrap->getCollisionObject(),m_body1Wrap->getCollisionObject());
+ newPt.m_combinedSpinningFriction = gCalculateCombinedSpinningFrictionCallback(m_body0Wrap->getCollisionObject(),m_body1Wrap->getCollisionObject());
+
+ if ( (m_body0Wrap->getCollisionObject()->getCollisionFlags()& btCollisionObject::CF_HAS_CONTACT_STIFFNESS_DAMPING) ||
+ (m_body1Wrap->getCollisionObject()->getCollisionFlags()& btCollisionObject::CF_HAS_CONTACT_STIFFNESS_DAMPING))
+ {
+ newPt.m_combinedContactDamping1 = gCalculateCombinedContactDampingCallback(m_body0Wrap->getCollisionObject(),m_body1Wrap->getCollisionObject());
+ newPt.m_combinedContactStiffness1 = gCalculateCombinedContactStiffnessCallback(m_body0Wrap->getCollisionObject(),m_body1Wrap->getCollisionObject());
+ newPt.m_contactPointFlags |= BT_CONTACT_FLAG_CONTACT_STIFFNESS_DAMPING;
+ }
+
+ if ( (m_body0Wrap->getCollisionObject()->getCollisionFlags()& btCollisionObject::CF_HAS_FRICTION_ANCHOR) ||
+ (m_body1Wrap->getCollisionObject()->getCollisionFlags()& btCollisionObject::CF_HAS_FRICTION_ANCHOR))
+ {
+ newPt.m_contactPointFlags |= BT_CONTACT_FLAG_FRICTION_ANCHOR;
+ }
+
+ btPlaneSpace1(newPt.m_normalWorldOnB,newPt.m_lateralFrictionDir1,newPt.m_lateralFrictionDir2);
+
+
+
+ //BP mod, store contact triangles.
+ if (isSwapped)
+ {
+ newPt.m_partId0 = m_partId1;
+ newPt.m_partId1 = m_partId0;
+ newPt.m_index0 = m_index1;
+ newPt.m_index1 = m_index0;
+ } else
+ {
+ newPt.m_partId0 = m_partId0;
+ newPt.m_partId1 = m_partId1;
+ newPt.m_index0 = m_index0;
+ newPt.m_index1 = m_index1;
+ }
+ //printf("depth=%f\n",depth);
+ ///@todo, check this for any side effects
+ if (insertIndex >= 0)
+ {
+ //const btManifoldPoint& oldPoint = m_manifoldPtr->getContactPoint(insertIndex);
+ m_manifoldPtr->replaceContactPoint(newPt,insertIndex);
+ } else
+ {
+ insertIndex = m_manifoldPtr->addManifoldPoint(newPt);
+ }
+
+ //User can override friction and/or restitution
+ if (gContactAddedCallback &&
+ //and if either of the two bodies requires custom material
+ ((m_body0Wrap->getCollisionObject()->getCollisionFlags() & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK) ||
+ (m_body1Wrap->getCollisionObject()->getCollisionFlags() & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK)))
+ {
+ //experimental feature info, for per-triangle material etc.
+ const btCollisionObjectWrapper* obj0Wrap = isSwapped? m_body1Wrap : m_body0Wrap;
+ const btCollisionObjectWrapper* obj1Wrap = isSwapped? m_body0Wrap : m_body1Wrap;
+ (*gContactAddedCallback)(m_manifoldPtr->getContactPoint(insertIndex),obj0Wrap,newPt.m_partId0,newPt.m_index0,obj1Wrap,newPt.m_partId1,newPt.m_index1);
+ }
+
+ if (gContactStartedCallback && isNewCollision)
+ {
+ gContactStartedCallback(m_manifoldPtr);
+ }
+}
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btManifoldResult.h b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btManifoldResult.h
new file mode 100644
index 0000000000..12cdafd1b6
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btManifoldResult.h
@@ -0,0 +1,167 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#ifndef BT_MANIFOLD_RESULT_H
+#define BT_MANIFOLD_RESULT_H
+
+class btCollisionObject;
+struct btCollisionObjectWrapper;
+
+#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
+class btManifoldPoint;
+
+#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
+
+#include "LinearMath/btTransform.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+
+typedef bool (*ContactAddedCallback)(btManifoldPoint& cp, const btCollisionObjectWrapper* colObj0Wrap,int partId0,int index0,const btCollisionObjectWrapper* colObj1Wrap,int partId1,int index1);
+extern ContactAddedCallback gContactAddedCallback;
+
+//#define DEBUG_PART_INDEX 1
+
+/// These callbacks are used to customize the algorith that combine restitution, friction, damping, Stiffness
+typedef btScalar (*CalculateCombinedCallback)(const btCollisionObject* body0,const btCollisionObject* body1);
+
+extern CalculateCombinedCallback gCalculateCombinedRestitutionCallback;
+extern CalculateCombinedCallback gCalculateCombinedFrictionCallback;
+extern CalculateCombinedCallback gCalculateCombinedRollingFrictionCallback;
+extern CalculateCombinedCallback gCalculateCombinedSpinningFrictionCallback;
+extern CalculateCombinedCallback gCalculateCombinedContactDampingCallback;
+extern CalculateCombinedCallback gCalculateCombinedContactStiffnessCallback;
+
+///btManifoldResult is a helper class to manage contact results.
+class btManifoldResult : public btDiscreteCollisionDetectorInterface::Result
+{
+protected:
+
+ btPersistentManifold* m_manifoldPtr;
+
+ const btCollisionObjectWrapper* m_body0Wrap;
+ const btCollisionObjectWrapper* m_body1Wrap;
+ int m_partId0;
+ int m_partId1;
+ int m_index0;
+ int m_index1;
+
+
+public:
+
+ btManifoldResult()
+ :
+#ifdef DEBUG_PART_INDEX
+
+ m_partId0(-1),
+ m_partId1(-1),
+ m_index0(-1),
+ m_index1(-1)
+#endif //DEBUG_PART_INDEX
+ m_closestPointDistanceThreshold(0)
+ {
+ }
+
+ btManifoldResult(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap);
+
+ virtual ~btManifoldResult() {};
+
+ void setPersistentManifold(btPersistentManifold* manifoldPtr)
+ {
+ m_manifoldPtr = manifoldPtr;
+ }
+
+ const btPersistentManifold* getPersistentManifold() const
+ {
+ return m_manifoldPtr;
+ }
+ btPersistentManifold* getPersistentManifold()
+ {
+ return m_manifoldPtr;
+ }
+
+ virtual void setShapeIdentifiersA(int partId0,int index0)
+ {
+ m_partId0=partId0;
+ m_index0=index0;
+ }
+
+ virtual void setShapeIdentifiersB( int partId1,int index1)
+ {
+ m_partId1=partId1;
+ m_index1=index1;
+ }
+
+
+ virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth);
+
+ SIMD_FORCE_INLINE void refreshContactPoints()
+ {
+ btAssert(m_manifoldPtr);
+ if (!m_manifoldPtr->getNumContacts())
+ return;
+
+ bool isSwapped = m_manifoldPtr->getBody0() != m_body0Wrap->getCollisionObject();
+
+ if (isSwapped)
+ {
+ m_manifoldPtr->refreshContactPoints(m_body1Wrap->getCollisionObject()->getWorldTransform(),m_body0Wrap->getCollisionObject()->getWorldTransform());
+ } else
+ {
+ m_manifoldPtr->refreshContactPoints(m_body0Wrap->getCollisionObject()->getWorldTransform(),m_body1Wrap->getCollisionObject()->getWorldTransform());
+ }
+ }
+
+ const btCollisionObjectWrapper* getBody0Wrap() const
+ {
+ return m_body0Wrap;
+ }
+ const btCollisionObjectWrapper* getBody1Wrap() const
+ {
+ return m_body1Wrap;
+ }
+
+ void setBody0Wrap(const btCollisionObjectWrapper* obj0Wrap)
+ {
+ m_body0Wrap = obj0Wrap;
+ }
+
+ void setBody1Wrap(const btCollisionObjectWrapper* obj1Wrap)
+ {
+ m_body1Wrap = obj1Wrap;
+ }
+
+ const btCollisionObject* getBody0Internal() const
+ {
+ return m_body0Wrap->getCollisionObject();
+ }
+
+ const btCollisionObject* getBody1Internal() const
+ {
+ return m_body1Wrap->getCollisionObject();
+ }
+
+ btScalar m_closestPointDistanceThreshold;
+
+ /// in the future we can let the user override the methods to combine restitution and friction
+ static btScalar calculateCombinedRestitution(const btCollisionObject* body0,const btCollisionObject* body1);
+ static btScalar calculateCombinedFriction(const btCollisionObject* body0,const btCollisionObject* body1);
+ static btScalar calculateCombinedRollingFriction(const btCollisionObject* body0,const btCollisionObject* body1);
+ static btScalar calculateCombinedSpinningFriction(const btCollisionObject* body0,const btCollisionObject* body1);
+ static btScalar calculateCombinedContactDamping(const btCollisionObject* body0,const btCollisionObject* body1);
+ static btScalar calculateCombinedContactStiffness(const btCollisionObject* body0,const btCollisionObject* body1);
+};
+
+#endif //BT_MANIFOLD_RESULT_H
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp
new file mode 100644
index 0000000000..1344782257
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp
@@ -0,0 +1,450 @@
+
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "LinearMath/btScalar.h"
+#include "btSimulationIslandManager.h"
+#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
+#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/CollisionDispatch/btCollisionWorld.h"
+
+//#include <stdio.h>
+#include "LinearMath/btQuickprof.h"
+
+btSimulationIslandManager::btSimulationIslandManager():
+m_splitIslands(true)
+{
+}
+
+btSimulationIslandManager::~btSimulationIslandManager()
+{
+}
+
+
+void btSimulationIslandManager::initUnionFind(int n)
+{
+ m_unionFind.reset(n);
+}
+
+
+void btSimulationIslandManager::findUnions(btDispatcher* /* dispatcher */,btCollisionWorld* colWorld)
+{
+
+ {
+ btOverlappingPairCache* pairCachePtr = colWorld->getPairCache();
+ const int numOverlappingPairs = pairCachePtr->getNumOverlappingPairs();
+ if (numOverlappingPairs)
+ {
+ btBroadphasePair* pairPtr = pairCachePtr->getOverlappingPairArrayPtr();
+
+ for (int i=0;i<numOverlappingPairs;i++)
+ {
+ const btBroadphasePair& collisionPair = pairPtr[i];
+ btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
+ btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;
+
+ if (((colObj0) && ((colObj0)->mergesSimulationIslands())) &&
+ ((colObj1) && ((colObj1)->mergesSimulationIslands())))
+ {
+
+ m_unionFind.unite((colObj0)->getIslandTag(),
+ (colObj1)->getIslandTag());
+ }
+ }
+ }
+ }
+}
+
+#ifdef STATIC_SIMULATION_ISLAND_OPTIMIZATION
+void btSimulationIslandManager::updateActivationState(btCollisionWorld* colWorld,btDispatcher* dispatcher)
+{
+
+ // put the index into m_controllers into m_tag
+ int index = 0;
+ {
+
+ int i;
+ for (i=0;i<colWorld->getCollisionObjectArray().size(); i++)
+ {
+ btCollisionObject* collisionObject= colWorld->getCollisionObjectArray()[i];
+ //Adding filtering here
+ if (!collisionObject->isStaticOrKinematicObject())
+ {
+ collisionObject->setIslandTag(index++);
+ }
+ collisionObject->setCompanionId(-1);
+ collisionObject->setHitFraction(btScalar(1.));
+ }
+ }
+ // do the union find
+
+ initUnionFind( index );
+
+ findUnions(dispatcher,colWorld);
+}
+
+void btSimulationIslandManager::storeIslandActivationState(btCollisionWorld* colWorld)
+{
+ // put the islandId ('find' value) into m_tag
+ {
+ int index = 0;
+ int i;
+ for (i=0;i<colWorld->getCollisionObjectArray().size();i++)
+ {
+ btCollisionObject* collisionObject= colWorld->getCollisionObjectArray()[i];
+ if (!collisionObject->isStaticOrKinematicObject())
+ {
+ collisionObject->setIslandTag( m_unionFind.find(index) );
+ //Set the correct object offset in Collision Object Array
+ m_unionFind.getElement(index).m_sz = i;
+ collisionObject->setCompanionId(-1);
+ index++;
+ } else
+ {
+ collisionObject->setIslandTag(-1);
+ collisionObject->setCompanionId(-2);
+ }
+ }
+ }
+}
+
+
+#else //STATIC_SIMULATION_ISLAND_OPTIMIZATION
+void btSimulationIslandManager::updateActivationState(btCollisionWorld* colWorld,btDispatcher* dispatcher)
+{
+
+ initUnionFind( int (colWorld->getCollisionObjectArray().size()));
+
+ // put the index into m_controllers into m_tag
+ {
+
+ int index = 0;
+ int i;
+ for (i=0;i<colWorld->getCollisionObjectArray().size(); i++)
+ {
+ btCollisionObject* collisionObject= colWorld->getCollisionObjectArray()[i];
+ collisionObject->setIslandTag(index);
+ collisionObject->setCompanionId(-1);
+ collisionObject->setHitFraction(btScalar(1.));
+ index++;
+
+ }
+ }
+ // do the union find
+
+ findUnions(dispatcher,colWorld);
+}
+
+void btSimulationIslandManager::storeIslandActivationState(btCollisionWorld* colWorld)
+{
+ // put the islandId ('find' value) into m_tag
+ {
+
+
+ int index = 0;
+ int i;
+ for (i=0;i<colWorld->getCollisionObjectArray().size();i++)
+ {
+ btCollisionObject* collisionObject= colWorld->getCollisionObjectArray()[i];
+ if (!collisionObject->isStaticOrKinematicObject())
+ {
+ collisionObject->setIslandTag( m_unionFind.find(index) );
+ collisionObject->setCompanionId(-1);
+ } else
+ {
+ collisionObject->setIslandTag(-1);
+ collisionObject->setCompanionId(-2);
+ }
+ index++;
+ }
+ }
+}
+
+#endif //STATIC_SIMULATION_ISLAND_OPTIMIZATION
+
+inline int getIslandId(const btPersistentManifold* lhs)
+{
+ int islandId;
+ const btCollisionObject* rcolObj0 = static_cast<const btCollisionObject*>(lhs->getBody0());
+ const btCollisionObject* rcolObj1 = static_cast<const btCollisionObject*>(lhs->getBody1());
+ islandId= rcolObj0->getIslandTag()>=0?rcolObj0->getIslandTag():rcolObj1->getIslandTag();
+ return islandId;
+
+}
+
+
+
+/// function object that routes calls to operator<
+class btPersistentManifoldSortPredicate
+{
+ public:
+
+ SIMD_FORCE_INLINE bool operator() ( const btPersistentManifold* lhs, const btPersistentManifold* rhs ) const
+ {
+ return getIslandId(lhs) < getIslandId(rhs);
+ }
+};
+
+
+void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher,btCollisionWorld* collisionWorld)
+{
+
+ BT_PROFILE("islandUnionFindAndQuickSort");
+
+ btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray();
+
+ m_islandmanifold.resize(0);
+
+ //we are going to sort the unionfind array, and store the element id in the size
+ //afterwards, we clean unionfind, to make sure no-one uses it anymore
+
+ getUnionFind().sortIslands();
+ int numElem = getUnionFind().getNumElements();
+
+ int endIslandIndex=1;
+ int startIslandIndex;
+
+
+ //update the sleeping state for bodies, if all are sleeping
+ for ( startIslandIndex=0;startIslandIndex<numElem;startIslandIndex = endIslandIndex)
+ {
+ int islandId = getUnionFind().getElement(startIslandIndex).m_id;
+ for (endIslandIndex = startIslandIndex+1;(endIslandIndex<numElem) && (getUnionFind().getElement(endIslandIndex).m_id == islandId);endIslandIndex++)
+ {
+ }
+
+ //int numSleeping = 0;
+
+ bool allSleeping = true;
+
+ int idx;
+ for (idx=startIslandIndex;idx<endIslandIndex;idx++)
+ {
+ int i = getUnionFind().getElement(idx).m_sz;
+
+ btCollisionObject* colObj0 = collisionObjects[i];
+ if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
+ {
+// printf("error in island management\n");
+ }
+
+ btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
+ if (colObj0->getIslandTag() == islandId)
+ {
+ if (colObj0->getActivationState()== ACTIVE_TAG)
+ {
+ allSleeping = false;
+ }
+ if (colObj0->getActivationState()== DISABLE_DEACTIVATION)
+ {
+ allSleeping = false;
+ }
+ }
+ }
+
+
+ if (allSleeping)
+ {
+ int idx;
+ for (idx=startIslandIndex;idx<endIslandIndex;idx++)
+ {
+ int i = getUnionFind().getElement(idx).m_sz;
+ btCollisionObject* colObj0 = collisionObjects[i];
+ if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
+ {
+// printf("error in island management\n");
+ }
+
+ btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
+
+ if (colObj0->getIslandTag() == islandId)
+ {
+ colObj0->setActivationState( ISLAND_SLEEPING );
+ }
+ }
+ } else
+ {
+
+ int idx;
+ for (idx=startIslandIndex;idx<endIslandIndex;idx++)
+ {
+ int i = getUnionFind().getElement(idx).m_sz;
+
+ btCollisionObject* colObj0 = collisionObjects[i];
+ if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
+ {
+// printf("error in island management\n");
+ }
+
+ btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
+
+ if (colObj0->getIslandTag() == islandId)
+ {
+ if ( colObj0->getActivationState() == ISLAND_SLEEPING)
+ {
+ colObj0->setActivationState( WANTS_DEACTIVATION);
+ colObj0->setDeactivationTime(0.f);
+ }
+ }
+ }
+ }
+ }
+
+
+ int i;
+ int maxNumManifolds = dispatcher->getNumManifolds();
+
+//#define SPLIT_ISLANDS 1
+//#ifdef SPLIT_ISLANDS
+
+
+//#endif //SPLIT_ISLANDS
+
+
+ for (i=0;i<maxNumManifolds ;i++)
+ {
+ btPersistentManifold* manifold = dispatcher->getManifoldByIndexInternal(i);
+
+ const btCollisionObject* colObj0 = static_cast<const btCollisionObject*>(manifold->getBody0());
+ const btCollisionObject* colObj1 = static_cast<const btCollisionObject*>(manifold->getBody1());
+
+ ///@todo: check sleeping conditions!
+ if (((colObj0) && colObj0->getActivationState() != ISLAND_SLEEPING) ||
+ ((colObj1) && colObj1->getActivationState() != ISLAND_SLEEPING))
+ {
+
+ //kinematic objects don't merge islands, but wake up all connected objects
+ if (colObj0->isKinematicObject() && colObj0->getActivationState() != ISLAND_SLEEPING)
+ {
+ if (colObj0->hasContactResponse())
+ colObj1->activate();
+ }
+ if (colObj1->isKinematicObject() && colObj1->getActivationState() != ISLAND_SLEEPING)
+ {
+ if (colObj1->hasContactResponse())
+ colObj0->activate();
+ }
+ if(m_splitIslands)
+ {
+ //filtering for response
+ if (dispatcher->needsResponse(colObj0,colObj1))
+ m_islandmanifold.push_back(manifold);
+ }
+ }
+ }
+}
+
+
+
+///@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);
+
+ int endIslandIndex=1;
+ int startIslandIndex;
+ int numElem = getUnionFind().getNumElements();
+
+ BT_PROFILE("processIslands");
+
+ if(!m_splitIslands)
+ {
+ btPersistentManifold** manifold = dispatcher->getInternalManifoldPointer();
+ int maxNumManifolds = dispatcher->getNumManifolds();
+ callback->processIsland(&collisionObjects[0],collisionObjects.size(),manifold,maxNumManifolds, -1);
+ }
+ else
+ {
+ // Sort manifolds, based on islands
+ // Sort the vector using predicate and std::sort
+ //std::sort(islandmanifold.begin(), islandmanifold.end(), btPersistentManifoldSortPredicate);
+
+ int numManifolds = int (m_islandmanifold.size());
+
+ //tried a radix sort, but quicksort/heapsort seems still faster
+ //@todo rewrite island management
+ m_islandmanifold.quickSort(btPersistentManifoldSortPredicate());
+ //m_islandmanifold.heapSort(btPersistentManifoldSortPredicate());
+
+ //now process all active islands (sets of manifolds for now)
+
+ int startManifoldIndex = 0;
+ int endManifoldIndex = 1;
+
+ //int islandId;
+
+
+
+ // printf("Start Islands\n");
+
+ //traverse the simulation islands, and call the solver, unless all objects are sleeping/deactivated
+ for ( startIslandIndex=0;startIslandIndex<numElem;startIslandIndex = endIslandIndex)
+ {
+ int islandId = getUnionFind().getElement(startIslandIndex).m_id;
+
+
+ bool islandSleeping = true;
+
+ for (endIslandIndex = startIslandIndex;(endIslandIndex<numElem) && (getUnionFind().getElement(endIslandIndex).m_id == islandId);endIslandIndex++)
+ {
+ int i = getUnionFind().getElement(endIslandIndex).m_sz;
+ btCollisionObject* colObj0 = collisionObjects[i];
+ m_islandBodies.push_back(colObj0);
+ if (colObj0->isActive())
+ islandSleeping = false;
+ }
+
+
+ //find the accompanying contact manifold for this islandId
+ int numIslandManifolds = 0;
+ btPersistentManifold** startManifold = 0;
+
+ if (startManifoldIndex<numManifolds)
+ {
+ int curIslandId = getIslandId(m_islandmanifold[startManifoldIndex]);
+ if (curIslandId == islandId)
+ {
+ startManifold = &m_islandmanifold[startManifoldIndex];
+
+ for (endManifoldIndex = startManifoldIndex+1;(endManifoldIndex<numManifolds) && (islandId == getIslandId(m_islandmanifold[endManifoldIndex]));endManifoldIndex++)
+ {
+
+ }
+ /// Process the actual simulation, only if not sleeping/deactivated
+ numIslandManifolds = endManifoldIndex-startManifoldIndex;
+ }
+
+ }
+
+ if (!islandSleeping)
+ {
+ callback->processIsland(&m_islandBodies[0],m_islandBodies.size(),startManifold,numIslandManifolds, islandId);
+ // printf("Island callback of size:%d bodies, %d manifolds\n",islandBodies.size(),numIslandManifolds);
+ }
+
+ if (numIslandManifolds)
+ {
+ startManifoldIndex = endManifoldIndex;
+ }
+
+ m_islandBodies.resize(0);
+ }
+ } // else if(!splitIslands)
+
+}
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h
new file mode 100644
index 0000000000..e24c6afeca
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h
@@ -0,0 +1,81 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_SIMULATION_ISLAND_MANAGER_H
+#define BT_SIMULATION_ISLAND_MANAGER_H
+
+#include "BulletCollision/CollisionDispatch/btUnionFind.h"
+#include "btCollisionCreateFunc.h"
+#include "LinearMath/btAlignedObjectArray.h"
+#include "btCollisionObject.h"
+
+class btCollisionObject;
+class btCollisionWorld;
+class btDispatcher;
+class btPersistentManifold;
+
+
+///SimulationIslandManager creates and handles simulation islands, using btUnionFind
+class btSimulationIslandManager
+{
+ btUnionFind m_unionFind;
+
+ btAlignedObjectArray<btPersistentManifold*> m_islandmanifold;
+ btAlignedObjectArray<btCollisionObject* > m_islandBodies;
+
+ bool m_splitIslands;
+
+public:
+ btSimulationIslandManager();
+ virtual ~btSimulationIslandManager();
+
+
+ void initUnionFind(int n);
+
+
+ btUnionFind& getUnionFind() { return m_unionFind;}
+
+ virtual void updateActivationState(btCollisionWorld* colWorld,btDispatcher* dispatcher);
+ virtual void storeIslandActivationState(btCollisionWorld* world);
+
+
+ void findUnions(btDispatcher* dispatcher,btCollisionWorld* colWorld);
+
+
+
+ struct IslandCallback
+ {
+ virtual ~IslandCallback() {};
+
+ virtual void processIsland(btCollisionObject** bodies,int numBodies,class btPersistentManifold** manifolds,int numManifolds, int islandId) = 0;
+ };
+
+ void buildAndProcessIslands(btDispatcher* dispatcher,btCollisionWorld* collisionWorld, IslandCallback* callback);
+
+ void buildIslands(btDispatcher* dispatcher,btCollisionWorld* colWorld);
+
+ bool getSplitIslands()
+ {
+ return m_splitIslands;
+ }
+ void setSplitIslands(bool doSplitIslands)
+ {
+ m_splitIslands = doSplitIslands;
+ }
+
+};
+
+#endif //BT_SIMULATION_ISLAND_MANAGER_H
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp
new file mode 100644
index 0000000000..e8b567e0ef
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp
@@ -0,0 +1,214 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btSphereBoxCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"
+#include "BulletCollision/CollisionShapes/btBoxShape.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
+//#include <stdio.h>
+
+btSphereBoxCollisionAlgorithm::btSphereBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* col0Wrap,const btCollisionObjectWrapper* col1Wrap, bool isSwapped)
+: btActivatingCollisionAlgorithm(ci,col0Wrap,col1Wrap),
+m_ownManifold(false),
+m_manifoldPtr(mf),
+m_isSwapped(isSwapped)
+{
+ const btCollisionObjectWrapper* sphereObjWrap = m_isSwapped? col1Wrap : col0Wrap;
+ const btCollisionObjectWrapper* boxObjWrap = m_isSwapped? col0Wrap : col1Wrap;
+
+ if (!m_manifoldPtr && m_dispatcher->needsCollision(sphereObjWrap->getCollisionObject(),boxObjWrap->getCollisionObject()))
+ {
+ m_manifoldPtr = m_dispatcher->getNewManifold(sphereObjWrap->getCollisionObject(),boxObjWrap->getCollisionObject());
+ m_ownManifold = true;
+ }
+}
+
+
+btSphereBoxCollisionAlgorithm::~btSphereBoxCollisionAlgorithm()
+{
+ if (m_ownManifold)
+ {
+ if (m_manifoldPtr)
+ m_dispatcher->releaseManifold(m_manifoldPtr);
+ }
+}
+
+
+
+void btSphereBoxCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
+{
+ (void)dispatchInfo;
+ (void)resultOut;
+ if (!m_manifoldPtr)
+ return;
+
+ const btCollisionObjectWrapper* sphereObjWrap = m_isSwapped? body1Wrap : body0Wrap;
+ const btCollisionObjectWrapper* boxObjWrap = m_isSwapped? body0Wrap : body1Wrap;
+
+ btVector3 pOnBox;
+
+ btVector3 normalOnSurfaceB;
+ btScalar penetrationDepth;
+ btVector3 sphereCenter = sphereObjWrap->getWorldTransform().getOrigin();
+ const btSphereShape* sphere0 = (const btSphereShape*)sphereObjWrap->getCollisionShape();
+ btScalar radius = sphere0->getRadius();
+ btScalar maxContactDistance = m_manifoldPtr->getContactBreakingThreshold();
+
+ resultOut->setPersistentManifold(m_manifoldPtr);
+
+ if (getSphereDistance(boxObjWrap, pOnBox, normalOnSurfaceB, penetrationDepth, sphereCenter, radius, maxContactDistance))
+ {
+ /// report a contact. internally this will be kept persistent, and contact reduction is done
+ resultOut->addContactPoint(normalOnSurfaceB, pOnBox, penetrationDepth);
+ }
+
+ if (m_ownManifold)
+ {
+ if (m_manifoldPtr->getNumContacts())
+ {
+ resultOut->refreshContactPoints();
+ }
+ }
+
+}
+
+btScalar btSphereBoxCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+ (void)resultOut;
+ (void)dispatchInfo;
+ (void)col0;
+ (void)col1;
+
+ //not yet
+ return btScalar(1.);
+}
+
+
+bool btSphereBoxCollisionAlgorithm::getSphereDistance(const btCollisionObjectWrapper* boxObjWrap, btVector3& pointOnBox, btVector3& normal, btScalar& penetrationDepth, const btVector3& sphereCenter, btScalar fRadius, btScalar maxContactDistance )
+{
+ const btBoxShape* boxShape= (const btBoxShape*)boxObjWrap->getCollisionShape();
+ btVector3 const &boxHalfExtent = boxShape->getHalfExtentsWithoutMargin();
+ btScalar boxMargin = boxShape->getMargin();
+ penetrationDepth = 1.0f;
+
+ // convert the sphere position to the box's local space
+ btTransform const &m44T = boxObjWrap->getWorldTransform();
+ btVector3 sphereRelPos = m44T.invXform(sphereCenter);
+
+ // Determine the closest point to the sphere center in the box
+ btVector3 closestPoint = sphereRelPos;
+ closestPoint.setX( btMin(boxHalfExtent.getX(), closestPoint.getX()) );
+ closestPoint.setX( btMax(-boxHalfExtent.getX(), closestPoint.getX()) );
+ closestPoint.setY( btMin(boxHalfExtent.getY(), closestPoint.getY()) );
+ closestPoint.setY( btMax(-boxHalfExtent.getY(), closestPoint.getY()) );
+ closestPoint.setZ( btMin(boxHalfExtent.getZ(), closestPoint.getZ()) );
+ closestPoint.setZ( btMax(-boxHalfExtent.getZ(), closestPoint.getZ()) );
+
+ btScalar intersectionDist = fRadius + boxMargin;
+ btScalar contactDist = intersectionDist + maxContactDistance;
+ normal = sphereRelPos - closestPoint;
+
+ //if there is no penetration, we are done
+ btScalar dist2 = normal.length2();
+ if (dist2 > contactDist * contactDist)
+ {
+ return false;
+ }
+
+ btScalar distance;
+
+ //special case if the sphere center is inside the box
+ if (dist2 <= SIMD_EPSILON)
+ {
+ distance = -getSpherePenetration(boxHalfExtent, sphereRelPos, closestPoint, normal);
+ }
+ else //compute the penetration details
+ {
+ distance = normal.length();
+ normal /= distance;
+ }
+
+ pointOnBox = closestPoint + normal * boxMargin;
+// v3PointOnSphere = sphereRelPos - (normal * fRadius);
+ penetrationDepth = distance - intersectionDist;
+
+ // transform back in world space
+ btVector3 tmp = m44T(pointOnBox);
+ pointOnBox = tmp;
+// tmp = m44T(v3PointOnSphere);
+// v3PointOnSphere = tmp;
+ tmp = m44T.getBasis() * normal;
+ normal = tmp;
+
+ return true;
+}
+
+btScalar btSphereBoxCollisionAlgorithm::getSpherePenetration( btVector3 const &boxHalfExtent, btVector3 const &sphereRelPos, btVector3 &closestPoint, btVector3& normal )
+{
+ //project the center of the sphere on the closest face of the box
+ btScalar faceDist = boxHalfExtent.getX() - sphereRelPos.getX();
+ btScalar minDist = faceDist;
+ closestPoint.setX( boxHalfExtent.getX() );
+ normal.setValue(btScalar(1.0f), btScalar(0.0f), btScalar(0.0f));
+
+ faceDist = boxHalfExtent.getX() + sphereRelPos.getX();
+ if (faceDist < minDist)
+ {
+ minDist = faceDist;
+ closestPoint = sphereRelPos;
+ closestPoint.setX( -boxHalfExtent.getX() );
+ normal.setValue(btScalar(-1.0f), btScalar(0.0f), btScalar(0.0f));
+ }
+
+ faceDist = boxHalfExtent.getY() - sphereRelPos.getY();
+ if (faceDist < minDist)
+ {
+ minDist = faceDist;
+ closestPoint = sphereRelPos;
+ closestPoint.setY( boxHalfExtent.getY() );
+ normal.setValue(btScalar(0.0f), btScalar(1.0f), btScalar(0.0f));
+ }
+
+ faceDist = boxHalfExtent.getY() + sphereRelPos.getY();
+ if (faceDist < minDist)
+ {
+ minDist = faceDist;
+ closestPoint = sphereRelPos;
+ closestPoint.setY( -boxHalfExtent.getY() );
+ normal.setValue(btScalar(0.0f), btScalar(-1.0f), btScalar(0.0f));
+ }
+
+ faceDist = boxHalfExtent.getZ() - sphereRelPos.getZ();
+ if (faceDist < minDist)
+ {
+ minDist = faceDist;
+ closestPoint = sphereRelPos;
+ closestPoint.setZ( boxHalfExtent.getZ() );
+ normal.setValue(btScalar(0.0f), btScalar(0.0f), btScalar(1.0f));
+ }
+
+ faceDist = boxHalfExtent.getZ() + sphereRelPos.getZ();
+ if (faceDist < minDist)
+ {
+ minDist = faceDist;
+ closestPoint = sphereRelPos;
+ closestPoint.setZ( -boxHalfExtent.getZ() );
+ normal.setValue(btScalar(0.0f), btScalar(0.0f), btScalar(-1.0f));
+ }
+
+ return minDist;
+}
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h
new file mode 100644
index 0000000000..eefaedc9e7
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h
@@ -0,0 +1,75 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_SPHERE_BOX_COLLISION_ALGORITHM_H
+#define BT_SPHERE_BOX_COLLISION_ALGORITHM_H
+
+#include "btActivatingCollisionAlgorithm.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
+class btPersistentManifold;
+#include "btCollisionDispatcher.h"
+
+#include "LinearMath/btVector3.h"
+
+/// btSphereBoxCollisionAlgorithm provides sphere-box collision detection.
+/// Other features are frame-coherency (persistent data) and collision response.
+class btSphereBoxCollisionAlgorithm : public btActivatingCollisionAlgorithm
+{
+ bool m_ownManifold;
+ btPersistentManifold* m_manifoldPtr;
+ bool m_isSwapped;
+
+public:
+
+ btSphereBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap, bool isSwapped);
+
+ virtual ~btSphereBoxCollisionAlgorithm();
+
+ virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+ virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+ virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
+ {
+ if (m_manifoldPtr && m_ownManifold)
+ {
+ manifoldArray.push_back(m_manifoldPtr);
+ }
+ }
+
+ bool getSphereDistance( const btCollisionObjectWrapper* boxObjWrap, btVector3& v3PointOnBox, btVector3& normal, btScalar& penetrationDepth, const btVector3& v3SphereCenter, btScalar fRadius, btScalar maxContactDistance );
+
+ btScalar getSpherePenetration( btVector3 const &boxHalfExtent, btVector3 const &sphereRelPos, btVector3 &closestPoint, btVector3& normal );
+
+ struct CreateFunc :public btCollisionAlgorithmCreateFunc
+ {
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
+ {
+ void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereBoxCollisionAlgorithm));
+ if (!m_swapped)
+ {
+ return new(mem) btSphereBoxCollisionAlgorithm(0,ci,body0Wrap,body1Wrap,false);
+ } else
+ {
+ return new(mem) btSphereBoxCollisionAlgorithm(0,ci,body0Wrap,body1Wrap,true);
+ }
+ }
+ };
+
+};
+
+#endif //BT_SPHERE_BOX_COLLISION_ALGORITHM_H
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp
new file mode 100644
index 0000000000..27eaec3059
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp
@@ -0,0 +1,107 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+#define CLEAR_MANIFOLD 1
+
+#include "btSphereSphereCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
+
+btSphereSphereCollisionAlgorithm::btSphereSphereCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* col0Wrap,const btCollisionObjectWrapper* col1Wrap)
+: btActivatingCollisionAlgorithm(ci,col0Wrap,col1Wrap),
+m_ownManifold(false),
+m_manifoldPtr(mf)
+{
+ if (!m_manifoldPtr)
+ {
+ m_manifoldPtr = m_dispatcher->getNewManifold(col0Wrap->getCollisionObject(),col1Wrap->getCollisionObject());
+ m_ownManifold = true;
+ }
+}
+
+btSphereSphereCollisionAlgorithm::~btSphereSphereCollisionAlgorithm()
+{
+ if (m_ownManifold)
+ {
+ if (m_manifoldPtr)
+ m_dispatcher->releaseManifold(m_manifoldPtr);
+ }
+}
+
+void btSphereSphereCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* col0Wrap,const btCollisionObjectWrapper* col1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+ (void)dispatchInfo;
+
+ if (!m_manifoldPtr)
+ return;
+
+ resultOut->setPersistentManifold(m_manifoldPtr);
+
+ btSphereShape* sphere0 = (btSphereShape*)col0Wrap->getCollisionShape();
+ btSphereShape* sphere1 = (btSphereShape*)col1Wrap->getCollisionShape();
+
+ btVector3 diff = col0Wrap->getWorldTransform().getOrigin()- col1Wrap->getWorldTransform().getOrigin();
+ btScalar len = diff.length();
+ btScalar radius0 = sphere0->getRadius();
+ btScalar radius1 = sphere1->getRadius();
+
+#ifdef CLEAR_MANIFOLD
+ m_manifoldPtr->clearManifold(); //don't do this, it disables warmstarting
+#endif
+
+ ///iff distance positive, don't generate a new contact
+ if ( len > (radius0+radius1+resultOut->m_closestPointDistanceThreshold))
+ {
+#ifndef CLEAR_MANIFOLD
+ resultOut->refreshContactPoints();
+#endif //CLEAR_MANIFOLD
+ return;
+ }
+ ///distance (negative means penetration)
+ btScalar dist = len - (radius0+radius1);
+
+ btVector3 normalOnSurfaceB(1,0,0);
+ if (len > SIMD_EPSILON)
+ {
+ normalOnSurfaceB = diff / len;
+ }
+
+ ///point on A (worldspace)
+ ///btVector3 pos0 = col0->getWorldTransform().getOrigin() - radius0 * normalOnSurfaceB;
+ ///point on B (worldspace)
+ btVector3 pos1 = col1Wrap->getWorldTransform().getOrigin() + radius1* normalOnSurfaceB;
+
+ /// report a contact. internally this will be kept persistent, and contact reduction is done
+
+
+ resultOut->addContactPoint(normalOnSurfaceB,pos1,dist);
+
+#ifndef CLEAR_MANIFOLD
+ resultOut->refreshContactPoints();
+#endif //CLEAR_MANIFOLD
+
+}
+
+btScalar btSphereSphereCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+ (void)col0;
+ (void)col1;
+ (void)dispatchInfo;
+ (void)resultOut;
+
+ //not yet
+ return btScalar(1.);
+}
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h
new file mode 100644
index 0000000000..3517a568a9
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h
@@ -0,0 +1,66 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_SPHERE_SPHERE_COLLISION_ALGORITHM_H
+#define BT_SPHERE_SPHERE_COLLISION_ALGORITHM_H
+
+#include "btActivatingCollisionAlgorithm.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
+#include "btCollisionDispatcher.h"
+
+class btPersistentManifold;
+
+/// btSphereSphereCollisionAlgorithm provides sphere-sphere collision detection.
+/// Other features are frame-coherency (persistent data) and collision response.
+/// Also provides the most basic sample for custom/user btCollisionAlgorithm
+class btSphereSphereCollisionAlgorithm : public btActivatingCollisionAlgorithm
+{
+ bool m_ownManifold;
+ btPersistentManifold* m_manifoldPtr;
+
+public:
+ btSphereSphereCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* col0Wrap,const btCollisionObjectWrapper* col1Wrap);
+
+ btSphereSphereCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
+ : btActivatingCollisionAlgorithm(ci) {}
+
+ virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+ virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+ virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
+ {
+ if (m_manifoldPtr && m_ownManifold)
+ {
+ manifoldArray.push_back(m_manifoldPtr);
+ }
+ }
+
+ virtual ~btSphereSphereCollisionAlgorithm();
+
+ struct CreateFunc :public btCollisionAlgorithmCreateFunc
+ {
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* col0Wrap,const btCollisionObjectWrapper* col1Wrap)
+ {
+ void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereSphereCollisionAlgorithm));
+ return new(mem) btSphereSphereCollisionAlgorithm(0,ci,col0Wrap,col1Wrap);
+ }
+ };
+
+};
+
+#endif //BT_SPHERE_SPHERE_COLLISION_ALGORITHM_H
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp
new file mode 100644
index 0000000000..86d4e74400
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp
@@ -0,0 +1,84 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "btSphereTriangleCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "SphereTriangleDetector.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
+
+btSphereTriangleCollisionAlgorithm::btSphereTriangleCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool swapped)
+: btActivatingCollisionAlgorithm(ci,body0Wrap,body1Wrap),
+m_ownManifold(false),
+m_manifoldPtr(mf),
+m_swapped(swapped)
+{
+ if (!m_manifoldPtr)
+ {
+ m_manifoldPtr = m_dispatcher->getNewManifold(body0Wrap->getCollisionObject(),body1Wrap->getCollisionObject());
+ m_ownManifold = true;
+ }
+}
+
+btSphereTriangleCollisionAlgorithm::~btSphereTriangleCollisionAlgorithm()
+{
+ if (m_ownManifold)
+ {
+ if (m_manifoldPtr)
+ m_dispatcher->releaseManifold(m_manifoldPtr);
+ }
+}
+
+void btSphereTriangleCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* col0Wrap,const btCollisionObjectWrapper* col1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+ if (!m_manifoldPtr)
+ return;
+
+ const btCollisionObjectWrapper* sphereObjWrap = m_swapped? col1Wrap : col0Wrap;
+ const btCollisionObjectWrapper* triObjWrap = m_swapped? col0Wrap : col1Wrap;
+
+ btSphereShape* sphere = (btSphereShape*)sphereObjWrap->getCollisionShape();
+ btTriangleShape* triangle = (btTriangleShape*)triObjWrap->getCollisionShape();
+
+ /// report a contact. internally this will be kept persistent, and contact reduction is done
+ resultOut->setPersistentManifold(m_manifoldPtr);
+ SphereTriangleDetector detector(sphere,triangle, m_manifoldPtr->getContactBreakingThreshold()+ resultOut->m_closestPointDistanceThreshold);
+
+ btDiscreteCollisionDetectorInterface::ClosestPointInput input;
+ input.m_maximumDistanceSquared = btScalar(BT_LARGE_FLOAT);///@todo: tighter bounds
+ input.m_transformA = sphereObjWrap->getWorldTransform();
+ input.m_transformB = triObjWrap->getWorldTransform();
+
+ bool swapResults = m_swapped;
+
+ detector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw,swapResults);
+
+ if (m_ownManifold)
+ resultOut->refreshContactPoints();
+
+}
+
+btScalar btSphereTriangleCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+ (void)resultOut;
+ (void)dispatchInfo;
+ (void)col0;
+ (void)col1;
+
+ //not yet
+ return btScalar(1.);
+}
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h
new file mode 100644
index 0000000000..6b6e39a72b
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h
@@ -0,0 +1,69 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_SPHERE_TRIANGLE_COLLISION_ALGORITHM_H
+#define BT_SPHERE_TRIANGLE_COLLISION_ALGORITHM_H
+
+#include "btActivatingCollisionAlgorithm.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
+class btPersistentManifold;
+#include "btCollisionDispatcher.h"
+
+/// btSphereSphereCollisionAlgorithm provides sphere-sphere collision detection.
+/// Other features are frame-coherency (persistent data) and collision response.
+/// Also provides the most basic sample for custom/user btCollisionAlgorithm
+class btSphereTriangleCollisionAlgorithm : public btActivatingCollisionAlgorithm
+{
+ bool m_ownManifold;
+ btPersistentManifold* m_manifoldPtr;
+ bool m_swapped;
+
+public:
+ btSphereTriangleCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool swapped);
+
+ btSphereTriangleCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
+ : btActivatingCollisionAlgorithm(ci) {}
+
+ virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+ virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+ virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
+ {
+ if (m_manifoldPtr && m_ownManifold)
+ {
+ manifoldArray.push_back(m_manifoldPtr);
+ }
+ }
+
+ virtual ~btSphereTriangleCollisionAlgorithm();
+
+ struct CreateFunc :public btCollisionAlgorithmCreateFunc
+ {
+
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
+ {
+
+ void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereTriangleCollisionAlgorithm));
+
+ return new(mem) btSphereTriangleCollisionAlgorithm(ci.m_manifold,ci,body0Wrap,body1Wrap,m_swapped);
+ }
+ };
+
+};
+
+#endif //BT_SPHERE_TRIANGLE_COLLISION_ALGORITHM_H
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btUnionFind.cpp b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btUnionFind.cpp
new file mode 100644
index 0000000000..5222933595
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btUnionFind.cpp
@@ -0,0 +1,82 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btUnionFind.h"
+
+
+
+btUnionFind::~btUnionFind()
+{
+ Free();
+
+}
+
+btUnionFind::btUnionFind()
+{
+
+}
+
+void btUnionFind::allocate(int N)
+{
+ m_elements.resize(N);
+}
+void btUnionFind::Free()
+{
+ m_elements.clear();
+}
+
+
+void btUnionFind::reset(int N)
+{
+ allocate(N);
+
+ for (int i = 0; i < N; i++)
+ {
+ m_elements[i].m_id = i; m_elements[i].m_sz = 1;
+ }
+}
+
+
+class btUnionFindElementSortPredicate
+{
+ public:
+
+ bool operator() ( const btElement& lhs, const btElement& rhs ) const
+ {
+ return lhs.m_id < rhs.m_id;
+ }
+};
+
+///this is a special operation, destroying the content of btUnionFind.
+///it sorts the elements, based on island id, in order to make it easy to iterate over islands
+void btUnionFind::sortIslands()
+{
+
+ //first store the original body index, and islandId
+ int numElements = m_elements.size();
+
+ for (int i=0;i<numElements;i++)
+ {
+ m_elements[i].m_id = find(i);
+#ifndef STATIC_SIMULATION_ISLAND_OPTIMIZATION
+ m_elements[i].m_sz = i;
+#endif //STATIC_SIMULATION_ISLAND_OPTIMIZATION
+ }
+
+ // Sort the vector using predicate and std::sort
+ //std::sort(m_elements.begin(), m_elements.end(), btUnionFindElementSortPredicate);
+ m_elements.quickSort(btUnionFindElementSortPredicate());
+
+}
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btUnionFind.h b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btUnionFind.h
new file mode 100644
index 0000000000..ef2a29202f
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionDispatch/btUnionFind.h
@@ -0,0 +1,129 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_UNION_FIND_H
+#define BT_UNION_FIND_H
+
+#include "LinearMath/btAlignedObjectArray.h"
+
+#define USE_PATH_COMPRESSION 1
+
+///see for discussion of static island optimizations by Vroonsh here: http://code.google.com/p/bullet/issues/detail?id=406
+#define STATIC_SIMULATION_ISLAND_OPTIMIZATION 1
+
+struct btElement
+{
+ int m_id;
+ int m_sz;
+};
+
+///UnionFind calculates connected subsets
+// Implements weighted Quick Union with path compression
+// optimization: could use short ints instead of ints (halving memory, would limit the number of rigid bodies to 64k, sounds reasonable)
+class btUnionFind
+ {
+ private:
+ btAlignedObjectArray<btElement> m_elements;
+
+ public:
+
+ btUnionFind();
+ ~btUnionFind();
+
+
+ //this is a special operation, destroying the content of btUnionFind.
+ //it sorts the elements, based on island id, in order to make it easy to iterate over islands
+ void sortIslands();
+
+ void reset(int N);
+
+ SIMD_FORCE_INLINE int getNumElements() const
+ {
+ return int(m_elements.size());
+ }
+ SIMD_FORCE_INLINE bool isRoot(int x) const
+ {
+ return (x == m_elements[x].m_id);
+ }
+
+ btElement& getElement(int index)
+ {
+ return m_elements[index];
+ }
+ const btElement& getElement(int index) const
+ {
+ return m_elements[index];
+ }
+
+ void allocate(int N);
+ void Free();
+
+
+
+
+ int find(int p, int q)
+ {
+ return (find(p) == find(q));
+ }
+
+ void unite(int p, int q)
+ {
+ int i = find(p), j = find(q);
+ if (i == j)
+ return;
+
+#ifndef USE_PATH_COMPRESSION
+ //weighted quick union, this keeps the 'trees' balanced, and keeps performance of unite O( log(n) )
+ if (m_elements[i].m_sz < m_elements[j].m_sz)
+ {
+ m_elements[i].m_id = j; m_elements[j].m_sz += m_elements[i].m_sz;
+ }
+ else
+ {
+ m_elements[j].m_id = i; m_elements[i].m_sz += m_elements[j].m_sz;
+ }
+#else
+ m_elements[i].m_id = j; m_elements[j].m_sz += m_elements[i].m_sz;
+#endif //USE_PATH_COMPRESSION
+ }
+
+ int find(int x)
+ {
+ //btAssert(x < m_N);
+ //btAssert(x >= 0);
+
+ while (x != m_elements[x].m_id)
+ {
+ //not really a reason not to use path compression, and it flattens the trees/improves find performance dramatically
+
+ #ifdef USE_PATH_COMPRESSION
+ const btElement* elementPtr = &m_elements[m_elements[x].m_id];
+ m_elements[x].m_id = elementPtr->m_id;
+ x = elementPtr->m_id;
+ #else//
+ x = m_elements[x].m_id;
+ #endif
+ //btAssert(x < m_N);
+ //btAssert(x >= 0);
+
+ }
+ return x;
+ }
+
+
+ };
+
+
+#endif //BT_UNION_FIND_H
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btBox2dShape.cpp b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btBox2dShape.cpp
new file mode 100644
index 0000000000..ecce028c2e
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btBox2dShape.cpp
@@ -0,0 +1,42 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btBox2dShape.h"
+
+
+//{
+
+
+void btBox2dShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+{
+ btTransformAabb(getHalfExtentsWithoutMargin(),getMargin(),t,aabbMin,aabbMax);
+}
+
+
+void btBox2dShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+{
+ //btScalar margin = btScalar(0.);
+ btVector3 halfExtents = getHalfExtentsWithMargin();
+
+ btScalar lx=btScalar(2.)*(halfExtents.x());
+ btScalar ly=btScalar(2.)*(halfExtents.y());
+ btScalar lz=btScalar(2.)*(halfExtents.z());
+
+ inertia.setValue(mass/(btScalar(12.0)) * (ly*ly + lz*lz),
+ mass/(btScalar(12.0)) * (lx*lx + lz*lz),
+ mass/(btScalar(12.0)) * (lx*lx + ly*ly));
+
+}
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btBox2dShape.h b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btBox2dShape.h
new file mode 100644
index 0000000000..22bee4f2c8
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btBox2dShape.h
@@ -0,0 +1,372 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_OBB_BOX_2D_SHAPE_H
+#define BT_OBB_BOX_2D_SHAPE_H
+
+#include "BulletCollision/CollisionShapes/btPolyhedralConvexShape.h"
+#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btMinMax.h"
+
+///The btBox2dShape is a box primitive around the origin, its sides axis aligned with length specified by half extents, in local shape coordinates. When used as part of a btCollisionObject or btRigidBody it will be an oriented box in world space.
+ATTRIBUTE_ALIGNED16(class) btBox2dShape: public btPolyhedralConvexShape
+{
+
+ //btVector3 m_boxHalfExtents1; //use m_implicitShapeDimensions instead
+
+ btVector3 m_centroid;
+ btVector3 m_vertices[4];
+ btVector3 m_normals[4];
+
+public:
+
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ btVector3 getHalfExtentsWithMargin() const
+ {
+ btVector3 halfExtents = getHalfExtentsWithoutMargin();
+ btVector3 margin(getMargin(),getMargin(),getMargin());
+ halfExtents += margin;
+ return halfExtents;
+ }
+
+ const btVector3& getHalfExtentsWithoutMargin() const
+ {
+ return m_implicitShapeDimensions;//changed in Bullet 2.63: assume the scaling and margin are included
+ }
+
+
+ virtual btVector3 localGetSupportingVertex(const btVector3& vec) const
+ {
+ btVector3 halfExtents = getHalfExtentsWithoutMargin();
+ btVector3 margin(getMargin(),getMargin(),getMargin());
+ halfExtents += margin;
+
+ return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
+ btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
+ btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
+ }
+
+ SIMD_FORCE_INLINE btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const
+ {
+ const btVector3& halfExtents = getHalfExtentsWithoutMargin();
+
+ return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
+ btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
+ btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
+ }
+
+ virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+ {
+ const btVector3& halfExtents = getHalfExtentsWithoutMargin();
+
+ for (int i=0;i<numVectors;i++)
+ {
+ const btVector3& vec = vectors[i];
+ supportVerticesOut[i].setValue(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
+ btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
+ btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
+ }
+
+ }
+
+
+ ///a btBox2dShape is a flat 2D box in the X-Y plane (Z extents are zero)
+ btBox2dShape( const btVector3& boxHalfExtents)
+ : btPolyhedralConvexShape(),
+ m_centroid(0,0,0)
+ {
+ m_vertices[0].setValue(-boxHalfExtents.getX(),-boxHalfExtents.getY(),0);
+ m_vertices[1].setValue(boxHalfExtents.getX(),-boxHalfExtents.getY(),0);
+ m_vertices[2].setValue(boxHalfExtents.getX(),boxHalfExtents.getY(),0);
+ m_vertices[3].setValue(-boxHalfExtents.getX(),boxHalfExtents.getY(),0);
+
+ m_normals[0].setValue(0,-1,0);
+ m_normals[1].setValue(1,0,0);
+ m_normals[2].setValue(0,1,0);
+ m_normals[3].setValue(-1,0,0);
+
+ btScalar minDimension = boxHalfExtents.getX();
+ if (minDimension>boxHalfExtents.getY())
+ minDimension = boxHalfExtents.getY();
+
+ m_shapeType = BOX_2D_SHAPE_PROXYTYPE;
+ btVector3 margin(getMargin(),getMargin(),getMargin());
+ m_implicitShapeDimensions = (boxHalfExtents * m_localScaling) - margin;
+
+ setSafeMargin(minDimension);
+ };
+
+ virtual void setMargin(btScalar collisionMargin)
+ {
+ //correct the m_implicitShapeDimensions for the margin
+ btVector3 oldMargin(getMargin(),getMargin(),getMargin());
+ btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin;
+
+ btConvexInternalShape::setMargin(collisionMargin);
+ btVector3 newMargin(getMargin(),getMargin(),getMargin());
+ m_implicitShapeDimensions = implicitShapeDimensionsWithMargin - newMargin;
+
+ }
+ virtual void setLocalScaling(const btVector3& scaling)
+ {
+ btVector3 oldMargin(getMargin(),getMargin(),getMargin());
+ btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin;
+ btVector3 unScaledImplicitShapeDimensionsWithMargin = implicitShapeDimensionsWithMargin / m_localScaling;
+
+ btConvexInternalShape::setLocalScaling(scaling);
+
+ m_implicitShapeDimensions = (unScaledImplicitShapeDimensionsWithMargin * m_localScaling) - oldMargin;
+
+ }
+
+ virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+
+
+
+ virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+
+
+
+
+
+ int getVertexCount() const
+ {
+ return 4;
+ }
+
+ virtual int getNumVertices()const
+ {
+ return 4;
+ }
+
+ const btVector3* getVertices() const
+ {
+ return &m_vertices[0];
+ }
+
+ const btVector3* getNormals() const
+ {
+ return &m_normals[0];
+ }
+
+
+
+
+
+
+
+ virtual void getPlane(btVector3& planeNormal,btVector3& planeSupport,int i ) const
+ {
+ //this plane might not be aligned...
+ btVector4 plane ;
+ getPlaneEquation(plane,i);
+ planeNormal = btVector3(plane.getX(),plane.getY(),plane.getZ());
+ planeSupport = localGetSupportingVertex(-planeNormal);
+ }
+
+
+ const btVector3& getCentroid() const
+ {
+ return m_centroid;
+ }
+
+ virtual int getNumPlanes() const
+ {
+ return 6;
+ }
+
+
+
+ virtual int getNumEdges() const
+ {
+ return 12;
+ }
+
+
+ virtual void getVertex(int i,btVector3& vtx) const
+ {
+ btVector3 halfExtents = getHalfExtentsWithoutMargin();
+
+ vtx = btVector3(
+ halfExtents.x() * (1-(i&1)) - halfExtents.x() * (i&1),
+ halfExtents.y() * (1-((i&2)>>1)) - halfExtents.y() * ((i&2)>>1),
+ halfExtents.z() * (1-((i&4)>>2)) - halfExtents.z() * ((i&4)>>2));
+ }
+
+
+ virtual void getPlaneEquation(btVector4& plane,int i) const
+ {
+ btVector3 halfExtents = getHalfExtentsWithoutMargin();
+
+ switch (i)
+ {
+ case 0:
+ plane.setValue(btScalar(1.),btScalar(0.),btScalar(0.),-halfExtents.x());
+ break;
+ case 1:
+ plane.setValue(btScalar(-1.),btScalar(0.),btScalar(0.),-halfExtents.x());
+ break;
+ case 2:
+ plane.setValue(btScalar(0.),btScalar(1.),btScalar(0.),-halfExtents.y());
+ break;
+ case 3:
+ plane.setValue(btScalar(0.),btScalar(-1.),btScalar(0.),-halfExtents.y());
+ break;
+ case 4:
+ plane.setValue(btScalar(0.),btScalar(0.),btScalar(1.),-halfExtents.z());
+ break;
+ case 5:
+ plane.setValue(btScalar(0.),btScalar(0.),btScalar(-1.),-halfExtents.z());
+ break;
+ default:
+ btAssert(0);
+ }
+ }
+
+
+ virtual void getEdge(int i,btVector3& pa,btVector3& pb) const
+ //virtual void getEdge(int i,Edge& edge) const
+ {
+ int edgeVert0 = 0;
+ int edgeVert1 = 0;
+
+ switch (i)
+ {
+ case 0:
+ edgeVert0 = 0;
+ edgeVert1 = 1;
+ break;
+ case 1:
+ edgeVert0 = 0;
+ edgeVert1 = 2;
+ break;
+ case 2:
+ edgeVert0 = 1;
+ edgeVert1 = 3;
+
+ break;
+ case 3:
+ edgeVert0 = 2;
+ edgeVert1 = 3;
+ break;
+ case 4:
+ edgeVert0 = 0;
+ edgeVert1 = 4;
+ break;
+ case 5:
+ edgeVert0 = 1;
+ edgeVert1 = 5;
+
+ break;
+ case 6:
+ edgeVert0 = 2;
+ edgeVert1 = 6;
+ break;
+ case 7:
+ edgeVert0 = 3;
+ edgeVert1 = 7;
+ break;
+ case 8:
+ edgeVert0 = 4;
+ edgeVert1 = 5;
+ break;
+ case 9:
+ edgeVert0 = 4;
+ edgeVert1 = 6;
+ break;
+ case 10:
+ edgeVert0 = 5;
+ edgeVert1 = 7;
+ break;
+ case 11:
+ edgeVert0 = 6;
+ edgeVert1 = 7;
+ break;
+ default:
+ btAssert(0);
+
+ }
+
+ getVertex(edgeVert0,pa );
+ getVertex(edgeVert1,pb );
+ }
+
+
+
+
+
+ virtual bool isInside(const btVector3& pt,btScalar tolerance) const
+ {
+ btVector3 halfExtents = getHalfExtentsWithoutMargin();
+
+ //btScalar minDist = 2*tolerance;
+
+ bool result = (pt.x() <= (halfExtents.x()+tolerance)) &&
+ (pt.x() >= (-halfExtents.x()-tolerance)) &&
+ (pt.y() <= (halfExtents.y()+tolerance)) &&
+ (pt.y() >= (-halfExtents.y()-tolerance)) &&
+ (pt.z() <= (halfExtents.z()+tolerance)) &&
+ (pt.z() >= (-halfExtents.z()-tolerance));
+
+ return result;
+ }
+
+
+ //debugging
+ virtual const char* getName()const
+ {
+ return "Box2d";
+ }
+
+ virtual int getNumPreferredPenetrationDirections() const
+ {
+ return 6;
+ }
+
+ virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const
+ {
+ switch (index)
+ {
+ case 0:
+ penetrationVector.setValue(btScalar(1.),btScalar(0.),btScalar(0.));
+ break;
+ case 1:
+ penetrationVector.setValue(btScalar(-1.),btScalar(0.),btScalar(0.));
+ break;
+ case 2:
+ penetrationVector.setValue(btScalar(0.),btScalar(1.),btScalar(0.));
+ break;
+ case 3:
+ penetrationVector.setValue(btScalar(0.),btScalar(-1.),btScalar(0.));
+ break;
+ case 4:
+ penetrationVector.setValue(btScalar(0.),btScalar(0.),btScalar(1.));
+ break;
+ case 5:
+ penetrationVector.setValue(btScalar(0.),btScalar(0.),btScalar(-1.));
+ break;
+ default:
+ btAssert(0);
+ }
+ }
+
+};
+
+#endif //BT_OBB_BOX_2D_SHAPE_H
+
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btBoxShape.cpp b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btBoxShape.cpp
new file mode 100644
index 0000000000..72eeb38911
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btBoxShape.cpp
@@ -0,0 +1,51 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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 "btBoxShape.h"
+
+btBoxShape::btBoxShape( const btVector3& boxHalfExtents)
+: btPolyhedralConvexShape()
+{
+ m_shapeType = BOX_SHAPE_PROXYTYPE;
+
+ btVector3 margin(getMargin(),getMargin(),getMargin());
+ m_implicitShapeDimensions = (boxHalfExtents * m_localScaling) - margin;
+
+ setSafeMargin(boxHalfExtents);
+};
+
+
+
+
+void btBoxShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+{
+ btTransformAabb(getHalfExtentsWithoutMargin(),getMargin(),t,aabbMin,aabbMax);
+}
+
+
+void btBoxShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+{
+ //btScalar margin = btScalar(0.);
+ btVector3 halfExtents = getHalfExtentsWithMargin();
+
+ btScalar lx=btScalar(2.)*(halfExtents.x());
+ btScalar ly=btScalar(2.)*(halfExtents.y());
+ btScalar lz=btScalar(2.)*(halfExtents.z());
+
+ inertia.setValue(mass/(btScalar(12.0)) * (ly*ly + lz*lz),
+ mass/(btScalar(12.0)) * (lx*lx + lz*lz),
+ mass/(btScalar(12.0)) * (lx*lx + ly*ly));
+
+}
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btBoxShape.h b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btBoxShape.h
new file mode 100644
index 0000000000..715e3f2ab9
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btBoxShape.h
@@ -0,0 +1,314 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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_OBB_BOX_MINKOWSKI_H
+#define BT_OBB_BOX_MINKOWSKI_H
+
+#include "btPolyhedralConvexShape.h"
+#include "btCollisionMargin.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btMinMax.h"
+
+///The btBoxShape is a box primitive around the origin, its sides axis aligned with length specified by half extents, in local shape coordinates. When used as part of a btCollisionObject or btRigidBody it will be an oriented box in world space.
+ATTRIBUTE_ALIGNED16(class) btBoxShape: public btPolyhedralConvexShape
+{
+
+ //btVector3 m_boxHalfExtents1; //use m_implicitShapeDimensions instead
+
+
+public:
+
+BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ btVector3 getHalfExtentsWithMargin() const
+ {
+ btVector3 halfExtents = getHalfExtentsWithoutMargin();
+ btVector3 margin(getMargin(),getMargin(),getMargin());
+ halfExtents += margin;
+ return halfExtents;
+ }
+
+ const btVector3& getHalfExtentsWithoutMargin() const
+ {
+ return m_implicitShapeDimensions;//scaling is included, margin is not
+ }
+
+
+ virtual btVector3 localGetSupportingVertex(const btVector3& vec) const
+ {
+ btVector3 halfExtents = getHalfExtentsWithoutMargin();
+ btVector3 margin(getMargin(),getMargin(),getMargin());
+ halfExtents += margin;
+
+ return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
+ btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
+ btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
+ }
+
+ SIMD_FORCE_INLINE btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const
+ {
+ const btVector3& halfExtents = getHalfExtentsWithoutMargin();
+
+ return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
+ btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
+ btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
+ }
+
+ virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+ {
+ const btVector3& halfExtents = getHalfExtentsWithoutMargin();
+
+ for (int i=0;i<numVectors;i++)
+ {
+ const btVector3& vec = vectors[i];
+ supportVerticesOut[i].setValue(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
+ btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
+ btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
+ }
+
+ }
+
+
+ btBoxShape( const btVector3& boxHalfExtents);
+
+ virtual void setMargin(btScalar collisionMargin)
+ {
+ //correct the m_implicitShapeDimensions for the margin
+ btVector3 oldMargin(getMargin(),getMargin(),getMargin());
+ btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin;
+
+ btConvexInternalShape::setMargin(collisionMargin);
+ btVector3 newMargin(getMargin(),getMargin(),getMargin());
+ m_implicitShapeDimensions = implicitShapeDimensionsWithMargin - newMargin;
+
+ }
+ virtual void setLocalScaling(const btVector3& scaling)
+ {
+ btVector3 oldMargin(getMargin(),getMargin(),getMargin());
+ btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin;
+ btVector3 unScaledImplicitShapeDimensionsWithMargin = implicitShapeDimensionsWithMargin / m_localScaling;
+
+ btConvexInternalShape::setLocalScaling(scaling);
+
+ m_implicitShapeDimensions = (unScaledImplicitShapeDimensionsWithMargin * m_localScaling) - oldMargin;
+
+ }
+
+ virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+
+
+
+ virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+
+ virtual void getPlane(btVector3& planeNormal,btVector3& planeSupport,int i ) const
+ {
+ //this plane might not be aligned...
+ btVector4 plane ;
+ getPlaneEquation(plane,i);
+ planeNormal = btVector3(plane.getX(),plane.getY(),plane.getZ());
+ planeSupport = localGetSupportingVertex(-planeNormal);
+ }
+
+
+ virtual int getNumPlanes() const
+ {
+ return 6;
+ }
+
+ virtual int getNumVertices() const
+ {
+ return 8;
+ }
+
+ virtual int getNumEdges() const
+ {
+ return 12;
+ }
+
+
+ virtual void getVertex(int i,btVector3& vtx) const
+ {
+ btVector3 halfExtents = getHalfExtentsWithMargin();
+
+ vtx = btVector3(
+ halfExtents.x() * (1-(i&1)) - halfExtents.x() * (i&1),
+ halfExtents.y() * (1-((i&2)>>1)) - halfExtents.y() * ((i&2)>>1),
+ halfExtents.z() * (1-((i&4)>>2)) - halfExtents.z() * ((i&4)>>2));
+ }
+
+
+ virtual void getPlaneEquation(btVector4& plane,int i) const
+ {
+ btVector3 halfExtents = getHalfExtentsWithoutMargin();
+
+ switch (i)
+ {
+ case 0:
+ plane.setValue(btScalar(1.),btScalar(0.),btScalar(0.),-halfExtents.x());
+ break;
+ case 1:
+ plane.setValue(btScalar(-1.),btScalar(0.),btScalar(0.),-halfExtents.x());
+ break;
+ case 2:
+ plane.setValue(btScalar(0.),btScalar(1.),btScalar(0.),-halfExtents.y());
+ break;
+ case 3:
+ plane.setValue(btScalar(0.),btScalar(-1.),btScalar(0.),-halfExtents.y());
+ break;
+ case 4:
+ plane.setValue(btScalar(0.),btScalar(0.),btScalar(1.),-halfExtents.z());
+ break;
+ case 5:
+ plane.setValue(btScalar(0.),btScalar(0.),btScalar(-1.),-halfExtents.z());
+ break;
+ default:
+ btAssert(0);
+ }
+ }
+
+
+ virtual void getEdge(int i,btVector3& pa,btVector3& pb) const
+ //virtual void getEdge(int i,Edge& edge) const
+ {
+ int edgeVert0 = 0;
+ int edgeVert1 = 0;
+
+ switch (i)
+ {
+ case 0:
+ edgeVert0 = 0;
+ edgeVert1 = 1;
+ break;
+ case 1:
+ edgeVert0 = 0;
+ edgeVert1 = 2;
+ break;
+ case 2:
+ edgeVert0 = 1;
+ edgeVert1 = 3;
+
+ break;
+ case 3:
+ edgeVert0 = 2;
+ edgeVert1 = 3;
+ break;
+ case 4:
+ edgeVert0 = 0;
+ edgeVert1 = 4;
+ break;
+ case 5:
+ edgeVert0 = 1;
+ edgeVert1 = 5;
+
+ break;
+ case 6:
+ edgeVert0 = 2;
+ edgeVert1 = 6;
+ break;
+ case 7:
+ edgeVert0 = 3;
+ edgeVert1 = 7;
+ break;
+ case 8:
+ edgeVert0 = 4;
+ edgeVert1 = 5;
+ break;
+ case 9:
+ edgeVert0 = 4;
+ edgeVert1 = 6;
+ break;
+ case 10:
+ edgeVert0 = 5;
+ edgeVert1 = 7;
+ break;
+ case 11:
+ edgeVert0 = 6;
+ edgeVert1 = 7;
+ break;
+ default:
+ btAssert(0);
+
+ }
+
+ getVertex(edgeVert0,pa );
+ getVertex(edgeVert1,pb );
+ }
+
+
+
+
+
+ virtual bool isInside(const btVector3& pt,btScalar tolerance) const
+ {
+ btVector3 halfExtents = getHalfExtentsWithoutMargin();
+
+ //btScalar minDist = 2*tolerance;
+
+ bool result = (pt.x() <= (halfExtents.x()+tolerance)) &&
+ (pt.x() >= (-halfExtents.x()-tolerance)) &&
+ (pt.y() <= (halfExtents.y()+tolerance)) &&
+ (pt.y() >= (-halfExtents.y()-tolerance)) &&
+ (pt.z() <= (halfExtents.z()+tolerance)) &&
+ (pt.z() >= (-halfExtents.z()-tolerance));
+
+ return result;
+ }
+
+
+ //debugging
+ virtual const char* getName()const
+ {
+ return "Box";
+ }
+
+ virtual int getNumPreferredPenetrationDirections() const
+ {
+ return 6;
+ }
+
+ virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const
+ {
+ switch (index)
+ {
+ case 0:
+ penetrationVector.setValue(btScalar(1.),btScalar(0.),btScalar(0.));
+ break;
+ case 1:
+ penetrationVector.setValue(btScalar(-1.),btScalar(0.),btScalar(0.));
+ break;
+ case 2:
+ penetrationVector.setValue(btScalar(0.),btScalar(1.),btScalar(0.));
+ break;
+ case 3:
+ penetrationVector.setValue(btScalar(0.),btScalar(-1.),btScalar(0.));
+ break;
+ case 4:
+ penetrationVector.setValue(btScalar(0.),btScalar(0.),btScalar(1.));
+ break;
+ case 5:
+ penetrationVector.setValue(btScalar(0.),btScalar(0.),btScalar(-1.));
+ break;
+ default:
+ btAssert(0);
+ }
+ }
+
+};
+
+
+#endif //BT_OBB_BOX_MINKOWSKI_H
+
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp
new file mode 100644
index 0000000000..61f465cb72
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp
@@ -0,0 +1,470 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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.
+*/
+
+//#define DISABLE_BVH
+
+#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h"
+#include "BulletCollision/CollisionShapes/btOptimizedBvh.h"
+#include "LinearMath/btSerializer.h"
+
+///Bvh Concave triangle mesh is a static-triangle mesh shape with Bounding Volume Hierarchy optimization.
+///Uses an interface to access the triangles to allow for sharing graphics/physics triangles.
+btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, bool buildBvh)
+:btTriangleMeshShape(meshInterface),
+m_bvh(0),
+m_triangleInfoMap(0),
+m_useQuantizedAabbCompression(useQuantizedAabbCompression),
+m_ownsBvh(false)
+{
+ m_shapeType = TRIANGLE_MESH_SHAPE_PROXYTYPE;
+ //construct bvh from meshInterface
+#ifndef DISABLE_BVH
+
+ if (buildBvh)
+ {
+ buildOptimizedBvh();
+ }
+
+#endif //DISABLE_BVH
+
+}
+
+btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,bool buildBvh)
+:btTriangleMeshShape(meshInterface),
+m_bvh(0),
+m_triangleInfoMap(0),
+m_useQuantizedAabbCompression(useQuantizedAabbCompression),
+m_ownsBvh(false)
+{
+ m_shapeType = TRIANGLE_MESH_SHAPE_PROXYTYPE;
+ //construct bvh from meshInterface
+#ifndef DISABLE_BVH
+
+ if (buildBvh)
+ {
+ void* mem = btAlignedAlloc(sizeof(btOptimizedBvh),16);
+ m_bvh = new (mem) btOptimizedBvh();
+
+ m_bvh->build(meshInterface,m_useQuantizedAabbCompression,bvhAabbMin,bvhAabbMax);
+ m_ownsBvh = true;
+ }
+
+#endif //DISABLE_BVH
+
+}
+
+void btBvhTriangleMeshShape::partialRefitTree(const btVector3& aabbMin,const btVector3& aabbMax)
+{
+ m_bvh->refitPartial( m_meshInterface,aabbMin,aabbMax );
+
+ m_localAabbMin.setMin(aabbMin);
+ m_localAabbMax.setMax(aabbMax);
+}
+
+
+void btBvhTriangleMeshShape::refitTree(const btVector3& aabbMin,const btVector3& aabbMax)
+{
+ m_bvh->refit( m_meshInterface, aabbMin,aabbMax );
+
+ recalcLocalAabb();
+}
+
+btBvhTriangleMeshShape::~btBvhTriangleMeshShape()
+{
+ if (m_ownsBvh)
+ {
+ m_bvh->~btOptimizedBvh();
+ btAlignedFree(m_bvh);
+ }
+}
+
+void btBvhTriangleMeshShape::performRaycast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget)
+{
+ struct MyNodeOverlapCallback : public btNodeOverlapCallback
+ {
+ btStridingMeshInterface* m_meshInterface;
+ btTriangleCallback* m_callback;
+
+ MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface)
+ :m_meshInterface(meshInterface),
+ m_callback(callback)
+ {
+ }
+
+ virtual void processNode(int nodeSubPart, int nodeTriangleIndex)
+ {
+ btVector3 m_triangle[3];
+ const unsigned char *vertexbase;
+ int numverts;
+ PHY_ScalarType type;
+ int stride;
+ const unsigned char *indexbase;
+ int indexstride;
+ int numfaces;
+ PHY_ScalarType indicestype;
+
+ m_meshInterface->getLockedReadOnlyVertexIndexBase(
+ &vertexbase,
+ numverts,
+ type,
+ stride,
+ &indexbase,
+ indexstride,
+ numfaces,
+ indicestype,
+ nodeSubPart);
+
+ unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride);
+ btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT);
+
+ const btVector3& meshScaling = m_meshInterface->getScaling();
+ for (int j=2;j>=0;j--)
+ {
+ int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j];
+
+ if (type == PHY_FLOAT)
+ {
+ float* graphicsbase = (float*)(vertexbase+graphicsindex*stride);
+
+ m_triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());
+ }
+ else
+ {
+ double* graphicsbase = (double*)(vertexbase+graphicsindex*stride);
+
+ m_triangle[j] = btVector3(btScalar(graphicsbase[0])*meshScaling.getX(),btScalar(graphicsbase[1])*meshScaling.getY(),btScalar(graphicsbase[2])*meshScaling.getZ());
+ }
+ }
+
+ /* Perform ray vs. triangle collision here */
+ m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex);
+ m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
+ }
+ };
+
+ MyNodeOverlapCallback myNodeCallback(callback,m_meshInterface);
+
+ m_bvh->reportRayOverlappingNodex(&myNodeCallback,raySource,rayTarget);
+}
+
+void btBvhTriangleMeshShape::performConvexcast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax)
+{
+ struct MyNodeOverlapCallback : public btNodeOverlapCallback
+ {
+ btStridingMeshInterface* m_meshInterface;
+ btTriangleCallback* m_callback;
+
+ MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface)
+ :m_meshInterface(meshInterface),
+ m_callback(callback)
+ {
+ }
+
+ virtual void processNode(int nodeSubPart, int nodeTriangleIndex)
+ {
+ btVector3 m_triangle[3];
+ const unsigned char *vertexbase;
+ int numverts;
+ PHY_ScalarType type;
+ int stride;
+ const unsigned char *indexbase;
+ int indexstride;
+ int numfaces;
+ PHY_ScalarType indicestype;
+
+ m_meshInterface->getLockedReadOnlyVertexIndexBase(
+ &vertexbase,
+ numverts,
+ type,
+ stride,
+ &indexbase,
+ indexstride,
+ numfaces,
+ indicestype,
+ nodeSubPart);
+
+ unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride);
+ btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT);
+
+ const btVector3& meshScaling = m_meshInterface->getScaling();
+ for (int j=2;j>=0;j--)
+ {
+ int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j];
+
+ if (type == PHY_FLOAT)
+ {
+ float* graphicsbase = (float*)(vertexbase+graphicsindex*stride);
+
+ m_triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());
+ }
+ else
+ {
+ double* graphicsbase = (double*)(vertexbase+graphicsindex*stride);
+
+ m_triangle[j] = btVector3(btScalar(graphicsbase[0])*meshScaling.getX(),btScalar(graphicsbase[1])*meshScaling.getY(),btScalar(graphicsbase[2])*meshScaling.getZ());
+ }
+ }
+
+ /* Perform ray vs. triangle collision here */
+ m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex);
+ m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
+ }
+ };
+
+ MyNodeOverlapCallback myNodeCallback(callback,m_meshInterface);
+
+ m_bvh->reportBoxCastOverlappingNodex (&myNodeCallback, raySource, rayTarget, aabbMin, aabbMax);
+}
+
+//perform bvh tree traversal and report overlapping triangles to 'callback'
+void btBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
+{
+
+#ifdef DISABLE_BVH
+ //brute force traverse all triangles
+ btTriangleMeshShape::processAllTriangles(callback,aabbMin,aabbMax);
+#else
+
+ //first get all the nodes
+
+
+ struct MyNodeOverlapCallback : public btNodeOverlapCallback
+ {
+ btStridingMeshInterface* m_meshInterface;
+ btTriangleCallback* m_callback;
+ btVector3 m_triangle[3];
+ int m_numOverlap;
+
+ MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface)
+ :m_meshInterface(meshInterface),
+ m_callback(callback),
+ m_numOverlap(0)
+ {
+ }
+
+ virtual void processNode(int nodeSubPart, int nodeTriangleIndex)
+ {
+ m_numOverlap++;
+ const unsigned char *vertexbase;
+ int numverts;
+ PHY_ScalarType type;
+ int stride;
+ const unsigned char *indexbase;
+ int indexstride;
+ int numfaces;
+ PHY_ScalarType indicestype;
+
+
+ m_meshInterface->getLockedReadOnlyVertexIndexBase(
+ &vertexbase,
+ numverts,
+ type,
+ stride,
+ &indexbase,
+ indexstride,
+ numfaces,
+ indicestype,
+ nodeSubPart);
+
+ unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride);
+ btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT||indicestype==PHY_UCHAR);
+
+ const btVector3& meshScaling = m_meshInterface->getScaling();
+ for (int j=2;j>=0;j--)
+ {
+
+ int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:indicestype==PHY_INTEGER?gfxbase[j]:((unsigned char*)gfxbase)[j];
+
+
+#ifdef DEBUG_TRIANGLE_MESH
+ printf("%d ,",graphicsindex);
+#endif //DEBUG_TRIANGLE_MESH
+ if (type == PHY_FLOAT)
+ {
+ float* graphicsbase = (float*)(vertexbase+graphicsindex*stride);
+
+ m_triangle[j] = btVector3(
+ graphicsbase[0]*meshScaling.getX(),
+ graphicsbase[1]*meshScaling.getY(),
+ graphicsbase[2]*meshScaling.getZ());
+ }
+ else
+ {
+ double* graphicsbase = (double*)(vertexbase+graphicsindex*stride);
+
+ m_triangle[j] = btVector3(
+ btScalar(graphicsbase[0])*meshScaling.getX(),
+ btScalar(graphicsbase[1])*meshScaling.getY(),
+ btScalar(graphicsbase[2])*meshScaling.getZ());
+ }
+#ifdef DEBUG_TRIANGLE_MESH
+ printf("triangle vertices:%f,%f,%f\n",triangle[j].x(),triangle[j].y(),triangle[j].z());
+#endif //DEBUG_TRIANGLE_MESH
+ }
+
+ m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex);
+ m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
+ }
+
+ };
+
+ MyNodeOverlapCallback myNodeCallback(callback,m_meshInterface);
+
+ m_bvh->reportAabbOverlappingNodex(&myNodeCallback,aabbMin,aabbMax);
+
+#endif//DISABLE_BVH
+
+
+}
+
+void btBvhTriangleMeshShape::setLocalScaling(const btVector3& scaling)
+{
+ if ((getLocalScaling() -scaling).length2() > SIMD_EPSILON)
+ {
+ btTriangleMeshShape::setLocalScaling(scaling);
+ buildOptimizedBvh();
+ }
+}
+
+void btBvhTriangleMeshShape::buildOptimizedBvh()
+{
+ if (m_ownsBvh)
+ {
+ m_bvh->~btOptimizedBvh();
+ btAlignedFree(m_bvh);
+ }
+ ///m_localAabbMin/m_localAabbMax is already re-calculated in btTriangleMeshShape. We could just scale aabb, but this needs some more work
+ void* mem = btAlignedAlloc(sizeof(btOptimizedBvh),16);
+ m_bvh = new(mem) btOptimizedBvh();
+ //rebuild the bvh...
+ m_bvh->build(m_meshInterface,m_useQuantizedAabbCompression,m_localAabbMin,m_localAabbMax);
+ m_ownsBvh = true;
+}
+
+void btBvhTriangleMeshShape::setOptimizedBvh(btOptimizedBvh* bvh, const btVector3& scaling)
+{
+ btAssert(!m_bvh);
+ btAssert(!m_ownsBvh);
+
+ m_bvh = bvh;
+ m_ownsBvh = false;
+ // update the scaling without rebuilding the bvh
+ if ((getLocalScaling() -scaling).length2() > SIMD_EPSILON)
+ {
+ btTriangleMeshShape::setLocalScaling(scaling);
+ }
+}
+
+
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+const char* btBvhTriangleMeshShape::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+ btTriangleMeshShapeData* trimeshData = (btTriangleMeshShapeData*) dataBuffer;
+
+ btCollisionShape::serialize(&trimeshData->m_collisionShapeData,serializer);
+
+ m_meshInterface->serialize(&trimeshData->m_meshInterface, serializer);
+
+ trimeshData->m_collisionMargin = float(m_collisionMargin);
+
+
+
+ if (m_bvh && !(serializer->getSerializationFlags()&BT_SERIALIZE_NO_BVH))
+ {
+ void* chunk = serializer->findPointer(m_bvh);
+ if (chunk)
+ {
+#ifdef BT_USE_DOUBLE_PRECISION
+ trimeshData->m_quantizedDoubleBvh = (btQuantizedBvhData*)chunk;
+ trimeshData->m_quantizedFloatBvh = 0;
+#else
+ trimeshData->m_quantizedFloatBvh = (btQuantizedBvhData*)chunk;
+ trimeshData->m_quantizedDoubleBvh= 0;
+#endif //BT_USE_DOUBLE_PRECISION
+ } else
+ {
+
+#ifdef BT_USE_DOUBLE_PRECISION
+ trimeshData->m_quantizedDoubleBvh = (btQuantizedBvhData*)serializer->getUniquePointer(m_bvh);
+ trimeshData->m_quantizedFloatBvh = 0;
+#else
+ trimeshData->m_quantizedFloatBvh = (btQuantizedBvhData*)serializer->getUniquePointer(m_bvh);
+ trimeshData->m_quantizedDoubleBvh= 0;
+#endif //BT_USE_DOUBLE_PRECISION
+
+ int sz = m_bvh->calculateSerializeBufferSizeNew();
+ btChunk* chunk = serializer->allocate(sz,1);
+ const char* structType = m_bvh->serialize(chunk->m_oldPtr, serializer);
+ serializer->finalizeChunk(chunk,structType,BT_QUANTIZED_BVH_CODE,m_bvh);
+ }
+ } else
+ {
+ trimeshData->m_quantizedFloatBvh = 0;
+ trimeshData->m_quantizedDoubleBvh = 0;
+ }
+
+
+
+ if (m_triangleInfoMap && !(serializer->getSerializationFlags()&BT_SERIALIZE_NO_TRIANGLEINFOMAP))
+ {
+ void* chunk = serializer->findPointer(m_triangleInfoMap);
+ if (chunk)
+ {
+ trimeshData->m_triangleInfoMap = (btTriangleInfoMapData*)chunk;
+ } else
+ {
+ trimeshData->m_triangleInfoMap = (btTriangleInfoMapData*)serializer->getUniquePointer(m_triangleInfoMap);
+ int sz = m_triangleInfoMap->calculateSerializeBufferSize();
+ btChunk* chunk = serializer->allocate(sz,1);
+ const char* structType = m_triangleInfoMap->serialize(chunk->m_oldPtr, serializer);
+ serializer->finalizeChunk(chunk,structType,BT_TRIANLGE_INFO_MAP,m_triangleInfoMap);
+ }
+ } else
+ {
+ trimeshData->m_triangleInfoMap = 0;
+ }
+
+ // Fill padding with zeros to appease msan.
+ memset(trimeshData->m_pad3, 0, sizeof(trimeshData->m_pad3));
+
+ return "btTriangleMeshShapeData";
+}
+
+void btBvhTriangleMeshShape::serializeSingleBvh(btSerializer* serializer) const
+{
+ if (m_bvh)
+ {
+ int len = m_bvh->calculateSerializeBufferSizeNew(); //make sure not to use calculateSerializeBufferSize because it is used for in-place
+ btChunk* chunk = serializer->allocate(len,1);
+ const char* structType = m_bvh->serialize(chunk->m_oldPtr, serializer);
+ serializer->finalizeChunk(chunk,structType,BT_QUANTIZED_BVH_CODE,(void*)m_bvh);
+ }
+}
+
+void btBvhTriangleMeshShape::serializeSingleTriangleInfoMap(btSerializer* serializer) const
+{
+ if (m_triangleInfoMap)
+ {
+ int len = m_triangleInfoMap->calculateSerializeBufferSize();
+ btChunk* chunk = serializer->allocate(len,1);
+ const char* structType = m_triangleInfoMap->serialize(chunk->m_oldPtr, serializer);
+ serializer->finalizeChunk(chunk,structType,BT_TRIANLGE_INFO_MAP,(void*)m_triangleInfoMap);
+ }
+}
+
+
+
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h
new file mode 100644
index 0000000000..1fa4995d16
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h
@@ -0,0 +1,149 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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_BVH_TRIANGLE_MESH_SHAPE_H
+#define BT_BVH_TRIANGLE_MESH_SHAPE_H
+
+#include "btTriangleMeshShape.h"
+#include "btOptimizedBvh.h"
+#include "LinearMath/btAlignedAllocator.h"
+#include "btTriangleInfoMap.h"
+
+///The btBvhTriangleMeshShape is a static-triangle mesh shape, it can only be used for fixed/non-moving objects.
+///If you required moving concave triangle meshes, it is recommended to perform convex decomposition
+///using HACD, see Bullet/Demos/ConvexDecompositionDemo.
+///Alternatively, you can use btGimpactMeshShape for moving concave triangle meshes.
+///btBvhTriangleMeshShape has several optimizations, such as bounding volume hierarchy and
+///cache friendly traversal for PlayStation 3 Cell SPU.
+///It is recommended to enable useQuantizedAabbCompression for better memory usage.
+///It takes a triangle mesh as input, for example a btTriangleMesh or btTriangleIndexVertexArray. The btBvhTriangleMeshShape class allows for triangle mesh deformations by a refit or partialRefit method.
+///Instead of building the bounding volume hierarchy acceleration structure, it is also possible to serialize (save) and deserialize (load) the structure from disk.
+///See Demos\ConcaveDemo\ConcavePhysicsDemo.cpp for an example.
+ATTRIBUTE_ALIGNED16(class) btBvhTriangleMeshShape : public btTriangleMeshShape
+{
+
+ btOptimizedBvh* m_bvh;
+ btTriangleInfoMap* m_triangleInfoMap;
+
+ bool m_useQuantizedAabbCompression;
+ bool m_ownsBvh;
+#ifdef __clang__
+ bool m_pad[11] __attribute__((unused));////need padding due to alignment
+#else
+ bool m_pad[11];////need padding due to alignment
+#endif
+
+public:
+
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+
+ btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, bool buildBvh = true);
+
+ ///optionally pass in a larger bvh aabb, used for quantization. This allows for deformations within this aabb
+ btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax, bool buildBvh = true);
+
+ virtual ~btBvhTriangleMeshShape();
+
+ bool getOwnsBvh () const
+ {
+ return m_ownsBvh;
+ }
+
+
+
+ void performRaycast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget);
+ void performConvexcast (btTriangleCallback* callback, const btVector3& boxSource, const btVector3& boxTarget, const btVector3& boxMin, const btVector3& boxMax);
+
+ virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
+
+ void refitTree(const btVector3& aabbMin,const btVector3& aabbMax);
+
+ ///for a fast incremental refit of parts of the tree. Note: the entire AABB of the tree will become more conservative, it never shrinks
+ void partialRefitTree(const btVector3& aabbMin,const btVector3& aabbMax);
+
+ //debugging
+ virtual const char* getName()const {return "BVHTRIANGLEMESH";}
+
+
+ virtual void setLocalScaling(const btVector3& scaling);
+
+ btOptimizedBvh* getOptimizedBvh()
+ {
+ return m_bvh;
+ }
+
+ void setOptimizedBvh(btOptimizedBvh* bvh, const btVector3& localScaling=btVector3(1,1,1));
+
+ void buildOptimizedBvh();
+
+ bool usesQuantizedAabbCompression() const
+ {
+ return m_useQuantizedAabbCompression;
+ }
+
+ void setTriangleInfoMap(btTriangleInfoMap* triangleInfoMap)
+ {
+ m_triangleInfoMap = triangleInfoMap;
+ }
+
+ const btTriangleInfoMap* getTriangleInfoMap() const
+ {
+ return m_triangleInfoMap;
+ }
+
+ btTriangleInfoMap* getTriangleInfoMap()
+ {
+ return m_triangleInfoMap;
+ }
+
+ virtual int calculateSerializeBufferSize() const;
+
+ ///fills the dataBuffer and returns the struct name (and 0 on failure)
+ virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
+
+ virtual void serializeSingleBvh(btSerializer* serializer) const;
+
+ virtual void serializeSingleTriangleInfoMap(btSerializer* serializer) const;
+
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btTriangleMeshShapeData
+{
+ btCollisionShapeData m_collisionShapeData;
+
+ btStridingMeshInterfaceData m_meshInterface;
+
+ btQuantizedBvhFloatData *m_quantizedFloatBvh;
+ btQuantizedBvhDoubleData *m_quantizedDoubleBvh;
+
+ btTriangleInfoMapData *m_triangleInfoMap;
+
+ float m_collisionMargin;
+
+ char m_pad3[4];
+
+};
+
+
+SIMD_FORCE_INLINE int btBvhTriangleMeshShape::calculateSerializeBufferSize() const
+{
+ return sizeof(btTriangleMeshShapeData);
+}
+
+
+
+#endif //BT_BVH_TRIANGLE_MESH_SHAPE_H
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp
new file mode 100644
index 0000000000..0345501ce2
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp
@@ -0,0 +1,169 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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 "btCapsuleShape.h"
+
+#include "LinearMath/btQuaternion.h"
+
+btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height) : btConvexInternalShape ()
+{
+ m_collisionMargin = radius;
+ m_shapeType = CAPSULE_SHAPE_PROXYTYPE;
+ m_upAxis = 1;
+ m_implicitShapeDimensions.setValue(radius,0.5f*height,radius);
+}
+
+
+ btVector3 btCapsuleShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0)const
+{
+
+ btVector3 supVec(0,0,0);
+
+ btScalar maxDot(btScalar(-BT_LARGE_FLOAT));
+
+ btVector3 vec = vec0;
+ btScalar lenSqr = vec.length2();
+ if (lenSqr < btScalar(0.0001))
+ {
+ vec.setValue(1,0,0);
+ } else
+ {
+ btScalar rlen = btScalar(1.) / btSqrt(lenSqr );
+ vec *= rlen;
+ }
+
+ btVector3 vtx;
+ btScalar newDot;
+
+
+
+ {
+ btVector3 pos(0,0,0);
+ pos[getUpAxis()] = getHalfHeight();
+
+ vtx = pos;
+ newDot = vec.dot(vtx);
+ if (newDot > maxDot)
+ {
+ maxDot = newDot;
+ supVec = vtx;
+ }
+ }
+ {
+ btVector3 pos(0,0,0);
+ pos[getUpAxis()] = -getHalfHeight();
+
+ vtx = pos;
+ newDot = vec.dot(vtx);
+ if (newDot > maxDot)
+ {
+ maxDot = newDot;
+ supVec = vtx;
+ }
+ }
+
+ return supVec;
+
+}
+
+ void btCapsuleShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+{
+
+
+
+ for (int j=0;j<numVectors;j++)
+ {
+ btScalar maxDot(btScalar(-BT_LARGE_FLOAT));
+ const btVector3& vec = vectors[j];
+
+ btVector3 vtx;
+ btScalar newDot;
+ {
+ btVector3 pos(0,0,0);
+ pos[getUpAxis()] = getHalfHeight();
+ vtx = pos;
+ newDot = vec.dot(vtx);
+ if (newDot > maxDot)
+ {
+ maxDot = newDot;
+ supportVerticesOut[j] = vtx;
+ }
+ }
+ {
+ btVector3 pos(0,0,0);
+ pos[getUpAxis()] = -getHalfHeight();
+ vtx = pos;
+ newDot = vec.dot(vtx);
+ if (newDot > maxDot)
+ {
+ maxDot = newDot;
+ supportVerticesOut[j] = vtx;
+ }
+ }
+
+ }
+}
+
+
+void btCapsuleShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+{
+ //as an approximation, take the inertia of the box that bounds the spheres
+
+ btTransform ident;
+ ident.setIdentity();
+
+
+ btScalar radius = getRadius();
+
+ btVector3 halfExtents(radius,radius,radius);
+ halfExtents[getUpAxis()]+=getHalfHeight();
+
+ btScalar lx=btScalar(2.)*(halfExtents[0]);
+ btScalar ly=btScalar(2.)*(halfExtents[1]);
+ btScalar lz=btScalar(2.)*(halfExtents[2]);
+ const btScalar x2 = lx*lx;
+ const btScalar y2 = ly*ly;
+ const btScalar z2 = lz*lz;
+ const btScalar scaledmass = mass * btScalar(.08333333);
+
+ inertia[0] = scaledmass * (y2+z2);
+ inertia[1] = scaledmass * (x2+z2);
+ inertia[2] = scaledmass * (x2+y2);
+
+}
+
+btCapsuleShapeX::btCapsuleShapeX(btScalar radius,btScalar height)
+{
+ m_collisionMargin = radius;
+ m_upAxis = 0;
+ m_implicitShapeDimensions.setValue(0.5f*height, radius,radius);
+}
+
+
+
+
+
+
+btCapsuleShapeZ::btCapsuleShapeZ(btScalar radius,btScalar height)
+{
+ m_collisionMargin = radius;
+ m_upAxis = 2;
+ m_implicitShapeDimensions.setValue(radius,radius,0.5f*height);
+}
+
+
+
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btCapsuleShape.h b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btCapsuleShape.h
new file mode 100644
index 0000000000..7d64b46abf
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btCapsuleShape.h
@@ -0,0 +1,190 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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_CAPSULE_SHAPE_H
+#define BT_CAPSULE_SHAPE_H
+
+#include "btConvexInternalShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
+
+
+///The btCapsuleShape represents a capsule around the Y axis, there is also the btCapsuleShapeX aligned around the X axis and btCapsuleShapeZ around the Z axis.
+///The total height is height+2*radius, so the height is just the height between the center of each 'sphere' of the capsule caps.
+///The btCapsuleShape is a convex hull of two spheres. The btMultiSphereShape is a more general collision shape that takes the convex hull of multiple sphere, so it can also represent a capsule when just using two spheres.
+ATTRIBUTE_ALIGNED16(class) btCapsuleShape : public btConvexInternalShape
+{
+protected:
+ int m_upAxis;
+
+protected:
+ ///only used for btCapsuleShapeZ and btCapsuleShapeX subclasses.
+ btCapsuleShape() : btConvexInternalShape() {m_shapeType = CAPSULE_SHAPE_PROXYTYPE;};
+
+public:
+
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ btCapsuleShape(btScalar radius,btScalar height);
+
+ ///CollisionShape Interface
+ virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+
+ /// btConvexShape Interface
+ virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
+
+ virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
+
+ virtual void setMargin(btScalar collisionMargin)
+ {
+ //don't override the margin for capsules, their entire radius == margin
+ }
+
+ virtual void getAabb (const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
+ {
+ btVector3 halfExtents(getRadius(),getRadius(),getRadius());
+ halfExtents[m_upAxis] = getRadius() + getHalfHeight();
+ btMatrix3x3 abs_b = t.getBasis().absolute();
+ btVector3 center = t.getOrigin();
+ btVector3 extent = halfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
+
+ aabbMin = center - extent;
+ aabbMax = center + extent;
+ }
+
+ virtual const char* getName()const
+ {
+ return "CapsuleShape";
+ }
+
+ int getUpAxis() const
+ {
+ return m_upAxis;
+ }
+
+ btScalar getRadius() const
+ {
+ int radiusAxis = (m_upAxis+2)%3;
+ return m_implicitShapeDimensions[radiusAxis];
+ }
+
+ btScalar getHalfHeight() const
+ {
+ return m_implicitShapeDimensions[m_upAxis];
+ }
+
+ virtual void setLocalScaling(const btVector3& scaling)
+ {
+ btVector3 unScaledImplicitShapeDimensions = m_implicitShapeDimensions / m_localScaling;
+ btConvexInternalShape::setLocalScaling(scaling);
+ m_implicitShapeDimensions = (unScaledImplicitShapeDimensions * scaling);
+ //update m_collisionMargin, since entire radius==margin
+ int radiusAxis = (m_upAxis+2)%3;
+ m_collisionMargin = m_implicitShapeDimensions[radiusAxis];
+ }
+
+ virtual btVector3 getAnisotropicRollingFrictionDirection() const
+ {
+ btVector3 aniDir(0,0,0);
+ aniDir[getUpAxis()]=1;
+ return aniDir;
+ }
+
+
+ virtual int calculateSerializeBufferSize() const;
+
+ ///fills the dataBuffer and returns the struct name (and 0 on failure)
+ virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
+
+ SIMD_FORCE_INLINE void deSerializeFloat(struct btCapsuleShapeData* dataBuffer);
+
+};
+
+///btCapsuleShapeX represents a capsule around the Z axis
+///the total height is height+2*radius, so the height is just the height between the center of each 'sphere' of the capsule caps.
+class btCapsuleShapeX : public btCapsuleShape
+{
+public:
+
+ btCapsuleShapeX(btScalar radius,btScalar height);
+
+ //debugging
+ virtual const char* getName()const
+ {
+ return "CapsuleX";
+ }
+
+
+
+};
+
+///btCapsuleShapeZ represents a capsule around the Z axis
+///the total height is height+2*radius, so the height is just the height between the center of each 'sphere' of the capsule caps.
+class btCapsuleShapeZ : public btCapsuleShape
+{
+public:
+ btCapsuleShapeZ(btScalar radius,btScalar height);
+
+ //debugging
+ virtual const char* getName()const
+ {
+ return "CapsuleZ";
+ }
+
+
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btCapsuleShapeData
+{
+ btConvexInternalShapeData m_convexInternalShapeData;
+
+ int m_upAxis;
+
+ char m_padding[4];
+};
+
+SIMD_FORCE_INLINE int btCapsuleShape::calculateSerializeBufferSize() const
+{
+ return sizeof(btCapsuleShapeData);
+}
+
+ ///fills the dataBuffer and returns the struct name (and 0 on failure)
+SIMD_FORCE_INLINE const char* btCapsuleShape::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+ btCapsuleShapeData* shapeData = (btCapsuleShapeData*) dataBuffer;
+
+ btConvexInternalShape::serialize(&shapeData->m_convexInternalShapeData,serializer);
+
+ shapeData->m_upAxis = m_upAxis;
+
+ // Fill padding with zeros to appease msan.
+ shapeData->m_padding[0] = 0;
+ shapeData->m_padding[1] = 0;
+ shapeData->m_padding[2] = 0;
+ shapeData->m_padding[3] = 0;
+
+ return "btCapsuleShapeData";
+}
+
+SIMD_FORCE_INLINE void btCapsuleShape::deSerializeFloat(btCapsuleShapeData* dataBuffer)
+{
+ m_implicitShapeDimensions.deSerializeFloat(dataBuffer->m_convexInternalShapeData.m_implicitShapeDimensions);
+ m_collisionMargin = dataBuffer->m_convexInternalShapeData.m_collisionMargin;
+ m_localScaling.deSerializeFloat(dataBuffer->m_convexInternalShapeData.m_localScaling);
+ //it is best to already pre-allocate the matching btCapsuleShape*(X/Z) version to match m_upAxis
+ m_upAxis = dataBuffer->m_upAxis;
+}
+
+#endif //BT_CAPSULE_SHAPE_H
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btCollisionMargin.h b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btCollisionMargin.h
new file mode 100644
index 0000000000..474bf1fb49
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btCollisionMargin.h
@@ -0,0 +1,27 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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_COLLISION_MARGIN_H
+#define BT_COLLISION_MARGIN_H
+
+///The CONVEX_DISTANCE_MARGIN is a default collision margin for convex collision shapes derived from btConvexInternalShape.
+///This collision margin is used by Gjk and some other algorithms
+///Note that when creating small objects, you need to make sure to set a smaller collision margin, using the 'setMargin' API
+#define CONVEX_DISTANCE_MARGIN btScalar(0.04)// btScalar(0.1)//;//btScalar(0.01)
+
+
+
+#endif //BT_COLLISION_MARGIN_H
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btCollisionShape.cpp b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btCollisionShape.cpp
new file mode 100644
index 0000000000..823e2788f2
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btCollisionShape.cpp
@@ -0,0 +1,122 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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 "BulletCollision/CollisionShapes/btCollisionShape.h"
+#include "LinearMath/btSerializer.h"
+
+/*
+ Make sure this dummy function never changes so that it
+ can be used by probes that are checking whether the
+ library is actually installed.
+*/
+extern "C"
+{
+void btBulletCollisionProbe ();
+
+void btBulletCollisionProbe () {}
+}
+
+
+
+void btCollisionShape::getBoundingSphere(btVector3& center,btScalar& radius) const
+{
+ btTransform tr;
+ tr.setIdentity();
+ btVector3 aabbMin,aabbMax;
+
+ getAabb(tr,aabbMin,aabbMax);
+
+ radius = (aabbMax-aabbMin).length()*btScalar(0.5);
+ center = (aabbMin+aabbMax)*btScalar(0.5);
+}
+
+
+btScalar btCollisionShape::getContactBreakingThreshold(btScalar defaultContactThreshold) const
+{
+ return getAngularMotionDisc() * defaultContactThreshold;
+}
+
+btScalar btCollisionShape::getAngularMotionDisc() const
+{
+ ///@todo cache this value, to improve performance
+ btVector3 center;
+ btScalar disc;
+ getBoundingSphere(center,disc);
+ disc += (center).length();
+ return disc;
+}
+
+void btCollisionShape::calculateTemporalAabb(const btTransform& curTrans,const btVector3& linvel,const btVector3& angvel,btScalar timeStep, btVector3& temporalAabbMin,btVector3& temporalAabbMax) const
+{
+ //start with static aabb
+ getAabb(curTrans,temporalAabbMin,temporalAabbMax);
+
+ btScalar temporalAabbMaxx = temporalAabbMax.getX();
+ btScalar temporalAabbMaxy = temporalAabbMax.getY();
+ btScalar temporalAabbMaxz = temporalAabbMax.getZ();
+ btScalar temporalAabbMinx = temporalAabbMin.getX();
+ btScalar temporalAabbMiny = temporalAabbMin.getY();
+ btScalar temporalAabbMinz = temporalAabbMin.getZ();
+
+ // add linear motion
+ btVector3 linMotion = linvel*timeStep;
+ ///@todo: simd would have a vector max/min operation, instead of per-element access
+ if (linMotion.x() > btScalar(0.))
+ temporalAabbMaxx += linMotion.x();
+ else
+ temporalAabbMinx += linMotion.x();
+ if (linMotion.y() > btScalar(0.))
+ temporalAabbMaxy += linMotion.y();
+ else
+ temporalAabbMiny += linMotion.y();
+ if (linMotion.z() > btScalar(0.))
+ temporalAabbMaxz += linMotion.z();
+ else
+ temporalAabbMinz += linMotion.z();
+
+ //add conservative angular motion
+ btScalar angularMotion = angvel.length() * getAngularMotionDisc() * timeStep;
+ btVector3 angularMotion3d(angularMotion,angularMotion,angularMotion);
+ temporalAabbMin = btVector3(temporalAabbMinx,temporalAabbMiny,temporalAabbMinz);
+ temporalAabbMax = btVector3(temporalAabbMaxx,temporalAabbMaxy,temporalAabbMaxz);
+
+ temporalAabbMin -= angularMotion3d;
+ temporalAabbMax += angularMotion3d;
+}
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+const char* btCollisionShape::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+ btCollisionShapeData* shapeData = (btCollisionShapeData*) dataBuffer;
+ char* name = (char*) serializer->findNameForPointer(this);
+ shapeData->m_name = (char*)serializer->getUniquePointer(name);
+ if (shapeData->m_name)
+ {
+ serializer->serializeName(name);
+ }
+ shapeData->m_shapeType = m_shapeType;
+
+ // Fill padding with zeros to appease msan.
+ memset(shapeData->m_padding, 0, sizeof(shapeData->m_padding));
+
+ return "btCollisionShapeData";
+}
+
+void btCollisionShape::serializeSingleShape(btSerializer* serializer) const
+{
+ int len = calculateSerializeBufferSize();
+ btChunk* chunk = serializer->allocate(len,1);
+ const char* structType = serialize(chunk->m_oldPtr, serializer);
+ serializer->finalizeChunk(chunk,structType,BT_SHAPE_CODE,(void*)this);
+} \ No newline at end of file
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btCollisionShape.h b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btCollisionShape.h
new file mode 100644
index 0000000000..6c4916fbd4
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btCollisionShape.h
@@ -0,0 +1,170 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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_COLLISION_SHAPE_H
+#define BT_COLLISION_SHAPE_H
+
+#include "LinearMath/btTransform.h"
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btMatrix3x3.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" //for the shape types
+class btSerializer;
+
+
+///The btCollisionShape class provides an interface for collision shapes that can be shared among btCollisionObjects.
+ATTRIBUTE_ALIGNED16(class) btCollisionShape
+{
+protected:
+ int m_shapeType;
+ void* m_userPointer;
+ int m_userIndex;
+
+public:
+
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ btCollisionShape() : m_shapeType (INVALID_SHAPE_PROXYTYPE), m_userPointer(0), m_userIndex(-1)
+ {
+ }
+
+ virtual ~btCollisionShape()
+ {
+ }
+
+ ///getAabb returns the axis aligned bounding box in the coordinate frame of the given transform t.
+ virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const =0;
+
+ virtual void getBoundingSphere(btVector3& center,btScalar& radius) const;
+
+ ///getAngularMotionDisc returns the maximum radius needed for Conservative Advancement to handle time-of-impact with rotations.
+ virtual btScalar getAngularMotionDisc() const;
+
+ virtual btScalar getContactBreakingThreshold(btScalar defaultContactThresholdFactor) const;
+
+
+ ///calculateTemporalAabb calculates the enclosing aabb for the moving object over interval [0..timeStep)
+ ///result is conservative
+ void calculateTemporalAabb(const btTransform& curTrans,const btVector3& linvel,const btVector3& angvel,btScalar timeStep, btVector3& temporalAabbMin,btVector3& temporalAabbMax) const;
+
+
+
+ SIMD_FORCE_INLINE bool isPolyhedral() const
+ {
+ return btBroadphaseProxy::isPolyhedral(getShapeType());
+ }
+
+ SIMD_FORCE_INLINE bool isConvex2d() const
+ {
+ return btBroadphaseProxy::isConvex2d(getShapeType());
+ }
+
+ SIMD_FORCE_INLINE bool isConvex() const
+ {
+ return btBroadphaseProxy::isConvex(getShapeType());
+ }
+ SIMD_FORCE_INLINE bool isNonMoving() const
+ {
+ return btBroadphaseProxy::isNonMoving(getShapeType());
+ }
+ SIMD_FORCE_INLINE bool isConcave() const
+ {
+ return btBroadphaseProxy::isConcave(getShapeType());
+ }
+ SIMD_FORCE_INLINE bool isCompound() const
+ {
+ return btBroadphaseProxy::isCompound(getShapeType());
+ }
+
+ SIMD_FORCE_INLINE bool isSoftBody() const
+ {
+ return btBroadphaseProxy::isSoftBody(getShapeType());
+ }
+
+ ///isInfinite is used to catch simulation error (aabb check)
+ SIMD_FORCE_INLINE bool isInfinite() const
+ {
+ return btBroadphaseProxy::isInfinite(getShapeType());
+ }
+
+#ifndef __SPU__
+ virtual void setLocalScaling(const btVector3& scaling) =0;
+ virtual const btVector3& getLocalScaling() const =0;
+ virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const = 0;
+
+
+//debugging support
+ virtual const char* getName()const =0 ;
+#endif //__SPU__
+
+
+ int getShapeType() const { return m_shapeType; }
+
+ ///the getAnisotropicRollingFrictionDirection can be used in combination with setAnisotropicFriction
+ ///See Bullet/Demos/RollingFrictionDemo for an example
+ virtual btVector3 getAnisotropicRollingFrictionDirection() const
+ {
+ return btVector3(1,1,1);
+ }
+ virtual void setMargin(btScalar margin) = 0;
+ virtual btScalar getMargin() const = 0;
+
+
+ ///optional user data pointer
+ void setUserPointer(void* userPtr)
+ {
+ m_userPointer = userPtr;
+ }
+
+ void* getUserPointer() const
+ {
+ return m_userPointer;
+ }
+ void setUserIndex(int index)
+ {
+ m_userIndex = index;
+ }
+
+ int getUserIndex() const
+ {
+ return m_userIndex;
+ }
+
+
+ virtual int calculateSerializeBufferSize() const;
+
+ ///fills the dataBuffer and returns the struct name (and 0 on failure)
+ virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
+
+ virtual void serializeSingleShape(btSerializer* serializer) const;
+
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btCollisionShapeData
+{
+ char *m_name;
+ int m_shapeType;
+ char m_padding[4];
+};
+
+SIMD_FORCE_INLINE int btCollisionShape::calculateSerializeBufferSize() const
+{
+ return sizeof(btCollisionShapeData);
+}
+
+
+
+#endif //BT_COLLISION_SHAPE_H
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btCompoundShape.cpp b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btCompoundShape.cpp
new file mode 100644
index 0000000000..e8c8c336cd
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btCompoundShape.cpp
@@ -0,0 +1,359 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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 "btCompoundShape.h"
+#include "btCollisionShape.h"
+#include "BulletCollision/BroadphaseCollision/btDbvt.h"
+#include "LinearMath/btSerializer.h"
+
+btCompoundShape::btCompoundShape(bool enableDynamicAabbTree, const int initialChildCapacity)
+: m_localAabbMin(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT)),
+m_localAabbMax(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT)),
+m_dynamicAabbTree(0),
+m_updateRevision(1),
+m_collisionMargin(btScalar(0.)),
+m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.))
+{
+ m_shapeType = COMPOUND_SHAPE_PROXYTYPE;
+
+ if (enableDynamicAabbTree)
+ {
+ void* mem = btAlignedAlloc(sizeof(btDbvt),16);
+ m_dynamicAabbTree = new(mem) btDbvt();
+ btAssert(mem==m_dynamicAabbTree);
+ }
+
+ m_children.reserve(initialChildCapacity);
+}
+
+
+btCompoundShape::~btCompoundShape()
+{
+ if (m_dynamicAabbTree)
+ {
+ m_dynamicAabbTree->~btDbvt();
+ btAlignedFree(m_dynamicAabbTree);
+ }
+}
+
+void btCompoundShape::addChildShape(const btTransform& localTransform,btCollisionShape* shape)
+{
+ m_updateRevision++;
+ //m_childTransforms.push_back(localTransform);
+ //m_childShapes.push_back(shape);
+ btCompoundShapeChild child;
+ child.m_node = 0;
+ child.m_transform = localTransform;
+ child.m_childShape = shape;
+ child.m_childShapeType = shape->getShapeType();
+ child.m_childMargin = shape->getMargin();
+
+
+ //extend the local aabbMin/aabbMax
+ btVector3 localAabbMin,localAabbMax;
+ shape->getAabb(localTransform,localAabbMin,localAabbMax);
+ for (int i=0;i<3;i++)
+ {
+ if (m_localAabbMin[i] > localAabbMin[i])
+ {
+ m_localAabbMin[i] = localAabbMin[i];
+ }
+ if (m_localAabbMax[i] < localAabbMax[i])
+ {
+ m_localAabbMax[i] = localAabbMax[i];
+ }
+
+ }
+ if (m_dynamicAabbTree)
+ {
+ const btDbvtVolume bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax);
+ size_t index = m_children.size();
+ child.m_node = m_dynamicAabbTree->insert(bounds,reinterpret_cast<void*>(index) );
+ }
+
+ m_children.push_back(child);
+
+}
+
+void btCompoundShape::updateChildTransform(int childIndex, const btTransform& newChildTransform,bool shouldRecalculateLocalAabb)
+{
+ m_children[childIndex].m_transform = newChildTransform;
+
+ if (m_dynamicAabbTree)
+ {
+ ///update the dynamic aabb tree
+ btVector3 localAabbMin,localAabbMax;
+ m_children[childIndex].m_childShape->getAabb(newChildTransform,localAabbMin,localAabbMax);
+ ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax);
+ //int index = m_children.size()-1;
+ m_dynamicAabbTree->update(m_children[childIndex].m_node,bounds);
+ }
+
+ if (shouldRecalculateLocalAabb)
+ {
+ recalculateLocalAabb();
+ }
+}
+
+void btCompoundShape::removeChildShapeByIndex(int childShapeIndex)
+{
+ m_updateRevision++;
+ btAssert(childShapeIndex >=0 && childShapeIndex < m_children.size());
+ if (m_dynamicAabbTree)
+ {
+ m_dynamicAabbTree->remove(m_children[childShapeIndex].m_node);
+ }
+ m_children.swap(childShapeIndex,m_children.size()-1);
+ if (m_dynamicAabbTree)
+ m_children[childShapeIndex].m_node->dataAsInt = childShapeIndex;
+ m_children.pop_back();
+
+}
+
+
+
+void btCompoundShape::removeChildShape(btCollisionShape* shape)
+{
+ m_updateRevision++;
+ // Find the children containing the shape specified, and remove those children.
+ //note: there might be multiple children using the same shape!
+ for(int i = m_children.size()-1; i >= 0 ; i--)
+ {
+ if(m_children[i].m_childShape == shape)
+ {
+ removeChildShapeByIndex(i);
+ }
+ }
+
+
+
+ recalculateLocalAabb();
+}
+
+void btCompoundShape::recalculateLocalAabb()
+{
+ // Recalculate the local aabb
+ // Brute force, it iterates over all the shapes left.
+
+ m_localAabbMin = btVector3(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
+ m_localAabbMax = btVector3(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT));
+
+ //extend the local aabbMin/aabbMax
+ for (int j = 0; j < m_children.size(); j++)
+ {
+ btVector3 localAabbMin,localAabbMax;
+ m_children[j].m_childShape->getAabb(m_children[j].m_transform, localAabbMin, localAabbMax);
+ for (int i=0;i<3;i++)
+ {
+ if (m_localAabbMin[i] > localAabbMin[i])
+ m_localAabbMin[i] = localAabbMin[i];
+ if (m_localAabbMax[i] < localAabbMax[i])
+ m_localAabbMax[i] = localAabbMax[i];
+ }
+ }
+}
+
+///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
+void btCompoundShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const
+{
+ btVector3 localHalfExtents = btScalar(0.5)*(m_localAabbMax-m_localAabbMin);
+ btVector3 localCenter = btScalar(0.5)*(m_localAabbMax+m_localAabbMin);
+
+ //avoid an illegal AABB when there are no children
+ if (!m_children.size())
+ {
+ localHalfExtents.setValue(0,0,0);
+ localCenter.setValue(0,0,0);
+ }
+ localHalfExtents += btVector3(getMargin(),getMargin(),getMargin());
+
+
+ btMatrix3x3 abs_b = trans.getBasis().absolute();
+
+ btVector3 center = trans(localCenter);
+
+ btVector3 extent = localHalfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
+ aabbMin = center-extent;
+ aabbMax = center+extent;
+
+}
+
+void btCompoundShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+{
+ //approximation: take the inertia from the aabb for now
+ btTransform ident;
+ ident.setIdentity();
+ btVector3 aabbMin,aabbMax;
+ getAabb(ident,aabbMin,aabbMax);
+
+ btVector3 halfExtents = (aabbMax-aabbMin)*btScalar(0.5);
+
+ btScalar lx=btScalar(2.)*(halfExtents.x());
+ btScalar ly=btScalar(2.)*(halfExtents.y());
+ btScalar lz=btScalar(2.)*(halfExtents.z());
+
+ inertia[0] = mass/(btScalar(12.0)) * (ly*ly + lz*lz);
+ inertia[1] = mass/(btScalar(12.0)) * (lx*lx + lz*lz);
+ inertia[2] = mass/(btScalar(12.0)) * (lx*lx + ly*ly);
+
+}
+
+
+
+
+void btCompoundShape::calculatePrincipalAxisTransform(btScalar* masses, btTransform& principal, btVector3& inertia) const
+{
+ int n = m_children.size();
+
+ btScalar totalMass = 0;
+ btVector3 center(0, 0, 0);
+ int k;
+
+ for (k = 0; k < n; k++)
+ {
+ btAssert(masses[k]>0);
+ center += m_children[k].m_transform.getOrigin() * masses[k];
+ totalMass += masses[k];
+ }
+
+ btAssert(totalMass>0);
+
+ center /= totalMass;
+ principal.setOrigin(center);
+
+ btMatrix3x3 tensor(0, 0, 0, 0, 0, 0, 0, 0, 0);
+ for ( k = 0; k < n; k++)
+ {
+ btVector3 i;
+ m_children[k].m_childShape->calculateLocalInertia(masses[k], i);
+
+ const btTransform& t = m_children[k].m_transform;
+ btVector3 o = t.getOrigin() - center;
+
+ //compute inertia tensor in coordinate system of compound shape
+ btMatrix3x3 j = t.getBasis().transpose();
+ j[0] *= i[0];
+ j[1] *= i[1];
+ j[2] *= i[2];
+ j = t.getBasis() * j;
+
+ //add inertia tensor
+ tensor[0] += j[0];
+ tensor[1] += j[1];
+ tensor[2] += j[2];
+
+ //compute inertia tensor of pointmass at o
+ btScalar o2 = o.length2();
+ j[0].setValue(o2, 0, 0);
+ j[1].setValue(0, o2, 0);
+ j[2].setValue(0, 0, o2);
+ j[0] += o * -o.x();
+ j[1] += o * -o.y();
+ j[2] += o * -o.z();
+
+ //add inertia tensor of pointmass
+ tensor[0] += masses[k] * j[0];
+ tensor[1] += masses[k] * j[1];
+ tensor[2] += masses[k] * j[2];
+ }
+
+ tensor.diagonalize(principal.getBasis(), btScalar(0.00001), 20);
+ inertia.setValue(tensor[0][0], tensor[1][1], tensor[2][2]);
+}
+
+
+
+
+
+void btCompoundShape::setLocalScaling(const btVector3& scaling)
+{
+
+ for(int i = 0; i < m_children.size(); i++)
+ {
+ btTransform childTrans = getChildTransform(i);
+ btVector3 childScale = m_children[i].m_childShape->getLocalScaling();
+// childScale = childScale * (childTrans.getBasis() * scaling);
+ childScale = childScale * scaling / m_localScaling;
+ m_children[i].m_childShape->setLocalScaling(childScale);
+ childTrans.setOrigin((childTrans.getOrigin()) * scaling / m_localScaling);
+ updateChildTransform(i, childTrans,false);
+ }
+
+ m_localScaling = scaling;
+ recalculateLocalAabb();
+
+}
+
+
+void btCompoundShape::createAabbTreeFromChildren()
+{
+ if ( !m_dynamicAabbTree )
+ {
+ void* mem = btAlignedAlloc(sizeof(btDbvt),16);
+ m_dynamicAabbTree = new(mem) btDbvt();
+ btAssert(mem==m_dynamicAabbTree);
+
+ for ( int index = 0; index < m_children.size(); index++ )
+ {
+ btCompoundShapeChild &child = m_children[index];
+
+ //extend the local aabbMin/aabbMax
+ btVector3 localAabbMin,localAabbMax;
+ child.m_childShape->getAabb(child.m_transform,localAabbMin,localAabbMax);
+
+ const btDbvtVolume bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax);
+ size_t index2 = index;
+ child.m_node = m_dynamicAabbTree->insert(bounds, reinterpret_cast<void*>(index2) );
+ }
+ }
+}
+
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+const char* btCompoundShape::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+
+ btCompoundShapeData* shapeData = (btCompoundShapeData*) dataBuffer;
+ btCollisionShape::serialize(&shapeData->m_collisionShapeData, serializer);
+
+ shapeData->m_collisionMargin = float(m_collisionMargin);
+ shapeData->m_numChildShapes = m_children.size();
+ shapeData->m_childShapePtr = 0;
+ if (shapeData->m_numChildShapes)
+ {
+ btChunk* chunk = serializer->allocate(sizeof(btCompoundShapeChildData),shapeData->m_numChildShapes);
+ btCompoundShapeChildData* memPtr = (btCompoundShapeChildData*)chunk->m_oldPtr;
+ shapeData->m_childShapePtr = (btCompoundShapeChildData*)serializer->getUniquePointer(memPtr);
+
+ for (int i=0;i<shapeData->m_numChildShapes;i++,memPtr++)
+ {
+ memPtr->m_childMargin = float(m_children[i].m_childMargin);
+ memPtr->m_childShape = (btCollisionShapeData*)serializer->getUniquePointer(m_children[i].m_childShape);
+ //don't serialize shapes that already have been serialized
+ if (!serializer->findPointer(m_children[i].m_childShape))
+ {
+ btChunk* chunk = serializer->allocate(m_children[i].m_childShape->calculateSerializeBufferSize(),1);
+ const char* structType = m_children[i].m_childShape->serialize(chunk->m_oldPtr,serializer);
+ serializer->finalizeChunk(chunk,structType,BT_SHAPE_CODE,m_children[i].m_childShape);
+ }
+
+ memPtr->m_childShapeType = m_children[i].m_childShapeType;
+ m_children[i].m_transform.serializeFloat(memPtr->m_transform);
+ }
+ serializer->finalizeChunk(chunk,"btCompoundShapeChildData",BT_ARRAY_CODE,chunk->m_oldPtr);
+ }
+ return "btCompoundShapeData";
+}
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btCompoundShape.h b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btCompoundShape.h
new file mode 100644
index 0000000000..4eef8dba30
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btCompoundShape.h
@@ -0,0 +1,212 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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_COMPOUND_SHAPE_H
+#define BT_COMPOUND_SHAPE_H
+
+#include "btCollisionShape.h"
+
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btTransform.h"
+#include "LinearMath/btMatrix3x3.h"
+#include "btCollisionMargin.h"
+#include "LinearMath/btAlignedObjectArray.h"
+
+//class btOptimizedBvh;
+struct btDbvt;
+
+ATTRIBUTE_ALIGNED16(struct) btCompoundShapeChild
+{
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ btTransform m_transform;
+ btCollisionShape* m_childShape;
+ int m_childShapeType;
+ btScalar m_childMargin;
+ struct btDbvtNode* m_node;
+};
+
+SIMD_FORCE_INLINE bool operator==(const btCompoundShapeChild& c1, const btCompoundShapeChild& c2)
+{
+ return ( c1.m_transform == c2.m_transform &&
+ c1.m_childShape == c2.m_childShape &&
+ c1.m_childShapeType == c2.m_childShapeType &&
+ c1.m_childMargin == c2.m_childMargin );
+}
+
+/// The btCompoundShape allows to store multiple other btCollisionShapes
+/// This allows for moving concave collision objects. This is more general then the static concave btBvhTriangleMeshShape.
+/// It has an (optional) dynamic aabb tree to accelerate early rejection tests.
+/// @todo: This aabb tree can also be use to speed up ray tests on btCompoundShape, see http://code.google.com/p/bullet/issues/detail?id=25
+/// Currently, removal of child shapes is only supported when disabling the aabb tree (pass 'false' in the constructor of btCompoundShape)
+ATTRIBUTE_ALIGNED16(class) btCompoundShape : public btCollisionShape
+{
+protected:
+ btAlignedObjectArray<btCompoundShapeChild> m_children;
+ btVector3 m_localAabbMin;
+ btVector3 m_localAabbMax;
+
+ btDbvt* m_dynamicAabbTree;
+
+ ///increment m_updateRevision when adding/removing/replacing child shapes, so that some caches can be updated
+ int m_updateRevision;
+
+ btScalar m_collisionMargin;
+
+ btVector3 m_localScaling;
+
+public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ explicit btCompoundShape(bool enableDynamicAabbTree = true, const int initialChildCapacity = 0);
+
+ virtual ~btCompoundShape();
+
+ void addChildShape(const btTransform& localTransform,btCollisionShape* shape);
+
+ /// Remove all children shapes that contain the specified shape
+ virtual void removeChildShape(btCollisionShape* shape);
+
+ void removeChildShapeByIndex(int childShapeindex);
+
+
+ int getNumChildShapes() const
+ {
+ return int (m_children.size());
+ }
+
+ btCollisionShape* getChildShape(int index)
+ {
+ return m_children[index].m_childShape;
+ }
+ const btCollisionShape* getChildShape(int index) const
+ {
+ return m_children[index].m_childShape;
+ }
+
+ btTransform& getChildTransform(int index)
+ {
+ return m_children[index].m_transform;
+ }
+ const btTransform& getChildTransform(int index) const
+ {
+ return m_children[index].m_transform;
+ }
+
+ ///set a new transform for a child, and update internal data structures (local aabb and dynamic tree)
+ void updateChildTransform(int childIndex, const btTransform& newChildTransform, bool shouldRecalculateLocalAabb = true);
+
+
+ btCompoundShapeChild* getChildList()
+ {
+ return &m_children[0];
+ }
+
+ ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
+ virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+
+ /** Re-calculate the local Aabb. Is called at the end of removeChildShapes.
+ Use this yourself if you modify the children or their transforms. */
+ virtual void recalculateLocalAabb();
+
+ virtual void setLocalScaling(const btVector3& scaling);
+
+ virtual const btVector3& getLocalScaling() const
+ {
+ return m_localScaling;
+ }
+
+ virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+
+ virtual void setMargin(btScalar margin)
+ {
+ m_collisionMargin = margin;
+ }
+ virtual btScalar getMargin() const
+ {
+ return m_collisionMargin;
+ }
+ virtual const char* getName()const
+ {
+ return "Compound";
+ }
+
+ const btDbvt* getDynamicAabbTree() const
+ {
+ return m_dynamicAabbTree;
+ }
+
+ btDbvt* getDynamicAabbTree()
+ {
+ return m_dynamicAabbTree;
+ }
+
+ void createAabbTreeFromChildren();
+
+ ///computes the exact moment of inertia and the transform from the coordinate system defined by the principal axes of the moment of inertia
+ ///and the center of mass to the current coordinate system. "masses" points to an array of masses of the children. The resulting transform
+ ///"principal" has to be applied inversely to all children transforms in order for the local coordinate system of the compound
+ ///shape to be centered at the center of mass and to coincide with the principal axes. This also necessitates a correction of the world transform
+ ///of the collision object by the principal transform.
+ void calculatePrincipalAxisTransform(btScalar* masses, btTransform& principal, btVector3& inertia) const;
+
+ int getUpdateRevision() const
+ {
+ return m_updateRevision;
+ }
+
+ virtual int calculateSerializeBufferSize() const;
+
+ ///fills the dataBuffer and returns the struct name (and 0 on failure)
+ virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
+
+
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btCompoundShapeChildData
+{
+ btTransformFloatData m_transform;
+ btCollisionShapeData *m_childShape;
+ int m_childShapeType;
+ float m_childMargin;
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btCompoundShapeData
+{
+ btCollisionShapeData m_collisionShapeData;
+
+ btCompoundShapeChildData *m_childShapePtr;
+
+ int m_numChildShapes;
+
+ float m_collisionMargin;
+
+};
+
+
+SIMD_FORCE_INLINE int btCompoundShape::calculateSerializeBufferSize() const
+{
+ return sizeof(btCompoundShapeData);
+}
+
+
+
+
+
+
+
+#endif //BT_COMPOUND_SHAPE_H
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btConcaveShape.cpp b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btConcaveShape.cpp
new file mode 100644
index 0000000000..58ff84a5b0
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btConcaveShape.cpp
@@ -0,0 +1,27 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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 "btConcaveShape.h"
+
+btConcaveShape::btConcaveShape() : m_collisionMargin(btScalar(0.))
+{
+
+}
+
+btConcaveShape::~btConcaveShape()
+{
+
+}
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btConcaveShape.h b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btConcaveShape.h
new file mode 100644
index 0000000000..2917cc5b60
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btConcaveShape.h
@@ -0,0 +1,62 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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_CONCAVE_SHAPE_H
+#define BT_CONCAVE_SHAPE_H
+
+#include "btCollisionShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
+#include "btTriangleCallback.h"
+
+/// PHY_ScalarType enumerates possible scalar types.
+/// See the btStridingMeshInterface or btHeightfieldTerrainShape for its use
+typedef enum PHY_ScalarType {
+ PHY_FLOAT,
+ PHY_DOUBLE,
+ PHY_INTEGER,
+ PHY_SHORT,
+ PHY_FIXEDPOINT88,
+ PHY_UCHAR
+} PHY_ScalarType;
+
+///The btConcaveShape class provides an interface for non-moving (static) concave shapes.
+///It has been implemented by the btStaticPlaneShape, btBvhTriangleMeshShape and btHeightfieldTerrainShape.
+ATTRIBUTE_ALIGNED16(class) btConcaveShape : public btCollisionShape
+{
+protected:
+ btScalar m_collisionMargin;
+
+public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ btConcaveShape();
+
+ virtual ~btConcaveShape();
+
+ virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const = 0;
+
+ virtual btScalar getMargin() const {
+ return m_collisionMargin;
+ }
+ virtual void setMargin(btScalar collisionMargin)
+ {
+ m_collisionMargin = collisionMargin;
+ }
+
+
+
+};
+
+#endif //BT_CONCAVE_SHAPE_H
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btConeShape.cpp b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btConeShape.cpp
new file mode 100644
index 0000000000..2d83c8bfba
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btConeShape.cpp
@@ -0,0 +1,147 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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 "btConeShape.h"
+
+
+
+btConeShape::btConeShape (btScalar radius,btScalar height): btConvexInternalShape (),
+m_radius (radius),
+m_height(height)
+{
+ m_shapeType = CONE_SHAPE_PROXYTYPE;
+ setConeUpIndex(1);
+ btVector3 halfExtents;
+ m_sinAngle = (m_radius / btSqrt(m_radius * m_radius + m_height * m_height));
+}
+
+btConeShapeZ::btConeShapeZ (btScalar radius,btScalar height):
+btConeShape(radius,height)
+{
+ setConeUpIndex(2);
+}
+
+btConeShapeX::btConeShapeX (btScalar radius,btScalar height):
+btConeShape(radius,height)
+{
+ setConeUpIndex(0);
+}
+
+///choose upAxis index
+void btConeShape::setConeUpIndex(int upIndex)
+{
+ switch (upIndex)
+ {
+ case 0:
+ m_coneIndices[0] = 1;
+ m_coneIndices[1] = 0;
+ m_coneIndices[2] = 2;
+ break;
+ case 1:
+ m_coneIndices[0] = 0;
+ m_coneIndices[1] = 1;
+ m_coneIndices[2] = 2;
+ break;
+ case 2:
+ m_coneIndices[0] = 0;
+ m_coneIndices[1] = 2;
+ m_coneIndices[2] = 1;
+ break;
+ default:
+ btAssert(0);
+ };
+
+ m_implicitShapeDimensions[m_coneIndices[0]] = m_radius;
+ m_implicitShapeDimensions[m_coneIndices[1]] = m_height;
+ m_implicitShapeDimensions[m_coneIndices[2]] = m_radius;
+}
+
+btVector3 btConeShape::coneLocalSupport(const btVector3& v) const
+{
+
+ btScalar halfHeight = m_height * btScalar(0.5);
+
+ if (v[m_coneIndices[1]] > v.length() * m_sinAngle)
+ {
+ btVector3 tmp;
+
+ tmp[m_coneIndices[0]] = btScalar(0.);
+ tmp[m_coneIndices[1]] = halfHeight;
+ tmp[m_coneIndices[2]] = btScalar(0.);
+ return tmp;
+ }
+ else {
+ btScalar s = btSqrt(v[m_coneIndices[0]] * v[m_coneIndices[0]] + v[m_coneIndices[2]] * v[m_coneIndices[2]]);
+ if (s > SIMD_EPSILON) {
+ btScalar d = m_radius / s;
+ btVector3 tmp;
+ tmp[m_coneIndices[0]] = v[m_coneIndices[0]] * d;
+ tmp[m_coneIndices[1]] = -halfHeight;
+ tmp[m_coneIndices[2]] = v[m_coneIndices[2]] * d;
+ return tmp;
+ }
+ else {
+ btVector3 tmp;
+ tmp[m_coneIndices[0]] = btScalar(0.);
+ tmp[m_coneIndices[1]] = -halfHeight;
+ tmp[m_coneIndices[2]] = btScalar(0.);
+ return tmp;
+ }
+ }
+
+}
+
+btVector3 btConeShape::localGetSupportingVertexWithoutMargin(const btVector3& vec) const
+{
+ return coneLocalSupport(vec);
+}
+
+void btConeShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+{
+ for (int i=0;i<numVectors;i++)
+ {
+ const btVector3& vec = vectors[i];
+ supportVerticesOut[i] = coneLocalSupport(vec);
+ }
+}
+
+
+btVector3 btConeShape::localGetSupportingVertex(const btVector3& vec) const
+{
+ btVector3 supVertex = coneLocalSupport(vec);
+ if ( getMargin()!=btScalar(0.) )
+ {
+ btVector3 vecnorm = vec;
+ if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON))
+ {
+ vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.));
+ }
+ vecnorm.normalize();
+ supVertex+= getMargin() * vecnorm;
+ }
+ return supVertex;
+}
+
+
+void btConeShape::setLocalScaling(const btVector3& scaling)
+{
+ int axis = m_coneIndices[1];
+ int r1 = m_coneIndices[0];
+ int r2 = m_coneIndices[2];
+ m_height *= scaling[axis] / m_localScaling[axis];
+ m_radius *= (scaling[r1] / m_localScaling[r1] + scaling[r2] / m_localScaling[r2]) / 2;
+ m_sinAngle = (m_radius / btSqrt(m_radius * m_radius + m_height * m_height));
+ btConvexInternalShape::setLocalScaling(scaling);
+} \ No newline at end of file
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btConeShape.h b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btConeShape.h
new file mode 100644
index 0000000000..3b44e3f272
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btConeShape.h
@@ -0,0 +1,186 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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_CONE_MINKOWSKI_H
+#define BT_CONE_MINKOWSKI_H
+
+#include "btConvexInternalShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
+
+///The btConeShape implements a cone shape primitive, centered around the origin and aligned with the Y axis. The btConeShapeX is aligned around the X axis and btConeShapeZ around the Z axis.
+ATTRIBUTE_ALIGNED16(class) btConeShape : public btConvexInternalShape
+
+{
+
+ btScalar m_sinAngle;
+ btScalar m_radius;
+ btScalar m_height;
+ int m_coneIndices[3];
+ btVector3 coneLocalSupport(const btVector3& v) const;
+
+
+public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ btConeShape (btScalar radius,btScalar height);
+
+ virtual btVector3 localGetSupportingVertex(const btVector3& vec) const;
+ virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const;
+ virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
+
+ btScalar getRadius() const { return m_radius;}
+ btScalar getHeight() const { return m_height;}
+
+ void setRadius(const btScalar radius)
+ {
+ m_radius = radius;
+ }
+ void setHeight(const btScalar height)
+ {
+ m_height = height;
+ }
+
+
+ virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const
+ {
+ btTransform identity;
+ identity.setIdentity();
+ btVector3 aabbMin,aabbMax;
+ getAabb(identity,aabbMin,aabbMax);
+
+ btVector3 halfExtents = (aabbMax-aabbMin)*btScalar(0.5);
+
+ btScalar margin = getMargin();
+
+ btScalar lx=btScalar(2.)*(halfExtents.x()+margin);
+ btScalar ly=btScalar(2.)*(halfExtents.y()+margin);
+ btScalar lz=btScalar(2.)*(halfExtents.z()+margin);
+ const btScalar x2 = lx*lx;
+ const btScalar y2 = ly*ly;
+ const btScalar z2 = lz*lz;
+ const btScalar scaledmass = mass * btScalar(0.08333333);
+
+ inertia = scaledmass * (btVector3(y2+z2,x2+z2,x2+y2));
+
+// inertia.x() = scaledmass * (y2+z2);
+// inertia.y() = scaledmass * (x2+z2);
+// inertia.z() = scaledmass * (x2+y2);
+ }
+
+
+ virtual const char* getName()const
+ {
+ return "Cone";
+ }
+
+ ///choose upAxis index
+ void setConeUpIndex(int upIndex);
+
+ int getConeUpIndex() const
+ {
+ return m_coneIndices[1];
+ }
+
+ virtual btVector3 getAnisotropicRollingFrictionDirection() const
+ {
+ return btVector3 (0,1,0);
+ }
+
+ virtual void setLocalScaling(const btVector3& scaling);
+
+
+ virtual int calculateSerializeBufferSize() const;
+
+ ///fills the dataBuffer and returns the struct name (and 0 on failure)
+ virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
+
+
+};
+
+///btConeShape implements a Cone shape, around the X axis
+class btConeShapeX : public btConeShape
+{
+ public:
+ btConeShapeX(btScalar radius,btScalar height);
+
+ virtual btVector3 getAnisotropicRollingFrictionDirection() const
+ {
+ return btVector3 (1,0,0);
+ }
+
+ //debugging
+ virtual const char* getName()const
+ {
+ return "ConeX";
+ }
+
+
+};
+
+///btConeShapeZ implements a Cone shape, around the Z axis
+class btConeShapeZ : public btConeShape
+{
+public:
+ btConeShapeZ(btScalar radius,btScalar height);
+
+ virtual btVector3 getAnisotropicRollingFrictionDirection() const
+ {
+ return btVector3 (0,0,1);
+ }
+
+ //debugging
+ virtual const char* getName()const
+ {
+ return "ConeZ";
+ }
+
+
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btConeShapeData
+{
+ btConvexInternalShapeData m_convexInternalShapeData;
+
+ int m_upIndex;
+
+ char m_padding[4];
+};
+
+SIMD_FORCE_INLINE int btConeShape::calculateSerializeBufferSize() const
+{
+ return sizeof(btConeShapeData);
+}
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+SIMD_FORCE_INLINE const char* btConeShape::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+ btConeShapeData* shapeData = (btConeShapeData*) dataBuffer;
+
+ btConvexInternalShape::serialize(&shapeData->m_convexInternalShapeData,serializer);
+
+ shapeData->m_upIndex = m_coneIndices[1];
+
+ // Fill padding with zeros to appease msan.
+ shapeData->m_padding[0] = 0;
+ shapeData->m_padding[1] = 0;
+ shapeData->m_padding[2] = 0;
+ shapeData->m_padding[3] = 0;
+
+ return "btConeShapeData";
+}
+
+#endif //BT_CONE_MINKOWSKI_H
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btConvex2dShape.cpp b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btConvex2dShape.cpp
new file mode 100644
index 0000000000..10ea3e981a
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btConvex2dShape.cpp
@@ -0,0 +1,92 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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 "btConvex2dShape.h"
+
+btConvex2dShape::btConvex2dShape( btConvexShape* convexChildShape):
+btConvexShape (), m_childConvexShape(convexChildShape)
+{
+ m_shapeType = CONVEX_2D_SHAPE_PROXYTYPE;
+}
+
+btConvex2dShape::~btConvex2dShape()
+{
+}
+
+
+
+btVector3 btConvex2dShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const
+{
+ return m_childConvexShape->localGetSupportingVertexWithoutMargin(vec);
+}
+
+void btConvex2dShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+{
+ m_childConvexShape->batchedUnitVectorGetSupportingVertexWithoutMargin(vectors,supportVerticesOut,numVectors);
+}
+
+
+btVector3 btConvex2dShape::localGetSupportingVertex(const btVector3& vec)const
+{
+ return m_childConvexShape->localGetSupportingVertex(vec);
+}
+
+
+void btConvex2dShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+{
+ ///this linear upscaling is not realistic, but we don't deal with large mass ratios...
+ m_childConvexShape->calculateLocalInertia(mass,inertia);
+}
+
+
+ ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
+void btConvex2dShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+{
+ m_childConvexShape->getAabb(t,aabbMin,aabbMax);
+}
+
+void btConvex2dShape::getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+{
+ m_childConvexShape->getAabbSlow(t,aabbMin,aabbMax);
+}
+
+void btConvex2dShape::setLocalScaling(const btVector3& scaling)
+{
+ m_childConvexShape->setLocalScaling(scaling);
+}
+
+const btVector3& btConvex2dShape::getLocalScaling() const
+{
+ return m_childConvexShape->getLocalScaling();
+}
+
+void btConvex2dShape::setMargin(btScalar margin)
+{
+ m_childConvexShape->setMargin(margin);
+}
+btScalar btConvex2dShape::getMargin() const
+{
+ return m_childConvexShape->getMargin();
+}
+
+int btConvex2dShape::getNumPreferredPenetrationDirections() const
+{
+ return m_childConvexShape->getNumPreferredPenetrationDirections();
+}
+
+void btConvex2dShape::getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const
+{
+ m_childConvexShape->getPreferredPenetrationDirection(index,penetrationVector);
+}
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btConvex2dShape.h b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btConvex2dShape.h
new file mode 100644
index 0000000000..bbd1caf42f
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btConvex2dShape.h
@@ -0,0 +1,82 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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_CONVEX_2D_SHAPE_H
+#define BT_CONVEX_2D_SHAPE_H
+
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
+
+///The btConvex2dShape allows to use arbitrary convex shapes as 2d convex shapes, with the Z component assumed to be 0.
+///For 2d boxes, the btBox2dShape is recommended.
+ATTRIBUTE_ALIGNED16(class) btConvex2dShape : public btConvexShape
+{
+ btConvexShape* m_childConvexShape;
+
+ public:
+
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ btConvex2dShape( btConvexShape* convexChildShape);
+
+ virtual ~btConvex2dShape();
+
+ virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
+
+ virtual btVector3 localGetSupportingVertex(const btVector3& vec)const;
+
+ virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
+
+ virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+
+ btConvexShape* getChildShape()
+ {
+ return m_childConvexShape;
+ }
+
+ const btConvexShape* getChildShape() const
+ {
+ return m_childConvexShape;
+ }
+
+ virtual const char* getName()const
+ {
+ return "Convex2dShape";
+ }
+
+
+
+ ///////////////////////////
+
+
+ ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
+ void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+
+ virtual void getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+
+ virtual void setLocalScaling(const btVector3& scaling) ;
+ virtual const btVector3& getLocalScaling() const ;
+
+ virtual void setMargin(btScalar margin);
+ virtual btScalar getMargin() const;
+
+ virtual int getNumPreferredPenetrationDirections() const;
+
+ virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const;
+
+
+};
+
+#endif //BT_CONVEX_2D_SHAPE_H
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btConvexHullShape.cpp b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btConvexHullShape.cpp
new file mode 100644
index 0000000000..a7a9598406
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btConvexHullShape.cpp
@@ -0,0 +1,262 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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.
+*/
+
+#if defined (_WIN32) || defined (__i386__)
+#define BT_USE_SSE_IN_API
+#endif
+
+#include "btConvexHullShape.h"
+#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
+
+#include "LinearMath/btQuaternion.h"
+#include "LinearMath/btSerializer.h"
+#include "btConvexPolyhedron.h"
+#include "LinearMath/btConvexHullComputer.h"
+
+btConvexHullShape ::btConvexHullShape (const btScalar* points,int numPoints,int stride) : btPolyhedralConvexAabbCachingShape ()
+{
+ m_shapeType = CONVEX_HULL_SHAPE_PROXYTYPE;
+ m_unscaledPoints.resize(numPoints);
+
+ unsigned char* pointsAddress = (unsigned char*)points;
+
+ for (int i=0;i<numPoints;i++)
+ {
+ btScalar* point = (btScalar*)pointsAddress;
+ m_unscaledPoints[i] = btVector3(point[0], point[1], point[2]);
+ pointsAddress += stride;
+ }
+
+ recalcLocalAabb();
+
+}
+
+
+
+void btConvexHullShape::setLocalScaling(const btVector3& scaling)
+{
+ m_localScaling = scaling;
+ recalcLocalAabb();
+}
+
+void btConvexHullShape::addPoint(const btVector3& point, bool recalculateLocalAabb)
+{
+ m_unscaledPoints.push_back(point);
+ if (recalculateLocalAabb)
+ recalcLocalAabb();
+
+}
+
+btVector3 btConvexHullShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const
+{
+ btVector3 supVec(btScalar(0.),btScalar(0.),btScalar(0.));
+ btScalar maxDot = btScalar(-BT_LARGE_FLOAT);
+
+ // Here we take advantage of dot(a, b*c) = dot(a*b, c). Note: This is true mathematically, but not numerically.
+ if( 0 < m_unscaledPoints.size() )
+ {
+ btVector3 scaled = vec * m_localScaling;
+ int index = (int) scaled.maxDot( &m_unscaledPoints[0], m_unscaledPoints.size(), maxDot); // FIXME: may violate encapsulation of m_unscaledPoints
+ return m_unscaledPoints[index] * m_localScaling;
+ }
+
+ return supVec;
+}
+
+void btConvexHullShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+{
+ btScalar newDot;
+ //use 'w' component of supportVerticesOut?
+ {
+ for (int i=0;i<numVectors;i++)
+ {
+ supportVerticesOut[i][3] = btScalar(-BT_LARGE_FLOAT);
+ }
+ }
+
+ for (int j=0;j<numVectors;j++)
+ {
+ btVector3 vec = vectors[j] * m_localScaling; // dot(a*b,c) = dot(a,b*c)
+ if( 0 < m_unscaledPoints.size() )
+ {
+ int i = (int) vec.maxDot( &m_unscaledPoints[0], m_unscaledPoints.size(), newDot);
+ supportVerticesOut[j] = getScaledPoint(i);
+ supportVerticesOut[j][3] = newDot;
+ }
+ else
+ supportVerticesOut[j][3] = -BT_LARGE_FLOAT;
+ }
+
+
+
+}
+
+
+
+btVector3 btConvexHullShape::localGetSupportingVertex(const btVector3& vec)const
+{
+ btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec);
+
+ if ( getMargin()!=btScalar(0.) )
+ {
+ btVector3 vecnorm = vec;
+ if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON))
+ {
+ vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.));
+ }
+ vecnorm.normalize();
+ supVertex+= getMargin() * vecnorm;
+ }
+ return supVertex;
+}
+
+
+void btConvexHullShape::optimizeConvexHull()
+{
+ btConvexHullComputer conv;
+ conv.compute(&m_unscaledPoints[0].getX(), sizeof(btVector3),m_unscaledPoints.size(),0.f,0.f);
+ int numVerts = conv.vertices.size();
+ m_unscaledPoints.resize(0);
+ for (int i=0;i<numVerts;i++)
+ {
+ m_unscaledPoints.push_back(conv.vertices[i]);
+ }
+}
+
+
+
+//currently just for debugging (drawing), perhaps future support for algebraic continuous collision detection
+//Please note that you can debug-draw btConvexHullShape with the Raytracer Demo
+int btConvexHullShape::getNumVertices() const
+{
+ return m_unscaledPoints.size();
+}
+
+int btConvexHullShape::getNumEdges() const
+{
+ return m_unscaledPoints.size();
+}
+
+void btConvexHullShape::getEdge(int i,btVector3& pa,btVector3& pb) const
+{
+
+ int index0 = i%m_unscaledPoints.size();
+ int index1 = (i+1)%m_unscaledPoints.size();
+ pa = getScaledPoint(index0);
+ pb = getScaledPoint(index1);
+}
+
+void btConvexHullShape::getVertex(int i,btVector3& vtx) const
+{
+ vtx = getScaledPoint(i);
+}
+
+int btConvexHullShape::getNumPlanes() const
+{
+ return 0;
+}
+
+void btConvexHullShape::getPlane(btVector3& ,btVector3& ,int ) const
+{
+
+ btAssert(0);
+}
+
+//not yet
+bool btConvexHullShape::isInside(const btVector3& ,btScalar ) const
+{
+ btAssert(0);
+ return false;
+}
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+const char* btConvexHullShape::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+ //int szc = sizeof(btConvexHullShapeData);
+ btConvexHullShapeData* shapeData = (btConvexHullShapeData*) dataBuffer;
+ btConvexInternalShape::serialize(&shapeData->m_convexInternalShapeData, serializer);
+
+ int numElem = m_unscaledPoints.size();
+ shapeData->m_numUnscaledPoints = numElem;
+#ifdef BT_USE_DOUBLE_PRECISION
+ shapeData->m_unscaledPointsFloatPtr = 0;
+ shapeData->m_unscaledPointsDoublePtr = numElem ? (btVector3Data*)serializer->getUniquePointer((void*)&m_unscaledPoints[0]): 0;
+#else
+ shapeData->m_unscaledPointsFloatPtr = numElem ? (btVector3Data*)serializer->getUniquePointer((void*)&m_unscaledPoints[0]): 0;
+ shapeData->m_unscaledPointsDoublePtr = 0;
+#endif
+
+ if (numElem)
+ {
+ int sz = sizeof(btVector3Data);
+ // int sz2 = sizeof(btVector3DoubleData);
+ // int sz3 = sizeof(btVector3FloatData);
+ btChunk* chunk = serializer->allocate(sz,numElem);
+ btVector3Data* memPtr = (btVector3Data*)chunk->m_oldPtr;
+ for (int i=0;i<numElem;i++,memPtr++)
+ {
+ m_unscaledPoints[i].serialize(*memPtr);
+ }
+ serializer->finalizeChunk(chunk,btVector3DataName,BT_ARRAY_CODE,(void*)&m_unscaledPoints[0]);
+ }
+
+ // Fill padding with zeros to appease msan.
+ memset(shapeData->m_padding3, 0, sizeof(shapeData->m_padding3));
+
+ return "btConvexHullShapeData";
+}
+
+void btConvexHullShape::project(const btTransform& trans, const btVector3& dir, btScalar& minProj, btScalar& maxProj, btVector3& witnesPtMin,btVector3& witnesPtMax) const
+{
+#if 1
+ minProj = FLT_MAX;
+ maxProj = -FLT_MAX;
+
+ int numVerts = m_unscaledPoints.size();
+ for(int i=0;i<numVerts;i++)
+ {
+ btVector3 vtx = m_unscaledPoints[i] * m_localScaling;
+ btVector3 pt = trans * vtx;
+ btScalar dp = pt.dot(dir);
+ if(dp < minProj)
+ {
+ minProj = dp;
+ witnesPtMin = pt;
+ }
+ if(dp > maxProj)
+ {
+ maxProj = dp;
+ witnesPtMax=pt;
+ }
+ }
+#else
+ btVector3 localAxis = dir*trans.getBasis();
+ witnesPtMin = trans(localGetSupportingVertex(localAxis));
+ witnesPtMax = trans(localGetSupportingVertex(-localAxis));
+
+ minProj = witnesPtMin.dot(dir);
+ maxProj = witnesPtMax.dot(dir);
+#endif
+
+ if(minProj>maxProj)
+ {
+ btSwap(minProj,maxProj);
+ btSwap(witnesPtMin,witnesPtMax);
+ }
+
+
+}
+
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btConvexHullShape.h b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btConvexHullShape.h
new file mode 100644
index 0000000000..0c12aeef15
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btConvexHullShape.h
@@ -0,0 +1,121 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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_CONVEX_HULL_SHAPE_H
+#define BT_CONVEX_HULL_SHAPE_H
+
+#include "btPolyhedralConvexShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
+#include "LinearMath/btAlignedObjectArray.h"
+
+
+///The btConvexHullShape implements an implicit convex hull of an array of vertices.
+///Bullet provides a general and fast collision detector for convex shapes based on GJK and EPA using localGetSupportingVertex.
+ATTRIBUTE_ALIGNED16(class) btConvexHullShape : public btPolyhedralConvexAabbCachingShape
+{
+ btAlignedObjectArray<btVector3> m_unscaledPoints;
+
+public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+
+ ///this constructor optionally takes in a pointer to points. Each point is assumed to be 3 consecutive btScalar (x,y,z), the striding defines the number of bytes between each point, in memory.
+ ///It is easier to not pass any points in the constructor, and just add one point at a time, using addPoint.
+ ///btConvexHullShape make an internal copy of the points.
+ btConvexHullShape(const btScalar* points=0,int numPoints=0, int stride=sizeof(btVector3));
+
+ void addPoint(const btVector3& point, bool recalculateLocalAabb = true);
+
+
+ btVector3* getUnscaledPoints()
+ {
+ return &m_unscaledPoints[0];
+ }
+
+ const btVector3* getUnscaledPoints() const
+ {
+ return &m_unscaledPoints[0];
+ }
+
+ ///getPoints is obsolete, please use getUnscaledPoints
+ const btVector3* getPoints() const
+ {
+ return getUnscaledPoints();
+ }
+
+ void optimizeConvexHull();
+
+ SIMD_FORCE_INLINE btVector3 getScaledPoint(int i) const
+ {
+ return m_unscaledPoints[i] * m_localScaling;
+ }
+
+ SIMD_FORCE_INLINE int getNumPoints() const
+ {
+ return m_unscaledPoints.size();
+ }
+
+ virtual btVector3 localGetSupportingVertex(const btVector3& vec)const;
+ virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
+ virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
+
+
+ virtual void project(const btTransform& trans, const btVector3& dir, btScalar& minProj, btScalar& maxProj, btVector3& witnesPtMin,btVector3& witnesPtMax) const;
+
+
+ //debugging
+ virtual const char* getName()const {return "Convex";}
+
+
+ virtual int getNumVertices() const;
+ virtual int getNumEdges() const;
+ virtual void getEdge(int i,btVector3& pa,btVector3& pb) const;
+ virtual void getVertex(int i,btVector3& vtx) const;
+ virtual int getNumPlanes() const;
+ virtual void getPlane(btVector3& planeNormal,btVector3& planeSupport,int i ) const;
+ virtual bool isInside(const btVector3& pt,btScalar tolerance) const;
+
+ ///in case we receive negative scaling
+ virtual void setLocalScaling(const btVector3& scaling);
+
+ virtual int calculateSerializeBufferSize() const;
+
+ ///fills the dataBuffer and returns the struct name (and 0 on failure)
+ virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
+
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btConvexHullShapeData
+{
+ btConvexInternalShapeData m_convexInternalShapeData;
+
+ btVector3FloatData *m_unscaledPointsFloatPtr;
+ btVector3DoubleData *m_unscaledPointsDoublePtr;
+
+ int m_numUnscaledPoints;
+ char m_padding3[4];
+
+};
+
+
+SIMD_FORCE_INLINE int btConvexHullShape::calculateSerializeBufferSize() const
+{
+ return sizeof(btConvexHullShapeData);
+}
+
+
+#endif //BT_CONVEX_HULL_SHAPE_H
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp
new file mode 100644
index 0000000000..083d60b1b1
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp
@@ -0,0 +1,151 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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 "btConvexInternalShape.h"
+
+
+
+btConvexInternalShape::btConvexInternalShape()
+: m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.)),
+m_collisionMargin(CONVEX_DISTANCE_MARGIN)
+{
+}
+
+
+void btConvexInternalShape::setLocalScaling(const btVector3& scaling)
+{
+ m_localScaling = scaling.absolute();
+}
+
+
+
+void btConvexInternalShape::getAabbSlow(const btTransform& trans,btVector3&minAabb,btVector3&maxAabb) const
+{
+#ifndef __SPU__
+ //use localGetSupportingVertexWithoutMargin?
+ btScalar margin = getMargin();
+ for (int i=0;i<3;i++)
+ {
+ btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.));
+ vec[i] = btScalar(1.);
+
+ btVector3 sv = localGetSupportingVertex(vec*trans.getBasis());
+
+ btVector3 tmp = trans(sv);
+ maxAabb[i] = tmp[i]+margin;
+ vec[i] = btScalar(-1.);
+ tmp = trans(localGetSupportingVertex(vec*trans.getBasis()));
+ minAabb[i] = tmp[i]-margin;
+ }
+#endif
+}
+
+
+
+btVector3 btConvexInternalShape::localGetSupportingVertex(const btVector3& vec)const
+{
+#ifndef __SPU__
+
+ btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec);
+
+ if ( getMargin()!=btScalar(0.) )
+ {
+ btVector3 vecnorm = vec;
+ if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON))
+ {
+ vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.));
+ }
+ vecnorm.normalize();
+ supVertex+= getMargin() * vecnorm;
+ }
+ return supVertex;
+
+#else
+ btAssert(0);
+ return btVector3(0,0,0);
+#endif //__SPU__
+
+ }
+
+
+btConvexInternalAabbCachingShape::btConvexInternalAabbCachingShape()
+ : btConvexInternalShape(),
+m_localAabbMin(1,1,1),
+m_localAabbMax(-1,-1,-1),
+m_isLocalAabbValid(false)
+{
+}
+
+
+void btConvexInternalAabbCachingShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const
+{
+ getNonvirtualAabb(trans,aabbMin,aabbMax,getMargin());
+}
+
+void btConvexInternalAabbCachingShape::setLocalScaling(const btVector3& scaling)
+{
+ btConvexInternalShape::setLocalScaling(scaling);
+ recalcLocalAabb();
+}
+
+
+void btConvexInternalAabbCachingShape::recalcLocalAabb()
+{
+ m_isLocalAabbValid = true;
+
+ #if 1
+ static const btVector3 _directions[] =
+ {
+ btVector3( 1., 0., 0.),
+ btVector3( 0., 1., 0.),
+ btVector3( 0., 0., 1.),
+ btVector3( -1., 0., 0.),
+ btVector3( 0., -1., 0.),
+ btVector3( 0., 0., -1.)
+ };
+
+ btVector3 _supporting[] =
+ {
+ btVector3( 0., 0., 0.),
+ btVector3( 0., 0., 0.),
+ btVector3( 0., 0., 0.),
+ btVector3( 0., 0., 0.),
+ btVector3( 0., 0., 0.),
+ btVector3( 0., 0., 0.)
+ };
+
+ batchedUnitVectorGetSupportingVertexWithoutMargin(_directions, _supporting, 6);
+
+ for ( int i = 0; i < 3; ++i )
+ {
+ m_localAabbMax[i] = _supporting[i][i] + m_collisionMargin;
+ m_localAabbMin[i] = _supporting[i + 3][i] - m_collisionMargin;
+ }
+
+ #else
+
+ for (int i=0;i<3;i++)
+ {
+ btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.));
+ vec[i] = btScalar(1.);
+ btVector3 tmp = localGetSupportingVertex(vec);
+ m_localAabbMax[i] = tmp[i]+m_collisionMargin;
+ vec[i] = btScalar(-1.);
+ tmp = localGetSupportingVertex(vec);
+ m_localAabbMin[i] = tmp[i]-m_collisionMargin;
+ }
+ #endif
+}
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btConvexInternalShape.h b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btConvexInternalShape.h
new file mode 100644
index 0000000000..1213b82fbe
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btConvexInternalShape.h
@@ -0,0 +1,227 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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_CONVEX_INTERNAL_SHAPE_H
+#define BT_CONVEX_INTERNAL_SHAPE_H
+
+#include "btConvexShape.h"
+#include "LinearMath/btAabbUtil2.h"
+
+
+///The btConvexInternalShape is an internal base class, shared by most convex shape implementations.
+///The btConvexInternalShape uses a default collision margin set to CONVEX_DISTANCE_MARGIN.
+///This collision margin used by Gjk and some other algorithms, see also btCollisionMargin.h
+///Note that when creating small shapes (derived from btConvexInternalShape),
+///you need to make sure to set a smaller collision margin, using the 'setMargin' API
+///There is a automatic mechanism 'setSafeMargin' used by btBoxShape and btCylinderShape
+ATTRIBUTE_ALIGNED16(class) btConvexInternalShape : public btConvexShape
+{
+
+ protected:
+
+ //local scaling. collisionMargin is not scaled !
+ btVector3 m_localScaling;
+
+ btVector3 m_implicitShapeDimensions;
+
+ btScalar m_collisionMargin;
+
+ btScalar m_padding;
+
+ btConvexInternalShape();
+
+public:
+
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ virtual ~btConvexInternalShape()
+ {
+
+ }
+
+ virtual btVector3 localGetSupportingVertex(const btVector3& vec)const;
+
+ const btVector3& getImplicitShapeDimensions() const
+ {
+ return m_implicitShapeDimensions;
+ }
+
+ ///warning: use setImplicitShapeDimensions with care
+ ///changing a collision shape while the body is in the world is not recommended,
+ ///it is best to remove the body from the world, then make the change, and re-add it
+ ///alternatively flush the contact points, see documentation for 'cleanProxyFromPairs'
+ void setImplicitShapeDimensions(const btVector3& dimensions)
+ {
+ m_implicitShapeDimensions = dimensions;
+ }
+
+ void setSafeMargin(btScalar minDimension, btScalar defaultMarginMultiplier = 0.1f)
+ {
+ btScalar safeMargin = defaultMarginMultiplier*minDimension;
+ if (safeMargin < getMargin())
+ {
+ setMargin(safeMargin);
+ }
+ }
+ void setSafeMargin(const btVector3& halfExtents, btScalar defaultMarginMultiplier = 0.1f)
+ {
+ //see http://code.google.com/p/bullet/issues/detail?id=349
+ //this margin check could could be added to other collision shapes too,
+ //or add some assert/warning somewhere
+ btScalar minDimension=halfExtents[halfExtents.minAxis()];
+ setSafeMargin(minDimension, defaultMarginMultiplier);
+ }
+
+ ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
+ void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+ {
+ getAabbSlow(t,aabbMin,aabbMax);
+ }
+
+
+
+ virtual void getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+
+
+ virtual void setLocalScaling(const btVector3& scaling);
+ virtual const btVector3& getLocalScaling() const
+ {
+ return m_localScaling;
+ }
+
+ const btVector3& getLocalScalingNV() const
+ {
+ return m_localScaling;
+ }
+
+ virtual void setMargin(btScalar margin)
+ {
+ m_collisionMargin = margin;
+ }
+ virtual btScalar getMargin() const
+ {
+ return m_collisionMargin;
+ }
+
+ btScalar getMarginNV() const
+ {
+ return m_collisionMargin;
+ }
+
+ virtual int getNumPreferredPenetrationDirections() const
+ {
+ return 0;
+ }
+
+ virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const
+ {
+ (void)penetrationVector;
+ (void)index;
+ btAssert(0);
+ }
+
+ virtual int calculateSerializeBufferSize() const;
+
+ ///fills the dataBuffer and returns the struct name (and 0 on failure)
+ virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
+
+
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btConvexInternalShapeData
+{
+ btCollisionShapeData m_collisionShapeData;
+
+ btVector3FloatData m_localScaling;
+
+ btVector3FloatData m_implicitShapeDimensions;
+
+ float m_collisionMargin;
+
+ int m_padding;
+
+};
+
+
+
+SIMD_FORCE_INLINE int btConvexInternalShape::calculateSerializeBufferSize() const
+{
+ return sizeof(btConvexInternalShapeData);
+}
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+SIMD_FORCE_INLINE const char* btConvexInternalShape::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+ btConvexInternalShapeData* shapeData = (btConvexInternalShapeData*) dataBuffer;
+ btCollisionShape::serialize(&shapeData->m_collisionShapeData, serializer);
+
+ m_implicitShapeDimensions.serializeFloat(shapeData->m_implicitShapeDimensions);
+ m_localScaling.serializeFloat(shapeData->m_localScaling);
+ shapeData->m_collisionMargin = float(m_collisionMargin);
+
+ // Fill padding with zeros to appease msan.
+ shapeData->m_padding = 0;
+
+ return "btConvexInternalShapeData";
+}
+
+
+
+
+///btConvexInternalAabbCachingShape adds local aabb caching for convex shapes, to avoid expensive bounding box calculations
+class btConvexInternalAabbCachingShape : public btConvexInternalShape
+{
+ btVector3 m_localAabbMin;
+ btVector3 m_localAabbMax;
+ bool m_isLocalAabbValid;
+
+protected:
+
+ btConvexInternalAabbCachingShape();
+
+ void setCachedLocalAabb (const btVector3& aabbMin, const btVector3& aabbMax)
+ {
+ m_isLocalAabbValid = true;
+ m_localAabbMin = aabbMin;
+ m_localAabbMax = aabbMax;
+ }
+
+ inline void getCachedLocalAabb (btVector3& aabbMin, btVector3& aabbMax) const
+ {
+ btAssert(m_isLocalAabbValid);
+ aabbMin = m_localAabbMin;
+ aabbMax = m_localAabbMax;
+ }
+
+ inline void getNonvirtualAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax, btScalar margin) const
+ {
+
+ //lazy evaluation of local aabb
+ btAssert(m_isLocalAabbValid);
+ btTransformAabb(m_localAabbMin,m_localAabbMax,margin,trans,aabbMin,aabbMax);
+ }
+
+public:
+
+ virtual void setLocalScaling(const btVector3& scaling);
+
+ virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+
+ void recalcLocalAabb();
+
+};
+
+#endif //BT_CONVEX_INTERNAL_SHAPE_H
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp
new file mode 100644
index 0000000000..ad1d1bf78f
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp
@@ -0,0 +1,139 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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 "btConvexPointCloudShape.h"
+#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
+
+#include "LinearMath/btQuaternion.h"
+
+void btConvexPointCloudShape::setLocalScaling(const btVector3& scaling)
+{
+ m_localScaling = scaling;
+ recalcLocalAabb();
+}
+
+#ifndef __SPU__
+btVector3 btConvexPointCloudShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0)const
+{
+ btVector3 supVec(btScalar(0.),btScalar(0.),btScalar(0.));
+ btScalar maxDot = btScalar(-BT_LARGE_FLOAT);
+
+ btVector3 vec = vec0;
+ btScalar lenSqr = vec.length2();
+ if (lenSqr < btScalar(0.0001))
+ {
+ vec.setValue(1,0,0);
+ } else
+ {
+ btScalar rlen = btScalar(1.) / btSqrt(lenSqr );
+ vec *= rlen;
+ }
+
+ if( m_numPoints > 0 )
+ {
+ // Here we take advantage of dot(a*b, c) = dot( a, b*c) to do less work. Note this transformation is true mathematically, not numerically.
+ // btVector3 scaled = vec * m_localScaling;
+ int index = (int) vec.maxDot( &m_unscaledPoints[0], m_numPoints, maxDot); //FIXME: may violate encapsulation of m_unscaledPoints
+ return getScaledPoint(index);
+ }
+
+ return supVec;
+}
+
+void btConvexPointCloudShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+{
+ for( int j = 0; j < numVectors; j++ )
+ {
+ const btVector3& vec = vectors[j] * m_localScaling; // dot( a*c, b) = dot(a, b*c)
+ btScalar maxDot;
+ int index = (int) vec.maxDot( &m_unscaledPoints[0], m_numPoints, maxDot);
+ supportVerticesOut[j][3] = btScalar(-BT_LARGE_FLOAT);
+ if( 0 <= index )
+ {
+ //WARNING: don't swap next lines, the w component would get overwritten!
+ supportVerticesOut[j] = getScaledPoint(index);
+ supportVerticesOut[j][3] = maxDot;
+ }
+ }
+
+}
+
+
+
+btVector3 btConvexPointCloudShape::localGetSupportingVertex(const btVector3& vec)const
+{
+ btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec);
+
+ if ( getMargin()!=btScalar(0.) )
+ {
+ btVector3 vecnorm = vec;
+ if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON))
+ {
+ vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.));
+ }
+ vecnorm.normalize();
+ supVertex+= getMargin() * vecnorm;
+ }
+ return supVertex;
+}
+
+
+#endif
+
+
+
+
+
+
+//currently just for debugging (drawing), perhaps future support for algebraic continuous collision detection
+//Please note that you can debug-draw btConvexHullShape with the Raytracer Demo
+int btConvexPointCloudShape::getNumVertices() const
+{
+ return m_numPoints;
+}
+
+int btConvexPointCloudShape::getNumEdges() const
+{
+ return 0;
+}
+
+void btConvexPointCloudShape::getEdge(int i,btVector3& pa,btVector3& pb) const
+{
+ btAssert (0);
+}
+
+void btConvexPointCloudShape::getVertex(int i,btVector3& vtx) const
+{
+ vtx = m_unscaledPoints[i]*m_localScaling;
+}
+
+int btConvexPointCloudShape::getNumPlanes() const
+{
+ return 0;
+}
+
+void btConvexPointCloudShape::getPlane(btVector3& ,btVector3& ,int ) const
+{
+
+ btAssert(0);
+}
+
+//not yet
+bool btConvexPointCloudShape::isInside(const btVector3& ,btScalar ) const
+{
+ btAssert(0);
+ return false;
+}
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btConvexPointCloudShape.h b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btConvexPointCloudShape.h
new file mode 100644
index 0000000000..54b5afac3e
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btConvexPointCloudShape.h
@@ -0,0 +1,105 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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_CONVEX_POINT_CLOUD_SHAPE_H
+#define BT_CONVEX_POINT_CLOUD_SHAPE_H
+
+#include "btPolyhedralConvexShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
+#include "LinearMath/btAlignedObjectArray.h"
+
+///The btConvexPointCloudShape implements an implicit convex hull of an array of vertices.
+ATTRIBUTE_ALIGNED16(class) btConvexPointCloudShape : public btPolyhedralConvexAabbCachingShape
+{
+ btVector3* m_unscaledPoints;
+ int m_numPoints;
+
+public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ btConvexPointCloudShape()
+ {
+ m_localScaling.setValue(1.f,1.f,1.f);
+ m_shapeType = CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE;
+ m_unscaledPoints = 0;
+ m_numPoints = 0;
+ }
+
+ btConvexPointCloudShape(btVector3* points,int numPoints, const btVector3& localScaling,bool computeAabb = true)
+ {
+ m_localScaling = localScaling;
+ m_shapeType = CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE;
+ m_unscaledPoints = points;
+ m_numPoints = numPoints;
+
+ if (computeAabb)
+ recalcLocalAabb();
+ }
+
+ void setPoints (btVector3* points, int numPoints, bool computeAabb = true,const btVector3& localScaling=btVector3(1.f,1.f,1.f))
+ {
+ m_unscaledPoints = points;
+ m_numPoints = numPoints;
+ m_localScaling = localScaling;
+
+ if (computeAabb)
+ recalcLocalAabb();
+ }
+
+ SIMD_FORCE_INLINE btVector3* getUnscaledPoints()
+ {
+ return m_unscaledPoints;
+ }
+
+ SIMD_FORCE_INLINE const btVector3* getUnscaledPoints() const
+ {
+ return m_unscaledPoints;
+ }
+
+ SIMD_FORCE_INLINE int getNumPoints() const
+ {
+ return m_numPoints;
+ }
+
+ SIMD_FORCE_INLINE btVector3 getScaledPoint( int index) const
+ {
+ return m_unscaledPoints[index] * m_localScaling;
+ }
+
+#ifndef __SPU__
+ virtual btVector3 localGetSupportingVertex(const btVector3& vec)const;
+ virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
+ virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
+#endif
+
+
+ //debugging
+ virtual const char* getName()const {return "ConvexPointCloud";}
+
+ virtual int getNumVertices() const;
+ virtual int getNumEdges() const;
+ virtual void getEdge(int i,btVector3& pa,btVector3& pb) const;
+ virtual void getVertex(int i,btVector3& vtx) const;
+ virtual int getNumPlanes() const;
+ virtual void getPlane(btVector3& planeNormal,btVector3& planeSupport,int i ) const;
+ virtual bool isInside(const btVector3& pt,btScalar tolerance) const;
+
+ ///in case we receive negative scaling
+ virtual void setLocalScaling(const btVector3& scaling);
+};
+
+
+#endif //BT_CONVEX_POINT_CLOUD_SHAPE_H
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp
new file mode 100644
index 0000000000..4f45319a83
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp
@@ -0,0 +1,303 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2011 Advanced Micro Devices, 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.
+*/
+
+
+///This file was written by Erwin Coumans
+///Separating axis rest based on work from Pierre Terdiman, see
+///And contact clipping based on work from Simon Hobbs
+
+#include "btConvexPolyhedron.h"
+#include "LinearMath/btHashMap.h"
+
+
+btConvexPolyhedron::btConvexPolyhedron()
+{
+
+}
+btConvexPolyhedron::~btConvexPolyhedron()
+{
+
+}
+
+
+inline bool IsAlmostZero(const btVector3& v)
+{
+ if(btFabs(v.x())>1e-6 || btFabs(v.y())>1e-6 || btFabs(v.z())>1e-6) return false;
+ return true;
+}
+
+struct btInternalVertexPair
+{
+ btInternalVertexPair(short int v0,short int v1)
+ :m_v0(v0),
+ m_v1(v1)
+ {
+ if (m_v1>m_v0)
+ btSwap(m_v0,m_v1);
+ }
+ short int m_v0;
+ short int m_v1;
+ int getHash() const
+ {
+ return m_v0+(m_v1<<16);
+ }
+ bool equals(const btInternalVertexPair& other) const
+ {
+ return m_v0==other.m_v0 && m_v1==other.m_v1;
+ }
+};
+
+struct btInternalEdge
+{
+ btInternalEdge()
+ :m_face0(-1),
+ m_face1(-1)
+ {
+ }
+ short int m_face0;
+ short int m_face1;
+};
+
+//
+
+#ifdef TEST_INTERNAL_OBJECTS
+bool btConvexPolyhedron::testContainment() const
+{
+ for(int p=0;p<8;p++)
+ {
+ btVector3 LocalPt;
+ if(p==0) LocalPt = m_localCenter + btVector3(m_extents[0], m_extents[1], m_extents[2]);
+ else if(p==1) LocalPt = m_localCenter + btVector3(m_extents[0], m_extents[1], -m_extents[2]);
+ else if(p==2) LocalPt = m_localCenter + btVector3(m_extents[0], -m_extents[1], m_extents[2]);
+ else if(p==3) LocalPt = m_localCenter + btVector3(m_extents[0], -m_extents[1], -m_extents[2]);
+ else if(p==4) LocalPt = m_localCenter + btVector3(-m_extents[0], m_extents[1], m_extents[2]);
+ else if(p==5) LocalPt = m_localCenter + btVector3(-m_extents[0], m_extents[1], -m_extents[2]);
+ else if(p==6) LocalPt = m_localCenter + btVector3(-m_extents[0], -m_extents[1], m_extents[2]);
+ else if(p==7) LocalPt = m_localCenter + btVector3(-m_extents[0], -m_extents[1], -m_extents[2]);
+
+ for(int i=0;i<m_faces.size();i++)
+ {
+ const btVector3 Normal(m_faces[i].m_plane[0], m_faces[i].m_plane[1], m_faces[i].m_plane[2]);
+ const btScalar d = LocalPt.dot(Normal) + m_faces[i].m_plane[3];
+ if(d>0.0f)
+ return false;
+ }
+ }
+ return true;
+}
+#endif
+
+void btConvexPolyhedron::initialize()
+{
+
+ btHashMap<btInternalVertexPair,btInternalEdge> edges;
+
+ btScalar TotalArea = 0.0f;
+
+ m_localCenter.setValue(0, 0, 0);
+ for(int i=0;i<m_faces.size();i++)
+ {
+ int numVertices = m_faces[i].m_indices.size();
+ int NbTris = numVertices;
+ for(int j=0;j<NbTris;j++)
+ {
+ int k = (j+1)%numVertices;
+ btInternalVertexPair vp(m_faces[i].m_indices[j],m_faces[i].m_indices[k]);
+ btInternalEdge* edptr = edges.find(vp);
+ btVector3 edge = m_vertices[vp.m_v1]-m_vertices[vp.m_v0];
+ edge.normalize();
+
+ bool found = false;
+
+ for (int p=0;p<m_uniqueEdges.size();p++)
+ {
+
+ if (IsAlmostZero(m_uniqueEdges[p]-edge) ||
+ IsAlmostZero(m_uniqueEdges[p]+edge))
+ {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found)
+ {
+ m_uniqueEdges.push_back(edge);
+ }
+
+ if (edptr)
+ {
+ btAssert(edptr->m_face0>=0);
+ btAssert(edptr->m_face1<0);
+ edptr->m_face1 = i;
+ } else
+ {
+ btInternalEdge ed;
+ ed.m_face0 = i;
+ edges.insert(vp,ed);
+ }
+ }
+ }
+
+#ifdef USE_CONNECTED_FACES
+ for(int i=0;i<m_faces.size();i++)
+ {
+ int numVertices = m_faces[i].m_indices.size();
+ m_faces[i].m_connectedFaces.resize(numVertices);
+
+ for(int j=0;j<numVertices;j++)
+ {
+ int k = (j+1)%numVertices;
+ btInternalVertexPair vp(m_faces[i].m_indices[j],m_faces[i].m_indices[k]);
+ btInternalEdge* edptr = edges.find(vp);
+ btAssert(edptr);
+ btAssert(edptr->m_face0>=0);
+ btAssert(edptr->m_face1>=0);
+
+ int connectedFace = (edptr->m_face0==i)?edptr->m_face1:edptr->m_face0;
+ m_faces[i].m_connectedFaces[j] = connectedFace;
+ }
+ }
+#endif//USE_CONNECTED_FACES
+
+ for(int i=0;i<m_faces.size();i++)
+ {
+ int numVertices = m_faces[i].m_indices.size();
+ int NbTris = numVertices-2;
+
+ const btVector3& p0 = m_vertices[m_faces[i].m_indices[0]];
+ for(int j=1;j<=NbTris;j++)
+ {
+ int k = (j+1)%numVertices;
+ const btVector3& p1 = m_vertices[m_faces[i].m_indices[j]];
+ const btVector3& p2 = m_vertices[m_faces[i].m_indices[k]];
+ btScalar Area = ((p0 - p1).cross(p0 - p2)).length() * 0.5f;
+ btVector3 Center = (p0+p1+p2)/3.0f;
+ m_localCenter += Area * Center;
+ TotalArea += Area;
+ }
+ }
+ m_localCenter /= TotalArea;
+
+
+
+
+#ifdef TEST_INTERNAL_OBJECTS
+ if(1)
+ {
+ m_radius = FLT_MAX;
+ for(int i=0;i<m_faces.size();i++)
+ {
+ const btVector3 Normal(m_faces[i].m_plane[0], m_faces[i].m_plane[1], m_faces[i].m_plane[2]);
+ const btScalar dist = btFabs(m_localCenter.dot(Normal) + m_faces[i].m_plane[3]);
+ if(dist<m_radius)
+ m_radius = dist;
+ }
+
+
+ btScalar MinX = FLT_MAX;
+ btScalar MinY = FLT_MAX;
+ btScalar MinZ = FLT_MAX;
+ btScalar MaxX = -FLT_MAX;
+ btScalar MaxY = -FLT_MAX;
+ btScalar MaxZ = -FLT_MAX;
+ for(int i=0; i<m_vertices.size(); i++)
+ {
+ const btVector3& pt = m_vertices[i];
+ if(pt.x()<MinX) MinX = pt.x();
+ if(pt.x()>MaxX) MaxX = pt.x();
+ if(pt.y()<MinY) MinY = pt.y();
+ if(pt.y()>MaxY) MaxY = pt.y();
+ if(pt.z()<MinZ) MinZ = pt.z();
+ if(pt.z()>MaxZ) MaxZ = pt.z();
+ }
+ mC.setValue(MaxX+MinX, MaxY+MinY, MaxZ+MinZ);
+ mE.setValue(MaxX-MinX, MaxY-MinY, MaxZ-MinZ);
+
+
+
+// const btScalar r = m_radius / sqrtf(2.0f);
+ const btScalar r = m_radius / sqrtf(3.0f);
+ const int LargestExtent = mE.maxAxis();
+ const btScalar Step = (mE[LargestExtent]*0.5f - r)/1024.0f;
+ m_extents[0] = m_extents[1] = m_extents[2] = r;
+ m_extents[LargestExtent] = mE[LargestExtent]*0.5f;
+ bool FoundBox = false;
+ for(int j=0;j<1024;j++)
+ {
+ if(testContainment())
+ {
+ FoundBox = true;
+ break;
+ }
+
+ m_extents[LargestExtent] -= Step;
+ }
+ if(!FoundBox)
+ {
+ m_extents[0] = m_extents[1] = m_extents[2] = r;
+ }
+ else
+ {
+ // Refine the box
+ const btScalar Step = (m_radius - r)/1024.0f;
+ const int e0 = (1<<LargestExtent) & 3;
+ const int e1 = (1<<e0) & 3;
+
+ for(int j=0;j<1024;j++)
+ {
+ const btScalar Saved0 = m_extents[e0];
+ const btScalar Saved1 = m_extents[e1];
+ m_extents[e0] += Step;
+ m_extents[e1] += Step;
+
+ if(!testContainment())
+ {
+ m_extents[e0] = Saved0;
+ m_extents[e1] = Saved1;
+ break;
+ }
+ }
+ }
+ }
+#endif
+}
+
+void btConvexPolyhedron::project(const btTransform& trans, const btVector3& dir, btScalar& minProj, btScalar& maxProj, btVector3& witnesPtMin,btVector3& witnesPtMax) const
+{
+ minProj = FLT_MAX;
+ maxProj = -FLT_MAX;
+ int numVerts = m_vertices.size();
+ for(int i=0;i<numVerts;i++)
+ {
+ btVector3 pt = trans * m_vertices[i];
+ btScalar dp = pt.dot(dir);
+ if(dp < minProj)
+ {
+ minProj = dp;
+ witnesPtMin = pt;
+ }
+ if(dp > maxProj)
+ {
+ maxProj = dp;
+ witnesPtMax = pt;
+ }
+ }
+ if(minProj>maxProj)
+ {
+ btSwap(minProj,maxProj);
+ btSwap(witnesPtMin,witnesPtMax);
+ }
+}
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btConvexPolyhedron.h b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btConvexPolyhedron.h
new file mode 100644
index 0000000000..d3cd066ac8
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btConvexPolyhedron.h
@@ -0,0 +1,65 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2011 Advanced Micro Devices, 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.
+*/
+
+
+///This file was written by Erwin Coumans
+
+
+#ifndef _BT_POLYHEDRAL_FEATURES_H
+#define _BT_POLYHEDRAL_FEATURES_H
+
+#include "LinearMath/btTransform.h"
+#include "LinearMath/btAlignedObjectArray.h"
+
+#define TEST_INTERNAL_OBJECTS 1
+
+
+struct btFace
+{
+ btAlignedObjectArray<int> m_indices;
+// btAlignedObjectArray<int> m_connectedFaces;
+ btScalar m_plane[4];
+};
+
+
+ATTRIBUTE_ALIGNED16(class) btConvexPolyhedron
+{
+ public:
+
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ btConvexPolyhedron();
+ virtual ~btConvexPolyhedron();
+
+ btAlignedObjectArray<btVector3> m_vertices;
+ btAlignedObjectArray<btFace> m_faces;
+ btAlignedObjectArray<btVector3> m_uniqueEdges;
+
+ btVector3 m_localCenter;
+ btVector3 m_extents;
+ btScalar m_radius;
+ btVector3 mC;
+ btVector3 mE;
+
+ void initialize();
+ bool testContainment() const;
+
+ void project(const btTransform& trans, const btVector3& dir, btScalar& minProj, btScalar& maxProj, btVector3& witnesPtMin,btVector3& witnesPtMax) const;
+};
+
+
+#endif //_BT_POLYHEDRAL_FEATURES_H
+
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btConvexShape.cpp b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btConvexShape.cpp
new file mode 100644
index 0000000000..8d7fb054d6
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btConvexShape.cpp
@@ -0,0 +1,455 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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.
+*/
+
+#if defined (_WIN32) || defined (__i386__)
+#define BT_USE_SSE_IN_API
+#endif
+
+#include "btConvexShape.h"
+#include "btTriangleShape.h"
+#include "btSphereShape.h"
+#include "btCylinderShape.h"
+#include "btConeShape.h"
+#include "btCapsuleShape.h"
+#include "btConvexHullShape.h"
+#include "btConvexPointCloudShape.h"
+
+///not supported on IBM SDK, until we fix the alignment of btVector3
+#if defined (__CELLOS_LV2__) && defined (__SPU__)
+#include <spu_intrinsics.h>
+static inline vec_float4 vec_dot3( vec_float4 vec0, vec_float4 vec1 )
+{
+ vec_float4 result;
+ result = spu_mul( vec0, vec1 );
+ result = spu_madd( spu_rlqwbyte( vec0, 4 ), spu_rlqwbyte( vec1, 4 ), result );
+ return spu_madd( spu_rlqwbyte( vec0, 8 ), spu_rlqwbyte( vec1, 8 ), result );
+}
+#endif //__SPU__
+
+btConvexShape::btConvexShape ()
+{
+}
+
+btConvexShape::~btConvexShape()
+{
+
+}
+
+
+void btConvexShape::project(const btTransform& trans, const btVector3& dir, btScalar& min, btScalar& max, btVector3& witnesPtMin,btVector3& witnesPtMax) const
+{
+ btVector3 localAxis = dir*trans.getBasis();
+ btVector3 vtx1 = trans(localGetSupportingVertex(localAxis));
+ btVector3 vtx2 = trans(localGetSupportingVertex(-localAxis));
+
+ min = vtx1.dot(dir);
+ max = vtx2.dot(dir);
+ witnesPtMax = vtx2;
+ witnesPtMin = vtx1;
+
+ if(min>max)
+ {
+ btScalar tmp = min;
+ min = max;
+ max = tmp;
+ witnesPtMax = vtx1;
+ witnesPtMin = vtx2;
+ }
+}
+
+
+static btVector3 convexHullSupport (const btVector3& localDirOrg, const btVector3* points, int numPoints, const btVector3& localScaling)
+{
+
+ btVector3 vec = localDirOrg * localScaling;
+
+#if defined (__CELLOS_LV2__) && defined (__SPU__)
+
+ btVector3 localDir = vec;
+
+ vec_float4 v_distMax = {-FLT_MAX,0,0,0};
+ vec_int4 v_idxMax = {-999,0,0,0};
+ int v=0;
+ int numverts = numPoints;
+
+ for(;v<(int)numverts-4;v+=4) {
+ vec_float4 p0 = vec_dot3(points[v ].get128(),localDir.get128());
+ vec_float4 p1 = vec_dot3(points[v+1].get128(),localDir.get128());
+ vec_float4 p2 = vec_dot3(points[v+2].get128(),localDir.get128());
+ vec_float4 p3 = vec_dot3(points[v+3].get128(),localDir.get128());
+ const vec_int4 i0 = {v ,0,0,0};
+ const vec_int4 i1 = {v+1,0,0,0};
+ const vec_int4 i2 = {v+2,0,0,0};
+ const vec_int4 i3 = {v+3,0,0,0};
+ vec_uint4 retGt01 = spu_cmpgt(p0,p1);
+ vec_float4 pmax01 = spu_sel(p1,p0,retGt01);
+ vec_int4 imax01 = spu_sel(i1,i0,retGt01);
+ vec_uint4 retGt23 = spu_cmpgt(p2,p3);
+ vec_float4 pmax23 = spu_sel(p3,p2,retGt23);
+ vec_int4 imax23 = spu_sel(i3,i2,retGt23);
+ vec_uint4 retGt0123 = spu_cmpgt(pmax01,pmax23);
+ vec_float4 pmax0123 = spu_sel(pmax23,pmax01,retGt0123);
+ vec_int4 imax0123 = spu_sel(imax23,imax01,retGt0123);
+ vec_uint4 retGtMax = spu_cmpgt(v_distMax,pmax0123);
+ v_distMax = spu_sel(pmax0123,v_distMax,retGtMax);
+ v_idxMax = spu_sel(imax0123,v_idxMax,retGtMax);
+ }
+ for(;v<(int)numverts;v++) {
+ vec_float4 p = vec_dot3(points[v].get128(),localDir.get128());
+ const vec_int4 i = {v,0,0,0};
+ vec_uint4 retGtMax = spu_cmpgt(v_distMax,p);
+ v_distMax = spu_sel(p,v_distMax,retGtMax);
+ v_idxMax = spu_sel(i,v_idxMax,retGtMax);
+ }
+ int ptIndex = spu_extract(v_idxMax,0);
+ const btVector3& supVec= points[ptIndex] * localScaling;
+ return supVec;
+#else
+
+ btScalar maxDot;
+ long ptIndex = vec.maxDot( points, numPoints, maxDot);
+ btAssert(ptIndex >= 0);
+ btVector3 supVec = points[ptIndex] * localScaling;
+ return supVec;
+#endif //__SPU__
+}
+
+btVector3 btConvexShape::localGetSupportVertexWithoutMarginNonVirtual (const btVector3& localDir) const
+{
+ switch (m_shapeType)
+ {
+ case SPHERE_SHAPE_PROXYTYPE:
+ {
+ return btVector3(0,0,0);
+ }
+ case BOX_SHAPE_PROXYTYPE:
+ {
+ btBoxShape* convexShape = (btBoxShape*)this;
+ const btVector3& halfExtents = convexShape->getImplicitShapeDimensions();
+
+#if defined( __APPLE__ ) && (defined( BT_USE_SSE )||defined( BT_USE_NEON ))
+ #if defined( BT_USE_SSE )
+ return btVector3( _mm_xor_ps( _mm_and_ps( localDir.mVec128, (__m128){-0.0f, -0.0f, -0.0f, -0.0f }), halfExtents.mVec128 ));
+ #elif defined( BT_USE_NEON )
+ return btVector3( (float32x4_t) (((uint32x4_t) localDir.mVec128 & (uint32x4_t){ 0x80000000, 0x80000000, 0x80000000, 0x80000000}) ^ (uint32x4_t) halfExtents.mVec128 ));
+ #else
+ #error unknown vector arch
+ #endif
+#else
+ return btVector3(btFsels(localDir.x(), halfExtents.x(), -halfExtents.x()),
+ btFsels(localDir.y(), halfExtents.y(), -halfExtents.y()),
+ btFsels(localDir.z(), halfExtents.z(), -halfExtents.z()));
+#endif
+ }
+ case TRIANGLE_SHAPE_PROXYTYPE:
+ {
+ btTriangleShape* triangleShape = (btTriangleShape*)this;
+ btVector3 dir(localDir.getX(),localDir.getY(),localDir.getZ());
+ btVector3* vertices = &triangleShape->m_vertices1[0];
+ btVector3 dots = dir.dot3(vertices[0], vertices[1], vertices[2]);
+ btVector3 sup = vertices[dots.maxAxis()];
+ return btVector3(sup.getX(),sup.getY(),sup.getZ());
+ }
+ case CYLINDER_SHAPE_PROXYTYPE:
+ {
+ btCylinderShape* cylShape = (btCylinderShape*)this;
+ //mapping of halfextents/dimension onto radius/height depends on how cylinder local orientation is (upAxis)
+
+ btVector3 halfExtents = cylShape->getImplicitShapeDimensions();
+ btVector3 v(localDir.getX(),localDir.getY(),localDir.getZ());
+ int cylinderUpAxis = cylShape->getUpAxis();
+ int XX(1),YY(0),ZZ(2);
+
+ switch (cylinderUpAxis)
+ {
+ case 0:
+ {
+ XX = 1;
+ YY = 0;
+ ZZ = 2;
+ }
+ break;
+ case 1:
+ {
+ XX = 0;
+ YY = 1;
+ ZZ = 2;
+ }
+ break;
+ case 2:
+ {
+ XX = 0;
+ YY = 2;
+ ZZ = 1;
+
+ }
+ break;
+ default:
+ btAssert(0);
+ break;
+ };
+
+ btScalar radius = halfExtents[XX];
+ btScalar halfHeight = halfExtents[cylinderUpAxis];
+
+ btVector3 tmp;
+ btScalar d ;
+
+ btScalar s = btSqrt(v[XX] * v[XX] + v[ZZ] * v[ZZ]);
+ if (s != btScalar(0.0))
+ {
+ d = radius / s;
+ tmp[XX] = v[XX] * d;
+ tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
+ tmp[ZZ] = v[ZZ] * d;
+ return btVector3(tmp.getX(),tmp.getY(),tmp.getZ());
+ } else {
+ tmp[XX] = radius;
+ tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
+ tmp[ZZ] = btScalar(0.0);
+ return btVector3(tmp.getX(),tmp.getY(),tmp.getZ());
+ }
+ }
+ case CAPSULE_SHAPE_PROXYTYPE:
+ {
+ btVector3 vec0(localDir.getX(),localDir.getY(),localDir.getZ());
+
+ btCapsuleShape* capsuleShape = (btCapsuleShape*)this;
+ btScalar halfHeight = capsuleShape->getHalfHeight();
+ int capsuleUpAxis = capsuleShape->getUpAxis();
+
+ btVector3 supVec(0,0,0);
+
+ btScalar maxDot(btScalar(-BT_LARGE_FLOAT));
+
+ btVector3 vec = vec0;
+ btScalar lenSqr = vec.length2();
+ if (lenSqr < SIMD_EPSILON*SIMD_EPSILON)
+ {
+ vec.setValue(1,0,0);
+ } else
+ {
+ btScalar rlen = btScalar(1.) / btSqrt(lenSqr );
+ vec *= rlen;
+ }
+ btVector3 vtx;
+ btScalar newDot;
+ {
+ btVector3 pos(0,0,0);
+ pos[capsuleUpAxis] = halfHeight;
+
+ vtx = pos;
+ newDot = vec.dot(vtx);
+
+
+ if (newDot > maxDot)
+ {
+ maxDot = newDot;
+ supVec = vtx;
+ }
+ }
+ {
+ btVector3 pos(0,0,0);
+ pos[capsuleUpAxis] = -halfHeight;
+
+ vtx = pos;
+ newDot = vec.dot(vtx);
+ if (newDot > maxDot)
+ {
+ maxDot = newDot;
+ supVec = vtx;
+ }
+ }
+ return btVector3(supVec.getX(),supVec.getY(),supVec.getZ());
+ }
+ case CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE:
+ {
+ btConvexPointCloudShape* convexPointCloudShape = (btConvexPointCloudShape*)this;
+ btVector3* points = convexPointCloudShape->getUnscaledPoints ();
+ int numPoints = convexPointCloudShape->getNumPoints ();
+ return convexHullSupport (localDir, points, numPoints,convexPointCloudShape->getLocalScalingNV());
+ }
+ case CONVEX_HULL_SHAPE_PROXYTYPE:
+ {
+ btConvexHullShape* convexHullShape = (btConvexHullShape*)this;
+ btVector3* points = convexHullShape->getUnscaledPoints();
+ int numPoints = convexHullShape->getNumPoints ();
+ return convexHullSupport (localDir, points, numPoints,convexHullShape->getLocalScalingNV());
+ }
+ default:
+#ifndef __SPU__
+ return this->localGetSupportingVertexWithoutMargin (localDir);
+#else
+ btAssert (0);
+#endif
+ }
+
+ // should never reach here
+ btAssert (0);
+ return btVector3 (btScalar(0.0f), btScalar(0.0f), btScalar(0.0f));
+}
+
+btVector3 btConvexShape::localGetSupportVertexNonVirtual (const btVector3& localDir) const
+{
+ btVector3 localDirNorm = localDir;
+ if (localDirNorm .length2() < (SIMD_EPSILON*SIMD_EPSILON))
+ {
+ localDirNorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.));
+ }
+ localDirNorm.normalize ();
+
+ return localGetSupportVertexWithoutMarginNonVirtual(localDirNorm)+ getMarginNonVirtual() * localDirNorm;
+}
+
+/* TODO: This should be bumped up to btCollisionShape () */
+btScalar btConvexShape::getMarginNonVirtual () const
+{
+ switch (m_shapeType)
+ {
+ case SPHERE_SHAPE_PROXYTYPE:
+ {
+ btSphereShape* sphereShape = (btSphereShape*)this;
+ return sphereShape->getRadius ();
+ }
+ case BOX_SHAPE_PROXYTYPE:
+ {
+ btBoxShape* convexShape = (btBoxShape*)this;
+ return convexShape->getMarginNV ();
+ }
+ case TRIANGLE_SHAPE_PROXYTYPE:
+ {
+ btTriangleShape* triangleShape = (btTriangleShape*)this;
+ return triangleShape->getMarginNV ();
+ }
+ case CYLINDER_SHAPE_PROXYTYPE:
+ {
+ btCylinderShape* cylShape = (btCylinderShape*)this;
+ return cylShape->getMarginNV();
+ }
+ case CONE_SHAPE_PROXYTYPE:
+ {
+ btConeShape* conShape = (btConeShape*)this;
+ return conShape->getMarginNV();
+ }
+ case CAPSULE_SHAPE_PROXYTYPE:
+ {
+ btCapsuleShape* capsuleShape = (btCapsuleShape*)this;
+ return capsuleShape->getMarginNV();
+ }
+ case CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE:
+ /* fall through */
+ case CONVEX_HULL_SHAPE_PROXYTYPE:
+ {
+ btPolyhedralConvexShape* convexHullShape = (btPolyhedralConvexShape*)this;
+ return convexHullShape->getMarginNV();
+ }
+ default:
+#ifndef __SPU__
+ return this->getMargin ();
+#else
+ btAssert (0);
+#endif
+ }
+
+ // should never reach here
+ btAssert (0);
+ return btScalar(0.0f);
+}
+#ifndef __SPU__
+void btConvexShape::getAabbNonVirtual (const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
+{
+ switch (m_shapeType)
+ {
+ case SPHERE_SHAPE_PROXYTYPE:
+ {
+ btSphereShape* sphereShape = (btSphereShape*)this;
+ btScalar radius = sphereShape->getImplicitShapeDimensions().getX();// * convexShape->getLocalScaling().getX();
+ btScalar margin = radius + sphereShape->getMarginNonVirtual();
+ const btVector3& center = t.getOrigin();
+ btVector3 extent(margin,margin,margin);
+ aabbMin = center - extent;
+ aabbMax = center + extent;
+ }
+ break;
+ case CYLINDER_SHAPE_PROXYTYPE:
+ /* fall through */
+ case BOX_SHAPE_PROXYTYPE:
+ {
+ btBoxShape* convexShape = (btBoxShape*)this;
+ btScalar margin=convexShape->getMarginNonVirtual();
+ btVector3 halfExtents = convexShape->getImplicitShapeDimensions();
+ halfExtents += btVector3(margin,margin,margin);
+ btMatrix3x3 abs_b = t.getBasis().absolute();
+ btVector3 center = t.getOrigin();
+ btVector3 extent = halfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
+
+ aabbMin = center - extent;
+ aabbMax = center + extent;
+ break;
+ }
+ case TRIANGLE_SHAPE_PROXYTYPE:
+ {
+ btTriangleShape* triangleShape = (btTriangleShape*)this;
+ btScalar margin = triangleShape->getMarginNonVirtual();
+ for (int i=0;i<3;i++)
+ {
+ btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.));
+ vec[i] = btScalar(1.);
+
+ btVector3 sv = localGetSupportVertexWithoutMarginNonVirtual(vec*t.getBasis());
+
+ btVector3 tmp = t(sv);
+ aabbMax[i] = tmp[i]+margin;
+ vec[i] = btScalar(-1.);
+ tmp = t(localGetSupportVertexWithoutMarginNonVirtual(vec*t.getBasis()));
+ aabbMin[i] = tmp[i]-margin;
+ }
+ }
+ break;
+ case CAPSULE_SHAPE_PROXYTYPE:
+ {
+ btCapsuleShape* capsuleShape = (btCapsuleShape*)this;
+ btVector3 halfExtents(capsuleShape->getRadius(),capsuleShape->getRadius(),capsuleShape->getRadius());
+ int m_upAxis = capsuleShape->getUpAxis();
+ halfExtents[m_upAxis] = capsuleShape->getRadius() + capsuleShape->getHalfHeight();
+ btMatrix3x3 abs_b = t.getBasis().absolute();
+ btVector3 center = t.getOrigin();
+ btVector3 extent = halfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
+ aabbMin = center - extent;
+ aabbMax = center + extent;
+ }
+ break;
+ case CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE:
+ case CONVEX_HULL_SHAPE_PROXYTYPE:
+ {
+ btPolyhedralConvexAabbCachingShape* convexHullShape = (btPolyhedralConvexAabbCachingShape*)this;
+ btScalar margin = convexHullShape->getMarginNonVirtual();
+ convexHullShape->getNonvirtualAabb (t, aabbMin, aabbMax, margin);
+ }
+ break;
+ default:
+#ifndef __SPU__
+ this->getAabb (t, aabbMin, aabbMax);
+#else
+ btAssert (0);
+#endif
+ break;
+ }
+
+ // should never reach here
+ btAssert (0);
+}
+
+#endif //__SPU__
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btConvexShape.h b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btConvexShape.h
new file mode 100644
index 0000000000..875f2ac195
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btConvexShape.h
@@ -0,0 +1,85 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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_CONVEX_SHAPE_INTERFACE1
+#define BT_CONVEX_SHAPE_INTERFACE1
+
+#include "btCollisionShape.h"
+
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btTransform.h"
+#include "LinearMath/btMatrix3x3.h"
+#include "btCollisionMargin.h"
+#include "LinearMath/btAlignedAllocator.h"
+
+#define MAX_PREFERRED_PENETRATION_DIRECTIONS 10
+
+/// The btConvexShape is an abstract shape interface, implemented by all convex shapes such as btBoxShape, btConvexHullShape etc.
+/// It describes general convex shapes using the localGetSupportingVertex interface, used by collision detectors such as btGjkPairDetector.
+ATTRIBUTE_ALIGNED16(class) btConvexShape : public btCollisionShape
+{
+
+
+public:
+
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ btConvexShape ();
+
+ virtual ~btConvexShape();
+
+ virtual btVector3 localGetSupportingVertex(const btVector3& vec)const = 0;
+
+ ////////
+ #ifndef __SPU__
+ virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const=0;
+ #endif //#ifndef __SPU__
+
+ btVector3 localGetSupportVertexWithoutMarginNonVirtual (const btVector3& vec) const;
+ btVector3 localGetSupportVertexNonVirtual (const btVector3& vec) const;
+ btScalar getMarginNonVirtual () const;
+ void getAabbNonVirtual (const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
+
+
+ virtual void project(const btTransform& trans, const btVector3& dir, btScalar& minProj, btScalar& maxProj, btVector3& witnesPtMin,btVector3& witnesPtMax) const;
+
+
+ //notice that the vectors should be unit length
+ virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const= 0;
+
+ ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
+ void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const =0;
+
+ virtual void getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const =0;
+
+ virtual void setLocalScaling(const btVector3& scaling) =0;
+ virtual const btVector3& getLocalScaling() const =0;
+
+ virtual void setMargin(btScalar margin)=0;
+
+ virtual btScalar getMargin() const=0;
+
+ virtual int getNumPreferredPenetrationDirections() const=0;
+
+ virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const=0;
+
+
+
+
+};
+
+
+
+#endif //BT_CONVEX_SHAPE_INTERFACE1
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp
new file mode 100644
index 0000000000..0f9ced554b
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp
@@ -0,0 +1,315 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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 "btConvexTriangleMeshShape.h"
+#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
+
+#include "LinearMath/btQuaternion.h"
+#include "BulletCollision/CollisionShapes/btStridingMeshInterface.h"
+
+
+btConvexTriangleMeshShape ::btConvexTriangleMeshShape (btStridingMeshInterface* meshInterface, bool calcAabb)
+: btPolyhedralConvexAabbCachingShape(), m_stridingMesh(meshInterface)
+{
+ m_shapeType = CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE;
+ if ( calcAabb )
+ recalcLocalAabb();
+}
+
+
+
+
+///It's not nice to have all this virtual function overhead, so perhaps we can also gather the points once
+///but then we are duplicating
+class LocalSupportVertexCallback: public btInternalTriangleIndexCallback
+{
+
+ btVector3 m_supportVertexLocal;
+public:
+
+ btScalar m_maxDot;
+ btVector3 m_supportVecLocal;
+
+ LocalSupportVertexCallback(const btVector3& supportVecLocal)
+ : m_supportVertexLocal(btScalar(0.),btScalar(0.),btScalar(0.)),
+ m_maxDot(btScalar(-BT_LARGE_FLOAT)),
+ m_supportVecLocal(supportVecLocal)
+ {
+ }
+
+ virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex)
+ {
+ (void)triangleIndex;
+ (void)partId;
+
+ for (int i=0;i<3;i++)
+ {
+ btScalar dot = m_supportVecLocal.dot(triangle[i]);
+ if (dot > m_maxDot)
+ {
+ m_maxDot = dot;
+ m_supportVertexLocal = triangle[i];
+ }
+ }
+ }
+
+ btVector3 GetSupportVertexLocal()
+ {
+ return m_supportVertexLocal;
+ }
+
+};
+
+
+
+
+
+btVector3 btConvexTriangleMeshShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0)const
+{
+ btVector3 supVec(btScalar(0.),btScalar(0.),btScalar(0.));
+
+ btVector3 vec = vec0;
+ btScalar lenSqr = vec.length2();
+ if (lenSqr < btScalar(0.0001))
+ {
+ vec.setValue(1,0,0);
+ } else
+ {
+ btScalar rlen = btScalar(1.) / btSqrt(lenSqr );
+ vec *= rlen;
+ }
+
+ LocalSupportVertexCallback supportCallback(vec);
+ btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
+ m_stridingMesh->InternalProcessAllTriangles(&supportCallback,-aabbMax,aabbMax);
+ supVec = supportCallback.GetSupportVertexLocal();
+
+ return supVec;
+}
+
+void btConvexTriangleMeshShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+{
+ //use 'w' component of supportVerticesOut?
+ {
+ for (int i=0;i<numVectors;i++)
+ {
+ supportVerticesOut[i][3] = btScalar(-BT_LARGE_FLOAT);
+ }
+ }
+
+ ///@todo: could do the batch inside the callback!
+
+
+ for (int j=0;j<numVectors;j++)
+ {
+ const btVector3& vec = vectors[j];
+ LocalSupportVertexCallback supportCallback(vec);
+ btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
+ m_stridingMesh->InternalProcessAllTriangles(&supportCallback,-aabbMax,aabbMax);
+ supportVerticesOut[j] = supportCallback.GetSupportVertexLocal();
+ }
+
+}
+
+
+
+btVector3 btConvexTriangleMeshShape::localGetSupportingVertex(const btVector3& vec)const
+{
+ btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec);
+
+ if ( getMargin()!=btScalar(0.) )
+ {
+ btVector3 vecnorm = vec;
+ if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON))
+ {
+ vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.));
+ }
+ vecnorm.normalize();
+ supVertex+= getMargin() * vecnorm;
+ }
+ return supVertex;
+}
+
+
+
+
+
+
+
+
+
+//currently just for debugging (drawing), perhaps future support for algebraic continuous collision detection
+//Please note that you can debug-draw btConvexTriangleMeshShape with the Raytracer Demo
+int btConvexTriangleMeshShape::getNumVertices() const
+{
+ //cache this?
+ return 0;
+
+}
+
+int btConvexTriangleMeshShape::getNumEdges() const
+{
+ return 0;
+}
+
+void btConvexTriangleMeshShape::getEdge(int ,btVector3& ,btVector3& ) const
+{
+ btAssert(0);
+}
+
+void btConvexTriangleMeshShape::getVertex(int ,btVector3& ) const
+{
+ btAssert(0);
+}
+
+int btConvexTriangleMeshShape::getNumPlanes() const
+{
+ return 0;
+}
+
+void btConvexTriangleMeshShape::getPlane(btVector3& ,btVector3& ,int ) const
+{
+ btAssert(0);
+}
+
+//not yet
+bool btConvexTriangleMeshShape::isInside(const btVector3& ,btScalar ) const
+{
+ btAssert(0);
+ return false;
+}
+
+
+
+void btConvexTriangleMeshShape::setLocalScaling(const btVector3& scaling)
+{
+ m_stridingMesh->setScaling(scaling);
+
+ recalcLocalAabb();
+
+}
+
+
+const btVector3& btConvexTriangleMeshShape::getLocalScaling() const
+{
+ return m_stridingMesh->getScaling();
+}
+
+void btConvexTriangleMeshShape::calculatePrincipalAxisTransform(btTransform& principal, btVector3& inertia, btScalar& volume) const
+{
+ class CenterCallback: public btInternalTriangleIndexCallback
+ {
+ bool first;
+ btVector3 ref;
+ btVector3 sum;
+ btScalar volume;
+
+ public:
+
+ CenterCallback() : first(true), ref(0, 0, 0), sum(0, 0, 0), volume(0)
+ {
+ }
+
+ virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex)
+ {
+ (void) triangleIndex;
+ (void) partId;
+ if (first)
+ {
+ ref = triangle[0];
+ first = false;
+ }
+ else
+ {
+ btScalar vol = btFabs((triangle[0] - ref).triple(triangle[1] - ref, triangle[2] - ref));
+ sum += (btScalar(0.25) * vol) * ((triangle[0] + triangle[1] + triangle[2] + ref));
+ volume += vol;
+ }
+ }
+
+ btVector3 getCenter()
+ {
+ return (volume > 0) ? sum / volume : ref;
+ }
+
+ btScalar getVolume()
+ {
+ return volume * btScalar(1. / 6);
+ }
+
+ };
+
+ class InertiaCallback: public btInternalTriangleIndexCallback
+ {
+ btMatrix3x3 sum;
+ btVector3 center;
+
+ public:
+
+ InertiaCallback(btVector3& center) : sum(0, 0, 0, 0, 0, 0, 0, 0, 0), center(center)
+ {
+ }
+
+ virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex)
+ {
+ (void) triangleIndex;
+ (void) partId;
+ btMatrix3x3 i;
+ btVector3 a = triangle[0] - center;
+ btVector3 b = triangle[1] - center;
+ btVector3 c = triangle[2] - center;
+ btScalar volNeg = -btFabs(a.triple(b, c)) * btScalar(1. / 6);
+ for (int j = 0; j < 3; j++)
+ {
+ for (int k = 0; k <= j; k++)
+ {
+ i[j][k] = i[k][j] = volNeg * (btScalar(0.1) * (a[j] * a[k] + b[j] * b[k] + c[j] * c[k])
+ + btScalar(0.05) * (a[j] * b[k] + a[k] * b[j] + a[j] * c[k] + a[k] * c[j] + b[j] * c[k] + b[k] * c[j]));
+ }
+ }
+ btScalar i00 = -i[0][0];
+ btScalar i11 = -i[1][1];
+ btScalar i22 = -i[2][2];
+ i[0][0] = i11 + i22;
+ i[1][1] = i22 + i00;
+ i[2][2] = i00 + i11;
+ sum[0] += i[0];
+ sum[1] += i[1];
+ sum[2] += i[2];
+ }
+
+ btMatrix3x3& getInertia()
+ {
+ return sum;
+ }
+
+ };
+
+ CenterCallback centerCallback;
+ btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
+ m_stridingMesh->InternalProcessAllTriangles(&centerCallback, -aabbMax, aabbMax);
+ btVector3 center = centerCallback.getCenter();
+ principal.setOrigin(center);
+ volume = centerCallback.getVolume();
+
+ InertiaCallback inertiaCallback(center);
+ m_stridingMesh->InternalProcessAllTriangles(&inertiaCallback, -aabbMax, aabbMax);
+
+ btMatrix3x3& i = inertiaCallback.getInertia();
+ i.diagonalize(principal.getBasis(), btScalar(0.00001), 20);
+ inertia.setValue(i[0][0], i[1][1], i[2][2]);
+ inertia /= volume;
+}
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h
new file mode 100644
index 0000000000..f338865ca1
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h
@@ -0,0 +1,77 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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_CONVEX_TRIANGLEMESH_SHAPE_H
+#define BT_CONVEX_TRIANGLEMESH_SHAPE_H
+
+
+#include "btPolyhedralConvexShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
+
+
+/// The btConvexTriangleMeshShape is a convex hull of a triangle mesh, but the performance is not as good as btConvexHullShape.
+/// A small benefit of this class is that it uses the btStridingMeshInterface, so you can avoid the duplication of the triangle mesh data. Nevertheless, most users should use the much better performing btConvexHullShape instead.
+ATTRIBUTE_ALIGNED16(class) btConvexTriangleMeshShape : public btPolyhedralConvexAabbCachingShape
+{
+
+ class btStridingMeshInterface* m_stridingMesh;
+
+public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ btConvexTriangleMeshShape(btStridingMeshInterface* meshInterface, bool calcAabb = true);
+
+ class btStridingMeshInterface* getMeshInterface()
+ {
+ return m_stridingMesh;
+ }
+ const class btStridingMeshInterface* getMeshInterface() const
+ {
+ return m_stridingMesh;
+ }
+
+ virtual btVector3 localGetSupportingVertex(const btVector3& vec)const;
+ virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
+ virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
+
+ //debugging
+ virtual const char* getName()const {return "ConvexTrimesh";}
+
+ virtual int getNumVertices() const;
+ virtual int getNumEdges() const;
+ virtual void getEdge(int i,btVector3& pa,btVector3& pb) const;
+ virtual void getVertex(int i,btVector3& vtx) const;
+ virtual int getNumPlanes() const;
+ virtual void getPlane(btVector3& planeNormal,btVector3& planeSupport,int i ) const;
+ virtual bool isInside(const btVector3& pt,btScalar tolerance) const;
+
+
+ virtual void setLocalScaling(const btVector3& scaling);
+ virtual const btVector3& getLocalScaling() const;
+
+ ///computes the exact moment of inertia and the transform from the coordinate system defined by the principal axes of the moment of inertia
+ ///and the center of mass to the current coordinate system. A mass of 1 is assumed, for other masses just multiply the computed "inertia"
+ ///by the mass. The resulting transform "principal" has to be applied inversely to the mesh in order for the local coordinate system of the
+ ///shape to be centered at the center of mass and to coincide with the principal axes. This also necessitates a correction of the world transform
+ ///of the collision object by the principal transform. This method also computes the volume of the convex mesh.
+ void calculatePrincipalAxisTransform(btTransform& principal, btVector3& inertia, btScalar& volume) const;
+
+};
+
+
+
+#endif //BT_CONVEX_TRIANGLEMESH_SHAPE_H
+
+
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btCylinderShape.cpp b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btCylinderShape.cpp
new file mode 100644
index 0000000000..604b3fc770
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btCylinderShape.cpp
@@ -0,0 +1,282 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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 "btCylinderShape.h"
+
+btCylinderShape::btCylinderShape (const btVector3& halfExtents)
+:btConvexInternalShape(),
+m_upAxis(1)
+{
+ btVector3 margin(getMargin(),getMargin(),getMargin());
+ m_implicitShapeDimensions = (halfExtents * m_localScaling) - margin;
+
+ setSafeMargin(halfExtents);
+
+ m_shapeType = CYLINDER_SHAPE_PROXYTYPE;
+}
+
+
+btCylinderShapeX::btCylinderShapeX (const btVector3& halfExtents)
+:btCylinderShape(halfExtents)
+{
+ m_upAxis = 0;
+
+}
+
+
+btCylinderShapeZ::btCylinderShapeZ (const btVector3& halfExtents)
+:btCylinderShape(halfExtents)
+{
+ m_upAxis = 2;
+
+}
+
+void btCylinderShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+{
+ btTransformAabb(getHalfExtentsWithoutMargin(),getMargin(),t,aabbMin,aabbMax);
+}
+
+void btCylinderShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+{
+
+//Until Bullet 2.77 a box approximation was used, so uncomment this if you need backwards compatibility
+//#define USE_BOX_INERTIA_APPROXIMATION 1
+#ifndef USE_BOX_INERTIA_APPROXIMATION
+
+ /*
+ cylinder is defined as following:
+ *
+ * - principle axis aligned along y by default, radius in x, z-value not used
+ * - for btCylinderShapeX: principle axis aligned along x, radius in y direction, z-value not used
+ * - for btCylinderShapeZ: principle axis aligned along z, radius in x direction, y-value not used
+ *
+ */
+
+ btScalar radius2; // square of cylinder radius
+ btScalar height2; // square of cylinder height
+ btVector3 halfExtents = getHalfExtentsWithMargin(); // get cylinder dimension
+ btScalar div12 = mass / 12.f;
+ btScalar div4 = mass / 4.f;
+ btScalar div2 = mass / 2.f;
+ int idxRadius, idxHeight;
+
+ switch (m_upAxis) // get indices of radius and height of cylinder
+ {
+ case 0: // cylinder is aligned along x
+ idxRadius = 1;
+ idxHeight = 0;
+ break;
+ case 2: // cylinder is aligned along z
+ idxRadius = 0;
+ idxHeight = 2;
+ break;
+ default: // cylinder is aligned along y
+ idxRadius = 0;
+ idxHeight = 1;
+ }
+
+ // calculate squares
+ radius2 = halfExtents[idxRadius] * halfExtents[idxRadius];
+ height2 = btScalar(4.) * halfExtents[idxHeight] * halfExtents[idxHeight];
+
+ // calculate tensor terms
+ btScalar t1 = div12 * height2 + div4 * radius2;
+ btScalar t2 = div2 * radius2;
+
+ switch (m_upAxis) // set diagonal elements of inertia tensor
+ {
+ case 0: // cylinder is aligned along x
+ inertia.setValue(t2,t1,t1);
+ break;
+ case 2: // cylinder is aligned along z
+ inertia.setValue(t1,t1,t2);
+ break;
+ default: // cylinder is aligned along y
+ inertia.setValue(t1,t2,t1);
+ }
+#else //USE_BOX_INERTIA_APPROXIMATION
+ //approximation of box shape
+ btVector3 halfExtents = getHalfExtentsWithMargin();
+
+ btScalar lx=btScalar(2.)*(halfExtents.x());
+ btScalar ly=btScalar(2.)*(halfExtents.y());
+ btScalar lz=btScalar(2.)*(halfExtents.z());
+
+ inertia.setValue(mass/(btScalar(12.0)) * (ly*ly + lz*lz),
+ mass/(btScalar(12.0)) * (lx*lx + lz*lz),
+ mass/(btScalar(12.0)) * (lx*lx + ly*ly));
+#endif //USE_BOX_INERTIA_APPROXIMATION
+}
+
+
+SIMD_FORCE_INLINE btVector3 CylinderLocalSupportX(const btVector3& halfExtents,const btVector3& v)
+{
+const int cylinderUpAxis = 0;
+const int XX = 1;
+const int YY = 0;
+const int ZZ = 2;
+
+ //mapping depends on how cylinder local orientation is
+ // extents of the cylinder is: X,Y is for radius, and Z for height
+
+
+ btScalar radius = halfExtents[XX];
+ btScalar halfHeight = halfExtents[cylinderUpAxis];
+
+
+ btVector3 tmp;
+ btScalar d ;
+
+ btScalar s = btSqrt(v[XX] * v[XX] + v[ZZ] * v[ZZ]);
+ if (s != btScalar(0.0))
+ {
+ d = radius / s;
+ tmp[XX] = v[XX] * d;
+ tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
+ tmp[ZZ] = v[ZZ] * d;
+ return tmp;
+ }
+ else
+ {
+ tmp[XX] = radius;
+ tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
+ tmp[ZZ] = btScalar(0.0);
+ return tmp;
+ }
+
+
+}
+
+
+
+
+
+
+inline btVector3 CylinderLocalSupportY(const btVector3& halfExtents,const btVector3& v)
+{
+
+const int cylinderUpAxis = 1;
+const int XX = 0;
+const int YY = 1;
+const int ZZ = 2;
+
+
+ btScalar radius = halfExtents[XX];
+ btScalar halfHeight = halfExtents[cylinderUpAxis];
+
+
+ btVector3 tmp;
+ btScalar d ;
+
+ btScalar s = btSqrt(v[XX] * v[XX] + v[ZZ] * v[ZZ]);
+ if (s != btScalar(0.0))
+ {
+ d = radius / s;
+ tmp[XX] = v[XX] * d;
+ tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
+ tmp[ZZ] = v[ZZ] * d;
+ return tmp;
+ }
+ else
+ {
+ tmp[XX] = radius;
+ tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
+ tmp[ZZ] = btScalar(0.0);
+ return tmp;
+ }
+
+}
+
+inline btVector3 CylinderLocalSupportZ(const btVector3& halfExtents,const btVector3& v)
+{
+const int cylinderUpAxis = 2;
+const int XX = 0;
+const int YY = 2;
+const int ZZ = 1;
+
+ //mapping depends on how cylinder local orientation is
+ // extents of the cylinder is: X,Y is for radius, and Z for height
+
+
+ btScalar radius = halfExtents[XX];
+ btScalar halfHeight = halfExtents[cylinderUpAxis];
+
+
+ btVector3 tmp;
+ btScalar d ;
+
+ btScalar s = btSqrt(v[XX] * v[XX] + v[ZZ] * v[ZZ]);
+ if (s != btScalar(0.0))
+ {
+ d = radius / s;
+ tmp[XX] = v[XX] * d;
+ tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
+ tmp[ZZ] = v[ZZ] * d;
+ return tmp;
+ }
+ else
+ {
+ tmp[XX] = radius;
+ tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
+ tmp[ZZ] = btScalar(0.0);
+ return tmp;
+ }
+
+
+}
+
+btVector3 btCylinderShapeX::localGetSupportingVertexWithoutMargin(const btVector3& vec)const
+{
+ return CylinderLocalSupportX(getHalfExtentsWithoutMargin(),vec);
+}
+
+
+btVector3 btCylinderShapeZ::localGetSupportingVertexWithoutMargin(const btVector3& vec)const
+{
+ return CylinderLocalSupportZ(getHalfExtentsWithoutMargin(),vec);
+}
+btVector3 btCylinderShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const
+{
+ return CylinderLocalSupportY(getHalfExtentsWithoutMargin(),vec);
+}
+
+void btCylinderShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+{
+ for (int i=0;i<numVectors;i++)
+ {
+ supportVerticesOut[i] = CylinderLocalSupportY(getHalfExtentsWithoutMargin(),vectors[i]);
+ }
+}
+
+void btCylinderShapeZ::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+{
+ for (int i=0;i<numVectors;i++)
+ {
+ supportVerticesOut[i] = CylinderLocalSupportZ(getHalfExtentsWithoutMargin(),vectors[i]);
+ }
+}
+
+
+
+
+void btCylinderShapeX::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+{
+ for (int i=0;i<numVectors;i++)
+ {
+ supportVerticesOut[i] = CylinderLocalSupportX(getHalfExtentsWithoutMargin(),vectors[i]);
+ }
+}
+
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btCylinderShape.h b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btCylinderShape.h
new file mode 100644
index 0000000000..a214a827c9
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btCylinderShape.h
@@ -0,0 +1,219 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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_CYLINDER_MINKOWSKI_H
+#define BT_CYLINDER_MINKOWSKI_H
+
+#include "btBoxShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
+#include "LinearMath/btVector3.h"
+
+/// The btCylinderShape class implements a cylinder shape primitive, centered around the origin. Its central axis aligned with the Y axis. btCylinderShapeX is aligned with the X axis and btCylinderShapeZ around the Z axis.
+ATTRIBUTE_ALIGNED16(class) btCylinderShape : public btConvexInternalShape
+
+{
+
+protected:
+
+ int m_upAxis;
+
+public:
+
+BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ btVector3 getHalfExtentsWithMargin() const
+ {
+ btVector3 halfExtents = getHalfExtentsWithoutMargin();
+ btVector3 margin(getMargin(),getMargin(),getMargin());
+ halfExtents += margin;
+ return halfExtents;
+ }
+
+ const btVector3& getHalfExtentsWithoutMargin() const
+ {
+ return m_implicitShapeDimensions;//changed in Bullet 2.63: assume the scaling and margin are included
+ }
+
+ btCylinderShape (const btVector3& halfExtents);
+
+ void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+
+ virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+
+ virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
+
+ virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
+
+ virtual void setMargin(btScalar collisionMargin)
+ {
+ //correct the m_implicitShapeDimensions for the margin
+ btVector3 oldMargin(getMargin(),getMargin(),getMargin());
+ btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin;
+
+ btConvexInternalShape::setMargin(collisionMargin);
+ btVector3 newMargin(getMargin(),getMargin(),getMargin());
+ m_implicitShapeDimensions = implicitShapeDimensionsWithMargin - newMargin;
+
+ }
+
+ virtual btVector3 localGetSupportingVertex(const btVector3& vec) const
+ {
+
+ btVector3 supVertex;
+ supVertex = localGetSupportingVertexWithoutMargin(vec);
+
+ if ( getMargin()!=btScalar(0.) )
+ {
+ btVector3 vecnorm = vec;
+ if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON))
+ {
+ vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.));
+ }
+ vecnorm.normalize();
+ supVertex+= getMargin() * vecnorm;
+ }
+ return supVertex;
+ }
+
+
+ //use box inertia
+ // virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+
+
+ int getUpAxis() const
+ {
+ return m_upAxis;
+ }
+
+ virtual btVector3 getAnisotropicRollingFrictionDirection() const
+ {
+ btVector3 aniDir(0,0,0);
+ aniDir[getUpAxis()]=1;
+ return aniDir;
+ }
+
+ virtual btScalar getRadius() const
+ {
+ return getHalfExtentsWithMargin().getX();
+ }
+
+ virtual void setLocalScaling(const btVector3& scaling)
+ {
+ btVector3 oldMargin(getMargin(),getMargin(),getMargin());
+ btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin;
+ btVector3 unScaledImplicitShapeDimensionsWithMargin = implicitShapeDimensionsWithMargin / m_localScaling;
+
+ btConvexInternalShape::setLocalScaling(scaling);
+
+ m_implicitShapeDimensions = (unScaledImplicitShapeDimensionsWithMargin * m_localScaling) - oldMargin;
+
+ }
+
+ //debugging
+ virtual const char* getName()const
+ {
+ return "CylinderY";
+ }
+
+ virtual int calculateSerializeBufferSize() const;
+
+ ///fills the dataBuffer and returns the struct name (and 0 on failure)
+ virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
+
+};
+
+class btCylinderShapeX : public btCylinderShape
+{
+public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ btCylinderShapeX (const btVector3& halfExtents);
+
+ virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
+ virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
+
+ //debugging
+ virtual const char* getName()const
+ {
+ return "CylinderX";
+ }
+
+ virtual btScalar getRadius() const
+ {
+ return getHalfExtentsWithMargin().getY();
+ }
+
+};
+
+class btCylinderShapeZ : public btCylinderShape
+{
+public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ btCylinderShapeZ (const btVector3& halfExtents);
+
+ virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
+ virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
+
+ //debugging
+ virtual const char* getName()const
+ {
+ return "CylinderZ";
+ }
+
+ virtual btScalar getRadius() const
+ {
+ return getHalfExtentsWithMargin().getX();
+ }
+
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btCylinderShapeData
+{
+ btConvexInternalShapeData m_convexInternalShapeData;
+
+ int m_upAxis;
+
+ char m_padding[4];
+};
+
+SIMD_FORCE_INLINE int btCylinderShape::calculateSerializeBufferSize() const
+{
+ return sizeof(btCylinderShapeData);
+}
+
+ ///fills the dataBuffer and returns the struct name (and 0 on failure)
+SIMD_FORCE_INLINE const char* btCylinderShape::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+ btCylinderShapeData* shapeData = (btCylinderShapeData*) dataBuffer;
+
+ btConvexInternalShape::serialize(&shapeData->m_convexInternalShapeData,serializer);
+
+ shapeData->m_upAxis = m_upAxis;
+
+ // Fill padding with zeros to appease msan.
+ shapeData->m_padding[0] = 0;
+ shapeData->m_padding[1] = 0;
+ shapeData->m_padding[2] = 0;
+ shapeData->m_padding[3] = 0;
+
+ return "btCylinderShapeData";
+}
+
+
+
+#endif //BT_CYLINDER_MINKOWSKI_H
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btEmptyShape.cpp b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btEmptyShape.cpp
new file mode 100644
index 0000000000..a9e6df5c58
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btEmptyShape.cpp
@@ -0,0 +1,50 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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 "btEmptyShape.h"
+
+
+#include "btCollisionShape.h"
+
+
+btEmptyShape::btEmptyShape() : btConcaveShape ()
+{
+ m_shapeType = EMPTY_SHAPE_PROXYTYPE;
+}
+
+
+btEmptyShape::~btEmptyShape()
+{
+}
+
+
+ ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
+void btEmptyShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+{
+ btVector3 margin(getMargin(),getMargin(),getMargin());
+
+ aabbMin = t.getOrigin() - margin;
+
+ aabbMax = t.getOrigin() + margin;
+
+}
+
+void btEmptyShape::calculateLocalInertia(btScalar ,btVector3& ) const
+{
+ btAssert(0);
+}
+
+
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btEmptyShape.h b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btEmptyShape.h
new file mode 100644
index 0000000000..069a79402b
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btEmptyShape.h
@@ -0,0 +1,72 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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_EMPTY_SHAPE_H
+#define BT_EMPTY_SHAPE_H
+
+#include "btConcaveShape.h"
+
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btTransform.h"
+#include "LinearMath/btMatrix3x3.h"
+#include "btCollisionMargin.h"
+
+
+
+
+/// The btEmptyShape is a collision shape without actual collision detection shape, so most users should ignore this class.
+/// It can be replaced by another shape during runtime, but the inertia tensor should be recomputed.
+ATTRIBUTE_ALIGNED16(class) btEmptyShape : public btConcaveShape
+{
+public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ btEmptyShape();
+
+ virtual ~btEmptyShape();
+
+
+ ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
+ void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+
+
+ virtual void setLocalScaling(const btVector3& scaling)
+ {
+ m_localScaling = scaling;
+ }
+ virtual const btVector3& getLocalScaling() const
+ {
+ return m_localScaling;
+ }
+
+ virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+
+ virtual const char* getName()const
+ {
+ return "Empty";
+ }
+
+ virtual void processAllTriangles(btTriangleCallback* ,const btVector3& ,const btVector3& ) const
+ {
+ }
+
+protected:
+ btVector3 m_localScaling;
+
+};
+
+
+
+#endif //BT_EMPTY_SHAPE_H
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp
new file mode 100644
index 0000000000..441a89c6bb
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp
@@ -0,0 +1,409 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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 "btHeightfieldTerrainShape.h"
+
+#include "LinearMath/btTransformUtil.h"
+
+
+
+btHeightfieldTerrainShape::btHeightfieldTerrainShape
+(
+int heightStickWidth, int heightStickLength, const void* heightfieldData,
+btScalar heightScale, btScalar minHeight, btScalar maxHeight,int upAxis,
+PHY_ScalarType hdt, bool flipQuadEdges
+)
+{
+ initialize(heightStickWidth, heightStickLength, heightfieldData,
+ heightScale, minHeight, maxHeight, upAxis, hdt,
+ flipQuadEdges);
+}
+
+
+
+btHeightfieldTerrainShape::btHeightfieldTerrainShape(int heightStickWidth, int heightStickLength,const void* heightfieldData,btScalar maxHeight,int upAxis,bool useFloatData,bool flipQuadEdges)
+{
+ // legacy constructor: support only float or unsigned char,
+ // and min height is zero
+ PHY_ScalarType hdt = (useFloatData) ? PHY_FLOAT : PHY_UCHAR;
+ btScalar minHeight = 0.0f;
+
+ // previously, height = uchar * maxHeight / 65535.
+ // So to preserve legacy behavior, heightScale = maxHeight / 65535
+ btScalar heightScale = maxHeight / 65535;
+
+ initialize(heightStickWidth, heightStickLength, heightfieldData,
+ heightScale, minHeight, maxHeight, upAxis, hdt,
+ flipQuadEdges);
+}
+
+
+
+void btHeightfieldTerrainShape::initialize
+(
+int heightStickWidth, int heightStickLength, const void* heightfieldData,
+btScalar heightScale, btScalar minHeight, btScalar maxHeight, int upAxis,
+PHY_ScalarType hdt, bool flipQuadEdges
+)
+{
+ // validation
+ btAssert(heightStickWidth > 1);// && "bad width");
+ btAssert(heightStickLength > 1);// && "bad length");
+ btAssert(heightfieldData);// && "null heightfield data");
+ // btAssert(heightScale) -- do we care? Trust caller here
+ btAssert(minHeight <= maxHeight);// && "bad min/max height");
+ btAssert(upAxis >= 0 && upAxis < 3);// && "bad upAxis--should be in range [0,2]");
+ btAssert(hdt != PHY_UCHAR || hdt != PHY_FLOAT || hdt != PHY_SHORT);// && "Bad height data type enum");
+
+ // initialize member variables
+ m_shapeType = TERRAIN_SHAPE_PROXYTYPE;
+ m_heightStickWidth = heightStickWidth;
+ m_heightStickLength = heightStickLength;
+ m_minHeight = minHeight;
+ m_maxHeight = maxHeight;
+ m_width = (btScalar) (heightStickWidth - 1);
+ m_length = (btScalar) (heightStickLength - 1);
+ m_heightScale = heightScale;
+ m_heightfieldDataUnknown = heightfieldData;
+ m_heightDataType = hdt;
+ m_flipQuadEdges = flipQuadEdges;
+ m_useDiamondSubdivision = false;
+ m_useZigzagSubdivision = false;
+ m_upAxis = upAxis;
+ m_localScaling.setValue(btScalar(1.), btScalar(1.), btScalar(1.));
+
+ // determine min/max axis-aligned bounding box (aabb) values
+ switch (m_upAxis)
+ {
+ case 0:
+ {
+ m_localAabbMin.setValue(m_minHeight, 0, 0);
+ m_localAabbMax.setValue(m_maxHeight, m_width, m_length);
+ break;
+ }
+ case 1:
+ {
+ m_localAabbMin.setValue(0, m_minHeight, 0);
+ m_localAabbMax.setValue(m_width, m_maxHeight, m_length);
+ break;
+ };
+ case 2:
+ {
+ m_localAabbMin.setValue(0, 0, m_minHeight);
+ m_localAabbMax.setValue(m_width, m_length, m_maxHeight);
+ break;
+ }
+ default:
+ {
+ //need to get valid m_upAxis
+ btAssert(0);// && "Bad m_upAxis");
+ }
+ }
+
+ // remember origin (defined as exact middle of aabb)
+ m_localOrigin = btScalar(0.5) * (m_localAabbMin + m_localAabbMax);
+}
+
+
+
+btHeightfieldTerrainShape::~btHeightfieldTerrainShape()
+{
+}
+
+
+
+void btHeightfieldTerrainShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+{
+ btVector3 halfExtents = (m_localAabbMax-m_localAabbMin)* m_localScaling * btScalar(0.5);
+
+ btVector3 localOrigin(0, 0, 0);
+ localOrigin[m_upAxis] = (m_minHeight + m_maxHeight) * btScalar(0.5);
+ localOrigin *= m_localScaling;
+
+ btMatrix3x3 abs_b = t.getBasis().absolute();
+ btVector3 center = t.getOrigin();
+ btVector3 extent = halfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
+ extent += btVector3(getMargin(),getMargin(),getMargin());
+
+ aabbMin = center - extent;
+ aabbMax = center + extent;
+}
+
+
+/// This returns the "raw" (user's initial) height, not the actual height.
+/// The actual height needs to be adjusted to be relative to the center
+/// of the heightfield's AABB.
+btScalar
+btHeightfieldTerrainShape::getRawHeightFieldValue(int x,int y) const
+{
+ btScalar val = 0.f;
+ switch (m_heightDataType)
+ {
+ case PHY_FLOAT:
+ {
+ val = m_heightfieldDataFloat[(y*m_heightStickWidth)+x];
+ break;
+ }
+
+ case PHY_UCHAR:
+ {
+ unsigned char heightFieldValue = m_heightfieldDataUnsignedChar[(y*m_heightStickWidth)+x];
+ val = heightFieldValue * m_heightScale;
+ break;
+ }
+
+ case PHY_SHORT:
+ {
+ short hfValue = m_heightfieldDataShort[(y * m_heightStickWidth) + x];
+ val = hfValue * m_heightScale;
+ break;
+ }
+
+ default:
+ {
+ btAssert(!"Bad m_heightDataType");
+ }
+ }
+
+ return val;
+}
+
+
+
+
+/// this returns the vertex in bullet-local coordinates
+void btHeightfieldTerrainShape::getVertex(int x,int y,btVector3& vertex) const
+{
+ btAssert(x>=0);
+ btAssert(y>=0);
+ btAssert(x<m_heightStickWidth);
+ btAssert(y<m_heightStickLength);
+
+ btScalar height = getRawHeightFieldValue(x,y);
+
+ switch (m_upAxis)
+ {
+ case 0:
+ {
+ vertex.setValue(
+ height - m_localOrigin.getX(),
+ (-m_width/btScalar(2.0)) + x,
+ (-m_length/btScalar(2.0) ) + y
+ );
+ break;
+ }
+ case 1:
+ {
+ vertex.setValue(
+ (-m_width/btScalar(2.0)) + x,
+ height - m_localOrigin.getY(),
+ (-m_length/btScalar(2.0)) + y
+ );
+ break;
+ };
+ case 2:
+ {
+ vertex.setValue(
+ (-m_width/btScalar(2.0)) + x,
+ (-m_length/btScalar(2.0)) + y,
+ height - m_localOrigin.getZ()
+ );
+ break;
+ }
+ default:
+ {
+ //need to get valid m_upAxis
+ btAssert(0);
+ }
+ }
+
+ vertex*=m_localScaling;
+}
+
+
+
+static inline int
+getQuantized
+(
+btScalar x
+)
+{
+ if (x < 0.0) {
+ return (int) (x - 0.5);
+ }
+ return (int) (x + 0.5);
+}
+
+
+
+/// given input vector, return quantized version
+/**
+ This routine is basically determining the gridpoint indices for a given
+ input vector, answering the question: "which gridpoint is closest to the
+ provided point?".
+
+ "with clamp" means that we restrict the point to be in the heightfield's
+ axis-aligned bounding box.
+ */
+void btHeightfieldTerrainShape::quantizeWithClamp(int* out, const btVector3& point,int /*isMax*/) const
+{
+ btVector3 clampedPoint(point);
+ clampedPoint.setMax(m_localAabbMin);
+ clampedPoint.setMin(m_localAabbMax);
+
+ out[0] = getQuantized(clampedPoint.getX());
+ out[1] = getQuantized(clampedPoint.getY());
+ out[2] = getQuantized(clampedPoint.getZ());
+
+}
+
+
+
+/// process all triangles within the provided axis-aligned bounding box
+/**
+ basic algorithm:
+ - convert input aabb to local coordinates (scale down and shift for local origin)
+ - convert input aabb to a range of heightfield grid points (quantize)
+ - iterate over all triangles in that subset of the grid
+ */
+void btHeightfieldTerrainShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
+{
+ // scale down the input aabb's so they are in local (non-scaled) coordinates
+ btVector3 localAabbMin = aabbMin*btVector3(1.f/m_localScaling[0],1.f/m_localScaling[1],1.f/m_localScaling[2]);
+ btVector3 localAabbMax = aabbMax*btVector3(1.f/m_localScaling[0],1.f/m_localScaling[1],1.f/m_localScaling[2]);
+
+ // account for local origin
+ localAabbMin += m_localOrigin;
+ localAabbMax += m_localOrigin;
+
+ //quantize the aabbMin and aabbMax, and adjust the start/end ranges
+ int quantizedAabbMin[3];
+ int quantizedAabbMax[3];
+ quantizeWithClamp(quantizedAabbMin, localAabbMin,0);
+ quantizeWithClamp(quantizedAabbMax, localAabbMax,1);
+
+ // expand the min/max quantized values
+ // this is to catch the case where the input aabb falls between grid points!
+ for (int i = 0; i < 3; ++i) {
+ quantizedAabbMin[i]--;
+ quantizedAabbMax[i]++;
+ }
+
+ int startX=0;
+ int endX=m_heightStickWidth-1;
+ int startJ=0;
+ int endJ=m_heightStickLength-1;
+
+ switch (m_upAxis)
+ {
+ case 0:
+ {
+ if (quantizedAabbMin[1]>startX)
+ startX = quantizedAabbMin[1];
+ if (quantizedAabbMax[1]<endX)
+ endX = quantizedAabbMax[1];
+ if (quantizedAabbMin[2]>startJ)
+ startJ = quantizedAabbMin[2];
+ if (quantizedAabbMax[2]<endJ)
+ endJ = quantizedAabbMax[2];
+ break;
+ }
+ case 1:
+ {
+ if (quantizedAabbMin[0]>startX)
+ startX = quantizedAabbMin[0];
+ if (quantizedAabbMax[0]<endX)
+ endX = quantizedAabbMax[0];
+ if (quantizedAabbMin[2]>startJ)
+ startJ = quantizedAabbMin[2];
+ if (quantizedAabbMax[2]<endJ)
+ endJ = quantizedAabbMax[2];
+ break;
+ };
+ case 2:
+ {
+ if (quantizedAabbMin[0]>startX)
+ startX = quantizedAabbMin[0];
+ if (quantizedAabbMax[0]<endX)
+ endX = quantizedAabbMax[0];
+ if (quantizedAabbMin[1]>startJ)
+ startJ = quantizedAabbMin[1];
+ if (quantizedAabbMax[1]<endJ)
+ endJ = quantizedAabbMax[1];
+ break;
+ }
+ default:
+ {
+ //need to get valid m_upAxis
+ btAssert(0);
+ }
+ }
+
+
+
+
+ for(int j=startJ; j<endJ; j++)
+ {
+ for(int x=startX; x<endX; x++)
+ {
+ btVector3 vertices[3];
+ if (m_flipQuadEdges || (m_useDiamondSubdivision && !((j+x) & 1))|| (m_useZigzagSubdivision && !(j & 1)))
+ {
+ //first triangle
+ getVertex(x,j,vertices[0]);
+ getVertex(x, j + 1, vertices[1]);
+ getVertex(x + 1, j + 1, vertices[2]);
+ callback->processTriangle(vertices,x,j);
+ //second triangle
+ // getVertex(x,j,vertices[0]);//already got this vertex before, thanks to Danny Chapman
+ getVertex(x+1,j+1,vertices[1]);
+ getVertex(x + 1, j, vertices[2]);
+ callback->processTriangle(vertices, x, j);
+
+ } else
+ {
+ //first triangle
+ getVertex(x,j,vertices[0]);
+ getVertex(x,j+1,vertices[1]);
+ getVertex(x+1,j,vertices[2]);
+ callback->processTriangle(vertices,x,j);
+ //second triangle
+ getVertex(x+1,j,vertices[0]);
+ //getVertex(x,j+1,vertices[1]);
+ getVertex(x+1,j+1,vertices[2]);
+ callback->processTriangle(vertices,x,j);
+ }
+ }
+ }
+
+
+
+}
+
+void btHeightfieldTerrainShape::calculateLocalInertia(btScalar ,btVector3& inertia) const
+{
+ //moving concave objects not supported
+
+ inertia.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
+}
+
+void btHeightfieldTerrainShape::setLocalScaling(const btVector3& scaling)
+{
+ m_localScaling = scaling;
+}
+const btVector3& btHeightfieldTerrainShape::getLocalScaling() const
+{
+ return m_localScaling;
+}
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h
new file mode 100644
index 0000000000..4a7a4a4bda
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h
@@ -0,0 +1,167 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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_HEIGHTFIELD_TERRAIN_SHAPE_H
+#define BT_HEIGHTFIELD_TERRAIN_SHAPE_H
+
+#include "btConcaveShape.h"
+
+///btHeightfieldTerrainShape simulates a 2D heightfield terrain
+/**
+ The caller is responsible for maintaining the heightfield array; this
+ class does not make a copy.
+
+ The heightfield can be dynamic so long as the min/max height values
+ capture the extremes (heights must always be in that range).
+
+ The local origin of the heightfield is assumed to be the exact
+ center (as determined by width and length and height, with each
+ axis multiplied by the localScaling).
+
+ \b NOTE: be careful with coordinates. If you have a heightfield with a local
+ min height of -100m, and a max height of +500m, you may be tempted to place it
+ at the origin (0,0) and expect the heights in world coordinates to be
+ -100 to +500 meters.
+ Actually, the heights will be -300 to +300m, because bullet will re-center
+ the heightfield based on its AABB (which is determined by the min/max
+ heights). So keep in mind that once you create a btHeightfieldTerrainShape
+ object, the heights will be adjusted relative to the center of the AABB. This
+ is different to the behavior of many rendering engines, but is useful for
+ physics engines.
+
+ Most (but not all) rendering and heightfield libraries assume upAxis = 1
+ (that is, the y-axis is "up"). This class allows any of the 3 coordinates
+ to be "up". Make sure your choice of axis is consistent with your rendering
+ system.
+
+ The heightfield heights are determined from the data type used for the
+ heightfieldData array.
+
+ - PHY_UCHAR: height at a point is the uchar value at the
+ grid point, multipled by heightScale. uchar isn't recommended
+ because of its inability to deal with negative values, and
+ low resolution (8-bit).
+
+ - PHY_SHORT: height at a point is the short int value at that grid
+ point, multipled by heightScale.
+
+ - PHY_FLOAT: height at a point is the float value at that grid
+ point. heightScale is ignored when using the float heightfield
+ data type.
+
+ Whatever the caller specifies as minHeight and maxHeight will be honored.
+ The class will not inspect the heightfield to discover the actual minimum
+ or maximum heights. These values are used to determine the heightfield's
+ axis-aligned bounding box, multiplied by localScaling.
+
+ For usage and testing see the TerrainDemo.
+ */
+ATTRIBUTE_ALIGNED16(class) btHeightfieldTerrainShape : public btConcaveShape
+{
+protected:
+ btVector3 m_localAabbMin;
+ btVector3 m_localAabbMax;
+ btVector3 m_localOrigin;
+
+ ///terrain data
+ int m_heightStickWidth;
+ int m_heightStickLength;
+ btScalar m_minHeight;
+ btScalar m_maxHeight;
+ btScalar m_width;
+ btScalar m_length;
+ btScalar m_heightScale;
+ union
+ {
+ const unsigned char* m_heightfieldDataUnsignedChar;
+ const short* m_heightfieldDataShort;
+ const btScalar* m_heightfieldDataFloat;
+ const void* m_heightfieldDataUnknown;
+ };
+
+ PHY_ScalarType m_heightDataType;
+ bool m_flipQuadEdges;
+ bool m_useDiamondSubdivision;
+ bool m_useZigzagSubdivision;
+
+ int m_upAxis;
+
+ btVector3 m_localScaling;
+
+ virtual btScalar getRawHeightFieldValue(int x,int y) const;
+ void quantizeWithClamp(int* out, const btVector3& point,int isMax) const;
+ void getVertex(int x,int y,btVector3& vertex) const;
+
+
+
+ /// protected initialization
+ /**
+ Handles the work of constructors so that public constructors can be
+ backwards-compatible without a lot of copy/paste.
+ */
+ void initialize(int heightStickWidth, int heightStickLength,
+ const void* heightfieldData, btScalar heightScale,
+ btScalar minHeight, btScalar maxHeight, int upAxis,
+ PHY_ScalarType heightDataType, bool flipQuadEdges);
+
+public:
+
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ /// preferred constructor
+ /**
+ This constructor supports a range of heightfield
+ data types, and allows for a non-zero minimum height value.
+ heightScale is needed for any integer-based heightfield data types.
+ */
+ btHeightfieldTerrainShape(int heightStickWidth,int heightStickLength,
+ const void* heightfieldData, btScalar heightScale,
+ btScalar minHeight, btScalar maxHeight,
+ int upAxis, PHY_ScalarType heightDataType,
+ bool flipQuadEdges);
+
+ /// legacy constructor
+ /**
+ The legacy constructor assumes the heightfield has a minimum height
+ of zero. Only unsigned char or floats are supported. For legacy
+ compatibility reasons, heightScale is calculated as maxHeight / 65535
+ (and is only used when useFloatData = false).
+ */
+ btHeightfieldTerrainShape(int heightStickWidth,int heightStickLength,const void* heightfieldData, btScalar maxHeight,int upAxis,bool useFloatData,bool flipQuadEdges);
+
+ virtual ~btHeightfieldTerrainShape();
+
+
+ void setUseDiamondSubdivision(bool useDiamondSubdivision=true) { m_useDiamondSubdivision = useDiamondSubdivision;}
+
+ ///could help compatibility with Ogre heightfields. See https://code.google.com/p/bullet/issues/detail?id=625
+ void setUseZigzagSubdivision(bool useZigzagSubdivision=true) { m_useZigzagSubdivision = useZigzagSubdivision;}
+
+ virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+
+ virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
+
+ virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+
+ virtual void setLocalScaling(const btVector3& scaling);
+
+ virtual const btVector3& getLocalScaling() const;
+
+ //debugging
+ virtual const char* getName()const {return "HEIGHTFIELD";}
+
+};
+
+#endif //BT_HEIGHTFIELD_TERRAIN_SHAPE_H
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btMaterial.h b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btMaterial.h
new file mode 100644
index 0000000000..866f9b4da4
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btMaterial.h
@@ -0,0 +1,35 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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.
+*/
+
+/// This file was created by Alex Silverman
+
+#ifndef BT_MATERIAL_H
+#define BT_MATERIAL_H
+
+// Material class to be used by btMultimaterialTriangleMeshShape to store triangle properties
+class btMaterial
+{
+ // public members so that materials can change due to world events
+public:
+ btScalar m_friction;
+ btScalar m_restitution;
+ int pad[2];
+
+ btMaterial(){}
+ btMaterial(btScalar fric, btScalar rest) { m_friction = fric; m_restitution = rest; }
+};
+
+#endif // BT_MATERIAL_H
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp
new file mode 100644
index 0000000000..899ef50056
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp
@@ -0,0 +1,77 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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 "btMinkowskiSumShape.h"
+
+
+btMinkowskiSumShape::btMinkowskiSumShape(const btConvexShape* shapeA,const btConvexShape* shapeB)
+: btConvexInternalShape (),
+m_shapeA(shapeA),
+m_shapeB(shapeB)
+{
+ m_shapeType = MINKOWSKI_DIFFERENCE_SHAPE_PROXYTYPE;
+ m_transA.setIdentity();
+ m_transB.setIdentity();
+}
+
+btVector3 btMinkowskiSumShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const
+{
+ btVector3 supVertexA = m_transA(m_shapeA->localGetSupportingVertexWithoutMargin(vec*m_transA.getBasis()));
+ btVector3 supVertexB = m_transB(m_shapeB->localGetSupportingVertexWithoutMargin(-vec*m_transB.getBasis()));
+ return supVertexA - supVertexB;
+}
+
+void btMinkowskiSumShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+{
+ ///@todo: could make recursive use of batching. probably this shape is not used frequently.
+ for (int i=0;i<numVectors;i++)
+ {
+ supportVerticesOut[i] = localGetSupportingVertexWithoutMargin(vectors[i]);
+ }
+
+}
+
+
+
+btScalar btMinkowskiSumShape::getMargin() const
+{
+ return m_shapeA->getMargin() + m_shapeB->getMargin();
+}
+
+
+void btMinkowskiSumShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+{
+ (void)mass;
+ //inertia of the AABB of the Minkowski sum
+ btTransform identity;
+ identity.setIdentity();
+ btVector3 aabbMin,aabbMax;
+ getAabb(identity,aabbMin,aabbMax);
+
+ btVector3 halfExtents = (aabbMax-aabbMin)*btScalar(0.5);
+
+ btScalar margin = getMargin();
+
+ btScalar lx=btScalar(2.)*(halfExtents.x()+margin);
+ btScalar ly=btScalar(2.)*(halfExtents.y()+margin);
+ btScalar lz=btScalar(2.)*(halfExtents.z()+margin);
+ const btScalar x2 = lx*lx;
+ const btScalar y2 = ly*ly;
+ const btScalar z2 = lz*lz;
+ const btScalar scaledmass = mass * btScalar(0.08333333);
+
+ inertia = scaledmass * (btVector3(y2+z2,x2+z2,x2+y2));
+}
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h
new file mode 100644
index 0000000000..a3f9a47239
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h
@@ -0,0 +1,62 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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_MINKOWSKI_SUM_SHAPE_H
+#define BT_MINKOWSKI_SUM_SHAPE_H
+
+#include "btConvexInternalShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
+
+/// The btMinkowskiSumShape is only for advanced users. This shape represents implicit based minkowski sum of two convex implicit shapes.
+ATTRIBUTE_ALIGNED16(class) btMinkowskiSumShape : public btConvexInternalShape
+{
+
+ btTransform m_transA;
+ btTransform m_transB;
+ const btConvexShape* m_shapeA;
+ const btConvexShape* m_shapeB;
+
+public:
+
+BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ btMinkowskiSumShape(const btConvexShape* shapeA,const btConvexShape* shapeB);
+
+ virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
+
+ virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
+
+
+ virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+
+ void setTransformA(const btTransform& transA) { m_transA = transA;}
+ void setTransformB(const btTransform& transB) { m_transB = transB;}
+
+ const btTransform& getTransformA()const { return m_transA;}
+ const btTransform& GetTransformB()const { return m_transB;}
+
+
+ virtual btScalar getMargin() const;
+
+ const btConvexShape* getShapeA() const { return m_shapeA;}
+ const btConvexShape* getShapeB() const { return m_shapeB;}
+
+ virtual const char* getName()const
+ {
+ return "MinkowskiSum";
+ }
+};
+
+#endif //BT_MINKOWSKI_SUM_SHAPE_H
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp
new file mode 100644
index 0000000000..4195fa3138
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp
@@ -0,0 +1,185 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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.
+*/
+
+#if defined (_WIN32) || defined (__i386__)
+#define BT_USE_SSE_IN_API
+#endif
+
+#include "btMultiSphereShape.h"
+#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
+#include "LinearMath/btQuaternion.h"
+#include "LinearMath/btSerializer.h"
+
+btMultiSphereShape::btMultiSphereShape (const btVector3* positions,const btScalar* radi,int numSpheres)
+:btConvexInternalAabbCachingShape ()
+{
+ m_shapeType = MULTI_SPHERE_SHAPE_PROXYTYPE;
+ //btScalar startMargin = btScalar(BT_LARGE_FLOAT);
+
+ m_localPositionArray.resize(numSpheres);
+ m_radiArray.resize(numSpheres);
+ for (int i=0;i<numSpheres;i++)
+ {
+ m_localPositionArray[i] = positions[i];
+ m_radiArray[i] = radi[i];
+
+ }
+
+ recalcLocalAabb();
+
+}
+
+#ifndef MIN
+ #define MIN( _a, _b) ((_a) < (_b) ? (_a) : (_b))
+#endif
+ btVector3 btMultiSphereShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0)const
+{
+ btVector3 supVec(0,0,0);
+
+ btScalar maxDot(btScalar(-BT_LARGE_FLOAT));
+
+
+ btVector3 vec = vec0;
+ btScalar lenSqr = vec.length2();
+ if (lenSqr < (SIMD_EPSILON*SIMD_EPSILON))
+ {
+ vec.setValue(1,0,0);
+ } else
+ {
+ btScalar rlen = btScalar(1.) / btSqrt(lenSqr );
+ vec *= rlen;
+ }
+
+ btVector3 vtx;
+ btScalar newDot;
+
+ const btVector3* pos = &m_localPositionArray[0];
+ const btScalar* rad = &m_radiArray[0];
+ int numSpheres = m_localPositionArray.size();
+
+ for( int k = 0; k < numSpheres; k+= 128 )
+ {
+ btVector3 temp[128];
+ int inner_count = MIN( numSpheres - k, 128 );
+ for( long i = 0; i < inner_count; i++ )
+ {
+ temp[i] = (*pos)*m_localScaling +vec*m_localScaling*(*rad) - vec * getMargin();
+ pos++;
+ rad++;
+ }
+ long i = vec.maxDot( temp, inner_count, newDot);
+ if( newDot > maxDot )
+ {
+ maxDot = newDot;
+ supVec = temp[i];
+ }
+ }
+
+ return supVec;
+
+}
+
+ void btMultiSphereShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+{
+
+ for (int j=0;j<numVectors;j++)
+ {
+ btScalar maxDot(btScalar(-BT_LARGE_FLOAT));
+
+ const btVector3& vec = vectors[j];
+
+ btVector3 vtx;
+ btScalar newDot;
+
+ const btVector3* pos = &m_localPositionArray[0];
+ const btScalar* rad = &m_radiArray[0];
+ int numSpheres = m_localPositionArray.size();
+
+ for( int k = 0; k < numSpheres; k+= 128 )
+ {
+ btVector3 temp[128];
+ int inner_count = MIN( numSpheres - k, 128 );
+ for( long i = 0; i < inner_count; i++ )
+ {
+ temp[i] = (*pos)*m_localScaling +vec*m_localScaling*(*rad) - vec * getMargin();
+ pos++;
+ rad++;
+ }
+ long i = vec.maxDot( temp, inner_count, newDot);
+ if( newDot > maxDot )
+ {
+ maxDot = newDot;
+ supportVerticesOut[j] = temp[i];
+ }
+ }
+
+ }
+}
+
+
+
+
+
+
+
+
+void btMultiSphereShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+{
+ //as an approximation, take the inertia of the box that bounds the spheres
+
+ btVector3 localAabbMin,localAabbMax;
+ getCachedLocalAabb(localAabbMin,localAabbMax);
+ btVector3 halfExtents = (localAabbMax-localAabbMin)*btScalar(0.5);
+
+ btScalar lx=btScalar(2.)*(halfExtents.x());
+ btScalar ly=btScalar(2.)*(halfExtents.y());
+ btScalar lz=btScalar(2.)*(halfExtents.z());
+
+ inertia.setValue(mass/(btScalar(12.0)) * (ly*ly + lz*lz),
+ mass/(btScalar(12.0)) * (lx*lx + lz*lz),
+ mass/(btScalar(12.0)) * (lx*lx + ly*ly));
+
+}
+
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+const char* btMultiSphereShape::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+ btMultiSphereShapeData* shapeData = (btMultiSphereShapeData*) dataBuffer;
+ btConvexInternalShape::serialize(&shapeData->m_convexInternalShapeData, serializer);
+
+ int numElem = m_localPositionArray.size();
+ shapeData->m_localPositionArrayPtr = numElem ? (btPositionAndRadius*)serializer->getUniquePointer((void*)&m_localPositionArray[0]): 0;
+
+ shapeData->m_localPositionArraySize = numElem;
+ if (numElem)
+ {
+ btChunk* chunk = serializer->allocate(sizeof(btPositionAndRadius),numElem);
+ btPositionAndRadius* memPtr = (btPositionAndRadius*)chunk->m_oldPtr;
+ for (int i=0;i<numElem;i++,memPtr++)
+ {
+ m_localPositionArray[i].serializeFloat(memPtr->m_pos);
+ memPtr->m_radius = float(m_radiArray[i]);
+ }
+ serializer->finalizeChunk(chunk,"btPositionAndRadius",BT_ARRAY_CODE,(void*)&m_localPositionArray[0]);
+ }
+
+ // Fill padding with zeros to appease msan.
+ memset(shapeData->m_padding, 0, sizeof(shapeData->m_padding));
+
+ return "btMultiSphereShapeData";
+}
+
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btMultiSphereShape.h b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btMultiSphereShape.h
new file mode 100644
index 0000000000..5d3b402684
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btMultiSphereShape.h
@@ -0,0 +1,101 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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_MULTI_SPHERE_MINKOWSKI_H
+#define BT_MULTI_SPHERE_MINKOWSKI_H
+
+#include "btConvexInternalShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
+#include "LinearMath/btAlignedObjectArray.h"
+#include "LinearMath/btAabbUtil2.h"
+
+
+
+///The btMultiSphereShape represents the convex hull of a collection of spheres. You can create special capsules or other smooth volumes.
+///It is possible to animate the spheres for deformation, but call 'recalcLocalAabb' after changing any sphere position/radius
+ATTRIBUTE_ALIGNED16(class) btMultiSphereShape : public btConvexInternalAabbCachingShape
+{
+
+ btAlignedObjectArray<btVector3> m_localPositionArray;
+ btAlignedObjectArray<btScalar> m_radiArray;
+
+public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ btMultiSphereShape (const btVector3* positions,const btScalar* radi,int numSpheres);
+
+ ///CollisionShape Interface
+ virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+
+ /// btConvexShape Interface
+ virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
+
+ virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
+
+ int getSphereCount() const
+ {
+ return m_localPositionArray.size();
+ }
+
+ const btVector3& getSpherePosition(int index) const
+ {
+ return m_localPositionArray[index];
+ }
+
+ btScalar getSphereRadius(int index) const
+ {
+ return m_radiArray[index];
+ }
+
+
+ virtual const char* getName()const
+ {
+ return "MultiSphere";
+ }
+
+ virtual int calculateSerializeBufferSize() const;
+
+ ///fills the dataBuffer and returns the struct name (and 0 on failure)
+ virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
+
+
+};
+
+
+struct btPositionAndRadius
+{
+ btVector3FloatData m_pos;
+ float m_radius;
+};
+
+struct btMultiSphereShapeData
+{
+ btConvexInternalShapeData m_convexInternalShapeData;
+
+ btPositionAndRadius *m_localPositionArrayPtr;
+ int m_localPositionArraySize;
+ char m_padding[4];
+};
+
+
+
+SIMD_FORCE_INLINE int btMultiSphereShape::calculateSerializeBufferSize() const
+{
+ return sizeof(btMultiSphereShapeData);
+}
+
+
+
+#endif //BT_MULTI_SPHERE_MINKOWSKI_H
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp
new file mode 100644
index 0000000000..58799ac96a
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp
@@ -0,0 +1,45 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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.
+*/
+
+/// This file was created by Alex Silverman
+
+#include "BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h"
+#include "BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h"
+//#include "BulletCollision/CollisionShapes/btOptimizedBvh.h"
+
+
+///Obtains the material for a specific triangle
+const btMaterial * btMultimaterialTriangleMeshShape::getMaterialProperties(int partID, int triIndex)
+{
+ const unsigned char * materialBase = 0;
+ int numMaterials;
+ PHY_ScalarType materialType;
+ int materialStride;
+ const unsigned char * triangleMaterialBase = 0;
+ int numTriangles;
+ int triangleMaterialStride;
+ PHY_ScalarType triangleType;
+
+ ((btTriangleIndexVertexMaterialArray*)m_meshInterface)->getLockedReadOnlyMaterialBase(&materialBase, numMaterials, materialType, materialStride,
+ &triangleMaterialBase, numTriangles, triangleMaterialStride, triangleType, partID);
+
+ // return the pointer to the place with the friction for the triangle
+ // TODO: This depends on whether it's a moving mesh or not
+ // BUG IN GIMPACT
+ //return (btScalar*)(&materialBase[triangleMaterialBase[(triIndex-1) * triangleMaterialStride] * materialStride]);
+ int * matInd = (int *)(&(triangleMaterialBase[(triIndex * triangleMaterialStride)]));
+ btMaterial *matVal = (btMaterial *)(&(materialBase[*matInd * materialStride]));
+ return (matVal);
+}
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h
new file mode 100644
index 0000000000..5ebaede4a8
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h
@@ -0,0 +1,119 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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.
+*/
+
+/// This file was created by Alex Silverman
+
+#ifndef BT_BVH_TRIANGLE_MATERIAL_MESH_SHAPE_H
+#define BT_BVH_TRIANGLE_MATERIAL_MESH_SHAPE_H
+
+#include "btBvhTriangleMeshShape.h"
+#include "btMaterial.h"
+
+///The BvhTriangleMaterialMeshShape extends the btBvhTriangleMeshShape. Its main contribution is the interface into a material array, which allows per-triangle friction and restitution.
+ATTRIBUTE_ALIGNED16(class) btMultimaterialTriangleMeshShape : public btBvhTriangleMeshShape
+{
+ btAlignedObjectArray <btMaterial*> m_materialList;
+
+public:
+
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ btMultimaterialTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, bool buildBvh = true):
+ btBvhTriangleMeshShape(meshInterface, useQuantizedAabbCompression, buildBvh)
+ {
+ m_shapeType = MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE;
+
+ const unsigned char *vertexbase;
+ int numverts;
+ PHY_ScalarType type;
+ int stride;
+ const unsigned char *indexbase;
+ int indexstride;
+ int numfaces;
+ PHY_ScalarType indicestype;
+
+ //m_materialLookup = (int**)(btAlignedAlloc(sizeof(int*) * meshInterface->getNumSubParts(), 16));
+
+ for(int i = 0; i < meshInterface->getNumSubParts(); i++)
+ {
+ m_meshInterface->getLockedReadOnlyVertexIndexBase(
+ &vertexbase,
+ numverts,
+ type,
+ stride,
+ &indexbase,
+ indexstride,
+ numfaces,
+ indicestype,
+ i);
+ //m_materialLookup[i] = (int*)(btAlignedAlloc(sizeof(int) * numfaces, 16));
+ }
+ }
+
+ ///optionally pass in a larger bvh aabb, used for quantization. This allows for deformations within this aabb
+ btMultimaterialTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax, bool buildBvh = true):
+ btBvhTriangleMeshShape(meshInterface, useQuantizedAabbCompression, bvhAabbMin, bvhAabbMax, buildBvh)
+ {
+ m_shapeType = MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE;
+
+ const unsigned char *vertexbase;
+ int numverts;
+ PHY_ScalarType type;
+ int stride;
+ const unsigned char *indexbase;
+ int indexstride;
+ int numfaces;
+ PHY_ScalarType indicestype;
+
+ //m_materialLookup = (int**)(btAlignedAlloc(sizeof(int*) * meshInterface->getNumSubParts(), 16));
+
+ for(int i = 0; i < meshInterface->getNumSubParts(); i++)
+ {
+ m_meshInterface->getLockedReadOnlyVertexIndexBase(
+ &vertexbase,
+ numverts,
+ type,
+ stride,
+ &indexbase,
+ indexstride,
+ numfaces,
+ indicestype,
+ i);
+ //m_materialLookup[i] = (int*)(btAlignedAlloc(sizeof(int) * numfaces * 2, 16));
+ }
+ }
+
+ virtual ~btMultimaterialTriangleMeshShape()
+ {
+/*
+ for(int i = 0; i < m_meshInterface->getNumSubParts(); i++)
+ {
+ btAlignedFree(m_materialValues[i]);
+ m_materialLookup[i] = NULL;
+ }
+ btAlignedFree(m_materialValues);
+ m_materialLookup = NULL;
+*/
+ }
+ //debugging
+ virtual const char* getName()const {return "MULTIMATERIALTRIANGLEMESH";}
+
+ ///Obtains the material for a specific triangle
+ const btMaterial * getMaterialProperties(int partID, int triIndex);
+
+}
+;
+
+#endif //BT_BVH_TRIANGLE_MATERIAL_MESH_SHAPE_H
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp
new file mode 100644
index 0000000000..6f36775f7c
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp
@@ -0,0 +1,391 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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 "btOptimizedBvh.h"
+#include "btStridingMeshInterface.h"
+#include "LinearMath/btAabbUtil2.h"
+#include "LinearMath/btIDebugDraw.h"
+
+
+btOptimizedBvh::btOptimizedBvh()
+{
+}
+
+btOptimizedBvh::~btOptimizedBvh()
+{
+}
+
+
+void btOptimizedBvh::build(btStridingMeshInterface* triangles, bool useQuantizedAabbCompression, const btVector3& bvhAabbMin, const btVector3& bvhAabbMax)
+{
+ m_useQuantization = useQuantizedAabbCompression;
+
+
+ // NodeArray triangleNodes;
+
+ struct NodeTriangleCallback : public btInternalTriangleIndexCallback
+ {
+
+ NodeArray& m_triangleNodes;
+
+ NodeTriangleCallback& operator=(NodeTriangleCallback& other)
+ {
+ m_triangleNodes.copyFromArray(other.m_triangleNodes);
+ return *this;
+ }
+
+ NodeTriangleCallback(NodeArray& triangleNodes)
+ :m_triangleNodes(triangleNodes)
+ {
+ }
+
+ virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex)
+ {
+ btOptimizedBvhNode node;
+ 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]);
+
+ //with quantization?
+ node.m_aabbMinOrg = aabbMin;
+ node.m_aabbMaxOrg = aabbMax;
+
+ node.m_escapeIndex = -1;
+
+ //for child nodes
+ node.m_subPart = partId;
+ node.m_triangleIndex = triangleIndex;
+ m_triangleNodes.push_back(node);
+ }
+ };
+ struct QuantizedNodeTriangleCallback : public btInternalTriangleIndexCallback
+ {
+ QuantizedNodeArray& m_triangleNodes;
+ const btQuantizedBvh* m_optimizedTree; // for quantization
+
+ QuantizedNodeTriangleCallback& operator=(QuantizedNodeTriangleCallback& other)
+ {
+ m_triangleNodes.copyFromArray(other.m_triangleNodes);
+ m_optimizedTree = other.m_optimizedTree;
+ return *this;
+ }
+
+ QuantizedNodeTriangleCallback(QuantizedNodeArray& triangleNodes,const btQuantizedBvh* tree)
+ :m_triangleNodes(triangleNodes),m_optimizedTree(tree)
+ {
+ }
+
+ virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex)
+ {
+ // The partId and triangle index must fit in the same (positive) integer
+ btAssert(partId < (1<<MAX_NUM_PARTS_IN_BITS));
+ btAssert(triangleIndex < (1<<(31-MAX_NUM_PARTS_IN_BITS)));
+ //negative indices are reserved for escapeIndex
+ btAssert(triangleIndex>=0);
+
+ btQuantizedBvhNode node;
+ 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]);
+
+ //PCK: add these checks for zero dimensions of aabb
+ const btScalar MIN_AABB_DIMENSION = btScalar(0.002);
+ const btScalar MIN_AABB_HALF_DIMENSION = btScalar(0.001);
+ if (aabbMax.x() - aabbMin.x() < MIN_AABB_DIMENSION)
+ {
+ aabbMax.setX(aabbMax.x() + MIN_AABB_HALF_DIMENSION);
+ aabbMin.setX(aabbMin.x() - MIN_AABB_HALF_DIMENSION);
+ }
+ if (aabbMax.y() - aabbMin.y() < MIN_AABB_DIMENSION)
+ {
+ aabbMax.setY(aabbMax.y() + MIN_AABB_HALF_DIMENSION);
+ aabbMin.setY(aabbMin.y() - MIN_AABB_HALF_DIMENSION);
+ }
+ if (aabbMax.z() - aabbMin.z() < MIN_AABB_DIMENSION)
+ {
+ aabbMax.setZ(aabbMax.z() + MIN_AABB_HALF_DIMENSION);
+ aabbMin.setZ(aabbMin.z() - MIN_AABB_HALF_DIMENSION);
+ }
+
+ m_optimizedTree->quantize(&node.m_quantizedAabbMin[0],aabbMin,0);
+ m_optimizedTree->quantize(&node.m_quantizedAabbMax[0],aabbMax,1);
+
+ node.m_escapeIndexOrTriangleIndex = (partId<<(31-MAX_NUM_PARTS_IN_BITS)) | triangleIndex;
+
+ m_triangleNodes.push_back(node);
+ }
+ };
+
+
+
+ int numLeafNodes = 0;
+
+
+ if (m_useQuantization)
+ {
+
+ //initialize quantization values
+ setQuantizationValues(bvhAabbMin,bvhAabbMax);
+
+ QuantizedNodeTriangleCallback callback(m_quantizedLeafNodes,this);
+
+
+ triangles->InternalProcessAllTriangles(&callback,m_bvhAabbMin,m_bvhAabbMax);
+
+ //now we have an array of leafnodes in m_leafNodes
+ numLeafNodes = m_quantizedLeafNodes.size();
+
+
+ m_quantizedContiguousNodes.resize(2*numLeafNodes);
+
+
+ } else
+ {
+ NodeTriangleCallback callback(m_leafNodes);
+
+ btVector3 aabbMin(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT));
+ btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
+
+ triangles->InternalProcessAllTriangles(&callback,aabbMin,aabbMax);
+
+ //now we have an array of leafnodes in m_leafNodes
+ numLeafNodes = m_leafNodes.size();
+
+ m_contiguousNodes.resize(2*numLeafNodes);
+ }
+
+ m_curNodeIndex = 0;
+
+ buildTree(0,numLeafNodes);
+
+ ///if the entire tree is small then subtree size, we need to create a header info for the tree
+ if(m_useQuantization && !m_SubtreeHeaders.size())
+ {
+ btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand();
+ subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[0]);
+ subtree.m_rootNodeIndex = 0;
+ subtree.m_subtreeSize = m_quantizedContiguousNodes[0].isLeafNode() ? 1 : m_quantizedContiguousNodes[0].getEscapeIndex();
+ }
+
+ //PCK: update the copy of the size
+ m_subtreeHeaderCount = m_SubtreeHeaders.size();
+
+ //PCK: clear m_quantizedLeafNodes and m_leafNodes, they are temporary
+ m_quantizedLeafNodes.clear();
+ m_leafNodes.clear();
+}
+
+
+
+
+void btOptimizedBvh::refit(btStridingMeshInterface* meshInterface,const btVector3& aabbMin,const btVector3& aabbMax)
+{
+ if (m_useQuantization)
+ {
+
+ setQuantizationValues(aabbMin,aabbMax);
+
+ updateBvhNodes(meshInterface,0,m_curNodeIndex,0);
+
+ ///now update all subtree headers
+
+ int i;
+ for (i=0;i<m_SubtreeHeaders.size();i++)
+ {
+ btBvhSubtreeInfo& subtree = m_SubtreeHeaders[i];
+ subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[subtree.m_rootNodeIndex]);
+ }
+
+ } else
+ {
+
+ }
+}
+
+
+
+
+void btOptimizedBvh::refitPartial(btStridingMeshInterface* meshInterface,const btVector3& aabbMin,const btVector3& aabbMax)
+{
+ //incrementally initialize quantization values
+ btAssert(m_useQuantization);
+
+ btAssert(aabbMin.getX() > m_bvhAabbMin.getX());
+ btAssert(aabbMin.getY() > m_bvhAabbMin.getY());
+ btAssert(aabbMin.getZ() > m_bvhAabbMin.getZ());
+
+ btAssert(aabbMax.getX() < m_bvhAabbMax.getX());
+ btAssert(aabbMax.getY() < m_bvhAabbMax.getY());
+ btAssert(aabbMax.getZ() < m_bvhAabbMax.getZ());
+
+ ///we should update all quantization values, using updateBvhNodes(meshInterface);
+ ///but we only update chunks that overlap the given aabb
+
+ unsigned short quantizedQueryAabbMin[3];
+ unsigned short quantizedQueryAabbMax[3];
+
+ quantize(&quantizedQueryAabbMin[0],aabbMin,0);
+ quantize(&quantizedQueryAabbMax[0],aabbMax,1);
+
+ int i;
+ for (i=0;i<this->m_SubtreeHeaders.size();i++)
+ {
+ btBvhSubtreeInfo& subtree = m_SubtreeHeaders[i];
+
+ //PCK: unsigned instead of bool
+ unsigned overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax);
+ if (overlap != 0)
+ {
+ updateBvhNodes(meshInterface,subtree.m_rootNodeIndex,subtree.m_rootNodeIndex+subtree.m_subtreeSize,i);
+
+ subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[subtree.m_rootNodeIndex]);
+ }
+ }
+
+}
+
+void btOptimizedBvh::updateBvhNodes(btStridingMeshInterface* meshInterface,int firstNode,int endNode,int index)
+{
+ (void)index;
+
+ btAssert(m_useQuantization);
+
+ int curNodeSubPart=-1;
+
+ //get access info to trianglemesh data
+ const unsigned char *vertexbase = 0;
+ int numverts = 0;
+ PHY_ScalarType type = PHY_INTEGER;
+ int stride = 0;
+ const unsigned char *indexbase = 0;
+ int indexstride = 0;
+ int numfaces = 0;
+ PHY_ScalarType indicestype = PHY_INTEGER;
+
+ btVector3 triangleVerts[3];
+ btVector3 aabbMin,aabbMax;
+ const btVector3& meshScaling = meshInterface->getScaling();
+
+ int i;
+ for (i=endNode-1;i>=firstNode;i--)
+ {
+
+
+ btQuantizedBvhNode& curNode = m_quantizedContiguousNodes[i];
+ if (curNode.isLeafNode())
+ {
+ //recalc aabb from triangle data
+ int nodeSubPart = curNode.getPartId();
+ int nodeTriangleIndex = curNode.getTriangleIndex();
+ if (nodeSubPart != curNodeSubPart)
+ {
+ if (curNodeSubPart >= 0)
+ meshInterface->unLockReadOnlyVertexBase(curNodeSubPart);
+ meshInterface->getLockedReadOnlyVertexIndexBase(&vertexbase,numverts, type,stride,&indexbase,indexstride,numfaces,indicestype,nodeSubPart);
+
+ curNodeSubPart = nodeSubPart;
+ btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT);
+ }
+ //triangles->getLockedReadOnlyVertexIndexBase(vertexBase,numVerts,
+
+ unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride);
+
+
+ for (int j=2;j>=0;j--)
+ {
+
+ int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j];
+ if (type == PHY_FLOAT)
+ {
+ float* graphicsbase = (float*)(vertexbase+graphicsindex*stride);
+ triangleVerts[j] = btVector3(
+ graphicsbase[0]*meshScaling.getX(),
+ graphicsbase[1]*meshScaling.getY(),
+ graphicsbase[2]*meshScaling.getZ());
+ }
+ else
+ {
+ double* graphicsbase = (double*)(vertexbase+graphicsindex*stride);
+ triangleVerts[j] = btVector3( btScalar(graphicsbase[0]*meshScaling.getX()), btScalar(graphicsbase[1]*meshScaling.getY()), btScalar(graphicsbase[2]*meshScaling.getZ()));
+ }
+ }
+
+
+
+ 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(triangleVerts[0]);
+ aabbMax.setMax(triangleVerts[0]);
+ aabbMin.setMin(triangleVerts[1]);
+ aabbMax.setMax(triangleVerts[1]);
+ aabbMin.setMin(triangleVerts[2]);
+ aabbMax.setMax(triangleVerts[2]);
+
+ quantize(&curNode.m_quantizedAabbMin[0],aabbMin,0);
+ quantize(&curNode.m_quantizedAabbMax[0],aabbMax,1);
+
+ } else
+ {
+ //combine aabb from both children
+
+ btQuantizedBvhNode* leftChildNode = &m_quantizedContiguousNodes[i+1];
+
+ btQuantizedBvhNode* rightChildNode = leftChildNode->isLeafNode() ? &m_quantizedContiguousNodes[i+2] :
+ &m_quantizedContiguousNodes[i+1+leftChildNode->getEscapeIndex()];
+
+
+ {
+ for (int i=0;i<3;i++)
+ {
+ curNode.m_quantizedAabbMin[i] = leftChildNode->m_quantizedAabbMin[i];
+ if (curNode.m_quantizedAabbMin[i]>rightChildNode->m_quantizedAabbMin[i])
+ curNode.m_quantizedAabbMin[i]=rightChildNode->m_quantizedAabbMin[i];
+
+ curNode.m_quantizedAabbMax[i] = leftChildNode->m_quantizedAabbMax[i];
+ if (curNode.m_quantizedAabbMax[i] < rightChildNode->m_quantizedAabbMax[i])
+ curNode.m_quantizedAabbMax[i] = rightChildNode->m_quantizedAabbMax[i];
+ }
+ }
+ }
+
+ }
+
+ if (curNodeSubPart >= 0)
+ meshInterface->unLockReadOnlyVertexBase(curNodeSubPart);
+
+
+}
+
+///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place'
+btOptimizedBvh* btOptimizedBvh::deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian)
+{
+ btQuantizedBvh* bvh = btQuantizedBvh::deSerializeInPlace(i_alignedDataBuffer,i_dataBufferSize,i_swapEndian);
+
+ //we don't add additional data so just do a static upcast
+ return static_cast<btOptimizedBvh*>(bvh);
+}
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btOptimizedBvh.h b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btOptimizedBvh.h
new file mode 100644
index 0000000000..715961f552
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btOptimizedBvh.h
@@ -0,0 +1,65 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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.
+*/
+
+///Contains contributions from Disney Studio's
+
+#ifndef BT_OPTIMIZED_BVH_H
+#define BT_OPTIMIZED_BVH_H
+
+#include "BulletCollision/BroadphaseCollision/btQuantizedBvh.h"
+
+class btStridingMeshInterface;
+
+
+///The btOptimizedBvh extends the btQuantizedBvh to create AABB tree for triangle meshes, through the btStridingMeshInterface.
+ATTRIBUTE_ALIGNED16(class) btOptimizedBvh : public btQuantizedBvh
+{
+
+public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+protected:
+
+public:
+
+ btOptimizedBvh();
+
+ virtual ~btOptimizedBvh();
+
+ void build(btStridingMeshInterface* triangles,bool useQuantizedAabbCompression, const btVector3& bvhAabbMin, const btVector3& bvhAabbMax);
+
+ void refit(btStridingMeshInterface* triangles,const btVector3& aabbMin,const btVector3& aabbMax);
+
+ void refitPartial(btStridingMeshInterface* triangles,const btVector3& aabbMin, const btVector3& aabbMax);
+
+ void updateBvhNodes(btStridingMeshInterface* meshInterface,int firstNode,int endNode,int index);
+
+ /// Data buffer MUST be 16 byte aligned
+ virtual bool serializeInPlace(void *o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian) const
+ {
+ return btQuantizedBvh::serialize(o_alignedDataBuffer,i_dataBufferSize,i_swapEndian);
+
+ }
+
+ ///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place'
+ static btOptimizedBvh *deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian);
+
+
+};
+
+
+#endif //BT_OPTIMIZED_BVH_H
+
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp
new file mode 100644
index 0000000000..4854f370f7
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp
@@ -0,0 +1,500 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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.
+*/
+#if defined (_WIN32) || defined (__i386__)
+#define BT_USE_SSE_IN_API
+#endif
+
+#include "BulletCollision/CollisionShapes/btPolyhedralConvexShape.h"
+#include "btConvexPolyhedron.h"
+#include "LinearMath/btConvexHullComputer.h"
+#include <new>
+#include "LinearMath/btGeometryUtil.h"
+#include "LinearMath/btGrahamScan2dConvexHull.h"
+
+
+btPolyhedralConvexShape::btPolyhedralConvexShape() :btConvexInternalShape(),
+m_polyhedron(0)
+{
+
+}
+
+btPolyhedralConvexShape::~btPolyhedralConvexShape()
+{
+ if (m_polyhedron)
+ {
+ m_polyhedron->~btConvexPolyhedron();
+ btAlignedFree(m_polyhedron);
+ }
+}
+
+
+bool btPolyhedralConvexShape::initializePolyhedralFeatures(int shiftVerticesByMargin)
+{
+
+ if (m_polyhedron)
+ {
+ m_polyhedron->~btConvexPolyhedron();
+ btAlignedFree(m_polyhedron);
+ }
+
+ void* mem = btAlignedAlloc(sizeof(btConvexPolyhedron),16);
+ m_polyhedron = new (mem) btConvexPolyhedron;
+
+ btAlignedObjectArray<btVector3> orgVertices;
+
+ for (int i=0;i<getNumVertices();i++)
+ {
+ btVector3& newVertex = orgVertices.expand();
+ getVertex(i,newVertex);
+ }
+
+ btConvexHullComputer conv;
+
+ if (shiftVerticesByMargin)
+ {
+ btAlignedObjectArray<btVector3> planeEquations;
+ btGeometryUtil::getPlaneEquationsFromVertices(orgVertices,planeEquations);
+
+ btAlignedObjectArray<btVector3> shiftedPlaneEquations;
+ for (int p=0;p<planeEquations.size();p++)
+ {
+ btVector3 plane = planeEquations[p];
+ // btScalar margin = getMargin();
+ plane[3] -= getMargin();
+ shiftedPlaneEquations.push_back(plane);
+ }
+
+ btAlignedObjectArray<btVector3> tmpVertices;
+
+ btGeometryUtil::getVerticesFromPlaneEquations(shiftedPlaneEquations,tmpVertices);
+
+ conv.compute(&tmpVertices[0].getX(), sizeof(btVector3),tmpVertices.size(),0.f,0.f);
+ } else
+ {
+
+ conv.compute(&orgVertices[0].getX(), sizeof(btVector3),orgVertices.size(),0.f,0.f);
+ }
+
+
+
+ btAlignedObjectArray<btVector3> faceNormals;
+ int numFaces = conv.faces.size();
+ faceNormals.resize(numFaces);
+ btConvexHullComputer* convexUtil = &conv;
+
+
+ btAlignedObjectArray<btFace> tmpFaces;
+ tmpFaces.resize(numFaces);
+
+ int numVertices = convexUtil->vertices.size();
+ m_polyhedron->m_vertices.resize(numVertices);
+ for (int p=0;p<numVertices;p++)
+ {
+ m_polyhedron->m_vertices[p] = convexUtil->vertices[p];
+ }
+
+
+ for (int i=0;i<numFaces;i++)
+ {
+ int face = convexUtil->faces[i];
+ //printf("face=%d\n",face);
+ const btConvexHullComputer::Edge* firstEdge = &convexUtil->edges[face];
+ const btConvexHullComputer::Edge* edge = firstEdge;
+
+ btVector3 edges[3];
+ int numEdges = 0;
+ //compute face normals
+
+ do
+ {
+
+ int src = edge->getSourceVertex();
+ tmpFaces[i].m_indices.push_back(src);
+ int targ = edge->getTargetVertex();
+ btVector3 wa = convexUtil->vertices[src];
+
+ btVector3 wb = convexUtil->vertices[targ];
+ btVector3 newEdge = wb-wa;
+ newEdge.normalize();
+ if (numEdges<2)
+ edges[numEdges++] = newEdge;
+
+ edge = edge->getNextEdgeOfFace();
+ } while (edge!=firstEdge);
+
+ btScalar planeEq = 1e30f;
+
+
+ if (numEdges==2)
+ {
+ faceNormals[i] = edges[0].cross(edges[1]);
+ faceNormals[i].normalize();
+ tmpFaces[i].m_plane[0] = faceNormals[i].getX();
+ tmpFaces[i].m_plane[1] = faceNormals[i].getY();
+ tmpFaces[i].m_plane[2] = faceNormals[i].getZ();
+ tmpFaces[i].m_plane[3] = planeEq;
+
+ }
+ else
+ {
+ btAssert(0);//degenerate?
+ faceNormals[i].setZero();
+ }
+
+ for (int v=0;v<tmpFaces[i].m_indices.size();v++)
+ {
+ btScalar eq = m_polyhedron->m_vertices[tmpFaces[i].m_indices[v]].dot(faceNormals[i]);
+ if (planeEq>eq)
+ {
+ planeEq=eq;
+ }
+ }
+ tmpFaces[i].m_plane[3] = -planeEq;
+ }
+
+ //merge coplanar faces and copy them to m_polyhedron
+
+ btScalar faceWeldThreshold= 0.999f;
+ btAlignedObjectArray<int> todoFaces;
+ for (int i=0;i<tmpFaces.size();i++)
+ todoFaces.push_back(i);
+
+ while (todoFaces.size())
+ {
+ btAlignedObjectArray<int> coplanarFaceGroup;
+ int refFace = todoFaces[todoFaces.size()-1];
+
+ coplanarFaceGroup.push_back(refFace);
+ btFace& faceA = tmpFaces[refFace];
+ todoFaces.pop_back();
+
+ btVector3 faceNormalA(faceA.m_plane[0],faceA.m_plane[1],faceA.m_plane[2]);
+ for (int j=todoFaces.size()-1;j>=0;j--)
+ {
+ int i = todoFaces[j];
+ btFace& faceB = tmpFaces[i];
+ btVector3 faceNormalB(faceB.m_plane[0],faceB.m_plane[1],faceB.m_plane[2]);
+ if (faceNormalA.dot(faceNormalB)>faceWeldThreshold)
+ {
+ coplanarFaceGroup.push_back(i);
+ todoFaces.remove(i);
+ }
+ }
+
+
+ bool did_merge = false;
+ if (coplanarFaceGroup.size()>1)
+ {
+ //do the merge: use Graham Scan 2d convex hull
+
+ btAlignedObjectArray<GrahamVector3> orgpoints;
+ btVector3 averageFaceNormal(0,0,0);
+
+ for (int i=0;i<coplanarFaceGroup.size();i++)
+ {
+// m_polyhedron->m_faces.push_back(tmpFaces[coplanarFaceGroup[i]]);
+
+ btFace& face = tmpFaces[coplanarFaceGroup[i]];
+ btVector3 faceNormal(face.m_plane[0],face.m_plane[1],face.m_plane[2]);
+ averageFaceNormal+=faceNormal;
+ for (int f=0;f<face.m_indices.size();f++)
+ {
+ int orgIndex = face.m_indices[f];
+ btVector3 pt = m_polyhedron->m_vertices[orgIndex];
+
+ bool found = false;
+
+ for (int i=0;i<orgpoints.size();i++)
+ {
+ //if ((orgpoints[i].m_orgIndex == orgIndex) || ((rotatedPt-orgpoints[i]).length2()<0.0001))
+ if (orgpoints[i].m_orgIndex == orgIndex)
+ {
+ found=true;
+ break;
+ }
+ }
+ if (!found)
+ orgpoints.push_back(GrahamVector3(pt,orgIndex));
+ }
+ }
+
+
+
+ btFace combinedFace;
+ for (int i=0;i<4;i++)
+ combinedFace.m_plane[i] = tmpFaces[coplanarFaceGroup[0]].m_plane[i];
+
+ btAlignedObjectArray<GrahamVector3> hull;
+
+ averageFaceNormal.normalize();
+ GrahamScanConvexHull2D(orgpoints,hull,averageFaceNormal);
+
+ for (int i=0;i<hull.size();i++)
+ {
+ combinedFace.m_indices.push_back(hull[i].m_orgIndex);
+ for(int k = 0; k < orgpoints.size(); k++)
+ {
+ if(orgpoints[k].m_orgIndex == hull[i].m_orgIndex)
+ {
+ orgpoints[k].m_orgIndex = -1; // invalidate...
+ break;
+ }
+ }
+ }
+
+ // are there rejected vertices?
+ bool reject_merge = false;
+
+
+
+ for(int i = 0; i < orgpoints.size(); i++) {
+ if(orgpoints[i].m_orgIndex == -1)
+ continue; // this is in the hull...
+ // this vertex is rejected -- is anybody else using this vertex?
+ for(int j = 0; j < tmpFaces.size(); j++) {
+
+ btFace& face = tmpFaces[j];
+ // is this a face of the current coplanar group?
+ bool is_in_current_group = false;
+ for(int k = 0; k < coplanarFaceGroup.size(); k++) {
+ if(coplanarFaceGroup[k] == j) {
+ is_in_current_group = true;
+ break;
+ }
+ }
+ if(is_in_current_group) // ignore this face...
+ continue;
+ // does this face use this rejected vertex?
+ for(int v = 0; v < face.m_indices.size(); v++) {
+ if(face.m_indices[v] == orgpoints[i].m_orgIndex) {
+ // this rejected vertex is used in another face -- reject merge
+ reject_merge = true;
+ break;
+ }
+ }
+ if(reject_merge)
+ break;
+ }
+ if(reject_merge)
+ break;
+ }
+
+ if (!reject_merge)
+ {
+ // do this merge!
+ did_merge = true;
+ m_polyhedron->m_faces.push_back(combinedFace);
+ }
+ }
+ if(!did_merge)
+ {
+ for (int i=0;i<coplanarFaceGroup.size();i++)
+ {
+ btFace face = tmpFaces[coplanarFaceGroup[i]];
+ m_polyhedron->m_faces.push_back(face);
+ }
+
+ }
+
+
+
+ }
+
+ m_polyhedron->initialize();
+
+ return true;
+}
+
+#ifndef MIN
+ #define MIN(_a, _b) ((_a) < (_b) ? (_a) : (_b))
+#endif
+
+btVector3 btPolyhedralConvexShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0)const
+{
+
+
+ btVector3 supVec(0,0,0);
+#ifndef __SPU__
+ int i;
+ btScalar maxDot(btScalar(-BT_LARGE_FLOAT));
+
+ btVector3 vec = vec0;
+ btScalar lenSqr = vec.length2();
+ if (lenSqr < btScalar(0.0001))
+ {
+ vec.setValue(1,0,0);
+ } else
+ {
+ btScalar rlen = btScalar(1.) / btSqrt(lenSqr );
+ vec *= rlen;
+ }
+
+ btVector3 vtx;
+ btScalar newDot;
+
+ for( int k = 0; k < getNumVertices(); k += 128 )
+ {
+ btVector3 temp[128];
+ int inner_count = MIN(getNumVertices() - k, 128);
+ for( i = 0; i < inner_count; i++ )
+ getVertex(i,temp[i]);
+ i = (int) vec.maxDot( temp, inner_count, newDot);
+ if (newDot > maxDot)
+ {
+ maxDot = newDot;
+ supVec = temp[i];
+ }
+ }
+
+#endif //__SPU__
+ return supVec;
+}
+
+
+
+void btPolyhedralConvexShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+{
+#ifndef __SPU__
+ int i;
+
+ btVector3 vtx;
+ btScalar newDot;
+
+ for (i=0;i<numVectors;i++)
+ {
+ supportVerticesOut[i][3] = btScalar(-BT_LARGE_FLOAT);
+ }
+
+ for (int j=0;j<numVectors;j++)
+ {
+ const btVector3& vec = vectors[j];
+
+ for( int k = 0; k < getNumVertices(); k += 128 )
+ {
+ btVector3 temp[128];
+ int inner_count = MIN(getNumVertices() - k, 128);
+ for( i = 0; i < inner_count; i++ )
+ getVertex(i,temp[i]);
+ i = (int) vec.maxDot( temp, inner_count, newDot);
+ if (newDot > supportVerticesOut[j][3])
+ {
+ supportVerticesOut[j] = temp[i];
+ supportVerticesOut[j][3] = newDot;
+ }
+ }
+ }
+
+#endif //__SPU__
+}
+
+
+
+void btPolyhedralConvexShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+{
+#ifndef __SPU__
+ //not yet, return box inertia
+
+ btScalar margin = getMargin();
+
+ btTransform ident;
+ ident.setIdentity();
+ btVector3 aabbMin,aabbMax;
+ getAabb(ident,aabbMin,aabbMax);
+ btVector3 halfExtents = (aabbMax-aabbMin)*btScalar(0.5);
+
+ btScalar lx=btScalar(2.)*(halfExtents.x()+margin);
+ btScalar ly=btScalar(2.)*(halfExtents.y()+margin);
+ btScalar lz=btScalar(2.)*(halfExtents.z()+margin);
+ const btScalar x2 = lx*lx;
+ const btScalar y2 = ly*ly;
+ const btScalar z2 = lz*lz;
+ const btScalar scaledmass = mass * btScalar(0.08333333);
+
+ inertia = scaledmass * (btVector3(y2+z2,x2+z2,x2+y2));
+#endif //__SPU__
+}
+
+
+
+void btPolyhedralConvexAabbCachingShape::setLocalScaling(const btVector3& scaling)
+{
+ btConvexInternalShape::setLocalScaling(scaling);
+ recalcLocalAabb();
+}
+
+btPolyhedralConvexAabbCachingShape::btPolyhedralConvexAabbCachingShape()
+:btPolyhedralConvexShape(),
+m_localAabbMin(1,1,1),
+m_localAabbMax(-1,-1,-1),
+m_isLocalAabbValid(false)
+{
+}
+
+void btPolyhedralConvexAabbCachingShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const
+{
+ getNonvirtualAabb(trans,aabbMin,aabbMax,getMargin());
+}
+
+void btPolyhedralConvexAabbCachingShape::recalcLocalAabb()
+{
+ m_isLocalAabbValid = true;
+
+ #if 1
+ static const btVector3 _directions[] =
+ {
+ btVector3( 1., 0., 0.),
+ btVector3( 0., 1., 0.),
+ btVector3( 0., 0., 1.),
+ btVector3( -1., 0., 0.),
+ btVector3( 0., -1., 0.),
+ btVector3( 0., 0., -1.)
+ };
+
+ btVector3 _supporting[] =
+ {
+ btVector3( 0., 0., 0.),
+ btVector3( 0., 0., 0.),
+ btVector3( 0., 0., 0.),
+ btVector3( 0., 0., 0.),
+ btVector3( 0., 0., 0.),
+ btVector3( 0., 0., 0.)
+ };
+
+ batchedUnitVectorGetSupportingVertexWithoutMargin(_directions, _supporting, 6);
+
+ for ( int i = 0; i < 3; ++i )
+ {
+ m_localAabbMax[i] = _supporting[i][i] + m_collisionMargin;
+ m_localAabbMin[i] = _supporting[i + 3][i] - m_collisionMargin;
+ }
+
+ #else
+
+ for (int i=0;i<3;i++)
+ {
+ btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.));
+ vec[i] = btScalar(1.);
+ btVector3 tmp = localGetSupportingVertex(vec);
+ m_localAabbMax[i] = tmp[i];
+ vec[i] = btScalar(-1.);
+ tmp = localGetSupportingVertex(vec);
+ m_localAabbMin[i] = tmp[i];
+ }
+ #endif
+}
+
+
+
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h
new file mode 100644
index 0000000000..7bf8e01c1f
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h
@@ -0,0 +1,118 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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_POLYHEDRAL_CONVEX_SHAPE_H
+#define BT_POLYHEDRAL_CONVEX_SHAPE_H
+
+#include "LinearMath/btMatrix3x3.h"
+#include "btConvexInternalShape.h"
+class btConvexPolyhedron;
+
+
+///The btPolyhedralConvexShape is an internal interface class for polyhedral convex shapes.
+ATTRIBUTE_ALIGNED16(class) btPolyhedralConvexShape : public btConvexInternalShape
+{
+
+
+protected:
+
+ btConvexPolyhedron* m_polyhedron;
+
+public:
+
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+
+ btPolyhedralConvexShape();
+
+ virtual ~btPolyhedralConvexShape();
+
+ ///optional method mainly used to generate multiple contact points by clipping polyhedral features (faces/edges)
+ ///experimental/work-in-progress
+ virtual bool initializePolyhedralFeatures(int shiftVerticesByMargin=0);
+
+ const btConvexPolyhedron* getConvexPolyhedron() const
+ {
+ return m_polyhedron;
+ }
+
+ //brute force implementations
+
+ virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
+ virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
+
+ virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+
+
+ virtual int getNumVertices() const = 0 ;
+ virtual int getNumEdges() const = 0;
+ virtual void getEdge(int i,btVector3& pa,btVector3& pb) const = 0;
+ virtual void getVertex(int i,btVector3& vtx) const = 0;
+ virtual int getNumPlanes() const = 0;
+ virtual void getPlane(btVector3& planeNormal,btVector3& planeSupport,int i ) const = 0;
+// virtual int getIndex(int i) const = 0 ;
+
+ virtual bool isInside(const btVector3& pt,btScalar tolerance) const = 0;
+
+};
+
+
+///The btPolyhedralConvexAabbCachingShape adds aabb caching to the btPolyhedralConvexShape
+class btPolyhedralConvexAabbCachingShape : public btPolyhedralConvexShape
+{
+
+ btVector3 m_localAabbMin;
+ btVector3 m_localAabbMax;
+ bool m_isLocalAabbValid;
+
+protected:
+
+ void setCachedLocalAabb (const btVector3& aabbMin, const btVector3& aabbMax)
+ {
+ m_isLocalAabbValid = true;
+ m_localAabbMin = aabbMin;
+ m_localAabbMax = aabbMax;
+ }
+
+ inline void getCachedLocalAabb (btVector3& aabbMin, btVector3& aabbMax) const
+ {
+ btAssert(m_isLocalAabbValid);
+ aabbMin = m_localAabbMin;
+ aabbMax = m_localAabbMax;
+ }
+
+protected:
+
+ btPolyhedralConvexAabbCachingShape();
+
+public:
+
+ inline void getNonvirtualAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax, btScalar margin) const
+ {
+
+ //lazy evaluation of local aabb
+ btAssert(m_isLocalAabbValid);
+ btTransformAabb(m_localAabbMin,m_localAabbMax,margin,trans,aabbMin,aabbMax);
+ }
+
+ virtual void setLocalScaling(const btVector3& scaling);
+
+ virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+
+ void recalcLocalAabb();
+
+};
+
+#endif //BT_POLYHEDRAL_CONVEX_SHAPE_H
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp
new file mode 100644
index 0000000000..6a337c786c
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp
@@ -0,0 +1,121 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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 "btScaledBvhTriangleMeshShape.h"
+
+btScaledBvhTriangleMeshShape::btScaledBvhTriangleMeshShape(btBvhTriangleMeshShape* childShape,const btVector3& localScaling)
+:m_localScaling(localScaling),m_bvhTriMeshShape(childShape)
+{
+ m_shapeType = SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE;
+}
+
+btScaledBvhTriangleMeshShape::~btScaledBvhTriangleMeshShape()
+{
+}
+
+
+class btScaledTriangleCallback : public btTriangleCallback
+{
+ btTriangleCallback* m_originalCallback;
+
+ btVector3 m_localScaling;
+
+public:
+
+ btScaledTriangleCallback(btTriangleCallback* originalCallback,const btVector3& localScaling)
+ :m_originalCallback(originalCallback),
+ m_localScaling(localScaling)
+ {
+ }
+
+ virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
+ {
+ btVector3 newTriangle[3];
+ newTriangle[0] = triangle[0]*m_localScaling;
+ newTriangle[1] = triangle[1]*m_localScaling;
+ newTriangle[2] = triangle[2]*m_localScaling;
+ m_originalCallback->processTriangle(&newTriangle[0],partId,triangleIndex);
+ }
+};
+
+void btScaledBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
+{
+ btScaledTriangleCallback scaledCallback(callback,m_localScaling);
+
+ btVector3 invLocalScaling(1.f/m_localScaling.getX(),1.f/m_localScaling.getY(),1.f/m_localScaling.getZ());
+ btVector3 scaledAabbMin,scaledAabbMax;
+
+ ///support negative scaling
+ scaledAabbMin[0] = m_localScaling.getX() >= 0. ? aabbMin[0] * invLocalScaling[0] : aabbMax[0] * invLocalScaling[0];
+ scaledAabbMin[1] = m_localScaling.getY() >= 0. ? aabbMin[1] * invLocalScaling[1] : aabbMax[1] * invLocalScaling[1];
+ scaledAabbMin[2] = m_localScaling.getZ() >= 0. ? aabbMin[2] * invLocalScaling[2] : aabbMax[2] * invLocalScaling[2];
+ scaledAabbMin[3] = 0.f;
+
+ scaledAabbMax[0] = m_localScaling.getX() <= 0. ? aabbMin[0] * invLocalScaling[0] : aabbMax[0] * invLocalScaling[0];
+ scaledAabbMax[1] = m_localScaling.getY() <= 0. ? aabbMin[1] * invLocalScaling[1] : aabbMax[1] * invLocalScaling[1];
+ scaledAabbMax[2] = m_localScaling.getZ() <= 0. ? aabbMin[2] * invLocalScaling[2] : aabbMax[2] * invLocalScaling[2];
+ scaledAabbMax[3] = 0.f;
+
+
+ m_bvhTriMeshShape->processAllTriangles(&scaledCallback,scaledAabbMin,scaledAabbMax);
+}
+
+
+void btScaledBvhTriangleMeshShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const
+{
+ btVector3 localAabbMin = m_bvhTriMeshShape->getLocalAabbMin();
+ btVector3 localAabbMax = m_bvhTriMeshShape->getLocalAabbMax();
+
+ btVector3 tmpLocalAabbMin = localAabbMin * m_localScaling;
+ btVector3 tmpLocalAabbMax = localAabbMax * m_localScaling;
+
+ localAabbMin[0] = (m_localScaling.getX() >= 0.) ? tmpLocalAabbMin[0] : tmpLocalAabbMax[0];
+ localAabbMin[1] = (m_localScaling.getY() >= 0.) ? tmpLocalAabbMin[1] : tmpLocalAabbMax[1];
+ localAabbMin[2] = (m_localScaling.getZ() >= 0.) ? tmpLocalAabbMin[2] : tmpLocalAabbMax[2];
+ localAabbMax[0] = (m_localScaling.getX() <= 0.) ? tmpLocalAabbMin[0] : tmpLocalAabbMax[0];
+ localAabbMax[1] = (m_localScaling.getY() <= 0.) ? tmpLocalAabbMin[1] : tmpLocalAabbMax[1];
+ localAabbMax[2] = (m_localScaling.getZ() <= 0.) ? tmpLocalAabbMin[2] : tmpLocalAabbMax[2];
+
+ btVector3 localHalfExtents = btScalar(0.5)*(localAabbMax-localAabbMin);
+ btScalar margin = m_bvhTriMeshShape->getMargin();
+ localHalfExtents += btVector3(margin,margin,margin);
+ btVector3 localCenter = btScalar(0.5)*(localAabbMax+localAabbMin);
+
+ btMatrix3x3 abs_b = trans.getBasis().absolute();
+
+ btVector3 center = trans(localCenter);
+
+ btVector3 extent = localHalfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
+ aabbMin = center - extent;
+ aabbMax = center + extent;
+
+}
+
+void btScaledBvhTriangleMeshShape::setLocalScaling(const btVector3& scaling)
+{
+ m_localScaling = scaling;
+}
+
+const btVector3& btScaledBvhTriangleMeshShape::getLocalScaling() const
+{
+ return m_localScaling;
+}
+
+void btScaledBvhTriangleMeshShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+{
+ ///don't make this a movable object!
+// btAssert(0);
+}
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h
new file mode 100644
index 0000000000..39049eaf08
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h
@@ -0,0 +1,95 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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_SCALED_BVH_TRIANGLE_MESH_SHAPE_H
+#define BT_SCALED_BVH_TRIANGLE_MESH_SHAPE_H
+
+#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h"
+
+
+///The btScaledBvhTriangleMeshShape allows to instance a scaled version of an existing btBvhTriangleMeshShape.
+///Note that each btBvhTriangleMeshShape still can have its own local scaling, independent from this btScaledBvhTriangleMeshShape 'localScaling'
+ATTRIBUTE_ALIGNED16(class) btScaledBvhTriangleMeshShape : public btConcaveShape
+{
+
+
+ btVector3 m_localScaling;
+
+ btBvhTriangleMeshShape* m_bvhTriMeshShape;
+
+public:
+
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+
+ btScaledBvhTriangleMeshShape(btBvhTriangleMeshShape* childShape,const btVector3& localScaling);
+
+ virtual ~btScaledBvhTriangleMeshShape();
+
+
+ virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+ virtual void setLocalScaling(const btVector3& scaling);
+ virtual const btVector3& getLocalScaling() const;
+ virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+
+ virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
+
+ btBvhTriangleMeshShape* getChildShape()
+ {
+ return m_bvhTriMeshShape;
+ }
+
+ const btBvhTriangleMeshShape* getChildShape() const
+ {
+ return m_bvhTriMeshShape;
+ }
+
+ //debugging
+ virtual const char* getName()const {return "SCALEDBVHTRIANGLEMESH";}
+
+ virtual int calculateSerializeBufferSize() const;
+
+ ///fills the dataBuffer and returns the struct name (and 0 on failure)
+ virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
+
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btScaledTriangleMeshShapeData
+{
+ btTriangleMeshShapeData m_trimeshShapeData;
+
+ btVector3FloatData m_localScaling;
+};
+
+
+SIMD_FORCE_INLINE int btScaledBvhTriangleMeshShape::calculateSerializeBufferSize() const
+{
+ return sizeof(btScaledTriangleMeshShapeData);
+}
+
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+SIMD_FORCE_INLINE const char* btScaledBvhTriangleMeshShape::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+ btScaledTriangleMeshShapeData* scaledMeshData = (btScaledTriangleMeshShapeData*) dataBuffer;
+ m_bvhTriMeshShape->serialize(&scaledMeshData->m_trimeshShapeData,serializer);
+ scaledMeshData->m_trimeshShapeData.m_collisionShapeData.m_shapeType = SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE;
+ m_localScaling.serializeFloat(scaledMeshData->m_localScaling);
+ return "btScaledTriangleMeshShapeData";
+}
+
+
+#endif //BT_SCALED_BVH_TRIANGLE_MESH_SHAPE_H
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btShapeHull.cpp b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btShapeHull.cpp
new file mode 100644
index 0000000000..3beaf86580
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btShapeHull.cpp
@@ -0,0 +1,170 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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.
+*/
+
+//btShapeHull was implemented by John McCutchan.
+
+
+#include "btShapeHull.h"
+#include "LinearMath/btConvexHull.h"
+
+#define NUM_UNITSPHERE_POINTS 42
+
+btShapeHull::btShapeHull (const btConvexShape* shape)
+{
+ m_shape = shape;
+ m_vertices.clear ();
+ m_indices.clear();
+ m_numIndices = 0;
+}
+
+btShapeHull::~btShapeHull ()
+{
+ m_indices.clear();
+ m_vertices.clear ();
+}
+
+bool
+btShapeHull::buildHull (btScalar /*margin*/)
+{
+ int numSampleDirections = NUM_UNITSPHERE_POINTS;
+ {
+ int numPDA = m_shape->getNumPreferredPenetrationDirections();
+ if (numPDA)
+ {
+ for (int i=0;i<numPDA;i++)
+ {
+ btVector3 norm;
+ m_shape->getPreferredPenetrationDirection(i,norm);
+ getUnitSpherePoints()[numSampleDirections] = norm;
+ numSampleDirections++;
+ }
+ }
+ }
+
+ btVector3 supportPoints[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2];
+ int i;
+ for (i = 0; i < numSampleDirections; i++)
+ {
+ supportPoints[i] = m_shape->localGetSupportingVertex(getUnitSpherePoints()[i]);
+ }
+
+ HullDesc hd;
+ hd.mFlags = QF_TRIANGLES;
+ hd.mVcount = static_cast<unsigned int>(numSampleDirections);
+
+#ifdef BT_USE_DOUBLE_PRECISION
+ hd.mVertices = &supportPoints[0];
+ hd.mVertexStride = sizeof(btVector3);
+#else
+ hd.mVertices = &supportPoints[0];
+ hd.mVertexStride = sizeof (btVector3);
+#endif
+
+ HullLibrary hl;
+ HullResult hr;
+ if (hl.CreateConvexHull (hd, hr) == QE_FAIL)
+ {
+ return false;
+ }
+
+ m_vertices.resize (static_cast<int>(hr.mNumOutputVertices));
+
+
+ for (i = 0; i < static_cast<int>(hr.mNumOutputVertices); i++)
+ {
+ m_vertices[i] = hr.m_OutputVertices[i];
+ }
+ m_numIndices = hr.mNumIndices;
+ m_indices.resize(static_cast<int>(m_numIndices));
+ for (i = 0; i < static_cast<int>(m_numIndices); i++)
+ {
+ m_indices[i] = hr.m_Indices[i];
+ }
+
+ // free temporary hull result that we just copied
+ hl.ReleaseResult (hr);
+
+ return true;
+}
+
+int
+btShapeHull::numTriangles () const
+{
+ return static_cast<int>(m_numIndices / 3);
+}
+
+int
+btShapeHull::numVertices () const
+{
+ return m_vertices.size ();
+}
+
+int
+btShapeHull::numIndices () const
+{
+ return static_cast<int>(m_numIndices);
+}
+
+
+btVector3* btShapeHull::getUnitSpherePoints()
+{
+ static btVector3 sUnitSpherePoints[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2] =
+ {
+ btVector3(btScalar(0.000000) , btScalar(-0.000000),btScalar(-1.000000)),
+ btVector3(btScalar(0.723608) , btScalar(-0.525725),btScalar(-0.447219)),
+ btVector3(btScalar(-0.276388) , btScalar(-0.850649),btScalar(-0.447219)),
+ btVector3(btScalar(-0.894426) , btScalar(-0.000000),btScalar(-0.447216)),
+ btVector3(btScalar(-0.276388) , btScalar(0.850649),btScalar(-0.447220)),
+ btVector3(btScalar(0.723608) , btScalar(0.525725),btScalar(-0.447219)),
+ btVector3(btScalar(0.276388) , btScalar(-0.850649),btScalar(0.447220)),
+ btVector3(btScalar(-0.723608) , btScalar(-0.525725),btScalar(0.447219)),
+ btVector3(btScalar(-0.723608) , btScalar(0.525725),btScalar(0.447219)),
+ btVector3(btScalar(0.276388) , btScalar(0.850649),btScalar(0.447219)),
+ btVector3(btScalar(0.894426) , btScalar(0.000000),btScalar(0.447216)),
+ btVector3(btScalar(-0.000000) , btScalar(0.000000),btScalar(1.000000)),
+ btVector3(btScalar(0.425323) , btScalar(-0.309011),btScalar(-0.850654)),
+ btVector3(btScalar(-0.162456) , btScalar(-0.499995),btScalar(-0.850654)),
+ btVector3(btScalar(0.262869) , btScalar(-0.809012),btScalar(-0.525738)),
+ btVector3(btScalar(0.425323) , btScalar(0.309011),btScalar(-0.850654)),
+ btVector3(btScalar(0.850648) , btScalar(-0.000000),btScalar(-0.525736)),
+ btVector3(btScalar(-0.525730) , btScalar(-0.000000),btScalar(-0.850652)),
+ btVector3(btScalar(-0.688190) , btScalar(-0.499997),btScalar(-0.525736)),
+ btVector3(btScalar(-0.162456) , btScalar(0.499995),btScalar(-0.850654)),
+ btVector3(btScalar(-0.688190) , btScalar(0.499997),btScalar(-0.525736)),
+ btVector3(btScalar(0.262869) , btScalar(0.809012),btScalar(-0.525738)),
+ btVector3(btScalar(0.951058) , btScalar(0.309013),btScalar(0.000000)),
+ btVector3(btScalar(0.951058) , btScalar(-0.309013),btScalar(0.000000)),
+ btVector3(btScalar(0.587786) , btScalar(-0.809017),btScalar(0.000000)),
+ btVector3(btScalar(0.000000) , btScalar(-1.000000),btScalar(0.000000)),
+ btVector3(btScalar(-0.587786) , btScalar(-0.809017),btScalar(0.000000)),
+ btVector3(btScalar(-0.951058) , btScalar(-0.309013),btScalar(-0.000000)),
+ btVector3(btScalar(-0.951058) , btScalar(0.309013),btScalar(-0.000000)),
+ btVector3(btScalar(-0.587786) , btScalar(0.809017),btScalar(-0.000000)),
+ btVector3(btScalar(-0.000000) , btScalar(1.000000),btScalar(-0.000000)),
+ btVector3(btScalar(0.587786) , btScalar(0.809017),btScalar(-0.000000)),
+ btVector3(btScalar(0.688190) , btScalar(-0.499997),btScalar(0.525736)),
+ btVector3(btScalar(-0.262869) , btScalar(-0.809012),btScalar(0.525738)),
+ btVector3(btScalar(-0.850648) , btScalar(0.000000),btScalar(0.525736)),
+ btVector3(btScalar(-0.262869) , btScalar(0.809012),btScalar(0.525738)),
+ btVector3(btScalar(0.688190) , btScalar(0.499997),btScalar(0.525736)),
+ btVector3(btScalar(0.525730) , btScalar(0.000000),btScalar(0.850652)),
+ btVector3(btScalar(0.162456) , btScalar(-0.499995),btScalar(0.850654)),
+ btVector3(btScalar(-0.425323) , btScalar(-0.309011),btScalar(0.850654)),
+ btVector3(btScalar(-0.425323) , btScalar(0.309011),btScalar(0.850654)),
+ btVector3(btScalar(0.162456) , btScalar(0.499995),btScalar(0.850654))
+ };
+ return sUnitSpherePoints;
+}
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btShapeHull.h b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btShapeHull.h
new file mode 100644
index 0000000000..e959f198b6
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btShapeHull.h
@@ -0,0 +1,61 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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.
+*/
+
+///btShapeHull implemented by John McCutchan.
+
+#ifndef BT_SHAPE_HULL_H
+#define BT_SHAPE_HULL_H
+
+#include "LinearMath/btAlignedObjectArray.h"
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+
+
+///The btShapeHull class takes a btConvexShape, builds a simplified convex hull using btConvexHull and provides triangle indices and vertices.
+///It can be useful for to simplify a complex convex object and for visualization of a non-polyhedral convex object.
+///It approximates the convex hull using the supporting vertex of 42 directions.
+ATTRIBUTE_ALIGNED16(class) btShapeHull
+{
+protected:
+
+ btAlignedObjectArray<btVector3> m_vertices;
+ btAlignedObjectArray<unsigned int> m_indices;
+ unsigned int m_numIndices;
+ const btConvexShape* m_shape;
+
+ static btVector3* getUnitSpherePoints();
+
+public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ btShapeHull (const btConvexShape* shape);
+ ~btShapeHull ();
+
+ bool buildHull (btScalar margin);
+
+ int numTriangles () const;
+ int numVertices () const;
+ int numIndices () const;
+
+ const btVector3* getVertexPointer() const
+ {
+ return &m_vertices[0];
+ }
+ const unsigned int* getIndexPointer() const
+ {
+ return &m_indices[0];
+ }
+};
+
+#endif //BT_SHAPE_HULL_H
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btSphereShape.cpp b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btSphereShape.cpp
new file mode 100644
index 0000000000..b9a736c0fd
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btSphereShape.cpp
@@ -0,0 +1,71 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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 "btSphereShape.h"
+#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
+
+#include "LinearMath/btQuaternion.h"
+
+btVector3 btSphereShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const
+{
+ (void)vec;
+ return btVector3(btScalar(0.),btScalar(0.),btScalar(0.));
+}
+
+void btSphereShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+{
+ (void)vectors;
+
+ for (int i=0;i<numVectors;i++)
+ {
+ supportVerticesOut[i].setValue(btScalar(0.),btScalar(0.),btScalar(0.));
+ }
+}
+
+
+btVector3 btSphereShape::localGetSupportingVertex(const btVector3& vec)const
+{
+ btVector3 supVertex;
+ supVertex = localGetSupportingVertexWithoutMargin(vec);
+
+ btVector3 vecnorm = vec;
+ if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON))
+ {
+ vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.));
+ }
+ vecnorm.normalize();
+ supVertex+= getMargin() * vecnorm;
+ return supVertex;
+}
+
+
+//broken due to scaling
+void btSphereShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+{
+ const btVector3& center = t.getOrigin();
+ btVector3 extent(getMargin(),getMargin(),getMargin());
+ aabbMin = center - extent;
+ aabbMax = center + extent;
+}
+
+
+
+void btSphereShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+{
+ btScalar elem = btScalar(0.4) * mass * getMargin()*getMargin();
+ inertia.setValue(elem,elem,elem);
+
+}
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btSphereShape.h b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btSphereShape.h
new file mode 100644
index 0000000000..50561f7f54
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btSphereShape.h
@@ -0,0 +1,76 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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_SPHERE_MINKOWSKI_H
+#define BT_SPHERE_MINKOWSKI_H
+
+#include "btConvexInternalShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
+
+///The btSphereShape implements an implicit sphere, centered around a local origin with radius.
+ATTRIBUTE_ALIGNED16(class) btSphereShape : public btConvexInternalShape
+
+{
+
+public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ btSphereShape (btScalar radius) : btConvexInternalShape ()
+ {
+ m_shapeType = SPHERE_SHAPE_PROXYTYPE;
+ m_localScaling.setValue(1.0, 1.0, 1.0);
+ m_implicitShapeDimensions.setZero();
+ m_implicitShapeDimensions.setX(radius);
+ m_collisionMargin = radius;
+ m_padding = 0;
+ }
+
+ virtual btVector3 localGetSupportingVertex(const btVector3& vec)const;
+ virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
+ //notice that the vectors should be unit length
+ virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
+
+
+ virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+
+ virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+
+
+ btScalar getRadius() const { return m_implicitShapeDimensions.getX() * m_localScaling.getX();}
+
+ void setUnscaledRadius(btScalar radius)
+ {
+ m_implicitShapeDimensions.setX(radius);
+ btConvexInternalShape::setMargin(radius);
+ }
+
+ //debugging
+ virtual const char* getName()const {return "SPHERE";}
+
+ virtual void setMargin(btScalar margin)
+ {
+ btConvexInternalShape::setMargin(margin);
+ }
+ virtual btScalar getMargin() const
+ {
+ //to improve gjk behaviour, use radius+margin as the full margin, so never get into the penetration case
+ //this means, non-uniform scaling is not supported anymore
+ return getRadius();
+ }
+
+
+};
+
+
+#endif //BT_SPHERE_MINKOWSKI_H
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btStaticPlaneShape.cpp b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btStaticPlaneShape.cpp
new file mode 100644
index 0000000000..d17141e3f2
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btStaticPlaneShape.cpp
@@ -0,0 +1,107 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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 "btStaticPlaneShape.h"
+
+#include "LinearMath/btTransformUtil.h"
+
+
+btStaticPlaneShape::btStaticPlaneShape(const btVector3& planeNormal,btScalar planeConstant)
+: btConcaveShape (), m_planeNormal(planeNormal.normalized()),
+m_planeConstant(planeConstant),
+m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.))
+{
+ m_shapeType = STATIC_PLANE_PROXYTYPE;
+ // btAssert( btFuzzyZero(m_planeNormal.length() - btScalar(1.)) );
+}
+
+
+btStaticPlaneShape::~btStaticPlaneShape()
+{
+}
+
+
+
+void btStaticPlaneShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+{
+ (void)t;
+ /*
+ btVector3 infvec (btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
+
+ btVector3 center = m_planeNormal*m_planeConstant;
+ aabbMin = center + infvec*m_planeNormal;
+ aabbMax = aabbMin;
+ aabbMin.setMin(center - infvec*m_planeNormal);
+ aabbMax.setMax(center - infvec*m_planeNormal);
+ */
+
+ 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));
+
+}
+
+
+
+
+void btStaticPlaneShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
+{
+
+ btVector3 halfExtents = (aabbMax - aabbMin) * btScalar(0.5);
+ btScalar radius = halfExtents.length();
+ btVector3 center = (aabbMax + aabbMin) * btScalar(0.5);
+
+ //this is where the triangles are generated, given AABB and plane equation (normal/constant)
+
+ btVector3 tangentDir0,tangentDir1;
+
+ //tangentDir0/tangentDir1 can be precalculated
+ btPlaneSpace1(m_planeNormal,tangentDir0,tangentDir1);
+
+ btVector3 supVertex0,supVertex1;
+
+ btVector3 projectedCenter = center - (m_planeNormal.dot(center) - m_planeConstant)*m_planeNormal;
+
+ btVector3 triangle[3];
+ triangle[0] = projectedCenter + tangentDir0*radius + tangentDir1*radius;
+ triangle[1] = projectedCenter + tangentDir0*radius - tangentDir1*radius;
+ triangle[2] = projectedCenter - tangentDir0*radius - tangentDir1*radius;
+
+ callback->processTriangle(triangle,0,0);
+
+ triangle[0] = projectedCenter - tangentDir0*radius - tangentDir1*radius;
+ triangle[1] = projectedCenter - tangentDir0*radius + tangentDir1*radius;
+ triangle[2] = projectedCenter + tangentDir0*radius + tangentDir1*radius;
+
+ callback->processTriangle(triangle,0,1);
+
+}
+
+void btStaticPlaneShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+{
+ (void)mass;
+
+ //moving concave objects not supported
+
+ inertia.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
+}
+
+void btStaticPlaneShape::setLocalScaling(const btVector3& scaling)
+{
+ m_localScaling = scaling;
+}
+const btVector3& btStaticPlaneShape::getLocalScaling() const
+{
+ return m_localScaling;
+}
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btStaticPlaneShape.h b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btStaticPlaneShape.h
new file mode 100644
index 0000000000..5e9eccc77d
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btStaticPlaneShape.h
@@ -0,0 +1,111 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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_STATIC_PLANE_SHAPE_H
+#define BT_STATIC_PLANE_SHAPE_H
+
+#include "btConcaveShape.h"
+
+
+///The btStaticPlaneShape simulates an infinite non-moving (static) collision plane.
+ATTRIBUTE_ALIGNED16(class) btStaticPlaneShape : public btConcaveShape
+{
+protected:
+ btVector3 m_localAabbMin;
+ btVector3 m_localAabbMax;
+
+ btVector3 m_planeNormal;
+ btScalar m_planeConstant;
+ btVector3 m_localScaling;
+
+public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ btStaticPlaneShape(const btVector3& planeNormal,btScalar planeConstant);
+
+ virtual ~btStaticPlaneShape();
+
+
+ virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+
+ virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
+
+ virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+
+ virtual void setLocalScaling(const btVector3& scaling);
+ virtual const btVector3& getLocalScaling() const;
+
+ const btVector3& getPlaneNormal() const
+ {
+ return m_planeNormal;
+ }
+
+ const btScalar& getPlaneConstant() const
+ {
+ return m_planeConstant;
+ }
+
+ //debugging
+ virtual const char* getName()const {return "STATICPLANE";}
+
+ virtual int calculateSerializeBufferSize() const;
+
+ ///fills the dataBuffer and returns the struct name (and 0 on failure)
+ virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
+
+
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btStaticPlaneShapeData
+{
+ btCollisionShapeData m_collisionShapeData;
+
+ btVector3FloatData m_localScaling;
+ btVector3FloatData m_planeNormal;
+ float m_planeConstant;
+ char m_pad[4];
+};
+
+
+SIMD_FORCE_INLINE int btStaticPlaneShape::calculateSerializeBufferSize() const
+{
+ return sizeof(btStaticPlaneShapeData);
+}
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+SIMD_FORCE_INLINE const char* btStaticPlaneShape::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+ btStaticPlaneShapeData* planeData = (btStaticPlaneShapeData*) dataBuffer;
+ btCollisionShape::serialize(&planeData->m_collisionShapeData,serializer);
+
+ m_localScaling.serializeFloat(planeData->m_localScaling);
+ m_planeNormal.serializeFloat(planeData->m_planeNormal);
+ planeData->m_planeConstant = float(m_planeConstant);
+
+ // Fill padding with zeros to appease msan.
+ planeData->m_pad[0] = 0;
+ planeData->m_pad[1] = 0;
+ planeData->m_pad[2] = 0;
+ planeData->m_pad[3] = 0;
+
+ return "btStaticPlaneShapeData";
+}
+
+
+#endif //BT_STATIC_PLANE_SHAPE_H
+
+
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp
new file mode 100644
index 0000000000..78ddeb3704
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp
@@ -0,0 +1,388 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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 "btStridingMeshInterface.h"
+#include "LinearMath/btSerializer.h"
+
+btStridingMeshInterface::~btStridingMeshInterface()
+{
+
+}
+
+
+void btStridingMeshInterface::InternalProcessAllTriangles(btInternalTriangleIndexCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
+{
+ (void)aabbMin;
+ (void)aabbMax;
+ int numtotalphysicsverts = 0;
+ int part,graphicssubparts = getNumSubParts();
+ const unsigned char * vertexbase;
+ const unsigned char * indexbase;
+ int indexstride;
+ PHY_ScalarType type;
+ PHY_ScalarType gfxindextype;
+ int stride,numverts,numtriangles;
+ int gfxindex;
+ btVector3 triangle[3];
+
+ btVector3 meshScaling = getScaling();
+
+ ///if the number of parts is big, the performance might drop due to the innerloop switch on indextype
+ for (part=0;part<graphicssubparts ;part++)
+ {
+ getLockedReadOnlyVertexIndexBase(&vertexbase,numverts,type,stride,&indexbase,indexstride,numtriangles,gfxindextype,part);
+ numtotalphysicsverts+=numtriangles*3; //upper bound
+
+ ///unlike that developers want to pass in double-precision meshes in single-precision Bullet build
+ ///so disable this feature by default
+ ///see patch http://code.google.com/p/bullet/issues/detail?id=213
+
+ switch (type)
+ {
+ case PHY_FLOAT:
+ {
+
+ float* graphicsbase;
+
+ switch (gfxindextype)
+ {
+ case PHY_INTEGER:
+ {
+ for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
+ {
+ unsigned int* tri_indices= (unsigned int*)(indexbase+gfxindex*indexstride);
+ graphicsbase = (float*)(vertexbase+tri_indices[0]*stride);
+ triangle[0].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());
+ graphicsbase = (float*)(vertexbase+tri_indices[1]*stride);
+ triangle[1].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(), graphicsbase[2]*meshScaling.getZ());
+ graphicsbase = (float*)(vertexbase+tri_indices[2]*stride);
+ triangle[2].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(), graphicsbase[2]*meshScaling.getZ());
+ callback->internalProcessTriangleIndex(triangle,part,gfxindex);
+ }
+ break;
+ }
+ case PHY_SHORT:
+ {
+ for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
+ {
+ unsigned short int* tri_indices= (unsigned short int*)(indexbase+gfxindex*indexstride);
+ graphicsbase = (float*)(vertexbase+tri_indices[0]*stride);
+ triangle[0].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());
+ graphicsbase = (float*)(vertexbase+tri_indices[1]*stride);
+ triangle[1].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(), graphicsbase[2]*meshScaling.getZ());
+ graphicsbase = (float*)(vertexbase+tri_indices[2]*stride);
+ triangle[2].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(), graphicsbase[2]*meshScaling.getZ());
+ callback->internalProcessTriangleIndex(triangle,part,gfxindex);
+ }
+ break;
+ }
+ case PHY_UCHAR:
+ {
+ for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
+ {
+ unsigned char* tri_indices= (unsigned char*)(indexbase+gfxindex*indexstride);
+ graphicsbase = (float*)(vertexbase+tri_indices[0]*stride);
+ triangle[0].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());
+ graphicsbase = (float*)(vertexbase+tri_indices[1]*stride);
+ triangle[1].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(), graphicsbase[2]*meshScaling.getZ());
+ graphicsbase = (float*)(vertexbase+tri_indices[2]*stride);
+ triangle[2].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(), graphicsbase[2]*meshScaling.getZ());
+ callback->internalProcessTriangleIndex(triangle,part,gfxindex);
+ }
+ break;
+ }
+ default:
+ btAssert((gfxindextype == PHY_INTEGER) || (gfxindextype == PHY_SHORT));
+ }
+ break;
+ }
+
+ case PHY_DOUBLE:
+ {
+ double* graphicsbase;
+
+ switch (gfxindextype)
+ {
+ case PHY_INTEGER:
+ {
+ for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
+ {
+ unsigned int* tri_indices= (unsigned int*)(indexbase+gfxindex*indexstride);
+ graphicsbase = (double*)(vertexbase+tri_indices[0]*stride);
+ triangle[0].setValue((btScalar)graphicsbase[0]*meshScaling.getX(),(btScalar)graphicsbase[1]*meshScaling.getY(),(btScalar)graphicsbase[2]*meshScaling.getZ());
+ graphicsbase = (double*)(vertexbase+tri_indices[1]*stride);
+ triangle[1].setValue((btScalar)graphicsbase[0]*meshScaling.getX(),(btScalar)graphicsbase[1]*meshScaling.getY(), (btScalar)graphicsbase[2]*meshScaling.getZ());
+ graphicsbase = (double*)(vertexbase+tri_indices[2]*stride);
+ triangle[2].setValue((btScalar)graphicsbase[0]*meshScaling.getX(),(btScalar)graphicsbase[1]*meshScaling.getY(), (btScalar)graphicsbase[2]*meshScaling.getZ());
+ callback->internalProcessTriangleIndex(triangle,part,gfxindex);
+ }
+ break;
+ }
+ case PHY_SHORT:
+ {
+ for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
+ {
+ unsigned short int* tri_indices= (unsigned short int*)(indexbase+gfxindex*indexstride);
+ graphicsbase = (double*)(vertexbase+tri_indices[0]*stride);
+ triangle[0].setValue((btScalar)graphicsbase[0]*meshScaling.getX(),(btScalar)graphicsbase[1]*meshScaling.getY(),(btScalar)graphicsbase[2]*meshScaling.getZ());
+ graphicsbase = (double*)(vertexbase+tri_indices[1]*stride);
+ triangle[1].setValue((btScalar)graphicsbase[0]*meshScaling.getX(),(btScalar)graphicsbase[1]*meshScaling.getY(), (btScalar)graphicsbase[2]*meshScaling.getZ());
+ graphicsbase = (double*)(vertexbase+tri_indices[2]*stride);
+ triangle[2].setValue((btScalar)graphicsbase[0]*meshScaling.getX(),(btScalar)graphicsbase[1]*meshScaling.getY(), (btScalar)graphicsbase[2]*meshScaling.getZ());
+ callback->internalProcessTriangleIndex(triangle,part,gfxindex);
+ }
+ break;
+ }
+ case PHY_UCHAR:
+ {
+ for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
+ {
+ unsigned char* tri_indices= (unsigned char*)(indexbase+gfxindex*indexstride);
+ graphicsbase = (double*)(vertexbase+tri_indices[0]*stride);
+ triangle[0].setValue((btScalar)graphicsbase[0]*meshScaling.getX(),(btScalar)graphicsbase[1]*meshScaling.getY(),(btScalar)graphicsbase[2]*meshScaling.getZ());
+ graphicsbase = (double*)(vertexbase+tri_indices[1]*stride);
+ triangle[1].setValue((btScalar)graphicsbase[0]*meshScaling.getX(),(btScalar)graphicsbase[1]*meshScaling.getY(), (btScalar)graphicsbase[2]*meshScaling.getZ());
+ graphicsbase = (double*)(vertexbase+tri_indices[2]*stride);
+ triangle[2].setValue((btScalar)graphicsbase[0]*meshScaling.getX(),(btScalar)graphicsbase[1]*meshScaling.getY(), (btScalar)graphicsbase[2]*meshScaling.getZ());
+ callback->internalProcessTriangleIndex(triangle,part,gfxindex);
+ }
+ break;
+ }
+ default:
+ btAssert((gfxindextype == PHY_INTEGER) || (gfxindextype == PHY_SHORT));
+ }
+ break;
+ }
+ default:
+ btAssert((type == PHY_FLOAT) || (type == PHY_DOUBLE));
+ }
+
+ unLockReadOnlyVertexBase(part);
+ }
+}
+
+void btStridingMeshInterface::calculateAabbBruteForce(btVector3& aabbMin,btVector3& aabbMax)
+{
+
+ struct AabbCalculationCallback : public btInternalTriangleIndexCallback
+ {
+ btVector3 m_aabbMin;
+ btVector3 m_aabbMax;
+
+ AabbCalculationCallback()
+ {
+ m_aabbMin.setValue(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
+ m_aabbMax.setValue(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT));
+ }
+
+ virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex)
+ {
+ (void)partId;
+ (void)triangleIndex;
+
+ m_aabbMin.setMin(triangle[0]);
+ m_aabbMax.setMax(triangle[0]);
+ m_aabbMin.setMin(triangle[1]);
+ m_aabbMax.setMax(triangle[1]);
+ m_aabbMin.setMin(triangle[2]);
+ m_aabbMax.setMax(triangle[2]);
+ }
+ };
+
+ //first calculate the total aabb for all triangles
+ AabbCalculationCallback aabbCallback;
+ 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));
+ InternalProcessAllTriangles(&aabbCallback,aabbMin,aabbMax);
+
+ aabbMin = aabbCallback.m_aabbMin;
+ aabbMax = aabbCallback.m_aabbMax;
+}
+
+
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+const char* btStridingMeshInterface::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+ btStridingMeshInterfaceData* trimeshData = (btStridingMeshInterfaceData*) dataBuffer;
+
+ trimeshData->m_numMeshParts = getNumSubParts();
+
+ //void* uniquePtr = 0;
+
+ trimeshData->m_meshPartsPtr = 0;
+
+ if (trimeshData->m_numMeshParts)
+ {
+ btChunk* chunk = serializer->allocate(sizeof(btMeshPartData),trimeshData->m_numMeshParts);
+ btMeshPartData* memPtr = (btMeshPartData*)chunk->m_oldPtr;
+ trimeshData->m_meshPartsPtr = (btMeshPartData *)serializer->getUniquePointer(memPtr);
+
+
+ // int numtotalphysicsverts = 0;
+ int part,graphicssubparts = getNumSubParts();
+ const unsigned char * vertexbase;
+ const unsigned char * indexbase;
+ int indexstride;
+ PHY_ScalarType type;
+ PHY_ScalarType gfxindextype;
+ int stride,numverts,numtriangles;
+ int gfxindex;
+ // btVector3 triangle[3];
+
+ // btVector3 meshScaling = getScaling();
+
+ ///if the number of parts is big, the performance might drop due to the innerloop switch on indextype
+ for (part=0;part<graphicssubparts ;part++,memPtr++)
+ {
+ getLockedReadOnlyVertexIndexBase(&vertexbase,numverts,type,stride,&indexbase,indexstride,numtriangles,gfxindextype,part);
+ memPtr->m_numTriangles = numtriangles;//indices = 3*numtriangles
+ memPtr->m_numVertices = numverts;
+ memPtr->m_indices16 = 0;
+ memPtr->m_indices32 = 0;
+ memPtr->m_3indices16 = 0;
+ memPtr->m_3indices8 = 0;
+ memPtr->m_vertices3f = 0;
+ memPtr->m_vertices3d = 0;
+
+
+ switch (gfxindextype)
+ {
+ case PHY_INTEGER:
+ {
+ int numindices = numtriangles*3;
+
+ if (numindices)
+ {
+ btChunk* chunk = serializer->allocate(sizeof(btIntIndexData),numindices);
+ btIntIndexData* tmpIndices = (btIntIndexData*)chunk->m_oldPtr;
+ memPtr->m_indices32 = (btIntIndexData*)serializer->getUniquePointer(tmpIndices);
+ for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
+ {
+ unsigned int* tri_indices= (unsigned int*)(indexbase+gfxindex*indexstride);
+ tmpIndices[gfxindex*3].m_value = tri_indices[0];
+ tmpIndices[gfxindex*3+1].m_value = tri_indices[1];
+ tmpIndices[gfxindex*3+2].m_value = tri_indices[2];
+ }
+ serializer->finalizeChunk(chunk,"btIntIndexData",BT_ARRAY_CODE,(void*)chunk->m_oldPtr);
+ }
+ break;
+ }
+ case PHY_SHORT:
+ {
+ if (numtriangles)
+ {
+ btChunk* chunk = serializer->allocate(sizeof(btShortIntIndexTripletData),numtriangles);
+ btShortIntIndexTripletData* tmpIndices = (btShortIntIndexTripletData*)chunk->m_oldPtr;
+ memPtr->m_3indices16 = (btShortIntIndexTripletData*) serializer->getUniquePointer(tmpIndices);
+ for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
+ {
+ unsigned short int* tri_indices= (unsigned short int*)(indexbase+gfxindex*indexstride);
+ tmpIndices[gfxindex].m_values[0] = tri_indices[0];
+ tmpIndices[gfxindex].m_values[1] = tri_indices[1];
+ tmpIndices[gfxindex].m_values[2] = tri_indices[2];
+ // Fill padding with zeros to appease msan.
+ tmpIndices[gfxindex].m_pad[0] = 0;
+ tmpIndices[gfxindex].m_pad[1] = 0;
+ }
+ serializer->finalizeChunk(chunk,"btShortIntIndexTripletData",BT_ARRAY_CODE,(void*)chunk->m_oldPtr);
+ }
+ break;
+ }
+ case PHY_UCHAR:
+ {
+ if (numtriangles)
+ {
+ btChunk* chunk = serializer->allocate(sizeof(btCharIndexTripletData),numtriangles);
+ btCharIndexTripletData* tmpIndices = (btCharIndexTripletData*)chunk->m_oldPtr;
+ memPtr->m_3indices8 = (btCharIndexTripletData*) serializer->getUniquePointer(tmpIndices);
+ for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
+ {
+ unsigned char* tri_indices= (unsigned char*)(indexbase+gfxindex*indexstride);
+ tmpIndices[gfxindex].m_values[0] = tri_indices[0];
+ tmpIndices[gfxindex].m_values[1] = tri_indices[1];
+ tmpIndices[gfxindex].m_values[2] = tri_indices[2];
+ // Fill padding with zeros to appease msan.
+ tmpIndices[gfxindex].m_pad = 0;
+ }
+ serializer->finalizeChunk(chunk,"btCharIndexTripletData",BT_ARRAY_CODE,(void*)chunk->m_oldPtr);
+ }
+ break;
+ }
+ default:
+ {
+ btAssert(0);
+ //unknown index type
+ }
+ }
+
+ switch (type)
+ {
+ case PHY_FLOAT:
+ {
+ float* graphicsbase;
+
+ if (numverts)
+ {
+ btChunk* chunk = serializer->allocate(sizeof(btVector3FloatData),numverts);
+ btVector3FloatData* tmpVertices = (btVector3FloatData*) chunk->m_oldPtr;
+ memPtr->m_vertices3f = (btVector3FloatData *)serializer->getUniquePointer(tmpVertices);
+ for (int i=0;i<numverts;i++)
+ {
+ graphicsbase = (float*)(vertexbase+i*stride);
+ tmpVertices[i].m_floats[0] = graphicsbase[0];
+ tmpVertices[i].m_floats[1] = graphicsbase[1];
+ tmpVertices[i].m_floats[2] = graphicsbase[2];
+ }
+ serializer->finalizeChunk(chunk,"btVector3FloatData",BT_ARRAY_CODE,(void*)chunk->m_oldPtr);
+ }
+ break;
+ }
+
+ case PHY_DOUBLE:
+ {
+ if (numverts)
+ {
+ btChunk* chunk = serializer->allocate(sizeof(btVector3DoubleData),numverts);
+ btVector3DoubleData* tmpVertices = (btVector3DoubleData*) chunk->m_oldPtr;
+ memPtr->m_vertices3d = (btVector3DoubleData *) serializer->getUniquePointer(tmpVertices);
+ for (int i=0;i<numverts;i++)
+ {
+ double* graphicsbase = (double*)(vertexbase+i*stride);//for now convert to float, might leave it at double
+ tmpVertices[i].m_floats[0] = graphicsbase[0];
+ tmpVertices[i].m_floats[1] = graphicsbase[1];
+ tmpVertices[i].m_floats[2] = graphicsbase[2];
+ }
+ serializer->finalizeChunk(chunk,"btVector3DoubleData",BT_ARRAY_CODE,(void*)chunk->m_oldPtr);
+ }
+ break;
+ }
+
+ default:
+ btAssert((type == PHY_FLOAT) || (type == PHY_DOUBLE));
+ }
+
+ unLockReadOnlyVertexBase(part);
+ }
+
+ serializer->finalizeChunk(chunk,"btMeshPartData",BT_ARRAY_CODE,chunk->m_oldPtr);
+ }
+
+ // Fill padding with zeros to appease msan.
+ memset(trimeshData->m_padding, 0, sizeof(trimeshData->m_padding));
+
+ m_scaling.serializeFloat(trimeshData->m_scaling);
+ return "btStridingMeshInterfaceData";
+}
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btStridingMeshInterface.h b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btStridingMeshInterface.h
new file mode 100644
index 0000000000..9fbe139768
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btStridingMeshInterface.h
@@ -0,0 +1,164 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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_STRIDING_MESHINTERFACE_H
+#define BT_STRIDING_MESHINTERFACE_H
+
+#include "LinearMath/btVector3.h"
+#include "btTriangleCallback.h"
+#include "btConcaveShape.h"
+
+
+
+
+
+/// The btStridingMeshInterface is the interface class for high performance generic access to triangle meshes, used in combination with btBvhTriangleMeshShape and some other collision shapes.
+/// Using index striding of 3*sizeof(integer) it can use triangle arrays, using index striding of 1*sizeof(integer) it can handle triangle strips.
+/// It allows for sharing graphics and collision meshes. Also it provides locking/unlocking of graphics meshes that are in gpu memory.
+ATTRIBUTE_ALIGNED16(class ) btStridingMeshInterface
+{
+ protected:
+
+ btVector3 m_scaling;
+
+ public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ btStridingMeshInterface() :m_scaling(btScalar(1.),btScalar(1.),btScalar(1.))
+ {
+
+ }
+
+ virtual ~btStridingMeshInterface();
+
+
+
+ virtual void InternalProcessAllTriangles(btInternalTriangleIndexCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
+
+ ///brute force method to calculate aabb
+ void calculateAabbBruteForce(btVector3& aabbMin,btVector3& aabbMax);
+
+ /// get read and write access to a subpart of a triangle mesh
+ /// this subpart has a continuous array of vertices and indices
+ /// in this way the mesh can be handled as chunks of memory with striding
+ /// very similar to OpenGL vertexarray support
+ /// make a call to unLockVertexBase when the read and write access is finished
+ virtual void getLockedVertexIndexBase(unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& stride,unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0)=0;
+
+ virtual void getLockedReadOnlyVertexIndexBase(const unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& stride,const unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0) const=0;
+
+ /// unLockVertexBase finishes the access to a subpart of the triangle mesh
+ /// make a call to unLockVertexBase when the read and write access (using getLockedVertexIndexBase) is finished
+ virtual void unLockVertexBase(int subpart)=0;
+
+ virtual void unLockReadOnlyVertexBase(int subpart) const=0;
+
+
+ /// getNumSubParts returns the number of seperate subparts
+ /// each subpart has a continuous array of vertices and indices
+ virtual int getNumSubParts() const=0;
+
+ virtual void preallocateVertices(int numverts)=0;
+ virtual void preallocateIndices(int numindices)=0;
+
+ virtual bool hasPremadeAabb() const { return false; }
+ virtual void setPremadeAabb(const btVector3& aabbMin, const btVector3& aabbMax ) const
+ {
+ (void) aabbMin;
+ (void) aabbMax;
+ }
+ virtual void getPremadeAabb(btVector3* aabbMin, btVector3* aabbMax ) const
+ {
+ (void) aabbMin;
+ (void) aabbMax;
+ }
+
+ const btVector3& getScaling() const {
+ return m_scaling;
+ }
+ void setScaling(const btVector3& scaling)
+ {
+ m_scaling = scaling;
+ }
+
+ virtual int calculateSerializeBufferSize() const;
+
+ ///fills the dataBuffer and returns the struct name (and 0 on failure)
+ virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
+
+
+};
+
+struct btIntIndexData
+{
+ int m_value;
+};
+
+struct btShortIntIndexData
+{
+ short m_value;
+ char m_pad[2];
+};
+
+struct btShortIntIndexTripletData
+{
+ short m_values[3];
+ char m_pad[2];
+};
+
+struct btCharIndexTripletData
+{
+ unsigned char m_values[3];
+ char m_pad;
+};
+
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btMeshPartData
+{
+ btVector3FloatData *m_vertices3f;
+ btVector3DoubleData *m_vertices3d;
+
+ btIntIndexData *m_indices32;
+ btShortIntIndexTripletData *m_3indices16;
+ btCharIndexTripletData *m_3indices8;
+
+ btShortIntIndexData *m_indices16;//backwards compatibility
+
+ int m_numTriangles;//length of m_indices = m_numTriangles
+ int m_numVertices;
+};
+
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btStridingMeshInterfaceData
+{
+ btMeshPartData *m_meshPartsPtr;
+ btVector3FloatData m_scaling;
+ int m_numMeshParts;
+ char m_padding[4];
+};
+
+
+
+
+SIMD_FORCE_INLINE int btStridingMeshInterface::calculateSerializeBufferSize() const
+{
+ return sizeof(btStridingMeshInterfaceData);
+}
+
+
+
+#endif //BT_STRIDING_MESHINTERFACE_H
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btTetrahedronShape.cpp b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btTetrahedronShape.cpp
new file mode 100644
index 0000000000..52f346bf72
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btTetrahedronShape.cpp
@@ -0,0 +1,218 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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 "btTetrahedronShape.h"
+#include "LinearMath/btMatrix3x3.h"
+
+btBU_Simplex1to4::btBU_Simplex1to4() : btPolyhedralConvexAabbCachingShape (),
+m_numVertices(0)
+{
+ m_shapeType = TETRAHEDRAL_SHAPE_PROXYTYPE;
+}
+
+btBU_Simplex1to4::btBU_Simplex1to4(const btVector3& pt0) : btPolyhedralConvexAabbCachingShape (),
+m_numVertices(0)
+{
+ m_shapeType = TETRAHEDRAL_SHAPE_PROXYTYPE;
+ addVertex(pt0);
+}
+
+btBU_Simplex1to4::btBU_Simplex1to4(const btVector3& pt0,const btVector3& pt1) : btPolyhedralConvexAabbCachingShape (),
+m_numVertices(0)
+{
+ m_shapeType = TETRAHEDRAL_SHAPE_PROXYTYPE;
+ addVertex(pt0);
+ addVertex(pt1);
+}
+
+btBU_Simplex1to4::btBU_Simplex1to4(const btVector3& pt0,const btVector3& pt1,const btVector3& pt2) : btPolyhedralConvexAabbCachingShape (),
+m_numVertices(0)
+{
+ m_shapeType = TETRAHEDRAL_SHAPE_PROXYTYPE;
+ addVertex(pt0);
+ addVertex(pt1);
+ addVertex(pt2);
+}
+
+btBU_Simplex1to4::btBU_Simplex1to4(const btVector3& pt0,const btVector3& pt1,const btVector3& pt2,const btVector3& pt3) : btPolyhedralConvexAabbCachingShape (),
+m_numVertices(0)
+{
+ m_shapeType = TETRAHEDRAL_SHAPE_PROXYTYPE;
+ addVertex(pt0);
+ addVertex(pt1);
+ addVertex(pt2);
+ addVertex(pt3);
+}
+
+
+void btBU_Simplex1to4::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+{
+#if 1
+ btPolyhedralConvexAabbCachingShape::getAabb(t,aabbMin,aabbMax);
+#else
+ aabbMin.setValue(BT_LARGE_FLOAT,BT_LARGE_FLOAT,BT_LARGE_FLOAT);
+ aabbMax.setValue(-BT_LARGE_FLOAT,-BT_LARGE_FLOAT,-BT_LARGE_FLOAT);
+
+ //just transform the vertices in worldspace, and take their AABB
+ for (int i=0;i<m_numVertices;i++)
+ {
+ btVector3 worldVertex = t(m_vertices[i]);
+ aabbMin.setMin(worldVertex);
+ aabbMax.setMax(worldVertex);
+ }
+#endif
+}
+
+
+
+
+
+void btBU_Simplex1to4::addVertex(const btVector3& pt)
+{
+ m_vertices[m_numVertices++] = pt;
+ recalcLocalAabb();
+}
+
+
+int btBU_Simplex1to4::getNumVertices() const
+{
+ return m_numVertices;
+}
+
+int btBU_Simplex1to4::getNumEdges() const
+{
+ //euler formula, F-E+V = 2, so E = F+V-2
+
+ switch (m_numVertices)
+ {
+ case 0:
+ return 0;
+ case 1: return 0;
+ case 2: return 1;
+ case 3: return 3;
+ case 4: return 6;
+
+
+ }
+
+ return 0;
+}
+
+void btBU_Simplex1to4::getEdge(int i,btVector3& pa,btVector3& pb) const
+{
+
+ switch (m_numVertices)
+ {
+
+ case 2:
+ pa = m_vertices[0];
+ pb = m_vertices[1];
+ break;
+ case 3:
+ switch (i)
+ {
+ case 0:
+ pa = m_vertices[0];
+ pb = m_vertices[1];
+ break;
+ case 1:
+ pa = m_vertices[1];
+ pb = m_vertices[2];
+ break;
+ case 2:
+ pa = m_vertices[2];
+ pb = m_vertices[0];
+ break;
+
+ }
+ break;
+ case 4:
+ switch (i)
+ {
+ case 0:
+ pa = m_vertices[0];
+ pb = m_vertices[1];
+ break;
+ case 1:
+ pa = m_vertices[1];
+ pb = m_vertices[2];
+ break;
+ case 2:
+ pa = m_vertices[2];
+ pb = m_vertices[0];
+ break;
+ case 3:
+ pa = m_vertices[0];
+ pb = m_vertices[3];
+ break;
+ case 4:
+ pa = m_vertices[1];
+ pb = m_vertices[3];
+ break;
+ case 5:
+ pa = m_vertices[2];
+ pb = m_vertices[3];
+ break;
+ }
+
+ }
+
+
+
+
+}
+
+void btBU_Simplex1to4::getVertex(int i,btVector3& vtx) const
+{
+ vtx = m_vertices[i];
+}
+
+int btBU_Simplex1to4::getNumPlanes() const
+{
+ switch (m_numVertices)
+ {
+ case 0:
+ return 0;
+ case 1:
+ return 0;
+ case 2:
+ return 0;
+ case 3:
+ return 2;
+ case 4:
+ return 4;
+ default:
+ {
+ }
+ }
+ return 0;
+}
+
+
+void btBU_Simplex1to4::getPlane(btVector3&, btVector3& ,int ) const
+{
+
+}
+
+int btBU_Simplex1to4::getIndex(int ) const
+{
+ return 0;
+}
+
+bool btBU_Simplex1to4::isInside(const btVector3& ,btScalar ) const
+{
+ return false;
+}
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btTetrahedronShape.h b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btTetrahedronShape.h
new file mode 100644
index 0000000000..b69209835e
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btTetrahedronShape.h
@@ -0,0 +1,76 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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_SIMPLEX_1TO4_SHAPE
+#define BT_SIMPLEX_1TO4_SHAPE
+
+
+#include "btPolyhedralConvexShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+
+
+///The btBU_Simplex1to4 implements tetrahedron, triangle, line, vertex collision shapes. In most cases it is better to use btConvexHullShape instead.
+ATTRIBUTE_ALIGNED16(class) btBU_Simplex1to4 : public btPolyhedralConvexAabbCachingShape
+{
+protected:
+
+ int m_numVertices;
+ btVector3 m_vertices[4];
+
+public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ btBU_Simplex1to4();
+
+ btBU_Simplex1to4(const btVector3& pt0);
+ btBU_Simplex1to4(const btVector3& pt0,const btVector3& pt1);
+ btBU_Simplex1to4(const btVector3& pt0,const btVector3& pt1,const btVector3& pt2);
+ btBU_Simplex1to4(const btVector3& pt0,const btVector3& pt1,const btVector3& pt2,const btVector3& pt3);
+
+
+ void reset()
+ {
+ m_numVertices = 0;
+ }
+
+ virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+
+ void addVertex(const btVector3& pt);
+
+ //PolyhedralConvexShape interface
+
+ virtual int getNumVertices() const;
+
+ virtual int getNumEdges() const;
+
+ virtual void getEdge(int i,btVector3& pa,btVector3& pb) const;
+
+ virtual void getVertex(int i,btVector3& vtx) const;
+
+ virtual int getNumPlanes() const;
+
+ virtual void getPlane(btVector3& planeNormal,btVector3& planeSupport,int i) const;
+
+ virtual int getIndex(int i) const;
+
+ virtual bool isInside(const btVector3& pt,btScalar tolerance) const;
+
+
+ ///getName is for debugging
+ virtual const char* getName()const { return "btBU_Simplex1to4";}
+
+};
+
+#endif //BT_SIMPLEX_1TO4_SHAPE
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btTriangleBuffer.cpp b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btTriangleBuffer.cpp
new file mode 100644
index 0000000000..3027e65b25
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btTriangleBuffer.cpp
@@ -0,0 +1,35 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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 "btTriangleBuffer.h"
+
+
+
+
+
+
+
+void btTriangleBuffer::processTriangle(btVector3* triangle,int partId,int triangleIndex)
+{
+ btTriangle tri;
+ tri.m_vertex0 = triangle[0];
+ tri.m_vertex1 = triangle[1];
+ tri.m_vertex2 = triangle[2];
+ tri.m_partId = partId;
+ tri.m_triangleIndex = triangleIndex;
+
+ m_triangleBuffer.push_back(tri);
+}
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btTriangleBuffer.h b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btTriangleBuffer.h
new file mode 100644
index 0000000000..b71fc8b374
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btTriangleBuffer.h
@@ -0,0 +1,69 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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_TRIANGLE_BUFFER_H
+#define BT_TRIANGLE_BUFFER_H
+
+#include "btTriangleCallback.h"
+#include "LinearMath/btAlignedObjectArray.h"
+
+struct btTriangle
+{
+ btVector3 m_vertex0;
+ btVector3 m_vertex1;
+ btVector3 m_vertex2;
+ int m_partId;
+ int m_triangleIndex;
+};
+
+///The btTriangleBuffer callback can be useful to collect and store overlapping triangles between AABB and concave objects that support 'processAllTriangles'
+///Example usage of this class:
+/// btTriangleBuffer triBuf;
+/// concaveShape->processAllTriangles(&triBuf,aabbMin, aabbMax);
+/// for (int i=0;i<triBuf.getNumTriangles();i++)
+/// {
+/// const btTriangle& tri = triBuf.getTriangle(i);
+/// //do something useful here with the triangle
+/// }
+class btTriangleBuffer : public btTriangleCallback
+{
+
+ btAlignedObjectArray<btTriangle> m_triangleBuffer;
+
+public:
+
+
+ virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex);
+
+ int getNumTriangles() const
+ {
+ return int(m_triangleBuffer.size());
+ }
+
+ const btTriangle& getTriangle(int index) const
+ {
+ return m_triangleBuffer[index];
+ }
+
+ void clearBuffer()
+ {
+ m_triangleBuffer.clear();
+ }
+
+};
+
+
+#endif //BT_TRIANGLE_BUFFER_H
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btTriangleCallback.cpp b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btTriangleCallback.cpp
new file mode 100644
index 0000000000..f558bf6d24
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btTriangleCallback.cpp
@@ -0,0 +1,28 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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 "btTriangleCallback.h"
+
+btTriangleCallback::~btTriangleCallback()
+{
+
+}
+
+
+btInternalTriangleIndexCallback::~btInternalTriangleIndexCallback()
+{
+
+}
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btTriangleCallback.h b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btTriangleCallback.h
new file mode 100644
index 0000000000..461c57f877
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btTriangleCallback.h
@@ -0,0 +1,42 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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_TRIANGLE_CALLBACK_H
+#define BT_TRIANGLE_CALLBACK_H
+
+#include "LinearMath/btVector3.h"
+
+
+///The btTriangleCallback provides a callback for each overlapping triangle when calling processAllTriangles.
+///This callback is called by processAllTriangles for all btConcaveShape derived class, such as btBvhTriangleMeshShape, btStaticPlaneShape and btHeightfieldTerrainShape.
+class btTriangleCallback
+{
+public:
+
+ virtual ~btTriangleCallback();
+ virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex) = 0;
+};
+
+class btInternalTriangleIndexCallback
+{
+public:
+
+ virtual ~btInternalTriangleIndexCallback();
+ virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex) = 0;
+};
+
+
+
+#endif //BT_TRIANGLE_CALLBACK_H
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp
new file mode 100644
index 0000000000..a665024cb6
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp
@@ -0,0 +1,95 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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 "btTriangleIndexVertexArray.h"
+
+btTriangleIndexVertexArray::btTriangleIndexVertexArray(int numTriangles,int* triangleIndexBase,int triangleIndexStride,int numVertices,btScalar* vertexBase,int vertexStride)
+: m_hasAabb(0)
+{
+ btIndexedMesh mesh;
+
+ mesh.m_numTriangles = numTriangles;
+ mesh.m_triangleIndexBase = (const unsigned char *)triangleIndexBase;
+ mesh.m_triangleIndexStride = triangleIndexStride;
+ mesh.m_numVertices = numVertices;
+ mesh.m_vertexBase = (const unsigned char *)vertexBase;
+ mesh.m_vertexStride = vertexStride;
+
+ addIndexedMesh(mesh);
+
+}
+
+btTriangleIndexVertexArray::~btTriangleIndexVertexArray()
+{
+
+}
+
+void btTriangleIndexVertexArray::getLockedVertexIndexBase(unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& vertexStride,unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart)
+{
+ btAssert(subpart< getNumSubParts() );
+
+ btIndexedMesh& mesh = m_indexedMeshes[subpart];
+
+ numverts = mesh.m_numVertices;
+ (*vertexbase) = (unsigned char *) mesh.m_vertexBase;
+
+ type = mesh.m_vertexType;
+
+ vertexStride = mesh.m_vertexStride;
+
+ numfaces = mesh.m_numTriangles;
+
+ (*indexbase) = (unsigned char *)mesh.m_triangleIndexBase;
+ indexstride = mesh.m_triangleIndexStride;
+ indicestype = mesh.m_indexType;
+}
+
+void btTriangleIndexVertexArray::getLockedReadOnlyVertexIndexBase(const unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& vertexStride,const unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart) const
+{
+ const btIndexedMesh& mesh = m_indexedMeshes[subpart];
+
+ numverts = mesh.m_numVertices;
+ (*vertexbase) = (const unsigned char *)mesh.m_vertexBase;
+
+ type = mesh.m_vertexType;
+
+ vertexStride = mesh.m_vertexStride;
+
+ numfaces = mesh.m_numTriangles;
+ (*indexbase) = (const unsigned char *)mesh.m_triangleIndexBase;
+ indexstride = mesh.m_triangleIndexStride;
+ indicestype = mesh.m_indexType;
+}
+
+bool btTriangleIndexVertexArray::hasPremadeAabb() const
+{
+ return (m_hasAabb == 1);
+}
+
+
+void btTriangleIndexVertexArray::setPremadeAabb(const btVector3& aabbMin, const btVector3& aabbMax ) const
+{
+ m_aabbMin = aabbMin;
+ m_aabbMax = aabbMax;
+ m_hasAabb = 1; // this is intentionally an int see notes in header
+}
+
+void btTriangleIndexVertexArray::getPremadeAabb(btVector3* aabbMin, btVector3* aabbMax ) const
+{
+ *aabbMin = m_aabbMin;
+ *aabbMax = m_aabbMax;
+}
+
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h
new file mode 100644
index 0000000000..9e1544e87a
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h
@@ -0,0 +1,133 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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_TRIANGLE_INDEX_VERTEX_ARRAY_H
+#define BT_TRIANGLE_INDEX_VERTEX_ARRAY_H
+
+#include "btStridingMeshInterface.h"
+#include "LinearMath/btAlignedObjectArray.h"
+#include "LinearMath/btScalar.h"
+
+
+///The btIndexedMesh indexes a single vertex and index array. Multiple btIndexedMesh objects can be passed into a btTriangleIndexVertexArray using addIndexedMesh.
+///Instead of the number of indices, we pass the number of triangles.
+ATTRIBUTE_ALIGNED16( struct) btIndexedMesh
+{
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ int m_numTriangles;
+ const unsigned char * m_triangleIndexBase;
+ // Size in byte of the indices for one triangle (3*sizeof(index_type) if the indices are tightly packed)
+ int m_triangleIndexStride;
+ int m_numVertices;
+ const unsigned char * m_vertexBase;
+ // Size of a vertex, in bytes
+ int m_vertexStride;
+
+ // The index type is set when adding an indexed mesh to the
+ // btTriangleIndexVertexArray, do not set it manually
+ PHY_ScalarType m_indexType;
+
+ // The vertex type has a default type similar to Bullet's precision mode (float or double)
+ // but can be set manually if you for example run Bullet with double precision but have
+ // mesh data in single precision..
+ PHY_ScalarType m_vertexType;
+
+
+ btIndexedMesh()
+ :m_indexType(PHY_INTEGER),
+#ifdef BT_USE_DOUBLE_PRECISION
+ m_vertexType(PHY_DOUBLE)
+#else // BT_USE_DOUBLE_PRECISION
+ m_vertexType(PHY_FLOAT)
+#endif // BT_USE_DOUBLE_PRECISION
+ {
+ }
+}
+;
+
+
+typedef btAlignedObjectArray<btIndexedMesh> IndexedMeshArray;
+
+///The btTriangleIndexVertexArray allows to access multiple triangle meshes, by indexing into existing triangle/index arrays.
+///Additional meshes can be added using addIndexedMesh
+///No duplcate is made of the vertex/index data, it only indexes into external vertex/index arrays.
+///So keep those arrays around during the lifetime of this btTriangleIndexVertexArray.
+ATTRIBUTE_ALIGNED16( class) btTriangleIndexVertexArray : public btStridingMeshInterface
+{
+protected:
+ IndexedMeshArray m_indexedMeshes;
+ int m_pad[2];
+ mutable int m_hasAabb; // using int instead of bool to maintain alignment
+ mutable btVector3 m_aabbMin;
+ mutable btVector3 m_aabbMax;
+
+public:
+
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ btTriangleIndexVertexArray() : m_hasAabb(0)
+ {
+ }
+
+ virtual ~btTriangleIndexVertexArray();
+
+ //just to be backwards compatible
+ btTriangleIndexVertexArray(int numTriangles,int* triangleIndexBase,int triangleIndexStride,int numVertices,btScalar* vertexBase,int vertexStride);
+
+ void addIndexedMesh(const btIndexedMesh& mesh, PHY_ScalarType indexType = PHY_INTEGER)
+ {
+ m_indexedMeshes.push_back(mesh);
+ m_indexedMeshes[m_indexedMeshes.size()-1].m_indexType = indexType;
+ }
+
+
+ virtual void getLockedVertexIndexBase(unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& vertexStride,unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0);
+
+ virtual void getLockedReadOnlyVertexIndexBase(const unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& vertexStride,const unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0) const;
+
+ /// unLockVertexBase finishes the access to a subpart of the triangle mesh
+ /// make a call to unLockVertexBase when the read and write access (using getLockedVertexIndexBase) is finished
+ virtual void unLockVertexBase(int subpart) {(void)subpart;}
+
+ virtual void unLockReadOnlyVertexBase(int subpart) const {(void)subpart;}
+
+ /// getNumSubParts returns the number of seperate subparts
+ /// each subpart has a continuous array of vertices and indices
+ virtual int getNumSubParts() const {
+ return (int)m_indexedMeshes.size();
+ }
+
+ IndexedMeshArray& getIndexedMeshArray()
+ {
+ return m_indexedMeshes;
+ }
+
+ const IndexedMeshArray& getIndexedMeshArray() const
+ {
+ return m_indexedMeshes;
+ }
+
+ virtual void preallocateVertices(int numverts){(void) numverts;}
+ virtual void preallocateIndices(int numindices){(void) numindices;}
+
+ virtual bool hasPremadeAabb() const;
+ virtual void setPremadeAabb(const btVector3& aabbMin, const btVector3& aabbMax ) const;
+ virtual void getPremadeAabb(btVector3* aabbMin, btVector3* aabbMax ) const;
+
+}
+;
+
+#endif //BT_TRIANGLE_INDEX_VERTEX_ARRAY_H
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp
new file mode 100644
index 0000000000..dc562941ad
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp
@@ -0,0 +1,86 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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.
+*/
+
+///This file was created by Alex Silverman
+
+#include "btTriangleIndexVertexMaterialArray.h"
+
+btTriangleIndexVertexMaterialArray::btTriangleIndexVertexMaterialArray(int numTriangles,int* triangleIndexBase,int triangleIndexStride,
+ int numVertices,btScalar* vertexBase,int vertexStride,
+ int numMaterials, unsigned char* materialBase, int materialStride,
+ int* triangleMaterialsBase, int materialIndexStride) :
+btTriangleIndexVertexArray(numTriangles, triangleIndexBase, triangleIndexStride, numVertices, vertexBase, vertexStride)
+{
+ btMaterialProperties mat;
+
+ mat.m_numMaterials = numMaterials;
+ mat.m_materialBase = materialBase;
+ mat.m_materialStride = materialStride;
+#ifdef BT_USE_DOUBLE_PRECISION
+ mat.m_materialType = PHY_DOUBLE;
+#else
+ mat.m_materialType = PHY_FLOAT;
+#endif
+
+ mat.m_numTriangles = numTriangles;
+ mat.m_triangleMaterialsBase = (unsigned char *)triangleMaterialsBase;
+ mat.m_triangleMaterialStride = materialIndexStride;
+ mat.m_triangleType = PHY_INTEGER;
+
+ addMaterialProperties(mat);
+}
+
+
+void btTriangleIndexVertexMaterialArray::getLockedMaterialBase(unsigned char **materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride,
+ unsigned char ** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType, int subpart)
+{
+ btAssert(subpart< getNumSubParts() );
+
+ btMaterialProperties& mats = m_materials[subpart];
+
+ numMaterials = mats.m_numMaterials;
+ (*materialBase) = (unsigned char *) mats.m_materialBase;
+#ifdef BT_USE_DOUBLE_PRECISION
+ materialType = PHY_DOUBLE;
+#else
+ materialType = PHY_FLOAT;
+#endif
+ materialStride = mats.m_materialStride;
+
+ numTriangles = mats.m_numTriangles;
+ (*triangleMaterialBase) = (unsigned char *)mats.m_triangleMaterialsBase;
+ triangleMaterialStride = mats.m_triangleMaterialStride;
+ triangleType = mats.m_triangleType;
+}
+
+void btTriangleIndexVertexMaterialArray::getLockedReadOnlyMaterialBase(const unsigned char **materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride,
+ const unsigned char ** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType, int subpart)
+{
+ btMaterialProperties& mats = m_materials[subpart];
+
+ numMaterials = mats.m_numMaterials;
+ (*materialBase) = (const unsigned char *) mats.m_materialBase;
+#ifdef BT_USE_DOUBLE_PRECISION
+ materialType = PHY_DOUBLE;
+#else
+ materialType = PHY_FLOAT;
+#endif
+ materialStride = mats.m_materialStride;
+
+ numTriangles = mats.m_numTriangles;
+ (*triangleMaterialBase) = (const unsigned char *)mats.m_triangleMaterialsBase;
+ triangleMaterialStride = mats.m_triangleMaterialStride;
+ triangleType = mats.m_triangleType;
+}
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h
new file mode 100644
index 0000000000..ba4f7b4607
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h
@@ -0,0 +1,84 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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.
+*/
+
+///This file was created by Alex Silverman
+
+#ifndef BT_MULTIMATERIAL_TRIANGLE_INDEX_VERTEX_ARRAY_H
+#define BT_MULTIMATERIAL_TRIANGLE_INDEX_VERTEX_ARRAY_H
+
+#include "btTriangleIndexVertexArray.h"
+
+
+ATTRIBUTE_ALIGNED16( struct) btMaterialProperties
+{
+ ///m_materialBase ==========> 2 btScalar values make up one material, friction then restitution
+ int m_numMaterials;
+ const unsigned char * m_materialBase;
+ int m_materialStride;
+ PHY_ScalarType m_materialType;
+ ///m_numTriangles <=========== This exists in the btIndexedMesh object for the same subpart, but since we're
+ /// padding the structure, it can be reproduced at no real cost
+ ///m_triangleMaterials =====> 1 integer value makes up one entry
+ /// eg: m_triangleMaterials[1] = 5; // This will set triangle 2 to use material 5
+ int m_numTriangles;
+ const unsigned char * m_triangleMaterialsBase;
+ int m_triangleMaterialStride;
+ ///m_triangleType <========== Automatically set in addMaterialProperties
+ PHY_ScalarType m_triangleType;
+};
+
+typedef btAlignedObjectArray<btMaterialProperties> MaterialArray;
+
+///Teh btTriangleIndexVertexMaterialArray is built on TriangleIndexVertexArray
+///The addition of a material array allows for the utilization of the partID and
+///triangleIndex that are returned in the ContactAddedCallback. As with
+///TriangleIndexVertexArray, no duplicate is made of the material data, so it
+///is the users responsibility to maintain the array during the lifetime of the
+///TriangleIndexVertexMaterialArray.
+ATTRIBUTE_ALIGNED16(class) btTriangleIndexVertexMaterialArray : public btTriangleIndexVertexArray
+{
+protected:
+ MaterialArray m_materials;
+
+public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ btTriangleIndexVertexMaterialArray()
+ {
+ }
+
+ btTriangleIndexVertexMaterialArray(int numTriangles,int* triangleIndexBase,int triangleIndexStride,
+ int numVertices,btScalar* vertexBase,int vertexStride,
+ int numMaterials, unsigned char* materialBase, int materialStride,
+ int* triangleMaterialsBase, int materialIndexStride);
+
+ virtual ~btTriangleIndexVertexMaterialArray() {}
+
+ void addMaterialProperties(const btMaterialProperties& mat, PHY_ScalarType triangleType = PHY_INTEGER)
+ {
+ m_materials.push_back(mat);
+ m_materials[m_materials.size()-1].m_triangleType = triangleType;
+ }
+
+ virtual void getLockedMaterialBase(unsigned char **materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride,
+ unsigned char ** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType ,int subpart = 0);
+
+ virtual void getLockedReadOnlyMaterialBase(const unsigned char **materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride,
+ const unsigned char ** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType, int subpart = 0);
+
+}
+;
+
+#endif //BT_MULTIMATERIAL_TRIANGLE_INDEX_VERTEX_ARRAY_H
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btTriangleInfoMap.h b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btTriangleInfoMap.h
new file mode 100644
index 0000000000..6427589590
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btTriangleInfoMap.h
@@ -0,0 +1,248 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2010 Erwin Coumans 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_TRIANGLE_INFO_MAP_H
+#define _BT_TRIANGLE_INFO_MAP_H
+
+
+#include "LinearMath/btHashMap.h"
+#include "LinearMath/btSerializer.h"
+
+
+///for btTriangleInfo m_flags
+#define TRI_INFO_V0V1_CONVEX 1
+#define TRI_INFO_V1V2_CONVEX 2
+#define TRI_INFO_V2V0_CONVEX 4
+
+#define TRI_INFO_V0V1_SWAP_NORMALB 8
+#define TRI_INFO_V1V2_SWAP_NORMALB 16
+#define TRI_INFO_V2V0_SWAP_NORMALB 32
+
+
+///The btTriangleInfo structure stores information to adjust collision normals to avoid collisions against internal edges
+///it can be generated using
+struct btTriangleInfo
+{
+ btTriangleInfo()
+ {
+ m_edgeV0V1Angle = SIMD_2_PI;
+ m_edgeV1V2Angle = SIMD_2_PI;
+ m_edgeV2V0Angle = SIMD_2_PI;
+ m_flags=0;
+ }
+
+ int m_flags;
+
+ btScalar m_edgeV0V1Angle;
+ btScalar m_edgeV1V2Angle;
+ btScalar m_edgeV2V0Angle;
+
+};
+
+typedef btHashMap<btHashInt,btTriangleInfo> btInternalTriangleInfoMap;
+
+
+///The btTriangleInfoMap stores edge angle information for some triangles. You can compute this information yourself or using btGenerateInternalEdgeInfo.
+struct btTriangleInfoMap : public btInternalTriangleInfoMap
+{
+ btScalar m_convexEpsilon;///used to determine if an edge or contact normal is convex, using the dot product
+ btScalar m_planarEpsilon; ///used to determine if a triangle edge is planar with zero angle
+ btScalar m_equalVertexThreshold; ///used to compute connectivity: if the distance between two vertices is smaller than m_equalVertexThreshold, they are considered to be 'shared'
+ btScalar m_edgeDistanceThreshold; ///used to determine edge contacts: if the closest distance between a contact point and an edge is smaller than this distance threshold it is considered to "hit the edge"
+ btScalar m_maxEdgeAngleThreshold; //ignore edges that connect triangles at an angle larger than this m_maxEdgeAngleThreshold
+ btScalar m_zeroAreaThreshold; ///used to determine if a triangle is degenerate (length squared of cross product of 2 triangle edges < threshold)
+
+
+ btTriangleInfoMap()
+ {
+ m_convexEpsilon = 0.00f;
+ m_planarEpsilon = 0.0001f;
+ m_equalVertexThreshold = btScalar(0.0001)*btScalar(0.0001);
+ m_edgeDistanceThreshold = btScalar(0.1);
+ m_zeroAreaThreshold = btScalar(0.0001)*btScalar(0.0001);
+ m_maxEdgeAngleThreshold = SIMD_2_PI;
+ }
+ virtual ~btTriangleInfoMap() {}
+
+ virtual int calculateSerializeBufferSize() const;
+
+ ///fills the dataBuffer and returns the struct name (and 0 on failure)
+ virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
+
+ void deSerialize(struct btTriangleInfoMapData& data);
+
+};
+
+///those fields have to be float and not btScalar for the serialization to work properly
+struct btTriangleInfoData
+{
+ int m_flags;
+ float m_edgeV0V1Angle;
+ float m_edgeV1V2Angle;
+ float m_edgeV2V0Angle;
+};
+
+struct btTriangleInfoMapData
+{
+ int *m_hashTablePtr;
+ int *m_nextPtr;
+ btTriangleInfoData *m_valueArrayPtr;
+ int *m_keyArrayPtr;
+
+ float m_convexEpsilon;
+ float m_planarEpsilon;
+ float m_equalVertexThreshold;
+ float m_edgeDistanceThreshold;
+ float m_zeroAreaThreshold;
+
+ int m_nextSize;
+ int m_hashTableSize;
+ int m_numValues;
+ int m_numKeys;
+ char m_padding[4];
+};
+
+SIMD_FORCE_INLINE int btTriangleInfoMap::calculateSerializeBufferSize() const
+{
+ return sizeof(btTriangleInfoMapData);
+}
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+SIMD_FORCE_INLINE const char* btTriangleInfoMap::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+ btTriangleInfoMapData* tmapData = (btTriangleInfoMapData*) dataBuffer;
+ tmapData->m_convexEpsilon = (float)m_convexEpsilon;
+ tmapData->m_planarEpsilon = (float)m_planarEpsilon;
+ tmapData->m_equalVertexThreshold =(float) m_equalVertexThreshold;
+ tmapData->m_edgeDistanceThreshold = (float)m_edgeDistanceThreshold;
+ tmapData->m_zeroAreaThreshold = (float)m_zeroAreaThreshold;
+
+ tmapData->m_hashTableSize = m_hashTable.size();
+
+ tmapData->m_hashTablePtr = tmapData->m_hashTableSize ? (int*)serializer->getUniquePointer((void*)&m_hashTable[0]) : 0;
+ if (tmapData->m_hashTablePtr)
+ {
+ //serialize an int buffer
+ int sz = sizeof(int);
+ int numElem = tmapData->m_hashTableSize;
+ btChunk* chunk = serializer->allocate(sz,numElem);
+ int* memPtr = (int*)chunk->m_oldPtr;
+ for (int i=0;i<numElem;i++,memPtr++)
+ {
+ *memPtr = m_hashTable[i];
+ }
+ serializer->finalizeChunk(chunk,"int",BT_ARRAY_CODE,(void*)&m_hashTable[0]);
+
+ }
+
+ tmapData->m_nextSize = m_next.size();
+ tmapData->m_nextPtr = tmapData->m_nextSize? (int*)serializer->getUniquePointer((void*)&m_next[0]): 0;
+ if (tmapData->m_nextPtr)
+ {
+ int sz = sizeof(int);
+ int numElem = tmapData->m_nextSize;
+ btChunk* chunk = serializer->allocate(sz,numElem);
+ int* memPtr = (int*)chunk->m_oldPtr;
+ for (int i=0;i<numElem;i++,memPtr++)
+ {
+ *memPtr = m_next[i];
+ }
+ serializer->finalizeChunk(chunk,"int",BT_ARRAY_CODE,(void*)&m_next[0]);
+ }
+
+ tmapData->m_numValues = m_valueArray.size();
+ tmapData->m_valueArrayPtr = tmapData->m_numValues ? (btTriangleInfoData*)serializer->getUniquePointer((void*)&m_valueArray[0]): 0;
+ if (tmapData->m_valueArrayPtr)
+ {
+ int sz = sizeof(btTriangleInfoData);
+ int numElem = tmapData->m_numValues;
+ btChunk* chunk = serializer->allocate(sz,numElem);
+ btTriangleInfoData* memPtr = (btTriangleInfoData*)chunk->m_oldPtr;
+ for (int i=0;i<numElem;i++,memPtr++)
+ {
+ memPtr->m_edgeV0V1Angle = (float)m_valueArray[i].m_edgeV0V1Angle;
+ memPtr->m_edgeV1V2Angle = (float)m_valueArray[i].m_edgeV1V2Angle;
+ memPtr->m_edgeV2V0Angle = (float)m_valueArray[i].m_edgeV2V0Angle;
+ memPtr->m_flags = m_valueArray[i].m_flags;
+ }
+ serializer->finalizeChunk(chunk,"btTriangleInfoData",BT_ARRAY_CODE,(void*) &m_valueArray[0]);
+ }
+
+ tmapData->m_numKeys = m_keyArray.size();
+ tmapData->m_keyArrayPtr = tmapData->m_numKeys ? (int*)serializer->getUniquePointer((void*)&m_keyArray[0]) : 0;
+ if (tmapData->m_keyArrayPtr)
+ {
+ int sz = sizeof(int);
+ int numElem = tmapData->m_numValues;
+ btChunk* chunk = serializer->allocate(sz,numElem);
+ int* memPtr = (int*)chunk->m_oldPtr;
+ for (int i=0;i<numElem;i++,memPtr++)
+ {
+ *memPtr = m_keyArray[i].getUid1();
+ }
+ serializer->finalizeChunk(chunk,"int",BT_ARRAY_CODE,(void*) &m_keyArray[0]);
+
+ }
+
+ // Fill padding with zeros to appease msan.
+ tmapData->m_padding[0] = 0;
+ tmapData->m_padding[1] = 0;
+ tmapData->m_padding[2] = 0;
+ tmapData->m_padding[3] = 0;
+
+ return "btTriangleInfoMapData";
+}
+
+
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+SIMD_FORCE_INLINE void btTriangleInfoMap::deSerialize(btTriangleInfoMapData& tmapData )
+{
+
+
+ m_convexEpsilon = tmapData.m_convexEpsilon;
+ m_planarEpsilon = tmapData.m_planarEpsilon;
+ m_equalVertexThreshold = tmapData.m_equalVertexThreshold;
+ m_edgeDistanceThreshold = tmapData.m_edgeDistanceThreshold;
+ m_zeroAreaThreshold = tmapData.m_zeroAreaThreshold;
+ m_hashTable.resize(tmapData.m_hashTableSize);
+ int i =0;
+ for (i=0;i<tmapData.m_hashTableSize;i++)
+ {
+ m_hashTable[i] = tmapData.m_hashTablePtr[i];
+ }
+ m_next.resize(tmapData.m_nextSize);
+ for (i=0;i<tmapData.m_nextSize;i++)
+ {
+ m_next[i] = tmapData.m_nextPtr[i];
+ }
+ m_valueArray.resize(tmapData.m_numValues);
+ for (i=0;i<tmapData.m_numValues;i++)
+ {
+ m_valueArray[i].m_edgeV0V1Angle = tmapData.m_valueArrayPtr[i].m_edgeV0V1Angle;
+ m_valueArray[i].m_edgeV1V2Angle = tmapData.m_valueArrayPtr[i].m_edgeV1V2Angle;
+ m_valueArray[i].m_edgeV2V0Angle = tmapData.m_valueArrayPtr[i].m_edgeV2V0Angle;
+ m_valueArray[i].m_flags = tmapData.m_valueArrayPtr[i].m_flags;
+ }
+
+ m_keyArray.resize(tmapData.m_numKeys,btHashInt(0));
+ for (i=0;i<tmapData.m_numKeys;i++)
+ {
+ m_keyArray[i].setUid1(tmapData.m_keyArrayPtr[i]);
+ }
+}
+
+
+#endif //_BT_TRIANGLE_INFO_MAP_H
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btTriangleMesh.cpp b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btTriangleMesh.cpp
new file mode 100644
index 0000000000..e4de732093
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btTriangleMesh.cpp
@@ -0,0 +1,169 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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 "btTriangleMesh.h"
+
+
+
+btTriangleMesh::btTriangleMesh (bool use32bitIndices,bool use4componentVertices)
+:m_use32bitIndices(use32bitIndices),
+m_use4componentVertices(use4componentVertices),
+m_weldingThreshold(0.0)
+{
+ btIndexedMesh meshIndex;
+ meshIndex.m_numTriangles = 0;
+ meshIndex.m_numVertices = 0;
+ meshIndex.m_indexType = PHY_INTEGER;
+ meshIndex.m_triangleIndexBase = 0;
+ meshIndex.m_triangleIndexStride = 3*sizeof(int);
+ meshIndex.m_vertexBase = 0;
+ meshIndex.m_vertexStride = sizeof(btVector3);
+ m_indexedMeshes.push_back(meshIndex);
+
+ if (m_use32bitIndices)
+ {
+ m_indexedMeshes[0].m_numTriangles = m_32bitIndices.size()/3;
+ m_indexedMeshes[0].m_triangleIndexBase = 0;
+ m_indexedMeshes[0].m_indexType = PHY_INTEGER;
+ m_indexedMeshes[0].m_triangleIndexStride = 3*sizeof(int);
+ } else
+ {
+ m_indexedMeshes[0].m_numTriangles = m_16bitIndices.size()/3;
+ m_indexedMeshes[0].m_triangleIndexBase = 0;
+ m_indexedMeshes[0].m_indexType = PHY_SHORT;
+ m_indexedMeshes[0].m_triangleIndexStride = 3*sizeof(short int);
+ }
+
+ if (m_use4componentVertices)
+ {
+ m_indexedMeshes[0].m_numVertices = m_4componentVertices.size();
+ m_indexedMeshes[0].m_vertexBase = 0;
+ m_indexedMeshes[0].m_vertexStride = sizeof(btVector3);
+ } else
+ {
+ m_indexedMeshes[0].m_numVertices = m_3componentVertices.size()/3;
+ m_indexedMeshes[0].m_vertexBase = 0;
+ m_indexedMeshes[0].m_vertexStride = 3*sizeof(btScalar);
+ }
+
+
+}
+
+void btTriangleMesh::addIndex(int index)
+{
+ if (m_use32bitIndices)
+ {
+ m_32bitIndices.push_back(index);
+ m_indexedMeshes[0].m_triangleIndexBase = (unsigned char*) &m_32bitIndices[0];
+ } else
+ {
+ m_16bitIndices.push_back(index);
+ m_indexedMeshes[0].m_triangleIndexBase = (unsigned char*) &m_16bitIndices[0];
+ }
+}
+
+void btTriangleMesh::addTriangleIndices(int index1, int index2, int index3 )
+{
+ m_indexedMeshes[0].m_numTriangles++;
+ addIndex( index1 );
+ addIndex( index2 );
+ addIndex( index3 );
+}
+
+int btTriangleMesh::findOrAddVertex(const btVector3& vertex, bool removeDuplicateVertices)
+{
+ //return index of new/existing vertex
+ ///@todo: could use acceleration structure for this
+ if (m_use4componentVertices)
+ {
+ if (removeDuplicateVertices)
+ {
+ for (int i=0;i< m_4componentVertices.size();i++)
+ {
+ if ((m_4componentVertices[i]-vertex).length2() <= m_weldingThreshold)
+ {
+ return i;
+ }
+ }
+ }
+ m_indexedMeshes[0].m_numVertices++;
+ m_4componentVertices.push_back(vertex);
+ m_indexedMeshes[0].m_vertexBase = (unsigned char*)&m_4componentVertices[0];
+
+ return m_4componentVertices.size()-1;
+
+ } else
+ {
+
+ if (removeDuplicateVertices)
+ {
+ for (int i=0;i< m_3componentVertices.size();i+=3)
+ {
+ btVector3 vtx(m_3componentVertices[i],m_3componentVertices[i+1],m_3componentVertices[i+2]);
+ if ((vtx-vertex).length2() <= m_weldingThreshold)
+ {
+ return i/3;
+ }
+ }
+ }
+ m_3componentVertices.push_back(vertex.getX());
+ m_3componentVertices.push_back(vertex.getY());
+ m_3componentVertices.push_back(vertex.getZ());
+ m_indexedMeshes[0].m_numVertices++;
+ m_indexedMeshes[0].m_vertexBase = (unsigned char*)&m_3componentVertices[0];
+ return (m_3componentVertices.size()/3)-1;
+ }
+
+}
+
+void btTriangleMesh::addTriangle(const btVector3& vertex0,const btVector3& vertex1,const btVector3& vertex2,bool removeDuplicateVertices)
+{
+ m_indexedMeshes[0].m_numTriangles++;
+ addIndex(findOrAddVertex(vertex0,removeDuplicateVertices));
+ addIndex(findOrAddVertex(vertex1,removeDuplicateVertices));
+ addIndex(findOrAddVertex(vertex2,removeDuplicateVertices));
+}
+
+int btTriangleMesh::getNumTriangles() const
+{
+ if (m_use32bitIndices)
+ {
+ return m_32bitIndices.size() / 3;
+ }
+ return m_16bitIndices.size() / 3;
+}
+
+void btTriangleMesh::preallocateVertices(int numverts)
+{
+ if (m_use4componentVertices)
+ {
+ m_4componentVertices.reserve(numverts);
+ } else
+ {
+ m_3componentVertices.reserve(numverts);
+ }
+}
+
+void btTriangleMesh::preallocateIndices(int numindices)
+{
+ if (m_use32bitIndices)
+ {
+ m_32bitIndices.reserve(numindices);
+ } else
+ {
+ m_16bitIndices.reserve(numindices);
+ }
+}
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btTriangleMesh.h b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btTriangleMesh.h
new file mode 100644
index 0000000000..ac4afa7f6b
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btTriangleMesh.h
@@ -0,0 +1,72 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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_TRIANGLE_MESH_H
+#define BT_TRIANGLE_MESH_H
+
+#include "btTriangleIndexVertexArray.h"
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btAlignedObjectArray.h"
+
+///The btTriangleMesh class is a convenience class derived from btTriangleIndexVertexArray, that provides storage for a concave triangle mesh. It can be used as data for the btBvhTriangleMeshShape.
+///It allows either 32bit or 16bit indices, and 4 (x-y-z-w) or 3 (x-y-z) component vertices.
+///If you want to share triangle/index data between graphics mesh and collision mesh (btBvhTriangleMeshShape), you can directly use btTriangleIndexVertexArray or derive your own class from btStridingMeshInterface.
+///Performance of btTriangleMesh and btTriangleIndexVertexArray used in a btBvhTriangleMeshShape is the same.
+class btTriangleMesh : public btTriangleIndexVertexArray
+{
+ btAlignedObjectArray<btVector3> m_4componentVertices;
+ btAlignedObjectArray<btScalar> m_3componentVertices;
+
+ btAlignedObjectArray<unsigned int> m_32bitIndices;
+ btAlignedObjectArray<unsigned short int> m_16bitIndices;
+ bool m_use32bitIndices;
+ bool m_use4componentVertices;
+
+
+ public:
+ btScalar m_weldingThreshold;
+
+ btTriangleMesh (bool use32bitIndices=true,bool use4componentVertices=true);
+
+ bool getUse32bitIndices() const
+ {
+ return m_use32bitIndices;
+ }
+
+ bool getUse4componentVertices() const
+ {
+ return m_use4componentVertices;
+ }
+ ///By default addTriangle won't search for duplicate vertices, because the search is very slow for large triangle meshes.
+ ///In general it is better to directly use btTriangleIndexVertexArray instead.
+ void addTriangle(const btVector3& vertex0,const btVector3& vertex1,const btVector3& vertex2, bool removeDuplicateVertices=false);
+
+ ///Add a triangle using its indices. Make sure the indices are pointing within the vertices array, so add the vertices first (and to be sure, avoid removal of duplicate vertices)
+ void addTriangleIndices(int index1, int index2, int index3 );
+
+ int getNumTriangles() const;
+
+ virtual void preallocateVertices(int numverts);
+ virtual void preallocateIndices(int numindices);
+
+ ///findOrAddVertex is an internal method, use addTriangle instead
+ int findOrAddVertex(const btVector3& vertex, bool removeDuplicateVertices);
+ ///addIndex is an internal method, use addTriangle instead
+ void addIndex(int index);
+
+};
+
+#endif //BT_TRIANGLE_MESH_H
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp
new file mode 100644
index 0000000000..0e17951405
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp
@@ -0,0 +1,207 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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 "btTriangleMeshShape.h"
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btQuaternion.h"
+#include "btStridingMeshInterface.h"
+#include "LinearMath/btAabbUtil2.h"
+#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
+
+
+btTriangleMeshShape::btTriangleMeshShape(btStridingMeshInterface* meshInterface)
+: btConcaveShape (), m_meshInterface(meshInterface)
+{
+ m_shapeType = TRIANGLE_MESH_SHAPE_PROXYTYPE;
+ if(meshInterface->hasPremadeAabb())
+ {
+ meshInterface->getPremadeAabb(&m_localAabbMin, &m_localAabbMax);
+ }
+ else
+ {
+ recalcLocalAabb();
+ }
+}
+
+
+btTriangleMeshShape::~btTriangleMeshShape()
+{
+
+}
+
+
+
+
+void btTriangleMeshShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const
+{
+
+ btVector3 localHalfExtents = btScalar(0.5)*(m_localAabbMax-m_localAabbMin);
+ localHalfExtents += btVector3(getMargin(),getMargin(),getMargin());
+ btVector3 localCenter = btScalar(0.5)*(m_localAabbMax+m_localAabbMin);
+
+ btMatrix3x3 abs_b = trans.getBasis().absolute();
+
+ btVector3 center = trans(localCenter);
+
+ btVector3 extent = localHalfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
+ aabbMin = center - extent;
+ aabbMax = center + extent;
+}
+
+void btTriangleMeshShape::recalcLocalAabb()
+{
+ for (int i=0;i<3;i++)
+ {
+ btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.));
+ vec[i] = btScalar(1.);
+ btVector3 tmp = localGetSupportingVertex(vec);
+ m_localAabbMax[i] = tmp[i]+m_collisionMargin;
+ vec[i] = btScalar(-1.);
+ tmp = localGetSupportingVertex(vec);
+ m_localAabbMin[i] = tmp[i]-m_collisionMargin;
+ }
+}
+
+
+
+class SupportVertexCallback : public btTriangleCallback
+{
+
+ btVector3 m_supportVertexLocal;
+public:
+
+ btTransform m_worldTrans;
+ btScalar m_maxDot;
+ btVector3 m_supportVecLocal;
+
+ SupportVertexCallback(const btVector3& supportVecWorld,const btTransform& trans)
+ : m_supportVertexLocal(btScalar(0.),btScalar(0.),btScalar(0.)), m_worldTrans(trans) ,m_maxDot(btScalar(-BT_LARGE_FLOAT))
+
+ {
+ m_supportVecLocal = supportVecWorld * m_worldTrans.getBasis();
+ }
+
+ virtual void processTriangle( btVector3* triangle,int partId, int triangleIndex)
+ {
+ (void)partId;
+ (void)triangleIndex;
+ for (int i=0;i<3;i++)
+ {
+ btScalar dot = m_supportVecLocal.dot(triangle[i]);
+ if (dot > m_maxDot)
+ {
+ m_maxDot = dot;
+ m_supportVertexLocal = triangle[i];
+ }
+ }
+ }
+
+ btVector3 GetSupportVertexWorldSpace()
+ {
+ return m_worldTrans(m_supportVertexLocal);
+ }
+
+ btVector3 GetSupportVertexLocal()
+ {
+ return m_supportVertexLocal;
+ }
+
+};
+
+
+void btTriangleMeshShape::setLocalScaling(const btVector3& scaling)
+{
+ m_meshInterface->setScaling(scaling);
+ recalcLocalAabb();
+}
+
+const btVector3& btTriangleMeshShape::getLocalScaling() const
+{
+ return m_meshInterface->getScaling();
+}
+
+
+
+
+
+
+//#define DEBUG_TRIANGLE_MESH
+
+
+
+void btTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
+{
+ struct FilteredCallback : public btInternalTriangleIndexCallback
+ {
+ btTriangleCallback* m_callback;
+ btVector3 m_aabbMin;
+ btVector3 m_aabbMax;
+
+ FilteredCallback(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax)
+ :m_callback(callback),
+ m_aabbMin(aabbMin),
+ m_aabbMax(aabbMax)
+ {
+ }
+
+ virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex)
+ {
+ if (TestTriangleAgainstAabb2(&triangle[0],m_aabbMin,m_aabbMax))
+ {
+ //check aabb in triangle-space, before doing this
+ m_callback->processTriangle(triangle,partId,triangleIndex);
+ }
+
+ }
+
+ };
+
+ FilteredCallback filterCallback(callback,aabbMin,aabbMax);
+
+ m_meshInterface->InternalProcessAllTriangles(&filterCallback,aabbMin,aabbMax);
+}
+
+
+
+
+
+void btTriangleMeshShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+{
+ (void)mass;
+ //moving concave objects not supported
+ btAssert(0);
+ inertia.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
+}
+
+
+btVector3 btTriangleMeshShape::localGetSupportingVertex(const btVector3& vec) const
+{
+ btVector3 supportVertex;
+
+ btTransform ident;
+ ident.setIdentity();
+
+ SupportVertexCallback supportCallback(vec,ident);
+
+ btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
+
+ processAllTriangles(&supportCallback,-aabbMax,aabbMax);
+
+ supportVertex = supportCallback.GetSupportVertexLocal();
+
+ return supportVertex;
+}
+
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h
new file mode 100644
index 0000000000..453e58005a
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h
@@ -0,0 +1,90 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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_TRIANGLE_MESH_SHAPE_H
+#define BT_TRIANGLE_MESH_SHAPE_H
+
+#include "btConcaveShape.h"
+#include "btStridingMeshInterface.h"
+
+
+///The btTriangleMeshShape is an internal concave triangle mesh interface. Don't use this class directly, use btBvhTriangleMeshShape instead.
+ATTRIBUTE_ALIGNED16(class) btTriangleMeshShape : public btConcaveShape
+{
+protected:
+ btVector3 m_localAabbMin;
+ btVector3 m_localAabbMax;
+ btStridingMeshInterface* m_meshInterface;
+
+ ///btTriangleMeshShape constructor has been disabled/protected, so that users will not mistakenly use this class.
+ ///Don't use btTriangleMeshShape but use btBvhTriangleMeshShape instead!
+ btTriangleMeshShape(btStridingMeshInterface* meshInterface);
+
+public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ virtual ~btTriangleMeshShape();
+
+ virtual btVector3 localGetSupportingVertex(const btVector3& vec) const;
+
+ virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const
+ {
+ btAssert(0);
+ return localGetSupportingVertex(vec);
+ }
+
+ void recalcLocalAabb();
+
+ virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+
+ virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
+
+ virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+
+ virtual void setLocalScaling(const btVector3& scaling);
+ virtual const btVector3& getLocalScaling() const;
+
+ btStridingMeshInterface* getMeshInterface()
+ {
+ return m_meshInterface;
+ }
+
+ const btStridingMeshInterface* getMeshInterface() const
+ {
+ return m_meshInterface;
+ }
+
+ const btVector3& getLocalAabbMin() const
+ {
+ return m_localAabbMin;
+ }
+ const btVector3& getLocalAabbMax() const
+ {
+ return m_localAabbMax;
+ }
+
+
+
+ //debugging
+ virtual const char* getName()const {return "TRIANGLEMESH";}
+
+
+
+};
+
+
+
+
+#endif //BT_TRIANGLE_MESH_SHAPE_H
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btTriangleShape.h b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btTriangleShape.h
new file mode 100644
index 0000000000..a8a80f82fe
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btTriangleShape.h
@@ -0,0 +1,184 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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_OBB_TRIANGLE_MINKOWSKI_H
+#define BT_OBB_TRIANGLE_MINKOWSKI_H
+
+#include "btConvexShape.h"
+#include "btBoxShape.h"
+
+ATTRIBUTE_ALIGNED16(class) btTriangleShape : public btPolyhedralConvexShape
+{
+
+
+public:
+
+BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ btVector3 m_vertices1[3];
+
+ virtual int getNumVertices() const
+ {
+ return 3;
+ }
+
+ btVector3& getVertexPtr(int index)
+ {
+ return m_vertices1[index];
+ }
+
+ const btVector3& getVertexPtr(int index) const
+ {
+ return m_vertices1[index];
+ }
+ virtual void getVertex(int index,btVector3& vert) const
+ {
+ vert = m_vertices1[index];
+ }
+
+ virtual int getNumEdges() const
+ {
+ return 3;
+ }
+
+ virtual void getEdge(int i,btVector3& pa,btVector3& pb) const
+ {
+ getVertex(i,pa);
+ getVertex((i+1)%3,pb);
+ }
+
+
+ virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax)const
+ {
+// btAssert(0);
+ getAabbSlow(t,aabbMin,aabbMax);
+ }
+
+ btVector3 localGetSupportingVertexWithoutMargin(const btVector3& dir)const
+ {
+ btVector3 dots = dir.dot3(m_vertices1[0], m_vertices1[1], m_vertices1[2]);
+ return m_vertices1[dots.maxAxis()];
+
+ }
+
+ virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+ {
+ for (int i=0;i<numVectors;i++)
+ {
+ const btVector3& dir = vectors[i];
+ btVector3 dots = dir.dot3(m_vertices1[0], m_vertices1[1], m_vertices1[2]);
+ supportVerticesOut[i] = m_vertices1[dots.maxAxis()];
+ }
+
+ }
+
+ btTriangleShape() : btPolyhedralConvexShape ()
+ {
+ m_shapeType = TRIANGLE_SHAPE_PROXYTYPE;
+ }
+
+ btTriangleShape(const btVector3& p0,const btVector3& p1,const btVector3& p2) : btPolyhedralConvexShape ()
+ {
+ m_shapeType = TRIANGLE_SHAPE_PROXYTYPE;
+ m_vertices1[0] = p0;
+ m_vertices1[1] = p1;
+ m_vertices1[2] = p2;
+ }
+
+
+ virtual void getPlane(btVector3& planeNormal,btVector3& planeSupport,int i) const
+ {
+ getPlaneEquation(i,planeNormal,planeSupport);
+ }
+
+ virtual int getNumPlanes() const
+ {
+ return 1;
+ }
+
+ void calcNormal(btVector3& normal) const
+ {
+ normal = (m_vertices1[1]-m_vertices1[0]).cross(m_vertices1[2]-m_vertices1[0]);
+ normal.normalize();
+ }
+
+ virtual void getPlaneEquation(int i, btVector3& planeNormal,btVector3& planeSupport) const
+ {
+ (void)i;
+ calcNormal(planeNormal);
+ planeSupport = m_vertices1[0];
+ }
+
+ virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const
+ {
+ (void)mass;
+ btAssert(0);
+ inertia.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
+ }
+
+ virtual bool isInside(const btVector3& pt,btScalar tolerance) const
+ {
+ btVector3 normal;
+ calcNormal(normal);
+ //distance to plane
+ btScalar dist = pt.dot(normal);
+ btScalar planeconst = m_vertices1[0].dot(normal);
+ dist -= planeconst;
+ if (dist >= -tolerance && dist <= tolerance)
+ {
+ //inside check on edge-planes
+ int i;
+ for (i=0;i<3;i++)
+ {
+ btVector3 pa,pb;
+ getEdge(i,pa,pb);
+ btVector3 edge = pb-pa;
+ btVector3 edgeNormal = edge.cross(normal);
+ edgeNormal.normalize();
+ btScalar dist = pt.dot( edgeNormal);
+ btScalar edgeConst = pa.dot(edgeNormal);
+ dist -= edgeConst;
+ if (dist < -tolerance)
+ return false;
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+ //debugging
+ virtual const char* getName()const
+ {
+ return "Triangle";
+ }
+
+ virtual int getNumPreferredPenetrationDirections() const
+ {
+ return 2;
+ }
+
+ virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const
+ {
+ calcNormal(penetrationVector);
+ if (index)
+ penetrationVector *= btScalar(-1.);
+ }
+
+
+};
+
+#endif //BT_OBB_TRIANGLE_MINKOWSKI_H
+
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btUniformScalingShape.cpp b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btUniformScalingShape.cpp
new file mode 100644
index 0000000000..b148bbd99a
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btUniformScalingShape.cpp
@@ -0,0 +1,160 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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 "btUniformScalingShape.h"
+
+btUniformScalingShape::btUniformScalingShape( btConvexShape* convexChildShape,btScalar uniformScalingFactor):
+btConvexShape (), m_childConvexShape(convexChildShape),
+m_uniformScalingFactor(uniformScalingFactor)
+{
+ m_shapeType = UNIFORM_SCALING_SHAPE_PROXYTYPE;
+}
+
+btUniformScalingShape::~btUniformScalingShape()
+{
+}
+
+
+btVector3 btUniformScalingShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const
+{
+ btVector3 tmpVertex;
+ tmpVertex = m_childConvexShape->localGetSupportingVertexWithoutMargin(vec);
+ return tmpVertex*m_uniformScalingFactor;
+}
+
+void btUniformScalingShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+{
+ m_childConvexShape->batchedUnitVectorGetSupportingVertexWithoutMargin(vectors,supportVerticesOut,numVectors);
+ int i;
+ for (i=0;i<numVectors;i++)
+ {
+ supportVerticesOut[i] = supportVerticesOut[i] * m_uniformScalingFactor;
+ }
+}
+
+
+btVector3 btUniformScalingShape::localGetSupportingVertex(const btVector3& vec)const
+{
+ btVector3 tmpVertex;
+ tmpVertex = m_childConvexShape->localGetSupportingVertex(vec);
+ return tmpVertex*m_uniformScalingFactor;
+}
+
+
+void btUniformScalingShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+{
+
+ ///this linear upscaling is not realistic, but we don't deal with large mass ratios...
+ btVector3 tmpInertia;
+ m_childConvexShape->calculateLocalInertia(mass,tmpInertia);
+ inertia = tmpInertia * m_uniformScalingFactor;
+}
+
+
+ ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
+void btUniformScalingShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const
+{
+ getAabbSlow(trans,aabbMin,aabbMax);
+
+}
+
+void btUniformScalingShape::getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+{
+#if 1
+ btVector3 _directions[] =
+ {
+ btVector3( 1., 0., 0.),
+ btVector3( 0., 1., 0.),
+ btVector3( 0., 0., 1.),
+ btVector3( -1., 0., 0.),
+ btVector3( 0., -1., 0.),
+ btVector3( 0., 0., -1.)
+ };
+
+ btVector3 _supporting[] =
+ {
+ btVector3( 0., 0., 0.),
+ btVector3( 0., 0., 0.),
+ btVector3( 0., 0., 0.),
+ btVector3( 0., 0., 0.),
+ btVector3( 0., 0., 0.),
+ btVector3( 0., 0., 0.)
+ };
+
+ for (int i=0;i<6;i++)
+ {
+ _directions[i] = _directions[i]*t.getBasis();
+ }
+
+ batchedUnitVectorGetSupportingVertexWithoutMargin(_directions, _supporting, 6);
+
+ btVector3 aabbMin1(0,0,0),aabbMax1(0,0,0);
+
+ for ( int i = 0; i < 3; ++i )
+ {
+ aabbMax1[i] = t(_supporting[i])[i];
+ aabbMin1[i] = t(_supporting[i + 3])[i];
+ }
+ btVector3 marginVec(getMargin(),getMargin(),getMargin());
+ aabbMin = aabbMin1-marginVec;
+ aabbMax = aabbMax1+marginVec;
+
+#else
+
+ btScalar margin = getMargin();
+ for (int i=0;i<3;i++)
+ {
+ btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.));
+ vec[i] = btScalar(1.);
+ btVector3 sv = localGetSupportingVertex(vec*t.getBasis());
+ btVector3 tmp = t(sv);
+ aabbMax[i] = tmp[i]+margin;
+ vec[i] = btScalar(-1.);
+ sv = localGetSupportingVertex(vec*t.getBasis());
+ tmp = t(sv);
+ aabbMin[i] = tmp[i]-margin;
+ }
+
+#endif
+}
+
+void btUniformScalingShape::setLocalScaling(const btVector3& scaling)
+{
+ m_childConvexShape->setLocalScaling(scaling);
+}
+
+const btVector3& btUniformScalingShape::getLocalScaling() const
+{
+ return m_childConvexShape->getLocalScaling();
+}
+
+void btUniformScalingShape::setMargin(btScalar margin)
+{
+ m_childConvexShape->setMargin(margin);
+}
+btScalar btUniformScalingShape::getMargin() const
+{
+ return m_childConvexShape->getMargin() * m_uniformScalingFactor;
+}
+
+int btUniformScalingShape::getNumPreferredPenetrationDirections() const
+{
+ return m_childConvexShape->getNumPreferredPenetrationDirections();
+}
+
+void btUniformScalingShape::getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const
+{
+ m_childConvexShape->getPreferredPenetrationDirection(index,penetrationVector);
+}
diff --git a/thirdparty/bullet/src/BulletCollision/CollisionShapes/btUniformScalingShape.h b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btUniformScalingShape.h
new file mode 100644
index 0000000000..a10f58d242
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/CollisionShapes/btUniformScalingShape.h
@@ -0,0 +1,89 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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_UNIFORM_SCALING_SHAPE_H
+#define BT_UNIFORM_SCALING_SHAPE_H
+
+#include "btConvexShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
+
+///The btUniformScalingShape allows to re-use uniform scaled instances of btConvexShape in a memory efficient way.
+///Istead of using btUniformScalingShape, it is better to use the non-uniform setLocalScaling method on convex shapes that implement it.
+ATTRIBUTE_ALIGNED16(class) btUniformScalingShape : public btConvexShape
+{
+ btConvexShape* m_childConvexShape;
+
+ btScalar m_uniformScalingFactor;
+
+ public:
+
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ btUniformScalingShape( btConvexShape* convexChildShape, btScalar uniformScalingFactor);
+
+ virtual ~btUniformScalingShape();
+
+ virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
+
+ virtual btVector3 localGetSupportingVertex(const btVector3& vec)const;
+
+ virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
+
+ virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+
+ btScalar getUniformScalingFactor() const
+ {
+ return m_uniformScalingFactor;
+ }
+
+ btConvexShape* getChildShape()
+ {
+ return m_childConvexShape;
+ }
+
+ const btConvexShape* getChildShape() const
+ {
+ return m_childConvexShape;
+ }
+
+ virtual const char* getName()const
+ {
+ return "UniformScalingShape";
+ }
+
+
+
+ ///////////////////////////
+
+
+ ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
+ void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+
+ virtual void getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+
+ virtual void setLocalScaling(const btVector3& scaling) ;
+ virtual const btVector3& getLocalScaling() const ;
+
+ virtual void setMargin(btScalar margin);
+ virtual btScalar getMargin() const;
+
+ virtual int getNumPreferredPenetrationDirections() const;
+
+ virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const;
+
+
+};
+
+#endif //BT_UNIFORM_SCALING_SHAPE_H
diff --git a/thirdparty/bullet/src/BulletCollision/Gimpact/btBoxCollision.h b/thirdparty/bullet/src/BulletCollision/Gimpact/btBoxCollision.h
new file mode 100644
index 0000000000..0a0357e5a8
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/Gimpact/btBoxCollision.h
@@ -0,0 +1,645 @@
+#ifndef BT_BOX_COLLISION_H_INCLUDED
+#define BT_BOX_COLLISION_H_INCLUDED
+
+/*! \file gim_box_collision.h
+\author Francisco Leon Najera
+*/
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+
+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 "LinearMath/btTransform.h"
+
+
+///Swap numbers
+#define BT_SWAP_NUMBERS(a,b){ \
+ a = a+b; \
+ b = a-b; \
+ a = a-b; \
+}\
+
+
+#define BT_MAX(a,b) (a<b?b:a)
+#define BT_MIN(a,b) (a>b?b:a)
+
+#define BT_GREATER(x, y) btFabs(x) > (y)
+
+#define BT_MAX3(a,b,c) BT_MAX(a,BT_MAX(b,c))
+#define BT_MIN3(a,b,c) BT_MIN(a,BT_MIN(b,c))
+
+
+
+
+
+
+enum eBT_PLANE_INTERSECTION_TYPE
+{
+ BT_CONST_BACK_PLANE = 0,
+ BT_CONST_COLLIDE_PLANE,
+ BT_CONST_FRONT_PLANE
+};
+
+//SIMD_FORCE_INLINE bool test_cross_edge_box(
+// const btVector3 & edge,
+// const btVector3 & absolute_edge,
+// const btVector3 & pointa,
+// const btVector3 & pointb, const btVector3 & extend,
+// int dir_index0,
+// int dir_index1
+// int component_index0,
+// int component_index1)
+//{
+// // dir coords are -z and y
+//
+// const btScalar dir0 = -edge[dir_index0];
+// const btScalar dir1 = edge[dir_index1];
+// btScalar pmin = pointa[component_index0]*dir0 + pointa[component_index1]*dir1;
+// btScalar pmax = pointb[component_index0]*dir0 + pointb[component_index1]*dir1;
+// //find minmax
+// if(pmin>pmax)
+// {
+// BT_SWAP_NUMBERS(pmin,pmax);
+// }
+// //find extends
+// const btScalar rad = extend[component_index0] * absolute_edge[dir_index0] +
+// extend[component_index1] * absolute_edge[dir_index1];
+//
+// if(pmin>rad || -rad>pmax) return false;
+// return true;
+//}
+//
+//SIMD_FORCE_INLINE bool test_cross_edge_box_X_axis(
+// const btVector3 & edge,
+// const btVector3 & absolute_edge,
+// const btVector3 & pointa,
+// const btVector3 & pointb, btVector3 & extend)
+//{
+//
+// return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,2,1,1,2);
+//}
+//
+//
+//SIMD_FORCE_INLINE bool test_cross_edge_box_Y_axis(
+// const btVector3 & edge,
+// const btVector3 & absolute_edge,
+// const btVector3 & pointa,
+// const btVector3 & pointb, btVector3 & extend)
+//{
+//
+// return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,0,2,2,0);
+//}
+//
+//SIMD_FORCE_INLINE bool test_cross_edge_box_Z_axis(
+// const btVector3 & edge,
+// const btVector3 & absolute_edge,
+// const btVector3 & pointa,
+// const btVector3 & pointb, btVector3 & extend)
+//{
+//
+// return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,1,0,0,1);
+//}
+
+
+#define TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,i_dir_0,i_dir_1,i_comp_0,i_comp_1)\
+{\
+ const btScalar dir0 = -edge[i_dir_0];\
+ const btScalar dir1 = edge[i_dir_1];\
+ btScalar pmin = pointa[i_comp_0]*dir0 + pointa[i_comp_1]*dir1;\
+ btScalar pmax = pointb[i_comp_0]*dir0 + pointb[i_comp_1]*dir1;\
+ if(pmin>pmax)\
+ {\
+ BT_SWAP_NUMBERS(pmin,pmax); \
+ }\
+ const btScalar abs_dir0 = absolute_edge[i_dir_0];\
+ const btScalar abs_dir1 = absolute_edge[i_dir_1];\
+ const btScalar rad = _extend[i_comp_0] * abs_dir0 + _extend[i_comp_1] * abs_dir1;\
+ if(pmin>rad || -rad>pmax) return false;\
+}\
+
+
+#define TEST_CROSS_EDGE_BOX_X_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\
+{\
+ TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,2,1,1,2);\
+}\
+
+#define TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\
+{\
+ TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,0,2,2,0);\
+}\
+
+#define TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\
+{\
+ TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,1,0,0,1);\
+}\
+
+
+//! Returns the dot product between a vec3f and the col of a matrix
+SIMD_FORCE_INLINE btScalar bt_mat3_dot_col(
+const btMatrix3x3 & mat, const btVector3 & vec3, int colindex)
+{
+ return vec3[0]*mat[0][colindex] + vec3[1]*mat[1][colindex] + vec3[2]*mat[2][colindex];
+}
+
+
+//! Class for transforming a model1 to the space of model0
+ATTRIBUTE_ALIGNED16 (class) BT_BOX_BOX_TRANSFORM_CACHE
+{
+public:
+ btVector3 m_T1to0;//!< Transforms translation of model1 to model 0
+ btMatrix3x3 m_R1to0;//!< Transforms Rotation of model1 to model 0, equal to R0' * R1
+ btMatrix3x3 m_AR;//!< Absolute value of m_R1to0
+
+ SIMD_FORCE_INLINE void calc_absolute_matrix()
+ {
+// static const btVector3 vepsi(1e-6f,1e-6f,1e-6f);
+// m_AR[0] = vepsi + m_R1to0[0].absolute();
+// m_AR[1] = vepsi + m_R1to0[1].absolute();
+// m_AR[2] = vepsi + m_R1to0[2].absolute();
+
+ int i,j;
+
+ for(i=0;i<3;i++)
+ {
+ for(j=0;j<3;j++ )
+ {
+ m_AR[i][j] = 1e-6f + btFabs(m_R1to0[i][j]);
+ }
+ }
+
+ }
+
+ BT_BOX_BOX_TRANSFORM_CACHE()
+ {
+ }
+
+
+
+ //! Calc the transformation relative 1 to 0. Inverts matrics by transposing
+ SIMD_FORCE_INLINE void calc_from_homogenic(const btTransform & trans0,const btTransform & trans1)
+ {
+
+ btTransform temp_trans = trans0.inverse();
+ temp_trans = temp_trans * trans1;
+
+ m_T1to0 = temp_trans.getOrigin();
+ m_R1to0 = temp_trans.getBasis();
+
+
+ calc_absolute_matrix();
+ }
+
+ //! Calcs the full invertion of the matrices. Useful for scaling matrices
+ SIMD_FORCE_INLINE void calc_from_full_invert(const btTransform & trans0,const btTransform & trans1)
+ {
+ m_R1to0 = trans0.getBasis().inverse();
+ m_T1to0 = m_R1to0 * (-trans0.getOrigin());
+
+ m_T1to0 += m_R1to0*trans1.getOrigin();
+ m_R1to0 *= trans1.getBasis();
+
+ calc_absolute_matrix();
+ }
+
+ SIMD_FORCE_INLINE btVector3 transform(const btVector3 & point) const
+ {
+ return point.dot3( m_R1to0[0], m_R1to0[1], m_R1to0[2] ) + m_T1to0;
+ }
+};
+
+
+#define BOX_PLANE_EPSILON 0.000001f
+
+//! Axis aligned box
+ATTRIBUTE_ALIGNED16 (class) btAABB
+{
+public:
+ btVector3 m_min;
+ btVector3 m_max;
+
+ btAABB()
+ {}
+
+
+ btAABB(const btVector3 & V1,
+ const btVector3 & V2,
+ const btVector3 & V3)
+ {
+ m_min[0] = BT_MIN3(V1[0],V2[0],V3[0]);
+ m_min[1] = BT_MIN3(V1[1],V2[1],V3[1]);
+ m_min[2] = BT_MIN3(V1[2],V2[2],V3[2]);
+
+ m_max[0] = BT_MAX3(V1[0],V2[0],V3[0]);
+ m_max[1] = BT_MAX3(V1[1],V2[1],V3[1]);
+ m_max[2] = BT_MAX3(V1[2],V2[2],V3[2]);
+ }
+
+ btAABB(const btVector3 & V1,
+ const btVector3 & V2,
+ const btVector3 & V3,
+ btScalar margin)
+ {
+ m_min[0] = BT_MIN3(V1[0],V2[0],V3[0]);
+ m_min[1] = BT_MIN3(V1[1],V2[1],V3[1]);
+ m_min[2] = BT_MIN3(V1[2],V2[2],V3[2]);
+
+ m_max[0] = BT_MAX3(V1[0],V2[0],V3[0]);
+ m_max[1] = BT_MAX3(V1[1],V2[1],V3[1]);
+ m_max[2] = BT_MAX3(V1[2],V2[2],V3[2]);
+
+ m_min[0] -= margin;
+ m_min[1] -= margin;
+ m_min[2] -= margin;
+ m_max[0] += margin;
+ m_max[1] += margin;
+ m_max[2] += margin;
+ }
+
+ btAABB(const btAABB &other):
+ m_min(other.m_min),m_max(other.m_max)
+ {
+ }
+
+ btAABB(const btAABB &other,btScalar margin ):
+ m_min(other.m_min),m_max(other.m_max)
+ {
+ m_min[0] -= margin;
+ m_min[1] -= margin;
+ m_min[2] -= margin;
+ m_max[0] += margin;
+ m_max[1] += margin;
+ m_max[2] += margin;
+ }
+
+ SIMD_FORCE_INLINE void invalidate()
+ {
+ m_min[0] = SIMD_INFINITY;
+ m_min[1] = SIMD_INFINITY;
+ m_min[2] = SIMD_INFINITY;
+ m_max[0] = -SIMD_INFINITY;
+ m_max[1] = -SIMD_INFINITY;
+ m_max[2] = -SIMD_INFINITY;
+ }
+
+ SIMD_FORCE_INLINE void increment_margin(btScalar margin)
+ {
+ m_min[0] -= margin;
+ m_min[1] -= margin;
+ m_min[2] -= margin;
+ m_max[0] += margin;
+ m_max[1] += margin;
+ m_max[2] += margin;
+ }
+
+ SIMD_FORCE_INLINE void copy_with_margin(const btAABB &other, btScalar margin)
+ {
+ m_min[0] = other.m_min[0] - margin;
+ m_min[1] = other.m_min[1] - margin;
+ m_min[2] = other.m_min[2] - margin;
+
+ m_max[0] = other.m_max[0] + margin;
+ m_max[1] = other.m_max[1] + margin;
+ m_max[2] = other.m_max[2] + margin;
+ }
+
+ template<typename CLASS_POINT>
+ SIMD_FORCE_INLINE void calc_from_triangle(
+ const CLASS_POINT & V1,
+ const CLASS_POINT & V2,
+ const CLASS_POINT & V3)
+ {
+ m_min[0] = BT_MIN3(V1[0],V2[0],V3[0]);
+ m_min[1] = BT_MIN3(V1[1],V2[1],V3[1]);
+ m_min[2] = BT_MIN3(V1[2],V2[2],V3[2]);
+
+ m_max[0] = BT_MAX3(V1[0],V2[0],V3[0]);
+ m_max[1] = BT_MAX3(V1[1],V2[1],V3[1]);
+ m_max[2] = BT_MAX3(V1[2],V2[2],V3[2]);
+ }
+
+ template<typename CLASS_POINT>
+ SIMD_FORCE_INLINE void calc_from_triangle_margin(
+ const CLASS_POINT & V1,
+ const CLASS_POINT & V2,
+ const CLASS_POINT & V3, btScalar margin)
+ {
+ m_min[0] = BT_MIN3(V1[0],V2[0],V3[0]);
+ m_min[1] = BT_MIN3(V1[1],V2[1],V3[1]);
+ m_min[2] = BT_MIN3(V1[2],V2[2],V3[2]);
+
+ m_max[0] = BT_MAX3(V1[0],V2[0],V3[0]);
+ m_max[1] = BT_MAX3(V1[1],V2[1],V3[1]);
+ m_max[2] = BT_MAX3(V1[2],V2[2],V3[2]);
+
+ m_min[0] -= margin;
+ m_min[1] -= margin;
+ m_min[2] -= margin;
+ m_max[0] += margin;
+ m_max[1] += margin;
+ m_max[2] += margin;
+ }
+
+ //! Apply a transform to an AABB
+ SIMD_FORCE_INLINE void appy_transform(const btTransform & trans)
+ {
+ btVector3 center = (m_max+m_min)*0.5f;
+ btVector3 extends = m_max - center;
+ // Compute new center
+ center = trans(center);
+
+ btVector3 textends = extends.dot3(trans.getBasis().getRow(0).absolute(),
+ trans.getBasis().getRow(1).absolute(),
+ trans.getBasis().getRow(2).absolute());
+
+ m_min = center - textends;
+ m_max = center + textends;
+ }
+
+
+ //! Apply a transform to an AABB
+ SIMD_FORCE_INLINE void appy_transform_trans_cache(const BT_BOX_BOX_TRANSFORM_CACHE & trans)
+ {
+ btVector3 center = (m_max+m_min)*0.5f;
+ btVector3 extends = m_max - center;
+ // Compute new center
+ center = trans.transform(center);
+
+ btVector3 textends = extends.dot3(trans.m_R1to0.getRow(0).absolute(),
+ trans.m_R1to0.getRow(1).absolute(),
+ trans.m_R1to0.getRow(2).absolute());
+
+ m_min = center - textends;
+ m_max = center + textends;
+ }
+
+ //! Merges a Box
+ SIMD_FORCE_INLINE void merge(const btAABB & box)
+ {
+ m_min[0] = BT_MIN(m_min[0],box.m_min[0]);
+ m_min[1] = BT_MIN(m_min[1],box.m_min[1]);
+ m_min[2] = BT_MIN(m_min[2],box.m_min[2]);
+
+ m_max[0] = BT_MAX(m_max[0],box.m_max[0]);
+ m_max[1] = BT_MAX(m_max[1],box.m_max[1]);
+ m_max[2] = BT_MAX(m_max[2],box.m_max[2]);
+ }
+
+ //! Merges a point
+ template<typename CLASS_POINT>
+ SIMD_FORCE_INLINE void merge_point(const CLASS_POINT & point)
+ {
+ m_min[0] = BT_MIN(m_min[0],point[0]);
+ m_min[1] = BT_MIN(m_min[1],point[1]);
+ m_min[2] = BT_MIN(m_min[2],point[2]);
+
+ m_max[0] = BT_MAX(m_max[0],point[0]);
+ m_max[1] = BT_MAX(m_max[1],point[1]);
+ m_max[2] = BT_MAX(m_max[2],point[2]);
+ }
+
+ //! Gets the extend and center
+ SIMD_FORCE_INLINE void get_center_extend(btVector3 & center,btVector3 & extend) const
+ {
+ center = (m_max+m_min)*0.5f;
+ extend = m_max - center;
+ }
+
+ //! Finds the intersecting box between this box and the other.
+ SIMD_FORCE_INLINE void find_intersection(const btAABB & other, btAABB & intersection) const
+ {
+ intersection.m_min[0] = BT_MAX(other.m_min[0],m_min[0]);
+ intersection.m_min[1] = BT_MAX(other.m_min[1],m_min[1]);
+ intersection.m_min[2] = BT_MAX(other.m_min[2],m_min[2]);
+
+ intersection.m_max[0] = BT_MIN(other.m_max[0],m_max[0]);
+ intersection.m_max[1] = BT_MIN(other.m_max[1],m_max[1]);
+ intersection.m_max[2] = BT_MIN(other.m_max[2],m_max[2]);
+ }
+
+
+ SIMD_FORCE_INLINE bool has_collision(const btAABB & other) const
+ {
+ if(m_min[0] > other.m_max[0] ||
+ m_max[0] < other.m_min[0] ||
+ m_min[1] > other.m_max[1] ||
+ m_max[1] < other.m_min[1] ||
+ m_min[2] > other.m_max[2] ||
+ m_max[2] < other.m_min[2])
+ {
+ return false;
+ }
+ return true;
+ }
+
+ /*! \brief Finds the Ray intersection parameter.
+ \param aabb Aligned box
+ \param vorigin A vec3f with the origin of the ray
+ \param vdir A vec3f with the direction of the ray
+ */
+ SIMD_FORCE_INLINE bool collide_ray(const btVector3 & vorigin,const btVector3 & vdir) const
+ {
+ btVector3 extents,center;
+ this->get_center_extend(center,extents);;
+
+ btScalar Dx = vorigin[0] - center[0];
+ if(BT_GREATER(Dx, extents[0]) && Dx*vdir[0]>=0.0f) return false;
+ btScalar Dy = vorigin[1] - center[1];
+ if(BT_GREATER(Dy, extents[1]) && Dy*vdir[1]>=0.0f) return false;
+ btScalar Dz = vorigin[2] - center[2];
+ if(BT_GREATER(Dz, extents[2]) && Dz*vdir[2]>=0.0f) return false;
+
+
+ btScalar f = vdir[1] * Dz - vdir[2] * Dy;
+ if(btFabs(f) > extents[1]*btFabs(vdir[2]) + extents[2]*btFabs(vdir[1])) return false;
+ f = vdir[2] * Dx - vdir[0] * Dz;
+ if(btFabs(f) > extents[0]*btFabs(vdir[2]) + extents[2]*btFabs(vdir[0]))return false;
+ f = vdir[0] * Dy - vdir[1] * Dx;
+ if(btFabs(f) > extents[0]*btFabs(vdir[1]) + extents[1]*btFabs(vdir[0]))return false;
+ return true;
+ }
+
+
+ SIMD_FORCE_INLINE void projection_interval(const btVector3 & direction, btScalar &vmin, btScalar &vmax) const
+ {
+ btVector3 center = (m_max+m_min)*0.5f;
+ btVector3 extend = m_max-center;
+
+ btScalar _fOrigin = direction.dot(center);
+ btScalar _fMaximumExtent = extend.dot(direction.absolute());
+ vmin = _fOrigin - _fMaximumExtent;
+ vmax = _fOrigin + _fMaximumExtent;
+ }
+
+ SIMD_FORCE_INLINE eBT_PLANE_INTERSECTION_TYPE plane_classify(const btVector4 &plane) const
+ {
+ btScalar _fmin,_fmax;
+ this->projection_interval(plane,_fmin,_fmax);
+
+ if(plane[3] > _fmax + BOX_PLANE_EPSILON)
+ {
+ return BT_CONST_BACK_PLANE; // 0
+ }
+
+ if(plane[3]+BOX_PLANE_EPSILON >=_fmin)
+ {
+ return BT_CONST_COLLIDE_PLANE; //1
+ }
+ return BT_CONST_FRONT_PLANE;//2
+ }
+
+ SIMD_FORCE_INLINE bool overlapping_trans_conservative(const btAABB & box, btTransform & trans1_to_0) const
+ {
+ btAABB tbox = box;
+ tbox.appy_transform(trans1_to_0);
+ return has_collision(tbox);
+ }
+
+ SIMD_FORCE_INLINE bool overlapping_trans_conservative2(const btAABB & box,
+ const BT_BOX_BOX_TRANSFORM_CACHE & trans1_to_0) const
+ {
+ btAABB tbox = box;
+ tbox.appy_transform_trans_cache(trans1_to_0);
+ return has_collision(tbox);
+ }
+
+ //! transcache is the transformation cache from box to this AABB
+ SIMD_FORCE_INLINE bool overlapping_trans_cache(
+ const btAABB & box,const BT_BOX_BOX_TRANSFORM_CACHE & transcache, bool fulltest) const
+ {
+
+ //Taken from OPCODE
+ btVector3 ea,eb;//extends
+ btVector3 ca,cb;//extends
+ get_center_extend(ca,ea);
+ box.get_center_extend(cb,eb);
+
+
+ btVector3 T;
+ btScalar t,t2;
+ int i;
+
+ // Class I : A's basis vectors
+ for(i=0;i<3;i++)
+ {
+ T[i] = transcache.m_R1to0[i].dot(cb) + transcache.m_T1to0[i] - ca[i];
+ t = transcache.m_AR[i].dot(eb) + ea[i];
+ if(BT_GREATER(T[i], t)) return false;
+ }
+ // Class II : B's basis vectors
+ for(i=0;i<3;i++)
+ {
+ t = bt_mat3_dot_col(transcache.m_R1to0,T,i);
+ t2 = bt_mat3_dot_col(transcache.m_AR,ea,i) + eb[i];
+ if(BT_GREATER(t,t2)) return false;
+ }
+ // Class III : 9 cross products
+ if(fulltest)
+ {
+ int j,m,n,o,p,q,r;
+ for(i=0;i<3;i++)
+ {
+ m = (i+1)%3;
+ n = (i+2)%3;
+ o = i==0?1:0;
+ p = i==2?1:2;
+ for(j=0;j<3;j++)
+ {
+ q = j==2?1:2;
+ r = j==0?1:0;
+ t = T[n]*transcache.m_R1to0[m][j] - T[m]*transcache.m_R1to0[n][j];
+ t2 = ea[o]*transcache.m_AR[p][j] + ea[p]*transcache.m_AR[o][j] +
+ eb[r]*transcache.m_AR[i][q] + eb[q]*transcache.m_AR[i][r];
+ if(BT_GREATER(t,t2)) return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ //! Simple test for planes.
+ SIMD_FORCE_INLINE bool collide_plane(
+ const btVector4 & plane) const
+ {
+ eBT_PLANE_INTERSECTION_TYPE classify = plane_classify(plane);
+ return (classify == BT_CONST_COLLIDE_PLANE);
+ }
+
+ //! test for a triangle, with edges
+ SIMD_FORCE_INLINE bool collide_triangle_exact(
+ const btVector3 & p1,
+ const btVector3 & p2,
+ const btVector3 & p3,
+ const btVector4 & triangle_plane) const
+ {
+ if(!collide_plane(triangle_plane)) return false;
+
+ btVector3 center,extends;
+ this->get_center_extend(center,extends);
+
+ const btVector3 v1(p1 - center);
+ const btVector3 v2(p2 - center);
+ const btVector3 v3(p3 - center);
+
+ //First axis
+ btVector3 diff(v2 - v1);
+ btVector3 abs_diff = diff.absolute();
+ //Test With X axis
+ TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v1,v3,extends);
+ //Test With Y axis
+ TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v1,v3,extends);
+ //Test With Z axis
+ TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v1,v3,extends);
+
+
+ diff = v3 - v2;
+ abs_diff = diff.absolute();
+ //Test With X axis
+ TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v2,v1,extends);
+ //Test With Y axis
+ TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v2,v1,extends);
+ //Test With Z axis
+ TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v2,v1,extends);
+
+ diff = v1 - v3;
+ abs_diff = diff.absolute();
+ //Test With X axis
+ TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v3,v2,extends);
+ //Test With Y axis
+ TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v3,v2,extends);
+ //Test With Z axis
+ TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v3,v2,extends);
+
+ return true;
+ }
+};
+
+
+//! Compairison of transformation objects
+SIMD_FORCE_INLINE bool btCompareTransformsEqual(const btTransform & t1,const btTransform & t2)
+{
+ if(!(t1.getOrigin() == t2.getOrigin()) ) return false;
+
+ if(!(t1.getBasis().getRow(0) == t2.getBasis().getRow(0)) ) return false;
+ if(!(t1.getBasis().getRow(1) == t2.getBasis().getRow(1)) ) return false;
+ if(!(t1.getBasis().getRow(2) == t2.getBasis().getRow(2)) ) return false;
+ return true;
+}
+
+
+
+#endif // GIM_BOX_COLLISION_H_INCLUDED
diff --git a/thirdparty/bullet/src/BulletCollision/Gimpact/btClipPolygon.h b/thirdparty/bullet/src/BulletCollision/Gimpact/btClipPolygon.h
new file mode 100644
index 0000000000..de0a5231ba
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/Gimpact/btClipPolygon.h
@@ -0,0 +1,182 @@
+#ifndef BT_CLIP_POLYGON_H_INCLUDED
+#define BT_CLIP_POLYGON_H_INCLUDED
+
+/*! \file btClipPolygon.h
+\author Francisco Leon Najera
+*/
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+
+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 "LinearMath/btTransform.h"
+#include "LinearMath/btGeometryUtil.h"
+
+
+SIMD_FORCE_INLINE btScalar bt_distance_point_plane(const btVector4 & plane,const btVector3 &point)
+{
+ return point.dot(plane) - plane[3];
+}
+
+/*! Vector blending
+Takes two vectors a, b, blends them together*/
+SIMD_FORCE_INLINE void bt_vec_blend(btVector3 &vr, const btVector3 &va,const btVector3 &vb, btScalar blend_factor)
+{
+ vr = (1-blend_factor)*va + blend_factor*vb;
+}
+
+//! This function calcs the distance from a 3D plane
+SIMD_FORCE_INLINE void bt_plane_clip_polygon_collect(
+ const btVector3 & point0,
+ const btVector3 & point1,
+ btScalar dist0,
+ btScalar dist1,
+ btVector3 * clipped,
+ int & clipped_count)
+{
+ bool _prevclassif = (dist0>SIMD_EPSILON);
+ bool _classif = (dist1>SIMD_EPSILON);
+ if(_classif!=_prevclassif)
+ {
+ btScalar blendfactor = -dist0/(dist1-dist0);
+ bt_vec_blend(clipped[clipped_count],point0,point1,blendfactor);
+ clipped_count++;
+ }
+ if(!_classif)
+ {
+ clipped[clipped_count] = point1;
+ clipped_count++;
+ }
+}
+
+
+//! Clips a polygon by a plane
+/*!
+*\return The count of the clipped counts
+*/
+SIMD_FORCE_INLINE int bt_plane_clip_polygon(
+ const btVector4 & plane,
+ const btVector3 * polygon_points,
+ int polygon_point_count,
+ btVector3 * clipped)
+{
+ int clipped_count = 0;
+
+
+ //clip first point
+ btScalar firstdist = bt_distance_point_plane(plane,polygon_points[0]);;
+ if(!(firstdist>SIMD_EPSILON))
+ {
+ clipped[clipped_count] = polygon_points[0];
+ clipped_count++;
+ }
+
+ btScalar olddist = firstdist;
+ for(int i=1;i<polygon_point_count;i++)
+ {
+ btScalar dist = bt_distance_point_plane(plane,polygon_points[i]);
+
+ bt_plane_clip_polygon_collect(
+ polygon_points[i-1],polygon_points[i],
+ olddist,
+ dist,
+ clipped,
+ clipped_count);
+
+
+ olddist = dist;
+ }
+
+ //RETURN TO FIRST point
+
+ bt_plane_clip_polygon_collect(
+ polygon_points[polygon_point_count-1],polygon_points[0],
+ olddist,
+ firstdist,
+ clipped,
+ clipped_count);
+
+ return clipped_count;
+}
+
+//! Clips a polygon by a plane
+/*!
+*\param clipped must be an array of 16 points.
+*\return The count of the clipped counts
+*/
+SIMD_FORCE_INLINE int bt_plane_clip_triangle(
+ const btVector4 & plane,
+ const btVector3 & point0,
+ const btVector3 & point1,
+ const btVector3& point2,
+ btVector3 * clipped // an allocated array of 16 points at least
+ )
+{
+ int clipped_count = 0;
+
+ //clip first point0
+ btScalar firstdist = bt_distance_point_plane(plane,point0);;
+ if(!(firstdist>SIMD_EPSILON))
+ {
+ clipped[clipped_count] = point0;
+ clipped_count++;
+ }
+
+ // point 1
+ btScalar olddist = firstdist;
+ btScalar dist = bt_distance_point_plane(plane,point1);
+
+ bt_plane_clip_polygon_collect(
+ point0,point1,
+ olddist,
+ dist,
+ clipped,
+ clipped_count);
+
+ olddist = dist;
+
+
+ // point 2
+ dist = bt_distance_point_plane(plane,point2);
+
+ bt_plane_clip_polygon_collect(
+ point1,point2,
+ olddist,
+ dist,
+ clipped,
+ clipped_count);
+ olddist = dist;
+
+
+
+ //RETURN TO FIRST point0
+ bt_plane_clip_polygon_collect(
+ point2,point0,
+ olddist,
+ firstdist,
+ clipped,
+ clipped_count);
+
+ return clipped_count;
+}
+
+
+
+
+
+#endif // GIM_TRI_COLLISION_H_INCLUDED
diff --git a/thirdparty/bullet/src/BulletCollision/Gimpact/btCompoundFromGimpact.h b/thirdparty/bullet/src/BulletCollision/Gimpact/btCompoundFromGimpact.h
new file mode 100644
index 0000000000..19f7ecddd0
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/Gimpact/btCompoundFromGimpact.h
@@ -0,0 +1,109 @@
+#ifndef BT_COMPOUND_FROM_GIMPACT
+#define BT_COMPOUND_FROM_GIMPACT
+
+#include "BulletCollision/CollisionShapes/btCompoundShape.h"
+#include "btGImpactShape.h"
+#include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h"
+
+ATTRIBUTE_ALIGNED16(class) btCompoundFromGimpactShape : public btCompoundShape
+{
+public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ virtual ~btCompoundFromGimpactShape()
+ {
+ /*delete all the btBU_Simplex1to4 ChildShapes*/
+ for (int i = 0; i < m_children.size(); i++)
+ {
+ delete m_children[i].m_childShape;
+ }
+ }
+
+};
+
+struct MyCallback : public btTriangleRaycastCallback
+ {
+ int m_ignorePart;
+ int m_ignoreTriangleIndex;
+
+
+ MyCallback(const btVector3& from, const btVector3& to, int ignorePart, int ignoreTriangleIndex)
+ :btTriangleRaycastCallback(from,to),
+ m_ignorePart(ignorePart),
+ m_ignoreTriangleIndex(ignoreTriangleIndex)
+ {
+
+ }
+ virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex)
+ {
+ if (partId!=m_ignorePart || triangleIndex!=m_ignoreTriangleIndex)
+ {
+ if (hitFraction < m_hitFraction)
+ return hitFraction;
+ }
+
+ return m_hitFraction;
+ }
+ };
+ struct MyInternalTriangleIndexCallback :public btInternalTriangleIndexCallback
+ {
+ const btGImpactMeshShape* m_gimpactShape;
+ btCompoundShape* m_colShape;
+ btScalar m_depth;
+
+ MyInternalTriangleIndexCallback (btCompoundShape* colShape, const btGImpactMeshShape* meshShape, btScalar depth)
+ :m_colShape(colShape),
+ m_gimpactShape(meshShape),
+ m_depth(depth)
+ {
+ }
+
+ virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex)
+ {
+ btVector3 scale = m_gimpactShape->getLocalScaling();
+ btVector3 v0=triangle[0]*scale;
+ btVector3 v1=triangle[1]*scale;
+ btVector3 v2=triangle[2]*scale;
+
+ btVector3 centroid = (v0+v1+v2)/3;
+ btVector3 normal = (v1-v0).cross(v2-v0);
+ normal.normalize();
+ btVector3 rayFrom = centroid;
+ btVector3 rayTo = centroid-normal*m_depth;
+
+ MyCallback cb(rayFrom,rayTo,partId,triangleIndex);
+
+ m_gimpactShape->processAllTrianglesRay(&cb,rayFrom, rayTo);
+ if (cb.m_hitFraction<1)
+ {
+ rayTo.setInterpolate3(cb.m_from,cb.m_to,cb.m_hitFraction);
+ //rayTo = cb.m_from;
+ //rayTo = rayTo.lerp(cb.m_to,cb.m_hitFraction);
+ //gDebugDraw.drawLine(tr(centroid),tr(centroid+normal),btVector3(1,0,0));
+ }
+
+
+
+ btBU_Simplex1to4* tet = new btBU_Simplex1to4(v0,v1,v2,rayTo);
+ btTransform ident;
+ ident.setIdentity();
+ m_colShape->addChildShape(ident,tet);
+ }
+ };
+
+btCompoundShape* btCreateCompoundFromGimpactShape(const btGImpactMeshShape* gimpactMesh, btScalar depth)
+{
+ btCompoundShape* colShape = new btCompoundFromGimpactShape();
+
+ btTransform tr;
+ tr.setIdentity();
+
+ MyInternalTriangleIndexCallback cb(colShape,gimpactMesh, depth);
+ btVector3 aabbMin,aabbMax;
+ gimpactMesh->getAabb(tr,aabbMin,aabbMax);
+ gimpactMesh->getMeshInterface()->InternalProcessAllTriangles(&cb,aabbMin,aabbMax);
+
+ return colShape;
+}
+
+#endif //BT_COMPOUND_FROM_GIMPACT
diff --git a/thirdparty/bullet/src/BulletCollision/Gimpact/btContactProcessing.cpp b/thirdparty/bullet/src/BulletCollision/Gimpact/btContactProcessing.cpp
new file mode 100644
index 0000000000..eed31d839f
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/Gimpact/btContactProcessing.cpp
@@ -0,0 +1,181 @@
+
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+
+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 "btContactProcessing.h"
+
+#define MAX_COINCIDENT 8
+
+struct CONTACT_KEY_TOKEN
+{
+ unsigned int m_key;
+ int m_value;
+ CONTACT_KEY_TOKEN()
+ {
+ }
+
+ CONTACT_KEY_TOKEN(unsigned int key,int token)
+ {
+ m_key = key;
+ m_value = token;
+ }
+
+ CONTACT_KEY_TOKEN(const CONTACT_KEY_TOKEN& rtoken)
+ {
+ m_key = rtoken.m_key;
+ m_value = rtoken.m_value;
+ }
+
+ inline bool operator <(const CONTACT_KEY_TOKEN& other) const
+ {
+ return (m_key < other.m_key);
+ }
+
+ inline bool operator >(const CONTACT_KEY_TOKEN& other) const
+ {
+ return (m_key > other.m_key);
+ }
+
+};
+
+class CONTACT_KEY_TOKEN_COMP
+{
+ public:
+
+ bool operator() ( const CONTACT_KEY_TOKEN& a, const CONTACT_KEY_TOKEN& b ) const
+ {
+ return ( a < b );
+ }
+};
+
+
+void btContactArray::merge_contacts(
+ const btContactArray & contacts, bool normal_contact_average)
+{
+ clear();
+
+ int i;
+ if(contacts.size()==0) return;
+
+
+ if(contacts.size()==1)
+ {
+ push_back(contacts[0]);
+ return;
+ }
+
+ btAlignedObjectArray<CONTACT_KEY_TOKEN> keycontacts;
+
+ keycontacts.reserve(contacts.size());
+
+ //fill key contacts
+
+ for ( i = 0;i<contacts.size() ;i++ )
+ {
+ keycontacts.push_back(CONTACT_KEY_TOKEN(contacts[i].calc_key_contact(),i));
+ }
+
+ //sort keys
+ keycontacts.quickSort(CONTACT_KEY_TOKEN_COMP());
+
+ // Merge contacts
+ int coincident_count=0;
+ btVector3 coincident_normals[MAX_COINCIDENT];
+
+ unsigned int last_key = keycontacts[0].m_key;
+ unsigned int key = 0;
+
+ push_back(contacts[keycontacts[0].m_value]);
+
+ GIM_CONTACT * pcontact = &(*this)[0];
+
+ for( i=1;i<keycontacts.size();i++)
+ {
+ key = keycontacts[i].m_key;
+ const GIM_CONTACT * scontact = &contacts[keycontacts[i].m_value];
+
+ if(last_key == key)//same points
+ {
+ //merge contact
+ if(pcontact->m_depth - CONTACT_DIFF_EPSILON > scontact->m_depth)//)
+ {
+ *pcontact = *scontact;
+ coincident_count = 0;
+ }
+ else if(normal_contact_average)
+ {
+ if(btFabs(pcontact->m_depth - scontact->m_depth)<CONTACT_DIFF_EPSILON)
+ {
+ if(coincident_count<MAX_COINCIDENT)
+ {
+ coincident_normals[coincident_count] = scontact->m_normal;
+ coincident_count++;
+ }
+ }
+ }
+ }
+ else
+ {//add new contact
+
+ if(normal_contact_average && coincident_count>0)
+ {
+ pcontact->interpolate_normals(coincident_normals,coincident_count);
+ coincident_count = 0;
+ }
+
+ push_back(*scontact);
+ pcontact = &(*this)[this->size()-1];
+ }
+ last_key = key;
+ }
+}
+
+void btContactArray::merge_contacts_unique(const btContactArray & contacts)
+{
+ clear();
+
+ if(contacts.size()==0) return;
+
+ if(contacts.size()==1)
+ {
+ push_back(contacts[0]);
+ return;
+ }
+
+ GIM_CONTACT average_contact = contacts[0];
+
+ for (int i=1;i<contacts.size() ;i++ )
+ {
+ average_contact.m_point += contacts[i].m_point;
+ average_contact.m_normal += contacts[i].m_normal * contacts[i].m_depth;
+ }
+
+ //divide
+ btScalar divide_average = 1.0f/((btScalar)contacts.size());
+
+ average_contact.m_point *= divide_average;
+
+ average_contact.m_normal *= divide_average;
+
+ average_contact.m_depth = average_contact.m_normal.length();
+
+ average_contact.m_normal /= average_contact.m_depth;
+
+}
+
diff --git a/thirdparty/bullet/src/BulletCollision/Gimpact/btContactProcessing.h b/thirdparty/bullet/src/BulletCollision/Gimpact/btContactProcessing.h
new file mode 100644
index 0000000000..d1027dbe67
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/Gimpact/btContactProcessing.h
@@ -0,0 +1,65 @@
+#ifndef BT_CONTACT_H_INCLUDED
+#define BT_CONTACT_H_INCLUDED
+
+/*! \file gim_contact.h
+\author Francisco Leon Najera
+*/
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+
+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 "LinearMath/btTransform.h"
+#include "LinearMath/btAlignedObjectArray.h"
+#include "btTriangleShapeEx.h"
+#include "btContactProcessingStructs.h"
+
+class btContactArray:public btAlignedObjectArray<GIM_CONTACT>
+{
+public:
+ btContactArray()
+ {
+ reserve(64);
+ }
+
+ SIMD_FORCE_INLINE void push_contact(
+ const btVector3 &point,const btVector3 & normal,
+ btScalar depth, int feature1, int feature2)
+ {
+ push_back( GIM_CONTACT(point,normal,depth,feature1,feature2) );
+ }
+
+ SIMD_FORCE_INLINE void push_triangle_contacts(
+ const GIM_TRIANGLE_CONTACT & tricontact,
+ int feature1,int feature2)
+ {
+ for(int i = 0;i<tricontact.m_point_count ;i++ )
+ {
+ push_contact(
+ tricontact.m_points[i],
+ tricontact.m_separating_normal,
+ tricontact.m_penetration_depth,feature1,feature2);
+ }
+ }
+
+ void merge_contacts(const btContactArray & contacts, bool normal_contact_average = true);
+
+ void merge_contacts_unique(const btContactArray & contacts);
+};
+
+#endif // GIM_CONTACT_H_INCLUDED
diff --git a/thirdparty/bullet/src/BulletCollision/Gimpact/btContactProcessingStructs.h b/thirdparty/bullet/src/BulletCollision/Gimpact/btContactProcessingStructs.h
new file mode 100644
index 0000000000..efbc4a567a
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/Gimpact/btContactProcessingStructs.h
@@ -0,0 +1,109 @@
+#ifndef BT_CONTACT_H_STRUCTS_INCLUDED
+#define BT_CONTACT_H_STRUCTS_INCLUDED
+
+/*! \file gim_contact.h
+\author Francisco Leon Najera
+*/
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+
+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 "LinearMath/btTransform.h"
+#include "LinearMath/btAlignedObjectArray.h"
+#include "btTriangleShapeEx.h"
+
+
+/**
+Configuration var for applying interpolation of contact normals
+*/
+#define NORMAL_CONTACT_AVERAGE 1
+
+#define CONTACT_DIFF_EPSILON 0.00001f
+
+///The GIM_CONTACT is an internal GIMPACT structure, similar to btManifoldPoint.
+///@todo: remove and replace GIM_CONTACT by btManifoldPoint.
+class GIM_CONTACT
+{
+public:
+ btVector3 m_point;
+ btVector3 m_normal;
+ btScalar m_depth;//Positive value indicates interpenetration
+ btScalar m_distance;//Padding not for use
+ int m_feature1;//Face number
+ int m_feature2;//Face number
+public:
+ GIM_CONTACT()
+ {
+ }
+
+ GIM_CONTACT(const GIM_CONTACT & contact):
+ m_point(contact.m_point),
+ m_normal(contact.m_normal),
+ m_depth(contact.m_depth),
+ m_feature1(contact.m_feature1),
+ m_feature2(contact.m_feature2)
+ {
+ }
+
+ GIM_CONTACT(const btVector3 &point,const btVector3 & normal,
+ btScalar depth, int feature1, int feature2):
+ m_point(point),
+ m_normal(normal),
+ m_depth(depth),
+ m_feature1(feature1),
+ m_feature2(feature2)
+ {
+ }
+
+ //! Calcs key for coord classification
+ SIMD_FORCE_INLINE unsigned int calc_key_contact() const
+ {
+ int _coords[] = {
+ (int)(m_point[0]*1000.0f+1.0f),
+ (int)(m_point[1]*1333.0f),
+ (int)(m_point[2]*2133.0f+3.0f)};
+ unsigned int _hash=0;
+ unsigned int *_uitmp = (unsigned int *)(&_coords[0]);
+ _hash = *_uitmp;
+ _uitmp++;
+ _hash += (*_uitmp)<<4;
+ _uitmp++;
+ _hash += (*_uitmp)<<8;
+ return _hash;
+ }
+
+ SIMD_FORCE_INLINE void interpolate_normals( btVector3 * normals,int normal_count)
+ {
+ btVector3 vec_sum(m_normal);
+ for(int i=0;i<normal_count;i++)
+ {
+ vec_sum += normals[i];
+ }
+
+ btScalar vec_sum_len = vec_sum.length2();
+ if(vec_sum_len <CONTACT_DIFF_EPSILON) return;
+
+ //GIM_INV_SQRT(vec_sum_len,vec_sum_len); // 1/sqrt(vec_sum_len)
+
+ m_normal = vec_sum/btSqrt(vec_sum_len);
+ }
+
+};
+
+#endif // BT_CONTACT_H_STRUCTS_INCLUDED
diff --git a/thirdparty/bullet/src/BulletCollision/Gimpact/btGImpactBvh.cpp b/thirdparty/bullet/src/BulletCollision/Gimpact/btGImpactBvh.cpp
new file mode 100644
index 0000000000..863233163a
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/Gimpact/btGImpactBvh.cpp
@@ -0,0 +1,498 @@
+/*! \file gim_box_set.h
+\author Francisco Leon Najera
+*/
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+
+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 "btGImpactBvh.h"
+#include "LinearMath/btQuickprof.h"
+
+#ifdef TRI_COLLISION_PROFILING
+
+btClock g_tree_clock;
+
+float g_accum_tree_collision_time = 0;
+int g_count_traversing = 0;
+
+
+void bt_begin_gim02_tree_time()
+{
+ g_tree_clock.reset();
+}
+
+void bt_end_gim02_tree_time()
+{
+ g_accum_tree_collision_time += g_tree_clock.getTimeMicroseconds();
+ g_count_traversing++;
+}
+
+//! Gets the average time in miliseconds of tree collisions
+float btGImpactBvh::getAverageTreeCollisionTime()
+{
+ if(g_count_traversing == 0) return 0;
+
+ float avgtime = g_accum_tree_collision_time;
+ avgtime /= (float)g_count_traversing;
+
+ g_accum_tree_collision_time = 0;
+ g_count_traversing = 0;
+ return avgtime;
+
+// float avgtime = g_count_traversing;
+// g_count_traversing = 0;
+// return avgtime;
+
+}
+
+#endif //TRI_COLLISION_PROFILING
+
+/////////////////////// btBvhTree /////////////////////////////////
+
+int btBvhTree::_calc_splitting_axis(
+ GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex)
+{
+
+ int i;
+
+ btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.));
+ btVector3 variance(btScalar(0.),btScalar(0.),btScalar(0.));
+ int numIndices = endIndex-startIndex;
+
+ for (i=startIndex;i<endIndex;i++)
+ {
+ btVector3 center = btScalar(0.5)*(primitive_boxes[i].m_bound.m_max +
+ primitive_boxes[i].m_bound.m_min);
+ means+=center;
+ }
+ means *= (btScalar(1.)/(btScalar)numIndices);
+
+ for (i=startIndex;i<endIndex;i++)
+ {
+ btVector3 center = btScalar(0.5)*(primitive_boxes[i].m_bound.m_max +
+ primitive_boxes[i].m_bound.m_min);
+ btVector3 diff2 = center-means;
+ diff2 = diff2 * diff2;
+ variance += diff2;
+ }
+ variance *= (btScalar(1.)/ ((btScalar)numIndices-1) );
+
+ return variance.maxAxis();
+}
+
+
+int btBvhTree::_sort_and_calc_splitting_index(
+ GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex,
+ int endIndex, int splitAxis)
+{
+ int i;
+ int splitIndex =startIndex;
+ int numIndices = endIndex - startIndex;
+
+ // average of centers
+ btScalar splitValue = 0.0f;
+
+ btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.));
+ for (i=startIndex;i<endIndex;i++)
+ {
+ btVector3 center = btScalar(0.5)*(primitive_boxes[i].m_bound.m_max +
+ primitive_boxes[i].m_bound.m_min);
+ means+=center;
+ }
+ means *= (btScalar(1.)/(btScalar)numIndices);
+
+ splitValue = means[splitAxis];
+
+
+ //sort leafNodes so all values larger then splitValue comes first, and smaller values start from 'splitIndex'.
+ for (i=startIndex;i<endIndex;i++)
+ {
+ btVector3 center = btScalar(0.5)*(primitive_boxes[i].m_bound.m_max +
+ primitive_boxes[i].m_bound.m_min);
+ if (center[splitAxis] > splitValue)
+ {
+ //swap
+ primitive_boxes.swap(i,splitIndex);
+ //swapLeafNodes(i,splitIndex);
+ splitIndex++;
+ }
+ }
+
+ //if the splitIndex causes unbalanced trees, fix this by using the center in between startIndex and endIndex
+ //otherwise the tree-building might fail due to stack-overflows in certain cases.
+ //unbalanced1 is unsafe: it can cause stack overflows
+ //bool unbalanced1 = ((splitIndex==startIndex) || (splitIndex == (endIndex-1)));
+
+ //unbalanced2 should work too: always use center (perfect balanced trees)
+ //bool unbalanced2 = true;
+
+ //this should be safe too:
+ int rangeBalancedIndices = numIndices/3;
+ bool unbalanced = ((splitIndex<=(startIndex+rangeBalancedIndices)) || (splitIndex >=(endIndex-1-rangeBalancedIndices)));
+
+ if (unbalanced)
+ {
+ splitIndex = startIndex+ (numIndices>>1);
+ }
+
+ btAssert(!((splitIndex==startIndex) || (splitIndex == (endIndex))));
+
+ return splitIndex;
+
+}
+
+
+void btBvhTree::_build_sub_tree(GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex)
+{
+ int curIndex = m_num_nodes;
+ m_num_nodes++;
+
+ btAssert((endIndex-startIndex)>0);
+
+ if ((endIndex-startIndex)==1)
+ {
+ //We have a leaf node
+ setNodeBound(curIndex,primitive_boxes[startIndex].m_bound);
+ m_node_array[curIndex].setDataIndex(primitive_boxes[startIndex].m_data);
+
+ return;
+ }
+ //calculate Best Splitting Axis and where to split it. Sort the incoming 'leafNodes' array within range 'startIndex/endIndex'.
+
+ //split axis
+ int splitIndex = _calc_splitting_axis(primitive_boxes,startIndex,endIndex);
+
+ splitIndex = _sort_and_calc_splitting_index(
+ primitive_boxes,startIndex,endIndex,
+ splitIndex//split axis
+ );
+
+
+ //calc this node bounding box
+
+ btAABB node_bound;
+ node_bound.invalidate();
+
+ for (int i=startIndex;i<endIndex;i++)
+ {
+ node_bound.merge(primitive_boxes[i].m_bound);
+ }
+
+ setNodeBound(curIndex,node_bound);
+
+
+ //build left branch
+ _build_sub_tree(primitive_boxes, startIndex, splitIndex );
+
+
+ //build right branch
+ _build_sub_tree(primitive_boxes, splitIndex ,endIndex);
+
+ m_node_array[curIndex].setEscapeIndex(m_num_nodes - curIndex);
+
+
+}
+
+//! stackless build tree
+void btBvhTree::build_tree(
+ GIM_BVH_DATA_ARRAY & primitive_boxes)
+{
+ // initialize node count to 0
+ m_num_nodes = 0;
+ // allocate nodes
+ m_node_array.resize(primitive_boxes.size()*2);
+
+ _build_sub_tree(primitive_boxes, 0, primitive_boxes.size());
+}
+
+////////////////////////////////////class btGImpactBvh
+
+void btGImpactBvh::refit()
+{
+ int nodecount = getNodeCount();
+ while(nodecount--)
+ {
+ if(isLeafNode(nodecount))
+ {
+ btAABB leafbox;
+ m_primitive_manager->get_primitive_box(getNodeData(nodecount),leafbox);
+ setNodeBound(nodecount,leafbox);
+ }
+ else
+ {
+ //const GIM_BVH_TREE_NODE * nodepointer = get_node_pointer(nodecount);
+ //get left bound
+ btAABB bound;
+ bound.invalidate();
+
+ btAABB temp_box;
+
+ int child_node = getLeftNode(nodecount);
+ if(child_node)
+ {
+ getNodeBound(child_node,temp_box);
+ bound.merge(temp_box);
+ }
+
+ child_node = getRightNode(nodecount);
+ if(child_node)
+ {
+ getNodeBound(child_node,temp_box);
+ bound.merge(temp_box);
+ }
+
+ setNodeBound(nodecount,bound);
+ }
+ }
+}
+
+//! this rebuild the entire set
+void btGImpactBvh::buildSet()
+{
+ //obtain primitive boxes
+ GIM_BVH_DATA_ARRAY primitive_boxes;
+ primitive_boxes.resize(m_primitive_manager->get_primitive_count());
+
+ for (int i = 0;i<primitive_boxes.size() ;i++ )
+ {
+ m_primitive_manager->get_primitive_box(i,primitive_boxes[i].m_bound);
+ primitive_boxes[i].m_data = i;
+ }
+
+ m_box_tree.build_tree(primitive_boxes);
+}
+
+//! returns the indices of the primitives in the m_primitive_manager
+bool btGImpactBvh::boxQuery(const btAABB & box, btAlignedObjectArray<int> & collided_results) const
+{
+ int curIndex = 0;
+ int numNodes = getNodeCount();
+
+ while (curIndex < numNodes)
+ {
+ btAABB bound;
+ getNodeBound(curIndex,bound);
+
+ //catch bugs in tree data
+
+ bool aabbOverlap = bound.has_collision(box);
+ bool isleafnode = isLeafNode(curIndex);
+
+ if (isleafnode && aabbOverlap)
+ {
+ collided_results.push_back(getNodeData(curIndex));
+ }
+
+ if (aabbOverlap || isleafnode)
+ {
+ //next subnode
+ curIndex++;
+ }
+ else
+ {
+ //skip node
+ curIndex+= getEscapeNodeIndex(curIndex);
+ }
+ }
+ if(collided_results.size()>0) return true;
+ return false;
+}
+
+
+
+//! returns the indices of the primitives in the m_primitive_manager
+bool btGImpactBvh::rayQuery(
+ const btVector3 & ray_dir,const btVector3 & ray_origin ,
+ btAlignedObjectArray<int> & collided_results) const
+{
+ int curIndex = 0;
+ int numNodes = getNodeCount();
+
+ while (curIndex < numNodes)
+ {
+ btAABB bound;
+ getNodeBound(curIndex,bound);
+
+ //catch bugs in tree data
+
+ bool aabbOverlap = bound.collide_ray(ray_origin,ray_dir);
+ bool isleafnode = isLeafNode(curIndex);
+
+ if (isleafnode && aabbOverlap)
+ {
+ collided_results.push_back(getNodeData( curIndex));
+ }
+
+ if (aabbOverlap || isleafnode)
+ {
+ //next subnode
+ curIndex++;
+ }
+ else
+ {
+ //skip node
+ curIndex+= getEscapeNodeIndex(curIndex);
+ }
+ }
+ if(collided_results.size()>0) return true;
+ return false;
+}
+
+
+SIMD_FORCE_INLINE bool _node_collision(
+ btGImpactBvh * boxset0, btGImpactBvh * boxset1,
+ const BT_BOX_BOX_TRANSFORM_CACHE & trans_cache_1to0,
+ int node0 ,int node1, bool complete_primitive_tests)
+{
+ btAABB box0;
+ boxset0->getNodeBound(node0,box0);
+ btAABB box1;
+ boxset1->getNodeBound(node1,box1);
+
+ return box0.overlapping_trans_cache(box1,trans_cache_1to0,complete_primitive_tests );
+// box1.appy_transform_trans_cache(trans_cache_1to0);
+// return box0.has_collision(box1);
+
+}
+
+
+//stackless recursive collision routine
+static void _find_collision_pairs_recursive(
+ btGImpactBvh * boxset0, btGImpactBvh * boxset1,
+ btPairSet * collision_pairs,
+ const BT_BOX_BOX_TRANSFORM_CACHE & trans_cache_1to0,
+ int node0, int node1, bool complete_primitive_tests)
+{
+
+
+
+ if( _node_collision(
+ boxset0,boxset1,trans_cache_1to0,
+ node0,node1,complete_primitive_tests) ==false) return;//avoid colliding internal nodes
+
+ if(boxset0->isLeafNode(node0))
+ {
+ if(boxset1->isLeafNode(node1))
+ {
+ // collision result
+ collision_pairs->push_pair(
+ boxset0->getNodeData(node0),boxset1->getNodeData(node1));
+ return;
+ }
+ else
+ {
+
+ //collide left recursive
+
+ _find_collision_pairs_recursive(
+ boxset0,boxset1,
+ collision_pairs,trans_cache_1to0,
+ node0,boxset1->getLeftNode(node1),false);
+
+ //collide right recursive
+ _find_collision_pairs_recursive(
+ boxset0,boxset1,
+ collision_pairs,trans_cache_1to0,
+ node0,boxset1->getRightNode(node1),false);
+
+
+ }
+ }
+ else
+ {
+ if(boxset1->isLeafNode(node1))
+ {
+
+ //collide left recursive
+ _find_collision_pairs_recursive(
+ boxset0,boxset1,
+ collision_pairs,trans_cache_1to0,
+ boxset0->getLeftNode(node0),node1,false);
+
+
+ //collide right recursive
+
+ _find_collision_pairs_recursive(
+ boxset0,boxset1,
+ collision_pairs,trans_cache_1to0,
+ boxset0->getRightNode(node0),node1,false);
+
+
+ }
+ else
+ {
+ //collide left0 left1
+
+
+
+ _find_collision_pairs_recursive(
+ boxset0,boxset1,
+ collision_pairs,trans_cache_1to0,
+ boxset0->getLeftNode(node0),boxset1->getLeftNode(node1),false);
+
+ //collide left0 right1
+
+ _find_collision_pairs_recursive(
+ boxset0,boxset1,
+ collision_pairs,trans_cache_1to0,
+ boxset0->getLeftNode(node0),boxset1->getRightNode(node1),false);
+
+
+ //collide right0 left1
+
+ _find_collision_pairs_recursive(
+ boxset0,boxset1,
+ collision_pairs,trans_cache_1to0,
+ boxset0->getRightNode(node0),boxset1->getLeftNode(node1),false);
+
+ //collide right0 right1
+
+ _find_collision_pairs_recursive(
+ boxset0,boxset1,
+ collision_pairs,trans_cache_1to0,
+ boxset0->getRightNode(node0),boxset1->getRightNode(node1),false);
+
+ }// else if node1 is not a leaf
+ }// else if node0 is not a leaf
+}
+
+
+void btGImpactBvh::find_collision(btGImpactBvh * boxset0, const btTransform & trans0,
+ btGImpactBvh * boxset1, const btTransform & trans1,
+ btPairSet & collision_pairs)
+{
+
+ if(boxset0->getNodeCount()==0 || boxset1->getNodeCount()==0 ) return;
+
+ BT_BOX_BOX_TRANSFORM_CACHE trans_cache_1to0;
+
+ trans_cache_1to0.calc_from_homogenic(trans0,trans1);
+
+#ifdef TRI_COLLISION_PROFILING
+ bt_begin_gim02_tree_time();
+#endif //TRI_COLLISION_PROFILING
+
+ _find_collision_pairs_recursive(
+ boxset0,boxset1,
+ &collision_pairs,trans_cache_1to0,0,0,true);
+#ifdef TRI_COLLISION_PROFILING
+ bt_end_gim02_tree_time();
+#endif //TRI_COLLISION_PROFILING
+
+}
+
diff --git a/thirdparty/bullet/src/BulletCollision/Gimpact/btGImpactBvh.h b/thirdparty/bullet/src/BulletCollision/Gimpact/btGImpactBvh.h
new file mode 100644
index 0000000000..e20e03cc1d
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/Gimpact/btGImpactBvh.h
@@ -0,0 +1,318 @@
+#ifndef GIM_BOX_SET_H_INCLUDED
+#define GIM_BOX_SET_H_INCLUDED
+
+/*! \file gim_box_set.h
+\author Francisco Leon Najera
+*/
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+
+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 "LinearMath/btAlignedObjectArray.h"
+
+#include "btBoxCollision.h"
+#include "btTriangleShapeEx.h"
+#include "btGImpactBvhStructs.h"
+
+//! A pairset array
+class btPairSet: public btAlignedObjectArray<GIM_PAIR>
+{
+public:
+ btPairSet()
+ {
+ reserve(32);
+ }
+ inline void push_pair(int index1,int index2)
+ {
+ push_back(GIM_PAIR(index1,index2));
+ }
+
+ inline void push_pair_inv(int index1,int index2)
+ {
+ push_back(GIM_PAIR(index2,index1));
+ }
+};
+
+class GIM_BVH_DATA_ARRAY:public btAlignedObjectArray<GIM_BVH_DATA>
+{
+};
+
+
+class GIM_BVH_TREE_NODE_ARRAY:public btAlignedObjectArray<GIM_BVH_TREE_NODE>
+{
+};
+
+
+
+
+//! Basic Box tree structure
+class btBvhTree
+{
+protected:
+ int m_num_nodes;
+ GIM_BVH_TREE_NODE_ARRAY m_node_array;
+protected:
+ int _sort_and_calc_splitting_index(
+ GIM_BVH_DATA_ARRAY & primitive_boxes,
+ int startIndex, int endIndex, int splitAxis);
+
+ int _calc_splitting_axis(GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex);
+
+ void _build_sub_tree(GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex);
+public:
+ btBvhTree()
+ {
+ m_num_nodes = 0;
+ }
+
+ //! prototype functions for box tree management
+ //!@{
+ void build_tree(GIM_BVH_DATA_ARRAY & primitive_boxes);
+
+ SIMD_FORCE_INLINE void clearNodes()
+ {
+ m_node_array.clear();
+ m_num_nodes = 0;
+ }
+
+ //! node count
+ SIMD_FORCE_INLINE int getNodeCount() const
+ {
+ return m_num_nodes;
+ }
+
+ //! tells if the node is a leaf
+ SIMD_FORCE_INLINE bool isLeafNode(int nodeindex) const
+ {
+ return m_node_array[nodeindex].isLeafNode();
+ }
+
+ SIMD_FORCE_INLINE int getNodeData(int nodeindex) const
+ {
+ return m_node_array[nodeindex].getDataIndex();
+ }
+
+ SIMD_FORCE_INLINE void getNodeBound(int nodeindex, btAABB & bound) const
+ {
+ bound = m_node_array[nodeindex].m_bound;
+ }
+
+ SIMD_FORCE_INLINE void setNodeBound(int nodeindex, const btAABB & bound)
+ {
+ m_node_array[nodeindex].m_bound = bound;
+ }
+
+ SIMD_FORCE_INLINE int getLeftNode(int nodeindex) const
+ {
+ return nodeindex+1;
+ }
+
+ SIMD_FORCE_INLINE int getRightNode(int nodeindex) const
+ {
+ if(m_node_array[nodeindex+1].isLeafNode()) return nodeindex+2;
+ return nodeindex+1 + m_node_array[nodeindex+1].getEscapeIndex();
+ }
+
+ SIMD_FORCE_INLINE int getEscapeNodeIndex(int nodeindex) const
+ {
+ return m_node_array[nodeindex].getEscapeIndex();
+ }
+
+ SIMD_FORCE_INLINE const GIM_BVH_TREE_NODE * get_node_pointer(int index = 0) const
+ {
+ return &m_node_array[index];
+ }
+
+ //!@}
+};
+
+
+//! Prototype Base class for primitive classification
+/*!
+This class is a wrapper for primitive collections.
+This tells relevant info for the Bounding Box set classes, which take care of space classification.
+This class can manage Compound shapes and trimeshes, and if it is managing trimesh then the Hierarchy Bounding Box classes will take advantage of primitive Vs Box overlapping tests for getting optimal results and less Per Box compairisons.
+*/
+class btPrimitiveManagerBase
+{
+public:
+
+ virtual ~btPrimitiveManagerBase() {}
+
+ //! determines if this manager consist on only triangles, which special case will be optimized
+ virtual bool is_trimesh() const = 0;
+ virtual int get_primitive_count() const = 0;
+ virtual void get_primitive_box(int prim_index ,btAABB & primbox) const = 0;
+ //! retrieves only the points of the triangle, and the collision margin
+ virtual void get_primitive_triangle(int prim_index,btPrimitiveTriangle & triangle) const= 0;
+};
+
+
+//! Structure for containing Boxes
+/*!
+This class offers an structure for managing a box tree of primitives.
+Requires a Primitive prototype (like btPrimitiveManagerBase )
+*/
+class btGImpactBvh
+{
+protected:
+ btBvhTree m_box_tree;
+ btPrimitiveManagerBase * m_primitive_manager;
+
+protected:
+ //stackless refit
+ void refit();
+public:
+
+ //! this constructor doesn't build the tree. you must call buildSet
+ btGImpactBvh()
+ {
+ m_primitive_manager = NULL;
+ }
+
+ //! this constructor doesn't build the tree. you must call buildSet
+ btGImpactBvh(btPrimitiveManagerBase * primitive_manager)
+ {
+ m_primitive_manager = primitive_manager;
+ }
+
+ SIMD_FORCE_INLINE btAABB getGlobalBox() const
+ {
+ btAABB totalbox;
+ getNodeBound(0, totalbox);
+ return totalbox;
+ }
+
+ SIMD_FORCE_INLINE void setPrimitiveManager(btPrimitiveManagerBase * primitive_manager)
+ {
+ m_primitive_manager = primitive_manager;
+ }
+
+ SIMD_FORCE_INLINE btPrimitiveManagerBase * getPrimitiveManager() const
+ {
+ return m_primitive_manager;
+ }
+
+
+//! node manager prototype functions
+///@{
+
+ //! this attemps to refit the box set.
+ SIMD_FORCE_INLINE void update()
+ {
+ refit();
+ }
+
+ //! this rebuild the entire set
+ void buildSet();
+
+ //! returns the indices of the primitives in the m_primitive_manager
+ bool boxQuery(const btAABB & box, btAlignedObjectArray<int> & collided_results) const;
+
+ //! returns the indices of the primitives in the m_primitive_manager
+ SIMD_FORCE_INLINE bool boxQueryTrans(const btAABB & box,
+ const btTransform & transform, btAlignedObjectArray<int> & collided_results) const
+ {
+ btAABB transbox=box;
+ transbox.appy_transform(transform);
+ return boxQuery(transbox,collided_results);
+ }
+
+ //! returns the indices of the primitives in the m_primitive_manager
+ bool rayQuery(
+ const btVector3 & ray_dir,const btVector3 & ray_origin ,
+ btAlignedObjectArray<int> & collided_results) const;
+
+ //! tells if this set has hierarcht
+ SIMD_FORCE_INLINE bool hasHierarchy() const
+ {
+ return true;
+ }
+
+ //! tells if this set is a trimesh
+ SIMD_FORCE_INLINE bool isTrimesh() const
+ {
+ return m_primitive_manager->is_trimesh();
+ }
+
+ //! node count
+ SIMD_FORCE_INLINE int getNodeCount() const
+ {
+ return m_box_tree.getNodeCount();
+ }
+
+ //! tells if the node is a leaf
+ SIMD_FORCE_INLINE bool isLeafNode(int nodeindex) const
+ {
+ return m_box_tree.isLeafNode(nodeindex);
+ }
+
+ SIMD_FORCE_INLINE int getNodeData(int nodeindex) const
+ {
+ return m_box_tree.getNodeData(nodeindex);
+ }
+
+ SIMD_FORCE_INLINE void getNodeBound(int nodeindex, btAABB & bound) const
+ {
+ m_box_tree.getNodeBound(nodeindex, bound);
+ }
+
+ SIMD_FORCE_INLINE void setNodeBound(int nodeindex, const btAABB & bound)
+ {
+ m_box_tree.setNodeBound(nodeindex, bound);
+ }
+
+
+ SIMD_FORCE_INLINE int getLeftNode(int nodeindex) const
+ {
+ return m_box_tree.getLeftNode(nodeindex);
+ }
+
+ SIMD_FORCE_INLINE int getRightNode(int nodeindex) const
+ {
+ return m_box_tree.getRightNode(nodeindex);
+ }
+
+ SIMD_FORCE_INLINE int getEscapeNodeIndex(int nodeindex) const
+ {
+ return m_box_tree.getEscapeNodeIndex(nodeindex);
+ }
+
+ SIMD_FORCE_INLINE void getNodeTriangle(int nodeindex,btPrimitiveTriangle & triangle) const
+ {
+ m_primitive_manager->get_primitive_triangle(getNodeData(nodeindex),triangle);
+ }
+
+
+ SIMD_FORCE_INLINE const GIM_BVH_TREE_NODE * get_node_pointer(int index = 0) const
+ {
+ return m_box_tree.get_node_pointer(index);
+ }
+
+#ifdef TRI_COLLISION_PROFILING
+ static float getAverageTreeCollisionTime();
+#endif //TRI_COLLISION_PROFILING
+
+ static void find_collision(btGImpactBvh * boxset1, const btTransform & trans1,
+ btGImpactBvh * boxset2, const btTransform & trans2,
+ btPairSet & collision_pairs);
+};
+
+#endif // GIM_BOXPRUNING_H_INCLUDED
diff --git a/thirdparty/bullet/src/BulletCollision/Gimpact/btGImpactBvhStructs.h b/thirdparty/bullet/src/BulletCollision/Gimpact/btGImpactBvhStructs.h
new file mode 100644
index 0000000000..9342a572d0
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/Gimpact/btGImpactBvhStructs.h
@@ -0,0 +1,105 @@
+#ifndef GIM_BOX_SET_STRUCT_H_INCLUDED
+#define GIM_BOX_SET_STRUCT_H_INCLUDED
+
+/*! \file gim_box_set.h
+\author Francisco Leon Najera
+*/
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+
+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 "LinearMath/btAlignedObjectArray.h"
+
+#include "btBoxCollision.h"
+#include "btTriangleShapeEx.h"
+
+//! Overlapping pair
+struct GIM_PAIR
+{
+ int m_index1;
+ int m_index2;
+ GIM_PAIR()
+ {}
+
+ GIM_PAIR(const GIM_PAIR & p)
+ {
+ m_index1 = p.m_index1;
+ m_index2 = p.m_index2;
+ }
+
+ GIM_PAIR(int index1, int index2)
+ {
+ m_index1 = index1;
+ m_index2 = index2;
+ }
+};
+
+///GIM_BVH_DATA is an internal GIMPACT collision structure to contain axis aligned bounding box
+struct GIM_BVH_DATA
+{
+ btAABB m_bound;
+ int m_data;
+};
+
+//! Node Structure for trees
+class GIM_BVH_TREE_NODE
+{
+public:
+ btAABB m_bound;
+protected:
+ int m_escapeIndexOrDataIndex;
+public:
+ GIM_BVH_TREE_NODE()
+ {
+ m_escapeIndexOrDataIndex = 0;
+ }
+
+ SIMD_FORCE_INLINE bool isLeafNode() const
+ {
+ //skipindex is negative (internal node), triangleindex >=0 (leafnode)
+ return (m_escapeIndexOrDataIndex>=0);
+ }
+
+ SIMD_FORCE_INLINE int getEscapeIndex() const
+ {
+ //btAssert(m_escapeIndexOrDataIndex < 0);
+ return -m_escapeIndexOrDataIndex;
+ }
+
+ SIMD_FORCE_INLINE void setEscapeIndex(int index)
+ {
+ m_escapeIndexOrDataIndex = -index;
+ }
+
+ SIMD_FORCE_INLINE int getDataIndex() const
+ {
+ //btAssert(m_escapeIndexOrDataIndex >= 0);
+
+ return m_escapeIndexOrDataIndex;
+ }
+
+ SIMD_FORCE_INLINE void setDataIndex(int index)
+ {
+ m_escapeIndexOrDataIndex = index;
+ }
+
+};
+
+#endif // GIM_BOXPRUNING_H_INCLUDED
diff --git a/thirdparty/bullet/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp b/thirdparty/bullet/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp
new file mode 100644
index 0000000000..2e87475e39
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp
@@ -0,0 +1,932 @@
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+
+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.
+*/
+/*
+Author: Francisco Len Nßjera
+Concave-Concave Collision
+
+*/
+
+#include "BulletCollision/CollisionDispatch/btManifoldResult.h"
+#include "LinearMath/btIDebugDraw.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/CollisionShapes/btBoxShape.h"
+#include "btGImpactCollisionAlgorithm.h"
+#include "btContactProcessing.h"
+#include "LinearMath/btQuickprof.h"
+
+
+//! Class for accessing the plane equation
+class btPlaneShape : public btStaticPlaneShape
+{
+public:
+
+ btPlaneShape(const btVector3& v, float f)
+ :btStaticPlaneShape(v,f)
+ {
+ }
+
+ void get_plane_equation(btVector4 &equation)
+ {
+ equation[0] = m_planeNormal[0];
+ equation[1] = m_planeNormal[1];
+ equation[2] = m_planeNormal[2];
+ equation[3] = m_planeConstant;
+ }
+
+
+ void get_plane_equation_transformed(const btTransform & trans,btVector4 &equation) const
+ {
+ equation[0] = trans.getBasis().getRow(0).dot(m_planeNormal);
+ equation[1] = trans.getBasis().getRow(1).dot(m_planeNormal);
+ equation[2] = trans.getBasis().getRow(2).dot(m_planeNormal);
+ equation[3] = trans.getOrigin().dot(m_planeNormal) + m_planeConstant;
+ }
+};
+
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////
+#ifdef TRI_COLLISION_PROFILING
+
+btClock g_triangle_clock;
+
+float g_accum_triangle_collision_time = 0;
+int g_count_triangle_collision = 0;
+
+void bt_begin_gim02_tri_time()
+{
+ g_triangle_clock.reset();
+}
+
+void bt_end_gim02_tri_time()
+{
+ g_accum_triangle_collision_time += g_triangle_clock.getTimeMicroseconds();
+ g_count_triangle_collision++;
+}
+#endif //TRI_COLLISION_PROFILING
+//! Retrieving shapes shapes
+/*!
+Declared here due of insuficent space on Pool allocators
+*/
+//!@{
+class GIM_ShapeRetriever
+{
+public:
+ const btGImpactShapeInterface * m_gim_shape;
+ btTriangleShapeEx m_trishape;
+ btTetrahedronShapeEx m_tetrashape;
+
+public:
+ class ChildShapeRetriever
+ {
+ public:
+ GIM_ShapeRetriever * m_parent;
+ virtual const btCollisionShape * getChildShape(int index)
+ {
+ return m_parent->m_gim_shape->getChildShape(index);
+ }
+ virtual ~ChildShapeRetriever() {}
+ };
+
+ class TriangleShapeRetriever:public ChildShapeRetriever
+ {
+ public:
+
+ virtual btCollisionShape * getChildShape(int index)
+ {
+ m_parent->m_gim_shape->getBulletTriangle(index,m_parent->m_trishape);
+ return &m_parent->m_trishape;
+ }
+ virtual ~TriangleShapeRetriever() {}
+ };
+
+ class TetraShapeRetriever:public ChildShapeRetriever
+ {
+ public:
+
+ virtual btCollisionShape * getChildShape(int index)
+ {
+ m_parent->m_gim_shape->getBulletTetrahedron(index,m_parent->m_tetrashape);
+ return &m_parent->m_tetrashape;
+ }
+ };
+public:
+ ChildShapeRetriever m_child_retriever;
+ TriangleShapeRetriever m_tri_retriever;
+ TetraShapeRetriever m_tetra_retriever;
+ ChildShapeRetriever * m_current_retriever;
+
+ GIM_ShapeRetriever(const btGImpactShapeInterface * gim_shape)
+ {
+ m_gim_shape = gim_shape;
+ //select retriever
+ if(m_gim_shape->needsRetrieveTriangles())
+ {
+ m_current_retriever = &m_tri_retriever;
+ }
+ else if(m_gim_shape->needsRetrieveTetrahedrons())
+ {
+ m_current_retriever = &m_tetra_retriever;
+ }
+ else
+ {
+ m_current_retriever = &m_child_retriever;
+ }
+
+ m_current_retriever->m_parent = this;
+ }
+
+ const btCollisionShape * getChildShape(int index)
+ {
+ return m_current_retriever->getChildShape(index);
+ }
+
+
+};
+
+
+
+//!@}
+
+
+#ifdef TRI_COLLISION_PROFILING
+
+//! Gets the average time in miliseconds of tree collisions
+float btGImpactCollisionAlgorithm::getAverageTreeCollisionTime()
+{
+ return btGImpactBoxSet::getAverageTreeCollisionTime();
+
+}
+
+//! Gets the average time in miliseconds of triangle collisions
+float btGImpactCollisionAlgorithm::getAverageTriangleCollisionTime()
+{
+ if(g_count_triangle_collision == 0) return 0;
+
+ float avgtime = g_accum_triangle_collision_time;
+ avgtime /= (float)g_count_triangle_collision;
+
+ g_accum_triangle_collision_time = 0;
+ g_count_triangle_collision = 0;
+
+ return avgtime;
+}
+
+#endif //TRI_COLLISION_PROFILING
+
+
+
+btGImpactCollisionAlgorithm::btGImpactCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
+: btActivatingCollisionAlgorithm(ci,body0Wrap,body1Wrap)
+{
+ m_manifoldPtr = NULL;
+ m_convex_algorithm = NULL;
+}
+
+btGImpactCollisionAlgorithm::~btGImpactCollisionAlgorithm()
+{
+ clearCache();
+}
+
+
+
+
+
+void btGImpactCollisionAlgorithm::addContactPoint(const btCollisionObjectWrapper * body0Wrap,
+ const btCollisionObjectWrapper * body1Wrap,
+ const btVector3 & point,
+ const btVector3 & normal,
+ btScalar distance)
+{
+ m_resultOut->setShapeIdentifiersA(m_part0,m_triface0);
+ m_resultOut->setShapeIdentifiersB(m_part1,m_triface1);
+ checkManifold(body0Wrap,body1Wrap);
+ m_resultOut->addContactPoint(normal,point,distance);
+}
+
+
+void btGImpactCollisionAlgorithm::shape_vs_shape_collision(
+ const btCollisionObjectWrapper * body0Wrap,
+ const btCollisionObjectWrapper* body1Wrap,
+ const btCollisionShape * shape0,
+ const btCollisionShape * shape1)
+{
+
+
+ {
+
+ btCollisionAlgorithm* algor = newAlgorithm(body0Wrap,body1Wrap);
+ // post : checkManifold is called
+
+ m_resultOut->setShapeIdentifiersA(m_part0,m_triface0);
+ m_resultOut->setShapeIdentifiersB(m_part1,m_triface1);
+
+ algor->processCollision(body0Wrap,body1Wrap,*m_dispatchInfo,m_resultOut);
+
+ algor->~btCollisionAlgorithm();
+ m_dispatcher->freeCollisionAlgorithm(algor);
+ }
+
+}
+
+void btGImpactCollisionAlgorithm::convex_vs_convex_collision(
+ const btCollisionObjectWrapper* body0Wrap,
+ const btCollisionObjectWrapper* body1Wrap,
+ const btCollisionShape* shape0,
+ const btCollisionShape* shape1)
+{
+
+ m_resultOut->setShapeIdentifiersA(m_part0,m_triface0);
+ m_resultOut->setShapeIdentifiersB(m_part1,m_triface1);
+
+ btCollisionObjectWrapper ob0(body0Wrap,shape0,body0Wrap->getCollisionObject(),body0Wrap->getWorldTransform(),m_part0,m_triface0);
+ btCollisionObjectWrapper ob1(body1Wrap,shape1,body1Wrap->getCollisionObject(),body1Wrap->getWorldTransform(),m_part1,m_triface1);
+ checkConvexAlgorithm(&ob0,&ob1);
+ m_convex_algorithm->processCollision(&ob0,&ob1,*m_dispatchInfo,m_resultOut);
+
+
+}
+
+
+
+
+void btGImpactCollisionAlgorithm::gimpact_vs_gimpact_find_pairs(
+ const btTransform & trans0,
+ const btTransform & trans1,
+ const btGImpactShapeInterface * shape0,
+ const btGImpactShapeInterface * shape1,btPairSet & pairset)
+{
+ if(shape0->hasBoxSet() && shape1->hasBoxSet())
+ {
+ btGImpactBoxSet::find_collision(shape0->getBoxSet(),trans0,shape1->getBoxSet(),trans1,pairset);
+ }
+ else
+ {
+ btAABB boxshape0;
+ btAABB boxshape1;
+ int i = shape0->getNumChildShapes();
+
+ while(i--)
+ {
+ shape0->getChildAabb(i,trans0,boxshape0.m_min,boxshape0.m_max);
+
+ int j = shape1->getNumChildShapes();
+ while(j--)
+ {
+ shape1->getChildAabb(i,trans1,boxshape1.m_min,boxshape1.m_max);
+
+ if(boxshape1.has_collision(boxshape0))
+ {
+ pairset.push_pair(i,j);
+ }
+ }
+ }
+ }
+
+
+}
+
+
+void btGImpactCollisionAlgorithm::gimpact_vs_shape_find_pairs(
+ const btTransform & trans0,
+ const btTransform & trans1,
+ const btGImpactShapeInterface * shape0,
+ const btCollisionShape * shape1,
+ btAlignedObjectArray<int> & collided_primitives)
+{
+
+ btAABB boxshape;
+
+
+ if(shape0->hasBoxSet())
+ {
+ btTransform trans1to0 = trans0.inverse();
+ trans1to0 *= trans1;
+
+ shape1->getAabb(trans1to0,boxshape.m_min,boxshape.m_max);
+
+ shape0->getBoxSet()->boxQuery(boxshape, collided_primitives);
+ }
+ else
+ {
+ shape1->getAabb(trans1,boxshape.m_min,boxshape.m_max);
+
+ btAABB boxshape0;
+ int i = shape0->getNumChildShapes();
+
+ while(i--)
+ {
+ shape0->getChildAabb(i,trans0,boxshape0.m_min,boxshape0.m_max);
+
+ if(boxshape.has_collision(boxshape0))
+ {
+ collided_primitives.push_back(i);
+ }
+ }
+
+ }
+
+}
+
+
+void btGImpactCollisionAlgorithm::collide_gjk_triangles(const btCollisionObjectWrapper * body0Wrap,
+ const btCollisionObjectWrapper * body1Wrap,
+ const btGImpactMeshShapePart * shape0,
+ const btGImpactMeshShapePart * shape1,
+ const int * pairs, int pair_count)
+{
+ btTriangleShapeEx tri0;
+ btTriangleShapeEx tri1;
+
+ shape0->lockChildShapes();
+ shape1->lockChildShapes();
+
+ const int * pair_pointer = pairs;
+
+ while(pair_count--)
+ {
+
+ m_triface0 = *(pair_pointer);
+ m_triface1 = *(pair_pointer+1);
+ pair_pointer+=2;
+
+
+
+ shape0->getBulletTriangle(m_triface0,tri0);
+ shape1->getBulletTriangle(m_triface1,tri1);
+
+
+ //collide two convex shapes
+ if(tri0.overlap_test_conservative(tri1))
+ {
+ convex_vs_convex_collision(body0Wrap,body1Wrap,&tri0,&tri1);
+ }
+
+ }
+
+ shape0->unlockChildShapes();
+ shape1->unlockChildShapes();
+}
+
+void btGImpactCollisionAlgorithm::collide_sat_triangles(const btCollisionObjectWrapper* body0Wrap,
+ const btCollisionObjectWrapper* body1Wrap,
+ const btGImpactMeshShapePart * shape0,
+ const btGImpactMeshShapePart * shape1,
+ const int * pairs, int pair_count)
+{
+ btTransform orgtrans0 = body0Wrap->getWorldTransform();
+ btTransform orgtrans1 = body1Wrap->getWorldTransform();
+
+ btPrimitiveTriangle ptri0;
+ btPrimitiveTriangle ptri1;
+ GIM_TRIANGLE_CONTACT contact_data;
+
+ shape0->lockChildShapes();
+ shape1->lockChildShapes();
+
+ const int * pair_pointer = pairs;
+
+ while(pair_count--)
+ {
+
+ m_triface0 = *(pair_pointer);
+ m_triface1 = *(pair_pointer+1);
+ pair_pointer+=2;
+
+
+ shape0->getPrimitiveTriangle(m_triface0,ptri0);
+ shape1->getPrimitiveTriangle(m_triface1,ptri1);
+
+ #ifdef TRI_COLLISION_PROFILING
+ bt_begin_gim02_tri_time();
+ #endif
+
+ ptri0.applyTransform(orgtrans0);
+ ptri1.applyTransform(orgtrans1);
+
+
+ //build planes
+ ptri0.buildTriPlane();
+ ptri1.buildTriPlane();
+ // test conservative
+
+
+
+ if(ptri0.overlap_test_conservative(ptri1))
+ {
+ if(ptri0.find_triangle_collision_clip_method(ptri1,contact_data))
+ {
+
+ int j = contact_data.m_point_count;
+ while(j--)
+ {
+
+ addContactPoint(body0Wrap, body1Wrap,
+ contact_data.m_points[j],
+ contact_data.m_separating_normal,
+ -contact_data.m_penetration_depth);
+ }
+ }
+ }
+
+ #ifdef TRI_COLLISION_PROFILING
+ bt_end_gim02_tri_time();
+ #endif
+
+ }
+
+ shape0->unlockChildShapes();
+ shape1->unlockChildShapes();
+
+}
+
+
+void btGImpactCollisionAlgorithm::gimpact_vs_gimpact(
+ const btCollisionObjectWrapper* body0Wrap,
+ const btCollisionObjectWrapper * body1Wrap,
+ const btGImpactShapeInterface * shape0,
+ const btGImpactShapeInterface * shape1)
+{
+
+ if(shape0->getGImpactShapeType()==CONST_GIMPACT_TRIMESH_SHAPE)
+ {
+ const btGImpactMeshShape * meshshape0 = static_cast<const btGImpactMeshShape *>(shape0);
+ m_part0 = meshshape0->getMeshPartCount();
+
+ while(m_part0--)
+ {
+ gimpact_vs_gimpact(body0Wrap,body1Wrap,meshshape0->getMeshPart(m_part0),shape1);
+ }
+
+ return;
+ }
+
+ if(shape1->getGImpactShapeType()==CONST_GIMPACT_TRIMESH_SHAPE)
+ {
+ const btGImpactMeshShape * meshshape1 = static_cast<const btGImpactMeshShape *>(shape1);
+ m_part1 = meshshape1->getMeshPartCount();
+
+ while(m_part1--)
+ {
+
+ gimpact_vs_gimpact(body0Wrap,body1Wrap,shape0,meshshape1->getMeshPart(m_part1));
+
+ }
+
+ return;
+ }
+
+
+ btTransform orgtrans0 = body0Wrap->getWorldTransform();
+ btTransform orgtrans1 = body1Wrap->getWorldTransform();
+
+ btPairSet pairset;
+
+ gimpact_vs_gimpact_find_pairs(orgtrans0,orgtrans1,shape0,shape1,pairset);
+
+ if(pairset.size()== 0) return;
+
+ if(shape0->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE_PART &&
+ shape1->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE_PART)
+ {
+ const btGImpactMeshShapePart * shapepart0 = static_cast<const btGImpactMeshShapePart * >(shape0);
+ const btGImpactMeshShapePart * shapepart1 = static_cast<const btGImpactMeshShapePart * >(shape1);
+ //specialized function
+ #ifdef BULLET_TRIANGLE_COLLISION
+ collide_gjk_triangles(body0Wrap,body1Wrap,shapepart0,shapepart1,&pairset[0].m_index1,pairset.size());
+ #else
+ collide_sat_triangles(body0Wrap,body1Wrap,shapepart0,shapepart1,&pairset[0].m_index1,pairset.size());
+ #endif
+
+ return;
+ }
+
+ //general function
+
+ shape0->lockChildShapes();
+ shape1->lockChildShapes();
+
+ GIM_ShapeRetriever retriever0(shape0);
+ GIM_ShapeRetriever retriever1(shape1);
+
+ bool child_has_transform0 = shape0->childrenHasTransform();
+ bool child_has_transform1 = shape1->childrenHasTransform();
+
+ int i = pairset.size();
+ while(i--)
+ {
+ GIM_PAIR * pair = &pairset[i];
+ m_triface0 = pair->m_index1;
+ m_triface1 = pair->m_index2;
+ const btCollisionShape * colshape0 = retriever0.getChildShape(m_triface0);
+ const btCollisionShape * colshape1 = retriever1.getChildShape(m_triface1);
+
+ btTransform tr0 = body0Wrap->getWorldTransform();
+ btTransform tr1 = body1Wrap->getWorldTransform();
+
+ if(child_has_transform0)
+ {
+ tr0 = orgtrans0*shape0->getChildTransform(m_triface0);
+ }
+
+ if(child_has_transform1)
+ {
+ tr1 = orgtrans1*shape1->getChildTransform(m_triface1);
+ }
+
+ btCollisionObjectWrapper ob0(body0Wrap,colshape0,body0Wrap->getCollisionObject(),tr0,m_part0,m_triface0);
+ btCollisionObjectWrapper ob1(body1Wrap,colshape1,body1Wrap->getCollisionObject(),tr1,m_part1,m_triface1);
+
+ //collide two convex shapes
+ convex_vs_convex_collision(&ob0,&ob1,colshape0,colshape1);
+ }
+
+ shape0->unlockChildShapes();
+ shape1->unlockChildShapes();
+}
+
+void btGImpactCollisionAlgorithm::gimpact_vs_shape(const btCollisionObjectWrapper* body0Wrap,
+ const btCollisionObjectWrapper * body1Wrap,
+ const btGImpactShapeInterface * shape0,
+ const btCollisionShape * shape1,bool swapped)
+{
+ if(shape0->getGImpactShapeType()==CONST_GIMPACT_TRIMESH_SHAPE)
+ {
+ const btGImpactMeshShape * meshshape0 = static_cast<const btGImpactMeshShape *>(shape0);
+ int& part = swapped ? m_part1 : m_part0;
+ part = meshshape0->getMeshPartCount();
+
+ while(part--)
+ {
+
+ gimpact_vs_shape(body0Wrap,
+ body1Wrap,
+ meshshape0->getMeshPart(part),
+ shape1,swapped);
+
+ }
+
+ return;
+ }
+
+ #ifdef GIMPACT_VS_PLANE_COLLISION
+ if(shape0->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE_PART &&
+ shape1->getShapeType() == STATIC_PLANE_PROXYTYPE)
+ {
+ const btGImpactMeshShapePart * shapepart = static_cast<const btGImpactMeshShapePart *>(shape0);
+ const btStaticPlaneShape * planeshape = static_cast<const btStaticPlaneShape * >(shape1);
+ gimpacttrimeshpart_vs_plane_collision(body0Wrap,body1Wrap,shapepart,planeshape,swapped);
+ return;
+ }
+
+ #endif
+
+
+
+ if(shape1->isCompound())
+ {
+ const btCompoundShape * compoundshape = static_cast<const btCompoundShape *>(shape1);
+ gimpact_vs_compoundshape(body0Wrap,body1Wrap,shape0,compoundshape,swapped);
+ return;
+ }
+ else if(shape1->isConcave())
+ {
+ const btConcaveShape * concaveshape = static_cast<const btConcaveShape *>(shape1);
+ gimpact_vs_concave(body0Wrap,body1Wrap,shape0,concaveshape,swapped);
+ return;
+ }
+
+
+ btTransform orgtrans0 = body0Wrap->getWorldTransform();
+
+ btTransform orgtrans1 = body1Wrap->getWorldTransform();
+
+ btAlignedObjectArray<int> collided_results;
+
+ gimpact_vs_shape_find_pairs(orgtrans0,orgtrans1,shape0,shape1,collided_results);
+
+ if(collided_results.size() == 0) return;
+
+
+ shape0->lockChildShapes();
+
+ GIM_ShapeRetriever retriever0(shape0);
+
+
+ bool child_has_transform0 = shape0->childrenHasTransform();
+
+
+ int i = collided_results.size();
+
+ while(i--)
+ {
+ int child_index = collided_results[i];
+ if(swapped)
+ m_triface1 = child_index;
+ else
+ m_triface0 = child_index;
+
+ const btCollisionShape * colshape0 = retriever0.getChildShape(child_index);
+
+ btTransform tr0 = body0Wrap->getWorldTransform();
+
+ if(child_has_transform0)
+ {
+ tr0 = orgtrans0*shape0->getChildTransform(child_index);
+ }
+
+ btCollisionObjectWrapper ob0(body0Wrap,colshape0,body0Wrap->getCollisionObject(),body0Wrap->getWorldTransform(),m_part0,m_triface0);
+ const btCollisionObjectWrapper* prevObj0 = m_resultOut->getBody0Wrap();
+
+ if (m_resultOut->getBody0Wrap()->getCollisionObject()==ob0.getCollisionObject())
+ {
+ m_resultOut->setBody0Wrap(&ob0);
+ } else
+ {
+ m_resultOut->setBody1Wrap(&ob0);
+ }
+
+ //collide two shapes
+ if(swapped)
+ {
+
+ shape_vs_shape_collision(body1Wrap,&ob0,shape1,colshape0);
+ }
+ else
+ {
+
+ shape_vs_shape_collision(&ob0,body1Wrap,colshape0,shape1);
+ }
+ m_resultOut->setBody0Wrap(prevObj0);
+
+ }
+
+ shape0->unlockChildShapes();
+
+}
+
+void btGImpactCollisionAlgorithm::gimpact_vs_compoundshape(const btCollisionObjectWrapper* body0Wrap,
+ const btCollisionObjectWrapper* body1Wrap,
+ const btGImpactShapeInterface * shape0,
+ const btCompoundShape * shape1,bool swapped)
+{
+ btTransform orgtrans1 = body1Wrap->getWorldTransform();
+
+ int i = shape1->getNumChildShapes();
+ while(i--)
+ {
+
+ const btCollisionShape * colshape1 = shape1->getChildShape(i);
+ btTransform childtrans1 = orgtrans1*shape1->getChildTransform(i);
+
+ btCollisionObjectWrapper ob1(body1Wrap,colshape1,body1Wrap->getCollisionObject(),childtrans1,-1,i);
+
+ const btCollisionObjectWrapper* tmp = 0;
+ if (m_resultOut->getBody0Wrap()->getCollisionObject()==ob1.getCollisionObject())
+ {
+ tmp = m_resultOut->getBody0Wrap();
+ m_resultOut->setBody0Wrap(&ob1);
+ } else
+ {
+ tmp = m_resultOut->getBody1Wrap();
+ m_resultOut->setBody1Wrap(&ob1);
+ }
+ //collide child shape
+ gimpact_vs_shape(body0Wrap, &ob1,
+ shape0,colshape1,swapped);
+
+ if (m_resultOut->getBody0Wrap()->getCollisionObject()==ob1.getCollisionObject())
+ {
+ m_resultOut->setBody0Wrap(tmp);
+ } else
+ {
+ m_resultOut->setBody1Wrap(tmp);
+ }
+ }
+}
+
+void btGImpactCollisionAlgorithm::gimpacttrimeshpart_vs_plane_collision(
+ const btCollisionObjectWrapper * body0Wrap,
+ const btCollisionObjectWrapper * body1Wrap,
+ const btGImpactMeshShapePart * shape0,
+ const btStaticPlaneShape * shape1,bool swapped)
+{
+
+
+ btTransform orgtrans0 = body0Wrap->getWorldTransform();
+ btTransform orgtrans1 = body1Wrap->getWorldTransform();
+
+ const btPlaneShape * planeshape = static_cast<const btPlaneShape *>(shape1);
+ btVector4 plane;
+ planeshape->get_plane_equation_transformed(orgtrans1,plane);
+
+ //test box against plane
+
+ btAABB tribox;
+ shape0->getAabb(orgtrans0,tribox.m_min,tribox.m_max);
+ tribox.increment_margin(planeshape->getMargin());
+
+ if( tribox.plane_classify(plane)!= BT_CONST_COLLIDE_PLANE) return;
+
+ shape0->lockChildShapes();
+
+ btScalar margin = shape0->getMargin() + planeshape->getMargin();
+
+ btVector3 vertex;
+ int vi = shape0->getVertexCount();
+ while(vi--)
+ {
+ shape0->getVertex(vi,vertex);
+ vertex = orgtrans0(vertex);
+
+ btScalar distance = vertex.dot(plane) - plane[3] - margin;
+
+ if(distance<0.0)//add contact
+ {
+ if(swapped)
+ {
+ addContactPoint(body1Wrap, body0Wrap,
+ vertex,
+ -plane,
+ distance);
+ }
+ else
+ {
+ addContactPoint(body0Wrap, body1Wrap,
+ vertex,
+ plane,
+ distance);
+ }
+ }
+ }
+
+ shape0->unlockChildShapes();
+}
+
+
+
+
+class btGImpactTriangleCallback: public btTriangleCallback
+{
+public:
+ btGImpactCollisionAlgorithm * algorithm;
+ const btCollisionObjectWrapper * body0Wrap;
+ const btCollisionObjectWrapper * body1Wrap;
+ const btGImpactShapeInterface * gimpactshape0;
+ bool swapped;
+ btScalar margin;
+
+ virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
+ {
+ btTriangleShapeEx tri1(triangle[0],triangle[1],triangle[2]);
+ tri1.setMargin(margin);
+ if(swapped)
+ {
+ algorithm->setPart0(partId);
+ algorithm->setFace0(triangleIndex);
+ }
+ else
+ {
+ algorithm->setPart1(partId);
+ algorithm->setFace1(triangleIndex);
+ }
+
+ btCollisionObjectWrapper ob1Wrap(body1Wrap,&tri1,body1Wrap->getCollisionObject(),body1Wrap->getWorldTransform(),partId,triangleIndex);
+ const btCollisionObjectWrapper * tmp = 0;
+
+ if (algorithm->internalGetResultOut()->getBody0Wrap()->getCollisionObject()==ob1Wrap.getCollisionObject())
+ {
+ tmp = algorithm->internalGetResultOut()->getBody0Wrap();
+ algorithm->internalGetResultOut()->setBody0Wrap(&ob1Wrap);
+ } else
+ {
+ tmp = algorithm->internalGetResultOut()->getBody1Wrap();
+ algorithm->internalGetResultOut()->setBody1Wrap(&ob1Wrap);
+ }
+
+ algorithm->gimpact_vs_shape(
+ body0Wrap,&ob1Wrap,gimpactshape0,&tri1,swapped);
+
+ if (algorithm->internalGetResultOut()->getBody0Wrap()->getCollisionObject()==ob1Wrap.getCollisionObject())
+ {
+ algorithm->internalGetResultOut()->setBody0Wrap(tmp);
+ } else
+ {
+ algorithm->internalGetResultOut()->setBody1Wrap(tmp);
+ }
+
+ }
+};
+
+
+
+
+void btGImpactCollisionAlgorithm::gimpact_vs_concave(
+ const btCollisionObjectWrapper* body0Wrap,
+ const btCollisionObjectWrapper * body1Wrap,
+ const btGImpactShapeInterface * shape0,
+ const btConcaveShape * shape1,bool swapped)
+{
+ //create the callback
+ btGImpactTriangleCallback tricallback;
+ tricallback.algorithm = this;
+ tricallback.body0Wrap = body0Wrap;
+ tricallback.body1Wrap = body1Wrap;
+ tricallback.gimpactshape0 = shape0;
+ tricallback.swapped = swapped;
+ tricallback.margin = shape1->getMargin();
+
+ //getting the trimesh AABB
+ btTransform gimpactInConcaveSpace;
+
+ gimpactInConcaveSpace = body1Wrap->getWorldTransform().inverse() * body0Wrap->getWorldTransform();
+
+ btVector3 minAABB,maxAABB;
+ shape0->getAabb(gimpactInConcaveSpace,minAABB,maxAABB);
+
+ shape1->processAllTriangles(&tricallback,minAABB,maxAABB);
+
+}
+
+
+
+void btGImpactCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+ clearCache();
+
+ m_resultOut = resultOut;
+ m_dispatchInfo = &dispatchInfo;
+ const btGImpactShapeInterface * gimpactshape0;
+ const btGImpactShapeInterface * gimpactshape1;
+
+ if (body0Wrap->getCollisionShape()->getShapeType()==GIMPACT_SHAPE_PROXYTYPE)
+ {
+ gimpactshape0 = static_cast<const btGImpactShapeInterface *>(body0Wrap->getCollisionShape());
+
+ if( body1Wrap->getCollisionShape()->getShapeType()==GIMPACT_SHAPE_PROXYTYPE )
+ {
+ gimpactshape1 = static_cast<const btGImpactShapeInterface *>(body1Wrap->getCollisionShape());
+
+ gimpact_vs_gimpact(body0Wrap,body1Wrap,gimpactshape0,gimpactshape1);
+ }
+ else
+ {
+ gimpact_vs_shape(body0Wrap,body1Wrap,gimpactshape0,body1Wrap->getCollisionShape(),false);
+ }
+
+ }
+ else if (body1Wrap->getCollisionShape()->getShapeType()==GIMPACT_SHAPE_PROXYTYPE )
+ {
+ gimpactshape1 = static_cast<const btGImpactShapeInterface *>(body1Wrap->getCollisionShape());
+
+ gimpact_vs_shape(body1Wrap,body0Wrap,gimpactshape1,body0Wrap->getCollisionShape(),true);
+ }
+}
+
+
+btScalar btGImpactCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+ return 1.f;
+
+}
+
+///////////////////////////////////// REGISTERING ALGORITHM //////////////////////////////////////////////
+
+
+
+//! Use this function for register the algorithm externally
+void btGImpactCollisionAlgorithm::registerAlgorithm(btCollisionDispatcher * dispatcher)
+{
+
+ static btGImpactCollisionAlgorithm::CreateFunc s_gimpact_cf;
+
+ int i;
+
+ for ( i = 0;i < MAX_BROADPHASE_COLLISION_TYPES ;i++ )
+ {
+ dispatcher->registerCollisionCreateFunc(GIMPACT_SHAPE_PROXYTYPE,i ,&s_gimpact_cf);
+ }
+
+ for ( i = 0;i < MAX_BROADPHASE_COLLISION_TYPES ;i++ )
+ {
+ dispatcher->registerCollisionCreateFunc(i,GIMPACT_SHAPE_PROXYTYPE ,&s_gimpact_cf);
+ }
+
+}
diff --git a/thirdparty/bullet/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h b/thirdparty/bullet/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h
new file mode 100644
index 0000000000..3e5675f729
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h
@@ -0,0 +1,310 @@
+/*! \file btGImpactShape.h
+\author Francisco Leon Najera
+*/
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+
+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_GIMPACT_BVH_CONCAVE_COLLISION_ALGORITHM_H
+#define BT_GIMPACT_BVH_CONCAVE_COLLISION_ALGORITHM_H
+
+#include "BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h"
+#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
+#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
+class btDispatcher;
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+
+#include "LinearMath/btAlignedObjectArray.h"
+
+#include "btGImpactShape.h"
+#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h"
+#include "BulletCollision/CollisionShapes/btCompoundShape.h"
+#include "BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h"
+#include "LinearMath/btIDebugDraw.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
+
+
+//! Collision Algorithm for GImpact Shapes
+/*!
+For register this algorithm in Bullet, proceed as following:
+ \code
+btCollisionDispatcher * dispatcher = static_cast<btCollisionDispatcher *>(m_dynamicsWorld ->getDispatcher());
+btGImpactCollisionAlgorithm::registerAlgorithm(dispatcher);
+ \endcode
+*/
+class btGImpactCollisionAlgorithm : public btActivatingCollisionAlgorithm
+{
+protected:
+ btCollisionAlgorithm * m_convex_algorithm;
+ btPersistentManifold * m_manifoldPtr;
+ btManifoldResult* m_resultOut;
+ const btDispatcherInfo * m_dispatchInfo;
+ int m_triface0;
+ int m_part0;
+ int m_triface1;
+ int m_part1;
+
+
+ //! Creates a new contact point
+ SIMD_FORCE_INLINE btPersistentManifold* newContactManifold(const btCollisionObject* body0,const btCollisionObject* body1)
+ {
+ m_manifoldPtr = m_dispatcher->getNewManifold(body0,body1);
+ return m_manifoldPtr;
+ }
+
+ SIMD_FORCE_INLINE void destroyConvexAlgorithm()
+ {
+ if(m_convex_algorithm)
+ {
+ m_convex_algorithm->~btCollisionAlgorithm();
+ m_dispatcher->freeCollisionAlgorithm( m_convex_algorithm);
+ m_convex_algorithm = NULL;
+ }
+ }
+
+ SIMD_FORCE_INLINE void destroyContactManifolds()
+ {
+ if(m_manifoldPtr == NULL) return;
+ m_dispatcher->releaseManifold(m_manifoldPtr);
+ m_manifoldPtr = NULL;
+ }
+
+ SIMD_FORCE_INLINE void clearCache()
+ {
+ destroyContactManifolds();
+ destroyConvexAlgorithm();
+
+ m_triface0 = -1;
+ m_part0 = -1;
+ m_triface1 = -1;
+ m_part1 = -1;
+ }
+
+ SIMD_FORCE_INLINE btPersistentManifold* getLastManifold()
+ {
+ return m_manifoldPtr;
+ }
+
+
+ // Call before process collision
+ SIMD_FORCE_INLINE void checkManifold(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
+ {
+ if(getLastManifold() == 0)
+ {
+ newContactManifold(body0Wrap->getCollisionObject(),body1Wrap->getCollisionObject());
+ }
+
+ m_resultOut->setPersistentManifold(getLastManifold());
+ }
+
+ // Call before process collision
+ SIMD_FORCE_INLINE btCollisionAlgorithm * newAlgorithm(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
+ {
+ checkManifold(body0Wrap,body1Wrap);
+
+ btCollisionAlgorithm * convex_algorithm = m_dispatcher->findAlgorithm(
+ body0Wrap,body1Wrap,getLastManifold(), BT_CONTACT_POINT_ALGORITHMS);
+ return convex_algorithm ;
+ }
+
+ // Call before process collision
+ SIMD_FORCE_INLINE void checkConvexAlgorithm(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
+ {
+ if(m_convex_algorithm) return;
+ m_convex_algorithm = newAlgorithm(body0Wrap,body1Wrap);
+ }
+
+
+
+
+ void addContactPoint(const btCollisionObjectWrapper * body0Wrap,
+ const btCollisionObjectWrapper * body1Wrap,
+ const btVector3 & point,
+ const btVector3 & normal,
+ btScalar distance);
+
+//! Collision routines
+//!@{
+
+ void collide_gjk_triangles(const btCollisionObjectWrapper* body0Wrap,
+ const btCollisionObjectWrapper* body1Wrap,
+ const btGImpactMeshShapePart * shape0,
+ const btGImpactMeshShapePart * shape1,
+ const int * pairs, int pair_count);
+
+ void collide_sat_triangles(const btCollisionObjectWrapper* body0Wrap,
+ const btCollisionObjectWrapper* body1Wrap,
+ const btGImpactMeshShapePart * shape0,
+ const btGImpactMeshShapePart * shape1,
+ const int * pairs, int pair_count);
+
+
+
+
+ void shape_vs_shape_collision(
+ const btCollisionObjectWrapper* body0,
+ const btCollisionObjectWrapper* body1,
+ const btCollisionShape * shape0,
+ const btCollisionShape * shape1);
+
+ void convex_vs_convex_collision(const btCollisionObjectWrapper* body0Wrap,
+ const btCollisionObjectWrapper* body1Wrap,
+ const btCollisionShape* shape0,
+ const btCollisionShape* shape1);
+
+
+
+ void gimpact_vs_gimpact_find_pairs(
+ const btTransform & trans0,
+ const btTransform & trans1,
+ const btGImpactShapeInterface * shape0,
+ const btGImpactShapeInterface * shape1,btPairSet & pairset);
+
+ void gimpact_vs_shape_find_pairs(
+ const btTransform & trans0,
+ const btTransform & trans1,
+ const btGImpactShapeInterface * shape0,
+ const btCollisionShape * shape1,
+ btAlignedObjectArray<int> & collided_primitives);
+
+
+ void gimpacttrimeshpart_vs_plane_collision(
+ const btCollisionObjectWrapper * body0Wrap,
+ const btCollisionObjectWrapper * body1Wrap,
+ const btGImpactMeshShapePart * shape0,
+ const btStaticPlaneShape * shape1,bool swapped);
+
+
+public:
+
+ btGImpactCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap);
+
+ virtual ~btGImpactCollisionAlgorithm();
+
+ virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+ btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+ virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
+ {
+ if (m_manifoldPtr)
+ manifoldArray.push_back(m_manifoldPtr);
+ }
+
+ btManifoldResult* internalGetResultOut()
+ {
+ return m_resultOut;
+ }
+
+ struct CreateFunc :public btCollisionAlgorithmCreateFunc
+ {
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
+ {
+ void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btGImpactCollisionAlgorithm));
+ return new(mem) btGImpactCollisionAlgorithm(ci,body0Wrap,body1Wrap);
+ }
+ };
+
+ //! Use this function for register the algorithm externally
+ static void registerAlgorithm(btCollisionDispatcher * dispatcher);
+#ifdef TRI_COLLISION_PROFILING
+ //! Gets the average time in miliseconds of tree collisions
+ static float getAverageTreeCollisionTime();
+
+ //! Gets the average time in miliseconds of triangle collisions
+ static float getAverageTriangleCollisionTime();
+#endif //TRI_COLLISION_PROFILING
+
+ //! Collides two gimpact shapes
+ /*!
+ \pre shape0 and shape1 couldn't be btGImpactMeshShape objects
+ */
+
+
+ void gimpact_vs_gimpact(const btCollisionObjectWrapper* body0Wrap,
+ const btCollisionObjectWrapper * body1Wrap,
+ const btGImpactShapeInterface * shape0,
+ const btGImpactShapeInterface * shape1);
+
+ void gimpact_vs_shape(const btCollisionObjectWrapper* body0Wrap,
+ const btCollisionObjectWrapper* body1Wrap,
+ const btGImpactShapeInterface * shape0,
+ const btCollisionShape * shape1,bool swapped);
+
+ void gimpact_vs_compoundshape(const btCollisionObjectWrapper * body0Wrap,
+ const btCollisionObjectWrapper * body1Wrap,
+ const btGImpactShapeInterface * shape0,
+ const btCompoundShape * shape1,bool swapped);
+
+ void gimpact_vs_concave(
+ const btCollisionObjectWrapper * body0Wrap,
+ const btCollisionObjectWrapper * body1Wrap,
+ const btGImpactShapeInterface * shape0,
+ const btConcaveShape * shape1,bool swapped);
+
+
+
+
+ /// Accessor/Mutator pairs for Part and triangleID
+ void setFace0(int value)
+ {
+ m_triface0 = value;
+ }
+ int getFace0()
+ {
+ return m_triface0;
+ }
+ void setFace1(int value)
+ {
+ m_triface1 = value;
+ }
+ int getFace1()
+ {
+ return m_triface1;
+ }
+ void setPart0(int value)
+ {
+ m_part0 = value;
+ }
+ int getPart0()
+ {
+ return m_part0;
+ }
+ void setPart1(int value)
+ {
+ m_part1 = value;
+ }
+ int getPart1()
+ {
+ return m_part1;
+ }
+
+};
+
+
+//algorithm details
+//#define BULLET_TRIANGLE_COLLISION 1
+#define GIMPACT_VS_PLANE_COLLISION 1
+
+
+
+#endif //BT_GIMPACT_BVH_CONCAVE_COLLISION_ALGORITHM_H
diff --git a/thirdparty/bullet/src/BulletCollision/Gimpact/btGImpactMassUtil.h b/thirdparty/bullet/src/BulletCollision/Gimpact/btGImpactMassUtil.h
new file mode 100644
index 0000000000..2543aefcfc
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/Gimpact/btGImpactMassUtil.h
@@ -0,0 +1,60 @@
+/*! \file btGImpactMassUtil.h
+\author Francisco Leon Najera
+*/
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+
+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 GIMPACT_MASS_UTIL_H
+#define GIMPACT_MASS_UTIL_H
+
+#include "LinearMath/btTransform.h"
+
+
+
+SIMD_FORCE_INLINE btVector3 gim_inertia_add_transformed(
+ const btVector3 & source_inertia, const btVector3 & added_inertia, const btTransform & transform)
+{
+ btMatrix3x3 rotatedTensor = transform.getBasis().scaled(added_inertia) * transform.getBasis().transpose();
+
+ btScalar x2 = transform.getOrigin()[0];
+ x2*= x2;
+ btScalar y2 = transform.getOrigin()[1];
+ y2*= y2;
+ btScalar z2 = transform.getOrigin()[2];
+ z2*= z2;
+
+ btScalar ix = rotatedTensor[0][0]*(y2+z2);
+ btScalar iy = rotatedTensor[1][1]*(x2+z2);
+ btScalar iz = rotatedTensor[2][2]*(x2+y2);
+
+ return btVector3(source_inertia[0]+ix,source_inertia[1]+iy,source_inertia[2] + iz);
+}
+
+SIMD_FORCE_INLINE btVector3 gim_get_point_inertia(const btVector3 & point, btScalar mass)
+{
+ btScalar x2 = point[0]*point[0];
+ btScalar y2 = point[1]*point[1];
+ btScalar z2 = point[2]*point[2];
+ return btVector3(mass*(y2+z2),mass*(x2+z2),mass*(x2+y2));
+}
+
+
+#endif //GIMPACT_MESH_SHAPE_H
diff --git a/thirdparty/bullet/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp b/thirdparty/bullet/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp
new file mode 100644
index 0000000000..4528758c37
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp
@@ -0,0 +1,528 @@
+/*! \file gim_box_set.h
+\author Francisco Leon Najera
+*/
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+
+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 "btGImpactQuantizedBvh.h"
+#include "LinearMath/btQuickprof.h"
+
+#ifdef TRI_COLLISION_PROFILING
+btClock g_q_tree_clock;
+
+
+float g_q_accum_tree_collision_time = 0;
+int g_q_count_traversing = 0;
+
+
+void bt_begin_gim02_q_tree_time()
+{
+ g_q_tree_clock.reset();
+}
+
+void bt_end_gim02_q_tree_time()
+{
+ g_q_accum_tree_collision_time += g_q_tree_clock.getTimeMicroseconds();
+ g_q_count_traversing++;
+}
+
+
+//! Gets the average time in miliseconds of tree collisions
+float btGImpactQuantizedBvh::getAverageTreeCollisionTime()
+{
+ if(g_q_count_traversing == 0) return 0;
+
+ float avgtime = g_q_accum_tree_collision_time;
+ avgtime /= (float)g_q_count_traversing;
+
+ g_q_accum_tree_collision_time = 0;
+ g_q_count_traversing = 0;
+ return avgtime;
+
+// float avgtime = g_q_count_traversing;
+// g_q_count_traversing = 0;
+// return avgtime;
+
+}
+
+#endif //TRI_COLLISION_PROFILING
+
+/////////////////////// btQuantizedBvhTree /////////////////////////////////
+
+void btQuantizedBvhTree::calc_quantization(
+ GIM_BVH_DATA_ARRAY & primitive_boxes, btScalar boundMargin)
+{
+ //calc globa box
+ btAABB global_bound;
+ global_bound.invalidate();
+
+ for (int i=0;i<primitive_boxes.size() ;i++ )
+ {
+ global_bound.merge(primitive_boxes[i].m_bound);
+ }
+
+ bt_calc_quantization_parameters(
+ m_global_bound.m_min,m_global_bound.m_max,m_bvhQuantization,global_bound.m_min,global_bound.m_max,boundMargin);
+
+}
+
+
+
+int btQuantizedBvhTree::_calc_splitting_axis(
+ GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex)
+{
+
+ int i;
+
+ btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.));
+ btVector3 variance(btScalar(0.),btScalar(0.),btScalar(0.));
+ int numIndices = endIndex-startIndex;
+
+ for (i=startIndex;i<endIndex;i++)
+ {
+ btVector3 center = btScalar(0.5)*(primitive_boxes[i].m_bound.m_max +
+ primitive_boxes[i].m_bound.m_min);
+ means+=center;
+ }
+ means *= (btScalar(1.)/(btScalar)numIndices);
+
+ for (i=startIndex;i<endIndex;i++)
+ {
+ btVector3 center = btScalar(0.5)*(primitive_boxes[i].m_bound.m_max +
+ primitive_boxes[i].m_bound.m_min);
+ btVector3 diff2 = center-means;
+ diff2 = diff2 * diff2;
+ variance += diff2;
+ }
+ variance *= (btScalar(1.)/ ((btScalar)numIndices-1) );
+
+ return variance.maxAxis();
+}
+
+
+int btQuantizedBvhTree::_sort_and_calc_splitting_index(
+ GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex,
+ int endIndex, int splitAxis)
+{
+ int i;
+ int splitIndex =startIndex;
+ int numIndices = endIndex - startIndex;
+
+ // average of centers
+ btScalar splitValue = 0.0f;
+
+ btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.));
+ for (i=startIndex;i<endIndex;i++)
+ {
+ btVector3 center = btScalar(0.5)*(primitive_boxes[i].m_bound.m_max +
+ primitive_boxes[i].m_bound.m_min);
+ means+=center;
+ }
+ means *= (btScalar(1.)/(btScalar)numIndices);
+
+ splitValue = means[splitAxis];
+
+
+ //sort leafNodes so all values larger then splitValue comes first, and smaller values start from 'splitIndex'.
+ for (i=startIndex;i<endIndex;i++)
+ {
+ btVector3 center = btScalar(0.5)*(primitive_boxes[i].m_bound.m_max +
+ primitive_boxes[i].m_bound.m_min);
+ if (center[splitAxis] > splitValue)
+ {
+ //swap
+ primitive_boxes.swap(i,splitIndex);
+ //swapLeafNodes(i,splitIndex);
+ splitIndex++;
+ }
+ }
+
+ //if the splitIndex causes unbalanced trees, fix this by using the center in between startIndex and endIndex
+ //otherwise the tree-building might fail due to stack-overflows in certain cases.
+ //unbalanced1 is unsafe: it can cause stack overflows
+ //bool unbalanced1 = ((splitIndex==startIndex) || (splitIndex == (endIndex-1)));
+
+ //unbalanced2 should work too: always use center (perfect balanced trees)
+ //bool unbalanced2 = true;
+
+ //this should be safe too:
+ int rangeBalancedIndices = numIndices/3;
+ bool unbalanced = ((splitIndex<=(startIndex+rangeBalancedIndices)) || (splitIndex >=(endIndex-1-rangeBalancedIndices)));
+
+ if (unbalanced)
+ {
+ splitIndex = startIndex+ (numIndices>>1);
+ }
+
+ btAssert(!((splitIndex==startIndex) || (splitIndex == (endIndex))));
+
+ return splitIndex;
+
+}
+
+
+void btQuantizedBvhTree::_build_sub_tree(GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex)
+{
+ int curIndex = m_num_nodes;
+ m_num_nodes++;
+
+ btAssert((endIndex-startIndex)>0);
+
+ if ((endIndex-startIndex)==1)
+ {
+ //We have a leaf node
+ setNodeBound(curIndex,primitive_boxes[startIndex].m_bound);
+ m_node_array[curIndex].setDataIndex(primitive_boxes[startIndex].m_data);
+
+ return;
+ }
+ //calculate Best Splitting Axis and where to split it. Sort the incoming 'leafNodes' array within range 'startIndex/endIndex'.
+
+ //split axis
+ int splitIndex = _calc_splitting_axis(primitive_boxes,startIndex,endIndex);
+
+ splitIndex = _sort_and_calc_splitting_index(
+ primitive_boxes,startIndex,endIndex,
+ splitIndex//split axis
+ );
+
+
+ //calc this node bounding box
+
+ btAABB node_bound;
+ node_bound.invalidate();
+
+ for (int i=startIndex;i<endIndex;i++)
+ {
+ node_bound.merge(primitive_boxes[i].m_bound);
+ }
+
+ setNodeBound(curIndex,node_bound);
+
+
+ //build left branch
+ _build_sub_tree(primitive_boxes, startIndex, splitIndex );
+
+
+ //build right branch
+ _build_sub_tree(primitive_boxes, splitIndex ,endIndex);
+
+ m_node_array[curIndex].setEscapeIndex(m_num_nodes - curIndex);
+
+
+}
+
+//! stackless build tree
+void btQuantizedBvhTree::build_tree(
+ GIM_BVH_DATA_ARRAY & primitive_boxes)
+{
+ calc_quantization(primitive_boxes);
+ // initialize node count to 0
+ m_num_nodes = 0;
+ // allocate nodes
+ m_node_array.resize(primitive_boxes.size()*2);
+
+ _build_sub_tree(primitive_boxes, 0, primitive_boxes.size());
+}
+
+////////////////////////////////////class btGImpactQuantizedBvh
+
+void btGImpactQuantizedBvh::refit()
+{
+ int nodecount = getNodeCount();
+ while(nodecount--)
+ {
+ if(isLeafNode(nodecount))
+ {
+ btAABB leafbox;
+ m_primitive_manager->get_primitive_box(getNodeData(nodecount),leafbox);
+ setNodeBound(nodecount,leafbox);
+ }
+ else
+ {
+ //const GIM_BVH_TREE_NODE * nodepointer = get_node_pointer(nodecount);
+ //get left bound
+ btAABB bound;
+ bound.invalidate();
+
+ btAABB temp_box;
+
+ int child_node = getLeftNode(nodecount);
+ if(child_node)
+ {
+ getNodeBound(child_node,temp_box);
+ bound.merge(temp_box);
+ }
+
+ child_node = getRightNode(nodecount);
+ if(child_node)
+ {
+ getNodeBound(child_node,temp_box);
+ bound.merge(temp_box);
+ }
+
+ setNodeBound(nodecount,bound);
+ }
+ }
+}
+
+//! this rebuild the entire set
+void btGImpactQuantizedBvh::buildSet()
+{
+ //obtain primitive boxes
+ GIM_BVH_DATA_ARRAY primitive_boxes;
+ primitive_boxes.resize(m_primitive_manager->get_primitive_count());
+
+ for (int i = 0;i<primitive_boxes.size() ;i++ )
+ {
+ m_primitive_manager->get_primitive_box(i,primitive_boxes[i].m_bound);
+ primitive_boxes[i].m_data = i;
+ }
+
+ m_box_tree.build_tree(primitive_boxes);
+}
+
+//! returns the indices of the primitives in the m_primitive_manager
+bool btGImpactQuantizedBvh::boxQuery(const btAABB & box, btAlignedObjectArray<int> & collided_results) const
+{
+ int curIndex = 0;
+ int numNodes = getNodeCount();
+
+ //quantize box
+
+ unsigned short quantizedMin[3];
+ unsigned short quantizedMax[3];
+
+ m_box_tree.quantizePoint(quantizedMin,box.m_min);
+ m_box_tree.quantizePoint(quantizedMax,box.m_max);
+
+
+ while (curIndex < numNodes)
+ {
+
+ //catch bugs in tree data
+
+ bool aabbOverlap = m_box_tree.testQuantizedBoxOverlapp(curIndex, quantizedMin,quantizedMax);
+ bool isleafnode = isLeafNode(curIndex);
+
+ if (isleafnode && aabbOverlap)
+ {
+ collided_results.push_back(getNodeData(curIndex));
+ }
+
+ if (aabbOverlap || isleafnode)
+ {
+ //next subnode
+ curIndex++;
+ }
+ else
+ {
+ //skip node
+ curIndex+= getEscapeNodeIndex(curIndex);
+ }
+ }
+ if(collided_results.size()>0) return true;
+ return false;
+}
+
+
+
+//! returns the indices of the primitives in the m_primitive_manager
+bool btGImpactQuantizedBvh::rayQuery(
+ const btVector3 & ray_dir,const btVector3 & ray_origin ,
+ btAlignedObjectArray<int> & collided_results) const
+{
+ int curIndex = 0;
+ int numNodes = getNodeCount();
+
+ while (curIndex < numNodes)
+ {
+ btAABB bound;
+ getNodeBound(curIndex,bound);
+
+ //catch bugs in tree data
+
+ bool aabbOverlap = bound.collide_ray(ray_origin,ray_dir);
+ bool isleafnode = isLeafNode(curIndex);
+
+ if (isleafnode && aabbOverlap)
+ {
+ collided_results.push_back(getNodeData( curIndex));
+ }
+
+ if (aabbOverlap || isleafnode)
+ {
+ //next subnode
+ curIndex++;
+ }
+ else
+ {
+ //skip node
+ curIndex+= getEscapeNodeIndex(curIndex);
+ }
+ }
+ if(collided_results.size()>0) return true;
+ return false;
+}
+
+
+SIMD_FORCE_INLINE bool _quantized_node_collision(
+ const btGImpactQuantizedBvh * boxset0, const btGImpactQuantizedBvh * boxset1,
+ const BT_BOX_BOX_TRANSFORM_CACHE & trans_cache_1to0,
+ int node0 ,int node1, bool complete_primitive_tests)
+{
+ btAABB box0;
+ boxset0->getNodeBound(node0,box0);
+ btAABB box1;
+ boxset1->getNodeBound(node1,box1);
+
+ return box0.overlapping_trans_cache(box1,trans_cache_1to0,complete_primitive_tests );
+// box1.appy_transform_trans_cache(trans_cache_1to0);
+// return box0.has_collision(box1);
+
+}
+
+
+//stackless recursive collision routine
+static void _find_quantized_collision_pairs_recursive(
+ const btGImpactQuantizedBvh * boxset0, const btGImpactQuantizedBvh * boxset1,
+ btPairSet * collision_pairs,
+ const BT_BOX_BOX_TRANSFORM_CACHE & trans_cache_1to0,
+ int node0, int node1, bool complete_primitive_tests)
+{
+
+
+
+ if( _quantized_node_collision(
+ boxset0,boxset1,trans_cache_1to0,
+ node0,node1,complete_primitive_tests) ==false) return;//avoid colliding internal nodes
+
+ if(boxset0->isLeafNode(node0))
+ {
+ if(boxset1->isLeafNode(node1))
+ {
+ // collision result
+ collision_pairs->push_pair(
+ boxset0->getNodeData(node0),boxset1->getNodeData(node1));
+ return;
+ }
+ else
+ {
+
+ //collide left recursive
+
+ _find_quantized_collision_pairs_recursive(
+ boxset0,boxset1,
+ collision_pairs,trans_cache_1to0,
+ node0,boxset1->getLeftNode(node1),false);
+
+ //collide right recursive
+ _find_quantized_collision_pairs_recursive(
+ boxset0,boxset1,
+ collision_pairs,trans_cache_1to0,
+ node0,boxset1->getRightNode(node1),false);
+
+
+ }
+ }
+ else
+ {
+ if(boxset1->isLeafNode(node1))
+ {
+
+ //collide left recursive
+ _find_quantized_collision_pairs_recursive(
+ boxset0,boxset1,
+ collision_pairs,trans_cache_1to0,
+ boxset0->getLeftNode(node0),node1,false);
+
+
+ //collide right recursive
+
+ _find_quantized_collision_pairs_recursive(
+ boxset0,boxset1,
+ collision_pairs,trans_cache_1to0,
+ boxset0->getRightNode(node0),node1,false);
+
+
+ }
+ else
+ {
+ //collide left0 left1
+
+
+
+ _find_quantized_collision_pairs_recursive(
+ boxset0,boxset1,
+ collision_pairs,trans_cache_1to0,
+ boxset0->getLeftNode(node0),boxset1->getLeftNode(node1),false);
+
+ //collide left0 right1
+
+ _find_quantized_collision_pairs_recursive(
+ boxset0,boxset1,
+ collision_pairs,trans_cache_1to0,
+ boxset0->getLeftNode(node0),boxset1->getRightNode(node1),false);
+
+
+ //collide right0 left1
+
+ _find_quantized_collision_pairs_recursive(
+ boxset0,boxset1,
+ collision_pairs,trans_cache_1to0,
+ boxset0->getRightNode(node0),boxset1->getLeftNode(node1),false);
+
+ //collide right0 right1
+
+ _find_quantized_collision_pairs_recursive(
+ boxset0,boxset1,
+ collision_pairs,trans_cache_1to0,
+ boxset0->getRightNode(node0),boxset1->getRightNode(node1),false);
+
+ }// else if node1 is not a leaf
+ }// else if node0 is not a leaf
+}
+
+
+void btGImpactQuantizedBvh::find_collision(const btGImpactQuantizedBvh * boxset0, const btTransform & trans0,
+ const btGImpactQuantizedBvh * boxset1, const btTransform & trans1,
+ btPairSet & collision_pairs)
+{
+
+ if(boxset0->getNodeCount()==0 || boxset1->getNodeCount()==0 ) return;
+
+ BT_BOX_BOX_TRANSFORM_CACHE trans_cache_1to0;
+
+ trans_cache_1to0.calc_from_homogenic(trans0,trans1);
+
+#ifdef TRI_COLLISION_PROFILING
+ bt_begin_gim02_q_tree_time();
+#endif //TRI_COLLISION_PROFILING
+
+ _find_quantized_collision_pairs_recursive(
+ boxset0,boxset1,
+ &collision_pairs,trans_cache_1to0,0,0,true);
+#ifdef TRI_COLLISION_PROFILING
+ bt_end_gim02_q_tree_time();
+#endif //TRI_COLLISION_PROFILING
+
+}
+
+
diff --git a/thirdparty/bullet/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.h b/thirdparty/bullet/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.h
new file mode 100644
index 0000000000..42e5520fc0
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.h
@@ -0,0 +1,305 @@
+#ifndef GIM_QUANTIZED_SET_H_INCLUDED
+#define GIM_QUANTIZED_SET_H_INCLUDED
+
+/*! \file btGImpactQuantizedBvh.h
+\author Francisco Leon Najera
+*/
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+
+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 "btGImpactBvh.h"
+#include "btQuantization.h"
+#include "btGImpactQuantizedBvhStructs.h"
+
+class GIM_QUANTIZED_BVH_NODE_ARRAY:public btAlignedObjectArray<BT_QUANTIZED_BVH_NODE>
+{
+};
+
+
+
+
+//! Basic Box tree structure
+class btQuantizedBvhTree
+{
+protected:
+ int m_num_nodes;
+ GIM_QUANTIZED_BVH_NODE_ARRAY m_node_array;
+ btAABB m_global_bound;
+ btVector3 m_bvhQuantization;
+protected:
+ void calc_quantization(GIM_BVH_DATA_ARRAY & primitive_boxes, btScalar boundMargin = btScalar(1.0) );
+
+ int _sort_and_calc_splitting_index(
+ GIM_BVH_DATA_ARRAY & primitive_boxes,
+ int startIndex, int endIndex, int splitAxis);
+
+ int _calc_splitting_axis(GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex);
+
+ void _build_sub_tree(GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex);
+public:
+ btQuantizedBvhTree()
+ {
+ m_num_nodes = 0;
+ }
+
+ //! prototype functions for box tree management
+ //!@{
+ void build_tree(GIM_BVH_DATA_ARRAY & primitive_boxes);
+
+ SIMD_FORCE_INLINE void quantizePoint(
+ unsigned short * quantizedpoint, const btVector3 & point) const
+ {
+ bt_quantize_clamp(quantizedpoint,point,m_global_bound.m_min,m_global_bound.m_max,m_bvhQuantization);
+ }
+
+
+ SIMD_FORCE_INLINE bool testQuantizedBoxOverlapp(
+ int node_index,
+ unsigned short * quantizedMin,unsigned short * quantizedMax) const
+ {
+ return m_node_array[node_index].testQuantizedBoxOverlapp(quantizedMin,quantizedMax);
+ }
+
+ SIMD_FORCE_INLINE void clearNodes()
+ {
+ m_node_array.clear();
+ m_num_nodes = 0;
+ }
+
+ //! node count
+ SIMD_FORCE_INLINE int getNodeCount() const
+ {
+ return m_num_nodes;
+ }
+
+ //! tells if the node is a leaf
+ SIMD_FORCE_INLINE bool isLeafNode(int nodeindex) const
+ {
+ return m_node_array[nodeindex].isLeafNode();
+ }
+
+ SIMD_FORCE_INLINE int getNodeData(int nodeindex) const
+ {
+ return m_node_array[nodeindex].getDataIndex();
+ }
+
+ SIMD_FORCE_INLINE void getNodeBound(int nodeindex, btAABB & bound) const
+ {
+ bound.m_min = bt_unquantize(
+ m_node_array[nodeindex].m_quantizedAabbMin,
+ m_global_bound.m_min,m_bvhQuantization);
+
+ bound.m_max = bt_unquantize(
+ m_node_array[nodeindex].m_quantizedAabbMax,
+ m_global_bound.m_min,m_bvhQuantization);
+ }
+
+ SIMD_FORCE_INLINE void setNodeBound(int nodeindex, const btAABB & bound)
+ {
+ bt_quantize_clamp( m_node_array[nodeindex].m_quantizedAabbMin,
+ bound.m_min,
+ m_global_bound.m_min,
+ m_global_bound.m_max,
+ m_bvhQuantization);
+
+ bt_quantize_clamp( m_node_array[nodeindex].m_quantizedAabbMax,
+ bound.m_max,
+ m_global_bound.m_min,
+ m_global_bound.m_max,
+ m_bvhQuantization);
+ }
+
+ SIMD_FORCE_INLINE int getLeftNode(int nodeindex) const
+ {
+ return nodeindex+1;
+ }
+
+ SIMD_FORCE_INLINE int getRightNode(int nodeindex) const
+ {
+ if(m_node_array[nodeindex+1].isLeafNode()) return nodeindex+2;
+ return nodeindex+1 + m_node_array[nodeindex+1].getEscapeIndex();
+ }
+
+ SIMD_FORCE_INLINE int getEscapeNodeIndex(int nodeindex) const
+ {
+ return m_node_array[nodeindex].getEscapeIndex();
+ }
+
+ SIMD_FORCE_INLINE const BT_QUANTIZED_BVH_NODE * get_node_pointer(int index = 0) const
+ {
+ return &m_node_array[index];
+ }
+
+ //!@}
+};
+
+
+
+//! Structure for containing Boxes
+/*!
+This class offers an structure for managing a box tree of primitives.
+Requires a Primitive prototype (like btPrimitiveManagerBase )
+*/
+class btGImpactQuantizedBvh
+{
+protected:
+ btQuantizedBvhTree m_box_tree;
+ btPrimitiveManagerBase * m_primitive_manager;
+
+protected:
+ //stackless refit
+ void refit();
+public:
+
+ //! this constructor doesn't build the tree. you must call buildSet
+ btGImpactQuantizedBvh()
+ {
+ m_primitive_manager = NULL;
+ }
+
+ //! this constructor doesn't build the tree. you must call buildSet
+ btGImpactQuantizedBvh(btPrimitiveManagerBase * primitive_manager)
+ {
+ m_primitive_manager = primitive_manager;
+ }
+
+ SIMD_FORCE_INLINE btAABB getGlobalBox() const
+ {
+ btAABB totalbox;
+ getNodeBound(0, totalbox);
+ return totalbox;
+ }
+
+ SIMD_FORCE_INLINE void setPrimitiveManager(btPrimitiveManagerBase * primitive_manager)
+ {
+ m_primitive_manager = primitive_manager;
+ }
+
+ SIMD_FORCE_INLINE btPrimitiveManagerBase * getPrimitiveManager() const
+ {
+ return m_primitive_manager;
+ }
+
+
+//! node manager prototype functions
+///@{
+
+ //! this attemps to refit the box set.
+ SIMD_FORCE_INLINE void update()
+ {
+ refit();
+ }
+
+ //! this rebuild the entire set
+ void buildSet();
+
+ //! returns the indices of the primitives in the m_primitive_manager
+ bool boxQuery(const btAABB & box, btAlignedObjectArray<int> & collided_results) const;
+
+ //! returns the indices of the primitives in the m_primitive_manager
+ SIMD_FORCE_INLINE bool boxQueryTrans(const btAABB & box,
+ const btTransform & transform, btAlignedObjectArray<int> & collided_results) const
+ {
+ btAABB transbox=box;
+ transbox.appy_transform(transform);
+ return boxQuery(transbox,collided_results);
+ }
+
+ //! returns the indices of the primitives in the m_primitive_manager
+ bool rayQuery(
+ const btVector3 & ray_dir,const btVector3 & ray_origin ,
+ btAlignedObjectArray<int> & collided_results) const;
+
+ //! tells if this set has hierarcht
+ SIMD_FORCE_INLINE bool hasHierarchy() const
+ {
+ return true;
+ }
+
+ //! tells if this set is a trimesh
+ SIMD_FORCE_INLINE bool isTrimesh() const
+ {
+ return m_primitive_manager->is_trimesh();
+ }
+
+ //! node count
+ SIMD_FORCE_INLINE int getNodeCount() const
+ {
+ return m_box_tree.getNodeCount();
+ }
+
+ //! tells if the node is a leaf
+ SIMD_FORCE_INLINE bool isLeafNode(int nodeindex) const
+ {
+ return m_box_tree.isLeafNode(nodeindex);
+ }
+
+ SIMD_FORCE_INLINE int getNodeData(int nodeindex) const
+ {
+ return m_box_tree.getNodeData(nodeindex);
+ }
+
+ SIMD_FORCE_INLINE void getNodeBound(int nodeindex, btAABB & bound) const
+ {
+ m_box_tree.getNodeBound(nodeindex, bound);
+ }
+
+ SIMD_FORCE_INLINE void setNodeBound(int nodeindex, const btAABB & bound)
+ {
+ m_box_tree.setNodeBound(nodeindex, bound);
+ }
+
+
+ SIMD_FORCE_INLINE int getLeftNode(int nodeindex) const
+ {
+ return m_box_tree.getLeftNode(nodeindex);
+ }
+
+ SIMD_FORCE_INLINE int getRightNode(int nodeindex) const
+ {
+ return m_box_tree.getRightNode(nodeindex);
+ }
+
+ SIMD_FORCE_INLINE int getEscapeNodeIndex(int nodeindex) const
+ {
+ return m_box_tree.getEscapeNodeIndex(nodeindex);
+ }
+
+ SIMD_FORCE_INLINE void getNodeTriangle(int nodeindex,btPrimitiveTriangle & triangle) const
+ {
+ m_primitive_manager->get_primitive_triangle(getNodeData(nodeindex),triangle);
+ }
+
+
+ SIMD_FORCE_INLINE const BT_QUANTIZED_BVH_NODE * get_node_pointer(int index = 0) const
+ {
+ return m_box_tree.get_node_pointer(index);
+ }
+
+#ifdef TRI_COLLISION_PROFILING
+ static float getAverageTreeCollisionTime();
+#endif //TRI_COLLISION_PROFILING
+
+ static void find_collision(const btGImpactQuantizedBvh * boxset1, const btTransform & trans1,
+ const btGImpactQuantizedBvh * boxset2, const btTransform & trans2,
+ btPairSet & collision_pairs);
+};
+
+#endif // GIM_BOXPRUNING_H_INCLUDED
diff --git a/thirdparty/bullet/src/BulletCollision/Gimpact/btGImpactQuantizedBvhStructs.h b/thirdparty/bullet/src/BulletCollision/Gimpact/btGImpactQuantizedBvhStructs.h
new file mode 100644
index 0000000000..7dd5a1b9d0
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/Gimpact/btGImpactQuantizedBvhStructs.h
@@ -0,0 +1,91 @@
+#ifndef GIM_QUANTIZED_SET_STRUCTS_H_INCLUDED
+#define GIM_QUANTIZED_SET_STRUCTS_H_INCLUDED
+
+/*! \file btGImpactQuantizedBvh.h
+\author Francisco Leon Najera
+*/
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+
+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 "btGImpactBvh.h"
+#include "btQuantization.h"
+
+///btQuantizedBvhNode is a compressed aabb node, 16 bytes.
+///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range).
+ATTRIBUTE_ALIGNED16 (struct) BT_QUANTIZED_BVH_NODE
+{
+ //12 bytes
+ unsigned short int m_quantizedAabbMin[3];
+ unsigned short int m_quantizedAabbMax[3];
+ //4 bytes
+ int m_escapeIndexOrDataIndex;
+
+ BT_QUANTIZED_BVH_NODE()
+ {
+ m_escapeIndexOrDataIndex = 0;
+ }
+
+ SIMD_FORCE_INLINE bool isLeafNode() const
+ {
+ //skipindex is negative (internal node), triangleindex >=0 (leafnode)
+ return (m_escapeIndexOrDataIndex>=0);
+ }
+
+ SIMD_FORCE_INLINE int getEscapeIndex() const
+ {
+ //btAssert(m_escapeIndexOrDataIndex < 0);
+ return -m_escapeIndexOrDataIndex;
+ }
+
+ SIMD_FORCE_INLINE void setEscapeIndex(int index)
+ {
+ m_escapeIndexOrDataIndex = -index;
+ }
+
+ SIMD_FORCE_INLINE int getDataIndex() const
+ {
+ //btAssert(m_escapeIndexOrDataIndex >= 0);
+
+ return m_escapeIndexOrDataIndex;
+ }
+
+ SIMD_FORCE_INLINE void setDataIndex(int index)
+ {
+ m_escapeIndexOrDataIndex = index;
+ }
+
+ SIMD_FORCE_INLINE bool testQuantizedBoxOverlapp(
+ unsigned short * quantizedMin,unsigned short * quantizedMax) const
+ {
+ if(m_quantizedAabbMin[0] > quantizedMax[0] ||
+ m_quantizedAabbMax[0] < quantizedMin[0] ||
+ m_quantizedAabbMin[1] > quantizedMax[1] ||
+ m_quantizedAabbMax[1] < quantizedMin[1] ||
+ m_quantizedAabbMin[2] > quantizedMax[2] ||
+ m_quantizedAabbMax[2] < quantizedMin[2])
+ {
+ return false;
+ }
+ return true;
+ }
+
+};
+
+#endif // GIM_QUANTIZED_SET_STRUCTS_H_INCLUDED
diff --git a/thirdparty/bullet/src/BulletCollision/Gimpact/btGImpactShape.cpp b/thirdparty/bullet/src/BulletCollision/Gimpact/btGImpactShape.cpp
new file mode 100644
index 0000000000..30c85e3fff
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/Gimpact/btGImpactShape.cpp
@@ -0,0 +1,291 @@
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+
+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 "btGImpactShape.h"
+#include "btGImpactMassUtil.h"
+
+
+btGImpactMeshShapePart::btGImpactMeshShapePart( btStridingMeshInterface * meshInterface, int part )
+{
+ // moved from .h to .cpp because of conditional compilation
+ // (The setting of BT_THREADSAFE may differ between various cpp files, so it is best to
+ // avoid using it in h files)
+ m_primitive_manager.m_meshInterface = meshInterface;
+ m_primitive_manager.m_part = part;
+ m_box_set.setPrimitiveManager( &m_primitive_manager );
+#if BT_THREADSAFE
+ // If threadsafe is requested, this object uses a different lock/unlock
+ // model with the btStridingMeshInterface -- lock once when the object is constructed
+ // and unlock once in the destructor.
+ // The other way of locking and unlocking for each collision check in the narrowphase
+ // is not threadsafe. Note these are not thread-locks, they are calls to the meshInterface's
+ // getLockedReadOnlyVertexIndexBase virtual function, which by default just returns a couple of
+ // pointers. In theory a client could override the lock function to do all sorts of
+ // things like reading data from GPU memory, or decompressing data on the fly, but such things
+ // do not seem all that likely or useful, given the performance cost.
+ m_primitive_manager.lock();
+#endif
+}
+
+btGImpactMeshShapePart::~btGImpactMeshShapePart()
+{
+ // moved from .h to .cpp because of conditional compilation
+#if BT_THREADSAFE
+ m_primitive_manager.unlock();
+#endif
+}
+
+void btGImpactMeshShapePart::lockChildShapes() const
+{
+ // moved from .h to .cpp because of conditional compilation
+#if ! BT_THREADSAFE
+ // called in the narrowphase -- not threadsafe!
+ void * dummy = (void*) ( m_box_set.getPrimitiveManager() );
+ TrimeshPrimitiveManager * dummymanager = static_cast<TrimeshPrimitiveManager *>( dummy );
+ dummymanager->lock();
+#endif
+}
+
+void btGImpactMeshShapePart::unlockChildShapes() const
+{
+ // moved from .h to .cpp because of conditional compilation
+#if ! BT_THREADSAFE
+ // called in the narrowphase -- not threadsafe!
+ void * dummy = (void*) ( m_box_set.getPrimitiveManager() );
+ TrimeshPrimitiveManager * dummymanager = static_cast<TrimeshPrimitiveManager *>( dummy );
+ dummymanager->unlock();
+#endif
+}
+
+
+#define CALC_EXACT_INERTIA 1
+
+
+void btGImpactCompoundShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+{
+ lockChildShapes();
+#ifdef CALC_EXACT_INERTIA
+ inertia.setValue(0.f,0.f,0.f);
+
+ int i = this->getNumChildShapes();
+ btScalar shapemass = mass/btScalar(i);
+
+ while(i--)
+ {
+ btVector3 temp_inertia;
+ m_childShapes[i]->calculateLocalInertia(shapemass,temp_inertia);
+ if(childrenHasTransform())
+ {
+ inertia = gim_inertia_add_transformed( inertia,temp_inertia,m_childTransforms[i]);
+ }
+ else
+ {
+ inertia = gim_inertia_add_transformed( inertia,temp_inertia,btTransform::getIdentity());
+ }
+
+ }
+
+#else
+
+ // Calc box inertia
+
+ btScalar lx= m_localAABB.m_max[0] - m_localAABB.m_min[0];
+ btScalar ly= m_localAABB.m_max[1] - m_localAABB.m_min[1];
+ btScalar lz= m_localAABB.m_max[2] - m_localAABB.m_min[2];
+ const btScalar x2 = lx*lx;
+ const btScalar y2 = ly*ly;
+ const btScalar z2 = lz*lz;
+ const btScalar scaledmass = mass * btScalar(0.08333333);
+
+ inertia = scaledmass * (btVector3(y2+z2,x2+z2,x2+y2));
+
+#endif
+ unlockChildShapes();
+}
+
+
+
+void btGImpactMeshShapePart::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+{
+ lockChildShapes();
+
+
+#ifdef CALC_EXACT_INERTIA
+ inertia.setValue(0.f,0.f,0.f);
+
+ int i = this->getVertexCount();
+ btScalar pointmass = mass/btScalar(i);
+
+ while(i--)
+ {
+ btVector3 pointintertia;
+ this->getVertex(i,pointintertia);
+ pointintertia = gim_get_point_inertia(pointintertia,pointmass);
+ inertia+=pointintertia;
+ }
+
+#else
+
+ // Calc box inertia
+
+ btScalar lx= m_localAABB.m_max[0] - m_localAABB.m_min[0];
+ btScalar ly= m_localAABB.m_max[1] - m_localAABB.m_min[1];
+ btScalar lz= m_localAABB.m_max[2] - m_localAABB.m_min[2];
+ const btScalar x2 = lx*lx;
+ const btScalar y2 = ly*ly;
+ const btScalar z2 = lz*lz;
+ const btScalar scaledmass = mass * btScalar(0.08333333);
+
+ inertia = scaledmass * (btVector3(y2+z2,x2+z2,x2+y2));
+
+#endif
+
+ unlockChildShapes();
+}
+
+void btGImpactMeshShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+{
+
+#ifdef CALC_EXACT_INERTIA
+ inertia.setValue(0.f,0.f,0.f);
+
+ int i = this->getMeshPartCount();
+ btScalar partmass = mass/btScalar(i);
+
+ while(i--)
+ {
+ btVector3 partinertia;
+ getMeshPart(i)->calculateLocalInertia(partmass,partinertia);
+ inertia+=partinertia;
+ }
+
+#else
+
+ // Calc box inertia
+
+ btScalar lx= m_localAABB.m_max[0] - m_localAABB.m_min[0];
+ btScalar ly= m_localAABB.m_max[1] - m_localAABB.m_min[1];
+ btScalar lz= m_localAABB.m_max[2] - m_localAABB.m_min[2];
+ const btScalar x2 = lx*lx;
+ const btScalar y2 = ly*ly;
+ const btScalar z2 = lz*lz;
+ const btScalar scaledmass = mass * btScalar(0.08333333);
+
+ inertia = scaledmass * (btVector3(y2+z2,x2+z2,x2+y2));
+
+#endif
+}
+
+void btGImpactMeshShape::rayTest(const btVector3& rayFrom, const btVector3& rayTo, btCollisionWorld::RayResultCallback& resultCallback) const
+{
+}
+
+void btGImpactMeshShapePart::processAllTrianglesRay(btTriangleCallback* callback,const btVector3& rayFrom, const btVector3& rayTo) const
+{
+ lockChildShapes();
+
+ btAlignedObjectArray<int> collided;
+ btVector3 rayDir(rayTo - rayFrom);
+ rayDir.normalize();
+ m_box_set.rayQuery(rayDir, rayFrom, collided);
+
+ if(collided.size()==0)
+ {
+ unlockChildShapes();
+ return;
+ }
+
+ int part = (int)getPart();
+ btPrimitiveTriangle triangle;
+ int i = collided.size();
+ while(i--)
+ {
+ getPrimitiveTriangle(collided[i],triangle);
+ callback->processTriangle(triangle.m_vertices,part,collided[i]);
+ }
+ unlockChildShapes();
+}
+
+void btGImpactMeshShapePart::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
+{
+ lockChildShapes();
+ btAABB box;
+ box.m_min = aabbMin;
+ box.m_max = aabbMax;
+
+ btAlignedObjectArray<int> collided;
+ m_box_set.boxQuery(box,collided);
+
+ if(collided.size()==0)
+ {
+ unlockChildShapes();
+ return;
+ }
+
+ int part = (int)getPart();
+ btPrimitiveTriangle triangle;
+ int i = collided.size();
+ while(i--)
+ {
+ this->getPrimitiveTriangle(collided[i],triangle);
+ callback->processTriangle(triangle.m_vertices,part,collided[i]);
+ }
+ unlockChildShapes();
+
+}
+
+void btGImpactMeshShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
+{
+ int i = m_mesh_parts.size();
+ while(i--)
+ {
+ m_mesh_parts[i]->processAllTriangles(callback,aabbMin,aabbMax);
+ }
+}
+
+void btGImpactMeshShape::processAllTrianglesRay(btTriangleCallback* callback,const btVector3& rayFrom, const btVector3& rayTo) const
+{
+ int i = m_mesh_parts.size();
+ while(i--)
+ {
+ m_mesh_parts[i]->processAllTrianglesRay(callback, rayFrom, rayTo);
+ }
+}
+
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+const char* btGImpactMeshShape::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+ btGImpactMeshShapeData* trimeshData = (btGImpactMeshShapeData*) dataBuffer;
+
+ btCollisionShape::serialize(&trimeshData->m_collisionShapeData,serializer);
+
+ m_meshInterface->serialize(&trimeshData->m_meshInterface, serializer);
+
+ trimeshData->m_collisionMargin = float(m_collisionMargin);
+
+ localScaling.serializeFloat(trimeshData->m_localScaling);
+
+ trimeshData->m_gimpactSubType = int(getGImpactShapeType());
+
+ return "btGImpactMeshShapeData";
+}
+
diff --git a/thirdparty/bullet/src/BulletCollision/Gimpact/btGImpactShape.h b/thirdparty/bullet/src/BulletCollision/Gimpact/btGImpactShape.h
new file mode 100644
index 0000000000..9d7e40562c
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/Gimpact/btGImpactShape.h
@@ -0,0 +1,1164 @@
+/*! \file btGImpactShape.h
+\author Francisco Len Nßjera
+*/
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+
+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 GIMPACT_SHAPE_H
+#define GIMPACT_SHAPE_H
+
+#include "BulletCollision/CollisionShapes/btCollisionShape.h"
+#include "BulletCollision/CollisionShapes/btTriangleShape.h"
+#include "BulletCollision/CollisionShapes/btStridingMeshInterface.h"
+#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
+#include "BulletCollision/CollisionDispatch/btCollisionWorld.h"
+#include "BulletCollision/CollisionShapes/btConcaveShape.h"
+#include "BulletCollision/CollisionShapes/btTetrahedronShape.h"
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btTransform.h"
+#include "LinearMath/btMatrix3x3.h"
+#include "LinearMath/btAlignedObjectArray.h"
+
+#include "btGImpactQuantizedBvh.h" // box tree class
+
+
+//! declare Quantized trees, (you can change to float based trees)
+typedef btGImpactQuantizedBvh btGImpactBoxSet;
+
+enum eGIMPACT_SHAPE_TYPE
+{
+ CONST_GIMPACT_COMPOUND_SHAPE = 0,
+ CONST_GIMPACT_TRIMESH_SHAPE_PART,
+ CONST_GIMPACT_TRIMESH_SHAPE
+};
+
+
+
+//! Helper class for tetrahedrons
+class btTetrahedronShapeEx:public btBU_Simplex1to4
+{
+public:
+ btTetrahedronShapeEx()
+ {
+ m_numVertices = 4;
+ }
+
+
+ SIMD_FORCE_INLINE void setVertices(
+ const btVector3 & v0,const btVector3 & v1,
+ const btVector3 & v2,const btVector3 & v3)
+ {
+ m_vertices[0] = v0;
+ m_vertices[1] = v1;
+ m_vertices[2] = v2;
+ m_vertices[3] = v3;
+ recalcLocalAabb();
+ }
+};
+
+
+//! Base class for gimpact shapes
+class btGImpactShapeInterface : public btConcaveShape
+{
+protected:
+ btAABB m_localAABB;
+ bool m_needs_update;
+ btVector3 localScaling;
+ btGImpactBoxSet m_box_set;// optionally boxset
+
+ //! use this function for perfofm refit in bounding boxes
+ //! use this function for perfofm refit in bounding boxes
+ virtual void calcLocalAABB()
+ {
+ lockChildShapes();
+ if(m_box_set.getNodeCount() == 0)
+ {
+ m_box_set.buildSet();
+ }
+ else
+ {
+ m_box_set.update();
+ }
+ unlockChildShapes();
+
+ m_localAABB = m_box_set.getGlobalBox();
+ }
+
+
+public:
+ btGImpactShapeInterface()
+ {
+ m_shapeType=GIMPACT_SHAPE_PROXYTYPE;
+ m_localAABB.invalidate();
+ m_needs_update = true;
+ localScaling.setValue(1.f,1.f,1.f);
+ }
+
+
+ //! performs refit operation
+ /*!
+ Updates the entire Box set of this shape.
+ \pre postUpdate() must be called for attemps to calculating the box set, else this function
+ will does nothing.
+ \post if m_needs_update == true, then it calls calcLocalAABB();
+ */
+ SIMD_FORCE_INLINE void updateBound()
+ {
+ if(!m_needs_update) return;
+ calcLocalAABB();
+ m_needs_update = false;
+ }
+
+ //! If the Bounding box is not updated, then this class attemps to calculate it.
+ /*!
+ \post Calls updateBound() for update the box set.
+ */
+ void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+ {
+ btAABB transformedbox = m_localAABB;
+ transformedbox.appy_transform(t);
+ aabbMin = transformedbox.m_min;
+ aabbMax = transformedbox.m_max;
+ }
+
+ //! Tells to this object that is needed to refit the box set
+ virtual void postUpdate()
+ {
+ m_needs_update = true;
+ }
+
+ //! Obtains the local box, which is the global calculated box of the total of subshapes
+ SIMD_FORCE_INLINE const btAABB & getLocalBox()
+ {
+ return m_localAABB;
+ }
+
+
+ virtual int getShapeType() const
+ {
+ return GIMPACT_SHAPE_PROXYTYPE;
+ }
+
+ /*!
+ \post You must call updateBound() for update the box set.
+ */
+ virtual void setLocalScaling(const btVector3& scaling)
+ {
+ localScaling = scaling;
+ postUpdate();
+ }
+
+ virtual const btVector3& getLocalScaling() const
+ {
+ return localScaling;
+ }
+
+
+ virtual void setMargin(btScalar margin)
+ {
+ m_collisionMargin = margin;
+ int i = getNumChildShapes();
+ while(i--)
+ {
+ btCollisionShape* child = getChildShape(i);
+ child->setMargin(margin);
+ }
+
+ m_needs_update = true;
+ }
+
+
+ //! Subshape member functions
+ //!@{
+
+ //! Base method for determinig which kind of GIMPACT shape we get
+ virtual eGIMPACT_SHAPE_TYPE getGImpactShapeType() const = 0 ;
+
+ //! gets boxset
+ SIMD_FORCE_INLINE const btGImpactBoxSet * getBoxSet() const
+ {
+ return &m_box_set;
+ }
+
+ //! Determines if this class has a hierarchy structure for sorting its primitives
+ SIMD_FORCE_INLINE bool hasBoxSet() const
+ {
+ if(m_box_set.getNodeCount() == 0) return false;
+ return true;
+ }
+
+ //! Obtains the primitive manager
+ virtual const btPrimitiveManagerBase * getPrimitiveManager() const = 0;
+
+
+ //! Gets the number of children
+ virtual int getNumChildShapes() const = 0;
+
+ //! if true, then its children must get transforms.
+ virtual bool childrenHasTransform() const = 0;
+
+ //! Determines if this shape has triangles
+ virtual bool needsRetrieveTriangles() const = 0;
+
+ //! Determines if this shape has tetrahedrons
+ virtual bool needsRetrieveTetrahedrons() const = 0;
+
+ virtual void getBulletTriangle(int prim_index,btTriangleShapeEx & triangle) const = 0;
+
+ virtual void getBulletTetrahedron(int prim_index,btTetrahedronShapeEx & tetrahedron) const = 0;
+
+
+
+ //! call when reading child shapes
+ virtual void lockChildShapes() const
+ {
+ }
+
+ virtual void unlockChildShapes() const
+ {
+ }
+
+ //! if this trimesh
+ SIMD_FORCE_INLINE void getPrimitiveTriangle(int index,btPrimitiveTriangle & triangle) const
+ {
+ getPrimitiveManager()->get_primitive_triangle(index,triangle);
+ }
+
+
+ //! Retrieves the bound from a child
+ /*!
+ */
+ virtual void getChildAabb(int child_index,const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+ {
+ btAABB child_aabb;
+ getPrimitiveManager()->get_primitive_box(child_index,child_aabb);
+ child_aabb.appy_transform(t);
+ aabbMin = child_aabb.m_min;
+ aabbMax = child_aabb.m_max;
+ }
+
+ //! Gets the children
+ virtual btCollisionShape* getChildShape(int index) = 0;
+
+
+ //! Gets the child
+ virtual const btCollisionShape* getChildShape(int index) const = 0;
+
+ //! Gets the children transform
+ virtual btTransform getChildTransform(int index) const = 0;
+
+ //! Sets the children transform
+ /*!
+ \post You must call updateBound() for update the box set.
+ */
+ virtual void setChildTransform(int index, const btTransform & transform) = 0;
+
+ //!@}
+
+
+ //! virtual method for ray collision
+ virtual void rayTest(const btVector3& rayFrom, const btVector3& rayTo, btCollisionWorld::RayResultCallback& resultCallback) const
+ {
+ (void) rayFrom; (void) rayTo; (void) resultCallback;
+ }
+
+ //! Function for retrieve triangles.
+ /*!
+ It gives the triangles in local space
+ */
+ virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
+ {
+ (void) callback; (void) aabbMin; (void) aabbMax;
+ }
+
+ //! Function for retrieve triangles.
+ /*!
+ It gives the triangles in local space
+ */
+ virtual void processAllTrianglesRay(btTriangleCallback* /*callback*/,const btVector3& /*rayFrom*/, const btVector3& /*rayTo*/) const
+ {
+
+ }
+
+ //!@}
+
+};
+
+
+//! btGImpactCompoundShape allows to handle multiple btCollisionShape objects at once
+/*!
+This class only can manage Convex subshapes
+*/
+class btGImpactCompoundShape : public btGImpactShapeInterface
+{
+public:
+ //! compound primitive manager
+ class CompoundPrimitiveManager:public btPrimitiveManagerBase
+ {
+ public:
+ virtual ~CompoundPrimitiveManager() {}
+ btGImpactCompoundShape * m_compoundShape;
+
+
+ CompoundPrimitiveManager(const CompoundPrimitiveManager& compound)
+ : btPrimitiveManagerBase()
+ {
+ m_compoundShape = compound.m_compoundShape;
+ }
+
+ CompoundPrimitiveManager(btGImpactCompoundShape * compoundShape)
+ {
+ m_compoundShape = compoundShape;
+ }
+
+ CompoundPrimitiveManager()
+ {
+ m_compoundShape = NULL;
+ }
+
+ virtual bool is_trimesh() const
+ {
+ return false;
+ }
+
+ virtual int get_primitive_count() const
+ {
+ return (int )m_compoundShape->getNumChildShapes();
+ }
+
+ virtual void get_primitive_box(int prim_index ,btAABB & primbox) const
+ {
+ btTransform prim_trans;
+ if(m_compoundShape->childrenHasTransform())
+ {
+ prim_trans = m_compoundShape->getChildTransform(prim_index);
+ }
+ else
+ {
+ prim_trans.setIdentity();
+ }
+ const btCollisionShape* shape = m_compoundShape->getChildShape(prim_index);
+ shape->getAabb(prim_trans,primbox.m_min,primbox.m_max);
+ }
+
+ virtual void get_primitive_triangle(int prim_index,btPrimitiveTriangle & triangle) const
+ {
+ btAssert(0);
+ (void) prim_index; (void) triangle;
+ }
+
+ };
+
+
+
+protected:
+ CompoundPrimitiveManager m_primitive_manager;
+ btAlignedObjectArray<btTransform> m_childTransforms;
+ btAlignedObjectArray<btCollisionShape*> m_childShapes;
+
+
+public:
+
+ btGImpactCompoundShape(bool children_has_transform = true)
+ {
+ (void) children_has_transform;
+ m_primitive_manager.m_compoundShape = this;
+ m_box_set.setPrimitiveManager(&m_primitive_manager);
+ }
+
+ virtual ~btGImpactCompoundShape()
+ {
+ }
+
+
+ //! if true, then its children must get transforms.
+ virtual bool childrenHasTransform() const
+ {
+ if(m_childTransforms.size()==0) return false;
+ return true;
+ }
+
+
+ //! Obtains the primitive manager
+ virtual const btPrimitiveManagerBase * getPrimitiveManager() const
+ {
+ return &m_primitive_manager;
+ }
+
+ //! Obtains the compopund primitive manager
+ SIMD_FORCE_INLINE CompoundPrimitiveManager * getCompoundPrimitiveManager()
+ {
+ return &m_primitive_manager;
+ }
+
+ //! Gets the number of children
+ virtual int getNumChildShapes() const
+ {
+ return m_childShapes.size();
+ }
+
+
+ //! Use this method for adding children. Only Convex shapes are allowed.
+ void addChildShape(const btTransform& localTransform,btCollisionShape* shape)
+ {
+ btAssert(shape->isConvex());
+ m_childTransforms.push_back(localTransform);
+ m_childShapes.push_back(shape);
+ }
+
+ //! Use this method for adding children. Only Convex shapes are allowed.
+ void addChildShape(btCollisionShape* shape)
+ {
+ btAssert(shape->isConvex());
+ m_childShapes.push_back(shape);
+ }
+
+ //! Gets the children
+ virtual btCollisionShape* getChildShape(int index)
+ {
+ return m_childShapes[index];
+ }
+
+ //! Gets the children
+ virtual const btCollisionShape* getChildShape(int index) const
+ {
+ return m_childShapes[index];
+ }
+
+ //! Retrieves the bound from a child
+ /*!
+ */
+ virtual void getChildAabb(int child_index,const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+ {
+
+ if(childrenHasTransform())
+ {
+ m_childShapes[child_index]->getAabb(t*m_childTransforms[child_index],aabbMin,aabbMax);
+ }
+ else
+ {
+ m_childShapes[child_index]->getAabb(t,aabbMin,aabbMax);
+ }
+ }
+
+
+ //! Gets the children transform
+ virtual btTransform getChildTransform(int index) const
+ {
+ btAssert(m_childTransforms.size() == m_childShapes.size());
+ return m_childTransforms[index];
+ }
+
+ //! Sets the children transform
+ /*!
+ \post You must call updateBound() for update the box set.
+ */
+ virtual void setChildTransform(int index, const btTransform & transform)
+ {
+ btAssert(m_childTransforms.size() == m_childShapes.size());
+ m_childTransforms[index] = transform;
+ postUpdate();
+ }
+
+ //! Determines if this shape has triangles
+ virtual bool needsRetrieveTriangles() const
+ {
+ return false;
+ }
+
+ //! Determines if this shape has tetrahedrons
+ virtual bool needsRetrieveTetrahedrons() const
+ {
+ return false;
+ }
+
+
+ virtual void getBulletTriangle(int prim_index,btTriangleShapeEx & triangle) const
+ {
+ (void) prim_index; (void) triangle;
+ btAssert(0);
+ }
+
+ virtual void getBulletTetrahedron(int prim_index,btTetrahedronShapeEx & tetrahedron) const
+ {
+ (void) prim_index; (void) tetrahedron;
+ btAssert(0);
+ }
+
+
+ //! Calculates the exact inertia tensor for this shape
+ virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+
+ virtual const char* getName()const
+ {
+ return "GImpactCompound";
+ }
+
+ virtual eGIMPACT_SHAPE_TYPE getGImpactShapeType() const
+ {
+ return CONST_GIMPACT_COMPOUND_SHAPE;
+ }
+
+};
+
+
+
+//! This class manages a sub part of a mesh supplied by the btStridingMeshInterface interface.
+/*!
+- Simply create this shape by passing the btStridingMeshInterface to the constructor btGImpactMeshShapePart, then you must call updateBound() after creating the mesh
+- When making operations with this shape, you must call <b>lock</b> before accessing to the trimesh primitives, and then call <b>unlock</b>
+- You can handle deformable meshes with this shape, by calling postUpdate() every time when changing the mesh vertices.
+
+*/
+class btGImpactMeshShapePart : public btGImpactShapeInterface
+{
+public:
+ //! Trimesh primitive manager
+ /*!
+ Manages the info from btStridingMeshInterface object and controls the Lock/Unlock mechanism
+ */
+ class TrimeshPrimitiveManager:public btPrimitiveManagerBase
+ {
+ public:
+ btScalar m_margin;
+ btStridingMeshInterface * m_meshInterface;
+ btVector3 m_scale;
+ int m_part;
+ int m_lock_count;
+ const unsigned char *vertexbase;
+ int numverts;
+ PHY_ScalarType type;
+ int stride;
+ const unsigned char *indexbase;
+ int indexstride;
+ int numfaces;
+ PHY_ScalarType indicestype;
+
+ TrimeshPrimitiveManager()
+ {
+ m_meshInterface = NULL;
+ m_part = 0;
+ m_margin = 0.01f;
+ m_scale = btVector3(1.f,1.f,1.f);
+ m_lock_count = 0;
+ vertexbase = 0;
+ numverts = 0;
+ stride = 0;
+ indexbase = 0;
+ indexstride = 0;
+ numfaces = 0;
+ }
+
+ TrimeshPrimitiveManager(const TrimeshPrimitiveManager & manager)
+ : btPrimitiveManagerBase()
+ {
+ m_meshInterface = manager.m_meshInterface;
+ m_part = manager.m_part;
+ m_margin = manager.m_margin;
+ m_scale = manager.m_scale;
+ m_lock_count = 0;
+ vertexbase = 0;
+ numverts = 0;
+ stride = 0;
+ indexbase = 0;
+ indexstride = 0;
+ numfaces = 0;
+
+ }
+
+ TrimeshPrimitiveManager(
+ btStridingMeshInterface * meshInterface, int part)
+ {
+ m_meshInterface = meshInterface;
+ m_part = part;
+ m_scale = m_meshInterface->getScaling();
+ m_margin = 0.1f;
+ m_lock_count = 0;
+ vertexbase = 0;
+ numverts = 0;
+ stride = 0;
+ indexbase = 0;
+ indexstride = 0;
+ numfaces = 0;
+
+ }
+
+ virtual ~TrimeshPrimitiveManager() {}
+
+ void lock()
+ {
+ if(m_lock_count>0)
+ {
+ m_lock_count++;
+ return;
+ }
+ m_meshInterface->getLockedReadOnlyVertexIndexBase(
+ &vertexbase,numverts,
+ type, stride,&indexbase, indexstride, numfaces,indicestype,m_part);
+
+ m_lock_count = 1;
+ }
+
+ void unlock()
+ {
+ if(m_lock_count == 0) return;
+ if(m_lock_count>1)
+ {
+ --m_lock_count;
+ return;
+ }
+ m_meshInterface->unLockReadOnlyVertexBase(m_part);
+ vertexbase = NULL;
+ m_lock_count = 0;
+ }
+
+ virtual bool is_trimesh() const
+ {
+ return true;
+ }
+
+ virtual int get_primitive_count() const
+ {
+ return (int )numfaces;
+ }
+
+ SIMD_FORCE_INLINE int get_vertex_count() const
+ {
+ return (int )numverts;
+ }
+
+ SIMD_FORCE_INLINE void get_indices(int face_index,unsigned int &i0,unsigned int &i1,unsigned int &i2) const
+ {
+ if(indicestype == PHY_SHORT)
+ {
+ unsigned short* s_indices = (unsigned short *)(indexbase + face_index * indexstride);
+ i0 = s_indices[0];
+ i1 = s_indices[1];
+ i2 = s_indices[2];
+ }
+ else
+ {
+ unsigned int * i_indices = (unsigned int *)(indexbase + face_index*indexstride);
+ i0 = i_indices[0];
+ i1 = i_indices[1];
+ i2 = i_indices[2];
+ }
+ }
+
+ SIMD_FORCE_INLINE void get_vertex(unsigned int vertex_index, btVector3 & vertex) const
+ {
+ if(type == PHY_DOUBLE)
+ {
+ double * dvertices = (double *)(vertexbase + vertex_index*stride);
+ vertex[0] = btScalar(dvertices[0]*m_scale[0]);
+ vertex[1] = btScalar(dvertices[1]*m_scale[1]);
+ vertex[2] = btScalar(dvertices[2]*m_scale[2]);
+ }
+ else
+ {
+ float * svertices = (float *)(vertexbase + vertex_index*stride);
+ vertex[0] = svertices[0]*m_scale[0];
+ vertex[1] = svertices[1]*m_scale[1];
+ vertex[2] = svertices[2]*m_scale[2];
+ }
+ }
+
+ virtual void get_primitive_box(int prim_index ,btAABB & primbox) const
+ {
+ btPrimitiveTriangle triangle;
+ get_primitive_triangle(prim_index,triangle);
+ primbox.calc_from_triangle_margin(
+ triangle.m_vertices[0],
+ triangle.m_vertices[1],triangle.m_vertices[2],triangle.m_margin);
+ }
+
+ virtual void get_primitive_triangle(int prim_index,btPrimitiveTriangle & triangle) const
+ {
+ unsigned int indices[3];
+ get_indices(prim_index,indices[0],indices[1],indices[2]);
+ get_vertex(indices[0],triangle.m_vertices[0]);
+ get_vertex(indices[1],triangle.m_vertices[1]);
+ get_vertex(indices[2],triangle.m_vertices[2]);
+ triangle.m_margin = m_margin;
+ }
+
+ SIMD_FORCE_INLINE void get_bullet_triangle(int prim_index,btTriangleShapeEx & triangle) const
+ {
+ unsigned int indices[3];
+ get_indices(prim_index,indices[0],indices[1],indices[2]);
+ get_vertex(indices[0],triangle.m_vertices1[0]);
+ get_vertex(indices[1],triangle.m_vertices1[1]);
+ get_vertex(indices[2],triangle.m_vertices1[2]);
+ triangle.setMargin(m_margin);
+ }
+
+ };
+
+
+protected:
+ TrimeshPrimitiveManager m_primitive_manager;
+public:
+
+ btGImpactMeshShapePart()
+ {
+ m_box_set.setPrimitiveManager(&m_primitive_manager);
+ }
+
+ btGImpactMeshShapePart( btStridingMeshInterface * meshInterface, int part );
+ virtual ~btGImpactMeshShapePart();
+
+ //! if true, then its children must get transforms.
+ virtual bool childrenHasTransform() const
+ {
+ return false;
+ }
+
+
+ //! call when reading child shapes
+ virtual void lockChildShapes() const;
+ virtual void unlockChildShapes() const;
+
+ //! Gets the number of children
+ virtual int getNumChildShapes() const
+ {
+ return m_primitive_manager.get_primitive_count();
+ }
+
+
+ //! Gets the children
+ virtual btCollisionShape* getChildShape(int index)
+ {
+ (void) index;
+ btAssert(0);
+ return NULL;
+ }
+
+
+
+ //! Gets the child
+ virtual const btCollisionShape* getChildShape(int index) const
+ {
+ (void) index;
+ btAssert(0);
+ return NULL;
+ }
+
+ //! Gets the children transform
+ virtual btTransform getChildTransform(int index) const
+ {
+ (void) index;
+ btAssert(0);
+ return btTransform();
+ }
+
+ //! Sets the children transform
+ /*!
+ \post You must call updateBound() for update the box set.
+ */
+ virtual void setChildTransform(int index, const btTransform & transform)
+ {
+ (void) index;
+ (void) transform;
+ btAssert(0);
+ }
+
+
+ //! Obtains the primitive manager
+ virtual const btPrimitiveManagerBase * getPrimitiveManager() const
+ {
+ return &m_primitive_manager;
+ }
+
+ SIMD_FORCE_INLINE TrimeshPrimitiveManager * getTrimeshPrimitiveManager()
+ {
+ return &m_primitive_manager;
+ }
+
+
+
+
+
+ virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+
+
+
+
+ virtual const char* getName()const
+ {
+ return "GImpactMeshShapePart";
+ }
+
+ virtual eGIMPACT_SHAPE_TYPE getGImpactShapeType() const
+ {
+ return CONST_GIMPACT_TRIMESH_SHAPE_PART;
+ }
+
+ //! Determines if this shape has triangles
+ virtual bool needsRetrieveTriangles() const
+ {
+ return true;
+ }
+
+ //! Determines if this shape has tetrahedrons
+ virtual bool needsRetrieveTetrahedrons() const
+ {
+ return false;
+ }
+
+ virtual void getBulletTriangle(int prim_index,btTriangleShapeEx & triangle) const
+ {
+ m_primitive_manager.get_bullet_triangle(prim_index,triangle);
+ }
+
+ virtual void getBulletTetrahedron(int prim_index,btTetrahedronShapeEx & tetrahedron) const
+ {
+ (void) prim_index;
+ (void) tetrahedron;
+ btAssert(0);
+ }
+
+
+
+ SIMD_FORCE_INLINE int getVertexCount() const
+ {
+ return m_primitive_manager.get_vertex_count();
+ }
+
+ SIMD_FORCE_INLINE void getVertex(int vertex_index, btVector3 & vertex) const
+ {
+ m_primitive_manager.get_vertex(vertex_index,vertex);
+ }
+
+ SIMD_FORCE_INLINE void setMargin(btScalar margin)
+ {
+ m_primitive_manager.m_margin = margin;
+ postUpdate();
+ }
+
+ SIMD_FORCE_INLINE btScalar getMargin() const
+ {
+ return m_primitive_manager.m_margin;
+ }
+
+ virtual void setLocalScaling(const btVector3& scaling)
+ {
+ m_primitive_manager.m_scale = scaling;
+ postUpdate();
+ }
+
+ virtual const btVector3& getLocalScaling() const
+ {
+ return m_primitive_manager.m_scale;
+ }
+
+ SIMD_FORCE_INLINE int getPart() const
+ {
+ return (int)m_primitive_manager.m_part;
+ }
+
+ virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
+ virtual void processAllTrianglesRay(btTriangleCallback* callback,const btVector3& rayFrom,const btVector3& rayTo) const;
+};
+
+
+//! This class manages a mesh supplied by the btStridingMeshInterface interface.
+/*!
+Set of btGImpactMeshShapePart parts
+- Simply create this shape by passing the btStridingMeshInterface to the constructor btGImpactMeshShape, then you must call updateBound() after creating the mesh
+
+- You can handle deformable meshes with this shape, by calling postUpdate() every time when changing the mesh vertices.
+
+*/
+class btGImpactMeshShape : public btGImpactShapeInterface
+{
+ btStridingMeshInterface* m_meshInterface;
+
+protected:
+ btAlignedObjectArray<btGImpactMeshShapePart*> m_mesh_parts;
+ void buildMeshParts(btStridingMeshInterface * meshInterface)
+ {
+ for (int i=0;i<meshInterface->getNumSubParts() ;++i )
+ {
+ btGImpactMeshShapePart * newpart = new btGImpactMeshShapePart(meshInterface,i);
+ m_mesh_parts.push_back(newpart);
+ }
+ }
+
+ //! use this function for perfofm refit in bounding boxes
+ virtual void calcLocalAABB()
+ {
+ m_localAABB.invalidate();
+ int i = m_mesh_parts.size();
+ while(i--)
+ {
+ m_mesh_parts[i]->updateBound();
+ m_localAABB.merge(m_mesh_parts[i]->getLocalBox());
+ }
+ }
+
+public:
+ btGImpactMeshShape(btStridingMeshInterface * meshInterface)
+ {
+ m_meshInterface = meshInterface;
+ buildMeshParts(meshInterface);
+ }
+
+ virtual ~btGImpactMeshShape()
+ {
+ int i = m_mesh_parts.size();
+ while(i--)
+ {
+ btGImpactMeshShapePart * part = m_mesh_parts[i];
+ delete part;
+ }
+ m_mesh_parts.clear();
+ }
+
+
+ btStridingMeshInterface* getMeshInterface()
+ {
+ return m_meshInterface;
+ }
+
+ const btStridingMeshInterface* getMeshInterface() const
+ {
+ return m_meshInterface;
+ }
+
+ int getMeshPartCount() const
+ {
+ return m_mesh_parts.size();
+ }
+
+ btGImpactMeshShapePart * getMeshPart(int index)
+ {
+ return m_mesh_parts[index];
+ }
+
+
+
+ const btGImpactMeshShapePart * getMeshPart(int index) const
+ {
+ return m_mesh_parts[index];
+ }
+
+
+ virtual void setLocalScaling(const btVector3& scaling)
+ {
+ localScaling = scaling;
+
+ int i = m_mesh_parts.size();
+ while(i--)
+ {
+ btGImpactMeshShapePart * part = m_mesh_parts[i];
+ part->setLocalScaling(scaling);
+ }
+
+ m_needs_update = true;
+ }
+
+ virtual void setMargin(btScalar margin)
+ {
+ m_collisionMargin = margin;
+
+ int i = m_mesh_parts.size();
+ while(i--)
+ {
+ btGImpactMeshShapePart * part = m_mesh_parts[i];
+ part->setMargin(margin);
+ }
+
+ m_needs_update = true;
+ }
+
+ //! Tells to this object that is needed to refit all the meshes
+ virtual void postUpdate()
+ {
+ int i = m_mesh_parts.size();
+ while(i--)
+ {
+ btGImpactMeshShapePart * part = m_mesh_parts[i];
+ part->postUpdate();
+ }
+
+ m_needs_update = true;
+ }
+
+ virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+
+
+ //! Obtains the primitive manager
+ virtual const btPrimitiveManagerBase * getPrimitiveManager() const
+ {
+ btAssert(0);
+ return NULL;
+ }
+
+
+ //! Gets the number of children
+ virtual int getNumChildShapes() const
+ {
+ btAssert(0);
+ return 0;
+ }
+
+
+ //! if true, then its children must get transforms.
+ virtual bool childrenHasTransform() const
+ {
+ btAssert(0);
+ return false;
+ }
+
+ //! Determines if this shape has triangles
+ virtual bool needsRetrieveTriangles() const
+ {
+ btAssert(0);
+ return false;
+ }
+
+ //! Determines if this shape has tetrahedrons
+ virtual bool needsRetrieveTetrahedrons() const
+ {
+ btAssert(0);
+ return false;
+ }
+
+ virtual void getBulletTriangle(int prim_index,btTriangleShapeEx & triangle) const
+ {
+ (void) prim_index; (void) triangle;
+ btAssert(0);
+ }
+
+ virtual void getBulletTetrahedron(int prim_index,btTetrahedronShapeEx & tetrahedron) const
+ {
+ (void) prim_index; (void) tetrahedron;
+ btAssert(0);
+ }
+
+ //! call when reading child shapes
+ virtual void lockChildShapes() const
+ {
+ btAssert(0);
+ }
+
+ virtual void unlockChildShapes() const
+ {
+ btAssert(0);
+ }
+
+
+
+
+ //! Retrieves the bound from a child
+ /*!
+ */
+ virtual void getChildAabb(int child_index,const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+ {
+ (void) child_index; (void) t; (void) aabbMin; (void) aabbMax;
+ btAssert(0);
+ }
+
+ //! Gets the children
+ virtual btCollisionShape* getChildShape(int index)
+ {
+ (void) index;
+ btAssert(0);
+ return NULL;
+ }
+
+
+ //! Gets the child
+ virtual const btCollisionShape* getChildShape(int index) const
+ {
+ (void) index;
+ btAssert(0);
+ return NULL;
+ }
+
+ //! Gets the children transform
+ virtual btTransform getChildTransform(int index) const
+ {
+ (void) index;
+ btAssert(0);
+ return btTransform();
+ }
+
+ //! Sets the children transform
+ /*!
+ \post You must call updateBound() for update the box set.
+ */
+ virtual void setChildTransform(int index, const btTransform & transform)
+ {
+ (void) index; (void) transform;
+ btAssert(0);
+ }
+
+
+ virtual eGIMPACT_SHAPE_TYPE getGImpactShapeType() const
+ {
+ return CONST_GIMPACT_TRIMESH_SHAPE;
+ }
+
+
+ virtual const char* getName()const
+ {
+ return "GImpactMesh";
+ }
+
+ virtual void rayTest(const btVector3& rayFrom, const btVector3& rayTo, btCollisionWorld::RayResultCallback& resultCallback) const;
+
+ //! Function for retrieve triangles.
+ /*!
+ It gives the triangles in local space
+ */
+ virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
+
+ virtual void processAllTrianglesRay (btTriangleCallback* callback,const btVector3& rayFrom,const btVector3& rayTo) const;
+
+ virtual int calculateSerializeBufferSize() const;
+
+ ///fills the dataBuffer and returns the struct name (and 0 on failure)
+ virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
+
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btGImpactMeshShapeData
+{
+ btCollisionShapeData m_collisionShapeData;
+
+ btStridingMeshInterfaceData m_meshInterface;
+
+ btVector3FloatData m_localScaling;
+
+ float m_collisionMargin;
+
+ int m_gimpactSubType;
+};
+
+SIMD_FORCE_INLINE int btGImpactMeshShape::calculateSerializeBufferSize() const
+{
+ return sizeof(btGImpactMeshShapeData);
+}
+
+
+#endif //GIMPACT_MESH_SHAPE_H
diff --git a/thirdparty/bullet/src/BulletCollision/Gimpact/btGenericPoolAllocator.cpp b/thirdparty/bullet/src/BulletCollision/Gimpact/btGenericPoolAllocator.cpp
new file mode 100644
index 0000000000..5d07d1adb9
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/Gimpact/btGenericPoolAllocator.cpp
@@ -0,0 +1,283 @@
+/*! \file btGenericPoolAllocator.cpp
+\author Francisco Leon Najera. email projectileman@yahoo.com
+
+General purpose allocator class
+*/
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btGenericPoolAllocator.h"
+
+
+
+/// *************** btGenericMemoryPool ******************///////////
+
+size_t btGenericMemoryPool::allocate_from_free_nodes(size_t num_elements)
+{
+ size_t ptr = BT_UINT_MAX;
+
+ if(m_free_nodes_count == 0) return BT_UINT_MAX;
+ // find an avaliable free node with the correct size
+ size_t revindex = m_free_nodes_count;
+
+ while(revindex-- && ptr == BT_UINT_MAX)
+ {
+ if(m_allocated_sizes[m_free_nodes[revindex]]>=num_elements)
+ {
+ ptr = revindex;
+ }
+ }
+ if(ptr == BT_UINT_MAX) return BT_UINT_MAX; // not found
+
+
+ revindex = ptr;
+ ptr = m_free_nodes[revindex];
+ // post: ptr contains the node index, and revindex the index in m_free_nodes
+
+ size_t finalsize = m_allocated_sizes[ptr];
+ finalsize -= num_elements;
+
+ m_allocated_sizes[ptr] = num_elements;
+
+ // post: finalsize>=0, m_allocated_sizes[ptr] has the requested size
+
+ if(finalsize>0) // preserve free node, there are some free memory
+ {
+ m_free_nodes[revindex] = ptr + num_elements;
+ m_allocated_sizes[ptr + num_elements] = finalsize;
+ }
+ else // delete free node
+ {
+ // swap with end
+ m_free_nodes[revindex] = m_free_nodes[m_free_nodes_count-1];
+ m_free_nodes_count--;
+ }
+
+ return ptr;
+}
+
+size_t btGenericMemoryPool::allocate_from_pool(size_t num_elements)
+{
+ if(m_allocated_count+num_elements>m_max_element_count) return BT_UINT_MAX;
+
+ size_t ptr = m_allocated_count;
+
+ m_allocated_sizes[m_allocated_count] = num_elements;
+ m_allocated_count+=num_elements;
+
+ return ptr;
+}
+
+
+void btGenericMemoryPool::init_pool(size_t element_size, size_t element_count)
+{
+ m_allocated_count = 0;
+ m_free_nodes_count = 0;
+
+ m_element_size = element_size;
+ m_max_element_count = element_count;
+
+
+
+
+ m_pool = (unsigned char *) btAlignedAlloc(m_element_size*m_max_element_count,16);
+ m_free_nodes = (size_t *) btAlignedAlloc(sizeof(size_t)*m_max_element_count,16);
+ m_allocated_sizes = (size_t *) btAlignedAlloc(sizeof(size_t)*m_max_element_count,16);
+
+ for (size_t i = 0;i< m_max_element_count;i++ )
+ {
+ m_allocated_sizes[i] = 0;
+ }
+}
+
+void btGenericMemoryPool::end_pool()
+{
+ btAlignedFree(m_pool);
+ btAlignedFree(m_free_nodes);
+ btAlignedFree(m_allocated_sizes);
+ m_allocated_count = 0;
+ m_free_nodes_count = 0;
+}
+
+
+//! Allocates memory in pool
+/*!
+\param size_bytes size in bytes of the buffer
+*/
+void * btGenericMemoryPool::allocate(size_t size_bytes)
+{
+
+ size_t module = size_bytes%m_element_size;
+ size_t element_count = size_bytes/m_element_size;
+ if(module>0) element_count++;
+
+ size_t alloc_pos = allocate_from_free_nodes(element_count);
+ // a free node is found
+ if(alloc_pos != BT_UINT_MAX)
+ {
+ return get_element_data(alloc_pos);
+ }
+ // allocate directly on pool
+ alloc_pos = allocate_from_pool(element_count);
+
+ if(alloc_pos == BT_UINT_MAX) return NULL; // not space
+ return get_element_data(alloc_pos);
+}
+
+bool btGenericMemoryPool::freeMemory(void * pointer)
+{
+ unsigned char * pointer_pos = (unsigned char *)pointer;
+ unsigned char * pool_pos = (unsigned char *)m_pool;
+ // calc offset
+ if(pointer_pos<pool_pos) return false;//other pool
+ size_t offset = size_t(pointer_pos - pool_pos);
+ if(offset>=get_pool_capacity()) return false;// far away
+
+ // find free position
+ m_free_nodes[m_free_nodes_count] = offset/m_element_size;
+ m_free_nodes_count++;
+ return true;
+}
+
+
+/// *******************! btGenericPoolAllocator *******************!///
+
+
+btGenericPoolAllocator::~btGenericPoolAllocator()
+{
+ // destroy pools
+ size_t i;
+ for (i=0;i<m_pool_count;i++)
+ {
+ m_pools[i]->end_pool();
+ btAlignedFree(m_pools[i]);
+ }
+}
+
+
+// creates a pool
+btGenericMemoryPool * btGenericPoolAllocator::push_new_pool()
+{
+ if(m_pool_count >= BT_DEFAULT_MAX_POOLS) return NULL;
+
+ btGenericMemoryPool * newptr = (btGenericMemoryPool *)btAlignedAlloc(sizeof(btGenericMemoryPool),16);
+
+ m_pools[m_pool_count] = newptr;
+
+ m_pools[m_pool_count]->init_pool(m_pool_element_size,m_pool_element_count);
+
+ m_pool_count++;
+ return newptr;
+}
+
+void * btGenericPoolAllocator::failback_alloc(size_t size_bytes)
+{
+
+ btGenericMemoryPool * pool = NULL;
+
+
+ if(size_bytes<=get_pool_capacity())
+ {
+ pool = push_new_pool();
+ }
+
+ if(pool==NULL) // failback
+ {
+ return btAlignedAlloc(size_bytes,16);
+ }
+
+ return pool->allocate(size_bytes);
+}
+
+bool btGenericPoolAllocator::failback_free(void * pointer)
+{
+ btAlignedFree(pointer);
+ return true;
+}
+
+
+//! Allocates memory in pool
+/*!
+\param size_bytes size in bytes of the buffer
+*/
+void * btGenericPoolAllocator::allocate(size_t size_bytes)
+{
+ void * ptr = NULL;
+
+ size_t i = 0;
+ while(i<m_pool_count && ptr == NULL)
+ {
+ ptr = m_pools[i]->allocate(size_bytes);
+ ++i;
+ }
+
+ if(ptr) return ptr;
+
+ return failback_alloc(size_bytes);
+}
+
+bool btGenericPoolAllocator::freeMemory(void * pointer)
+{
+ bool result = false;
+
+ size_t i = 0;
+ while(i<m_pool_count && result == false)
+ {
+ result = m_pools[i]->freeMemory(pointer);
+ ++i;
+ }
+
+ if(result) return true;
+
+ return failback_free(pointer);
+}
+
+/// ************** STANDARD ALLOCATOR ***************************///
+
+
+#define BT_DEFAULT_POOL_SIZE 32768
+#define BT_DEFAULT_POOL_ELEMENT_SIZE 8
+
+// main allocator
+class GIM_STANDARD_ALLOCATOR: public btGenericPoolAllocator
+{
+public:
+ GIM_STANDARD_ALLOCATOR():btGenericPoolAllocator(BT_DEFAULT_POOL_ELEMENT_SIZE,BT_DEFAULT_POOL_SIZE)
+ {
+ }
+};
+
+// global allocator
+GIM_STANDARD_ALLOCATOR g_main_allocator;
+
+
+void * btPoolAlloc(size_t size)
+{
+ return g_main_allocator.allocate(size);
+}
+
+void * btPoolRealloc(void *ptr, size_t oldsize, size_t newsize)
+{
+ void * newptr = btPoolAlloc(newsize);
+ size_t copysize = oldsize<newsize?oldsize:newsize;
+ memcpy(newptr,ptr,copysize);
+ btPoolFree(ptr);
+ return newptr;
+}
+
+void btPoolFree(void *ptr)
+{
+ g_main_allocator.freeMemory(ptr);
+}
diff --git a/thirdparty/bullet/src/BulletCollision/Gimpact/btGenericPoolAllocator.h b/thirdparty/bullet/src/BulletCollision/Gimpact/btGenericPoolAllocator.h
new file mode 100644
index 0000000000..b46d851634
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/Gimpact/btGenericPoolAllocator.h
@@ -0,0 +1,163 @@
+/*! \file btGenericPoolAllocator.h
+\author Francisco Leon Najera. email projectileman@yahoo.com
+
+General purpose allocator class
+*/
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_GENERIC_POOL_ALLOCATOR_H
+#define BT_GENERIC_POOL_ALLOCATOR_H
+
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+#include "LinearMath/btAlignedAllocator.h"
+
+#define BT_UINT_MAX UINT_MAX
+#define BT_DEFAULT_MAX_POOLS 16
+
+
+//! Generic Pool class
+class btGenericMemoryPool
+{
+public:
+ unsigned char * m_pool; //[m_element_size*m_max_element_count];
+ size_t * m_free_nodes; //[m_max_element_count];//! free nodes
+ size_t * m_allocated_sizes;//[m_max_element_count];//! Number of elements allocated per node
+ size_t m_allocated_count;
+ size_t m_free_nodes_count;
+protected:
+ size_t m_element_size;
+ size_t m_max_element_count;
+
+ size_t allocate_from_free_nodes(size_t num_elements);
+ size_t allocate_from_pool(size_t num_elements);
+
+public:
+
+ void init_pool(size_t element_size, size_t element_count);
+
+ void end_pool();
+
+
+ btGenericMemoryPool(size_t element_size, size_t element_count)
+ {
+ init_pool(element_size, element_count);
+ }
+
+ ~btGenericMemoryPool()
+ {
+ end_pool();
+ }
+
+
+ inline size_t get_pool_capacity()
+ {
+ return m_element_size*m_max_element_count;
+ }
+
+ inline size_t gem_element_size()
+ {
+ return m_element_size;
+ }
+
+ inline size_t get_max_element_count()
+ {
+ return m_max_element_count;
+ }
+
+ inline size_t get_allocated_count()
+ {
+ return m_allocated_count;
+ }
+
+ inline size_t get_free_positions_count()
+ {
+ return m_free_nodes_count;
+ }
+
+ inline void * get_element_data(size_t element_index)
+ {
+ return &m_pool[element_index*m_element_size];
+ }
+
+ //! Allocates memory in pool
+ /*!
+ \param size_bytes size in bytes of the buffer
+ */
+ void * allocate(size_t size_bytes);
+
+ bool freeMemory(void * pointer);
+};
+
+
+
+
+//! Generic Allocator with pools
+/*!
+General purpose Allocator which can create Memory Pools dynamiacally as needed.
+*/
+class btGenericPoolAllocator
+{
+protected:
+ size_t m_pool_element_size;
+ size_t m_pool_element_count;
+public:
+ btGenericMemoryPool * m_pools[BT_DEFAULT_MAX_POOLS];
+ size_t m_pool_count;
+
+
+ inline size_t get_pool_capacity()
+ {
+ return m_pool_element_size*m_pool_element_count;
+ }
+
+
+protected:
+ // creates a pool
+ btGenericMemoryPool * push_new_pool();
+
+ void * failback_alloc(size_t size_bytes);
+
+ bool failback_free(void * pointer);
+public:
+
+ btGenericPoolAllocator(size_t pool_element_size, size_t pool_element_count)
+ {
+ m_pool_count = 0;
+ m_pool_element_size = pool_element_size;
+ m_pool_element_count = pool_element_count;
+ }
+
+ virtual ~btGenericPoolAllocator();
+
+ //! Allocates memory in pool
+ /*!
+ \param size_bytes size in bytes of the buffer
+ */
+ void * allocate(size_t size_bytes);
+
+ bool freeMemory(void * pointer);
+};
+
+
+
+void * btPoolAlloc(size_t size);
+void * btPoolRealloc(void *ptr, size_t oldsize, size_t newsize);
+void btPoolFree(void *ptr);
+
+
+#endif
diff --git a/thirdparty/bullet/src/BulletCollision/Gimpact/btGeometryOperations.h b/thirdparty/bullet/src/BulletCollision/Gimpact/btGeometryOperations.h
new file mode 100644
index 0000000000..60f06510ad
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/Gimpact/btGeometryOperations.h
@@ -0,0 +1,212 @@
+#ifndef BT_BASIC_GEOMETRY_OPERATIONS_H_INCLUDED
+#define BT_BASIC_GEOMETRY_OPERATIONS_H_INCLUDED
+
+/*! \file btGeometryOperations.h
+*\author Francisco Leon Najera
+
+*/
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+
+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 "btBoxCollision.h"
+
+
+
+
+
+#define PLANEDIREPSILON 0.0000001f
+#define PARALELENORMALS 0.000001f
+
+
+#define BT_CLAMP(number,minval,maxval) (number<minval?minval:(number>maxval?maxval:number))
+
+/// Calc a plane from a triangle edge an a normal. plane is a vec4f
+SIMD_FORCE_INLINE void bt_edge_plane(const btVector3 & e1,const btVector3 & e2, const btVector3 & normal,btVector4 & plane)
+{
+ btVector3 planenormal = (e2-e1).cross(normal);
+ planenormal.normalize();
+ plane.setValue(planenormal[0],planenormal[1],planenormal[2],e2.dot(planenormal));
+}
+
+
+
+//***************** SEGMENT and LINE FUNCTIONS **********************************///
+
+/*! Finds the closest point(cp) to (v) on a segment (e1,e2)
+ */
+SIMD_FORCE_INLINE void bt_closest_point_on_segment(
+ btVector3 & cp, const btVector3 & v,
+ const btVector3 &e1,const btVector3 &e2)
+{
+ btVector3 n = e2-e1;
+ cp = v - e1;
+ btScalar _scalar = cp.dot(n)/n.dot(n);
+ if(_scalar <0.0f)
+ {
+ cp = e1;
+ }
+ else if(_scalar >1.0f)
+ {
+ cp = e2;
+ }
+ else
+ {
+ cp = _scalar*n + e1;
+ }
+}
+
+
+//! line plane collision
+/*!
+*\return
+ -0 if the ray never intersects
+ -1 if the ray collides in front
+ -2 if the ray collides in back
+*/
+
+SIMD_FORCE_INLINE int bt_line_plane_collision(
+ const btVector4 & plane,
+ const btVector3 & vDir,
+ const btVector3 & vPoint,
+ btVector3 & pout,
+ btScalar &tparam,
+ btScalar tmin, btScalar tmax)
+{
+
+ btScalar _dotdir = vDir.dot(plane);
+
+ if(btFabs(_dotdir)<PLANEDIREPSILON)
+ {
+ tparam = tmax;
+ return 0;
+ }
+
+ btScalar _dis = bt_distance_point_plane(plane,vPoint);
+ char returnvalue = _dis<0.0f? 2:1;
+ tparam = -_dis/_dotdir;
+
+ if(tparam<tmin)
+ {
+ returnvalue = 0;
+ tparam = tmin;
+ }
+ else if(tparam>tmax)
+ {
+ returnvalue = 0;
+ tparam = tmax;
+ }
+ pout = tparam*vDir + vPoint;
+ return returnvalue;
+}
+
+
+//! Find closest points on segments
+SIMD_FORCE_INLINE void bt_segment_collision(
+ const btVector3 & vA1,
+ const btVector3 & vA2,
+ const btVector3 & vB1,
+ const btVector3 & vB2,
+ btVector3 & vPointA,
+ btVector3 & vPointB)
+{
+ btVector3 AD = vA2 - vA1;
+ btVector3 BD = vB2 - vB1;
+ btVector3 N = AD.cross(BD);
+ btScalar tp = N.length2();
+
+ btVector4 _M;//plane
+
+ if(tp<SIMD_EPSILON)//ARE PARALELE
+ {
+ //project B over A
+ bool invert_b_order = false;
+ _M[0] = vB1.dot(AD);
+ _M[1] = vB2.dot(AD);
+
+ if(_M[0]>_M[1])
+ {
+ invert_b_order = true;
+ BT_SWAP_NUMBERS(_M[0],_M[1]);
+ }
+ _M[2] = vA1.dot(AD);
+ _M[3] = vA2.dot(AD);
+ //mid points
+ N[0] = (_M[0]+_M[1])*0.5f;
+ N[1] = (_M[2]+_M[3])*0.5f;
+
+ if(N[0]<N[1])
+ {
+ if(_M[1]<_M[2])
+ {
+ vPointB = invert_b_order?vB1:vB2;
+ vPointA = vA1;
+ }
+ else if(_M[1]<_M[3])
+ {
+ vPointB = invert_b_order?vB1:vB2;
+ bt_closest_point_on_segment(vPointA,vPointB,vA1,vA2);
+ }
+ else
+ {
+ vPointA = vA2;
+ bt_closest_point_on_segment(vPointB,vPointA,vB1,vB2);
+ }
+ }
+ else
+ {
+ if(_M[3]<_M[0])
+ {
+ vPointB = invert_b_order?vB2:vB1;
+ vPointA = vA2;
+ }
+ else if(_M[3]<_M[1])
+ {
+ vPointA = vA2;
+ bt_closest_point_on_segment(vPointB,vPointA,vB1,vB2);
+ }
+ else
+ {
+ vPointB = invert_b_order?vB1:vB2;
+ bt_closest_point_on_segment(vPointA,vPointB,vA1,vA2);
+ }
+ }
+ return;
+ }
+
+ N = N.cross(BD);
+ _M.setValue(N[0],N[1],N[2],vB1.dot(N));
+
+ // get point A as the plane collision point
+ bt_line_plane_collision(_M,AD,vA1,vPointA,tp,btScalar(0), btScalar(1));
+
+ /*Closest point on segment*/
+ vPointB = vPointA - vB1;
+ tp = vPointB.dot(BD);
+ tp/= BD.dot(BD);
+ tp = BT_CLAMP(tp,0.0f,1.0f);
+
+ vPointB = tp*BD + vB1;
+}
+
+
+
+
+
+#endif // GIM_VECTOR_H_INCLUDED
diff --git a/thirdparty/bullet/src/BulletCollision/Gimpact/btQuantization.h b/thirdparty/bullet/src/BulletCollision/Gimpact/btQuantization.h
new file mode 100644
index 0000000000..bd2633cfc5
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/Gimpact/btQuantization.h
@@ -0,0 +1,88 @@
+#ifndef BT_GIMPACT_QUANTIZATION_H_INCLUDED
+#define BT_GIMPACT_QUANTIZATION_H_INCLUDED
+
+/*! \file btQuantization.h
+*\author Francisco Leon Najera
+
+*/
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+
+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 "LinearMath/btTransform.h"
+
+
+
+
+
+
+SIMD_FORCE_INLINE void bt_calc_quantization_parameters(
+ btVector3 & outMinBound,
+ btVector3 & outMaxBound,
+ btVector3 & bvhQuantization,
+ const btVector3& srcMinBound,const btVector3& srcMaxBound,
+ btScalar quantizationMargin)
+{
+ //enlarge the AABB to avoid division by zero when initializing the quantization values
+ btVector3 clampValue(quantizationMargin,quantizationMargin,quantizationMargin);
+ outMinBound = srcMinBound - clampValue;
+ outMaxBound = srcMaxBound + clampValue;
+ btVector3 aabbSize = outMaxBound - outMinBound;
+ bvhQuantization = btVector3(btScalar(65535.0),
+ btScalar(65535.0),
+ btScalar(65535.0)) / aabbSize;
+}
+
+
+SIMD_FORCE_INLINE void bt_quantize_clamp(
+ unsigned short* out,
+ const btVector3& point,
+ const btVector3 & min_bound,
+ const btVector3 & max_bound,
+ const btVector3 & bvhQuantization)
+{
+
+ btVector3 clampedPoint(point);
+ clampedPoint.setMax(min_bound);
+ clampedPoint.setMin(max_bound);
+
+ btVector3 v = (clampedPoint - min_bound) * bvhQuantization;
+ out[0] = (unsigned short)(v.getX()+0.5f);
+ out[1] = (unsigned short)(v.getY()+0.5f);
+ out[2] = (unsigned short)(v.getZ()+0.5f);
+}
+
+
+SIMD_FORCE_INLINE btVector3 bt_unquantize(
+ const unsigned short* vecIn,
+ const btVector3 & offset,
+ const btVector3 & bvhQuantization)
+{
+ btVector3 vecOut;
+ vecOut.setValue(
+ (btScalar)(vecIn[0]) / (bvhQuantization.getX()),
+ (btScalar)(vecIn[1]) / (bvhQuantization.getY()),
+ (btScalar)(vecIn[2]) / (bvhQuantization.getZ()));
+ vecOut += offset;
+ return vecOut;
+}
+
+
+
+#endif // BT_GIMPACT_QUANTIZATION_H_INCLUDED
diff --git a/thirdparty/bullet/src/BulletCollision/Gimpact/btTriangleShapeEx.cpp b/thirdparty/bullet/src/BulletCollision/Gimpact/btTriangleShapeEx.cpp
new file mode 100644
index 0000000000..ca76cc54a1
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/Gimpact/btTriangleShapeEx.cpp
@@ -0,0 +1,218 @@
+/*! \file btGImpactTriangleShape.h
+\author Francisco Leon Najera
+*/
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+
+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 "btTriangleShapeEx.h"
+
+
+
+void GIM_TRIANGLE_CONTACT::merge_points(const btVector4 & plane,
+ btScalar margin, const btVector3 * points, int point_count)
+{
+ m_point_count = 0;
+ m_penetration_depth= -1000.0f;
+
+ int point_indices[MAX_TRI_CLIPPING];
+
+ int _k;
+
+ for ( _k=0;_k<point_count;_k++)
+ {
+ btScalar _dist = - bt_distance_point_plane(plane,points[_k]) + margin;
+
+ if (_dist>=0.0f)
+ {
+ if (_dist>m_penetration_depth)
+ {
+ m_penetration_depth = _dist;
+ point_indices[0] = _k;
+ m_point_count=1;
+ }
+ else if ((_dist+SIMD_EPSILON)>=m_penetration_depth)
+ {
+ point_indices[m_point_count] = _k;
+ m_point_count++;
+ }
+ }
+ }
+
+ for ( _k=0;_k<m_point_count;_k++)
+ {
+ m_points[_k] = points[point_indices[_k]];
+ }
+}
+
+///class btPrimitiveTriangle
+bool btPrimitiveTriangle::overlap_test_conservative(const btPrimitiveTriangle& other)
+{
+ btScalar total_margin = m_margin + other.m_margin;
+ // classify points on other triangle
+ btScalar dis0 = bt_distance_point_plane(m_plane,other.m_vertices[0]) - total_margin;
+
+ btScalar dis1 = bt_distance_point_plane(m_plane,other.m_vertices[1]) - total_margin;
+
+ btScalar dis2 = bt_distance_point_plane(m_plane,other.m_vertices[2]) - total_margin;
+
+ if (dis0>0.0f&&dis1>0.0f&&dis2>0.0f) return false;
+
+ // classify points on this triangle
+ dis0 = bt_distance_point_plane(other.m_plane,m_vertices[0]) - total_margin;
+
+ dis1 = bt_distance_point_plane(other.m_plane,m_vertices[1]) - total_margin;
+
+ dis2 = bt_distance_point_plane(other.m_plane,m_vertices[2]) - total_margin;
+
+ if (dis0>0.0f&&dis1>0.0f&&dis2>0.0f) return false;
+
+ return true;
+}
+
+int btPrimitiveTriangle::clip_triangle(btPrimitiveTriangle & other, btVector3 * clipped_points )
+{
+ // edge 0
+
+ btVector3 temp_points[MAX_TRI_CLIPPING];
+
+
+ btVector4 edgeplane;
+
+ get_edge_plane(0,edgeplane);
+
+
+ int clipped_count = bt_plane_clip_triangle(
+ edgeplane,other.m_vertices[0],other.m_vertices[1],other.m_vertices[2],temp_points);
+
+ if (clipped_count == 0) return 0;
+
+ btVector3 temp_points1[MAX_TRI_CLIPPING];
+
+
+ // edge 1
+ get_edge_plane(1,edgeplane);
+
+
+ clipped_count = bt_plane_clip_polygon(edgeplane,temp_points,clipped_count,temp_points1);
+
+ if (clipped_count == 0) return 0;
+
+ // edge 2
+ get_edge_plane(2,edgeplane);
+
+ clipped_count = bt_plane_clip_polygon(
+ edgeplane,temp_points1,clipped_count,clipped_points);
+
+ return clipped_count;
+}
+
+bool btPrimitiveTriangle::find_triangle_collision_clip_method(btPrimitiveTriangle & other, GIM_TRIANGLE_CONTACT & contacts)
+{
+ btScalar margin = m_margin + other.m_margin;
+
+ btVector3 clipped_points[MAX_TRI_CLIPPING];
+ int clipped_count;
+ //create planes
+ // plane v vs U points
+
+ GIM_TRIANGLE_CONTACT contacts1;
+
+ contacts1.m_separating_normal = m_plane;
+
+
+ clipped_count = clip_triangle(other,clipped_points);
+
+ if (clipped_count == 0 )
+ {
+ return false;//Reject
+ }
+
+ //find most deep interval face1
+ contacts1.merge_points(contacts1.m_separating_normal,margin,clipped_points,clipped_count);
+ if (contacts1.m_point_count == 0) return false; // too far
+ //Normal pointing to this triangle
+ contacts1.m_separating_normal *= -1.f;
+
+
+ //Clip tri1 by tri2 edges
+ GIM_TRIANGLE_CONTACT contacts2;
+ contacts2.m_separating_normal = other.m_plane;
+
+ clipped_count = other.clip_triangle(*this,clipped_points);
+
+ if (clipped_count == 0 )
+ {
+ return false;//Reject
+ }
+
+ //find most deep interval face1
+ contacts2.merge_points(contacts2.m_separating_normal,margin,clipped_points,clipped_count);
+ if (contacts2.m_point_count == 0) return false; // too far
+
+
+
+
+ ////check most dir for contacts
+ if (contacts2.m_penetration_depth<contacts1.m_penetration_depth)
+ {
+ contacts.copy_from(contacts2);
+ }
+ else
+ {
+ contacts.copy_from(contacts1);
+ }
+ return true;
+}
+
+
+
+///class btTriangleShapeEx: public btTriangleShape
+
+bool btTriangleShapeEx::overlap_test_conservative(const btTriangleShapeEx& other)
+{
+ btScalar total_margin = getMargin() + other.getMargin();
+
+ btVector4 plane0;
+ buildTriPlane(plane0);
+ btVector4 plane1;
+ other.buildTriPlane(plane1);
+
+ // classify points on other triangle
+ btScalar dis0 = bt_distance_point_plane(plane0,other.m_vertices1[0]) - total_margin;
+
+ btScalar dis1 = bt_distance_point_plane(plane0,other.m_vertices1[1]) - total_margin;
+
+ btScalar dis2 = bt_distance_point_plane(plane0,other.m_vertices1[2]) - total_margin;
+
+ if (dis0>0.0f&&dis1>0.0f&&dis2>0.0f) return false;
+
+ // classify points on this triangle
+ dis0 = bt_distance_point_plane(plane1,m_vertices1[0]) - total_margin;
+
+ dis1 = bt_distance_point_plane(plane1,m_vertices1[1]) - total_margin;
+
+ dis2 = bt_distance_point_plane(plane1,m_vertices1[2]) - total_margin;
+
+ if (dis0>0.0f&&dis1>0.0f&&dis2>0.0f) return false;
+
+ return true;
+}
+
+
diff --git a/thirdparty/bullet/src/BulletCollision/Gimpact/btTriangleShapeEx.h b/thirdparty/bullet/src/BulletCollision/Gimpact/btTriangleShapeEx.h
new file mode 100644
index 0000000000..973c2ed127
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/Gimpact/btTriangleShapeEx.h
@@ -0,0 +1,180 @@
+/*! \file btGImpactShape.h
+\author Francisco Leon Najera
+*/
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+
+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 GIMPACT_TRIANGLE_SHAPE_EX_H
+#define GIMPACT_TRIANGLE_SHAPE_EX_H
+
+#include "BulletCollision/CollisionShapes/btCollisionShape.h"
+#include "BulletCollision/CollisionShapes/btTriangleShape.h"
+#include "btBoxCollision.h"
+#include "btClipPolygon.h"
+#include "btGeometryOperations.h"
+
+
+#define MAX_TRI_CLIPPING 16
+
+//! Structure for collision
+struct GIM_TRIANGLE_CONTACT
+{
+ btScalar m_penetration_depth;
+ int m_point_count;
+ btVector4 m_separating_normal;
+ btVector3 m_points[MAX_TRI_CLIPPING];
+
+ SIMD_FORCE_INLINE void copy_from(const GIM_TRIANGLE_CONTACT& other)
+ {
+ m_penetration_depth = other.m_penetration_depth;
+ m_separating_normal = other.m_separating_normal;
+ m_point_count = other.m_point_count;
+ int i = m_point_count;
+ while(i--)
+ {
+ m_points[i] = other.m_points[i];
+ }
+ }
+
+ GIM_TRIANGLE_CONTACT()
+ {
+ }
+
+ GIM_TRIANGLE_CONTACT(const GIM_TRIANGLE_CONTACT& other)
+ {
+ copy_from(other);
+ }
+
+ //! classify points that are closer
+ void merge_points(const btVector4 & plane,
+ btScalar margin, const btVector3 * points, int point_count);
+
+};
+
+
+
+class btPrimitiveTriangle
+{
+public:
+ btVector3 m_vertices[3];
+ btVector4 m_plane;
+ btScalar m_margin;
+ btScalar m_dummy;
+ btPrimitiveTriangle():m_margin(0.01f)
+ {
+
+ }
+
+
+ SIMD_FORCE_INLINE void buildTriPlane()
+ {
+ btVector3 normal = (m_vertices[1]-m_vertices[0]).cross(m_vertices[2]-m_vertices[0]);
+ normal.normalize();
+ m_plane.setValue(normal[0],normal[1],normal[2],m_vertices[0].dot(normal));
+ }
+
+ //! Test if triangles could collide
+ bool overlap_test_conservative(const btPrimitiveTriangle& other);
+
+ //! Calcs the plane which is paralele to the edge and perpendicular to the triangle plane
+ /*!
+ \pre this triangle must have its plane calculated.
+ */
+ SIMD_FORCE_INLINE void get_edge_plane(int edge_index, btVector4 &plane) const
+ {
+ const btVector3 & e0 = m_vertices[edge_index];
+ const btVector3 & e1 = m_vertices[(edge_index+1)%3];
+ bt_edge_plane(e0,e1,m_plane,plane);
+ }
+
+ void applyTransform(const btTransform& t)
+ {
+ m_vertices[0] = t(m_vertices[0]);
+ m_vertices[1] = t(m_vertices[1]);
+ m_vertices[2] = t(m_vertices[2]);
+ }
+
+ //! Clips the triangle against this
+ /*!
+ \pre clipped_points must have MAX_TRI_CLIPPING size, and this triangle must have its plane calculated.
+ \return the number of clipped points
+ */
+ int clip_triangle(btPrimitiveTriangle & other, btVector3 * clipped_points );
+
+ //! Find collision using the clipping method
+ /*!
+ \pre this triangle and other must have their triangles calculated
+ */
+ bool find_triangle_collision_clip_method(btPrimitiveTriangle & other, GIM_TRIANGLE_CONTACT & contacts);
+};
+
+
+
+//! Helper class for colliding Bullet Triangle Shapes
+/*!
+This class implements a better getAabb method than the previous btTriangleShape class
+*/
+class btTriangleShapeEx: public btTriangleShape
+{
+public:
+
+ btTriangleShapeEx():btTriangleShape(btVector3(0,0,0),btVector3(0,0,0),btVector3(0,0,0))
+ {
+ }
+
+ btTriangleShapeEx(const btVector3& p0,const btVector3& p1,const btVector3& p2): btTriangleShape(p0,p1,p2)
+ {
+ }
+
+ btTriangleShapeEx(const btTriangleShapeEx & other): btTriangleShape(other.m_vertices1[0],other.m_vertices1[1],other.m_vertices1[2])
+ {
+ }
+
+ virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax)const
+ {
+ btVector3 tv0 = t(m_vertices1[0]);
+ btVector3 tv1 = t(m_vertices1[1]);
+ btVector3 tv2 = t(m_vertices1[2]);
+
+ btAABB trianglebox(tv0,tv1,tv2,m_collisionMargin);
+ aabbMin = trianglebox.m_min;
+ aabbMax = trianglebox.m_max;
+ }
+
+ void applyTransform(const btTransform& t)
+ {
+ m_vertices1[0] = t(m_vertices1[0]);
+ m_vertices1[1] = t(m_vertices1[1]);
+ m_vertices1[2] = t(m_vertices1[2]);
+ }
+
+ SIMD_FORCE_INLINE void buildTriPlane(btVector4 & plane) const
+ {
+ btVector3 normal = (m_vertices1[1]-m_vertices1[0]).cross(m_vertices1[2]-m_vertices1[0]);
+ normal.normalize();
+ plane.setValue(normal[0],normal[1],normal[2],m_vertices1[0].dot(normal));
+ }
+
+ bool overlap_test_conservative(const btTriangleShapeEx& other);
+};
+
+
+#endif //GIMPACT_TRIANGLE_MESH_SHAPE_H
diff --git a/thirdparty/bullet/src/BulletCollision/Gimpact/gim_array.h b/thirdparty/bullet/src/BulletCollision/Gimpact/gim_array.h
new file mode 100644
index 0000000000..cda51a5fce
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/Gimpact/gim_array.h
@@ -0,0 +1,324 @@
+#ifndef GIM_ARRAY_H_INCLUDED
+#define GIM_ARRAY_H_INCLUDED
+/*! \file gim_array.h
+\author Francisco Leon Najera
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+ (1) The GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 2.1 of the License, or (at
+ your option) any later version. The text of the GNU Lesser
+ General Public License is included with this library in the
+ file GIMPACT-LICENSE-LGPL.TXT.
+ (2) The BSD-style license that is included with this library in
+ the file GIMPACT-LICENSE-BSD.TXT.
+ (3) The zlib/libpng license that is included with this library in
+ the file GIMPACT-LICENSE-ZLIB.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+#include "gim_memory.h"
+
+
+#define GIM_ARRAY_GROW_INCREMENT 2
+#define GIM_ARRAY_GROW_FACTOR 2
+
+//! Very simple array container with fast access and simd memory
+template<typename T>
+class gim_array
+{
+public:
+//! properties
+//!@{
+ T *m_data;
+ GUINT m_size;
+ GUINT m_allocated_size;
+//!@}
+//! protected operations
+//!@{
+
+ inline void destroyData()
+ {
+ m_allocated_size = 0;
+ if(m_data==NULL) return;
+ gim_free(m_data);
+ m_data = NULL;
+ }
+
+ inline bool resizeData(GUINT newsize)
+ {
+ if(newsize==0)
+ {
+ destroyData();
+ return true;
+ }
+
+ if(m_size>0)
+ {
+ m_data = (T*)gim_realloc(m_data,m_size*sizeof(T),newsize*sizeof(T));
+ }
+ else
+ {
+ m_data = (T*)gim_alloc(newsize*sizeof(T));
+ }
+ m_allocated_size = newsize;
+ return true;
+ }
+
+ inline bool growingCheck()
+ {
+ if(m_allocated_size<=m_size)
+ {
+ GUINT requestsize = m_size;
+ m_size = m_allocated_size;
+ if(resizeData((requestsize+GIM_ARRAY_GROW_INCREMENT)*GIM_ARRAY_GROW_FACTOR)==false) return false;
+ }
+ return true;
+ }
+
+//!@}
+//! public operations
+//!@{
+ inline bool reserve(GUINT size)
+ {
+ if(m_allocated_size>=size) return false;
+ return resizeData(size);
+ }
+
+ inline void clear_range(GUINT start_range)
+ {
+ while(m_size>start_range)
+ {
+ m_data[--m_size].~T();
+ }
+ }
+
+ inline void clear()
+ {
+ if(m_size==0)return;
+ clear_range(0);
+ }
+
+ inline void clear_memory()
+ {
+ clear();
+ destroyData();
+ }
+
+ gim_array()
+ {
+ m_data = 0;
+ m_size = 0;
+ m_allocated_size = 0;
+ }
+
+ gim_array(GUINT reservesize)
+ {
+ m_data = 0;
+ m_size = 0;
+
+ m_allocated_size = 0;
+ reserve(reservesize);
+ }
+
+ ~gim_array()
+ {
+ clear_memory();
+ }
+
+ inline GUINT size() const
+ {
+ return m_size;
+ }
+
+ inline GUINT max_size() const
+ {
+ return m_allocated_size;
+ }
+
+ inline T & operator[](size_t i)
+ {
+ return m_data[i];
+ }
+ inline const T & operator[](size_t i) const
+ {
+ return m_data[i];
+ }
+
+ inline T * pointer(){ return m_data;}
+ inline const T * pointer() const
+ { return m_data;}
+
+
+ inline T * get_pointer_at(GUINT i)
+ {
+ return m_data + i;
+ }
+
+ inline const T * get_pointer_at(GUINT i) const
+ {
+ return m_data + i;
+ }
+
+ inline T & at(GUINT i)
+ {
+ return m_data[i];
+ }
+
+ inline const T & at(GUINT i) const
+ {
+ return m_data[i];
+ }
+
+ inline T & front()
+ {
+ return *m_data;
+ }
+
+ inline const T & front() const
+ {
+ return *m_data;
+ }
+
+ inline T & back()
+ {
+ return m_data[m_size-1];
+ }
+
+ inline const T & back() const
+ {
+ return m_data[m_size-1];
+ }
+
+
+ inline void swap(GUINT i, GUINT j)
+ {
+ gim_swap_elements(m_data,i,j);
+ }
+
+ inline void push_back(const T & obj)
+ {
+ this->growingCheck();
+ m_data[m_size] = obj;
+ m_size++;
+ }
+
+ //!Simply increase the m_size, doesn't call the new element constructor
+ inline void push_back_mem()
+ {
+ this->growingCheck();
+ m_size++;
+ }
+
+ inline void push_back_memcpy(const T & obj)
+ {
+ this->growingCheck();
+ gim_simd_memcpy(&m_data[m_size],&obj,sizeof(T));
+ m_size++;
+ }
+
+ inline void pop_back()
+ {
+ m_size--;
+ m_data[m_size].~T();
+ }
+
+ //!Simply decrease the m_size, doesn't call the deleted element destructor
+ inline void pop_back_mem()
+ {
+ m_size--;
+ }
+
+ //! fast erase
+ inline void erase(GUINT index)
+ {
+ if(index<m_size-1)
+ {
+ swap(index,m_size-1);
+ }
+ pop_back();
+ }
+
+ inline void erase_sorted_mem(GUINT index)
+ {
+ m_size--;
+ for(GUINT i = index;i<m_size;i++)
+ {
+ gim_simd_memcpy(m_data+i,m_data+i+1,sizeof(T));
+ }
+ }
+
+ inline void erase_sorted(GUINT index)
+ {
+ m_data[index].~T();
+ erase_sorted_mem(index);
+ }
+
+ inline void insert_mem(GUINT index)
+ {
+ this->growingCheck();
+ for(GUINT i = m_size;i>index;i--)
+ {
+ gim_simd_memcpy(m_data+i,m_data+i-1,sizeof(T));
+ }
+ m_size++;
+ }
+
+ inline void insert(const T & obj,GUINT index)
+ {
+ insert_mem(index);
+ m_data[index] = obj;
+ }
+
+ inline void resize(GUINT size, bool call_constructor = true, const T& fillData=T())
+ {
+ if(size>m_size)
+ {
+ reserve(size);
+ if(call_constructor)
+ {
+ while(m_size<size)
+ {
+ m_data[m_size] = fillData;
+ m_size++;
+ }
+ }
+ else
+ {
+ m_size = size;
+ }
+ }
+ else if(size<m_size)
+ {
+ if(call_constructor) clear_range(size);
+ m_size = size;
+ }
+ }
+
+ inline void refit()
+ {
+ resizeData(m_size);
+ }
+
+};
+
+
+
+
+
+#endif // GIM_CONTAINERS_H_INCLUDED
diff --git a/thirdparty/bullet/src/BulletCollision/Gimpact/gim_basic_geometry_operations.h b/thirdparty/bullet/src/BulletCollision/Gimpact/gim_basic_geometry_operations.h
new file mode 100644
index 0000000000..0c48cb60fc
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/Gimpact/gim_basic_geometry_operations.h
@@ -0,0 +1,546 @@
+#ifndef GIM_BASIC_GEOMETRY_OPERATIONS_H_INCLUDED
+#define GIM_BASIC_GEOMETRY_OPERATIONS_H_INCLUDED
+
+/*! \file gim_basic_geometry_operations.h
+*\author Francisco Leon Najera
+type independant geometry routines
+
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+ (1) The GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 2.1 of the License, or (at
+ your option) any later version. The text of the GNU Lesser
+ General Public License is included with this library in the
+ file GIMPACT-LICENSE-LGPL.TXT.
+ (2) The BSD-style license that is included with this library in
+ the file GIMPACT-LICENSE-BSD.TXT.
+ (3) The zlib/libpng license that is included with this library in
+ the file GIMPACT-LICENSE-ZLIB.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+
+#include "gim_linear_math.h"
+
+
+
+
+#ifndef PLANEDIREPSILON
+#define PLANEDIREPSILON 0.0000001f
+#endif
+
+#ifndef PARALELENORMALS
+#define PARALELENORMALS 0.000001f
+#endif
+
+#define TRIANGLE_NORMAL(v1,v2,v3,n)\
+{\
+ vec3f _dif1,_dif2;\
+ VEC_DIFF(_dif1,v2,v1);\
+ VEC_DIFF(_dif2,v3,v1);\
+ VEC_CROSS(n,_dif1,_dif2);\
+ VEC_NORMALIZE(n);\
+}\
+
+#define TRIANGLE_NORMAL_FAST(v1,v2,v3,n){\
+ vec3f _dif1,_dif2; \
+ VEC_DIFF(_dif1,v2,v1); \
+ VEC_DIFF(_dif2,v3,v1); \
+ VEC_CROSS(n,_dif1,_dif2); \
+}\
+
+/// plane is a vec4f
+#define TRIANGLE_PLANE(v1,v2,v3,plane) {\
+ TRIANGLE_NORMAL(v1,v2,v3,plane);\
+ plane[3] = VEC_DOT(v1,plane);\
+}\
+
+/// plane is a vec4f
+#define TRIANGLE_PLANE_FAST(v1,v2,v3,plane) {\
+ TRIANGLE_NORMAL_FAST(v1,v2,v3,plane);\
+ plane[3] = VEC_DOT(v1,plane);\
+}\
+
+/// Calc a plane from an edge an a normal. plane is a vec4f
+#define EDGE_PLANE(e1,e2,n,plane) {\
+ vec3f _dif; \
+ VEC_DIFF(_dif,e2,e1); \
+ VEC_CROSS(plane,_dif,n); \
+ VEC_NORMALIZE(plane); \
+ plane[3] = VEC_DOT(e1,plane);\
+}\
+
+#define DISTANCE_PLANE_POINT(plane,point) (VEC_DOT(plane,point) - plane[3])
+
+#define PROJECT_POINT_PLANE(point,plane,projected) {\
+ GREAL _dis;\
+ _dis = DISTANCE_PLANE_POINT(plane,point);\
+ VEC_SCALE(projected,-_dis,plane);\
+ VEC_SUM(projected,projected,point); \
+}\
+
+//! Verifies if a point is in the plane hull
+template<typename CLASS_POINT,typename CLASS_PLANE>
+SIMD_FORCE_INLINE bool POINT_IN_HULL(
+ const CLASS_POINT& point,const CLASS_PLANE * planes,GUINT plane_count)
+{
+ GREAL _dis;
+ for (GUINT _i = 0;_i< plane_count;++_i)
+ {
+ _dis = DISTANCE_PLANE_POINT(planes[_i],point);
+ if(_dis>0.0f) return false;
+ }
+ return true;
+}
+
+template<typename CLASS_POINT,typename CLASS_PLANE>
+SIMD_FORCE_INLINE void PLANE_CLIP_SEGMENT(
+ const CLASS_POINT& s1,
+ const CLASS_POINT &s2,const CLASS_PLANE &plane,CLASS_POINT &clipped)
+{
+ GREAL _dis1,_dis2;
+ _dis1 = DISTANCE_PLANE_POINT(plane,s1);
+ VEC_DIFF(clipped,s2,s1);
+ _dis2 = VEC_DOT(clipped,plane);
+ VEC_SCALE(clipped,-_dis1/_dis2,clipped);
+ VEC_SUM(clipped,clipped,s1);
+}
+
+enum ePLANE_INTERSECTION_TYPE
+{
+ G_BACK_PLANE = 0,
+ G_COLLIDE_PLANE,
+ G_FRONT_PLANE
+};
+
+enum eLINE_PLANE_INTERSECTION_TYPE
+{
+ G_FRONT_PLANE_S1 = 0,
+ G_FRONT_PLANE_S2,
+ G_BACK_PLANE_S1,
+ G_BACK_PLANE_S2,
+ G_COLLIDE_PLANE_S1,
+ G_COLLIDE_PLANE_S2
+};
+
+//! Confirms if the plane intersect the edge or nor
+/*!
+intersection type must have the following values
+<ul>
+<li> 0 : Segment in front of plane, s1 closest
+<li> 1 : Segment in front of plane, s2 closest
+<li> 2 : Segment in back of plane, s1 closest
+<li> 3 : Segment in back of plane, s2 closest
+<li> 4 : Segment collides plane, s1 in back
+<li> 5 : Segment collides plane, s2 in back
+</ul>
+*/
+
+template<typename CLASS_POINT,typename CLASS_PLANE>
+SIMD_FORCE_INLINE eLINE_PLANE_INTERSECTION_TYPE PLANE_CLIP_SEGMENT2(
+ const CLASS_POINT& s1,
+ const CLASS_POINT &s2,
+ const CLASS_PLANE &plane,CLASS_POINT &clipped)
+{
+ GREAL _dis1 = DISTANCE_PLANE_POINT(plane,s1);
+ GREAL _dis2 = DISTANCE_PLANE_POINT(plane,s2);
+ if(_dis1 >-G_EPSILON && _dis2 >-G_EPSILON)
+ {
+ if(_dis1<_dis2) return G_FRONT_PLANE_S1;
+ return G_FRONT_PLANE_S2;
+ }
+ else if(_dis1 <G_EPSILON && _dis2 <G_EPSILON)
+ {
+ if(_dis1>_dis2) return G_BACK_PLANE_S1;
+ return G_BACK_PLANE_S2;
+ }
+
+ VEC_DIFF(clipped,s2,s1);
+ _dis2 = VEC_DOT(clipped,plane);
+ VEC_SCALE(clipped,-_dis1/_dis2,clipped);
+ VEC_SUM(clipped,clipped,s1);
+ if(_dis1<_dis2) return G_COLLIDE_PLANE_S1;
+ return G_COLLIDE_PLANE_S2;
+}
+
+//! Confirms if the plane intersect the edge or not
+/*!
+clipped1 and clipped2 are the vertices behind the plane.
+clipped1 is the closest
+
+intersection_type must have the following values
+<ul>
+<li> 0 : Segment in front of plane, s1 closest
+<li> 1 : Segment in front of plane, s2 closest
+<li> 2 : Segment in back of plane, s1 closest
+<li> 3 : Segment in back of plane, s2 closest
+<li> 4 : Segment collides plane, s1 in back
+<li> 5 : Segment collides plane, s2 in back
+</ul>
+*/
+template<typename CLASS_POINT,typename CLASS_PLANE>
+SIMD_FORCE_INLINE eLINE_PLANE_INTERSECTION_TYPE PLANE_CLIP_SEGMENT_CLOSEST(
+ const CLASS_POINT& s1,
+ const CLASS_POINT &s2,
+ const CLASS_PLANE &plane,
+ CLASS_POINT &clipped1,CLASS_POINT &clipped2)
+{
+ eLINE_PLANE_INTERSECTION_TYPE intersection_type = PLANE_CLIP_SEGMENT2(s1,s2,plane,clipped1);
+ switch(intersection_type)
+ {
+ case G_FRONT_PLANE_S1:
+ VEC_COPY(clipped1,s1);
+ VEC_COPY(clipped2,s2);
+ break;
+ case G_FRONT_PLANE_S2:
+ VEC_COPY(clipped1,s2);
+ VEC_COPY(clipped2,s1);
+ break;
+ case G_BACK_PLANE_S1:
+ VEC_COPY(clipped1,s1);
+ VEC_COPY(clipped2,s2);
+ break;
+ case G_BACK_PLANE_S2:
+ VEC_COPY(clipped1,s2);
+ VEC_COPY(clipped2,s1);
+ break;
+ case G_COLLIDE_PLANE_S1:
+ VEC_COPY(clipped2,s1);
+ break;
+ case G_COLLIDE_PLANE_S2:
+ VEC_COPY(clipped2,s2);
+ break;
+ }
+ return intersection_type;
+}
+
+
+//! Finds the 2 smallest cartesian coordinates of a plane normal
+#define PLANE_MINOR_AXES(plane, i0, i1) VEC_MINOR_AXES(plane, i0, i1)
+
+//! Ray plane collision in one way
+/*!
+Intersects plane in one way only. The ray must face the plane (normals must be in opossite directions).<br/>
+It uses the PLANEDIREPSILON constant.
+*/
+template<typename T,typename CLASS_POINT,typename CLASS_PLANE>
+SIMD_FORCE_INLINE bool RAY_PLANE_COLLISION(
+ const CLASS_PLANE & plane,
+ const CLASS_POINT & vDir,
+ const CLASS_POINT & vPoint,
+ CLASS_POINT & pout,T &tparam)
+{
+ GREAL _dis,_dotdir;
+ _dotdir = VEC_DOT(plane,vDir);
+ if(_dotdir<PLANEDIREPSILON)
+ {
+ return false;
+ }
+ _dis = DISTANCE_PLANE_POINT(plane,vPoint);
+ tparam = -_dis/_dotdir;
+ VEC_SCALE(pout,tparam,vDir);
+ VEC_SUM(pout,vPoint,pout);
+ return true;
+}
+
+//! line collision
+/*!
+*\return
+ -0 if the ray never intersects
+ -1 if the ray collides in front
+ -2 if the ray collides in back
+*/
+template<typename T,typename CLASS_POINT,typename CLASS_PLANE>
+SIMD_FORCE_INLINE GUINT LINE_PLANE_COLLISION(
+ const CLASS_PLANE & plane,
+ const CLASS_POINT & vDir,
+ const CLASS_POINT & vPoint,
+ CLASS_POINT & pout,
+ T &tparam,
+ T tmin, T tmax)
+{
+ GREAL _dis,_dotdir;
+ _dotdir = VEC_DOT(plane,vDir);
+ if(btFabs(_dotdir)<PLANEDIREPSILON)
+ {
+ tparam = tmax;
+ return 0;
+ }
+ _dis = DISTANCE_PLANE_POINT(plane,vPoint);
+ char returnvalue = _dis<0.0f?2:1;
+ tparam = -_dis/_dotdir;
+
+ if(tparam<tmin)
+ {
+ returnvalue = 0;
+ tparam = tmin;
+ }
+ else if(tparam>tmax)
+ {
+ returnvalue = 0;
+ tparam = tmax;
+ }
+
+ VEC_SCALE(pout,tparam,vDir);
+ VEC_SUM(pout,vPoint,pout);
+ return returnvalue;
+}
+
+/*! \brief Returns the Ray on which 2 planes intersect if they do.
+ Written by Rodrigo Hernandez on ODE convex collision
+
+ \param p1 Plane 1
+ \param p2 Plane 2
+ \param p Contains the origin of the ray upon returning if planes intersect
+ \param d Contains the direction of the ray upon returning if planes intersect
+ \return true if the planes intersect, 0 if paralell.
+
+*/
+template<typename CLASS_POINT,typename CLASS_PLANE>
+SIMD_FORCE_INLINE bool INTERSECT_PLANES(
+ const CLASS_PLANE &p1,
+ const CLASS_PLANE &p2,
+ CLASS_POINT &p,
+ CLASS_POINT &d)
+{
+ VEC_CROSS(d,p1,p2);
+ GREAL denom = VEC_DOT(d, d);
+ if(GIM_IS_ZERO(denom)) return false;
+ vec3f _n;
+ _n[0]=p1[3]*p2[0] - p2[3]*p1[0];
+ _n[1]=p1[3]*p2[1] - p2[3]*p1[1];
+ _n[2]=p1[3]*p2[2] - p2[3]*p1[2];
+ VEC_CROSS(p,_n,d);
+ p[0]/=denom;
+ p[1]/=denom;
+ p[2]/=denom;
+ return true;
+}
+
+//***************** SEGMENT and LINE FUNCTIONS **********************************///
+
+/*! Finds the closest point(cp) to (v) on a segment (e1,e2)
+ */
+template<typename CLASS_POINT>
+SIMD_FORCE_INLINE void CLOSEST_POINT_ON_SEGMENT(
+ CLASS_POINT & cp, const CLASS_POINT & v,
+ const CLASS_POINT &e1,const CLASS_POINT &e2)
+{
+ vec3f _n;
+ VEC_DIFF(_n,e2,e1);
+ VEC_DIFF(cp,v,e1);
+ GREAL _scalar = VEC_DOT(cp, _n);
+ _scalar/= VEC_DOT(_n, _n);
+ if(_scalar <0.0f)
+ {
+ VEC_COPY(cp,e1);
+ }
+ else if(_scalar >1.0f)
+ {
+ VEC_COPY(cp,e2);
+ }
+ else
+ {
+ VEC_SCALE(cp,_scalar,_n);
+ VEC_SUM(cp,cp,e1);
+ }
+}
+
+
+/*! \brief Finds the line params where these lines intersect.
+
+\param dir1 Direction of line 1
+\param point1 Point of line 1
+\param dir2 Direction of line 2
+\param point2 Point of line 2
+\param t1 Result Parameter for line 1
+\param t2 Result Parameter for line 2
+\param dointersect 0 if the lines won't intersect, else 1
+
+*/
+template<typename T,typename CLASS_POINT>
+SIMD_FORCE_INLINE bool LINE_INTERSECTION_PARAMS(
+ const CLASS_POINT & dir1,
+ CLASS_POINT & point1,
+ const CLASS_POINT & dir2,
+ CLASS_POINT & point2,
+ T& t1,T& t2)
+{
+ GREAL det;
+ GREAL e1e1 = VEC_DOT(dir1,dir1);
+ GREAL e1e2 = VEC_DOT(dir1,dir2);
+ GREAL e2e2 = VEC_DOT(dir2,dir2);
+ vec3f p1p2;
+ VEC_DIFF(p1p2,point1,point2);
+ GREAL p1p2e1 = VEC_DOT(p1p2,dir1);
+ GREAL p1p2e2 = VEC_DOT(p1p2,dir2);
+ det = e1e2*e1e2 - e1e1*e2e2;
+ if(GIM_IS_ZERO(det)) return false;
+ t1 = (e1e2*p1p2e2 - e2e2*p1p2e1)/det;
+ t2 = (e1e1*p1p2e2 - e1e2*p1p2e1)/det;
+ return true;
+}
+
+//! Find closest points on segments
+template<typename CLASS_POINT>
+SIMD_FORCE_INLINE void SEGMENT_COLLISION(
+ const CLASS_POINT & vA1,
+ const CLASS_POINT & vA2,
+ const CLASS_POINT & vB1,
+ const CLASS_POINT & vB2,
+ CLASS_POINT & vPointA,
+ CLASS_POINT & vPointB)
+{
+ CLASS_POINT _AD,_BD,n;
+ vec4f _M;//plane
+ VEC_DIFF(_AD,vA2,vA1);
+ VEC_DIFF(_BD,vB2,vB1);
+ VEC_CROSS(n,_AD,_BD);
+ GREAL _tp = VEC_DOT(n,n);
+ if(_tp<G_EPSILON)//ARE PARALELE
+ {
+ //project B over A
+ bool invert_b_order = false;
+ _M[0] = VEC_DOT(vB1,_AD);
+ _M[1] = VEC_DOT(vB2,_AD);
+ if(_M[0]>_M[1])
+ {
+ invert_b_order = true;
+ GIM_SWAP_NUMBERS(_M[0],_M[1]);
+ }
+ _M[2] = VEC_DOT(vA1,_AD);
+ _M[3] = VEC_DOT(vA2,_AD);
+ //mid points
+ n[0] = (_M[0]+_M[1])*0.5f;
+ n[1] = (_M[2]+_M[3])*0.5f;
+
+ if(n[0]<n[1])
+ {
+ if(_M[1]<_M[2])
+ {
+ vPointB = invert_b_order?vB1:vB2;
+ vPointA = vA1;
+ }
+ else if(_M[1]<_M[3])
+ {
+ vPointB = invert_b_order?vB1:vB2;
+ CLOSEST_POINT_ON_SEGMENT(vPointA,vPointB,vA1,vA2);
+ }
+ else
+ {
+ vPointA = vA2;
+ CLOSEST_POINT_ON_SEGMENT(vPointB,vPointA,vB1,vB2);
+ }
+ }
+ else
+ {
+ if(_M[3]<_M[0])
+ {
+ vPointB = invert_b_order?vB2:vB1;
+ vPointA = vA2;
+ }
+ else if(_M[3]<_M[1])
+ {
+ vPointA = vA2;
+ CLOSEST_POINT_ON_SEGMENT(vPointB,vPointA,vB1,vB2);
+ }
+ else
+ {
+ vPointB = invert_b_order?vB1:vB2;
+ CLOSEST_POINT_ON_SEGMENT(vPointA,vPointB,vA1,vA2);
+ }
+ }
+ return;
+ }
+
+
+ VEC_CROSS(_M,n,_BD);
+ _M[3] = VEC_DOT(_M,vB1);
+
+ LINE_PLANE_COLLISION(_M,_AD,vA1,vPointA,_tp,btScalar(0), btScalar(1));
+ /*Closest point on segment*/
+ VEC_DIFF(vPointB,vPointA,vB1);
+ _tp = VEC_DOT(vPointB, _BD);
+ _tp/= VEC_DOT(_BD, _BD);
+ _tp = GIM_CLAMP(_tp,0.0f,1.0f);
+ VEC_SCALE(vPointB,_tp,_BD);
+ VEC_SUM(vPointB,vPointB,vB1);
+}
+
+
+
+
+//! Line box intersection in one dimension
+/*!
+
+*\param pos Position of the ray
+*\param dir Projection of the Direction of the ray
+*\param bmin Minimum bound of the box
+*\param bmax Maximum bound of the box
+*\param tfirst the minimum projection. Assign to 0 at first.
+*\param tlast the maximum projection. Assign to INFINITY at first.
+*\return true if there is an intersection.
+*/
+template<typename T>
+SIMD_FORCE_INLINE bool BOX_AXIS_INTERSECT(T pos, T dir,T bmin, T bmax, T & tfirst, T & tlast)
+{
+ if(GIM_IS_ZERO(dir))
+ {
+ return !(pos < bmin || pos > bmax);
+ }
+ GREAL a0 = (bmin - pos) / dir;
+ GREAL a1 = (bmax - pos) / dir;
+ if(a0 > a1) GIM_SWAP_NUMBERS(a0, a1);
+ tfirst = GIM_MAX(a0, tfirst);
+ tlast = GIM_MIN(a1, tlast);
+ if (tlast < tfirst) return false;
+ return true;
+}
+
+
+//! Sorts 3 componets
+template<typename T>
+SIMD_FORCE_INLINE void SORT_3_INDICES(
+ const T * values,
+ GUINT * order_indices)
+{
+ //get minimum
+ order_indices[0] = values[0] < values[1] ? (values[0] < values[2] ? 0 : 2) : (values[1] < values[2] ? 1 : 2);
+
+ //get second and third
+ GUINT i0 = (order_indices[0] + 1)%3;
+ GUINT i1 = (i0 + 1)%3;
+
+ if(values[i0] < values[i1])
+ {
+ order_indices[1] = i0;
+ order_indices[2] = i1;
+ }
+ else
+ {
+ order_indices[1] = i1;
+ order_indices[2] = i0;
+ }
+}
+
+
+
+
+
+#endif // GIM_VECTOR_H_INCLUDED
diff --git a/thirdparty/bullet/src/BulletCollision/Gimpact/gim_bitset.h b/thirdparty/bullet/src/BulletCollision/Gimpact/gim_bitset.h
new file mode 100644
index 0000000000..7dee48a4c7
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/Gimpact/gim_bitset.h
@@ -0,0 +1,123 @@
+#ifndef GIM_BITSET_H_INCLUDED
+#define GIM_BITSET_H_INCLUDED
+/*! \file gim_bitset.h
+\author Francisco Leon Najera
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+ (1) The GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 2.1 of the License, or (at
+ your option) any later version. The text of the GNU Lesser
+ General Public License is included with this library in the
+ file GIMPACT-LICENSE-LGPL.TXT.
+ (2) The BSD-style license that is included with this library in
+ the file GIMPACT-LICENSE-BSD.TXT.
+ (3) The zlib/libpng license that is included with this library in
+ the file GIMPACT-LICENSE-ZLIB.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+#include "gim_array.h"
+
+
+#define GUINT_BIT_COUNT 32
+#define GUINT_EXPONENT 5
+
+class gim_bitset
+{
+public:
+ gim_array<GUINT> m_container;
+
+ gim_bitset()
+ {
+
+ }
+
+ gim_bitset(GUINT bits_count)
+ {
+ resize(bits_count);
+ }
+
+ ~gim_bitset()
+ {
+ }
+
+ inline bool resize(GUINT newsize)
+ {
+ GUINT oldsize = m_container.size();
+ m_container.resize(newsize/GUINT_BIT_COUNT + 1,false);
+ while(oldsize<m_container.size())
+ {
+ m_container[oldsize] = 0;
+ }
+ return true;
+ }
+
+ inline GUINT size()
+ {
+ return m_container.size()*GUINT_BIT_COUNT;
+ }
+
+ inline void set_all()
+ {
+ for(GUINT i = 0;i<m_container.size();++i)
+ {
+ m_container[i] = 0xffffffff;
+ }
+ }
+
+ inline void clear_all()
+ {
+ for(GUINT i = 0;i<m_container.size();++i)
+ {
+ m_container[i] = 0;
+ }
+ }
+
+ inline void set(GUINT bit_index)
+ {
+ if(bit_index>=size())
+ {
+ resize(bit_index);
+ }
+ m_container[bit_index >> GUINT_EXPONENT] |= (1 << (bit_index & (GUINT_BIT_COUNT-1)));
+ }
+
+ ///Return 0 or 1
+ inline char get(GUINT bit_index)
+ {
+ if(bit_index>=size())
+ {
+ return 0;
+ }
+ char value = m_container[bit_index >> GUINT_EXPONENT] &
+ (1 << (bit_index & (GUINT_BIT_COUNT-1)));
+ return value;
+ }
+
+ inline void clear(GUINT bit_index)
+ {
+ m_container[bit_index >> GUINT_EXPONENT] &= ~(1 << (bit_index & (GUINT_BIT_COUNT-1)));
+ }
+};
+
+
+
+
+
+#endif // GIM_CONTAINERS_H_INCLUDED
diff --git a/thirdparty/bullet/src/BulletCollision/Gimpact/gim_box_collision.h b/thirdparty/bullet/src/BulletCollision/Gimpact/gim_box_collision.h
new file mode 100644
index 0000000000..a051b4fdbf
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/Gimpact/gim_box_collision.h
@@ -0,0 +1,593 @@
+#ifndef GIM_BOX_COLLISION_H_INCLUDED
+#define GIM_BOX_COLLISION_H_INCLUDED
+
+/*! \file gim_box_collision.h
+\author Francisco Leon Najera
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+ (1) The GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 2.1 of the License, or (at
+ your option) any later version. The text of the GNU Lesser
+ General Public License is included with this library in the
+ file GIMPACT-LICENSE-LGPL.TXT.
+ (2) The BSD-style license that is included with this library in
+ the file GIMPACT-LICENSE-BSD.TXT.
+ (3) The zlib/libpng license that is included with this library in
+ the file GIMPACT-LICENSE-ZLIB.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+#include "gim_basic_geometry_operations.h"
+#include "LinearMath/btTransform.h"
+
+
+
+//SIMD_FORCE_INLINE bool test_cross_edge_box(
+// const btVector3 & edge,
+// const btVector3 & absolute_edge,
+// const btVector3 & pointa,
+// const btVector3 & pointb, const btVector3 & extend,
+// int dir_index0,
+// int dir_index1
+// int component_index0,
+// int component_index1)
+//{
+// // dir coords are -z and y
+//
+// const btScalar dir0 = -edge[dir_index0];
+// const btScalar dir1 = edge[dir_index1];
+// btScalar pmin = pointa[component_index0]*dir0 + pointa[component_index1]*dir1;
+// btScalar pmax = pointb[component_index0]*dir0 + pointb[component_index1]*dir1;
+// //find minmax
+// if(pmin>pmax)
+// {
+// GIM_SWAP_NUMBERS(pmin,pmax);
+// }
+// //find extends
+// const btScalar rad = extend[component_index0] * absolute_edge[dir_index0] +
+// extend[component_index1] * absolute_edge[dir_index1];
+//
+// if(pmin>rad || -rad>pmax) return false;
+// return true;
+//}
+//
+//SIMD_FORCE_INLINE bool test_cross_edge_box_X_axis(
+// const btVector3 & edge,
+// const btVector3 & absolute_edge,
+// const btVector3 & pointa,
+// const btVector3 & pointb, btVector3 & extend)
+//{
+//
+// return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,2,1,1,2);
+//}
+//
+//
+//SIMD_FORCE_INLINE bool test_cross_edge_box_Y_axis(
+// const btVector3 & edge,
+// const btVector3 & absolute_edge,
+// const btVector3 & pointa,
+// const btVector3 & pointb, btVector3 & extend)
+//{
+//
+// return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,0,2,2,0);
+//}
+//
+//SIMD_FORCE_INLINE bool test_cross_edge_box_Z_axis(
+// const btVector3 & edge,
+// const btVector3 & absolute_edge,
+// const btVector3 & pointa,
+// const btVector3 & pointb, btVector3 & extend)
+//{
+//
+// return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,1,0,0,1);
+//}
+
+#ifndef TEST_CROSS_EDGE_BOX_MCR
+
+#define TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,i_dir_0,i_dir_1,i_comp_0,i_comp_1)\
+{\
+ const btScalar dir0 = -edge[i_dir_0];\
+ const btScalar dir1 = edge[i_dir_1];\
+ btScalar pmin = pointa[i_comp_0]*dir0 + pointa[i_comp_1]*dir1;\
+ btScalar pmax = pointb[i_comp_0]*dir0 + pointb[i_comp_1]*dir1;\
+ if(pmin>pmax)\
+ {\
+ GIM_SWAP_NUMBERS(pmin,pmax); \
+ }\
+ const btScalar abs_dir0 = absolute_edge[i_dir_0];\
+ const btScalar abs_dir1 = absolute_edge[i_dir_1];\
+ const btScalar rad = _extend[i_comp_0] * abs_dir0 + _extend[i_comp_1] * abs_dir1;\
+ if(pmin>rad || -rad>pmax) return false;\
+}\
+
+#endif
+
+#define TEST_CROSS_EDGE_BOX_X_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\
+{\
+ TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,2,1,1,2);\
+}\
+
+#define TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\
+{\
+ TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,0,2,2,0);\
+}\
+
+#define TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\
+{\
+ TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,1,0,0,1);\
+}\
+
+
+
+//! Class for transforming a model1 to the space of model0
+class GIM_BOX_BOX_TRANSFORM_CACHE
+{
+public:
+ btVector3 m_T1to0;//!< Transforms translation of model1 to model 0
+ btMatrix3x3 m_R1to0;//!< Transforms Rotation of model1 to model 0, equal to R0' * R1
+ btMatrix3x3 m_AR;//!< Absolute value of m_R1to0
+
+ SIMD_FORCE_INLINE void calc_absolute_matrix()
+ {
+ static const btVector3 vepsi(1e-6f,1e-6f,1e-6f);
+ m_AR[0] = vepsi + m_R1to0[0].absolute();
+ m_AR[1] = vepsi + m_R1to0[1].absolute();
+ m_AR[2] = vepsi + m_R1to0[2].absolute();
+ }
+
+ GIM_BOX_BOX_TRANSFORM_CACHE()
+ {
+ }
+
+
+ GIM_BOX_BOX_TRANSFORM_CACHE(mat4f trans1_to_0)
+ {
+ COPY_MATRIX_3X3(m_R1to0,trans1_to_0)
+ MAT_GET_TRANSLATION(trans1_to_0,m_T1to0)
+ calc_absolute_matrix();
+ }
+
+ //! Calc the transformation relative 1 to 0. Inverts matrics by transposing
+ SIMD_FORCE_INLINE void calc_from_homogenic(const btTransform & trans0,const btTransform & trans1)
+ {
+
+ m_R1to0 = trans0.getBasis().transpose();
+ m_T1to0 = m_R1to0 * (-trans0.getOrigin());
+
+ m_T1to0 += m_R1to0*trans1.getOrigin();
+ m_R1to0 *= trans1.getBasis();
+
+ calc_absolute_matrix();
+ }
+
+ //! Calcs the full invertion of the matrices. Useful for scaling matrices
+ SIMD_FORCE_INLINE void calc_from_full_invert(const btTransform & trans0,const btTransform & trans1)
+ {
+ m_R1to0 = trans0.getBasis().inverse();
+ m_T1to0 = m_R1to0 * (-trans0.getOrigin());
+
+ m_T1to0 += m_R1to0*trans1.getOrigin();
+ m_R1to0 *= trans1.getBasis();
+
+ calc_absolute_matrix();
+ }
+
+ SIMD_FORCE_INLINE btVector3 transform(const btVector3 & point)
+ {
+ return point.dot3(m_R1to0[0], m_R1to0[1], m_R1to0[2]) + m_T1to0;
+ }
+};
+
+#ifndef BOX_PLANE_EPSILON
+#define BOX_PLANE_EPSILON 0.000001f
+#endif
+
+//! Axis aligned box
+class GIM_AABB
+{
+public:
+ btVector3 m_min;
+ btVector3 m_max;
+
+ GIM_AABB()
+ {}
+
+
+ GIM_AABB(const btVector3 & V1,
+ const btVector3 & V2,
+ const btVector3 & V3)
+ {
+ m_min[0] = GIM_MIN3(V1[0],V2[0],V3[0]);
+ m_min[1] = GIM_MIN3(V1[1],V2[1],V3[1]);
+ m_min[2] = GIM_MIN3(V1[2],V2[2],V3[2]);
+
+ m_max[0] = GIM_MAX3(V1[0],V2[0],V3[0]);
+ m_max[1] = GIM_MAX3(V1[1],V2[1],V3[1]);
+ m_max[2] = GIM_MAX3(V1[2],V2[2],V3[2]);
+ }
+
+ GIM_AABB(const btVector3 & V1,
+ const btVector3 & V2,
+ const btVector3 & V3,
+ GREAL margin)
+ {
+ m_min[0] = GIM_MIN3(V1[0],V2[0],V3[0]);
+ m_min[1] = GIM_MIN3(V1[1],V2[1],V3[1]);
+ m_min[2] = GIM_MIN3(V1[2],V2[2],V3[2]);
+
+ m_max[0] = GIM_MAX3(V1[0],V2[0],V3[0]);
+ m_max[1] = GIM_MAX3(V1[1],V2[1],V3[1]);
+ m_max[2] = GIM_MAX3(V1[2],V2[2],V3[2]);
+
+ m_min[0] -= margin;
+ m_min[1] -= margin;
+ m_min[2] -= margin;
+ m_max[0] += margin;
+ m_max[1] += margin;
+ m_max[2] += margin;
+ }
+
+ GIM_AABB(const GIM_AABB &other):
+ m_min(other.m_min),m_max(other.m_max)
+ {
+ }
+
+ GIM_AABB(const GIM_AABB &other,btScalar margin ):
+ m_min(other.m_min),m_max(other.m_max)
+ {
+ m_min[0] -= margin;
+ m_min[1] -= margin;
+ m_min[2] -= margin;
+ m_max[0] += margin;
+ m_max[1] += margin;
+ m_max[2] += margin;
+ }
+
+ SIMD_FORCE_INLINE void invalidate()
+ {
+ m_min[0] = G_REAL_INFINITY;
+ m_min[1] = G_REAL_INFINITY;
+ m_min[2] = G_REAL_INFINITY;
+ m_max[0] = -G_REAL_INFINITY;
+ m_max[1] = -G_REAL_INFINITY;
+ m_max[2] = -G_REAL_INFINITY;
+ }
+
+ SIMD_FORCE_INLINE void increment_margin(btScalar margin)
+ {
+ m_min[0] -= margin;
+ m_min[1] -= margin;
+ m_min[2] -= margin;
+ m_max[0] += margin;
+ m_max[1] += margin;
+ m_max[2] += margin;
+ }
+
+ SIMD_FORCE_INLINE void copy_with_margin(const GIM_AABB &other, btScalar margin)
+ {
+ m_min[0] = other.m_min[0] - margin;
+ m_min[1] = other.m_min[1] - margin;
+ m_min[2] = other.m_min[2] - margin;
+
+ m_max[0] = other.m_max[0] + margin;
+ m_max[1] = other.m_max[1] + margin;
+ m_max[2] = other.m_max[2] + margin;
+ }
+
+ template<typename CLASS_POINT>
+ SIMD_FORCE_INLINE void calc_from_triangle(
+ const CLASS_POINT & V1,
+ const CLASS_POINT & V2,
+ const CLASS_POINT & V3)
+ {
+ m_min[0] = GIM_MIN3(V1[0],V2[0],V3[0]);
+ m_min[1] = GIM_MIN3(V1[1],V2[1],V3[1]);
+ m_min[2] = GIM_MIN3(V1[2],V2[2],V3[2]);
+
+ m_max[0] = GIM_MAX3(V1[0],V2[0],V3[0]);
+ m_max[1] = GIM_MAX3(V1[1],V2[1],V3[1]);
+ m_max[2] = GIM_MAX3(V1[2],V2[2],V3[2]);
+ }
+
+ template<typename CLASS_POINT>
+ SIMD_FORCE_INLINE void calc_from_triangle_margin(
+ const CLASS_POINT & V1,
+ const CLASS_POINT & V2,
+ const CLASS_POINT & V3, btScalar margin)
+ {
+ m_min[0] = GIM_MIN3(V1[0],V2[0],V3[0]);
+ m_min[1] = GIM_MIN3(V1[1],V2[1],V3[1]);
+ m_min[2] = GIM_MIN3(V1[2],V2[2],V3[2]);
+
+ m_max[0] = GIM_MAX3(V1[0],V2[0],V3[0]);
+ m_max[1] = GIM_MAX3(V1[1],V2[1],V3[1]);
+ m_max[2] = GIM_MAX3(V1[2],V2[2],V3[2]);
+
+ m_min[0] -= margin;
+ m_min[1] -= margin;
+ m_min[2] -= margin;
+ m_max[0] += margin;
+ m_max[1] += margin;
+ m_max[2] += margin;
+ }
+
+ //! Apply a transform to an AABB
+ SIMD_FORCE_INLINE void appy_transform(const btTransform & trans)
+ {
+ btVector3 center = (m_max+m_min)*0.5f;
+ btVector3 extends = m_max - center;
+ // Compute new center
+ center = trans(center);
+
+ btVector3 textends = extends.dot3(trans.getBasis().getRow(0).absolute(),
+ trans.getBasis().getRow(1).absolute(),
+ trans.getBasis().getRow(2).absolute());
+
+ m_min = center - textends;
+ m_max = center + textends;
+ }
+
+ //! Merges a Box
+ SIMD_FORCE_INLINE void merge(const GIM_AABB & box)
+ {
+ m_min[0] = GIM_MIN(m_min[0],box.m_min[0]);
+ m_min[1] = GIM_MIN(m_min[1],box.m_min[1]);
+ m_min[2] = GIM_MIN(m_min[2],box.m_min[2]);
+
+ m_max[0] = GIM_MAX(m_max[0],box.m_max[0]);
+ m_max[1] = GIM_MAX(m_max[1],box.m_max[1]);
+ m_max[2] = GIM_MAX(m_max[2],box.m_max[2]);
+ }
+
+ //! Merges a point
+ template<typename CLASS_POINT>
+ SIMD_FORCE_INLINE void merge_point(const CLASS_POINT & point)
+ {
+ m_min[0] = GIM_MIN(m_min[0],point[0]);
+ m_min[1] = GIM_MIN(m_min[1],point[1]);
+ m_min[2] = GIM_MIN(m_min[2],point[2]);
+
+ m_max[0] = GIM_MAX(m_max[0],point[0]);
+ m_max[1] = GIM_MAX(m_max[1],point[1]);
+ m_max[2] = GIM_MAX(m_max[2],point[2]);
+ }
+
+ //! Gets the extend and center
+ SIMD_FORCE_INLINE void get_center_extend(btVector3 & center,btVector3 & extend) const
+ {
+ center = (m_max+m_min)*0.5f;
+ extend = m_max - center;
+ }
+
+ //! Finds the intersecting box between this box and the other.
+ SIMD_FORCE_INLINE void find_intersection(const GIM_AABB & other, GIM_AABB & intersection) const
+ {
+ intersection.m_min[0] = GIM_MAX(other.m_min[0],m_min[0]);
+ intersection.m_min[1] = GIM_MAX(other.m_min[1],m_min[1]);
+ intersection.m_min[2] = GIM_MAX(other.m_min[2],m_min[2]);
+
+ intersection.m_max[0] = GIM_MIN(other.m_max[0],m_max[0]);
+ intersection.m_max[1] = GIM_MIN(other.m_max[1],m_max[1]);
+ intersection.m_max[2] = GIM_MIN(other.m_max[2],m_max[2]);
+ }
+
+
+ SIMD_FORCE_INLINE bool has_collision(const GIM_AABB & other) const
+ {
+ if(m_min[0] > other.m_max[0] ||
+ m_max[0] < other.m_min[0] ||
+ m_min[1] > other.m_max[1] ||
+ m_max[1] < other.m_min[1] ||
+ m_min[2] > other.m_max[2] ||
+ m_max[2] < other.m_min[2])
+ {
+ return false;
+ }
+ return true;
+ }
+
+ /*! \brief Finds the Ray intersection parameter.
+ \param aabb Aligned box
+ \param vorigin A vec3f with the origin of the ray
+ \param vdir A vec3f with the direction of the ray
+ */
+ SIMD_FORCE_INLINE bool collide_ray(const btVector3 & vorigin,const btVector3 & vdir)
+ {
+ btVector3 extents,center;
+ this->get_center_extend(center,extents);;
+
+ btScalar Dx = vorigin[0] - center[0];
+ if(GIM_GREATER(Dx, extents[0]) && Dx*vdir[0]>=0.0f) return false;
+ btScalar Dy = vorigin[1] - center[1];
+ if(GIM_GREATER(Dy, extents[1]) && Dy*vdir[1]>=0.0f) return false;
+ btScalar Dz = vorigin[2] - center[2];
+ if(GIM_GREATER(Dz, extents[2]) && Dz*vdir[2]>=0.0f) return false;
+
+
+ btScalar f = vdir[1] * Dz - vdir[2] * Dy;
+ if(btFabs(f) > extents[1]*btFabs(vdir[2]) + extents[2]*btFabs(vdir[1])) return false;
+ f = vdir[2] * Dx - vdir[0] * Dz;
+ if(btFabs(f) > extents[0]*btFabs(vdir[2]) + extents[2]*btFabs(vdir[0]))return false;
+ f = vdir[0] * Dy - vdir[1] * Dx;
+ if(btFabs(f) > extents[0]*btFabs(vdir[1]) + extents[1]*btFabs(vdir[0]))return false;
+ return true;
+ }
+
+
+ SIMD_FORCE_INLINE void projection_interval(const btVector3 & direction, btScalar &vmin, btScalar &vmax) const
+ {
+ btVector3 center = (m_max+m_min)*0.5f;
+ btVector3 extend = m_max-center;
+
+ btScalar _fOrigin = direction.dot(center);
+ btScalar _fMaximumExtent = extend.dot(direction.absolute());
+ vmin = _fOrigin - _fMaximumExtent;
+ vmax = _fOrigin + _fMaximumExtent;
+ }
+
+ SIMD_FORCE_INLINE ePLANE_INTERSECTION_TYPE plane_classify(const btVector4 &plane) const
+ {
+ btScalar _fmin,_fmax;
+ this->projection_interval(plane,_fmin,_fmax);
+
+ if(plane[3] > _fmax + BOX_PLANE_EPSILON)
+ {
+ return G_BACK_PLANE; // 0
+ }
+
+ if(plane[3]+BOX_PLANE_EPSILON >=_fmin)
+ {
+ return G_COLLIDE_PLANE; //1
+ }
+ return G_FRONT_PLANE;//2
+ }
+
+ SIMD_FORCE_INLINE bool overlapping_trans_conservative(const GIM_AABB & box, btTransform & trans1_to_0)
+ {
+ GIM_AABB tbox = box;
+ tbox.appy_transform(trans1_to_0);
+ return has_collision(tbox);
+ }
+
+ //! transcache is the transformation cache from box to this AABB
+ SIMD_FORCE_INLINE bool overlapping_trans_cache(
+ const GIM_AABB & box,const GIM_BOX_BOX_TRANSFORM_CACHE & transcache, bool fulltest)
+ {
+
+ //Taken from OPCODE
+ btVector3 ea,eb;//extends
+ btVector3 ca,cb;//extends
+ get_center_extend(ca,ea);
+ box.get_center_extend(cb,eb);
+
+
+ btVector3 T;
+ btScalar t,t2;
+ int i;
+
+ // Class I : A's basis vectors
+ for(i=0;i<3;i++)
+ {
+ T[i] = transcache.m_R1to0[i].dot(cb) + transcache.m_T1to0[i] - ca[i];
+ t = transcache.m_AR[i].dot(eb) + ea[i];
+ if(GIM_GREATER(T[i], t)) return false;
+ }
+ // Class II : B's basis vectors
+ for(i=0;i<3;i++)
+ {
+ t = MAT_DOT_COL(transcache.m_R1to0,T,i);
+ t2 = MAT_DOT_COL(transcache.m_AR,ea,i) + eb[i];
+ if(GIM_GREATER(t,t2)) return false;
+ }
+ // Class III : 9 cross products
+ if(fulltest)
+ {
+ int j,m,n,o,p,q,r;
+ for(i=0;i<3;i++)
+ {
+ m = (i+1)%3;
+ n = (i+2)%3;
+ o = i==0?1:0;
+ p = i==2?1:2;
+ for(j=0;j<3;j++)
+ {
+ q = j==2?1:2;
+ r = j==0?1:0;
+ t = T[n]*transcache.m_R1to0[m][j] - T[m]*transcache.m_R1to0[n][j];
+ t2 = ea[o]*transcache.m_AR[p][j] + ea[p]*transcache.m_AR[o][j] +
+ eb[r]*transcache.m_AR[i][q] + eb[q]*transcache.m_AR[i][r];
+ if(GIM_GREATER(t,t2)) return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ //! Simple test for planes.
+ SIMD_FORCE_INLINE bool collide_plane(
+ const btVector4 & plane)
+ {
+ ePLANE_INTERSECTION_TYPE classify = plane_classify(plane);
+ return (classify == G_COLLIDE_PLANE);
+ }
+
+ //! test for a triangle, with edges
+ SIMD_FORCE_INLINE bool collide_triangle_exact(
+ const btVector3 & p1,
+ const btVector3 & p2,
+ const btVector3 & p3,
+ const btVector4 & triangle_plane)
+ {
+ if(!collide_plane(triangle_plane)) return false;
+
+ btVector3 center,extends;
+ this->get_center_extend(center,extends);
+
+ const btVector3 v1(p1 - center);
+ const btVector3 v2(p2 - center);
+ const btVector3 v3(p3 - center);
+
+ //First axis
+ btVector3 diff(v2 - v1);
+ btVector3 abs_diff = diff.absolute();
+ //Test With X axis
+ TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v1,v3,extends);
+ //Test With Y axis
+ TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v1,v3,extends);
+ //Test With Z axis
+ TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v1,v3,extends);
+
+
+ diff = v3 - v2;
+ abs_diff = diff.absolute();
+ //Test With X axis
+ TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v2,v1,extends);
+ //Test With Y axis
+ TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v2,v1,extends);
+ //Test With Z axis
+ TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v2,v1,extends);
+
+ diff = v1 - v3;
+ abs_diff = diff.absolute();
+ //Test With X axis
+ TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v3,v2,extends);
+ //Test With Y axis
+ TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v3,v2,extends);
+ //Test With Z axis
+ TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v3,v2,extends);
+
+ return true;
+ }
+};
+
+#ifndef BT_BOX_COLLISION_H_INCLUDED
+//! Compairison of transformation objects
+SIMD_FORCE_INLINE bool btCompareTransformsEqual(const btTransform & t1,const btTransform & t2)
+{
+ if(!(t1.getOrigin() == t2.getOrigin()) ) return false;
+
+ if(!(t1.getBasis().getRow(0) == t2.getBasis().getRow(0)) ) return false;
+ if(!(t1.getBasis().getRow(1) == t2.getBasis().getRow(1)) ) return false;
+ if(!(t1.getBasis().getRow(2) == t2.getBasis().getRow(2)) ) return false;
+ return true;
+}
+#endif
+
+
+
+#endif // GIM_BOX_COLLISION_H_INCLUDED
diff --git a/thirdparty/bullet/src/BulletCollision/Gimpact/gim_box_set.cpp b/thirdparty/bullet/src/BulletCollision/Gimpact/gim_box_set.cpp
new file mode 100644
index 0000000000..0c3d7ba8db
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/Gimpact/gim_box_set.cpp
@@ -0,0 +1,182 @@
+
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+ (1) The GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 2.1 of the License, or (at
+ your option) any later version. The text of the GNU Lesser
+ General Public License is included with this library in the
+ file GIMPACT-LICENSE-LGPL.TXT.
+ (2) The BSD-style license that is included with this library in
+ the file GIMPACT-LICENSE-BSD.TXT.
+ (3) The zlib/libpng license that is included with this library in
+ the file GIMPACT-LICENSE-ZLIB.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+
+#include "gim_box_set.h"
+
+
+GUINT GIM_BOX_TREE::_calc_splitting_axis(
+ gim_array<GIM_AABB_DATA> & primitive_boxes, GUINT startIndex, GUINT endIndex)
+{
+ GUINT i;
+
+ btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.));
+ btVector3 variance(btScalar(0.),btScalar(0.),btScalar(0.));
+ GUINT numIndices = endIndex-startIndex;
+
+ for (i=startIndex;i<endIndex;i++)
+ {
+ btVector3 center = btScalar(0.5)*(primitive_boxes[i].m_bound.m_max +
+ primitive_boxes[i].m_bound.m_min);
+ means+=center;
+ }
+ means *= (btScalar(1.)/(btScalar)numIndices);
+
+ for (i=startIndex;i<endIndex;i++)
+ {
+ btVector3 center = btScalar(0.5)*(primitive_boxes[i].m_bound.m_max +
+ primitive_boxes[i].m_bound.m_min);
+ btVector3 diff2 = center-means;
+ diff2 = diff2 * diff2;
+ variance += diff2;
+ }
+ variance *= (btScalar(1.)/ ((btScalar)numIndices-1) );
+
+ return variance.maxAxis();
+}
+
+
+GUINT GIM_BOX_TREE::_sort_and_calc_splitting_index(
+ gim_array<GIM_AABB_DATA> & primitive_boxes, GUINT startIndex,
+ GUINT endIndex, GUINT splitAxis)
+{
+ GUINT i;
+ GUINT splitIndex =startIndex;
+ GUINT numIndices = endIndex - startIndex;
+
+ // average of centers
+ btScalar splitValue = 0.0f;
+ for (i=startIndex;i<endIndex;i++)
+ {
+ splitValue+= 0.5f*(primitive_boxes[i].m_bound.m_max[splitAxis] +
+ primitive_boxes[i].m_bound.m_min[splitAxis]);
+ }
+ splitValue /= (btScalar)numIndices;
+
+ //sort leafNodes so all values larger then splitValue comes first, and smaller values start from 'splitIndex'.
+ for (i=startIndex;i<endIndex;i++)
+ {
+ btScalar center = 0.5f*(primitive_boxes[i].m_bound.m_max[splitAxis] +
+ primitive_boxes[i].m_bound.m_min[splitAxis]);
+ if (center > splitValue)
+ {
+ //swap
+ primitive_boxes.swap(i,splitIndex);
+ splitIndex++;
+ }
+ }
+
+ //if the splitIndex causes unbalanced trees, fix this by using the center in between startIndex and endIndex
+ //otherwise the tree-building might fail due to stack-overflows in certain cases.
+ //unbalanced1 is unsafe: it can cause stack overflows
+ //bool unbalanced1 = ((splitIndex==startIndex) || (splitIndex == (endIndex-1)));
+
+ //unbalanced2 should work too: always use center (perfect balanced trees)
+ //bool unbalanced2 = true;
+
+ //this should be safe too:
+ GUINT rangeBalancedIndices = numIndices/3;
+ bool unbalanced = ((splitIndex<=(startIndex+rangeBalancedIndices)) || (splitIndex >=(endIndex-1-rangeBalancedIndices)));
+
+ if (unbalanced)
+ {
+ splitIndex = startIndex+ (numIndices>>1);
+ }
+
+ btAssert(!((splitIndex==startIndex) || (splitIndex == (endIndex))));
+
+ return splitIndex;
+}
+
+
+void GIM_BOX_TREE::_build_sub_tree(gim_array<GIM_AABB_DATA> & primitive_boxes, GUINT startIndex, GUINT endIndex)
+{
+ GUINT current_index = m_num_nodes++;
+
+ btAssert((endIndex-startIndex)>0);
+
+ if((endIndex-startIndex) == 1) //we got a leaf
+ {
+ m_node_array[current_index].m_left = 0;
+ m_node_array[current_index].m_right = 0;
+ m_node_array[current_index].m_escapeIndex = 0;
+
+ m_node_array[current_index].m_bound = primitive_boxes[startIndex].m_bound;
+ m_node_array[current_index].m_data = primitive_boxes[startIndex].m_data;
+ return;
+ }
+
+ //configure inner node
+
+ GUINT splitIndex;
+
+ //calc this node bounding box
+ m_node_array[current_index].m_bound.invalidate();
+ for (splitIndex=startIndex;splitIndex<endIndex;splitIndex++)
+ {
+ m_node_array[current_index].m_bound.merge(primitive_boxes[splitIndex].m_bound);
+ }
+
+ //calculate Best Splitting Axis and where to split it. Sort the incoming 'leafNodes' array within range 'startIndex/endIndex'.
+
+ //split axis
+ splitIndex = _calc_splitting_axis(primitive_boxes,startIndex,endIndex);
+
+ splitIndex = _sort_and_calc_splitting_index(
+ primitive_boxes,startIndex,endIndex,splitIndex);
+
+ //configure this inner node : the left node index
+ m_node_array[current_index].m_left = m_num_nodes;
+ //build left child tree
+ _build_sub_tree(primitive_boxes, startIndex, splitIndex );
+
+ //configure this inner node : the right node index
+ m_node_array[current_index].m_right = m_num_nodes;
+
+ //build right child tree
+ _build_sub_tree(primitive_boxes, splitIndex ,endIndex);
+
+ //configure this inner node : the escape index
+ m_node_array[current_index].m_escapeIndex = m_num_nodes - current_index;
+}
+
+//! stackless build tree
+void GIM_BOX_TREE::build_tree(
+ gim_array<GIM_AABB_DATA> & primitive_boxes)
+{
+ // initialize node count to 0
+ m_num_nodes = 0;
+ // allocate nodes
+ m_node_array.resize(primitive_boxes.size()*2);
+
+ _build_sub_tree(primitive_boxes, 0, primitive_boxes.size());
+}
+
+
diff --git a/thirdparty/bullet/src/BulletCollision/Gimpact/gim_box_set.h b/thirdparty/bullet/src/BulletCollision/Gimpact/gim_box_set.h
new file mode 100644
index 0000000000..61d190a7df
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/Gimpact/gim_box_set.h
@@ -0,0 +1,674 @@
+#ifndef GIM_BOX_SET_H_INCLUDED
+#define GIM_BOX_SET_H_INCLUDED
+
+/*! \file gim_box_set.h
+\author Francisco Leon Najera
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+ (1) The GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 2.1 of the License, or (at
+ your option) any later version. The text of the GNU Lesser
+ General Public License is included with this library in the
+ file GIMPACT-LICENSE-LGPL.TXT.
+ (2) The BSD-style license that is included with this library in
+ the file GIMPACT-LICENSE-BSD.TXT.
+ (3) The zlib/libpng license that is included with this library in
+ the file GIMPACT-LICENSE-ZLIB.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+
+#include "gim_array.h"
+#include "gim_radixsort.h"
+#include "gim_box_collision.h"
+#include "gim_tri_collision.h"
+
+
+
+//! Overlapping pair
+struct GIM_PAIR
+{
+ GUINT m_index1;
+ GUINT m_index2;
+ GIM_PAIR()
+ {}
+
+ GIM_PAIR(const GIM_PAIR & p)
+ {
+ m_index1 = p.m_index1;
+ m_index2 = p.m_index2;
+ }
+
+ GIM_PAIR(GUINT index1, GUINT index2)
+ {
+ m_index1 = index1;
+ m_index2 = index2;
+ }
+};
+
+//! A pairset array
+class gim_pair_set: public gim_array<GIM_PAIR>
+{
+public:
+ gim_pair_set():gim_array<GIM_PAIR>(32)
+ {
+ }
+ inline void push_pair(GUINT index1,GUINT index2)
+ {
+ push_back(GIM_PAIR(index1,index2));
+ }
+
+ inline void push_pair_inv(GUINT index1,GUINT index2)
+ {
+ push_back(GIM_PAIR(index2,index1));
+ }
+};
+
+
+//! Prototype Base class for primitive classification
+/*!
+This class is a wrapper for primitive collections.
+This tells relevant info for the Bounding Box set classes, which take care of space classification.
+This class can manage Compound shapes and trimeshes, and if it is managing trimesh then the Hierarchy Bounding Box classes will take advantage of primitive Vs Box overlapping tests for getting optimal results and less Per Box compairisons.
+*/
+class GIM_PRIMITIVE_MANAGER_PROTOTYPE
+{
+public:
+
+ virtual ~GIM_PRIMITIVE_MANAGER_PROTOTYPE() {}
+ //! determines if this manager consist on only triangles, which special case will be optimized
+ virtual bool is_trimesh() = 0;
+ virtual GUINT get_primitive_count() = 0;
+ virtual void get_primitive_box(GUINT prim_index ,GIM_AABB & primbox) = 0;
+ virtual void get_primitive_triangle(GUINT prim_index,GIM_TRIANGLE & triangle) = 0;
+};
+
+
+struct GIM_AABB_DATA
+{
+ GIM_AABB m_bound;
+ GUINT m_data;
+};
+
+//! Node Structure for trees
+struct GIM_BOX_TREE_NODE
+{
+ GIM_AABB m_bound;
+ GUINT m_left;//!< Left subtree
+ GUINT m_right;//!< Right subtree
+ GUINT m_escapeIndex;//!< Scape index for traversing
+ GUINT m_data;//!< primitive index if apply
+
+ GIM_BOX_TREE_NODE()
+ {
+ m_left = 0;
+ m_right = 0;
+ m_escapeIndex = 0;
+ m_data = 0;
+ }
+
+ SIMD_FORCE_INLINE bool is_leaf_node() const
+ {
+ return (!m_left && !m_right);
+ }
+};
+
+//! Basic Box tree structure
+class GIM_BOX_TREE
+{
+protected:
+ GUINT m_num_nodes;
+ gim_array<GIM_BOX_TREE_NODE> m_node_array;
+protected:
+ GUINT _sort_and_calc_splitting_index(
+ gim_array<GIM_AABB_DATA> & primitive_boxes,
+ GUINT startIndex, GUINT endIndex, GUINT splitAxis);
+
+ GUINT _calc_splitting_axis(gim_array<GIM_AABB_DATA> & primitive_boxes, GUINT startIndex, GUINT endIndex);
+
+ void _build_sub_tree(gim_array<GIM_AABB_DATA> & primitive_boxes, GUINT startIndex, GUINT endIndex);
+public:
+ GIM_BOX_TREE()
+ {
+ m_num_nodes = 0;
+ }
+
+ //! prototype functions for box tree management
+ //!@{
+ void build_tree(gim_array<GIM_AABB_DATA> & primitive_boxes);
+
+ SIMD_FORCE_INLINE void clearNodes()
+ {
+ m_node_array.clear();
+ m_num_nodes = 0;
+ }
+
+ //! node count
+ SIMD_FORCE_INLINE GUINT getNodeCount() const
+ {
+ return m_num_nodes;
+ }
+
+ //! tells if the node is a leaf
+ SIMD_FORCE_INLINE bool isLeafNode(GUINT nodeindex) const
+ {
+ return m_node_array[nodeindex].is_leaf_node();
+ }
+
+ SIMD_FORCE_INLINE GUINT getNodeData(GUINT nodeindex) const
+ {
+ return m_node_array[nodeindex].m_data;
+ }
+
+ SIMD_FORCE_INLINE void getNodeBound(GUINT nodeindex, GIM_AABB & bound) const
+ {
+ bound = m_node_array[nodeindex].m_bound;
+ }
+
+ SIMD_FORCE_INLINE void setNodeBound(GUINT nodeindex, const GIM_AABB & bound)
+ {
+ m_node_array[nodeindex].m_bound = bound;
+ }
+
+ SIMD_FORCE_INLINE GUINT getLeftNodeIndex(GUINT nodeindex) const
+ {
+ return m_node_array[nodeindex].m_left;
+ }
+
+ SIMD_FORCE_INLINE GUINT getRightNodeIndex(GUINT nodeindex) const
+ {
+ return m_node_array[nodeindex].m_right;
+ }
+
+ SIMD_FORCE_INLINE GUINT getScapeNodeIndex(GUINT nodeindex) const
+ {
+ return m_node_array[nodeindex].m_escapeIndex;
+ }
+
+ //!@}
+};
+
+
+//! Generic Box Tree Template
+/*!
+This class offers an structure for managing a box tree of primitives.
+Requires a Primitive prototype (like GIM_PRIMITIVE_MANAGER_PROTOTYPE ) and
+a Box tree structure ( like GIM_BOX_TREE).
+*/
+template<typename _GIM_PRIMITIVE_MANAGER_PROTOTYPE, typename _GIM_BOX_TREE_PROTOTYPE>
+class GIM_BOX_TREE_TEMPLATE_SET
+{
+protected:
+ _GIM_PRIMITIVE_MANAGER_PROTOTYPE m_primitive_manager;
+ _GIM_BOX_TREE_PROTOTYPE m_box_tree;
+protected:
+ //stackless refit
+ SIMD_FORCE_INLINE void refit()
+ {
+ GUINT nodecount = getNodeCount();
+ while(nodecount--)
+ {
+ if(isLeafNode(nodecount))
+ {
+ GIM_AABB leafbox;
+ m_primitive_manager.get_primitive_box(getNodeData(nodecount),leafbox);
+ setNodeBound(nodecount,leafbox);
+ }
+ else
+ {
+ //get left bound
+ GUINT childindex = getLeftNodeIndex(nodecount);
+ GIM_AABB bound;
+ getNodeBound(childindex,bound);
+ //get right bound
+ childindex = getRightNodeIndex(nodecount);
+ GIM_AABB bound2;
+ getNodeBound(childindex,bound2);
+ bound.merge(bound2);
+
+ setNodeBound(nodecount,bound);
+ }
+ }
+ }
+public:
+
+ GIM_BOX_TREE_TEMPLATE_SET()
+ {
+ }
+
+ SIMD_FORCE_INLINE GIM_AABB getGlobalBox() const
+ {
+ GIM_AABB totalbox;
+ getNodeBound(0, totalbox);
+ return totalbox;
+ }
+
+ SIMD_FORCE_INLINE void setPrimitiveManager(const _GIM_PRIMITIVE_MANAGER_PROTOTYPE & primitive_manager)
+ {
+ m_primitive_manager = primitive_manager;
+ }
+
+ const _GIM_PRIMITIVE_MANAGER_PROTOTYPE & getPrimitiveManager() const
+ {
+ return m_primitive_manager;
+ }
+
+ _GIM_PRIMITIVE_MANAGER_PROTOTYPE & getPrimitiveManager()
+ {
+ return m_primitive_manager;
+ }
+
+//! node manager prototype functions
+///@{
+
+ //! this attemps to refit the box set.
+ SIMD_FORCE_INLINE void update()
+ {
+ refit();
+ }
+
+ //! this rebuild the entire set
+ SIMD_FORCE_INLINE void buildSet()
+ {
+ //obtain primitive boxes
+ gim_array<GIM_AABB_DATA> primitive_boxes;
+ primitive_boxes.resize(m_primitive_manager.get_primitive_count(),false);
+
+ for (GUINT i = 0;i<primitive_boxes.size() ;i++ )
+ {
+ m_primitive_manager.get_primitive_box(i,primitive_boxes[i].m_bound);
+ primitive_boxes[i].m_data = i;
+ }
+
+ m_box_tree.build_tree(primitive_boxes);
+ }
+
+ //! returns the indices of the primitives in the m_primitive_manager
+ SIMD_FORCE_INLINE bool boxQuery(const GIM_AABB & box, gim_array<GUINT> & collided_results) const
+ {
+ GUINT curIndex = 0;
+ GUINT numNodes = getNodeCount();
+
+ while (curIndex < numNodes)
+ {
+ GIM_AABB bound;
+ getNodeBound(curIndex,bound);
+
+ //catch bugs in tree data
+
+ bool aabbOverlap = bound.has_collision(box);
+ bool isleafnode = isLeafNode(curIndex);
+
+ if (isleafnode && aabbOverlap)
+ {
+ collided_results.push_back(getNodeData(curIndex));
+ }
+
+ if (aabbOverlap || isleafnode)
+ {
+ //next subnode
+ curIndex++;
+ }
+ else
+ {
+ //skip node
+ curIndex+= getScapeNodeIndex(curIndex);
+ }
+ }
+ if(collided_results.size()>0) return true;
+ return false;
+ }
+
+ //! returns the indices of the primitives in the m_primitive_manager
+ SIMD_FORCE_INLINE bool boxQueryTrans(const GIM_AABB & box,
+ const btTransform & transform, gim_array<GUINT> & collided_results) const
+ {
+ GIM_AABB transbox=box;
+ transbox.appy_transform(transform);
+ return boxQuery(transbox,collided_results);
+ }
+
+ //! returns the indices of the primitives in the m_primitive_manager
+ SIMD_FORCE_INLINE bool rayQuery(
+ const btVector3 & ray_dir,const btVector3 & ray_origin ,
+ gim_array<GUINT> & collided_results) const
+ {
+ GUINT curIndex = 0;
+ GUINT numNodes = getNodeCount();
+
+ while (curIndex < numNodes)
+ {
+ GIM_AABB bound;
+ getNodeBound(curIndex,bound);
+
+ //catch bugs in tree data
+
+ bool aabbOverlap = bound.collide_ray(ray_origin,ray_dir);
+ bool isleafnode = isLeafNode(curIndex);
+
+ if (isleafnode && aabbOverlap)
+ {
+ collided_results.push_back(getNodeData( curIndex));
+ }
+
+ if (aabbOverlap || isleafnode)
+ {
+ //next subnode
+ curIndex++;
+ }
+ else
+ {
+ //skip node
+ curIndex+= getScapeNodeIndex(curIndex);
+ }
+ }
+ if(collided_results.size()>0) return true;
+ return false;
+ }
+
+ //! tells if this set has hierarcht
+ SIMD_FORCE_INLINE bool hasHierarchy() const
+ {
+ return true;
+ }
+
+ //! tells if this set is a trimesh
+ SIMD_FORCE_INLINE bool isTrimesh() const
+ {
+ return m_primitive_manager.is_trimesh();
+ }
+
+ //! node count
+ SIMD_FORCE_INLINE GUINT getNodeCount() const
+ {
+ return m_box_tree.getNodeCount();
+ }
+
+ //! tells if the node is a leaf
+ SIMD_FORCE_INLINE bool isLeafNode(GUINT nodeindex) const
+ {
+ return m_box_tree.isLeafNode(nodeindex);
+ }
+
+ SIMD_FORCE_INLINE GUINT getNodeData(GUINT nodeindex) const
+ {
+ return m_box_tree.getNodeData(nodeindex);
+ }
+
+ SIMD_FORCE_INLINE void getNodeBound(GUINT nodeindex, GIM_AABB & bound) const
+ {
+ m_box_tree.getNodeBound(nodeindex, bound);
+ }
+
+ SIMD_FORCE_INLINE void setNodeBound(GUINT nodeindex, const GIM_AABB & bound)
+ {
+ m_box_tree.setNodeBound(nodeindex, bound);
+ }
+
+ SIMD_FORCE_INLINE GUINT getLeftNodeIndex(GUINT nodeindex) const
+ {
+ return m_box_tree.getLeftNodeIndex(nodeindex);
+ }
+
+ SIMD_FORCE_INLINE GUINT getRightNodeIndex(GUINT nodeindex) const
+ {
+ return m_box_tree.getRightNodeIndex(nodeindex);
+ }
+
+ SIMD_FORCE_INLINE GUINT getScapeNodeIndex(GUINT nodeindex) const
+ {
+ return m_box_tree.getScapeNodeIndex(nodeindex);
+ }
+
+ SIMD_FORCE_INLINE void getNodeTriangle(GUINT nodeindex,GIM_TRIANGLE & triangle) const
+ {
+ m_primitive_manager.get_primitive_triangle(getNodeData(nodeindex),triangle);
+ }
+
+};
+
+//! Class for Box Tree Sets
+/*!
+this has the GIM_BOX_TREE implementation for bounding boxes.
+*/
+template<typename _GIM_PRIMITIVE_MANAGER_PROTOTYPE>
+class GIM_BOX_TREE_SET: public GIM_BOX_TREE_TEMPLATE_SET< _GIM_PRIMITIVE_MANAGER_PROTOTYPE, GIM_BOX_TREE>
+{
+public:
+
+};
+
+
+
+
+
+/// GIM_BOX_SET collision methods
+template<typename BOX_SET_CLASS0,typename BOX_SET_CLASS1>
+class GIM_TREE_TREE_COLLIDER
+{
+public:
+ gim_pair_set * m_collision_pairs;
+ BOX_SET_CLASS0 * m_boxset0;
+ BOX_SET_CLASS1 * m_boxset1;
+ GUINT current_node0;
+ GUINT current_node1;
+ bool node0_is_leaf;
+ bool node1_is_leaf;
+ bool t0_is_trimesh;
+ bool t1_is_trimesh;
+ bool node0_has_triangle;
+ bool node1_has_triangle;
+ GIM_AABB m_box0;
+ GIM_AABB m_box1;
+ GIM_BOX_BOX_TRANSFORM_CACHE trans_cache_1to0;
+ btTransform trans_cache_0to1;
+ GIM_TRIANGLE m_tri0;
+ btVector4 m_tri0_plane;
+ GIM_TRIANGLE m_tri1;
+ btVector4 m_tri1_plane;
+
+
+public:
+ GIM_TREE_TREE_COLLIDER()
+ {
+ current_node0 = G_UINT_INFINITY;
+ current_node1 = G_UINT_INFINITY;
+ }
+protected:
+ SIMD_FORCE_INLINE void retrieve_node0_triangle(GUINT node0)
+ {
+ if(node0_has_triangle) return;
+ m_boxset0->getNodeTriangle(node0,m_tri0);
+ //transform triangle
+ m_tri0.m_vertices[0] = trans_cache_0to1(m_tri0.m_vertices[0]);
+ m_tri0.m_vertices[1] = trans_cache_0to1(m_tri0.m_vertices[1]);
+ m_tri0.m_vertices[2] = trans_cache_0to1(m_tri0.m_vertices[2]);
+ m_tri0.get_plane(m_tri0_plane);
+
+ node0_has_triangle = true;
+ }
+
+ SIMD_FORCE_INLINE void retrieve_node1_triangle(GUINT node1)
+ {
+ if(node1_has_triangle) return;
+ m_boxset1->getNodeTriangle(node1,m_tri1);
+ //transform triangle
+ m_tri1.m_vertices[0] = trans_cache_1to0.transform(m_tri1.m_vertices[0]);
+ m_tri1.m_vertices[1] = trans_cache_1to0.transform(m_tri1.m_vertices[1]);
+ m_tri1.m_vertices[2] = trans_cache_1to0.transform(m_tri1.m_vertices[2]);
+ m_tri1.get_plane(m_tri1_plane);
+
+ node1_has_triangle = true;
+ }
+
+ SIMD_FORCE_INLINE void retrieve_node0_info(GUINT node0)
+ {
+ if(node0 == current_node0) return;
+ m_boxset0->getNodeBound(node0,m_box0);
+ node0_is_leaf = m_boxset0->isLeafNode(node0);
+ node0_has_triangle = false;
+ current_node0 = node0;
+ }
+
+ SIMD_FORCE_INLINE void retrieve_node1_info(GUINT node1)
+ {
+ if(node1 == current_node1) return;
+ m_boxset1->getNodeBound(node1,m_box1);
+ node1_is_leaf = m_boxset1->isLeafNode(node1);
+ node1_has_triangle = false;
+ current_node1 = node1;
+ }
+
+ SIMD_FORCE_INLINE bool node_collision(GUINT node0 ,GUINT node1)
+ {
+ retrieve_node0_info(node0);
+ retrieve_node1_info(node1);
+ bool result = m_box0.overlapping_trans_cache(m_box1,trans_cache_1to0,true);
+ if(!result) return false;
+
+ if(t0_is_trimesh && node0_is_leaf)
+ {
+ //perform primitive vs box collision
+ retrieve_node0_triangle(node0);
+ //do triangle vs box collision
+ m_box1.increment_margin(m_tri0.m_margin);
+
+ result = m_box1.collide_triangle_exact(
+ m_tri0.m_vertices[0],m_tri0.m_vertices[1],m_tri0.m_vertices[2],m_tri0_plane);
+
+ m_box1.increment_margin(-m_tri0.m_margin);
+
+ if(!result) return false;
+ return true;
+ }
+ else if(t1_is_trimesh && node1_is_leaf)
+ {
+ //perform primitive vs box collision
+ retrieve_node1_triangle(node1);
+ //do triangle vs box collision
+ m_box0.increment_margin(m_tri1.m_margin);
+
+ result = m_box0.collide_triangle_exact(
+ m_tri1.m_vertices[0],m_tri1.m_vertices[1],m_tri1.m_vertices[2],m_tri1_plane);
+
+ m_box0.increment_margin(-m_tri1.m_margin);
+
+ if(!result) return false;
+ return true;
+ }
+ return true;
+ }
+
+ //stackless collision routine
+ void find_collision_pairs()
+ {
+ gim_pair_set stack_collisions;
+ stack_collisions.reserve(32);
+
+ //add the first pair
+ stack_collisions.push_pair(0,0);
+
+
+ while(stack_collisions.size())
+ {
+ //retrieve the last pair and pop
+ GUINT node0 = stack_collisions.back().m_index1;
+ GUINT node1 = stack_collisions.back().m_index2;
+ stack_collisions.pop_back();
+ if(node_collision(node0,node1)) // a collision is found
+ {
+ if(node0_is_leaf)
+ {
+ if(node1_is_leaf)
+ {
+ m_collision_pairs->push_pair(m_boxset0->getNodeData(node0),m_boxset1->getNodeData(node1));
+ }
+ else
+ {
+ //collide left
+ stack_collisions.push_pair(node0,m_boxset1->getLeftNodeIndex(node1));
+
+ //collide right
+ stack_collisions.push_pair(node0,m_boxset1->getRightNodeIndex(node1));
+ }
+ }
+ else
+ {
+ if(node1_is_leaf)
+ {
+ //collide left
+ stack_collisions.push_pair(m_boxset0->getLeftNodeIndex(node0),node1);
+ //collide right
+ stack_collisions.push_pair(m_boxset0->getRightNodeIndex(node0),node1);
+ }
+ else
+ {
+ GUINT left0 = m_boxset0->getLeftNodeIndex(node0);
+ GUINT right0 = m_boxset0->getRightNodeIndex(node0);
+ GUINT left1 = m_boxset1->getLeftNodeIndex(node1);
+ GUINT right1 = m_boxset1->getRightNodeIndex(node1);
+ //collide left
+ stack_collisions.push_pair(left0,left1);
+ //collide right
+ stack_collisions.push_pair(left0,right1);
+ //collide left
+ stack_collisions.push_pair(right0,left1);
+ //collide right
+ stack_collisions.push_pair(right0,right1);
+
+ }// else if node1 is not a leaf
+ }// else if node0 is not a leaf
+
+ }// if(node_collision(node0,node1))
+ }//while(stack_collisions.size())
+ }
+public:
+ void find_collision(BOX_SET_CLASS0 * boxset1, const btTransform & trans1,
+ BOX_SET_CLASS1 * boxset2, const btTransform & trans2,
+ gim_pair_set & collision_pairs, bool complete_primitive_tests = true)
+ {
+ m_collision_pairs = &collision_pairs;
+ m_boxset0 = boxset1;
+ m_boxset1 = boxset2;
+
+ trans_cache_1to0.calc_from_homogenic(trans1,trans2);
+
+ trans_cache_0to1 = trans2.inverse();
+ trans_cache_0to1 *= trans1;
+
+
+ if(complete_primitive_tests)
+ {
+ t0_is_trimesh = boxset1->getPrimitiveManager().is_trimesh();
+ t1_is_trimesh = boxset2->getPrimitiveManager().is_trimesh();
+ }
+ else
+ {
+ t0_is_trimesh = false;
+ t1_is_trimesh = false;
+ }
+
+ find_collision_pairs();
+ }
+};
+
+
+#endif // GIM_BOXPRUNING_H_INCLUDED
+
+
diff --git a/thirdparty/bullet/src/BulletCollision/Gimpact/gim_clip_polygon.h b/thirdparty/bullet/src/BulletCollision/Gimpact/gim_clip_polygon.h
new file mode 100644
index 0000000000..e342459ce5
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/Gimpact/gim_clip_polygon.h
@@ -0,0 +1,210 @@
+#ifndef GIM_CLIP_POLYGON_H_INCLUDED
+#define GIM_CLIP_POLYGON_H_INCLUDED
+
+/*! \file gim_tri_collision.h
+\author Francisco Leon Najera
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+ (1) The GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 2.1 of the License, or (at
+ your option) any later version. The text of the GNU Lesser
+ General Public License is included with this library in the
+ file GIMPACT-LICENSE-LGPL.TXT.
+ (2) The BSD-style license that is included with this library in
+ the file GIMPACT-LICENSE-BSD.TXT.
+ (3) The zlib/libpng license that is included with this library in
+ the file GIMPACT-LICENSE-ZLIB.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+
+//! This function calcs the distance from a 3D plane
+class DISTANCE_PLANE_3D_FUNC
+{
+public:
+ template<typename CLASS_POINT,typename CLASS_PLANE>
+ inline GREAL operator()(const CLASS_PLANE & plane, const CLASS_POINT & point)
+ {
+ return DISTANCE_PLANE_POINT(plane, point);
+ }
+};
+
+
+
+template<typename CLASS_POINT>
+SIMD_FORCE_INLINE void PLANE_CLIP_POLYGON_COLLECT(
+ const CLASS_POINT & point0,
+ const CLASS_POINT & point1,
+ GREAL dist0,
+ GREAL dist1,
+ CLASS_POINT * clipped,
+ GUINT & clipped_count)
+{
+ GUINT _prevclassif = (dist0>G_EPSILON);
+ GUINT _classif = (dist1>G_EPSILON);
+ if(_classif!=_prevclassif)
+ {
+ GREAL blendfactor = -dist0/(dist1-dist0);
+ VEC_BLEND(clipped[clipped_count],point0,point1,blendfactor);
+ clipped_count++;
+ }
+ if(!_classif)
+ {
+ VEC_COPY(clipped[clipped_count],point1);
+ clipped_count++;
+ }
+}
+
+
+//! Clips a polygon by a plane
+/*!
+*\return The count of the clipped counts
+*/
+template<typename CLASS_POINT,typename CLASS_PLANE, typename DISTANCE_PLANE_FUNC>
+SIMD_FORCE_INLINE GUINT PLANE_CLIP_POLYGON_GENERIC(
+ const CLASS_PLANE & plane,
+ const CLASS_POINT * polygon_points,
+ GUINT polygon_point_count,
+ CLASS_POINT * clipped,DISTANCE_PLANE_FUNC distance_func)
+{
+ GUINT clipped_count = 0;
+
+
+ //clip first point
+ GREAL firstdist = distance_func(plane,polygon_points[0]);;
+ if(!(firstdist>G_EPSILON))
+ {
+ VEC_COPY(clipped[clipped_count],polygon_points[0]);
+ clipped_count++;
+ }
+
+ GREAL olddist = firstdist;
+ for(GUINT _i=1;_i<polygon_point_count;_i++)
+ {
+ GREAL dist = distance_func(plane,polygon_points[_i]);
+
+ PLANE_CLIP_POLYGON_COLLECT(
+ polygon_points[_i-1],polygon_points[_i],
+ olddist,
+ dist,
+ clipped,
+ clipped_count);
+
+
+ olddist = dist;
+ }
+
+ //RETURN TO FIRST point
+
+ PLANE_CLIP_POLYGON_COLLECT(
+ polygon_points[polygon_point_count-1],polygon_points[0],
+ olddist,
+ firstdist,
+ clipped,
+ clipped_count);
+
+ return clipped_count;
+}
+
+//! Clips a polygon by a plane
+/*!
+*\return The count of the clipped counts
+*/
+template<typename CLASS_POINT,typename CLASS_PLANE, typename DISTANCE_PLANE_FUNC>
+SIMD_FORCE_INLINE GUINT PLANE_CLIP_TRIANGLE_GENERIC(
+ const CLASS_PLANE & plane,
+ const CLASS_POINT & point0,
+ const CLASS_POINT & point1,
+ const CLASS_POINT & point2,
+ CLASS_POINT * clipped,DISTANCE_PLANE_FUNC distance_func)
+{
+ GUINT clipped_count = 0;
+
+ //clip first point
+ GREAL firstdist = distance_func(plane,point0);;
+ if(!(firstdist>G_EPSILON))
+ {
+ VEC_COPY(clipped[clipped_count],point0);
+ clipped_count++;
+ }
+
+ // point 1
+ GREAL olddist = firstdist;
+ GREAL dist = distance_func(plane,point1);
+
+ PLANE_CLIP_POLYGON_COLLECT(
+ point0,point1,
+ olddist,
+ dist,
+ clipped,
+ clipped_count);
+
+ olddist = dist;
+
+
+ // point 2
+ dist = distance_func(plane,point2);
+
+ PLANE_CLIP_POLYGON_COLLECT(
+ point1,point2,
+ olddist,
+ dist,
+ clipped,
+ clipped_count);
+ olddist = dist;
+
+
+
+ //RETURN TO FIRST point
+ PLANE_CLIP_POLYGON_COLLECT(
+ point2,point0,
+ olddist,
+ firstdist,
+ clipped,
+ clipped_count);
+
+ return clipped_count;
+}
+
+
+template<typename CLASS_POINT,typename CLASS_PLANE>
+SIMD_FORCE_INLINE GUINT PLANE_CLIP_POLYGON3D(
+ const CLASS_PLANE & plane,
+ const CLASS_POINT * polygon_points,
+ GUINT polygon_point_count,
+ CLASS_POINT * clipped)
+{
+ return PLANE_CLIP_POLYGON_GENERIC<CLASS_POINT,CLASS_PLANE>(plane,polygon_points,polygon_point_count,clipped,DISTANCE_PLANE_3D_FUNC());
+}
+
+
+template<typename CLASS_POINT,typename CLASS_PLANE>
+SIMD_FORCE_INLINE GUINT PLANE_CLIP_TRIANGLE3D(
+ const CLASS_PLANE & plane,
+ const CLASS_POINT & point0,
+ const CLASS_POINT & point1,
+ const CLASS_POINT & point2,
+ CLASS_POINT * clipped)
+{
+ return PLANE_CLIP_TRIANGLE_GENERIC<CLASS_POINT,CLASS_PLANE>(plane,point0,point1,point2,clipped,DISTANCE_PLANE_3D_FUNC());
+}
+
+
+
+#endif // GIM_TRI_COLLISION_H_INCLUDED
diff --git a/thirdparty/bullet/src/BulletCollision/Gimpact/gim_contact.cpp b/thirdparty/bullet/src/BulletCollision/Gimpact/gim_contact.cpp
new file mode 100644
index 0000000000..20e41de089
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/Gimpact/gim_contact.cpp
@@ -0,0 +1,146 @@
+
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+ (1) The GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 2.1 of the License, or (at
+ your option) any later version. The text of the GNU Lesser
+ General Public License is included with this library in the
+ file GIMPACT-LICENSE-LGPL.TXT.
+ (2) The BSD-style license that is included with this library in
+ the file GIMPACT-LICENSE-BSD.TXT.
+ (3) The zlib/libpng license that is included with this library in
+ the file GIMPACT-LICENSE-ZLIB.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+#include "gim_contact.h"
+
+#define MAX_COINCIDENT 8
+
+void gim_contact_array::merge_contacts(
+ const gim_contact_array & contacts, bool normal_contact_average)
+{
+ clear();
+
+ if(contacts.size()==1)
+ {
+ push_back(contacts.back());
+ return;
+ }
+
+ gim_array<GIM_RSORT_TOKEN> keycontacts(contacts.size());
+ keycontacts.resize(contacts.size(),false);
+
+ //fill key contacts
+
+ GUINT i;
+
+ for (i = 0;i<contacts.size() ;i++ )
+ {
+ keycontacts[i].m_key = contacts[i].calc_key_contact();
+ keycontacts[i].m_value = i;
+ }
+
+ //sort keys
+ gim_heap_sort(keycontacts.pointer(),keycontacts.size(),GIM_RSORT_TOKEN_COMPARATOR());
+
+ // Merge contacts
+
+ GUINT coincident_count=0;
+ btVector3 coincident_normals[MAX_COINCIDENT];
+
+ GUINT last_key = keycontacts[0].m_key;
+ GUINT key = 0;
+
+ push_back(contacts[keycontacts[0].m_value]);
+ GIM_CONTACT * pcontact = &back();
+
+
+
+ for( i=1;i<keycontacts.size();i++)
+ {
+ key = keycontacts[i].m_key;
+ const GIM_CONTACT * scontact = &contacts[keycontacts[i].m_value];
+
+ if(last_key == key)//same points
+ {
+ //merge contact
+ if(pcontact->m_depth - CONTACT_DIFF_EPSILON > scontact->m_depth)//)
+ {
+ *pcontact = *scontact;
+ coincident_count = 0;
+ }
+ else if(normal_contact_average)
+ {
+ if(btFabs(pcontact->m_depth - scontact->m_depth)<CONTACT_DIFF_EPSILON)
+ {
+ if(coincident_count<MAX_COINCIDENT)
+ {
+ coincident_normals[coincident_count] = scontact->m_normal;
+ coincident_count++;
+ }
+ }
+ }
+ }
+ else
+ {//add new contact
+
+ if(normal_contact_average && coincident_count>0)
+ {
+ pcontact->interpolate_normals(coincident_normals,coincident_count);
+ coincident_count = 0;
+ }
+
+ push_back(*scontact);
+ pcontact = &back();
+ }
+ last_key = key;
+ }
+}
+
+void gim_contact_array::merge_contacts_unique(const gim_contact_array & contacts)
+{
+ clear();
+
+ if(contacts.size()==1)
+ {
+ push_back(contacts.back());
+ return;
+ }
+
+ GIM_CONTACT average_contact = contacts.back();
+
+ for (GUINT i=1;i<contacts.size() ;i++ )
+ {
+ average_contact.m_point += contacts[i].m_point;
+ average_contact.m_normal += contacts[i].m_normal * contacts[i].m_depth;
+ }
+
+ //divide
+ GREAL divide_average = 1.0f/((GREAL)contacts.size());
+
+ average_contact.m_point *= divide_average;
+
+ average_contact.m_normal *= divide_average;
+
+ average_contact.m_depth = average_contact.m_normal.length();
+
+ average_contact.m_normal /= average_contact.m_depth;
+
+}
+
diff --git a/thirdparty/bullet/src/BulletCollision/Gimpact/gim_contact.h b/thirdparty/bullet/src/BulletCollision/Gimpact/gim_contact.h
new file mode 100644
index 0000000000..b41c714b5f
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/Gimpact/gim_contact.h
@@ -0,0 +1,172 @@
+#ifndef GIM_CONTACT_H_INCLUDED
+#define GIM_CONTACT_H_INCLUDED
+
+/*! \file gim_contact.h
+\author Francisco Leon Najera
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+ (1) The GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 2.1 of the License, or (at
+ your option) any later version. The text of the GNU Lesser
+ General Public License is included with this library in the
+ file GIMPACT-LICENSE-LGPL.TXT.
+ (2) The BSD-style license that is included with this library in
+ the file GIMPACT-LICENSE-BSD.TXT.
+ (3) The zlib/libpng license that is included with this library in
+ the file GIMPACT-LICENSE-ZLIB.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+#include "gim_geometry.h"
+#include "gim_radixsort.h"
+#include "gim_array.h"
+
+
+/**
+Configuration var for applying interpolation of contact normals
+*/
+#ifndef NORMAL_CONTACT_AVERAGE
+#define NORMAL_CONTACT_AVERAGE 1
+#endif
+
+#ifndef CONTACT_DIFF_EPSILON
+#define CONTACT_DIFF_EPSILON 0.00001f
+#endif
+
+#ifndef BT_CONTACT_H_STRUCTS_INCLUDED
+
+/// Structure for collision results
+///Functions for managing and sorting contacts resulting from a collision query.
+///Contact lists must be create by calling \ref GIM_CREATE_CONTACT_LIST
+///After querys, contact lists must be destroy by calling \ref GIM_DYNARRAY_DESTROY
+///Contacts can be merge for avoid duplicate results by calling \ref gim_merge_contacts
+class GIM_CONTACT
+{
+public:
+ btVector3 m_point;
+ btVector3 m_normal;
+ GREAL m_depth;//Positive value indicates interpenetration
+ GREAL m_distance;//Padding not for use
+ GUINT m_feature1;//Face number
+ GUINT m_feature2;//Face number
+public:
+ GIM_CONTACT()
+ {
+ }
+
+ GIM_CONTACT(const GIM_CONTACT & contact):
+ m_point(contact.m_point),
+ m_normal(contact.m_normal),
+ m_depth(contact.m_depth),
+ m_feature1(contact.m_feature1),
+ m_feature2(contact.m_feature2)
+ {
+ m_point = contact.m_point;
+ m_normal = contact.m_normal;
+ m_depth = contact.m_depth;
+ m_feature1 = contact.m_feature1;
+ m_feature2 = contact.m_feature2;
+ }
+
+ GIM_CONTACT(const btVector3 &point,const btVector3 & normal,
+ GREAL depth, GUINT feature1, GUINT feature2):
+ m_point(point),
+ m_normal(normal),
+ m_depth(depth),
+ m_feature1(feature1),
+ m_feature2(feature2)
+ {
+ }
+
+ //! Calcs key for coord classification
+ SIMD_FORCE_INLINE GUINT calc_key_contact() const
+ {
+ GINT _coords[] = {
+ (GINT)(m_point[0]*1000.0f+1.0f),
+ (GINT)(m_point[1]*1333.0f),
+ (GINT)(m_point[2]*2133.0f+3.0f)};
+ GUINT _hash=0;
+ GUINT *_uitmp = (GUINT *)(&_coords[0]);
+ _hash = *_uitmp;
+ _uitmp++;
+ _hash += (*_uitmp)<<4;
+ _uitmp++;
+ _hash += (*_uitmp)<<8;
+ return _hash;
+ }
+
+ SIMD_FORCE_INLINE void interpolate_normals( btVector3 * normals,GUINT normal_count)
+ {
+ btVector3 vec_sum(m_normal);
+ for(GUINT i=0;i<normal_count;i++)
+ {
+ vec_sum += normals[i];
+ }
+
+ GREAL vec_sum_len = vec_sum.length2();
+ if(vec_sum_len <CONTACT_DIFF_EPSILON) return;
+
+ GIM_INV_SQRT(vec_sum_len,vec_sum_len); // 1/sqrt(vec_sum_len)
+
+ m_normal = vec_sum*vec_sum_len;
+ }
+
+};
+
+#endif
+
+class gim_contact_array:public gim_array<GIM_CONTACT>
+{
+public:
+ gim_contact_array():gim_array<GIM_CONTACT>(64)
+ {
+ }
+
+ SIMD_FORCE_INLINE void push_contact(const btVector3 &point,const btVector3 & normal,
+ GREAL depth, GUINT feature1, GUINT feature2)
+ {
+ push_back_mem();
+ GIM_CONTACT & newele = back();
+ newele.m_point = point;
+ newele.m_normal = normal;
+ newele.m_depth = depth;
+ newele.m_feature1 = feature1;
+ newele.m_feature2 = feature2;
+ }
+
+ SIMD_FORCE_INLINE void push_triangle_contacts(
+ const GIM_TRIANGLE_CONTACT_DATA & tricontact,
+ GUINT feature1,GUINT feature2)
+ {
+ for(GUINT i = 0;i<tricontact.m_point_count ;i++ )
+ {
+ push_back_mem();
+ GIM_CONTACT & newele = back();
+ newele.m_point = tricontact.m_points[i];
+ newele.m_normal = tricontact.m_separating_normal;
+ newele.m_depth = tricontact.m_penetration_depth;
+ newele.m_feature1 = feature1;
+ newele.m_feature2 = feature2;
+ }
+ }
+
+ void merge_contacts(const gim_contact_array & contacts, bool normal_contact_average = true);
+ void merge_contacts_unique(const gim_contact_array & contacts);
+};
+
+#endif // GIM_CONTACT_H_INCLUDED
diff --git a/thirdparty/bullet/src/BulletCollision/Gimpact/gim_geom_types.h b/thirdparty/bullet/src/BulletCollision/Gimpact/gim_geom_types.h
new file mode 100644
index 0000000000..6b8f9ea6c2
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/Gimpact/gim_geom_types.h
@@ -0,0 +1,97 @@
+#ifndef GIM_GEOM_TYPES_H_INCLUDED
+#define GIM_GEOM_TYPES_H_INCLUDED
+
+/*! \file gim_geom_types.h
+\author Francisco Leon Najera
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+ (1) The GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 2.1 of the License, or (at
+ your option) any later version. The text of the GNU Lesser
+ General Public License is included with this library in the
+ file GIMPACT-LICENSE-LGPL.TXT.
+ (2) The BSD-style license that is included with this library in
+ the file GIMPACT-LICENSE-BSD.TXT.
+ (3) The zlib/libpng license that is included with this library in
+ the file GIMPACT-LICENSE-ZLIB.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+
+#include "gim_math.h"
+
+
+
+//! Short Integer vector 2D
+typedef GSHORT vec2s[2];
+//! Integer vector 3D
+typedef GSHORT vec3s[3];
+//! Integer vector 4D
+typedef GSHORT vec4s[4];
+
+//! Short Integer vector 2D
+typedef GUSHORT vec2us[2];
+//! Integer vector 3D
+typedef GUSHORT vec3us[3];
+//! Integer vector 4D
+typedef GUSHORT vec4us[4];
+
+//! Integer vector 2D
+typedef GINT vec2i[2];
+//! Integer vector 3D
+typedef GINT vec3i[3];
+//! Integer vector 4D
+typedef GINT vec4i[4];
+
+//! Unsigned Integer vector 2D
+typedef GUINT vec2ui[2];
+//! Unsigned Integer vector 3D
+typedef GUINT vec3ui[3];
+//! Unsigned Integer vector 4D
+typedef GUINT vec4ui[4];
+
+//! Float vector 2D
+typedef GREAL vec2f[2];
+//! Float vector 3D
+typedef GREAL vec3f[3];
+//! Float vector 4D
+typedef GREAL vec4f[4];
+
+//! Double vector 2D
+typedef GREAL2 vec2d[2];
+//! Float vector 3D
+typedef GREAL2 vec3d[3];
+//! Float vector 4D
+typedef GREAL2 vec4d[4];
+
+//! Matrix 2D, row ordered
+typedef GREAL mat2f[2][2];
+//! Matrix 3D, row ordered
+typedef GREAL mat3f[3][3];
+//! Matrix 4D, row ordered
+typedef GREAL mat4f[4][4];
+
+//! Quaternion
+typedef GREAL quatf[4];
+
+//typedef struct _aabb3f aabb3f;
+
+
+
+#endif // GIM_GEOM_TYPES_H_INCLUDED
diff --git a/thirdparty/bullet/src/BulletCollision/Gimpact/gim_geometry.h b/thirdparty/bullet/src/BulletCollision/Gimpact/gim_geometry.h
new file mode 100644
index 0000000000..c67a6991c0
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/Gimpact/gim_geometry.h
@@ -0,0 +1,42 @@
+#ifndef GIM_GEOMETRY_H_INCLUDED
+#define GIM_GEOMETRY_H_INCLUDED
+
+/*! \file gim_geometry.h
+\author Francisco Leon Najera
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+ (1) The GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 2.1 of the License, or (at
+ your option) any later version. The text of the GNU Lesser
+ General Public License is included with this library in the
+ file GIMPACT-LICENSE-LGPL.TXT.
+ (2) The BSD-style license that is included with this library in
+ the file GIMPACT-LICENSE-BSD.TXT.
+ (3) The zlib/libpng license that is included with this library in
+ the file GIMPACT-LICENSE-ZLIB.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+///Additional Headers for Collision
+#include "gim_basic_geometry_operations.h"
+#include "gim_clip_polygon.h"
+#include "gim_box_collision.h"
+#include "gim_tri_collision.h"
+
+#endif // GIM_VECTOR_H_INCLUDED
diff --git a/thirdparty/bullet/src/BulletCollision/Gimpact/gim_hash_table.h b/thirdparty/bullet/src/BulletCollision/Gimpact/gim_hash_table.h
new file mode 100644
index 0000000000..e4237c2c57
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/Gimpact/gim_hash_table.h
@@ -0,0 +1,902 @@
+#ifndef GIM_HASH_TABLE_H_INCLUDED
+#define GIM_HASH_TABLE_H_INCLUDED
+/*! \file gim_trimesh_data.h
+\author Francisco Leon Najera
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+ (1) The GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 2.1 of the License, or (at
+ your option) any later version. The text of the GNU Lesser
+ General Public License is included with this library in the
+ file GIMPACT-LICENSE-LGPL.TXT.
+ (2) The BSD-style license that is included with this library in
+ the file GIMPACT-LICENSE-BSD.TXT.
+ (3) The zlib/libpng license that is included with this library in
+ the file GIMPACT-LICENSE-ZLIB.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+#include "gim_radixsort.h"
+
+
+#define GIM_INVALID_HASH 0xffffffff //!< A very very high value
+#define GIM_DEFAULT_HASH_TABLE_SIZE 380
+#define GIM_DEFAULT_HASH_TABLE_NODE_SIZE 4
+#define GIM_HASH_TABLE_GROW_FACTOR 2
+
+#define GIM_MIN_RADIX_SORT_SIZE 860 //!< calibrated on a PIII
+
+template<typename T>
+struct GIM_HASH_TABLE_NODE
+{
+ GUINT m_key;
+ T m_data;
+ GIM_HASH_TABLE_NODE()
+ {
+ }
+
+ GIM_HASH_TABLE_NODE(const GIM_HASH_TABLE_NODE & value)
+ {
+ m_key = value.m_key;
+ m_data = value.m_data;
+ }
+
+ GIM_HASH_TABLE_NODE(GUINT key, const T & data)
+ {
+ m_key = key;
+ m_data = data;
+ }
+
+ bool operator <(const GIM_HASH_TABLE_NODE<T> & other) const
+ {
+ ///inverse order, further objects are first
+ if(m_key < other.m_key) return true;
+ return false;
+ }
+
+ bool operator >(const GIM_HASH_TABLE_NODE<T> & other) const
+ {
+ ///inverse order, further objects are first
+ if(m_key > other.m_key) return true;
+ return false;
+ }
+
+ bool operator ==(const GIM_HASH_TABLE_NODE<T> & other) const
+ {
+ ///inverse order, further objects are first
+ if(m_key == other.m_key) return true;
+ return false;
+ }
+};
+
+///Macro for getting the key
+class GIM_HASH_NODE_GET_KEY
+{
+public:
+ template<class T>
+ inline GUINT operator()( const T& a)
+ {
+ return a.m_key;
+ }
+};
+
+
+
+///Macro for comparing the key and the element
+class GIM_HASH_NODE_CMP_KEY_MACRO
+{
+public:
+ template<class T>
+ inline int operator() ( const T& a, GUINT key)
+ {
+ return ((int)(a.m_key - key));
+ }
+};
+
+///Macro for comparing Hash nodes
+class GIM_HASH_NODE_CMP_MACRO
+{
+public:
+ template<class T>
+ inline int operator() ( const T& a, const T& b )
+ {
+ return ((int)(a.m_key - b.m_key));
+ }
+};
+
+
+
+
+
+//! Sorting for hash table
+/*!
+switch automatically between quicksort and radixsort
+*/
+template<typename T>
+void gim_sort_hash_node_array(T * array, GUINT array_count)
+{
+ if(array_count<GIM_MIN_RADIX_SORT_SIZE)
+ {
+ gim_heap_sort(array,array_count,GIM_HASH_NODE_CMP_MACRO());
+ }
+ else
+ {
+ memcopy_elements_func cmpfunc;
+ gim_radix_sort(array,array_count,GIM_HASH_NODE_GET_KEY(),cmpfunc);
+ }
+}
+
+
+
+
+
+
+// Note: assumes long is at least 32 bits.
+#define GIM_NUM_PRIME 28
+
+static const GUINT gim_prime_list[GIM_NUM_PRIME] =
+{
+ 53ul, 97ul, 193ul, 389ul, 769ul,
+ 1543ul, 3079ul, 6151ul, 12289ul, 24593ul,
+ 49157ul, 98317ul, 196613ul, 393241ul, 786433ul,
+ 1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul,
+ 50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul,
+ 1610612741ul, 3221225473ul, 4294967291ul
+};
+
+inline GUINT gim_next_prime(GUINT number)
+{
+ //Find nearest upper prime
+ GUINT result_ind = 0;
+ gim_binary_search(gim_prime_list,0,(GIM_NUM_PRIME-2),number,result_ind);
+
+ // inv: result_ind < 28
+ return gim_prime_list[result_ind];
+}
+
+
+
+//! A compact hash table implementation
+/*!
+A memory aligned compact hash table that coud be treated as an array.
+It could be a simple sorted array without the overhead of the hash key bucked, or could
+be a formely hash table with an array of keys.
+You can use switch_to_hashtable() and switch_to_sorted_array for saving space or increase speed.
+</br>
+
+<ul>
+<li> if node_size = 0, then this container becomes a simple sorted array allocator. reserve_size is used for reserve memory in m_nodes.
+When the array size reaches the size equivalent to 'min_hash_table_size', then it becomes a hash table by calling check_for_switching_to_hashtable.
+<li> If node_size != 0, then this container becomes a hash table for ever
+</ul>
+
+*/
+template<class T>
+class gim_hash_table
+{
+protected:
+ typedef GIM_HASH_TABLE_NODE<T> _node_type;
+
+ //!The nodes
+ //array< _node_type, SuperAllocator<_node_type> > m_nodes;
+ gim_array< _node_type > m_nodes;
+ //SuperBufferedArray< _node_type > m_nodes;
+ bool m_sorted;
+
+ ///Hash table data management. The hash table has the indices to the corresponding m_nodes array
+ GUINT * m_hash_table;//!<
+ GUINT m_table_size;//!<
+ GUINT m_node_size;//!<
+ GUINT m_min_hash_table_size;
+
+
+
+ //! Returns the cell index
+ inline GUINT _find_cell(GUINT hashkey)
+ {
+ _node_type * nodesptr = m_nodes.pointer();
+ GUINT start_index = (hashkey%m_table_size)*m_node_size;
+ GUINT end_index = start_index + m_node_size;
+
+ while(start_index<end_index)
+ {
+ GUINT value = m_hash_table[start_index];
+ if(value != GIM_INVALID_HASH)
+ {
+ if(nodesptr[value].m_key == hashkey) return start_index;
+ }
+ start_index++;
+ }
+ return GIM_INVALID_HASH;
+ }
+
+ //! Find the avaliable cell for the hashkey, and return an existing cell if it has the same hash key
+ inline GUINT _find_avaliable_cell(GUINT hashkey)
+ {
+ _node_type * nodesptr = m_nodes.pointer();
+ GUINT avaliable_index = GIM_INVALID_HASH;
+ GUINT start_index = (hashkey%m_table_size)*m_node_size;
+ GUINT end_index = start_index + m_node_size;
+
+ while(start_index<end_index)
+ {
+ GUINT value = m_hash_table[start_index];
+ if(value == GIM_INVALID_HASH)
+ {
+ if(avaliable_index==GIM_INVALID_HASH)
+ {
+ avaliable_index = start_index;
+ }
+ }
+ else if(nodesptr[value].m_key == hashkey)
+ {
+ return start_index;
+ }
+ start_index++;
+ }
+ return avaliable_index;
+ }
+
+
+
+ //! reserves the memory for the hash table.
+ /*!
+ \pre hash table must be empty
+ \post reserves the memory for the hash table, an initializes all elements to GIM_INVALID_HASH.
+ */
+ inline void _reserve_table_memory(GUINT newtablesize)
+ {
+ if(newtablesize==0) return;
+ if(m_node_size==0) return;
+
+ //Get a Prime size
+
+ m_table_size = gim_next_prime(newtablesize);
+
+ GUINT datasize = m_table_size*m_node_size;
+ //Alloc the data buffer
+ m_hash_table = (GUINT *)gim_alloc(datasize*sizeof(GUINT));
+ }
+
+ inline void _invalidate_keys()
+ {
+ GUINT datasize = m_table_size*m_node_size;
+ for(GUINT i=0;i<datasize;i++)
+ {
+ m_hash_table[i] = GIM_INVALID_HASH;// invalidate keys
+ }
+ }
+
+ //! Clear all memory for the hash table
+ inline void _clear_table_memory()
+ {
+ if(m_hash_table==NULL) return;
+ gim_free(m_hash_table);
+ m_hash_table = NULL;
+ m_table_size = 0;
+ }
+
+ //! Invalidates the keys (Assigning GIM_INVALID_HASH to all) Reorders the hash keys
+ inline void _rehash()
+ {
+ _invalidate_keys();
+
+ _node_type * nodesptr = m_nodes.pointer();
+ for(GUINT i=0;i<(GUINT)m_nodes.size();i++)
+ {
+ GUINT nodekey = nodesptr[i].m_key;
+ if(nodekey != GIM_INVALID_HASH)
+ {
+ //Search for the avaliable cell in buffer
+ GUINT index = _find_avaliable_cell(nodekey);
+
+
+ if(m_hash_table[index]!=GIM_INVALID_HASH)
+ {//The new index is alreade used... discard this new incomming object, repeated key
+ btAssert(m_hash_table[index]==nodekey);
+ nodesptr[i].m_key = GIM_INVALID_HASH;
+ }
+ else
+ {
+ //;
+ //Assign the value for alloc
+ m_hash_table[index] = i;
+ }
+ }
+ }
+ }
+
+ //! Resize hash table indices
+ inline void _resize_table(GUINT newsize)
+ {
+ //Clear memory
+ _clear_table_memory();
+ //Alloc the data
+ _reserve_table_memory(newsize);
+ //Invalidate keys and rehash
+ _rehash();
+ }
+
+ //! Destroy hash table memory
+ inline void _destroy()
+ {
+ if(m_hash_table==NULL) return;
+ _clear_table_memory();
+ }
+
+ //! Finds an avaliable hash table cell, and resizes the table if there isn't space
+ inline GUINT _assign_hash_table_cell(GUINT hashkey)
+ {
+ GUINT cell_index = _find_avaliable_cell(hashkey);
+
+ if(cell_index==GIM_INVALID_HASH)
+ {
+ //rehashing
+ _resize_table(m_table_size+1);
+ GUINT cell_index = _find_avaliable_cell(hashkey);
+ btAssert(cell_index!=GIM_INVALID_HASH);
+ }
+ return cell_index;
+ }
+
+ //! erase by index in hash table
+ inline bool _erase_by_index_hash_table(GUINT index)
+ {
+ if(index >= m_nodes.size()) return false;
+ if(m_nodes[index].m_key != GIM_INVALID_HASH)
+ {
+ //Search for the avaliable cell in buffer
+ GUINT cell_index = _find_cell(m_nodes[index].m_key);
+
+ btAssert(cell_index!=GIM_INVALID_HASH);
+ btAssert(m_hash_table[cell_index]==index);
+
+ m_hash_table[cell_index] = GIM_INVALID_HASH;
+ }
+
+ return this->_erase_unsorted(index);
+ }
+
+ //! erase by key in hash table
+ inline bool _erase_hash_table(GUINT hashkey)
+ {
+ if(hashkey == GIM_INVALID_HASH) return false;
+
+ //Search for the avaliable cell in buffer
+ GUINT cell_index = _find_cell(hashkey);
+ if(cell_index ==GIM_INVALID_HASH) return false;
+
+ GUINT index = m_hash_table[cell_index];
+ m_hash_table[cell_index] = GIM_INVALID_HASH;
+
+ return this->_erase_unsorted(index);
+ }
+
+
+
+ //! insert an element in hash table
+ /*!
+ If the element exists, this won't insert the element
+ \return the index in the array of the existing element,or GIM_INVALID_HASH if the element has been inserted
+ If so, the element has been inserted at the last position of the array.
+ */
+ inline GUINT _insert_hash_table(GUINT hashkey, const T & value)
+ {
+ if(hashkey==GIM_INVALID_HASH)
+ {
+ //Insert anyway
+ _insert_unsorted(hashkey,value);
+ return GIM_INVALID_HASH;
+ }
+
+ GUINT cell_index = _assign_hash_table_cell(hashkey);
+
+ GUINT value_key = m_hash_table[cell_index];
+
+ if(value_key!= GIM_INVALID_HASH) return value_key;// Not overrited
+
+ m_hash_table[cell_index] = m_nodes.size();
+
+ _insert_unsorted(hashkey,value);
+ return GIM_INVALID_HASH;
+ }
+
+ //! insert an element in hash table.
+ /*!
+ If the element exists, this replaces the element.
+ \return the index in the array of the existing element,or GIM_INVALID_HASH if the element has been inserted
+ If so, the element has been inserted at the last position of the array.
+ */
+ inline GUINT _insert_hash_table_replace(GUINT hashkey, const T & value)
+ {
+ if(hashkey==GIM_INVALID_HASH)
+ {
+ //Insert anyway
+ _insert_unsorted(hashkey,value);
+ return GIM_INVALID_HASH;
+ }
+
+ GUINT cell_index = _assign_hash_table_cell(hashkey);
+
+ GUINT value_key = m_hash_table[cell_index];
+
+ if(value_key!= GIM_INVALID_HASH)
+ {//replaces the existing
+ m_nodes[value_key] = _node_type(hashkey,value);
+ return value_key;// index of the replaced element
+ }
+
+ m_hash_table[cell_index] = m_nodes.size();
+
+ _insert_unsorted(hashkey,value);
+ return GIM_INVALID_HASH;
+
+ }
+
+
+ ///Sorted array data management. The hash table has the indices to the corresponding m_nodes array
+ inline bool _erase_sorted(GUINT index)
+ {
+ if(index>=(GUINT)m_nodes.size()) return false;
+ m_nodes.erase_sorted(index);
+ if(m_nodes.size()<2) m_sorted = false;
+ return true;
+ }
+
+ //! faster, but unsorted
+ inline bool _erase_unsorted(GUINT index)
+ {
+ if(index>=m_nodes.size()) return false;
+
+ GUINT lastindex = m_nodes.size()-1;
+ if(index<lastindex && m_hash_table!=0)
+ {
+ GUINT hashkey = m_nodes[lastindex].m_key;
+ if(hashkey!=GIM_INVALID_HASH)
+ {
+ //update the new position of the last element
+ GUINT cell_index = _find_cell(hashkey);
+ btAssert(cell_index!=GIM_INVALID_HASH);
+ //new position of the last element which will be swaped
+ m_hash_table[cell_index] = index;
+ }
+ }
+ m_nodes.erase(index);
+ m_sorted = false;
+ return true;
+ }
+
+ //! Insert in position ordered
+ /*!
+ Also checks if it is needed to transform this container to a hash table, by calling check_for_switching_to_hashtable
+ */
+ inline void _insert_in_pos(GUINT hashkey, const T & value, GUINT pos)
+ {
+ m_nodes.insert(_node_type(hashkey,value),pos);
+ this->check_for_switching_to_hashtable();
+ }
+
+ //! Insert an element in an ordered array
+ inline GUINT _insert_sorted(GUINT hashkey, const T & value)
+ {
+ if(hashkey==GIM_INVALID_HASH || size()==0)
+ {
+ m_nodes.push_back(_node_type(hashkey,value));
+ return GIM_INVALID_HASH;
+ }
+ //Insert at last position
+ //Sort element
+
+
+ GUINT result_ind=0;
+ GUINT last_index = m_nodes.size()-1;
+ _node_type * ptr = m_nodes.pointer();
+
+ bool found = gim_binary_search_ex(
+ ptr,0,last_index,result_ind,hashkey,GIM_HASH_NODE_CMP_KEY_MACRO());
+
+
+ //Insert before found index
+ if(found)
+ {
+ return result_ind;
+ }
+ else
+ {
+ _insert_in_pos(hashkey, value, result_ind);
+ }
+ return GIM_INVALID_HASH;
+ }
+
+ inline GUINT _insert_sorted_replace(GUINT hashkey, const T & value)
+ {
+ if(hashkey==GIM_INVALID_HASH || size()==0)
+ {
+ m_nodes.push_back(_node_type(hashkey,value));
+ return GIM_INVALID_HASH;
+ }
+ //Insert at last position
+ //Sort element
+ GUINT result_ind;
+ GUINT last_index = m_nodes.size()-1;
+ _node_type * ptr = m_nodes.pointer();
+
+ bool found = gim_binary_search_ex(
+ ptr,0,last_index,result_ind,hashkey,GIM_HASH_NODE_CMP_KEY_MACRO());
+
+ //Insert before found index
+ if(found)
+ {
+ m_nodes[result_ind] = _node_type(hashkey,value);
+ }
+ else
+ {
+ _insert_in_pos(hashkey, value, result_ind);
+ }
+ return result_ind;
+ }
+
+ //! Fast insertion in m_nodes array
+ inline GUINT _insert_unsorted(GUINT hashkey, const T & value)
+ {
+ m_nodes.push_back(_node_type(hashkey,value));
+ m_sorted = false;
+ return GIM_INVALID_HASH;
+ }
+
+
+
+public:
+
+ /*!
+ <li> if node_size = 0, then this container becomes a simple sorted array allocator. reserve_size is used for reserve memory in m_nodes.
+ When the array size reaches the size equivalent to 'min_hash_table_size', then it becomes a hash table by calling check_for_switching_to_hashtable.
+ <li> If node_size != 0, then this container becomes a hash table for ever
+ </ul>
+ */
+ gim_hash_table(GUINT reserve_size = GIM_DEFAULT_HASH_TABLE_SIZE,
+ GUINT node_size = GIM_DEFAULT_HASH_TABLE_NODE_SIZE,
+ GUINT min_hash_table_size = GIM_INVALID_HASH)
+ {
+ m_hash_table = NULL;
+ m_table_size = 0;
+ m_sorted = false;
+ m_node_size = node_size;
+ m_min_hash_table_size = min_hash_table_size;
+
+ if(m_node_size!=0)
+ {
+ if(reserve_size!=0)
+ {
+ m_nodes.reserve(reserve_size);
+ _reserve_table_memory(reserve_size);
+ _invalidate_keys();
+ }
+ else
+ {
+ m_nodes.reserve(GIM_DEFAULT_HASH_TABLE_SIZE);
+ _reserve_table_memory(GIM_DEFAULT_HASH_TABLE_SIZE);
+ _invalidate_keys();
+ }
+ }
+ else if(reserve_size!=0)
+ {
+ m_nodes.reserve(reserve_size);
+ }
+
+ }
+
+ ~gim_hash_table()
+ {
+ _destroy();
+ }
+
+ inline bool is_hash_table()
+ {
+ if(m_hash_table) return true;
+ return false;
+ }
+
+ inline bool is_sorted()
+ {
+ if(size()<2) return true;
+ return m_sorted;
+ }
+
+ bool sort()
+ {
+ if(is_sorted()) return true;
+ if(m_nodes.size()<2) return false;
+
+
+ _node_type * ptr = m_nodes.pointer();
+ GUINT siz = m_nodes.size();
+ gim_sort_hash_node_array(ptr,siz);
+ m_sorted=true;
+
+
+
+ if(m_hash_table)
+ {
+ _rehash();
+ }
+ return true;
+ }
+
+ bool switch_to_hashtable()
+ {
+ if(m_hash_table) return false;
+ if(m_node_size==0) m_node_size = GIM_DEFAULT_HASH_TABLE_NODE_SIZE;
+ if(m_nodes.size()<GIM_DEFAULT_HASH_TABLE_SIZE)
+ {
+ _resize_table(GIM_DEFAULT_HASH_TABLE_SIZE);
+ }
+ else
+ {
+ _resize_table(m_nodes.size()+1);
+ }
+
+ return true;
+ }
+
+ bool switch_to_sorted_array()
+ {
+ if(m_hash_table==NULL) return true;
+ _clear_table_memory();
+ return sort();
+ }
+
+ //!If the container reaches the
+ bool check_for_switching_to_hashtable()
+ {
+ if(this->m_hash_table) return true;
+
+ if(!(m_nodes.size()< m_min_hash_table_size))
+ {
+ if(m_node_size == 0)
+ {
+ m_node_size = GIM_DEFAULT_HASH_TABLE_NODE_SIZE;
+ }
+
+ _resize_table(m_nodes.size()+1);
+ return true;
+ }
+ return false;
+ }
+
+ inline void set_sorted(bool value)
+ {
+ m_sorted = value;
+ }
+
+ //! Retrieves the amount of keys.
+ inline GUINT size() const
+ {
+ return m_nodes.size();
+ }
+
+ //! Retrieves the hash key.
+ inline GUINT get_key(GUINT index) const
+ {
+ return m_nodes[index].m_key;
+ }
+
+ //! Retrieves the value by index
+ /*!
+ */
+ inline T * get_value_by_index(GUINT index)
+ {
+ return &m_nodes[index].m_data;
+ }
+
+ inline const T& operator[](GUINT index) const
+ {
+ return m_nodes[index].m_data;
+ }
+
+ inline T& operator[](GUINT index)
+ {
+ return m_nodes[index].m_data;
+ }
+
+ //! Finds the index of the element with the key
+ /*!
+ \return the index in the array of the existing element,or GIM_INVALID_HASH if the element has been inserted
+ If so, the element has been inserted at the last position of the array.
+ */
+ inline GUINT find(GUINT hashkey)
+ {
+ if(m_hash_table)
+ {
+ GUINT cell_index = _find_cell(hashkey);
+ if(cell_index==GIM_INVALID_HASH) return GIM_INVALID_HASH;
+ return m_hash_table[cell_index];
+ }
+ GUINT last_index = m_nodes.size();
+ if(last_index<2)
+ {
+ if(last_index==0) return GIM_INVALID_HASH;
+ if(m_nodes[0].m_key == hashkey) return 0;
+ return GIM_INVALID_HASH;
+ }
+ else if(m_sorted)
+ {
+ //Binary search
+ GUINT result_ind = 0;
+ last_index--;
+ _node_type * ptr = m_nodes.pointer();
+
+ bool found = gim_binary_search_ex(ptr,0,last_index,result_ind,hashkey,GIM_HASH_NODE_CMP_KEY_MACRO());
+
+
+ if(found) return result_ind;
+ }
+ return GIM_INVALID_HASH;
+ }
+
+ //! Retrieves the value associated with the index
+ /*!
+ \return the found element, or null
+ */
+ inline T * get_value(GUINT hashkey)
+ {
+ GUINT index = find(hashkey);
+ if(index == GIM_INVALID_HASH) return NULL;
+ return &m_nodes[index].m_data;
+ }
+
+
+ /*!
+ */
+ inline bool erase_by_index(GUINT index)
+ {
+ if(index > m_nodes.size()) return false;
+
+ if(m_hash_table == NULL)
+ {
+ if(is_sorted())
+ {
+ return this->_erase_sorted(index);
+ }
+ else
+ {
+ return this->_erase_unsorted(index);
+ }
+ }
+ else
+ {
+ return this->_erase_by_index_hash_table(index);
+ }
+ return false;
+ }
+
+
+
+ inline bool erase_by_index_unsorted(GUINT index)
+ {
+ if(index > m_nodes.size()) return false;
+
+ if(m_hash_table == NULL)
+ {
+ return this->_erase_unsorted(index);
+ }
+ else
+ {
+ return this->_erase_by_index_hash_table(index);
+ }
+ return false;
+ }
+
+
+
+ /*!
+
+ */
+ inline bool erase_by_key(GUINT hashkey)
+ {
+ if(size()==0) return false;
+
+ if(m_hash_table)
+ {
+ return this->_erase_hash_table(hashkey);
+ }
+ //Binary search
+
+ if(is_sorted()==false) return false;
+
+ GUINT result_ind = find(hashkey);
+ if(result_ind!= GIM_INVALID_HASH)
+ {
+ return this->_erase_sorted(result_ind);
+ }
+ return false;
+ }
+
+ void clear()
+ {
+ m_nodes.clear();
+
+ if(m_hash_table==NULL) return;
+ GUINT datasize = m_table_size*m_node_size;
+ //Initialize the hashkeys.
+ GUINT i;
+ for(i=0;i<datasize;i++)
+ {
+ m_hash_table[i] = GIM_INVALID_HASH;// invalidate keys
+ }
+ m_sorted = false;
+ }
+
+ //! Insert an element into the hash
+ /*!
+ \return If GIM_INVALID_HASH, the object has been inserted succesfully. Else it returns the position
+ of the existing element.
+ */
+ inline GUINT insert(GUINT hashkey, const T & element)
+ {
+ if(m_hash_table)
+ {
+ return this->_insert_hash_table(hashkey,element);
+ }
+ if(this->is_sorted())
+ {
+ return this->_insert_sorted(hashkey,element);
+ }
+ return this->_insert_unsorted(hashkey,element);
+ }
+
+ //! Insert an element into the hash, and could overrite an existing object with the same hash.
+ /*!
+ \return If GIM_INVALID_HASH, the object has been inserted succesfully. Else it returns the position
+ of the replaced element.
+ */
+ inline GUINT insert_override(GUINT hashkey, const T & element)
+ {
+ if(m_hash_table)
+ {
+ return this->_insert_hash_table_replace(hashkey,element);
+ }
+ if(this->is_sorted())
+ {
+ return this->_insert_sorted_replace(hashkey,element);
+ }
+ this->_insert_unsorted(hashkey,element);
+ return m_nodes.size();
+ }
+
+
+
+ //! Insert an element into the hash,But if this container is a sorted array, this inserts it unsorted
+ /*!
+ */
+ inline GUINT insert_unsorted(GUINT hashkey,const T & element)
+ {
+ if(m_hash_table)
+ {
+ return this->_insert_hash_table(hashkey,element);
+ }
+ return this->_insert_unsorted(hashkey,element);
+ }
+
+
+};
+
+
+
+#endif // GIM_CONTAINERS_H_INCLUDED
diff --git a/thirdparty/bullet/src/BulletCollision/Gimpact/gim_linear_math.h b/thirdparty/bullet/src/BulletCollision/Gimpact/gim_linear_math.h
new file mode 100644
index 0000000000..64f11b4954
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/Gimpact/gim_linear_math.h
@@ -0,0 +1,1573 @@
+#ifndef GIM_LINEAR_H_INCLUDED
+#define GIM_LINEAR_H_INCLUDED
+
+/*! \file gim_linear_math.h
+*\author Francisco Leon Najera
+Type Independant Vector and matrix operations.
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+ (1) The GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 2.1 of the License, or (at
+ your option) any later version. The text of the GNU Lesser
+ General Public License is included with this library in the
+ file GIMPACT-LICENSE-LGPL.TXT.
+ (2) The BSD-style license that is included with this library in
+ the file GIMPACT-LICENSE-BSD.TXT.
+ (3) The zlib/libpng license that is included with this library in
+ the file GIMPACT-LICENSE-ZLIB.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+
+#include "gim_math.h"
+#include "gim_geom_types.h"
+
+
+
+
+//! Zero out a 2D vector
+#define VEC_ZERO_2(a) \
+{ \
+ (a)[0] = (a)[1] = 0.0f; \
+}\
+
+
+//! Zero out a 3D vector
+#define VEC_ZERO(a) \
+{ \
+ (a)[0] = (a)[1] = (a)[2] = 0.0f; \
+}\
+
+
+/// Zero out a 4D vector
+#define VEC_ZERO_4(a) \
+{ \
+ (a)[0] = (a)[1] = (a)[2] = (a)[3] = 0.0f; \
+}\
+
+
+/// Vector copy
+#define VEC_COPY_2(b,a) \
+{ \
+ (b)[0] = (a)[0]; \
+ (b)[1] = (a)[1]; \
+}\
+
+
+/// Copy 3D vector
+#define VEC_COPY(b,a) \
+{ \
+ (b)[0] = (a)[0]; \
+ (b)[1] = (a)[1]; \
+ (b)[2] = (a)[2]; \
+}\
+
+
+/// Copy 4D vector
+#define VEC_COPY_4(b,a) \
+{ \
+ (b)[0] = (a)[0]; \
+ (b)[1] = (a)[1]; \
+ (b)[2] = (a)[2]; \
+ (b)[3] = (a)[3]; \
+}\
+
+/// VECTOR SWAP
+#define VEC_SWAP(b,a) \
+{ \
+ GIM_SWAP_NUMBERS((b)[0],(a)[0]);\
+ GIM_SWAP_NUMBERS((b)[1],(a)[1]);\
+ GIM_SWAP_NUMBERS((b)[2],(a)[2]);\
+}\
+
+/// Vector difference
+#define VEC_DIFF_2(v21,v2,v1) \
+{ \
+ (v21)[0] = (v2)[0] - (v1)[0]; \
+ (v21)[1] = (v2)[1] - (v1)[1]; \
+}\
+
+
+/// Vector difference
+#define VEC_DIFF(v21,v2,v1) \
+{ \
+ (v21)[0] = (v2)[0] - (v1)[0]; \
+ (v21)[1] = (v2)[1] - (v1)[1]; \
+ (v21)[2] = (v2)[2] - (v1)[2]; \
+}\
+
+
+/// Vector difference
+#define VEC_DIFF_4(v21,v2,v1) \
+{ \
+ (v21)[0] = (v2)[0] - (v1)[0]; \
+ (v21)[1] = (v2)[1] - (v1)[1]; \
+ (v21)[2] = (v2)[2] - (v1)[2]; \
+ (v21)[3] = (v2)[3] - (v1)[3]; \
+}\
+
+
+/// Vector sum
+#define VEC_SUM_2(v21,v2,v1) \
+{ \
+ (v21)[0] = (v2)[0] + (v1)[0]; \
+ (v21)[1] = (v2)[1] + (v1)[1]; \
+}\
+
+
+/// Vector sum
+#define VEC_SUM(v21,v2,v1) \
+{ \
+ (v21)[0] = (v2)[0] + (v1)[0]; \
+ (v21)[1] = (v2)[1] + (v1)[1]; \
+ (v21)[2] = (v2)[2] + (v1)[2]; \
+}\
+
+
+/// Vector sum
+#define VEC_SUM_4(v21,v2,v1) \
+{ \
+ (v21)[0] = (v2)[0] + (v1)[0]; \
+ (v21)[1] = (v2)[1] + (v1)[1]; \
+ (v21)[2] = (v2)[2] + (v1)[2]; \
+ (v21)[3] = (v2)[3] + (v1)[3]; \
+}\
+
+
+/// scalar times vector
+#define VEC_SCALE_2(c,a,b) \
+{ \
+ (c)[0] = (a)*(b)[0]; \
+ (c)[1] = (a)*(b)[1]; \
+}\
+
+
+/// scalar times vector
+#define VEC_SCALE(c,a,b) \
+{ \
+ (c)[0] = (a)*(b)[0]; \
+ (c)[1] = (a)*(b)[1]; \
+ (c)[2] = (a)*(b)[2]; \
+}\
+
+
+/// scalar times vector
+#define VEC_SCALE_4(c,a,b) \
+{ \
+ (c)[0] = (a)*(b)[0]; \
+ (c)[1] = (a)*(b)[1]; \
+ (c)[2] = (a)*(b)[2]; \
+ (c)[3] = (a)*(b)[3]; \
+}\
+
+
+/// accumulate scaled vector
+#define VEC_ACCUM_2(c,a,b) \
+{ \
+ (c)[0] += (a)*(b)[0]; \
+ (c)[1] += (a)*(b)[1]; \
+}\
+
+
+/// accumulate scaled vector
+#define VEC_ACCUM(c,a,b) \
+{ \
+ (c)[0] += (a)*(b)[0]; \
+ (c)[1] += (a)*(b)[1]; \
+ (c)[2] += (a)*(b)[2]; \
+}\
+
+
+/// accumulate scaled vector
+#define VEC_ACCUM_4(c,a,b) \
+{ \
+ (c)[0] += (a)*(b)[0]; \
+ (c)[1] += (a)*(b)[1]; \
+ (c)[2] += (a)*(b)[2]; \
+ (c)[3] += (a)*(b)[3]; \
+}\
+
+
+/// Vector dot product
+#define VEC_DOT_2(a,b) ((a)[0]*(b)[0] + (a)[1]*(b)[1])
+
+
+/// Vector dot product
+#define VEC_DOT(a,b) ((a)[0]*(b)[0] + (a)[1]*(b)[1] + (a)[2]*(b)[2])
+
+/// Vector dot product
+#define VEC_DOT_4(a,b) ((a)[0]*(b)[0] + (a)[1]*(b)[1] + (a)[2]*(b)[2] + (a)[3]*(b)[3])
+
+/// vector impact parameter (squared)
+#define VEC_IMPACT_SQ(bsq,direction,position) {\
+ GREAL _llel_ = VEC_DOT(direction, position);\
+ bsq = VEC_DOT(position, position) - _llel_*_llel_;\
+}\
+
+
+/// vector impact parameter
+#define VEC_IMPACT(bsq,direction,position) {\
+ VEC_IMPACT_SQ(bsq,direction,position); \
+ GIM_SQRT(bsq,bsq); \
+}\
+
+/// Vector length
+#define VEC_LENGTH_2(a,l)\
+{\
+ GREAL _pp = VEC_DOT_2(a,a);\
+ GIM_SQRT(_pp,l);\
+}\
+
+
+/// Vector length
+#define VEC_LENGTH(a,l)\
+{\
+ GREAL _pp = VEC_DOT(a,a);\
+ GIM_SQRT(_pp,l);\
+}\
+
+
+/// Vector length
+#define VEC_LENGTH_4(a,l)\
+{\
+ GREAL _pp = VEC_DOT_4(a,a);\
+ GIM_SQRT(_pp,l);\
+}\
+
+/// Vector inv length
+#define VEC_INV_LENGTH_2(a,l)\
+{\
+ GREAL _pp = VEC_DOT_2(a,a);\
+ GIM_INV_SQRT(_pp,l);\
+}\
+
+
+/// Vector inv length
+#define VEC_INV_LENGTH(a,l)\
+{\
+ GREAL _pp = VEC_DOT(a,a);\
+ GIM_INV_SQRT(_pp,l);\
+}\
+
+
+/// Vector inv length
+#define VEC_INV_LENGTH_4(a,l)\
+{\
+ GREAL _pp = VEC_DOT_4(a,a);\
+ GIM_INV_SQRT(_pp,l);\
+}\
+
+
+
+/// distance between two points
+#define VEC_DISTANCE(_len,_va,_vb) {\
+ vec3f _tmp_; \
+ VEC_DIFF(_tmp_, _vb, _va); \
+ VEC_LENGTH(_tmp_,_len); \
+}\
+
+
+/// Vector length
+#define VEC_CONJUGATE_LENGTH(a,l)\
+{\
+ GREAL _pp = 1.0 - a[0]*a[0] - a[1]*a[1] - a[2]*a[2];\
+ GIM_SQRT(_pp,l);\
+}\
+
+
+/// Vector length
+#define VEC_NORMALIZE(a) { \
+ GREAL len;\
+ VEC_INV_LENGTH(a,len); \
+ if(len<G_REAL_INFINITY)\
+ {\
+ a[0] *= len; \
+ a[1] *= len; \
+ a[2] *= len; \
+ } \
+}\
+
+/// Set Vector size
+#define VEC_RENORMALIZE(a,newlen) { \
+ GREAL len;\
+ VEC_INV_LENGTH(a,len); \
+ if(len<G_REAL_INFINITY)\
+ {\
+ len *= newlen;\
+ a[0] *= len; \
+ a[1] *= len; \
+ a[2] *= len; \
+ } \
+}\
+
+/// Vector cross
+#define VEC_CROSS(c,a,b) \
+{ \
+ c[0] = (a)[1] * (b)[2] - (a)[2] * (b)[1]; \
+ c[1] = (a)[2] * (b)[0] - (a)[0] * (b)[2]; \
+ c[2] = (a)[0] * (b)[1] - (a)[1] * (b)[0]; \
+}\
+
+
+/*! Vector perp -- assumes that n is of unit length
+ * accepts vector v, subtracts out any component parallel to n */
+#define VEC_PERPENDICULAR(vp,v,n) \
+{ \
+ GREAL dot = VEC_DOT(v, n); \
+ vp[0] = (v)[0] - dot*(n)[0]; \
+ vp[1] = (v)[1] - dot*(n)[1]; \
+ vp[2] = (v)[2] - dot*(n)[2]; \
+}\
+
+
+/*! Vector parallel -- assumes that n is of unit length */
+#define VEC_PARALLEL(vp,v,n) \
+{ \
+ GREAL dot = VEC_DOT(v, n); \
+ vp[0] = (dot) * (n)[0]; \
+ vp[1] = (dot) * (n)[1]; \
+ vp[2] = (dot) * (n)[2]; \
+}\
+
+/*! Same as Vector parallel -- n can have any length
+ * accepts vector v, subtracts out any component perpendicular to n */
+#define VEC_PROJECT(vp,v,n) \
+{ \
+ GREAL scalar = VEC_DOT(v, n); \
+ scalar/= VEC_DOT(n, n); \
+ vp[0] = (scalar) * (n)[0]; \
+ vp[1] = (scalar) * (n)[1]; \
+ vp[2] = (scalar) * (n)[2]; \
+}\
+
+
+/*! accepts vector v*/
+#define VEC_UNPROJECT(vp,v,n) \
+{ \
+ GREAL scalar = VEC_DOT(v, n); \
+ scalar = VEC_DOT(n, n)/scalar; \
+ vp[0] = (scalar) * (n)[0]; \
+ vp[1] = (scalar) * (n)[1]; \
+ vp[2] = (scalar) * (n)[2]; \
+}\
+
+
+/*! Vector reflection -- assumes n is of unit length
+ Takes vector v, reflects it against reflector n, and returns vr */
+#define VEC_REFLECT(vr,v,n) \
+{ \
+ GREAL dot = VEC_DOT(v, n); \
+ vr[0] = (v)[0] - 2.0 * (dot) * (n)[0]; \
+ vr[1] = (v)[1] - 2.0 * (dot) * (n)[1]; \
+ vr[2] = (v)[2] - 2.0 * (dot) * (n)[2]; \
+}\
+
+
+/*! Vector blending
+Takes two vectors a, b, blends them together with two scalars */
+#define VEC_BLEND_AB(vr,sa,a,sb,b) \
+{ \
+ vr[0] = (sa) * (a)[0] + (sb) * (b)[0]; \
+ vr[1] = (sa) * (a)[1] + (sb) * (b)[1]; \
+ vr[2] = (sa) * (a)[2] + (sb) * (b)[2]; \
+}\
+
+/*! Vector blending
+Takes two vectors a, b, blends them together with s <=1 */
+#define VEC_BLEND(vr,a,b,s) VEC_BLEND_AB(vr,(1-s),a,s,b)
+
+#define VEC_SET3(a,b,op,c) a[0]=b[0] op c[0]; a[1]=b[1] op c[1]; a[2]=b[2] op c[2];
+
+//! Finds the bigger cartesian coordinate from a vector
+#define VEC_MAYOR_COORD(vec, maxc)\
+{\
+ GREAL A[] = {fabs(vec[0]),fabs(vec[1]),fabs(vec[2])};\
+ maxc = A[0]>A[1]?(A[0]>A[2]?0:2):(A[1]>A[2]?1:2);\
+}\
+
+//! Finds the 2 smallest cartesian coordinates from a vector
+#define VEC_MINOR_AXES(vec, i0, i1)\
+{\
+ VEC_MAYOR_COORD(vec,i0);\
+ i0 = (i0+1)%3;\
+ i1 = (i0+1)%3;\
+}\
+
+
+
+
+#define VEC_EQUAL(v1,v2) (v1[0]==v2[0]&&v1[1]==v2[1]&&v1[2]==v2[2])
+
+#define VEC_NEAR_EQUAL(v1,v2) (GIM_NEAR_EQUAL(v1[0],v2[0])&&GIM_NEAR_EQUAL(v1[1],v2[1])&&GIM_NEAR_EQUAL(v1[2],v2[2]))
+
+
+/// Vector cross
+#define X_AXIS_CROSS_VEC(dst,src)\
+{ \
+ dst[0] = 0.0f; \
+ dst[1] = -src[2]; \
+ dst[2] = src[1]; \
+}\
+
+#define Y_AXIS_CROSS_VEC(dst,src)\
+{ \
+ dst[0] = src[2]; \
+ dst[1] = 0.0f; \
+ dst[2] = -src[0]; \
+}\
+
+#define Z_AXIS_CROSS_VEC(dst,src)\
+{ \
+ dst[0] = -src[1]; \
+ dst[1] = src[0]; \
+ dst[2] = 0.0f; \
+}\
+
+
+
+
+
+
+/// initialize matrix
+#define IDENTIFY_MATRIX_3X3(m) \
+{ \
+ m[0][0] = 1.0; \
+ m[0][1] = 0.0; \
+ m[0][2] = 0.0; \
+ \
+ m[1][0] = 0.0; \
+ m[1][1] = 1.0; \
+ m[1][2] = 0.0; \
+ \
+ m[2][0] = 0.0; \
+ m[2][1] = 0.0; \
+ m[2][2] = 1.0; \
+}\
+
+/*! initialize matrix */
+#define IDENTIFY_MATRIX_4X4(m) \
+{ \
+ m[0][0] = 1.0; \
+ m[0][1] = 0.0; \
+ m[0][2] = 0.0; \
+ m[0][3] = 0.0; \
+ \
+ m[1][0] = 0.0; \
+ m[1][1] = 1.0; \
+ m[1][2] = 0.0; \
+ m[1][3] = 0.0; \
+ \
+ m[2][0] = 0.0; \
+ m[2][1] = 0.0; \
+ m[2][2] = 1.0; \
+ m[2][3] = 0.0; \
+ \
+ m[3][0] = 0.0; \
+ m[3][1] = 0.0; \
+ m[3][2] = 0.0; \
+ m[3][3] = 1.0; \
+}\
+
+/*! initialize matrix */
+#define ZERO_MATRIX_4X4(m) \
+{ \
+ m[0][0] = 0.0; \
+ m[0][1] = 0.0; \
+ m[0][2] = 0.0; \
+ m[0][3] = 0.0; \
+ \
+ m[1][0] = 0.0; \
+ m[1][1] = 0.0; \
+ m[1][2] = 0.0; \
+ m[1][3] = 0.0; \
+ \
+ m[2][0] = 0.0; \
+ m[2][1] = 0.0; \
+ m[2][2] = 0.0; \
+ m[2][3] = 0.0; \
+ \
+ m[3][0] = 0.0; \
+ m[3][1] = 0.0; \
+ m[3][2] = 0.0; \
+ m[3][3] = 0.0; \
+}\
+
+/*! matrix rotation X */
+#define ROTX_CS(m,cosine,sine) \
+{ \
+ /* rotation about the x-axis */ \
+ \
+ m[0][0] = 1.0; \
+ m[0][1] = 0.0; \
+ m[0][2] = 0.0; \
+ m[0][3] = 0.0; \
+ \
+ m[1][0] = 0.0; \
+ m[1][1] = (cosine); \
+ m[1][2] = (sine); \
+ m[1][3] = 0.0; \
+ \
+ m[2][0] = 0.0; \
+ m[2][1] = -(sine); \
+ m[2][2] = (cosine); \
+ m[2][3] = 0.0; \
+ \
+ m[3][0] = 0.0; \
+ m[3][1] = 0.0; \
+ m[3][2] = 0.0; \
+ m[3][3] = 1.0; \
+}\
+
+/*! matrix rotation Y */
+#define ROTY_CS(m,cosine,sine) \
+{ \
+ /* rotation about the y-axis */ \
+ \
+ m[0][0] = (cosine); \
+ m[0][1] = 0.0; \
+ m[0][2] = -(sine); \
+ m[0][3] = 0.0; \
+ \
+ m[1][0] = 0.0; \
+ m[1][1] = 1.0; \
+ m[1][2] = 0.0; \
+ m[1][3] = 0.0; \
+ \
+ m[2][0] = (sine); \
+ m[2][1] = 0.0; \
+ m[2][2] = (cosine); \
+ m[2][3] = 0.0; \
+ \
+ m[3][0] = 0.0; \
+ m[3][1] = 0.0; \
+ m[3][2] = 0.0; \
+ m[3][3] = 1.0; \
+}\
+
+/*! matrix rotation Z */
+#define ROTZ_CS(m,cosine,sine) \
+{ \
+ /* rotation about the z-axis */ \
+ \
+ m[0][0] = (cosine); \
+ m[0][1] = (sine); \
+ m[0][2] = 0.0; \
+ m[0][3] = 0.0; \
+ \
+ m[1][0] = -(sine); \
+ m[1][1] = (cosine); \
+ m[1][2] = 0.0; \
+ m[1][3] = 0.0; \
+ \
+ m[2][0] = 0.0; \
+ m[2][1] = 0.0; \
+ m[2][2] = 1.0; \
+ m[2][3] = 0.0; \
+ \
+ m[3][0] = 0.0; \
+ m[3][1] = 0.0; \
+ m[3][2] = 0.0; \
+ m[3][3] = 1.0; \
+}\
+
+/*! matrix copy */
+#define COPY_MATRIX_2X2(b,a) \
+{ \
+ b[0][0] = a[0][0]; \
+ b[0][1] = a[0][1]; \
+ \
+ b[1][0] = a[1][0]; \
+ b[1][1] = a[1][1]; \
+ \
+}\
+
+
+/*! matrix copy */
+#define COPY_MATRIX_2X3(b,a) \
+{ \
+ b[0][0] = a[0][0]; \
+ b[0][1] = a[0][1]; \
+ b[0][2] = a[0][2]; \
+ \
+ b[1][0] = a[1][0]; \
+ b[1][1] = a[1][1]; \
+ b[1][2] = a[1][2]; \
+}\
+
+
+/*! matrix copy */
+#define COPY_MATRIX_3X3(b,a) \
+{ \
+ b[0][0] = a[0][0]; \
+ b[0][1] = a[0][1]; \
+ b[0][2] = a[0][2]; \
+ \
+ b[1][0] = a[1][0]; \
+ b[1][1] = a[1][1]; \
+ b[1][2] = a[1][2]; \
+ \
+ b[2][0] = a[2][0]; \
+ b[2][1] = a[2][1]; \
+ b[2][2] = a[2][2]; \
+}\
+
+
+/*! matrix copy */
+#define COPY_MATRIX_4X4(b,a) \
+{ \
+ b[0][0] = a[0][0]; \
+ b[0][1] = a[0][1]; \
+ b[0][2] = a[0][2]; \
+ b[0][3] = a[0][3]; \
+ \
+ b[1][0] = a[1][0]; \
+ b[1][1] = a[1][1]; \
+ b[1][2] = a[1][2]; \
+ b[1][3] = a[1][3]; \
+ \
+ b[2][0] = a[2][0]; \
+ b[2][1] = a[2][1]; \
+ b[2][2] = a[2][2]; \
+ b[2][3] = a[2][3]; \
+ \
+ b[3][0] = a[3][0]; \
+ b[3][1] = a[3][1]; \
+ b[3][2] = a[3][2]; \
+ b[3][3] = a[3][3]; \
+}\
+
+
+/*! matrix transpose */
+#define TRANSPOSE_MATRIX_2X2(b,a) \
+{ \
+ b[0][0] = a[0][0]; \
+ b[0][1] = a[1][0]; \
+ \
+ b[1][0] = a[0][1]; \
+ b[1][1] = a[1][1]; \
+}\
+
+
+/*! matrix transpose */
+#define TRANSPOSE_MATRIX_3X3(b,a) \
+{ \
+ b[0][0] = a[0][0]; \
+ b[0][1] = a[1][0]; \
+ b[0][2] = a[2][0]; \
+ \
+ b[1][0] = a[0][1]; \
+ b[1][1] = a[1][1]; \
+ b[1][2] = a[2][1]; \
+ \
+ b[2][0] = a[0][2]; \
+ b[2][1] = a[1][2]; \
+ b[2][2] = a[2][2]; \
+}\
+
+
+/*! matrix transpose */
+#define TRANSPOSE_MATRIX_4X4(b,a) \
+{ \
+ b[0][0] = a[0][0]; \
+ b[0][1] = a[1][0]; \
+ b[0][2] = a[2][0]; \
+ b[0][3] = a[3][0]; \
+ \
+ b[1][0] = a[0][1]; \
+ b[1][1] = a[1][1]; \
+ b[1][2] = a[2][1]; \
+ b[1][3] = a[3][1]; \
+ \
+ b[2][0] = a[0][2]; \
+ b[2][1] = a[1][2]; \
+ b[2][2] = a[2][2]; \
+ b[2][3] = a[3][2]; \
+ \
+ b[3][0] = a[0][3]; \
+ b[3][1] = a[1][3]; \
+ b[3][2] = a[2][3]; \
+ b[3][3] = a[3][3]; \
+}\
+
+
+/*! multiply matrix by scalar */
+#define SCALE_MATRIX_2X2(b,s,a) \
+{ \
+ b[0][0] = (s) * a[0][0]; \
+ b[0][1] = (s) * a[0][1]; \
+ \
+ b[1][0] = (s) * a[1][0]; \
+ b[1][1] = (s) * a[1][1]; \
+}\
+
+
+/*! multiply matrix by scalar */
+#define SCALE_MATRIX_3X3(b,s,a) \
+{ \
+ b[0][0] = (s) * a[0][0]; \
+ b[0][1] = (s) * a[0][1]; \
+ b[0][2] = (s) * a[0][2]; \
+ \
+ b[1][0] = (s) * a[1][0]; \
+ b[1][1] = (s) * a[1][1]; \
+ b[1][2] = (s) * a[1][2]; \
+ \
+ b[2][0] = (s) * a[2][0]; \
+ b[2][1] = (s) * a[2][1]; \
+ b[2][2] = (s) * a[2][2]; \
+}\
+
+
+/*! multiply matrix by scalar */
+#define SCALE_MATRIX_4X4(b,s,a) \
+{ \
+ b[0][0] = (s) * a[0][0]; \
+ b[0][1] = (s) * a[0][1]; \
+ b[0][2] = (s) * a[0][2]; \
+ b[0][3] = (s) * a[0][3]; \
+ \
+ b[1][0] = (s) * a[1][0]; \
+ b[1][1] = (s) * a[1][1]; \
+ b[1][2] = (s) * a[1][2]; \
+ b[1][3] = (s) * a[1][3]; \
+ \
+ b[2][0] = (s) * a[2][0]; \
+ b[2][1] = (s) * a[2][1]; \
+ b[2][2] = (s) * a[2][2]; \
+ b[2][3] = (s) * a[2][3]; \
+ \
+ b[3][0] = s * a[3][0]; \
+ b[3][1] = s * a[3][1]; \
+ b[3][2] = s * a[3][2]; \
+ b[3][3] = s * a[3][3]; \
+}\
+
+
+/*! multiply matrix by scalar */
+#define SCALE_VEC_MATRIX_2X2(b,svec,a) \
+{ \
+ b[0][0] = svec[0] * a[0][0]; \
+ b[1][0] = svec[0] * a[1][0]; \
+ \
+ b[0][1] = svec[1] * a[0][1]; \
+ b[1][1] = svec[1] * a[1][1]; \
+}\
+
+
+/*! multiply matrix by scalar. Each columns is scaled by each scalar vector component */
+#define SCALE_VEC_MATRIX_3X3(b,svec,a) \
+{ \
+ b[0][0] = svec[0] * a[0][0]; \
+ b[1][0] = svec[0] * a[1][0]; \
+ b[2][0] = svec[0] * a[2][0]; \
+ \
+ b[0][1] = svec[1] * a[0][1]; \
+ b[1][1] = svec[1] * a[1][1]; \
+ b[2][1] = svec[1] * a[2][1]; \
+ \
+ b[0][2] = svec[2] * a[0][2]; \
+ b[1][2] = svec[2] * a[1][2]; \
+ b[2][2] = svec[2] * a[2][2]; \
+}\
+
+
+/*! multiply matrix by scalar */
+#define SCALE_VEC_MATRIX_4X4(b,svec,a) \
+{ \
+ b[0][0] = svec[0] * a[0][0]; \
+ b[1][0] = svec[0] * a[1][0]; \
+ b[2][0] = svec[0] * a[2][0]; \
+ b[3][0] = svec[0] * a[3][0]; \
+ \
+ b[0][1] = svec[1] * a[0][1]; \
+ b[1][1] = svec[1] * a[1][1]; \
+ b[2][1] = svec[1] * a[2][1]; \
+ b[3][1] = svec[1] * a[3][1]; \
+ \
+ b[0][2] = svec[2] * a[0][2]; \
+ b[1][2] = svec[2] * a[1][2]; \
+ b[2][2] = svec[2] * a[2][2]; \
+ b[3][2] = svec[2] * a[3][2]; \
+ \
+ b[0][3] = svec[3] * a[0][3]; \
+ b[1][3] = svec[3] * a[1][3]; \
+ b[2][3] = svec[3] * a[2][3]; \
+ b[3][3] = svec[3] * a[3][3]; \
+}\
+
+
+/*! multiply matrix by scalar */
+#define ACCUM_SCALE_MATRIX_2X2(b,s,a) \
+{ \
+ b[0][0] += (s) * a[0][0]; \
+ b[0][1] += (s) * a[0][1]; \
+ \
+ b[1][0] += (s) * a[1][0]; \
+ b[1][1] += (s) * a[1][1]; \
+}\
+
+
+/*! multiply matrix by scalar */
+#define ACCUM_SCALE_MATRIX_3X3(b,s,a) \
+{ \
+ b[0][0] += (s) * a[0][0]; \
+ b[0][1] += (s) * a[0][1]; \
+ b[0][2] += (s) * a[0][2]; \
+ \
+ b[1][0] += (s) * a[1][0]; \
+ b[1][1] += (s) * a[1][1]; \
+ b[1][2] += (s) * a[1][2]; \
+ \
+ b[2][0] += (s) * a[2][0]; \
+ b[2][1] += (s) * a[2][1]; \
+ b[2][2] += (s) * a[2][2]; \
+}\
+
+
+/*! multiply matrix by scalar */
+#define ACCUM_SCALE_MATRIX_4X4(b,s,a) \
+{ \
+ b[0][0] += (s) * a[0][0]; \
+ b[0][1] += (s) * a[0][1]; \
+ b[0][2] += (s) * a[0][2]; \
+ b[0][3] += (s) * a[0][3]; \
+ \
+ b[1][0] += (s) * a[1][0]; \
+ b[1][1] += (s) * a[1][1]; \
+ b[1][2] += (s) * a[1][2]; \
+ b[1][3] += (s) * a[1][3]; \
+ \
+ b[2][0] += (s) * a[2][0]; \
+ b[2][1] += (s) * a[2][1]; \
+ b[2][2] += (s) * a[2][2]; \
+ b[2][3] += (s) * a[2][3]; \
+ \
+ b[3][0] += (s) * a[3][0]; \
+ b[3][1] += (s) * a[3][1]; \
+ b[3][2] += (s) * a[3][2]; \
+ b[3][3] += (s) * a[3][3]; \
+}\
+
+/*! matrix product */
+/*! c[x][y] = a[x][0]*b[0][y]+a[x][1]*b[1][y]+a[x][2]*b[2][y]+a[x][3]*b[3][y];*/
+#define MATRIX_PRODUCT_2X2(c,a,b) \
+{ \
+ c[0][0] = a[0][0]*b[0][0]+a[0][1]*b[1][0]; \
+ c[0][1] = a[0][0]*b[0][1]+a[0][1]*b[1][1]; \
+ \
+ c[1][0] = a[1][0]*b[0][0]+a[1][1]*b[1][0]; \
+ c[1][1] = a[1][0]*b[0][1]+a[1][1]*b[1][1]; \
+ \
+}\
+
+/*! matrix product */
+/*! c[x][y] = a[x][0]*b[0][y]+a[x][1]*b[1][y]+a[x][2]*b[2][y]+a[x][3]*b[3][y];*/
+#define MATRIX_PRODUCT_3X3(c,a,b) \
+{ \
+ c[0][0] = a[0][0]*b[0][0]+a[0][1]*b[1][0]+a[0][2]*b[2][0]; \
+ c[0][1] = a[0][0]*b[0][1]+a[0][1]*b[1][1]+a[0][2]*b[2][1]; \
+ c[0][2] = a[0][0]*b[0][2]+a[0][1]*b[1][2]+a[0][2]*b[2][2]; \
+ \
+ c[1][0] = a[1][0]*b[0][0]+a[1][1]*b[1][0]+a[1][2]*b[2][0]; \
+ c[1][1] = a[1][0]*b[0][1]+a[1][1]*b[1][1]+a[1][2]*b[2][1]; \
+ c[1][2] = a[1][0]*b[0][2]+a[1][1]*b[1][2]+a[1][2]*b[2][2]; \
+ \
+ c[2][0] = a[2][0]*b[0][0]+a[2][1]*b[1][0]+a[2][2]*b[2][0]; \
+ c[2][1] = a[2][0]*b[0][1]+a[2][1]*b[1][1]+a[2][2]*b[2][1]; \
+ c[2][2] = a[2][0]*b[0][2]+a[2][1]*b[1][2]+a[2][2]*b[2][2]; \
+}\
+
+
+/*! matrix product */
+/*! c[x][y] = a[x][0]*b[0][y]+a[x][1]*b[1][y]+a[x][2]*b[2][y]+a[x][3]*b[3][y];*/
+#define MATRIX_PRODUCT_4X4(c,a,b) \
+{ \
+ c[0][0] = a[0][0]*b[0][0]+a[0][1]*b[1][0]+a[0][2]*b[2][0]+a[0][3]*b[3][0];\
+ c[0][1] = a[0][0]*b[0][1]+a[0][1]*b[1][1]+a[0][2]*b[2][1]+a[0][3]*b[3][1];\
+ c[0][2] = a[0][0]*b[0][2]+a[0][1]*b[1][2]+a[0][2]*b[2][2]+a[0][3]*b[3][2];\
+ c[0][3] = a[0][0]*b[0][3]+a[0][1]*b[1][3]+a[0][2]*b[2][3]+a[0][3]*b[3][3];\
+ \
+ c[1][0] = a[1][0]*b[0][0]+a[1][1]*b[1][0]+a[1][2]*b[2][0]+a[1][3]*b[3][0];\
+ c[1][1] = a[1][0]*b[0][1]+a[1][1]*b[1][1]+a[1][2]*b[2][1]+a[1][3]*b[3][1];\
+ c[1][2] = a[1][0]*b[0][2]+a[1][1]*b[1][2]+a[1][2]*b[2][2]+a[1][3]*b[3][2];\
+ c[1][3] = a[1][0]*b[0][3]+a[1][1]*b[1][3]+a[1][2]*b[2][3]+a[1][3]*b[3][3];\
+ \
+ c[2][0] = a[2][0]*b[0][0]+a[2][1]*b[1][0]+a[2][2]*b[2][0]+a[2][3]*b[3][0];\
+ c[2][1] = a[2][0]*b[0][1]+a[2][1]*b[1][1]+a[2][2]*b[2][1]+a[2][3]*b[3][1];\
+ c[2][2] = a[2][0]*b[0][2]+a[2][1]*b[1][2]+a[2][2]*b[2][2]+a[2][3]*b[3][2];\
+ c[2][3] = a[2][0]*b[0][3]+a[2][1]*b[1][3]+a[2][2]*b[2][3]+a[2][3]*b[3][3];\
+ \
+ c[3][0] = a[3][0]*b[0][0]+a[3][1]*b[1][0]+a[3][2]*b[2][0]+a[3][3]*b[3][0];\
+ c[3][1] = a[3][0]*b[0][1]+a[3][1]*b[1][1]+a[3][2]*b[2][1]+a[3][3]*b[3][1];\
+ c[3][2] = a[3][0]*b[0][2]+a[3][1]*b[1][2]+a[3][2]*b[2][2]+a[3][3]*b[3][2];\
+ c[3][3] = a[3][0]*b[0][3]+a[3][1]*b[1][3]+a[3][2]*b[2][3]+a[3][3]*b[3][3];\
+}\
+
+
+/*! matrix times vector */
+#define MAT_DOT_VEC_2X2(p,m,v) \
+{ \
+ p[0] = m[0][0]*v[0] + m[0][1]*v[1]; \
+ p[1] = m[1][0]*v[0] + m[1][1]*v[1]; \
+}\
+
+
+/*! matrix times vector */
+#define MAT_DOT_VEC_3X3(p,m,v) \
+{ \
+ p[0] = m[0][0]*v[0] + m[0][1]*v[1] + m[0][2]*v[2]; \
+ p[1] = m[1][0]*v[0] + m[1][1]*v[1] + m[1][2]*v[2]; \
+ p[2] = m[2][0]*v[0] + m[2][1]*v[1] + m[2][2]*v[2]; \
+}\
+
+
+/*! matrix times vector
+v is a vec4f
+*/
+#define MAT_DOT_VEC_4X4(p,m,v) \
+{ \
+ p[0] = m[0][0]*v[0] + m[0][1]*v[1] + m[0][2]*v[2] + m[0][3]*v[3]; \
+ p[1] = m[1][0]*v[0] + m[1][1]*v[1] + m[1][2]*v[2] + m[1][3]*v[3]; \
+ p[2] = m[2][0]*v[0] + m[2][1]*v[1] + m[2][2]*v[2] + m[2][3]*v[3]; \
+ p[3] = m[3][0]*v[0] + m[3][1]*v[1] + m[3][2]*v[2] + m[3][3]*v[3]; \
+}\
+
+/*! matrix times vector
+v is a vec3f
+and m is a mat4f<br>
+Last column is added as the position
+*/
+#define MAT_DOT_VEC_3X4(p,m,v) \
+{ \
+ p[0] = m[0][0]*v[0] + m[0][1]*v[1] + m[0][2]*v[2] + m[0][3]; \
+ p[1] = m[1][0]*v[0] + m[1][1]*v[1] + m[1][2]*v[2] + m[1][3]; \
+ p[2] = m[2][0]*v[0] + m[2][1]*v[1] + m[2][2]*v[2] + m[2][3]; \
+}\
+
+
+/*! vector transpose times matrix */
+/*! p[j] = v[0]*m[0][j] + v[1]*m[1][j] + v[2]*m[2][j]; */
+#define VEC_DOT_MAT_3X3(p,v,m) \
+{ \
+ p[0] = v[0]*m[0][0] + v[1]*m[1][0] + v[2]*m[2][0]; \
+ p[1] = v[0]*m[0][1] + v[1]*m[1][1] + v[2]*m[2][1]; \
+ p[2] = v[0]*m[0][2] + v[1]*m[1][2] + v[2]*m[2][2]; \
+}\
+
+
+/*! affine matrix times vector */
+/** The matrix is assumed to be an affine matrix, with last two
+ * entries representing a translation */
+#define MAT_DOT_VEC_2X3(p,m,v) \
+{ \
+ p[0] = m[0][0]*v[0] + m[0][1]*v[1] + m[0][2]; \
+ p[1] = m[1][0]*v[0] + m[1][1]*v[1] + m[1][2]; \
+}\
+
+//! Transform a plane
+#define MAT_TRANSFORM_PLANE_4X4(pout,m,plane)\
+{ \
+ pout[0] = m[0][0]*plane[0] + m[0][1]*plane[1] + m[0][2]*plane[2];\
+ pout[1] = m[1][0]*plane[0] + m[1][1]*plane[1] + m[1][2]*plane[2];\
+ pout[2] = m[2][0]*plane[0] + m[2][1]*plane[1] + m[2][2]*plane[2];\
+ pout[3] = m[0][3]*pout[0] + m[1][3]*pout[1] + m[2][3]*pout[2] + plane[3];\
+}\
+
+
+
+/** inverse transpose of matrix times vector
+ *
+ * This macro computes inverse transpose of matrix m,
+ * and multiplies vector v into it, to yeild vector p
+ *
+ * DANGER !!! Do Not use this on normal vectors!!!
+ * It will leave normals the wrong length !!!
+ * See macro below for use on normals.
+ */
+#define INV_TRANSP_MAT_DOT_VEC_2X2(p,m,v) \
+{ \
+ GREAL det; \
+ \
+ det = m[0][0]*m[1][1] - m[0][1]*m[1][0]; \
+ p[0] = m[1][1]*v[0] - m[1][0]*v[1]; \
+ p[1] = - m[0][1]*v[0] + m[0][0]*v[1]; \
+ \
+ /* if matrix not singular, and not orthonormal, then renormalize */ \
+ if ((det!=1.0f) && (det != 0.0f)) { \
+ det = 1.0f / det; \
+ p[0] *= det; \
+ p[1] *= det; \
+ } \
+}\
+
+
+/** transform normal vector by inverse transpose of matrix
+ * and then renormalize the vector
+ *
+ * This macro computes inverse transpose of matrix m,
+ * and multiplies vector v into it, to yeild vector p
+ * Vector p is then normalized.
+ */
+#define NORM_XFORM_2X2(p,m,v) \
+{ \
+ GREAL len; \
+ \
+ /* do nothing if off-diagonals are zero and diagonals are \
+ * equal */ \
+ if ((m[0][1] != 0.0) || (m[1][0] != 0.0) || (m[0][0] != m[1][1])) { \
+ p[0] = m[1][1]*v[0] - m[1][0]*v[1]; \
+ p[1] = - m[0][1]*v[0] + m[0][0]*v[1]; \
+ \
+ len = p[0]*p[0] + p[1]*p[1]; \
+ GIM_INV_SQRT(len,len); \
+ p[0] *= len; \
+ p[1] *= len; \
+ } else { \
+ VEC_COPY_2 (p, v); \
+ } \
+}\
+
+
+/** outer product of vector times vector transpose
+ *
+ * The outer product of vector v and vector transpose t yeilds
+ * dyadic matrix m.
+ */
+#define OUTER_PRODUCT_2X2(m,v,t) \
+{ \
+ m[0][0] = v[0] * t[0]; \
+ m[0][1] = v[0] * t[1]; \
+ \
+ m[1][0] = v[1] * t[0]; \
+ m[1][1] = v[1] * t[1]; \
+}\
+
+
+/** outer product of vector times vector transpose
+ *
+ * The outer product of vector v and vector transpose t yeilds
+ * dyadic matrix m.
+ */
+#define OUTER_PRODUCT_3X3(m,v,t) \
+{ \
+ m[0][0] = v[0] * t[0]; \
+ m[0][1] = v[0] * t[1]; \
+ m[0][2] = v[0] * t[2]; \
+ \
+ m[1][0] = v[1] * t[0]; \
+ m[1][1] = v[1] * t[1]; \
+ m[1][2] = v[1] * t[2]; \
+ \
+ m[2][0] = v[2] * t[0]; \
+ m[2][1] = v[2] * t[1]; \
+ m[2][2] = v[2] * t[2]; \
+}\
+
+
+/** outer product of vector times vector transpose
+ *
+ * The outer product of vector v and vector transpose t yeilds
+ * dyadic matrix m.
+ */
+#define OUTER_PRODUCT_4X4(m,v,t) \
+{ \
+ m[0][0] = v[0] * t[0]; \
+ m[0][1] = v[0] * t[1]; \
+ m[0][2] = v[0] * t[2]; \
+ m[0][3] = v[0] * t[3]; \
+ \
+ m[1][0] = v[1] * t[0]; \
+ m[1][1] = v[1] * t[1]; \
+ m[1][2] = v[1] * t[2]; \
+ m[1][3] = v[1] * t[3]; \
+ \
+ m[2][0] = v[2] * t[0]; \
+ m[2][1] = v[2] * t[1]; \
+ m[2][2] = v[2] * t[2]; \
+ m[2][3] = v[2] * t[3]; \
+ \
+ m[3][0] = v[3] * t[0]; \
+ m[3][1] = v[3] * t[1]; \
+ m[3][2] = v[3] * t[2]; \
+ m[3][3] = v[3] * t[3]; \
+}\
+
+
+/** outer product of vector times vector transpose
+ *
+ * The outer product of vector v and vector transpose t yeilds
+ * dyadic matrix m.
+ */
+#define ACCUM_OUTER_PRODUCT_2X2(m,v,t) \
+{ \
+ m[0][0] += v[0] * t[0]; \
+ m[0][1] += v[0] * t[1]; \
+ \
+ m[1][0] += v[1] * t[0]; \
+ m[1][1] += v[1] * t[1]; \
+}\
+
+
+/** outer product of vector times vector transpose
+ *
+ * The outer product of vector v and vector transpose t yeilds
+ * dyadic matrix m.
+ */
+#define ACCUM_OUTER_PRODUCT_3X3(m,v,t) \
+{ \
+ m[0][0] += v[0] * t[0]; \
+ m[0][1] += v[0] * t[1]; \
+ m[0][2] += v[0] * t[2]; \
+ \
+ m[1][0] += v[1] * t[0]; \
+ m[1][1] += v[1] * t[1]; \
+ m[1][2] += v[1] * t[2]; \
+ \
+ m[2][0] += v[2] * t[0]; \
+ m[2][1] += v[2] * t[1]; \
+ m[2][2] += v[2] * t[2]; \
+}\
+
+
+/** outer product of vector times vector transpose
+ *
+ * The outer product of vector v and vector transpose t yeilds
+ * dyadic matrix m.
+ */
+#define ACCUM_OUTER_PRODUCT_4X4(m,v,t) \
+{ \
+ m[0][0] += v[0] * t[0]; \
+ m[0][1] += v[0] * t[1]; \
+ m[0][2] += v[0] * t[2]; \
+ m[0][3] += v[0] * t[3]; \
+ \
+ m[1][0] += v[1] * t[0]; \
+ m[1][1] += v[1] * t[1]; \
+ m[1][2] += v[1] * t[2]; \
+ m[1][3] += v[1] * t[3]; \
+ \
+ m[2][0] += v[2] * t[0]; \
+ m[2][1] += v[2] * t[1]; \
+ m[2][2] += v[2] * t[2]; \
+ m[2][3] += v[2] * t[3]; \
+ \
+ m[3][0] += v[3] * t[0]; \
+ m[3][1] += v[3] * t[1]; \
+ m[3][2] += v[3] * t[2]; \
+ m[3][3] += v[3] * t[3]; \
+}\
+
+
+/** determinant of matrix
+ *
+ * Computes determinant of matrix m, returning d
+ */
+#define DETERMINANT_2X2(d,m) \
+{ \
+ d = m[0][0] * m[1][1] - m[0][1] * m[1][0]; \
+}\
+
+
+/** determinant of matrix
+ *
+ * Computes determinant of matrix m, returning d
+ */
+#define DETERMINANT_3X3(d,m) \
+{ \
+ d = m[0][0] * (m[1][1]*m[2][2] - m[1][2] * m[2][1]); \
+ d -= m[0][1] * (m[1][0]*m[2][2] - m[1][2] * m[2][0]); \
+ d += m[0][2] * (m[1][0]*m[2][1] - m[1][1] * m[2][0]); \
+}\
+
+
+/** i,j,th cofactor of a 4x4 matrix
+ *
+ */
+#define COFACTOR_4X4_IJ(fac,m,i,j) \
+{ \
+ GUINT __ii[4], __jj[4], __k; \
+ \
+ for (__k=0; __k<i; __k++) __ii[__k] = __k; \
+ for (__k=i; __k<3; __k++) __ii[__k] = __k+1; \
+ for (__k=0; __k<j; __k++) __jj[__k] = __k; \
+ for (__k=j; __k<3; __k++) __jj[__k] = __k+1; \
+ \
+ (fac) = m[__ii[0]][__jj[0]] * (m[__ii[1]][__jj[1]]*m[__ii[2]][__jj[2]] \
+ - m[__ii[1]][__jj[2]]*m[__ii[2]][__jj[1]]); \
+ (fac) -= m[__ii[0]][__jj[1]] * (m[__ii[1]][__jj[0]]*m[__ii[2]][__jj[2]] \
+ - m[__ii[1]][__jj[2]]*m[__ii[2]][__jj[0]]);\
+ (fac) += m[__ii[0]][__jj[2]] * (m[__ii[1]][__jj[0]]*m[__ii[2]][__jj[1]] \
+ - m[__ii[1]][__jj[1]]*m[__ii[2]][__jj[0]]);\
+ \
+ __k = i+j; \
+ if ( __k != (__k/2)*2) { \
+ (fac) = -(fac); \
+ } \
+}\
+
+
+/** determinant of matrix
+ *
+ * Computes determinant of matrix m, returning d
+ */
+#define DETERMINANT_4X4(d,m) \
+{ \
+ GREAL cofac; \
+ COFACTOR_4X4_IJ (cofac, m, 0, 0); \
+ d = m[0][0] * cofac; \
+ COFACTOR_4X4_IJ (cofac, m, 0, 1); \
+ d += m[0][1] * cofac; \
+ COFACTOR_4X4_IJ (cofac, m, 0, 2); \
+ d += m[0][2] * cofac; \
+ COFACTOR_4X4_IJ (cofac, m, 0, 3); \
+ d += m[0][3] * cofac; \
+}\
+
+
+/** cofactor of matrix
+ *
+ * Computes cofactor of matrix m, returning a
+ */
+#define COFACTOR_2X2(a,m) \
+{ \
+ a[0][0] = (m)[1][1]; \
+ a[0][1] = - (m)[1][0]; \
+ a[1][0] = - (m)[0][1]; \
+ a[1][1] = (m)[0][0]; \
+}\
+
+
+/** cofactor of matrix
+ *
+ * Computes cofactor of matrix m, returning a
+ */
+#define COFACTOR_3X3(a,m) \
+{ \
+ a[0][0] = m[1][1]*m[2][2] - m[1][2]*m[2][1]; \
+ a[0][1] = - (m[1][0]*m[2][2] - m[2][0]*m[1][2]); \
+ a[0][2] = m[1][0]*m[2][1] - m[1][1]*m[2][0]; \
+ a[1][0] = - (m[0][1]*m[2][2] - m[0][2]*m[2][1]); \
+ a[1][1] = m[0][0]*m[2][2] - m[0][2]*m[2][0]; \
+ a[1][2] = - (m[0][0]*m[2][1] - m[0][1]*m[2][0]); \
+ a[2][0] = m[0][1]*m[1][2] - m[0][2]*m[1][1]; \
+ a[2][1] = - (m[0][0]*m[1][2] - m[0][2]*m[1][0]); \
+ a[2][2] = m[0][0]*m[1][1] - m[0][1]*m[1][0]); \
+}\
+
+
+/** cofactor of matrix
+ *
+ * Computes cofactor of matrix m, returning a
+ */
+#define COFACTOR_4X4(a,m) \
+{ \
+ int i,j; \
+ \
+ for (i=0; i<4; i++) { \
+ for (j=0; j<4; j++) { \
+ COFACTOR_4X4_IJ (a[i][j], m, i, j); \
+ } \
+ } \
+}\
+
+
+/** adjoint of matrix
+ *
+ * Computes adjoint of matrix m, returning a
+ * (Note that adjoint is just the transpose of the cofactor matrix)
+ */
+#define ADJOINT_2X2(a,m) \
+{ \
+ a[0][0] = (m)[1][1]; \
+ a[1][0] = - (m)[1][0]; \
+ a[0][1] = - (m)[0][1]; \
+ a[1][1] = (m)[0][0]; \
+}\
+
+
+/** adjoint of matrix
+ *
+ * Computes adjoint of matrix m, returning a
+ * (Note that adjoint is just the transpose of the cofactor matrix)
+ */
+#define ADJOINT_3X3(a,m) \
+{ \
+ a[0][0] = m[1][1]*m[2][2] - m[1][2]*m[2][1]; \
+ a[1][0] = - (m[1][0]*m[2][2] - m[2][0]*m[1][2]); \
+ a[2][0] = m[1][0]*m[2][1] - m[1][1]*m[2][0]; \
+ a[0][1] = - (m[0][1]*m[2][2] - m[0][2]*m[2][1]); \
+ a[1][1] = m[0][0]*m[2][2] - m[0][2]*m[2][0]; \
+ a[2][1] = - (m[0][0]*m[2][1] - m[0][1]*m[2][0]); \
+ a[0][2] = m[0][1]*m[1][2] - m[0][2]*m[1][1]; \
+ a[1][2] = - (m[0][0]*m[1][2] - m[0][2]*m[1][0]); \
+ a[2][2] = m[0][0]*m[1][1] - m[0][1]*m[1][0]); \
+}\
+
+
+/** adjoint of matrix
+ *
+ * Computes adjoint of matrix m, returning a
+ * (Note that adjoint is just the transpose of the cofactor matrix)
+ */
+#define ADJOINT_4X4(a,m) \
+{ \
+ char _i_,_j_; \
+ \
+ for (_i_=0; _i_<4; _i_++) { \
+ for (_j_=0; _j_<4; _j_++) { \
+ COFACTOR_4X4_IJ (a[_j_][_i_], m, _i_, _j_); \
+ } \
+ } \
+}\
+
+
+/** compute adjoint of matrix and scale
+ *
+ * Computes adjoint of matrix m, scales it by s, returning a
+ */
+#define SCALE_ADJOINT_2X2(a,s,m) \
+{ \
+ a[0][0] = (s) * m[1][1]; \
+ a[1][0] = - (s) * m[1][0]; \
+ a[0][1] = - (s) * m[0][1]; \
+ a[1][1] = (s) * m[0][0]; \
+}\
+
+
+/** compute adjoint of matrix and scale
+ *
+ * Computes adjoint of matrix m, scales it by s, returning a
+ */
+#define SCALE_ADJOINT_3X3(a,s,m) \
+{ \
+ a[0][0] = (s) * (m[1][1] * m[2][2] - m[1][2] * m[2][1]); \
+ a[1][0] = (s) * (m[1][2] * m[2][0] - m[1][0] * m[2][2]); \
+ a[2][0] = (s) * (m[1][0] * m[2][1] - m[1][1] * m[2][0]); \
+ \
+ a[0][1] = (s) * (m[0][2] * m[2][1] - m[0][1] * m[2][2]); \
+ a[1][1] = (s) * (m[0][0] * m[2][2] - m[0][2] * m[2][0]); \
+ a[2][1] = (s) * (m[0][1] * m[2][0] - m[0][0] * m[2][1]); \
+ \
+ a[0][2] = (s) * (m[0][1] * m[1][2] - m[0][2] * m[1][1]); \
+ a[1][2] = (s) * (m[0][2] * m[1][0] - m[0][0] * m[1][2]); \
+ a[2][2] = (s) * (m[0][0] * m[1][1] - m[0][1] * m[1][0]); \
+}\
+
+
+/** compute adjoint of matrix and scale
+ *
+ * Computes adjoint of matrix m, scales it by s, returning a
+ */
+#define SCALE_ADJOINT_4X4(a,s,m) \
+{ \
+ char _i_,_j_; \
+ for (_i_=0; _i_<4; _i_++) { \
+ for (_j_=0; _j_<4; _j_++) { \
+ COFACTOR_4X4_IJ (a[_j_][_i_], m, _i_, _j_); \
+ a[_j_][_i_] *= s; \
+ } \
+ } \
+}\
+
+/** inverse of matrix
+ *
+ * Compute inverse of matrix a, returning determinant m and
+ * inverse b
+ */
+#define INVERT_2X2(b,det,a) \
+{ \
+ GREAL _tmp_; \
+ DETERMINANT_2X2 (det, a); \
+ _tmp_ = 1.0 / (det); \
+ SCALE_ADJOINT_2X2 (b, _tmp_, a); \
+}\
+
+
+/** inverse of matrix
+ *
+ * Compute inverse of matrix a, returning determinant m and
+ * inverse b
+ */
+#define INVERT_3X3(b,det,a) \
+{ \
+ GREAL _tmp_; \
+ DETERMINANT_3X3 (det, a); \
+ _tmp_ = 1.0 / (det); \
+ SCALE_ADJOINT_3X3 (b, _tmp_, a); \
+}\
+
+
+/** inverse of matrix
+ *
+ * Compute inverse of matrix a, returning determinant m and
+ * inverse b
+ */
+#define INVERT_4X4(b,det,a) \
+{ \
+ GREAL _tmp_; \
+ DETERMINANT_4X4 (det, a); \
+ _tmp_ = 1.0 / (det); \
+ SCALE_ADJOINT_4X4 (b, _tmp_, a); \
+}\
+
+//! Get the triple(3) row of a transform matrix
+#define MAT_GET_ROW(mat,vec3,rowindex)\
+{\
+ vec3[0] = mat[rowindex][0];\
+ vec3[1] = mat[rowindex][1];\
+ vec3[2] = mat[rowindex][2]; \
+}\
+
+//! Get the tuple(2) row of a transform matrix
+#define MAT_GET_ROW2(mat,vec2,rowindex)\
+{\
+ vec2[0] = mat[rowindex][0];\
+ vec2[1] = mat[rowindex][1];\
+}\
+
+
+//! Get the quad (4) row of a transform matrix
+#define MAT_GET_ROW4(mat,vec4,rowindex)\
+{\
+ vec4[0] = mat[rowindex][0];\
+ vec4[1] = mat[rowindex][1];\
+ vec4[2] = mat[rowindex][2];\
+ vec4[3] = mat[rowindex][3];\
+}\
+
+//! Get the triple(3) col of a transform matrix
+#define MAT_GET_COL(mat,vec3,colindex)\
+{\
+ vec3[0] = mat[0][colindex];\
+ vec3[1] = mat[1][colindex];\
+ vec3[2] = mat[2][colindex]; \
+}\
+
+//! Get the tuple(2) col of a transform matrix
+#define MAT_GET_COL2(mat,vec2,colindex)\
+{\
+ vec2[0] = mat[0][colindex];\
+ vec2[1] = mat[1][colindex];\
+}\
+
+
+//! Get the quad (4) col of a transform matrix
+#define MAT_GET_COL4(mat,vec4,colindex)\
+{\
+ vec4[0] = mat[0][colindex];\
+ vec4[1] = mat[1][colindex];\
+ vec4[2] = mat[2][colindex];\
+ vec4[3] = mat[3][colindex];\
+}\
+
+//! Get the triple(3) col of a transform matrix
+#define MAT_GET_X(mat,vec3)\
+{\
+ MAT_GET_COL(mat,vec3,0);\
+}\
+
+//! Get the triple(3) col of a transform matrix
+#define MAT_GET_Y(mat,vec3)\
+{\
+ MAT_GET_COL(mat,vec3,1);\
+}\
+
+//! Get the triple(3) col of a transform matrix
+#define MAT_GET_Z(mat,vec3)\
+{\
+ MAT_GET_COL(mat,vec3,2);\
+}\
+
+
+//! Get the triple(3) col of a transform matrix
+#define MAT_SET_X(mat,vec3)\
+{\
+ mat[0][0] = vec3[0];\
+ mat[1][0] = vec3[1];\
+ mat[2][0] = vec3[2];\
+}\
+
+//! Get the triple(3) col of a transform matrix
+#define MAT_SET_Y(mat,vec3)\
+{\
+ mat[0][1] = vec3[0];\
+ mat[1][1] = vec3[1];\
+ mat[2][1] = vec3[2];\
+}\
+
+//! Get the triple(3) col of a transform matrix
+#define MAT_SET_Z(mat,vec3)\
+{\
+ mat[0][2] = vec3[0];\
+ mat[1][2] = vec3[1];\
+ mat[2][2] = vec3[2];\
+}\
+
+
+//! Get the triple(3) col of a transform matrix
+#define MAT_GET_TRANSLATION(mat,vec3)\
+{\
+ vec3[0] = mat[0][3];\
+ vec3[1] = mat[1][3];\
+ vec3[2] = mat[2][3]; \
+}\
+
+//! Set the triple(3) col of a transform matrix
+#define MAT_SET_TRANSLATION(mat,vec3)\
+{\
+ mat[0][3] = vec3[0];\
+ mat[1][3] = vec3[1];\
+ mat[2][3] = vec3[2]; \
+}\
+
+
+
+//! Returns the dot product between a vec3f and the row of a matrix
+#define MAT_DOT_ROW(mat,vec3,rowindex) (vec3[0]*mat[rowindex][0] + vec3[1]*mat[rowindex][1] + vec3[2]*mat[rowindex][2])
+
+//! Returns the dot product between a vec2f and the row of a matrix
+#define MAT_DOT_ROW2(mat,vec2,rowindex) (vec2[0]*mat[rowindex][0] + vec2[1]*mat[rowindex][1])
+
+//! Returns the dot product between a vec4f and the row of a matrix
+#define MAT_DOT_ROW4(mat,vec4,rowindex) (vec4[0]*mat[rowindex][0] + vec4[1]*mat[rowindex][1] + vec4[2]*mat[rowindex][2] + vec4[3]*mat[rowindex][3])
+
+
+//! Returns the dot product between a vec3f and the col of a matrix
+#define MAT_DOT_COL(mat,vec3,colindex) (vec3[0]*mat[0][colindex] + vec3[1]*mat[1][colindex] + vec3[2]*mat[2][colindex])
+
+//! Returns the dot product between a vec2f and the col of a matrix
+#define MAT_DOT_COL2(mat,vec2,colindex) (vec2[0]*mat[0][colindex] + vec2[1]*mat[1][colindex])
+
+//! Returns the dot product between a vec4f and the col of a matrix
+#define MAT_DOT_COL4(mat,vec4,colindex) (vec4[0]*mat[0][colindex] + vec4[1]*mat[1][colindex] + vec4[2]*mat[2][colindex] + vec4[3]*mat[3][colindex])
+
+/*!Transpose matrix times vector
+v is a vec3f
+and m is a mat4f<br>
+*/
+#define INV_MAT_DOT_VEC_3X3(p,m,v) \
+{ \
+ p[0] = MAT_DOT_COL(m,v,0); \
+ p[1] = MAT_DOT_COL(m,v,1); \
+ p[2] = MAT_DOT_COL(m,v,2); \
+}\
+
+
+
+#endif // GIM_VECTOR_H_INCLUDED
diff --git a/thirdparty/bullet/src/BulletCollision/Gimpact/gim_math.h b/thirdparty/bullet/src/BulletCollision/Gimpact/gim_math.h
new file mode 100644
index 0000000000..939079e104
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/Gimpact/gim_math.h
@@ -0,0 +1,157 @@
+#ifndef GIM_MATH_H_INCLUDED
+#define GIM_MATH_H_INCLUDED
+/*! \file gim_math.h
+\author Francisco Leon Najera
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+ (1) The GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 2.1 of the License, or (at
+ your option) any later version. The text of the GNU Lesser
+ General Public License is included with this library in the
+ file GIMPACT-LICENSE-LGPL.TXT.
+ (2) The BSD-style license that is included with this library in
+ the file GIMPACT-LICENSE-BSD.TXT.
+ (3) The zlib/libpng license that is included with this library in
+ the file GIMPACT-LICENSE-ZLIB.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+#include "LinearMath/btScalar.h"
+
+
+
+#define GREAL btScalar
+#define GREAL2 double
+#define GINT int
+#define GUINT unsigned int
+#define GSHORT short
+#define GUSHORT unsigned short
+#define GINT64 long long
+#define GUINT64 unsigned long long
+
+
+
+#define G_PI 3.14159265358979f
+#define G_HALF_PI 1.5707963f
+//267948966
+#define G_TWO_PI 6.28318530f
+//71795864
+#define G_ROOT3 1.73205f
+#define G_ROOT2 1.41421f
+#define G_UINT_INFINITY 0xffffffff //!< A very very high value
+#define G_REAL_INFINITY FLT_MAX
+#define G_SIGN_BITMASK 0x80000000
+#define G_EPSILON SIMD_EPSILON
+
+
+
+enum GIM_SCALAR_TYPES
+{
+ G_STYPE_REAL =0,
+ G_STYPE_REAL2,
+ G_STYPE_SHORT,
+ G_STYPE_USHORT,
+ G_STYPE_INT,
+ G_STYPE_UINT,
+ G_STYPE_INT64,
+ G_STYPE_UINT64
+};
+
+
+
+#define G_DEGTORAD(X) ((X)*3.1415926f/180.0f)
+#define G_RADTODEG(X) ((X)*180.0f/3.1415926f)
+
+//! Integer representation of a floating-point value.
+#define GIM_IR(x) ((GUINT&)(x))
+
+//! Signed integer representation of a floating-point value.
+#define GIM_SIR(x) ((GINT&)(x))
+
+//! Absolute integer representation of a floating-point value
+#define GIM_AIR(x) (GIM_IR(x)&0x7fffffff)
+
+//! Floating-point representation of an integer value.
+#define GIM_FR(x) ((GREAL&)(x))
+
+#define GIM_MAX(a,b) (a<b?b:a)
+#define GIM_MIN(a,b) (a>b?b:a)
+
+#define GIM_MAX3(a,b,c) GIM_MAX(a,GIM_MAX(b,c))
+#define GIM_MIN3(a,b,c) GIM_MIN(a,GIM_MIN(b,c))
+
+#define GIM_IS_ZERO(value) (value < G_EPSILON && value > -G_EPSILON)
+
+#define GIM_IS_NEGATIVE(value) (value <= -G_EPSILON)
+
+#define GIM_IS_POSISITVE(value) (value >= G_EPSILON)
+
+#define GIM_NEAR_EQUAL(v1,v2) GIM_IS_ZERO((v1-v2))
+
+///returns a clamped number
+#define GIM_CLAMP(number,minval,maxval) (number<minval?minval:(number>maxval?maxval:number))
+
+#define GIM_GREATER(x, y) btFabs(x) > (y)
+
+///Swap numbers
+#define GIM_SWAP_NUMBERS(a,b){ \
+ a = a+b; \
+ b = a-b; \
+ a = a-b; \
+}\
+
+#define GIM_INV_SQRT(va,isva)\
+{\
+ if(va<=0.0000001f)\
+ {\
+ isva = G_REAL_INFINITY;\
+ }\
+ else\
+ {\
+ GREAL _x = va * 0.5f;\
+ GUINT _y = 0x5f3759df - ( GIM_IR(va) >> 1);\
+ isva = GIM_FR(_y);\
+ isva = isva * ( 1.5f - ( _x * isva * isva ) );\
+ }\
+}\
+
+#define GIM_SQRT(va,sva)\
+{\
+ GIM_INV_SQRT(va,sva);\
+ sva = 1.0f/sva;\
+}\
+
+//! Computes 1.0f / sqrtf(x). Comes from Quake3. See http://www.magic-software.com/3DGEDInvSqrt.html
+inline GREAL gim_inv_sqrt(GREAL f)
+{
+ GREAL r;
+ GIM_INV_SQRT(f,r);
+ return r;
+}
+
+inline GREAL gim_sqrt(GREAL f)
+{
+ GREAL r;
+ GIM_SQRT(f,r);
+ return r;
+}
+
+
+
+#endif // GIM_MATH_H_INCLUDED
diff --git a/thirdparty/bullet/src/BulletCollision/Gimpact/gim_memory.cpp b/thirdparty/bullet/src/BulletCollision/Gimpact/gim_memory.cpp
new file mode 100644
index 0000000000..1636eb7867
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/Gimpact/gim_memory.cpp
@@ -0,0 +1,135 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+ (1) The GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 2.1 of the License, or (at
+ your option) any later version. The text of the GNU Lesser
+ General Public License is included with this library in the
+ file GIMPACT-LICENSE-LGPL.TXT.
+ (2) The BSD-style license that is included with this library in
+ the file GIMPACT-LICENSE-BSD.TXT.
+ (3) The zlib/libpng license that is included with this library in
+ the file GIMPACT-LICENSE-ZLIB.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+
+#include "gim_memory.h"
+#include "stdlib.h"
+
+#ifdef GIM_SIMD_MEMORY
+#include "LinearMath/btAlignedAllocator.h"
+#endif
+
+static gim_alloc_function *g_allocfn = 0;
+static gim_alloca_function *g_allocafn = 0;
+static gim_realloc_function *g_reallocfn = 0;
+static gim_free_function *g_freefn = 0;
+
+void gim_set_alloc_handler (gim_alloc_function *fn)
+{
+ g_allocfn = fn;
+}
+
+void gim_set_alloca_handler (gim_alloca_function *fn)
+{
+ g_allocafn = fn;
+}
+
+void gim_set_realloc_handler (gim_realloc_function *fn)
+{
+ g_reallocfn = fn;
+}
+
+void gim_set_free_handler (gim_free_function *fn)
+{
+ g_freefn = fn;
+}
+
+gim_alloc_function *gim_get_alloc_handler()
+{
+ return g_allocfn;
+}
+
+gim_alloca_function *gim_get_alloca_handler()
+{
+ return g_allocafn;
+}
+
+
+gim_realloc_function *gim_get_realloc_handler ()
+{
+ return g_reallocfn;
+}
+
+
+gim_free_function *gim_get_free_handler ()
+{
+ return g_freefn;
+}
+
+
+void * gim_alloc(size_t size)
+{
+ void * ptr;
+ if (g_allocfn)
+ {
+ ptr = g_allocfn(size);
+ }
+ else
+ {
+#ifdef GIM_SIMD_MEMORY
+ ptr = btAlignedAlloc(size,16);
+#else
+ ptr = malloc(size);
+#endif
+ }
+ return ptr;
+}
+
+void * gim_alloca(size_t size)
+{
+ if (g_allocafn) return g_allocafn(size); else return gim_alloc(size);
+}
+
+
+void * gim_realloc(void *ptr, size_t oldsize, size_t newsize)
+{
+ void * newptr = gim_alloc(newsize);
+ size_t copysize = oldsize<newsize?oldsize:newsize;
+ gim_simd_memcpy(newptr,ptr,copysize);
+ gim_free(ptr);
+ return newptr;
+}
+
+void gim_free(void *ptr)
+{
+ if (!ptr) return;
+ if (g_freefn)
+ {
+ g_freefn(ptr);
+ }
+ else
+ {
+ #ifdef GIM_SIMD_MEMORY
+ btAlignedFree(ptr);
+ #else
+ free(ptr);
+ #endif
+ }
+}
+
diff --git a/thirdparty/bullet/src/BulletCollision/Gimpact/gim_memory.h b/thirdparty/bullet/src/BulletCollision/Gimpact/gim_memory.h
new file mode 100644
index 0000000000..e203888a1e
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/Gimpact/gim_memory.h
@@ -0,0 +1,190 @@
+#ifndef GIM_MEMORY_H_INCLUDED
+#define GIM_MEMORY_H_INCLUDED
+/*! \file gim_memory.h
+\author Francisco Leon Najera
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+ (1) The GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 2.1 of the License, or (at
+ your option) any later version. The text of the GNU Lesser
+ General Public License is included with this library in the
+ file GIMPACT-LICENSE-LGPL.TXT.
+ (2) The BSD-style license that is included with this library in
+ the file GIMPACT-LICENSE-BSD.TXT.
+ (3) The zlib/libpng license that is included with this library in
+ the file GIMPACT-LICENSE-ZLIB.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+
+#include "gim_math.h"
+#include <string.h>
+
+#ifdef PREFETCH
+#include <xmmintrin.h> // for prefetch
+#define pfval 64
+#define pfval2 128
+//! Prefetch 64
+#define pf(_x,_i) _mm_prefetch((void *)(_x + _i + pfval), 0)
+//! Prefetch 128
+#define pf2(_x,_i) _mm_prefetch((void *)(_x + _i + pfval2), 0)
+#else
+//! Prefetch 64
+#define pf(_x,_i)
+//! Prefetch 128
+#define pf2(_x,_i)
+#endif
+
+
+///Functions for manip packed arrays of numbers
+#define GIM_COPY_ARRAYS(dest_array,source_array,element_count)\
+{\
+ for (GUINT _i_=0;_i_<element_count ;++_i_)\
+ {\
+ dest_array[_i_] = source_array[_i_];\
+ }\
+}\
+
+#define GIM_COPY_ARRAYS_1(dest_array,source_array,element_count,copy_macro)\
+{\
+ for (GUINT _i_=0;_i_<element_count ;++_i_)\
+ {\
+ copy_macro(dest_array[_i_],source_array[_i_]);\
+ }\
+}\
+
+
+#define GIM_ZERO_ARRAY(array,element_count)\
+{\
+ for (GUINT _i_=0;_i_<element_count ;++_i_)\
+ {\
+ array[_i_] = 0;\
+ }\
+}\
+
+#define GIM_CONSTANT_ARRAY(array,element_count,constant)\
+{\
+ for (GUINT _i_=0;_i_<element_count ;++_i_)\
+ {\
+ array[_i_] = constant;\
+ }\
+}\
+
+
+///Function prototypes to allocate and free memory.
+typedef void * gim_alloc_function (size_t size);
+typedef void * gim_alloca_function (size_t size);//Allocs on the heap
+typedef void * gim_realloc_function (void *ptr, size_t oldsize, size_t newsize);
+typedef void gim_free_function (void *ptr);
+
+
+///Memory Function Handlers
+///set new memory management functions. if fn is 0, the default handlers are used.
+void gim_set_alloc_handler (gim_alloc_function *fn);
+void gim_set_alloca_handler (gim_alloca_function *fn);
+void gim_set_realloc_handler (gim_realloc_function *fn);
+void gim_set_free_handler (gim_free_function *fn);
+
+
+///get current memory management functions.
+gim_alloc_function *gim_get_alloc_handler (void);
+gim_alloca_function *gim_get_alloca_handler(void);
+gim_realloc_function *gim_get_realloc_handler (void);
+gim_free_function *gim_get_free_handler (void);
+
+
+///Standar Memory functions
+void * gim_alloc(size_t size);
+void * gim_alloca(size_t size);
+void * gim_realloc(void *ptr, size_t oldsize, size_t newsize);
+void gim_free(void *ptr);
+
+
+
+#if defined (_WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__)
+ #define GIM_SIMD_MEMORY 1
+#endif
+
+//! SIMD POINTER INTEGER
+#define SIMD_T GUINT64
+//! SIMD INTEGER SIZE
+#define SIMD_T_SIZE sizeof(SIMD_T)
+
+
+inline void gim_simd_memcpy(void * dst, const void * src, size_t copysize)
+{
+#ifdef GIM_SIMD_MEMORY
+/*
+//'long long int' is incompatible with visual studio 6...
+ //copy words
+ SIMD_T * ui_src_ptr = (SIMD_T *)src;
+ SIMD_T * ui_dst_ptr = (SIMD_T *)dst;
+ while(copysize>=SIMD_T_SIZE)
+ {
+ *(ui_dst_ptr++) = *(ui_src_ptr++);
+ copysize-=SIMD_T_SIZE;
+ }
+ if(copysize==0) return;
+*/
+
+ char * c_src_ptr = (char *)src;
+ char * c_dst_ptr = (char *)dst;
+ while(copysize>0)
+ {
+ *(c_dst_ptr++) = *(c_src_ptr++);
+ copysize--;
+ }
+ return;
+#else
+ memcpy(dst,src,copysize);
+#endif
+}
+
+
+
+template<class T>
+inline void gim_swap_elements(T* _array,size_t _i,size_t _j)
+{
+ T _e_tmp_ = _array[_i];
+ _array[_i] = _array[_j];
+ _array[_j] = _e_tmp_;
+}
+
+
+template<class T>
+inline void gim_swap_elements_memcpy(T* _array,size_t _i,size_t _j)
+{
+ char _e_tmp_[sizeof(T)];
+ gim_simd_memcpy(_e_tmp_,&_array[_i],sizeof(T));
+ gim_simd_memcpy(&_array[_i],&_array[_j],sizeof(T));
+ gim_simd_memcpy(&_array[_j],_e_tmp_,sizeof(T));
+}
+
+template <int SIZE>
+inline void gim_swap_elements_ptr(char * _array,size_t _i,size_t _j)
+{
+ char _e_tmp_[SIZE];
+ _i*=SIZE;
+ _j*=SIZE;
+ gim_simd_memcpy(_e_tmp_,_array+_i,SIZE);
+ gim_simd_memcpy(_array+_i,_array+_j,SIZE);
+ gim_simd_memcpy(_array+_j,_e_tmp_,SIZE);
+}
+
+#endif // GIM_MEMORY_H_INCLUDED
diff --git a/thirdparty/bullet/src/BulletCollision/Gimpact/gim_radixsort.h b/thirdparty/bullet/src/BulletCollision/Gimpact/gim_radixsort.h
new file mode 100644
index 0000000000..c246ef1254
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/Gimpact/gim_radixsort.h
@@ -0,0 +1,406 @@
+#ifndef GIM_RADIXSORT_H_INCLUDED
+#define GIM_RADIXSORT_H_INCLUDED
+/*! \file gim_radixsort.h
+\author Francisco Leon Najera.
+Based on the work of Michael Herf : "fast floating-point radix sort"
+Avaliable on http://www.stereopsis.com/radix.html
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+ (1) The GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 2.1 of the License, or (at
+ your option) any later version. The text of the GNU Lesser
+ General Public License is included with this library in the
+ file GIMPACT-LICENSE-LGPL.TXT.
+ (2) The BSD-style license that is included with this library in
+ the file GIMPACT-LICENSE-BSD.TXT.
+ (3) The zlib/libpng license that is included with this library in
+ the file GIMPACT-LICENSE-ZLIB.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+#include "gim_memory.h"
+
+///Macros for sorting.
+//! Prototype for comparators
+class less_comparator
+{
+ public:
+
+ template<class T,class Z>
+ inline int operator() ( const T& a, const Z& b )
+ {
+ return ( a<b?-1:(a>b?1:0));
+ }
+};
+
+//! Prototype for comparators
+class integer_comparator
+{
+ public:
+
+ template<class T>
+ inline int operator() ( const T& a, const T& b )
+ {
+ return (int)(a-b);
+ }
+};
+
+//!Prototype for getting the integer representation of an object
+class uint_key_func
+{
+public:
+ template<class T>
+ inline GUINT operator()( const T& a)
+ {
+ return (GUINT)a;
+ }
+};
+
+
+//!Prototype for copying elements
+class copy_elements_func
+{
+public:
+ template<class T>
+ inline void operator()(T& a,T& b)
+ {
+ a = b;
+ }
+};
+
+//!Prototype for copying elements
+class memcopy_elements_func
+{
+public:
+ template<class T>
+ inline void operator()(T& a,T& b)
+ {
+ gim_simd_memcpy(&a,&b,sizeof(T));
+ }
+};
+
+
+//! @{
+struct GIM_RSORT_TOKEN
+{
+ GUINT m_key;
+ GUINT m_value;
+ GIM_RSORT_TOKEN()
+ {
+ }
+ GIM_RSORT_TOKEN(const GIM_RSORT_TOKEN& rtoken)
+ {
+ m_key = rtoken.m_key;
+ m_value = rtoken.m_value;
+ }
+
+ inline bool operator <(const GIM_RSORT_TOKEN& other) const
+ {
+ return (m_key < other.m_key);
+ }
+
+ inline bool operator >(const GIM_RSORT_TOKEN& other) const
+ {
+ return (m_key > other.m_key);
+ }
+};
+
+//! Prototype for comparators
+class GIM_RSORT_TOKEN_COMPARATOR
+{
+ public:
+
+ inline int operator()( const GIM_RSORT_TOKEN& a, const GIM_RSORT_TOKEN& b )
+ {
+ return (int)((a.m_key) - (b.m_key));
+ }
+};
+
+
+
+#define kHist 2048
+// ---- utils for accessing 11-bit quantities
+#define D11_0(x) (x & 0x7FF)
+#define D11_1(x) (x >> 11 & 0x7FF)
+#define D11_2(x) (x >> 22 )
+
+
+
+///Radix sort for unsigned integer keys
+inline void gim_radix_sort_rtokens(
+ GIM_RSORT_TOKEN * array,
+ GIM_RSORT_TOKEN * sorted, GUINT element_count)
+{
+ GUINT i;
+ GUINT b0[kHist * 3];
+ GUINT *b1 = b0 + kHist;
+ GUINT *b2 = b1 + kHist;
+ for (i = 0; i < kHist * 3; ++i)
+ {
+ b0[i] = 0;
+ }
+ GUINT fi;
+ GUINT pos;
+ for (i = 0; i < element_count; ++i)
+ {
+ fi = array[i].m_key;
+ b0[D11_0(fi)] ++;
+ b1[D11_1(fi)] ++;
+ b2[D11_2(fi)] ++;
+ }
+ {
+ GUINT sum0 = 0, sum1 = 0, sum2 = 0;
+ GUINT tsum;
+ for (i = 0; i < kHist; ++i)
+ {
+ tsum = b0[i] + sum0;
+ b0[i] = sum0 - 1;
+ sum0 = tsum;
+ tsum = b1[i] + sum1;
+ b1[i] = sum1 - 1;
+ sum1 = tsum;
+ tsum = b2[i] + sum2;
+ b2[i] = sum2 - 1;
+ sum2 = tsum;
+ }
+ }
+ for (i = 0; i < element_count; ++i)
+ {
+ fi = array[i].m_key;
+ pos = D11_0(fi);
+ pos = ++b0[pos];
+ sorted[pos].m_key = array[i].m_key;
+ sorted[pos].m_value = array[i].m_value;
+ }
+ for (i = 0; i < element_count; ++i)
+ {
+ fi = sorted[i].m_key;
+ pos = D11_1(fi);
+ pos = ++b1[pos];
+ array[pos].m_key = sorted[i].m_key;
+ array[pos].m_value = sorted[i].m_value;
+ }
+ for (i = 0; i < element_count; ++i)
+ {
+ fi = array[i].m_key;
+ pos = D11_2(fi);
+ pos = ++b2[pos];
+ sorted[pos].m_key = array[i].m_key;
+ sorted[pos].m_value = array[i].m_value;
+ }
+}
+
+
+
+
+/// Get the sorted tokens from an array. For generic use. Tokens are IRR_RSORT_TOKEN
+/*!
+*\param array Array of elements to sort
+*\param sorted_tokens Tokens of sorted elements
+*\param element_count element count
+*\param uintkey_macro Functor which retrieves the integer representation of an array element
+*/
+template<typename T, class GETKEY_CLASS>
+void gim_radix_sort_array_tokens(
+ T* array ,
+ GIM_RSORT_TOKEN * sorted_tokens,
+ GUINT element_count,GETKEY_CLASS uintkey_macro)
+{
+ GIM_RSORT_TOKEN * _unsorted = (GIM_RSORT_TOKEN *) gim_alloc(sizeof(GIM_RSORT_TOKEN)*element_count);
+ for (GUINT _i=0;_i<element_count;++_i)
+ {
+ _unsorted[_i].m_key = uintkey_macro(array[_i]);
+ _unsorted[_i].m_value = _i;
+ }
+ gim_radix_sort_rtokens(_unsorted,sorted_tokens,element_count);
+ gim_free(_unsorted);
+ gim_free(_unsorted);
+}
+
+/// Sorts array in place. For generic use
+/*!
+\param type Type of the array
+\param array
+\param element_count
+\param get_uintkey_macro Macro for extract the Integer value of the element. Similar to SIMPLE_GET_UINTKEY
+\param copy_elements_macro Macro for copy elements, similar to SIMPLE_COPY_ELEMENTS
+*/
+template<typename T, class GETKEY_CLASS, class COPY_CLASS>
+void gim_radix_sort(
+ T * array, GUINT element_count,
+ GETKEY_CLASS get_uintkey_macro, COPY_CLASS copy_elements_macro)
+{
+ GIM_RSORT_TOKEN * _sorted = (GIM_RSORT_TOKEN *) gim_alloc(sizeof(GIM_RSORT_TOKEN)*element_count);
+ gim_radix_sort_array_tokens(array,_sorted,element_count,get_uintkey_macro);
+ T * _original_array = (T *) gim_alloc(sizeof(T)*element_count);
+ gim_simd_memcpy(_original_array,array,sizeof(T)*element_count);
+ for (GUINT _i=0;_i<element_count;++_i)
+ {
+ copy_elements_macro(array[_i],_original_array[_sorted[_i].m_value]);
+ }
+ gim_free(_original_array);
+ gim_free(_sorted);
+}
+
+//! Failsafe Iterative binary search,
+/*!
+If the element is not found, it returns the nearest upper element position, may be the further position after the last element.
+\param _array
+\param _start_i the beginning of the array
+\param _end_i the ending index of the array
+\param _search_key Value to find
+\param _comp_macro macro for comparing elements
+\param _found If true the value has found. Boolean
+\param _result_index the index of the found element, or if not found then it will get the index of the closest bigger value
+*/
+template<class T, typename KEYCLASS, typename COMP_CLASS>
+bool gim_binary_search_ex(
+ const T* _array, GUINT _start_i,
+ GUINT _end_i,GUINT & _result_index,
+ const KEYCLASS & _search_key,
+ COMP_CLASS _comp_macro)
+{
+ GUINT _k;
+ int _comp_result;
+ GUINT _i = _start_i;
+ GUINT _j = _end_i+1;
+ while (_i < _j)
+ {
+ _k = (_j+_i-1)/2;
+ _comp_result = _comp_macro(_array[_k], _search_key);
+ if (_comp_result == 0)
+ {
+ _result_index = _k;
+ return true;
+ }
+ else if (_comp_result < 0)
+ {
+ _i = _k+1;
+ }
+ else
+ {
+ _j = _k;
+ }
+ }
+ _result_index = _i;
+ return false;
+}
+
+
+
+//! Failsafe Iterative binary search,Template version
+/*!
+If the element is not found, it returns the nearest upper element position, may be the further position after the last element.
+\param _array
+\param _start_i the beginning of the array
+\param _end_i the ending index of the array
+\param _search_key Value to find
+\param _result_index the index of the found element, or if not found then it will get the index of the closest bigger value
+\return true if found, else false
+*/
+template<class T>
+bool gim_binary_search(
+ const T*_array,GUINT _start_i,
+ GUINT _end_i,const T & _search_key,
+ GUINT & _result_index)
+{
+ GUINT _i = _start_i;
+ GUINT _j = _end_i+1;
+ GUINT _k;
+ while(_i < _j)
+ {
+ _k = (_j+_i-1)/2;
+ if(_array[_k]==_search_key)
+ {
+ _result_index = _k;
+ return true;
+ }
+ else if (_array[_k]<_search_key)
+ {
+ _i = _k+1;
+ }
+ else
+ {
+ _j = _k;
+ }
+ }
+ _result_index = _i;
+ return false;
+}
+
+
+
+///heap sort from http://www.csse.monash.edu.au/~lloyd/tildeAlgDS/Sort/Heap/
+template <typename T, typename COMP_CLASS>
+void gim_down_heap(T *pArr, GUINT k, GUINT n,COMP_CLASS CompareFunc)
+{
+ /* PRE: a[k+1..N] is a heap */
+ /* POST: a[k..N] is a heap */
+
+ T temp = pArr[k - 1];
+ /* k has child(s) */
+ while (k <= n/2)
+ {
+ int child = 2*k;
+
+ if ((child < (int)n) && CompareFunc(pArr[child - 1] , pArr[child])<0)
+ {
+ child++;
+ }
+ /* pick larger child */
+ if (CompareFunc(temp , pArr[child - 1])<0)
+ {
+ /* move child up */
+ pArr[k - 1] = pArr[child - 1];
+ k = child;
+ }
+ else
+ {
+ break;
+ }
+ }
+ pArr[k - 1] = temp;
+} /*downHeap*/
+
+
+template <typename T, typename COMP_CLASS>
+void gim_heap_sort(T *pArr, GUINT element_count, COMP_CLASS CompareFunc)
+{
+ /* sort a[0..N-1], N.B. 0 to N-1 */
+ GUINT k;
+ GUINT n = element_count;
+ for (k = n/2; k > 0; k--)
+ {
+ gim_down_heap(pArr, k, n, CompareFunc);
+ }
+
+ /* a[1..N] is now a heap */
+ while ( n>=2 )
+ {
+ gim_swap_elements(pArr,0,n-1); /* largest of a[0..n-1] */
+ --n;
+ /* restore a[1..i-1] heap */
+ gim_down_heap(pArr, 1, n, CompareFunc);
+ }
+}
+
+
+
+
+#endif // GIM_RADIXSORT_H_INCLUDED
diff --git a/thirdparty/bullet/src/BulletCollision/Gimpact/gim_tri_collision.cpp b/thirdparty/bullet/src/BulletCollision/Gimpact/gim_tri_collision.cpp
new file mode 100644
index 0000000000..f9727e1d53
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/Gimpact/gim_tri_collision.cpp
@@ -0,0 +1,640 @@
+
+/*! \file gim_tri_collision.h
+\author Francisco Leon Najera
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+ (1) The GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 2.1 of the License, or (at
+ your option) any later version. The text of the GNU Lesser
+ General Public License is included with this library in the
+ file GIMPACT-LICENSE-LGPL.TXT.
+ (2) The BSD-style license that is included with this library in
+ the file GIMPACT-LICENSE-BSD.TXT.
+ (3) The zlib/libpng license that is included with this library in
+ the file GIMPACT-LICENSE-ZLIB.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+#include "gim_tri_collision.h"
+
+
+#define TRI_LOCAL_EPSILON 0.000001f
+#define MIN_EDGE_EDGE_DIS 0.00001f
+
+
+class GIM_TRIANGLE_CALCULATION_CACHE
+{
+public:
+ GREAL margin;
+ btVector3 tu_vertices[3];
+ btVector3 tv_vertices[3];
+ btVector4 tu_plane;
+ btVector4 tv_plane;
+ btVector3 closest_point_u;
+ btVector3 closest_point_v;
+ btVector3 edge_edge_dir;
+ btVector3 distances;
+ GREAL du[4];
+ GREAL du0du1;
+ GREAL du0du2;
+ GREAL dv[4];
+ GREAL dv0dv1;
+ GREAL dv0dv2;
+ btVector3 temp_points[MAX_TRI_CLIPPING];
+ btVector3 temp_points1[MAX_TRI_CLIPPING];
+ btVector3 contact_points[MAX_TRI_CLIPPING];
+
+
+
+ //! if returns false, the faces are paralele
+ SIMD_FORCE_INLINE bool compute_intervals(
+ const GREAL &D0,
+ const GREAL &D1,
+ const GREAL &D2,
+ const GREAL &D0D1,
+ const GREAL &D0D2,
+ GREAL & scale_edge0,
+ GREAL & scale_edge1,
+ GUINT &edge_index0,
+ GUINT &edge_index1)
+ {
+ if(D0D1>0.0f)
+ {
+ /* here we know that D0D2<=0.0 */
+ /* that is D0, D1 are on the same side, D2 on the other or on the plane */
+ scale_edge0 = -D2/(D0-D2);
+ scale_edge1 = -D1/(D2-D1);
+ edge_index0 = 2;edge_index1 = 1;
+ }
+ else if(D0D2>0.0f)
+ {
+ /* here we know that d0d1<=0.0 */
+ scale_edge0 = -D0/(D1-D0);
+ scale_edge1 = -D1/(D2-D1);
+ edge_index0 = 0;edge_index1 = 1;
+ }
+ else if(D1*D2>0.0f || D0!=0.0f)
+ {
+ /* here we know that d0d1<=0.0 or that D0!=0.0 */
+ scale_edge0 = -D0/(D1-D0);
+ scale_edge1 = -D2/(D0-D2);
+ edge_index0 = 0 ;edge_index1 = 2;
+ }
+ else
+ {
+ return false;
+ }
+ return true;
+ }
+
+
+ //! clip triangle
+ /*!
+ */
+ SIMD_FORCE_INLINE GUINT clip_triangle(
+ const btVector4 & tri_plane,
+ const btVector3 * tripoints,
+ const btVector3 * srcpoints,
+ btVector3 * clip_points)
+ {
+ // edge 0
+
+ btVector4 edgeplane;
+
+ EDGE_PLANE(tripoints[0],tripoints[1],tri_plane,edgeplane);
+
+ GUINT clipped_count = PLANE_CLIP_TRIANGLE3D(
+ edgeplane,srcpoints[0],srcpoints[1],srcpoints[2],temp_points);
+
+ if(clipped_count == 0) return 0;
+
+ // edge 1
+
+ EDGE_PLANE(tripoints[1],tripoints[2],tri_plane,edgeplane);
+
+ clipped_count = PLANE_CLIP_POLYGON3D(
+ edgeplane,temp_points,clipped_count,temp_points1);
+
+ if(clipped_count == 0) return 0;
+
+ // edge 2
+
+ EDGE_PLANE(tripoints[2],tripoints[0],tri_plane,edgeplane);
+
+ clipped_count = PLANE_CLIP_POLYGON3D(
+ edgeplane,temp_points1,clipped_count,clip_points);
+
+ return clipped_count;
+
+
+ /*GUINT i0 = (tri_plane.closestAxis()+1)%3;
+ GUINT i1 = (i0+1)%3;
+ // edge 0
+ btVector3 temp_points[MAX_TRI_CLIPPING];
+ btVector3 temp_points1[MAX_TRI_CLIPPING];
+
+ GUINT clipped_count= PLANE_CLIP_TRIANGLE_GENERIC(
+ 0,srcpoints[0],srcpoints[1],srcpoints[2],temp_points,
+ DISTANCE_EDGE(tripoints[0],tripoints[1],i0,i1));
+
+
+ if(clipped_count == 0) return 0;
+
+ // edge 1
+ clipped_count = PLANE_CLIP_POLYGON_GENERIC(
+ 0,temp_points,clipped_count,temp_points1,
+ DISTANCE_EDGE(tripoints[1],tripoints[2],i0,i1));
+
+ if(clipped_count == 0) return 0;
+
+ // edge 2
+ clipped_count = PLANE_CLIP_POLYGON_GENERIC(
+ 0,temp_points1,clipped_count,clipped_points,
+ DISTANCE_EDGE(tripoints[2],tripoints[0],i0,i1));
+
+ return clipped_count;*/
+ }
+
+ SIMD_FORCE_INLINE void sort_isect(
+ GREAL & isect0,GREAL & isect1,GUINT &e0,GUINT &e1,btVector3 & vec0,btVector3 & vec1)
+ {
+ if(isect1<isect0)
+ {
+ //swap
+ GIM_SWAP_NUMBERS(isect0,isect1);
+ GIM_SWAP_NUMBERS(e0,e1);
+ btVector3 tmp = vec0;
+ vec0 = vec1;
+ vec1 = tmp;
+ }
+ }
+
+ //! Test verifying interval intersection with the direction between planes
+ /*!
+ \pre tv_plane and tu_plane must be set
+ \post
+ distances[2] is set with the distance
+ closest_point_u, closest_point_v, edge_edge_dir are set too
+ \return
+ - 0: faces are paralele
+ - 1: face U casts face V
+ - 2: face V casts face U
+ - 3: nearest edges
+ */
+ SIMD_FORCE_INLINE GUINT cross_line_intersection_test()
+ {
+ // Compute direction of intersection line
+ edge_edge_dir = tu_plane.cross(tv_plane);
+ GREAL Dlen;
+ VEC_LENGTH(edge_edge_dir,Dlen);
+
+ if(Dlen<0.0001)
+ {
+ return 0; //faces near paralele
+ }
+
+ edge_edge_dir*= 1/Dlen;//normalize
+
+
+ // Compute interval for triangle 1
+ GUINT tu_e0,tu_e1;//edge indices
+ GREAL tu_scale_e0,tu_scale_e1;//edge scale
+ if(!compute_intervals(du[0],du[1],du[2],
+ du0du1,du0du2,tu_scale_e0,tu_scale_e1,tu_e0,tu_e1)) return 0;
+
+ // Compute interval for triangle 2
+ GUINT tv_e0,tv_e1;//edge indices
+ GREAL tv_scale_e0,tv_scale_e1;//edge scale
+
+ if(!compute_intervals(dv[0],dv[1],dv[2],
+ dv0dv1,dv0dv2,tv_scale_e0,tv_scale_e1,tv_e0,tv_e1)) return 0;
+
+ //proyected vertices
+ btVector3 up_e0 = tu_vertices[tu_e0].lerp(tu_vertices[(tu_e0+1)%3],tu_scale_e0);
+ btVector3 up_e1 = tu_vertices[tu_e1].lerp(tu_vertices[(tu_e1+1)%3],tu_scale_e1);
+
+ btVector3 vp_e0 = tv_vertices[tv_e0].lerp(tv_vertices[(tv_e0+1)%3],tv_scale_e0);
+ btVector3 vp_e1 = tv_vertices[tv_e1].lerp(tv_vertices[(tv_e1+1)%3],tv_scale_e1);
+
+ //proyected intervals
+ GREAL isect_u[] = {up_e0.dot(edge_edge_dir),up_e1.dot(edge_edge_dir)};
+ GREAL isect_v[] = {vp_e0.dot(edge_edge_dir),vp_e1.dot(edge_edge_dir)};
+
+ sort_isect(isect_u[0],isect_u[1],tu_e0,tu_e1,up_e0,up_e1);
+ sort_isect(isect_v[0],isect_v[1],tv_e0,tv_e1,vp_e0,vp_e1);
+
+ const GREAL midpoint_u = 0.5f*(isect_u[0]+isect_u[1]); // midpoint
+ const GREAL midpoint_v = 0.5f*(isect_v[0]+isect_v[1]); // midpoint
+
+ if(midpoint_u<midpoint_v)
+ {
+ if(isect_u[1]>=isect_v[1]) // face U casts face V
+ {
+ return 1;
+ }
+ else if(isect_v[0]<=isect_u[0]) // face V casts face U
+ {
+ return 2;
+ }
+ // closest points
+ closest_point_u = up_e1;
+ closest_point_v = vp_e0;
+ // calc edges and separation
+
+ if(isect_u[1]+ MIN_EDGE_EDGE_DIS<isect_v[0]) //calc distance between two lines instead
+ {
+ SEGMENT_COLLISION(
+ tu_vertices[tu_e1],tu_vertices[(tu_e1+1)%3],
+ tv_vertices[tv_e0],tv_vertices[(tv_e0+1)%3],
+ closest_point_u,
+ closest_point_v);
+
+ edge_edge_dir = closest_point_u-closest_point_v;
+ VEC_LENGTH(edge_edge_dir,distances[2]);
+ edge_edge_dir *= 1.0f/distances[2];// normalize
+ }
+ else
+ {
+ distances[2] = isect_v[0]-isect_u[1];//distance negative
+ //edge_edge_dir *= -1.0f; //normal pointing from V to U
+ }
+
+ }
+ else
+ {
+ if(isect_v[1]>=isect_u[1]) // face V casts face U
+ {
+ return 2;
+ }
+ else if(isect_u[0]<=isect_v[0]) // face U casts face V
+ {
+ return 1;
+ }
+ // closest points
+ closest_point_u = up_e0;
+ closest_point_v = vp_e1;
+ // calc edges and separation
+
+ if(isect_v[1]+MIN_EDGE_EDGE_DIS<isect_u[0]) //calc distance between two lines instead
+ {
+ SEGMENT_COLLISION(
+ tu_vertices[tu_e0],tu_vertices[(tu_e0+1)%3],
+ tv_vertices[tv_e1],tv_vertices[(tv_e1+1)%3],
+ closest_point_u,
+ closest_point_v);
+
+ edge_edge_dir = closest_point_u-closest_point_v;
+ VEC_LENGTH(edge_edge_dir,distances[2]);
+ edge_edge_dir *= 1.0f/distances[2];// normalize
+ }
+ else
+ {
+ distances[2] = isect_u[0]-isect_v[1];//distance negative
+ //edge_edge_dir *= -1.0f; //normal pointing from V to U
+ }
+ }
+ return 3;
+ }
+
+
+ //! collides by two sides
+ SIMD_FORCE_INLINE bool triangle_collision(
+ const btVector3 & u0,
+ const btVector3 & u1,
+ const btVector3 & u2,
+ GREAL margin_u,
+ const btVector3 & v0,
+ const btVector3 & v1,
+ const btVector3 & v2,
+ GREAL margin_v,
+ GIM_TRIANGLE_CONTACT_DATA & contacts)
+ {
+
+ margin = margin_u + margin_v;
+
+ tu_vertices[0] = u0;
+ tu_vertices[1] = u1;
+ tu_vertices[2] = u2;
+
+ tv_vertices[0] = v0;
+ tv_vertices[1] = v1;
+ tv_vertices[2] = v2;
+
+ //create planes
+ // plane v vs U points
+
+ TRIANGLE_PLANE(tv_vertices[0],tv_vertices[1],tv_vertices[2],tv_plane);
+
+ du[0] = DISTANCE_PLANE_POINT(tv_plane,tu_vertices[0]);
+ du[1] = DISTANCE_PLANE_POINT(tv_plane,tu_vertices[1]);
+ du[2] = DISTANCE_PLANE_POINT(tv_plane,tu_vertices[2]);
+
+
+ du0du1 = du[0] * du[1];
+ du0du2 = du[0] * du[2];
+
+
+ if(du0du1>0.0f && du0du2>0.0f) // same sign on all of them + not equal 0 ?
+ {
+ if(du[0]<0) //we need test behind the triangle plane
+ {
+ distances[0] = GIM_MAX3(du[0],du[1],du[2]);
+ distances[0] = -distances[0];
+ if(distances[0]>margin) return false; //never intersect
+
+ //reorder triangle v
+ VEC_SWAP(tv_vertices[0],tv_vertices[1]);
+ VEC_SCALE_4(tv_plane,-1.0f,tv_plane);
+ }
+ else
+ {
+ distances[0] = GIM_MIN3(du[0],du[1],du[2]);
+ if(distances[0]>margin) return false; //never intersect
+ }
+ }
+ else
+ {
+ //Look if we need to invert the triangle
+ distances[0] = (du[0]+du[1]+du[2])/3.0f; //centroid
+
+ if(distances[0]<0.0f)
+ {
+ //reorder triangle v
+ VEC_SWAP(tv_vertices[0],tv_vertices[1]);
+ VEC_SCALE_4(tv_plane,-1.0f,tv_plane);
+
+ distances[0] = GIM_MAX3(du[0],du[1],du[2]);
+ distances[0] = -distances[0];
+ }
+ else
+ {
+ distances[0] = GIM_MIN3(du[0],du[1],du[2]);
+ }
+ }
+
+
+ // plane U vs V points
+
+ TRIANGLE_PLANE(tu_vertices[0],tu_vertices[1],tu_vertices[2],tu_plane);
+
+ dv[0] = DISTANCE_PLANE_POINT(tu_plane,tv_vertices[0]);
+ dv[1] = DISTANCE_PLANE_POINT(tu_plane,tv_vertices[1]);
+ dv[2] = DISTANCE_PLANE_POINT(tu_plane,tv_vertices[2]);
+
+ dv0dv1 = dv[0] * dv[1];
+ dv0dv2 = dv[0] * dv[2];
+
+
+ if(dv0dv1>0.0f && dv0dv2>0.0f) // same sign on all of them + not equal 0 ?
+ {
+ if(dv[0]<0) //we need test behind the triangle plane
+ {
+ distances[1] = GIM_MAX3(dv[0],dv[1],dv[2]);
+ distances[1] = -distances[1];
+ if(distances[1]>margin) return false; //never intersect
+
+ //reorder triangle u
+ VEC_SWAP(tu_vertices[0],tu_vertices[1]);
+ VEC_SCALE_4(tu_plane,-1.0f,tu_plane);
+ }
+ else
+ {
+ distances[1] = GIM_MIN3(dv[0],dv[1],dv[2]);
+ if(distances[1]>margin) return false; //never intersect
+ }
+ }
+ else
+ {
+ //Look if we need to invert the triangle
+ distances[1] = (dv[0]+dv[1]+dv[2])/3.0f; //centroid
+
+ if(distances[1]<0.0f)
+ {
+ //reorder triangle v
+ VEC_SWAP(tu_vertices[0],tu_vertices[1]);
+ VEC_SCALE_4(tu_plane,-1.0f,tu_plane);
+
+ distances[1] = GIM_MAX3(dv[0],dv[1],dv[2]);
+ distances[1] = -distances[1];
+ }
+ else
+ {
+ distances[1] = GIM_MIN3(dv[0],dv[1],dv[2]);
+ }
+ }
+
+ GUINT bl;
+ /* bl = cross_line_intersection_test();
+ if(bl==3)
+ {
+ //take edge direction too
+ bl = distances.maxAxis();
+ }
+ else
+ {*/
+ bl = 0;
+ if(distances[0]<distances[1]) bl = 1;
+ //}
+
+ if(bl==2) //edge edge separation
+ {
+ if(distances[2]>margin) return false;
+
+ contacts.m_penetration_depth = -distances[2] + margin;
+ contacts.m_points[0] = closest_point_v;
+ contacts.m_point_count = 1;
+ VEC_COPY(contacts.m_separating_normal,edge_edge_dir);
+
+ return true;
+ }
+
+ //clip face against other
+
+
+ GUINT point_count;
+ //TODO
+ if(bl == 0) //clip U points against V
+ {
+ point_count = clip_triangle(tv_plane,tv_vertices,tu_vertices,contact_points);
+ if(point_count == 0) return false;
+ contacts.merge_points(tv_plane,margin,contact_points,point_count);
+ }
+ else //clip V points against U
+ {
+ point_count = clip_triangle(tu_plane,tu_vertices,tv_vertices,contact_points);
+ if(point_count == 0) return false;
+ contacts.merge_points(tu_plane,margin,contact_points,point_count);
+ contacts.m_separating_normal *= -1.f;
+ }
+ if(contacts.m_point_count == 0) return false;
+ return true;
+ }
+
+};
+
+
+/*class GIM_TRIANGLE_CALCULATION_CACHE
+{
+public:
+ GREAL margin;
+ GUINT clipped_count;
+ btVector3 tu_vertices[3];
+ btVector3 tv_vertices[3];
+ btVector3 temp_points[MAX_TRI_CLIPPING];
+ btVector3 temp_points1[MAX_TRI_CLIPPING];
+ btVector3 clipped_points[MAX_TRI_CLIPPING];
+ GIM_TRIANGLE_CONTACT_DATA contacts1;
+ GIM_TRIANGLE_CONTACT_DATA contacts2;
+
+
+ //! clip triangle
+ GUINT clip_triangle(
+ const btVector4 & tri_plane,
+ const btVector3 * tripoints,
+ const btVector3 * srcpoints,
+ btVector3 * clipped_points)
+ {
+ // edge 0
+
+ btVector4 edgeplane;
+
+ EDGE_PLANE(tripoints[0],tripoints[1],tri_plane,edgeplane);
+
+ GUINT clipped_count = PLANE_CLIP_TRIANGLE3D(
+ edgeplane,srcpoints[0],srcpoints[1],srcpoints[2],temp_points);
+
+ if(clipped_count == 0) return 0;
+
+ // edge 1
+
+ EDGE_PLANE(tripoints[1],tripoints[2],tri_plane,edgeplane);
+
+ clipped_count = PLANE_CLIP_POLYGON3D(
+ edgeplane,temp_points,clipped_count,temp_points1);
+
+ if(clipped_count == 0) return 0;
+
+ // edge 2
+
+ EDGE_PLANE(tripoints[2],tripoints[0],tri_plane,edgeplane);
+
+ clipped_count = PLANE_CLIP_POLYGON3D(
+ edgeplane,temp_points1,clipped_count,clipped_points);
+
+ return clipped_count;
+ }
+
+
+
+
+ //! collides only on one side
+ bool triangle_collision(
+ const btVector3 & u0,
+ const btVector3 & u1,
+ const btVector3 & u2,
+ GREAL margin_u,
+ const btVector3 & v0,
+ const btVector3 & v1,
+ const btVector3 & v2,
+ GREAL margin_v,
+ GIM_TRIANGLE_CONTACT_DATA & contacts)
+ {
+
+ margin = margin_u + margin_v;
+
+
+ tu_vertices[0] = u0;
+ tu_vertices[1] = u1;
+ tu_vertices[2] = u2;
+
+ tv_vertices[0] = v0;
+ tv_vertices[1] = v1;
+ tv_vertices[2] = v2;
+
+ //create planes
+ // plane v vs U points
+
+
+ TRIANGLE_PLANE(tv_vertices[0],tv_vertices[1],tv_vertices[2],contacts1.m_separating_normal);
+
+ clipped_count = clip_triangle(
+ contacts1.m_separating_normal,tv_vertices,tu_vertices,clipped_points);
+
+ if(clipped_count == 0 )
+ {
+ return false;//Reject
+ }
+
+ //find most deep interval face1
+ contacts1.merge_points(contacts1.m_separating_normal,margin,clipped_points,clipped_count);
+ if(contacts1.m_point_count == 0) return false; // too far
+
+ //Normal pointing to triangle1
+ //contacts1.m_separating_normal *= -1.f;
+
+ //Clip tri1 by tri2 edges
+
+ TRIANGLE_PLANE(tu_vertices[0],tu_vertices[1],tu_vertices[2],contacts2.m_separating_normal);
+
+ clipped_count = clip_triangle(
+ contacts2.m_separating_normal,tu_vertices,tv_vertices,clipped_points);
+
+ if(clipped_count == 0 )
+ {
+ return false;//Reject
+ }
+
+ //find most deep interval face1
+ contacts2.merge_points(contacts2.m_separating_normal,margin,clipped_points,clipped_count);
+ if(contacts2.m_point_count == 0) return false; // too far
+
+ contacts2.m_separating_normal *= -1.f;
+
+ ////check most dir for contacts
+ if(contacts2.m_penetration_depth<contacts1.m_penetration_depth)
+ {
+ contacts.copy_from(contacts2);
+ }
+ else
+ {
+ contacts.copy_from(contacts1);
+ }
+ return true;
+ }
+
+
+};*/
+
+
+
+bool GIM_TRIANGLE::collide_triangle_hard_test(
+ const GIM_TRIANGLE & other,
+ GIM_TRIANGLE_CONTACT_DATA & contact_data) const
+{
+ GIM_TRIANGLE_CALCULATION_CACHE calc_cache;
+ return calc_cache.triangle_collision(
+ m_vertices[0],m_vertices[1],m_vertices[2],m_margin,
+ other.m_vertices[0],other.m_vertices[1],other.m_vertices[2],other.m_margin,
+ contact_data);
+
+}
+
+
+
+
diff --git a/thirdparty/bullet/src/BulletCollision/Gimpact/gim_tri_collision.h b/thirdparty/bullet/src/BulletCollision/Gimpact/gim_tri_collision.h
new file mode 100644
index 0000000000..267f806e7e
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/Gimpact/gim_tri_collision.h
@@ -0,0 +1,380 @@
+#ifndef GIM_TRI_COLLISION_H_INCLUDED
+#define GIM_TRI_COLLISION_H_INCLUDED
+
+/*! \file gim_tri_collision.h
+\author Francisco Leon Najera
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+ (1) The GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 2.1 of the License, or (at
+ your option) any later version. The text of the GNU Lesser
+ General Public License is included with this library in the
+ file GIMPACT-LICENSE-LGPL.TXT.
+ (2) The BSD-style license that is included with this library in
+ the file GIMPACT-LICENSE-BSD.TXT.
+ (3) The zlib/libpng license that is included with this library in
+ the file GIMPACT-LICENSE-ZLIB.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+#include "gim_box_collision.h"
+#include "gim_clip_polygon.h"
+
+
+
+#ifndef MAX_TRI_CLIPPING
+#define MAX_TRI_CLIPPING 16
+#endif
+
+//! Structure for collision
+struct GIM_TRIANGLE_CONTACT_DATA
+{
+ GREAL m_penetration_depth;
+ GUINT m_point_count;
+ btVector4 m_separating_normal;
+ btVector3 m_points[MAX_TRI_CLIPPING];
+
+ SIMD_FORCE_INLINE void copy_from(const GIM_TRIANGLE_CONTACT_DATA& other)
+ {
+ m_penetration_depth = other.m_penetration_depth;
+ m_separating_normal = other.m_separating_normal;
+ m_point_count = other.m_point_count;
+ GUINT i = m_point_count;
+ while(i--)
+ {
+ m_points[i] = other.m_points[i];
+ }
+ }
+
+ GIM_TRIANGLE_CONTACT_DATA()
+ {
+ }
+
+ GIM_TRIANGLE_CONTACT_DATA(const GIM_TRIANGLE_CONTACT_DATA& other)
+ {
+ copy_from(other);
+ }
+
+
+
+
+ //! classify points that are closer
+ template<typename DISTANCE_FUNC,typename CLASS_PLANE>
+ SIMD_FORCE_INLINE void mergepoints_generic(const CLASS_PLANE & plane,
+ GREAL margin, const btVector3 * points, GUINT point_count, DISTANCE_FUNC distance_func)
+ {
+ m_point_count = 0;
+ m_penetration_depth= -1000.0f;
+
+ GUINT point_indices[MAX_TRI_CLIPPING];
+
+ GUINT _k;
+
+ for(_k=0;_k<point_count;_k++)
+ {
+ GREAL _dist = -distance_func(plane,points[_k]) + margin;
+
+ if(_dist>=0.0f)
+ {
+ if(_dist>m_penetration_depth)
+ {
+ m_penetration_depth = _dist;
+ point_indices[0] = _k;
+ m_point_count=1;
+ }
+ else if((_dist+G_EPSILON)>=m_penetration_depth)
+ {
+ point_indices[m_point_count] = _k;
+ m_point_count++;
+ }
+ }
+ }
+
+ for( _k=0;_k<m_point_count;_k++)
+ {
+ m_points[_k] = points[point_indices[_k]];
+ }
+ }
+
+ //! classify points that are closer
+ SIMD_FORCE_INLINE void merge_points(const btVector4 & plane, GREAL margin,
+ const btVector3 * points, GUINT point_count)
+ {
+ m_separating_normal = plane;
+ mergepoints_generic(plane, margin, points, point_count, DISTANCE_PLANE_3D_FUNC());
+ }
+};
+
+
+//! Class for colliding triangles
+class GIM_TRIANGLE
+{
+public:
+ btScalar m_margin;
+ btVector3 m_vertices[3];
+
+ GIM_TRIANGLE():m_margin(0.1f)
+ {
+ }
+
+ SIMD_FORCE_INLINE GIM_AABB get_box() const
+ {
+ return GIM_AABB(m_vertices[0],m_vertices[1],m_vertices[2],m_margin);
+ }
+
+ SIMD_FORCE_INLINE void get_normal(btVector3 &normal) const
+ {
+ TRIANGLE_NORMAL(m_vertices[0],m_vertices[1],m_vertices[2],normal);
+ }
+
+ SIMD_FORCE_INLINE void get_plane(btVector4 &plane) const
+ {
+ TRIANGLE_PLANE(m_vertices[0],m_vertices[1],m_vertices[2],plane);;
+ }
+
+ SIMD_FORCE_INLINE void apply_transform(const btTransform & trans)
+ {
+ m_vertices[0] = trans(m_vertices[0]);
+ m_vertices[1] = trans(m_vertices[1]);
+ m_vertices[2] = trans(m_vertices[2]);
+ }
+
+ SIMD_FORCE_INLINE void get_edge_plane(GUINT edge_index,const btVector3 &triangle_normal,btVector4 &plane) const
+ {
+ const btVector3 & e0 = m_vertices[edge_index];
+ const btVector3 & e1 = m_vertices[(edge_index+1)%3];
+ EDGE_PLANE(e0,e1,triangle_normal,plane);
+ }
+
+ //! Gets the relative transformation of this triangle
+ /*!
+ The transformation is oriented to the triangle normal , and aligned to the 1st edge of this triangle. The position corresponds to vertice 0:
+ - triangle normal corresponds to Z axis.
+ - 1st normalized edge corresponds to X axis,
+
+ */
+ SIMD_FORCE_INLINE void get_triangle_transform(btTransform & triangle_transform) const
+ {
+ btMatrix3x3 & matrix = triangle_transform.getBasis();
+
+ btVector3 zaxis;
+ get_normal(zaxis);
+ MAT_SET_Z(matrix,zaxis);
+
+ btVector3 xaxis = m_vertices[1] - m_vertices[0];
+ VEC_NORMALIZE(xaxis);
+ MAT_SET_X(matrix,xaxis);
+
+ //y axis
+ xaxis = zaxis.cross(xaxis);
+ MAT_SET_Y(matrix,xaxis);
+
+ triangle_transform.setOrigin(m_vertices[0]);
+ }
+
+
+ //! Test triangles by finding separating axis
+ /*!
+ \param other Triangle for collide
+ \param contact_data Structure for holding contact points, normal and penetration depth; The normal is pointing toward this triangle from the other triangle
+ */
+ bool collide_triangle_hard_test(
+ const GIM_TRIANGLE & other,
+ GIM_TRIANGLE_CONTACT_DATA & contact_data) const;
+
+ //! Test boxes before doing hard test
+ /*!
+ \param other Triangle for collide
+ \param contact_data Structure for holding contact points, normal and penetration depth; The normal is pointing toward this triangle from the other triangle
+ \
+ */
+ SIMD_FORCE_INLINE bool collide_triangle(
+ const GIM_TRIANGLE & other,
+ GIM_TRIANGLE_CONTACT_DATA & contact_data) const
+ {
+ //test box collisioin
+ GIM_AABB boxu(m_vertices[0],m_vertices[1],m_vertices[2],m_margin);
+ GIM_AABB boxv(other.m_vertices[0],other.m_vertices[1],other.m_vertices[2],other.m_margin);
+ if(!boxu.has_collision(boxv)) return false;
+
+ //do hard test
+ return collide_triangle_hard_test(other,contact_data);
+ }
+
+ /*!
+
+ Solve the System for u,v parameters:
+
+ u*axe1[i1] + v*axe2[i1] = vecproj[i1]
+ u*axe1[i2] + v*axe2[i2] = vecproj[i2]
+
+ sustitute:
+ v = (vecproj[i2] - u*axe1[i2])/axe2[i2]
+
+ then the first equation in terms of 'u':
+
+ --> u*axe1[i1] + ((vecproj[i2] - u*axe1[i2])/axe2[i2])*axe2[i1] = vecproj[i1]
+
+ --> u*axe1[i1] + vecproj[i2]*axe2[i1]/axe2[i2] - u*axe1[i2]*axe2[i1]/axe2[i2] = vecproj[i1]
+
+ --> u*(axe1[i1] - axe1[i2]*axe2[i1]/axe2[i2]) = vecproj[i1] - vecproj[i2]*axe2[i1]/axe2[i2]
+
+ --> u*((axe1[i1]*axe2[i2] - axe1[i2]*axe2[i1])/axe2[i2]) = (vecproj[i1]*axe2[i2] - vecproj[i2]*axe2[i1])/axe2[i2]
+
+ --> u*(axe1[i1]*axe2[i2] - axe1[i2]*axe2[i1]) = vecproj[i1]*axe2[i2] - vecproj[i2]*axe2[i1]
+
+ --> u = (vecproj[i1]*axe2[i2] - vecproj[i2]*axe2[i1]) /(axe1[i1]*axe2[i2] - axe1[i2]*axe2[i1])
+
+if 0.0<= u+v <=1.0 then they are inside of triangle
+
+ \return false if the point is outside of triangle.This function doesn't take the margin
+ */
+ SIMD_FORCE_INLINE bool get_uv_parameters(
+ const btVector3 & point,
+ const btVector3 & tri_plane,
+ GREAL & u, GREAL & v) const
+ {
+ btVector3 _axe1 = m_vertices[1]-m_vertices[0];
+ btVector3 _axe2 = m_vertices[2]-m_vertices[0];
+ btVector3 _vecproj = point - m_vertices[0];
+ GUINT _i1 = (tri_plane.closestAxis()+1)%3;
+ GUINT _i2 = (_i1+1)%3;
+ if(btFabs(_axe2[_i2])<G_EPSILON)
+ {
+ u = (_vecproj[_i2]*_axe2[_i1] - _vecproj[_i1]*_axe2[_i2]) /(_axe1[_i2]*_axe2[_i1] - _axe1[_i1]*_axe2[_i2]);
+ v = (_vecproj[_i1] - u*_axe1[_i1])/_axe2[_i1];
+ }
+ else
+ {
+ u = (_vecproj[_i1]*_axe2[_i2] - _vecproj[_i2]*_axe2[_i1]) /(_axe1[_i1]*_axe2[_i2] - _axe1[_i2]*_axe2[_i1]);
+ v = (_vecproj[_i2] - u*_axe1[_i2])/_axe2[_i2];
+ }
+
+ if(u<-G_EPSILON)
+ {
+ return false;
+ }
+ else if(v<-G_EPSILON)
+ {
+ return false;
+ }
+ else
+ {
+ btScalar sumuv;
+ sumuv = u+v;
+ if(sumuv<-G_EPSILON)
+ {
+ return false;
+ }
+ else if(sumuv-1.0f>G_EPSILON)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ //! is point in triangle beam?
+ /*!
+ Test if point is in triangle, with m_margin tolerance
+ */
+ SIMD_FORCE_INLINE bool is_point_inside(const btVector3 & point, const btVector3 & tri_normal) const
+ {
+ //Test with edge 0
+ btVector4 edge_plane;
+ this->get_edge_plane(0,tri_normal,edge_plane);
+ GREAL dist = DISTANCE_PLANE_POINT(edge_plane,point);
+ if(dist-m_margin>0.0f) return false; // outside plane
+
+ this->get_edge_plane(1,tri_normal,edge_plane);
+ dist = DISTANCE_PLANE_POINT(edge_plane,point);
+ if(dist-m_margin>0.0f) return false; // outside plane
+
+ this->get_edge_plane(2,tri_normal,edge_plane);
+ dist = DISTANCE_PLANE_POINT(edge_plane,point);
+ if(dist-m_margin>0.0f) return false; // outside plane
+ return true;
+ }
+
+
+ //! Bidireccional ray collision
+ SIMD_FORCE_INLINE bool ray_collision(
+ const btVector3 & vPoint,
+ const btVector3 & vDir, btVector3 & pout, btVector3 & triangle_normal,
+ GREAL & tparam, GREAL tmax = G_REAL_INFINITY)
+ {
+ btVector4 faceplane;
+ {
+ btVector3 dif1 = m_vertices[1] - m_vertices[0];
+ btVector3 dif2 = m_vertices[2] - m_vertices[0];
+ VEC_CROSS(faceplane,dif1,dif2);
+ faceplane[3] = m_vertices[0].dot(faceplane);
+ }
+
+ GUINT res = LINE_PLANE_COLLISION(faceplane,vDir,vPoint,pout,tparam, btScalar(0), tmax);
+ if(res == 0) return false;
+ if(! is_point_inside(pout,faceplane)) return false;
+
+ if(res==2) //invert normal
+ {
+ triangle_normal.setValue(-faceplane[0],-faceplane[1],-faceplane[2]);
+ }
+ else
+ {
+ triangle_normal.setValue(faceplane[0],faceplane[1],faceplane[2]);
+ }
+
+ VEC_NORMALIZE(triangle_normal);
+
+ return true;
+ }
+
+
+ //! one direccion ray collision
+ SIMD_FORCE_INLINE bool ray_collision_front_side(
+ const btVector3 & vPoint,
+ const btVector3 & vDir, btVector3 & pout, btVector3 & triangle_normal,
+ GREAL & tparam, GREAL tmax = G_REAL_INFINITY)
+ {
+ btVector4 faceplane;
+ {
+ btVector3 dif1 = m_vertices[1] - m_vertices[0];
+ btVector3 dif2 = m_vertices[2] - m_vertices[0];
+ VEC_CROSS(faceplane,dif1,dif2);
+ faceplane[3] = m_vertices[0].dot(faceplane);
+ }
+
+ GUINT res = LINE_PLANE_COLLISION(faceplane,vDir,vPoint,pout,tparam, btScalar(0), tmax);
+ if(res != 1) return false;
+
+ if(!is_point_inside(pout,faceplane)) return false;
+
+ triangle_normal.setValue(faceplane[0],faceplane[1],faceplane[2]);
+
+ VEC_NORMALIZE(triangle_normal);
+
+ return true;
+ }
+
+};
+
+
+
+
+#endif // GIM_TRI_COLLISION_H_INCLUDED
diff --git a/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btComputeGjkEpaPenetration.h b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btComputeGjkEpaPenetration.h
new file mode 100644
index 0000000000..9eb880b8df
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btComputeGjkEpaPenetration.h
@@ -0,0 +1,369 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2014 Erwin Coumans 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_GJK_EPA_PENETATION_CONVEX_COLLISION_H
+#define BT_GJK_EPA_PENETATION_CONVEX_COLLISION_H
+
+#include "LinearMath/btTransform.h" // Note that btVector3 might be double precision...
+#include "btGjkEpa3.h"
+#include "btGjkCollisionDescription.h"
+#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
+
+
+
+
+
+
+template <typename btConvexTemplate>
+bool btGjkEpaCalcPenDepth(const btConvexTemplate& a, const btConvexTemplate& b,
+ const btGjkCollisionDescription& colDesc,
+ btVector3& v, btVector3& wWitnessOnA, btVector3& wWitnessOnB)
+{
+ (void)v;
+
+ // const btScalar radialmargin(btScalar(0.));
+
+ btVector3 guessVector(b.getWorldTransform().getOrigin()-a.getWorldTransform().getOrigin());//?? why not use the GJK input?
+
+ btGjkEpaSolver3::sResults results;
+
+
+ if(btGjkEpaSolver3_Penetration(a,b,guessVector,results))
+
+ {
+ // debugDraw->drawLine(results.witnesses[1],results.witnesses[1]+results.normal,btVector3(255,0,0));
+ //resultOut->addContactPoint(results.normal,results.witnesses[1],-results.depth);
+ wWitnessOnA = results.witnesses[0];
+ wWitnessOnB = results.witnesses[1];
+ v = results.normal;
+ return true;
+ } else
+ {
+ if(btGjkEpaSolver3_Distance(a,b,guessVector,results))
+ {
+ wWitnessOnA = results.witnesses[0];
+ wWitnessOnB = results.witnesses[1];
+ v = results.normal;
+ return false;
+ }
+ }
+ return false;
+}
+
+template <typename btConvexTemplate, typename btGjkDistanceTemplate>
+int btComputeGjkEpaPenetration(const btConvexTemplate& a, const btConvexTemplate& b, const btGjkCollisionDescription& colDesc, btVoronoiSimplexSolver& simplexSolver, btGjkDistanceTemplate* distInfo)
+{
+
+ bool m_catchDegeneracies = true;
+ btScalar m_cachedSeparatingDistance = 0.f;
+
+ btScalar distance=btScalar(0.);
+ btVector3 normalInB(btScalar(0.),btScalar(0.),btScalar(0.));
+
+ btVector3 pointOnA,pointOnB;
+ btTransform localTransA = a.getWorldTransform();
+ btTransform localTransB = b.getWorldTransform();
+
+ btScalar marginA = a.getMargin();
+ btScalar marginB = b.getMargin();
+
+ int m_curIter = 0;
+ int gGjkMaxIter = colDesc.m_maxGjkIterations;//this is to catch invalid input, perhaps check for #NaN?
+ btVector3 m_cachedSeparatingAxis = colDesc.m_firstDir;
+
+ bool isValid = false;
+ bool checkSimplex = false;
+ bool checkPenetration = true;
+ int m_degenerateSimplex = 0;
+
+ int m_lastUsedMethod = -1;
+
+ {
+ btScalar squaredDistance = BT_LARGE_FLOAT;
+ btScalar delta = btScalar(0.);
+
+ btScalar margin = marginA + marginB;
+
+
+
+ simplexSolver.reset();
+
+ for ( ; ; )
+ //while (true)
+ {
+
+ btVector3 seperatingAxisInA = (-m_cachedSeparatingAxis)* localTransA.getBasis();
+ btVector3 seperatingAxisInB = m_cachedSeparatingAxis* localTransB.getBasis();
+
+ btVector3 pInA = a.getLocalSupportWithoutMargin(seperatingAxisInA);
+ btVector3 qInB = b.getLocalSupportWithoutMargin(seperatingAxisInB);
+
+ btVector3 pWorld = localTransA(pInA);
+ btVector3 qWorld = localTransB(qInB);
+
+
+
+ btVector3 w = pWorld - qWorld;
+ delta = m_cachedSeparatingAxis.dot(w);
+
+ // potential exit, they don't overlap
+ if ((delta > btScalar(0.0)) && (delta * delta > squaredDistance * colDesc.m_maximumDistanceSquared))
+ {
+ m_degenerateSimplex = 10;
+ checkSimplex=true;
+ //checkPenetration = false;
+ break;
+ }
+
+ //exit 0: the new point is already in the simplex, or we didn't come any closer
+ if (simplexSolver.inSimplex(w))
+ {
+ m_degenerateSimplex = 1;
+ checkSimplex = true;
+ break;
+ }
+ // are we getting any closer ?
+ btScalar f0 = squaredDistance - delta;
+ btScalar f1 = squaredDistance * colDesc.m_gjkRelError2;
+
+ if (f0 <= f1)
+ {
+ if (f0 <= btScalar(0.))
+ {
+ m_degenerateSimplex = 2;
+ } else
+ {
+ m_degenerateSimplex = 11;
+ }
+ checkSimplex = true;
+ break;
+ }
+
+ //add current vertex to simplex
+ simplexSolver.addVertex(w, pWorld, qWorld);
+ btVector3 newCachedSeparatingAxis;
+
+ //calculate the closest point to the origin (update vector v)
+ if (!simplexSolver.closest(newCachedSeparatingAxis))
+ {
+ m_degenerateSimplex = 3;
+ checkSimplex = true;
+ break;
+ }
+
+ if(newCachedSeparatingAxis.length2()<colDesc.m_gjkRelError2)
+ {
+ m_cachedSeparatingAxis = newCachedSeparatingAxis;
+ m_degenerateSimplex = 6;
+ checkSimplex = true;
+ break;
+ }
+
+ btScalar previousSquaredDistance = squaredDistance;
+ squaredDistance = newCachedSeparatingAxis.length2();
+#if 0
+ ///warning: this termination condition leads to some problems in 2d test case see Bullet/Demos/Box2dDemo
+ if (squaredDistance>previousSquaredDistance)
+ {
+ m_degenerateSimplex = 7;
+ squaredDistance = previousSquaredDistance;
+ checkSimplex = false;
+ break;
+ }
+#endif //
+
+
+ //redundant m_simplexSolver->compute_points(pointOnA, pointOnB);
+
+ //are we getting any closer ?
+ if (previousSquaredDistance - squaredDistance <= SIMD_EPSILON * previousSquaredDistance)
+ {
+ // m_simplexSolver->backup_closest(m_cachedSeparatingAxis);
+ checkSimplex = true;
+ m_degenerateSimplex = 12;
+
+ break;
+ }
+
+ m_cachedSeparatingAxis = newCachedSeparatingAxis;
+
+ //degeneracy, this is typically due to invalid/uninitialized worldtransforms for a btCollisionObject
+ if (m_curIter++ > gGjkMaxIter)
+ {
+#if defined(DEBUG) || defined (_DEBUG)
+
+ printf("btGjkPairDetector maxIter exceeded:%i\n",m_curIter);
+ printf("sepAxis=(%f,%f,%f), squaredDistance = %f\n",
+ m_cachedSeparatingAxis.getX(),
+ m_cachedSeparatingAxis.getY(),
+ m_cachedSeparatingAxis.getZ(),
+ squaredDistance);
+#endif
+
+ break;
+
+ }
+
+
+ bool check = (!simplexSolver.fullSimplex());
+ //bool check = (!m_simplexSolver->fullSimplex() && squaredDistance > SIMD_EPSILON * m_simplexSolver->maxVertex());
+
+ if (!check)
+ {
+ //do we need this backup_closest here ?
+ // m_simplexSolver->backup_closest(m_cachedSeparatingAxis);
+ m_degenerateSimplex = 13;
+ break;
+ }
+ }
+
+ if (checkSimplex)
+ {
+ simplexSolver.compute_points(pointOnA, pointOnB);
+ normalInB = m_cachedSeparatingAxis;
+
+ btScalar lenSqr =m_cachedSeparatingAxis.length2();
+
+ //valid normal
+ if (lenSqr < 0.0001)
+ {
+ m_degenerateSimplex = 5;
+ }
+ if (lenSqr > SIMD_EPSILON*SIMD_EPSILON)
+ {
+ btScalar rlen = btScalar(1.) / btSqrt(lenSqr );
+ normalInB *= rlen; //normalize
+
+ btScalar s = btSqrt(squaredDistance);
+
+ btAssert(s > btScalar(0.0));
+ pointOnA -= m_cachedSeparatingAxis * (marginA / s);
+ pointOnB += m_cachedSeparatingAxis * (marginB / s);
+ distance = ((btScalar(1.)/rlen) - margin);
+ isValid = true;
+
+ m_lastUsedMethod = 1;
+ } else
+ {
+ m_lastUsedMethod = 2;
+ }
+ }
+
+ bool catchDegeneratePenetrationCase =
+ (m_catchDegeneracies && m_degenerateSimplex && ((distance+margin) < 0.01));
+
+ //if (checkPenetration && !isValid)
+ if (checkPenetration && (!isValid || catchDegeneratePenetrationCase ))
+ {
+ //penetration case
+
+ //if there is no way to handle penetrations, bail out
+
+ // Penetration depth case.
+ btVector3 tmpPointOnA,tmpPointOnB;
+
+ m_cachedSeparatingAxis.setZero();
+
+ bool isValid2 = btGjkEpaCalcPenDepth(a,b,
+ colDesc,
+ m_cachedSeparatingAxis, tmpPointOnA, tmpPointOnB);
+
+ if (isValid2)
+ {
+ btVector3 tmpNormalInB = tmpPointOnB-tmpPointOnA;
+ btScalar lenSqr = tmpNormalInB.length2();
+ if (lenSqr <= (SIMD_EPSILON*SIMD_EPSILON))
+ {
+ tmpNormalInB = m_cachedSeparatingAxis;
+ lenSqr = m_cachedSeparatingAxis.length2();
+ }
+
+ if (lenSqr > (SIMD_EPSILON*SIMD_EPSILON))
+ {
+ tmpNormalInB /= btSqrt(lenSqr);
+ btScalar distance2 = -(tmpPointOnA-tmpPointOnB).length();
+ //only replace valid penetrations when the result is deeper (check)
+ if (!isValid || (distance2 < distance))
+ {
+ distance = distance2;
+ pointOnA = tmpPointOnA;
+ pointOnB = tmpPointOnB;
+ normalInB = tmpNormalInB;
+
+ isValid = true;
+ m_lastUsedMethod = 3;
+ } else
+ {
+ m_lastUsedMethod = 8;
+ }
+ } else
+ {
+ m_lastUsedMethod = 9;
+ }
+ } else
+
+ {
+ ///this is another degenerate case, where the initial GJK calculation reports a degenerate case
+ ///EPA reports no penetration, and the second GJK (using the supporting vector without margin)
+ ///reports a valid positive distance. Use the results of the second GJK instead of failing.
+ ///thanks to Jacob.Langford for the reproduction case
+ ///http://code.google.com/p/bullet/issues/detail?id=250
+
+
+ if (m_cachedSeparatingAxis.length2() > btScalar(0.))
+ {
+ btScalar distance2 = (tmpPointOnA-tmpPointOnB).length()-margin;
+ //only replace valid distances when the distance is less
+ if (!isValid || (distance2 < distance))
+ {
+ distance = distance2;
+ pointOnA = tmpPointOnA;
+ pointOnB = tmpPointOnB;
+ pointOnA -= m_cachedSeparatingAxis * marginA ;
+ pointOnB += m_cachedSeparatingAxis * marginB ;
+ normalInB = m_cachedSeparatingAxis;
+ normalInB.normalize();
+
+ isValid = true;
+ m_lastUsedMethod = 6;
+ } else
+ {
+ m_lastUsedMethod = 5;
+ }
+ }
+ }
+ }
+ }
+
+
+
+ if (isValid && ((distance < 0) || (distance*distance < colDesc.m_maximumDistanceSquared)))
+ {
+
+ m_cachedSeparatingAxis = normalInB;
+ m_cachedSeparatingDistance = distance;
+ distInfo->m_distance = distance;
+ distInfo->m_normalBtoA = normalInB;
+ distInfo->m_pointOnB = pointOnB;
+ distInfo->m_pointOnA = pointOnB+normalInB*distance;
+ return 0;
+ }
+ return -m_lastUsedMethod;
+}
+
+
+
+
+#endif //BT_GJK_EPA_PENETATION_CONVEX_COLLISION_H
diff --git a/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp
new file mode 100644
index 0000000000..940282f576
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp
@@ -0,0 +1,242 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "btContinuousConvexCollision.h"
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+#include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h"
+#include "LinearMath/btTransformUtil.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"
+
+#include "btGjkPairDetector.h"
+#include "btPointCollector.h"
+#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h"
+
+
+
+btContinuousConvexCollision::btContinuousConvexCollision ( const btConvexShape* convexA,const btConvexShape* convexB,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* penetrationDepthSolver)
+:m_simplexSolver(simplexSolver),
+m_penetrationDepthSolver(penetrationDepthSolver),
+m_convexA(convexA),m_convexB1(convexB),m_planeShape(0)
+{
+}
+
+
+btContinuousConvexCollision::btContinuousConvexCollision( const btConvexShape* convexA,const btStaticPlaneShape* plane)
+:m_simplexSolver(0),
+m_penetrationDepthSolver(0),
+m_convexA(convexA),m_convexB1(0),m_planeShape(plane)
+{
+}
+
+
+/// This maximum should not be necessary. It allows for untested/degenerate cases in production code.
+/// You don't want your game ever to lock-up.
+#define MAX_ITERATIONS 64
+
+void btContinuousConvexCollision::computeClosestPoints( const btTransform& transA, const btTransform& transB,btPointCollector& pointCollector)
+{
+ if (m_convexB1)
+ {
+ m_simplexSolver->reset();
+ btGjkPairDetector gjk(m_convexA,m_convexB1,m_convexA->getShapeType(),m_convexB1->getShapeType(),m_convexA->getMargin(),m_convexB1->getMargin(),m_simplexSolver,m_penetrationDepthSolver);
+ btGjkPairDetector::ClosestPointInput input;
+ input.m_transformA = transA;
+ input.m_transformB = transB;
+ gjk.getClosestPoints(input,pointCollector,0);
+ } else
+ {
+ //convex versus plane
+ const btConvexShape* convexShape = m_convexA;
+ const btStaticPlaneShape* planeShape = m_planeShape;
+
+ const btVector3& planeNormal = planeShape->getPlaneNormal();
+ const btScalar& planeConstant = planeShape->getPlaneConstant();
+
+ btTransform convexWorldTransform = transA;
+ btTransform convexInPlaneTrans;
+ convexInPlaneTrans= transB.inverse() * convexWorldTransform;
+ btTransform planeInConvex;
+ planeInConvex= convexWorldTransform.inverse() * transB;
+
+ btVector3 vtx = convexShape->localGetSupportingVertex(planeInConvex.getBasis()*-planeNormal);
+
+ btVector3 vtxInPlane = convexInPlaneTrans(vtx);
+ btScalar distance = (planeNormal.dot(vtxInPlane) - planeConstant);
+
+ btVector3 vtxInPlaneProjected = vtxInPlane - distance*planeNormal;
+ btVector3 vtxInPlaneWorld = transB * vtxInPlaneProjected;
+ btVector3 normalOnSurfaceB = transB.getBasis() * planeNormal;
+
+ pointCollector.addContactPoint(
+ normalOnSurfaceB,
+ vtxInPlaneWorld,
+ distance);
+ }
+}
+
+bool btContinuousConvexCollision::calcTimeOfImpact(
+ const btTransform& fromA,
+ const btTransform& toA,
+ const btTransform& fromB,
+ const btTransform& toB,
+ CastResult& result)
+{
+
+
+ /// compute linear and angular velocity for this interval, to interpolate
+ btVector3 linVelA,angVelA,linVelB,angVelB;
+ btTransformUtil::calculateVelocity(fromA,toA,btScalar(1.),linVelA,angVelA);
+ btTransformUtil::calculateVelocity(fromB,toB,btScalar(1.),linVelB,angVelB);
+
+
+ btScalar boundingRadiusA = m_convexA->getAngularMotionDisc();
+ btScalar boundingRadiusB = m_convexB1?m_convexB1->getAngularMotionDisc():0.f;
+
+ btScalar maxAngularProjectedVelocity = angVelA.length() * boundingRadiusA + angVelB.length() * boundingRadiusB;
+ btVector3 relLinVel = (linVelB-linVelA);
+
+ btScalar relLinVelocLength = (linVelB-linVelA).length();
+
+ if ((relLinVelocLength+maxAngularProjectedVelocity) == 0.f)
+ return false;
+
+
+
+ btScalar lambda = btScalar(0.);
+ btVector3 v(1,0,0);
+
+ int maxIter = MAX_ITERATIONS;
+
+ btVector3 n;
+ n.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
+ bool hasResult = false;
+ btVector3 c;
+
+ btScalar lastLambda = lambda;
+ //btScalar epsilon = btScalar(0.001);
+
+ int numIter = 0;
+ //first solution, using GJK
+
+
+ btScalar radius = 0.001f;
+// result.drawCoordSystem(sphereTr);
+
+ btPointCollector pointCollector1;
+
+ {
+
+ computeClosestPoints(fromA,fromB,pointCollector1);
+
+ hasResult = pointCollector1.m_hasResult;
+ c = pointCollector1.m_pointInWorld;
+ }
+
+ if (hasResult)
+ {
+ btScalar dist;
+ dist = pointCollector1.m_distance + result.m_allowedPenetration;
+ n = pointCollector1.m_normalOnBInWorld;
+ btScalar projectedLinearVelocity = relLinVel.dot(n);
+ if ((projectedLinearVelocity+ maxAngularProjectedVelocity)<=SIMD_EPSILON)
+ return false;
+
+ //not close enough
+ while (dist > radius)
+ {
+ if (result.m_debugDrawer)
+ {
+ result.m_debugDrawer->drawSphere(c,0.2f,btVector3(1,1,1));
+ }
+ btScalar dLambda = btScalar(0.);
+
+ projectedLinearVelocity = relLinVel.dot(n);
+
+
+ //don't report time of impact for motion away from the contact normal (or causes minor penetration)
+ if ((projectedLinearVelocity+ maxAngularProjectedVelocity)<=SIMD_EPSILON)
+ return false;
+
+ dLambda = dist / (projectedLinearVelocity+ maxAngularProjectedVelocity);
+
+
+
+ lambda = lambda + dLambda;
+
+ if (lambda > btScalar(1.))
+ return false;
+
+ if (lambda < btScalar(0.))
+ return false;
+
+
+ //todo: next check with relative epsilon
+ if (lambda <= lastLambda)
+ {
+ return false;
+ //n.setValue(0,0,0);
+ break;
+ }
+ lastLambda = lambda;
+
+
+
+ //interpolate to next lambda
+ btTransform interpolatedTransA,interpolatedTransB,relativeTrans;
+
+ btTransformUtil::integrateTransform(fromA,linVelA,angVelA,lambda,interpolatedTransA);
+ btTransformUtil::integrateTransform(fromB,linVelB,angVelB,lambda,interpolatedTransB);
+ relativeTrans = interpolatedTransB.inverseTimes(interpolatedTransA);
+
+ if (result.m_debugDrawer)
+ {
+ result.m_debugDrawer->drawSphere(interpolatedTransA.getOrigin(),0.2f,btVector3(1,0,0));
+ }
+
+ result.DebugDraw( lambda );
+
+ btPointCollector pointCollector;
+ computeClosestPoints(interpolatedTransA,interpolatedTransB,pointCollector);
+
+ if (pointCollector.m_hasResult)
+ {
+ dist = pointCollector.m_distance+result.m_allowedPenetration;
+ c = pointCollector.m_pointInWorld;
+ n = pointCollector.m_normalOnBInWorld;
+ } else
+ {
+ result.reportFailure(-1, numIter);
+ return false;
+ }
+
+ numIter++;
+ if (numIter > maxIter)
+ {
+ result.reportFailure(-2, numIter);
+ return false;
+ }
+ }
+
+ result.m_fraction = lambda;
+ result.m_normal = n;
+ result.m_hitPoint = c;
+ return true;
+ }
+
+ return false;
+
+}
+
diff --git a/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h
new file mode 100644
index 0000000000..bdc0572f75
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h
@@ -0,0 +1,59 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#ifndef BT_CONTINUOUS_COLLISION_CONVEX_CAST_H
+#define BT_CONTINUOUS_COLLISION_CONVEX_CAST_H
+
+#include "btConvexCast.h"
+#include "btSimplexSolverInterface.h"
+class btConvexPenetrationDepthSolver;
+class btConvexShape;
+class btStaticPlaneShape;
+
+/// btContinuousConvexCollision implements angular and linear time of impact for convex objects.
+/// Based on Brian Mirtich's Conservative Advancement idea (PhD thesis).
+/// Algorithm operates in worldspace, in order to keep inbetween motion globally consistent.
+/// It uses GJK at the moment. Future improvement would use minkowski sum / supporting vertex, merging innerloops
+class btContinuousConvexCollision : public btConvexCast
+{
+ btSimplexSolverInterface* m_simplexSolver;
+ btConvexPenetrationDepthSolver* m_penetrationDepthSolver;
+ const btConvexShape* m_convexA;
+ //second object is either a convex or a plane (code sharing)
+ const btConvexShape* m_convexB1;
+ const btStaticPlaneShape* m_planeShape;
+
+ void computeClosestPoints( const btTransform& transA, const btTransform& transB,struct btPointCollector& pointCollector);
+
+public:
+
+ btContinuousConvexCollision (const btConvexShape* shapeA,const btConvexShape* shapeB ,btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver* penetrationDepthSolver);
+
+ btContinuousConvexCollision(const btConvexShape* shapeA,const btStaticPlaneShape* plane );
+
+ virtual bool calcTimeOfImpact(
+ const btTransform& fromA,
+ const btTransform& toA,
+ const btTransform& fromB,
+ const btTransform& toB,
+ CastResult& result);
+
+
+};
+
+
+#endif //BT_CONTINUOUS_COLLISION_CONVEX_CAST_H
+
diff --git a/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btConvexCast.cpp b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btConvexCast.cpp
new file mode 100644
index 0000000000..d2a1310b23
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btConvexCast.cpp
@@ -0,0 +1,20 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btConvexCast.h"
+
+btConvexCast::~btConvexCast()
+{
+}
diff --git a/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btConvexCast.h b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btConvexCast.h
new file mode 100644
index 0000000000..bfd79d03be
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btConvexCast.h
@@ -0,0 +1,73 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#ifndef BT_CONVEX_CAST_H
+#define BT_CONVEX_CAST_H
+
+#include "LinearMath/btTransform.h"
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btScalar.h"
+class btMinkowskiSumShape;
+#include "LinearMath/btIDebugDraw.h"
+
+/// btConvexCast is an interface for Casting
+class btConvexCast
+{
+public:
+
+
+ virtual ~btConvexCast();
+
+ ///RayResult stores the closest result
+ /// alternatively, add a callback method to decide about closest/all results
+ struct CastResult
+ {
+ //virtual bool addRayResult(const btVector3& normal,btScalar fraction) = 0;
+
+ virtual void DebugDraw(btScalar fraction) {(void)fraction;}
+ virtual void drawCoordSystem(const btTransform& trans) {(void)trans;}
+ virtual void reportFailure(int errNo, int numIterations) {(void)errNo;(void)numIterations;}
+ CastResult()
+ :m_fraction(btScalar(BT_LARGE_FLOAT)),
+ m_debugDrawer(0),
+ m_allowedPenetration(btScalar(0))
+ {
+ }
+
+
+ virtual ~CastResult() {};
+
+ btTransform m_hitTransformA;
+ btTransform m_hitTransformB;
+ btVector3 m_normal;
+ btVector3 m_hitPoint;
+ btScalar m_fraction; //input and output
+ btIDebugDraw* m_debugDrawer;
+ btScalar m_allowedPenetration;
+
+ };
+
+
+ /// cast a convex against another convex object
+ virtual bool calcTimeOfImpact(
+ const btTransform& fromA,
+ const btTransform& toA,
+ const btTransform& fromB,
+ const btTransform& toB,
+ CastResult& result) = 0;
+};
+
+#endif //BT_CONVEX_CAST_H
diff --git a/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h
new file mode 100644
index 0000000000..29620abffb
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h
@@ -0,0 +1,40 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#ifndef BT_CONVEX_PENETRATION_DEPTH_H
+#define BT_CONVEX_PENETRATION_DEPTH_H
+
+class btVector3;
+#include "btSimplexSolverInterface.h"
+class btConvexShape;
+class btTransform;
+
+///ConvexPenetrationDepthSolver provides an interface for penetration depth calculation.
+class btConvexPenetrationDepthSolver
+{
+public:
+
+ virtual ~btConvexPenetrationDepthSolver() {};
+ virtual bool calcPenDepth( btSimplexSolverInterface& simplexSolver,
+ const btConvexShape* convexA,const btConvexShape* convexB,
+ const btTransform& transA,const btTransform& transB,
+ btVector3& v, btVector3& pa, btVector3& pb,
+ class btIDebugDraw* debugDraw) = 0;
+
+
+};
+#endif //BT_CONVEX_PENETRATION_DEPTH_H
+
diff --git a/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h
new file mode 100644
index 0000000000..0ea7b483cf
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h
@@ -0,0 +1,90 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#ifndef BT_DISCRETE_COLLISION_DETECTOR1_INTERFACE_H
+#define BT_DISCRETE_COLLISION_DETECTOR1_INTERFACE_H
+
+#include "LinearMath/btTransform.h"
+#include "LinearMath/btVector3.h"
+
+/// This interface is made to be used by an iterative approach to do TimeOfImpact calculations
+/// This interface allows to query for closest points and penetration depth between two (convex) objects
+/// the closest point is on the second object (B), and the normal points from the surface on B towards A.
+/// distance is between closest points on B and closest point on A. So you can calculate closest point on A
+/// by taking closestPointInA = closestPointInB + m_distance * m_normalOnSurfaceB
+struct btDiscreteCollisionDetectorInterface
+{
+
+ struct Result
+ {
+
+ virtual ~Result(){}
+
+ ///setShapeIdentifiersA/B provides experimental support for per-triangle material / custom material combiner
+ virtual void setShapeIdentifiersA(int partId0,int index0)=0;
+ virtual void setShapeIdentifiersB(int partId1,int index1)=0;
+ virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth)=0;
+ };
+
+ struct ClosestPointInput
+ {
+ ClosestPointInput()
+ :m_maximumDistanceSquared(btScalar(BT_LARGE_FLOAT))
+ {
+ }
+
+ btTransform m_transformA;
+ btTransform m_transformB;
+ btScalar m_maximumDistanceSquared;
+ };
+
+ virtual ~btDiscreteCollisionDetectorInterface() {};
+
+ //
+ // give either closest points (distance > 0) or penetration (distance)
+ // the normal always points from B towards A
+ //
+ virtual void getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults=false) = 0;
+
+};
+
+struct btStorageResult : public btDiscreteCollisionDetectorInterface::Result
+{
+ btVector3 m_normalOnSurfaceB;
+ btVector3 m_closestPointInB;
+ btScalar m_distance; //negative means penetration !
+
+ protected:
+ btStorageResult() : m_distance(btScalar(BT_LARGE_FLOAT))
+ {
+ }
+
+ public:
+ virtual ~btStorageResult() {};
+
+ virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth)
+ {
+ if (depth < m_distance)
+ {
+ m_normalOnSurfaceB = normalOnBInWorld;
+ m_closestPointInB = pointInWorld;
+ m_distance = depth;
+ }
+ }
+};
+
+#endif //BT_DISCRETE_COLLISION_DETECTOR1_INTERFACE_H
+
diff --git a/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btGjkCollisionDescription.h b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btGjkCollisionDescription.h
new file mode 100644
index 0000000000..0b49b0ecc6
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btGjkCollisionDescription.h
@@ -0,0 +1,41 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2014 Erwin Coumans 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 GJK_COLLISION_DESCRIPTION_H
+#define GJK_COLLISION_DESCRIPTION_H
+
+#include "LinearMath/btVector3.h"
+
+struct btGjkCollisionDescription
+{
+ btVector3 m_firstDir;
+ int m_maxGjkIterations;
+ btScalar m_maximumDistanceSquared;
+ btScalar m_gjkRelError2;
+ btGjkCollisionDescription()
+ :m_firstDir(0,1,0),
+ m_maxGjkIterations(1000),
+ m_maximumDistanceSquared(1e30f),
+ m_gjkRelError2(1.0e-6)
+ {
+ }
+ virtual ~btGjkCollisionDescription()
+ {
+ }
+};
+
+#endif //GJK_COLLISION_DESCRIPTION_H
+
diff --git a/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp
new file mode 100644
index 0000000000..bef697a0a1
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp
@@ -0,0 +1,176 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+#include "btGjkConvexCast.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"
+#include "btGjkPairDetector.h"
+#include "btPointCollector.h"
+#include "LinearMath/btTransformUtil.h"
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define MAX_ITERATIONS 64
+#else
+#define MAX_ITERATIONS 32
+#endif
+
+btGjkConvexCast::btGjkConvexCast(const btConvexShape* convexA,const btConvexShape* convexB,btSimplexSolverInterface* simplexSolver)
+:m_simplexSolver(simplexSolver),
+m_convexA(convexA),
+m_convexB(convexB)
+{
+}
+
+bool btGjkConvexCast::calcTimeOfImpact(
+ const btTransform& fromA,
+ const btTransform& toA,
+ const btTransform& fromB,
+ const btTransform& toB,
+ CastResult& result)
+{
+
+
+ m_simplexSolver->reset();
+
+ /// compute linear velocity for this interval, to interpolate
+ //assume no rotation/angular velocity, assert here?
+ btVector3 linVelA,linVelB;
+ linVelA = toA.getOrigin()-fromA.getOrigin();
+ linVelB = toB.getOrigin()-fromB.getOrigin();
+
+ btScalar radius = btScalar(0.001);
+ btScalar lambda = btScalar(0.);
+ btVector3 v(1,0,0);
+
+ int maxIter = MAX_ITERATIONS;
+
+ btVector3 n;
+ n.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
+ bool hasResult = false;
+ btVector3 c;
+ btVector3 r = (linVelA-linVelB);
+
+ btScalar lastLambda = lambda;
+ //btScalar epsilon = btScalar(0.001);
+
+ int numIter = 0;
+ //first solution, using GJK
+
+
+ btTransform identityTrans;
+ identityTrans.setIdentity();
+
+
+// result.drawCoordSystem(sphereTr);
+
+ btPointCollector pointCollector;
+
+
+ btGjkPairDetector gjk(m_convexA,m_convexB,m_simplexSolver,0);//m_penetrationDepthSolver);
+ btGjkPairDetector::ClosestPointInput input;
+
+ //we don't use margins during CCD
+ // gjk.setIgnoreMargin(true);
+
+ input.m_transformA = fromA;
+ input.m_transformB = fromB;
+ gjk.getClosestPoints(input,pointCollector,0);
+
+ hasResult = pointCollector.m_hasResult;
+ c = pointCollector.m_pointInWorld;
+
+ if (hasResult)
+ {
+ btScalar dist;
+ dist = pointCollector.m_distance;
+ n = pointCollector.m_normalOnBInWorld;
+
+
+
+ //not close enough
+ while (dist > radius)
+ {
+ numIter++;
+ if (numIter > maxIter)
+ {
+ return false; //todo: report a failure
+ }
+ btScalar dLambda = btScalar(0.);
+
+ btScalar projectedLinearVelocity = r.dot(n);
+
+ dLambda = dist / (projectedLinearVelocity);
+
+ lambda = lambda - dLambda;
+
+ if (lambda > btScalar(1.))
+ return false;
+
+ if (lambda < btScalar(0.))
+ return false;
+
+ //todo: next check with relative epsilon
+ if (lambda <= lastLambda)
+ {
+ return false;
+ //n.setValue(0,0,0);
+ break;
+ }
+ lastLambda = lambda;
+
+ //interpolate to next lambda
+ result.DebugDraw( lambda );
+ input.m_transformA.getOrigin().setInterpolate3(fromA.getOrigin(),toA.getOrigin(),lambda);
+ input.m_transformB.getOrigin().setInterpolate3(fromB.getOrigin(),toB.getOrigin(),lambda);
+
+ gjk.getClosestPoints(input,pointCollector,0);
+ if (pointCollector.m_hasResult)
+ {
+ if (pointCollector.m_distance < btScalar(0.))
+ {
+ result.m_fraction = lastLambda;
+ n = pointCollector.m_normalOnBInWorld;
+ result.m_normal=n;
+ result.m_hitPoint = pointCollector.m_pointInWorld;
+ return true;
+ }
+ c = pointCollector.m_pointInWorld;
+ n = pointCollector.m_normalOnBInWorld;
+ dist = pointCollector.m_distance;
+ } else
+ {
+ //??
+ return false;
+ }
+
+ }
+
+ //is n normalized?
+ //don't report time of impact for motion away from the contact normal (or causes minor penetration)
+ if (n.dot(r)>=-result.m_allowedPenetration)
+ return false;
+
+ result.m_fraction = lambda;
+ result.m_normal = n;
+ result.m_hitPoint = c;
+ return true;
+ }
+
+ return false;
+
+
+}
+
diff --git a/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h
new file mode 100644
index 0000000000..6a42ee63b0
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h
@@ -0,0 +1,50 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+#ifndef BT_GJK_CONVEX_CAST_H
+#define BT_GJK_CONVEX_CAST_H
+
+#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
+
+#include "LinearMath/btVector3.h"
+#include "btConvexCast.h"
+class btConvexShape;
+class btMinkowskiSumShape;
+#include "btSimplexSolverInterface.h"
+
+///GjkConvexCast performs a raycast on a convex object using support mapping.
+class btGjkConvexCast : public btConvexCast
+{
+ btSimplexSolverInterface* m_simplexSolver;
+ const btConvexShape* m_convexA;
+ const btConvexShape* m_convexB;
+
+public:
+
+ btGjkConvexCast(const btConvexShape* convexA,const btConvexShape* convexB,btSimplexSolverInterface* simplexSolver);
+
+ /// cast a convex against another convex object
+ virtual bool calcTimeOfImpact(
+ const btTransform& fromA,
+ const btTransform& toA,
+ const btTransform& fromB,
+ const btTransform& toB,
+ CastResult& result);
+
+};
+
+#endif //BT_GJK_CONVEX_CAST_H
diff --git a/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp
new file mode 100644
index 0000000000..eefb974bbd
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp
@@ -0,0 +1,1048 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2008 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the
+use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+claim that you wrote the original software. If you use this software in a
+product, an acknowledgment in the product documentation would be appreciated
+but is not required.
+2. Altered source versions must be plainly marked as such, and must not be
+misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+/*
+GJK-EPA collision solver by Nathanael Presson, 2008
+*/
+#include "BulletCollision/CollisionShapes/btConvexInternalShape.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"
+#include "btGjkEpa2.h"
+
+#if defined(DEBUG) || defined (_DEBUG)
+#include <stdio.h> //for debug printf
+#ifdef __SPU__
+#include <spu_printf.h>
+#define printf spu_printf
+#endif //__SPU__
+#endif
+
+namespace gjkepa2_impl
+{
+
+ // Config
+
+ /* GJK */
+#define GJK_MAX_ITERATIONS 128
+
+#ifdef BT_USE_DOUBLE_PRECISION
+ #define GJK_ACCURACY ((btScalar)1e-12)
+ #define GJK_MIN_DISTANCE ((btScalar)1e-12)
+ #define GJK_DUPLICATED_EPS ((btScalar)1e-12)
+#else
+ #define GJK_ACCURACY ((btScalar)0.0001)
+ #define GJK_MIN_DISTANCE ((btScalar)0.0001)
+ #define GJK_DUPLICATED_EPS ((btScalar)0.0001)
+#endif //BT_USE_DOUBLE_PRECISION
+
+
+#define GJK_SIMPLEX2_EPS ((btScalar)0.0)
+#define GJK_SIMPLEX3_EPS ((btScalar)0.0)
+#define GJK_SIMPLEX4_EPS ((btScalar)0.0)
+
+ /* EPA */
+#define EPA_MAX_VERTICES 128
+#define EPA_MAX_ITERATIONS 255
+
+#ifdef BT_USE_DOUBLE_PRECISION
+ #define EPA_ACCURACY ((btScalar)1e-12)
+ #define EPA_PLANE_EPS ((btScalar)1e-14)
+ #define EPA_INSIDE_EPS ((btScalar)1e-9)
+#else
+ #define EPA_ACCURACY ((btScalar)0.0001)
+ #define EPA_PLANE_EPS ((btScalar)0.00001)
+ #define EPA_INSIDE_EPS ((btScalar)0.01)
+#endif
+
+#define EPA_FALLBACK (10*EPA_ACCURACY)
+#define EPA_MAX_FACES (EPA_MAX_VERTICES*2)
+
+
+ // Shorthands
+ typedef unsigned int U;
+ typedef unsigned char U1;
+
+ // MinkowskiDiff
+ struct MinkowskiDiff
+ {
+ const btConvexShape* m_shapes[2];
+ btMatrix3x3 m_toshape1;
+ btTransform m_toshape0;
+#ifdef __SPU__
+ bool m_enableMargin;
+#else
+ btVector3 (btConvexShape::*Ls)(const btVector3&) const;
+#endif//__SPU__
+
+
+ MinkowskiDiff()
+ {
+
+ }
+#ifdef __SPU__
+ void EnableMargin(bool enable)
+ {
+ m_enableMargin = enable;
+ }
+ inline btVector3 Support0(const btVector3& d) const
+ {
+ if (m_enableMargin)
+ {
+ return m_shapes[0]->localGetSupportVertexNonVirtual(d);
+ } else
+ {
+ return m_shapes[0]->localGetSupportVertexWithoutMarginNonVirtual(d);
+ }
+ }
+ inline btVector3 Support1(const btVector3& d) const
+ {
+ if (m_enableMargin)
+ {
+ return m_toshape0*(m_shapes[1]->localGetSupportVertexNonVirtual(m_toshape1*d));
+ } else
+ {
+ return m_toshape0*(m_shapes[1]->localGetSupportVertexWithoutMarginNonVirtual(m_toshape1*d));
+ }
+ }
+#else
+ void EnableMargin(bool enable)
+ {
+ if(enable)
+ Ls=&btConvexShape::localGetSupportVertexNonVirtual;
+ else
+ Ls=&btConvexShape::localGetSupportVertexWithoutMarginNonVirtual;
+ }
+ inline btVector3 Support0(const btVector3& d) const
+ {
+ return(((m_shapes[0])->*(Ls))(d));
+ }
+ inline btVector3 Support1(const btVector3& d) const
+ {
+ return(m_toshape0*((m_shapes[1])->*(Ls))(m_toshape1*d));
+ }
+#endif //__SPU__
+
+ inline btVector3 Support(const btVector3& d) const
+ {
+ return(Support0(d)-Support1(-d));
+ }
+ btVector3 Support(const btVector3& d,U index) const
+ {
+ if(index)
+ return(Support1(d));
+ else
+ return(Support0(d));
+ }
+ };
+
+ typedef MinkowskiDiff tShape;
+
+
+ // GJK
+ struct GJK
+ {
+ /* Types */
+ struct sSV
+ {
+ btVector3 d,w;
+ };
+ struct sSimplex
+ {
+ sSV* c[4];
+ btScalar p[4];
+ U rank;
+ };
+ struct eStatus { enum _ {
+ Valid,
+ Inside,
+ Failed };};
+ /* Fields */
+ tShape m_shape;
+ btVector3 m_ray;
+ btScalar m_distance;
+ sSimplex m_simplices[2];
+ sSV m_store[4];
+ sSV* m_free[4];
+ U m_nfree;
+ U m_current;
+ sSimplex* m_simplex;
+ eStatus::_ m_status;
+ /* Methods */
+ GJK()
+ {
+ Initialize();
+ }
+ void Initialize()
+ {
+ m_ray = btVector3(0,0,0);
+ m_nfree = 0;
+ m_status = eStatus::Failed;
+ m_current = 0;
+ m_distance = 0;
+ }
+ eStatus::_ Evaluate(const tShape& shapearg,const btVector3& guess)
+ {
+ U iterations=0;
+ btScalar sqdist=0;
+ btScalar alpha=0;
+ btVector3 lastw[4];
+ U clastw=0;
+ /* Initialize solver */
+ m_free[0] = &m_store[0];
+ m_free[1] = &m_store[1];
+ m_free[2] = &m_store[2];
+ m_free[3] = &m_store[3];
+ m_nfree = 4;
+ m_current = 0;
+ m_status = eStatus::Valid;
+ m_shape = shapearg;
+ m_distance = 0;
+ /* Initialize simplex */
+ m_simplices[0].rank = 0;
+ m_ray = guess;
+ const btScalar sqrl= m_ray.length2();
+ appendvertice(m_simplices[0],sqrl>0?-m_ray:btVector3(1,0,0));
+ m_simplices[0].p[0] = 1;
+ m_ray = m_simplices[0].c[0]->w;
+ sqdist = sqrl;
+ lastw[0] =
+ lastw[1] =
+ lastw[2] =
+ lastw[3] = m_ray;
+ /* Loop */
+ do {
+ const U next=1-m_current;
+ sSimplex& cs=m_simplices[m_current];
+ sSimplex& ns=m_simplices[next];
+ /* Check zero */
+ const btScalar rl=m_ray.length();
+ if(rl<GJK_MIN_DISTANCE)
+ {/* Touching or inside */
+ m_status=eStatus::Inside;
+ break;
+ }
+ /* Append new vertice in -'v' direction */
+ appendvertice(cs,-m_ray);
+ const btVector3& w=cs.c[cs.rank-1]->w;
+ bool found=false;
+ for(U i=0;i<4;++i)
+ {
+ if((w-lastw[i]).length2()<GJK_DUPLICATED_EPS)
+ { found=true;break; }
+ }
+ if(found)
+ {/* Return old simplex */
+ removevertice(m_simplices[m_current]);
+ break;
+ }
+ else
+ {/* Update lastw */
+ lastw[clastw=(clastw+1)&3]=w;
+ }
+ /* Check for termination */
+ const btScalar omega=btDot(m_ray,w)/rl;
+ alpha=btMax(omega,alpha);
+ if(((rl-alpha)-(GJK_ACCURACY*rl))<=0)
+ {/* Return old simplex */
+ removevertice(m_simplices[m_current]);
+ break;
+ }
+ /* Reduce simplex */
+ btScalar weights[4];
+ U mask=0;
+ switch(cs.rank)
+ {
+ case 2: sqdist=projectorigin( cs.c[0]->w,
+ cs.c[1]->w,
+ weights,mask);break;
+ case 3: sqdist=projectorigin( cs.c[0]->w,
+ cs.c[1]->w,
+ cs.c[2]->w,
+ weights,mask);break;
+ case 4: sqdist=projectorigin( cs.c[0]->w,
+ cs.c[1]->w,
+ cs.c[2]->w,
+ cs.c[3]->w,
+ weights,mask);break;
+ }
+ if(sqdist>=0)
+ {/* Valid */
+ ns.rank = 0;
+ m_ray = btVector3(0,0,0);
+ m_current = next;
+ for(U i=0,ni=cs.rank;i<ni;++i)
+ {
+ if(mask&(1<<i))
+ {
+ ns.c[ns.rank] = cs.c[i];
+ ns.p[ns.rank++] = weights[i];
+ m_ray += cs.c[i]->w*weights[i];
+ }
+ else
+ {
+ m_free[m_nfree++] = cs.c[i];
+ }
+ }
+ if(mask==15) m_status=eStatus::Inside;
+ }
+ else
+ {/* Return old simplex */
+ removevertice(m_simplices[m_current]);
+ break;
+ }
+ m_status=((++iterations)<GJK_MAX_ITERATIONS)?m_status:eStatus::Failed;
+ } while(m_status==eStatus::Valid);
+ m_simplex=&m_simplices[m_current];
+ switch(m_status)
+ {
+ case eStatus::Valid: m_distance=m_ray.length();break;
+ case eStatus::Inside: m_distance=0;break;
+ default:
+ {
+ }
+ }
+ return(m_status);
+ }
+ bool EncloseOrigin()
+ {
+ switch(m_simplex->rank)
+ {
+ case 1:
+ {
+ for(U i=0;i<3;++i)
+ {
+ btVector3 axis=btVector3(0,0,0);
+ axis[i]=1;
+ appendvertice(*m_simplex, axis);
+ if(EncloseOrigin()) return(true);
+ removevertice(*m_simplex);
+ appendvertice(*m_simplex,-axis);
+ if(EncloseOrigin()) return(true);
+ removevertice(*m_simplex);
+ }
+ }
+ break;
+ case 2:
+ {
+ const btVector3 d=m_simplex->c[1]->w-m_simplex->c[0]->w;
+ for(U i=0;i<3;++i)
+ {
+ btVector3 axis=btVector3(0,0,0);
+ axis[i]=1;
+ const btVector3 p=btCross(d,axis);
+ if(p.length2()>0)
+ {
+ appendvertice(*m_simplex, p);
+ if(EncloseOrigin()) return(true);
+ removevertice(*m_simplex);
+ appendvertice(*m_simplex,-p);
+ if(EncloseOrigin()) return(true);
+ removevertice(*m_simplex);
+ }
+ }
+ }
+ break;
+ case 3:
+ {
+ const btVector3 n=btCross(m_simplex->c[1]->w-m_simplex->c[0]->w,
+ m_simplex->c[2]->w-m_simplex->c[0]->w);
+ if(n.length2()>0)
+ {
+ appendvertice(*m_simplex,n);
+ if(EncloseOrigin()) return(true);
+ removevertice(*m_simplex);
+ appendvertice(*m_simplex,-n);
+ if(EncloseOrigin()) return(true);
+ removevertice(*m_simplex);
+ }
+ }
+ break;
+ case 4:
+ {
+ if(btFabs(det( m_simplex->c[0]->w-m_simplex->c[3]->w,
+ m_simplex->c[1]->w-m_simplex->c[3]->w,
+ m_simplex->c[2]->w-m_simplex->c[3]->w))>0)
+ return(true);
+ }
+ break;
+ }
+ return(false);
+ }
+ /* Internals */
+ void getsupport(const btVector3& d,sSV& sv) const
+ {
+ sv.d = d/d.length();
+ sv.w = m_shape.Support(sv.d);
+ }
+ void removevertice(sSimplex& simplex)
+ {
+ m_free[m_nfree++]=simplex.c[--simplex.rank];
+ }
+ void appendvertice(sSimplex& simplex,const btVector3& v)
+ {
+ simplex.p[simplex.rank]=0;
+ simplex.c[simplex.rank]=m_free[--m_nfree];
+ getsupport(v,*simplex.c[simplex.rank++]);
+ }
+ static btScalar det(const btVector3& a,const btVector3& b,const btVector3& c)
+ {
+ return( a.y()*b.z()*c.x()+a.z()*b.x()*c.y()-
+ a.x()*b.z()*c.y()-a.y()*b.x()*c.z()+
+ a.x()*b.y()*c.z()-a.z()*b.y()*c.x());
+ }
+ static btScalar projectorigin( const btVector3& a,
+ const btVector3& b,
+ btScalar* w,U& m)
+ {
+ const btVector3 d=b-a;
+ const btScalar l=d.length2();
+ if(l>GJK_SIMPLEX2_EPS)
+ {
+ const btScalar t(l>0?-btDot(a,d)/l:0);
+ if(t>=1) { w[0]=0;w[1]=1;m=2;return(b.length2()); }
+ else if(t<=0) { w[0]=1;w[1]=0;m=1;return(a.length2()); }
+ else { w[0]=1-(w[1]=t);m=3;return((a+d*t).length2()); }
+ }
+ return(-1);
+ }
+ static btScalar projectorigin( const btVector3& a,
+ const btVector3& b,
+ const btVector3& c,
+ btScalar* w,U& m)
+ {
+ static const U imd3[]={1,2,0};
+ const btVector3* vt[]={&a,&b,&c};
+ const btVector3 dl[]={a-b,b-c,c-a};
+ const btVector3 n=btCross(dl[0],dl[1]);
+ const btScalar l=n.length2();
+ if(l>GJK_SIMPLEX3_EPS)
+ {
+ btScalar mindist=-1;
+ btScalar subw[2]={0.f,0.f};
+ U subm(0);
+ for(U i=0;i<3;++i)
+ {
+ if(btDot(*vt[i],btCross(dl[i],n))>0)
+ {
+ const U j=imd3[i];
+ const btScalar subd(projectorigin(*vt[i],*vt[j],subw,subm));
+ if((mindist<0)||(subd<mindist))
+ {
+ mindist = subd;
+ m = static_cast<U>(((subm&1)?1<<i:0)+((subm&2)?1<<j:0));
+ w[i] = subw[0];
+ w[j] = subw[1];
+ w[imd3[j]] = 0;
+ }
+ }
+ }
+ if(mindist<0)
+ {
+ const btScalar d=btDot(a,n);
+ const btScalar s=btSqrt(l);
+ const btVector3 p=n*(d/l);
+ mindist = p.length2();
+ m = 7;
+ w[0] = (btCross(dl[1],b-p)).length()/s;
+ w[1] = (btCross(dl[2],c-p)).length()/s;
+ w[2] = 1-(w[0]+w[1]);
+ }
+ return(mindist);
+ }
+ return(-1);
+ }
+ static btScalar projectorigin( const btVector3& a,
+ const btVector3& b,
+ const btVector3& c,
+ const btVector3& d,
+ btScalar* w,U& m)
+ {
+ static const U imd3[]={1,2,0};
+ const btVector3* vt[]={&a,&b,&c,&d};
+ const btVector3 dl[]={a-d,b-d,c-d};
+ const btScalar vl=det(dl[0],dl[1],dl[2]);
+ const bool ng=(vl*btDot(a,btCross(b-c,a-b)))<=0;
+ if(ng&&(btFabs(vl)>GJK_SIMPLEX4_EPS))
+ {
+ btScalar mindist=-1;
+ btScalar subw[3]={0.f,0.f,0.f};
+ U subm(0);
+ for(U i=0;i<3;++i)
+ {
+ const U j=imd3[i];
+ const btScalar s=vl*btDot(d,btCross(dl[i],dl[j]));
+ if(s>0)
+ {
+ const btScalar subd=projectorigin(*vt[i],*vt[j],d,subw,subm);
+ if((mindist<0)||(subd<mindist))
+ {
+ mindist = subd;
+ m = static_cast<U>((subm&1?1<<i:0)+
+ (subm&2?1<<j:0)+
+ (subm&4?8:0));
+ w[i] = subw[0];
+ w[j] = subw[1];
+ w[imd3[j]] = 0;
+ w[3] = subw[2];
+ }
+ }
+ }
+ if(mindist<0)
+ {
+ mindist = 0;
+ m = 15;
+ w[0] = det(c,b,d)/vl;
+ w[1] = det(a,c,d)/vl;
+ w[2] = det(b,a,d)/vl;
+ w[3] = 1-(w[0]+w[1]+w[2]);
+ }
+ return(mindist);
+ }
+ return(-1);
+ }
+ };
+
+ // EPA
+ struct EPA
+ {
+ /* Types */
+ typedef GJK::sSV sSV;
+ struct sFace
+ {
+ btVector3 n;
+ btScalar d;
+ sSV* c[3];
+ sFace* f[3];
+ sFace* l[2];
+ U1 e[3];
+ U1 pass;
+ };
+ struct sList
+ {
+ sFace* root;
+ U count;
+ sList() : root(0),count(0) {}
+ };
+ struct sHorizon
+ {
+ sFace* cf;
+ sFace* ff;
+ U nf;
+ sHorizon() : cf(0),ff(0),nf(0) {}
+ };
+ struct eStatus { enum _ {
+ Valid,
+ Touching,
+ Degenerated,
+ NonConvex,
+ InvalidHull,
+ OutOfFaces,
+ OutOfVertices,
+ AccuraryReached,
+ FallBack,
+ Failed };};
+ /* Fields */
+ eStatus::_ m_status;
+ GJK::sSimplex m_result;
+ btVector3 m_normal;
+ btScalar m_depth;
+ sSV m_sv_store[EPA_MAX_VERTICES];
+ sFace m_fc_store[EPA_MAX_FACES];
+ U m_nextsv;
+ sList m_hull;
+ sList m_stock;
+ /* Methods */
+ EPA()
+ {
+ Initialize();
+ }
+
+
+ static inline void bind(sFace* fa,U ea,sFace* fb,U eb)
+ {
+ fa->e[ea]=(U1)eb;fa->f[ea]=fb;
+ fb->e[eb]=(U1)ea;fb->f[eb]=fa;
+ }
+ static inline void append(sList& list,sFace* face)
+ {
+ face->l[0] = 0;
+ face->l[1] = list.root;
+ if(list.root) list.root->l[0]=face;
+ list.root = face;
+ ++list.count;
+ }
+ static inline void remove(sList& list,sFace* face)
+ {
+ if(face->l[1]) face->l[1]->l[0]=face->l[0];
+ if(face->l[0]) face->l[0]->l[1]=face->l[1];
+ if(face==list.root) list.root=face->l[1];
+ --list.count;
+ }
+
+
+ void Initialize()
+ {
+ m_status = eStatus::Failed;
+ m_normal = btVector3(0,0,0);
+ m_depth = 0;
+ m_nextsv = 0;
+ for(U i=0;i<EPA_MAX_FACES;++i)
+ {
+ append(m_stock,&m_fc_store[EPA_MAX_FACES-i-1]);
+ }
+ }
+ eStatus::_ Evaluate(GJK& gjk,const btVector3& guess)
+ {
+ GJK::sSimplex& simplex=*gjk.m_simplex;
+ if((simplex.rank>1)&&gjk.EncloseOrigin())
+ {
+
+ /* Clean up */
+ while(m_hull.root)
+ {
+ sFace* f = m_hull.root;
+ remove(m_hull,f);
+ append(m_stock,f);
+ }
+ m_status = eStatus::Valid;
+ m_nextsv = 0;
+ /* Orient simplex */
+ if(gjk.det( simplex.c[0]->w-simplex.c[3]->w,
+ simplex.c[1]->w-simplex.c[3]->w,
+ simplex.c[2]->w-simplex.c[3]->w)<0)
+ {
+ btSwap(simplex.c[0],simplex.c[1]);
+ btSwap(simplex.p[0],simplex.p[1]);
+ }
+ /* Build initial hull */
+ sFace* tetra[]={newface(simplex.c[0],simplex.c[1],simplex.c[2],true),
+ newface(simplex.c[1],simplex.c[0],simplex.c[3],true),
+ newface(simplex.c[2],simplex.c[1],simplex.c[3],true),
+ newface(simplex.c[0],simplex.c[2],simplex.c[3],true)};
+ if(m_hull.count==4)
+ {
+ sFace* best=findbest();
+ sFace outer=*best;
+ U pass=0;
+ U iterations=0;
+ bind(tetra[0],0,tetra[1],0);
+ bind(tetra[0],1,tetra[2],0);
+ bind(tetra[0],2,tetra[3],0);
+ bind(tetra[1],1,tetra[3],2);
+ bind(tetra[1],2,tetra[2],1);
+ bind(tetra[2],2,tetra[3],1);
+ m_status=eStatus::Valid;
+ for(;iterations<EPA_MAX_ITERATIONS;++iterations)
+ {
+ if(m_nextsv<EPA_MAX_VERTICES)
+ {
+ sHorizon horizon;
+ sSV* w=&m_sv_store[m_nextsv++];
+ bool valid=true;
+ best->pass = (U1)(++pass);
+ gjk.getsupport(best->n,*w);
+ const btScalar wdist=btDot(best->n,w->w)-best->d;
+ if(wdist>EPA_ACCURACY)
+ {
+ for(U j=0;(j<3)&&valid;++j)
+ {
+ valid&=expand( pass,w,
+ best->f[j],best->e[j],
+ horizon);
+ }
+ if(valid&&(horizon.nf>=3))
+ {
+ bind(horizon.cf,1,horizon.ff,2);
+ remove(m_hull,best);
+ append(m_stock,best);
+ best=findbest();
+ outer=*best;
+ } else { m_status=eStatus::InvalidHull;break; }
+ } else { m_status=eStatus::AccuraryReached;break; }
+ } else { m_status=eStatus::OutOfVertices;break; }
+ }
+ const btVector3 projection=outer.n*outer.d;
+ m_normal = outer.n;
+ m_depth = outer.d;
+ m_result.rank = 3;
+ m_result.c[0] = outer.c[0];
+ m_result.c[1] = outer.c[1];
+ m_result.c[2] = outer.c[2];
+ m_result.p[0] = btCross( outer.c[1]->w-projection,
+ outer.c[2]->w-projection).length();
+ m_result.p[1] = btCross( outer.c[2]->w-projection,
+ outer.c[0]->w-projection).length();
+ m_result.p[2] = btCross( outer.c[0]->w-projection,
+ outer.c[1]->w-projection).length();
+ const btScalar sum=m_result.p[0]+m_result.p[1]+m_result.p[2];
+ m_result.p[0] /= sum;
+ m_result.p[1] /= sum;
+ m_result.p[2] /= sum;
+ return(m_status);
+ }
+ }
+ /* Fallback */
+ m_status = eStatus::FallBack;
+ m_normal = -guess;
+ const btScalar nl=m_normal.length();
+ if(nl>0)
+ m_normal = m_normal/nl;
+ else
+ m_normal = btVector3(1,0,0);
+ m_depth = 0;
+ m_result.rank=1;
+ m_result.c[0]=simplex.c[0];
+ m_result.p[0]=1;
+ return(m_status);
+ }
+ bool getedgedist(sFace* face, sSV* a, sSV* b, btScalar& dist)
+ {
+ const btVector3 ba = b->w - a->w;
+ const btVector3 n_ab = btCross(ba, face->n); // Outward facing edge normal direction, on triangle plane
+ const btScalar a_dot_nab = btDot(a->w, n_ab); // Only care about the sign to determine inside/outside, so not normalization required
+
+ if(a_dot_nab < 0)
+ {
+ // Outside of edge a->b
+
+ const btScalar ba_l2 = ba.length2();
+ const btScalar a_dot_ba = btDot(a->w, ba);
+ const btScalar b_dot_ba = btDot(b->w, ba);
+
+ if(a_dot_ba > 0)
+ {
+ // Pick distance vertex a
+ dist = a->w.length();
+ }
+ else if(b_dot_ba < 0)
+ {
+ // Pick distance vertex b
+ dist = b->w.length();
+ }
+ else
+ {
+ // Pick distance to edge a->b
+ const btScalar a_dot_b = btDot(a->w, b->w);
+ dist = btSqrt(btMax((a->w.length2() * b->w.length2() - a_dot_b * a_dot_b) / ba_l2, (btScalar)0));
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+ sFace* newface(sSV* a,sSV* b,sSV* c,bool forced)
+ {
+ if(m_stock.root)
+ {
+ sFace* face=m_stock.root;
+ remove(m_stock,face);
+ append(m_hull,face);
+ face->pass = 0;
+ face->c[0] = a;
+ face->c[1] = b;
+ face->c[2] = c;
+ face->n = btCross(b->w-a->w,c->w-a->w);
+ const btScalar l=face->n.length();
+ const bool v=l>EPA_ACCURACY;
+
+ if(v)
+ {
+ if(!(getedgedist(face, a, b, face->d) ||
+ getedgedist(face, b, c, face->d) ||
+ getedgedist(face, c, a, face->d)))
+ {
+ // Origin projects to the interior of the triangle
+ // Use distance to triangle plane
+ face->d = btDot(a->w, face->n) / l;
+ }
+
+ face->n /= l;
+ if(forced || (face->d >= -EPA_PLANE_EPS))
+ {
+ return face;
+ }
+ else
+ m_status=eStatus::NonConvex;
+ }
+ else
+ m_status=eStatus::Degenerated;
+
+ remove(m_hull, face);
+ append(m_stock, face);
+ return 0;
+
+ }
+ m_status = m_stock.root ? eStatus::OutOfVertices : eStatus::OutOfFaces;
+ return 0;
+ }
+ sFace* findbest()
+ {
+ sFace* minf=m_hull.root;
+ btScalar mind=minf->d*minf->d;
+ for(sFace* f=minf->l[1];f;f=f->l[1])
+ {
+ const btScalar sqd=f->d*f->d;
+ if(sqd<mind)
+ {
+ minf=f;
+ mind=sqd;
+ }
+ }
+ return(minf);
+ }
+ bool expand(U pass,sSV* w,sFace* f,U e,sHorizon& horizon)
+ {
+ static const U i1m3[]={1,2,0};
+ static const U i2m3[]={2,0,1};
+ if(f->pass!=pass)
+ {
+ const U e1=i1m3[e];
+ if((btDot(f->n,w->w)-f->d)<-EPA_PLANE_EPS)
+ {
+ sFace* nf=newface(f->c[e1],f->c[e],w,false);
+ if(nf)
+ {
+ bind(nf,0,f,e);
+ if(horizon.cf) bind(horizon.cf,1,nf,2); else horizon.ff=nf;
+ horizon.cf=nf;
+ ++horizon.nf;
+ return(true);
+ }
+ }
+ else
+ {
+ const U e2=i2m3[e];
+ f->pass = (U1)pass;
+ if( expand(pass,w,f->f[e1],f->e[e1],horizon)&&
+ expand(pass,w,f->f[e2],f->e[e2],horizon))
+ {
+ remove(m_hull,f);
+ append(m_stock,f);
+ return(true);
+ }
+ }
+ }
+ return(false);
+ }
+
+ };
+
+ //
+ static void Initialize( const btConvexShape* shape0,const btTransform& wtrs0,
+ const btConvexShape* shape1,const btTransform& wtrs1,
+ btGjkEpaSolver2::sResults& results,
+ tShape& shape,
+ bool withmargins)
+ {
+ /* Results */
+ results.witnesses[0] =
+ results.witnesses[1] = btVector3(0,0,0);
+ results.status = btGjkEpaSolver2::sResults::Separated;
+ /* Shape */
+ shape.m_shapes[0] = shape0;
+ shape.m_shapes[1] = shape1;
+ shape.m_toshape1 = wtrs1.getBasis().transposeTimes(wtrs0.getBasis());
+ shape.m_toshape0 = wtrs0.inverseTimes(wtrs1);
+ shape.EnableMargin(withmargins);
+ }
+
+}
+
+//
+// Api
+//
+
+using namespace gjkepa2_impl;
+
+//
+int btGjkEpaSolver2::StackSizeRequirement()
+{
+ return(sizeof(GJK)+sizeof(EPA));
+}
+
+//
+bool btGjkEpaSolver2::Distance( const btConvexShape* shape0,
+ const btTransform& wtrs0,
+ const btConvexShape* shape1,
+ const btTransform& wtrs1,
+ const btVector3& guess,
+ sResults& results)
+{
+ tShape shape;
+ Initialize(shape0,wtrs0,shape1,wtrs1,results,shape,false);
+ GJK gjk;
+ GJK::eStatus::_ gjk_status=gjk.Evaluate(shape,guess);
+ if(gjk_status==GJK::eStatus::Valid)
+ {
+ btVector3 w0=btVector3(0,0,0);
+ btVector3 w1=btVector3(0,0,0);
+ for(U i=0;i<gjk.m_simplex->rank;++i)
+ {
+ const btScalar p=gjk.m_simplex->p[i];
+ w0+=shape.Support( gjk.m_simplex->c[i]->d,0)*p;
+ w1+=shape.Support(-gjk.m_simplex->c[i]->d,1)*p;
+ }
+ results.witnesses[0] = wtrs0*w0;
+ results.witnesses[1] = wtrs0*w1;
+ results.normal = w0-w1;
+ results.distance = results.normal.length();
+ results.normal /= results.distance>GJK_MIN_DISTANCE?results.distance:1;
+ return(true);
+ }
+ else
+ {
+ results.status = gjk_status==GJK::eStatus::Inside?
+ sResults::Penetrating :
+ sResults::GJK_Failed ;
+ return(false);
+ }
+}
+
+//
+bool btGjkEpaSolver2::Penetration( const btConvexShape* shape0,
+ const btTransform& wtrs0,
+ const btConvexShape* shape1,
+ const btTransform& wtrs1,
+ const btVector3& guess,
+ sResults& results,
+ bool usemargins)
+{
+ tShape shape;
+ Initialize(shape0,wtrs0,shape1,wtrs1,results,shape,usemargins);
+ GJK gjk;
+ GJK::eStatus::_ gjk_status=gjk.Evaluate(shape,-guess);
+ switch(gjk_status)
+ {
+ case GJK::eStatus::Inside:
+ {
+ EPA epa;
+ EPA::eStatus::_ epa_status=epa.Evaluate(gjk,-guess);
+ if(epa_status!=EPA::eStatus::Failed)
+ {
+ btVector3 w0=btVector3(0,0,0);
+ for(U i=0;i<epa.m_result.rank;++i)
+ {
+ w0+=shape.Support(epa.m_result.c[i]->d,0)*epa.m_result.p[i];
+ }
+ results.status = sResults::Penetrating;
+ results.witnesses[0] = wtrs0*w0;
+ results.witnesses[1] = wtrs0*(w0-epa.m_normal*epa.m_depth);
+ results.normal = -epa.m_normal;
+ results.distance = -epa.m_depth;
+ return(true);
+ } else results.status=sResults::EPA_Failed;
+ }
+ break;
+ case GJK::eStatus::Failed:
+ results.status=sResults::GJK_Failed;
+ break;
+ default:
+ {
+ }
+ }
+ return(false);
+}
+
+#ifndef __SPU__
+//
+btScalar btGjkEpaSolver2::SignedDistance(const btVector3& position,
+ btScalar margin,
+ const btConvexShape* shape0,
+ const btTransform& wtrs0,
+ sResults& results)
+{
+ tShape shape;
+ btSphereShape shape1(margin);
+ btTransform wtrs1(btQuaternion(0,0,0,1),position);
+ Initialize(shape0,wtrs0,&shape1,wtrs1,results,shape,false);
+ GJK gjk;
+ GJK::eStatus::_ gjk_status=gjk.Evaluate(shape,btVector3(1,1,1));
+ if(gjk_status==GJK::eStatus::Valid)
+ {
+ btVector3 w0=btVector3(0,0,0);
+ btVector3 w1=btVector3(0,0,0);
+ for(U i=0;i<gjk.m_simplex->rank;++i)
+ {
+ const btScalar p=gjk.m_simplex->p[i];
+ w0+=shape.Support( gjk.m_simplex->c[i]->d,0)*p;
+ w1+=shape.Support(-gjk.m_simplex->c[i]->d,1)*p;
+ }
+ results.witnesses[0] = wtrs0*w0;
+ results.witnesses[1] = wtrs0*w1;
+ const btVector3 delta= results.witnesses[1]-
+ results.witnesses[0];
+ const btScalar margin= shape0->getMarginNonVirtual()+
+ shape1.getMarginNonVirtual();
+ const btScalar length= delta.length();
+ results.normal = delta/length;
+ results.witnesses[0] += results.normal*margin;
+ return(length-margin);
+ }
+ else
+ {
+ if(gjk_status==GJK::eStatus::Inside)
+ {
+ if(Penetration(shape0,wtrs0,&shape1,wtrs1,gjk.m_ray,results))
+ {
+ const btVector3 delta= results.witnesses[0]-
+ results.witnesses[1];
+ const btScalar length= delta.length();
+ if (length >= SIMD_EPSILON)
+ results.normal = delta/length;
+ return(-length);
+ }
+ }
+ }
+ return(SIMD_INFINITY);
+}
+
+//
+bool btGjkEpaSolver2::SignedDistance(const btConvexShape* shape0,
+ const btTransform& wtrs0,
+ const btConvexShape* shape1,
+ const btTransform& wtrs1,
+ const btVector3& guess,
+ sResults& results)
+{
+ if(!Distance(shape0,wtrs0,shape1,wtrs1,guess,results))
+ return(Penetration(shape0,wtrs0,shape1,wtrs1,guess,results,false));
+ else
+ return(true);
+}
+#endif //__SPU__
+
+/* Symbols cleanup */
+
+#undef GJK_MAX_ITERATIONS
+#undef GJK_ACCURACY
+#undef GJK_MIN_DISTANCE
+#undef GJK_DUPLICATED_EPS
+#undef GJK_SIMPLEX2_EPS
+#undef GJK_SIMPLEX3_EPS
+#undef GJK_SIMPLEX4_EPS
+
+#undef EPA_MAX_VERTICES
+#undef EPA_MAX_FACES
+#undef EPA_MAX_ITERATIONS
+#undef EPA_ACCURACY
+#undef EPA_FALLBACK
+#undef EPA_PLANE_EPS
+#undef EPA_INSIDE_EPS
diff --git a/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h
new file mode 100644
index 0000000000..ac501d5ecf
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h
@@ -0,0 +1,75 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2008 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the
+use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+claim that you wrote the original software. If you use this software in a
+product, an acknowledgment in the product documentation would be appreciated
+but is not required.
+2. Altered source versions must be plainly marked as such, and must not be
+misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+/*
+GJK-EPA collision solver by Nathanael Presson, 2008
+*/
+#ifndef BT_GJK_EPA2_H
+#define BT_GJK_EPA2_H
+
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+
+///btGjkEpaSolver contributed under zlib by Nathanael Presson
+struct btGjkEpaSolver2
+{
+struct sResults
+ {
+ enum eStatus
+ {
+ Separated, /* Shapes doesnt penetrate */
+ Penetrating, /* Shapes are penetrating */
+ GJK_Failed, /* GJK phase fail, no big issue, shapes are probably just 'touching' */
+ EPA_Failed /* EPA phase fail, bigger problem, need to save parameters, and debug */
+ } status;
+ btVector3 witnesses[2];
+ btVector3 normal;
+ btScalar distance;
+ };
+
+static int StackSizeRequirement();
+
+static bool Distance( const btConvexShape* shape0,const btTransform& wtrs0,
+ const btConvexShape* shape1,const btTransform& wtrs1,
+ const btVector3& guess,
+ sResults& results);
+
+static bool Penetration(const btConvexShape* shape0,const btTransform& wtrs0,
+ const btConvexShape* shape1,const btTransform& wtrs1,
+ const btVector3& guess,
+ sResults& results,
+ bool usemargins=true);
+#ifndef __SPU__
+static btScalar SignedDistance( const btVector3& position,
+ btScalar margin,
+ const btConvexShape* shape,
+ const btTransform& wtrs,
+ sResults& results);
+
+static bool SignedDistance( const btConvexShape* shape0,const btTransform& wtrs0,
+ const btConvexShape* shape1,const btTransform& wtrs1,
+ const btVector3& guess,
+ sResults& results);
+#endif //__SPU__
+
+};
+
+#endif //BT_GJK_EPA2_H
+
diff --git a/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btGjkEpa3.h b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btGjkEpa3.h
new file mode 100644
index 0000000000..ce1f24bc50
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btGjkEpa3.h
@@ -0,0 +1,1035 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2014 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the
+use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+claim that you wrote the original software. If you use this software in a
+product, an acknowledgment in the product documentation would be appreciated
+but is not required.
+2. Altered source versions must be plainly marked as such, and must not be
+misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+/*
+Initial GJK-EPA collision solver by Nathanael Presson, 2008
+Improvements and refactoring by Erwin Coumans, 2008-2014
+*/
+#ifndef BT_GJK_EPA3_H
+#define BT_GJK_EPA3_H
+
+#include "LinearMath/btTransform.h"
+#include "btGjkCollisionDescription.h"
+
+
+
+struct btGjkEpaSolver3
+{
+struct sResults
+ {
+ enum eStatus
+ {
+ Separated, /* Shapes doesnt penetrate */
+ Penetrating, /* Shapes are penetrating */
+ GJK_Failed, /* GJK phase fail, no big issue, shapes are probably just 'touching' */
+ EPA_Failed /* EPA phase fail, bigger problem, need to save parameters, and debug */
+ } status;
+ btVector3 witnesses[2];
+ btVector3 normal;
+ btScalar distance;
+ };
+
+
+};
+
+
+
+#if defined(DEBUG) || defined (_DEBUG)
+#include <stdio.h> //for debug printf
+#ifdef __SPU__
+#include <spu_printf.h>
+#define printf spu_printf
+#endif //__SPU__
+#endif
+
+
+
+ // Config
+
+ /* GJK */
+#define GJK_MAX_ITERATIONS 128
+#define GJK_ACCURARY ((btScalar)0.0001)
+#define GJK_MIN_DISTANCE ((btScalar)0.0001)
+#define GJK_DUPLICATED_EPS ((btScalar)0.0001)
+#define GJK_SIMPLEX2_EPS ((btScalar)0.0)
+#define GJK_SIMPLEX3_EPS ((btScalar)0.0)
+#define GJK_SIMPLEX4_EPS ((btScalar)0.0)
+
+ /* EPA */
+#define EPA_MAX_VERTICES 64
+#define EPA_MAX_FACES (EPA_MAX_VERTICES*2)
+#define EPA_MAX_ITERATIONS 255
+#define EPA_ACCURACY ((btScalar)0.0001)
+#define EPA_FALLBACK (10*EPA_ACCURACY)
+#define EPA_PLANE_EPS ((btScalar)0.00001)
+#define EPA_INSIDE_EPS ((btScalar)0.01)
+
+
+ // Shorthands
+ typedef unsigned int U;
+ typedef unsigned char U1;
+
+ // MinkowskiDiff
+ template <typename btConvexTemplate>
+ struct MinkowskiDiff
+ {
+ const btConvexTemplate* m_convexAPtr;
+ const btConvexTemplate* m_convexBPtr;
+
+ btMatrix3x3 m_toshape1;
+ btTransform m_toshape0;
+
+ bool m_enableMargin;
+
+
+ MinkowskiDiff(const btConvexTemplate& a, const btConvexTemplate& b)
+ :m_convexAPtr(&a),
+ m_convexBPtr(&b)
+ {
+ }
+
+ void EnableMargin(bool enable)
+ {
+ m_enableMargin = enable;
+ }
+ inline btVector3 Support0(const btVector3& d) const
+ {
+ return m_convexAPtr->getLocalSupportWithMargin(d);
+ }
+ inline btVector3 Support1(const btVector3& d) const
+ {
+ return m_toshape0*m_convexBPtr->getLocalSupportWithMargin(m_toshape1*d);
+ }
+
+
+ inline btVector3 Support(const btVector3& d) const
+ {
+ return(Support0(d)-Support1(-d));
+ }
+ btVector3 Support(const btVector3& d,U index) const
+ {
+ if(index)
+ return(Support1(d));
+ else
+ return(Support0(d));
+ }
+ };
+
+enum eGjkStatus
+{
+ eGjkValid,
+ eGjkInside,
+ eGjkFailed
+};
+
+ // GJK
+ template <typename btConvexTemplate>
+ struct GJK
+ {
+ /* Types */
+ struct sSV
+ {
+ btVector3 d,w;
+ };
+ struct sSimplex
+ {
+ sSV* c[4];
+ btScalar p[4];
+ U rank;
+ };
+
+ /* Fields */
+
+ MinkowskiDiff<btConvexTemplate> m_shape;
+ btVector3 m_ray;
+ btScalar m_distance;
+ sSimplex m_simplices[2];
+ sSV m_store[4];
+ sSV* m_free[4];
+ U m_nfree;
+ U m_current;
+ sSimplex* m_simplex;
+ eGjkStatus m_status;
+ /* Methods */
+
+ GJK(const btConvexTemplate& a, const btConvexTemplate& b)
+ :m_shape(a,b)
+ {
+ Initialize();
+ }
+ void Initialize()
+ {
+ m_ray = btVector3(0,0,0);
+ m_nfree = 0;
+ m_status = eGjkFailed;
+ m_current = 0;
+ m_distance = 0;
+ }
+ eGjkStatus Evaluate(const MinkowskiDiff<btConvexTemplate>& shapearg,const btVector3& guess)
+ {
+ U iterations=0;
+ btScalar sqdist=0;
+ btScalar alpha=0;
+ btVector3 lastw[4];
+ U clastw=0;
+ /* Initialize solver */
+ m_free[0] = &m_store[0];
+ m_free[1] = &m_store[1];
+ m_free[2] = &m_store[2];
+ m_free[3] = &m_store[3];
+ m_nfree = 4;
+ m_current = 0;
+ m_status = eGjkValid;
+ m_shape = shapearg;
+ m_distance = 0;
+ /* Initialize simplex */
+ m_simplices[0].rank = 0;
+ m_ray = guess;
+ const btScalar sqrl= m_ray.length2();
+ appendvertice(m_simplices[0],sqrl>0?-m_ray:btVector3(1,0,0));
+ m_simplices[0].p[0] = 1;
+ m_ray = m_simplices[0].c[0]->w;
+ sqdist = sqrl;
+ lastw[0] =
+ lastw[1] =
+ lastw[2] =
+ lastw[3] = m_ray;
+ /* Loop */
+ do {
+ const U next=1-m_current;
+ sSimplex& cs=m_simplices[m_current];
+ sSimplex& ns=m_simplices[next];
+ /* Check zero */
+ const btScalar rl=m_ray.length();
+ if(rl<GJK_MIN_DISTANCE)
+ {/* Touching or inside */
+ m_status=eGjkInside;
+ break;
+ }
+ /* Append new vertice in -'v' direction */
+ appendvertice(cs,-m_ray);
+ const btVector3& w=cs.c[cs.rank-1]->w;
+ bool found=false;
+ for(U i=0;i<4;++i)
+ {
+ if((w-lastw[i]).length2()<GJK_DUPLICATED_EPS)
+ { found=true;break; }
+ }
+ if(found)
+ {/* Return old simplex */
+ removevertice(m_simplices[m_current]);
+ break;
+ }
+ else
+ {/* Update lastw */
+ lastw[clastw=(clastw+1)&3]=w;
+ }
+ /* Check for termination */
+ const btScalar omega=btDot(m_ray,w)/rl;
+ alpha=btMax(omega,alpha);
+ if(((rl-alpha)-(GJK_ACCURARY*rl))<=0)
+ {/* Return old simplex */
+ removevertice(m_simplices[m_current]);
+ break;
+ }
+ /* Reduce simplex */
+ btScalar weights[4];
+ U mask=0;
+ switch(cs.rank)
+ {
+ case 2: sqdist=projectorigin( cs.c[0]->w,
+ cs.c[1]->w,
+ weights,mask);break;
+ case 3: sqdist=projectorigin( cs.c[0]->w,
+ cs.c[1]->w,
+ cs.c[2]->w,
+ weights,mask);break;
+ case 4: sqdist=projectorigin( cs.c[0]->w,
+ cs.c[1]->w,
+ cs.c[2]->w,
+ cs.c[3]->w,
+ weights,mask);break;
+ }
+ if(sqdist>=0)
+ {/* Valid */
+ ns.rank = 0;
+ m_ray = btVector3(0,0,0);
+ m_current = next;
+ for(U i=0,ni=cs.rank;i<ni;++i)
+ {
+ if(mask&(1<<i))
+ {
+ ns.c[ns.rank] = cs.c[i];
+ ns.p[ns.rank++] = weights[i];
+ m_ray += cs.c[i]->w*weights[i];
+ }
+ else
+ {
+ m_free[m_nfree++] = cs.c[i];
+ }
+ }
+ if(mask==15) m_status=eGjkInside;
+ }
+ else
+ {/* Return old simplex */
+ removevertice(m_simplices[m_current]);
+ break;
+ }
+ m_status=((++iterations)<GJK_MAX_ITERATIONS)?m_status:eGjkFailed;
+ } while(m_status==eGjkValid);
+ m_simplex=&m_simplices[m_current];
+ switch(m_status)
+ {
+ case eGjkValid: m_distance=m_ray.length();break;
+ case eGjkInside: m_distance=0;break;
+ default:
+ {
+ }
+ }
+ return(m_status);
+ }
+ bool EncloseOrigin()
+ {
+ switch(m_simplex->rank)
+ {
+ case 1:
+ {
+ for(U i=0;i<3;++i)
+ {
+ btVector3 axis=btVector3(0,0,0);
+ axis[i]=1;
+ appendvertice(*m_simplex, axis);
+ if(EncloseOrigin()) return(true);
+ removevertice(*m_simplex);
+ appendvertice(*m_simplex,-axis);
+ if(EncloseOrigin()) return(true);
+ removevertice(*m_simplex);
+ }
+ }
+ break;
+ case 2:
+ {
+ const btVector3 d=m_simplex->c[1]->w-m_simplex->c[0]->w;
+ for(U i=0;i<3;++i)
+ {
+ btVector3 axis=btVector3(0,0,0);
+ axis[i]=1;
+ const btVector3 p=btCross(d,axis);
+ if(p.length2()>0)
+ {
+ appendvertice(*m_simplex, p);
+ if(EncloseOrigin()) return(true);
+ removevertice(*m_simplex);
+ appendvertice(*m_simplex,-p);
+ if(EncloseOrigin()) return(true);
+ removevertice(*m_simplex);
+ }
+ }
+ }
+ break;
+ case 3:
+ {
+ const btVector3 n=btCross(m_simplex->c[1]->w-m_simplex->c[0]->w,
+ m_simplex->c[2]->w-m_simplex->c[0]->w);
+ if(n.length2()>0)
+ {
+ appendvertice(*m_simplex,n);
+ if(EncloseOrigin()) return(true);
+ removevertice(*m_simplex);
+ appendvertice(*m_simplex,-n);
+ if(EncloseOrigin()) return(true);
+ removevertice(*m_simplex);
+ }
+ }
+ break;
+ case 4:
+ {
+ if(btFabs(det( m_simplex->c[0]->w-m_simplex->c[3]->w,
+ m_simplex->c[1]->w-m_simplex->c[3]->w,
+ m_simplex->c[2]->w-m_simplex->c[3]->w))>0)
+ return(true);
+ }
+ break;
+ }
+ return(false);
+ }
+ /* Internals */
+ void getsupport(const btVector3& d,sSV& sv) const
+ {
+ sv.d = d/d.length();
+ sv.w = m_shape.Support(sv.d);
+ }
+ void removevertice(sSimplex& simplex)
+ {
+ m_free[m_nfree++]=simplex.c[--simplex.rank];
+ }
+ void appendvertice(sSimplex& simplex,const btVector3& v)
+ {
+ simplex.p[simplex.rank]=0;
+ simplex.c[simplex.rank]=m_free[--m_nfree];
+ getsupport(v,*simplex.c[simplex.rank++]);
+ }
+ static btScalar det(const btVector3& a,const btVector3& b,const btVector3& c)
+ {
+ return( a.y()*b.z()*c.x()+a.z()*b.x()*c.y()-
+ a.x()*b.z()*c.y()-a.y()*b.x()*c.z()+
+ a.x()*b.y()*c.z()-a.z()*b.y()*c.x());
+ }
+ static btScalar projectorigin( const btVector3& a,
+ const btVector3& b,
+ btScalar* w,U& m)
+ {
+ const btVector3 d=b-a;
+ const btScalar l=d.length2();
+ if(l>GJK_SIMPLEX2_EPS)
+ {
+ const btScalar t(l>0?-btDot(a,d)/l:0);
+ if(t>=1) { w[0]=0;w[1]=1;m=2;return(b.length2()); }
+ else if(t<=0) { w[0]=1;w[1]=0;m=1;return(a.length2()); }
+ else { w[0]=1-(w[1]=t);m=3;return((a+d*t).length2()); }
+ }
+ return(-1);
+ }
+ static btScalar projectorigin( const btVector3& a,
+ const btVector3& b,
+ const btVector3& c,
+ btScalar* w,U& m)
+ {
+ static const U imd3[]={1,2,0};
+ const btVector3* vt[]={&a,&b,&c};
+ const btVector3 dl[]={a-b,b-c,c-a};
+ const btVector3 n=btCross(dl[0],dl[1]);
+ const btScalar l=n.length2();
+ if(l>GJK_SIMPLEX3_EPS)
+ {
+ btScalar mindist=-1;
+ btScalar subw[2]={0.f,0.f};
+ U subm(0);
+ for(U i=0;i<3;++i)
+ {
+ if(btDot(*vt[i],btCross(dl[i],n))>0)
+ {
+ const U j=imd3[i];
+ const btScalar subd(projectorigin(*vt[i],*vt[j],subw,subm));
+ if((mindist<0)||(subd<mindist))
+ {
+ mindist = subd;
+ m = static_cast<U>(((subm&1)?1<<i:0)+((subm&2)?1<<j:0));
+ w[i] = subw[0];
+ w[j] = subw[1];
+ w[imd3[j]] = 0;
+ }
+ }
+ }
+ if(mindist<0)
+ {
+ const btScalar d=btDot(a,n);
+ const btScalar s=btSqrt(l);
+ const btVector3 p=n*(d/l);
+ mindist = p.length2();
+ m = 7;
+ w[0] = (btCross(dl[1],b-p)).length()/s;
+ w[1] = (btCross(dl[2],c-p)).length()/s;
+ w[2] = 1-(w[0]+w[1]);
+ }
+ return(mindist);
+ }
+ return(-1);
+ }
+ static btScalar projectorigin( const btVector3& a,
+ const btVector3& b,
+ const btVector3& c,
+ const btVector3& d,
+ btScalar* w,U& m)
+ {
+ static const U imd3[]={1,2,0};
+ const btVector3* vt[]={&a,&b,&c,&d};
+ const btVector3 dl[]={a-d,b-d,c-d};
+ const btScalar vl=det(dl[0],dl[1],dl[2]);
+ const bool ng=(vl*btDot(a,btCross(b-c,a-b)))<=0;
+ if(ng&&(btFabs(vl)>GJK_SIMPLEX4_EPS))
+ {
+ btScalar mindist=-1;
+ btScalar subw[3]={0.f,0.f,0.f};
+ U subm(0);
+ for(U i=0;i<3;++i)
+ {
+ const U j=imd3[i];
+ const btScalar s=vl*btDot(d,btCross(dl[i],dl[j]));
+ if(s>0)
+ {
+ const btScalar subd=projectorigin(*vt[i],*vt[j],d,subw,subm);
+ if((mindist<0)||(subd<mindist))
+ {
+ mindist = subd;
+ m = static_cast<U>((subm&1?1<<i:0)+
+ (subm&2?1<<j:0)+
+ (subm&4?8:0));
+ w[i] = subw[0];
+ w[j] = subw[1];
+ w[imd3[j]] = 0;
+ w[3] = subw[2];
+ }
+ }
+ }
+ if(mindist<0)
+ {
+ mindist = 0;
+ m = 15;
+ w[0] = det(c,b,d)/vl;
+ w[1] = det(a,c,d)/vl;
+ w[2] = det(b,a,d)/vl;
+ w[3] = 1-(w[0]+w[1]+w[2]);
+ }
+ return(mindist);
+ }
+ return(-1);
+ }
+ };
+
+
+enum eEpaStatus
+{
+ eEpaValid,
+ eEpaTouching,
+ eEpaDegenerated,
+ eEpaNonConvex,
+ eEpaInvalidHull,
+ eEpaOutOfFaces,
+ eEpaOutOfVertices,
+ eEpaAccuraryReached,
+ eEpaFallBack,
+ eEpaFailed
+};
+
+
+ // EPA
+template <typename btConvexTemplate>
+ struct EPA
+ {
+ /* Types */
+
+ struct sFace
+ {
+ btVector3 n;
+ btScalar d;
+ typename GJK<btConvexTemplate>::sSV* c[3];
+ sFace* f[3];
+ sFace* l[2];
+ U1 e[3];
+ U1 pass;
+ };
+ struct sList
+ {
+ sFace* root;
+ U count;
+ sList() : root(0),count(0) {}
+ };
+ struct sHorizon
+ {
+ sFace* cf;
+ sFace* ff;
+ U nf;
+ sHorizon() : cf(0),ff(0),nf(0) {}
+ };
+
+ /* Fields */
+ eEpaStatus m_status;
+ typename GJK<btConvexTemplate>::sSimplex m_result;
+ btVector3 m_normal;
+ btScalar m_depth;
+ typename GJK<btConvexTemplate>::sSV m_sv_store[EPA_MAX_VERTICES];
+ sFace m_fc_store[EPA_MAX_FACES];
+ U m_nextsv;
+ sList m_hull;
+ sList m_stock;
+ /* Methods */
+ EPA()
+ {
+ Initialize();
+ }
+
+
+ static inline void bind(sFace* fa,U ea,sFace* fb,U eb)
+ {
+ fa->e[ea]=(U1)eb;fa->f[ea]=fb;
+ fb->e[eb]=(U1)ea;fb->f[eb]=fa;
+ }
+ static inline void append(sList& list,sFace* face)
+ {
+ face->l[0] = 0;
+ face->l[1] = list.root;
+ if(list.root) list.root->l[0]=face;
+ list.root = face;
+ ++list.count;
+ }
+ static inline void remove(sList& list,sFace* face)
+ {
+ if(face->l[1]) face->l[1]->l[0]=face->l[0];
+ if(face->l[0]) face->l[0]->l[1]=face->l[1];
+ if(face==list.root) list.root=face->l[1];
+ --list.count;
+ }
+
+
+ void Initialize()
+ {
+ m_status = eEpaFailed;
+ m_normal = btVector3(0,0,0);
+ m_depth = 0;
+ m_nextsv = 0;
+ for(U i=0;i<EPA_MAX_FACES;++i)
+ {
+ append(m_stock,&m_fc_store[EPA_MAX_FACES-i-1]);
+ }
+ }
+ eEpaStatus Evaluate(GJK<btConvexTemplate>& gjk,const btVector3& guess)
+ {
+ typename GJK<btConvexTemplate>::sSimplex& simplex=*gjk.m_simplex;
+ if((simplex.rank>1)&&gjk.EncloseOrigin())
+ {
+
+ /* Clean up */
+ while(m_hull.root)
+ {
+ sFace* f = m_hull.root;
+ remove(m_hull,f);
+ append(m_stock,f);
+ }
+ m_status = eEpaValid;
+ m_nextsv = 0;
+ /* Orient simplex */
+ if(gjk.det( simplex.c[0]->w-simplex.c[3]->w,
+ simplex.c[1]->w-simplex.c[3]->w,
+ simplex.c[2]->w-simplex.c[3]->w)<0)
+ {
+ btSwap(simplex.c[0],simplex.c[1]);
+ btSwap(simplex.p[0],simplex.p[1]);
+ }
+ /* Build initial hull */
+ sFace* tetra[]={newface(simplex.c[0],simplex.c[1],simplex.c[2],true),
+ newface(simplex.c[1],simplex.c[0],simplex.c[3],true),
+ newface(simplex.c[2],simplex.c[1],simplex.c[3],true),
+ newface(simplex.c[0],simplex.c[2],simplex.c[3],true)};
+ if(m_hull.count==4)
+ {
+ sFace* best=findbest();
+ sFace outer=*best;
+ U pass=0;
+ U iterations=0;
+ bind(tetra[0],0,tetra[1],0);
+ bind(tetra[0],1,tetra[2],0);
+ bind(tetra[0],2,tetra[3],0);
+ bind(tetra[1],1,tetra[3],2);
+ bind(tetra[1],2,tetra[2],1);
+ bind(tetra[2],2,tetra[3],1);
+ m_status=eEpaValid;
+ for(;iterations<EPA_MAX_ITERATIONS;++iterations)
+ {
+ if(m_nextsv<EPA_MAX_VERTICES)
+ {
+ sHorizon horizon;
+ typename GJK<btConvexTemplate>::sSV* w=&m_sv_store[m_nextsv++];
+ bool valid=true;
+ best->pass = (U1)(++pass);
+ gjk.getsupport(best->n,*w);
+ const btScalar wdist=btDot(best->n,w->w)-best->d;
+ if(wdist>EPA_ACCURACY)
+ {
+ for(U j=0;(j<3)&&valid;++j)
+ {
+ valid&=expand( pass,w,
+ best->f[j],best->e[j],
+ horizon);
+ }
+ if(valid&&(horizon.nf>=3))
+ {
+ bind(horizon.cf,1,horizon.ff,2);
+ remove(m_hull,best);
+ append(m_stock,best);
+ best=findbest();
+ outer=*best;
+ } else { m_status=eEpaInvalidHull;break; }
+ } else { m_status=eEpaAccuraryReached;break; }
+ } else { m_status=eEpaOutOfVertices;break; }
+ }
+ const btVector3 projection=outer.n*outer.d;
+ m_normal = outer.n;
+ m_depth = outer.d;
+ m_result.rank = 3;
+ m_result.c[0] = outer.c[0];
+ m_result.c[1] = outer.c[1];
+ m_result.c[2] = outer.c[2];
+ m_result.p[0] = btCross( outer.c[1]->w-projection,
+ outer.c[2]->w-projection).length();
+ m_result.p[1] = btCross( outer.c[2]->w-projection,
+ outer.c[0]->w-projection).length();
+ m_result.p[2] = btCross( outer.c[0]->w-projection,
+ outer.c[1]->w-projection).length();
+ const btScalar sum=m_result.p[0]+m_result.p[1]+m_result.p[2];
+ m_result.p[0] /= sum;
+ m_result.p[1] /= sum;
+ m_result.p[2] /= sum;
+ return(m_status);
+ }
+ }
+ /* Fallback */
+ m_status = eEpaFallBack;
+ m_normal = -guess;
+ const btScalar nl=m_normal.length();
+ if(nl>0)
+ m_normal = m_normal/nl;
+ else
+ m_normal = btVector3(1,0,0);
+ m_depth = 0;
+ m_result.rank=1;
+ m_result.c[0]=simplex.c[0];
+ m_result.p[0]=1;
+ return(m_status);
+ }
+ bool getedgedist(sFace* face, typename GJK<btConvexTemplate>::sSV* a, typename GJK<btConvexTemplate>::sSV* b, btScalar& dist)
+ {
+ const btVector3 ba = b->w - a->w;
+ const btVector3 n_ab = btCross(ba, face->n); // Outward facing edge normal direction, on triangle plane
+ const btScalar a_dot_nab = btDot(a->w, n_ab); // Only care about the sign to determine inside/outside, so not normalization required
+
+ if(a_dot_nab < 0)
+ {
+ // Outside of edge a->b
+
+ const btScalar ba_l2 = ba.length2();
+ const btScalar a_dot_ba = btDot(a->w, ba);
+ const btScalar b_dot_ba = btDot(b->w, ba);
+
+ if(a_dot_ba > 0)
+ {
+ // Pick distance vertex a
+ dist = a->w.length();
+ }
+ else if(b_dot_ba < 0)
+ {
+ // Pick distance vertex b
+ dist = b->w.length();
+ }
+ else
+ {
+ // Pick distance to edge a->b
+ const btScalar a_dot_b = btDot(a->w, b->w);
+ dist = btSqrt(btMax((a->w.length2() * b->w.length2() - a_dot_b * a_dot_b) / ba_l2, (btScalar)0));
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+ sFace* newface(typename GJK<btConvexTemplate>::sSV* a,typename GJK<btConvexTemplate>::sSV* b,typename GJK<btConvexTemplate>::sSV* c,bool forced)
+ {
+ if(m_stock.root)
+ {
+ sFace* face=m_stock.root;
+ remove(m_stock,face);
+ append(m_hull,face);
+ face->pass = 0;
+ face->c[0] = a;
+ face->c[1] = b;
+ face->c[2] = c;
+ face->n = btCross(b->w-a->w,c->w-a->w);
+ const btScalar l=face->n.length();
+ const bool v=l>EPA_ACCURACY;
+
+ if(v)
+ {
+ if(!(getedgedist(face, a, b, face->d) ||
+ getedgedist(face, b, c, face->d) ||
+ getedgedist(face, c, a, face->d)))
+ {
+ // Origin projects to the interior of the triangle
+ // Use distance to triangle plane
+ face->d = btDot(a->w, face->n) / l;
+ }
+
+ face->n /= l;
+ if(forced || (face->d >= -EPA_PLANE_EPS))
+ {
+ return face;
+ }
+ else
+ m_status=eEpaNonConvex;
+ }
+ else
+ m_status=eEpaDegenerated;
+
+ remove(m_hull, face);
+ append(m_stock, face);
+ return 0;
+
+ }
+ m_status = m_stock.root ? eEpaOutOfVertices : eEpaOutOfFaces;
+ return 0;
+ }
+ sFace* findbest()
+ {
+ sFace* minf=m_hull.root;
+ btScalar mind=minf->d*minf->d;
+ for(sFace* f=minf->l[1];f;f=f->l[1])
+ {
+ const btScalar sqd=f->d*f->d;
+ if(sqd<mind)
+ {
+ minf=f;
+ mind=sqd;
+ }
+ }
+ return(minf);
+ }
+ bool expand(U pass,typename GJK<btConvexTemplate>::sSV* w,sFace* f,U e,sHorizon& horizon)
+ {
+ static const U i1m3[]={1,2,0};
+ static const U i2m3[]={2,0,1};
+ if(f->pass!=pass)
+ {
+ const U e1=i1m3[e];
+ if((btDot(f->n,w->w)-f->d)<-EPA_PLANE_EPS)
+ {
+ sFace* nf=newface(f->c[e1],f->c[e],w,false);
+ if(nf)
+ {
+ bind(nf,0,f,e);
+ if(horizon.cf) bind(horizon.cf,1,nf,2); else horizon.ff=nf;
+ horizon.cf=nf;
+ ++horizon.nf;
+ return(true);
+ }
+ }
+ else
+ {
+ const U e2=i2m3[e];
+ f->pass = (U1)pass;
+ if( expand(pass,w,f->f[e1],f->e[e1],horizon)&&
+ expand(pass,w,f->f[e2],f->e[e2],horizon))
+ {
+ remove(m_hull,f);
+ append(m_stock,f);
+ return(true);
+ }
+ }
+ }
+ return(false);
+ }
+
+ };
+
+ template <typename btConvexTemplate>
+ static void Initialize( const btConvexTemplate& a, const btConvexTemplate& b,
+ btGjkEpaSolver3::sResults& results,
+ MinkowskiDiff<btConvexTemplate>& shape)
+ {
+ /* Results */
+ results.witnesses[0] =
+ results.witnesses[1] = btVector3(0,0,0);
+ results.status = btGjkEpaSolver3::sResults::Separated;
+ /* Shape */
+
+ shape.m_toshape1 = b.getWorldTransform().getBasis().transposeTimes(a.getWorldTransform().getBasis());
+ shape.m_toshape0 = a.getWorldTransform().inverseTimes(b.getWorldTransform());
+
+ }
+
+
+//
+// Api
+//
+
+
+
+//
+template <typename btConvexTemplate>
+bool btGjkEpaSolver3_Distance(const btConvexTemplate& a, const btConvexTemplate& b,
+ const btVector3& guess,
+ btGjkEpaSolver3::sResults& results)
+{
+ MinkowskiDiff<btConvexTemplate> shape(a,b);
+ Initialize(a,b,results,shape);
+ GJK<btConvexTemplate> gjk(a,b);
+ eGjkStatus gjk_status=gjk.Evaluate(shape,guess);
+ if(gjk_status==eGjkValid)
+ {
+ btVector3 w0=btVector3(0,0,0);
+ btVector3 w1=btVector3(0,0,0);
+ for(U i=0;i<gjk.m_simplex->rank;++i)
+ {
+ const btScalar p=gjk.m_simplex->p[i];
+ w0+=shape.Support( gjk.m_simplex->c[i]->d,0)*p;
+ w1+=shape.Support(-gjk.m_simplex->c[i]->d,1)*p;
+ }
+ results.witnesses[0] = a.getWorldTransform()*w0;
+ results.witnesses[1] = a.getWorldTransform()*w1;
+ results.normal = w0-w1;
+ results.distance = results.normal.length();
+ results.normal /= results.distance>GJK_MIN_DISTANCE?results.distance:1;
+ return(true);
+ }
+ else
+ {
+ results.status = gjk_status==eGjkInside?
+ btGjkEpaSolver3::sResults::Penetrating :
+ btGjkEpaSolver3::sResults::GJK_Failed ;
+ return(false);
+ }
+}
+
+
+template <typename btConvexTemplate>
+bool btGjkEpaSolver3_Penetration(const btConvexTemplate& a,
+ const btConvexTemplate& b,
+ const btVector3& guess,
+ btGjkEpaSolver3::sResults& results)
+{
+ MinkowskiDiff<btConvexTemplate> shape(a,b);
+ Initialize(a,b,results,shape);
+ GJK<btConvexTemplate> gjk(a,b);
+ eGjkStatus gjk_status=gjk.Evaluate(shape,-guess);
+ switch(gjk_status)
+ {
+ case eGjkInside:
+ {
+ EPA<btConvexTemplate> epa;
+ eEpaStatus epa_status=epa.Evaluate(gjk,-guess);
+ if(epa_status!=eEpaFailed)
+ {
+ btVector3 w0=btVector3(0,0,0);
+ for(U i=0;i<epa.m_result.rank;++i)
+ {
+ w0+=shape.Support(epa.m_result.c[i]->d,0)*epa.m_result.p[i];
+ }
+ results.status = btGjkEpaSolver3::sResults::Penetrating;
+ results.witnesses[0] = a.getWorldTransform()*w0;
+ results.witnesses[1] = a.getWorldTransform()*(w0-epa.m_normal*epa.m_depth);
+ results.normal = -epa.m_normal;
+ results.distance = -epa.m_depth;
+ return(true);
+ } else results.status=btGjkEpaSolver3::sResults::EPA_Failed;
+ }
+ break;
+ case eGjkFailed:
+ results.status=btGjkEpaSolver3::sResults::GJK_Failed;
+ break;
+ default:
+ {
+ }
+ }
+ return(false);
+}
+
+#if 0
+int btComputeGjkEpaPenetration2(const btCollisionDescription& colDesc, btDistanceInfo* distInfo)
+{
+ btGjkEpaSolver3::sResults results;
+ btVector3 guess = colDesc.m_firstDir;
+
+ bool res = btGjkEpaSolver3::Penetration(colDesc.m_objA,colDesc.m_objB,
+ colDesc.m_transformA,colDesc.m_transformB,
+ colDesc.m_localSupportFuncA,colDesc.m_localSupportFuncB,
+ guess,
+ results);
+ if (res)
+ {
+ if ((results.status==btGjkEpaSolver3::sResults::Penetrating) || results.status==GJK::eStatus::Inside)
+ {
+ //normal could be 'swapped'
+
+ distInfo->m_distance = results.distance;
+ distInfo->m_normalBtoA = results.normal;
+ btVector3 tmpNormalInB = results.witnesses[1]-results.witnesses[0];
+ btScalar lenSqr = tmpNormalInB.length2();
+ if (lenSqr <= (SIMD_EPSILON*SIMD_EPSILON))
+ {
+ tmpNormalInB = results.normal;
+ lenSqr = results.normal.length2();
+ }
+
+ if (lenSqr > (SIMD_EPSILON*SIMD_EPSILON))
+ {
+ tmpNormalInB /= btSqrt(lenSqr);
+ btScalar distance2 = -(results.witnesses[0]-results.witnesses[1]).length();
+ //only replace valid penetrations when the result is deeper (check)
+ //if ((distance2 < results.distance))
+ {
+ distInfo->m_distance = distance2;
+ distInfo->m_pointOnA= results.witnesses[0];
+ distInfo->m_pointOnB= results.witnesses[1];
+ distInfo->m_normalBtoA= tmpNormalInB;
+ return 0;
+ }
+ }
+ }
+
+ }
+
+ return -1;
+}
+#endif
+
+template <typename btConvexTemplate, typename btDistanceInfoTemplate>
+int btComputeGjkDistance(const btConvexTemplate& a, const btConvexTemplate& b,
+ const btGjkCollisionDescription& colDesc, btDistanceInfoTemplate* distInfo)
+{
+ btGjkEpaSolver3::sResults results;
+ btVector3 guess = colDesc.m_firstDir;
+
+ bool isSeparated = btGjkEpaSolver3_Distance( a,b,
+ guess,
+ results);
+ if (isSeparated)
+ {
+ distInfo->m_distance = results.distance;
+ distInfo->m_pointOnA= results.witnesses[0];
+ distInfo->m_pointOnB= results.witnesses[1];
+ distInfo->m_normalBtoA= results.normal;
+ return 0;
+ }
+
+ return -1;
+}
+
+/* Symbols cleanup */
+
+#undef GJK_MAX_ITERATIONS
+#undef GJK_ACCURARY
+#undef GJK_MIN_DISTANCE
+#undef GJK_DUPLICATED_EPS
+#undef GJK_SIMPLEX2_EPS
+#undef GJK_SIMPLEX3_EPS
+#undef GJK_SIMPLEX4_EPS
+
+#undef EPA_MAX_VERTICES
+#undef EPA_MAX_FACES
+#undef EPA_MAX_ITERATIONS
+#undef EPA_ACCURACY
+#undef EPA_FALLBACK
+#undef EPA_PLANE_EPS
+#undef EPA_INSIDE_EPS
+
+
+
+#endif //BT_GJK_EPA3_H
+
diff --git a/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp
new file mode 100644
index 0000000000..572ec36f56
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp
@@ -0,0 +1,66 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+EPA Copyright (c) Ricardo Padrela 2006
+
+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 "BulletCollision/CollisionShapes/btConvexShape.h"
+#include "btGjkEpaPenetrationDepthSolver.h"
+
+
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h"
+
+bool btGjkEpaPenetrationDepthSolver::calcPenDepth( btSimplexSolverInterface& simplexSolver,
+ const btConvexShape* pConvexA, const btConvexShape* pConvexB,
+ const btTransform& transformA, const btTransform& transformB,
+ btVector3& v, btVector3& wWitnessOnA, btVector3& wWitnessOnB,
+ class btIDebugDraw* debugDraw)
+{
+
+ (void)debugDraw;
+ (void)v;
+ (void)simplexSolver;
+
+// const btScalar radialmargin(btScalar(0.));
+
+ btVector3 guessVector(transformB.getOrigin()-transformA.getOrigin());
+ btGjkEpaSolver2::sResults results;
+
+
+ if(btGjkEpaSolver2::Penetration(pConvexA,transformA,
+ pConvexB,transformB,
+ guessVector,results))
+
+ {
+ // debugDraw->drawLine(results.witnesses[1],results.witnesses[1]+results.normal,btVector3(255,0,0));
+ //resultOut->addContactPoint(results.normal,results.witnesses[1],-results.depth);
+ wWitnessOnA = results.witnesses[0];
+ wWitnessOnB = results.witnesses[1];
+ v = results.normal;
+ return true;
+ } else
+ {
+ if(btGjkEpaSolver2::Distance(pConvexA,transformA,pConvexB,transformB,guessVector,results))
+ {
+ wWitnessOnA = results.witnesses[0];
+ wWitnessOnB = results.witnesses[1];
+ v = results.normal;
+ return false;
+ }
+ }
+
+ return false;
+}
+
+
diff --git a/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h
new file mode 100644
index 0000000000..1ed6340af3
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h
@@ -0,0 +1,43 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+EPA Copyright (c) Ricardo Padrela 2006
+
+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_GJP_EPA_PENETRATION_DEPTH_H
+#define BT_GJP_EPA_PENETRATION_DEPTH_H
+
+#include "btConvexPenetrationDepthSolver.h"
+
+///EpaPenetrationDepthSolver uses the Expanding Polytope Algorithm to
+///calculate the penetration depth between two convex shapes.
+class btGjkEpaPenetrationDepthSolver : public btConvexPenetrationDepthSolver
+{
+ public :
+
+ btGjkEpaPenetrationDepthSolver()
+ {
+ }
+
+ bool calcPenDepth( btSimplexSolverInterface& simplexSolver,
+ const btConvexShape* pConvexA, const btConvexShape* pConvexB,
+ const btTransform& transformA, const btTransform& transformB,
+ btVector3& v, btVector3& wWitnessOnA, btVector3& wWitnessOnB,
+ class btIDebugDraw* debugDraw);
+
+ private :
+
+};
+
+#endif // BT_GJP_EPA_PENETRATION_DEPTH_H
+
diff --git a/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp
new file mode 100644
index 0000000000..257b026d9b
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp
@@ -0,0 +1,467 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btGjkPairDetector.h"
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+#include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h"
+#include "BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h"
+
+
+
+#if defined(DEBUG) || defined (_DEBUG)
+//#define TEST_NON_VIRTUAL 1
+#include <stdio.h> //for debug printf
+#ifdef __SPU__
+#include <spu_printf.h>
+#define printf spu_printf
+#endif //__SPU__
+#endif
+
+//must be above the machine epsilon
+#ifdef BT_USE_DOUBLE_PRECISION
+ #define REL_ERROR2 btScalar(1.0e-12)
+ btScalar gGjkEpaPenetrationTolerance = 1e-7;
+#else
+ #define REL_ERROR2 btScalar(1.0e-6)
+ btScalar gGjkEpaPenetrationTolerance = 0.001;
+#endif
+
+//temp globals, to improve GJK/EPA/penetration calculations
+int gNumDeepPenetrationChecks = 0;
+int gNumGjkChecks = 0;
+
+
+btGjkPairDetector::btGjkPairDetector(const btConvexShape* objectA,const btConvexShape* objectB,btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver* penetrationDepthSolver)
+:m_cachedSeparatingAxis(btScalar(0.),btScalar(1.),btScalar(0.)),
+m_penetrationDepthSolver(penetrationDepthSolver),
+m_simplexSolver(simplexSolver),
+m_minkowskiA(objectA),
+m_minkowskiB(objectB),
+m_shapeTypeA(objectA->getShapeType()),
+m_shapeTypeB(objectB->getShapeType()),
+m_marginA(objectA->getMargin()),
+m_marginB(objectB->getMargin()),
+m_ignoreMargin(false),
+m_lastUsedMethod(-1),
+m_catchDegeneracies(1),
+m_fixContactNormalDirection(1)
+{
+}
+btGjkPairDetector::btGjkPairDetector(const btConvexShape* objectA,const btConvexShape* objectB,int shapeTypeA,int shapeTypeB,btScalar marginA, btScalar marginB, btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver* penetrationDepthSolver)
+:m_cachedSeparatingAxis(btScalar(0.),btScalar(1.),btScalar(0.)),
+m_penetrationDepthSolver(penetrationDepthSolver),
+m_simplexSolver(simplexSolver),
+m_minkowskiA(objectA),
+m_minkowskiB(objectB),
+m_shapeTypeA(shapeTypeA),
+m_shapeTypeB(shapeTypeB),
+m_marginA(marginA),
+m_marginB(marginB),
+m_ignoreMargin(false),
+m_lastUsedMethod(-1),
+m_catchDegeneracies(1),
+m_fixContactNormalDirection(1)
+{
+}
+
+void btGjkPairDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults)
+{
+ (void)swapResults;
+
+ getClosestPointsNonVirtual(input,output,debugDraw);
+}
+
+#ifdef __SPU__
+void btGjkPairDetector::getClosestPointsNonVirtual(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw)
+#else
+void btGjkPairDetector::getClosestPointsNonVirtual(const ClosestPointInput& input, Result& output, class btIDebugDraw* debugDraw)
+#endif
+{
+ m_cachedSeparatingDistance = 0.f;
+
+ btScalar distance=btScalar(0.);
+ btVector3 normalInB(btScalar(0.),btScalar(0.),btScalar(0.));
+
+ btVector3 pointOnA,pointOnB;
+ btTransform localTransA = input.m_transformA;
+ btTransform localTransB = input.m_transformB;
+ btVector3 positionOffset=(localTransA.getOrigin() + localTransB.getOrigin()) * btScalar(0.5);
+ localTransA.getOrigin() -= positionOffset;
+ localTransB.getOrigin() -= positionOffset;
+
+ bool check2d = m_minkowskiA->isConvex2d() && m_minkowskiB->isConvex2d();
+
+ btScalar marginA = m_marginA;
+ btScalar marginB = m_marginB;
+
+ gNumGjkChecks++;
+
+ //for CCD we don't use margins
+ if (m_ignoreMargin)
+ {
+ marginA = btScalar(0.);
+ marginB = btScalar(0.);
+ }
+
+ m_curIter = 0;
+ int gGjkMaxIter = 1000;//this is to catch invalid input, perhaps check for #NaN?
+ m_cachedSeparatingAxis.setValue(0,1,0);
+
+ bool isValid = false;
+ bool checkSimplex = false;
+ bool checkPenetration = true;
+ m_degenerateSimplex = 0;
+
+ m_lastUsedMethod = -1;
+
+ {
+ btScalar squaredDistance = BT_LARGE_FLOAT;
+ btScalar delta = btScalar(0.);
+
+ btScalar margin = marginA + marginB;
+
+
+
+ m_simplexSolver->reset();
+
+ for ( ; ; )
+ //while (true)
+ {
+
+ btVector3 seperatingAxisInA = (-m_cachedSeparatingAxis)* input.m_transformA.getBasis();
+ btVector3 seperatingAxisInB = m_cachedSeparatingAxis* input.m_transformB.getBasis();
+
+
+ btVector3 pInA = m_minkowskiA->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInA);
+ btVector3 qInB = m_minkowskiB->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInB);
+
+ btVector3 pWorld = localTransA(pInA);
+ btVector3 qWorld = localTransB(qInB);
+
+
+ if (check2d)
+ {
+ pWorld[2] = 0.f;
+ qWorld[2] = 0.f;
+ }
+
+ btVector3 w = pWorld - qWorld;
+ delta = m_cachedSeparatingAxis.dot(w);
+
+ // potential exit, they don't overlap
+ if ((delta > btScalar(0.0)) && (delta * delta > squaredDistance * input.m_maximumDistanceSquared))
+ {
+ m_degenerateSimplex = 10;
+ checkSimplex=true;
+ //checkPenetration = false;
+ break;
+ }
+
+ //exit 0: the new point is already in the simplex, or we didn't come any closer
+ if (m_simplexSolver->inSimplex(w))
+ {
+ m_degenerateSimplex = 1;
+ checkSimplex = true;
+ break;
+ }
+ // are we getting any closer ?
+ btScalar f0 = squaredDistance - delta;
+ btScalar f1 = squaredDistance * REL_ERROR2;
+
+ if (f0 <= f1)
+ {
+ if (f0 <= btScalar(0.))
+ {
+ m_degenerateSimplex = 2;
+ } else
+ {
+ m_degenerateSimplex = 11;
+ }
+ checkSimplex = true;
+ break;
+ }
+
+ //add current vertex to simplex
+ m_simplexSolver->addVertex(w, pWorld, qWorld);
+ btVector3 newCachedSeparatingAxis;
+
+ //calculate the closest point to the origin (update vector v)
+ if (!m_simplexSolver->closest(newCachedSeparatingAxis))
+ {
+ m_degenerateSimplex = 3;
+ checkSimplex = true;
+ break;
+ }
+
+ if(newCachedSeparatingAxis.length2()<REL_ERROR2)
+ {
+ m_cachedSeparatingAxis = newCachedSeparatingAxis;
+ m_degenerateSimplex = 6;
+ checkSimplex = true;
+ break;
+ }
+
+ btScalar previousSquaredDistance = squaredDistance;
+ squaredDistance = newCachedSeparatingAxis.length2();
+#if 0
+///warning: this termination condition leads to some problems in 2d test case see Bullet/Demos/Box2dDemo
+ if (squaredDistance>previousSquaredDistance)
+ {
+ m_degenerateSimplex = 7;
+ squaredDistance = previousSquaredDistance;
+ checkSimplex = false;
+ break;
+ }
+#endif //
+
+
+ //redundant m_simplexSolver->compute_points(pointOnA, pointOnB);
+
+ //are we getting any closer ?
+ if (previousSquaredDistance - squaredDistance <= SIMD_EPSILON * previousSquaredDistance)
+ {
+// m_simplexSolver->backup_closest(m_cachedSeparatingAxis);
+ checkSimplex = true;
+ m_degenerateSimplex = 12;
+
+ break;
+ }
+
+ m_cachedSeparatingAxis = newCachedSeparatingAxis;
+
+ //degeneracy, this is typically due to invalid/uninitialized worldtransforms for a btCollisionObject
+ if (m_curIter++ > gGjkMaxIter)
+ {
+ #if defined(DEBUG) || defined (_DEBUG)
+
+ printf("btGjkPairDetector maxIter exceeded:%i\n",m_curIter);
+ printf("sepAxis=(%f,%f,%f), squaredDistance = %f, shapeTypeA=%i,shapeTypeB=%i\n",
+ m_cachedSeparatingAxis.getX(),
+ m_cachedSeparatingAxis.getY(),
+ m_cachedSeparatingAxis.getZ(),
+ squaredDistance,
+ m_minkowskiA->getShapeType(),
+ m_minkowskiB->getShapeType());
+
+ #endif
+ break;
+
+ }
+
+
+ bool check = (!m_simplexSolver->fullSimplex());
+ //bool check = (!m_simplexSolver->fullSimplex() && squaredDistance > SIMD_EPSILON * m_simplexSolver->maxVertex());
+
+ if (!check)
+ {
+ //do we need this backup_closest here ?
+// m_simplexSolver->backup_closest(m_cachedSeparatingAxis);
+ m_degenerateSimplex = 13;
+ break;
+ }
+ }
+
+ if (checkSimplex)
+ {
+ m_simplexSolver->compute_points(pointOnA, pointOnB);
+ normalInB = m_cachedSeparatingAxis;
+
+ btScalar lenSqr =m_cachedSeparatingAxis.length2();
+
+ //valid normal
+ if (lenSqr < REL_ERROR2)
+ {
+ m_degenerateSimplex = 5;
+ }
+ if (lenSqr > SIMD_EPSILON*SIMD_EPSILON)
+ {
+ btScalar rlen = btScalar(1.) / btSqrt(lenSqr );
+ normalInB *= rlen; //normalize
+
+ btScalar s = btSqrt(squaredDistance);
+
+ btAssert(s > btScalar(0.0));
+ pointOnA -= m_cachedSeparatingAxis * (marginA / s);
+ pointOnB += m_cachedSeparatingAxis * (marginB / s);
+ distance = ((btScalar(1.)/rlen) - margin);
+ isValid = true;
+
+ m_lastUsedMethod = 1;
+ } else
+ {
+ m_lastUsedMethod = 2;
+ }
+ }
+
+ bool catchDegeneratePenetrationCase =
+ (m_catchDegeneracies && m_penetrationDepthSolver && m_degenerateSimplex && ((distance+margin) < gGjkEpaPenetrationTolerance));
+
+ //if (checkPenetration && !isValid)
+ if (checkPenetration && (!isValid || catchDegeneratePenetrationCase ))
+ {
+ //penetration case
+
+ //if there is no way to handle penetrations, bail out
+ if (m_penetrationDepthSolver)
+ {
+ // Penetration depth case.
+ btVector3 tmpPointOnA,tmpPointOnB;
+
+ gNumDeepPenetrationChecks++;
+ m_cachedSeparatingAxis.setZero();
+
+ bool isValid2 = m_penetrationDepthSolver->calcPenDepth(
+ *m_simplexSolver,
+ m_minkowskiA,m_minkowskiB,
+ localTransA,localTransB,
+ m_cachedSeparatingAxis, tmpPointOnA, tmpPointOnB,
+ debugDraw
+ );
+
+
+ if (isValid2)
+ {
+ btVector3 tmpNormalInB = tmpPointOnB-tmpPointOnA;
+ btScalar lenSqr = tmpNormalInB.length2();
+ if (lenSqr <= (SIMD_EPSILON*SIMD_EPSILON))
+ {
+ tmpNormalInB = m_cachedSeparatingAxis;
+ lenSqr = m_cachedSeparatingAxis.length2();
+ }
+
+ if (lenSqr > (SIMD_EPSILON*SIMD_EPSILON))
+ {
+ tmpNormalInB /= btSqrt(lenSqr);
+ btScalar distance2 = -(tmpPointOnA-tmpPointOnB).length();
+ m_lastUsedMethod = 3;
+ //only replace valid penetrations when the result is deeper (check)
+ if (!isValid || (distance2 < distance))
+ {
+ distance = distance2;
+ pointOnA = tmpPointOnA;
+ pointOnB = tmpPointOnB;
+ normalInB = tmpNormalInB;
+
+ isValid = true;
+
+ } else
+ {
+ m_lastUsedMethod = 8;
+ }
+ } else
+ {
+ m_lastUsedMethod = 9;
+ }
+ } else
+
+ {
+ ///this is another degenerate case, where the initial GJK calculation reports a degenerate case
+ ///EPA reports no penetration, and the second GJK (using the supporting vector without margin)
+ ///reports a valid positive distance. Use the results of the second GJK instead of failing.
+ ///thanks to Jacob.Langford for the reproduction case
+ ///http://code.google.com/p/bullet/issues/detail?id=250
+
+
+ if (m_cachedSeparatingAxis.length2() > btScalar(0.))
+ {
+ btScalar distance2 = (tmpPointOnA-tmpPointOnB).length()-margin;
+ //only replace valid distances when the distance is less
+ if (!isValid || (distance2 < distance))
+ {
+ distance = distance2;
+ pointOnA = tmpPointOnA;
+ pointOnB = tmpPointOnB;
+ pointOnA -= m_cachedSeparatingAxis * marginA ;
+ pointOnB += m_cachedSeparatingAxis * marginB ;
+ normalInB = m_cachedSeparatingAxis;
+ normalInB.normalize();
+
+ isValid = true;
+ m_lastUsedMethod = 6;
+ } else
+ {
+ m_lastUsedMethod = 5;
+ }
+ }
+ }
+
+ }
+
+ }
+ }
+
+
+
+ if (isValid && ((distance < 0) || (distance*distance < input.m_maximumDistanceSquared)))
+ {
+
+ m_cachedSeparatingAxis = normalInB;
+ m_cachedSeparatingDistance = distance;
+
+ {
+ ///todo: need to track down this EPA penetration solver degeneracy
+ ///the penetration solver reports penetration but the contact normal
+ ///connecting the contact points is pointing in the opposite direction
+ ///until then, detect the issue and revert the normal
+
+ btScalar d1=0;
+ {
+ btVector3 seperatingAxisInA = (normalInB)* input.m_transformA.getBasis();
+ btVector3 seperatingAxisInB = -normalInB* input.m_transformB.getBasis();
+
+
+ btVector3 pInA = m_minkowskiA->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInA);
+ btVector3 qInB = m_minkowskiB->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInB);
+
+ btVector3 pWorld = localTransA(pInA);
+ btVector3 qWorld = localTransB(qInB);
+ btVector3 w = pWorld - qWorld;
+ d1 = (-normalInB).dot(w);
+ }
+ btScalar d0 = 0.f;
+ {
+ btVector3 seperatingAxisInA = (-normalInB)* input.m_transformA.getBasis();
+ btVector3 seperatingAxisInB = normalInB* input.m_transformB.getBasis();
+
+
+ btVector3 pInA = m_minkowskiA->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInA);
+ btVector3 qInB = m_minkowskiB->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInB);
+
+ btVector3 pWorld = localTransA(pInA);
+ btVector3 qWorld = localTransB(qInB);
+ btVector3 w = pWorld - qWorld;
+ d0 = normalInB.dot(w);
+ }
+ if (d1>d0)
+ {
+ m_lastUsedMethod = 10;
+ normalInB*=-1;
+ }
+
+ }
+ output.addContactPoint(
+ normalInB,
+ pointOnB+positionOffset,
+ distance);
+
+ }
+
+
+}
+
+
+
+
+
diff --git a/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h
new file mode 100644
index 0000000000..feeae68621
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h
@@ -0,0 +1,103 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+
+#ifndef BT_GJK_PAIR_DETECTOR_H
+#define BT_GJK_PAIR_DETECTOR_H
+
+#include "btDiscreteCollisionDetectorInterface.h"
+#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
+
+class btConvexShape;
+#include "btSimplexSolverInterface.h"
+class btConvexPenetrationDepthSolver;
+
+/// btGjkPairDetector uses GJK to implement the btDiscreteCollisionDetectorInterface
+class btGjkPairDetector : public btDiscreteCollisionDetectorInterface
+{
+
+
+ btVector3 m_cachedSeparatingAxis;
+ btConvexPenetrationDepthSolver* m_penetrationDepthSolver;
+ btSimplexSolverInterface* m_simplexSolver;
+ const btConvexShape* m_minkowskiA;
+ const btConvexShape* m_minkowskiB;
+ int m_shapeTypeA;
+ int m_shapeTypeB;
+ btScalar m_marginA;
+ btScalar m_marginB;
+
+ bool m_ignoreMargin;
+ btScalar m_cachedSeparatingDistance;
+
+
+public:
+
+ //some debugging to fix degeneracy problems
+ int m_lastUsedMethod;
+ int m_curIter;
+ int m_degenerateSimplex;
+ int m_catchDegeneracies;
+ int m_fixContactNormalDirection;
+
+ btGjkPairDetector(const btConvexShape* objectA,const btConvexShape* objectB,btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver* penetrationDepthSolver);
+ btGjkPairDetector(const btConvexShape* objectA,const btConvexShape* objectB,int shapeTypeA,int shapeTypeB,btScalar marginA, btScalar marginB, btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver* penetrationDepthSolver);
+ virtual ~btGjkPairDetector() {};
+
+ virtual void getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults=false);
+
+ void getClosestPointsNonVirtual(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw);
+
+
+ void setMinkowskiA(const btConvexShape* minkA)
+ {
+ m_minkowskiA = minkA;
+ }
+
+ void setMinkowskiB(const btConvexShape* minkB)
+ {
+ m_minkowskiB = minkB;
+ }
+ void setCachedSeperatingAxis(const btVector3& seperatingAxis)
+ {
+ m_cachedSeparatingAxis = seperatingAxis;
+ }
+
+ const btVector3& getCachedSeparatingAxis() const
+ {
+ return m_cachedSeparatingAxis;
+ }
+ btScalar getCachedSeparatingDistance() const
+ {
+ return m_cachedSeparatingDistance;
+ }
+
+ void setPenetrationDepthSolver(btConvexPenetrationDepthSolver* penetrationDepthSolver)
+ {
+ m_penetrationDepthSolver = penetrationDepthSolver;
+ }
+
+ ///don't use setIgnoreMargin, it's for Bullet's internal use
+ void setIgnoreMargin(bool ignoreMargin)
+ {
+ m_ignoreMargin = ignoreMargin;
+ }
+
+
+};
+
+#endif //BT_GJK_PAIR_DETECTOR_H
diff --git a/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h
new file mode 100644
index 0000000000..571ad2c5f7
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h
@@ -0,0 +1,180 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_MANIFOLD_CONTACT_POINT_H
+#define BT_MANIFOLD_CONTACT_POINT_H
+
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btTransformUtil.h"
+
+#ifdef PFX_USE_FREE_VECTORMATH
+ #include "physics_effects/base_level/solver/pfx_constraint_row.h"
+typedef sce::PhysicsEffects::PfxConstraintRow btConstraintRow;
+#else
+ // Don't change following order of parameters
+ ATTRIBUTE_ALIGNED16(struct) btConstraintRow {
+ btScalar m_normal[3];
+ btScalar m_rhs;
+ btScalar m_jacDiagInv;
+ btScalar m_lowerLimit;
+ btScalar m_upperLimit;
+ btScalar m_accumImpulse;
+ };
+ typedef btConstraintRow PfxConstraintRow;
+#endif //PFX_USE_FREE_VECTORMATH
+
+enum btContactPointFlags
+{
+ BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED=1,
+ BT_CONTACT_FLAG_HAS_CONTACT_CFM=2,
+ BT_CONTACT_FLAG_HAS_CONTACT_ERP=4,
+ BT_CONTACT_FLAG_CONTACT_STIFFNESS_DAMPING = 8,
+ BT_CONTACT_FLAG_FRICTION_ANCHOR = 16,
+};
+
+/// ManifoldContactPoint collects and maintains persistent contactpoints.
+/// used to improve stability and performance of rigidbody dynamics response.
+class btManifoldPoint
+ {
+ public:
+ btManifoldPoint()
+ :m_userPersistentData(0),
+ m_contactPointFlags(0),
+ m_appliedImpulse(0.f),
+ m_appliedImpulseLateral1(0.f),
+ m_appliedImpulseLateral2(0.f),
+ m_contactMotion1(0.f),
+ m_contactMotion2(0.f),
+ m_contactCFM(0.f),
+ m_contactERP(0.f),
+ m_frictionCFM(0.f),
+ m_lifeTime(0)
+ {
+ }
+
+ btManifoldPoint( const btVector3 &pointA, const btVector3 &pointB,
+ const btVector3 &normal,
+ btScalar distance ) :
+ m_localPointA( pointA ),
+ m_localPointB( pointB ),
+ m_normalWorldOnB( normal ),
+ m_distance1( distance ),
+ m_combinedFriction(btScalar(0.)),
+ m_combinedRollingFriction(btScalar(0.)),
+ m_combinedSpinningFriction(btScalar(0.)),
+ m_combinedRestitution(btScalar(0.)),
+ m_userPersistentData(0),
+ m_contactPointFlags(0),
+ m_appliedImpulse(0.f),
+ m_appliedImpulseLateral1(0.f),
+ m_appliedImpulseLateral2(0.f),
+ m_contactMotion1(0.f),
+ m_contactMotion2(0.f),
+ m_contactCFM(0.f),
+ m_contactERP(0.f),
+ m_frictionCFM(0.f),
+ m_lifeTime(0)
+ {
+
+ }
+
+
+
+ btVector3 m_localPointA;
+ btVector3 m_localPointB;
+ btVector3 m_positionWorldOnB;
+ ///m_positionWorldOnA is redundant information, see getPositionWorldOnA(), but for clarity
+ btVector3 m_positionWorldOnA;
+ btVector3 m_normalWorldOnB;
+
+ btScalar m_distance1;
+ btScalar m_combinedFriction;
+ btScalar m_combinedRollingFriction;//torsional friction orthogonal to contact normal, useful to make spheres stop rolling forever
+ btScalar m_combinedSpinningFriction;//torsional friction around contact normal, useful for grasping objects
+ btScalar m_combinedRestitution;
+
+ //BP mod, store contact triangles.
+ int m_partId0;
+ int m_partId1;
+ int m_index0;
+ int m_index1;
+
+ mutable void* m_userPersistentData;
+ //bool m_lateralFrictionInitialized;
+ int m_contactPointFlags;
+
+ btScalar m_appliedImpulse;
+ btScalar m_appliedImpulseLateral1;
+ btScalar m_appliedImpulseLateral2;
+ btScalar m_contactMotion1;
+ btScalar m_contactMotion2;
+
+ union
+ {
+ btScalar m_contactCFM;
+ btScalar m_combinedContactStiffness1;
+ };
+
+ union
+ {
+ btScalar m_contactERP;
+ btScalar m_combinedContactDamping1;
+ };
+
+ btScalar m_frictionCFM;
+
+ int m_lifeTime;//lifetime of the contactpoint in frames
+
+ btVector3 m_lateralFrictionDir1;
+ btVector3 m_lateralFrictionDir2;
+
+
+
+
+ btScalar getDistance() const
+ {
+ return m_distance1;
+ }
+ int getLifeTime() const
+ {
+ return m_lifeTime;
+ }
+
+ const btVector3& getPositionWorldOnA() const {
+ return m_positionWorldOnA;
+// return m_positionWorldOnB + m_normalWorldOnB * m_distance1;
+ }
+
+ const btVector3& getPositionWorldOnB() const
+ {
+ return m_positionWorldOnB;
+ }
+
+ void setDistance(btScalar dist)
+ {
+ m_distance1 = dist;
+ }
+
+ ///this returns the most recent applied impulse, to satisfy contact constraints by the constraint solver
+ btScalar getAppliedImpulse() const
+ {
+ return m_appliedImpulse;
+ }
+
+
+
+ };
+
+#endif //BT_MANIFOLD_CONTACT_POINT_H
diff --git a/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp
new file mode 100644
index 0000000000..fa45f49037
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp
@@ -0,0 +1,361 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btMinkowskiPenetrationDepthSolver.h"
+#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
+#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h"
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+
+#define NUM_UNITSPHERE_POINTS 42
+
+
+bool btMinkowskiPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& simplexSolver,
+ const btConvexShape* convexA,const btConvexShape* convexB,
+ const btTransform& transA,const btTransform& transB,
+ btVector3& v, btVector3& pa, btVector3& pb,
+ class btIDebugDraw* debugDraw
+ )
+{
+
+ (void)v;
+
+ bool check2d= convexA->isConvex2d() && convexB->isConvex2d();
+
+ struct btIntermediateResult : public btDiscreteCollisionDetectorInterface::Result
+ {
+
+ btIntermediateResult():m_hasResult(false)
+ {
+ }
+
+ btVector3 m_normalOnBInWorld;
+ btVector3 m_pointInWorld;
+ btScalar m_depth;
+ bool m_hasResult;
+
+ virtual void setShapeIdentifiersA(int partId0,int index0)
+ {
+ (void)partId0;
+ (void)index0;
+ }
+ virtual void setShapeIdentifiersB(int partId1,int index1)
+ {
+ (void)partId1;
+ (void)index1;
+ }
+ void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth)
+ {
+ m_normalOnBInWorld = normalOnBInWorld;
+ m_pointInWorld = pointInWorld;
+ m_depth = depth;
+ m_hasResult = true;
+ }
+ };
+
+ //just take fixed number of orientation, and sample the penetration depth in that direction
+ btScalar minProj = btScalar(BT_LARGE_FLOAT);
+ btVector3 minNorm(btScalar(0.), btScalar(0.), btScalar(0.));
+ btVector3 minA,minB;
+ btVector3 seperatingAxisInA,seperatingAxisInB;
+ btVector3 pInA,qInB,pWorld,qWorld,w;
+
+#ifndef __SPU__
+#define USE_BATCHED_SUPPORT 1
+#endif
+#ifdef USE_BATCHED_SUPPORT
+
+ 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];
+ int i;
+
+ int numSampleDirections = NUM_UNITSPHERE_POINTS;
+
+ for (i=0;i<numSampleDirections;i++)
+ {
+ btVector3 norm = getPenetrationDirections()[i];
+ seperatingAxisInABatch[i] = (-norm) * transA.getBasis() ;
+ seperatingAxisInBBatch[i] = norm * transB.getBasis() ;
+ }
+
+ {
+ int numPDA = convexA->getNumPreferredPenetrationDirections();
+ if (numPDA)
+ {
+ for (int i=0;i<numPDA;i++)
+ {
+ btVector3 norm;
+ convexA->getPreferredPenetrationDirection(i,norm);
+ norm = transA.getBasis() * norm;
+ getPenetrationDirections()[numSampleDirections] = norm;
+ seperatingAxisInABatch[numSampleDirections] = (-norm) * transA.getBasis();
+ seperatingAxisInBBatch[numSampleDirections] = norm * transB.getBasis();
+ numSampleDirections++;
+ }
+ }
+ }
+
+ {
+ int numPDB = convexB->getNumPreferredPenetrationDirections();
+ if (numPDB)
+ {
+ for (int i=0;i<numPDB;i++)
+ {
+ btVector3 norm;
+ convexB->getPreferredPenetrationDirection(i,norm);
+ norm = transB.getBasis() * norm;
+ getPenetrationDirections()[numSampleDirections] = norm;
+ seperatingAxisInABatch[numSampleDirections] = (-norm) * transA.getBasis();
+ seperatingAxisInBBatch[numSampleDirections] = norm * transB.getBasis();
+ numSampleDirections++;
+ }
+ }
+ }
+
+
+
+
+ convexA->batchedUnitVectorGetSupportingVertexWithoutMargin(seperatingAxisInABatch,supportVerticesABatch,numSampleDirections);
+ convexB->batchedUnitVectorGetSupportingVertexWithoutMargin(seperatingAxisInBBatch,supportVerticesBBatch,numSampleDirections);
+
+ for (i=0;i<numSampleDirections;i++)
+ {
+ btVector3 norm = getPenetrationDirections()[i];
+ if (check2d)
+ {
+ norm[2] = 0.f;
+ }
+ if (norm.length2()>0.01)
+ {
+
+ seperatingAxisInA = seperatingAxisInABatch[i];
+ seperatingAxisInB = seperatingAxisInBBatch[i];
+
+ pInA = supportVerticesABatch[i];
+ qInB = supportVerticesBBatch[i];
+
+ pWorld = transA(pInA);
+ qWorld = transB(qInB);
+ if (check2d)
+ {
+ pWorld[2] = 0.f;
+ qWorld[2] = 0.f;
+ }
+
+ w = qWorld - pWorld;
+ btScalar delta = norm.dot(w);
+ //find smallest delta
+ if (delta < minProj)
+ {
+ minProj = delta;
+ minNorm = norm;
+ minA = pWorld;
+ minB = qWorld;
+ }
+ }
+ }
+#else
+
+ int numSampleDirections = NUM_UNITSPHERE_POINTS;
+
+#ifndef __SPU__
+ {
+ int numPDA = convexA->getNumPreferredPenetrationDirections();
+ if (numPDA)
+ {
+ for (int i=0;i<numPDA;i++)
+ {
+ btVector3 norm;
+ convexA->getPreferredPenetrationDirection(i,norm);
+ norm = transA.getBasis() * norm;
+ getPenetrationDirections()[numSampleDirections] = norm;
+ numSampleDirections++;
+ }
+ }
+ }
+
+ {
+ int numPDB = convexB->getNumPreferredPenetrationDirections();
+ if (numPDB)
+ {
+ for (int i=0;i<numPDB;i++)
+ {
+ btVector3 norm;
+ convexB->getPreferredPenetrationDirection(i,norm);
+ norm = transB.getBasis() * norm;
+ getPenetrationDirections()[numSampleDirections] = norm;
+ numSampleDirections++;
+ }
+ }
+ }
+#endif // __SPU__
+
+ 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);
+ pWorld = transA(pInA);
+ qWorld = transB(qInB);
+ w = qWorld - pWorld;
+ btScalar delta = norm.dot(w);
+ //find smallest delta
+ if (delta < minProj)
+ {
+ minProj = delta;
+ minNorm = norm;
+ minA = pWorld;
+ minB = qWorld;
+ }
+ }
+#endif //USE_BATCHED_SUPPORT
+
+ //add the margins
+
+ minA += minNorm*convexA->getMarginNonVirtual();
+ minB -= minNorm*convexB->getMarginNonVirtual();
+ //no penetration
+ if (minProj < btScalar(0.))
+ return false;
+
+ btScalar extraSeparation = 0.5f;///scale dependent
+ minProj += extraSeparation+(convexA->getMarginNonVirtual() + convexB->getMarginNonVirtual());
+
+
+
+
+
+//#define DEBUG_DRAW 1
+#ifdef DEBUG_DRAW
+ if (debugDraw)
+ {
+ btVector3 color(0,1,0);
+ debugDraw->drawLine(minA,minB,color);
+ color = btVector3 (1,1,1);
+ btVector3 vec = minB-minA;
+ btScalar prj2 = minNorm.dot(vec);
+ debugDraw->drawLine(minA,minA+(minNorm*minProj),color);
+
+ }
+#endif //DEBUG_DRAW
+
+
+
+ btGjkPairDetector gjkdet(convexA,convexB,&simplexSolver,0);
+
+ btScalar offsetDist = minProj;
+ btVector3 offset = minNorm * offsetDist;
+
+
+
+ btGjkPairDetector::ClosestPointInput input;
+
+ btVector3 newOrg = transA.getOrigin() + offset;
+
+ btTransform displacedTrans = transA;
+ displacedTrans.setOrigin(newOrg);
+
+ input.m_transformA = displacedTrans;
+ input.m_transformB = transB;
+ input.m_maximumDistanceSquared = btScalar(BT_LARGE_FLOAT);//minProj;
+
+ btIntermediateResult res;
+ gjkdet.setCachedSeperatingAxis(-minNorm);
+ gjkdet.getClosestPoints(input,res,debugDraw);
+
+ btScalar correctedMinNorm = minProj - res.m_depth;
+
+
+ //the penetration depth is over-estimated, relax it
+ btScalar penetration_relaxation= btScalar(1.);
+ minNorm*=penetration_relaxation;
+
+
+ if (res.m_hasResult)
+ {
+
+ pa = res.m_pointInWorld - minNorm * correctedMinNorm;
+ pb = res.m_pointInWorld;
+ v = minNorm;
+
+#ifdef DEBUG_DRAW
+ if (debugDraw)
+ {
+ btVector3 color(1,0,0);
+ debugDraw->drawLine(pa,pb,color);
+ }
+#endif//DEBUG_DRAW
+
+
+ }
+ return res.m_hasResult;
+}
+
+btVector3* btMinkowskiPenetrationDepthSolver::getPenetrationDirections()
+{
+ static btVector3 sPenetrationDirections[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2] =
+ {
+ btVector3(btScalar(0.000000) , btScalar(-0.000000),btScalar(-1.000000)),
+ btVector3(btScalar(0.723608) , btScalar(-0.525725),btScalar(-0.447219)),
+ btVector3(btScalar(-0.276388) , btScalar(-0.850649),btScalar(-0.447219)),
+ btVector3(btScalar(-0.894426) , btScalar(-0.000000),btScalar(-0.447216)),
+ btVector3(btScalar(-0.276388) , btScalar(0.850649),btScalar(-0.447220)),
+ btVector3(btScalar(0.723608) , btScalar(0.525725),btScalar(-0.447219)),
+ btVector3(btScalar(0.276388) , btScalar(-0.850649),btScalar(0.447220)),
+ btVector3(btScalar(-0.723608) , btScalar(-0.525725),btScalar(0.447219)),
+ btVector3(btScalar(-0.723608) , btScalar(0.525725),btScalar(0.447219)),
+ btVector3(btScalar(0.276388) , btScalar(0.850649),btScalar(0.447219)),
+ btVector3(btScalar(0.894426) , btScalar(0.000000),btScalar(0.447216)),
+ btVector3(btScalar(-0.000000) , btScalar(0.000000),btScalar(1.000000)),
+ btVector3(btScalar(0.425323) , btScalar(-0.309011),btScalar(-0.850654)),
+ btVector3(btScalar(-0.162456) , btScalar(-0.499995),btScalar(-0.850654)),
+ btVector3(btScalar(0.262869) , btScalar(-0.809012),btScalar(-0.525738)),
+ btVector3(btScalar(0.425323) , btScalar(0.309011),btScalar(-0.850654)),
+ btVector3(btScalar(0.850648) , btScalar(-0.000000),btScalar(-0.525736)),
+ btVector3(btScalar(-0.525730) , btScalar(-0.000000),btScalar(-0.850652)),
+ btVector3(btScalar(-0.688190) , btScalar(-0.499997),btScalar(-0.525736)),
+ btVector3(btScalar(-0.162456) , btScalar(0.499995),btScalar(-0.850654)),
+ btVector3(btScalar(-0.688190) , btScalar(0.499997),btScalar(-0.525736)),
+ btVector3(btScalar(0.262869) , btScalar(0.809012),btScalar(-0.525738)),
+ btVector3(btScalar(0.951058) , btScalar(0.309013),btScalar(0.000000)),
+ btVector3(btScalar(0.951058) , btScalar(-0.309013),btScalar(0.000000)),
+ btVector3(btScalar(0.587786) , btScalar(-0.809017),btScalar(0.000000)),
+ btVector3(btScalar(0.000000) , btScalar(-1.000000),btScalar(0.000000)),
+ btVector3(btScalar(-0.587786) , btScalar(-0.809017),btScalar(0.000000)),
+ btVector3(btScalar(-0.951058) , btScalar(-0.309013),btScalar(-0.000000)),
+ btVector3(btScalar(-0.951058) , btScalar(0.309013),btScalar(-0.000000)),
+ btVector3(btScalar(-0.587786) , btScalar(0.809017),btScalar(-0.000000)),
+ btVector3(btScalar(-0.000000) , btScalar(1.000000),btScalar(-0.000000)),
+ btVector3(btScalar(0.587786) , btScalar(0.809017),btScalar(-0.000000)),
+ btVector3(btScalar(0.688190) , btScalar(-0.499997),btScalar(0.525736)),
+ btVector3(btScalar(-0.262869) , btScalar(-0.809012),btScalar(0.525738)),
+ btVector3(btScalar(-0.850648) , btScalar(0.000000),btScalar(0.525736)),
+ btVector3(btScalar(-0.262869) , btScalar(0.809012),btScalar(0.525738)),
+ btVector3(btScalar(0.688190) , btScalar(0.499997),btScalar(0.525736)),
+ btVector3(btScalar(0.525730) , btScalar(0.000000),btScalar(0.850652)),
+ btVector3(btScalar(0.162456) , btScalar(-0.499995),btScalar(0.850654)),
+ btVector3(btScalar(-0.425323) , btScalar(-0.309011),btScalar(0.850654)),
+ btVector3(btScalar(-0.425323) , btScalar(0.309011),btScalar(0.850654)),
+ btVector3(btScalar(0.162456) , btScalar(0.499995),btScalar(0.850654))
+ };
+
+ return sPenetrationDirections;
+}
+
+
diff --git a/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h
new file mode 100644
index 0000000000..fd533b4fc3
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h
@@ -0,0 +1,40 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_MINKOWSKI_PENETRATION_DEPTH_SOLVER_H
+#define BT_MINKOWSKI_PENETRATION_DEPTH_SOLVER_H
+
+#include "btConvexPenetrationDepthSolver.h"
+
+///MinkowskiPenetrationDepthSolver implements bruteforce penetration depth estimation.
+///Implementation is based on sampling the depth using support mapping, and using GJK step to get the witness points.
+class btMinkowskiPenetrationDepthSolver : public btConvexPenetrationDepthSolver
+{
+protected:
+
+ static btVector3* getPenetrationDirections();
+
+public:
+
+ virtual bool calcPenDepth( btSimplexSolverInterface& simplexSolver,
+ const btConvexShape* convexA,const btConvexShape* convexB,
+ const btTransform& transA,const btTransform& transB,
+ btVector3& v, btVector3& pa, btVector3& pb,
+ class btIDebugDraw* debugDraw
+ );
+};
+
+#endif //BT_MINKOWSKI_PENETRATION_DEPTH_SOLVER_H
+
diff --git a/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btMprPenetration.h b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btMprPenetration.h
new file mode 100644
index 0000000000..a22a0bae66
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btMprPenetration.h
@@ -0,0 +1,908 @@
+
+/***
+ * ---------------------------------
+ * Copyright (c)2012 Daniel Fiser <danfis@danfis.cz>
+ *
+ * This file was ported from mpr.c file, part of libccd.
+ * The Minkoski Portal Refinement implementation was ported
+ * to OpenCL by Erwin Coumans for the Bullet 3 Physics library.
+ * The original MPR idea and implementation is by Gary Snethen
+ * in XenoCollide, see http://github.com/erwincoumans/xenocollide
+ *
+ * Distributed under the OSI-approved BSD License (the "License");
+ * see <http://www.opensource.org/licenses/bsd-license.php>.
+ * This software is distributed WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the License for more information.
+ */
+
+///2014 Oct, Erwin Coumans, Use templates to avoid void* casts
+
+#ifndef BT_MPR_PENETRATION_H
+#define BT_MPR_PENETRATION_H
+
+#define BT_DEBUG_MPR1
+
+#include "LinearMath/btTransform.h"
+#include "LinearMath/btAlignedObjectArray.h"
+
+//#define MPR_AVERAGE_CONTACT_POSITIONS
+
+
+struct btMprCollisionDescription
+{
+ btVector3 m_firstDir;
+ int m_maxGjkIterations;
+ btScalar m_maximumDistanceSquared;
+ btScalar m_gjkRelError2;
+
+ btMprCollisionDescription()
+ : m_firstDir(0,1,0),
+ m_maxGjkIterations(1000),
+ m_maximumDistanceSquared(1e30f),
+ m_gjkRelError2(1.0e-6)
+ {
+ }
+ virtual ~btMprCollisionDescription()
+ {
+ }
+};
+
+struct btMprDistanceInfo
+{
+ btVector3 m_pointOnA;
+ btVector3 m_pointOnB;
+ btVector3 m_normalBtoA;
+ btScalar m_distance;
+};
+
+#ifdef __cplusplus
+#define BT_MPR_SQRT sqrtf
+#else
+#define BT_MPR_SQRT sqrt
+#endif
+#define BT_MPR_FMIN(x, y) ((x) < (y) ? (x) : (y))
+#define BT_MPR_FABS fabs
+
+#define BT_MPR_TOLERANCE 1E-6f
+#define BT_MPR_MAX_ITERATIONS 1000
+
+struct _btMprSupport_t
+{
+ btVector3 v; //!< Support point in minkowski sum
+ btVector3 v1; //!< Support point in obj1
+ btVector3 v2; //!< Support point in obj2
+};
+typedef struct _btMprSupport_t btMprSupport_t;
+
+struct _btMprSimplex_t
+{
+ btMprSupport_t ps[4];
+ int last; //!< index of last added point
+};
+typedef struct _btMprSimplex_t btMprSimplex_t;
+
+inline btMprSupport_t* btMprSimplexPointW(btMprSimplex_t *s, int idx)
+{
+ return &s->ps[idx];
+}
+
+inline void btMprSimplexSetSize(btMprSimplex_t *s, int size)
+{
+ s->last = size - 1;
+}
+
+#ifdef DEBUG_MPR
+inline void btPrintPortalVertex(_btMprSimplex_t* portal, int index)
+{
+ printf("portal[%d].v = %f,%f,%f, v1=%f,%f,%f, v2=%f,%f,%f\n", index, portal->ps[index].v.x(),portal->ps[index].v.y(),portal->ps[index].v.z(),
+ portal->ps[index].v1.x(),portal->ps[index].v1.y(),portal->ps[index].v1.z(),
+ portal->ps[index].v2.x(),portal->ps[index].v2.y(),portal->ps[index].v2.z());
+}
+#endif //DEBUG_MPR
+
+
+
+
+inline int btMprSimplexSize(const btMprSimplex_t *s)
+{
+ return s->last + 1;
+}
+
+
+inline const btMprSupport_t* btMprSimplexPoint(const btMprSimplex_t* s, int idx)
+{
+ // here is no check on boundaries
+ return &s->ps[idx];
+}
+
+inline void btMprSupportCopy(btMprSupport_t *d, const btMprSupport_t *s)
+{
+ *d = *s;
+}
+
+inline void btMprSimplexSet(btMprSimplex_t *s, size_t pos, const btMprSupport_t *a)
+{
+ btMprSupportCopy(s->ps + pos, a);
+}
+
+
+inline void btMprSimplexSwap(btMprSimplex_t *s, size_t pos1, size_t pos2)
+{
+ btMprSupport_t supp;
+
+ btMprSupportCopy(&supp, &s->ps[pos1]);
+ btMprSupportCopy(&s->ps[pos1], &s->ps[pos2]);
+ btMprSupportCopy(&s->ps[pos2], &supp);
+}
+
+
+inline int btMprIsZero(float val)
+{
+ return BT_MPR_FABS(val) < FLT_EPSILON;
+}
+
+
+
+inline int btMprEq(float _a, float _b)
+{
+ float ab;
+ float a, b;
+
+ ab = BT_MPR_FABS(_a - _b);
+ if (BT_MPR_FABS(ab) < FLT_EPSILON)
+ return 1;
+
+ a = BT_MPR_FABS(_a);
+ b = BT_MPR_FABS(_b);
+ if (b > a){
+ return ab < FLT_EPSILON * b;
+ }else{
+ return ab < FLT_EPSILON * a;
+ }
+}
+
+
+inline int btMprVec3Eq(const btVector3* a, const btVector3 *b)
+{
+ return btMprEq((*a).x(), (*b).x())
+ && btMprEq((*a).y(), (*b).y())
+ && btMprEq((*a).z(), (*b).z());
+}
+
+
+
+
+
+
+
+
+
+
+
+template <typename btConvexTemplate>
+inline void btFindOrigin(const btConvexTemplate& a, const btConvexTemplate& b, const btMprCollisionDescription& colDesc,btMprSupport_t *center)
+{
+
+ center->v1 = a.getObjectCenterInWorld();
+ center->v2 = b.getObjectCenterInWorld();
+ center->v = center->v1 - center->v2;
+}
+
+inline void btMprVec3Set(btVector3 *v, float x, float y, float z)
+{
+ v->setValue(x,y,z);
+}
+
+inline void btMprVec3Add(btVector3 *v, const btVector3 *w)
+{
+ *v += *w;
+}
+
+inline void btMprVec3Copy(btVector3 *v, const btVector3 *w)
+{
+ *v = *w;
+}
+
+inline void btMprVec3Scale(btVector3 *d, float k)
+{
+ *d *= k;
+}
+
+inline float btMprVec3Dot(const btVector3 *a, const btVector3 *b)
+{
+ float dot;
+
+ dot = btDot(*a,*b);
+ return dot;
+}
+
+
+inline float btMprVec3Len2(const btVector3 *v)
+{
+ return btMprVec3Dot(v, v);
+}
+
+inline void btMprVec3Normalize(btVector3 *d)
+{
+ float k = 1.f / BT_MPR_SQRT(btMprVec3Len2(d));
+ btMprVec3Scale(d, k);
+}
+
+inline void btMprVec3Cross(btVector3 *d, const btVector3 *a, const btVector3 *b)
+{
+ *d = btCross(*a,*b);
+
+}
+
+
+inline void btMprVec3Sub2(btVector3 *d, const btVector3 *v, const btVector3 *w)
+{
+ *d = *v - *w;
+}
+
+inline void btPortalDir(const btMprSimplex_t *portal, btVector3 *dir)
+{
+ btVector3 v2v1, v3v1;
+
+ btMprVec3Sub2(&v2v1, &btMprSimplexPoint(portal, 2)->v,
+ &btMprSimplexPoint(portal, 1)->v);
+ btMprVec3Sub2(&v3v1, &btMprSimplexPoint(portal, 3)->v,
+ &btMprSimplexPoint(portal, 1)->v);
+ btMprVec3Cross(dir, &v2v1, &v3v1);
+ btMprVec3Normalize(dir);
+}
+
+
+inline int portalEncapsulesOrigin(const btMprSimplex_t *portal,
+ const btVector3 *dir)
+{
+ float dot;
+ dot = btMprVec3Dot(dir, &btMprSimplexPoint(portal, 1)->v);
+ return btMprIsZero(dot) || dot > 0.f;
+}
+
+inline int portalReachTolerance(const btMprSimplex_t *portal,
+ const btMprSupport_t *v4,
+ const btVector3 *dir)
+{
+ float dv1, dv2, dv3, dv4;
+ float dot1, dot2, dot3;
+
+ // find the smallest dot product of dir and {v1-v4, v2-v4, v3-v4}
+
+ dv1 = btMprVec3Dot(&btMprSimplexPoint(portal, 1)->v, dir);
+ dv2 = btMprVec3Dot(&btMprSimplexPoint(portal, 2)->v, dir);
+ dv3 = btMprVec3Dot(&btMprSimplexPoint(portal, 3)->v, dir);
+ dv4 = btMprVec3Dot(&v4->v, dir);
+
+ dot1 = dv4 - dv1;
+ dot2 = dv4 - dv2;
+ dot3 = dv4 - dv3;
+
+ dot1 = BT_MPR_FMIN(dot1, dot2);
+ dot1 = BT_MPR_FMIN(dot1, dot3);
+
+ return btMprEq(dot1, BT_MPR_TOLERANCE) || dot1 < BT_MPR_TOLERANCE;
+}
+
+inline int portalCanEncapsuleOrigin(const btMprSimplex_t *portal,
+ const btMprSupport_t *v4,
+ const btVector3 *dir)
+{
+ float dot;
+ dot = btMprVec3Dot(&v4->v, dir);
+ return btMprIsZero(dot) || dot > 0.f;
+}
+
+inline void btExpandPortal(btMprSimplex_t *portal,
+ const btMprSupport_t *v4)
+{
+ float dot;
+ btVector3 v4v0;
+
+ btMprVec3Cross(&v4v0, &v4->v, &btMprSimplexPoint(portal, 0)->v);
+ dot = btMprVec3Dot(&btMprSimplexPoint(portal, 1)->v, &v4v0);
+ if (dot > 0.f){
+ dot = btMprVec3Dot(&btMprSimplexPoint(portal, 2)->v, &v4v0);
+ if (dot > 0.f){
+ btMprSimplexSet(portal, 1, v4);
+ }else{
+ btMprSimplexSet(portal, 3, v4);
+ }
+ }else{
+ dot = btMprVec3Dot(&btMprSimplexPoint(portal, 3)->v, &v4v0);
+ if (dot > 0.f){
+ btMprSimplexSet(portal, 2, v4);
+ }else{
+ btMprSimplexSet(portal, 1, v4);
+ }
+ }
+}
+template <typename btConvexTemplate>
+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 pInA = a.getLocalSupportWithMargin(seperatingAxisInA);
+ btVector3 qInB = b.getLocalSupportWithMargin(seperatingAxisInB);
+
+ supp->v1 = a.getWorldTransform()(pInA);
+ supp->v2 = b.getWorldTransform()(qInB);
+ supp->v = supp->v1 - supp->v2;
+}
+
+
+template <typename btConvexTemplate>
+static int btDiscoverPortal(const btConvexTemplate& a, const btConvexTemplate& b,
+ const btMprCollisionDescription& colDesc,
+ btMprSimplex_t *portal)
+{
+ btVector3 dir, va, vb;
+ float dot;
+ int cont;
+
+
+
+ // vertex 0 is center of portal
+ btFindOrigin(a,b,colDesc, btMprSimplexPointW(portal, 0));
+
+
+ // vertex 0 is center of portal
+ btMprSimplexSetSize(portal, 1);
+
+
+
+ btVector3 zero = btVector3(0,0,0);
+ btVector3* org = &zero;
+
+ if (btMprVec3Eq(&btMprSimplexPoint(portal, 0)->v, org)){
+ // Portal's center lies on origin (0,0,0) => we know that objects
+ // intersect but we would need to know penetration info.
+ // So move center little bit...
+ btMprVec3Set(&va, FLT_EPSILON * 10.f, 0.f, 0.f);
+ btMprVec3Add(&btMprSimplexPointW(portal, 0)->v, &va);
+ }
+
+
+ // vertex 1 = support in direction of origin
+ btMprVec3Copy(&dir, &btMprSimplexPoint(portal, 0)->v);
+ btMprVec3Scale(&dir, -1.f);
+ btMprVec3Normalize(&dir);
+
+
+ btMprSupport(a,b,colDesc, dir, btMprSimplexPointW(portal, 1));
+
+ btMprSimplexSetSize(portal, 2);
+
+ // test if origin isn't outside of v1
+ dot = btMprVec3Dot(&btMprSimplexPoint(portal, 1)->v, &dir);
+
+
+ if (btMprIsZero(dot) || dot < 0.f)
+ return -1;
+
+
+ // vertex 2
+ btMprVec3Cross(&dir, &btMprSimplexPoint(portal, 0)->v,
+ &btMprSimplexPoint(portal, 1)->v);
+ if (btMprIsZero(btMprVec3Len2(&dir))){
+ if (btMprVec3Eq(&btMprSimplexPoint(portal, 1)->v, org)){
+ // origin lies on v1
+ return 1;
+ }else{
+ // origin lies on v0-v1 segment
+ return 2;
+ }
+ }
+
+ btMprVec3Normalize(&dir);
+ btMprSupport(a,b,colDesc, dir, btMprSimplexPointW(portal, 2));
+
+
+
+ dot = btMprVec3Dot(&btMprSimplexPoint(portal, 2)->v, &dir);
+ if (btMprIsZero(dot) || dot < 0.f)
+ return -1;
+
+ btMprSimplexSetSize(portal, 3);
+
+ // vertex 3 direction
+ btMprVec3Sub2(&va, &btMprSimplexPoint(portal, 1)->v,
+ &btMprSimplexPoint(portal, 0)->v);
+ btMprVec3Sub2(&vb, &btMprSimplexPoint(portal, 2)->v,
+ &btMprSimplexPoint(portal, 0)->v);
+ btMprVec3Cross(&dir, &va, &vb);
+ btMprVec3Normalize(&dir);
+
+ // it is better to form portal faces to be oriented "outside" origin
+ dot = btMprVec3Dot(&dir, &btMprSimplexPoint(portal, 0)->v);
+ if (dot > 0.f){
+ btMprSimplexSwap(portal, 1, 2);
+ btMprVec3Scale(&dir, -1.f);
+ }
+
+ while (btMprSimplexSize(portal) < 4){
+ btMprSupport(a,b,colDesc, dir, btMprSimplexPointW(portal, 3));
+
+ dot = btMprVec3Dot(&btMprSimplexPoint(portal, 3)->v, &dir);
+ if (btMprIsZero(dot) || dot < 0.f)
+ return -1;
+
+ cont = 0;
+
+ // test if origin is outside (v1, v0, v3) - set v2 as v3 and
+ // continue
+ btMprVec3Cross(&va, &btMprSimplexPoint(portal, 1)->v,
+ &btMprSimplexPoint(portal, 3)->v);
+ dot = btMprVec3Dot(&va, &btMprSimplexPoint(portal, 0)->v);
+ if (dot < 0.f && !btMprIsZero(dot)){
+ btMprSimplexSet(portal, 2, btMprSimplexPoint(portal, 3));
+ cont = 1;
+ }
+
+ if (!cont){
+ // test if origin is outside (v3, v0, v2) - set v1 as v3 and
+ // continue
+ btMprVec3Cross(&va, &btMprSimplexPoint(portal, 3)->v,
+ &btMprSimplexPoint(portal, 2)->v);
+ dot = btMprVec3Dot(&va, &btMprSimplexPoint(portal, 0)->v);
+ if (dot < 0.f && !btMprIsZero(dot)){
+ btMprSimplexSet(portal, 1, btMprSimplexPoint(portal, 3));
+ cont = 1;
+ }
+ }
+
+ if (cont){
+ btMprVec3Sub2(&va, &btMprSimplexPoint(portal, 1)->v,
+ &btMprSimplexPoint(portal, 0)->v);
+ btMprVec3Sub2(&vb, &btMprSimplexPoint(portal, 2)->v,
+ &btMprSimplexPoint(portal, 0)->v);
+ btMprVec3Cross(&dir, &va, &vb);
+ btMprVec3Normalize(&dir);
+ }else{
+ btMprSimplexSetSize(portal, 4);
+ }
+ }
+
+ return 0;
+}
+
+template <typename btConvexTemplate>
+static int btRefinePortal(const btConvexTemplate& a, const btConvexTemplate& b,const btMprCollisionDescription& colDesc,
+ btMprSimplex_t *portal)
+{
+ btVector3 dir;
+ btMprSupport_t v4;
+
+ for (int i=0;i<BT_MPR_MAX_ITERATIONS;i++)
+ //while (1)
+ {
+ // compute direction outside the portal (from v0 throught v1,v2,v3
+ // face)
+ btPortalDir(portal, &dir);
+
+ // test if origin is inside the portal
+ if (portalEncapsulesOrigin(portal, &dir))
+ return 0;
+
+ // get next support point
+
+ btMprSupport(a,b,colDesc, dir, &v4);
+
+
+ // test if v4 can expand portal to contain origin and if portal
+ // expanding doesn't reach given tolerance
+ if (!portalCanEncapsuleOrigin(portal, &v4, &dir)
+ || portalReachTolerance(portal, &v4, &dir))
+ {
+ return -1;
+ }
+
+ // v1-v2-v3 triangle must be rearranged to face outside Minkowski
+ // difference (direction from v0).
+ btExpandPortal(portal, &v4);
+ }
+
+ return -1;
+}
+
+static void btFindPos(const btMprSimplex_t *portal, btVector3 *pos)
+{
+
+ btVector3 zero = btVector3(0,0,0);
+ btVector3* origin = &zero;
+
+ btVector3 dir;
+ size_t i;
+ float b[4], sum, inv;
+ btVector3 vec, p1, p2;
+
+ btPortalDir(portal, &dir);
+
+ // use barycentric coordinates of tetrahedron to find origin
+ btMprVec3Cross(&vec, &btMprSimplexPoint(portal, 1)->v,
+ &btMprSimplexPoint(portal, 2)->v);
+ b[0] = btMprVec3Dot(&vec, &btMprSimplexPoint(portal, 3)->v);
+
+ btMprVec3Cross(&vec, &btMprSimplexPoint(portal, 3)->v,
+ &btMprSimplexPoint(portal, 2)->v);
+ b[1] = btMprVec3Dot(&vec, &btMprSimplexPoint(portal, 0)->v);
+
+ btMprVec3Cross(&vec, &btMprSimplexPoint(portal, 0)->v,
+ &btMprSimplexPoint(portal, 1)->v);
+ b[2] = btMprVec3Dot(&vec, &btMprSimplexPoint(portal, 3)->v);
+
+ btMprVec3Cross(&vec, &btMprSimplexPoint(portal, 2)->v,
+ &btMprSimplexPoint(portal, 1)->v);
+ b[3] = btMprVec3Dot(&vec, &btMprSimplexPoint(portal, 0)->v);
+
+ sum = b[0] + b[1] + b[2] + b[3];
+
+ if (btMprIsZero(sum) || sum < 0.f){
+ b[0] = 0.f;
+
+ btMprVec3Cross(&vec, &btMprSimplexPoint(portal, 2)->v,
+ &btMprSimplexPoint(portal, 3)->v);
+ b[1] = btMprVec3Dot(&vec, &dir);
+ btMprVec3Cross(&vec, &btMprSimplexPoint(portal, 3)->v,
+ &btMprSimplexPoint(portal, 1)->v);
+ b[2] = btMprVec3Dot(&vec, &dir);
+ btMprVec3Cross(&vec, &btMprSimplexPoint(portal, 1)->v,
+ &btMprSimplexPoint(portal, 2)->v);
+ b[3] = btMprVec3Dot(&vec, &dir);
+
+ sum = b[1] + b[2] + b[3];
+ }
+
+ inv = 1.f / sum;
+
+ btMprVec3Copy(&p1, origin);
+ btMprVec3Copy(&p2, origin);
+ for (i = 0; i < 4; i++){
+ btMprVec3Copy(&vec, &btMprSimplexPoint(portal, i)->v1);
+ btMprVec3Scale(&vec, b[i]);
+ btMprVec3Add(&p1, &vec);
+
+ btMprVec3Copy(&vec, &btMprSimplexPoint(portal, i)->v2);
+ btMprVec3Scale(&vec, b[i]);
+ btMprVec3Add(&p2, &vec);
+ }
+ btMprVec3Scale(&p1, inv);
+ btMprVec3Scale(&p2, inv);
+#ifdef MPR_AVERAGE_CONTACT_POSITIONS
+ btMprVec3Copy(pos, &p1);
+ btMprVec3Add(pos, &p2);
+ btMprVec3Scale(pos, 0.5);
+#else
+ btMprVec3Copy(pos, &p2);
+#endif//MPR_AVERAGE_CONTACT_POSITIONS
+}
+
+inline float btMprVec3Dist2(const btVector3 *a, const btVector3 *b)
+{
+ btVector3 ab;
+ btMprVec3Sub2(&ab, a, b);
+ return btMprVec3Len2(&ab);
+}
+
+inline float _btMprVec3PointSegmentDist2(const btVector3 *P,
+ const btVector3 *x0,
+ const btVector3 *b,
+ btVector3 *witness)
+{
+ // The computation comes from solving equation of segment:
+ // S(t) = x0 + t.d
+ // where - x0 is initial point of segment
+ // - d is direction of segment from x0 (|d| > 0)
+ // - t belongs to <0, 1> interval
+ //
+ // Than, distance from a segment to some point P can be expressed:
+ // D(t) = |x0 + t.d - P|^2
+ // which is distance from any point on segment. Minimization
+ // of this function brings distance from P to segment.
+ // Minimization of D(t) leads to simple quadratic equation that's
+ // solving is straightforward.
+ //
+ // Bonus of this method is witness point for free.
+
+ float dist, t;
+ btVector3 d, a;
+
+ // direction of segment
+ btMprVec3Sub2(&d, b, x0);
+
+ // precompute vector from P to x0
+ btMprVec3Sub2(&a, x0, P);
+
+ t = -1.f * btMprVec3Dot(&a, &d);
+ t /= btMprVec3Len2(&d);
+
+ if (t < 0.f || btMprIsZero(t)){
+ dist = btMprVec3Dist2(x0, P);
+ if (witness)
+ btMprVec3Copy(witness, x0);
+ }else if (t > 1.f || btMprEq(t, 1.f)){
+ dist = btMprVec3Dist2(b, P);
+ if (witness)
+ btMprVec3Copy(witness, b);
+ }else{
+ if (witness){
+ btMprVec3Copy(witness, &d);
+ btMprVec3Scale(witness, t);
+ btMprVec3Add(witness, x0);
+ dist = btMprVec3Dist2(witness, P);
+ }else{
+ // recycling variables
+ btMprVec3Scale(&d, t);
+ btMprVec3Add(&d, &a);
+ dist = btMprVec3Len2(&d);
+ }
+ }
+
+ return dist;
+}
+
+
+
+inline float btMprVec3PointTriDist2(const btVector3 *P,
+ const btVector3 *x0, const btVector3 *B,
+ const btVector3 *C,
+ btVector3 *witness)
+{
+ // Computation comes from analytic expression for triangle (x0, B, C)
+ // T(s, t) = x0 + s.d1 + t.d2, where d1 = B - x0 and d2 = C - x0 and
+ // Then equation for distance is:
+ // D(s, t) = | T(s, t) - P |^2
+ // This leads to minimization of quadratic function of two variables.
+ // The solution from is taken only if s is between 0 and 1, t is
+ // between 0 and 1 and t + s < 1, otherwise distance from segment is
+ // computed.
+
+ btVector3 d1, d2, a;
+ float u, v, w, p, q, r;
+ float s, t, dist, dist2;
+ btVector3 witness2;
+
+ btMprVec3Sub2(&d1, B, x0);
+ btMprVec3Sub2(&d2, C, x0);
+ btMprVec3Sub2(&a, x0, P);
+
+ u = btMprVec3Dot(&a, &a);
+ v = btMprVec3Dot(&d1, &d1);
+ w = btMprVec3Dot(&d2, &d2);
+ p = btMprVec3Dot(&a, &d1);
+ q = btMprVec3Dot(&a, &d2);
+ r = btMprVec3Dot(&d1, &d2);
+
+ btScalar div = (w * v - r * r);
+ if (btMprIsZero(div))
+ {
+ s=-1;
+ } else
+ {
+ s = (q * r - w * p) / div;
+ t = (-s * r - q) / w;
+ }
+
+ if ((btMprIsZero(s) || s > 0.f)
+ && (btMprEq(s, 1.f) || s < 1.f)
+ && (btMprIsZero(t) || t > 0.f)
+ && (btMprEq(t, 1.f) || t < 1.f)
+ && (btMprEq(t + s, 1.f) || t + s < 1.f)){
+
+ if (witness){
+ btMprVec3Scale(&d1, s);
+ btMprVec3Scale(&d2, t);
+ btMprVec3Copy(witness, x0);
+ btMprVec3Add(witness, &d1);
+ btMprVec3Add(witness, &d2);
+
+ dist = btMprVec3Dist2(witness, P);
+ }else{
+ dist = s * s * v;
+ dist += t * t * w;
+ dist += 2.f * s * t * r;
+ dist += 2.f * s * p;
+ dist += 2.f * t * q;
+ dist += u;
+ }
+ }else{
+ dist = _btMprVec3PointSegmentDist2(P, x0, B, witness);
+
+ dist2 = _btMprVec3PointSegmentDist2(P, x0, C, &witness2);
+ if (dist2 < dist){
+ dist = dist2;
+ if (witness)
+ btMprVec3Copy(witness, &witness2);
+ }
+
+ dist2 = _btMprVec3PointSegmentDist2(P, B, C, &witness2);
+ if (dist2 < dist){
+ dist = dist2;
+ if (witness)
+ btMprVec3Copy(witness, &witness2);
+ }
+ }
+
+ return dist;
+}
+
+template <typename btConvexTemplate>
+static void btFindPenetr(const btConvexTemplate& a, const btConvexTemplate& b,
+ const btMprCollisionDescription& colDesc,
+ btMprSimplex_t *portal,
+ float *depth, btVector3 *pdir, btVector3 *pos)
+{
+ btVector3 dir;
+ btMprSupport_t v4;
+ unsigned long iterations;
+
+ btVector3 zero = btVector3(0,0,0);
+ btVector3* origin = &zero;
+
+
+ iterations = 1UL;
+ for (int i=0;i<BT_MPR_MAX_ITERATIONS;i++)
+ //while (1)
+ {
+ // compute portal direction and obtain next support point
+ btPortalDir(portal, &dir);
+
+ btMprSupport(a,b,colDesc, dir, &v4);
+
+
+ // reached tolerance -> find penetration info
+ if (portalReachTolerance(portal, &v4, &dir)
+ || iterations ==BT_MPR_MAX_ITERATIONS)
+ {
+ *depth = btMprVec3PointTriDist2(origin,&btMprSimplexPoint(portal, 1)->v,&btMprSimplexPoint(portal, 2)->v,&btMprSimplexPoint(portal, 3)->v,pdir);
+ *depth = BT_MPR_SQRT(*depth);
+
+ if (btMprIsZero((*pdir).x()) && btMprIsZero((*pdir).y()) && btMprIsZero((*pdir).z()))
+ {
+
+ *pdir = dir;
+ }
+ btMprVec3Normalize(pdir);
+
+ // barycentric coordinates:
+ btFindPos(portal, pos);
+
+
+ return;
+ }
+
+ btExpandPortal(portal, &v4);
+
+ iterations++;
+ }
+}
+
+static void btFindPenetrTouch(btMprSimplex_t *portal,float *depth, btVector3 *dir, btVector3 *pos)
+{
+ // Touching contact on portal's v1 - so depth is zero and direction
+ // is unimportant and pos can be guessed
+ *depth = 0.f;
+ btVector3 zero = btVector3(0,0,0);
+ btVector3* origin = &zero;
+
+
+ btMprVec3Copy(dir, origin);
+#ifdef MPR_AVERAGE_CONTACT_POSITIONS
+ btMprVec3Copy(pos, &btMprSimplexPoint(portal, 1)->v1);
+ btMprVec3Add(pos, &btMprSimplexPoint(portal, 1)->v2);
+ btMprVec3Scale(pos, 0.5);
+#else
+ btMprVec3Copy(pos, &btMprSimplexPoint(portal, 1)->v2);
+#endif
+}
+
+static void btFindPenetrSegment(btMprSimplex_t *portal,
+ float *depth, btVector3 *dir, btVector3 *pos)
+{
+
+ // Origin lies on v0-v1 segment.
+ // Depth is distance to v1, direction also and position must be
+ // computed
+#ifdef MPR_AVERAGE_CONTACT_POSITIONS
+ btMprVec3Copy(pos, &btMprSimplexPoint(portal, 1)->v1);
+ btMprVec3Add(pos, &btMprSimplexPoint(portal, 1)->v2);
+ btMprVec3Scale(pos, 0.5f);
+#else
+ btMprVec3Copy(pos, &btMprSimplexPoint(portal, 1)->v2);
+#endif//MPR_AVERAGE_CONTACT_POSITIONS
+
+ btMprVec3Copy(dir, &btMprSimplexPoint(portal, 1)->v);
+ *depth = BT_MPR_SQRT(btMprVec3Len2(dir));
+ btMprVec3Normalize(dir);
+
+
+}
+
+
+template <typename btConvexTemplate>
+inline int btMprPenetration( const btConvexTemplate& a, const btConvexTemplate& b,
+ const btMprCollisionDescription& colDesc,
+ float *depthOut, btVector3* dirOut, btVector3* posOut)
+{
+
+ btMprSimplex_t portal;
+
+
+ // Phase 1: Portal discovery
+ int result = btDiscoverPortal(a,b,colDesc, &portal);
+
+
+ //sepAxis[pairIndex] = *pdir;//or -dir?
+
+ switch (result)
+ {
+ case 0:
+ {
+ // Phase 2: Portal refinement
+
+ result = btRefinePortal(a,b,colDesc, &portal);
+ if (result < 0)
+ return -1;
+
+ // Phase 3. Penetration info
+ btFindPenetr(a,b,colDesc, &portal, depthOut, dirOut, posOut);
+
+
+ break;
+ }
+ case 1:
+ {
+ // Touching contact on portal's v1.
+ btFindPenetrTouch(&portal, depthOut, dirOut, posOut);
+ result=0;
+ break;
+ }
+ case 2:
+ {
+
+ btFindPenetrSegment( &portal, depthOut, dirOut, posOut);
+ result=0;
+ break;
+ }
+ default:
+ {
+ //if (res < 0)
+ //{
+ // Origin isn't inside portal - no collision.
+ result = -1;
+ //}
+ }
+ };
+
+ return result;
+};
+
+
+template<typename btConvexTemplate, typename btMprDistanceTemplate>
+inline int btComputeMprPenetration( const btConvexTemplate& a, const btConvexTemplate& b, const
+ btMprCollisionDescription& colDesc, btMprDistanceTemplate* distInfo)
+{
+ btVector3 dir,pos;
+ float depth;
+
+ int res = btMprPenetration(a,b,colDesc,&depth, &dir, &pos);
+ if (res==0)
+ {
+ distInfo->m_distance = -depth;
+ distInfo->m_pointOnB = pos;
+ distInfo->m_normalBtoA = -dir;
+ distInfo->m_pointOnA = pos-distInfo->m_distance*dir;
+ return 0;
+ }
+
+ return -1;
+}
+
+
+
+#endif //BT_MPR_PENETRATION_H
diff --git a/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp
new file mode 100644
index 0000000000..23aaece22b
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp
@@ -0,0 +1,308 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "btPersistentManifold.h"
+#include "LinearMath/btTransform.h"
+
+
+btScalar gContactBreakingThreshold = btScalar(0.02);
+ContactDestroyedCallback gContactDestroyedCallback = 0;
+ContactProcessedCallback gContactProcessedCallback = 0;
+ContactStartedCallback gContactStartedCallback = 0;
+ContactEndedCallback gContactEndedCallback = 0;
+///gContactCalcArea3Points will approximate the convex hull area using 3 points
+///when setting it to false, it will use 4 points to compute the area: it is more accurate but slower
+bool gContactCalcArea3Points = true;
+
+
+btPersistentManifold::btPersistentManifold()
+:btTypedObject(BT_PERSISTENT_MANIFOLD_TYPE),
+m_body0(0),
+m_body1(0),
+m_cachedPoints (0),
+m_index1a(0)
+{
+}
+
+
+
+
+#ifdef DEBUG_PERSISTENCY
+#include <stdio.h>
+void btPersistentManifold::DebugPersistency()
+{
+ int i;
+ printf("DebugPersistency : numPoints %d\n",m_cachedPoints);
+ for (i=0;i<m_cachedPoints;i++)
+ {
+ printf("m_pointCache[%d].m_userPersistentData = %x\n",i,m_pointCache[i].m_userPersistentData);
+ }
+}
+#endif //DEBUG_PERSISTENCY
+
+void btPersistentManifold::clearUserCache(btManifoldPoint& pt)
+{
+
+ void* oldPtr = pt.m_userPersistentData;
+ if (oldPtr)
+ {
+#ifdef DEBUG_PERSISTENCY
+ int i;
+ int occurance = 0;
+ for (i=0;i<m_cachedPoints;i++)
+ {
+ if (m_pointCache[i].m_userPersistentData == oldPtr)
+ {
+ occurance++;
+ if (occurance>1)
+ printf("error in clearUserCache\n");
+ }
+ }
+ btAssert(occurance<=0);
+#endif //DEBUG_PERSISTENCY
+
+ if (pt.m_userPersistentData && gContactDestroyedCallback)
+ {
+ (*gContactDestroyedCallback)(pt.m_userPersistentData);
+ pt.m_userPersistentData = 0;
+ }
+
+#ifdef DEBUG_PERSISTENCY
+ DebugPersistency();
+#endif
+ }
+
+
+}
+
+static inline btScalar calcArea4Points(const btVector3 &p0,const btVector3 &p1,const btVector3 &p2,const btVector3 &p3)
+{
+ // It calculates possible 3 area constructed from random 4 points and returns the biggest one.
+
+ btVector3 a[3],b[3];
+ a[0] = p0 - p1;
+ a[1] = p0 - p2;
+ a[2] = p0 - p3;
+ b[0] = p2 - p3;
+ b[1] = p1 - p3;
+ b[2] = p1 - p2;
+
+ //todo: Following 3 cross production can be easily optimized by SIMD.
+ btVector3 tmp0 = a[0].cross(b[0]);
+ btVector3 tmp1 = a[1].cross(b[1]);
+ btVector3 tmp2 = a[2].cross(b[2]);
+
+ return btMax(btMax(tmp0.length2(),tmp1.length2()),tmp2.length2());
+}
+
+int btPersistentManifold::sortCachedPoints(const btManifoldPoint& pt)
+{
+ //calculate 4 possible cases areas, and take biggest area
+ //also need to keep 'deepest'
+
+ int maxPenetrationIndex = -1;
+#define KEEP_DEEPEST_POINT 1
+#ifdef KEEP_DEEPEST_POINT
+ btScalar maxPenetration = pt.getDistance();
+ for (int i=0;i<4;i++)
+ {
+ if (m_pointCache[i].getDistance() < maxPenetration)
+ {
+ maxPenetrationIndex = i;
+ maxPenetration = m_pointCache[i].getDistance();
+ }
+ }
+#endif //KEEP_DEEPEST_POINT
+
+ btScalar res0(btScalar(0.)),res1(btScalar(0.)),res2(btScalar(0.)),res3(btScalar(0.));
+
+ if (gContactCalcArea3Points)
+ {
+ if (maxPenetrationIndex != 0)
+ {
+ btVector3 a0 = pt.m_localPointA-m_pointCache[1].m_localPointA;
+ btVector3 b0 = m_pointCache[3].m_localPointA-m_pointCache[2].m_localPointA;
+ btVector3 cross = a0.cross(b0);
+ res0 = cross.length2();
+ }
+ if (maxPenetrationIndex != 1)
+ {
+ btVector3 a1 = pt.m_localPointA-m_pointCache[0].m_localPointA;
+ btVector3 b1 = m_pointCache[3].m_localPointA-m_pointCache[2].m_localPointA;
+ btVector3 cross = a1.cross(b1);
+ res1 = cross.length2();
+ }
+
+ if (maxPenetrationIndex != 2)
+ {
+ btVector3 a2 = pt.m_localPointA-m_pointCache[0].m_localPointA;
+ btVector3 b2 = m_pointCache[3].m_localPointA-m_pointCache[1].m_localPointA;
+ btVector3 cross = a2.cross(b2);
+ res2 = cross.length2();
+ }
+
+ if (maxPenetrationIndex != 3)
+ {
+ btVector3 a3 = pt.m_localPointA-m_pointCache[0].m_localPointA;
+ btVector3 b3 = m_pointCache[2].m_localPointA-m_pointCache[1].m_localPointA;
+ btVector3 cross = a3.cross(b3);
+ res3 = cross.length2();
+ }
+ }
+ else
+ {
+ if(maxPenetrationIndex != 0) {
+ res0 = calcArea4Points(pt.m_localPointA,m_pointCache[1].m_localPointA,m_pointCache[2].m_localPointA,m_pointCache[3].m_localPointA);
+ }
+
+ if(maxPenetrationIndex != 1) {
+ res1 = calcArea4Points(pt.m_localPointA,m_pointCache[0].m_localPointA,m_pointCache[2].m_localPointA,m_pointCache[3].m_localPointA);
+ }
+
+ if(maxPenetrationIndex != 2) {
+ res2 = calcArea4Points(pt.m_localPointA,m_pointCache[0].m_localPointA,m_pointCache[1].m_localPointA,m_pointCache[3].m_localPointA);
+ }
+
+ if(maxPenetrationIndex != 3) {
+ res3 = calcArea4Points(pt.m_localPointA,m_pointCache[0].m_localPointA,m_pointCache[1].m_localPointA,m_pointCache[2].m_localPointA);
+ }
+ }
+ btVector4 maxvec(res0,res1,res2,res3);
+ int biggestarea = maxvec.closestAxis4();
+ return biggestarea;
+
+}
+
+
+int btPersistentManifold::getCacheEntry(const btManifoldPoint& newPoint) const
+{
+ btScalar shortestDist = getContactBreakingThreshold() * getContactBreakingThreshold();
+ int size = getNumContacts();
+ int nearestPoint = -1;
+ for( int i = 0; i < size; i++ )
+ {
+ const btManifoldPoint &mp = m_pointCache[i];
+
+ btVector3 diffA = mp.m_localPointA- newPoint.m_localPointA;
+ const btScalar distToManiPoint = diffA.dot(diffA);
+ if( distToManiPoint < shortestDist )
+ {
+ shortestDist = distToManiPoint;
+ nearestPoint = i;
+ }
+ }
+ return nearestPoint;
+}
+
+int btPersistentManifold::addManifoldPoint(const btManifoldPoint& newPoint, bool isPredictive)
+{
+ if (!isPredictive)
+ {
+ btAssert(validContactDistance(newPoint));
+ }
+
+ int insertIndex = getNumContacts();
+ if (insertIndex == MANIFOLD_CACHE_SIZE)
+ {
+#if MANIFOLD_CACHE_SIZE >= 4
+ //sort cache so best points come first, based on area
+ insertIndex = sortCachedPoints(newPoint);
+#else
+ insertIndex = 0;
+#endif
+ clearUserCache(m_pointCache[insertIndex]);
+
+ } else
+ {
+ m_cachedPoints++;
+
+
+ }
+ if (insertIndex<0)
+ insertIndex=0;
+
+ btAssert(m_pointCache[insertIndex].m_userPersistentData==0);
+ m_pointCache[insertIndex] = newPoint;
+ return insertIndex;
+}
+
+btScalar btPersistentManifold::getContactBreakingThreshold() const
+{
+ return m_contactBreakingThreshold;
+}
+
+
+
+void btPersistentManifold::refreshContactPoints(const btTransform& trA,const btTransform& trB)
+{
+ int i;
+#ifdef DEBUG_PERSISTENCY
+ printf("refreshContactPoints posA = (%f,%f,%f) posB = (%f,%f,%f)\n",
+ trA.getOrigin().getX(),
+ trA.getOrigin().getY(),
+ trA.getOrigin().getZ(),
+ trB.getOrigin().getX(),
+ trB.getOrigin().getY(),
+ trB.getOrigin().getZ());
+#endif //DEBUG_PERSISTENCY
+ /// first refresh worldspace positions and distance
+ for (i=getNumContacts()-1;i>=0;i--)
+ {
+ btManifoldPoint &manifoldPoint = m_pointCache[i];
+ manifoldPoint.m_positionWorldOnA = trA( manifoldPoint.m_localPointA );
+ manifoldPoint.m_positionWorldOnB = trB( manifoldPoint.m_localPointB );
+ manifoldPoint.m_distance1 = (manifoldPoint.m_positionWorldOnA - manifoldPoint.m_positionWorldOnB).dot(manifoldPoint.m_normalWorldOnB);
+ manifoldPoint.m_lifeTime++;
+ }
+
+ /// then
+ btScalar distance2d;
+ btVector3 projectedDifference,projectedPoint;
+ for (i=getNumContacts()-1;i>=0;i--)
+ {
+
+ btManifoldPoint &manifoldPoint = m_pointCache[i];
+ //contact becomes invalid when signed distance exceeds margin (projected on contactnormal direction)
+ if (!validContactDistance(manifoldPoint))
+ {
+ removeContactPoint(i);
+ } else
+ {
+ //todo: friction anchor may require the contact to be around a bit longer
+ //contact also becomes invalid when relative movement orthogonal to normal exceeds margin
+ projectedPoint = manifoldPoint.m_positionWorldOnA - manifoldPoint.m_normalWorldOnB * manifoldPoint.m_distance1;
+ projectedDifference = manifoldPoint.m_positionWorldOnB - projectedPoint;
+ distance2d = projectedDifference.dot(projectedDifference);
+ if (distance2d > getContactBreakingThreshold()*getContactBreakingThreshold() )
+ {
+ removeContactPoint(i);
+ } else
+ {
+ //contact point processed callback
+ if (gContactProcessedCallback)
+ (*gContactProcessedCallback)(manifoldPoint,(void*)m_body0,(void*)m_body1);
+ }
+ }
+ }
+#ifdef DEBUG_PERSISTENCY
+ DebugPersistency();
+#endif //
+}
+
+
+
+
+
diff --git a/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h
new file mode 100644
index 0000000000..f872c8e1c9
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h
@@ -0,0 +1,268 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_PERSISTENT_MANIFOLD_H
+#define BT_PERSISTENT_MANIFOLD_H
+
+
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btTransform.h"
+#include "btManifoldPoint.h"
+class btCollisionObject;
+#include "LinearMath/btAlignedAllocator.h"
+
+struct btCollisionResult;
+
+///maximum contact breaking and merging threshold
+extern btScalar gContactBreakingThreshold;
+
+#ifndef SWIG
+class btPersistentManifold;
+
+typedef bool (*ContactDestroyedCallback)(void* userPersistentData);
+typedef bool (*ContactProcessedCallback)(btManifoldPoint& cp,void* body0,void* body1);
+typedef void (*ContactStartedCallback)(btPersistentManifold* const &manifold);
+typedef void (*ContactEndedCallback)(btPersistentManifold* const &manifold);
+extern ContactDestroyedCallback gContactDestroyedCallback;
+extern ContactProcessedCallback gContactProcessedCallback;
+extern ContactStartedCallback gContactStartedCallback;
+extern ContactEndedCallback gContactEndedCallback;
+#endif //SWIG
+
+//the enum starts at 1024 to avoid type conflicts with btTypedConstraint
+enum btContactManifoldTypes
+{
+ MIN_CONTACT_MANIFOLD_TYPE = 1024,
+ BT_PERSISTENT_MANIFOLD_TYPE
+};
+
+#define MANIFOLD_CACHE_SIZE 4
+
+///btPersistentManifold is a contact point cache, it stays persistent as long as objects are overlapping in the broadphase.
+///Those contact points are created by the collision narrow phase.
+///The cache can be empty, or hold 1,2,3 or 4 points. Some collision algorithms (GJK) might only add one point at a time.
+///updates/refreshes old contact points, and throw them away if necessary (distance becomes too large)
+///reduces the cache to 4 points, when more then 4 points are added, using following rules:
+///the contact point with deepest penetration is always kept, and it tries to maximuze the area covered by the points
+///note that some pairs of objects might have more then one contact manifold.
+
+
+//ATTRIBUTE_ALIGNED128( class) btPersistentManifold : public btTypedObject
+ATTRIBUTE_ALIGNED16( class) btPersistentManifold : public btTypedObject
+{
+
+ btManifoldPoint m_pointCache[MANIFOLD_CACHE_SIZE];
+
+ /// this two body pointers can point to the physics rigidbody class.
+ const btCollisionObject* m_body0;
+ const btCollisionObject* m_body1;
+
+ int m_cachedPoints;
+
+ btScalar m_contactBreakingThreshold;
+ btScalar m_contactProcessingThreshold;
+
+
+ /// sort cached points so most isolated points come first
+ int sortCachedPoints(const btManifoldPoint& pt);
+
+ int findContactPoint(const btManifoldPoint* unUsed, int numUnused,const btManifoldPoint& pt);
+
+public:
+
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ int m_companionIdA;
+ int m_companionIdB;
+
+ int m_index1a;
+
+ btPersistentManifold();
+
+ btPersistentManifold(const btCollisionObject* body0,const btCollisionObject* body1,int , btScalar contactBreakingThreshold,btScalar contactProcessingThreshold)
+ : btTypedObject(BT_PERSISTENT_MANIFOLD_TYPE),
+ m_body0(body0),m_body1(body1),m_cachedPoints(0),
+ m_contactBreakingThreshold(contactBreakingThreshold),
+ m_contactProcessingThreshold(contactProcessingThreshold)
+ {
+ }
+
+ SIMD_FORCE_INLINE const btCollisionObject* getBody0() const { return m_body0;}
+ SIMD_FORCE_INLINE const btCollisionObject* getBody1() const { return m_body1;}
+
+ void setBodies(const btCollisionObject* body0,const btCollisionObject* body1)
+ {
+ m_body0 = body0;
+ m_body1 = body1;
+ }
+
+ void clearUserCache(btManifoldPoint& pt);
+
+#ifdef DEBUG_PERSISTENCY
+ void DebugPersistency();
+#endif //
+
+ SIMD_FORCE_INLINE int getNumContacts() const { return m_cachedPoints;}
+ /// the setNumContacts API is usually not used, except when you gather/fill all contacts manually
+ void setNumContacts(int cachedPoints)
+ {
+ m_cachedPoints = cachedPoints;
+ }
+
+
+ SIMD_FORCE_INLINE const btManifoldPoint& getContactPoint(int index) const
+ {
+ btAssert(index < m_cachedPoints);
+ return m_pointCache[index];
+ }
+
+ SIMD_FORCE_INLINE btManifoldPoint& getContactPoint(int index)
+ {
+ btAssert(index < m_cachedPoints);
+ return m_pointCache[index];
+ }
+
+ ///@todo: get this margin from the current physics / collision environment
+ btScalar getContactBreakingThreshold() const;
+
+ btScalar getContactProcessingThreshold() const
+ {
+ return m_contactProcessingThreshold;
+ }
+
+ void setContactBreakingThreshold(btScalar contactBreakingThreshold)
+ {
+ m_contactBreakingThreshold = contactBreakingThreshold;
+ }
+
+ void setContactProcessingThreshold(btScalar contactProcessingThreshold)
+ {
+ m_contactProcessingThreshold = contactProcessingThreshold;
+ }
+
+
+
+
+ int getCacheEntry(const btManifoldPoint& newPoint) const;
+
+ int addManifoldPoint( const btManifoldPoint& newPoint, bool isPredictive=false);
+
+ void removeContactPoint (int index)
+ {
+ clearUserCache(m_pointCache[index]);
+
+ int lastUsedIndex = getNumContacts() - 1;
+// m_pointCache[index] = m_pointCache[lastUsedIndex];
+ if(index != lastUsedIndex)
+ {
+ m_pointCache[index] = m_pointCache[lastUsedIndex];
+ //get rid of duplicated userPersistentData pointer
+ m_pointCache[lastUsedIndex].m_userPersistentData = 0;
+ m_pointCache[lastUsedIndex].m_appliedImpulse = 0.f;
+ m_pointCache[lastUsedIndex].m_contactPointFlags = 0;
+ m_pointCache[lastUsedIndex].m_appliedImpulseLateral1 = 0.f;
+ m_pointCache[lastUsedIndex].m_appliedImpulseLateral2 = 0.f;
+ m_pointCache[lastUsedIndex].m_lifeTime = 0;
+ }
+
+ btAssert(m_pointCache[lastUsedIndex].m_userPersistentData==0);
+ m_cachedPoints--;
+
+ if (gContactEndedCallback && m_cachedPoints == 0)
+ {
+ gContactEndedCallback(this);
+ }
+ }
+ void replaceContactPoint(const btManifoldPoint& newPoint, int insertIndex)
+ {
+ btAssert(validContactDistance(newPoint));
+
+#define MAINTAIN_PERSISTENCY 1
+#ifdef MAINTAIN_PERSISTENCY
+ int lifeTime = m_pointCache[insertIndex].getLifeTime();
+ btScalar appliedImpulse = m_pointCache[insertIndex].m_appliedImpulse;
+ btScalar appliedLateralImpulse1 = m_pointCache[insertIndex].m_appliedImpulseLateral1;
+ btScalar appliedLateralImpulse2 = m_pointCache[insertIndex].m_appliedImpulseLateral2;
+
+ bool replacePoint = true;
+ ///we keep existing contact points for friction anchors
+ ///if the friction force is within the Coulomb friction cone
+ if (newPoint.m_contactPointFlags & BT_CONTACT_FLAG_FRICTION_ANCHOR)
+ {
+ // printf("appliedImpulse=%f\n", appliedImpulse);
+ // printf("appliedLateralImpulse1=%f\n", appliedLateralImpulse1);
+ // printf("appliedLateralImpulse2=%f\n", appliedLateralImpulse2);
+ // printf("mu = %f\n", m_pointCache[insertIndex].m_combinedFriction);
+ btScalar mu = m_pointCache[insertIndex].m_combinedFriction;
+ btScalar eps = 0; //we could allow to enlarge or shrink the tolerance to check against the friction cone a bit, say 1e-7
+ btScalar a = appliedLateralImpulse1 * appliedLateralImpulse1 + appliedLateralImpulse2 * appliedLateralImpulse2;
+ btScalar b = eps + mu * appliedImpulse;
+ b = b * b;
+ replacePoint = (a) > (b);
+ }
+
+ if (replacePoint)
+ {
+ btAssert(lifeTime >= 0);
+ void* cache = m_pointCache[insertIndex].m_userPersistentData;
+
+ m_pointCache[insertIndex] = newPoint;
+ m_pointCache[insertIndex].m_userPersistentData = cache;
+ m_pointCache[insertIndex].m_appliedImpulse = appliedImpulse;
+ m_pointCache[insertIndex].m_appliedImpulseLateral1 = appliedLateralImpulse1;
+ m_pointCache[insertIndex].m_appliedImpulseLateral2 = appliedLateralImpulse2;
+ }
+
+ m_pointCache[insertIndex].m_lifeTime = lifeTime;
+#else
+ clearUserCache(m_pointCache[insertIndex]);
+ m_pointCache[insertIndex] = newPoint;
+
+#endif
+ }
+
+ bool validContactDistance(const btManifoldPoint& pt) const
+ {
+ return pt.m_distance1 <= getContactBreakingThreshold();
+ }
+ /// calculated new worldspace coordinates and depth, and reject points that exceed the collision margin
+ void refreshContactPoints( const btTransform& trA,const btTransform& trB);
+
+
+ SIMD_FORCE_INLINE void clearManifold()
+ {
+ int i;
+ for (i=0;i<m_cachedPoints;i++)
+ {
+ clearUserCache(m_pointCache[i]);
+ }
+
+ if (gContactEndedCallback && m_cachedPoints)
+ {
+ gContactEndedCallback(this);
+ }
+ m_cachedPoints = 0;
+ }
+
+
+
+}
+;
+
+
+
+
+
+#endif //BT_PERSISTENT_MANIFOLD_H
diff --git a/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btPointCollector.h b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btPointCollector.h
new file mode 100644
index 0000000000..18da171011
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btPointCollector.h
@@ -0,0 +1,64 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_POINT_COLLECTOR_H
+#define BT_POINT_COLLECTOR_H
+
+#include "btDiscreteCollisionDetectorInterface.h"
+
+
+
+struct btPointCollector : public btDiscreteCollisionDetectorInterface::Result
+{
+
+
+ btVector3 m_normalOnBInWorld;
+ btVector3 m_pointInWorld;
+ btScalar m_distance;//negative means penetration
+
+ bool m_hasResult;
+
+ btPointCollector ()
+ : m_distance(btScalar(BT_LARGE_FLOAT)),m_hasResult(false)
+ {
+ }
+
+ virtual void setShapeIdentifiersA(int partId0,int index0)
+ {
+ (void)partId0;
+ (void)index0;
+
+ }
+ virtual void setShapeIdentifiersB(int partId1,int index1)
+ {
+ (void)partId1;
+ (void)index1;
+ }
+
+ virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth)
+ {
+ if (depth< m_distance)
+ {
+ m_hasResult = true;
+ m_normalOnBInWorld = normalOnBInWorld;
+ m_pointInWorld = pointInWorld;
+ //negative means penetration
+ m_distance = depth;
+ }
+ }
+};
+
+#endif //BT_POINT_COLLECTOR_H
+
diff --git a/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp
new file mode 100644
index 0000000000..ea380bc5f1
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp
@@ -0,0 +1,570 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2011 Advanced Micro Devices, 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.
+*/
+
+
+///This file was written by Erwin Coumans
+///Separating axis rest based on work from Pierre Terdiman, see
+///And contact clipping based on work from Simon Hobbs
+
+
+#include "btPolyhedralContactClipping.h"
+#include "BulletCollision/CollisionShapes/btConvexPolyhedron.h"
+
+#include <float.h> //for FLT_MAX
+
+int gExpectedNbTests=0;
+int gActualNbTests = 0;
+bool gUseInternalObject = true;
+
+// Clips a face to the back of a plane
+void btPolyhedralContactClipping::clipFace(const btVertexArray& pVtxIn, btVertexArray& ppVtxOut, const btVector3& planeNormalWS,btScalar planeEqWS)
+{
+
+ int ve;
+ btScalar ds, de;
+ int numVerts = pVtxIn.size();
+ if (numVerts < 2)
+ return;
+
+ btVector3 firstVertex=pVtxIn[pVtxIn.size()-1];
+ btVector3 endVertex = pVtxIn[0];
+
+ ds = planeNormalWS.dot(firstVertex)+planeEqWS;
+
+ for (ve = 0; ve < numVerts; ve++)
+ {
+ endVertex=pVtxIn[ve];
+
+ de = planeNormalWS.dot(endVertex)+planeEqWS;
+
+ if (ds<0)
+ {
+ if (de<0)
+ {
+ // Start < 0, end < 0, so output endVertex
+ ppVtxOut.push_back(endVertex);
+ }
+ else
+ {
+ // Start < 0, end >= 0, so output intersection
+ ppVtxOut.push_back( firstVertex.lerp(endVertex,btScalar(ds * 1.f/(ds - de))));
+ }
+ }
+ else
+ {
+ if (de<0)
+ {
+ // Start >= 0, end < 0 so output intersection and end
+ ppVtxOut.push_back(firstVertex.lerp(endVertex,btScalar(ds * 1.f/(ds - de))));
+ ppVtxOut.push_back(endVertex);
+ }
+ }
+ firstVertex = endVertex;
+ ds = de;
+ }
+}
+
+
+static bool TestSepAxis(const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA,const btTransform& transB, const btVector3& sep_axis, btScalar& depth, btVector3& witnessPointA, btVector3& witnessPointB)
+{
+ btScalar Min0,Max0;
+ btScalar Min1,Max1;
+ btVector3 witnesPtMinA,witnesPtMaxA;
+ btVector3 witnesPtMinB,witnesPtMaxB;
+
+ hullA.project(transA,sep_axis, Min0, Max0,witnesPtMinA,witnesPtMaxA);
+ hullB.project(transB, sep_axis, Min1, Max1,witnesPtMinB,witnesPtMaxB);
+
+ if(Max0<Min1 || Max1<Min0)
+ return false;
+
+ btScalar d0 = Max0 - Min1;
+ btAssert(d0>=0.0f);
+ btScalar d1 = Max1 - Min0;
+ btAssert(d1>=0.0f);
+ if (d0<d1)
+ {
+ depth = d0;
+ witnessPointA = witnesPtMaxA;
+ witnessPointB = witnesPtMinB;
+
+ } else
+ {
+ depth = d1;
+ witnessPointA = witnesPtMinA;
+ witnessPointB = witnesPtMaxB;
+ }
+
+ return true;
+}
+
+
+
+static int gActualSATPairTests=0;
+
+inline bool IsAlmostZero(const btVector3& v)
+{
+ if(btFabs(v.x())>1e-6 || btFabs(v.y())>1e-6 || btFabs(v.z())>1e-6) return false;
+ return true;
+}
+
+#ifdef TEST_INTERNAL_OBJECTS
+
+inline void BoxSupport(const btScalar extents[3], const btScalar sv[3], btScalar p[3])
+{
+ // This version is ~11.000 cycles (4%) faster overall in one of the tests.
+// IR(p[0]) = IR(extents[0])|(IR(sv[0])&SIGN_BITMASK);
+// IR(p[1]) = IR(extents[1])|(IR(sv[1])&SIGN_BITMASK);
+// IR(p[2]) = IR(extents[2])|(IR(sv[2])&SIGN_BITMASK);
+ p[0] = sv[0] < 0.0f ? -extents[0] : extents[0];
+ p[1] = sv[1] < 0.0f ? -extents[1] : extents[1];
+ p[2] = sv[2] < 0.0f ? -extents[2] : extents[2];
+}
+
+void InverseTransformPoint3x3(btVector3& out, const btVector3& in, const btTransform& tr)
+{
+ const btMatrix3x3& rot = tr.getBasis();
+ const btVector3& r0 = rot[0];
+ const btVector3& r1 = rot[1];
+ const btVector3& r2 = rot[2];
+
+ const btScalar x = r0.x()*in.x() + r1.x()*in.y() + r2.x()*in.z();
+ const btScalar y = r0.y()*in.x() + r1.y()*in.y() + r2.y()*in.z();
+ const btScalar z = r0.z()*in.x() + r1.z()*in.y() + r2.z()*in.z();
+
+ out.setValue(x, y, z);
+}
+
+ bool TestInternalObjects( const btTransform& trans0, const btTransform& trans1, const btVector3& delta_c, const btVector3& axis, const btConvexPolyhedron& convex0, const btConvexPolyhedron& convex1, btScalar dmin)
+{
+ const btScalar dp = delta_c.dot(axis);
+
+ btVector3 localAxis0;
+ InverseTransformPoint3x3(localAxis0, axis,trans0);
+ btVector3 localAxis1;
+ InverseTransformPoint3x3(localAxis1, axis,trans1);
+
+ btScalar p0[3];
+ BoxSupport(convex0.m_extents, localAxis0, p0);
+ btScalar p1[3];
+ BoxSupport(convex1.m_extents, localAxis1, p1);
+
+ const btScalar Radius0 = p0[0]*localAxis0.x() + p0[1]*localAxis0.y() + p0[2]*localAxis0.z();
+ const btScalar Radius1 = p1[0]*localAxis1.x() + p1[1]*localAxis1.y() + p1[2]*localAxis1.z();
+
+ const btScalar MinRadius = Radius0>convex0.m_radius ? Radius0 : convex0.m_radius;
+ const btScalar MaxRadius = Radius1>convex1.m_radius ? Radius1 : convex1.m_radius;
+
+ const btScalar MinMaxRadius = MaxRadius + MinRadius;
+ const btScalar d0 = MinMaxRadius + dp;
+ const btScalar d1 = MinMaxRadius - dp;
+
+ const btScalar depth = d0<d1 ? d0:d1;
+ if(depth>dmin)
+ return false;
+ return true;
+}
+#endif //TEST_INTERNAL_OBJECTS
+
+
+
+ SIMD_FORCE_INLINE void btSegmentsClosestPoints(
+ btVector3& ptsVector,
+ btVector3& offsetA,
+ btVector3& offsetB,
+ btScalar& tA, btScalar& tB,
+ const btVector3& translation,
+ const btVector3& dirA, btScalar hlenA,
+ const btVector3& dirB, btScalar hlenB )
+{
+ // compute the parameters of the closest points on each line segment
+
+ btScalar dirA_dot_dirB = btDot(dirA,dirB);
+ btScalar dirA_dot_trans = btDot(dirA,translation);
+ btScalar dirB_dot_trans = btDot(dirB,translation);
+
+ btScalar denom = 1.0f - dirA_dot_dirB * dirA_dot_dirB;
+
+ if ( denom == 0.0f ) {
+ tA = 0.0f;
+ } else {
+ tA = ( dirA_dot_trans - dirB_dot_trans * dirA_dot_dirB ) / denom;
+ if ( tA < -hlenA )
+ tA = -hlenA;
+ else if ( tA > hlenA )
+ tA = hlenA;
+ }
+
+ tB = tA * dirA_dot_dirB - dirB_dot_trans;
+
+ if ( tB < -hlenB ) {
+ tB = -hlenB;
+ tA = tB * dirA_dot_dirB + dirA_dot_trans;
+
+ if ( tA < -hlenA )
+ tA = -hlenA;
+ else if ( tA > hlenA )
+ tA = hlenA;
+ } else if ( tB > hlenB ) {
+ tB = hlenB;
+ tA = tB * dirA_dot_dirB + dirA_dot_trans;
+
+ if ( tA < -hlenA )
+ tA = -hlenA;
+ else if ( tA > hlenA )
+ tA = hlenA;
+ }
+
+ // compute the closest points relative to segment centers.
+
+ offsetA = dirA * tA;
+ offsetB = dirB * tB;
+
+ ptsVector = translation - offsetA + offsetB;
+}
+
+
+
+bool btPolyhedralContactClipping::findSeparatingAxis( const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA,const btTransform& transB, btVector3& sep, btDiscreteCollisionDetectorInterface::Result& resultOut)
+{
+ gActualSATPairTests++;
+
+//#ifdef TEST_INTERNAL_OBJECTS
+ const btVector3 c0 = transA * hullA.m_localCenter;
+ const btVector3 c1 = transB * hullB.m_localCenter;
+ const btVector3 DeltaC2 = c0 - c1;
+//#endif
+
+ btScalar dmin = FLT_MAX;
+ int curPlaneTests=0;
+
+ int numFacesA = hullA.m_faces.size();
+ // Test normals from hullA
+ for(int i=0;i<numFacesA;i++)
+ {
+ const btVector3 Normal(hullA.m_faces[i].m_plane[0], hullA.m_faces[i].m_plane[1], hullA.m_faces[i].m_plane[2]);
+ btVector3 faceANormalWS = transA.getBasis() * Normal;
+ if (DeltaC2.dot(faceANormalWS)<0)
+ faceANormalWS*=-1.f;
+
+ curPlaneTests++;
+#ifdef TEST_INTERNAL_OBJECTS
+ gExpectedNbTests++;
+ if(gUseInternalObject && !TestInternalObjects(transA,transB, DeltaC2, faceANormalWS, hullA, hullB, dmin))
+ continue;
+ gActualNbTests++;
+#endif
+
+ btScalar d;
+ btVector3 wA,wB;
+ if(!TestSepAxis( hullA, hullB, transA,transB, faceANormalWS, d,wA,wB))
+ return false;
+
+ if(d<dmin)
+ {
+ dmin = d;
+ sep = faceANormalWS;
+ }
+ }
+
+ int numFacesB = hullB.m_faces.size();
+ // Test normals from hullB
+ for(int i=0;i<numFacesB;i++)
+ {
+ const btVector3 Normal(hullB.m_faces[i].m_plane[0], hullB.m_faces[i].m_plane[1], hullB.m_faces[i].m_plane[2]);
+ btVector3 WorldNormal = transB.getBasis() * Normal;
+ if (DeltaC2.dot(WorldNormal)<0)
+ WorldNormal *=-1.f;
+
+ curPlaneTests++;
+#ifdef TEST_INTERNAL_OBJECTS
+ gExpectedNbTests++;
+ if(gUseInternalObject && !TestInternalObjects(transA,transB,DeltaC2, WorldNormal, hullA, hullB, dmin))
+ continue;
+ gActualNbTests++;
+#endif
+
+ btScalar d;
+ btVector3 wA,wB;
+ if(!TestSepAxis(hullA, hullB,transA,transB, WorldNormal,d,wA,wB))
+ return false;
+
+ if(d<dmin)
+ {
+ dmin = d;
+ sep = WorldNormal;
+ }
+ }
+
+ btVector3 edgeAstart,edgeAend,edgeBstart,edgeBend;
+ int edgeA=-1;
+ int edgeB=-1;
+ btVector3 worldEdgeA;
+ btVector3 worldEdgeB;
+ btVector3 witnessPointA(0,0,0),witnessPointB(0,0,0);
+
+
+ int curEdgeEdge = 0;
+ // Test edges
+ for(int e0=0;e0<hullA.m_uniqueEdges.size();e0++)
+ {
+ const btVector3 edge0 = hullA.m_uniqueEdges[e0];
+ const btVector3 WorldEdge0 = transA.getBasis() * edge0;
+ for(int e1=0;e1<hullB.m_uniqueEdges.size();e1++)
+ {
+ const btVector3 edge1 = hullB.m_uniqueEdges[e1];
+ const btVector3 WorldEdge1 = transB.getBasis() * edge1;
+
+ btVector3 Cross = WorldEdge0.cross(WorldEdge1);
+ curEdgeEdge++;
+ if(!IsAlmostZero(Cross))
+ {
+ Cross = Cross.normalize();
+ if (DeltaC2.dot(Cross)<0)
+ Cross *= -1.f;
+
+
+#ifdef TEST_INTERNAL_OBJECTS
+ gExpectedNbTests++;
+ if(gUseInternalObject && !TestInternalObjects(transA,transB,DeltaC2, Cross, hullA, hullB, dmin))
+ continue;
+ gActualNbTests++;
+#endif
+
+ btScalar dist;
+ btVector3 wA,wB;
+ if(!TestSepAxis( hullA, hullB, transA,transB, Cross, dist,wA,wB))
+ return false;
+
+ if(dist<dmin)
+ {
+ dmin = dist;
+ sep = Cross;
+ edgeA=e0;
+ edgeB=e1;
+ worldEdgeA = WorldEdge0;
+ worldEdgeB = WorldEdge1;
+ witnessPointA=wA;
+ witnessPointB=wB;
+ }
+ }
+ }
+
+ }
+
+ if (edgeA>=0&&edgeB>=0)
+ {
+// printf("edge-edge\n");
+ //add an edge-edge contact
+
+ btVector3 ptsVector;
+ btVector3 offsetA;
+ btVector3 offsetB;
+ btScalar tA;
+ btScalar tB;
+
+ btVector3 translation = witnessPointB-witnessPointA;
+
+ btVector3 dirA = worldEdgeA;
+ btVector3 dirB = worldEdgeB;
+
+ btScalar hlenB = 1e30f;
+ btScalar hlenA = 1e30f;
+
+ btSegmentsClosestPoints(ptsVector,offsetA,offsetB,tA,tB,
+ translation,
+ dirA, hlenA,
+ dirB,hlenB);
+
+ btScalar nlSqrt = ptsVector.length2();
+ if (nlSqrt>SIMD_EPSILON)
+ {
+ btScalar nl = btSqrt(nlSqrt);
+ ptsVector *= 1.f/nl;
+ if (ptsVector.dot(DeltaC2)<0.f)
+ {
+ ptsVector*=-1.f;
+ }
+ btVector3 ptOnB = witnessPointB + offsetB;
+ btScalar distance = nl;
+ resultOut.addContactPoint(ptsVector, ptOnB,-distance);
+ }
+
+ }
+
+
+ if((DeltaC2.dot(sep))<0.0f)
+ sep = -sep;
+
+ return true;
+}
+
+void btPolyhedralContactClipping::clipFaceAgainstHull(const btVector3& separatingNormal, const btConvexPolyhedron& hullA, const btTransform& transA, btVertexArray& worldVertsB1,btVertexArray& worldVertsB2, const btScalar minDist, btScalar maxDist,btDiscreteCollisionDetectorInterface::Result& resultOut)
+{
+ worldVertsB2.resize(0);
+ btVertexArray* pVtxIn = &worldVertsB1;
+ btVertexArray* pVtxOut = &worldVertsB2;
+ pVtxOut->reserve(pVtxIn->size());
+
+ int closestFaceA=-1;
+ {
+ btScalar dmin = FLT_MAX;
+ for(int face=0;face<hullA.m_faces.size();face++)
+ {
+ const btVector3 Normal(hullA.m_faces[face].m_plane[0], hullA.m_faces[face].m_plane[1], hullA.m_faces[face].m_plane[2]);
+ const btVector3 faceANormalWS = transA.getBasis() * Normal;
+
+ btScalar d = faceANormalWS.dot(separatingNormal);
+ if (d < dmin)
+ {
+ dmin = d;
+ closestFaceA = face;
+ }
+ }
+ }
+ if (closestFaceA<0)
+ return;
+
+ const btFace& polyA = hullA.m_faces[closestFaceA];
+
+ // clip polygon to back of planes of all faces of hull A that are adjacent to witness face
+ int numVerticesA = polyA.m_indices.size();
+ for(int e0=0;e0<numVerticesA;e0++)
+ {
+ const btVector3& a = hullA.m_vertices[polyA.m_indices[e0]];
+ const btVector3& b = hullA.m_vertices[polyA.m_indices[(e0+1)%numVerticesA]];
+ const btVector3 edge0 = a - b;
+ const btVector3 WorldEdge0 = transA.getBasis() * edge0;
+ btVector3 worldPlaneAnormal1 = transA.getBasis()* btVector3(polyA.m_plane[0],polyA.m_plane[1],polyA.m_plane[2]);
+
+ btVector3 planeNormalWS1 = -WorldEdge0.cross(worldPlaneAnormal1);//.cross(WorldEdge0);
+ btVector3 worldA1 = transA*a;
+ btScalar planeEqWS1 = -worldA1.dot(planeNormalWS1);
+
+//int otherFace=0;
+#ifdef BLA1
+ int otherFace = polyA.m_connectedFaces[e0];
+ btVector3 localPlaneNormal (hullA.m_faces[otherFace].m_plane[0],hullA.m_faces[otherFace].m_plane[1],hullA.m_faces[otherFace].m_plane[2]);
+ btScalar localPlaneEq = hullA.m_faces[otherFace].m_plane[3];
+
+ btVector3 planeNormalWS = transA.getBasis()*localPlaneNormal;
+ btScalar planeEqWS=localPlaneEq-planeNormalWS.dot(transA.getOrigin());
+#else
+ btVector3 planeNormalWS = planeNormalWS1;
+ btScalar planeEqWS=planeEqWS1;
+
+#endif
+ //clip face
+
+ clipFace(*pVtxIn, *pVtxOut,planeNormalWS,planeEqWS);
+ btSwap(pVtxIn,pVtxOut);
+ pVtxOut->resize(0);
+ }
+
+
+
+//#define ONLY_REPORT_DEEPEST_POINT
+
+ btVector3 point;
+
+
+ // only keep points that are behind the witness face
+ {
+ btVector3 localPlaneNormal (polyA.m_plane[0],polyA.m_plane[1],polyA.m_plane[2]);
+ btScalar localPlaneEq = polyA.m_plane[3];
+ btVector3 planeNormalWS = transA.getBasis()*localPlaneNormal;
+ btScalar planeEqWS=localPlaneEq-planeNormalWS.dot(transA.getOrigin());
+ for (int i=0;i<pVtxIn->size();i++)
+ {
+ btVector3 vtx = pVtxIn->at(i);
+ btScalar depth = planeNormalWS.dot(vtx)+planeEqWS;
+ if (depth <=minDist)
+ {
+// printf("clamped: depth=%f to minDist=%f\n",depth,minDist);
+ depth = minDist;
+ }
+
+ if (depth <=maxDist)
+ {
+ btVector3 point = pVtxIn->at(i);
+#ifdef ONLY_REPORT_DEEPEST_POINT
+ curMaxDist = depth;
+#else
+#if 0
+ if (depth<-3)
+ {
+ printf("error in btPolyhedralContactClipping depth = %f\n", depth);
+ printf("likely wrong separatingNormal passed in\n");
+ }
+#endif
+ resultOut.addContactPoint(separatingNormal,point,depth);
+#endif
+ }
+ }
+ }
+#ifdef ONLY_REPORT_DEEPEST_POINT
+ if (curMaxDist<maxDist)
+ {
+ resultOut.addContactPoint(separatingNormal,point,curMaxDist);
+ }
+#endif //ONLY_REPORT_DEEPEST_POINT
+
+}
+
+
+
+
+
+void btPolyhedralContactClipping::clipHullAgainstHull(const btVector3& separatingNormal1, const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA,const btTransform& transB, const btScalar minDist, btScalar maxDist,btVertexArray& worldVertsB1,btVertexArray& worldVertsB2,btDiscreteCollisionDetectorInterface::Result& resultOut)
+{
+
+ btVector3 separatingNormal = separatingNormal1.normalized();
+// const btVector3 c0 = transA * hullA.m_localCenter;
+// const btVector3 c1 = transB * hullB.m_localCenter;
+ //const btVector3 DeltaC2 = c0 - c1;
+
+
+
+ int closestFaceB=-1;
+ btScalar dmax = -FLT_MAX;
+ {
+ for(int face=0;face<hullB.m_faces.size();face++)
+ {
+ const btVector3 Normal(hullB.m_faces[face].m_plane[0], hullB.m_faces[face].m_plane[1], hullB.m_faces[face].m_plane[2]);
+ const btVector3 WorldNormal = transB.getBasis() * Normal;
+ btScalar d = WorldNormal.dot(separatingNormal);
+ if (d > dmax)
+ {
+ dmax = d;
+ closestFaceB = face;
+ }
+ }
+ }
+ worldVertsB1.resize(0);
+ {
+ const btFace& polyB = hullB.m_faces[closestFaceB];
+ const int numVertices = polyB.m_indices.size();
+ for(int e0=0;e0<numVertices;e0++)
+ {
+ const btVector3& b = hullB.m_vertices[polyB.m_indices[e0]];
+ worldVertsB1.push_back(transB*b);
+ }
+ }
+
+
+ if (closestFaceB>=0)
+ clipFaceAgainstHull(separatingNormal, hullA, transA,worldVertsB1, worldVertsB2,minDist, maxDist,resultOut);
+
+}
diff --git a/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h
new file mode 100644
index 0000000000..30e3db687b
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h
@@ -0,0 +1,49 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2011 Advanced Micro Devices, 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.
+*/
+
+
+///This file was written by Erwin Coumans
+
+
+#ifndef BT_POLYHEDRAL_CONTACT_CLIPPING_H
+#define BT_POLYHEDRAL_CONTACT_CLIPPING_H
+
+
+#include "LinearMath/btAlignedObjectArray.h"
+#include "LinearMath/btTransform.h"
+#include "btDiscreteCollisionDetectorInterface.h"
+
+class btConvexPolyhedron;
+
+typedef btAlignedObjectArray<btVector3> btVertexArray;
+
+// Clips a face to the back of a plane
+struct btPolyhedralContactClipping
+{
+
+ static void clipHullAgainstHull(const btVector3& separatingNormal1, const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA,const btTransform& transB, const btScalar minDist, btScalar maxDist,btVertexArray& worldVertsB1,btVertexArray& worldVertsB2,btDiscreteCollisionDetectorInterface::Result& resultOut);
+
+ static void clipFaceAgainstHull(const btVector3& separatingNormal, const btConvexPolyhedron& hullA, const btTransform& transA, btVertexArray& worldVertsB1,btVertexArray& worldVertsB2, const btScalar minDist, btScalar maxDist,btDiscreteCollisionDetectorInterface::Result& resultOut);
+
+
+ static bool findSeparatingAxis( const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA,const btTransform& transB, btVector3& sep, btDiscreteCollisionDetectorInterface::Result& resultOut);
+
+ ///the clipFace method is used internally
+ static void clipFace(const btVertexArray& pVtxIn, btVertexArray& ppVtxOut, const btVector3& planeNormalWS,btScalar planeEqWS);
+
+};
+
+#endif // BT_POLYHEDRAL_CONTACT_CLIPPING_H
+
diff --git a/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp
new file mode 100644
index 0000000000..786efd1820
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp
@@ -0,0 +1,178 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+//#include <stdio.h>
+
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+#include "BulletCollision/CollisionShapes/btTriangleShape.h"
+#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h"
+#include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
+#include "btRaycastCallback.h"
+
+btTriangleRaycastCallback::btTriangleRaycastCallback(const btVector3& from,const btVector3& to, unsigned int flags)
+ :
+ m_from(from),
+ m_to(to),
+ //@BP Mod
+ m_flags(flags),
+ m_hitFraction(btScalar(1.))
+{
+
+}
+
+
+
+void btTriangleRaycastCallback::processTriangle(btVector3* triangle,int partId, int triangleIndex)
+{
+ const btVector3 &vert0=triangle[0];
+ const btVector3 &vert1=triangle[1];
+ const btVector3 &vert2=triangle[2];
+
+ btVector3 v10; v10 = vert1 - vert0 ;
+ btVector3 v20; v20 = vert2 - vert0 ;
+
+ btVector3 triangleNormal; triangleNormal = v10.cross( v20 );
+
+ const btScalar dist = vert0.dot(triangleNormal);
+ btScalar dist_a = triangleNormal.dot(m_from) ;
+ dist_a-= dist;
+ btScalar dist_b = triangleNormal.dot(m_to);
+ dist_b -= dist;
+
+ if ( dist_a * dist_b >= btScalar(0.0) )
+ {
+ return ; // same sign
+ }
+
+ if (((m_flags & kF_FilterBackfaces) != 0) && (dist_a <= btScalar(0.0)))
+ {
+ // Backface, skip check
+ return;
+ }
+
+
+ const btScalar proj_length=dist_a-dist_b;
+ const btScalar distance = (dist_a)/(proj_length);
+ // Now we have the intersection point on the plane, we'll see if it's inside the triangle
+ // Add an epsilon as a tolerance for the raycast,
+ // in case the ray hits exacly on the edge of the triangle.
+ // It must be scaled for the triangle size.
+
+ if(distance < m_hitFraction)
+ {
+
+
+ btScalar edge_tolerance =triangleNormal.length2();
+ edge_tolerance *= btScalar(-0.0001);
+ btVector3 point; point.setInterpolate3( m_from, m_to, distance);
+ {
+ btVector3 v0p; v0p = vert0 - point;
+ btVector3 v1p; v1p = vert1 - point;
+ btVector3 cp0; cp0 = v0p.cross( v1p );
+
+ if ( (btScalar)(cp0.dot(triangleNormal)) >=edge_tolerance)
+ {
+
+
+ btVector3 v2p; v2p = vert2 - point;
+ btVector3 cp1;
+ cp1 = v1p.cross( v2p);
+ if ( (btScalar)(cp1.dot(triangleNormal)) >=edge_tolerance)
+ {
+ btVector3 cp2;
+ cp2 = v2p.cross(v0p);
+
+ if ( (btScalar)(cp2.dot(triangleNormal)) >=edge_tolerance)
+ {
+ //@BP Mod
+ // Triangle normal isn't normalized
+ triangleNormal.normalize();
+
+ //@BP Mod - Allow for unflipped normal when raycasting against backfaces
+ if (((m_flags & kF_KeepUnflippedNormal) == 0) && (dist_a <= btScalar(0.0)))
+ {
+ m_hitFraction = reportHit(-triangleNormal,distance,partId,triangleIndex);
+ }
+ else
+ {
+ m_hitFraction = reportHit(triangleNormal,distance,partId,triangleIndex);
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+
+btTriangleConvexcastCallback::btTriangleConvexcastCallback (const btConvexShape* convexShape, const btTransform& convexShapeFrom, const btTransform& convexShapeTo, const btTransform& triangleToWorld, const btScalar triangleCollisionMargin)
+{
+ m_convexShape = convexShape;
+ m_convexShapeFrom = convexShapeFrom;
+ m_convexShapeTo = convexShapeTo;
+ m_triangleToWorld = triangleToWorld;
+ m_hitFraction = 1.0f;
+ m_triangleCollisionMargin = triangleCollisionMargin;
+ m_allowedPenetration = 0.f;
+}
+
+void
+btTriangleConvexcastCallback::processTriangle (btVector3* triangle, int partId, int triangleIndex)
+{
+ btTriangleShape triangleShape (triangle[0], triangle[1], triangle[2]);
+ triangleShape.setMargin(m_triangleCollisionMargin);
+
+ btVoronoiSimplexSolver simplexSolver;
+ btGjkEpaPenetrationDepthSolver gjkEpaPenetrationSolver;
+
+//#define USE_SUBSIMPLEX_CONVEX_CAST 1
+//if you reenable USE_SUBSIMPLEX_CONVEX_CAST see commented out code below
+#ifdef USE_SUBSIMPLEX_CONVEX_CAST
+ btSubsimplexConvexCast convexCaster(m_convexShape, &triangleShape, &simplexSolver);
+#else
+ //btGjkConvexCast convexCaster(m_convexShape,&triangleShape,&simplexSolver);
+ btContinuousConvexCollision convexCaster(m_convexShape,&triangleShape,&simplexSolver,&gjkEpaPenetrationSolver);
+#endif //#USE_SUBSIMPLEX_CONVEX_CAST
+
+ btConvexCast::CastResult castResult;
+ castResult.m_fraction = btScalar(1.);
+ castResult.m_allowedPenetration = m_allowedPenetration;
+ if (convexCaster.calcTimeOfImpact(m_convexShapeFrom,m_convexShapeTo,m_triangleToWorld, m_triangleToWorld, castResult))
+ {
+ //add hit
+ if (castResult.m_normal.length2() > btScalar(0.0001))
+ {
+ if (castResult.m_fraction < m_hitFraction)
+ {
+/* btContinuousConvexCast's normal is already in world space */
+/*
+#ifdef USE_SUBSIMPLEX_CONVEX_CAST
+ //rotate normal into worldspace
+ castResult.m_normal = m_convexShapeFrom.getBasis() * castResult.m_normal;
+#endif //USE_SUBSIMPLEX_CONVEX_CAST
+*/
+ castResult.m_normal.normalize();
+
+ reportHit (castResult.m_normal,
+ castResult.m_hitPoint,
+ castResult.m_fraction,
+ partId,
+ triangleIndex);
+ }
+ }
+ }
+}
diff --git a/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h
new file mode 100644
index 0000000000..f2ed0cd39c
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h
@@ -0,0 +1,74 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_RAYCAST_TRI_CALLBACK_H
+#define BT_RAYCAST_TRI_CALLBACK_H
+
+#include "BulletCollision/CollisionShapes/btTriangleCallback.h"
+#include "LinearMath/btTransform.h"
+struct btBroadphaseProxy;
+class btConvexShape;
+
+class btTriangleRaycastCallback: public btTriangleCallback
+{
+public:
+
+ //input
+ btVector3 m_from;
+ btVector3 m_to;
+
+ //@BP Mod - allow backface filtering and unflipped normals
+ enum EFlags
+ {
+ kF_None = 0,
+ kF_FilterBackfaces = 1 << 0,
+ kF_KeepUnflippedNormal = 1 << 1, // Prevents returned face normal getting flipped when a ray hits a back-facing triangle
+ ///SubSimplexConvexCastRaytest is the default, even if kF_None is set.
+ kF_UseSubSimplexConvexCastRaytest = 1 << 2, // Uses an approximate but faster ray versus convex intersection algorithm
+ kF_UseGjkConvexCastRaytest = 1 << 3,
+ kF_Terminator = 0xFFFFFFFF
+ };
+ unsigned int m_flags;
+
+ btScalar m_hitFraction;
+
+ btTriangleRaycastCallback(const btVector3& from,const btVector3& to, unsigned int flags=0);
+
+ virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex);
+
+ virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex ) = 0;
+
+};
+
+class btTriangleConvexcastCallback : public btTriangleCallback
+{
+public:
+ const btConvexShape* m_convexShape;
+ btTransform m_convexShapeFrom;
+ btTransform m_convexShapeTo;
+ btTransform m_triangleToWorld;
+ btScalar m_hitFraction;
+ btScalar m_triangleCollisionMargin;
+ btScalar m_allowedPenetration;
+
+ btTriangleConvexcastCallback (const btConvexShape* convexShape, const btTransform& convexShapeFrom, const btTransform& convexShapeTo, const btTransform& triangleToWorld, const btScalar triangleCollisionMargin);
+
+ virtual void processTriangle (btVector3* triangle, int partId, int triangleIndex);
+
+ virtual btScalar reportHit (const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex) = 0;
+};
+
+#endif //BT_RAYCAST_TRI_CALLBACK_H
+
diff --git a/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h
new file mode 100644
index 0000000000..da8a13914c
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h
@@ -0,0 +1,63 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+#ifndef BT_SIMPLEX_SOLVER_INTERFACE_H
+#define BT_SIMPLEX_SOLVER_INTERFACE_H
+
+#include "LinearMath/btVector3.h"
+
+#define NO_VIRTUAL_INTERFACE 1
+#ifdef NO_VIRTUAL_INTERFACE
+#include "btVoronoiSimplexSolver.h"
+#define btSimplexSolverInterface btVoronoiSimplexSolver
+#else
+
+/// btSimplexSolverInterface can incrementally calculate distance between origin and up to 4 vertices
+/// Used by GJK or Linear Casting. Can be implemented by the Johnson-algorithm or alternative approaches based on
+/// voronoi regions or barycentric coordinates
+class btSimplexSolverInterface
+{
+ public:
+ virtual ~btSimplexSolverInterface() {};
+
+ virtual void reset() = 0;
+
+ virtual void addVertex(const btVector3& w, const btVector3& p, const btVector3& q) = 0;
+
+ virtual bool closest(btVector3& v) = 0;
+
+ virtual btScalar maxVertex() = 0;
+
+ virtual bool fullSimplex() const = 0;
+
+ virtual int getSimplex(btVector3 *pBuf, btVector3 *qBuf, btVector3 *yBuf) const = 0;
+
+ virtual bool inSimplex(const btVector3& w) = 0;
+
+ virtual void backup_closest(btVector3& v) = 0;
+
+ virtual bool emptySimplex() const = 0;
+
+ virtual void compute_points(btVector3& p1, btVector3& p2) = 0;
+
+ virtual int numVertices() const =0;
+
+
+};
+#endif
+#endif //BT_SIMPLEX_SOLVER_INTERFACE_H
+
diff --git a/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp
new file mode 100644
index 0000000000..ec638f60ba
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp
@@ -0,0 +1,160 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "btSubSimplexConvexCast.h"
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+
+#include "BulletCollision/CollisionShapes/btMinkowskiSumShape.h"
+#include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h"
+#include "btPointCollector.h"
+#include "LinearMath/btTransformUtil.h"
+
+btSubsimplexConvexCast::btSubsimplexConvexCast (const btConvexShape* convexA,const btConvexShape* convexB,btSimplexSolverInterface* simplexSolver)
+:m_simplexSolver(simplexSolver),
+m_convexA(convexA),m_convexB(convexB)
+{
+}
+
+///Typically the conservative advancement reaches solution in a few iterations, clip it to 32 for degenerate cases.
+///See discussion about this here http://continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=565
+#ifdef BT_USE_DOUBLE_PRECISION
+#define MAX_ITERATIONS 64
+#else
+#define MAX_ITERATIONS 32
+#endif
+bool btSubsimplexConvexCast::calcTimeOfImpact(
+ const btTransform& fromA,
+ const btTransform& toA,
+ const btTransform& fromB,
+ const btTransform& toB,
+ CastResult& result)
+{
+
+ m_simplexSolver->reset();
+
+ btVector3 linVelA,linVelB;
+ linVelA = toA.getOrigin()-fromA.getOrigin();
+ linVelB = toB.getOrigin()-fromB.getOrigin();
+
+ btScalar lambda = btScalar(0.);
+
+ btTransform interpolatedTransA = fromA;
+ btTransform interpolatedTransB = fromB;
+
+ ///take relative motion
+ btVector3 r = (linVelA-linVelB);
+ btVector3 v;
+
+ btVector3 supVertexA = fromA(m_convexA->localGetSupportingVertex(-r*fromA.getBasis()));
+ btVector3 supVertexB = fromB(m_convexB->localGetSupportingVertex(r*fromB.getBasis()));
+ v = supVertexA-supVertexB;
+ int maxIter = MAX_ITERATIONS;
+
+ btVector3 n;
+ n.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
+
+ btVector3 c;
+
+
+
+
+ btScalar dist2 = v.length2();
+#ifdef BT_USE_DOUBLE_PRECISION
+ btScalar epsilon = btScalar(0.0001);
+#else
+ btScalar epsilon = btScalar(0.0001);
+#endif //BT_USE_DOUBLE_PRECISION
+ btVector3 w,p;
+ btScalar VdotR;
+
+ while ( (dist2 > epsilon) && maxIter--)
+ {
+ supVertexA = interpolatedTransA(m_convexA->localGetSupportingVertex(-v*interpolatedTransA.getBasis()));
+ supVertexB = interpolatedTransB(m_convexB->localGetSupportingVertex(v*interpolatedTransB.getBasis()));
+ w = supVertexA-supVertexB;
+
+ btScalar VdotW = v.dot(w);
+
+ if (lambda > btScalar(1.0))
+ {
+ return false;
+ }
+
+ if ( VdotW > btScalar(0.))
+ {
+ VdotR = v.dot(r);
+
+ if (VdotR >= -(SIMD_EPSILON*SIMD_EPSILON))
+ return false;
+ else
+ {
+ lambda = lambda - VdotW / VdotR;
+ //interpolate to next lambda
+ // x = s + lambda * r;
+ interpolatedTransA.getOrigin().setInterpolate3(fromA.getOrigin(),toA.getOrigin(),lambda);
+ interpolatedTransB.getOrigin().setInterpolate3(fromB.getOrigin(),toB.getOrigin(),lambda);
+ //m_simplexSolver->reset();
+ //check next line
+ w = supVertexA-supVertexB;
+
+ n = v;
+
+ }
+ }
+ ///Just like regular GJK only add the vertex if it isn't already (close) to current vertex, it would lead to divisions by zero and NaN etc.
+ if (!m_simplexSolver->inSimplex(w))
+ m_simplexSolver->addVertex( w, supVertexA , supVertexB);
+
+ if (m_simplexSolver->closest(v))
+ {
+ dist2 = v.length2();
+
+ //todo: check this normal for validity
+ //n=v;
+ //printf("V=%f , %f, %f\n",v[0],v[1],v[2]);
+ //printf("DIST2=%f\n",dist2);
+ //printf("numverts = %i\n",m_simplexSolver->numVertices());
+ } else
+ {
+ dist2 = btScalar(0.);
+ }
+ }
+
+ //int numiter = MAX_ITERATIONS - maxIter;
+// printf("number of iterations: %d", numiter);
+
+ //don't report a time of impact when moving 'away' from the hitnormal
+
+
+ result.m_fraction = lambda;
+ if (n.length2() >= (SIMD_EPSILON*SIMD_EPSILON))
+ result.m_normal = n.normalized();
+ else
+ result.m_normal = btVector3(btScalar(0.0), btScalar(0.0), btScalar(0.0));
+
+ //don't report time of impact for motion away from the contact normal (or causes minor penetration)
+ if (result.m_normal.dot(r)>=-result.m_allowedPenetration)
+ return false;
+
+ btVector3 hitA,hitB;
+ m_simplexSolver->compute_points(hitA,hitB);
+ result.m_hitPoint=hitB;
+ return true;
+}
+
+
+
+
diff --git a/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h
new file mode 100644
index 0000000000..6c8127983e
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h
@@ -0,0 +1,50 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#ifndef BT_SUBSIMPLEX_CONVEX_CAST_H
+#define BT_SUBSIMPLEX_CONVEX_CAST_H
+
+#include "btConvexCast.h"
+#include "btSimplexSolverInterface.h"
+class btConvexShape;
+
+/// btSubsimplexConvexCast implements Gino van den Bergens' paper
+///"Ray Casting against bteral Convex Objects with Application to Continuous Collision Detection"
+/// GJK based Ray Cast, optimized version
+/// Objects should not start in overlap, otherwise results are not defined.
+class btSubsimplexConvexCast : public btConvexCast
+{
+ btSimplexSolverInterface* m_simplexSolver;
+ const btConvexShape* m_convexA;
+ const btConvexShape* m_convexB;
+
+public:
+
+ btSubsimplexConvexCast (const btConvexShape* shapeA,const btConvexShape* shapeB,btSimplexSolverInterface* simplexSolver);
+
+ //virtual ~btSubsimplexConvexCast();
+ ///SimsimplexConvexCast calculateTimeOfImpact calculates the time of impact+normal for the linear cast (sweep) between two moving objects.
+ ///Precondition is that objects should not penetration/overlap at the start from the interval. Overlap can be tested using btGjkPairDetector.
+ virtual bool calcTimeOfImpact(
+ const btTransform& fromA,
+ const btTransform& toA,
+ const btTransform& fromB,
+ const btTransform& toB,
+ CastResult& result);
+
+};
+
+#endif //BT_SUBSIMPLEX_CONVEX_CAST_H
diff --git a/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp
new file mode 100644
index 0000000000..756373c9b5
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp
@@ -0,0 +1,612 @@
+
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+
+ Elsevier CDROM license agreements grants nonexclusive license to use the software
+ for any purpose, commercial or non-commercial as long as the following credit is included
+ identifying the original source of the software:
+
+ Parts of the source are "from the book Real-Time Collision Detection by
+ Christer Ericson, published by Morgan Kaufmann Publishers,
+ (c) 2005 Elsevier Inc."
+
+*/
+
+
+#include "btVoronoiSimplexSolver.h"
+
+#define VERTA 0
+#define VERTB 1
+#define VERTC 2
+#define VERTD 3
+
+#define CATCH_DEGENERATE_TETRAHEDRON 1
+void btVoronoiSimplexSolver::removeVertex(int index)
+{
+
+ btAssert(m_numVertices>0);
+ m_numVertices--;
+ m_simplexVectorW[index] = m_simplexVectorW[m_numVertices];
+ m_simplexPointsP[index] = m_simplexPointsP[m_numVertices];
+ m_simplexPointsQ[index] = m_simplexPointsQ[m_numVertices];
+}
+
+void btVoronoiSimplexSolver::reduceVertices (const btUsageBitfield& usedVerts)
+{
+ if ((numVertices() >= 4) && (!usedVerts.usedVertexD))
+ removeVertex(3);
+
+ if ((numVertices() >= 3) && (!usedVerts.usedVertexC))
+ removeVertex(2);
+
+ if ((numVertices() >= 2) && (!usedVerts.usedVertexB))
+ removeVertex(1);
+
+ if ((numVertices() >= 1) && (!usedVerts.usedVertexA))
+ removeVertex(0);
+
+}
+
+
+
+
+
+//clear the simplex, remove all the vertices
+void btVoronoiSimplexSolver::reset()
+{
+ m_cachedValidClosest = false;
+ m_numVertices = 0;
+ m_needsUpdate = true;
+ m_lastW = btVector3(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
+ m_cachedBC.reset();
+}
+
+
+
+ //add a vertex
+void btVoronoiSimplexSolver::addVertex(const btVector3& w, const btVector3& p, const btVector3& q)
+{
+ m_lastW = w;
+ m_needsUpdate = true;
+
+ m_simplexVectorW[m_numVertices] = w;
+ m_simplexPointsP[m_numVertices] = p;
+ m_simplexPointsQ[m_numVertices] = q;
+
+ m_numVertices++;
+}
+
+bool btVoronoiSimplexSolver::updateClosestVectorAndPoints()
+{
+
+ if (m_needsUpdate)
+ {
+ m_cachedBC.reset();
+
+ m_needsUpdate = false;
+
+ switch (numVertices())
+ {
+ case 0:
+ m_cachedValidClosest = false;
+ break;
+ case 1:
+ {
+ m_cachedP1 = m_simplexPointsP[0];
+ m_cachedP2 = m_simplexPointsQ[0];
+ m_cachedV = m_cachedP1-m_cachedP2; //== m_simplexVectorW[0]
+ m_cachedBC.reset();
+ m_cachedBC.setBarycentricCoordinates(btScalar(1.),btScalar(0.),btScalar(0.),btScalar(0.));
+ m_cachedValidClosest = m_cachedBC.isValid();
+ break;
+ };
+ case 2:
+ {
+ //closest point origin from line segment
+ const btVector3& from = m_simplexVectorW[0];
+ const btVector3& to = m_simplexVectorW[1];
+ btVector3 nearest;
+
+ btVector3 p (btScalar(0.),btScalar(0.),btScalar(0.));
+ btVector3 diff = p - from;
+ btVector3 v = to - from;
+ btScalar t = v.dot(diff);
+
+ if (t > 0) {
+ btScalar dotVV = v.dot(v);
+ if (t < dotVV) {
+ t /= dotVV;
+ diff -= t*v;
+ m_cachedBC.m_usedVertices.usedVertexA = true;
+ m_cachedBC.m_usedVertices.usedVertexB = true;
+ } else {
+ t = 1;
+ diff -= v;
+ //reduce to 1 point
+ m_cachedBC.m_usedVertices.usedVertexB = true;
+ }
+ } else
+ {
+ t = 0;
+ //reduce to 1 point
+ m_cachedBC.m_usedVertices.usedVertexA = true;
+ }
+ m_cachedBC.setBarycentricCoordinates(1-t,t);
+ nearest = from + t*v;
+
+ m_cachedP1 = m_simplexPointsP[0] + t * (m_simplexPointsP[1] - m_simplexPointsP[0]);
+ m_cachedP2 = m_simplexPointsQ[0] + t * (m_simplexPointsQ[1] - m_simplexPointsQ[0]);
+ m_cachedV = m_cachedP1 - m_cachedP2;
+
+ reduceVertices(m_cachedBC.m_usedVertices);
+
+ m_cachedValidClosest = m_cachedBC.isValid();
+ break;
+ }
+ case 3:
+ {
+ //closest point origin from triangle
+ btVector3 p (btScalar(0.),btScalar(0.),btScalar(0.));
+
+ const btVector3& a = m_simplexVectorW[0];
+ const btVector3& b = m_simplexVectorW[1];
+ const btVector3& c = m_simplexVectorW[2];
+
+ closestPtPointTriangle(p,a,b,c,m_cachedBC);
+ m_cachedP1 = m_simplexPointsP[0] * m_cachedBC.m_barycentricCoords[0] +
+ m_simplexPointsP[1] * m_cachedBC.m_barycentricCoords[1] +
+ m_simplexPointsP[2] * m_cachedBC.m_barycentricCoords[2];
+
+ m_cachedP2 = m_simplexPointsQ[0] * m_cachedBC.m_barycentricCoords[0] +
+ m_simplexPointsQ[1] * m_cachedBC.m_barycentricCoords[1] +
+ m_simplexPointsQ[2] * m_cachedBC.m_barycentricCoords[2];
+
+ m_cachedV = m_cachedP1-m_cachedP2;
+
+ reduceVertices (m_cachedBC.m_usedVertices);
+ m_cachedValidClosest = m_cachedBC.isValid();
+
+ break;
+ }
+ case 4:
+ {
+
+
+ btVector3 p (btScalar(0.),btScalar(0.),btScalar(0.));
+
+ const btVector3& a = m_simplexVectorW[0];
+ const btVector3& b = m_simplexVectorW[1];
+ const btVector3& c = m_simplexVectorW[2];
+ const btVector3& d = m_simplexVectorW[3];
+
+ bool hasSeparation = closestPtPointTetrahedron(p,a,b,c,d,m_cachedBC);
+
+ if (hasSeparation)
+ {
+
+ m_cachedP1 = m_simplexPointsP[0] * m_cachedBC.m_barycentricCoords[0] +
+ m_simplexPointsP[1] * m_cachedBC.m_barycentricCoords[1] +
+ m_simplexPointsP[2] * m_cachedBC.m_barycentricCoords[2] +
+ m_simplexPointsP[3] * m_cachedBC.m_barycentricCoords[3];
+
+ m_cachedP2 = m_simplexPointsQ[0] * m_cachedBC.m_barycentricCoords[0] +
+ m_simplexPointsQ[1] * m_cachedBC.m_barycentricCoords[1] +
+ m_simplexPointsQ[2] * m_cachedBC.m_barycentricCoords[2] +
+ m_simplexPointsQ[3] * m_cachedBC.m_barycentricCoords[3];
+
+ m_cachedV = m_cachedP1-m_cachedP2;
+ reduceVertices (m_cachedBC.m_usedVertices);
+ } else
+ {
+// printf("sub distance got penetration\n");
+
+ if (m_cachedBC.m_degenerate)
+ {
+ m_cachedValidClosest = false;
+ } else
+ {
+ m_cachedValidClosest = true;
+ //degenerate case == false, penetration = true + zero
+ m_cachedV.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
+ }
+ break;
+ }
+
+ m_cachedValidClosest = m_cachedBC.isValid();
+
+ //closest point origin from tetrahedron
+ break;
+ }
+ default:
+ {
+ m_cachedValidClosest = false;
+ }
+ };
+ }
+
+ return m_cachedValidClosest;
+
+}
+
+//return/calculate the closest vertex
+bool btVoronoiSimplexSolver::closest(btVector3& v)
+{
+ bool succes = updateClosestVectorAndPoints();
+ v = m_cachedV;
+ return succes;
+}
+
+
+
+btScalar btVoronoiSimplexSolver::maxVertex()
+{
+ int i, numverts = numVertices();
+ btScalar maxV = btScalar(0.);
+ for (i=0;i<numverts;i++)
+ {
+ btScalar curLen2 = m_simplexVectorW[i].length2();
+ if (maxV < curLen2)
+ maxV = curLen2;
+ }
+ return maxV;
+}
+
+
+
+ //return the current simplex
+int btVoronoiSimplexSolver::getSimplex(btVector3 *pBuf, btVector3 *qBuf, btVector3 *yBuf) const
+{
+ int i;
+ for (i=0;i<numVertices();i++)
+ {
+ yBuf[i] = m_simplexVectorW[i];
+ pBuf[i] = m_simplexPointsP[i];
+ qBuf[i] = m_simplexPointsQ[i];
+ }
+ return numVertices();
+}
+
+
+
+
+bool btVoronoiSimplexSolver::inSimplex(const btVector3& w)
+{
+ bool found = false;
+ int i, numverts = numVertices();
+ //btScalar maxV = btScalar(0.);
+
+ //w is in the current (reduced) simplex
+ for (i=0;i<numverts;i++)
+ {
+#ifdef BT_USE_EQUAL_VERTEX_THRESHOLD
+ if ( m_simplexVectorW[i].distance2(w) <= m_equalVertexThreshold)
+#else
+ if (m_simplexVectorW[i] == w)
+#endif
+ {
+ found = true;
+ break;
+ }
+ }
+
+ //check in case lastW is already removed
+ if (w == m_lastW)
+ return true;
+
+ return found;
+}
+
+void btVoronoiSimplexSolver::backup_closest(btVector3& v)
+{
+ v = m_cachedV;
+}
+
+
+bool btVoronoiSimplexSolver::emptySimplex() const
+{
+ return (numVertices() == 0);
+
+}
+
+void btVoronoiSimplexSolver::compute_points(btVector3& p1, btVector3& p2)
+{
+ updateClosestVectorAndPoints();
+ p1 = m_cachedP1;
+ p2 = m_cachedP2;
+
+}
+
+
+
+
+bool btVoronoiSimplexSolver::closestPtPointTriangle(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c,btSubSimplexClosestResult& result)
+{
+ result.m_usedVertices.reset();
+
+ // Check if P in vertex region outside A
+ btVector3 ab = b - a;
+ btVector3 ac = c - a;
+ btVector3 ap = p - a;
+ btScalar d1 = ab.dot(ap);
+ btScalar d2 = ac.dot(ap);
+ if (d1 <= btScalar(0.0) && d2 <= btScalar(0.0))
+ {
+ result.m_closestPointOnSimplex = a;
+ result.m_usedVertices.usedVertexA = true;
+ result.setBarycentricCoordinates(1,0,0);
+ return true;// a; // barycentric coordinates (1,0,0)
+ }
+
+ // Check if P in vertex region outside B
+ btVector3 bp = p - b;
+ btScalar d3 = ab.dot(bp);
+ btScalar d4 = ac.dot(bp);
+ if (d3 >= btScalar(0.0) && d4 <= d3)
+ {
+ result.m_closestPointOnSimplex = b;
+ result.m_usedVertices.usedVertexB = true;
+ result.setBarycentricCoordinates(0,1,0);
+
+ return true; // b; // barycentric coordinates (0,1,0)
+ }
+ // Check if P in edge region of AB, if so return projection of P onto AB
+ btScalar vc = d1*d4 - d3*d2;
+ if (vc <= btScalar(0.0) && d1 >= btScalar(0.0) && d3 <= btScalar(0.0)) {
+ btScalar v = d1 / (d1 - d3);
+ result.m_closestPointOnSimplex = a + v * ab;
+ result.m_usedVertices.usedVertexA = true;
+ result.m_usedVertices.usedVertexB = true;
+ result.setBarycentricCoordinates(1-v,v,0);
+ return true;
+ //return a + v * ab; // barycentric coordinates (1-v,v,0)
+ }
+
+ // Check if P in vertex region outside C
+ btVector3 cp = p - c;
+ btScalar d5 = ab.dot(cp);
+ btScalar d6 = ac.dot(cp);
+ if (d6 >= btScalar(0.0) && d5 <= d6)
+ {
+ result.m_closestPointOnSimplex = c;
+ result.m_usedVertices.usedVertexC = true;
+ result.setBarycentricCoordinates(0,0,1);
+ return true;//c; // barycentric coordinates (0,0,1)
+ }
+
+ // Check if P in edge region of AC, if so return projection of P onto AC
+ btScalar vb = d5*d2 - d1*d6;
+ if (vb <= btScalar(0.0) && d2 >= btScalar(0.0) && d6 <= btScalar(0.0)) {
+ btScalar w = d2 / (d2 - d6);
+ result.m_closestPointOnSimplex = a + w * ac;
+ result.m_usedVertices.usedVertexA = true;
+ result.m_usedVertices.usedVertexC = true;
+ result.setBarycentricCoordinates(1-w,0,w);
+ return true;
+ //return a + w * ac; // barycentric coordinates (1-w,0,w)
+ }
+
+ // Check if P in edge region of BC, if so return projection of P onto BC
+ btScalar va = d3*d6 - d5*d4;
+ if (va <= btScalar(0.0) && (d4 - d3) >= btScalar(0.0) && (d5 - d6) >= btScalar(0.0)) {
+ btScalar w = (d4 - d3) / ((d4 - d3) + (d5 - d6));
+
+ result.m_closestPointOnSimplex = b + w * (c - b);
+ result.m_usedVertices.usedVertexB = true;
+ result.m_usedVertices.usedVertexC = true;
+ result.setBarycentricCoordinates(0,1-w,w);
+ return true;
+ // return b + w * (c - b); // barycentric coordinates (0,1-w,w)
+ }
+
+ // P inside face region. Compute Q through its barycentric coordinates (u,v,w)
+ btScalar denom = btScalar(1.0) / (va + vb + vc);
+ btScalar v = vb * denom;
+ btScalar w = vc * denom;
+
+ result.m_closestPointOnSimplex = a + ab * v + ac * w;
+ result.m_usedVertices.usedVertexA = true;
+ result.m_usedVertices.usedVertexB = true;
+ result.m_usedVertices.usedVertexC = true;
+ result.setBarycentricCoordinates(1-v-w,v,w);
+
+ return true;
+// return a + ab * v + ac * w; // = u*a + v*b + w*c, u = va * denom = btScalar(1.0) - v - w
+
+}
+
+
+
+
+
+/// Test if point p and d lie on opposite sides of plane through abc
+int btVoronoiSimplexSolver::pointOutsideOfPlane(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& d)
+{
+ btVector3 normal = (b-a).cross(c-a);
+
+ btScalar signp = (p - a).dot(normal); // [AP AB AC]
+ btScalar signd = (d - a).dot( normal); // [AD AB AC]
+
+#ifdef CATCH_DEGENERATE_TETRAHEDRON
+#ifdef BT_USE_DOUBLE_PRECISION
+if (signd * signd < (btScalar(1e-8) * btScalar(1e-8)))
+ {
+ return -1;
+ }
+#else
+ if (signd * signd < (btScalar(1e-4) * btScalar(1e-4)))
+ {
+// printf("affine dependent/degenerate\n");//
+ return -1;
+ }
+#endif
+
+#endif
+ // Points on opposite sides if expression signs are opposite
+ return signp * signd < btScalar(0.);
+}
+
+
+bool btVoronoiSimplexSolver::closestPtPointTetrahedron(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& d, btSubSimplexClosestResult& finalResult)
+{
+ btSubSimplexClosestResult tempResult;
+
+ // Start out assuming point inside all halfspaces, so closest to itself
+ finalResult.m_closestPointOnSimplex = p;
+ finalResult.m_usedVertices.reset();
+ finalResult.m_usedVertices.usedVertexA = true;
+ finalResult.m_usedVertices.usedVertexB = true;
+ finalResult.m_usedVertices.usedVertexC = true;
+ finalResult.m_usedVertices.usedVertexD = true;
+
+ int pointOutsideABC = pointOutsideOfPlane(p, a, b, c, d);
+ int pointOutsideACD = pointOutsideOfPlane(p, a, c, d, b);
+ int pointOutsideADB = pointOutsideOfPlane(p, a, d, b, c);
+ int pointOutsideBDC = pointOutsideOfPlane(p, b, d, c, a);
+
+ if (pointOutsideABC < 0 || pointOutsideACD < 0 || pointOutsideADB < 0 || pointOutsideBDC < 0)
+ {
+ finalResult.m_degenerate = true;
+ return false;
+ }
+
+ if (!pointOutsideABC && !pointOutsideACD && !pointOutsideADB && !pointOutsideBDC)
+ {
+ return false;
+ }
+
+
+ btScalar bestSqDist = FLT_MAX;
+ // If point outside face abc then compute closest point on abc
+ if (pointOutsideABC)
+ {
+ closestPtPointTriangle(p, a, b, c,tempResult);
+ btVector3 q = tempResult.m_closestPointOnSimplex;
+
+ btScalar sqDist = (q - p).dot( q - p);
+ // Update best closest point if (squared) distance is less than current best
+ if (sqDist < bestSqDist) {
+ bestSqDist = sqDist;
+ finalResult.m_closestPointOnSimplex = q;
+ //convert result bitmask!
+ finalResult.m_usedVertices.reset();
+ finalResult.m_usedVertices.usedVertexA = tempResult.m_usedVertices.usedVertexA;
+ finalResult.m_usedVertices.usedVertexB = tempResult.m_usedVertices.usedVertexB;
+ finalResult.m_usedVertices.usedVertexC = tempResult.m_usedVertices.usedVertexC;
+ finalResult.setBarycentricCoordinates(
+ tempResult.m_barycentricCoords[VERTA],
+ tempResult.m_barycentricCoords[VERTB],
+ tempResult.m_barycentricCoords[VERTC],
+ 0
+ );
+
+ }
+ }
+
+
+ // Repeat test for face acd
+ if (pointOutsideACD)
+ {
+ closestPtPointTriangle(p, a, c, d,tempResult);
+ btVector3 q = tempResult.m_closestPointOnSimplex;
+ //convert result bitmask!
+
+ btScalar sqDist = (q - p).dot( q - p);
+ if (sqDist < bestSqDist)
+ {
+ bestSqDist = sqDist;
+ finalResult.m_closestPointOnSimplex = q;
+ finalResult.m_usedVertices.reset();
+ finalResult.m_usedVertices.usedVertexA = tempResult.m_usedVertices.usedVertexA;
+
+ finalResult.m_usedVertices.usedVertexC = tempResult.m_usedVertices.usedVertexB;
+ finalResult.m_usedVertices.usedVertexD = tempResult.m_usedVertices.usedVertexC;
+ finalResult.setBarycentricCoordinates(
+ tempResult.m_barycentricCoords[VERTA],
+ 0,
+ tempResult.m_barycentricCoords[VERTB],
+ tempResult.m_barycentricCoords[VERTC]
+ );
+
+ }
+ }
+ // Repeat test for face adb
+
+
+ if (pointOutsideADB)
+ {
+ closestPtPointTriangle(p, a, d, b,tempResult);
+ btVector3 q = tempResult.m_closestPointOnSimplex;
+ //convert result bitmask!
+
+ btScalar sqDist = (q - p).dot( q - p);
+ if (sqDist < bestSqDist)
+ {
+ bestSqDist = sqDist;
+ finalResult.m_closestPointOnSimplex = q;
+ finalResult.m_usedVertices.reset();
+ finalResult.m_usedVertices.usedVertexA = tempResult.m_usedVertices.usedVertexA;
+ finalResult.m_usedVertices.usedVertexB = tempResult.m_usedVertices.usedVertexC;
+
+ finalResult.m_usedVertices.usedVertexD = tempResult.m_usedVertices.usedVertexB;
+ finalResult.setBarycentricCoordinates(
+ tempResult.m_barycentricCoords[VERTA],
+ tempResult.m_barycentricCoords[VERTC],
+ 0,
+ tempResult.m_barycentricCoords[VERTB]
+ );
+
+ }
+ }
+ // Repeat test for face bdc
+
+
+ if (pointOutsideBDC)
+ {
+ closestPtPointTriangle(p, b, d, c,tempResult);
+ btVector3 q = tempResult.m_closestPointOnSimplex;
+ //convert result bitmask!
+ btScalar sqDist = (q - p).dot( q - p);
+ if (sqDist < bestSqDist)
+ {
+ bestSqDist = sqDist;
+ finalResult.m_closestPointOnSimplex = q;
+ finalResult.m_usedVertices.reset();
+ //
+ finalResult.m_usedVertices.usedVertexB = tempResult.m_usedVertices.usedVertexA;
+ finalResult.m_usedVertices.usedVertexC = tempResult.m_usedVertices.usedVertexC;
+ finalResult.m_usedVertices.usedVertexD = tempResult.m_usedVertices.usedVertexB;
+
+ finalResult.setBarycentricCoordinates(
+ 0,
+ tempResult.m_barycentricCoords[VERTA],
+ tempResult.m_barycentricCoords[VERTC],
+ tempResult.m_barycentricCoords[VERTB]
+ );
+
+ }
+ }
+
+ //help! we ended up full !
+
+ if (finalResult.m_usedVertices.usedVertexA &&
+ finalResult.m_usedVertices.usedVertexB &&
+ finalResult.m_usedVertices.usedVertexC &&
+ finalResult.m_usedVertices.usedVertexD)
+ {
+ return true;
+ }
+
+ return true;
+}
+
diff --git a/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h
new file mode 100644
index 0000000000..80fd490f4e
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h
@@ -0,0 +1,185 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+#ifndef BT_VORONOI_SIMPLEX_SOLVER_H
+#define BT_VORONOI_SIMPLEX_SOLVER_H
+
+#include "btSimplexSolverInterface.h"
+
+
+
+#define VORONOI_SIMPLEX_MAX_VERTS 5
+
+///disable next define, or use defaultCollisionConfiguration->getSimplexSolver()->setEqualVertexThreshold(0.f) to disable/configure
+#define BT_USE_EQUAL_VERTEX_THRESHOLD
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define VORONOI_DEFAULT_EQUAL_VERTEX_THRESHOLD 1e-12f
+#else
+#define VORONOI_DEFAULT_EQUAL_VERTEX_THRESHOLD 0.0001f
+#endif//BT_USE_DOUBLE_PRECISION
+
+struct btUsageBitfield{
+ btUsageBitfield()
+ {
+ reset();
+ }
+
+ void reset()
+ {
+ usedVertexA = false;
+ usedVertexB = false;
+ usedVertexC = false;
+ usedVertexD = false;
+ }
+ unsigned short usedVertexA : 1;
+ unsigned short usedVertexB : 1;
+ unsigned short usedVertexC : 1;
+ unsigned short usedVertexD : 1;
+ unsigned short unused1 : 1;
+ unsigned short unused2 : 1;
+ unsigned short unused3 : 1;
+ unsigned short unused4 : 1;
+};
+
+
+struct btSubSimplexClosestResult
+{
+ btVector3 m_closestPointOnSimplex;
+ //MASK for m_usedVertices
+ //stores the simplex vertex-usage, using the MASK,
+ // if m_usedVertices & MASK then the related vertex is used
+ btUsageBitfield m_usedVertices;
+ btScalar m_barycentricCoords[4];
+ bool m_degenerate;
+
+ void reset()
+ {
+ m_degenerate = false;
+ setBarycentricCoordinates();
+ m_usedVertices.reset();
+ }
+ bool isValid()
+ {
+ bool valid = (m_barycentricCoords[0] >= btScalar(0.)) &&
+ (m_barycentricCoords[1] >= btScalar(0.)) &&
+ (m_barycentricCoords[2] >= btScalar(0.)) &&
+ (m_barycentricCoords[3] >= btScalar(0.));
+
+
+ return valid;
+ }
+ void setBarycentricCoordinates(btScalar a=btScalar(0.),btScalar b=btScalar(0.),btScalar c=btScalar(0.),btScalar d=btScalar(0.))
+ {
+ m_barycentricCoords[0] = a;
+ m_barycentricCoords[1] = b;
+ m_barycentricCoords[2] = c;
+ m_barycentricCoords[3] = d;
+ }
+
+};
+
+/// btVoronoiSimplexSolver is an implementation of the closest point distance algorithm from a 1-4 points simplex to the origin.
+/// Can be used with GJK, as an alternative to Johnson distance algorithm.
+#ifdef NO_VIRTUAL_INTERFACE
+ATTRIBUTE_ALIGNED16(class) btVoronoiSimplexSolver
+#else
+ATTRIBUTE_ALIGNED16(class) btVoronoiSimplexSolver : public btSimplexSolverInterface
+#endif
+{
+public:
+
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ int m_numVertices;
+
+ btVector3 m_simplexVectorW[VORONOI_SIMPLEX_MAX_VERTS];
+ btVector3 m_simplexPointsP[VORONOI_SIMPLEX_MAX_VERTS];
+ btVector3 m_simplexPointsQ[VORONOI_SIMPLEX_MAX_VERTS];
+
+
+
+ btVector3 m_cachedP1;
+ btVector3 m_cachedP2;
+ btVector3 m_cachedV;
+ btVector3 m_lastW;
+
+ btScalar m_equalVertexThreshold;
+ bool m_cachedValidClosest;
+
+
+ btSubSimplexClosestResult m_cachedBC;
+
+ bool m_needsUpdate;
+
+ void removeVertex(int index);
+ void reduceVertices (const btUsageBitfield& usedVerts);
+ bool updateClosestVectorAndPoints();
+
+ bool closestPtPointTetrahedron(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& d, btSubSimplexClosestResult& finalResult);
+ int pointOutsideOfPlane(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& d);
+ bool closestPtPointTriangle(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c,btSubSimplexClosestResult& result);
+
+public:
+
+ btVoronoiSimplexSolver()
+ : m_equalVertexThreshold(VORONOI_DEFAULT_EQUAL_VERTEX_THRESHOLD)
+ {
+ }
+ void reset();
+
+ void addVertex(const btVector3& w, const btVector3& p, const btVector3& q);
+
+ void setEqualVertexThreshold(btScalar threshold)
+ {
+ m_equalVertexThreshold = threshold;
+ }
+
+ btScalar getEqualVertexThreshold() const
+ {
+ return m_equalVertexThreshold;
+ }
+
+ bool closest(btVector3& v);
+
+ btScalar maxVertex();
+
+ bool fullSimplex() const
+ {
+ return (m_numVertices == 4);
+ }
+
+ int getSimplex(btVector3 *pBuf, btVector3 *qBuf, btVector3 *yBuf) const;
+
+ bool inSimplex(const btVector3& w);
+
+ void backup_closest(btVector3& v) ;
+
+ bool emptySimplex() const ;
+
+ void compute_points(btVector3& p1, btVector3& p2) ;
+
+ int numVertices() const
+ {
+ return m_numVertices;
+ }
+
+
+};
+
+#endif //BT_VORONOI_SIMPLEX_SOLVER_H
+
diff --git a/thirdparty/bullet/src/BulletCollision/premake4.lua b/thirdparty/bullet/src/BulletCollision/premake4.lua
new file mode 100644
index 0000000000..70019df8f6
--- /dev/null
+++ b/thirdparty/bullet/src/BulletCollision/premake4.lua
@@ -0,0 +1,20 @@
+ project "BulletCollision"
+
+ kind "StaticLib"
+ includedirs {
+ "..",
+ }
+ files {
+ "*.cpp",
+ "*.h",
+ "BroadphaseCollision/*.cpp",
+ "BroadphaseCollision/*.h",
+ "CollisionDispatch/*.cpp",
+ "CollisionDispatch/*.h",
+ "CollisionShapes/*.cpp",
+ "CollisionShapes/*.h",
+ "Gimpact/*.cpp",
+ "Gimpact/*.h",
+ "NarrowPhaseCollision/*.cpp",
+ "NarrowPhaseCollision/*.h",
+ }
diff --git a/thirdparty/bullet/src/BulletDynamics/CMakeLists.txt b/thirdparty/bullet/src/BulletDynamics/CMakeLists.txt
new file mode 100644
index 0000000000..f8a6f34baf
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/CMakeLists.txt
@@ -0,0 +1,170 @@
+INCLUDE_DIRECTORIES( ${BULLET_PHYSICS_SOURCE_DIR}/src )
+
+
+
+SET(BulletDynamics_SRCS
+ Character/btKinematicCharacterController.cpp
+ ConstraintSolver/btConeTwistConstraint.cpp
+ ConstraintSolver/btContactConstraint.cpp
+ ConstraintSolver/btFixedConstraint.cpp
+ ConstraintSolver/btGearConstraint.cpp
+ ConstraintSolver/btGeneric6DofConstraint.cpp
+ ConstraintSolver/btGeneric6DofSpringConstraint.cpp
+ ConstraintSolver/btGeneric6DofSpring2Constraint.cpp
+ ConstraintSolver/btHinge2Constraint.cpp
+ ConstraintSolver/btHingeConstraint.cpp
+ ConstraintSolver/btPoint2PointConstraint.cpp
+ ConstraintSolver/btSequentialImpulseConstraintSolver.cpp
+ ConstraintSolver/btNNCGConstraintSolver.cpp
+ ConstraintSolver/btSliderConstraint.cpp
+ ConstraintSolver/btSolve2LinearConstraint.cpp
+ ConstraintSolver/btTypedConstraint.cpp
+ ConstraintSolver/btUniversalConstraint.cpp
+ Dynamics/btDiscreteDynamicsWorld.cpp
+ Dynamics/btDiscreteDynamicsWorldMt.cpp
+ Dynamics/btSimulationIslandManagerMt.cpp
+ Dynamics/btRigidBody.cpp
+ Dynamics/btSimpleDynamicsWorld.cpp
+# Dynamics/Bullet-C-API.cpp
+ Vehicle/btRaycastVehicle.cpp
+ Vehicle/btWheelInfo.cpp
+ Featherstone/btMultiBody.cpp
+ Featherstone/btMultiBodyConstraintSolver.cpp
+ Featherstone/btMultiBodyDynamicsWorld.cpp
+ Featherstone/btMultiBodyJointLimitConstraint.cpp
+ Featherstone/btMultiBodyConstraint.cpp
+ Featherstone/btMultiBodyPoint2Point.cpp
+ Featherstone/btMultiBodyFixedConstraint.cpp
+ Featherstone/btMultiBodySliderConstraint.cpp
+ Featherstone/btMultiBodyJointMotor.cpp
+ Featherstone/btMultiBodyGearConstraint.cpp
+ MLCPSolvers/btDantzigLCP.cpp
+ MLCPSolvers/btMLCPSolver.cpp
+ MLCPSolvers/btLemkeAlgorithm.cpp
+)
+
+SET(Root_HDRS
+ ../btBulletDynamicsCommon.h
+ ../btBulletCollisionCommon.h
+)
+SET(ConstraintSolver_HDRS
+ ConstraintSolver/btConeTwistConstraint.h
+ ConstraintSolver/btConstraintSolver.h
+ ConstraintSolver/btContactConstraint.h
+ ConstraintSolver/btContactSolverInfo.h
+ ConstraintSolver/btFixedConstraint.h
+ ConstraintSolver/btGearConstraint.h
+ ConstraintSolver/btGeneric6DofConstraint.h
+ ConstraintSolver/btGeneric6DofSpringConstraint.h
+ ConstraintSolver/btGeneric6DofSpring2Constraint.h
+ ConstraintSolver/btHinge2Constraint.h
+ ConstraintSolver/btHingeConstraint.h
+ ConstraintSolver/btJacobianEntry.h
+ ConstraintSolver/btPoint2PointConstraint.h
+ ConstraintSolver/btSequentialImpulseConstraintSolver.h
+ ConstraintSolver/btNNCGConstraintSolver.h
+ ConstraintSolver/btSliderConstraint.h
+ ConstraintSolver/btSolve2LinearConstraint.h
+ ConstraintSolver/btSolverBody.h
+ ConstraintSolver/btSolverConstraint.h
+ ConstraintSolver/btTypedConstraint.h
+ ConstraintSolver/btUniversalConstraint.h
+)
+SET(Dynamics_HDRS
+ Dynamics/btActionInterface.h
+ Dynamics/btDiscreteDynamicsWorld.h
+ Dynamics/btDiscreteDynamicsWorldMt.h
+ Dynamics/btSimulationIslandManagerMt.h
+ Dynamics/btDynamicsWorld.h
+ Dynamics/btSimpleDynamicsWorld.h
+ Dynamics/btRigidBody.h
+)
+SET(Vehicle_HDRS
+ Vehicle/btRaycastVehicle.h
+ Vehicle/btVehicleRaycaster.h
+ Vehicle/btWheelInfo.h
+)
+
+SET(Featherstone_HDRS
+ Featherstone/btMultiBody.h
+ Featherstone/btMultiBodyConstraintSolver.h
+ Featherstone/btMultiBodyDynamicsWorld.h
+ Featherstone/btMultiBodyLink.h
+ Featherstone/btMultiBodyLinkCollider.h
+ Featherstone/btMultiBodySolverConstraint.h
+ Featherstone/btMultiBodyConstraint.h
+ Featherstone/btMultiBodyJointLimitConstraint.h
+ Featherstone/btMultiBodyConstraint.h
+ Featherstone/btMultiBodyPoint2Point.h
+ Featherstone/btMultiBodyFixedConstraint.h
+ Featherstone/btMultiBodySliderConstraint.h
+ Featherstone/btMultiBodyJointMotor.h
+ Featherstone/btMultiBodyGearConstraint.h
+)
+
+SET(MLCPSolvers_HDRS
+ MLCPSolvers/btDantzigLCP.h
+ MLCPSolvers/btDantzigSolver.h
+ MLCPSolvers/btMLCPSolver.h
+ MLCPSolvers/btMLCPSolverInterface.h
+ MLCPSolvers/btPATHSolver.h
+ MLCPSolvers/btSolveProjectedGaussSeidel.h
+ MLCPSolvers/btLemkeSolver.h
+ MLCPSolvers/btLemkeAlgorithm.h
+)
+
+SET(Character_HDRS
+ Character/btCharacterControllerInterface.h
+ Character/btKinematicCharacterController.h
+)
+
+
+
+SET(BulletDynamics_HDRS
+ ${Root_HDRS}
+ ${ConstraintSolver_HDRS}
+ ${Dynamics_HDRS}
+ ${Vehicle_HDRS}
+ ${Character_HDRS}
+ ${Featherstone_HDRS}
+ ${MLCPSolvers_HDRS}
+)
+
+
+ADD_LIBRARY(BulletDynamics ${BulletDynamics_SRCS} ${BulletDynamics_HDRS})
+SET_TARGET_PROPERTIES(BulletDynamics PROPERTIES VERSION ${BULLET_VERSION})
+SET_TARGET_PROPERTIES(BulletDynamics PROPERTIES SOVERSION ${BULLET_VERSION})
+IF (BUILD_SHARED_LIBS)
+ TARGET_LINK_LIBRARIES(BulletDynamics BulletCollision LinearMath)
+ENDIF (BUILD_SHARED_LIBS)
+
+IF (INSTALL_LIBS)
+ IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
+ IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
+ IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+ INSTALL(TARGETS BulletDynamics DESTINATION .)
+ ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+ INSTALL(TARGETS BulletDynamics RUNTIME DESTINATION bin
+ LIBRARY DESTINATION lib${LIB_SUFFIX}
+ ARCHIVE DESTINATION lib${LIB_SUFFIX})
+ INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.h" PATTERN
+".svn" EXCLUDE PATTERN "CMakeFiles" EXCLUDE)
+ INSTALL(FILES ../btBulletDynamicsCommon.h
+DESTINATION ${INCLUDE_INSTALL_DIR}/BulletDynamics)
+ ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+ ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
+
+ IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+ SET_TARGET_PROPERTIES(BulletDynamics PROPERTIES FRAMEWORK true)
+ SET_TARGET_PROPERTIES(BulletDynamics PROPERTIES PUBLIC_HEADER "${Root_HDRS}")
+ # Have to list out sub-directories manually:
+ SET_PROPERTY(SOURCE ${ConstraintSolver_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/ConstraintSolver)
+ SET_PROPERTY(SOURCE ${Dynamics_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/Dynamics)
+ SET_PROPERTY(SOURCE ${Vehicle_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/Vehicle)
+ SET_PROPERTY(SOURCE ${Character_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/Character)
+ SET_PROPERTY(SOURCE ${Featherstone_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/Featherstone)
+ SET_PROPERTY(SOURCE ${MLCPSolvers_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/MLCPSolvers)
+ ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+ ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
+ENDIF (INSTALL_LIBS)
diff --git a/thirdparty/bullet/src/BulletDynamics/Character/btCharacterControllerInterface.h b/thirdparty/bullet/src/BulletDynamics/Character/btCharacterControllerInterface.h
new file mode 100644
index 0000000000..abe24b5ca6
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/Character/btCharacterControllerInterface.h
@@ -0,0 +1,47 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com
+
+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_CHARACTER_CONTROLLER_INTERFACE_H
+#define BT_CHARACTER_CONTROLLER_INTERFACE_H
+
+#include "LinearMath/btVector3.h"
+#include "BulletDynamics/Dynamics/btActionInterface.h"
+
+class btCollisionShape;
+class btRigidBody;
+class btCollisionWorld;
+
+class btCharacterControllerInterface : public btActionInterface
+{
+public:
+ btCharacterControllerInterface () {};
+ virtual ~btCharacterControllerInterface () {};
+
+ virtual void setWalkDirection(const btVector3& walkDirection) = 0;
+ virtual void setVelocityForTimeInterval(const btVector3& velocity, btScalar timeInterval) = 0;
+ virtual void reset ( btCollisionWorld* collisionWorld ) = 0;
+ virtual void warp (const btVector3& origin) = 0;
+
+ virtual void preStep ( btCollisionWorld* collisionWorld) = 0;
+ virtual void playerStep (btCollisionWorld* collisionWorld, btScalar dt) = 0;
+ virtual bool canJump () const = 0;
+ virtual void jump(const btVector3& dir = btVector3(0, 0, 0)) = 0;
+
+ virtual bool onGround () const = 0;
+ virtual void setUpInterpolate (bool value) = 0;
+};
+
+#endif //BT_CHARACTER_CONTROLLER_INTERFACE_H
+
diff --git a/thirdparty/bullet/src/BulletDynamics/Character/btKinematicCharacterController.cpp b/thirdparty/bullet/src/BulletDynamics/Character/btKinematicCharacterController.cpp
new file mode 100644
index 0000000000..cb1aa71a14
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/Character/btKinematicCharacterController.cpp
@@ -0,0 +1,1000 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com
+
+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 "LinearMath/btIDebugDraw.h"
+#include "BulletCollision/CollisionDispatch/btGhostObject.h"
+#include "BulletCollision/CollisionShapes/btMultiSphereShape.h"
+#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
+#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btCollisionWorld.h"
+#include "LinearMath/btDefaultMotionState.h"
+#include "btKinematicCharacterController.h"
+
+
+// static helper method
+static btVector3
+getNormalizedVector(const btVector3& v)
+{
+ btVector3 n(0, 0, 0);
+
+ if (v.length() > SIMD_EPSILON) {
+ n = v.normalized();
+ }
+ return n;
+}
+
+
+///@todo Interact with dynamic objects,
+///Ride kinematicly animated platforms properly
+///More realistic (or maybe just a config option) falling
+/// -> Should integrate falling velocity manually and use that in stepDown()
+///Support jumping
+///Support ducking
+class btKinematicClosestNotMeRayResultCallback : public btCollisionWorld::ClosestRayResultCallback
+{
+public:
+ btKinematicClosestNotMeRayResultCallback (btCollisionObject* me) : btCollisionWorld::ClosestRayResultCallback(btVector3(0.0, 0.0, 0.0), btVector3(0.0, 0.0, 0.0))
+ {
+ m_me = me;
+ }
+
+ virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult,bool normalInWorldSpace)
+ {
+ if (rayResult.m_collisionObject == m_me)
+ return 1.0;
+
+ return ClosestRayResultCallback::addSingleResult (rayResult, normalInWorldSpace);
+ }
+protected:
+ btCollisionObject* m_me;
+};
+
+class btKinematicClosestNotMeConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback
+{
+public:
+ btKinematicClosestNotMeConvexResultCallback (btCollisionObject* me, const btVector3& up, btScalar minSlopeDot)
+ : btCollisionWorld::ClosestConvexResultCallback(btVector3(0.0, 0.0, 0.0), btVector3(0.0, 0.0, 0.0))
+ , m_me(me)
+ , m_up(up)
+ , m_minSlopeDot(minSlopeDot)
+ {
+ }
+
+ virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& convexResult,bool normalInWorldSpace)
+ {
+ if (convexResult.m_hitCollisionObject == m_me)
+ return btScalar(1.0);
+
+ if (!convexResult.m_hitCollisionObject->hasContactResponse())
+ return btScalar(1.0);
+
+ btVector3 hitNormalWorld;
+ if (normalInWorldSpace)
+ {
+ hitNormalWorld = convexResult.m_hitNormalLocal;
+ } else
+ {
+ ///need to transform normal into worldspace
+ hitNormalWorld = convexResult.m_hitCollisionObject->getWorldTransform().getBasis()*convexResult.m_hitNormalLocal;
+ }
+
+ btScalar dotUp = m_up.dot(hitNormalWorld);
+ if (dotUp < m_minSlopeDot) {
+ return btScalar(1.0);
+ }
+
+ return ClosestConvexResultCallback::addSingleResult (convexResult, normalInWorldSpace);
+ }
+protected:
+ btCollisionObject* m_me;
+ const btVector3 m_up;
+ btScalar m_minSlopeDot;
+};
+
+/*
+ * Returns the reflection direction of a ray going 'direction' hitting a surface with normal 'normal'
+ *
+ * from: http://www-cs-students.stanford.edu/~adityagp/final/node3.html
+ */
+btVector3 btKinematicCharacterController::computeReflectionDirection (const btVector3& direction, const btVector3& normal)
+{
+ return direction - (btScalar(2.0) * direction.dot(normal)) * normal;
+}
+
+/*
+ * Returns the portion of 'direction' that is parallel to 'normal'
+ */
+btVector3 btKinematicCharacterController::parallelComponent (const btVector3& direction, const btVector3& normal)
+{
+ btScalar magnitude = direction.dot(normal);
+ return normal * magnitude;
+}
+
+/*
+ * Returns the portion of 'direction' that is perpindicular to 'normal'
+ */
+btVector3 btKinematicCharacterController::perpindicularComponent (const btVector3& direction, const btVector3& normal)
+{
+ return direction - parallelComponent(direction, normal);
+}
+
+btKinematicCharacterController::btKinematicCharacterController (btPairCachingGhostObject* ghostObject,btConvexShape* convexShape,btScalar stepHeight, const btVector3& up)
+{
+ m_ghostObject = ghostObject;
+ m_up.setValue(0.0f, 0.0f, 1.0f);
+ m_jumpAxis.setValue(0.0f, 0.0f, 1.0f);
+ m_addedMargin = 0.02;
+ m_walkDirection.setValue(0.0,0.0,0.0);
+ m_AngVel.setValue(0.0, 0.0, 0.0);
+ m_useGhostObjectSweepTest = true;
+ m_turnAngle = btScalar(0.0);
+ m_convexShape=convexShape;
+ m_useWalkDirection = true; // use walk direction by default, legacy behavior
+ m_velocityTimeInterval = 0.0;
+ m_verticalVelocity = 0.0;
+ m_verticalOffset = 0.0;
+ m_gravity = 9.8 * 3.0 ; // 3G acceleration.
+ m_fallSpeed = 55.0; // Terminal velocity of a sky diver in m/s.
+ m_jumpSpeed = 10.0; // ?
+ m_SetjumpSpeed = m_jumpSpeed;
+ m_wasOnGround = false;
+ m_wasJumping = false;
+ m_interpolateUp = true;
+ m_currentStepOffset = 0.0;
+ m_maxPenetrationDepth = 0.2;
+ full_drop = false;
+ bounce_fix = false;
+ m_linearDamping = btScalar(0.0);
+ m_angularDamping = btScalar(0.0);
+
+ setUp(up);
+ setStepHeight(stepHeight);
+ setMaxSlope(btRadians(45.0));
+}
+
+btKinematicCharacterController::~btKinematicCharacterController ()
+{
+}
+
+btPairCachingGhostObject* btKinematicCharacterController::getGhostObject()
+{
+ return m_ghostObject;
+}
+
+bool btKinematicCharacterController::recoverFromPenetration ( btCollisionWorld* collisionWorld)
+{
+ // Here we must refresh the overlapping paircache as the penetrating movement itself or the
+ // previous recovery iteration might have used setWorldTransform and pushed us into an object
+ // that is not in the previous cache contents from the last timestep, as will happen if we
+ // are pushed into a new AABB overlap. Unhandled this means the next convex sweep gets stuck.
+ //
+ // Do this by calling the broadphase's setAabb with the moved AABB, this will update the broadphase
+ // paircache and the ghostobject's internal paircache at the same time. /BW
+
+ btVector3 minAabb, maxAabb;
+ m_convexShape->getAabb(m_ghostObject->getWorldTransform(), minAabb,maxAabb);
+ collisionWorld->getBroadphase()->setAabb(m_ghostObject->getBroadphaseHandle(),
+ minAabb,
+ maxAabb,
+ collisionWorld->getDispatcher());
+
+ bool penetration = false;
+
+ collisionWorld->getDispatcher()->dispatchAllCollisionPairs(m_ghostObject->getOverlappingPairCache(), collisionWorld->getDispatchInfo(), collisionWorld->getDispatcher());
+
+ m_currentPosition = m_ghostObject->getWorldTransform().getOrigin();
+
+// btScalar maxPen = btScalar(0.0);
+ for (int i = 0; i < m_ghostObject->getOverlappingPairCache()->getNumOverlappingPairs(); i++)
+ {
+ m_manifoldArray.resize(0);
+
+ btBroadphasePair* collisionPair = &m_ghostObject->getOverlappingPairCache()->getOverlappingPairArray()[i];
+
+ btCollisionObject* obj0 = static_cast<btCollisionObject*>(collisionPair->m_pProxy0->m_clientObject);
+ btCollisionObject* obj1 = static_cast<btCollisionObject*>(collisionPair->m_pProxy1->m_clientObject);
+
+ if ((obj0 && !obj0->hasContactResponse()) || (obj1 && !obj1->hasContactResponse()))
+ continue;
+
+ if (!needsCollision(obj0, obj1))
+ continue;
+
+ if (collisionPair->m_algorithm)
+ collisionPair->m_algorithm->getAllContactManifolds(m_manifoldArray);
+
+
+ for (int j=0;j<m_manifoldArray.size();j++)
+ {
+ btPersistentManifold* manifold = m_manifoldArray[j];
+ btScalar directionSign = manifold->getBody0() == m_ghostObject ? btScalar(-1.0) : btScalar(1.0);
+ for (int p=0;p<manifold->getNumContacts();p++)
+ {
+ const btManifoldPoint&pt = manifold->getContactPoint(p);
+
+ btScalar dist = pt.getDistance();
+
+ if (dist < -m_maxPenetrationDepth)
+ {
+ // TODO: cause problems on slopes, not sure if it is needed
+ //if (dist < maxPen)
+ //{
+ // maxPen = dist;
+ // m_touchingNormal = pt.m_normalWorldOnB * directionSign;//??
+
+ //}
+ m_currentPosition += pt.m_normalWorldOnB * directionSign * dist * btScalar(0.2);
+ penetration = true;
+ } else {
+ //printf("touching %f\n", dist);
+ }
+ }
+
+ //manifold->clearManifold();
+ }
+ }
+ btTransform newTrans = m_ghostObject->getWorldTransform();
+ newTrans.setOrigin(m_currentPosition);
+ m_ghostObject->setWorldTransform(newTrans);
+// printf("m_touchingNormal = %f,%f,%f\n",m_touchingNormal[0],m_touchingNormal[1],m_touchingNormal[2]);
+ return penetration;
+}
+
+void btKinematicCharacterController::stepUp ( btCollisionWorld* world)
+{
+ btScalar stepHeight = 0.0f;
+ if (m_verticalVelocity < 0.0)
+ stepHeight = m_stepHeight;
+
+ // phase 1: up
+ btTransform start, end;
+
+ start.setIdentity ();
+ end.setIdentity ();
+
+ /* FIXME: Handle penetration properly */
+ start.setOrigin(m_currentPosition);
+
+ m_targetPosition = m_currentPosition + m_up * (stepHeight) + m_jumpAxis * ((m_verticalOffset > 0.f ? m_verticalOffset : 0.f));
+ m_currentPosition = m_targetPosition;
+
+ end.setOrigin (m_targetPosition);
+
+ start.setRotation(m_currentOrientation);
+ end.setRotation(m_targetOrientation);
+
+ btKinematicClosestNotMeConvexResultCallback callback(m_ghostObject, -m_up, m_maxSlopeCosine);
+ callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup;
+ callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask;
+
+ if (m_useGhostObjectSweepTest)
+ {
+ m_ghostObject->convexSweepTest (m_convexShape, start, end, callback, world->getDispatchInfo().m_allowedCcdPenetration);
+ }
+ else
+ {
+ world->convexSweepTest(m_convexShape, start, end, callback, world->getDispatchInfo().m_allowedCcdPenetration);
+ }
+
+ if (callback.hasHit() && m_ghostObject->hasContactResponse() && needsCollision(m_ghostObject, callback.m_hitCollisionObject))
+ {
+ // Only modify the position if the hit was a slope and not a wall or ceiling.
+ if (callback.m_hitNormalWorld.dot(m_up) > 0.0)
+ {
+ // we moved up only a fraction of the step height
+ m_currentStepOffset = stepHeight * callback.m_closestHitFraction;
+ if (m_interpolateUp == true)
+ m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, callback.m_closestHitFraction);
+ else
+ m_currentPosition = m_targetPosition;
+ }
+
+ btTransform& xform = m_ghostObject->getWorldTransform();
+ xform.setOrigin(m_currentPosition);
+ m_ghostObject->setWorldTransform(xform);
+
+ // fix penetration if we hit a ceiling for example
+ int numPenetrationLoops = 0;
+ m_touchingContact = false;
+ while (recoverFromPenetration(world))
+ {
+ numPenetrationLoops++;
+ m_touchingContact = true;
+ if (numPenetrationLoops > 4)
+ {
+ //printf("character could not recover from penetration = %d\n", numPenetrationLoops);
+ break;
+ }
+ }
+ m_targetPosition = m_ghostObject->getWorldTransform().getOrigin();
+ m_currentPosition = m_targetPosition;
+
+ if (m_verticalOffset > 0)
+ {
+ m_verticalOffset = 0.0;
+ m_verticalVelocity = 0.0;
+ m_currentStepOffset = m_stepHeight;
+ }
+ } else {
+ m_currentStepOffset = stepHeight;
+ m_currentPosition = m_targetPosition;
+ }
+}
+
+bool btKinematicCharacterController::needsCollision(const btCollisionObject* body0, const btCollisionObject* body1)
+{
+ bool collides = (body0->getBroadphaseHandle()->m_collisionFilterGroup & body1->getBroadphaseHandle()->m_collisionFilterMask) != 0;
+ collides = collides && (body1->getBroadphaseHandle()->m_collisionFilterGroup & body0->getBroadphaseHandle()->m_collisionFilterMask);
+ return collides;
+}
+
+void btKinematicCharacterController::updateTargetPositionBasedOnCollision (const btVector3& hitNormal, btScalar tangentMag, btScalar normalMag)
+{
+ btVector3 movementDirection = m_targetPosition - m_currentPosition;
+ btScalar movementLength = movementDirection.length();
+ if (movementLength>SIMD_EPSILON)
+ {
+ movementDirection.normalize();
+
+ btVector3 reflectDir = computeReflectionDirection (movementDirection, hitNormal);
+ reflectDir.normalize();
+
+ btVector3 parallelDir, perpindicularDir;
+
+ parallelDir = parallelComponent (reflectDir, hitNormal);
+ perpindicularDir = perpindicularComponent (reflectDir, hitNormal);
+
+ m_targetPosition = m_currentPosition;
+ if (0)//tangentMag != 0.0)
+ {
+ btVector3 parComponent = parallelDir * btScalar (tangentMag*movementLength);
+// printf("parComponent=%f,%f,%f\n",parComponent[0],parComponent[1],parComponent[2]);
+ m_targetPosition += parComponent;
+ }
+
+ if (normalMag != 0.0)
+ {
+ btVector3 perpComponent = perpindicularDir * btScalar (normalMag*movementLength);
+// printf("perpComponent=%f,%f,%f\n",perpComponent[0],perpComponent[1],perpComponent[2]);
+ m_targetPosition += perpComponent;
+ }
+ } else
+ {
+// printf("movementLength don't normalize a zero vector\n");
+ }
+}
+
+void btKinematicCharacterController::stepForwardAndStrafe ( btCollisionWorld* collisionWorld, const btVector3& walkMove)
+{
+ // printf("m_normalizedDirection=%f,%f,%f\n",
+ // m_normalizedDirection[0],m_normalizedDirection[1],m_normalizedDirection[2]);
+ // phase 2: forward and strafe
+ btTransform start, end;
+
+ m_targetPosition = m_currentPosition + walkMove;
+
+ start.setIdentity ();
+ end.setIdentity ();
+
+ btScalar fraction = 1.0;
+ btScalar distance2 = (m_currentPosition-m_targetPosition).length2();
+// printf("distance2=%f\n",distance2);
+
+ int maxIter = 10;
+
+ while (fraction > btScalar(0.01) && maxIter-- > 0)
+ {
+ start.setOrigin (m_currentPosition);
+ end.setOrigin (m_targetPosition);
+ btVector3 sweepDirNegative(m_currentPosition - m_targetPosition);
+
+ start.setRotation(m_currentOrientation);
+ end.setRotation(m_targetOrientation);
+
+ btKinematicClosestNotMeConvexResultCallback callback (m_ghostObject, sweepDirNegative, btScalar(0.0));
+ callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup;
+ callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask;
+
+
+ btScalar margin = m_convexShape->getMargin();
+ m_convexShape->setMargin(margin + m_addedMargin);
+
+ if (!(start == end))
+ {
+ if (m_useGhostObjectSweepTest)
+ {
+ m_ghostObject->convexSweepTest(m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
+ }
+ else
+ {
+ collisionWorld->convexSweepTest(m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
+ }
+ }
+ m_convexShape->setMargin(margin);
+
+
+ fraction -= callback.m_closestHitFraction;
+
+ if (callback.hasHit() && m_ghostObject->hasContactResponse() && needsCollision(m_ghostObject, callback.m_hitCollisionObject))
+ {
+ // we moved only a fraction
+ //btScalar hitDistance;
+ //hitDistance = (callback.m_hitPointWorld - m_currentPosition).length();
+
+// m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, callback.m_closestHitFraction);
+
+ updateTargetPositionBasedOnCollision (callback.m_hitNormalWorld);
+ btVector3 currentDir = m_targetPosition - m_currentPosition;
+ distance2 = currentDir.length2();
+ if (distance2 > SIMD_EPSILON)
+ {
+ currentDir.normalize();
+ /* See Quake2: "If velocity is against original velocity, stop ead to avoid tiny oscilations in sloping corners." */
+ if (currentDir.dot(m_normalizedDirection) <= btScalar(0.0))
+ {
+ break;
+ }
+ } else
+ {
+// printf("currentDir: don't normalize a zero vector\n");
+ break;
+ }
+
+ }
+ else
+ {
+ m_currentPosition = m_targetPosition;
+ }
+ }
+}
+
+void btKinematicCharacterController::stepDown ( btCollisionWorld* collisionWorld, btScalar dt)
+{
+ btTransform start, end, end_double;
+ bool runonce = false;
+
+ // phase 3: down
+ /*btScalar additionalDownStep = (m_wasOnGround && !onGround()) ? m_stepHeight : 0.0;
+ btVector3 step_drop = m_up * (m_currentStepOffset + additionalDownStep);
+ btScalar downVelocity = (additionalDownStep == 0.0 && m_verticalVelocity<0.0?-m_verticalVelocity:0.0) * dt;
+ btVector3 gravity_drop = m_up * downVelocity;
+ m_targetPosition -= (step_drop + gravity_drop);*/
+
+ btVector3 orig_position = m_targetPosition;
+
+ btScalar downVelocity = (m_verticalVelocity<0.f?-m_verticalVelocity:0.f) * dt;
+
+ if (m_verticalVelocity > 0.0)
+ return;
+
+ if(downVelocity > 0.0 && downVelocity > m_fallSpeed
+ && (m_wasOnGround || !m_wasJumping))
+ downVelocity = m_fallSpeed;
+
+ btVector3 step_drop = m_up * (m_currentStepOffset + downVelocity);
+ m_targetPosition -= step_drop;
+
+ btKinematicClosestNotMeConvexResultCallback callback(m_ghostObject, m_up, m_maxSlopeCosine);
+ callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup;
+ callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask;
+
+ btKinematicClosestNotMeConvexResultCallback callback2(m_ghostObject, m_up, m_maxSlopeCosine);
+ callback2.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup;
+ callback2.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask;
+
+ while (1)
+ {
+ start.setIdentity ();
+ end.setIdentity ();
+
+ end_double.setIdentity ();
+
+ start.setOrigin (m_currentPosition);
+ end.setOrigin (m_targetPosition);
+
+ start.setRotation(m_currentOrientation);
+ end.setRotation(m_targetOrientation);
+
+ //set double test for 2x the step drop, to check for a large drop vs small drop
+ end_double.setOrigin (m_targetPosition - step_drop);
+
+ if (m_useGhostObjectSweepTest)
+ {
+ m_ghostObject->convexSweepTest (m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
+
+ if (!callback.hasHit() && m_ghostObject->hasContactResponse())
+ {
+ //test a double fall height, to see if the character should interpolate it's fall (full) or not (partial)
+ m_ghostObject->convexSweepTest (m_convexShape, start, end_double, callback2, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
+ }
+ } else
+ {
+ collisionWorld->convexSweepTest (m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
+
+ if (!callback.hasHit() && m_ghostObject->hasContactResponse())
+ {
+ //test a double fall height, to see if the character should interpolate it's fall (large) or not (small)
+ collisionWorld->convexSweepTest (m_convexShape, start, end_double, callback2, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
+ }
+ }
+
+ btScalar downVelocity2 = (m_verticalVelocity<0.f?-m_verticalVelocity:0.f) * dt;
+ bool has_hit;
+ if (bounce_fix == true)
+ has_hit = (callback.hasHit() || callback2.hasHit()) && m_ghostObject->hasContactResponse() && needsCollision(m_ghostObject, callback.m_hitCollisionObject);
+ else
+ has_hit = callback2.hasHit() && m_ghostObject->hasContactResponse() && needsCollision(m_ghostObject, callback2.m_hitCollisionObject);
+
+ btScalar stepHeight = 0.0f;
+ if (m_verticalVelocity < 0.0)
+ stepHeight = m_stepHeight;
+
+ if (downVelocity2 > 0.0 && downVelocity2 < stepHeight && has_hit == true && runonce == false
+ && (m_wasOnGround || !m_wasJumping))
+ {
+ //redo the velocity calculation when falling a small amount, for fast stairs motion
+ //for larger falls, use the smoother/slower interpolated movement by not touching the target position
+
+ m_targetPosition = orig_position;
+ downVelocity = stepHeight;
+
+ step_drop = m_up * (m_currentStepOffset + downVelocity);
+ m_targetPosition -= step_drop;
+ runonce = true;
+ continue; //re-run previous tests
+ }
+ break;
+ }
+
+ if ((m_ghostObject->hasContactResponse() && (callback.hasHit() && needsCollision(m_ghostObject, callback.m_hitCollisionObject))) || runonce == true)
+ {
+ // we dropped a fraction of the height -> hit floor
+ btScalar fraction = (m_currentPosition.getY() - callback.m_hitPointWorld.getY()) / 2;
+
+ //printf("hitpoint: %g - pos %g\n", callback.m_hitPointWorld.getY(), m_currentPosition.getY());
+
+ if (bounce_fix == true)
+ {
+ if (full_drop == true)
+ m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, callback.m_closestHitFraction);
+ else
+ //due to errors in the closestHitFraction variable when used with large polygons, calculate the hit fraction manually
+ m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, fraction);
+ }
+ else
+ m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, callback.m_closestHitFraction);
+
+ full_drop = false;
+
+ m_verticalVelocity = 0.0;
+ m_verticalOffset = 0.0;
+ m_wasJumping = false;
+ } else {
+ // we dropped the full height
+
+ full_drop = true;
+
+ if (bounce_fix == true)
+ {
+ downVelocity = (m_verticalVelocity<0.f?-m_verticalVelocity:0.f) * dt;
+ if (downVelocity > m_fallSpeed && (m_wasOnGround || !m_wasJumping))
+ {
+ m_targetPosition += step_drop; //undo previous target change
+ downVelocity = m_fallSpeed;
+ step_drop = m_up * (m_currentStepOffset + downVelocity);
+ m_targetPosition -= step_drop;
+ }
+ }
+ //printf("full drop - %g, %g\n", m_currentPosition.getY(), m_targetPosition.getY());
+
+ m_currentPosition = m_targetPosition;
+ }
+}
+
+
+
+void btKinematicCharacterController::setWalkDirection
+(
+const btVector3& walkDirection
+)
+{
+ m_useWalkDirection = true;
+ m_walkDirection = walkDirection;
+ m_normalizedDirection = getNormalizedVector(m_walkDirection);
+}
+
+
+
+void btKinematicCharacterController::setVelocityForTimeInterval
+(
+const btVector3& velocity,
+btScalar timeInterval
+)
+{
+// printf("setVelocity!\n");
+// printf(" interval: %f\n", timeInterval);
+// printf(" velocity: (%f, %f, %f)\n",
+// velocity.x(), velocity.y(), velocity.z());
+
+ m_useWalkDirection = false;
+ m_walkDirection = velocity;
+ m_normalizedDirection = getNormalizedVector(m_walkDirection);
+ m_velocityTimeInterval += timeInterval;
+}
+
+void btKinematicCharacterController::setAngularVelocity(const btVector3& velocity)
+{
+ m_AngVel = velocity;
+}
+
+const btVector3& btKinematicCharacterController::getAngularVelocity() const
+{
+ return m_AngVel;
+}
+
+void btKinematicCharacterController::setLinearVelocity(const btVector3& velocity)
+{
+ m_walkDirection = velocity;
+
+ // HACK: if we are moving in the direction of the up, treat it as a jump :(
+ if (m_walkDirection.length2() > 0)
+ {
+ btVector3 w = velocity.normalized();
+ btScalar c = w.dot(m_up);
+ if (c != 0)
+ {
+ //there is a component in walkdirection for vertical velocity
+ btVector3 upComponent = m_up * (btSin(SIMD_HALF_PI - btAcos(c)) * m_walkDirection.length());
+ m_walkDirection -= upComponent;
+ m_verticalVelocity = (c < 0.0f ? -1 : 1) * upComponent.length();
+
+ if (c > 0.0f)
+ {
+ m_wasJumping = true;
+ m_jumpPosition = m_ghostObject->getWorldTransform().getOrigin();
+ }
+ }
+ }
+ else
+ m_verticalVelocity = 0.0f;
+}
+
+btVector3 btKinematicCharacterController::getLinearVelocity() const
+{
+ return m_walkDirection + (m_verticalVelocity * m_up);
+}
+
+void btKinematicCharacterController::reset ( btCollisionWorld* collisionWorld )
+{
+ m_verticalVelocity = 0.0;
+ m_verticalOffset = 0.0;
+ m_wasOnGround = false;
+ m_wasJumping = false;
+ m_walkDirection.setValue(0,0,0);
+ m_velocityTimeInterval = 0.0;
+
+ //clear pair cache
+ btHashedOverlappingPairCache *cache = m_ghostObject->getOverlappingPairCache();
+ while (cache->getOverlappingPairArray().size() > 0)
+ {
+ cache->removeOverlappingPair(cache->getOverlappingPairArray()[0].m_pProxy0, cache->getOverlappingPairArray()[0].m_pProxy1, collisionWorld->getDispatcher());
+ }
+}
+
+void btKinematicCharacterController::warp (const btVector3& origin)
+{
+ btTransform xform;
+ xform.setIdentity();
+ xform.setOrigin (origin);
+ m_ghostObject->setWorldTransform (xform);
+}
+
+
+void btKinematicCharacterController::preStep ( btCollisionWorld* collisionWorld)
+{
+ m_currentPosition = m_ghostObject->getWorldTransform().getOrigin();
+ m_targetPosition = m_currentPosition;
+
+ m_currentOrientation = m_ghostObject->getWorldTransform().getRotation();
+ m_targetOrientation = m_currentOrientation;
+// printf("m_targetPosition=%f,%f,%f\n",m_targetPosition[0],m_targetPosition[1],m_targetPosition[2]);
+}
+
+void btKinematicCharacterController::playerStep ( btCollisionWorld* collisionWorld, btScalar dt)
+{
+// printf("playerStep(): ");
+// printf(" dt = %f", dt);
+
+ if (m_AngVel.length2() > 0.0f)
+ {
+ m_AngVel *= btPow(btScalar(1) - m_angularDamping, dt);
+ }
+
+ // integrate for angular velocity
+ if (m_AngVel.length2() > 0.0f)
+ {
+ btTransform xform;
+ xform = m_ghostObject->getWorldTransform();
+
+ btQuaternion rot(m_AngVel.normalized(), m_AngVel.length() * dt);
+
+ btQuaternion orn = rot * xform.getRotation();
+
+ xform.setRotation(orn);
+ m_ghostObject->setWorldTransform(xform);
+
+ m_currentPosition = m_ghostObject->getWorldTransform().getOrigin();
+ m_targetPosition = m_currentPosition;
+ m_currentOrientation = m_ghostObject->getWorldTransform().getRotation();
+ m_targetOrientation = m_currentOrientation;
+ }
+
+ // quick check...
+ if (!m_useWalkDirection && (m_velocityTimeInterval <= 0.0)) {
+// printf("\n");
+ return; // no motion
+ }
+
+ m_wasOnGround = onGround();
+
+ //btVector3 lvel = m_walkDirection;
+ //btScalar c = 0.0f;
+
+ if (m_walkDirection.length2() > 0)
+ {
+ // apply damping
+ m_walkDirection *= btPow(btScalar(1) - m_linearDamping, dt);
+ }
+
+ m_verticalVelocity *= btPow(btScalar(1) - m_linearDamping, dt);
+
+ // Update fall velocity.
+ m_verticalVelocity -= m_gravity * dt;
+ if (m_verticalVelocity > 0.0 && m_verticalVelocity > m_jumpSpeed)
+ {
+ m_verticalVelocity = m_jumpSpeed;
+ }
+ if (m_verticalVelocity < 0.0 && btFabs(m_verticalVelocity) > btFabs(m_fallSpeed))
+ {
+ m_verticalVelocity = -btFabs(m_fallSpeed);
+ }
+ m_verticalOffset = m_verticalVelocity * dt;
+
+ btTransform xform;
+ xform = m_ghostObject->getWorldTransform();
+
+// printf("walkDirection(%f,%f,%f)\n",walkDirection[0],walkDirection[1],walkDirection[2]);
+// printf("walkSpeed=%f\n",walkSpeed);
+
+ stepUp(collisionWorld);
+ //todo: Experimenting with behavior of controller when it hits a ceiling..
+ //bool hitUp = stepUp (collisionWorld);
+ //if (hitUp)
+ //{
+ // m_verticalVelocity -= m_gravity * dt;
+ // if (m_verticalVelocity > 0.0 && m_verticalVelocity > m_jumpSpeed)
+ // {
+ // m_verticalVelocity = m_jumpSpeed;
+ // }
+ // if (m_verticalVelocity < 0.0 && btFabs(m_verticalVelocity) > btFabs(m_fallSpeed))
+ // {
+ // m_verticalVelocity = -btFabs(m_fallSpeed);
+ // }
+ // m_verticalOffset = m_verticalVelocity * dt;
+
+ // xform = m_ghostObject->getWorldTransform();
+ //}
+
+ if (m_useWalkDirection) {
+ stepForwardAndStrafe (collisionWorld, m_walkDirection);
+ } else {
+ //printf(" time: %f", m_velocityTimeInterval);
+ // still have some time left for moving!
+ btScalar dtMoving =
+ (dt < m_velocityTimeInterval) ? dt : m_velocityTimeInterval;
+ m_velocityTimeInterval -= dt;
+
+ // how far will we move while we are moving?
+ btVector3 move = m_walkDirection * dtMoving;
+
+ //printf(" dtMoving: %f", dtMoving);
+
+ // okay, step
+ stepForwardAndStrafe(collisionWorld, move);
+ }
+ stepDown (collisionWorld, dt);
+
+ //todo: Experimenting with max jump height
+ //if (m_wasJumping)
+ //{
+ // btScalar ds = m_currentPosition[m_upAxis] - m_jumpPosition[m_upAxis];
+ // if (ds > m_maxJumpHeight)
+ // {
+ // // substract the overshoot
+ // m_currentPosition[m_upAxis] -= ds - m_maxJumpHeight;
+
+ // // max height was reached, so potential energy is at max
+ // // and kinematic energy is 0, thus velocity is 0.
+ // if (m_verticalVelocity > 0.0)
+ // m_verticalVelocity = 0.0;
+ // }
+ //}
+ // printf("\n");
+
+ xform.setOrigin (m_currentPosition);
+ m_ghostObject->setWorldTransform (xform);
+
+ int numPenetrationLoops = 0;
+ m_touchingContact = false;
+ while (recoverFromPenetration(collisionWorld))
+ {
+ numPenetrationLoops++;
+ m_touchingContact = true;
+ if (numPenetrationLoops > 4)
+ {
+ //printf("character could not recover from penetration = %d\n", numPenetrationLoops);
+ break;
+ }
+ }
+}
+
+void btKinematicCharacterController::setFallSpeed (btScalar fallSpeed)
+{
+ m_fallSpeed = fallSpeed;
+}
+
+void btKinematicCharacterController::setJumpSpeed (btScalar jumpSpeed)
+{
+ m_jumpSpeed = jumpSpeed;
+ m_SetjumpSpeed = m_jumpSpeed;
+}
+
+void btKinematicCharacterController::setMaxJumpHeight (btScalar maxJumpHeight)
+{
+ m_maxJumpHeight = maxJumpHeight;
+}
+
+bool btKinematicCharacterController::canJump () const
+{
+ return onGround();
+}
+
+void btKinematicCharacterController::jump(const btVector3& v)
+{
+ m_jumpSpeed = v.length2() == 0 ? m_SetjumpSpeed : v.length();
+ m_verticalVelocity = m_jumpSpeed;
+ m_wasJumping = true;
+
+ m_jumpAxis = v.length2() == 0 ? m_up : v.normalized();
+
+ m_jumpPosition = m_ghostObject->getWorldTransform().getOrigin();
+
+#if 0
+ currently no jumping.
+ btTransform xform;
+ m_rigidBody->getMotionState()->getWorldTransform (xform);
+ btVector3 up = xform.getBasis()[1];
+ up.normalize ();
+ btScalar magnitude = (btScalar(1.0)/m_rigidBody->getInvMass()) * btScalar(8.0);
+ m_rigidBody->applyCentralImpulse (up * magnitude);
+#endif
+}
+
+void btKinematicCharacterController::setGravity(const btVector3& gravity)
+{
+ if (gravity.length2() > 0) setUpVector(-gravity);
+
+ m_gravity = gravity.length();
+}
+
+btVector3 btKinematicCharacterController::getGravity() const
+{
+ return -m_gravity * m_up;
+}
+
+void btKinematicCharacterController::setMaxSlope(btScalar slopeRadians)
+{
+ m_maxSlopeRadians = slopeRadians;
+ m_maxSlopeCosine = btCos(slopeRadians);
+}
+
+btScalar btKinematicCharacterController::getMaxSlope() const
+{
+ return m_maxSlopeRadians;
+}
+
+void btKinematicCharacterController::setMaxPenetrationDepth(btScalar d)
+{
+ m_maxPenetrationDepth = d;
+}
+
+btScalar btKinematicCharacterController::getMaxPenetrationDepth() const
+{
+ return m_maxPenetrationDepth;
+}
+
+bool btKinematicCharacterController::onGround () const
+{
+ return (fabs(m_verticalVelocity) < SIMD_EPSILON) && (fabs(m_verticalOffset) < SIMD_EPSILON);
+}
+
+void btKinematicCharacterController::setStepHeight(btScalar h)
+{
+ m_stepHeight = h;
+}
+
+btVector3* btKinematicCharacterController::getUpAxisDirections()
+{
+ static btVector3 sUpAxisDirection[3] = { btVector3(1.0f, 0.0f, 0.0f), btVector3(0.0f, 1.0f, 0.0f), btVector3(0.0f, 0.0f, 1.0f) };
+
+ return sUpAxisDirection;
+}
+
+void btKinematicCharacterController::debugDraw(btIDebugDraw* debugDrawer)
+{
+}
+
+void btKinematicCharacterController::setUpInterpolate(bool value)
+{
+ m_interpolateUp = value;
+}
+
+void btKinematicCharacterController::setUp(const btVector3& up)
+{
+ if (up.length2() > 0 && m_gravity > 0.0f)
+ {
+ setGravity(-m_gravity * up.normalized());
+ return;
+ }
+
+ setUpVector(up);
+}
+
+void btKinematicCharacterController::setUpVector(const btVector3& up)
+{
+ if (m_up == up)
+ return;
+
+ btVector3 u = m_up;
+
+ if (up.length2() > 0)
+ m_up = up.normalized();
+ else
+ m_up = btVector3(0.0, 0.0, 0.0);
+
+ if (!m_ghostObject) return;
+ btQuaternion rot = getRotation(m_up, u);
+
+ //set orientation with new up
+ btTransform xform;
+ xform = m_ghostObject->getWorldTransform();
+ btQuaternion orn = rot.inverse() * xform.getRotation();
+ xform.setRotation(orn);
+ m_ghostObject->setWorldTransform(xform);
+}
+
+btQuaternion btKinematicCharacterController::getRotation(btVector3& v0, btVector3& v1) const
+{
+ if (v0.length2() == 0.0f || v1.length2() == 0.0f)
+ {
+ btQuaternion q;
+ return q;
+ }
+
+ return shortestArcQuatNormalize2(v0, v1);
+}
+
diff --git a/thirdparty/bullet/src/BulletDynamics/Character/btKinematicCharacterController.h b/thirdparty/bullet/src/BulletDynamics/Character/btKinematicCharacterController.h
new file mode 100644
index 0000000000..00c59c0248
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/Character/btKinematicCharacterController.h
@@ -0,0 +1,204 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com
+
+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_KINEMATIC_CHARACTER_CONTROLLER_H
+#define BT_KINEMATIC_CHARACTER_CONTROLLER_H
+
+#include "LinearMath/btVector3.h"
+
+#include "btCharacterControllerInterface.h"
+
+#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
+
+
+class btCollisionShape;
+class btConvexShape;
+class btRigidBody;
+class btCollisionWorld;
+class btCollisionDispatcher;
+class btPairCachingGhostObject;
+
+///btKinematicCharacterController is an object that supports a sliding motion in a world.
+///It uses a ghost object and convex sweep test to test for upcoming collisions. This is combined with discrete collision detection to recover from penetrations.
+///Interaction between btKinematicCharacterController and dynamic rigid bodies needs to be explicity implemented by the user.
+ATTRIBUTE_ALIGNED16(class) btKinematicCharacterController : public btCharacterControllerInterface
+{
+protected:
+
+ btScalar m_halfHeight;
+
+ btPairCachingGhostObject* m_ghostObject;
+ btConvexShape* m_convexShape;//is also in m_ghostObject, but it needs to be convex, so we store it here to avoid upcast
+
+ btScalar m_maxPenetrationDepth;
+ btScalar m_verticalVelocity;
+ btScalar m_verticalOffset;
+ btScalar m_fallSpeed;
+ btScalar m_jumpSpeed;
+ btScalar m_SetjumpSpeed;
+ btScalar m_maxJumpHeight;
+ btScalar m_maxSlopeRadians; // Slope angle that is set (used for returning the exact value)
+ btScalar m_maxSlopeCosine; // Cosine equivalent of m_maxSlopeRadians (calculated once when set, for optimization)
+ btScalar m_gravity;
+
+ btScalar m_turnAngle;
+
+ btScalar m_stepHeight;
+
+ btScalar m_addedMargin;//@todo: remove this and fix the code
+
+ ///this is the desired walk direction, set by the user
+ btVector3 m_walkDirection;
+ btVector3 m_normalizedDirection;
+ btVector3 m_AngVel;
+
+ btVector3 m_jumpPosition;
+
+ //some internal variables
+ btVector3 m_currentPosition;
+ btScalar m_currentStepOffset;
+ btVector3 m_targetPosition;
+
+ btQuaternion m_currentOrientation;
+ btQuaternion m_targetOrientation;
+
+ ///keep track of the contact manifolds
+ btManifoldArray m_manifoldArray;
+
+ bool m_touchingContact;
+ btVector3 m_touchingNormal;
+
+ btScalar m_linearDamping;
+ btScalar m_angularDamping;
+
+ bool m_wasOnGround;
+ bool m_wasJumping;
+ bool m_useGhostObjectSweepTest;
+ bool m_useWalkDirection;
+ btScalar m_velocityTimeInterval;
+ btVector3 m_up;
+ btVector3 m_jumpAxis;
+
+ static btVector3* getUpAxisDirections();
+ bool m_interpolateUp;
+ bool full_drop;
+ bool bounce_fix;
+
+ btVector3 computeReflectionDirection (const btVector3& direction, const btVector3& normal);
+ btVector3 parallelComponent (const btVector3& direction, const btVector3& normal);
+ btVector3 perpindicularComponent (const btVector3& direction, const btVector3& normal);
+
+ bool recoverFromPenetration ( btCollisionWorld* collisionWorld);
+ void stepUp (btCollisionWorld* collisionWorld);
+ void updateTargetPositionBasedOnCollision (const btVector3& hit_normal, btScalar tangentMag = btScalar(0.0), btScalar normalMag = btScalar(1.0));
+ void stepForwardAndStrafe (btCollisionWorld* collisionWorld, const btVector3& walkMove);
+ void stepDown (btCollisionWorld* collisionWorld, btScalar dt);
+
+ virtual bool needsCollision(const btCollisionObject* body0, const btCollisionObject* body1);
+
+ void setUpVector(const btVector3& up);
+
+ btQuaternion getRotation(btVector3& v0, btVector3& v1) const;
+
+public:
+
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ btKinematicCharacterController (btPairCachingGhostObject* ghostObject,btConvexShape* convexShape,btScalar stepHeight, const btVector3& up = btVector3(1.0,0.0,0.0));
+ ~btKinematicCharacterController ();
+
+
+ ///btActionInterface interface
+ virtual void updateAction( btCollisionWorld* collisionWorld,btScalar deltaTime)
+ {
+ preStep ( collisionWorld);
+ playerStep (collisionWorld, deltaTime);
+ }
+
+ ///btActionInterface interface
+ void debugDraw(btIDebugDraw* debugDrawer);
+
+ void setUp(const btVector3& up);
+
+ const btVector3& getUp() { return m_up; }
+
+ /// This should probably be called setPositionIncrementPerSimulatorStep.
+ /// This is neither a direction nor a velocity, but the amount to
+ /// increment the position each simulation iteration, regardless
+ /// of dt.
+ /// This call will reset any velocity set by setVelocityForTimeInterval().
+ virtual void setWalkDirection(const btVector3& walkDirection);
+
+ /// Caller provides a velocity with which the character should move for
+ /// the given time period. After the time period, velocity is reset
+ /// to zero.
+ /// This call will reset any walk direction set by setWalkDirection().
+ /// Negative time intervals will result in no motion.
+ virtual void setVelocityForTimeInterval(const btVector3& velocity,
+ btScalar timeInterval);
+
+ virtual void setAngularVelocity(const btVector3& velocity);
+ virtual const btVector3& getAngularVelocity() const;
+
+ virtual void setLinearVelocity(const btVector3& velocity);
+ virtual btVector3 getLinearVelocity() const;
+
+ void setLinearDamping(btScalar d) { m_linearDamping = btClamped(d, (btScalar)btScalar(0.0), (btScalar)btScalar(1.0)); }
+ btScalar getLinearDamping() const { return m_linearDamping; }
+ void setAngularDamping(btScalar d) { m_angularDamping = btClamped(d, (btScalar)btScalar(0.0), (btScalar)btScalar(1.0)); }
+ btScalar getAngularDamping() const { return m_angularDamping; }
+
+ void reset ( btCollisionWorld* collisionWorld );
+ void warp (const btVector3& origin);
+
+ void preStep ( btCollisionWorld* collisionWorld);
+ void playerStep ( btCollisionWorld* collisionWorld, btScalar dt);
+
+ void setStepHeight(btScalar h);
+ btScalar getStepHeight() const { return m_stepHeight; }
+ void setFallSpeed (btScalar fallSpeed);
+ btScalar getFallSpeed() const { return m_fallSpeed; }
+ void setJumpSpeed (btScalar jumpSpeed);
+ btScalar getJumpSpeed() const { return m_jumpSpeed; }
+ void setMaxJumpHeight (btScalar maxJumpHeight);
+ bool canJump () const;
+
+ void jump(const btVector3& v = btVector3(0, 0, 0));
+
+ void applyImpulse(const btVector3& v) { jump(v); }
+
+ void setGravity(const btVector3& gravity);
+ btVector3 getGravity() const;
+
+ /// The max slope determines the maximum angle that the controller can walk up.
+ /// The slope angle is measured in radians.
+ void setMaxSlope(btScalar slopeRadians);
+ btScalar getMaxSlope() const;
+
+ void setMaxPenetrationDepth(btScalar d);
+ btScalar getMaxPenetrationDepth() const;
+
+ btPairCachingGhostObject* getGhostObject();
+ void setUseGhostSweepTest(bool useGhostObjectSweepTest)
+ {
+ m_useGhostObjectSweepTest = useGhostObjectSweepTest;
+ }
+
+ bool onGround () const;
+ void setUpInterpolate (bool value);
+};
+
+#endif // BT_KINEMATIC_CHARACTER_CONTROLLER_H
diff --git a/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp
new file mode 100644
index 0000000000..0572256f74
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp
@@ -0,0 +1,1143 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+btConeTwistConstraint is Copyright (c) 2007 Starbreeze Studios
+
+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.
+
+Written by: Marcus Hennix
+*/
+
+
+#include "btConeTwistConstraint.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "LinearMath/btTransformUtil.h"
+#include "LinearMath/btMinMax.h"
+#include <new>
+
+
+
+//#define CONETWIST_USE_OBSOLETE_SOLVER true
+#define CONETWIST_USE_OBSOLETE_SOLVER false
+#define CONETWIST_DEF_FIX_THRESH btScalar(.05f)
+
+
+SIMD_FORCE_INLINE btScalar computeAngularImpulseDenominator(const btVector3& axis, const btMatrix3x3& invInertiaWorld)
+{
+ btVector3 vec = axis * invInertiaWorld;
+ return axis.dot(vec);
+}
+
+
+
+
+btConeTwistConstraint::btConeTwistConstraint(btRigidBody& rbA,btRigidBody& rbB,
+ const btTransform& rbAFrame,const btTransform& rbBFrame)
+ :btTypedConstraint(CONETWIST_CONSTRAINT_TYPE, rbA,rbB),m_rbAFrame(rbAFrame),m_rbBFrame(rbBFrame),
+ m_angularOnly(false),
+ m_useSolveConstraintObsolete(CONETWIST_USE_OBSOLETE_SOLVER)
+{
+ init();
+}
+
+btConeTwistConstraint::btConeTwistConstraint(btRigidBody& rbA,const btTransform& rbAFrame)
+ :btTypedConstraint(CONETWIST_CONSTRAINT_TYPE,rbA),m_rbAFrame(rbAFrame),
+ m_angularOnly(false),
+ m_useSolveConstraintObsolete(CONETWIST_USE_OBSOLETE_SOLVER)
+{
+ m_rbBFrame = m_rbAFrame;
+ m_rbBFrame.setOrigin(btVector3(0., 0., 0.));
+ init();
+}
+
+
+void btConeTwistConstraint::init()
+{
+ m_angularOnly = false;
+ m_solveTwistLimit = false;
+ m_solveSwingLimit = false;
+ m_bMotorEnabled = false;
+ m_maxMotorImpulse = btScalar(-1);
+
+ setLimit(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
+ m_damping = btScalar(0.01);
+ m_fixThresh = CONETWIST_DEF_FIX_THRESH;
+ m_flags = 0;
+ m_linCFM = btScalar(0.f);
+ m_linERP = btScalar(0.7f);
+ m_angCFM = btScalar(0.f);
+}
+
+
+void btConeTwistConstraint::getInfo1 (btConstraintInfo1* info)
+{
+ if (m_useSolveConstraintObsolete)
+ {
+ info->m_numConstraintRows = 0;
+ info->nub = 0;
+ }
+ else
+ {
+ info->m_numConstraintRows = 3;
+ info->nub = 3;
+ calcAngleInfo2(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform(),m_rbA.getInvInertiaTensorWorld(),m_rbB.getInvInertiaTensorWorld());
+ if(m_solveSwingLimit)
+ {
+ info->m_numConstraintRows++;
+ info->nub--;
+ if((m_swingSpan1 < m_fixThresh) && (m_swingSpan2 < m_fixThresh))
+ {
+ info->m_numConstraintRows++;
+ info->nub--;
+ }
+ }
+ if(m_solveTwistLimit)
+ {
+ info->m_numConstraintRows++;
+ info->nub--;
+ }
+ }
+}
+
+void btConeTwistConstraint::getInfo1NonVirtual (btConstraintInfo1* info)
+{
+ //always reserve 6 rows: object transform is not available on SPU
+ info->m_numConstraintRows = 6;
+ info->nub = 0;
+
+}
+
+
+void btConeTwistConstraint::getInfo2 (btConstraintInfo2* info)
+{
+ getInfo2NonVirtual(info,m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform(),m_rbA.getInvInertiaTensorWorld(),m_rbB.getInvInertiaTensorWorld());
+}
+
+void btConeTwistConstraint::getInfo2NonVirtual (btConstraintInfo2* info,const btTransform& transA,const btTransform& transB,const btMatrix3x3& invInertiaWorldA,const btMatrix3x3& invInertiaWorldB)
+{
+ calcAngleInfo2(transA,transB,invInertiaWorldA,invInertiaWorldB);
+
+ btAssert(!m_useSolveConstraintObsolete);
+ // set jacobian
+ info->m_J1linearAxis[0] = 1;
+ info->m_J1linearAxis[info->rowskip+1] = 1;
+ info->m_J1linearAxis[2*info->rowskip+2] = 1;
+ btVector3 a1 = transA.getBasis() * m_rbAFrame.getOrigin();
+ {
+ btVector3* angular0 = (btVector3*)(info->m_J1angularAxis);
+ btVector3* angular1 = (btVector3*)(info->m_J1angularAxis+info->rowskip);
+ btVector3* angular2 = (btVector3*)(info->m_J1angularAxis+2*info->rowskip);
+ btVector3 a1neg = -a1;
+ a1neg.getSkewSymmetricMatrix(angular0,angular1,angular2);
+ }
+ info->m_J2linearAxis[0] = -1;
+ info->m_J2linearAxis[info->rowskip+1] = -1;
+ info->m_J2linearAxis[2*info->rowskip+2] = -1;
+ btVector3 a2 = transB.getBasis() * m_rbBFrame.getOrigin();
+ {
+ btVector3* angular0 = (btVector3*)(info->m_J2angularAxis);
+ btVector3* angular1 = (btVector3*)(info->m_J2angularAxis+info->rowskip);
+ btVector3* angular2 = (btVector3*)(info->m_J2angularAxis+2*info->rowskip);
+ a2.getSkewSymmetricMatrix(angular0,angular1,angular2);
+ }
+ // set right hand side
+ btScalar linERP = (m_flags & BT_CONETWIST_FLAGS_LIN_ERP) ? m_linERP : info->erp;
+ btScalar k = info->fps * linERP;
+ int j;
+ for (j=0; j<3; j++)
+ {
+ info->m_constraintError[j*info->rowskip] = k * (a2[j] + transB.getOrigin()[j] - a1[j] - transA.getOrigin()[j]);
+ info->m_lowerLimit[j*info->rowskip] = -SIMD_INFINITY;
+ info->m_upperLimit[j*info->rowskip] = SIMD_INFINITY;
+ if(m_flags & BT_CONETWIST_FLAGS_LIN_CFM)
+ {
+ info->cfm[j*info->rowskip] = m_linCFM;
+ }
+ }
+ int row = 3;
+ int srow = row * info->rowskip;
+ btVector3 ax1;
+ // angular limits
+ if(m_solveSwingLimit)
+ {
+ btScalar *J1 = info->m_J1angularAxis;
+ btScalar *J2 = info->m_J2angularAxis;
+ if((m_swingSpan1 < m_fixThresh) && (m_swingSpan2 < m_fixThresh))
+ {
+ btTransform trA = transA*m_rbAFrame;
+ btVector3 p = trA.getBasis().getColumn(1);
+ btVector3 q = trA.getBasis().getColumn(2);
+ int srow1 = srow + info->rowskip;
+ J1[srow+0] = p[0];
+ J1[srow+1] = p[1];
+ J1[srow+2] = p[2];
+ J1[srow1+0] = q[0];
+ J1[srow1+1] = q[1];
+ J1[srow1+2] = q[2];
+ J2[srow+0] = -p[0];
+ J2[srow+1] = -p[1];
+ J2[srow+2] = -p[2];
+ J2[srow1+0] = -q[0];
+ J2[srow1+1] = -q[1];
+ J2[srow1+2] = -q[2];
+ btScalar fact = info->fps * m_relaxationFactor;
+ info->m_constraintError[srow] = fact * m_swingAxis.dot(p);
+ info->m_constraintError[srow1] = fact * m_swingAxis.dot(q);
+ info->m_lowerLimit[srow] = -SIMD_INFINITY;
+ info->m_upperLimit[srow] = SIMD_INFINITY;
+ info->m_lowerLimit[srow1] = -SIMD_INFINITY;
+ info->m_upperLimit[srow1] = SIMD_INFINITY;
+ srow = srow1 + info->rowskip;
+ }
+ else
+ {
+ ax1 = m_swingAxis * m_relaxationFactor * m_relaxationFactor;
+ J1[srow+0] = ax1[0];
+ J1[srow+1] = ax1[1];
+ J1[srow+2] = ax1[2];
+ J2[srow+0] = -ax1[0];
+ J2[srow+1] = -ax1[1];
+ J2[srow+2] = -ax1[2];
+ btScalar k = info->fps * m_biasFactor;
+
+ info->m_constraintError[srow] = k * m_swingCorrection;
+ if(m_flags & BT_CONETWIST_FLAGS_ANG_CFM)
+ {
+ info->cfm[srow] = m_angCFM;
+ }
+ // m_swingCorrection is always positive or 0
+ info->m_lowerLimit[srow] = 0;
+ info->m_upperLimit[srow] = (m_bMotorEnabled && m_maxMotorImpulse >= 0.0f) ? m_maxMotorImpulse : SIMD_INFINITY;
+ srow += info->rowskip;
+ }
+ }
+ if(m_solveTwistLimit)
+ {
+ ax1 = m_twistAxis * m_relaxationFactor * m_relaxationFactor;
+ btScalar *J1 = info->m_J1angularAxis;
+ btScalar *J2 = info->m_J2angularAxis;
+ J1[srow+0] = ax1[0];
+ J1[srow+1] = ax1[1];
+ J1[srow+2] = ax1[2];
+ J2[srow+0] = -ax1[0];
+ J2[srow+1] = -ax1[1];
+ J2[srow+2] = -ax1[2];
+ btScalar k = info->fps * m_biasFactor;
+ info->m_constraintError[srow] = k * m_twistCorrection;
+ if(m_flags & BT_CONETWIST_FLAGS_ANG_CFM)
+ {
+ info->cfm[srow] = m_angCFM;
+ }
+ if(m_twistSpan > 0.0f)
+ {
+
+ if(m_twistCorrection > 0.0f)
+ {
+ info->m_lowerLimit[srow] = 0;
+ info->m_upperLimit[srow] = SIMD_INFINITY;
+ }
+ else
+ {
+ info->m_lowerLimit[srow] = -SIMD_INFINITY;
+ info->m_upperLimit[srow] = 0;
+ }
+ }
+ else
+ {
+ info->m_lowerLimit[srow] = -SIMD_INFINITY;
+ info->m_upperLimit[srow] = SIMD_INFINITY;
+ }
+ srow += info->rowskip;
+ }
+}
+
+
+
+void btConeTwistConstraint::buildJacobian()
+{
+ if (m_useSolveConstraintObsolete)
+ {
+ m_appliedImpulse = btScalar(0.);
+ m_accTwistLimitImpulse = btScalar(0.);
+ m_accSwingLimitImpulse = btScalar(0.);
+ m_accMotorImpulse = btVector3(0.,0.,0.);
+
+ if (!m_angularOnly)
+ {
+ btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_rbAFrame.getOrigin();
+ btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_rbBFrame.getOrigin();
+ btVector3 relPos = pivotBInW - pivotAInW;
+
+ btVector3 normal[3];
+ if (relPos.length2() > SIMD_EPSILON)
+ {
+ normal[0] = relPos.normalized();
+ }
+ else
+ {
+ normal[0].setValue(btScalar(1.0),0,0);
+ }
+
+ btPlaneSpace1(normal[0], normal[1], normal[2]);
+
+ for (int i=0;i<3;i++)
+ {
+ new (&m_jac[i]) btJacobianEntry(
+ m_rbA.getCenterOfMassTransform().getBasis().transpose(),
+ m_rbB.getCenterOfMassTransform().getBasis().transpose(),
+ pivotAInW - m_rbA.getCenterOfMassPosition(),
+ pivotBInW - m_rbB.getCenterOfMassPosition(),
+ normal[i],
+ m_rbA.getInvInertiaDiagLocal(),
+ m_rbA.getInvMass(),
+ m_rbB.getInvInertiaDiagLocal(),
+ m_rbB.getInvMass());
+ }
+ }
+
+ calcAngleInfo2(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform(),m_rbA.getInvInertiaTensorWorld(),m_rbB.getInvInertiaTensorWorld());
+ }
+}
+
+
+
+void btConeTwistConstraint::solveConstraintObsolete(btSolverBody& bodyA,btSolverBody& bodyB,btScalar timeStep)
+{
+ #ifndef __SPU__
+ if (m_useSolveConstraintObsolete)
+ {
+ btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_rbAFrame.getOrigin();
+ btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_rbBFrame.getOrigin();
+
+ btScalar tau = btScalar(0.3);
+
+ //linear part
+ if (!m_angularOnly)
+ {
+ btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition();
+ btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition();
+
+ btVector3 vel1;
+ bodyA.internalGetVelocityInLocalPointObsolete(rel_pos1,vel1);
+ btVector3 vel2;
+ bodyB.internalGetVelocityInLocalPointObsolete(rel_pos2,vel2);
+ btVector3 vel = vel1 - vel2;
+
+ for (int i=0;i<3;i++)
+ {
+ const btVector3& normal = m_jac[i].m_linearJointAxis;
+ btScalar jacDiagABInv = btScalar(1.) / m_jac[i].getDiagonal();
+
+ btScalar rel_vel;
+ rel_vel = normal.dot(vel);
+ //positional error (zeroth order error)
+ btScalar depth = -(pivotAInW - pivotBInW).dot(normal); //this is the error projected on the normal
+ btScalar impulse = depth*tau/timeStep * jacDiagABInv - rel_vel * jacDiagABInv;
+ m_appliedImpulse += impulse;
+
+ btVector3 ftorqueAxis1 = rel_pos1.cross(normal);
+ btVector3 ftorqueAxis2 = rel_pos2.cross(normal);
+ bodyA.internalApplyImpulse(normal*m_rbA.getInvMass(), m_rbA.getInvInertiaTensorWorld()*ftorqueAxis1,impulse);
+ bodyB.internalApplyImpulse(normal*m_rbB.getInvMass(), m_rbB.getInvInertiaTensorWorld()*ftorqueAxis2,-impulse);
+
+ }
+ }
+
+ // apply motor
+ if (m_bMotorEnabled)
+ {
+ // compute current and predicted transforms
+ btTransform trACur = m_rbA.getCenterOfMassTransform();
+ btTransform trBCur = m_rbB.getCenterOfMassTransform();
+ btVector3 omegaA; bodyA.internalGetAngularVelocity(omegaA);
+ btVector3 omegaB; bodyB.internalGetAngularVelocity(omegaB);
+ btTransform trAPred; trAPred.setIdentity();
+ btVector3 zerovec(0,0,0);
+ btTransformUtil::integrateTransform(
+ trACur, zerovec, omegaA, timeStep, trAPred);
+ btTransform trBPred; trBPred.setIdentity();
+ btTransformUtil::integrateTransform(
+ trBCur, zerovec, omegaB, timeStep, trBPred);
+
+ // compute desired transforms in world
+ btTransform trPose(m_qTarget);
+ btTransform trABDes = m_rbBFrame * trPose * m_rbAFrame.inverse();
+ btTransform trADes = trBPred * trABDes;
+ btTransform trBDes = trAPred * trABDes.inverse();
+
+ // compute desired omegas in world
+ btVector3 omegaADes, omegaBDes;
+
+ btTransformUtil::calculateVelocity(trACur, trADes, timeStep, zerovec, omegaADes);
+ btTransformUtil::calculateVelocity(trBCur, trBDes, timeStep, zerovec, omegaBDes);
+
+ // compute delta omegas
+ btVector3 dOmegaA = omegaADes - omegaA;
+ btVector3 dOmegaB = omegaBDes - omegaB;
+
+ // compute weighted avg axis of dOmega (weighting based on inertias)
+ btVector3 axisA, axisB;
+ btScalar kAxisAInv = 0, kAxisBInv = 0;
+
+ if (dOmegaA.length2() > SIMD_EPSILON)
+ {
+ axisA = dOmegaA.normalized();
+ kAxisAInv = getRigidBodyA().computeAngularImpulseDenominator(axisA);
+ }
+
+ if (dOmegaB.length2() > SIMD_EPSILON)
+ {
+ axisB = dOmegaB.normalized();
+ kAxisBInv = getRigidBodyB().computeAngularImpulseDenominator(axisB);
+ }
+
+ btVector3 avgAxis = kAxisAInv * axisA + kAxisBInv * axisB;
+
+ static bool bDoTorque = true;
+ if (bDoTorque && avgAxis.length2() > SIMD_EPSILON)
+ {
+ avgAxis.normalize();
+ kAxisAInv = getRigidBodyA().computeAngularImpulseDenominator(avgAxis);
+ kAxisBInv = getRigidBodyB().computeAngularImpulseDenominator(avgAxis);
+ btScalar kInvCombined = kAxisAInv + kAxisBInv;
+
+ btVector3 impulse = (kAxisAInv * dOmegaA - kAxisBInv * dOmegaB) /
+ (kInvCombined * kInvCombined);
+
+ if (m_maxMotorImpulse >= 0)
+ {
+ btScalar fMaxImpulse = m_maxMotorImpulse;
+ if (m_bNormalizedMotorStrength)
+ fMaxImpulse = fMaxImpulse/kAxisAInv;
+
+ btVector3 newUnclampedAccImpulse = m_accMotorImpulse + impulse;
+ btScalar newUnclampedMag = newUnclampedAccImpulse.length();
+ if (newUnclampedMag > fMaxImpulse)
+ {
+ newUnclampedAccImpulse.normalize();
+ newUnclampedAccImpulse *= fMaxImpulse;
+ impulse = newUnclampedAccImpulse - m_accMotorImpulse;
+ }
+ m_accMotorImpulse += impulse;
+ }
+
+ btScalar impulseMag = impulse.length();
+ btVector3 impulseAxis = impulse / impulseMag;
+
+ bodyA.internalApplyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*impulseAxis, impulseMag);
+ bodyB.internalApplyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*impulseAxis, -impulseMag);
+
+ }
+ }
+ else if (m_damping > SIMD_EPSILON) // no motor: do a little damping
+ {
+ btVector3 angVelA; bodyA.internalGetAngularVelocity(angVelA);
+ btVector3 angVelB; bodyB.internalGetAngularVelocity(angVelB);
+ btVector3 relVel = angVelB - angVelA;
+ if (relVel.length2() > SIMD_EPSILON)
+ {
+ btVector3 relVelAxis = relVel.normalized();
+ btScalar m_kDamping = btScalar(1.) /
+ (getRigidBodyA().computeAngularImpulseDenominator(relVelAxis) +
+ getRigidBodyB().computeAngularImpulseDenominator(relVelAxis));
+ btVector3 impulse = m_damping * m_kDamping * relVel;
+
+ btScalar impulseMag = impulse.length();
+ btVector3 impulseAxis = impulse / impulseMag;
+ bodyA.internalApplyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*impulseAxis, impulseMag);
+ bodyB.internalApplyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*impulseAxis, -impulseMag);
+ }
+ }
+
+ // joint limits
+ {
+ ///solve angular part
+ btVector3 angVelA;
+ bodyA.internalGetAngularVelocity(angVelA);
+ btVector3 angVelB;
+ bodyB.internalGetAngularVelocity(angVelB);
+
+ // solve swing limit
+ if (m_solveSwingLimit)
+ {
+ btScalar amplitude = m_swingLimitRatio * m_swingCorrection*m_biasFactor/timeStep;
+ btScalar relSwingVel = (angVelB - angVelA).dot(m_swingAxis);
+ if (relSwingVel > 0)
+ amplitude += m_swingLimitRatio * relSwingVel * m_relaxationFactor;
+ btScalar impulseMag = amplitude * m_kSwing;
+
+ // Clamp the accumulated impulse
+ btScalar temp = m_accSwingLimitImpulse;
+ m_accSwingLimitImpulse = btMax(m_accSwingLimitImpulse + impulseMag, btScalar(0.0) );
+ impulseMag = m_accSwingLimitImpulse - temp;
+
+ btVector3 impulse = m_swingAxis * impulseMag;
+
+ // don't let cone response affect twist
+ // (this can happen since body A's twist doesn't match body B's AND we use an elliptical cone limit)
+ {
+ btVector3 impulseTwistCouple = impulse.dot(m_twistAxisA) * m_twistAxisA;
+ btVector3 impulseNoTwistCouple = impulse - impulseTwistCouple;
+ impulse = impulseNoTwistCouple;
+ }
+
+ impulseMag = impulse.length();
+ btVector3 noTwistSwingAxis = impulse / impulseMag;
+
+ bodyA.internalApplyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*noTwistSwingAxis, impulseMag);
+ bodyB.internalApplyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*noTwistSwingAxis, -impulseMag);
+ }
+
+
+ // solve twist limit
+ if (m_solveTwistLimit)
+ {
+ btScalar amplitude = m_twistLimitRatio * m_twistCorrection*m_biasFactor/timeStep;
+ btScalar relTwistVel = (angVelB - angVelA).dot( m_twistAxis );
+ if (relTwistVel > 0) // only damp when moving towards limit (m_twistAxis flipping is important)
+ amplitude += m_twistLimitRatio * relTwistVel * m_relaxationFactor;
+ btScalar impulseMag = amplitude * m_kTwist;
+
+ // Clamp the accumulated impulse
+ btScalar temp = m_accTwistLimitImpulse;
+ m_accTwistLimitImpulse = btMax(m_accTwistLimitImpulse + impulseMag, btScalar(0.0) );
+ impulseMag = m_accTwistLimitImpulse - temp;
+
+ // btVector3 impulse = m_twistAxis * impulseMag;
+
+ bodyA.internalApplyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*m_twistAxis,impulseMag);
+ bodyB.internalApplyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*m_twistAxis,-impulseMag);
+ }
+ }
+ }
+#else
+btAssert(0);
+#endif //__SPU__
+}
+
+
+
+
+void btConeTwistConstraint::updateRHS(btScalar timeStep)
+{
+ (void)timeStep;
+
+}
+
+
+#ifndef __SPU__
+void btConeTwistConstraint::calcAngleInfo()
+{
+ m_swingCorrection = btScalar(0.);
+ m_twistLimitSign = btScalar(0.);
+ m_solveTwistLimit = false;
+ m_solveSwingLimit = false;
+
+ btVector3 b1Axis1(0,0,0),b1Axis2(0,0,0),b1Axis3(0,0,0);
+ btVector3 b2Axis1(0,0,0),b2Axis2(0,0,0);
+
+ b1Axis1 = getRigidBodyA().getCenterOfMassTransform().getBasis() * this->m_rbAFrame.getBasis().getColumn(0);
+ b2Axis1 = getRigidBodyB().getCenterOfMassTransform().getBasis() * this->m_rbBFrame.getBasis().getColumn(0);
+
+ btScalar swing1=btScalar(0.),swing2 = btScalar(0.);
+
+ btScalar swx=btScalar(0.),swy = btScalar(0.);
+ btScalar thresh = btScalar(10.);
+ btScalar fact;
+
+ // Get Frame into world space
+ if (m_swingSpan1 >= btScalar(0.05f))
+ {
+ b1Axis2 = getRigidBodyA().getCenterOfMassTransform().getBasis() * this->m_rbAFrame.getBasis().getColumn(1);
+ swx = b2Axis1.dot(b1Axis1);
+ swy = b2Axis1.dot(b1Axis2);
+ swing1 = btAtan2Fast(swy, swx);
+ fact = (swy*swy + swx*swx) * thresh * thresh;
+ fact = fact / (fact + btScalar(1.0));
+ swing1 *= fact;
+ }
+
+ if (m_swingSpan2 >= btScalar(0.05f))
+ {
+ b1Axis3 = getRigidBodyA().getCenterOfMassTransform().getBasis() * this->m_rbAFrame.getBasis().getColumn(2);
+ swx = b2Axis1.dot(b1Axis1);
+ swy = b2Axis1.dot(b1Axis3);
+ swing2 = btAtan2Fast(swy, swx);
+ fact = (swy*swy + swx*swx) * thresh * thresh;
+ fact = fact / (fact + btScalar(1.0));
+ swing2 *= fact;
+ }
+
+ btScalar RMaxAngle1Sq = 1.0f / (m_swingSpan1*m_swingSpan1);
+ btScalar RMaxAngle2Sq = 1.0f / (m_swingSpan2*m_swingSpan2);
+ btScalar EllipseAngle = btFabs(swing1*swing1)* RMaxAngle1Sq + btFabs(swing2*swing2) * RMaxAngle2Sq;
+
+ if (EllipseAngle > 1.0f)
+ {
+ m_swingCorrection = EllipseAngle-1.0f;
+ m_solveSwingLimit = true;
+ // Calculate necessary axis & factors
+ m_swingAxis = b2Axis1.cross(b1Axis2* b2Axis1.dot(b1Axis2) + b1Axis3* b2Axis1.dot(b1Axis3));
+ m_swingAxis.normalize();
+ btScalar swingAxisSign = (b2Axis1.dot(b1Axis1) >= 0.0f) ? 1.0f : -1.0f;
+ m_swingAxis *= swingAxisSign;
+ }
+
+ // Twist limits
+ if (m_twistSpan >= btScalar(0.))
+ {
+ btVector3 b2Axis2 = getRigidBodyB().getCenterOfMassTransform().getBasis() * this->m_rbBFrame.getBasis().getColumn(1);
+ btQuaternion rotationArc = shortestArcQuat(b2Axis1,b1Axis1);
+ btVector3 TwistRef = quatRotate(rotationArc,b2Axis2);
+ btScalar twist = btAtan2Fast( TwistRef.dot(b1Axis3), TwistRef.dot(b1Axis2) );
+ m_twistAngle = twist;
+
+// btScalar lockedFreeFactor = (m_twistSpan > btScalar(0.05f)) ? m_limitSoftness : btScalar(0.);
+ btScalar lockedFreeFactor = (m_twistSpan > btScalar(0.05f)) ? btScalar(1.0f) : btScalar(0.);
+ if (twist <= -m_twistSpan*lockedFreeFactor)
+ {
+ m_twistCorrection = -(twist + m_twistSpan);
+ m_solveTwistLimit = true;
+ m_twistAxis = (b2Axis1 + b1Axis1) * 0.5f;
+ m_twistAxis.normalize();
+ m_twistAxis *= -1.0f;
+ }
+ else if (twist > m_twistSpan*lockedFreeFactor)
+ {
+ m_twistCorrection = (twist - m_twistSpan);
+ m_solveTwistLimit = true;
+ m_twistAxis = (b2Axis1 + b1Axis1) * 0.5f;
+ m_twistAxis.normalize();
+ }
+ }
+}
+#endif //__SPU__
+
+static btVector3 vTwist(1,0,0); // twist axis in constraint's space
+
+
+
+void btConeTwistConstraint::calcAngleInfo2(const btTransform& transA, const btTransform& transB, const btMatrix3x3& invInertiaWorldA,const btMatrix3x3& invInertiaWorldB)
+{
+ m_swingCorrection = btScalar(0.);
+ m_twistLimitSign = btScalar(0.);
+ m_solveTwistLimit = false;
+ m_solveSwingLimit = false;
+ // compute rotation of A wrt B (in constraint space)
+ if (m_bMotorEnabled && (!m_useSolveConstraintObsolete))
+ { // it is assumed that setMotorTarget() was alredy called
+ // and motor target m_qTarget is within constraint limits
+ // TODO : split rotation to pure swing and pure twist
+ // compute desired transforms in world
+ btTransform trPose(m_qTarget);
+ btTransform trA = transA * m_rbAFrame;
+ btTransform trB = transB * m_rbBFrame;
+ btTransform trDeltaAB = trB * trPose * trA.inverse();
+ btQuaternion qDeltaAB = trDeltaAB.getRotation();
+ btVector3 swingAxis = btVector3(qDeltaAB.x(), qDeltaAB.y(), qDeltaAB.z());
+ btScalar swingAxisLen2 = swingAxis.length2();
+ if(btFuzzyZero(swingAxisLen2))
+ {
+ return;
+ }
+ m_swingAxis = swingAxis;
+ m_swingAxis.normalize();
+ m_swingCorrection = qDeltaAB.getAngle();
+ if(!btFuzzyZero(m_swingCorrection))
+ {
+ m_solveSwingLimit = true;
+ }
+ return;
+ }
+
+
+ {
+ // compute rotation of A wrt B (in constraint space)
+ btQuaternion qA = transA.getRotation() * m_rbAFrame.getRotation();
+ btQuaternion qB = transB.getRotation() * m_rbBFrame.getRotation();
+ btQuaternion qAB = qB.inverse() * qA;
+ // split rotation into cone and twist
+ // (all this is done from B's perspective. Maybe I should be averaging axes...)
+ btVector3 vConeNoTwist = quatRotate(qAB, vTwist); vConeNoTwist.normalize();
+ btQuaternion qABCone = shortestArcQuat(vTwist, vConeNoTwist); qABCone.normalize();
+ btQuaternion qABTwist = qABCone.inverse() * qAB; qABTwist.normalize();
+
+ if (m_swingSpan1 >= m_fixThresh && m_swingSpan2 >= m_fixThresh)
+ {
+ btScalar swingAngle, swingLimit = 0; btVector3 swingAxis;
+ computeConeLimitInfo(qABCone, swingAngle, swingAxis, swingLimit);
+
+ if (swingAngle > swingLimit * m_limitSoftness)
+ {
+ m_solveSwingLimit = true;
+
+ // compute limit ratio: 0->1, where
+ // 0 == beginning of soft limit
+ // 1 == hard/real limit
+ m_swingLimitRatio = 1.f;
+ if (swingAngle < swingLimit && m_limitSoftness < 1.f - SIMD_EPSILON)
+ {
+ m_swingLimitRatio = (swingAngle - swingLimit * m_limitSoftness)/
+ (swingLimit - swingLimit * m_limitSoftness);
+ }
+
+ // swing correction tries to get back to soft limit
+ m_swingCorrection = swingAngle - (swingLimit * m_limitSoftness);
+
+ // adjustment of swing axis (based on ellipse normal)
+ adjustSwingAxisToUseEllipseNormal(swingAxis);
+
+ // Calculate necessary axis & factors
+ m_swingAxis = quatRotate(qB, -swingAxis);
+
+ m_twistAxisA.setValue(0,0,0);
+
+ m_kSwing = btScalar(1.) /
+ (computeAngularImpulseDenominator(m_swingAxis,invInertiaWorldA) +
+ computeAngularImpulseDenominator(m_swingAxis,invInertiaWorldB));
+ }
+ }
+ else
+ {
+ // you haven't set any limits;
+ // or you're trying to set at least one of the swing limits too small. (if so, do you really want a conetwist constraint?)
+ // anyway, we have either hinge or fixed joint
+ btVector3 ivA = transA.getBasis() * m_rbAFrame.getBasis().getColumn(0);
+ btVector3 jvA = transA.getBasis() * m_rbAFrame.getBasis().getColumn(1);
+ btVector3 kvA = transA.getBasis() * m_rbAFrame.getBasis().getColumn(2);
+ btVector3 ivB = transB.getBasis() * m_rbBFrame.getBasis().getColumn(0);
+ btVector3 target;
+ btScalar x = ivB.dot(ivA);
+ btScalar y = ivB.dot(jvA);
+ btScalar z = ivB.dot(kvA);
+ if((m_swingSpan1 < m_fixThresh) && (m_swingSpan2 < m_fixThresh))
+ { // fixed. We'll need to add one more row to constraint
+ if((!btFuzzyZero(y)) || (!(btFuzzyZero(z))))
+ {
+ m_solveSwingLimit = true;
+ m_swingAxis = -ivB.cross(ivA);
+ }
+ }
+ else
+ {
+ if(m_swingSpan1 < m_fixThresh)
+ { // hinge around Y axis
+// if(!(btFuzzyZero(y)))
+ if((!(btFuzzyZero(x))) || (!(btFuzzyZero(z))))
+ {
+ m_solveSwingLimit = true;
+ if(m_swingSpan2 >= m_fixThresh)
+ {
+ y = btScalar(0.f);
+ btScalar span2 = btAtan2(z, x);
+ if(span2 > m_swingSpan2)
+ {
+ x = btCos(m_swingSpan2);
+ z = btSin(m_swingSpan2);
+ }
+ else if(span2 < -m_swingSpan2)
+ {
+ x = btCos(m_swingSpan2);
+ z = -btSin(m_swingSpan2);
+ }
+ }
+ }
+ }
+ else
+ { // hinge around Z axis
+// if(!btFuzzyZero(z))
+ if((!(btFuzzyZero(x))) || (!(btFuzzyZero(y))))
+ {
+ m_solveSwingLimit = true;
+ if(m_swingSpan1 >= m_fixThresh)
+ {
+ z = btScalar(0.f);
+ btScalar span1 = btAtan2(y, x);
+ if(span1 > m_swingSpan1)
+ {
+ x = btCos(m_swingSpan1);
+ y = btSin(m_swingSpan1);
+ }
+ else if(span1 < -m_swingSpan1)
+ {
+ x = btCos(m_swingSpan1);
+ y = -btSin(m_swingSpan1);
+ }
+ }
+ }
+ }
+ target[0] = x * ivA[0] + y * jvA[0] + z * kvA[0];
+ target[1] = x * ivA[1] + y * jvA[1] + z * kvA[1];
+ target[2] = x * ivA[2] + y * jvA[2] + z * kvA[2];
+ target.normalize();
+ m_swingAxis = -ivB.cross(target);
+ m_swingCorrection = m_swingAxis.length();
+
+ if (!btFuzzyZero(m_swingCorrection))
+ m_swingAxis.normalize();
+ }
+ }
+
+ if (m_twistSpan >= btScalar(0.f))
+ {
+ btVector3 twistAxis;
+ computeTwistLimitInfo(qABTwist, m_twistAngle, twistAxis);
+
+ if (m_twistAngle > m_twistSpan*m_limitSoftness)
+ {
+ m_solveTwistLimit = true;
+
+ m_twistLimitRatio = 1.f;
+ if (m_twistAngle < m_twistSpan && m_limitSoftness < 1.f - SIMD_EPSILON)
+ {
+ m_twistLimitRatio = (m_twistAngle - m_twistSpan * m_limitSoftness)/
+ (m_twistSpan - m_twistSpan * m_limitSoftness);
+ }
+
+ // twist correction tries to get back to soft limit
+ m_twistCorrection = m_twistAngle - (m_twistSpan * m_limitSoftness);
+
+ m_twistAxis = quatRotate(qB, -twistAxis);
+
+ m_kTwist = btScalar(1.) /
+ (computeAngularImpulseDenominator(m_twistAxis,invInertiaWorldA) +
+ computeAngularImpulseDenominator(m_twistAxis,invInertiaWorldB));
+ }
+
+ if (m_solveSwingLimit)
+ m_twistAxisA = quatRotate(qA, -twistAxis);
+ }
+ else
+ {
+ m_twistAngle = btScalar(0.f);
+ }
+ }
+}
+
+
+
+// given a cone rotation in constraint space, (pre: twist must already be removed)
+// this method computes its corresponding swing angle and axis.
+// more interestingly, it computes the cone/swing limit (angle) for this cone "pose".
+void btConeTwistConstraint::computeConeLimitInfo(const btQuaternion& qCone,
+ btScalar& swingAngle, // out
+ btVector3& vSwingAxis, // out
+ btScalar& swingLimit) // out
+{
+ swingAngle = qCone.getAngle();
+ if (swingAngle > SIMD_EPSILON)
+ {
+ vSwingAxis = btVector3(qCone.x(), qCone.y(), qCone.z());
+ vSwingAxis.normalize();
+#if 0
+ // non-zero twist?! this should never happen.
+ btAssert(fabs(vSwingAxis.x()) <= SIMD_EPSILON));
+#endif
+
+ // Compute limit for given swing. tricky:
+ // Given a swing axis, we're looking for the intersection with the bounding cone ellipse.
+ // (Since we're dealing with angles, this ellipse is embedded on the surface of a sphere.)
+
+ // For starters, compute the direction from center to surface of ellipse.
+ // This is just the perpendicular (ie. rotate 2D vector by PI/2) of the swing axis.
+ // (vSwingAxis is the cone rotation (in z,y); change vars and rotate to (x,y) coords.)
+ btScalar xEllipse = vSwingAxis.y();
+ btScalar yEllipse = -vSwingAxis.z();
+
+ // Now, we use the slope of the vector (using x/yEllipse) and find the length
+ // of the line that intersects the ellipse:
+ // x^2 y^2
+ // --- + --- = 1, where a and b are semi-major axes 2 and 1 respectively (ie. the limits)
+ // a^2 b^2
+ // Do the math and it should be clear.
+
+ swingLimit = m_swingSpan1; // if xEllipse == 0, we have a pure vSwingAxis.z rotation: just use swingspan1
+ if (fabs(xEllipse) > SIMD_EPSILON)
+ {
+ btScalar surfaceSlope2 = (yEllipse*yEllipse)/(xEllipse*xEllipse);
+ btScalar norm = 1 / (m_swingSpan2 * m_swingSpan2);
+ norm += surfaceSlope2 / (m_swingSpan1 * m_swingSpan1);
+ btScalar swingLimit2 = (1 + surfaceSlope2) / norm;
+ swingLimit = sqrt(swingLimit2);
+ }
+
+ // test!
+ /*swingLimit = m_swingSpan2;
+ if (fabs(vSwingAxis.z()) > SIMD_EPSILON)
+ {
+ btScalar mag_2 = m_swingSpan1*m_swingSpan1 + m_swingSpan2*m_swingSpan2;
+ btScalar sinphi = m_swingSpan2 / sqrt(mag_2);
+ btScalar phi = asin(sinphi);
+ btScalar theta = atan2(fabs(vSwingAxis.y()),fabs(vSwingAxis.z()));
+ btScalar alpha = 3.14159f - theta - phi;
+ btScalar sinalpha = sin(alpha);
+ swingLimit = m_swingSpan1 * sinphi/sinalpha;
+ }*/
+ }
+ else if (swingAngle < 0)
+ {
+ // this should never happen!
+#if 0
+ btAssert(0);
+#endif
+ }
+}
+
+btVector3 btConeTwistConstraint::GetPointForAngle(btScalar fAngleInRadians, btScalar fLength) const
+{
+ // compute x/y in ellipse using cone angle (0 -> 2*PI along surface of cone)
+ btScalar xEllipse = btCos(fAngleInRadians);
+ btScalar yEllipse = btSin(fAngleInRadians);
+
+ // Use the slope of the vector (using x/yEllipse) and find the length
+ // of the line that intersects the ellipse:
+ // x^2 y^2
+ // --- + --- = 1, where a and b are semi-major axes 2 and 1 respectively (ie. the limits)
+ // a^2 b^2
+ // Do the math and it should be clear.
+
+ btScalar swingLimit = m_swingSpan1; // if xEllipse == 0, just use axis b (1)
+ if (fabs(xEllipse) > SIMD_EPSILON)
+ {
+ btScalar surfaceSlope2 = (yEllipse*yEllipse)/(xEllipse*xEllipse);
+ btScalar norm = 1 / (m_swingSpan2 * m_swingSpan2);
+ norm += surfaceSlope2 / (m_swingSpan1 * m_swingSpan1);
+ btScalar swingLimit2 = (1 + surfaceSlope2) / norm;
+ swingLimit = sqrt(swingLimit2);
+ }
+
+ // convert into point in constraint space:
+ // note: twist is x-axis, swing 1 and 2 are along the z and y axes respectively
+ btVector3 vSwingAxis(0, xEllipse, -yEllipse);
+ btQuaternion qSwing(vSwingAxis, swingLimit);
+ btVector3 vPointInConstraintSpace(fLength,0,0);
+ return quatRotate(qSwing, vPointInConstraintSpace);
+}
+
+// given a twist rotation in constraint space, (pre: cone must already be removed)
+// this method computes its corresponding angle and axis.
+void btConeTwistConstraint::computeTwistLimitInfo(const btQuaternion& qTwist,
+ btScalar& twistAngle, // out
+ btVector3& vTwistAxis) // out
+{
+ btQuaternion qMinTwist = qTwist;
+ twistAngle = qTwist.getAngle();
+
+ if (twistAngle > SIMD_PI) // long way around. flip quat and recalculate.
+ {
+ qMinTwist = -(qTwist);
+ twistAngle = qMinTwist.getAngle();
+ }
+ if (twistAngle < 0)
+ {
+ // this should never happen
+#if 0
+ btAssert(0);
+#endif
+ }
+
+ vTwistAxis = btVector3(qMinTwist.x(), qMinTwist.y(), qMinTwist.z());
+ if (twistAngle > SIMD_EPSILON)
+ vTwistAxis.normalize();
+}
+
+
+void btConeTwistConstraint::adjustSwingAxisToUseEllipseNormal(btVector3& vSwingAxis) const
+{
+ // the swing axis is computed as the "twist-free" cone rotation,
+ // but the cone limit is not circular, but elliptical (if swingspan1 != swingspan2).
+ // so, if we're outside the limits, the closest way back inside the cone isn't
+ // along the vector back to the center. better (and more stable) to use the ellipse normal.
+
+ // convert swing axis to direction from center to surface of ellipse
+ // (ie. rotate 2D vector by PI/2)
+ btScalar y = -vSwingAxis.z();
+ btScalar z = vSwingAxis.y();
+
+ // do the math...
+ if (fabs(z) > SIMD_EPSILON) // avoid division by 0. and we don't need an update if z == 0.
+ {
+ // compute gradient/normal of ellipse surface at current "point"
+ btScalar grad = y/z;
+ grad *= m_swingSpan2 / m_swingSpan1;
+
+ // adjust y/z to represent normal at point (instead of vector to point)
+ if (y > 0)
+ y = fabs(grad * z);
+ else
+ y = -fabs(grad * z);
+
+ // convert ellipse direction back to swing axis
+ vSwingAxis.setZ(-y);
+ vSwingAxis.setY( z);
+ vSwingAxis.normalize();
+ }
+}
+
+
+
+void btConeTwistConstraint::setMotorTarget(const btQuaternion &q)
+{
+ //btTransform trACur = m_rbA.getCenterOfMassTransform();
+ //btTransform trBCur = m_rbB.getCenterOfMassTransform();
+// btTransform trABCur = trBCur.inverse() * trACur;
+// btQuaternion qABCur = trABCur.getRotation();
+// btTransform trConstraintCur = (trBCur * m_rbBFrame).inverse() * (trACur * m_rbAFrame);
+ //btQuaternion qConstraintCur = trConstraintCur.getRotation();
+
+ btQuaternion qConstraint = m_rbBFrame.getRotation().inverse() * q * m_rbAFrame.getRotation();
+ setMotorTargetInConstraintSpace(qConstraint);
+}
+
+
+void btConeTwistConstraint::setMotorTargetInConstraintSpace(const btQuaternion &q)
+{
+ m_qTarget = q;
+
+ // clamp motor target to within limits
+ {
+ btScalar softness = 1.f;//m_limitSoftness;
+
+ // split into twist and cone
+ btVector3 vTwisted = quatRotate(m_qTarget, vTwist);
+ btQuaternion qTargetCone = shortestArcQuat(vTwist, vTwisted); qTargetCone.normalize();
+ btQuaternion qTargetTwist = qTargetCone.inverse() * m_qTarget; qTargetTwist.normalize();
+
+ // clamp cone
+ if (m_swingSpan1 >= btScalar(0.05f) && m_swingSpan2 >= btScalar(0.05f))
+ {
+ btScalar swingAngle, swingLimit; btVector3 swingAxis;
+ computeConeLimitInfo(qTargetCone, swingAngle, swingAxis, swingLimit);
+
+ if (fabs(swingAngle) > SIMD_EPSILON)
+ {
+ if (swingAngle > swingLimit*softness)
+ swingAngle = swingLimit*softness;
+ else if (swingAngle < -swingLimit*softness)
+ swingAngle = -swingLimit*softness;
+ qTargetCone = btQuaternion(swingAxis, swingAngle);
+ }
+ }
+
+ // clamp twist
+ if (m_twistSpan >= btScalar(0.05f))
+ {
+ btScalar twistAngle; btVector3 twistAxis;
+ computeTwistLimitInfo(qTargetTwist, twistAngle, twistAxis);
+
+ if (fabs(twistAngle) > SIMD_EPSILON)
+ {
+ // eddy todo: limitSoftness used here???
+ if (twistAngle > m_twistSpan*softness)
+ twistAngle = m_twistSpan*softness;
+ else if (twistAngle < -m_twistSpan*softness)
+ twistAngle = -m_twistSpan*softness;
+ qTargetTwist = btQuaternion(twistAxis, twistAngle);
+ }
+ }
+
+ m_qTarget = qTargetCone * qTargetTwist;
+ }
+}
+
+///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
+///If no axis is provided, it uses the default axis for this constraint.
+void btConeTwistConstraint::setParam(int num, btScalar value, int axis)
+{
+ switch(num)
+ {
+ case BT_CONSTRAINT_ERP :
+ case BT_CONSTRAINT_STOP_ERP :
+ if((axis >= 0) && (axis < 3))
+ {
+ m_linERP = value;
+ m_flags |= BT_CONETWIST_FLAGS_LIN_ERP;
+ }
+ else
+ {
+ m_biasFactor = value;
+ }
+ break;
+ case BT_CONSTRAINT_CFM :
+ case BT_CONSTRAINT_STOP_CFM :
+ if((axis >= 0) && (axis < 3))
+ {
+ m_linCFM = value;
+ m_flags |= BT_CONETWIST_FLAGS_LIN_CFM;
+ }
+ else
+ {
+ m_angCFM = value;
+ m_flags |= BT_CONETWIST_FLAGS_ANG_CFM;
+ }
+ break;
+ default:
+ btAssertConstrParams(0);
+ break;
+ }
+}
+
+///return the local value of parameter
+btScalar btConeTwistConstraint::getParam(int num, int axis) const
+{
+ btScalar retVal = 0;
+ switch(num)
+ {
+ case BT_CONSTRAINT_ERP :
+ case BT_CONSTRAINT_STOP_ERP :
+ if((axis >= 0) && (axis < 3))
+ {
+ btAssertConstrParams(m_flags & BT_CONETWIST_FLAGS_LIN_ERP);
+ retVal = m_linERP;
+ }
+ else if((axis >= 3) && (axis < 6))
+ {
+ retVal = m_biasFactor;
+ }
+ else
+ {
+ btAssertConstrParams(0);
+ }
+ break;
+ case BT_CONSTRAINT_CFM :
+ case BT_CONSTRAINT_STOP_CFM :
+ if((axis >= 0) && (axis < 3))
+ {
+ btAssertConstrParams(m_flags & BT_CONETWIST_FLAGS_LIN_CFM);
+ retVal = m_linCFM;
+ }
+ else if((axis >= 3) && (axis < 6))
+ {
+ btAssertConstrParams(m_flags & BT_CONETWIST_FLAGS_ANG_CFM);
+ retVal = m_angCFM;
+ }
+ else
+ {
+ btAssertConstrParams(0);
+ }
+ break;
+ default :
+ btAssertConstrParams(0);
+ }
+ return retVal;
+}
+
+
+void btConeTwistConstraint::setFrames(const btTransform & frameA, const btTransform & frameB)
+{
+ m_rbAFrame = frameA;
+ m_rbBFrame = frameB;
+ buildJacobian();
+ //calculateTransforms();
+}
+
+
+
+
diff --git a/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h
new file mode 100644
index 0000000000..7a33d01d1e
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h
@@ -0,0 +1,435 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+btConeTwistConstraint is Copyright (c) 2007 Starbreeze Studios
+
+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.
+
+Written by: Marcus Hennix
+*/
+
+
+
+/*
+Overview:
+
+btConeTwistConstraint can be used to simulate ragdoll joints (upper arm, leg etc).
+It is a fixed translation, 3 degree-of-freedom (DOF) rotational "joint".
+It divides the 3 rotational DOFs into swing (movement within a cone) and twist.
+Swing is divided into swing1 and swing2 which can have different limits, giving an elliptical shape.
+(Note: the cone's base isn't flat, so this ellipse is "embedded" on the surface of a sphere.)
+
+In the contraint's frame of reference:
+twist is along the x-axis,
+and swing 1 and 2 are along the z and y axes respectively.
+*/
+
+
+
+#ifndef BT_CONETWISTCONSTRAINT_H
+#define BT_CONETWISTCONSTRAINT_H
+
+#include "LinearMath/btVector3.h"
+#include "btJacobianEntry.h"
+#include "btTypedConstraint.h"
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define btConeTwistConstraintData2 btConeTwistConstraintDoubleData
+#define btConeTwistConstraintDataName "btConeTwistConstraintDoubleData"
+#else
+#define btConeTwistConstraintData2 btConeTwistConstraintData
+#define btConeTwistConstraintDataName "btConeTwistConstraintData"
+#endif //BT_USE_DOUBLE_PRECISION
+
+
+class btRigidBody;
+
+enum btConeTwistFlags
+{
+ BT_CONETWIST_FLAGS_LIN_CFM = 1,
+ BT_CONETWIST_FLAGS_LIN_ERP = 2,
+ BT_CONETWIST_FLAGS_ANG_CFM = 4
+};
+
+///btConeTwistConstraint can be used to simulate ragdoll joints (upper arm, leg etc)
+ATTRIBUTE_ALIGNED16(class) btConeTwistConstraint : public btTypedConstraint
+{
+#ifdef IN_PARALLELL_SOLVER
+public:
+#endif
+ btJacobianEntry m_jac[3]; //3 orthogonal linear constraints
+
+ btTransform m_rbAFrame;
+ btTransform m_rbBFrame;
+
+ btScalar m_limitSoftness;
+ btScalar m_biasFactor;
+ btScalar m_relaxationFactor;
+
+ btScalar m_damping;
+
+ btScalar m_swingSpan1;
+ btScalar m_swingSpan2;
+ btScalar m_twistSpan;
+
+ btScalar m_fixThresh;
+
+ btVector3 m_swingAxis;
+ btVector3 m_twistAxis;
+
+ btScalar m_kSwing;
+ btScalar m_kTwist;
+
+ btScalar m_twistLimitSign;
+ btScalar m_swingCorrection;
+ btScalar m_twistCorrection;
+
+ btScalar m_twistAngle;
+
+ btScalar m_accSwingLimitImpulse;
+ btScalar m_accTwistLimitImpulse;
+
+ bool m_angularOnly;
+ bool m_solveTwistLimit;
+ bool m_solveSwingLimit;
+
+ bool m_useSolveConstraintObsolete;
+
+ // not yet used...
+ btScalar m_swingLimitRatio;
+ btScalar m_twistLimitRatio;
+ btVector3 m_twistAxisA;
+
+ // motor
+ bool m_bMotorEnabled;
+ bool m_bNormalizedMotorStrength;
+ btQuaternion m_qTarget;
+ btScalar m_maxMotorImpulse;
+ btVector3 m_accMotorImpulse;
+
+ // parameters
+ int m_flags;
+ btScalar m_linCFM;
+ btScalar m_linERP;
+ btScalar m_angCFM;
+
+protected:
+
+ void init();
+
+ void computeConeLimitInfo(const btQuaternion& qCone, // in
+ btScalar& swingAngle, btVector3& vSwingAxis, btScalar& swingLimit); // all outs
+
+ void computeTwistLimitInfo(const btQuaternion& qTwist, // in
+ btScalar& twistAngle, btVector3& vTwistAxis); // all outs
+
+ void adjustSwingAxisToUseEllipseNormal(btVector3& vSwingAxis) const;
+
+
+public:
+
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ btConeTwistConstraint(btRigidBody& rbA,btRigidBody& rbB,const btTransform& rbAFrame, const btTransform& rbBFrame);
+
+ btConeTwistConstraint(btRigidBody& rbA,const btTransform& rbAFrame);
+
+ virtual void buildJacobian();
+
+ virtual void getInfo1 (btConstraintInfo1* info);
+
+ void getInfo1NonVirtual(btConstraintInfo1* info);
+
+ virtual void getInfo2 (btConstraintInfo2* info);
+
+ void getInfo2NonVirtual(btConstraintInfo2* info,const btTransform& transA,const btTransform& transB,const btMatrix3x3& invInertiaWorldA,const btMatrix3x3& invInertiaWorldB);
+
+ virtual void solveConstraintObsolete(btSolverBody& bodyA,btSolverBody& bodyB,btScalar timeStep);
+
+
+ void updateRHS(btScalar timeStep);
+
+
+ const btRigidBody& getRigidBodyA() const
+ {
+ return m_rbA;
+ }
+ const btRigidBody& getRigidBodyB() const
+ {
+ return m_rbB;
+ }
+
+ void setAngularOnly(bool angularOnly)
+ {
+ m_angularOnly = angularOnly;
+ }
+
+ bool getAngularOnly() const
+ {
+ return m_angularOnly;
+ }
+
+ void setLimit(int limitIndex,btScalar limitValue)
+ {
+ switch (limitIndex)
+ {
+ case 3:
+ {
+ m_twistSpan = limitValue;
+ break;
+ }
+ case 4:
+ {
+ m_swingSpan2 = limitValue;
+ break;
+ }
+ case 5:
+ {
+ m_swingSpan1 = limitValue;
+ break;
+ }
+ default:
+ {
+ }
+ };
+ }
+
+ btScalar getLimit(int limitIndex) const
+ {
+ switch (limitIndex)
+ {
+ case 3:
+ {
+ return m_twistSpan;
+ break;
+ }
+ case 4:
+ {
+ return m_swingSpan2;
+ break;
+ }
+ case 5:
+ {
+ return m_swingSpan1;
+ break;
+ }
+ default:
+ {
+ btAssert(0 && "Invalid limitIndex specified for btConeTwistConstraint");
+ return 0.0;
+ }
+ };
+ }
+
+ // setLimit(), a few notes:
+ // _softness:
+ // 0->1, recommend ~0.8->1.
+ // describes % of limits where movement is free.
+ // beyond this softness %, the limit is gradually enforced until the "hard" (1.0) limit is reached.
+ // _biasFactor:
+ // 0->1?, recommend 0.3 +/-0.3 or so.
+ // strength with which constraint resists zeroth order (angular, not angular velocity) limit violation.
+ // __relaxationFactor:
+ // 0->1, recommend to stay near 1.
+ // the lower the value, the less the constraint will fight velocities which violate the angular limits.
+ void setLimit(btScalar _swingSpan1,btScalar _swingSpan2,btScalar _twistSpan, btScalar _softness = 1.f, btScalar _biasFactor = 0.3f, btScalar _relaxationFactor = 1.0f)
+ {
+ m_swingSpan1 = _swingSpan1;
+ m_swingSpan2 = _swingSpan2;
+ m_twistSpan = _twistSpan;
+
+ m_limitSoftness = _softness;
+ m_biasFactor = _biasFactor;
+ m_relaxationFactor = _relaxationFactor;
+ }
+
+ const btTransform& getAFrame() const { return m_rbAFrame; };
+ const btTransform& getBFrame() const { return m_rbBFrame; };
+
+ inline int getSolveTwistLimit()
+ {
+ return m_solveTwistLimit;
+ }
+
+ inline int getSolveSwingLimit()
+ {
+ return m_solveSwingLimit;
+ }
+
+ inline btScalar getTwistLimitSign()
+ {
+ return m_twistLimitSign;
+ }
+
+ void calcAngleInfo();
+ void calcAngleInfo2(const btTransform& transA, const btTransform& transB,const btMatrix3x3& invInertiaWorldA,const btMatrix3x3& invInertiaWorldB);
+
+ inline btScalar getSwingSpan1() const
+ {
+ return m_swingSpan1;
+ }
+ inline btScalar getSwingSpan2() const
+ {
+ return m_swingSpan2;
+ }
+ inline btScalar getTwistSpan() const
+ {
+ return m_twistSpan;
+ }
+ inline btScalar getLimitSoftness() const
+ {
+ return m_limitSoftness;
+ }
+ inline btScalar getBiasFactor() const
+ {
+ return m_biasFactor;
+ }
+ inline btScalar getRelaxationFactor() const
+ {
+ return m_relaxationFactor;
+ }
+ inline btScalar getTwistAngle() const
+ {
+ return m_twistAngle;
+ }
+ bool isPastSwingLimit() { return m_solveSwingLimit; }
+
+ btScalar getDamping() const { return m_damping; }
+ void setDamping(btScalar damping) { m_damping = damping; }
+
+ void enableMotor(bool b) { m_bMotorEnabled = b; }
+ bool isMotorEnabled() const { return m_bMotorEnabled; }
+ btScalar getMaxMotorImpulse() const { return m_maxMotorImpulse; }
+ bool isMaxMotorImpulseNormalized() const { return m_bNormalizedMotorStrength; }
+ void setMaxMotorImpulse(btScalar maxMotorImpulse) { m_maxMotorImpulse = maxMotorImpulse; m_bNormalizedMotorStrength = false; }
+ void setMaxMotorImpulseNormalized(btScalar maxMotorImpulse) { m_maxMotorImpulse = maxMotorImpulse; m_bNormalizedMotorStrength = true; }
+
+ btScalar getFixThresh() { return m_fixThresh; }
+ void setFixThresh(btScalar fixThresh) { m_fixThresh = fixThresh; }
+
+ // setMotorTarget:
+ // q: the desired rotation of bodyA wrt bodyB.
+ // note: if q violates the joint limits, the internal target is clamped to avoid conflicting impulses (very bad for stability)
+ // note: don't forget to enableMotor()
+ void setMotorTarget(const btQuaternion &q);
+ const btQuaternion& getMotorTarget() const { return m_qTarget; }
+
+ // same as above, but q is the desired rotation of frameA wrt frameB in constraint space
+ void setMotorTargetInConstraintSpace(const btQuaternion &q);
+
+ btVector3 GetPointForAngle(btScalar fAngleInRadians, btScalar fLength) const;
+
+ ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
+ ///If no axis is provided, it uses the default axis for this constraint.
+ virtual void setParam(int num, btScalar value, int axis = -1);
+
+ virtual void setFrames(const btTransform& frameA, const btTransform& frameB);
+
+ const btTransform& getFrameOffsetA() const
+ {
+ return m_rbAFrame;
+ }
+
+ const btTransform& getFrameOffsetB() const
+ {
+ return m_rbBFrame;
+ }
+
+
+ ///return the local value of parameter
+ virtual btScalar getParam(int num, int axis = -1) const;
+
+ int getFlags() const
+ {
+ return m_flags;
+ }
+
+ virtual int calculateSerializeBufferSize() const;
+
+ ///fills the dataBuffer and returns the struct name (and 0 on failure)
+ virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
+
+};
+
+
+
+struct btConeTwistConstraintDoubleData
+{
+ btTypedConstraintDoubleData m_typeConstraintData;
+ btTransformDoubleData m_rbAFrame;
+ btTransformDoubleData m_rbBFrame;
+
+ //limits
+ double m_swingSpan1;
+ double m_swingSpan2;
+ double m_twistSpan;
+ double m_limitSoftness;
+ double m_biasFactor;
+ double m_relaxationFactor;
+
+ double m_damping;
+
+
+
+};
+
+#ifdef BT_BACKWARDS_COMPATIBLE_SERIALIZATION
+///this structure is not used, except for loading pre-2.82 .bullet files
+struct btConeTwistConstraintData
+{
+ btTypedConstraintData m_typeConstraintData;
+ btTransformFloatData m_rbAFrame;
+ btTransformFloatData m_rbBFrame;
+
+ //limits
+ float m_swingSpan1;
+ float m_swingSpan2;
+ float m_twistSpan;
+ float m_limitSoftness;
+ float m_biasFactor;
+ float m_relaxationFactor;
+
+ float m_damping;
+
+ char m_pad[4];
+
+};
+#endif //BT_BACKWARDS_COMPATIBLE_SERIALIZATION
+//
+
+SIMD_FORCE_INLINE int btConeTwistConstraint::calculateSerializeBufferSize() const
+{
+ return sizeof(btConeTwistConstraintData2);
+
+}
+
+
+ ///fills the dataBuffer and returns the struct name (and 0 on failure)
+SIMD_FORCE_INLINE const char* btConeTwistConstraint::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+ btConeTwistConstraintData2* cone = (btConeTwistConstraintData2*) dataBuffer;
+ btTypedConstraint::serialize(&cone->m_typeConstraintData,serializer);
+
+ m_rbAFrame.serialize(cone->m_rbAFrame);
+ m_rbBFrame.serialize(cone->m_rbBFrame);
+
+ cone->m_swingSpan1 = m_swingSpan1;
+ cone->m_swingSpan2 = m_swingSpan2;
+ cone->m_twistSpan = m_twistSpan;
+ cone->m_limitSoftness = m_limitSoftness;
+ cone->m_biasFactor = m_biasFactor;
+ cone->m_relaxationFactor = m_relaxationFactor;
+ cone->m_damping = m_damping;
+
+ return btConeTwistConstraintDataName;
+}
+
+
+#endif //BT_CONETWISTCONSTRAINT_H
diff --git a/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btConstraintSolver.h b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btConstraintSolver.h
new file mode 100644
index 0000000000..890afe6da4
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btConstraintSolver.h
@@ -0,0 +1,65 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_CONSTRAINT_SOLVER_H
+#define BT_CONSTRAINT_SOLVER_H
+
+#include "LinearMath/btScalar.h"
+
+class btPersistentManifold;
+class btRigidBody;
+class btCollisionObject;
+class btTypedConstraint;
+struct btContactSolverInfo;
+struct btBroadphaseProxy;
+class btIDebugDraw;
+class btStackAlloc;
+class btDispatcher;
+/// btConstraintSolver provides solver interface
+
+
+enum btConstraintSolverType
+{
+ BT_SEQUENTIAL_IMPULSE_SOLVER=1,
+ BT_MLCP_SOLVER=2,
+ BT_NNCG_SOLVER=4
+};
+
+class btConstraintSolver
+{
+
+public:
+
+ virtual ~btConstraintSolver() {}
+
+ virtual void prepareSolve (int /* numBodies */, int /* numManifolds */) {;}
+
+ ///solve a group of constraints
+ virtual btScalar solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints, const btContactSolverInfo& info,class btIDebugDraw* debugDrawer,btDispatcher* dispatcher) = 0;
+
+ virtual void allSolved (const btContactSolverInfo& /* info */,class btIDebugDraw* /* debugDrawer */) {;}
+
+ ///clear internal cached data and reset random seed
+ virtual void reset() = 0;
+
+ virtual btConstraintSolverType getSolverType() const=0;
+
+
+};
+
+
+
+
+#endif //BT_CONSTRAINT_SOLVER_H
diff --git a/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp
new file mode 100644
index 0000000000..1098d0c96b
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp
@@ -0,0 +1,177 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "btContactConstraint.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "LinearMath/btVector3.h"
+#include "btJacobianEntry.h"
+#include "btContactSolverInfo.h"
+#include "LinearMath/btMinMax.h"
+#include "BulletCollision/NarrowPhaseCollision/btManifoldPoint.h"
+
+
+
+btContactConstraint::btContactConstraint(btPersistentManifold* contactManifold,btRigidBody& rbA,btRigidBody& rbB)
+:btTypedConstraint(CONTACT_CONSTRAINT_TYPE,rbA,rbB),
+ m_contactManifold(*contactManifold)
+{
+
+}
+
+btContactConstraint::~btContactConstraint()
+{
+
+}
+
+void btContactConstraint::setContactManifold(btPersistentManifold* contactManifold)
+{
+ m_contactManifold = *contactManifold;
+}
+
+void btContactConstraint::getInfo1 (btConstraintInfo1* info)
+{
+
+}
+
+void btContactConstraint::getInfo2 (btConstraintInfo2* info)
+{
+
+}
+
+void btContactConstraint::buildJacobian()
+{
+
+}
+
+
+
+
+
+#include "btContactConstraint.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "LinearMath/btVector3.h"
+#include "btJacobianEntry.h"
+#include "btContactSolverInfo.h"
+#include "LinearMath/btMinMax.h"
+#include "BulletCollision/NarrowPhaseCollision/btManifoldPoint.h"
+
+
+
+//response between two dynamic objects without friction and no restitution, assuming 0 penetration depth
+btScalar resolveSingleCollision(
+ btRigidBody* body1,
+ btCollisionObject* colObj2,
+ const btVector3& contactPositionWorld,
+ const btVector3& contactNormalOnB,
+ const btContactSolverInfo& solverInfo,
+ btScalar distance)
+{
+ btRigidBody* body2 = btRigidBody::upcast(colObj2);
+
+
+ const btVector3& normal = contactNormalOnB;
+
+ btVector3 rel_pos1 = contactPositionWorld - body1->getWorldTransform().getOrigin();
+ btVector3 rel_pos2 = contactPositionWorld - colObj2->getWorldTransform().getOrigin();
+
+ btVector3 vel1 = body1->getVelocityInLocalPoint(rel_pos1);
+ btVector3 vel2 = body2? body2->getVelocityInLocalPoint(rel_pos2) : btVector3(0,0,0);
+ btVector3 vel = vel1 - vel2;
+ btScalar rel_vel;
+ rel_vel = normal.dot(vel);
+
+ btScalar combinedRestitution = 0.f;
+ btScalar restitution = combinedRestitution* -rel_vel;
+
+ btScalar positionalError = solverInfo.m_erp *-distance /solverInfo.m_timeStep ;
+ btScalar velocityError = -(1.0f + restitution) * rel_vel;// * damping;
+ btScalar denom0 = body1->computeImpulseDenominator(contactPositionWorld,normal);
+ btScalar denom1 = body2? body2->computeImpulseDenominator(contactPositionWorld,normal) : 0.f;
+ btScalar relaxation = 1.f;
+ btScalar jacDiagABInv = relaxation/(denom0+denom1);
+
+ btScalar penetrationImpulse = positionalError * jacDiagABInv;
+ btScalar velocityImpulse = velocityError * jacDiagABInv;
+
+ btScalar normalImpulse = penetrationImpulse+velocityImpulse;
+ normalImpulse = 0.f > normalImpulse ? 0.f: normalImpulse;
+
+ body1->applyImpulse(normal*(normalImpulse), rel_pos1);
+ if (body2)
+ body2->applyImpulse(-normal*(normalImpulse), rel_pos2);
+
+ return normalImpulse;
+}
+
+
+//bilateral constraint between two dynamic objects
+void resolveSingleBilateral(btRigidBody& body1, const btVector3& pos1,
+ btRigidBody& body2, const btVector3& pos2,
+ btScalar distance, const btVector3& normal,btScalar& impulse ,btScalar timeStep)
+{
+ (void)timeStep;
+ (void)distance;
+
+
+ btScalar normalLenSqr = normal.length2();
+ btAssert(btFabs(normalLenSqr) < btScalar(1.1));
+ if (normalLenSqr > btScalar(1.1))
+ {
+ impulse = btScalar(0.);
+ return;
+ }
+ btVector3 rel_pos1 = pos1 - body1.getCenterOfMassPosition();
+ btVector3 rel_pos2 = pos2 - body2.getCenterOfMassPosition();
+ //this jacobian entry could be re-used for all iterations
+
+ btVector3 vel1 = body1.getVelocityInLocalPoint(rel_pos1);
+ btVector3 vel2 = body2.getVelocityInLocalPoint(rel_pos2);
+ btVector3 vel = vel1 - vel2;
+
+
+ btJacobianEntry jac(body1.getCenterOfMassTransform().getBasis().transpose(),
+ body2.getCenterOfMassTransform().getBasis().transpose(),
+ rel_pos1,rel_pos2,normal,body1.getInvInertiaDiagLocal(),body1.getInvMass(),
+ body2.getInvInertiaDiagLocal(),body2.getInvMass());
+
+ btScalar jacDiagAB = jac.getDiagonal();
+ btScalar jacDiagABInv = btScalar(1.) / jacDiagAB;
+
+ btScalar rel_vel = jac.getRelativeVelocity(
+ body1.getLinearVelocity(),
+ body1.getCenterOfMassTransform().getBasis().transpose() * body1.getAngularVelocity(),
+ body2.getLinearVelocity(),
+ body2.getCenterOfMassTransform().getBasis().transpose() * body2.getAngularVelocity());
+
+
+
+ rel_vel = normal.dot(vel);
+
+ //todo: move this into proper structure
+ btScalar contactDamping = btScalar(0.2);
+
+#ifdef ONLY_USE_LINEAR_MASS
+ btScalar massTerm = btScalar(1.) / (body1.getInvMass() + body2.getInvMass());
+ impulse = - contactDamping * rel_vel * massTerm;
+#else
+ btScalar velocityImpulse = -contactDamping * rel_vel * jacDiagABInv;
+ impulse = velocityImpulse;
+#endif
+}
+
+
+
+
diff --git a/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btContactConstraint.h b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btContactConstraint.h
new file mode 100644
index 0000000000..adb2268353
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btContactConstraint.h
@@ -0,0 +1,73 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_CONTACT_CONSTRAINT_H
+#define BT_CONTACT_CONSTRAINT_H
+
+#include "LinearMath/btVector3.h"
+#include "btJacobianEntry.h"
+#include "btTypedConstraint.h"
+#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
+
+///btContactConstraint can be automatically created to solve contact constraints using the unified btTypedConstraint interface
+ATTRIBUTE_ALIGNED16(class) btContactConstraint : public btTypedConstraint
+{
+protected:
+
+ btPersistentManifold m_contactManifold;
+
+protected:
+
+
+ btContactConstraint(btPersistentManifold* contactManifold,btRigidBody& rbA,btRigidBody& rbB);
+
+public:
+
+ void setContactManifold(btPersistentManifold* contactManifold);
+
+ btPersistentManifold* getContactManifold()
+ {
+ return &m_contactManifold;
+ }
+
+ const btPersistentManifold* getContactManifold() const
+ {
+ return &m_contactManifold;
+ }
+
+ virtual ~btContactConstraint();
+
+ virtual void getInfo1 (btConstraintInfo1* info);
+
+ virtual void getInfo2 (btConstraintInfo2* info);
+
+ ///obsolete methods
+ virtual void buildJacobian();
+
+
+};
+
+///very basic collision resolution without friction
+btScalar resolveSingleCollision(btRigidBody* body1, class btCollisionObject* colObj2, const btVector3& contactPositionWorld,const btVector3& contactNormalOnB, const struct btContactSolverInfo& solverInfo,btScalar distance);
+
+
+///resolveSingleBilateral is an obsolete methods used for vehicle friction between two dynamic objects
+void resolveSingleBilateral(btRigidBody& body1, const btVector3& pos1,
+ btRigidBody& body2, const btVector3& pos2,
+ btScalar distance, const btVector3& normal,btScalar& impulse ,btScalar timeStep);
+
+
+
+#endif //BT_CONTACT_CONSTRAINT_H
diff --git a/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h
new file mode 100644
index 0000000000..28d0c1dd48
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h
@@ -0,0 +1,167 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_CONTACT_SOLVER_INFO
+#define BT_CONTACT_SOLVER_INFO
+
+#include "LinearMath/btScalar.h"
+
+enum btSolverMode
+{
+ SOLVER_RANDMIZE_ORDER = 1,
+ SOLVER_FRICTION_SEPARATE = 2,
+ SOLVER_USE_WARMSTARTING = 4,
+ SOLVER_USE_2_FRICTION_DIRECTIONS = 16,
+ SOLVER_ENABLE_FRICTION_DIRECTION_CACHING = 32,
+ SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION = 64,
+ SOLVER_CACHE_FRIENDLY = 128,
+ SOLVER_SIMD = 256,
+ SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS = 512,
+ SOLVER_ALLOW_ZERO_LENGTH_FRICTION_DIRECTIONS = 1024
+};
+
+struct btContactSolverInfoData
+{
+
+
+ btScalar m_tau;
+ btScalar m_damping;//global non-contact constraint damping, can be locally overridden by constraints during 'getInfo2'.
+ btScalar m_friction;
+ btScalar m_timeStep;
+ btScalar m_restitution;
+ int m_numIterations;
+ btScalar m_maxErrorReduction;
+ 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_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
+
+ int m_splitImpulse;
+ btScalar m_splitImpulsePenetrationThreshold;
+ btScalar m_splitImpulseTurnErp;
+ btScalar m_linearSlop;
+ btScalar m_warmstartingFactor;
+
+ int m_solverMode;
+ int m_restingContactRestitutionThreshold;
+ int m_minimumSolverBatchSize;
+ btScalar m_maxGyroscopicForce;
+ btScalar m_singleAxisRollingFrictionThreshold;
+ btScalar m_leastSquaresResidualThreshold;
+ btScalar m_restitutionVelocityThreshold;
+
+};
+
+struct btContactSolverInfo : public btContactSolverInfoData
+{
+
+
+
+ inline btContactSolverInfo()
+ {
+ m_tau = btScalar(0.6);
+ m_damping = btScalar(1.0);
+ m_friction = btScalar(0.3);
+ m_timeStep = btScalar(1.f/60.f);
+ m_restitution = btScalar(0.);
+ m_maxErrorReduction = btScalar(20.);
+ m_numIterations = 10;
+ m_erp = btScalar(0.2);
+ m_erp2 = btScalar(0.2);
+ m_globalCfm = btScalar(0.);
+ m_frictionERP = btScalar(0.2);//positional friction 'anchors' are disabled by default
+ m_frictionCFM = btScalar(0.);
+ m_sor = btScalar(1.);
+ m_splitImpulse = true;
+ m_splitImpulsePenetrationThreshold = -.04f;
+ m_splitImpulseTurnErp = 0.1f;
+ m_linearSlop = btScalar(0.0);
+ m_warmstartingFactor=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
+ m_minimumSolverBatchSize = 128; //try to combine islands until the amount of constraints reaches this limit
+ m_maxGyroscopicForce = 100.f; ///it is only used for 'explicit' version of gyroscopic force
+ m_singleAxisRollingFrictionThreshold = 1e30f;///if the velocity is above this threshold, it will use a single constraint row (axis), otherwise 3 rows.
+ m_leastSquaresResidualThreshold = 0.f;
+ m_restitutionVelocityThreshold = 0.2f;//if the relative velocity is below this threshold, there is zero restitution
+ }
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btContactSolverInfoDoubleData
+{
+ double m_tau;
+ double m_damping;//global non-contact constraint damping, can be locally overridden by constraints during 'getInfo2'.
+ double m_friction;
+ double m_timeStep;
+ double m_restitution;
+ double m_maxErrorReduction;
+ double m_sor;
+ double m_erp;//used as Baumgarte factor
+ double m_erp2;//used in Split Impulse
+ double m_globalCfm;//constraint force mixing
+ double m_splitImpulsePenetrationThreshold;
+ double m_splitImpulseTurnErp;
+ double m_linearSlop;
+ double m_warmstartingFactor;
+ double m_maxGyroscopicForce;///it is only used for 'explicit' version of gyroscopic force
+ double m_singleAxisRollingFrictionThreshold;
+
+ int m_numIterations;
+ int m_solverMode;
+ int m_restingContactRestitutionThreshold;
+ int m_minimumSolverBatchSize;
+ int m_splitImpulse;
+ char m_padding[4];
+
+};
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btContactSolverInfoFloatData
+{
+ float m_tau;
+ float m_damping;//global non-contact constraint damping, can be locally overridden by constraints during 'getInfo2'.
+ float m_friction;
+ float m_timeStep;
+
+ float m_restitution;
+ float m_maxErrorReduction;
+ float m_sor;
+ float m_erp;//used as Baumgarte factor
+
+ float m_erp2;//used in Split Impulse
+ float m_globalCfm;//constraint force mixing
+ float m_splitImpulsePenetrationThreshold;
+ float m_splitImpulseTurnErp;
+
+ float m_linearSlop;
+ float m_warmstartingFactor;
+ float m_maxGyroscopicForce;
+ float m_singleAxisRollingFrictionThreshold;
+
+ int m_numIterations;
+ int m_solverMode;
+ int m_restingContactRestitutionThreshold;
+ int m_minimumSolverBatchSize;
+
+ int m_splitImpulse;
+ char m_padding[4];
+};
+
+
+
+#endif //BT_CONTACT_SOLVER_INFO
diff --git a/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btFixedConstraint.cpp b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btFixedConstraint.cpp
new file mode 100644
index 0000000000..75d81cc08c
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btFixedConstraint.cpp
@@ -0,0 +1,37 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2013 Erwin Coumans 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 "btFixedConstraint.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "LinearMath/btTransformUtil.h"
+#include <new>
+
+
+btFixedConstraint::btFixedConstraint(btRigidBody& rbA,btRigidBody& rbB, const btTransform& frameInA,const btTransform& frameInB)
+:btGeneric6DofSpring2Constraint(rbA,rbB,frameInA,frameInB)
+{
+ setAngularLowerLimit(btVector3(0,0,0));
+ setAngularUpperLimit(btVector3(0,0,0));
+ setLinearLowerLimit(btVector3(0,0,0));
+ setLinearUpperLimit(btVector3(0,0,0));
+}
+
+
+
+
+btFixedConstraint::~btFixedConstraint ()
+{
+}
diff --git a/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btFixedConstraint.h b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btFixedConstraint.h
new file mode 100644
index 0000000000..bff2008b28
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btFixedConstraint.h
@@ -0,0 +1,33 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2013 Erwin Coumans 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_FIXED_CONSTRAINT_H
+#define BT_FIXED_CONSTRAINT_H
+
+#include "btGeneric6DofSpring2Constraint.h"
+
+
+ATTRIBUTE_ALIGNED16(class) btFixedConstraint : public btGeneric6DofSpring2Constraint
+{
+
+public:
+ btFixedConstraint(btRigidBody& rbA,btRigidBody& rbB, const btTransform& frameInA,const btTransform& frameInB);
+
+
+ virtual ~btFixedConstraint();
+
+};
+
+#endif //BT_FIXED_CONSTRAINT_H
diff --git a/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btGearConstraint.cpp b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btGearConstraint.cpp
new file mode 100644
index 0000000000..bcd457b673
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btGearConstraint.cpp
@@ -0,0 +1,54 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2012 Advanced Micro Devices, 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.
+*/
+
+/// Implemented by Erwin Coumans. The idea for the constraint comes from Dimitris Papavasiliou.
+
+#include "btGearConstraint.h"
+
+btGearConstraint::btGearConstraint(btRigidBody& rbA, btRigidBody& rbB, const btVector3& axisInA,const btVector3& axisInB, btScalar ratio)
+:btTypedConstraint(GEAR_CONSTRAINT_TYPE,rbA,rbB),
+m_axisInA(axisInA),
+m_axisInB(axisInB),
+m_ratio(ratio)
+{
+}
+
+btGearConstraint::~btGearConstraint ()
+{
+}
+
+void btGearConstraint::getInfo1 (btConstraintInfo1* info)
+{
+ info->m_numConstraintRows = 1;
+ info->nub = 1;
+}
+
+void btGearConstraint::getInfo2 (btConstraintInfo2* info)
+{
+ btVector3 globalAxisA, globalAxisB;
+
+ globalAxisA = m_rbA.getWorldTransform().getBasis()*this->m_axisInA;
+ globalAxisB = m_rbB.getWorldTransform().getBasis()*this->m_axisInB;
+
+ info->m_J1angularAxis[0] = globalAxisA[0];
+ info->m_J1angularAxis[1] = globalAxisA[1];
+ info->m_J1angularAxis[2] = globalAxisA[2];
+
+ info->m_J2angularAxis[0] = m_ratio*globalAxisB[0];
+ info->m_J2angularAxis[1] = m_ratio*globalAxisB[1];
+ info->m_J2angularAxis[2] = m_ratio*globalAxisB[2];
+
+}
+
diff --git a/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btGearConstraint.h b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btGearConstraint.h
new file mode 100644
index 0000000000..e4613455a2
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btGearConstraint.h
@@ -0,0 +1,160 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2012 Advanced Micro Devices, 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_GEAR_CONSTRAINT_H
+#define BT_GEAR_CONSTRAINT_H
+
+#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
+
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define btGearConstraintData btGearConstraintDoubleData
+#define btGearConstraintDataName "btGearConstraintDoubleData"
+#else
+#define btGearConstraintData btGearConstraintFloatData
+#define btGearConstraintDataName "btGearConstraintFloatData"
+#endif //BT_USE_DOUBLE_PRECISION
+
+
+
+///The btGeatConstraint will couple the angular velocity for two bodies around given local axis and ratio.
+///See Bullet/Demos/ConstraintDemo for an example use.
+class btGearConstraint : public btTypedConstraint
+{
+protected:
+ btVector3 m_axisInA;
+ btVector3 m_axisInB;
+ bool m_useFrameA;
+ btScalar m_ratio;
+
+public:
+ btGearConstraint(btRigidBody& rbA, btRigidBody& rbB, const btVector3& axisInA,const btVector3& axisInB, btScalar ratio=1.f);
+ virtual ~btGearConstraint ();
+
+ ///internal method used by the constraint solver, don't use them directly
+ virtual void getInfo1 (btConstraintInfo1* info);
+
+ ///internal method used by the constraint solver, don't use them directly
+ virtual void getInfo2 (btConstraintInfo2* info);
+
+ void setAxisA(btVector3& axisA)
+ {
+ m_axisInA = axisA;
+ }
+ void setAxisB(btVector3& axisB)
+ {
+ m_axisInB = axisB;
+ }
+ void setRatio(btScalar ratio)
+ {
+ m_ratio = ratio;
+ }
+ const btVector3& getAxisA() const
+ {
+ return m_axisInA;
+ }
+ const btVector3& getAxisB() const
+ {
+ return m_axisInB;
+ }
+ btScalar getRatio() const
+ {
+ return m_ratio;
+ }
+
+
+ virtual void setParam(int num, btScalar value, int axis = -1)
+ {
+ (void) num;
+ (void) value;
+ (void) axis;
+ btAssert(0);
+ }
+
+ ///return the local value of parameter
+ virtual btScalar getParam(int num, int axis = -1) const
+ {
+ (void) num;
+ (void) axis;
+ btAssert(0);
+ return 0.f;
+ }
+
+ virtual int calculateSerializeBufferSize() const;
+
+ ///fills the dataBuffer and returns the struct name (and 0 on failure)
+ virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
+};
+
+
+
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btGearConstraintFloatData
+{
+ btTypedConstraintFloatData m_typeConstraintData;
+
+ btVector3FloatData m_axisInA;
+ btVector3FloatData m_axisInB;
+
+ float m_ratio;
+ char m_padding[4];
+};
+
+struct btGearConstraintDoubleData
+{
+ btTypedConstraintDoubleData m_typeConstraintData;
+
+ btVector3DoubleData m_axisInA;
+ btVector3DoubleData m_axisInB;
+
+ double m_ratio;
+};
+
+SIMD_FORCE_INLINE int btGearConstraint::calculateSerializeBufferSize() const
+{
+ return sizeof(btGearConstraintData);
+}
+
+ ///fills the dataBuffer and returns the struct name (and 0 on failure)
+SIMD_FORCE_INLINE const char* btGearConstraint::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+ btGearConstraintData* gear = (btGearConstraintData*)dataBuffer;
+ btTypedConstraint::serialize(&gear->m_typeConstraintData,serializer);
+
+ m_axisInA.serialize( gear->m_axisInA );
+ m_axisInB.serialize( gear->m_axisInB );
+
+ gear->m_ratio = m_ratio;
+
+ // Fill padding with zeros to appease msan.
+#ifndef BT_USE_DOUBLE_PRECISION
+ gear->m_padding[0] = 0;
+ gear->m_padding[1] = 0;
+ gear->m_padding[2] = 0;
+ gear->m_padding[3] = 0;
+#endif
+
+ return btGearConstraintDataName;
+}
+
+
+
+
+
+
+#endif //BT_GEAR_CONSTRAINT_H
diff --git a/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp
new file mode 100644
index 0000000000..fa17254ec3
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp
@@ -0,0 +1,1063 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+/*
+2007-09-09
+Refactored by Francisco Le?n
+email: projectileman@yahoo.com
+http://gimpact.sf.net
+*/
+
+#include "btGeneric6DofConstraint.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "LinearMath/btTransformUtil.h"
+#include "LinearMath/btTransformUtil.h"
+#include <new>
+
+
+
+#define D6_USE_OBSOLETE_METHOD false
+#define D6_USE_FRAME_OFFSET true
+
+
+
+
+
+
+btGeneric6DofConstraint::btGeneric6DofConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA)
+: btTypedConstraint(D6_CONSTRAINT_TYPE, rbA, rbB)
+, m_frameInA(frameInA)
+, m_frameInB(frameInB),
+m_useLinearReferenceFrameA(useLinearReferenceFrameA),
+m_useOffsetForConstraintFrame(D6_USE_FRAME_OFFSET),
+m_flags(0),
+m_useSolveConstraintObsolete(D6_USE_OBSOLETE_METHOD)
+{
+ calculateTransforms();
+}
+
+
+
+btGeneric6DofConstraint::btGeneric6DofConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameB)
+ : btTypedConstraint(D6_CONSTRAINT_TYPE, getFixedBody(), rbB),
+ m_frameInB(frameInB),
+ m_useLinearReferenceFrameA(useLinearReferenceFrameB),
+ m_useOffsetForConstraintFrame(D6_USE_FRAME_OFFSET),
+ m_flags(0),
+ m_useSolveConstraintObsolete(false)
+{
+ ///not providing rigidbody A means implicitly using worldspace for body A
+ m_frameInA = rbB.getCenterOfMassTransform() * m_frameInB;
+ calculateTransforms();
+}
+
+
+
+
+#define GENERIC_D6_DISABLE_WARMSTARTING 1
+
+
+
+btScalar btGetMatrixElem(const btMatrix3x3& mat, int index);
+btScalar btGetMatrixElem(const btMatrix3x3& mat, int index)
+{
+ int i = index%3;
+ int j = index/3;
+ return mat[i][j];
+}
+
+
+
+///MatrixToEulerXYZ from http://www.geometrictools.com/LibFoundation/Mathematics/Wm4Matrix3.inl.html
+bool matrixToEulerXYZ(const btMatrix3x3& mat,btVector3& xyz);
+bool matrixToEulerXYZ(const btMatrix3x3& mat,btVector3& xyz)
+{
+ // // rot = cy*cz -cy*sz sy
+ // // cz*sx*sy+cx*sz cx*cz-sx*sy*sz -cy*sx
+ // // -cx*cz*sy+sx*sz cz*sx+cx*sy*sz cx*cy
+ //
+
+ btScalar fi = btGetMatrixElem(mat,2);
+ if (fi < btScalar(1.0f))
+ {
+ if (fi > btScalar(-1.0f))
+ {
+ xyz[0] = btAtan2(-btGetMatrixElem(mat,5),btGetMatrixElem(mat,8));
+ xyz[1] = btAsin(btGetMatrixElem(mat,2));
+ xyz[2] = btAtan2(-btGetMatrixElem(mat,1),btGetMatrixElem(mat,0));
+ return true;
+ }
+ else
+ {
+ // WARNING. Not unique. XA - ZA = -atan2(r10,r11)
+ xyz[0] = -btAtan2(btGetMatrixElem(mat,3),btGetMatrixElem(mat,4));
+ xyz[1] = -SIMD_HALF_PI;
+ xyz[2] = btScalar(0.0);
+ return false;
+ }
+ }
+ else
+ {
+ // WARNING. Not unique. XAngle + ZAngle = atan2(r10,r11)
+ xyz[0] = btAtan2(btGetMatrixElem(mat,3),btGetMatrixElem(mat,4));
+ xyz[1] = SIMD_HALF_PI;
+ xyz[2] = 0.0;
+ }
+ return false;
+}
+
+//////////////////////////// btRotationalLimitMotor ////////////////////////////////////
+
+int btRotationalLimitMotor::testLimitValue(btScalar test_value)
+{
+ if(m_loLimit>m_hiLimit)
+ {
+ m_currentLimit = 0;//Free from violation
+ return 0;
+ }
+ if (test_value < m_loLimit)
+ {
+ m_currentLimit = 1;//low limit violation
+ m_currentLimitError = test_value - m_loLimit;
+ if(m_currentLimitError>SIMD_PI)
+ m_currentLimitError-=SIMD_2_PI;
+ else if(m_currentLimitError<-SIMD_PI)
+ m_currentLimitError+=SIMD_2_PI;
+ return 1;
+ }
+ else if (test_value> m_hiLimit)
+ {
+ m_currentLimit = 2;//High limit violation
+ m_currentLimitError = test_value - m_hiLimit;
+ if(m_currentLimitError>SIMD_PI)
+ m_currentLimitError-=SIMD_2_PI;
+ else if(m_currentLimitError<-SIMD_PI)
+ m_currentLimitError+=SIMD_2_PI;
+ return 2;
+ };
+
+ m_currentLimit = 0;//Free from violation
+ return 0;
+
+}
+
+
+
+btScalar btRotationalLimitMotor::solveAngularLimits(
+ btScalar timeStep,btVector3& axis,btScalar jacDiagABInv,
+ btRigidBody * body0, btRigidBody * body1 )
+{
+ if (needApplyTorques()==false) return 0.0f;
+
+ btScalar target_velocity = m_targetVelocity;
+ btScalar maxMotorForce = m_maxMotorForce;
+
+ //current error correction
+ if (m_currentLimit!=0)
+ {
+ target_velocity = -m_stopERP*m_currentLimitError/(timeStep);
+ maxMotorForce = m_maxLimitForce;
+ }
+
+ maxMotorForce *= timeStep;
+
+ // current velocity difference
+
+ btVector3 angVelA = body0->getAngularVelocity();
+ btVector3 angVelB = body1->getAngularVelocity();
+
+ btVector3 vel_diff;
+ vel_diff = angVelA-angVelB;
+
+
+
+ btScalar rel_vel = axis.dot(vel_diff);
+
+ // correction velocity
+ btScalar motor_relvel = m_limitSoftness*(target_velocity - m_damping*rel_vel);
+
+
+ if ( motor_relvel < SIMD_EPSILON && motor_relvel > -SIMD_EPSILON )
+ {
+ return 0.0f;//no need for applying force
+ }
+
+
+ // correction impulse
+ btScalar unclippedMotorImpulse = (1+m_bounce)*motor_relvel*jacDiagABInv;
+
+ // clip correction impulse
+ btScalar clippedMotorImpulse;
+
+ ///@todo: should clip against accumulated impulse
+ if (unclippedMotorImpulse>0.0f)
+ {
+ clippedMotorImpulse = unclippedMotorImpulse > maxMotorForce? maxMotorForce: unclippedMotorImpulse;
+ }
+ else
+ {
+ clippedMotorImpulse = unclippedMotorImpulse < -maxMotorForce ? -maxMotorForce: unclippedMotorImpulse;
+ }
+
+
+ // sort with accumulated impulses
+ btScalar lo = btScalar(-BT_LARGE_FLOAT);
+ btScalar hi = btScalar(BT_LARGE_FLOAT);
+
+ btScalar oldaccumImpulse = m_accumulatedImpulse;
+ btScalar sum = oldaccumImpulse + clippedMotorImpulse;
+ m_accumulatedImpulse = sum > hi ? btScalar(0.) : sum < lo ? btScalar(0.) : sum;
+
+ clippedMotorImpulse = m_accumulatedImpulse - oldaccumImpulse;
+
+ btVector3 motorImp = clippedMotorImpulse * axis;
+
+ body0->applyTorqueImpulse(motorImp);
+ body1->applyTorqueImpulse(-motorImp);
+
+ return clippedMotorImpulse;
+
+
+}
+
+//////////////////////////// End btRotationalLimitMotor ////////////////////////////////////
+
+
+
+
+//////////////////////////// btTranslationalLimitMotor ////////////////////////////////////
+
+
+int btTranslationalLimitMotor::testLimitValue(int limitIndex, btScalar test_value)
+{
+ btScalar loLimit = m_lowerLimit[limitIndex];
+ btScalar hiLimit = m_upperLimit[limitIndex];
+ if(loLimit > hiLimit)
+ {
+ m_currentLimit[limitIndex] = 0;//Free from violation
+ m_currentLimitError[limitIndex] = btScalar(0.f);
+ return 0;
+ }
+
+ if (test_value < loLimit)
+ {
+ m_currentLimit[limitIndex] = 2;//low limit violation
+ m_currentLimitError[limitIndex] = test_value - loLimit;
+ return 2;
+ }
+ else if (test_value> hiLimit)
+ {
+ m_currentLimit[limitIndex] = 1;//High limit violation
+ m_currentLimitError[limitIndex] = test_value - hiLimit;
+ return 1;
+ };
+
+ m_currentLimit[limitIndex] = 0;//Free from violation
+ m_currentLimitError[limitIndex] = btScalar(0.f);
+ return 0;
+}
+
+
+
+btScalar btTranslationalLimitMotor::solveLinearAxis(
+ btScalar timeStep,
+ btScalar jacDiagABInv,
+ btRigidBody& body1,const btVector3 &pointInA,
+ btRigidBody& body2,const btVector3 &pointInB,
+ int limit_index,
+ const btVector3 & axis_normal_on_a,
+ const btVector3 & anchorPos)
+{
+
+ ///find relative velocity
+ // btVector3 rel_pos1 = pointInA - body1.getCenterOfMassPosition();
+ // btVector3 rel_pos2 = pointInB - body2.getCenterOfMassPosition();
+ btVector3 rel_pos1 = anchorPos - body1.getCenterOfMassPosition();
+ btVector3 rel_pos2 = anchorPos - body2.getCenterOfMassPosition();
+
+ btVector3 vel1 = body1.getVelocityInLocalPoint(rel_pos1);
+ btVector3 vel2 = body2.getVelocityInLocalPoint(rel_pos2);
+ btVector3 vel = vel1 - vel2;
+
+ btScalar rel_vel = axis_normal_on_a.dot(vel);
+
+
+
+ /// apply displacement correction
+
+ //positional error (zeroth order error)
+ btScalar depth = -(pointInA - pointInB).dot(axis_normal_on_a);
+ btScalar lo = btScalar(-BT_LARGE_FLOAT);
+ btScalar hi = btScalar(BT_LARGE_FLOAT);
+
+ btScalar minLimit = m_lowerLimit[limit_index];
+ btScalar maxLimit = m_upperLimit[limit_index];
+
+ //handle the limits
+ if (minLimit < maxLimit)
+ {
+ {
+ if (depth > maxLimit)
+ {
+ depth -= maxLimit;
+ lo = btScalar(0.);
+
+ }
+ else
+ {
+ if (depth < minLimit)
+ {
+ depth -= minLimit;
+ hi = btScalar(0.);
+ }
+ else
+ {
+ return 0.0f;
+ }
+ }
+ }
+ }
+
+ btScalar normalImpulse= m_limitSoftness*(m_restitution*depth/timeStep - m_damping*rel_vel) * jacDiagABInv;
+
+
+
+
+ btScalar oldNormalImpulse = m_accumulatedImpulse[limit_index];
+ btScalar sum = oldNormalImpulse + normalImpulse;
+ m_accumulatedImpulse[limit_index] = sum > hi ? btScalar(0.) : sum < lo ? btScalar(0.) : sum;
+ normalImpulse = m_accumulatedImpulse[limit_index] - oldNormalImpulse;
+
+ btVector3 impulse_vector = axis_normal_on_a * normalImpulse;
+ body1.applyImpulse( impulse_vector, rel_pos1);
+ body2.applyImpulse(-impulse_vector, rel_pos2);
+
+
+
+ return normalImpulse;
+}
+
+//////////////////////////// btTranslationalLimitMotor ////////////////////////////////////
+
+void btGeneric6DofConstraint::calculateAngleInfo()
+{
+ btMatrix3x3 relative_frame = m_calculatedTransformA.getBasis().inverse()*m_calculatedTransformB.getBasis();
+ matrixToEulerXYZ(relative_frame,m_calculatedAxisAngleDiff);
+ // in euler angle mode we do not actually constrain the angular velocity
+ // along the axes axis[0] and axis[2] (although we do use axis[1]) :
+ //
+ // to get constrain w2-w1 along ...not
+ // ------ --------------------- ------
+ // d(angle[0])/dt = 0 ax[1] x ax[2] ax[0]
+ // d(angle[1])/dt = 0 ax[1]
+ // d(angle[2])/dt = 0 ax[0] x ax[1] ax[2]
+ //
+ // constraining w2-w1 along an axis 'a' means that a'*(w2-w1)=0.
+ // to prove the result for angle[0], write the expression for angle[0] from
+ // GetInfo1 then take the derivative. to prove this for angle[2] it is
+ // easier to take the euler rate expression for d(angle[2])/dt with respect
+ // to the components of w and set that to 0.
+ btVector3 axis0 = m_calculatedTransformB.getBasis().getColumn(0);
+ btVector3 axis2 = m_calculatedTransformA.getBasis().getColumn(2);
+
+ m_calculatedAxis[1] = axis2.cross(axis0);
+ m_calculatedAxis[0] = m_calculatedAxis[1].cross(axis2);
+ m_calculatedAxis[2] = axis0.cross(m_calculatedAxis[1]);
+
+ m_calculatedAxis[0].normalize();
+ m_calculatedAxis[1].normalize();
+ m_calculatedAxis[2].normalize();
+
+}
+
+void btGeneric6DofConstraint::calculateTransforms()
+{
+ calculateTransforms(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform());
+}
+
+void btGeneric6DofConstraint::calculateTransforms(const btTransform& transA,const btTransform& transB)
+{
+ m_calculatedTransformA = transA * m_frameInA;
+ m_calculatedTransformB = transB * m_frameInB;
+ calculateLinearInfo();
+ calculateAngleInfo();
+ if(m_useOffsetForConstraintFrame)
+ { // get weight factors depending on masses
+ btScalar miA = getRigidBodyA().getInvMass();
+ btScalar miB = getRigidBodyB().getInvMass();
+ m_hasStaticBody = (miA < SIMD_EPSILON) || (miB < SIMD_EPSILON);
+ btScalar miS = miA + miB;
+ if(miS > btScalar(0.f))
+ {
+ m_factA = miB / miS;
+ }
+ else
+ {
+ m_factA = btScalar(0.5f);
+ }
+ m_factB = btScalar(1.0f) - m_factA;
+ }
+}
+
+
+
+void btGeneric6DofConstraint::buildLinearJacobian(
+ btJacobianEntry & jacLinear,const btVector3 & normalWorld,
+ const btVector3 & pivotAInW,const btVector3 & pivotBInW)
+{
+ new (&jacLinear) btJacobianEntry(
+ m_rbA.getCenterOfMassTransform().getBasis().transpose(),
+ m_rbB.getCenterOfMassTransform().getBasis().transpose(),
+ pivotAInW - m_rbA.getCenterOfMassPosition(),
+ pivotBInW - m_rbB.getCenterOfMassPosition(),
+ normalWorld,
+ m_rbA.getInvInertiaDiagLocal(),
+ m_rbA.getInvMass(),
+ m_rbB.getInvInertiaDiagLocal(),
+ m_rbB.getInvMass());
+}
+
+
+
+void btGeneric6DofConstraint::buildAngularJacobian(
+ btJacobianEntry & jacAngular,const btVector3 & jointAxisW)
+{
+ new (&jacAngular) btJacobianEntry(jointAxisW,
+ m_rbA.getCenterOfMassTransform().getBasis().transpose(),
+ m_rbB.getCenterOfMassTransform().getBasis().transpose(),
+ m_rbA.getInvInertiaDiagLocal(),
+ m_rbB.getInvInertiaDiagLocal());
+
+}
+
+
+
+bool btGeneric6DofConstraint::testAngularLimitMotor(int axis_index)
+{
+ btScalar angle = m_calculatedAxisAngleDiff[axis_index];
+ angle = btAdjustAngleToLimits(angle, m_angularLimits[axis_index].m_loLimit, m_angularLimits[axis_index].m_hiLimit);
+ m_angularLimits[axis_index].m_currentPosition = angle;
+ //test limits
+ m_angularLimits[axis_index].testLimitValue(angle);
+ return m_angularLimits[axis_index].needApplyTorques();
+}
+
+
+
+void btGeneric6DofConstraint::buildJacobian()
+{
+#ifndef __SPU__
+ if (m_useSolveConstraintObsolete)
+ {
+
+ // Clear accumulated impulses for the next simulation step
+ m_linearLimits.m_accumulatedImpulse.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
+ int i;
+ for(i = 0; i < 3; i++)
+ {
+ m_angularLimits[i].m_accumulatedImpulse = btScalar(0.);
+ }
+ //calculates transform
+ calculateTransforms(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform());
+
+ // const btVector3& pivotAInW = m_calculatedTransformA.getOrigin();
+ // const btVector3& pivotBInW = m_calculatedTransformB.getOrigin();
+ calcAnchorPos();
+ btVector3 pivotAInW = m_AnchorPos;
+ btVector3 pivotBInW = m_AnchorPos;
+
+ // not used here
+ // btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition();
+ // btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition();
+
+ btVector3 normalWorld;
+ //linear part
+ for (i=0;i<3;i++)
+ {
+ if (m_linearLimits.isLimited(i))
+ {
+ if (m_useLinearReferenceFrameA)
+ normalWorld = m_calculatedTransformA.getBasis().getColumn(i);
+ else
+ normalWorld = m_calculatedTransformB.getBasis().getColumn(i);
+
+ buildLinearJacobian(
+ m_jacLinear[i],normalWorld ,
+ pivotAInW,pivotBInW);
+
+ }
+ }
+
+ // angular part
+ for (i=0;i<3;i++)
+ {
+ //calculates error angle
+ if (testAngularLimitMotor(i))
+ {
+ normalWorld = this->getAxis(i);
+ // Create angular atom
+ buildAngularJacobian(m_jacAng[i],normalWorld);
+ }
+ }
+
+ }
+#endif //__SPU__
+
+}
+
+
+void btGeneric6DofConstraint::getInfo1 (btConstraintInfo1* info)
+{
+ if (m_useSolveConstraintObsolete)
+ {
+ info->m_numConstraintRows = 0;
+ info->nub = 0;
+ } else
+ {
+ //prepare constraint
+ calculateTransforms(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform());
+ info->m_numConstraintRows = 0;
+ info->nub = 6;
+ int i;
+ //test linear limits
+ for(i = 0; i < 3; i++)
+ {
+ if(m_linearLimits.needApplyForce(i))
+ {
+ info->m_numConstraintRows++;
+ info->nub--;
+ }
+ }
+ //test angular limits
+ for (i=0;i<3 ;i++ )
+ {
+ if(testAngularLimitMotor(i))
+ {
+ info->m_numConstraintRows++;
+ info->nub--;
+ }
+ }
+ }
+}
+
+void btGeneric6DofConstraint::getInfo1NonVirtual (btConstraintInfo1* info)
+{
+ if (m_useSolveConstraintObsolete)
+ {
+ info->m_numConstraintRows = 0;
+ info->nub = 0;
+ } else
+ {
+ //pre-allocate all 6
+ info->m_numConstraintRows = 6;
+ info->nub = 0;
+ }
+}
+
+
+void btGeneric6DofConstraint::getInfo2 (btConstraintInfo2* info)
+{
+ btAssert(!m_useSolveConstraintObsolete);
+
+ const btTransform& transA = m_rbA.getCenterOfMassTransform();
+ const btTransform& transB = m_rbB.getCenterOfMassTransform();
+ const btVector3& linVelA = m_rbA.getLinearVelocity();
+ const btVector3& linVelB = m_rbB.getLinearVelocity();
+ const btVector3& angVelA = m_rbA.getAngularVelocity();
+ const btVector3& angVelB = m_rbB.getAngularVelocity();
+
+ if(m_useOffsetForConstraintFrame)
+ { // for stability better to solve angular limits first
+ int row = setAngularLimits(info, 0,transA,transB,linVelA,linVelB,angVelA,angVelB);
+ setLinearLimits(info, row, transA,transB,linVelA,linVelB,angVelA,angVelB);
+ }
+ else
+ { // leave old version for compatibility
+ int row = setLinearLimits(info, 0, transA,transB,linVelA,linVelB,angVelA,angVelB);
+ setAngularLimits(info, row,transA,transB,linVelA,linVelB,angVelA,angVelB);
+ }
+
+}
+
+
+void btGeneric6DofConstraint::getInfo2NonVirtual (btConstraintInfo2* info, const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB)
+{
+
+ btAssert(!m_useSolveConstraintObsolete);
+ //prepare constraint
+ calculateTransforms(transA,transB);
+
+ int i;
+ for (i=0;i<3 ;i++ )
+ {
+ testAngularLimitMotor(i);
+ }
+
+ if(m_useOffsetForConstraintFrame)
+ { // for stability better to solve angular limits first
+ int row = setAngularLimits(info, 0,transA,transB,linVelA,linVelB,angVelA,angVelB);
+ setLinearLimits(info, row, transA,transB,linVelA,linVelB,angVelA,angVelB);
+ }
+ else
+ { // leave old version for compatibility
+ int row = setLinearLimits(info, 0, transA,transB,linVelA,linVelB,angVelA,angVelB);
+ setAngularLimits(info, row,transA,transB,linVelA,linVelB,angVelA,angVelB);
+ }
+}
+
+
+
+int btGeneric6DofConstraint::setLinearLimits(btConstraintInfo2* info, int row, const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB)
+{
+// int row = 0;
+ //solve linear limits
+ btRotationalLimitMotor limot;
+ for (int i=0;i<3 ;i++ )
+ {
+ if(m_linearLimits.needApplyForce(i))
+ { // re-use rotational motor code
+ limot.m_bounce = btScalar(0.f);
+ limot.m_currentLimit = m_linearLimits.m_currentLimit[i];
+ limot.m_currentPosition = m_linearLimits.m_currentLinearDiff[i];
+ limot.m_currentLimitError = m_linearLimits.m_currentLimitError[i];
+ limot.m_damping = m_linearLimits.m_damping;
+ limot.m_enableMotor = m_linearLimits.m_enableMotor[i];
+ limot.m_hiLimit = m_linearLimits.m_upperLimit[i];
+ limot.m_limitSoftness = m_linearLimits.m_limitSoftness;
+ limot.m_loLimit = m_linearLimits.m_lowerLimit[i];
+ limot.m_maxLimitForce = btScalar(0.f);
+ limot.m_maxMotorForce = m_linearLimits.m_maxMotorForce[i];
+ limot.m_targetVelocity = m_linearLimits.m_targetVelocity[i];
+ btVector3 axis = m_calculatedTransformA.getBasis().getColumn(i);
+ int flags = m_flags >> (i * BT_6DOF_FLAGS_AXIS_SHIFT);
+ limot.m_normalCFM = (flags & BT_6DOF_FLAGS_CFM_NORM) ? m_linearLimits.m_normalCFM[i] : info->cfm[0];
+ limot.m_stopCFM = (flags & BT_6DOF_FLAGS_CFM_STOP) ? m_linearLimits.m_stopCFM[i] : info->cfm[0];
+ limot.m_stopERP = (flags & BT_6DOF_FLAGS_ERP_STOP) ? m_linearLimits.m_stopERP[i] : info->erp;
+ if(m_useOffsetForConstraintFrame)
+ {
+ int indx1 = (i + 1) % 3;
+ int indx2 = (i + 2) % 3;
+ int rotAllowed = 1; // rotations around orthos to current axis
+ if(m_angularLimits[indx1].m_currentLimit && m_angularLimits[indx2].m_currentLimit)
+ {
+ rotAllowed = 0;
+ }
+ row += get_limit_motor_info2(&limot, transA,transB,linVelA,linVelB,angVelA,angVelB, info, row, axis, 0, rotAllowed);
+ }
+ else
+ {
+ row += get_limit_motor_info2(&limot, transA,transB,linVelA,linVelB,angVelA,angVelB, info, row, axis, 0);
+ }
+ }
+ }
+ return row;
+}
+
+
+
+int btGeneric6DofConstraint::setAngularLimits(btConstraintInfo2 *info, int row_offset, const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB)
+{
+ btGeneric6DofConstraint * d6constraint = this;
+ int row = row_offset;
+ //solve angular limits
+ for (int i=0;i<3 ;i++ )
+ {
+ if(d6constraint->getRotationalLimitMotor(i)->needApplyTorques())
+ {
+ btVector3 axis = d6constraint->getAxis(i);
+ int flags = m_flags >> ((i + 3) * BT_6DOF_FLAGS_AXIS_SHIFT);
+ if(!(flags & BT_6DOF_FLAGS_CFM_NORM))
+ {
+ m_angularLimits[i].m_normalCFM = info->cfm[0];
+ }
+ if(!(flags & BT_6DOF_FLAGS_CFM_STOP))
+ {
+ m_angularLimits[i].m_stopCFM = info->cfm[0];
+ }
+ if(!(flags & BT_6DOF_FLAGS_ERP_STOP))
+ {
+ m_angularLimits[i].m_stopERP = info->erp;
+ }
+ row += get_limit_motor_info2(d6constraint->getRotationalLimitMotor(i),
+ transA,transB,linVelA,linVelB,angVelA,angVelB, info,row,axis,1);
+ }
+ }
+
+ return row;
+}
+
+
+
+
+void btGeneric6DofConstraint::updateRHS(btScalar timeStep)
+{
+ (void)timeStep;
+
+}
+
+
+void btGeneric6DofConstraint::setFrames(const btTransform& frameA, const btTransform& frameB)
+{
+ m_frameInA = frameA;
+ m_frameInB = frameB;
+ buildJacobian();
+ calculateTransforms();
+}
+
+
+
+btVector3 btGeneric6DofConstraint::getAxis(int axis_index) const
+{
+ return m_calculatedAxis[axis_index];
+}
+
+
+btScalar btGeneric6DofConstraint::getRelativePivotPosition(int axisIndex) const
+{
+ return m_calculatedLinearDiff[axisIndex];
+}
+
+
+btScalar btGeneric6DofConstraint::getAngle(int axisIndex) const
+{
+ return m_calculatedAxisAngleDiff[axisIndex];
+}
+
+
+
+void btGeneric6DofConstraint::calcAnchorPos(void)
+{
+ btScalar imA = m_rbA.getInvMass();
+ btScalar imB = m_rbB.getInvMass();
+ btScalar weight;
+ if(imB == btScalar(0.0))
+ {
+ weight = btScalar(1.0);
+ }
+ else
+ {
+ weight = imA / (imA + imB);
+ }
+ const btVector3& pA = m_calculatedTransformA.getOrigin();
+ const btVector3& pB = m_calculatedTransformB.getOrigin();
+ m_AnchorPos = pA * weight + pB * (btScalar(1.0) - weight);
+ return;
+}
+
+
+
+void btGeneric6DofConstraint::calculateLinearInfo()
+{
+ m_calculatedLinearDiff = m_calculatedTransformB.getOrigin() - m_calculatedTransformA.getOrigin();
+ m_calculatedLinearDiff = m_calculatedTransformA.getBasis().inverse() * m_calculatedLinearDiff;
+ for(int i = 0; i < 3; i++)
+ {
+ m_linearLimits.m_currentLinearDiff[i] = m_calculatedLinearDiff[i];
+ m_linearLimits.testLimitValue(i, m_calculatedLinearDiff[i]);
+ }
+}
+
+
+
+int btGeneric6DofConstraint::get_limit_motor_info2(
+ btRotationalLimitMotor * limot,
+ const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB,
+ btConstraintInfo2 *info, int row, btVector3& ax1, int rotational,int rotAllowed)
+{
+ int srow = row * info->rowskip;
+ bool powered = limot->m_enableMotor;
+ int limit = limot->m_currentLimit;
+ if (powered || limit)
+ { // if the joint is powered, or has joint limits, add in the extra row
+ btScalar *J1 = rotational ? info->m_J1angularAxis : info->m_J1linearAxis;
+ btScalar *J2 = rotational ? info->m_J2angularAxis : info->m_J2linearAxis;
+ J1[srow+0] = ax1[0];
+ J1[srow+1] = ax1[1];
+ J1[srow+2] = ax1[2];
+
+ J2[srow+0] = -ax1[0];
+ J2[srow+1] = -ax1[1];
+ J2[srow+2] = -ax1[2];
+
+ if((!rotational))
+ {
+ if (m_useOffsetForConstraintFrame)
+ {
+ btVector3 tmpA, tmpB, relA, relB;
+ // get vector from bodyB to frameB in WCS
+ relB = m_calculatedTransformB.getOrigin() - transB.getOrigin();
+ // get its projection to constraint axis
+ btVector3 projB = ax1 * relB.dot(ax1);
+ // get vector directed from bodyB to constraint axis (and orthogonal to it)
+ btVector3 orthoB = relB - projB;
+ // same for bodyA
+ relA = m_calculatedTransformA.getOrigin() - transA.getOrigin();
+ btVector3 projA = ax1 * relA.dot(ax1);
+ btVector3 orthoA = relA - projA;
+ // get desired offset between frames A and B along constraint axis
+ btScalar desiredOffs = limot->m_currentPosition - limot->m_currentLimitError;
+ // desired vector from projection of center of bodyA to projection of center of bodyB to constraint axis
+ btVector3 totalDist = projA + ax1 * desiredOffs - projB;
+ // get offset vectors relA and relB
+ relA = orthoA + totalDist * m_factA;
+ relB = orthoB - totalDist * m_factB;
+ tmpA = relA.cross(ax1);
+ tmpB = relB.cross(ax1);
+ if(m_hasStaticBody && (!rotAllowed))
+ {
+ tmpA *= m_factA;
+ tmpB *= m_factB;
+ }
+ int i;
+ for (i=0; i<3; i++) info->m_J1angularAxis[srow+i] = tmpA[i];
+ for (i=0; i<3; i++) info->m_J2angularAxis[srow+i] = -tmpB[i];
+ } else
+ {
+ btVector3 ltd; // Linear Torque Decoupling vector
+ btVector3 c = m_calculatedTransformB.getOrigin() - transA.getOrigin();
+ ltd = c.cross(ax1);
+ info->m_J1angularAxis[srow+0] = ltd[0];
+ info->m_J1angularAxis[srow+1] = ltd[1];
+ info->m_J1angularAxis[srow+2] = ltd[2];
+
+ c = m_calculatedTransformB.getOrigin() - transB.getOrigin();
+ ltd = -c.cross(ax1);
+ info->m_J2angularAxis[srow+0] = ltd[0];
+ info->m_J2angularAxis[srow+1] = ltd[1];
+ info->m_J2angularAxis[srow+2] = ltd[2];
+ }
+ }
+ // if we're limited low and high simultaneously, the joint motor is
+ // ineffective
+ if (limit && (limot->m_loLimit == limot->m_hiLimit)) powered = false;
+ info->m_constraintError[srow] = btScalar(0.f);
+ if (powered)
+ {
+ info->cfm[srow] = limot->m_normalCFM;
+ if(!limit)
+ {
+ btScalar tag_vel = rotational ? limot->m_targetVelocity : -limot->m_targetVelocity;
+
+ btScalar mot_fact = getMotorFactor( limot->m_currentPosition,
+ limot->m_loLimit,
+ limot->m_hiLimit,
+ tag_vel,
+ info->fps * limot->m_stopERP);
+ info->m_constraintError[srow] += mot_fact * limot->m_targetVelocity;
+ info->m_lowerLimit[srow] = -limot->m_maxMotorForce;
+ info->m_upperLimit[srow] = limot->m_maxMotorForce;
+ }
+ }
+ if(limit)
+ {
+ btScalar k = info->fps * limot->m_stopERP;
+ if(!rotational)
+ {
+ info->m_constraintError[srow] += k * limot->m_currentLimitError;
+ }
+ else
+ {
+ info->m_constraintError[srow] += -k * limot->m_currentLimitError;
+ }
+ info->cfm[srow] = limot->m_stopCFM;
+ if (limot->m_loLimit == limot->m_hiLimit)
+ { // limited low and high simultaneously
+ info->m_lowerLimit[srow] = -SIMD_INFINITY;
+ info->m_upperLimit[srow] = SIMD_INFINITY;
+ }
+ else
+ {
+ if (limit == 1)
+ {
+ info->m_lowerLimit[srow] = 0;
+ info->m_upperLimit[srow] = SIMD_INFINITY;
+ }
+ else
+ {
+ info->m_lowerLimit[srow] = -SIMD_INFINITY;
+ info->m_upperLimit[srow] = 0;
+ }
+ // deal with bounce
+ if (limot->m_bounce > 0)
+ {
+ // calculate joint velocity
+ btScalar vel;
+ if (rotational)
+ {
+ vel = angVelA.dot(ax1);
+//make sure that if no body -> angVelB == zero vec
+// if (body1)
+ vel -= angVelB.dot(ax1);
+ }
+ else
+ {
+ vel = linVelA.dot(ax1);
+//make sure that if no body -> angVelB == zero vec
+// if (body1)
+ vel -= linVelB.dot(ax1);
+ }
+ // only apply bounce if the velocity is incoming, and if the
+ // resulting c[] exceeds what we already have.
+ if (limit == 1)
+ {
+ if (vel < 0)
+ {
+ btScalar newc = -limot->m_bounce* vel;
+ if (newc > info->m_constraintError[srow])
+ info->m_constraintError[srow] = newc;
+ }
+ }
+ else
+ {
+ if (vel > 0)
+ {
+ btScalar newc = -limot->m_bounce * vel;
+ if (newc < info->m_constraintError[srow])
+ info->m_constraintError[srow] = newc;
+ }
+ }
+ }
+ }
+ }
+ return 1;
+ }
+ else return 0;
+}
+
+
+
+
+
+
+ ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
+ ///If no axis is provided, it uses the default axis for this constraint.
+void btGeneric6DofConstraint::setParam(int num, btScalar value, int axis)
+{
+ if((axis >= 0) && (axis < 3))
+ {
+ switch(num)
+ {
+ case BT_CONSTRAINT_STOP_ERP :
+ m_linearLimits.m_stopERP[axis] = value;
+ m_flags |= BT_6DOF_FLAGS_ERP_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT);
+ break;
+ case BT_CONSTRAINT_STOP_CFM :
+ m_linearLimits.m_stopCFM[axis] = value;
+ m_flags |= BT_6DOF_FLAGS_CFM_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT);
+ break;
+ case BT_CONSTRAINT_CFM :
+ m_linearLimits.m_normalCFM[axis] = value;
+ m_flags |= BT_6DOF_FLAGS_CFM_NORM << (axis * BT_6DOF_FLAGS_AXIS_SHIFT);
+ break;
+ default :
+ btAssertConstrParams(0);
+ }
+ }
+ else if((axis >=3) && (axis < 6))
+ {
+ switch(num)
+ {
+ case BT_CONSTRAINT_STOP_ERP :
+ m_angularLimits[axis - 3].m_stopERP = value;
+ m_flags |= BT_6DOF_FLAGS_ERP_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT);
+ break;
+ case BT_CONSTRAINT_STOP_CFM :
+ m_angularLimits[axis - 3].m_stopCFM = value;
+ m_flags |= BT_6DOF_FLAGS_CFM_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT);
+ break;
+ case BT_CONSTRAINT_CFM :
+ m_angularLimits[axis - 3].m_normalCFM = value;
+ m_flags |= BT_6DOF_FLAGS_CFM_NORM << (axis * BT_6DOF_FLAGS_AXIS_SHIFT);
+ break;
+ default :
+ btAssertConstrParams(0);
+ }
+ }
+ else
+ {
+ btAssertConstrParams(0);
+ }
+}
+
+ ///return the local value of parameter
+btScalar btGeneric6DofConstraint::getParam(int num, int axis) const
+{
+ btScalar retVal = 0;
+ if((axis >= 0) && (axis < 3))
+ {
+ switch(num)
+ {
+ case BT_CONSTRAINT_STOP_ERP :
+ btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_ERP_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT)));
+ retVal = m_linearLimits.m_stopERP[axis];
+ break;
+ case BT_CONSTRAINT_STOP_CFM :
+ btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_CFM_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT)));
+ retVal = m_linearLimits.m_stopCFM[axis];
+ break;
+ case BT_CONSTRAINT_CFM :
+ btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_CFM_NORM << (axis * BT_6DOF_FLAGS_AXIS_SHIFT)));
+ retVal = m_linearLimits.m_normalCFM[axis];
+ break;
+ default :
+ btAssertConstrParams(0);
+ }
+ }
+ else if((axis >=3) && (axis < 6))
+ {
+ switch(num)
+ {
+ case BT_CONSTRAINT_STOP_ERP :
+ btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_ERP_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT)));
+ retVal = m_angularLimits[axis - 3].m_stopERP;
+ break;
+ case BT_CONSTRAINT_STOP_CFM :
+ btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_CFM_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT)));
+ retVal = m_angularLimits[axis - 3].m_stopCFM;
+ break;
+ case BT_CONSTRAINT_CFM :
+ btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_CFM_NORM << (axis * BT_6DOF_FLAGS_AXIS_SHIFT)));
+ retVal = m_angularLimits[axis - 3].m_normalCFM;
+ break;
+ default :
+ btAssertConstrParams(0);
+ }
+ }
+ else
+ {
+ btAssertConstrParams(0);
+ }
+ return retVal;
+}
+
+
+
+void btGeneric6DofConstraint::setAxis(const btVector3& axis1,const btVector3& axis2)
+{
+ btVector3 zAxis = axis1.normalized();
+ btVector3 yAxis = axis2.normalized();
+ btVector3 xAxis = yAxis.cross(zAxis); // we want right coordinate system
+
+ btTransform frameInW;
+ frameInW.setIdentity();
+ frameInW.getBasis().setValue( xAxis[0], yAxis[0], zAxis[0],
+ xAxis[1], yAxis[1], zAxis[1],
+ xAxis[2], yAxis[2], zAxis[2]);
+
+ // now get constraint frame in local coordinate systems
+ m_frameInA = m_rbA.getCenterOfMassTransform().inverse() * frameInW;
+ m_frameInB = m_rbB.getCenterOfMassTransform().inverse() * frameInW;
+
+ calculateTransforms();
+}
diff --git a/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h
new file mode 100644
index 0000000000..bea8629c32
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h
@@ -0,0 +1,647 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+/// 2009 March: btGeneric6DofConstraint refactored by Roman Ponomarev
+/// Added support for generic constraint solver through getInfo1/getInfo2 methods
+
+/*
+2007-09-09
+btGeneric6DofConstraint Refactored by Francisco Le?n
+email: projectileman@yahoo.com
+http://gimpact.sf.net
+*/
+
+
+#ifndef BT_GENERIC_6DOF_CONSTRAINT_H
+#define BT_GENERIC_6DOF_CONSTRAINT_H
+
+#include "LinearMath/btVector3.h"
+#include "btJacobianEntry.h"
+#include "btTypedConstraint.h"
+
+class btRigidBody;
+
+
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define btGeneric6DofConstraintData2 btGeneric6DofConstraintDoubleData2
+#define btGeneric6DofConstraintDataName "btGeneric6DofConstraintDoubleData2"
+#else
+#define btGeneric6DofConstraintData2 btGeneric6DofConstraintData
+#define btGeneric6DofConstraintDataName "btGeneric6DofConstraintData"
+#endif //BT_USE_DOUBLE_PRECISION
+
+
+//! Rotation Limit structure for generic joints
+class btRotationalLimitMotor
+{
+public:
+ //! limit_parameters
+ //!@{
+ btScalar m_loLimit;//!< joint limit
+ btScalar m_hiLimit;//!< joint limit
+ btScalar m_targetVelocity;//!< target motor velocity
+ btScalar m_maxMotorForce;//!< max force on motor
+ btScalar m_maxLimitForce;//!< max force on limit
+ btScalar m_damping;//!< Damping.
+ btScalar m_limitSoftness;//! Relaxation factor
+ btScalar m_normalCFM;//!< Constraint force mixing factor
+ btScalar m_stopERP;//!< Error tolerance factor when joint is at limit
+ btScalar m_stopCFM;//!< Constraint force mixing factor when joint is at limit
+ btScalar m_bounce;//!< restitution factor
+ bool m_enableMotor;
+
+ //!@}
+
+ //! temp_variables
+ //!@{
+ btScalar m_currentLimitError;//! How much is violated this limit
+ btScalar m_currentPosition; //! current value of angle
+ int m_currentLimit;//!< 0=free, 1=at lo limit, 2=at hi limit
+ btScalar m_accumulatedImpulse;
+ //!@}
+
+ btRotationalLimitMotor()
+ {
+ m_accumulatedImpulse = 0.f;
+ m_targetVelocity = 0;
+ m_maxMotorForce = 0.1f;
+ m_maxLimitForce = 300.0f;
+ m_loLimit = 1.0f;
+ m_hiLimit = -1.0f;
+ m_normalCFM = 0.f;
+ m_stopERP = 0.2f;
+ m_stopCFM = 0.f;
+ m_bounce = 0.0f;
+ m_damping = 1.0f;
+ m_limitSoftness = 0.5f;
+ m_currentLimit = 0;
+ m_currentLimitError = 0;
+ m_enableMotor = false;
+ }
+
+ btRotationalLimitMotor(const btRotationalLimitMotor & limot)
+ {
+ m_targetVelocity = limot.m_targetVelocity;
+ m_maxMotorForce = limot.m_maxMotorForce;
+ m_limitSoftness = limot.m_limitSoftness;
+ m_loLimit = limot.m_loLimit;
+ m_hiLimit = limot.m_hiLimit;
+ m_normalCFM = limot.m_normalCFM;
+ m_stopERP = limot.m_stopERP;
+ m_stopCFM = limot.m_stopCFM;
+ m_bounce = limot.m_bounce;
+ m_currentLimit = limot.m_currentLimit;
+ m_currentLimitError = limot.m_currentLimitError;
+ m_enableMotor = limot.m_enableMotor;
+ }
+
+
+
+ //! Is limited
+ bool isLimited() const
+ {
+ if(m_loLimit > m_hiLimit) return false;
+ return true;
+ }
+
+ //! Need apply correction
+ bool needApplyTorques() const
+ {
+ if(m_currentLimit == 0 && m_enableMotor == false) return false;
+ return true;
+ }
+
+ //! calculates error
+ /*!
+ calculates m_currentLimit and m_currentLimitError.
+ */
+ int testLimitValue(btScalar test_value);
+
+ //! apply the correction impulses for two bodies
+ btScalar solveAngularLimits(btScalar timeStep,btVector3& axis, btScalar jacDiagABInv,btRigidBody * body0, btRigidBody * body1);
+
+};
+
+
+
+class btTranslationalLimitMotor
+{
+public:
+ btVector3 m_lowerLimit;//!< the constraint lower limits
+ btVector3 m_upperLimit;//!< the constraint upper limits
+ btVector3 m_accumulatedImpulse;
+ //! Linear_Limit_parameters
+ //!@{
+ btScalar m_limitSoftness;//!< Softness for linear limit
+ btScalar m_damping;//!< Damping for linear limit
+ btScalar m_restitution;//! Bounce parameter for linear limit
+ btVector3 m_normalCFM;//!< Constraint force mixing factor
+ btVector3 m_stopERP;//!< Error tolerance factor when joint is at limit
+ btVector3 m_stopCFM;//!< Constraint force mixing factor when joint is at limit
+ //!@}
+ bool m_enableMotor[3];
+ btVector3 m_targetVelocity;//!< target motor velocity
+ btVector3 m_maxMotorForce;//!< max force on motor
+ btVector3 m_currentLimitError;//! How much is violated this limit
+ btVector3 m_currentLinearDiff;//! Current relative offset of constraint frames
+ int m_currentLimit[3];//!< 0=free, 1=at lower limit, 2=at upper limit
+
+ btTranslationalLimitMotor()
+ {
+ m_lowerLimit.setValue(0.f,0.f,0.f);
+ m_upperLimit.setValue(0.f,0.f,0.f);
+ m_accumulatedImpulse.setValue(0.f,0.f,0.f);
+ m_normalCFM.setValue(0.f, 0.f, 0.f);
+ m_stopERP.setValue(0.2f, 0.2f, 0.2f);
+ m_stopCFM.setValue(0.f, 0.f, 0.f);
+
+ m_limitSoftness = 0.7f;
+ m_damping = btScalar(1.0f);
+ m_restitution = btScalar(0.5f);
+ for(int i=0; i < 3; i++)
+ {
+ m_enableMotor[i] = false;
+ m_targetVelocity[i] = btScalar(0.f);
+ m_maxMotorForce[i] = btScalar(0.f);
+ }
+ }
+
+ btTranslationalLimitMotor(const btTranslationalLimitMotor & other )
+ {
+ m_lowerLimit = other.m_lowerLimit;
+ m_upperLimit = other.m_upperLimit;
+ m_accumulatedImpulse = other.m_accumulatedImpulse;
+
+ m_limitSoftness = other.m_limitSoftness ;
+ m_damping = other.m_damping;
+ m_restitution = other.m_restitution;
+ m_normalCFM = other.m_normalCFM;
+ m_stopERP = other.m_stopERP;
+ m_stopCFM = other.m_stopCFM;
+
+ for(int i=0; i < 3; i++)
+ {
+ m_enableMotor[i] = other.m_enableMotor[i];
+ m_targetVelocity[i] = other.m_targetVelocity[i];
+ m_maxMotorForce[i] = other.m_maxMotorForce[i];
+ }
+ }
+
+ //! Test limit
+ /*!
+ - free means upper < lower,
+ - locked means upper == lower
+ - limited means upper > lower
+ - limitIndex: first 3 are linear, next 3 are angular
+ */
+ inline bool isLimited(int limitIndex) const
+ {
+ return (m_upperLimit[limitIndex] >= m_lowerLimit[limitIndex]);
+ }
+ inline bool needApplyForce(int limitIndex) const
+ {
+ if(m_currentLimit[limitIndex] == 0 && m_enableMotor[limitIndex] == false) return false;
+ return true;
+ }
+ int testLimitValue(int limitIndex, btScalar test_value);
+
+
+ btScalar solveLinearAxis(
+ btScalar timeStep,
+ btScalar jacDiagABInv,
+ btRigidBody& body1,const btVector3 &pointInA,
+ btRigidBody& body2,const btVector3 &pointInB,
+ int limit_index,
+ const btVector3 & axis_normal_on_a,
+ const btVector3 & anchorPos);
+
+
+};
+
+enum bt6DofFlags
+{
+ BT_6DOF_FLAGS_CFM_NORM = 1,
+ BT_6DOF_FLAGS_CFM_STOP = 2,
+ BT_6DOF_FLAGS_ERP_STOP = 4
+};
+#define BT_6DOF_FLAGS_AXIS_SHIFT 3 // bits per axis
+
+
+/// btGeneric6DofConstraint between two rigidbodies each with a pivotpoint that descibes the axis location in local space
+/*!
+btGeneric6DofConstraint can leave any of the 6 degree of freedom 'free' or 'locked'.
+currently this limit supports rotational motors<br>
+<ul>
+<li> For Linear limits, use btGeneric6DofConstraint.setLinearUpperLimit, btGeneric6DofConstraint.setLinearLowerLimit. You can set the parameters with the btTranslationalLimitMotor structure accsesible through the btGeneric6DofConstraint.getTranslationalLimitMotor method.
+At this moment translational motors are not supported. May be in the future. </li>
+
+<li> For Angular limits, use the btRotationalLimitMotor structure for configuring the limit.
+This is accessible through btGeneric6DofConstraint.getLimitMotor method,
+This brings support for limit parameters and motors. </li>
+
+<li> Angulars limits have these possible ranges:
+<table border=1 >
+<tr>
+ <td><b>AXIS</b></td>
+ <td><b>MIN ANGLE</b></td>
+ <td><b>MAX ANGLE</b></td>
+</tr><tr>
+ <td>X</td>
+ <td>-PI</td>
+ <td>PI</td>
+</tr><tr>
+ <td>Y</td>
+ <td>-PI/2</td>
+ <td>PI/2</td>
+</tr><tr>
+ <td>Z</td>
+ <td>-PI</td>
+ <td>PI</td>
+</tr>
+</table>
+</li>
+</ul>
+
+*/
+ATTRIBUTE_ALIGNED16(class) btGeneric6DofConstraint : public btTypedConstraint
+{
+protected:
+
+ //! relative_frames
+ //!@{
+ btTransform m_frameInA;//!< the constraint space w.r.t body A
+ btTransform m_frameInB;//!< the constraint space w.r.t body B
+ //!@}
+
+ //! Jacobians
+ //!@{
+ btJacobianEntry m_jacLinear[3];//!< 3 orthogonal linear constraints
+ btJacobianEntry m_jacAng[3];//!< 3 orthogonal angular constraints
+ //!@}
+
+ //! Linear_Limit_parameters
+ //!@{
+ btTranslationalLimitMotor m_linearLimits;
+ //!@}
+
+
+ //! hinge_parameters
+ //!@{
+ btRotationalLimitMotor m_angularLimits[3];
+ //!@}
+
+
+protected:
+ //! temporal variables
+ //!@{
+ btScalar m_timeStep;
+ btTransform m_calculatedTransformA;
+ btTransform m_calculatedTransformB;
+ btVector3 m_calculatedAxisAngleDiff;
+ btVector3 m_calculatedAxis[3];
+ btVector3 m_calculatedLinearDiff;
+ btScalar m_factA;
+ btScalar m_factB;
+ bool m_hasStaticBody;
+
+ btVector3 m_AnchorPos; // point betwen pivots of bodies A and B to solve linear axes
+
+ bool m_useLinearReferenceFrameA;
+ bool m_useOffsetForConstraintFrame;
+
+ int m_flags;
+
+ //!@}
+
+ btGeneric6DofConstraint& operator=(btGeneric6DofConstraint& other)
+ {
+ btAssert(0);
+ (void) other;
+ return *this;
+ }
+
+
+ int setAngularLimits(btConstraintInfo2 *info, int row_offset,const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB);
+
+ int setLinearLimits(btConstraintInfo2 *info, int row, const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB);
+
+ void buildLinearJacobian(
+ btJacobianEntry & jacLinear,const btVector3 & normalWorld,
+ const btVector3 & pivotAInW,const btVector3 & pivotBInW);
+
+ void buildAngularJacobian(btJacobianEntry & jacAngular,const btVector3 & jointAxisW);
+
+ // tests linear limits
+ void calculateLinearInfo();
+
+ //! calcs the euler angles between the two bodies.
+ void calculateAngleInfo();
+
+
+
+public:
+
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ ///for backwards compatibility during the transition to 'getInfo/getInfo2'
+ bool m_useSolveConstraintObsolete;
+
+ btGeneric6DofConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ,bool useLinearReferenceFrameA);
+ btGeneric6DofConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameB);
+
+ //! Calcs global transform of the offsets
+ /*!
+ Calcs the global transform for the joint offset for body A an B, and also calcs the agle differences between the bodies.
+ \sa btGeneric6DofConstraint.getCalculatedTransformA , btGeneric6DofConstraint.getCalculatedTransformB, btGeneric6DofConstraint.calculateAngleInfo
+ */
+ void calculateTransforms(const btTransform& transA,const btTransform& transB);
+
+ void calculateTransforms();
+
+ //! Gets the global transform of the offset for body A
+ /*!
+ \sa btGeneric6DofConstraint.getFrameOffsetA, btGeneric6DofConstraint.getFrameOffsetB, btGeneric6DofConstraint.calculateAngleInfo.
+ */
+ const btTransform & getCalculatedTransformA() const
+ {
+ return m_calculatedTransformA;
+ }
+
+ //! Gets the global transform of the offset for body B
+ /*!
+ \sa btGeneric6DofConstraint.getFrameOffsetA, btGeneric6DofConstraint.getFrameOffsetB, btGeneric6DofConstraint.calculateAngleInfo.
+ */
+ const btTransform & getCalculatedTransformB() const
+ {
+ return m_calculatedTransformB;
+ }
+
+ const btTransform & getFrameOffsetA() const
+ {
+ return m_frameInA;
+ }
+
+ const btTransform & getFrameOffsetB() const
+ {
+ return m_frameInB;
+ }
+
+
+ btTransform & getFrameOffsetA()
+ {
+ return m_frameInA;
+ }
+
+ btTransform & getFrameOffsetB()
+ {
+ return m_frameInB;
+ }
+
+
+ //! performs Jacobian calculation, and also calculates angle differences and axis
+ virtual void buildJacobian();
+
+ virtual void getInfo1 (btConstraintInfo1* info);
+
+ void getInfo1NonVirtual (btConstraintInfo1* info);
+
+ virtual void getInfo2 (btConstraintInfo2* info);
+
+ void getInfo2NonVirtual (btConstraintInfo2* info,const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB);
+
+
+ void updateRHS(btScalar timeStep);
+
+ //! Get the rotation axis in global coordinates
+ /*!
+ \pre btGeneric6DofConstraint.buildJacobian must be called previously.
+ */
+ btVector3 getAxis(int axis_index) const;
+
+ //! Get the relative Euler angle
+ /*!
+ \pre btGeneric6DofConstraint::calculateTransforms() must be called previously.
+ */
+ btScalar getAngle(int axis_index) const;
+
+ //! Get the relative position of the constraint pivot
+ /*!
+ \pre btGeneric6DofConstraint::calculateTransforms() must be called previously.
+ */
+ btScalar getRelativePivotPosition(int axis_index) const;
+
+ void setFrames(const btTransform & frameA, const btTransform & frameB);
+
+ //! Test angular limit.
+ /*!
+ Calculates angular correction and returns true if limit needs to be corrected.
+ \pre btGeneric6DofConstraint::calculateTransforms() must be called previously.
+ */
+ bool testAngularLimitMotor(int axis_index);
+
+ void setLinearLowerLimit(const btVector3& linearLower)
+ {
+ m_linearLimits.m_lowerLimit = linearLower;
+ }
+
+ void getLinearLowerLimit(btVector3& linearLower) const
+ {
+ linearLower = m_linearLimits.m_lowerLimit;
+ }
+
+ void setLinearUpperLimit(const btVector3& linearUpper)
+ {
+ m_linearLimits.m_upperLimit = linearUpper;
+ }
+
+ void getLinearUpperLimit(btVector3& linearUpper) const
+ {
+ linearUpper = m_linearLimits.m_upperLimit;
+ }
+
+ void setAngularLowerLimit(const btVector3& angularLower)
+ {
+ for(int i = 0; i < 3; i++)
+ m_angularLimits[i].m_loLimit = btNormalizeAngle(angularLower[i]);
+ }
+
+ void getAngularLowerLimit(btVector3& angularLower) const
+ {
+ for(int i = 0; i < 3; i++)
+ angularLower[i] = m_angularLimits[i].m_loLimit;
+ }
+
+ void setAngularUpperLimit(const btVector3& angularUpper)
+ {
+ for(int i = 0; i < 3; i++)
+ m_angularLimits[i].m_hiLimit = btNormalizeAngle(angularUpper[i]);
+ }
+
+ void getAngularUpperLimit(btVector3& angularUpper) const
+ {
+ for(int i = 0; i < 3; i++)
+ angularUpper[i] = m_angularLimits[i].m_hiLimit;
+ }
+
+ //! Retrieves the angular limit informacion
+ btRotationalLimitMotor * getRotationalLimitMotor(int index)
+ {
+ return &m_angularLimits[index];
+ }
+
+ //! Retrieves the limit informacion
+ btTranslationalLimitMotor * getTranslationalLimitMotor()
+ {
+ return &m_linearLimits;
+ }
+
+ //first 3 are linear, next 3 are angular
+ void setLimit(int axis, btScalar lo, btScalar hi)
+ {
+ if(axis<3)
+ {
+ m_linearLimits.m_lowerLimit[axis] = lo;
+ m_linearLimits.m_upperLimit[axis] = hi;
+ }
+ else
+ {
+ lo = btNormalizeAngle(lo);
+ hi = btNormalizeAngle(hi);
+ m_angularLimits[axis-3].m_loLimit = lo;
+ m_angularLimits[axis-3].m_hiLimit = hi;
+ }
+ }
+
+ //! Test limit
+ /*!
+ - free means upper < lower,
+ - locked means upper == lower
+ - limited means upper > lower
+ - limitIndex: first 3 are linear, next 3 are angular
+ */
+ bool isLimited(int limitIndex) const
+ {
+ if(limitIndex<3)
+ {
+ return m_linearLimits.isLimited(limitIndex);
+
+ }
+ return m_angularLimits[limitIndex-3].isLimited();
+ }
+
+ virtual void calcAnchorPos(void); // overridable
+
+ int get_limit_motor_info2( btRotationalLimitMotor * limot,
+ const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB,
+ btConstraintInfo2 *info, int row, btVector3& ax1, int rotational, int rotAllowed = false);
+
+ // access for UseFrameOffset
+ bool getUseFrameOffset() const { return m_useOffsetForConstraintFrame; }
+ void setUseFrameOffset(bool frameOffsetOnOff) { m_useOffsetForConstraintFrame = frameOffsetOnOff; }
+
+ bool getUseLinearReferenceFrameA() const { return m_useLinearReferenceFrameA; }
+ void setUseLinearReferenceFrameA(bool linearReferenceFrameA) { m_useLinearReferenceFrameA = linearReferenceFrameA; }
+
+ ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
+ ///If no axis is provided, it uses the default axis for this constraint.
+ virtual void setParam(int num, btScalar value, int axis = -1);
+ ///return the local value of parameter
+ virtual btScalar getParam(int num, int axis = -1) const;
+
+ void setAxis( const btVector3& axis1, const btVector3& axis2);
+
+ virtual int getFlags() const
+ {
+ return m_flags;
+ }
+
+ virtual int calculateSerializeBufferSize() const;
+
+ ///fills the dataBuffer and returns the struct name (and 0 on failure)
+ virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
+
+
+};
+
+
+struct btGeneric6DofConstraintData
+{
+ btTypedConstraintData m_typeConstraintData;
+ btTransformFloatData m_rbAFrame; // constraint axii. Assumes z is hinge axis.
+ btTransformFloatData m_rbBFrame;
+
+ btVector3FloatData m_linearUpperLimit;
+ btVector3FloatData m_linearLowerLimit;
+
+ btVector3FloatData m_angularUpperLimit;
+ btVector3FloatData m_angularLowerLimit;
+
+ int m_useLinearReferenceFrameA;
+ int m_useOffsetForConstraintFrame;
+};
+
+struct btGeneric6DofConstraintDoubleData2
+{
+ btTypedConstraintDoubleData m_typeConstraintData;
+ btTransformDoubleData m_rbAFrame; // constraint axii. Assumes z is hinge axis.
+ btTransformDoubleData m_rbBFrame;
+
+ btVector3DoubleData m_linearUpperLimit;
+ btVector3DoubleData m_linearLowerLimit;
+
+ btVector3DoubleData m_angularUpperLimit;
+ btVector3DoubleData m_angularLowerLimit;
+
+ int m_useLinearReferenceFrameA;
+ int m_useOffsetForConstraintFrame;
+};
+
+SIMD_FORCE_INLINE int btGeneric6DofConstraint::calculateSerializeBufferSize() const
+{
+ return sizeof(btGeneric6DofConstraintData2);
+}
+
+ ///fills the dataBuffer and returns the struct name (and 0 on failure)
+SIMD_FORCE_INLINE const char* btGeneric6DofConstraint::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+
+ btGeneric6DofConstraintData2* dof = (btGeneric6DofConstraintData2*)dataBuffer;
+ btTypedConstraint::serialize(&dof->m_typeConstraintData,serializer);
+
+ m_frameInA.serialize(dof->m_rbAFrame);
+ m_frameInB.serialize(dof->m_rbBFrame);
+
+
+ int i;
+ for (i=0;i<3;i++)
+ {
+ dof->m_angularLowerLimit.m_floats[i] = m_angularLimits[i].m_loLimit;
+ dof->m_angularUpperLimit.m_floats[i] = m_angularLimits[i].m_hiLimit;
+ dof->m_linearLowerLimit.m_floats[i] = m_linearLimits.m_lowerLimit[i];
+ dof->m_linearUpperLimit.m_floats[i] = m_linearLimits.m_upperLimit[i];
+ }
+
+ dof->m_useLinearReferenceFrameA = m_useLinearReferenceFrameA? 1 : 0;
+ dof->m_useOffsetForConstraintFrame = m_useOffsetForConstraintFrame ? 1 : 0;
+
+ return btGeneric6DofConstraintDataName;
+}
+
+
+
+
+
+#endif //BT_GENERIC_6DOF_CONSTRAINT_H
diff --git a/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.cpp b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.cpp
new file mode 100644
index 0000000000..f0976ee493
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.cpp
@@ -0,0 +1,1172 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+/*
+2014 May: btGeneric6DofSpring2Constraint is created from the original (2.82.2712) btGeneric6DofConstraint by Gabor Puhr and Tamas Umenhoffer
+Pros:
+- Much more accurate and stable in a lot of situation. (Especially when a sleeping chain of RBs connected with 6dof2 is pulled)
+- Stable and accurate spring with minimal energy loss that works with all of the solvers. (latter is not true for the original 6dof spring)
+- Servo motor functionality
+- Much more accurate bouncing. 0 really means zero bouncing (not true for the original 6odf) and there is only a minimal energy loss when the value is 1 (because of the solvers' precision)
+- Rotation order for the Euler system can be set. (One axis' freedom is still limited to pi/2)
+
+Cons:
+- It is slower than the original 6dof. There is no exact ratio, but half speed is a good estimation. (with PGS)
+- At bouncing the correct velocity is calculated, but not the correct position. (it is because of the solver can correct position or velocity, but not both.)
+*/
+
+/// 2009 March: btGeneric6DofConstraint refactored by Roman Ponomarev
+/// Added support for generic constraint solver through getInfo1/getInfo2 methods
+
+/*
+2007-09-09
+btGeneric6DofConstraint Refactored by Francisco Le?n
+email: projectileman@yahoo.com
+http://gimpact.sf.net
+*/
+
+
+
+#include "btGeneric6DofSpring2Constraint.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "LinearMath/btTransformUtil.h"
+#include <new>
+
+
+
+btGeneric6DofSpring2Constraint::btGeneric6DofSpring2Constraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, RotateOrder rotOrder)
+ : btTypedConstraint(D6_SPRING_2_CONSTRAINT_TYPE, rbA, rbB)
+ , m_frameInA(frameInA)
+ , m_frameInB(frameInB)
+ , m_rotateOrder(rotOrder)
+ , m_flags(0)
+{
+ calculateTransforms();
+}
+
+
+btGeneric6DofSpring2Constraint::btGeneric6DofSpring2Constraint(btRigidBody& rbB, const btTransform& frameInB, RotateOrder rotOrder)
+ : btTypedConstraint(D6_SPRING_2_CONSTRAINT_TYPE, getFixedBody(), rbB)
+ , m_frameInB(frameInB)
+ , m_rotateOrder(rotOrder)
+ , m_flags(0)
+{
+ ///not providing rigidbody A means implicitly using worldspace for body A
+ m_frameInA = rbB.getCenterOfMassTransform() * m_frameInB;
+ calculateTransforms();
+}
+
+
+btScalar btGeneric6DofSpring2Constraint::btGetMatrixElem(const btMatrix3x3& mat, int index)
+{
+ int i = index%3;
+ int j = index/3;
+ return mat[i][j];
+}
+
+// MatrixToEulerXYZ from http://www.geometrictools.com/LibFoundation/Mathematics/Wm4Matrix3.inl.html
+
+bool btGeneric6DofSpring2Constraint::matrixToEulerXYZ(const btMatrix3x3& mat,btVector3& xyz)
+{
+ // rot = cy*cz -cy*sz sy
+ // cz*sx*sy+cx*sz cx*cz-sx*sy*sz -cy*sx
+ // -cx*cz*sy+sx*sz cz*sx+cx*sy*sz cx*cy
+
+ btScalar fi = btGetMatrixElem(mat,2);
+ if (fi < btScalar(1.0f))
+ {
+ if (fi > btScalar(-1.0f))
+ {
+ xyz[0] = btAtan2(-btGetMatrixElem(mat,5),btGetMatrixElem(mat,8));
+ xyz[1] = btAsin(btGetMatrixElem(mat,2));
+ xyz[2] = btAtan2(-btGetMatrixElem(mat,1),btGetMatrixElem(mat,0));
+ return true;
+ }
+ else
+ {
+ // WARNING. Not unique. XA - ZA = -atan2(r10,r11)
+ xyz[0] = -btAtan2(btGetMatrixElem(mat,3),btGetMatrixElem(mat,4));
+ xyz[1] = -SIMD_HALF_PI;
+ xyz[2] = btScalar(0.0);
+ return false;
+ }
+ }
+ else
+ {
+ // WARNING. Not unique. XAngle + ZAngle = atan2(r10,r11)
+ xyz[0] = btAtan2(btGetMatrixElem(mat,3),btGetMatrixElem(mat,4));
+ xyz[1] = SIMD_HALF_PI;
+ xyz[2] = 0.0;
+ }
+ return false;
+}
+
+bool btGeneric6DofSpring2Constraint::matrixToEulerXZY(const btMatrix3x3& mat,btVector3& xyz)
+{
+ // rot = cy*cz -sz sy*cz
+ // cy*cx*sz+sx*sy cx*cz sy*cx*sz-cy*sx
+ // cy*sx*sz-cx*sy sx*cz sy*sx*sz+cx*cy
+
+ btScalar fi = btGetMatrixElem(mat,1);
+ if (fi < btScalar(1.0f))
+ {
+ if (fi > btScalar(-1.0f))
+ {
+ xyz[0] = btAtan2(btGetMatrixElem(mat,7),btGetMatrixElem(mat,4));
+ xyz[1] = btAtan2(btGetMatrixElem(mat,2),btGetMatrixElem(mat,0));
+ xyz[2] = btAsin(-btGetMatrixElem(mat,1));
+ return true;
+ }
+ else
+ {
+ xyz[0] = -btAtan2(-btGetMatrixElem(mat,6),btGetMatrixElem(mat,8));
+ xyz[1] = btScalar(0.0);
+ xyz[2] = SIMD_HALF_PI;
+ return false;
+ }
+ }
+ else
+ {
+ xyz[0] = btAtan2(-btGetMatrixElem(mat,6),btGetMatrixElem(mat,8));
+ xyz[1] = 0.0;
+ xyz[2] = -SIMD_HALF_PI;
+ }
+ return false;
+}
+
+bool btGeneric6DofSpring2Constraint::matrixToEulerYXZ(const btMatrix3x3& mat,btVector3& xyz)
+{
+ // rot = cy*cz+sy*sx*sz cz*sy*sx-cy*sz cx*sy
+ // cx*sz cx*cz -sx
+ // cy*sx*sz-cz*sy sy*sz+cy*cz*sx cy*cx
+
+ btScalar fi = btGetMatrixElem(mat,5);
+ if (fi < btScalar(1.0f))
+ {
+ if (fi > btScalar(-1.0f))
+ {
+ xyz[0] = btAsin(-btGetMatrixElem(mat,5));
+ xyz[1] = btAtan2(btGetMatrixElem(mat,2),btGetMatrixElem(mat,8));
+ xyz[2] = btAtan2(btGetMatrixElem(mat,3),btGetMatrixElem(mat,4));
+ return true;
+ }
+ else
+ {
+ xyz[0] = SIMD_HALF_PI;
+ xyz[1] = -btAtan2(-btGetMatrixElem(mat,1),btGetMatrixElem(mat,0));
+ xyz[2] = btScalar(0.0);
+ return false;
+ }
+ }
+ else
+ {
+ xyz[0] = -SIMD_HALF_PI;
+ xyz[1] = btAtan2(-btGetMatrixElem(mat,1),btGetMatrixElem(mat,0));
+ xyz[2] = 0.0;
+ }
+ return false;
+}
+
+bool btGeneric6DofSpring2Constraint::matrixToEulerYZX(const btMatrix3x3& mat,btVector3& xyz)
+{
+ // rot = cy*cz sy*sx-cy*cx*sz cx*sy+cy*sz*sx
+ // sz cz*cx -cz*sx
+ // -cz*sy cy*sx+cx*sy*sz cy*cx-sy*sz*sx
+
+ btScalar fi = btGetMatrixElem(mat,3);
+ if (fi < btScalar(1.0f))
+ {
+ if (fi > btScalar(-1.0f))
+ {
+ xyz[0] = btAtan2(-btGetMatrixElem(mat,5),btGetMatrixElem(mat,4));
+ xyz[1] = btAtan2(-btGetMatrixElem(mat,6),btGetMatrixElem(mat,0));
+ xyz[2] = btAsin(btGetMatrixElem(mat,3));
+ return true;
+ }
+ else
+ {
+ xyz[0] = btScalar(0.0);
+ xyz[1] = -btAtan2(btGetMatrixElem(mat,7),btGetMatrixElem(mat,8));
+ xyz[2] = -SIMD_HALF_PI;
+ return false;
+ }
+ }
+ else
+ {
+ xyz[0] = btScalar(0.0);
+ xyz[1] = btAtan2(btGetMatrixElem(mat,7),btGetMatrixElem(mat,8));
+ xyz[2] = SIMD_HALF_PI;
+ }
+ return false;
+}
+
+bool btGeneric6DofSpring2Constraint::matrixToEulerZXY(const btMatrix3x3& mat,btVector3& xyz)
+{
+ // rot = cz*cy-sz*sx*sy -cx*sz cz*sy+cy*sz*sx
+ // cy*sz+cz*sx*sy cz*cx sz*sy-cz*xy*sx
+ // -cx*sy sx cx*cy
+
+ btScalar fi = btGetMatrixElem(mat,7);
+ if (fi < btScalar(1.0f))
+ {
+ if (fi > btScalar(-1.0f))
+ {
+ xyz[0] = btAsin(btGetMatrixElem(mat,7));
+ xyz[1] = btAtan2(-btGetMatrixElem(mat,6),btGetMatrixElem(mat,8));
+ xyz[2] = btAtan2(-btGetMatrixElem(mat,1),btGetMatrixElem(mat,4));
+ return true;
+ }
+ else
+ {
+ xyz[0] = -SIMD_HALF_PI;
+ xyz[1] = btScalar(0.0);
+ xyz[2] = -btAtan2(btGetMatrixElem(mat,2),btGetMatrixElem(mat,0));
+ return false;
+ }
+ }
+ else
+ {
+ xyz[0] = SIMD_HALF_PI;
+ xyz[1] = btScalar(0.0);
+ xyz[2] = btAtan2(btGetMatrixElem(mat,2),btGetMatrixElem(mat,0));
+ }
+ return false;
+}
+
+bool btGeneric6DofSpring2Constraint::matrixToEulerZYX(const btMatrix3x3& mat,btVector3& xyz)
+{
+ // rot = cz*cy cz*sy*sx-cx*sz sz*sx+cz*cx*sy
+ // cy*sz cz*cx+sz*sy*sx cx*sz*sy-cz*sx
+ // -sy cy*sx cy*cx
+
+ btScalar fi = btGetMatrixElem(mat,6);
+ if (fi < btScalar(1.0f))
+ {
+ if (fi > btScalar(-1.0f))
+ {
+ xyz[0] = btAtan2(btGetMatrixElem(mat,7), btGetMatrixElem(mat,8));
+ xyz[1] = btAsin(-btGetMatrixElem(mat,6));
+ xyz[2] = btAtan2(btGetMatrixElem(mat,3),btGetMatrixElem(mat,0));
+ return true;
+ }
+ else
+ {
+ xyz[0] = btScalar(0.0);
+ xyz[1] = SIMD_HALF_PI;
+ xyz[2] = -btAtan2(btGetMatrixElem(mat,1),btGetMatrixElem(mat,2));
+ return false;
+ }
+ }
+ else
+ {
+ xyz[0] = btScalar(0.0);
+ xyz[1] = -SIMD_HALF_PI;
+ xyz[2] = btAtan2(-btGetMatrixElem(mat,1),-btGetMatrixElem(mat,2));
+ }
+ return false;
+}
+
+void btGeneric6DofSpring2Constraint::calculateAngleInfo()
+{
+ btMatrix3x3 relative_frame = m_calculatedTransformA.getBasis().inverse()*m_calculatedTransformB.getBasis();
+ switch (m_rotateOrder)
+ {
+ case RO_XYZ : matrixToEulerXYZ(relative_frame,m_calculatedAxisAngleDiff); break;
+ case RO_XZY : matrixToEulerXZY(relative_frame,m_calculatedAxisAngleDiff); break;
+ case RO_YXZ : matrixToEulerYXZ(relative_frame,m_calculatedAxisAngleDiff); break;
+ case RO_YZX : matrixToEulerYZX(relative_frame,m_calculatedAxisAngleDiff); break;
+ case RO_ZXY : matrixToEulerZXY(relative_frame,m_calculatedAxisAngleDiff); break;
+ case RO_ZYX : matrixToEulerZYX(relative_frame,m_calculatedAxisAngleDiff); break;
+ default : btAssert(false);
+ }
+ // in euler angle mode we do not actually constrain the angular velocity
+ // along the axes axis[0] and axis[2] (although we do use axis[1]) :
+ //
+ // to get constrain w2-w1 along ...not
+ // ------ --------------------- ------
+ // d(angle[0])/dt = 0 ax[1] x ax[2] ax[0]
+ // d(angle[1])/dt = 0 ax[1]
+ // d(angle[2])/dt = 0 ax[0] x ax[1] ax[2]
+ //
+ // constraining w2-w1 along an axis 'a' means that a'*(w2-w1)=0.
+ // to prove the result for angle[0], write the expression for angle[0] from
+ // GetInfo1 then take the derivative. to prove this for angle[2] it is
+ // easier to take the euler rate expression for d(angle[2])/dt with respect
+ // to the components of w and set that to 0.
+ switch (m_rotateOrder)
+ {
+ 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
+ //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)
+ // x' = Nperp = N.cross(axis2)
+ // y' = N = axis2.cross(axis0)
+ // z' = z
+ //
+ // x" = X
+ // y" = y'
+ // z" = ??
+ //in other words:
+ //first rotate around z
+ //second rotate around y'= z.cross(X)
+ //third rotate around x" = X
+ //Original XYZ extrinsic rotation order.
+ //Planes: xy and YZ normals: z, X. Plane intersection (N) is z.cross(X)
+ btVector3 axis0 = m_calculatedTransformB.getBasis().getColumn(0);
+ btVector3 axis2 = m_calculatedTransformA.getBasis().getColumn(2);
+ m_calculatedAxis[1] = axis2.cross(axis0);
+ m_calculatedAxis[0] = m_calculatedAxis[1].cross(axis2);
+ m_calculatedAxis[2] = axis0.cross(m_calculatedAxis[1]);
+ break;
+ }
+ case RO_XZY :
+ {
+ //planes: xz,ZY normals: y, X
+ //first rotate around y
+ //second rotate around z'= y.cross(X)
+ //third rotate around x" = X
+ btVector3 axis0 = m_calculatedTransformB.getBasis().getColumn(0);
+ btVector3 axis1 = m_calculatedTransformA.getBasis().getColumn(1);
+ m_calculatedAxis[2] = axis0.cross(axis1);
+ m_calculatedAxis[0] = axis1.cross(m_calculatedAxis[2]);
+ m_calculatedAxis[1] = m_calculatedAxis[2].cross(axis0);
+ break;
+ }
+ case RO_YXZ :
+ {
+ //planes: yx,XZ normals: z, Y
+ //first rotate around z
+ //second rotate around x'= z.cross(Y)
+ //third rotate around y" = Y
+ btVector3 axis1 = m_calculatedTransformB.getBasis().getColumn(1);
+ btVector3 axis2 = m_calculatedTransformA.getBasis().getColumn(2);
+ m_calculatedAxis[0] = axis1.cross(axis2);
+ m_calculatedAxis[1] = axis2.cross(m_calculatedAxis[0]);
+ m_calculatedAxis[2] = m_calculatedAxis[0].cross(axis1);
+ break;
+ }
+ case RO_YZX :
+ {
+ //planes: yz,ZX normals: x, Y
+ //first rotate around x
+ //second rotate around z'= x.cross(Y)
+ //third rotate around y" = Y
+ btVector3 axis0 = m_calculatedTransformA.getBasis().getColumn(0);
+ btVector3 axis1 = m_calculatedTransformB.getBasis().getColumn(1);
+ m_calculatedAxis[2] = axis0.cross(axis1);
+ m_calculatedAxis[0] = axis1.cross(m_calculatedAxis[2]);
+ m_calculatedAxis[1] = m_calculatedAxis[2].cross(axis0);
+ break;
+ }
+ case RO_ZXY :
+ {
+ //planes: zx,XY normals: y, Z
+ //first rotate around y
+ //second rotate around x'= y.cross(Z)
+ //third rotate around z" = Z
+ btVector3 axis1 = m_calculatedTransformA.getBasis().getColumn(1);
+ btVector3 axis2 = m_calculatedTransformB.getBasis().getColumn(2);
+ m_calculatedAxis[0] = axis1.cross(axis2);
+ m_calculatedAxis[1] = axis2.cross(m_calculatedAxis[0]);
+ m_calculatedAxis[2] = m_calculatedAxis[0].cross(axis1);
+ break;
+ }
+ case RO_ZYX :
+ {
+ //planes: zy,YX normals: x, Z
+ //first rotate around x
+ //second rotate around y' = x.cross(Z)
+ //third rotate around z" = Z
+ btVector3 axis0 = m_calculatedTransformA.getBasis().getColumn(0);
+ btVector3 axis2 = m_calculatedTransformB.getBasis().getColumn(2);
+ m_calculatedAxis[1] = axis2.cross(axis0);
+ m_calculatedAxis[0] = m_calculatedAxis[1].cross(axis2);
+ m_calculatedAxis[2] = axis0.cross(m_calculatedAxis[1]);
+ break;
+ }
+ default:
+ btAssert(false);
+ }
+
+ m_calculatedAxis[0].normalize();
+ m_calculatedAxis[1].normalize();
+ m_calculatedAxis[2].normalize();
+
+}
+
+void btGeneric6DofSpring2Constraint::calculateTransforms()
+{
+ calculateTransforms(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform());
+}
+
+void btGeneric6DofSpring2Constraint::calculateTransforms(const btTransform& transA,const btTransform& transB)
+{
+ m_calculatedTransformA = transA * m_frameInA;
+ m_calculatedTransformB = transB * m_frameInB;
+ calculateLinearInfo();
+ calculateAngleInfo();
+
+ btScalar miA = getRigidBodyA().getInvMass();
+ btScalar miB = getRigidBodyB().getInvMass();
+ m_hasStaticBody = (miA < SIMD_EPSILON) || (miB < SIMD_EPSILON);
+ btScalar miS = miA + miB;
+ if(miS > btScalar(0.f))
+ {
+ m_factA = miB / miS;
+ }
+ else
+ {
+ m_factA = btScalar(0.5f);
+ }
+ m_factB = btScalar(1.0f) - m_factA;
+}
+
+
+void btGeneric6DofSpring2Constraint::testAngularLimitMotor(int axis_index)
+{
+ btScalar angle = m_calculatedAxisAngleDiff[axis_index];
+ angle = btAdjustAngleToLimits(angle, m_angularLimits[axis_index].m_loLimit, m_angularLimits[axis_index].m_hiLimit);
+ m_angularLimits[axis_index].m_currentPosition = angle;
+ m_angularLimits[axis_index].testLimitValue(angle);
+}
+
+
+void btGeneric6DofSpring2Constraint::getInfo1 (btConstraintInfo1* info)
+{
+ //prepare constraint
+ calculateTransforms(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform());
+ info->m_numConstraintRows = 0;
+ info->nub = 0;
+ int i;
+ //test linear limits
+ for(i = 0; i < 3; i++)
+ {
+ if (m_linearLimits.m_currentLimit[i]==4) info->m_numConstraintRows += 2;
+ else if (m_linearLimits.m_currentLimit[i]!=0) info->m_numConstraintRows += 1;
+ if (m_linearLimits.m_enableMotor[i] ) info->m_numConstraintRows += 1;
+ if (m_linearLimits.m_enableSpring[i]) info->m_numConstraintRows += 1;
+ }
+ //test angular limits
+ for (i=0;i<3 ;i++ )
+ {
+ testAngularLimitMotor(i);
+ if (m_angularLimits[i].m_currentLimit==4) info->m_numConstraintRows += 2;
+ else if (m_angularLimits[i].m_currentLimit!=0) info->m_numConstraintRows += 1;
+ if (m_angularLimits[i].m_enableMotor ) info->m_numConstraintRows += 1;
+ if (m_angularLimits[i].m_enableSpring) info->m_numConstraintRows += 1;
+ }
+}
+
+
+void btGeneric6DofSpring2Constraint::getInfo2 (btConstraintInfo2* info)
+{
+ const btTransform& transA = m_rbA.getCenterOfMassTransform();
+ const btTransform& transB = m_rbB.getCenterOfMassTransform();
+ const btVector3& linVelA = m_rbA.getLinearVelocity();
+ const btVector3& linVelB = m_rbB.getLinearVelocity();
+ const btVector3& angVelA = m_rbA.getAngularVelocity();
+ const btVector3& angVelB = m_rbB.getAngularVelocity();
+
+ // for stability better to solve angular limits first
+ int row = setAngularLimits(info, 0,transA,transB,linVelA,linVelB,angVelA,angVelB);
+ setLinearLimits(info, row, transA,transB,linVelA,linVelB,angVelA,angVelB);
+}
+
+
+int btGeneric6DofSpring2Constraint::setLinearLimits(btConstraintInfo2* info, int row, const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB)
+{
+ //solve linear limits
+ btRotationalLimitMotor2 limot;
+ for (int i=0;i<3 ;i++ )
+ {
+ if(m_linearLimits.m_currentLimit[i] || m_linearLimits.m_enableMotor[i] || m_linearLimits.m_enableSpring[i])
+ { // re-use rotational motor code
+ limot.m_bounce = m_linearLimits.m_bounce[i];
+ limot.m_currentLimit = m_linearLimits.m_currentLimit[i];
+ limot.m_currentPosition = m_linearLimits.m_currentLinearDiff[i];
+ limot.m_currentLimitError = m_linearLimits.m_currentLimitError[i];
+ limot.m_currentLimitErrorHi = m_linearLimits.m_currentLimitErrorHi[i];
+ limot.m_enableMotor = m_linearLimits.m_enableMotor[i];
+ limot.m_servoMotor = m_linearLimits.m_servoMotor[i];
+ limot.m_servoTarget = m_linearLimits.m_servoTarget[i];
+ limot.m_enableSpring = m_linearLimits.m_enableSpring[i];
+ limot.m_springStiffness = m_linearLimits.m_springStiffness[i];
+ limot.m_springStiffnessLimited = m_linearLimits.m_springStiffnessLimited[i];
+ limot.m_springDamping = m_linearLimits.m_springDamping[i];
+ limot.m_springDampingLimited = m_linearLimits.m_springDampingLimited[i];
+ limot.m_equilibriumPoint = m_linearLimits.m_equilibriumPoint[i];
+ limot.m_hiLimit = m_linearLimits.m_upperLimit[i];
+ limot.m_loLimit = m_linearLimits.m_lowerLimit[i];
+ limot.m_maxMotorForce = m_linearLimits.m_maxMotorForce[i];
+ limot.m_targetVelocity = m_linearLimits.m_targetVelocity[i];
+ btVector3 axis = m_calculatedTransformA.getBasis().getColumn(i);
+ int flags = m_flags >> (i * BT_6DOF_FLAGS_AXIS_SHIFT2);
+ limot.m_stopCFM = (flags & BT_6DOF_FLAGS_CFM_STOP2) ? m_linearLimits.m_stopCFM[i] : info->cfm[0];
+ limot.m_stopERP = (flags & BT_6DOF_FLAGS_ERP_STOP2) ? m_linearLimits.m_stopERP[i] : info->erp;
+ limot.m_motorCFM = (flags & BT_6DOF_FLAGS_CFM_MOTO2) ? m_linearLimits.m_motorCFM[i] : info->cfm[0];
+ limot.m_motorERP = (flags & BT_6DOF_FLAGS_ERP_MOTO2) ? m_linearLimits.m_motorERP[i] : info->erp;
+
+ //rotAllowed is a bit of a magic from the original 6dof. The calculation of it here is something that imitates the original behavior as much as possible.
+ int indx1 = (i + 1) % 3;
+ int indx2 = (i + 2) % 3;
+ int rotAllowed = 1; // rotations around orthos to current axis (it is used only when one of the body is static)
+ #define D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION 1.0e-3
+ bool indx1Violated = m_angularLimits[indx1].m_currentLimit == 1 ||
+ m_angularLimits[indx1].m_currentLimit == 2 ||
+ ( m_angularLimits[indx1].m_currentLimit == 3 && ( m_angularLimits[indx1].m_currentLimitError < -D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION || m_angularLimits[indx1].m_currentLimitError > D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION ) ) ||
+ ( m_angularLimits[indx1].m_currentLimit == 4 && ( m_angularLimits[indx1].m_currentLimitError < -D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION || m_angularLimits[indx1].m_currentLimitErrorHi > D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION ) );
+ bool indx2Violated = m_angularLimits[indx2].m_currentLimit == 1 ||
+ m_angularLimits[indx2].m_currentLimit == 2 ||
+ ( m_angularLimits[indx2].m_currentLimit == 3 && ( m_angularLimits[indx2].m_currentLimitError < -D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION || m_angularLimits[indx2].m_currentLimitError > D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION ) ) ||
+ ( m_angularLimits[indx2].m_currentLimit == 4 && ( m_angularLimits[indx2].m_currentLimitError < -D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION || m_angularLimits[indx2].m_currentLimitErrorHi > D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION ) );
+ if( indx1Violated && indx2Violated )
+ {
+ rotAllowed = 0;
+ }
+ row += get_limit_motor_info2(&limot, transA,transB,linVelA,linVelB,angVelA,angVelB, info, row, axis, 0, rotAllowed);
+
+ }
+ }
+ return row;
+}
+
+
+
+int btGeneric6DofSpring2Constraint::setAngularLimits(btConstraintInfo2 *info, int row_offset, const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB)
+{
+ int row = row_offset;
+
+ //order of rotational constraint rows
+ int cIdx[] = {0, 1, 2};
+ switch(m_rotateOrder)
+ {
+ case RO_XYZ : cIdx[0] = 0; cIdx[1] = 1; cIdx[2] = 2; break;
+ case RO_XZY : cIdx[0] = 0; cIdx[1] = 2; cIdx[2] = 1; break;
+ case RO_YXZ : cIdx[0] = 1; cIdx[1] = 0; cIdx[2] = 2; break;
+ case RO_YZX : cIdx[0] = 1; cIdx[1] = 2; cIdx[2] = 0; break;
+ case RO_ZXY : cIdx[0] = 2; cIdx[1] = 0; cIdx[2] = 1; break;
+ case RO_ZYX : cIdx[0] = 2; cIdx[1] = 1; cIdx[2] = 0; break;
+ default : btAssert(false);
+ }
+
+ for (int ii = 0; ii < 3 ; ii++ )
+ {
+ int i = cIdx[ii];
+ if(m_angularLimits[i].m_currentLimit || m_angularLimits[i].m_enableMotor || m_angularLimits[i].m_enableSpring)
+ {
+ btVector3 axis = getAxis(i);
+ int flags = m_flags >> ((i + 3) * BT_6DOF_FLAGS_AXIS_SHIFT2);
+ if(!(flags & BT_6DOF_FLAGS_CFM_STOP2))
+ {
+ m_angularLimits[i].m_stopCFM = info->cfm[0];
+ }
+ if(!(flags & BT_6DOF_FLAGS_ERP_STOP2))
+ {
+ m_angularLimits[i].m_stopERP = info->erp;
+ }
+ if(!(flags & BT_6DOF_FLAGS_CFM_MOTO2))
+ {
+ m_angularLimits[i].m_motorCFM = info->cfm[0];
+ }
+ if(!(flags & BT_6DOF_FLAGS_ERP_MOTO2))
+ {
+ m_angularLimits[i].m_motorERP = info->erp;
+ }
+ row += get_limit_motor_info2(&m_angularLimits[i],transA,transB,linVelA,linVelB,angVelA,angVelB, info,row,axis,1);
+ }
+ }
+
+ return row;
+}
+
+
+void btGeneric6DofSpring2Constraint::setFrames(const btTransform& frameA, const btTransform& frameB)
+{
+ m_frameInA = frameA;
+ m_frameInB = frameB;
+ buildJacobian();
+ calculateTransforms();
+}
+
+
+void btGeneric6DofSpring2Constraint::calculateLinearInfo()
+{
+ m_calculatedLinearDiff = m_calculatedTransformB.getOrigin() - m_calculatedTransformA.getOrigin();
+ m_calculatedLinearDiff = m_calculatedTransformA.getBasis().inverse() * m_calculatedLinearDiff;
+ for(int i = 0; i < 3; i++)
+ {
+ m_linearLimits.m_currentLinearDiff[i] = m_calculatedLinearDiff[i];
+ m_linearLimits.testLimitValue(i, m_calculatedLinearDiff[i]);
+ }
+}
+
+void btGeneric6DofSpring2Constraint::calculateJacobi(btRotationalLimitMotor2 * limot, const btTransform& transA,const btTransform& transB, btConstraintInfo2 *info, int srow, btVector3& ax1, int rotational, int rotAllowed)
+{
+ btScalar *J1 = rotational ? info->m_J1angularAxis : info->m_J1linearAxis;
+ btScalar *J2 = rotational ? info->m_J2angularAxis : info->m_J2linearAxis;
+
+ J1[srow+0] = ax1[0];
+ J1[srow+1] = ax1[1];
+ J1[srow+2] = ax1[2];
+
+ J2[srow+0] = -ax1[0];
+ J2[srow+1] = -ax1[1];
+ J2[srow+2] = -ax1[2];
+
+ if(!rotational)
+ {
+ btVector3 tmpA, tmpB, relA, relB;
+ // get vector from bodyB to frameB in WCS
+ relB = m_calculatedTransformB.getOrigin() - transB.getOrigin();
+ // same for bodyA
+ relA = m_calculatedTransformA.getOrigin() - transA.getOrigin();
+ tmpA = relA.cross(ax1);
+ tmpB = relB.cross(ax1);
+ if(m_hasStaticBody && (!rotAllowed))
+ {
+ tmpA *= m_factA;
+ tmpB *= m_factB;
+ }
+ int i;
+ for (i=0; i<3; i++) info->m_J1angularAxis[srow+i] = tmpA[i];
+ for (i=0; i<3; i++) info->m_J2angularAxis[srow+i] = -tmpB[i];
+ }
+}
+
+
+int btGeneric6DofSpring2Constraint::get_limit_motor_info2(
+ btRotationalLimitMotor2 * limot,
+ const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB,
+ btConstraintInfo2 *info, int row, btVector3& ax1, int rotational,int rotAllowed)
+{
+ int count = 0;
+ int srow = row * info->rowskip;
+
+ if (limot->m_currentLimit==4)
+ {
+ btScalar vel = rotational ? angVelA.dot(ax1) - angVelB.dot(ax1) : linVelA.dot(ax1) - linVelB.dot(ax1);
+
+ calculateJacobi(limot,transA,transB,info,srow,ax1,rotational,rotAllowed);
+ info->m_constraintError[srow] = info->fps * limot->m_stopERP * limot->m_currentLimitError * (rotational ? -1 : 1);
+ if (rotational) {
+ if (info->m_constraintError[srow]-vel*limot->m_stopERP > 0) {
+ btScalar bounceerror = -limot->m_bounce* vel;
+ if (bounceerror > info->m_constraintError[srow]) info->m_constraintError[srow] = bounceerror;
+ }
+ } else {
+ if (info->m_constraintError[srow]-vel*limot->m_stopERP < 0) {
+ btScalar bounceerror = -limot->m_bounce* vel;
+ if (bounceerror < info->m_constraintError[srow]) info->m_constraintError[srow] = bounceerror;
+ }
+ }
+ info->m_lowerLimit[srow] = rotational ? 0 : -SIMD_INFINITY;
+ info->m_upperLimit[srow] = rotational ? SIMD_INFINITY : 0;
+ info->cfm[srow] = limot->m_stopCFM;
+ srow += info->rowskip;
+ ++count;
+
+ calculateJacobi(limot,transA,transB,info,srow,ax1,rotational,rotAllowed);
+ info->m_constraintError[srow] = info->fps * limot->m_stopERP * limot->m_currentLimitErrorHi * (rotational ? -1 : 1);
+ if (rotational) {
+ if (info->m_constraintError[srow]-vel*limot->m_stopERP < 0) {
+ btScalar bounceerror = -limot->m_bounce* vel;
+ if (bounceerror < info->m_constraintError[srow]) info->m_constraintError[srow] = bounceerror;
+ }
+ } else {
+ if (info->m_constraintError[srow]-vel*limot->m_stopERP > 0) {
+ btScalar bounceerror = -limot->m_bounce* vel;
+ if (bounceerror > info->m_constraintError[srow]) info->m_constraintError[srow] = bounceerror;
+ }
+ }
+ info->m_lowerLimit[srow] = rotational ? -SIMD_INFINITY : 0;
+ info->m_upperLimit[srow] = rotational ? 0 : SIMD_INFINITY;
+ info->cfm[srow] = limot->m_stopCFM;
+ srow += info->rowskip;
+ ++count;
+ } else
+ if (limot->m_currentLimit==3)
+ {
+ calculateJacobi(limot,transA,transB,info,srow,ax1,rotational,rotAllowed);
+ info->m_constraintError[srow] = info->fps * limot->m_stopERP * limot->m_currentLimitError * (rotational ? -1 : 1);
+ info->m_lowerLimit[srow] = -SIMD_INFINITY;
+ info->m_upperLimit[srow] = SIMD_INFINITY;
+ info->cfm[srow] = limot->m_stopCFM;
+ srow += info->rowskip;
+ ++count;
+ }
+
+ if (limot->m_enableMotor && !limot->m_servoMotor)
+ {
+ calculateJacobi(limot,transA,transB,info,srow,ax1,rotational,rotAllowed);
+ btScalar tag_vel = rotational ? limot->m_targetVelocity : -limot->m_targetVelocity;
+ btScalar mot_fact = getMotorFactor(limot->m_currentPosition,
+ limot->m_loLimit,
+ limot->m_hiLimit,
+ tag_vel,
+ info->fps * limot->m_motorERP);
+ info->m_constraintError[srow] = mot_fact * limot->m_targetVelocity;
+ info->m_lowerLimit[srow] = -limot->m_maxMotorForce;
+ info->m_upperLimit[srow] = limot->m_maxMotorForce;
+ info->cfm[srow] = limot->m_motorCFM;
+ srow += info->rowskip;
+ ++count;
+ }
+
+ if (limot->m_enableMotor && limot->m_servoMotor)
+ {
+ btScalar error = limot->m_currentPosition - limot->m_servoTarget;
+ btScalar curServoTarget = limot->m_servoTarget;
+ if (rotational)
+ {
+ if (error > SIMD_PI)
+ {
+ error -= SIMD_2_PI;
+ curServoTarget +=SIMD_2_PI;
+ }
+ if (error < -SIMD_PI)
+ {
+ error += SIMD_2_PI;
+ curServoTarget -=SIMD_2_PI;
+ }
+ }
+
+ calculateJacobi(limot,transA,transB,info,srow,ax1,rotational,rotAllowed);
+ btScalar targetvelocity = error<0 ? -limot->m_targetVelocity : limot->m_targetVelocity;
+ btScalar tag_vel = -targetvelocity;
+ btScalar mot_fact;
+ if(error != 0)
+ {
+ btScalar lowLimit;
+ btScalar hiLimit;
+ if(limot->m_loLimit > limot->m_hiLimit)
+ {
+ lowLimit = error > 0 ? curServoTarget : -SIMD_INFINITY;
+ hiLimit = error < 0 ? curServoTarget : SIMD_INFINITY;
+ }
+ else
+ {
+ lowLimit = error > 0 && curServoTarget>limot->m_loLimit ? curServoTarget : limot->m_loLimit;
+ hiLimit = error < 0 && curServoTarget<limot->m_hiLimit ? curServoTarget : limot->m_hiLimit;
+ }
+ mot_fact = getMotorFactor(limot->m_currentPosition, lowLimit, hiLimit, tag_vel, info->fps * limot->m_motorERP);
+ }
+ else
+ {
+ mot_fact = 0;
+ }
+ info->m_constraintError[srow] = mot_fact * targetvelocity * (rotational ? -1 : 1);
+ info->m_lowerLimit[srow] = -limot->m_maxMotorForce;
+ info->m_upperLimit[srow] = limot->m_maxMotorForce;
+ info->cfm[srow] = limot->m_motorCFM;
+ srow += info->rowskip;
+ ++count;
+ }
+
+ if (limot->m_enableSpring)
+ {
+ btScalar error = limot->m_currentPosition - limot->m_equilibriumPoint;
+ calculateJacobi(limot,transA,transB,info,srow,ax1,rotational,rotAllowed);
+
+ //btScalar cfm = 1.0 / ((1.0/info->fps)*limot->m_springStiffness+ limot->m_springDamping);
+ //if(cfm > 0.99999)
+ // cfm = 0.99999;
+ //btScalar erp = (1.0/info->fps)*limot->m_springStiffness / ((1.0/info->fps)*limot->m_springStiffness + limot->m_springDamping);
+ //info->m_constraintError[srow] = info->fps * erp * error * (rotational ? -1.0 : 1.0);
+ //info->m_lowerLimit[srow] = -SIMD_INFINITY;
+ //info->m_upperLimit[srow] = SIMD_INFINITY;
+
+ btScalar dt = BT_ONE / info->fps;
+ btScalar kd = limot->m_springDamping;
+ btScalar ks = limot->m_springStiffness;
+ btScalar vel = rotational ? angVelA.dot(ax1) - angVelB.dot(ax1) : linVelA.dot(ax1) - linVelB.dot(ax1);
+// btScalar erp = 0.1;
+ btScalar cfm = BT_ZERO;
+ btScalar mA = BT_ONE / m_rbA.getInvMass();
+ btScalar mB = BT_ONE / m_rbB.getInvMass();
+ btScalar m = mA > mB ? mB : mA;
+ btScalar angularfreq = sqrt(ks / m);
+
+
+ //limit stiffness (the spring should not be sampled faster that the quarter of its angular frequency)
+ if(limot->m_springStiffnessLimited && 0.25 < angularfreq * dt)
+ {
+ ks = BT_ONE / dt / dt / btScalar(16.0) * m;
+ }
+ //avoid damping that would blow up the spring
+ if(limot->m_springDampingLimited && kd * dt > m)
+ {
+ kd = m / dt;
+ }
+ btScalar fs = ks * error * dt;
+ btScalar fd = -kd * (vel) * (rotational ? -1 : 1) * dt;
+ btScalar f = (fs+fd);
+
+ info->m_constraintError[srow] = (vel + f * (rotational ? -1 : 1)) ;
+
+ btScalar minf = f < fd ? f : fd;
+ btScalar maxf = f < fd ? fd : f;
+ if(!rotational)
+ {
+ info->m_lowerLimit[srow] = minf > 0 ? 0 : minf;
+ info->m_upperLimit[srow] = maxf < 0 ? 0 : maxf;
+ }
+ else
+ {
+ info->m_lowerLimit[srow] = -maxf > 0 ? 0 : -maxf;
+ info->m_upperLimit[srow] = -minf < 0 ? 0 : -minf;
+ }
+
+ info->cfm[srow] = cfm;
+ srow += info->rowskip;
+ ++count;
+ }
+
+ return count;
+}
+
+
+//override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
+//If no axis is provided, it uses the default axis for this constraint.
+void btGeneric6DofSpring2Constraint::setParam(int num, btScalar value, int axis)
+{
+ if((axis >= 0) && (axis < 3))
+ {
+ switch(num)
+ {
+ case BT_CONSTRAINT_STOP_ERP :
+ m_linearLimits.m_stopERP[axis] = value;
+ m_flags |= BT_6DOF_FLAGS_ERP_STOP2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2);
+ break;
+ case BT_CONSTRAINT_STOP_CFM :
+ m_linearLimits.m_stopCFM[axis] = value;
+ m_flags |= BT_6DOF_FLAGS_CFM_STOP2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2);
+ break;
+ case BT_CONSTRAINT_ERP :
+ m_linearLimits.m_motorERP[axis] = value;
+ m_flags |= BT_6DOF_FLAGS_ERP_MOTO2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2);
+ break;
+ case BT_CONSTRAINT_CFM :
+ m_linearLimits.m_motorCFM[axis] = value;
+ m_flags |= BT_6DOF_FLAGS_CFM_MOTO2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2);
+ break;
+ default :
+ btAssertConstrParams(0);
+ }
+ }
+ else if((axis >=3) && (axis < 6))
+ {
+ switch(num)
+ {
+ case BT_CONSTRAINT_STOP_ERP :
+ m_angularLimits[axis - 3].m_stopERP = value;
+ m_flags |= BT_6DOF_FLAGS_ERP_STOP2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2);
+ break;
+ case BT_CONSTRAINT_STOP_CFM :
+ m_angularLimits[axis - 3].m_stopCFM = value;
+ m_flags |= BT_6DOF_FLAGS_CFM_STOP2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2);
+ break;
+ case BT_CONSTRAINT_ERP :
+ m_angularLimits[axis - 3].m_motorERP = value;
+ m_flags |= BT_6DOF_FLAGS_ERP_MOTO2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2);
+ break;
+ case BT_CONSTRAINT_CFM :
+ m_angularLimits[axis - 3].m_motorCFM = value;
+ m_flags |= BT_6DOF_FLAGS_CFM_MOTO2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2);
+ break;
+ default :
+ btAssertConstrParams(0);
+ }
+ }
+ else
+ {
+ btAssertConstrParams(0);
+ }
+}
+
+//return the local value of parameter
+btScalar btGeneric6DofSpring2Constraint::getParam(int num, int axis) const
+{
+ btScalar retVal = 0;
+ if((axis >= 0) && (axis < 3))
+ {
+ switch(num)
+ {
+ case BT_CONSTRAINT_STOP_ERP :
+ btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_ERP_STOP2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2)));
+ retVal = m_linearLimits.m_stopERP[axis];
+ break;
+ case BT_CONSTRAINT_STOP_CFM :
+ btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_CFM_STOP2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2)));
+ retVal = m_linearLimits.m_stopCFM[axis];
+ break;
+ case BT_CONSTRAINT_ERP :
+ btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_ERP_MOTO2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2)));
+ retVal = m_linearLimits.m_motorERP[axis];
+ break;
+ case BT_CONSTRAINT_CFM :
+ btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_CFM_MOTO2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2)));
+ retVal = m_linearLimits.m_motorCFM[axis];
+ break;
+ default :
+ btAssertConstrParams(0);
+ }
+ }
+ else if((axis >=3) && (axis < 6))
+ {
+ switch(num)
+ {
+ case BT_CONSTRAINT_STOP_ERP :
+ btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_ERP_STOP2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2)));
+ retVal = m_angularLimits[axis - 3].m_stopERP;
+ break;
+ case BT_CONSTRAINT_STOP_CFM :
+ btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_CFM_STOP2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2)));
+ retVal = m_angularLimits[axis - 3].m_stopCFM;
+ break;
+ case BT_CONSTRAINT_ERP :
+ btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_ERP_MOTO2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2)));
+ retVal = m_angularLimits[axis - 3].m_motorERP;
+ break;
+ case BT_CONSTRAINT_CFM :
+ btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_CFM_MOTO2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2)));
+ retVal = m_angularLimits[axis - 3].m_motorCFM;
+ break;
+ default :
+ btAssertConstrParams(0);
+ }
+ }
+ else
+ {
+ btAssertConstrParams(0);
+ }
+ return retVal;
+}
+
+
+
+void btGeneric6DofSpring2Constraint::setAxis(const btVector3& axis1,const btVector3& axis2)
+{
+ btVector3 zAxis = axis1.normalized();
+ btVector3 yAxis = axis2.normalized();
+ btVector3 xAxis = yAxis.cross(zAxis); // we want right coordinate system
+
+ btTransform frameInW;
+ frameInW.setIdentity();
+ frameInW.getBasis().setValue( xAxis[0], yAxis[0], zAxis[0],
+ xAxis[1], yAxis[1], zAxis[1],
+ xAxis[2], yAxis[2], zAxis[2]);
+
+ // now get constraint frame in local coordinate systems
+ m_frameInA = m_rbA.getCenterOfMassTransform().inverse() * frameInW;
+ m_frameInB = m_rbB.getCenterOfMassTransform().inverse() * frameInW;
+
+ calculateTransforms();
+}
+
+void btGeneric6DofSpring2Constraint::setBounce(int index, btScalar bounce)
+{
+ btAssert((index >= 0) && (index < 6));
+ if (index<3)
+ m_linearLimits.m_bounce[index] = bounce;
+ else
+ m_angularLimits[index - 3].m_bounce = bounce;
+}
+
+void btGeneric6DofSpring2Constraint::enableMotor(int index, bool onOff)
+{
+ btAssert((index >= 0) && (index < 6));
+ if (index<3)
+ m_linearLimits.m_enableMotor[index] = onOff;
+ else
+ m_angularLimits[index - 3].m_enableMotor = onOff;
+}
+
+void btGeneric6DofSpring2Constraint::setServo(int index, bool onOff)
+{
+ btAssert((index >= 0) && (index < 6));
+ if (index<3)
+ m_linearLimits.m_servoMotor[index] = onOff;
+ else
+ m_angularLimits[index - 3].m_servoMotor = onOff;
+}
+
+void btGeneric6DofSpring2Constraint::setTargetVelocity(int index, btScalar velocity)
+{
+ btAssert((index >= 0) && (index < 6));
+ if (index<3)
+ m_linearLimits.m_targetVelocity[index] = velocity;
+ else
+ m_angularLimits[index - 3].m_targetVelocity = velocity;
+}
+
+
+
+void btGeneric6DofSpring2Constraint::setServoTarget(int index, btScalar targetOrg)
+{
+ btAssert((index >= 0) && (index < 6));
+ if (index<3)
+ {
+ m_linearLimits.m_servoTarget[index] = targetOrg;
+ }
+ else
+ {
+ //wrap between -PI and PI, see also
+ //https://stackoverflow.com/questions/4633177/c-how-to-wrap-a-float-to-the-interval-pi-pi
+
+ btScalar target = targetOrg+SIMD_PI;
+ if (1)
+ {
+ btScalar m = target - SIMD_2_PI * floor(target/SIMD_2_PI);
+ // handle boundary cases resulted from floating-point cut off:
+ {
+ if (m>=SIMD_2_PI)
+ {
+ target = 0;
+ } else
+ {
+ if (m<0 )
+ {
+ if (SIMD_2_PI+m == SIMD_2_PI)
+ target = 0;
+ else
+ target = SIMD_2_PI+m;
+ }
+ else
+ {
+ target = m;
+ }
+ }
+ }
+ target -= SIMD_PI;
+ }
+
+ m_angularLimits[index - 3].m_servoTarget = target;
+ }
+}
+
+void btGeneric6DofSpring2Constraint::setMaxMotorForce(int index, btScalar force)
+{
+ btAssert((index >= 0) && (index < 6));
+ if (index<3)
+ m_linearLimits.m_maxMotorForce[index] = force;
+ else
+ m_angularLimits[index - 3].m_maxMotorForce = force;
+}
+
+void btGeneric6DofSpring2Constraint::enableSpring(int index, bool onOff)
+{
+ btAssert((index >= 0) && (index < 6));
+ if (index<3)
+ m_linearLimits.m_enableSpring[index] = onOff;
+ else
+ m_angularLimits[index - 3] .m_enableSpring = onOff;
+}
+
+void btGeneric6DofSpring2Constraint::setStiffness(int index, btScalar stiffness, bool limitIfNeeded)
+{
+ btAssert((index >= 0) && (index < 6));
+ if (index<3) {
+ m_linearLimits.m_springStiffness[index] = stiffness;
+ m_linearLimits.m_springStiffnessLimited[index] = limitIfNeeded;
+ } else {
+ m_angularLimits[index - 3].m_springStiffness = stiffness;
+ m_angularLimits[index - 3].m_springStiffnessLimited = limitIfNeeded;
+ }
+}
+
+void btGeneric6DofSpring2Constraint::setDamping(int index, btScalar damping, bool limitIfNeeded)
+{
+ btAssert((index >= 0) && (index < 6));
+ if (index<3) {
+ m_linearLimits.m_springDamping[index] = damping;
+ m_linearLimits.m_springDampingLimited[index] = limitIfNeeded;
+ } else {
+ m_angularLimits[index - 3].m_springDamping = damping;
+ m_angularLimits[index - 3].m_springDampingLimited = limitIfNeeded;
+ }
+}
+
+void btGeneric6DofSpring2Constraint::setEquilibriumPoint()
+{
+ calculateTransforms();
+ int i;
+ for( i = 0; i < 3; i++)
+ m_linearLimits.m_equilibriumPoint[i] = m_calculatedLinearDiff[i];
+ for(i = 0; i < 3; i++)
+ m_angularLimits[i].m_equilibriumPoint = m_calculatedAxisAngleDiff[i];
+}
+
+void btGeneric6DofSpring2Constraint::setEquilibriumPoint(int index)
+{
+ btAssert((index >= 0) && (index < 6));
+ calculateTransforms();
+ if (index<3)
+ m_linearLimits.m_equilibriumPoint[index] = m_calculatedLinearDiff[index];
+ else
+ m_angularLimits[index - 3] .m_equilibriumPoint = m_calculatedAxisAngleDiff[index - 3];
+}
+
+void btGeneric6DofSpring2Constraint::setEquilibriumPoint(int index, btScalar val)
+{
+ btAssert((index >= 0) && (index < 6));
+ if (index<3)
+ m_linearLimits.m_equilibriumPoint[index] = val;
+ else
+ m_angularLimits[index - 3] .m_equilibriumPoint = val;
+}
+
+
+//////////////////////////// btRotationalLimitMotor2 ////////////////////////////////////
+
+void btRotationalLimitMotor2::testLimitValue(btScalar test_value)
+{
+ //we can't normalize the angles here because we would lost the sign that we use later, but it doesn't seem to be a problem
+ if(m_loLimit > m_hiLimit) {
+ m_currentLimit = 0;
+ m_currentLimitError = btScalar(0.f);
+ }
+ else if(m_loLimit == m_hiLimit) {
+ m_currentLimitError = test_value - m_loLimit;
+ m_currentLimit = 3;
+ } else {
+ m_currentLimitError = test_value - m_loLimit;
+ m_currentLimitErrorHi = test_value - m_hiLimit;
+ m_currentLimit = 4;
+ }
+}
+
+//////////////////////////// btTranslationalLimitMotor2 ////////////////////////////////////
+
+void btTranslationalLimitMotor2::testLimitValue(int limitIndex, btScalar test_value)
+{
+ btScalar loLimit = m_lowerLimit[limitIndex];
+ btScalar hiLimit = m_upperLimit[limitIndex];
+ if(loLimit > hiLimit) {
+ m_currentLimitError[limitIndex] = 0;
+ m_currentLimit[limitIndex] = 0;
+ }
+ else if(loLimit == hiLimit) {
+ m_currentLimitError[limitIndex] = test_value - loLimit;
+ m_currentLimit[limitIndex] = 3;
+ } else {
+ m_currentLimitError[limitIndex] = test_value - loLimit;
+ m_currentLimitErrorHi[limitIndex] = test_value - hiLimit;
+ m_currentLimit[limitIndex] = 4;
+ }
+}
+
+
diff --git a/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h
new file mode 100644
index 0000000000..66d1769583
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h
@@ -0,0 +1,679 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+/*
+2014 May: btGeneric6DofSpring2Constraint is created from the original (2.82.2712) btGeneric6DofConstraint by Gabor Puhr and Tamas Umenhoffer
+Pros:
+- Much more accurate and stable in a lot of situation. (Especially when a sleeping chain of RBs connected with 6dof2 is pulled)
+- Stable and accurate spring with minimal energy loss that works with all of the solvers. (latter is not true for the original 6dof spring)
+- Servo motor functionality
+- Much more accurate bouncing. 0 really means zero bouncing (not true for the original 6odf) and there is only a minimal energy loss when the value is 1 (because of the solvers' precision)
+- Rotation order for the Euler system can be set. (One axis' freedom is still limited to pi/2)
+
+Cons:
+- It is slower than the original 6dof. There is no exact ratio, but half speed is a good estimation.
+- At bouncing the correct velocity is calculated, but not the correct position. (it is because of the solver can correct position or velocity, but not both.)
+*/
+
+/// 2009 March: btGeneric6DofConstraint refactored by Roman Ponomarev
+/// Added support for generic constraint solver through getInfo1/getInfo2 methods
+
+/*
+2007-09-09
+btGeneric6DofConstraint Refactored by Francisco Le?n
+email: projectileman@yahoo.com
+http://gimpact.sf.net
+*/
+
+
+#ifndef BT_GENERIC_6DOF_CONSTRAINT2_H
+#define BT_GENERIC_6DOF_CONSTRAINT2_H
+
+#include "LinearMath/btVector3.h"
+#include "btJacobianEntry.h"
+#include "btTypedConstraint.h"
+
+class btRigidBody;
+
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define btGeneric6DofSpring2ConstraintData2 btGeneric6DofSpring2ConstraintDoubleData2
+#define btGeneric6DofSpring2ConstraintDataName "btGeneric6DofSpring2ConstraintDoubleData2"
+#else
+#define btGeneric6DofSpring2ConstraintData2 btGeneric6DofSpring2ConstraintData
+#define btGeneric6DofSpring2ConstraintDataName "btGeneric6DofSpring2ConstraintData"
+#endif //BT_USE_DOUBLE_PRECISION
+
+enum RotateOrder
+{
+ RO_XYZ=0,
+ RO_XZY,
+ RO_YXZ,
+ RO_YZX,
+ RO_ZXY,
+ RO_ZYX
+};
+
+class btRotationalLimitMotor2
+{
+public:
+// upper < lower means free
+// upper == lower means locked
+// upper > lower means limited
+ btScalar m_loLimit;
+ btScalar m_hiLimit;
+ btScalar m_bounce;
+ btScalar m_stopERP;
+ btScalar m_stopCFM;
+ btScalar m_motorERP;
+ btScalar m_motorCFM;
+ bool m_enableMotor;
+ btScalar m_targetVelocity;
+ btScalar m_maxMotorForce;
+ bool m_servoMotor;
+ btScalar m_servoTarget;
+ bool m_enableSpring;
+ btScalar m_springStiffness;
+ bool m_springStiffnessLimited;
+ btScalar m_springDamping;
+ bool m_springDampingLimited;
+ btScalar m_equilibriumPoint;
+
+ btScalar m_currentLimitError;
+ btScalar m_currentLimitErrorHi;
+ btScalar m_currentPosition;
+ int m_currentLimit;
+
+ btRotationalLimitMotor2()
+ {
+ m_loLimit = 1.0f;
+ m_hiLimit = -1.0f;
+ m_bounce = 0.0f;
+ m_stopERP = 0.2f;
+ m_stopCFM = 0.f;
+ m_motorERP = 0.9f;
+ m_motorCFM = 0.f;
+ m_enableMotor = false;
+ m_targetVelocity = 0;
+ m_maxMotorForce = 0.1f;
+ m_servoMotor = false;
+ m_servoTarget = 0;
+ m_enableSpring = false;
+ m_springStiffness = 0;
+ m_springStiffnessLimited = false;
+ m_springDamping = 0;
+ m_springDampingLimited = false;
+ m_equilibriumPoint = 0;
+
+ m_currentLimitError = 0;
+ m_currentLimitErrorHi = 0;
+ m_currentPosition = 0;
+ m_currentLimit = 0;
+ }
+
+ btRotationalLimitMotor2(const btRotationalLimitMotor2 & limot)
+ {
+ m_loLimit = limot.m_loLimit;
+ m_hiLimit = limot.m_hiLimit;
+ m_bounce = limot.m_bounce;
+ m_stopERP = limot.m_stopERP;
+ m_stopCFM = limot.m_stopCFM;
+ m_motorERP = limot.m_motorERP;
+ m_motorCFM = limot.m_motorCFM;
+ m_enableMotor = limot.m_enableMotor;
+ m_targetVelocity = limot.m_targetVelocity;
+ m_maxMotorForce = limot.m_maxMotorForce;
+ m_servoMotor = limot.m_servoMotor;
+ m_servoTarget = limot.m_servoTarget;
+ m_enableSpring = limot.m_enableSpring;
+ m_springStiffness = limot.m_springStiffness;
+ m_springStiffnessLimited = limot.m_springStiffnessLimited;
+ m_springDamping = limot.m_springDamping;
+ m_springDampingLimited = limot.m_springDampingLimited;
+ m_equilibriumPoint = limot.m_equilibriumPoint;
+
+ m_currentLimitError = limot.m_currentLimitError;
+ m_currentLimitErrorHi = limot.m_currentLimitErrorHi;
+ m_currentPosition = limot.m_currentPosition;
+ m_currentLimit = limot.m_currentLimit;
+ }
+
+
+ bool isLimited()
+ {
+ if(m_loLimit > m_hiLimit) return false;
+ return true;
+ }
+
+ void testLimitValue(btScalar test_value);
+};
+
+
+
+class btTranslationalLimitMotor2
+{
+public:
+// upper < lower means free
+// upper == lower means locked
+// upper > lower means limited
+ btVector3 m_lowerLimit;
+ btVector3 m_upperLimit;
+ btVector3 m_bounce;
+ btVector3 m_stopERP;
+ btVector3 m_stopCFM;
+ btVector3 m_motorERP;
+ btVector3 m_motorCFM;
+ bool m_enableMotor[3];
+ bool m_servoMotor[3];
+ bool m_enableSpring[3];
+ btVector3 m_servoTarget;
+ btVector3 m_springStiffness;
+ bool m_springStiffnessLimited[3];
+ btVector3 m_springDamping;
+ bool m_springDampingLimited[3];
+ btVector3 m_equilibriumPoint;
+ btVector3 m_targetVelocity;
+ btVector3 m_maxMotorForce;
+
+ btVector3 m_currentLimitError;
+ btVector3 m_currentLimitErrorHi;
+ btVector3 m_currentLinearDiff;
+ int m_currentLimit[3];
+
+ btTranslationalLimitMotor2()
+ {
+ m_lowerLimit .setValue(0.f , 0.f , 0.f );
+ m_upperLimit .setValue(0.f , 0.f , 0.f );
+ m_bounce .setValue(0.f , 0.f , 0.f );
+ m_stopERP .setValue(0.2f, 0.2f, 0.2f);
+ m_stopCFM .setValue(0.f , 0.f , 0.f );
+ m_motorERP .setValue(0.9f, 0.9f, 0.9f);
+ m_motorCFM .setValue(0.f , 0.f , 0.f );
+
+ m_currentLimitError .setValue(0.f , 0.f , 0.f );
+ m_currentLimitErrorHi.setValue(0.f , 0.f , 0.f );
+ m_currentLinearDiff .setValue(0.f , 0.f , 0.f );
+
+ for(int i=0; i < 3; i++)
+ {
+ m_enableMotor[i] = false;
+ m_servoMotor[i] = false;
+ m_enableSpring[i] = false;
+ m_servoTarget[i] = btScalar(0.f);
+ m_springStiffness[i] = btScalar(0.f);
+ m_springStiffnessLimited[i] = false;
+ m_springDamping[i] = btScalar(0.f);
+ m_springDampingLimited[i] = false;
+ m_equilibriumPoint[i] = btScalar(0.f);
+ m_targetVelocity[i] = btScalar(0.f);
+ m_maxMotorForce[i] = btScalar(0.f);
+
+ m_currentLimit[i] = 0;
+ }
+ }
+
+ btTranslationalLimitMotor2(const btTranslationalLimitMotor2 & other )
+ {
+ m_lowerLimit = other.m_lowerLimit;
+ m_upperLimit = other.m_upperLimit;
+ m_bounce = other.m_bounce;
+ m_stopERP = other.m_stopERP;
+ m_stopCFM = other.m_stopCFM;
+ m_motorERP = other.m_motorERP;
+ m_motorCFM = other.m_motorCFM;
+
+ m_currentLimitError = other.m_currentLimitError;
+ m_currentLimitErrorHi = other.m_currentLimitErrorHi;
+ m_currentLinearDiff = other.m_currentLinearDiff;
+
+ for(int i=0; i < 3; i++)
+ {
+ m_enableMotor[i] = other.m_enableMotor[i];
+ m_servoMotor[i] = other.m_servoMotor[i];
+ m_enableSpring[i] = other.m_enableSpring[i];
+ m_servoTarget[i] = other.m_servoTarget[i];
+ m_springStiffness[i] = other.m_springStiffness[i];
+ m_springStiffnessLimited[i] = other.m_springStiffnessLimited[i];
+ m_springDamping[i] = other.m_springDamping[i];
+ m_springDampingLimited[i] = other.m_springDampingLimited[i];
+ m_equilibriumPoint[i] = other.m_equilibriumPoint[i];
+ m_targetVelocity[i] = other.m_targetVelocity[i];
+ m_maxMotorForce[i] = other.m_maxMotorForce[i];
+
+ m_currentLimit[i] = other.m_currentLimit[i];
+ }
+ }
+
+ inline bool isLimited(int limitIndex)
+ {
+ return (m_upperLimit[limitIndex] >= m_lowerLimit[limitIndex]);
+ }
+
+ void testLimitValue(int limitIndex, btScalar test_value);
+};
+
+enum bt6DofFlags2
+{
+ BT_6DOF_FLAGS_CFM_STOP2 = 1,
+ BT_6DOF_FLAGS_ERP_STOP2 = 2,
+ BT_6DOF_FLAGS_CFM_MOTO2 = 4,
+ BT_6DOF_FLAGS_ERP_MOTO2 = 8
+};
+#define BT_6DOF_FLAGS_AXIS_SHIFT2 4 // bits per axis
+
+
+ATTRIBUTE_ALIGNED16(class) btGeneric6DofSpring2Constraint : public btTypedConstraint
+{
+protected:
+
+ btTransform m_frameInA;
+ btTransform m_frameInB;
+
+ btJacobianEntry m_jacLinear[3];
+ btJacobianEntry m_jacAng[3];
+
+ btTranslationalLimitMotor2 m_linearLimits;
+ btRotationalLimitMotor2 m_angularLimits[3];
+
+ RotateOrder m_rotateOrder;
+
+protected:
+
+ btTransform m_calculatedTransformA;
+ btTransform m_calculatedTransformB;
+ btVector3 m_calculatedAxisAngleDiff;
+ btVector3 m_calculatedAxis[3];
+ btVector3 m_calculatedLinearDiff;
+ btScalar m_factA;
+ btScalar m_factB;
+ bool m_hasStaticBody;
+ int m_flags;
+
+ btGeneric6DofSpring2Constraint& operator=(btGeneric6DofSpring2Constraint&)
+ {
+ btAssert(0);
+ return *this;
+ }
+
+ int setAngularLimits(btConstraintInfo2 *info, int row_offset,const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB);
+ int setLinearLimits(btConstraintInfo2 *info, int row, const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB);
+
+ void calculateLinearInfo();
+ void calculateAngleInfo();
+ void testAngularLimitMotor(int axis_index);
+
+ void calculateJacobi(btRotationalLimitMotor2* limot, const btTransform& transA,const btTransform& transB, btConstraintInfo2* info, int srow, btVector3& ax1, int rotational, int rotAllowed);
+ int get_limit_motor_info2(btRotationalLimitMotor2* limot,
+ const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB,
+ btConstraintInfo2* info, int row, btVector3& ax1, int rotational, int rotAllowed = false);
+
+public:
+
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ btGeneric6DofSpring2Constraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, RotateOrder rotOrder = RO_XYZ);
+ btGeneric6DofSpring2Constraint(btRigidBody& rbB, const btTransform& frameInB, RotateOrder rotOrder = RO_XYZ);
+
+ virtual void buildJacobian() {}
+ virtual void getInfo1 (btConstraintInfo1* info);
+ virtual void getInfo2 (btConstraintInfo2* info);
+ virtual int calculateSerializeBufferSize() const;
+ virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
+
+ btRotationalLimitMotor2* getRotationalLimitMotor(int index) { return &m_angularLimits[index]; }
+ btTranslationalLimitMotor2* getTranslationalLimitMotor() { return &m_linearLimits; }
+
+ // Calculates the global transform for the joint offset for body A an B, and also calculates the angle differences between the bodies.
+ void calculateTransforms(const btTransform& transA,const btTransform& transB);
+ void calculateTransforms();
+
+ // Gets the global transform of the offset for body A
+ const btTransform & getCalculatedTransformA() const { return m_calculatedTransformA; }
+ // Gets the global transform of the offset for body B
+ const btTransform & getCalculatedTransformB() const { return m_calculatedTransformB; }
+
+ const btTransform & getFrameOffsetA() const { return m_frameInA; }
+ const btTransform & getFrameOffsetB() const { return m_frameInB; }
+
+ btTransform & getFrameOffsetA() { return m_frameInA; }
+ btTransform & getFrameOffsetB() { return m_frameInB; }
+
+ // Get the rotation axis in global coordinates ( btGeneric6DofSpring2Constraint::calculateTransforms() must be called previously )
+ btVector3 getAxis(int axis_index) const { return m_calculatedAxis[axis_index]; }
+
+ // Get the relative Euler angle ( btGeneric6DofSpring2Constraint::calculateTransforms() must be called previously )
+ btScalar getAngle(int axis_index) const { return m_calculatedAxisAngleDiff[axis_index]; }
+
+ // Get the relative position of the constraint pivot ( btGeneric6DofSpring2Constraint::calculateTransforms() must be called previously )
+ btScalar getRelativePivotPosition(int axis_index) const { return m_calculatedLinearDiff[axis_index]; }
+
+ void setFrames(const btTransform & frameA, const btTransform & frameB);
+
+ void setLinearLowerLimit(const btVector3& linearLower) { m_linearLimits.m_lowerLimit = linearLower; }
+ void getLinearLowerLimit(btVector3& linearLower) { linearLower = m_linearLimits.m_lowerLimit; }
+ void setLinearUpperLimit(const btVector3& linearUpper) { m_linearLimits.m_upperLimit = linearUpper; }
+ void getLinearUpperLimit(btVector3& linearUpper) { linearUpper = m_linearLimits.m_upperLimit; }
+
+ void setAngularLowerLimit(const btVector3& angularLower)
+ {
+ for(int i = 0; i < 3; i++)
+ m_angularLimits[i].m_loLimit = btNormalizeAngle(angularLower[i]);
+ }
+
+ void setAngularLowerLimitReversed(const btVector3& angularLower)
+ {
+ for(int i = 0; i < 3; i++)
+ m_angularLimits[i].m_hiLimit = btNormalizeAngle(-angularLower[i]);
+ }
+
+ void getAngularLowerLimit(btVector3& angularLower)
+ {
+ for(int i = 0; i < 3; i++)
+ angularLower[i] = m_angularLimits[i].m_loLimit;
+ }
+
+ void getAngularLowerLimitReversed(btVector3& angularLower)
+ {
+ for(int i = 0; i < 3; i++)
+ angularLower[i] = -m_angularLimits[i].m_hiLimit;
+ }
+
+ void setAngularUpperLimit(const btVector3& angularUpper)
+ {
+ for(int i = 0; i < 3; i++)
+ m_angularLimits[i].m_hiLimit = btNormalizeAngle(angularUpper[i]);
+ }
+
+ void setAngularUpperLimitReversed(const btVector3& angularUpper)
+ {
+ for(int i = 0; i < 3; i++)
+ m_angularLimits[i].m_loLimit = btNormalizeAngle(-angularUpper[i]);
+ }
+
+ void getAngularUpperLimit(btVector3& angularUpper)
+ {
+ for(int i = 0; i < 3; i++)
+ angularUpper[i] = m_angularLimits[i].m_hiLimit;
+ }
+
+ void getAngularUpperLimitReversed(btVector3& angularUpper)
+ {
+ for(int i = 0; i < 3; i++)
+ angularUpper[i] = -m_angularLimits[i].m_loLimit;
+ }
+
+ //first 3 are linear, next 3 are angular
+
+ void setLimit(int axis, btScalar lo, btScalar hi)
+ {
+ if(axis<3)
+ {
+ m_linearLimits.m_lowerLimit[axis] = lo;
+ m_linearLimits.m_upperLimit[axis] = hi;
+ }
+ else
+ {
+ lo = btNormalizeAngle(lo);
+ hi = btNormalizeAngle(hi);
+ m_angularLimits[axis-3].m_loLimit = lo;
+ m_angularLimits[axis-3].m_hiLimit = hi;
+ }
+ }
+
+ void setLimitReversed(int axis, btScalar lo, btScalar hi)
+ {
+ if(axis<3)
+ {
+ m_linearLimits.m_lowerLimit[axis] = lo;
+ m_linearLimits.m_upperLimit[axis] = hi;
+ }
+ else
+ {
+ lo = btNormalizeAngle(lo);
+ hi = btNormalizeAngle(hi);
+ m_angularLimits[axis-3].m_hiLimit = -lo;
+ m_angularLimits[axis-3].m_loLimit = -hi;
+ }
+ }
+
+ bool isLimited(int limitIndex)
+ {
+ if(limitIndex<3)
+ {
+ return m_linearLimits.isLimited(limitIndex);
+ }
+ return m_angularLimits[limitIndex-3].isLimited();
+ }
+
+ void setRotationOrder(RotateOrder order) { m_rotateOrder = order; }
+ RotateOrder getRotationOrder() { return m_rotateOrder; }
+
+ void setAxis( const btVector3& axis1, const btVector3& axis2);
+
+ void setBounce(int index, btScalar bounce);
+
+ void enableMotor(int index, bool onOff);
+ void setServo(int index, bool onOff); // set the type of the motor (servo or not) (the motor has to be turned on for servo also)
+ void setTargetVelocity(int index, btScalar velocity);
+ void setServoTarget(int index, btScalar target);
+ void setMaxMotorForce(int index, btScalar force);
+
+ void enableSpring(int index, bool onOff);
+ void setStiffness(int index, btScalar stiffness, bool limitIfNeeded = true); // if limitIfNeeded is true the system will automatically limit the stiffness in necessary situations where otherwise the spring would move unrealistically too widely
+ void setDamping(int index, btScalar damping, bool limitIfNeeded = true); // if limitIfNeeded is true the system will automatically limit the damping in necessary situations where otherwise the spring would blow up
+ void setEquilibriumPoint(); // set the current constraint position/orientation as an equilibrium point for all DOF
+ void setEquilibriumPoint(int index); // set the current constraint position/orientation as an equilibrium point for given DOF
+ void setEquilibriumPoint(int index, btScalar val);
+
+ //override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
+ //If no axis is provided, it uses the default axis for this constraint.
+ virtual void setParam(int num, btScalar value, int axis = -1);
+ virtual btScalar getParam(int num, int axis = -1) const;
+
+ static btScalar btGetMatrixElem(const btMatrix3x3& mat, int index);
+ static bool matrixToEulerXYZ(const btMatrix3x3& mat,btVector3& xyz);
+ static bool matrixToEulerXZY(const btMatrix3x3& mat,btVector3& xyz);
+ static bool matrixToEulerYXZ(const btMatrix3x3& mat,btVector3& xyz);
+ static bool matrixToEulerYZX(const btMatrix3x3& mat,btVector3& xyz);
+ static bool matrixToEulerZXY(const btMatrix3x3& mat,btVector3& xyz);
+ static bool matrixToEulerZYX(const btMatrix3x3& mat,btVector3& xyz);
+};
+
+
+struct btGeneric6DofSpring2ConstraintData
+{
+ btTypedConstraintData m_typeConstraintData;
+ btTransformFloatData m_rbAFrame;
+ btTransformFloatData m_rbBFrame;
+
+ btVector3FloatData m_linearUpperLimit;
+ btVector3FloatData m_linearLowerLimit;
+ btVector3FloatData m_linearBounce;
+ btVector3FloatData m_linearStopERP;
+ btVector3FloatData m_linearStopCFM;
+ btVector3FloatData m_linearMotorERP;
+ btVector3FloatData m_linearMotorCFM;
+ btVector3FloatData m_linearTargetVelocity;
+ btVector3FloatData m_linearMaxMotorForce;
+ btVector3FloatData m_linearServoTarget;
+ btVector3FloatData m_linearSpringStiffness;
+ btVector3FloatData m_linearSpringDamping;
+ btVector3FloatData m_linearEquilibriumPoint;
+ char m_linearEnableMotor[4];
+ char m_linearServoMotor[4];
+ char m_linearEnableSpring[4];
+ char m_linearSpringStiffnessLimited[4];
+ char m_linearSpringDampingLimited[4];
+ char m_padding1[4];
+
+ btVector3FloatData m_angularUpperLimit;
+ btVector3FloatData m_angularLowerLimit;
+ btVector3FloatData m_angularBounce;
+ btVector3FloatData m_angularStopERP;
+ btVector3FloatData m_angularStopCFM;
+ btVector3FloatData m_angularMotorERP;
+ btVector3FloatData m_angularMotorCFM;
+ btVector3FloatData m_angularTargetVelocity;
+ btVector3FloatData m_angularMaxMotorForce;
+ btVector3FloatData m_angularServoTarget;
+ btVector3FloatData m_angularSpringStiffness;
+ btVector3FloatData m_angularSpringDamping;
+ btVector3FloatData m_angularEquilibriumPoint;
+ char m_angularEnableMotor[4];
+ char m_angularServoMotor[4];
+ char m_angularEnableSpring[4];
+ char m_angularSpringStiffnessLimited[4];
+ char m_angularSpringDampingLimited[4];
+
+ int m_rotateOrder;
+};
+
+struct btGeneric6DofSpring2ConstraintDoubleData2
+{
+ btTypedConstraintDoubleData m_typeConstraintData;
+ btTransformDoubleData m_rbAFrame;
+ btTransformDoubleData m_rbBFrame;
+
+ btVector3DoubleData m_linearUpperLimit;
+ btVector3DoubleData m_linearLowerLimit;
+ btVector3DoubleData m_linearBounce;
+ btVector3DoubleData m_linearStopERP;
+ btVector3DoubleData m_linearStopCFM;
+ btVector3DoubleData m_linearMotorERP;
+ btVector3DoubleData m_linearMotorCFM;
+ btVector3DoubleData m_linearTargetVelocity;
+ btVector3DoubleData m_linearMaxMotorForce;
+ btVector3DoubleData m_linearServoTarget;
+ btVector3DoubleData m_linearSpringStiffness;
+ btVector3DoubleData m_linearSpringDamping;
+ btVector3DoubleData m_linearEquilibriumPoint;
+ char m_linearEnableMotor[4];
+ char m_linearServoMotor[4];
+ char m_linearEnableSpring[4];
+ char m_linearSpringStiffnessLimited[4];
+ char m_linearSpringDampingLimited[4];
+ char m_padding1[4];
+
+ btVector3DoubleData m_angularUpperLimit;
+ btVector3DoubleData m_angularLowerLimit;
+ btVector3DoubleData m_angularBounce;
+ btVector3DoubleData m_angularStopERP;
+ btVector3DoubleData m_angularStopCFM;
+ btVector3DoubleData m_angularMotorERP;
+ btVector3DoubleData m_angularMotorCFM;
+ btVector3DoubleData m_angularTargetVelocity;
+ btVector3DoubleData m_angularMaxMotorForce;
+ btVector3DoubleData m_angularServoTarget;
+ btVector3DoubleData m_angularSpringStiffness;
+ btVector3DoubleData m_angularSpringDamping;
+ btVector3DoubleData m_angularEquilibriumPoint;
+ char m_angularEnableMotor[4];
+ char m_angularServoMotor[4];
+ char m_angularEnableSpring[4];
+ char m_angularSpringStiffnessLimited[4];
+ char m_angularSpringDampingLimited[4];
+
+ int m_rotateOrder;
+};
+
+SIMD_FORCE_INLINE int btGeneric6DofSpring2Constraint::calculateSerializeBufferSize() const
+{
+ return sizeof(btGeneric6DofSpring2ConstraintData2);
+}
+
+SIMD_FORCE_INLINE const char* btGeneric6DofSpring2Constraint::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+ btGeneric6DofSpring2ConstraintData2* dof = (btGeneric6DofSpring2ConstraintData2*)dataBuffer;
+ btTypedConstraint::serialize(&dof->m_typeConstraintData,serializer);
+
+ m_frameInA.serialize(dof->m_rbAFrame);
+ m_frameInB.serialize(dof->m_rbBFrame);
+
+ int i;
+ for (i=0;i<3;i++)
+ {
+ dof->m_angularLowerLimit.m_floats[i] = m_angularLimits[i].m_loLimit;
+ dof->m_angularUpperLimit.m_floats[i] = m_angularLimits[i].m_hiLimit;
+ dof->m_angularBounce.m_floats[i] = m_angularLimits[i].m_bounce;
+ dof->m_angularStopERP.m_floats[i] = m_angularLimits[i].m_stopERP;
+ dof->m_angularStopCFM.m_floats[i] = m_angularLimits[i].m_stopCFM;
+ dof->m_angularMotorERP.m_floats[i] = m_angularLimits[i].m_motorERP;
+ dof->m_angularMotorCFM.m_floats[i] = m_angularLimits[i].m_motorCFM;
+ dof->m_angularTargetVelocity.m_floats[i] = m_angularLimits[i].m_targetVelocity;
+ dof->m_angularMaxMotorForce.m_floats[i] = m_angularLimits[i].m_maxMotorForce;
+ dof->m_angularServoTarget.m_floats[i] = m_angularLimits[i].m_servoTarget;
+ dof->m_angularSpringStiffness.m_floats[i] = m_angularLimits[i].m_springStiffness;
+ dof->m_angularSpringDamping.m_floats[i] = m_angularLimits[i].m_springDamping;
+ dof->m_angularEquilibriumPoint.m_floats[i] = m_angularLimits[i].m_equilibriumPoint;
+ }
+ dof->m_angularLowerLimit.m_floats[3] = 0;
+ dof->m_angularUpperLimit.m_floats[3] = 0;
+ dof->m_angularBounce.m_floats[3] = 0;
+ dof->m_angularStopERP.m_floats[3] = 0;
+ dof->m_angularStopCFM.m_floats[3] = 0;
+ dof->m_angularMotorERP.m_floats[3] = 0;
+ dof->m_angularMotorCFM.m_floats[3] = 0;
+ dof->m_angularTargetVelocity.m_floats[3] = 0;
+ dof->m_angularMaxMotorForce.m_floats[3] = 0;
+ dof->m_angularServoTarget.m_floats[3] = 0;
+ dof->m_angularSpringStiffness.m_floats[3] = 0;
+ dof->m_angularSpringDamping.m_floats[3] = 0;
+ dof->m_angularEquilibriumPoint.m_floats[3] = 0;
+ for (i=0;i<4;i++)
+ {
+ dof->m_angularEnableMotor[i] = i < 3 ? ( m_angularLimits[i].m_enableMotor ? 1 : 0 ) : 0;
+ dof->m_angularServoMotor[i] = i < 3 ? ( m_angularLimits[i].m_servoMotor ? 1 : 0 ) : 0;
+ dof->m_angularEnableSpring[i] = i < 3 ? ( m_angularLimits[i].m_enableSpring ? 1 : 0 ) : 0;
+ dof->m_angularSpringStiffnessLimited[i] = i < 3 ? ( m_angularLimits[i].m_springStiffnessLimited ? 1 : 0 ) : 0;
+ dof->m_angularSpringDampingLimited[i] = i < 3 ? ( m_angularLimits[i].m_springDampingLimited ? 1 : 0 ) : 0;
+ }
+
+ m_linearLimits.m_lowerLimit.serialize( dof->m_linearLowerLimit );
+ m_linearLimits.m_upperLimit.serialize( dof->m_linearUpperLimit );
+ m_linearLimits.m_bounce.serialize( dof->m_linearBounce );
+ m_linearLimits.m_stopERP.serialize( dof->m_linearStopERP );
+ m_linearLimits.m_stopCFM.serialize( dof->m_linearStopCFM );
+ m_linearLimits.m_motorERP.serialize( dof->m_linearMotorERP );
+ m_linearLimits.m_motorCFM.serialize( dof->m_linearMotorCFM );
+ m_linearLimits.m_targetVelocity.serialize( dof->m_linearTargetVelocity );
+ m_linearLimits.m_maxMotorForce.serialize( dof->m_linearMaxMotorForce );
+ m_linearLimits.m_servoTarget.serialize( dof->m_linearServoTarget );
+ m_linearLimits.m_springStiffness.serialize( dof->m_linearSpringStiffness );
+ m_linearLimits.m_springDamping.serialize( dof->m_linearSpringDamping );
+ m_linearLimits.m_equilibriumPoint.serialize( dof->m_linearEquilibriumPoint );
+ for (i=0;i<4;i++)
+ {
+ dof->m_linearEnableMotor[i] = i < 3 ? ( m_linearLimits.m_enableMotor[i] ? 1 : 0 ) : 0;
+ dof->m_linearServoMotor[i] = i < 3 ? ( m_linearLimits.m_servoMotor[i] ? 1 : 0 ) : 0;
+ dof->m_linearEnableSpring[i] = i < 3 ? ( m_linearLimits.m_enableSpring[i] ? 1 : 0 ) : 0;
+ dof->m_linearSpringStiffnessLimited[i] = i < 3 ? ( m_linearLimits.m_springStiffnessLimited[i] ? 1 : 0 ) : 0;
+ dof->m_linearSpringDampingLimited[i] = i < 3 ? ( m_linearLimits.m_springDampingLimited[i] ? 1 : 0 ) : 0;
+ }
+
+ dof->m_rotateOrder = m_rotateOrder;
+
+ dof->m_padding1[0] = 0;
+ dof->m_padding1[1] = 0;
+ dof->m_padding1[2] = 0;
+ dof->m_padding1[3] = 0;
+
+ return btGeneric6DofSpring2ConstraintDataName;
+}
+
+
+
+
+
+#endif //BT_GENERIC_6DOF_CONSTRAINT_H
diff --git a/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp
new file mode 100644
index 0000000000..6f765884ec
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp
@@ -0,0 +1,185 @@
+/*
+Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org
+Copyright (C) 2006, 2007 Sony Computer Entertainment Inc.
+
+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 "btGeneric6DofSpringConstraint.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "LinearMath/btTransformUtil.h"
+
+
+btGeneric6DofSpringConstraint::btGeneric6DofSpringConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ,bool useLinearReferenceFrameA)
+ : btGeneric6DofConstraint(rbA, rbB, frameInA, frameInB, useLinearReferenceFrameA)
+{
+ init();
+}
+
+
+btGeneric6DofSpringConstraint::btGeneric6DofSpringConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameB)
+ : btGeneric6DofConstraint(rbB, frameInB, useLinearReferenceFrameB)
+{
+ init();
+}
+
+
+void btGeneric6DofSpringConstraint::init()
+{
+ m_objectType = D6_SPRING_CONSTRAINT_TYPE;
+
+ for(int i = 0; i < 6; i++)
+ {
+ m_springEnabled[i] = false;
+ m_equilibriumPoint[i] = btScalar(0.f);
+ m_springStiffness[i] = btScalar(0.f);
+ m_springDamping[i] = btScalar(1.f);
+ }
+}
+
+
+void btGeneric6DofSpringConstraint::enableSpring(int index, bool onOff)
+{
+ btAssert((index >= 0) && (index < 6));
+ m_springEnabled[index] = onOff;
+ if(index < 3)
+ {
+ m_linearLimits.m_enableMotor[index] = onOff;
+ }
+ else
+ {
+ m_angularLimits[index - 3].m_enableMotor = onOff;
+ }
+}
+
+
+
+void btGeneric6DofSpringConstraint::setStiffness(int index, btScalar stiffness)
+{
+ btAssert((index >= 0) && (index < 6));
+ m_springStiffness[index] = stiffness;
+}
+
+
+void btGeneric6DofSpringConstraint::setDamping(int index, btScalar damping)
+{
+ btAssert((index >= 0) && (index < 6));
+ m_springDamping[index] = damping;
+}
+
+
+void btGeneric6DofSpringConstraint::setEquilibriumPoint()
+{
+ calculateTransforms();
+ int i;
+
+ for( i = 0; i < 3; i++)
+ {
+ m_equilibriumPoint[i] = m_calculatedLinearDiff[i];
+ }
+ for(i = 0; i < 3; i++)
+ {
+ m_equilibriumPoint[i + 3] = m_calculatedAxisAngleDiff[i];
+ }
+}
+
+
+
+void btGeneric6DofSpringConstraint::setEquilibriumPoint(int index)
+{
+ btAssert((index >= 0) && (index < 6));
+ calculateTransforms();
+ if(index < 3)
+ {
+ m_equilibriumPoint[index] = m_calculatedLinearDiff[index];
+ }
+ else
+ {
+ m_equilibriumPoint[index] = m_calculatedAxisAngleDiff[index - 3];
+ }
+}
+
+void btGeneric6DofSpringConstraint::setEquilibriumPoint(int index, btScalar val)
+{
+ btAssert((index >= 0) && (index < 6));
+ m_equilibriumPoint[index] = val;
+}
+
+
+void btGeneric6DofSpringConstraint::internalUpdateSprings(btConstraintInfo2* info)
+{
+ // it is assumed that calculateTransforms() have been called before this call
+ int i;
+ //btVector3 relVel = m_rbB.getLinearVelocity() - m_rbA.getLinearVelocity();
+ for(i = 0; i < 3; i++)
+ {
+ if(m_springEnabled[i])
+ {
+ // get current position of constraint
+ btScalar currPos = m_calculatedLinearDiff[i];
+ // calculate difference
+ btScalar delta = currPos - m_equilibriumPoint[i];
+ // spring force is (delta * m_stiffness) according to Hooke's Law
+ btScalar force = delta * m_springStiffness[i];
+ btScalar velFactor = info->fps * m_springDamping[i] / btScalar(info->m_numIterations);
+ m_linearLimits.m_targetVelocity[i] = velFactor * force;
+ m_linearLimits.m_maxMotorForce[i] = btFabs(force) / info->fps;
+ }
+ }
+ for(i = 0; i < 3; i++)
+ {
+ if(m_springEnabled[i + 3])
+ {
+ // get current position of constraint
+ btScalar currPos = m_calculatedAxisAngleDiff[i];
+ // calculate difference
+ btScalar delta = currPos - m_equilibriumPoint[i+3];
+ // spring force is (-delta * m_stiffness) according to Hooke's Law
+ btScalar force = -delta * m_springStiffness[i+3];
+ btScalar velFactor = info->fps * m_springDamping[i+3] / btScalar(info->m_numIterations);
+ m_angularLimits[i].m_targetVelocity = velFactor * force;
+ m_angularLimits[i].m_maxMotorForce = btFabs(force) / info->fps;
+ }
+ }
+}
+
+
+void btGeneric6DofSpringConstraint::getInfo2(btConstraintInfo2* info)
+{
+ // this will be called by constraint solver at the constraint setup stage
+ // set current motor parameters
+ internalUpdateSprings(info);
+ // do the rest of job for constraint setup
+ btGeneric6DofConstraint::getInfo2(info);
+}
+
+
+void btGeneric6DofSpringConstraint::setAxis(const btVector3& axis1,const btVector3& axis2)
+{
+ btVector3 zAxis = axis1.normalized();
+ btVector3 yAxis = axis2.normalized();
+ btVector3 xAxis = yAxis.cross(zAxis); // we want right coordinate system
+
+ btTransform frameInW;
+ frameInW.setIdentity();
+ frameInW.getBasis().setValue( xAxis[0], yAxis[0], zAxis[0],
+ xAxis[1], yAxis[1], zAxis[1],
+ xAxis[2], yAxis[2], zAxis[2]);
+
+ // now get constraint frame in local coordinate systems
+ m_frameInA = m_rbA.getCenterOfMassTransform().inverse() * frameInW;
+ m_frameInB = m_rbB.getCenterOfMassTransform().inverse() * frameInW;
+
+ calculateTransforms();
+}
+
+
+
diff --git a/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h
new file mode 100644
index 0000000000..dac59c6889
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h
@@ -0,0 +1,141 @@
+/*
+Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org
+Copyright (C) 2006, 2007 Sony Computer Entertainment Inc.
+
+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_GENERIC_6DOF_SPRING_CONSTRAINT_H
+#define BT_GENERIC_6DOF_SPRING_CONSTRAINT_H
+
+
+#include "LinearMath/btVector3.h"
+#include "btTypedConstraint.h"
+#include "btGeneric6DofConstraint.h"
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define btGeneric6DofSpringConstraintData2 btGeneric6DofSpringConstraintDoubleData2
+#define btGeneric6DofSpringConstraintDataName "btGeneric6DofSpringConstraintDoubleData2"
+#else
+#define btGeneric6DofSpringConstraintData2 btGeneric6DofSpringConstraintData
+#define btGeneric6DofSpringConstraintDataName "btGeneric6DofSpringConstraintData"
+#endif //BT_USE_DOUBLE_PRECISION
+
+
+
+/// Generic 6 DOF constraint that allows to set spring motors to any translational and rotational DOF
+
+/// DOF index used in enableSpring() and setStiffness() means:
+/// 0 : translation X
+/// 1 : translation Y
+/// 2 : translation Z
+/// 3 : rotation X (3rd Euler rotational around new position of X axis, range [-PI+epsilon, PI-epsilon] )
+/// 4 : rotation Y (2nd Euler rotational around new position of Y axis, range [-PI/2+epsilon, PI/2-epsilon] )
+/// 5 : rotation Z (1st Euler rotational around Z axis, range [-PI+epsilon, PI-epsilon] )
+
+ATTRIBUTE_ALIGNED16(class) btGeneric6DofSpringConstraint : public btGeneric6DofConstraint
+{
+protected:
+ bool m_springEnabled[6];
+ btScalar m_equilibriumPoint[6];
+ btScalar m_springStiffness[6];
+ btScalar m_springDamping[6]; // between 0 and 1 (1 == no damping)
+ void init();
+ void internalUpdateSprings(btConstraintInfo2* info);
+public:
+
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ btGeneric6DofSpringConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ,bool useLinearReferenceFrameA);
+ btGeneric6DofSpringConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameB);
+ void enableSpring(int index, bool onOff);
+ void setStiffness(int index, btScalar stiffness);
+ void setDamping(int index, btScalar damping);
+ void setEquilibriumPoint(); // set the current constraint position/orientation as an equilibrium point for all DOF
+ void setEquilibriumPoint(int index); // set the current constraint position/orientation as an equilibrium point for given DOF
+ void setEquilibriumPoint(int index, btScalar val);
+
+ bool isSpringEnabled(int index) const
+ {
+ return m_springEnabled[index];
+ }
+
+ btScalar getStiffness(int index) const
+ {
+ return m_springStiffness[index];
+ }
+
+ btScalar getDamping(int index) const
+ {
+ return m_springDamping[index];
+ }
+
+ btScalar getEquilibriumPoint(int index) const
+ {
+ return m_equilibriumPoint[index];
+ }
+
+ virtual void setAxis( const btVector3& axis1, const btVector3& axis2);
+
+ virtual void getInfo2 (btConstraintInfo2* info);
+
+ virtual int calculateSerializeBufferSize() const;
+ ///fills the dataBuffer and returns the struct name (and 0 on failure)
+ virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
+
+};
+
+
+struct btGeneric6DofSpringConstraintData
+{
+ btGeneric6DofConstraintData m_6dofData;
+
+ int m_springEnabled[6];
+ float m_equilibriumPoint[6];
+ float m_springStiffness[6];
+ float m_springDamping[6];
+};
+
+struct btGeneric6DofSpringConstraintDoubleData2
+{
+ btGeneric6DofConstraintDoubleData2 m_6dofData;
+
+ int m_springEnabled[6];
+ double m_equilibriumPoint[6];
+ double m_springStiffness[6];
+ double m_springDamping[6];
+};
+
+
+SIMD_FORCE_INLINE int btGeneric6DofSpringConstraint::calculateSerializeBufferSize() const
+{
+ return sizeof(btGeneric6DofSpringConstraintData2);
+}
+
+ ///fills the dataBuffer and returns the struct name (and 0 on failure)
+SIMD_FORCE_INLINE const char* btGeneric6DofSpringConstraint::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+ btGeneric6DofSpringConstraintData2* dof = (btGeneric6DofSpringConstraintData2*)dataBuffer;
+ btGeneric6DofConstraint::serialize(&dof->m_6dofData,serializer);
+
+ int i;
+ for (i=0;i<6;i++)
+ {
+ dof->m_equilibriumPoint[i] = m_equilibriumPoint[i];
+ dof->m_springDamping[i] = m_springDamping[i];
+ dof->m_springEnabled[i] = m_springEnabled[i]? 1 : 0;
+ dof->m_springStiffness[i] = m_springStiffness[i];
+ }
+ return btGeneric6DofSpringConstraintDataName;
+}
+
+#endif // BT_GENERIC_6DOF_SPRING_CONSTRAINT_H
+
diff --git a/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btHinge2Constraint.cpp b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btHinge2Constraint.cpp
new file mode 100644
index 0000000000..4be2aabe4d
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btHinge2Constraint.cpp
@@ -0,0 +1,66 @@
+/*
+Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org
+Copyright (C) 2006, 2007 Sony Computer Entertainment Inc.
+
+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 "btHinge2Constraint.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "LinearMath/btTransformUtil.h"
+
+
+
+// constructor
+// anchor, axis1 and axis2 are in world coordinate system
+// axis1 must be orthogonal to axis2
+btHinge2Constraint::btHinge2Constraint(btRigidBody& rbA, btRigidBody& rbB, btVector3& anchor, btVector3& axis1, btVector3& axis2)
+: btGeneric6DofSpring2Constraint(rbA, rbB, btTransform::getIdentity(), btTransform::getIdentity(),RO_XYZ),
+ m_anchor(anchor),
+ m_axis1(axis1),
+ m_axis2(axis2)
+{
+ // build frame basis
+ // 6DOF constraint uses Euler angles and to define limits
+ // it is assumed that rotational order is :
+ // Z - first, allowed limits are (-PI,PI);
+ // new position of Y - second (allowed limits are (-PI/2 + epsilon, PI/2 - epsilon), where epsilon is a small positive number
+ // used to prevent constraint from instability on poles;
+ // new position of X, allowed limits are (-PI,PI);
+ // So to simulate ODE Universal joint we should use parent axis as Z, child axis as Y and limit all other DOFs
+ // Build the frame in world coordinate system first
+ btVector3 zAxis = axis1.normalize();
+ btVector3 xAxis = axis2.normalize();
+ btVector3 yAxis = zAxis.cross(xAxis); // we want right coordinate system
+ btTransform frameInW;
+ frameInW.setIdentity();
+ frameInW.getBasis().setValue( xAxis[0], yAxis[0], zAxis[0],
+ xAxis[1], yAxis[1], zAxis[1],
+ xAxis[2], yAxis[2], zAxis[2]);
+ frameInW.setOrigin(anchor);
+ // now get constraint frame in local coordinate systems
+ m_frameInA = rbA.getCenterOfMassTransform().inverse() * frameInW;
+ m_frameInB = rbB.getCenterOfMassTransform().inverse() * frameInW;
+ // sei limits
+ setLinearLowerLimit(btVector3(0.f, 0.f, -1.f));
+ setLinearUpperLimit(btVector3(0.f, 0.f, 1.f));
+ // like front wheels of a car
+ setAngularLowerLimit(btVector3(1.f, 0.f, -SIMD_HALF_PI * 0.5f));
+ setAngularUpperLimit(btVector3(-1.f, 0.f, SIMD_HALF_PI * 0.5f));
+ // enable suspension
+ enableSpring(2, true);
+ setStiffness(2, SIMD_PI * SIMD_PI * 4.f);
+ setDamping(2, 0.01f);
+ setEquilibriumPoint();
+}
+
diff --git a/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btHinge2Constraint.h b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btHinge2Constraint.h
new file mode 100644
index 0000000000..06a8e3ecd1
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btHinge2Constraint.h
@@ -0,0 +1,60 @@
+/*
+Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org
+Copyright (C) 2006, 2007 Sony Computer Entertainment Inc.
+
+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_HINGE2_CONSTRAINT_H
+#define BT_HINGE2_CONSTRAINT_H
+
+
+
+#include "LinearMath/btVector3.h"
+#include "btTypedConstraint.h"
+#include "btGeneric6DofSpring2Constraint.h"
+
+
+
+// Constraint similar to ODE Hinge2 Joint
+// has 3 degrees of frredom:
+// 2 rotational degrees of freedom, similar to Euler rotations around Z (axis 1) and X (axis 2)
+// 1 translational (along axis Z) with suspension spring
+
+ATTRIBUTE_ALIGNED16(class) btHinge2Constraint : public btGeneric6DofSpring2Constraint
+{
+protected:
+ btVector3 m_anchor;
+ btVector3 m_axis1;
+ btVector3 m_axis2;
+public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ // constructor
+ // anchor, axis1 and axis2 are in world coordinate system
+ // axis1 must be orthogonal to axis2
+ btHinge2Constraint(btRigidBody& rbA, btRigidBody& rbB, btVector3& anchor, btVector3& axis1, btVector3& axis2);
+ // access
+ const btVector3& getAnchor() { return m_calculatedTransformA.getOrigin(); }
+ const btVector3& getAnchor2() { return m_calculatedTransformB.getOrigin(); }
+ const btVector3& getAxis1() { return m_axis1; }
+ const btVector3& getAxis2() { return m_axis2; }
+ btScalar getAngle1() { return getAngle(2); }
+ btScalar getAngle2() { return getAngle(0); }
+ // limits
+ void setUpperLimit(btScalar ang1max) { setAngularUpperLimit(btVector3(-1.f, 0.f, ang1max)); }
+ void setLowerLimit(btScalar ang1min) { setAngularLowerLimit(btVector3( 1.f, 0.f, ang1min)); }
+};
+
+
+
+#endif // BT_HINGE2_CONSTRAINT_H
+
diff --git a/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp
new file mode 100644
index 0000000000..7e5e6f9e54
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp
@@ -0,0 +1,1120 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "btHingeConstraint.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "LinearMath/btTransformUtil.h"
+#include "LinearMath/btMinMax.h"
+#include <new>
+#include "btSolverBody.h"
+
+
+
+//#define HINGE_USE_OBSOLETE_SOLVER false
+#define HINGE_USE_OBSOLETE_SOLVER false
+
+#define HINGE_USE_FRAME_OFFSET true
+
+#ifndef __SPU__
+
+
+
+
+
+btHingeConstraint::btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB,
+ const btVector3& axisInA,const btVector3& axisInB, bool useReferenceFrameA)
+ :btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA,rbB),
+#ifdef _BT_USE_CENTER_LIMIT_
+ m_limit(),
+#endif
+ m_angularOnly(false),
+ m_enableAngularMotor(false),
+ m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER),
+ m_useOffsetForConstraintFrame(HINGE_USE_FRAME_OFFSET),
+ m_useReferenceFrameA(useReferenceFrameA),
+ m_flags(0),
+ m_normalCFM(0),
+ m_normalERP(0),
+ m_stopCFM(0),
+ m_stopERP(0)
+{
+ m_rbAFrame.getOrigin() = pivotInA;
+
+ // since no frame is given, assume this to be zero angle and just pick rb transform axis
+ btVector3 rbAxisA1 = rbA.getCenterOfMassTransform().getBasis().getColumn(0);
+
+ btVector3 rbAxisA2;
+ btScalar projection = axisInA.dot(rbAxisA1);
+ if (projection >= 1.0f - SIMD_EPSILON) {
+ rbAxisA1 = -rbA.getCenterOfMassTransform().getBasis().getColumn(2);
+ rbAxisA2 = rbA.getCenterOfMassTransform().getBasis().getColumn(1);
+ } else if (projection <= -1.0f + SIMD_EPSILON) {
+ rbAxisA1 = rbA.getCenterOfMassTransform().getBasis().getColumn(2);
+ rbAxisA2 = rbA.getCenterOfMassTransform().getBasis().getColumn(1);
+ } else {
+ rbAxisA2 = axisInA.cross(rbAxisA1);
+ rbAxisA1 = rbAxisA2.cross(axisInA);
+ }
+
+ m_rbAFrame.getBasis().setValue( rbAxisA1.getX(),rbAxisA2.getX(),axisInA.getX(),
+ rbAxisA1.getY(),rbAxisA2.getY(),axisInA.getY(),
+ rbAxisA1.getZ(),rbAxisA2.getZ(),axisInA.getZ() );
+
+ btQuaternion rotationArc = shortestArcQuat(axisInA,axisInB);
+ btVector3 rbAxisB1 = quatRotate(rotationArc,rbAxisA1);
+ btVector3 rbAxisB2 = axisInB.cross(rbAxisB1);
+
+ m_rbBFrame.getOrigin() = pivotInB;
+ m_rbBFrame.getBasis().setValue( rbAxisB1.getX(),rbAxisB2.getX(),axisInB.getX(),
+ rbAxisB1.getY(),rbAxisB2.getY(),axisInB.getY(),
+ rbAxisB1.getZ(),rbAxisB2.getZ(),axisInB.getZ() );
+
+#ifndef _BT_USE_CENTER_LIMIT_
+ //start with free
+ m_lowerLimit = btScalar(1.0f);
+ m_upperLimit = btScalar(-1.0f);
+ m_biasFactor = 0.3f;
+ m_relaxationFactor = 1.0f;
+ m_limitSoftness = 0.9f;
+ m_solveLimit = false;
+#endif
+ m_referenceSign = m_useReferenceFrameA ? btScalar(-1.f) : btScalar(1.f);
+}
+
+
+
+btHingeConstraint::btHingeConstraint(btRigidBody& rbA,const btVector3& pivotInA,const btVector3& axisInA, bool useReferenceFrameA)
+:btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA),
+#ifdef _BT_USE_CENTER_LIMIT_
+m_limit(),
+#endif
+m_angularOnly(false), m_enableAngularMotor(false),
+m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER),
+m_useOffsetForConstraintFrame(HINGE_USE_FRAME_OFFSET),
+m_useReferenceFrameA(useReferenceFrameA),
+m_flags(0),
+m_normalCFM(0),
+m_normalERP(0),
+m_stopCFM(0),
+m_stopERP(0)
+{
+
+ // since no frame is given, assume this to be zero angle and just pick rb transform axis
+ // fixed axis in worldspace
+ btVector3 rbAxisA1, rbAxisA2;
+ btPlaneSpace1(axisInA, rbAxisA1, rbAxisA2);
+
+ m_rbAFrame.getOrigin() = pivotInA;
+ m_rbAFrame.getBasis().setValue( rbAxisA1.getX(),rbAxisA2.getX(),axisInA.getX(),
+ rbAxisA1.getY(),rbAxisA2.getY(),axisInA.getY(),
+ rbAxisA1.getZ(),rbAxisA2.getZ(),axisInA.getZ() );
+
+ btVector3 axisInB = rbA.getCenterOfMassTransform().getBasis() * axisInA;
+
+ btQuaternion rotationArc = shortestArcQuat(axisInA,axisInB);
+ btVector3 rbAxisB1 = quatRotate(rotationArc,rbAxisA1);
+ btVector3 rbAxisB2 = axisInB.cross(rbAxisB1);
+
+
+ m_rbBFrame.getOrigin() = rbA.getCenterOfMassTransform()(pivotInA);
+ m_rbBFrame.getBasis().setValue( rbAxisB1.getX(),rbAxisB2.getX(),axisInB.getX(),
+ rbAxisB1.getY(),rbAxisB2.getY(),axisInB.getY(),
+ rbAxisB1.getZ(),rbAxisB2.getZ(),axisInB.getZ() );
+
+#ifndef _BT_USE_CENTER_LIMIT_
+ //start with free
+ m_lowerLimit = btScalar(1.0f);
+ m_upperLimit = btScalar(-1.0f);
+ m_biasFactor = 0.3f;
+ m_relaxationFactor = 1.0f;
+ m_limitSoftness = 0.9f;
+ m_solveLimit = false;
+#endif
+ m_referenceSign = m_useReferenceFrameA ? btScalar(-1.f) : btScalar(1.f);
+}
+
+
+
+btHingeConstraint::btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB,
+ const btTransform& rbAFrame, const btTransform& rbBFrame, bool useReferenceFrameA)
+:btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA,rbB),m_rbAFrame(rbAFrame),m_rbBFrame(rbBFrame),
+#ifdef _BT_USE_CENTER_LIMIT_
+m_limit(),
+#endif
+m_angularOnly(false),
+m_enableAngularMotor(false),
+m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER),
+m_useOffsetForConstraintFrame(HINGE_USE_FRAME_OFFSET),
+m_useReferenceFrameA(useReferenceFrameA),
+m_flags(0),
+m_normalCFM(0),
+m_normalERP(0),
+m_stopCFM(0),
+m_stopERP(0)
+{
+#ifndef _BT_USE_CENTER_LIMIT_
+ //start with free
+ m_lowerLimit = btScalar(1.0f);
+ m_upperLimit = btScalar(-1.0f);
+ m_biasFactor = 0.3f;
+ m_relaxationFactor = 1.0f;
+ m_limitSoftness = 0.9f;
+ m_solveLimit = false;
+#endif
+ m_referenceSign = m_useReferenceFrameA ? btScalar(-1.f) : btScalar(1.f);
+}
+
+
+
+btHingeConstraint::btHingeConstraint(btRigidBody& rbA, const btTransform& rbAFrame, bool useReferenceFrameA)
+:btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA),m_rbAFrame(rbAFrame),m_rbBFrame(rbAFrame),
+#ifdef _BT_USE_CENTER_LIMIT_
+m_limit(),
+#endif
+m_angularOnly(false),
+m_enableAngularMotor(false),
+m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER),
+m_useOffsetForConstraintFrame(HINGE_USE_FRAME_OFFSET),
+m_useReferenceFrameA(useReferenceFrameA),
+m_flags(0),
+m_normalCFM(0),
+m_normalERP(0),
+m_stopCFM(0),
+m_stopERP(0)
+{
+ ///not providing rigidbody B means implicitly using worldspace for body B
+
+ m_rbBFrame.getOrigin() = m_rbA.getCenterOfMassTransform()(m_rbAFrame.getOrigin());
+#ifndef _BT_USE_CENTER_LIMIT_
+ //start with free
+ m_lowerLimit = btScalar(1.0f);
+ m_upperLimit = btScalar(-1.0f);
+ m_biasFactor = 0.3f;
+ m_relaxationFactor = 1.0f;
+ m_limitSoftness = 0.9f;
+ m_solveLimit = false;
+#endif
+ m_referenceSign = m_useReferenceFrameA ? btScalar(-1.f) : btScalar(1.f);
+}
+
+
+
+void btHingeConstraint::buildJacobian()
+{
+ if (m_useSolveConstraintObsolete)
+ {
+ m_appliedImpulse = btScalar(0.);
+ m_accMotorImpulse = btScalar(0.);
+
+ if (!m_angularOnly)
+ {
+ btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_rbAFrame.getOrigin();
+ btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_rbBFrame.getOrigin();
+ btVector3 relPos = pivotBInW - pivotAInW;
+
+ btVector3 normal[3];
+ if (relPos.length2() > SIMD_EPSILON)
+ {
+ normal[0] = relPos.normalized();
+ }
+ else
+ {
+ normal[0].setValue(btScalar(1.0),0,0);
+ }
+
+ btPlaneSpace1(normal[0], normal[1], normal[2]);
+
+ for (int i=0;i<3;i++)
+ {
+ new (&m_jac[i]) btJacobianEntry(
+ m_rbA.getCenterOfMassTransform().getBasis().transpose(),
+ m_rbB.getCenterOfMassTransform().getBasis().transpose(),
+ pivotAInW - m_rbA.getCenterOfMassPosition(),
+ pivotBInW - m_rbB.getCenterOfMassPosition(),
+ normal[i],
+ m_rbA.getInvInertiaDiagLocal(),
+ m_rbA.getInvMass(),
+ m_rbB.getInvInertiaDiagLocal(),
+ m_rbB.getInvMass());
+ }
+ }
+
+ //calculate two perpendicular jointAxis, orthogonal to hingeAxis
+ //these two jointAxis require equal angular velocities for both bodies
+
+ //this is unused for now, it's a todo
+ btVector3 jointAxis0local;
+ btVector3 jointAxis1local;
+
+ btPlaneSpace1(m_rbAFrame.getBasis().getColumn(2),jointAxis0local,jointAxis1local);
+
+ btVector3 jointAxis0 = getRigidBodyA().getCenterOfMassTransform().getBasis() * jointAxis0local;
+ btVector3 jointAxis1 = getRigidBodyA().getCenterOfMassTransform().getBasis() * jointAxis1local;
+ btVector3 hingeAxisWorld = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2);
+
+ new (&m_jacAng[0]) btJacobianEntry(jointAxis0,
+ m_rbA.getCenterOfMassTransform().getBasis().transpose(),
+ m_rbB.getCenterOfMassTransform().getBasis().transpose(),
+ m_rbA.getInvInertiaDiagLocal(),
+ m_rbB.getInvInertiaDiagLocal());
+
+ new (&m_jacAng[1]) btJacobianEntry(jointAxis1,
+ m_rbA.getCenterOfMassTransform().getBasis().transpose(),
+ m_rbB.getCenterOfMassTransform().getBasis().transpose(),
+ m_rbA.getInvInertiaDiagLocal(),
+ m_rbB.getInvInertiaDiagLocal());
+
+ new (&m_jacAng[2]) btJacobianEntry(hingeAxisWorld,
+ m_rbA.getCenterOfMassTransform().getBasis().transpose(),
+ m_rbB.getCenterOfMassTransform().getBasis().transpose(),
+ m_rbA.getInvInertiaDiagLocal(),
+ m_rbB.getInvInertiaDiagLocal());
+
+ // clear accumulator
+ m_accLimitImpulse = btScalar(0.);
+
+ // test angular limit
+ testLimit(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform());
+
+ //Compute K = J*W*J' for hinge axis
+ btVector3 axisA = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2);
+ m_kHinge = 1.0f / (getRigidBodyA().computeAngularImpulseDenominator(axisA) +
+ getRigidBodyB().computeAngularImpulseDenominator(axisA));
+
+ }
+}
+
+
+#endif //__SPU__
+
+
+static inline btScalar btNormalizeAnglePositive(btScalar angle)
+{
+ return btFmod(btFmod(angle, btScalar(2.0*SIMD_PI)) + btScalar(2.0*SIMD_PI), btScalar(2.0*SIMD_PI));
+}
+
+
+
+static btScalar btShortestAngularDistance(btScalar accAngle, btScalar curAngle)
+{
+ btScalar result = btNormalizeAngle(btNormalizeAnglePositive(btNormalizeAnglePositive(curAngle) -
+ btNormalizeAnglePositive(accAngle)));
+ return result;
+}
+
+static btScalar btShortestAngleUpdate(btScalar accAngle, btScalar curAngle)
+{
+ btScalar tol(0.3);
+ btScalar result = btShortestAngularDistance(accAngle, curAngle);
+
+ if (btFabs(result) > tol)
+ return curAngle;
+ else
+ return accAngle + result;
+
+ return curAngle;
+}
+
+
+btScalar btHingeAccumulatedAngleConstraint::getAccumulatedHingeAngle()
+{
+ btScalar hingeAngle = getHingeAngle();
+ m_accumulatedAngle = btShortestAngleUpdate(m_accumulatedAngle,hingeAngle);
+ return m_accumulatedAngle;
+}
+void btHingeAccumulatedAngleConstraint::setAccumulatedHingeAngle(btScalar accAngle)
+{
+ m_accumulatedAngle = accAngle;
+}
+
+void btHingeAccumulatedAngleConstraint::getInfo1(btConstraintInfo1* info)
+{
+ //update m_accumulatedAngle
+ btScalar curHingeAngle = getHingeAngle();
+ m_accumulatedAngle = btShortestAngleUpdate(m_accumulatedAngle,curHingeAngle);
+
+ btHingeConstraint::getInfo1(info);
+
+}
+
+
+void btHingeConstraint::getInfo1(btConstraintInfo1* info)
+{
+
+
+ if (m_useSolveConstraintObsolete)
+ {
+ info->m_numConstraintRows = 0;
+ info->nub = 0;
+ }
+ else
+ {
+ info->m_numConstraintRows = 5; // Fixed 3 linear + 2 angular
+ info->nub = 1;
+ //always add the row, to avoid computation (data is not available yet)
+ //prepare constraint
+ testLimit(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform());
+ if(getSolveLimit() || getEnableAngularMotor())
+ {
+ info->m_numConstraintRows++; // limit 3rd anguar as well
+ info->nub--;
+ }
+
+ }
+}
+
+void btHingeConstraint::getInfo1NonVirtual(btConstraintInfo1* info)
+{
+ if (m_useSolveConstraintObsolete)
+ {
+ info->m_numConstraintRows = 0;
+ info->nub = 0;
+ }
+ else
+ {
+ //always add the 'limit' row, to avoid computation (data is not available yet)
+ info->m_numConstraintRows = 6; // Fixed 3 linear + 2 angular
+ info->nub = 0;
+ }
+}
+
+void btHingeConstraint::getInfo2 (btConstraintInfo2* info)
+{
+ if(m_useOffsetForConstraintFrame)
+ {
+ getInfo2InternalUsingFrameOffset(info, m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform(),m_rbA.getAngularVelocity(),m_rbB.getAngularVelocity());
+ }
+ else
+ {
+ getInfo2Internal(info, m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform(),m_rbA.getAngularVelocity(),m_rbB.getAngularVelocity());
+ }
+}
+
+
+void btHingeConstraint::getInfo2NonVirtual (btConstraintInfo2* info,const btTransform& transA,const btTransform& transB,const btVector3& angVelA,const btVector3& angVelB)
+{
+ ///the regular (virtual) implementation getInfo2 already performs 'testLimit' during getInfo1, so we need to do it now
+ testLimit(transA,transB);
+
+ getInfo2Internal(info,transA,transB,angVelA,angVelB);
+}
+
+
+void btHingeConstraint::getInfo2Internal(btConstraintInfo2* info, const btTransform& transA,const btTransform& transB,const btVector3& angVelA,const btVector3& angVelB)
+{
+
+ btAssert(!m_useSolveConstraintObsolete);
+ int i, skip = info->rowskip;
+ // transforms in world space
+ btTransform trA = transA*m_rbAFrame;
+ btTransform trB = transB*m_rbBFrame;
+ // pivot point
+ btVector3 pivotAInW = trA.getOrigin();
+ btVector3 pivotBInW = trB.getOrigin();
+#if 0
+ if (0)
+ {
+ for (i=0;i<6;i++)
+ {
+ info->m_J1linearAxis[i*skip]=0;
+ info->m_J1linearAxis[i*skip+1]=0;
+ info->m_J1linearAxis[i*skip+2]=0;
+
+ info->m_J1angularAxis[i*skip]=0;
+ info->m_J1angularAxis[i*skip+1]=0;
+ info->m_J1angularAxis[i*skip+2]=0;
+
+ info->m_J2linearAxis[i*skip]=0;
+ info->m_J2linearAxis[i*skip+1]=0;
+ info->m_J2linearAxis[i*skip+2]=0;
+
+ info->m_J2angularAxis[i*skip]=0;
+ info->m_J2angularAxis[i*skip+1]=0;
+ info->m_J2angularAxis[i*skip+2]=0;
+
+ info->m_constraintError[i*skip]=0.f;
+ }
+ }
+#endif //#if 0
+ // linear (all fixed)
+
+ if (!m_angularOnly)
+ {
+ info->m_J1linearAxis[0] = 1;
+ info->m_J1linearAxis[skip + 1] = 1;
+ info->m_J1linearAxis[2 * skip + 2] = 1;
+
+ info->m_J2linearAxis[0] = -1;
+ info->m_J2linearAxis[skip + 1] = -1;
+ info->m_J2linearAxis[2 * skip + 2] = -1;
+ }
+
+
+
+
+ btVector3 a1 = pivotAInW - transA.getOrigin();
+ {
+ btVector3* angular0 = (btVector3*)(info->m_J1angularAxis);
+ btVector3* angular1 = (btVector3*)(info->m_J1angularAxis + skip);
+ btVector3* angular2 = (btVector3*)(info->m_J1angularAxis + 2 * skip);
+ btVector3 a1neg = -a1;
+ a1neg.getSkewSymmetricMatrix(angular0,angular1,angular2);
+ }
+ btVector3 a2 = pivotBInW - transB.getOrigin();
+ {
+ btVector3* angular0 = (btVector3*)(info->m_J2angularAxis);
+ btVector3* angular1 = (btVector3*)(info->m_J2angularAxis + skip);
+ btVector3* angular2 = (btVector3*)(info->m_J2angularAxis + 2 * skip);
+ a2.getSkewSymmetricMatrix(angular0,angular1,angular2);
+ }
+ // linear RHS
+ btScalar normalErp = (m_flags & BT_HINGE_FLAGS_ERP_NORM) ? m_normalERP : info->erp;
+
+ btScalar k = info->fps * normalErp;
+ if (!m_angularOnly)
+ {
+ for(i = 0; i < 3; i++)
+ {
+ info->m_constraintError[i * skip] = k * (pivotBInW[i] - pivotAInW[i]);
+ }
+ }
+ // make rotations around X and Y equal
+ // the hinge axis should be the only unconstrained
+ // rotational axis, the angular velocity of the two bodies perpendicular to
+ // the hinge axis should be equal. thus the constraint equations are
+ // p*w1 - p*w2 = 0
+ // q*w1 - q*w2 = 0
+ // where p and q are unit vectors normal to the hinge axis, and w1 and w2
+ // are the angular velocity vectors of the two bodies.
+ // get hinge axis (Z)
+ btVector3 ax1 = trA.getBasis().getColumn(2);
+ // get 2 orthos to hinge axis (X, Y)
+ btVector3 p = trA.getBasis().getColumn(0);
+ btVector3 q = trA.getBasis().getColumn(1);
+ // set the two hinge angular rows
+ int s3 = 3 * info->rowskip;
+ int s4 = 4 * info->rowskip;
+
+ info->m_J1angularAxis[s3 + 0] = p[0];
+ info->m_J1angularAxis[s3 + 1] = p[1];
+ info->m_J1angularAxis[s3 + 2] = p[2];
+ info->m_J1angularAxis[s4 + 0] = q[0];
+ info->m_J1angularAxis[s4 + 1] = q[1];
+ info->m_J1angularAxis[s4 + 2] = q[2];
+
+ info->m_J2angularAxis[s3 + 0] = -p[0];
+ info->m_J2angularAxis[s3 + 1] = -p[1];
+ info->m_J2angularAxis[s3 + 2] = -p[2];
+ info->m_J2angularAxis[s4 + 0] = -q[0];
+ info->m_J2angularAxis[s4 + 1] = -q[1];
+ info->m_J2angularAxis[s4 + 2] = -q[2];
+ // compute the right hand side of the constraint equation. set relative
+ // body velocities along p and q to bring the hinge back into alignment.
+ // if ax1,ax2 are the unit length hinge axes as computed from body1 and
+ // body2, we need to rotate both bodies along the axis u = (ax1 x ax2).
+ // if `theta' is the angle between ax1 and ax2, we need an angular velocity
+ // along u to cover angle erp*theta in one step :
+ // |angular_velocity| = angle/time = erp*theta / stepsize
+ // = (erp*fps) * theta
+ // angular_velocity = |angular_velocity| * (ax1 x ax2) / |ax1 x ax2|
+ // = (erp*fps) * theta * (ax1 x ax2) / sin(theta)
+ // ...as ax1 and ax2 are unit length. if theta is smallish,
+ // theta ~= sin(theta), so
+ // angular_velocity = (erp*fps) * (ax1 x ax2)
+ // ax1 x ax2 is in the plane space of ax1, so we project the angular
+ // velocity to p and q to find the right hand side.
+ btVector3 ax2 = trB.getBasis().getColumn(2);
+ btVector3 u = ax1.cross(ax2);
+ info->m_constraintError[s3] = k * u.dot(p);
+ info->m_constraintError[s4] = k * u.dot(q);
+ // check angular limits
+ int nrow = 4; // last filled row
+ int srow;
+ btScalar limit_err = btScalar(0.0);
+ int limit = 0;
+ if(getSolveLimit())
+ {
+#ifdef _BT_USE_CENTER_LIMIT_
+ limit_err = m_limit.getCorrection() * m_referenceSign;
+#else
+ limit_err = m_correction * m_referenceSign;
+#endif
+ limit = (limit_err > btScalar(0.0)) ? 1 : 2;
+
+ }
+ // if the hinge has joint limits or motor, add in the extra row
+ bool powered = getEnableAngularMotor();
+ if(limit || powered)
+ {
+ nrow++;
+ srow = nrow * info->rowskip;
+ info->m_J1angularAxis[srow+0] = ax1[0];
+ info->m_J1angularAxis[srow+1] = ax1[1];
+ info->m_J1angularAxis[srow+2] = ax1[2];
+
+ info->m_J2angularAxis[srow+0] = -ax1[0];
+ info->m_J2angularAxis[srow+1] = -ax1[1];
+ info->m_J2angularAxis[srow+2] = -ax1[2];
+
+ btScalar lostop = getLowerLimit();
+ btScalar histop = getUpperLimit();
+ if(limit && (lostop == histop))
+ { // the joint motor is ineffective
+ powered = false;
+ }
+ info->m_constraintError[srow] = btScalar(0.0f);
+ btScalar currERP = (m_flags & BT_HINGE_FLAGS_ERP_STOP) ? m_stopERP : normalErp;
+ if(powered)
+ {
+ if(m_flags & BT_HINGE_FLAGS_CFM_NORM)
+ {
+ info->cfm[srow] = m_normalCFM;
+ }
+ btScalar mot_fact = getMotorFactor(m_hingeAngle, lostop, histop, m_motorTargetVelocity, info->fps * currERP);
+ info->m_constraintError[srow] += mot_fact * m_motorTargetVelocity * m_referenceSign;
+ info->m_lowerLimit[srow] = - m_maxMotorImpulse;
+ info->m_upperLimit[srow] = m_maxMotorImpulse;
+ }
+ if(limit)
+ {
+ k = info->fps * currERP;
+ info->m_constraintError[srow] += k * limit_err;
+ if(m_flags & BT_HINGE_FLAGS_CFM_STOP)
+ {
+ info->cfm[srow] = m_stopCFM;
+ }
+ if(lostop == histop)
+ {
+ // limited low and high simultaneously
+ info->m_lowerLimit[srow] = -SIMD_INFINITY;
+ info->m_upperLimit[srow] = SIMD_INFINITY;
+ }
+ else if(limit == 1)
+ { // low limit
+ info->m_lowerLimit[srow] = 0;
+ info->m_upperLimit[srow] = SIMD_INFINITY;
+ }
+ else
+ { // high limit
+ info->m_lowerLimit[srow] = -SIMD_INFINITY;
+ info->m_upperLimit[srow] = 0;
+ }
+ // bounce (we'll use slider parameter abs(1.0 - m_dampingLimAng) for that)
+#ifdef _BT_USE_CENTER_LIMIT_
+ btScalar bounce = m_limit.getRelaxationFactor();
+#else
+ btScalar bounce = m_relaxationFactor;
+#endif
+ if(bounce > btScalar(0.0))
+ {
+ btScalar vel = angVelA.dot(ax1);
+ vel -= angVelB.dot(ax1);
+ // only apply bounce if the velocity is incoming, and if the
+ // resulting c[] exceeds what we already have.
+ if(limit == 1)
+ { // low limit
+ if(vel < 0)
+ {
+ btScalar newc = -bounce * vel;
+ if(newc > info->m_constraintError[srow])
+ {
+ info->m_constraintError[srow] = newc;
+ }
+ }
+ }
+ else
+ { // high limit - all those computations are reversed
+ if(vel > 0)
+ {
+ btScalar newc = -bounce * vel;
+ if(newc < info->m_constraintError[srow])
+ {
+ info->m_constraintError[srow] = newc;
+ }
+ }
+ }
+ }
+#ifdef _BT_USE_CENTER_LIMIT_
+ info->m_constraintError[srow] *= m_limit.getBiasFactor();
+#else
+ info->m_constraintError[srow] *= m_biasFactor;
+#endif
+ } // if(limit)
+ } // if angular limit or powered
+}
+
+
+void btHingeConstraint::setFrames(const btTransform & frameA, const btTransform & frameB)
+{
+ m_rbAFrame = frameA;
+ m_rbBFrame = frameB;
+ buildJacobian();
+}
+
+
+void btHingeConstraint::updateRHS(btScalar timeStep)
+{
+ (void)timeStep;
+
+}
+
+
+
+
+btScalar btHingeConstraint::getHingeAngle()
+{
+ return getHingeAngle(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform());
+}
+
+btScalar btHingeConstraint::getHingeAngle(const btTransform& transA,const btTransform& transB)
+{
+ const btVector3 refAxis0 = transA.getBasis() * m_rbAFrame.getBasis().getColumn(0);
+ const btVector3 refAxis1 = transA.getBasis() * m_rbAFrame.getBasis().getColumn(1);
+ const btVector3 swingAxis = transB.getBasis() * m_rbBFrame.getBasis().getColumn(1);
+// btScalar angle = btAtan2Fast(swingAxis.dot(refAxis0), swingAxis.dot(refAxis1));
+ btScalar angle = btAtan2(swingAxis.dot(refAxis0), swingAxis.dot(refAxis1));
+ return m_referenceSign * angle;
+}
+
+
+
+void btHingeConstraint::testLimit(const btTransform& transA,const btTransform& transB)
+{
+ // Compute limit information
+ m_hingeAngle = getHingeAngle(transA,transB);
+#ifdef _BT_USE_CENTER_LIMIT_
+ m_limit.test(m_hingeAngle);
+#else
+ m_correction = btScalar(0.);
+ m_limitSign = btScalar(0.);
+ m_solveLimit = false;
+ if (m_lowerLimit <= m_upperLimit)
+ {
+ m_hingeAngle = btAdjustAngleToLimits(m_hingeAngle, m_lowerLimit, m_upperLimit);
+ if (m_hingeAngle <= m_lowerLimit)
+ {
+ m_correction = (m_lowerLimit - m_hingeAngle);
+ m_limitSign = 1.0f;
+ m_solveLimit = true;
+ }
+ else if (m_hingeAngle >= m_upperLimit)
+ {
+ m_correction = m_upperLimit - m_hingeAngle;
+ m_limitSign = -1.0f;
+ m_solveLimit = true;
+ }
+ }
+#endif
+ return;
+}
+
+
+static btVector3 vHinge(0, 0, btScalar(1));
+
+void btHingeConstraint::setMotorTarget(const btQuaternion& qAinB, btScalar dt)
+{
+ // convert target from body to constraint space
+ btQuaternion qConstraint = m_rbBFrame.getRotation().inverse() * qAinB * m_rbAFrame.getRotation();
+ qConstraint.normalize();
+
+ // extract "pure" hinge component
+ btVector3 vNoHinge = quatRotate(qConstraint, vHinge); vNoHinge.normalize();
+ btQuaternion qNoHinge = shortestArcQuat(vHinge, vNoHinge);
+ btQuaternion qHinge = qNoHinge.inverse() * qConstraint;
+ qHinge.normalize();
+
+ // compute angular target, clamped to limits
+ btScalar targetAngle = qHinge.getAngle();
+ if (targetAngle > SIMD_PI) // long way around. flip quat and recalculate.
+ {
+ qHinge = -(qHinge);
+ targetAngle = qHinge.getAngle();
+ }
+ if (qHinge.getZ() < 0)
+ targetAngle = -targetAngle;
+
+ setMotorTarget(targetAngle, dt);
+}
+
+void btHingeConstraint::setMotorTarget(btScalar targetAngle, btScalar dt)
+{
+#ifdef _BT_USE_CENTER_LIMIT_
+ m_limit.fit(targetAngle);
+#else
+ if (m_lowerLimit < m_upperLimit)
+ {
+ if (targetAngle < m_lowerLimit)
+ targetAngle = m_lowerLimit;
+ else if (targetAngle > m_upperLimit)
+ targetAngle = m_upperLimit;
+ }
+#endif
+ // compute angular velocity
+ btScalar curAngle = getHingeAngle(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform());
+ btScalar dAngle = targetAngle - curAngle;
+ m_motorTargetVelocity = dAngle / dt;
+}
+
+
+
+void btHingeConstraint::getInfo2InternalUsingFrameOffset(btConstraintInfo2* info, const btTransform& transA,const btTransform& transB,const btVector3& angVelA,const btVector3& angVelB)
+{
+ btAssert(!m_useSolveConstraintObsolete);
+ int i, s = info->rowskip;
+ // transforms in world space
+ btTransform trA = transA*m_rbAFrame;
+ btTransform trB = transB*m_rbBFrame;
+ // pivot point
+// btVector3 pivotAInW = trA.getOrigin();
+// btVector3 pivotBInW = trB.getOrigin();
+#if 1
+ // difference between frames in WCS
+ btVector3 ofs = trB.getOrigin() - trA.getOrigin();
+ // now get weight factors depending on masses
+ btScalar miA = getRigidBodyA().getInvMass();
+ btScalar miB = getRigidBodyB().getInvMass();
+ bool hasStaticBody = (miA < SIMD_EPSILON) || (miB < SIMD_EPSILON);
+ btScalar miS = miA + miB;
+ btScalar factA, factB;
+ if(miS > btScalar(0.f))
+ {
+ factA = miB / miS;
+ }
+ else
+ {
+ factA = btScalar(0.5f);
+ }
+ factB = btScalar(1.0f) - factA;
+ // get the desired direction of hinge axis
+ // as weighted sum of Z-orthos of frameA and frameB in WCS
+ btVector3 ax1A = trA.getBasis().getColumn(2);
+ btVector3 ax1B = trB.getBasis().getColumn(2);
+ btVector3 ax1 = ax1A * factA + ax1B * factB;
+ ax1.normalize();
+ // fill first 3 rows
+ // we want: velA + wA x relA == velB + wB x relB
+ btTransform bodyA_trans = transA;
+ btTransform bodyB_trans = transB;
+ int s0 = 0;
+ int s1 = s;
+ int s2 = s * 2;
+ int nrow = 2; // last filled row
+ btVector3 tmpA, tmpB, relA, relB, p, q;
+ // get vector from bodyB to frameB in WCS
+ relB = trB.getOrigin() - bodyB_trans.getOrigin();
+ // get its projection to hinge axis
+ btVector3 projB = ax1 * relB.dot(ax1);
+ // get vector directed from bodyB to hinge axis (and orthogonal to it)
+ btVector3 orthoB = relB - projB;
+ // same for bodyA
+ relA = trA.getOrigin() - bodyA_trans.getOrigin();
+ btVector3 projA = ax1 * relA.dot(ax1);
+ btVector3 orthoA = relA - projA;
+ btVector3 totalDist = projA - projB;
+ // get offset vectors relA and relB
+ relA = orthoA + totalDist * factA;
+ relB = orthoB - totalDist * factB;
+ // now choose average ortho to hinge axis
+ p = orthoB * factA + orthoA * factB;
+ btScalar len2 = p.length2();
+ if(len2 > SIMD_EPSILON)
+ {
+ p /= btSqrt(len2);
+ }
+ else
+ {
+ p = trA.getBasis().getColumn(1);
+ }
+ // make one more ortho
+ q = ax1.cross(p);
+ // fill three rows
+ tmpA = relA.cross(p);
+ tmpB = relB.cross(p);
+ for (i=0; i<3; i++) info->m_J1angularAxis[s0+i] = tmpA[i];
+ for (i=0; i<3; i++) info->m_J2angularAxis[s0+i] = -tmpB[i];
+ tmpA = relA.cross(q);
+ tmpB = relB.cross(q);
+ if(hasStaticBody && getSolveLimit())
+ { // to make constraint between static and dynamic objects more rigid
+ // remove wA (or wB) from equation if angular limit is hit
+ tmpB *= factB;
+ tmpA *= factA;
+ }
+ for (i=0; i<3; i++) info->m_J1angularAxis[s1+i] = tmpA[i];
+ for (i=0; i<3; i++) info->m_J2angularAxis[s1+i] = -tmpB[i];
+ tmpA = relA.cross(ax1);
+ tmpB = relB.cross(ax1);
+ if(hasStaticBody)
+ { // to make constraint between static and dynamic objects more rigid
+ // remove wA (or wB) from equation
+ tmpB *= factB;
+ tmpA *= factA;
+ }
+ for (i=0; i<3; i++) info->m_J1angularAxis[s2+i] = tmpA[i];
+ for (i=0; i<3; i++) info->m_J2angularAxis[s2+i] = -tmpB[i];
+
+ btScalar normalErp = (m_flags & BT_HINGE_FLAGS_ERP_NORM)? m_normalERP : info->erp;
+ btScalar k = info->fps * normalErp;
+
+ if (!m_angularOnly)
+ {
+ for (i=0; i<3; i++) info->m_J1linearAxis[s0+i] = p[i];
+ for (i=0; i<3; i++) info->m_J1linearAxis[s1+i] = q[i];
+ for (i=0; i<3; i++) info->m_J1linearAxis[s2+i] = ax1[i];
+
+ for (i=0; i<3; i++) info->m_J2linearAxis[s0+i] = -p[i];
+ for (i=0; i<3; i++) info->m_J2linearAxis[s1+i] = -q[i];
+ for (i=0; i<3; i++) info->m_J2linearAxis[s2+i] = -ax1[i];
+
+ // compute three elements of right hand side
+
+ btScalar rhs = k * p.dot(ofs);
+ info->m_constraintError[s0] = rhs;
+ rhs = k * q.dot(ofs);
+ info->m_constraintError[s1] = rhs;
+ rhs = k * ax1.dot(ofs);
+ info->m_constraintError[s2] = rhs;
+ }
+ // the hinge axis should be the only unconstrained
+ // rotational axis, the angular velocity of the two bodies perpendicular to
+ // the hinge axis should be equal. thus the constraint equations are
+ // p*w1 - p*w2 = 0
+ // q*w1 - q*w2 = 0
+ // where p and q are unit vectors normal to the hinge axis, and w1 and w2
+ // are the angular velocity vectors of the two bodies.
+ int s3 = 3 * s;
+ int s4 = 4 * s;
+ info->m_J1angularAxis[s3 + 0] = p[0];
+ info->m_J1angularAxis[s3 + 1] = p[1];
+ info->m_J1angularAxis[s3 + 2] = p[2];
+ info->m_J1angularAxis[s4 + 0] = q[0];
+ info->m_J1angularAxis[s4 + 1] = q[1];
+ info->m_J1angularAxis[s4 + 2] = q[2];
+
+ info->m_J2angularAxis[s3 + 0] = -p[0];
+ info->m_J2angularAxis[s3 + 1] = -p[1];
+ info->m_J2angularAxis[s3 + 2] = -p[2];
+ info->m_J2angularAxis[s4 + 0] = -q[0];
+ info->m_J2angularAxis[s4 + 1] = -q[1];
+ info->m_J2angularAxis[s4 + 2] = -q[2];
+ // compute the right hand side of the constraint equation. set relative
+ // body velocities along p and q to bring the hinge back into alignment.
+ // if ax1A,ax1B are the unit length hinge axes as computed from bodyA and
+ // bodyB, we need to rotate both bodies along the axis u = (ax1 x ax2).
+ // if "theta" is the angle between ax1 and ax2, we need an angular velocity
+ // along u to cover angle erp*theta in one step :
+ // |angular_velocity| = angle/time = erp*theta / stepsize
+ // = (erp*fps) * theta
+ // angular_velocity = |angular_velocity| * (ax1 x ax2) / |ax1 x ax2|
+ // = (erp*fps) * theta * (ax1 x ax2) / sin(theta)
+ // ...as ax1 and ax2 are unit length. if theta is smallish,
+ // theta ~= sin(theta), so
+ // angular_velocity = (erp*fps) * (ax1 x ax2)
+ // ax1 x ax2 is in the plane space of ax1, so we project the angular
+ // velocity to p and q to find the right hand side.
+ k = info->fps * normalErp;//??
+
+ btVector3 u = ax1A.cross(ax1B);
+ info->m_constraintError[s3] = k * u.dot(p);
+ info->m_constraintError[s4] = k * u.dot(q);
+#endif
+ // check angular limits
+ nrow = 4; // last filled row
+ int srow;
+ btScalar limit_err = btScalar(0.0);
+ int limit = 0;
+ if(getSolveLimit())
+ {
+#ifdef _BT_USE_CENTER_LIMIT_
+ limit_err = m_limit.getCorrection() * m_referenceSign;
+#else
+ limit_err = m_correction * m_referenceSign;
+#endif
+ limit = (limit_err > btScalar(0.0)) ? 1 : 2;
+
+ }
+ // if the hinge has joint limits or motor, add in the extra row
+ bool powered = getEnableAngularMotor();
+ if(limit || powered)
+ {
+ nrow++;
+ srow = nrow * info->rowskip;
+ info->m_J1angularAxis[srow+0] = ax1[0];
+ info->m_J1angularAxis[srow+1] = ax1[1];
+ info->m_J1angularAxis[srow+2] = ax1[2];
+
+ info->m_J2angularAxis[srow+0] = -ax1[0];
+ info->m_J2angularAxis[srow+1] = -ax1[1];
+ info->m_J2angularAxis[srow+2] = -ax1[2];
+
+ btScalar lostop = getLowerLimit();
+ btScalar histop = getUpperLimit();
+ if(limit && (lostop == histop))
+ { // the joint motor is ineffective
+ powered = false;
+ }
+ info->m_constraintError[srow] = btScalar(0.0f);
+ btScalar currERP = (m_flags & BT_HINGE_FLAGS_ERP_STOP) ? m_stopERP : normalErp;
+ if(powered)
+ {
+ if(m_flags & BT_HINGE_FLAGS_CFM_NORM)
+ {
+ info->cfm[srow] = m_normalCFM;
+ }
+ btScalar mot_fact = getMotorFactor(m_hingeAngle, lostop, histop, m_motorTargetVelocity, info->fps * currERP);
+ info->m_constraintError[srow] += mot_fact * m_motorTargetVelocity * m_referenceSign;
+ info->m_lowerLimit[srow] = - m_maxMotorImpulse;
+ info->m_upperLimit[srow] = m_maxMotorImpulse;
+ }
+ if(limit)
+ {
+ k = info->fps * currERP;
+ info->m_constraintError[srow] += k * limit_err;
+ if(m_flags & BT_HINGE_FLAGS_CFM_STOP)
+ {
+ info->cfm[srow] = m_stopCFM;
+ }
+ if(lostop == histop)
+ {
+ // limited low and high simultaneously
+ info->m_lowerLimit[srow] = -SIMD_INFINITY;
+ info->m_upperLimit[srow] = SIMD_INFINITY;
+ }
+ else if(limit == 1)
+ { // low limit
+ info->m_lowerLimit[srow] = 0;
+ info->m_upperLimit[srow] = SIMD_INFINITY;
+ }
+ else
+ { // high limit
+ info->m_lowerLimit[srow] = -SIMD_INFINITY;
+ info->m_upperLimit[srow] = 0;
+ }
+ // bounce (we'll use slider parameter abs(1.0 - m_dampingLimAng) for that)
+#ifdef _BT_USE_CENTER_LIMIT_
+ btScalar bounce = m_limit.getRelaxationFactor();
+#else
+ btScalar bounce = m_relaxationFactor;
+#endif
+ if(bounce > btScalar(0.0))
+ {
+ btScalar vel = angVelA.dot(ax1);
+ vel -= angVelB.dot(ax1);
+ // only apply bounce if the velocity is incoming, and if the
+ // resulting c[] exceeds what we already have.
+ if(limit == 1)
+ { // low limit
+ if(vel < 0)
+ {
+ btScalar newc = -bounce * vel;
+ if(newc > info->m_constraintError[srow])
+ {
+ info->m_constraintError[srow] = newc;
+ }
+ }
+ }
+ else
+ { // high limit - all those computations are reversed
+ if(vel > 0)
+ {
+ btScalar newc = -bounce * vel;
+ if(newc < info->m_constraintError[srow])
+ {
+ info->m_constraintError[srow] = newc;
+ }
+ }
+ }
+ }
+#ifdef _BT_USE_CENTER_LIMIT_
+ info->m_constraintError[srow] *= m_limit.getBiasFactor();
+#else
+ info->m_constraintError[srow] *= m_biasFactor;
+#endif
+ } // if(limit)
+ } // if angular limit or powered
+}
+
+
+///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
+///If no axis is provided, it uses the default axis for this constraint.
+void btHingeConstraint::setParam(int num, btScalar value, int axis)
+{
+ if((axis == -1) || (axis == 5))
+ {
+ switch(num)
+ {
+ case BT_CONSTRAINT_STOP_ERP :
+ m_stopERP = value;
+ m_flags |= BT_HINGE_FLAGS_ERP_STOP;
+ break;
+ case BT_CONSTRAINT_STOP_CFM :
+ m_stopCFM = value;
+ m_flags |= BT_HINGE_FLAGS_CFM_STOP;
+ break;
+ case BT_CONSTRAINT_CFM :
+ m_normalCFM = value;
+ m_flags |= BT_HINGE_FLAGS_CFM_NORM;
+ break;
+ case BT_CONSTRAINT_ERP:
+ m_normalERP = value;
+ m_flags |= BT_HINGE_FLAGS_ERP_NORM;
+ break;
+ default :
+ btAssertConstrParams(0);
+ }
+ }
+ else
+ {
+ btAssertConstrParams(0);
+ }
+}
+
+///return the local value of parameter
+btScalar btHingeConstraint::getParam(int num, int axis) const
+{
+ btScalar retVal = 0;
+ if((axis == -1) || (axis == 5))
+ {
+ switch(num)
+ {
+ case BT_CONSTRAINT_STOP_ERP :
+ btAssertConstrParams(m_flags & BT_HINGE_FLAGS_ERP_STOP);
+ retVal = m_stopERP;
+ break;
+ case BT_CONSTRAINT_STOP_CFM :
+ btAssertConstrParams(m_flags & BT_HINGE_FLAGS_CFM_STOP);
+ retVal = m_stopCFM;
+ break;
+ case BT_CONSTRAINT_CFM :
+ btAssertConstrParams(m_flags & BT_HINGE_FLAGS_CFM_NORM);
+ retVal = m_normalCFM;
+ break;
+ case BT_CONSTRAINT_ERP:
+ btAssertConstrParams(m_flags & BT_HINGE_FLAGS_ERP_NORM);
+ retVal = m_normalERP;
+ break;
+ default :
+ btAssertConstrParams(0);
+ }
+ }
+ else
+ {
+ btAssertConstrParams(0);
+ }
+ return retVal;
+}
+
+
diff --git a/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h
new file mode 100644
index 0000000000..3c3df24dba
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h
@@ -0,0 +1,503 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+/* Hinge Constraint by Dirk Gregorius. Limits added by Marcus Hennix at Starbreeze Studios */
+
+#ifndef BT_HINGECONSTRAINT_H
+#define BT_HINGECONSTRAINT_H
+
+#define _BT_USE_CENTER_LIMIT_ 1
+
+
+#include "LinearMath/btVector3.h"
+#include "btJacobianEntry.h"
+#include "btTypedConstraint.h"
+
+class btRigidBody;
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define btHingeConstraintData btHingeConstraintDoubleData2 //rename to 2 for backwards compatibility, so we can still load the 'btHingeConstraintDoubleData' version
+#define btHingeConstraintDataName "btHingeConstraintDoubleData2"
+#else
+#define btHingeConstraintData btHingeConstraintFloatData
+#define btHingeConstraintDataName "btHingeConstraintFloatData"
+#endif //BT_USE_DOUBLE_PRECISION
+
+
+
+enum btHingeFlags
+{
+ BT_HINGE_FLAGS_CFM_STOP = 1,
+ BT_HINGE_FLAGS_ERP_STOP = 2,
+ BT_HINGE_FLAGS_CFM_NORM = 4,
+ BT_HINGE_FLAGS_ERP_NORM = 8
+};
+
+
+/// hinge constraint between two rigidbodies each with a pivotpoint that descibes the axis location in local space
+/// axis defines the orientation of the hinge axis
+ATTRIBUTE_ALIGNED16(class) btHingeConstraint : public btTypedConstraint
+{
+#ifdef IN_PARALLELL_SOLVER
+public:
+#endif
+ btJacobianEntry m_jac[3]; //3 orthogonal linear constraints
+ btJacobianEntry m_jacAng[3]; //2 orthogonal angular constraints+ 1 for limit/motor
+
+ btTransform m_rbAFrame; // constraint axii. Assumes z is hinge axis.
+ btTransform m_rbBFrame;
+
+ btScalar m_motorTargetVelocity;
+ btScalar m_maxMotorImpulse;
+
+
+#ifdef _BT_USE_CENTER_LIMIT_
+ btAngularLimit m_limit;
+#else
+ btScalar m_lowerLimit;
+ btScalar m_upperLimit;
+ btScalar m_limitSign;
+ btScalar m_correction;
+
+ btScalar m_limitSoftness;
+ btScalar m_biasFactor;
+ btScalar m_relaxationFactor;
+
+ bool m_solveLimit;
+#endif
+
+ btScalar m_kHinge;
+
+
+ btScalar m_accLimitImpulse;
+ btScalar m_hingeAngle;
+ btScalar m_referenceSign;
+
+ bool m_angularOnly;
+ bool m_enableAngularMotor;
+ bool m_useSolveConstraintObsolete;
+ bool m_useOffsetForConstraintFrame;
+ bool m_useReferenceFrameA;
+
+ btScalar m_accMotorImpulse;
+
+ int m_flags;
+ btScalar m_normalCFM;
+ btScalar m_normalERP;
+ btScalar m_stopCFM;
+ btScalar m_stopERP;
+
+
+public:
+
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB, const btVector3& axisInA,const btVector3& axisInB, bool useReferenceFrameA = false);
+
+ btHingeConstraint(btRigidBody& rbA,const btVector3& pivotInA,const btVector3& axisInA, bool useReferenceFrameA = false);
+
+ btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btTransform& rbAFrame, const btTransform& rbBFrame, bool useReferenceFrameA = false);
+
+ btHingeConstraint(btRigidBody& rbA,const btTransform& rbAFrame, bool useReferenceFrameA = false);
+
+
+ virtual void buildJacobian();
+
+ virtual void getInfo1 (btConstraintInfo1* info);
+
+ void getInfo1NonVirtual(btConstraintInfo1* info);
+
+ virtual void getInfo2 (btConstraintInfo2* info);
+
+ void getInfo2NonVirtual(btConstraintInfo2* info,const btTransform& transA,const btTransform& transB,const btVector3& angVelA,const btVector3& angVelB);
+
+ void getInfo2Internal(btConstraintInfo2* info,const btTransform& transA,const btTransform& transB,const btVector3& angVelA,const btVector3& angVelB);
+ void getInfo2InternalUsingFrameOffset(btConstraintInfo2* info,const btTransform& transA,const btTransform& transB,const btVector3& angVelA,const btVector3& angVelB);
+
+
+ void updateRHS(btScalar timeStep);
+
+ const btRigidBody& getRigidBodyA() const
+ {
+ return m_rbA;
+ }
+ const btRigidBody& getRigidBodyB() const
+ {
+ return m_rbB;
+ }
+
+ btRigidBody& getRigidBodyA()
+ {
+ return m_rbA;
+ }
+
+ btRigidBody& getRigidBodyB()
+ {
+ return m_rbB;
+ }
+
+ btTransform& getFrameOffsetA()
+ {
+ return m_rbAFrame;
+ }
+
+ btTransform& getFrameOffsetB()
+ {
+ return m_rbBFrame;
+ }
+
+ void setFrames(const btTransform& frameA, const btTransform& frameB);
+
+ void setAngularOnly(bool angularOnly)
+ {
+ m_angularOnly = angularOnly;
+ }
+
+ void enableAngularMotor(bool enableMotor,btScalar targetVelocity,btScalar maxMotorImpulse)
+ {
+ m_enableAngularMotor = enableMotor;
+ m_motorTargetVelocity = targetVelocity;
+ m_maxMotorImpulse = maxMotorImpulse;
+ }
+
+ // extra motor API, including ability to set a target rotation (as opposed to angular velocity)
+ // note: setMotorTarget sets angular velocity under the hood, so you must call it every tick to
+ // maintain a given angular target.
+ void enableMotor(bool enableMotor) { m_enableAngularMotor = enableMotor; }
+ void setMaxMotorImpulse(btScalar maxMotorImpulse) { m_maxMotorImpulse = maxMotorImpulse; }
+ void setMotorTargetVelocity(btScalar motorTargetVelocity) { m_motorTargetVelocity = motorTargetVelocity; }
+ void setMotorTarget(const btQuaternion& qAinB, btScalar dt); // qAinB is rotation of body A wrt body B.
+ void setMotorTarget(btScalar targetAngle, btScalar dt);
+
+
+ void setLimit(btScalar low,btScalar high,btScalar _softness = 0.9f, btScalar _biasFactor = 0.3f, btScalar _relaxationFactor = 1.0f)
+ {
+#ifdef _BT_USE_CENTER_LIMIT_
+ m_limit.set(low, high, _softness, _biasFactor, _relaxationFactor);
+#else
+ m_lowerLimit = btNormalizeAngle(low);
+ m_upperLimit = btNormalizeAngle(high);
+ m_limitSoftness = _softness;
+ m_biasFactor = _biasFactor;
+ m_relaxationFactor = _relaxationFactor;
+#endif
+ }
+
+ btScalar getLimitSoftness() const
+ {
+#ifdef _BT_USE_CENTER_LIMIT_
+ return m_limit.getSoftness();
+#else
+ return m_limitSoftness;
+#endif
+ }
+
+ btScalar getLimitBiasFactor() const
+ {
+#ifdef _BT_USE_CENTER_LIMIT_
+ return m_limit.getBiasFactor();
+#else
+ return m_biasFactor;
+#endif
+ }
+
+ btScalar getLimitRelaxationFactor() const
+ {
+#ifdef _BT_USE_CENTER_LIMIT_
+ return m_limit.getRelaxationFactor();
+#else
+ return m_relaxationFactor;
+#endif
+ }
+
+ void setAxis(btVector3& axisInA)
+ {
+ btVector3 rbAxisA1, rbAxisA2;
+ btPlaneSpace1(axisInA, rbAxisA1, rbAxisA2);
+ btVector3 pivotInA = m_rbAFrame.getOrigin();
+// m_rbAFrame.getOrigin() = pivotInA;
+ m_rbAFrame.getBasis().setValue( rbAxisA1.getX(),rbAxisA2.getX(),axisInA.getX(),
+ rbAxisA1.getY(),rbAxisA2.getY(),axisInA.getY(),
+ rbAxisA1.getZ(),rbAxisA2.getZ(),axisInA.getZ() );
+
+ btVector3 axisInB = m_rbA.getCenterOfMassTransform().getBasis() * axisInA;
+
+ btQuaternion rotationArc = shortestArcQuat(axisInA,axisInB);
+ btVector3 rbAxisB1 = quatRotate(rotationArc,rbAxisA1);
+ btVector3 rbAxisB2 = axisInB.cross(rbAxisB1);
+
+ m_rbBFrame.getOrigin() = m_rbB.getCenterOfMassTransform().inverse()(m_rbA.getCenterOfMassTransform()(pivotInA));
+
+ m_rbBFrame.getBasis().setValue( rbAxisB1.getX(),rbAxisB2.getX(),axisInB.getX(),
+ rbAxisB1.getY(),rbAxisB2.getY(),axisInB.getY(),
+ rbAxisB1.getZ(),rbAxisB2.getZ(),axisInB.getZ() );
+ m_rbBFrame.getBasis() = m_rbB.getCenterOfMassTransform().getBasis().inverse() * m_rbBFrame.getBasis();
+
+ }
+
+ bool hasLimit() const {
+#ifdef _BT_USE_CENTER_LIMIT_
+ return m_limit.getHalfRange() > 0;
+#else
+ return m_lowerLimit <= m_upperLimit;
+#endif
+ }
+
+ btScalar getLowerLimit() const
+ {
+#ifdef _BT_USE_CENTER_LIMIT_
+ return m_limit.getLow();
+#else
+ return m_lowerLimit;
+#endif
+ }
+
+ btScalar getUpperLimit() const
+ {
+#ifdef _BT_USE_CENTER_LIMIT_
+ return m_limit.getHigh();
+#else
+ return m_upperLimit;
+#endif
+ }
+
+
+ ///The getHingeAngle gives the hinge angle in range [-PI,PI]
+ btScalar getHingeAngle();
+
+ btScalar getHingeAngle(const btTransform& transA,const btTransform& transB);
+
+ void testLimit(const btTransform& transA,const btTransform& transB);
+
+
+ const btTransform& getAFrame() const { return m_rbAFrame; };
+ const btTransform& getBFrame() const { return m_rbBFrame; };
+
+ btTransform& getAFrame() { return m_rbAFrame; };
+ btTransform& getBFrame() { return m_rbBFrame; };
+
+ inline int getSolveLimit()
+ {
+#ifdef _BT_USE_CENTER_LIMIT_
+ return m_limit.isLimit();
+#else
+ return m_solveLimit;
+#endif
+ }
+
+ inline btScalar getLimitSign()
+ {
+#ifdef _BT_USE_CENTER_LIMIT_
+ return m_limit.getSign();
+#else
+ return m_limitSign;
+#endif
+ }
+
+ inline bool getAngularOnly()
+ {
+ return m_angularOnly;
+ }
+ inline bool getEnableAngularMotor()
+ {
+ return m_enableAngularMotor;
+ }
+ inline btScalar getMotorTargetVelocity()
+ {
+ return m_motorTargetVelocity;
+ }
+ inline btScalar getMaxMotorImpulse()
+ {
+ return m_maxMotorImpulse;
+ }
+ // access for UseFrameOffset
+ bool getUseFrameOffset() { return m_useOffsetForConstraintFrame; }
+ void setUseFrameOffset(bool frameOffsetOnOff) { m_useOffsetForConstraintFrame = frameOffsetOnOff; }
+ // access for UseReferenceFrameA
+ bool getUseReferenceFrameA() const { return m_useReferenceFrameA; }
+ void setUseReferenceFrameA(bool useReferenceFrameA) { m_useReferenceFrameA = useReferenceFrameA; }
+
+ ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
+ ///If no axis is provided, it uses the default axis for this constraint.
+ virtual void setParam(int num, btScalar value, int axis = -1);
+ ///return the local value of parameter
+ virtual btScalar getParam(int num, int axis = -1) const;
+
+ virtual int getFlags() const
+ {
+ return m_flags;
+ }
+
+ virtual int calculateSerializeBufferSize() const;
+
+ ///fills the dataBuffer and returns the struct name (and 0 on failure)
+ virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
+
+
+};
+
+
+//only for backward compatibility
+#ifdef BT_BACKWARDS_COMPATIBLE_SERIALIZATION
+///this structure is not used, except for loading pre-2.82 .bullet files
+struct btHingeConstraintDoubleData
+{
+ btTypedConstraintData m_typeConstraintData;
+ btTransformDoubleData m_rbAFrame; // constraint axii. Assumes z is hinge axis.
+ btTransformDoubleData m_rbBFrame;
+ int m_useReferenceFrameA;
+ int m_angularOnly;
+ int m_enableAngularMotor;
+ float m_motorTargetVelocity;
+ float m_maxMotorImpulse;
+
+ float m_lowerLimit;
+ float m_upperLimit;
+ float m_limitSoftness;
+ float m_biasFactor;
+ float m_relaxationFactor;
+
+};
+#endif //BT_BACKWARDS_COMPATIBLE_SERIALIZATION
+
+///The getAccumulatedHingeAngle returns the accumulated hinge angle, taking rotation across the -PI/PI boundary into account
+ATTRIBUTE_ALIGNED16(class) btHingeAccumulatedAngleConstraint : public btHingeConstraint
+{
+protected:
+ btScalar m_accumulatedAngle;
+public:
+
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ btHingeAccumulatedAngleConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB, const btVector3& axisInA,const btVector3& axisInB, bool useReferenceFrameA = false)
+ :btHingeConstraint(rbA,rbB,pivotInA,pivotInB, axisInA,axisInB, useReferenceFrameA )
+ {
+ m_accumulatedAngle=getHingeAngle();
+ }
+
+ btHingeAccumulatedAngleConstraint(btRigidBody& rbA,const btVector3& pivotInA,const btVector3& axisInA, bool useReferenceFrameA = false)
+ :btHingeConstraint(rbA,pivotInA,axisInA, useReferenceFrameA)
+ {
+ m_accumulatedAngle=getHingeAngle();
+ }
+
+ btHingeAccumulatedAngleConstraint(btRigidBody& rbA,btRigidBody& rbB, const btTransform& rbAFrame, const btTransform& rbBFrame, bool useReferenceFrameA = false)
+ :btHingeConstraint(rbA,rbB, rbAFrame, rbBFrame, useReferenceFrameA )
+ {
+ m_accumulatedAngle=getHingeAngle();
+ }
+
+ btHingeAccumulatedAngleConstraint(btRigidBody& rbA,const btTransform& rbAFrame, bool useReferenceFrameA = false)
+ :btHingeConstraint(rbA,rbAFrame, useReferenceFrameA )
+ {
+ m_accumulatedAngle=getHingeAngle();
+ }
+ btScalar getAccumulatedHingeAngle();
+ void setAccumulatedHingeAngle(btScalar accAngle);
+ virtual void getInfo1 (btConstraintInfo1* info);
+
+};
+
+struct btHingeConstraintFloatData
+{
+ btTypedConstraintData m_typeConstraintData;
+ btTransformFloatData m_rbAFrame; // constraint axii. Assumes z is hinge axis.
+ btTransformFloatData m_rbBFrame;
+ int m_useReferenceFrameA;
+ int m_angularOnly;
+
+ int m_enableAngularMotor;
+ float m_motorTargetVelocity;
+ float m_maxMotorImpulse;
+
+ float m_lowerLimit;
+ float m_upperLimit;
+ float m_limitSoftness;
+ float m_biasFactor;
+ float m_relaxationFactor;
+
+};
+
+
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btHingeConstraintDoubleData2
+{
+ btTypedConstraintDoubleData m_typeConstraintData;
+ btTransformDoubleData m_rbAFrame; // constraint axii. Assumes z is hinge axis.
+ btTransformDoubleData m_rbBFrame;
+ int m_useReferenceFrameA;
+ int m_angularOnly;
+ int m_enableAngularMotor;
+ double m_motorTargetVelocity;
+ double m_maxMotorImpulse;
+
+ double m_lowerLimit;
+ double m_upperLimit;
+ double m_limitSoftness;
+ double m_biasFactor;
+ double m_relaxationFactor;
+ char m_padding1[4];
+
+};
+
+
+
+
+SIMD_FORCE_INLINE int btHingeConstraint::calculateSerializeBufferSize() const
+{
+ return sizeof(btHingeConstraintData);
+}
+
+ ///fills the dataBuffer and returns the struct name (and 0 on failure)
+SIMD_FORCE_INLINE const char* btHingeConstraint::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+ btHingeConstraintData* hingeData = (btHingeConstraintData*)dataBuffer;
+ btTypedConstraint::serialize(&hingeData->m_typeConstraintData,serializer);
+
+ m_rbAFrame.serialize(hingeData->m_rbAFrame);
+ m_rbBFrame.serialize(hingeData->m_rbBFrame);
+
+ hingeData->m_angularOnly = m_angularOnly;
+ hingeData->m_enableAngularMotor = m_enableAngularMotor;
+ hingeData->m_maxMotorImpulse = float(m_maxMotorImpulse);
+ hingeData->m_motorTargetVelocity = float(m_motorTargetVelocity);
+ hingeData->m_useReferenceFrameA = m_useReferenceFrameA;
+#ifdef _BT_USE_CENTER_LIMIT_
+ hingeData->m_lowerLimit = float(m_limit.getLow());
+ hingeData->m_upperLimit = float(m_limit.getHigh());
+ hingeData->m_limitSoftness = float(m_limit.getSoftness());
+ hingeData->m_biasFactor = float(m_limit.getBiasFactor());
+ hingeData->m_relaxationFactor = float(m_limit.getRelaxationFactor());
+#else
+ hingeData->m_lowerLimit = float(m_lowerLimit);
+ hingeData->m_upperLimit = float(m_upperLimit);
+ hingeData->m_limitSoftness = float(m_limitSoftness);
+ hingeData->m_biasFactor = float(m_biasFactor);
+ hingeData->m_relaxationFactor = float(m_relaxationFactor);
+#endif
+
+ // Fill padding with zeros to appease msan.
+#ifdef BT_USE_DOUBLE_PRECISION
+ hingeData->m_padding1[0] = 0;
+ hingeData->m_padding1[1] = 0;
+ hingeData->m_padding1[2] = 0;
+ hingeData->m_padding1[3] = 0;
+#endif
+
+ return btHingeConstraintDataName;
+}
+
+#endif //BT_HINGECONSTRAINT_H
diff --git a/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h
new file mode 100644
index 0000000000..125580d199
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h
@@ -0,0 +1,155 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_JACOBIAN_ENTRY_H
+#define BT_JACOBIAN_ENTRY_H
+
+#include "LinearMath/btMatrix3x3.h"
+
+
+//notes:
+// Another memory optimization would be to store m_1MinvJt in the remaining 3 w components
+// which makes the btJacobianEntry memory layout 16 bytes
+// if you only are interested in angular part, just feed massInvA and massInvB zero
+
+/// Jacobian entry is an abstraction that allows to describe constraints
+/// it can be used in combination with a constraint solver
+/// Can be used to relate the effect of an impulse to the constraint error
+ATTRIBUTE_ALIGNED16(class) btJacobianEntry
+{
+public:
+ btJacobianEntry() {};
+ //constraint between two different rigidbodies
+ btJacobianEntry(
+ const btMatrix3x3& world2A,
+ const btMatrix3x3& world2B,
+ const btVector3& rel_pos1,const btVector3& rel_pos2,
+ const btVector3& jointAxis,
+ const btVector3& inertiaInvA,
+ const btScalar massInvA,
+ const btVector3& inertiaInvB,
+ const btScalar massInvB)
+ :m_linearJointAxis(jointAxis)
+ {
+ m_aJ = world2A*(rel_pos1.cross(m_linearJointAxis));
+ m_bJ = world2B*(rel_pos2.cross(-m_linearJointAxis));
+ m_0MinvJt = inertiaInvA * m_aJ;
+ m_1MinvJt = inertiaInvB * m_bJ;
+ m_Adiag = massInvA + m_0MinvJt.dot(m_aJ) + massInvB + m_1MinvJt.dot(m_bJ);
+
+ btAssert(m_Adiag > btScalar(0.0));
+ }
+
+ //angular constraint between two different rigidbodies
+ btJacobianEntry(const btVector3& jointAxis,
+ const btMatrix3x3& world2A,
+ const btMatrix3x3& world2B,
+ const btVector3& inertiaInvA,
+ const btVector3& inertiaInvB)
+ :m_linearJointAxis(btVector3(btScalar(0.),btScalar(0.),btScalar(0.)))
+ {
+ m_aJ= world2A*jointAxis;
+ m_bJ = world2B*-jointAxis;
+ m_0MinvJt = inertiaInvA * m_aJ;
+ m_1MinvJt = inertiaInvB * m_bJ;
+ m_Adiag = m_0MinvJt.dot(m_aJ) + m_1MinvJt.dot(m_bJ);
+
+ btAssert(m_Adiag > btScalar(0.0));
+ }
+
+ //angular constraint between two different rigidbodies
+ btJacobianEntry(const btVector3& axisInA,
+ const btVector3& axisInB,
+ const btVector3& inertiaInvA,
+ const btVector3& inertiaInvB)
+ : m_linearJointAxis(btVector3(btScalar(0.),btScalar(0.),btScalar(0.)))
+ , m_aJ(axisInA)
+ , m_bJ(-axisInB)
+ {
+ m_0MinvJt = inertiaInvA * m_aJ;
+ m_1MinvJt = inertiaInvB * m_bJ;
+ m_Adiag = m_0MinvJt.dot(m_aJ) + m_1MinvJt.dot(m_bJ);
+
+ btAssert(m_Adiag > btScalar(0.0));
+ }
+
+ //constraint on one rigidbody
+ btJacobianEntry(
+ const btMatrix3x3& world2A,
+ const btVector3& rel_pos1,const btVector3& rel_pos2,
+ const btVector3& jointAxis,
+ const btVector3& inertiaInvA,
+ const btScalar massInvA)
+ :m_linearJointAxis(jointAxis)
+ {
+ m_aJ= world2A*(rel_pos1.cross(jointAxis));
+ m_bJ = world2A*(rel_pos2.cross(-jointAxis));
+ m_0MinvJt = inertiaInvA * m_aJ;
+ m_1MinvJt = btVector3(btScalar(0.),btScalar(0.),btScalar(0.));
+ m_Adiag = massInvA + m_0MinvJt.dot(m_aJ);
+
+ btAssert(m_Adiag > btScalar(0.0));
+ }
+
+ btScalar getDiagonal() const { return m_Adiag; }
+
+ // for two constraints on the same rigidbody (for example vehicle friction)
+ btScalar getNonDiagonal(const btJacobianEntry& jacB, const btScalar massInvA) const
+ {
+ const btJacobianEntry& jacA = *this;
+ btScalar lin = massInvA * jacA.m_linearJointAxis.dot(jacB.m_linearJointAxis);
+ btScalar ang = jacA.m_0MinvJt.dot(jacB.m_aJ);
+ return lin + ang;
+ }
+
+
+
+ // for two constraints on sharing two same rigidbodies (for example two contact points between two rigidbodies)
+ btScalar getNonDiagonal(const btJacobianEntry& jacB,const btScalar massInvA,const btScalar massInvB) const
+ {
+ const btJacobianEntry& jacA = *this;
+ btVector3 lin = jacA.m_linearJointAxis * jacB.m_linearJointAxis;
+ btVector3 ang0 = jacA.m_0MinvJt * jacB.m_aJ;
+ btVector3 ang1 = jacA.m_1MinvJt * jacB.m_bJ;
+ btVector3 lin0 = massInvA * lin ;
+ btVector3 lin1 = massInvB * lin;
+ btVector3 sum = ang0+ang1+lin0+lin1;
+ return sum[0]+sum[1]+sum[2];
+ }
+
+ btScalar getRelativeVelocity(const btVector3& linvelA,const btVector3& angvelA,const btVector3& linvelB,const btVector3& angvelB)
+ {
+ btVector3 linrel = linvelA - linvelB;
+ btVector3 angvela = angvelA * m_aJ;
+ btVector3 angvelb = angvelB * m_bJ;
+ linrel *= m_linearJointAxis;
+ angvela += angvelb;
+ angvela += linrel;
+ btScalar rel_vel2 = angvela[0]+angvela[1]+angvela[2];
+ return rel_vel2 + SIMD_EPSILON;
+ }
+//private:
+
+ btVector3 m_linearJointAxis;
+ btVector3 m_aJ;
+ btVector3 m_bJ;
+ btVector3 m_0MinvJt;
+ btVector3 m_1MinvJt;
+ //Optimization: can be stored in the w/last component of one of the vectors
+ btScalar m_Adiag;
+
+};
+
+#endif //BT_JACOBIAN_ENTRY_H
diff --git a/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btNNCGConstraintSolver.cpp b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btNNCGConstraintSolver.cpp
new file mode 100644
index 0000000000..f3979be358
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btNNCGConstraintSolver.cpp
@@ -0,0 +1,374 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btNNCGConstraintSolver.h"
+
+
+
+
+
+
+btScalar btNNCGConstraintSolver::solveGroupCacheFriendlySetup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer)
+{
+ btScalar val = btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup( bodies,numBodies,manifoldPtr, numManifolds, constraints,numConstraints,infoGlobal,debugDrawer);
+
+ m_pNC.resizeNoInitialize(m_tmpSolverNonContactConstraintPool.size());
+ m_pC.resizeNoInitialize(m_tmpSolverContactConstraintPool.size());
+ m_pCF.resizeNoInitialize(m_tmpSolverContactFrictionConstraintPool.size());
+ m_pCRF.resizeNoInitialize(m_tmpSolverContactRollingFrictionConstraintPool.size());
+
+ m_deltafNC.resizeNoInitialize(m_tmpSolverNonContactConstraintPool.size());
+ m_deltafC.resizeNoInitialize(m_tmpSolverContactConstraintPool.size());
+ m_deltafCF.resizeNoInitialize(m_tmpSolverContactFrictionConstraintPool.size());
+ m_deltafCRF.resizeNoInitialize(m_tmpSolverContactRollingFrictionConstraintPool.size());
+
+ return val;
+}
+
+btScalar btNNCGConstraintSolver::solveSingleIteration(int iteration, btCollisionObject** /*bodies */,int /*numBodies*/,btPersistentManifold** /*manifoldPtr*/, int /*numManifolds*/,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* /*debugDrawer*/)
+{
+
+ int numNonContactPool = m_tmpSolverNonContactConstraintPool.size();
+ int numConstraintPool = m_tmpSolverContactConstraintPool.size();
+ int numFrictionPool = m_tmpSolverContactFrictionConstraintPool.size();
+
+ if (infoGlobal.m_solverMode & SOLVER_RANDMIZE_ORDER)
+ {
+ if (1) // uncomment this for a bit less random ((iteration & 7) == 0)
+ {
+
+ for (int j=0; j<numNonContactPool; ++j) {
+ 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
+ if (iteration< infoGlobal.m_numIterations)
+ {
+ for (int j=0; j<numConstraintPool; ++j) {
+ 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 = m_orderFrictionConstraintPool[j];
+ int swapi = btRandInt2(j+1);
+ m_orderFrictionConstraintPool[j] = m_orderFrictionConstraintPool[swapi];
+ m_orderFrictionConstraintPool[swapi] = tmp;
+ }
+ }
+ }
+ }
+
+
+ btScalar deltaflengthsqr = 0;
+ {
+ for (int j=0;j<m_tmpSolverNonContactConstraintPool.size();j++)
+ {
+ btSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[m_orderNonContactConstraintPool[j]];
+ if (iteration < constraint.m_overrideNumSolverIterations)
+ {
+ btScalar deltaf = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[constraint.m_solverBodyIdA],m_tmpSolverBodyPool[constraint.m_solverBodyIdB],constraint);
+ m_deltafNC[j] = deltaf;
+ deltaflengthsqr += deltaf * deltaf;
+ }
+ }
+ }
+
+
+ if (m_onlyForNoneContact)
+ {
+ if (iteration==0)
+ {
+ for (int j=0;j<m_tmpSolverNonContactConstraintPool.size();j++) m_pNC[j] = m_deltafNC[j];
+ } else {
+ // deltaflengthsqrprev can be 0 only if the solver solved the problem exactly in the previous iteration. In this case we should have quit, but mainly for debug reason with this 'hack' it is now allowed to continue the calculation
+ btScalar beta = m_deltafLengthSqrPrev>0 ? deltaflengthsqr / m_deltafLengthSqrPrev : 2;
+ if (beta>1)
+ {
+ for (int j=0;j<m_tmpSolverNonContactConstraintPool.size();j++) m_pNC[j] = 0;
+ } else
+ {
+ for (int j=0;j<m_tmpSolverNonContactConstraintPool.size();j++)
+ {
+ btSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[m_orderNonContactConstraintPool[j]];
+ if (iteration < constraint.m_overrideNumSolverIterations)
+ {
+ btScalar additionaldeltaimpulse = beta * m_pNC[j];
+ constraint.m_appliedImpulse = btScalar(constraint.m_appliedImpulse) + additionaldeltaimpulse;
+ m_pNC[j] = beta * m_pNC[j] + m_deltafNC[j];
+ btSolverBody& body1 = m_tmpSolverBodyPool[constraint.m_solverBodyIdA];
+ btSolverBody& body2 = m_tmpSolverBodyPool[constraint.m_solverBodyIdB];
+ const btSolverConstraint& c = constraint;
+ body1.internalApplyImpulse(c.m_contactNormal1*body1.internalGetInvMass(),c.m_angularComponentA,additionaldeltaimpulse);
+ body2.internalApplyImpulse(c.m_contactNormal2*body2.internalGetInvMass(),c.m_angularComponentB,additionaldeltaimpulse);
+ }
+ }
+ }
+ }
+ m_deltafLengthSqrPrev = deltaflengthsqr;
+ }
+
+
+
+ {
+
+ if (iteration< infoGlobal.m_numIterations)
+ {
+ for (int j=0;j<numConstraints;j++)
+ {
+ if (constraints[j]->isEnabled())
+ {
+ 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);
+ }
+ }
+
+ ///solve all contact constraints
+ if (infoGlobal.m_solverMode & SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS)
+ {
+ int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
+ int multiplier = (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)? 2 : 1;
+
+ for (int c=0;c<numPoolConstraints;c++)
+ {
+ btScalar totalImpulse =0;
+
+ {
+ const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[c]];
+ btScalar deltaf = resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
+ m_deltafC[c] = deltaf;
+ deltaflengthsqr += deltaf*deltaf;
+ totalImpulse = solveManifold.m_appliedImpulse;
+ }
+ bool applyFriction = true;
+ if (applyFriction)
+ {
+ {
+
+ 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 deltaf = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
+ m_deltafCF[c*multiplier] = deltaf;
+ deltaflengthsqr += deltaf*deltaf;
+ } else {
+ m_deltafCF[c*multiplier] = 0;
+ }
+ }
+
+ if (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)
+ {
+
+ 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 deltaf = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
+ m_deltafCF[c*multiplier+1] = deltaf;
+ deltaflengthsqr += deltaf*deltaf;
+ } else {
+ m_deltafCF[c*multiplier+1] = 0;
+ }
+ }
+ }
+ }
+
+ }
+ else//SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS
+ {
+ //solve the friction constraints after all contact constraints, don't interleave them
+ int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
+ int j;
+
+ for (j=0;j<numPoolConstraints;j++)
+ {
+ const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
+ btScalar deltaf = resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
+ m_deltafC[j] = deltaf;
+ deltaflengthsqr += deltaf*deltaf;
+ }
+
+
+
+ ///solve all friction constraints
+
+ int numFrictionPoolConstraints = m_tmpSolverContactFrictionConstraintPool.size();
+ for (j=0;j<numFrictionPoolConstraints;j++)
+ {
+ 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 deltaf = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
+ m_deltafCF[j] = deltaf;
+ deltaflengthsqr += deltaf*deltaf;
+ } else {
+ m_deltafCF[j] = 0;
+ }
+ }
+ }
+
+ {
+ int numRollingFrictionPoolConstraints = m_tmpSolverContactRollingFrictionConstraintPool.size();
+ for (int j=0;j<numRollingFrictionPoolConstraints;j++)
+ {
+
+ btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[j];
+ btScalar totalImpulse = m_tmpSolverContactConstraintPool[rollingFrictionConstraint.m_frictionIndex].m_appliedImpulse;
+ if (totalImpulse>btScalar(0))
+ {
+ btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction*totalImpulse;
+ if (rollingFrictionMagnitude>rollingFrictionConstraint.m_friction)
+ rollingFrictionMagnitude = rollingFrictionConstraint.m_friction;
+
+ rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude;
+ rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude;
+
+ btScalar deltaf = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA],m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB],rollingFrictionConstraint);
+ m_deltafCRF[j] = deltaf;
+ deltaflengthsqr += deltaf*deltaf;
+ } else {
+ m_deltafCRF[j] = 0;
+ }
+ }
+ }
+
+ }
+
+
+
+ }
+
+
+
+
+ if (!m_onlyForNoneContact)
+ {
+ if (iteration==0)
+ {
+ for (int j=0;j<m_tmpSolverNonContactConstraintPool.size();j++) m_pNC[j] = m_deltafNC[j];
+ for (int j=0;j<m_tmpSolverContactConstraintPool.size();j++) m_pC[j] = m_deltafC[j];
+ for (int j=0;j<m_tmpSolverContactFrictionConstraintPool.size();j++) m_pCF[j] = m_deltafCF[j];
+ for (int j=0;j<m_tmpSolverContactRollingFrictionConstraintPool.size();j++) m_pCRF[j] = m_deltafCRF[j];
+ } else
+ {
+ // deltaflengthsqrprev can be 0 only if the solver solved the problem exactly in the previous iteration. In this case we should have quit, but mainly for debug reason with this 'hack' it is now allowed to continue the calculation
+ btScalar beta = m_deltafLengthSqrPrev>0 ? deltaflengthsqr / m_deltafLengthSqrPrev : 2;
+ if (beta>1) {
+ for (int j=0;j<m_tmpSolverNonContactConstraintPool.size();j++) m_pNC[j] = 0;
+ for (int j=0;j<m_tmpSolverContactConstraintPool.size();j++) m_pC[j] = 0;
+ for (int j=0;j<m_tmpSolverContactFrictionConstraintPool.size();j++) m_pCF[j] = 0;
+ for (int j=0;j<m_tmpSolverContactRollingFrictionConstraintPool.size();j++) m_pCRF[j] = 0;
+ } else {
+ for (int j=0;j<m_tmpSolverNonContactConstraintPool.size();j++)
+ {
+ btSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[m_orderNonContactConstraintPool[j]];
+ if (iteration < constraint.m_overrideNumSolverIterations) {
+ btScalar additionaldeltaimpulse = beta * m_pNC[j];
+ constraint.m_appliedImpulse = btScalar(constraint.m_appliedImpulse) + additionaldeltaimpulse;
+ m_pNC[j] = beta * m_pNC[j] + m_deltafNC[j];
+ btSolverBody& body1 = m_tmpSolverBodyPool[constraint.m_solverBodyIdA];
+ btSolverBody& body2 = m_tmpSolverBodyPool[constraint.m_solverBodyIdB];
+ const btSolverConstraint& c = constraint;
+ body1.internalApplyImpulse(c.m_contactNormal1*body1.internalGetInvMass(),c.m_angularComponentA,additionaldeltaimpulse);
+ body2.internalApplyImpulse(c.m_contactNormal2*body2.internalGetInvMass(),c.m_angularComponentB,additionaldeltaimpulse);
+ }
+ }
+ for (int j=0;j<m_tmpSolverContactConstraintPool.size();j++)
+ {
+ btSolverConstraint& constraint = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
+ if (iteration< infoGlobal.m_numIterations) {
+ btScalar additionaldeltaimpulse = beta * m_pC[j];
+ constraint.m_appliedImpulse = btScalar(constraint.m_appliedImpulse) + additionaldeltaimpulse;
+ m_pC[j] = beta * m_pC[j] + m_deltafC[j];
+ btSolverBody& body1 = m_tmpSolverBodyPool[constraint.m_solverBodyIdA];
+ btSolverBody& body2 = m_tmpSolverBodyPool[constraint.m_solverBodyIdB];
+ const btSolverConstraint& c = constraint;
+ body1.internalApplyImpulse(c.m_contactNormal1*body1.internalGetInvMass(),c.m_angularComponentA,additionaldeltaimpulse);
+ body2.internalApplyImpulse(c.m_contactNormal2*body2.internalGetInvMass(),c.m_angularComponentB,additionaldeltaimpulse);
+ }
+ }
+ for (int j=0;j<m_tmpSolverContactFrictionConstraintPool.size();j++)
+ {
+ btSolverConstraint& constraint = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[j]];
+ if (iteration< infoGlobal.m_numIterations) {
+ btScalar additionaldeltaimpulse = beta * m_pCF[j];
+ constraint.m_appliedImpulse = btScalar(constraint.m_appliedImpulse) + additionaldeltaimpulse;
+ m_pCF[j] = beta * m_pCF[j] + m_deltafCF[j];
+ btSolverBody& body1 = m_tmpSolverBodyPool[constraint.m_solverBodyIdA];
+ btSolverBody& body2 = m_tmpSolverBodyPool[constraint.m_solverBodyIdB];
+ const btSolverConstraint& c = constraint;
+ body1.internalApplyImpulse(c.m_contactNormal1*body1.internalGetInvMass(),c.m_angularComponentA,additionaldeltaimpulse);
+ body2.internalApplyImpulse(c.m_contactNormal2*body2.internalGetInvMass(),c.m_angularComponentB,additionaldeltaimpulse);
+ }
+ }
+ {
+ for (int j=0;j<m_tmpSolverContactRollingFrictionConstraintPool.size();j++)
+ {
+ btSolverConstraint& constraint = m_tmpSolverContactRollingFrictionConstraintPool[j];
+ if (iteration< infoGlobal.m_numIterations) {
+ btScalar additionaldeltaimpulse = beta * m_pCRF[j];
+ constraint.m_appliedImpulse = btScalar(constraint.m_appliedImpulse) + additionaldeltaimpulse;
+ m_pCRF[j] = beta * m_pCRF[j] + m_deltafCRF[j];
+ btSolverBody& body1 = m_tmpSolverBodyPool[constraint.m_solverBodyIdA];
+ btSolverBody& body2 = m_tmpSolverBodyPool[constraint.m_solverBodyIdB];
+ const btSolverConstraint& c = constraint;
+ body1.internalApplyImpulse(c.m_contactNormal1*body1.internalGetInvMass(),c.m_angularComponentA,additionaldeltaimpulse);
+ body2.internalApplyImpulse(c.m_contactNormal2*body2.internalGetInvMass(),c.m_angularComponentB,additionaldeltaimpulse);
+ }
+ }
+ }
+ }
+ }
+ m_deltafLengthSqrPrev = deltaflengthsqr;
+ }
+
+ return deltaflengthsqr;
+}
+
+btScalar btNNCGConstraintSolver::solveGroupCacheFriendlyFinish(btCollisionObject** bodies,int numBodies,const btContactSolverInfo& infoGlobal)
+{
+ m_pNC.resizeNoInitialize(0);
+ m_pC.resizeNoInitialize(0);
+ m_pCF.resizeNoInitialize(0);
+ m_pCRF.resizeNoInitialize(0);
+
+ m_deltafNC.resizeNoInitialize(0);
+ m_deltafC.resizeNoInitialize(0);
+ m_deltafCF.resizeNoInitialize(0);
+ m_deltafCRF.resizeNoInitialize(0);
+
+ return btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyFinish(bodies, numBodies, infoGlobal);
+}
+
+
+
diff --git a/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btNNCGConstraintSolver.h b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btNNCGConstraintSolver.h
new file mode 100644
index 0000000000..a300929cd5
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btNNCGConstraintSolver.h
@@ -0,0 +1,64 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_NNCG_CONSTRAINT_SOLVER_H
+#define BT_NNCG_CONSTRAINT_SOLVER_H
+
+#include "btSequentialImpulseConstraintSolver.h"
+
+ATTRIBUTE_ALIGNED16(class) btNNCGConstraintSolver : public btSequentialImpulseConstraintSolver
+{
+protected:
+
+ btScalar m_deltafLengthSqrPrev;
+
+ btAlignedObjectArray<btScalar> m_pNC; // p for None Contact constraints
+ btAlignedObjectArray<btScalar> m_pC; // p for Contact constraints
+ btAlignedObjectArray<btScalar> m_pCF; // p for ContactFriction constraints
+ btAlignedObjectArray<btScalar> m_pCRF; // p for ContactRollingFriction constraints
+
+ //These are recalculated in every iterations. We just keep these to prevent reallocation in each iteration.
+ btAlignedObjectArray<btScalar> m_deltafNC; // deltaf for NoneContact constraints
+ btAlignedObjectArray<btScalar> m_deltafC; // deltaf for Contact constraints
+ btAlignedObjectArray<btScalar> m_deltafCF; // deltaf for ContactFriction constraints
+ btAlignedObjectArray<btScalar> m_deltafCRF; // deltaf for ContactRollingFriction constraints
+
+
+protected:
+
+ 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);
+
+public:
+
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ btNNCGConstraintSolver() : btSequentialImpulseConstraintSolver(), m_onlyForNoneContact(false) {}
+
+ virtual btConstraintSolverType getSolverType() const
+ {
+ return BT_NNCG_SOLVER;
+ }
+
+ bool m_onlyForNoneContact;
+};
+
+
+
+
+#endif //BT_NNCG_CONSTRAINT_SOLVER_H
+
diff --git a/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp
new file mode 100644
index 0000000000..3c0430b903
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp
@@ -0,0 +1,229 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "btPoint2PointConstraint.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include <new>
+
+
+
+
+
+btPoint2PointConstraint::btPoint2PointConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB)
+:btTypedConstraint(POINT2POINT_CONSTRAINT_TYPE,rbA,rbB),m_pivotInA(pivotInA),m_pivotInB(pivotInB),
+m_flags(0),
+m_useSolveConstraintObsolete(false)
+{
+
+}
+
+
+btPoint2PointConstraint::btPoint2PointConstraint(btRigidBody& rbA,const btVector3& pivotInA)
+:btTypedConstraint(POINT2POINT_CONSTRAINT_TYPE,rbA),m_pivotInA(pivotInA),m_pivotInB(rbA.getCenterOfMassTransform()(pivotInA)),
+m_flags(0),
+m_useSolveConstraintObsolete(false)
+{
+
+}
+
+void btPoint2PointConstraint::buildJacobian()
+{
+
+ ///we need it for both methods
+ {
+ m_appliedImpulse = btScalar(0.);
+
+ btVector3 normal(0,0,0);
+
+ for (int i=0;i<3;i++)
+ {
+ normal[i] = 1;
+ new (&m_jac[i]) btJacobianEntry(
+ m_rbA.getCenterOfMassTransform().getBasis().transpose(),
+ m_rbB.getCenterOfMassTransform().getBasis().transpose(),
+ m_rbA.getCenterOfMassTransform()*m_pivotInA - m_rbA.getCenterOfMassPosition(),
+ m_rbB.getCenterOfMassTransform()*m_pivotInB - m_rbB.getCenterOfMassPosition(),
+ normal,
+ m_rbA.getInvInertiaDiagLocal(),
+ m_rbA.getInvMass(),
+ m_rbB.getInvInertiaDiagLocal(),
+ m_rbB.getInvMass());
+ normal[i] = 0;
+ }
+ }
+
+
+}
+
+void btPoint2PointConstraint::getInfo1 (btConstraintInfo1* info)
+{
+ getInfo1NonVirtual(info);
+}
+
+void btPoint2PointConstraint::getInfo1NonVirtual (btConstraintInfo1* info)
+{
+ if (m_useSolveConstraintObsolete)
+ {
+ info->m_numConstraintRows = 0;
+ info->nub = 0;
+ } else
+ {
+ info->m_numConstraintRows = 3;
+ info->nub = 3;
+ }
+}
+
+
+
+
+void btPoint2PointConstraint::getInfo2 (btConstraintInfo2* info)
+{
+ getInfo2NonVirtual(info, m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform());
+}
+
+void btPoint2PointConstraint::getInfo2NonVirtual (btConstraintInfo2* info, const btTransform& body0_trans, const btTransform& body1_trans)
+{
+ btAssert(!m_useSolveConstraintObsolete);
+
+ //retrieve matrices
+
+ // anchor points in global coordinates with respect to body PORs.
+
+ // set jacobian
+ info->m_J1linearAxis[0] = 1;
+ info->m_J1linearAxis[info->rowskip+1] = 1;
+ info->m_J1linearAxis[2*info->rowskip+2] = 1;
+
+ btVector3 a1 = body0_trans.getBasis()*getPivotInA();
+ {
+ btVector3* angular0 = (btVector3*)(info->m_J1angularAxis);
+ btVector3* angular1 = (btVector3*)(info->m_J1angularAxis+info->rowskip);
+ btVector3* angular2 = (btVector3*)(info->m_J1angularAxis+2*info->rowskip);
+ btVector3 a1neg = -a1;
+ a1neg.getSkewSymmetricMatrix(angular0,angular1,angular2);
+ }
+
+ info->m_J2linearAxis[0] = -1;
+ info->m_J2linearAxis[info->rowskip+1] = -1;
+ info->m_J2linearAxis[2*info->rowskip+2] = -1;
+
+ btVector3 a2 = body1_trans.getBasis()*getPivotInB();
+
+ {
+ // btVector3 a2n = -a2;
+ btVector3* angular0 = (btVector3*)(info->m_J2angularAxis);
+ btVector3* angular1 = (btVector3*)(info->m_J2angularAxis+info->rowskip);
+ btVector3* angular2 = (btVector3*)(info->m_J2angularAxis+2*info->rowskip);
+ a2.getSkewSymmetricMatrix(angular0,angular1,angular2);
+ }
+
+
+
+ // set right hand side
+ btScalar currERP = (m_flags & BT_P2P_FLAGS_ERP) ? m_erp : info->erp;
+ btScalar k = info->fps * currERP;
+ int j;
+ for (j=0; j<3; j++)
+ {
+ info->m_constraintError[j*info->rowskip] = k * (a2[j] + body1_trans.getOrigin()[j] - a1[j] - body0_trans.getOrigin()[j]);
+ //printf("info->m_constraintError[%d]=%f\n",j,info->m_constraintError[j]);
+ }
+ if(m_flags & BT_P2P_FLAGS_CFM)
+ {
+ for (j=0; j<3; j++)
+ {
+ info->cfm[j*info->rowskip] = m_cfm;
+ }
+ }
+
+ btScalar impulseClamp = m_setting.m_impulseClamp;//
+ for (j=0; j<3; j++)
+ {
+ if (m_setting.m_impulseClamp > 0)
+ {
+ info->m_lowerLimit[j*info->rowskip] = -impulseClamp;
+ info->m_upperLimit[j*info->rowskip] = impulseClamp;
+ }
+ }
+ info->m_damping = m_setting.m_damping;
+
+}
+
+
+
+void btPoint2PointConstraint::updateRHS(btScalar timeStep)
+{
+ (void)timeStep;
+
+}
+
+///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
+///If no axis is provided, it uses the default axis for this constraint.
+void btPoint2PointConstraint::setParam(int num, btScalar value, int axis)
+{
+ if(axis != -1)
+ {
+ btAssertConstrParams(0);
+ }
+ else
+ {
+ switch(num)
+ {
+ case BT_CONSTRAINT_ERP :
+ case BT_CONSTRAINT_STOP_ERP :
+ m_erp = value;
+ m_flags |= BT_P2P_FLAGS_ERP;
+ break;
+ case BT_CONSTRAINT_CFM :
+ case BT_CONSTRAINT_STOP_CFM :
+ m_cfm = value;
+ m_flags |= BT_P2P_FLAGS_CFM;
+ break;
+ default:
+ btAssertConstrParams(0);
+ }
+ }
+}
+
+///return the local value of parameter
+btScalar btPoint2PointConstraint::getParam(int num, int axis) const
+{
+ btScalar retVal(SIMD_INFINITY);
+ if(axis != -1)
+ {
+ btAssertConstrParams(0);
+ }
+ else
+ {
+ switch(num)
+ {
+ case BT_CONSTRAINT_ERP :
+ case BT_CONSTRAINT_STOP_ERP :
+ btAssertConstrParams(m_flags & BT_P2P_FLAGS_ERP);
+ retVal = m_erp;
+ break;
+ case BT_CONSTRAINT_CFM :
+ case BT_CONSTRAINT_STOP_CFM :
+ btAssertConstrParams(m_flags & BT_P2P_FLAGS_CFM);
+ retVal = m_cfm;
+ break;
+ default:
+ btAssertConstrParams(0);
+ }
+ }
+ return retVal;
+}
+
diff --git a/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h
new file mode 100644
index 0000000000..8fa03d719d
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h
@@ -0,0 +1,180 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_POINT2POINTCONSTRAINT_H
+#define BT_POINT2POINTCONSTRAINT_H
+
+#include "LinearMath/btVector3.h"
+#include "btJacobianEntry.h"
+#include "btTypedConstraint.h"
+
+class btRigidBody;
+
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define btPoint2PointConstraintData2 btPoint2PointConstraintDoubleData2
+#define btPoint2PointConstraintDataName "btPoint2PointConstraintDoubleData2"
+#else
+#define btPoint2PointConstraintData2 btPoint2PointConstraintFloatData
+#define btPoint2PointConstraintDataName "btPoint2PointConstraintFloatData"
+#endif //BT_USE_DOUBLE_PRECISION
+
+struct btConstraintSetting
+{
+ btConstraintSetting() :
+ m_tau(btScalar(0.3)),
+ m_damping(btScalar(1.)),
+ m_impulseClamp(btScalar(0.))
+ {
+ }
+ btScalar m_tau;
+ btScalar m_damping;
+ btScalar m_impulseClamp;
+};
+
+enum btPoint2PointFlags
+{
+ BT_P2P_FLAGS_ERP = 1,
+ BT_P2P_FLAGS_CFM = 2
+};
+
+/// point to point constraint between two rigidbodies each with a pivotpoint that descibes the 'ballsocket' location in local space
+ATTRIBUTE_ALIGNED16(class) btPoint2PointConstraint : public btTypedConstraint
+{
+#ifdef IN_PARALLELL_SOLVER
+public:
+#endif
+ btJacobianEntry m_jac[3]; //3 orthogonal linear constraints
+
+ btVector3 m_pivotInA;
+ btVector3 m_pivotInB;
+
+ int m_flags;
+ btScalar m_erp;
+ btScalar m_cfm;
+
+public:
+
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ ///for backwards compatibility during the transition to 'getInfo/getInfo2'
+ bool m_useSolveConstraintObsolete;
+
+ btConstraintSetting m_setting;
+
+ btPoint2PointConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB);
+
+ btPoint2PointConstraint(btRigidBody& rbA,const btVector3& pivotInA);
+
+
+ virtual void buildJacobian();
+
+ virtual void getInfo1 (btConstraintInfo1* info);
+
+ void getInfo1NonVirtual (btConstraintInfo1* info);
+
+ virtual void getInfo2 (btConstraintInfo2* info);
+
+ void getInfo2NonVirtual (btConstraintInfo2* info, const btTransform& body0_trans, const btTransform& body1_trans);
+
+ void updateRHS(btScalar timeStep);
+
+ void setPivotA(const btVector3& pivotA)
+ {
+ m_pivotInA = pivotA;
+ }
+
+ void setPivotB(const btVector3& pivotB)
+ {
+ m_pivotInB = pivotB;
+ }
+
+ const btVector3& getPivotInA() const
+ {
+ return m_pivotInA;
+ }
+
+ const btVector3& getPivotInB() const
+ {
+ return m_pivotInB;
+ }
+
+ ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
+ ///If no axis is provided, it uses the default axis for this constraint.
+ virtual void setParam(int num, btScalar value, int axis = -1);
+ ///return the local value of parameter
+ virtual btScalar getParam(int num, int axis = -1) const;
+
+ virtual int getFlags() const
+ {
+ return m_flags;
+ }
+
+ virtual int calculateSerializeBufferSize() const;
+
+ ///fills the dataBuffer and returns the struct name (and 0 on failure)
+ virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
+
+
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btPoint2PointConstraintFloatData
+{
+ btTypedConstraintData m_typeConstraintData;
+ btVector3FloatData m_pivotInA;
+ btVector3FloatData m_pivotInB;
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btPoint2PointConstraintDoubleData2
+{
+ btTypedConstraintDoubleData m_typeConstraintData;
+ btVector3DoubleData m_pivotInA;
+ btVector3DoubleData m_pivotInB;
+};
+
+#ifdef BT_BACKWARDS_COMPATIBLE_SERIALIZATION
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+///this structure is not used, except for loading pre-2.82 .bullet files
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btPoint2PointConstraintDoubleData
+{
+ btTypedConstraintData m_typeConstraintData;
+ btVector3DoubleData m_pivotInA;
+ btVector3DoubleData m_pivotInB;
+};
+#endif //BT_BACKWARDS_COMPATIBLE_SERIALIZATION
+
+
+SIMD_FORCE_INLINE int btPoint2PointConstraint::calculateSerializeBufferSize() const
+{
+ return sizeof(btPoint2PointConstraintData2);
+
+}
+
+ ///fills the dataBuffer and returns the struct name (and 0 on failure)
+SIMD_FORCE_INLINE const char* btPoint2PointConstraint::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+ btPoint2PointConstraintData2* p2pData = (btPoint2PointConstraintData2*)dataBuffer;
+
+ btTypedConstraint::serialize(&p2pData->m_typeConstraintData,serializer);
+ m_pivotInA.serialize(p2pData->m_pivotInA);
+ m_pivotInB.serialize(p2pData->m_pivotInB);
+
+ return btPoint2PointConstraintDataName;
+}
+
+#endif //BT_POINT2POINTCONSTRAINT_H
diff --git a/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp
new file mode 100644
index 0000000000..b0d57a3e87
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp
@@ -0,0 +1,1973 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+//#define COMPUTE_IMPULSE_DENOM 1
+//#define BT_ADDITIONAL_DEBUG
+
+//It is not necessary (redundant) to refresh contact manifolds, this refresh has been moved to the collision algorithms.
+
+#include "btSequentialImpulseConstraintSolver.h"
+#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
+
+#include "LinearMath/btIDebugDraw.h"
+#include "LinearMath/btCpuFeatureUtility.h"
+
+//#include "btJacobianEntry.h"
+#include "LinearMath/btMinMax.h"
+#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
+#include <new>
+#include "LinearMath/btStackAlloc.h"
+#include "LinearMath/btQuickprof.h"
+//#include "btSolverBody.h"
+//#include "btSolverConstraint.h"
+#include "LinearMath/btAlignedObjectArray.h"
+#include <string.h> //for memset
+
+int gNumSplitImpulseRecoveries = 0;
+
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+
+//#define VERBOSE_RESIDUAL_PRINTF 1
+///This is the scalar reference implementation of solving a single constraint row, the innerloop of the Projected Gauss Seidel/Sequential Impulse constraint solver
+///Below are optional SSE2 and SSE4/FMA3 versions. We assume most hardware has SSE2. For SSE4/FMA3 we perform a CPU feature check.
+static btSimdScalar gResolveSingleConstraintRowGeneric_scalar_reference(btSolverBody& body1, btSolverBody& body2, const btSolverConstraint& c)
+{
+ btScalar deltaImpulse = c.m_rhs - btScalar(c.m_appliedImpulse)*c.m_cfm;
+ const btScalar deltaVel1Dotn = c.m_contactNormal1.dot(body1.internalGetDeltaLinearVelocity()) + c.m_relpos1CrossNormal.dot(body1.internalGetDeltaAngularVelocity());
+ const btScalar deltaVel2Dotn = c.m_contactNormal2.dot(body2.internalGetDeltaLinearVelocity()) + c.m_relpos2CrossNormal.dot(body2.internalGetDeltaAngularVelocity());
+
+ // const btScalar delta_rel_vel = deltaVel1Dotn-deltaVel2Dotn;
+ deltaImpulse -= deltaVel1Dotn*c.m_jacDiagABInv;
+ deltaImpulse -= deltaVel2Dotn*c.m_jacDiagABInv;
+
+ const btScalar sum = btScalar(c.m_appliedImpulse) + deltaImpulse;
+ if (sum < c.m_lowerLimit)
+ {
+ deltaImpulse = c.m_lowerLimit - c.m_appliedImpulse;
+ c.m_appliedImpulse = c.m_lowerLimit;
+ }
+ else if (sum > c.m_upperLimit)
+ {
+ deltaImpulse = c.m_upperLimit - c.m_appliedImpulse;
+ c.m_appliedImpulse = c.m_upperLimit;
+ }
+ else
+ {
+ c.m_appliedImpulse = sum;
+ }
+
+ body1.internalApplyImpulse(c.m_contactNormal1*body1.internalGetInvMass(), c.m_angularComponentA, deltaImpulse);
+ body2.internalApplyImpulse(c.m_contactNormal2*body2.internalGetInvMass(), c.m_angularComponentB, deltaImpulse);
+
+ return deltaImpulse;
+}
+
+
+static btSimdScalar gResolveSingleConstraintRowLowerLimit_scalar_reference(btSolverBody& body1, btSolverBody& body2, const btSolverConstraint& c)
+{
+ btScalar deltaImpulse = c.m_rhs - btScalar(c.m_appliedImpulse)*c.m_cfm;
+ const btScalar deltaVel1Dotn = c.m_contactNormal1.dot(body1.internalGetDeltaLinearVelocity()) + c.m_relpos1CrossNormal.dot(body1.internalGetDeltaAngularVelocity());
+ const btScalar deltaVel2Dotn = c.m_contactNormal2.dot(body2.internalGetDeltaLinearVelocity()) + c.m_relpos2CrossNormal.dot(body2.internalGetDeltaAngularVelocity());
+
+ deltaImpulse -= deltaVel1Dotn*c.m_jacDiagABInv;
+ deltaImpulse -= deltaVel2Dotn*c.m_jacDiagABInv;
+ const btScalar sum = btScalar(c.m_appliedImpulse) + deltaImpulse;
+ if (sum < c.m_lowerLimit)
+ {
+ deltaImpulse = c.m_lowerLimit - c.m_appliedImpulse;
+ c.m_appliedImpulse = c.m_lowerLimit;
+ }
+ else
+ {
+ c.m_appliedImpulse = sum;
+ }
+ body1.internalApplyImpulse(c.m_contactNormal1*body1.internalGetInvMass(), c.m_angularComponentA, deltaImpulse);
+ body2.internalApplyImpulse(c.m_contactNormal2*body2.internalGetInvMass(), c.m_angularComponentB, deltaImpulse);
+
+ return deltaImpulse;
+}
+
+
+
+#ifdef USE_SIMD
+#include <emmintrin.h>
+
+
+#define btVecSplat(x, e) _mm_shuffle_ps(x, x, _MM_SHUFFLE(e,e,e,e))
+static inline __m128 btSimdDot3( __m128 vec0, __m128 vec1 )
+{
+ __m128 result = _mm_mul_ps( vec0, vec1);
+ return _mm_add_ps( btVecSplat( result, 0 ), _mm_add_ps( btVecSplat( result, 1 ), btVecSplat( result, 2 ) ) );
+}
+
+#if defined (BT_ALLOW_SSE4)
+#include <intrin.h>
+
+#define USE_FMA 1
+#define USE_FMA3_INSTEAD_FMA4 1
+#define USE_SSE4_DOT 1
+
+#define SSE4_DP(a, b) _mm_dp_ps(a, b, 0x7f)
+#define SSE4_DP_FP(a, b) _mm_cvtss_f32(_mm_dp_ps(a, b, 0x7f))
+
+#if USE_SSE4_DOT
+#define DOT_PRODUCT(a, b) SSE4_DP(a, b)
+#else
+#define DOT_PRODUCT(a, b) btSimdDot3(a, b)
+#endif
+
+#if USE_FMA
+#if USE_FMA3_INSTEAD_FMA4
+// a*b + c
+#define FMADD(a, b, c) _mm_fmadd_ps(a, b, c)
+// -(a*b) + c
+#define FMNADD(a, b, c) _mm_fnmadd_ps(a, b, c)
+#else // USE_FMA3
+// a*b + c
+#define FMADD(a, b, c) _mm_macc_ps(a, b, c)
+// -(a*b) + c
+#define FMNADD(a, b, c) _mm_nmacc_ps(a, b, c)
+#endif
+#else // USE_FMA
+// c + a*b
+#define FMADD(a, b, c) _mm_add_ps(c, _mm_mul_ps(a, b))
+// c - a*b
+#define FMNADD(a, b, c) _mm_sub_ps(c, _mm_mul_ps(a, b))
+#endif
+#endif
+
+// Project Gauss Seidel or the equivalent Sequential Impulse
+static btSimdScalar gResolveSingleConstraintRowGeneric_sse2(btSolverBody& body1, btSolverBody& body2, const btSolverConstraint& c)
+{
+ __m128 cpAppliedImp = _mm_set1_ps(c.m_appliedImpulse);
+ __m128 lowerLimit1 = _mm_set1_ps(c.m_lowerLimit);
+ __m128 upperLimit1 = _mm_set1_ps(c.m_upperLimit);
+ btSimdScalar deltaImpulse = _mm_sub_ps(_mm_set1_ps(c.m_rhs), _mm_mul_ps(_mm_set1_ps(c.m_appliedImpulse), _mm_set1_ps(c.m_cfm)));
+ __m128 deltaVel1Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal1.mVec128, body1.internalGetDeltaLinearVelocity().mVec128), btSimdDot3(c.m_relpos1CrossNormal.mVec128, body1.internalGetDeltaAngularVelocity().mVec128));
+ __m128 deltaVel2Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal2.mVec128, body2.internalGetDeltaLinearVelocity().mVec128), btSimdDot3(c.m_relpos2CrossNormal.mVec128, body2.internalGetDeltaAngularVelocity().mVec128));
+ deltaImpulse = _mm_sub_ps(deltaImpulse, _mm_mul_ps(deltaVel1Dotn, _mm_set1_ps(c.m_jacDiagABInv)));
+ deltaImpulse = _mm_sub_ps(deltaImpulse, _mm_mul_ps(deltaVel2Dotn, _mm_set1_ps(c.m_jacDiagABInv)));
+ btSimdScalar sum = _mm_add_ps(cpAppliedImp, deltaImpulse);
+ btSimdScalar resultLowerLess, resultUpperLess;
+ resultLowerLess = _mm_cmplt_ps(sum, lowerLimit1);
+ resultUpperLess = _mm_cmplt_ps(sum, upperLimit1);
+ __m128 lowMinApplied = _mm_sub_ps(lowerLimit1, cpAppliedImp);
+ deltaImpulse = _mm_or_ps(_mm_and_ps(resultLowerLess, lowMinApplied), _mm_andnot_ps(resultLowerLess, deltaImpulse));
+ c.m_appliedImpulse = _mm_or_ps(_mm_and_ps(resultLowerLess, lowerLimit1), _mm_andnot_ps(resultLowerLess, sum));
+ __m128 upperMinApplied = _mm_sub_ps(upperLimit1, cpAppliedImp);
+ deltaImpulse = _mm_or_ps(_mm_and_ps(resultUpperLess, deltaImpulse), _mm_andnot_ps(resultUpperLess, upperMinApplied));
+ c.m_appliedImpulse = _mm_or_ps(_mm_and_ps(resultUpperLess, c.m_appliedImpulse), _mm_andnot_ps(resultUpperLess, upperLimit1));
+ __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal1.mVec128, body1.internalGetInvMass().mVec128);
+ __m128 linearComponentB = _mm_mul_ps((c.m_contactNormal2).mVec128, body2.internalGetInvMass().mVec128);
+ __m128 impulseMagnitude = deltaImpulse;
+ body1.internalGetDeltaLinearVelocity().mVec128 = _mm_add_ps(body1.internalGetDeltaLinearVelocity().mVec128, _mm_mul_ps(linearComponentA, impulseMagnitude));
+ body1.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(body1.internalGetDeltaAngularVelocity().mVec128, _mm_mul_ps(c.m_angularComponentA.mVec128, impulseMagnitude));
+ body2.internalGetDeltaLinearVelocity().mVec128 = _mm_add_ps(body2.internalGetDeltaLinearVelocity().mVec128, _mm_mul_ps(linearComponentB, impulseMagnitude));
+ body2.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(body2.internalGetDeltaAngularVelocity().mVec128, _mm_mul_ps(c.m_angularComponentB.mVec128, impulseMagnitude));
+ return deltaImpulse;
+}
+
+
+// Enhanced version of gResolveSingleConstraintRowGeneric_sse2 with SSE4.1 and FMA3
+static btSimdScalar gResolveSingleConstraintRowGeneric_sse4_1_fma3(btSolverBody& body1, btSolverBody& body2, const btSolverConstraint& c)
+{
+#if defined (BT_ALLOW_SSE4)
+ __m128 tmp = _mm_set_ps1(c.m_jacDiagABInv);
+ __m128 deltaImpulse = _mm_set_ps1(c.m_rhs - btScalar(c.m_appliedImpulse)*c.m_cfm);
+ const __m128 lowerLimit = _mm_set_ps1(c.m_lowerLimit);
+ const __m128 upperLimit = _mm_set_ps1(c.m_upperLimit);
+ const __m128 deltaVel1Dotn = _mm_add_ps(DOT_PRODUCT(c.m_contactNormal1.mVec128, body1.internalGetDeltaLinearVelocity().mVec128), DOT_PRODUCT(c.m_relpos1CrossNormal.mVec128, body1.internalGetDeltaAngularVelocity().mVec128));
+ const __m128 deltaVel2Dotn = _mm_add_ps(DOT_PRODUCT(c.m_contactNormal2.mVec128, body2.internalGetDeltaLinearVelocity().mVec128), DOT_PRODUCT(c.m_relpos2CrossNormal.mVec128, body2.internalGetDeltaAngularVelocity().mVec128));
+ deltaImpulse = FMNADD(deltaVel1Dotn, tmp, deltaImpulse);
+ deltaImpulse = FMNADD(deltaVel2Dotn, tmp, deltaImpulse);
+ tmp = _mm_add_ps(c.m_appliedImpulse, deltaImpulse); // sum
+ const __m128 maskLower = _mm_cmpgt_ps(tmp, lowerLimit);
+ const __m128 maskUpper = _mm_cmpgt_ps(upperLimit, tmp);
+ deltaImpulse = _mm_blendv_ps(_mm_sub_ps(lowerLimit, c.m_appliedImpulse), _mm_blendv_ps(_mm_sub_ps(upperLimit, c.m_appliedImpulse), deltaImpulse, maskUpper), maskLower);
+ c.m_appliedImpulse = _mm_blendv_ps(lowerLimit, _mm_blendv_ps(upperLimit, tmp, maskUpper), maskLower);
+ body1.internalGetDeltaLinearVelocity().mVec128 = FMADD(_mm_mul_ps(c.m_contactNormal1.mVec128, body1.internalGetInvMass().mVec128), deltaImpulse, body1.internalGetDeltaLinearVelocity().mVec128);
+ body1.internalGetDeltaAngularVelocity().mVec128 = FMADD(c.m_angularComponentA.mVec128, deltaImpulse, body1.internalGetDeltaAngularVelocity().mVec128);
+ body2.internalGetDeltaLinearVelocity().mVec128 = FMADD(_mm_mul_ps(c.m_contactNormal2.mVec128, body2.internalGetInvMass().mVec128), deltaImpulse, body2.internalGetDeltaLinearVelocity().mVec128);
+ body2.internalGetDeltaAngularVelocity().mVec128 = FMADD(c.m_angularComponentB.mVec128, deltaImpulse, body2.internalGetDeltaAngularVelocity().mVec128);
+ return deltaImpulse;
+#else
+ return gResolveSingleConstraintRowGeneric_sse2(body1,body2,c);
+#endif
+}
+
+
+
+static btSimdScalar gResolveSingleConstraintRowLowerLimit_sse2(btSolverBody& body1, btSolverBody& body2, const btSolverConstraint& c)
+{
+ __m128 cpAppliedImp = _mm_set1_ps(c.m_appliedImpulse);
+ __m128 lowerLimit1 = _mm_set1_ps(c.m_lowerLimit);
+ __m128 upperLimit1 = _mm_set1_ps(c.m_upperLimit);
+ btSimdScalar deltaImpulse = _mm_sub_ps(_mm_set1_ps(c.m_rhs), _mm_mul_ps(_mm_set1_ps(c.m_appliedImpulse), _mm_set1_ps(c.m_cfm)));
+ __m128 deltaVel1Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal1.mVec128, body1.internalGetDeltaLinearVelocity().mVec128), btSimdDot3(c.m_relpos1CrossNormal.mVec128, body1.internalGetDeltaAngularVelocity().mVec128));
+ __m128 deltaVel2Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal2.mVec128, body2.internalGetDeltaLinearVelocity().mVec128), btSimdDot3(c.m_relpos2CrossNormal.mVec128, body2.internalGetDeltaAngularVelocity().mVec128));
+ deltaImpulse = _mm_sub_ps(deltaImpulse, _mm_mul_ps(deltaVel1Dotn, _mm_set1_ps(c.m_jacDiagABInv)));
+ deltaImpulse = _mm_sub_ps(deltaImpulse, _mm_mul_ps(deltaVel2Dotn, _mm_set1_ps(c.m_jacDiagABInv)));
+ btSimdScalar sum = _mm_add_ps(cpAppliedImp, deltaImpulse);
+ btSimdScalar resultLowerLess, resultUpperLess;
+ resultLowerLess = _mm_cmplt_ps(sum, lowerLimit1);
+ resultUpperLess = _mm_cmplt_ps(sum, upperLimit1);
+ __m128 lowMinApplied = _mm_sub_ps(lowerLimit1, cpAppliedImp);
+ deltaImpulse = _mm_or_ps(_mm_and_ps(resultLowerLess, lowMinApplied), _mm_andnot_ps(resultLowerLess, deltaImpulse));
+ c.m_appliedImpulse = _mm_or_ps(_mm_and_ps(resultLowerLess, lowerLimit1), _mm_andnot_ps(resultLowerLess, sum));
+ __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal1.mVec128, body1.internalGetInvMass().mVec128);
+ __m128 linearComponentB = _mm_mul_ps(c.m_contactNormal2.mVec128, body2.internalGetInvMass().mVec128);
+ __m128 impulseMagnitude = deltaImpulse;
+ body1.internalGetDeltaLinearVelocity().mVec128 = _mm_add_ps(body1.internalGetDeltaLinearVelocity().mVec128, _mm_mul_ps(linearComponentA, impulseMagnitude));
+ body1.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(body1.internalGetDeltaAngularVelocity().mVec128, _mm_mul_ps(c.m_angularComponentA.mVec128, impulseMagnitude));
+ body2.internalGetDeltaLinearVelocity().mVec128 = _mm_add_ps(body2.internalGetDeltaLinearVelocity().mVec128, _mm_mul_ps(linearComponentB, impulseMagnitude));
+ body2.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(body2.internalGetDeltaAngularVelocity().mVec128, _mm_mul_ps(c.m_angularComponentB.mVec128, impulseMagnitude));
+ return deltaImpulse;
+}
+
+
+// Enhanced version of gResolveSingleConstraintRowGeneric_sse2 with SSE4.1 and FMA3
+static btSimdScalar gResolveSingleConstraintRowLowerLimit_sse4_1_fma3(btSolverBody& body1, btSolverBody& body2, const btSolverConstraint& c)
+{
+#ifdef BT_ALLOW_SSE4
+ __m128 tmp = _mm_set_ps1(c.m_jacDiagABInv);
+ __m128 deltaImpulse = _mm_set_ps1(c.m_rhs - btScalar(c.m_appliedImpulse)*c.m_cfm);
+ const __m128 lowerLimit = _mm_set_ps1(c.m_lowerLimit);
+ const __m128 deltaVel1Dotn = _mm_add_ps(DOT_PRODUCT(c.m_contactNormal1.mVec128, body1.internalGetDeltaLinearVelocity().mVec128), DOT_PRODUCT(c.m_relpos1CrossNormal.mVec128, body1.internalGetDeltaAngularVelocity().mVec128));
+ const __m128 deltaVel2Dotn = _mm_add_ps(DOT_PRODUCT(c.m_contactNormal2.mVec128, body2.internalGetDeltaLinearVelocity().mVec128), DOT_PRODUCT(c.m_relpos2CrossNormal.mVec128, body2.internalGetDeltaAngularVelocity().mVec128));
+ deltaImpulse = FMNADD(deltaVel1Dotn, tmp, deltaImpulse);
+ deltaImpulse = FMNADD(deltaVel2Dotn, tmp, deltaImpulse);
+ tmp = _mm_add_ps(c.m_appliedImpulse, deltaImpulse);
+ const __m128 mask = _mm_cmpgt_ps(tmp, lowerLimit);
+ deltaImpulse = _mm_blendv_ps(_mm_sub_ps(lowerLimit, c.m_appliedImpulse), deltaImpulse, mask);
+ c.m_appliedImpulse = _mm_blendv_ps(lowerLimit, tmp, mask);
+ body1.internalGetDeltaLinearVelocity().mVec128 = FMADD(_mm_mul_ps(c.m_contactNormal1.mVec128, body1.internalGetInvMass().mVec128), deltaImpulse, body1.internalGetDeltaLinearVelocity().mVec128);
+ body1.internalGetDeltaAngularVelocity().mVec128 = FMADD(c.m_angularComponentA.mVec128, deltaImpulse, body1.internalGetDeltaAngularVelocity().mVec128);
+ body2.internalGetDeltaLinearVelocity().mVec128 = FMADD(_mm_mul_ps(c.m_contactNormal2.mVec128, body2.internalGetInvMass().mVec128), deltaImpulse, body2.internalGetDeltaLinearVelocity().mVec128);
+ body2.internalGetDeltaAngularVelocity().mVec128 = FMADD(c.m_angularComponentB.mVec128, deltaImpulse, body2.internalGetDeltaAngularVelocity().mVec128);
+ return deltaImpulse;
+#else
+ return gResolveSingleConstraintRowLowerLimit_sse2(body1,body2,c);
+#endif //BT_ALLOW_SSE4
+}
+
+
+#endif //USE_SIMD
+
+
+
+btSimdScalar btSequentialImpulseConstraintSolver::resolveSingleConstraintRowGenericSIMD(btSolverBody& body1,btSolverBody& body2,const btSolverConstraint& c)
+{
+ return m_resolveSingleConstraintRowGeneric(body1, body2, c);
+}
+
+// Project Gauss Seidel or the equivalent Sequential Impulse
+btSimdScalar btSequentialImpulseConstraintSolver::resolveSingleConstraintRowGeneric(btSolverBody& body1,btSolverBody& body2,const btSolverConstraint& c)
+{
+ return m_resolveSingleConstraintRowGeneric(body1, body2, c);
+}
+
+btSimdScalar btSequentialImpulseConstraintSolver::resolveSingleConstraintRowLowerLimitSIMD(btSolverBody& body1,btSolverBody& body2,const btSolverConstraint& c)
+{
+ return m_resolveSingleConstraintRowLowerLimit(body1, body2, c);
+}
+
+
+btSimdScalar btSequentialImpulseConstraintSolver::resolveSingleConstraintRowLowerLimit(btSolverBody& body1,btSolverBody& body2,const btSolverConstraint& c)
+{
+ return m_resolveSingleConstraintRowLowerLimit(body1, body2, c);
+}
+
+
+static btSimdScalar gResolveSplitPenetrationImpulse_scalar_reference(
+ btSolverBody& body1,
+ btSolverBody& body2,
+ const btSolverConstraint& c)
+{
+ btScalar deltaImpulse = 0.f;
+
+ if (c.m_rhsPenetration)
+ {
+ gNumSplitImpulseRecoveries++;
+ deltaImpulse = c.m_rhsPenetration-btScalar(c.m_appliedPushImpulse)*c.m_cfm;
+ const btScalar deltaVel1Dotn = c.m_contactNormal1.dot(body1.internalGetPushVelocity()) + c.m_relpos1CrossNormal.dot(body1.internalGetTurnVelocity());
+ const btScalar deltaVel2Dotn = c.m_contactNormal2.dot(body2.internalGetPushVelocity()) + c.m_relpos2CrossNormal.dot(body2.internalGetTurnVelocity());
+
+ deltaImpulse -= deltaVel1Dotn*c.m_jacDiagABInv;
+ deltaImpulse -= deltaVel2Dotn*c.m_jacDiagABInv;
+ const btScalar sum = btScalar(c.m_appliedPushImpulse) + deltaImpulse;
+ if (sum < c.m_lowerLimit)
+ {
+ deltaImpulse = c.m_lowerLimit-c.m_appliedPushImpulse;
+ c.m_appliedPushImpulse = c.m_lowerLimit;
+ }
+ else
+ {
+ c.m_appliedPushImpulse = sum;
+ }
+ body1.internalApplyPushImpulse(c.m_contactNormal1*body1.internalGetInvMass(),c.m_angularComponentA,deltaImpulse);
+ body2.internalApplyPushImpulse(c.m_contactNormal2*body2.internalGetInvMass(),c.m_angularComponentB,deltaImpulse);
+ }
+ return deltaImpulse;
+}
+
+static btSimdScalar gResolveSplitPenetrationImpulse_sse2(btSolverBody& body1,btSolverBody& body2,const btSolverConstraint& c)
+{
+#ifdef USE_SIMD
+ if (!c.m_rhsPenetration)
+ return 0.f;
+
+ gNumSplitImpulseRecoveries++;
+
+ __m128 cpAppliedImp = _mm_set1_ps(c.m_appliedPushImpulse);
+ __m128 lowerLimit1 = _mm_set1_ps(c.m_lowerLimit);
+ __m128 upperLimit1 = _mm_set1_ps(c.m_upperLimit);
+ __m128 deltaImpulse = _mm_sub_ps(_mm_set1_ps(c.m_rhsPenetration), _mm_mul_ps(_mm_set1_ps(c.m_appliedPushImpulse),_mm_set1_ps(c.m_cfm)));
+ __m128 deltaVel1Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal1.mVec128,body1.internalGetPushVelocity().mVec128), btSimdDot3(c.m_relpos1CrossNormal.mVec128,body1.internalGetTurnVelocity().mVec128));
+ __m128 deltaVel2Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal2.mVec128,body2.internalGetPushVelocity().mVec128), btSimdDot3(c.m_relpos2CrossNormal.mVec128,body2.internalGetTurnVelocity().mVec128));
+ deltaImpulse = _mm_sub_ps(deltaImpulse,_mm_mul_ps(deltaVel1Dotn,_mm_set1_ps(c.m_jacDiagABInv)));
+ deltaImpulse = _mm_sub_ps(deltaImpulse,_mm_mul_ps(deltaVel2Dotn,_mm_set1_ps(c.m_jacDiagABInv)));
+ btSimdScalar sum = _mm_add_ps(cpAppliedImp,deltaImpulse);
+ btSimdScalar resultLowerLess,resultUpperLess;
+ resultLowerLess = _mm_cmplt_ps(sum,lowerLimit1);
+ resultUpperLess = _mm_cmplt_ps(sum,upperLimit1);
+ __m128 lowMinApplied = _mm_sub_ps(lowerLimit1,cpAppliedImp);
+ deltaImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowMinApplied), _mm_andnot_ps(resultLowerLess, deltaImpulse) );
+ c.m_appliedPushImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowerLimit1), _mm_andnot_ps(resultLowerLess, sum) );
+ __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal1.mVec128,body1.internalGetInvMass().mVec128);
+ __m128 linearComponentB = _mm_mul_ps(c.m_contactNormal2.mVec128,body2.internalGetInvMass().mVec128);
+ __m128 impulseMagnitude = deltaImpulse;
+ body1.internalGetPushVelocity().mVec128 = _mm_add_ps(body1.internalGetPushVelocity().mVec128,_mm_mul_ps(linearComponentA,impulseMagnitude));
+ body1.internalGetTurnVelocity().mVec128 = _mm_add_ps(body1.internalGetTurnVelocity().mVec128 ,_mm_mul_ps(c.m_angularComponentA.mVec128,impulseMagnitude));
+ body2.internalGetPushVelocity().mVec128 = _mm_add_ps(body2.internalGetPushVelocity().mVec128,_mm_mul_ps(linearComponentB,impulseMagnitude));
+ body2.internalGetTurnVelocity().mVec128 = _mm_add_ps(body2.internalGetTurnVelocity().mVec128 ,_mm_mul_ps(c.m_angularComponentB.mVec128,impulseMagnitude));
+ return deltaImpulse;
+#else
+ return gResolveSplitPenetrationImpulse_scalar_reference(body1,body2,c);
+#endif
+}
+
+
+btSequentialImpulseConstraintSolver::btSequentialImpulseConstraintSolver()
+{
+ m_btSeed2 = 0;
+ m_cachedSolverMode = 0;
+ setupSolverFunctions( false );
+}
+
+void btSequentialImpulseConstraintSolver::setupSolverFunctions( bool useSimd )
+{
+ m_resolveSingleConstraintRowGeneric = gResolveSingleConstraintRowGeneric_scalar_reference;
+ m_resolveSingleConstraintRowLowerLimit = gResolveSingleConstraintRowLowerLimit_scalar_reference;
+ m_resolveSplitPenetrationImpulse = gResolveSplitPenetrationImpulse_scalar_reference;
+
+ if ( useSimd )
+ {
+#ifdef USE_SIMD
+ m_resolveSingleConstraintRowGeneric = gResolveSingleConstraintRowGeneric_sse2;
+ m_resolveSingleConstraintRowLowerLimit = gResolveSingleConstraintRowLowerLimit_sse2;
+ m_resolveSplitPenetrationImpulse = gResolveSplitPenetrationImpulse_sse2;
+
+#ifdef BT_ALLOW_SSE4
+ int cpuFeatures = btCpuFeatureUtility::getCpuFeatures();
+ if ((cpuFeatures & btCpuFeatureUtility::CPU_FEATURE_FMA3) && (cpuFeatures & btCpuFeatureUtility::CPU_FEATURE_SSE4_1))
+ {
+ m_resolveSingleConstraintRowGeneric = gResolveSingleConstraintRowGeneric_sse4_1_fma3;
+ m_resolveSingleConstraintRowLowerLimit = gResolveSingleConstraintRowLowerLimit_sse4_1_fma3;
+ }
+#endif//BT_ALLOW_SSE4
+#endif //USE_SIMD
+ }
+}
+
+ btSequentialImpulseConstraintSolver::~btSequentialImpulseConstraintSolver()
+ {
+ }
+
+ btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getScalarConstraintRowSolverGeneric()
+ {
+ return gResolveSingleConstraintRowGeneric_scalar_reference;
+ }
+
+ btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getScalarConstraintRowSolverLowerLimit()
+ {
+ return gResolveSingleConstraintRowLowerLimit_scalar_reference;
+ }
+
+
+#ifdef USE_SIMD
+ btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getSSE2ConstraintRowSolverGeneric()
+ {
+ return gResolveSingleConstraintRowGeneric_sse2;
+ }
+ btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getSSE2ConstraintRowSolverLowerLimit()
+ {
+ return gResolveSingleConstraintRowLowerLimit_sse2;
+ }
+#ifdef BT_ALLOW_SSE4
+ btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getSSE4_1ConstraintRowSolverGeneric()
+ {
+ return gResolveSingleConstraintRowGeneric_sse4_1_fma3;
+ }
+ btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getSSE4_1ConstraintRowSolverLowerLimit()
+ {
+ return gResolveSingleConstraintRowLowerLimit_sse4_1_fma3;
+ }
+#endif //BT_ALLOW_SSE4
+#endif //USE_SIMD
+
+unsigned long btSequentialImpulseConstraintSolver::btRand2()
+{
+ m_btSeed2 = (1664525L*m_btSeed2 + 1013904223L) & 0xffffffff;
+ return m_btSeed2;
+}
+
+
+
+//See ODE: adam's all-int straightforward(?) dRandInt (0..n-1)
+int btSequentialImpulseConstraintSolver::btRandInt2 (int n)
+{
+ // seems good; xor-fold and modulus
+ const unsigned long un = static_cast<unsigned long>(n);
+ unsigned long r = btRand2();
+
+ // 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) {
+ r ^= (r >> 16);
+ if (un <= 0x00000100UL) {
+ r ^= (r >> 8);
+ if (un <= 0x00000010UL) {
+ r ^= (r >> 4);
+ if (un <= 0x00000004UL) {
+ r ^= (r >> 2);
+ if (un <= 0x00000002UL) {
+ r ^= (r >> 1);
+ }
+ }
+ }
+ }
+ }
+
+ return (int) (r % un);
+}
+
+
+
+void btSequentialImpulseConstraintSolver::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);
+ }
+
+
+}
+
+
+
+
+
+
+btScalar btSequentialImpulseConstraintSolver::restitutionCurve(btScalar rel_vel, btScalar restitution, btScalar velocityThreshold)
+{
+ //printf("rel_vel =%f\n", rel_vel);
+ if (btFabs(rel_vel)<velocityThreshold)
+ return 0.;
+
+ btScalar rest = restitution * -rel_vel;
+ return rest;
+}
+
+
+
+void btSequentialImpulseConstraintSolver::applyAnisotropicFriction(btCollisionObject* colObj,btVector3& frictionDirection, int frictionMode)
+{
+
+
+ if (colObj && colObj->hasAnisotropicFriction(frictionMode))
+ {
+ // transform to local coordinates
+ btVector3 loc_lateral = frictionDirection * colObj->getWorldTransform().getBasis();
+ const btVector3& friction_scaling = colObj->getAnisotropicFriction();
+ //apply anisotropic friction
+ loc_lateral *= friction_scaling;
+ // ... and transform it back to global coordinates
+ frictionDirection = colObj->getWorldTransform().getBasis() * loc_lateral;
+ }
+
+}
+
+
+
+
+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 = m_tmpSolverBodyPool[solverBodyIdA];
+ btSolverBody& solverBodyB = m_tmpSolverBodyPool[solverBodyIdB];
+
+ btRigidBody* body0 = m_tmpSolverBodyPool[solverBodyIdA].m_originalBody;
+ btRigidBody* body1 = m_tmpSolverBodyPool[solverBodyIdB].m_originalBody;
+
+ solverConstraint.m_solverBodyIdA = solverBodyIdA;
+ solverConstraint.m_solverBodyIdB = solverBodyIdB;
+
+ solverConstraint.m_friction = cp.m_combinedFriction;
+ solverConstraint.m_originalContactPoint = 0;
+
+ solverConstraint.m_appliedImpulse = 0.f;
+ solverConstraint.m_appliedPushImpulse = 0.f;
+
+ if (body0)
+ {
+ solverConstraint.m_contactNormal1 = normalAxis;
+ btVector3 ftorqueAxis1 = rel_pos1.cross(solverConstraint.m_contactNormal1);
+ solverConstraint.m_relpos1CrossNormal = ftorqueAxis1;
+ solverConstraint.m_angularComponentA = body0->getInvInertiaTensorWorld()*ftorqueAxis1*body0->getAngularFactor();
+ }else
+ {
+ solverConstraint.m_contactNormal1.setZero();
+ solverConstraint.m_relpos1CrossNormal.setZero();
+ solverConstraint.m_angularComponentA .setZero();
+ }
+
+ if (body1)
+ {
+ solverConstraint.m_contactNormal2 = -normalAxis;
+ btVector3 ftorqueAxis1 = rel_pos2.cross(solverConstraint.m_contactNormal2);
+ solverConstraint.m_relpos2CrossNormal = ftorqueAxis1;
+ solverConstraint.m_angularComponentB = body1->getInvInertiaTensorWorld()*ftorqueAxis1*body1->getAngularFactor();
+ } else
+ {
+ solverConstraint.m_contactNormal2.setZero();
+ solverConstraint.m_relpos2CrossNormal.setZero();
+ solverConstraint.m_angularComponentB.setZero();
+ }
+
+ {
+ btVector3 vec;
+ btScalar denom0 = 0.f;
+ btScalar denom1 = 0.f;
+ if (body0)
+ {
+ vec = ( solverConstraint.m_angularComponentA).cross(rel_pos1);
+ denom0 = body0->getInvMass() + normalAxis.dot(vec);
+ }
+ if (body1)
+ {
+ vec = ( -solverConstraint.m_angularComponentB).cross(rel_pos2);
+ denom1 = body1->getInvMass() + normalAxis.dot(vec);
+ }
+ btScalar denom = relaxation/(denom0+denom1);
+ solverConstraint.m_jacDiagABInv = denom;
+ }
+
+ {
+
+
+ btScalar rel_vel;
+ btScalar vel1Dotn = solverConstraint.m_contactNormal1.dot(body0?solverBodyA.m_linearVelocity+solverBodyA.m_externalForceImpulse:btVector3(0,0,0))
+ + solverConstraint.m_relpos1CrossNormal.dot(body0?solverBodyA.m_angularVelocity:btVector3(0,0,0));
+ btScalar vel2Dotn = solverConstraint.m_contactNormal2.dot(body1?solverBodyB.m_linearVelocity+solverBodyB.m_externalForceImpulse:btVector3(0,0,0))
+ + solverConstraint.m_relpos2CrossNormal.dot(body1?solverBodyB.m_angularVelocity:btVector3(0,0,0));
+
+ rel_vel = vel1Dotn+vel2Dotn;
+
+// btScalar positionalError = 0.f;
+
+ btScalar velocityError = desiredVelocity - rel_vel;
+ btScalar velocityImpulse = velocityError * solverConstraint.m_jacDiagABInv;
+
+ btScalar penetrationImpulse = btScalar(0);
+
+ if (cp.m_contactPointFlags & BT_CONTACT_FLAG_FRICTION_ANCHOR)
+ {
+ btScalar distance = (cp.getPositionWorldOnA() - cp.getPositionWorldOnB()).dot(normalAxis);
+ btScalar positionalError = -distance * infoGlobal.m_frictionERP/infoGlobal.m_timeStep;
+ penetrationImpulse = positionalError*solverConstraint.m_jacDiagABInv;
+ }
+
+ solverConstraint.m_rhs = penetrationImpulse + velocityImpulse;
+ solverConstraint.m_rhsPenetration = 0.f;
+ solverConstraint.m_cfm = cfmSlip;
+ solverConstraint.m_lowerLimit = -solverConstraint.m_friction;
+ solverConstraint.m_upperLimit = solverConstraint.m_friction;
+
+ }
+}
+
+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();
+ solverConstraint.m_frictionIndex = frictionIndex;
+ setupFrictionConstraint(solverConstraint, normalAxis, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2,
+ colObj0, colObj1, relaxation, infoGlobal, desiredVelocity, cfmSlip);
+ return solverConstraint;
+}
+
+
+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)
+
+{
+ btVector3 normalAxis(0,0,0);
+
+
+ solverConstraint.m_contactNormal1 = normalAxis;
+ solverConstraint.m_contactNormal2 = -normalAxis;
+ btSolverBody& solverBodyA = m_tmpSolverBodyPool[solverBodyIdA];
+ btSolverBody& solverBodyB = m_tmpSolverBodyPool[solverBodyIdB];
+
+ btRigidBody* body0 = m_tmpSolverBodyPool[solverBodyIdA].m_originalBody;
+ btRigidBody* body1 = m_tmpSolverBodyPool[solverBodyIdB].m_originalBody;
+
+ solverConstraint.m_solverBodyIdA = solverBodyIdA;
+ solverConstraint.m_solverBodyIdB = solverBodyIdB;
+
+ solverConstraint.m_friction = combinedTorsionalFriction;
+ solverConstraint.m_originalContactPoint = 0;
+
+ solverConstraint.m_appliedImpulse = 0.f;
+ solverConstraint.m_appliedPushImpulse = 0.f;
+
+ {
+ btVector3 ftorqueAxis1 = -normalAxis1;
+ solverConstraint.m_relpos1CrossNormal = ftorqueAxis1;
+ solverConstraint.m_angularComponentA = body0 ? body0->getInvInertiaTensorWorld()*ftorqueAxis1*body0->getAngularFactor() : btVector3(0,0,0);
+ }
+ {
+ btVector3 ftorqueAxis1 = normalAxis1;
+ solverConstraint.m_relpos2CrossNormal = ftorqueAxis1;
+ solverConstraint.m_angularComponentB = body1 ? body1->getInvInertiaTensorWorld()*ftorqueAxis1*body1->getAngularFactor() : btVector3(0,0,0);
+ }
+
+
+ {
+ btVector3 iMJaA = body0?body0->getInvInertiaTensorWorld()*solverConstraint.m_relpos1CrossNormal:btVector3(0,0,0);
+ btVector3 iMJaB = body1?body1->getInvInertiaTensorWorld()*solverConstraint.m_relpos2CrossNormal:btVector3(0,0,0);
+ btScalar sum = 0;
+ sum += iMJaA.dot(solverConstraint.m_relpos1CrossNormal);
+ sum += iMJaB.dot(solverConstraint.m_relpos2CrossNormal);
+ solverConstraint.m_jacDiagABInv = btScalar(1.)/sum;
+ }
+
+ {
+
+
+ btScalar rel_vel;
+ btScalar vel1Dotn = solverConstraint.m_contactNormal1.dot(body0?solverBodyA.m_linearVelocity+solverBodyA.m_externalForceImpulse:btVector3(0,0,0))
+ + solverConstraint.m_relpos1CrossNormal.dot(body0?solverBodyA.m_angularVelocity:btVector3(0,0,0));
+ btScalar vel2Dotn = solverConstraint.m_contactNormal2.dot(body1?solverBodyB.m_linearVelocity+solverBodyB.m_externalForceImpulse:btVector3(0,0,0))
+ + solverConstraint.m_relpos2CrossNormal.dot(body1?solverBodyB.m_angularVelocity:btVector3(0,0,0));
+
+ rel_vel = vel1Dotn+vel2Dotn;
+
+// btScalar positionalError = 0.f;
+
+ btSimdScalar velocityError = desiredVelocity - rel_vel;
+ btSimdScalar velocityImpulse = velocityError * btSimdScalar(solverConstraint.m_jacDiagABInv);
+ solverConstraint.m_rhs = velocityImpulse;
+ solverConstraint.m_cfm = cfmSlip;
+ solverConstraint.m_lowerLimit = -solverConstraint.m_friction;
+ solverConstraint.m_upperLimit = solverConstraint.m_friction;
+
+ }
+}
+
+
+
+
+
+
+
+
+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();
+ solverConstraint.m_frictionIndex = frictionIndex;
+ setupTorsionalFrictionConstraint(solverConstraint, normalAxis, solverBodyIdA, solverBodyIdB, cp, combinedTorsionalFriction,rel_pos1, rel_pos2,
+ colObj0, colObj1, relaxation, desiredVelocity, cfmSlip);
+ return solverConstraint;
+}
+
+
+int btSequentialImpulseConstraintSolver::getOrInitSolverBody(btCollisionObject& body,btScalar timeStep)
+{
+#if BT_THREADSAFE
+ int solverBodyId = -1;
+ if ( !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 )
+ {
+ if ( btRigidBody* rb = btRigidBody::upcast( &body ) )
+ {
+ solverBodyId = m_tmpSolverBodyPool.size();
+ btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
+ initSolverBody( &solverBody, &body, timeStep );
+ body.setCompanionId( solverBodyId );
+ }
+ }
+ }
+ else if (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
+ btRigidBody* rb = btRigidBody::upcast( &body );
+ solverBodyId = m_tmpSolverBodyPool.size();
+ btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
+ initSolverBody( &solverBody, &body, timeStep );
+ m_kinematicBodyUniqueIdToSolverBodyTable[ uniqueId ] = solverBodyId;
+ }
+ }
+ else
+ {
+ // 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 < 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
+
+}
+#include <stdio.h>
+
+
+void btSequentialImpulseConstraintSolver::setupContactConstraint(btSolverConstraint& solverConstraint,
+ int solverBodyIdA, int solverBodyIdB,
+ btManifoldPoint& cp, const btContactSolverInfo& infoGlobal,
+ btScalar& relaxation,
+ const btVector3& rel_pos1, const btVector3& rel_pos2)
+{
+
+ // const btVector3& pos1 = cp.getPositionWorldOnA();
+ // const btVector3& pos2 = cp.getPositionWorldOnB();
+
+ btSolverBody* bodyA = &m_tmpSolverBodyPool[solverBodyIdA];
+ btSolverBody* bodyB = &m_tmpSolverBodyPool[solverBodyIdB];
+
+ btRigidBody* rb0 = bodyA->m_originalBody;
+ btRigidBody* rb1 = bodyB->m_originalBody;
+
+// btVector3 rel_pos1 = pos1 - colObj0->getWorldTransform().getOrigin();
+// btVector3 rel_pos2 = pos2 - colObj1->getWorldTransform().getOrigin();
+ //rel_pos1 = pos1 - bodyA->getWorldTransform().getOrigin();
+ //rel_pos2 = pos2 - bodyB->getWorldTransform().getOrigin();
+
+ relaxation = infoGlobal.m_sor;
+ btScalar invTimeStep = btScalar(1)/infoGlobal.m_timeStep;
+
+ //cfm = 1 / ( dt * kp + kd )
+ //erp = dt * kp / ( dt * kp + kd )
+
+ btScalar cfm = infoGlobal.m_globalCfm;
+ btScalar erp = infoGlobal.m_erp2;
+
+ if ((cp.m_contactPointFlags&BT_CONTACT_FLAG_HAS_CONTACT_CFM) || (cp.m_contactPointFlags&BT_CONTACT_FLAG_HAS_CONTACT_ERP))
+ {
+ if (cp.m_contactPointFlags&BT_CONTACT_FLAG_HAS_CONTACT_CFM)
+ cfm = cp.m_contactCFM;
+ if (cp.m_contactPointFlags&BT_CONTACT_FLAG_HAS_CONTACT_ERP)
+ erp = cp.m_contactERP;
+ } else
+ {
+ if (cp.m_contactPointFlags & BT_CONTACT_FLAG_CONTACT_STIFFNESS_DAMPING)
+ {
+ btScalar denom = ( infoGlobal.m_timeStep * cp.m_combinedContactStiffness1 + cp.m_combinedContactDamping1 );
+ if (denom < SIMD_EPSILON)
+ {
+ denom = SIMD_EPSILON;
+ }
+ cfm = btScalar(1) / denom;
+ erp = (infoGlobal.m_timeStep * cp.m_combinedContactStiffness1) / denom;
+ }
+ }
+
+ cfm *= invTimeStep;
+
+
+ btVector3 torqueAxis0 = rel_pos1.cross(cp.m_normalWorldOnB);
+ solverConstraint.m_angularComponentA = rb0 ? rb0->getInvInertiaTensorWorld()*torqueAxis0*rb0->getAngularFactor() : btVector3(0,0,0);
+ btVector3 torqueAxis1 = rel_pos2.cross(cp.m_normalWorldOnB);
+ solverConstraint.m_angularComponentB = rb1 ? rb1->getInvInertiaTensorWorld()*-torqueAxis1*rb1->getAngularFactor() : btVector3(0,0,0);
+
+ {
+#ifdef COMPUTE_IMPULSE_DENOM
+ btScalar denom0 = rb0->computeImpulseDenominator(pos1,cp.m_normalWorldOnB);
+ btScalar denom1 = rb1->computeImpulseDenominator(pos2,cp.m_normalWorldOnB);
+#else
+ btVector3 vec;
+ btScalar denom0 = 0.f;
+ btScalar denom1 = 0.f;
+ if (rb0)
+ {
+ vec = ( solverConstraint.m_angularComponentA).cross(rel_pos1);
+ denom0 = rb0->getInvMass() + cp.m_normalWorldOnB.dot(vec);
+ }
+ if (rb1)
+ {
+ vec = ( -solverConstraint.m_angularComponentB).cross(rel_pos2);
+ denom1 = rb1->getInvMass() + cp.m_normalWorldOnB.dot(vec);
+ }
+#endif //COMPUTE_IMPULSE_DENOM
+
+ btScalar denom = relaxation/(denom0+denom1+cfm);
+ solverConstraint.m_jacDiagABInv = denom;
+ }
+
+ if (rb0)
+ {
+ solverConstraint.m_contactNormal1 = cp.m_normalWorldOnB;
+ solverConstraint.m_relpos1CrossNormal = torqueAxis0;
+ } else
+ {
+ solverConstraint.m_contactNormal1.setZero();
+ solverConstraint.m_relpos1CrossNormal.setZero();
+ }
+ if (rb1)
+ {
+ solverConstraint.m_contactNormal2 = -cp.m_normalWorldOnB;
+ solverConstraint.m_relpos2CrossNormal = -torqueAxis1;
+ }else
+ {
+ solverConstraint.m_contactNormal2.setZero();
+ solverConstraint.m_relpos2CrossNormal.setZero();
+ }
+
+ btScalar restitution = 0.f;
+ btScalar penetration = cp.getDistance()+infoGlobal.m_linearSlop;
+
+ {
+ btVector3 vel1,vel2;
+
+ vel1 = rb0? rb0->getVelocityInLocalPoint(rel_pos1) : btVector3(0,0,0);
+ vel2 = rb1? rb1->getVelocityInLocalPoint(rel_pos2) : btVector3(0,0,0);
+
+ // btVector3 vel2 = rb1 ? rb1->getVelocityInLocalPoint(rel_pos2) : btVector3(0,0,0);
+ btVector3 vel = vel1 - vel2;
+ btScalar rel_vel = cp.m_normalWorldOnB.dot(vel);
+
+
+
+ solverConstraint.m_friction = cp.m_combinedFriction;
+
+
+ restitution = restitutionCurve(rel_vel, cp.m_combinedRestitution, infoGlobal.m_restitutionVelocityThreshold);
+ if (restitution <= btScalar(0.))
+ {
+ restitution = 0.f;
+ };
+ }
+
+
+ ///warm starting (or zero if disabled)
+ if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
+ {
+ solverConstraint.m_appliedImpulse = cp.m_appliedImpulse * infoGlobal.m_warmstartingFactor;
+ if (rb0)
+ bodyA->internalApplyImpulse(solverConstraint.m_contactNormal1*bodyA->internalGetInvMass()*rb0->getLinearFactor(),solverConstraint.m_angularComponentA,solverConstraint.m_appliedImpulse);
+ 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;
+
+ {
+
+ btVector3 externalForceImpulseA = bodyA->m_originalBody ? bodyA->m_externalForceImpulse: btVector3(0,0,0);
+ btVector3 externalTorqueImpulseA = bodyA->m_originalBody ? bodyA->m_externalTorqueImpulse: btVector3(0,0,0);
+ btVector3 externalForceImpulseB = bodyB->m_originalBody ? bodyB->m_externalForceImpulse: btVector3(0,0,0);
+ btVector3 externalTorqueImpulseB = bodyB->m_originalBody ?bodyB->m_externalTorqueImpulse : btVector3(0,0,0);
+
+
+ btScalar vel1Dotn = solverConstraint.m_contactNormal1.dot(bodyA->m_linearVelocity+externalForceImpulseA)
+ + solverConstraint.m_relpos1CrossNormal.dot(bodyA->m_angularVelocity+externalTorqueImpulseA);
+ btScalar vel2Dotn = solverConstraint.m_contactNormal2.dot(bodyB->m_linearVelocity+externalForceImpulseB)
+ + solverConstraint.m_relpos2CrossNormal.dot(bodyB->m_angularVelocity+externalTorqueImpulseB);
+ btScalar rel_vel = vel1Dotn+vel2Dotn;
+
+ btScalar positionalError = 0.f;
+ btScalar velocityError = restitution - rel_vel;// * damping;
+
+
+
+ if (penetration>0)
+ {
+ positionalError = 0;
+
+ velocityError -= penetration *invTimeStep;
+ } else
+ {
+ positionalError = -penetration * erp*invTimeStep;
+
+ }
+
+ btScalar penetrationImpulse = positionalError*solverConstraint.m_jacDiagABInv;
+ btScalar velocityImpulse = velocityError *solverConstraint.m_jacDiagABInv;
+
+ if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold))
+ {
+ //combine position and velocity into rhs
+ solverConstraint.m_rhs = penetrationImpulse+velocityImpulse;//-solverConstraint.m_contactNormal1.dot(bodyA->m_externalForce*bodyA->m_invMass-bodyB->m_externalForce/bodyB->m_invMass)*solverConstraint.m_jacDiagABInv;
+ solverConstraint.m_rhsPenetration = 0.f;
+
+ } else
+ {
+ //split position and velocity into rhs and m_rhsPenetration
+ solverConstraint.m_rhs = velocityImpulse;
+ solverConstraint.m_rhsPenetration = penetrationImpulse;
+ }
+ solverConstraint.m_cfm = cfm*solverConstraint.m_jacDiagABInv;
+ solverConstraint.m_lowerLimit = 0;
+ solverConstraint.m_upperLimit = 1e10f;
+ }
+
+
+
+
+}
+
+
+
+void btSequentialImpulseConstraintSolver::setFrictionConstraintImpulse( btSolverConstraint& solverConstraint,
+ int solverBodyIdA, int solverBodyIdB,
+ btManifoldPoint& cp, const btContactSolverInfo& infoGlobal)
+{
+
+ btSolverBody* bodyA = &m_tmpSolverBodyPool[solverBodyIdA];
+ btSolverBody* bodyB = &m_tmpSolverBodyPool[solverBodyIdB];
+
+ btRigidBody* rb0 = bodyA->m_originalBody;
+ btRigidBody* rb1 = bodyB->m_originalBody;
+
+ {
+ btSolverConstraint& frictionConstraint1 = m_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()*rb0->getLinearFactor(),frictionConstraint1.m_angularComponentA,frictionConstraint1.m_appliedImpulse);
+ if (rb1)
+ bodyB->internalApplyImpulse(-frictionConstraint1.m_contactNormal2*rb1->getInvMass()*rb1->getLinearFactor(),-frictionConstraint1.m_angularComponentB,-(btScalar)frictionConstraint1.m_appliedImpulse);
+ } else
+ {
+ frictionConstraint1.m_appliedImpulse = 0.f;
+ }
+ }
+
+ if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
+ {
+ btSolverConstraint& frictionConstraint2 = m_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;
+ }
+ }
+}
+
+
+
+
+void btSequentialImpulseConstraintSolver::convertContact(btPersistentManifold* manifold,const btContactSolverInfo& infoGlobal)
+{
+ btCollisionObject* colObj0=0,*colObj1=0;
+
+ colObj0 = (btCollisionObject*)manifold->getBody0();
+ colObj1 = (btCollisionObject*)manifold->getBody1();
+
+ 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 = &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())))
+ return;
+
+ int rollingFriction=1;
+ for (int j=0;j<manifold->getNumContacts();j++)
+ {
+
+ btManifoldPoint& cp = manifold->getContactPoint(j);
+
+ if (cp.getDistance() <= manifold->getContactProcessingThreshold())
+ {
+ btVector3 rel_pos1;
+ btVector3 rel_pos2;
+ btScalar relaxation;
+
+
+ int frictionIndex = m_tmpSolverContactConstraintPool.size();
+ btSolverConstraint& solverConstraint = m_tmpSolverContactConstraintPool.expandNonInitializing();
+ solverConstraint.m_solverBodyIdA = solverBodyIdA;
+ solverConstraint.m_solverBodyIdB = solverBodyIdB;
+
+ solverConstraint.m_originalContactPoint = &cp;
+
+ const btVector3& pos1 = cp.getPositionWorldOnA();
+ const btVector3& pos2 = cp.getPositionWorldOnB();
+
+ rel_pos1 = pos1 - colObj0->getWorldTransform().getOrigin();
+ rel_pos2 = pos2 - colObj1->getWorldTransform().getOrigin();
+
+ btVector3 vel1;
+ btVector3 vel2;
+
+ solverBodyA->getVelocityInLocalPointNoDelta(rel_pos1,vel1);
+ solverBodyB->getVelocityInLocalPointNoDelta(rel_pos2,vel2 );
+
+ btVector3 vel = vel1 - vel2;
+ btScalar rel_vel = cp.m_normalWorldOnB.dot(vel);
+
+ setupContactConstraint(solverConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal, relaxation, rel_pos1, rel_pos2);
+
+
+
+
+ /////setup the friction constraints
+
+ solverConstraint.m_frictionIndex = m_tmpSolverContactFrictionConstraintPool.size();
+
+ if ((cp.m_combinedRollingFriction>0.f) && (rollingFriction>0))
+ {
+
+ {
+ 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();
+ axis1.normalize();
+
+ applyAnisotropicFriction(colObj0,axis0,btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
+ applyAnisotropicFriction(colObj1,axis0,btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
+ applyAnisotropicFriction(colObj0,axis1,btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
+ applyAnisotropicFriction(colObj1,axis1,btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
+ if (axis0.length()>0.001)
+ addTorsionalFrictionConstraint(axis0,solverBodyIdA,solverBodyIdB,frictionIndex,cp,
+ cp.m_combinedRollingFriction, rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
+ if (axis1.length()>0.001)
+ 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
+ ///based on the relative linear velocity.
+ ///If the relative velocity it zero, it will automatically compute a friction direction.
+
+ ///You can also enable two friction directions, using the SOLVER_USE_2_FRICTION_DIRECTIONS.
+ ///In that case, the second friction direction will be orthogonal to both contact normal and first friction direction.
+ ///
+ ///If you choose SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION, then the friction will be independent from the relative projected velocity.
+ ///
+ ///The user can manually override the friction directions for certain contacts using a contact callback,
+ ///and set the cp.m_lateralFrictionInitialized to true
+ ///In that case, you can set the target relative motion in each friction direction (cp.m_contactMotion1 and cp.m_contactMotion2)
+ ///this will give a conveyor belt effect
+ ///
+
+ if (!(infoGlobal.m_solverMode & SOLVER_ENABLE_FRICTION_DIRECTION_CACHING) || !(cp.m_contactPointFlags&BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED))
+ {
+ cp.m_lateralFrictionDir1 = vel - cp.m_normalWorldOnB * rel_vel;
+ btScalar lat_rel_vel = cp.m_lateralFrictionDir1.length2();
+ if (!(infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION) && lat_rel_vel > SIMD_EPSILON)
+ {
+ 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);
+ 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))
+ {
+ cp.m_lateralFrictionDir2 = cp.m_lateralFrictionDir1.cross(cp.m_normalWorldOnB);
+ cp.m_lateralFrictionDir2.normalize();//??
+ applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir2,btCollisionObject::CF_ANISOTROPIC_FRICTION);
+ applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir2,btCollisionObject::CF_ANISOTROPIC_FRICTION);
+ addFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation, infoGlobal);
+ }
+
+ } else
+ {
+ btPlaneSpace1(cp.m_normalWorldOnB,cp.m_lateralFrictionDir1,cp.m_lateralFrictionDir2);
+
+ applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir1,btCollisionObject::CF_ANISOTROPIC_FRICTION);
+ applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir1,btCollisionObject::CF_ANISOTROPIC_FRICTION);
+ 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);
+ 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))
+ {
+ cp.m_contactPointFlags|=BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED;
+ }
+ }
+
+ } else
+ {
+ 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))
+ 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);
+
+
+
+
+ }
+ }
+}
+
+void btSequentialImpulseConstraintSolver::convertContacts(btPersistentManifold** manifoldPtr,int numManifolds, const btContactSolverInfo& infoGlobal)
+{
+ int i;
+ btPersistentManifold* manifold = 0;
+// btCollisionObject* colObj0=0,*colObj1=0;
+
+
+ for (i=0;i<numManifolds;i++)
+ {
+ manifold = manifoldPtr[i];
+ convertContact(manifold,infoGlobal);
+ }
+}
+
+btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer)
+{
+ m_fixedBodyId = -1;
+ BT_PROFILE("solveGroupCacheFriendlySetup");
+ (void)debugDrawer;
+
+ // if solver mode has changed,
+ if ( infoGlobal.m_solverMode != m_cachedSolverMode )
+ {
+ // update solver functions to use SIMD or non-SIMD
+ bool useSimd = !!( infoGlobal.m_solverMode & SOLVER_SIMD );
+ setupSolverFunctions( useSimd );
+ m_cachedSolverMode = infoGlobal.m_solverMode;
+ }
+ m_maxOverrideNumSolverIterations = 0;
+
+#ifdef BT_ADDITIONAL_DEBUG
+ //make sure that dynamic bodies exist for all (enabled) constraints
+ for (int i=0;i<numConstraints;i++)
+ {
+ btTypedConstraint* constraint = constraints[i];
+ if (constraint->isEnabled())
+ {
+ if (!constraint->getRigidBodyA().isStaticOrKinematicObject())
+ {
+ bool found=false;
+ for (int b=0;b<numBodies;b++)
+ {
+
+ if (&constraint->getRigidBodyA()==bodies[b])
+ {
+ found = true;
+ break;
+ }
+ }
+ btAssert(found);
+ }
+ if (!constraint->getRigidBodyB().isStaticOrKinematicObject())
+ {
+ bool found=false;
+ for (int b=0;b<numBodies;b++)
+ {
+ if (&constraint->getRigidBodyB()==bodies[b])
+ {
+ found = true;
+ break;
+ }
+ }
+ btAssert(found);
+ }
+ }
+ }
+ //make sure that dynamic bodies exist for all contact manifolds
+ for (int i=0;i<numManifolds;i++)
+ {
+ if (!manifoldPtr[i]->getBody0()->isStaticOrKinematicObject())
+ {
+ bool found=false;
+ for (int b=0;b<numBodies;b++)
+ {
+
+ if (manifoldPtr[i]->getBody0()==bodies[b])
+ {
+ found = true;
+ break;
+ }
+ }
+ btAssert(found);
+ }
+ if (!manifoldPtr[i]->getBody1()->isStaticOrKinematicObject())
+ {
+ bool found=false;
+ for (int b=0;b<numBodies;b++)
+ {
+ if (manifoldPtr[i]->getBody1()==bodies[b])
+ {
+ found = true;
+ break;
+ }
+ }
+ btAssert(found);
+ }
+ }
+#endif //BT_ADDITIONAL_DEBUG
+
+
+ for (int i = 0; i < numBodies; i++)
+ {
+ bodies[i]->setCompanionId(-1);
+ }
+#if BT_THREADSAFE
+ m_kinematicBodyUniqueIdToSolverBodyTable.resize( 0 );
+#endif // BT_THREADSAFE
+
+ m_tmpSolverBodyPool.reserve(numBodies+1);
+ m_tmpSolverBodyPool.resize(0);
+
+ //btSolverBody& fixedBody = m_tmpSolverBodyPool.expand();
+ //initSolverBody(&fixedBody,0);
+
+ //convert all bodies
+
+
+ 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];
+ btVector3 gyroForce (0,0,0);
+ if (body->getFlags()&BT_ENABLE_GYROSCOPIC_FORCE_EXPLICIT)
+ {
+ gyroForce = body->computeGyroscopicForceExplicit(infoGlobal.m_maxGyroscopicForce);
+ solverBody.m_externalTorqueImpulse -= gyroForce*body->getInvInertiaTensorWorld()*infoGlobal.m_timeStep;
+ }
+ if (body->getFlags()&BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_WORLD)
+ {
+ gyroForce = body->computeGyroscopicImpulseImplicit_World(infoGlobal.m_timeStep);
+ solverBody.m_externalTorqueImpulse += gyroForce;
+ }
+ if (body->getFlags()&BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_BODY)
+ {
+ gyroForce = body->computeGyroscopicImpulseImplicit_Body(infoGlobal.m_timeStep);
+ solverBody.m_externalTorqueImpulse += gyroForce;
+
+ }
+
+
+ }
+ }
+
+ if (1)
+ {
+ int j;
+ for (j=0;j<numConstraints;j++)
+ {
+ btTypedConstraint* constraint = constraints[j];
+ constraint->buildJacobian();
+ constraint->internalSetAppliedImpulse(0.0f);
+ }
+ }
+
+ //btRigidBody* rb0=0,*rb1=0;
+
+ //if (1)
+ {
+ {
+
+ int totalNumRows = 0;
+ int i;
+
+ m_tmpConstraintSizesPool.resizeNoInitialize(numConstraints);
+ //calculate the total number of contraint rows
+ for (i=0;i<numConstraints;i++)
+ {
+ btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[i];
+ btJointFeedback* fb = constraints[i]->getJointFeedback();
+ if (fb)
+ {
+ fb->m_appliedForceBodyA.setZero();
+ fb->m_appliedTorqueBodyA.setZero();
+ fb->m_appliedForceBodyB.setZero();
+ fb->m_appliedTorqueBodyB.setZero();
+ }
+
+ if (constraints[i]->isEnabled())
+ {
+ }
+ if (constraints[i]->isEnabled())
+ {
+ constraints[i]->getInfo1(&info1);
+ } else
+ {
+ info1.m_numConstraintRows = 0;
+ info1.nub = 0;
+ }
+ totalNumRows += info1.m_numConstraintRows;
+ }
+ m_tmpSolverNonContactConstraintPool.resizeNoInitialize(totalNumRows);
+
+
+ ///setup the btSolverConstraints
+ int currentRow = 0;
+
+ for (i=0;i<numConstraints;i++)
+ {
+ const btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[i];
+
+ if (info1.m_numConstraintRows)
+ {
+ btAssert(currentRow<totalNumRows);
+
+ btSolverConstraint* currentConstraintRow = &m_tmpSolverNonContactConstraintPool[currentRow];
+ btTypedConstraint* constraint = constraints[i];
+ btRigidBody& rbA = constraint->getRigidBodyA();
+ btRigidBody& rbB = constraint->getRigidBodyB();
+
+ int solverBodyIdA = getOrInitSolverBody(rbA,infoGlobal.m_timeStep);
+ int solverBodyIdB = getOrInitSolverBody(rbB,infoGlobal.m_timeStep);
+
+ btSolverBody* bodyAPtr = &m_tmpSolverBodyPool[solverBodyIdA];
+ btSolverBody* bodyBPtr = &m_tmpSolverBodyPool[solverBodyIdB];
+
+
+
+
+ int overrideNumSolverIterations = constraint->getOverrideNumSolverIterations() > 0 ? constraint->getOverrideNumSolverIterations() : infoGlobal.m_numIterations;
+ if (overrideNumSolverIterations>m_maxOverrideNumSolverIterations)
+ m_maxOverrideNumSolverIterations = overrideNumSolverIterations;
+
+
+ int j;
+ for ( j=0;j<info1.m_numConstraintRows;j++)
+ {
+ memset(&currentConstraintRow[j],0,sizeof(btSolverConstraint));
+ currentConstraintRow[j].m_lowerLimit = -SIMD_INFINITY;
+ currentConstraintRow[j].m_upperLimit = SIMD_INFINITY;
+ currentConstraintRow[j].m_appliedImpulse = 0.f;
+ currentConstraintRow[j].m_appliedPushImpulse = 0.f;
+ currentConstraintRow[j].m_solverBodyIdA = solverBodyIdA;
+ currentConstraintRow[j].m_solverBodyIdB = solverBodyIdB;
+ currentConstraintRow[j].m_overrideNumSolverIterations = overrideNumSolverIterations;
+ }
+
+ bodyAPtr->internalGetDeltaLinearVelocity().setValue(0.f,0.f,0.f);
+ bodyAPtr->internalGetDeltaAngularVelocity().setValue(0.f,0.f,0.f);
+ bodyAPtr->internalGetPushVelocity().setValue(0.f,0.f,0.f);
+ bodyAPtr->internalGetTurnVelocity().setValue(0.f,0.f,0.f);
+ bodyBPtr->internalGetDeltaLinearVelocity().setValue(0.f,0.f,0.f);
+ bodyBPtr->internalGetDeltaAngularVelocity().setValue(0.f,0.f,0.f);
+ bodyBPtr->internalGetPushVelocity().setValue(0.f,0.f,0.f);
+ bodyBPtr->internalGetTurnVelocity().setValue(0.f,0.f,0.f);
+
+
+ btTypedConstraint::btConstraintInfo2 info2;
+ info2.fps = 1.f/infoGlobal.m_timeStep;
+ info2.erp = infoGlobal.m_erp;
+ info2.m_J1linearAxis = currentConstraintRow->m_contactNormal1;
+ info2.m_J1angularAxis = currentConstraintRow->m_relpos1CrossNormal;
+ info2.m_J2linearAxis = currentConstraintRow->m_contactNormal2;
+ info2.m_J2angularAxis = currentConstraintRow->m_relpos2CrossNormal;
+ info2.rowskip = sizeof(btSolverConstraint)/sizeof(btScalar);//check this
+ ///the size of btSolverConstraint needs be a multiple of btScalar
+ btAssert(info2.rowskip*sizeof(btScalar)== sizeof(btSolverConstraint));
+ info2.m_constraintError = &currentConstraintRow->m_rhs;
+ currentConstraintRow->m_cfm = infoGlobal.m_globalCfm;
+ info2.m_damping = infoGlobal.m_damping;
+ info2.cfm = &currentConstraintRow->m_cfm;
+ info2.m_lowerLimit = &currentConstraintRow->m_lowerLimit;
+ info2.m_upperLimit = &currentConstraintRow->m_upperLimit;
+ info2.m_numIterations = infoGlobal.m_numIterations;
+ constraints[i]->getInfo2(&info2);
+
+ ///finalize the constraint setup
+ for ( j=0;j<info1.m_numConstraintRows;j++)
+ {
+ btSolverConstraint& solverConstraint = currentConstraintRow[j];
+
+ if (solverConstraint.m_upperLimit>=constraints[i]->getBreakingImpulseThreshold())
+ {
+ solverConstraint.m_upperLimit = constraints[i]->getBreakingImpulseThreshold();
+ }
+
+ if (solverConstraint.m_lowerLimit<=-constraints[i]->getBreakingImpulseThreshold())
+ {
+ solverConstraint.m_lowerLimit = -constraints[i]->getBreakingImpulseThreshold();
+ }
+
+ solverConstraint.m_originalContactPoint = constraint;
+
+ {
+ const btVector3& ftorqueAxis1 = solverConstraint.m_relpos1CrossNormal;
+ solverConstraint.m_angularComponentA = constraint->getRigidBodyA().getInvInertiaTensorWorld()*ftorqueAxis1*constraint->getRigidBodyA().getAngularFactor();
+ }
+ {
+ const btVector3& ftorqueAxis2 = solverConstraint.m_relpos2CrossNormal;
+ solverConstraint.m_angularComponentB = constraint->getRigidBodyB().getInvInertiaTensorWorld()*ftorqueAxis2*constraint->getRigidBodyB().getAngularFactor();
+ }
+
+ {
+ btVector3 iMJlA = solverConstraint.m_contactNormal1*rbA.getInvMass();
+ btVector3 iMJaA = rbA.getInvInertiaTensorWorld()*solverConstraint.m_relpos1CrossNormal;
+ btVector3 iMJlB = solverConstraint.m_contactNormal2*rbB.getInvMass();//sign of normal?
+ btVector3 iMJaB = rbB.getInvInertiaTensorWorld()*solverConstraint.m_relpos2CrossNormal;
+
+ btScalar sum = iMJlA.dot(solverConstraint.m_contactNormal1);
+ sum += iMJaA.dot(solverConstraint.m_relpos1CrossNormal);
+ sum += iMJlB.dot(solverConstraint.m_contactNormal2);
+ sum += iMJaB.dot(solverConstraint.m_relpos2CrossNormal);
+ btScalar fsum = btFabs(sum);
+ btAssert(fsum > SIMD_EPSILON);
+ btScalar sorRelaxation = 1.f;//todo: get from globalInfo?
+ solverConstraint.m_jacDiagABInv = fsum>SIMD_EPSILON?sorRelaxation/sum : 0.f;
+ }
+
+
+
+ {
+ btScalar rel_vel;
+ btVector3 externalForceImpulseA = bodyAPtr->m_originalBody ? bodyAPtr->m_externalForceImpulse : btVector3(0,0,0);
+ btVector3 externalTorqueImpulseA = bodyAPtr->m_originalBody ? bodyAPtr->m_externalTorqueImpulse : btVector3(0,0,0);
+
+ btVector3 externalForceImpulseB = bodyBPtr->m_originalBody ? bodyBPtr->m_externalForceImpulse : btVector3(0,0,0);
+ btVector3 externalTorqueImpulseB = bodyBPtr->m_originalBody ?bodyBPtr->m_externalTorqueImpulse : btVector3(0,0,0);
+
+ btScalar vel1Dotn = solverConstraint.m_contactNormal1.dot(rbA.getLinearVelocity()+externalForceImpulseA)
+ + solverConstraint.m_relpos1CrossNormal.dot(rbA.getAngularVelocity()+externalTorqueImpulseA);
+
+ btScalar vel2Dotn = solverConstraint.m_contactNormal2.dot(rbB.getLinearVelocity()+externalForceImpulseB)
+ + solverConstraint.m_relpos2CrossNormal.dot(rbB.getAngularVelocity()+externalTorqueImpulseB);
+
+ rel_vel = vel1Dotn+vel2Dotn;
+ btScalar restitution = 0.f;
+ btScalar positionalError = solverConstraint.m_rhs;//already filled in by getConstraintInfo2
+ btScalar velocityError = restitution - rel_vel * info2.m_damping;
+ btScalar penetrationImpulse = positionalError*solverConstraint.m_jacDiagABInv;
+ btScalar velocityImpulse = velocityError *solverConstraint.m_jacDiagABInv;
+ solverConstraint.m_rhs = penetrationImpulse+velocityImpulse;
+ solverConstraint.m_appliedImpulse = 0.f;
+
+
+ }
+ }
+ }
+ currentRow+=m_tmpConstraintSizesPool[i].m_numConstraintRows;
+ }
+ }
+
+ convertContacts(manifoldPtr,numManifolds,infoGlobal);
+
+ }
+
+// btContactSolverInfo info = infoGlobal;
+
+
+ int numNonContactPool = m_tmpSolverNonContactConstraintPool.size();
+ int numConstraintPool = m_tmpSolverContactConstraintPool.size();
+ int numFrictionPool = m_tmpSolverContactFrictionConstraintPool.size();
+
+ ///@todo: use stack allocator for such temporarily memory, same for solver bodies/constraints
+ m_orderNonContactConstraintPool.resizeNoInitialize(numNonContactPool);
+ if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
+ m_orderTmpConstraintPool.resizeNoInitialize(numConstraintPool*2);
+ else
+ m_orderTmpConstraintPool.resizeNoInitialize(numConstraintPool);
+
+ m_orderFrictionConstraintPool.resizeNoInitialize(numFrictionPool);
+ {
+ int i;
+ for (i=0;i<numNonContactPool;i++)
+ {
+ m_orderNonContactConstraintPool[i] = i;
+ }
+ for (i=0;i<numConstraintPool;i++)
+ {
+ m_orderTmpConstraintPool[i] = i;
+ }
+ for (i=0;i<numFrictionPool;i++)
+ {
+ m_orderFrictionConstraintPool[i] = i;
+ }
+ }
+
+ return 0.f;
+
+}
+
+
+btScalar btSequentialImpulseConstraintSolver::solveSingleIteration(int iteration, btCollisionObject** /*bodies */,int /*numBodies*/,btPersistentManifold** /*manifoldPtr*/, int /*numManifolds*/,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* /*debugDrawer*/)
+{
+ btScalar leastSquaresResidual = 0.f;
+
+ int numNonContactPool = m_tmpSolverNonContactConstraintPool.size();
+ int numConstraintPool = m_tmpSolverContactConstraintPool.size();
+ int numFrictionPool = m_tmpSolverContactFrictionConstraintPool.size();
+
+ if (infoGlobal.m_solverMode & SOLVER_RANDMIZE_ORDER)
+ {
+ if (1) // uncomment this for a bit less random ((iteration & 7) == 0)
+ {
+
+ for (int j=0; j<numNonContactPool; ++j) {
+ 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
+ if (iteration< infoGlobal.m_numIterations)
+ {
+ for (int j=0; j<numConstraintPool; ++j) {
+ 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 = 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<m_tmpSolverNonContactConstraintPool.size();j++)
+ {
+ btSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[m_orderNonContactConstraintPool[j]];
+ if (iteration < constraint.m_overrideNumSolverIterations)
+ {
+ btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[constraint.m_solverBodyIdA],m_tmpSolverBodyPool[constraint.m_solverBodyIdB],constraint);
+ leastSquaresResidual += residual*residual;
+ }
+ }
+
+ if (iteration< infoGlobal.m_numIterations)
+ {
+ for (int j=0;j<numConstraints;j++)
+ {
+ if (constraints[j]->isEnabled())
+ {
+ 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);
+ }
+ }
+
+ ///solve all contact constraints
+ if (infoGlobal.m_solverMode & SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS)
+ {
+ int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
+ int multiplier = (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)? 2 : 1;
+
+ for (int c=0;c<numPoolConstraints;c++)
+ {
+ btScalar totalImpulse =0;
+
+ {
+ const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[c]];
+ btScalar residual = resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
+ leastSquaresResidual += residual*residual;
+
+ totalImpulse = solveManifold.m_appliedImpulse;
+ }
+ bool applyFriction = true;
+ if (applyFriction)
+ {
+ {
+
+ 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 = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
+ leastSquaresResidual += residual*residual;
+ }
+ }
+
+ if (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)
+ {
+
+ 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 = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
+ leastSquaresResidual += residual*residual;
+ }
+ }
+ }
+ }
+
+ }
+ else//SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS
+ {
+ //solve the friction constraints after all contact constraints, don't interleave them
+ int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
+ int j;
+
+ for (j=0;j<numPoolConstraints;j++)
+ {
+ const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
+ btScalar residual = resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
+ leastSquaresResidual += residual*residual;
+ }
+
+
+
+ ///solve all friction constraints
+
+ int numFrictionPoolConstraints = m_tmpSolverContactFrictionConstraintPool.size();
+ for (j=0;j<numFrictionPoolConstraints;j++)
+ {
+ 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 = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
+ leastSquaresResidual += residual*residual;
+ }
+ }
+ }
+
+
+ int numRollingFrictionPoolConstraints = m_tmpSolverContactRollingFrictionConstraintPool.size();
+ for (int j=0;j<numRollingFrictionPoolConstraints;j++)
+ {
+
+ btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[j];
+ btScalar totalImpulse = m_tmpSolverContactConstraintPool[rollingFrictionConstraint.m_frictionIndex].m_appliedImpulse;
+ if (totalImpulse>btScalar(0))
+ {
+ btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction*totalImpulse;
+ if (rollingFrictionMagnitude>rollingFrictionConstraint.m_friction)
+ rollingFrictionMagnitude = rollingFrictionConstraint.m_friction;
+
+ rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude;
+ rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude;
+
+ btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA],m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB],rollingFrictionConstraint);
+ leastSquaresResidual += residual*residual;
+ }
+ }
+
+
+ }
+ return leastSquaresResidual;
+}
+
+
+void btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySplitImpulseIterations(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer)
+{
+ int iteration;
+ if (infoGlobal.m_splitImpulse)
+ {
+ {
+ 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 += 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;
+ }
+ }
+ }
+ }
+}
+
+btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyIterations(btCollisionObject** bodies ,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer)
+{
+ BT_PROFILE("solveGroupCacheFriendlyIterations");
+
+ {
+ ///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++)
+ //for ( int iteration = maxIterations-1 ; iteration >= 0;iteration--)
+ {
+ m_leastSquaresResidual = solveSingleIteration(iteration, bodies ,numBodies,manifoldPtr, numManifolds,constraints,numConstraints,infoGlobal,debugDrawer);
+
+ if (m_leastSquaresResidual <= infoGlobal.m_leastSquaresResidualThreshold || (iteration>= (maxIterations-1)))
+ {
+#ifdef VERBOSE_RESIDUAL_PRINTF
+ printf("residual = %f at iteration #%d\n",m_leastSquaresResidual,iteration);
+#endif
+ break;
+ }
+ }
+
+ }
+ return 0.f;
+}
+
+btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyFinish(btCollisionObject** bodies,int numBodies,const btContactSolverInfo& infoGlobal)
+{
+ int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
+ int i,j;
+
+ if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
+ {
+ for (j=0;j<numPoolConstraints;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 = 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 = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex+1].m_appliedImpulse;
+ }
+ //do a callback here?
+ }
+ }
+
+ numPoolConstraints = m_tmpSolverNonContactConstraintPool.size();
+ for (j=0;j<numPoolConstraints;j++)
+ {
+ const btSolverConstraint& solverConstr = m_tmpSolverNonContactConstraintPool[j];
+ btTypedConstraint* constr = (btTypedConstraint*)solverConstr.m_originalContactPoint;
+ btJointFeedback* fb = constr->getJointFeedback();
+ if (fb)
+ {
+ fb->m_appliedForceBodyA += solverConstr.m_contactNormal1*solverConstr.m_appliedImpulse*constr->getRigidBodyA().getLinearFactor()/infoGlobal.m_timeStep;
+ fb->m_appliedForceBodyB += solverConstr.m_contactNormal2*solverConstr.m_appliedImpulse*constr->getRigidBodyB().getLinearFactor()/infoGlobal.m_timeStep;
+ fb->m_appliedTorqueBodyA += solverConstr.m_relpos1CrossNormal* constr->getRigidBodyA().getAngularFactor()*solverConstr.m_appliedImpulse/infoGlobal.m_timeStep;
+ fb->m_appliedTorqueBodyB += solverConstr.m_relpos2CrossNormal* constr->getRigidBodyB().getAngularFactor()*solverConstr.m_appliedImpulse/infoGlobal.m_timeStep; /*RGM ???? */
+
+ }
+
+ constr->internalSetAppliedImpulse(solverConstr.m_appliedImpulse);
+ if (btFabs(solverConstr.m_appliedImpulse)>=constr->getBreakingImpulseThreshold())
+ {
+ constr->setEnabled(false);
+ }
+ }
+
+
+
+ for ( i=0;i<m_tmpSolverBodyPool.size();i++)
+ {
+ btRigidBody* body = m_tmpSolverBodyPool[i].m_originalBody;
+ if (body)
+ {
+ if (infoGlobal.m_splitImpulse)
+ m_tmpSolverBodyPool[i].writebackVelocityAndTransform(infoGlobal.m_timeStep, infoGlobal.m_splitImpulseTurnErp);
+ else
+ m_tmpSolverBodyPool[i].writebackVelocity();
+
+ m_tmpSolverBodyPool[i].m_originalBody->setLinearVelocity(
+ m_tmpSolverBodyPool[i].m_linearVelocity+
+ m_tmpSolverBodyPool[i].m_externalForceImpulse);
+
+ m_tmpSolverBodyPool[i].m_originalBody->setAngularVelocity(
+ m_tmpSolverBodyPool[i].m_angularVelocity+
+ m_tmpSolverBodyPool[i].m_externalTorqueImpulse);
+
+ if (infoGlobal.m_splitImpulse)
+ m_tmpSolverBodyPool[i].m_originalBody->setWorldTransform(m_tmpSolverBodyPool[i].m_worldTransform);
+
+ m_tmpSolverBodyPool[i].m_originalBody->setCompanionId(-1);
+ }
+ }
+
+ m_tmpSolverContactConstraintPool.resizeNoInitialize(0);
+ m_tmpSolverNonContactConstraintPool.resizeNoInitialize(0);
+ m_tmpSolverContactFrictionConstraintPool.resizeNoInitialize(0);
+ m_tmpSolverContactRollingFrictionConstraintPool.resizeNoInitialize(0);
+
+ m_tmpSolverBodyPool.resizeNoInitialize(0);
+ return 0.f;
+}
+
+
+
+/// 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*/)
+{
+
+ BT_PROFILE("solveGroup");
+ //you need to provide at least some bodies
+
+ solveGroupCacheFriendlySetup( bodies, numBodies, manifoldPtr, numManifolds,constraints, numConstraints,infoGlobal,debugDrawer);
+
+ solveGroupCacheFriendlyIterations(bodies, numBodies, manifoldPtr, numManifolds,constraints, numConstraints,infoGlobal,debugDrawer);
+
+ solveGroupCacheFriendlyFinish(bodies, numBodies, infoGlobal);
+
+ return 0.f;
+}
+
+void btSequentialImpulseConstraintSolver::reset()
+{
+ m_btSeed2 = 0;
+}
diff --git a/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h
new file mode 100644
index 0000000000..16c7eb74c1
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h
@@ -0,0 +1,196 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_SEQUENTIAL_IMPULSE_CONSTRAINT_SOLVER_H
+#define BT_SEQUENTIAL_IMPULSE_CONSTRAINT_SOLVER_H
+
+class btIDebugDraw;
+class btPersistentManifold;
+class btDispatcher;
+class btCollisionObject;
+#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h"
+#include "BulletDynamics/ConstraintSolver/btSolverBody.h"
+#include "BulletDynamics/ConstraintSolver/btSolverConstraint.h"
+#include "BulletCollision/NarrowPhaseCollision/btManifoldPoint.h"
+#include "BulletDynamics/ConstraintSolver/btConstraintSolver.h"
+
+typedef btSimdScalar(*btSingleConstraintRowSolver)(btSolverBody&, btSolverBody&, const btSolverConstraint&);
+
+///The btSequentialImpulseConstraintSolver is a fast SIMD implementation of the Projected Gauss Seidel (iterative LCP) method.
+ATTRIBUTE_ALIGNED16(class) btSequentialImpulseConstraintSolver : public btConstraintSolver
+{
+protected:
+ 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;
+ int m_maxOverrideNumSolverIterations;
+ int m_fixedBodyId;
+ // When running solvers on multiple threads, a race condition exists for Kinematic objects that
+ // participate in more than one solver.
+ // The getOrInitSolverBody() function writes the companionId of each body (storing the index of the solver body
+ // for the current solver). For normal dynamic bodies it isn't an issue because they can only be in one island
+ // (and therefore one thread) at a time. But kinematic bodies can be in multiple islands at once.
+ // To avoid this race condition, this solver does not write the companionId, instead it stores the solver body
+ // index in this solver-local table, indexed by the uniqueId of the body.
+ btAlignedObjectArray<int> m_kinematicBodyUniqueIdToSolverBodyTable; // only used for multithreading
+
+ btSingleConstraintRowSolver m_resolveSingleConstraintRowGeneric;
+ btSingleConstraintRowSolver m_resolveSingleConstraintRowLowerLimit;
+ btSingleConstraintRowSolver m_resolveSplitPenetrationImpulse;
+ int m_cachedSolverMode; // used to check if SOLVER_SIMD flag has been changed
+ void setupSolverFunctions( bool useSimd );
+
+ btScalar m_leastSquaresResidual;
+
+ void 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=0., btScalar cfmSlip=0.);
+
+ void setupTorsionalFrictionConstraint( btSolverConstraint& solverConstraint, const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB,
+ btManifoldPoint& cp,btScalar combinedTorsionalFriction, const btVector3& rel_pos1,const btVector3& rel_pos2,
+ btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation,
+ btScalar desiredVelocity=0., btScalar cfmSlip=0.);
+
+ btSolverConstraint& 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=0., btScalar cfmSlip=0.);
+ btSolverConstraint& addTorsionalFrictionConstraint(const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB,int frictionIndex,btManifoldPoint& cp,btScalar torsionalFriction, const btVector3& rel_pos1,const btVector3& rel_pos2,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, btScalar desiredVelocity=0, btScalar cfmSlip=0.f);
+
+
+ void setupContactConstraint(btSolverConstraint& solverConstraint, int solverBodyIdA, int solverBodyIdB, btManifoldPoint& cp,
+ const btContactSolverInfo& infoGlobal,btScalar& relaxation, const btVector3& rel_pos1, const btVector3& rel_pos2);
+
+ static void applyAnisotropicFriction(btCollisionObject* colObj,btVector3& frictionDirection, int frictionMode);
+
+ void setFrictionConstraintImpulse( btSolverConstraint& solverConstraint, int solverBodyIdA,int solverBodyIdB,
+ btManifoldPoint& cp, const btContactSolverInfo& infoGlobal);
+
+ ///m_btSeed2 is used for re-arranging the constraint rows. improves convergence/quality of friction
+ unsigned long m_btSeed2;
+
+
+ btScalar restitutionCurve(btScalar rel_vel, btScalar restitution, btScalar velocityThreshold);
+
+ virtual void convertContacts(btPersistentManifold** manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal);
+
+ void convertContact(btPersistentManifold* manifold,const btContactSolverInfo& infoGlobal);
+
+
+ btSimdScalar resolveSplitPenetrationSIMD(btSolverBody& bodyA,btSolverBody& bodyB, const btSolverConstraint& contactConstraint)
+ {
+ return m_resolveSplitPenetrationImpulse( bodyA, bodyB, contactConstraint );
+ }
+
+ btSimdScalar resolveSplitPenetrationImpulseCacheFriendly(btSolverBody& bodyA,btSolverBody& bodyB, const btSolverConstraint& contactConstraint)
+ {
+ return m_resolveSplitPenetrationImpulse( bodyA, bodyB, contactConstraint );
+ }
+
+ //internal method
+ int getOrInitSolverBody(btCollisionObject& body,btScalar timeStep);
+ void initSolverBody(btSolverBody* solverBody, btCollisionObject* collisionObject, btScalar timeStep);
+
+ btSimdScalar resolveSingleConstraintRowGeneric(btSolverBody& bodyA,btSolverBody& bodyB,const btSolverConstraint& contactConstraint);
+ btSimdScalar resolveSingleConstraintRowGenericSIMD(btSolverBody& bodyA,btSolverBody& bodyB,const btSolverConstraint& contactConstraint);
+ btSimdScalar resolveSingleConstraintRowLowerLimit(btSolverBody& bodyA,btSolverBody& bodyB,const btSolverConstraint& contactConstraint);
+ btSimdScalar resolveSingleConstraintRowLowerLimitSIMD(btSolverBody& bodyA,btSolverBody& bodyB,const btSolverConstraint& contactConstraint);
+ btSimdScalar resolveSplitPenetrationImpulse(btSolverBody& bodyA,btSolverBody& bodyB, const btSolverConstraint& contactConstraint)
+ {
+ return m_resolveSplitPenetrationImpulse( bodyA, bodyB, contactConstraint );
+ }
+
+protected:
+
+
+ virtual void solveGroupCacheFriendlySplitImpulseIterations(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer);
+ 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);
+
+
+public:
+
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ btSequentialImpulseConstraintSolver();
+ virtual ~btSequentialImpulseConstraintSolver();
+
+ virtual btScalar solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& info, btIDebugDraw* debugDrawer,btDispatcher* dispatcher);
+
+ ///clear internal cached data and reset random seed
+ virtual void reset();
+
+ unsigned long btRand2();
+
+ int btRandInt2 (int n);
+
+ void setRandSeed(unsigned long seed)
+ {
+ m_btSeed2 = seed;
+ }
+ unsigned long getRandSeed() const
+ {
+ return m_btSeed2;
+ }
+
+
+ virtual btConstraintSolverType getSolverType() const
+ {
+ return BT_SEQUENTIAL_IMPULSE_SOLVER;
+ }
+
+ btSingleConstraintRowSolver getActiveConstraintRowSolverGeneric()
+ {
+ return m_resolveSingleConstraintRowGeneric;
+ }
+ void setConstraintRowSolverGeneric(btSingleConstraintRowSolver rowSolver)
+ {
+ m_resolveSingleConstraintRowGeneric = rowSolver;
+ }
+ btSingleConstraintRowSolver getActiveConstraintRowSolverLowerLimit()
+ {
+ return m_resolveSingleConstraintRowLowerLimit;
+ }
+ void setConstraintRowSolverLowerLimit(btSingleConstraintRowSolver rowSolver)
+ {
+ m_resolveSingleConstraintRowLowerLimit = rowSolver;
+ }
+
+ ///Various implementations of solving a single constraint row using a generic equality constraint, using scalar reference, SSE2 or SSE4
+ 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
+ btSingleConstraintRowSolver getScalarConstraintRowSolverLowerLimit();
+ btSingleConstraintRowSolver getSSE2ConstraintRowSolverLowerLimit();
+ btSingleConstraintRowSolver getSSE4_1ConstraintRowSolverLowerLimit();
+};
+
+
+
+
+#endif //BT_SEQUENTIAL_IMPULSE_CONSTRAINT_SOLVER_H
+
diff --git a/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp
new file mode 100644
index 0000000000..d63cef0316
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp
@@ -0,0 +1,855 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+/*
+Added by Roman Ponomarev (rponom@gmail.com)
+April 04, 2008
+*/
+
+
+
+#include "btSliderConstraint.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "LinearMath/btTransformUtil.h"
+#include <new>
+
+#define USE_OFFSET_FOR_CONSTANT_FRAME true
+
+void btSliderConstraint::initParams()
+{
+ m_lowerLinLimit = btScalar(1.0);
+ m_upperLinLimit = btScalar(-1.0);
+ m_lowerAngLimit = btScalar(0.);
+ m_upperAngLimit = btScalar(0.);
+ m_softnessDirLin = SLIDER_CONSTRAINT_DEF_SOFTNESS;
+ m_restitutionDirLin = SLIDER_CONSTRAINT_DEF_RESTITUTION;
+ m_dampingDirLin = btScalar(0.);
+ m_cfmDirLin = SLIDER_CONSTRAINT_DEF_CFM;
+ m_softnessDirAng = SLIDER_CONSTRAINT_DEF_SOFTNESS;
+ m_restitutionDirAng = SLIDER_CONSTRAINT_DEF_RESTITUTION;
+ m_dampingDirAng = btScalar(0.);
+ m_cfmDirAng = SLIDER_CONSTRAINT_DEF_CFM;
+ m_softnessOrthoLin = SLIDER_CONSTRAINT_DEF_SOFTNESS;
+ m_restitutionOrthoLin = SLIDER_CONSTRAINT_DEF_RESTITUTION;
+ m_dampingOrthoLin = SLIDER_CONSTRAINT_DEF_DAMPING;
+ m_cfmOrthoLin = SLIDER_CONSTRAINT_DEF_CFM;
+ m_softnessOrthoAng = SLIDER_CONSTRAINT_DEF_SOFTNESS;
+ m_restitutionOrthoAng = SLIDER_CONSTRAINT_DEF_RESTITUTION;
+ m_dampingOrthoAng = SLIDER_CONSTRAINT_DEF_DAMPING;
+ m_cfmOrthoAng = SLIDER_CONSTRAINT_DEF_CFM;
+ m_softnessLimLin = SLIDER_CONSTRAINT_DEF_SOFTNESS;
+ m_restitutionLimLin = SLIDER_CONSTRAINT_DEF_RESTITUTION;
+ m_dampingLimLin = SLIDER_CONSTRAINT_DEF_DAMPING;
+ m_cfmLimLin = SLIDER_CONSTRAINT_DEF_CFM;
+ m_softnessLimAng = SLIDER_CONSTRAINT_DEF_SOFTNESS;
+ m_restitutionLimAng = SLIDER_CONSTRAINT_DEF_RESTITUTION;
+ m_dampingLimAng = SLIDER_CONSTRAINT_DEF_DAMPING;
+ m_cfmLimAng = SLIDER_CONSTRAINT_DEF_CFM;
+
+ m_poweredLinMotor = false;
+ m_targetLinMotorVelocity = btScalar(0.);
+ m_maxLinMotorForce = btScalar(0.);
+ m_accumulatedLinMotorImpulse = btScalar(0.0);
+
+ m_poweredAngMotor = false;
+ m_targetAngMotorVelocity = btScalar(0.);
+ m_maxAngMotorForce = btScalar(0.);
+ m_accumulatedAngMotorImpulse = btScalar(0.0);
+
+ m_flags = 0;
+ m_flags = 0;
+
+ m_useOffsetForConstraintFrame = USE_OFFSET_FOR_CONSTANT_FRAME;
+
+ calculateTransforms(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform());
+}
+
+
+
+
+
+btSliderConstraint::btSliderConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA)
+ : btTypedConstraint(SLIDER_CONSTRAINT_TYPE, rbA, rbB),
+ m_useSolveConstraintObsolete(false),
+ m_frameInA(frameInA),
+ m_frameInB(frameInB),
+ m_useLinearReferenceFrameA(useLinearReferenceFrameA)
+{
+ initParams();
+}
+
+
+
+btSliderConstraint::btSliderConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameA)
+ : btTypedConstraint(SLIDER_CONSTRAINT_TYPE, getFixedBody(), rbB),
+ m_useSolveConstraintObsolete(false),
+ m_frameInB(frameInB),
+ m_useLinearReferenceFrameA(useLinearReferenceFrameA)
+{
+ ///not providing rigidbody A means implicitly using worldspace for body A
+ m_frameInA = rbB.getCenterOfMassTransform() * m_frameInB;
+// m_frameInA.getOrigin() = m_rbA.getCenterOfMassTransform()(m_frameInA.getOrigin());
+
+ initParams();
+}
+
+
+
+
+
+
+void btSliderConstraint::getInfo1(btConstraintInfo1* info)
+{
+ if (m_useSolveConstraintObsolete)
+ {
+ info->m_numConstraintRows = 0;
+ info->nub = 0;
+ }
+ else
+ {
+ info->m_numConstraintRows = 4; // Fixed 2 linear + 2 angular
+ info->nub = 2;
+ //prepare constraint
+ calculateTransforms(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform());
+ testAngLimits();
+ testLinLimits();
+ if(getSolveLinLimit() || getPoweredLinMotor())
+ {
+ info->m_numConstraintRows++; // limit 3rd linear as well
+ info->nub--;
+ }
+ if(getSolveAngLimit() || getPoweredAngMotor())
+ {
+ info->m_numConstraintRows++; // limit 3rd angular as well
+ info->nub--;
+ }
+ }
+}
+
+void btSliderConstraint::getInfo1NonVirtual(btConstraintInfo1* info)
+{
+
+ info->m_numConstraintRows = 6; // Fixed 2 linear + 2 angular + 1 limit (even if not used)
+ info->nub = 0;
+}
+
+void btSliderConstraint::getInfo2(btConstraintInfo2* info)
+{
+ getInfo2NonVirtual(info,m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform(), m_rbA.getLinearVelocity(),m_rbB.getLinearVelocity(), m_rbA.getInvMass(),m_rbB.getInvMass());
+}
+
+
+
+
+
+
+
+void btSliderConstraint::calculateTransforms(const btTransform& transA,const btTransform& transB)
+{
+ if(m_useLinearReferenceFrameA || (!m_useSolveConstraintObsolete))
+ {
+ m_calculatedTransformA = transA * m_frameInA;
+ m_calculatedTransformB = transB * m_frameInB;
+ }
+ else
+ {
+ m_calculatedTransformA = transB * m_frameInB;
+ m_calculatedTransformB = transA * m_frameInA;
+ }
+ m_realPivotAInW = m_calculatedTransformA.getOrigin();
+ m_realPivotBInW = m_calculatedTransformB.getOrigin();
+ m_sliderAxis = m_calculatedTransformA.getBasis().getColumn(0); // along X
+ if(m_useLinearReferenceFrameA || m_useSolveConstraintObsolete)
+ {
+ m_delta = m_realPivotBInW - m_realPivotAInW;
+ }
+ else
+ {
+ m_delta = m_realPivotAInW - m_realPivotBInW;
+ }
+ m_projPivotInW = m_realPivotAInW + m_sliderAxis.dot(m_delta) * m_sliderAxis;
+ btVector3 normalWorld;
+ int i;
+ //linear part
+ for(i = 0; i < 3; i++)
+ {
+ normalWorld = m_calculatedTransformA.getBasis().getColumn(i);
+ m_depth[i] = m_delta.dot(normalWorld);
+ }
+}
+
+
+
+void btSliderConstraint::testLinLimits(void)
+{
+ m_solveLinLim = false;
+ m_linPos = m_depth[0];
+ if(m_lowerLinLimit <= m_upperLinLimit)
+ {
+ if(m_depth[0] > m_upperLinLimit)
+ {
+ m_depth[0] -= m_upperLinLimit;
+ m_solveLinLim = true;
+ }
+ else if(m_depth[0] < m_lowerLinLimit)
+ {
+ m_depth[0] -= m_lowerLinLimit;
+ m_solveLinLim = true;
+ }
+ else
+ {
+ m_depth[0] = btScalar(0.);
+ }
+ }
+ else
+ {
+ m_depth[0] = btScalar(0.);
+ }
+}
+
+
+
+void btSliderConstraint::testAngLimits(void)
+{
+ m_angDepth = btScalar(0.);
+ m_solveAngLim = false;
+ if(m_lowerAngLimit <= m_upperAngLimit)
+ {
+ const btVector3 axisA0 = m_calculatedTransformA.getBasis().getColumn(1);
+ const btVector3 axisA1 = m_calculatedTransformA.getBasis().getColumn(2);
+ const btVector3 axisB0 = m_calculatedTransformB.getBasis().getColumn(1);
+// btScalar rot = btAtan2Fast(axisB0.dot(axisA1), axisB0.dot(axisA0));
+ btScalar rot = btAtan2(axisB0.dot(axisA1), axisB0.dot(axisA0));
+ rot = btAdjustAngleToLimits(rot, m_lowerAngLimit, m_upperAngLimit);
+ m_angPos = rot;
+ if(rot < m_lowerAngLimit)
+ {
+ m_angDepth = rot - m_lowerAngLimit;
+ m_solveAngLim = true;
+ }
+ else if(rot > m_upperAngLimit)
+ {
+ m_angDepth = rot - m_upperAngLimit;
+ m_solveAngLim = true;
+ }
+ }
+}
+
+btVector3 btSliderConstraint::getAncorInA(void)
+{
+ btVector3 ancorInA;
+ ancorInA = m_realPivotAInW + (m_lowerLinLimit + m_upperLinLimit) * btScalar(0.5) * m_sliderAxis;
+ ancorInA = m_rbA.getCenterOfMassTransform().inverse() * ancorInA;
+ return ancorInA;
+}
+
+
+
+btVector3 btSliderConstraint::getAncorInB(void)
+{
+ btVector3 ancorInB;
+ ancorInB = m_frameInB.getOrigin();
+ return ancorInB;
+}
+
+
+void btSliderConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTransform& transA,const btTransform& transB, const btVector3& linVelA,const btVector3& linVelB, btScalar rbAinvMass,btScalar rbBinvMass )
+{
+ const btTransform& trA = getCalculatedTransformA();
+ const btTransform& trB = getCalculatedTransformB();
+
+ btAssert(!m_useSolveConstraintObsolete);
+ int i, s = info->rowskip;
+
+ btScalar signFact = m_useLinearReferenceFrameA ? btScalar(1.0f) : btScalar(-1.0f);
+
+ // difference between frames in WCS
+ btVector3 ofs = trB.getOrigin() - trA.getOrigin();
+ // now get weight factors depending on masses
+ btScalar miA = rbAinvMass;
+ btScalar miB = rbBinvMass;
+ bool hasStaticBody = (miA < SIMD_EPSILON) || (miB < SIMD_EPSILON);
+ btScalar miS = miA + miB;
+ btScalar factA, factB;
+ if(miS > btScalar(0.f))
+ {
+ factA = miB / miS;
+ }
+ else
+ {
+ factA = btScalar(0.5f);
+ }
+ factB = btScalar(1.0f) - factA;
+ btVector3 ax1, p, q;
+ btVector3 ax1A = trA.getBasis().getColumn(0);
+ btVector3 ax1B = trB.getBasis().getColumn(0);
+ if(m_useOffsetForConstraintFrame)
+ {
+ // get the desired direction of slider axis
+ // as weighted sum of X-orthos of frameA and frameB in WCS
+ ax1 = ax1A * factA + ax1B * factB;
+ ax1.normalize();
+ // construct two orthos to slider axis
+ btPlaneSpace1 (ax1, p, q);
+ }
+ else
+ { // old way - use frameA
+ ax1 = trA.getBasis().getColumn(0);
+ // get 2 orthos to slider axis (Y, Z)
+ p = trA.getBasis().getColumn(1);
+ q = trA.getBasis().getColumn(2);
+ }
+ // make rotations around these orthos equal
+ // the slider axis should be the only unconstrained
+ // rotational axis, the angular velocity of the two bodies perpendicular to
+ // the slider axis should be equal. thus the constraint equations are
+ // p*w1 - p*w2 = 0
+ // q*w1 - q*w2 = 0
+ // where p and q are unit vectors normal to the slider axis, and w1 and w2
+ // are the angular velocity vectors of the two bodies.
+ info->m_J1angularAxis[0] = p[0];
+ info->m_J1angularAxis[1] = p[1];
+ info->m_J1angularAxis[2] = p[2];
+ info->m_J1angularAxis[s+0] = q[0];
+ info->m_J1angularAxis[s+1] = q[1];
+ info->m_J1angularAxis[s+2] = q[2];
+
+ info->m_J2angularAxis[0] = -p[0];
+ info->m_J2angularAxis[1] = -p[1];
+ info->m_J2angularAxis[2] = -p[2];
+ info->m_J2angularAxis[s+0] = -q[0];
+ info->m_J2angularAxis[s+1] = -q[1];
+ info->m_J2angularAxis[s+2] = -q[2];
+ // compute the right hand side of the constraint equation. set relative
+ // body velocities along p and q to bring the slider back into alignment.
+ // if ax1A,ax1B are the unit length slider axes as computed from bodyA and
+ // bodyB, we need to rotate both bodies along the axis u = (ax1 x ax2).
+ // if "theta" is the angle between ax1 and ax2, we need an angular velocity
+ // along u to cover angle erp*theta in one step :
+ // |angular_velocity| = angle/time = erp*theta / stepsize
+ // = (erp*fps) * theta
+ // angular_velocity = |angular_velocity| * (ax1 x ax2) / |ax1 x ax2|
+ // = (erp*fps) * theta * (ax1 x ax2) / sin(theta)
+ // ...as ax1 and ax2 are unit length. if theta is smallish,
+ // theta ~= sin(theta), so
+ // angular_velocity = (erp*fps) * (ax1 x ax2)
+ // ax1 x ax2 is in the plane space of ax1, so we project the angular
+ // velocity to p and q to find the right hand side.
+// btScalar k = info->fps * info->erp * getSoftnessOrthoAng();
+ btScalar currERP = (m_flags & BT_SLIDER_FLAGS_ERP_ORTANG) ? m_softnessOrthoAng : m_softnessOrthoAng * info->erp;
+ btScalar k = info->fps * currERP;
+
+ btVector3 u = ax1A.cross(ax1B);
+ info->m_constraintError[0] = k * u.dot(p);
+ info->m_constraintError[s] = k * u.dot(q);
+ if(m_flags & BT_SLIDER_FLAGS_CFM_ORTANG)
+ {
+ info->cfm[0] = m_cfmOrthoAng;
+ info->cfm[s] = m_cfmOrthoAng;
+ }
+
+ int nrow = 1; // last filled row
+ int srow;
+ btScalar limit_err;
+ int limit;
+
+ // next two rows.
+ // we want: velA + wA x relA == velB + wB x relB ... but this would
+ // result in three equations, so we project along two orthos to the slider axis
+
+ btTransform bodyA_trans = transA;
+ btTransform bodyB_trans = transB;
+ nrow++;
+ int s2 = nrow * s;
+ nrow++;
+ int s3 = nrow * s;
+ btVector3 tmpA(0,0,0), tmpB(0,0,0), relA(0,0,0), relB(0,0,0), c(0,0,0);
+ if(m_useOffsetForConstraintFrame)
+ {
+ // get vector from bodyB to frameB in WCS
+ relB = trB.getOrigin() - bodyB_trans.getOrigin();
+ // get its projection to slider axis
+ btVector3 projB = ax1 * relB.dot(ax1);
+ // get vector directed from bodyB to slider axis (and orthogonal to it)
+ btVector3 orthoB = relB - projB;
+ // same for bodyA
+ relA = trA.getOrigin() - bodyA_trans.getOrigin();
+ btVector3 projA = ax1 * relA.dot(ax1);
+ btVector3 orthoA = relA - projA;
+ // get desired offset between frames A and B along slider axis
+ btScalar sliderOffs = m_linPos - m_depth[0];
+ // desired vector from projection of center of bodyA to projection of center of bodyB to slider axis
+ btVector3 totalDist = projA + ax1 * sliderOffs - projB;
+ // get offset vectors relA and relB
+ relA = orthoA + totalDist * factA;
+ relB = orthoB - totalDist * factB;
+ // now choose average ortho to slider axis
+ p = orthoB * factA + orthoA * factB;
+ btScalar len2 = p.length2();
+ if(len2 > SIMD_EPSILON)
+ {
+ p /= btSqrt(len2);
+ }
+ else
+ {
+ p = trA.getBasis().getColumn(1);
+ }
+ // make one more ortho
+ q = ax1.cross(p);
+ // fill two rows
+ tmpA = relA.cross(p);
+ tmpB = relB.cross(p);
+ for (i=0; i<3; i++) info->m_J1angularAxis[s2+i] = tmpA[i];
+ for (i=0; i<3; i++) info->m_J2angularAxis[s2+i] = -tmpB[i];
+ tmpA = relA.cross(q);
+ tmpB = relB.cross(q);
+ if(hasStaticBody && getSolveAngLimit())
+ { // to make constraint between static and dynamic objects more rigid
+ // remove wA (or wB) from equation if angular limit is hit
+ tmpB *= factB;
+ tmpA *= factA;
+ }
+ for (i=0; i<3; i++) info->m_J1angularAxis[s3+i] = tmpA[i];
+ for (i=0; i<3; i++) info->m_J2angularAxis[s3+i] = -tmpB[i];
+ for (i=0; i<3; i++) info->m_J1linearAxis[s2+i] = p[i];
+ for (i=0; i<3; i++) info->m_J1linearAxis[s3+i] = q[i];
+ for (i=0; i<3; i++) info->m_J2linearAxis[s2+i] = -p[i];
+ for (i=0; i<3; i++) info->m_J2linearAxis[s3+i] = -q[i];
+ }
+ else
+ { // old way - maybe incorrect if bodies are not on the slider axis
+ // see discussion "Bug in slider constraint" http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?f=9&t=4024&start=0
+ c = bodyB_trans.getOrigin() - bodyA_trans.getOrigin();
+ btVector3 tmp = c.cross(p);
+ for (i=0; i<3; i++) info->m_J1angularAxis[s2+i] = factA*tmp[i];
+ for (i=0; i<3; i++) info->m_J2angularAxis[s2+i] = factB*tmp[i];
+ tmp = c.cross(q);
+ for (i=0; i<3; i++) info->m_J1angularAxis[s3+i] = factA*tmp[i];
+ for (i=0; i<3; i++) info->m_J2angularAxis[s3+i] = factB*tmp[i];
+
+ for (i=0; i<3; i++) info->m_J1linearAxis[s2+i] = p[i];
+ for (i=0; i<3; i++) info->m_J1linearAxis[s3+i] = q[i];
+ for (i=0; i<3; i++) info->m_J2linearAxis[s2+i] = -p[i];
+ for (i=0; i<3; i++) info->m_J2linearAxis[s3+i] = -q[i];
+ }
+ // compute two elements of right hand side
+
+ // k = info->fps * info->erp * getSoftnessOrthoLin();
+ currERP = (m_flags & BT_SLIDER_FLAGS_ERP_ORTLIN) ? m_softnessOrthoLin : m_softnessOrthoLin * info->erp;
+ k = info->fps * currERP;
+
+ btScalar rhs = k * p.dot(ofs);
+ info->m_constraintError[s2] = rhs;
+ rhs = k * q.dot(ofs);
+ info->m_constraintError[s3] = rhs;
+ if(m_flags & BT_SLIDER_FLAGS_CFM_ORTLIN)
+ {
+ info->cfm[s2] = m_cfmOrthoLin;
+ info->cfm[s3] = m_cfmOrthoLin;
+ }
+
+
+ // check linear limits
+ limit_err = btScalar(0.0);
+ limit = 0;
+ if(getSolveLinLimit())
+ {
+ limit_err = getLinDepth() * signFact;
+ limit = (limit_err > btScalar(0.0)) ? 2 : 1;
+ }
+ bool powered = getPoweredLinMotor();
+ // if the slider has joint limits or motor, add in the extra row
+ if (limit || powered)
+ {
+ nrow++;
+ srow = nrow * info->rowskip;
+ info->m_J1linearAxis[srow+0] = ax1[0];
+ info->m_J1linearAxis[srow+1] = ax1[1];
+ info->m_J1linearAxis[srow+2] = ax1[2];
+ info->m_J2linearAxis[srow+0] = -ax1[0];
+ info->m_J2linearAxis[srow+1] = -ax1[1];
+ info->m_J2linearAxis[srow+2] = -ax1[2];
+ // linear torque decoupling step:
+ //
+ // we have to be careful that the linear constraint forces (+/- ax1) applied to the two bodies
+ // do not create a torque couple. in other words, the points that the
+ // constraint force is applied at must lie along the same ax1 axis.
+ // a torque couple will result in limited slider-jointed free
+ // bodies from gaining angular momentum.
+ if(m_useOffsetForConstraintFrame)
+ {
+ // this is needed only when bodyA and bodyB are both dynamic.
+ if(!hasStaticBody)
+ {
+ tmpA = relA.cross(ax1);
+ tmpB = relB.cross(ax1);
+ info->m_J1angularAxis[srow+0] = tmpA[0];
+ info->m_J1angularAxis[srow+1] = tmpA[1];
+ info->m_J1angularAxis[srow+2] = tmpA[2];
+ info->m_J2angularAxis[srow+0] = -tmpB[0];
+ info->m_J2angularAxis[srow+1] = -tmpB[1];
+ info->m_J2angularAxis[srow+2] = -tmpB[2];
+ }
+ }
+ else
+ { // The old way. May be incorrect if bodies are not on the slider axis
+ btVector3 ltd; // Linear Torque Decoupling vector (a torque)
+ ltd = c.cross(ax1);
+ info->m_J1angularAxis[srow+0] = factA*ltd[0];
+ info->m_J1angularAxis[srow+1] = factA*ltd[1];
+ info->m_J1angularAxis[srow+2] = factA*ltd[2];
+ info->m_J2angularAxis[srow+0] = factB*ltd[0];
+ info->m_J2angularAxis[srow+1] = factB*ltd[1];
+ info->m_J2angularAxis[srow+2] = factB*ltd[2];
+ }
+ // right-hand part
+ btScalar lostop = getLowerLinLimit();
+ btScalar histop = getUpperLinLimit();
+ if(limit && (lostop == histop))
+ { // the joint motor is ineffective
+ powered = false;
+ }
+ info->m_constraintError[srow] = 0.;
+ info->m_lowerLimit[srow] = 0.;
+ info->m_upperLimit[srow] = 0.;
+ currERP = (m_flags & BT_SLIDER_FLAGS_ERP_LIMLIN) ? m_softnessLimLin : info->erp;
+ if(powered)
+ {
+ if(m_flags & BT_SLIDER_FLAGS_CFM_DIRLIN)
+ {
+ info->cfm[srow] = m_cfmDirLin;
+ }
+ btScalar tag_vel = getTargetLinMotorVelocity();
+ btScalar mot_fact = getMotorFactor(m_linPos, m_lowerLinLimit, m_upperLinLimit, tag_vel, info->fps * currERP);
+ info->m_constraintError[srow] -= signFact * mot_fact * getTargetLinMotorVelocity();
+ info->m_lowerLimit[srow] += -getMaxLinMotorForce() / info->fps;
+ info->m_upperLimit[srow] += getMaxLinMotorForce() / info->fps;
+ }
+ if(limit)
+ {
+ k = info->fps * currERP;
+ info->m_constraintError[srow] += k * limit_err;
+ if(m_flags & BT_SLIDER_FLAGS_CFM_LIMLIN)
+ {
+ info->cfm[srow] = m_cfmLimLin;
+ }
+ if(lostop == histop)
+ { // limited low and high simultaneously
+ info->m_lowerLimit[srow] = -SIMD_INFINITY;
+ info->m_upperLimit[srow] = SIMD_INFINITY;
+ }
+ else if(limit == 1)
+ { // low limit
+ info->m_lowerLimit[srow] = -SIMD_INFINITY;
+ info->m_upperLimit[srow] = 0;
+ }
+ else
+ { // high limit
+ info->m_lowerLimit[srow] = 0;
+ info->m_upperLimit[srow] = SIMD_INFINITY;
+ }
+ // bounce (we'll use slider parameter abs(1.0 - m_dampingLimLin) for that)
+ btScalar bounce = btFabs(btScalar(1.0) - getDampingLimLin());
+ if(bounce > btScalar(0.0))
+ {
+ btScalar vel = linVelA.dot(ax1);
+ vel -= linVelB.dot(ax1);
+ vel *= signFact;
+ // only apply bounce if the velocity is incoming, and if the
+ // resulting c[] exceeds what we already have.
+ if(limit == 1)
+ { // low limit
+ if(vel < 0)
+ {
+ btScalar newc = -bounce * vel;
+ if (newc > info->m_constraintError[srow])
+ {
+ info->m_constraintError[srow] = newc;
+ }
+ }
+ }
+ else
+ { // high limit - all those computations are reversed
+ if(vel > 0)
+ {
+ btScalar newc = -bounce * vel;
+ if(newc < info->m_constraintError[srow])
+ {
+ info->m_constraintError[srow] = newc;
+ }
+ }
+ }
+ }
+ info->m_constraintError[srow] *= getSoftnessLimLin();
+ } // if(limit)
+ } // if linear limit
+ // check angular limits
+ limit_err = btScalar(0.0);
+ limit = 0;
+ if(getSolveAngLimit())
+ {
+ limit_err = getAngDepth();
+ limit = (limit_err > btScalar(0.0)) ? 1 : 2;
+ }
+ // if the slider has joint limits, add in the extra row
+ powered = getPoweredAngMotor();
+ if(limit || powered)
+ {
+ nrow++;
+ srow = nrow * info->rowskip;
+ info->m_J1angularAxis[srow+0] = ax1[0];
+ info->m_J1angularAxis[srow+1] = ax1[1];
+ info->m_J1angularAxis[srow+2] = ax1[2];
+
+ info->m_J2angularAxis[srow+0] = -ax1[0];
+ info->m_J2angularAxis[srow+1] = -ax1[1];
+ info->m_J2angularAxis[srow+2] = -ax1[2];
+
+ btScalar lostop = getLowerAngLimit();
+ btScalar histop = getUpperAngLimit();
+ if(limit && (lostop == histop))
+ { // the joint motor is ineffective
+ powered = false;
+ }
+ currERP = (m_flags & BT_SLIDER_FLAGS_ERP_LIMANG) ? m_softnessLimAng : info->erp;
+ if(powered)
+ {
+ if(m_flags & BT_SLIDER_FLAGS_CFM_DIRANG)
+ {
+ info->cfm[srow] = m_cfmDirAng;
+ }
+ btScalar mot_fact = getMotorFactor(m_angPos, m_lowerAngLimit, m_upperAngLimit, getTargetAngMotorVelocity(), info->fps * currERP);
+ info->m_constraintError[srow] = mot_fact * getTargetAngMotorVelocity();
+ info->m_lowerLimit[srow] = -getMaxAngMotorForce() / info->fps;
+ info->m_upperLimit[srow] = getMaxAngMotorForce() / info->fps;
+ }
+ if(limit)
+ {
+ k = info->fps * currERP;
+ info->m_constraintError[srow] += k * limit_err;
+ if(m_flags & BT_SLIDER_FLAGS_CFM_LIMANG)
+ {
+ info->cfm[srow] = m_cfmLimAng;
+ }
+ if(lostop == histop)
+ {
+ // limited low and high simultaneously
+ info->m_lowerLimit[srow] = -SIMD_INFINITY;
+ info->m_upperLimit[srow] = SIMD_INFINITY;
+ }
+ else if(limit == 1)
+ { // low limit
+ info->m_lowerLimit[srow] = 0;
+ info->m_upperLimit[srow] = SIMD_INFINITY;
+ }
+ else
+ { // high limit
+ info->m_lowerLimit[srow] = -SIMD_INFINITY;
+ info->m_upperLimit[srow] = 0;
+ }
+ // bounce (we'll use slider parameter abs(1.0 - m_dampingLimAng) for that)
+ btScalar bounce = btFabs(btScalar(1.0) - getDampingLimAng());
+ if(bounce > btScalar(0.0))
+ {
+ btScalar vel = m_rbA.getAngularVelocity().dot(ax1);
+ vel -= m_rbB.getAngularVelocity().dot(ax1);
+ // only apply bounce if the velocity is incoming, and if the
+ // resulting c[] exceeds what we already have.
+ if(limit == 1)
+ { // low limit
+ if(vel < 0)
+ {
+ btScalar newc = -bounce * vel;
+ if(newc > info->m_constraintError[srow])
+ {
+ info->m_constraintError[srow] = newc;
+ }
+ }
+ }
+ else
+ { // high limit - all those computations are reversed
+ if(vel > 0)
+ {
+ btScalar newc = -bounce * vel;
+ if(newc < info->m_constraintError[srow])
+ {
+ info->m_constraintError[srow] = newc;
+ }
+ }
+ }
+ }
+ info->m_constraintError[srow] *= getSoftnessLimAng();
+ } // if(limit)
+ } // if angular limit or powered
+}
+
+
+///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
+///If no axis is provided, it uses the default axis for this constraint.
+void btSliderConstraint::setParam(int num, btScalar value, int axis)
+{
+ switch(num)
+ {
+ case BT_CONSTRAINT_STOP_ERP :
+ if(axis < 1)
+ {
+ m_softnessLimLin = value;
+ m_flags |= BT_SLIDER_FLAGS_ERP_LIMLIN;
+ }
+ else if(axis < 3)
+ {
+ m_softnessOrthoLin = value;
+ m_flags |= BT_SLIDER_FLAGS_ERP_ORTLIN;
+ }
+ else if(axis == 3)
+ {
+ m_softnessLimAng = value;
+ m_flags |= BT_SLIDER_FLAGS_ERP_LIMANG;
+ }
+ else if(axis < 6)
+ {
+ m_softnessOrthoAng = value;
+ m_flags |= BT_SLIDER_FLAGS_ERP_ORTANG;
+ }
+ else
+ {
+ btAssertConstrParams(0);
+ }
+ break;
+ case BT_CONSTRAINT_CFM :
+ if(axis < 1)
+ {
+ m_cfmDirLin = value;
+ m_flags |= BT_SLIDER_FLAGS_CFM_DIRLIN;
+ }
+ else if(axis == 3)
+ {
+ m_cfmDirAng = value;
+ m_flags |= BT_SLIDER_FLAGS_CFM_DIRANG;
+ }
+ else
+ {
+ btAssertConstrParams(0);
+ }
+ break;
+ case BT_CONSTRAINT_STOP_CFM :
+ if(axis < 1)
+ {
+ m_cfmLimLin = value;
+ m_flags |= BT_SLIDER_FLAGS_CFM_LIMLIN;
+ }
+ else if(axis < 3)
+ {
+ m_cfmOrthoLin = value;
+ m_flags |= BT_SLIDER_FLAGS_CFM_ORTLIN;
+ }
+ else if(axis == 3)
+ {
+ m_cfmLimAng = value;
+ m_flags |= BT_SLIDER_FLAGS_CFM_LIMANG;
+ }
+ else if(axis < 6)
+ {
+ m_cfmOrthoAng = value;
+ m_flags |= BT_SLIDER_FLAGS_CFM_ORTANG;
+ }
+ else
+ {
+ btAssertConstrParams(0);
+ }
+ break;
+ }
+}
+
+///return the local value of parameter
+btScalar btSliderConstraint::getParam(int num, int axis) const
+{
+ btScalar retVal(SIMD_INFINITY);
+ switch(num)
+ {
+ case BT_CONSTRAINT_STOP_ERP :
+ if(axis < 1)
+ {
+ btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_ERP_LIMLIN);
+ retVal = m_softnessLimLin;
+ }
+ else if(axis < 3)
+ {
+ btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_ERP_ORTLIN);
+ retVal = m_softnessOrthoLin;
+ }
+ else if(axis == 3)
+ {
+ btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_ERP_LIMANG);
+ retVal = m_softnessLimAng;
+ }
+ else if(axis < 6)
+ {
+ btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_ERP_ORTANG);
+ retVal = m_softnessOrthoAng;
+ }
+ else
+ {
+ btAssertConstrParams(0);
+ }
+ break;
+ case BT_CONSTRAINT_CFM :
+ if(axis < 1)
+ {
+ btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_DIRLIN);
+ retVal = m_cfmDirLin;
+ }
+ else if(axis == 3)
+ {
+ btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_DIRANG);
+ retVal = m_cfmDirAng;
+ }
+ else
+ {
+ btAssertConstrParams(0);
+ }
+ break;
+ case BT_CONSTRAINT_STOP_CFM :
+ if(axis < 1)
+ {
+ btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_LIMLIN);
+ retVal = m_cfmLimLin;
+ }
+ else if(axis < 3)
+ {
+ btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_ORTLIN);
+ retVal = m_cfmOrthoLin;
+ }
+ else if(axis == 3)
+ {
+ btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_LIMANG);
+ retVal = m_cfmLimAng;
+ }
+ else if(axis < 6)
+ {
+ btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_ORTANG);
+ retVal = m_cfmOrthoAng;
+ }
+ else
+ {
+ btAssertConstrParams(0);
+ }
+ break;
+ }
+ return retVal;
+}
+
+
+
diff --git a/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h
new file mode 100644
index 0000000000..1957f08a96
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h
@@ -0,0 +1,368 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+/*
+Added by Roman Ponomarev (rponom@gmail.com)
+April 04, 2008
+
+TODO:
+ - add clamping od accumulated impulse to improve stability
+ - add conversion for ODE constraint solver
+*/
+
+#ifndef BT_SLIDER_CONSTRAINT_H
+#define BT_SLIDER_CONSTRAINT_H
+
+#include "LinearMath/btScalar.h"//for BT_USE_DOUBLE_PRECISION
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define btSliderConstraintData2 btSliderConstraintDoubleData
+#define btSliderConstraintDataName "btSliderConstraintDoubleData"
+#else
+#define btSliderConstraintData2 btSliderConstraintData
+#define btSliderConstraintDataName "btSliderConstraintData"
+#endif //BT_USE_DOUBLE_PRECISION
+
+#include "LinearMath/btVector3.h"
+#include "btJacobianEntry.h"
+#include "btTypedConstraint.h"
+
+
+
+class btRigidBody;
+
+
+
+#define SLIDER_CONSTRAINT_DEF_SOFTNESS (btScalar(1.0))
+#define SLIDER_CONSTRAINT_DEF_DAMPING (btScalar(1.0))
+#define SLIDER_CONSTRAINT_DEF_RESTITUTION (btScalar(0.7))
+#define SLIDER_CONSTRAINT_DEF_CFM (btScalar(0.f))
+
+
+enum btSliderFlags
+{
+ BT_SLIDER_FLAGS_CFM_DIRLIN = (1 << 0),
+ BT_SLIDER_FLAGS_ERP_DIRLIN = (1 << 1),
+ BT_SLIDER_FLAGS_CFM_DIRANG = (1 << 2),
+ BT_SLIDER_FLAGS_ERP_DIRANG = (1 << 3),
+ BT_SLIDER_FLAGS_CFM_ORTLIN = (1 << 4),
+ BT_SLIDER_FLAGS_ERP_ORTLIN = (1 << 5),
+ BT_SLIDER_FLAGS_CFM_ORTANG = (1 << 6),
+ BT_SLIDER_FLAGS_ERP_ORTANG = (1 << 7),
+ BT_SLIDER_FLAGS_CFM_LIMLIN = (1 << 8),
+ BT_SLIDER_FLAGS_ERP_LIMLIN = (1 << 9),
+ BT_SLIDER_FLAGS_CFM_LIMANG = (1 << 10),
+ BT_SLIDER_FLAGS_ERP_LIMANG = (1 << 11)
+};
+
+
+ATTRIBUTE_ALIGNED16(class) btSliderConstraint : public btTypedConstraint
+{
+protected:
+ ///for backwards compatibility during the transition to 'getInfo/getInfo2'
+ bool m_useSolveConstraintObsolete;
+ bool m_useOffsetForConstraintFrame;
+ btTransform m_frameInA;
+ btTransform m_frameInB;
+ // use frameA fo define limits, if true
+ bool m_useLinearReferenceFrameA;
+ // linear limits
+ btScalar m_lowerLinLimit;
+ btScalar m_upperLinLimit;
+ // angular limits
+ btScalar m_lowerAngLimit;
+ btScalar m_upperAngLimit;
+ // softness, restitution and damping for different cases
+ // DirLin - moving inside linear limits
+ // LimLin - hitting linear limit
+ // DirAng - moving inside angular limits
+ // LimAng - hitting angular limit
+ // OrthoLin, OrthoAng - against constraint axis
+ btScalar m_softnessDirLin;
+ btScalar m_restitutionDirLin;
+ btScalar m_dampingDirLin;
+ btScalar m_cfmDirLin;
+
+ btScalar m_softnessDirAng;
+ btScalar m_restitutionDirAng;
+ btScalar m_dampingDirAng;
+ btScalar m_cfmDirAng;
+
+ btScalar m_softnessLimLin;
+ btScalar m_restitutionLimLin;
+ btScalar m_dampingLimLin;
+ btScalar m_cfmLimLin;
+
+ btScalar m_softnessLimAng;
+ btScalar m_restitutionLimAng;
+ btScalar m_dampingLimAng;
+ btScalar m_cfmLimAng;
+
+ btScalar m_softnessOrthoLin;
+ btScalar m_restitutionOrthoLin;
+ btScalar m_dampingOrthoLin;
+ btScalar m_cfmOrthoLin;
+
+ btScalar m_softnessOrthoAng;
+ btScalar m_restitutionOrthoAng;
+ btScalar m_dampingOrthoAng;
+ btScalar m_cfmOrthoAng;
+
+ // for interlal use
+ bool m_solveLinLim;
+ bool m_solveAngLim;
+
+ int m_flags;
+
+ btJacobianEntry m_jacLin[3];
+ btScalar m_jacLinDiagABInv[3];
+
+ btJacobianEntry m_jacAng[3];
+
+ btScalar m_timeStep;
+ btTransform m_calculatedTransformA;
+ btTransform m_calculatedTransformB;
+
+ btVector3 m_sliderAxis;
+ btVector3 m_realPivotAInW;
+ btVector3 m_realPivotBInW;
+ btVector3 m_projPivotInW;
+ btVector3 m_delta;
+ btVector3 m_depth;
+ btVector3 m_relPosA;
+ btVector3 m_relPosB;
+
+ btScalar m_linPos;
+ btScalar m_angPos;
+
+ btScalar m_angDepth;
+ btScalar m_kAngle;
+
+ bool m_poweredLinMotor;
+ btScalar m_targetLinMotorVelocity;
+ btScalar m_maxLinMotorForce;
+ btScalar m_accumulatedLinMotorImpulse;
+
+ bool m_poweredAngMotor;
+ btScalar m_targetAngMotorVelocity;
+ btScalar m_maxAngMotorForce;
+ btScalar m_accumulatedAngMotorImpulse;
+
+ //------------------------
+ void initParams();
+public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ // constructors
+ btSliderConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ,bool useLinearReferenceFrameA);
+ btSliderConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameA);
+
+ // overrides
+
+ virtual void getInfo1 (btConstraintInfo1* info);
+
+ void getInfo1NonVirtual(btConstraintInfo1* info);
+
+ virtual void getInfo2 (btConstraintInfo2* info);
+
+ void getInfo2NonVirtual(btConstraintInfo2* info, const btTransform& transA, const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB, btScalar rbAinvMass,btScalar rbBinvMass);
+
+
+ // access
+ const btRigidBody& getRigidBodyA() const { return m_rbA; }
+ const btRigidBody& getRigidBodyB() const { return m_rbB; }
+ const btTransform & getCalculatedTransformA() const { return m_calculatedTransformA; }
+ const btTransform & getCalculatedTransformB() const { return m_calculatedTransformB; }
+ const btTransform & getFrameOffsetA() const { return m_frameInA; }
+ const btTransform & getFrameOffsetB() const { return m_frameInB; }
+ btTransform & getFrameOffsetA() { return m_frameInA; }
+ btTransform & getFrameOffsetB() { return m_frameInB; }
+ btScalar getLowerLinLimit() { return m_lowerLinLimit; }
+ void setLowerLinLimit(btScalar lowerLimit) { m_lowerLinLimit = lowerLimit; }
+ btScalar getUpperLinLimit() { return m_upperLinLimit; }
+ void setUpperLinLimit(btScalar upperLimit) { m_upperLinLimit = upperLimit; }
+ btScalar getLowerAngLimit() { return m_lowerAngLimit; }
+ void setLowerAngLimit(btScalar lowerLimit) { m_lowerAngLimit = btNormalizeAngle(lowerLimit); }
+ btScalar getUpperAngLimit() { return m_upperAngLimit; }
+ void setUpperAngLimit(btScalar upperLimit) { m_upperAngLimit = btNormalizeAngle(upperLimit); }
+ bool getUseLinearReferenceFrameA() { return m_useLinearReferenceFrameA; }
+ btScalar getSoftnessDirLin() { return m_softnessDirLin; }
+ btScalar getRestitutionDirLin() { return m_restitutionDirLin; }
+ btScalar getDampingDirLin() { return m_dampingDirLin ; }
+ btScalar getSoftnessDirAng() { return m_softnessDirAng; }
+ btScalar getRestitutionDirAng() { return m_restitutionDirAng; }
+ btScalar getDampingDirAng() { return m_dampingDirAng; }
+ btScalar getSoftnessLimLin() { return m_softnessLimLin; }
+ btScalar getRestitutionLimLin() { return m_restitutionLimLin; }
+ btScalar getDampingLimLin() { return m_dampingLimLin; }
+ btScalar getSoftnessLimAng() { return m_softnessLimAng; }
+ btScalar getRestitutionLimAng() { return m_restitutionLimAng; }
+ btScalar getDampingLimAng() { return m_dampingLimAng; }
+ btScalar getSoftnessOrthoLin() { return m_softnessOrthoLin; }
+ btScalar getRestitutionOrthoLin() { return m_restitutionOrthoLin; }
+ btScalar getDampingOrthoLin() { return m_dampingOrthoLin; }
+ btScalar getSoftnessOrthoAng() { return m_softnessOrthoAng; }
+ btScalar getRestitutionOrthoAng() { return m_restitutionOrthoAng; }
+ btScalar getDampingOrthoAng() { return m_dampingOrthoAng; }
+ void setSoftnessDirLin(btScalar softnessDirLin) { m_softnessDirLin = softnessDirLin; }
+ void setRestitutionDirLin(btScalar restitutionDirLin) { m_restitutionDirLin = restitutionDirLin; }
+ void setDampingDirLin(btScalar dampingDirLin) { m_dampingDirLin = dampingDirLin; }
+ void setSoftnessDirAng(btScalar softnessDirAng) { m_softnessDirAng = softnessDirAng; }
+ void setRestitutionDirAng(btScalar restitutionDirAng) { m_restitutionDirAng = restitutionDirAng; }
+ void setDampingDirAng(btScalar dampingDirAng) { m_dampingDirAng = dampingDirAng; }
+ void setSoftnessLimLin(btScalar softnessLimLin) { m_softnessLimLin = softnessLimLin; }
+ void setRestitutionLimLin(btScalar restitutionLimLin) { m_restitutionLimLin = restitutionLimLin; }
+ void setDampingLimLin(btScalar dampingLimLin) { m_dampingLimLin = dampingLimLin; }
+ void setSoftnessLimAng(btScalar softnessLimAng) { m_softnessLimAng = softnessLimAng; }
+ void setRestitutionLimAng(btScalar restitutionLimAng) { m_restitutionLimAng = restitutionLimAng; }
+ void setDampingLimAng(btScalar dampingLimAng) { m_dampingLimAng = dampingLimAng; }
+ void setSoftnessOrthoLin(btScalar softnessOrthoLin) { m_softnessOrthoLin = softnessOrthoLin; }
+ void setRestitutionOrthoLin(btScalar restitutionOrthoLin) { m_restitutionOrthoLin = restitutionOrthoLin; }
+ void setDampingOrthoLin(btScalar dampingOrthoLin) { m_dampingOrthoLin = dampingOrthoLin; }
+ void setSoftnessOrthoAng(btScalar softnessOrthoAng) { m_softnessOrthoAng = softnessOrthoAng; }
+ void setRestitutionOrthoAng(btScalar restitutionOrthoAng) { m_restitutionOrthoAng = restitutionOrthoAng; }
+ void setDampingOrthoAng(btScalar dampingOrthoAng) { m_dampingOrthoAng = dampingOrthoAng; }
+ void setPoweredLinMotor(bool onOff) { m_poweredLinMotor = onOff; }
+ bool getPoweredLinMotor() { return m_poweredLinMotor; }
+ void setTargetLinMotorVelocity(btScalar targetLinMotorVelocity) { m_targetLinMotorVelocity = targetLinMotorVelocity; }
+ btScalar getTargetLinMotorVelocity() { return m_targetLinMotorVelocity; }
+ void setMaxLinMotorForce(btScalar maxLinMotorForce) { m_maxLinMotorForce = maxLinMotorForce; }
+ btScalar getMaxLinMotorForce() { return m_maxLinMotorForce; }
+ void setPoweredAngMotor(bool onOff) { m_poweredAngMotor = onOff; }
+ bool getPoweredAngMotor() { return m_poweredAngMotor; }
+ void setTargetAngMotorVelocity(btScalar targetAngMotorVelocity) { m_targetAngMotorVelocity = targetAngMotorVelocity; }
+ btScalar getTargetAngMotorVelocity() { return m_targetAngMotorVelocity; }
+ void setMaxAngMotorForce(btScalar maxAngMotorForce) { m_maxAngMotorForce = maxAngMotorForce; }
+ btScalar getMaxAngMotorForce() { return m_maxAngMotorForce; }
+
+ btScalar getLinearPos() const { return m_linPos; }
+ btScalar getAngularPos() const { return m_angPos; }
+
+
+
+ // access for ODE solver
+ bool getSolveLinLimit() { return m_solveLinLim; }
+ btScalar getLinDepth() { return m_depth[0]; }
+ bool getSolveAngLimit() { return m_solveAngLim; }
+ btScalar getAngDepth() { return m_angDepth; }
+ // shared code used by ODE solver
+ void calculateTransforms(const btTransform& transA,const btTransform& transB);
+ void testLinLimits();
+ void testAngLimits();
+ // access for PE Solver
+ btVector3 getAncorInA();
+ btVector3 getAncorInB();
+ // access for UseFrameOffset
+ bool getUseFrameOffset() { return m_useOffsetForConstraintFrame; }
+ void setUseFrameOffset(bool frameOffsetOnOff) { m_useOffsetForConstraintFrame = frameOffsetOnOff; }
+
+ void setFrames(const btTransform& frameA, const btTransform& frameB)
+ {
+ m_frameInA=frameA;
+ m_frameInB=frameB;
+ calculateTransforms(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform());
+ buildJacobian();
+ }
+
+
+ ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
+ ///If no axis is provided, it uses the default axis for this constraint.
+ virtual void setParam(int num, btScalar value, int axis = -1);
+ ///return the local value of parameter
+ virtual btScalar getParam(int num, int axis = -1) const;
+
+ virtual int getFlags() const
+ {
+ return m_flags;
+ }
+
+ virtual int calculateSerializeBufferSize() const;
+
+ ///fills the dataBuffer and returns the struct name (and 0 on failure)
+ virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
+
+
+};
+
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+
+
+struct btSliderConstraintData
+{
+ btTypedConstraintData m_typeConstraintData;
+ btTransformFloatData m_rbAFrame; // constraint axii. Assumes z is hinge axis.
+ btTransformFloatData m_rbBFrame;
+
+ float m_linearUpperLimit;
+ float m_linearLowerLimit;
+
+ float m_angularUpperLimit;
+ float m_angularLowerLimit;
+
+ int m_useLinearReferenceFrameA;
+ int m_useOffsetForConstraintFrame;
+
+};
+
+
+struct btSliderConstraintDoubleData
+{
+ btTypedConstraintDoubleData m_typeConstraintData;
+ btTransformDoubleData m_rbAFrame; // constraint axii. Assumes z is hinge axis.
+ btTransformDoubleData m_rbBFrame;
+
+ double m_linearUpperLimit;
+ double m_linearLowerLimit;
+
+ double m_angularUpperLimit;
+ double m_angularLowerLimit;
+
+ int m_useLinearReferenceFrameA;
+ int m_useOffsetForConstraintFrame;
+
+};
+
+SIMD_FORCE_INLINE int btSliderConstraint::calculateSerializeBufferSize() const
+{
+ return sizeof(btSliderConstraintData2);
+}
+
+ ///fills the dataBuffer and returns the struct name (and 0 on failure)
+SIMD_FORCE_INLINE const char* btSliderConstraint::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+
+ btSliderConstraintData2* sliderData = (btSliderConstraintData2*) dataBuffer;
+ btTypedConstraint::serialize(&sliderData->m_typeConstraintData,serializer);
+
+ m_frameInA.serialize(sliderData->m_rbAFrame);
+ m_frameInB.serialize(sliderData->m_rbBFrame);
+
+ sliderData->m_linearUpperLimit = m_upperLinLimit;
+ sliderData->m_linearLowerLimit = m_lowerLinLimit;
+
+ sliderData->m_angularUpperLimit = m_upperAngLimit;
+ sliderData->m_angularLowerLimit = m_lowerAngLimit;
+
+ sliderData->m_useLinearReferenceFrameA = m_useLinearReferenceFrameA;
+ sliderData->m_useOffsetForConstraintFrame = m_useOffsetForConstraintFrame;
+
+ return btSliderConstraintDataName;
+}
+
+
+
+#endif //BT_SLIDER_CONSTRAINT_H
+
diff --git a/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp
new file mode 100644
index 0000000000..0c7dbd668b
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp
@@ -0,0 +1,255 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+#include "btSolve2LinearConstraint.h"
+
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "LinearMath/btVector3.h"
+#include "btJacobianEntry.h"
+
+
+void btSolve2LinearConstraint::resolveUnilateralPairConstraint(
+ btRigidBody* body1,
+ btRigidBody* body2,
+
+ const btMatrix3x3& world2A,
+ const btMatrix3x3& world2B,
+
+ const btVector3& invInertiaADiag,
+ const btScalar invMassA,
+ const btVector3& linvelA,const btVector3& angvelA,
+ const btVector3& rel_posA1,
+ const btVector3& invInertiaBDiag,
+ const btScalar invMassB,
+ const btVector3& linvelB,const btVector3& angvelB,
+ const btVector3& rel_posA2,
+
+ btScalar depthA, const btVector3& normalA,
+ const btVector3& rel_posB1,const btVector3& rel_posB2,
+ btScalar depthB, const btVector3& normalB,
+ btScalar& imp0,btScalar& imp1)
+{
+ (void)linvelA;
+ (void)linvelB;
+ (void)angvelB;
+ (void)angvelA;
+
+
+
+ imp0 = btScalar(0.);
+ imp1 = btScalar(0.);
+
+ btScalar len = btFabs(normalA.length()) - btScalar(1.);
+ if (btFabs(len) >= SIMD_EPSILON)
+ return;
+
+ btAssert(len < SIMD_EPSILON);
+
+
+ //this jacobian entry could be re-used for all iterations
+ btJacobianEntry jacA(world2A,world2B,rel_posA1,rel_posA2,normalA,invInertiaADiag,invMassA,
+ invInertiaBDiag,invMassB);
+ btJacobianEntry jacB(world2A,world2B,rel_posB1,rel_posB2,normalB,invInertiaADiag,invMassA,
+ invInertiaBDiag,invMassB);
+
+ //const btScalar vel0 = jacA.getRelativeVelocity(linvelA,angvelA,linvelB,angvelB);
+ //const btScalar vel1 = jacB.getRelativeVelocity(linvelA,angvelA,linvelB,angvelB);
+
+ const btScalar vel0 = normalA.dot(body1->getVelocityInLocalPoint(rel_posA1)-body2->getVelocityInLocalPoint(rel_posA1));
+ const btScalar vel1 = normalB.dot(body1->getVelocityInLocalPoint(rel_posB1)-body2->getVelocityInLocalPoint(rel_posB1));
+
+// btScalar penetrationImpulse = (depth*contactTau*timeCorrection) * massTerm;//jacDiagABInv
+ btScalar massTerm = btScalar(1.) / (invMassA + invMassB);
+
+
+ // calculate rhs (or error) terms
+ const btScalar dv0 = depthA * m_tau * massTerm - vel0 * m_damping;
+ const btScalar dv1 = depthB * m_tau * massTerm - vel1 * m_damping;
+
+
+ // dC/dv * dv = -C
+
+ // jacobian * impulse = -error
+ //
+
+ //impulse = jacobianInverse * -error
+
+ // inverting 2x2 symmetric system (offdiagonal are equal!)
+ //
+
+
+ btScalar nonDiag = jacA.getNonDiagonal(jacB,invMassA,invMassB);
+ btScalar invDet = btScalar(1.0) / (jacA.getDiagonal() * jacB.getDiagonal() - nonDiag * nonDiag );
+
+ //imp0 = dv0 * jacA.getDiagonal() * invDet + dv1 * -nonDiag * invDet;
+ //imp1 = dv1 * jacB.getDiagonal() * invDet + dv0 * - nonDiag * invDet;
+
+ imp0 = dv0 * jacA.getDiagonal() * invDet + dv1 * -nonDiag * invDet;
+ imp1 = dv1 * jacB.getDiagonal() * invDet + dv0 * - nonDiag * invDet;
+
+ //[a b] [d -c]
+ //[c d] inverse = (1 / determinant) * [-b a] where determinant is (ad - bc)
+
+ //[jA nD] * [imp0] = [dv0]
+ //[nD jB] [imp1] [dv1]
+
+}
+
+
+
+void btSolve2LinearConstraint::resolveBilateralPairConstraint(
+ btRigidBody* body1,
+ btRigidBody* body2,
+ const btMatrix3x3& world2A,
+ const btMatrix3x3& world2B,
+
+ const btVector3& invInertiaADiag,
+ const btScalar invMassA,
+ const btVector3& linvelA,const btVector3& angvelA,
+ const btVector3& rel_posA1,
+ const btVector3& invInertiaBDiag,
+ const btScalar invMassB,
+ const btVector3& linvelB,const btVector3& angvelB,
+ const btVector3& rel_posA2,
+
+ btScalar depthA, const btVector3& normalA,
+ const btVector3& rel_posB1,const btVector3& rel_posB2,
+ btScalar depthB, const btVector3& normalB,
+ btScalar& imp0,btScalar& imp1)
+{
+
+ (void)linvelA;
+ (void)linvelB;
+ (void)angvelA;
+ (void)angvelB;
+
+
+
+ imp0 = btScalar(0.);
+ imp1 = btScalar(0.);
+
+ btScalar len = btFabs(normalA.length()) - btScalar(1.);
+ if (btFabs(len) >= SIMD_EPSILON)
+ return;
+
+ btAssert(len < SIMD_EPSILON);
+
+
+ //this jacobian entry could be re-used for all iterations
+ btJacobianEntry jacA(world2A,world2B,rel_posA1,rel_posA2,normalA,invInertiaADiag,invMassA,
+ invInertiaBDiag,invMassB);
+ btJacobianEntry jacB(world2A,world2B,rel_posB1,rel_posB2,normalB,invInertiaADiag,invMassA,
+ invInertiaBDiag,invMassB);
+
+ //const btScalar vel0 = jacA.getRelativeVelocity(linvelA,angvelA,linvelB,angvelB);
+ //const btScalar vel1 = jacB.getRelativeVelocity(linvelA,angvelA,linvelB,angvelB);
+
+ const btScalar vel0 = normalA.dot(body1->getVelocityInLocalPoint(rel_posA1)-body2->getVelocityInLocalPoint(rel_posA1));
+ const btScalar vel1 = normalB.dot(body1->getVelocityInLocalPoint(rel_posB1)-body2->getVelocityInLocalPoint(rel_posB1));
+
+ // calculate rhs (or error) terms
+ const btScalar dv0 = depthA * m_tau - vel0 * m_damping;
+ const btScalar dv1 = depthB * m_tau - vel1 * m_damping;
+
+ // dC/dv * dv = -C
+
+ // jacobian * impulse = -error
+ //
+
+ //impulse = jacobianInverse * -error
+
+ // inverting 2x2 symmetric system (offdiagonal are equal!)
+ //
+
+
+ btScalar nonDiag = jacA.getNonDiagonal(jacB,invMassA,invMassB);
+ btScalar invDet = btScalar(1.0) / (jacA.getDiagonal() * jacB.getDiagonal() - nonDiag * nonDiag );
+
+ //imp0 = dv0 * jacA.getDiagonal() * invDet + dv1 * -nonDiag * invDet;
+ //imp1 = dv1 * jacB.getDiagonal() * invDet + dv0 * - nonDiag * invDet;
+
+ imp0 = dv0 * jacA.getDiagonal() * invDet + dv1 * -nonDiag * invDet;
+ imp1 = dv1 * jacB.getDiagonal() * invDet + dv0 * - nonDiag * invDet;
+
+ //[a b] [d -c]
+ //[c d] inverse = (1 / determinant) * [-b a] where determinant is (ad - bc)
+
+ //[jA nD] * [imp0] = [dv0]
+ //[nD jB] [imp1] [dv1]
+
+ if ( imp0 > btScalar(0.0))
+ {
+ if ( imp1 > btScalar(0.0) )
+ {
+ //both positive
+ }
+ else
+ {
+ imp1 = btScalar(0.);
+
+ // now imp0>0 imp1<0
+ imp0 = dv0 / jacA.getDiagonal();
+ if ( imp0 > btScalar(0.0) )
+ {
+ } else
+ {
+ imp0 = btScalar(0.);
+ }
+ }
+ }
+ else
+ {
+ imp0 = btScalar(0.);
+
+ imp1 = dv1 / jacB.getDiagonal();
+ if ( imp1 <= btScalar(0.0) )
+ {
+ imp1 = btScalar(0.);
+ // now imp0>0 imp1<0
+ imp0 = dv0 / jacA.getDiagonal();
+ if ( imp0 > btScalar(0.0) )
+ {
+ } else
+ {
+ imp0 = btScalar(0.);
+ }
+ } else
+ {
+ }
+ }
+}
+
+
+/*
+void btSolve2LinearConstraint::resolveAngularConstraint( const btMatrix3x3& invInertiaAWS,
+ const btScalar invMassA,
+ const btVector3& linvelA,const btVector3& angvelA,
+ const btVector3& rel_posA1,
+ const btMatrix3x3& invInertiaBWS,
+ const btScalar invMassB,
+ const btVector3& linvelB,const btVector3& angvelB,
+ const btVector3& rel_posA2,
+
+ btScalar depthA, const btVector3& normalA,
+ const btVector3& rel_posB1,const btVector3& rel_posB2,
+ btScalar depthB, const btVector3& normalB,
+ btScalar& imp0,btScalar& imp1)
+{
+
+}
+*/
+
diff --git a/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h
new file mode 100644
index 0000000000..e8bfabf864
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h
@@ -0,0 +1,107 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_SOLVE_2LINEAR_CONSTRAINT_H
+#define BT_SOLVE_2LINEAR_CONSTRAINT_H
+
+#include "LinearMath/btMatrix3x3.h"
+#include "LinearMath/btVector3.h"
+
+
+class btRigidBody;
+
+
+
+/// constraint class used for lateral tyre friction.
+class btSolve2LinearConstraint
+{
+ btScalar m_tau;
+ btScalar m_damping;
+
+public:
+
+ btSolve2LinearConstraint(btScalar tau,btScalar damping)
+ {
+ m_tau = tau;
+ m_damping = damping;
+ }
+ //
+ // solve unilateral constraint (equality, direct method)
+ //
+ void resolveUnilateralPairConstraint(
+ btRigidBody* body0,
+ btRigidBody* body1,
+
+ const btMatrix3x3& world2A,
+ const btMatrix3x3& world2B,
+
+ const btVector3& invInertiaADiag,
+ const btScalar invMassA,
+ const btVector3& linvelA,const btVector3& angvelA,
+ const btVector3& rel_posA1,
+ const btVector3& invInertiaBDiag,
+ const btScalar invMassB,
+ const btVector3& linvelB,const btVector3& angvelB,
+ const btVector3& rel_posA2,
+
+ btScalar depthA, const btVector3& normalA,
+ const btVector3& rel_posB1,const btVector3& rel_posB2,
+ btScalar depthB, const btVector3& normalB,
+ btScalar& imp0,btScalar& imp1);
+
+
+ //
+ // solving 2x2 lcp problem (inequality, direct solution )
+ //
+ void resolveBilateralPairConstraint(
+ btRigidBody* body0,
+ btRigidBody* body1,
+ const btMatrix3x3& world2A,
+ const btMatrix3x3& world2B,
+
+ const btVector3& invInertiaADiag,
+ const btScalar invMassA,
+ const btVector3& linvelA,const btVector3& angvelA,
+ const btVector3& rel_posA1,
+ const btVector3& invInertiaBDiag,
+ const btScalar invMassB,
+ const btVector3& linvelB,const btVector3& angvelB,
+ const btVector3& rel_posA2,
+
+ btScalar depthA, const btVector3& normalA,
+ const btVector3& rel_posB1,const btVector3& rel_posB2,
+ btScalar depthB, const btVector3& normalB,
+ btScalar& imp0,btScalar& imp1);
+
+/*
+ void resolveAngularConstraint( const btMatrix3x3& invInertiaAWS,
+ const btScalar invMassA,
+ const btVector3& linvelA,const btVector3& angvelA,
+ const btVector3& rel_posA1,
+ const btMatrix3x3& invInertiaBWS,
+ const btScalar invMassB,
+ const btVector3& linvelB,const btVector3& angvelB,
+ const btVector3& rel_posA2,
+
+ btScalar depthA, const btVector3& normalA,
+ const btVector3& rel_posB1,const btVector3& rel_posB2,
+ btScalar depthB, const btVector3& normalB,
+ btScalar& imp0,btScalar& imp1);
+
+*/
+
+};
+
+#endif //BT_SOLVE_2LINEAR_CONSTRAINT_H
diff --git a/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btSolverBody.h b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btSolverBody.h
new file mode 100644
index 0000000000..27ccefe416
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btSolverBody.h
@@ -0,0 +1,306 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_SOLVER_BODY_H
+#define BT_SOLVER_BODY_H
+
+class btRigidBody;
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btMatrix3x3.h"
+
+#include "LinearMath/btAlignedAllocator.h"
+#include "LinearMath/btTransformUtil.h"
+
+///Until we get other contributions, only use SIMD on Windows, when using Visual Studio 2008 or later, and not double precision
+#ifdef BT_USE_SSE
+#define USE_SIMD 1
+#endif //
+
+
+#ifdef USE_SIMD
+
+struct btSimdScalar
+{
+ SIMD_FORCE_INLINE btSimdScalar()
+ {
+
+ }
+
+ SIMD_FORCE_INLINE btSimdScalar(float fl)
+ :m_vec128 (_mm_set1_ps(fl))
+ {
+ }
+
+ SIMD_FORCE_INLINE btSimdScalar(__m128 v128)
+ :m_vec128(v128)
+ {
+ }
+ union
+ {
+ __m128 m_vec128;
+ float m_floats[4];
+ int m_ints[4];
+ btScalar m_unusedPadding;
+ };
+ SIMD_FORCE_INLINE __m128 get128()
+ {
+ return m_vec128;
+ }
+
+ SIMD_FORCE_INLINE const __m128 get128() const
+ {
+ return m_vec128;
+ }
+
+ SIMD_FORCE_INLINE void set128(__m128 v128)
+ {
+ m_vec128 = v128;
+ }
+
+ SIMD_FORCE_INLINE operator __m128()
+ {
+ return m_vec128;
+ }
+ SIMD_FORCE_INLINE operator const __m128() const
+ {
+ return m_vec128;
+ }
+
+ SIMD_FORCE_INLINE operator float() const
+ {
+ return m_floats[0];
+ }
+
+};
+
+///@brief Return the elementwise product of two btSimdScalar
+SIMD_FORCE_INLINE btSimdScalar
+operator*(const btSimdScalar& v1, const btSimdScalar& v2)
+{
+ return btSimdScalar(_mm_mul_ps(v1.get128(),v2.get128()));
+}
+
+///@brief Return the elementwise product of two btSimdScalar
+SIMD_FORCE_INLINE btSimdScalar
+operator+(const btSimdScalar& v1, const btSimdScalar& v2)
+{
+ return btSimdScalar(_mm_add_ps(v1.get128(),v2.get128()));
+}
+
+
+#else
+#define btSimdScalar btScalar
+#endif
+
+///The btSolverBody is an internal datastructure for the constraint solver. Only necessary data is packed to increase cache coherence/performance.
+ATTRIBUTE_ALIGNED16 (struct) btSolverBody
+{
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+ btTransform m_worldTransform;
+ btVector3 m_deltaLinearVelocity;
+ btVector3 m_deltaAngularVelocity;
+ btVector3 m_angularFactor;
+ btVector3 m_linearFactor;
+ btVector3 m_invMass;
+ btVector3 m_pushVelocity;
+ btVector3 m_turnVelocity;
+ btVector3 m_linearVelocity;
+ btVector3 m_angularVelocity;
+ btVector3 m_externalForceImpulse;
+ btVector3 m_externalTorqueImpulse;
+
+ btRigidBody* m_originalBody;
+ void setWorldTransform(const btTransform& worldTransform)
+ {
+ m_worldTransform = worldTransform;
+ }
+
+ const btTransform& getWorldTransform() const
+ {
+ return m_worldTransform;
+ }
+
+
+
+ SIMD_FORCE_INLINE void getVelocityInLocalPointNoDelta(const btVector3& rel_pos, btVector3& velocity ) const
+ {
+ if (m_originalBody)
+ velocity = m_linearVelocity + m_externalForceImpulse + (m_angularVelocity+m_externalTorqueImpulse).cross(rel_pos);
+ else
+ velocity.setValue(0,0,0);
+ }
+
+
+ SIMD_FORCE_INLINE void getVelocityInLocalPointObsolete(const btVector3& rel_pos, btVector3& velocity ) const
+ {
+ if (m_originalBody)
+ velocity = m_linearVelocity+m_deltaLinearVelocity + (m_angularVelocity+m_deltaAngularVelocity).cross(rel_pos);
+ else
+ velocity.setValue(0,0,0);
+ }
+
+ SIMD_FORCE_INLINE void getAngularVelocity(btVector3& angVel) const
+ {
+ if (m_originalBody)
+ angVel =m_angularVelocity+m_deltaAngularVelocity;
+ else
+ angVel.setValue(0,0,0);
+ }
+
+
+ //Optimization for the iterative solver: avoid calculating constant terms involving inertia, normal, relative position
+ SIMD_FORCE_INLINE void applyImpulse(const btVector3& linearComponent, const btVector3& angularComponent,const btScalar impulseMagnitude)
+ {
+ if (m_originalBody)
+ {
+ m_deltaLinearVelocity += linearComponent*impulseMagnitude*m_linearFactor;
+ m_deltaAngularVelocity += angularComponent*(impulseMagnitude*m_angularFactor);
+ }
+ }
+
+ SIMD_FORCE_INLINE void internalApplyPushImpulse(const btVector3& linearComponent, const btVector3& angularComponent,btScalar impulseMagnitude)
+ {
+ if (m_originalBody)
+ {
+ m_pushVelocity += linearComponent*impulseMagnitude*m_linearFactor;
+ m_turnVelocity += angularComponent*(impulseMagnitude*m_angularFactor);
+ }
+ }
+
+
+
+ const btVector3& getDeltaLinearVelocity() const
+ {
+ return m_deltaLinearVelocity;
+ }
+
+ const btVector3& getDeltaAngularVelocity() const
+ {
+ return m_deltaAngularVelocity;
+ }
+
+ const btVector3& getPushVelocity() const
+ {
+ return m_pushVelocity;
+ }
+
+ const btVector3& getTurnVelocity() const
+ {
+ return m_turnVelocity;
+ }
+
+
+ ////////////////////////////////////////////////
+ ///some internal methods, don't use them
+
+ btVector3& internalGetDeltaLinearVelocity()
+ {
+ return m_deltaLinearVelocity;
+ }
+
+ btVector3& internalGetDeltaAngularVelocity()
+ {
+ return m_deltaAngularVelocity;
+ }
+
+ const btVector3& internalGetAngularFactor() const
+ {
+ return m_angularFactor;
+ }
+
+ const btVector3& internalGetInvMass() const
+ {
+ return m_invMass;
+ }
+
+ void internalSetInvMass(const btVector3& invMass)
+ {
+ m_invMass = invMass;
+ }
+
+ btVector3& internalGetPushVelocity()
+ {
+ return m_pushVelocity;
+ }
+
+ btVector3& internalGetTurnVelocity()
+ {
+ return m_turnVelocity;
+ }
+
+ SIMD_FORCE_INLINE void internalGetVelocityInLocalPointObsolete(const btVector3& rel_pos, btVector3& velocity ) const
+ {
+ velocity = m_linearVelocity+m_deltaLinearVelocity + (m_angularVelocity+m_deltaAngularVelocity).cross(rel_pos);
+ }
+
+ SIMD_FORCE_INLINE void internalGetAngularVelocity(btVector3& angVel) const
+ {
+ angVel = m_angularVelocity+m_deltaAngularVelocity;
+ }
+
+
+ //Optimization for the iterative solver: avoid calculating constant terms involving inertia, normal, relative position
+ SIMD_FORCE_INLINE void internalApplyImpulse(const btVector3& linearComponent, const btVector3& angularComponent,const btScalar impulseMagnitude)
+ {
+ if (m_originalBody)
+ {
+ m_deltaLinearVelocity += linearComponent*impulseMagnitude*m_linearFactor;
+ m_deltaAngularVelocity += angularComponent*(impulseMagnitude*m_angularFactor);
+ }
+ }
+
+
+
+
+ void writebackVelocity()
+ {
+ if (m_originalBody)
+ {
+ m_linearVelocity +=m_deltaLinearVelocity;
+ m_angularVelocity += m_deltaAngularVelocity;
+
+ //m_originalBody->setCompanionId(-1);
+ }
+ }
+
+
+ void writebackVelocityAndTransform(btScalar timeStep, btScalar splitImpulseTurnErp)
+ {
+ (void) timeStep;
+ if (m_originalBody)
+ {
+ m_linearVelocity += m_deltaLinearVelocity;
+ m_angularVelocity += m_deltaAngularVelocity;
+
+ //correct the position/orientation based on push/turn recovery
+ btTransform newTransform;
+ if (m_pushVelocity[0]!=0.f || m_pushVelocity[1]!=0 || m_pushVelocity[2]!=0 || m_turnVelocity[0]!=0.f || m_turnVelocity[1]!=0 || m_turnVelocity[2]!=0)
+ {
+ // btQuaternion orn = m_worldTransform.getRotation();
+ btTransformUtil::integrateTransform(m_worldTransform,m_pushVelocity,m_turnVelocity*splitImpulseTurnErp,timeStep,newTransform);
+ m_worldTransform = newTransform;
+ }
+ //m_worldTransform.setRotation(orn);
+ //m_originalBody->setCompanionId(-1);
+ }
+ }
+
+
+
+};
+
+#endif //BT_SOLVER_BODY_H
+
+
diff --git a/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h
new file mode 100644
index 0000000000..5515e6b311
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h
@@ -0,0 +1,80 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_SOLVER_CONSTRAINT_H
+#define BT_SOLVER_CONSTRAINT_H
+
+class btRigidBody;
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btMatrix3x3.h"
+#include "btJacobianEntry.h"
+#include "LinearMath/btAlignedObjectArray.h"
+
+//#define NO_FRICTION_TANGENTIALS 1
+#include "btSolverBody.h"
+
+
+///1D constraint along a normal axis between bodyA and bodyB. It can be combined to solve contact and friction constraints.
+ATTRIBUTE_ALIGNED16 (struct) btSolverConstraint
+{
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ btVector3 m_relpos1CrossNormal;
+ btVector3 m_contactNormal1;
+
+ btVector3 m_relpos2CrossNormal;
+ btVector3 m_contactNormal2; //usually m_contactNormal2 == -m_contactNormal1, but not always
+
+ btVector3 m_angularComponentA;
+ btVector3 m_angularComponentB;
+
+ mutable btSimdScalar m_appliedPushImpulse;
+ mutable btSimdScalar m_appliedImpulse;
+
+ btScalar m_friction;
+ btScalar m_jacDiagABInv;
+ btScalar m_rhs;
+ btScalar m_cfm;
+
+ btScalar m_lowerLimit;
+ btScalar m_upperLimit;
+ btScalar m_rhsPenetration;
+ union
+ {
+ void* m_originalContactPoint;
+ btScalar m_unusedPadding4;
+ int m_numRowsForNonContactConstraint;
+ };
+
+ int m_overrideNumSolverIterations;
+ int m_frictionIndex;
+ int m_solverBodyIdA;
+ int m_solverBodyIdB;
+
+
+ enum btSolverConstraintType
+ {
+ BT_SOLVER_CONTACT_1D = 0,
+ BT_SOLVER_FRICTION_1D
+ };
+};
+
+typedef btAlignedObjectArray<btSolverConstraint> btConstraintArray;
+
+
+#endif //BT_SOLVER_CONSTRAINT_H
+
+
+
diff --git a/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp
new file mode 100644
index 0000000000..9f04f28053
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp
@@ -0,0 +1,222 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "btTypedConstraint.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "LinearMath/btSerializer.h"
+
+
+#define DEFAULT_DEBUGDRAW_SIZE btScalar(0.05f)
+
+btTypedConstraint::btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA)
+:btTypedObject(type),
+m_userConstraintType(-1),
+m_userConstraintPtr((void*)-1),
+m_breakingImpulseThreshold(SIMD_INFINITY),
+m_isEnabled(true),
+m_needsFeedback(false),
+m_overrideNumSolverIterations(-1),
+m_rbA(rbA),
+m_rbB(getFixedBody()),
+m_appliedImpulse(btScalar(0.)),
+m_dbgDrawSize(DEFAULT_DEBUGDRAW_SIZE),
+m_jointFeedback(0)
+{
+}
+
+
+btTypedConstraint::btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA,btRigidBody& rbB)
+:btTypedObject(type),
+m_userConstraintType(-1),
+m_userConstraintPtr((void*)-1),
+m_breakingImpulseThreshold(SIMD_INFINITY),
+m_isEnabled(true),
+m_needsFeedback(false),
+m_overrideNumSolverIterations(-1),
+m_rbA(rbA),
+m_rbB(rbB),
+m_appliedImpulse(btScalar(0.)),
+m_dbgDrawSize(DEFAULT_DEBUGDRAW_SIZE),
+m_jointFeedback(0)
+{
+}
+
+
+
+
+btScalar btTypedConstraint::getMotorFactor(btScalar pos, btScalar lowLim, btScalar uppLim, btScalar vel, btScalar timeFact)
+{
+ if(lowLim > uppLim)
+ {
+ return btScalar(1.0f);
+ }
+ else if(lowLim == uppLim)
+ {
+ return btScalar(0.0f);
+ }
+ btScalar lim_fact = btScalar(1.0f);
+ btScalar delta_max = vel / timeFact;
+ if(delta_max < btScalar(0.0f))
+ {
+ if((pos >= lowLim) && (pos < (lowLim - delta_max)))
+ {
+ lim_fact = (lowLim - pos) / delta_max;
+ }
+ else if(pos < lowLim)
+ {
+ lim_fact = btScalar(0.0f);
+ }
+ else
+ {
+ lim_fact = btScalar(1.0f);
+ }
+ }
+ else if(delta_max > btScalar(0.0f))
+ {
+ if((pos <= uppLim) && (pos > (uppLim - delta_max)))
+ {
+ lim_fact = (uppLim - pos) / delta_max;
+ }
+ else if(pos > uppLim)
+ {
+ lim_fact = btScalar(0.0f);
+ }
+ else
+ {
+ lim_fact = btScalar(1.0f);
+ }
+ }
+ else
+ {
+ lim_fact = btScalar(0.0f);
+ }
+ return lim_fact;
+}
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+const char* btTypedConstraint::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+ btTypedConstraintData2* tcd = (btTypedConstraintData2*) dataBuffer;
+
+ tcd->m_rbA = (btRigidBodyData*)serializer->getUniquePointer(&m_rbA);
+ tcd->m_rbB = (btRigidBodyData*)serializer->getUniquePointer(&m_rbB);
+ char* name = (char*) serializer->findNameForPointer(this);
+ tcd->m_name = (char*)serializer->getUniquePointer(name);
+ if (tcd->m_name)
+ {
+ serializer->serializeName(name);
+ }
+
+ tcd->m_objectType = m_objectType;
+ tcd->m_needsFeedback = m_needsFeedback;
+ tcd->m_overrideNumSolverIterations = m_overrideNumSolverIterations;
+ tcd->m_breakingImpulseThreshold = m_breakingImpulseThreshold;
+ tcd->m_isEnabled = m_isEnabled? 1: 0;
+
+ tcd->m_userConstraintId =m_userConstraintId;
+ tcd->m_userConstraintType =m_userConstraintType;
+
+ tcd->m_appliedImpulse = m_appliedImpulse;
+ tcd->m_dbgDrawSize = m_dbgDrawSize;
+
+ tcd->m_disableCollisionsBetweenLinkedBodies = false;
+
+ int i;
+ for (i=0;i<m_rbA.getNumConstraintRefs();i++)
+ if (m_rbA.getConstraintRef(i) == this)
+ tcd->m_disableCollisionsBetweenLinkedBodies = true;
+ for (i=0;i<m_rbB.getNumConstraintRefs();i++)
+ if (m_rbB.getConstraintRef(i) == this)
+ tcd->m_disableCollisionsBetweenLinkedBodies = true;
+
+ return btTypedConstraintDataName;
+}
+
+btRigidBody& btTypedConstraint::getFixedBody()
+{
+ static btRigidBody s_fixed(0, 0,0);
+ s_fixed.setMassProps(btScalar(0.),btVector3(btScalar(0.),btScalar(0.),btScalar(0.)));
+ return s_fixed;
+}
+
+
+void btAngularLimit::set(btScalar low, btScalar high, btScalar _softness, btScalar _biasFactor, btScalar _relaxationFactor)
+{
+ m_halfRange = (high - low) / 2.0f;
+ m_center = btNormalizeAngle(low + m_halfRange);
+ m_softness = _softness;
+ m_biasFactor = _biasFactor;
+ m_relaxationFactor = _relaxationFactor;
+}
+
+void btAngularLimit::test(const btScalar angle)
+{
+ m_correction = 0.0f;
+ m_sign = 0.0f;
+ m_solveLimit = false;
+
+ if (m_halfRange >= 0.0f)
+ {
+ btScalar deviation = btNormalizeAngle(angle - m_center);
+ if (deviation < -m_halfRange)
+ {
+ m_solveLimit = true;
+ m_correction = - (deviation + m_halfRange);
+ m_sign = +1.0f;
+ }
+ else if (deviation > m_halfRange)
+ {
+ m_solveLimit = true;
+ m_correction = m_halfRange - deviation;
+ m_sign = -1.0f;
+ }
+ }
+}
+
+
+btScalar btAngularLimit::getError() const
+{
+ return m_correction * m_sign;
+}
+
+void btAngularLimit::fit(btScalar& angle) const
+{
+ if (m_halfRange > 0.0f)
+ {
+ btScalar relativeAngle = btNormalizeAngle(angle - m_center);
+ if (!btEqual(relativeAngle, m_halfRange))
+ {
+ if (relativeAngle > 0.0f)
+ {
+ angle = getHigh();
+ }
+ else
+ {
+ angle = getLow();
+ }
+ }
+ }
+}
+
+btScalar btAngularLimit::getLow() const
+{
+ return btNormalizeAngle(m_center - m_halfRange);
+}
+
+btScalar btAngularLimit::getHigh() const
+{
+ return btNormalizeAngle(m_center + m_halfRange);
+}
diff --git a/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h
new file mode 100644
index 0000000000..8a2a2d1ae7
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h
@@ -0,0 +1,541 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2010 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_TYPED_CONSTRAINT_H
+#define BT_TYPED_CONSTRAINT_H
+
+
+#include "LinearMath/btScalar.h"
+#include "btSolverConstraint.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define btTypedConstraintData2 btTypedConstraintDoubleData
+#define btTypedConstraintDataName "btTypedConstraintDoubleData"
+#else
+#define btTypedConstraintData2 btTypedConstraintFloatData
+#define btTypedConstraintDataName "btTypedConstraintFloatData"
+#endif //BT_USE_DOUBLE_PRECISION
+
+
+class btSerializer;
+
+//Don't change any of the existing enum values, so add enum types at the end for serialization compatibility
+enum btTypedConstraintType
+{
+ POINT2POINT_CONSTRAINT_TYPE=3,
+ HINGE_CONSTRAINT_TYPE,
+ CONETWIST_CONSTRAINT_TYPE,
+ D6_CONSTRAINT_TYPE,
+ SLIDER_CONSTRAINT_TYPE,
+ CONTACT_CONSTRAINT_TYPE,
+ D6_SPRING_CONSTRAINT_TYPE,
+ GEAR_CONSTRAINT_TYPE,
+ FIXED_CONSTRAINT_TYPE,
+ D6_SPRING_2_CONSTRAINT_TYPE,
+ MAX_CONSTRAINT_TYPE
+};
+
+
+enum btConstraintParams
+{
+ BT_CONSTRAINT_ERP=1,
+ BT_CONSTRAINT_STOP_ERP,
+ BT_CONSTRAINT_CFM,
+ BT_CONSTRAINT_STOP_CFM
+};
+
+#if 1
+ #define btAssertConstrParams(_par) btAssert(_par)
+#else
+ #define btAssertConstrParams(_par)
+#endif
+
+
+ATTRIBUTE_ALIGNED16(struct) btJointFeedback
+{
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+ btVector3 m_appliedForceBodyA;
+ btVector3 m_appliedTorqueBodyA;
+ btVector3 m_appliedForceBodyB;
+ btVector3 m_appliedTorqueBodyB;
+};
+
+
+///TypedConstraint is the baseclass for Bullet constraints and vehicles
+ATTRIBUTE_ALIGNED16(class) btTypedConstraint : public btTypedObject
+{
+ int m_userConstraintType;
+
+ union
+ {
+ int m_userConstraintId;
+ void* m_userConstraintPtr;
+ };
+
+ btScalar m_breakingImpulseThreshold;
+ bool m_isEnabled;
+ bool m_needsFeedback;
+ int m_overrideNumSolverIterations;
+
+
+ btTypedConstraint& operator=(btTypedConstraint& other)
+ {
+ btAssert(0);
+ (void) other;
+ return *this;
+ }
+
+protected:
+ btRigidBody& m_rbA;
+ btRigidBody& m_rbB;
+ btScalar m_appliedImpulse;
+ btScalar m_dbgDrawSize;
+ btJointFeedback* m_jointFeedback;
+
+ ///internal method used by the constraint solver, don't use them directly
+ btScalar getMotorFactor(btScalar pos, btScalar lowLim, btScalar uppLim, btScalar vel, btScalar timeFact);
+
+
+public:
+
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ virtual ~btTypedConstraint() {};
+ btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA);
+ btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA,btRigidBody& rbB);
+
+ struct btConstraintInfo1 {
+ int m_numConstraintRows,nub;
+ };
+
+ static btRigidBody& getFixedBody();
+
+ struct btConstraintInfo2 {
+ // integrator parameters: frames per second (1/stepsize), default error
+ // reduction parameter (0..1).
+ btScalar fps,erp;
+
+ // for the first and second body, pointers to two (linear and angular)
+ // n*3 jacobian sub matrices, stored by rows. these matrices will have
+ // been initialized to 0 on entry. if the second body is zero then the
+ // J2xx pointers may be 0.
+ btScalar *m_J1linearAxis,*m_J1angularAxis,*m_J2linearAxis,*m_J2angularAxis;
+
+ // elements to jump from one row to the next in J's
+ int rowskip;
+
+ // right hand sides of the equation J*v = c + cfm * lambda. cfm is the
+ // "constraint force mixing" vector. c is set to zero on entry, cfm is
+ // set to a constant value (typically very small or zero) value on entry.
+ btScalar *m_constraintError,*cfm;
+
+ // lo and hi limits for variables (set to -/+ infinity on entry).
+ btScalar *m_lowerLimit,*m_upperLimit;
+
+ // number of solver iterations
+ int m_numIterations;
+
+ //damping of the velocity
+ btScalar m_damping;
+ };
+
+ int getOverrideNumSolverIterations() const
+ {
+ return m_overrideNumSolverIterations;
+ }
+
+ ///override the number of constraint solver iterations used to solve this constraint
+ ///-1 will use the default number of iterations, as specified in SolverInfo.m_numIterations
+ void setOverrideNumSolverIterations(int overideNumIterations)
+ {
+ m_overrideNumSolverIterations = overideNumIterations;
+ }
+
+ ///internal method used by the constraint solver, don't use them directly
+ virtual void buildJacobian() {};
+
+ ///internal method used by the constraint solver, don't use them directly
+ virtual void setupSolverConstraint(btConstraintArray& ca, int solverBodyA,int solverBodyB, btScalar timeStep)
+ {
+ (void)ca;
+ (void)solverBodyA;
+ (void)solverBodyB;
+ (void)timeStep;
+ }
+
+ ///internal method used by the constraint solver, don't use them directly
+ virtual void getInfo1 (btConstraintInfo1* info)=0;
+
+ ///internal method used by the constraint solver, don't use them directly
+ virtual void getInfo2 (btConstraintInfo2* info)=0;
+
+ ///internal method used by the constraint solver, don't use them directly
+ void internalSetAppliedImpulse(btScalar appliedImpulse)
+ {
+ m_appliedImpulse = appliedImpulse;
+ }
+ ///internal method used by the constraint solver, don't use them directly
+ btScalar internalGetAppliedImpulse()
+ {
+ return m_appliedImpulse;
+ }
+
+
+ btScalar getBreakingImpulseThreshold() const
+ {
+ return m_breakingImpulseThreshold;
+ }
+
+ void setBreakingImpulseThreshold(btScalar threshold)
+ {
+ m_breakingImpulseThreshold = threshold;
+ }
+
+ bool isEnabled() const
+ {
+ return m_isEnabled;
+ }
+
+ void setEnabled(bool enabled)
+ {
+ m_isEnabled=enabled;
+ }
+
+
+ ///internal method used by the constraint solver, don't use them directly
+ virtual void solveConstraintObsolete(btSolverBody& /*bodyA*/,btSolverBody& /*bodyB*/,btScalar /*timeStep*/) {};
+
+
+ const btRigidBody& getRigidBodyA() const
+ {
+ return m_rbA;
+ }
+ const btRigidBody& getRigidBodyB() const
+ {
+ return m_rbB;
+ }
+
+ btRigidBody& getRigidBodyA()
+ {
+ return m_rbA;
+ }
+ btRigidBody& getRigidBodyB()
+ {
+ return m_rbB;
+ }
+
+ int getUserConstraintType() const
+ {
+ return m_userConstraintType ;
+ }
+
+ void setUserConstraintType(int userConstraintType)
+ {
+ m_userConstraintType = userConstraintType;
+ };
+
+ void setUserConstraintId(int uid)
+ {
+ m_userConstraintId = uid;
+ }
+
+ int getUserConstraintId() const
+ {
+ return m_userConstraintId;
+ }
+
+ void setUserConstraintPtr(void* ptr)
+ {
+ m_userConstraintPtr = ptr;
+ }
+
+ void* getUserConstraintPtr()
+ {
+ return m_userConstraintPtr;
+ }
+
+ void setJointFeedback(btJointFeedback* jointFeedback)
+ {
+ m_jointFeedback = jointFeedback;
+ }
+
+ const btJointFeedback* getJointFeedback() const
+ {
+ return m_jointFeedback;
+ }
+
+ btJointFeedback* getJointFeedback()
+ {
+ return m_jointFeedback;
+ }
+
+
+ int getUid() const
+ {
+ return m_userConstraintId;
+ }
+
+ bool needsFeedback() const
+ {
+ return m_needsFeedback;
+ }
+
+ ///enableFeedback will allow to read the applied linear and angular impulse
+ ///use getAppliedImpulse, getAppliedLinearImpulse and getAppliedAngularImpulse to read feedback information
+ void enableFeedback(bool needsFeedback)
+ {
+ m_needsFeedback = needsFeedback;
+ }
+
+ ///getAppliedImpulse is an estimated total applied impulse.
+ ///This feedback could be used to determine breaking constraints or playing sounds.
+ btScalar getAppliedImpulse() const
+ {
+ btAssert(m_needsFeedback);
+ return m_appliedImpulse;
+ }
+
+ btTypedConstraintType getConstraintType () const
+ {
+ return btTypedConstraintType(m_objectType);
+ }
+
+ void setDbgDrawSize(btScalar dbgDrawSize)
+ {
+ m_dbgDrawSize = dbgDrawSize;
+ }
+ btScalar getDbgDrawSize()
+ {
+ return m_dbgDrawSize;
+ }
+
+ ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
+ ///If no axis is provided, it uses the default axis for this constraint.
+ virtual void setParam(int num, btScalar value, int axis = -1) = 0;
+
+ ///return the local value of parameter
+ virtual btScalar getParam(int num, int axis = -1) const = 0;
+
+ virtual int calculateSerializeBufferSize() const;
+
+ ///fills the dataBuffer and returns the struct name (and 0 on failure)
+ virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
+
+};
+
+// returns angle in range [-SIMD_2_PI, SIMD_2_PI], closest to one of the limits
+// all arguments should be normalized angles (i.e. in range [-SIMD_PI, SIMD_PI])
+SIMD_FORCE_INLINE btScalar btAdjustAngleToLimits(btScalar angleInRadians, btScalar angleLowerLimitInRadians, btScalar angleUpperLimitInRadians)
+{
+ if(angleLowerLimitInRadians >= angleUpperLimitInRadians)
+ {
+ return angleInRadians;
+ }
+ else if(angleInRadians < angleLowerLimitInRadians)
+ {
+ btScalar diffLo = btFabs(btNormalizeAngle(angleLowerLimitInRadians - angleInRadians));
+ btScalar diffHi = btFabs(btNormalizeAngle(angleUpperLimitInRadians - angleInRadians));
+ return (diffLo < diffHi) ? angleInRadians : (angleInRadians + SIMD_2_PI);
+ }
+ else if(angleInRadians > angleUpperLimitInRadians)
+ {
+ btScalar diffHi = btFabs(btNormalizeAngle(angleInRadians - angleUpperLimitInRadians));
+ btScalar diffLo = btFabs(btNormalizeAngle(angleInRadians - angleLowerLimitInRadians));
+ return (diffLo < diffHi) ? (angleInRadians - SIMD_2_PI) : angleInRadians;
+ }
+ else
+ {
+ return angleInRadians;
+ }
+}
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btTypedConstraintFloatData
+{
+ btRigidBodyFloatData *m_rbA;
+ btRigidBodyFloatData *m_rbB;
+ char *m_name;
+
+ int m_objectType;
+ int m_userConstraintType;
+ int m_userConstraintId;
+ int m_needsFeedback;
+
+ float m_appliedImpulse;
+ float m_dbgDrawSize;
+
+ int m_disableCollisionsBetweenLinkedBodies;
+ int m_overrideNumSolverIterations;
+
+ float m_breakingImpulseThreshold;
+ int m_isEnabled;
+
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+
+#define BT_BACKWARDS_COMPATIBLE_SERIALIZATION
+#ifdef BT_BACKWARDS_COMPATIBLE_SERIALIZATION
+///this structure is not used, except for loading pre-2.82 .bullet files
+struct btTypedConstraintData
+{
+ btRigidBodyData *m_rbA;
+ btRigidBodyData *m_rbB;
+ char *m_name;
+
+ int m_objectType;
+ int m_userConstraintType;
+ int m_userConstraintId;
+ int m_needsFeedback;
+
+ float m_appliedImpulse;
+ float m_dbgDrawSize;
+
+ int m_disableCollisionsBetweenLinkedBodies;
+ int m_overrideNumSolverIterations;
+
+ float m_breakingImpulseThreshold;
+ int m_isEnabled;
+
+};
+#endif //BACKWARDS_COMPATIBLE
+
+struct btTypedConstraintDoubleData
+{
+ btRigidBodyDoubleData *m_rbA;
+ btRigidBodyDoubleData *m_rbB;
+ char *m_name;
+
+ int m_objectType;
+ int m_userConstraintType;
+ int m_userConstraintId;
+ int m_needsFeedback;
+
+ double m_appliedImpulse;
+ double m_dbgDrawSize;
+
+ int m_disableCollisionsBetweenLinkedBodies;
+ int m_overrideNumSolverIterations;
+
+ double m_breakingImpulseThreshold;
+ int m_isEnabled;
+ char padding[4];
+
+};
+
+
+SIMD_FORCE_INLINE int btTypedConstraint::calculateSerializeBufferSize() const
+{
+ return sizeof(btTypedConstraintData2);
+}
+
+
+
+class btAngularLimit
+{
+private:
+ btScalar
+ m_center,
+ m_halfRange,
+ m_softness,
+ m_biasFactor,
+ m_relaxationFactor,
+ m_correction,
+ m_sign;
+
+ bool
+ m_solveLimit;
+
+public:
+ /// Default constructor initializes limit as inactive, allowing free constraint movement
+ btAngularLimit()
+ :m_center(0.0f),
+ m_halfRange(-1.0f),
+ m_softness(0.9f),
+ m_biasFactor(0.3f),
+ m_relaxationFactor(1.0f),
+ m_correction(0.0f),
+ m_sign(0.0f),
+ m_solveLimit(false)
+ {}
+
+ /// Sets all limit's parameters.
+ /// When low > high limit becomes inactive.
+ /// When high - low > 2PI limit is ineffective too becouse no angle can exceed the limit
+ void set(btScalar low, btScalar high, btScalar _softness = 0.9f, btScalar _biasFactor = 0.3f, btScalar _relaxationFactor = 1.0f);
+
+ /// Checks conastaint angle against limit. If limit is active and the angle violates the limit
+ /// correction is calculated.
+ void test(const btScalar angle);
+
+ /// Returns limit's softness
+ inline btScalar getSoftness() const
+ {
+ return m_softness;
+ }
+
+ /// Returns limit's bias factor
+ inline btScalar getBiasFactor() const
+ {
+ return m_biasFactor;
+ }
+
+ /// Returns limit's relaxation factor
+ inline btScalar getRelaxationFactor() const
+ {
+ return m_relaxationFactor;
+ }
+
+ /// Returns correction value evaluated when test() was invoked
+ inline btScalar getCorrection() const
+ {
+ return m_correction;
+ }
+
+ /// Returns sign value evaluated when test() was invoked
+ inline btScalar getSign() const
+ {
+ return m_sign;
+ }
+
+ /// Gives half of the distance between min and max limit angle
+ inline btScalar getHalfRange() const
+ {
+ return m_halfRange;
+ }
+
+ /// Returns true when the last test() invocation recognized limit violation
+ inline bool isLimit() const
+ {
+ return m_solveLimit;
+ }
+
+ /// Checks given angle against limit. If limit is active and angle doesn't fit it, the angle
+ /// returned is modified so it equals to the limit closest to given angle.
+ void fit(btScalar& angle) const;
+
+ /// Returns correction value multiplied by sign value
+ btScalar getError() const;
+
+ btScalar getLow() const;
+
+ btScalar getHigh() const;
+
+};
+
+
+
+#endif //BT_TYPED_CONSTRAINT_H
diff --git a/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp
new file mode 100644
index 0000000000..b009f41aec
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp
@@ -0,0 +1,87 @@
+/*
+Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org
+Copyright (C) 2006, 2007 Sony Computer Entertainment Inc.
+
+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 "btUniversalConstraint.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "LinearMath/btTransformUtil.h"
+
+
+
+#define UNIV_EPS btScalar(0.01f)
+
+
+// constructor
+// anchor, axis1 and axis2 are in world coordinate system
+// axis1 must be orthogonal to axis2
+btUniversalConstraint::btUniversalConstraint(btRigidBody& rbA, btRigidBody& rbB, const btVector3& anchor, const btVector3& axis1, const btVector3& axis2)
+: btGeneric6DofConstraint(rbA, rbB, btTransform::getIdentity(), btTransform::getIdentity(), true),
+ m_anchor(anchor),
+ m_axis1(axis1),
+ m_axis2(axis2)
+{
+ // build frame basis
+ // 6DOF constraint uses Euler angles and to define limits
+ // it is assumed that rotational order is :
+ // Z - first, allowed limits are (-PI,PI);
+ // new position of Y - second (allowed limits are (-PI/2 + epsilon, PI/2 - epsilon), where epsilon is a small positive number
+ // used to prevent constraint from instability on poles;
+ // new position of X, allowed limits are (-PI,PI);
+ // So to simulate ODE Universal joint we should use parent axis as Z, child axis as Y and limit all other DOFs
+ // Build the frame in world coordinate system first
+ btVector3 zAxis = m_axis1.normalize();
+ btVector3 yAxis = m_axis2.normalize();
+ btVector3 xAxis = yAxis.cross(zAxis); // we want right coordinate system
+ btTransform frameInW;
+ frameInW.setIdentity();
+ frameInW.getBasis().setValue( xAxis[0], yAxis[0], zAxis[0],
+ xAxis[1], yAxis[1], zAxis[1],
+ xAxis[2], yAxis[2], zAxis[2]);
+ frameInW.setOrigin(anchor);
+ // now get constraint frame in local coordinate systems
+ m_frameInA = rbA.getCenterOfMassTransform().inverse() * frameInW;
+ m_frameInB = rbB.getCenterOfMassTransform().inverse() * frameInW;
+ // sei limits
+ setLinearLowerLimit(btVector3(0., 0., 0.));
+ setLinearUpperLimit(btVector3(0., 0., 0.));
+ setAngularLowerLimit(btVector3(0.f, -SIMD_HALF_PI + UNIV_EPS, -SIMD_PI + UNIV_EPS));
+ setAngularUpperLimit(btVector3(0.f, SIMD_HALF_PI - UNIV_EPS, SIMD_PI - UNIV_EPS));
+}
+
+void btUniversalConstraint::setAxis(const btVector3& axis1,const btVector3& axis2)
+{
+ m_axis1 = axis1;
+ m_axis2 = axis2;
+
+ btVector3 zAxis = axis1.normalized();
+ btVector3 yAxis = axis2.normalized();
+ btVector3 xAxis = yAxis.cross(zAxis); // we want right coordinate system
+
+ btTransform frameInW;
+ frameInW.setIdentity();
+ frameInW.getBasis().setValue( xAxis[0], yAxis[0], zAxis[0],
+ xAxis[1], yAxis[1], zAxis[1],
+ xAxis[2], yAxis[2], zAxis[2]);
+ frameInW.setOrigin(m_anchor);
+
+ // now get constraint frame in local coordinate systems
+ m_frameInA = m_rbA.getCenterOfMassTransform().inverse() * frameInW;
+ m_frameInB = m_rbB.getCenterOfMassTransform().inverse() * frameInW;
+
+ calculateTransforms();
+}
+
+
diff --git a/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.h b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.h
new file mode 100644
index 0000000000..9e70841043
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.h
@@ -0,0 +1,65 @@
+/*
+Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org
+Copyright (C) 2006, 2007 Sony Computer Entertainment Inc.
+
+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_UNIVERSAL_CONSTRAINT_H
+#define BT_UNIVERSAL_CONSTRAINT_H
+
+
+
+#include "LinearMath/btVector3.h"
+#include "btTypedConstraint.h"
+#include "btGeneric6DofConstraint.h"
+
+
+
+/// Constraint similar to ODE Universal Joint
+/// has 2 rotatioonal degrees of freedom, similar to Euler rotations around Z (axis 1)
+/// and Y (axis 2)
+/// Description from ODE manual :
+/// "Given axis 1 on body 1, and axis 2 on body 2 that is perpendicular to axis 1, it keeps them perpendicular.
+/// In other words, rotation of the two bodies about the direction perpendicular to the two axes will be equal."
+
+ATTRIBUTE_ALIGNED16(class) btUniversalConstraint : public btGeneric6DofConstraint
+{
+protected:
+ btVector3 m_anchor;
+ btVector3 m_axis1;
+ btVector3 m_axis2;
+public:
+
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ // constructor
+ // anchor, axis1 and axis2 are in world coordinate system
+ // axis1 must be orthogonal to axis2
+ btUniversalConstraint(btRigidBody& rbA, btRigidBody& rbB, const btVector3& anchor, const btVector3& axis1, const btVector3& axis2);
+ // access
+ const btVector3& getAnchor() { return m_calculatedTransformA.getOrigin(); }
+ const btVector3& getAnchor2() { return m_calculatedTransformB.getOrigin(); }
+ const btVector3& getAxis1() { return m_axis1; }
+ const btVector3& getAxis2() { return m_axis2; }
+ btScalar getAngle1() { return getAngle(2); }
+ btScalar getAngle2() { return getAngle(1); }
+ // limits
+ void setUpperLimit(btScalar ang1max, btScalar ang2max) { setAngularUpperLimit(btVector3(0.f, ang1max, ang2max)); }
+ void setLowerLimit(btScalar ang1min, btScalar ang2min) { setAngularLowerLimit(btVector3(0.f, ang1min, ang2min)); }
+
+ void setAxis( const btVector3& axis1, const btVector3& axis2);
+};
+
+
+
+#endif // BT_UNIVERSAL_CONSTRAINT_H
+
diff --git a/thirdparty/bullet/src/BulletDynamics/Dynamics/btActionInterface.h b/thirdparty/bullet/src/BulletDynamics/Dynamics/btActionInterface.h
new file mode 100644
index 0000000000..e1fea3a49c
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/Dynamics/btActionInterface.h
@@ -0,0 +1,46 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef _BT_ACTION_INTERFACE_H
+#define _BT_ACTION_INTERFACE_H
+
+class btIDebugDraw;
+class btCollisionWorld;
+
+#include "LinearMath/btScalar.h"
+#include "btRigidBody.h"
+
+///Basic interface to allow actions such as vehicles and characters to be updated inside a btDynamicsWorld
+class btActionInterface
+{
+protected:
+
+ static btRigidBody& getFixedBody();
+
+
+public:
+
+ virtual ~btActionInterface()
+ {
+ }
+
+ virtual void updateAction( btCollisionWorld* collisionWorld, btScalar deltaTimeStep)=0;
+
+ virtual void debugDraw(btIDebugDraw* debugDrawer) = 0;
+
+};
+
+#endif //_BT_ACTION_INTERFACE_H
+
diff --git a/thirdparty/bullet/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp b/thirdparty/bullet/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp
new file mode 100644
index 0000000000..a196d4522e
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp
@@ -0,0 +1,1538 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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 "btDiscreteDynamicsWorld.h"
+
+//collision detection
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h"
+#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
+#include "BulletCollision/CollisionShapes/btCollisionShape.h"
+#include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h"
+#include "LinearMath/btTransformUtil.h"
+#include "LinearMath/btQuickprof.h"
+
+//rigidbody & constraints
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h"
+#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h"
+#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btHingeConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btConeTwistConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h"
+#include "BulletDynamics/ConstraintSolver/btSliderConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btContactConstraint.h"
+
+
+#include "LinearMath/btIDebugDraw.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"
+
+
+#include "BulletDynamics/Dynamics/btActionInterface.h"
+#include "LinearMath/btQuickprof.h"
+#include "LinearMath/btMotionState.h"
+
+#include "LinearMath/btSerializer.h"
+
+#if 0
+btAlignedObjectArray<btVector3> debugContacts;
+btAlignedObjectArray<btVector3> debugNormals;
+int startHit=2;
+int firstHit=startHit;
+#endif
+
+SIMD_FORCE_INLINE int btGetConstraintIslandId(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 btSortConstraintOnIslandPredicate
+{
+ public:
+
+ bool operator() ( const btTypedConstraint* lhs, const btTypedConstraint* rhs ) const
+ {
+ int rIslandId0,lIslandId0;
+ rIslandId0 = btGetConstraintIslandId(rhs);
+ lIslandId0 = btGetConstraintIslandId(lhs);
+ return lIslandId0 < rIslandId0;
+ }
+};
+
+struct InplaceSolverIslandCallback : public btSimulationIslandManager::IslandCallback
+{
+ btContactSolverInfo* m_solverInfo;
+ btConstraintSolver* m_solver;
+ btTypedConstraint** m_sortedConstraints;
+ int m_numConstraints;
+ btIDebugDraw* m_debugDrawer;
+ btDispatcher* m_dispatcher;
+
+ btAlignedObjectArray<btCollisionObject*> m_bodies;
+ btAlignedObjectArray<btPersistentManifold*> m_manifolds;
+ btAlignedObjectArray<btTypedConstraint*> m_constraints;
+
+
+ InplaceSolverIslandCallback(
+ btConstraintSolver* solver,
+ btStackAlloc* stackAlloc,
+ btDispatcher* dispatcher)
+ :m_solverInfo(NULL),
+ m_solver(solver),
+ m_sortedConstraints(NULL),
+ m_numConstraints(0),
+ m_debugDrawer(NULL),
+ m_dispatcher(dispatcher)
+ {
+
+ }
+
+ InplaceSolverIslandCallback& operator=(InplaceSolverIslandCallback& other)
+ {
+ btAssert(0);
+ (void)other;
+ return *this;
+ }
+
+ SIMD_FORCE_INLINE void setup ( btContactSolverInfo* solverInfo, btTypedConstraint** sortedConstraints, int numConstraints, btIDebugDraw* debugDrawer)
+ {
+ btAssert(solverInfo);
+ m_solverInfo = solverInfo;
+ m_sortedConstraints = sortedConstraints;
+ m_numConstraints = numConstraints;
+ m_debugDrawer = debugDrawer;
+ m_bodies.resize (0);
+ m_manifolds.resize (0);
+ m_constraints.resize (0);
+ }
+
+
+ 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->solveGroup( bodies,numBodies,manifolds, numManifolds,&m_sortedConstraints[0],m_numConstraints,*m_solverInfo,m_debugDrawer,m_dispatcher);
+ } else
+ {
+ //also add all non-contact constraints/joints for this island
+ btTypedConstraint** startConstraint = 0;
+ int numCurConstraints = 0;
+ int i;
+
+ //find the first constraint for this island
+ for (i=0;i<m_numConstraints;i++)
+ {
+ if (btGetConstraintIslandId(m_sortedConstraints[i]) == islandId)
+ {
+ startConstraint = &m_sortedConstraints[i];
+ break;
+ }
+ }
+ //count the number of constraints in this island
+ for (;i<m_numConstraints;i++)
+ {
+ if (btGetConstraintIslandId(m_sortedConstraints[i]) == islandId)
+ {
+ numCurConstraints++;
+ }
+ }
+
+ 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]);
+ if ((m_constraints.size()+m_manifolds.size())>m_solverInfo->m_minimumSolverBatchSize)
+ {
+ processConstraints();
+ } else
+ {
+ //printf("deferred\n");
+ }
+ }
+ }
+ }
+ void processConstraints()
+ {
+
+ 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;
+
+ m_solver->solveGroup( bodies,m_bodies.size(),manifold, m_manifolds.size(),constraints, m_constraints.size() ,*m_solverInfo,m_debugDrawer,m_dispatcher);
+ m_bodies.resize(0);
+ m_manifolds.resize(0);
+ m_constraints.resize(0);
+
+ }
+
+};
+
+
+
+btDiscreteDynamicsWorld::btDiscreteDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration)
+:btDynamicsWorld(dispatcher,pairCache,collisionConfiguration),
+m_sortedConstraints (),
+m_solverIslandCallback ( NULL ),
+m_constraintSolver(constraintSolver),
+m_gravity(0,-10,0),
+m_localTime(0),
+m_fixedTimeStep(0),
+m_synchronizeAllMotionStates(false),
+m_applySpeculativeContactRestitution(false),
+m_profileTimings(0),
+m_latencyMotionStateInterpolation(true)
+
+{
+ if (!m_constraintSolver)
+ {
+ void* mem = btAlignedAlloc(sizeof(btSequentialImpulseConstraintSolver),16);
+ m_constraintSolver = new (mem) btSequentialImpulseConstraintSolver;
+ m_ownsConstraintSolver = true;
+ } else
+ {
+ m_ownsConstraintSolver = false;
+ }
+
+ {
+ void* mem = btAlignedAlloc(sizeof(btSimulationIslandManager),16);
+ m_islandManager = new (mem) btSimulationIslandManager();
+ }
+
+ m_ownsIslandManager = true;
+
+ {
+ void* mem = btAlignedAlloc(sizeof(InplaceSolverIslandCallback),16);
+ m_solverIslandCallback = new (mem) InplaceSolverIslandCallback (m_constraintSolver, 0, dispatcher);
+ }
+}
+
+
+btDiscreteDynamicsWorld::~btDiscreteDynamicsWorld()
+{
+ //only delete it when we created it
+ if (m_ownsIslandManager)
+ {
+ m_islandManager->~btSimulationIslandManager();
+ btAlignedFree( m_islandManager);
+ }
+ if (m_solverIslandCallback)
+ {
+ m_solverIslandCallback->~InplaceSolverIslandCallback();
+ btAlignedFree(m_solverIslandCallback);
+ }
+ if (m_ownsConstraintSolver)
+ {
+
+ m_constraintSolver->~btConstraintSolver();
+ btAlignedFree(m_constraintSolver);
+ }
+}
+
+void btDiscreteDynamicsWorld::saveKinematicState(btScalar timeStep)
+{
+///would like to iterate over m_nonStaticRigidBodies, but unfortunately old API allows
+///to switch status _after_ adding kinematic objects to the world
+///fix it for Bullet 3.x release
+ for (int i=0;i<m_collisionObjects.size();i++)
+ {
+ btCollisionObject* colObj = m_collisionObjects[i];
+ btRigidBody* body = btRigidBody::upcast(colObj);
+ if (body && body->getActivationState() != ISLAND_SLEEPING)
+ {
+ if (body->isKinematicObject())
+ {
+ //to calculate velocities next frame
+ body->saveKinematicState(timeStep);
+ }
+ }
+ }
+
+}
+
+void btDiscreteDynamicsWorld::debugDrawWorld()
+{
+ BT_PROFILE("debugDrawWorld");
+
+ btCollisionWorld::debugDrawWorld();
+
+ bool drawConstraints = false;
+ if (getDebugDrawer())
+ {
+ int mode = getDebugDrawer()->getDebugMode();
+ if(mode & (btIDebugDraw::DBG_DrawConstraints | btIDebugDraw::DBG_DrawConstraintLimits))
+ {
+ drawConstraints = true;
+ }
+ }
+ if(drawConstraints)
+ {
+ for(int i = getNumConstraints()-1; i>=0 ;i--)
+ {
+ btTypedConstraint* constraint = getConstraint(i);
+ debugDrawConstraint(constraint);
+ }
+ }
+
+
+
+ if (getDebugDrawer() && (getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe | btIDebugDraw::DBG_DrawAabb | btIDebugDraw::DBG_DrawNormals)))
+ {
+ int i;
+
+ if (getDebugDrawer() && getDebugDrawer()->getDebugMode())
+ {
+ for (i=0;i<m_actions.size();i++)
+ {
+ m_actions[i]->debugDraw(m_debugDrawer);
+ }
+ }
+ }
+ if (getDebugDrawer())
+ getDebugDrawer()->flushLines();
+
+}
+
+void btDiscreteDynamicsWorld::clearForces()
+{
+ ///@todo: iterate over awake simulation islands!
+ for ( int i=0;i<m_nonStaticRigidBodies.size();i++)
+ {
+ btRigidBody* body = m_nonStaticRigidBodies[i];
+ //need to check if next line is ok
+ //it might break backward compatibility (people applying forces on sleeping objects get never cleared and accumulate on wake-up
+ body->clearForces();
+ }
+}
+
+///apply gravity, call this once per timestep
+void btDiscreteDynamicsWorld::applyGravity()
+{
+ ///@todo: iterate over awake simulation islands!
+ for ( int i=0;i<m_nonStaticRigidBodies.size();i++)
+ {
+ btRigidBody* body = m_nonStaticRigidBodies[i];
+ if (body->isActive())
+ {
+ body->applyGravity();
+ }
+ }
+}
+
+
+void btDiscreteDynamicsWorld::synchronizeSingleMotionState(btRigidBody* body)
+{
+ btAssert(body);
+
+ if (body->getMotionState() && !body->isStaticOrKinematicObject())
+ {
+ //we need to call the update at least once, even for sleeping objects
+ //otherwise the 'graphics' transform never updates properly
+ ///@todo: add 'dirty' flag
+ //if (body->getActivationState() != ISLAND_SLEEPING)
+ {
+ btTransform interpolatedTransform;
+ btTransformUtil::integrateTransform(body->getInterpolationWorldTransform(),
+ body->getInterpolationLinearVelocity(),body->getInterpolationAngularVelocity(),
+ (m_latencyMotionStateInterpolation && m_fixedTimeStep) ? m_localTime - m_fixedTimeStep : m_localTime*body->getHitFraction(),
+ interpolatedTransform);
+ body->getMotionState()->setWorldTransform(interpolatedTransform);
+ }
+ }
+}
+
+
+void btDiscreteDynamicsWorld::synchronizeMotionStates()
+{
+// BT_PROFILE("synchronizeMotionStates");
+ if (m_synchronizeAllMotionStates)
+ {
+ //iterate over all collision objects
+ for ( int i=0;i<m_collisionObjects.size();i++)
+ {
+ btCollisionObject* colObj = m_collisionObjects[i];
+ btRigidBody* body = btRigidBody::upcast(colObj);
+ if (body)
+ synchronizeSingleMotionState(body);
+ }
+ } else
+ {
+ //iterate over all active rigid bodies
+ for ( int i=0;i<m_nonStaticRigidBodies.size();i++)
+ {
+ btRigidBody* body = m_nonStaticRigidBodies[i];
+ if (body->isActive())
+ synchronizeSingleMotionState(body);
+ }
+ }
+}
+
+
+int btDiscreteDynamicsWorld::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);
+
+ applyGravity();
+
+
+
+ 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;
+}
+
+void btDiscreteDynamicsWorld::internalSingleStepSimulation(btScalar timeStep)
+{
+
+ BT_PROFILE("internalSingleStepSimulation");
+
+ if(0 != m_internalPreTickCallback) {
+ (*m_internalPreTickCallback)(this, timeStep);
+ }
+
+ ///apply gravity, predict motion
+ predictUnconstraintMotion(timeStep);
+
+ btDispatcherInfo& dispatchInfo = getDispatchInfo();
+
+ dispatchInfo.m_timeStep = timeStep;
+ dispatchInfo.m_stepCount = 0;
+ dispatchInfo.m_debugDraw = getDebugDrawer();
+
+
+ createPredictiveContacts(timeStep);
+
+ ///perform collision detection
+ performDiscreteCollisionDetection();
+
+ calculateSimulationIslands();
+
+
+ getSolverInfo().m_timeStep = timeStep;
+
+
+
+ ///solve contact and other joint constraints
+ solveConstraints(getSolverInfo());
+
+ ///CallbackTriggers();
+
+ ///integrate transforms
+
+ integrateTransforms(timeStep);
+
+ ///update vehicle simulation
+ updateActions(timeStep);
+
+ updateActivationState( timeStep );
+
+ if(0 != m_internalTickCallback) {
+ (*m_internalTickCallback)(this, timeStep);
+ }
+}
+
+void btDiscreteDynamicsWorld::setGravity(const btVector3& gravity)
+{
+ m_gravity = gravity;
+ for ( int i=0;i<m_nonStaticRigidBodies.size();i++)
+ {
+ btRigidBody* body = m_nonStaticRigidBodies[i];
+ if (body->isActive() && !(body->getFlags() &BT_DISABLE_WORLD_GRAVITY))
+ {
+ body->setGravity(gravity);
+ }
+ }
+}
+
+btVector3 btDiscreteDynamicsWorld::getGravity () const
+{
+ return m_gravity;
+}
+
+void btDiscreteDynamicsWorld::addCollisionObject(btCollisionObject* collisionObject, int collisionFilterGroup, int collisionFilterMask)
+{
+ btCollisionWorld::addCollisionObject(collisionObject,collisionFilterGroup,collisionFilterMask);
+}
+
+void btDiscreteDynamicsWorld::removeCollisionObject(btCollisionObject* collisionObject)
+{
+ btRigidBody* body = btRigidBody::upcast(collisionObject);
+ if (body)
+ removeRigidBody(body);
+ else
+ btCollisionWorld::removeCollisionObject(collisionObject);
+}
+
+void btDiscreteDynamicsWorld::removeRigidBody(btRigidBody* body)
+{
+ m_nonStaticRigidBodies.remove(body);
+ btCollisionWorld::removeCollisionObject(body);
+}
+
+
+void btDiscreteDynamicsWorld::addRigidBody(btRigidBody* body)
+{
+ if (!body->isStaticOrKinematicObject() && !(body->getFlags() &BT_DISABLE_WORLD_GRAVITY))
+ {
+ body->setGravity(m_gravity);
+ }
+
+ if (body->getCollisionShape())
+ {
+ if (!body->isStaticObject())
+ {
+ m_nonStaticRigidBodies.push_back(body);
+ } else
+ {
+ body->setActivationState(ISLAND_SLEEPING);
+ }
+
+ bool isDynamic = !(body->isStaticObject() || body->isKinematicObject());
+ int collisionFilterGroup = isDynamic? int(btBroadphaseProxy::DefaultFilter) : int(btBroadphaseProxy::StaticFilter);
+ int collisionFilterMask = isDynamic? int(btBroadphaseProxy::AllFilter) : int(btBroadphaseProxy::AllFilter ^ btBroadphaseProxy::StaticFilter);
+
+ addCollisionObject(body,collisionFilterGroup,collisionFilterMask);
+ }
+}
+
+void btDiscreteDynamicsWorld::addRigidBody(btRigidBody* body, int group, int mask)
+{
+ if (!body->isStaticOrKinematicObject() && !(body->getFlags() &BT_DISABLE_WORLD_GRAVITY))
+ {
+ body->setGravity(m_gravity);
+ }
+
+ if (body->getCollisionShape())
+ {
+ if (!body->isStaticObject())
+ {
+ m_nonStaticRigidBodies.push_back(body);
+ }
+ else
+ {
+ body->setActivationState(ISLAND_SLEEPING);
+ }
+ addCollisionObject(body,group,mask);
+ }
+}
+
+
+void btDiscreteDynamicsWorld::updateActions(btScalar timeStep)
+{
+ BT_PROFILE("updateActions");
+
+ for ( int i=0;i<m_actions.size();i++)
+ {
+ m_actions[i]->updateAction( this, timeStep);
+ }
+}
+
+
+void btDiscreteDynamicsWorld::updateActivationState(btScalar timeStep)
+{
+ BT_PROFILE("updateActivationState");
+
+ for ( int i=0;i<m_nonStaticRigidBodies.size();i++)
+ {
+ btRigidBody* body = m_nonStaticRigidBodies[i];
+ if (body)
+ {
+ body->updateDeactivation(timeStep);
+
+ if (body->wantsSleeping())
+ {
+ if (body->isStaticOrKinematicObject())
+ {
+ body->setActivationState(ISLAND_SLEEPING);
+ } else
+ {
+ if (body->getActivationState() == ACTIVE_TAG)
+ body->setActivationState( WANTS_DEACTIVATION );
+ if (body->getActivationState() == ISLAND_SLEEPING)
+ {
+ body->setAngularVelocity(btVector3(0,0,0));
+ body->setLinearVelocity(btVector3(0,0,0));
+ }
+
+ }
+ } else
+ {
+ if (body->getActivationState() != DISABLE_DEACTIVATION)
+ body->setActivationState( ACTIVE_TAG );
+ }
+ }
+ }
+}
+
+void btDiscreteDynamicsWorld::addConstraint(btTypedConstraint* constraint,bool disableCollisionsBetweenLinkedBodies)
+{
+ m_constraints.push_back(constraint);
+ //Make sure the two bodies of a type constraint are different (possibly add this to the btTypedConstraint constructor?)
+ btAssert(&constraint->getRigidBodyA()!=&constraint->getRigidBodyB());
+
+ if (disableCollisionsBetweenLinkedBodies)
+ {
+ constraint->getRigidBodyA().addConstraintRef(constraint);
+ constraint->getRigidBodyB().addConstraintRef(constraint);
+ }
+}
+
+void btDiscreteDynamicsWorld::removeConstraint(btTypedConstraint* constraint)
+{
+ m_constraints.remove(constraint);
+ constraint->getRigidBodyA().removeConstraintRef(constraint);
+ constraint->getRigidBodyB().removeConstraintRef(constraint);
+}
+
+void btDiscreteDynamicsWorld::addAction(btActionInterface* action)
+{
+ m_actions.push_back(action);
+}
+
+void btDiscreteDynamicsWorld::removeAction(btActionInterface* action)
+{
+ m_actions.remove(action);
+}
+
+
+void btDiscreteDynamicsWorld::addVehicle(btActionInterface* vehicle)
+{
+ addAction(vehicle);
+}
+
+void btDiscreteDynamicsWorld::removeVehicle(btActionInterface* vehicle)
+{
+ removeAction(vehicle);
+}
+
+void btDiscreteDynamicsWorld::addCharacter(btActionInterface* character)
+{
+ addAction(character);
+}
+
+void btDiscreteDynamicsWorld::removeCharacter(btActionInterface* character)
+{
+ removeAction(character);
+}
+
+
+
+
+void btDiscreteDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo)
+{
+ BT_PROFILE("solveConstraints");
+
+ m_sortedConstraints.resize( m_constraints.size());
+ int i;
+ for (i=0;i<getNumConstraints();i++)
+ {
+ m_sortedConstraints[i] = m_constraints[i];
+ }
+
+// btAssert(0);
+
+
+
+ m_sortedConstraints.quickSort(btSortConstraintOnIslandPredicate());
+
+ btTypedConstraint** constraintsPtr = getNumConstraints() ? &m_sortedConstraints[0] : 0;
+
+ m_solverIslandCallback->setup(&solverInfo,constraintsPtr,m_sortedConstraints.size(),getDebugDrawer());
+ m_constraintSolver->prepareSolve(getCollisionWorld()->getNumCollisionObjects(), getCollisionWorld()->getDispatcher()->getNumManifolds());
+
+ /// solve all the constraints for this island
+ m_islandManager->buildAndProcessIslands(getCollisionWorld()->getDispatcher(),getCollisionWorld(),m_solverIslandCallback);
+
+ m_solverIslandCallback->processConstraints();
+
+ m_constraintSolver->allSolved(solverInfo, m_debugDrawer);
+}
+
+
+void btDiscreteDynamicsWorld::calculateSimulationIslands()
+{
+ BT_PROFILE("calculateSimulationIslands");
+
+ getSimulationIslandManager()->updateActivationState(getCollisionWorld(),getCollisionWorld()->getDispatcher());
+
+ {
+ //merge islands based on speculative contact manifolds too
+ for (int i=0;i<this->m_predictiveManifolds.size();i++)
+ {
+ btPersistentManifold* manifold = m_predictiveManifolds[i];
+
+ const btCollisionObject* colObj0 = manifold->getBody0();
+ const btCollisionObject* colObj1 = manifold->getBody1();
+
+ if (((colObj0) && (!(colObj0)->isStaticOrKinematicObject())) &&
+ ((colObj1) && (!(colObj1)->isStaticOrKinematicObject())))
+ {
+ getSimulationIslandManager()->getUnionFind().unite((colObj0)->getIslandTag(),(colObj1)->getIslandTag());
+ }
+ }
+ }
+
+ {
+ int i;
+ int numConstraints = int(m_constraints.size());
+ for (i=0;i< numConstraints ; i++ )
+ {
+ btTypedConstraint* constraint = m_constraints[i];
+ if (constraint->isEnabled())
+ {
+ const btRigidBody* colObj0 = &constraint->getRigidBodyA();
+ const btRigidBody* colObj1 = &constraint->getRigidBodyB();
+
+ if (((colObj0) && (!(colObj0)->isStaticOrKinematicObject())) &&
+ ((colObj1) && (!(colObj1)->isStaticOrKinematicObject())))
+ {
+ getSimulationIslandManager()->getUnionFind().unite((colObj0)->getIslandTag(),(colObj1)->getIslandTag());
+ }
+ }
+ }
+ }
+
+ //Store the island id in each body
+ getSimulationIslandManager()->storeIslandActivationState(getCollisionWorld());
+
+
+}
+
+
+
+
+class btClosestNotMeConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback
+{
+public:
+
+ btCollisionObject* m_me;
+ btScalar m_allowedPenetration;
+ btOverlappingPairCache* m_pairCache;
+ btDispatcher* m_dispatcher;
+
+public:
+ btClosestNotMeConvexResultCallback (btCollisionObject* me,const btVector3& fromA,const btVector3& toA,btOverlappingPairCache* pairCache,btDispatcher* dispatcher) :
+ btCollisionWorld::ClosestConvexResultCallback(fromA,toA),
+ m_me(me),
+ m_allowedPenetration(0.0f),
+ m_pairCache(pairCache),
+ m_dispatcher(dispatcher)
+ {
+ }
+
+ virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& convexResult,bool normalInWorldSpace)
+ {
+ if (convexResult.m_hitCollisionObject == m_me)
+ return 1.0f;
+
+ //ignore result if there is no contact response
+ if(!convexResult.m_hitCollisionObject->hasContactResponse())
+ return 1.0f;
+
+ btVector3 linVelA,linVelB;
+ linVelA = m_convexToWorld-m_convexFromWorld;
+ linVelB = btVector3(0,0,0);//toB.getOrigin()-fromB.getOrigin();
+
+ btVector3 relativeVelocity = (linVelA-linVelB);
+ //don't report time of impact for motion away from the contact normal (or causes minor penetration)
+ if (convexResult.m_hitNormalLocal.dot(relativeVelocity)>=-m_allowedPenetration)
+ return 1.f;
+
+ return ClosestConvexResultCallback::addSingleResult (convexResult, normalInWorldSpace);
+ }
+
+ virtual bool needsCollision(btBroadphaseProxy* proxy0) const
+ {
+ //don't collide with itself
+ if (proxy0->m_clientObject == m_me)
+ return false;
+
+ ///don't do CCD when the collision filters are not matching
+ if (!ClosestConvexResultCallback::needsCollision(proxy0))
+ return false;
+
+ btCollisionObject* otherObj = (btCollisionObject*) proxy0->m_clientObject;
+
+ //call needsResponse, see http://code.google.com/p/bullet/issues/detail?id=179
+ if (m_dispatcher->needsResponse(m_me,otherObj))
+ {
+#if 0
+ ///don't do CCD when there are already contact points (touching contact/penetration)
+ btAlignedObjectArray<btPersistentManifold*> manifoldArray;
+ btBroadphasePair* collisionPair = m_pairCache->findPair(m_me->getBroadphaseHandle(),proxy0);
+ if (collisionPair)
+ {
+ if (collisionPair->m_algorithm)
+ {
+ manifoldArray.resize(0);
+ collisionPair->m_algorithm->getAllContactManifolds(manifoldArray);
+ for (int j=0;j<manifoldArray.size();j++)
+ {
+ btPersistentManifold* manifold = manifoldArray[j];
+ if (manifold->getNumContacts()>0)
+ return false;
+ }
+ }
+ }
+#endif
+ return true;
+ }
+
+ return false;
+ }
+
+
+};
+
+///internal debugging variable. this value shouldn't be too high
+int gNumClampedCcdMotions=0;
+
+
+void btDiscreteDynamicsWorld::createPredictiveContactsInternal( btRigidBody** bodies, int numBodies, btScalar timeStep)
+{
+ btTransform predictedTrans;
+ for ( int i=0;i<numBodies;i++)
+ {
+ btRigidBody* body = bodies[i];
+ body->setHitFraction(1.f);
+
+ if (body->isActive() && (!body->isStaticOrKinematicObject()))
+ {
+
+ body->predictIntegratedTransform(timeStep, predictedTrans);
+
+ btScalar squareMotion = (predictedTrans.getOrigin()-body->getWorldTransform().getOrigin()).length2();
+
+ if (getDispatchInfo().m_useContinuous && body->getCcdSquareMotionThreshold() && body->getCcdSquareMotionThreshold() < squareMotion)
+ {
+ BT_PROFILE("predictive convexSweepTest");
+ if (body->getCollisionShape()->isConvex())
+ {
+ gNumClampedCcdMotions++;
+#ifdef PREDICTIVE_CONTACT_USE_STATIC_ONLY
+ class StaticOnlyCallback : public btClosestNotMeConvexResultCallback
+ {
+ public:
+
+ StaticOnlyCallback (btCollisionObject* me,const btVector3& fromA,const btVector3& toA,btOverlappingPairCache* pairCache,btDispatcher* dispatcher) :
+ btClosestNotMeConvexResultCallback(me,fromA,toA,pairCache,dispatcher)
+ {
+ }
+
+ virtual bool needsCollision(btBroadphaseProxy* proxy0) const
+ {
+ btCollisionObject* otherObj = (btCollisionObject*) proxy0->m_clientObject;
+ if (!otherObj->isStaticOrKinematicObject())
+ return false;
+ return btClosestNotMeConvexResultCallback::needsCollision(proxy0);
+ }
+ };
+
+ StaticOnlyCallback sweepResults(body,body->getWorldTransform().getOrigin(),predictedTrans.getOrigin(),getBroadphase()->getOverlappingPairCache(),getDispatcher());
+#else
+ btClosestNotMeConvexResultCallback sweepResults(body,body->getWorldTransform().getOrigin(),predictedTrans.getOrigin(),getBroadphase()->getOverlappingPairCache(),getDispatcher());
+#endif
+ //btConvexShape* convexShape = static_cast<btConvexShape*>(body->getCollisionShape());
+ btSphereShape tmpSphere(body->getCcdSweptSphereRadius());//btConvexShape* convexShape = static_cast<btConvexShape*>(body->getCollisionShape());
+ sweepResults.m_allowedPenetration=getDispatchInfo().m_allowedCcdPenetration;
+
+ sweepResults.m_collisionFilterGroup = body->getBroadphaseProxy()->m_collisionFilterGroup;
+ sweepResults.m_collisionFilterMask = body->getBroadphaseProxy()->m_collisionFilterMask;
+ btTransform modifiedPredictedTrans = predictedTrans;
+ modifiedPredictedTrans.setBasis(body->getWorldTransform().getBasis());
+
+ convexSweepTest(&tmpSphere,body->getWorldTransform(),modifiedPredictedTrans,sweepResults);
+ if (sweepResults.hasHit() && (sweepResults.m_closestHitFraction < 1.f))
+ {
+
+ btVector3 distVec = (predictedTrans.getOrigin()-body->getWorldTransform().getOrigin())*sweepResults.m_closestHitFraction;
+ btScalar distance = distVec.dot(-sweepResults.m_hitNormalWorld);
+
+
+ btPersistentManifold* manifold = m_dispatcher1->getNewManifold(body,sweepResults.m_hitCollisionObject);
+ btMutexLock( &m_predictiveManifoldsMutex );
+ m_predictiveManifolds.push_back(manifold);
+ btMutexUnlock( &m_predictiveManifoldsMutex );
+
+ btVector3 worldPointB = body->getWorldTransform().getOrigin()+distVec;
+ btVector3 localPointB = sweepResults.m_hitCollisionObject->getWorldTransform().inverse()*worldPointB;
+
+ btManifoldPoint newPoint(btVector3(0,0,0), localPointB,sweepResults.m_hitNormalWorld,distance);
+
+ bool isPredictive = true;
+ int index = manifold->addManifoldPoint(newPoint, isPredictive);
+ btManifoldPoint& pt = manifold->getContactPoint(index);
+ pt.m_combinedRestitution = 0;
+ pt.m_combinedFriction = gCalculateCombinedFrictionCallback(body,sweepResults.m_hitCollisionObject);
+ pt.m_positionWorldOnA = body->getWorldTransform().getOrigin();
+ pt.m_positionWorldOnB = worldPointB;
+
+ }
+ }
+ }
+ }
+ }
+}
+
+void btDiscreteDynamicsWorld::releasePredictiveContacts()
+{
+ BT_PROFILE( "release predictive contact manifolds" );
+
+ for ( int i = 0; i < m_predictiveManifolds.size(); i++ )
+ {
+ btPersistentManifold* manifold = m_predictiveManifolds[ i ];
+ this->m_dispatcher1->releaseManifold( manifold );
+ }
+ m_predictiveManifolds.clear();
+}
+
+void btDiscreteDynamicsWorld::createPredictiveContacts(btScalar timeStep)
+{
+ BT_PROFILE("createPredictiveContacts");
+ releasePredictiveContacts();
+ if (m_nonStaticRigidBodies.size() > 0)
+ {
+ createPredictiveContactsInternal( &m_nonStaticRigidBodies[ 0 ], m_nonStaticRigidBodies.size(), timeStep );
+ }
+}
+
+void btDiscreteDynamicsWorld::integrateTransformsInternal( btRigidBody** bodies, int numBodies, btScalar timeStep )
+{
+ btTransform predictedTrans;
+ for (int i=0;i<numBodies;i++)
+ {
+ btRigidBody* body = bodies[i];
+ body->setHitFraction(1.f);
+
+ if (body->isActive() && (!body->isStaticOrKinematicObject()))
+ {
+
+ body->predictIntegratedTransform(timeStep, predictedTrans);
+
+ btScalar squareMotion = (predictedTrans.getOrigin()-body->getWorldTransform().getOrigin()).length2();
+
+
+
+ if (getDispatchInfo().m_useContinuous && body->getCcdSquareMotionThreshold() && body->getCcdSquareMotionThreshold() < squareMotion)
+ {
+ BT_PROFILE("CCD motion clamping");
+ if (body->getCollisionShape()->isConvex())
+ {
+ gNumClampedCcdMotions++;
+#ifdef USE_STATIC_ONLY
+ class StaticOnlyCallback : public btClosestNotMeConvexResultCallback
+ {
+ public:
+
+ StaticOnlyCallback (btCollisionObject* me,const btVector3& fromA,const btVector3& toA,btOverlappingPairCache* pairCache,btDispatcher* dispatcher) :
+ btClosestNotMeConvexResultCallback(me,fromA,toA,pairCache,dispatcher)
+ {
+ }
+
+ virtual bool needsCollision(btBroadphaseProxy* proxy0) const
+ {
+ btCollisionObject* otherObj = (btCollisionObject*) proxy0->m_clientObject;
+ if (!otherObj->isStaticOrKinematicObject())
+ return false;
+ return btClosestNotMeConvexResultCallback::needsCollision(proxy0);
+ }
+ };
+
+ StaticOnlyCallback sweepResults(body,body->getWorldTransform().getOrigin(),predictedTrans.getOrigin(),getBroadphase()->getOverlappingPairCache(),getDispatcher());
+#else
+ btClosestNotMeConvexResultCallback sweepResults(body,body->getWorldTransform().getOrigin(),predictedTrans.getOrigin(),getBroadphase()->getOverlappingPairCache(),getDispatcher());
+#endif
+ //btConvexShape* convexShape = static_cast<btConvexShape*>(body->getCollisionShape());
+ btSphereShape tmpSphere(body->getCcdSweptSphereRadius());//btConvexShape* convexShape = static_cast<btConvexShape*>(body->getCollisionShape());
+ sweepResults.m_allowedPenetration=getDispatchInfo().m_allowedCcdPenetration;
+
+ sweepResults.m_collisionFilterGroup = body->getBroadphaseProxy()->m_collisionFilterGroup;
+ sweepResults.m_collisionFilterMask = body->getBroadphaseProxy()->m_collisionFilterMask;
+ btTransform modifiedPredictedTrans = predictedTrans;
+ modifiedPredictedTrans.setBasis(body->getWorldTransform().getBasis());
+
+ convexSweepTest(&tmpSphere,body->getWorldTransform(),modifiedPredictedTrans,sweepResults);
+ if (sweepResults.hasHit() && (sweepResults.m_closestHitFraction < 1.f))
+ {
+
+ //printf("clamped integration to hit fraction = %f\n",fraction);
+ body->setHitFraction(sweepResults.m_closestHitFraction);
+ body->predictIntegratedTransform(timeStep*body->getHitFraction(), predictedTrans);
+ body->setHitFraction(0.f);
+ body->proceedToTransform( predictedTrans);
+
+#if 0
+ btVector3 linVel = body->getLinearVelocity();
+
+ btScalar maxSpeed = body->getCcdMotionThreshold()/getSolverInfo().m_timeStep;
+ btScalar maxSpeedSqr = maxSpeed*maxSpeed;
+ if (linVel.length2()>maxSpeedSqr)
+ {
+ linVel.normalize();
+ linVel*= maxSpeed;
+ body->setLinearVelocity(linVel);
+ btScalar ms2 = body->getLinearVelocity().length2();
+ body->predictIntegratedTransform(timeStep, predictedTrans);
+
+ btScalar sm2 = (predictedTrans.getOrigin()-body->getWorldTransform().getOrigin()).length2();
+ btScalar smt = body->getCcdSquareMotionThreshold();
+ printf("sm2=%f\n",sm2);
+ }
+#else
+
+ //don't apply the collision response right now, it will happen next frame
+ //if you really need to, you can uncomment next 3 lines. Note that is uses zero restitution.
+ //btScalar appliedImpulse = 0.f;
+ //btScalar depth = 0.f;
+ //appliedImpulse = resolveSingleCollision(body,(btCollisionObject*)sweepResults.m_hitCollisionObject,sweepResults.m_hitPointWorld,sweepResults.m_hitNormalWorld,getSolverInfo(), depth);
+
+
+#endif
+
+ continue;
+ }
+ }
+ }
+
+
+ body->proceedToTransform( predictedTrans);
+
+ }
+
+ }
+
+}
+
+void btDiscreteDynamicsWorld::integrateTransforms(btScalar timeStep)
+{
+ BT_PROFILE("integrateTransforms");
+ if (m_nonStaticRigidBodies.size() > 0)
+ {
+ integrateTransformsInternal(&m_nonStaticRigidBodies[0], m_nonStaticRigidBodies.size(), timeStep);
+ }
+
+ ///this should probably be switched on by default, but it is not well tested yet
+ if (m_applySpeculativeContactRestitution)
+ {
+ BT_PROFILE("apply speculative contact restitution");
+ for (int i=0;i<m_predictiveManifolds.size();i++)
+ {
+ btPersistentManifold* manifold = m_predictiveManifolds[i];
+ btRigidBody* body0 = btRigidBody::upcast((btCollisionObject*)manifold->getBody0());
+ btRigidBody* body1 = btRigidBody::upcast((btCollisionObject*)manifold->getBody1());
+
+ for (int p=0;p<manifold->getNumContacts();p++)
+ {
+ const btManifoldPoint& pt = manifold->getContactPoint(p);
+ btScalar combinedRestitution = gCalculateCombinedRestitutionCallback(body0, body1);
+
+ if (combinedRestitution>0 && pt.m_appliedImpulse != 0.f)
+ //if (pt.getDistance()>0 && combinedRestitution>0 && pt.m_appliedImpulse != 0.f)
+ {
+ btVector3 imp = -pt.m_normalWorldOnB * pt.m_appliedImpulse* combinedRestitution;
+
+ const btVector3& pos1 = pt.getPositionWorldOnA();
+ const btVector3& pos2 = pt.getPositionWorldOnB();
+
+ btVector3 rel_pos0 = pos1 - body0->getWorldTransform().getOrigin();
+ btVector3 rel_pos1 = pos2 - body1->getWorldTransform().getOrigin();
+
+ if (body0)
+ body0->applyImpulse(imp,rel_pos0);
+ if (body1)
+ body1->applyImpulse(-imp,rel_pos1);
+ }
+ }
+ }
+ }
+}
+
+
+
+
+
+void btDiscreteDynamicsWorld::predictUnconstraintMotion(btScalar timeStep)
+{
+ BT_PROFILE("predictUnconstraintMotion");
+ for ( int i=0;i<m_nonStaticRigidBodies.size();i++)
+ {
+ btRigidBody* body = m_nonStaticRigidBodies[i];
+ if (!body->isStaticOrKinematicObject())
+ {
+ //don't integrate/update velocities here, it happens in the constraint solver
+
+ body->applyDamping(timeStep);
+
+ body->predictIntegratedTransform(timeStep,body->getInterpolationWorldTransform());
+ }
+ }
+}
+
+
+void btDiscreteDynamicsWorld::startProfiling(btScalar timeStep)
+{
+ (void)timeStep;
+
+#ifndef BT_NO_PROFILE
+ CProfileManager::Reset();
+#endif //BT_NO_PROFILE
+
+}
+
+
+
+
+
+
+void btDiscreteDynamicsWorld::debugDrawConstraint(btTypedConstraint* constraint)
+{
+ bool drawFrames = (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawConstraints) != 0;
+ bool drawLimits = (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawConstraintLimits) != 0;
+ btScalar dbgDrawSize = constraint->getDbgDrawSize();
+ if(dbgDrawSize <= btScalar(0.f))
+ {
+ return;
+ }
+
+ switch(constraint->getConstraintType())
+ {
+ case POINT2POINT_CONSTRAINT_TYPE:
+ {
+ btPoint2PointConstraint* p2pC = (btPoint2PointConstraint*)constraint;
+ btTransform tr;
+ tr.setIdentity();
+ btVector3 pivot = p2pC->getPivotInA();
+ pivot = p2pC->getRigidBodyA().getCenterOfMassTransform() * pivot;
+ tr.setOrigin(pivot);
+ getDebugDrawer()->drawTransform(tr, dbgDrawSize);
+ // that ideally should draw the same frame
+ pivot = p2pC->getPivotInB();
+ pivot = p2pC->getRigidBodyB().getCenterOfMassTransform() * pivot;
+ tr.setOrigin(pivot);
+ if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
+ }
+ break;
+ case HINGE_CONSTRAINT_TYPE:
+ {
+ btHingeConstraint* pHinge = (btHingeConstraint*)constraint;
+ btTransform tr = pHinge->getRigidBodyA().getCenterOfMassTransform() * pHinge->getAFrame();
+ if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
+ tr = pHinge->getRigidBodyB().getCenterOfMassTransform() * pHinge->getBFrame();
+ if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
+ btScalar minAng = pHinge->getLowerLimit();
+ btScalar maxAng = pHinge->getUpperLimit();
+ if(minAng == maxAng)
+ {
+ break;
+ }
+ bool drawSect = true;
+ if(!pHinge->hasLimit())
+ {
+ minAng = btScalar(0.f);
+ maxAng = SIMD_2_PI;
+ drawSect = false;
+ }
+ if(drawLimits)
+ {
+ btVector3& center = tr.getOrigin();
+ btVector3 normal = tr.getBasis().getColumn(2);
+ btVector3 axis = tr.getBasis().getColumn(0);
+ getDebugDrawer()->drawArc(center, normal, axis, dbgDrawSize, dbgDrawSize, minAng, maxAng, btVector3(0,0,0), drawSect);
+ }
+ }
+ break;
+ case CONETWIST_CONSTRAINT_TYPE:
+ {
+ btConeTwistConstraint* pCT = (btConeTwistConstraint*)constraint;
+ btTransform tr = pCT->getRigidBodyA().getCenterOfMassTransform() * pCT->getAFrame();
+ if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
+ tr = pCT->getRigidBodyB().getCenterOfMassTransform() * pCT->getBFrame();
+ if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
+ if(drawLimits)
+ {
+ //const btScalar length = btScalar(5);
+ const btScalar length = dbgDrawSize;
+ static int nSegments = 8*4;
+ btScalar fAngleInRadians = btScalar(2.*3.1415926) * (btScalar)(nSegments-1)/btScalar(nSegments);
+ btVector3 pPrev = pCT->GetPointForAngle(fAngleInRadians, length);
+ pPrev = tr * pPrev;
+ for (int i=0; i<nSegments; i++)
+ {
+ fAngleInRadians = btScalar(2.*3.1415926) * (btScalar)i/btScalar(nSegments);
+ btVector3 pCur = pCT->GetPointForAngle(fAngleInRadians, length);
+ pCur = tr * pCur;
+ getDebugDrawer()->drawLine(pPrev, pCur, btVector3(0,0,0));
+
+ if (i%(nSegments/8) == 0)
+ getDebugDrawer()->drawLine(tr.getOrigin(), pCur, btVector3(0,0,0));
+
+ pPrev = pCur;
+ }
+ btScalar tws = pCT->getTwistSpan();
+ btScalar twa = pCT->getTwistAngle();
+ bool useFrameB = (pCT->getRigidBodyB().getInvMass() > btScalar(0.f));
+ if(useFrameB)
+ {
+ tr = pCT->getRigidBodyB().getCenterOfMassTransform() * pCT->getBFrame();
+ }
+ else
+ {
+ tr = pCT->getRigidBodyA().getCenterOfMassTransform() * pCT->getAFrame();
+ }
+ btVector3 pivot = tr.getOrigin();
+ btVector3 normal = tr.getBasis().getColumn(0);
+ btVector3 axis1 = tr.getBasis().getColumn(1);
+ getDebugDrawer()->drawArc(pivot, normal, axis1, dbgDrawSize, dbgDrawSize, -twa-tws, -twa+tws, btVector3(0,0,0), true);
+
+ }
+ }
+ break;
+ case D6_SPRING_CONSTRAINT_TYPE:
+ case D6_CONSTRAINT_TYPE:
+ {
+ btGeneric6DofConstraint* p6DOF = (btGeneric6DofConstraint*)constraint;
+ btTransform tr = p6DOF->getCalculatedTransformA();
+ if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
+ tr = p6DOF->getCalculatedTransformB();
+ if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
+ if(drawLimits)
+ {
+ tr = p6DOF->getCalculatedTransformA();
+ const btVector3& center = p6DOF->getCalculatedTransformB().getOrigin();
+ btVector3 up = tr.getBasis().getColumn(2);
+ btVector3 axis = tr.getBasis().getColumn(0);
+ btScalar minTh = p6DOF->getRotationalLimitMotor(1)->m_loLimit;
+ btScalar maxTh = p6DOF->getRotationalLimitMotor(1)->m_hiLimit;
+ btScalar minPs = p6DOF->getRotationalLimitMotor(2)->m_loLimit;
+ btScalar maxPs = p6DOF->getRotationalLimitMotor(2)->m_hiLimit;
+ getDebugDrawer()->drawSpherePatch(center, up, axis, dbgDrawSize * btScalar(.9f), minTh, maxTh, minPs, maxPs, btVector3(0,0,0));
+ axis = tr.getBasis().getColumn(1);
+ btScalar ay = p6DOF->getAngle(1);
+ btScalar az = p6DOF->getAngle(2);
+ btScalar cy = btCos(ay);
+ btScalar sy = btSin(ay);
+ btScalar cz = btCos(az);
+ btScalar sz = btSin(az);
+ btVector3 ref;
+ ref[0] = cy*cz*axis[0] + cy*sz*axis[1] - sy*axis[2];
+ ref[1] = -sz*axis[0] + cz*axis[1];
+ ref[2] = cz*sy*axis[0] + sz*sy*axis[1] + cy*axis[2];
+ tr = p6DOF->getCalculatedTransformB();
+ btVector3 normal = -tr.getBasis().getColumn(0);
+ btScalar minFi = p6DOF->getRotationalLimitMotor(0)->m_loLimit;
+ btScalar maxFi = p6DOF->getRotationalLimitMotor(0)->m_hiLimit;
+ if(minFi > maxFi)
+ {
+ getDebugDrawer()->drawArc(center, normal, ref, dbgDrawSize, dbgDrawSize, -SIMD_PI, SIMD_PI, btVector3(0,0,0), false);
+ }
+ else if(minFi < maxFi)
+ {
+ getDebugDrawer()->drawArc(center, normal, ref, dbgDrawSize, dbgDrawSize, minFi, maxFi, btVector3(0,0,0), true);
+ }
+ tr = p6DOF->getCalculatedTransformA();
+ btVector3 bbMin = p6DOF->getTranslationalLimitMotor()->m_lowerLimit;
+ btVector3 bbMax = p6DOF->getTranslationalLimitMotor()->m_upperLimit;
+ getDebugDrawer()->drawBox(bbMin, bbMax, tr, btVector3(0,0,0));
+ }
+ }
+ break;
+ ///note: the code for D6_SPRING_2_CONSTRAINT_TYPE is identical to D6_CONSTRAINT_TYPE, the D6_CONSTRAINT_TYPE+D6_SPRING_CONSTRAINT_TYPE will likely become obsolete/deprecated at some stage
+ case D6_SPRING_2_CONSTRAINT_TYPE:
+ {
+ {
+ btGeneric6DofSpring2Constraint* p6DOF = (btGeneric6DofSpring2Constraint*)constraint;
+ btTransform tr = p6DOF->getCalculatedTransformA();
+ if (drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
+ tr = p6DOF->getCalculatedTransformB();
+ if (drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
+ if (drawLimits)
+ {
+ tr = p6DOF->getCalculatedTransformA();
+ const btVector3& center = p6DOF->getCalculatedTransformB().getOrigin();
+ btVector3 up = tr.getBasis().getColumn(2);
+ btVector3 axis = tr.getBasis().getColumn(0);
+ btScalar minTh = p6DOF->getRotationalLimitMotor(1)->m_loLimit;
+ btScalar maxTh = p6DOF->getRotationalLimitMotor(1)->m_hiLimit;
+ btScalar minPs = p6DOF->getRotationalLimitMotor(2)->m_loLimit;
+ btScalar maxPs = p6DOF->getRotationalLimitMotor(2)->m_hiLimit;
+ getDebugDrawer()->drawSpherePatch(center, up, axis, dbgDrawSize * btScalar(.9f), minTh, maxTh, minPs, maxPs, btVector3(0, 0, 0));
+ axis = tr.getBasis().getColumn(1);
+ btScalar ay = p6DOF->getAngle(1);
+ btScalar az = p6DOF->getAngle(2);
+ btScalar cy = btCos(ay);
+ btScalar sy = btSin(ay);
+ btScalar cz = btCos(az);
+ btScalar sz = btSin(az);
+ btVector3 ref;
+ ref[0] = cy*cz*axis[0] + cy*sz*axis[1] - sy*axis[2];
+ ref[1] = -sz*axis[0] + cz*axis[1];
+ ref[2] = cz*sy*axis[0] + sz*sy*axis[1] + cy*axis[2];
+ tr = p6DOF->getCalculatedTransformB();
+ btVector3 normal = -tr.getBasis().getColumn(0);
+ btScalar minFi = p6DOF->getRotationalLimitMotor(0)->m_loLimit;
+ btScalar maxFi = p6DOF->getRotationalLimitMotor(0)->m_hiLimit;
+ if (minFi > maxFi)
+ {
+ getDebugDrawer()->drawArc(center, normal, ref, dbgDrawSize, dbgDrawSize, -SIMD_PI, SIMD_PI, btVector3(0, 0, 0), false);
+ }
+ else if (minFi < maxFi)
+ {
+ getDebugDrawer()->drawArc(center, normal, ref, dbgDrawSize, dbgDrawSize, minFi, maxFi, btVector3(0, 0, 0), true);
+ }
+ tr = p6DOF->getCalculatedTransformA();
+ btVector3 bbMin = p6DOF->getTranslationalLimitMotor()->m_lowerLimit;
+ btVector3 bbMax = p6DOF->getTranslationalLimitMotor()->m_upperLimit;
+ getDebugDrawer()->drawBox(bbMin, bbMax, tr, btVector3(0, 0, 0));
+ }
+ }
+ break;
+ }
+ case SLIDER_CONSTRAINT_TYPE:
+ {
+ btSliderConstraint* pSlider = (btSliderConstraint*)constraint;
+ btTransform tr = pSlider->getCalculatedTransformA();
+ if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
+ tr = pSlider->getCalculatedTransformB();
+ if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
+ if(drawLimits)
+ {
+ btTransform tr = pSlider->getUseLinearReferenceFrameA() ? pSlider->getCalculatedTransformA() : pSlider->getCalculatedTransformB();
+ btVector3 li_min = tr * btVector3(pSlider->getLowerLinLimit(), 0.f, 0.f);
+ btVector3 li_max = tr * btVector3(pSlider->getUpperLinLimit(), 0.f, 0.f);
+ getDebugDrawer()->drawLine(li_min, li_max, btVector3(0, 0, 0));
+ btVector3 normal = tr.getBasis().getColumn(0);
+ btVector3 axis = tr.getBasis().getColumn(1);
+ btScalar a_min = pSlider->getLowerAngLimit();
+ btScalar a_max = pSlider->getUpperAngLimit();
+ const btVector3& center = pSlider->getCalculatedTransformB().getOrigin();
+ getDebugDrawer()->drawArc(center, normal, axis, dbgDrawSize, dbgDrawSize, a_min, a_max, btVector3(0,0,0), true);
+ }
+ }
+ break;
+ default :
+ break;
+ }
+ return;
+}
+
+
+
+
+
+void btDiscreteDynamicsWorld::setConstraintSolver(btConstraintSolver* solver)
+{
+ if (m_ownsConstraintSolver)
+ {
+ btAlignedFree( m_constraintSolver);
+ }
+ m_ownsConstraintSolver = false;
+ m_constraintSolver = solver;
+ m_solverIslandCallback->m_solver = solver;
+}
+
+btConstraintSolver* btDiscreteDynamicsWorld::getConstraintSolver()
+{
+ return m_constraintSolver;
+}
+
+
+int btDiscreteDynamicsWorld::getNumConstraints() const
+{
+ return int(m_constraints.size());
+}
+btTypedConstraint* btDiscreteDynamicsWorld::getConstraint(int index)
+{
+ return m_constraints[index];
+}
+const btTypedConstraint* btDiscreteDynamicsWorld::getConstraint(int index) const
+{
+ return m_constraints[index];
+}
+
+
+
+void btDiscreteDynamicsWorld::serializeRigidBodies(btSerializer* serializer)
+{
+ int i;
+ //serialize all collision objects
+ for (i=0;i<m_collisionObjects.size();i++)
+ {
+ btCollisionObject* colObj = m_collisionObjects[i];
+ if (colObj->getInternalType() & btCollisionObject::CO_RIGID_BODY)
+ {
+ int len = colObj->calculateSerializeBufferSize();
+ btChunk* chunk = serializer->allocate(len,1);
+ const char* structType = colObj->serialize(chunk->m_oldPtr, serializer);
+ serializer->finalizeChunk(chunk,structType,BT_RIGIDBODY_CODE,colObj);
+ }
+ }
+
+ for (i=0;i<m_constraints.size();i++)
+ {
+ btTypedConstraint* constraint = m_constraints[i];
+ int size = constraint->calculateSerializeBufferSize();
+ btChunk* chunk = serializer->allocate(size,1);
+ const char* structType = constraint->serialize(chunk->m_oldPtr,serializer);
+ serializer->finalizeChunk(chunk,structType,BT_CONSTRAINT_CODE,constraint);
+ }
+}
+
+
+
+
+void btDiscreteDynamicsWorld::serializeDynamicsWorldInfo(btSerializer* serializer)
+{
+#ifdef BT_USE_DOUBLE_PRECISION
+ int len = sizeof(btDynamicsWorldDoubleData);
+ btChunk* chunk = serializer->allocate(len,1);
+ btDynamicsWorldDoubleData* worldInfo = (btDynamicsWorldDoubleData*)chunk->m_oldPtr;
+#else//BT_USE_DOUBLE_PRECISION
+ int len = sizeof(btDynamicsWorldFloatData);
+ btChunk* chunk = serializer->allocate(len,1);
+ btDynamicsWorldFloatData* worldInfo = (btDynamicsWorldFloatData*)chunk->m_oldPtr;
+#endif//BT_USE_DOUBLE_PRECISION
+
+ memset(worldInfo ,0x00,len);
+
+ m_gravity.serialize(worldInfo->m_gravity);
+ worldInfo->m_solverInfo.m_tau = getSolverInfo().m_tau;
+ worldInfo->m_solverInfo.m_damping = getSolverInfo().m_damping;
+ worldInfo->m_solverInfo.m_friction = getSolverInfo().m_friction;
+ worldInfo->m_solverInfo.m_timeStep = getSolverInfo().m_timeStep;
+
+ worldInfo->m_solverInfo.m_restitution = getSolverInfo().m_restitution;
+ worldInfo->m_solverInfo.m_maxErrorReduction = getSolverInfo().m_maxErrorReduction;
+ worldInfo->m_solverInfo.m_sor = getSolverInfo().m_sor;
+ worldInfo->m_solverInfo.m_erp = getSolverInfo().m_erp;
+
+ worldInfo->m_solverInfo.m_erp2 = getSolverInfo().m_erp2;
+ worldInfo->m_solverInfo.m_globalCfm = getSolverInfo().m_globalCfm;
+ worldInfo->m_solverInfo.m_splitImpulsePenetrationThreshold = getSolverInfo().m_splitImpulsePenetrationThreshold;
+ worldInfo->m_solverInfo.m_splitImpulseTurnErp = getSolverInfo().m_splitImpulseTurnErp;
+
+ worldInfo->m_solverInfo.m_linearSlop = getSolverInfo().m_linearSlop;
+ worldInfo->m_solverInfo.m_warmstartingFactor = getSolverInfo().m_warmstartingFactor;
+ worldInfo->m_solverInfo.m_maxGyroscopicForce = getSolverInfo().m_maxGyroscopicForce;
+ worldInfo->m_solverInfo.m_singleAxisRollingFrictionThreshold = getSolverInfo().m_singleAxisRollingFrictionThreshold;
+
+ worldInfo->m_solverInfo.m_numIterations = getSolverInfo().m_numIterations;
+ worldInfo->m_solverInfo.m_solverMode = getSolverInfo().m_solverMode;
+ worldInfo->m_solverInfo.m_restingContactRestitutionThreshold = getSolverInfo().m_restingContactRestitutionThreshold;
+ worldInfo->m_solverInfo.m_minimumSolverBatchSize = getSolverInfo().m_minimumSolverBatchSize;
+
+ 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
+ const char* structType = "btDynamicsWorldFloatData";
+#endif//BT_USE_DOUBLE_PRECISION
+ serializer->finalizeChunk(chunk,structType,BT_DYNAMICSWORLD_CODE,worldInfo);
+}
+
+void btDiscreteDynamicsWorld::serialize(btSerializer* serializer)
+{
+
+ serializer->startSerialization();
+
+ serializeDynamicsWorldInfo(serializer);
+
+ serializeCollisionObjects(serializer);
+
+ serializeRigidBodies(serializer);
+
+ serializer->finishSerialization();
+}
+
diff --git a/thirdparty/bullet/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h b/thirdparty/bullet/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h
new file mode 100644
index 0000000000..b0d19f48a3
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h
@@ -0,0 +1,239 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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_DISCRETE_DYNAMICS_WORLD_H
+#define BT_DISCRETE_DYNAMICS_WORLD_H
+
+#include "btDynamicsWorld.h"
+
+class btDispatcher;
+class btOverlappingPairCache;
+class btConstraintSolver;
+class btSimulationIslandManager;
+class btTypedConstraint;
+class btActionInterface;
+class btPersistentManifold;
+class btIDebugDraw;
+struct InplaceSolverIslandCallback;
+
+#include "LinearMath/btAlignedObjectArray.h"
+#include "LinearMath/btThreads.h"
+
+
+///btDiscreteDynamicsWorld provides discrete rigid body simulation
+///those classes replace the obsolete CcdPhysicsEnvironment/CcdPhysicsController
+ATTRIBUTE_ALIGNED16(class) btDiscreteDynamicsWorld : public btDynamicsWorld
+{
+protected:
+
+ btAlignedObjectArray<btTypedConstraint*> m_sortedConstraints;
+ InplaceSolverIslandCallback* m_solverIslandCallback;
+
+ btConstraintSolver* m_constraintSolver;
+
+ btSimulationIslandManager* m_islandManager;
+
+ btAlignedObjectArray<btTypedConstraint*> m_constraints;
+
+ btAlignedObjectArray<btRigidBody*> m_nonStaticRigidBodies;
+
+ btVector3 m_gravity;
+
+ //for variable timesteps
+ btScalar m_localTime;
+ btScalar m_fixedTimeStep;
+ //for variable timesteps
+
+ bool m_ownsIslandManager;
+ bool m_ownsConstraintSolver;
+ bool m_synchronizeAllMotionStates;
+ bool m_applySpeculativeContactRestitution;
+
+ btAlignedObjectArray<btActionInterface*> m_actions;
+
+ int m_profileTimings;
+
+ bool m_latencyMotionStateInterpolation;
+
+ btAlignedObjectArray<btPersistentManifold*> m_predictiveManifolds;
+ btSpinMutex m_predictiveManifoldsMutex; // used to synchronize threads creating predictive contacts
+
+ virtual void predictUnconstraintMotion(btScalar timeStep);
+
+ void integrateTransformsInternal( btRigidBody** bodies, int numBodies, btScalar timeStep ); // can be called in parallel
+ virtual void integrateTransforms(btScalar timeStep);
+
+ virtual void calculateSimulationIslands();
+
+ virtual void solveConstraints(btContactSolverInfo& solverInfo);
+
+ virtual void updateActivationState(btScalar timeStep);
+
+ void updateActions(btScalar timeStep);
+
+ void startProfiling(btScalar timeStep);
+
+ virtual void internalSingleStepSimulation( btScalar timeStep);
+
+ void releasePredictiveContacts();
+ void createPredictiveContactsInternal( btRigidBody** bodies, int numBodies, btScalar timeStep ); // can be called in parallel
+ virtual void createPredictiveContacts(btScalar timeStep);
+
+ virtual void saveKinematicState(btScalar timeStep);
+
+ void serializeRigidBodies(btSerializer* serializer);
+
+ void serializeDynamicsWorldInfo(btSerializer* serializer);
+
+public:
+
+
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ ///this btDiscreteDynamicsWorld constructor gets created objects from the user, and will not delete those
+ btDiscreteDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration);
+
+ virtual ~btDiscreteDynamicsWorld();
+
+ ///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 synchronizeMotionStates();
+
+ ///this can be useful to synchronize a single rigid body -> graphics object
+ void synchronizeSingleMotionState(btRigidBody* body);
+
+ virtual void addConstraint(btTypedConstraint* constraint, bool disableCollisionsBetweenLinkedBodies=false);
+
+ virtual void removeConstraint(btTypedConstraint* constraint);
+
+ virtual void addAction(btActionInterface*);
+
+ virtual void removeAction(btActionInterface*);
+
+ btSimulationIslandManager* getSimulationIslandManager()
+ {
+ return m_islandManager;
+ }
+
+ const btSimulationIslandManager* getSimulationIslandManager() const
+ {
+ return m_islandManager;
+ }
+
+ btCollisionWorld* getCollisionWorld()
+ {
+ return this;
+ }
+
+ virtual void setGravity(const btVector3& gravity);
+
+ virtual btVector3 getGravity () const;
+
+ virtual void addCollisionObject(btCollisionObject* collisionObject, int collisionFilterGroup=btBroadphaseProxy::StaticFilter, int collisionFilterMask=btBroadphaseProxy::AllFilter ^ btBroadphaseProxy::StaticFilter);
+
+ virtual void addRigidBody(btRigidBody* body);
+
+ virtual void addRigidBody(btRigidBody* body, int group, int mask);
+
+ virtual void removeRigidBody(btRigidBody* body);
+
+ ///removeCollisionObject will first check if it is a rigid body, if so call removeRigidBody otherwise call btCollisionWorld::removeCollisionObject
+ virtual void removeCollisionObject(btCollisionObject* collisionObject);
+
+
+ virtual void debugDrawConstraint(btTypedConstraint* constraint);
+
+ virtual void debugDrawWorld();
+
+ virtual void setConstraintSolver(btConstraintSolver* solver);
+
+ virtual btConstraintSolver* getConstraintSolver();
+
+ virtual int getNumConstraints() const;
+
+ virtual btTypedConstraint* getConstraint(int index) ;
+
+ virtual const btTypedConstraint* getConstraint(int index) const;
+
+
+ virtual btDynamicsWorldType getWorldType() const
+ {
+ return BT_DISCRETE_DYNAMICS_WORLD;
+ }
+
+ ///the forces on each rigidbody is accumulating together with gravity. clear this after each timestep.
+ virtual void clearForces();
+
+ ///apply gravity, call this once per timestep
+ virtual void applyGravity();
+
+ virtual void setNumTasks(int numTasks)
+ {
+ (void) numTasks;
+ }
+
+ ///obsolete, use updateActions instead
+ virtual void updateVehicles(btScalar timeStep)
+ {
+ updateActions(timeStep);
+ }
+
+ ///obsolete, use addAction instead
+ virtual void addVehicle(btActionInterface* vehicle);
+ ///obsolete, use removeAction instead
+ virtual void removeVehicle(btActionInterface* vehicle);
+ ///obsolete, use addAction instead
+ virtual void addCharacter(btActionInterface* character);
+ ///obsolete, use removeAction instead
+ virtual void removeCharacter(btActionInterface* character);
+
+ void setSynchronizeAllMotionStates(bool synchronizeAll)
+ {
+ m_synchronizeAllMotionStates = synchronizeAll;
+ }
+ bool getSynchronizeAllMotionStates() const
+ {
+ return m_synchronizeAllMotionStates;
+ }
+
+ void setApplySpeculativeContactRestitution(bool enable)
+ {
+ m_applySpeculativeContactRestitution = enable;
+ }
+
+ bool getApplySpeculativeContactRestitution() const
+ {
+ return m_applySpeculativeContactRestitution;
+ }
+
+ ///Preliminary serialization test for Bullet 2.76. Loading those files requires a separate parser (see Bullet/Demos/SerializeDemo)
+ virtual void serialize(btSerializer* serializer);
+
+ ///Interpolate motion state between previous and current transform, instead of current and next transform.
+ ///This can relieve discontinuities in the rendering, due to penetrations
+ void setLatencyMotionStateInterpolation(bool latencyInterpolation )
+ {
+ m_latencyMotionStateInterpolation = latencyInterpolation;
+ }
+ bool getLatencyMotionStateInterpolation() const
+ {
+ return m_latencyMotionStateInterpolation;
+ }
+};
+
+#endif //BT_DISCRETE_DYNAMICS_WORLD_H
diff --git a/thirdparty/bullet/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.cpp b/thirdparty/bullet/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.cpp
new file mode 100644
index 0000000000..1d10bad922
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.cpp
@@ -0,0 +1,327 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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 "btDiscreteDynamicsWorldMt.h"
+
+//collision detection
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h"
+#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
+#include "BulletCollision/CollisionShapes/btCollisionShape.h"
+#include "btSimulationIslandManagerMt.h"
+#include "LinearMath/btTransformUtil.h"
+#include "LinearMath/btQuickprof.h"
+
+//rigidbody & constraints
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h"
+#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h"
+#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btHingeConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btConeTwistConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h"
+#include "BulletDynamics/ConstraintSolver/btSliderConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btContactConstraint.h"
+
+
+#include "LinearMath/btIDebugDraw.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"
+
+
+#include "BulletDynamics/Dynamics/btActionInterface.h"
+#include "LinearMath/btQuickprof.h"
+#include "LinearMath/btMotionState.h"
+
+#include "LinearMath/btSerializer.h"
+
+
+struct InplaceSolverIslandCallbackMt : public btSimulationIslandManagerMt::IslandCallback
+{
+ btContactSolverInfo* m_solverInfo;
+ btConstraintSolver* m_solver;
+ btIDebugDraw* m_debugDrawer;
+ btDispatcher* m_dispatcher;
+
+ InplaceSolverIslandCallbackMt(
+ btConstraintSolver* solver,
+ btStackAlloc* stackAlloc,
+ btDispatcher* dispatcher)
+ :m_solverInfo(NULL),
+ m_solver(solver),
+ m_debugDrawer(NULL),
+ m_dispatcher(dispatcher)
+ {
+
+ }
+
+ InplaceSolverIslandCallbackMt& operator=(InplaceSolverIslandCallbackMt& other)
+ {
+ btAssert(0);
+ (void)other;
+ return *this;
+ }
+
+ SIMD_FORCE_INLINE void setup ( btContactSolverInfo* solverInfo, btIDebugDraw* debugDrawer)
+ {
+ btAssert(solverInfo);
+ m_solverInfo = solverInfo;
+ m_debugDrawer = debugDrawer;
+ }
+
+
+ virtual void processIsland( btCollisionObject** bodies,
+ int numBodies,
+ btPersistentManifold** manifolds,
+ int numManifolds,
+ btTypedConstraint** constraints,
+ int numConstraints,
+ int islandId
+ )
+ {
+ m_solver->solveGroup( bodies,
+ numBodies,
+ manifolds,
+ numManifolds,
+ constraints,
+ numConstraints,
+ *m_solverInfo,
+ m_debugDrawer,
+ m_dispatcher
+ );
+ }
+
+};
+
+
+///
+/// btConstraintSolverPoolMt
+///
+
+btConstraintSolverPoolMt::ThreadSolver* btConstraintSolverPoolMt::getAndLockThreadSolver()
+{
+ int i = 0;
+#if BT_THREADSAFE
+ i = btGetCurrentThreadIndex() % m_solvers.size();
+#endif // #if BT_THREADSAFE
+ while ( true )
+ {
+ ThreadSolver& solver = m_solvers[ i ];
+ if ( solver.mutex.tryLock() )
+ {
+ return &solver;
+ }
+ // failed, try the next one
+ i = ( i + 1 ) % m_solvers.size();
+ }
+ return NULL;
+}
+
+void btConstraintSolverPoolMt::init( btConstraintSolver** solvers, int numSolvers )
+{
+ m_solverType = BT_SEQUENTIAL_IMPULSE_SOLVER;
+ m_solvers.resize( numSolvers );
+ for ( int i = 0; i < numSolvers; ++i )
+ {
+ m_solvers[ i ].solver = solvers[ i ];
+ }
+ if ( numSolvers > 0 )
+ {
+ m_solverType = solvers[ 0 ]->getSolverType();
+ }
+}
+
+// create the solvers for me
+btConstraintSolverPoolMt::btConstraintSolverPoolMt( int numSolvers )
+{
+ btAlignedObjectArray<btConstraintSolver*> solvers;
+ solvers.reserve( numSolvers );
+ for ( int i = 0; i < numSolvers; ++i )
+ {
+ btConstraintSolver* solver = new btSequentialImpulseConstraintSolver();
+ solvers.push_back( solver );
+ }
+ init( &solvers[ 0 ], numSolvers );
+}
+
+// pass in fully constructed solvers (destructor will delete them)
+btConstraintSolverPoolMt::btConstraintSolverPoolMt( btConstraintSolver** solvers, int numSolvers )
+{
+ init( solvers, numSolvers );
+}
+
+btConstraintSolverPoolMt::~btConstraintSolverPoolMt()
+{
+ // delete all solvers
+ for ( int i = 0; i < m_solvers.size(); ++i )
+ {
+ ThreadSolver& solver = m_solvers[ i ];
+ delete solver.solver;
+ solver.solver = NULL;
+ }
+}
+
+///solve a group of constraints
+btScalar btConstraintSolverPoolMt::solveGroup( btCollisionObject** bodies,
+ int numBodies,
+ btPersistentManifold** manifolds,
+ int numManifolds,
+ btTypedConstraint** constraints,
+ int numConstraints,
+ const btContactSolverInfo& info,
+ btIDebugDraw* debugDrawer,
+ btDispatcher* dispatcher
+)
+{
+ ThreadSolver* ts = getAndLockThreadSolver();
+ ts->solver->solveGroup( bodies, numBodies, manifolds, numManifolds, constraints, numConstraints, info, debugDrawer, dispatcher );
+ ts->mutex.unlock();
+ return 0.0f;
+}
+
+void btConstraintSolverPoolMt::reset()
+{
+ for ( int i = 0; i < m_solvers.size(); ++i )
+ {
+ ThreadSolver& solver = m_solvers[ i ];
+ solver.mutex.lock();
+ solver.solver->reset();
+ solver.mutex.unlock();
+ }
+}
+
+
+///
+/// btDiscreteDynamicsWorldMt
+///
+
+btDiscreteDynamicsWorldMt::btDiscreteDynamicsWorldMt(btDispatcher* dispatcher, btBroadphaseInterface* pairCache, btConstraintSolverPoolMt* constraintSolver, btCollisionConfiguration* collisionConfiguration)
+: btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver,collisionConfiguration)
+{
+ if (m_ownsIslandManager)
+ {
+ m_islandManager->~btSimulationIslandManager();
+ btAlignedFree( m_islandManager);
+ }
+ {
+ void* mem = btAlignedAlloc(sizeof(InplaceSolverIslandCallbackMt),16);
+ m_solverIslandCallbackMt = new (mem) InplaceSolverIslandCallbackMt (m_constraintSolver, 0, dispatcher);
+ }
+ {
+ void* mem = btAlignedAlloc(sizeof(btSimulationIslandManagerMt),16);
+ btSimulationIslandManagerMt* im = new (mem) btSimulationIslandManagerMt();
+ im->setMinimumSolverBatchSize( m_solverInfo.m_minimumSolverBatchSize );
+ m_islandManager = im;
+ }
+}
+
+
+btDiscreteDynamicsWorldMt::~btDiscreteDynamicsWorldMt()
+{
+ if (m_solverIslandCallbackMt)
+ {
+ m_solverIslandCallbackMt->~InplaceSolverIslandCallbackMt();
+ btAlignedFree(m_solverIslandCallbackMt);
+ }
+ if (m_ownsConstraintSolver)
+ {
+ m_constraintSolver->~btConstraintSolver();
+ btAlignedFree(m_constraintSolver);
+ }
+}
+
+
+void btDiscreteDynamicsWorldMt::solveConstraints(btContactSolverInfo& solverInfo)
+{
+ BT_PROFILE("solveConstraints");
+
+ m_solverIslandCallbackMt->setup(&solverInfo, getDebugDrawer());
+ m_constraintSolver->prepareSolve(getCollisionWorld()->getNumCollisionObjects(), getCollisionWorld()->getDispatcher()->getNumManifolds());
+
+ /// solve all the constraints for this island
+ btSimulationIslandManagerMt* im = static_cast<btSimulationIslandManagerMt*>(m_islandManager);
+ im->buildAndProcessIslands( getCollisionWorld()->getDispatcher(), getCollisionWorld(), m_constraints, m_solverIslandCallbackMt );
+
+ m_constraintSolver->allSolved(solverInfo, m_debugDrawer);
+}
+
+
+struct UpdaterUnconstrainedMotion : public btIParallelForBody
+{
+ btScalar timeStep;
+ btRigidBody** rigidBodies;
+
+ void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE
+ {
+ for ( int i = iBegin; i < iEnd; ++i )
+ {
+ btRigidBody* body = rigidBodies[ i ];
+ if ( !body->isStaticOrKinematicObject() )
+ {
+ //don't integrate/update velocities here, it happens in the constraint solver
+ body->applyDamping( timeStep );
+ body->predictIntegratedTransform( timeStep, body->getInterpolationWorldTransform() );
+ }
+ }
+ }
+};
+
+
+void btDiscreteDynamicsWorldMt::predictUnconstraintMotion( btScalar timeStep )
+{
+ BT_PROFILE( "predictUnconstraintMotion" );
+ if ( m_nonStaticRigidBodies.size() > 0 )
+ {
+ UpdaterUnconstrainedMotion update;
+ update.timeStep = timeStep;
+ update.rigidBodies = &m_nonStaticRigidBodies[ 0 ];
+ int grainSize = 50; // num of iterations per task for task scheduler
+ btParallelFor( 0, m_nonStaticRigidBodies.size(), grainSize, update );
+ }
+}
+
+
+void btDiscreteDynamicsWorldMt::createPredictiveContacts( btScalar timeStep )
+{
+ BT_PROFILE( "createPredictiveContacts" );
+ releasePredictiveContacts();
+ if ( m_nonStaticRigidBodies.size() > 0 )
+ {
+ UpdaterCreatePredictiveContacts update;
+ update.world = this;
+ update.timeStep = timeStep;
+ update.rigidBodies = &m_nonStaticRigidBodies[ 0 ];
+ int grainSize = 50; // num of iterations per task for task scheduler
+ btParallelFor( 0, m_nonStaticRigidBodies.size(), grainSize, update );
+ }
+}
+
+
+void btDiscreteDynamicsWorldMt::integrateTransforms( btScalar timeStep )
+{
+ BT_PROFILE( "integrateTransforms" );
+ if ( m_nonStaticRigidBodies.size() > 0 )
+ {
+ UpdaterIntegrateTransforms update;
+ update.world = this;
+ update.timeStep = timeStep;
+ update.rigidBodies = &m_nonStaticRigidBodies[ 0 ];
+ int grainSize = 50; // num of iterations per task for task scheduler
+ btParallelFor( 0, m_nonStaticRigidBodies.size(), grainSize, update );
+ }
+}
+
diff --git a/thirdparty/bullet/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.h b/thirdparty/bullet/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.h
new file mode 100644
index 0000000000..2f144cdda4
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.h
@@ -0,0 +1,134 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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_DISCRETE_DYNAMICS_WORLD_MT_H
+#define BT_DISCRETE_DYNAMICS_WORLD_MT_H
+
+#include "btDiscreteDynamicsWorld.h"
+#include "btSimulationIslandManagerMt.h"
+#include "BulletDynamics/ConstraintSolver/btConstraintSolver.h"
+
+struct InplaceSolverIslandCallbackMt;
+
+///
+/// btConstraintSolverPoolMt - masquerades as a constraint solver, but really it is a threadsafe pool of them.
+///
+/// Each solver in the pool is protected by a mutex. When solveGroup is called from a thread,
+/// the pool looks for a solver that isn't being used by another thread, locks it, and dispatches the
+/// call to the solver.
+/// So long as there are at least as many solvers as there are hardware threads, it should never need to
+/// spin wait.
+///
+class btConstraintSolverPoolMt : public btConstraintSolver
+{
+public:
+ // create the solvers for me
+ explicit btConstraintSolverPoolMt( int numSolvers );
+
+ // pass in fully constructed solvers (destructor will delete them)
+ btConstraintSolverPoolMt( btConstraintSolver** solvers, int numSolvers );
+
+ virtual ~btConstraintSolverPoolMt();
+
+ ///solve a group of constraints
+ virtual btScalar solveGroup( btCollisionObject** bodies,
+ int numBodies,
+ btPersistentManifold** manifolds,
+ int numManifolds,
+ btTypedConstraint** constraints,
+ int numConstraints,
+ const btContactSolverInfo& info,
+ btIDebugDraw* debugDrawer,
+ btDispatcher* dispatcher
+ ) BT_OVERRIDE;
+
+ virtual void reset() BT_OVERRIDE;
+ virtual btConstraintSolverType getSolverType() const BT_OVERRIDE { return m_solverType; }
+
+private:
+ const static size_t kCacheLineSize = 128;
+ struct ThreadSolver
+ {
+ btConstraintSolver* solver;
+ btSpinMutex mutex;
+ char _cachelinePadding[ kCacheLineSize - sizeof( btSpinMutex ) - sizeof( void* ) ]; // keep mutexes from sharing a cache line
+ };
+ btAlignedObjectArray<ThreadSolver> m_solvers;
+ btConstraintSolverType m_solverType;
+
+ ThreadSolver* getAndLockThreadSolver();
+ void init( btConstraintSolver** solvers, int numSolvers );
+};
+
+
+
+///
+/// btDiscreteDynamicsWorldMt -- a version of DiscreteDynamicsWorld with some minor changes to support
+/// solving simulation islands on multiple threads.
+///
+/// Should function exactly like btDiscreteDynamicsWorld.
+/// Also 3 methods that iterate over all of the rigidbodies can run in parallel:
+/// - predictUnconstraintMotion
+/// - integrateTransforms
+/// - createPredictiveContacts
+///
+ATTRIBUTE_ALIGNED16(class) btDiscreteDynamicsWorldMt : public btDiscreteDynamicsWorld
+{
+protected:
+ InplaceSolverIslandCallbackMt* m_solverIslandCallbackMt;
+
+ virtual void solveConstraints(btContactSolverInfo& solverInfo) BT_OVERRIDE;
+
+ virtual void predictUnconstraintMotion( btScalar timeStep ) BT_OVERRIDE;
+
+ struct UpdaterCreatePredictiveContacts : public btIParallelForBody
+ {
+ btScalar timeStep;
+ btRigidBody** rigidBodies;
+ btDiscreteDynamicsWorldMt* world;
+
+ void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE
+ {
+ world->createPredictiveContactsInternal( &rigidBodies[ iBegin ], iEnd - iBegin, timeStep );
+ }
+ };
+ virtual void createPredictiveContacts( btScalar timeStep ) BT_OVERRIDE;
+
+ struct UpdaterIntegrateTransforms : public btIParallelForBody
+ {
+ btScalar timeStep;
+ btRigidBody** rigidBodies;
+ btDiscreteDynamicsWorldMt* world;
+
+ void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE
+ {
+ world->integrateTransformsInternal( &rigidBodies[ iBegin ], iEnd - iBegin, timeStep );
+ }
+ };
+ virtual void integrateTransforms( btScalar timeStep ) BT_OVERRIDE;
+
+public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ btDiscreteDynamicsWorldMt(btDispatcher* dispatcher,
+ btBroadphaseInterface* pairCache,
+ btConstraintSolverPoolMt* constraintSolver, // Note this should be a solver-pool for multi-threading
+ btCollisionConfiguration* collisionConfiguration
+ );
+ virtual ~btDiscreteDynamicsWorldMt();
+};
+
+#endif //BT_DISCRETE_DYNAMICS_WORLD_H
diff --git a/thirdparty/bullet/src/BulletDynamics/Dynamics/btDynamicsWorld.h b/thirdparty/bullet/src/BulletDynamics/Dynamics/btDynamicsWorld.h
new file mode 100644
index 0000000000..42d8fc0de3
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/Dynamics/btDynamicsWorld.h
@@ -0,0 +1,173 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_DYNAMICS_WORLD_H
+#define BT_DYNAMICS_WORLD_H
+
+#include "BulletCollision/CollisionDispatch/btCollisionWorld.h"
+#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h"
+
+class btTypedConstraint;
+class btActionInterface;
+class btConstraintSolver;
+class btDynamicsWorld;
+
+
+/// Type for the callback for each tick
+typedef void (*btInternalTickCallback)(btDynamicsWorld *world, btScalar timeStep);
+
+enum btDynamicsWorldType
+{
+ BT_SIMPLE_DYNAMICS_WORLD=1,
+ BT_DISCRETE_DYNAMICS_WORLD=2,
+ BT_CONTINUOUS_DYNAMICS_WORLD=3,
+ BT_SOFT_RIGID_DYNAMICS_WORLD=4,
+ BT_GPU_DYNAMICS_WORLD=5,
+ BT_SOFT_MULTIBODY_DYNAMICS_WORLD=6
+};
+
+///The btDynamicsWorld is the interface class for several dynamics implementation, basic, discrete, parallel, and continuous etc.
+class btDynamicsWorld : public btCollisionWorld
+{
+
+protected:
+ btInternalTickCallback m_internalTickCallback;
+ btInternalTickCallback m_internalPreTickCallback;
+ void* m_worldUserInfo;
+
+ btContactSolverInfo m_solverInfo;
+
+public:
+
+
+ btDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* broadphase,btCollisionConfiguration* collisionConfiguration)
+ :btCollisionWorld(dispatcher,broadphase,collisionConfiguration), m_internalTickCallback(0),m_internalPreTickCallback(0), m_worldUserInfo(0)
+ {
+ }
+
+ virtual ~btDynamicsWorld()
+ {
+ }
+
+ ///stepSimulation proceeds the simulation over 'timeStep', units in preferably in seconds.
+ ///By default, Bullet will subdivide the timestep in constant substeps of each 'fixedTimeStep'.
+ ///in order to keep the simulation real-time, the maximum number of substeps can be clamped to 'maxSubSteps'.
+ ///You can disable subdividing the timestep/substepping by passing maxSubSteps=0 as second argument to stepSimulation, but in that case you have to keep the timeStep constant.
+ virtual int stepSimulation( btScalar timeStep,int maxSubSteps=1, btScalar fixedTimeStep=btScalar(1.)/btScalar(60.))=0;
+
+ virtual void debugDrawWorld() = 0;
+
+ virtual void addConstraint(btTypedConstraint* constraint, bool disableCollisionsBetweenLinkedBodies=false)
+ {
+ (void)constraint; (void)disableCollisionsBetweenLinkedBodies;
+ }
+
+ virtual void removeConstraint(btTypedConstraint* constraint) {(void)constraint;}
+
+ virtual void addAction(btActionInterface* action) = 0;
+
+ virtual void removeAction(btActionInterface* action) = 0;
+
+ //once a rigidbody is added to the dynamics world, it will get this gravity assigned
+ //existing rigidbodies in the world get gravity assigned too, during this method
+ virtual void setGravity(const btVector3& gravity) = 0;
+ virtual btVector3 getGravity () const = 0;
+
+ virtual void synchronizeMotionStates() = 0;
+
+ virtual void addRigidBody(btRigidBody* body) = 0;
+
+ virtual void addRigidBody(btRigidBody* body, int group, int mask) = 0;
+
+ virtual void removeRigidBody(btRigidBody* body) = 0;
+
+ virtual void setConstraintSolver(btConstraintSolver* solver) = 0;
+
+ virtual btConstraintSolver* getConstraintSolver() = 0;
+
+ virtual int getNumConstraints() const { return 0; }
+
+ virtual btTypedConstraint* getConstraint(int index) { (void)index; return 0; }
+
+ virtual const btTypedConstraint* getConstraint(int index) const { (void)index; return 0; }
+
+ virtual btDynamicsWorldType getWorldType() const=0;
+
+ virtual void clearForces() = 0;
+
+ /// Set the callback for when an internal tick (simulation substep) happens, optional user info
+ void setInternalTickCallback(btInternalTickCallback cb, void* worldUserInfo=0,bool isPreTick=false)
+ {
+ if (isPreTick)
+ {
+ m_internalPreTickCallback = cb;
+ } else
+ {
+ m_internalTickCallback = cb;
+ }
+ m_worldUserInfo = worldUserInfo;
+ }
+
+ void setWorldUserInfo(void* worldUserInfo)
+ {
+ m_worldUserInfo = worldUserInfo;
+ }
+
+ void* getWorldUserInfo() const
+ {
+ return m_worldUserInfo;
+ }
+
+ btContactSolverInfo& getSolverInfo()
+ {
+ return m_solverInfo;
+ }
+
+ const btContactSolverInfo& getSolverInfo() const
+ {
+ return m_solverInfo;
+ }
+
+
+ ///obsolete, use addAction instead.
+ virtual void addVehicle(btActionInterface* vehicle) {(void)vehicle;}
+ ///obsolete, use removeAction instead
+ virtual void removeVehicle(btActionInterface* vehicle) {(void)vehicle;}
+ ///obsolete, use addAction instead.
+ virtual void addCharacter(btActionInterface* character) {(void)character;}
+ ///obsolete, use removeAction instead
+ virtual void removeCharacter(btActionInterface* character) {(void)character;}
+
+
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btDynamicsWorldDoubleData
+{
+ btContactSolverInfoDoubleData m_solverInfo;
+ btVector3DoubleData m_gravity;
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btDynamicsWorldFloatData
+{
+ btContactSolverInfoFloatData m_solverInfo;
+ btVector3FloatData m_gravity;
+};
+
+
+#endif //BT_DYNAMICS_WORLD_H
+
+
diff --git a/thirdparty/bullet/src/BulletDynamics/Dynamics/btRigidBody.cpp b/thirdparty/bullet/src/BulletDynamics/Dynamics/btRigidBody.cpp
new file mode 100644
index 0000000000..ca0714fcfa
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/Dynamics/btRigidBody.cpp
@@ -0,0 +1,527 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btRigidBody.h"
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+#include "LinearMath/btMinMax.h"
+#include "LinearMath/btTransformUtil.h"
+#include "LinearMath/btMotionState.h"
+#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
+#include "LinearMath/btSerializer.h"
+
+//'temporarily' global variables
+btScalar gDeactivationTime = btScalar(2.);
+bool gDisableDeactivation = false;
+static int uniqueId = 0;
+
+
+btRigidBody::btRigidBody(const btRigidBody::btRigidBodyConstructionInfo& constructionInfo)
+{
+ setupRigidBody(constructionInfo);
+}
+
+btRigidBody::btRigidBody(btScalar mass, btMotionState *motionState, btCollisionShape *collisionShape, const btVector3 &localInertia)
+{
+ btRigidBodyConstructionInfo cinfo(mass,motionState,collisionShape,localInertia);
+ setupRigidBody(cinfo);
+}
+
+void btRigidBody::setupRigidBody(const btRigidBody::btRigidBodyConstructionInfo& constructionInfo)
+{
+
+ m_internalType=CO_RIGID_BODY;
+
+ m_linearVelocity.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
+ m_angularVelocity.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
+ m_angularFactor.setValue(1,1,1);
+ m_linearFactor.setValue(1,1,1);
+ m_gravity.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
+ m_gravity_acceleration.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
+ m_totalForce.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
+ m_totalTorque.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)),
+ setDamping(constructionInfo.m_linearDamping, constructionInfo.m_angularDamping);
+
+ m_linearSleepingThreshold = constructionInfo.m_linearSleepingThreshold;
+ m_angularSleepingThreshold = constructionInfo.m_angularSleepingThreshold;
+ m_optionalMotionState = constructionInfo.m_motionState;
+ m_contactSolverType = 0;
+ m_frictionSolverType = 0;
+ m_additionalDamping = constructionInfo.m_additionalDamping;
+ m_additionalDampingFactor = constructionInfo.m_additionalDampingFactor;
+ m_additionalLinearDampingThresholdSqr = constructionInfo.m_additionalLinearDampingThresholdSqr;
+ m_additionalAngularDampingThresholdSqr = constructionInfo.m_additionalAngularDampingThresholdSqr;
+ m_additionalAngularDampingFactor = constructionInfo.m_additionalAngularDampingFactor;
+
+ if (m_optionalMotionState)
+ {
+ m_optionalMotionState->getWorldTransform(m_worldTransform);
+ } else
+ {
+ m_worldTransform = constructionInfo.m_startWorldTransform;
+ }
+
+ m_interpolationWorldTransform = m_worldTransform;
+ m_interpolationLinearVelocity.setValue(0,0,0);
+ m_interpolationAngularVelocity.setValue(0,0,0);
+
+ //moved to btCollisionObject
+ m_friction = constructionInfo.m_friction;
+ m_rollingFriction = constructionInfo.m_rollingFriction;
+ m_spinningFriction = constructionInfo.m_spinningFriction;
+
+ m_restitution = constructionInfo.m_restitution;
+
+ setCollisionShape( constructionInfo.m_collisionShape );
+ m_debugBodyId = uniqueId++;
+
+ setMassProps(constructionInfo.m_mass, constructionInfo.m_localInertia);
+ updateInertiaTensor();
+
+ m_rigidbodyFlags = BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_BODY;
+
+
+ m_deltaLinearVelocity.setZero();
+ m_deltaAngularVelocity.setZero();
+ m_invMass = m_inverseMass*m_linearFactor;
+ m_pushVelocity.setZero();
+ m_turnVelocity.setZero();
+
+
+
+}
+
+
+void btRigidBody::predictIntegratedTransform(btScalar timeStep,btTransform& predictedTransform)
+{
+ btTransformUtil::integrateTransform(m_worldTransform,m_linearVelocity,m_angularVelocity,timeStep,predictedTransform);
+}
+
+void btRigidBody::saveKinematicState(btScalar timeStep)
+{
+ //todo: clamp to some (user definable) safe minimum timestep, to limit maximum angular/linear velocities
+ if (timeStep != btScalar(0.))
+ {
+ //if we use motionstate to synchronize world transforms, get the new kinematic/animated world transform
+ if (getMotionState())
+ getMotionState()->getWorldTransform(m_worldTransform);
+ btVector3 linVel,angVel;
+
+ btTransformUtil::calculateVelocity(m_interpolationWorldTransform,m_worldTransform,timeStep,m_linearVelocity,m_angularVelocity);
+ m_interpolationLinearVelocity = m_linearVelocity;
+ m_interpolationAngularVelocity = m_angularVelocity;
+ m_interpolationWorldTransform = m_worldTransform;
+ //printf("angular = %f %f %f\n",m_angularVelocity.getX(),m_angularVelocity.getY(),m_angularVelocity.getZ());
+ }
+}
+
+void btRigidBody::getAabb(btVector3& aabbMin,btVector3& aabbMax) const
+{
+ getCollisionShape()->getAabb(m_worldTransform,aabbMin,aabbMax);
+}
+
+
+
+
+void btRigidBody::setGravity(const btVector3& acceleration)
+{
+ if (m_inverseMass != btScalar(0.0))
+ {
+ m_gravity = acceleration * (btScalar(1.0) / m_inverseMass);
+ }
+ m_gravity_acceleration = acceleration;
+}
+
+
+
+
+
+
+void btRigidBody::setDamping(btScalar lin_damping, btScalar ang_damping)
+{
+ m_linearDamping = btClamped(lin_damping, (btScalar)btScalar(0.0), (btScalar)btScalar(1.0));
+ m_angularDamping = btClamped(ang_damping, (btScalar)btScalar(0.0), (btScalar)btScalar(1.0));
+}
+
+
+
+
+///applyDamping damps the velocity, using the given m_linearDamping and m_angularDamping
+void btRigidBody::applyDamping(btScalar timeStep)
+{
+ //On new damping: see discussion/issue report here: http://code.google.com/p/bullet/issues/detail?id=74
+ //todo: do some performance comparisons (but other parts of the engine are probably bottleneck anyway
+
+//#define USE_OLD_DAMPING_METHOD 1
+#ifdef USE_OLD_DAMPING_METHOD
+ m_linearVelocity *= GEN_clamped((btScalar(1.) - timeStep * m_linearDamping), (btScalar)btScalar(0.0), (btScalar)btScalar(1.0));
+ m_angularVelocity *= GEN_clamped((btScalar(1.) - timeStep * m_angularDamping), (btScalar)btScalar(0.0), (btScalar)btScalar(1.0));
+#else
+ m_linearVelocity *= btPow(btScalar(1)-m_linearDamping, timeStep);
+ m_angularVelocity *= btPow(btScalar(1)-m_angularDamping, timeStep);
+#endif
+
+ if (m_additionalDamping)
+ {
+ //Additional damping can help avoiding lowpass jitter motion, help stability for ragdolls etc.
+ //Such damping is undesirable, so once the overall simulation quality of the rigid body dynamics system has improved, this should become obsolete
+ if ((m_angularVelocity.length2() < m_additionalAngularDampingThresholdSqr) &&
+ (m_linearVelocity.length2() < m_additionalLinearDampingThresholdSqr))
+ {
+ m_angularVelocity *= m_additionalDampingFactor;
+ m_linearVelocity *= m_additionalDampingFactor;
+ }
+
+
+ btScalar speed = m_linearVelocity.length();
+ if (speed < m_linearDamping)
+ {
+ btScalar dampVel = btScalar(0.005);
+ if (speed > dampVel)
+ {
+ btVector3 dir = m_linearVelocity.normalized();
+ m_linearVelocity -= dir * dampVel;
+ } else
+ {
+ m_linearVelocity.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
+ }
+ }
+
+ btScalar angSpeed = m_angularVelocity.length();
+ if (angSpeed < m_angularDamping)
+ {
+ btScalar angDampVel = btScalar(0.005);
+ if (angSpeed > angDampVel)
+ {
+ btVector3 dir = m_angularVelocity.normalized();
+ m_angularVelocity -= dir * angDampVel;
+ } else
+ {
+ m_angularVelocity.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
+ }
+ }
+ }
+}
+
+
+void btRigidBody::applyGravity()
+{
+ if (isStaticOrKinematicObject())
+ return;
+
+ applyCentralForce(m_gravity);
+
+}
+
+void btRigidBody::proceedToTransform(const btTransform& newTrans)
+{
+ setCenterOfMassTransform( newTrans );
+}
+
+
+void btRigidBody::setMassProps(btScalar mass, const btVector3& inertia)
+{
+ if (mass == btScalar(0.))
+ {
+ m_collisionFlags |= btCollisionObject::CF_STATIC_OBJECT;
+ m_inverseMass = btScalar(0.);
+ } else
+ {
+ m_collisionFlags &= (~btCollisionObject::CF_STATIC_OBJECT);
+ m_inverseMass = btScalar(1.0) / mass;
+ }
+
+ //Fg = m * a
+ m_gravity = mass * m_gravity_acceleration;
+
+ m_invInertiaLocal.setValue(inertia.x() != btScalar(0.0) ? btScalar(1.0) / inertia.x(): btScalar(0.0),
+ inertia.y() != btScalar(0.0) ? btScalar(1.0) / inertia.y(): btScalar(0.0),
+ inertia.z() != btScalar(0.0) ? btScalar(1.0) / inertia.z(): btScalar(0.0));
+
+ m_invMass = m_linearFactor*m_inverseMass;
+}
+
+
+void btRigidBody::updateInertiaTensor()
+{
+ m_invInertiaTensorWorld = m_worldTransform.getBasis().scaled(m_invInertiaLocal) * m_worldTransform.getBasis().transpose();
+}
+
+
+
+btVector3 btRigidBody::getLocalInertia() const
+{
+
+ btVector3 inertiaLocal;
+ const btVector3 inertia = m_invInertiaLocal;
+ inertiaLocal.setValue(inertia.x() != btScalar(0.0) ? btScalar(1.0) / inertia.x() : btScalar(0.0),
+ inertia.y() != btScalar(0.0) ? btScalar(1.0) / inertia.y() : btScalar(0.0),
+ inertia.z() != btScalar(0.0) ? btScalar(1.0) / inertia.z() : btScalar(0.0));
+ return inertiaLocal;
+}
+
+inline btVector3 evalEulerEqn(const btVector3& w1, const btVector3& w0, const btVector3& T, const btScalar dt,
+ const btMatrix3x3 &I)
+{
+ const btVector3 w2 = I*w1 + w1.cross(I*w1)*dt - (T*dt + I*w0);
+ return w2;
+}
+
+inline btMatrix3x3 evalEulerEqnDeriv(const btVector3& w1, const btVector3& w0, const btScalar dt,
+ const btMatrix3x3 &I)
+{
+
+ btMatrix3x3 w1x, Iw1x;
+ const btVector3 Iwi = (I*w1);
+ w1.getSkewSymmetricMatrix(&w1x[0], &w1x[1], &w1x[2]);
+ Iwi.getSkewSymmetricMatrix(&Iw1x[0], &Iw1x[1], &Iw1x[2]);
+
+ const btMatrix3x3 dfw1 = I + (w1x*I - Iw1x)*dt;
+ return dfw1;
+}
+
+btVector3 btRigidBody::computeGyroscopicForceExplicit(btScalar maxGyroscopicForce) const
+{
+ btVector3 inertiaLocal = getLocalInertia();
+ btMatrix3x3 inertiaTensorWorld = getWorldTransform().getBasis().scaled(inertiaLocal) * getWorldTransform().getBasis().transpose();
+ btVector3 tmp = inertiaTensorWorld*getAngularVelocity();
+ btVector3 gf = getAngularVelocity().cross(tmp);
+ btScalar l2 = gf.length2();
+ if (l2>maxGyroscopicForce*maxGyroscopicForce)
+ {
+ gf *= btScalar(1.)/btSqrt(l2)*maxGyroscopicForce;
+ }
+ return gf;
+}
+
+
+btVector3 btRigidBody::computeGyroscopicImpulseImplicit_Body(btScalar step) const
+{
+ btVector3 idl = getLocalInertia();
+ btVector3 omega1 = getAngularVelocity();
+ btQuaternion q = getWorldTransform().getRotation();
+
+ // Convert to body coordinates
+ btVector3 omegab = quatRotate(q.inverse(), omega1);
+ btMatrix3x3 Ib;
+ Ib.setValue(idl.x(),0,0,
+ 0,idl.y(),0,
+ 0,0,idl.z());
+
+ btVector3 ibo = Ib*omegab;
+
+ // Residual vector
+ btVector3 f = step * omegab.cross(ibo);
+
+ btMatrix3x3 skew0;
+ omegab.getSkewSymmetricMatrix(&skew0[0], &skew0[1], &skew0[2]);
+ btVector3 om = Ib*omegab;
+ btMatrix3x3 skew1;
+ om.getSkewSymmetricMatrix(&skew1[0],&skew1[1],&skew1[2]);
+
+ // Jacobian
+ btMatrix3x3 J = Ib + (skew0*Ib - skew1)*step;
+
+// btMatrix3x3 Jinv = J.inverse();
+// btVector3 omega_div = Jinv*f;
+ btVector3 omega_div = J.solve33(f);
+
+ // Single Newton-Raphson update
+ omegab = omegab - omega_div;//Solve33(J, f);
+ // Back to world coordinates
+ btVector3 omega2 = quatRotate(q,omegab);
+ btVector3 gf = omega2-omega1;
+ return gf;
+}
+
+
+
+btVector3 btRigidBody::computeGyroscopicImpulseImplicit_World(btScalar step) const
+{
+ // use full newton-euler equations. common practice to drop the wxIw term. want it for better tumbling behavior.
+ // calculate using implicit euler step so it's stable.
+
+ const btVector3 inertiaLocal = getLocalInertia();
+ const btVector3 w0 = getAngularVelocity();
+
+ btMatrix3x3 I;
+
+ I = m_worldTransform.getBasis().scaled(inertiaLocal) *
+ m_worldTransform.getBasis().transpose();
+
+ // use newtons method to find implicit solution for new angular velocity (w')
+ // f(w') = -(T*step + Iw) + Iw' + w' + w'xIw'*step = 0
+ // df/dw' = I + 1xIw'*step + w'xI*step
+
+ btVector3 w1 = w0;
+
+ // one step of newton's method
+ {
+ const btVector3 fw = evalEulerEqn(w1, w0, btVector3(0, 0, 0), step, I);
+ const btMatrix3x3 dfw = evalEulerEqnDeriv(w1, w0, step, I);
+
+ btVector3 dw;
+ dw = dfw.solve33(fw);
+ //const btMatrix3x3 dfw_inv = dfw.inverse();
+ //dw = dfw_inv*fw;
+
+ w1 -= dw;
+ }
+
+ btVector3 gf = (w1 - w0);
+ return gf;
+}
+
+
+void btRigidBody::integrateVelocities(btScalar step)
+{
+ if (isStaticOrKinematicObject())
+ return;
+
+ m_linearVelocity += m_totalForce * (m_inverseMass * step);
+ m_angularVelocity += m_invInertiaTensorWorld * m_totalTorque * step;
+
+#define MAX_ANGVEL SIMD_HALF_PI
+ /// clamp angular velocity. collision calculations will fail on higher angular velocities
+ btScalar angvel = m_angularVelocity.length();
+ if (angvel*step > MAX_ANGVEL)
+ {
+ m_angularVelocity *= (MAX_ANGVEL/step) /angvel;
+ }
+
+}
+
+btQuaternion btRigidBody::getOrientation() const
+{
+ btQuaternion orn;
+ m_worldTransform.getBasis().getRotation(orn);
+ return orn;
+}
+
+
+void btRigidBody::setCenterOfMassTransform(const btTransform& xform)
+{
+
+ if (isKinematicObject())
+ {
+ m_interpolationWorldTransform = m_worldTransform;
+ } else
+ {
+ m_interpolationWorldTransform = xform;
+ }
+ m_interpolationLinearVelocity = getLinearVelocity();
+ m_interpolationAngularVelocity = getAngularVelocity();
+ m_worldTransform = xform;
+ updateInertiaTensor();
+}
+
+
+
+
+
+void btRigidBody::addConstraintRef(btTypedConstraint* c)
+{
+ ///disable collision with the 'other' body
+
+ int index = m_constraintRefs.findLinearSearch(c);
+ //don't add constraints that are already referenced
+ //btAssert(index == m_constraintRefs.size());
+ if (index == m_constraintRefs.size())
+ {
+ m_constraintRefs.push_back(c);
+ btCollisionObject* colObjA = &c->getRigidBodyA();
+ btCollisionObject* colObjB = &c->getRigidBodyB();
+ if (colObjA == this)
+ {
+ colObjA->setIgnoreCollisionCheck(colObjB, true);
+ }
+ else
+ {
+ colObjB->setIgnoreCollisionCheck(colObjA, true);
+ }
+ }
+}
+
+void btRigidBody::removeConstraintRef(btTypedConstraint* c)
+{
+ int index = m_constraintRefs.findLinearSearch(c);
+ //don't remove constraints that are not referenced
+ if(index < m_constraintRefs.size())
+ {
+ m_constraintRefs.remove(c);
+ btCollisionObject* colObjA = &c->getRigidBodyA();
+ btCollisionObject* colObjB = &c->getRigidBodyB();
+ if (colObjA == this)
+ {
+ colObjA->setIgnoreCollisionCheck(colObjB, false);
+ }
+ else
+ {
+ colObjB->setIgnoreCollisionCheck(colObjA, false);
+ }
+ }
+}
+
+int btRigidBody::calculateSerializeBufferSize() const
+{
+ int sz = sizeof(btRigidBodyData);
+ return sz;
+}
+
+ ///fills the dataBuffer and returns the struct name (and 0 on failure)
+const char* btRigidBody::serialize(void* dataBuffer, class btSerializer* serializer) const
+{
+ btRigidBodyData* rbd = (btRigidBodyData*) dataBuffer;
+
+ btCollisionObject::serialize(&rbd->m_collisionObjectData, serializer);
+
+ m_invInertiaTensorWorld.serialize(rbd->m_invInertiaTensorWorld);
+ m_linearVelocity.serialize(rbd->m_linearVelocity);
+ m_angularVelocity.serialize(rbd->m_angularVelocity);
+ rbd->m_inverseMass = m_inverseMass;
+ m_angularFactor.serialize(rbd->m_angularFactor);
+ m_linearFactor.serialize(rbd->m_linearFactor);
+ m_gravity.serialize(rbd->m_gravity);
+ m_gravity_acceleration.serialize(rbd->m_gravity_acceleration);
+ m_invInertiaLocal.serialize(rbd->m_invInertiaLocal);
+ m_totalForce.serialize(rbd->m_totalForce);
+ m_totalTorque.serialize(rbd->m_totalTorque);
+ rbd->m_linearDamping = m_linearDamping;
+ rbd->m_angularDamping = m_angularDamping;
+ rbd->m_additionalDamping = m_additionalDamping;
+ rbd->m_additionalDampingFactor = m_additionalDampingFactor;
+ rbd->m_additionalLinearDampingThresholdSqr = m_additionalLinearDampingThresholdSqr;
+ rbd->m_additionalAngularDampingThresholdSqr = m_additionalAngularDampingThresholdSqr;
+ rbd->m_additionalAngularDampingFactor = m_additionalAngularDampingFactor;
+ rbd->m_linearSleepingThreshold=m_linearSleepingThreshold;
+ rbd->m_angularSleepingThreshold = m_angularSleepingThreshold;
+
+ // Fill padding with zeros to appease msan.
+#ifdef BT_USE_DOUBLE_PRECISION
+ memset(rbd->m_padding, 0, sizeof(rbd->m_padding));
+#endif
+
+ return btRigidBodyDataName;
+}
+
+
+
+void btRigidBody::serializeSingleObject(class btSerializer* serializer) const
+{
+ btChunk* chunk = serializer->allocate(calculateSerializeBufferSize(),1);
+ const char* structType = serialize(chunk->m_oldPtr, serializer);
+ serializer->finalizeChunk(chunk,structType,BT_RIGIDBODY_CODE,(void*)this);
+}
+
+
diff --git a/thirdparty/bullet/src/BulletDynamics/Dynamics/btRigidBody.h b/thirdparty/bullet/src/BulletDynamics/Dynamics/btRigidBody.h
new file mode 100644
index 0000000000..372245031b
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/Dynamics/btRigidBody.h
@@ -0,0 +1,619 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_RIGIDBODY_H
+#define BT_RIGIDBODY_H
+
+#include "LinearMath/btAlignedObjectArray.h"
+#include "LinearMath/btTransform.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+
+class btCollisionShape;
+class btMotionState;
+class btTypedConstraint;
+
+
+extern btScalar gDeactivationTime;
+extern bool gDisableDeactivation;
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define btRigidBodyData btRigidBodyDoubleData
+#define btRigidBodyDataName "btRigidBodyDoubleData"
+#else
+#define btRigidBodyData btRigidBodyFloatData
+#define btRigidBodyDataName "btRigidBodyFloatData"
+#endif //BT_USE_DOUBLE_PRECISION
+
+
+enum btRigidBodyFlags
+{
+ BT_DISABLE_WORLD_GRAVITY = 1,
+ ///BT_ENABLE_GYROPSCOPIC_FORCE flags is enabled by default in Bullet 2.83 and onwards.
+ ///and it BT_ENABLE_GYROPSCOPIC_FORCE becomes equivalent to BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_BODY
+ ///See Demos/GyroscopicDemo and computeGyroscopicImpulseImplicit
+ BT_ENABLE_GYROSCOPIC_FORCE_EXPLICIT = 2,
+ BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_WORLD=4,
+ BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_BODY=8,
+ BT_ENABLE_GYROPSCOPIC_FORCE = BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_BODY,
+};
+
+
+///The btRigidBody is the main class for rigid body objects. It is derived from btCollisionObject, so it keeps a pointer to a btCollisionShape.
+///It is recommended for performance and memory use to share btCollisionShape objects whenever possible.
+///There are 3 types of rigid bodies:
+///- A) Dynamic rigid bodies, with positive mass. Motion is controlled by rigid body dynamics.
+///- B) Fixed objects with zero mass. They are not moving (basically collision objects)
+///- C) Kinematic objects, which are objects without mass, but the user can move them. There is on-way interaction, and Bullet calculates a velocity based on the timestep and previous and current world transform.
+///Bullet automatically deactivates dynamic rigid bodies, when the velocity is below a threshold for a given time.
+///Deactivated (sleeping) rigid bodies don't take any processing time, except a minor broadphase collision detection impact (to allow active objects to activate/wake up sleeping objects)
+class btRigidBody : public btCollisionObject
+{
+
+ btMatrix3x3 m_invInertiaTensorWorld;
+ btVector3 m_linearVelocity;
+ btVector3 m_angularVelocity;
+ btScalar m_inverseMass;
+ btVector3 m_linearFactor;
+
+ btVector3 m_gravity;
+ btVector3 m_gravity_acceleration;
+ btVector3 m_invInertiaLocal;
+ btVector3 m_totalForce;
+ btVector3 m_totalTorque;
+
+ btScalar m_linearDamping;
+ btScalar m_angularDamping;
+
+ bool m_additionalDamping;
+ btScalar m_additionalDampingFactor;
+ btScalar m_additionalLinearDampingThresholdSqr;
+ btScalar m_additionalAngularDampingThresholdSqr;
+ btScalar m_additionalAngularDampingFactor;
+
+
+ btScalar m_linearSleepingThreshold;
+ btScalar m_angularSleepingThreshold;
+
+ //m_optionalMotionState allows to automatic synchronize the world transform for active objects
+ btMotionState* m_optionalMotionState;
+
+ //keep track of typed constraints referencing this rigid body, to disable collision between linked bodies
+ btAlignedObjectArray<btTypedConstraint*> m_constraintRefs;
+
+ int m_rigidbodyFlags;
+
+ int m_debugBodyId;
+
+
+protected:
+
+ ATTRIBUTE_ALIGNED16(btVector3 m_deltaLinearVelocity);
+ btVector3 m_deltaAngularVelocity;
+ btVector3 m_angularFactor;
+ btVector3 m_invMass;
+ btVector3 m_pushVelocity;
+ btVector3 m_turnVelocity;
+
+
+public:
+
+
+ ///The btRigidBodyConstructionInfo structure provides information to create a rigid body. Setting mass to zero creates a fixed (non-dynamic) rigid body.
+ ///For dynamic objects, you can use the collision shape to approximate the local inertia tensor, otherwise use the zero vector (default argument)
+ ///You can use the motion state to synchronize the world transform between physics and graphics objects.
+ ///And if the motion state is provided, the rigid body will initialize its initial world transform from the motion state,
+ ///m_startWorldTransform is only used when you don't provide a motion state.
+ struct btRigidBodyConstructionInfo
+ {
+ btScalar m_mass;
+
+ ///When a motionState is provided, the rigid body will initialize its world transform from the motion state
+ ///In this case, m_startWorldTransform is ignored.
+ btMotionState* m_motionState;
+ btTransform m_startWorldTransform;
+
+ btCollisionShape* m_collisionShape;
+ btVector3 m_localInertia;
+ btScalar m_linearDamping;
+ btScalar m_angularDamping;
+
+ ///best simulation results when friction is non-zero
+ btScalar m_friction;
+ ///the m_rollingFriction prevents rounded shapes, such as spheres, cylinders and capsules from rolling forever.
+ ///See Bullet/Demos/RollingFrictionDemo for usage
+ btScalar m_rollingFriction;
+ btScalar m_spinningFriction;//torsional friction around contact normal
+
+ ///best simulation results using zero restitution.
+ btScalar m_restitution;
+
+ btScalar m_linearSleepingThreshold;
+ btScalar m_angularSleepingThreshold;
+
+ //Additional damping can help avoiding lowpass jitter motion, help stability for ragdolls etc.
+ //Such damping is undesirable, so once the overall simulation quality of the rigid body dynamics system has improved, this should become obsolete
+ bool m_additionalDamping;
+ btScalar m_additionalDampingFactor;
+ btScalar m_additionalLinearDampingThresholdSqr;
+ btScalar m_additionalAngularDampingThresholdSqr;
+ btScalar m_additionalAngularDampingFactor;
+
+ btRigidBodyConstructionInfo( btScalar mass, btMotionState* motionState, btCollisionShape* collisionShape, const btVector3& localInertia=btVector3(0,0,0)):
+ m_mass(mass),
+ m_motionState(motionState),
+ m_collisionShape(collisionShape),
+ m_localInertia(localInertia),
+ m_linearDamping(btScalar(0.)),
+ m_angularDamping(btScalar(0.)),
+ m_friction(btScalar(0.5)),
+ m_rollingFriction(btScalar(0)),
+ m_spinningFriction(btScalar(0)),
+ m_restitution(btScalar(0.)),
+ m_linearSleepingThreshold(btScalar(0.8)),
+ m_angularSleepingThreshold(btScalar(1.f)),
+ m_additionalDamping(false),
+ m_additionalDampingFactor(btScalar(0.005)),
+ m_additionalLinearDampingThresholdSqr(btScalar(0.01)),
+ m_additionalAngularDampingThresholdSqr(btScalar(0.01)),
+ m_additionalAngularDampingFactor(btScalar(0.01))
+ {
+ m_startWorldTransform.setIdentity();
+ }
+ };
+
+ ///btRigidBody constructor using construction info
+ btRigidBody( const btRigidBodyConstructionInfo& constructionInfo);
+
+ ///btRigidBody constructor for backwards compatibility.
+ ///To specify friction (etc) during rigid body construction, please use the other constructor (using btRigidBodyConstructionInfo)
+ btRigidBody( btScalar mass, btMotionState* motionState, btCollisionShape* collisionShape, const btVector3& localInertia=btVector3(0,0,0));
+
+
+ virtual ~btRigidBody()
+ {
+ //No constraints should point to this rigidbody
+ //Remove constraints from the dynamics world before you delete the related rigidbodies.
+ btAssert(m_constraintRefs.size()==0);
+ }
+
+protected:
+
+ ///setupRigidBody is only used internally by the constructor
+ void setupRigidBody(const btRigidBodyConstructionInfo& constructionInfo);
+
+public:
+
+ void proceedToTransform(const btTransform& newTrans);
+
+ ///to keep collision detection and dynamics separate we don't store a rigidbody pointer
+ ///but a rigidbody is derived from btCollisionObject, so we can safely perform an upcast
+ static const btRigidBody* upcast(const btCollisionObject* colObj)
+ {
+ if (colObj->getInternalType()&btCollisionObject::CO_RIGID_BODY)
+ return (const btRigidBody*)colObj;
+ return 0;
+ }
+ static btRigidBody* upcast(btCollisionObject* colObj)
+ {
+ if (colObj->getInternalType()&btCollisionObject::CO_RIGID_BODY)
+ return (btRigidBody*)colObj;
+ return 0;
+ }
+
+ /// continuous collision detection needs prediction
+ void predictIntegratedTransform(btScalar step, btTransform& predictedTransform) ;
+
+ void saveKinematicState(btScalar step);
+
+ void applyGravity();
+
+ void setGravity(const btVector3& acceleration);
+
+ const btVector3& getGravity() const
+ {
+ return m_gravity_acceleration;
+ }
+
+ void setDamping(btScalar lin_damping, btScalar ang_damping);
+
+ btScalar getLinearDamping() const
+ {
+ return m_linearDamping;
+ }
+
+ btScalar getAngularDamping() const
+ {
+ return m_angularDamping;
+ }
+
+ btScalar getLinearSleepingThreshold() const
+ {
+ return m_linearSleepingThreshold;
+ }
+
+ btScalar getAngularSleepingThreshold() const
+ {
+ return m_angularSleepingThreshold;
+ }
+
+ void applyDamping(btScalar timeStep);
+
+ SIMD_FORCE_INLINE const btCollisionShape* getCollisionShape() const {
+ return m_collisionShape;
+ }
+
+ SIMD_FORCE_INLINE btCollisionShape* getCollisionShape() {
+ return m_collisionShape;
+ }
+
+ void setMassProps(btScalar mass, const btVector3& inertia);
+
+ const btVector3& getLinearFactor() const
+ {
+ return m_linearFactor;
+ }
+ void setLinearFactor(const btVector3& linearFactor)
+ {
+ m_linearFactor = linearFactor;
+ m_invMass = m_linearFactor*m_inverseMass;
+ }
+ btScalar getInvMass() const { return m_inverseMass; }
+ const btMatrix3x3& getInvInertiaTensorWorld() const {
+ return m_invInertiaTensorWorld;
+ }
+
+ void integrateVelocities(btScalar step);
+
+ void setCenterOfMassTransform(const btTransform& xform);
+
+ void applyCentralForce(const btVector3& force)
+ {
+ m_totalForce += force*m_linearFactor;
+ }
+
+ const btVector3& getTotalForce() const
+ {
+ return m_totalForce;
+ };
+
+ const btVector3& getTotalTorque() const
+ {
+ return m_totalTorque;
+ };
+
+ const btVector3& getInvInertiaDiagLocal() const
+ {
+ return m_invInertiaLocal;
+ };
+
+ void setInvInertiaDiagLocal(const btVector3& diagInvInertia)
+ {
+ m_invInertiaLocal = diagInvInertia;
+ }
+
+ void setSleepingThresholds(btScalar linear,btScalar angular)
+ {
+ m_linearSleepingThreshold = linear;
+ m_angularSleepingThreshold = angular;
+ }
+
+ void applyTorque(const btVector3& torque)
+ {
+ m_totalTorque += torque*m_angularFactor;
+ }
+
+ void applyForce(const btVector3& force, const btVector3& rel_pos)
+ {
+ applyCentralForce(force);
+ applyTorque(rel_pos.cross(force*m_linearFactor));
+ }
+
+ void applyCentralImpulse(const btVector3& impulse)
+ {
+ m_linearVelocity += impulse *m_linearFactor * m_inverseMass;
+ }
+
+ void applyTorqueImpulse(const btVector3& torque)
+ {
+ m_angularVelocity += m_invInertiaTensorWorld * torque * m_angularFactor;
+ }
+
+ void applyImpulse(const btVector3& impulse, const btVector3& rel_pos)
+ {
+ if (m_inverseMass != btScalar(0.))
+ {
+ applyCentralImpulse(impulse);
+ if (m_angularFactor)
+ {
+ applyTorqueImpulse(rel_pos.cross(impulse*m_linearFactor));
+ }
+ }
+ }
+
+ void clearForces()
+ {
+ m_totalForce.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
+ m_totalTorque.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
+ }
+
+ void updateInertiaTensor();
+
+ const btVector3& getCenterOfMassPosition() const {
+ return m_worldTransform.getOrigin();
+ }
+ btQuaternion getOrientation() const;
+
+ const btTransform& getCenterOfMassTransform() const {
+ return m_worldTransform;
+ }
+ const btVector3& getLinearVelocity() const {
+ return m_linearVelocity;
+ }
+ const btVector3& getAngularVelocity() const {
+ return m_angularVelocity;
+ }
+
+
+ inline void setLinearVelocity(const btVector3& lin_vel)
+ {
+ m_updateRevision++;
+ m_linearVelocity = lin_vel;
+ }
+
+ inline void setAngularVelocity(const btVector3& ang_vel)
+ {
+ m_updateRevision++;
+ m_angularVelocity = ang_vel;
+ }
+
+ btVector3 getVelocityInLocalPoint(const btVector3& rel_pos) const
+ {
+ //we also calculate lin/ang velocity for kinematic objects
+ return m_linearVelocity + m_angularVelocity.cross(rel_pos);
+
+ //for kinematic objects, we could also use use:
+ // return (m_worldTransform(rel_pos) - m_interpolationWorldTransform(rel_pos)) / m_kinematicTimeStep;
+ }
+
+ void translate(const btVector3& v)
+ {
+ m_worldTransform.getOrigin() += v;
+ }
+
+
+ void getAabb(btVector3& aabbMin,btVector3& aabbMax) const;
+
+
+
+
+
+ SIMD_FORCE_INLINE btScalar computeImpulseDenominator(const btVector3& pos, const btVector3& normal) const
+ {
+ btVector3 r0 = pos - getCenterOfMassPosition();
+
+ btVector3 c0 = (r0).cross(normal);
+
+ btVector3 vec = (c0 * getInvInertiaTensorWorld()).cross(r0);
+
+ return m_inverseMass + normal.dot(vec);
+
+ }
+
+ SIMD_FORCE_INLINE btScalar computeAngularImpulseDenominator(const btVector3& axis) const
+ {
+ btVector3 vec = axis * getInvInertiaTensorWorld();
+ return axis.dot(vec);
+ }
+
+ SIMD_FORCE_INLINE void updateDeactivation(btScalar timeStep)
+ {
+ if ( (getActivationState() == ISLAND_SLEEPING) || (getActivationState() == DISABLE_DEACTIVATION))
+ return;
+
+ if ((getLinearVelocity().length2() < m_linearSleepingThreshold*m_linearSleepingThreshold) &&
+ (getAngularVelocity().length2() < m_angularSleepingThreshold*m_angularSleepingThreshold))
+ {
+ m_deactivationTime += timeStep;
+ } else
+ {
+ m_deactivationTime=btScalar(0.);
+ setActivationState(0);
+ }
+
+ }
+
+ SIMD_FORCE_INLINE bool 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;
+ }
+
+
+
+ const btBroadphaseProxy* getBroadphaseProxy() const
+ {
+ return m_broadphaseHandle;
+ }
+ btBroadphaseProxy* getBroadphaseProxy()
+ {
+ return m_broadphaseHandle;
+ }
+ void setNewBroadphaseProxy(btBroadphaseProxy* broadphaseProxy)
+ {
+ m_broadphaseHandle = broadphaseProxy;
+ }
+
+ //btMotionState allows to automatic synchronize the world transform for active objects
+ btMotionState* getMotionState()
+ {
+ return m_optionalMotionState;
+ }
+ const btMotionState* getMotionState() const
+ {
+ return m_optionalMotionState;
+ }
+ void setMotionState(btMotionState* motionState)
+ {
+ m_optionalMotionState = motionState;
+ if (m_optionalMotionState)
+ motionState->getWorldTransform(m_worldTransform);
+ }
+
+ //for experimental overriding of friction/contact solver func
+ int m_contactSolverType;
+ int m_frictionSolverType;
+
+ void setAngularFactor(const btVector3& angFac)
+ {
+ m_updateRevision++;
+ m_angularFactor = angFac;
+ }
+
+ void setAngularFactor(btScalar angFac)
+ {
+ m_updateRevision++;
+ m_angularFactor.setValue(angFac,angFac,angFac);
+ }
+ const btVector3& getAngularFactor() const
+ {
+ return m_angularFactor;
+ }
+
+ //is this rigidbody added to a btCollisionWorld/btDynamicsWorld/btBroadphase?
+ bool isInWorld() const
+ {
+ return (getBroadphaseProxy() != 0);
+ }
+
+ void addConstraintRef(btTypedConstraint* c);
+ void removeConstraintRef(btTypedConstraint* c);
+
+ btTypedConstraint* getConstraintRef(int index)
+ {
+ return m_constraintRefs[index];
+ }
+
+ int getNumConstraintRefs() const
+ {
+ return m_constraintRefs.size();
+ }
+
+ void setFlags(int flags)
+ {
+ m_rigidbodyFlags = flags;
+ }
+
+ int getFlags() const
+ {
+ return m_rigidbodyFlags;
+ }
+
+
+
+
+ ///perform implicit force computation in world space
+ btVector3 computeGyroscopicImpulseImplicit_World(btScalar dt) const;
+
+ ///perform implicit force computation in body space (inertial frame)
+ btVector3 computeGyroscopicImpulseImplicit_Body(btScalar step) const;
+
+ ///explicit version is best avoided, it gains energy
+ btVector3 computeGyroscopicForceExplicit(btScalar maxGyroscopicForce) const;
+ btVector3 getLocalInertia() const;
+
+ ///////////////////////////////////////////////
+
+ 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;
+
+};
+
+//@todo add m_optionalMotionState and m_constraintRefs to btRigidBodyData
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btRigidBodyFloatData
+{
+ btCollisionObjectFloatData m_collisionObjectData;
+ btMatrix3x3FloatData m_invInertiaTensorWorld;
+ btVector3FloatData m_linearVelocity;
+ btVector3FloatData m_angularVelocity;
+ btVector3FloatData m_angularFactor;
+ btVector3FloatData m_linearFactor;
+ btVector3FloatData m_gravity;
+ btVector3FloatData m_gravity_acceleration;
+ btVector3FloatData m_invInertiaLocal;
+ btVector3FloatData m_totalForce;
+ btVector3FloatData m_totalTorque;
+ float m_inverseMass;
+ float m_linearDamping;
+ float m_angularDamping;
+ float m_additionalDampingFactor;
+ float m_additionalLinearDampingThresholdSqr;
+ float m_additionalAngularDampingThresholdSqr;
+ float m_additionalAngularDampingFactor;
+ float m_linearSleepingThreshold;
+ float m_angularSleepingThreshold;
+ int m_additionalDamping;
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btRigidBodyDoubleData
+{
+ btCollisionObjectDoubleData m_collisionObjectData;
+ btMatrix3x3DoubleData m_invInertiaTensorWorld;
+ btVector3DoubleData m_linearVelocity;
+ btVector3DoubleData m_angularVelocity;
+ btVector3DoubleData m_angularFactor;
+ btVector3DoubleData m_linearFactor;
+ btVector3DoubleData m_gravity;
+ btVector3DoubleData m_gravity_acceleration;
+ btVector3DoubleData m_invInertiaLocal;
+ btVector3DoubleData m_totalForce;
+ btVector3DoubleData m_totalTorque;
+ double m_inverseMass;
+ double m_linearDamping;
+ double m_angularDamping;
+ double m_additionalDampingFactor;
+ double m_additionalLinearDampingThresholdSqr;
+ double m_additionalAngularDampingThresholdSqr;
+ double m_additionalAngularDampingFactor;
+ double m_linearSleepingThreshold;
+ double m_angularSleepingThreshold;
+ int m_additionalDamping;
+ char m_padding[4];
+};
+
+
+
+#endif //BT_RIGIDBODY_H
+
diff --git a/thirdparty/bullet/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp b/thirdparty/bullet/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp
new file mode 100644
index 0000000000..6f63b87c80
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp
@@ -0,0 +1,280 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btSimpleDynamicsWorld.h"
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h"
+#include "BulletCollision/CollisionShapes/btCollisionShape.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h"
+#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h"
+
+
+/*
+ Make sure this dummy function never changes so that it
+ can be used by probes that are checking whether the
+ library is actually installed.
+*/
+extern "C"
+{
+ void btBulletDynamicsProbe ();
+ void btBulletDynamicsProbe () {}
+}
+
+
+
+
+btSimpleDynamicsWorld::btSimpleDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration)
+:btDynamicsWorld(dispatcher,pairCache,collisionConfiguration),
+m_constraintSolver(constraintSolver),
+m_ownsConstraintSolver(false),
+m_gravity(0,0,-10)
+{
+
+}
+
+
+btSimpleDynamicsWorld::~btSimpleDynamicsWorld()
+{
+ if (m_ownsConstraintSolver)
+ btAlignedFree( m_constraintSolver);
+}
+
+int btSimpleDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, btScalar fixedTimeStep)
+{
+ (void)fixedTimeStep;
+ (void)maxSubSteps;
+
+
+ ///apply gravity, predict motion
+ predictUnconstraintMotion(timeStep);
+
+ btDispatcherInfo& dispatchInfo = getDispatchInfo();
+ dispatchInfo.m_timeStep = timeStep;
+ dispatchInfo.m_stepCount = 0;
+ dispatchInfo.m_debugDraw = getDebugDrawer();
+
+ ///perform collision detection
+ performDiscreteCollisionDetection();
+
+ ///solve contact constraints
+ int numManifolds = m_dispatcher1->getNumManifolds();
+ if (numManifolds)
+ {
+ btPersistentManifold** manifoldPtr = ((btCollisionDispatcher*)m_dispatcher1)->getInternalManifoldPointer();
+
+ btContactSolverInfo infoGlobal;
+ infoGlobal.m_timeStep = timeStep;
+ m_constraintSolver->prepareSolve(0,numManifolds);
+ m_constraintSolver->solveGroup(&getCollisionObjectArray()[0],getNumCollisionObjects(),manifoldPtr, numManifolds,0,0,infoGlobal,m_debugDrawer, m_dispatcher1);
+ m_constraintSolver->allSolved(infoGlobal,m_debugDrawer);
+ }
+
+ ///integrate transforms
+ integrateTransforms(timeStep);
+
+ updateAabbs();
+
+ synchronizeMotionStates();
+
+ clearForces();
+
+ return 1;
+
+}
+
+void btSimpleDynamicsWorld::clearForces()
+{
+ ///@todo: iterate over awake simulation islands!
+ for ( int i=0;i<m_collisionObjects.size();i++)
+ {
+ btCollisionObject* colObj = m_collisionObjects[i];
+
+ btRigidBody* body = btRigidBody::upcast(colObj);
+ if (body)
+ {
+ body->clearForces();
+ }
+ }
+}
+
+
+void btSimpleDynamicsWorld::setGravity(const btVector3& gravity)
+{
+ m_gravity = gravity;
+ for ( int i=0;i<m_collisionObjects.size();i++)
+ {
+ btCollisionObject* colObj = m_collisionObjects[i];
+ btRigidBody* body = btRigidBody::upcast(colObj);
+ if (body)
+ {
+ body->setGravity(gravity);
+ }
+ }
+}
+
+btVector3 btSimpleDynamicsWorld::getGravity () const
+{
+ return m_gravity;
+}
+
+void btSimpleDynamicsWorld::removeRigidBody(btRigidBody* body)
+{
+ btCollisionWorld::removeCollisionObject(body);
+}
+
+void btSimpleDynamicsWorld::removeCollisionObject(btCollisionObject* collisionObject)
+{
+ btRigidBody* body = btRigidBody::upcast(collisionObject);
+ if (body)
+ removeRigidBody(body);
+ else
+ btCollisionWorld::removeCollisionObject(collisionObject);
+}
+
+
+void btSimpleDynamicsWorld::addRigidBody(btRigidBody* body)
+{
+ body->setGravity(m_gravity);
+
+ if (body->getCollisionShape())
+ {
+ addCollisionObject(body);
+ }
+}
+
+void btSimpleDynamicsWorld::addRigidBody(btRigidBody* body, int group, int mask)
+{
+ body->setGravity(m_gravity);
+
+ if (body->getCollisionShape())
+ {
+ addCollisionObject(body,group,mask);
+ }
+}
+
+
+void btSimpleDynamicsWorld::debugDrawWorld()
+{
+
+}
+
+void btSimpleDynamicsWorld::addAction(btActionInterface* action)
+{
+
+}
+
+void btSimpleDynamicsWorld::removeAction(btActionInterface* action)
+{
+
+}
+
+
+void btSimpleDynamicsWorld::updateAabbs()
+{
+ btTransform predictedTrans;
+ for ( int i=0;i<m_collisionObjects.size();i++)
+ {
+ btCollisionObject* colObj = m_collisionObjects[i];
+ btRigidBody* body = btRigidBody::upcast(colObj);
+ if (body)
+ {
+ if (body->isActive() && (!body->isStaticObject()))
+ {
+ btVector3 minAabb,maxAabb;
+ colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb,maxAabb);
+ btBroadphaseInterface* bp = getBroadphase();
+ bp->setAabb(body->getBroadphaseHandle(),minAabb,maxAabb, m_dispatcher1);
+ }
+ }
+ }
+}
+
+void btSimpleDynamicsWorld::integrateTransforms(btScalar timeStep)
+{
+ btTransform predictedTrans;
+ for ( int i=0;i<m_collisionObjects.size();i++)
+ {
+ btCollisionObject* colObj = m_collisionObjects[i];
+ btRigidBody* body = btRigidBody::upcast(colObj);
+ if (body)
+ {
+ if (body->isActive() && (!body->isStaticObject()))
+ {
+ body->predictIntegratedTransform(timeStep, predictedTrans);
+ body->proceedToTransform( predictedTrans);
+ }
+ }
+ }
+}
+
+
+
+void btSimpleDynamicsWorld::predictUnconstraintMotion(btScalar timeStep)
+{
+ for ( int i=0;i<m_collisionObjects.size();i++)
+ {
+ btCollisionObject* colObj = m_collisionObjects[i];
+ btRigidBody* body = btRigidBody::upcast(colObj);
+ if (body)
+ {
+ if (!body->isStaticObject())
+ {
+ if (body->isActive())
+ {
+ body->applyGravity();
+ body->integrateVelocities( timeStep);
+ body->applyDamping(timeStep);
+ body->predictIntegratedTransform(timeStep,body->getInterpolationWorldTransform());
+ }
+ }
+ }
+ }
+}
+
+
+void btSimpleDynamicsWorld::synchronizeMotionStates()
+{
+ ///@todo: iterate over awake simulation islands!
+ for ( int i=0;i<m_collisionObjects.size();i++)
+ {
+ btCollisionObject* colObj = m_collisionObjects[i];
+ btRigidBody* body = btRigidBody::upcast(colObj);
+ if (body && body->getMotionState())
+ {
+ if (body->getActivationState() != ISLAND_SLEEPING)
+ {
+ body->getMotionState()->setWorldTransform(body->getWorldTransform());
+ }
+ }
+ }
+
+}
+
+
+void btSimpleDynamicsWorld::setConstraintSolver(btConstraintSolver* solver)
+{
+ if (m_ownsConstraintSolver)
+ {
+ btAlignedFree(m_constraintSolver);
+ }
+ m_ownsConstraintSolver = false;
+ m_constraintSolver = solver;
+}
+
+btConstraintSolver* btSimpleDynamicsWorld::getConstraintSolver()
+{
+ return m_constraintSolver;
+}
diff --git a/thirdparty/bullet/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h b/thirdparty/bullet/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h
new file mode 100644
index 0000000000..44b7e7fb34
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h
@@ -0,0 +1,89 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_SIMPLE_DYNAMICS_WORLD_H
+#define BT_SIMPLE_DYNAMICS_WORLD_H
+
+#include "btDynamicsWorld.h"
+
+class btDispatcher;
+class btOverlappingPairCache;
+class btConstraintSolver;
+
+///The btSimpleDynamicsWorld serves as unit-test and to verify more complicated and optimized dynamics worlds.
+///Please use btDiscreteDynamicsWorld instead
+class btSimpleDynamicsWorld : public btDynamicsWorld
+{
+protected:
+
+ btConstraintSolver* m_constraintSolver;
+
+ bool m_ownsConstraintSolver;
+
+ void predictUnconstraintMotion(btScalar timeStep);
+
+ void integrateTransforms(btScalar timeStep);
+
+ btVector3 m_gravity;
+
+public:
+
+
+
+ ///this btSimpleDynamicsWorld constructor creates dispatcher, broadphase pairCache and constraintSolver
+ btSimpleDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration);
+
+ virtual ~btSimpleDynamicsWorld();
+
+ ///maxSubSteps/fixedTimeStep for interpolation is currently ignored for btSimpleDynamicsWorld, use btDiscreteDynamicsWorld instead
+ virtual int stepSimulation( btScalar timeStep,int maxSubSteps=1, btScalar fixedTimeStep=btScalar(1.)/btScalar(60.));
+
+ virtual void setGravity(const btVector3& gravity);
+
+ virtual btVector3 getGravity () const;
+
+ virtual void addRigidBody(btRigidBody* body);
+
+ virtual void addRigidBody(btRigidBody* body, int group, int mask);
+
+ virtual void removeRigidBody(btRigidBody* body);
+
+ virtual void debugDrawWorld();
+
+ virtual void addAction(btActionInterface* action);
+
+ virtual void removeAction(btActionInterface* action);
+
+ ///removeCollisionObject will first check if it is a rigid body, if so call removeRigidBody otherwise call btCollisionWorld::removeCollisionObject
+ virtual void removeCollisionObject(btCollisionObject* collisionObject);
+
+ virtual void updateAabbs();
+
+ virtual void synchronizeMotionStates();
+
+ virtual void setConstraintSolver(btConstraintSolver* solver);
+
+ virtual btConstraintSolver* getConstraintSolver();
+
+ virtual btDynamicsWorldType getWorldType() const
+ {
+ return BT_SIMPLE_DYNAMICS_WORLD;
+ }
+
+ virtual void clearForces();
+
+};
+
+#endif //BT_SIMPLE_DYNAMICS_WORLD_H
diff --git a/thirdparty/bullet/src/BulletDynamics/Dynamics/btSimulationIslandManagerMt.cpp b/thirdparty/bullet/src/BulletDynamics/Dynamics/btSimulationIslandManagerMt.cpp
new file mode 100644
index 0000000000..99b34353c7
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/Dynamics/btSimulationIslandManagerMt.cpp
@@ -0,0 +1,678 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "LinearMath/btScalar.h"
+#include "LinearMath/btThreads.h"
+#include "btSimulationIslandManagerMt.h"
+#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
+#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/CollisionDispatch/btCollisionWorld.h"
+#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
+
+//#include <stdio.h>
+#include "LinearMath/btQuickprof.h"
+
+
+SIMD_FORCE_INLINE int calcBatchCost( int bodies, int manifolds, int constraints )
+{
+ // rough estimate of the cost of a batch, used for merging
+ int batchCost = bodies + 8 * manifolds + 4 * constraints;
+ return batchCost;
+}
+
+
+SIMD_FORCE_INLINE int calcBatchCost( const btSimulationIslandManagerMt::Island* island )
+{
+ return calcBatchCost( island->bodyArray.size(), island->manifoldArray.size(), island->constraintArray.size() );
+}
+
+
+btSimulationIslandManagerMt::btSimulationIslandManagerMt()
+{
+ m_minimumSolverBatchSize = calcBatchCost(0, 128, 0);
+ m_batchIslandMinBodyCount = 32;
+ m_islandDispatch = parallelIslandDispatch;
+ m_batchIsland = NULL;
+}
+
+
+btSimulationIslandManagerMt::~btSimulationIslandManagerMt()
+{
+ for ( int i = 0; i < m_allocatedIslands.size(); ++i )
+ {
+ delete m_allocatedIslands[ i ];
+ }
+ m_allocatedIslands.resize( 0 );
+ m_activeIslands.resize( 0 );
+ m_freeIslands.resize( 0 );
+}
+
+
+inline int getIslandId(const btPersistentManifold* lhs)
+{
+ const btCollisionObject* rcolObj0 = static_cast<const btCollisionObject*>(lhs->getBody0());
+ const btCollisionObject* rcolObj1 = static_cast<const btCollisionObject*>(lhs->getBody1());
+ int islandId = rcolObj0->getIslandTag() >= 0 ? rcolObj0->getIslandTag() : rcolObj1->getIslandTag();
+ return islandId;
+}
+
+
+SIMD_FORCE_INLINE int btGetConstraintIslandId( const btTypedConstraint* lhs )
+{
+ const btCollisionObject& rcolObj0 = lhs->getRigidBodyA();
+ const btCollisionObject& rcolObj1 = lhs->getRigidBodyB();
+ int islandId = rcolObj0.getIslandTag() >= 0 ? rcolObj0.getIslandTag() : rcolObj1.getIslandTag();
+ return islandId;
+}
+
+/// function object that routes calls to operator<
+class IslandBatchSizeSortPredicate
+{
+public:
+ bool operator() ( const btSimulationIslandManagerMt::Island* lhs, const btSimulationIslandManagerMt::Island* rhs ) const
+ {
+ int lCost = calcBatchCost( lhs );
+ int rCost = calcBatchCost( rhs );
+ return lCost > rCost;
+ }
+};
+
+
+class IslandBodyCapacitySortPredicate
+{
+public:
+ bool operator() ( const btSimulationIslandManagerMt::Island* lhs, const btSimulationIslandManagerMt::Island* rhs ) const
+ {
+ return lhs->bodyArray.capacity() > rhs->bodyArray.capacity();
+ }
+};
+
+
+void btSimulationIslandManagerMt::Island::append( const Island& other )
+{
+ // append bodies
+ for ( int i = 0; i < other.bodyArray.size(); ++i )
+ {
+ bodyArray.push_back( other.bodyArray[ i ] );
+ }
+ // append manifolds
+ for ( int i = 0; i < other.manifoldArray.size(); ++i )
+ {
+ manifoldArray.push_back( other.manifoldArray[ i ] );
+ }
+ // append constraints
+ for ( int i = 0; i < other.constraintArray.size(); ++i )
+ {
+ constraintArray.push_back( other.constraintArray[ i ] );
+ }
+}
+
+
+bool btIsBodyInIsland( const btSimulationIslandManagerMt::Island& island, const btCollisionObject* obj )
+{
+ for ( int i = 0; i < island.bodyArray.size(); ++i )
+ {
+ if ( island.bodyArray[ i ] == obj )
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+
+void btSimulationIslandManagerMt::initIslandPools()
+{
+ // reset island pools
+ int numElem = getUnionFind().getNumElements();
+ m_lookupIslandFromId.resize( numElem );
+ for ( int i = 0; i < m_lookupIslandFromId.size(); ++i )
+ {
+ m_lookupIslandFromId[ i ] = NULL;
+ }
+ m_activeIslands.resize( 0 );
+ m_freeIslands.resize( 0 );
+ // check whether allocated islands are sorted by body capacity (largest to smallest)
+ int lastCapacity = 0;
+ bool isSorted = true;
+ for ( int i = 0; i < m_allocatedIslands.size(); ++i )
+ {
+ Island* island = m_allocatedIslands[ i ];
+ int cap = island->bodyArray.capacity();
+ if ( cap > lastCapacity )
+ {
+ isSorted = false;
+ break;
+ }
+ lastCapacity = cap;
+ }
+ if ( !isSorted )
+ {
+ m_allocatedIslands.quickSort( IslandBodyCapacitySortPredicate() );
+ }
+
+ m_batchIsland = NULL;
+ // mark all islands free (but avoid deallocation)
+ for ( int i = 0; i < m_allocatedIslands.size(); ++i )
+ {
+ Island* island = m_allocatedIslands[ i ];
+ island->bodyArray.resize( 0 );
+ island->manifoldArray.resize( 0 );
+ island->constraintArray.resize( 0 );
+ island->id = -1;
+ island->isSleeping = true;
+ m_freeIslands.push_back( island );
+ }
+}
+
+
+btSimulationIslandManagerMt::Island* btSimulationIslandManagerMt::getIsland( int id )
+{
+ Island* island = m_lookupIslandFromId[ id ];
+ if ( island == NULL )
+ {
+ // search for existing island
+ for ( int i = 0; i < m_activeIslands.size(); ++i )
+ {
+ if ( m_activeIslands[ i ]->id == id )
+ {
+ island = m_activeIslands[ i ];
+ break;
+ }
+ }
+ m_lookupIslandFromId[ id ] = island;
+ }
+ return island;
+}
+
+
+btSimulationIslandManagerMt::Island* btSimulationIslandManagerMt::allocateIsland( int id, int numBodies )
+{
+ Island* island = NULL;
+ int allocSize = numBodies;
+ if ( numBodies < m_batchIslandMinBodyCount )
+ {
+ if ( m_batchIsland )
+ {
+ island = m_batchIsland;
+ m_lookupIslandFromId[ id ] = island;
+ // if we've made a large enough batch,
+ if ( island->bodyArray.size() + numBodies >= m_batchIslandMinBodyCount )
+ {
+ // next time start a new batch
+ m_batchIsland = NULL;
+ }
+ return island;
+ }
+ else
+ {
+ // need to allocate a batch island
+ allocSize = m_batchIslandMinBodyCount * 2;
+ }
+ }
+ btAlignedObjectArray<Island*>& freeIslands = m_freeIslands;
+
+ // search for free island
+ if ( freeIslands.size() > 0 )
+ {
+ // try to reuse a previously allocated island
+ int iFound = freeIslands.size();
+ // linear search for smallest island that can hold our bodies
+ for ( int i = freeIslands.size() - 1; i >= 0; --i )
+ {
+ if ( freeIslands[ i ]->bodyArray.capacity() >= allocSize )
+ {
+ iFound = i;
+ island = freeIslands[ i ];
+ island->id = id;
+ break;
+ }
+ }
+ // if found, shrink array while maintaining ordering
+ if ( island )
+ {
+ int iDest = iFound;
+ int iSrc = iDest + 1;
+ while ( iSrc < freeIslands.size() )
+ {
+ freeIslands[ iDest++ ] = freeIslands[ iSrc++ ];
+ }
+ freeIslands.pop_back();
+ }
+ }
+ if ( island == NULL )
+ {
+ // no free island found, allocate
+ island = new Island(); // TODO: change this to use the pool allocator
+ island->id = id;
+ island->bodyArray.reserve( allocSize );
+ m_allocatedIslands.push_back( island );
+ }
+ m_lookupIslandFromId[ id ] = island;
+ if ( numBodies < m_batchIslandMinBodyCount )
+ {
+ m_batchIsland = island;
+ }
+ m_activeIslands.push_back( island );
+ return island;
+}
+
+
+void btSimulationIslandManagerMt::buildIslands( btDispatcher* dispatcher, btCollisionWorld* collisionWorld )
+{
+
+ BT_PROFILE("islandUnionFindAndQuickSort");
+
+ btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray();
+
+ //we are going to sort the unionfind array, and store the element id in the size
+ //afterwards, we clean unionfind, to make sure no-one uses it anymore
+
+ getUnionFind().sortIslands();
+ int numElem = getUnionFind().getNumElements();
+
+ int endIslandIndex=1;
+ int startIslandIndex;
+
+ //update the sleeping state for bodies, if all are sleeping
+ for ( startIslandIndex=0;startIslandIndex<numElem;startIslandIndex = endIslandIndex)
+ {
+ int islandId = getUnionFind().getElement(startIslandIndex).m_id;
+ for (endIslandIndex = startIslandIndex+1;(endIslandIndex<numElem) && (getUnionFind().getElement(endIslandIndex).m_id == islandId);endIslandIndex++)
+ {
+ }
+
+ //int numSleeping = 0;
+
+ bool allSleeping = true;
+
+ int idx;
+ for (idx=startIslandIndex;idx<endIslandIndex;idx++)
+ {
+ int i = getUnionFind().getElement(idx).m_sz;
+
+ btCollisionObject* colObj0 = collisionObjects[i];
+ if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
+ {
+// printf("error in island management\n");
+ }
+
+ btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
+ if (colObj0->getIslandTag() == islandId)
+ {
+ if (colObj0->getActivationState()== ACTIVE_TAG)
+ {
+ allSleeping = false;
+ }
+ if (colObj0->getActivationState()== DISABLE_DEACTIVATION)
+ {
+ allSleeping = false;
+ }
+ }
+ }
+
+ if (allSleeping)
+ {
+ int idx;
+ for (idx=startIslandIndex;idx<endIslandIndex;idx++)
+ {
+ int i = getUnionFind().getElement(idx).m_sz;
+ btCollisionObject* colObj0 = collisionObjects[i];
+ if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
+ {
+// printf("error in island management\n");
+ }
+
+ btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
+
+ if (colObj0->getIslandTag() == islandId)
+ {
+ colObj0->setActivationState( ISLAND_SLEEPING );
+ }
+ }
+ } else
+ {
+
+ int idx;
+ for (idx=startIslandIndex;idx<endIslandIndex;idx++)
+ {
+ int i = getUnionFind().getElement(idx).m_sz;
+
+ btCollisionObject* colObj0 = collisionObjects[i];
+ if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
+ {
+// printf("error in island management\n");
+ }
+
+ btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
+
+ if (colObj0->getIslandTag() == islandId)
+ {
+ if ( colObj0->getActivationState() == ISLAND_SLEEPING)
+ {
+ colObj0->setActivationState( WANTS_DEACTIVATION);
+ colObj0->setDeactivationTime(0.f);
+ }
+ }
+ }
+ }
+ }
+}
+
+
+void btSimulationIslandManagerMt::addBodiesToIslands( btCollisionWorld* collisionWorld )
+{
+ btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray();
+ int endIslandIndex = 1;
+ int startIslandIndex;
+ int numElem = getUnionFind().getNumElements();
+
+ // create explicit islands and add bodies to each
+ for ( startIslandIndex = 0; startIslandIndex < numElem; startIslandIndex = endIslandIndex )
+ {
+ int islandId = getUnionFind().getElement( startIslandIndex ).m_id;
+
+ // find end index
+ for ( endIslandIndex = startIslandIndex; ( endIslandIndex < numElem ) && ( getUnionFind().getElement( endIslandIndex ).m_id == islandId ); endIslandIndex++ )
+ {
+ }
+ // check if island is sleeping
+ bool islandSleeping = true;
+ for ( int iElem = startIslandIndex; iElem < endIslandIndex; iElem++ )
+ {
+ int i = getUnionFind().getElement( iElem ).m_sz;
+ btCollisionObject* colObj = collisionObjects[ i ];
+ if ( colObj->isActive() )
+ {
+ islandSleeping = false;
+ }
+ }
+ if ( !islandSleeping )
+ {
+ // want to count the number of bodies before allocating the island to optimize memory usage of the Island structures
+ int numBodies = endIslandIndex - startIslandIndex;
+ Island* island = allocateIsland( islandId, numBodies );
+ island->isSleeping = false;
+
+ // add bodies to island
+ for ( int iElem = startIslandIndex; iElem < endIslandIndex; iElem++ )
+ {
+ int i = getUnionFind().getElement( iElem ).m_sz;
+ btCollisionObject* colObj = collisionObjects[ i ];
+ island->bodyArray.push_back( colObj );
+ }
+ }
+ }
+
+}
+
+
+void btSimulationIslandManagerMt::addManifoldsToIslands( btDispatcher* dispatcher )
+{
+ // walk all the manifolds, activating bodies touched by kinematic objects, and add each manifold to its Island
+ int maxNumManifolds = dispatcher->getNumManifolds();
+ for ( int i = 0; i < maxNumManifolds; i++ )
+ {
+ btPersistentManifold* manifold = dispatcher->getManifoldByIndexInternal( i );
+
+ const btCollisionObject* colObj0 = static_cast<const btCollisionObject*>( manifold->getBody0() );
+ const btCollisionObject* colObj1 = static_cast<const btCollisionObject*>( manifold->getBody1() );
+
+ ///@todo: check sleeping conditions!
+ if ( ( ( colObj0 ) && colObj0->getActivationState() != ISLAND_SLEEPING ) ||
+ ( ( colObj1 ) && colObj1->getActivationState() != ISLAND_SLEEPING ) )
+ {
+
+ //kinematic objects don't merge islands, but wake up all connected objects
+ if ( colObj0->isKinematicObject() && colObj0->getActivationState() != ISLAND_SLEEPING )
+ {
+ if ( colObj0->hasContactResponse() )
+ colObj1->activate();
+ }
+ if ( colObj1->isKinematicObject() && colObj1->getActivationState() != ISLAND_SLEEPING )
+ {
+ if ( colObj1->hasContactResponse() )
+ colObj0->activate();
+ }
+ //filtering for response
+ if ( dispatcher->needsResponse( colObj0, colObj1 ) )
+ {
+ // scatter manifolds into various islands
+ int islandId = getIslandId( manifold );
+ // if island not sleeping,
+ if ( Island* island = getIsland( islandId ) )
+ {
+ island->manifoldArray.push_back( manifold );
+ }
+ }
+ }
+ }
+}
+
+
+void btSimulationIslandManagerMt::addConstraintsToIslands( btAlignedObjectArray<btTypedConstraint*>& constraints )
+{
+ // walk constraints
+ for ( int i = 0; i < constraints.size(); i++ )
+ {
+ // scatter constraints into various islands
+ btTypedConstraint* constraint = constraints[ i ];
+ if ( constraint->isEnabled() )
+ {
+ int islandId = btGetConstraintIslandId( constraint );
+ // if island is not sleeping,
+ if ( Island* island = getIsland( islandId ) )
+ {
+ island->constraintArray.push_back( constraint );
+ }
+ }
+ }
+}
+
+
+void btSimulationIslandManagerMt::mergeIslands()
+{
+ // sort islands in order of decreasing batch size
+ m_activeIslands.quickSort( IslandBatchSizeSortPredicate() );
+
+ // merge small islands to satisfy minimum batch size
+ // find first small batch island
+ int destIslandIndex = m_activeIslands.size();
+ for ( int i = 0; i < m_activeIslands.size(); ++i )
+ {
+ Island* island = m_activeIslands[ i ];
+ int batchSize = calcBatchCost( island );
+ if ( batchSize < m_minimumSolverBatchSize )
+ {
+ destIslandIndex = i;
+ break;
+ }
+ }
+ int lastIndex = m_activeIslands.size() - 1;
+ while ( destIslandIndex < lastIndex )
+ {
+ // merge islands from the back of the list
+ Island* island = m_activeIslands[ destIslandIndex ];
+ int numBodies = island->bodyArray.size();
+ int numManifolds = island->manifoldArray.size();
+ int numConstraints = island->constraintArray.size();
+ int firstIndex = lastIndex;
+ // figure out how many islands we want to merge and find out how many bodies, manifolds and constraints we will have
+ while ( true )
+ {
+ Island* src = m_activeIslands[ firstIndex ];
+ numBodies += src->bodyArray.size();
+ numManifolds += src->manifoldArray.size();
+ numConstraints += src->constraintArray.size();
+ int batchCost = calcBatchCost( numBodies, numManifolds, numConstraints );
+ if ( batchCost >= m_minimumSolverBatchSize )
+ {
+ break;
+ }
+ if ( firstIndex - 1 == destIslandIndex )
+ {
+ break;
+ }
+ firstIndex--;
+ }
+ // reserve space for these pointers to minimize reallocation
+ island->bodyArray.reserve( numBodies );
+ island->manifoldArray.reserve( numManifolds );
+ island->constraintArray.reserve( numConstraints );
+ // merge islands
+ for ( int i = firstIndex; i <= lastIndex; ++i )
+ {
+ island->append( *m_activeIslands[ i ] );
+ }
+ // shrink array to exclude the islands that were merged from
+ m_activeIslands.resize( firstIndex );
+ lastIndex = firstIndex - 1;
+ destIslandIndex++;
+ }
+}
+
+
+void btSimulationIslandManagerMt::serialIslandDispatch( btAlignedObjectArray<Island*>* islandsPtr, IslandCallback* callback )
+{
+ BT_PROFILE( "serialIslandDispatch" );
+ // serial dispatch
+ btAlignedObjectArray<Island*>& islands = *islandsPtr;
+ for ( int i = 0; i < islands.size(); ++i )
+ {
+ Island* island = islands[ i ];
+ btPersistentManifold** manifolds = island->manifoldArray.size() ? &island->manifoldArray[ 0 ] : NULL;
+ btTypedConstraint** constraintsPtr = island->constraintArray.size() ? &island->constraintArray[ 0 ] : NULL;
+ callback->processIsland( &island->bodyArray[ 0 ],
+ island->bodyArray.size(),
+ manifolds,
+ island->manifoldArray.size(),
+ constraintsPtr,
+ island->constraintArray.size(),
+ island->id
+ );
+ }
+}
+
+struct UpdateIslandDispatcher : public btIParallelForBody
+{
+ btAlignedObjectArray<btSimulationIslandManagerMt::Island*>* islandsPtr;
+ btSimulationIslandManagerMt::IslandCallback* callback;
+
+ void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE
+ {
+ for ( int i = iBegin; i < iEnd; ++i )
+ {
+ btSimulationIslandManagerMt::Island* island = ( *islandsPtr )[ i ];
+ btPersistentManifold** manifolds = island->manifoldArray.size() ? &island->manifoldArray[ 0 ] : NULL;
+ btTypedConstraint** constraintsPtr = island->constraintArray.size() ? &island->constraintArray[ 0 ] : NULL;
+ callback->processIsland( &island->bodyArray[ 0 ],
+ island->bodyArray.size(),
+ manifolds,
+ island->manifoldArray.size(),
+ constraintsPtr,
+ island->constraintArray.size(),
+ island->id
+ );
+ }
+ }
+};
+
+void btSimulationIslandManagerMt::parallelIslandDispatch( btAlignedObjectArray<Island*>* islandsPtr, IslandCallback* callback )
+{
+ BT_PROFILE( "parallelIslandDispatch" );
+ int grainSize = 1; // iterations per task
+ UpdateIslandDispatcher dispatcher;
+ dispatcher.islandsPtr = islandsPtr;
+ dispatcher.callback = callback;
+ btParallelFor( 0, islandsPtr->size(), grainSize, dispatcher );
+}
+
+
+///@todo: this is random access, it can be walked 'cache friendly'!
+void btSimulationIslandManagerMt::buildAndProcessIslands( btDispatcher* dispatcher,
+ btCollisionWorld* collisionWorld,
+ btAlignedObjectArray<btTypedConstraint*>& constraints,
+ IslandCallback* callback
+ )
+{
+ btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray();
+
+ buildIslands(dispatcher,collisionWorld);
+
+ BT_PROFILE("processIslands");
+
+ if(!getSplitIslands())
+ {
+ btPersistentManifold** manifolds = dispatcher->getInternalManifoldPointer();
+ int maxNumManifolds = dispatcher->getNumManifolds();
+
+ for ( int i = 0; i < maxNumManifolds; i++ )
+ {
+ btPersistentManifold* manifold = manifolds[ i ];
+
+ const btCollisionObject* colObj0 = static_cast<const btCollisionObject*>( manifold->getBody0() );
+ const btCollisionObject* colObj1 = static_cast<const btCollisionObject*>( manifold->getBody1() );
+
+ ///@todo: check sleeping conditions!
+ if ( ( ( colObj0 ) && colObj0->getActivationState() != ISLAND_SLEEPING ) ||
+ ( ( colObj1 ) && colObj1->getActivationState() != ISLAND_SLEEPING ) )
+ {
+
+ //kinematic objects don't merge islands, but wake up all connected objects
+ if ( colObj0->isKinematicObject() && colObj0->getActivationState() != ISLAND_SLEEPING )
+ {
+ if ( colObj0->hasContactResponse() )
+ colObj1->activate();
+ }
+ if ( colObj1->isKinematicObject() && colObj1->getActivationState() != ISLAND_SLEEPING )
+ {
+ if ( colObj1->hasContactResponse() )
+ colObj0->activate();
+ }
+ }
+ }
+ btTypedConstraint** constraintsPtr = constraints.size() ? &constraints[ 0 ] : NULL;
+ callback->processIsland(&collisionObjects[0],
+ collisionObjects.size(),
+ manifolds,
+ maxNumManifolds,
+ constraintsPtr,
+ constraints.size(),
+ -1
+ );
+ }
+ else
+ {
+ initIslandPools();
+
+ //traverse the simulation islands, and call the solver, unless all objects are sleeping/deactivated
+ addBodiesToIslands( collisionWorld );
+ addManifoldsToIslands( dispatcher );
+ addConstraintsToIslands( constraints );
+
+ // m_activeIslands array should now contain all non-sleeping Islands, and each Island should
+ // have all the necessary bodies, manifolds and constraints.
+
+ // if we want to merge islands with small batch counts,
+ if ( m_minimumSolverBatchSize > 1 )
+ {
+ mergeIslands();
+ }
+ // dispatch islands to solver
+ m_islandDispatch( &m_activeIslands, callback );
+ }
+}
diff --git a/thirdparty/bullet/src/BulletDynamics/Dynamics/btSimulationIslandManagerMt.h b/thirdparty/bullet/src/BulletDynamics/Dynamics/btSimulationIslandManagerMt.h
new file mode 100644
index 0000000000..9a781aaef1
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/Dynamics/btSimulationIslandManagerMt.h
@@ -0,0 +1,110 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_SIMULATION_ISLAND_MANAGER_MT_H
+#define BT_SIMULATION_ISLAND_MANAGER_MT_H
+
+#include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h"
+
+class btTypedConstraint;
+
+
+///
+/// SimulationIslandManagerMt -- Multithread capable version of SimulationIslandManager
+/// Splits the world up into islands which can be solved in parallel.
+/// In order to solve islands in parallel, an IslandDispatch function
+/// must be provided which will dispatch calls to multiple threads.
+/// The amount of parallelism that can be achieved depends on the number
+/// of islands. If only a single island exists, then no parallelism is
+/// possible.
+///
+class btSimulationIslandManagerMt : public btSimulationIslandManager
+{
+public:
+ struct Island
+ {
+ // a simulation island consisting of bodies, manifolds and constraints,
+ // to be passed into a constraint solver.
+ btAlignedObjectArray<btCollisionObject*> bodyArray;
+ btAlignedObjectArray<btPersistentManifold*> manifoldArray;
+ btAlignedObjectArray<btTypedConstraint*> constraintArray;
+ int id; // island id
+ bool isSleeping;
+
+ void append( const Island& other ); // add bodies, manifolds, constraints to my own
+ };
+ struct IslandCallback
+ {
+ virtual ~IslandCallback() {};
+
+ virtual void processIsland( btCollisionObject** bodies,
+ int numBodies,
+ btPersistentManifold** manifolds,
+ int numManifolds,
+ btTypedConstraint** constraints,
+ int numConstraints,
+ int islandId
+ ) = 0;
+ };
+ typedef void( *IslandDispatchFunc ) ( btAlignedObjectArray<Island*>* islands, IslandCallback* callback );
+ static void serialIslandDispatch( btAlignedObjectArray<Island*>* islandsPtr, IslandCallback* callback );
+ static void parallelIslandDispatch( btAlignedObjectArray<Island*>* islandsPtr, IslandCallback* callback );
+protected:
+ btAlignedObjectArray<Island*> m_allocatedIslands; // owner of all Islands
+ btAlignedObjectArray<Island*> m_activeIslands; // islands actively in use
+ btAlignedObjectArray<Island*> m_freeIslands; // islands ready to be reused
+ btAlignedObjectArray<Island*> m_lookupIslandFromId; // big lookup table to map islandId to Island pointer
+ Island* m_batchIsland;
+ int m_minimumSolverBatchSize;
+ int m_batchIslandMinBodyCount;
+ IslandDispatchFunc m_islandDispatch;
+
+ Island* getIsland( int id );
+ virtual Island* allocateIsland( int id, int numBodies );
+ virtual void initIslandPools();
+ virtual void addBodiesToIslands( btCollisionWorld* collisionWorld );
+ virtual void addManifoldsToIslands( btDispatcher* dispatcher );
+ virtual void addConstraintsToIslands( btAlignedObjectArray<btTypedConstraint*>& constraints );
+ virtual void mergeIslands();
+
+public:
+ btSimulationIslandManagerMt();
+ virtual ~btSimulationIslandManagerMt();
+
+ virtual void buildAndProcessIslands( btDispatcher* dispatcher, btCollisionWorld* collisionWorld, btAlignedObjectArray<btTypedConstraint*>& constraints, IslandCallback* callback );
+
+ virtual void buildIslands(btDispatcher* dispatcher,btCollisionWorld* colWorld);
+
+ int getMinimumSolverBatchSize() const
+ {
+ return m_minimumSolverBatchSize;
+ }
+ void setMinimumSolverBatchSize( int sz )
+ {
+ m_minimumSolverBatchSize = sz;
+ }
+ IslandDispatchFunc getIslandDispatchFunction() const
+ {
+ return m_islandDispatch;
+ }
+ // allow users to set their own dispatch function for multithreaded dispatch
+ void setIslandDispatchFunction( IslandDispatchFunc func )
+ {
+ m_islandDispatch = func;
+ }
+};
+
+#endif //BT_SIMULATION_ISLAND_MANAGER_H
+
diff --git a/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBody.cpp b/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBody.cpp
new file mode 100644
index 0000000000..62865e0c78
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBody.cpp
@@ -0,0 +1,2043 @@
+/*
+ * PURPOSE:
+ * Class representing an articulated rigid body. Stores the body's
+ * current state, allows forces and torques to be set, handles
+ * timestepping and implements Featherstone's algorithm.
+ *
+ * COPYRIGHT:
+ * Copyright (C) Stephen Thompson, <stephen@solarflare.org.uk>, 2011-2013
+ * Portions written By Erwin Coumans: connection to LCP solver, various multibody constraints, replacing Eigen math library by Bullet LinearMath and a dedicated 6x6 matrix inverse (solveImatrix)
+ * Portions written By Jakub Stepien: support for multi-DOF constraints, introduction of spatial algebra and several other improvements
+
+ 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 "btMultiBody.h"
+#include "btMultiBodyLink.h"
+#include "btMultiBodyLinkCollider.h"
+#include "btMultiBodyJointFeedback.h"
+#include "LinearMath/btTransformUtil.h"
+#include "LinearMath/btSerializer.h"
+//#include "Bullet3Common/b3Logging.h"
+// #define INCLUDE_GYRO_TERM
+
+///todo: determine if we need these options. If so, make a proper API, otherwise delete those globals
+bool gJointFeedbackInWorldSpace = false;
+bool gJointFeedbackInJointFrame = false;
+
+namespace {
+ const btScalar SLEEP_EPSILON = btScalar(0.05); // this is a squared velocity (m^2 s^-2)
+ const btScalar SLEEP_TIMEOUT = btScalar(2); // in seconds
+}
+
+namespace {
+ void SpatialTransform(const btMatrix3x3 &rotation_matrix, // rotates vectors in 'from' frame to vectors in 'to' frame
+ const btVector3 &displacement, // vector from origin of 'from' frame to origin of 'to' frame, in 'to' coordinates
+ const btVector3 &top_in, // top part of input vector
+ const btVector3 &bottom_in, // bottom part of input vector
+ btVector3 &top_out, // top part of output vector
+ btVector3 &bottom_out) // bottom part of output vector
+ {
+ top_out = rotation_matrix * top_in;
+ bottom_out = -displacement.cross(top_out) + rotation_matrix * bottom_in;
+ }
+
+#if 0
+ void InverseSpatialTransform(const btMatrix3x3 &rotation_matrix,
+ const btVector3 &displacement,
+ const btVector3 &top_in,
+ const btVector3 &bottom_in,
+ btVector3 &top_out,
+ btVector3 &bottom_out)
+ {
+ top_out = rotation_matrix.transpose() * top_in;
+ bottom_out = rotation_matrix.transpose() * (bottom_in + displacement.cross(top_in));
+ }
+
+ btScalar SpatialDotProduct(const btVector3 &a_top,
+ const btVector3 &a_bottom,
+ const btVector3 &b_top,
+ const btVector3 &b_bottom)
+ {
+ return a_bottom.dot(b_top) + a_top.dot(b_bottom);
+ }
+
+ void SpatialCrossProduct(const btVector3 &a_top,
+ const btVector3 &a_bottom,
+ const btVector3 &b_top,
+ const btVector3 &b_bottom,
+ btVector3 &top_out,
+ btVector3 &bottom_out)
+ {
+ top_out = a_top.cross(b_top);
+ bottom_out = a_bottom.cross(b_top) + a_top.cross(b_bottom);
+ }
+#endif
+
+}
+
+
+//
+// Implementation of class btMultiBody
+//
+
+btMultiBody::btMultiBody(int n_links,
+ btScalar mass,
+ const btVector3 &inertia,
+ bool fixedBase,
+ bool canSleep,
+ bool /*deprecatedUseMultiDof*/)
+ :
+ m_baseCollider(0),
+ m_baseName(0),
+ m_basePos(0,0,0),
+ m_baseQuat(0, 0, 0, 1),
+ m_baseMass(mass),
+ m_baseInertia(inertia),
+
+ m_fixedBase(fixedBase),
+ m_awake(true),
+ m_canSleep(canSleep),
+ m_sleepTimer(0),
+ m_userObjectPointer(0),
+ m_userIndex2(-1),
+ m_userIndex(-1),
+ m_linearDamping(0.04f),
+ m_angularDamping(0.04f),
+ m_useGyroTerm(true),
+ m_maxAppliedImpulse(1000.f),
+ m_maxCoordinateVelocity(100.f),
+ m_hasSelfCollision(true),
+ __posUpdated(false),
+ m_dofCount(0),
+ m_posVarCnt(0),
+ m_useRK4(false),
+ m_useGlobalVelocities(false),
+ m_internalNeedsJointFeedback(false)
+{
+ m_cachedInertiaTopLeft.setValue(0,0,0,0,0,0,0,0,0);
+ m_cachedInertiaTopRight.setValue(0,0,0,0,0,0,0,0,0);
+ m_cachedInertiaLowerLeft.setValue(0,0,0,0,0,0,0,0,0);
+ m_cachedInertiaLowerRight.setValue(0,0,0,0,0,0,0,0,0);
+ m_cachedInertiaValid=false;
+
+ m_links.resize(n_links);
+ m_matrixBuf.resize(n_links + 1);
+
+ m_baseForce.setValue(0, 0, 0);
+ m_baseTorque.setValue(0, 0, 0);
+}
+
+btMultiBody::~btMultiBody()
+{
+}
+
+void btMultiBody::setupFixed(int i,
+ btScalar mass,
+ const btVector3 &inertia,
+ int parent,
+ const btQuaternion &rotParentToThis,
+ const btVector3 &parentComToThisPivotOffset,
+ const btVector3 &thisPivotToThisComOffset, bool /*deprecatedDisableParentCollision*/)
+{
+
+ m_links[i].m_mass = mass;
+ m_links[i].m_inertiaLocal = inertia;
+ m_links[i].m_parent = parent;
+ m_links[i].setAxisTop(0, 0., 0., 0.);
+ m_links[i].setAxisBottom(0, btVector3(0,0,0));
+ m_links[i].m_zeroRotParentToThis = rotParentToThis;
+ m_links[i].m_dVector = thisPivotToThisComOffset;
+ m_links[i].m_eVector = parentComToThisPivotOffset;
+
+ m_links[i].m_jointType = btMultibodyLink::eFixed;
+ m_links[i].m_dofCount = 0;
+ m_links[i].m_posVarCount = 0;
+
+ m_links[i].m_flags |=BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION;
+
+ m_links[i].updateCacheMultiDof();
+
+ updateLinksDofOffsets();
+
+}
+
+
+void btMultiBody::setupPrismatic(int i,
+ btScalar mass,
+ const btVector3 &inertia,
+ int parent,
+ const btQuaternion &rotParentToThis,
+ const btVector3 &jointAxis,
+ const btVector3 &parentComToThisPivotOffset,
+ const btVector3 &thisPivotToThisComOffset,
+ bool disableParentCollision)
+{
+ m_dofCount += 1;
+ m_posVarCnt += 1;
+
+ m_links[i].m_mass = mass;
+ m_links[i].m_inertiaLocal = inertia;
+ m_links[i].m_parent = parent;
+ m_links[i].m_zeroRotParentToThis = rotParentToThis;
+ m_links[i].setAxisTop(0, 0., 0., 0.);
+ m_links[i].setAxisBottom(0, jointAxis);
+ m_links[i].m_eVector = parentComToThisPivotOffset;
+ m_links[i].m_dVector = thisPivotToThisComOffset;
+ m_links[i].m_cachedRotParentToThis = rotParentToThis;
+
+ m_links[i].m_jointType = btMultibodyLink::ePrismatic;
+ m_links[i].m_dofCount = 1;
+ m_links[i].m_posVarCount = 1;
+ m_links[i].m_jointPos[0] = 0.f;
+ m_links[i].m_jointTorque[0] = 0.f;
+
+ if (disableParentCollision)
+ m_links[i].m_flags |=BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION;
+ //
+
+ m_links[i].updateCacheMultiDof();
+
+ updateLinksDofOffsets();
+}
+
+void btMultiBody::setupRevolute(int i,
+ btScalar mass,
+ const btVector3 &inertia,
+ int parent,
+ const btQuaternion &rotParentToThis,
+ const btVector3 &jointAxis,
+ const btVector3 &parentComToThisPivotOffset,
+ const btVector3 &thisPivotToThisComOffset,
+ bool disableParentCollision)
+{
+ m_dofCount += 1;
+ m_posVarCnt += 1;
+
+ m_links[i].m_mass = mass;
+ m_links[i].m_inertiaLocal = inertia;
+ m_links[i].m_parent = parent;
+ m_links[i].m_zeroRotParentToThis = rotParentToThis;
+ m_links[i].setAxisTop(0, jointAxis);
+ m_links[i].setAxisBottom(0, jointAxis.cross(thisPivotToThisComOffset));
+ m_links[i].m_dVector = thisPivotToThisComOffset;
+ m_links[i].m_eVector = parentComToThisPivotOffset;
+
+ m_links[i].m_jointType = btMultibodyLink::eRevolute;
+ m_links[i].m_dofCount = 1;
+ m_links[i].m_posVarCount = 1;
+ m_links[i].m_jointPos[0] = 0.f;
+ m_links[i].m_jointTorque[0] = 0.f;
+
+ if (disableParentCollision)
+ m_links[i].m_flags |=BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION;
+ //
+ m_links[i].updateCacheMultiDof();
+ //
+ updateLinksDofOffsets();
+}
+
+
+
+void btMultiBody::setupSpherical(int i,
+ btScalar mass,
+ const btVector3 &inertia,
+ int parent,
+ const btQuaternion &rotParentToThis,
+ const btVector3 &parentComToThisPivotOffset,
+ const btVector3 &thisPivotToThisComOffset,
+ bool disableParentCollision)
+{
+
+ m_dofCount += 3;
+ m_posVarCnt += 4;
+
+ m_links[i].m_mass = mass;
+ m_links[i].m_inertiaLocal = inertia;
+ m_links[i].m_parent = parent;
+ m_links[i].m_zeroRotParentToThis = rotParentToThis;
+ m_links[i].m_dVector = thisPivotToThisComOffset;
+ m_links[i].m_eVector = parentComToThisPivotOffset;
+
+ m_links[i].m_jointType = btMultibodyLink::eSpherical;
+ m_links[i].m_dofCount = 3;
+ m_links[i].m_posVarCount = 4;
+ m_links[i].setAxisTop(0, 1.f, 0.f, 0.f);
+ m_links[i].setAxisTop(1, 0.f, 1.f, 0.f);
+ m_links[i].setAxisTop(2, 0.f, 0.f, 1.f);
+ m_links[i].setAxisBottom(0, m_links[i].getAxisTop(0).cross(thisPivotToThisComOffset));
+ m_links[i].setAxisBottom(1, m_links[i].getAxisTop(1).cross(thisPivotToThisComOffset));
+ m_links[i].setAxisBottom(2, m_links[i].getAxisTop(2).cross(thisPivotToThisComOffset));
+ m_links[i].m_jointPos[0] = m_links[i].m_jointPos[1] = m_links[i].m_jointPos[2] = 0.f; m_links[i].m_jointPos[3] = 1.f;
+ m_links[i].m_jointTorque[0] = m_links[i].m_jointTorque[1] = m_links[i].m_jointTorque[2] = 0.f;
+
+
+ if (disableParentCollision)
+ m_links[i].m_flags |=BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION;
+ //
+ m_links[i].updateCacheMultiDof();
+ //
+ updateLinksDofOffsets();
+}
+
+void btMultiBody::setupPlanar(int i,
+ btScalar mass,
+ const btVector3 &inertia,
+ int parent,
+ const btQuaternion &rotParentToThis,
+ const btVector3 &rotationAxis,
+ const btVector3 &parentComToThisComOffset,
+ bool disableParentCollision)
+{
+
+ m_dofCount += 3;
+ m_posVarCnt += 3;
+
+ m_links[i].m_mass = mass;
+ m_links[i].m_inertiaLocal = inertia;
+ m_links[i].m_parent = parent;
+ m_links[i].m_zeroRotParentToThis = rotParentToThis;
+ m_links[i].m_dVector.setZero();
+ m_links[i].m_eVector = parentComToThisComOffset;
+
+ //
+ btVector3 vecNonParallelToRotAxis(1, 0, 0);
+ if(rotationAxis.normalized().dot(vecNonParallelToRotAxis) > 0.999)
+ vecNonParallelToRotAxis.setValue(0, 1, 0);
+ //
+
+ m_links[i].m_jointType = btMultibodyLink::ePlanar;
+ m_links[i].m_dofCount = 3;
+ m_links[i].m_posVarCount = 3;
+ btVector3 n=rotationAxis.normalized();
+ m_links[i].setAxisTop(0, n[0],n[1],n[2]);
+ m_links[i].setAxisTop(1,0,0,0);
+ m_links[i].setAxisTop(2,0,0,0);
+ m_links[i].setAxisBottom(0,0,0,0);
+ btVector3 cr = m_links[i].getAxisTop(0).cross(vecNonParallelToRotAxis);
+ m_links[i].setAxisBottom(1,cr[0],cr[1],cr[2]);
+ cr = m_links[i].getAxisBottom(1).cross(m_links[i].getAxisTop(0));
+ m_links[i].setAxisBottom(2,cr[0],cr[1],cr[2]);
+ m_links[i].m_jointPos[0] = m_links[i].m_jointPos[1] = m_links[i].m_jointPos[2] = 0.f;
+ m_links[i].m_jointTorque[0] = m_links[i].m_jointTorque[1] = m_links[i].m_jointTorque[2] = 0.f;
+
+ if (disableParentCollision)
+ m_links[i].m_flags |=BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION;
+ //
+ m_links[i].updateCacheMultiDof();
+ //
+ updateLinksDofOffsets();
+}
+
+void btMultiBody::finalizeMultiDof()
+{
+ m_deltaV.resize(0);
+ m_deltaV.resize(6 + m_dofCount);
+ m_realBuf.resize(6 + m_dofCount + m_dofCount*m_dofCount + 6 + m_dofCount); //m_dofCount for joint-space vels + m_dofCount^2 for "D" matrices + delta-pos vector (6 base "vels" + joint "vels")
+ m_vectorBuf.resize(2 * m_dofCount); //two 3-vectors (i.e. one six-vector) for each system dof ("h" matrices)
+ for (int i=0;i<m_vectorBuf.size();i++)
+ {
+ m_vectorBuf[i].setValue(0,0,0);
+ }
+ updateLinksDofOffsets();
+}
+
+int btMultiBody::getParent(int i) const
+{
+ return m_links[i].m_parent;
+}
+
+btScalar btMultiBody::getLinkMass(int i) const
+{
+ return m_links[i].m_mass;
+}
+
+const btVector3 & btMultiBody::getLinkInertia(int i) const
+{
+ return m_links[i].m_inertiaLocal;
+}
+
+btScalar btMultiBody::getJointPos(int i) const
+{
+ return m_links[i].m_jointPos[0];
+}
+
+btScalar btMultiBody::getJointVel(int i) const
+{
+ return m_realBuf[6 + m_links[i].m_dofOffset];
+}
+
+btScalar * btMultiBody::getJointPosMultiDof(int i)
+{
+ return &m_links[i].m_jointPos[0];
+}
+
+btScalar * btMultiBody::getJointVelMultiDof(int i)
+{
+ return &m_realBuf[6 + m_links[i].m_dofOffset];
+}
+
+const btScalar * btMultiBody::getJointPosMultiDof(int i) const
+{
+ return &m_links[i].m_jointPos[0];
+}
+
+const btScalar * btMultiBody::getJointVelMultiDof(int i) const
+{
+ return &m_realBuf[6 + m_links[i].m_dofOffset];
+}
+
+
+void btMultiBody::setJointPos(int i, btScalar q)
+{
+ m_links[i].m_jointPos[0] = q;
+ m_links[i].updateCacheMultiDof();
+}
+
+void btMultiBody::setJointPosMultiDof(int i, btScalar *q)
+{
+ for(int pos = 0; pos < m_links[i].m_posVarCount; ++pos)
+ m_links[i].m_jointPos[pos] = q[pos];
+
+ m_links[i].updateCacheMultiDof();
+}
+
+void btMultiBody::setJointVel(int i, btScalar qdot)
+{
+ m_realBuf[6 + m_links[i].m_dofOffset] = qdot;
+}
+
+void btMultiBody::setJointVelMultiDof(int i, btScalar *qdot)
+{
+ for(int dof = 0; dof < m_links[i].m_dofCount; ++dof)
+ m_realBuf[6 + m_links[i].m_dofOffset + dof] = qdot[dof];
+}
+
+const btVector3 & btMultiBody::getRVector(int i) const
+{
+ return m_links[i].m_cachedRVector;
+}
+
+const btQuaternion & btMultiBody::getParentToLocalRot(int i) const
+{
+ return m_links[i].m_cachedRotParentToThis;
+}
+
+btVector3 btMultiBody::localPosToWorld(int i, const btVector3 &local_pos) const
+{
+ btAssert(i>=-1);
+ btAssert(i<m_links.size());
+ if ((i<-1) || (i>=m_links.size()))
+ {
+ return btVector3(SIMD_INFINITY,SIMD_INFINITY,SIMD_INFINITY);
+ }
+
+ btVector3 result = local_pos;
+ while (i != -1) {
+ // 'result' is in frame i. transform it to frame parent(i)
+ result += getRVector(i);
+ result = quatRotate(getParentToLocalRot(i).inverse(),result);
+ i = getParent(i);
+ }
+
+ // 'result' is now in the base frame. transform it to world frame
+ result = quatRotate(getWorldToBaseRot().inverse() ,result);
+ result += getBasePos();
+
+ return result;
+}
+
+btVector3 btMultiBody::worldPosToLocal(int i, const btVector3 &world_pos) const
+{
+ btAssert(i>=-1);
+ btAssert(i<m_links.size());
+ if ((i<-1) || (i>=m_links.size()))
+ {
+ return btVector3(SIMD_INFINITY,SIMD_INFINITY,SIMD_INFINITY);
+ }
+
+ if (i == -1) {
+ // world to base
+ return quatRotate(getWorldToBaseRot(),(world_pos - getBasePos()));
+ } else {
+ // find position in parent frame, then transform to current frame
+ return quatRotate(getParentToLocalRot(i),worldPosToLocal(getParent(i), world_pos)) - getRVector(i);
+ }
+}
+
+btVector3 btMultiBody::localDirToWorld(int i, const btVector3 &local_dir) const
+{
+ btAssert(i>=-1);
+ btAssert(i<m_links.size());
+ if ((i<-1) || (i>=m_links.size()))
+ {
+ return btVector3(SIMD_INFINITY,SIMD_INFINITY,SIMD_INFINITY);
+ }
+
+
+ btVector3 result = local_dir;
+ while (i != -1) {
+ result = quatRotate(getParentToLocalRot(i).inverse() , result);
+ i = getParent(i);
+ }
+ result = quatRotate(getWorldToBaseRot().inverse() , result);
+ return result;
+}
+
+btVector3 btMultiBody::worldDirToLocal(int i, const btVector3 &world_dir) const
+{
+ btAssert(i>=-1);
+ btAssert(i<m_links.size());
+ if ((i<-1) || (i>=m_links.size()))
+ {
+ return btVector3(SIMD_INFINITY,SIMD_INFINITY,SIMD_INFINITY);
+ }
+
+ if (i == -1) {
+ return quatRotate(getWorldToBaseRot(), world_dir);
+ } else {
+ return quatRotate(getParentToLocalRot(i) ,worldDirToLocal(getParent(i), world_dir));
+ }
+}
+
+btMatrix3x3 btMultiBody::localFrameToWorld(int i, const btMatrix3x3 &local_frame) const
+{
+ btMatrix3x3 result = local_frame;
+ btVector3 frameInWorld0 = localDirToWorld(i, local_frame.getColumn(0));
+ btVector3 frameInWorld1 = localDirToWorld(i, local_frame.getColumn(1));
+ btVector3 frameInWorld2 = localDirToWorld(i, local_frame.getColumn(2));
+ result.setValue(frameInWorld0[0], frameInWorld1[0], frameInWorld2[0], frameInWorld0[1], frameInWorld1[1], frameInWorld2[1], frameInWorld0[2], frameInWorld1[2], frameInWorld2[2]);
+ return result;
+}
+
+void btMultiBody::compTreeLinkVelocities(btVector3 *omega, btVector3 *vel) const
+{
+ int num_links = getNumLinks();
+ // Calculates the velocities of each link (and the base) in its local frame
+ omega[0] = quatRotate(m_baseQuat ,getBaseOmega());
+ vel[0] = quatRotate(m_baseQuat ,getBaseVel());
+
+ for (int i = 0; i < num_links; ++i)
+ {
+ const int parent = m_links[i].m_parent;
+
+ // transform parent vel into this frame, store in omega[i+1], vel[i+1]
+ SpatialTransform(btMatrix3x3(m_links[i].m_cachedRotParentToThis), m_links[i].m_cachedRVector,
+ omega[parent+1], vel[parent+1],
+ omega[i+1], vel[i+1]);
+
+ // now add qidot * shat_i
+ //only supported for revolute/prismatic joints, todo: spherical and planar joints
+ switch(m_links[i].m_jointType)
+ {
+ case btMultibodyLink::ePrismatic:
+ case btMultibodyLink::eRevolute:
+ {
+ btVector3 axisTop = m_links[i].getAxisTop(0);
+ btVector3 axisBottom = m_links[i].getAxisBottom(0);
+ btScalar jointVel = getJointVel(i);
+ omega[i+1] += jointVel * axisTop;
+ vel[i+1] += jointVel * axisBottom;
+ break;
+ }
+ default:
+ {
+ }
+ }
+ }
+}
+
+btScalar btMultiBody::getKineticEnergy() const
+{
+ int num_links = getNumLinks();
+ // TODO: would be better not to allocate memory here
+ btAlignedObjectArray<btVector3> omega;omega.resize(num_links+1);
+ btAlignedObjectArray<btVector3> vel;vel.resize(num_links+1);
+ compTreeLinkVelocities(&omega[0], &vel[0]);
+
+ // we will do the factor of 0.5 at the end
+ btScalar result = m_baseMass * vel[0].dot(vel[0]);
+ result += omega[0].dot(m_baseInertia * omega[0]);
+
+ for (int i = 0; i < num_links; ++i) {
+ result += m_links[i].m_mass * vel[i+1].dot(vel[i+1]);
+ result += omega[i+1].dot(m_links[i].m_inertiaLocal * omega[i+1]);
+ }
+
+ return 0.5f * result;
+}
+
+btVector3 btMultiBody::getAngularMomentum() const
+{
+ int num_links = getNumLinks();
+ // TODO: would be better not to allocate memory here
+ btAlignedObjectArray<btVector3> omega;omega.resize(num_links+1);
+ btAlignedObjectArray<btVector3> vel;vel.resize(num_links+1);
+ btAlignedObjectArray<btQuaternion> rot_from_world;rot_from_world.resize(num_links+1);
+ compTreeLinkVelocities(&omega[0], &vel[0]);
+
+ rot_from_world[0] = m_baseQuat;
+ btVector3 result = quatRotate(rot_from_world[0].inverse() , (m_baseInertia * omega[0]));
+
+ for (int i = 0; i < num_links; ++i) {
+ rot_from_world[i+1] = m_links[i].m_cachedRotParentToThis * rot_from_world[m_links[i].m_parent+1];
+ result += (quatRotate(rot_from_world[i+1].inverse() , (m_links[i].m_inertiaLocal * omega[i+1])));
+ }
+
+ return result;
+}
+
+void btMultiBody::clearConstraintForces()
+{
+ m_baseConstraintForce.setValue(0, 0, 0);
+ m_baseConstraintTorque.setValue(0, 0, 0);
+
+
+ for (int i = 0; i < getNumLinks(); ++i) {
+ m_links[i].m_appliedConstraintForce.setValue(0, 0, 0);
+ m_links[i].m_appliedConstraintTorque.setValue(0, 0, 0);
+ }
+}
+void btMultiBody::clearForcesAndTorques()
+{
+ m_baseForce.setValue(0, 0, 0);
+ m_baseTorque.setValue(0, 0, 0);
+
+
+ for (int i = 0; i < getNumLinks(); ++i) {
+ m_links[i].m_appliedForce.setValue(0, 0, 0);
+ m_links[i].m_appliedTorque.setValue(0, 0, 0);
+ m_links[i].m_jointTorque[0] = m_links[i].m_jointTorque[1] = m_links[i].m_jointTorque[2] = m_links[i].m_jointTorque[3] = m_links[i].m_jointTorque[4] = m_links[i].m_jointTorque[5] = 0.f;
+ }
+}
+
+void btMultiBody::clearVelocities()
+{
+ for (int i = 0; i < 6 + getNumDofs(); ++i)
+ {
+ m_realBuf[i] = 0.f;
+ }
+}
+void btMultiBody::addLinkForce(int i, const btVector3 &f)
+{
+ m_links[i].m_appliedForce += f;
+}
+
+void btMultiBody::addLinkTorque(int i, const btVector3 &t)
+{
+ m_links[i].m_appliedTorque += t;
+}
+
+void btMultiBody::addLinkConstraintForce(int i, const btVector3 &f)
+{
+ m_links[i].m_appliedConstraintForce += f;
+}
+
+void btMultiBody::addLinkConstraintTorque(int i, const btVector3 &t)
+{
+ m_links[i].m_appliedConstraintTorque += t;
+}
+
+
+
+void btMultiBody::addJointTorque(int i, btScalar Q)
+{
+ m_links[i].m_jointTorque[0] += Q;
+}
+
+void btMultiBody::addJointTorqueMultiDof(int i, int dof, btScalar Q)
+{
+ m_links[i].m_jointTorque[dof] += Q;
+}
+
+void btMultiBody::addJointTorqueMultiDof(int i, const btScalar *Q)
+{
+ for(int dof = 0; dof < m_links[i].m_dofCount; ++dof)
+ m_links[i].m_jointTorque[dof] = Q[dof];
+}
+
+const btVector3 & btMultiBody::getLinkForce(int i) const
+{
+ return m_links[i].m_appliedForce;
+}
+
+const btVector3 & btMultiBody::getLinkTorque(int i) const
+{
+ return m_links[i].m_appliedTorque;
+}
+
+btScalar btMultiBody::getJointTorque(int i) const
+{
+ return m_links[i].m_jointTorque[0];
+}
+
+btScalar * btMultiBody::getJointTorqueMultiDof(int i)
+{
+ return &m_links[i].m_jointTorque[0];
+}
+
+inline btMatrix3x3 outerProduct(const btVector3& v0, const btVector3& v1) //renamed it from vecMulVecTranspose (http://en.wikipedia.org/wiki/Outer_product); maybe it should be moved to btVector3 like dot and cross?
+{
+ btVector3 row0 = btVector3(
+ v0.x() * v1.x(),
+ v0.x() * v1.y(),
+ v0.x() * v1.z());
+ btVector3 row1 = btVector3(
+ v0.y() * v1.x(),
+ v0.y() * v1.y(),
+ v0.y() * v1.z());
+ btVector3 row2 = btVector3(
+ v0.z() * v1.x(),
+ v0.z() * v1.y(),
+ v0.z() * v1.z());
+
+ btMatrix3x3 m(row0[0],row0[1],row0[2],
+ row1[0],row1[1],row1[2],
+ row2[0],row2[1],row2[2]);
+ return m;
+}
+
+#define vecMulVecTranspose(v0, v1Transposed) outerProduct(v0, v1Transposed)
+//
+
+void btMultiBody::computeAccelerationsArticulatedBodyAlgorithmMultiDof(btScalar dt,
+ btAlignedObjectArray<btScalar> &scratch_r,
+ btAlignedObjectArray<btVector3> &scratch_v,
+ btAlignedObjectArray<btMatrix3x3> &scratch_m,
+ bool isConstraintPass)
+{
+ // Implement Featherstone's algorithm to calculate joint accelerations (q_double_dot)
+ // and the base linear & angular accelerations.
+
+ // We apply damping forces in this routine as well as any external forces specified by the
+ // caller (via addBaseForce etc).
+
+ // output should point to an array of 6 + num_links reals.
+ // Format is: 3 angular accelerations (in world frame), 3 linear accelerations (in world frame),
+ // num_links joint acceleration values.
+
+ // We added support for multi degree of freedom (multi dof) joints.
+ // In addition we also can compute the joint reaction forces. This is performed in a second pass,
+ // so that we can include the effect of the constraint solver forces (computed in the PGS LCP solver)
+
+ m_internalNeedsJointFeedback = false;
+
+ int num_links = getNumLinks();
+
+ const btScalar DAMPING_K1_LINEAR = m_linearDamping;
+ const btScalar DAMPING_K2_LINEAR = m_linearDamping;
+
+ const btScalar DAMPING_K1_ANGULAR = m_angularDamping;
+ const btScalar DAMPING_K2_ANGULAR= m_angularDamping;
+
+ btVector3 base_vel = getBaseVel();
+ btVector3 base_omega = getBaseOmega();
+
+ // Temporary matrices/vectors -- use scratch space from caller
+ // so that we don't have to keep reallocating every frame
+
+ scratch_r.resize(2*m_dofCount + 6); //multidof? ("Y"s use it and it is used to store qdd) => 2 x m_dofCount
+ scratch_v.resize(8*num_links + 6);
+ scratch_m.resize(4*num_links + 4);
+
+ //btScalar * r_ptr = &scratch_r[0];
+ btScalar * output = &scratch_r[m_dofCount]; // "output" holds the q_double_dot results
+ btVector3 * v_ptr = &scratch_v[0];
+
+ // vhat_i (top = angular, bottom = linear part)
+ btSpatialMotionVector *spatVel = (btSpatialMotionVector *)v_ptr;
+ v_ptr += num_links * 2 + 2;
+ //
+ // zhat_i^A
+ btSpatialForceVector * zeroAccSpatFrc = (btSpatialForceVector *)v_ptr;
+ v_ptr += num_links * 2 + 2;
+ //
+ // chat_i (note NOT defined for the base)
+ btSpatialMotionVector * spatCoriolisAcc = (btSpatialMotionVector *)v_ptr;
+ v_ptr += num_links * 2;
+ //
+ // Ihat_i^A.
+ btSymmetricSpatialDyad * spatInertia = (btSymmetricSpatialDyad *)&scratch_m[num_links + 1];
+
+ // Cached 3x3 rotation matrices from parent frame to this frame.
+ btMatrix3x3 * rot_from_parent = &m_matrixBuf[0];
+ btMatrix3x3 * rot_from_world = &scratch_m[0];
+
+ // hhat_i, ahat_i
+ // hhat is NOT stored for the base (but ahat is)
+ btSpatialForceVector * h = (btSpatialForceVector *)(m_dofCount > 0 ? &m_vectorBuf[0] : 0);
+ btSpatialMotionVector * spatAcc = (btSpatialMotionVector *)v_ptr;
+ v_ptr += num_links * 2 + 2;
+ //
+ // Y_i, invD_i
+ btScalar * invD = m_dofCount > 0 ? &m_realBuf[6 + m_dofCount] : 0;
+ btScalar * Y = &scratch_r[0];
+ //
+ //aux variables
+ btSpatialMotionVector spatJointVel; //spatial velocity due to the joint motion (i.e. without predecessors' influence)
+ btScalar D[36]; //"D" matrix; it's dofxdof for each body so asingle 6x6 D matrix will do
+ btScalar invD_times_Y[6]; //D^{-1} * Y [dofxdof x dofx1 = dofx1] <=> D^{-1} * u; better moved to buffers since it is recalced in calcAccelerationDeltasMultiDof; num_dof of btScalar would cover all bodies
+ btSpatialMotionVector result; //holds results of the SolveImatrix op; it is a spatial motion vector (accel)
+ btScalar Y_minus_hT_a[6]; //Y - h^{T} * a; it's dofx1 for each body so a single 6x1 temp is enough
+ btSpatialForceVector spatForceVecTemps[6]; //6 temporary spatial force vectors
+ btSpatialTransformationMatrix fromParent; //spatial transform from parent to child
+ btSymmetricSpatialDyad dyadTemp; //inertia matrix temp
+ btSpatialTransformationMatrix fromWorld;
+ fromWorld.m_trnVec.setZero();
+ /////////////////
+
+ // ptr to the joint accel part of the output
+ btScalar * joint_accel = output + 6;
+
+ // Start of the algorithm proper.
+
+ // First 'upward' loop.
+ // Combines CompTreeLinkVelocities and InitTreeLinks from Mirtich.
+
+ rot_from_parent[0] = btMatrix3x3(m_baseQuat); //m_baseQuat assumed to be alias!?
+
+ //create the vector of spatial velocity of the base by transforming global-coor linear and angular velocities into base-local coordinates
+ spatVel[0].setVector(rot_from_parent[0] * base_omega, rot_from_parent[0] * base_vel);
+
+ if (m_fixedBase)
+ {
+ zeroAccSpatFrc[0].setZero();
+ }
+ else
+ {
+ btVector3 baseForce = isConstraintPass? m_baseConstraintForce : m_baseForce;
+ btVector3 baseTorque = isConstraintPass? m_baseConstraintTorque : m_baseTorque;
+ //external forces
+ zeroAccSpatFrc[0].setVector(-(rot_from_parent[0] * baseTorque), -(rot_from_parent[0] * baseForce));
+
+ //adding damping terms (only)
+ btScalar linDampMult = 1., angDampMult = 1.;
+ zeroAccSpatFrc[0].addVector(angDampMult * m_baseInertia * spatVel[0].getAngular() * (DAMPING_K1_ANGULAR + DAMPING_K2_ANGULAR * spatVel[0].getAngular().safeNorm()),
+ linDampMult * m_baseMass * spatVel[0].getLinear() * (DAMPING_K1_LINEAR + DAMPING_K2_LINEAR * spatVel[0].getLinear().safeNorm()));
+
+ //
+ //p += vhat x Ihat vhat - done in a simpler way
+ if (m_useGyroTerm)
+ zeroAccSpatFrc[0].addAngular(spatVel[0].getAngular().cross(m_baseInertia * spatVel[0].getAngular()));
+ //
+ zeroAccSpatFrc[0].addLinear(m_baseMass * spatVel[0].getAngular().cross(spatVel[0].getLinear()));
+ }
+
+
+ //init the spatial AB inertia (it has the simple form thanks to choosing local body frames origins at their COMs)
+ spatInertia[0].setMatrix( btMatrix3x3(0,0,0,0,0,0,0,0,0),
+ //
+ btMatrix3x3(m_baseMass, 0, 0,
+ 0, m_baseMass, 0,
+ 0, 0, m_baseMass),
+ //
+ btMatrix3x3(m_baseInertia[0], 0, 0,
+ 0, m_baseInertia[1], 0,
+ 0, 0, m_baseInertia[2])
+ );
+
+ rot_from_world[0] = rot_from_parent[0];
+
+ //
+ for (int i = 0; i < num_links; ++i) {
+ const int parent = m_links[i].m_parent;
+ rot_from_parent[i+1] = btMatrix3x3(m_links[i].m_cachedRotParentToThis);
+ rot_from_world[i+1] = rot_from_parent[i+1] * rot_from_world[parent+1];
+
+ fromParent.m_rotMat = rot_from_parent[i+1]; fromParent.m_trnVec = m_links[i].m_cachedRVector;
+ fromWorld.m_rotMat = rot_from_world[i+1];
+ fromParent.transform(spatVel[parent+1], spatVel[i+1]);
+
+ // now set vhat_i to its true value by doing
+ // vhat_i += qidot * shat_i
+ if(!m_useGlobalVelocities)
+ {
+ spatJointVel.setZero();
+
+ for(int dof = 0; dof < m_links[i].m_dofCount; ++dof)
+ spatJointVel += m_links[i].m_axes[dof] * getJointVelMultiDof(i)[dof];
+
+ // remember vhat_i is really vhat_p(i) (but in current frame) at this point => we need to add velocity across the inboard joint
+ spatVel[i+1] += spatJointVel;
+
+ //
+ // vhat_i is vhat_p(i) transformed to local coors + the velocity across the i-th inboard joint
+ //spatVel[i+1] = fromParent * spatVel[parent+1] + spatJointVel;
+
+ }
+ else
+ {
+ fromWorld.transformRotationOnly(m_links[i].m_absFrameTotVelocity, spatVel[i+1]);
+ fromWorld.transformRotationOnly(m_links[i].m_absFrameLocVelocity, spatJointVel);
+ }
+
+ // we can now calculate chat_i
+ spatVel[i+1].cross(spatJointVel, spatCoriolisAcc[i]);
+
+ // calculate zhat_i^A
+ //
+ //external forces
+ btVector3 linkAppliedForce = isConstraintPass? m_links[i].m_appliedConstraintForce : m_links[i].m_appliedForce;
+ btVector3 linkAppliedTorque =isConstraintPass ? m_links[i].m_appliedConstraintTorque : m_links[i].m_appliedTorque;
+
+ zeroAccSpatFrc[i+1].setVector(-(rot_from_world[i+1] * linkAppliedTorque), -(rot_from_world[i+1] * linkAppliedForce ));
+
+#if 0
+ {
+
+ b3Printf("stepVelocitiesMultiDof zeroAccSpatFrc[%d] linear:%f,%f,%f, angular:%f,%f,%f",
+ i+1,
+ zeroAccSpatFrc[i+1].m_topVec[0],
+ zeroAccSpatFrc[i+1].m_topVec[1],
+ zeroAccSpatFrc[i+1].m_topVec[2],
+
+ zeroAccSpatFrc[i+1].m_bottomVec[0],
+ zeroAccSpatFrc[i+1].m_bottomVec[1],
+ zeroAccSpatFrc[i+1].m_bottomVec[2]);
+ }
+#endif
+ //
+ //adding damping terms (only)
+ btScalar linDampMult = 1., angDampMult = 1.;
+ zeroAccSpatFrc[i+1].addVector(angDampMult * m_links[i].m_inertiaLocal * spatVel[i+1].getAngular() * (DAMPING_K1_ANGULAR + DAMPING_K2_ANGULAR * spatVel[i+1].getAngular().safeNorm()),
+ linDampMult * m_links[i].m_mass * spatVel[i+1].getLinear() * (DAMPING_K1_LINEAR + DAMPING_K2_LINEAR * spatVel[i+1].getLinear().safeNorm()));
+
+ // calculate Ihat_i^A
+ //init the spatial AB inertia (it has the simple form thanks to choosing local body frames origins at their COMs)
+ spatInertia[i+1].setMatrix( btMatrix3x3(0,0,0,0,0,0,0,0,0),
+ //
+ btMatrix3x3(m_links[i].m_mass, 0, 0,
+ 0, m_links[i].m_mass, 0,
+ 0, 0, m_links[i].m_mass),
+ //
+ btMatrix3x3(m_links[i].m_inertiaLocal[0], 0, 0,
+ 0, m_links[i].m_inertiaLocal[1], 0,
+ 0, 0, m_links[i].m_inertiaLocal[2])
+ );
+ //
+ //p += vhat x Ihat vhat - done in a simpler way
+ if(m_useGyroTerm)
+ zeroAccSpatFrc[i+1].addAngular(spatVel[i+1].getAngular().cross(m_links[i].m_inertiaLocal * spatVel[i+1].getAngular()));
+ //
+ zeroAccSpatFrc[i+1].addLinear(m_links[i].m_mass * spatVel[i+1].getAngular().cross(spatVel[i+1].getLinear()));
+ //btVector3 temp = m_links[i].m_mass * spatVel[i+1].getAngular().cross(spatVel[i+1].getLinear());
+ ////clamp parent's omega
+ //btScalar parOmegaMod = temp.length();
+ //btScalar parOmegaModMax = 1000;
+ //if(parOmegaMod > parOmegaModMax)
+ // temp *= parOmegaModMax / parOmegaMod;
+ //zeroAccSpatFrc[i+1].addLinear(temp);
+ //printf("|zeroAccSpatFrc[%d]| = %.4f\n", i+1, temp.length());
+ //temp = spatCoriolisAcc[i].getLinear();
+ //printf("|spatCoriolisAcc[%d]| = %.4f\n", i+1, temp.length());
+
+
+
+ //printf("w[%d] = [%.4f %.4f %.4f]\n", i, vel_top_angular[i+1].x(), vel_top_angular[i+1].y(), vel_top_angular[i+1].z());
+ //printf("v[%d] = [%.4f %.4f %.4f]\n", i, vel_bottom_linear[i+1].x(), vel_bottom_linear[i+1].y(), vel_bottom_linear[i+1].z());
+ //printf("c[%d] = [%.4f %.4f %.4f]\n", i, coriolis_bottom_linear[i].x(), coriolis_bottom_linear[i].y(), coriolis_bottom_linear[i].z());
+ }
+
+ // 'Downward' loop.
+ // (part of TreeForwardDynamics in Mirtich.)
+ for (int i = num_links - 1; i >= 0; --i)
+ {
+ const int parent = m_links[i].m_parent;
+ fromParent.m_rotMat = rot_from_parent[i+1]; fromParent.m_trnVec = m_links[i].m_cachedRVector;
+
+ for(int dof = 0; dof < m_links[i].m_dofCount; ++dof)
+ {
+ btSpatialForceVector &hDof = h[m_links[i].m_dofOffset + dof];
+ //
+ hDof = spatInertia[i+1] * m_links[i].m_axes[dof];
+ //
+ Y[m_links[i].m_dofOffset + dof] = m_links[i].m_jointTorque[dof]
+ - m_links[i].m_axes[dof].dot(zeroAccSpatFrc[i+1])
+ - spatCoriolisAcc[i].dot(hDof)
+ ;
+ }
+
+ for(int dof = 0; dof < m_links[i].m_dofCount; ++dof)
+ {
+ btScalar *D_row = &D[dof * m_links[i].m_dofCount];
+ for(int dof2 = 0; dof2 < m_links[i].m_dofCount; ++dof2)
+ {
+ btSpatialForceVector &hDof2 = h[m_links[i].m_dofOffset + dof2];
+ D_row[dof2] = m_links[i].m_axes[dof].dot(hDof2);
+ }
+ }
+
+ btScalar *invDi = &invD[m_links[i].m_dofOffset*m_links[i].m_dofOffset];
+ switch(m_links[i].m_jointType)
+ {
+ case btMultibodyLink::ePrismatic:
+ case btMultibodyLink::eRevolute:
+ {
+ invDi[0] = 1.0f / D[0];
+ break;
+ }
+ case btMultibodyLink::eSpherical:
+ case btMultibodyLink::ePlanar:
+ {
+ btMatrix3x3 D3x3; D3x3.setValue(D[0], D[1], D[2], D[3], D[4], D[5], D[6], D[7], D[8]);
+ btMatrix3x3 invD3x3; invD3x3 = D3x3.inverse();
+
+ //unroll the loop?
+ for(int row = 0; row < 3; ++row)
+ {
+ for(int col = 0; col < 3; ++col)
+ {
+ invDi[row * 3 + col] = invD3x3[row][col];
+ }
+ }
+
+ break;
+ }
+ default:
+ {
+
+ }
+ }
+
+ //determine h*D^{-1}
+ for(int dof = 0; dof < m_links[i].m_dofCount; ++dof)
+ {
+ spatForceVecTemps[dof].setZero();
+
+ for(int dof2 = 0; dof2 < m_links[i].m_dofCount; ++dof2)
+ {
+ btSpatialForceVector &hDof2 = h[m_links[i].m_dofOffset + dof2];
+ //
+ spatForceVecTemps[dof] += hDof2 * invDi[dof2 * m_links[i].m_dofCount + dof];
+ }
+ }
+
+ dyadTemp = spatInertia[i+1];
+
+ //determine (h*D^{-1}) * h^{T}
+ for(int dof = 0; dof < m_links[i].m_dofCount; ++dof)
+ {
+ btSpatialForceVector &hDof = h[m_links[i].m_dofOffset + dof];
+ //
+ dyadTemp -= symmetricSpatialOuterProduct(hDof, spatForceVecTemps[dof]);
+ }
+
+ fromParent.transformInverse(dyadTemp, spatInertia[parent+1], btSpatialTransformationMatrix::Add);
+
+ for(int dof = 0; dof < m_links[i].m_dofCount; ++dof)
+ {
+ invD_times_Y[dof] = 0.f;
+
+ for(int dof2 = 0; dof2 < m_links[i].m_dofCount; ++dof2)
+ {
+ invD_times_Y[dof] += invDi[dof * m_links[i].m_dofCount + dof2] * Y[m_links[i].m_dofOffset + dof2];
+ }
+ }
+
+ spatForceVecTemps[0] = zeroAccSpatFrc[i+1] + spatInertia[i+1] * spatCoriolisAcc[i];
+
+ for(int dof = 0; dof < m_links[i].m_dofCount; ++dof)
+ {
+ btSpatialForceVector &hDof = h[m_links[i].m_dofOffset + dof];
+ //
+ spatForceVecTemps[0] += hDof * invD_times_Y[dof];
+ }
+
+ fromParent.transformInverse(spatForceVecTemps[0], spatForceVecTemps[1]);
+
+ zeroAccSpatFrc[parent+1] += spatForceVecTemps[1];
+ }
+
+
+ // Second 'upward' loop
+ // (part of TreeForwardDynamics in Mirtich)
+
+ if (m_fixedBase)
+ {
+ spatAcc[0].setZero();
+ }
+ else
+ {
+ if (num_links > 0)
+ {
+ m_cachedInertiaValid = true;
+ m_cachedInertiaTopLeft = spatInertia[0].m_topLeftMat;
+ m_cachedInertiaTopRight = spatInertia[0].m_topRightMat;
+ m_cachedInertiaLowerLeft = spatInertia[0].m_bottomLeftMat;
+ m_cachedInertiaLowerRight= spatInertia[0].m_topLeftMat.transpose();
+
+ }
+
+ solveImatrix(zeroAccSpatFrc[0], result);
+ spatAcc[0] = -result;
+ }
+
+
+ // now do the loop over the m_links
+ for (int i = 0; i < num_links; ++i)
+ {
+ // qdd = D^{-1} * (Y - h^{T}*apar) = (S^{T}*I*S)^{-1} * (tau - S^{T}*I*cor - S^{T}*zeroAccFrc - S^{T}*I*apar)
+ // a = apar + cor + Sqdd
+ //or
+ // qdd = D^{-1} * (Y - h^{T}*(apar+cor))
+ // a = apar + Sqdd
+
+ const int parent = m_links[i].m_parent;
+ fromParent.m_rotMat = rot_from_parent[i+1]; fromParent.m_trnVec = m_links[i].m_cachedRVector;
+
+ fromParent.transform(spatAcc[parent+1], spatAcc[i+1]);
+
+ for(int dof = 0; dof < m_links[i].m_dofCount; ++dof)
+ {
+ btSpatialForceVector &hDof = h[m_links[i].m_dofOffset + dof];
+ //
+ Y_minus_hT_a[dof] = Y[m_links[i].m_dofOffset + dof] - spatAcc[i+1].dot(hDof);
+ }
+
+ btScalar *invDi = &invD[m_links[i].m_dofOffset*m_links[i].m_dofOffset];
+ //D^{-1} * (Y - h^{T}*apar)
+ mulMatrix(invDi, Y_minus_hT_a, m_links[i].m_dofCount, m_links[i].m_dofCount, m_links[i].m_dofCount, 1, &joint_accel[m_links[i].m_dofOffset]);
+
+ spatAcc[i+1] += spatCoriolisAcc[i];
+
+ for(int dof = 0; dof < m_links[i].m_dofCount; ++dof)
+ spatAcc[i+1] += m_links[i].m_axes[dof] * joint_accel[m_links[i].m_dofOffset + dof];
+
+ if (m_links[i].m_jointFeedback)
+ {
+ m_internalNeedsJointFeedback = true;
+
+ btVector3 angularBotVec = (spatInertia[i+1]*spatAcc[i+1]+zeroAccSpatFrc[i+1]).m_bottomVec;
+ btVector3 linearTopVec = (spatInertia[i+1]*spatAcc[i+1]+zeroAccSpatFrc[i+1]).m_topVec;
+
+ if (gJointFeedbackInJointFrame)
+ {
+ //shift the reaction forces to the joint frame
+ //linear (force) component is the same
+ //shift the angular (torque, moment) component using the relative position, m_links[i].m_dVector
+ angularBotVec = angularBotVec - linearTopVec.cross(m_links[i].m_dVector);
+ }
+
+
+ if (gJointFeedbackInWorldSpace)
+ {
+ if (isConstraintPass)
+ {
+ m_links[i].m_jointFeedback->m_reactionForces.m_bottomVec += m_links[i].m_cachedWorldTransform.getBasis()*angularBotVec;
+ m_links[i].m_jointFeedback->m_reactionForces.m_topVec += m_links[i].m_cachedWorldTransform.getBasis()*linearTopVec;
+ } else
+ {
+ m_links[i].m_jointFeedback->m_reactionForces.m_bottomVec = m_links[i].m_cachedWorldTransform.getBasis()*angularBotVec;
+ m_links[i].m_jointFeedback->m_reactionForces.m_topVec = m_links[i].m_cachedWorldTransform.getBasis()*linearTopVec;
+ }
+ } else
+ {
+ if (isConstraintPass)
+ {
+ m_links[i].m_jointFeedback->m_reactionForces.m_bottomVec += angularBotVec;
+ m_links[i].m_jointFeedback->m_reactionForces.m_topVec += linearTopVec;
+
+ }
+ else
+ {
+ m_links[i].m_jointFeedback->m_reactionForces.m_bottomVec = angularBotVec;
+ m_links[i].m_jointFeedback->m_reactionForces.m_topVec = linearTopVec;
+ }
+ }
+ }
+
+ }
+
+ // transform base accelerations back to the world frame.
+ btVector3 omegadot_out = rot_from_parent[0].transpose() * spatAcc[0].getAngular();
+ output[0] = omegadot_out[0];
+ output[1] = omegadot_out[1];
+ output[2] = omegadot_out[2];
+
+ btVector3 vdot_out = rot_from_parent[0].transpose() * (spatAcc[0].getLinear() + spatVel[0].getAngular().cross(spatVel[0].getLinear()));
+ output[3] = vdot_out[0];
+ output[4] = vdot_out[1];
+ output[5] = vdot_out[2];
+
+ /////////////////
+ //printf("q = [");
+ //printf("%.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f ", m_baseQuat.x(), m_baseQuat.y(), m_baseQuat.z(), m_baseQuat.w(), m_basePos.x(), m_basePos.y(), m_basePos.z());
+ //for(int link = 0; link < getNumLinks(); ++link)
+ // for(int dof = 0; dof < m_links[link].m_dofCount; ++dof)
+ // printf("%.6f ", m_links[link].m_jointPos[dof]);
+ //printf("]\n");
+ ////
+ //printf("qd = [");
+ //for(int dof = 0; dof < getNumDofs() + 6; ++dof)
+ // printf("%.6f ", m_realBuf[dof]);
+ //printf("]\n");
+ //printf("qdd = [");
+ //for(int dof = 0; dof < getNumDofs() + 6; ++dof)
+ // printf("%.6f ", output[dof]);
+ //printf("]\n");
+ /////////////////
+
+ // Final step: add the accelerations (times dt) to the velocities.
+
+ if (!isConstraintPass)
+ {
+ if(dt > 0.)
+ applyDeltaVeeMultiDof(output, dt);
+
+ }
+ /////
+ //btScalar angularThres = 1;
+ //btScalar maxAngVel = 0.;
+ //bool scaleDown = 1.;
+ //for(int link = 0; link < m_links.size(); ++link)
+ //{
+ // if(spatVel[link+1].getAngular().length() > maxAngVel)
+ // {
+ // maxAngVel = spatVel[link+1].getAngular().length();
+ // scaleDown = angularThres / spatVel[link+1].getAngular().length();
+ // break;
+ // }
+ //}
+
+ //if(scaleDown != 1.)
+ //{
+ // for(int link = 0; link < m_links.size(); ++link)
+ // {
+ // if(m_links[link].m_jointType == btMultibodyLink::eRevolute || m_links[link].m_jointType == btMultibodyLink::eSpherical)
+ // {
+ // for(int dof = 0; dof < m_links[link].m_dofCount; ++dof)
+ // getJointVelMultiDof(link)[dof] *= scaleDown;
+ // }
+ // }
+ //}
+ /////
+
+ /////////////////////
+ if(m_useGlobalVelocities)
+ {
+ for (int i = 0; i < num_links; ++i)
+ {
+ const int parent = m_links[i].m_parent;
+ //rot_from_parent[i+1] = btMatrix3x3(m_links[i].m_cachedRotParentToThis); /// <- done
+ //rot_from_world[i+1] = rot_from_parent[i+1] * rot_from_world[parent+1]; /// <- done
+
+ fromParent.m_rotMat = rot_from_parent[i+1]; fromParent.m_trnVec = m_links[i].m_cachedRVector;
+ fromWorld.m_rotMat = rot_from_world[i+1];
+
+ // vhat_i = i_xhat_p(i) * vhat_p(i)
+ fromParent.transform(spatVel[parent+1], spatVel[i+1]);
+ //nice alternative below (using operator *) but it generates temps
+ /////////////////////////////////////////////////////////////
+
+ // now set vhat_i to its true value by doing
+ // vhat_i += qidot * shat_i
+ spatJointVel.setZero();
+
+ for(int dof = 0; dof < m_links[i].m_dofCount; ++dof)
+ spatJointVel += m_links[i].m_axes[dof] * getJointVelMultiDof(i)[dof];
+
+ // remember vhat_i is really vhat_p(i) (but in current frame) at this point => we need to add velocity across the inboard joint
+ spatVel[i+1] += spatJointVel;
+
+
+ fromWorld.transformInverseRotationOnly(spatVel[i+1], m_links[i].m_absFrameTotVelocity);
+ fromWorld.transformInverseRotationOnly(spatJointVel, m_links[i].m_absFrameLocVelocity);
+ }
+ }
+
+}
+
+
+
+void btMultiBody::solveImatrix(const btVector3& rhs_top, const btVector3& rhs_bot, btScalar result[6]) const
+{
+ int num_links = getNumLinks();
+ ///solve I * x = rhs, so the result = invI * rhs
+ if (num_links == 0)
+ {
+ // in the case of 0 m_links (i.e. a plain rigid body, not a multibody) rhs * invI is easier
+ result[0] = rhs_bot[0] / m_baseInertia[0];
+ result[1] = rhs_bot[1] / m_baseInertia[1];
+ result[2] = rhs_bot[2] / m_baseInertia[2];
+ result[3] = rhs_top[0] / m_baseMass;
+ result[4] = rhs_top[1] / m_baseMass;
+ result[5] = rhs_top[2] / m_baseMass;
+ } else
+ {
+ if (!m_cachedInertiaValid)
+ {
+ for (int i=0;i<6;i++)
+ {
+ result[i] = 0.f;
+ }
+ return;
+ }
+ /// Special routine for calculating the inverse of a spatial inertia matrix
+ ///the 6x6 matrix is stored as 4 blocks of 3x3 matrices
+ btMatrix3x3 Binv = m_cachedInertiaTopRight.inverse()*-1.f;
+ btMatrix3x3 tmp = m_cachedInertiaLowerRight * Binv;
+ btMatrix3x3 invIupper_right = (tmp * m_cachedInertiaTopLeft + m_cachedInertiaLowerLeft).inverse();
+ tmp = invIupper_right * m_cachedInertiaLowerRight;
+ btMatrix3x3 invI_upper_left = (tmp * Binv);
+ btMatrix3x3 invI_lower_right = (invI_upper_left).transpose();
+ tmp = m_cachedInertiaTopLeft * invI_upper_left;
+ tmp[0][0]-= 1.0;
+ tmp[1][1]-= 1.0;
+ tmp[2][2]-= 1.0;
+ btMatrix3x3 invI_lower_left = (Binv * tmp);
+
+ //multiply result = invI * rhs
+ {
+ btVector3 vtop = invI_upper_left*rhs_top;
+ btVector3 tmp;
+ tmp = invIupper_right * rhs_bot;
+ vtop += tmp;
+ btVector3 vbot = invI_lower_left*rhs_top;
+ tmp = invI_lower_right * rhs_bot;
+ vbot += tmp;
+ result[0] = vtop[0];
+ result[1] = vtop[1];
+ result[2] = vtop[2];
+ result[3] = vbot[0];
+ result[4] = vbot[1];
+ result[5] = vbot[2];
+ }
+
+ }
+}
+void btMultiBody::solveImatrix(const btSpatialForceVector &rhs, btSpatialMotionVector &result) const
+{
+ int num_links = getNumLinks();
+ ///solve I * x = rhs, so the result = invI * rhs
+ if (num_links == 0)
+ {
+ // in the case of 0 m_links (i.e. a plain rigid body, not a multibody) rhs * invI is easier
+ result.setAngular(rhs.getAngular() / m_baseInertia);
+ result.setLinear(rhs.getLinear() / m_baseMass);
+ } else
+ {
+ /// Special routine for calculating the inverse of a spatial inertia matrix
+ ///the 6x6 matrix is stored as 4 blocks of 3x3 matrices
+ if (!m_cachedInertiaValid)
+ {
+ result.setLinear(btVector3(0,0,0));
+ result.setAngular(btVector3(0,0,0));
+ result.setVector(btVector3(0,0,0),btVector3(0,0,0));
+ return;
+ }
+ btMatrix3x3 Binv = m_cachedInertiaTopRight.inverse()*-1.f;
+ btMatrix3x3 tmp = m_cachedInertiaLowerRight * Binv;
+ btMatrix3x3 invIupper_right = (tmp * m_cachedInertiaTopLeft + m_cachedInertiaLowerLeft).inverse();
+ tmp = invIupper_right * m_cachedInertiaLowerRight;
+ btMatrix3x3 invI_upper_left = (tmp * Binv);
+ btMatrix3x3 invI_lower_right = (invI_upper_left).transpose();
+ tmp = m_cachedInertiaTopLeft * invI_upper_left;
+ tmp[0][0]-= 1.0;
+ tmp[1][1]-= 1.0;
+ tmp[2][2]-= 1.0;
+ btMatrix3x3 invI_lower_left = (Binv * tmp);
+
+ //multiply result = invI * rhs
+ {
+ btVector3 vtop = invI_upper_left*rhs.getLinear();
+ btVector3 tmp;
+ tmp = invIupper_right * rhs.getAngular();
+ vtop += tmp;
+ btVector3 vbot = invI_lower_left*rhs.getLinear();
+ tmp = invI_lower_right * rhs.getAngular();
+ vbot += tmp;
+ result.setVector(vtop, vbot);
+ }
+
+ }
+}
+
+void btMultiBody::mulMatrix(btScalar *pA, btScalar *pB, int rowsA, int colsA, int rowsB, int colsB, btScalar *pC) const
+{
+ for (int row = 0; row < rowsA; row++)
+ {
+ for (int col = 0; col < colsB; col++)
+ {
+ pC[row * colsB + col] = 0.f;
+ for (int inner = 0; inner < rowsB; inner++)
+ {
+ pC[row * colsB + col] += pA[row * colsA + inner] * pB[col + inner * colsB];
+ }
+ }
+ }
+}
+
+void btMultiBody::calcAccelerationDeltasMultiDof(const btScalar *force, btScalar *output,
+ btAlignedObjectArray<btScalar> &scratch_r, btAlignedObjectArray<btVector3> &scratch_v) const
+{
+ // Temporary matrices/vectors -- use scratch space from caller
+ // so that we don't have to keep reallocating every frame
+
+
+ int num_links = getNumLinks();
+ scratch_r.resize(m_dofCount);
+ scratch_v.resize(4*num_links + 4);
+
+ btScalar * r_ptr = m_dofCount ? &scratch_r[0] : 0;
+ btVector3 * v_ptr = &scratch_v[0];
+
+ // zhat_i^A (scratch space)
+ btSpatialForceVector * zeroAccSpatFrc = (btSpatialForceVector *)v_ptr;
+ v_ptr += num_links * 2 + 2;
+
+ // rot_from_parent (cached from calcAccelerations)
+ const btMatrix3x3 * rot_from_parent = &m_matrixBuf[0];
+
+ // hhat (cached), accel (scratch)
+ // hhat is NOT stored for the base (but ahat is)
+ const btSpatialForceVector * h = (btSpatialForceVector *)(m_dofCount > 0 ? &m_vectorBuf[0] : 0);
+ btSpatialMotionVector * spatAcc = (btSpatialMotionVector *)v_ptr;
+ v_ptr += num_links * 2 + 2;
+
+ // Y_i (scratch), invD_i (cached)
+ const btScalar * invD = m_dofCount > 0 ? &m_realBuf[6 + m_dofCount] : 0;
+ btScalar * Y = r_ptr;
+ ////////////////
+ //aux variables
+ btScalar invD_times_Y[6]; //D^{-1} * Y [dofxdof x dofx1 = dofx1] <=> D^{-1} * u; better moved to buffers since it is recalced in calcAccelerationDeltasMultiDof; num_dof of btScalar would cover all bodies
+ btSpatialMotionVector result; //holds results of the SolveImatrix op; it is a spatial motion vector (accel)
+ btScalar Y_minus_hT_a[6]; //Y - h^{T} * a; it's dofx1 for each body so a single 6x1 temp is enough
+ btSpatialForceVector spatForceVecTemps[6]; //6 temporary spatial force vectors
+ btSpatialTransformationMatrix fromParent;
+ /////////////////
+
+ // First 'upward' loop.
+ // Combines CompTreeLinkVelocities and InitTreeLinks from Mirtich.
+
+ // Fill in zero_acc
+ // -- set to force/torque on the base, zero otherwise
+ if (m_fixedBase)
+ {
+ zeroAccSpatFrc[0].setZero();
+ } else
+ {
+ //test forces
+ fromParent.m_rotMat = rot_from_parent[0];
+ fromParent.transformRotationOnly(btSpatialForceVector(-force[0],-force[1],-force[2], -force[3],-force[4],-force[5]), zeroAccSpatFrc[0]);
+ }
+ for (int i = 0; i < num_links; ++i)
+ {
+ zeroAccSpatFrc[i+1].setZero();
+ }
+
+ // 'Downward' loop.
+ // (part of TreeForwardDynamics in Mirtich.)
+ for (int i = num_links - 1; i >= 0; --i)
+ {
+ const int parent = m_links[i].m_parent;
+ fromParent.m_rotMat = rot_from_parent[i+1]; fromParent.m_trnVec = m_links[i].m_cachedRVector;
+
+ for(int dof = 0; dof < m_links[i].m_dofCount; ++dof)
+ {
+ Y[m_links[i].m_dofOffset + dof] = force[6 + m_links[i].m_dofOffset + dof]
+ - m_links[i].m_axes[dof].dot(zeroAccSpatFrc[i+1])
+ ;
+ }
+
+ btVector3 in_top, in_bottom, out_top, out_bottom;
+ const btScalar *invDi = &invD[m_links[i].m_dofOffset*m_links[i].m_dofOffset];
+
+ for(int dof = 0; dof < m_links[i].m_dofCount; ++dof)
+ {
+ invD_times_Y[dof] = 0.f;
+
+ for(int dof2 = 0; dof2 < m_links[i].m_dofCount; ++dof2)
+ {
+ invD_times_Y[dof] += invDi[dof * m_links[i].m_dofCount + dof2] * Y[m_links[i].m_dofOffset + dof2];
+ }
+ }
+
+ // Zp += pXi * (Zi + hi*Yi/Di)
+ spatForceVecTemps[0] = zeroAccSpatFrc[i+1];
+
+ for(int dof = 0; dof < m_links[i].m_dofCount; ++dof)
+ {
+ const btSpatialForceVector &hDof = h[m_links[i].m_dofOffset + dof];
+ //
+ spatForceVecTemps[0] += hDof * invD_times_Y[dof];
+ }
+
+
+ fromParent.transformInverse(spatForceVecTemps[0], spatForceVecTemps[1]);
+
+ zeroAccSpatFrc[parent+1] += spatForceVecTemps[1];
+ }
+
+ // ptr to the joint accel part of the output
+ btScalar * joint_accel = output + 6;
+
+
+ // Second 'upward' loop
+ // (part of TreeForwardDynamics in Mirtich)
+
+ if (m_fixedBase)
+ {
+ spatAcc[0].setZero();
+ }
+ else
+ {
+ solveImatrix(zeroAccSpatFrc[0], result);
+ spatAcc[0] = -result;
+
+ }
+
+ // now do the loop over the m_links
+ for (int i = 0; i < num_links; ++i)
+ {
+ const int parent = m_links[i].m_parent;
+ fromParent.m_rotMat = rot_from_parent[i+1]; fromParent.m_trnVec = m_links[i].m_cachedRVector;
+
+ fromParent.transform(spatAcc[parent+1], spatAcc[i+1]);
+
+ for(int dof = 0; dof < m_links[i].m_dofCount; ++dof)
+ {
+ const btSpatialForceVector &hDof = h[m_links[i].m_dofOffset + dof];
+ //
+ Y_minus_hT_a[dof] = Y[m_links[i].m_dofOffset + dof] - spatAcc[i+1].dot(hDof);
+ }
+
+ const btScalar *invDi = &invD[m_links[i].m_dofOffset*m_links[i].m_dofOffset];
+ mulMatrix(const_cast<btScalar*>(invDi), Y_minus_hT_a, m_links[i].m_dofCount, m_links[i].m_dofCount, m_links[i].m_dofCount, 1, &joint_accel[m_links[i].m_dofOffset]);
+
+ for(int dof = 0; dof < m_links[i].m_dofCount; ++dof)
+ spatAcc[i+1] += m_links[i].m_axes[dof] * joint_accel[m_links[i].m_dofOffset + dof];
+ }
+
+ // transform base accelerations back to the world frame.
+ btVector3 omegadot_out;
+ omegadot_out = rot_from_parent[0].transpose() * spatAcc[0].getAngular();
+ output[0] = omegadot_out[0];
+ output[1] = omegadot_out[1];
+ output[2] = omegadot_out[2];
+
+ btVector3 vdot_out;
+ vdot_out = rot_from_parent[0].transpose() * spatAcc[0].getLinear();
+ output[3] = vdot_out[0];
+ output[4] = vdot_out[1];
+ output[5] = vdot_out[2];
+
+ /////////////////
+ //printf("delta = [");
+ //for(int dof = 0; dof < getNumDofs() + 6; ++dof)
+ // printf("%.2f ", output[dof]);
+ //printf("]\n");
+ /////////////////
+}
+
+
+
+
+void btMultiBody::stepPositionsMultiDof(btScalar dt, btScalar *pq, btScalar *pqd)
+{
+ int num_links = getNumLinks();
+ // step position by adding dt * velocity
+ //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)
+ //
+ 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 = 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; 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();
+
+
+ //printf("pBaseOmega = %.4f %.4f %.4f\n", pBaseOmega->x(), pBaseOmega->y(), pBaseOmega->z());
+ //printf("pBaseVel = %.4f %.4f %.4f\n", pBaseVel->x(), pBaseVel->y(), pBaseVel->z());
+ //printf("baseQuat = %.4f %.4f %.4f %.4f\n", pBaseQuat->x(), pBaseQuat->y(), pBaseQuat->z(), pBaseQuat->w());
+
+ if(pq)
+ pq += 7;
+ if(pqd)
+ pqd += 6;
+
+ // 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 *pJointVel = (pqd ? pqd : getJointVelMultiDof(i));
+
+ switch(m_links[i].m_jointType)
+ {
+ case btMultibodyLink::ePrismatic:
+ case btMultibodyLink::eRevolute:
+ {
+ btScalar jointVel = pJointVel[0];
+ pJointPos[0] += dt * jointVel;
+ break;
+ }
+ case btMultibodyLink::eSpherical:
+ {
+ 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:
+ {
+ 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].updateCacheMultiDof(pq);
+
+ if(pq)
+ pq += m_links[i].m_posVarCount;
+ if(pqd)
+ pqd += m_links[i].m_dofCount;
+ }
+}
+
+void btMultiBody::fillConstraintJacobianMultiDof(int link,
+ const btVector3 &contact_point,
+ const btVector3 &normal_ang,
+ const btVector3 &normal_lin,
+ btScalar *jac,
+ btAlignedObjectArray<btScalar> &scratch_r,
+ btAlignedObjectArray<btVector3> &scratch_v,
+ btAlignedObjectArray<btMatrix3x3> &scratch_m) const
+{
+ // temporary space
+ int num_links = getNumLinks();
+ int m_dofCount = getNumDofs();
+ scratch_v.resize(3*num_links + 3); //(num_links + base) offsets + (num_links + base) normals_lin + (num_links + base) normals_ang
+ scratch_m.resize(num_links + 1);
+
+ btVector3 * v_ptr = &scratch_v[0];
+ btVector3 * p_minus_com_local = v_ptr; v_ptr += num_links + 1;
+ btVector3 * n_local_lin = v_ptr; v_ptr += num_links + 1;
+ btVector3 * n_local_ang = v_ptr; v_ptr += num_links + 1;
+ btAssert(v_ptr - &scratch_v[0] == scratch_v.size());
+
+ scratch_r.resize(m_dofCount);
+ btScalar * results = m_dofCount > 0 ? &scratch_r[0] : 0;
+
+ btMatrix3x3 * rot_from_world = &scratch_m[0];
+
+ const btVector3 p_minus_com_world = contact_point - m_basePos;
+ const btVector3 &normal_lin_world = normal_lin; //convenience
+ const btVector3 &normal_ang_world = normal_ang;
+
+ rot_from_world[0] = btMatrix3x3(m_baseQuat);
+
+ // omega coeffients first.
+ btVector3 omega_coeffs_world;
+ omega_coeffs_world = p_minus_com_world.cross(normal_lin_world);
+ jac[0] = omega_coeffs_world[0] + normal_ang_world[0];
+ jac[1] = omega_coeffs_world[1] + normal_ang_world[1];
+ jac[2] = omega_coeffs_world[2] + normal_ang_world[2];
+ // then v coefficients
+ jac[3] = normal_lin_world[0];
+ jac[4] = normal_lin_world[1];
+ jac[5] = normal_lin_world[2];
+
+ //create link-local versions of p_minus_com and normal
+ p_minus_com_local[0] = rot_from_world[0] * p_minus_com_world;
+ n_local_lin[0] = rot_from_world[0] * normal_lin_world;
+ n_local_ang[0] = rot_from_world[0] * normal_ang_world;
+
+ // Set remaining jac values to zero for now.
+ for (int i = 6; i < 6 + m_dofCount; ++i)
+ {
+ jac[i] = 0;
+ }
+
+ // Qdot coefficients, if necessary.
+ if (num_links > 0 && link > -1) {
+
+ // TODO: speed this up -- don't calculate for m_links we don't need.
+ // (Also, we are making 3 separate calls to this function, for the normal & the 2 friction directions,
+ // which is resulting in repeated work being done...)
+
+ // calculate required normals & positions in the local frames.
+ for (int i = 0; i < num_links; ++i) {
+
+ // transform to local frame
+ const int parent = m_links[i].m_parent;
+ const btMatrix3x3 mtx(m_links[i].m_cachedRotParentToThis);
+ rot_from_world[i+1] = mtx * rot_from_world[parent+1];
+
+ n_local_lin[i+1] = mtx * n_local_lin[parent+1];
+ n_local_ang[i+1] = mtx * n_local_ang[parent+1];
+ p_minus_com_local[i+1] = mtx * p_minus_com_local[parent+1] - m_links[i].m_cachedRVector;
+
+ // calculate the jacobian entry
+ switch(m_links[i].m_jointType)
+ {
+ case btMultibodyLink::eRevolute:
+ {
+ results[m_links[i].m_dofOffset] = n_local_lin[i+1].dot(m_links[i].getAxisTop(0).cross(p_minus_com_local[i+1]) + m_links[i].getAxisBottom(0));
+ results[m_links[i].m_dofOffset] += n_local_ang[i+1].dot(m_links[i].getAxisTop(0));
+ break;
+ }
+ case btMultibodyLink::ePrismatic:
+ {
+ results[m_links[i].m_dofOffset] = n_local_lin[i+1].dot(m_links[i].getAxisBottom(0));
+ break;
+ }
+ case btMultibodyLink::eSpherical:
+ {
+ results[m_links[i].m_dofOffset + 0] = n_local_lin[i+1].dot(m_links[i].getAxisTop(0).cross(p_minus_com_local[i+1]) + m_links[i].getAxisBottom(0));
+ results[m_links[i].m_dofOffset + 1] = n_local_lin[i+1].dot(m_links[i].getAxisTop(1).cross(p_minus_com_local[i+1]) + m_links[i].getAxisBottom(1));
+ results[m_links[i].m_dofOffset + 2] = n_local_lin[i+1].dot(m_links[i].getAxisTop(2).cross(p_minus_com_local[i+1]) + m_links[i].getAxisBottom(2));
+
+ results[m_links[i].m_dofOffset + 0] += n_local_ang[i+1].dot(m_links[i].getAxisTop(0));
+ results[m_links[i].m_dofOffset + 1] += n_local_ang[i+1].dot(m_links[i].getAxisTop(1));
+ results[m_links[i].m_dofOffset + 2] += n_local_ang[i+1].dot(m_links[i].getAxisTop(2));
+
+ break;
+ }
+ case btMultibodyLink::ePlanar:
+ {
+ results[m_links[i].m_dofOffset + 0] = n_local_lin[i+1].dot(m_links[i].getAxisTop(0).cross(p_minus_com_local[i+1]));// + m_links[i].getAxisBottom(0));
+ results[m_links[i].m_dofOffset + 1] = n_local_lin[i+1].dot(m_links[i].getAxisBottom(1));
+ results[m_links[i].m_dofOffset + 2] = n_local_lin[i+1].dot(m_links[i].getAxisBottom(2));
+
+ break;
+ }
+ default:
+ {
+ }
+ }
+
+ }
+
+ // Now copy through to output.
+ //printf("jac[%d] = ", link);
+ while (link != -1)
+ {
+ for(int dof = 0; dof < m_links[link].m_dofCount; ++dof)
+ {
+ jac[6 + m_links[link].m_dofOffset + dof] = results[m_links[link].m_dofOffset + dof];
+ //printf("%.2f\t", jac[6 + m_links[link].m_dofOffset + dof]);
+ }
+
+ link = m_links[link].m_parent;
+ }
+ //printf("]\n");
+ }
+}
+
+
+void btMultiBody::wakeUp()
+{
+ m_awake = true;
+}
+
+void btMultiBody::goToSleep()
+{
+ m_awake = false;
+}
+
+void btMultiBody::checkMotionAndSleepIfRequired(btScalar timestep)
+{
+ extern bool gDisableDeactivation;
+ if (!m_canSleep || gDisableDeactivation)
+ {
+ m_awake = true;
+ m_sleepTimer = 0;
+ return;
+ }
+
+ // motion is computed as omega^2 + v^2 + (sum of squares of joint velocities)
+ btScalar motion = 0;
+ {
+ for (int i = 0; i < 6 + m_dofCount; ++i)
+ motion += m_realBuf[i] * m_realBuf[i];
+ }
+
+
+ if (motion < SLEEP_EPSILON) {
+ m_sleepTimer += timestep;
+ if (m_sleepTimer > SLEEP_TIMEOUT) {
+ goToSleep();
+ }
+ } else {
+ m_sleepTimer = 0;
+ if (!m_awake)
+ wakeUp();
+ }
+}
+
+
+void btMultiBody::forwardKinematics(btAlignedObjectArray<btQuaternion>& world_to_local,btAlignedObjectArray<btVector3>& local_origin)
+{
+
+ int num_links = getNumLinks();
+
+ // Cached 3x3 rotation matrices from parent frame to this frame.
+ btMatrix3x3* rot_from_parent =(btMatrix3x3 *) &m_matrixBuf[0];
+
+ rot_from_parent[0] = btMatrix3x3(m_baseQuat); //m_baseQuat assumed to be alias!?
+
+ for (int i = 0; i < num_links; ++i)
+ {
+ rot_from_parent[i+1] = btMatrix3x3(m_links[i].m_cachedRotParentToThis);
+ }
+
+ int nLinks = getNumLinks();
+ ///base + num m_links
+ world_to_local.resize(nLinks+1);
+ local_origin.resize(nLinks+1);
+
+ world_to_local[0] = getWorldToBaseRot();
+ local_origin[0] = getBasePos();
+
+ for (int k=0;k<getNumLinks();k++)
+ {
+ const int parent = getParent(k);
+ world_to_local[k+1] = getParentToLocalRot(k) * world_to_local[parent+1];
+ local_origin[k+1] = local_origin[parent+1] + (quatRotate(world_to_local[k+1].inverse() , getRVector(k)));
+ }
+
+ for (int link=0;link<getNumLinks();link++)
+ {
+ int index = link+1;
+
+ btVector3 posr = local_origin[index];
+ 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]));
+ getLink(link).m_cachedWorldTransform = tr;
+
+ }
+
+}
+
+void btMultiBody::updateCollisionObjectWorldTransforms(btAlignedObjectArray<btQuaternion>& world_to_local,btAlignedObjectArray<btVector3>& local_origin)
+{
+ world_to_local.resize(getNumLinks()+1);
+ local_origin.resize(getNumLinks()+1);
+
+ world_to_local[0] = getWorldToBaseRot();
+ local_origin[0] = getBasePos();
+
+ 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()->setWorldTransform(tr);
+
+ }
+
+ for (int k=0;k<getNumLinks();k++)
+ {
+ const int parent = getParent(k);
+ world_to_local[k+1] = getParentToLocalRot(k) * world_to_local[parent+1];
+ local_origin[k+1] = local_origin[parent+1] + (quatRotate(world_to_local[k+1].inverse() , getRVector(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->setWorldTransform(tr);
+ }
+ }
+}
+
+int btMultiBody::calculateSerializeBufferSize() const
+{
+ int sz = sizeof(btMultiBodyData);
+ return sz;
+}
+
+ ///fills the dataBuffer and returns the struct name (and 0 on failure)
+const char* btMultiBody::serialize(void* dataBuffer, class btSerializer* serializer) const
+{
+ btMultiBodyData* mbd = (btMultiBodyData*) dataBuffer;
+ getBaseWorldTransform().serialize(mbd->m_baseWorldTransform);
+ mbd->m_baseMass = this->getBaseMass();
+ getBaseInertia().serialize(mbd->m_baseInertia);
+ {
+ char* name = (char*) serializer->findNameForPointer(m_baseName);
+ mbd->m_baseName = (char*)serializer->getUniquePointer(name);
+ if (mbd->m_baseName)
+ {
+ serializer->serializeName(name);
+ }
+ }
+ mbd->m_numLinks = this->getNumLinks();
+ if (mbd->m_numLinks)
+ {
+ int sz = sizeof(btMultiBodyLinkData);
+ int numElem = mbd->m_numLinks;
+ btChunk* chunk = serializer->allocate(sz,numElem);
+ btMultiBodyLinkData* memPtr = (btMultiBodyLinkData*)chunk->m_oldPtr;
+ for (int i=0;i<numElem;i++,memPtr++)
+ {
+
+ memPtr->m_jointType = getLink(i).m_jointType;
+ memPtr->m_dofCount = getLink(i).m_dofCount;
+ memPtr->m_posVarCount = getLink(i).m_posVarCount;
+
+ getLink(i).m_inertiaLocal.serialize(memPtr->m_linkInertia);
+ memPtr->m_linkMass = getLink(i).m_mass;
+ memPtr->m_parentIndex = getLink(i).m_parent;
+ memPtr->m_jointDamping = getLink(i).m_jointDamping;
+ memPtr->m_jointFriction = getLink(i).m_jointFriction;
+ memPtr->m_jointLowerLimit = getLink(i).m_jointLowerLimit;
+ memPtr->m_jointUpperLimit = getLink(i).m_jointUpperLimit;
+ memPtr->m_jointMaxForce = getLink(i).m_jointMaxForce;
+ memPtr->m_jointMaxVelocity = getLink(i).m_jointMaxVelocity;
+
+ getLink(i).m_eVector.serialize(memPtr->m_parentComToThisComOffset);
+ getLink(i).m_dVector.serialize(memPtr->m_thisPivotToThisComOffset);
+ getLink(i).m_zeroRotParentToThis.serialize(memPtr->m_zeroRotParentToThis);
+ btAssert(memPtr->m_dofCount<=3);
+ for (int dof = 0;dof<getLink(i).m_dofCount;dof++)
+ {
+ getLink(i).getAxisBottom(dof).serialize(memPtr->m_jointAxisBottom[dof]);
+ getLink(i).getAxisTop(dof).serialize(memPtr->m_jointAxisTop[dof]);
+
+ memPtr->m_jointTorque[dof] = getLink(i).m_jointTorque[dof];
+ memPtr->m_jointVel[dof] = getJointVelMultiDof(i)[dof];
+
+ }
+ int numPosVar = getLink(i).m_posVarCount;
+ for (int posvar = 0; posvar < numPosVar;posvar++)
+ {
+ memPtr->m_jointPos[posvar] = getLink(i).m_jointPos[posvar];
+ }
+
+
+ {
+ char* name = (char*) serializer->findNameForPointer(m_links[i].m_linkName);
+ memPtr->m_linkName = (char*)serializer->getUniquePointer(name);
+ if (memPtr->m_linkName)
+ {
+ serializer->serializeName(name);
+ }
+ }
+ {
+ char* name = (char*) serializer->findNameForPointer(m_links[i].m_jointName);
+ memPtr->m_jointName = (char*)serializer->getUniquePointer(name);
+ if (memPtr->m_jointName)
+ {
+ serializer->serializeName(name);
+ }
+ }
+ memPtr->m_linkCollider = (btCollisionObjectData*)serializer->getUniquePointer(getLink(i).m_collider);
+
+ }
+ serializer->finalizeChunk(chunk,btMultiBodyLinkDataName,BT_ARRAY_CODE,(void*) &m_links[0]);
+ }
+ mbd->m_links = mbd->m_numLinks? (btMultiBodyLinkData*) serializer->getUniquePointer((void*)&m_links[0]):0;
+
+ // Fill padding with zeros to appease msan.
+#ifdef BT_USE_DOUBLE_PRECISION
+ memset(mbd->m_padding, 0, sizeof(mbd->m_padding));
+#endif
+
+ return btMultiBodyDataName;
+}
diff --git a/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBody.h b/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBody.h
new file mode 100644
index 0000000000..655165ac18
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBody.h
@@ -0,0 +1,814 @@
+/*
+ * PURPOSE:
+ * Class representing an articulated rigid body. Stores the body's
+ * current state, allows forces and torques to be set, handles
+ * timestepping and implements Featherstone's algorithm.
+ *
+ * COPYRIGHT:
+ * Copyright (C) Stephen Thompson, <stephen@solarflare.org.uk>, 2011-2013
+ * Portions written By Erwin Coumans: connection to LCP solver, various multibody constraints, replacing Eigen math library by Bullet LinearMath and a dedicated 6x6 matrix inverse (solveImatrix)
+ * Portions written By Jakub Stepien: support for multi-DOF constraints, introduction of spatial algebra and several other improvements
+
+ 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_H
+#define BT_MULTIBODY_H
+
+#include "LinearMath/btScalar.h"
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btQuaternion.h"
+#include "LinearMath/btMatrix3x3.h"
+#include "LinearMath/btAlignedObjectArray.h"
+
+
+///serialization data, don't change them if you are not familiar with the details of the serialization mechanisms
+#ifdef BT_USE_DOUBLE_PRECISION
+ #define btMultiBodyData btMultiBodyDoubleData
+ #define btMultiBodyDataName "btMultiBodyDoubleData"
+ #define btMultiBodyLinkData btMultiBodyLinkDoubleData
+ #define btMultiBodyLinkDataName "btMultiBodyLinkDoubleData"
+#else
+ #define btMultiBodyData btMultiBodyFloatData
+ #define btMultiBodyDataName "btMultiBodyFloatData"
+ #define btMultiBodyLinkData btMultiBodyLinkFloatData
+ #define btMultiBodyLinkDataName "btMultiBodyLinkFloatData"
+#endif //BT_USE_DOUBLE_PRECISION
+
+#include "btMultiBodyLink.h"
+class btMultiBodyLinkCollider;
+
+ATTRIBUTE_ALIGNED16(class) btMultiBody
+{
+public:
+
+
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ //
+ // initialization
+ //
+
+ btMultiBody(int n_links, // NOT including the base
+ btScalar mass, // mass of base
+ const btVector3 &inertia, // inertia of base, in base frame; assumed diagonal
+ bool fixedBase, // whether the base is fixed (true) or can move (false)
+ bool canSleep, bool deprecatedMultiDof=true);
+
+
+ virtual ~btMultiBody();
+
+ //note: fixed link collision with parent is always disabled
+ void setupFixed(int linkIndex,
+ btScalar mass,
+ const btVector3 &inertia,
+ int parent,
+ const btQuaternion &rotParentToThis,
+ const btVector3 &parentComToThisPivotOffset,
+ const btVector3 &thisPivotToThisComOffset, bool deprecatedDisableParentCollision=true);
+
+
+ void setupPrismatic(int i,
+ btScalar mass,
+ const btVector3 &inertia,
+ int parent,
+ const btQuaternion &rotParentToThis,
+ const btVector3 &jointAxis,
+ const btVector3 &parentComToThisPivotOffset,
+ const btVector3 &thisPivotToThisComOffset,
+ bool disableParentCollision);
+
+ void setupRevolute(int linkIndex, // 0 to num_links-1
+ btScalar mass,
+ const btVector3 &inertia,
+ int parentIndex,
+ const btQuaternion &rotParentToThis, // rotate points in parent frame to this frame, when q = 0
+ const btVector3 &jointAxis, // in my frame
+ const btVector3 &parentComToThisPivotOffset, // vector from parent COM to joint axis, in PARENT frame
+ const btVector3 &thisPivotToThisComOffset, // vector from joint axis to my COM, in MY frame
+ bool disableParentCollision=false);
+
+ void setupSpherical(int linkIndex, // 0 to num_links-1
+ btScalar mass,
+ const btVector3 &inertia,
+ int parent,
+ const btQuaternion &rotParentToThis, // rotate points in parent frame to this frame, when q = 0
+ const btVector3 &parentComToThisPivotOffset, // vector from parent COM to joint axis, in PARENT frame
+ const btVector3 &thisPivotToThisComOffset, // vector from joint axis to my COM, in MY frame
+ bool disableParentCollision=false);
+
+ void setupPlanar(int i, // 0 to num_links-1
+ btScalar mass,
+ const btVector3 &inertia,
+ int parent,
+ const btQuaternion &rotParentToThis, // rotate points in parent frame to this frame, when q = 0
+ const btVector3 &rotationAxis,
+ const btVector3 &parentComToThisComOffset, // vector from parent COM to this COM, in PARENT frame
+ bool disableParentCollision=false);
+
+ const btMultibodyLink& getLink(int index) const
+ {
+ return m_links[index];
+ }
+
+ btMultibodyLink& getLink(int index)
+ {
+ return m_links[index];
+ }
+
+
+ void setBaseCollider(btMultiBodyLinkCollider* collider)//collider can be NULL to disable collision for the base
+ {
+ m_baseCollider = collider;
+ }
+ const btMultiBodyLinkCollider* getBaseCollider() const
+ {
+ return m_baseCollider;
+ }
+ btMultiBodyLinkCollider* getBaseCollider()
+ {
+ return m_baseCollider;
+ }
+
+ btMultiBodyLinkCollider* getLinkCollider(int index)
+ {
+ if (index >= 0 && index < getNumLinks())
+ {
+ return getLink(index).m_collider;
+ }
+ return 0;
+ }
+
+ //
+ // get parent
+ // input: link num from 0 to num_links-1
+ // output: link num from 0 to num_links-1, OR -1 to mean the base.
+ //
+ int getParent(int link_num) const;
+
+
+ //
+ // get number of m_links, masses, moments of inertia
+ //
+
+ int getNumLinks() const { return m_links.size(); }
+ int getNumDofs() const { return m_dofCount; }
+ int getNumPosVars() const { return m_posVarCnt; }
+ btScalar getBaseMass() const { return m_baseMass; }
+ const btVector3 & getBaseInertia() const { return m_baseInertia; }
+ btScalar getLinkMass(int i) const;
+ const btVector3 & getLinkInertia(int i) const;
+
+
+
+ //
+ // change mass (incomplete: can only change base mass and inertia at present)
+ //
+
+ void setBaseMass(btScalar mass) { m_baseMass = mass; }
+ void setBaseInertia(const btVector3 &inertia) { m_baseInertia = inertia; }
+
+
+ //
+ // get/set pos/vel/rot/omega for the base link
+ //
+
+ const btVector3 & getBasePos() const { return m_basePos; } // in world frame
+ const btVector3 getBaseVel() const
+ {
+ return btVector3(m_realBuf[3],m_realBuf[4],m_realBuf[5]);
+ } // in world frame
+ const btQuaternion & getWorldToBaseRot() const
+ {
+ return m_baseQuat;
+ } // 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;
+ }
+
+ void setBaseWorldTransform(const btTransform& tr)
+ {
+ setBasePos(tr.getOrigin());
+ setWorldToBaseRot(tr.getRotation().inverse());
+
+ }
+
+ btTransform getBaseWorldTransform() const
+ {
+ btTransform tr;
+ tr.setOrigin(getBasePos());
+ tr.setRotation(getWorldToBaseRot().inverse());
+ return tr;
+ }
+
+ void setBaseVel(const btVector3 &vel)
+ {
+
+ m_realBuf[3]=vel[0]; m_realBuf[4]=vel[1]; m_realBuf[5]=vel[2];
+ }
+ void setWorldToBaseRot(const btQuaternion &rot)
+ {
+ m_baseQuat = rot; //m_baseQuat asumed to ba alias!?
+ }
+ void setBaseOmega(const btVector3 &omega)
+ {
+ m_realBuf[0]=omega[0];
+ m_realBuf[1]=omega[1];
+ m_realBuf[2]=omega[2];
+ }
+
+
+ //
+ // get/set pos/vel for child m_links (i = 0 to num_links-1)
+ //
+
+ btScalar getJointPos(int i) const;
+ btScalar getJointVel(int i) const;
+
+ btScalar * getJointVelMultiDof(int i);
+ btScalar * getJointPosMultiDof(int i);
+
+ const btScalar * getJointVelMultiDof(int i) const ;
+ const btScalar * getJointPosMultiDof(int i) const ;
+
+ void setJointPos(int i, btScalar q);
+ void setJointVel(int i, btScalar qdot);
+ void setJointPosMultiDof(int i, btScalar *q);
+ void setJointVelMultiDof(int i, btScalar *qdot);
+
+
+
+ //
+ // direct access to velocities as a vector of 6 + num_links elements.
+ // (omega first, then v, then joint velocities.)
+ //
+ const btScalar * getVelocityVector() const
+ {
+ return &m_realBuf[0];
+ }
+/* btScalar * getVelocityVector()
+ {
+ return &real_buf[0];
+ }
+ */
+
+ //
+ // get the frames of reference (positions and orientations) of the child m_links
+ // (i = 0 to num_links-1)
+ //
+
+ 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.
+
+
+ //
+ // transform vectors in local frame of link i to world frame (or vice versa)
+ //
+ btVector3 localPosToWorld(int i, const btVector3 &vec) const;
+ btVector3 localDirToWorld(int i, const btVector3 &vec) const;
+ btVector3 worldPosToLocal(int i, const btVector3 &vec) const;
+ btVector3 worldDirToLocal(int i, const btVector3 &vec) const;
+
+ //
+ // transform a frame in local coordinate to a frame in world coordinate
+ //
+ btMatrix3x3 localFrameToWorld(int i, const btMatrix3x3 &mat) const;
+
+ //
+ // calculate kinetic energy and angular momentum
+ // useful for debugging.
+ //
+
+ btScalar getKineticEnergy() const;
+ btVector3 getAngularMomentum() const;
+
+
+ //
+ // set external forces and torques. Note all external forces/torques are given in the WORLD frame.
+ //
+
+ void clearForcesAndTorques();
+ void clearConstraintForces();
+
+ void clearVelocities();
+
+ void addBaseForce(const btVector3 &f)
+ {
+ m_baseForce += f;
+ }
+ void addBaseTorque(const btVector3 &t) { m_baseTorque += t; }
+ void addLinkForce(int i, const btVector3 &f);
+ void addLinkTorque(int i, const btVector3 &t);
+
+ void addBaseConstraintForce(const btVector3 &f)
+ {
+ m_baseConstraintForce += f;
+ }
+ void addBaseConstraintTorque(const btVector3 &t) { m_baseConstraintTorque += t; }
+ void addLinkConstraintForce(int i, const btVector3 &f);
+ void addLinkConstraintTorque(int i, const btVector3 &t);
+
+
+void addJointTorque(int i, btScalar Q);
+ void addJointTorqueMultiDof(int i, int dof, btScalar Q);
+ void addJointTorqueMultiDof(int i, const btScalar *Q);
+
+ const btVector3 & getBaseForce() const { return m_baseForce; }
+ const btVector3 & getBaseTorque() const { return m_baseTorque; }
+ const btVector3 & getLinkForce(int i) const;
+ const btVector3 & getLinkTorque(int i) const;
+ btScalar getJointTorque(int i) const;
+ btScalar * getJointTorqueMultiDof(int i);
+
+
+ //
+ // dynamics routines.
+ //
+
+ // timestep the velocities (given the external forces/torques set using addBaseForce etc).
+ // also sets up caches for calcAccelerationDeltas.
+ //
+ // Note: the caller must provide three vectors which are used as
+ // temporary scratch space. The idea here is to reduce dynamic
+ // memory allocation: the same scratch vectors can be re-used
+ // again and again for different Multibodies, instead of each
+ // btMultiBody allocating (and then deallocating) their own
+ // individual scratch buffers. This gives a considerable speed
+ // improvement, at least on Windows (where dynamic memory
+ // allocation appears to be fairly slow).
+ //
+
+
+ void computeAccelerationsArticulatedBodyAlgorithmMultiDof(btScalar dt,
+ btAlignedObjectArray<btScalar> &scratch_r,
+ btAlignedObjectArray<btVector3> &scratch_v,
+ btAlignedObjectArray<btMatrix3x3> &scratch_m,
+ bool isConstraintPass=false
+ );
+
+///stepVelocitiesMultiDof is deprecated, use computeAccelerationsArticulatedBodyAlgorithmMultiDof instead
+ void stepVelocitiesMultiDof(btScalar dt,
+ btAlignedObjectArray<btScalar> &scratch_r,
+ btAlignedObjectArray<btVector3> &scratch_v,
+ btAlignedObjectArray<btMatrix3x3> &scratch_m,
+ bool isConstraintPass=false)
+ {
+ computeAccelerationsArticulatedBodyAlgorithmMultiDof(dt,scratch_r,scratch_v,scratch_m,isConstraintPass);
+ }
+
+ // calcAccelerationDeltasMultiDof
+ // input: force vector (in same format as jacobian, i.e.:
+ // 3 torque values, 3 force values, num_links joint torque values)
+ // output: 3 omegadot values, 3 vdot values, num_links q_double_dot values
+ // (existing contents of output array are replaced)
+ // calcAccelerationDeltasMultiDof must have been called first.
+ void calcAccelerationDeltasMultiDof(const btScalar *force, btScalar *output,
+ btAlignedObjectArray<btScalar> &scratch_r,
+ btAlignedObjectArray<btVector3> &scratch_v) const;
+
+
+ void applyDeltaVeeMultiDof2(const btScalar * delta_vee, btScalar multiplier)
+ {
+ for (int dof = 0; dof < 6 + getNumDofs(); ++dof)
+ {
+ m_deltaV[dof] += delta_vee[dof] * multiplier;
+ }
+ }
+ void processDeltaVeeMultiDof2()
+ {
+ applyDeltaVeeMultiDof(&m_deltaV[0],1);
+
+ for (int dof = 0; dof < 6 + getNumDofs(); ++dof)
+ {
+ m_deltaV[dof] = 0.f;
+ }
+ }
+
+ void applyDeltaVeeMultiDof(const btScalar * delta_vee, btScalar multiplier)
+ {
+ //for (int dof = 0; dof < 6 + getNumDofs(); ++dof)
+ // printf("%.4f ", delta_vee[dof]*multiplier);
+ //printf("\n");
+
+ //btScalar sum = 0;
+ //for (int dof = 0; dof < 6 + getNumDofs(); ++dof)
+ //{
+ // sum += delta_vee[dof]*multiplier*delta_vee[dof]*multiplier;
+ //}
+ //btScalar l = btSqrt(sum);
+
+ //if (l>m_maxAppliedImpulse)
+ //{
+ // multiplier *= m_maxAppliedImpulse/l;
+ //}
+
+ for (int dof = 0; dof < 6 + getNumDofs(); ++dof)
+ {
+ m_realBuf[dof] += delta_vee[dof] * multiplier;
+ btClamp(m_realBuf[dof],-m_maxCoordinateVelocity,m_maxCoordinateVelocity);
+ }
+ }
+
+
+
+ // timestep the positions (given current velocities).
+ void stepPositionsMultiDof(btScalar dt, btScalar *pq = 0, btScalar *pqd = 0);
+
+
+ //
+ // contacts
+ //
+
+ // This routine fills out a contact constraint jacobian for this body.
+ // the 'normal' supplied must be -n for body1 or +n for body2 of the contact.
+ // 'normal' & 'contact_point' are both given in world coordinates.
+
+ void fillContactJacobianMultiDof(int link,
+ const btVector3 &contact_point,
+ const btVector3 &normal,
+ btScalar *jac,
+ btAlignedObjectArray<btScalar> &scratch_r,
+ btAlignedObjectArray<btVector3> &scratch_v,
+ btAlignedObjectArray<btMatrix3x3> &scratch_m) const { fillConstraintJacobianMultiDof(link, contact_point, btVector3(0, 0, 0), normal, jac, scratch_r, scratch_v, scratch_m); }
+
+ //a more general version of fillContactJacobianMultiDof which does not assume..
+ //.. that the constraint in question is contact or, to be more precise, constrains linear velocity only
+ void fillConstraintJacobianMultiDof(int link,
+ const btVector3 &contact_point,
+ const btVector3 &normal_ang,
+ const btVector3 &normal_lin,
+ btScalar *jac,
+ btAlignedObjectArray<btScalar> &scratch_r,
+ btAlignedObjectArray<btVector3> &scratch_v,
+ btAlignedObjectArray<btMatrix3x3> &scratch_m) const;
+
+
+ //
+ // sleeping
+ //
+ void setCanSleep(bool canSleep)
+ {
+ m_canSleep = canSleep;
+ }
+
+ bool getCanSleep()const
+ {
+ return m_canSleep;
+ }
+
+ bool isAwake() const { return m_awake; }
+ void wakeUp();
+ void goToSleep();
+ void checkMotionAndSleepIfRequired(btScalar timestep);
+
+ bool hasFixedBase() const
+ {
+ return m_fixedBase;
+ }
+
+ int getCompanionId() const
+ {
+ return m_companionId;
+ }
+ void setCompanionId(int id)
+ {
+ //printf("for %p setCompanionId(%d)\n",this, id);
+ m_companionId = id;
+ }
+
+ void setNumLinks(int numLinks)//careful: when changing the number of m_links, make sure to re-initialize or update existing m_links
+ {
+ m_links.resize(numLinks);
+ }
+
+ btScalar getLinearDamping() const
+ {
+ return m_linearDamping;
+ }
+ void setLinearDamping( btScalar damp)
+ {
+ m_linearDamping = damp;
+ }
+ btScalar getAngularDamping() const
+ {
+ return m_angularDamping;
+ }
+ void setAngularDamping( btScalar damp)
+ {
+ m_angularDamping = damp;
+ }
+
+ bool getUseGyroTerm() const
+ {
+ return m_useGyroTerm;
+ }
+ void setUseGyroTerm(bool useGyro)
+ {
+ m_useGyroTerm = useGyro;
+ }
+ btScalar getMaxCoordinateVelocity() const
+ {
+ return m_maxCoordinateVelocity ;
+ }
+ void setMaxCoordinateVelocity(btScalar maxVel)
+ {
+ m_maxCoordinateVelocity = maxVel;
+ }
+
+ btScalar getMaxAppliedImpulse() const
+ {
+ return m_maxAppliedImpulse;
+ }
+ void setMaxAppliedImpulse(btScalar maxImp)
+ {
+ m_maxAppliedImpulse = maxImp;
+ }
+ void setHasSelfCollision(bool hasSelfCollision)
+ {
+ m_hasSelfCollision = hasSelfCollision;
+ }
+ bool hasSelfCollision() const
+ {
+ return m_hasSelfCollision;
+ }
+
+
+ void finalizeMultiDof();
+
+ void useRK4Integration(bool use) { m_useRK4 = use; }
+ bool isUsingRK4Integration() const { return m_useRK4; }
+ void useGlobalVelocities(bool use) { m_useGlobalVelocities = use; }
+ bool isUsingGlobalVelocities() const { return m_useGlobalVelocities; }
+
+ bool isPosUpdated() const
+ {
+ return __posUpdated;
+ }
+ void setPosUpdated(bool updated)
+ {
+ __posUpdated = updated;
+ }
+
+ //internalNeedsJointFeedback is for internal use only
+ bool internalNeedsJointFeedback() const
+ {
+ return m_internalNeedsJointFeedback;
+ }
+ void forwardKinematics(btAlignedObjectArray<btQuaternion>& scratch_q,btAlignedObjectArray<btVector3>& scratch_m);
+
+ void compTreeLinkVelocities(btVector3 *omega, btVector3 *vel) const;
+
+ void updateCollisionObjectWorldTransforms(btAlignedObjectArray<btQuaternion>& scratch_q,btAlignedObjectArray<btVector3>& scratch_m);
+
+ 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;
+
+ const char* getBaseName() const
+ {
+ return m_baseName;
+ }
+ ///memory of setBaseName needs to be manager by user
+ void setBaseName(const char* name)
+ {
+ m_baseName = name;
+ }
+
+ ///users can point to their objects, userPointer is not used by Bullet
+ void* getUserPointer() const
+ {
+ return m_userObjectPointer;
+ }
+
+ int getUserIndex() const
+ {
+ return m_userIndex;
+ }
+
+ int getUserIndex2() const
+ {
+ return m_userIndex2;
+ }
+ ///users can point to their objects, userPointer is not used by Bullet
+ void setUserPointer(void* userPointer)
+ {
+ m_userObjectPointer = userPointer;
+ }
+
+ ///users can point to their objects, userPointer is not used by Bullet
+ void setUserIndex(int index)
+ {
+ m_userIndex = index;
+ }
+
+ void setUserIndex2(int index)
+ {
+ m_userIndex2 = index;
+ }
+
+private:
+ btMultiBody(const btMultiBody &); // not implemented
+ void operator=(const btMultiBody &); // not implemented
+
+
+ void solveImatrix(const btVector3& rhs_top, const btVector3& rhs_bot, btScalar result[6]) const;
+ void solveImatrix(const btSpatialForceVector &rhs, btSpatialMotionVector &result) const;
+
+ void updateLinksDofOffsets()
+ {
+ int dofOffset = 0, cfgOffset = 0;
+ for(int bidx = 0; bidx < m_links.size(); ++bidx)
+ {
+ m_links[bidx].m_dofOffset = dofOffset; m_links[bidx].m_cfgOffset = cfgOffset;
+ dofOffset += m_links[bidx].m_dofCount; cfgOffset += m_links[bidx].m_posVarCount;
+ }
+ }
+
+ void mulMatrix(btScalar *pA, btScalar *pB, int rowsA, int colsA, int rowsB, int colsB, btScalar *pC) const;
+
+
+private:
+
+ btMultiBodyLinkCollider* m_baseCollider;//can be NULL
+ const char* m_baseName;//memory needs to be manager by user!
+
+ btVector3 m_basePos; // position of COM of base (world frame)
+ btQuaternion m_baseQuat; // rotates world points into base frame
+
+ btScalar m_baseMass; // mass of the base
+ btVector3 m_baseInertia; // inertia of the base (in local frame; diagonal)
+
+ btVector3 m_baseForce; // external force applied to base. World frame.
+ btVector3 m_baseTorque; // external torque applied to base. World frame.
+
+ btVector3 m_baseConstraintForce; // external force applied to base. World frame.
+ btVector3 m_baseConstraintTorque; // external torque applied to base. World frame.
+
+ btAlignedObjectArray<btMultibodyLink> m_links; // array of m_links, excluding the base. index from 0 to num_links-1.
+
+
+ //
+ // realBuf:
+ // offset size array
+ // 0 6 + num_links v (base_omega; base_vel; joint_vels) MULTIDOF [sysdof x sysdof for D matrices (TOO MUCH!) + pos_delta which is sys-cfg sized]
+ // 6+num_links num_links D
+ //
+ // vectorBuf:
+ // offset size array
+ // 0 num_links h_top
+ // num_links num_links h_bottom
+ //
+ // matrixBuf:
+ // offset size array
+ // 0 num_links+1 rot_from_parent
+ //
+ btAlignedObjectArray<btScalar> m_deltaV;
+ btAlignedObjectArray<btScalar> m_realBuf;
+ btAlignedObjectArray<btVector3> m_vectorBuf;
+ btAlignedObjectArray<btMatrix3x3> m_matrixBuf;
+
+
+ btMatrix3x3 m_cachedInertiaTopLeft;
+ btMatrix3x3 m_cachedInertiaTopRight;
+ btMatrix3x3 m_cachedInertiaLowerLeft;
+ btMatrix3x3 m_cachedInertiaLowerRight;
+ bool m_cachedInertiaValid;
+
+ bool m_fixedBase;
+
+ // Sleep parameters.
+ bool m_awake;
+ bool m_canSleep;
+ btScalar m_sleepTimer;
+
+ void* m_userObjectPointer;
+ int m_userIndex2;
+ int m_userIndex;
+
+ int m_companionId;
+ btScalar m_linearDamping;
+ btScalar m_angularDamping;
+ bool m_useGyroTerm;
+ btScalar m_maxAppliedImpulse;
+ btScalar m_maxCoordinateVelocity;
+ bool m_hasSelfCollision;
+
+ bool __posUpdated;
+ int m_dofCount, m_posVarCnt;
+ bool m_useRK4, m_useGlobalVelocities;
+
+ ///the m_needsJointFeedback gets updated/computed during the stepVelocitiesMultiDof and it for internal usage only
+ bool m_internalNeedsJointFeedback;
+};
+
+struct btMultiBodyLinkDoubleData
+{
+ btQuaternionDoubleData m_zeroRotParentToThis;
+ btVector3DoubleData m_parentComToThisComOffset;
+ btVector3DoubleData m_thisPivotToThisComOffset;
+ btVector3DoubleData m_jointAxisTop[6];
+ btVector3DoubleData m_jointAxisBottom[6];
+
+ btVector3DoubleData m_linkInertia; // inertia of the base (in local frame; diagonal)
+ double m_linkMass;
+ int m_parentIndex;
+ int m_jointType;
+
+ int m_dofCount;
+ int m_posVarCount;
+ double m_jointPos[7];
+ double m_jointVel[6];
+ double m_jointTorque[6];
+
+ double m_jointDamping;
+ double m_jointFriction;
+ double m_jointLowerLimit;
+ double m_jointUpperLimit;
+ double m_jointMaxForce;
+ double m_jointMaxVelocity;
+
+ char *m_linkName;
+ char *m_jointName;
+ btCollisionObjectDoubleData *m_linkCollider;
+ char *m_paddingPtr;
+
+};
+
+struct btMultiBodyLinkFloatData
+{
+ btQuaternionFloatData m_zeroRotParentToThis;
+ btVector3FloatData m_parentComToThisComOffset;
+ btVector3FloatData m_thisPivotToThisComOffset;
+ btVector3FloatData m_jointAxisTop[6];
+ btVector3FloatData m_jointAxisBottom[6];
+ btVector3FloatData m_linkInertia; // inertia of the base (in local frame; diagonal)
+ int m_dofCount;
+ float m_linkMass;
+ int m_parentIndex;
+ int m_jointType;
+
+
+
+ float m_jointPos[7];
+ float m_jointVel[6];
+ float m_jointTorque[6];
+ int m_posVarCount;
+ float m_jointDamping;
+ float m_jointFriction;
+ float m_jointLowerLimit;
+ float m_jointUpperLimit;
+ float m_jointMaxForce;
+ float m_jointMaxVelocity;
+
+ char *m_linkName;
+ char *m_jointName;
+ btCollisionObjectFloatData *m_linkCollider;
+ char *m_paddingPtr;
+
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btMultiBodyDoubleData
+{
+ btTransformDoubleData m_baseWorldTransform;
+ btVector3DoubleData m_baseInertia; // inertia of the base (in local frame; diagonal)
+ double m_baseMass;
+
+ char *m_baseName;
+ btMultiBodyLinkDoubleData *m_links;
+ btCollisionObjectDoubleData *m_baseCollider;
+ char *m_paddingPtr;
+ int m_numLinks;
+ char m_padding[4];
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btMultiBodyFloatData
+{
+ char *m_baseName;
+ btMultiBodyLinkFloatData *m_links;
+ btCollisionObjectFloatData *m_baseCollider;
+ btTransformFloatData m_baseWorldTransform;
+ btVector3FloatData m_baseInertia; // inertia of the base (in local frame; diagonal)
+
+ float m_baseMass;
+ int m_numLinks;
+};
+
+
+
+#endif
diff --git a/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyConstraint.cpp b/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyConstraint.cpp
new file mode 100644
index 0000000000..d52852dd8e
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyConstraint.cpp
@@ -0,0 +1,417 @@
+#include "btMultiBodyConstraint.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "btMultiBodyPoint2Point.h" //for testing (BTMBP2PCONSTRAINT_BLOCK_ANGULAR_MOTION_TEST macro)
+
+
+
+btMultiBodyConstraint::btMultiBodyConstraint(btMultiBody* bodyA,btMultiBody* bodyB,int linkA, int linkB, int numRows, bool isUnilateral)
+ :m_bodyA(bodyA),
+ m_bodyB(bodyB),
+ m_linkA(linkA),
+ m_linkB(linkB),
+ m_numRows(numRows),
+ m_jacSizeA(0),
+ m_jacSizeBoth(0),
+ m_isUnilateral(isUnilateral),
+ m_numDofsFinalized(-1),
+ m_maxAppliedImpulse(100)
+{
+
+}
+
+void btMultiBodyConstraint::updateJacobianSizes()
+{
+ if(m_bodyA)
+ {
+ m_jacSizeA = (6 + m_bodyA->getNumDofs());
+ }
+
+ if(m_bodyB)
+ {
+ m_jacSizeBoth = m_jacSizeA + 6 + m_bodyB->getNumDofs();
+ }
+ else
+ m_jacSizeBoth = m_jacSizeA;
+}
+
+void btMultiBodyConstraint::allocateJacobiansMultiDof()
+{
+ updateJacobianSizes();
+
+ m_posOffset = ((1 + m_jacSizeBoth)*m_numRows);
+ m_data.resize((2 + m_jacSizeBoth) * m_numRows);
+}
+
+btMultiBodyConstraint::~btMultiBodyConstraint()
+{
+}
+
+void btMultiBodyConstraint::applyDeltaVee(btMultiBodyJacobianData& data, btScalar* delta_vee, btScalar impulse, int velocityIndex, int ndof)
+{
+ for (int i = 0; i < ndof; ++i)
+ data.m_deltaVelocities[velocityIndex+i] += delta_vee[i] * impulse;
+}
+
+btScalar btMultiBodyConstraint::fillMultiBodyConstraint( btMultiBodySolverConstraint& solverConstraint,
+ btMultiBodyJacobianData& data,
+ btScalar* jacOrgA, btScalar* jacOrgB,
+ const btVector3& constraintNormalAng,
+ const btVector3& constraintNormalLin,
+ const btVector3& posAworld, const btVector3& posBworld,
+ btScalar posError,
+ const btContactSolverInfo& infoGlobal,
+ btScalar lowerLimit, btScalar upperLimit,
+ bool angConstraint,
+ btScalar relaxation,
+ bool isFriction, btScalar desiredVelocity, btScalar cfmSlip)
+{
+ solverConstraint.m_multiBodyA = m_bodyA;
+ solverConstraint.m_multiBodyB = m_bodyB;
+ solverConstraint.m_linkA = m_linkA;
+ solverConstraint.m_linkB = m_linkB;
+
+ btMultiBody* multiBodyA = solverConstraint.m_multiBodyA;
+ btMultiBody* multiBodyB = solverConstraint.m_multiBodyB;
+
+ btSolverBody* bodyA = multiBodyA ? 0 : &data.m_solverBodyPool->at(solverConstraint.m_solverBodyIdA);
+ btSolverBody* bodyB = multiBodyB ? 0 : &data.m_solverBodyPool->at(solverConstraint.m_solverBodyIdB);
+
+ btRigidBody* rb0 = multiBodyA ? 0 : bodyA->m_originalBody;
+ btRigidBody* rb1 = multiBodyB ? 0 : bodyB->m_originalBody;
+
+ btVector3 rel_pos1, rel_pos2; //these two used to be inited to posAworld and posBworld (respectively) but it does not seem necessary
+ if (bodyA)
+ rel_pos1 = posAworld - bodyA->getWorldTransform().getOrigin();
+ if (bodyB)
+ rel_pos2 = posBworld - bodyB->getWorldTransform().getOrigin();
+
+ if (multiBodyA)
+ {
+ if (solverConstraint.m_linkA<0)
+ {
+ rel_pos1 = posAworld - multiBodyA->getBasePos();
+ } else
+ {
+ rel_pos1 = posAworld - multiBodyA->getLink(solverConstraint.m_linkA).m_cachedWorldTransform.getOrigin();
+ }
+
+ const int ndofA = multiBodyA->getNumDofs() + 6;
+
+ solverConstraint.m_deltaVelAindex = multiBodyA->getCompanionId();
+
+ if (solverConstraint.m_deltaVelAindex <0)
+ {
+ solverConstraint.m_deltaVelAindex = data.m_deltaVelocities.size();
+ multiBodyA->setCompanionId(solverConstraint.m_deltaVelAindex);
+ data.m_deltaVelocities.resize(data.m_deltaVelocities.size()+ndofA);
+ } else
+ {
+ btAssert(data.m_deltaVelocities.size() >= solverConstraint.m_deltaVelAindex+ndofA);
+ }
+
+ //determine jacobian of this 1D constraint in terms of multibodyA's degrees of freedom
+ //resize..
+ solverConstraint.m_jacAindex = data.m_jacobians.size();
+ data.m_jacobians.resize(data.m_jacobians.size()+ndofA);
+ //copy/determine
+ if(jacOrgA)
+ {
+ for (int i=0;i<ndofA;i++)
+ data.m_jacobians[solverConstraint.m_jacAindex+i] = jacOrgA[i];
+ }
+ else
+ {
+ btScalar* jac1=&data.m_jacobians[solverConstraint.m_jacAindex];
+ //multiBodyA->fillContactJacobianMultiDof(solverConstraint.m_linkA, posAworld, constraintNormalLin, jac1, data.scratch_r, data.scratch_v, data.scratch_m);
+ multiBodyA->fillConstraintJacobianMultiDof(solverConstraint.m_linkA, posAworld, constraintNormalAng, constraintNormalLin, jac1, data.scratch_r, data.scratch_v, data.scratch_m);
+ }
+
+ //determine the velocity response of multibodyA to reaction impulses of this constraint (i.e. A[i,i] for i=1,...n_con: multibody's inverse inertia with respect to this 1D constraint)
+ //resize..
+ data.m_deltaVelocitiesUnitImpulse.resize(data.m_deltaVelocitiesUnitImpulse.size()+ndofA); //=> each constraint row has the constrained tree dofs allocated in m_deltaVelocitiesUnitImpulse
+ btAssert(data.m_jacobians.size() == data.m_deltaVelocitiesUnitImpulse.size());
+ btScalar* delta = &data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex];
+ //determine..
+ multiBodyA->calcAccelerationDeltasMultiDof(&data.m_jacobians[solverConstraint.m_jacAindex],delta,data.scratch_r, data.scratch_v);
+
+ btVector3 torqueAxis0;
+ if (angConstraint) {
+ torqueAxis0 = constraintNormalAng;
+ }
+ else {
+ torqueAxis0 = rel_pos1.cross(constraintNormalLin);
+
+ }
+ solverConstraint.m_relpos1CrossNormal = torqueAxis0;
+ solverConstraint.m_contactNormal1 = constraintNormalLin;
+ }
+ else //if(rb0)
+ {
+ btVector3 torqueAxis0;
+ if (angConstraint) {
+ torqueAxis0 = constraintNormalAng;
+ }
+ else {
+ torqueAxis0 = rel_pos1.cross(constraintNormalLin);
+ }
+ solverConstraint.m_angularComponentA = rb0 ? rb0->getInvInertiaTensorWorld()*torqueAxis0*rb0->getAngularFactor() : btVector3(0,0,0);
+ solverConstraint.m_relpos1CrossNormal = torqueAxis0;
+ solverConstraint.m_contactNormal1 = constraintNormalLin;
+ }
+
+ if (multiBodyB)
+ {
+ if (solverConstraint.m_linkB<0)
+ {
+ rel_pos2 = posBworld - multiBodyB->getBasePos();
+ } else
+ {
+ rel_pos2 = posBworld - multiBodyB->getLink(solverConstraint.m_linkB).m_cachedWorldTransform.getOrigin();
+ }
+
+ const int ndofB = multiBodyB->getNumDofs() + 6;
+
+ solverConstraint.m_deltaVelBindex = multiBodyB->getCompanionId();
+ if (solverConstraint.m_deltaVelBindex <0)
+ {
+ solverConstraint.m_deltaVelBindex = data.m_deltaVelocities.size();
+ multiBodyB->setCompanionId(solverConstraint.m_deltaVelBindex);
+ data.m_deltaVelocities.resize(data.m_deltaVelocities.size()+ndofB);
+ }
+
+ //determine jacobian of this 1D constraint in terms of multibodyB's degrees of freedom
+ //resize..
+ solverConstraint.m_jacBindex = data.m_jacobians.size();
+ data.m_jacobians.resize(data.m_jacobians.size()+ndofB);
+ //copy/determine..
+ if(jacOrgB)
+ {
+ for (int i=0;i<ndofB;i++)
+ data.m_jacobians[solverConstraint.m_jacBindex+i] = jacOrgB[i];
+ }
+ else
+ {
+ //multiBodyB->fillContactJacobianMultiDof(solverConstraint.m_linkB, posBworld, -constraintNormalLin, &data.m_jacobians[solverConstraint.m_jacBindex], data.scratch_r, data.scratch_v, data.scratch_m);
+ multiBodyB->fillConstraintJacobianMultiDof(solverConstraint.m_linkB, posBworld, -constraintNormalAng, -constraintNormalLin, &data.m_jacobians[solverConstraint.m_jacBindex], data.scratch_r, data.scratch_v, data.scratch_m);
+ }
+
+ //determine velocity response of multibodyB to reaction impulses of this constraint (i.e. A[i,i] for i=1,...n_con: multibody's inverse inertia with respect to this 1D constraint)
+ //resize..
+ data.m_deltaVelocitiesUnitImpulse.resize(data.m_deltaVelocitiesUnitImpulse.size()+ndofB);
+ btAssert(data.m_jacobians.size() == data.m_deltaVelocitiesUnitImpulse.size());
+ btScalar* delta = &data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex];
+ //determine..
+ multiBodyB->calcAccelerationDeltasMultiDof(&data.m_jacobians[solverConstraint.m_jacBindex],delta,data.scratch_r, data.scratch_v);
+
+ btVector3 torqueAxis1;
+ if (angConstraint) {
+ torqueAxis1 = constraintNormalAng;
+ }
+ else {
+ torqueAxis1 = rel_pos2.cross(constraintNormalLin);
+ }
+ solverConstraint.m_relpos2CrossNormal = -torqueAxis1;
+ solverConstraint.m_contactNormal2 = -constraintNormalLin;
+ }
+ else //if(rb1)
+ {
+ btVector3 torqueAxis1;
+ if (angConstraint) {
+ torqueAxis1 = constraintNormalAng;
+ }
+ else {
+ torqueAxis1 = rel_pos2.cross(constraintNormalLin);
+ }
+ solverConstraint.m_angularComponentB = rb1 ? rb1->getInvInertiaTensorWorld()*-torqueAxis1*rb1->getAngularFactor() : btVector3(0,0,0);
+ solverConstraint.m_relpos2CrossNormal = -torqueAxis1;
+ solverConstraint.m_contactNormal2 = -constraintNormalLin;
+ }
+ {
+
+ btVector3 vec;
+ btScalar denom0 = 0.f;
+ btScalar denom1 = 0.f;
+ btScalar* jacB = 0;
+ btScalar* jacA = 0;
+ btScalar* deltaVelA = 0;
+ btScalar* deltaVelB = 0;
+ int ndofA = 0;
+ //determine the "effective mass" of the constrained multibodyA with respect to this 1D constraint (i.e. 1/A[i,i])
+ if (multiBodyA)
+ {
+ ndofA = multiBodyA->getNumDofs() + 6;
+ jacA = &data.m_jacobians[solverConstraint.m_jacAindex];
+ deltaVelA = &data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex];
+ for (int i = 0; i < ndofA; ++i)
+ {
+ btScalar j = jacA[i] ;
+ btScalar l = deltaVelA[i];
+ denom0 += j*l;
+ }
+ }
+ else if(rb0)
+ {
+ vec = ( solverConstraint.m_angularComponentA).cross(rel_pos1);
+ if (angConstraint) {
+ denom0 = rb0->getInvMass() + constraintNormalAng.dot(vec);
+ }
+ else {
+ denom0 = rb0->getInvMass() + constraintNormalLin.dot(vec);
+ }
+ }
+ //
+ if (multiBodyB)
+ {
+ const int ndofB = multiBodyB->getNumDofs() + 6;
+ jacB = &data.m_jacobians[solverConstraint.m_jacBindex];
+ deltaVelB = &data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex];
+ for (int i = 0; i < ndofB; ++i)
+ {
+ btScalar j = jacB[i] ;
+ btScalar l = deltaVelB[i];
+ denom1 += j*l;
+ }
+
+ }
+ else if(rb1)
+ {
+ vec = ( -solverConstraint.m_angularComponentB).cross(rel_pos2);
+ if (angConstraint) {
+ denom1 = rb1->getInvMass() + constraintNormalAng.dot(vec);
+ }
+ else {
+ denom1 = rb1->getInvMass() + constraintNormalLin.dot(vec);
+ }
+ }
+
+ //
+ btScalar d = denom0+denom1;
+ if (d>SIMD_EPSILON)
+ {
+ solverConstraint.m_jacDiagABInv = relaxation/(d);
+ }
+ else
+ {
+ //disable the constraint row to handle singularity/redundant constraint
+ solverConstraint.m_jacDiagABInv = 0.f;
+ }
+ }
+
+
+ //compute rhs and remaining solverConstraint fields
+ btScalar penetration = isFriction? 0 : posError;
+
+ btScalar rel_vel = 0.f;
+ int ndofA = 0;
+ int ndofB = 0;
+ {
+ btVector3 vel1,vel2;
+ if (multiBodyA)
+ {
+ ndofA = multiBodyA->getNumDofs() + 6;
+ btScalar* jacA = &data.m_jacobians[solverConstraint.m_jacAindex];
+ for (int i = 0; i < ndofA ; ++i)
+ rel_vel += multiBodyA->getVelocityVector()[i] * jacA[i];
+ }
+ else if(rb0)
+ {
+ rel_vel += rb0->getVelocityInLocalPoint(rel_pos1).dot(solverConstraint.m_contactNormal1);
+ }
+ if (multiBodyB)
+ {
+ ndofB = multiBodyB->getNumDofs() + 6;
+ btScalar* jacB = &data.m_jacobians[solverConstraint.m_jacBindex];
+ for (int i = 0; i < ndofB ; ++i)
+ rel_vel += multiBodyB->getVelocityVector()[i] * jacB[i];
+
+ }
+ else if(rb1)
+ {
+ rel_vel += rb1->getVelocityInLocalPoint(rel_pos2).dot(solverConstraint.m_contactNormal2);
+ }
+
+ 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;
+
+ {
+
+ btScalar positionalError = 0.f;
+ btScalar velocityError = desiredVelocity - rel_vel;// * damping;
+
+
+ btScalar erp = infoGlobal.m_erp2;
+
+ //split impulse is not implemented yet for btMultiBody*
+ //if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold))
+ {
+ erp = infoGlobal.m_erp;
+ }
+
+ positionalError = -penetration * erp/infoGlobal.m_timeStep;
+
+ btScalar penetrationImpulse = positionalError*solverConstraint.m_jacDiagABInv;
+ btScalar velocityImpulse = velocityError *solverConstraint.m_jacDiagABInv;
+
+ //split impulse is not implemented yet for btMultiBody*
+
+ // if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold))
+ {
+ //combine position and velocity into rhs
+ solverConstraint.m_rhs = penetrationImpulse+velocityImpulse;
+ solverConstraint.m_rhsPenetration = 0.f;
+
+ }
+ /*else
+ {
+ //split position and velocity into rhs and m_rhsPenetration
+ solverConstraint.m_rhs = velocityImpulse;
+ solverConstraint.m_rhsPenetration = penetrationImpulse;
+ }
+ */
+
+ solverConstraint.m_cfm = 0.f;
+ solverConstraint.m_lowerLimit = lowerLimit;
+ solverConstraint.m_upperLimit = upperLimit;
+ }
+
+ return rel_vel;
+
+}
diff --git a/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyConstraint.h b/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyConstraint.h
new file mode 100644
index 0000000000..83521b9501
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyConstraint.h
@@ -0,0 +1,195 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2013 Erwin Coumans 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_CONSTRAINT_H
+#define BT_MULTIBODY_CONSTRAINT_H
+
+#include "LinearMath/btScalar.h"
+#include "LinearMath/btAlignedObjectArray.h"
+#include "btMultiBody.h"
+
+class btMultiBody;
+struct btSolverInfo;
+
+#include "btMultiBodySolverConstraint.h"
+
+struct btMultiBodyJacobianData
+{
+ btAlignedObjectArray<btScalar> m_jacobians;
+ btAlignedObjectArray<btScalar> m_deltaVelocitiesUnitImpulse; //holds the joint-space response of the corresp. tree to the test impulse in each constraint space dimension
+ btAlignedObjectArray<btScalar> m_deltaVelocities; //holds joint-space vectors of all the constrained trees accumulating the effect of corrective impulses applied in SI
+ btAlignedObjectArray<btScalar> scratch_r;
+ btAlignedObjectArray<btVector3> scratch_v;
+ btAlignedObjectArray<btMatrix3x3> scratch_m;
+ btAlignedObjectArray<btSolverBody>* m_solverBodyPool;
+ int m_fixedBodyId;
+
+};
+
+
+ATTRIBUTE_ALIGNED16(class) btMultiBodyConstraint
+{
+protected:
+
+ btMultiBody* m_bodyA;
+ btMultiBody* m_bodyB;
+ int m_linkA;
+ int m_linkB;
+
+ int m_numRows;
+ int m_jacSizeA;
+ int m_jacSizeBoth;
+ int m_posOffset;
+
+ bool m_isUnilateral;
+ int m_numDofsFinalized;
+ btScalar m_maxAppliedImpulse;
+
+
+ // warning: the data block lay out is not consistent for all constraints
+ // data block laid out as follows:
+ // cached impulses. (one per row.)
+ // jacobians. (interleaved, row1 body1 then row1 body2 then row2 body 1 etc)
+ // positions. (one per row.)
+ btAlignedObjectArray<btScalar> m_data;
+
+ void applyDeltaVee(btMultiBodyJacobianData& data, btScalar* delta_vee, btScalar impulse, int velocityIndex, int ndof);
+
+ btScalar fillMultiBodyConstraint(btMultiBodySolverConstraint& solverConstraint,
+ btMultiBodyJacobianData& data,
+ btScalar* jacOrgA, btScalar* jacOrgB,
+ const btVector3& constraintNormalAng,
+
+ const btVector3& constraintNormalLin,
+ const btVector3& posAworld, const btVector3& posBworld,
+ btScalar posError,
+ const btContactSolverInfo& infoGlobal,
+ btScalar lowerLimit, btScalar upperLimit,
+ bool angConstraint = false,
+
+ btScalar relaxation = 1.f,
+ bool isFriction = false, btScalar desiredVelocity=0, btScalar cfmSlip=0);
+
+public:
+
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ btMultiBodyConstraint(btMultiBody* bodyA,btMultiBody* bodyB,int linkA, int linkB, int numRows, bool isUnilateral);
+ virtual ~btMultiBodyConstraint();
+
+ void updateJacobianSizes();
+ void allocateJacobiansMultiDof();
+
+ //many constraints have setFrameInB/setPivotInB. Will use 'getConstraintType' later.
+ virtual void setFrameInB(const btMatrix3x3& frameInB) {}
+ virtual void setPivotInB(const btVector3& pivotInB){}
+
+ virtual void finalizeMultiDof()=0;
+
+ virtual int getIslandIdA() const =0;
+ virtual int getIslandIdB() const =0;
+
+ virtual void createConstraintRows(btMultiBodyConstraintArray& constraintRows,
+ btMultiBodyJacobianData& data,
+ const btContactSolverInfo& infoGlobal)=0;
+
+ int getNumRows() const
+ {
+ return m_numRows;
+ }
+
+ btMultiBody* getMultiBodyA()
+ {
+ return m_bodyA;
+ }
+ btMultiBody* getMultiBodyB()
+ {
+ return m_bodyB;
+ }
+
+ void internalSetAppliedImpulse(int dof, btScalar appliedImpulse)
+ {
+ btAssert(dof>=0);
+ btAssert(dof < getNumRows());
+ m_data[dof] = appliedImpulse;
+
+ }
+
+ btScalar getAppliedImpulse(int dof)
+ {
+ btAssert(dof>=0);
+ btAssert(dof < getNumRows());
+ return m_data[dof];
+ }
+ // current constraint position
+ // constraint is pos >= 0 for unilateral, or pos = 0 for bilateral
+ // NOTE: ignored position for friction rows.
+ btScalar getPosition(int row) const
+ {
+ return m_data[m_posOffset + row];
+ }
+
+ void setPosition(int row, btScalar pos)
+ {
+ m_data[m_posOffset + row] = pos;
+ }
+
+
+ bool isUnilateral() const
+ {
+ return m_isUnilateral;
+ }
+
+ // jacobian blocks.
+ // each of size 6 + num_links. (jacobian2 is null if no body2.)
+ // format: 3 'omega' coefficients, 3 'v' coefficients, then the 'qdot' coefficients.
+ btScalar* jacobianA(int row)
+ {
+ return &m_data[m_numRows + row * m_jacSizeBoth];
+ }
+ const btScalar* jacobianA(int row) const
+ {
+ return &m_data[m_numRows + (row * m_jacSizeBoth)];
+ }
+ btScalar* jacobianB(int row)
+ {
+ return &m_data[m_numRows + (row * m_jacSizeBoth) + m_jacSizeA];
+ }
+ const btScalar* jacobianB(int row) const
+ {
+ return &m_data[m_numRows + (row * m_jacSizeBoth) + m_jacSizeA];
+ }
+
+ btScalar getMaxAppliedImpulse() const
+ {
+ return m_maxAppliedImpulse;
+ }
+ void setMaxAppliedImpulse(btScalar maxImp)
+ {
+ m_maxAppliedImpulse = maxImp;
+ }
+
+ virtual void debugDraw(class btIDebugDraw* drawer)=0;
+
+ virtual void setGearRatio(btScalar ratio) {}
+ virtual void setGearAuxLink(int gearAuxLink) {}
+ virtual void setRelativePositionTarget(btScalar relPosTarget){}
+ virtual void setErp(btScalar erp){}
+
+
+};
+
+#endif //BT_MULTIBODY_CONSTRAINT_H
+
diff --git a/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp b/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp
new file mode 100644
index 0000000000..1e2d074096
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp
@@ -0,0 +1,1429 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2013 Erwin Coumans 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 "btMultiBodyConstraintSolver.h"
+#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
+#include "btMultiBodyLinkCollider.h"
+
+#include "BulletDynamics/ConstraintSolver/btSolverBody.h"
+#include "btMultiBodyConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h"
+
+#include "LinearMath/btQuickprof.h"
+
+btScalar btMultiBodyConstraintSolver::solveSingleIteration(int iteration, btCollisionObject** bodies ,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer)
+{
+ btScalar leastSquaredResidual = btSequentialImpulseConstraintSolver::solveSingleIteration(iteration, bodies ,numBodies,manifoldPtr, numManifolds,constraints,numConstraints,infoGlobal,debugDrawer);
+
+ //solve featherstone non-contact constraints
+
+ //printf("m_multiBodyNonContactConstraints = %d\n",m_multiBodyNonContactConstraints.size());
+
+ for (int j=0;j<m_multiBodyNonContactConstraints.size();j++)
+ {
+ int index = iteration&1? j : m_multiBodyNonContactConstraints.size()-1-j;
+
+ btMultiBodySolverConstraint& constraint = m_multiBodyNonContactConstraints[index];
+
+ btScalar residual = resolveSingleConstraintRowGeneric(constraint);
+ leastSquaredResidual += residual*residual;
+
+ if(constraint.m_multiBodyA)
+ constraint.m_multiBodyA->setPosUpdated(false);
+ if(constraint.m_multiBodyB)
+ constraint.m_multiBodyB->setPosUpdated(false);
+ }
+
+ //solve featherstone normal contact
+ for (int j0=0;j0<m_multiBodyNormalContactConstraints.size();j0++)
+ {
+ int index = j0;//iteration&1? j0 : m_multiBodyNormalContactConstraints.size()-1-j0;
+
+ btMultiBodySolverConstraint& constraint = m_multiBodyNormalContactConstraints[index];
+ btScalar residual = 0.f;
+
+ if (iteration < infoGlobal.m_numIterations)
+ {
+ residual = resolveSingleConstraintRowGeneric(constraint);
+ }
+
+ leastSquaredResidual += residual*residual;
+
+ if(constraint.m_multiBodyA)
+ constraint.m_multiBodyA->setPosUpdated(false);
+ if(constraint.m_multiBodyB)
+ constraint.m_multiBodyB->setPosUpdated(false);
+ }
+
+ //solve featherstone frictional contact
+
+ for (int j1=0;j1<this->m_multiBodyFrictionContactConstraints.size();j1++)
+ {
+ if (iteration < infoGlobal.m_numIterations)
+ {
+ int index = j1;//iteration&1? j1 : m_multiBodyFrictionContactConstraints.size()-1-j1;
+
+ btMultiBodySolverConstraint& frictionConstraint = m_multiBodyFrictionContactConstraints[index];
+ btScalar totalImpulse = m_multiBodyNormalContactConstraints[frictionConstraint.m_frictionIndex].m_appliedImpulse;
+ //adjust friction limits here
+ if (totalImpulse>btScalar(0))
+ {
+ frictionConstraint.m_lowerLimit = -(frictionConstraint.m_friction*totalImpulse);
+ frictionConstraint.m_upperLimit = frictionConstraint.m_friction*totalImpulse;
+ btScalar residual = resolveSingleConstraintRowGeneric(frictionConstraint);
+ leastSquaredResidual += residual*residual;
+
+ if(frictionConstraint.m_multiBodyA)
+ frictionConstraint.m_multiBodyA->setPosUpdated(false);
+ if(frictionConstraint.m_multiBodyB)
+ frictionConstraint.m_multiBodyB->setPosUpdated(false);
+ }
+ }
+ }
+ return leastSquaredResidual;
+}
+
+btScalar btMultiBodyConstraintSolver::solveGroupCacheFriendlySetup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer)
+{
+ m_multiBodyNonContactConstraints.resize(0);
+ m_multiBodyNormalContactConstraints.resize(0);
+ m_multiBodyFrictionContactConstraints.resize(0);
+ m_data.m_jacobians.resize(0);
+ m_data.m_deltaVelocitiesUnitImpulse.resize(0);
+ m_data.m_deltaVelocities.resize(0);
+
+ for (int i=0;i<numBodies;i++)
+ {
+ const btMultiBodyLinkCollider* fcA = btMultiBodyLinkCollider::upcast(bodies[i]);
+ if (fcA)
+ {
+ fcA->m_multiBody->setCompanionId(-1);
+ }
+ }
+
+ btScalar val = btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup( bodies,numBodies,manifoldPtr, numManifolds, constraints,numConstraints,infoGlobal,debugDrawer);
+
+ return val;
+}
+
+void btMultiBodyConstraintSolver::applyDeltaVee(btScalar* delta_vee, btScalar impulse, int velocityIndex, int ndof)
+{
+ for (int i = 0; i < ndof; ++i)
+ m_data.m_deltaVelocities[velocityIndex+i] += delta_vee[i] * impulse;
+}
+
+btScalar btMultiBodyConstraintSolver::resolveSingleConstraintRowGeneric(const btMultiBodySolverConstraint& c)
+{
+
+ btScalar deltaImpulse = c.m_rhs-btScalar(c.m_appliedImpulse)*c.m_cfm;
+ btScalar deltaVelADotn=0;
+ btScalar deltaVelBDotn=0;
+ btSolverBody* bodyA = 0;
+ btSolverBody* bodyB = 0;
+ int ndofA=0;
+ int ndofB=0;
+
+ if (c.m_multiBodyA)
+ {
+ ndofA = c.m_multiBodyA->getNumDofs() + 6;
+ for (int i = 0; i < ndofA; ++i)
+ deltaVelADotn += m_data.m_jacobians[c.m_jacAindex+i] * m_data.m_deltaVelocities[c.m_deltaVelAindex+i];
+ } else if(c.m_solverBodyIdA >= 0)
+ {
+ bodyA = &m_tmpSolverBodyPool[c.m_solverBodyIdA];
+ deltaVelADotn += c.m_contactNormal1.dot(bodyA->internalGetDeltaLinearVelocity()) + c.m_relpos1CrossNormal.dot(bodyA->internalGetDeltaAngularVelocity());
+ }
+
+ if (c.m_multiBodyB)
+ {
+ ndofB = c.m_multiBodyB->getNumDofs() + 6;
+ for (int i = 0; i < ndofB; ++i)
+ deltaVelBDotn += m_data.m_jacobians[c.m_jacBindex+i] * m_data.m_deltaVelocities[c.m_deltaVelBindex+i];
+ } else if(c.m_solverBodyIdB >= 0)
+ {
+ bodyB = &m_tmpSolverBodyPool[c.m_solverBodyIdB];
+ deltaVelBDotn += c.m_contactNormal2.dot(bodyB->internalGetDeltaLinearVelocity()) + c.m_relpos2CrossNormal.dot(bodyB->internalGetDeltaAngularVelocity());
+ }
+
+
+ deltaImpulse -= deltaVelADotn*c.m_jacDiagABInv;//m_jacDiagABInv = 1./denom
+ deltaImpulse -= deltaVelBDotn*c.m_jacDiagABInv;
+ const btScalar sum = btScalar(c.m_appliedImpulse) + deltaImpulse;
+
+ if (sum < c.m_lowerLimit)
+ {
+ deltaImpulse = c.m_lowerLimit-c.m_appliedImpulse;
+ c.m_appliedImpulse = c.m_lowerLimit;
+ }
+ else if (sum > c.m_upperLimit)
+ {
+ deltaImpulse = c.m_upperLimit-c.m_appliedImpulse;
+ c.m_appliedImpulse = c.m_upperLimit;
+ }
+ else
+ {
+ c.m_appliedImpulse = sum;
+ }
+
+ if (c.m_multiBodyA)
+ {
+ applyDeltaVee(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacAindex],deltaImpulse,c.m_deltaVelAindex,ndofA);
+#ifdef DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
+ //note: update of the actual velocities (below) in the multibody does not have to happen now since m_deltaVelocities can be applied after all iterations
+ //it would make the multibody solver more like the regular one with m_deltaVelocities being equivalent to btSolverBody::m_deltaLinearVelocity/m_deltaAngularVelocity
+ c.m_multiBodyA->applyDeltaVeeMultiDof2(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacAindex],deltaImpulse);
+#endif //DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
+ } else if(c.m_solverBodyIdA >= 0)
+ {
+ bodyA->internalApplyImpulse(c.m_contactNormal1*bodyA->internalGetInvMass(),c.m_angularComponentA,deltaImpulse);
+
+ }
+ if (c.m_multiBodyB)
+ {
+ applyDeltaVee(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacBindex],deltaImpulse,c.m_deltaVelBindex,ndofB);
+#ifdef DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
+ //note: update of the actual velocities (below) in the multibody does not have to happen now since m_deltaVelocities can be applied after all iterations
+ //it would make the multibody solver more like the regular one with m_deltaVelocities being equivalent to btSolverBody::m_deltaLinearVelocity/m_deltaAngularVelocity
+ c.m_multiBodyB->applyDeltaVeeMultiDof2(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacBindex],deltaImpulse);
+#endif //DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
+ } else if(c.m_solverBodyIdB >= 0)
+ {
+ bodyB->internalApplyImpulse(c.m_contactNormal2*bodyB->internalGetInvMass(),c.m_angularComponentB,deltaImpulse);
+ }
+ return deltaImpulse;
+}
+
+
+
+
+void btMultiBodyConstraintSolver::setupMultiBodyContactConstraint(btMultiBodySolverConstraint& solverConstraint,
+ const btVector3& contactNormal,
+ btManifoldPoint& cp, const btContactSolverInfo& infoGlobal,
+ btScalar& relaxation,
+ bool isFriction, btScalar desiredVelocity, btScalar cfmSlip)
+{
+
+ BT_PROFILE("setupMultiBodyContactConstraint");
+ btVector3 rel_pos1;
+ btVector3 rel_pos2;
+
+ btMultiBody* multiBodyA = solverConstraint.m_multiBodyA;
+ btMultiBody* multiBodyB = solverConstraint.m_multiBodyB;
+
+ const btVector3& pos1 = cp.getPositionWorldOnA();
+ const btVector3& pos2 = cp.getPositionWorldOnB();
+
+ btSolverBody* bodyA = multiBodyA ? 0 : &m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdA];
+ btSolverBody* bodyB = multiBodyB ? 0 : &m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdB];
+
+ btRigidBody* rb0 = multiBodyA ? 0 : bodyA->m_originalBody;
+ btRigidBody* rb1 = multiBodyB ? 0 : bodyB->m_originalBody;
+
+ if (bodyA)
+ rel_pos1 = pos1 - bodyA->getWorldTransform().getOrigin();
+ if (bodyB)
+ rel_pos2 = pos2 - bodyB->getWorldTransform().getOrigin();
+
+ relaxation = infoGlobal.m_sor;
+
+ btScalar invTimeStep = btScalar(1)/infoGlobal.m_timeStep;
+
+ //cfm = 1 / ( dt * kp + kd )
+ //erp = dt * kp / ( dt * kp + kd )
+
+ btScalar cfm;
+ btScalar erp;
+ if (isFriction)
+ {
+ cfm = infoGlobal.m_frictionCFM;
+ erp = infoGlobal.m_frictionERP;
+ } else
+ {
+ cfm = infoGlobal.m_globalCfm;
+ erp = infoGlobal.m_erp2;
+
+ if ((cp.m_contactPointFlags&BT_CONTACT_FLAG_HAS_CONTACT_CFM) || (cp.m_contactPointFlags&BT_CONTACT_FLAG_HAS_CONTACT_ERP))
+ {
+ if (cp.m_contactPointFlags&BT_CONTACT_FLAG_HAS_CONTACT_CFM)
+ cfm = cp.m_contactCFM;
+ if (cp.m_contactPointFlags&BT_CONTACT_FLAG_HAS_CONTACT_ERP)
+ erp = cp.m_contactERP;
+ } else
+ {
+ if (cp.m_contactPointFlags & BT_CONTACT_FLAG_CONTACT_STIFFNESS_DAMPING)
+ {
+ btScalar denom = ( infoGlobal.m_timeStep * cp.m_combinedContactStiffness1 + cp.m_combinedContactDamping1 );
+ if (denom < SIMD_EPSILON)
+ {
+ denom = SIMD_EPSILON;
+ }
+ cfm = btScalar(1) / denom;
+ erp = (infoGlobal.m_timeStep * cp.m_combinedContactStiffness1) / denom;
+ }
+ }
+ }
+
+ cfm *= invTimeStep;
+
+ if (multiBodyA)
+ {
+ if (solverConstraint.m_linkA<0)
+ {
+ rel_pos1 = pos1 - multiBodyA->getBasePos();
+ } else
+ {
+ rel_pos1 = pos1 - multiBodyA->getLink(solverConstraint.m_linkA).m_cachedWorldTransform.getOrigin();
+ }
+ const int ndofA = multiBodyA->getNumDofs() + 6;
+
+ solverConstraint.m_deltaVelAindex = multiBodyA->getCompanionId();
+
+ if (solverConstraint.m_deltaVelAindex <0)
+ {
+ solverConstraint.m_deltaVelAindex = m_data.m_deltaVelocities.size();
+ multiBodyA->setCompanionId(solverConstraint.m_deltaVelAindex);
+ m_data.m_deltaVelocities.resize(m_data.m_deltaVelocities.size()+ndofA);
+ } else
+ {
+ btAssert(m_data.m_deltaVelocities.size() >= solverConstraint.m_deltaVelAindex+ndofA);
+ }
+
+ solverConstraint.m_jacAindex = m_data.m_jacobians.size();
+ m_data.m_jacobians.resize(m_data.m_jacobians.size()+ndofA);
+ m_data.m_deltaVelocitiesUnitImpulse.resize(m_data.m_deltaVelocitiesUnitImpulse.size()+ndofA);
+ btAssert(m_data.m_jacobians.size() == m_data.m_deltaVelocitiesUnitImpulse.size());
+
+ btScalar* jac1=&m_data.m_jacobians[solverConstraint.m_jacAindex];
+ multiBodyA->fillContactJacobianMultiDof(solverConstraint.m_linkA, cp.getPositionWorldOnA(), contactNormal, jac1, m_data.scratch_r, m_data.scratch_v, m_data.scratch_m);
+ 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 = rel_pos1.cross(contactNormal);
+ solverConstraint.m_relpos1CrossNormal = torqueAxis0;
+ solverConstraint.m_contactNormal1 = contactNormal;
+ } else
+ {
+ btVector3 torqueAxis0 = rel_pos1.cross(contactNormal);
+ solverConstraint.m_relpos1CrossNormal = torqueAxis0;
+ solverConstraint.m_contactNormal1 = contactNormal;
+ solverConstraint.m_angularComponentA = rb0 ? rb0->getInvInertiaTensorWorld()*torqueAxis0*rb0->getAngularFactor() : btVector3(0,0,0);
+ }
+
+
+
+ if (multiBodyB)
+ {
+ if (solverConstraint.m_linkB<0)
+ {
+ rel_pos2 = pos2 - multiBodyB->getBasePos();
+ } else
+ {
+ rel_pos2 = pos2 - multiBodyB->getLink(solverConstraint.m_linkB).m_cachedWorldTransform.getOrigin();
+ }
+
+ const int ndofB = multiBodyB->getNumDofs() + 6;
+
+ solverConstraint.m_deltaVelBindex = multiBodyB->getCompanionId();
+ if (solverConstraint.m_deltaVelBindex <0)
+ {
+ solverConstraint.m_deltaVelBindex = m_data.m_deltaVelocities.size();
+ multiBodyB->setCompanionId(solverConstraint.m_deltaVelBindex);
+ m_data.m_deltaVelocities.resize(m_data.m_deltaVelocities.size()+ndofB);
+ }
+
+ solverConstraint.m_jacBindex = m_data.m_jacobians.size();
+
+ m_data.m_jacobians.resize(m_data.m_jacobians.size()+ndofB);
+ m_data.m_deltaVelocitiesUnitImpulse.resize(m_data.m_deltaVelocitiesUnitImpulse.size()+ndofB);
+ btAssert(m_data.m_jacobians.size() == m_data.m_deltaVelocitiesUnitImpulse.size());
+
+ multiBodyB->fillContactJacobianMultiDof(solverConstraint.m_linkB, cp.getPositionWorldOnB(), -contactNormal, &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 = rel_pos2.cross(contactNormal);
+ solverConstraint.m_relpos2CrossNormal = -torqueAxis1;
+ solverConstraint.m_contactNormal2 = -contactNormal;
+
+ } else
+ {
+ btVector3 torqueAxis1 = rel_pos2.cross(contactNormal);
+ solverConstraint.m_relpos2CrossNormal = -torqueAxis1;
+ solverConstraint.m_contactNormal2 = -contactNormal;
+
+ solverConstraint.m_angularComponentB = rb1 ? rb1->getInvInertiaTensorWorld()*-torqueAxis1*rb1->getAngularFactor() : btVector3(0,0,0);
+ }
+
+ {
+
+ btVector3 vec;
+ btScalar denom0 = 0.f;
+ btScalar denom1 = 0.f;
+ btScalar* jacB = 0;
+ btScalar* jacA = 0;
+ btScalar* lambdaA =0;
+ btScalar* lambdaB =0;
+ int ndofA = 0;
+ if (multiBodyA)
+ {
+ ndofA = multiBodyA->getNumDofs() + 6;
+ jacA = &m_data.m_jacobians[solverConstraint.m_jacAindex];
+ lambdaA = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex];
+ for (int i = 0; i < ndofA; ++i)
+ {
+ btScalar j = jacA[i] ;
+ btScalar l =lambdaA[i];
+ denom0 += j*l;
+ }
+ } else
+ {
+ if (rb0)
+ {
+ vec = ( solverConstraint.m_angularComponentA).cross(rel_pos1);
+ denom0 = rb0->getInvMass() + contactNormal.dot(vec);
+ }
+ }
+ if (multiBodyB)
+ {
+ const int ndofB = multiBodyB->getNumDofs() + 6;
+ jacB = &m_data.m_jacobians[solverConstraint.m_jacBindex];
+ lambdaB = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex];
+ for (int i = 0; i < ndofB; ++i)
+ {
+ btScalar j = jacB[i] ;
+ btScalar l =lambdaB[i];
+ denom1 += j*l;
+ }
+
+ } else
+ {
+ if (rb1)
+ {
+ vec = ( -solverConstraint.m_angularComponentB).cross(rel_pos2);
+ denom1 = rb1->getInvMass() + contactNormal.dot(vec);
+ }
+ }
+
+
+
+ btScalar d = denom0+denom1+cfm;
+ if (d>SIMD_EPSILON)
+ {
+ solverConstraint.m_jacDiagABInv = relaxation/(d);
+ } else
+ {
+ //disable the constraint row to handle singularity/redundant constraint
+ solverConstraint.m_jacDiagABInv = 0.f;
+ }
+
+ }
+
+
+ //compute rhs and remaining solverConstraint fields
+
+
+
+ btScalar restitution = 0.f;
+ btScalar distance = 0;
+ if (!isFriction)
+ {
+ distance = cp.getDistance()+infoGlobal.m_linearSlop;
+ } else
+ {
+ if (cp.m_contactPointFlags & BT_CONTACT_FLAG_FRICTION_ANCHOR)
+ {
+ distance = (cp.getPositionWorldOnA() - cp.getPositionWorldOnB()).dot(contactNormal);
+ }
+ }
+
+
+ btScalar rel_vel = 0.f;
+ int ndofA = 0;
+ int ndofB = 0;
+ {
+
+ btVector3 vel1,vel2;
+ if (multiBodyA)
+ {
+ ndofA = multiBodyA->getNumDofs() + 6;
+ btScalar* jacA = &m_data.m_jacobians[solverConstraint.m_jacAindex];
+ for (int i = 0; i < ndofA ; ++i)
+ rel_vel += multiBodyA->getVelocityVector()[i] * jacA[i];
+ } else
+ {
+ if (rb0)
+ {
+ rel_vel += (rb0->getVelocityInLocalPoint(rel_pos1) +
+ (rb0->getTotalTorque()*rb0->getInvInertiaTensorWorld()*infoGlobal.m_timeStep).cross(rel_pos1)+
+ rb0->getTotalForce()*rb0->getInvMass()*infoGlobal.m_timeStep).dot(solverConstraint.m_contactNormal1);
+ }
+ }
+ if (multiBodyB)
+ {
+ ndofB = multiBodyB->getNumDofs() + 6;
+ btScalar* jacB = &m_data.m_jacobians[solverConstraint.m_jacBindex];
+ for (int i = 0; i < ndofB ; ++i)
+ rel_vel += multiBodyB->getVelocityVector()[i] * jacB[i];
+
+ } else
+ {
+ if (rb1)
+ {
+ rel_vel += (rb1->getVelocityInLocalPoint(rel_pos2)+
+ (rb1->getTotalTorque()*rb1->getInvInertiaTensorWorld()*infoGlobal.m_timeStep).cross(rel_pos2) +
+ rb1->getTotalForce()*rb1->getInvMass()*infoGlobal.m_timeStep).dot(solverConstraint.m_contactNormal2);
+ }
+ }
+
+ solverConstraint.m_friction = cp.m_combinedFriction;
+
+ if(!isFriction)
+ {
+ restitution = restitutionCurve(rel_vel, cp.m_combinedRestitution, infoGlobal.m_restitutionVelocityThreshold);
+ if (restitution <= btScalar(0.))
+ {
+ restitution = 0.f;
+ }
+ }
+ }
+
+
+ ///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
+ if (isFriction)
+ {
+ positionalError = -distance * erp/infoGlobal.m_timeStep;
+ } else
+ {
+ if (distance>0)
+ {
+ positionalError = 0;
+ velocityError -= distance / infoGlobal.m_timeStep;
+
+ } else
+ {
+ positionalError = -distance * erp/infoGlobal.m_timeStep;
+ }
+ }
+
+ btScalar penetrationImpulse = positionalError*solverConstraint.m_jacDiagABInv;
+ btScalar velocityImpulse = velocityError *solverConstraint.m_jacDiagABInv;
+
+ if(!isFriction)
+ {
+ // if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold))
+ {
+ //combine position and velocity into rhs
+ solverConstraint.m_rhs = penetrationImpulse+velocityImpulse;
+ solverConstraint.m_rhsPenetration = 0.f;
+
+ }
+ /*else
+ {
+ //split position and velocity into rhs and m_rhsPenetration
+ solverConstraint.m_rhs = velocityImpulse;
+ solverConstraint.m_rhsPenetration = penetrationImpulse;
+ }
+ */
+ solverConstraint.m_lowerLimit = 0;
+ solverConstraint.m_upperLimit = 1e10f;
+ }
+ else
+ {
+ solverConstraint.m_rhs = penetrationImpulse+velocityImpulse;
+ solverConstraint.m_rhsPenetration = 0.f;
+ solverConstraint.m_lowerLimit = -solverConstraint.m_friction;
+ solverConstraint.m_upperLimit = solverConstraint.m_friction;
+ }
+
+ solverConstraint.m_cfm = cfm*solverConstraint.m_jacDiagABInv;
+
+
+
+ }
+
+}
+
+void btMultiBodyConstraintSolver::setupMultiBodyTorsionalFrictionConstraint(btMultiBodySolverConstraint& solverConstraint,
+ const btVector3& constraintNormal,
+ btManifoldPoint& cp,
+ btScalar combinedTorsionalFriction,
+ const btContactSolverInfo& infoGlobal,
+ btScalar& relaxation,
+ bool isFriction, btScalar desiredVelocity, btScalar cfmSlip)
+{
+
+ BT_PROFILE("setupMultiBodyRollingFrictionConstraint");
+ btVector3 rel_pos1;
+ btVector3 rel_pos2;
+
+ btMultiBody* multiBodyA = solverConstraint.m_multiBodyA;
+ btMultiBody* multiBodyB = solverConstraint.m_multiBodyB;
+
+ const btVector3& pos1 = cp.getPositionWorldOnA();
+ const btVector3& pos2 = cp.getPositionWorldOnB();
+
+ btSolverBody* bodyA = multiBodyA ? 0 : &m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdA];
+ btSolverBody* bodyB = multiBodyB ? 0 : &m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdB];
+
+ btRigidBody* rb0 = multiBodyA ? 0 : bodyA->m_originalBody;
+ btRigidBody* rb1 = multiBodyB ? 0 : bodyB->m_originalBody;
+
+ if (bodyA)
+ rel_pos1 = pos1 - bodyA->getWorldTransform().getOrigin();
+ if (bodyB)
+ rel_pos2 = pos2 - bodyB->getWorldTransform().getOrigin();
+
+ relaxation = infoGlobal.m_sor;
+
+ // btScalar invTimeStep = btScalar(1)/infoGlobal.m_timeStep;
+
+
+ if (multiBodyA)
+ {
+ if (solverConstraint.m_linkA<0)
+ {
+ rel_pos1 = pos1 - multiBodyA->getBasePos();
+ } else
+ {
+ rel_pos1 = pos1 - multiBodyA->getLink(solverConstraint.m_linkA).m_cachedWorldTransform.getOrigin();
+ }
+ const int ndofA = multiBodyA->getNumDofs() + 6;
+
+ solverConstraint.m_deltaVelAindex = multiBodyA->getCompanionId();
+
+ if (solverConstraint.m_deltaVelAindex <0)
+ {
+ solverConstraint.m_deltaVelAindex = m_data.m_deltaVelocities.size();
+ multiBodyA->setCompanionId(solverConstraint.m_deltaVelAindex);
+ m_data.m_deltaVelocities.resize(m_data.m_deltaVelocities.size()+ndofA);
+ } else
+ {
+ btAssert(m_data.m_deltaVelocities.size() >= solverConstraint.m_deltaVelAindex+ndofA);
+ }
+
+ solverConstraint.m_jacAindex = m_data.m_jacobians.size();
+ m_data.m_jacobians.resize(m_data.m_jacobians.size()+ndofA);
+ m_data.m_deltaVelocitiesUnitImpulse.resize(m_data.m_deltaVelocitiesUnitImpulse.size()+ndofA);
+ btAssert(m_data.m_jacobians.size() == m_data.m_deltaVelocitiesUnitImpulse.size());
+
+ btScalar* jac1=&m_data.m_jacobians[solverConstraint.m_jacAindex];
+ multiBodyA->fillConstraintJacobianMultiDof(solverConstraint.m_linkA, cp.getPositionWorldOnA(), constraintNormal, btVector3(0,0,0), jac1, m_data.scratch_r, m_data.scratch_v, m_data.scratch_m);
+ 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;
+ solverConstraint.m_relpos1CrossNormal = torqueAxis0;
+ solverConstraint.m_contactNormal1 = btVector3(0,0,0);
+ } else
+ {
+ 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);
+ }
+
+
+
+ if (multiBodyB)
+ {
+ if (solverConstraint.m_linkB<0)
+ {
+ rel_pos2 = pos2 - multiBodyB->getBasePos();
+ } else
+ {
+ rel_pos2 = pos2 - multiBodyB->getLink(solverConstraint.m_linkB).m_cachedWorldTransform.getOrigin();
+ }
+
+ const int ndofB = multiBodyB->getNumDofs() + 6;
+
+ solverConstraint.m_deltaVelBindex = multiBodyB->getCompanionId();
+ if (solverConstraint.m_deltaVelBindex <0)
+ {
+ solverConstraint.m_deltaVelBindex = m_data.m_deltaVelocities.size();
+ multiBodyB->setCompanionId(solverConstraint.m_deltaVelBindex);
+ m_data.m_deltaVelocities.resize(m_data.m_deltaVelocities.size()+ndofB);
+ }
+
+ solverConstraint.m_jacBindex = m_data.m_jacobians.size();
+
+ m_data.m_jacobians.resize(m_data.m_jacobians.size()+ndofB);
+ m_data.m_deltaVelocitiesUnitImpulse.resize(m_data.m_deltaVelocitiesUnitImpulse.size()+ndofB);
+ btAssert(m_data.m_jacobians.size() == m_data.m_deltaVelocitiesUnitImpulse.size());
+
+ 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;
+ solverConstraint.m_relpos2CrossNormal = torqueAxis1;
+ solverConstraint.m_contactNormal2 = -btVector3(0,0,0);
+
+ } else
+ {
+ btVector3 torqueAxis1 = constraintNormal;
+ solverConstraint.m_relpos2CrossNormal = torqueAxis1;
+ solverConstraint.m_contactNormal2 = -btVector3(0,0,0);
+
+ solverConstraint.m_angularComponentB = rb1 ? rb1->getInvInertiaTensorWorld()*torqueAxis1*rb1->getAngularFactor() : btVector3(0,0,0);
+ }
+
+ {
+
+ btScalar denom0 = 0.f;
+ btScalar denom1 = 0.f;
+ btScalar* jacB = 0;
+ btScalar* jacA = 0;
+ btScalar* lambdaA =0;
+ btScalar* lambdaB =0;
+ int ndofA = 0;
+ if (multiBodyA)
+ {
+ ndofA = multiBodyA->getNumDofs() + 6;
+ jacA = &m_data.m_jacobians[solverConstraint.m_jacAindex];
+ lambdaA = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex];
+ for (int i = 0; i < ndofA; ++i)
+ {
+ btScalar j = jacA[i] ;
+ btScalar l =lambdaA[i];
+ denom0 += j*l;
+ }
+ } else
+ {
+ if (rb0)
+ {
+ btVector3 iMJaA = rb0?rb0->getInvInertiaTensorWorld()*solverConstraint.m_relpos1CrossNormal:btVector3(0,0,0);
+ denom0 = iMJaA.dot(solverConstraint.m_relpos1CrossNormal);
+ }
+ }
+ if (multiBodyB)
+ {
+ const int ndofB = multiBodyB->getNumDofs() + 6;
+ jacB = &m_data.m_jacobians[solverConstraint.m_jacBindex];
+ lambdaB = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex];
+ for (int i = 0; i < ndofB; ++i)
+ {
+ btScalar j = jacB[i] ;
+ btScalar l =lambdaB[i];
+ denom1 += j*l;
+ }
+
+ } else
+ {
+ if (rb1)
+ {
+ btVector3 iMJaB = rb1?rb1->getInvInertiaTensorWorld()*solverConstraint.m_relpos2CrossNormal:btVector3(0,0,0);
+ denom1 = iMJaB.dot(solverConstraint.m_relpos2CrossNormal);
+ }
+ }
+
+
+
+ btScalar d = denom0+denom1+infoGlobal.m_globalCfm;
+ if (d>SIMD_EPSILON)
+ {
+ solverConstraint.m_jacDiagABInv = relaxation/(d);
+ } else
+ {
+ //disable the constraint row to handle singularity/redundant constraint
+ solverConstraint.m_jacDiagABInv = 0.f;
+ }
+
+ }
+
+
+ //compute rhs and remaining solverConstraint fields
+
+
+
+ btScalar restitution = 0.f;
+ btScalar penetration = isFriction? 0 : cp.getDistance();
+
+ btScalar rel_vel = 0.f;
+ int ndofA = 0;
+ int ndofB = 0;
+ {
+
+ btVector3 vel1,vel2;
+ if (multiBodyA)
+ {
+ ndofA = multiBodyA->getNumDofs() + 6;
+ btScalar* jacA = &m_data.m_jacobians[solverConstraint.m_jacAindex];
+ for (int i = 0; i < ndofA ; ++i)
+ rel_vel += multiBodyA->getVelocityVector()[i] * jacA[i];
+ } else
+ {
+ if (rb0)
+ {
+ btSolverBody* solverBodyA = &m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdA];
+ rel_vel += solverConstraint.m_contactNormal1.dot(rb0?solverBodyA->m_linearVelocity+solverBodyA->m_externalForceImpulse:btVector3(0,0,0))
+ + solverConstraint.m_relpos1CrossNormal.dot(rb0?solverBodyA->m_angularVelocity:btVector3(0,0,0));
+
+ }
+ }
+ if (multiBodyB)
+ {
+ ndofB = multiBodyB->getNumDofs() + 6;
+ btScalar* jacB = &m_data.m_jacobians[solverConstraint.m_jacBindex];
+ for (int i = 0; i < ndofB ; ++i)
+ rel_vel += multiBodyB->getVelocityVector()[i] * jacB[i];
+
+ } else
+ {
+ if (rb1)
+ {
+ btSolverBody* solverBodyB = &m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdB];
+ rel_vel += solverConstraint.m_contactNormal2.dot(rb1?solverBodyB->m_linearVelocity+solverBodyB->m_externalForceImpulse:btVector3(0,0,0))
+ + solverConstraint.m_relpos2CrossNormal.dot(rb1?solverBodyB->m_angularVelocity:btVector3(0,0,0));
+
+ }
+ }
+
+ solverConstraint.m_friction =combinedTorsionalFriction;
+
+ if(!isFriction)
+ {
+ restitution = restitutionCurve(rel_vel, cp.m_combinedRestitution, infoGlobal.m_restitutionVelocityThreshold);
+ if (restitution <= btScalar(0.))
+ {
+ restitution = 0.f;
+ }
+ }
+ }
+
+
+ solverConstraint.m_appliedImpulse = 0.f;
+ solverConstraint.m_appliedPushImpulse = 0.f;
+
+ {
+
+ btScalar velocityError = 0 - rel_vel;// * damping; //note for friction restitution is always set to 0 (check above) so it is acutally velocityError = -rel_vel for friction
+
+
+
+ btScalar velocityImpulse = velocityError*solverConstraint.m_jacDiagABInv;
+
+ solverConstraint.m_rhs = velocityImpulse;
+ solverConstraint.m_rhsPenetration = 0.f;
+ solverConstraint.m_lowerLimit = -solverConstraint.m_friction;
+ solverConstraint.m_upperLimit = solverConstraint.m_friction;
+
+ solverConstraint.m_cfm = infoGlobal.m_globalCfm*solverConstraint.m_jacDiagABInv;
+
+
+
+ }
+
+}
+
+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)
+{
+ BT_PROFILE("addMultiBodyFrictionConstraint");
+ btMultiBodySolverConstraint& solverConstraint = m_multiBodyFrictionContactConstraints.expandNonInitializing();
+ solverConstraint.m_orgConstraint = 0;
+ solverConstraint.m_orgDofIndex = -1;
+
+ solverConstraint.m_frictionIndex = frictionIndex;
+ bool isFriction = true;
+
+ const btMultiBodyLinkCollider* fcA = btMultiBodyLinkCollider::upcast(manifold->getBody0());
+ const btMultiBodyLinkCollider* fcB = btMultiBodyLinkCollider::upcast(manifold->getBody1());
+
+ btMultiBody* mbA = fcA? fcA->m_multiBody : 0;
+ btMultiBody* mbB = fcB? fcB->m_multiBody : 0;
+
+ int solverBodyIdA = mbA? -1 : getOrInitSolverBody(*colObj0,infoGlobal.m_timeStep);
+ int solverBodyIdB = mbB ? -1 : getOrInitSolverBody(*colObj1,infoGlobal.m_timeStep);
+
+ solverConstraint.m_solverBodyIdA = solverBodyIdA;
+ solverConstraint.m_solverBodyIdB = solverBodyIdB;
+ solverConstraint.m_multiBodyA = mbA;
+ if (mbA)
+ solverConstraint.m_linkA = fcA->m_link;
+
+ solverConstraint.m_multiBodyB = mbB;
+ if (mbB)
+ solverConstraint.m_linkB = fcB->m_link;
+
+ solverConstraint.m_originalContactPoint = &cp;
+
+ setupMultiBodyContactConstraint(solverConstraint, normalAxis, cp, infoGlobal,relaxation,isFriction, desiredVelocity, cfmSlip);
+ return solverConstraint;
+}
+
+btMultiBodySolverConstraint& btMultiBodyConstraintSolver::addMultiBodyTorsionalFrictionConstraint(const btVector3& normalAxis,btPersistentManifold* manifold,int frictionIndex,btManifoldPoint& cp,
+ btScalar combinedTorsionalFriction,
+ btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity, btScalar cfmSlip)
+{
+ BT_PROFILE("addMultiBodyRollingFrictionConstraint");
+ btMultiBodySolverConstraint& solverConstraint = m_multiBodyFrictionContactConstraints.expandNonInitializing();
+ solverConstraint.m_orgConstraint = 0;
+ solverConstraint.m_orgDofIndex = -1;
+
+ solverConstraint.m_frictionIndex = frictionIndex;
+ bool isFriction = true;
+
+ const btMultiBodyLinkCollider* fcA = btMultiBodyLinkCollider::upcast(manifold->getBody0());
+ const btMultiBodyLinkCollider* fcB = btMultiBodyLinkCollider::upcast(manifold->getBody1());
+
+ btMultiBody* mbA = fcA? fcA->m_multiBody : 0;
+ btMultiBody* mbB = fcB? fcB->m_multiBody : 0;
+
+ int solverBodyIdA = mbA? -1 : getOrInitSolverBody(*colObj0,infoGlobal.m_timeStep);
+ int solverBodyIdB = mbB ? -1 : getOrInitSolverBody(*colObj1,infoGlobal.m_timeStep);
+
+ solverConstraint.m_solverBodyIdA = solverBodyIdA;
+ solverConstraint.m_solverBodyIdB = solverBodyIdB;
+ solverConstraint.m_multiBodyA = mbA;
+ if (mbA)
+ solverConstraint.m_linkA = fcA->m_link;
+
+ solverConstraint.m_multiBodyB = mbB;
+ if (mbB)
+ solverConstraint.m_linkB = fcB->m_link;
+
+ solverConstraint.m_originalContactPoint = &cp;
+
+ setupMultiBodyTorsionalFrictionConstraint(solverConstraint, normalAxis, cp, combinedTorsionalFriction,infoGlobal,relaxation,isFriction, desiredVelocity, cfmSlip);
+ return solverConstraint;
+}
+
+void btMultiBodyConstraintSolver::convertMultiBodyContact(btPersistentManifold* manifold,const btContactSolverInfo& infoGlobal)
+{
+ const btMultiBodyLinkCollider* fcA = btMultiBodyLinkCollider::upcast(manifold->getBody0());
+ const btMultiBodyLinkCollider* fcB = btMultiBodyLinkCollider::upcast(manifold->getBody1());
+
+ btMultiBody* mbA = fcA? fcA->m_multiBody : 0;
+ btMultiBody* mbB = fcB? fcB->m_multiBody : 0;
+
+ btCollisionObject* colObj0=0,*colObj1=0;
+
+ colObj0 = (btCollisionObject*)manifold->getBody0();
+ colObj1 = (btCollisionObject*)manifold->getBody1();
+
+ int solverBodyIdA = mbA? -1 : getOrInitSolverBody(*colObj0,infoGlobal.m_timeStep);
+ int solverBodyIdB = mbB ? -1 : getOrInitSolverBody(*colObj1,infoGlobal.m_timeStep);
+
+// btSolverBody* solverBodyA = mbA ? 0 : &m_tmpSolverBodyPool[solverBodyIdA];
+// btSolverBody* solverBodyB = mbB ? 0 : &m_tmpSolverBodyPool[solverBodyIdB];
+
+
+ ///avoid collision response between two static objects
+// if (!solverBodyA || (solverBodyA->m_invMass.isZero() && (!solverBodyB || solverBodyB->m_invMass.isZero())))
+ // return;
+
+ //only a single rollingFriction per manifold
+ int rollingFriction=1;
+
+ for (int j=0;j<manifold->getNumContacts();j++)
+ {
+
+ btManifoldPoint& cp = manifold->getContactPoint(j);
+
+ if (cp.getDistance() <= manifold->getContactProcessingThreshold())
+ {
+
+ btScalar relaxation;
+
+ int frictionIndex = m_multiBodyNormalContactConstraints.size();
+
+ btMultiBodySolverConstraint& solverConstraint = m_multiBodyNormalContactConstraints.expandNonInitializing();
+
+ // btRigidBody* rb0 = btRigidBody::upcast(colObj0);
+ // btRigidBody* rb1 = btRigidBody::upcast(colObj1);
+ solverConstraint.m_orgConstraint = 0;
+ solverConstraint.m_orgDofIndex = -1;
+ solverConstraint.m_solverBodyIdA = solverBodyIdA;
+ solverConstraint.m_solverBodyIdB = solverBodyIdB;
+ solverConstraint.m_multiBodyA = mbA;
+ if (mbA)
+ solverConstraint.m_linkA = fcA->m_link;
+
+ solverConstraint.m_multiBodyB = mbB;
+ if (mbB)
+ solverConstraint.m_linkB = fcB->m_link;
+
+ solverConstraint.m_originalContactPoint = &cp;
+
+ bool isFriction = false;
+ setupMultiBodyContactConstraint(solverConstraint, cp.m_normalWorldOnB,cp, infoGlobal, relaxation, isFriction);
+
+// const btVector3& pos1 = cp.getPositionWorldOnA();
+// const btVector3& pos2 = cp.getPositionWorldOnB();
+
+ /////setup the friction constraints
+#define ENABLE_FRICTION
+#ifdef ENABLE_FRICTION
+ solverConstraint.m_frictionIndex = frictionIndex;
+
+ ///Bullet has several options to set the friction directions
+ ///By default, each contact has only a single friction direction that is recomputed automatically every frame
+ ///based on the relative linear velocity.
+ ///If the relative velocity is zero, it will automatically compute a friction direction.
+
+ ///You can also enable two friction directions, using the SOLVER_USE_2_FRICTION_DIRECTIONS.
+ ///In that case, the second friction direction will be orthogonal to both contact normal and first friction direction.
+ ///
+ ///If you choose SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION, then the friction will be independent from the relative projected velocity.
+ ///
+ ///The user can manually override the friction directions for certain contacts using a contact callback,
+ ///and set the cp.m_lateralFrictionInitialized to true
+ ///In that case, you can set the target relative motion in each friction direction (cp.m_contactMotion1 and cp.m_contactMotion2)
+ ///this will give a conveyor belt effect
+ ///
+
+ btPlaneSpace1(cp.m_normalWorldOnB,cp.m_lateralFrictionDir1,cp.m_lateralFrictionDir2);
+ cp.m_lateralFrictionDir1.normalize();
+ cp.m_lateralFrictionDir2.normalize();
+
+ if (rollingFriction > 0 )
+ {
+ if (cp.m_combinedSpinningFriction>0)
+ {
+ addMultiBodyTorsionalFrictionConstraint(cp.m_normalWorldOnB,manifold,frictionIndex,cp,cp.m_combinedSpinningFriction, colObj0,colObj1, relaxation,infoGlobal);
+ }
+ if (cp.m_combinedRollingFriction>0)
+ {
+
+ applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir1,btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
+ applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir1,btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
+ applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir2,btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
+ applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir2,btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
+
+ if (cp.m_lateralFrictionDir1.length()>0.001)
+ addMultiBodyTorsionalFrictionConstraint(cp.m_lateralFrictionDir1,manifold,frictionIndex,cp,cp.m_combinedRollingFriction, colObj0,colObj1, relaxation,infoGlobal);
+
+ if (cp.m_lateralFrictionDir2.length()>0.001)
+ addMultiBodyTorsionalFrictionConstraint(cp.m_lateralFrictionDir2,manifold,frictionIndex,cp,cp.m_combinedRollingFriction, colObj0,colObj1, relaxation,infoGlobal);
+ }
+ rollingFriction--;
+ }
+ if (!(infoGlobal.m_solverMode & SOLVER_ENABLE_FRICTION_DIRECTION_CACHING) || !(cp.m_contactPointFlags&BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED))
+ {/*
+ cp.m_lateralFrictionDir1 = vel - cp.m_normalWorldOnB * rel_vel;
+ btScalar lat_rel_vel = cp.m_lateralFrictionDir1.length2();
+ if (!(infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION) && lat_rel_vel > SIMD_EPSILON)
+ {
+ cp.m_lateralFrictionDir1 *= 1.f/btSqrt(lat_rel_vel);
+ if((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
+ {
+ cp.m_lateralFrictionDir2 = cp.m_lateralFrictionDir1.cross(cp.m_normalWorldOnB);
+ cp.m_lateralFrictionDir2.normalize();//??
+ applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir2,btCollisionObject::CF_ANISOTROPIC_FRICTION);
+ applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir2,btCollisionObject::CF_ANISOTROPIC_FRICTION);
+ addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
+
+ }
+
+ applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir1,btCollisionObject::CF_ANISOTROPIC_FRICTION);
+ applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir1,btCollisionObject::CF_ANISOTROPIC_FRICTION);
+ addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
+
+ } else
+ */
+ {
+
+
+ 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);
+
+
+ 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);
+ }
+
+ if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS) && (infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION))
+ {
+ cp.m_contactPointFlags|=BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED;
+ }
+ }
+
+ } else
+ {
+ addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir1,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:
+ solverConstraint.m_appliedImpulse = 0.f;
+ solverConstraint.m_appliedPushImpulse = 0.f;
+ }
+
+
+#endif //ENABLE_FRICTION
+
+ }
+ }
+}
+
+void btMultiBodyConstraintSolver::convertContacts(btPersistentManifold** manifoldPtr,int numManifolds, const btContactSolverInfo& infoGlobal)
+{
+ //btPersistentManifold* manifold = 0;
+
+ for (int i=0;i<numManifolds;i++)
+ {
+ btPersistentManifold* manifold= manifoldPtr[i];
+ const btMultiBodyLinkCollider* fcA = btMultiBodyLinkCollider::upcast(manifold->getBody0());
+ const btMultiBodyLinkCollider* fcB = btMultiBodyLinkCollider::upcast(manifold->getBody1());
+ if (!fcA && !fcB)
+ {
+ //the contact doesn't involve any Featherstone btMultiBody, so deal with the regular btRigidBody/btCollisionObject case
+ convertContact(manifold,infoGlobal);
+ } else
+ {
+ convertMultiBodyContact(manifold,infoGlobal);
+ }
+ }
+
+ //also convert the multibody constraints, if any
+
+
+ for (int i=0;i<m_tmpNumMultiBodyConstraints;i++)
+ {
+ btMultiBodyConstraint* c = m_tmpMultiBodyConstraints[i];
+ m_data.m_solverBodyPool = &m_tmpSolverBodyPool;
+ m_data.m_fixedBodyId = m_fixedBodyId;
+
+ c->createConstraintRows(m_multiBodyNonContactConstraints,m_data, infoGlobal);
+ }
+
+}
+
+
+
+btScalar btMultiBodyConstraintSolver::solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& info, btIDebugDraw* debugDrawer,btDispatcher* dispatcher)
+{
+ return btSequentialImpulseConstraintSolver::solveGroup(bodies,numBodies,manifold,numManifolds,constraints,numConstraints,info,debugDrawer,dispatcher);
+}
+
+#if 0
+static void applyJointFeedback(btMultiBodyJacobianData& data, const btMultiBodySolverConstraint& solverConstraint, int jacIndex, btMultiBody* mb, btScalar appliedImpulse)
+{
+ if (appliedImpulse!=0 && mb->internalNeedsJointFeedback())
+ {
+ //todo: get rid of those temporary memory allocations for the joint feedback
+ btAlignedObjectArray<btScalar> forceVector;
+ int numDofsPlusBase = 6+mb->getNumDofs();
+ forceVector.resize(numDofsPlusBase);
+ for (int i=0;i<numDofsPlusBase;i++)
+ {
+ forceVector[i] = data.m_jacobians[jacIndex+i]*appliedImpulse;
+ }
+ btAlignedObjectArray<btScalar> output;
+ output.resize(numDofsPlusBase);
+ bool applyJointFeedback = true;
+ mb->calcAccelerationDeltasMultiDof(&forceVector[0],&output[0],data.scratch_r,data.scratch_v,applyJointFeedback);
+ }
+}
+#endif
+
+
+void btMultiBodyConstraintSolver::writeBackSolverBodyToMultiBody(btMultiBodySolverConstraint& c, btScalar deltaTime)
+{
+#if 1
+
+ //bod->addBaseForce(m_gravity * bod->getBaseMass());
+ //bod->addLinkForce(j, m_gravity * bod->getLinkMass(j));
+
+ if (c.m_orgConstraint)
+ {
+ c.m_orgConstraint->internalSetAppliedImpulse(c.m_orgDofIndex,c.m_appliedImpulse);
+ }
+
+
+ if (c.m_multiBodyA)
+ {
+
+ c.m_multiBodyA->setCompanionId(-1);
+ btVector3 force = c.m_contactNormal1*(c.m_appliedImpulse/deltaTime);
+ btVector3 torque = c.m_relpos1CrossNormal*(c.m_appliedImpulse/deltaTime);
+ if (c.m_linkA<0)
+ {
+ c.m_multiBodyA->addBaseConstraintForce(force);
+ c.m_multiBodyA->addBaseConstraintTorque(torque);
+ } else
+ {
+ c.m_multiBodyA->addLinkConstraintForce(c.m_linkA,force);
+ //b3Printf("force = %f,%f,%f\n",force[0],force[1],force[2]);//[0],torque[1],torque[2]);
+ c.m_multiBodyA->addLinkConstraintTorque(c.m_linkA,torque);
+ }
+ }
+
+ if (c.m_multiBodyB)
+ {
+ {
+ c.m_multiBodyB->setCompanionId(-1);
+ btVector3 force = c.m_contactNormal2*(c.m_appliedImpulse/deltaTime);
+ btVector3 torque = c.m_relpos2CrossNormal*(c.m_appliedImpulse/deltaTime);
+ if (c.m_linkB<0)
+ {
+ c.m_multiBodyB->addBaseConstraintForce(force);
+ c.m_multiBodyB->addBaseConstraintTorque(torque);
+ } else
+ {
+ {
+ c.m_multiBodyB->addLinkConstraintForce(c.m_linkB,force);
+ //b3Printf("t = %f,%f,%f\n",force[0],force[1],force[2]);//[0],torque[1],torque[2]);
+ c.m_multiBodyB->addLinkConstraintTorque(c.m_linkB,torque);
+ }
+
+ }
+ }
+ }
+#endif
+
+#ifndef DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
+
+ if (c.m_multiBodyA)
+ {
+
+ if(c.m_multiBodyA->isMultiDof())
+ {
+ c.m_multiBodyA->applyDeltaVeeMultiDof(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacAindex],c.m_appliedImpulse);
+ }
+ else
+ {
+ c.m_multiBodyA->applyDeltaVee(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacAindex],c.m_appliedImpulse);
+ }
+ }
+
+ if (c.m_multiBodyB)
+ {
+ if(c.m_multiBodyB->isMultiDof())
+ {
+ c.m_multiBodyB->applyDeltaVeeMultiDof(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacBindex],c.m_appliedImpulse);
+ }
+ else
+ {
+ c.m_multiBodyB->applyDeltaVee(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacBindex],c.m_appliedImpulse);
+ }
+ }
+#endif
+
+
+
+}
+
+btScalar btMultiBodyConstraintSolver::solveGroupCacheFriendlyFinish(btCollisionObject** bodies,int numBodies,const btContactSolverInfo& infoGlobal)
+{
+ BT_PROFILE("btMultiBodyConstraintSolver::solveGroupCacheFriendlyFinish");
+ int numPoolConstraints = m_multiBodyNormalContactConstraints.size();
+
+
+ //write back the delta v to the multi bodies, either as applied impulse (direct velocity change)
+ //or as applied force, so we can measure the joint reaction forces easier
+ for (int i=0;i<numPoolConstraints;i++)
+ {
+ btMultiBodySolverConstraint& solverConstraint = m_multiBodyNormalContactConstraints[i];
+ writeBackSolverBodyToMultiBody(solverConstraint,infoGlobal.m_timeStep);
+
+ writeBackSolverBodyToMultiBody(m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex],infoGlobal.m_timeStep);
+
+ if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
+ {
+ writeBackSolverBodyToMultiBody(m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1],infoGlobal.m_timeStep);
+ }
+ }
+
+
+ for (int i=0;i<m_multiBodyNonContactConstraints.size();i++)
+ {
+ btMultiBodySolverConstraint& solverConstraint = m_multiBodyNonContactConstraints[i];
+ 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++)
+ {
+ const btMultiBodySolverConstraint& solverConstraint = m_multiBodyNormalContactConstraints[j];
+ btManifoldPoint* pt = (btManifoldPoint*) solverConstraint.m_originalContactPoint;
+ btAssert(pt);
+ pt->m_appliedImpulse = solverConstraint.m_appliedImpulse;
+ pt->m_appliedImpulseLateral1 = m_multiBodyFrictionContactConstraints[solverConstraint.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 = m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1].m_appliedImpulse;
+ }
+ //do a callback here?
+ }
+ }
+#if 0
+ //multibody joint feedback
+ {
+ BT_PROFILE("multi body joint feedback");
+ for (int j=0;j<numPoolConstraints;j++)
+ {
+ const btMultiBodySolverConstraint& solverConstraint = m_multiBodyNormalContactConstraints[j];
+
+ //apply the joint feedback into all links of the btMultiBody
+ //todo: double-check the signs of the applied impulse
+
+ if(solverConstraint.m_multiBodyA && solverConstraint.m_multiBodyA->isMultiDof())
+ {
+ applyJointFeedback(m_data,solverConstraint, solverConstraint.m_jacAindex,solverConstraint.m_multiBodyA, solverConstraint.m_appliedImpulse*btSimdScalar(1./infoGlobal.m_timeStep));
+ }
+ if(solverConstraint.m_multiBodyB && solverConstraint.m_multiBodyB->isMultiDof())
+ {
+ applyJointFeedback(m_data,solverConstraint, solverConstraint.m_jacBindex,solverConstraint.m_multiBodyB,solverConstraint.m_appliedImpulse*btSimdScalar(-1./infoGlobal.m_timeStep));
+ }
+#if 0
+ if (m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex].m_multiBodyA && m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex].m_multiBodyA->isMultiDof())
+ {
+ applyJointFeedback(m_data,m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex],
+ m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex].m_jacAindex,
+ m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex].m_multiBodyA,
+ m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex].m_appliedImpulse*btSimdScalar(1./infoGlobal.m_timeStep));
+
+ }
+ if (m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex].m_multiBodyB && m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex].m_multiBodyB->isMultiDof())
+ {
+ applyJointFeedback(m_data,m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex],
+ m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex].m_jacBindex,
+ m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex].m_multiBodyB,
+ m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex].m_appliedImpulse*btSimdScalar(-1./infoGlobal.m_timeStep));
+ }
+
+ if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
+ {
+ if (m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1].m_multiBodyA && m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1].m_multiBodyA->isMultiDof())
+ {
+ applyJointFeedback(m_data,m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1],
+ m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1].m_jacAindex,
+ m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1].m_multiBodyA,
+ m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1].m_appliedImpulse*btSimdScalar(1./infoGlobal.m_timeStep));
+ }
+
+ if (m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1].m_multiBodyB && m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1].m_multiBodyB->isMultiDof())
+ {
+ applyJointFeedback(m_data,m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1],
+ m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1].m_jacBindex,
+ m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1].m_multiBodyB,
+ m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1].m_appliedImpulse*btSimdScalar(-1./infoGlobal.m_timeStep));
+ }
+ }
+#endif
+ }
+
+ for (int i=0;i<m_multiBodyNonContactConstraints.size();i++)
+ {
+ const btMultiBodySolverConstraint& solverConstraint = m_multiBodyNonContactConstraints[i];
+ if(solverConstraint.m_multiBodyA && solverConstraint.m_multiBodyA->isMultiDof())
+ {
+ applyJointFeedback(m_data,solverConstraint, solverConstraint.m_jacAindex,solverConstraint.m_multiBodyA, solverConstraint.m_appliedImpulse*btSimdScalar(1./infoGlobal.m_timeStep));
+ }
+ if(solverConstraint.m_multiBodyB && solverConstraint.m_multiBodyB->isMultiDof())
+ {
+ applyJointFeedback(m_data,solverConstraint, solverConstraint.m_jacBindex,solverConstraint.m_multiBodyB,solverConstraint.m_appliedImpulse*btSimdScalar(1./infoGlobal.m_timeStep));
+ }
+ }
+ }
+
+ numPoolConstraints = m_multiBodyNonContactConstraints.size();
+
+#if 0
+ //@todo: m_originalContactPoint is not initialized for btMultiBodySolverConstraint
+ for (int i=0;i<numPoolConstraints;i++)
+ {
+ const btMultiBodySolverConstraint& c = m_multiBodyNonContactConstraints[i];
+
+ btTypedConstraint* constr = (btTypedConstraint*)c.m_originalContactPoint;
+ btJointFeedback* fb = constr->getJointFeedback();
+ if (fb)
+ {
+ fb->m_appliedForceBodyA += c.m_contactNormal1*c.m_appliedImpulse*constr->getRigidBodyA().getLinearFactor()/infoGlobal.m_timeStep;
+ fb->m_appliedForceBodyB += c.m_contactNormal2*c.m_appliedImpulse*constr->getRigidBodyB().getLinearFactor()/infoGlobal.m_timeStep;
+ fb->m_appliedTorqueBodyA += c.m_relpos1CrossNormal* constr->getRigidBodyA().getAngularFactor()*c.m_appliedImpulse/infoGlobal.m_timeStep;
+ fb->m_appliedTorqueBodyB += c.m_relpos2CrossNormal* constr->getRigidBodyB().getAngularFactor()*c.m_appliedImpulse/infoGlobal.m_timeStep; /*RGM ???? */
+
+ }
+
+ constr->internalSetAppliedImpulse(c.m_appliedImpulse);
+ if (btFabs(c.m_appliedImpulse)>=constr->getBreakingImpulseThreshold())
+ {
+ constr->setEnabled(false);
+ }
+
+ }
+#endif
+#endif
+
+ return btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyFinish(bodies,numBodies,infoGlobal);
+}
+
+
+void btMultiBodyConstraintSolver::solveMultiBodyGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints,btMultiBodyConstraint** multiBodyConstraints, int numMultiBodyConstraints, const btContactSolverInfo& info, btIDebugDraw* debugDrawer,btDispatcher* dispatcher)
+{
+ //printf("solveMultiBodyGroup start\n");
+ m_tmpMultiBodyConstraints = multiBodyConstraints;
+ m_tmpNumMultiBodyConstraints = numMultiBodyConstraints;
+
+ btSequentialImpulseConstraintSolver::solveGroup(bodies,numBodies,manifold,numManifolds,constraints,numConstraints,info,debugDrawer,dispatcher);
+
+ m_tmpMultiBodyConstraints = 0;
+ m_tmpNumMultiBodyConstraints = 0;
+
+
+}
diff --git a/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h b/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h
new file mode 100644
index 0000000000..489347d874
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h
@@ -0,0 +1,100 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2013 Erwin Coumans 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_CONSTRAINT_SOLVER_H
+#define BT_MULTIBODY_CONSTRAINT_SOLVER_H
+
+#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h"
+#include "btMultiBodySolverConstraint.h"
+
+#define DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
+
+class btMultiBody;
+
+#include "btMultiBodyConstraint.h"
+
+
+
+ATTRIBUTE_ALIGNED16(class) btMultiBodyConstraintSolver : public btSequentialImpulseConstraintSolver
+{
+
+protected:
+
+ btMultiBodyConstraintArray m_multiBodyNonContactConstraints;
+
+ btMultiBodyConstraintArray m_multiBodyNormalContactConstraints;
+ btMultiBodyConstraintArray m_multiBodyFrictionContactConstraints;
+
+ btMultiBodyJacobianData m_data;
+
+ //temp storage for multi body constraints for a specific island/group called by 'solveGroup'
+ btMultiBodyConstraint** m_tmpMultiBodyConstraints;
+ int m_tmpNumMultiBodyConstraints;
+
+ btScalar resolveSingleConstraintRowGeneric(const btMultiBodySolverConstraint& c);
+
+
+ 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& addMultiBodyTorsionalFrictionConstraint(const btVector3& normalAxis,btPersistentManifold* manifold,int frictionIndex,btManifoldPoint& cp,
+ btScalar combinedTorsionalFriction,
+ btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity=0, btScalar cfmSlip=0);
+
+ void setupMultiBodyJointLimitConstraint(btMultiBodySolverConstraint& constraintRow,
+ btScalar* jacA,btScalar* jacB,
+ btScalar penetration,btScalar combinedFrictionCoeff, btScalar combinedRestitutionCoeff,
+ const btContactSolverInfo& infoGlobal);
+
+ void setupMultiBodyContactConstraint(btMultiBodySolverConstraint& solverConstraint,
+ const btVector3& contactNormal,
+ btManifoldPoint& cp, const btContactSolverInfo& infoGlobal,
+ btScalar& relaxation,
+ bool isFriction, btScalar desiredVelocity=0, btScalar cfmSlip=0);
+
+ //either rolling or spinning friction
+ void setupMultiBodyTorsionalFrictionConstraint(btMultiBodySolverConstraint& solverConstraint,
+ const btVector3& contactNormal,
+ btManifoldPoint& cp,
+ btScalar combinedTorsionalFriction,
+ const btContactSolverInfo& infoGlobal,
+ btScalar& relaxation,
+ bool isFriction, btScalar desiredVelocity=0, btScalar cfmSlip=0);
+
+ 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);
+public:
+
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ ///this method should not be called, it was just used during porting/integration of Featherstone btMultiBody, providing backwards compatibility but no support for btMultiBodyConstraint (only contact constraints)
+ virtual btScalar solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& info, btIDebugDraw* debugDrawer,btDispatcher* dispatcher);
+ virtual btScalar solveGroupCacheFriendlyFinish(btCollisionObject** bodies,int numBodies,const btContactSolverInfo& infoGlobal);
+
+ virtual void solveMultiBodyGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints,btMultiBodyConstraint** multiBodyConstraints, int numMultiBodyConstraints, const btContactSolverInfo& info, btIDebugDraw* debugDrawer,btDispatcher* dispatcher);
+};
+
+
+
+
+
+#endif //BT_MULTIBODY_CONSTRAINT_SOLVER_H
+
diff --git a/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.cpp b/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.cpp
new file mode 100644
index 0000000000..9eacc22647
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.cpp
@@ -0,0 +1,991 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2013 Erwin Coumans 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 "btMultiBodyDynamicsWorld.h"
+#include "btMultiBodyConstraintSolver.h"
+#include "btMultiBody.h"
+#include "btMultiBodyLinkCollider.h"
+#include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h"
+#include "LinearMath/btQuickprof.h"
+#include "btMultiBodyConstraint.h"
+#include "LinearMath/btIDebugDraw.h"
+#include "LinearMath/btSerializer.h"
+
+
+void btMultiBodyDynamicsWorld::addMultiBody(btMultiBody* body, int group, int mask)
+{
+ m_multiBodies.push_back(body);
+
+}
+
+void btMultiBodyDynamicsWorld::removeMultiBody(btMultiBody* body)
+{
+ m_multiBodies.remove(body);
+}
+
+void btMultiBodyDynamicsWorld::calculateSimulationIslands()
+{
+ BT_PROFILE("calculateSimulationIslands");
+
+ getSimulationIslandManager()->updateActivationState(getCollisionWorld(),getCollisionWorld()->getDispatcher());
+
+ {
+ //merge islands based on speculative contact manifolds too
+ for (int i=0;i<this->m_predictiveManifolds.size();i++)
+ {
+ btPersistentManifold* manifold = m_predictiveManifolds[i];
+
+ const btCollisionObject* colObj0 = manifold->getBody0();
+ const btCollisionObject* colObj1 = manifold->getBody1();
+
+ if (((colObj0) && (!(colObj0)->isStaticOrKinematicObject())) &&
+ ((colObj1) && (!(colObj1)->isStaticOrKinematicObject())))
+ {
+ getSimulationIslandManager()->getUnionFind().unite((colObj0)->getIslandTag(),(colObj1)->getIslandTag());
+ }
+ }
+ }
+
+ {
+ int i;
+ int numConstraints = int(m_constraints.size());
+ for (i=0;i< numConstraints ; i++ )
+ {
+ btTypedConstraint* constraint = m_constraints[i];
+ if (constraint->isEnabled())
+ {
+ const btRigidBody* colObj0 = &constraint->getRigidBodyA();
+ const btRigidBody* colObj1 = &constraint->getRigidBodyB();
+
+ if (((colObj0) && (!(colObj0)->isStaticOrKinematicObject())) &&
+ ((colObj1) && (!(colObj1)->isStaticOrKinematicObject())))
+ {
+ getSimulationIslandManager()->getUnionFind().unite((colObj0)->getIslandTag(),(colObj1)->getIslandTag());
+ }
+ }
+ }
+ }
+
+ //merge islands linked by Featherstone link colliders
+ for (int i=0;i<m_multiBodies.size();i++)
+ {
+ btMultiBody* body = m_multiBodies[i];
+ {
+ btMultiBodyLinkCollider* prev = body->getBaseCollider();
+
+ for (int b=0;b<body->getNumLinks();b++)
+ {
+ btMultiBodyLinkCollider* cur = body->getLink(b).m_collider;
+
+ if (((cur) && (!(cur)->isStaticOrKinematicObject())) &&
+ ((prev) && (!(prev)->isStaticOrKinematicObject())))
+ {
+ int tagPrev = prev->getIslandTag();
+ int tagCur = cur->getIslandTag();
+ getSimulationIslandManager()->getUnionFind().unite(tagPrev, tagCur);
+ }
+ if (cur && !cur->isStaticOrKinematicObject())
+ prev = cur;
+
+ }
+ }
+ }
+
+ //merge islands linked by multibody constraints
+ {
+ for (int i=0;i<this->m_multiBodyConstraints.size();i++)
+ {
+ btMultiBodyConstraint* c = m_multiBodyConstraints[i];
+ int tagA = c->getIslandIdA();
+ int tagB = c->getIslandIdB();
+ if (tagA>=0 && tagB>=0)
+ getSimulationIslandManager()->getUnionFind().unite(tagA, tagB);
+ }
+ }
+
+ //Store the island id in each body
+ getSimulationIslandManager()->storeIslandActivationState(getCollisionWorld());
+
+}
+
+
+void btMultiBodyDynamicsWorld::updateActivationState(btScalar timeStep)
+{
+ BT_PROFILE("btMultiBodyDynamicsWorld::updateActivationState");
+
+
+
+ for ( int i=0;i<m_multiBodies.size();i++)
+ {
+ btMultiBody* body = m_multiBodies[i];
+ if (body)
+ {
+ body->checkMotionAndSleepIfRequired(timeStep);
+ if (!body->isAwake())
+ {
+ btMultiBodyLinkCollider* col = body->getBaseCollider();
+ if (col && col->getActivationState() == ACTIVE_TAG)
+ {
+ col->setActivationState( WANTS_DEACTIVATION);
+ col->setDeactivationTime(0.f);
+ }
+ for (int b=0;b<body->getNumLinks();b++)
+ {
+ btMultiBodyLinkCollider* col = body->getLink(b).m_collider;
+ if (col && col->getActivationState() == ACTIVE_TAG)
+ {
+ col->setActivationState( WANTS_DEACTIVATION);
+ col->setDeactivationTime(0.f);
+ }
+ }
+ } else
+ {
+ btMultiBodyLinkCollider* col = body->getBaseCollider();
+ if (col && col->getActivationState() != DISABLE_DEACTIVATION)
+ col->setActivationState( ACTIVE_TAG );
+
+ for (int b=0;b<body->getNumLinks();b++)
+ {
+ btMultiBodyLinkCollider* col = body->getLink(b).m_collider;
+ if (col && col->getActivationState() != DISABLE_DEACTIVATION)
+ col->setActivationState( ACTIVE_TAG );
+ }
+ }
+
+ }
+ }
+
+ 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;
+
+
+ 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=(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)
+ {
+ 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);
+ }
+
+
+ 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);
+ } 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_constraints.size()+m_manifolds.size())>m_solverInfo->m_minimumSolverBatchSize)
+ {
+ processConstraints();
+ } else
+ {
+ //printf("deferred\n");
+ }
+ }
+ }
+ }
+ void processConstraints()
+ {
+
+ 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);
+ m_bodies.resize(0);
+ m_manifolds.resize(0);
+ m_constraints.resize(0);
+ m_multiBodyConstraints.resize(0);
+ }
+
+};
+
+
+
+btMultiBodyDynamicsWorld::btMultiBodyDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btMultiBodyConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration)
+ :btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver,collisionConfiguration),
+ m_multiBodyConstraintSolver(constraintSolver)
+{
+ //split impulse is not yet supported for Featherstone hierarchies
+// getSolverInfo().m_splitImpulse = false;
+ getSolverInfo().m_solverMode |=SOLVER_USE_2_FRICTION_DIRECTIONS;
+ m_solverMultiBodyIslandCallback = new MultiBodyInplaceSolverIslandCallback(constraintSolver,dispatcher);
+}
+
+btMultiBodyDynamicsWorld::~btMultiBodyDynamicsWorld ()
+{
+ delete m_solverMultiBodyIslandCallback;
+}
+
+void btMultiBodyDynamicsWorld::forwardKinematics()
+{
+
+ for (int b=0;b<m_multiBodies.size();b++)
+ {
+ btMultiBody* bod = m_multiBodies[b];
+ bod->forwardKinematics(m_scratch_world_to_local,m_scratch_local_origin);
+ }
+}
+void btMultiBodyDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo)
+{
+ forwardKinematics();
+
+
+
+ BT_PROFILE("solveConstraints");
+
+ 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());
+
+ /// solve all the constraints for this island
+ m_islandManager->buildAndProcessIslands(getCollisionWorld()->getDispatcher(),getCollisionWorld(),m_solverMultiBodyIslandCallback);
+
+#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)
+ }
+ }
+#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;
+
+ {
+ if(!bod->isUsingRK4Integration())
+ {
+ bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(solverInfo.m_timeStep, m_scratch_r, m_scratch_v, m_scratch_m);
+ }
+ 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);
+ 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);
+ 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);
+ 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);
+ 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);
+ }
+
+ }
+ }
+
+#ifndef BT_USE_VIRTUAL_CLEARFORCES_AND_GRAVITY
+ bod->clearForcesAndTorques();
+#endif //BT_USE_VIRTUAL_CLEARFORCES_AND_GRAVITY
+ }//if (!isSleeping)
+ }
+ }
+
+ clearMultiBodyConstraintForces();
+
+ 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->isUsingRK4Integration())
+ {
+ bool isConstraintPass = true;
+ bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(solverInfo.m_timeStep, m_scratch_r, m_scratch_v, m_scratch_m, isConstraintPass);
+ }
+ }
+ }
+ }
+ }
+
+ for (int i=0;i<this->m_multiBodies.size();i++)
+ {
+ btMultiBody* bod = m_multiBodies[i];
+ bod->processDeltaVeeMultiDof2();
+ }
+
+}
+
+void btMultiBodyDynamicsWorld::integrateTransforms(btScalar timeStep)
+{
+ btDiscreteDynamicsWorld::integrateTransforms(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();
+
+ ///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();
+
+ 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);
+
+ } else
+ {
+ bod->clearVelocities();
+ }
+ }
+ }
+}
+
+
+
+void btMultiBodyDynamicsWorld::addMultiBodyConstraint( btMultiBodyConstraint* constraint)
+{
+ m_multiBodyConstraints.push_back(constraint);
+}
+
+void btMultiBodyDynamicsWorld::removeMultiBodyConstraint( btMultiBodyConstraint* constraint)
+{
+ m_multiBodyConstraints.remove(constraint);
+}
+
+void btMultiBodyDynamicsWorld::debugDrawMultiBodyConstraint(btMultiBodyConstraint* constraint)
+{
+ constraint->debugDraw(getDebugDrawer());
+}
+
+
+void btMultiBodyDynamicsWorld::debugDrawWorld()
+{
+ BT_PROFILE("btMultiBodyDynamicsWorld debugDrawWorld");
+
+ btDiscreteDynamicsWorld::debugDrawWorld();
+
+ bool drawConstraints = false;
+ if (getDebugDrawer())
+ {
+ int mode = getDebugDrawer()->getDebugMode();
+ if (mode & (btIDebugDraw::DBG_DrawConstraints | btIDebugDraw::DBG_DrawConstraintLimits))
+ {
+ drawConstraints = true;
+ }
+
+ if (drawConstraints)
+ {
+ BT_PROFILE("btMultiBody debugDrawWorld");
+
+
+ for (int c=0;c<m_multiBodyConstraints.size();c++)
+ {
+ btMultiBodyConstraint* constraint = m_multiBodyConstraints[c];
+ debugDrawMultiBodyConstraint(constraint);
+ }
+
+ for (int b = 0; b<m_multiBodies.size(); b++)
+ {
+ btMultiBody* bod = m_multiBodies[b];
+ bod->forwardKinematics(m_scratch_world_to_local1,m_scratch_local_origin1);
+
+ getDebugDrawer()->drawTransform(bod->getBaseWorldTransform(), 0.1);
+
+
+ for (int m = 0; m<bod->getNumLinks(); m++)
+ {
+
+ const btTransform& tr = bod->getLink(m).m_cachedWorldTransform;
+
+ getDebugDrawer()->drawTransform(tr, 0.1);
+
+ //draw the joint axis
+ if (bod->getLink(m).m_jointType==btMultibodyLink::eRevolute)
+ {
+ btVector3 vec = quatRotate(tr.getRotation(),bod->getLink(m).m_axes[0].m_topVec);
+
+ btVector4 color(0,0,0,1);//1,1,1);
+ btVector3 from = vec+tr.getOrigin()-quatRotate(tr.getRotation(),bod->getLink(m).m_dVector);
+ btVector3 to = tr.getOrigin()-quatRotate(tr.getRotation(),bod->getLink(m).m_dVector);
+ getDebugDrawer()->drawLine(from,to,color);
+ }
+ if (bod->getLink(m).m_jointType==btMultibodyLink::eFixed)
+ {
+ btVector3 vec = quatRotate(tr.getRotation(),bod->getLink(m).m_axes[0].m_bottomVec);
+
+ btVector4 color(0,0,0,1);//1,1,1);
+ btVector3 from = vec+tr.getOrigin()-quatRotate(tr.getRotation(),bod->getLink(m).m_dVector);
+ btVector3 to = tr.getOrigin()-quatRotate(tr.getRotation(),bod->getLink(m).m_dVector);
+ getDebugDrawer()->drawLine(from,to,color);
+ }
+ if (bod->getLink(m).m_jointType==btMultibodyLink::ePrismatic)
+ {
+ btVector3 vec = quatRotate(tr.getRotation(),bod->getLink(m).m_axes[0].m_bottomVec);
+
+ btVector4 color(0,0,0,1);//1,1,1);
+ btVector3 from = vec+tr.getOrigin()-quatRotate(tr.getRotation(),bod->getLink(m).m_dVector);
+ btVector3 to = tr.getOrigin()-quatRotate(tr.getRotation(),bod->getLink(m).m_dVector);
+ getDebugDrawer()->drawLine(from,to,color);
+ }
+
+ }
+ }
+ }
+ }
+
+
+}
+
+
+
+void btMultiBodyDynamicsWorld::applyGravity()
+{
+ btDiscreteDynamicsWorld::applyGravity();
+#ifdef BT_USE_VIRTUAL_CLEARFORCES_AND_GRAVITY
+ BT_PROFILE("btMultiBody addGravity");
+ 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));
+ }
+ }//if (!isSleeping)
+ }
+#endif //BT_USE_VIRTUAL_CLEARFORCES_AND_GRAVITY
+}
+
+void btMultiBodyDynamicsWorld::clearMultiBodyConstraintForces()
+{
+ for (int i=0;i<this->m_multiBodies.size();i++)
+ {
+ btMultiBody* bod = m_multiBodies[i];
+ bod->clearConstraintForces();
+ }
+}
+void btMultiBodyDynamicsWorld::clearMultiBodyForces()
+{
+ {
+ // BT_PROFILE("clearMultiBodyForces");
+ 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)
+ {
+ btMultiBody* bod = m_multiBodies[i];
+ bod->clearForcesAndTorques();
+ }
+ }
+ }
+
+}
+void btMultiBodyDynamicsWorld::clearForces()
+{
+ btDiscreteDynamicsWorld::clearForces();
+
+#ifdef BT_USE_VIRTUAL_CLEARFORCES_AND_GRAVITY
+ clearMultiBodyForces();
+#endif
+}
+
+
+
+
+void btMultiBodyDynamicsWorld::serialize(btSerializer* serializer)
+{
+
+ serializer->startSerialization();
+
+ serializeDynamicsWorldInfo( serializer);
+
+ serializeMultiBodies(serializer);
+
+ serializeRigidBodies(serializer);
+
+ serializeCollisionObjects(serializer);
+
+ serializer->finishSerialization();
+}
+
+void btMultiBodyDynamicsWorld::serializeMultiBodies(btSerializer* serializer)
+{
+ int i;
+ //serialize all collision objects
+ for (i=0;i<m_multiBodies.size();i++)
+ {
+ btMultiBody* mb = m_multiBodies[i];
+ {
+ int len = mb->calculateSerializeBufferSize();
+ btChunk* chunk = serializer->allocate(len,1);
+ const char* structType = mb->serialize(chunk->m_oldPtr, serializer);
+ serializer->finalizeChunk(chunk,structType,BT_MULTIBODY_CODE,mb);
+ }
+ }
+
+} \ No newline at end of file
diff --git a/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h b/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h
new file mode 100644
index 0000000000..c0c132bbba
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h
@@ -0,0 +1,114 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2013 Erwin Coumans 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_DYNAMICS_WORLD_H
+#define BT_MULTIBODY_DYNAMICS_WORLD_H
+
+#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h"
+
+#define BT_USE_VIRTUAL_CLEARFORCES_AND_GRAVITY
+
+class btMultiBody;
+class btMultiBodyConstraint;
+class btMultiBodyConstraintSolver;
+struct MultiBodyInplaceSolverIslandCallback;
+
+///The btMultiBodyDynamicsWorld adds Featherstone multi body dynamics to Bullet
+///This implementation is still preliminary/experimental.
+class btMultiBodyDynamicsWorld : public btDiscreteDynamicsWorld
+{
+protected:
+ btAlignedObjectArray<btMultiBody*> m_multiBodies;
+ btAlignedObjectArray<btMultiBodyConstraint*> m_multiBodyConstraints;
+ btAlignedObjectArray<btMultiBodyConstraint*> m_sortedMultiBodyConstraints;
+ btMultiBodyConstraintSolver* m_multiBodyConstraintSolver;
+ MultiBodyInplaceSolverIslandCallback* m_solverMultiBodyIslandCallback;
+
+ //cached data to avoid memory allocations
+ btAlignedObjectArray<btQuaternion> m_scratch_world_to_local;
+ btAlignedObjectArray<btVector3> m_scratch_local_origin;
+ btAlignedObjectArray<btQuaternion> m_scratch_world_to_local1;
+ btAlignedObjectArray<btVector3> m_scratch_local_origin1;
+ btAlignedObjectArray<btScalar> m_scratch_r;
+ btAlignedObjectArray<btVector3> m_scratch_v;
+ btAlignedObjectArray<btMatrix3x3> m_scratch_m;
+
+
+ virtual void calculateSimulationIslands();
+ virtual void updateActivationState(btScalar timeStep);
+ virtual void solveConstraints(btContactSolverInfo& solverInfo);
+
+ virtual void serializeMultiBodies(btSerializer* serializer);
+
+public:
+
+ btMultiBodyDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btMultiBodyConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration);
+
+ virtual ~btMultiBodyDynamicsWorld ();
+
+ virtual void addMultiBody(btMultiBody* body, int group= btBroadphaseProxy::DefaultFilter, int mask=btBroadphaseProxy::AllFilter);
+
+ virtual void removeMultiBody(btMultiBody* body);
+
+ virtual int getNumMultibodies() const
+ {
+ return m_multiBodies.size();
+ }
+
+ btMultiBody* getMultiBody(int mbIndex)
+ {
+ return m_multiBodies[mbIndex];
+ }
+
+ const btMultiBody* getMultiBody(int mbIndex) const
+ {
+ return m_multiBodies[mbIndex];
+ }
+
+ virtual void addMultiBodyConstraint( btMultiBodyConstraint* constraint);
+
+ virtual int getNumMultiBodyConstraints() const
+ {
+ return m_multiBodyConstraints.size();
+ }
+
+ virtual btMultiBodyConstraint* getMultiBodyConstraint( int constraintIndex)
+ {
+ return m_multiBodyConstraints[constraintIndex];
+ }
+
+ virtual const btMultiBodyConstraint* getMultiBodyConstraint( int constraintIndex) const
+ {
+ return m_multiBodyConstraints[constraintIndex];
+ }
+
+ virtual void removeMultiBodyConstraint( btMultiBodyConstraint* constraint);
+
+ virtual void integrateTransforms(btScalar timeStep);
+
+ virtual void debugDrawWorld();
+
+ virtual void debugDrawMultiBodyConstraint(btMultiBodyConstraint* constraint);
+
+ void forwardKinematics();
+ virtual void clearForces();
+ virtual void clearMultiBodyConstraintForces();
+ virtual void clearMultiBodyForces();
+ virtual void applyGravity();
+
+ virtual void serialize(btSerializer* serializer);
+
+};
+#endif //BT_MULTIBODY_DYNAMICS_WORLD_H
diff --git a/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyFixedConstraint.cpp b/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyFixedConstraint.cpp
new file mode 100644
index 0000000000..1f94117aa9
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyFixedConstraint.cpp
@@ -0,0 +1,211 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2013 Erwin Coumans 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.
+*/
+
+///This file was written by Erwin Coumans
+
+#include "btMultiBodyFixedConstraint.h"
+#include "btMultiBodyLinkCollider.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h"
+#include "LinearMath/btIDebugDraw.h"
+
+#define BTMBFIXEDCONSTRAINT_DIM 6
+
+btMultiBodyFixedConstraint::btMultiBodyFixedConstraint(btMultiBody* body, int link, btRigidBody* bodyB, const btVector3& pivotInA, const btVector3& pivotInB, const btMatrix3x3& frameInA, const btMatrix3x3& frameInB)
+ :btMultiBodyConstraint(body,0,link,-1,BTMBFIXEDCONSTRAINT_DIM,false),
+ m_rigidBodyA(0),
+ m_rigidBodyB(bodyB),
+ m_pivotInA(pivotInA),
+ m_pivotInB(pivotInB),
+ m_frameInA(frameInA),
+ m_frameInB(frameInB)
+{
+ m_data.resize(BTMBFIXEDCONSTRAINT_DIM);//at least store the applied impulses
+}
+
+btMultiBodyFixedConstraint::btMultiBodyFixedConstraint(btMultiBody* bodyA, int linkA, btMultiBody* bodyB, int linkB, const btVector3& pivotInA, const btVector3& pivotInB, const btMatrix3x3& frameInA, const btMatrix3x3& frameInB)
+ :btMultiBodyConstraint(bodyA,bodyB,linkA,linkB,BTMBFIXEDCONSTRAINT_DIM,false),
+ m_rigidBodyA(0),
+ m_rigidBodyB(0),
+ m_pivotInA(pivotInA),
+ m_pivotInB(pivotInB),
+ m_frameInA(frameInA),
+ m_frameInB(frameInB)
+{
+ m_data.resize(BTMBFIXEDCONSTRAINT_DIM);//at least store the applied impulses
+}
+
+void btMultiBodyFixedConstraint::finalizeMultiDof()
+{
+ //not implemented yet
+ btAssert(0);
+}
+
+btMultiBodyFixedConstraint::~btMultiBodyFixedConstraint()
+{
+}
+
+
+int btMultiBodyFixedConstraint::getIslandIdA() const
+{
+ if (m_rigidBodyA)
+ return m_rigidBodyA->getIslandTag();
+
+ if (m_bodyA)
+ {
+ btMultiBodyLinkCollider* col = m_bodyA->getBaseCollider();
+ if (col)
+ return col->getIslandTag();
+ for (int i=0;i<m_bodyA->getNumLinks();i++)
+ {
+ if (m_bodyA->getLink(i).m_collider)
+ return m_bodyA->getLink(i).m_collider->getIslandTag();
+ }
+ }
+ return -1;
+}
+
+int btMultiBodyFixedConstraint::getIslandIdB() const
+{
+ if (m_rigidBodyB)
+ return m_rigidBodyB->getIslandTag();
+ if (m_bodyB)
+ {
+ btMultiBodyLinkCollider* col = m_bodyB->getBaseCollider();
+ if (col)
+ return col->getIslandTag();
+
+ for (int i=0;i<m_bodyB->getNumLinks();i++)
+ {
+ col = m_bodyB->getLink(i).m_collider;
+ if (col)
+ return col->getIslandTag();
+ }
+ }
+ return -1;
+}
+
+void btMultiBodyFixedConstraint::createConstraintRows(btMultiBodyConstraintArray& constraintRows, btMultiBodyJacobianData& data, const btContactSolverInfo& infoGlobal)
+{
+ int numDim = BTMBFIXEDCONSTRAINT_DIM;
+ for (int i=0;i<numDim;i++)
+ {
+ btMultiBodySolverConstraint& constraintRow = constraintRows.expandNonInitializing();
+ constraintRow.m_orgConstraint = this;
+ constraintRow.m_orgDofIndex = i;
+ constraintRow.m_relpos1CrossNormal.setValue(0,0,0);
+ constraintRow.m_contactNormal1.setValue(0,0,0);
+ constraintRow.m_relpos2CrossNormal.setValue(0,0,0);
+ constraintRow.m_contactNormal2.setValue(0,0,0);
+ constraintRow.m_angularComponentA.setValue(0,0,0);
+ constraintRow.m_angularComponentB.setValue(0,0,0);
+
+ constraintRow.m_solverBodyIdA = data.m_fixedBodyId;
+ constraintRow.m_solverBodyIdB = data.m_fixedBodyId;
+
+ // Convert local points back to world
+ btVector3 pivotAworld = m_pivotInA;
+ btMatrix3x3 frameAworld = m_frameInA;
+ if (m_rigidBodyA)
+ {
+
+ constraintRow.m_solverBodyIdA = m_rigidBodyA->getCompanionId();
+ pivotAworld = m_rigidBodyA->getCenterOfMassTransform()*m_pivotInA;
+ frameAworld = frameAworld.transpose()*btMatrix3x3(m_rigidBodyA->getOrientation());
+
+ } else
+ {
+ if (m_bodyA) {
+ pivotAworld = m_bodyA->localPosToWorld(m_linkA, m_pivotInA);
+ frameAworld = m_bodyA->localFrameToWorld(m_linkA, frameAworld);
+ }
+ }
+ btVector3 pivotBworld = m_pivotInB;
+ btMatrix3x3 frameBworld = m_frameInB;
+ if (m_rigidBodyB)
+ {
+ constraintRow.m_solverBodyIdB = m_rigidBodyB->getCompanionId();
+ pivotBworld = m_rigidBodyB->getCenterOfMassTransform()*m_pivotInB;
+ frameBworld = frameBworld.transpose()*btMatrix3x3(m_rigidBodyB->getOrientation());
+
+ } else
+ {
+ if (m_bodyB) {
+ pivotBworld = m_bodyB->localPosToWorld(m_linkB, m_pivotInB);
+ frameBworld = m_bodyB->localFrameToWorld(m_linkB, frameBworld);
+ }
+ }
+
+ btMatrix3x3 relRot = frameAworld.inverse()*frameBworld;
+ btVector3 angleDiff;
+ btGeneric6DofSpring2Constraint::matrixToEulerXYZ(relRot,angleDiff);
+
+ btVector3 constraintNormalLin(0,0,0);
+ btVector3 constraintNormalAng(0,0,0);
+ btScalar posError = 0.0;
+ if (i < 3) {
+ constraintNormalLin[i] = 1;
+ posError = (pivotAworld-pivotBworld).dot(constraintNormalLin);
+ fillMultiBodyConstraint(constraintRow, data, 0, 0, constraintNormalAng,
+ constraintNormalLin, pivotAworld, pivotBworld,
+ posError,
+ infoGlobal,
+ -m_maxAppliedImpulse, m_maxAppliedImpulse
+ );
+ }
+ else { //i>=3
+ constraintNormalAng = frameAworld.getColumn(i%3);
+ posError = angleDiff[i%3];
+ fillMultiBodyConstraint(constraintRow, data, 0, 0, constraintNormalAng,
+ constraintNormalLin, pivotAworld, pivotBworld,
+ posError,
+ infoGlobal,
+ -m_maxAppliedImpulse, m_maxAppliedImpulse, true
+ );
+ }
+ }
+}
+
+void btMultiBodyFixedConstraint::debugDraw(class btIDebugDraw* drawer)
+{
+ btTransform tr;
+ tr.setIdentity();
+
+ if (m_rigidBodyA)
+ {
+ btVector3 pivot = m_rigidBodyA->getCenterOfMassTransform() * m_pivotInA;
+ tr.setOrigin(pivot);
+ drawer->drawTransform(tr, 0.1);
+ }
+ if (m_bodyA)
+ {
+ btVector3 pivotAworld = m_bodyA->localPosToWorld(m_linkA, m_pivotInA);
+ tr.setOrigin(pivotAworld);
+ drawer->drawTransform(tr, 0.1);
+ }
+ if (m_rigidBodyB)
+ {
+ // that ideally should draw the same frame
+ btVector3 pivot = m_rigidBodyB->getCenterOfMassTransform() * m_pivotInB;
+ tr.setOrigin(pivot);
+ drawer->drawTransform(tr, 0.1);
+ }
+ if (m_bodyB)
+ {
+ btVector3 pivotBworld = m_bodyB->localPosToWorld(m_linkB, m_pivotInB);
+ tr.setOrigin(pivotBworld);
+ drawer->drawTransform(tr, 0.1);
+ }
+}
diff --git a/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyFixedConstraint.h b/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyFixedConstraint.h
new file mode 100644
index 0000000000..036025136e
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyFixedConstraint.h
@@ -0,0 +1,94 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2013 Erwin Coumans 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.
+*/
+
+///This file was written by Erwin Coumans
+
+#ifndef BT_MULTIBODY_FIXED_CONSTRAINT_H
+#define BT_MULTIBODY_FIXED_CONSTRAINT_H
+
+#include "btMultiBodyConstraint.h"
+
+class btMultiBodyFixedConstraint : public btMultiBodyConstraint
+{
+protected:
+
+ btRigidBody* m_rigidBodyA;
+ btRigidBody* m_rigidBodyB;
+ btVector3 m_pivotInA;
+ btVector3 m_pivotInB;
+ btMatrix3x3 m_frameInA;
+ btMatrix3x3 m_frameInB;
+
+public:
+
+ btMultiBodyFixedConstraint(btMultiBody* body, int link, btRigidBody* bodyB, const btVector3& pivotInA, const btVector3& pivotInB, const btMatrix3x3& frameInA, const btMatrix3x3& frameInB);
+ btMultiBodyFixedConstraint(btMultiBody* bodyA, int linkA, btMultiBody* bodyB, int linkB, const btVector3& pivotInA, const btVector3& pivotInB, const btMatrix3x3& frameInA, const btMatrix3x3& frameInB);
+
+ virtual ~btMultiBodyFixedConstraint();
+
+ virtual void finalizeMultiDof();
+
+ virtual int getIslandIdA() const;
+ virtual int getIslandIdB() const;
+
+ virtual void createConstraintRows(btMultiBodyConstraintArray& constraintRows,
+ btMultiBodyJacobianData& data,
+ const btContactSolverInfo& infoGlobal);
+
+ const btVector3& getPivotInA() const
+ {
+ return m_pivotInA;
+ }
+
+ void setPivotInA(const btVector3& pivotInA)
+ {
+ m_pivotInA = pivotInA;
+ }
+
+ const btVector3& getPivotInB() const
+ {
+ return m_pivotInB;
+ }
+
+ virtual void setPivotInB(const btVector3& pivotInB)
+ {
+ m_pivotInB = pivotInB;
+ }
+
+ const btMatrix3x3& getFrameInA() const
+ {
+ return m_frameInA;
+ }
+
+ void setFrameInA(const btMatrix3x3& frameInA)
+ {
+ m_frameInA = frameInA;
+ }
+
+ const btMatrix3x3& getFrameInB() const
+ {
+ return m_frameInB;
+ }
+
+ virtual void setFrameInB(const btMatrix3x3& frameInB)
+ {
+ m_frameInB = frameInB;
+ }
+
+ virtual void debugDraw(class btIDebugDraw* drawer);
+
+};
+
+#endif //BT_MULTIBODY_FIXED_CONSTRAINT_H
diff --git a/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyGearConstraint.cpp b/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyGearConstraint.cpp
new file mode 100644
index 0000000000..5fdb7007d8
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyGearConstraint.cpp
@@ -0,0 +1,184 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2013 Erwin Coumans 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.
+*/
+
+///This file was written by Erwin Coumans
+
+#include "btMultiBodyGearConstraint.h"
+#include "btMultiBody.h"
+#include "btMultiBodyLinkCollider.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+
+btMultiBodyGearConstraint::btMultiBodyGearConstraint(btMultiBody* bodyA, int linkA, btMultiBody* bodyB, int linkB, const btVector3& pivotInA, const btVector3& pivotInB, const btMatrix3x3& frameInA, const btMatrix3x3& frameInB)
+ :btMultiBodyConstraint(bodyA,bodyB,linkA,linkB,1,false),
+ m_gearRatio(1),
+ m_gearAuxLink(-1),
+ m_erp(0),
+ m_relativePositionTarget(0)
+{
+
+}
+
+void btMultiBodyGearConstraint::finalizeMultiDof()
+{
+
+ allocateJacobiansMultiDof();
+
+ m_numDofsFinalized = m_jacSizeBoth;
+}
+
+btMultiBodyGearConstraint::~btMultiBodyGearConstraint()
+{
+}
+
+
+int btMultiBodyGearConstraint::getIslandIdA() const
+{
+
+ if (m_bodyA)
+ {
+ btMultiBodyLinkCollider* col = m_bodyA->getBaseCollider();
+ if (col)
+ return col->getIslandTag();
+ for (int i=0;i<m_bodyA->getNumLinks();i++)
+ {
+ if (m_bodyA->getLink(i).m_collider)
+ return m_bodyA->getLink(i).m_collider->getIslandTag();
+ }
+ }
+ return -1;
+}
+
+int btMultiBodyGearConstraint::getIslandIdB() const
+{
+ if (m_bodyB)
+ {
+ btMultiBodyLinkCollider* col = m_bodyB->getBaseCollider();
+ if (col)
+ return col->getIslandTag();
+
+ for (int i=0;i<m_bodyB->getNumLinks();i++)
+ {
+ col = m_bodyB->getLink(i).m_collider;
+ if (col)
+ return col->getIslandTag();
+ }
+ }
+ return -1;
+}
+
+
+void btMultiBodyGearConstraint::createConstraintRows(btMultiBodyConstraintArray& constraintRows,
+ btMultiBodyJacobianData& data,
+ const btContactSolverInfo& infoGlobal)
+{
+ // only positions need to be updated -- data.m_jacobians and force
+ // directions were set in the ctor and never change.
+
+ if (m_numDofsFinalized != m_jacSizeBoth)
+ {
+ finalizeMultiDof();
+ }
+
+ //don't crash
+ if (m_numDofsFinalized != m_jacSizeBoth)
+ return;
+
+
+ if (m_maxAppliedImpulse==0.f)
+ return;
+
+ // note: we rely on the fact that data.m_jacobians are
+ // always initialized to zero by the Constraint ctor
+ int linkDoF = 0;
+ unsigned int offsetA = 6 + (m_bodyA->getLink(m_linkA).m_dofOffset + linkDoF);
+ unsigned int offsetB = 6 + (m_bodyB->getLink(m_linkB).m_dofOffset + linkDoF);
+
+ // row 0: the lower bound
+ jacobianA(0)[offsetA] = 1;
+ jacobianB(0)[offsetB] = m_gearRatio;
+
+ btScalar posError = 0;
+ const btVector3 dummy(0, 0, 0);
+
+ btScalar kp = 1;
+ btScalar kd = 1;
+ int numRows = getNumRows();
+
+ for (int row=0;row<numRows;row++)
+ {
+ btMultiBodySolverConstraint& constraintRow = constraintRows.expandNonInitializing();
+
+
+ int dof = 0;
+ btScalar currentPosition = m_bodyA->getJointPosMultiDof(m_linkA)[dof];
+ btScalar currentVelocity = m_bodyA->getJointVelMultiDof(m_linkA)[dof];
+ btScalar auxVel = 0;
+
+ if (m_gearAuxLink>=0)
+ {
+ auxVel = m_bodyA->getJointVelMultiDof(m_gearAuxLink)[dof];
+ }
+ currentVelocity += auxVel;
+ if (m_erp!=0)
+ {
+ btScalar currentPositionA = m_bodyA->getJointPosMultiDof(m_linkA)[dof];
+ btScalar currentPositionB = m_gearRatio*m_bodyA->getJointPosMultiDof(m_linkB)[dof];
+ btScalar diff = currentPositionB+currentPositionA;
+ btScalar desiredPositionDiff = this->m_relativePositionTarget;
+ posError = -m_erp*(desiredPositionDiff - diff);
+ }
+
+ btScalar desiredRelativeVelocity = auxVel;
+
+ fillMultiBodyConstraint(constraintRow,data,jacobianA(row),jacobianB(row),dummy,dummy,dummy,dummy,posError,infoGlobal,-m_maxAppliedImpulse,m_maxAppliedImpulse,false,1,false,desiredRelativeVelocity);
+
+ constraintRow.m_orgConstraint = this;
+ constraintRow.m_orgDofIndex = row;
+ {
+ //expect either prismatic or revolute joint type for now
+ btAssert((m_bodyA->getLink(m_linkA).m_jointType == btMultibodyLink::eRevolute)||(m_bodyA->getLink(m_linkA).m_jointType == btMultibodyLink::ePrismatic));
+ switch (m_bodyA->getLink(m_linkA).m_jointType)
+ {
+ case btMultibodyLink::eRevolute:
+ {
+ constraintRow.m_contactNormal1.setZero();
+ constraintRow.m_contactNormal2.setZero();
+ btVector3 revoluteAxisInWorld = quatRotate(m_bodyA->getLink(m_linkA).m_cachedWorldTransform.getRotation(),m_bodyA->getLink(m_linkA).m_axes[0].m_topVec);
+ constraintRow.m_relpos1CrossNormal=revoluteAxisInWorld;
+ constraintRow.m_relpos2CrossNormal=-revoluteAxisInWorld;
+
+ break;
+ }
+ case btMultibodyLink::ePrismatic:
+ {
+ btVector3 prismaticAxisInWorld = quatRotate(m_bodyA->getLink(m_linkA).m_cachedWorldTransform.getRotation(),m_bodyA->getLink(m_linkA).m_axes[0].m_bottomVec);
+ constraintRow.m_contactNormal1=prismaticAxisInWorld;
+ constraintRow.m_contactNormal2=-prismaticAxisInWorld;
+ constraintRow.m_relpos1CrossNormal.setZero();
+ constraintRow.m_relpos2CrossNormal.setZero();
+ break;
+ }
+ default:
+ {
+ btAssert(0);
+ }
+ };
+
+ }
+
+ }
+
+}
+
diff --git a/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyGearConstraint.h b/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyGearConstraint.h
new file mode 100644
index 0000000000..0115de6241
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyGearConstraint.h
@@ -0,0 +1,117 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2013 Erwin Coumans 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.
+*/
+
+///This file was written by Erwin Coumans
+
+#ifndef BT_MULTIBODY_GEAR_CONSTRAINT_H
+#define BT_MULTIBODY_GEAR_CONSTRAINT_H
+
+#include "btMultiBodyConstraint.h"
+
+class btMultiBodyGearConstraint : public btMultiBodyConstraint
+{
+protected:
+
+ btRigidBody* m_rigidBodyA;
+ btRigidBody* m_rigidBodyB;
+ btVector3 m_pivotInA;
+ btVector3 m_pivotInB;
+ btMatrix3x3 m_frameInA;
+ btMatrix3x3 m_frameInB;
+ btScalar m_gearRatio;
+ int m_gearAuxLink;
+ btScalar m_erp;
+ btScalar m_relativePositionTarget;
+
+public:
+
+ //btMultiBodyGearConstraint(btMultiBody* body, int link, btRigidBody* bodyB, const btVector3& pivotInA, const btVector3& pivotInB, const btMatrix3x3& frameInA, const btMatrix3x3& frameInB);
+ btMultiBodyGearConstraint(btMultiBody* bodyA, int linkA, btMultiBody* bodyB, int linkB, const btVector3& pivotInA, const btVector3& pivotInB, const btMatrix3x3& frameInA, const btMatrix3x3& frameInB);
+
+ virtual ~btMultiBodyGearConstraint();
+
+ virtual void finalizeMultiDof();
+
+ virtual int getIslandIdA() const;
+ virtual int getIslandIdB() const;
+
+ virtual void createConstraintRows(btMultiBodyConstraintArray& constraintRows,
+ btMultiBodyJacobianData& data,
+ const btContactSolverInfo& infoGlobal);
+
+ const btVector3& getPivotInA() const
+ {
+ return m_pivotInA;
+ }
+
+ void setPivotInA(const btVector3& pivotInA)
+ {
+ m_pivotInA = pivotInA;
+ }
+
+ const btVector3& getPivotInB() const
+ {
+ return m_pivotInB;
+ }
+
+ virtual void setPivotInB(const btVector3& pivotInB)
+ {
+ m_pivotInB = pivotInB;
+ }
+
+ const btMatrix3x3& getFrameInA() const
+ {
+ return m_frameInA;
+ }
+
+ void setFrameInA(const btMatrix3x3& frameInA)
+ {
+ m_frameInA = frameInA;
+ }
+
+ const btMatrix3x3& getFrameInB() const
+ {
+ return m_frameInB;
+ }
+
+ virtual void setFrameInB(const btMatrix3x3& frameInB)
+ {
+ m_frameInB = frameInB;
+ }
+
+ virtual void debugDraw(class btIDebugDraw* drawer)
+ {
+ //todo(erwincoumans)
+ }
+
+ virtual void setGearRatio(btScalar gearRatio)
+ {
+ m_gearRatio = gearRatio;
+ }
+ virtual void setGearAuxLink(int gearAuxLink)
+ {
+ m_gearAuxLink = gearAuxLink;
+ }
+ virtual void setRelativePositionTarget(btScalar relPosTarget)
+ {
+ m_relativePositionTarget = relPosTarget;
+ }
+ virtual void setErp(btScalar erp)
+ {
+ m_erp = erp;
+ }
+};
+
+#endif //BT_MULTIBODY_GEAR_CONSTRAINT_H
diff --git a/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyJointFeedback.h b/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyJointFeedback.h
new file mode 100644
index 0000000000..5c2fa8ed5b
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyJointFeedback.h
@@ -0,0 +1,27 @@
+/*
+Copyright (c) 2015 Google Inc.
+
+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_JOINT_FEEDBACK_H
+#define BT_MULTIBODY_JOINT_FEEDBACK_H
+
+#include "LinearMath/btSpatialAlgebra.h"
+
+struct btMultiBodyJointFeedback
+{
+ btSpatialForceVector m_reactionForces;
+};
+
+#endif //BT_MULTIBODY_JOINT_FEEDBACK_H
diff --git a/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.cpp b/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.cpp
new file mode 100644
index 0000000000..6d173b66a1
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.cpp
@@ -0,0 +1,205 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2013 Erwin Coumans 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.
+*/
+
+///This file was written by Erwin Coumans
+
+#include "btMultiBodyJointLimitConstraint.h"
+#include "btMultiBody.h"
+#include "btMultiBodyLinkCollider.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+
+
+
+btMultiBodyJointLimitConstraint::btMultiBodyJointLimitConstraint(btMultiBody* body, int link, btScalar lower, btScalar upper)
+ //:btMultiBodyConstraint(body,0,link,-1,2,true),
+ :btMultiBodyConstraint(body,body,link,body->getLink(link).m_parent,2,true),
+ m_lowerBound(lower),
+ m_upperBound(upper)
+{
+
+}
+
+void btMultiBodyJointLimitConstraint::finalizeMultiDof()
+{
+ // the data.m_jacobians never change, so may as well
+ // initialize them here
+
+ allocateJacobiansMultiDof();
+
+ unsigned int offset = 6 + m_bodyA->getLink(m_linkA).m_dofOffset;
+
+ // row 0: the lower bound
+ jacobianA(0)[offset] = 1;
+ // row 1: the upper bound
+ //jacobianA(1)[offset] = -1;
+ jacobianB(1)[offset] = -1;
+
+ m_numDofsFinalized = m_jacSizeBoth;
+}
+
+btMultiBodyJointLimitConstraint::~btMultiBodyJointLimitConstraint()
+{
+}
+
+int btMultiBodyJointLimitConstraint::getIslandIdA() const
+{
+ if(m_bodyA)
+ {
+ btMultiBodyLinkCollider* col = m_bodyA->getBaseCollider();
+ if (col)
+ return col->getIslandTag();
+ for (int i=0;i<m_bodyA->getNumLinks();i++)
+ {
+ if (m_bodyA->getLink(i).m_collider)
+ return m_bodyA->getLink(i).m_collider->getIslandTag();
+ }
+ }
+ return -1;
+}
+
+int btMultiBodyJointLimitConstraint::getIslandIdB() const
+{
+ if(m_bodyB)
+ {
+ btMultiBodyLinkCollider* col = m_bodyB->getBaseCollider();
+ if (col)
+ return col->getIslandTag();
+
+ for (int i=0;i<m_bodyB->getNumLinks();i++)
+ {
+ col = m_bodyB->getLink(i).m_collider;
+ if (col)
+ return col->getIslandTag();
+ }
+ }
+ return -1;
+}
+
+
+void btMultiBodyJointLimitConstraint::createConstraintRows(btMultiBodyConstraintArray& constraintRows,
+ btMultiBodyJacobianData& data,
+ const btContactSolverInfo& infoGlobal)
+{
+
+ // only positions need to be updated -- data.m_jacobians and force
+ // directions were set in the ctor and never change.
+
+ if (m_numDofsFinalized != m_jacSizeBoth)
+ {
+ finalizeMultiDof();
+ }
+
+
+ // row 0: the lower bound
+ setPosition(0, m_bodyA->getJointPos(m_linkA) - m_lowerBound); //multidof: this is joint-type dependent
+
+ // row 1: the upper bound
+ setPosition(1, m_upperBound - m_bodyA->getJointPos(m_linkA));
+
+ for (int row=0;row<getNumRows();row++)
+ {
+ btScalar penetration = getPosition(row);
+
+ //todo: consider adding some safety threshold here
+ if (penetration>0)
+ {
+ continue;
+ }
+ btScalar direction = row? -1 : 1;
+
+ btMultiBodySolverConstraint& constraintRow = constraintRows.expandNonInitializing();
+ constraintRow.m_orgConstraint = this;
+ constraintRow.m_orgDofIndex = row;
+
+ constraintRow.m_multiBodyA = m_bodyA;
+ constraintRow.m_multiBodyB = m_bodyB;
+ const btScalar posError = 0; //why assume it's zero?
+ const btVector3 dummy(0, 0, 0);
+
+ btScalar rel_vel = fillMultiBodyConstraint(constraintRow,data,jacobianA(row),jacobianB(row),dummy,dummy,dummy,dummy,posError,infoGlobal,0,m_maxAppliedImpulse);
+
+ {
+ //expect either prismatic or revolute joint type for now
+ btAssert((m_bodyA->getLink(m_linkA).m_jointType == btMultibodyLink::eRevolute)||(m_bodyA->getLink(m_linkA).m_jointType == btMultibodyLink::ePrismatic));
+ switch (m_bodyA->getLink(m_linkA).m_jointType)
+ {
+ case btMultibodyLink::eRevolute:
+ {
+ constraintRow.m_contactNormal1.setZero();
+ constraintRow.m_contactNormal2.setZero();
+ btVector3 revoluteAxisInWorld = direction*quatRotate(m_bodyA->getLink(m_linkA).m_cachedWorldTransform.getRotation(),m_bodyA->getLink(m_linkA).m_axes[0].m_topVec);
+ constraintRow.m_relpos1CrossNormal=revoluteAxisInWorld;
+ constraintRow.m_relpos2CrossNormal=-revoluteAxisInWorld;
+
+ break;
+ }
+ case btMultibodyLink::ePrismatic:
+ {
+ btVector3 prismaticAxisInWorld = direction* quatRotate(m_bodyA->getLink(m_linkA).m_cachedWorldTransform.getRotation(),m_bodyA->getLink(m_linkA).m_axes[0].m_bottomVec);
+ constraintRow.m_contactNormal1=prismaticAxisInWorld;
+ constraintRow.m_contactNormal2=-prismaticAxisInWorld;
+ constraintRow.m_relpos1CrossNormal.setZero();
+ constraintRow.m_relpos2CrossNormal.setZero();
+
+ break;
+ }
+ default:
+ {
+ btAssert(0);
+ }
+ };
+
+ }
+
+ {
+
+ btScalar positionalError = 0.f;
+ btScalar velocityError = - rel_vel;// * damping;
+ btScalar erp = infoGlobal.m_erp2;
+ if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold))
+ {
+ erp = infoGlobal.m_erp;
+ }
+ if (penetration>0)
+ {
+ positionalError = 0;
+ velocityError = -penetration / infoGlobal.m_timeStep;
+ } else
+ {
+ positionalError = -penetration * erp/infoGlobal.m_timeStep;
+ }
+
+ btScalar penetrationImpulse = positionalError*constraintRow.m_jacDiagABInv;
+ btScalar velocityImpulse = velocityError *constraintRow.m_jacDiagABInv;
+ if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold))
+ {
+ //combine position and velocity into rhs
+ constraintRow.m_rhs = penetrationImpulse+velocityImpulse;
+ constraintRow.m_rhsPenetration = 0.f;
+
+ } else
+ {
+ //split position and velocity into rhs and m_rhsPenetration
+ constraintRow.m_rhs = velocityImpulse;
+ constraintRow.m_rhsPenetration = penetrationImpulse;
+ }
+ }
+ }
+
+}
+
+
+
+
diff --git a/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.h b/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.h
new file mode 100644
index 0000000000..55b8d122b9
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.h
@@ -0,0 +1,50 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2013 Erwin Coumans 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_JOINT_LIMIT_CONSTRAINT_H
+#define BT_MULTIBODY_JOINT_LIMIT_CONSTRAINT_H
+
+#include "btMultiBodyConstraint.h"
+struct btSolverInfo;
+
+class btMultiBodyJointLimitConstraint : public btMultiBodyConstraint
+{
+protected:
+
+ btScalar m_lowerBound;
+ btScalar m_upperBound;
+public:
+
+ btMultiBodyJointLimitConstraint(btMultiBody* body, int link, btScalar lower, btScalar upper);
+ virtual ~btMultiBodyJointLimitConstraint();
+
+ virtual void finalizeMultiDof();
+
+ virtual int getIslandIdA() const;
+ virtual int getIslandIdB() const;
+
+ virtual void createConstraintRows(btMultiBodyConstraintArray& constraintRows,
+ btMultiBodyJacobianData& data,
+ const btContactSolverInfo& infoGlobal);
+
+ virtual void debugDraw(class btIDebugDraw* drawer)
+ {
+ //todo(erwincoumans)
+ }
+
+};
+
+#endif //BT_MULTIBODY_JOINT_LIMIT_CONSTRAINT_H
+
diff --git a/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyJointMotor.cpp b/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyJointMotor.cpp
new file mode 100644
index 0000000000..e0921178e9
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyJointMotor.cpp
@@ -0,0 +1,186 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2013 Erwin Coumans 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.
+*/
+
+///This file was written by Erwin Coumans
+
+#include "btMultiBodyJointMotor.h"
+#include "btMultiBody.h"
+#include "btMultiBodyLinkCollider.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+
+
+btMultiBodyJointMotor::btMultiBodyJointMotor(btMultiBody* body, int link, btScalar desiredVelocity, btScalar maxMotorImpulse)
+ :btMultiBodyConstraint(body,body,link,body->getLink(link).m_parent,1,true),
+ m_desiredVelocity(desiredVelocity),
+ m_desiredPosition(0),
+ m_kd(1.),
+ m_kp(0),
+ m_erp(1),
+ m_rhsClamp(SIMD_INFINITY)
+{
+
+ m_maxAppliedImpulse = maxMotorImpulse;
+ // the data.m_jacobians never change, so may as well
+ // initialize them here
+
+
+}
+
+void btMultiBodyJointMotor::finalizeMultiDof()
+{
+ allocateJacobiansMultiDof();
+ // note: we rely on the fact that data.m_jacobians are
+ // always initialized to zero by the Constraint ctor
+ int linkDoF = 0;
+ unsigned int offset = 6 + (m_bodyA->getLink(m_linkA).m_dofOffset + linkDoF);
+
+ // row 0: the lower bound
+ // row 0: the lower bound
+ jacobianA(0)[offset] = 1;
+
+ m_numDofsFinalized = m_jacSizeBoth;
+}
+
+btMultiBodyJointMotor::btMultiBodyJointMotor(btMultiBody* body, int link, int linkDoF, btScalar desiredVelocity, btScalar maxMotorImpulse)
+ //:btMultiBodyConstraint(body,0,link,-1,1,true),
+ :btMultiBodyConstraint(body,body,link,body->getLink(link).m_parent,1,true),
+ m_desiredVelocity(desiredVelocity),
+ m_desiredPosition(0),
+ m_kd(1.),
+ m_kp(0),
+ m_erp(1),
+ m_rhsClamp(SIMD_INFINITY)
+{
+ btAssert(linkDoF < body->getLink(link).m_dofCount);
+
+ m_maxAppliedImpulse = maxMotorImpulse;
+
+}
+btMultiBodyJointMotor::~btMultiBodyJointMotor()
+{
+}
+
+int btMultiBodyJointMotor::getIslandIdA() const
+{
+ btMultiBodyLinkCollider* col = m_bodyA->getBaseCollider();
+ if (col)
+ return col->getIslandTag();
+ for (int i=0;i<m_bodyA->getNumLinks();i++)
+ {
+ if (m_bodyA->getLink(i).m_collider)
+ return m_bodyA->getLink(i).m_collider->getIslandTag();
+ }
+ return -1;
+}
+
+int btMultiBodyJointMotor::getIslandIdB() const
+{
+ btMultiBodyLinkCollider* col = m_bodyB->getBaseCollider();
+ if (col)
+ return col->getIslandTag();
+
+ for (int i=0;i<m_bodyB->getNumLinks();i++)
+ {
+ col = m_bodyB->getLink(i).m_collider;
+ if (col)
+ return col->getIslandTag();
+ }
+ return -1;
+}
+
+
+void btMultiBodyJointMotor::createConstraintRows(btMultiBodyConstraintArray& constraintRows,
+ btMultiBodyJacobianData& data,
+ const btContactSolverInfo& infoGlobal)
+{
+ // only positions need to be updated -- data.m_jacobians and force
+ // directions were set in the ctor and never change.
+
+ if (m_numDofsFinalized != m_jacSizeBoth)
+ {
+ finalizeMultiDof();
+ }
+
+ //don't crash
+ if (m_numDofsFinalized != m_jacSizeBoth)
+ return;
+
+ if (m_maxAppliedImpulse==0.f)
+ return;
+
+ const btScalar posError = 0;
+ const btVector3 dummy(0, 0, 0);
+
+ for (int row=0;row<getNumRows();row++)
+ {
+ btMultiBodySolverConstraint& constraintRow = constraintRows.expandNonInitializing();
+
+ int dof = 0;
+ btScalar currentPosition = m_bodyA->getJointPosMultiDof(m_linkA)[dof];
+ btScalar currentVelocity = m_bodyA->getJointVelMultiDof(m_linkA)[dof];
+ btScalar positionStabiliationTerm = m_erp*(m_desiredPosition-currentPosition)/infoGlobal.m_timeStep;
+
+ btScalar velocityError = (m_desiredVelocity - currentVelocity);
+ btScalar rhs = m_kp * positionStabiliationTerm + currentVelocity+m_kd * velocityError;
+ if (rhs>m_rhsClamp)
+ {
+ rhs=m_rhsClamp;
+ }
+ if (rhs<-m_rhsClamp)
+ {
+ rhs=-m_rhsClamp;
+ }
+
+
+ fillMultiBodyConstraint(constraintRow,data,jacobianA(row),jacobianB(row),dummy,dummy,dummy,dummy,posError,infoGlobal,-m_maxAppliedImpulse,m_maxAppliedImpulse,false,1,false,rhs);
+ constraintRow.m_orgConstraint = this;
+ constraintRow.m_orgDofIndex = row;
+ {
+ //expect either prismatic or revolute joint type for now
+ btAssert((m_bodyA->getLink(m_linkA).m_jointType == btMultibodyLink::eRevolute)||(m_bodyA->getLink(m_linkA).m_jointType == btMultibodyLink::ePrismatic));
+ switch (m_bodyA->getLink(m_linkA).m_jointType)
+ {
+ case btMultibodyLink::eRevolute:
+ {
+ constraintRow.m_contactNormal1.setZero();
+ constraintRow.m_contactNormal2.setZero();
+ btVector3 revoluteAxisInWorld = quatRotate(m_bodyA->getLink(m_linkA).m_cachedWorldTransform.getRotation(),m_bodyA->getLink(m_linkA).m_axes[0].m_topVec);
+ constraintRow.m_relpos1CrossNormal=revoluteAxisInWorld;
+ constraintRow.m_relpos2CrossNormal=-revoluteAxisInWorld;
+
+ break;
+ }
+ case btMultibodyLink::ePrismatic:
+ {
+ btVector3 prismaticAxisInWorld = quatRotate(m_bodyA->getLink(m_linkA).m_cachedWorldTransform.getRotation(),m_bodyA->getLink(m_linkA).m_axes[0].m_bottomVec);
+ constraintRow.m_contactNormal1=prismaticAxisInWorld;
+ constraintRow.m_contactNormal2=-prismaticAxisInWorld;
+ constraintRow.m_relpos1CrossNormal.setZero();
+ constraintRow.m_relpos2CrossNormal.setZero();
+
+ break;
+ }
+ default:
+ {
+ btAssert(0);
+ }
+ };
+
+ }
+
+ }
+
+}
+
diff --git a/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyJointMotor.h b/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyJointMotor.h
new file mode 100644
index 0000000000..4063bed79a
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyJointMotor.h
@@ -0,0 +1,81 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2013 Erwin Coumans 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.
+*/
+
+///This file was written by Erwin Coumans
+
+#ifndef BT_MULTIBODY_JOINT_MOTOR_H
+#define BT_MULTIBODY_JOINT_MOTOR_H
+
+#include "btMultiBodyConstraint.h"
+struct btSolverInfo;
+
+class btMultiBodyJointMotor : public btMultiBodyConstraint
+{
+protected:
+
+ btScalar m_desiredVelocity;
+ btScalar m_desiredPosition;
+ btScalar m_kd;
+ btScalar m_kp;
+ btScalar m_erp;
+ btScalar m_rhsClamp;//maximum error
+
+
+public:
+
+ btMultiBodyJointMotor(btMultiBody* body, int link, btScalar desiredVelocity, btScalar maxMotorImpulse);
+ btMultiBodyJointMotor(btMultiBody* body, int link, int linkDoF, btScalar desiredVelocity, btScalar maxMotorImpulse);
+ virtual ~btMultiBodyJointMotor();
+ virtual void finalizeMultiDof();
+
+ virtual int getIslandIdA() const;
+ virtual int getIslandIdB() const;
+
+ virtual void createConstraintRows(btMultiBodyConstraintArray& constraintRows,
+ btMultiBodyJacobianData& data,
+ const btContactSolverInfo& infoGlobal);
+
+ virtual void setVelocityTarget(btScalar velTarget, btScalar kd = 1.f)
+ {
+ m_desiredVelocity = velTarget;
+ m_kd = kd;
+ }
+
+ virtual void setPositionTarget(btScalar posTarget, btScalar kp = 1.f)
+ {
+ m_desiredPosition = posTarget;
+ m_kp = kp;
+ }
+
+ virtual void setErp(btScalar erp)
+ {
+ m_erp = erp;
+ }
+ virtual btScalar getErp() const
+ {
+ return m_erp;
+ }
+ virtual void setRhsClamp(btScalar rhsClamp)
+ {
+ m_rhsClamp = rhsClamp;
+ }
+ virtual void debugDraw(class btIDebugDraw* drawer)
+ {
+ //todo(erwincoumans)
+ }
+};
+
+#endif //BT_MULTIBODY_JOINT_MOTOR_H
+
diff --git a/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyLink.h b/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyLink.h
new file mode 100644
index 0000000000..01828e5843
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyLink.h
@@ -0,0 +1,244 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2013 Erwin Coumans 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_LINK_H
+#define BT_MULTIBODY_LINK_H
+
+#include "LinearMath/btQuaternion.h"
+#include "LinearMath/btVector3.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+
+enum btMultiBodyLinkFlags
+{
+ BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION = 1,
+ BT_MULTIBODYLINKFLAGS_DISABLE_ALL_PARENT_COLLISION = 2,
+};
+
+//both defines are now permanently enabled
+#define BT_MULTIBODYLINK_INCLUDE_PLANAR_JOINTS
+#define TEST_SPATIAL_ALGEBRA_LAYER
+
+//
+// Various spatial helper functions
+//
+
+//namespace {
+
+
+#include "LinearMath/btSpatialAlgebra.h"
+
+//}
+
+//
+// Link struct
+//
+
+struct btMultibodyLink
+{
+
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ btScalar m_mass; // mass of link
+ btVector3 m_inertiaLocal; // inertia of link (local frame; diagonal)
+
+ int m_parent; // index of the parent link (assumed to be < index of this link), or -1 if parent is the base link.
+
+ btQuaternion m_zeroRotParentToThis; // rotates vectors in parent-frame to vectors in local-frame (when q=0). constant.
+
+ btVector3 m_dVector; // vector from the inboard joint pos to this link's COM. (local frame.) constant.
+ //this is set to zero for planar joint (see also m_eVector comment)
+
+ // m_eVector is constant, but depends on the joint type:
+ // revolute, fixed, prismatic, spherical: vector from parent's COM to the pivot point, in PARENT's frame.
+ // planar: vector from COM of parent to COM of this link, WHEN Q = 0. (local frame.)
+ // todo: fix the planar so it is consistent with the other joints
+
+ btVector3 m_eVector;
+
+ btSpatialMotionVector m_absFrameTotVelocity, m_absFrameLocVelocity;
+
+ enum eFeatherstoneJointType
+ {
+ eRevolute = 0,
+ ePrismatic = 1,
+ eSpherical = 2,
+ ePlanar = 3,
+ eFixed = 4,
+ eInvalid
+ };
+
+
+
+ // "axis" = spatial joint axis (Mirtich Defn 9 p104). (expressed in local frame.) constant.
+ // for prismatic: m_axesTop[0] = zero;
+ // m_axesBottom[0] = unit vector along the joint axis.
+ // for revolute: m_axesTop[0] = unit vector along the rotation axis (u);
+ // m_axesBottom[0] = u cross m_dVector (i.e. COM linear motion due to the rotation at the joint)
+ //
+ // for spherical: m_axesTop[0][1][2] (u1,u2,u3) form a 3x3 identity matrix (3 rotation axes)
+ // m_axesBottom[0][1][2] cross u1,u2,u3 (i.e. COM linear motion due to the rotation at the joint)
+ //
+ // for planar: m_axesTop[0] = unit vector along the rotation axis (u); defines the plane of motion
+ // m_axesTop[1][2] = zero
+ // m_axesBottom[0] = zero
+ // m_axesBottom[1][2] = unit vectors along the translational axes on that plane
+ btSpatialMotionVector m_axes[6];
+ void setAxisTop(int dof, const btVector3 &axis) { m_axes[dof].m_topVec = axis; }
+ void setAxisBottom(int dof, const btVector3 &axis)
+ {
+ m_axes[dof].m_bottomVec = axis;
+ }
+ void setAxisTop(int dof, const btScalar &x, const btScalar &y, const btScalar &z)
+ {
+ m_axes[dof].m_topVec.setValue(x, y, z);
+ }
+ void setAxisBottom(int dof, const btScalar &x, const btScalar &y, const btScalar &z)
+ {
+ m_axes[dof].m_bottomVec.setValue(x, y, z);
+ }
+ const btVector3 & getAxisTop(int dof) const { return m_axes[dof].m_topVec; }
+ const btVector3 & getAxisBottom(int dof) const { return m_axes[dof].m_bottomVec; }
+
+ int m_dofOffset, m_cfgOffset;
+
+ 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.
+
+ btVector3 m_appliedForce; // In WORLD frame
+ btVector3 m_appliedTorque; // In WORLD frame
+
+btVector3 m_appliedConstraintForce; // In WORLD frame
+ btVector3 m_appliedConstraintTorque; // In WORLD frame
+
+ btScalar m_jointPos[7];
+
+ //m_jointTorque is the joint torque applied by the user using 'addJointTorque'.
+ //It gets set to zero after each internal stepSimulation call
+ btScalar m_jointTorque[6];
+
+ class btMultiBodyLinkCollider* m_collider;
+ int m_flags;
+
+
+ int m_dofCount, m_posVarCount; //redundant but handy
+
+ eFeatherstoneJointType m_jointType;
+
+ struct btMultiBodyJointFeedback* m_jointFeedback;
+
+ btTransform m_cachedWorldTransform;//this cache is updated when calling btMultiBody::forwardKinematics
+
+ const char* m_linkName;//m_linkName memory needs to be managed by the developer/user!
+ const char* m_jointName;//m_jointName memory needs to be managed by the developer/user!
+ const void* m_userPtr;//m_userPtr ptr needs to be managed by the developer/user!
+
+ btScalar m_jointDamping; //todo: implement this internally. It is unused for now, it is set by a URDF loader. User can apply manual damping.
+ btScalar m_jointFriction; //todo: implement this internally. It is unused for now, it is set by a URDF loader. User can apply manual friction using a velocity motor.
+ btScalar m_jointLowerLimit; //todo: implement this internally. It is unused for now, it is set by a URDF loader.
+ btScalar m_jointUpperLimit; //todo: implement this internally. It is unused for now, it is set by a URDF loader.
+ btScalar m_jointMaxForce; //todo: implement this internally. It is unused for now, it is set by a URDF loader.
+ btScalar m_jointMaxVelocity;//todo: implement this internally. It is unused for now, it is set by a URDF loader.
+
+ // ctor: set some sensible defaults
+ btMultibodyLink()
+ : m_mass(1),
+ m_parent(-1),
+ m_zeroRotParentToThis(0, 0, 0, 1),
+ m_cachedRotParentToThis(0, 0, 0, 1),
+ m_collider(0),
+ m_flags(0),
+ m_dofCount(0),
+ m_posVarCount(0),
+ m_jointType(btMultibodyLink::eInvalid),
+ m_jointFeedback(0),
+ m_linkName(0),
+ m_jointName(0),
+ m_userPtr(0),
+ m_jointDamping(0),
+ m_jointFriction(0),
+ m_jointLowerLimit(0),
+ m_jointUpperLimit(0),
+ m_jointMaxForce(0),
+ m_jointMaxVelocity(0)
+ {
+
+ m_inertiaLocal.setValue(1, 1, 1);
+ setAxisTop(0, 0., 0., 0.);
+ setAxisBottom(0, 1., 0., 0.);
+ m_dVector.setValue(0, 0, 0);
+ m_eVector.setValue(0, 0, 0);
+ m_cachedRVector.setValue(0, 0, 0);
+ m_appliedForce.setValue( 0, 0, 0);
+ m_appliedTorque.setValue(0, 0, 0);
+ //
+ m_jointPos[0] = m_jointPos[1] = m_jointPos[2] = m_jointPos[4] = m_jointPos[5] = m_jointPos[6] = 0.f;
+ m_jointPos[3] = 1.f; //"quat.w"
+ m_jointTorque[0] = m_jointTorque[1] = m_jointTorque[2] = m_jointTorque[3] = m_jointTorque[4] = m_jointTorque[5] = 0.f;
+ m_cachedWorldTransform.setIdentity();
+ }
+
+ // routine to update m_cachedRotParentToThis and m_cachedRVector
+ void updateCacheMultiDof(btScalar *pq = 0)
+ {
+ btScalar *pJointPos = (pq ? pq : &m_jointPos[0]);
+
+ switch(m_jointType)
+ {
+ case eRevolute:
+ {
+ m_cachedRotParentToThis = btQuaternion(getAxisTop(0),-pJointPos[0]) * m_zeroRotParentToThis;
+ m_cachedRVector = 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);
+
+ 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);
+
+ 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);
+
+ break;
+ }
+ case eFixed:
+ {
+ m_cachedRotParentToThis = m_zeroRotParentToThis;
+ m_cachedRVector = m_dVector + quatRotate(m_cachedRotParentToThis,m_eVector);
+
+ break;
+ }
+ default:
+ {
+ //invalid type
+ btAssert(0);
+ }
+ }
+ }
+};
+
+
+#endif //BT_MULTIBODY_LINK_H
diff --git a/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyLinkCollider.h b/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyLinkCollider.h
new file mode 100644
index 0000000000..671e15d314
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyLinkCollider.h
@@ -0,0 +1,125 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2013 Erwin Coumans 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_FEATHERSTONE_LINK_COLLIDER_H
+#define BT_FEATHERSTONE_LINK_COLLIDER_H
+
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+
+#include "btMultiBody.h"
+
+class btMultiBodyLinkCollider : public btCollisionObject
+{
+//protected:
+public:
+
+ btMultiBody* m_multiBody;
+ int m_link;
+
+
+ btMultiBodyLinkCollider (btMultiBody* multiBody,int link)
+ :m_multiBody(multiBody),
+ m_link(link)
+ {
+ m_checkCollideWith = true;
+ //we need to remove the 'CF_STATIC_OBJECT' flag, otherwise links/base doesn't merge islands
+ //this means that some constraints might point to bodies that are not in the islands, causing crashes
+ //if (link>=0 || (multiBody && !multiBody->hasFixedBase()))
+ {
+ m_collisionFlags &= (~btCollisionObject::CF_STATIC_OBJECT);
+ }
+ // else
+ //{
+ // m_collisionFlags |= (btCollisionObject::CF_STATIC_OBJECT);
+ //}
+
+ m_internalType = CO_FEATHERSTONE_LINK;
+ }
+ static btMultiBodyLinkCollider* upcast(btCollisionObject* colObj)
+ {
+ if (colObj->getInternalType()&btCollisionObject::CO_FEATHERSTONE_LINK)
+ return (btMultiBodyLinkCollider*)colObj;
+ return 0;
+ }
+ static const btMultiBodyLinkCollider* upcast(const btCollisionObject* colObj)
+ {
+ if (colObj->getInternalType()&btCollisionObject::CO_FEATHERSTONE_LINK)
+ return (btMultiBodyLinkCollider*)colObj;
+ return 0;
+ }
+
+ virtual bool checkCollideWithOverride(const btCollisionObject* co) const
+ {
+ const btMultiBodyLinkCollider* other = btMultiBodyLinkCollider::upcast(co);
+ if (!other)
+ return true;
+ if (other->m_multiBody != this->m_multiBody)
+ return true;
+ if (!m_multiBody->hasSelfCollision())
+ return false;
+
+ //check if 'link' has collision disabled
+ if (m_link>=0)
+ {
+ const btMultibodyLink& link = m_multiBody->getLink(this->m_link);
+ if (link.m_flags&BT_MULTIBODYLINKFLAGS_DISABLE_ALL_PARENT_COLLISION)
+ {
+ int parent_of_this = m_link;
+ while (1)
+ {
+ if (parent_of_this==-1)
+ break;
+ parent_of_this = m_multiBody->getLink(parent_of_this).m_parent;
+ if (parent_of_this==other->m_link)
+ {
+ return false;
+ }
+ }
+ }
+ else if (link.m_flags&BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION)
+ {
+ if ( link.m_parent == other->m_link)
+ return false;
+ }
+
+ }
+
+ if (other->m_link>=0)
+ {
+ const btMultibodyLink& otherLink = other->m_multiBody->getLink(other->m_link);
+ if (otherLink.m_flags& BT_MULTIBODYLINKFLAGS_DISABLE_ALL_PARENT_COLLISION)
+ {
+ int parent_of_other = other->m_link;
+ while (1)
+ {
+ if (parent_of_other==-1)
+ break;
+ parent_of_other = m_multiBody->getLink(parent_of_other).m_parent;
+ if (parent_of_other==this->m_link)
+ return false;
+ }
+ }
+ else if (otherLink.m_flags& BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION)
+ {
+ if (otherLink.m_parent == this->m_link)
+ return false;
+ }
+ }
+ return true;
+ }
+};
+
+#endif //BT_FEATHERSTONE_LINK_COLLIDER_H
+
diff --git a/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyPoint2Point.cpp b/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyPoint2Point.cpp
new file mode 100644
index 0000000000..125d52ad0b
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyPoint2Point.cpp
@@ -0,0 +1,221 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2013 Erwin Coumans 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.
+*/
+
+///This file was written by Erwin Coumans
+
+#include "btMultiBodyPoint2Point.h"
+#include "btMultiBodyLinkCollider.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "LinearMath/btIDebugDraw.h"
+
+#ifndef BTMBP2PCONSTRAINT_BLOCK_ANGULAR_MOTION_TEST
+ #define BTMBP2PCONSTRAINT_DIM 3
+#else
+ #define BTMBP2PCONSTRAINT_DIM 6
+#endif
+
+btMultiBodyPoint2Point::btMultiBodyPoint2Point(btMultiBody* body, int link, btRigidBody* bodyB, const btVector3& pivotInA, const btVector3& pivotInB)
+ :btMultiBodyConstraint(body,0,link,-1,BTMBP2PCONSTRAINT_DIM,false),
+ m_rigidBodyA(0),
+ m_rigidBodyB(bodyB),
+ m_pivotInA(pivotInA),
+ m_pivotInB(pivotInB)
+{
+ m_data.resize(BTMBP2PCONSTRAINT_DIM);//at least store the applied impulses
+}
+
+btMultiBodyPoint2Point::btMultiBodyPoint2Point(btMultiBody* bodyA, int linkA, btMultiBody* bodyB, int linkB, const btVector3& pivotInA, const btVector3& pivotInB)
+ :btMultiBodyConstraint(bodyA,bodyB,linkA,linkB,BTMBP2PCONSTRAINT_DIM,false),
+ m_rigidBodyA(0),
+ m_rigidBodyB(0),
+ m_pivotInA(pivotInA),
+ m_pivotInB(pivotInB)
+{
+ m_data.resize(BTMBP2PCONSTRAINT_DIM);//at least store the applied impulses
+}
+
+void btMultiBodyPoint2Point::finalizeMultiDof()
+{
+ //not implemented yet
+ btAssert(0);
+}
+
+btMultiBodyPoint2Point::~btMultiBodyPoint2Point()
+{
+}
+
+
+int btMultiBodyPoint2Point::getIslandIdA() const
+{
+ if (m_rigidBodyA)
+ return m_rigidBodyA->getIslandTag();
+
+ if (m_bodyA)
+ {
+ btMultiBodyLinkCollider* col = m_bodyA->getBaseCollider();
+ if (col)
+ return col->getIslandTag();
+ for (int i=0;i<m_bodyA->getNumLinks();i++)
+ {
+ if (m_bodyA->getLink(i).m_collider)
+ return m_bodyA->getLink(i).m_collider->getIslandTag();
+ }
+ }
+ return -1;
+}
+
+int btMultiBodyPoint2Point::getIslandIdB() const
+{
+ if (m_rigidBodyB)
+ return m_rigidBodyB->getIslandTag();
+ if (m_bodyB)
+ {
+ btMultiBodyLinkCollider* col = m_bodyB->getBaseCollider();
+ if (col)
+ return col->getIslandTag();
+
+ for (int i=0;i<m_bodyB->getNumLinks();i++)
+ {
+ col = m_bodyB->getLink(i).m_collider;
+ if (col)
+ return col->getIslandTag();
+ }
+ }
+ return -1;
+}
+
+
+
+void btMultiBodyPoint2Point::createConstraintRows(btMultiBodyConstraintArray& constraintRows,
+ btMultiBodyJacobianData& data,
+ const btContactSolverInfo& infoGlobal)
+{
+
+// int i=1;
+int numDim = BTMBP2PCONSTRAINT_DIM;
+ for (int i=0;i<numDim;i++)
+ {
+
+ btMultiBodySolverConstraint& constraintRow = constraintRows.expandNonInitializing();
+ //memset(&constraintRow,0xffffffff,sizeof(btMultiBodySolverConstraint));
+ constraintRow.m_orgConstraint = this;
+ constraintRow.m_orgDofIndex = i;
+ constraintRow.m_relpos1CrossNormal.setValue(0,0,0);
+ constraintRow.m_contactNormal1.setValue(0,0,0);
+ constraintRow.m_relpos2CrossNormal.setValue(0,0,0);
+ constraintRow.m_contactNormal2.setValue(0,0,0);
+ constraintRow.m_angularComponentA.setValue(0,0,0);
+ constraintRow.m_angularComponentB.setValue(0,0,0);
+
+ constraintRow.m_solverBodyIdA = data.m_fixedBodyId;
+ constraintRow.m_solverBodyIdB = data.m_fixedBodyId;
+
+ btVector3 contactNormalOnB(0,0,0);
+#ifndef BTMBP2PCONSTRAINT_BLOCK_ANGULAR_MOTION_TEST
+ contactNormalOnB[i] = -1;
+#else
+ contactNormalOnB[i%3] = -1;
+#endif
+
+
+ // Convert local points back to world
+ btVector3 pivotAworld = m_pivotInA;
+ if (m_rigidBodyA)
+ {
+
+ constraintRow.m_solverBodyIdA = m_rigidBodyA->getCompanionId();
+ pivotAworld = m_rigidBodyA->getCenterOfMassTransform()*m_pivotInA;
+ } else
+ {
+ if (m_bodyA)
+ pivotAworld = m_bodyA->localPosToWorld(m_linkA, m_pivotInA);
+ }
+ btVector3 pivotBworld = m_pivotInB;
+ if (m_rigidBodyB)
+ {
+ constraintRow.m_solverBodyIdB = m_rigidBodyB->getCompanionId();
+ pivotBworld = m_rigidBodyB->getCenterOfMassTransform()*m_pivotInB;
+ } else
+ {
+ if (m_bodyB)
+ pivotBworld = m_bodyB->localPosToWorld(m_linkB, m_pivotInB);
+
+ }
+
+ btScalar posError = i < 3 ? (pivotAworld-pivotBworld).dot(contactNormalOnB) : 0;
+
+#ifndef BTMBP2PCONSTRAINT_BLOCK_ANGULAR_MOTION_TEST
+
+
+ fillMultiBodyConstraint(constraintRow, data, 0, 0, btVector3(0,0,0),
+ contactNormalOnB, pivotAworld, pivotBworld, //sucks but let it be this way "for the time being"
+ posError,
+ infoGlobal,
+ -m_maxAppliedImpulse, m_maxAppliedImpulse
+ );
+ //@todo: support the case of btMultiBody versus btRigidBody,
+ //see btPoint2PointConstraint::getInfo2NonVirtual
+#else
+ const btVector3 dummy(0, 0, 0);
+
+ btAssert(m_bodyA->isMultiDof());
+
+ btScalar* jac1 = jacobianA(i);
+ const btVector3 &normalAng = i >= 3 ? contactNormalOnB : dummy;
+ const btVector3 &normalLin = i < 3 ? contactNormalOnB : dummy;
+
+ m_bodyA->filConstraintJacobianMultiDof(m_linkA, pivotAworld, normalAng, normalLin, jac1, data.scratch_r, data.scratch_v, data.scratch_m);
+
+ fillMultiBodyConstraint(constraintRow, data, jac1, 0,
+ dummy, dummy, dummy, //sucks but let it be this way "for the time being"
+ posError,
+ infoGlobal,
+ -m_maxAppliedImpulse, m_maxAppliedImpulse
+ );
+#endif
+ }
+}
+
+void btMultiBodyPoint2Point::debugDraw(class btIDebugDraw* drawer)
+{
+ btTransform tr;
+ tr.setIdentity();
+
+ if (m_rigidBodyA)
+ {
+ btVector3 pivot = m_rigidBodyA->getCenterOfMassTransform() * m_pivotInA;
+ tr.setOrigin(pivot);
+ drawer->drawTransform(tr, 0.1);
+ }
+ if (m_bodyA)
+ {
+ btVector3 pivotAworld = m_bodyA->localPosToWorld(m_linkA, m_pivotInA);
+ tr.setOrigin(pivotAworld);
+ drawer->drawTransform(tr, 0.1);
+ }
+ if (m_rigidBodyB)
+ {
+ // that ideally should draw the same frame
+ btVector3 pivot = m_rigidBodyB->getCenterOfMassTransform() * m_pivotInB;
+ tr.setOrigin(pivot);
+ drawer->drawTransform(tr, 0.1);
+ }
+ if (m_bodyB)
+ {
+ btVector3 pivotBworld = m_bodyB->localPosToWorld(m_linkB, m_pivotInB);
+ tr.setOrigin(pivotBworld);
+ drawer->drawTransform(tr, 0.1);
+ }
+}
diff --git a/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyPoint2Point.h b/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyPoint2Point.h
new file mode 100644
index 0000000000..bf39acc5b9
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodyPoint2Point.h
@@ -0,0 +1,68 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2013 Erwin Coumans 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.
+*/
+
+///This file was written by Erwin Coumans
+
+#ifndef BT_MULTIBODY_POINT2POINT_H
+#define BT_MULTIBODY_POINT2POINT_H
+
+#include "btMultiBodyConstraint.h"
+
+//#define BTMBP2PCONSTRAINT_BLOCK_ANGULAR_MOTION_TEST
+
+ATTRIBUTE_ALIGNED16(class) btMultiBodyPoint2Point : public btMultiBodyConstraint
+{
+protected:
+
+ btRigidBody* m_rigidBodyA;
+ btRigidBody* m_rigidBodyB;
+ btVector3 m_pivotInA;
+ btVector3 m_pivotInB;
+
+
+public:
+
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ btMultiBodyPoint2Point(btMultiBody* body, int link, btRigidBody* bodyB, const btVector3& pivotInA, const btVector3& pivotInB);
+ btMultiBodyPoint2Point(btMultiBody* bodyA, int linkA, btMultiBody* bodyB, int linkB, const btVector3& pivotInA, const btVector3& pivotInB);
+
+ virtual ~btMultiBodyPoint2Point();
+
+ virtual void finalizeMultiDof();
+
+ virtual int getIslandIdA() const;
+ virtual int getIslandIdB() const;
+
+ virtual void createConstraintRows(btMultiBodyConstraintArray& constraintRows,
+ btMultiBodyJacobianData& data,
+ const btContactSolverInfo& infoGlobal);
+
+ const btVector3& getPivotInB() const
+ {
+ return m_pivotInB;
+ }
+
+ virtual void setPivotInB(const btVector3& pivotInB)
+ {
+ m_pivotInB = pivotInB;
+ }
+
+
+ virtual void debugDraw(class btIDebugDraw* drawer);
+
+};
+
+#endif //BT_MULTIBODY_POINT2POINT_H
diff --git a/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodySliderConstraint.cpp b/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodySliderConstraint.cpp
new file mode 100644
index 0000000000..3b64b8183f
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodySliderConstraint.cpp
@@ -0,0 +1,230 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2013 Erwin Coumans 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.
+*/
+
+///This file was written by Erwin Coumans
+
+#include "btMultiBodySliderConstraint.h"
+#include "btMultiBodyLinkCollider.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h"
+#include "LinearMath/btIDebugDraw.h"
+
+#define BTMBSLIDERCONSTRAINT_DIM 5
+#define EPSILON 0.000001
+
+btMultiBodySliderConstraint::btMultiBodySliderConstraint(btMultiBody* body, int link, btRigidBody* bodyB, const btVector3& pivotInA, const btVector3& pivotInB, const btMatrix3x3& frameInA, const btMatrix3x3& frameInB, const btVector3& jointAxis)
+ :btMultiBodyConstraint(body,0,link,-1,BTMBSLIDERCONSTRAINT_DIM,false),
+ m_rigidBodyA(0),
+ m_rigidBodyB(bodyB),
+ m_pivotInA(pivotInA),
+ m_pivotInB(pivotInB),
+ m_frameInA(frameInA),
+ m_frameInB(frameInB),
+ m_jointAxis(jointAxis)
+{
+ m_data.resize(BTMBSLIDERCONSTRAINT_DIM);//at least store the applied impulses
+}
+
+btMultiBodySliderConstraint::btMultiBodySliderConstraint(btMultiBody* bodyA, int linkA, btMultiBody* bodyB, int linkB, const btVector3& pivotInA, const btVector3& pivotInB, const btMatrix3x3& frameInA, const btMatrix3x3& frameInB, const btVector3& jointAxis)
+ :btMultiBodyConstraint(bodyA,bodyB,linkA,linkB,BTMBSLIDERCONSTRAINT_DIM,false),
+ m_rigidBodyA(0),
+ m_rigidBodyB(0),
+ m_pivotInA(pivotInA),
+ m_pivotInB(pivotInB),
+ m_frameInA(frameInA),
+ m_frameInB(frameInB),
+ m_jointAxis(jointAxis)
+{
+ m_data.resize(BTMBSLIDERCONSTRAINT_DIM);//at least store the applied impulses
+}
+
+void btMultiBodySliderConstraint::finalizeMultiDof()
+{
+ //not implemented yet
+ btAssert(0);
+}
+
+btMultiBodySliderConstraint::~btMultiBodySliderConstraint()
+{
+}
+
+
+int btMultiBodySliderConstraint::getIslandIdA() const
+{
+ if (m_rigidBodyA)
+ return m_rigidBodyA->getIslandTag();
+
+ if (m_bodyA)
+ {
+ btMultiBodyLinkCollider* col = m_bodyA->getBaseCollider();
+ if (col)
+ return col->getIslandTag();
+ for (int i=0;i<m_bodyA->getNumLinks();i++)
+ {
+ if (m_bodyA->getLink(i).m_collider)
+ return m_bodyA->getLink(i).m_collider->getIslandTag();
+ }
+ }
+ return -1;
+}
+
+int btMultiBodySliderConstraint::getIslandIdB() const
+{
+ if (m_rigidBodyB)
+ return m_rigidBodyB->getIslandTag();
+ if (m_bodyB)
+ {
+ btMultiBodyLinkCollider* col = m_bodyB->getBaseCollider();
+ if (col)
+ return col->getIslandTag();
+
+ for (int i=0;i<m_bodyB->getNumLinks();i++)
+ {
+ col = m_bodyB->getLink(i).m_collider;
+ if (col)
+ return col->getIslandTag();
+ }
+ }
+ return -1;
+}
+
+void btMultiBodySliderConstraint::createConstraintRows(btMultiBodyConstraintArray& constraintRows, btMultiBodyJacobianData& data, const btContactSolverInfo& infoGlobal)
+{
+ // Convert local points back to world
+ btVector3 pivotAworld = m_pivotInA;
+ btMatrix3x3 frameAworld = m_frameInA;
+ btVector3 jointAxis = m_jointAxis;
+ if (m_rigidBodyA)
+ {
+ pivotAworld = m_rigidBodyA->getCenterOfMassTransform()*m_pivotInA;
+ frameAworld = m_frameInA.transpose()*btMatrix3x3(m_rigidBodyA->getOrientation());
+ jointAxis = quatRotate(m_rigidBodyA->getOrientation(),m_jointAxis);
+
+ } else if (m_bodyA) {
+ pivotAworld = m_bodyA->localPosToWorld(m_linkA, m_pivotInA);
+ frameAworld = m_bodyA->localFrameToWorld(m_linkA, m_frameInA);
+ jointAxis = m_bodyA->localDirToWorld(m_linkA, m_jointAxis);
+ }
+ btVector3 pivotBworld = m_pivotInB;
+ btMatrix3x3 frameBworld = m_frameInB;
+ if (m_rigidBodyB)
+ {
+ pivotBworld = m_rigidBodyB->getCenterOfMassTransform()*m_pivotInB;
+ frameBworld = m_frameInB.transpose()*btMatrix3x3(m_rigidBodyB->getOrientation());
+
+ } else if (m_bodyB) {
+ pivotBworld = m_bodyB->localPosToWorld(m_linkB, m_pivotInB);
+ frameBworld = m_bodyB->localFrameToWorld(m_linkB, m_frameInB);
+ }
+
+ btVector3 constraintAxis[2];
+ for (int i = 0; i < 3; ++i)
+ {
+ constraintAxis[0] = frameAworld.getColumn(i).cross(jointAxis);
+ if (constraintAxis[0].safeNorm() > EPSILON)
+ {
+ constraintAxis[0] = constraintAxis[0].normalized();
+ constraintAxis[1] = jointAxis.cross(constraintAxis[0]);
+ constraintAxis[1] = constraintAxis[1].normalized();
+ break;
+ }
+ }
+
+ btMatrix3x3 relRot = frameAworld.inverse()*frameBworld;
+ btVector3 angleDiff;
+ btGeneric6DofSpring2Constraint::matrixToEulerXYZ(relRot,angleDiff);
+
+ int numDim = BTMBSLIDERCONSTRAINT_DIM;
+ for (int i=0;i<numDim;i++)
+ {
+ btMultiBodySolverConstraint& constraintRow = constraintRows.expandNonInitializing();
+ constraintRow.m_orgConstraint = this;
+ constraintRow.m_orgDofIndex = i;
+ constraintRow.m_relpos1CrossNormal.setValue(0,0,0);
+ constraintRow.m_contactNormal1.setValue(0,0,0);
+ constraintRow.m_relpos2CrossNormal.setValue(0,0,0);
+ constraintRow.m_contactNormal2.setValue(0,0,0);
+ constraintRow.m_angularComponentA.setValue(0,0,0);
+ constraintRow.m_angularComponentB.setValue(0,0,0);
+
+ constraintRow.m_solverBodyIdA = data.m_fixedBodyId;
+ constraintRow.m_solverBodyIdB = data.m_fixedBodyId;
+
+ if (m_rigidBodyA)
+ {
+ constraintRow.m_solverBodyIdA = m_rigidBodyA->getCompanionId();
+ }
+ if (m_rigidBodyB)
+ {
+ constraintRow.m_solverBodyIdB = m_rigidBodyB->getCompanionId();
+ }
+
+ btVector3 constraintNormalLin(0,0,0);
+ btVector3 constraintNormalAng(0,0,0);
+ btScalar posError = 0.0;
+ if (i < 2) {
+ constraintNormalLin = constraintAxis[i];
+ posError = (pivotAworld-pivotBworld).dot(constraintNormalLin);
+ fillMultiBodyConstraint(constraintRow, data, 0, 0, constraintNormalAng,
+ constraintNormalLin, pivotAworld, pivotBworld,
+ posError,
+ infoGlobal,
+ -m_maxAppliedImpulse, m_maxAppliedImpulse
+ );
+ }
+ else { //i>=2
+ constraintNormalAng = frameAworld.getColumn(i%3);
+ posError = angleDiff[i%3];
+ fillMultiBodyConstraint(constraintRow, data, 0, 0, constraintNormalAng,
+ constraintNormalLin, pivotAworld, pivotBworld,
+ posError,
+ infoGlobal,
+ -m_maxAppliedImpulse, m_maxAppliedImpulse, true
+ );
+ }
+ }
+}
+
+void btMultiBodySliderConstraint::debugDraw(class btIDebugDraw* drawer)
+{
+ btTransform tr;
+ tr.setIdentity();
+
+ if (m_rigidBodyA)
+ {
+ btVector3 pivot = m_rigidBodyA->getCenterOfMassTransform() * m_pivotInA;
+ tr.setOrigin(pivot);
+ drawer->drawTransform(tr, 0.1);
+ }
+ if (m_bodyA)
+ {
+ btVector3 pivotAworld = m_bodyA->localPosToWorld(m_linkA, m_pivotInA);
+ tr.setOrigin(pivotAworld);
+ drawer->drawTransform(tr, 0.1);
+ }
+ if (m_rigidBodyB)
+ {
+ // that ideally should draw the same frame
+ btVector3 pivot = m_rigidBodyB->getCenterOfMassTransform() * m_pivotInB;
+ tr.setOrigin(pivot);
+ drawer->drawTransform(tr, 0.1);
+ }
+ if (m_bodyB)
+ {
+ btVector3 pivotBworld = m_bodyB->localPosToWorld(m_linkB, m_pivotInB);
+ tr.setOrigin(pivotBworld);
+ drawer->drawTransform(tr, 0.1);
+ }
+}
diff --git a/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodySliderConstraint.h b/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodySliderConstraint.h
new file mode 100644
index 0000000000..0a6cf3df12
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodySliderConstraint.h
@@ -0,0 +1,105 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2013 Erwin Coumans 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.
+*/
+
+///This file was written by Erwin Coumans
+
+#ifndef BT_MULTIBODY_SLIDER_CONSTRAINT_H
+#define BT_MULTIBODY_SLIDER_CONSTRAINT_H
+
+#include "btMultiBodyConstraint.h"
+
+class btMultiBodySliderConstraint : public btMultiBodyConstraint
+{
+protected:
+
+ btRigidBody* m_rigidBodyA;
+ btRigidBody* m_rigidBodyB;
+ btVector3 m_pivotInA;
+ btVector3 m_pivotInB;
+ btMatrix3x3 m_frameInA;
+ btMatrix3x3 m_frameInB;
+ btVector3 m_jointAxis;
+
+public:
+
+ btMultiBodySliderConstraint(btMultiBody* body, int link, btRigidBody* bodyB, const btVector3& pivotInA, const btVector3& pivotInB, const btMatrix3x3& frameInA, const btMatrix3x3& frameInB, const btVector3& jointAxis);
+ btMultiBodySliderConstraint(btMultiBody* bodyA, int linkA, btMultiBody* bodyB, int linkB, const btVector3& pivotInA, const btVector3& pivotInB, const btMatrix3x3& frameInA, const btMatrix3x3& frameInB, const btVector3& jointAxis);
+
+ virtual ~btMultiBodySliderConstraint();
+
+ virtual void finalizeMultiDof();
+
+ virtual int getIslandIdA() const;
+ virtual int getIslandIdB() const;
+
+ virtual void createConstraintRows(btMultiBodyConstraintArray& constraintRows,
+ btMultiBodyJacobianData& data,
+ const btContactSolverInfo& infoGlobal);
+
+ const btVector3& getPivotInA() const
+ {
+ return m_pivotInA;
+ }
+
+ void setPivotInA(const btVector3& pivotInA)
+ {
+ m_pivotInA = pivotInA;
+ }
+
+ const btVector3& getPivotInB() const
+ {
+ return m_pivotInB;
+ }
+
+ virtual void setPivotInB(const btVector3& pivotInB)
+ {
+ m_pivotInB = pivotInB;
+ }
+
+ const btMatrix3x3& getFrameInA() const
+ {
+ return m_frameInA;
+ }
+
+ void setFrameInA(const btMatrix3x3& frameInA)
+ {
+ m_frameInA = frameInA;
+ }
+
+ const btMatrix3x3& getFrameInB() const
+ {
+ return m_frameInB;
+ }
+
+ virtual void setFrameInB(const btMatrix3x3& frameInB)
+ {
+ m_frameInB = frameInB;
+ }
+
+ const btVector3& getJointAxis() const
+ {
+ return m_jointAxis;
+ }
+
+ void setJointAxis(const btVector3& jointAxis)
+ {
+ m_jointAxis = jointAxis;
+ }
+
+ virtual void debugDraw(class btIDebugDraw* drawer);
+
+};
+
+#endif //BT_MULTIBODY_SLIDER_CONSTRAINT_H
diff --git a/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodySolverConstraint.h b/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodySolverConstraint.h
new file mode 100644
index 0000000000..6fa1550e9e
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/Featherstone/btMultiBodySolverConstraint.h
@@ -0,0 +1,90 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2013 Erwin Coumans 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_SOLVER_CONSTRAINT_H
+#define BT_MULTIBODY_SOLVER_CONSTRAINT_H
+
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btAlignedObjectArray.h"
+
+class btMultiBody;
+class btMultiBodyConstraint;
+#include "BulletDynamics/ConstraintSolver/btSolverBody.h"
+#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h"
+
+///1D constraint along a normal axis between bodyA and bodyB. It can be combined to solve contact and friction constraints.
+ATTRIBUTE_ALIGNED16 (struct) btMultiBodySolverConstraint
+{
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ btMultiBodySolverConstraint() : m_solverBodyIdA(-1), m_multiBodyA(0), m_linkA(-1), m_solverBodyIdB(-1), m_multiBodyB(0), m_linkB(-1),m_orgConstraint(0), m_orgDofIndex(-1)
+ {}
+
+ int m_deltaVelAindex;//more generic version of m_relpos1CrossNormal/m_contactNormal1
+ int m_jacAindex;
+ int m_deltaVelBindex;
+ int m_jacBindex;
+
+ btVector3 m_relpos1CrossNormal;
+ btVector3 m_contactNormal1;
+ btVector3 m_relpos2CrossNormal;
+ btVector3 m_contactNormal2; //usually m_contactNormal2 == -m_contactNormal1, but not always
+
+
+ btVector3 m_angularComponentA;
+ btVector3 m_angularComponentB;
+
+ mutable btSimdScalar m_appliedPushImpulse;
+ mutable btSimdScalar m_appliedImpulse;
+
+ btScalar m_friction;
+ btScalar m_jacDiagABInv;
+ btScalar m_rhs;
+ btScalar m_cfm;
+
+ btScalar m_lowerLimit;
+ btScalar m_upperLimit;
+ btScalar m_rhsPenetration;
+ union
+ {
+ void* m_originalContactPoint;
+ btScalar m_unusedPadding4;
+ };
+
+ int m_overrideNumSolverIterations;
+ int m_frictionIndex;
+
+ int m_solverBodyIdA;
+ btMultiBody* m_multiBodyA;
+ int m_linkA;
+
+ int m_solverBodyIdB;
+ btMultiBody* m_multiBodyB;
+ int m_linkB;
+
+ //for writing back applied impulses
+ btMultiBodyConstraint* m_orgConstraint;
+ int m_orgDofIndex;
+
+ enum btSolverConstraintType
+ {
+ BT_SOLVER_CONTACT_1D = 0,
+ BT_SOLVER_FRICTION_1D
+ };
+};
+
+typedef btAlignedObjectArray<btMultiBodySolverConstraint> btMultiBodyConstraintArray;
+
+#endif //BT_MULTIBODY_SOLVER_CONSTRAINT_H
diff --git a/thirdparty/bullet/src/BulletDynamics/MLCPSolvers/btDantzigLCP.cpp b/thirdparty/bullet/src/BulletDynamics/MLCPSolvers/btDantzigLCP.cpp
new file mode 100644
index 0000000000..986f214870
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/MLCPSolvers/btDantzigLCP.cpp
@@ -0,0 +1,2080 @@
+/*************************************************************************
+* *
+* Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
+* All rights reserved. Email: russ@q12.org Web: www.q12.org *
+* *
+* This library is free software; you can redistribute it and/or *
+* modify it under the terms of EITHER: *
+* (1) The GNU Lesser General Public License as published by the Free *
+* Software Foundation; either version 2.1 of the License, or (at *
+* your option) any later version. The text of the GNU Lesser *
+* General Public License is included with this library in the *
+* file LICENSE.TXT. *
+* (2) The BSD-style license that is included with this library in *
+* the file LICENSE-BSD.TXT. *
+* *
+* This library is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
+* LICENSE.TXT and LICENSE-BSD.TXT for more details. *
+* *
+*************************************************************************/
+
+/*
+
+
+THE ALGORITHM
+-------------
+
+solve A*x = b+w, with x and w subject to certain LCP conditions.
+each x(i),w(i) must lie on one of the three line segments in the following
+diagram. each line segment corresponds to one index set :
+
+ w(i)
+ /|\ | :
+ | | :
+ | |i in N :
+ w>0 | |state[i]=0 :
+ | | :
+ | | : i in C
+ w=0 + +-----------------------+
+ | : |
+ | : |
+ w<0 | : |i in N
+ | : |state[i]=1
+ | : |
+ | : |
+ +-------|-----------|-----------|----------> x(i)
+ lo 0 hi
+
+the Dantzig algorithm proceeds as follows:
+ for i=1:n
+ * if (x(i),w(i)) is not on the line, push x(i) and w(i) positive or
+ negative towards the line. as this is done, the other (x(j),w(j))
+ for j<i are constrained to be on the line. if any (x,w) reaches the
+ end of a line segment then it is switched between index sets.
+ * i is added to the appropriate index set depending on what line segment
+ it hits.
+
+we restrict lo(i) <= 0 and hi(i) >= 0. this makes the algorithm a bit
+simpler, because the starting point for x(i),w(i) is always on the dotted
+line x=0 and x will only ever increase in one direction, so it can only hit
+two out of the three line segments.
+
+
+NOTES
+-----
+
+this is an implementation of "lcp_dantzig2_ldlt.m" and "lcp_dantzig_lohi.m".
+the implementation is split into an LCP problem object (btLCP) and an LCP
+driver function. most optimization occurs in the btLCP object.
+
+a naive implementation of the algorithm requires either a lot of data motion
+or a lot of permutation-array lookup, because we are constantly re-ordering
+rows and columns. to avoid this and make a more optimized algorithm, a
+non-trivial data structure is used to represent the matrix A (this is
+implemented in the fast version of the btLCP object).
+
+during execution of this algorithm, some indexes in A are clamped (set C),
+some are non-clamped (set N), and some are "don't care" (where x=0).
+A,x,b,w (and other problem vectors) are permuted such that the clamped
+indexes are first, the unclamped indexes are next, and the don't-care
+indexes are last. this permutation is recorded in the array `p'.
+initially p = 0..n-1, and as the rows and columns of A,x,b,w are swapped,
+the corresponding elements of p are swapped.
+
+because the C and N elements are grouped together in the rows of A, we can do
+lots of work with a fast dot product function. if A,x,etc were not permuted
+and we only had a permutation array, then those dot products would be much
+slower as we would have a permutation array lookup in some inner loops.
+
+A is accessed through an array of row pointers, so that element (i,j) of the
+permuted matrix is A[i][j]. this makes row swapping fast. for column swapping
+we still have to actually move the data.
+
+during execution of this algorithm we maintain an L*D*L' factorization of
+the clamped submatrix of A (call it `AC') which is the top left nC*nC
+submatrix of A. there are two ways we could arrange the rows/columns in AC.
+
+(1) AC is always permuted such that L*D*L' = AC. this causes a problem
+when a row/column is removed from C, because then all the rows/columns of A
+between the deleted index and the end of C need to be rotated downward.
+this results in a lot of data motion and slows things down.
+(2) L*D*L' is actually a factorization of a *permutation* of AC (which is
+itself a permutation of the underlying A). this is what we do - the
+permutation is recorded in the vector C. call this permutation A[C,C].
+when a row/column is removed from C, all we have to do is swap two
+rows/columns and manipulate C.
+
+*/
+
+
+#include "btDantzigLCP.h"
+
+#include <string.h>//memcpy
+
+bool s_error = false;
+
+//***************************************************************************
+// code generation parameters
+
+
+#define btLCP_FAST // use fast btLCP object
+
+// option 1 : matrix row pointers (less data copying)
+#define BTROWPTRS
+#define BTATYPE btScalar **
+#define BTAROW(i) (m_A[i])
+
+// option 2 : no matrix row pointers (slightly faster inner loops)
+//#define NOROWPTRS
+//#define BTATYPE btScalar *
+//#define BTAROW(i) (m_A+(i)*m_nskip)
+
+#define BTNUB_OPTIMIZATIONS
+
+
+
+/* solve L*X=B, with B containing 1 right hand sides.
+ * L is an n*n lower triangular matrix with ones on the diagonal.
+ * L is stored by rows and its leading dimension is lskip.
+ * B is an n*1 matrix that contains the right hand sides.
+ * B is stored by columns and its leading dimension is also lskip.
+ * B is overwritten with X.
+ * this processes blocks of 2*2.
+ * if this is in the factorizer source file, n must be a multiple of 2.
+ */
+
+static void btSolveL1_1 (const btScalar *L, btScalar *B, int n, int lskip1)
+{
+ /* declare variables - Z matrix, p and q vectors, etc */
+ btScalar Z11,m11,Z21,m21,p1,q1,p2,*ex;
+ const btScalar *ell;
+ int i,j;
+ /* compute all 2 x 1 blocks of X */
+ for (i=0; i < n; i+=2) {
+ /* compute all 2 x 1 block of X, from rows i..i+2-1 */
+ /* set the Z matrix to 0 */
+ Z11=0;
+ Z21=0;
+ ell = L + i*lskip1;
+ ex = B;
+ /* the inner loop that computes outer products and adds them to Z */
+ for (j=i-2; j >= 0; j -= 2) {
+ /* compute outer product and add it to the Z matrix */
+ p1=ell[0];
+ q1=ex[0];
+ m11 = p1 * q1;
+ p2=ell[lskip1];
+ m21 = p2 * q1;
+ Z11 += m11;
+ Z21 += m21;
+ /* compute outer product and add it to the Z matrix */
+ p1=ell[1];
+ q1=ex[1];
+ m11 = p1 * q1;
+ p2=ell[1+lskip1];
+ m21 = p2 * q1;
+ /* advance pointers */
+ ell += 2;
+ ex += 2;
+ Z11 += m11;
+ Z21 += m21;
+ /* end of inner loop */
+ }
+ /* compute left-over iterations */
+ j += 2;
+ for (; j > 0; j--) {
+ /* compute outer product and add it to the Z matrix */
+ p1=ell[0];
+ q1=ex[0];
+ m11 = p1 * q1;
+ p2=ell[lskip1];
+ m21 = p2 * q1;
+ /* advance pointers */
+ ell += 1;
+ ex += 1;
+ Z11 += m11;
+ Z21 += m21;
+ }
+ /* finish computing the X(i) block */
+ Z11 = ex[0] - Z11;
+ ex[0] = Z11;
+ p1 = ell[lskip1];
+ Z21 = ex[1] - Z21 - p1*Z11;
+ ex[1] = Z21;
+ /* end of outer loop */
+ }
+}
+
+/* solve L*X=B, with B containing 2 right hand sides.
+ * L is an n*n lower triangular matrix with ones on the diagonal.
+ * L is stored by rows and its leading dimension is lskip.
+ * B is an n*2 matrix that contains the right hand sides.
+ * B is stored by columns and its leading dimension is also lskip.
+ * B is overwritten with X.
+ * this processes blocks of 2*2.
+ * if this is in the factorizer source file, n must be a multiple of 2.
+ */
+
+static void btSolveL1_2 (const btScalar *L, btScalar *B, int n, int lskip1)
+{
+ /* declare variables - Z matrix, p and q vectors, etc */
+ btScalar Z11,m11,Z12,m12,Z21,m21,Z22,m22,p1,q1,p2,q2,*ex;
+ const btScalar *ell;
+ int i,j;
+ /* compute all 2 x 2 blocks of X */
+ for (i=0; i < n; i+=2) {
+ /* compute all 2 x 2 block of X, from rows i..i+2-1 */
+ /* set the Z matrix to 0 */
+ Z11=0;
+ Z12=0;
+ Z21=0;
+ Z22=0;
+ ell = L + i*lskip1;
+ ex = B;
+ /* the inner loop that computes outer products and adds them to Z */
+ for (j=i-2; j >= 0; j -= 2) {
+ /* compute outer product and add it to the Z matrix */
+ p1=ell[0];
+ q1=ex[0];
+ m11 = p1 * q1;
+ q2=ex[lskip1];
+ m12 = p1 * q2;
+ p2=ell[lskip1];
+ m21 = p2 * q1;
+ m22 = p2 * q2;
+ Z11 += m11;
+ Z12 += m12;
+ Z21 += m21;
+ Z22 += m22;
+ /* compute outer product and add it to the Z matrix */
+ p1=ell[1];
+ q1=ex[1];
+ m11 = p1 * q1;
+ q2=ex[1+lskip1];
+ m12 = p1 * q2;
+ p2=ell[1+lskip1];
+ m21 = p2 * q1;
+ m22 = p2 * q2;
+ /* advance pointers */
+ ell += 2;
+ ex += 2;
+ Z11 += m11;
+ Z12 += m12;
+ Z21 += m21;
+ Z22 += m22;
+ /* end of inner loop */
+ }
+ /* compute left-over iterations */
+ j += 2;
+ for (; j > 0; j--) {
+ /* compute outer product and add it to the Z matrix */
+ p1=ell[0];
+ q1=ex[0];
+ m11 = p1 * q1;
+ q2=ex[lskip1];
+ m12 = p1 * q2;
+ p2=ell[lskip1];
+ m21 = p2 * q1;
+ m22 = p2 * q2;
+ /* advance pointers */
+ ell += 1;
+ ex += 1;
+ Z11 += m11;
+ Z12 += m12;
+ Z21 += m21;
+ Z22 += m22;
+ }
+ /* finish computing the X(i) block */
+ Z11 = ex[0] - Z11;
+ ex[0] = Z11;
+ Z12 = ex[lskip1] - Z12;
+ ex[lskip1] = Z12;
+ p1 = ell[lskip1];
+ Z21 = ex[1] - Z21 - p1*Z11;
+ ex[1] = Z21;
+ Z22 = ex[1+lskip1] - Z22 - p1*Z12;
+ ex[1+lskip1] = Z22;
+ /* end of outer loop */
+ }
+}
+
+
+void btFactorLDLT (btScalar *A, btScalar *d, int n, int nskip1)
+{
+ int i,j;
+ btScalar sum,*ell,*dee,dd,p1,p2,q1,q2,Z11,m11,Z21,m21,Z22,m22;
+ if (n < 1) return;
+
+ for (i=0; i<=n-2; i += 2) {
+ /* solve L*(D*l)=a, l is scaled elements in 2 x i block at A(i,0) */
+ btSolveL1_2 (A,A+i*nskip1,i,nskip1);
+ /* scale the elements in a 2 x i block at A(i,0), and also */
+ /* compute Z = the outer product matrix that we'll need. */
+ Z11 = 0;
+ Z21 = 0;
+ Z22 = 0;
+ ell = A+i*nskip1;
+ dee = d;
+ for (j=i-6; j >= 0; j -= 6) {
+ p1 = ell[0];
+ p2 = ell[nskip1];
+ dd = dee[0];
+ q1 = p1*dd;
+ q2 = p2*dd;
+ ell[0] = q1;
+ ell[nskip1] = q2;
+ m11 = p1*q1;
+ m21 = p2*q1;
+ m22 = p2*q2;
+ Z11 += m11;
+ Z21 += m21;
+ Z22 += m22;
+ p1 = ell[1];
+ p2 = ell[1+nskip1];
+ dd = dee[1];
+ q1 = p1*dd;
+ q2 = p2*dd;
+ ell[1] = q1;
+ ell[1+nskip1] = q2;
+ m11 = p1*q1;
+ m21 = p2*q1;
+ m22 = p2*q2;
+ Z11 += m11;
+ Z21 += m21;
+ Z22 += m22;
+ p1 = ell[2];
+ p2 = ell[2+nskip1];
+ dd = dee[2];
+ q1 = p1*dd;
+ q2 = p2*dd;
+ ell[2] = q1;
+ ell[2+nskip1] = q2;
+ m11 = p1*q1;
+ m21 = p2*q1;
+ m22 = p2*q2;
+ Z11 += m11;
+ Z21 += m21;
+ Z22 += m22;
+ p1 = ell[3];
+ p2 = ell[3+nskip1];
+ dd = dee[3];
+ q1 = p1*dd;
+ q2 = p2*dd;
+ ell[3] = q1;
+ ell[3+nskip1] = q2;
+ m11 = p1*q1;
+ m21 = p2*q1;
+ m22 = p2*q2;
+ Z11 += m11;
+ Z21 += m21;
+ Z22 += m22;
+ p1 = ell[4];
+ p2 = ell[4+nskip1];
+ dd = dee[4];
+ q1 = p1*dd;
+ q2 = p2*dd;
+ ell[4] = q1;
+ ell[4+nskip1] = q2;
+ m11 = p1*q1;
+ m21 = p2*q1;
+ m22 = p2*q2;
+ Z11 += m11;
+ Z21 += m21;
+ Z22 += m22;
+ p1 = ell[5];
+ p2 = ell[5+nskip1];
+ dd = dee[5];
+ q1 = p1*dd;
+ q2 = p2*dd;
+ ell[5] = q1;
+ ell[5+nskip1] = q2;
+ m11 = p1*q1;
+ m21 = p2*q1;
+ m22 = p2*q2;
+ Z11 += m11;
+ Z21 += m21;
+ Z22 += m22;
+ ell += 6;
+ dee += 6;
+ }
+ /* compute left-over iterations */
+ j += 6;
+ for (; j > 0; j--) {
+ p1 = ell[0];
+ p2 = ell[nskip1];
+ dd = dee[0];
+ q1 = p1*dd;
+ q2 = p2*dd;
+ ell[0] = q1;
+ ell[nskip1] = q2;
+ m11 = p1*q1;
+ m21 = p2*q1;
+ m22 = p2*q2;
+ Z11 += m11;
+ Z21 += m21;
+ Z22 += m22;
+ ell++;
+ dee++;
+ }
+ /* solve for diagonal 2 x 2 block at A(i,i) */
+ Z11 = ell[0] - Z11;
+ Z21 = ell[nskip1] - Z21;
+ Z22 = ell[1+nskip1] - Z22;
+ dee = d + i;
+ /* factorize 2 x 2 block Z,dee */
+ /* factorize row 1 */
+ dee[0] = btRecip(Z11);
+ /* factorize row 2 */
+ sum = 0;
+ q1 = Z21;
+ q2 = q1 * dee[0];
+ Z21 = q2;
+ sum += q1*q2;
+ dee[1] = btRecip(Z22 - sum);
+ /* done factorizing 2 x 2 block */
+ ell[nskip1] = Z21;
+ }
+ /* compute the (less than 2) rows at the bottom */
+ switch (n-i) {
+ case 0:
+ break;
+
+ case 1:
+ btSolveL1_1 (A,A+i*nskip1,i,nskip1);
+ /* scale the elements in a 1 x i block at A(i,0), and also */
+ /* compute Z = the outer product matrix that we'll need. */
+ Z11 = 0;
+ ell = A+i*nskip1;
+ dee = d;
+ for (j=i-6; j >= 0; j -= 6) {
+ p1 = ell[0];
+ dd = dee[0];
+ q1 = p1*dd;
+ ell[0] = q1;
+ m11 = p1*q1;
+ Z11 += m11;
+ p1 = ell[1];
+ dd = dee[1];
+ q1 = p1*dd;
+ ell[1] = q1;
+ m11 = p1*q1;
+ Z11 += m11;
+ p1 = ell[2];
+ dd = dee[2];
+ q1 = p1*dd;
+ ell[2] = q1;
+ m11 = p1*q1;
+ Z11 += m11;
+ p1 = ell[3];
+ dd = dee[3];
+ q1 = p1*dd;
+ ell[3] = q1;
+ m11 = p1*q1;
+ Z11 += m11;
+ p1 = ell[4];
+ dd = dee[4];
+ q1 = p1*dd;
+ ell[4] = q1;
+ m11 = p1*q1;
+ Z11 += m11;
+ p1 = ell[5];
+ dd = dee[5];
+ q1 = p1*dd;
+ ell[5] = q1;
+ m11 = p1*q1;
+ Z11 += m11;
+ ell += 6;
+ dee += 6;
+ }
+ /* compute left-over iterations */
+ j += 6;
+ for (; j > 0; j--) {
+ p1 = ell[0];
+ dd = dee[0];
+ q1 = p1*dd;
+ ell[0] = q1;
+ m11 = p1*q1;
+ Z11 += m11;
+ ell++;
+ dee++;
+ }
+ /* solve for diagonal 1 x 1 block at A(i,i) */
+ Z11 = ell[0] - Z11;
+ dee = d + i;
+ /* factorize 1 x 1 block Z,dee */
+ /* factorize row 1 */
+ dee[0] = btRecip(Z11);
+ /* done factorizing 1 x 1 block */
+ break;
+
+ //default: *((char*)0)=0; /* this should never happen! */
+ }
+}
+
+/* solve L*X=B, with B containing 1 right hand sides.
+ * L is an n*n lower triangular matrix with ones on the diagonal.
+ * L is stored by rows and its leading dimension is lskip.
+ * B is an n*1 matrix that contains the right hand sides.
+ * B is stored by columns and its leading dimension is also lskip.
+ * B is overwritten with X.
+ * this processes blocks of 4*4.
+ * if this is in the factorizer source file, n must be a multiple of 4.
+ */
+
+void btSolveL1 (const btScalar *L, btScalar *B, int n, int lskip1)
+{
+ /* declare variables - Z matrix, p and q vectors, etc */
+ btScalar Z11,Z21,Z31,Z41,p1,q1,p2,p3,p4,*ex;
+ const btScalar *ell;
+ int lskip2,lskip3,i,j;
+ /* compute lskip values */
+ lskip2 = 2*lskip1;
+ lskip3 = 3*lskip1;
+ /* compute all 4 x 1 blocks of X */
+ for (i=0; i <= n-4; i+=4) {
+ /* compute all 4 x 1 block of X, from rows i..i+4-1 */
+ /* set the Z matrix to 0 */
+ Z11=0;
+ Z21=0;
+ Z31=0;
+ Z41=0;
+ ell = L + i*lskip1;
+ ex = B;
+ /* the inner loop that computes outer products and adds them to Z */
+ for (j=i-12; j >= 0; j -= 12) {
+ /* load p and q values */
+ p1=ell[0];
+ q1=ex[0];
+ p2=ell[lskip1];
+ p3=ell[lskip2];
+ p4=ell[lskip3];
+ /* compute outer product and add it to the Z matrix */
+ Z11 += p1 * q1;
+ Z21 += p2 * q1;
+ Z31 += p3 * q1;
+ Z41 += p4 * q1;
+ /* load p and q values */
+ p1=ell[1];
+ q1=ex[1];
+ p2=ell[1+lskip1];
+ p3=ell[1+lskip2];
+ p4=ell[1+lskip3];
+ /* compute outer product and add it to the Z matrix */
+ Z11 += p1 * q1;
+ Z21 += p2 * q1;
+ Z31 += p3 * q1;
+ Z41 += p4 * q1;
+ /* load p and q values */
+ p1=ell[2];
+ q1=ex[2];
+ p2=ell[2+lskip1];
+ p3=ell[2+lskip2];
+ p4=ell[2+lskip3];
+ /* compute outer product and add it to the Z matrix */
+ Z11 += p1 * q1;
+ Z21 += p2 * q1;
+ Z31 += p3 * q1;
+ Z41 += p4 * q1;
+ /* load p and q values */
+ p1=ell[3];
+ q1=ex[3];
+ p2=ell[3+lskip1];
+ p3=ell[3+lskip2];
+ p4=ell[3+lskip3];
+ /* compute outer product and add it to the Z matrix */
+ Z11 += p1 * q1;
+ Z21 += p2 * q1;
+ Z31 += p3 * q1;
+ Z41 += p4 * q1;
+ /* load p and q values */
+ p1=ell[4];
+ q1=ex[4];
+ p2=ell[4+lskip1];
+ p3=ell[4+lskip2];
+ p4=ell[4+lskip3];
+ /* compute outer product and add it to the Z matrix */
+ Z11 += p1 * q1;
+ Z21 += p2 * q1;
+ Z31 += p3 * q1;
+ Z41 += p4 * q1;
+ /* load p and q values */
+ p1=ell[5];
+ q1=ex[5];
+ p2=ell[5+lskip1];
+ p3=ell[5+lskip2];
+ p4=ell[5+lskip3];
+ /* compute outer product and add it to the Z matrix */
+ Z11 += p1 * q1;
+ Z21 += p2 * q1;
+ Z31 += p3 * q1;
+ Z41 += p4 * q1;
+ /* load p and q values */
+ p1=ell[6];
+ q1=ex[6];
+ p2=ell[6+lskip1];
+ p3=ell[6+lskip2];
+ p4=ell[6+lskip3];
+ /* compute outer product and add it to the Z matrix */
+ Z11 += p1 * q1;
+ Z21 += p2 * q1;
+ Z31 += p3 * q1;
+ Z41 += p4 * q1;
+ /* load p and q values */
+ p1=ell[7];
+ q1=ex[7];
+ p2=ell[7+lskip1];
+ p3=ell[7+lskip2];
+ p4=ell[7+lskip3];
+ /* compute outer product and add it to the Z matrix */
+ Z11 += p1 * q1;
+ Z21 += p2 * q1;
+ Z31 += p3 * q1;
+ Z41 += p4 * q1;
+ /* load p and q values */
+ p1=ell[8];
+ q1=ex[8];
+ p2=ell[8+lskip1];
+ p3=ell[8+lskip2];
+ p4=ell[8+lskip3];
+ /* compute outer product and add it to the Z matrix */
+ Z11 += p1 * q1;
+ Z21 += p2 * q1;
+ Z31 += p3 * q1;
+ Z41 += p4 * q1;
+ /* load p and q values */
+ p1=ell[9];
+ q1=ex[9];
+ p2=ell[9+lskip1];
+ p3=ell[9+lskip2];
+ p4=ell[9+lskip3];
+ /* compute outer product and add it to the Z matrix */
+ Z11 += p1 * q1;
+ Z21 += p2 * q1;
+ Z31 += p3 * q1;
+ Z41 += p4 * q1;
+ /* load p and q values */
+ p1=ell[10];
+ q1=ex[10];
+ p2=ell[10+lskip1];
+ p3=ell[10+lskip2];
+ p4=ell[10+lskip3];
+ /* compute outer product and add it to the Z matrix */
+ Z11 += p1 * q1;
+ Z21 += p2 * q1;
+ Z31 += p3 * q1;
+ Z41 += p4 * q1;
+ /* load p and q values */
+ p1=ell[11];
+ q1=ex[11];
+ p2=ell[11+lskip1];
+ p3=ell[11+lskip2];
+ p4=ell[11+lskip3];
+ /* compute outer product and add it to the Z matrix */
+ Z11 += p1 * q1;
+ Z21 += p2 * q1;
+ Z31 += p3 * q1;
+ Z41 += p4 * q1;
+ /* advance pointers */
+ ell += 12;
+ ex += 12;
+ /* end of inner loop */
+ }
+ /* compute left-over iterations */
+ j += 12;
+ for (; j > 0; j--) {
+ /* load p and q values */
+ p1=ell[0];
+ q1=ex[0];
+ p2=ell[lskip1];
+ p3=ell[lskip2];
+ p4=ell[lskip3];
+ /* compute outer product and add it to the Z matrix */
+ Z11 += p1 * q1;
+ Z21 += p2 * q1;
+ Z31 += p3 * q1;
+ Z41 += p4 * q1;
+ /* advance pointers */
+ ell += 1;
+ ex += 1;
+ }
+ /* finish computing the X(i) block */
+ Z11 = ex[0] - Z11;
+ ex[0] = Z11;
+ p1 = ell[lskip1];
+ Z21 = ex[1] - Z21 - p1*Z11;
+ ex[1] = Z21;
+ p1 = ell[lskip2];
+ p2 = ell[1+lskip2];
+ Z31 = ex[2] - Z31 - p1*Z11 - p2*Z21;
+ ex[2] = Z31;
+ p1 = ell[lskip3];
+ p2 = ell[1+lskip3];
+ p3 = ell[2+lskip3];
+ Z41 = ex[3] - Z41 - p1*Z11 - p2*Z21 - p3*Z31;
+ ex[3] = Z41;
+ /* end of outer loop */
+ }
+ /* compute rows at end that are not a multiple of block size */
+ for (; i < n; i++) {
+ /* compute all 1 x 1 block of X, from rows i..i+1-1 */
+ /* set the Z matrix to 0 */
+ Z11=0;
+ ell = L + i*lskip1;
+ ex = B;
+ /* the inner loop that computes outer products and adds them to Z */
+ for (j=i-12; j >= 0; j -= 12) {
+ /* load p and q values */
+ p1=ell[0];
+ q1=ex[0];
+ /* compute outer product and add it to the Z matrix */
+ Z11 += p1 * q1;
+ /* load p and q values */
+ p1=ell[1];
+ q1=ex[1];
+ /* compute outer product and add it to the Z matrix */
+ Z11 += p1 * q1;
+ /* load p and q values */
+ p1=ell[2];
+ q1=ex[2];
+ /* compute outer product and add it to the Z matrix */
+ Z11 += p1 * q1;
+ /* load p and q values */
+ p1=ell[3];
+ q1=ex[3];
+ /* compute outer product and add it to the Z matrix */
+ Z11 += p1 * q1;
+ /* load p and q values */
+ p1=ell[4];
+ q1=ex[4];
+ /* compute outer product and add it to the Z matrix */
+ Z11 += p1 * q1;
+ /* load p and q values */
+ p1=ell[5];
+ q1=ex[5];
+ /* compute outer product and add it to the Z matrix */
+ Z11 += p1 * q1;
+ /* load p and q values */
+ p1=ell[6];
+ q1=ex[6];
+ /* compute outer product and add it to the Z matrix */
+ Z11 += p1 * q1;
+ /* load p and q values */
+ p1=ell[7];
+ q1=ex[7];
+ /* compute outer product and add it to the Z matrix */
+ Z11 += p1 * q1;
+ /* load p and q values */
+ p1=ell[8];
+ q1=ex[8];
+ /* compute outer product and add it to the Z matrix */
+ Z11 += p1 * q1;
+ /* load p and q values */
+ p1=ell[9];
+ q1=ex[9];
+ /* compute outer product and add it to the Z matrix */
+ Z11 += p1 * q1;
+ /* load p and q values */
+ p1=ell[10];
+ q1=ex[10];
+ /* compute outer product and add it to the Z matrix */
+ Z11 += p1 * q1;
+ /* load p and q values */
+ p1=ell[11];
+ q1=ex[11];
+ /* compute outer product and add it to the Z matrix */
+ Z11 += p1 * q1;
+ /* advance pointers */
+ ell += 12;
+ ex += 12;
+ /* end of inner loop */
+ }
+ /* compute left-over iterations */
+ j += 12;
+ for (; j > 0; j--) {
+ /* load p and q values */
+ p1=ell[0];
+ q1=ex[0];
+ /* compute outer product and add it to the Z matrix */
+ Z11 += p1 * q1;
+ /* advance pointers */
+ ell += 1;
+ ex += 1;
+ }
+ /* finish computing the X(i) block */
+ Z11 = ex[0] - Z11;
+ ex[0] = Z11;
+ }
+}
+
+/* solve L^T * x=b, with b containing 1 right hand side.
+ * L is an n*n lower triangular matrix with ones on the diagonal.
+ * L is stored by rows and its leading dimension is lskip.
+ * b is an n*1 matrix that contains the right hand side.
+ * b is overwritten with x.
+ * this processes blocks of 4.
+ */
+
+void btSolveL1T (const btScalar *L, btScalar *B, int n, int lskip1)
+{
+ /* declare variables - Z matrix, p and q vectors, etc */
+ btScalar Z11,m11,Z21,m21,Z31,m31,Z41,m41,p1,q1,p2,p3,p4,*ex;
+ const btScalar *ell;
+ int lskip2,i,j;
+// int lskip3;
+ /* special handling for L and B because we're solving L1 *transpose* */
+ L = L + (n-1)*(lskip1+1);
+ B = B + n-1;
+ lskip1 = -lskip1;
+ /* compute lskip values */
+ lskip2 = 2*lskip1;
+ //lskip3 = 3*lskip1;
+ /* compute all 4 x 1 blocks of X */
+ for (i=0; i <= n-4; i+=4) {
+ /* compute all 4 x 1 block of X, from rows i..i+4-1 */
+ /* set the Z matrix to 0 */
+ Z11=0;
+ Z21=0;
+ Z31=0;
+ Z41=0;
+ ell = L - i;
+ ex = B;
+ /* the inner loop that computes outer products and adds them to Z */
+ for (j=i-4; j >= 0; j -= 4) {
+ /* load p and q values */
+ p1=ell[0];
+ q1=ex[0];
+ p2=ell[-1];
+ p3=ell[-2];
+ p4=ell[-3];
+ /* compute outer product and add it to the Z matrix */
+ m11 = p1 * q1;
+ m21 = p2 * q1;
+ m31 = p3 * q1;
+ m41 = p4 * q1;
+ ell += lskip1;
+ Z11 += m11;
+ Z21 += m21;
+ Z31 += m31;
+ Z41 += m41;
+ /* load p and q values */
+ p1=ell[0];
+ q1=ex[-1];
+ p2=ell[-1];
+ p3=ell[-2];
+ p4=ell[-3];
+ /* compute outer product and add it to the Z matrix */
+ m11 = p1 * q1;
+ m21 = p2 * q1;
+ m31 = p3 * q1;
+ m41 = p4 * q1;
+ ell += lskip1;
+ Z11 += m11;
+ Z21 += m21;
+ Z31 += m31;
+ Z41 += m41;
+ /* load p and q values */
+ p1=ell[0];
+ q1=ex[-2];
+ p2=ell[-1];
+ p3=ell[-2];
+ p4=ell[-3];
+ /* compute outer product and add it to the Z matrix */
+ m11 = p1 * q1;
+ m21 = p2 * q1;
+ m31 = p3 * q1;
+ m41 = p4 * q1;
+ ell += lskip1;
+ Z11 += m11;
+ Z21 += m21;
+ Z31 += m31;
+ Z41 += m41;
+ /* load p and q values */
+ p1=ell[0];
+ q1=ex[-3];
+ p2=ell[-1];
+ p3=ell[-2];
+ p4=ell[-3];
+ /* compute outer product and add it to the Z matrix */
+ m11 = p1 * q1;
+ m21 = p2 * q1;
+ m31 = p3 * q1;
+ m41 = p4 * q1;
+ ell += lskip1;
+ ex -= 4;
+ Z11 += m11;
+ Z21 += m21;
+ Z31 += m31;
+ Z41 += m41;
+ /* end of inner loop */
+ }
+ /* compute left-over iterations */
+ j += 4;
+ for (; j > 0; j--) {
+ /* load p and q values */
+ p1=ell[0];
+ q1=ex[0];
+ p2=ell[-1];
+ p3=ell[-2];
+ p4=ell[-3];
+ /* compute outer product and add it to the Z matrix */
+ m11 = p1 * q1;
+ m21 = p2 * q1;
+ m31 = p3 * q1;
+ m41 = p4 * q1;
+ ell += lskip1;
+ ex -= 1;
+ Z11 += m11;
+ Z21 += m21;
+ Z31 += m31;
+ Z41 += m41;
+ }
+ /* finish computing the X(i) block */
+ Z11 = ex[0] - Z11;
+ ex[0] = Z11;
+ p1 = ell[-1];
+ Z21 = ex[-1] - Z21 - p1*Z11;
+ ex[-1] = Z21;
+ p1 = ell[-2];
+ p2 = ell[-2+lskip1];
+ Z31 = ex[-2] - Z31 - p1*Z11 - p2*Z21;
+ ex[-2] = Z31;
+ p1 = ell[-3];
+ p2 = ell[-3+lskip1];
+ p3 = ell[-3+lskip2];
+ Z41 = ex[-3] - Z41 - p1*Z11 - p2*Z21 - p3*Z31;
+ ex[-3] = Z41;
+ /* end of outer loop */
+ }
+ /* compute rows at end that are not a multiple of block size */
+ for (; i < n; i++) {
+ /* compute all 1 x 1 block of X, from rows i..i+1-1 */
+ /* set the Z matrix to 0 */
+ Z11=0;
+ ell = L - i;
+ ex = B;
+ /* the inner loop that computes outer products and adds them to Z */
+ for (j=i-4; j >= 0; j -= 4) {
+ /* load p and q values */
+ p1=ell[0];
+ q1=ex[0];
+ /* compute outer product and add it to the Z matrix */
+ m11 = p1 * q1;
+ ell += lskip1;
+ Z11 += m11;
+ /* load p and q values */
+ p1=ell[0];
+ q1=ex[-1];
+ /* compute outer product and add it to the Z matrix */
+ m11 = p1 * q1;
+ ell += lskip1;
+ Z11 += m11;
+ /* load p and q values */
+ p1=ell[0];
+ q1=ex[-2];
+ /* compute outer product and add it to the Z matrix */
+ m11 = p1 * q1;
+ ell += lskip1;
+ Z11 += m11;
+ /* load p and q values */
+ p1=ell[0];
+ q1=ex[-3];
+ /* compute outer product and add it to the Z matrix */
+ m11 = p1 * q1;
+ ell += lskip1;
+ ex -= 4;
+ Z11 += m11;
+ /* end of inner loop */
+ }
+ /* compute left-over iterations */
+ j += 4;
+ for (; j > 0; j--) {
+ /* load p and q values */
+ p1=ell[0];
+ q1=ex[0];
+ /* compute outer product and add it to the Z matrix */
+ m11 = p1 * q1;
+ ell += lskip1;
+ ex -= 1;
+ Z11 += m11;
+ }
+ /* finish computing the X(i) block */
+ Z11 = ex[0] - Z11;
+ ex[0] = Z11;
+ }
+}
+
+
+
+void btVectorScale (btScalar *a, const btScalar *d, int n)
+{
+ btAssert (a && d && n >= 0);
+ for (int i=0; i<n; i++) {
+ a[i] *= d[i];
+ }
+}
+
+void btSolveLDLT (const btScalar *L, const btScalar *d, btScalar *b, int n, int nskip)
+{
+ btAssert (L && d && b && n > 0 && nskip >= n);
+ btSolveL1 (L,b,n,nskip);
+ btVectorScale (b,d,n);
+ btSolveL1T (L,b,n,nskip);
+}
+
+
+
+//***************************************************************************
+
+// swap row/column i1 with i2 in the n*n matrix A. the leading dimension of
+// A is nskip. this only references and swaps the lower triangle.
+// if `do_fast_row_swaps' is nonzero and row pointers are being used, then
+// rows will be swapped by exchanging row pointers. otherwise the data will
+// be copied.
+
+static void btSwapRowsAndCols (BTATYPE A, int n, int i1, int i2, int nskip,
+ int do_fast_row_swaps)
+{
+ btAssert (A && n > 0 && i1 >= 0 && i2 >= 0 && i1 < n && i2 < n &&
+ nskip >= n && i1 < i2);
+
+# ifdef BTROWPTRS
+ btScalar *A_i1 = A[i1];
+ btScalar *A_i2 = A[i2];
+ for (int i=i1+1; i<i2; ++i) {
+ btScalar *A_i_i1 = A[i] + i1;
+ A_i1[i] = *A_i_i1;
+ *A_i_i1 = A_i2[i];
+ }
+ A_i1[i2] = A_i1[i1];
+ A_i1[i1] = A_i2[i1];
+ A_i2[i1] = A_i2[i2];
+ // swap rows, by swapping row pointers
+ if (do_fast_row_swaps) {
+ A[i1] = A_i2;
+ A[i2] = A_i1;
+ }
+ else {
+ // Only swap till i2 column to match A plain storage variant.
+ for (int k = 0; k <= i2; ++k) {
+ btScalar tmp = A_i1[k];
+ A_i1[k] = A_i2[k];
+ A_i2[k] = tmp;
+ }
+ }
+ // swap columns the hard way
+ for (int j=i2+1; j<n; ++j) {
+ btScalar *A_j = A[j];
+ btScalar tmp = A_j[i1];
+ A_j[i1] = A_j[i2];
+ A_j[i2] = tmp;
+ }
+# else
+ btScalar *A_i1 = A+i1*nskip;
+ btScalar *A_i2 = A+i2*nskip;
+ for (int k = 0; k < i1; ++k) {
+ btScalar tmp = A_i1[k];
+ A_i1[k] = A_i2[k];
+ A_i2[k] = tmp;
+ }
+ btScalar *A_i = A_i1 + nskip;
+ for (int i=i1+1; i<i2; A_i+=nskip, ++i) {
+ btScalar tmp = A_i2[i];
+ A_i2[i] = A_i[i1];
+ A_i[i1] = tmp;
+ }
+ {
+ btScalar tmp = A_i1[i1];
+ A_i1[i1] = A_i2[i2];
+ A_i2[i2] = tmp;
+ }
+ btScalar *A_j = A_i2 + nskip;
+ for (int j=i2+1; j<n; A_j+=nskip, ++j) {
+ btScalar tmp = A_j[i1];
+ A_j[i1] = A_j[i2];
+ A_j[i2] = tmp;
+ }
+# endif
+}
+
+
+// swap two indexes in the n*n LCP problem. i1 must be <= i2.
+
+static void btSwapProblem (BTATYPE A, btScalar *x, btScalar *b, btScalar *w, btScalar *lo,
+ btScalar *hi, int *p, bool *state, int *findex,
+ int n, int i1, int i2, int nskip,
+ int do_fast_row_swaps)
+{
+ btScalar tmpr;
+ int tmpi;
+ bool tmpb;
+ btAssert (n>0 && i1 >=0 && i2 >= 0 && i1 < n && i2 < n && nskip >= n && i1 <= i2);
+ if (i1==i2) return;
+
+ btSwapRowsAndCols (A,n,i1,i2,nskip,do_fast_row_swaps);
+
+ tmpr = x[i1];
+ x[i1] = x[i2];
+ x[i2] = tmpr;
+
+ tmpr = b[i1];
+ b[i1] = b[i2];
+ b[i2] = tmpr;
+
+ tmpr = w[i1];
+ w[i1] = w[i2];
+ w[i2] = tmpr;
+
+ tmpr = lo[i1];
+ lo[i1] = lo[i2];
+ lo[i2] = tmpr;
+
+ tmpr = hi[i1];
+ hi[i1] = hi[i2];
+ hi[i2] = tmpr;
+
+ tmpi = p[i1];
+ p[i1] = p[i2];
+ p[i2] = tmpi;
+
+ tmpb = state[i1];
+ state[i1] = state[i2];
+ state[i2] = tmpb;
+
+ if (findex) {
+ tmpi = findex[i1];
+ findex[i1] = findex[i2];
+ findex[i2] = tmpi;
+ }
+}
+
+
+
+
+//***************************************************************************
+// btLCP manipulator object. this represents an n*n LCP problem.
+//
+// two index sets C and N are kept. each set holds a subset of
+// the variable indexes 0..n-1. an index can only be in one set.
+// initially both sets are empty.
+//
+// the index set C is special: solutions to A(C,C)\A(C,i) can be generated.
+
+//***************************************************************************
+// fast implementation of btLCP. see the above definition of btLCP for
+// interface comments.
+//
+// `p' records the permutation of A,x,b,w,etc. p is initially 1:n and is
+// permuted as the other vectors/matrices are permuted.
+//
+// A,x,b,w,lo,hi,state,findex,p,c are permuted such that sets C,N have
+// contiguous indexes. the don't-care indexes follow N.
+//
+// an L*D*L' factorization is maintained of A(C,C), and whenever indexes are
+// added or removed from the set C the factorization is updated.
+// thus L*D*L'=A[C,C], i.e. a permuted top left nC*nC submatrix of A.
+// the leading dimension of the matrix L is always `nskip'.
+//
+// at the start there may be other indexes that are unbounded but are not
+// included in `nub'. btLCP will permute the matrix so that absolutely all
+// unbounded vectors are at the start. thus there may be some initial
+// permutation.
+//
+// the algorithms here assume certain patterns, particularly with respect to
+// index transfer.
+
+#ifdef btLCP_FAST
+
+struct btLCP
+{
+ const int m_n;
+ const int m_nskip;
+ int m_nub;
+ int m_nC, m_nN; // size of each index set
+ BTATYPE const m_A; // A rows
+ btScalar *const m_x, * const m_b, *const m_w, *const m_lo,* const m_hi; // permuted LCP problem data
+ btScalar *const m_L, *const m_d; // L*D*L' factorization of set C
+ btScalar *const m_Dell, *const m_ell, *const m_tmp;
+ bool *const m_state;
+ int *const m_findex, *const m_p, *const m_C;
+
+ btLCP (int _n, int _nskip, int _nub, btScalar *_Adata, btScalar *_x, btScalar *_b, btScalar *_w,
+ btScalar *_lo, btScalar *_hi, btScalar *l, btScalar *_d,
+ btScalar *_Dell, btScalar *_ell, btScalar *_tmp,
+ bool *_state, int *_findex, int *p, int *c, btScalar **Arows);
+ int getNub() const { return m_nub; }
+ void transfer_i_to_C (int i);
+ void transfer_i_to_N (int i) { m_nN++; } // because we can assume C and N span 1:i-1
+ void transfer_i_from_N_to_C (int i);
+ void transfer_i_from_C_to_N (int i, btAlignedObjectArray<btScalar>& scratch);
+ int numC() const { return m_nC; }
+ int numN() const { return m_nN; }
+ int indexC (int i) const { return i; }
+ int indexN (int i) const { return i+m_nC; }
+ btScalar Aii (int i) const { return BTAROW(i)[i]; }
+ btScalar AiC_times_qC (int i, btScalar *q) const { return btLargeDot (BTAROW(i), q, m_nC); }
+ btScalar AiN_times_qN (int i, btScalar *q) const { return btLargeDot (BTAROW(i)+m_nC, q+m_nC, m_nN); }
+ void pN_equals_ANC_times_qC (btScalar *p, btScalar *q);
+ void pN_plusequals_ANi (btScalar *p, int i, int sign=1);
+ void pC_plusequals_s_times_qC (btScalar *p, btScalar s, btScalar *q);
+ void pN_plusequals_s_times_qN (btScalar *p, btScalar s, btScalar *q);
+ void solve1 (btScalar *a, int i, int dir=1, int only_transfer=0);
+ void unpermute();
+};
+
+
+btLCP::btLCP (int _n, int _nskip, int _nub, btScalar *_Adata, btScalar *_x, btScalar *_b, btScalar *_w,
+ btScalar *_lo, btScalar *_hi, btScalar *l, btScalar *_d,
+ btScalar *_Dell, btScalar *_ell, btScalar *_tmp,
+ bool *_state, int *_findex, int *p, int *c, btScalar **Arows):
+ m_n(_n), m_nskip(_nskip), m_nub(_nub), m_nC(0), m_nN(0),
+# ifdef BTROWPTRS
+ m_A(Arows),
+#else
+ m_A(_Adata),
+#endif
+ m_x(_x), m_b(_b), m_w(_w), m_lo(_lo), m_hi(_hi),
+ m_L(l), m_d(_d), m_Dell(_Dell), m_ell(_ell), m_tmp(_tmp),
+ m_state(_state), m_findex(_findex), m_p(p), m_C(c)
+{
+ {
+ btSetZero (m_x,m_n);
+ }
+
+ {
+# ifdef BTROWPTRS
+ // make matrix row pointers
+ btScalar *aptr = _Adata;
+ BTATYPE A = m_A;
+ const int n = m_n, nskip = m_nskip;
+ for (int k=0; k<n; aptr+=nskip, ++k) A[k] = aptr;
+# endif
+ }
+
+ {
+ int *p = m_p;
+ const int n = m_n;
+ for (int k=0; k<n; ++k) p[k]=k; // initially unpermuted
+ }
+
+ /*
+ // for testing, we can do some random swaps in the area i > nub
+ {
+ const int n = m_n;
+ const int nub = m_nub;
+ if (nub < n) {
+ for (int k=0; k<100; k++) {
+ int i1,i2;
+ do {
+ i1 = dRandInt(n-nub)+nub;
+ i2 = dRandInt(n-nub)+nub;
+ }
+ while (i1 > i2);
+ //printf ("--> %d %d\n",i1,i2);
+ btSwapProblem (m_A,m_x,m_b,m_w,m_lo,m_hi,m_p,m_state,m_findex,n,i1,i2,m_nskip,0);
+ }
+ }
+ */
+
+ // permute the problem so that *all* the unbounded variables are at the
+ // start, i.e. look for unbounded variables not included in `nub'. we can
+ // potentially push up `nub' this way and get a bigger initial factorization.
+ // note that when we swap rows/cols here we must not just swap row pointers,
+ // as the initial factorization relies on the data being all in one chunk.
+ // variables that have findex >= 0 are *not* considered to be unbounded even
+ // if lo=-inf and hi=inf - this is because these limits may change during the
+ // solution process.
+
+ {
+ int *findex = m_findex;
+ btScalar *lo = m_lo, *hi = m_hi;
+ const int n = m_n;
+ for (int k = m_nub; k<n; ++k) {
+ if (findex && findex[k] >= 0) continue;
+ if (lo[k]==-BT_INFINITY && hi[k]==BT_INFINITY) {
+ btSwapProblem (m_A,m_x,m_b,m_w,lo,hi,m_p,m_state,findex,n,m_nub,k,m_nskip,0);
+ m_nub++;
+ }
+ }
+ }
+
+ // if there are unbounded variables at the start, factorize A up to that
+ // point and solve for x. this puts all indexes 0..nub-1 into C.
+ if (m_nub > 0) {
+ const int nub = m_nub;
+ {
+ btScalar *Lrow = m_L;
+ const int nskip = m_nskip;
+ for (int j=0; j<nub; Lrow+=nskip, ++j) memcpy(Lrow,BTAROW(j),(j+1)*sizeof(btScalar));
+ }
+ btFactorLDLT (m_L,m_d,nub,m_nskip);
+ memcpy (m_x,m_b,nub*sizeof(btScalar));
+ btSolveLDLT (m_L,m_d,m_x,nub,m_nskip);
+ btSetZero (m_w,nub);
+ {
+ int *C = m_C;
+ for (int k=0; k<nub; ++k) C[k] = k;
+ }
+ m_nC = nub;
+ }
+
+ // permute the indexes > nub such that all findex variables are at the end
+ if (m_findex) {
+ const int nub = m_nub;
+ int *findex = m_findex;
+ int num_at_end = 0;
+ for (int k=m_n-1; k >= nub; k--) {
+ if (findex[k] >= 0) {
+ btSwapProblem (m_A,m_x,m_b,m_w,m_lo,m_hi,m_p,m_state,findex,m_n,k,m_n-1-num_at_end,m_nskip,1);
+ num_at_end++;
+ }
+ }
+ }
+
+ // print info about indexes
+ /*
+ {
+ const int n = m_n;
+ const int nub = m_nub;
+ for (int k=0; k<n; k++) {
+ if (k<nub) printf ("C");
+ else if (m_lo[k]==-BT_INFINITY && m_hi[k]==BT_INFINITY) printf ("c");
+ else printf (".");
+ }
+ printf ("\n");
+ }
+ */
+}
+
+
+void btLCP::transfer_i_to_C (int i)
+{
+ {
+ if (m_nC > 0) {
+ // ell,Dell were computed by solve1(). note, ell = D \ L1solve (L,A(i,C))
+ {
+ const int nC = m_nC;
+ btScalar *const Ltgt = m_L + nC*m_nskip, *ell = m_ell;
+ for (int j=0; j<nC; ++j) Ltgt[j] = ell[j];
+ }
+ const int nC = m_nC;
+ m_d[nC] = btRecip (BTAROW(i)[i] - btLargeDot(m_ell,m_Dell,nC));
+ }
+ else {
+ m_d[0] = btRecip (BTAROW(i)[i]);
+ }
+
+ btSwapProblem (m_A,m_x,m_b,m_w,m_lo,m_hi,m_p,m_state,m_findex,m_n,m_nC,i,m_nskip,1);
+
+ const int nC = m_nC;
+ m_C[nC] = nC;
+ m_nC = nC + 1; // nC value is outdated after this line
+ }
+
+}
+
+
+void btLCP::transfer_i_from_N_to_C (int i)
+{
+ {
+ if (m_nC > 0) {
+ {
+ btScalar *const aptr = BTAROW(i);
+ btScalar *Dell = m_Dell;
+ const int *C = m_C;
+# ifdef BTNUB_OPTIMIZATIONS
+ // if nub>0, initial part of aptr unpermuted
+ const int nub = m_nub;
+ int j=0;
+ for ( ; j<nub; ++j) Dell[j] = aptr[j];
+ const int nC = m_nC;
+ for ( ; j<nC; ++j) Dell[j] = aptr[C[j]];
+# else
+ const int nC = m_nC;
+ for (int j=0; j<nC; ++j) Dell[j] = aptr[C[j]];
+# endif
+ }
+ btSolveL1 (m_L,m_Dell,m_nC,m_nskip);
+ {
+ const int nC = m_nC;
+ btScalar *const Ltgt = m_L + nC*m_nskip;
+ btScalar *ell = m_ell, *Dell = m_Dell, *d = m_d;
+ for (int j=0; j<nC; ++j) Ltgt[j] = ell[j] = Dell[j] * d[j];
+ }
+ const int nC = m_nC;
+ m_d[nC] = btRecip (BTAROW(i)[i] - btLargeDot(m_ell,m_Dell,nC));
+ }
+ else {
+ m_d[0] = btRecip (BTAROW(i)[i]);
+ }
+
+ btSwapProblem (m_A,m_x,m_b,m_w,m_lo,m_hi,m_p,m_state,m_findex,m_n,m_nC,i,m_nskip,1);
+
+ const int nC = m_nC;
+ m_C[nC] = nC;
+ m_nN--;
+ m_nC = nC + 1; // nC value is outdated after this line
+ }
+
+ // @@@ TO DO LATER
+ // if we just finish here then we'll go back and re-solve for
+ // delta_x. but actually we can be more efficient and incrementally
+ // update delta_x here. but if we do this, we wont have ell and Dell
+ // to use in updating the factorization later.
+
+}
+
+void btRemoveRowCol (btScalar *A, int n, int nskip, int r)
+{
+ btAssert(A && n > 0 && nskip >= n && r >= 0 && r < n);
+ if (r >= n-1) return;
+ if (r > 0) {
+ {
+ const size_t move_size = (n-r-1)*sizeof(btScalar);
+ btScalar *Adst = A + r;
+ for (int i=0; i<r; Adst+=nskip,++i) {
+ btScalar *Asrc = Adst + 1;
+ memmove (Adst,Asrc,move_size);
+ }
+ }
+ {
+ const size_t cpy_size = r*sizeof(btScalar);
+ btScalar *Adst = A + r * nskip;
+ for (int i=r; i<(n-1); ++i) {
+ btScalar *Asrc = Adst + nskip;
+ memcpy (Adst,Asrc,cpy_size);
+ Adst = Asrc;
+ }
+ }
+ }
+ {
+ const size_t cpy_size = (n-r-1)*sizeof(btScalar);
+ btScalar *Adst = A + r * (nskip + 1);
+ for (int i=r; i<(n-1); ++i) {
+ btScalar *Asrc = Adst + (nskip + 1);
+ memcpy (Adst,Asrc,cpy_size);
+ Adst = Asrc - 1;
+ }
+ }
+}
+
+
+
+
+void btLDLTAddTL (btScalar *L, btScalar *d, const btScalar *a, int n, int nskip, btAlignedObjectArray<btScalar>& scratch)
+{
+ btAssert (L && d && a && n > 0 && nskip >= n);
+
+ if (n < 2) return;
+ scratch.resize(2*nskip);
+ btScalar *W1 = &scratch[0];
+
+ btScalar *W2 = W1 + nskip;
+
+ W1[0] = btScalar(0.0);
+ W2[0] = btScalar(0.0);
+ for (int j=1; j<n; ++j) {
+ W1[j] = W2[j] = (btScalar) (a[j] * SIMDSQRT12);
+ }
+ btScalar W11 = (btScalar) ((btScalar(0.5)*a[0]+1)*SIMDSQRT12);
+ btScalar W21 = (btScalar) ((btScalar(0.5)*a[0]-1)*SIMDSQRT12);
+
+ btScalar alpha1 = btScalar(1.0);
+ btScalar alpha2 = btScalar(1.0);
+
+ {
+ btScalar dee = d[0];
+ btScalar alphanew = alpha1 + (W11*W11)*dee;
+ btAssert(alphanew != btScalar(0.0));
+ dee /= alphanew;
+ btScalar gamma1 = W11 * dee;
+ dee *= alpha1;
+ alpha1 = alphanew;
+ alphanew = alpha2 - (W21*W21)*dee;
+ dee /= alphanew;
+ //btScalar gamma2 = W21 * dee;
+ alpha2 = alphanew;
+ btScalar k1 = btScalar(1.0) - W21*gamma1;
+ btScalar k2 = W21*gamma1*W11 - W21;
+ btScalar *ll = L + nskip;
+ for (int p=1; p<n; ll+=nskip, ++p) {
+ btScalar Wp = W1[p];
+ btScalar ell = *ll;
+ W1[p] = Wp - W11*ell;
+ W2[p] = k1*Wp + k2*ell;
+ }
+ }
+
+ btScalar *ll = L + (nskip + 1);
+ for (int j=1; j<n; ll+=nskip+1, ++j) {
+ btScalar k1 = W1[j];
+ btScalar k2 = W2[j];
+
+ btScalar dee = d[j];
+ btScalar alphanew = alpha1 + (k1*k1)*dee;
+ btAssert(alphanew != btScalar(0.0));
+ dee /= alphanew;
+ btScalar gamma1 = k1 * dee;
+ dee *= alpha1;
+ alpha1 = alphanew;
+ alphanew = alpha2 - (k2*k2)*dee;
+ dee /= alphanew;
+ btScalar gamma2 = k2 * dee;
+ dee *= alpha2;
+ d[j] = dee;
+ alpha2 = alphanew;
+
+ btScalar *l = ll + nskip;
+ for (int p=j+1; p<n; l+=nskip, ++p) {
+ btScalar ell = *l;
+ btScalar Wp = W1[p] - k1 * ell;
+ ell += gamma1 * Wp;
+ W1[p] = Wp;
+ Wp = W2[p] - k2 * ell;
+ ell -= gamma2 * Wp;
+ W2[p] = Wp;
+ *l = ell;
+ }
+ }
+}
+
+
+#define _BTGETA(i,j) (A[i][j])
+//#define _GETA(i,j) (A[(i)*nskip+(j)])
+#define BTGETA(i,j) ((i > j) ? _BTGETA(i,j) : _BTGETA(j,i))
+
+inline size_t btEstimateLDLTAddTLTmpbufSize(int nskip)
+{
+ return nskip * 2 * sizeof(btScalar);
+}
+
+
+void btLDLTRemove (btScalar **A, const int *p, btScalar *L, btScalar *d,
+ int n1, int n2, int r, int nskip, btAlignedObjectArray<btScalar>& scratch)
+{
+ btAssert(A && p && L && d && n1 > 0 && n2 > 0 && r >= 0 && r < n2 &&
+ n1 >= n2 && nskip >= n1);
+ #ifdef BT_DEBUG
+ for (int i=0; i<n2; ++i)
+ btAssert(p[i] >= 0 && p[i] < n1);
+ #endif
+
+ if (r==n2-1) {
+ return; // deleting last row/col is easy
+ }
+ else {
+ size_t LDLTAddTL_size = btEstimateLDLTAddTLTmpbufSize(nskip);
+ btAssert(LDLTAddTL_size % sizeof(btScalar) == 0);
+ scratch.resize(nskip * 2+n2);
+ btScalar *tmp = &scratch[0];
+ if (r==0) {
+ btScalar *a = (btScalar *)((char *)tmp + LDLTAddTL_size);
+ const int p_0 = p[0];
+ for (int i=0; i<n2; ++i) {
+ a[i] = -BTGETA(p[i],p_0);
+ }
+ a[0] += btScalar(1.0);
+ btLDLTAddTL (L,d,a,n2,nskip,scratch);
+ }
+ else {
+ btScalar *t = (btScalar *)((char *)tmp + LDLTAddTL_size);
+ {
+ btScalar *Lcurr = L + r*nskip;
+ for (int i=0; i<r; ++Lcurr, ++i) {
+ btAssert(d[i] != btScalar(0.0));
+ t[i] = *Lcurr / d[i];
+ }
+ }
+ btScalar *a = t + r;
+ {
+ btScalar *Lcurr = L + r*nskip;
+ const int *pp_r = p + r, p_r = *pp_r;
+ const int n2_minus_r = n2-r;
+ for (int i=0; i<n2_minus_r; Lcurr+=nskip,++i) {
+ a[i] = btLargeDot(Lcurr,t,r) - BTGETA(pp_r[i],p_r);
+ }
+ }
+ a[0] += btScalar(1.0);
+ btLDLTAddTL (L + r*nskip+r, d+r, a, n2-r, nskip, scratch);
+ }
+ }
+
+ // snip out row/column r from L and d
+ btRemoveRowCol (L,n2,nskip,r);
+ if (r < (n2-1)) memmove (d+r,d+r+1,(n2-r-1)*sizeof(btScalar));
+}
+
+
+void btLCP::transfer_i_from_C_to_N (int i, btAlignedObjectArray<btScalar>& scratch)
+{
+ {
+ int *C = m_C;
+ // remove a row/column from the factorization, and adjust the
+ // indexes (black magic!)
+ int last_idx = -1;
+ const int nC = m_nC;
+ int j = 0;
+ for ( ; j<nC; ++j) {
+ if (C[j]==nC-1) {
+ last_idx = j;
+ }
+ if (C[j]==i) {
+ btLDLTRemove (m_A,C,m_L,m_d,m_n,nC,j,m_nskip,scratch);
+ int k;
+ if (last_idx == -1) {
+ for (k=j+1 ; k<nC; ++k) {
+ if (C[k]==nC-1) {
+ break;
+ }
+ }
+ btAssert (k < nC);
+ }
+ else {
+ k = last_idx;
+ }
+ C[k] = C[j];
+ if (j < (nC-1)) memmove (C+j,C+j+1,(nC-j-1)*sizeof(int));
+ break;
+ }
+ }
+ btAssert (j < nC);
+
+ btSwapProblem (m_A,m_x,m_b,m_w,m_lo,m_hi,m_p,m_state,m_findex,m_n,i,nC-1,m_nskip,1);
+
+ m_nN++;
+ m_nC = nC - 1; // nC value is outdated after this line
+ }
+
+}
+
+
+void btLCP::pN_equals_ANC_times_qC (btScalar *p, btScalar *q)
+{
+ // we could try to make this matrix-vector multiplication faster using
+ // outer product matrix tricks, e.g. with the dMultidotX() functions.
+ // but i tried it and it actually made things slower on random 100x100
+ // problems because of the overhead involved. so we'll stick with the
+ // simple method for now.
+ const int nC = m_nC;
+ btScalar *ptgt = p + nC;
+ const int nN = m_nN;
+ for (int i=0; i<nN; ++i) {
+ ptgt[i] = btLargeDot (BTAROW(i+nC),q,nC);
+ }
+}
+
+
+void btLCP::pN_plusequals_ANi (btScalar *p, int i, int sign)
+{
+ const int nC = m_nC;
+ btScalar *aptr = BTAROW(i) + nC;
+ btScalar *ptgt = p + nC;
+ if (sign > 0) {
+ const int nN = m_nN;
+ for (int j=0; j<nN; ++j) ptgt[j] += aptr[j];
+ }
+ else {
+ const int nN = m_nN;
+ for (int j=0; j<nN; ++j) ptgt[j] -= aptr[j];
+ }
+}
+
+void btLCP::pC_plusequals_s_times_qC (btScalar *p, btScalar s, btScalar *q)
+{
+ const int nC = m_nC;
+ for (int i=0; i<nC; ++i) {
+ p[i] += s*q[i];
+ }
+}
+
+void btLCP::pN_plusequals_s_times_qN (btScalar *p, btScalar s, btScalar *q)
+{
+ const int nC = m_nC;
+ btScalar *ptgt = p + nC, *qsrc = q + nC;
+ const int nN = m_nN;
+ for (int i=0; i<nN; ++i) {
+ ptgt[i] += s*qsrc[i];
+ }
+}
+
+void btLCP::solve1 (btScalar *a, int i, int dir, int only_transfer)
+{
+ // the `Dell' and `ell' that are computed here are saved. if index i is
+ // later added to the factorization then they can be reused.
+ //
+ // @@@ question: do we need to solve for entire delta_x??? yes, but
+ // only if an x goes below 0 during the step.
+
+ if (m_nC > 0) {
+ {
+ btScalar *Dell = m_Dell;
+ int *C = m_C;
+ btScalar *aptr = BTAROW(i);
+# ifdef BTNUB_OPTIMIZATIONS
+ // if nub>0, initial part of aptr[] is guaranteed unpermuted
+ const int nub = m_nub;
+ int j=0;
+ for ( ; j<nub; ++j) Dell[j] = aptr[j];
+ const int nC = m_nC;
+ for ( ; j<nC; ++j) Dell[j] = aptr[C[j]];
+# else
+ const int nC = m_nC;
+ for (int j=0; j<nC; ++j) Dell[j] = aptr[C[j]];
+# endif
+ }
+ btSolveL1 (m_L,m_Dell,m_nC,m_nskip);
+ {
+ btScalar *ell = m_ell, *Dell = m_Dell, *d = m_d;
+ const int nC = m_nC;
+ for (int j=0; j<nC; ++j) ell[j] = Dell[j] * d[j];
+ }
+
+ if (!only_transfer) {
+ btScalar *tmp = m_tmp, *ell = m_ell;
+ {
+ const int nC = m_nC;
+ for (int j=0; j<nC; ++j) tmp[j] = ell[j];
+ }
+ btSolveL1T (m_L,tmp,m_nC,m_nskip);
+ if (dir > 0) {
+ int *C = m_C;
+ btScalar *tmp = m_tmp;
+ const int nC = m_nC;
+ for (int j=0; j<nC; ++j) a[C[j]] = -tmp[j];
+ } else {
+ int *C = m_C;
+ btScalar *tmp = m_tmp;
+ const int nC = m_nC;
+ for (int j=0; j<nC; ++j) a[C[j]] = tmp[j];
+ }
+ }
+ }
+}
+
+
+void btLCP::unpermute()
+{
+ // now we have to un-permute x and w
+ {
+ memcpy (m_tmp,m_x,m_n*sizeof(btScalar));
+ btScalar *x = m_x, *tmp = m_tmp;
+ const int *p = m_p;
+ const int n = m_n;
+ for (int j=0; j<n; ++j) x[p[j]] = tmp[j];
+ }
+ {
+ memcpy (m_tmp,m_w,m_n*sizeof(btScalar));
+ btScalar *w = m_w, *tmp = m_tmp;
+ const int *p = m_p;
+ const int n = m_n;
+ for (int j=0; j<n; ++j) w[p[j]] = tmp[j];
+ }
+}
+
+#endif // btLCP_FAST
+
+
+//***************************************************************************
+// an optimized Dantzig LCP driver routine for the lo-hi LCP problem.
+
+bool btSolveDantzigLCP (int n, btScalar *A, btScalar *x, btScalar *b,
+ btScalar* outer_w, int nub, btScalar *lo, btScalar *hi, int *findex, btDantzigScratchMemory& scratchMem)
+{
+ s_error = false;
+
+// printf("btSolveDantzigLCP n=%d\n",n);
+ btAssert (n>0 && A && x && b && lo && hi && nub >= 0 && nub <= n);
+ btAssert(outer_w);
+
+#ifdef BT_DEBUG
+ {
+ // check restrictions on lo and hi
+ for (int k=0; k<n; ++k)
+ btAssert (lo[k] <= 0 && hi[k] >= 0);
+ }
+# endif
+
+
+ // if all the variables are unbounded then we can just factor, solve,
+ // and return
+ if (nub >= n)
+ {
+
+
+ int nskip = (n);
+ btFactorLDLT (A, outer_w, n, nskip);
+ btSolveLDLT (A, outer_w, b, n, nskip);
+ memcpy (x, b, n*sizeof(btScalar));
+
+ return !s_error;
+ }
+
+ const int nskip = (n);
+ scratchMem.L.resize(n*nskip);
+
+ scratchMem.d.resize(n);
+
+ btScalar *w = outer_w;
+ scratchMem.delta_w.resize(n);
+ scratchMem.delta_x.resize(n);
+ scratchMem.Dell.resize(n);
+ scratchMem.ell.resize(n);
+ scratchMem.Arows.resize(n);
+ scratchMem.p.resize(n);
+ scratchMem.C.resize(n);
+
+ // for i in N, state[i] is 0 if x(i)==lo(i) or 1 if x(i)==hi(i)
+ scratchMem.state.resize(n);
+
+
+ // create LCP object. note that tmp is set to delta_w to save space, this
+ // optimization relies on knowledge of how tmp is used, so be careful!
+ btLCP lcp(n,nskip,nub,A,x,b,w,lo,hi,&scratchMem.L[0],&scratchMem.d[0],&scratchMem.Dell[0],&scratchMem.ell[0],&scratchMem.delta_w[0],&scratchMem.state[0],findex,&scratchMem.p[0],&scratchMem.C[0],&scratchMem.Arows[0]);
+ int adj_nub = lcp.getNub();
+
+ // loop over all indexes adj_nub..n-1. for index i, if x(i),w(i) satisfy the
+ // LCP conditions then i is added to the appropriate index set. otherwise
+ // x(i),w(i) is driven either +ve or -ve to force it to the valid region.
+ // as we drive x(i), x(C) is also adjusted to keep w(C) at zero.
+ // while driving x(i) we maintain the LCP conditions on the other variables
+ // 0..i-1. we do this by watching out for other x(i),w(i) values going
+ // outside the valid region, and then switching them between index sets
+ // when that happens.
+
+ bool hit_first_friction_index = false;
+ for (int i=adj_nub; i<n; ++i)
+ {
+ s_error = false;
+ // the index i is the driving index and indexes i+1..n-1 are "dont care",
+ // i.e. when we make changes to the system those x's will be zero and we
+ // don't care what happens to those w's. in other words, we only consider
+ // an (i+1)*(i+1) sub-problem of A*x=b+w.
+
+ // if we've hit the first friction index, we have to compute the lo and
+ // hi values based on the values of x already computed. we have been
+ // permuting the indexes, so the values stored in the findex vector are
+ // no longer valid. thus we have to temporarily unpermute the x vector.
+ // for the purposes of this computation, 0*infinity = 0 ... so if the
+ // contact constraint's normal force is 0, there should be no tangential
+ // force applied.
+
+ if (!hit_first_friction_index && findex && findex[i] >= 0) {
+ // un-permute x into delta_w, which is not being used at the moment
+ for (int j=0; j<n; ++j) scratchMem.delta_w[scratchMem.p[j]] = x[j];
+
+ // set lo and hi values
+ for (int k=i; k<n; ++k) {
+ btScalar wfk = scratchMem.delta_w[findex[k]];
+ if (wfk == 0) {
+ hi[k] = 0;
+ lo[k] = 0;
+ }
+ else {
+ hi[k] = btFabs (hi[k] * wfk);
+ lo[k] = -hi[k];
+ }
+ }
+ hit_first_friction_index = true;
+ }
+
+ // thus far we have not even been computing the w values for indexes
+ // greater than i, so compute w[i] now.
+ w[i] = lcp.AiC_times_qC (i,x) + lcp.AiN_times_qN (i,x) - b[i];
+
+ // if lo=hi=0 (which can happen for tangential friction when normals are
+ // 0) then the index will be assigned to set N with some state. however,
+ // set C's line has zero size, so the index will always remain in set N.
+ // with the "normal" switching logic, if w changed sign then the index
+ // would have to switch to set C and then back to set N with an inverted
+ // state. this is pointless, and also computationally expensive. to
+ // prevent this from happening, we use the rule that indexes with lo=hi=0
+ // will never be checked for set changes. this means that the state for
+ // these indexes may be incorrect, but that doesn't matter.
+
+ // see if x(i),w(i) is in a valid region
+ if (lo[i]==0 && w[i] >= 0) {
+ lcp.transfer_i_to_N (i);
+ scratchMem.state[i] = false;
+ }
+ else if (hi[i]==0 && w[i] <= 0) {
+ lcp.transfer_i_to_N (i);
+ scratchMem.state[i] = true;
+ }
+ else if (w[i]==0) {
+ // this is a degenerate case. by the time we get to this test we know
+ // that lo != 0, which means that lo < 0 as lo is not allowed to be +ve,
+ // and similarly that hi > 0. this means that the line segment
+ // corresponding to set C is at least finite in extent, and we are on it.
+ // NOTE: we must call lcp.solve1() before lcp.transfer_i_to_C()
+ lcp.solve1 (&scratchMem.delta_x[0],i,0,1);
+
+ lcp.transfer_i_to_C (i);
+ }
+ else {
+ // we must push x(i) and w(i)
+ for (;;) {
+ int dir;
+ btScalar dirf;
+ // find direction to push on x(i)
+ if (w[i] <= 0) {
+ dir = 1;
+ dirf = btScalar(1.0);
+ }
+ else {
+ dir = -1;
+ dirf = btScalar(-1.0);
+ }
+
+ // compute: delta_x(C) = -dir*A(C,C)\A(C,i)
+ lcp.solve1 (&scratchMem.delta_x[0],i,dir);
+
+ // note that delta_x[i] = dirf, but we wont bother to set it
+
+ // compute: delta_w = A*delta_x ... note we only care about
+ // delta_w(N) and delta_w(i), the rest is ignored
+ lcp.pN_equals_ANC_times_qC (&scratchMem.delta_w[0],&scratchMem.delta_x[0]);
+ lcp.pN_plusequals_ANi (&scratchMem.delta_w[0],i,dir);
+ scratchMem.delta_w[i] = lcp.AiC_times_qC (i,&scratchMem.delta_x[0]) + lcp.Aii(i)*dirf;
+
+ // find largest step we can take (size=s), either to drive x(i),w(i)
+ // to the valid LCP region or to drive an already-valid variable
+ // outside the valid region.
+
+ int cmd = 1; // index switching command
+ int si = 0; // si = index to switch if cmd>3
+ btScalar s = -w[i]/scratchMem.delta_w[i];
+ if (dir > 0) {
+ if (hi[i] < BT_INFINITY) {
+ btScalar s2 = (hi[i]-x[i])*dirf; // was (hi[i]-x[i])/dirf // step to x(i)=hi(i)
+ if (s2 < s) {
+ s = s2;
+ cmd = 3;
+ }
+ }
+ }
+ else {
+ if (lo[i] > -BT_INFINITY) {
+ btScalar s2 = (lo[i]-x[i])*dirf; // was (lo[i]-x[i])/dirf // step to x(i)=lo(i)
+ if (s2 < s) {
+ s = s2;
+ cmd = 2;
+ }
+ }
+ }
+
+ {
+ const int numN = lcp.numN();
+ for (int k=0; k < numN; ++k) {
+ const int indexN_k = lcp.indexN(k);
+ if (!scratchMem.state[indexN_k] ? scratchMem.delta_w[indexN_k] < 0 : scratchMem.delta_w[indexN_k] > 0) {
+ // don't bother checking if lo=hi=0
+ if (lo[indexN_k] == 0 && hi[indexN_k] == 0) continue;
+ btScalar s2 = -w[indexN_k] / scratchMem.delta_w[indexN_k];
+ if (s2 < s) {
+ s = s2;
+ cmd = 4;
+ si = indexN_k;
+ }
+ }
+ }
+ }
+
+ {
+ const int numC = lcp.numC();
+ for (int k=adj_nub; k < numC; ++k) {
+ const int indexC_k = lcp.indexC(k);
+ if (scratchMem.delta_x[indexC_k] < 0 && lo[indexC_k] > -BT_INFINITY) {
+ btScalar s2 = (lo[indexC_k]-x[indexC_k]) / scratchMem.delta_x[indexC_k];
+ if (s2 < s) {
+ s = s2;
+ cmd = 5;
+ si = indexC_k;
+ }
+ }
+ if (scratchMem.delta_x[indexC_k] > 0 && hi[indexC_k] < BT_INFINITY) {
+ btScalar s2 = (hi[indexC_k]-x[indexC_k]) / scratchMem.delta_x[indexC_k];
+ if (s2 < s) {
+ s = s2;
+ cmd = 6;
+ si = indexC_k;
+ }
+ }
+ }
+ }
+
+ //static char* cmdstring[8] = {0,"->C","->NL","->NH","N->C",
+ // "C->NL","C->NH"};
+ //printf ("cmd=%d (%s), si=%d\n",cmd,cmdstring[cmd],(cmd>3) ? si : i);
+
+ // if s <= 0 then we've got a problem. if we just keep going then
+ // we're going to get stuck in an infinite loop. instead, just cross
+ // our fingers and exit with the current solution.
+ if (s <= btScalar(0.0))
+ {
+// printf("LCP internal error, s <= 0 (s=%.4e)",(double)s);
+ if (i < n) {
+ btSetZero (x+i,n-i);
+ btSetZero (w+i,n-i);
+ }
+ s_error = true;
+ break;
+ }
+
+ // apply x = x + s * delta_x
+ lcp.pC_plusequals_s_times_qC (x, s, &scratchMem.delta_x[0]);
+ x[i] += s * dirf;
+
+ // apply w = w + s * delta_w
+ lcp.pN_plusequals_s_times_qN (w, s, &scratchMem.delta_w[0]);
+ w[i] += s * scratchMem.delta_w[i];
+
+// void *tmpbuf;
+ // switch indexes between sets if necessary
+ switch (cmd) {
+ case 1: // done
+ w[i] = 0;
+ lcp.transfer_i_to_C (i);
+ break;
+ case 2: // done
+ x[i] = lo[i];
+ scratchMem.state[i] = false;
+ lcp.transfer_i_to_N (i);
+ break;
+ case 3: // done
+ x[i] = hi[i];
+ scratchMem.state[i] = true;
+ lcp.transfer_i_to_N (i);
+ break;
+ case 4: // keep going
+ w[si] = 0;
+ lcp.transfer_i_from_N_to_C (si);
+ break;
+ case 5: // keep going
+ x[si] = lo[si];
+ scratchMem.state[si] = false;
+ lcp.transfer_i_from_C_to_N (si, scratchMem.m_scratch);
+ break;
+ case 6: // keep going
+ x[si] = hi[si];
+ scratchMem.state[si] = true;
+ lcp.transfer_i_from_C_to_N (si, scratchMem.m_scratch);
+ break;
+ }
+
+ if (cmd <= 3) break;
+ } // for (;;)
+ } // else
+
+ if (s_error)
+ {
+ break;
+ }
+ } // for (int i=adj_nub; i<n; ++i)
+
+ lcp.unpermute();
+
+
+ return !s_error;
+}
+
diff --git a/thirdparty/bullet/src/BulletDynamics/MLCPSolvers/btDantzigLCP.h b/thirdparty/bullet/src/BulletDynamics/MLCPSolvers/btDantzigLCP.h
new file mode 100644
index 0000000000..903832770a
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/MLCPSolvers/btDantzigLCP.h
@@ -0,0 +1,77 @@
+/*************************************************************************
+ * *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
+ * All rights reserved. Email: russ@q12.org Web: www.q12.org *
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of *
+ * The BSD-style license that is included with this library in *
+ * the file LICENSE-BSD.TXT. *
+ * *
+ * This library is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
+ * *
+ *************************************************************************/
+
+/*
+
+given (A,b,lo,hi), solve the LCP problem: A*x = b+w, where each x(i),w(i)
+satisfies one of
+ (1) x = lo, w >= 0
+ (2) x = hi, w <= 0
+ (3) lo < x < hi, w = 0
+A is a matrix of dimension n*n, everything else is a vector of size n*1.
+lo and hi can be +/- dInfinity as needed. the first `nub' variables are
+unbounded, i.e. hi and lo are assumed to be +/- dInfinity.
+
+we restrict lo(i) <= 0 and hi(i) >= 0.
+
+the original data (A,b) may be modified by this function.
+
+if the `findex' (friction index) parameter is nonzero, it points to an array
+of index values. in this case constraints that have findex[i] >= 0 are
+special. all non-special constraints are solved for, then the lo and hi values
+for the special constraints are set:
+ hi[i] = abs( hi[i] * x[findex[i]] )
+ lo[i] = -hi[i]
+and the solution continues. this mechanism allows a friction approximation
+to be implemented. the first `nub' variables are assumed to have findex < 0.
+
+*/
+
+
+#ifndef _BT_LCP_H_
+#define _BT_LCP_H_
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+
+
+#include "LinearMath/btScalar.h"
+#include "LinearMath/btAlignedObjectArray.h"
+
+struct btDantzigScratchMemory
+{
+ btAlignedObjectArray<btScalar> m_scratch;
+ btAlignedObjectArray<btScalar> L;
+ btAlignedObjectArray<btScalar> d;
+ btAlignedObjectArray<btScalar> delta_w;
+ btAlignedObjectArray<btScalar> delta_x;
+ btAlignedObjectArray<btScalar> Dell;
+ btAlignedObjectArray<btScalar> ell;
+ btAlignedObjectArray<btScalar*> Arows;
+ btAlignedObjectArray<int> p;
+ btAlignedObjectArray<int> C;
+ btAlignedObjectArray<bool> state;
+};
+
+//return false if solving failed
+bool btSolveDantzigLCP (int n, btScalar *A, btScalar *x, btScalar *b, btScalar *w,
+ int nub, btScalar *lo, btScalar *hi, int *findex,btDantzigScratchMemory& scratch);
+
+
+
+#endif //_BT_LCP_H_
diff --git a/thirdparty/bullet/src/BulletDynamics/MLCPSolvers/btDantzigSolver.h b/thirdparty/bullet/src/BulletDynamics/MLCPSolvers/btDantzigSolver.h
new file mode 100644
index 0000000000..2a2f2d3d32
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/MLCPSolvers/btDantzigSolver.h
@@ -0,0 +1,112 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2013 Erwin Coumans 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.
+*/
+///original version written by Erwin Coumans, October 2013
+
+#ifndef BT_DANTZIG_SOLVER_H
+#define BT_DANTZIG_SOLVER_H
+
+#include "btMLCPSolverInterface.h"
+#include "btDantzigLCP.h"
+
+
+class btDantzigSolver : public btMLCPSolverInterface
+{
+protected:
+
+ btScalar m_acceptableUpperLimitSolution;
+
+ btAlignedObjectArray<char> m_tempBuffer;
+
+ btAlignedObjectArray<btScalar> m_A;
+ btAlignedObjectArray<btScalar> m_b;
+ btAlignedObjectArray<btScalar> m_x;
+ btAlignedObjectArray<btScalar> m_lo;
+ btAlignedObjectArray<btScalar> m_hi;
+ btAlignedObjectArray<int> m_dependencies;
+ btDantzigScratchMemory m_scratchMemory;
+public:
+
+ btDantzigSolver()
+ :m_acceptableUpperLimitSolution(btScalar(1000))
+ {
+ }
+
+ virtual bool solveMLCP(const btMatrixXu & A, const btVectorXu & b, btVectorXu& x, const btVectorXu & lo,const btVectorXu & hi,const btAlignedObjectArray<int>& limitDependency, int numIterations, bool useSparsity = true)
+ {
+ bool result = true;
+ int n = b.rows();
+ if (n)
+ {
+ int nub = 0;
+ btAlignedObjectArray<btScalar> ww;
+ ww.resize(n);
+
+
+ const btScalar* Aptr = A.getBufferPointer();
+ m_A.resize(n*n);
+ for (int i=0;i<n*n;i++)
+ {
+ m_A[i] = Aptr[i];
+
+ }
+
+ m_b.resize(n);
+ m_x.resize(n);
+ m_lo.resize(n);
+ m_hi.resize(n);
+ m_dependencies.resize(n);
+ for (int i=0;i<n;i++)
+ {
+ m_lo[i] = lo[i];
+ m_hi[i] = hi[i];
+ m_b[i] = b[i];
+ m_x[i] = x[i];
+ m_dependencies[i] = limitDependency[i];
+ }
+
+
+ result = btSolveDantzigLCP (n,&m_A[0],&m_x[0],&m_b[0],&ww[0],nub,&m_lo[0],&m_hi[0],&m_dependencies[0],m_scratchMemory);
+ if (!result)
+ return result;
+
+// printf("numAllocas = %d\n",numAllocas);
+ for (int i=0;i<n;i++)
+ {
+ volatile btScalar xx = m_x[i];
+ if (xx != m_x[i])
+ return false;
+ if (x[i] >= m_acceptableUpperLimitSolution)
+ {
+ return false;
+ }
+
+ if (x[i] <= -m_acceptableUpperLimitSolution)
+ {
+ return false;
+ }
+ }
+
+ for (int i=0;i<n;i++)
+ {
+ x[i] = m_x[i];
+ }
+
+ }
+
+ return result;
+ }
+};
+
+#endif //BT_DANTZIG_SOLVER_H
diff --git a/thirdparty/bullet/src/BulletDynamics/MLCPSolvers/btLemkeAlgorithm.cpp b/thirdparty/bullet/src/BulletDynamics/MLCPSolvers/btLemkeAlgorithm.cpp
new file mode 100644
index 0000000000..1f4015c7c7
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/MLCPSolvers/btLemkeAlgorithm.cpp
@@ -0,0 +1,371 @@
+/* Copyright (C) 2004-2013 MBSim Development Team
+
+Code was converted for the Bullet Continuous Collision Detection and Physics Library
+
+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.
+*/
+
+//The original version is here
+//https://code.google.com/p/mbsim-env/source/browse/trunk/kernel/mbsim/numerics/linear_complementarity_problem/lemke_algorithm.cc
+//This file is re-distributed under the ZLib license, with permission of the original author
+//Math library was replaced from fmatvec to a the file src/LinearMath/btMatrixX.h
+//STL/std::vector replaced by btAlignedObjectArray
+
+
+
+#include "btLemkeAlgorithm.h"
+
+#undef BT_DEBUG_OSTREAM
+#ifdef BT_DEBUG_OSTREAM
+using namespace std;
+#endif //BT_DEBUG_OSTREAM
+
+btScalar btMachEps()
+{
+ static bool calculated=false;
+ static btScalar machEps = btScalar(1.);
+ if (!calculated)
+ {
+ do {
+ machEps /= btScalar(2.0);
+ // If next epsilon yields 1, then break, because current
+ // epsilon is the machine epsilon.
+ }
+ while ((btScalar)(1.0 + (machEps/btScalar(2.0))) != btScalar(1.0));
+// printf( "\nCalculated Machine epsilon: %G\n", machEps );
+ calculated=true;
+ }
+ return machEps;
+}
+
+btScalar btEpsRoot() {
+
+ static btScalar epsroot = 0.;
+ static bool alreadyCalculated = false;
+
+ if (!alreadyCalculated) {
+ epsroot = btSqrt(btMachEps());
+ alreadyCalculated = true;
+ }
+ return epsroot;
+}
+
+
+
+ btVectorXu btLemkeAlgorithm::solve(unsigned int maxloops /* = 0*/)
+{
+
+
+ steps = 0;
+
+ int dim = m_q.size();
+#ifdef BT_DEBUG_OSTREAM
+ if(DEBUGLEVEL >= 1) {
+ cout << "Dimension = " << dim << endl;
+ }
+#endif //BT_DEBUG_OSTREAM
+
+ btVectorXu solutionVector(2 * dim);
+ solutionVector.setZero();
+
+ //, INIT, 0.);
+
+ btMatrixXu ident(dim, dim);
+ ident.setIdentity();
+#ifdef BT_DEBUG_OSTREAM
+ cout << m_M << std::endl;
+#endif
+
+ btMatrixXu mNeg = m_M.negative();
+
+ btMatrixXu A(dim, 2 * dim + 2);
+ //
+ A.setSubMatrix(0, 0, dim - 1, dim - 1,ident);
+ A.setSubMatrix(0, dim, dim - 1, 2 * dim - 1,mNeg);
+ A.setSubMatrix(0, 2 * dim, dim - 1, 2 * dim, -1.f);
+ A.setSubMatrix(0, 2 * dim + 1, dim - 1, 2 * dim + 1,m_q);
+
+#ifdef BT_DEBUG_OSTREAM
+ cout << A << std::endl;
+#endif //BT_DEBUG_OSTREAM
+
+
+ // btVectorXu q_;
+ // q_ >> A(0, 2 * dim + 1, dim - 1, 2 * dim + 1);
+
+ btAlignedObjectArray<int> basis;
+ //At first, all w-values are in the basis
+ for (int i = 0; i < dim; i++)
+ basis.push_back(i);
+
+ int pivotRowIndex = -1;
+ btScalar minValue = 1e30f;
+ bool greaterZero = true;
+ for (int i=0;i<dim;i++)
+ {
+ btScalar v =A(i,2*dim+1);
+ if (v<minValue)
+ {
+ minValue=v;
+ pivotRowIndex = i;
+ }
+ if (v<0)
+ greaterZero = false;
+ }
+
+
+
+ // int pivotRowIndex = q_.minIndex();//minIndex(q_); // first row is that with lowest q-value
+ int z0Row = pivotRowIndex; // remember the col of z0 for ending algorithm afterwards
+ int pivotColIndex = 2 * dim; // first col is that of z0
+
+#ifdef BT_DEBUG_OSTREAM
+ if (DEBUGLEVEL >= 3)
+ {
+ // cout << "A: " << A << endl;
+ cout << "pivotRowIndex " << pivotRowIndex << endl;
+ cout << "pivotColIndex " << pivotColIndex << endl;
+ cout << "Basis: ";
+ for (int i = 0; i < basis.size(); i++)
+ cout << basis[i] << " ";
+ cout << endl;
+ }
+#endif //BT_DEBUG_OSTREAM
+
+ if (!greaterZero)
+ {
+
+ if (maxloops == 0) {
+ maxloops = 100;
+// maxloops = UINT_MAX; //TODO: not a really nice way, problem is: maxloops should be 2^dim (=1<<dim), but this could exceed UINT_MAX and thus the result would be 0 and therefore the lemke algorithm wouldn't start but probably would find a solution within less then UINT_MAX steps. Therefore this constant is used as a upper border right now...
+ }
+
+ /*start looping*/
+ for(steps = 0; steps < maxloops; steps++) {
+
+ GaussJordanEliminationStep(A, pivotRowIndex, pivotColIndex, basis);
+#ifdef BT_DEBUG_OSTREAM
+ if (DEBUGLEVEL >= 3) {
+ // cout << "A: " << A << endl;
+ cout << "pivotRowIndex " << pivotRowIndex << endl;
+ cout << "pivotColIndex " << pivotColIndex << endl;
+ cout << "Basis: ";
+ for (int i = 0; i < basis.size(); i++)
+ cout << basis[i] << " ";
+ cout << endl;
+ }
+#endif //BT_DEBUG_OSTREAM
+
+ int pivotColIndexOld = pivotColIndex;
+
+ /*find new column index */
+ if (basis[pivotRowIndex] < dim) //if a w-value left the basis get in the correspondent z-value
+ pivotColIndex = basis[pivotRowIndex] + dim;
+ else
+ //else do it the other way round and get in the corresponding w-value
+ pivotColIndex = basis[pivotRowIndex] - dim;
+
+ /*the column becomes part of the basis*/
+ basis[pivotRowIndex] = pivotColIndexOld;
+
+ pivotRowIndex = findLexicographicMinimum(A, pivotColIndex);
+
+ if(z0Row == pivotRowIndex) { //if z0 leaves the basis the solution is found --> one last elimination step is necessary
+ GaussJordanEliminationStep(A, pivotRowIndex, pivotColIndex, basis);
+ basis[pivotRowIndex] = pivotColIndex; //update basis
+ break;
+ }
+
+ }
+#ifdef BT_DEBUG_OSTREAM
+ if(DEBUGLEVEL >= 1) {
+ cout << "Number of loops: " << steps << endl;
+ cout << "Number of maximal loops: " << maxloops << endl;
+ }
+#endif //BT_DEBUG_OSTREAM
+
+ if(!validBasis(basis)) {
+ info = -1;
+#ifdef BT_DEBUG_OSTREAM
+ if(DEBUGLEVEL >= 1)
+ cerr << "Lemke-Algorithm ended with Ray-Termination (no valid solution)." << endl;
+#endif //BT_DEBUG_OSTREAM
+
+ return solutionVector;
+ }
+
+ }
+#ifdef BT_DEBUG_OSTREAM
+ if (DEBUGLEVEL >= 2) {
+ // cout << "A: " << A << endl;
+ cout << "pivotRowIndex " << pivotRowIndex << endl;
+ cout << "pivotColIndex " << pivotColIndex << endl;
+ }
+#endif //BT_DEBUG_OSTREAM
+
+ for (int i = 0; i < basis.size(); i++)
+ {
+ solutionVector[basis[i]] = A(i,2*dim+1);//q_[i];
+ }
+
+ info = 0;
+
+ return solutionVector;
+ }
+
+ int btLemkeAlgorithm::findLexicographicMinimum(const btMatrixXu& A, const int & pivotColIndex) {
+ int RowIndex = 0;
+ int dim = A.rows();
+ btAlignedObjectArray<btVectorXu> Rows;
+ for (int row = 0; row < dim; row++)
+ {
+
+ btVectorXu vec(dim + 1);
+ vec.setZero();//, INIT, 0.)
+ Rows.push_back(vec);
+ btScalar a = A(row, pivotColIndex);
+ if (a > 0) {
+ Rows[row][0] = A(row, 2 * dim + 1) / a;
+ Rows[row][1] = A(row, 2 * dim) / a;
+ for (int j = 2; j < dim + 1; j++)
+ Rows[row][j] = A(row, j - 1) / a;
+
+#ifdef BT_DEBUG_OSTREAM
+ // if (DEBUGLEVEL) {
+ // cout << "Rows(" << row << ") = " << Rows[row] << endl;
+ // }
+#endif
+ }
+ }
+
+ for (int i = 0; i < Rows.size(); i++)
+ {
+ if (Rows[i].nrm2() > 0.) {
+
+ int j = 0;
+ for (; j < Rows.size(); j++)
+ {
+ if(i != j)
+ {
+ if(Rows[j].nrm2() > 0.)
+ {
+ btVectorXu test(dim + 1);
+ for (int ii=0;ii<dim+1;ii++)
+ {
+ test[ii] = Rows[j][ii] - Rows[i][ii];
+ }
+
+ //=Rows[j] - Rows[i]
+ if (! LexicographicPositive(test))
+ break;
+ }
+ }
+ }
+
+ if (j == Rows.size())
+ {
+ RowIndex += i;
+ break;
+ }
+ }
+ }
+
+ return RowIndex;
+ }
+
+ bool btLemkeAlgorithm::LexicographicPositive(const btVectorXu & v)
+{
+ int i = 0;
+ // if (DEBUGLEVEL)
+ // cout << "v " << v << endl;
+
+ while(i < v.size()-1 && fabs(v[i]) < btMachEps())
+ i++;
+ if (v[i] > 0)
+ return true;
+
+ return false;
+ }
+
+void btLemkeAlgorithm::GaussJordanEliminationStep(btMatrixXu& A, int pivotRowIndex, int pivotColumnIndex, const btAlignedObjectArray<int>& basis)
+{
+
+ btScalar a = -1 / A(pivotRowIndex, pivotColumnIndex);
+#ifdef BT_DEBUG_OSTREAM
+ cout << A << std::endl;
+#endif
+
+ for (int i = 0; i < A.rows(); i++)
+ {
+ if (i != pivotRowIndex)
+ {
+ for (int j = 0; j < A.cols(); j++)
+ {
+ if (j != pivotColumnIndex)
+ {
+ btScalar v = A(i, j);
+ v += A(pivotRowIndex, j) * A(i, pivotColumnIndex) * a;
+ A.setElem(i, j, v);
+ }
+ }
+ }
+ }
+
+#ifdef BT_DEBUG_OSTREAM
+ cout << A << std::endl;
+#endif //BT_DEBUG_OSTREAM
+ for (int i = 0; i < A.cols(); i++)
+ {
+ A.mulElem(pivotRowIndex, i,-a);
+ }
+#ifdef BT_DEBUG_OSTREAM
+ cout << A << std::endl;
+#endif //#ifdef BT_DEBUG_OSTREAM
+
+ for (int i = 0; i < A.rows(); i++)
+ {
+ if (i != pivotRowIndex)
+ {
+ A.setElem(i, pivotColumnIndex,0);
+ }
+ }
+#ifdef BT_DEBUG_OSTREAM
+ cout << A << std::endl;
+#endif //#ifdef BT_DEBUG_OSTREAM
+ }
+
+ bool btLemkeAlgorithm::greaterZero(const btVectorXu & vector)
+{
+ bool isGreater = true;
+ for (int i = 0; i < vector.size(); i++) {
+ if (vector[i] < 0) {
+ isGreater = false;
+ break;
+ }
+ }
+
+ return isGreater;
+ }
+
+ bool btLemkeAlgorithm::validBasis(const btAlignedObjectArray<int>& basis)
+ {
+ bool isValid = true;
+ for (int i = 0; i < basis.size(); i++) {
+ if (basis[i] >= basis.size() * 2) { //then z0 is in the base
+ isValid = false;
+ break;
+ }
+ }
+
+ return isValid;
+ }
+
+
diff --git a/thirdparty/bullet/src/BulletDynamics/MLCPSolvers/btLemkeAlgorithm.h b/thirdparty/bullet/src/BulletDynamics/MLCPSolvers/btLemkeAlgorithm.h
new file mode 100644
index 0000000000..7555cd9d20
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/MLCPSolvers/btLemkeAlgorithm.h
@@ -0,0 +1,108 @@
+/* Copyright (C) 2004-2013 MBSim Development Team
+
+Code was converted for the Bullet Continuous Collision Detection and Physics Library
+
+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.
+*/
+
+//The original version is here
+//https://code.google.com/p/mbsim-env/source/browse/trunk/kernel/mbsim/numerics/linear_complementarity_problem/lemke_algorithm.cc
+//This file is re-distributed under the ZLib license, with permission of the original author (Kilian Grundl)
+//Math library was replaced from fmatvec to a the file src/LinearMath/btMatrixX.h
+//STL/std::vector replaced by btAlignedObjectArray
+
+
+
+#ifndef BT_NUMERICS_LEMKE_ALGORITHM_H_
+#define BT_NUMERICS_LEMKE_ALGORITHM_H_
+
+#include "LinearMath/btMatrixX.h"
+
+
+#include <vector> //todo: replace by btAlignedObjectArray
+
+class btLemkeAlgorithm
+{
+public:
+
+
+ btLemkeAlgorithm(const btMatrixXu& M_, const btVectorXu& q_, const int & DEBUGLEVEL_ = 0) :
+ DEBUGLEVEL(DEBUGLEVEL_)
+ {
+ setSystem(M_, q_);
+ }
+
+ /* GETTER / SETTER */
+ /**
+ * \brief return info of solution process
+ */
+ int getInfo() {
+ return info;
+ }
+
+ /**
+ * \brief get the number of steps until the solution was found
+ */
+ int getSteps(void) {
+ return steps;
+ }
+
+
+
+ /**
+ * \brief set system with Matrix M and vector q
+ */
+ void setSystem(const btMatrixXu & M_, const btVectorXu & q_)
+ {
+ m_M = M_;
+ m_q = q_;
+ }
+ /***************************************************/
+
+ /**
+ * \brief solve algorithm adapted from : Fast Implementation of Lemke’s Algorithm for Rigid Body Contact Simulation (John E. Lloyd)
+ */
+ btVectorXu solve(unsigned int maxloops = 0);
+
+ virtual ~btLemkeAlgorithm() {
+ }
+
+protected:
+ int findLexicographicMinimum(const btMatrixXu &A, const int & pivotColIndex);
+ bool LexicographicPositive(const btVectorXu & v);
+ void GaussJordanEliminationStep(btMatrixXu &A, int pivotRowIndex, int pivotColumnIndex, const btAlignedObjectArray<int>& basis);
+ bool greaterZero(const btVectorXu & vector);
+ bool validBasis(const btAlignedObjectArray<int>& basis);
+
+ btMatrixXu m_M;
+ btVectorXu m_q;
+
+ /**
+ * \brief number of steps until the Lemke algorithm found a solution
+ */
+ unsigned int steps;
+
+ /**
+ * \brief define level of debug output
+ */
+ int DEBUGLEVEL;
+
+ /**
+ * \brief did the algorithm find a solution
+ *
+ * -1 : not successful
+ * 0 : successful
+ */
+ int info;
+};
+
+
+#endif /* BT_NUMERICS_LEMKE_ALGORITHM_H_ */
diff --git a/thirdparty/bullet/src/BulletDynamics/MLCPSolvers/btLemkeSolver.h b/thirdparty/bullet/src/BulletDynamics/MLCPSolvers/btLemkeSolver.h
new file mode 100644
index 0000000000..98484c3796
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/MLCPSolvers/btLemkeSolver.h
@@ -0,0 +1,350 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2013 Erwin Coumans 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.
+*/
+///original version written by Erwin Coumans, October 2013
+
+#ifndef BT_LEMKE_SOLVER_H
+#define BT_LEMKE_SOLVER_H
+
+
+#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) "
+///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
+{
+protected:
+
+public:
+
+ btScalar m_maxValue;
+ int m_debugLevel;
+ int m_maxLoops;
+ bool m_useLoHighBounds;
+
+
+
+ btLemkeSolver()
+ :m_maxValue(100000),
+ m_debugLevel(0),
+ m_maxLoops(1000),
+ m_useLoHighBounds(true)
+ {
+ }
+ virtual bool solveMLCP(const btMatrixXu & A, const btVectorXu & b, btVectorXu& x, const btVectorXu & lo,const btVectorXu & hi,const btAlignedObjectArray<int>& limitDependency, int numIterations, bool useSparsity = true)
+ {
+
+ if (m_useLoHighBounds)
+ {
+
+ BT_PROFILE("btLemkeSolver::solveMLCP");
+ int n = A.rows();
+ if (0==n)
+ return true;
+
+ bool fail = false;
+
+ btVectorXu solution(n);
+ btVectorXu q1;
+ q1.resize(n);
+ for (int row=0;row<n;row++)
+ {
+ q1[row] = -b[row];
+ }
+
+ // cout << "A" << endl;
+ // cout << A << endl;
+
+ /////////////////////////////////////
+
+ //slow matrix inversion, replace with LU decomposition
+ btMatrixXu A1;
+ btMatrixXu B(n,n);
+ {
+ BT_PROFILE("inverse(slow)");
+ A1.resize(A.rows(),A.cols());
+ for (int row=0;row<A.rows();row++)
+ {
+ for (int col=0;col<A.cols();col++)
+ {
+ A1.setElem(row,col,A(row,col));
+ }
+ }
+
+ btMatrixXu matrix;
+ matrix.resize(n,2*n);
+ for (int row=0;row<n;row++)
+ {
+ for (int col=0;col<n;col++)
+ {
+ matrix.setElem(row,col,A1(row,col));
+ }
+ }
+
+
+ btScalar ratio,a;
+ int i,j,k;
+ for(i = 0; i < n; i++){
+ for(j = n; j < 2*n; j++){
+ if(i==(j-n))
+ matrix.setElem(i,j,1.0);
+ else
+ matrix.setElem(i,j,0.0);
+ }
+ }
+ for(i = 0; i < n; i++){
+ for(j = 0; j < n; j++){
+ if(i!=j)
+ {
+ btScalar v = matrix(i,i);
+ if (btFuzzyZero(v))
+ {
+ a = 0.000001f;
+ }
+ ratio = matrix(j,i)/matrix(i,i);
+ for(k = 0; k < 2*n; k++){
+ matrix.addElem(j,k,- ratio * matrix(i,k));
+ }
+ }
+ }
+ }
+ for(i = 0; i < n; i++){
+ a = matrix(i,i);
+ if (btFuzzyZero(a))
+ {
+ a = 0.000001f;
+ }
+ btScalar invA = 1.f/a;
+ for(j = 0; j < 2*n; j++){
+ matrix.mulElem(i,j,invA);
+ }
+ }
+
+
+
+
+
+ for (int row=0;row<n;row++)
+ {
+ for (int col=0;col<n;col++)
+ {
+ B.setElem(row,col,matrix(row,n+col));
+ }
+ }
+ }
+
+ btMatrixXu b1(n,1);
+
+ btMatrixXu M(n*2,n*2);
+ for (int row=0;row<n;row++)
+ {
+ b1.setElem(row,0,-b[row]);
+ for (int col=0;col<n;col++)
+ {
+ btScalar v =B(row,col);
+ M.setElem(row,col,v);
+ M.setElem(n+row,n+col,v);
+ M.setElem(n+row,col,-v);
+ M.setElem(row,n+col,-v);
+
+ }
+ }
+
+ btMatrixXu Bb1 = B*b1;
+// q = [ (-B*b1 - lo)' (hi + B*b1)' ]'
+
+ btVectorXu qq;
+ qq.resize(n*2);
+ for (int row=0;row<n;row++)
+ {
+ qq[row] = -Bb1(row,0)-lo[row];
+ qq[n+row] = Bb1(row,0)+hi[row];
+ }
+
+ btVectorXu z1;
+
+ btMatrixXu y1;
+ y1.resize(n,1);
+ btLemkeAlgorithm lemke(M,qq,m_debugLevel);
+ {
+ BT_PROFILE("lemke.solve");
+ lemke.setSystem(M,qq);
+ z1 = lemke.solve(m_maxLoops);
+ }
+ for (int row=0;row<n;row++)
+ {
+ y1.setElem(row,0,z1[2*n+row]-z1[3*n+row]);
+ }
+ btMatrixXu y1_b1(n,1);
+ for (int i=0;i<n;i++)
+ {
+ y1_b1.setElem(i,0,y1(i,0)-b1(i,0));
+ }
+
+ btMatrixXu x1;
+
+ x1 = B*(y1_b1);
+
+ for (int row=0;row<n;row++)
+ {
+ solution[row] = x1(row,0);//n];
+ }
+
+ int errorIndexMax = -1;
+ int errorIndexMin = -1;
+ float errorValueMax = -1e30;
+ float errorValueMin = 1e30;
+
+ for (int i=0;i<n;i++)
+ {
+ x[i] = solution[i];
+ volatile btScalar check = x[i];
+ if (x[i] != check)
+ {
+ //printf("Lemke result is #NAN\n");
+ x.setZero();
+ return false;
+ }
+
+ //this is some hack/safety mechanism, to discard invalid solutions from the Lemke solver
+ //we need to figure out why it happens, and fix it, or detect it properly)
+ if (x[i]>m_maxValue)
+ {
+ if (x[i]> errorValueMax)
+ {
+ fail = true;
+ errorIndexMax = i;
+ errorValueMax = x[i];
+ }
+ ////printf("x[i] = %f,",x[i]);
+ }
+ if (x[i]<-m_maxValue)
+ {
+ if (x[i]<errorValueMin)
+ {
+ errorIndexMin = i;
+ errorValueMin = x[i];
+ fail = true;
+ //printf("x[i] = %f,",x[i]);
+ }
+ }
+ }
+ if (fail)
+ {
+ int m_errorCountTimes = 0;
+ if (errorIndexMin<0)
+ errorValueMin = 0.f;
+ if (errorIndexMax<0)
+ errorValueMax = 0.f;
+ m_errorCountTimes++;
+ // printf("Error (x[%d] = %f, x[%d] = %f), resetting %d times\n", errorIndexMin,errorValueMin, errorIndexMax, errorValueMax, errorCountTimes++);
+ for (int i=0;i<n;i++)
+ {
+ x[i]=0.f;
+ }
+ }
+ return !fail;
+ } else
+
+ {
+ int dimension = A.rows();
+ if (0==dimension)
+ return true;
+
+// printf("================ solving using Lemke/Newton/Fixpoint\n");
+
+ btVectorXu q;
+ q.resize(dimension);
+ for (int row=0;row<dimension;row++)
+ {
+ q[row] = -b[row];
+ }
+
+ btLemkeAlgorithm lemke(A,q,m_debugLevel);
+
+
+ lemke.setSystem(A,q);
+
+ btVectorXu solution = lemke.solve(m_maxLoops);
+
+ //check solution
+
+ bool fail = false;
+ int errorIndexMax = -1;
+ int errorIndexMin = -1;
+ float errorValueMax = -1e30;
+ float errorValueMin = 1e30;
+
+ for (int i=0;i<dimension;i++)
+ {
+ x[i] = solution[i+dimension];
+ volatile btScalar check = x[i];
+ if (x[i] != check)
+ {
+ x.setZero();
+ return false;
+ }
+
+ //this is some hack/safety mechanism, to discard invalid solutions from the Lemke solver
+ //we need to figure out why it happens, and fix it, or detect it properly)
+ if (x[i]>m_maxValue)
+ {
+ if (x[i]> errorValueMax)
+ {
+ fail = true;
+ errorIndexMax = i;
+ errorValueMax = x[i];
+ }
+ ////printf("x[i] = %f,",x[i]);
+ }
+ if (x[i]<-m_maxValue)
+ {
+ if (x[i]<errorValueMin)
+ {
+ errorIndexMin = i;
+ errorValueMin = x[i];
+ fail = true;
+ //printf("x[i] = %f,",x[i]);
+ }
+ }
+ }
+ if (fail)
+ {
+ static int errorCountTimes = 0;
+ if (errorIndexMin<0)
+ errorValueMin = 0.f;
+ if (errorIndexMax<0)
+ errorValueMax = 0.f;
+ printf("Error (x[%d] = %f, x[%d] = %f), resetting %d times\n", errorIndexMin,errorValueMin, errorIndexMax, errorValueMax, errorCountTimes++);
+ for (int i=0;i<dimension;i++)
+ {
+ x[i]=0.f;
+ }
+ }
+
+
+ return !fail;
+ }
+ return true;
+
+ }
+
+};
+
+#endif //BT_LEMKE_SOLVER_H
diff --git a/thirdparty/bullet/src/BulletDynamics/MLCPSolvers/btMLCPSolver.cpp b/thirdparty/bullet/src/BulletDynamics/MLCPSolvers/btMLCPSolver.cpp
new file mode 100644
index 0000000000..8f54c52626
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/MLCPSolvers/btMLCPSolver.cpp
@@ -0,0 +1,639 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2013 Erwin Coumans 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.
+*/
+///original version written by Erwin Coumans, October 2013
+
+#include "btMLCPSolver.h"
+#include "LinearMath/btMatrixX.h"
+#include "LinearMath/btQuickprof.h"
+#include "btSolveProjectedGaussSeidel.h"
+
+
+btMLCPSolver::btMLCPSolver( btMLCPSolverInterface* solver)
+:m_solver(solver),
+m_fallback(0)
+{
+}
+
+btMLCPSolver::~btMLCPSolver()
+{
+}
+
+bool gUseMatrixMultiply = false;
+bool interleaveContactAndFriction = false;
+
+btScalar btMLCPSolver::solveGroupCacheFriendlySetup(btCollisionObject** bodies, int numBodiesUnUsed, btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer)
+{
+ btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup( bodies, numBodiesUnUsed, manifoldPtr, numManifolds,constraints,numConstraints,infoGlobal,debugDrawer);
+
+ {
+ BT_PROFILE("gather constraint data");
+
+ int numFrictionPerContact = m_tmpSolverContactConstraintPool.size()==m_tmpSolverContactFrictionConstraintPool.size()? 1 : 2;
+
+
+ // int numBodies = m_tmpSolverBodyPool.size();
+ m_allConstraintPtrArray.resize(0);
+ m_limitDependencies.resize(m_tmpSolverNonContactConstraintPool.size()+m_tmpSolverContactConstraintPool.size()+m_tmpSolverContactFrictionConstraintPool.size());
+ btAssert(m_limitDependencies.size() == m_tmpSolverNonContactConstraintPool.size()+m_tmpSolverContactConstraintPool.size()+m_tmpSolverContactFrictionConstraintPool.size());
+ // printf("m_limitDependencies.size() = %d\n",m_limitDependencies.size());
+
+ int dindex = 0;
+ for (int i=0;i<m_tmpSolverNonContactConstraintPool.size();i++)
+ {
+ m_allConstraintPtrArray.push_back(&m_tmpSolverNonContactConstraintPool[i]);
+ m_limitDependencies[dindex++] = -1;
+ }
+
+ ///The btSequentialImpulseConstraintSolver moves all friction constraints at the very end, we can also interleave them instead
+
+ int firstContactConstraintOffset=dindex;
+
+ if (interleaveContactAndFriction)
+ {
+ for (int i=0;i<m_tmpSolverContactConstraintPool.size();i++)
+ {
+ m_allConstraintPtrArray.push_back(&m_tmpSolverContactConstraintPool[i]);
+ m_limitDependencies[dindex++] = -1;
+ m_allConstraintPtrArray.push_back(&m_tmpSolverContactFrictionConstraintPool[i*numFrictionPerContact]);
+ int findex = (m_tmpSolverContactFrictionConstraintPool[i*numFrictionPerContact].m_frictionIndex*(1+numFrictionPerContact));
+ m_limitDependencies[dindex++] = findex +firstContactConstraintOffset;
+ if (numFrictionPerContact==2)
+ {
+ m_allConstraintPtrArray.push_back(&m_tmpSolverContactFrictionConstraintPool[i*numFrictionPerContact+1]);
+ m_limitDependencies[dindex++] = findex+firstContactConstraintOffset;
+ }
+ }
+ } else
+ {
+ for (int i=0;i<m_tmpSolverContactConstraintPool.size();i++)
+ {
+ m_allConstraintPtrArray.push_back(&m_tmpSolverContactConstraintPool[i]);
+ m_limitDependencies[dindex++] = -1;
+ }
+ for (int i=0;i<m_tmpSolverContactFrictionConstraintPool.size();i++)
+ {
+ m_allConstraintPtrArray.push_back(&m_tmpSolverContactFrictionConstraintPool[i]);
+ m_limitDependencies[dindex++] = m_tmpSolverContactFrictionConstraintPool[i].m_frictionIndex+firstContactConstraintOffset;
+ }
+
+ }
+
+
+ if (!m_allConstraintPtrArray.size())
+ {
+ m_A.resize(0,0);
+ m_b.resize(0);
+ m_x.resize(0);
+ m_lo.resize(0);
+ m_hi.resize(0);
+ return 0.f;
+ }
+ }
+
+
+ if (gUseMatrixMultiply)
+ {
+ BT_PROFILE("createMLCP");
+ createMLCP(infoGlobal);
+ }
+ else
+ {
+ BT_PROFILE("createMLCPFast");
+ createMLCPFast(infoGlobal);
+ }
+
+ return 0.f;
+}
+
+bool btMLCPSolver::solveMLCP(const btContactSolverInfo& infoGlobal)
+{
+ bool result = true;
+
+ if (m_A.rows()==0)
+ return true;
+
+ //if using split impulse, we solve 2 separate (M)LCPs
+ if (infoGlobal.m_splitImpulse)
+ {
+ btMatrixXu Acopy = m_A;
+ btAlignedObjectArray<int> limitDependenciesCopy = m_limitDependencies;
+// printf("solve first LCP\n");
+ result = m_solver->solveMLCP(m_A, m_b, m_x, m_lo,m_hi, m_limitDependencies,infoGlobal.m_numIterations );
+ if (result)
+ result = m_solver->solveMLCP(Acopy, m_bSplit, m_xSplit, m_lo,m_hi, limitDependenciesCopy,infoGlobal.m_numIterations );
+
+ } else
+ {
+ result = m_solver->solveMLCP(m_A, m_b, m_x, m_lo,m_hi, m_limitDependencies,infoGlobal.m_numIterations );
+ }
+ return result;
+}
+
+struct btJointNode
+{
+ int jointIndex; // pointer to enclosing dxJoint object
+ int otherBodyIndex; // *other* body this joint is connected to
+ int nextJointNodeIndex;//-1 for null
+ int constraintRowIndex;
+};
+
+
+
+void btMLCPSolver::createMLCPFast(const btContactSolverInfo& infoGlobal)
+{
+ int numContactRows = interleaveContactAndFriction ? 3 : 1;
+
+ int numConstraintRows = m_allConstraintPtrArray.size();
+ int n = numConstraintRows;
+ {
+ BT_PROFILE("init b (rhs)");
+ m_b.resize(numConstraintRows);
+ m_bSplit.resize(numConstraintRows);
+ m_b.setZero();
+ m_bSplit.setZero();
+ for (int i=0;i<numConstraintRows ;i++)
+ {
+ btScalar jacDiag = m_allConstraintPtrArray[i]->m_jacDiagABInv;
+ if (!btFuzzyZero(jacDiag))
+ {
+ btScalar rhs = m_allConstraintPtrArray[i]->m_rhs;
+ btScalar rhsPenetration = m_allConstraintPtrArray[i]->m_rhsPenetration;
+ m_b[i]=rhs/jacDiag;
+ m_bSplit[i] = rhsPenetration/jacDiag;
+ }
+
+ }
+ }
+
+// btScalar* w = 0;
+// int nub = 0;
+
+ m_lo.resize(numConstraintRows);
+ m_hi.resize(numConstraintRows);
+
+ {
+ BT_PROFILE("init lo/ho");
+
+ for (int i=0;i<numConstraintRows;i++)
+ {
+ if (0)//m_limitDependencies[i]>=0)
+ {
+ m_lo[i] = -BT_INFINITY;
+ m_hi[i] = BT_INFINITY;
+ } else
+ {
+ m_lo[i] = m_allConstraintPtrArray[i]->m_lowerLimit;
+ m_hi[i] = m_allConstraintPtrArray[i]->m_upperLimit;
+ }
+ }
+ }
+
+ //
+ int m=m_allConstraintPtrArray.size();
+
+ int numBodies = m_tmpSolverBodyPool.size();
+ btAlignedObjectArray<int> bodyJointNodeArray;
+ {
+ BT_PROFILE("bodyJointNodeArray.resize");
+ bodyJointNodeArray.resize(numBodies,-1);
+ }
+ btAlignedObjectArray<btJointNode> jointNodeArray;
+ {
+ BT_PROFILE("jointNodeArray.reserve");
+ jointNodeArray.reserve(2*m_allConstraintPtrArray.size());
+ }
+
+ btMatrixXu& J3 = m_scratchJ3;
+ {
+ BT_PROFILE("J3.resize");
+ J3.resize(2*m,8);
+ }
+ btMatrixXu& JinvM3 = m_scratchJInvM3;
+ {
+ BT_PROFILE("JinvM3.resize/setZero");
+
+ JinvM3.resize(2*m,8);
+ JinvM3.setZero();
+ J3.setZero();
+ }
+ int cur=0;
+ int rowOffset = 0;
+ btAlignedObjectArray<int>& ofs = m_scratchOfs;
+ {
+ BT_PROFILE("ofs resize");
+ ofs.resize(0);
+ ofs.resizeNoInitialize(m_allConstraintPtrArray.size());
+ }
+ {
+ BT_PROFILE("Compute J and JinvM");
+ int c=0;
+
+ int numRows = 0;
+
+ for (int i=0;i<m_allConstraintPtrArray.size();i+=numRows,c++)
+ {
+ ofs[c] = rowOffset;
+ int sbA = m_allConstraintPtrArray[i]->m_solverBodyIdA;
+ int sbB = m_allConstraintPtrArray[i]->m_solverBodyIdB;
+ btRigidBody* orgBodyA = m_tmpSolverBodyPool[sbA].m_originalBody;
+ btRigidBody* orgBodyB = m_tmpSolverBodyPool[sbB].m_originalBody;
+
+ numRows = i<m_tmpSolverNonContactConstraintPool.size() ? m_tmpConstraintSizesPool[c].m_numConstraintRows : numContactRows ;
+ if (orgBodyA)
+ {
+ {
+ int slotA=-1;
+ //find free jointNode slot for sbA
+ slotA =jointNodeArray.size();
+ jointNodeArray.expand();//NonInitializing();
+ int prevSlot = bodyJointNodeArray[sbA];
+ bodyJointNodeArray[sbA] = slotA;
+ jointNodeArray[slotA].nextJointNodeIndex = prevSlot;
+ jointNodeArray[slotA].jointIndex = c;
+ jointNodeArray[slotA].constraintRowIndex = i;
+ jointNodeArray[slotA].otherBodyIndex = orgBodyB ? sbB : -1;
+ }
+ for (int row=0;row<numRows;row++,cur++)
+ {
+ btVector3 normalInvMass = m_allConstraintPtrArray[i+row]->m_contactNormal1 * orgBodyA->getInvMass();
+ btVector3 relPosCrossNormalInvInertia = m_allConstraintPtrArray[i+row]->m_relpos1CrossNormal * orgBodyA->getInvInertiaTensorWorld();
+
+ for (int r=0;r<3;r++)
+ {
+ J3.setElem(cur,r,m_allConstraintPtrArray[i+row]->m_contactNormal1[r]);
+ J3.setElem(cur,r+4,m_allConstraintPtrArray[i+row]->m_relpos1CrossNormal[r]);
+ JinvM3.setElem(cur,r,normalInvMass[r]);
+ JinvM3.setElem(cur,r+4,relPosCrossNormalInvInertia[r]);
+ }
+ J3.setElem(cur,3,0);
+ JinvM3.setElem(cur,3,0);
+ J3.setElem(cur,7,0);
+ JinvM3.setElem(cur,7,0);
+ }
+ } else
+ {
+ cur += numRows;
+ }
+ if (orgBodyB)
+ {
+
+ {
+ int slotB=-1;
+ //find free jointNode slot for sbA
+ slotB =jointNodeArray.size();
+ jointNodeArray.expand();//NonInitializing();
+ int prevSlot = bodyJointNodeArray[sbB];
+ bodyJointNodeArray[sbB] = slotB;
+ jointNodeArray[slotB].nextJointNodeIndex = prevSlot;
+ jointNodeArray[slotB].jointIndex = c;
+ jointNodeArray[slotB].otherBodyIndex = orgBodyA ? sbA : -1;
+ jointNodeArray[slotB].constraintRowIndex = i;
+ }
+
+ for (int row=0;row<numRows;row++,cur++)
+ {
+ btVector3 normalInvMassB = m_allConstraintPtrArray[i+row]->m_contactNormal2*orgBodyB->getInvMass();
+ btVector3 relPosInvInertiaB = m_allConstraintPtrArray[i+row]->m_relpos2CrossNormal * orgBodyB->getInvInertiaTensorWorld();
+
+ for (int r=0;r<3;r++)
+ {
+ J3.setElem(cur,r,m_allConstraintPtrArray[i+row]->m_contactNormal2[r]);
+ J3.setElem(cur,r+4,m_allConstraintPtrArray[i+row]->m_relpos2CrossNormal[r]);
+ JinvM3.setElem(cur,r,normalInvMassB[r]);
+ JinvM3.setElem(cur,r+4,relPosInvInertiaB[r]);
+ }
+ J3.setElem(cur,3,0);
+ JinvM3.setElem(cur,3,0);
+ J3.setElem(cur,7,0);
+ JinvM3.setElem(cur,7,0);
+ }
+ }
+ else
+ {
+ cur += numRows;
+ }
+ rowOffset+=numRows;
+
+ }
+
+ }
+
+
+ //compute JinvM = J*invM.
+ const btScalar* JinvM = JinvM3.getBufferPointer();
+
+ const btScalar* Jptr = J3.getBufferPointer();
+ {
+ BT_PROFILE("m_A.resize");
+ m_A.resize(n,n);
+ }
+
+ {
+ BT_PROFILE("m_A.setZero");
+ m_A.setZero();
+ }
+ int c=0;
+ {
+ int numRows = 0;
+ BT_PROFILE("Compute A");
+ for (int i=0;i<m_allConstraintPtrArray.size();i+= numRows,c++)
+ {
+ int row__ = ofs[c];
+ int sbA = m_allConstraintPtrArray[i]->m_solverBodyIdA;
+ int sbB = m_allConstraintPtrArray[i]->m_solverBodyIdB;
+ // btRigidBody* orgBodyA = m_tmpSolverBodyPool[sbA].m_originalBody;
+ // btRigidBody* orgBodyB = m_tmpSolverBodyPool[sbB].m_originalBody;
+
+ numRows = i<m_tmpSolverNonContactConstraintPool.size() ? m_tmpConstraintSizesPool[c].m_numConstraintRows : numContactRows ;
+
+ const btScalar *JinvMrow = JinvM + 2*8*(size_t)row__;
+
+ {
+ int startJointNodeA = bodyJointNodeArray[sbA];
+ while (startJointNodeA>=0)
+ {
+ int j0 = jointNodeArray[startJointNodeA].jointIndex;
+ int cr0 = jointNodeArray[startJointNodeA].constraintRowIndex;
+ if (j0<c)
+ {
+
+ int numRowsOther = cr0 < m_tmpSolverNonContactConstraintPool.size() ? m_tmpConstraintSizesPool[j0].m_numConstraintRows : numContactRows;
+ size_t ofsother = (m_allConstraintPtrArray[cr0]->m_solverBodyIdB == sbA) ? 8*numRowsOther : 0;
+ //printf("%d joint i %d and j0: %d: ",count++,i,j0);
+ m_A.multiplyAdd2_p8r ( JinvMrow,
+ Jptr + 2*8*(size_t)ofs[j0] + ofsother, numRows, numRowsOther, row__,ofs[j0]);
+ }
+ startJointNodeA = jointNodeArray[startJointNodeA].nextJointNodeIndex;
+ }
+ }
+
+ {
+ int startJointNodeB = bodyJointNodeArray[sbB];
+ while (startJointNodeB>=0)
+ {
+ int j1 = jointNodeArray[startJointNodeB].jointIndex;
+ int cj1 = jointNodeArray[startJointNodeB].constraintRowIndex;
+
+ if (j1<c)
+ {
+ int numRowsOther = cj1 < m_tmpSolverNonContactConstraintPool.size() ? m_tmpConstraintSizesPool[j1].m_numConstraintRows : numContactRows;
+ size_t ofsother = (m_allConstraintPtrArray[cj1]->m_solverBodyIdB == sbB) ? 8*numRowsOther : 0;
+ m_A.multiplyAdd2_p8r ( JinvMrow + 8*(size_t)numRows,
+ Jptr + 2*8*(size_t)ofs[j1] + ofsother, numRows, numRowsOther, row__,ofs[j1]);
+ }
+ startJointNodeB = jointNodeArray[startJointNodeB].nextJointNodeIndex;
+ }
+ }
+ }
+
+ {
+ BT_PROFILE("compute diagonal");
+ // compute diagonal blocks of m_A
+
+ int row__ = 0;
+ int numJointRows = m_allConstraintPtrArray.size();
+
+ int jj=0;
+ for (;row__<numJointRows;)
+ {
+
+ //int sbA = m_allConstraintPtrArray[row__]->m_solverBodyIdA;
+ int sbB = m_allConstraintPtrArray[row__]->m_solverBodyIdB;
+ // btRigidBody* orgBodyA = m_tmpSolverBodyPool[sbA].m_originalBody;
+ btRigidBody* orgBodyB = m_tmpSolverBodyPool[sbB].m_originalBody;
+
+
+ const unsigned int infom = row__ < m_tmpSolverNonContactConstraintPool.size() ? m_tmpConstraintSizesPool[jj].m_numConstraintRows : numContactRows;
+
+ const btScalar *JinvMrow = JinvM + 2*8*(size_t)row__;
+ const btScalar *Jrow = Jptr + 2*8*(size_t)row__;
+ m_A.multiply2_p8r (JinvMrow, Jrow, infom, infom, row__,row__);
+ if (orgBodyB)
+ {
+ m_A.multiplyAdd2_p8r (JinvMrow + 8*(size_t)infom, Jrow + 8*(size_t)infom, infom, infom, row__,row__);
+ }
+ row__ += infom;
+ jj++;
+ }
+ }
+ }
+
+ if (1)
+ {
+ // add cfm to the diagonal of m_A
+ for ( int i=0; i<m_A.rows(); ++i)
+ {
+ m_A.setElem(i,i,m_A(i,i)+ infoGlobal.m_globalCfm/ infoGlobal.m_timeStep);
+ }
+ }
+
+ ///fill the upper triangle of the matrix, to make it symmetric
+ {
+ BT_PROFILE("fill the upper triangle ");
+ m_A.copyLowerToUpperTriangle();
+ }
+
+ {
+ BT_PROFILE("resize/init x");
+ m_x.resize(numConstraintRows);
+ m_xSplit.resize(numConstraintRows);
+
+ if (infoGlobal.m_solverMode&SOLVER_USE_WARMSTARTING)
+ {
+ for (int i=0;i<m_allConstraintPtrArray.size();i++)
+ {
+ const btSolverConstraint& c = *m_allConstraintPtrArray[i];
+ m_x[i]=c.m_appliedImpulse;
+ m_xSplit[i] = c.m_appliedPushImpulse;
+ }
+ } else
+ {
+ m_x.setZero();
+ m_xSplit.setZero();
+ }
+ }
+
+}
+
+void btMLCPSolver::createMLCP(const btContactSolverInfo& infoGlobal)
+{
+ int numBodies = this->m_tmpSolverBodyPool.size();
+ int numConstraintRows = m_allConstraintPtrArray.size();
+
+ m_b.resize(numConstraintRows);
+ if (infoGlobal.m_splitImpulse)
+ m_bSplit.resize(numConstraintRows);
+
+ m_bSplit.setZero();
+ m_b.setZero();
+
+ for (int i=0;i<numConstraintRows ;i++)
+ {
+ if (m_allConstraintPtrArray[i]->m_jacDiagABInv)
+ {
+ m_b[i]=m_allConstraintPtrArray[i]->m_rhs/m_allConstraintPtrArray[i]->m_jacDiagABInv;
+ if (infoGlobal.m_splitImpulse)
+ m_bSplit[i] = m_allConstraintPtrArray[i]->m_rhsPenetration/m_allConstraintPtrArray[i]->m_jacDiagABInv;
+ }
+ }
+
+ btMatrixXu& Minv = m_scratchMInv;
+ Minv.resize(6*numBodies,6*numBodies);
+ Minv.setZero();
+ for (int i=0;i<numBodies;i++)
+ {
+ const btSolverBody& rb = m_tmpSolverBodyPool[i];
+ const btVector3& invMass = rb.m_invMass;
+ setElem(Minv,i*6+0,i*6+0,invMass[0]);
+ setElem(Minv,i*6+1,i*6+1,invMass[1]);
+ setElem(Minv,i*6+2,i*6+2,invMass[2]);
+ btRigidBody* orgBody = m_tmpSolverBodyPool[i].m_originalBody;
+
+ for (int r=0;r<3;r++)
+ for (int c=0;c<3;c++)
+ setElem(Minv,i*6+3+r,i*6+3+c,orgBody? orgBody->getInvInertiaTensorWorld()[r][c] : 0);
+ }
+
+ btMatrixXu& J = m_scratchJ;
+ J.resize(numConstraintRows,6*numBodies);
+ J.setZero();
+
+ m_lo.resize(numConstraintRows);
+ m_hi.resize(numConstraintRows);
+
+ for (int i=0;i<numConstraintRows;i++)
+ {
+
+ m_lo[i] = m_allConstraintPtrArray[i]->m_lowerLimit;
+ m_hi[i] = m_allConstraintPtrArray[i]->m_upperLimit;
+
+ int bodyIndex0 = m_allConstraintPtrArray[i]->m_solverBodyIdA;
+ int bodyIndex1 = m_allConstraintPtrArray[i]->m_solverBodyIdB;
+ if (m_tmpSolverBodyPool[bodyIndex0].m_originalBody)
+ {
+ setElem(J,i,6*bodyIndex0+0,m_allConstraintPtrArray[i]->m_contactNormal1[0]);
+ setElem(J,i,6*bodyIndex0+1,m_allConstraintPtrArray[i]->m_contactNormal1[1]);
+ setElem(J,i,6*bodyIndex0+2,m_allConstraintPtrArray[i]->m_contactNormal1[2]);
+ setElem(J,i,6*bodyIndex0+3,m_allConstraintPtrArray[i]->m_relpos1CrossNormal[0]);
+ setElem(J,i,6*bodyIndex0+4,m_allConstraintPtrArray[i]->m_relpos1CrossNormal[1]);
+ setElem(J,i,6*bodyIndex0+5,m_allConstraintPtrArray[i]->m_relpos1CrossNormal[2]);
+ }
+ if (m_tmpSolverBodyPool[bodyIndex1].m_originalBody)
+ {
+ setElem(J,i,6*bodyIndex1+0,m_allConstraintPtrArray[i]->m_contactNormal2[0]);
+ setElem(J,i,6*bodyIndex1+1,m_allConstraintPtrArray[i]->m_contactNormal2[1]);
+ setElem(J,i,6*bodyIndex1+2,m_allConstraintPtrArray[i]->m_contactNormal2[2]);
+ setElem(J,i,6*bodyIndex1+3,m_allConstraintPtrArray[i]->m_relpos2CrossNormal[0]);
+ setElem(J,i,6*bodyIndex1+4,m_allConstraintPtrArray[i]->m_relpos2CrossNormal[1]);
+ setElem(J,i,6*bodyIndex1+5,m_allConstraintPtrArray[i]->m_relpos2CrossNormal[2]);
+ }
+ }
+
+ btMatrixXu& J_transpose = m_scratchJTranspose;
+ J_transpose= J.transpose();
+
+ btMatrixXu& tmp = m_scratchTmp;
+
+ {
+ {
+ BT_PROFILE("J*Minv");
+ tmp = J*Minv;
+
+ }
+ {
+ BT_PROFILE("J*tmp");
+ m_A = tmp*J_transpose;
+ }
+ }
+
+ if (1)
+ {
+ // add cfm to the diagonal of m_A
+ for ( int i=0; i<m_A.rows(); ++i)
+ {
+ m_A.setElem(i,i,m_A(i,i)+ infoGlobal.m_globalCfm / infoGlobal.m_timeStep);
+ }
+ }
+
+ m_x.resize(numConstraintRows);
+ if (infoGlobal.m_splitImpulse)
+ m_xSplit.resize(numConstraintRows);
+// m_x.setZero();
+
+ for (int i=0;i<m_allConstraintPtrArray.size();i++)
+ {
+ const btSolverConstraint& c = *m_allConstraintPtrArray[i];
+ m_x[i]=c.m_appliedImpulse;
+ if (infoGlobal.m_splitImpulse)
+ m_xSplit[i] = c.m_appliedPushImpulse;
+ }
+
+}
+
+
+btScalar btMLCPSolver::solveGroupCacheFriendlyIterations(btCollisionObject** bodies ,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer)
+{
+ bool result = true;
+ {
+ BT_PROFILE("solveMLCP");
+// printf("m_A(%d,%d)\n", m_A.rows(),m_A.cols());
+ result = solveMLCP(infoGlobal);
+ }
+
+ //check if solution is valid, and otherwise fallback to btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyIterations
+ if (result)
+ {
+ BT_PROFILE("process MLCP results");
+ for (int i=0;i<m_allConstraintPtrArray.size();i++)
+ {
+ {
+ btSolverConstraint& c = *m_allConstraintPtrArray[i];
+ int sbA = c.m_solverBodyIdA;
+ int sbB = c.m_solverBodyIdB;
+ //btRigidBody* orgBodyA = m_tmpSolverBodyPool[sbA].m_originalBody;
+ // btRigidBody* orgBodyB = m_tmpSolverBodyPool[sbB].m_originalBody;
+
+ btSolverBody& solverBodyA = m_tmpSolverBodyPool[sbA];
+ btSolverBody& solverBodyB = m_tmpSolverBodyPool[sbB];
+
+ {
+ btScalar deltaImpulse = m_x[i]-c.m_appliedImpulse;
+ c.m_appliedImpulse = m_x[i];
+ solverBodyA.internalApplyImpulse(c.m_contactNormal1*solverBodyA.internalGetInvMass(),c.m_angularComponentA,deltaImpulse);
+ solverBodyB.internalApplyImpulse(c.m_contactNormal2*solverBodyB.internalGetInvMass(),c.m_angularComponentB,deltaImpulse);
+ }
+
+ if (infoGlobal.m_splitImpulse)
+ {
+ btScalar deltaImpulse = m_xSplit[i] - c.m_appliedPushImpulse;
+ solverBodyA.internalApplyPushImpulse(c.m_contactNormal1*solverBodyA.internalGetInvMass(),c.m_angularComponentA,deltaImpulse);
+ solverBodyB.internalApplyPushImpulse(c.m_contactNormal2*solverBodyB.internalGetInvMass(),c.m_angularComponentB,deltaImpulse);
+ c.m_appliedPushImpulse = m_xSplit[i];
+ }
+
+ }
+ }
+ }
+ else
+ {
+ // printf("m_fallback = %d\n",m_fallback);
+ m_fallback++;
+ btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyIterations(bodies ,numBodies,manifoldPtr, numManifolds,constraints,numConstraints,infoGlobal,debugDrawer);
+ }
+
+ return 0.f;
+}
+
+
diff --git a/thirdparty/bullet/src/BulletDynamics/MLCPSolvers/btMLCPSolver.h b/thirdparty/bullet/src/BulletDynamics/MLCPSolvers/btMLCPSolver.h
new file mode 100644
index 0000000000..26b482ddc1
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/MLCPSolvers/btMLCPSolver.h
@@ -0,0 +1,94 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2013 Erwin Coumans 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.
+*/
+///original version written by Erwin Coumans, October 2013
+
+#ifndef BT_MLCP_SOLVER_H
+#define BT_MLCP_SOLVER_H
+
+#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h"
+#include "LinearMath/btMatrixX.h"
+#include "BulletDynamics/MLCPSolvers/btMLCPSolverInterface.h"
+
+class btMLCPSolver : public btSequentialImpulseConstraintSolver
+{
+
+protected:
+
+ btMatrixXu m_A;
+ btVectorXu m_b;
+ btVectorXu m_x;
+ btVectorXu m_lo;
+ btVectorXu m_hi;
+
+ ///when using 'split impulse' we solve two separate (M)LCPs
+ btVectorXu m_bSplit;
+ btVectorXu m_xSplit;
+ btVectorXu m_bSplit1;
+ btVectorXu m_xSplit2;
+
+ btAlignedObjectArray<int> m_limitDependencies;
+ btAlignedObjectArray<btSolverConstraint*> m_allConstraintPtrArray;
+ btMLCPSolverInterface* m_solver;
+ int m_fallback;
+
+ /// The following scratch variables are not stateful -- contents are cleared prior to each use.
+ /// They are only cached here to avoid extra memory allocations and deallocations and to ensure
+ /// that multiple instances of the solver can be run in parallel.
+ btMatrixXu m_scratchJ3;
+ btMatrixXu m_scratchJInvM3;
+ btAlignedObjectArray<int> m_scratchOfs;
+ btMatrixXu m_scratchMInv;
+ btMatrixXu m_scratchJ;
+ btMatrixXu m_scratchJTranspose;
+ btMatrixXu m_scratchTmp;
+
+ 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 void createMLCP(const btContactSolverInfo& infoGlobal);
+ virtual void createMLCPFast(const btContactSolverInfo& infoGlobal);
+
+ //return true is it solves the problem successfully
+ virtual bool solveMLCP(const btContactSolverInfo& infoGlobal);
+
+public:
+
+ btMLCPSolver( btMLCPSolverInterface* solver);
+ virtual ~btMLCPSolver();
+
+ void setMLCPSolver(btMLCPSolverInterface* solver)
+ {
+ m_solver = solver;
+ }
+
+ int getNumFallbacks() const
+ {
+ return m_fallback;
+ }
+ void setNumFallbacks(int num)
+ {
+ m_fallback = num;
+ }
+
+ virtual btConstraintSolverType getSolverType() const
+ {
+ return BT_MLCP_SOLVER;
+ }
+
+};
+
+
+#endif //BT_MLCP_SOLVER_H
diff --git a/thirdparty/bullet/src/BulletDynamics/MLCPSolvers/btMLCPSolverInterface.h b/thirdparty/bullet/src/BulletDynamics/MLCPSolvers/btMLCPSolverInterface.h
new file mode 100644
index 0000000000..25bb3f6d32
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/MLCPSolvers/btMLCPSolverInterface.h
@@ -0,0 +1,33 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2013 Erwin Coumans 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.
+*/
+///original version written by Erwin Coumans, October 2013
+
+#ifndef BT_MLCP_SOLVER_INTERFACE_H
+#define BT_MLCP_SOLVER_INTERFACE_H
+
+#include "LinearMath/btMatrixX.h"
+
+class btMLCPSolverInterface
+{
+public:
+ virtual ~btMLCPSolverInterface()
+ {
+ }
+
+ //return true is it solves the problem successfully
+ virtual bool solveMLCP(const btMatrixXu & A, const btVectorXu & b, btVectorXu& x, const btVectorXu & lo,const btVectorXu & hi,const btAlignedObjectArray<int>& limitDependency, int numIterations, bool useSparsity = true)=0;
+};
+
+#endif //BT_MLCP_SOLVER_INTERFACE_H
diff --git a/thirdparty/bullet/src/BulletDynamics/MLCPSolvers/btPATHSolver.h b/thirdparty/bullet/src/BulletDynamics/MLCPSolvers/btPATHSolver.h
new file mode 100644
index 0000000000..9ec31a6d4e
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/MLCPSolvers/btPATHSolver.h
@@ -0,0 +1,151 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2013 Erwin Coumans 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.
+*/
+///original version written by Erwin Coumans, October 2013
+
+
+#ifndef BT_PATH_SOLVER_H
+#define BT_PATH_SOLVER_H
+
+//#define BT_USE_PATH
+#ifdef BT_USE_PATH
+
+extern "C" {
+#include "PATH/SimpleLCP.h"
+#include "PATH/License.h"
+#include "PATH/Error_Interface.h"
+};
+ void __stdcall MyError(Void *data, Char *msg)
+{
+ printf("Path Error: %s\n",msg);
+}
+ void __stdcall MyWarning(Void *data, Char *msg)
+{
+ printf("Path Warning: %s\n",msg);
+}
+
+Error_Interface e;
+
+
+
+#include "btMLCPSolverInterface.h"
+#include "Dantzig/lcp.h"
+
+class btPathSolver : public btMLCPSolverInterface
+{
+public:
+
+ btPathSolver()
+ {
+ License_SetString("2069810742&Courtesy_License&&&USR&2013&14_12_2011&1000&PATH&GEN&31_12_2013&0_0_0&0&0_0");
+ e.error_data = 0;
+ e.warning = MyWarning;
+ e.error = MyError;
+ Error_SetInterface(&e);
+ }
+
+
+ virtual bool solveMLCP(const btMatrixXu & A, const btVectorXu & b, btVectorXu& x, const btVectorXu & lo,const btVectorXu & hi,const btAlignedObjectArray<int>& limitDependency, int numIterations, bool useSparsity = true)
+ {
+ MCP_Termination status;
+
+
+ int numVariables = b.rows();
+ if (0==numVariables)
+ return true;
+
+ /* - variables - the number of variables in the problem
+ - m_nnz - the number of nonzeros in the M matrix
+ - m_i - a vector of size m_nnz containing the row indices for M
+ - m_j - a vector of size m_nnz containing the column indices for M
+ - m_ij - a vector of size m_nnz containing the data for M
+ - q - a vector of size variables
+ - lb - a vector of size variables containing the lower bounds on x
+ - ub - a vector of size variables containing the upper bounds on x
+ */
+ btAlignedObjectArray<double> values;
+ btAlignedObjectArray<int> rowIndices;
+ btAlignedObjectArray<int> colIndices;
+
+ for (int i=0;i<A.rows();i++)
+ {
+ for (int j=0;j<A.cols();j++)
+ {
+ if (A(i,j)!=0.f)
+ {
+ //add 1, because Path starts at 1, instead of 0
+ rowIndices.push_back(i+1);
+ colIndices.push_back(j+1);
+ values.push_back(A(i,j));
+ }
+ }
+ }
+ int numNonZero = rowIndices.size();
+ btAlignedObjectArray<double> zResult;
+ zResult.resize(numVariables);
+ btAlignedObjectArray<double> rhs;
+ btAlignedObjectArray<double> upperBounds;
+ btAlignedObjectArray<double> lowerBounds;
+ for (int i=0;i<numVariables;i++)
+ {
+ upperBounds.push_back(hi[i]);
+ lowerBounds.push_back(lo[i]);
+ rhs.push_back(-b[i]);
+ }
+
+
+ SimpleLCP(numVariables,numNonZero,&rowIndices[0],&colIndices[0],&values[0],&rhs[0],&lowerBounds[0],&upperBounds[0], &status, &zResult[0]);
+
+ if (status != MCP_Solved)
+ {
+ static const char* gReturnMsgs[] = {
+ "Invalid return",
+ "MCP_Solved: The problem was solved",
+ "MCP_NoProgress: A stationary point was found",
+ "MCP_MajorIterationLimit: Major iteration limit met",
+ "MCP_MinorIterationLimit: Cumulative minor iteration limit met",
+ "MCP_TimeLimit: Ran out of time",
+ "MCP_UserInterrupt: Control-C, typically",
+ "MCP_BoundError: Problem has a bound error",
+ "MCP_DomainError: Could not find starting point",
+ "MCP_Infeasible: Problem has no solution",
+ "MCP_Error: An error occurred within the code",
+ "MCP_LicenseError: License could not be found",
+ "MCP_OK"
+ };
+
+ printf("ERROR: The PATH MCP solver failed: %s\n", gReturnMsgs[(unsigned int)status]);// << std::endl;
+ printf("using Projected Gauss Seidel fallback\n");
+
+ return false;
+ } else
+ {
+ for (int i=0;i<numVariables;i++)
+ {
+ x[i] = zResult[i];
+ //check for #NAN
+ if (x[i] != zResult[i])
+ return false;
+ }
+ return true;
+
+ }
+
+ }
+};
+
+#endif //BT_USE_PATH
+
+
+#endif //BT_PATH_SOLVER_H
diff --git a/thirdparty/bullet/src/BulletDynamics/MLCPSolvers/btSolveProjectedGaussSeidel.h b/thirdparty/bullet/src/BulletDynamics/MLCPSolvers/btSolveProjectedGaussSeidel.h
new file mode 100644
index 0000000000..c0b40ffd9f
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/MLCPSolvers/btSolveProjectedGaussSeidel.h
@@ -0,0 +1,110 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2013 Erwin Coumans 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.
+*/
+///original version written by Erwin Coumans, October 2013
+
+#ifndef BT_SOLVE_PROJECTED_GAUSS_SEIDEL_H
+#define BT_SOLVE_PROJECTED_GAUSS_SEIDEL_H
+
+
+#include "btMLCPSolverInterface.h"
+
+///This solver is mainly for debug/learning purposes: it is functionally equivalent to the btSequentialImpulseConstraintSolver solver, but much slower (it builds the full LCP matrix)
+class btSolveProjectedGaussSeidel : public btMLCPSolverInterface
+{
+
+public:
+
+ btScalar m_leastSquaresResidualThreshold;
+ btScalar m_leastSquaresResidual;
+
+ btSolveProjectedGaussSeidel()
+ :m_leastSquaresResidualThreshold(0),
+ m_leastSquaresResidual(0)
+ {
+ }
+
+ virtual bool solveMLCP(const btMatrixXu & A, const btVectorXu & b, btVectorXu& x, const btVectorXu & lo,const btVectorXu & hi,const btAlignedObjectArray<int>& limitDependency, int numIterations, bool useSparsity = true)
+ {
+ if (!A.rows())
+ return true;
+ //the A matrix is sparse, so compute the non-zero elements
+ A.rowComputeNonZeroElements();
+
+ //A is a m-n matrix, m rows, n columns
+ btAssert(A.rows() == b.rows());
+
+ int i, j, numRows = A.rows();
+
+ btScalar delta;
+
+ for (int k = 0; k <numIterations; k++)
+ {
+ m_leastSquaresResidual = 0.f;
+ for (i = 0; i <numRows; i++)
+ {
+ delta = 0.0f;
+ if (useSparsity)
+ {
+ for (int h=0;h<A.m_rowNonZeroElements1[i].size();h++)
+ {
+ int j = A.m_rowNonZeroElements1[i][h];
+ if (j != i)//skip main diagonal
+ {
+ delta += A(i,j) * x[j];
+ }
+ }
+ } else
+ {
+ for (j = 0; j <i; j++)
+ delta += A(i,j) * x[j];
+ for (j = i+1; j<numRows; j++)
+ delta += A(i,j) * x[j];
+ }
+
+ btScalar aDiag = A(i,i);
+ btScalar xOld = x[i];
+ x [i] = (b [i] - delta) / aDiag;
+ btScalar s = 1.f;
+
+ if (limitDependency[i]>=0)
+ {
+ s = x[limitDependency[i]];
+ if (s<0)
+ s=1;
+ }
+
+ if (x[i]<lo[i]*s)
+ x[i]=lo[i]*s;
+ if (x[i]>hi[i]*s)
+ x[i]=hi[i]*s;
+ btScalar diff = x[i] - xOld;
+ m_leastSquaresResidual += diff*diff;
+ }
+
+ btScalar eps = m_leastSquaresResidualThreshold;
+ if ((m_leastSquaresResidual < eps) || (k >=(numIterations-1)))
+ {
+#ifdef VERBOSE_PRINTF_RESIDUAL
+ printf("totalLenSqr = %f at iteration #%d\n", m_leastSquaresResidual,k);
+#endif
+ break;
+ }
+ }
+ return true;
+ }
+
+};
+
+#endif //BT_SOLVE_PROJECTED_GAUSS_SEIDEL_H
diff --git a/thirdparty/bullet/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp b/thirdparty/bullet/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp
new file mode 100644
index 0000000000..a7b1688469
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp
@@ -0,0 +1,772 @@
+/*
+ * Copyright (c) 2005 Erwin Coumans http://continuousphysics.com/Bullet/
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies.
+ * Erwin Coumans makes no representations about the suitability
+ * of this software for any purpose.
+ * It is provided "as is" without express or implied warranty.
+*/
+
+#include "LinearMath/btVector3.h"
+#include "btRaycastVehicle.h"
+
+#include "BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btJacobianEntry.h"
+#include "LinearMath/btQuaternion.h"
+#include "BulletDynamics/Dynamics/btDynamicsWorld.h"
+#include "btVehicleRaycaster.h"
+#include "btWheelInfo.h"
+#include "LinearMath/btMinMax.h"
+#include "LinearMath/btIDebugDraw.h"
+#include "BulletDynamics/ConstraintSolver/btContactConstraint.h"
+
+#define ROLLING_INFLUENCE_FIX
+
+
+btRigidBody& btActionInterface::getFixedBody()
+{
+ static btRigidBody s_fixed(0, 0,0);
+ s_fixed.setMassProps(btScalar(0.),btVector3(btScalar(0.),btScalar(0.),btScalar(0.)));
+ return s_fixed;
+}
+
+btRaycastVehicle::btRaycastVehicle(const btVehicleTuning& tuning,btRigidBody* chassis, btVehicleRaycaster* raycaster )
+:m_vehicleRaycaster(raycaster),
+m_pitchControl(btScalar(0.))
+{
+ m_chassisBody = chassis;
+ m_indexRightAxis = 0;
+ m_indexUpAxis = 2;
+ m_indexForwardAxis = 1;
+ defaultInit(tuning);
+}
+
+
+void btRaycastVehicle::defaultInit(const btVehicleTuning& tuning)
+{
+ (void)tuning;
+ m_currentVehicleSpeedKmHour = btScalar(0.);
+ m_steeringValue = btScalar(0.);
+
+}
+
+
+
+btRaycastVehicle::~btRaycastVehicle()
+{
+}
+
+
+//
+// basically most of the code is general for 2 or 4 wheel vehicles, but some of it needs to be reviewed
+//
+btWheelInfo& btRaycastVehicle::addWheel( const btVector3& connectionPointCS, const btVector3& wheelDirectionCS0,const btVector3& wheelAxleCS, btScalar suspensionRestLength, btScalar wheelRadius,const btVehicleTuning& tuning, bool isFrontWheel)
+{
+
+ btWheelInfoConstructionInfo ci;
+
+ ci.m_chassisConnectionCS = connectionPointCS;
+ ci.m_wheelDirectionCS = wheelDirectionCS0;
+ ci.m_wheelAxleCS = wheelAxleCS;
+ ci.m_suspensionRestLength = suspensionRestLength;
+ ci.m_wheelRadius = wheelRadius;
+ ci.m_suspensionStiffness = tuning.m_suspensionStiffness;
+ ci.m_wheelsDampingCompression = tuning.m_suspensionCompression;
+ ci.m_wheelsDampingRelaxation = tuning.m_suspensionDamping;
+ ci.m_frictionSlip = tuning.m_frictionSlip;
+ ci.m_bIsFrontWheel = isFrontWheel;
+ ci.m_maxSuspensionTravelCm = tuning.m_maxSuspensionTravelCm;
+ ci.m_maxSuspensionForce = tuning.m_maxSuspensionForce;
+
+ m_wheelInfo.push_back( btWheelInfo(ci));
+
+ btWheelInfo& wheel = m_wheelInfo[getNumWheels()-1];
+
+ updateWheelTransformsWS( wheel , false );
+ updateWheelTransform(getNumWheels()-1,false);
+ return wheel;
+}
+
+
+
+
+const btTransform& btRaycastVehicle::getWheelTransformWS( int wheelIndex ) const
+{
+ btAssert(wheelIndex < getNumWheels());
+ const btWheelInfo& wheel = m_wheelInfo[wheelIndex];
+ return wheel.m_worldTransform;
+
+}
+
+void btRaycastVehicle::updateWheelTransform( int wheelIndex , bool interpolatedTransform)
+{
+
+ btWheelInfo& wheel = m_wheelInfo[ wheelIndex ];
+ updateWheelTransformsWS(wheel,interpolatedTransform);
+ btVector3 up = -wheel.m_raycastInfo.m_wheelDirectionWS;
+ const btVector3& right = wheel.m_raycastInfo.m_wheelAxleWS;
+ btVector3 fwd = up.cross(right);
+ fwd = fwd.normalize();
+// up = right.cross(fwd);
+// up.normalize();
+
+ //rotate around steering over de wheelAxleWS
+ btScalar steering = wheel.m_steering;
+
+ btQuaternion steeringOrn(up,steering);//wheel.m_steering);
+ btMatrix3x3 steeringMat(steeringOrn);
+
+ btQuaternion rotatingOrn(right,-wheel.m_rotation);
+ btMatrix3x3 rotatingMat(rotatingOrn);
+
+ btMatrix3x3 basis2(
+ right[0],fwd[0],up[0],
+ right[1],fwd[1],up[1],
+ right[2],fwd[2],up[2]
+ );
+
+ wheel.m_worldTransform.setBasis(steeringMat * rotatingMat * basis2);
+ wheel.m_worldTransform.setOrigin(
+ wheel.m_raycastInfo.m_hardPointWS + wheel.m_raycastInfo.m_wheelDirectionWS * wheel.m_raycastInfo.m_suspensionLength
+ );
+}
+
+void btRaycastVehicle::resetSuspension()
+{
+
+ int i;
+ for (i=0;i<m_wheelInfo.size(); i++)
+ {
+ btWheelInfo& wheel = m_wheelInfo[i];
+ wheel.m_raycastInfo.m_suspensionLength = wheel.getSuspensionRestLength();
+ wheel.m_suspensionRelativeVelocity = btScalar(0.0);
+
+ wheel.m_raycastInfo.m_contactNormalWS = - wheel.m_raycastInfo.m_wheelDirectionWS;
+ //wheel_info.setContactFriction(btScalar(0.0));
+ wheel.m_clippedInvContactDotSuspension = btScalar(1.0);
+ }
+}
+
+void btRaycastVehicle::updateWheelTransformsWS(btWheelInfo& wheel , bool interpolatedTransform)
+{
+ wheel.m_raycastInfo.m_isInContact = false;
+
+ btTransform chassisTrans = getChassisWorldTransform();
+ if (interpolatedTransform && (getRigidBody()->getMotionState()))
+ {
+ getRigidBody()->getMotionState()->getWorldTransform(chassisTrans);
+ }
+
+ wheel.m_raycastInfo.m_hardPointWS = chassisTrans( wheel.m_chassisConnectionPointCS );
+ wheel.m_raycastInfo.m_wheelDirectionWS = chassisTrans.getBasis() * wheel.m_wheelDirectionCS ;
+ wheel.m_raycastInfo.m_wheelAxleWS = chassisTrans.getBasis() * wheel.m_wheelAxleCS;
+}
+
+btScalar btRaycastVehicle::rayCast(btWheelInfo& wheel)
+{
+ updateWheelTransformsWS( wheel,false);
+
+
+ btScalar depth = -1;
+
+ btScalar raylen = wheel.getSuspensionRestLength()+wheel.m_wheelsRadius;
+
+ btVector3 rayvector = wheel.m_raycastInfo.m_wheelDirectionWS * (raylen);
+ const btVector3& source = wheel.m_raycastInfo.m_hardPointWS;
+ wheel.m_raycastInfo.m_contactPointWS = source + rayvector;
+ const btVector3& target = wheel.m_raycastInfo.m_contactPointWS;
+
+ btScalar param = btScalar(0.);
+
+ btVehicleRaycaster::btVehicleRaycasterResult rayResults;
+
+ btAssert(m_vehicleRaycaster);
+
+ void* object = m_vehicleRaycaster->castRay(source,target,rayResults);
+
+ wheel.m_raycastInfo.m_groundObject = 0;
+
+ if (object)
+ {
+ param = rayResults.m_distFraction;
+ depth = raylen * rayResults.m_distFraction;
+ wheel.m_raycastInfo.m_contactNormalWS = rayResults.m_hitNormalInWorld;
+ wheel.m_raycastInfo.m_isInContact = true;
+
+ wheel.m_raycastInfo.m_groundObject = &getFixedBody();///@todo for driving on dynamic/movable objects!;
+ //wheel.m_raycastInfo.m_groundObject = object;
+
+
+ btScalar hitDistance = param*raylen;
+ wheel.m_raycastInfo.m_suspensionLength = hitDistance - wheel.m_wheelsRadius;
+ //clamp on max suspension travel
+
+ btScalar minSuspensionLength = wheel.getSuspensionRestLength() - wheel.m_maxSuspensionTravelCm*btScalar(0.01);
+ btScalar maxSuspensionLength = wheel.getSuspensionRestLength()+ wheel.m_maxSuspensionTravelCm*btScalar(0.01);
+ if (wheel.m_raycastInfo.m_suspensionLength < minSuspensionLength)
+ {
+ wheel.m_raycastInfo.m_suspensionLength = minSuspensionLength;
+ }
+ if (wheel.m_raycastInfo.m_suspensionLength > maxSuspensionLength)
+ {
+ wheel.m_raycastInfo.m_suspensionLength = maxSuspensionLength;
+ }
+
+ wheel.m_raycastInfo.m_contactPointWS = rayResults.m_hitPointInWorld;
+
+ btScalar denominator= wheel.m_raycastInfo.m_contactNormalWS.dot( wheel.m_raycastInfo.m_wheelDirectionWS );
+
+ btVector3 chassis_velocity_at_contactPoint;
+ btVector3 relpos = wheel.m_raycastInfo.m_contactPointWS-getRigidBody()->getCenterOfMassPosition();
+
+ chassis_velocity_at_contactPoint = getRigidBody()->getVelocityInLocalPoint(relpos);
+
+ btScalar projVel = wheel.m_raycastInfo.m_contactNormalWS.dot( chassis_velocity_at_contactPoint );
+
+ if ( denominator >= btScalar(-0.1))
+ {
+ wheel.m_suspensionRelativeVelocity = btScalar(0.0);
+ wheel.m_clippedInvContactDotSuspension = btScalar(1.0) / btScalar(0.1);
+ }
+ else
+ {
+ btScalar inv = btScalar(-1.) / denominator;
+ wheel.m_suspensionRelativeVelocity = projVel * inv;
+ wheel.m_clippedInvContactDotSuspension = inv;
+ }
+
+ } else
+ {
+ //put wheel info as in rest position
+ wheel.m_raycastInfo.m_suspensionLength = wheel.getSuspensionRestLength();
+ wheel.m_suspensionRelativeVelocity = btScalar(0.0);
+ wheel.m_raycastInfo.m_contactNormalWS = - wheel.m_raycastInfo.m_wheelDirectionWS;
+ wheel.m_clippedInvContactDotSuspension = btScalar(1.0);
+ }
+
+ return depth;
+}
+
+
+const btTransform& btRaycastVehicle::getChassisWorldTransform() const
+{
+ /*if (getRigidBody()->getMotionState())
+ {
+ btTransform chassisWorldTrans;
+ getRigidBody()->getMotionState()->getWorldTransform(chassisWorldTrans);
+ return chassisWorldTrans;
+ }
+ */
+
+
+ return getRigidBody()->getCenterOfMassTransform();
+}
+
+
+void btRaycastVehicle::updateVehicle( btScalar step )
+{
+ {
+ for (int i=0;i<getNumWheels();i++)
+ {
+ updateWheelTransform(i,false);
+ }
+ }
+
+
+ m_currentVehicleSpeedKmHour = btScalar(3.6) * getRigidBody()->getLinearVelocity().length();
+
+ const btTransform& chassisTrans = getChassisWorldTransform();
+
+ btVector3 forwardW (
+ chassisTrans.getBasis()[0][m_indexForwardAxis],
+ chassisTrans.getBasis()[1][m_indexForwardAxis],
+ chassisTrans.getBasis()[2][m_indexForwardAxis]);
+
+ if (forwardW.dot(getRigidBody()->getLinearVelocity()) < btScalar(0.))
+ {
+ m_currentVehicleSpeedKmHour *= btScalar(-1.);
+ }
+
+ //
+ // simulate suspension
+ //
+
+ int i=0;
+ for (i=0;i<m_wheelInfo.size();i++)
+ {
+ //btScalar depth;
+ //depth =
+ rayCast( m_wheelInfo[i]);
+ }
+
+ updateSuspension(step);
+
+
+ for (i=0;i<m_wheelInfo.size();i++)
+ {
+ //apply suspension force
+ btWheelInfo& wheel = m_wheelInfo[i];
+
+ btScalar suspensionForce = wheel.m_wheelsSuspensionForce;
+
+ if (suspensionForce > wheel.m_maxSuspensionForce)
+ {
+ suspensionForce = wheel.m_maxSuspensionForce;
+ }
+ btVector3 impulse = wheel.m_raycastInfo.m_contactNormalWS * suspensionForce * step;
+ btVector3 relpos = wheel.m_raycastInfo.m_contactPointWS - getRigidBody()->getCenterOfMassPosition();
+
+ getRigidBody()->applyImpulse(impulse, relpos);
+
+ }
+
+
+
+ updateFriction( step);
+
+
+ for (i=0;i<m_wheelInfo.size();i++)
+ {
+ btWheelInfo& wheel = m_wheelInfo[i];
+ btVector3 relpos = wheel.m_raycastInfo.m_hardPointWS - getRigidBody()->getCenterOfMassPosition();
+ btVector3 vel = getRigidBody()->getVelocityInLocalPoint( relpos );
+
+ if (wheel.m_raycastInfo.m_isInContact)
+ {
+ const btTransform& chassisWorldTransform = getChassisWorldTransform();
+
+ btVector3 fwd (
+ chassisWorldTransform.getBasis()[0][m_indexForwardAxis],
+ chassisWorldTransform.getBasis()[1][m_indexForwardAxis],
+ chassisWorldTransform.getBasis()[2][m_indexForwardAxis]);
+
+ btScalar proj = fwd.dot(wheel.m_raycastInfo.m_contactNormalWS);
+ fwd -= wheel.m_raycastInfo.m_contactNormalWS * proj;
+
+ btScalar proj2 = fwd.dot(vel);
+
+ wheel.m_deltaRotation = (proj2 * step) / (wheel.m_wheelsRadius);
+ wheel.m_rotation += wheel.m_deltaRotation;
+
+ } else
+ {
+ wheel.m_rotation += wheel.m_deltaRotation;
+ }
+
+ wheel.m_deltaRotation *= btScalar(0.99);//damping of rotation when not in contact
+
+ }
+
+
+
+}
+
+
+void btRaycastVehicle::setSteeringValue(btScalar steering,int wheel)
+{
+ btAssert(wheel>=0 && wheel < getNumWheels());
+
+ btWheelInfo& wheelInfo = getWheelInfo(wheel);
+ wheelInfo.m_steering = steering;
+}
+
+
+
+btScalar btRaycastVehicle::getSteeringValue(int wheel) const
+{
+ return getWheelInfo(wheel).m_steering;
+}
+
+
+void btRaycastVehicle::applyEngineForce(btScalar force, int wheel)
+{
+ btAssert(wheel>=0 && wheel < getNumWheels());
+ btWheelInfo& wheelInfo = getWheelInfo(wheel);
+ wheelInfo.m_engineForce = force;
+}
+
+
+const btWheelInfo& btRaycastVehicle::getWheelInfo(int index) const
+{
+ btAssert((index >= 0) && (index < getNumWheels()));
+
+ return m_wheelInfo[index];
+}
+
+btWheelInfo& btRaycastVehicle::getWheelInfo(int index)
+{
+ btAssert((index >= 0) && (index < getNumWheels()));
+
+ return m_wheelInfo[index];
+}
+
+void btRaycastVehicle::setBrake(btScalar brake,int wheelIndex)
+{
+ btAssert((wheelIndex >= 0) && (wheelIndex < getNumWheels()));
+ getWheelInfo(wheelIndex).m_brake = brake;
+}
+
+
+void btRaycastVehicle::updateSuspension(btScalar deltaTime)
+{
+ (void)deltaTime;
+
+ btScalar chassisMass = btScalar(1.) / m_chassisBody->getInvMass();
+
+ for (int w_it=0; w_it<getNumWheels(); w_it++)
+ {
+ btWheelInfo &wheel_info = m_wheelInfo[w_it];
+
+ if ( wheel_info.m_raycastInfo.m_isInContact )
+ {
+ btScalar force;
+ // Spring
+ {
+ btScalar susp_length = wheel_info.getSuspensionRestLength();
+ btScalar current_length = wheel_info.m_raycastInfo.m_suspensionLength;
+
+ btScalar length_diff = (susp_length - current_length);
+
+ force = wheel_info.m_suspensionStiffness
+ * length_diff * wheel_info.m_clippedInvContactDotSuspension;
+ }
+
+ // Damper
+ {
+ btScalar projected_rel_vel = wheel_info.m_suspensionRelativeVelocity;
+ {
+ btScalar susp_damping;
+ if ( projected_rel_vel < btScalar(0.0) )
+ {
+ susp_damping = wheel_info.m_wheelsDampingCompression;
+ }
+ else
+ {
+ susp_damping = wheel_info.m_wheelsDampingRelaxation;
+ }
+ force -= susp_damping * projected_rel_vel;
+ }
+ }
+
+ // RESULT
+ wheel_info.m_wheelsSuspensionForce = force * chassisMass;
+ if (wheel_info.m_wheelsSuspensionForce < btScalar(0.))
+ {
+ wheel_info.m_wheelsSuspensionForce = btScalar(0.);
+ }
+ }
+ else
+ {
+ wheel_info.m_wheelsSuspensionForce = btScalar(0.0);
+ }
+ }
+
+}
+
+
+struct btWheelContactPoint
+{
+ btRigidBody* m_body0;
+ btRigidBody* m_body1;
+ btVector3 m_frictionPositionWorld;
+ btVector3 m_frictionDirectionWorld;
+ btScalar m_jacDiagABInv;
+ btScalar m_maxImpulse;
+
+
+ btWheelContactPoint(btRigidBody* body0,btRigidBody* body1,const btVector3& frictionPosWorld,const btVector3& frictionDirectionWorld, btScalar maxImpulse)
+ :m_body0(body0),
+ m_body1(body1),
+ m_frictionPositionWorld(frictionPosWorld),
+ m_frictionDirectionWorld(frictionDirectionWorld),
+ m_maxImpulse(maxImpulse)
+ {
+ btScalar denom0 = body0->computeImpulseDenominator(frictionPosWorld,frictionDirectionWorld);
+ btScalar denom1 = body1->computeImpulseDenominator(frictionPosWorld,frictionDirectionWorld);
+ btScalar relaxation = 1.f;
+ m_jacDiagABInv = relaxation/(denom0+denom1);
+ }
+
+
+
+};
+
+btScalar calcRollingFriction(btWheelContactPoint& contactPoint);
+btScalar calcRollingFriction(btWheelContactPoint& contactPoint)
+{
+
+ btScalar j1=0.f;
+
+ const btVector3& contactPosWorld = contactPoint.m_frictionPositionWorld;
+
+ btVector3 rel_pos1 = contactPosWorld - contactPoint.m_body0->getCenterOfMassPosition();
+ btVector3 rel_pos2 = contactPosWorld - contactPoint.m_body1->getCenterOfMassPosition();
+
+ btScalar maxImpulse = contactPoint.m_maxImpulse;
+
+ btVector3 vel1 = contactPoint.m_body0->getVelocityInLocalPoint(rel_pos1);
+ btVector3 vel2 = contactPoint.m_body1->getVelocityInLocalPoint(rel_pos2);
+ btVector3 vel = vel1 - vel2;
+
+ btScalar vrel = contactPoint.m_frictionDirectionWorld.dot(vel);
+
+ // calculate j that moves us to zero relative velocity
+ j1 = -vrel * contactPoint.m_jacDiagABInv;
+ btSetMin(j1, maxImpulse);
+ btSetMax(j1, -maxImpulse);
+
+ return j1;
+}
+
+
+
+
+btScalar sideFrictionStiffness2 = btScalar(1.0);
+void btRaycastVehicle::updateFriction(btScalar timeStep)
+{
+
+ //calculate the impulse, so that the wheels don't move sidewards
+ int numWheel = getNumWheels();
+ if (!numWheel)
+ return;
+
+ m_forwardWS.resize(numWheel);
+ m_axle.resize(numWheel);
+ m_forwardImpulse.resize(numWheel);
+ m_sideImpulse.resize(numWheel);
+
+ int numWheelsOnGround = 0;
+
+
+ //collapse all those loops into one!
+ for (int i=0;i<getNumWheels();i++)
+ {
+ btWheelInfo& wheelInfo = m_wheelInfo[i];
+ class btRigidBody* groundObject = (class btRigidBody*) wheelInfo.m_raycastInfo.m_groundObject;
+ if (groundObject)
+ numWheelsOnGround++;
+ m_sideImpulse[i] = btScalar(0.);
+ m_forwardImpulse[i] = btScalar(0.);
+
+ }
+
+ {
+
+ for (int i=0;i<getNumWheels();i++)
+ {
+
+ btWheelInfo& wheelInfo = m_wheelInfo[i];
+
+ class btRigidBody* groundObject = (class btRigidBody*) wheelInfo.m_raycastInfo.m_groundObject;
+
+ if (groundObject)
+ {
+
+ const btTransform& wheelTrans = getWheelTransformWS( i );
+
+ btMatrix3x3 wheelBasis0 = wheelTrans.getBasis();
+ m_axle[i] = btVector3(
+ wheelBasis0[0][m_indexRightAxis],
+ wheelBasis0[1][m_indexRightAxis],
+ wheelBasis0[2][m_indexRightAxis]);
+
+ const btVector3& surfNormalWS = wheelInfo.m_raycastInfo.m_contactNormalWS;
+ btScalar proj = m_axle[i].dot(surfNormalWS);
+ m_axle[i] -= surfNormalWS * proj;
+ m_axle[i] = m_axle[i].normalize();
+
+ m_forwardWS[i] = surfNormalWS.cross(m_axle[i]);
+ m_forwardWS[i].normalize();
+
+
+ resolveSingleBilateral(*m_chassisBody, wheelInfo.m_raycastInfo.m_contactPointWS,
+ *groundObject, wheelInfo.m_raycastInfo.m_contactPointWS,
+ btScalar(0.), m_axle[i],m_sideImpulse[i],timeStep);
+
+ m_sideImpulse[i] *= sideFrictionStiffness2;
+
+ }
+
+
+ }
+ }
+
+ btScalar sideFactor = btScalar(1.);
+ btScalar fwdFactor = 0.5;
+
+ bool sliding = false;
+ {
+ for (int wheel =0;wheel <getNumWheels();wheel++)
+ {
+ btWheelInfo& wheelInfo = m_wheelInfo[wheel];
+ class btRigidBody* groundObject = (class btRigidBody*) wheelInfo.m_raycastInfo.m_groundObject;
+
+ btScalar rollingFriction = 0.f;
+
+ if (groundObject)
+ {
+ if (wheelInfo.m_engineForce != 0.f)
+ {
+ rollingFriction = wheelInfo.m_engineForce* timeStep;
+ } else
+ {
+ btScalar defaultRollingFrictionImpulse = 0.f;
+ btScalar maxImpulse = wheelInfo.m_brake ? wheelInfo.m_brake : defaultRollingFrictionImpulse;
+ btWheelContactPoint contactPt(m_chassisBody,groundObject,wheelInfo.m_raycastInfo.m_contactPointWS,m_forwardWS[wheel],maxImpulse);
+ rollingFriction = calcRollingFriction(contactPt);
+ }
+ }
+
+ //switch between active rolling (throttle), braking and non-active rolling friction (no throttle/break)
+
+
+
+
+ m_forwardImpulse[wheel] = btScalar(0.);
+ m_wheelInfo[wheel].m_skidInfo= btScalar(1.);
+
+ if (groundObject)
+ {
+ m_wheelInfo[wheel].m_skidInfo= btScalar(1.);
+
+ btScalar maximp = wheelInfo.m_wheelsSuspensionForce * timeStep * wheelInfo.m_frictionSlip;
+ btScalar maximpSide = maximp;
+
+ btScalar maximpSquared = maximp * maximpSide;
+
+
+ m_forwardImpulse[wheel] = rollingFriction;//wheelInfo.m_engineForce* timeStep;
+
+ btScalar x = (m_forwardImpulse[wheel] ) * fwdFactor;
+ btScalar y = (m_sideImpulse[wheel] ) * sideFactor;
+
+ btScalar impulseSquared = (x*x + y*y);
+
+ if (impulseSquared > maximpSquared)
+ {
+ sliding = true;
+
+ btScalar factor = maximp / btSqrt(impulseSquared);
+
+ m_wheelInfo[wheel].m_skidInfo *= factor;
+ }
+ }
+
+ }
+ }
+
+
+
+
+ if (sliding)
+ {
+ for (int wheel = 0;wheel < getNumWheels(); wheel++)
+ {
+ if (m_sideImpulse[wheel] != btScalar(0.))
+ {
+ if (m_wheelInfo[wheel].m_skidInfo< btScalar(1.))
+ {
+ m_forwardImpulse[wheel] *= m_wheelInfo[wheel].m_skidInfo;
+ m_sideImpulse[wheel] *= m_wheelInfo[wheel].m_skidInfo;
+ }
+ }
+ }
+ }
+
+ // apply the impulses
+ {
+ for (int wheel = 0;wheel<getNumWheels() ; wheel++)
+ {
+ btWheelInfo& wheelInfo = m_wheelInfo[wheel];
+
+ btVector3 rel_pos = wheelInfo.m_raycastInfo.m_contactPointWS -
+ m_chassisBody->getCenterOfMassPosition();
+
+ if (m_forwardImpulse[wheel] != btScalar(0.))
+ {
+ m_chassisBody->applyImpulse(m_forwardWS[wheel]*(m_forwardImpulse[wheel]),rel_pos);
+ }
+ if (m_sideImpulse[wheel] != btScalar(0.))
+ {
+ class btRigidBody* groundObject = (class btRigidBody*) m_wheelInfo[wheel].m_raycastInfo.m_groundObject;
+
+ btVector3 rel_pos2 = wheelInfo.m_raycastInfo.m_contactPointWS -
+ groundObject->getCenterOfMassPosition();
+
+
+ btVector3 sideImp = m_axle[wheel] * m_sideImpulse[wheel];
+
+#if defined ROLLING_INFLUENCE_FIX // fix. It only worked if car's up was along Y - VT.
+ btVector3 vChassisWorldUp = getRigidBody()->getCenterOfMassTransform().getBasis().getColumn(m_indexUpAxis);
+ rel_pos -= vChassisWorldUp * (vChassisWorldUp.dot(rel_pos) * (1.f-wheelInfo.m_rollInfluence));
+#else
+ rel_pos[m_indexUpAxis] *= wheelInfo.m_rollInfluence;
+#endif
+ m_chassisBody->applyImpulse(sideImp,rel_pos);
+
+ //apply friction impulse on the ground
+ groundObject->applyImpulse(-sideImp,rel_pos2);
+ }
+ }
+ }
+
+
+}
+
+
+
+void btRaycastVehicle::debugDraw(btIDebugDraw* debugDrawer)
+{
+
+ for (int v=0;v<this->getNumWheels();v++)
+ {
+ btVector3 wheelColor(0,1,1);
+ if (getWheelInfo(v).m_raycastInfo.m_isInContact)
+ {
+ wheelColor.setValue(0,0,1);
+ } else
+ {
+ wheelColor.setValue(1,0,1);
+ }
+
+ btVector3 wheelPosWS = getWheelInfo(v).m_worldTransform.getOrigin();
+
+ btVector3 axle = btVector3(
+ getWheelInfo(v).m_worldTransform.getBasis()[0][getRightAxis()],
+ getWheelInfo(v).m_worldTransform.getBasis()[1][getRightAxis()],
+ getWheelInfo(v).m_worldTransform.getBasis()[2][getRightAxis()]);
+
+ //debug wheels (cylinders)
+ debugDrawer->drawLine(wheelPosWS,wheelPosWS+axle,wheelColor);
+ debugDrawer->drawLine(wheelPosWS,getWheelInfo(v).m_raycastInfo.m_contactPointWS,wheelColor);
+
+ }
+}
+
+
+void* btDefaultVehicleRaycaster::castRay(const btVector3& from,const btVector3& to, btVehicleRaycasterResult& result)
+{
+// RayResultCallback& resultCallback;
+
+ btCollisionWorld::ClosestRayResultCallback rayCallback(from,to);
+
+ m_dynamicsWorld->rayTest(from, to, rayCallback);
+
+ if (rayCallback.hasHit())
+ {
+
+ const btRigidBody* body = btRigidBody::upcast(rayCallback.m_collisionObject);
+ if (body && body->hasContactResponse())
+ {
+ result.m_hitPointInWorld = rayCallback.m_hitPointWorld;
+ result.m_hitNormalInWorld = rayCallback.m_hitNormalWorld;
+ result.m_hitNormalInWorld.normalize();
+ result.m_distFraction = rayCallback.m_closestHitFraction;
+ return (void*)body;
+ }
+ }
+ return 0;
+}
+
diff --git a/thirdparty/bullet/src/BulletDynamics/Vehicle/btRaycastVehicle.h b/thirdparty/bullet/src/BulletDynamics/Vehicle/btRaycastVehicle.h
new file mode 100644
index 0000000000..04656b912c
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/Vehicle/btRaycastVehicle.h
@@ -0,0 +1,234 @@
+/*
+ * Copyright (c) 2005 Erwin Coumans http://continuousphysics.com/Bullet/
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies.
+ * Erwin Coumans makes no representations about the suitability
+ * of this software for any purpose.
+ * It is provided "as is" without express or implied warranty.
+*/
+#ifndef BT_RAYCASTVEHICLE_H
+#define BT_RAYCASTVEHICLE_H
+
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
+#include "btVehicleRaycaster.h"
+class btDynamicsWorld;
+#include "LinearMath/btAlignedObjectArray.h"
+#include "btWheelInfo.h"
+#include "BulletDynamics/Dynamics/btActionInterface.h"
+
+//class btVehicleTuning;
+
+///rayCast vehicle, very special constraint that turn a rigidbody into a vehicle.
+class btRaycastVehicle : public btActionInterface
+{
+
+ btAlignedObjectArray<btVector3> m_forwardWS;
+ btAlignedObjectArray<btVector3> m_axle;
+ btAlignedObjectArray<btScalar> m_forwardImpulse;
+ btAlignedObjectArray<btScalar> m_sideImpulse;
+
+ ///backwards compatibility
+ int m_userConstraintType;
+ int m_userConstraintId;
+
+public:
+ class btVehicleTuning
+ {
+ public:
+
+ btVehicleTuning()
+ :m_suspensionStiffness(btScalar(5.88)),
+ m_suspensionCompression(btScalar(0.83)),
+ m_suspensionDamping(btScalar(0.88)),
+ m_maxSuspensionTravelCm(btScalar(500.)),
+ m_frictionSlip(btScalar(10.5)),
+ m_maxSuspensionForce(btScalar(6000.))
+ {
+ }
+ btScalar m_suspensionStiffness;
+ btScalar m_suspensionCompression;
+ btScalar m_suspensionDamping;
+ btScalar m_maxSuspensionTravelCm;
+ btScalar m_frictionSlip;
+ btScalar m_maxSuspensionForce;
+
+ };
+private:
+
+ btVehicleRaycaster* m_vehicleRaycaster;
+ btScalar m_pitchControl;
+ btScalar m_steeringValue;
+ btScalar m_currentVehicleSpeedKmHour;
+
+ btRigidBody* m_chassisBody;
+
+ int m_indexRightAxis;
+ int m_indexUpAxis;
+ int m_indexForwardAxis;
+
+ void defaultInit(const btVehicleTuning& tuning);
+
+public:
+
+ //constructor to create a car from an existing rigidbody
+ btRaycastVehicle(const btVehicleTuning& tuning,btRigidBody* chassis, btVehicleRaycaster* raycaster );
+
+ virtual ~btRaycastVehicle() ;
+
+
+ ///btActionInterface interface
+ virtual void updateAction( btCollisionWorld* collisionWorld, btScalar step)
+ {
+ (void) collisionWorld;
+ updateVehicle(step);
+ }
+
+
+ ///btActionInterface interface
+ void debugDraw(btIDebugDraw* debugDrawer);
+
+ const btTransform& getChassisWorldTransform() const;
+
+ btScalar rayCast(btWheelInfo& wheel);
+
+ virtual void updateVehicle(btScalar step);
+
+
+ void resetSuspension();
+
+ btScalar getSteeringValue(int wheel) const;
+
+ void setSteeringValue(btScalar steering,int wheel);
+
+
+ void applyEngineForce(btScalar force, int wheel);
+
+ const btTransform& getWheelTransformWS( int wheelIndex ) const;
+
+ void updateWheelTransform( int wheelIndex, bool interpolatedTransform = true );
+
+// void setRaycastWheelInfo( int wheelIndex , bool isInContact, const btVector3& hitPoint, const btVector3& hitNormal,btScalar depth);
+
+ btWheelInfo& addWheel( const btVector3& connectionPointCS0, const btVector3& wheelDirectionCS0,const btVector3& wheelAxleCS,btScalar suspensionRestLength,btScalar wheelRadius,const btVehicleTuning& tuning, bool isFrontWheel);
+
+ inline int getNumWheels() const {
+ return int (m_wheelInfo.size());
+ }
+
+ btAlignedObjectArray<btWheelInfo> m_wheelInfo;
+
+
+ const btWheelInfo& getWheelInfo(int index) const;
+
+ btWheelInfo& getWheelInfo(int index);
+
+ void updateWheelTransformsWS(btWheelInfo& wheel , bool interpolatedTransform = true);
+
+
+ void setBrake(btScalar brake,int wheelIndex);
+
+ void setPitchControl(btScalar pitch)
+ {
+ m_pitchControl = pitch;
+ }
+
+ void updateSuspension(btScalar deltaTime);
+
+ virtual void updateFriction(btScalar timeStep);
+
+
+
+ inline btRigidBody* getRigidBody()
+ {
+ return m_chassisBody;
+ }
+
+ const btRigidBody* getRigidBody() const
+ {
+ return m_chassisBody;
+ }
+
+ inline int getRightAxis() const
+ {
+ return m_indexRightAxis;
+ }
+ inline int getUpAxis() const
+ {
+ return m_indexUpAxis;
+ }
+
+ inline int getForwardAxis() const
+ {
+ return m_indexForwardAxis;
+ }
+
+
+ ///Worldspace forward vector
+ btVector3 getForwardVector() const
+ {
+ const btTransform& chassisTrans = getChassisWorldTransform();
+
+ btVector3 forwardW (
+ chassisTrans.getBasis()[0][m_indexForwardAxis],
+ chassisTrans.getBasis()[1][m_indexForwardAxis],
+ chassisTrans.getBasis()[2][m_indexForwardAxis]);
+
+ return forwardW;
+ }
+
+ ///Velocity of vehicle (positive if velocity vector has same direction as foward vector)
+ btScalar getCurrentSpeedKmHour() const
+ {
+ return m_currentVehicleSpeedKmHour;
+ }
+
+ virtual void setCoordinateSystem(int rightIndex,int upIndex,int forwardIndex)
+ {
+ m_indexRightAxis = rightIndex;
+ m_indexUpAxis = upIndex;
+ m_indexForwardAxis = forwardIndex;
+ }
+
+
+ ///backwards compatibility
+ int getUserConstraintType() const
+ {
+ return m_userConstraintType ;
+ }
+
+ void setUserConstraintType(int userConstraintType)
+ {
+ m_userConstraintType = userConstraintType;
+ };
+
+ void setUserConstraintId(int uid)
+ {
+ m_userConstraintId = uid;
+ }
+
+ int getUserConstraintId() const
+ {
+ return m_userConstraintId;
+ }
+
+};
+
+class btDefaultVehicleRaycaster : public btVehicleRaycaster
+{
+ btDynamicsWorld* m_dynamicsWorld;
+public:
+ btDefaultVehicleRaycaster(btDynamicsWorld* world)
+ :m_dynamicsWorld(world)
+ {
+ }
+
+ virtual void* castRay(const btVector3& from,const btVector3& to, btVehicleRaycasterResult& result);
+
+};
+
+
+#endif //BT_RAYCASTVEHICLE_H
+
diff --git a/thirdparty/bullet/src/BulletDynamics/Vehicle/btVehicleRaycaster.h b/thirdparty/bullet/src/BulletDynamics/Vehicle/btVehicleRaycaster.h
new file mode 100644
index 0000000000..3cc909c653
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/Vehicle/btVehicleRaycaster.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2005 Erwin Coumans http://bulletphysics.org
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies.
+ * Erwin Coumans makes no representations about the suitability
+ * of this software for any purpose.
+ * It is provided "as is" without express or implied warranty.
+*/
+#ifndef BT_VEHICLE_RAYCASTER_H
+#define BT_VEHICLE_RAYCASTER_H
+
+#include "LinearMath/btVector3.h"
+
+/// btVehicleRaycaster is provides interface for between vehicle simulation and raycasting
+struct btVehicleRaycaster
+{
+virtual ~btVehicleRaycaster()
+{
+}
+ struct btVehicleRaycasterResult
+ {
+ btVehicleRaycasterResult() :m_distFraction(btScalar(-1.)){};
+ btVector3 m_hitPointInWorld;
+ btVector3 m_hitNormalInWorld;
+ btScalar m_distFraction;
+ };
+
+ virtual void* castRay(const btVector3& from,const btVector3& to, btVehicleRaycasterResult& result) = 0;
+
+};
+
+#endif //BT_VEHICLE_RAYCASTER_H
+
diff --git a/thirdparty/bullet/src/BulletDynamics/Vehicle/btWheelInfo.cpp b/thirdparty/bullet/src/BulletDynamics/Vehicle/btWheelInfo.cpp
new file mode 100644
index 0000000000..ef93c16fff
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/Vehicle/btWheelInfo.cpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2005 Erwin Coumans http://continuousphysics.com/Bullet/
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies.
+ * Erwin Coumans makes no representations about the suitability
+ * of this software for any purpose.
+ * It is provided "as is" without express or implied warranty.
+*/
+#include "btWheelInfo.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h" // for pointvelocity
+
+
+btScalar btWheelInfo::getSuspensionRestLength() const
+{
+
+ return m_suspensionRestLength1;
+
+}
+
+void btWheelInfo::updateWheel(const btRigidBody& chassis,RaycastInfo& raycastInfo)
+{
+ (void)raycastInfo;
+
+
+ if (m_raycastInfo.m_isInContact)
+
+ {
+ btScalar project= m_raycastInfo.m_contactNormalWS.dot( m_raycastInfo.m_wheelDirectionWS );
+ btVector3 chassis_velocity_at_contactPoint;
+ btVector3 relpos = m_raycastInfo.m_contactPointWS - chassis.getCenterOfMassPosition();
+ chassis_velocity_at_contactPoint = chassis.getVelocityInLocalPoint( relpos );
+ btScalar projVel = m_raycastInfo.m_contactNormalWS.dot( chassis_velocity_at_contactPoint );
+ if ( project >= btScalar(-0.1))
+ {
+ m_suspensionRelativeVelocity = btScalar(0.0);
+ m_clippedInvContactDotSuspension = btScalar(1.0) / btScalar(0.1);
+ }
+ else
+ {
+ btScalar inv = btScalar(-1.) / project;
+ m_suspensionRelativeVelocity = projVel * inv;
+ m_clippedInvContactDotSuspension = inv;
+ }
+
+ }
+
+ else // Not in contact : position wheel in a nice (rest length) position
+ {
+ m_raycastInfo.m_suspensionLength = this->getSuspensionRestLength();
+ m_suspensionRelativeVelocity = btScalar(0.0);
+ m_raycastInfo.m_contactNormalWS = -m_raycastInfo.m_wheelDirectionWS;
+ m_clippedInvContactDotSuspension = btScalar(1.0);
+ }
+}
diff --git a/thirdparty/bullet/src/BulletDynamics/Vehicle/btWheelInfo.h b/thirdparty/bullet/src/BulletDynamics/Vehicle/btWheelInfo.h
new file mode 100644
index 0000000000..f991a57b69
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/Vehicle/btWheelInfo.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2005 Erwin Coumans http://continuousphysics.com/Bullet/
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies.
+ * Erwin Coumans makes no representations about the suitability
+ * of this software for any purpose.
+ * It is provided "as is" without express or implied warranty.
+*/
+#ifndef BT_WHEEL_INFO_H
+#define BT_WHEEL_INFO_H
+
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btTransform.h"
+
+class btRigidBody;
+
+struct btWheelInfoConstructionInfo
+{
+ btVector3 m_chassisConnectionCS;
+ btVector3 m_wheelDirectionCS;
+ btVector3 m_wheelAxleCS;
+ btScalar m_suspensionRestLength;
+ btScalar m_maxSuspensionTravelCm;
+ btScalar m_wheelRadius;
+
+ btScalar m_suspensionStiffness;
+ btScalar m_wheelsDampingCompression;
+ btScalar m_wheelsDampingRelaxation;
+ btScalar m_frictionSlip;
+ btScalar m_maxSuspensionForce;
+ bool m_bIsFrontWheel;
+
+};
+
+/// btWheelInfo contains information per wheel about friction and suspension.
+struct btWheelInfo
+{
+ struct RaycastInfo
+ {
+ //set by raycaster
+ btVector3 m_contactNormalWS;//contactnormal
+ btVector3 m_contactPointWS;//raycast hitpoint
+ btScalar m_suspensionLength;
+ btVector3 m_hardPointWS;//raycast starting point
+ btVector3 m_wheelDirectionWS; //direction in worldspace
+ btVector3 m_wheelAxleWS; // axle in worldspace
+ bool m_isInContact;
+ void* m_groundObject; //could be general void* ptr
+ };
+
+ RaycastInfo m_raycastInfo;
+
+ btTransform m_worldTransform;
+
+ btVector3 m_chassisConnectionPointCS; //const
+ btVector3 m_wheelDirectionCS;//const
+ btVector3 m_wheelAxleCS; // const or modified by steering
+ btScalar m_suspensionRestLength1;//const
+ btScalar m_maxSuspensionTravelCm;
+ btScalar getSuspensionRestLength() const;
+ btScalar m_wheelsRadius;//const
+ btScalar m_suspensionStiffness;//const
+ btScalar m_wheelsDampingCompression;//const
+ btScalar m_wheelsDampingRelaxation;//const
+ btScalar m_frictionSlip;
+ btScalar m_steering;
+ btScalar m_rotation;
+ btScalar m_deltaRotation;
+ btScalar m_rollInfluence;
+ btScalar m_maxSuspensionForce;
+
+ btScalar m_engineForce;
+
+ btScalar m_brake;
+
+ bool m_bIsFrontWheel;
+
+ void* m_clientInfo;//can be used to store pointer to sync transforms...
+
+ btWheelInfo() {}
+
+ btWheelInfo(btWheelInfoConstructionInfo& ci)
+
+ {
+
+ m_suspensionRestLength1 = ci.m_suspensionRestLength;
+ m_maxSuspensionTravelCm = ci.m_maxSuspensionTravelCm;
+
+ m_wheelsRadius = ci.m_wheelRadius;
+ m_suspensionStiffness = ci.m_suspensionStiffness;
+ m_wheelsDampingCompression = ci.m_wheelsDampingCompression;
+ m_wheelsDampingRelaxation = ci.m_wheelsDampingRelaxation;
+ m_chassisConnectionPointCS = ci.m_chassisConnectionCS;
+ m_wheelDirectionCS = ci.m_wheelDirectionCS;
+ m_wheelAxleCS = ci.m_wheelAxleCS;
+ m_frictionSlip = ci.m_frictionSlip;
+ m_steering = btScalar(0.);
+ m_engineForce = btScalar(0.);
+ m_rotation = btScalar(0.);
+ m_deltaRotation = btScalar(0.);
+ m_brake = btScalar(0.);
+ m_rollInfluence = btScalar(0.1);
+ m_bIsFrontWheel = ci.m_bIsFrontWheel;
+ m_maxSuspensionForce = ci.m_maxSuspensionForce;
+
+ }
+
+ void updateWheel(const btRigidBody& chassis,RaycastInfo& raycastInfo);
+
+ btScalar m_clippedInvContactDotSuspension;
+ btScalar m_suspensionRelativeVelocity;
+ //calculated by suspension
+ btScalar m_wheelsSuspensionForce;
+ btScalar m_skidInfo;
+
+};
+
+#endif //BT_WHEEL_INFO_H
+
diff --git a/thirdparty/bullet/src/BulletDynamics/premake4.lua b/thirdparty/bullet/src/BulletDynamics/premake4.lua
new file mode 100644
index 0000000000..32414dce3e
--- /dev/null
+++ b/thirdparty/bullet/src/BulletDynamics/premake4.lua
@@ -0,0 +1,21 @@
+ project "BulletDynamics"
+ kind "StaticLib"
+ includedirs {
+ "..",
+ }
+ files {
+ "Dynamics/*.cpp",
+ "Dynamics/*.h",
+ "ConstraintSolver/*.cpp",
+ "ConstraintSolver/*.h",
+ "Featherstone/*.cpp",
+ "Featherstone/*.h",
+ "MLCPSolvers/*.cpp",
+ "MLCPSolvers/*.h",
+ "Vehicle/*.cpp",
+ "Vehicle/*.h",
+ "Character/*.cpp",
+ "Character/*.h"
+
+ }
+
diff --git a/thirdparty/bullet/src/BulletInverseDynamics/CMakeLists.txt b/thirdparty/bullet/src/BulletInverseDynamics/CMakeLists.txt
new file mode 100644
index 0000000000..3331c27eac
--- /dev/null
+++ b/thirdparty/bullet/src/BulletInverseDynamics/CMakeLists.txt
@@ -0,0 +1,66 @@
+INCLUDE_DIRECTORIES( ${BULLET_PHYSICS_SOURCE_DIR}/src )
+
+SET(BulletInverseDynamics_SRCS
+ IDMath.cpp
+ MultiBodyTree.cpp
+ details/MultiBodyTreeInitCache.cpp
+ details/MultiBodyTreeImpl.cpp
+)
+
+SET(BulletInverseDynamicsRoot_HDRS
+ IDConfig.hpp
+ IDConfigEigen.hpp
+ IDMath.hpp
+ IDConfigBuiltin.hpp
+ IDErrorMessages.hpp
+ MultiBodyTree.hpp
+)
+SET(BulletInverseDynamicsDetails_HDRS
+ details/IDEigenInterface.hpp
+ details/IDMatVec.hpp
+ details/IDLinearMathInterface.hpp
+ details/MultiBodyTreeImpl.hpp
+ details/MultiBodyTreeInitCache.hpp
+)
+
+SET(BulletInverseDynamics_HDRS
+ ${BulletInverseDynamicsRoot_HDRS}
+ ${BulletInverseDynamicsDetails_HDRS}
+)
+
+
+ADD_LIBRARY(BulletInverseDynamics ${BulletInverseDynamics_SRCS} ${BulletInverseDynamics_HDRS})
+SET_TARGET_PROPERTIES(BulletInverseDynamics PROPERTIES VERSION ${BULLET_VERSION})
+SET_TARGET_PROPERTIES(BulletInverseDynamics PROPERTIES SOVERSION ${BULLET_VERSION})
+IF (BUILD_SHARED_LIBS)
+ TARGET_LINK_LIBRARIES(BulletInverseDynamics Bullet3Common LinearMath)
+ENDIF (BUILD_SHARED_LIBS)
+
+
+IF (INSTALL_LIBS)
+ IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
+ #INSTALL of other files requires CMake 2.6
+ IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
+ IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+ INSTALL(TARGETS BulletInverseDynamics DESTINATION .)
+ ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+ INSTALL(TARGETS BulletInverseDynamics RUNTIME DESTINATION bin
+ LIBRARY DESTINATION lib${LIB_SUFFIX}
+ ARCHIVE DESTINATION lib${LIB_SUFFIX})
+ INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.h" PATTERN ".svn" EXCLUDE PATTERN "CMakeFiles" EXCLUDE)
+ INSTALL(FILES ../btBulletCollisionCommon.h
+DESTINATION ${INCLUDE_INSTALL_DIR}/BulletInverseDynamics)
+ ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+ ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
+
+ IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+ SET_TARGET_PROPERTIES(BulletInverseDynamics PROPERTIES FRAMEWORK true)
+
+ SET_TARGET_PROPERTIES(BulletInverseDynamics PROPERTIES PUBLIC_HEADER "${BulletInverseDynamicsRoot_HDRS}")
+ # Have to list out sub-directories manually:
+ SET_PROPERTY(SOURCE ${BulletInverseDynamicsDetails_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/details)
+
+ ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+ ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
+ENDIF (INSTALL_LIBS)
diff --git a/thirdparty/bullet/src/BulletInverseDynamics/IDConfig.hpp b/thirdparty/bullet/src/BulletInverseDynamics/IDConfig.hpp
new file mode 100644
index 0000000000..ebb10e7a16
--- /dev/null
+++ b/thirdparty/bullet/src/BulletInverseDynamics/IDConfig.hpp
@@ -0,0 +1,107 @@
+///@file Configuration for Inverse Dynamics Library,
+/// such as choice of linear algebra library and underlying scalar type
+#ifndef IDCONFIG_HPP_
+#define IDCONFIG_HPP_
+
+// If true, enable jacobian calculations.
+// This adds a 3xN matrix to every body, + 2 3-Vectors.
+// so it is not advised for large systems if it is not absolutely necessary.
+// Also, this is not required for standard inverse dynamics calculations.
+// Will only work with vector math libraries that support 3xN matrices.
+#define BT_ID_WITH_JACOBIANS
+
+// If we have a custom configuration, compile without using other parts of bullet.
+#ifdef BT_CUSTOM_INVERSE_DYNAMICS_CONFIG_H
+#include <cmath>
+#define BT_ID_WO_BULLET
+#define BT_ID_SQRT(x) std::sqrt(x)
+#define BT_ID_FABS(x) std::fabs(x)
+#define BT_ID_COS(x) std::cos(x)
+#define BT_ID_SIN(x) std::sin(x)
+#define BT_ID_ATAN2(x, y) std::atan2(x, y)
+#define BT_ID_POW(x, y) std::pow(x, y)
+#define BT_ID_SNPRINTF snprintf
+#define BT_ID_PI M_PI
+#define BT_ID_USE_DOUBLE_PRECISION
+#else
+#define BT_ID_SQRT(x) btSqrt(x)
+#define BT_ID_FABS(x) btFabs(x)
+#define BT_ID_COS(x) btCos(x)
+#define BT_ID_SIN(x) btSin(x)
+#define BT_ID_ATAN2(x, y) btAtan2(x, y)
+#define BT_ID_POW(x, y) btPow(x, y)
+#define BT_ID_PI SIMD_PI
+#ifdef _WIN32
+ #define BT_ID_SNPRINTF _snprintf
+#else
+ #define BT_ID_SNPRINTF snprintf
+#endif //
+#endif
+// error messages
+#include "IDErrorMessages.hpp"
+
+#ifdef BT_CUSTOM_INVERSE_DYNAMICS_CONFIG_H
+/*
+#include "IDConfigEigen.hpp"
+#include "IDConfigBuiltin.hpp"
+*/
+#define INVDYN_INCLUDE_HELPER_2(x) #x
+#define INVDYN_INCLUDE_HELPER(x) INVDYN_INCLUDE_HELPER_2(x)
+#include INVDYN_INCLUDE_HELPER(BT_CUSTOM_INVERSE_DYNAMICS_CONFIG_H)
+#ifndef btInverseDynamics
+#error "custom inverse dynamics config, but no custom namespace defined"
+#endif
+
+#define BT_ID_MAX(a,b) std::max(a,b)
+#define BT_ID_MIN(a,b) std::min(a,b)
+
+#else
+#define btInverseDynamics btInverseDynamicsBullet3
+// Use default configuration with bullet's types
+// Use the same scalar type as rest of bullet library
+#include "LinearMath/btScalar.h"
+typedef btScalar idScalar;
+#include "LinearMath/btMinMax.h"
+#define BT_ID_MAX(a,b) btMax(a,b)
+#define BT_ID_MIN(a,b) btMin(a,b)
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define BT_ID_USE_DOUBLE_PRECISION
+#endif
+
+#ifndef BT_USE_INVERSE_DYNAMICS_WITH_BULLET2
+
+
+// use bullet types for arrays and array indices
+#include "Bullet3Common/b3AlignedObjectArray.h"
+// this is to make it work with C++2003, otherwise we could do this:
+// template <typename T>
+// using idArray = b3AlignedObjectArray<T>;
+template <typename T>
+struct idArray {
+ typedef b3AlignedObjectArray<T> type;
+};
+typedef int idArrayIdx;
+#define ID_DECLARE_ALIGNED_ALLOCATOR() B3_DECLARE_ALIGNED_ALLOCATOR()
+
+#else // BT_USE_INVERSE_DYNAMICS_WITH_BULLET2
+
+#include "LinearMath/btAlignedObjectArray.h"
+template <typename T>
+struct idArray {
+ typedef btAlignedObjectArray<T> type;
+};
+typedef int idArrayIdx;
+#define ID_DECLARE_ALIGNED_ALLOCATOR() BT_DECLARE_ALIGNED_ALLOCATOR()
+
+#endif // BT_USE_INVERSE_DYNAMICS_WITH_BULLET2
+
+
+// use bullet's allocator functions
+#define idMalloc btAllocFunc
+#define idFree btFreeFunc
+
+#define ID_LINEAR_MATH_USE_BULLET
+#include "details/IDLinearMathInterface.hpp"
+#endif
+#endif
diff --git a/thirdparty/bullet/src/BulletInverseDynamics/IDConfigBuiltin.hpp b/thirdparty/bullet/src/BulletInverseDynamics/IDConfigBuiltin.hpp
new file mode 100644
index 0000000000..130c19c6d6
--- /dev/null
+++ b/thirdparty/bullet/src/BulletInverseDynamics/IDConfigBuiltin.hpp
@@ -0,0 +1,37 @@
+///@file Configuration for Inverse Dynamics Library without external dependencies
+#ifndef INVDYNCONFIG_BUILTIN_HPP_
+#define INVDYNCONFIG_BUILTIN_HPP_
+#define btInverseDynamics btInverseDynamicsBuiltin
+#ifdef BT_USE_DOUBLE_PRECISION
+// choose double/single precision version
+typedef double idScalar;
+#else
+typedef float idScalar;
+#endif
+// use std::vector for arrays
+#include <vector>
+// this is to make it work with C++2003, otherwise we could do this
+// template <typename T>
+// using idArray = std::vector<T>;
+template <typename T>
+struct idArray {
+ typedef std::vector<T> type;
+};
+typedef std::vector<int>::size_type idArrayIdx;
+// default to standard malloc/free
+#include <cstdlib>
+#define idMalloc ::malloc
+#define idFree ::free
+// currently not aligned at all...
+#define ID_DECLARE_ALIGNED_ALLOCATOR() \
+ inline void* operator new(std::size_t sizeInBytes) { return idMalloc(sizeInBytes); } \
+ inline void operator delete(void* ptr) { idFree(ptr); } \
+ inline void* operator new(std::size_t, void* ptr) { return ptr; } \
+ inline void operator delete(void*, void*) {} \
+ inline void* operator new[](std::size_t sizeInBytes) { return idMalloc(sizeInBytes); } \
+ inline void operator delete[](void* ptr) { idFree(ptr); } \
+ inline void* operator new[](std::size_t, void* ptr) { return ptr; } \
+ inline void operator delete[](void*, void*) {}
+
+#include "details/IDMatVec.hpp"
+#endif
diff --git a/thirdparty/bullet/src/BulletInverseDynamics/IDConfigEigen.hpp b/thirdparty/bullet/src/BulletInverseDynamics/IDConfigEigen.hpp
new file mode 100644
index 0000000000..cbd7e8a9c4
--- /dev/null
+++ b/thirdparty/bullet/src/BulletInverseDynamics/IDConfigEigen.hpp
@@ -0,0 +1,31 @@
+///@file Configuration for Inverse Dynamics Library with Eigen
+#ifndef INVDYNCONFIG_EIGEN_HPP_
+#define INVDYNCONFIG_EIGEN_HPP_
+#define btInverseDynamics btInverseDynamicsEigen
+#ifdef BT_USE_DOUBLE_PRECISION
+// choose double/single precision version
+typedef double idScalar;
+#else
+typedef float idScalar;
+#endif
+
+// use std::vector for arrays
+#include <vector>
+// this is to make it work with C++2003, otherwise we could do this
+// template <typename T>
+// using idArray = std::vector<T>;
+template <typename T>
+struct idArray {
+ typedef std::vector<T> type;
+};
+typedef std::vector<int>::size_type idArrayIdx;
+// default to standard malloc/free
+#include <cstdlib>
+#define ID_DECLARE_ALIGNED_ALLOCATOR() EIGEN_MAKE_ALIGNED_OPERATOR_NEW
+// Note on interfaces:
+// Eigen::Matrix has data(), to get c-array storage
+// HOWEVER: default storage is column-major!
+#define ID_LINEAR_MATH_USE_EIGEN
+#include "Eigen/Eigen"
+#include "details/IDEigenInterface.hpp"
+#endif
diff --git a/thirdparty/bullet/src/BulletInverseDynamics/IDErrorMessages.hpp b/thirdparty/bullet/src/BulletInverseDynamics/IDErrorMessages.hpp
new file mode 100644
index 0000000000..1dc22f860a
--- /dev/null
+++ b/thirdparty/bullet/src/BulletInverseDynamics/IDErrorMessages.hpp
@@ -0,0 +1,29 @@
+///@file error message utility functions
+#ifndef IDUTILS_HPP_
+#define IDUTILS_HPP_
+#include <cstring>
+/// name of file being compiled, without leading path components
+#define __INVDYN_FILE_WO_DIR__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
+
+#if !defined(BT_ID_WO_BULLET) && !defined(BT_USE_INVERSE_DYNAMICS_WITH_BULLET2)
+#include "Bullet3Common/b3Logging.h"
+#define error_message(...) b3Error(__VA_ARGS__)
+#define warning_message(...) b3Warning(__VA_ARGS__)
+#define id_printf(...) b3Printf(__VA_ARGS__)
+#else // BT_ID_WO_BULLET
+#include <cstdio>
+/// print error message with file/line information
+#define error_message(...) \
+ do { \
+ fprintf(stderr, "[Error:%s:%d] ", __INVDYN_FILE_WO_DIR__, __LINE__); \
+ fprintf(stderr, __VA_ARGS__); \
+ } while (0)
+/// print warning message with file/line information
+#define warning_message(...) \
+ do { \
+ fprintf(stderr, "[Warning:%s:%d] ", __INVDYN_FILE_WO_DIR__, __LINE__); \
+ fprintf(stderr, __VA_ARGS__); \
+ } while (0)
+#define id_printf(...) printf(__VA_ARGS__)
+#endif // BT_ID_WO_BULLET
+#endif
diff --git a/thirdparty/bullet/src/BulletInverseDynamics/IDMath.cpp b/thirdparty/bullet/src/BulletInverseDynamics/IDMath.cpp
new file mode 100644
index 0000000000..99fe20e492
--- /dev/null
+++ b/thirdparty/bullet/src/BulletInverseDynamics/IDMath.cpp
@@ -0,0 +1,437 @@
+#include "IDMath.hpp"
+
+#include <cmath>
+#include <limits>
+
+namespace btInverseDynamics {
+static const idScalar kIsZero = 5 * std::numeric_limits<idScalar>::epsilon();
+// requirements for axis length deviation from 1.0
+// experimentally set from random euler angle rotation matrices
+static const idScalar kAxisLengthEpsilon = 10 * kIsZero;
+
+void setZero(vec3 &v) {
+ v(0) = 0;
+ v(1) = 0;
+ v(2) = 0;
+}
+
+void setZero(vecx &v) {
+ for (int i = 0; i < v.size(); i++) {
+ v(i) = 0;
+ }
+}
+
+void setZero(mat33 &m) {
+ m(0, 0) = 0;
+ m(0, 1) = 0;
+ m(0, 2) = 0;
+ m(1, 0) = 0;
+ m(1, 1) = 0;
+ m(1, 2) = 0;
+ m(2, 0) = 0;
+ m(2, 1) = 0;
+ m(2, 2) = 0;
+}
+
+void skew(vec3& v, mat33* result) {
+ (*result)(0, 0) = 0.0;
+ (*result)(0, 1) = -v(2);
+ (*result)(0, 2) = v(1);
+ (*result)(1, 0) = v(2);
+ (*result)(1, 1) = 0.0;
+ (*result)(1, 2) = -v(0);
+ (*result)(2, 0) = -v(1);
+ (*result)(2, 1) = v(0);
+ (*result)(2, 2) = 0.0;
+}
+
+idScalar maxAbs(const vecx &v) {
+ idScalar result = 0.0;
+ for (int i = 0; i < v.size(); i++) {
+ const idScalar tmp = BT_ID_FABS(v(i));
+ if (tmp > result) {
+ result = tmp;
+ }
+ }
+ return result;
+}
+
+idScalar maxAbs(const vec3 &v) {
+ idScalar result = 0.0;
+ for (int i = 0; i < 3; i++) {
+ const idScalar tmp = BT_ID_FABS(v(i));
+ if (tmp > result) {
+ result = tmp;
+ }
+ }
+ return result;
+}
+
+#if (defined BT_ID_HAVE_MAT3X)
+idScalar maxAbsMat3x(const mat3x &m) {
+ // only used for tests -- so just loop here for portability
+ idScalar result = 0.0;
+ for (idArrayIdx col = 0; col < m.cols(); col++) {
+ for (idArrayIdx row = 0; row < 3; row++) {
+ result = BT_ID_MAX(result, std::fabs(m(row, col)));
+ }
+ }
+ return result;
+}
+
+void mul(const mat33 &a, const mat3x &b, mat3x *result) {
+ if (b.cols() != result->cols()) {
+ error_message("size missmatch. b.cols()= %d, result->cols()= %d\n",
+ static_cast<int>(b.cols()), static_cast<int>(result->cols()));
+ abort();
+ }
+
+ for (idArrayIdx col = 0; col < b.cols(); col++) {
+ const idScalar x = a(0,0)*b(0,col)+a(0,1)*b(1,col)+a(0,2)*b(2,col);
+ const idScalar y = a(1,0)*b(0,col)+a(1,1)*b(1,col)+a(1,2)*b(2,col);
+ const idScalar z = a(2,0)*b(0,col)+a(2,1)*b(1,col)+a(2,2)*b(2,col);
+ setMat3xElem(0, col, x, result);
+ setMat3xElem(1, col, y, result);
+ setMat3xElem(2, col, z, result);
+ }
+}
+void add(const mat3x &a, const mat3x &b, mat3x *result) {
+ if (a.cols() != b.cols()) {
+ error_message("size missmatch. a.cols()= %d, b.cols()= %d\n",
+ static_cast<int>(a.cols()), static_cast<int>(b.cols()));
+ abort();
+ }
+ for (idArrayIdx col = 0; col < b.cols(); col++) {
+ for (idArrayIdx row = 0; row < 3; row++) {
+ setMat3xElem(row, col, a(row, col) + b(row, col), result);
+ }
+ }
+}
+void sub(const mat3x &a, const mat3x &b, mat3x *result) {
+ if (a.cols() != b.cols()) {
+ error_message("size missmatch. a.cols()= %d, b.cols()= %d\n",
+ static_cast<int>(a.cols()), static_cast<int>(b.cols()));
+ abort();
+ }
+ for (idArrayIdx col = 0; col < b.cols(); col++) {
+ for (idArrayIdx row = 0; row < 3; row++) {
+ setMat3xElem(row, col, a(row, col) - b(row, col), result);
+ }
+ }
+}
+#endif
+
+mat33 transformX(const idScalar &alpha) {
+ mat33 T;
+ const idScalar cos_alpha = BT_ID_COS(alpha);
+ const idScalar sin_alpha = BT_ID_SIN(alpha);
+ // [1 0 0]
+ // [0 c s]
+ // [0 -s c]
+ T(0, 0) = 1.0;
+ T(0, 1) = 0.0;
+ T(0, 2) = 0.0;
+
+ T(1, 0) = 0.0;
+ T(1, 1) = cos_alpha;
+ T(1, 2) = sin_alpha;
+
+ T(2, 0) = 0.0;
+ T(2, 1) = -sin_alpha;
+ T(2, 2) = cos_alpha;
+
+ return T;
+}
+
+mat33 transformY(const idScalar &beta) {
+ mat33 T;
+ const idScalar cos_beta = BT_ID_COS(beta);
+ const idScalar sin_beta = BT_ID_SIN(beta);
+ // [c 0 -s]
+ // [0 1 0]
+ // [s 0 c]
+ T(0, 0) = cos_beta;
+ T(0, 1) = 0.0;
+ T(0, 2) = -sin_beta;
+
+ T(1, 0) = 0.0;
+ T(1, 1) = 1.0;
+ T(1, 2) = 0.0;
+
+ T(2, 0) = sin_beta;
+ T(2, 1) = 0.0;
+ T(2, 2) = cos_beta;
+
+ return T;
+}
+
+mat33 transformZ(const idScalar &gamma) {
+ mat33 T;
+ const idScalar cos_gamma = BT_ID_COS(gamma);
+ const idScalar sin_gamma = BT_ID_SIN(gamma);
+ // [ c s 0]
+ // [-s c 0]
+ // [ 0 0 1]
+ T(0, 0) = cos_gamma;
+ T(0, 1) = sin_gamma;
+ T(0, 2) = 0.0;
+
+ T(1, 0) = -sin_gamma;
+ T(1, 1) = cos_gamma;
+ T(1, 2) = 0.0;
+
+ T(2, 0) = 0.0;
+ T(2, 1) = 0.0;
+ T(2, 2) = 1.0;
+
+ return T;
+}
+
+mat33 tildeOperator(const vec3 &v) {
+ mat33 m;
+ m(0, 0) = 0.0;
+ m(0, 1) = -v(2);
+ m(0, 2) = v(1);
+ m(1, 0) = v(2);
+ m(1, 1) = 0.0;
+ m(1, 2) = -v(0);
+ m(2, 0) = -v(1);
+ m(2, 1) = v(0);
+ m(2, 2) = 0.0;
+ return m;
+}
+
+void getVecMatFromDH(idScalar theta, idScalar d, idScalar a, idScalar alpha, vec3 *r, mat33 *T) {
+ const idScalar sa = BT_ID_SIN(alpha);
+ const idScalar ca = BT_ID_COS(alpha);
+ const idScalar st = BT_ID_SIN(theta);
+ const idScalar ct = BT_ID_COS(theta);
+
+ (*r)(0) = a;
+ (*r)(1) = -sa * d;
+ (*r)(2) = ca * d;
+
+ (*T)(0, 0) = ct;
+ (*T)(0, 1) = -st;
+ (*T)(0, 2) = 0.0;
+
+ (*T)(1, 0) = st * ca;
+ (*T)(1, 1) = ct * ca;
+ (*T)(1, 2) = -sa;
+
+ (*T)(2, 0) = st * sa;
+ (*T)(2, 1) = ct * sa;
+ (*T)(2, 2) = ca;
+}
+
+void bodyTParentFromAxisAngle(const vec3 &axis, const idScalar &angle, mat33 *T) {
+ const idScalar c = BT_ID_COS(angle);
+ const idScalar s = -BT_ID_SIN(angle);
+ const idScalar one_m_c = 1.0 - c;
+
+ const idScalar &x = axis(0);
+ const idScalar &y = axis(1);
+ const idScalar &z = axis(2);
+
+ (*T)(0, 0) = x * x * one_m_c + c;
+ (*T)(0, 1) = x * y * one_m_c - z * s;
+ (*T)(0, 2) = x * z * one_m_c + y * s;
+
+ (*T)(1, 0) = x * y * one_m_c + z * s;
+ (*T)(1, 1) = y * y * one_m_c + c;
+ (*T)(1, 2) = y * z * one_m_c - x * s;
+
+ (*T)(2, 0) = x * z * one_m_c - y * s;
+ (*T)(2, 1) = y * z * one_m_c + x * s;
+ (*T)(2, 2) = z * z * one_m_c + c;
+}
+
+bool isPositiveDefinite(const mat33 &m) {
+ // test if all upper left determinants are positive
+ if (m(0, 0) <= 0) { // upper 1x1
+ return false;
+ }
+ if (m(0, 0) * m(1, 1) - m(0, 1) * m(1, 0) <= 0) { // upper 2x2
+ return false;
+ }
+ if ((m(0, 0) * (m(1, 1) * m(2, 2) - m(1, 2) * m(2, 1)) -
+ m(0, 1) * (m(1, 0) * m(2, 2) - m(1, 2) * m(2, 0)) +
+ m(0, 2) * (m(1, 0) * m(2, 1) - m(1, 1) * m(2, 0))) < 0) {
+ return false;
+ }
+ return true;
+}
+
+bool isPositiveSemiDefinite(const mat33 &m) {
+ // test if all upper left determinants are positive
+ if (m(0, 0) < 0) { // upper 1x1
+ return false;
+ }
+ if (m(0, 0) * m(1, 1) - m(0, 1) * m(1, 0) < 0) { // upper 2x2
+ return false;
+ }
+ if ((m(0, 0) * (m(1, 1) * m(2, 2) - m(1, 2) * m(2, 1)) -
+ m(0, 1) * (m(1, 0) * m(2, 2) - m(1, 2) * m(2, 0)) +
+ m(0, 2) * (m(1, 0) * m(2, 1) - m(1, 1) * m(2, 0))) < 0) {
+ return false;
+ }
+ return true;
+}
+
+bool isPositiveSemiDefiniteFuzzy(const mat33 &m) {
+ // test if all upper left determinants are positive
+ if (m(0, 0) < -kIsZero) { // upper 1x1
+ return false;
+ }
+ if (m(0, 0) * m(1, 1) - m(0, 1) * m(1, 0) < -kIsZero) { // upper 2x2
+ return false;
+ }
+ if ((m(0, 0) * (m(1, 1) * m(2, 2) - m(1, 2) * m(2, 1)) -
+ m(0, 1) * (m(1, 0) * m(2, 2) - m(1, 2) * m(2, 0)) +
+ m(0, 2) * (m(1, 0) * m(2, 1) - m(1, 1) * m(2, 0))) < -kIsZero) {
+ return false;
+ }
+ return true;
+}
+
+idScalar determinant(const mat33 &m) {
+ return m(0, 0) * m(1, 1) * m(2, 2) + m(0, 1) * m(1, 2) * m(2, 0) + m(0, 2) * m(1, 0) * m(2, 1) -
+ m(0, 2) * m(1, 1) * m(2, 0) - m(0, 0) * m(1, 2) * m(2, 1) - m(0, 1) * m(1, 0) * m(2, 2);
+}
+
+bool isValidInertiaMatrix(const mat33 &I, const int index, bool has_fixed_joint) {
+ // TODO(Thomas) do we really want this?
+ // in cases where the inertia tensor about the center of mass is zero,
+ // the determinant of the inertia tensor about the joint axis is almost
+ // zero and can have a very small negative value.
+ if (!isPositiveSemiDefiniteFuzzy(I)) {
+ error_message("invalid inertia matrix for body %d, not positive definite "
+ "(fixed joint)\n",
+ index);
+ error_message("matrix is:\n"
+ "[%.20e %.20e %.20e;\n"
+ "%.20e %.20e %.20e;\n"
+ "%.20e %.20e %.20e]\n",
+ I(0, 0), I(0, 1), I(0, 2), I(1, 0), I(1, 1), I(1, 2), I(2, 0), I(2, 1),
+ I(2, 2));
+
+ return false;
+ }
+
+ // check triangle inequality, must have I(i,i)+I(j,j)>=I(k,k)
+ if (!has_fixed_joint) {
+ if (I(0, 0) + I(1, 1) < I(2, 2)) {
+ error_message("invalid inertia tensor for body %d, I(0,0) + I(1,1) < I(2,2)\n", index);
+ error_message("matrix is:\n"
+ "[%.20e %.20e %.20e;\n"
+ "%.20e %.20e %.20e;\n"
+ "%.20e %.20e %.20e]\n",
+ I(0, 0), I(0, 1), I(0, 2), I(1, 0), I(1, 1), I(1, 2), I(2, 0), I(2, 1),
+ I(2, 2));
+ return false;
+ }
+ if (I(0, 0) + I(1, 1) < I(2, 2)) {
+ error_message("invalid inertia tensor for body %d, I(0,0) + I(1,1) < I(2,2)\n", index);
+ error_message("matrix is:\n"
+ "[%.20e %.20e %.20e;\n"
+ "%.20e %.20e %.20e;\n"
+ "%.20e %.20e %.20e]\n",
+ I(0, 0), I(0, 1), I(0, 2), I(1, 0), I(1, 1), I(1, 2), I(2, 0), I(2, 1),
+ I(2, 2));
+ return false;
+ }
+ if (I(1, 1) + I(2, 2) < I(0, 0)) {
+ error_message("invalid inertia tensor for body %d, I(1,1) + I(2,2) < I(0,0)\n", index);
+ error_message("matrix is:\n"
+ "[%.20e %.20e %.20e;\n"
+ "%.20e %.20e %.20e;\n"
+ "%.20e %.20e %.20e]\n",
+ I(0, 0), I(0, 1), I(0, 2), I(1, 0), I(1, 1), I(1, 2), I(2, 0), I(2, 1),
+ I(2, 2));
+ return false;
+ }
+ }
+ // check positive/zero diagonal elements
+ for (int i = 0; i < 3; i++) {
+ if (I(i, i) < 0) { // accept zero
+ error_message("invalid inertia tensor, I(%d,%d)= %e <0\n", i, i, I(i, i));
+ return false;
+ }
+ }
+ // check symmetry
+ if (BT_ID_FABS(I(1, 0) - I(0, 1)) > kIsZero) {
+ error_message("invalid inertia tensor for body %d I(1,0)!=I(0,1). I(1,0)-I(0,1)= "
+ "%e\n",
+ index, I(1, 0) - I(0, 1));
+ return false;
+ }
+ if (BT_ID_FABS(I(2, 0) - I(0, 2)) > kIsZero) {
+ error_message("invalid inertia tensor for body %d I(2,0)!=I(0,2). I(2,0)-I(0,2)= "
+ "%e\n",
+ index, I(2, 0) - I(0, 2));
+ return false;
+ }
+ if (BT_ID_FABS(I(1, 2) - I(2, 1)) > kIsZero) {
+ error_message("invalid inertia tensor body %d I(1,2)!=I(2,1). I(1,2)-I(2,1)= %e\n", index,
+ I(1, 2) - I(2, 1));
+ return false;
+ }
+ return true;
+}
+
+bool isValidTransformMatrix(const mat33 &m) {
+#define print_mat(x) \
+ error_message("matrix is [%e, %e, %e; %e, %e, %e; %e, %e, %e]\n", x(0, 0), x(0, 1), x(0, 2), \
+ x(1, 0), x(1, 1), x(1, 2), x(2, 0), x(2, 1), x(2, 2))
+
+ // check for unit length column vectors
+ for (int i = 0; i < 3; i++) {
+ const idScalar length_minus_1 =
+ BT_ID_FABS(m(0, i) * m(0, i) + m(1, i) * m(1, i) + m(2, i) * m(2, i) - 1.0);
+ if (length_minus_1 > kAxisLengthEpsilon) {
+ error_message("Not a valid rotation matrix (column %d not unit length)\n"
+ "column = [%.18e %.18e %.18e]\n"
+ "length-1.0= %.18e\n",
+ i, m(0, i), m(1, i), m(2, i), length_minus_1);
+ print_mat(m);
+ return false;
+ }
+ }
+ // check for orthogonal column vectors
+ if (BT_ID_FABS(m(0, 0) * m(0, 1) + m(1, 0) * m(1, 1) + m(2, 0) * m(2, 1)) > kAxisLengthEpsilon) {
+ error_message("Not a valid rotation matrix (columns 0 and 1 not orthogonal)\n");
+ print_mat(m);
+ return false;
+ }
+ if (BT_ID_FABS(m(0, 0) * m(0, 2) + m(1, 0) * m(1, 2) + m(2, 0) * m(2, 2)) > kAxisLengthEpsilon) {
+ error_message("Not a valid rotation matrix (columns 0 and 2 not orthogonal)\n");
+ print_mat(m);
+ return false;
+ }
+ if (BT_ID_FABS(m(0, 1) * m(0, 2) + m(1, 1) * m(1, 2) + m(2, 1) * m(2, 2)) > kAxisLengthEpsilon) {
+ error_message("Not a valid rotation matrix (columns 0 and 2 not orthogonal)\n");
+ print_mat(m);
+ return false;
+ }
+ // check determinant (rotation not reflection)
+ if (determinant(m) <= 0) {
+ error_message("Not a valid rotation matrix (determinant <=0)\n");
+ print_mat(m);
+ return false;
+ }
+ return true;
+}
+
+bool isUnitVector(const vec3 &vector) {
+ return BT_ID_FABS(vector(0) * vector(0) + vector(1) * vector(1) + vector(2) * vector(2) - 1.0) <
+ kIsZero;
+}
+
+vec3 rpyFromMatrix(const mat33 &rot) {
+ vec3 rpy;
+ rpy(2) = BT_ID_ATAN2(-rot(1, 0), rot(0, 0));
+ rpy(1) = BT_ID_ATAN2(rot(2, 0), BT_ID_COS(rpy(2)) * rot(0, 0) - BT_ID_SIN(rpy(0)) * rot(1, 0));
+ rpy(0) = BT_ID_ATAN2(-rot(2, 0), rot(2, 2));
+ return rpy;
+}
+}
diff --git a/thirdparty/bullet/src/BulletInverseDynamics/IDMath.hpp b/thirdparty/bullet/src/BulletInverseDynamics/IDMath.hpp
new file mode 100644
index 0000000000..b355474d44
--- /dev/null
+++ b/thirdparty/bullet/src/BulletInverseDynamics/IDMath.hpp
@@ -0,0 +1,99 @@
+/// @file Math utility functions used in inverse dynamics library.
+/// Defined here as they may not be provided by the math library.
+
+#ifndef IDMATH_HPP_
+#define IDMATH_HPP_
+#include "IDConfig.hpp"
+
+namespace btInverseDynamics {
+/// set all elements to zero
+void setZero(vec3& v);
+/// set all elements to zero
+void setZero(vecx& v);
+/// set all elements to zero
+void setZero(mat33& m);
+/// create a skew symmetric matrix from a vector (useful for cross product abstraction, e.g. v x a = V * a)
+void skew(vec3& v, mat33* result);
+/// return maximum absolute value
+idScalar maxAbs(const vecx& v);
+#ifndef ID_LINEAR_MATH_USE_EIGEN
+/// return maximum absolute value
+idScalar maxAbs(const vec3& v);
+#endif //ID_LINEAR_MATH_USE_EIGEN
+
+#if (defined BT_ID_HAVE_MAT3X)
+idScalar maxAbsMat3x(const mat3x& m);
+void setZero(mat3x&m);
+// define math functions on mat3x here to avoid allocations in operators.
+void mul(const mat33&a, const mat3x&b, mat3x* result);
+void add(const mat3x&a, const mat3x&b, mat3x* result);
+void sub(const mat3x&a, const mat3x&b, mat3x* result);
+#endif
+
+/// get offset vector & transform matrix from DH parameters
+/// TODO: add documentation
+void getVecMatFromDH(idScalar theta, idScalar d, idScalar a, idScalar alpha, vec3* r, mat33* T);
+
+/// Check if a 3x3 matrix is positive definite
+/// @param m a 3x3 matrix
+/// @return true if m>0, false otherwise
+bool isPositiveDefinite(const mat33& m);
+
+/// Check if a 3x3 matrix is positive semi definite
+/// @param m a 3x3 matrix
+/// @return true if m>=0, false otherwise
+bool isPositiveSemiDefinite(const mat33& m);
+/// Check if a 3x3 matrix is positive semi definite within numeric limits
+/// @param m a 3x3 matrix
+/// @return true if m>=-eps, false otherwise
+bool isPositiveSemiDefiniteFuzzy(const mat33& m);
+
+/// Determinant of 3x3 matrix
+/// NOTE: implemented here for portability, as determinant operation
+/// will be implemented differently for various matrix/vector libraries
+/// @param m a 3x3 matrix
+/// @return det(m)
+idScalar determinant(const mat33& m);
+
+/// Test if a 3x3 matrix satisfies some properties of inertia matrices
+/// @param I a 3x3 matrix
+/// @param index body index (for error messages)
+/// @param has_fixed_joint: if true, positive semi-definite matrices are accepted
+/// @return true if I satisfies inertia matrix properties, false otherwise.
+bool isValidInertiaMatrix(const mat33& I, int index, bool has_fixed_joint);
+
+/// Check if a 3x3 matrix is a valid transform (rotation) matrix
+/// @param m a 3x3 matrix
+/// @return true if m is a rotation matrix, false otherwise
+bool isValidTransformMatrix(const mat33& m);
+/// Transform matrix from parent to child frame,
+/// when the child frame is rotated about @param axis by @angle
+/// (mathematically positive)
+/// @param axis the axis of rotation
+/// @param angle rotation angle
+/// @param T pointer to transform matrix
+void bodyTParentFromAxisAngle(const vec3& axis, const idScalar& angle, mat33* T);
+
+/// Check if this is a unit vector
+/// @param vector
+/// @return true if |vector|=1 within numeric limits
+bool isUnitVector(const vec3& vector);
+
+/// @input a vector in R^3
+/// @returns corresponding spin tensor
+mat33 tildeOperator(const vec3& v);
+/// @param alpha angle in radians
+/// @returns transform matrix for ratation with @param alpha about x-axis
+mat33 transformX(const idScalar& alpha);
+/// @param beta angle in radians
+/// @returns transform matrix for ratation with @param beta about y-axis
+mat33 transformY(const idScalar& beta);
+/// @param gamma angle in radians
+/// @returns transform matrix for ratation with @param gamma about z-axis
+mat33 transformZ(const idScalar& gamma);
+///calculate rpy angles (x-y-z Euler angles) from a given rotation matrix
+/// @param rot rotation matrix
+/// @returns x-y-z Euler angles
+vec3 rpyFromMatrix(const mat33&rot);
+}
+#endif // IDMATH_HPP_
diff --git a/thirdparty/bullet/src/BulletInverseDynamics/MultiBodyTree.cpp b/thirdparty/bullet/src/BulletInverseDynamics/MultiBodyTree.cpp
new file mode 100644
index 0000000000..c67588d49f
--- /dev/null
+++ b/thirdparty/bullet/src/BulletInverseDynamics/MultiBodyTree.cpp
@@ -0,0 +1,445 @@
+#include "MultiBodyTree.hpp"
+
+#include <cmath>
+#include <limits>
+#include <vector>
+
+#include "IDMath.hpp"
+#include "details/MultiBodyTreeImpl.hpp"
+#include "details/MultiBodyTreeInitCache.hpp"
+
+namespace btInverseDynamics {
+
+MultiBodyTree::MultiBodyTree()
+ : m_is_finalized(false),
+ m_mass_parameters_are_valid(true),
+ m_accept_invalid_mass_parameters(false),
+ m_impl(0x0),
+ m_init_cache(0x0) {
+ m_init_cache = new InitCache();
+}
+
+MultiBodyTree::~MultiBodyTree() {
+ delete m_impl;
+ delete m_init_cache;
+}
+
+void MultiBodyTree::setAcceptInvalidMassParameters(bool flag) {
+ m_accept_invalid_mass_parameters = flag;
+}
+
+bool MultiBodyTree::getAcceptInvalidMassProperties() const {
+ return m_accept_invalid_mass_parameters;
+}
+
+int MultiBodyTree::getBodyOrigin(const int body_index, vec3 *world_origin) const {
+ return m_impl->getBodyOrigin(body_index, world_origin);
+}
+
+int MultiBodyTree::getBodyCoM(const int body_index, vec3 *world_com) const {
+ return m_impl->getBodyCoM(body_index, world_com);
+}
+
+int MultiBodyTree::getBodyTransform(const int body_index, mat33 *world_T_body) const {
+ return m_impl->getBodyTransform(body_index, world_T_body);
+}
+int MultiBodyTree::getBodyAngularVelocity(const int body_index, vec3 *world_omega) const {
+ return m_impl->getBodyAngularVelocity(body_index, world_omega);
+}
+int MultiBodyTree::getBodyLinearVelocity(const int body_index, vec3 *world_velocity) const {
+ return m_impl->getBodyLinearVelocity(body_index, world_velocity);
+}
+
+int MultiBodyTree::getBodyLinearVelocityCoM(const int body_index, vec3 *world_velocity) const {
+ return m_impl->getBodyLinearVelocityCoM(body_index, world_velocity);
+}
+
+int MultiBodyTree::getBodyAngularAcceleration(const int body_index, vec3 *world_dot_omega) const {
+ return m_impl->getBodyAngularAcceleration(body_index, world_dot_omega);
+}
+int MultiBodyTree::getBodyLinearAcceleration(const int body_index, vec3 *world_acceleration) const {
+ return m_impl->getBodyLinearAcceleration(body_index, world_acceleration);
+}
+
+int MultiBodyTree::getParentRParentBodyRef(const int body_index, vec3* r) const {
+ return m_impl->getParentRParentBodyRef(body_index, r);
+}
+
+int MultiBodyTree::getBodyTParentRef(const int body_index, mat33* T) const {
+ return m_impl->getBodyTParentRef(body_index, T);
+}
+
+int MultiBodyTree::getBodyAxisOfMotion(const int body_index, vec3* axis) const {
+ return m_impl->getBodyAxisOfMotion(body_index, axis);
+}
+
+void MultiBodyTree::printTree() { m_impl->printTree(); }
+void MultiBodyTree::printTreeData() { m_impl->printTreeData(); }
+
+int MultiBodyTree::numBodies() const { return m_impl->m_num_bodies; }
+
+int MultiBodyTree::numDoFs() const { return m_impl->m_num_dofs; }
+
+int MultiBodyTree::calculateInverseDynamics(const vecx &q, const vecx &u, const vecx &dot_u,
+ vecx *joint_forces) {
+ if (false == m_is_finalized) {
+ error_message("system has not been initialized\n");
+ return -1;
+ }
+ if (-1 == m_impl->calculateInverseDynamics(q, u, dot_u, joint_forces)) {
+ error_message("error in inverse dynamics calculation\n");
+ return -1;
+ }
+ return 0;
+}
+
+int MultiBodyTree::calculateMassMatrix(const vecx &q, const bool update_kinematics,
+ const bool initialize_matrix,
+ const bool set_lower_triangular_matrix, matxx *mass_matrix) {
+ if (false == m_is_finalized) {
+ error_message("system has not been initialized\n");
+ return -1;
+ }
+ if (-1 ==
+ m_impl->calculateMassMatrix(q, update_kinematics, initialize_matrix,
+ set_lower_triangular_matrix, mass_matrix)) {
+ error_message("error in mass matrix calculation\n");
+ return -1;
+ }
+ return 0;
+}
+
+int MultiBodyTree::calculateMassMatrix(const vecx &q, matxx *mass_matrix) {
+ return calculateMassMatrix(q, true, true, true, mass_matrix);
+}
+
+
+
+int MultiBodyTree::calculateKinematics(const vecx& q, const vecx& u, const vecx& dot_u) {
+ vec3 world_gravity(m_impl->m_world_gravity);
+ // temporarily set gravity to zero, to ensure we get the actual accelerations
+ setZero(m_impl->m_world_gravity);
+
+ if (false == m_is_finalized) {
+ error_message("system has not been initialized\n");
+ return -1;
+ }
+ if (-1 == m_impl->calculateKinematics(q, u, dot_u,
+ MultiBodyTree::MultiBodyImpl::POSITION_VELOCITY_ACCELERATION)) {
+ error_message("error in kinematics calculation\n");
+ return -1;
+ }
+
+ m_impl->m_world_gravity=world_gravity;
+ return 0;
+}
+
+
+int MultiBodyTree::calculatePositionKinematics(const vecx& q) {
+ if (false == m_is_finalized) {
+ error_message("system has not been initialized\n");
+ return -1;
+ }
+ if (-1 == m_impl->calculateKinematics(q, q, q,
+ MultiBodyTree::MultiBodyImpl::POSITION_VELOCITY)) {
+ error_message("error in kinematics calculation\n");
+ return -1;
+ }
+ return 0;
+}
+
+int MultiBodyTree::calculatePositionAndVelocityKinematics(const vecx& q, const vecx& u) {
+ if (false == m_is_finalized) {
+ error_message("system has not been initialized\n");
+ return -1;
+ }
+ if (-1 == m_impl->calculateKinematics(q, u, u,
+ MultiBodyTree::MultiBodyImpl::POSITION_VELOCITY)) {
+ error_message("error in kinematics calculation\n");
+ return -1;
+ }
+ return 0;
+}
+
+
+#if (defined BT_ID_HAVE_MAT3X) && (defined BT_ID_WITH_JACOBIANS)
+int MultiBodyTree::calculateJacobians(const vecx& q, const vecx& u) {
+ if (false == m_is_finalized) {
+ error_message("system has not been initialized\n");
+ return -1;
+ }
+ if (-1 == m_impl->calculateJacobians(q, u,
+ MultiBodyTree::MultiBodyImpl::POSITION_VELOCITY)) {
+ error_message("error in jacobian calculation\n");
+ return -1;
+ }
+ return 0;
+}
+
+int MultiBodyTree::calculateJacobians(const vecx& q){
+ if (false == m_is_finalized) {
+ error_message("system has not been initialized\n");
+ return -1;
+ }
+ if (-1 == m_impl->calculateJacobians(q, q,
+ MultiBodyTree::MultiBodyImpl::POSITION_ONLY)) {
+ error_message("error in jacobian calculation\n");
+ return -1;
+ }
+ return 0;
+}
+
+int MultiBodyTree::getBodyDotJacobianTransU(const int body_index, vec3* world_dot_jac_trans_u) const {
+ return m_impl->getBodyDotJacobianTransU(body_index,world_dot_jac_trans_u);
+}
+
+int MultiBodyTree::getBodyDotJacobianRotU(const int body_index, vec3* world_dot_jac_rot_u) const {
+ return m_impl->getBodyDotJacobianRotU(body_index,world_dot_jac_rot_u);
+}
+
+int MultiBodyTree::getBodyJacobianTrans(const int body_index, mat3x* world_jac_trans) const {
+ return m_impl->getBodyJacobianTrans(body_index,world_jac_trans);
+}
+
+int MultiBodyTree::getBodyJacobianRot(const int body_index, mat3x* world_jac_rot) const {
+ return m_impl->getBodyJacobianRot(body_index,world_jac_rot);
+}
+
+
+#endif
+
+int MultiBodyTree::addBody(int body_index, int parent_index, JointType joint_type,
+ const vec3 &parent_r_parent_body_ref, const mat33 &body_T_parent_ref,
+ const vec3 &body_axis_of_motion_, idScalar mass,
+ const vec3 &body_r_body_com, const mat33 &body_I_body,
+ const int user_int, void *user_ptr) {
+ if (body_index < 0) {
+ error_message("body index must be positive (got %d)\n", body_index);
+ return -1;
+ }
+ vec3 body_axis_of_motion(body_axis_of_motion_);
+ switch (joint_type) {
+ case REVOLUTE:
+ case PRISMATIC:
+ // check if axis is unit vector
+ if (!isUnitVector(body_axis_of_motion)) {
+ warning_message(
+ "axis of motion not a unit axis ([%f %f %f]), will use normalized vector\n",
+ body_axis_of_motion(0), body_axis_of_motion(1), body_axis_of_motion(2));
+ idScalar length = BT_ID_SQRT(BT_ID_POW(body_axis_of_motion(0), 2) +
+ BT_ID_POW(body_axis_of_motion(1), 2) +
+ BT_ID_POW(body_axis_of_motion(2), 2));
+ if (length < BT_ID_SQRT(std::numeric_limits<idScalar>::min())) {
+ error_message("axis of motion vector too short (%e)\n", length);
+ return -1;
+ }
+ body_axis_of_motion = (1.0 / length) * body_axis_of_motion;
+ }
+ break;
+ case FIXED:
+ break;
+ case FLOATING:
+ break;
+ default:
+ error_message("unknown joint type %d\n", joint_type);
+ return -1;
+ }
+
+ // sanity check for mass properties. Zero mass is OK.
+ if (mass < 0) {
+ m_mass_parameters_are_valid = false;
+ error_message("Body %d has invalid mass %e\n", body_index, mass);
+ if (!m_accept_invalid_mass_parameters) {
+ return -1;
+ }
+ }
+
+ if (!isValidInertiaMatrix(body_I_body, body_index, FIXED == joint_type)) {
+ m_mass_parameters_are_valid = false;
+ // error message printed in function call
+ if (!m_accept_invalid_mass_parameters) {
+ return -1;
+ }
+ }
+
+ if (!isValidTransformMatrix(body_T_parent_ref)) {
+ return -1;
+ }
+
+ return m_init_cache->addBody(body_index, parent_index, joint_type, parent_r_parent_body_ref,
+ body_T_parent_ref, body_axis_of_motion, mass, body_r_body_com,
+ body_I_body, user_int, user_ptr);
+}
+
+int MultiBodyTree::getParentIndex(const int body_index, int *parent_index) const {
+ return m_impl->getParentIndex(body_index, parent_index);
+}
+
+int MultiBodyTree::getUserInt(const int body_index, int *user_int) const {
+ return m_impl->getUserInt(body_index, user_int);
+}
+
+int MultiBodyTree::getUserPtr(const int body_index, void **user_ptr) const {
+ return m_impl->getUserPtr(body_index, user_ptr);
+}
+
+int MultiBodyTree::setUserInt(const int body_index, const int user_int) {
+ return m_impl->setUserInt(body_index, user_int);
+}
+
+int MultiBodyTree::setUserPtr(const int body_index, void *const user_ptr) {
+ return m_impl->setUserPtr(body_index, user_ptr);
+}
+
+int MultiBodyTree::finalize() {
+ const int &num_bodies = m_init_cache->numBodies();
+ const int &num_dofs = m_init_cache->numDoFs();
+
+ if(num_dofs<=0) {
+ error_message("Need num_dofs>=1, but num_dofs= %d\n", num_dofs);
+ //return -1;
+ }
+
+ // 1 allocate internal MultiBody structure
+ m_impl = new MultiBodyImpl(num_bodies, num_dofs);
+
+ // 2 build new index set assuring index(parent) < index(child)
+ if (-1 == m_init_cache->buildIndexSets()) {
+ return -1;
+ }
+ m_init_cache->getParentIndexArray(&m_impl->m_parent_index);
+
+ // 3 setup internal kinematic and dynamic data
+ for (int index = 0; index < num_bodies; index++) {
+ InertiaData inertia;
+ JointData joint;
+ if (-1 == m_init_cache->getInertiaData(index, &inertia)) {
+ return -1;
+ }
+ if (-1 == m_init_cache->getJointData(index, &joint)) {
+ return -1;
+ }
+
+ RigidBody &rigid_body = m_impl->m_body_list[index];
+
+ rigid_body.m_mass = inertia.m_mass;
+ rigid_body.m_body_mass_com = inertia.m_mass * inertia.m_body_pos_body_com;
+ rigid_body.m_body_I_body = inertia.m_body_I_body;
+ rigid_body.m_joint_type = joint.m_type;
+ rigid_body.m_parent_pos_parent_body_ref = joint.m_parent_pos_parent_child_ref;
+ rigid_body.m_body_T_parent_ref = joint.m_child_T_parent_ref;
+ rigid_body.m_parent_pos_parent_body_ref = joint.m_parent_pos_parent_child_ref;
+ rigid_body.m_joint_type = joint.m_type;
+
+ // Set joint Jacobians. Note that the dimension is always 3x1 here to avoid variable sized
+ // matrices.
+ switch (rigid_body.m_joint_type) {
+ case REVOLUTE:
+ rigid_body.m_Jac_JR(0) = joint.m_child_axis_of_motion(0);
+ rigid_body.m_Jac_JR(1) = joint.m_child_axis_of_motion(1);
+ rigid_body.m_Jac_JR(2) = joint.m_child_axis_of_motion(2);
+ rigid_body.m_Jac_JT(0) = 0.0;
+ rigid_body.m_Jac_JT(1) = 0.0;
+ rigid_body.m_Jac_JT(2) = 0.0;
+ break;
+ case PRISMATIC:
+ rigid_body.m_Jac_JR(0) = 0.0;
+ rigid_body.m_Jac_JR(1) = 0.0;
+ rigid_body.m_Jac_JR(2) = 0.0;
+ rigid_body.m_Jac_JT(0) = joint.m_child_axis_of_motion(0);
+ rigid_body.m_Jac_JT(1) = joint.m_child_axis_of_motion(1);
+ rigid_body.m_Jac_JT(2) = joint.m_child_axis_of_motion(2);
+ break;
+ case FIXED:
+ // NOTE/TODO: dimension really should be zero ..
+ rigid_body.m_Jac_JR(0) = 0.0;
+ rigid_body.m_Jac_JR(1) = 0.0;
+ rigid_body.m_Jac_JR(2) = 0.0;
+ rigid_body.m_Jac_JT(0) = 0.0;
+ rigid_body.m_Jac_JT(1) = 0.0;
+ rigid_body.m_Jac_JT(2) = 0.0;
+ break;
+ case FLOATING:
+ // NOTE/TODO: this is not really correct.
+ // the Jacobians should be 3x3 matrices here !
+ rigid_body.m_Jac_JR(0) = 0.0;
+ rigid_body.m_Jac_JR(1) = 0.0;
+ rigid_body.m_Jac_JR(2) = 0.0;
+ rigid_body.m_Jac_JT(0) = 0.0;
+ rigid_body.m_Jac_JT(1) = 0.0;
+ rigid_body.m_Jac_JT(2) = 0.0;
+ break;
+ default:
+ error_message("unsupported joint type %d\n", rigid_body.m_joint_type);
+ return -1;
+ }
+ }
+
+ // 4 assign degree of freedom indices & build per-joint-type index arrays
+ if (-1 == m_impl->generateIndexSets()) {
+ error_message("generating index sets\n");
+ return -1;
+ }
+
+ // 5 do some pre-computations ..
+ m_impl->calculateStaticData();
+
+ // 6. make sure all user forces are set to zero, as this might not happen
+ // in the vector ctors.
+ m_impl->clearAllUserForcesAndMoments();
+
+ m_is_finalized = true;
+ return 0;
+}
+
+int MultiBodyTree::setGravityInWorldFrame(const vec3 &gravity) {
+ return m_impl->setGravityInWorldFrame(gravity);
+}
+
+int MultiBodyTree::getJointType(const int body_index, JointType *joint_type) const {
+ return m_impl->getJointType(body_index, joint_type);
+}
+
+int MultiBodyTree::getJointTypeStr(const int body_index, const char **joint_type) const {
+ return m_impl->getJointTypeStr(body_index, joint_type);
+}
+
+int MultiBodyTree::getDoFOffset(const int body_index, int *q_offset) const {
+ return m_impl->getDoFOffset(body_index, q_offset);
+}
+
+int MultiBodyTree::setBodyMass(const int body_index, idScalar mass) {
+ return m_impl->setBodyMass(body_index, mass);
+}
+
+int MultiBodyTree::setBodyFirstMassMoment(const int body_index, const vec3& first_mass_moment) {
+ return m_impl->setBodyFirstMassMoment(body_index, first_mass_moment);
+}
+
+int MultiBodyTree::setBodySecondMassMoment(const int body_index, const mat33& second_mass_moment) {
+ return m_impl->setBodySecondMassMoment(body_index, second_mass_moment);
+}
+
+int MultiBodyTree::getBodyMass(const int body_index, idScalar *mass) const {
+ return m_impl->getBodyMass(body_index, mass);
+}
+
+int MultiBodyTree::getBodyFirstMassMoment(const int body_index, vec3 *first_mass_moment) const {
+ return m_impl->getBodyFirstMassMoment(body_index, first_mass_moment);
+}
+
+int MultiBodyTree::getBodySecondMassMoment(const int body_index, mat33 *second_mass_moment) const {
+ return m_impl->getBodySecondMassMoment(body_index, second_mass_moment);
+}
+
+void MultiBodyTree::clearAllUserForcesAndMoments() { m_impl->clearAllUserForcesAndMoments(); }
+
+int MultiBodyTree::addUserForce(const int body_index, const vec3 &body_force) {
+ return m_impl->addUserForce(body_index, body_force);
+}
+
+int MultiBodyTree::addUserMoment(const int body_index, const vec3 &body_moment) {
+ return m_impl->addUserMoment(body_index, body_moment);
+}
+
+}
diff --git a/thirdparty/bullet/src/BulletInverseDynamics/MultiBodyTree.hpp b/thirdparty/bullet/src/BulletInverseDynamics/MultiBodyTree.hpp
new file mode 100644
index 0000000000..d235aa6e76
--- /dev/null
+++ b/thirdparty/bullet/src/BulletInverseDynamics/MultiBodyTree.hpp
@@ -0,0 +1,363 @@
+#ifndef MULTIBODYTREE_HPP_
+#define MULTIBODYTREE_HPP_
+
+#include "IDConfig.hpp"
+#include "IDMath.hpp"
+
+namespace btInverseDynamics {
+
+/// Enumeration of supported joint types
+enum JointType {
+ /// no degree of freedom, moves with parent
+ FIXED = 0,
+ /// one rotational degree of freedom relative to parent
+ REVOLUTE,
+ /// one translational degree of freedom relative to parent
+ PRISMATIC,
+ /// six degrees of freedom relative to parent
+ FLOATING
+};
+
+/// Interface class for calculating inverse dynamics for tree structured
+/// multibody systems
+///
+/// Note on degrees of freedom
+/// The q vector contains the generalized coordinate set defining the tree's configuration.
+/// Every joint adds elements that define the corresponding link's frame pose relative to
+/// its parent. For the joint types that is:
+/// - FIXED: none
+/// - REVOLUTE: angle of rotation [rad]
+/// - PRISMATIC: displacement [m]
+/// - FLOATING: Euler x-y-z angles [rad] and displacement in body-fixed frame of parent [m]
+/// (in that order)
+/// The u vector contains the generalized speeds, which are
+/// - FIXED: none
+/// - REVOLUTE: time derivative of angle of rotation [rad/s]
+/// - PRISMATIC: time derivative of displacement [m/s]
+/// - FLOATING: angular velocity [rad/s] (*not* time derivative of rpy angles)
+/// and time derivative of displacement in parent frame [m/s]
+///
+/// The q and u vectors are obtained by stacking contributions of all bodies in one
+/// vector in the order of body indices.
+///
+/// Note on generalized forces: analogous to u, i.e.,
+/// - FIXED: none
+/// - REVOLUTE: moment [Nm], about joint axis
+/// - PRISMATIC: force [N], along joint axis
+/// - FLOATING: moment vector [Nm] and force vector [N], both in body-fixed frame
+/// (in that order)
+///
+/// TODO - force element interface (friction, springs, dampers, etc)
+/// - gears and motor inertia
+class MultiBodyTree {
+public:
+ ID_DECLARE_ALIGNED_ALLOCATOR();
+ /// The contructor.
+ /// Initialization & allocation is via addBody and buildSystem calls.
+ MultiBodyTree();
+ /// the destructor. This also deallocates all memory
+ ~MultiBodyTree();
+
+ /// Add body to the system. this allocates memory and not real-time safe.
+ /// This only adds the data to an initial cache. After all bodies have been
+ /// added,
+ /// the system is setup using the buildSystem call
+ /// @param body_index index of the body to be added. Must >=0, <number of bodies,
+ /// and index of parent must be < index of body
+ /// @param parent_index index of the parent body
+ /// The root of the tree has index 0 and its parent (the world frame)
+ /// is assigned index -1
+ /// the rotation and translation relative to the parent are taken as
+ /// pose of the root body relative to the world frame. Other parameters
+ /// are ignored
+ /// @param JointType type of joint connecting the body to the parent
+ /// @param mass the mass of the body
+ /// @param body_r_body_com the center of mass of the body relative to and
+ /// described in
+ /// the body fixed frame, which is located in the joint axis connecting
+ /// the body to its parent
+ /// @param body_I_body the moment of inertia of the body w.r.t the body-fixed
+ /// frame
+ /// (ie, the reference point is the origin of the body-fixed frame and
+ /// the matrix is written
+ /// w.r.t. those unit vectors)
+ /// @param parent_r_parent_body_ref position of joint relative to the parent
+ /// body's reference frame
+ /// for q=0, written in the parent bodies reference frame
+ /// @param body_axis_of_motion translation/rotation axis in body-fixed frame.
+ /// Ignored for joints that are not revolute or prismatic.
+ /// must be a unit vector.
+ /// @param body_T_parent_ref transform matrix from parent to body reference
+ /// frame for q=0.
+ /// This is the matrix transforming a vector represented in the
+ /// parent's reference frame into one represented
+ /// in this body's reference frame.
+ /// ie, if parent_vec is a vector in R^3 whose components are w.r.t to
+ /// the parent's reference frame,
+ /// then the same vector written w.r.t. this body's frame (for q=0) is
+ /// given by
+ /// body_vec = parent_R_body_ref * parent_vec
+ /// @param user_ptr pointer to user data
+ /// @param user_int pointer to user integer
+ /// @return 0 on success, -1 on error
+ int addBody(int body_index, int parent_index, JointType joint_type,
+ const vec3& parent_r_parent_body_ref, const mat33& body_T_parent_ref,
+ const vec3& body_axis_of_motion, idScalar mass, const vec3& body_r_body_com,
+ const mat33& body_I_body, const int user_int, void* user_ptr);
+ /// set policy for invalid mass properties
+ /// @param flag if true, invalid mass properties are accepted,
+ /// the default is false
+ void setAcceptInvalidMassParameters(bool flag);
+ /// @return the mass properties policy flag
+ bool getAcceptInvalidMassProperties() const;
+ /// build internal data structures
+ /// call this after all bodies have been added via addBody
+ /// @return 0 on success, -1 on error
+ int finalize();
+ /// pretty print ascii description of tree to stdout
+ void printTree();
+ /// print tree data to stdout
+ void printTreeData();
+ /// Calculate joint forces for given generalized state & derivatives.
+ /// This also updates kinematic terms computed in calculateKinematics.
+ /// If gravity is not set to zero, acceleration terms will contain
+ /// gravitational acceleration.
+ /// @param q generalized coordinates
+ /// @param u generalized velocities. In the general case, u=T(q)*dot(q) and dim(q)>=dim(u)
+ /// @param dot_u time derivative of u
+ /// @param joint_forces this is where the resulting joint forces will be
+ /// stored. dim(joint_forces) = dim(u)
+ /// @return 0 on success, -1 on error
+ int calculateInverseDynamics(const vecx& q, const vecx& u, const vecx& dot_u,
+ vecx* joint_forces);
+ /// Calculate joint space mass matrix
+ /// @param q generalized coordinates
+ /// @param initialize_matrix if true, initialize mass matrix with zero.
+ /// If mass_matrix is initialized to zero externally and only used
+ /// for mass matrix computations for the same system, it is safe to
+ /// set this to false.
+ /// @param set_lower_triangular_matrix if true, the lower triangular section of mass_matrix
+ /// is also populated, otherwise not.
+ /// @param mass_matrix matrix for storing the output (should be dim(q)xdim(q))
+ /// @return -1 on error, 0 on success
+ int calculateMassMatrix(const vecx& q, const bool update_kinematics,
+ const bool initialize_matrix, const bool set_lower_triangular_matrix,
+ matxx* mass_matrix);
+
+ /// Calculate joint space mass matrix.
+ /// This version will update kinematics, initialize all mass_matrix elements to zero and
+ /// populate all mass matrix entries.
+ /// @param q generalized coordinates
+ /// @param mass_matrix matrix for storing the output (should be dim(q)xdim(q))
+ /// @return -1 on error, 0 on success
+ int calculateMassMatrix(const vecx& q, matxx* mass_matrix);
+
+
+ /// Calculates kinematics also calculated in calculateInverseDynamics,
+ /// but not dynamics.
+ /// This function ensures that correct accelerations are computed that do not
+ /// contain gravitational acceleration terms.
+ /// Does not calculate Jacobians, but only vector quantities (positions, velocities & accelerations)
+ int calculateKinematics(const vecx& q, const vecx& u, const vecx& dot_u);
+ /// Calculate position kinematics
+ int calculatePositionKinematics(const vecx& q);
+ /// Calculate position and velocity kinematics
+ int calculatePositionAndVelocityKinematics(const vecx& q, const vecx& u);
+
+#if (defined BT_ID_HAVE_MAT3X) && (defined BT_ID_WITH_JACOBIANS)
+ /// Calculate Jacobians (dvel/du), as well as velocity-dependent accelearation components
+ /// d(Jacobian)/dt*u
+ /// This function assumes that calculateInverseDynamics was called, or calculateKinematics,
+ /// or calculatePositionAndVelocityKinematics
+ int calculateJacobians(const vecx& q, const vecx& u);
+ /// Calculate Jacobians (dvel/du)
+ /// This function assumes that calculateInverseDynamics was called, or
+ /// one of the calculateKineamtics functions
+ int calculateJacobians(const vecx& q);
+#endif // BT_ID_HAVE_MAT3X
+
+
+ /// set gravitational acceleration
+ /// the default is [0;0;-9.8] in the world frame
+ /// @param gravity the gravitational acceleration in world frame
+ /// @return 0 on success, -1 on error
+ int setGravityInWorldFrame(const vec3& gravity);
+ /// returns number of bodies in tree
+ int numBodies() const;
+ /// returns number of mechanical degrees of freedom (dimension of q-vector)
+ int numDoFs() const;
+ /// get origin of a body-fixed frame, represented in world frame
+ /// @param body_index index for frame/body
+ /// @param world_origin pointer for return data
+ /// @return 0 on success, -1 on error
+ int getBodyOrigin(const int body_index, vec3* world_origin) const;
+ /// get center of mass of a body, represented in world frame
+ /// @param body_index index for frame/body
+ /// @param world_com pointer for return data
+ /// @return 0 on success, -1 on error
+ int getBodyCoM(const int body_index, vec3* world_com) const;
+ /// get transform from of a body-fixed frame to the world frame
+ /// @param body_index index for frame/body
+ /// @param world_T_body pointer for return data
+ /// @return 0 on success, -1 on error
+ int getBodyTransform(const int body_index, mat33* world_T_body) const;
+ /// get absolute angular velocity for a body, represented in the world frame
+ /// @param body_index index for frame/body
+ /// @param world_omega pointer for return data
+ /// @return 0 on success, -1 on error
+ int getBodyAngularVelocity(const int body_index, vec3* world_omega) const;
+ /// get linear velocity of a body, represented in world frame
+ /// @param body_index index for frame/body
+ /// @param world_velocity pointer for return data
+ /// @return 0 on success, -1 on error
+ int getBodyLinearVelocity(const int body_index, vec3* world_velocity) const;
+ /// get linear velocity of a body's CoM, represented in world frame
+ /// (not required for inverse dynamics, provided for convenience)
+ /// @param body_index index for frame/body
+ /// @param world_vel_com pointer for return data
+ /// @return 0 on success, -1 on error
+ int getBodyLinearVelocityCoM(const int body_index, vec3* world_velocity) const;
+ /// get origin of a body-fixed frame, represented in world frame
+ /// @param body_index index for frame/body
+ /// @param world_origin pointer for return data
+ /// @return 0 on success, -1 on error
+ int getBodyAngularAcceleration(const int body_index, vec3* world_dot_omega) const;
+ /// get origin of a body-fixed frame, represented in world frame
+ /// NOTE: this will include the gravitational acceleration, so the actual acceleration is
+ /// obtainened by setting gravitational acceleration to zero, or subtracting it.
+ /// @param body_index index for frame/body
+ /// @param world_origin pointer for return data
+ /// @return 0 on success, -1 on error
+ int getBodyLinearAcceleration(const int body_index, vec3* world_acceleration) const;
+
+#if (defined BT_ID_HAVE_MAT3X) && (defined BT_ID_WITH_JACOBIANS)
+ // get translational jacobian, in world frame (dworld_velocity/du)
+ int getBodyJacobianTrans(const int body_index, mat3x* world_jac_trans) const;
+ // get rotational jacobian, in world frame (dworld_omega/du)
+ int getBodyJacobianRot(const int body_index, mat3x* world_jac_rot) const;
+ // get product of translational jacobian derivative * generatlized velocities
+ int getBodyDotJacobianTransU(const int body_index, vec3* world_dot_jac_trans_u) const;
+ // get product of rotational jacobian derivative * generatlized velocities
+ int getBodyDotJacobianRotU(const int body_index, vec3* world_dot_jac_rot_u) const;
+#endif // BT_ID_HAVE_MAT3X
+
+ /// returns the (internal) index of body
+ /// @param body_index is the index of a body
+ /// @param parent_index pointer to where parent index will be stored
+ /// @return 0 on success, -1 on error
+ int getParentIndex(const int body_index, int* parent_index) const;
+ /// get joint type
+ /// @param body_index index of the body
+ /// @param joint_type the corresponding joint type
+ /// @return 0 on success, -1 on failure
+ int getJointType(const int body_index, JointType* joint_type) const;
+ /// get joint type as string
+ /// @param body_index index of the body
+ /// @param joint_type string naming the corresponding joint type
+ /// @return 0 on success, -1 on failure
+ int getJointTypeStr(const int body_index, const char** joint_type) const;
+ /// get offset translation to parent body (see addBody)
+ /// @param body_index index of the body
+ /// @param r the offset translation (see above)
+ /// @return 0 on success, -1 on failure
+ int getParentRParentBodyRef(const int body_index, vec3* r) const;
+ /// get offset rotation to parent body (see addBody)
+ /// @param body_index index of the body
+ /// @param T the transform (see above)
+ /// @return 0 on success, -1 on failure
+ int getBodyTParentRef(const int body_index, mat33* T) const;
+ /// get axis of motion (see addBody)
+ /// @param body_index index of the body
+ /// @param axis the axis (see above)
+ /// @return 0 on success, -1 on failure
+ int getBodyAxisOfMotion(const int body_index, vec3* axis) const;
+ /// get offset for degrees of freedom of this body into the q-vector
+ /// @param body_index index of the body
+ /// @param q_offset offset the q vector
+ /// @return -1 on error, 0 on success
+ int getDoFOffset(const int body_index, int* q_offset) const;
+ /// get user integer. not used by the library.
+ /// @param body_index index of the body
+ /// @param user_int the user integer
+ /// @return 0 on success, -1 on error
+ int getUserInt(const int body_index, int* user_int) const;
+ /// get user pointer. not used by the library.
+ /// @param body_index index of the body
+ /// @param user_ptr the user pointer
+ /// @return 0 on success, -1 on error
+ int getUserPtr(const int body_index, void** user_ptr) const;
+ /// set user integer. not used by the library.
+ /// @param body_index index of the body
+ /// @param user_int the user integer
+ /// @return 0 on success, -1 on error
+ int setUserInt(const int body_index, const int user_int);
+ /// set user pointer. not used by the library.
+ /// @param body_index index of the body
+ /// @param user_ptr the user pointer
+ /// @return 0 on success, -1 on error
+ int setUserPtr(const int body_index, void* const user_ptr);
+ /// set mass for a body
+ /// @param body_index index of the body
+ /// @param mass the mass to set
+ /// @return 0 on success, -1 on failure
+ int setBodyMass(const int body_index, const idScalar mass);
+ /// set first moment of mass for a body
+ /// (mass * center of mass, in body fixed frame, relative to joint)
+ /// @param body_index index of the body
+ /// @param first_mass_moment the vector to set
+ /// @return 0 on success, -1 on failure
+ int setBodyFirstMassMoment(const int body_index, const vec3& first_mass_moment);
+ /// set second moment of mass for a body
+ /// (moment of inertia, in body fixed frame, relative to joint)
+ /// @param body_index index of the body
+ /// @param second_mass_moment the inertia matrix
+ /// @return 0 on success, -1 on failure
+ int setBodySecondMassMoment(const int body_index, const mat33& second_mass_moment);
+ /// get mass for a body
+ /// @param body_index index of the body
+ /// @param mass the mass
+ /// @return 0 on success, -1 on failure
+ int getBodyMass(const int body_index, idScalar* mass) const;
+ /// get first moment of mass for a body
+ /// (mass * center of mass, in body fixed frame, relative to joint)
+ /// @param body_index index of the body
+ /// @param first_moment the vector
+ /// @return 0 on success, -1 on failure
+ int getBodyFirstMassMoment(const int body_index, vec3* first_mass_moment) const;
+ /// get second moment of mass for a body
+ /// (moment of inertia, in body fixed frame, relative to joint)
+ /// @param body_index index of the body
+ /// @param second_mass_moment the inertia matrix
+ /// @return 0 on success, -1 on failure
+ int getBodySecondMassMoment(const int body_index, mat33* second_mass_moment) const;
+ /// set all user forces and moments to zero
+ void clearAllUserForcesAndMoments();
+ /// Add an external force to a body, acting at the origin of the body-fixed frame.
+ /// Calls to addUserForce are cumulative. Set the user force and moment to zero
+ /// via clearAllUserForcesAndMoments()
+ /// @param body_force the force represented in the body-fixed frame of reference
+ /// @return 0 on success, -1 on error
+ int addUserForce(const int body_index, const vec3& body_force);
+ /// Add an external moment to a body.
+ /// Calls to addUserMoment are cumulative. Set the user force and moment to zero
+ /// via clearAllUserForcesAndMoments()
+ /// @param body_moment the moment represented in the body-fixed frame of reference
+ /// @return 0 on success, -1 on error
+ int addUserMoment(const int body_index, const vec3& body_moment);
+
+private:
+ // flag indicating if system has been initialized
+ bool m_is_finalized;
+ // flag indicating if mass properties are physically valid
+ bool m_mass_parameters_are_valid;
+ // flag defining if unphysical mass parameters are accepted
+ bool m_accept_invalid_mass_parameters;
+ // This struct implements the inverse dynamics calculations
+ class MultiBodyImpl;
+ MultiBodyImpl* m_impl;
+ // cache data structure for initialization
+ class InitCache;
+ InitCache* m_init_cache;
+};
+} // namespace btInverseDynamics
+#endif // MULTIBODYTREE_HPP_
diff --git a/thirdparty/bullet/src/BulletInverseDynamics/details/IDEigenInterface.hpp b/thirdparty/bullet/src/BulletInverseDynamics/details/IDEigenInterface.hpp
new file mode 100644
index 0000000000..836395cea2
--- /dev/null
+++ b/thirdparty/bullet/src/BulletInverseDynamics/details/IDEigenInterface.hpp
@@ -0,0 +1,36 @@
+#ifndef INVDYNEIGENINTERFACE_HPP_
+#define INVDYNEIGENINTERFACE_HPP_
+#include "../IDConfig.hpp"
+namespace btInverseDynamics {
+
+#define BT_ID_HAVE_MAT3X
+
+#ifdef BT_USE_DOUBLE_PRECISION
+typedef Eigen::Matrix<double, Eigen::Dynamic, 1, Eigen::DontAlign> vecx;
+typedef Eigen::Matrix<double, 3, 1, Eigen::DontAlign> vec3;
+typedef Eigen::Matrix<double, 3, 3, Eigen::DontAlign> mat33;
+typedef Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::DontAlign> matxx;
+typedef Eigen::Matrix<double, 3, Eigen::Dynamic, Eigen::DontAlign> mat3x;
+#else
+typedef Eigen::Matrix<float, Eigen::Dynamic, 1, Eigen::DontAlign> vecx;
+typedef Eigen::Matrix<float, 3, 1, Eigen::DontAlign> vec3;
+typedef Eigen::Matrix<float, 3, 3, Eigen::DontAlign> mat33;
+typedef Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::DontAlign> matxx;
+typedef Eigen::Matrix<float, 3, Eigen::Dynamic, Eigen::DontAlign> mat3x;
+#endif
+
+inline void resize(mat3x &m, Eigen::Index size) {
+ m.resize(3, size);
+ m.setZero();
+}
+
+inline void setMatxxElem(const idArrayIdx row, const idArrayIdx col, const idScalar val, matxx*m){
+ (*m)(row, col) = val;
+}
+
+inline void setMat3xElem(const idArrayIdx row, const idArrayIdx col, const idScalar val, mat3x*m){
+ (*m)(row, col) = val;
+}
+
+}
+#endif // INVDYNEIGENINTERFACE_HPP_
diff --git a/thirdparty/bullet/src/BulletInverseDynamics/details/IDLinearMathInterface.hpp b/thirdparty/bullet/src/BulletInverseDynamics/details/IDLinearMathInterface.hpp
new file mode 100644
index 0000000000..5bb4a33bdd
--- /dev/null
+++ b/thirdparty/bullet/src/BulletInverseDynamics/details/IDLinearMathInterface.hpp
@@ -0,0 +1,172 @@
+#ifndef IDLINEARMATHINTERFACE_HPP_
+#define IDLINEARMATHINTERFACE_HPP_
+
+#include <cstdlib>
+
+#include "../IDConfig.hpp"
+
+#include "../../LinearMath/btMatrix3x3.h"
+#include "../../LinearMath/btVector3.h"
+#include "../../LinearMath/btMatrixX.h"
+#define BT_ID_HAVE_MAT3X
+
+namespace btInverseDynamics {
+class vec3;
+class vecx;
+class mat33;
+typedef btMatrixX<idScalar> matxx;
+
+class vec3 : public btVector3 {
+public:
+ vec3() : btVector3() {}
+ vec3(const btVector3& btv) { *this = btv; }
+ idScalar& operator()(int i) { return (*this)[i]; }
+ const idScalar& operator()(int i) const { return (*this)[i]; }
+ int size() const { return 3; }
+ const vec3& operator=(const btVector3& rhs) {
+ *static_cast<btVector3*>(this) = rhs;
+ return *this;
+ }
+};
+
+class mat33 : public btMatrix3x3 {
+public:
+ mat33() : btMatrix3x3() {}
+ mat33(const btMatrix3x3& btm) { *this = btm; }
+ idScalar& operator()(int i, int j) { return (*this)[i][j]; }
+ const idScalar& operator()(int i, int j) const { return (*this)[i][j]; }
+ const mat33& operator=(const btMatrix3x3& rhs) {
+ *static_cast<btMatrix3x3*>(this) = rhs;
+ return *this;
+ }
+ friend mat33 operator*(const idScalar& s, const mat33& a);
+ friend mat33 operator/(const mat33& a, const idScalar& s);
+};
+
+inline mat33 operator/(const mat33& a, const idScalar& s) { return a * (1.0 / s); }
+
+inline mat33 operator*(const idScalar& s, const mat33& a) { return a * s; }
+
+class vecx : public btVectorX<idScalar> {
+public:
+ vecx(int size) : btVectorX(size) {}
+ const vecx& operator=(const btVectorX<idScalar>& rhs) {
+ *static_cast<btVectorX*>(this) = rhs;
+ return *this;
+ }
+
+ idScalar& operator()(int i) { return (*this)[i]; }
+ const idScalar& operator()(int i) const { return (*this)[i]; }
+
+ friend vecx operator*(const vecx& a, const idScalar& s);
+ friend vecx operator*(const idScalar& s, const vecx& a);
+
+ friend vecx operator+(const vecx& a, const vecx& b);
+ friend vecx operator-(const vecx& a, const vecx& b);
+ friend vecx operator/(const vecx& a, const idScalar& s);
+};
+
+inline vecx operator*(const vecx& a, const idScalar& s) {
+ vecx result(a.size());
+ for (int i = 0; i < result.size(); i++) {
+ result(i) = a(i) * s;
+ }
+ return result;
+}
+inline vecx operator*(const idScalar& s, const vecx& a) { return a * s; }
+inline vecx operator+(const vecx& a, const vecx& b) {
+ vecx result(a.size());
+ // TODO: error handling for a.size() != b.size()??
+ if (a.size() != b.size()) {
+ error_message("size missmatch. a.size()= %d, b.size()= %d\n", a.size(), b.size());
+ abort();
+ }
+ for (int i = 0; i < a.size(); i++) {
+ result(i) = a(i) + b(i);
+ }
+
+ return result;
+}
+
+inline vecx operator-(const vecx& a, const vecx& b) {
+ vecx result(a.size());
+ // TODO: error handling for a.size() != b.size()??
+ if (a.size() != b.size()) {
+ error_message("size missmatch. a.size()= %d, b.size()= %d\n", a.size(), b.size());
+ abort();
+ }
+ for (int i = 0; i < a.size(); i++) {
+ result(i) = a(i) - b(i);
+ }
+ return result;
+}
+inline vecx operator/(const vecx& a, const idScalar& s) {
+ vecx result(a.size());
+ for (int i = 0; i < result.size(); i++) {
+ result(i) = a(i) / s;
+ }
+
+ return result;
+}
+
+// use btMatrixX to implement 3xX matrix
+class mat3x : public matxx {
+public:
+ mat3x(){}
+ mat3x(const mat3x&rhs) {
+ matxx::resize(rhs.rows(), rhs.cols());
+ *this = rhs;
+ }
+ mat3x(int rows, int cols): matxx(3,cols) {
+ }
+ void operator=(const mat3x& rhs) {
+ if (m_cols != rhs.m_cols) {
+ error_message("size missmatch, cols= %d but rhs.cols= %d\n", cols(), rhs.cols());
+ abort();
+ }
+ for(int i=0;i<rows();i++) {
+ for(int k=0;k<cols();k++) {
+ setElem(i,k,rhs(i,k));
+ }
+ }
+ }
+ void setZero() {
+ matxx::setZero();
+ }
+};
+
+
+inline vec3 operator*(const mat3x& a, const vecx& b) {
+ vec3 result;
+ if (a.cols() != b.size()) {
+ error_message("size missmatch. a.cols()= %d, b.size()= %d\n", a.cols(), b.size());
+ abort();
+ }
+ result(0)=0.0;
+ result(1)=0.0;
+ result(2)=0.0;
+ for(int i=0;i<b.size();i++) {
+ for(int k=0;k<3;k++) {
+ result(k)+=a(k,i)*b(i);
+ }
+ }
+ return result;
+}
+
+
+inline void resize(mat3x &m, idArrayIdx size) {
+ m.resize(3, size);
+ m.setZero();
+}
+
+inline void setMatxxElem(const idArrayIdx row, const idArrayIdx col, const idScalar val, matxx*m){
+ m->setElem(row, col, val);
+}
+
+inline void setMat3xElem(const idArrayIdx row, const idArrayIdx col, const idScalar val, mat3x*m){
+ m->setElem(row, col, val);
+}
+
+}
+
+#endif // IDLINEARMATHINTERFACE_HPP_
diff --git a/thirdparty/bullet/src/BulletInverseDynamics/details/IDMatVec.hpp b/thirdparty/bullet/src/BulletInverseDynamics/details/IDMatVec.hpp
new file mode 100644
index 0000000000..4d3f6c87e9
--- /dev/null
+++ b/thirdparty/bullet/src/BulletInverseDynamics/details/IDMatVec.hpp
@@ -0,0 +1,415 @@
+/// @file Built-In Matrix-Vector functions
+#ifndef IDMATVEC_HPP_
+#define IDMATVEC_HPP_
+
+#include <cstdlib>
+
+#include "../IDConfig.hpp"
+#define BT_ID_HAVE_MAT3X
+
+namespace btInverseDynamics {
+class vec3;
+class vecx;
+class mat33;
+class matxx;
+class mat3x;
+
+/// This is a very basic implementation to enable stand-alone use of the library.
+/// The implementation is not really optimized and misses many features that you would
+/// want from a "fully featured" linear math library.
+class vec3 {
+public:
+ idScalar& operator()(int i) { return m_data[i]; }
+ const idScalar& operator()(int i) const { return m_data[i]; }
+ const int size() const { return 3; }
+ const vec3& operator=(const vec3& rhs);
+ const vec3& operator+=(const vec3& b);
+ const vec3& operator-=(const vec3& b);
+ vec3 cross(const vec3& b) const;
+ idScalar dot(const vec3& b) const;
+
+ friend vec3 operator*(const mat33& a, const vec3& b);
+ friend vec3 operator*(const vec3& a, const idScalar& s);
+ friend vec3 operator*(const idScalar& s, const vec3& a);
+
+ friend vec3 operator+(const vec3& a, const vec3& b);
+ friend vec3 operator-(const vec3& a, const vec3& b);
+ friend vec3 operator/(const vec3& a, const idScalar& s);
+
+private:
+ idScalar m_data[3];
+};
+
+class mat33 {
+public:
+ idScalar& operator()(int i, int j) { return m_data[3 * i + j]; }
+ const idScalar& operator()(int i, int j) const { return m_data[3 * i + j]; }
+ const mat33& operator=(const mat33& rhs);
+ mat33 transpose() const;
+ const mat33& operator+=(const mat33& b);
+ const mat33& operator-=(const mat33& b);
+
+ friend mat33 operator*(const mat33& a, const mat33& b);
+ friend vec3 operator*(const mat33& a, const vec3& b);
+ friend mat33 operator*(const mat33& a, const idScalar& s);
+ friend mat33 operator*(const idScalar& s, const mat33& a);
+ friend mat33 operator+(const mat33& a, const mat33& b);
+ friend mat33 operator-(const mat33& a, const mat33& b);
+ friend mat33 operator/(const mat33& a, const idScalar& s);
+
+private:
+ // layout is [0,1,2;3,4,5;6,7,8]
+ idScalar m_data[9];
+};
+
+class vecx {
+public:
+ vecx(int size) : m_size(size) {
+ m_data = static_cast<idScalar*>(idMalloc(sizeof(idScalar) * size));
+ }
+ ~vecx() { idFree(m_data); }
+ const vecx& operator=(const vecx& rhs);
+ idScalar& operator()(int i) { return m_data[i]; }
+ const idScalar& operator()(int i) const { return m_data[i]; }
+ const int& size() const { return m_size; }
+
+ friend vecx operator*(const vecx& a, const idScalar& s);
+ friend vecx operator*(const idScalar& s, const vecx& a);
+
+ friend vecx operator+(const vecx& a, const vecx& b);
+ friend vecx operator-(const vecx& a, const vecx& b);
+ friend vecx operator/(const vecx& a, const idScalar& s);
+
+private:
+ int m_size;
+ idScalar* m_data;
+};
+
+class matxx {
+public:
+ matxx() {
+ m_data = 0x0;
+ m_cols=0;
+ m_rows=0;
+ }
+ matxx(int rows, int cols) : m_rows(rows), m_cols(cols) {
+ m_data = static_cast<idScalar*>(idMalloc(sizeof(idScalar) * rows * cols));
+ }
+ ~matxx() { idFree(m_data); }
+ idScalar& operator()(int row, int col) { return m_data[row * m_cols + col]; }
+ const idScalar& operator()(int row, int col) const { return m_data[row * m_cols + col]; }
+ const int& rows() const { return m_rows; }
+ const int& cols() const { return m_cols; }
+
+private:
+ int m_rows;
+ int m_cols;
+ idScalar* m_data;
+};
+
+class mat3x {
+public:
+ mat3x() {
+ m_data = 0x0;
+ m_cols=0;
+ }
+ mat3x(const mat3x&rhs) {
+ m_cols=rhs.m_cols;
+ allocate();
+ *this = rhs;
+ }
+ mat3x(int rows, int cols): m_cols(cols) {
+ allocate();
+ };
+ void operator=(const mat3x& rhs) {
+ if (m_cols != rhs.m_cols) {
+ error_message("size missmatch, cols= %d but rhs.cols= %d\n", cols(), rhs.cols());
+ abort();
+ }
+ for(int i=0;i<3*m_cols;i++) {
+ m_data[i] = rhs.m_data[i];
+ }
+ }
+
+ ~mat3x() {
+ free();
+ }
+ idScalar& operator()(int row, int col) { return m_data[row * m_cols + col]; }
+ const idScalar& operator()(int row, int col) const { return m_data[row * m_cols + col]; }
+ int rows() const { return m_rows; }
+ const int& cols() const { return m_cols; }
+ void resize(int rows, int cols) {
+ m_cols=cols;
+ free();
+ allocate();
+ }
+ void setZero() {
+ memset(m_data,0x0,sizeof(idScalar)*m_rows*m_cols);
+ }
+ // avoid operators that would allocate -- use functions sub/add/mul in IDMath.hpp instead
+private:
+ void allocate(){m_data = static_cast<idScalar*>(idMalloc(sizeof(idScalar) * m_rows * m_cols));}
+ void free() { idFree(m_data);}
+ enum {m_rows=3};
+ int m_cols;
+ idScalar* m_data;
+};
+
+inline void resize(mat3x &m, idArrayIdx size) {
+ m.resize(3, size);
+ m.setZero();
+}
+
+//////////////////////////////////////////////////
+// Implementations
+inline const vec3& vec3::operator=(const vec3& rhs) {
+ if (&rhs != this) {
+ memcpy(m_data, rhs.m_data, 3 * sizeof(idScalar));
+ }
+ return *this;
+}
+
+inline vec3 vec3::cross(const vec3& b) const {
+ vec3 result;
+ result.m_data[0] = m_data[1] * b.m_data[2] - m_data[2] * b.m_data[1];
+ result.m_data[1] = m_data[2] * b.m_data[0] - m_data[0] * b.m_data[2];
+ result.m_data[2] = m_data[0] * b.m_data[1] - m_data[1] * b.m_data[0];
+
+ return result;
+}
+
+inline idScalar vec3::dot(const vec3& b) const {
+ return m_data[0] * b.m_data[0] + m_data[1] * b.m_data[1] + m_data[2] * b.m_data[2];
+}
+
+inline const mat33& mat33::operator=(const mat33& rhs) {
+ if (&rhs != this) {
+ memcpy(m_data, rhs.m_data, 9 * sizeof(idScalar));
+ }
+ return *this;
+}
+inline mat33 mat33::transpose() const {
+ mat33 result;
+ result.m_data[0] = m_data[0];
+ result.m_data[1] = m_data[3];
+ result.m_data[2] = m_data[6];
+ result.m_data[3] = m_data[1];
+ result.m_data[4] = m_data[4];
+ result.m_data[5] = m_data[7];
+ result.m_data[6] = m_data[2];
+ result.m_data[7] = m_data[5];
+ result.m_data[8] = m_data[8];
+
+ return result;
+}
+
+inline mat33 operator*(const mat33& a, const mat33& b) {
+ mat33 result;
+ result.m_data[0] =
+ a.m_data[0] * b.m_data[0] + a.m_data[1] * b.m_data[3] + a.m_data[2] * b.m_data[6];
+ result.m_data[1] =
+ a.m_data[0] * b.m_data[1] + a.m_data[1] * b.m_data[4] + a.m_data[2] * b.m_data[7];
+ result.m_data[2] =
+ a.m_data[0] * b.m_data[2] + a.m_data[1] * b.m_data[5] + a.m_data[2] * b.m_data[8];
+ result.m_data[3] =
+ a.m_data[3] * b.m_data[0] + a.m_data[4] * b.m_data[3] + a.m_data[5] * b.m_data[6];
+ result.m_data[4] =
+ a.m_data[3] * b.m_data[1] + a.m_data[4] * b.m_data[4] + a.m_data[5] * b.m_data[7];
+ result.m_data[5] =
+ a.m_data[3] * b.m_data[2] + a.m_data[4] * b.m_data[5] + a.m_data[5] * b.m_data[8];
+ result.m_data[6] =
+ a.m_data[6] * b.m_data[0] + a.m_data[7] * b.m_data[3] + a.m_data[8] * b.m_data[6];
+ result.m_data[7] =
+ a.m_data[6] * b.m_data[1] + a.m_data[7] * b.m_data[4] + a.m_data[8] * b.m_data[7];
+ result.m_data[8] =
+ a.m_data[6] * b.m_data[2] + a.m_data[7] * b.m_data[5] + a.m_data[8] * b.m_data[8];
+
+ return result;
+}
+
+inline const mat33& mat33::operator+=(const mat33& b) {
+ for (int i = 0; i < 9; i++) {
+ m_data[i] += b.m_data[i];
+ }
+
+ return *this;
+}
+
+inline const mat33& mat33::operator-=(const mat33& b) {
+ for (int i = 0; i < 9; i++) {
+ m_data[i] -= b.m_data[i];
+ }
+ return *this;
+}
+
+inline vec3 operator*(const mat33& a, const vec3& b) {
+ vec3 result;
+
+ result.m_data[0] =
+ a.m_data[0] * b.m_data[0] + a.m_data[1] * b.m_data[1] + a.m_data[2] * b.m_data[2];
+ result.m_data[1] =
+ a.m_data[3] * b.m_data[0] + a.m_data[4] * b.m_data[1] + a.m_data[5] * b.m_data[2];
+ result.m_data[2] =
+ a.m_data[6] * b.m_data[0] + a.m_data[7] * b.m_data[1] + a.m_data[8] * b.m_data[2];
+
+ return result;
+}
+
+inline const vec3& vec3::operator+=(const vec3& b) {
+ for (int i = 0; i < 3; i++) {
+ m_data[i] += b.m_data[i];
+ }
+ return *this;
+}
+
+inline const vec3& vec3::operator-=(const vec3& b) {
+ for (int i = 0; i < 3; i++) {
+ m_data[i] -= b.m_data[i];
+ }
+ return *this;
+}
+
+inline mat33 operator*(const mat33& a, const idScalar& s) {
+ mat33 result;
+ for (int i = 0; i < 9; i++) {
+ result.m_data[i] = a.m_data[i] * s;
+ }
+ return result;
+}
+
+inline mat33 operator*(const idScalar& s, const mat33& a) { return a * s; }
+
+inline vec3 operator*(const vec3& a, const idScalar& s) {
+ vec3 result;
+ for (int i = 0; i < 3; i++) {
+ result.m_data[i] = a.m_data[i] * s;
+ }
+ return result;
+}
+inline vec3 operator*(const idScalar& s, const vec3& a) { return a * s; }
+
+inline mat33 operator+(const mat33& a, const mat33& b) {
+ mat33 result;
+ for (int i = 0; i < 9; i++) {
+ result.m_data[i] = a.m_data[i] + b.m_data[i];
+ }
+ return result;
+}
+inline vec3 operator+(const vec3& a, const vec3& b) {
+ vec3 result;
+ for (int i = 0; i < 3; i++) {
+ result.m_data[i] = a.m_data[i] + b.m_data[i];
+ }
+ return result;
+}
+
+inline mat33 operator-(const mat33& a, const mat33& b) {
+ mat33 result;
+ for (int i = 0; i < 9; i++) {
+ result.m_data[i] = a.m_data[i] - b.m_data[i];
+ }
+ return result;
+}
+inline vec3 operator-(const vec3& a, const vec3& b) {
+ vec3 result;
+ for (int i = 0; i < 3; i++) {
+ result.m_data[i] = a.m_data[i] - b.m_data[i];
+ }
+ return result;
+}
+
+inline mat33 operator/(const mat33& a, const idScalar& s) {
+ mat33 result;
+ for (int i = 0; i < 9; i++) {
+ result.m_data[i] = a.m_data[i] / s;
+ }
+ return result;
+}
+
+inline vec3 operator/(const vec3& a, const idScalar& s) {
+ vec3 result;
+ for (int i = 0; i < 3; i++) {
+ result.m_data[i] = a.m_data[i] / s;
+ }
+ return result;
+}
+
+inline const vecx& vecx::operator=(const vecx& rhs) {
+ if (size() != rhs.size()) {
+ error_message("size missmatch, size()= %d but rhs.size()= %d\n", size(), rhs.size());
+ abort();
+ }
+ if (&rhs != this) {
+ memcpy(m_data, rhs.m_data, rhs.size() * sizeof(idScalar));
+ }
+ return *this;
+}
+inline vecx operator*(const vecx& a, const idScalar& s) {
+ vecx result(a.size());
+ for (int i = 0; i < result.size(); i++) {
+ result.m_data[i] = a.m_data[i] * s;
+ }
+ return result;
+}
+inline vecx operator*(const idScalar& s, const vecx& a) { return a * s; }
+inline vecx operator+(const vecx& a, const vecx& b) {
+ vecx result(a.size());
+ // TODO: error handling for a.size() != b.size()??
+ if (a.size() != b.size()) {
+ error_message("size missmatch. a.size()= %d, b.size()= %d\n", a.size(), b.size());
+ abort();
+ }
+ for (int i = 0; i < a.size(); i++) {
+ result.m_data[i] = a.m_data[i] + b.m_data[i];
+ }
+
+ return result;
+}
+inline vecx operator-(const vecx& a, const vecx& b) {
+ vecx result(a.size());
+ // TODO: error handling for a.size() != b.size()??
+ if (a.size() != b.size()) {
+ error_message("size missmatch. a.size()= %d, b.size()= %d\n", a.size(), b.size());
+ abort();
+ }
+ for (int i = 0; i < a.size(); i++) {
+ result.m_data[i] = a.m_data[i] - b.m_data[i];
+ }
+ return result;
+}
+inline vecx operator/(const vecx& a, const idScalar& s) {
+ vecx result(a.size());
+ for (int i = 0; i < result.size(); i++) {
+ result.m_data[i] = a.m_data[i] / s;
+ }
+
+ return result;
+}
+
+inline vec3 operator*(const mat3x& a, const vecx& b) {
+ vec3 result;
+ if (a.cols() != b.size()) {
+ error_message("size missmatch. a.cols()= %d, b.size()= %d\n", a.cols(), b.size());
+ abort();
+ }
+ result(0)=0.0;
+ result(1)=0.0;
+ result(2)=0.0;
+ for(int i=0;i<b.size();i++) {
+ for(int k=0;k<3;k++) {
+ result(k)+=a(k,i)*b(i);
+ }
+ }
+ return result;
+}
+
+inline void setMatxxElem(const idArrayIdx row, const idArrayIdx col, const idScalar val, matxx*m){
+ (*m)(row, col) = val;
+}
+
+inline void setMat3xElem(const idArrayIdx row, const idArrayIdx col, const idScalar val, mat3x*m){
+ (*m)(row, col) = val;
+}
+
+} // namespace btInverseDynamcis
+#endif
diff --git a/thirdparty/bullet/src/BulletInverseDynamics/details/MultiBodyTreeImpl.cpp b/thirdparty/bullet/src/BulletInverseDynamics/details/MultiBodyTreeImpl.cpp
new file mode 100644
index 0000000000..b35c55df61
--- /dev/null
+++ b/thirdparty/bullet/src/BulletInverseDynamics/details/MultiBodyTreeImpl.cpp
@@ -0,0 +1,1028 @@
+#include "MultiBodyTreeImpl.hpp"
+
+namespace btInverseDynamics {
+
+MultiBodyTree::MultiBodyImpl::MultiBodyImpl(int num_bodies_, int num_dofs_)
+ : m_num_bodies(num_bodies_), m_num_dofs(num_dofs_)
+#if (defined BT_ID_HAVE_MAT3X) && (defined BT_ID_WITH_JACOBIANS)
+ ,m_m3x(3,m_num_dofs)
+#endif
+{
+
+#if (defined BT_ID_HAVE_MAT3X) && (defined BT_ID_WITH_JACOBIANS)
+ resize(m_m3x,m_num_dofs);
+#endif
+ m_body_list.resize(num_bodies_);
+ m_parent_index.resize(num_bodies_);
+ m_child_indices.resize(num_bodies_);
+ m_user_int.resize(num_bodies_);
+ m_user_ptr.resize(num_bodies_);
+
+ m_world_gravity(0) = 0.0;
+ m_world_gravity(1) = 0.0;
+ m_world_gravity(2) = -9.8;
+}
+
+const char *MultiBodyTree::MultiBodyImpl::jointTypeToString(const JointType &type) const {
+ switch (type) {
+ case FIXED:
+ return "fixed";
+ case REVOLUTE:
+ return "revolute";
+ case PRISMATIC:
+ return "prismatic";
+ case FLOATING:
+ return "floating";
+ }
+ return "error: invalid";
+}
+
+inline void indent(const int &level) {
+ for (int j = 0; j < level; j++)
+ id_printf(" "); // indent
+}
+
+void MultiBodyTree::MultiBodyImpl::printTree() {
+ id_printf("body %.2d[%s]: root\n", 0, jointTypeToString(m_body_list[0].m_joint_type));
+ printTree(0, 0);
+}
+
+void MultiBodyTree::MultiBodyImpl::printTreeData() {
+ for (idArrayIdx i = 0; i < m_body_list.size(); i++) {
+ RigidBody &body = m_body_list[i];
+ id_printf("body: %d\n", static_cast<int>(i));
+ id_printf("type: %s\n", jointTypeToString(body.m_joint_type));
+ id_printf("q_index= %d\n", body.m_q_index);
+ id_printf("Jac_JR= [%f;%f;%f]\n", body.m_Jac_JR(0), body.m_Jac_JR(1), body.m_Jac_JR(2));
+ id_printf("Jac_JT= [%f;%f;%f]\n", body.m_Jac_JT(0), body.m_Jac_JT(1), body.m_Jac_JT(2));
+
+ id_printf("mass = %f\n", body.m_mass);
+ id_printf("mass * com = [%f %f %f]\n", body.m_body_mass_com(0), body.m_body_mass_com(1),
+ body.m_body_mass_com(2));
+ id_printf("I_o= [%f %f %f;\n"
+ " %f %f %f;\n"
+ " %f %f %f]\n",
+ body.m_body_I_body(0, 0), body.m_body_I_body(0, 1), body.m_body_I_body(0, 2),
+ body.m_body_I_body(1, 0), body.m_body_I_body(1, 1), body.m_body_I_body(1, 2),
+ body.m_body_I_body(2, 0), body.m_body_I_body(2, 1), body.m_body_I_body(2, 2));
+
+ id_printf("parent_pos_parent_body_ref= [%f %f %f]\n", body.m_parent_pos_parent_body_ref(0),
+ body.m_parent_pos_parent_body_ref(1), body.m_parent_pos_parent_body_ref(2));
+ }
+}
+int MultiBodyTree::MultiBodyImpl::bodyNumDoFs(const JointType &type) const {
+ switch (type) {
+ case FIXED:
+ return 0;
+ case REVOLUTE:
+ case PRISMATIC:
+ return 1;
+ case FLOATING:
+ return 6;
+ }
+ error_message("unknown joint type %d\n", type);
+ return 0;
+}
+
+void MultiBodyTree::MultiBodyImpl::printTree(int index, int indentation) {
+ // this is adapted from URDF2Bullet.
+ // TODO: fix this and print proper graph (similar to git --log --graph)
+ int num_children = m_child_indices[index].size();
+
+ indentation += 2;
+ int count = 0;
+
+ for (int i = 0; i < num_children; i++) {
+ int child_index = m_child_indices[index][i];
+ indent(indentation);
+ id_printf("body %.2d[%s]: %.2d is child no. %d (qi= %d .. %d) \n", index,
+ jointTypeToString(m_body_list[index].m_joint_type), child_index, (count++) + 1,
+ m_body_list[index].m_q_index,
+ m_body_list[index].m_q_index + bodyNumDoFs(m_body_list[index].m_joint_type));
+ // first grandchild
+ printTree(child_index, indentation);
+ }
+}
+
+int MultiBodyTree::MultiBodyImpl::setGravityInWorldFrame(const vec3 &gravity) {
+ m_world_gravity = gravity;
+ return 0;
+}
+
+int MultiBodyTree::MultiBodyImpl::generateIndexSets() {
+ m_body_revolute_list.resize(0);
+ m_body_prismatic_list.resize(0);
+ int q_index = 0;
+ for (idArrayIdx i = 0; i < m_body_list.size(); i++) {
+ RigidBody &body = m_body_list[i];
+ body.m_q_index = -1;
+ switch (body.m_joint_type) {
+ case REVOLUTE:
+ m_body_revolute_list.push_back(i);
+ body.m_q_index = q_index;
+ q_index++;
+ break;
+ case PRISMATIC:
+ m_body_prismatic_list.push_back(i);
+ body.m_q_index = q_index;
+ q_index++;
+ break;
+ case FIXED:
+ // do nothing
+ break;
+ case FLOATING:
+ m_body_floating_list.push_back(i);
+ body.m_q_index = q_index;
+ q_index += 6;
+ break;
+ default:
+ error_message("unsupported joint type %d\n", body.m_joint_type);
+ return -1;
+ }
+ }
+ // sanity check
+ if (q_index != m_num_dofs) {
+ error_message("internal error, q_index= %d but num_dofs %d\n", q_index, m_num_dofs);
+ return -1;
+ }
+
+ m_child_indices.resize(m_body_list.size());
+
+ for (idArrayIdx child = 1; child < m_parent_index.size(); child++) {
+ const int &parent = m_parent_index[child];
+ if (parent >= 0 && parent < (static_cast<int>(m_parent_index.size()) - 1)) {
+ m_child_indices[parent].push_back(child);
+ } else {
+ if (-1 == parent) {
+ // multiple bodies are directly linked to the environment, ie, not a single root
+ error_message("building index sets parent(%zu)= -1 (multiple roots)\n", child);
+ } else {
+ // should never happen
+ error_message(
+ "building index sets. parent_index[%zu]= %d, but m_parent_index.size()= %d\n",
+ child, parent, static_cast<int>(m_parent_index.size()));
+ }
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+void MultiBodyTree::MultiBodyImpl::calculateStaticData() {
+ // relative kinematics that are not a function of q, u, dot_u
+ for (idArrayIdx i = 0; i < m_body_list.size(); i++) {
+ RigidBody &body = m_body_list[i];
+ switch (body.m_joint_type) {
+ case REVOLUTE:
+ body.m_parent_vel_rel(0) = 0;
+ body.m_parent_vel_rel(1) = 0;
+ body.m_parent_vel_rel(2) = 0;
+ body.m_parent_acc_rel(0) = 0;
+ body.m_parent_acc_rel(1) = 0;
+ body.m_parent_acc_rel(2) = 0;
+ body.m_parent_pos_parent_body = body.m_parent_pos_parent_body_ref;
+ break;
+ case PRISMATIC:
+ body.m_body_T_parent = body.m_body_T_parent_ref;
+ body.m_parent_Jac_JT = body.m_body_T_parent_ref.transpose() * body.m_Jac_JT;
+ body.m_body_ang_vel_rel(0) = 0;
+ body.m_body_ang_vel_rel(1) = 0;
+ body.m_body_ang_vel_rel(2) = 0;
+ body.m_body_ang_acc_rel(0) = 0;
+ body.m_body_ang_acc_rel(1) = 0;
+ body.m_body_ang_acc_rel(2) = 0;
+ break;
+ case FIXED:
+ body.m_parent_pos_parent_body = body.m_parent_pos_parent_body_ref;
+ body.m_body_T_parent = body.m_body_T_parent_ref;
+ body.m_body_ang_vel_rel(0) = 0;
+ body.m_body_ang_vel_rel(1) = 0;
+ body.m_body_ang_vel_rel(2) = 0;
+ body.m_parent_vel_rel(0) = 0;
+ body.m_parent_vel_rel(1) = 0;
+ body.m_parent_vel_rel(2) = 0;
+ body.m_body_ang_acc_rel(0) = 0;
+ body.m_body_ang_acc_rel(1) = 0;
+ body.m_body_ang_acc_rel(2) = 0;
+ body.m_parent_acc_rel(0) = 0;
+ body.m_parent_acc_rel(1) = 0;
+ body.m_parent_acc_rel(2) = 0;
+ break;
+ case FLOATING:
+ // no static data
+ break;
+ }
+
+ // resize & initialize jacobians to zero.
+#if (defined BT_ID_HAVE_MAT3X) && (defined BT_ID_WITH_JACOBIANS)
+ body.m_body_dot_Jac_T_u(0) = 0.0;
+ body.m_body_dot_Jac_T_u(1) = 0.0;
+ body.m_body_dot_Jac_T_u(2) = 0.0;
+ body.m_body_dot_Jac_R_u(0) = 0.0;
+ body.m_body_dot_Jac_R_u(1) = 0.0;
+ body.m_body_dot_Jac_R_u(2) = 0.0;
+ resize(body.m_body_Jac_T,m_num_dofs);
+ resize(body.m_body_Jac_R,m_num_dofs);
+ body.m_body_Jac_T.setZero();
+ body.m_body_Jac_R.setZero();
+#endif //
+ }
+}
+
+int MultiBodyTree::MultiBodyImpl::calculateInverseDynamics(const vecx &q, const vecx &u,
+ const vecx &dot_u, vecx *joint_forces) {
+ if (q.size() != m_num_dofs || u.size() != m_num_dofs || dot_u.size() != m_num_dofs ||
+ joint_forces->size() != m_num_dofs) {
+ error_message("wrong vector dimension. system has %d DOFs,\n"
+ "but dim(q)= %d, dim(u)= %d, dim(dot_u)= %d, dim(joint_forces)= %d\n",
+ m_num_dofs, static_cast<int>(q.size()), static_cast<int>(u.size()),
+ static_cast<int>(dot_u.size()), static_cast<int>(joint_forces->size()));
+ return -1;
+ }
+ // 1. relative kinematics
+ if(-1 == calculateKinematics(q,u,dot_u, POSITION_VELOCITY_ACCELERATION)) {
+ error_message("error in calculateKinematics\n");
+ return -1;
+ }
+ // 2. update contributions to equations of motion for every body.
+ for (idArrayIdx i = 0; i < m_body_list.size(); i++) {
+ RigidBody &body = m_body_list[i];
+ // 3.4 update dynamic terms (rate of change of angular & linear momentum)
+ body.m_eom_lhs_rotational =
+ body.m_body_I_body * body.m_body_ang_acc + body.m_body_mass_com.cross(body.m_body_acc) +
+ body.m_body_ang_vel.cross(body.m_body_I_body * body.m_body_ang_vel) -
+ body.m_body_moment_user;
+ body.m_eom_lhs_translational =
+ body.m_body_ang_acc.cross(body.m_body_mass_com) + body.m_mass * body.m_body_acc +
+ body.m_body_ang_vel.cross(body.m_body_ang_vel.cross(body.m_body_mass_com)) -
+ body.m_body_force_user;
+ }
+
+ // 3. calculate full set of forces at parent joint
+ // (not directly calculating the joint force along the free direction
+ // simplifies inclusion of fixed joints.
+ // An alternative would be to fuse bodies in a pre-processing step,
+ // but that would make changing masses online harder (eg, payload masses
+ // added with fixed joints to a gripper)
+ // Also, this enables adding zero weight bodies as a way to calculate frame poses
+ // for force elements, etc.
+
+ for (int body_idx = m_body_list.size() - 1; body_idx >= 0; body_idx--) {
+ // sum of forces and moments acting on this body from its children
+ vec3 sum_f_children;
+ vec3 sum_m_children;
+ setZero(sum_f_children);
+ setZero(sum_m_children);
+ for (idArrayIdx child_list_idx = 0; child_list_idx < m_child_indices[body_idx].size();
+ child_list_idx++) {
+ const RigidBody &child = m_body_list[m_child_indices[body_idx][child_list_idx]];
+ vec3 child_joint_force_in_this_frame =
+ child.m_body_T_parent.transpose() * child.m_force_at_joint;
+ sum_f_children -= child_joint_force_in_this_frame;
+ sum_m_children -= child.m_body_T_parent.transpose() * child.m_moment_at_joint +
+ child.m_parent_pos_parent_body.cross(child_joint_force_in_this_frame);
+ }
+ RigidBody &body = m_body_list[body_idx];
+
+ body.m_force_at_joint = body.m_eom_lhs_translational - sum_f_children;
+ body.m_moment_at_joint = body.m_eom_lhs_rotational - sum_m_children;
+ }
+
+ // 4. Calculate Joint forces.
+ // These are the components of force_at_joint/moment_at_joint
+ // in the free directions given by Jac_JT/Jac_JR
+ // 4.1 revolute joints
+ for (idArrayIdx i = 0; i < m_body_revolute_list.size(); i++) {
+ RigidBody &body = m_body_list[m_body_revolute_list[i]];
+ // (*joint_forces)(body.m_q_index) = body.m_Jac_JR.transpose() * body.m_moment_at_joint;
+ (*joint_forces)(body.m_q_index) = body.m_Jac_JR.dot(body.m_moment_at_joint);
+ }
+ // 4.2 for prismatic joints
+ for (idArrayIdx i = 0; i < m_body_prismatic_list.size(); i++) {
+ RigidBody &body = m_body_list[m_body_prismatic_list[i]];
+ // (*joint_forces)(body.m_q_index) = body.m_Jac_JT.transpose() * body.m_force_at_joint;
+ (*joint_forces)(body.m_q_index) = body.m_Jac_JT.dot(body.m_force_at_joint);
+ }
+ // 4.3 floating bodies (6-DoF joints)
+ for (idArrayIdx i = 0; i < m_body_floating_list.size(); i++) {
+ RigidBody &body = m_body_list[m_body_floating_list[i]];
+ (*joint_forces)(body.m_q_index + 0) = body.m_moment_at_joint(0);
+ (*joint_forces)(body.m_q_index + 1) = body.m_moment_at_joint(1);
+ (*joint_forces)(body.m_q_index + 2) = body.m_moment_at_joint(2);
+
+ (*joint_forces)(body.m_q_index + 3) = body.m_force_at_joint(0);
+ (*joint_forces)(body.m_q_index + 4) = body.m_force_at_joint(1);
+ (*joint_forces)(body.m_q_index + 5) = body.m_force_at_joint(2);
+ }
+
+ return 0;
+}
+
+int MultiBodyTree::MultiBodyImpl::calculateKinematics(const vecx &q, const vecx &u, const vecx& dot_u,
+ const KinUpdateType type) {
+ if (q.size() != m_num_dofs || u.size() != m_num_dofs || dot_u.size() != m_num_dofs ) {
+ error_message("wrong vector dimension. system has %d DOFs,\n"
+ "but dim(q)= %d, dim(u)= %d, dim(dot_u)= %d\n",
+ m_num_dofs, static_cast<int>(q.size()), static_cast<int>(u.size()),
+ static_cast<int>(dot_u.size()));
+ return -1;
+ }
+ if(type != POSITION_ONLY && type != POSITION_VELOCITY && type != POSITION_VELOCITY_ACCELERATION) {
+ error_message("invalid type %d\n", type);
+ return -1;
+ }
+
+ // 1. update relative kinematics
+ // 1.1 for revolute
+ for (idArrayIdx i = 0; i < m_body_revolute_list.size(); i++) {
+ RigidBody &body = m_body_list[m_body_revolute_list[i]];
+ mat33 T;
+ bodyTParentFromAxisAngle(body.m_Jac_JR, q(body.m_q_index), &T);
+ body.m_body_T_parent = T * body.m_body_T_parent_ref;
+ if(type >= POSITION_VELOCITY) {
+ body.m_body_ang_vel_rel = body.m_Jac_JR * u(body.m_q_index);
+ }
+ if(type >= POSITION_VELOCITY_ACCELERATION) {
+ body.m_body_ang_acc_rel = body.m_Jac_JR * dot_u(body.m_q_index);
+ }
+ }
+ // 1.2 for prismatic
+ for (idArrayIdx i = 0; i < m_body_prismatic_list.size(); i++) {
+ RigidBody &body = m_body_list[m_body_prismatic_list[i]];
+ body.m_parent_pos_parent_body =
+ body.m_parent_pos_parent_body_ref + body.m_parent_Jac_JT * q(body.m_q_index);
+ if(type >= POSITION_VELOCITY) {
+ body.m_parent_vel_rel =
+ body.m_body_T_parent_ref.transpose() * body.m_Jac_JT * u(body.m_q_index);
+ }
+ if(type >= POSITION_VELOCITY_ACCELERATION) {
+ body.m_parent_acc_rel = body.m_parent_Jac_JT * dot_u(body.m_q_index);
+ }
+ }
+ // 1.3 fixed joints: nothing to do
+ // 1.4 6dof joints:
+ for (idArrayIdx i = 0; i < m_body_floating_list.size(); i++) {
+ RigidBody &body = m_body_list[m_body_floating_list[i]];
+
+ body.m_body_T_parent = transformZ(q(body.m_q_index + 2)) *
+ transformY(q(body.m_q_index + 1)) * transformX(q(body.m_q_index));
+ body.m_parent_pos_parent_body(0) = q(body.m_q_index + 3);
+ body.m_parent_pos_parent_body(1) = q(body.m_q_index + 4);
+ body.m_parent_pos_parent_body(2) = q(body.m_q_index + 5);
+ body.m_parent_pos_parent_body = body.m_body_T_parent * body.m_parent_pos_parent_body;
+
+ if(type >= POSITION_VELOCITY) {
+ body.m_body_ang_vel_rel(0) = u(body.m_q_index + 0);
+ body.m_body_ang_vel_rel(1) = u(body.m_q_index + 1);
+ body.m_body_ang_vel_rel(2) = u(body.m_q_index + 2);
+
+ body.m_parent_vel_rel(0) = u(body.m_q_index + 3);
+ body.m_parent_vel_rel(1) = u(body.m_q_index + 4);
+ body.m_parent_vel_rel(2) = u(body.m_q_index + 5);
+
+ body.m_parent_vel_rel = body.m_body_T_parent.transpose() * body.m_parent_vel_rel;
+ }
+ if(type >= POSITION_VELOCITY_ACCELERATION) {
+ body.m_body_ang_acc_rel(0) = dot_u(body.m_q_index + 0);
+ body.m_body_ang_acc_rel(1) = dot_u(body.m_q_index + 1);
+ body.m_body_ang_acc_rel(2) = dot_u(body.m_q_index + 2);
+
+ body.m_parent_acc_rel(0) = dot_u(body.m_q_index + 3);
+ body.m_parent_acc_rel(1) = dot_u(body.m_q_index + 4);
+ body.m_parent_acc_rel(2) = dot_u(body.m_q_index + 5);
+
+ body.m_parent_acc_rel = body.m_body_T_parent.transpose() * body.m_parent_acc_rel;
+ }
+ }
+
+ // 2. absolute kinematic quantities (vector valued)
+ // NOTE: this should be optimized by specializing for different body types
+ // (e.g., relative rotation is always zero for prismatic joints, etc.)
+
+ // calculations for root body
+ {
+ RigidBody &body = m_body_list[0];
+ // 3.1 update absolute positions and orientations:
+ // will be required if we add force elements (eg springs between bodies,
+ // or contacts)
+ // not required right now, added here for debugging purposes
+ body.m_body_pos = body.m_body_T_parent * body.m_parent_pos_parent_body;
+ body.m_body_T_world = body.m_body_T_parent;
+
+ if(type >= POSITION_VELOCITY) {
+ // 3.2 update absolute velocities
+ body.m_body_ang_vel = body.m_body_ang_vel_rel;
+ body.m_body_vel = body.m_parent_vel_rel;
+ }
+ if(type >= POSITION_VELOCITY_ACCELERATION) {
+ // 3.3 update absolute accelerations
+ // NOTE: assumption: dot(J_JR) = 0; true here, but not for general joints
+ body.m_body_ang_acc = body.m_body_ang_acc_rel;
+ body.m_body_acc = body.m_body_T_parent * body.m_parent_acc_rel;
+ // add gravitational acceleration to root body
+ // this is an efficient way to add gravitational terms,
+ // but it does mean that the kinematics are no longer
+ // correct at the acceleration level
+ // NOTE: To get correct acceleration kinematics, just set world_gravity to zero
+ body.m_body_acc = body.m_body_acc - body.m_body_T_parent * m_world_gravity;
+ }
+ }
+
+ for (idArrayIdx i = 1; i < m_body_list.size(); i++) {
+ RigidBody &body = m_body_list[i];
+ RigidBody &parent = m_body_list[m_parent_index[i]];
+ // 2.1 update absolute positions and orientations:
+ // will be required if we add force elements (eg springs between bodies,
+ // or contacts) not required right now added here for debugging purposes
+ body.m_body_pos =
+ body.m_body_T_parent * (parent.m_body_pos + body.m_parent_pos_parent_body);
+ body.m_body_T_world = body.m_body_T_parent * parent.m_body_T_world;
+
+ if(type >= POSITION_VELOCITY) {
+ // 2.2 update absolute velocities
+ body.m_body_ang_vel =
+ body.m_body_T_parent * parent.m_body_ang_vel + body.m_body_ang_vel_rel;
+
+ body.m_body_vel =
+ body.m_body_T_parent *
+ (parent.m_body_vel + parent.m_body_ang_vel.cross(body.m_parent_pos_parent_body) +
+ body.m_parent_vel_rel);
+ }
+ if(type >= POSITION_VELOCITY_ACCELERATION) {
+ // 2.3 update absolute accelerations
+ // NOTE: assumption: dot(J_JR) = 0; true here, but not for general joints
+ body.m_body_ang_acc =
+ body.m_body_T_parent * parent.m_body_ang_acc -
+ body.m_body_ang_vel_rel.cross(body.m_body_T_parent * parent.m_body_ang_vel) +
+ body.m_body_ang_acc_rel;
+ body.m_body_acc =
+ body.m_body_T_parent *
+ (parent.m_body_acc + parent.m_body_ang_acc.cross(body.m_parent_pos_parent_body) +
+ parent.m_body_ang_vel.cross(parent.m_body_ang_vel.cross(body.m_parent_pos_parent_body)) +
+ 2.0 * parent.m_body_ang_vel.cross(body.m_parent_vel_rel) + body.m_parent_acc_rel);
+ }
+ }
+
+ return 0;
+}
+
+#if (defined BT_ID_HAVE_MAT3X) && (defined BT_ID_WITH_JACOBIANS)
+
+void MultiBodyTree::MultiBodyImpl::addRelativeJacobianComponent(RigidBody&body) {
+ const int& idx=body.m_q_index;
+ switch(body.m_joint_type) {
+ case FIXED:
+ break;
+ case REVOLUTE:
+ setMat3xElem(0,idx, body.m_Jac_JR(0), &body.m_body_Jac_R);
+ setMat3xElem(1,idx, body.m_Jac_JR(1), &body.m_body_Jac_R);
+ setMat3xElem(2,idx, body.m_Jac_JR(2), &body.m_body_Jac_R);
+ break;
+ case PRISMATIC:
+ setMat3xElem(0,idx, body.m_body_T_parent_ref(0,0)*body.m_Jac_JT(0)
+ +body.m_body_T_parent_ref(1,0)*body.m_Jac_JT(1)
+ +body.m_body_T_parent_ref(2,0)*body.m_Jac_JT(2),
+ &body.m_body_Jac_T);
+ setMat3xElem(1,idx,body.m_body_T_parent_ref(0,1)*body.m_Jac_JT(0)
+ +body.m_body_T_parent_ref(1,1)*body.m_Jac_JT(1)
+ +body.m_body_T_parent_ref(2,1)*body.m_Jac_JT(2),
+ &body.m_body_Jac_T);
+ setMat3xElem(2,idx, body.m_body_T_parent_ref(0,2)*body.m_Jac_JT(0)
+ +body.m_body_T_parent_ref(1,2)*body.m_Jac_JT(1)
+ +body.m_body_T_parent_ref(2,2)*body.m_Jac_JT(2),
+ &body.m_body_Jac_T);
+ break;
+ case FLOATING:
+ setMat3xElem(0,idx+0, 1.0, &body.m_body_Jac_R);
+ setMat3xElem(1,idx+1, 1.0, &body.m_body_Jac_R);
+ setMat3xElem(2,idx+2, 1.0, &body.m_body_Jac_R);
+ // body_Jac_T = body_T_parent.transpose();
+ setMat3xElem(0,idx+3, body.m_body_T_parent(0,0), &body.m_body_Jac_T);
+ setMat3xElem(0,idx+4, body.m_body_T_parent(1,0), &body.m_body_Jac_T);
+ setMat3xElem(0,idx+5, body.m_body_T_parent(2,0), &body.m_body_Jac_T);
+
+ setMat3xElem(1,idx+3, body.m_body_T_parent(0,1), &body.m_body_Jac_T);
+ setMat3xElem(1,idx+4, body.m_body_T_parent(1,1), &body.m_body_Jac_T);
+ setMat3xElem(1,idx+5, body.m_body_T_parent(2,1), &body.m_body_Jac_T);
+
+ setMat3xElem(2,idx+3, body.m_body_T_parent(0,2), &body.m_body_Jac_T);
+ setMat3xElem(2,idx+4, body.m_body_T_parent(1,2), &body.m_body_Jac_T);
+ setMat3xElem(2,idx+5, body.m_body_T_parent(2,2), &body.m_body_Jac_T);
+
+ break;
+ }
+}
+
+int MultiBodyTree::MultiBodyImpl::calculateJacobians(const vecx& q, const vecx& u, const KinUpdateType type) {
+ if (q.size() != m_num_dofs || u.size() != m_num_dofs) {
+ error_message("wrong vector dimension. system has %d DOFs,\n"
+ "but dim(q)= %d, dim(u)= %d\n",
+ m_num_dofs, static_cast<int>(q.size()), static_cast<int>(u.size()));
+ return -1;
+ }
+ if(type != POSITION_ONLY && type != POSITION_VELOCITY) {
+ error_message("invalid type %d\n", type);
+ return -1;
+ }
+
+ addRelativeJacobianComponent(m_body_list[0]);
+ for (idArrayIdx i = 1; i < m_body_list.size(); i++) {
+ RigidBody &body = m_body_list[i];
+ RigidBody &parent = m_body_list[m_parent_index[i]];
+
+ mul(body.m_body_T_parent, parent.m_body_Jac_R,& body.m_body_Jac_R);
+ body.m_body_Jac_T = parent.m_body_Jac_T;
+ mul(tildeOperator(body.m_parent_pos_parent_body),parent.m_body_Jac_R,&m_m3x);
+ sub(body.m_body_Jac_T,m_m3x, &body.m_body_Jac_T);
+
+ addRelativeJacobianComponent(body);
+ mul(body.m_body_T_parent, body.m_body_Jac_T,&body.m_body_Jac_T);
+
+ if(type >= POSITION_VELOCITY) {
+ body.m_body_dot_Jac_R_u = body.m_body_T_parent * parent.m_body_dot_Jac_R_u -
+ body.m_body_ang_vel_rel.cross(body.m_body_T_parent * parent.m_body_ang_vel);
+ body.m_body_dot_Jac_T_u = body.m_body_T_parent *
+ (parent.m_body_dot_Jac_T_u + parent.m_body_dot_Jac_R_u.cross(body.m_parent_pos_parent_body) +
+ parent.m_body_ang_vel.cross(parent.m_body_ang_vel.cross(body.m_parent_pos_parent_body)) +
+ 2.0 * parent.m_body_ang_vel.cross(body.m_parent_vel_rel));
+ }
+ }
+ return 0;
+}
+#endif
+
+static inline void setSixDoFJacobians(const int dof, vec3 &Jac_JR, vec3 &Jac_JT) {
+ switch (dof) {
+ // rotational part
+ case 0:
+ Jac_JR(0) = 1;
+ Jac_JR(1) = 0;
+ Jac_JR(2) = 0;
+ setZero(Jac_JT);
+ break;
+ case 1:
+ Jac_JR(0) = 0;
+ Jac_JR(1) = 1;
+ Jac_JR(2) = 0;
+ setZero(Jac_JT);
+ break;
+ case 2:
+ Jac_JR(0) = 0;
+ Jac_JR(1) = 0;
+ Jac_JR(2) = 1;
+ setZero(Jac_JT);
+ break;
+ // translational part
+ case 3:
+ setZero(Jac_JR);
+ Jac_JT(0) = 1;
+ Jac_JT(1) = 0;
+ Jac_JT(2) = 0;
+ break;
+ case 4:
+ setZero(Jac_JR);
+ Jac_JT(0) = 0;
+ Jac_JT(1) = 1;
+ Jac_JT(2) = 0;
+ break;
+ case 5:
+ setZero(Jac_JR);
+ Jac_JT(0) = 0;
+ Jac_JT(1) = 0;
+ Jac_JT(2) = 1;
+ break;
+ }
+}
+
+static inline int jointNumDoFs(const JointType &type) {
+ switch (type) {
+ case FIXED:
+ return 0;
+ case REVOLUTE:
+ case PRISMATIC:
+ return 1;
+ case FLOATING:
+ return 6;
+ }
+ // this should never happen
+ error_message("invalid joint type\n");
+ // TODO add configurable abort/crash function
+ abort();
+ return 0;
+}
+
+int MultiBodyTree::MultiBodyImpl::calculateMassMatrix(const vecx &q, const bool update_kinematics,
+ const bool initialize_matrix,
+ const bool set_lower_triangular_matrix,
+ matxx *mass_matrix) {
+// This calculates the joint space mass matrix for the multibody system.
+// The algorithm is essentially an implementation of "method 3"
+// in "Efficient Dynamic Simulation of Robotic Mechanisms" (Walker and Orin, 1982)
+// (Later named "Composite Rigid Body Algorithm" by Featherstone).
+//
+// This implementation, however, handles branched systems and uses a formulation centered
+// on the origin of the body-fixed frame to avoid re-computing various quantities at the com.
+
+ if (q.size() != m_num_dofs || mass_matrix->rows() != m_num_dofs ||
+ mass_matrix->cols() != m_num_dofs) {
+ error_message("Dimension error. System has %d DOFs,\n"
+ "but dim(q)= %d, dim(mass_matrix)= %d x %d\n",
+ m_num_dofs, static_cast<int>(q.size()), static_cast<int>(mass_matrix->rows()),
+ static_cast<int>(mass_matrix->cols()));
+ return -1;
+ }
+
+ // TODO add optimized zeroing function?
+ if (initialize_matrix) {
+ for (int i = 0; i < m_num_dofs; i++) {
+ for (int j = 0; j < m_num_dofs; j++) {
+ setMatxxElem(i, j, 0.0, mass_matrix);
+ }
+ }
+ }
+
+ if (update_kinematics) {
+ // 1. update relative kinematics
+ // 1.1 for revolute joints
+ for (idArrayIdx i = 0; i < m_body_revolute_list.size(); i++) {
+ RigidBody &body = m_body_list[m_body_revolute_list[i]];
+ // from reference orientation (q=0) of body-fixed frame to current orientation
+ mat33 body_T_body_ref;
+ bodyTParentFromAxisAngle(body.m_Jac_JR, q(body.m_q_index), &body_T_body_ref);
+ body.m_body_T_parent = body_T_body_ref * body.m_body_T_parent_ref;
+ }
+ // 1.2 for prismatic joints
+ for (idArrayIdx i = 0; i < m_body_prismatic_list.size(); i++) {
+ RigidBody &body = m_body_list[m_body_prismatic_list[i]];
+ // body.m_body_T_parent= fixed
+ body.m_parent_pos_parent_body =
+ body.m_parent_pos_parent_body_ref + body.m_parent_Jac_JT * q(body.m_q_index);
+ }
+ // 1.3 fixed joints: nothing to do
+ // 1.4 6dof joints:
+ for (idArrayIdx i = 0; i < m_body_floating_list.size(); i++) {
+ RigidBody &body = m_body_list[m_body_floating_list[i]];
+
+ body.m_body_T_parent = transformZ(q(body.m_q_index + 2)) *
+ transformY(q(body.m_q_index + 1)) *
+ transformX(q(body.m_q_index));
+ body.m_parent_pos_parent_body(0) = q(body.m_q_index + 3);
+ body.m_parent_pos_parent_body(1) = q(body.m_q_index + 4);
+ body.m_parent_pos_parent_body(2) = q(body.m_q_index + 5);
+
+ body.m_parent_pos_parent_body = body.m_body_T_parent * body.m_parent_pos_parent_body;
+ }
+ }
+ for (int i = m_body_list.size() - 1; i >= 0; i--) {
+ RigidBody &body = m_body_list[i];
+ // calculate mass, center of mass and inertia of "composite rigid body",
+ // ie, sub-tree starting at current body
+ body.m_subtree_mass = body.m_mass;
+ body.m_body_subtree_mass_com = body.m_body_mass_com;
+ body.m_body_subtree_I_body = body.m_body_I_body;
+
+ for (idArrayIdx c = 0; c < m_child_indices[i].size(); c++) {
+ RigidBody &child = m_body_list[m_child_indices[i][c]];
+ mat33 body_T_child = child.m_body_T_parent.transpose();
+
+ body.m_subtree_mass += child.m_subtree_mass;
+ body.m_body_subtree_mass_com += body_T_child * child.m_body_subtree_mass_com +
+ child.m_parent_pos_parent_body * child.m_subtree_mass;
+ body.m_body_subtree_I_body +=
+ body_T_child * child.m_body_subtree_I_body * child.m_body_T_parent;
+
+ if (child.m_subtree_mass > 0) {
+ // Shift the reference point for the child subtree inertia using the
+ // Huygens-Steiner ("parallel axis") theorem.
+ // (First shift from child origin to child com, then from there to this body's
+ // origin)
+ vec3 r_com = body_T_child * child.m_body_subtree_mass_com / child.m_subtree_mass;
+ mat33 tilde_r_child_com = tildeOperator(r_com);
+ mat33 tilde_r_body_com = tildeOperator(child.m_parent_pos_parent_body + r_com);
+ body.m_body_subtree_I_body +=
+ child.m_subtree_mass *
+ (tilde_r_child_com * tilde_r_child_com - tilde_r_body_com * tilde_r_body_com);
+ }
+ }
+ }
+
+ for (int i = m_body_list.size() - 1; i >= 0; i--) {
+ const RigidBody &body = m_body_list[i];
+
+ // determine DoF-range for body
+ const int q_index_min = body.m_q_index;
+ const int q_index_max = q_index_min + jointNumDoFs(body.m_joint_type) - 1;
+ // loop over the DoFs used by this body
+ // local joint jacobians (ok as is for 1-DoF joints)
+ vec3 Jac_JR = body.m_Jac_JR;
+ vec3 Jac_JT = body.m_Jac_JT;
+ for (int col = q_index_max; col >= q_index_min; col--) {
+ // set jacobians for 6-DoF joints
+ if (FLOATING == body.m_joint_type) {
+ setSixDoFJacobians(col - q_index_min, Jac_JR, Jac_JT);
+ }
+
+ vec3 body_eom_rot =
+ body.m_body_subtree_I_body * Jac_JR + body.m_body_subtree_mass_com.cross(Jac_JT);
+ vec3 body_eom_trans =
+ body.m_subtree_mass * Jac_JT - body.m_body_subtree_mass_com.cross(Jac_JR);
+ setMatxxElem(col, col, Jac_JR.dot(body_eom_rot) + Jac_JT.dot(body_eom_trans), mass_matrix);
+
+ // rest of the mass matrix column upwards
+ {
+ // 1. for multi-dof joints, rest of the dofs of this body
+ for (int row = col - 1; row >= q_index_min; row--) {
+ if (FLOATING != body.m_joint_type) {
+ error_message("??\n");
+ return -1;
+ }
+ setSixDoFJacobians(row - q_index_min, Jac_JR, Jac_JT);
+ const double Mrc = Jac_JR.dot(body_eom_rot) + Jac_JT.dot(body_eom_trans);
+ setMatxxElem(col, row, Mrc, mass_matrix);
+ }
+ // 2. ancestor dofs
+ int child_idx = i;
+ int parent_idx = m_parent_index[i];
+ while (parent_idx >= 0) {
+ const RigidBody &child_body = m_body_list[child_idx];
+ const RigidBody &parent_body = m_body_list[parent_idx];
+
+ const mat33 parent_T_child = child_body.m_body_T_parent.transpose();
+ body_eom_rot = parent_T_child * body_eom_rot;
+ body_eom_trans = parent_T_child * body_eom_trans;
+ body_eom_rot += child_body.m_parent_pos_parent_body.cross(body_eom_trans);
+
+ const int parent_body_q_index_min = parent_body.m_q_index;
+ const int parent_body_q_index_max =
+ parent_body_q_index_min + jointNumDoFs(parent_body.m_joint_type) - 1;
+ vec3 Jac_JR = parent_body.m_Jac_JR;
+ vec3 Jac_JT = parent_body.m_Jac_JT;
+ for (int row = parent_body_q_index_max; row >= parent_body_q_index_min; row--) {
+ // set jacobians for 6-DoF joints
+ if (FLOATING == parent_body.m_joint_type) {
+ setSixDoFJacobians(row - parent_body_q_index_min, Jac_JR, Jac_JT);
+ }
+ const double Mrc = Jac_JR.dot(body_eom_rot) + Jac_JT.dot(body_eom_trans);
+ setMatxxElem(col, row, Mrc, mass_matrix);
+ }
+
+ child_idx = parent_idx;
+ parent_idx = m_parent_index[child_idx];
+ }
+ }
+ }
+ }
+
+ if (set_lower_triangular_matrix) {
+ for (int col = 0; col < m_num_dofs; col++) {
+ for (int row = 0; row < col; row++) {
+ setMatxxElem(row, col, (*mass_matrix)(col, row), mass_matrix);
+ }
+ }
+ }
+ return 0;
+}
+
+// utility macro
+#define CHECK_IF_BODY_INDEX_IS_VALID(index) \
+ do { \
+ if (index < 0 || index >= m_num_bodies) { \
+ error_message("invalid index %d (num_bodies= %d)\n", index, m_num_bodies); \
+ return -1; \
+ } \
+ } while (0)
+
+int MultiBodyTree::MultiBodyImpl::getParentIndex(const int body_index, int *p) {
+ CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+ *p = m_parent_index[body_index];
+ return 0;
+}
+
+int MultiBodyTree::MultiBodyImpl::getUserInt(const int body_index, int *user_int) const {
+ CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+ *user_int = m_user_int[body_index];
+ return 0;
+}
+int MultiBodyTree::MultiBodyImpl::getUserPtr(const int body_index, void **user_ptr) const {
+ CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+ *user_ptr = m_user_ptr[body_index];
+ return 0;
+}
+
+int MultiBodyTree::MultiBodyImpl::setUserInt(const int body_index, const int user_int) {
+ CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+ m_user_int[body_index] = user_int;
+ return 0;
+}
+
+int MultiBodyTree::MultiBodyImpl::setUserPtr(const int body_index, void *const user_ptr) {
+ CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+ m_user_ptr[body_index] = user_ptr;
+ return 0;
+}
+
+int MultiBodyTree::MultiBodyImpl::getBodyOrigin(int body_index, vec3 *world_origin) const {
+ CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+ const RigidBody &body = m_body_list[body_index];
+ *world_origin = body.m_body_T_world.transpose() * body.m_body_pos;
+ return 0;
+}
+
+int MultiBodyTree::MultiBodyImpl::getBodyCoM(int body_index, vec3 *world_com) const {
+ CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+ const RigidBody &body = m_body_list[body_index];
+ if (body.m_mass > 0) {
+ *world_com = body.m_body_T_world.transpose() *
+ (body.m_body_pos + body.m_body_mass_com / body.m_mass);
+ } else {
+ *world_com = body.m_body_T_world.transpose() * (body.m_body_pos);
+ }
+ return 0;
+}
+
+int MultiBodyTree::MultiBodyImpl::getBodyTransform(int body_index, mat33 *world_T_body) const {
+ CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+ const RigidBody &body = m_body_list[body_index];
+ *world_T_body = body.m_body_T_world.transpose();
+ return 0;
+}
+int MultiBodyTree::MultiBodyImpl::getBodyAngularVelocity(int body_index, vec3 *world_omega) const {
+ CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+ const RigidBody &body = m_body_list[body_index];
+ *world_omega = body.m_body_T_world.transpose() * body.m_body_ang_vel;
+ return 0;
+}
+int MultiBodyTree::MultiBodyImpl::getBodyLinearVelocity(int body_index,
+ vec3 *world_velocity) const {
+ CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+ const RigidBody &body = m_body_list[body_index];
+ *world_velocity = body.m_body_T_world.transpose() * body.m_body_vel;
+ return 0;
+}
+
+int MultiBodyTree::MultiBodyImpl::getBodyLinearVelocityCoM(int body_index,
+ vec3 *world_velocity) const {
+ CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+ const RigidBody &body = m_body_list[body_index];
+ vec3 com;
+ if (body.m_mass > 0) {
+ com = body.m_body_mass_com / body.m_mass;
+ } else {
+ com(0) = 0;
+ com(1) = 0;
+ com(2) = 0;
+ }
+
+ *world_velocity =
+ body.m_body_T_world.transpose() * (body.m_body_vel + body.m_body_ang_vel.cross(com));
+ return 0;
+}
+
+int MultiBodyTree::MultiBodyImpl::getBodyAngularAcceleration(int body_index,
+ vec3 *world_dot_omega) const {
+ CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+ const RigidBody &body = m_body_list[body_index];
+ *world_dot_omega = body.m_body_T_world.transpose() * body.m_body_ang_acc;
+ return 0;
+}
+int MultiBodyTree::MultiBodyImpl::getBodyLinearAcceleration(int body_index,
+ vec3 *world_acceleration) const {
+ CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+ const RigidBody &body = m_body_list[body_index];
+ *world_acceleration = body.m_body_T_world.transpose() * body.m_body_acc;
+ return 0;
+}
+
+int MultiBodyTree::MultiBodyImpl::getJointType(const int body_index, JointType *joint_type) const {
+ CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+ *joint_type = m_body_list[body_index].m_joint_type;
+ return 0;
+}
+
+int MultiBodyTree::MultiBodyImpl::getJointTypeStr(const int body_index,
+ const char **joint_type) const {
+ CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+ *joint_type = jointTypeToString(m_body_list[body_index].m_joint_type);
+ return 0;
+}
+
+int MultiBodyTree::MultiBodyImpl::getParentRParentBodyRef(const int body_index, vec3* r) const{
+ CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+ *r=m_body_list[body_index].m_parent_pos_parent_body_ref;
+ return 0;
+}
+
+int MultiBodyTree::MultiBodyImpl::getBodyTParentRef(const int body_index, mat33* T) const{
+ CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+ *T=m_body_list[body_index].m_body_T_parent_ref;
+ return 0;
+}
+
+int MultiBodyTree::MultiBodyImpl::getBodyAxisOfMotion(const int body_index, vec3* axis) const{
+ CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+ if(m_body_list[body_index].m_joint_type == REVOLUTE) {
+ *axis = m_body_list[body_index].m_Jac_JR;
+ return 0;
+ }
+ if(m_body_list[body_index].m_joint_type == PRISMATIC) {
+ *axis = m_body_list[body_index].m_Jac_JT;
+ return 0;
+ }
+ setZero(*axis);
+ return 0;
+}
+
+int MultiBodyTree::MultiBodyImpl::getDoFOffset(const int body_index, int *q_index) const {
+ CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+ *q_index = m_body_list[body_index].m_q_index;
+ return 0;
+}
+
+int MultiBodyTree::MultiBodyImpl::setBodyMass(const int body_index, const idScalar mass) {
+ CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+ m_body_list[body_index].m_mass = mass;
+ return 0;
+}
+
+int MultiBodyTree::MultiBodyImpl::setBodyFirstMassMoment(const int body_index,
+ const vec3& first_mass_moment) {
+ CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+ m_body_list[body_index].m_body_mass_com = first_mass_moment;
+ return 0;
+}
+int MultiBodyTree::MultiBodyImpl::setBodySecondMassMoment(const int body_index,
+ const mat33& second_mass_moment) {
+ CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+ m_body_list[body_index].m_body_I_body = second_mass_moment;
+ return 0;
+}
+int MultiBodyTree::MultiBodyImpl::getBodyMass(const int body_index, idScalar *mass) const {
+ CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+ *mass = m_body_list[body_index].m_mass;
+ return 0;
+}
+int MultiBodyTree::MultiBodyImpl::getBodyFirstMassMoment(const int body_index,
+ vec3 *first_mass_moment) const {
+ CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+ *first_mass_moment = m_body_list[body_index].m_body_mass_com;
+ return 0;
+}
+int MultiBodyTree::MultiBodyImpl::getBodySecondMassMoment(const int body_index,
+ mat33 *second_mass_moment) const {
+ CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+ *second_mass_moment = m_body_list[body_index].m_body_I_body;
+ return 0;
+}
+
+void MultiBodyTree::MultiBodyImpl::clearAllUserForcesAndMoments() {
+ for (int index = 0; index < m_num_bodies; index++) {
+ RigidBody &body = m_body_list[index];
+ setZero(body.m_body_force_user);
+ setZero(body.m_body_moment_user);
+ }
+}
+
+int MultiBodyTree::MultiBodyImpl::addUserForce(const int body_index, const vec3 &body_force) {
+ CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+ m_body_list[body_index].m_body_force_user += body_force;
+ return 0;
+}
+
+int MultiBodyTree::MultiBodyImpl::addUserMoment(const int body_index, const vec3 &body_moment) {
+ CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+ m_body_list[body_index].m_body_moment_user += body_moment;
+ return 0;
+}
+
+#if (defined BT_ID_HAVE_MAT3X) && (defined BT_ID_WITH_JACOBIANS)
+int MultiBodyTree::MultiBodyImpl::getBodyDotJacobianTransU(const int body_index, vec3* world_dot_jac_trans_u) const {
+ CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+ const RigidBody &body = m_body_list[body_index];
+ *world_dot_jac_trans_u = body.m_body_T_world.transpose() * body.m_body_dot_Jac_T_u;
+ return 0;
+}
+
+int MultiBodyTree::MultiBodyImpl::getBodyDotJacobianRotU(const int body_index, vec3* world_dot_jac_rot_u) const{
+ CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+ const RigidBody &body = m_body_list[body_index];
+ *world_dot_jac_rot_u = body.m_body_T_world.transpose() * body.m_body_dot_Jac_R_u;
+ return 0;
+}
+
+int MultiBodyTree::MultiBodyImpl::getBodyJacobianTrans(const int body_index, mat3x* world_jac_trans) const{
+ CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+ const RigidBody &body = m_body_list[body_index];
+ mul(body.m_body_T_world.transpose(), body.m_body_Jac_T, world_jac_trans);
+ return 0;
+}
+
+int MultiBodyTree::MultiBodyImpl::getBodyJacobianRot(const int body_index, mat3x* world_jac_rot) const{
+ CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+ const RigidBody &body = m_body_list[body_index];
+ mul(body.m_body_T_world.transpose(), body.m_body_Jac_R,world_jac_rot);
+ return 0;
+}
+
+#endif
+}
diff --git a/thirdparty/bullet/src/BulletInverseDynamics/details/MultiBodyTreeImpl.hpp b/thirdparty/bullet/src/BulletInverseDynamics/details/MultiBodyTreeImpl.hpp
new file mode 100644
index 0000000000..3efe9d0492
--- /dev/null
+++ b/thirdparty/bullet/src/BulletInverseDynamics/details/MultiBodyTreeImpl.hpp
@@ -0,0 +1,283 @@
+// The structs and classes defined here provide a basic inverse fynamics implementation used
+// by MultiBodyTree
+// User interaction should be through MultiBodyTree
+
+#ifndef MULTI_BODY_REFERENCE_IMPL_HPP_
+#define MULTI_BODY_REFERENCE_IMPL_HPP_
+
+#include "../IDConfig.hpp"
+#include "../MultiBodyTree.hpp"
+
+namespace btInverseDynamics {
+
+/// Structure for for rigid body mass properties, connectivity and kinematic state
+/// all vectors and matrices are in body-fixed frame, if not indicated otherwise.
+/// The body-fixed frame is located in the joint connecting the body to its parent.
+struct RigidBody {
+ ID_DECLARE_ALIGNED_ALLOCATOR();
+ // 1 Inertial properties
+ /// Mass
+ idScalar m_mass;
+ /// Mass times center of gravity in body-fixed frame
+ vec3 m_body_mass_com;
+ /// Moment of inertia w.r.t. body-fixed frame
+ mat33 m_body_I_body;
+
+ // 2 dynamic properties
+ /// Left-hand side of the body equation of motion, translational part
+ vec3 m_eom_lhs_translational;
+ /// Left-hand side of the body equation of motion, rotational part
+ vec3 m_eom_lhs_rotational;
+ /// Force acting at the joint when the body is cut from its parent;
+ /// includes impressed joint force in J_JT direction,
+ /// as well as constraint force,
+ /// in body-fixed frame
+ vec3 m_force_at_joint;
+ /// Moment acting at the joint when the body is cut from its parent;
+ /// includes impressed joint moment in J_JR direction, and constraint moment
+ /// in body-fixed frame
+ vec3 m_moment_at_joint;
+ /// external (user provided) force acting at the body-fixed frame's origin, written in that
+ /// frame
+ vec3 m_body_force_user;
+ /// external (user provided) moment acting at the body-fixed frame's origin, written in that
+ /// frame
+ vec3 m_body_moment_user;
+ // 3 absolute kinematic properties
+ /// Position of body-fixed frame relative to world frame
+ /// this is currently only for debugging purposes
+ vec3 m_body_pos;
+ /// Absolute velocity of body-fixed frame
+ vec3 m_body_vel;
+ /// Absolute acceleration of body-fixed frame
+ /// NOTE: if gravitational acceleration is not zero, this is the accelation PLUS gravitational
+ /// acceleration!
+ vec3 m_body_acc;
+ /// Absolute angular velocity
+ vec3 m_body_ang_vel;
+ /// Absolute angular acceleration
+ /// NOTE: if gravitational acceleration is not zero, this is the accelation PLUS gravitational
+ /// acceleration!
+ vec3 m_body_ang_acc;
+
+ // 4 relative kinematic properties.
+ // these are in the parent body frame
+ /// Transform from world to body-fixed frame;
+ /// this is currently only for debugging purposes
+ mat33 m_body_T_world;
+ /// Transform from parent to body-fixed frame
+ mat33 m_body_T_parent;
+ /// Vector from parent to child frame in parent frame
+ vec3 m_parent_pos_parent_body;
+ /// Relative angular velocity
+ vec3 m_body_ang_vel_rel;
+ /// Relative linear velocity
+ vec3 m_parent_vel_rel;
+ /// Relative angular acceleration
+ vec3 m_body_ang_acc_rel;
+ /// Relative linear acceleration
+ vec3 m_parent_acc_rel;
+
+ // 5 Data describing the joint type and geometry
+ /// Type of joint
+ JointType m_joint_type;
+ /// Position of joint frame (body-fixed frame at q=0) relative to the parent frame
+ /// Components are in body-fixed frame of the parent
+ vec3 m_parent_pos_parent_body_ref;
+ /// Orientation of joint frame (body-fixed frame at q=0) relative to the parent frame
+ mat33 m_body_T_parent_ref;
+ /// Joint rotational Jacobian, ie, the partial derivative of the body-fixed frames absolute
+ /// angular velocity w.r.t. the generalized velocity of this body's relative degree of freedom.
+ /// For revolute joints this is the joint axis, for prismatic joints it is a null matrix.
+ /// (NOTE: dimensions will have to be dynamic for additional joint types!)
+ vec3 m_Jac_JR;
+ /// Joint translational Jacobian, ie, the partial derivative of the body-fixed frames absolute
+ /// linear velocity w.r.t. the generalized velocity of this body's relative degree of freedom.
+ /// For prismatic joints this is the joint axis, for revolute joints it is a null matrix.
+ /// (NOTE: dimensions might have to be dynamic for additional joint types!)
+ vec3 m_Jac_JT;
+ /// m_Jac_JT in the parent frame, it, m_body_T_parent_ref.transpose()*m_Jac_JT
+ vec3 m_parent_Jac_JT;
+ /// Start of index range for the position degree(s) of freedom describing this body's motion
+ /// relative to
+ /// its parent. The indices are wrt the multibody system's q-vector of generalized coordinates.
+ int m_q_index;
+
+ // 6 Scratch data for mass matrix computation using "composite rigid body algorithm"
+ /// mass of the subtree rooted in this body
+ idScalar m_subtree_mass;
+ /// center of mass * mass for subtree rooted in this body, in body-fixed frame
+ vec3 m_body_subtree_mass_com;
+ /// moment of inertia of subtree rooted in this body, w.r.t. body origin, in body-fixed frame
+ mat33 m_body_subtree_I_body;
+
+#if (defined BT_ID_HAVE_MAT3X) && (defined BT_ID_WITH_JACOBIANS)
+ /// translational jacobian in body-fixed frame d(m_body_vel)/du
+ mat3x m_body_Jac_T;
+ /// rotationsl jacobian in body-fixed frame d(m_body_ang_vel)/du
+ mat3x m_body_Jac_R;
+ /// components of linear acceleration depending on u
+ /// (same as is d(m_Jac_T)/dt*u)
+ vec3 m_body_dot_Jac_T_u;
+ /// components of angular acceleration depending on u
+ /// (same as is d(m_Jac_T)/dt*u)
+ vec3 m_body_dot_Jac_R_u;
+#endif
+};
+
+/// The MBS implements a tree structured multibody system
+class MultiBodyTree::MultiBodyImpl {
+ friend class MultiBodyTree;
+
+public:
+ ID_DECLARE_ALIGNED_ALLOCATOR();
+
+ enum KinUpdateType {
+ POSITION_ONLY,
+ POSITION_VELOCITY,
+ POSITION_VELOCITY_ACCELERATION
+ };
+
+ /// constructor
+ /// @param num_bodies the number of bodies in the system
+ /// @param num_dofs number of degrees of freedom in the system
+ MultiBodyImpl(int num_bodies_, int num_dofs_);
+
+ /// \copydoc MultiBodyTree::calculateInverseDynamics
+ int calculateInverseDynamics(const vecx& q, const vecx& u, const vecx& dot_u,
+ vecx* joint_forces);
+ ///\copydoc MultiBodyTree::calculateMassMatrix
+ int calculateMassMatrix(const vecx& q, const bool update_kinematics,
+ const bool initialize_matrix, const bool set_lower_triangular_matrix,
+ matxx* mass_matrix);
+ /// calculate kinematics (vector quantities)
+ /// Depending on type, update positions only, positions & velocities, or positions, velocities
+ /// and accelerations.
+ int calculateKinematics(const vecx& q, const vecx& u, const vecx& dot_u, const KinUpdateType type);
+#if (defined BT_ID_HAVE_MAT3X) && (defined BT_ID_WITH_JACOBIANS)
+ /// calculate jacobians and (if type == POSITION_VELOCITY), also velocity-dependent accelration terms.
+ int calculateJacobians(const vecx& q, const vecx& u, const KinUpdateType type);
+ /// \copydoc MultiBodyTree::getBodyDotJacobianTransU
+ int getBodyDotJacobianTransU(const int body_index, vec3* world_dot_jac_trans_u) const ;
+ /// \copydoc MultiBodyTree::getBodyDotJacobianRotU
+ int getBodyDotJacobianRotU(const int body_index, vec3* world_dot_jac_rot_u) const;
+ /// \copydoc MultiBodyTree::getBodyJacobianTrans
+ int getBodyJacobianTrans(const int body_index, mat3x* world_jac_trans) const ;
+ /// \copydoc MultiBodyTree::getBodyJacobianRot
+ int getBodyJacobianRot(const int body_index, mat3x* world_jac_rot) const;
+ /// Add relative Jacobian component from motion relative to parent body
+ /// @param body the body to add the Jacobian component for
+ void addRelativeJacobianComponent(RigidBody&body);
+#endif
+ /// generate additional index sets from the parent_index array
+ /// @return -1 on error, 0 on success
+ int generateIndexSets();
+ /// set gravity acceleration in world frame
+ /// @param gravity gravity vector in the world frame
+ /// @return 0 on success, -1 on error
+ int setGravityInWorldFrame(const vec3& gravity);
+ /// pretty print tree
+ void printTree();
+ /// print tree data
+ void printTreeData();
+ /// initialize fixed data
+ void calculateStaticData();
+ /// \copydoc MultiBodyTree::getBodyFrame
+ int getBodyFrame(const int index, vec3* world_origin, mat33* body_T_world) const;
+ /// \copydoc MultiBodyTree::getParentIndex
+ int getParentIndex(const int body_index, int* m_parent_index);
+ /// \copydoc MultiBodyTree::getJointType
+ int getJointType(const int body_index, JointType* joint_type) const;
+ /// \copydoc MultiBodyTree::getJointTypeStr
+ int getJointTypeStr(const int body_index, const char** joint_type) const;
+ /// \copydoc MultiBodyTree::getParentRParentBodyRef
+ int getParentRParentBodyRef(const int body_index, vec3* r) const;
+ /// \copydoc MultiBodyTree::getBodyTParentRef
+ int getBodyTParentRef(const int body_index, mat33* T) const;
+ /// \copydoc MultiBodyTree::getBodyAxisOfMotion
+ int getBodyAxisOfMotion(const int body_index, vec3* axis) const;
+ /// \copydoc MultiBodyTree:getDoFOffset
+ int getDoFOffset(const int body_index, int* q_index) const;
+ /// \copydoc MultiBodyTree::getBodyOrigin
+ int getBodyOrigin(const int body_index, vec3* world_origin) const;
+ /// \copydoc MultiBodyTree::getBodyCoM
+ int getBodyCoM(const int body_index, vec3* world_com) const;
+ /// \copydoc MultiBodyTree::getBodyTransform
+ int getBodyTransform(const int body_index, mat33* world_T_body) const;
+ /// \copydoc MultiBodyTree::getBodyAngularVelocity
+ int getBodyAngularVelocity(const int body_index, vec3* world_omega) const;
+ /// \copydoc MultiBodyTree::getBodyLinearVelocity
+ int getBodyLinearVelocity(const int body_index, vec3* world_velocity) const;
+ /// \copydoc MultiBodyTree::getBodyLinearVelocityCoM
+ int getBodyLinearVelocityCoM(const int body_index, vec3* world_velocity) const;
+ /// \copydoc MultiBodyTree::getBodyAngularAcceleration
+ int getBodyAngularAcceleration(const int body_index, vec3* world_dot_omega) const;
+ /// \copydoc MultiBodyTree::getBodyLinearAcceleration
+ int getBodyLinearAcceleration(const int body_index, vec3* world_acceleration) const;
+ /// \copydoc MultiBodyTree::getUserInt
+ int getUserInt(const int body_index, int* user_int) const;
+ /// \copydoc MultiBodyTree::getUserPtr
+ int getUserPtr(const int body_index, void** user_ptr) const;
+ /// \copydoc MultiBodyTree::setUserInt
+ int setUserInt(const int body_index, const int user_int);
+ /// \copydoc MultiBodyTree::setUserPtr
+ int setUserPtr(const int body_index, void* const user_ptr);
+ ///\copydoc MultiBodytTree::setBodyMass
+ int setBodyMass(const int body_index, const idScalar mass);
+ ///\copydoc MultiBodytTree::setBodyFirstMassMoment
+ int setBodyFirstMassMoment(const int body_index, const vec3& first_mass_moment);
+ ///\copydoc MultiBodytTree::setBodySecondMassMoment
+ int setBodySecondMassMoment(const int body_index, const mat33& second_mass_moment);
+ ///\copydoc MultiBodytTree::getBodyMass
+ int getBodyMass(const int body_index, idScalar* mass) const;
+ ///\copydoc MultiBodytTree::getBodyFirstMassMoment
+ int getBodyFirstMassMoment(const int body_index, vec3* first_mass_moment) const;
+ ///\copydoc MultiBodytTree::getBodySecondMassMoment
+ int getBodySecondMassMoment(const int body_index, mat33* second_mass_moment) const;
+ /// \copydoc MultiBodyTree::clearAllUserForcesAndMoments
+ void clearAllUserForcesAndMoments();
+ /// \copydoc MultiBodyTree::addUserForce
+ int addUserForce(const int body_index, const vec3& body_force);
+ /// \copydoc MultiBodyTree::addUserMoment
+ int addUserMoment(const int body_index, const vec3& body_moment);
+
+private:
+ // debug function. print tree structure to stdout
+ void printTree(int index, int indentation);
+ // get string representation of JointType (for debugging)
+ const char* jointTypeToString(const JointType& type) const;
+ // get number of degrees of freedom from joint type
+ int bodyNumDoFs(const JointType& type) const;
+ // number of bodies in the system
+ int m_num_bodies;
+ // number of degrees of freedom
+ int m_num_dofs;
+ // Gravitational acceleration (in world frame)
+ vec3 m_world_gravity;
+ // vector of bodies in the system
+ // body 0 is used as an environment body and is allways fixed.
+ // The bodies are ordered such that a parent body always has an index
+ // smaller than its child.
+ idArray<RigidBody>::type m_body_list;
+ // Parent_index[i] is the index for i's parent body in body_list.
+ // This fully describes the tree.
+ idArray<int>::type m_parent_index;
+ // child_indices[i] contains a vector of indices of
+ // all children of the i-th body
+ idArray<idArray<int>::type>::type m_child_indices;
+ // Indices of rotary joints
+ idArray<int>::type m_body_revolute_list;
+ // Indices of prismatic joints
+ idArray<int>::type m_body_prismatic_list;
+ // Indices of floating joints
+ idArray<int>::type m_body_floating_list;
+ // a user-provided integer
+ idArray<int>::type m_user_int;
+ // a user-provided pointer
+ idArray<void*>::type m_user_ptr;
+#if (defined BT_ID_HAVE_MAT3X) && (defined BT_ID_WITH_JACOBIANS)
+ mat3x m_m3x;
+#endif
+};
+}
+#endif
diff --git a/thirdparty/bullet/src/BulletInverseDynamics/details/MultiBodyTreeInitCache.cpp b/thirdparty/bullet/src/BulletInverseDynamics/details/MultiBodyTreeInitCache.cpp
new file mode 100644
index 0000000000..47b4ab3890
--- /dev/null
+++ b/thirdparty/bullet/src/BulletInverseDynamics/details/MultiBodyTreeInitCache.cpp
@@ -0,0 +1,113 @@
+#include "MultiBodyTreeInitCache.hpp"
+
+namespace btInverseDynamics {
+
+MultiBodyTree::InitCache::InitCache() {
+ m_inertias.resize(0);
+ m_joints.resize(0);
+ m_num_dofs = 0;
+ m_root_index=-1;
+}
+
+int MultiBodyTree::InitCache::addBody(const int body_index, const int parent_index,
+ const JointType joint_type,
+ const vec3& parent_r_parent_body_ref,
+ const mat33& body_T_parent_ref,
+ const vec3& body_axis_of_motion, const idScalar mass,
+ const vec3& body_r_body_com, const mat33& body_I_body,
+ const int user_int, void* user_ptr) {
+ switch (joint_type) {
+ case REVOLUTE:
+ case PRISMATIC:
+ m_num_dofs += 1;
+ break;
+ case FIXED:
+ // does not add a degree of freedom
+ // m_num_dofs+=0;
+ break;
+ case FLOATING:
+ m_num_dofs += 6;
+ break;
+ default:
+ error_message("unknown joint type %d\n", joint_type);
+ return -1;
+ }
+
+ if(-1 == parent_index) {
+ if(m_root_index>=0) {
+ error_message("trying to add body %d as root, but already added %d as root body\n",
+ body_index, m_root_index);
+ return -1;
+ }
+ m_root_index=body_index;
+ }
+
+ JointData joint;
+ joint.m_child = body_index;
+ joint.m_parent = parent_index;
+ joint.m_type = joint_type;
+ joint.m_parent_pos_parent_child_ref = parent_r_parent_body_ref;
+ joint.m_child_T_parent_ref = body_T_parent_ref;
+ joint.m_child_axis_of_motion = body_axis_of_motion;
+
+ InertiaData body;
+ body.m_mass = mass;
+ body.m_body_pos_body_com = body_r_body_com;
+ body.m_body_I_body = body_I_body;
+
+ m_inertias.push_back(body);
+ m_joints.push_back(joint);
+ m_user_int.push_back(user_int);
+ m_user_ptr.push_back(user_ptr);
+ return 0;
+}
+int MultiBodyTree::InitCache::getInertiaData(const int index, InertiaData* inertia) const {
+ if (index < 0 || index > static_cast<int>(m_inertias.size())) {
+ error_message("index out of range\n");
+ return -1;
+ }
+
+ *inertia = m_inertias[index];
+ return 0;
+}
+
+int MultiBodyTree::InitCache::getUserInt(const int index, int* user_int) const {
+ if (index < 0 || index > static_cast<int>(m_user_int.size())) {
+ error_message("index out of range\n");
+ return -1;
+ }
+ *user_int = m_user_int[index];
+ return 0;
+}
+
+int MultiBodyTree::InitCache::getUserPtr(const int index, void** user_ptr) const {
+ if (index < 0 || index > static_cast<int>(m_user_ptr.size())) {
+ error_message("index out of range\n");
+ return -1;
+ }
+ *user_ptr = m_user_ptr[index];
+ return 0;
+}
+
+int MultiBodyTree::InitCache::getJointData(const int index, JointData* joint) const {
+ if (index < 0 || index > static_cast<int>(m_joints.size())) {
+ error_message("index out of range\n");
+ return -1;
+ }
+ *joint = m_joints[index];
+ return 0;
+}
+
+int MultiBodyTree::InitCache::buildIndexSets() {
+ // NOTE: This function assumes that proper indices were provided
+ // User2InternalIndex from utils can be used to facilitate this.
+
+ m_parent_index.resize(numBodies());
+ for (idArrayIdx j = 0; j < m_joints.size(); j++) {
+ const JointData& joint = m_joints[j];
+ m_parent_index[joint.m_child] = joint.m_parent;
+ }
+
+ return 0;
+}
+}
diff --git a/thirdparty/bullet/src/BulletInverseDynamics/details/MultiBodyTreeInitCache.hpp b/thirdparty/bullet/src/BulletInverseDynamics/details/MultiBodyTreeInitCache.hpp
new file mode 100644
index 0000000000..0d2aa4a071
--- /dev/null
+++ b/thirdparty/bullet/src/BulletInverseDynamics/details/MultiBodyTreeInitCache.hpp
@@ -0,0 +1,109 @@
+#ifndef MULTIBODYTREEINITCACHE_HPP_
+#define MULTIBODYTREEINITCACHE_HPP_
+
+#include "../IDConfig.hpp"
+#include "../IDMath.hpp"
+#include "../MultiBodyTree.hpp"
+
+namespace btInverseDynamics {
+/// Mass properties of a rigid body
+struct InertiaData {
+ ID_DECLARE_ALIGNED_ALLOCATOR();
+
+ /// mass
+ idScalar m_mass;
+ /// vector from body-fixed frame to center of mass,
+ /// in body-fixed frame, multiplied by the mass
+ vec3 m_body_pos_body_com;
+ /// moment of inertia w.r.t. the origin of the body-fixed
+ /// frame, represented in that frame
+ mat33 m_body_I_body;
+};
+
+/// Joint properties
+struct JointData {
+ ID_DECLARE_ALIGNED_ALLOCATOR();
+
+ /// type of joint
+ JointType m_type;
+ /// index of parent body
+ int m_parent;
+ /// index of child body
+ int m_child;
+ /// vector from parent's body-fixed frame to child's body-fixed
+ /// frame for q=0, written in the parent's body fixed frame
+ vec3 m_parent_pos_parent_child_ref;
+ /// Transform matrix converting vectors written in the parent's frame
+ /// into vectors written in the child's frame for q=0
+ /// ie, child_vector = child_T_parent_ref * parent_vector;
+ mat33 m_child_T_parent_ref;
+ /// Axis of motion for 1 degree-of-freedom joints,
+ /// written in the child's frame
+ /// For revolute joints, the q-value is positive for a positive
+ /// rotation about this axis.
+ /// For prismatic joints, the q-value is positive for a positive
+ /// translation is this direction.
+ vec3 m_child_axis_of_motion;
+};
+
+/// Data structure to store data passed by the user.
+/// This is used in MultiBodyTree::finalize to build internal data structures.
+class MultiBodyTree::InitCache {
+public:
+ ID_DECLARE_ALIGNED_ALLOCATOR();
+ /// constructor
+ InitCache();
+ ///\copydoc MultiBodyTree::addBody
+ int addBody(const int body_index, const int parent_index, const JointType joint_type,
+ const vec3 &parent_r_parent_body_ref, const mat33 &body_T_parent_ref,
+ const vec3 &body_axis_of_motion, idScalar mass, const vec3 &body_r_body_com,
+ const mat33 &body_I_body, const int user_int, void *user_ptr);
+ /// build index arrays
+ /// @return 0 on success, -1 on failure
+ int buildIndexSets();
+ /// @return number of degrees of freedom
+ int numDoFs() const { return m_num_dofs; }
+ /// @return number of bodies
+ int numBodies() const { return m_inertias.size(); }
+ /// get inertia data for index
+ /// @param index of the body
+ /// @param inertia pointer for return data
+ /// @return 0 on success, -1 on failure
+ int getInertiaData(const int index, InertiaData *inertia) const;
+ /// get joint data for index
+ /// @param index of the body
+ /// @param joint pointer for return data
+ /// @return 0 on success, -1 on failure
+ int getJointData(const int index, JointData *joint) const;
+ /// get parent index array (paren_index[i] is the index of the parent of i)
+ /// @param parent_index pointer for return data
+ void getParentIndexArray(idArray<int>::type *parent_index) { *parent_index = m_parent_index; }
+ /// get user integer
+ /// @param index body index
+ /// @param user_int user integer
+ /// @return 0 on success, -1 on failure
+ int getUserInt(const int index, int *user_int) const;
+ /// get user pointer
+ /// @param index body index
+ /// @param user_int user pointer
+ /// @return 0 on success, -1 on failure
+ int getUserPtr(const int index, void **user_ptr) const;
+
+private:
+ // vector of bodies
+ idArray<InertiaData>::type m_inertias;
+ // vector of joints
+ idArray<JointData>::type m_joints;
+ // number of mechanical degrees of freedom
+ int m_num_dofs;
+ // parent index array
+ idArray<int>::type m_parent_index;
+ // user integers
+ idArray<int>::type m_user_int;
+ // user pointers
+ idArray<void *>::type m_user_ptr;
+ // index of root body (or -1 if not set)
+ int m_root_index;
+};
+}
+#endif // MULTIBODYTREEINITCACHE_HPP_
diff --git a/thirdparty/bullet/src/BulletInverseDynamics/premake4.lua b/thirdparty/bullet/src/BulletInverseDynamics/premake4.lua
new file mode 100644
index 0000000000..774e037b3f
--- /dev/null
+++ b/thirdparty/bullet/src/BulletInverseDynamics/premake4.lua
@@ -0,0 +1,12 @@
+ project "BulletInverseDynamics"
+
+ kind "StaticLib"
+ includedirs {
+ "..",
+ }
+ files {
+ "IDMath.cpp",
+ "MultiBodyTree.cpp",
+ "details/MultiBodyTreeInitCache.cpp",
+ "details/MultiBodyTreeImpl.cpp",
+ }
diff --git a/thirdparty/bullet/src/BulletSoftBody/CMakeLists.txt b/thirdparty/bullet/src/BulletSoftBody/CMakeLists.txt
new file mode 100644
index 0000000000..d43df1c67b
--- /dev/null
+++ b/thirdparty/bullet/src/BulletSoftBody/CMakeLists.txt
@@ -0,0 +1,69 @@
+
+INCLUDE_DIRECTORIES(
+${BULLET_PHYSICS_SOURCE_DIR}/src
+
+)
+
+#SUBDIRS( Solvers )
+
+SET(BulletSoftBody_SRCS
+ btSoftBody.cpp
+ btSoftBodyConcaveCollisionAlgorithm.cpp
+ btSoftBodyHelpers.cpp
+ btSoftBodyRigidBodyCollisionConfiguration.cpp
+ btSoftRigidCollisionAlgorithm.cpp
+ btSoftRigidDynamicsWorld.cpp
+ btSoftMultiBodyDynamicsWorld.cpp
+ btSoftSoftCollisionAlgorithm.cpp
+ btDefaultSoftBodySolver.cpp
+
+)
+
+SET(BulletSoftBody_HDRS
+ btSoftBody.h
+ btSoftBodyData.h
+ btSoftBodyConcaveCollisionAlgorithm.h
+ btSoftBodyHelpers.h
+ btSoftBodyRigidBodyCollisionConfiguration.h
+ btSoftRigidCollisionAlgorithm.h
+ btSoftRigidDynamicsWorld.h
+ btSoftMultiBodyDynamicsWorld.h
+ btSoftSoftCollisionAlgorithm.h
+ btSparseSDF.h
+
+ btSoftBodySolvers.h
+ btDefaultSoftBodySolver.h
+
+ btSoftBodySolverVertexBuffer.h
+)
+
+
+
+ADD_LIBRARY(BulletSoftBody ${BulletSoftBody_SRCS} ${BulletSoftBody_HDRS})
+SET_TARGET_PROPERTIES(BulletSoftBody PROPERTIES VERSION ${BULLET_VERSION})
+SET_TARGET_PROPERTIES(BulletSoftBody PROPERTIES SOVERSION ${BULLET_VERSION})
+IF (BUILD_SHARED_LIBS)
+ TARGET_LINK_LIBRARIES(BulletSoftBody BulletDynamics)
+ENDIF (BUILD_SHARED_LIBS)
+
+IF (INSTALL_LIBS)
+ IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
+ IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
+ IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+ INSTALL(TARGETS BulletSoftBody DESTINATION .)
+ ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+ INSTALL(TARGETS BulletSoftBody RUNTIME DESTINATION bin
+ LIBRARY DESTINATION lib${LIB_SUFFIX}
+ ARCHIVE DESTINATION lib${LIB_SUFFIX})
+ INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.h" PATTERN
+".svn" EXCLUDE PATTERN "CMakeFiles" EXCLUDE)
+ ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+ ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
+
+ IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+ SET_TARGET_PROPERTIES(BulletSoftBody PROPERTIES FRAMEWORK true)
+ SET_TARGET_PROPERTIES(BulletSoftBody PROPERTIES PUBLIC_HEADER "${BulletSoftBody_HDRS}")
+ ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+ ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
+ENDIF (INSTALL_LIBS)
diff --git a/thirdparty/bullet/src/BulletSoftBody/btDefaultSoftBodySolver.cpp b/thirdparty/bullet/src/BulletSoftBody/btDefaultSoftBodySolver.cpp
new file mode 100644
index 0000000000..9c20403074
--- /dev/null
+++ b/thirdparty/bullet/src/BulletSoftBody/btDefaultSoftBodySolver.cpp
@@ -0,0 +1,151 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/CollisionShapes/btCollisionShape.h"
+
+#include "btDefaultSoftBodySolver.h"
+#include "BulletCollision/CollisionShapes/btCapsuleShape.h"
+#include "BulletSoftBody/btSoftBody.h"
+
+
+btDefaultSoftBodySolver::btDefaultSoftBodySolver()
+{
+ // Initial we will clearly need to update solver constants
+ // For now this is global for the cloths linked with this solver - we should probably make this body specific
+ // for performance in future once we understand more clearly when constants need to be updated
+ m_updateSolverConstants = true;
+}
+
+btDefaultSoftBodySolver::~btDefaultSoftBodySolver()
+{
+}
+
+// In this case the data is already in the soft bodies so there is no need for us to do anything
+void btDefaultSoftBodySolver::copyBackToSoftBodies(bool bMove)
+{
+
+}
+
+void btDefaultSoftBodySolver::optimize( btAlignedObjectArray< btSoftBody * > &softBodies , bool forceUpdate)
+{
+ m_softBodySet.copyFromArray( softBodies );
+}
+
+void btDefaultSoftBodySolver::updateSoftBodies( )
+{
+ for ( int i=0; i < m_softBodySet.size(); i++)
+ {
+ btSoftBody* psb=(btSoftBody*)m_softBodySet[i];
+ if (psb->isActive())
+ {
+ psb->integrateMotion();
+ }
+ }
+} // updateSoftBodies
+
+bool btDefaultSoftBodySolver::checkInitialized()
+{
+ return true;
+}
+
+void btDefaultSoftBodySolver::solveConstraints( float solverdt )
+{
+ // Solve constraints for non-solver softbodies
+ for(int i=0; i < m_softBodySet.size(); ++i)
+ {
+ btSoftBody* psb = static_cast<btSoftBody*>(m_softBodySet[i]);
+ if (psb->isActive())
+ {
+ psb->solveConstraints();
+ }
+ }
+} // btDefaultSoftBodySolver::solveConstraints
+
+
+void btDefaultSoftBodySolver::copySoftBodyToVertexBuffer( const btSoftBody *const softBody, btVertexBufferDescriptor *vertexBuffer )
+{
+ // Currently only support CPU output buffers
+ // TODO: check for DX11 buffers. Take all offsets into the same DX11 buffer
+ // and use them together on a single kernel call if possible by setting up a
+ // per-cloth target buffer array for the copy kernel.
+
+ if( vertexBuffer->getBufferType() == btVertexBufferDescriptor::CPU_BUFFER )
+ {
+ const btAlignedObjectArray<btSoftBody::Node> &clothVertices( softBody->m_nodes );
+ int numVertices = clothVertices.size();
+
+ const btCPUVertexBufferDescriptor *cpuVertexBuffer = static_cast< btCPUVertexBufferDescriptor* >(vertexBuffer);
+ float *basePointer = cpuVertexBuffer->getBasePointer();
+
+ if( vertexBuffer->hasVertexPositions() )
+ {
+ const int vertexOffset = cpuVertexBuffer->getVertexOffset();
+ const int vertexStride = cpuVertexBuffer->getVertexStride();
+ float *vertexPointer = basePointer + vertexOffset;
+
+ for( int vertexIndex = 0; vertexIndex < numVertices; ++vertexIndex )
+ {
+ btVector3 position = clothVertices[vertexIndex].m_x;
+ *(vertexPointer + 0) = (float)position.getX();
+ *(vertexPointer + 1) = (float)position.getY();
+ *(vertexPointer + 2) = (float)position.getZ();
+ vertexPointer += vertexStride;
+ }
+ }
+ if( vertexBuffer->hasNormals() )
+ {
+ const int normalOffset = cpuVertexBuffer->getNormalOffset();
+ const int normalStride = cpuVertexBuffer->getNormalStride();
+ float *normalPointer = basePointer + normalOffset;
+
+ for( int vertexIndex = 0; vertexIndex < numVertices; ++vertexIndex )
+ {
+ btVector3 normal = clothVertices[vertexIndex].m_n;
+ *(normalPointer + 0) = (float)normal.getX();
+ *(normalPointer + 1) = (float)normal.getY();
+ *(normalPointer + 2) = (float)normal.getZ();
+ normalPointer += normalStride;
+ }
+ }
+ }
+} // btDefaultSoftBodySolver::copySoftBodyToVertexBuffer
+
+void btDefaultSoftBodySolver::processCollision( btSoftBody* softBody, btSoftBody* otherSoftBody)
+{
+ softBody->defaultCollisionHandler( otherSoftBody);
+}
+
+// For the default solver just leave the soft body to do its collision processing
+void btDefaultSoftBodySolver::processCollision( btSoftBody *softBody, const btCollisionObjectWrapper* collisionObjectWrap )
+{
+ softBody->defaultCollisionHandler( collisionObjectWrap );
+} // btDefaultSoftBodySolver::processCollision
+
+
+void btDefaultSoftBodySolver::predictMotion( float timeStep )
+{
+ for ( int i=0; i < m_softBodySet.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodySet[i];
+
+ if (psb->isActive())
+ {
+ psb->predictMotion(timeStep);
+ }
+ }
+}
+
diff --git a/thirdparty/bullet/src/BulletSoftBody/btDefaultSoftBodySolver.h b/thirdparty/bullet/src/BulletSoftBody/btDefaultSoftBodySolver.h
new file mode 100644
index 0000000000..1c17ffcbb2
--- /dev/null
+++ b/thirdparty/bullet/src/BulletSoftBody/btDefaultSoftBodySolver.h
@@ -0,0 +1,63 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_SOFT_BODY_DEFAULT_SOLVER_H
+#define BT_SOFT_BODY_DEFAULT_SOLVER_H
+
+
+#include "BulletSoftBody/btSoftBodySolvers.h"
+#include "btSoftBodySolverVertexBuffer.h"
+struct btCollisionObjectWrapper;
+
+class btDefaultSoftBodySolver : public btSoftBodySolver
+{
+protected:
+ /** Variable to define whether we need to update solver constants on the next iteration */
+ bool m_updateSolverConstants;
+
+ btAlignedObjectArray< btSoftBody * > m_softBodySet;
+
+
+public:
+ btDefaultSoftBodySolver();
+
+ virtual ~btDefaultSoftBodySolver();
+
+ virtual SolverTypes getSolverType() const
+ {
+ return DEFAULT_SOLVER;
+ }
+
+ virtual bool checkInitialized();
+
+ virtual void updateSoftBodies( );
+
+ virtual void optimize( btAlignedObjectArray< btSoftBody * > &softBodies,bool forceUpdate=false );
+
+ virtual void copyBackToSoftBodies(bool bMove = true);
+
+ virtual void solveConstraints( float solverdt );
+
+ virtual void predictMotion( float solverdt );
+
+ virtual void copySoftBodyToVertexBuffer( const btSoftBody *const softBody, btVertexBufferDescriptor *vertexBuffer );
+
+ virtual void processCollision( btSoftBody *, const btCollisionObjectWrapper* );
+
+ virtual void processCollision( btSoftBody*, btSoftBody* );
+
+};
+
+#endif // #ifndef BT_ACCELERATED_SOFT_BODY_CPU_SOLVER_H
diff --git a/thirdparty/bullet/src/BulletSoftBody/btSoftBody.cpp b/thirdparty/bullet/src/BulletSoftBody/btSoftBody.cpp
new file mode 100644
index 0000000000..48efb0d8d4
--- /dev/null
+++ b/thirdparty/bullet/src/BulletSoftBody/btSoftBody.cpp
@@ -0,0 +1,3709 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+///btSoftBody implementation by Nathanael Presson
+
+#include "btSoftBodyInternals.h"
+#include "BulletSoftBody/btSoftBodySolvers.h"
+#include "btSoftBodyData.h"
+#include "LinearMath/btSerializer.h"
+#include "BulletDynamics/Featherstone/btMultiBodyLinkCollider.h"
+#include "BulletDynamics/Featherstone/btMultiBodyConstraint.h"
+
+
+//
+btSoftBody::btSoftBody(btSoftBodyWorldInfo* worldInfo,int node_count, const btVector3* x, const btScalar* m)
+:m_softBodySolver(0),m_worldInfo(worldInfo)
+{
+ /* Init */
+ initDefaults();
+
+ /* Default material */
+ Material* pm=appendMaterial();
+ pm->m_kLST = 1;
+ pm->m_kAST = 1;
+ pm->m_kVST = 1;
+ pm->m_flags = fMaterial::Default;
+
+ /* Nodes */
+ const btScalar margin=getCollisionShape()->getMargin();
+ m_nodes.resize(node_count);
+ for(int i=0,ni=node_count;i<ni;++i)
+ {
+ Node& n=m_nodes[i];
+ ZeroInitialize(n);
+ n.m_x = x?*x++:btVector3(0,0,0);
+ n.m_q = n.m_x;
+ n.m_im = m?*m++:1;
+ n.m_im = n.m_im>0?1/n.m_im:0;
+ n.m_leaf = m_ndbvt.insert(btDbvtVolume::FromCR(n.m_x,margin),&n);
+ n.m_material= pm;
+ }
+ updateBounds();
+
+}
+
+btSoftBody::btSoftBody(btSoftBodyWorldInfo* worldInfo)
+:m_worldInfo(worldInfo)
+{
+ initDefaults();
+}
+
+
+void btSoftBody::initDefaults()
+{
+ m_internalType = CO_SOFT_BODY;
+ m_cfg.aeromodel = eAeroModel::V_Point;
+ m_cfg.kVCF = 1;
+ m_cfg.kDG = 0;
+ m_cfg.kLF = 0;
+ m_cfg.kDP = 0;
+ m_cfg.kPR = 0;
+ m_cfg.kVC = 0;
+ m_cfg.kDF = (btScalar)0.2;
+ m_cfg.kMT = 0;
+ m_cfg.kCHR = (btScalar)1.0;
+ m_cfg.kKHR = (btScalar)0.1;
+ m_cfg.kSHR = (btScalar)1.0;
+ m_cfg.kAHR = (btScalar)0.7;
+ m_cfg.kSRHR_CL = (btScalar)0.1;
+ m_cfg.kSKHR_CL = (btScalar)1;
+ m_cfg.kSSHR_CL = (btScalar)0.5;
+ m_cfg.kSR_SPLT_CL = (btScalar)0.5;
+ m_cfg.kSK_SPLT_CL = (btScalar)0.5;
+ m_cfg.kSS_SPLT_CL = (btScalar)0.5;
+ m_cfg.maxvolume = (btScalar)1;
+ m_cfg.timescale = 1;
+ m_cfg.viterations = 0;
+ m_cfg.piterations = 1;
+ m_cfg.diterations = 0;
+ m_cfg.citerations = 4;
+ m_cfg.collisions = fCollision::Default;
+ m_pose.m_bvolume = false;
+ m_pose.m_bframe = false;
+ m_pose.m_volume = 0;
+ m_pose.m_com = btVector3(0,0,0);
+ m_pose.m_rot.setIdentity();
+ m_pose.m_scl.setIdentity();
+ m_tag = 0;
+ m_timeacc = 0;
+ m_bUpdateRtCst = true;
+ m_bounds[0] = btVector3(0,0,0);
+ m_bounds[1] = btVector3(0,0,0);
+ m_worldTransform.setIdentity();
+ setSolver(eSolverPresets::Positions);
+
+ /* Collision shape */
+ ///for now, create a collision shape internally
+ m_collisionShape = new btSoftBodyCollisionShape(this);
+ m_collisionShape->setMargin(0.25f);
+
+ m_initialWorldTransform.setIdentity();
+
+ m_windVelocity = btVector3(0,0,0);
+ m_restLengthScale = btScalar(1.0);
+}
+
+//
+btSoftBody::~btSoftBody()
+{
+ //for now, delete the internal shape
+ delete m_collisionShape;
+ int i;
+
+ releaseClusters();
+ for(i=0;i<m_materials.size();++i)
+ btAlignedFree(m_materials[i]);
+ for(i=0;i<m_joints.size();++i)
+ btAlignedFree(m_joints[i]);
+}
+
+//
+bool btSoftBody::checkLink(int node0,int node1) const
+{
+ return(checkLink(&m_nodes[node0],&m_nodes[node1]));
+}
+
+//
+bool btSoftBody::checkLink(const Node* node0,const Node* node1) const
+{
+ const Node* n[]={node0,node1};
+ for(int i=0,ni=m_links.size();i<ni;++i)
+ {
+ const Link& l=m_links[i];
+ if( (l.m_n[0]==n[0]&&l.m_n[1]==n[1])||
+ (l.m_n[0]==n[1]&&l.m_n[1]==n[0]))
+ {
+ return(true);
+ }
+ }
+ return(false);
+}
+
+//
+bool btSoftBody::checkFace(int node0,int node1,int node2) const
+{
+ const Node* n[]={ &m_nodes[node0],
+ &m_nodes[node1],
+ &m_nodes[node2]};
+ for(int i=0,ni=m_faces.size();i<ni;++i)
+ {
+ const Face& f=m_faces[i];
+ int c=0;
+ for(int j=0;j<3;++j)
+ {
+ if( (f.m_n[j]==n[0])||
+ (f.m_n[j]==n[1])||
+ (f.m_n[j]==n[2])) c|=1<<j; else break;
+ }
+ if(c==7) return(true);
+ }
+ return(false);
+}
+
+//
+btSoftBody::Material* btSoftBody::appendMaterial()
+{
+ Material* pm=new(btAlignedAlloc(sizeof(Material),16)) Material();
+ if(m_materials.size()>0)
+ *pm=*m_materials[0];
+ else
+ ZeroInitialize(*pm);
+ m_materials.push_back(pm);
+ return(pm);
+}
+
+//
+void btSoftBody::appendNote( const char* text,
+ const btVector3& o,
+ const btVector4& c,
+ Node* n0,
+ Node* n1,
+ Node* n2,
+ Node* n3)
+{
+ Note n;
+ ZeroInitialize(n);
+ n.m_rank = 0;
+ n.m_text = text;
+ n.m_offset = o;
+ n.m_coords[0] = c.x();
+ n.m_coords[1] = c.y();
+ n.m_coords[2] = c.z();
+ n.m_coords[3] = c.w();
+ n.m_nodes[0] = n0;n.m_rank+=n0?1:0;
+ n.m_nodes[1] = n1;n.m_rank+=n1?1:0;
+ n.m_nodes[2] = n2;n.m_rank+=n2?1:0;
+ n.m_nodes[3] = n3;n.m_rank+=n3?1:0;
+ m_notes.push_back(n);
+}
+
+//
+void btSoftBody::appendNote( const char* text,
+ const btVector3& o,
+ Node* feature)
+{
+ appendNote(text,o,btVector4(1,0,0,0),feature);
+}
+
+//
+void btSoftBody::appendNote( const char* text,
+ const btVector3& o,
+ Link* feature)
+{
+ static const btScalar w=1/(btScalar)2;
+ appendNote(text,o,btVector4(w,w,0,0), feature->m_n[0],
+ feature->m_n[1]);
+}
+
+//
+void btSoftBody::appendNote( const char* text,
+ const btVector3& o,
+ Face* feature)
+{
+ static const btScalar w=1/(btScalar)3;
+ appendNote(text,o,btVector4(w,w,w,0), feature->m_n[0],
+ feature->m_n[1],
+ feature->m_n[2]);
+}
+
+//
+void btSoftBody::appendNode( const btVector3& x,btScalar m)
+{
+ if(m_nodes.capacity()==m_nodes.size())
+ {
+ pointersToIndices();
+ m_nodes.reserve(m_nodes.size()*2+1);
+ indicesToPointers();
+ }
+ const btScalar margin=getCollisionShape()->getMargin();
+ m_nodes.push_back(Node());
+ Node& n=m_nodes[m_nodes.size()-1];
+ ZeroInitialize(n);
+ n.m_x = x;
+ n.m_q = n.m_x;
+ n.m_im = m>0?1/m:0;
+ n.m_material = m_materials[0];
+ n.m_leaf = m_ndbvt.insert(btDbvtVolume::FromCR(n.m_x,margin),&n);
+}
+
+//
+void btSoftBody::appendLink(int model,Material* mat)
+{
+ Link l;
+ if(model>=0)
+ l=m_links[model];
+ else
+ { ZeroInitialize(l);l.m_material=mat?mat:m_materials[0]; }
+ m_links.push_back(l);
+}
+
+//
+void btSoftBody::appendLink( int node0,
+ int node1,
+ Material* mat,
+ bool bcheckexist)
+{
+ appendLink(&m_nodes[node0],&m_nodes[node1],mat,bcheckexist);
+}
+
+//
+void btSoftBody::appendLink( Node* node0,
+ Node* node1,
+ Material* mat,
+ bool bcheckexist)
+{
+ if((!bcheckexist)||(!checkLink(node0,node1)))
+ {
+ appendLink(-1,mat);
+ Link& l=m_links[m_links.size()-1];
+ l.m_n[0] = node0;
+ l.m_n[1] = node1;
+ l.m_rl = (l.m_n[0]->m_x-l.m_n[1]->m_x).length();
+ m_bUpdateRtCst=true;
+ }
+}
+
+//
+void btSoftBody::appendFace(int model,Material* mat)
+{
+ Face f;
+ if(model>=0)
+ { f=m_faces[model]; }
+ else
+ { ZeroInitialize(f);f.m_material=mat?mat:m_materials[0]; }
+ m_faces.push_back(f);
+}
+
+//
+void btSoftBody::appendFace(int node0,int node1,int node2,Material* mat)
+{
+ if (node0==node1)
+ return;
+ if (node1==node2)
+ return;
+ if (node2==node0)
+ return;
+
+ appendFace(-1,mat);
+ Face& f=m_faces[m_faces.size()-1];
+ btAssert(node0!=node1);
+ btAssert(node1!=node2);
+ btAssert(node2!=node0);
+ f.m_n[0] = &m_nodes[node0];
+ f.m_n[1] = &m_nodes[node1];
+ f.m_n[2] = &m_nodes[node2];
+ f.m_ra = AreaOf( f.m_n[0]->m_x,
+ f.m_n[1]->m_x,
+ f.m_n[2]->m_x);
+ m_bUpdateRtCst=true;
+}
+
+//
+void btSoftBody::appendTetra(int model,Material* mat)
+{
+Tetra t;
+if(model>=0)
+ t=m_tetras[model];
+ else
+ { ZeroInitialize(t);t.m_material=mat?mat:m_materials[0]; }
+m_tetras.push_back(t);
+}
+
+//
+void btSoftBody::appendTetra(int node0,
+ int node1,
+ int node2,
+ int node3,
+ Material* mat)
+{
+ appendTetra(-1,mat);
+ Tetra& t=m_tetras[m_tetras.size()-1];
+ t.m_n[0] = &m_nodes[node0];
+ t.m_n[1] = &m_nodes[node1];
+ t.m_n[2] = &m_nodes[node2];
+ t.m_n[3] = &m_nodes[node3];
+ t.m_rv = VolumeOf(t.m_n[0]->m_x,t.m_n[1]->m_x,t.m_n[2]->m_x,t.m_n[3]->m_x);
+ m_bUpdateRtCst=true;
+}
+
+//
+
+void btSoftBody::appendAnchor(int node,btRigidBody* body, bool disableCollisionBetweenLinkedBodies,btScalar influence)
+{
+ btVector3 local = body->getWorldTransform().inverse()*m_nodes[node].m_x;
+ appendAnchor(node,body,local,disableCollisionBetweenLinkedBodies,influence);
+}
+
+//
+void btSoftBody::appendAnchor(int node,btRigidBody* body, const btVector3& localPivot,bool disableCollisionBetweenLinkedBodies,btScalar influence)
+{
+ if (disableCollisionBetweenLinkedBodies)
+ {
+ if (m_collisionDisabledObjects.findLinearSearch(body)==m_collisionDisabledObjects.size())
+ {
+ m_collisionDisabledObjects.push_back(body);
+ }
+ }
+
+ Anchor a;
+ a.m_node = &m_nodes[node];
+ a.m_body = body;
+ a.m_local = localPivot;
+ a.m_node->m_battach = 1;
+ a.m_influence = influence;
+ m_anchors.push_back(a);
+}
+
+//
+void btSoftBody::appendLinearJoint(const LJoint::Specs& specs,Cluster* body0,Body body1)
+{
+ LJoint* pj = new(btAlignedAlloc(sizeof(LJoint),16)) LJoint();
+ pj->m_bodies[0] = body0;
+ pj->m_bodies[1] = body1;
+ pj->m_refs[0] = pj->m_bodies[0].xform().inverse()*specs.position;
+ pj->m_refs[1] = pj->m_bodies[1].xform().inverse()*specs.position;
+ pj->m_cfm = specs.cfm;
+ pj->m_erp = specs.erp;
+ pj->m_split = specs.split;
+ m_joints.push_back(pj);
+}
+
+//
+void btSoftBody::appendLinearJoint(const LJoint::Specs& specs,Body body)
+{
+ appendLinearJoint(specs,m_clusters[0],body);
+}
+
+//
+void btSoftBody::appendLinearJoint(const LJoint::Specs& specs,btSoftBody* body)
+{
+ appendLinearJoint(specs,m_clusters[0],body->m_clusters[0]);
+}
+
+//
+void btSoftBody::appendAngularJoint(const AJoint::Specs& specs,Cluster* body0,Body body1)
+{
+ AJoint* pj = new(btAlignedAlloc(sizeof(AJoint),16)) AJoint();
+ pj->m_bodies[0] = body0;
+ pj->m_bodies[1] = body1;
+ pj->m_refs[0] = pj->m_bodies[0].xform().inverse().getBasis()*specs.axis;
+ pj->m_refs[1] = pj->m_bodies[1].xform().inverse().getBasis()*specs.axis;
+ pj->m_cfm = specs.cfm;
+ pj->m_erp = specs.erp;
+ pj->m_split = specs.split;
+ pj->m_icontrol = specs.icontrol;
+ m_joints.push_back(pj);
+}
+
+//
+void btSoftBody::appendAngularJoint(const AJoint::Specs& specs,Body body)
+{
+ appendAngularJoint(specs,m_clusters[0],body);
+}
+
+//
+void btSoftBody::appendAngularJoint(const AJoint::Specs& specs,btSoftBody* body)
+{
+ appendAngularJoint(specs,m_clusters[0],body->m_clusters[0]);
+}
+
+//
+void btSoftBody::addForce(const btVector3& force)
+{
+ for(int i=0,ni=m_nodes.size();i<ni;++i) addForce(force,i);
+}
+
+//
+void btSoftBody::addForce(const btVector3& force,int node)
+{
+ Node& n=m_nodes[node];
+ if(n.m_im>0)
+ {
+ n.m_f += force;
+ }
+}
+
+void btSoftBody::addAeroForceToNode(const btVector3& windVelocity,int nodeIndex)
+{
+ btAssert(nodeIndex >= 0 && nodeIndex < m_nodes.size());
+
+ const btScalar dt = m_sst.sdt;
+ const btScalar kLF = m_cfg.kLF;
+ const btScalar kDG = m_cfg.kDG;
+ //const btScalar kPR = m_cfg.kPR;
+ //const btScalar kVC = m_cfg.kVC;
+ const bool as_lift = kLF>0;
+ const bool as_drag = kDG>0;
+ const bool as_aero = as_lift || as_drag;
+ const bool as_vaero = as_aero && (m_cfg.aeromodel < btSoftBody::eAeroModel::F_TwoSided);
+
+ Node& n = m_nodes[nodeIndex];
+
+ if( n.m_im>0 )
+ {
+ btSoftBody::sMedium medium;
+
+ EvaluateMedium(m_worldInfo, n.m_x, medium);
+ medium.m_velocity = windVelocity;
+ medium.m_density = m_worldInfo->air_density;
+
+ /* Aerodynamics */
+ if(as_vaero)
+ {
+ const btVector3 rel_v = n.m_v - medium.m_velocity;
+ const btScalar rel_v_len = rel_v.length();
+ const btScalar rel_v2 = rel_v.length2();
+
+ if(rel_v2>SIMD_EPSILON)
+ {
+ const btVector3 rel_v_nrm = rel_v.normalized();
+ btVector3 nrm = n.m_n;
+
+ if (m_cfg.aeromodel == btSoftBody::eAeroModel::V_TwoSidedLiftDrag)
+ {
+ nrm *= (btScalar)( (btDot(nrm,rel_v) < 0) ? -1 : +1);
+ btVector3 fDrag(0, 0, 0);
+ btVector3 fLift(0, 0, 0);
+
+ btScalar n_dot_v = nrm.dot(rel_v_nrm);
+ btScalar tri_area = 0.5f * n.m_area;
+
+ 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
+ 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));
+
+ // Check if the velocity change resulted by aero drag force exceeds the current velocity of the node.
+ btVector3 del_v_by_fDrag = fDrag*n.m_im*m_sst.sdt;
+ btScalar del_v_by_fDrag_len2 = del_v_by_fDrag.length2();
+ btScalar v_len2 = n.m_v.length2();
+
+ if (del_v_by_fDrag_len2 >= v_len2 && del_v_by_fDrag_len2 > 0)
+ {
+ btScalar del_v_by_fDrag_len = del_v_by_fDrag.length();
+ btScalar v_len = n.m_v.length();
+ fDrag *= btScalar(0.8)*(v_len / del_v_by_fDrag_len);
+ }
+
+ n.m_f += fDrag;
+ n.m_f += fLift;
+ }
+ else if (m_cfg.aeromodel == btSoftBody::eAeroModel::V_Point || m_cfg.aeromodel == btSoftBody::eAeroModel::V_OneSided || m_cfg.aeromodel == btSoftBody::eAeroModel::V_TwoSided)
+ {
+ if (m_cfg.aeromodel == btSoftBody::eAeroModel::V_TwoSided)
+ nrm *= (btScalar)( (btDot(nrm,rel_v) < 0) ? -1 : +1);
+
+ const btScalar dvn = btDot(rel_v,nrm);
+ /* Compute forces */
+ if(dvn>0)
+ {
+ btVector3 force(0,0,0);
+ const btScalar c0 = n.m_area * dvn * rel_v2/2;
+ const btScalar c1 = c0 * medium.m_density;
+ force += nrm*(-c1*kLF);
+ force += rel_v.normalized() * (-c1 * kDG);
+ ApplyClampedForce(n, force, dt);
+ }
+ }
+ }
+ }
+ }
+}
+
+void btSoftBody::addAeroForceToFace(const btVector3& windVelocity,int faceIndex)
+{
+ const btScalar dt = m_sst.sdt;
+ const btScalar kLF = m_cfg.kLF;
+ const btScalar kDG = m_cfg.kDG;
+// const btScalar kPR = m_cfg.kPR;
+// const btScalar kVC = m_cfg.kVC;
+ const bool as_lift = kLF>0;
+ const bool as_drag = kDG>0;
+ const bool as_aero = as_lift || as_drag;
+ const bool as_faero = as_aero && (m_cfg.aeromodel >= btSoftBody::eAeroModel::F_TwoSided);
+
+ if(as_faero)
+ {
+ btSoftBody::Face& f=m_faces[faceIndex];
+
+ btSoftBody::sMedium medium;
+
+ const btVector3 v=(f.m_n[0]->m_v+f.m_n[1]->m_v+f.m_n[2]->m_v)/3;
+ const btVector3 x=(f.m_n[0]->m_x+f.m_n[1]->m_x+f.m_n[2]->m_x)/3;
+ EvaluateMedium(m_worldInfo,x,medium);
+ medium.m_velocity = windVelocity;
+ medium.m_density = m_worldInfo->air_density;
+ const btVector3 rel_v=v-medium.m_velocity;
+ const btScalar rel_v_len = rel_v.length();
+ const btScalar rel_v2=rel_v.length2();
+
+ if(rel_v2>SIMD_EPSILON)
+ {
+ const btVector3 rel_v_nrm = rel_v.normalized();
+ btVector3 nrm = f.m_normal;
+
+ if (m_cfg.aeromodel == btSoftBody::eAeroModel::F_TwoSidedLiftDrag)
+ {
+ nrm *= (btScalar)( (btDot(nrm,rel_v) < 0) ? -1 : +1);
+
+ btVector3 fDrag(0, 0, 0);
+ btVector3 fLift(0, 0, 0);
+
+ btScalar n_dot_v = nrm.dot(rel_v_nrm);
+ btScalar tri_area = 0.5f * f.m_ra;
+
+ 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
+ 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));
+
+ fDrag /= 3;
+ fLift /= 3;
+
+ for(int j=0;j<3;++j)
+ {
+ if (f.m_n[j]->m_im>0)
+ {
+ // Check if the velocity change resulted by aero drag force exceeds the current velocity of the node.
+ btVector3 del_v_by_fDrag = fDrag*f.m_n[j]->m_im*m_sst.sdt;
+ btScalar del_v_by_fDrag_len2 = del_v_by_fDrag.length2();
+ btScalar v_len2 = f.m_n[j]->m_v.length2();
+
+ if (del_v_by_fDrag_len2 >= v_len2 && del_v_by_fDrag_len2 > 0)
+ {
+ btScalar del_v_by_fDrag_len = del_v_by_fDrag.length();
+ btScalar v_len = f.m_n[j]->m_v.length();
+ fDrag *= btScalar(0.8)*(v_len / del_v_by_fDrag_len);
+ }
+
+ f.m_n[j]->m_f += fDrag;
+ f.m_n[j]->m_f += fLift;
+ }
+ }
+ }
+ else if (m_cfg.aeromodel == btSoftBody::eAeroModel::F_OneSided || m_cfg.aeromodel == btSoftBody::eAeroModel::F_TwoSided)
+ {
+ if (m_cfg.aeromodel == btSoftBody::eAeroModel::F_TwoSided)
+ nrm *= (btScalar)( (btDot(nrm,rel_v) < 0) ? -1 : +1);
+
+ const btScalar dvn=btDot(rel_v,nrm);
+ /* Compute forces */
+ if(dvn>0)
+ {
+ btVector3 force(0,0,0);
+ const btScalar c0 = f.m_ra*dvn*rel_v2;
+ const btScalar c1 = c0*medium.m_density;
+ force += nrm*(-c1*kLF);
+ force += rel_v.normalized()*(-c1*kDG);
+ force /= 3;
+ for(int j=0;j<3;++j) ApplyClampedForce(*f.m_n[j],force,dt);
+ }
+ }
+ }
+ }
+
+}
+
+//
+void btSoftBody::addVelocity(const btVector3& velocity)
+{
+ for(int i=0,ni=m_nodes.size();i<ni;++i) addVelocity(velocity,i);
+}
+
+/* Set velocity for the entire body */
+void btSoftBody::setVelocity( const btVector3& velocity)
+{
+ for(int i=0,ni=m_nodes.size();i<ni;++i)
+ {
+ Node& n=m_nodes[i];
+ if(n.m_im>0)
+ {
+ n.m_v = velocity;
+ }
+ }
+}
+
+
+//
+void btSoftBody::addVelocity(const btVector3& velocity,int node)
+{
+ Node& n=m_nodes[node];
+ if(n.m_im>0)
+ {
+ n.m_v += velocity;
+ }
+}
+
+//
+void btSoftBody::setMass(int node,btScalar mass)
+{
+ m_nodes[node].m_im=mass>0?1/mass:0;
+ m_bUpdateRtCst=true;
+}
+
+//
+btScalar btSoftBody::getMass(int node) const
+{
+ return(m_nodes[node].m_im>0?1/m_nodes[node].m_im:0);
+}
+
+//
+btScalar btSoftBody::getTotalMass() const
+{
+ btScalar mass=0;
+ for(int i=0;i<m_nodes.size();++i)
+ {
+ mass+=getMass(i);
+ }
+ return(mass);
+}
+
+//
+void btSoftBody::setTotalMass(btScalar mass,bool fromfaces)
+{
+ int i;
+
+ if(fromfaces)
+ {
+
+ for(i=0;i<m_nodes.size();++i)
+ {
+ m_nodes[i].m_im=0;
+ }
+ for(i=0;i<m_faces.size();++i)
+ {
+ const Face& f=m_faces[i];
+ const btScalar twicearea=AreaOf( f.m_n[0]->m_x,
+ f.m_n[1]->m_x,
+ f.m_n[2]->m_x);
+ for(int j=0;j<3;++j)
+ {
+ f.m_n[j]->m_im+=twicearea;
+ }
+ }
+ for( i=0;i<m_nodes.size();++i)
+ {
+ m_nodes[i].m_im=1/m_nodes[i].m_im;
+ }
+ }
+ const btScalar tm=getTotalMass();
+ const btScalar itm=1/tm;
+ for( i=0;i<m_nodes.size();++i)
+ {
+ m_nodes[i].m_im/=itm*mass;
+ }
+ m_bUpdateRtCst=true;
+}
+
+//
+void btSoftBody::setTotalDensity(btScalar density)
+{
+ setTotalMass(getVolume()*density,true);
+}
+
+//
+void btSoftBody::setVolumeMass(btScalar mass)
+{
+btAlignedObjectArray<btScalar> ranks;
+ranks.resize(m_nodes.size(),0);
+int i;
+
+for(i=0;i<m_nodes.size();++i)
+ {
+ m_nodes[i].m_im=0;
+ }
+for(i=0;i<m_tetras.size();++i)
+ {
+ const Tetra& t=m_tetras[i];
+ for(int j=0;j<4;++j)
+ {
+ t.m_n[j]->m_im+=btFabs(t.m_rv);
+ ranks[int(t.m_n[j]-&m_nodes[0])]+=1;
+ }
+ }
+for( i=0;i<m_nodes.size();++i)
+ {
+ if(m_nodes[i].m_im>0)
+ {
+ m_nodes[i].m_im=ranks[i]/m_nodes[i].m_im;
+ }
+ }
+setTotalMass(mass,false);
+}
+
+//
+void btSoftBody::setVolumeDensity(btScalar density)
+{
+btScalar volume=0;
+for(int i=0;i<m_tetras.size();++i)
+ {
+ const Tetra& t=m_tetras[i];
+ for(int j=0;j<4;++j)
+ {
+ volume+=btFabs(t.m_rv);
+ }
+ }
+setVolumeMass(volume*density/6);
+}
+
+//
+void btSoftBody::transform(const btTransform& trs)
+{
+ const btScalar margin=getCollisionShape()->getMargin();
+ ATTRIBUTE_ALIGNED16(btDbvtVolume) vol;
+
+ for(int i=0,ni=m_nodes.size();i<ni;++i)
+ {
+ Node& n=m_nodes[i];
+ n.m_x=trs*n.m_x;
+ n.m_q=trs*n.m_q;
+ n.m_n=trs.getBasis()*n.m_n;
+ vol = btDbvtVolume::FromCR(n.m_x,margin);
+
+ m_ndbvt.update(n.m_leaf,vol);
+ }
+ updateNormals();
+ updateBounds();
+ updateConstants();
+ m_initialWorldTransform = trs;
+}
+
+//
+void btSoftBody::translate(const btVector3& trs)
+{
+ btTransform t;
+ t.setIdentity();
+ t.setOrigin(trs);
+ transform(t);
+}
+
+//
+void btSoftBody::rotate( const btQuaternion& rot)
+{
+ btTransform t;
+ t.setIdentity();
+ t.setRotation(rot);
+ transform(t);
+}
+
+//
+void btSoftBody::scale(const btVector3& scl)
+{
+
+ const btScalar margin=getCollisionShape()->getMargin();
+ ATTRIBUTE_ALIGNED16(btDbvtVolume) vol;
+
+ for(int i=0,ni=m_nodes.size();i<ni;++i)
+ {
+ Node& n=m_nodes[i];
+ n.m_x*=scl;
+ n.m_q*=scl;
+ vol = btDbvtVolume::FromCR(n.m_x,margin);
+ m_ndbvt.update(n.m_leaf,vol);
+ }
+ updateNormals();
+ updateBounds();
+ updateConstants();
+}
+
+//
+btScalar btSoftBody::getRestLengthScale()
+{
+ return m_restLengthScale;
+}
+
+//
+void btSoftBody::setRestLengthScale(btScalar restLengthScale)
+{
+ for(int i=0, ni=m_links.size(); i<ni; ++i)
+ {
+ Link& l=m_links[i];
+ l.m_rl = l.m_rl / m_restLengthScale * restLengthScale;
+ l.m_c1 = l.m_rl*l.m_rl;
+ }
+ m_restLengthScale = restLengthScale;
+
+ if (getActivationState() == ISLAND_SLEEPING)
+ activate();
+}
+
+//
+void btSoftBody::setPose(bool bvolume,bool bframe)
+{
+ m_pose.m_bvolume = bvolume;
+ m_pose.m_bframe = bframe;
+ int i,ni;
+
+ /* Weights */
+ const btScalar omass=getTotalMass();
+ const btScalar kmass=omass*m_nodes.size()*1000;
+ btScalar tmass=omass;
+ m_pose.m_wgh.resize(m_nodes.size());
+ for(i=0,ni=m_nodes.size();i<ni;++i)
+ {
+ if(m_nodes[i].m_im<=0) tmass+=kmass;
+ }
+ for( i=0,ni=m_nodes.size();i<ni;++i)
+ {
+ Node& n=m_nodes[i];
+ m_pose.m_wgh[i]= n.m_im>0 ?
+ 1/(m_nodes[i].m_im*tmass) :
+ kmass/tmass;
+ }
+ /* Pos */
+ const btVector3 com=evaluateCom();
+ m_pose.m_pos.resize(m_nodes.size());
+ for( i=0,ni=m_nodes.size();i<ni;++i)
+ {
+ m_pose.m_pos[i]=m_nodes[i].m_x-com;
+ }
+ m_pose.m_volume = bvolume?getVolume():0;
+ m_pose.m_com = com;
+ m_pose.m_rot.setIdentity();
+ m_pose.m_scl.setIdentity();
+ /* Aqq */
+ m_pose.m_aqq[0] =
+ m_pose.m_aqq[1] =
+ m_pose.m_aqq[2] = btVector3(0,0,0);
+ for( i=0,ni=m_nodes.size();i<ni;++i)
+ {
+ const btVector3& q=m_pose.m_pos[i];
+ const btVector3 mq=m_pose.m_wgh[i]*q;
+ m_pose.m_aqq[0]+=mq.x()*q;
+ m_pose.m_aqq[1]+=mq.y()*q;
+ m_pose.m_aqq[2]+=mq.z()*q;
+ }
+ m_pose.m_aqq=m_pose.m_aqq.inverse();
+
+ updateConstants();
+}
+
+void btSoftBody::resetLinkRestLengths()
+{
+ for(int i=0, ni=m_links.size();i<ni;++i)
+ {
+ Link& l = m_links[i];
+ l.m_rl = (l.m_n[0]->m_x-l.m_n[1]->m_x).length();
+ l.m_c1 = l.m_rl*l.m_rl;
+ }
+}
+
+//
+btScalar btSoftBody::getVolume() const
+{
+ btScalar vol=0;
+ if(m_nodes.size()>0)
+ {
+ int i,ni;
+
+ const btVector3 org=m_nodes[0].m_x;
+ for(i=0,ni=m_faces.size();i<ni;++i)
+ {
+ const Face& f=m_faces[i];
+ vol+=btDot(f.m_n[0]->m_x-org,btCross(f.m_n[1]->m_x-org,f.m_n[2]->m_x-org));
+ }
+ vol/=(btScalar)6;
+ }
+ return(vol);
+}
+
+//
+int btSoftBody::clusterCount() const
+{
+ return(m_clusters.size());
+}
+
+//
+btVector3 btSoftBody::clusterCom(const Cluster* cluster)
+{
+ btVector3 com(0,0,0);
+ for(int i=0,ni=cluster->m_nodes.size();i<ni;++i)
+ {
+ com+=cluster->m_nodes[i]->m_x*cluster->m_masses[i];
+ }
+ return(com*cluster->m_imass);
+}
+
+//
+btVector3 btSoftBody::clusterCom(int cluster) const
+{
+ return(clusterCom(m_clusters[cluster]));
+}
+
+//
+btVector3 btSoftBody::clusterVelocity(const Cluster* cluster,const btVector3& rpos)
+{
+ return(cluster->m_lv+btCross(cluster->m_av,rpos));
+}
+
+//
+void btSoftBody::clusterVImpulse(Cluster* cluster,const btVector3& rpos,const btVector3& impulse)
+{
+ const btVector3 li=cluster->m_imass*impulse;
+ const btVector3 ai=cluster->m_invwi*btCross(rpos,impulse);
+ cluster->m_vimpulses[0]+=li;cluster->m_lv+=li;
+ cluster->m_vimpulses[1]+=ai;cluster->m_av+=ai;
+ cluster->m_nvimpulses++;
+}
+
+//
+void btSoftBody::clusterDImpulse(Cluster* cluster,const btVector3& rpos,const btVector3& impulse)
+{
+ const btVector3 li=cluster->m_imass*impulse;
+ const btVector3 ai=cluster->m_invwi*btCross(rpos,impulse);
+ cluster->m_dimpulses[0]+=li;
+ cluster->m_dimpulses[1]+=ai;
+ cluster->m_ndimpulses++;
+}
+
+//
+void btSoftBody::clusterImpulse(Cluster* cluster,const btVector3& rpos,const Impulse& impulse)
+{
+ if(impulse.m_asVelocity) clusterVImpulse(cluster,rpos,impulse.m_velocity);
+ if(impulse.m_asDrift) clusterDImpulse(cluster,rpos,impulse.m_drift);
+}
+
+//
+void btSoftBody::clusterVAImpulse(Cluster* cluster,const btVector3& impulse)
+{
+ const btVector3 ai=cluster->m_invwi*impulse;
+ cluster->m_vimpulses[1]+=ai;cluster->m_av+=ai;
+ cluster->m_nvimpulses++;
+}
+
+//
+void btSoftBody::clusterDAImpulse(Cluster* cluster,const btVector3& impulse)
+{
+ const btVector3 ai=cluster->m_invwi*impulse;
+ cluster->m_dimpulses[1]+=ai;
+ cluster->m_ndimpulses++;
+}
+
+//
+void btSoftBody::clusterAImpulse(Cluster* cluster,const Impulse& impulse)
+{
+ if(impulse.m_asVelocity) clusterVAImpulse(cluster,impulse.m_velocity);
+ if(impulse.m_asDrift) clusterDAImpulse(cluster,impulse.m_drift);
+}
+
+//
+void btSoftBody::clusterDCImpulse(Cluster* cluster,const btVector3& impulse)
+{
+ cluster->m_dimpulses[0]+=impulse*cluster->m_imass;
+ cluster->m_ndimpulses++;
+}
+
+struct NodeLinks
+{
+ btAlignedObjectArray<int> m_links;
+};
+
+
+
+//
+int btSoftBody::generateBendingConstraints(int distance,Material* mat)
+{
+ int i,j;
+
+ if(distance>1)
+ {
+ /* Build graph */
+ const int n=m_nodes.size();
+ const unsigned inf=(~(unsigned)0)>>1;
+ unsigned* adj=new unsigned[n*n];
+
+
+#define IDX(_x_,_y_) ((_y_)*n+(_x_))
+ for(j=0;j<n;++j)
+ {
+ for(i=0;i<n;++i)
+ {
+ if(i!=j)
+ {
+ adj[IDX(i,j)]=adj[IDX(j,i)]=inf;
+ }
+ else
+ {
+ adj[IDX(i,j)]=adj[IDX(j,i)]=0;
+ }
+ }
+ }
+ for( i=0;i<m_links.size();++i)
+ {
+ const int ia=(int)(m_links[i].m_n[0]-&m_nodes[0]);
+ const int ib=(int)(m_links[i].m_n[1]-&m_nodes[0]);
+ adj[IDX(ia,ib)]=1;
+ adj[IDX(ib,ia)]=1;
+ }
+
+
+ //special optimized case for distance == 2
+ if (distance == 2)
+ {
+
+ btAlignedObjectArray<NodeLinks> nodeLinks;
+
+
+ /* Build node links */
+ nodeLinks.resize(m_nodes.size());
+
+ for( i=0;i<m_links.size();++i)
+ {
+ const int ia=(int)(m_links[i].m_n[0]-&m_nodes[0]);
+ const int ib=(int)(m_links[i].m_n[1]-&m_nodes[0]);
+ if (nodeLinks[ia].m_links.findLinearSearch(ib)==nodeLinks[ia].m_links.size())
+ nodeLinks[ia].m_links.push_back(ib);
+
+ if (nodeLinks[ib].m_links.findLinearSearch(ia)==nodeLinks[ib].m_links.size())
+ nodeLinks[ib].m_links.push_back(ia);
+ }
+ for (int ii=0;ii<nodeLinks.size();ii++)
+ {
+ int i=ii;
+
+ for (int jj=0;jj<nodeLinks[ii].m_links.size();jj++)
+ {
+ int k = nodeLinks[ii].m_links[jj];
+ for (int kk=0;kk<nodeLinks[k].m_links.size();kk++)
+ {
+ int j = nodeLinks[k].m_links[kk];
+ if (i!=j)
+ {
+ const unsigned sum=adj[IDX(i,k)]+adj[IDX(k,j)];
+ btAssert(sum==2);
+ if(adj[IDX(i,j)]>sum)
+ {
+ adj[IDX(i,j)]=adj[IDX(j,i)]=sum;
+ }
+ }
+
+ }
+ }
+ }
+ } else
+ {
+ ///generic Floyd's algorithm
+ for(int k=0;k<n;++k)
+ {
+ for(j=0;j<n;++j)
+ {
+ for(i=j+1;i<n;++i)
+ {
+ const unsigned sum=adj[IDX(i,k)]+adj[IDX(k,j)];
+ if(adj[IDX(i,j)]>sum)
+ {
+ adj[IDX(i,j)]=adj[IDX(j,i)]=sum;
+ }
+ }
+ }
+ }
+ }
+
+
+ /* Build links */
+ int nlinks=0;
+ for(j=0;j<n;++j)
+ {
+ for(i=j+1;i<n;++i)
+ {
+ if(adj[IDX(i,j)]==(unsigned)distance)
+ {
+ appendLink(i,j,mat);
+ m_links[m_links.size()-1].m_bbending=1;
+ ++nlinks;
+ }
+ }
+ }
+ delete[] adj;
+ return(nlinks);
+ }
+ return(0);
+}
+
+//
+void btSoftBody::randomizeConstraints()
+{
+ unsigned long seed=243703;
+#define NEXTRAND (seed=(1664525L*seed+1013904223L)&0xffffffff)
+ int i,ni;
+
+ for(i=0,ni=m_links.size();i<ni;++i)
+ {
+ btSwap(m_links[i],m_links[NEXTRAND%ni]);
+ }
+ for(i=0,ni=m_faces.size();i<ni;++i)
+ {
+ btSwap(m_faces[i],m_faces[NEXTRAND%ni]);
+ }
+#undef NEXTRAND
+}
+
+//
+void btSoftBody::releaseCluster(int index)
+{
+ Cluster* c=m_clusters[index];
+ if(c->m_leaf) m_cdbvt.remove(c->m_leaf);
+ c->~Cluster();
+ btAlignedFree(c);
+ m_clusters.remove(c);
+}
+
+//
+void btSoftBody::releaseClusters()
+{
+ while(m_clusters.size()>0) releaseCluster(0);
+}
+
+//
+int btSoftBody::generateClusters(int k,int maxiterations)
+{
+ int i;
+ releaseClusters();
+ m_clusters.resize(btMin(k,m_nodes.size()));
+ for(i=0;i<m_clusters.size();++i)
+ {
+ m_clusters[i] = new(btAlignedAlloc(sizeof(Cluster),16)) Cluster();
+ m_clusters[i]->m_collide= true;
+ }
+ k=m_clusters.size();
+ if(k>0)
+ {
+ /* Initialize */
+ btAlignedObjectArray<btVector3> centers;
+ btVector3 cog(0,0,0);
+ int i;
+ for(i=0;i<m_nodes.size();++i)
+ {
+ cog+=m_nodes[i].m_x;
+ m_clusters[(i*29873)%m_clusters.size()]->m_nodes.push_back(&m_nodes[i]);
+ }
+ cog/=(btScalar)m_nodes.size();
+ centers.resize(k,cog);
+ /* Iterate */
+ const btScalar slope=16;
+ bool changed;
+ int iterations=0;
+ do {
+ const btScalar w=2-btMin<btScalar>(1,iterations/slope);
+ changed=false;
+ iterations++;
+ int i;
+
+ for(i=0;i<k;++i)
+ {
+ btVector3 c(0,0,0);
+ for(int j=0;j<m_clusters[i]->m_nodes.size();++j)
+ {
+ c+=m_clusters[i]->m_nodes[j]->m_x;
+ }
+ if(m_clusters[i]->m_nodes.size())
+ {
+ c /= (btScalar)m_clusters[i]->m_nodes.size();
+ c = centers[i]+(c-centers[i])*w;
+ changed |= ((c-centers[i]).length2()>SIMD_EPSILON);
+ centers[i] = c;
+ m_clusters[i]->m_nodes.resize(0);
+ }
+ }
+ for(i=0;i<m_nodes.size();++i)
+ {
+ const btVector3 nx=m_nodes[i].m_x;
+ int kbest=0;
+ btScalar kdist=ClusterMetric(centers[0],nx);
+ for(int j=1;j<k;++j)
+ {
+ const btScalar d=ClusterMetric(centers[j],nx);
+ if(d<kdist)
+ {
+ kbest=j;
+ kdist=d;
+ }
+ }
+ m_clusters[kbest]->m_nodes.push_back(&m_nodes[i]);
+ }
+ } while(changed&&(iterations<maxiterations));
+ /* Merge */
+ btAlignedObjectArray<int> cids;
+ cids.resize(m_nodes.size(),-1);
+ for(i=0;i<m_clusters.size();++i)
+ {
+ for(int j=0;j<m_clusters[i]->m_nodes.size();++j)
+ {
+ cids[int(m_clusters[i]->m_nodes[j]-&m_nodes[0])]=i;
+ }
+ }
+ for(i=0;i<m_faces.size();++i)
+ {
+ const int idx[]={ int(m_faces[i].m_n[0]-&m_nodes[0]),
+ int(m_faces[i].m_n[1]-&m_nodes[0]),
+ int(m_faces[i].m_n[2]-&m_nodes[0])};
+ for(int j=0;j<3;++j)
+ {
+ const int cid=cids[idx[j]];
+ for(int q=1;q<3;++q)
+ {
+ const int kid=idx[(j+q)%3];
+ if(cids[kid]!=cid)
+ {
+ if(m_clusters[cid]->m_nodes.findLinearSearch(&m_nodes[kid])==m_clusters[cid]->m_nodes.size())
+ {
+ m_clusters[cid]->m_nodes.push_back(&m_nodes[kid]);
+ }
+ }
+ }
+ }
+ }
+ /* Master */
+ if(m_clusters.size()>1)
+ {
+ Cluster* pmaster=new(btAlignedAlloc(sizeof(Cluster),16)) Cluster();
+ pmaster->m_collide = false;
+ pmaster->m_nodes.reserve(m_nodes.size());
+ for(int i=0;i<m_nodes.size();++i) pmaster->m_nodes.push_back(&m_nodes[i]);
+ m_clusters.push_back(pmaster);
+ btSwap(m_clusters[0],m_clusters[m_clusters.size()-1]);
+ }
+ /* Terminate */
+ for(i=0;i<m_clusters.size();++i)
+ {
+ if(m_clusters[i]->m_nodes.size()==0)
+ {
+ releaseCluster(i--);
+ }
+ }
+ } else
+ {
+ //create a cluster for each tetrahedron (if tetrahedra exist) or each face
+ if (m_tetras.size())
+ {
+ m_clusters.resize(m_tetras.size());
+ for(i=0;i<m_clusters.size();++i)
+ {
+ m_clusters[i] = new(btAlignedAlloc(sizeof(Cluster),16)) Cluster();
+ m_clusters[i]->m_collide= true;
+ }
+ for (i=0;i<m_tetras.size();i++)
+ {
+ for (int j=0;j<4;j++)
+ {
+ m_clusters[i]->m_nodes.push_back(m_tetras[i].m_n[j]);
+ }
+ }
+
+ } else
+ {
+ m_clusters.resize(m_faces.size());
+ for(i=0;i<m_clusters.size();++i)
+ {
+ m_clusters[i] = new(btAlignedAlloc(sizeof(Cluster),16)) Cluster();
+ m_clusters[i]->m_collide= true;
+ }
+
+ for(i=0;i<m_faces.size();++i)
+ {
+ for(int j=0;j<3;++j)
+ {
+ m_clusters[i]->m_nodes.push_back(m_faces[i].m_n[j]);
+ }
+ }
+ }
+ }
+
+ if (m_clusters.size())
+ {
+ initializeClusters();
+ updateClusters();
+
+
+ //for self-collision
+ m_clusterConnectivity.resize(m_clusters.size()*m_clusters.size());
+ {
+ for (int c0=0;c0<m_clusters.size();c0++)
+ {
+ m_clusters[c0]->m_clusterIndex=c0;
+ for (int c1=0;c1<m_clusters.size();c1++)
+ {
+
+ bool connected=false;
+ Cluster* cla = m_clusters[c0];
+ Cluster* clb = m_clusters[c1];
+ for (int i=0;!connected&&i<cla->m_nodes.size();i++)
+ {
+ for (int j=0;j<clb->m_nodes.size();j++)
+ {
+ if (cla->m_nodes[i] == clb->m_nodes[j])
+ {
+ connected=true;
+ break;
+ }
+ }
+ }
+ m_clusterConnectivity[c0+c1*m_clusters.size()]=connected;
+ }
+ }
+ }
+ }
+
+ return(m_clusters.size());
+}
+
+//
+void btSoftBody::refine(ImplicitFn* ifn,btScalar accurary,bool cut)
+{
+ const Node* nbase = &m_nodes[0];
+ int ncount = m_nodes.size();
+ btSymMatrix<int> edges(ncount,-2);
+ int newnodes=0;
+ int i,j,k,ni;
+
+ /* Filter out */
+ for(i=0;i<m_links.size();++i)
+ {
+ Link& l=m_links[i];
+ if(l.m_bbending)
+ {
+ if(!SameSign(ifn->Eval(l.m_n[0]->m_x),ifn->Eval(l.m_n[1]->m_x)))
+ {
+ btSwap(m_links[i],m_links[m_links.size()-1]);
+ m_links.pop_back();--i;
+ }
+ }
+ }
+ /* Fill edges */
+ for(i=0;i<m_links.size();++i)
+ {
+ Link& l=m_links[i];
+ edges(int(l.m_n[0]-nbase),int(l.m_n[1]-nbase))=-1;
+ }
+ for(i=0;i<m_faces.size();++i)
+ {
+ Face& f=m_faces[i];
+ edges(int(f.m_n[0]-nbase),int(f.m_n[1]-nbase))=-1;
+ edges(int(f.m_n[1]-nbase),int(f.m_n[2]-nbase))=-1;
+ edges(int(f.m_n[2]-nbase),int(f.m_n[0]-nbase))=-1;
+ }
+ /* Intersect */
+ for(i=0;i<ncount;++i)
+ {
+ for(j=i+1;j<ncount;++j)
+ {
+ if(edges(i,j)==-1)
+ {
+ Node& a=m_nodes[i];
+ Node& b=m_nodes[j];
+ const btScalar t=ImplicitSolve(ifn,a.m_x,b.m_x,accurary);
+ if(t>0)
+ {
+ const btVector3 x=Lerp(a.m_x,b.m_x,t);
+ const btVector3 v=Lerp(a.m_v,b.m_v,t);
+ btScalar m=0;
+ if(a.m_im>0)
+ {
+ if(b.m_im>0)
+ {
+ const btScalar ma=1/a.m_im;
+ const btScalar mb=1/b.m_im;
+ const btScalar mc=Lerp(ma,mb,t);
+ const btScalar f=(ma+mb)/(ma+mb+mc);
+ a.m_im=1/(ma*f);
+ b.m_im=1/(mb*f);
+ m=mc*f;
+ }
+ else
+ { a.m_im/=0.5f;m=1/a.m_im; }
+ }
+ else
+ {
+ if(b.m_im>0)
+ { b.m_im/=0.5f;m=1/b.m_im; }
+ else
+ m=0;
+ }
+ appendNode(x,m);
+ edges(i,j)=m_nodes.size()-1;
+ m_nodes[edges(i,j)].m_v=v;
+ ++newnodes;
+ }
+ }
+ }
+ }
+ nbase=&m_nodes[0];
+ /* Refine links */
+ for(i=0,ni=m_links.size();i<ni;++i)
+ {
+ Link& feat=m_links[i];
+ const int idx[]={ int(feat.m_n[0]-nbase),
+ int(feat.m_n[1]-nbase)};
+ if((idx[0]<ncount)&&(idx[1]<ncount))
+ {
+ const int ni=edges(idx[0],idx[1]);
+ if(ni>0)
+ {
+ appendLink(i);
+ Link* pft[]={ &m_links[i],
+ &m_links[m_links.size()-1]};
+ pft[0]->m_n[0]=&m_nodes[idx[0]];
+ pft[0]->m_n[1]=&m_nodes[ni];
+ pft[1]->m_n[0]=&m_nodes[ni];
+ pft[1]->m_n[1]=&m_nodes[idx[1]];
+ }
+ }
+ }
+ /* Refine faces */
+ for(i=0;i<m_faces.size();++i)
+ {
+ const Face& feat=m_faces[i];
+ const int idx[]={ int(feat.m_n[0]-nbase),
+ int(feat.m_n[1]-nbase),
+ int(feat.m_n[2]-nbase)};
+ for(j=2,k=0;k<3;j=k++)
+ {
+ if((idx[j]<ncount)&&(idx[k]<ncount))
+ {
+ const int ni=edges(idx[j],idx[k]);
+ if(ni>0)
+ {
+ appendFace(i);
+ const int l=(k+1)%3;
+ Face* pft[]={ &m_faces[i],
+ &m_faces[m_faces.size()-1]};
+ pft[0]->m_n[0]=&m_nodes[idx[l]];
+ pft[0]->m_n[1]=&m_nodes[idx[j]];
+ pft[0]->m_n[2]=&m_nodes[ni];
+ pft[1]->m_n[0]=&m_nodes[ni];
+ pft[1]->m_n[1]=&m_nodes[idx[k]];
+ pft[1]->m_n[2]=&m_nodes[idx[l]];
+ appendLink(ni,idx[l],pft[0]->m_material);
+ --i;break;
+ }
+ }
+ }
+ }
+ /* Cut */
+ if(cut)
+ {
+ btAlignedObjectArray<int> cnodes;
+ const int pcount=ncount;
+ int i;
+ ncount=m_nodes.size();
+ cnodes.resize(ncount,0);
+ /* Nodes */
+ for(i=0;i<ncount;++i)
+ {
+ const btVector3 x=m_nodes[i].m_x;
+ if((i>=pcount)||(btFabs(ifn->Eval(x))<accurary))
+ {
+ const btVector3 v=m_nodes[i].m_v;
+ btScalar m=getMass(i);
+ if(m>0) { m*=0.5f;m_nodes[i].m_im/=0.5f; }
+ appendNode(x,m);
+ cnodes[i]=m_nodes.size()-1;
+ m_nodes[cnodes[i]].m_v=v;
+ }
+ }
+ nbase=&m_nodes[0];
+ /* Links */
+ for(i=0,ni=m_links.size();i<ni;++i)
+ {
+ const int id[]={ int(m_links[i].m_n[0]-nbase),
+ int(m_links[i].m_n[1]-nbase)};
+ int todetach=0;
+ if(cnodes[id[0]]&&cnodes[id[1]])
+ {
+ appendLink(i);
+ todetach=m_links.size()-1;
+ }
+ else
+ {
+ if(( (ifn->Eval(m_nodes[id[0]].m_x)<accurary)&&
+ (ifn->Eval(m_nodes[id[1]].m_x)<accurary)))
+ todetach=i;
+ }
+ if(todetach)
+ {
+ Link& l=m_links[todetach];
+ for(int j=0;j<2;++j)
+ {
+ int cn=cnodes[int(l.m_n[j]-nbase)];
+ if(cn) l.m_n[j]=&m_nodes[cn];
+ }
+ }
+ }
+ /* Faces */
+ for(i=0,ni=m_faces.size();i<ni;++i)
+ {
+ Node** n= m_faces[i].m_n;
+ if( (ifn->Eval(n[0]->m_x)<accurary)&&
+ (ifn->Eval(n[1]->m_x)<accurary)&&
+ (ifn->Eval(n[2]->m_x)<accurary))
+ {
+ for(int j=0;j<3;++j)
+ {
+ int cn=cnodes[int(n[j]-nbase)];
+ if(cn) n[j]=&m_nodes[cn];
+ }
+ }
+ }
+ /* Clean orphans */
+ int nnodes=m_nodes.size();
+ btAlignedObjectArray<int> ranks;
+ btAlignedObjectArray<int> todelete;
+ ranks.resize(nnodes,0);
+ for(i=0,ni=m_links.size();i<ni;++i)
+ {
+ for(int j=0;j<2;++j) ranks[int(m_links[i].m_n[j]-nbase)]++;
+ }
+ for(i=0,ni=m_faces.size();i<ni;++i)
+ {
+ for(int j=0;j<3;++j) ranks[int(m_faces[i].m_n[j]-nbase)]++;
+ }
+ for(i=0;i<m_links.size();++i)
+ {
+ const int id[]={ int(m_links[i].m_n[0]-nbase),
+ int(m_links[i].m_n[1]-nbase)};
+ const bool sg[]={ ranks[id[0]]==1,
+ ranks[id[1]]==1};
+ if(sg[0]||sg[1])
+ {
+ --ranks[id[0]];
+ --ranks[id[1]];
+ btSwap(m_links[i],m_links[m_links.size()-1]);
+ m_links.pop_back();--i;
+ }
+ }
+#if 0
+ for(i=nnodes-1;i>=0;--i)
+ {
+ if(!ranks[i]) todelete.push_back(i);
+ }
+ if(todelete.size())
+ {
+ btAlignedObjectArray<int>& map=ranks;
+ for(int i=0;i<nnodes;++i) map[i]=i;
+ PointersToIndices(this);
+ for(int i=0,ni=todelete.size();i<ni;++i)
+ {
+ int j=todelete[i];
+ int& a=map[j];
+ int& b=map[--nnodes];
+ m_ndbvt.remove(m_nodes[a].m_leaf);m_nodes[a].m_leaf=0;
+ btSwap(m_nodes[a],m_nodes[b]);
+ j=a;a=b;b=j;
+ }
+ IndicesToPointers(this,&map[0]);
+ m_nodes.resize(nnodes);
+ }
+#endif
+ }
+ m_bUpdateRtCst=true;
+}
+
+//
+bool btSoftBody::cutLink(const Node* node0,const Node* node1,btScalar position)
+{
+ return(cutLink(int(node0-&m_nodes[0]),int(node1-&m_nodes[0]),position));
+}
+
+//
+bool btSoftBody::cutLink(int node0,int node1,btScalar position)
+{
+ bool done=false;
+ int i,ni;
+// const btVector3 d=m_nodes[node0].m_x-m_nodes[node1].m_x;
+ const btVector3 x=Lerp(m_nodes[node0].m_x,m_nodes[node1].m_x,position);
+ const btVector3 v=Lerp(m_nodes[node0].m_v,m_nodes[node1].m_v,position);
+ const btScalar m=1;
+ appendNode(x,m);
+ appendNode(x,m);
+ Node* pa=&m_nodes[node0];
+ Node* pb=&m_nodes[node1];
+ Node* pn[2]={ &m_nodes[m_nodes.size()-2],
+ &m_nodes[m_nodes.size()-1]};
+ pn[0]->m_v=v;
+ pn[1]->m_v=v;
+ for(i=0,ni=m_links.size();i<ni;++i)
+ {
+ const int mtch=MatchEdge(m_links[i].m_n[0],m_links[i].m_n[1],pa,pb);
+ if(mtch!=-1)
+ {
+ appendLink(i);
+ Link* pft[]={&m_links[i],&m_links[m_links.size()-1]};
+ pft[0]->m_n[1]=pn[mtch];
+ pft[1]->m_n[0]=pn[1-mtch];
+ done=true;
+ }
+ }
+ for(i=0,ni=m_faces.size();i<ni;++i)
+ {
+ for(int k=2,l=0;l<3;k=l++)
+ {
+ const int mtch=MatchEdge(m_faces[i].m_n[k],m_faces[i].m_n[l],pa,pb);
+ if(mtch!=-1)
+ {
+ appendFace(i);
+ Face* pft[]={&m_faces[i],&m_faces[m_faces.size()-1]};
+ pft[0]->m_n[l]=pn[mtch];
+ pft[1]->m_n[k]=pn[1-mtch];
+ appendLink(pn[0],pft[0]->m_n[(l+1)%3],pft[0]->m_material,true);
+ appendLink(pn[1],pft[0]->m_n[(l+1)%3],pft[0]->m_material,true);
+ }
+ }
+ }
+ if(!done)
+ {
+ m_ndbvt.remove(pn[0]->m_leaf);
+ m_ndbvt.remove(pn[1]->m_leaf);
+ m_nodes.pop_back();
+ m_nodes.pop_back();
+ }
+ return(done);
+}
+
+//
+bool btSoftBody::rayTest(const btVector3& rayFrom,
+ const btVector3& rayTo,
+ sRayCast& results)
+{
+ if(m_faces.size()&&m_fdbvt.empty())
+ initializeFaceTree();
+
+ results.body = this;
+ results.fraction = 1.f;
+ results.feature = eFeature::None;
+ results.index = -1;
+
+ return(rayTest(rayFrom,rayTo,results.fraction,results.feature,results.index,false)!=0);
+}
+
+//
+void btSoftBody::setSolver(eSolverPresets::_ preset)
+{
+ m_cfg.m_vsequence.clear();
+ m_cfg.m_psequence.clear();
+ m_cfg.m_dsequence.clear();
+ switch(preset)
+ {
+ case eSolverPresets::Positions:
+ m_cfg.m_psequence.push_back(ePSolver::Anchors);
+ m_cfg.m_psequence.push_back(ePSolver::RContacts);
+ m_cfg.m_psequence.push_back(ePSolver::SContacts);
+ m_cfg.m_psequence.push_back(ePSolver::Linear);
+ break;
+ case eSolverPresets::Velocities:
+ m_cfg.m_vsequence.push_back(eVSolver::Linear);
+
+ m_cfg.m_psequence.push_back(ePSolver::Anchors);
+ m_cfg.m_psequence.push_back(ePSolver::RContacts);
+ m_cfg.m_psequence.push_back(ePSolver::SContacts);
+
+ m_cfg.m_dsequence.push_back(ePSolver::Linear);
+ break;
+ }
+}
+
+//
+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);
+}
+
+//
+void btSoftBody::solveConstraints()
+{
+
+ /* Apply clusters */
+ applyClusters(false);
+ /* Prepare links */
+
+ int i,ni;
+
+ for(i=0,ni=m_links.size();i<ni;++i)
+ {
+ Link& l=m_links[i];
+ l.m_c3 = l.m_n[1]->m_q-l.m_n[0]->m_q;
+ l.m_c2 = 1/(l.m_c3.length2()*l.m_c0);
+ }
+ /* Prepare anchors */
+ for(i=0,ni=m_anchors.size();i<ni;++i)
+ {
+ Anchor& a=m_anchors[i];
+ const btVector3 ra=a.m_body->getWorldTransform().getBasis()*a.m_local;
+ a.m_c0 = ImpulseMatrix( m_sst.sdt,
+ a.m_node->m_im,
+ a.m_body->getInvMass(),
+ a.m_body->getInvInertiaTensorWorld(),
+ ra);
+ a.m_c1 = ra;
+ a.m_c2 = m_sst.sdt*a.m_node->m_im;
+ a.m_body->activate();
+ }
+ /* Solve velocities */
+ if(m_cfg.viterations>0)
+ {
+ /* Solve */
+ for(int isolve=0;isolve<m_cfg.viterations;++isolve)
+ {
+ for(int iseq=0;iseq<m_cfg.m_vsequence.size();++iseq)
+ {
+ getSolver(m_cfg.m_vsequence[iseq])(this,1);
+ }
+ }
+ /* Update */
+ for(i=0,ni=m_nodes.size();i<ni;++i)
+ {
+ Node& n=m_nodes[i];
+ n.m_x = n.m_q+n.m_v*m_sst.sdt;
+ }
+ }
+ /* Solve positions */
+ if(m_cfg.piterations>0)
+ {
+ for(int isolve=0;isolve<m_cfg.piterations;++isolve)
+ {
+ const btScalar ti=isolve/(btScalar)m_cfg.piterations;
+ for(int iseq=0;iseq<m_cfg.m_psequence.size();++iseq)
+ {
+ getSolver(m_cfg.m_psequence[iseq])(this,1,ti);
+ }
+ }
+ const btScalar vc=m_sst.isdt*(1-m_cfg.kDP);
+ for(i=0,ni=m_nodes.size();i<ni;++i)
+ {
+ Node& n=m_nodes[i];
+ n.m_v = (n.m_x-n.m_q)*vc;
+ n.m_f = btVector3(0,0,0);
+ }
+ }
+ /* Solve drift */
+ if(m_cfg.diterations>0)
+ {
+ const btScalar vcf=m_cfg.kVCF*m_sst.isdt;
+ for(i=0,ni=m_nodes.size();i<ni;++i)
+ {
+ Node& n=m_nodes[i];
+ n.m_q = n.m_x;
+ }
+ for(int idrift=0;idrift<m_cfg.diterations;++idrift)
+ {
+ for(int iseq=0;iseq<m_cfg.m_dsequence.size();++iseq)
+ {
+ getSolver(m_cfg.m_dsequence[iseq])(this,1,0);
+ }
+ }
+ for(int i=0,ni=m_nodes.size();i<ni;++i)
+ {
+ Node& n=m_nodes[i];
+ n.m_v += (n.m_x-n.m_q)*vcf;
+ }
+ }
+ /* Apply clusters */
+ dampClusters();
+ applyClusters(true);
+}
+
+//
+void btSoftBody::staticSolve(int iterations)
+{
+ for(int isolve=0;isolve<iterations;++isolve)
+ {
+ for(int iseq=0;iseq<m_cfg.m_psequence.size();++iseq)
+ {
+ getSolver(m_cfg.m_psequence[iseq])(this,1,0);
+ }
+ }
+}
+
+//
+void btSoftBody::solveCommonConstraints(btSoftBody** /*bodies*/,int /*count*/,int /*iterations*/)
+{
+ /// placeholder
+}
+
+//
+void btSoftBody::solveClusters(const btAlignedObjectArray<btSoftBody*>& bodies)
+{
+ const int nb=bodies.size();
+ int iterations=0;
+ int i;
+
+ for(i=0;i<nb;++i)
+ {
+ iterations=btMax(iterations,bodies[i]->m_cfg.citerations);
+ }
+ for(i=0;i<nb;++i)
+ {
+ bodies[i]->prepareClusters(iterations);
+ }
+ for(i=0;i<iterations;++i)
+ {
+ const btScalar sor=1;
+ for(int j=0;j<nb;++j)
+ {
+ bodies[j]->solveClusters(sor);
+ }
+ }
+ for(i=0;i<nb;++i)
+ {
+ bodies[i]->cleanupClusters();
+ }
+}
+
+//
+void btSoftBody::integrateMotion()
+{
+ /* Update */
+ updateNormals();
+}
+
+//
+btSoftBody::RayFromToCaster::RayFromToCaster(const btVector3& rayFrom,const btVector3& rayTo,btScalar mxt)
+{
+ m_rayFrom = rayFrom;
+ m_rayNormalizedDirection = (rayTo-rayFrom);
+ m_rayTo = rayTo;
+ m_mint = mxt;
+ m_face = 0;
+ m_tests = 0;
+}
+
+//
+void btSoftBody::RayFromToCaster::Process(const btDbvtNode* leaf)
+{
+ btSoftBody::Face& f=*(btSoftBody::Face*)leaf->data;
+ const btScalar t=rayFromToTriangle( m_rayFrom,m_rayTo,m_rayNormalizedDirection,
+ f.m_n[0]->m_x,
+ f.m_n[1]->m_x,
+ f.m_n[2]->m_x,
+ m_mint);
+ if((t>0)&&(t<m_mint))
+ {
+ m_mint=t;m_face=&f;
+ }
+ ++m_tests;
+}
+
+//
+btScalar btSoftBody::RayFromToCaster::rayFromToTriangle( const btVector3& rayFrom,
+ const btVector3& rayTo,
+ const btVector3& rayNormalizedDirection,
+ const btVector3& a,
+ const btVector3& b,
+ const btVector3& c,
+ btScalar maxt)
+{
+ static const btScalar ceps=-SIMD_EPSILON*10;
+ static const btScalar teps=SIMD_EPSILON*10;
+
+ const btVector3 n=btCross(b-a,c-a);
+ const btScalar d=btDot(a,n);
+ const btScalar den=btDot(rayNormalizedDirection,n);
+ if(!btFuzzyZero(den))
+ {
+ const btScalar num=btDot(rayFrom,n)-d;
+ const btScalar t=-num/den;
+ if((t>teps)&&(t<maxt))
+ {
+ const btVector3 hit=rayFrom+rayNormalizedDirection*t;
+ if( (btDot(n,btCross(a-hit,b-hit))>ceps) &&
+ (btDot(n,btCross(b-hit,c-hit))>ceps) &&
+ (btDot(n,btCross(c-hit,a-hit))>ceps))
+ {
+ return(t);
+ }
+ }
+ }
+ return(-1);
+}
+
+//
+void btSoftBody::pointersToIndices()
+{
+#define PTR2IDX(_p_,_b_) reinterpret_cast<btSoftBody::Node*>((_p_)-(_b_))
+ btSoftBody::Node* base=m_nodes.size() ? &m_nodes[0] : 0;
+ int i,ni;
+
+ for(i=0,ni=m_nodes.size();i<ni;++i)
+ {
+ if(m_nodes[i].m_leaf)
+ {
+ m_nodes[i].m_leaf->data=*(void**)&i;
+ }
+ }
+ for(i=0,ni=m_links.size();i<ni;++i)
+ {
+ m_links[i].m_n[0]=PTR2IDX(m_links[i].m_n[0],base);
+ m_links[i].m_n[1]=PTR2IDX(m_links[i].m_n[1],base);
+ }
+ for(i=0,ni=m_faces.size();i<ni;++i)
+ {
+ m_faces[i].m_n[0]=PTR2IDX(m_faces[i].m_n[0],base);
+ m_faces[i].m_n[1]=PTR2IDX(m_faces[i].m_n[1],base);
+ m_faces[i].m_n[2]=PTR2IDX(m_faces[i].m_n[2],base);
+ if(m_faces[i].m_leaf)
+ {
+ m_faces[i].m_leaf->data=*(void**)&i;
+ }
+ }
+ for(i=0,ni=m_anchors.size();i<ni;++i)
+ {
+ m_anchors[i].m_node=PTR2IDX(m_anchors[i].m_node,base);
+ }
+ for(i=0,ni=m_notes.size();i<ni;++i)
+ {
+ for(int j=0;j<m_notes[i].m_rank;++j)
+ {
+ m_notes[i].m_nodes[j]=PTR2IDX(m_notes[i].m_nodes[j],base);
+ }
+ }
+#undef PTR2IDX
+}
+
+//
+void btSoftBody::indicesToPointers(const int* map)
+{
+#define IDX2PTR(_p_,_b_) map?(&(_b_)[map[(((char*)_p_)-(char*)0)]]): \
+ (&(_b_)[(((char*)_p_)-(char*)0)])
+ btSoftBody::Node* base=m_nodes.size() ? &m_nodes[0]:0;
+ int i,ni;
+
+ for(i=0,ni=m_nodes.size();i<ni;++i)
+ {
+ if(m_nodes[i].m_leaf)
+ {
+ m_nodes[i].m_leaf->data=&m_nodes[i];
+ }
+ }
+ for(i=0,ni=m_links.size();i<ni;++i)
+ {
+ m_links[i].m_n[0]=IDX2PTR(m_links[i].m_n[0],base);
+ m_links[i].m_n[1]=IDX2PTR(m_links[i].m_n[1],base);
+ }
+ for(i=0,ni=m_faces.size();i<ni;++i)
+ {
+ m_faces[i].m_n[0]=IDX2PTR(m_faces[i].m_n[0],base);
+ m_faces[i].m_n[1]=IDX2PTR(m_faces[i].m_n[1],base);
+ m_faces[i].m_n[2]=IDX2PTR(m_faces[i].m_n[2],base);
+ if(m_faces[i].m_leaf)
+ {
+ m_faces[i].m_leaf->data=&m_faces[i];
+ }
+ }
+ for(i=0,ni=m_anchors.size();i<ni;++i)
+ {
+ m_anchors[i].m_node=IDX2PTR(m_anchors[i].m_node,base);
+ }
+ for(i=0,ni=m_notes.size();i<ni;++i)
+ {
+ for(int j=0;j<m_notes[i].m_rank;++j)
+ {
+ m_notes[i].m_nodes[j]=IDX2PTR(m_notes[i].m_nodes[j],base);
+ }
+ }
+#undef IDX2PTR
+}
+
+//
+int btSoftBody::rayTest(const btVector3& rayFrom,const btVector3& rayTo,
+ btScalar& mint,eFeature::_& feature,int& index,bool bcountonly) const
+{
+ int cnt=0;
+ btVector3 dir = rayTo-rayFrom;
+
+
+ if(bcountonly||m_fdbvt.empty())
+ {/* Full search */
+
+ for(int i=0,ni=m_faces.size();i<ni;++i)
+ {
+ const btSoftBody::Face& f=m_faces[i];
+
+ const btScalar t=RayFromToCaster::rayFromToTriangle( rayFrom,rayTo,dir,
+ f.m_n[0]->m_x,
+ f.m_n[1]->m_x,
+ f.m_n[2]->m_x,
+ mint);
+ if(t>0)
+ {
+ ++cnt;
+ if(!bcountonly)
+ {
+ feature=btSoftBody::eFeature::Face;
+ index=i;
+ mint=t;
+ }
+ }
+ }
+ }
+ else
+ {/* Use dbvt */
+ RayFromToCaster collider(rayFrom,rayTo,mint);
+
+ btDbvt::rayTest(m_fdbvt.m_root,rayFrom,rayTo,collider);
+ if(collider.m_face)
+ {
+ mint=collider.m_mint;
+ feature=btSoftBody::eFeature::Face;
+ index=(int)(collider.m_face-&m_faces[0]);
+ cnt=1;
+ }
+ }
+
+ for (int i=0;i<m_tetras.size();i++)
+ {
+ const btSoftBody::Tetra& tet = m_tetras[i];
+ int tetfaces[4][3] = {{0,1,2},{0,1,3},{1,2,3},{0,2,3}};
+ for (int f=0;f<4;f++)
+ {
+
+ int index0=tetfaces[f][0];
+ int index1=tetfaces[f][1];
+ int index2=tetfaces[f][2];
+ btVector3 v0=tet.m_n[index0]->m_x;
+ btVector3 v1=tet.m_n[index1]->m_x;
+ btVector3 v2=tet.m_n[index2]->m_x;
+
+
+ const btScalar t=RayFromToCaster::rayFromToTriangle( rayFrom,rayTo,dir,
+ v0,v1,v2,
+ mint);
+ if(t>0)
+ {
+ ++cnt;
+ if(!bcountonly)
+ {
+ feature=btSoftBody::eFeature::Tetra;
+ index=i;
+ mint=t;
+ }
+ }
+ }
+ }
+ return(cnt);
+}
+
+//
+void btSoftBody::initializeFaceTree()
+{
+ m_fdbvt.clear();
+ for(int i=0;i<m_faces.size();++i)
+ {
+ Face& f=m_faces[i];
+ f.m_leaf=m_fdbvt.insert(VolumeOf(f,0),&f);
+ }
+}
+
+//
+btVector3 btSoftBody::evaluateCom() const
+{
+ btVector3 com(0,0,0);
+ if(m_pose.m_bframe)
+ {
+ for(int i=0,ni=m_nodes.size();i<ni;++i)
+ {
+ com+=m_nodes[i].m_x*m_pose.m_wgh[i];
+ }
+ }
+ 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);
+}
+
+//
+void btSoftBody::updateNormals()
+{
+
+ const btVector3 zv(0,0,0);
+ int i,ni;
+
+ for(i=0,ni=m_nodes.size();i<ni;++i)
+ {
+ m_nodes[i].m_n=zv;
+ }
+ for(i=0,ni=m_faces.size();i<ni;++i)
+ {
+ 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_n[0]->m_n+=n;
+ f.m_n[1]->m_n+=n;
+ f.m_n[2]->m_n+=n;
+ }
+ for(i=0,ni=m_nodes.size();i<ni;++i)
+ {
+ btScalar len = m_nodes[i].m_n.length();
+ if (len>SIMD_EPSILON)
+ m_nodes[i].m_n /= len;
+ }
+}
+
+//
+void btSoftBody::updateBounds()
+{
+ /*if( m_acceleratedSoftBody )
+ {
+ // If we have an accelerated softbody we need to obtain the bounds correctly
+ // For now (slightly hackily) just have a very large AABB
+ // TODO: Write get bounds kernel
+ // If that is updating in place, atomic collisions might be low (when the cloth isn't perfectly aligned to an axis) and we could
+ // probably do a test and exchange reasonably efficiently.
+
+ m_bounds[0] = btVector3(-1000, -1000, -1000);
+ 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);
+ }
+ //}
+}
+
+
+//
+void btSoftBody::updatePose()
+{
+ if(m_pose.m_bframe)
+ {
+ btSoftBody::Pose& pose=m_pose;
+ const btVector3 com=evaluateCom();
+ /* Com */
+ pose.m_com = com;
+ /* Rotation */
+ btMatrix3x3 Apq;
+ const btScalar eps=SIMD_EPSILON;
+ Apq[0]=Apq[1]=Apq[2]=btVector3(0,0,0);
+ Apq[0].setX(eps);Apq[1].setY(eps*2);Apq[2].setZ(eps*3);
+ for(int i=0,ni=m_nodes.size();i<ni;++i)
+ {
+ const btVector3 a=pose.m_wgh[i]*(m_nodes[i].m_x-com);
+ const btVector3& b=pose.m_pos[i];
+ Apq[0]+=a.x()*b;
+ Apq[1]+=a.y()*b;
+ Apq[2]+=a.z()*b;
+ }
+ btMatrix3x3 r,s;
+ PolarDecompose(Apq,r,s);
+ pose.m_rot=r;
+ pose.m_scl=pose.m_aqq*r.transpose()*Apq;
+ if(m_cfg.maxvolume>1)
+ {
+ const btScalar idet=Clamp<btScalar>( 1/pose.m_scl.determinant(),
+ 1,m_cfg.maxvolume);
+ pose.m_scl=Mul(pose.m_scl,idet);
+ }
+
+ }
+}
+
+//
+void btSoftBody::updateArea(bool averageArea)
+{
+ int i,ni;
+
+ /* Face area */
+ for(i=0,ni=m_faces.size();i<ni;++i)
+ {
+ Face& f=m_faces[i];
+ f.m_ra = AreaOf(f.m_n[0]->m_x,f.m_n[1]->m_x,f.m_n[2]->m_x);
+ }
+
+ /* Node area */
+
+ if (averageArea)
+ {
+ btAlignedObjectArray<int> counts;
+ counts.resize(m_nodes.size(),0);
+ for(i=0,ni=m_nodes.size();i<ni;++i)
+ {
+ m_nodes[i].m_area = 0;
+ }
+ for(i=0,ni=m_faces.size();i<ni;++i)
+ {
+ btSoftBody::Face& f=m_faces[i];
+ for(int j=0;j<3;++j)
+ {
+ const int index=(int)(f.m_n[j]-&m_nodes[0]);
+ counts[index]++;
+ f.m_n[j]->m_area+=btFabs(f.m_ra);
+ }
+ }
+ for(i=0,ni=m_nodes.size();i<ni;++i)
+ {
+ if(counts[i]>0)
+ m_nodes[i].m_area/=(btScalar)counts[i];
+ else
+ m_nodes[i].m_area=0;
+ }
+ }
+ else
+ {
+ // initialize node area as zero
+ for(i=0,ni=m_nodes.size();i<ni;++i)
+ {
+ m_nodes[i].m_area=0;
+ }
+
+ for(i=0,ni=m_faces.size();i<ni;++i)
+ {
+ btSoftBody::Face& f=m_faces[i];
+
+ for(int j=0;j<3;++j)
+ {
+ f.m_n[j]->m_area += f.m_ra;
+ }
+ }
+
+ for(i=0,ni=m_nodes.size();i<ni;++i)
+ {
+ m_nodes[i].m_area *= 0.3333333f;
+ }
+ }
+}
+
+
+void btSoftBody::updateLinkConstants()
+{
+ int i,ni;
+
+ /* Links */
+ for(i=0,ni=m_links.size();i<ni;++i)
+ {
+ Link& l=m_links[i];
+ Material& m=*l.m_material;
+ l.m_c0 = (l.m_n[0]->m_im+l.m_n[1]->m_im)/m.m_kLST;
+ }
+}
+
+void btSoftBody::updateConstants()
+{
+ resetLinkRestLengths();
+ updateLinkConstants();
+ updateArea();
+}
+
+
+
+//
+void btSoftBody::initializeClusters()
+{
+ int i;
+
+ for( i=0;i<m_clusters.size();++i)
+ {
+ Cluster& c=*m_clusters[i];
+ c.m_imass=0;
+ c.m_masses.resize(c.m_nodes.size());
+ for(int j=0;j<c.m_nodes.size();++j)
+ {
+ if (c.m_nodes[j]->m_im==0)
+ {
+ c.m_containsAnchor = true;
+ c.m_masses[j] = BT_LARGE_FLOAT;
+ } else
+ {
+ c.m_masses[j] = btScalar(1.)/c.m_nodes[j]->m_im;
+ }
+ c.m_imass += c.m_masses[j];
+ }
+ c.m_imass = btScalar(1.)/c.m_imass;
+ c.m_com = btSoftBody::clusterCom(&c);
+ c.m_lv = btVector3(0,0,0);
+ c.m_av = btVector3(0,0,0);
+ c.m_leaf = 0;
+ /* Inertia */
+ btMatrix3x3& ii=c.m_locii;
+ ii[0]=ii[1]=ii[2]=btVector3(0,0,0);
+ {
+ int i,ni;
+
+ for(i=0,ni=c.m_nodes.size();i<ni;++i)
+ {
+ const btVector3 k=c.m_nodes[i]->m_x-c.m_com;
+ const btVector3 q=k*k;
+ const btScalar m=c.m_masses[i];
+ ii[0][0] += m*(q[1]+q[2]);
+ ii[1][1] += m*(q[0]+q[2]);
+ ii[2][2] += m*(q[0]+q[1]);
+ ii[0][1] -= m*k[0]*k[1];
+ ii[0][2] -= m*k[0]*k[2];
+ ii[1][2] -= m*k[1]*k[2];
+ }
+ }
+ ii[1][0]=ii[0][1];
+ ii[2][0]=ii[0][2];
+ ii[2][1]=ii[1][2];
+
+ ii = ii.inverse();
+
+ /* Frame */
+ c.m_framexform.setIdentity();
+ c.m_framexform.setOrigin(c.m_com);
+ c.m_framerefs.resize(c.m_nodes.size());
+ {
+ int i;
+ for(i=0;i<c.m_framerefs.size();++i)
+ {
+ c.m_framerefs[i]=c.m_nodes[i]->m_x-c.m_com;
+ }
+ }
+ }
+}
+
+//
+void btSoftBody::updateClusters()
+{
+ BT_PROFILE("UpdateClusters");
+ int i;
+
+ for(i=0;i<m_clusters.size();++i)
+ {
+ btSoftBody::Cluster& c=*m_clusters[i];
+ const int n=c.m_nodes.size();
+ //const btScalar invn=1/(btScalar)n;
+ if(n)
+ {
+ /* Frame */
+ const btScalar eps=btScalar(0.0001);
+ btMatrix3x3 m,r,s;
+ m[0]=m[1]=m[2]=btVector3(0,0,0);
+ m[0][0]=eps*1;
+ m[1][1]=eps*2;
+ m[2][2]=eps*3;
+ c.m_com=clusterCom(&c);
+ for(int i=0;i<c.m_nodes.size();++i)
+ {
+ const btVector3 a=c.m_nodes[i]->m_x-c.m_com;
+ const btVector3& b=c.m_framerefs[i];
+ m[0]+=a[0]*b;m[1]+=a[1]*b;m[2]+=a[2]*b;
+ }
+ PolarDecompose(m,r,s);
+ c.m_framexform.setOrigin(c.m_com);
+ c.m_framexform.setBasis(r);
+ /* Inertia */
+#if 1/* Constant */
+ c.m_invwi=c.m_framexform.getBasis()*c.m_locii*c.m_framexform.getBasis().transpose();
+#else
+#if 0/* Sphere */
+ const btScalar rk=(2*c.m_extents.length2())/(5*c.m_imass);
+ const btVector3 inertia(rk,rk,rk);
+ const btVector3 iin(btFabs(inertia[0])>SIMD_EPSILON?1/inertia[0]:0,
+ btFabs(inertia[1])>SIMD_EPSILON?1/inertia[1]:0,
+ btFabs(inertia[2])>SIMD_EPSILON?1/inertia[2]:0);
+
+ c.m_invwi=c.m_xform.getBasis().scaled(iin)*c.m_xform.getBasis().transpose();
+#else/* Actual */
+ c.m_invwi[0]=c.m_invwi[1]=c.m_invwi[2]=btVector3(0,0,0);
+ for(int i=0;i<n;++i)
+ {
+ const btVector3 k=c.m_nodes[i]->m_x-c.m_com;
+ const btVector3 q=k*k;
+ const btScalar m=1/c.m_nodes[i]->m_im;
+ c.m_invwi[0][0] += m*(q[1]+q[2]);
+ c.m_invwi[1][1] += m*(q[0]+q[2]);
+ c.m_invwi[2][2] += m*(q[0]+q[1]);
+ c.m_invwi[0][1] -= m*k[0]*k[1];
+ c.m_invwi[0][2] -= m*k[0]*k[2];
+ c.m_invwi[1][2] -= m*k[1]*k[2];
+ }
+ c.m_invwi[1][0]=c.m_invwi[0][1];
+ c.m_invwi[2][0]=c.m_invwi[0][2];
+ c.m_invwi[2][1]=c.m_invwi[1][2];
+ c.m_invwi=c.m_invwi.inverse();
+#endif
+#endif
+ /* Velocities */
+ c.m_lv=btVector3(0,0,0);
+ c.m_av=btVector3(0,0,0);
+ {
+ int i;
+
+ for(i=0;i<n;++i)
+ {
+ const btVector3 v=c.m_nodes[i]->m_v*c.m_masses[i];
+ c.m_lv += v;
+ c.m_av += btCross(c.m_nodes[i]->m_x-c.m_com,v);
+ }
+ }
+ c.m_lv=c.m_imass*c.m_lv*(1-c.m_ldamping);
+ c.m_av=c.m_invwi*c.m_av*(1-c.m_adamping);
+ c.m_vimpulses[0] =
+ c.m_vimpulses[1] = btVector3(0,0,0);
+ c.m_dimpulses[0] =
+ c.m_dimpulses[1] = btVector3(0,0,0);
+ c.m_nvimpulses = 0;
+ c.m_ndimpulses = 0;
+ /* Matching */
+ if(c.m_matching>0)
+ {
+ for(int j=0;j<c.m_nodes.size();++j)
+ {
+ Node& n=*c.m_nodes[j];
+ const btVector3 x=c.m_framexform*c.m_framerefs[j];
+ n.m_x=Lerp(n.m_x,x,c.m_matching);
+ }
+ }
+ /* Dbvt */
+ if(c.m_collide)
+ {
+ btVector3 mi=c.m_nodes[0]->m_x;
+ btVector3 mx=mi;
+ for(int j=1;j<n;++j)
+ {
+ mi.setMin(c.m_nodes[j]->m_x);
+ mx.setMax(c.m_nodes[j]->m_x);
+ }
+ ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds=btDbvtVolume::FromMM(mi,mx);
+ if(c.m_leaf)
+ m_cdbvt.update(c.m_leaf,bounds,c.m_lv*m_sst.sdt*3,m_sst.radmrg);
+ else
+ c.m_leaf=m_cdbvt.insert(bounds,&c);
+ }
+ }
+ }
+
+
+}
+
+
+
+
+//
+void btSoftBody::cleanupClusters()
+{
+ for(int i=0;i<m_joints.size();++i)
+ {
+ m_joints[i]->Terminate(m_sst.sdt);
+ if(m_joints[i]->m_delete)
+ {
+ btAlignedFree(m_joints[i]);
+ m_joints.remove(m_joints[i--]);
+ }
+ }
+}
+
+//
+void btSoftBody::prepareClusters(int iterations)
+{
+ for(int i=0;i<m_joints.size();++i)
+ {
+ m_joints[i]->Prepare(m_sst.sdt,iterations);
+ }
+}
+
+
+//
+void btSoftBody::solveClusters(btScalar sor)
+{
+ for(int i=0,ni=m_joints.size();i<ni;++i)
+ {
+ m_joints[i]->Solve(m_sst.sdt,sor);
+ }
+}
+
+//
+void btSoftBody::applyClusters(bool drift)
+{
+ BT_PROFILE("ApplyClusters");
+// const btScalar f0=m_sst.sdt;
+ //const btScalar f1=f0/2;
+ btAlignedObjectArray<btVector3> deltas;
+ btAlignedObjectArray<btScalar> weights;
+ deltas.resize(m_nodes.size(),btVector3(0,0,0));
+ weights.resize(m_nodes.size(),0);
+ int i;
+
+ if(drift)
+ {
+ for(i=0;i<m_clusters.size();++i)
+ {
+ Cluster& c=*m_clusters[i];
+ if(c.m_ndimpulses)
+ {
+ c.m_dimpulses[0]/=(btScalar)c.m_ndimpulses;
+ c.m_dimpulses[1]/=(btScalar)c.m_ndimpulses;
+ }
+ }
+ }
+
+ for(i=0;i<m_clusters.size();++i)
+ {
+ Cluster& c=*m_clusters[i];
+ if(0<(drift?c.m_ndimpulses:c.m_nvimpulses))
+ {
+ const btVector3 v=(drift?c.m_dimpulses[0]:c.m_vimpulses[0])*m_sst.sdt;
+ const btVector3 w=(drift?c.m_dimpulses[1]:c.m_vimpulses[1])*m_sst.sdt;
+ for(int j=0;j<c.m_nodes.size();++j)
+ {
+ const int idx=int(c.m_nodes[j]-&m_nodes[0]);
+ const btVector3& x=c.m_nodes[j]->m_x;
+ const btScalar q=c.m_masses[j];
+ deltas[idx] += (v+btCross(w,x-c.m_com))*q;
+ weights[idx] += q;
+ }
+ }
+ }
+ for(i=0;i<deltas.size();++i)
+ {
+ if(weights[i]>0)
+ {
+ m_nodes[i].m_x+=deltas[i]/weights[i];
+ }
+ }
+}
+
+//
+void btSoftBody::dampClusters()
+{
+ int i;
+
+ for(i=0;i<m_clusters.size();++i)
+ {
+ Cluster& c=*m_clusters[i];
+ if(c.m_ndamping>0)
+ {
+ for(int j=0;j<c.m_nodes.size();++j)
+ {
+ Node& n=*c.m_nodes[j];
+ if(n.m_im>0)
+ {
+ const btVector3 vx=c.m_lv+btCross(c.m_av,c.m_nodes[j]->m_q-c.m_com);
+ if(vx.length2()<=n.m_v.length2())
+ {
+ n.m_v += c.m_ndamping*(vx-n.m_v);
+ }
+ }
+ }
+ }
+ }
+}
+
+//
+void btSoftBody::Joint::Prepare(btScalar dt,int)
+{
+ m_bodies[0].activate();
+ m_bodies[1].activate();
+}
+
+//
+void btSoftBody::LJoint::Prepare(btScalar dt,int iterations)
+{
+ static const btScalar maxdrift=4;
+ Joint::Prepare(dt,iterations);
+ m_rpos[0] = m_bodies[0].xform()*m_refs[0];
+ m_rpos[1] = m_bodies[1].xform()*m_refs[1];
+ m_drift = Clamp(m_rpos[0]-m_rpos[1],maxdrift)*m_erp/dt;
+ m_rpos[0] -= m_bodies[0].xform().getOrigin();
+ m_rpos[1] -= m_bodies[1].xform().getOrigin();
+ m_massmatrix = ImpulseMatrix( m_bodies[0].invMass(),m_bodies[0].invWorldInertia(),m_rpos[0],
+ m_bodies[1].invMass(),m_bodies[1].invWorldInertia(),m_rpos[1]);
+ if(m_split>0)
+ {
+ m_sdrift = m_massmatrix*(m_drift*m_split);
+ m_drift *= 1-m_split;
+ }
+ m_drift /=(btScalar)iterations;
+}
+
+//
+void btSoftBody::LJoint::Solve(btScalar dt,btScalar sor)
+{
+ const btVector3 va=m_bodies[0].velocity(m_rpos[0]);
+ const btVector3 vb=m_bodies[1].velocity(m_rpos[1]);
+ const btVector3 vr=va-vb;
+ btSoftBody::Impulse impulse;
+ impulse.m_asVelocity = 1;
+ impulse.m_velocity = m_massmatrix*(m_drift+vr*m_cfm)*sor;
+ m_bodies[0].applyImpulse(-impulse,m_rpos[0]);
+ m_bodies[1].applyImpulse( impulse,m_rpos[1]);
+}
+
+//
+void btSoftBody::LJoint::Terminate(btScalar dt)
+{
+ if(m_split>0)
+ {
+ m_bodies[0].applyDImpulse(-m_sdrift,m_rpos[0]);
+ m_bodies[1].applyDImpulse( m_sdrift,m_rpos[1]);
+ }
+}
+
+//
+void btSoftBody::AJoint::Prepare(btScalar dt,int iterations)
+{
+ static const btScalar maxdrift=SIMD_PI/16;
+ m_icontrol->Prepare(this);
+ Joint::Prepare(dt,iterations);
+ m_axis[0] = m_bodies[0].xform().getBasis()*m_refs[0];
+ m_axis[1] = m_bodies[1].xform().getBasis()*m_refs[1];
+ m_drift = NormalizeAny(btCross(m_axis[1],m_axis[0]));
+ m_drift *= btMin(maxdrift,btAcos(Clamp<btScalar>(btDot(m_axis[0],m_axis[1]),-1,+1)));
+ m_drift *= m_erp/dt;
+ m_massmatrix= AngularImpulseMatrix(m_bodies[0].invWorldInertia(),m_bodies[1].invWorldInertia());
+ if(m_split>0)
+ {
+ m_sdrift = m_massmatrix*(m_drift*m_split);
+ m_drift *= 1-m_split;
+ }
+ m_drift /=(btScalar)iterations;
+}
+
+//
+void btSoftBody::AJoint::Solve(btScalar dt,btScalar sor)
+{
+ const btVector3 va=m_bodies[0].angularVelocity();
+ const btVector3 vb=m_bodies[1].angularVelocity();
+ const btVector3 vr=va-vb;
+ const btScalar sp=btDot(vr,m_axis[0]);
+ const btVector3 vc=vr-m_axis[0]*m_icontrol->Speed(this,sp);
+ btSoftBody::Impulse impulse;
+ impulse.m_asVelocity = 1;
+ impulse.m_velocity = m_massmatrix*(m_drift+vc*m_cfm)*sor;
+ m_bodies[0].applyAImpulse(-impulse);
+ m_bodies[1].applyAImpulse( impulse);
+}
+
+//
+void btSoftBody::AJoint::Terminate(btScalar dt)
+{
+ if(m_split>0)
+ {
+ m_bodies[0].applyDAImpulse(-m_sdrift);
+ m_bodies[1].applyDAImpulse( m_sdrift);
+ }
+}
+
+//
+void btSoftBody::CJoint::Prepare(btScalar dt,int iterations)
+{
+ Joint::Prepare(dt,iterations);
+ const bool dodrift=(m_life==0);
+ m_delete=(++m_life)>m_maxlife;
+ if(dodrift)
+ {
+ m_drift=m_drift*m_erp/dt;
+ if(m_split>0)
+ {
+ m_sdrift = m_massmatrix*(m_drift*m_split);
+ m_drift *= 1-m_split;
+ }
+ m_drift/=(btScalar)iterations;
+ }
+ else
+ {
+ m_drift=m_sdrift=btVector3(0,0,0);
+ }
+}
+
+//
+void btSoftBody::CJoint::Solve(btScalar dt,btScalar sor)
+{
+ const btVector3 va=m_bodies[0].velocity(m_rpos[0]);
+ const btVector3 vb=m_bodies[1].velocity(m_rpos[1]);
+ const btVector3 vrel=va-vb;
+ const btScalar rvac=btDot(vrel,m_normal);
+ btSoftBody::Impulse impulse;
+ impulse.m_asVelocity = 1;
+ impulse.m_velocity = m_drift;
+ if(rvac<0)
+ {
+ const btVector3 iv=m_normal*rvac;
+ const btVector3 fv=vrel-iv;
+ impulse.m_velocity += iv+fv*m_friction;
+ }
+ impulse.m_velocity=m_massmatrix*impulse.m_velocity*sor;
+
+ if (m_bodies[0].m_soft==m_bodies[1].m_soft)
+ {
+ if ((impulse.m_velocity.getX() ==impulse.m_velocity.getX())&&(impulse.m_velocity.getY() ==impulse.m_velocity.getY())&&
+ (impulse.m_velocity.getZ() ==impulse.m_velocity.getZ()))
+ {
+ if (impulse.m_asVelocity)
+ {
+ if (impulse.m_velocity.length() <m_bodies[0].m_soft->m_maxSelfCollisionImpulse)
+ {
+
+ } else
+ {
+ m_bodies[0].applyImpulse(-impulse*m_bodies[0].m_soft->m_selfCollisionImpulseFactor,m_rpos[0]);
+ m_bodies[1].applyImpulse( impulse*m_bodies[0].m_soft->m_selfCollisionImpulseFactor,m_rpos[1]);
+ }
+ }
+ }
+ } else
+ {
+ m_bodies[0].applyImpulse(-impulse,m_rpos[0]);
+ m_bodies[1].applyImpulse( impulse,m_rpos[1]);
+ }
+}
+
+//
+void btSoftBody::CJoint::Terminate(btScalar dt)
+{
+ if(m_split>0)
+ {
+ m_bodies[0].applyDImpulse(-m_sdrift,m_rpos[0]);
+ m_bodies[1].applyDImpulse( m_sdrift,m_rpos[1]);
+ }
+}
+
+//
+void btSoftBody::applyForces()
+{
+
+ BT_PROFILE("SoftBody applyForces");
+// const btScalar dt = m_sst.sdt;
+ const btScalar kLF = m_cfg.kLF;
+ const btScalar kDG = m_cfg.kDG;
+ const btScalar kPR = m_cfg.kPR;
+ const btScalar kVC = m_cfg.kVC;
+ const bool as_lift = kLF>0;
+ const bool as_drag = kDG>0;
+ const bool as_pressure = kPR!=0;
+ const bool as_volume = kVC>0;
+ const bool as_aero = as_lift ||
+ as_drag ;
+ //const bool as_vaero = as_aero &&
+ // (m_cfg.aeromodel < btSoftBody::eAeroModel::F_TwoSided);
+ //const bool as_faero = as_aero &&
+ // (m_cfg.aeromodel >= btSoftBody::eAeroModel::F_TwoSided);
+ const bool use_medium = as_aero;
+ const bool use_volume = as_pressure ||
+ as_volume ;
+ btScalar volume = 0;
+ btScalar ivolumetp = 0;
+ btScalar dvolumetv = 0;
+ btSoftBody::sMedium medium;
+ if(use_volume)
+ {
+ volume = getVolume();
+ ivolumetp = 1/btFabs(volume)*kPR;
+ dvolumetv = (m_pose.m_volume-volume)*kVC;
+ }
+ /* Per vertex forces */
+ int i,ni;
+
+ for(i=0,ni=m_nodes.size();i<ni;++i)
+ {
+ btSoftBody::Node& n=m_nodes[i];
+ if(n.m_im>0)
+ {
+ if(use_medium)
+ {
+ /* Aerodynamics */
+ addAeroForceToNode(m_windVelocity, i);
+ }
+ /* Pressure */
+ if(as_pressure)
+ {
+ n.m_f += n.m_n*(n.m_area*ivolumetp);
+ }
+ /* Volume */
+ if(as_volume)
+ {
+ n.m_f += n.m_n*(n.m_area*dvolumetv);
+ }
+ }
+ }
+
+ /* Per face forces */
+ for(i=0,ni=m_faces.size();i<ni;++i)
+ {
+ // btSoftBody::Face& f=m_faces[i];
+
+ /* Aerodynamics */
+ addAeroForceToFace(m_windVelocity, i);
+ }
+}
+
+//
+void btSoftBody::PSolve_Anchors(btSoftBody* psb,btScalar kst,btScalar ti)
+{
+ BT_PROFILE("PSolve_Anchors");
+ const btScalar kAHR=psb->m_cfg.kAHR*kst;
+ const btScalar dt=psb->m_sst.sdt;
+ for(int i=0,ni=psb->m_anchors.size();i<ni;++i)
+ {
+ const Anchor& a=psb->m_anchors[i];
+ const btTransform& t=a.m_body->getWorldTransform();
+ Node& n=*a.m_node;
+ const btVector3 wa=t*a.m_local;
+ const btVector3 va=a.m_body->getVelocityInLocalPoint(a.m_c1)*dt;
+ const btVector3 vb=n.m_x-n.m_q;
+ const btVector3 vr=(va-vb)+(wa-n.m_x)*kAHR;
+ const btVector3 impulse=a.m_c0*vr*a.m_influence;
+ n.m_x+=impulse*a.m_c2;
+ a.m_body->applyImpulse(-impulse,a.m_c1);
+ }
+}
+
+
+//
+void btSoftBody::PSolve_RContacts(btSoftBody* psb, btScalar kst, btScalar ti)
+{
+ BT_PROFILE("PSolve_RContacts");
+ const btScalar dt = psb->m_sst.sdt;
+ const btScalar mrg = psb->getCollisionShape()->getMargin();
+ btMultiBodyJacobianData jacobianData;
+ for(int i=0,ni=psb->m_rcontacts.size();i<ni;++i)
+ {
+ const RContact& c = psb->m_rcontacts[i];
+ const sCti& cti = c.m_cti;
+ if (cti.m_colObj->hasContactResponse())
+ {
+ btVector3 va(0,0,0);
+ btRigidBody* rigidCol=0;
+ btMultiBodyLinkCollider* multibodyLinkCol=0;
+ btScalar* deltaV;
+
+ if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
+ {
+ rigidCol = (btRigidBody*)btRigidBody::upcast(cti.m_colObj);
+ va = rigidCol ? rigidCol->getVelocityInLocalPoint(c.m_c1)*dt : 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;
+ jacobianData.m_jacobians.resize(ndof);
+ jacobianData.m_deltaVelocitiesUnitImpulse.resize(ndof);
+ btScalar* jac=&jacobianData.m_jacobians[0];
+
+ multibodyLinkCol->m_multiBody->fillContactJacobianMultiDof(multibodyLinkCol->m_link, c.m_node->m_x, cti.m_normal, jac, jacobianData.scratch_r, jacobianData.scratch_v, jacobianData.scratch_m);
+ deltaV = &jacobianData.m_deltaVelocitiesUnitImpulse[0];
+ multibodyLinkCol->m_multiBody->calcAccelerationDeltasMultiDof(&jacobianData.m_jacobians[0],deltaV,jacobianData.scratch_r, jacobianData.scratch_v);
+
+ btScalar vel = 0.0;
+ for (int j = 0; j < ndof ; ++j) {
+ vel += multibodyLinkCol->m_multiBody->getVelocityVector()[j] * jac[j];
+ }
+ va = cti.m_normal*vel*dt;
+ }
+ }
+
+ const btVector3 vb = c.m_node->m_x-c.m_node->m_q;
+ const btVector3 vr = vb-va;
+ const btScalar dn = btDot(vr, cti.m_normal);
+ if(dn<=SIMD_EPSILON)
+ {
+ const btScalar dp = btMin( (btDot(c.m_node->m_x, cti.m_normal) + cti.m_offset), mrg );
+ const btVector3 fv = vr - (cti.m_normal * dn);
+ // c0 is the impulse matrix, c3 is 1 - the friction coefficient or 0, c4 is the contact hardness coefficient
+ const btVector3 impulse = c.m_c0 * ( (vr - (fv * c.m_c3) + (cti.m_normal * (dp * c.m_c4))) * kst );
+ c.m_node->m_x -= impulse * c.m_c2;
+
+ if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
+ {
+ if (rigidCol)
+ rigidCol->applyImpulse(impulse,c.m_c1);
+ }
+ else if (cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
+ {
+ if (multibodyLinkCol)
+ {
+ double multiplier = 0.5;
+ multibodyLinkCol->m_multiBody->applyDeltaVeeMultiDof(deltaV,-impulse.length()*multiplier);
+ }
+ }
+ }
+ }
+ }
+}
+
+//
+void btSoftBody::PSolve_SContacts(btSoftBody* psb,btScalar,btScalar ti)
+{
+ BT_PROFILE("PSolve_SContacts");
+
+ for(int i=0,ni=psb->m_scontacts.size();i<ni;++i)
+ {
+ const SContact& c=psb->m_scontacts[i];
+ const btVector3& nr=c.m_normal;
+ Node& n=*c.m_node;
+ Face& f=*c.m_face;
+ const btVector3 p=BaryEval( f.m_n[0]->m_x,
+ f.m_n[1]->m_x,
+ f.m_n[2]->m_x,
+ c.m_weights);
+ const btVector3 q=BaryEval( f.m_n[0]->m_q,
+ f.m_n[1]->m_q,
+ f.m_n[2]->m_q,
+ c.m_weights);
+ const btVector3 vr=(n.m_x-n.m_q)-(p-q);
+ btVector3 corr(0,0,0);
+ btScalar dot = btDot(vr,nr);
+ if(dot<0)
+ {
+ const btScalar j=c.m_margin-(btDot(nr,n.m_x)-btDot(nr,p));
+ corr+=c.m_normal*j;
+ }
+ corr -= ProjectOnPlane(vr,nr)*c.m_friction;
+ n.m_x += corr*c.m_cfm[0];
+ f.m_n[0]->m_x -= corr*(c.m_cfm[1]*c.m_weights.x());
+ f.m_n[1]->m_x -= corr*(c.m_cfm[1]*c.m_weights.y());
+ f.m_n[2]->m_x -= corr*(c.m_cfm[1]*c.m_weights.z());
+ }
+}
+
+//
+void btSoftBody::PSolve_Links(btSoftBody* psb,btScalar kst,btScalar ti)
+{
+BT_PROFILE("PSolve_Links");
+ for(int i=0,ni=psb->m_links.size();i<ni;++i)
+ {
+ Link& l=psb->m_links[i];
+ if(l.m_c0>0)
+ {
+ Node& a=*l.m_n[0];
+ Node& b=*l.m_n[1];
+ const btVector3 del=b.m_x-a.m_x;
+ const btScalar len=del.length2();
+ if (l.m_c1+len > SIMD_EPSILON)
+ {
+ const btScalar k=((l.m_c1-len)/(l.m_c0*(l.m_c1+len)))*kst;
+ a.m_x-=del*(k*a.m_im);
+ b.m_x+=del*(k*b.m_im);
+ }
+ }
+ }
+}
+
+//
+void btSoftBody::VSolve_Links(btSoftBody* psb,btScalar kst)
+{
+ BT_PROFILE("VSolve_Links");
+ for(int i=0,ni=psb->m_links.size();i<ni;++i)
+ {
+ Link& l=psb->m_links[i];
+ Node** n=l.m_n;
+ const btScalar j=-btDot(l.m_c3,n[0]->m_v-n[1]->m_v)*l.m_c2*kst;
+ n[0]->m_v+= l.m_c3*(j*n[0]->m_im);
+ n[1]->m_v-= l.m_c3*(j*n[1]->m_im);
+ }
+}
+
+//
+btSoftBody::psolver_t btSoftBody::getSolver(ePSolver::_ solver)
+{
+ switch(solver)
+ {
+ case ePSolver::Anchors:
+ return(&btSoftBody::PSolve_Anchors);
+ case ePSolver::Linear:
+ return(&btSoftBody::PSolve_Links);
+ case ePSolver::RContacts:
+ return(&btSoftBody::PSolve_RContacts);
+ case ePSolver::SContacts:
+ return(&btSoftBody::PSolve_SContacts);
+ default:
+ {
+ }
+ }
+ return(0);
+}
+
+//
+btSoftBody::vsolver_t btSoftBody::getSolver(eVSolver::_ solver)
+{
+ switch(solver)
+ {
+ case eVSolver::Linear: return(&btSoftBody::VSolve_Links);
+ default:
+ {
+ }
+ }
+ return(0);
+}
+
+//
+void btSoftBody::defaultCollisionHandler(const btCollisionObjectWrapper* pcoWrap)
+{
+
+ switch(m_cfg.collisions&fCollision::RVSmask)
+ {
+ case fCollision::SDF_RS:
+ {
+ btSoftColliders::CollideSDF_RS docollide;
+ btRigidBody* prb1=(btRigidBody*) btRigidBody::upcast(pcoWrap->getCollisionObject());
+ btTransform wtr=pcoWrap->getWorldTransform();
+
+ const btTransform ctr=pcoWrap->getWorldTransform();
+ const btScalar timemargin=(wtr.getOrigin()-ctr.getOrigin()).length();
+ const btScalar basemargin=getCollisionShape()->getMargin();
+ btVector3 mins;
+ btVector3 maxs;
+ ATTRIBUTE_ALIGNED16(btDbvtVolume) volume;
+ pcoWrap->getCollisionShape()->getAabb( pcoWrap->getWorldTransform(),
+ mins,
+ maxs);
+ volume=btDbvtVolume::FromMM(mins,maxs);
+ volume.Expand(btVector3(basemargin,basemargin,basemargin));
+ docollide.psb = this;
+ docollide.m_colObj1Wrap = pcoWrap;
+ docollide.m_rigidBody = prb1;
+
+ docollide.dynmargin = basemargin+timemargin;
+ docollide.stamargin = basemargin;
+ m_ndbvt.collideTV(m_ndbvt.m_root,volume,docollide);
+ }
+ break;
+ case fCollision::CL_RS:
+ {
+ btSoftColliders::CollideCL_RS collider;
+ collider.ProcessColObj(this,pcoWrap);
+ }
+ break;
+ }
+}
+
+//
+void btSoftBody::defaultCollisionHandler(btSoftBody* psb)
+{
+ const int cf=m_cfg.collisions&psb->m_cfg.collisions;
+ switch(cf&fCollision::SVSmask)
+ {
+ case fCollision::CL_SS:
+ {
+
+ //support self-collision if CL_SELF flag set
+ if (this!=psb || psb->m_cfg.collisions&fCollision::CL_SELF)
+ {
+ btSoftColliders::CollideCL_SS docollide;
+ docollide.ProcessSoftSoft(this,psb);
+ }
+
+ }
+ break;
+ case fCollision::VF_SS:
+ {
+ //only self-collision for Cluster, not Vertex-Face yet
+ if (this!=psb)
+ {
+ btSoftColliders::CollideVF_SS docollide;
+ /* common */
+ docollide.mrg= getCollisionShape()->getMargin()+
+ psb->getCollisionShape()->getMargin();
+ /* psb0 nodes vs psb1 faces */
+ 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 */
+ 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);
+ }
+ }
+ break;
+ default:
+ {
+
+ }
+ }
+}
+
+
+
+void btSoftBody::setWindVelocity( const btVector3 &velocity )
+{
+ m_windVelocity = velocity;
+}
+
+
+const btVector3& btSoftBody::getWindVelocity()
+{
+ return m_windVelocity;
+}
+
+
+
+int btSoftBody::calculateSerializeBufferSize() const
+{
+ int sz = sizeof(btSoftBodyData);
+ return sz;
+}
+
+ ///fills the dataBuffer and returns the struct name (and 0 on failure)
+const char* btSoftBody::serialize(void* dataBuffer, class btSerializer* serializer) const
+{
+ btSoftBodyData* sbd = (btSoftBodyData*) dataBuffer;
+
+ btCollisionObject::serialize(&sbd->m_collisionObjectData, serializer);
+
+ btHashMap<btHashPtr,int> m_nodeIndexMap;
+
+ sbd->m_numMaterials = m_materials.size();
+ sbd->m_materials = sbd->m_numMaterials? (SoftBodyMaterialData**) serializer->getUniquePointer((void*)&m_materials): 0;
+
+ if (sbd->m_materials)
+ {
+ int sz = sizeof(SoftBodyMaterialData*);
+ int numElem = sbd->m_numMaterials;
+ btChunk* chunk = serializer->allocate(sz,numElem);
+ //SoftBodyMaterialData** memPtr = chunk->m_oldPtr;
+ SoftBodyMaterialData** memPtr = (SoftBodyMaterialData**)chunk->m_oldPtr;
+ for (int i=0;i<numElem;i++,memPtr++)
+ {
+ btSoftBody::Material* mat = m_materials[i];
+ *memPtr = mat ? (SoftBodyMaterialData*)serializer->getUniquePointer((void*)mat) : 0;
+ if (!serializer->findPointer(mat))
+ {
+ //serialize it here
+ btChunk* chunk = serializer->allocate(sizeof(SoftBodyMaterialData),1);
+ SoftBodyMaterialData* memPtr = (SoftBodyMaterialData*)chunk->m_oldPtr;
+ memPtr->m_flags = mat->m_flags;
+ memPtr->m_angularStiffness = mat->m_kAST;
+ memPtr->m_linearStiffness = mat->m_kLST;
+ memPtr->m_volumeStiffness = mat->m_kVST;
+ serializer->finalizeChunk(chunk,"SoftBodyMaterialData",BT_SBMATERIAL_CODE,mat);
+ }
+ }
+ serializer->finalizeChunk(chunk,"SoftBodyMaterialData",BT_ARRAY_CODE,(void*) &m_materials);
+ }
+
+
+
+
+ sbd->m_numNodes = m_nodes.size();
+ sbd->m_nodes = sbd->m_numNodes ? (SoftBodyNodeData*)serializer->getUniquePointer((void*)&m_nodes): 0;
+ if (sbd->m_nodes)
+ {
+ int sz = sizeof(SoftBodyNodeData);
+ int numElem = sbd->m_numNodes;
+ btChunk* chunk = serializer->allocate(sz,numElem);
+ SoftBodyNodeData* memPtr = (SoftBodyNodeData*)chunk->m_oldPtr;
+ for (int i=0;i<numElem;i++,memPtr++)
+ {
+ m_nodes[i].m_f.serializeFloat( memPtr->m_accumulatedForce);
+ memPtr->m_area = m_nodes[i].m_area;
+ memPtr->m_attach = m_nodes[i].m_battach;
+ memPtr->m_inverseMass = m_nodes[i].m_im;
+ memPtr->m_material = m_nodes[i].m_material? (SoftBodyMaterialData*)serializer->getUniquePointer((void*) m_nodes[i].m_material):0;
+ m_nodes[i].m_n.serializeFloat(memPtr->m_normal);
+ m_nodes[i].m_x.serializeFloat(memPtr->m_position);
+ m_nodes[i].m_q.serializeFloat(memPtr->m_previousPosition);
+ m_nodes[i].m_v.serializeFloat(memPtr->m_velocity);
+ m_nodeIndexMap.insert(&m_nodes[i],i);
+ }
+ serializer->finalizeChunk(chunk,"SoftBodyNodeData",BT_SBNODE_CODE,(void*) &m_nodes);
+ }
+
+ sbd->m_numLinks = m_links.size();
+ sbd->m_links = sbd->m_numLinks? (SoftBodyLinkData*) serializer->getUniquePointer((void*)&m_links[0]):0;
+ if (sbd->m_links)
+ {
+ int sz = sizeof(SoftBodyLinkData);
+ int numElem = sbd->m_numLinks;
+ btChunk* chunk = serializer->allocate(sz,numElem);
+ SoftBodyLinkData* memPtr = (SoftBodyLinkData*)chunk->m_oldPtr;
+ for (int i=0;i<numElem;i++,memPtr++)
+ {
+ memPtr->m_bbending = m_links[i].m_bbending;
+ memPtr->m_material = m_links[i].m_material? (SoftBodyMaterialData*)serializer->getUniquePointer((void*) m_links[i].m_material):0;
+ memPtr->m_nodeIndices[0] = m_links[i].m_n[0] ? m_links[i].m_n[0] - &m_nodes[0]: -1;
+ memPtr->m_nodeIndices[1] = m_links[i].m_n[1] ? m_links[i].m_n[1] - &m_nodes[0]: -1;
+ btAssert(memPtr->m_nodeIndices[0]<m_nodes.size());
+ btAssert(memPtr->m_nodeIndices[1]<m_nodes.size());
+ memPtr->m_restLength = m_links[i].m_rl;
+ }
+ serializer->finalizeChunk(chunk,"SoftBodyLinkData",BT_ARRAY_CODE,(void*) &m_links[0]);
+
+ }
+
+
+ sbd->m_numFaces = m_faces.size();
+ sbd->m_faces = sbd->m_numFaces? (SoftBodyFaceData*) serializer->getUniquePointer((void*)&m_faces[0]):0;
+ if (sbd->m_faces)
+ {
+ int sz = sizeof(SoftBodyFaceData);
+ int numElem = sbd->m_numFaces;
+ btChunk* chunk = serializer->allocate(sz,numElem);
+ SoftBodyFaceData* memPtr = (SoftBodyFaceData*)chunk->m_oldPtr;
+ for (int i=0;i<numElem;i++,memPtr++)
+ {
+ memPtr->m_material = m_faces[i].m_material ? (SoftBodyMaterialData*) serializer->getUniquePointer((void*)m_faces[i].m_material): 0;
+ m_faces[i].m_normal.serializeFloat( memPtr->m_normal);
+ for (int j=0;j<3;j++)
+ {
+ memPtr->m_nodeIndices[j] = m_faces[i].m_n[j]? m_faces[i].m_n[j] - &m_nodes[0]: -1;
+ }
+ memPtr->m_restArea = m_faces[i].m_ra;
+ }
+ serializer->finalizeChunk(chunk,"SoftBodyFaceData",BT_ARRAY_CODE,(void*) &m_faces[0]);
+ }
+
+
+ sbd->m_numTetrahedra = m_tetras.size();
+ sbd->m_tetrahedra = sbd->m_numTetrahedra ? (SoftBodyTetraData*) serializer->getUniquePointer((void*)&m_tetras[0]):0;
+ if (sbd->m_tetrahedra)
+ {
+ int sz = sizeof(SoftBodyTetraData);
+ int numElem = sbd->m_numTetrahedra;
+ btChunk* chunk = serializer->allocate(sz,numElem);
+ SoftBodyTetraData* memPtr = (SoftBodyTetraData*)chunk->m_oldPtr;
+ for (int i=0;i<numElem;i++,memPtr++)
+ {
+ 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_c1 = m_tetras[i].m_c1;
+ memPtr->m_c2 = m_tetras[i].m_c2;
+ memPtr->m_material = m_tetras[i].m_material ? (SoftBodyMaterialData*)serializer->getUniquePointer((void*) m_tetras[i].m_material): 0;
+ memPtr->m_restVolume = m_tetras[i].m_rv;
+ }
+ serializer->finalizeChunk(chunk,"SoftBodyTetraData",BT_ARRAY_CODE,(void*) &m_tetras[0]);
+ }
+
+ sbd->m_numAnchors = m_anchors.size();
+ sbd->m_anchors = sbd->m_numAnchors ? (SoftRigidAnchorData*) serializer->getUniquePointer((void*)&m_anchors[0]):0;
+ if (sbd->m_anchors)
+ {
+ int sz = sizeof(SoftRigidAnchorData);
+ int numElem = sbd->m_numAnchors;
+ btChunk* chunk = serializer->allocate(sz,numElem);
+ SoftRigidAnchorData* memPtr = (SoftRigidAnchorData*)chunk->m_oldPtr;
+ for (int i=0;i<numElem;i++,memPtr++)
+ {
+ m_anchors[i].m_c0.serializeFloat(memPtr->m_c0);
+ m_anchors[i].m_c1.serializeFloat(memPtr->m_c1);
+ memPtr->m_c2 = m_anchors[i].m_c2;
+ m_anchors[i].m_local.serializeFloat(memPtr->m_localFrame);
+ memPtr->m_nodeIndex = m_anchors[i].m_node? m_anchors[i].m_node-&m_nodes[0]: -1;
+
+ memPtr->m_rigidBody = m_anchors[i].m_body? (btRigidBodyData*) serializer->getUniquePointer((void*)m_anchors[i].m_body): 0;
+ btAssert(memPtr->m_nodeIndex < m_nodes.size());
+ }
+ serializer->finalizeChunk(chunk,"SoftRigidAnchorData",BT_ARRAY_CODE,(void*) &m_anchors[0]);
+ }
+
+
+ sbd->m_config.m_dynamicFriction = m_cfg.kDF;
+ sbd->m_config.m_baumgarte = m_cfg.kVCF;
+ sbd->m_config.m_pressure = m_cfg.kPR;
+ sbd->m_config.m_aeroModel = this->m_cfg.aeromodel;
+ sbd->m_config.m_lift = m_cfg.kLF;
+ sbd->m_config.m_drag = m_cfg.kDG;
+ sbd->m_config.m_positionIterations = m_cfg.piterations;
+ sbd->m_config.m_driftIterations = m_cfg.diterations;
+ sbd->m_config.m_clusterIterations = m_cfg.citerations;
+ sbd->m_config.m_velocityIterations = m_cfg.viterations;
+ sbd->m_config.m_maxVolume = m_cfg.maxvolume;
+ sbd->m_config.m_damping = m_cfg.kDP;
+ sbd->m_config.m_poseMatch = m_cfg.kMT;
+ sbd->m_config.m_collisionFlags = m_cfg.collisions;
+ sbd->m_config.m_volume = m_cfg.kVC;
+ sbd->m_config.m_rigidContactHardness = m_cfg.kCHR;
+ sbd->m_config.m_kineticContactHardness = m_cfg.kKHR;
+ sbd->m_config.m_softContactHardness = m_cfg.kSHR;
+ sbd->m_config.m_anchorHardness = m_cfg.kAHR;
+ sbd->m_config.m_timeScale = m_cfg.timescale;
+ sbd->m_config.m_maxVolume = m_cfg.maxvolume;
+ sbd->m_config.m_softRigidClusterHardness = m_cfg.kSRHR_CL;
+ sbd->m_config.m_softKineticClusterHardness = m_cfg.kSKHR_CL;
+ sbd->m_config.m_softSoftClusterHardness = m_cfg.kSSHR_CL;
+ sbd->m_config.m_softRigidClusterImpulseSplit = m_cfg.kSR_SPLT_CL;
+ sbd->m_config.m_softKineticClusterImpulseSplit = m_cfg.kSK_SPLT_CL;
+ sbd->m_config.m_softSoftClusterImpulseSplit = m_cfg.kSS_SPLT_CL;
+
+ //pose for shape matching
+ {
+ sbd->m_pose = (SoftBodyPoseData*)serializer->getUniquePointer((void*)&m_pose);
+
+ int sz = sizeof(SoftBodyPoseData);
+ btChunk* chunk = serializer->allocate(sz,1);
+ SoftBodyPoseData* memPtr = (SoftBodyPoseData*)chunk->m_oldPtr;
+
+ m_pose.m_aqq.serializeFloat(memPtr->m_aqq);
+ memPtr->m_bframe = m_pose.m_bframe;
+ memPtr->m_bvolume = m_pose.m_bvolume;
+ m_pose.m_com.serializeFloat(memPtr->m_com);
+
+ memPtr->m_numPositions = m_pose.m_pos.size();
+ memPtr->m_positions = memPtr->m_numPositions ? (btVector3FloatData*)serializer->getUniquePointer((void*)&m_pose.m_pos[0]): 0;
+ if (memPtr->m_numPositions)
+ {
+ int numElem = memPtr->m_numPositions;
+ int sz = sizeof(btVector3Data);
+ btChunk* chunk = serializer->allocate(sz,numElem);
+ btVector3FloatData* memPtr = (btVector3FloatData*)chunk->m_oldPtr;
+ for (int i=0;i<numElem;i++,memPtr++)
+ {
+ m_pose.m_pos[i].serializeFloat(*memPtr);
+ }
+ serializer->finalizeChunk(chunk,"btVector3FloatData",BT_ARRAY_CODE,(void*)&m_pose.m_pos[0]);
+ }
+ memPtr->m_restVolume = m_pose.m_volume;
+ m_pose.m_rot.serializeFloat(memPtr->m_rot);
+ m_pose.m_scl.serializeFloat(memPtr->m_scale);
+
+ memPtr->m_numWeigts = m_pose.m_wgh.size();
+ memPtr->m_weights = memPtr->m_numWeigts? (float*) serializer->getUniquePointer((void*) &m_pose.m_wgh[0]) : 0;
+ if (memPtr->m_numWeigts)
+ {
+
+ int numElem = memPtr->m_numWeigts;
+ int sz = sizeof(float);
+ btChunk* chunk = serializer->allocate(sz,numElem);
+ float* memPtr = (float*) chunk->m_oldPtr;
+ for (int i=0;i<numElem;i++,memPtr++)
+ {
+ *memPtr = m_pose.m_wgh[i];
+ }
+ serializer->finalizeChunk(chunk,"float",BT_ARRAY_CODE,(void*)&m_pose.m_wgh[0]);
+ }
+
+ serializer->finalizeChunk(chunk,"SoftBodyPoseData",BT_ARRAY_CODE,(void*)&m_pose);
+ }
+
+ //clusters for convex-cluster collision detection
+
+ sbd->m_numClusters = m_clusters.size();
+ sbd->m_clusters = sbd->m_numClusters? (SoftBodyClusterData*) serializer->getUniquePointer((void*)m_clusters[0]) : 0;
+ if (sbd->m_numClusters)
+ {
+ int numElem = sbd->m_numClusters;
+ int sz = sizeof(SoftBodyClusterData);
+ btChunk* chunk = serializer->allocate(sz,numElem);
+ SoftBodyClusterData* memPtr = (SoftBodyClusterData*) chunk->m_oldPtr;
+ for (int i=0;i<numElem;i++,memPtr++)
+ {
+ memPtr->m_adamping= m_clusters[i]->m_adamping;
+ m_clusters[i]->m_av.serializeFloat(memPtr->m_av);
+ memPtr->m_clusterIndex = m_clusters[i]->m_clusterIndex;
+ memPtr->m_collide = m_clusters[i]->m_collide;
+ m_clusters[i]->m_com.serializeFloat(memPtr->m_com);
+ memPtr->m_containsAnchor = m_clusters[i]->m_containsAnchor;
+ m_clusters[i]->m_dimpulses[0].serializeFloat(memPtr->m_dimpulses[0]);
+ m_clusters[i]->m_dimpulses[1].serializeFloat(memPtr->m_dimpulses[1]);
+ m_clusters[i]->m_framexform.serializeFloat(memPtr->m_framexform);
+ memPtr->m_idmass = m_clusters[i]->m_idmass;
+ memPtr->m_imass = m_clusters[i]->m_imass;
+ m_clusters[i]->m_invwi.serializeFloat(memPtr->m_invwi);
+ memPtr->m_ldamping = m_clusters[i]->m_ldamping;
+ m_clusters[i]->m_locii.serializeFloat(memPtr->m_locii);
+ m_clusters[i]->m_lv.serializeFloat(memPtr->m_lv);
+ memPtr->m_matching = m_clusters[i]->m_matching;
+ memPtr->m_maxSelfCollisionImpulse = m_clusters[i]->m_maxSelfCollisionImpulse;
+ memPtr->m_ndamping = m_clusters[i]->m_ndamping;
+ memPtr->m_ldamping = m_clusters[i]->m_ldamping;
+ memPtr->m_adamping = m_clusters[i]->m_adamping;
+ memPtr->m_selfCollisionImpulseFactor = m_clusters[i]->m_selfCollisionImpulseFactor;
+
+ memPtr->m_numFrameRefs = m_clusters[i]->m_framerefs.size();
+ memPtr->m_numMasses = m_clusters[i]->m_masses.size();
+ memPtr->m_numNodes = m_clusters[i]->m_nodes.size();
+
+ memPtr->m_nvimpulses = m_clusters[i]->m_nvimpulses;
+ m_clusters[i]->m_vimpulses[0].serializeFloat(memPtr->m_vimpulses[0]);
+ m_clusters[i]->m_vimpulses[1].serializeFloat(memPtr->m_vimpulses[1]);
+ memPtr->m_ndimpulses = m_clusters[i]->m_ndimpulses;
+
+
+
+ memPtr->m_framerefs = memPtr->m_numFrameRefs? (btVector3FloatData*)serializer->getUniquePointer((void*)&m_clusters[i]->m_framerefs[0]) : 0;
+ if (memPtr->m_framerefs)
+ {
+ int numElem = memPtr->m_numFrameRefs;
+ int sz = sizeof(btVector3FloatData);
+ btChunk* chunk = serializer->allocate(sz,numElem);
+ btVector3FloatData* memPtr = (btVector3FloatData*) chunk->m_oldPtr;
+ for (int j=0;j<numElem;j++,memPtr++)
+ {
+ m_clusters[i]->m_framerefs[j].serializeFloat(*memPtr);
+ }
+ serializer->finalizeChunk(chunk,"btVector3FloatData",BT_ARRAY_CODE,(void*)&m_clusters[i]->m_framerefs[0]);
+ }
+
+ memPtr->m_masses = memPtr->m_numMasses ? (float*) serializer->getUniquePointer((void*)&m_clusters[i]->m_masses[0]): 0;
+ if (memPtr->m_masses)
+ {
+ int numElem = memPtr->m_numMasses;
+ int sz = sizeof(float);
+ btChunk* chunk = serializer->allocate(sz,numElem);
+ float* memPtr = (float*) chunk->m_oldPtr;
+ for (int j=0;j<numElem;j++,memPtr++)
+ {
+ *memPtr = m_clusters[i]->m_masses[j];
+ }
+ serializer->finalizeChunk(chunk,"float",BT_ARRAY_CODE,(void*)&m_clusters[i]->m_masses[0]);
+ }
+
+ memPtr->m_nodeIndices = memPtr->m_numNodes ? (int*) serializer->getUniquePointer((void*) &m_clusters[i]->m_nodes) : 0;
+ if (memPtr->m_nodeIndices )
+ {
+ int numElem = memPtr->m_numMasses;
+ int sz = sizeof(int);
+ btChunk* chunk = serializer->allocate(sz,numElem);
+ int* memPtr = (int*) chunk->m_oldPtr;
+ for (int j=0;j<numElem;j++,memPtr++)
+ {
+ int* indexPtr = m_nodeIndexMap.find(m_clusters[i]->m_nodes[j]);
+ btAssert(indexPtr);
+ *memPtr = *indexPtr;
+ }
+ serializer->finalizeChunk(chunk,"int",BT_ARRAY_CODE,(void*)&m_clusters[i]->m_nodes);
+ }
+ }
+ serializer->finalizeChunk(chunk,"SoftBodyClusterData",BT_ARRAY_CODE,(void*)m_clusters[0]);
+
+ }
+
+
+
+ sbd->m_numJoints = m_joints.size();
+ sbd->m_joints = m_joints.size()? (btSoftBodyJointData*) serializer->getUniquePointer((void*)&m_joints[0]) : 0;
+
+ if (sbd->m_joints)
+ {
+ int sz = sizeof(btSoftBodyJointData);
+ int numElem = m_joints.size();
+ btChunk* chunk = serializer->allocate(sz,numElem);
+ btSoftBodyJointData* memPtr = (btSoftBodyJointData*)chunk->m_oldPtr;
+
+ for (int i=0;i<numElem;i++,memPtr++)
+ {
+ memPtr->m_jointType = (int)m_joints[i]->Type();
+ m_joints[i]->m_refs[0].serializeFloat(memPtr->m_refs[0]);
+ m_joints[i]->m_refs[1].serializeFloat(memPtr->m_refs[1]);
+ memPtr->m_cfm = m_joints[i]->m_cfm;
+ memPtr->m_erp = float(m_joints[i]->m_erp);
+ memPtr->m_split = float(m_joints[i]->m_split);
+ memPtr->m_delete = m_joints[i]->m_delete;
+
+ for (int j=0;j<4;j++)
+ {
+ memPtr->m_relPosition[0].m_floats[j] = 0.f;
+ memPtr->m_relPosition[1].m_floats[j] = 0.f;
+ }
+ memPtr->m_bodyA = 0;
+ memPtr->m_bodyB = 0;
+ if (m_joints[i]->m_bodies[0].m_soft)
+ {
+ memPtr->m_bodyAtype = BT_JOINT_SOFT_BODY_CLUSTER;
+ memPtr->m_bodyA = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[0].m_soft);
+ }
+ if (m_joints[i]->m_bodies[0].m_collisionObject)
+ {
+ memPtr->m_bodyAtype = BT_JOINT_COLLISION_OBJECT;
+ memPtr->m_bodyA = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[0].m_collisionObject);
+ }
+ if (m_joints[i]->m_bodies[0].m_rigid)
+ {
+ memPtr->m_bodyAtype = BT_JOINT_RIGID_BODY;
+ memPtr->m_bodyA = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[0].m_rigid);
+ }
+
+ if (m_joints[i]->m_bodies[1].m_soft)
+ {
+ memPtr->m_bodyBtype = BT_JOINT_SOFT_BODY_CLUSTER;
+ memPtr->m_bodyB = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[1].m_soft);
+ }
+ if (m_joints[i]->m_bodies[1].m_collisionObject)
+ {
+ memPtr->m_bodyBtype = BT_JOINT_COLLISION_OBJECT;
+ memPtr->m_bodyB = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[1].m_collisionObject);
+ }
+ if (m_joints[i]->m_bodies[1].m_rigid)
+ {
+ memPtr->m_bodyBtype = BT_JOINT_RIGID_BODY;
+ memPtr->m_bodyB = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[1].m_rigid);
+ }
+ }
+ serializer->finalizeChunk(chunk,"btSoftBodyJointData",BT_ARRAY_CODE,(void*) &m_joints[0]);
+ }
+
+
+ return btSoftBodyDataName;
+}
+
diff --git a/thirdparty/bullet/src/BulletSoftBody/btSoftBody.h b/thirdparty/bullet/src/BulletSoftBody/btSoftBody.h
new file mode 100644
index 0000000000..ada0dfd1a5
--- /dev/null
+++ b/thirdparty/bullet/src/BulletSoftBody/btSoftBody.h
@@ -0,0 +1,1005 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+///btSoftBody implementation by Nathanael Presson
+
+#ifndef _BT_SOFT_BODY_H
+#define _BT_SOFT_BODY_H
+
+#include "LinearMath/btAlignedObjectArray.h"
+#include "LinearMath/btTransform.h"
+#include "LinearMath/btIDebugDraw.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+
+#include "BulletCollision/CollisionShapes/btConcaveShape.h"
+#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
+#include "btSparseSDF.h"
+#include "BulletCollision/BroadphaseCollision/btDbvt.h"
+
+//#ifdef BT_USE_DOUBLE_PRECISION
+//#define btRigidBodyData btRigidBodyDoubleData
+//#define btRigidBodyDataName "btRigidBodyDoubleData"
+//#else
+#define btSoftBodyData btSoftBodyFloatData
+#define btSoftBodyDataName "btSoftBodyFloatData"
+//#endif //BT_USE_DOUBLE_PRECISION
+
+class btBroadphaseInterface;
+class btDispatcher;
+class btSoftBodySolver;
+
+/* btSoftBodyWorldInfo */
+struct btSoftBodyWorldInfo
+{
+ btScalar air_density;
+ btScalar water_density;
+ btScalar water_offset;
+ btScalar m_maxDisplacement;
+ btVector3 water_normal;
+ btBroadphaseInterface* m_broadphase;
+ btDispatcher* m_dispatcher;
+ btVector3 m_gravity;
+ btSparseSdf<3> m_sparsesdf;
+
+ btSoftBodyWorldInfo()
+ :air_density((btScalar)1.2),
+ water_density(0),
+ water_offset(0),
+ m_maxDisplacement(1000.f),//avoid soft body from 'exploding' so use some upper threshold of maximum motion that a node can travel per frame
+ water_normal(0,0,0),
+ m_broadphase(0),
+ m_dispatcher(0),
+ m_gravity(0,-10,0)
+ {
+ }
+};
+
+
+///The btSoftBody is an class to simulate cloth and volumetric soft bodies.
+///There is two-way interaction between btSoftBody and btRigidBody/btCollisionObject.
+class btSoftBody : public btCollisionObject
+{
+public:
+ btAlignedObjectArray<const class btCollisionObject*> m_collisionDisabledObjects;
+
+ // The solver object that handles this soft body
+ btSoftBodySolver *m_softBodySolver;
+
+ //
+ // Enumerations
+ //
+
+ ///eAeroModel
+ struct eAeroModel { enum _ {
+ V_Point, ///Vertex normals are oriented toward velocity
+ V_TwoSided, ///Vertex normals are flipped to match velocity
+ V_TwoSidedLiftDrag, ///Vertex normals are flipped to match velocity and lift and drag forces are applied
+ V_OneSided, ///Vertex normals are taken as it is
+ F_TwoSided, ///Face normals are flipped to match velocity
+ F_TwoSidedLiftDrag, ///Face normals are flipped to match velocity and lift and drag forces are applied
+ F_OneSided, ///Face normals are taken as it is
+ END
+ };};
+
+ ///eVSolver : velocities solvers
+ struct eVSolver { enum _ {
+ Linear, ///Linear solver
+ END
+ };};
+
+ ///ePSolver : positions solvers
+ struct ePSolver { enum _ {
+ Linear, ///Linear solver
+ Anchors, ///Anchor solver
+ RContacts, ///Rigid contacts solver
+ SContacts, ///Soft contacts solver
+ END
+ };};
+
+ ///eSolverPresets
+ struct eSolverPresets { enum _ {
+ Positions,
+ Velocities,
+ Default = Positions,
+ END
+ };};
+
+ ///eFeature
+ struct eFeature { enum _ {
+ None,
+ Node,
+ Link,
+ Face,
+ Tetra,
+ END
+ };};
+
+ typedef btAlignedObjectArray<eVSolver::_> tVSolverArray;
+ typedef btAlignedObjectArray<ePSolver::_> tPSolverArray;
+
+ //
+ // Flags
+ //
+
+ ///fCollision
+ struct fCollision { enum _ {
+ RVSmask = 0x000f, ///Rigid versus soft mask
+ SDF_RS = 0x0001, ///SDF based rigid vs soft
+ CL_RS = 0x0002, ///Cluster vs convex rigid vs soft
+
+ SVSmask = 0x0030, ///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
+ /* presets */
+ Default = SDF_RS,
+ END
+ };};
+
+ ///fMaterial
+ struct fMaterial { enum _ {
+ DebugDraw = 0x0001, /// Enable debug draw
+ /* presets */
+ Default = DebugDraw,
+ END
+ };};
+
+ //
+ // API Types
+ //
+
+ /* sRayCast */
+ struct sRayCast
+ {
+ btSoftBody* body; /// soft body
+ eFeature::_ feature; /// feature type
+ int index; /// feature index
+ btScalar fraction; /// time of impact fraction (rayorg+(rayto-rayfrom)*fraction)
+ };
+
+ /* ImplicitFn */
+ struct ImplicitFn
+ {
+ virtual ~ImplicitFn() {}
+ virtual btScalar Eval(const btVector3& x)=0;
+ };
+
+ //
+ // Internal types
+ //
+
+ typedef btAlignedObjectArray<btScalar> tScalarArray;
+ typedef btAlignedObjectArray<btVector3> tVector3Array;
+
+ /* sCti is Softbody contact info */
+ struct sCti
+ {
+ const btCollisionObject* m_colObj; /* Rigid body */
+ btVector3 m_normal; /* Outward normal */
+ btScalar m_offset; /* Offset from origin */
+ };
+
+ /* sMedium */
+ struct sMedium
+ {
+ btVector3 m_velocity; /* Velocity */
+ btScalar m_pressure; /* Pressure */
+ btScalar m_density; /* Density */
+ };
+
+ /* Base type */
+ struct Element
+ {
+ void* m_tag; // User data
+ Element() : m_tag(0) {}
+ };
+ /* Material */
+ struct Material : Element
+ {
+ btScalar m_kLST; // Linear stiffness coefficient [0,1]
+ btScalar m_kAST; // Area/Angular stiffness coefficient [0,1]
+ btScalar m_kVST; // Volume stiffness coefficient [0,1]
+ int m_flags; // Flags
+ };
+
+ /* Feature */
+ struct Feature : Element
+ {
+ Material* m_material; // Material
+ };
+ /* Node */
+ struct Node : Feature
+ {
+ btVector3 m_x; // Position
+ btVector3 m_q; // Previous step position
+ btVector3 m_v; // 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
+ };
+ /* Link */
+ ATTRIBUTE_ALIGNED16(struct) Link : Feature
+ {
+ btVector3 m_c3; // gradient
+ Node* m_n[2]; // Node pointers
+ btScalar m_rl; // Rest length
+ int m_bbending:1; // Bending link
+ btScalar m_c0; // (ima+imb)*kLST
+ btScalar m_c1; // rl^2
+ btScalar m_c2; // |gradient|^2/c0
+
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ };
+ /* Face */
+ struct Face : Feature
+ {
+ Node* m_n[3]; // Node pointers
+ btVector3 m_normal; // Normal
+ btScalar m_ra; // Rest area
+ btDbvtNode* m_leaf; // Leaf data
+ };
+ /* Tetra */
+ struct Tetra : Feature
+ {
+ Node* m_n[4]; // Node pointers
+ btScalar m_rv; // Rest volume
+ btDbvtNode* m_leaf; // Leaf data
+ btVector3 m_c0[4]; // gradients
+ btScalar m_c1; // (4*kVST)/(im0+im1+im2+im3)
+ btScalar m_c2; // m_c1/sum(|g0..3|^2)
+ };
+ /* RContact */
+ struct RContact
+ {
+ sCti m_cti; // Contact infos
+ Node* m_node; // Owner node
+ btMatrix3x3 m_c0; // Impulse matrix
+ btVector3 m_c1; // Relative anchor
+ btScalar m_c2; // ima*dt
+ btScalar m_c3; // Friction
+ btScalar m_c4; // Hardness
+ };
+ /* SContact */
+ struct SContact
+ {
+ Node* m_node; // Node
+ Face* m_face; // Face
+ btVector3 m_weights; // Weigths
+ btVector3 m_normal; // Normal
+ btScalar m_margin; // Margin
+ btScalar m_friction; // Friction
+ btScalar m_cfm[2]; // Constraint force mixing
+ };
+ /* Anchor */
+ struct Anchor
+ {
+ Node* m_node; // Node pointer
+ btVector3 m_local; // Anchor position in body space
+ btRigidBody* m_body; // Body
+ btScalar m_influence;
+ btMatrix3x3 m_c0; // Impulse matrix
+ btVector3 m_c1; // Relative anchor
+ btScalar m_c2; // ima*dt
+ };
+ /* Note */
+ struct Note : Element
+ {
+ const char* m_text; // Text
+ btVector3 m_offset; // Offset
+ int m_rank; // Rank
+ Node* m_nodes[4]; // Nodes
+ btScalar m_coords[4]; // Coordinates
+ };
+ /* Pose */
+ struct Pose
+ {
+ bool m_bvolume; // Is valid
+ bool m_bframe; // Is frame
+ btScalar m_volume; // Rest volume
+ tVector3Array m_pos; // Reference positions
+ tScalarArray m_wgh; // Weights
+ btVector3 m_com; // COM
+ btMatrix3x3 m_rot; // Rotation
+ btMatrix3x3 m_scl; // Scale
+ btMatrix3x3 m_aqq; // Base scaling
+ };
+ /* Cluster */
+ struct Cluster
+ {
+ tScalarArray m_masses;
+ btAlignedObjectArray<Node*> m_nodes;
+ tVector3Array m_framerefs;
+ btTransform m_framexform;
+ btScalar m_idmass;
+ btScalar m_imass;
+ btMatrix3x3 m_locii;
+ btMatrix3x3 m_invwi;
+ btVector3 m_com;
+ btVector3 m_vimpulses[2];
+ btVector3 m_dimpulses[2];
+ int m_nvimpulses;
+ int m_ndimpulses;
+ btVector3 m_lv;
+ btVector3 m_av;
+ btDbvtNode* m_leaf;
+ btScalar m_ndamping; /* Node damping */
+ btScalar m_ldamping; /* Linear damping */
+ btScalar m_adamping; /* Angular damping */
+ btScalar m_matching;
+ btScalar m_maxSelfCollisionImpulse;
+ btScalar m_selfCollisionImpulseFactor;
+ bool m_containsAnchor;
+ bool m_collide;
+ int m_clusterIndex;
+ Cluster() : m_leaf(0),m_ndamping(0),m_ldamping(0),m_adamping(0),m_matching(0)
+ ,m_maxSelfCollisionImpulse(100.f),
+ m_selfCollisionImpulseFactor(0.01f),
+ m_containsAnchor(false)
+ {}
+ };
+ /* Impulse */
+ struct Impulse
+ {
+ btVector3 m_velocity;
+ btVector3 m_drift;
+ int m_asVelocity:1;
+ int m_asDrift:1;
+ Impulse() : m_velocity(0,0,0),m_drift(0,0,0),m_asVelocity(0),m_asDrift(0) {}
+ Impulse operator -() const
+ {
+ Impulse i=*this;
+ i.m_velocity=-i.m_velocity;
+ i.m_drift=-i.m_drift;
+ return(i);
+ }
+ Impulse operator*(btScalar x) const
+ {
+ Impulse i=*this;
+ i.m_velocity*=x;
+ i.m_drift*=x;
+ return(i);
+ }
+ };
+ /* Body */
+ struct Body
+ {
+ Cluster* m_soft;
+ btRigidBody* m_rigid;
+ const btCollisionObject* m_collisionObject;
+
+ Body() : m_soft(0),m_rigid(0),m_collisionObject(0) {}
+ Body(Cluster* p) : m_soft(p),m_rigid(0),m_collisionObject(0) {}
+ Body(const btCollisionObject* colObj) : m_soft(0),m_collisionObject(colObj)
+ {
+ m_rigid = (btRigidBody*)btRigidBody::upcast(m_collisionObject);
+ }
+
+ void activate() const
+ {
+ if(m_rigid)
+ m_rigid->activate();
+ if (m_collisionObject)
+ m_collisionObject->activate();
+
+ }
+ const btMatrix3x3& invWorldInertia() const
+ {
+ static const btMatrix3x3 iwi(0,0,0,0,0,0,0,0,0);
+ if(m_rigid) return(m_rigid->getInvInertiaTensorWorld());
+ if(m_soft) return(m_soft->m_invwi);
+ return(iwi);
+ }
+ btScalar invMass() const
+ {
+ if(m_rigid) return(m_rigid->getInvMass());
+ if(m_soft) return(m_soft->m_imass);
+ return(0);
+ }
+ const btTransform& xform() const
+ {
+ static const btTransform identity=btTransform::getIdentity();
+ if(m_collisionObject) return(m_collisionObject->getWorldTransform());
+ if(m_soft) return(m_soft->m_framexform);
+ return(identity);
+ }
+ btVector3 linearVelocity() const
+ {
+ if(m_rigid) return(m_rigid->getLinearVelocity());
+ if(m_soft) return(m_soft->m_lv);
+ return(btVector3(0,0,0));
+ }
+ btVector3 angularVelocity(const btVector3& rpos) const
+ {
+ if(m_rigid) return(btCross(m_rigid->getAngularVelocity(),rpos));
+ if(m_soft) return(btCross(m_soft->m_av,rpos));
+ return(btVector3(0,0,0));
+ }
+ btVector3 angularVelocity() const
+ {
+ if(m_rigid) return(m_rigid->getAngularVelocity());
+ if(m_soft) return(m_soft->m_av);
+ return(btVector3(0,0,0));
+ }
+ btVector3 velocity(const btVector3& rpos) const
+ {
+ return(linearVelocity()+angularVelocity(rpos));
+ }
+ void applyVImpulse(const btVector3& impulse,const btVector3& rpos) const
+ {
+ if(m_rigid) m_rigid->applyImpulse(impulse,rpos);
+ if(m_soft) btSoftBody::clusterVImpulse(m_soft,rpos,impulse);
+ }
+ void applyDImpulse(const btVector3& impulse,const btVector3& rpos) const
+ {
+ if(m_rigid) m_rigid->applyImpulse(impulse,rpos);
+ if(m_soft) btSoftBody::clusterDImpulse(m_soft,rpos,impulse);
+ }
+ void applyImpulse(const Impulse& impulse,const btVector3& rpos) const
+ {
+ if(impulse.m_asVelocity)
+ {
+// printf("impulse.m_velocity = %f,%f,%f\n",impulse.m_velocity.getX(),impulse.m_velocity.getY(),impulse.m_velocity.getZ());
+ applyVImpulse(impulse.m_velocity,rpos);
+ }
+ if(impulse.m_asDrift)
+ {
+// printf("impulse.m_drift = %f,%f,%f\n",impulse.m_drift.getX(),impulse.m_drift.getY(),impulse.m_drift.getZ());
+ applyDImpulse(impulse.m_drift,rpos);
+ }
+ }
+ void applyVAImpulse(const btVector3& impulse) const
+ {
+ if(m_rigid) m_rigid->applyTorqueImpulse(impulse);
+ if(m_soft) btSoftBody::clusterVAImpulse(m_soft,impulse);
+ }
+ void applyDAImpulse(const btVector3& impulse) const
+ {
+ if(m_rigid) m_rigid->applyTorqueImpulse(impulse);
+ if(m_soft) btSoftBody::clusterDAImpulse(m_soft,impulse);
+ }
+ void applyAImpulse(const Impulse& impulse) const
+ {
+ if(impulse.m_asVelocity) applyVAImpulse(impulse.m_velocity);
+ if(impulse.m_asDrift) applyDAImpulse(impulse.m_drift);
+ }
+ void applyDCImpulse(const btVector3& impulse) const
+ {
+ if(m_rigid) m_rigid->applyCentralImpulse(impulse);
+ if(m_soft) btSoftBody::clusterDCImpulse(m_soft,impulse);
+ }
+ };
+ /* Joint */
+ struct Joint
+ {
+ struct eType { enum _ {
+ Linear=0,
+ Angular,
+ Contact
+ };};
+ struct Specs
+ {
+ Specs() : erp(1),cfm(1),split(1) {}
+ btScalar erp;
+ btScalar cfm;
+ btScalar split;
+ };
+ Body m_bodies[2];
+ btVector3 m_refs[2];
+ btScalar m_cfm;
+ btScalar m_erp;
+ btScalar m_split;
+ btVector3 m_drift;
+ btVector3 m_sdrift;
+ btMatrix3x3 m_massmatrix;
+ bool m_delete;
+ virtual ~Joint() {}
+ Joint() : m_delete(false) {}
+ virtual void Prepare(btScalar dt,int iterations);
+ virtual void Solve(btScalar dt,btScalar sor)=0;
+ virtual void Terminate(btScalar dt)=0;
+ virtual eType::_ Type() const=0;
+ };
+ /* LJoint */
+ struct LJoint : Joint
+ {
+ struct Specs : Joint::Specs
+ {
+ btVector3 position;
+ };
+ btVector3 m_rpos[2];
+ void Prepare(btScalar dt,int iterations);
+ void Solve(btScalar dt,btScalar sor);
+ void Terminate(btScalar dt);
+ eType::_ Type() const { return(eType::Linear); }
+ };
+ /* AJoint */
+ struct AJoint : Joint
+ {
+ struct IControl
+ {
+ virtual ~IControl() {}
+ virtual void Prepare(AJoint*) {}
+ virtual btScalar Speed(AJoint*,btScalar current) { return(current); }
+ static IControl* Default() { static IControl def;return(&def); }
+ };
+ struct Specs : Joint::Specs
+ {
+ Specs() : icontrol(IControl::Default()) {}
+ btVector3 axis;
+ IControl* icontrol;
+ };
+ btVector3 m_axis[2];
+ IControl* m_icontrol;
+ void Prepare(btScalar dt,int iterations);
+ void Solve(btScalar dt,btScalar sor);
+ void Terminate(btScalar dt);
+ eType::_ Type() const { return(eType::Angular); }
+ };
+ /* CJoint */
+ struct CJoint : Joint
+ {
+ int m_life;
+ int m_maxlife;
+ btVector3 m_rpos[2];
+ btVector3 m_normal;
+ btScalar m_friction;
+ void Prepare(btScalar dt,int iterations);
+ void Solve(btScalar dt,btScalar sor);
+ void Terminate(btScalar dt);
+ eType::_ Type() const { return(eType::Contact); }
+ };
+ /* Config */
+ struct Config
+ {
+ eAeroModel::_ aeromodel; // Aerodynamic model (default: V_Point)
+ btScalar kVCF; // Velocities correction factor (Baumgarte)
+ btScalar kDP; // Damping coefficient [0,1]
+ btScalar kDG; // Drag coefficient [0,+inf]
+ btScalar kLF; // Lift coefficient [0,+inf]
+ btScalar kPR; // Pressure coefficient [-inf,+inf]
+ btScalar kVC; // Volume conversation coefficient [0,+inf]
+ btScalar kDF; // Dynamic friction coefficient [0,1]
+ btScalar kMT; // Pose matching coefficient [0,1]
+ btScalar kCHR; // Rigid contacts hardness [0,1]
+ btScalar kKHR; // Kinetic contacts hardness [0,1]
+ btScalar kSHR; // Soft contacts hardness [0,1]
+ btScalar kAHR; // Anchors hardness [0,1]
+ btScalar kSRHR_CL; // Soft vs rigid hardness [0,1] (cluster only)
+ btScalar kSKHR_CL; // Soft vs kinetic hardness [0,1] (cluster only)
+ btScalar kSSHR_CL; // Soft vs soft hardness [0,1] (cluster only)
+ btScalar kSR_SPLT_CL; // Soft vs rigid impulse split [0,1] (cluster only)
+ btScalar kSK_SPLT_CL; // Soft vs rigid impulse split [0,1] (cluster only)
+ btScalar kSS_SPLT_CL; // Soft vs rigid impulse split [0,1] (cluster only)
+ btScalar maxvolume; // Maximum volume ratio for pose
+ btScalar timescale; // Time scale
+ int viterations; // Velocities solver iterations
+ int piterations; // Positions solver iterations
+ int diterations; // Drift solver iterations
+ int citerations; // Cluster solver iterations
+ int collisions; // Collisions flags
+ tVSolverArray m_vsequence; // Velocity solvers sequence
+ tPSolverArray m_psequence; // Position solvers sequence
+ tPSolverArray m_dsequence; // Drift solvers sequence
+ };
+ /* SolverState */
+ struct SolverState
+ {
+ btScalar sdt; // dt*timescale
+ btScalar isdt; // 1/sdt
+ btScalar velmrg; // velocity margin
+ btScalar radmrg; // radial margin
+ btScalar updmrg; // Update margin
+ };
+ /// RayFromToCaster takes a ray from, ray to (instead of direction!)
+ struct RayFromToCaster : btDbvt::ICollide
+ {
+ btVector3 m_rayFrom;
+ btVector3 m_rayTo;
+ btVector3 m_rayNormalizedDirection;
+ btScalar m_mint;
+ Face* m_face;
+ int m_tests;
+ RayFromToCaster(const btVector3& rayFrom,const btVector3& rayTo,btScalar mxt);
+ void Process(const btDbvtNode* leaf);
+
+ static /*inline*/ btScalar rayFromToTriangle(const btVector3& rayFrom,
+ const btVector3& rayTo,
+ const btVector3& rayNormalizedDirection,
+ const btVector3& a,
+ const btVector3& b,
+ const btVector3& c,
+ btScalar maxt=SIMD_INFINITY);
+ };
+
+ //
+ // Typedefs
+ //
+
+ typedef void (*psolver_t)(btSoftBody*,btScalar,btScalar);
+ typedef void (*vsolver_t)(btSoftBody*,btScalar);
+ typedef btAlignedObjectArray<Cluster*> tClusterArray;
+ typedef btAlignedObjectArray<Note> tNoteArray;
+ typedef btAlignedObjectArray<Node> tNodeArray;
+ typedef btAlignedObjectArray<btDbvtNode*> tLeafArray;
+ typedef btAlignedObjectArray<Link> tLinkArray;
+ typedef btAlignedObjectArray<Face> tFaceArray;
+ typedef btAlignedObjectArray<Tetra> tTetraArray;
+ typedef btAlignedObjectArray<Anchor> tAnchorArray;
+ typedef btAlignedObjectArray<RContact> tRContactArray;
+ typedef btAlignedObjectArray<SContact> tSContactArray;
+ typedef btAlignedObjectArray<Material*> tMaterialArray;
+ typedef btAlignedObjectArray<Joint*> tJointArray;
+ typedef btAlignedObjectArray<btSoftBody*> tSoftBodyArray;
+
+ //
+ // Fields
+ //
+
+ Config m_cfg; // Configuration
+ SolverState m_sst; // Solver state
+ Pose m_pose; // Pose
+ void* m_tag; // User data
+ btSoftBodyWorldInfo* m_worldInfo; // World info
+ tNoteArray m_notes; // Notes
+ tNodeArray m_nodes; // Nodes
+ tLinkArray m_links; // Links
+ tFaceArray m_faces; // Faces
+ tTetraArray m_tetras; // Tetras
+ tAnchorArray m_anchors; // Anchors
+ tRContactArray m_rcontacts; // Rigid contacts
+ tSContactArray m_scontacts; // Soft contacts
+ tJointArray m_joints; // Joints
+ tMaterialArray m_materials; // Materials
+ btScalar m_timeacc; // Time accumulator
+ btVector3 m_bounds[2]; // Spatial bounds
+ bool m_bUpdateRtCst; // Update runtime constants
+ btDbvt m_ndbvt; // Nodes tree
+ btDbvt m_fdbvt; // Faces tree
+ btDbvt m_cdbvt; // Clusters tree
+ tClusterArray m_clusters; // Clusters
+
+ btAlignedObjectArray<bool>m_clusterConnectivity;//cluster connectivity, for self-collision
+
+ btTransform m_initialWorldTransform;
+
+ btVector3 m_windVelocity;
+
+ btScalar m_restLengthScale;
+
+ //
+ // Api
+ //
+
+ /* ctor */
+ btSoftBody( btSoftBodyWorldInfo* worldInfo,int node_count, const btVector3* x, const btScalar* m);
+
+ /* ctor */
+ btSoftBody( btSoftBodyWorldInfo* worldInfo);
+
+ void initDefaults();
+
+ /* dtor */
+ virtual ~btSoftBody();
+ /* Check for existing link */
+
+ btAlignedObjectArray<int> m_userIndexMapping;
+
+ btSoftBodyWorldInfo* getWorldInfo()
+ {
+ return m_worldInfo;
+ }
+
+ ///@todo: avoid internal softbody shape hack and move collision code to collision library
+ virtual void setCollisionShape(btCollisionShape* collisionShape)
+ {
+
+ }
+
+ bool checkLink( int node0,
+ int node1) const;
+ bool checkLink( const Node* node0,
+ const Node* node1) const;
+ /* Check for existring face */
+ bool checkFace( int node0,
+ int node1,
+ int node2) const;
+ /* Append material */
+ Material* appendMaterial();
+ /* Append note */
+ void appendNote( const char* text,
+ const btVector3& o,
+ const btVector4& c=btVector4(1,0,0,0),
+ Node* n0=0,
+ Node* n1=0,
+ Node* n2=0,
+ Node* n3=0);
+ void appendNote( const char* text,
+ const btVector3& o,
+ Node* feature);
+ void appendNote( const char* text,
+ const btVector3& o,
+ Link* feature);
+ void appendNote( const char* text,
+ const btVector3& o,
+ Face* feature);
+ /* Append node */
+ void appendNode( const btVector3& x,btScalar m);
+ /* Append link */
+ void appendLink(int model=-1,Material* mat=0);
+ void appendLink( int node0,
+ int node1,
+ Material* mat=0,
+ bool bcheckexist=false);
+ void appendLink( Node* node0,
+ Node* node1,
+ Material* mat=0,
+ bool bcheckexist=false);
+ /* Append face */
+ void appendFace(int model=-1,Material* mat=0);
+ void appendFace( int node0,
+ int node1,
+ int node2,
+ Material* mat=0);
+ void appendTetra(int model,Material* mat);
+ //
+ void appendTetra(int node0,
+ int node1,
+ int node2,
+ int node3,
+ Material* mat=0);
+
+
+ /* Append anchor */
+ 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 */
+ void appendLinearJoint(const LJoint::Specs& specs,Cluster* body0,Body body1);
+ void appendLinearJoint(const LJoint::Specs& specs,Body body=Body());
+ void appendLinearJoint(const LJoint::Specs& specs,btSoftBody* body);
+ /* Append linear joint */
+ void appendAngularJoint(const AJoint::Specs& specs,Cluster* body0,Body body1);
+ void appendAngularJoint(const AJoint::Specs& specs,Body body=Body());
+ void appendAngularJoint(const AJoint::Specs& specs,btSoftBody* body);
+ /* Add force (or gravity) to the entire body */
+ void addForce( const btVector3& force);
+ /* Add force (or gravity) to a node of the body */
+ void addForce( const btVector3& force,
+ int node);
+ /* Add aero force to a node of the body */
+ void addAeroForceToNode(const btVector3& windVelocity,int nodeIndex);
+
+ /* Add aero force to a face of the body */
+ void addAeroForceToFace(const btVector3& windVelocity,int faceIndex);
+
+ /* Add velocity to the entire body */
+ void addVelocity( const btVector3& velocity);
+
+ /* Set velocity for the entire body */
+ void setVelocity( const btVector3& velocity);
+
+ /* Add velocity to a node of the body */
+ void addVelocity( const btVector3& velocity,
+ int node);
+ /* Set mass */
+ void setMass( int node,
+ btScalar mass);
+ /* Get mass */
+ btScalar getMass( int node) const;
+ /* Get total mass */
+ btScalar getTotalMass() const;
+ /* Set total mass (weighted by previous masses) */
+ void setTotalMass( btScalar mass,
+ bool fromfaces=false);
+ /* Set total density */
+ void setTotalDensity(btScalar density);
+ /* Set volume mass (using tetrahedrons) */
+ void setVolumeMass( btScalar mass);
+ /* Set volume density (using tetrahedrons) */
+ void setVolumeDensity( btScalar density);
+ /* Transform */
+ void transform( const btTransform& trs);
+ /* Translate */
+ void translate( const btVector3& trs);
+ /* Rotate */
+ void rotate( const btQuaternion& rot);
+ /* Scale */
+ void scale( const btVector3& scl);
+ /* Get link resting lengths scale */
+ btScalar getRestLengthScale();
+ /* Scale resting length of all springs */
+ void setRestLengthScale(btScalar restLength);
+ /* Set current state as pose */
+ void setPose( bool bvolume,
+ bool bframe);
+ /* Set current link lengths as resting lengths */
+ void resetLinkRestLengths();
+ /* Return the volume */
+ btScalar getVolume() const;
+ /* Cluster count */
+ int clusterCount() const;
+ /* Cluster center of mass */
+ static btVector3 clusterCom(const Cluster* cluster);
+ btVector3 clusterCom(int cluster) const;
+ /* Cluster velocity at rpos */
+ static btVector3 clusterVelocity(const Cluster* cluster,const btVector3& rpos);
+ /* Cluster impulse */
+ static void clusterVImpulse(Cluster* cluster,const btVector3& rpos,const btVector3& impulse);
+ static void clusterDImpulse(Cluster* cluster,const btVector3& rpos,const btVector3& impulse);
+ static void clusterImpulse(Cluster* cluster,const btVector3& rpos,const Impulse& impulse);
+ static void clusterVAImpulse(Cluster* cluster,const btVector3& impulse);
+ static void clusterDAImpulse(Cluster* cluster,const btVector3& impulse);
+ static void clusterAImpulse(Cluster* cluster,const Impulse& impulse);
+ static void clusterDCImpulse(Cluster* cluster,const btVector3& impulse);
+ /* Generate bending constraints based on distance in the adjency graph */
+ int generateBendingConstraints( int distance,
+ Material* mat=0);
+ /* Randomize constraints to reduce solver bias */
+ void randomizeConstraints();
+ /* Release clusters */
+ void releaseCluster(int index);
+ void releaseClusters();
+ /* Generate clusters (K-mean) */
+ ///generateClusters with k=0 will create a convex cluster for each tetrahedron or triangle
+ ///otherwise an approximation will be used (better performance)
+ int generateClusters(int k,int maxiterations=8192);
+ /* Refine */
+ void refine(ImplicitFn* ifn,btScalar accurary,bool cut);
+ /* CutLink */
+ bool cutLink(int node0,int node1,btScalar position);
+ bool cutLink(const Node* node0,const Node* node1,btScalar position);
+
+ ///Ray casting using rayFrom and rayTo in worldspace, (not direction!)
+ bool rayTest(const btVector3& rayFrom,
+ const btVector3& rayTo,
+ sRayCast& results);
+ /* Solver presets */
+ void setSolver(eSolverPresets::_ preset);
+ /* predictMotion */
+ void predictMotion(btScalar dt);
+ /* solveConstraints */
+ void solveConstraints();
+ /* staticSolve */
+ void staticSolve(int iterations);
+ /* solveCommonConstraints */
+ static void solveCommonConstraints(btSoftBody** bodies,int count,int iterations);
+ /* solveClusters */
+ static void solveClusters(const btAlignedObjectArray<btSoftBody*>& bodies);
+ /* integrateMotion */
+ void integrateMotion();
+ /* defaultCollisionHandlers */
+ void defaultCollisionHandler(const btCollisionObjectWrapper* pcoWrap);
+ void defaultCollisionHandler(btSoftBody* psb);
+
+
+
+ //
+ // Functionality to deal with new accelerated solvers.
+ //
+
+ /**
+ * Set a wind velocity for interaction with the air.
+ */
+ void setWindVelocity( const btVector3 &velocity );
+
+
+ /**
+ * Return the wind velocity for interaction with the air.
+ */
+ const btVector3& getWindVelocity();
+
+ //
+ // Set the solver that handles this soft body
+ // Should not be allowed to get out of sync with reality
+ // Currently called internally on addition to the world
+ void setSoftBodySolver( btSoftBodySolver *softBodySolver )
+ {
+ m_softBodySolver = softBodySolver;
+ }
+
+ //
+ // Return the solver that handles this soft body
+ //
+ btSoftBodySolver *getSoftBodySolver()
+ {
+ return m_softBodySolver;
+ }
+
+ //
+ // Return the solver that handles this soft body
+ //
+ btSoftBodySolver *getSoftBodySolver() const
+ {
+ return m_softBodySolver;
+ }
+
+
+ //
+ // Cast
+ //
+
+ static const btSoftBody* upcast(const btCollisionObject* colObj)
+ {
+ if (colObj->getInternalType()==CO_SOFT_BODY)
+ return (const btSoftBody*)colObj;
+ return 0;
+ }
+ static btSoftBody* upcast(btCollisionObject* colObj)
+ {
+ if (colObj->getInternalType()==CO_SOFT_BODY)
+ return (btSoftBody*)colObj;
+ return 0;
+ }
+
+ //
+ // ::btCollisionObject
+ //
+
+ virtual void getAabb(btVector3& aabbMin,btVector3& aabbMax) const
+ {
+ aabbMin = m_bounds[0];
+ aabbMax = m_bounds[1];
+ }
+ //
+ // Private
+ //
+ void pointersToIndices();
+ void indicesToPointers(const int* map=0);
+
+ int rayTest(const btVector3& rayFrom,const btVector3& rayTo,
+ 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;
+ void updateNormals();
+ void updateBounds();
+ void updatePose();
+ void updateConstants();
+ void updateLinkConstants();
+ void updateArea(bool averageArea = true);
+ void initializeClusters();
+ void updateClusters();
+ void cleanupClusters();
+ void prepareClusters(int iterations);
+ void solveClusters(btScalar sor);
+ void applyClusters(bool drift);
+ void dampClusters();
+ void applyForces();
+ 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);
+ static void PSolve_Links(btSoftBody* psb,btScalar kst,btScalar ti);
+ static void VSolve_Links(btSoftBody* psb,btScalar kst);
+ static psolver_t getSolver(ePSolver::_ solver);
+ 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/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp b/thirdparty/bullet/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp
new file mode 100644
index 0000000000..ab84bddf2a
--- /dev/null
+++ b/thirdparty/bullet/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp
@@ -0,0 +1,358 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "btSoftBodyConcaveCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/CollisionShapes/btMultiSphereShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/CollisionShapes/btConcaveShape.h"
+#include "BulletCollision/CollisionDispatch/btManifoldResult.h"
+#include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h"
+#include "BulletCollision/CollisionShapes/btTriangleShape.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"
+#include "BulletCollision/CollisionShapes/btTetrahedronShape.h"
+#include "BulletCollision/CollisionShapes/btConvexHullShape.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
+
+
+#include "LinearMath/btIDebugDraw.h"
+#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
+#include "BulletSoftBody/btSoftBody.h"
+
+#define BT_SOFTBODY_TRIANGLE_EXTRUSION btScalar(0.06)//make this configurable
+
+btSoftBodyConcaveCollisionAlgorithm::btSoftBodyConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped)
+: btCollisionAlgorithm(ci),
+m_isSwapped(isSwapped),
+m_btSoftBodyTriangleCallback(ci.m_dispatcher1,body0Wrap,body1Wrap,isSwapped)
+{
+}
+
+
+
+btSoftBodyConcaveCollisionAlgorithm::~btSoftBodyConcaveCollisionAlgorithm()
+{
+}
+
+
+
+btSoftBodyTriangleCallback::btSoftBodyTriangleCallback(btDispatcher* dispatcher,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped):
+m_dispatcher(dispatcher),
+m_dispatchInfoPtr(0)
+{
+ m_softBody = (isSwapped? (btSoftBody*)body1Wrap->getCollisionObject():(btSoftBody*)body0Wrap->getCollisionObject());
+ m_triBody = isSwapped? body0Wrap->getCollisionObject():body1Wrap->getCollisionObject();
+
+ //
+ // create the manifold from the dispatcher 'manifold pool'
+ //
+ // m_manifoldPtr = m_dispatcher->getNewManifold(m_convexBody,m_triBody);
+
+ clearCache();
+}
+
+btSoftBodyTriangleCallback::~btSoftBodyTriangleCallback()
+{
+ clearCache();
+ // m_dispatcher->releaseManifold( m_manifoldPtr );
+
+}
+
+
+void btSoftBodyTriangleCallback::clearCache()
+{
+ for (int i=0;i<m_shapeCache.size();i++)
+ {
+ btTriIndex* tmp = m_shapeCache.getAtIndex(i);
+ btAssert(tmp);
+ btAssert(tmp->m_childShape);
+ m_softBody->getWorldInfo()->m_sparsesdf.RemoveReferences(tmp->m_childShape);//necessary?
+ delete tmp->m_childShape;
+ }
+ m_shapeCache.clear();
+}
+
+
+void btSoftBodyTriangleCallback::processTriangle(btVector3* triangle,int partId, int triangleIndex)
+{
+ //just for debugging purposes
+ //printf("triangle %d",m_triangleCount++);
+
+ btCollisionAlgorithmConstructionInfo ci;
+ ci.m_dispatcher1 = m_dispatcher;
+
+ ///debug drawing of the overlapping triangles
+ if (m_dispatchInfoPtr && m_dispatchInfoPtr->m_debugDraw && (m_dispatchInfoPtr->m_debugDraw->getDebugMode() &btIDebugDraw::DBG_DrawWireframe))
+ {
+ btVector3 color(1,1,0);
+ const btTransform& tr = m_triBody->getWorldTransform();
+ m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[0]),tr(triangle[1]),color);
+ m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[1]),tr(triangle[2]),color);
+ m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[2]),tr(triangle[0]),color);
+ }
+
+ btTriIndex triIndex(partId,triangleIndex,0);
+ btHashKey<btTriIndex> triKey(triIndex.getUid());
+
+
+ btTriIndex* shapeIndex = m_shapeCache[triKey];
+ if (shapeIndex)
+ {
+ btCollisionShape* tm = shapeIndex->m_childShape;
+ btAssert(tm);
+
+ //copy over user pointers to temporary shape
+ tm->setUserPointer(m_triBody->getCollisionShape()->getUserPointer());
+
+ btCollisionObjectWrapper softBody(0,m_softBody->getCollisionShape(),m_softBody,m_softBody->getWorldTransform(),-1,-1);
+ //btCollisionObjectWrapper triBody(0,tm, ob, btTransform::getIdentity());//ob->getWorldTransform());//??
+ btCollisionObjectWrapper triBody(0,tm, m_triBody, m_triBody->getWorldTransform(),partId, triangleIndex);
+ ebtDispatcherQueryType algoType = m_resultOut->m_closestPointDistanceThreshold > 0 ? BT_CLOSEST_POINT_ALGORITHMS : BT_CONTACT_POINT_ALGORITHMS;
+ btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(&softBody,&triBody,0, algoType);//m_manifoldPtr);
+
+ colAlgo->processCollision(&softBody,&triBody,*m_dispatchInfoPtr,m_resultOut);
+ colAlgo->~btCollisionAlgorithm();
+ ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo);
+
+ return;
+ }
+
+ //aabb filter is already applied!
+
+ //btCollisionObject* colObj = static_cast<btCollisionObject*>(m_convexProxy->m_clientObject);
+
+ // if (m_softBody->getCollisionShape()->getShapeType()==
+ {
+ // btVector3 other;
+ btVector3 normal = (triangle[1]-triangle[0]).cross(triangle[2]-triangle[0]);
+ normal.normalize();
+ normal*= BT_SOFTBODY_TRIANGLE_EXTRUSION;
+ // other=(triangle[0]+triangle[1]+triangle[2])*0.333333f;
+ // other+=normal*22.f;
+ btVector3 pts[6] = {triangle[0]+normal,
+ triangle[1]+normal,
+ triangle[2]+normal,
+ triangle[0]-normal,
+ triangle[1]-normal,
+ triangle[2]-normal};
+
+ btConvexHullShape* tm = new btConvexHullShape(&pts[0].getX(),6);
+
+
+ // btBU_Simplex1to4 tm(triangle[0],triangle[1],triangle[2],other);
+
+ //btTriangleShape tm(triangle[0],triangle[1],triangle[2]);
+ // tm.setMargin(m_collisionMarginTriangle);
+
+ //copy over user pointers to temporary shape
+ tm->setUserPointer(m_triBody->getCollisionShape()->getUserPointer());
+
+
+ btCollisionObjectWrapper softBody(0,m_softBody->getCollisionShape(),m_softBody,m_softBody->getWorldTransform(),-1,-1);
+ btCollisionObjectWrapper triBody(0,tm, m_triBody, m_triBody->getWorldTransform(),partId, triangleIndex);//btTransform::getIdentity());//??
+
+ ebtDispatcherQueryType algoType = m_resultOut->m_closestPointDistanceThreshold > 0 ? BT_CLOSEST_POINT_ALGORITHMS : BT_CONTACT_POINT_ALGORITHMS;
+ btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(&softBody,&triBody,0, algoType);//m_manifoldPtr);
+
+ colAlgo->processCollision(&softBody,&triBody,*m_dispatchInfoPtr,m_resultOut);
+ colAlgo->~btCollisionAlgorithm();
+ ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo);
+
+ triIndex.m_childShape = tm;
+ m_shapeCache.insert(triKey,triIndex);
+
+ }
+
+
+
+}
+
+
+
+void btSoftBodyTriangleCallback::setTimeStepAndCounters(btScalar collisionMarginTriangle,const btCollisionObjectWrapper* triBodyWrap, const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+ m_dispatchInfoPtr = &dispatchInfo;
+ m_collisionMarginTriangle = collisionMarginTriangle+btScalar(BT_SOFTBODY_TRIANGLE_EXTRUSION);
+ m_resultOut = resultOut;
+
+
+ btVector3 aabbWorldSpaceMin,aabbWorldSpaceMax;
+ m_softBody->getAabb(aabbWorldSpaceMin,aabbWorldSpaceMax);
+ btVector3 halfExtents = (aabbWorldSpaceMax-aabbWorldSpaceMin)*btScalar(0.5);
+ btVector3 softBodyCenter = (aabbWorldSpaceMax+aabbWorldSpaceMin)*btScalar(0.5);
+
+ btTransform softTransform;
+ softTransform.setIdentity();
+ softTransform.setOrigin(softBodyCenter);
+
+ btTransform convexInTriangleSpace;
+ convexInTriangleSpace = triBodyWrap->getWorldTransform().inverse() * softTransform;
+ btTransformAabb(halfExtents,m_collisionMarginTriangle,convexInTriangleSpace,m_aabbMin,m_aabbMax);
+}
+
+void btSoftBodyConcaveCollisionAlgorithm::clearCache()
+{
+ m_btSoftBodyTriangleCallback.clearCache();
+
+}
+
+void btSoftBodyConcaveCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+
+
+ //btCollisionObject* convexBody = m_isSwapped ? body1 : body0;
+ const btCollisionObjectWrapper* triBody = m_isSwapped ? body0Wrap : body1Wrap;
+
+ if (triBody->getCollisionShape()->isConcave())
+ {
+
+
+ const btCollisionObject* triOb = triBody->getCollisionObject();
+ const btConcaveShape* concaveShape = static_cast<const btConcaveShape*>( triOb->getCollisionShape());
+
+ // if (convexBody->getCollisionShape()->isConvex())
+ {
+ btScalar collisionMarginTriangle = concaveShape->getMargin();
+
+ // resultOut->setPersistentManifold(m_btSoftBodyTriangleCallback.m_manifoldPtr);
+ m_btSoftBodyTriangleCallback.setTimeStepAndCounters(collisionMarginTriangle,triBody,dispatchInfo,resultOut);
+
+
+ concaveShape->processAllTriangles( &m_btSoftBodyTriangleCallback,m_btSoftBodyTriangleCallback.getAabbMin(),m_btSoftBodyTriangleCallback.getAabbMax());
+
+ // resultOut->refreshContactPoints();
+
+ }
+
+ }
+
+}
+
+
+btScalar btSoftBodyConcaveCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+ (void)resultOut;
+ (void)dispatchInfo;
+ btCollisionObject* convexbody = m_isSwapped ? body1 : body0;
+ btCollisionObject* triBody = m_isSwapped ? body0 : body1;
+
+
+ //quick approximation using raycast, todo: hook up to the continuous collision detection (one of the btConvexCast)
+
+ //only perform CCD above a certain threshold, this prevents blocking on the long run
+ //because object in a blocked ccd state (hitfraction<1) get their linear velocity halved each frame...
+ btScalar squareMot0 = (convexbody->getInterpolationWorldTransform().getOrigin() - convexbody->getWorldTransform().getOrigin()).length2();
+ if (squareMot0 < convexbody->getCcdSquareMotionThreshold())
+ {
+ return btScalar(1.);
+ }
+
+ //const btVector3& from = convexbody->m_worldTransform.getOrigin();
+ //btVector3 to = convexbody->m_interpolationWorldTransform.getOrigin();
+ //todo: only do if the motion exceeds the 'radius'
+
+ btTransform triInv = triBody->getWorldTransform().inverse();
+ btTransform convexFromLocal = triInv * convexbody->getWorldTransform();
+ btTransform convexToLocal = triInv * convexbody->getInterpolationWorldTransform();
+
+ struct LocalTriangleSphereCastCallback : public btTriangleCallback
+ {
+ btTransform m_ccdSphereFromTrans;
+ btTransform m_ccdSphereToTrans;
+ btTransform m_meshTransform;
+
+ btScalar m_ccdSphereRadius;
+ btScalar m_hitFraction;
+
+
+ LocalTriangleSphereCastCallback(const btTransform& from,const btTransform& to,btScalar ccdSphereRadius,btScalar hitFraction)
+ :m_ccdSphereFromTrans(from),
+ m_ccdSphereToTrans(to),
+ m_ccdSphereRadius(ccdSphereRadius),
+ m_hitFraction(hitFraction)
+ {
+ }
+
+
+ virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
+ {
+ (void)partId;
+ (void)triangleIndex;
+ //do a swept sphere for now
+ btTransform ident;
+ ident.setIdentity();
+ btConvexCast::CastResult castResult;
+ castResult.m_fraction = m_hitFraction;
+ btSphereShape pointShape(m_ccdSphereRadius);
+ btTriangleShape triShape(triangle[0],triangle[1],triangle[2]);
+ btVoronoiSimplexSolver simplexSolver;
+ btSubsimplexConvexCast convexCaster(&pointShape,&triShape,&simplexSolver);
+ //GjkConvexCast convexCaster(&pointShape,convexShape,&simplexSolver);
+ //ContinuousConvexCollision convexCaster(&pointShape,convexShape,&simplexSolver,0);
+ //local space?
+
+ if (convexCaster.calcTimeOfImpact(m_ccdSphereFromTrans,m_ccdSphereToTrans,
+ ident,ident,castResult))
+ {
+ if (m_hitFraction > castResult.m_fraction)
+ m_hitFraction = castResult.m_fraction;
+ }
+
+ }
+
+ };
+
+
+
+
+
+ if (triBody->getCollisionShape()->isConcave())
+ {
+ btVector3 rayAabbMin = convexFromLocal.getOrigin();
+ rayAabbMin.setMin(convexToLocal.getOrigin());
+ btVector3 rayAabbMax = convexFromLocal.getOrigin();
+ rayAabbMax.setMax(convexToLocal.getOrigin());
+ btScalar ccdRadius0 = convexbody->getCcdSweptSphereRadius();
+ rayAabbMin -= btVector3(ccdRadius0,ccdRadius0,ccdRadius0);
+ rayAabbMax += btVector3(ccdRadius0,ccdRadius0,ccdRadius0);
+
+ btScalar curHitFraction = btScalar(1.); //is this available?
+ LocalTriangleSphereCastCallback raycastCallback(convexFromLocal,convexToLocal,
+ convexbody->getCcdSweptSphereRadius(),curHitFraction);
+
+ raycastCallback.m_hitFraction = convexbody->getHitFraction();
+
+ btCollisionObject* concavebody = triBody;
+
+ btConcaveShape* triangleMesh = (btConcaveShape*) concavebody->getCollisionShape();
+
+ if (triangleMesh)
+ {
+ triangleMesh->processAllTriangles(&raycastCallback,rayAabbMin,rayAabbMax);
+ }
+
+
+
+ if (raycastCallback.m_hitFraction < convexbody->getHitFraction())
+ {
+ convexbody->setHitFraction( raycastCallback.m_hitFraction);
+ return raycastCallback.m_hitFraction;
+ }
+ }
+
+ return btScalar(1.);
+
+}
diff --git a/thirdparty/bullet/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h b/thirdparty/bullet/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h
new file mode 100644
index 0000000000..11c7b88f98
--- /dev/null
+++ b/thirdparty/bullet/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h
@@ -0,0 +1,155 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_SOFT_BODY_CONCAVE_COLLISION_ALGORITHM_H
+#define BT_SOFT_BODY_CONCAVE_COLLISION_ALGORITHM_H
+
+#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
+#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
+#include "BulletCollision/CollisionShapes/btTriangleCallback.h"
+#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
+class btDispatcher;
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
+class btSoftBody;
+class btCollisionShape;
+
+#include "LinearMath/btHashMap.h"
+
+#include "BulletCollision/BroadphaseCollision/btQuantizedBvh.h" //for definition of MAX_NUM_PARTS_IN_BITS
+
+struct btTriIndex
+{
+ int m_PartIdTriangleIndex;
+ class btCollisionShape* m_childShape;
+
+ btTriIndex(int partId,int triangleIndex,btCollisionShape* shape)
+ {
+ m_PartIdTriangleIndex = (partId<<(31-MAX_NUM_PARTS_IN_BITS)) | triangleIndex;
+ m_childShape = shape;
+ }
+
+ int getTriangleIndex() const
+ {
+ // Get only the lower bits where the triangle index is stored
+ unsigned int x = 0;
+ unsigned int y = (~(x&0))<<(31-MAX_NUM_PARTS_IN_BITS);
+ return (m_PartIdTriangleIndex&~(y));
+ }
+ int getPartId() const
+ {
+ // Get only the highest bits where the part index is stored
+ return (m_PartIdTriangleIndex>>(31-MAX_NUM_PARTS_IN_BITS));
+ }
+ int getUid() const
+ {
+ return m_PartIdTriangleIndex;
+ }
+};
+
+
+///For each triangle in the concave mesh that overlaps with the AABB of a soft body (m_softBody), processTriangle is called.
+class btSoftBodyTriangleCallback : public btTriangleCallback
+{
+ btSoftBody* m_softBody;
+ const btCollisionObject* m_triBody;
+
+ btVector3 m_aabbMin;
+ btVector3 m_aabbMax ;
+
+ btManifoldResult* m_resultOut;
+
+ btDispatcher* m_dispatcher;
+ const btDispatcherInfo* m_dispatchInfoPtr;
+ btScalar m_collisionMarginTriangle;
+
+ btHashMap<btHashKey<btTriIndex>,btTriIndex> m_shapeCache;
+
+public:
+ int m_triangleCount;
+
+ // btPersistentManifold* m_manifoldPtr;
+
+ btSoftBodyTriangleCallback(btDispatcher* dispatcher,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped);
+
+ void setTimeStepAndCounters(btScalar collisionMarginTriangle,const btCollisionObjectWrapper* triObjWrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+ virtual ~btSoftBodyTriangleCallback();
+
+ virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex);
+
+ void clearCache();
+
+ SIMD_FORCE_INLINE const btVector3& getAabbMin() const
+ {
+ return m_aabbMin;
+ }
+ SIMD_FORCE_INLINE const btVector3& getAabbMax() const
+ {
+ return m_aabbMax;
+ }
+
+};
+
+
+
+
+/// btSoftBodyConcaveCollisionAlgorithm supports collision between soft body shapes and (concave) trianges meshes.
+class btSoftBodyConcaveCollisionAlgorithm : public btCollisionAlgorithm
+{
+
+ bool m_isSwapped;
+
+ btSoftBodyTriangleCallback m_btSoftBodyTriangleCallback;
+
+public:
+
+ btSoftBodyConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped);
+
+ virtual ~btSoftBodyConcaveCollisionAlgorithm();
+
+ virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+ btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+ virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
+ {
+ //we don't add any manifolds
+ }
+
+ void clearCache();
+
+ struct CreateFunc :public btCollisionAlgorithmCreateFunc
+ {
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
+ {
+ void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSoftBodyConcaveCollisionAlgorithm));
+ return new(mem) btSoftBodyConcaveCollisionAlgorithm(ci,body0Wrap,body1Wrap,false);
+ }
+ };
+
+ struct SwappedCreateFunc :public btCollisionAlgorithmCreateFunc
+ {
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
+ {
+ void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSoftBodyConcaveCollisionAlgorithm));
+ return new(mem) btSoftBodyConcaveCollisionAlgorithm(ci,body0Wrap,body1Wrap,true);
+ }
+ };
+
+};
+
+#endif //BT_SOFT_BODY_CONCAVE_COLLISION_ALGORITHM_H
diff --git a/thirdparty/bullet/src/BulletSoftBody/btSoftBodyData.h b/thirdparty/bullet/src/BulletSoftBody/btSoftBodyData.h
new file mode 100644
index 0000000000..87d8841cfa
--- /dev/null
+++ b/thirdparty/bullet/src/BulletSoftBody/btSoftBodyData.h
@@ -0,0 +1,217 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_SOFTBODY_FLOAT_DATA
+#define BT_SOFTBODY_FLOAT_DATA
+
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+
+
+struct SoftBodyMaterialData
+{
+ float m_linearStiffness;
+ float m_angularStiffness;
+ float m_volumeStiffness;
+ int m_flags;
+};
+
+struct SoftBodyNodeData
+{
+ SoftBodyMaterialData *m_material;
+ btVector3FloatData m_position;
+ btVector3FloatData m_previousPosition;
+ btVector3FloatData m_velocity;
+ btVector3FloatData m_accumulatedForce;
+ btVector3FloatData m_normal;
+ float m_inverseMass;
+ float m_area;
+ int m_attach;
+ int m_pad;
+};
+
+struct SoftBodyLinkData
+{
+ SoftBodyMaterialData *m_material;
+ int m_nodeIndices[2]; // Node pointers
+ float m_restLength; // Rest length
+ int m_bbending; // Bending link
+};
+
+struct SoftBodyFaceData
+{
+ btVector3FloatData m_normal; // Normal
+ SoftBodyMaterialData *m_material;
+ int m_nodeIndices[3]; // Node pointers
+ float m_restArea; // Rest area
+};
+
+struct SoftBodyTetraData
+{
+ btVector3FloatData m_c0[4]; // gradients
+ SoftBodyMaterialData *m_material;
+ int m_nodeIndices[4]; // Node pointers
+ float m_restVolume; // Rest volume
+ float m_c1; // (4*kVST)/(im0+im1+im2+im3)
+ float m_c2; // m_c1/sum(|g0..3|^2)
+ int m_pad;
+};
+
+struct SoftRigidAnchorData
+{
+ btMatrix3x3FloatData m_c0; // Impulse matrix
+ btVector3FloatData m_c1; // Relative anchor
+ btVector3FloatData m_localFrame; // Anchor position in body space
+ btRigidBodyData *m_rigidBody;
+ int m_nodeIndex; // Node pointer
+ float m_c2; // ima*dt
+};
+
+
+
+struct SoftBodyConfigData
+{
+ int m_aeroModel; // Aerodynamic model (default: V_Point)
+ float m_baumgarte; // Velocities correction factor (Baumgarte)
+ float m_damping; // Damping coefficient [0,1]
+ float m_drag; // Drag coefficient [0,+inf]
+ float m_lift; // Lift coefficient [0,+inf]
+ float m_pressure; // Pressure coefficient [-inf,+inf]
+ float m_volume; // Volume conversation coefficient [0,+inf]
+ float m_dynamicFriction; // Dynamic friction coefficient [0,1]
+ float m_poseMatch; // Pose matching coefficient [0,1]
+ float m_rigidContactHardness; // Rigid contacts hardness [0,1]
+ float m_kineticContactHardness; // Kinetic contacts hardness [0,1]
+ float m_softContactHardness; // Soft contacts hardness [0,1]
+ float m_anchorHardness; // Anchors hardness [0,1]
+ float m_softRigidClusterHardness; // Soft vs rigid hardness [0,1] (cluster only)
+ float m_softKineticClusterHardness; // Soft vs kinetic hardness [0,1] (cluster only)
+ float m_softSoftClusterHardness; // Soft vs soft hardness [0,1] (cluster only)
+ float m_softRigidClusterImpulseSplit; // Soft vs rigid impulse split [0,1] (cluster only)
+ float m_softKineticClusterImpulseSplit; // Soft vs rigid impulse split [0,1] (cluster only)
+ float m_softSoftClusterImpulseSplit; // Soft vs rigid impulse split [0,1] (cluster only)
+ float m_maxVolume; // Maximum volume ratio for pose
+ float m_timeScale; // Time scale
+ int m_velocityIterations; // Velocities solver iterations
+ int m_positionIterations; // Positions solver iterations
+ int m_driftIterations; // Drift solver iterations
+ int m_clusterIterations; // Cluster solver iterations
+ int m_collisionFlags; // Collisions flags
+};
+
+struct SoftBodyPoseData
+{
+ btMatrix3x3FloatData m_rot; // Rotation
+ btMatrix3x3FloatData m_scale; // Scale
+ btMatrix3x3FloatData m_aqq; // Base scaling
+ btVector3FloatData m_com; // COM
+
+ btVector3FloatData *m_positions; // Reference positions
+ float *m_weights; // Weights
+ int m_numPositions;
+ int m_numWeigts;
+
+ int m_bvolume; // Is valid
+ int m_bframe; // Is frame
+ float m_restVolume; // Rest volume
+ int m_pad;
+};
+
+struct SoftBodyClusterData
+{
+ btTransformFloatData m_framexform;
+ btMatrix3x3FloatData m_locii;
+ btMatrix3x3FloatData m_invwi;
+ btVector3FloatData m_com;
+ btVector3FloatData m_vimpulses[2];
+ btVector3FloatData m_dimpulses[2];
+ btVector3FloatData m_lv;
+ btVector3FloatData m_av;
+
+ btVector3FloatData *m_framerefs;
+ int *m_nodeIndices;
+ float *m_masses;
+
+ int m_numFrameRefs;
+ int m_numNodes;
+ int m_numMasses;
+
+ float m_idmass;
+ float m_imass;
+ int m_nvimpulses;
+ int m_ndimpulses;
+ float m_ndamping;
+ float m_ldamping;
+ float m_adamping;
+ float m_matching;
+ float m_maxSelfCollisionImpulse;
+ float m_selfCollisionImpulseFactor;
+ int m_containsAnchor;
+ int m_collide;
+ int m_clusterIndex;
+};
+
+
+enum btSoftJointBodyType
+{
+ BT_JOINT_SOFT_BODY_CLUSTER=1,
+ BT_JOINT_RIGID_BODY,
+ BT_JOINT_COLLISION_OBJECT
+};
+
+struct btSoftBodyJointData
+{
+ void *m_bodyA;
+ void *m_bodyB;
+ btVector3FloatData m_refs[2];
+ float m_cfm;
+ float m_erp;
+ float m_split;
+ int m_delete;
+ btVector3FloatData m_relPosition[2];//linear
+ int m_bodyAtype;
+ int m_bodyBtype;
+ int m_jointType;
+ int m_pad;
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btSoftBodyFloatData
+{
+ btCollisionObjectFloatData m_collisionObjectData;
+
+ SoftBodyPoseData *m_pose;
+ SoftBodyMaterialData **m_materials;
+ SoftBodyNodeData *m_nodes;
+ SoftBodyLinkData *m_links;
+ SoftBodyFaceData *m_faces;
+ SoftBodyTetraData *m_tetrahedra;
+ SoftRigidAnchorData *m_anchors;
+ SoftBodyClusterData *m_clusters;
+ btSoftBodyJointData *m_joints;
+
+ int m_numMaterials;
+ int m_numNodes;
+ int m_numLinks;
+ int m_numFaces;
+ int m_numTetrahedra;
+ int m_numAnchors;
+ int m_numClusters;
+ int m_numJoints;
+ SoftBodyConfigData m_config;
+};
+
+#endif //BT_SOFTBODY_FLOAT_DATA
+
diff --git a/thirdparty/bullet/src/BulletSoftBody/btSoftBodyHelpers.cpp b/thirdparty/bullet/src/BulletSoftBody/btSoftBodyHelpers.cpp
new file mode 100644
index 0000000000..51fcd16da4
--- /dev/null
+++ b/thirdparty/bullet/src/BulletSoftBody/btSoftBodyHelpers.cpp
@@ -0,0 +1,1219 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+///btSoftBodyHelpers.cpp by Nathanael Presson
+
+#include "btSoftBodyInternals.h"
+#include <stdio.h>
+#include <string.h>
+#include "btSoftBodyHelpers.h"
+#include "LinearMath/btConvexHull.h"
+#include "LinearMath/btConvexHullComputer.h"
+
+
+//
+static void drawVertex( btIDebugDraw* idraw,
+ const btVector3& x,btScalar s,const btVector3& c)
+{
+ idraw->drawLine(x-btVector3(s,0,0),x+btVector3(s,0,0),c);
+ idraw->drawLine(x-btVector3(0,s,0),x+btVector3(0,s,0),c);
+ idraw->drawLine(x-btVector3(0,0,s),x+btVector3(0,0,s),c);
+}
+
+//
+static void drawBox( btIDebugDraw* idraw,
+ const btVector3& mins,
+ const btVector3& maxs,
+ const btVector3& color)
+{
+ const btVector3 c[]={ btVector3(mins.x(),mins.y(),mins.z()),
+ btVector3(maxs.x(),mins.y(),mins.z()),
+ btVector3(maxs.x(),maxs.y(),mins.z()),
+ btVector3(mins.x(),maxs.y(),mins.z()),
+ btVector3(mins.x(),mins.y(),maxs.z()),
+ btVector3(maxs.x(),mins.y(),maxs.z()),
+ btVector3(maxs.x(),maxs.y(),maxs.z()),
+ btVector3(mins.x(),maxs.y(),maxs.z())};
+ idraw->drawLine(c[0],c[1],color);idraw->drawLine(c[1],c[2],color);
+ idraw->drawLine(c[2],c[3],color);idraw->drawLine(c[3],c[0],color);
+ idraw->drawLine(c[4],c[5],color);idraw->drawLine(c[5],c[6],color);
+ idraw->drawLine(c[6],c[7],color);idraw->drawLine(c[7],c[4],color);
+ idraw->drawLine(c[0],c[4],color);idraw->drawLine(c[1],c[5],color);
+ idraw->drawLine(c[2],c[6],color);idraw->drawLine(c[3],c[7],color);
+}
+
+//
+static void drawTree( btIDebugDraw* idraw,
+ const btDbvtNode* node,
+ int depth,
+ const btVector3& ncolor,
+ const btVector3& lcolor,
+ int mindepth,
+ int maxdepth)
+{
+ if(node)
+ {
+ if(node->isinternal()&&((depth<maxdepth)||(maxdepth<0)))
+ {
+ drawTree(idraw,node->childs[0],depth+1,ncolor,lcolor,mindepth,maxdepth);
+ drawTree(idraw,node->childs[1],depth+1,ncolor,lcolor,mindepth,maxdepth);
+ }
+ if(depth>=mindepth)
+ {
+ const btScalar scl=(btScalar)(node->isinternal()?1:1);
+ const btVector3 mi=node->volume.Center()-node->volume.Extents()*scl;
+ const btVector3 mx=node->volume.Center()+node->volume.Extents()*scl;
+ drawBox(idraw,mi,mx,node->isleaf()?lcolor:ncolor);
+ }
+ }
+}
+
+//
+template <typename T>
+static inline T sum(const btAlignedObjectArray<T>& items)
+{
+ T v;
+ if(items.size())
+ {
+ v=items[0];
+ for(int i=1,ni=items.size();i<ni;++i)
+ {
+ v+=items[i];
+ }
+ }
+ return(v);
+}
+
+//
+template <typename T,typename Q>
+static inline void add(btAlignedObjectArray<T>& items,const Q& value)
+{
+ for(int i=0,ni=items.size();i<ni;++i)
+ {
+ items[i]+=value;
+ }
+}
+
+//
+template <typename T,typename Q>
+static inline void mul(btAlignedObjectArray<T>& items,const Q& value)
+{
+ for(int i=0,ni=items.size();i<ni;++i)
+ {
+ items[i]*=value;
+ }
+}
+
+//
+template <typename T>
+static inline T average(const btAlignedObjectArray<T>& items)
+{
+ const btScalar n=(btScalar)(items.size()>0?items.size():1);
+ return(sum(items)/n);
+}
+
+#if 0
+//
+ inline static btScalar tetravolume(const btVector3& x0,
+ const btVector3& x1,
+ const btVector3& x2,
+ const btVector3& x3)
+{
+ const btVector3 a=x1-x0;
+ const btVector3 b=x2-x0;
+ const btVector3 c=x3-x0;
+ return(btDot(a,btCross(b,c)));
+}
+#endif
+
+//
+#if 0
+static btVector3 stresscolor(btScalar stress)
+{
+ static const btVector3 spectrum[]= { btVector3(1,0,1),
+ btVector3(0,0,1),
+ btVector3(0,1,1),
+ btVector3(0,1,0),
+ btVector3(1,1,0),
+ btVector3(1,0,0),
+ btVector3(1,0,0)};
+ static const int ncolors=sizeof(spectrum)/sizeof(spectrum[0])-1;
+ static const btScalar one=1;
+ stress=btMax<btScalar>(0,btMin<btScalar>(1,stress))*ncolors;
+ const int sel=(int)stress;
+ const btScalar frc=stress-sel;
+ return(spectrum[sel]+(spectrum[sel+1]-spectrum[sel])*frc);
+}
+#endif
+
+//
+void btSoftBodyHelpers::Draw( btSoftBody* psb,
+ btIDebugDraw* idraw,
+ int drawflags)
+{
+ const btScalar scl=(btScalar)0.1;
+ const btScalar nscl=scl*5;
+ const btVector3 lcolor=btVector3(0,0,0);
+ const btVector3 ncolor=btVector3(1,1,1);
+ const btVector3 ccolor=btVector3(1,0,0);
+ int i,j,nj;
+
+ /* Clusters */
+ if(0!=(drawflags&fDrawFlags::Clusters))
+ {
+ srand(1806);
+ for(i=0;i<psb->m_clusters.size();++i)
+ {
+ if(psb->m_clusters[i]->m_collide)
+ {
+ btVector3 color( rand()/(btScalar)RAND_MAX,
+ rand()/(btScalar)RAND_MAX,
+ rand()/(btScalar)RAND_MAX);
+ color=color.normalized()*0.75;
+ btAlignedObjectArray<btVector3> vertices;
+ vertices.resize(psb->m_clusters[i]->m_nodes.size());
+ for(j=0,nj=vertices.size();j<nj;++j)
+ {
+ vertices[j]=psb->m_clusters[i]->m_nodes[j]->m_x;
+ }
+#define USE_NEW_CONVEX_HULL_COMPUTER
+#ifdef USE_NEW_CONVEX_HULL_COMPUTER
+ btConvexHullComputer computer;
+ int stride = sizeof(btVector3);
+ int count = vertices.size();
+ btScalar shrink=0.f;
+ btScalar shrinkClamp=0.f;
+ computer.compute(&vertices[0].getX(),stride,count,shrink,shrinkClamp);
+ for (int i=0;i<computer.faces.size();i++)
+ {
+
+ int face = computer.faces[i];
+ //printf("face=%d\n",face);
+ const btConvexHullComputer::Edge* firstEdge = &computer.edges[face];
+ const btConvexHullComputer::Edge* edge = firstEdge->getNextEdgeOfFace();
+
+ int v0 = firstEdge->getSourceVertex();
+ int v1 = firstEdge->getTargetVertex();
+ while (edge!=firstEdge)
+ {
+ int v2 = edge->getTargetVertex();
+ idraw->drawTriangle(computer.vertices[v0],computer.vertices[v1],computer.vertices[v2],color,1);
+ edge = edge->getNextEdgeOfFace();
+ v0=v1;
+ v1=v2;
+ };
+ }
+#else
+
+ HullDesc hdsc(QF_TRIANGLES,vertices.size(),&vertices[0]);
+ HullResult hres;
+ HullLibrary hlib;
+ hdsc.mMaxVertices=vertices.size();
+ hlib.CreateConvexHull(hdsc,hres);
+ const btVector3 center=average(hres.m_OutputVertices);
+ add(hres.m_OutputVertices,-center);
+ mul(hres.m_OutputVertices,(btScalar)1);
+ add(hres.m_OutputVertices,center);
+ for(j=0;j<(int)hres.mNumFaces;++j)
+ {
+ const int idx[]={hres.m_Indices[j*3+0],hres.m_Indices[j*3+1],hres.m_Indices[j*3+2]};
+ idraw->drawTriangle(hres.m_OutputVertices[idx[0]],
+ hres.m_OutputVertices[idx[1]],
+ hres.m_OutputVertices[idx[2]],
+ color,1);
+ }
+ hlib.ReleaseResult(hres);
+#endif
+
+ }
+ /* Velocities */
+#if 0
+ for(int j=0;j<psb->m_clusters[i].m_nodes.size();++j)
+ {
+ const btSoftBody::Cluster& c=psb->m_clusters[i];
+ const btVector3 r=c.m_nodes[j]->m_x-c.m_com;
+ const btVector3 v=c.m_lv+btCross(c.m_av,r);
+ idraw->drawLine(c.m_nodes[j]->m_x,c.m_nodes[j]->m_x+v,btVector3(1,0,0));
+ }
+#endif
+ /* Frame */
+ // btSoftBody::Cluster& c=*psb->m_clusters[i];
+ // idraw->drawLine(c.m_com,c.m_framexform*btVector3(10,0,0),btVector3(1,0,0));
+ // idraw->drawLine(c.m_com,c.m_framexform*btVector3(0,10,0),btVector3(0,1,0));
+ // idraw->drawLine(c.m_com,c.m_framexform*btVector3(0,0,10),btVector3(0,0,1));
+ }
+ }
+ else
+ {
+ /* Nodes */
+ if(0!=(drawflags&fDrawFlags::Nodes))
+ {
+ for(i=0;i<psb->m_nodes.size();++i)
+ {
+ const btSoftBody::Node& n=psb->m_nodes[i];
+ if(0==(n.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue;
+ idraw->drawLine(n.m_x-btVector3(scl,0,0),n.m_x+btVector3(scl,0,0),btVector3(1,0,0));
+ idraw->drawLine(n.m_x-btVector3(0,scl,0),n.m_x+btVector3(0,scl,0),btVector3(0,1,0));
+ idraw->drawLine(n.m_x-btVector3(0,0,scl),n.m_x+btVector3(0,0,scl),btVector3(0,0,1));
+ }
+ }
+ /* Links */
+ if(0!=(drawflags&fDrawFlags::Links))
+ {
+ for(i=0;i<psb->m_links.size();++i)
+ {
+ const btSoftBody::Link& l=psb->m_links[i];
+ if(0==(l.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue;
+ idraw->drawLine(l.m_n[0]->m_x,l.m_n[1]->m_x,lcolor);
+ }
+ }
+ /* Normals */
+ if(0!=(drawflags&fDrawFlags::Normals))
+ {
+ for(i=0;i<psb->m_nodes.size();++i)
+ {
+ const btSoftBody::Node& n=psb->m_nodes[i];
+ if(0==(n.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue;
+ const btVector3 d=n.m_n*nscl;
+ idraw->drawLine(n.m_x,n.m_x+d,ncolor);
+ idraw->drawLine(n.m_x,n.m_x-d,ncolor*0.5);
+ }
+ }
+ /* Contacts */
+ if(0!=(drawflags&fDrawFlags::Contacts))
+ {
+ static const btVector3 axis[]={btVector3(1,0,0),
+ btVector3(0,1,0),
+ btVector3(0,0,1)};
+ for(i=0;i<psb->m_rcontacts.size();++i)
+ {
+ const btSoftBody::RContact& c=psb->m_rcontacts[i];
+ const btVector3 o= c.m_node->m_x-c.m_cti.m_normal*
+ (btDot(c.m_node->m_x,c.m_cti.m_normal)+c.m_cti.m_offset);
+ const btVector3 x=btCross(c.m_cti.m_normal,axis[c.m_cti.m_normal.minAxis()]).normalized();
+ const btVector3 y=btCross(x,c.m_cti.m_normal).normalized();
+ idraw->drawLine(o-x*nscl,o+x*nscl,ccolor);
+ idraw->drawLine(o-y*nscl,o+y*nscl,ccolor);
+ idraw->drawLine(o,o+c.m_cti.m_normal*nscl*3,btVector3(1,1,0));
+ }
+ }
+ /* Faces */
+ if(0!=(drawflags&fDrawFlags::Faces))
+ {
+ const btScalar scl=(btScalar)0.8;
+ const btScalar alp=(btScalar)1;
+ const btVector3 col(0,(btScalar)0.7,0);
+ for(i=0;i<psb->m_faces.size();++i)
+ {
+ const btSoftBody::Face& f=psb->m_faces[i];
+ if(0==(f.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue;
+ const btVector3 x[]={f.m_n[0]->m_x,f.m_n[1]->m_x,f.m_n[2]->m_x};
+ const btVector3 c=(x[0]+x[1]+x[2])/3;
+ idraw->drawTriangle((x[0]-c)*scl+c,
+ (x[1]-c)*scl+c,
+ (x[2]-c)*scl+c,
+ col,alp);
+ }
+ }
+ /* Tetras */
+ if(0!=(drawflags&fDrawFlags::Tetras))
+ {
+ const btScalar scl=(btScalar)0.8;
+ const btScalar alp=(btScalar)1;
+ const btVector3 col((btScalar)0.3,(btScalar)0.3,(btScalar)0.7);
+ for(int i=0;i<psb->m_tetras.size();++i)
+ {
+ const btSoftBody::Tetra& t=psb->m_tetras[i];
+ if(0==(t.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue;
+ const btVector3 x[]={t.m_n[0]->m_x,t.m_n[1]->m_x,t.m_n[2]->m_x,t.m_n[3]->m_x};
+ const btVector3 c=(x[0]+x[1]+x[2]+x[3])/4;
+ idraw->drawTriangle((x[0]-c)*scl+c,(x[1]-c)*scl+c,(x[2]-c)*scl+c,col,alp);
+ idraw->drawTriangle((x[0]-c)*scl+c,(x[1]-c)*scl+c,(x[3]-c)*scl+c,col,alp);
+ idraw->drawTriangle((x[1]-c)*scl+c,(x[2]-c)*scl+c,(x[3]-c)*scl+c,col,alp);
+ idraw->drawTriangle((x[2]-c)*scl+c,(x[0]-c)*scl+c,(x[3]-c)*scl+c,col,alp);
+ }
+ }
+ }
+ /* Anchors */
+ if(0!=(drawflags&fDrawFlags::Anchors))
+ {
+ for(i=0;i<psb->m_anchors.size();++i)
+ {
+ const btSoftBody::Anchor& a=psb->m_anchors[i];
+ const btVector3 q=a.m_body->getWorldTransform()*a.m_local;
+ drawVertex(idraw,a.m_node->m_x,0.25,btVector3(1,0,0));
+ drawVertex(idraw,q,0.25,btVector3(0,1,0));
+ idraw->drawLine(a.m_node->m_x,q,btVector3(1,1,1));
+ }
+ for(i=0;i<psb->m_nodes.size();++i)
+ {
+ const btSoftBody::Node& n=psb->m_nodes[i];
+ if(0==(n.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue;
+ if(n.m_im<=0)
+ {
+ drawVertex(idraw,n.m_x,0.25,btVector3(1,0,0));
+ }
+ }
+ }
+
+
+ /* Notes */
+ if(0!=(drawflags&fDrawFlags::Notes))
+ {
+ for(i=0;i<psb->m_notes.size();++i)
+ {
+ const btSoftBody::Note& n=psb->m_notes[i];
+ btVector3 p=n.m_offset;
+ for(int j=0;j<n.m_rank;++j)
+ {
+ p+=n.m_nodes[j]->m_x*n.m_coords[j];
+ }
+ idraw->draw3dText(p,n.m_text);
+ }
+ }
+ /* Node tree */
+ if(0!=(drawflags&fDrawFlags::NodeTree)) DrawNodeTree(psb,idraw);
+ /* Face tree */
+ if(0!=(drawflags&fDrawFlags::FaceTree)) DrawFaceTree(psb,idraw);
+ /* Cluster tree */
+ if(0!=(drawflags&fDrawFlags::ClusterTree)) DrawClusterTree(psb,idraw);
+ /* Joints */
+ if(0!=(drawflags&fDrawFlags::Joints))
+ {
+ for(i=0;i<psb->m_joints.size();++i)
+ {
+ const btSoftBody::Joint* pj=psb->m_joints[i];
+ switch(pj->Type())
+ {
+ case btSoftBody::Joint::eType::Linear:
+ {
+ const btSoftBody::LJoint* pjl=(const btSoftBody::LJoint*)pj;
+ const btVector3 a0=pj->m_bodies[0].xform()*pjl->m_refs[0];
+ const btVector3 a1=pj->m_bodies[1].xform()*pjl->m_refs[1];
+ idraw->drawLine(pj->m_bodies[0].xform().getOrigin(),a0,btVector3(1,1,0));
+ idraw->drawLine(pj->m_bodies[1].xform().getOrigin(),a1,btVector3(0,1,1));
+ drawVertex(idraw,a0,0.25,btVector3(1,1,0));
+ drawVertex(idraw,a1,0.25,btVector3(0,1,1));
+ }
+ break;
+ case btSoftBody::Joint::eType::Angular:
+ {
+ //const btSoftBody::AJoint* pja=(const btSoftBody::AJoint*)pj;
+ const btVector3 o0=pj->m_bodies[0].xform().getOrigin();
+ const btVector3 o1=pj->m_bodies[1].xform().getOrigin();
+ const btVector3 a0=pj->m_bodies[0].xform().getBasis()*pj->m_refs[0];
+ const btVector3 a1=pj->m_bodies[1].xform().getBasis()*pj->m_refs[1];
+ idraw->drawLine(o0,o0+a0*10,btVector3(1,1,0));
+ idraw->drawLine(o0,o0+a1*10,btVector3(1,1,0));
+ idraw->drawLine(o1,o1+a0*10,btVector3(0,1,1));
+ idraw->drawLine(o1,o1+a1*10,btVector3(0,1,1));
+ break;
+ }
+ default:
+ {
+ }
+
+ }
+ }
+ }
+}
+
+//
+void btSoftBodyHelpers::DrawInfos( btSoftBody* psb,
+ btIDebugDraw* idraw,
+ bool masses,
+ bool areas,
+ bool /*stress*/)
+{
+ for(int i=0;i<psb->m_nodes.size();++i)
+ {
+ const btSoftBody::Node& n=psb->m_nodes[i];
+ char text[2048]={0};
+ char buff[1024];
+ if(masses)
+ {
+ sprintf(buff," M(%.2f)",1/n.m_im);
+ strcat(text,buff);
+ }
+ if(areas)
+ {
+ sprintf(buff," A(%.2f)",n.m_area);
+ strcat(text,buff);
+ }
+ if(text[0]) idraw->draw3dText(n.m_x,text);
+ }
+}
+
+//
+void btSoftBodyHelpers::DrawNodeTree( btSoftBody* psb,
+ btIDebugDraw* idraw,
+ int mindepth,
+ int maxdepth)
+{
+ drawTree(idraw,psb->m_ndbvt.m_root,0,btVector3(1,0,1),btVector3(1,1,1),mindepth,maxdepth);
+}
+
+//
+void btSoftBodyHelpers::DrawFaceTree( btSoftBody* psb,
+ btIDebugDraw* idraw,
+ int mindepth,
+ int maxdepth)
+{
+ drawTree(idraw,psb->m_fdbvt.m_root,0,btVector3(0,1,0),btVector3(1,0,0),mindepth,maxdepth);
+}
+
+//
+void btSoftBodyHelpers::DrawClusterTree( btSoftBody* psb,
+ btIDebugDraw* idraw,
+ int mindepth,
+ int maxdepth)
+{
+ drawTree(idraw,psb->m_cdbvt.m_root,0,btVector3(0,1,1),btVector3(1,0,0),mindepth,maxdepth);
+}
+
+
+//The btSoftBody object from the BulletSDK includes an array of Nodes and Links. These links appear
+// to be first set up to connect a node to between 5 and 6 of its neighbors [480 links],
+//and then to the rest of the nodes after the execution of the Floyd-Warshall graph algorithm
+//[another 930 links].
+//The way the links are stored by default, we have a number of cases where adjacent links share a node in common
+// - this leads to the creation of a data dependency through memory.
+//The PSolve_Links() function reads and writes nodes as it iterates over each link.
+//So, we now have the possibility of a data dependency between iteration X
+//that processes link L with iteration X+1 that processes link L+1
+//because L and L+1 have one node in common, and iteration X updates the positions of that node,
+//and iteration X+1 reads in the position of that shared node.
+//
+//Such a memory dependency limits the ability of a modern CPU to speculate beyond
+//a certain point because it has to respect a possible dependency
+//- this prevents the CPU from making full use of its out-of-order resources.
+//If we re-order the links such that we minimize the cases where a link L and L+1 share a common node,
+//we create a temporal gap between when the node position is written,
+//and when it is subsequently read. This in turn allows the CPU to continue execution without
+//risking a dependency violation. Such a reordering would result in significant speedups on
+//modern CPUs with lots of execution resources.
+//In our testing, we see it have a tremendous impact not only on the A7,
+//but also on all x86 cores that ship with modern Macs.
+//The attached source file includes a single function (ReoptimizeLinkOrder) which can be called on a
+//btSoftBody object in the solveConstraints() function before the actual solver is invoked,
+//or right after generateBendingConstraints() once we have all 1410 links.
+
+
+//===================================================================
+//
+//
+// This function takes in a list of interdependent Links and tries
+// to maximize the distance between calculation
+// of dependent links. This increases the amount of parallelism that can
+// be exploited by out-of-order instruction processors with large but
+// (inevitably) finite instruction windows.
+//
+//===================================================================
+
+// A small structure to track lists of dependent link calculations
+class LinkDeps_t {
+ public:
+ int value; // A link calculation that is dependent on this one
+ // Positive values = "input A" while negative values = "input B"
+ LinkDeps_t *next; // Next dependence in the list
+};
+typedef LinkDeps_t *LinkDepsPtr_t;
+
+// Dependency list constants
+#define REOP_NOT_DEPENDENT -1
+#define REOP_NODE_COMPLETE -2 // Must be less than REOP_NOT_DEPENDENT
+
+
+void btSoftBodyHelpers::ReoptimizeLinkOrder(btSoftBody *psb /* This can be replaced by a btSoftBody pointer */)
+{
+ int i, nLinks=psb->m_links.size(), nNodes=psb->m_nodes.size();
+ btSoftBody::Link *lr;
+ int ar, br;
+ btSoftBody::Node *node0 = &(psb->m_nodes[0]);
+ btSoftBody::Node *node1 = &(psb->m_nodes[1]);
+ LinkDepsPtr_t linkDep;
+ int readyListHead, readyListTail, linkNum, linkDepFrees, depLink;
+
+ // Allocate temporary buffers
+ int *nodeWrittenAt = new int[nNodes+1]; // What link calculation produced this node's current values?
+ int *linkDepA = new int[nLinks]; // Link calculation input is dependent upon prior calculation #N
+ int *linkDepB = new int[nLinks];
+ int *readyList = new int[nLinks]; // List of ready-to-process link calculations (# of links, maximum)
+ LinkDeps_t *linkDepFreeList = new LinkDeps_t[2*nLinks]; // Dependent-on-me list elements (2x# of links, maximum)
+ LinkDepsPtr_t *linkDepListStarts = new LinkDepsPtr_t[nLinks]; // Start nodes of dependent-on-me lists, one for each link
+
+ // Copy the original, unsorted links to a side buffer
+ btSoftBody::Link *linkBuffer = new btSoftBody::Link[nLinks];
+ memcpy(linkBuffer, &(psb->m_links[0]), sizeof(btSoftBody::Link)*nLinks);
+
+ // Clear out the node setup and ready list
+ for (i=0; i < nNodes+1; i++) {
+ nodeWrittenAt[i] = REOP_NOT_DEPENDENT;
+ }
+ for (i=0; i < nLinks; i++) {
+ linkDepListStarts[i] = NULL;
+ }
+ readyListHead = readyListTail = linkDepFrees = 0;
+
+ // Initial link analysis to set up data structures
+ for (i=0; i < nLinks; i++) {
+
+ // Note which prior link calculations we are dependent upon & build up dependence lists
+ lr = &(psb->m_links[i]);
+ ar = (lr->m_n[0] - node0)/(node1 - node0);
+ br = (lr->m_n[1] - node0)/(node1 - node0);
+ if (nodeWrittenAt[ar] > REOP_NOT_DEPENDENT) {
+ linkDepA[i] = nodeWrittenAt[ar];
+ linkDep = &linkDepFreeList[linkDepFrees++];
+ linkDep->value = i;
+ linkDep->next = linkDepListStarts[nodeWrittenAt[ar]];
+ linkDepListStarts[nodeWrittenAt[ar]] = linkDep;
+ } else {
+ linkDepA[i] = REOP_NOT_DEPENDENT;
+ }
+ if (nodeWrittenAt[br] > REOP_NOT_DEPENDENT) {
+ linkDepB[i] = nodeWrittenAt[br];
+ linkDep = &linkDepFreeList[linkDepFrees++];
+ linkDep->value = -(i+1);
+ linkDep->next = linkDepListStarts[nodeWrittenAt[br]];
+ linkDepListStarts[nodeWrittenAt[br]] = linkDep;
+ } else {
+ linkDepB[i] = REOP_NOT_DEPENDENT;
+ }
+
+ // Add this link to the initial ready list, if it is not dependent on any other links
+ if ((linkDepA[i] == REOP_NOT_DEPENDENT) && (linkDepB[i] == REOP_NOT_DEPENDENT)) {
+ readyList[readyListTail++] = i;
+ linkDepA[i] = linkDepB[i] = REOP_NODE_COMPLETE; // Probably not needed now
+ }
+
+ // Update the nodes to mark which ones are calculated by this link
+ nodeWrittenAt[ar] = nodeWrittenAt[br] = i;
+ }
+
+ // Process the ready list and create the sorted list of links
+ // -- By treating the ready list as a queue, we maximize the distance between any
+ // inter-dependent node calculations
+ // -- All other (non-related) nodes in the ready list will automatically be inserted
+ // in between each set of inter-dependent link calculations by this loop
+ i = 0;
+ while (readyListHead != readyListTail) {
+ // Use ready list to select the next link to process
+ linkNum = readyList[readyListHead++];
+ // Copy the next-to-calculate link back into the original link array
+ psb->m_links[i++] = linkBuffer[linkNum];
+
+ // Free up any link inputs that are dependent on this one
+ linkDep = linkDepListStarts[linkNum];
+ while (linkDep) {
+ depLink = linkDep->value;
+ if (depLink >= 0) {
+ linkDepA[depLink] = REOP_NOT_DEPENDENT;
+ } else {
+ depLink = -depLink - 1;
+ linkDepB[depLink] = REOP_NOT_DEPENDENT;
+ }
+ // Add this dependent link calculation to the ready list if *both* inputs are clear
+ if ((linkDepA[depLink] == REOP_NOT_DEPENDENT) && (linkDepB[depLink] == REOP_NOT_DEPENDENT)) {
+ readyList[readyListTail++] = depLink;
+ linkDepA[depLink] = linkDepB[depLink] = REOP_NODE_COMPLETE; // Probably not needed now
+ }
+ linkDep = linkDep->next;
+ }
+ }
+
+ // Delete the temporary buffers
+ delete [] nodeWrittenAt;
+ delete [] linkDepA;
+ delete [] linkDepB;
+ delete [] readyList;
+ delete [] linkDepFreeList;
+ delete [] linkDepListStarts;
+ delete [] linkBuffer;
+}
+
+
+//
+void btSoftBodyHelpers::DrawFrame( btSoftBody* psb,
+ btIDebugDraw* idraw)
+{
+ if(psb->m_pose.m_bframe)
+ {
+ static const btScalar ascl=10;
+ static const btScalar nscl=(btScalar)0.1;
+ const btVector3 com=psb->m_pose.m_com;
+ const btMatrix3x3 trs=psb->m_pose.m_rot*psb->m_pose.m_scl;
+ const btVector3 Xaxis=(trs*btVector3(1,0,0)).normalized();
+ const btVector3 Yaxis=(trs*btVector3(0,1,0)).normalized();
+ const btVector3 Zaxis=(trs*btVector3(0,0,1)).normalized();
+ idraw->drawLine(com,com+Xaxis*ascl,btVector3(1,0,0));
+ idraw->drawLine(com,com+Yaxis*ascl,btVector3(0,1,0));
+ idraw->drawLine(com,com+Zaxis*ascl,btVector3(0,0,1));
+ for(int i=0;i<psb->m_pose.m_pos.size();++i)
+ {
+ const btVector3 x=com+trs*psb->m_pose.m_pos[i];
+ drawVertex(idraw,x,nscl,btVector3(1,0,1));
+ }
+ }
+}
+
+//
+btSoftBody* btSoftBodyHelpers::CreateRope( btSoftBodyWorldInfo& worldInfo, const btVector3& from,
+ const btVector3& to,
+ int res,
+ int fixeds)
+{
+ /* Create nodes */
+ const int r=res+2;
+ btVector3* x=new btVector3[r];
+ btScalar* m=new btScalar[r];
+ int i;
+
+ for(i=0;i<r;++i)
+ {
+ const btScalar t=i/(btScalar)(r-1);
+ x[i]=lerp(from,to,t);
+ m[i]=1;
+ }
+ btSoftBody* psb= new btSoftBody(&worldInfo,r,x,m);
+ if(fixeds&1) psb->setMass(0,0);
+ if(fixeds&2) psb->setMass(r-1,0);
+ delete[] x;
+ delete[] m;
+ /* Create links */
+ for(i=1;i<r;++i)
+ {
+ psb->appendLink(i-1,i);
+ }
+ /* Finished */
+ return(psb);
+}
+
+//
+btSoftBody* btSoftBodyHelpers::CreatePatch(btSoftBodyWorldInfo& worldInfo,const btVector3& corner00,
+ const btVector3& corner10,
+ const btVector3& corner01,
+ const btVector3& corner11,
+ int resx,
+ int resy,
+ int fixeds,
+ bool gendiags)
+{
+#define IDX(_x_,_y_) ((_y_)*rx+(_x_))
+ /* Create nodes */
+ if((resx<2)||(resy<2)) return(0);
+ const int rx=resx;
+ const int ry=resy;
+ const int tot=rx*ry;
+ btVector3* x=new btVector3[tot];
+ btScalar* m=new btScalar[tot];
+ int iy;
+
+ for(iy=0;iy<ry;++iy)
+ {
+ const btScalar ty=iy/(btScalar)(ry-1);
+ const btVector3 py0=lerp(corner00,corner01,ty);
+ const btVector3 py1=lerp(corner10,corner11,ty);
+ for(int ix=0;ix<rx;++ix)
+ {
+ const btScalar tx=ix/(btScalar)(rx-1);
+ x[IDX(ix,iy)]=lerp(py0,py1,tx);
+ m[IDX(ix,iy)]=1;
+ }
+ }
+ btSoftBody* psb=new btSoftBody(&worldInfo,tot,x,m);
+ if(fixeds&1) psb->setMass(IDX(0,0),0);
+ if(fixeds&2) psb->setMass(IDX(rx-1,0),0);
+ if(fixeds&4) psb->setMass(IDX(0,ry-1),0);
+ if(fixeds&8) psb->setMass(IDX(rx-1,ry-1),0);
+ delete[] x;
+ delete[] m;
+ /* Create links and faces */
+ for(iy=0;iy<ry;++iy)
+ {
+ for(int ix=0;ix<rx;++ix)
+ {
+ const int idx=IDX(ix,iy);
+ const bool mdx=(ix+1)<rx;
+ const bool mdy=(iy+1)<ry;
+ if(mdx) psb->appendLink(idx,IDX(ix+1,iy));
+ if(mdy) psb->appendLink(idx,IDX(ix,iy+1));
+ if(mdx&&mdy)
+ {
+ if((ix+iy)&1)
+ {
+ psb->appendFace(IDX(ix,iy),IDX(ix+1,iy),IDX(ix+1,iy+1));
+ psb->appendFace(IDX(ix,iy),IDX(ix+1,iy+1),IDX(ix,iy+1));
+ if(gendiags)
+ {
+ psb->appendLink(IDX(ix,iy),IDX(ix+1,iy+1));
+ }
+ }
+ else
+ {
+ psb->appendFace(IDX(ix,iy+1),IDX(ix,iy),IDX(ix+1,iy));
+ psb->appendFace(IDX(ix,iy+1),IDX(ix+1,iy),IDX(ix+1,iy+1));
+ if(gendiags)
+ {
+ psb->appendLink(IDX(ix+1,iy),IDX(ix,iy+1));
+ }
+ }
+ }
+ }
+ }
+ /* Finished */
+#undef IDX
+ return(psb);
+}
+
+//
+btSoftBody* btSoftBodyHelpers::CreatePatchUV(btSoftBodyWorldInfo& worldInfo,
+ const btVector3& corner00,
+ const btVector3& corner10,
+ const btVector3& corner01,
+ const btVector3& corner11,
+ int resx,
+ int resy,
+ int fixeds,
+ bool gendiags,
+ float* tex_coords)
+{
+
+ /*
+ *
+ * corners:
+ *
+ * [0][0] corner00 ------- corner01 [resx][0]
+ * | |
+ * | |
+ * [0][resy] corner10 -------- corner11 [resx][resy]
+ *
+ *
+ *
+ *
+ *
+ *
+ * "fixedgs" map:
+ *
+ * corner00 --> +1
+ * corner01 --> +2
+ * corner10 --> +4
+ * corner11 --> +8
+ * upper middle --> +16
+ * left middle --> +32
+ * right middle --> +64
+ * lower middle --> +128
+ * center --> +256
+ *
+ *
+ * tex_coords size (resx-1)*(resy-1)*12
+ *
+ *
+ *
+ * SINGLE QUAD INTERNALS
+ *
+ * 1) btSoftBody's nodes and links,
+ * diagonal link is optional ("gendiags")
+ *
+ *
+ * node00 ------ node01
+ * | .
+ * | .
+ * | .
+ * | .
+ * | .
+ * node10 node11
+ *
+ *
+ *
+ * 2) Faces:
+ * two triangles,
+ * UV Coordinates (hier example for single quad)
+ *
+ * (0,1) (0,1) (1,1)
+ * 1 |\ 3 \-----| 2
+ * | \ \ |
+ * | \ \ |
+ * | \ \ |
+ * | \ \ |
+ * 2 |-----\ 3 \| 1
+ * (0,0) (1,0) (1,0)
+ *
+ *
+ *
+ *
+ *
+ *
+ */
+
+#define IDX(_x_,_y_) ((_y_)*rx+(_x_))
+ /* Create nodes */
+ if((resx<2)||(resy<2)) return(0);
+ const int rx=resx;
+ const int ry=resy;
+ const int tot=rx*ry;
+ btVector3* x=new btVector3[tot];
+ btScalar* m=new btScalar[tot];
+
+ int iy;
+
+ for(iy=0;iy<ry;++iy)
+ {
+ const btScalar ty=iy/(btScalar)(ry-1);
+ const btVector3 py0=lerp(corner00,corner01,ty);
+ const btVector3 py1=lerp(corner10,corner11,ty);
+ for(int ix=0;ix<rx;++ix)
+ {
+ const btScalar tx=ix/(btScalar)(rx-1);
+ x[IDX(ix,iy)]=lerp(py0,py1,tx);
+ m[IDX(ix,iy)]=1;
+ }
+ }
+ btSoftBody* psb=new btSoftBody(&worldInfo,tot,x,m);
+ if(fixeds&1) psb->setMass(IDX(0,0),0);
+ if(fixeds&2) psb->setMass(IDX(rx-1,0),0);
+ if(fixeds&4) psb->setMass(IDX(0,ry-1),0);
+ if(fixeds&8) psb->setMass(IDX(rx-1,ry-1),0);
+ if(fixeds&16) psb->setMass(IDX((rx-1)/2,0),0);
+ if(fixeds&32) psb->setMass(IDX(0,(ry-1)/2),0);
+ if(fixeds&64) psb->setMass(IDX(rx-1,(ry-1)/2),0);
+ if(fixeds&128) psb->setMass(IDX((rx-1)/2,ry-1),0);
+ if(fixeds&256) psb->setMass(IDX((rx-1)/2,(ry-1)/2),0);
+ delete[] x;
+ delete[] m;
+
+
+ int z = 0;
+ /* Create links and faces */
+ for(iy=0;iy<ry;++iy)
+ {
+ for(int ix=0;ix<rx;++ix)
+ {
+ const bool mdx=(ix+1)<rx;
+ const bool mdy=(iy+1)<ry;
+
+ int node00=IDX(ix,iy);
+ int node01=IDX(ix+1,iy);
+ int node10=IDX(ix,iy+1);
+ int node11=IDX(ix+1,iy+1);
+
+ if(mdx) psb->appendLink(node00,node01);
+ if(mdy) psb->appendLink(node00,node10);
+ if(mdx&&mdy)
+ {
+ psb->appendFace(node00,node10,node11);
+ if (tex_coords) {
+ tex_coords[z+0]=CalculateUV(resx,resy,ix,iy,0);
+ tex_coords[z+1]=CalculateUV(resx,resy,ix,iy,1);
+ tex_coords[z+2]=CalculateUV(resx,resy,ix,iy,0);
+ tex_coords[z+3]=CalculateUV(resx,resy,ix,iy,2);
+ tex_coords[z+4]=CalculateUV(resx,resy,ix,iy,3);
+ tex_coords[z+5]=CalculateUV(resx,resy,ix,iy,2);
+ }
+ psb->appendFace(node11,node01,node00);
+ if (tex_coords) {
+ tex_coords[z+6 ]=CalculateUV(resx,resy,ix,iy,3);
+ tex_coords[z+7 ]=CalculateUV(resx,resy,ix,iy,2);
+ tex_coords[z+8 ]=CalculateUV(resx,resy,ix,iy,3);
+ tex_coords[z+9 ]=CalculateUV(resx,resy,ix,iy,1);
+ tex_coords[z+10]=CalculateUV(resx,resy,ix,iy,0);
+ tex_coords[z+11]=CalculateUV(resx,resy,ix,iy,1);
+ }
+ if (gendiags) psb->appendLink(node00,node11);
+ z += 12;
+ }
+ }
+ }
+ /* Finished */
+#undef IDX
+ return(psb);
+}
+
+float btSoftBodyHelpers::CalculateUV(int resx,int resy,int ix,int iy,int id)
+{
+
+ /*
+ *
+ *
+ * node00 --- node01
+ * | |
+ * node10 --- node11
+ *
+ *
+ * ID map:
+ *
+ * node00 s --> 0
+ * node00 t --> 1
+ *
+ * node01 s --> 3
+ * node01 t --> 1
+ *
+ * node10 s --> 0
+ * node10 t --> 2
+ *
+ * node11 s --> 3
+ * node11 t --> 2
+ *
+ *
+ */
+
+ float tc=0.0f;
+ if (id == 0) {
+ tc = (1.0f/((resx-1))*ix);
+ }
+ else if (id==1) {
+ tc = (1.0f/((resy-1))*(resy-1-iy));
+ }
+ else if (id==2) {
+ tc = (1.0f/((resy-1))*(resy-1-iy-1));
+ }
+ else if (id==3) {
+ tc = (1.0f/((resx-1))*(ix+1));
+ }
+ return tc;
+}
+//
+btSoftBody* btSoftBodyHelpers::CreateEllipsoid(btSoftBodyWorldInfo& worldInfo,const btVector3& center,
+ const btVector3& radius,
+ int res)
+{
+ struct Hammersley
+ {
+ static void Generate(btVector3* x,int n)
+ {
+ for(int i=0;i<n;i++)
+ {
+ btScalar p=0.5,t=0;
+ for(int j=i;j;p*=0.5,j>>=1) if(j&1) t+=p;
+ btScalar w=2*t-1;
+ btScalar a=(SIMD_PI+2*i*SIMD_PI)/n;
+ btScalar s=btSqrt(1-w*w);
+ *x++=btVector3(s*btCos(a),s*btSin(a),w);
+ }
+ }
+ };
+ btAlignedObjectArray<btVector3> vtx;
+ vtx.resize(3+res);
+ Hammersley::Generate(&vtx[0],vtx.size());
+ for(int i=0;i<vtx.size();++i)
+ {
+ vtx[i]=vtx[i]*radius+center;
+ }
+ return(CreateFromConvexHull(worldInfo,&vtx[0],vtx.size()));
+}
+
+
+
+//
+btSoftBody* btSoftBodyHelpers::CreateFromTriMesh(btSoftBodyWorldInfo& worldInfo,const btScalar* vertices,
+ const int* triangles,
+ int ntriangles, bool randomizeConstraints)
+{
+ int maxidx=0;
+ int i,j,ni;
+
+ for(i=0,ni=ntriangles*3;i<ni;++i)
+ {
+ maxidx=btMax(triangles[i],maxidx);
+ }
+ ++maxidx;
+ btAlignedObjectArray<bool> chks;
+ btAlignedObjectArray<btVector3> vtx;
+ chks.resize(maxidx*maxidx,false);
+ vtx.resize(maxidx);
+ for(i=0,j=0,ni=maxidx*3;i<ni;++j,i+=3)
+ {
+ vtx[j]=btVector3(vertices[i],vertices[i+1],vertices[i+2]);
+ }
+ btSoftBody* psb=new btSoftBody(&worldInfo,vtx.size(),&vtx[0],0);
+ for( i=0,ni=ntriangles*3;i<ni;i+=3)
+ {
+ const int idx[]={triangles[i],triangles[i+1],triangles[i+2]};
+#define IDX(_x_,_y_) ((_y_)*maxidx+(_x_))
+ for(int j=2,k=0;k<3;j=k++)
+ {
+ if(!chks[IDX(idx[j],idx[k])])
+ {
+ chks[IDX(idx[j],idx[k])]=true;
+ chks[IDX(idx[k],idx[j])]=true;
+ psb->appendLink(idx[j],idx[k]);
+ }
+ }
+#undef IDX
+ psb->appendFace(idx[0],idx[1],idx[2]);
+ }
+
+ if (randomizeConstraints)
+ {
+ psb->randomizeConstraints();
+ }
+
+ return(psb);
+}
+
+//
+btSoftBody* btSoftBodyHelpers::CreateFromConvexHull(btSoftBodyWorldInfo& worldInfo, const btVector3* vertices,
+ int nvertices, bool randomizeConstraints)
+{
+ HullDesc hdsc(QF_TRIANGLES,nvertices,vertices);
+ HullResult hres;
+ HullLibrary hlib;/*??*/
+ hdsc.mMaxVertices=nvertices;
+ hlib.CreateConvexHull(hdsc,hres);
+ btSoftBody* psb=new btSoftBody(&worldInfo,(int)hres.mNumOutputVertices,
+ &hres.m_OutputVertices[0],0);
+ for(int i=0;i<(int)hres.mNumFaces;++i)
+ {
+ const int idx[]={ static_cast<int>(hres.m_Indices[i*3+0]),
+ static_cast<int>(hres.m_Indices[i*3+1]),
+ static_cast<int>(hres.m_Indices[i*3+2])};
+ if(idx[0]<idx[1]) psb->appendLink( idx[0],idx[1]);
+ if(idx[1]<idx[2]) psb->appendLink( idx[1],idx[2]);
+ if(idx[2]<idx[0]) psb->appendLink( idx[2],idx[0]);
+ psb->appendFace(idx[0],idx[1],idx[2]);
+ }
+ hlib.ReleaseResult(hres);
+ if (randomizeConstraints)
+ {
+ psb->randomizeConstraints();
+ }
+ return(psb);
+}
+
+
+
+
+static int nextLine(const char* buffer)
+{
+ int numBytesRead=0;
+
+ while (*buffer != '\n')
+ {
+ buffer++;
+ numBytesRead++;
+ }
+
+
+ if (buffer[0]==0x0a)
+ {
+ buffer++;
+ numBytesRead++;
+ }
+ return numBytesRead;
+}
+
+/* Create from TetGen .ele, .face, .node data */
+btSoftBody* btSoftBodyHelpers::CreateFromTetGenData(btSoftBodyWorldInfo& worldInfo,
+ const char* ele,
+ const char* face,
+ const char* node,
+ bool bfacelinks,
+ bool btetralinks,
+ bool bfacesfromtetras)
+{
+btAlignedObjectArray<btVector3> pos;
+int nnode=0;
+int ndims=0;
+int nattrb=0;
+int hasbounds=0;
+int result = sscanf(node,"%d %d %d %d",&nnode,&ndims,&nattrb,&hasbounds);
+result = sscanf(node,"%d %d %d %d",&nnode,&ndims,&nattrb,&hasbounds);
+node += nextLine(node);
+
+pos.resize(nnode);
+for(int i=0;i<pos.size();++i)
+ {
+ int index=0;
+ //int bound=0;
+ float x,y,z;
+ sscanf(node,"%d %f %f %f",&index,&x,&y,&z);
+
+// sn>>index;
+// sn>>x;sn>>y;sn>>z;
+ node += nextLine(node);
+
+ //for(int j=0;j<nattrb;++j)
+ // sn>>a;
+
+ //if(hasbounds)
+ // sn>>bound;
+
+ pos[index].setX(btScalar(x));
+ pos[index].setY(btScalar(y));
+ pos[index].setZ(btScalar(z));
+ }
+btSoftBody* psb=new btSoftBody(&worldInfo,nnode,&pos[0],0);
+#if 0
+if(face&&face[0])
+ {
+ int nface=0;
+ sf>>nface;sf>>hasbounds;
+ for(int i=0;i<nface;++i)
+ {
+ int index=0;
+ int bound=0;
+ int ni[3];
+ sf>>index;
+ sf>>ni[0];sf>>ni[1];sf>>ni[2];
+ sf>>bound;
+ psb->appendFace(ni[0],ni[1],ni[2]);
+ if(btetralinks)
+ {
+ psb->appendLink(ni[0],ni[1],0,true);
+ psb->appendLink(ni[1],ni[2],0,true);
+ psb->appendLink(ni[2],ni[0],0,true);
+ }
+ }
+ }
+#endif
+
+if(ele&&ele[0])
+ {
+ int ntetra=0;
+ int ncorner=0;
+ int neattrb=0;
+ sscanf(ele,"%d %d %d",&ntetra,&ncorner,&neattrb);
+ ele += nextLine(ele);
+
+ //se>>ntetra;se>>ncorner;se>>neattrb;
+ for(int i=0;i<ntetra;++i)
+ {
+ int index=0;
+ int ni[4];
+
+ //se>>index;
+ //se>>ni[0];se>>ni[1];se>>ni[2];se>>ni[3];
+ sscanf(ele,"%d %d %d %d %d",&index,&ni[0],&ni[1],&ni[2],&ni[3]);
+ ele+=nextLine(ele);
+ //for(int j=0;j<neattrb;++j)
+ // se>>a;
+ psb->appendTetra(ni[0],ni[1],ni[2],ni[3]);
+ if(btetralinks)
+ {
+ 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);
+ }
+ }
+ }
+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);
+}
+
diff --git a/thirdparty/bullet/src/BulletSoftBody/btSoftBodyHelpers.h b/thirdparty/bullet/src/BulletSoftBody/btSoftBodyHelpers.h
new file mode 100644
index 0000000000..7271530109
--- /dev/null
+++ b/thirdparty/bullet/src/BulletSoftBody/btSoftBodyHelpers.h
@@ -0,0 +1,148 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2008 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_SOFT_BODY_HELPERS_H
+#define BT_SOFT_BODY_HELPERS_H
+
+#include "btSoftBody.h"
+
+//
+// Helpers
+//
+
+/* fDrawFlags */
+struct fDrawFlags { enum _ {
+ Nodes = 0x0001,
+ Links = 0x0002,
+ Faces = 0x0004,
+ Tetras = 0x0008,
+ Normals = 0x0010,
+ Contacts = 0x0020,
+ Anchors = 0x0040,
+ Notes = 0x0080,
+ Clusters = 0x0100,
+ NodeTree = 0x0200,
+ FaceTree = 0x0400,
+ ClusterTree = 0x0800,
+ Joints = 0x1000,
+ /* presets */
+ Std = Links+Faces+Tetras+Anchors+Notes+Joints,
+ StdTetra = Std-Faces+Tetras
+};};
+
+struct btSoftBodyHelpers
+{
+ /* Draw body */
+ static void Draw( btSoftBody* psb,
+ btIDebugDraw* idraw,
+ int drawflags=fDrawFlags::Std);
+ /* Draw body infos */
+ static void DrawInfos( btSoftBody* psb,
+ btIDebugDraw* idraw,
+ bool masses,
+ bool areas,
+ bool stress);
+ /* Draw node tree */
+ static void DrawNodeTree( btSoftBody* psb,
+ btIDebugDraw* idraw,
+ int mindepth=0,
+ int maxdepth=-1);
+ /* Draw face tree */
+ static void DrawFaceTree( btSoftBody* psb,
+ btIDebugDraw* idraw,
+ int mindepth=0,
+ int maxdepth=-1);
+ /* Draw cluster tree */
+ static void DrawClusterTree(btSoftBody* psb,
+ btIDebugDraw* idraw,
+ int mindepth=0,
+ int maxdepth=-1);
+ /* Draw rigid frame */
+ static void DrawFrame( btSoftBody* psb,
+ btIDebugDraw* idraw);
+ /* Create a rope */
+ static btSoftBody* CreateRope( btSoftBodyWorldInfo& worldInfo,
+ const btVector3& from,
+ const btVector3& to,
+ int res,
+ int fixeds);
+ /* Create a patch */
+ static btSoftBody* CreatePatch(btSoftBodyWorldInfo& worldInfo,
+ const btVector3& corner00,
+ const btVector3& corner10,
+ const btVector3& corner01,
+ const btVector3& corner11,
+ int resx,
+ int resy,
+ int fixeds,
+ bool gendiags);
+ /* Create a patch with UV Texture Coordinates */
+ static btSoftBody* CreatePatchUV(btSoftBodyWorldInfo& worldInfo,
+ const btVector3& corner00,
+ const btVector3& corner10,
+ const btVector3& corner01,
+ const btVector3& corner11,
+ int resx,
+ int resy,
+ int fixeds,
+ bool gendiags,
+ float* tex_coords=0);
+ static float CalculateUV(int resx,int resy,int ix,int iy,int id);
+ /* Create an ellipsoid */
+ static btSoftBody* CreateEllipsoid(btSoftBodyWorldInfo& worldInfo,
+ const btVector3& center,
+ const btVector3& radius,
+ int res);
+ /* Create from trimesh */
+ static btSoftBody* CreateFromTriMesh( btSoftBodyWorldInfo& worldInfo,
+ const btScalar* vertices,
+ const int* triangles,
+ int ntriangles,
+ bool randomizeConstraints = true);
+ /* Create from convex-hull */
+ static btSoftBody* CreateFromConvexHull( btSoftBodyWorldInfo& worldInfo,
+ const btVector3* vertices,
+ int nvertices,
+ bool randomizeConstraints = true);
+
+
+ /* Export TetGen compatible .smesh file */
+// static void ExportAsSMeshFile( btSoftBody* psb,
+// const char* filename);
+ /* Create from TetGen .ele, .face, .node files */
+// static btSoftBody* CreateFromTetGenFile( btSoftBodyWorldInfo& worldInfo,
+// const char* ele,
+// const char* face,
+// const char* node,
+// bool bfacelinks,
+// bool btetralinks,
+// bool bfacesfromtetras);
+ /* Create from TetGen .ele, .face, .node data */
+ static btSoftBody* CreateFromTetGenData( btSoftBodyWorldInfo& worldInfo,
+ const char* ele,
+ const char* face,
+ const char* node,
+ bool bfacelinks,
+ bool btetralinks,
+ bool bfacesfromtetras);
+
+ /// 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,
+ /// so out-of-order processors can execute instructions from multiple iterations at once
+ static void ReoptimizeLinkOrder(btSoftBody *psb );
+};
+
+#endif //BT_SOFT_BODY_HELPERS_H
diff --git a/thirdparty/bullet/src/BulletSoftBody/btSoftBodyInternals.h b/thirdparty/bullet/src/BulletSoftBody/btSoftBodyInternals.h
new file mode 100644
index 0000000000..1ad82616ea
--- /dev/null
+++ b/thirdparty/bullet/src/BulletSoftBody/btSoftBodyInternals.h
@@ -0,0 +1,911 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+///btSoftBody implementation by Nathanael Presson
+
+#ifndef _BT_SOFT_BODY_INTERNALS_H
+#define _BT_SOFT_BODY_INTERNALS_H
+
+#include "btSoftBody.h"
+
+
+#include "LinearMath/btQuickprof.h"
+#include "LinearMath/btPolarDecomposition.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/CollisionShapes/btConvexInternalShape.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h"
+#include <string.h> //for memset
+//
+// btSymMatrix
+//
+template <typename T>
+struct btSymMatrix
+{
+ btSymMatrix() : dim(0) {}
+ btSymMatrix(int n,const T& init=T()) { resize(n,init); }
+ void resize(int n,const T& init=T()) { dim=n;store.resize((n*(n+1))/2,init); }
+ int index(int c,int r) const { if(c>r) btSwap(c,r);btAssert(r<dim);return((r*(r+1))/2+c); }
+ T& operator()(int c,int r) { return(store[index(c,r)]); }
+ const T& operator()(int c,int r) const { return(store[index(c,r)]); }
+ btAlignedObjectArray<T> store;
+ int dim;
+};
+
+//
+// btSoftBodyCollisionShape
+//
+class btSoftBodyCollisionShape : public btConcaveShape
+{
+public:
+ btSoftBody* m_body;
+
+ btSoftBodyCollisionShape(btSoftBody* backptr)
+ {
+ m_shapeType = SOFTBODY_SHAPE_PROXYTYPE;
+ m_body=backptr;
+ }
+
+ virtual ~btSoftBodyCollisionShape()
+ {
+
+ }
+
+ void processAllTriangles(btTriangleCallback* /*callback*/,const btVector3& /*aabbMin*/,const btVector3& /*aabbMax*/) const
+ {
+ //not yet
+ btAssert(0);
+ }
+
+ ///getAabb returns the axis aligned bounding box in the coordinate frame of the given transform t.
+ virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+ {
+ /* t is usually identity, except when colliding against btCompoundShape. See Issue 512 */
+ const btVector3 mins=m_body->m_bounds[0];
+ const btVector3 maxs=m_body->m_bounds[1];
+ const btVector3 crns[]={t*btVector3(mins.x(),mins.y(),mins.z()),
+ t*btVector3(maxs.x(),mins.y(),mins.z()),
+ t*btVector3(maxs.x(),maxs.y(),mins.z()),
+ t*btVector3(mins.x(),maxs.y(),mins.z()),
+ t*btVector3(mins.x(),mins.y(),maxs.z()),
+ t*btVector3(maxs.x(),mins.y(),maxs.z()),
+ t*btVector3(maxs.x(),maxs.y(),maxs.z()),
+ t*btVector3(mins.x(),maxs.y(),maxs.z())};
+ aabbMin=aabbMax=crns[0];
+ for(int i=1;i<8;++i)
+ {
+ aabbMin.setMin(crns[i]);
+ aabbMax.setMax(crns[i]);
+ }
+ }
+
+
+ virtual void setLocalScaling(const btVector3& /*scaling*/)
+ {
+ ///na
+ }
+ virtual const btVector3& getLocalScaling() const
+ {
+ static const btVector3 dummy(1,1,1);
+ return dummy;
+ }
+ virtual void calculateLocalInertia(btScalar /*mass*/,btVector3& /*inertia*/) const
+ {
+ ///not yet
+ btAssert(0);
+ }
+ virtual const char* getName()const
+ {
+ return "SoftBody";
+ }
+
+};
+
+//
+// btSoftClusterCollisionShape
+//
+class btSoftClusterCollisionShape : public btConvexInternalShape
+{
+public:
+ const btSoftBody::Cluster* m_cluster;
+
+ btSoftClusterCollisionShape (const btSoftBody::Cluster* cluster) : m_cluster(cluster) { setMargin(0); }
+
+
+ virtual btVector3 localGetSupportingVertex(const btVector3& vec) const
+ {
+ btSoftBody::Node* const * n=&m_cluster->m_nodes[0];
+ btScalar d=btDot(vec,n[0]->m_x);
+ int j=0;
+ for(int i=1,ni=m_cluster->m_nodes.size();i<ni;++i)
+ {
+ const btScalar k=btDot(vec,n[i]->m_x);
+ if(k>d) { d=k;j=i; }
+ }
+ return(n[j]->m_x);
+ }
+ virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const
+ {
+ return(localGetSupportingVertex(vec));
+ }
+ //notice that the vectors should be unit length
+ virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+ {}
+
+
+ virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const
+ {}
+
+ virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+ {}
+
+ virtual int getShapeType() const { return SOFTBODY_SHAPE_PROXYTYPE; }
+
+ //debugging
+ virtual const char* getName()const {return "SOFTCLUSTER";}
+
+ virtual void setMargin(btScalar margin)
+ {
+ btConvexInternalShape::setMargin(margin);
+ }
+ virtual btScalar getMargin() const
+ {
+ return btConvexInternalShape::getMargin();
+ }
+};
+
+//
+// Inline's
+//
+
+//
+template <typename T>
+static inline void ZeroInitialize(T& value)
+{
+ memset(&value,0,sizeof(T));
+}
+//
+template <typename T>
+static inline bool CompLess(const T& a,const T& b)
+{ return(a<b); }
+//
+template <typename T>
+static inline bool CompGreater(const T& a,const T& b)
+{ return(a>b); }
+//
+template <typename T>
+static inline T Lerp(const T& a,const T& b,btScalar t)
+{ return(a+(b-a)*t); }
+//
+template <typename T>
+static inline T InvLerp(const T& a,const T& b,btScalar t)
+{ return((b+a*t-b*t)/(a*b)); }
+//
+static inline btMatrix3x3 Lerp( const btMatrix3x3& a,
+ const btMatrix3x3& b,
+ btScalar t)
+{
+ btMatrix3x3 r;
+ r[0]=Lerp(a[0],b[0],t);
+ r[1]=Lerp(a[1],b[1],t);
+ r[2]=Lerp(a[2],b[2],t);
+ return(r);
+}
+//
+static inline btVector3 Clamp(const btVector3& v,btScalar maxlength)
+{
+ const btScalar sql=v.length2();
+ if(sql>(maxlength*maxlength))
+ return((v*maxlength)/btSqrt(sql));
+ else
+ return(v);
+}
+//
+template <typename T>
+static inline T Clamp(const T& x,const T& l,const T& h)
+{ return(x<l?l:x>h?h:x); }
+//
+template <typename T>
+static inline T Sq(const T& x)
+{ return(x*x); }
+//
+template <typename T>
+static inline T Cube(const T& x)
+{ return(x*x*x); }
+//
+template <typename T>
+static inline T Sign(const T& x)
+{ return((T)(x<0?-1:+1)); }
+//
+template <typename T>
+static inline bool SameSign(const T& x,const T& y)
+{ return((x*y)>0); }
+//
+static inline btScalar ClusterMetric(const btVector3& x,const btVector3& y)
+{
+ const btVector3 d=x-y;
+ return(btFabs(d[0])+btFabs(d[1])+btFabs(d[2]));
+}
+//
+static inline btMatrix3x3 ScaleAlongAxis(const btVector3& a,btScalar s)
+{
+ const btScalar xx=a.x()*a.x();
+ const btScalar yy=a.y()*a.y();
+ const btScalar zz=a.z()*a.z();
+ const btScalar xy=a.x()*a.y();
+ const btScalar yz=a.y()*a.z();
+ const btScalar zx=a.z()*a.x();
+ btMatrix3x3 m;
+ m[0]=btVector3(1-xx+xx*s,xy*s-xy,zx*s-zx);
+ m[1]=btVector3(xy*s-xy,1-yy+yy*s,yz*s-yz);
+ m[2]=btVector3(zx*s-zx,yz*s-yz,1-zz+zz*s);
+ return(m);
+}
+//
+static inline btMatrix3x3 Cross(const btVector3& v)
+{
+ btMatrix3x3 m;
+ m[0]=btVector3(0,-v.z(),+v.y());
+ m[1]=btVector3(+v.z(),0,-v.x());
+ m[2]=btVector3(-v.y(),+v.x(),0);
+ return(m);
+}
+//
+static inline btMatrix3x3 Diagonal(btScalar x)
+{
+ btMatrix3x3 m;
+ m[0]=btVector3(x,0,0);
+ m[1]=btVector3(0,x,0);
+ m[2]=btVector3(0,0,x);
+ return(m);
+}
+//
+static inline btMatrix3x3 Add(const btMatrix3x3& a,
+ const btMatrix3x3& b)
+{
+ btMatrix3x3 r;
+ for(int i=0;i<3;++i) r[i]=a[i]+b[i];
+ return(r);
+}
+//
+static inline btMatrix3x3 Sub(const btMatrix3x3& a,
+ const btMatrix3x3& b)
+{
+ btMatrix3x3 r;
+ for(int i=0;i<3;++i) r[i]=a[i]-b[i];
+ return(r);
+}
+//
+static inline btMatrix3x3 Mul(const btMatrix3x3& a,
+ btScalar b)
+{
+ btMatrix3x3 r;
+ for(int i=0;i<3;++i) r[i]=a[i]*b;
+ return(r);
+}
+//
+static inline void Orthogonalize(btMatrix3x3& m)
+{
+ m[2]=btCross(m[0],m[1]).normalized();
+ m[1]=btCross(m[2],m[0]).normalized();
+ m[0]=btCross(m[1],m[2]).normalized();
+}
+//
+static inline btMatrix3x3 MassMatrix(btScalar im,const btMatrix3x3& iwi,const btVector3& r)
+{
+ const btMatrix3x3 cr=Cross(r);
+ return(Sub(Diagonal(im),cr*iwi*cr));
+}
+
+//
+static inline btMatrix3x3 ImpulseMatrix( btScalar dt,
+ btScalar ima,
+ btScalar imb,
+ const btMatrix3x3& iwi,
+ const btVector3& r)
+{
+ return(Diagonal(1/dt)*Add(Diagonal(ima),MassMatrix(imb,iwi,r)).inverse());
+}
+
+//
+static inline btMatrix3x3 ImpulseMatrix( btScalar ima,const btMatrix3x3& iia,const btVector3& ra,
+ btScalar imb,const btMatrix3x3& iib,const btVector3& rb)
+{
+ return(Add(MassMatrix(ima,iia,ra),MassMatrix(imb,iib,rb)).inverse());
+}
+
+//
+static inline btMatrix3x3 AngularImpulseMatrix( const btMatrix3x3& iia,
+ const btMatrix3x3& iib)
+{
+ return(Add(iia,iib).inverse());
+}
+
+//
+static inline btVector3 ProjectOnAxis( const btVector3& v,
+ const btVector3& a)
+{
+ return(a*btDot(v,a));
+}
+//
+static inline btVector3 ProjectOnPlane( const btVector3& v,
+ const btVector3& a)
+{
+ return(v-ProjectOnAxis(v,a));
+}
+
+//
+static inline void ProjectOrigin( const btVector3& a,
+ const btVector3& b,
+ btVector3& prj,
+ btScalar& sqd)
+{
+ const btVector3 d=b-a;
+ const btScalar m2=d.length2();
+ if(m2>SIMD_EPSILON)
+ {
+ const btScalar t=Clamp<btScalar>(-btDot(a,d)/m2,0,1);
+ const btVector3 p=a+d*t;
+ const btScalar l2=p.length2();
+ if(l2<sqd)
+ {
+ prj=p;
+ sqd=l2;
+ }
+ }
+}
+//
+static inline void ProjectOrigin( const btVector3& a,
+ const btVector3& b,
+ const btVector3& c,
+ btVector3& prj,
+ btScalar& sqd)
+{
+ const btVector3& q=btCross(b-a,c-a);
+ const btScalar m2=q.length2();
+ if(m2>SIMD_EPSILON)
+ {
+ const btVector3 n=q/btSqrt(m2);
+ const btScalar k=btDot(a,n);
+ const btScalar k2=k*k;
+ if(k2<sqd)
+ {
+ const btVector3 p=n*k;
+ if( (btDot(btCross(a-p,b-p),q)>0)&&
+ (btDot(btCross(b-p,c-p),q)>0)&&
+ (btDot(btCross(c-p,a-p),q)>0))
+ {
+ prj=p;
+ sqd=k2;
+ }
+ else
+ {
+ ProjectOrigin(a,b,prj,sqd);
+ ProjectOrigin(b,c,prj,sqd);
+ ProjectOrigin(c,a,prj,sqd);
+ }
+ }
+ }
+}
+
+//
+template <typename T>
+static inline T BaryEval( const T& a,
+ const T& b,
+ const T& c,
+ const btVector3& coord)
+{
+ return(a*coord.x()+b*coord.y()+c*coord.z());
+}
+//
+static inline btVector3 BaryCoord( const btVector3& a,
+ const btVector3& b,
+ const btVector3& c,
+ const btVector3& p)
+{
+ const btScalar w[]={ btCross(a-p,b-p).length(),
+ btCross(b-p,c-p).length(),
+ btCross(c-p,a-p).length()};
+ const btScalar isum=1/(w[0]+w[1]+w[2]);
+ return(btVector3(w[1]*isum,w[2]*isum,w[0]*isum));
+}
+
+//
+inline static btScalar ImplicitSolve( btSoftBody::ImplicitFn* fn,
+ const btVector3& a,
+ const btVector3& b,
+ const btScalar accuracy,
+ const int maxiterations=256)
+{
+ btScalar span[2]={0,1};
+ btScalar values[2]={fn->Eval(a),fn->Eval(b)};
+ if(values[0]>values[1])
+ {
+ btSwap(span[0],span[1]);
+ btSwap(values[0],values[1]);
+ }
+ if(values[0]>-accuracy) return(-1);
+ if(values[1]<+accuracy) return(-1);
+ for(int i=0;i<maxiterations;++i)
+ {
+ const btScalar t=Lerp(span[0],span[1],values[0]/(values[0]-values[1]));
+ const btScalar v=fn->Eval(Lerp(a,b,t));
+ if((t<=0)||(t>=1)) break;
+ if(btFabs(v)<accuracy) return(t);
+ if(v<0)
+ { span[0]=t;values[0]=v; }
+ else
+ { span[1]=t;values[1]=v; }
+ }
+ return(-1);
+}
+
+inline static void EvaluateMedium( const btSoftBodyWorldInfo* wfi,
+ const btVector3& x,
+ btSoftBody::sMedium& medium)
+{
+ medium.m_velocity = btVector3(0,0,0);
+ medium.m_pressure = 0;
+ medium.m_density = wfi->air_density;
+ if(wfi->water_density>0)
+ {
+ const btScalar depth=-(btDot(x,wfi->water_normal)+wfi->water_offset);
+ if(depth>0)
+ {
+ medium.m_density = wfi->water_density;
+ medium.m_pressure = depth*wfi->water_density*wfi->m_gravity.length();
+ }
+ }
+}
+
+
+//
+static inline btVector3 NormalizeAny(const btVector3& v)
+{
+ const btScalar l=v.length();
+ if(l>SIMD_EPSILON)
+ return(v/l);
+ else
+ return(btVector3(0,0,0));
+}
+
+//
+static inline btDbvtVolume VolumeOf( const btSoftBody::Face& f,
+ btScalar margin)
+{
+ const btVector3* pts[]={ &f.m_n[0]->m_x,
+ &f.m_n[1]->m_x,
+ &f.m_n[2]->m_x};
+ btDbvtVolume vol=btDbvtVolume::FromPoints(pts,3);
+ vol.Expand(btVector3(margin,margin,margin));
+ return(vol);
+}
+
+//
+static inline btVector3 CenterOf( const btSoftBody::Face& f)
+{
+ return((f.m_n[0]->m_x+f.m_n[1]->m_x+f.m_n[2]->m_x)/3);
+}
+
+//
+static inline btScalar AreaOf( const btVector3& x0,
+ const btVector3& x1,
+ const btVector3& x2)
+{
+ const btVector3 a=x1-x0;
+ const btVector3 b=x2-x0;
+ const btVector3 cr=btCross(a,b);
+ const btScalar area=cr.length();
+ return(area);
+}
+
+//
+static inline btScalar VolumeOf( const btVector3& x0,
+ const btVector3& x1,
+ const btVector3& x2,
+ const btVector3& x3)
+{
+ const btVector3 a=x1-x0;
+ const btVector3 b=x2-x0;
+ const btVector3 c=x3-x0;
+ return(btDot(a,btCross(b,c)));
+}
+
+//
+
+
+//
+static inline void ApplyClampedForce( btSoftBody::Node& n,
+ const btVector3& f,
+ btScalar dt)
+{
+ const btScalar dtim=dt*n.m_im;
+ if((f*dtim).length2()>n.m_v.length2())
+ {/* Clamp */
+ n.m_f-=ProjectOnAxis(n.m_v,f.normalized())/dtim;
+ }
+ else
+ {/* Apply */
+ n.m_f+=f;
+ }
+}
+
+//
+static inline int MatchEdge( const btSoftBody::Node* a,
+ const btSoftBody::Node* b,
+ const btSoftBody::Node* ma,
+ const btSoftBody::Node* mb)
+{
+ if((a==ma)&&(b==mb)) return(0);
+ if((a==mb)&&(b==ma)) return(1);
+ return(-1);
+}
+
+//
+// btEigen : Extract eigen system,
+// straitforward implementation of http://math.fullerton.edu/mathews/n2003/JacobiMethodMod.html
+// outputs are NOT sorted.
+//
+struct btEigen
+{
+ static int system(btMatrix3x3& a,btMatrix3x3* vectors,btVector3* values=0)
+ {
+ static const int maxiterations=16;
+ static const btScalar accuracy=(btScalar)0.0001;
+ btMatrix3x3& v=*vectors;
+ int iterations=0;
+ vectors->setIdentity();
+ do {
+ int p=0,q=1;
+ if(btFabs(a[p][q])<btFabs(a[0][2])) { p=0;q=2; }
+ if(btFabs(a[p][q])<btFabs(a[1][2])) { p=1;q=2; }
+ if(btFabs(a[p][q])>accuracy)
+ {
+ const btScalar w=(a[q][q]-a[p][p])/(2*a[p][q]);
+ const btScalar z=btFabs(w);
+ const btScalar t=w/(z*(btSqrt(1+w*w)+z));
+ if(t==t)/* [WARNING] let hope that one does not get thrown aways by some compilers... */
+ {
+ const btScalar c=1/btSqrt(t*t+1);
+ const btScalar s=c*t;
+ mulPQ(a,c,s,p,q);
+ mulTPQ(a,c,s,p,q);
+ mulPQ(v,c,s,p,q);
+ } else break;
+ } else break;
+ } while((++iterations)<maxiterations);
+ if(values)
+ {
+ *values=btVector3(a[0][0],a[1][1],a[2][2]);
+ }
+ return(iterations);
+ }
+private:
+ static inline void mulTPQ(btMatrix3x3& a,btScalar c,btScalar s,int p,int q)
+ {
+ const btScalar m[2][3]={ {a[p][0],a[p][1],a[p][2]},
+ {a[q][0],a[q][1],a[q][2]}};
+ int i;
+
+ for(i=0;i<3;++i) a[p][i]=c*m[0][i]-s*m[1][i];
+ for(i=0;i<3;++i) a[q][i]=c*m[1][i]+s*m[0][i];
+ }
+ static inline void mulPQ(btMatrix3x3& a,btScalar c,btScalar s,int p,int q)
+ {
+ const btScalar m[2][3]={ {a[0][p],a[1][p],a[2][p]},
+ {a[0][q],a[1][q],a[2][q]}};
+ int i;
+
+ for(i=0;i<3;++i) a[i][p]=c*m[0][i]-s*m[1][i];
+ for(i=0;i<3;++i) a[i][q]=c*m[1][i]+s*m[0][i];
+ }
+};
+
+//
+// Polar decomposition,
+// "Computing the Polar Decomposition with Applications", Nicholas J. Higham, 1986.
+//
+static inline int PolarDecompose( const btMatrix3x3& m,btMatrix3x3& q,btMatrix3x3& s)
+{
+ static const btPolarDecomposition polar;
+ return polar.decompose(m, q, s);
+}
+
+//
+// btSoftColliders
+//
+struct btSoftColliders
+{
+ //
+ // ClusterBase
+ //
+ struct ClusterBase : btDbvt::ICollide
+ {
+ btScalar erp;
+ btScalar idt;
+ btScalar m_margin;
+ btScalar friction;
+ btScalar threshold;
+ ClusterBase()
+ {
+ erp =(btScalar)1;
+ idt =0;
+ m_margin =0;
+ friction =0;
+ threshold =(btScalar)0;
+ }
+ bool SolveContact( const btGjkEpaSolver2::sResults& res,
+ btSoftBody::Body ba,const btSoftBody::Body bb,
+ btSoftBody::CJoint& joint)
+ {
+ if(res.distance<m_margin)
+ {
+ btVector3 norm = res.normal;
+ norm.normalize();//is it necessary?
+
+ const btVector3 ra=res.witnesses[0]-ba.xform().getOrigin();
+ const btVector3 rb=res.witnesses[1]-bb.xform().getOrigin();
+ const btVector3 va=ba.velocity(ra);
+ const btVector3 vb=bb.velocity(rb);
+ const btVector3 vrel=va-vb;
+ const btScalar rvac=btDot(vrel,norm);
+ btScalar depth=res.distance-m_margin;
+
+// printf("depth=%f\n",depth);
+ const btVector3 iv=norm*rvac;
+ const btVector3 fv=vrel-iv;
+ joint.m_bodies[0] = ba;
+ joint.m_bodies[1] = bb;
+ joint.m_refs[0] = ra*ba.xform().getBasis();
+ joint.m_refs[1] = rb*bb.xform().getBasis();
+ joint.m_rpos[0] = ra;
+ joint.m_rpos[1] = rb;
+ joint.m_cfm = 1;
+ joint.m_erp = 1;
+ joint.m_life = 0;
+ joint.m_maxlife = 0;
+ joint.m_split = 1;
+
+ joint.m_drift = depth*norm;
+
+ joint.m_normal = norm;
+// printf("normal=%f,%f,%f\n",res.normal.getX(),res.normal.getY(),res.normal.getZ());
+ joint.m_delete = false;
+ joint.m_friction = fv.length2()<(rvac*friction*rvac*friction)?1:friction;
+ joint.m_massmatrix = ImpulseMatrix( ba.invMass(),ba.invWorldInertia(),joint.m_rpos[0],
+ bb.invMass(),bb.invWorldInertia(),joint.m_rpos[1]);
+
+ return(true);
+ }
+ return(false);
+ }
+ };
+ //
+ // CollideCL_RS
+ //
+ struct CollideCL_RS : ClusterBase
+ {
+ btSoftBody* psb;
+ const btCollisionObjectWrapper* m_colObjWrap;
+
+ void Process(const btDbvtNode* leaf)
+ {
+ btSoftBody::Cluster* cluster=(btSoftBody::Cluster*)leaf->data;
+ btSoftClusterCollisionShape cshape(cluster);
+
+ const btConvexShape* rshape=(const btConvexShape*)m_colObjWrap->getCollisionShape();
+
+ ///don't collide an anchored cluster with a static/kinematic object
+ if(m_colObjWrap->getCollisionObject()->isStaticOrKinematicObject() && cluster->m_containsAnchor)
+ return;
+
+ btGjkEpaSolver2::sResults res;
+ if(btGjkEpaSolver2::SignedDistance( &cshape,btTransform::getIdentity(),
+ rshape,m_colObjWrap->getWorldTransform(),
+ btVector3(1,0,0),res))
+ {
+ btSoftBody::CJoint joint;
+ if(SolveContact(res,cluster,m_colObjWrap->getCollisionObject(),joint))//prb,joint))
+ {
+ btSoftBody::CJoint* pj=new(btAlignedAlloc(sizeof(btSoftBody::CJoint),16)) btSoftBody::CJoint();
+ *pj=joint;psb->m_joints.push_back(pj);
+ if(m_colObjWrap->getCollisionObject()->isStaticOrKinematicObject())
+ {
+ pj->m_erp *= psb->m_cfg.kSKHR_CL;
+ pj->m_split *= psb->m_cfg.kSK_SPLT_CL;
+ }
+ else
+ {
+ pj->m_erp *= psb->m_cfg.kSRHR_CL;
+ pj->m_split *= psb->m_cfg.kSR_SPLT_CL;
+ }
+ }
+ }
+ }
+ void ProcessColObj(btSoftBody* ps,const btCollisionObjectWrapper* colObWrap)
+ {
+ psb = ps;
+ m_colObjWrap = colObWrap;
+ idt = ps->m_sst.isdt;
+ m_margin = m_colObjWrap->getCollisionShape()->getMargin()+psb->getCollisionShape()->getMargin();
+ ///Bullet rigid body uses multiply instead of minimum to determine combined friction. Some customization would be useful.
+ friction = btMin(psb->m_cfg.kDF,m_colObjWrap->getCollisionObject()->getFriction());
+ btVector3 mins;
+ btVector3 maxs;
+
+ ATTRIBUTE_ALIGNED16(btDbvtVolume) volume;
+ colObWrap->getCollisionShape()->getAabb(colObWrap->getWorldTransform(),mins,maxs);
+ volume=btDbvtVolume::FromMM(mins,maxs);
+ volume.Expand(btVector3(1,1,1)*m_margin);
+ ps->m_cdbvt.collideTV(ps->m_cdbvt.m_root,volume,*this);
+ }
+ };
+ //
+ // CollideCL_SS
+ //
+ struct CollideCL_SS : ClusterBase
+ {
+ btSoftBody* bodies[2];
+ void Process(const btDbvtNode* la,const btDbvtNode* lb)
+ {
+ btSoftBody::Cluster* cla=(btSoftBody::Cluster*)la->data;
+ btSoftBody::Cluster* clb=(btSoftBody::Cluster*)lb->data;
+
+
+ bool connected=false;
+ if ((bodies[0]==bodies[1])&&(bodies[0]->m_clusterConnectivity.size()))
+ {
+ connected = bodies[0]->m_clusterConnectivity[cla->m_clusterIndex+bodies[0]->m_clusters.size()*clb->m_clusterIndex];
+ }
+
+ if (!connected)
+ {
+ btSoftClusterCollisionShape csa(cla);
+ btSoftClusterCollisionShape csb(clb);
+ btGjkEpaSolver2::sResults res;
+ if(btGjkEpaSolver2::SignedDistance( &csa,btTransform::getIdentity(),
+ &csb,btTransform::getIdentity(),
+ cla->m_com-clb->m_com,res))
+ {
+ btSoftBody::CJoint joint;
+ if(SolveContact(res,cla,clb,joint))
+ {
+ btSoftBody::CJoint* pj=new(btAlignedAlloc(sizeof(btSoftBody::CJoint),16)) btSoftBody::CJoint();
+ *pj=joint;bodies[0]->m_joints.push_back(pj);
+ pj->m_erp *= btMax(bodies[0]->m_cfg.kSSHR_CL,bodies[1]->m_cfg.kSSHR_CL);
+ pj->m_split *= (bodies[0]->m_cfg.kSS_SPLT_CL+bodies[1]->m_cfg.kSS_SPLT_CL)/2;
+ }
+ }
+ } else
+ {
+ static int count=0;
+ count++;
+ //printf("count=%d\n",count);
+
+ }
+ }
+ void ProcessSoftSoft(btSoftBody* psa,btSoftBody* psb)
+ {
+ idt = psa->m_sst.isdt;
+ //m_margin = (psa->getCollisionShape()->getMargin()+psb->getCollisionShape()->getMargin())/2;
+ m_margin = (psa->getCollisionShape()->getMargin()+psb->getCollisionShape()->getMargin());
+ friction = btMin(psa->m_cfg.kDF,psb->m_cfg.kDF);
+ bodies[0] = psa;
+ bodies[1] = psb;
+ 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;
+ };
+ //
+ // CollideVF_SS
+ //
+ struct CollideVF_SS : 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).length()*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::SContact c;
+ c.m_normal = p/-btSqrt(d);
+ c.m_margin = m;
+ 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_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);
+ }
+ }
+ }
+ btSoftBody* psb[2];
+ btScalar mrg;
+ };
+};
+
+#endif //_BT_SOFT_BODY_INTERNALS_H
diff --git a/thirdparty/bullet/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp b/thirdparty/bullet/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp
new file mode 100644
index 0000000000..f5a67f6d89
--- /dev/null
+++ b/thirdparty/bullet/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp
@@ -0,0 +1,134 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btSoftBodyRigidBodyCollisionConfiguration.h"
+#include "btSoftRigidCollisionAlgorithm.h"
+#include "btSoftBodyConcaveCollisionAlgorithm.h"
+#include "btSoftSoftCollisionAlgorithm.h"
+
+#include "LinearMath/btPoolAllocator.h"
+
+#define ENABLE_SOFTBODY_CONCAVE_COLLISIONS 1
+
+btSoftBodyRigidBodyCollisionConfiguration::btSoftBodyRigidBodyCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo)
+:btDefaultCollisionConfiguration(constructionInfo)
+{
+ void* mem;
+
+ mem = btAlignedAlloc(sizeof(btSoftSoftCollisionAlgorithm::CreateFunc),16);
+ m_softSoftCreateFunc = new(mem) btSoftSoftCollisionAlgorithm::CreateFunc;
+
+ mem = btAlignedAlloc(sizeof(btSoftRigidCollisionAlgorithm::CreateFunc),16);
+ m_softRigidConvexCreateFunc = new(mem) btSoftRigidCollisionAlgorithm::CreateFunc;
+
+ mem = btAlignedAlloc(sizeof(btSoftRigidCollisionAlgorithm::CreateFunc),16);
+ m_swappedSoftRigidConvexCreateFunc = new(mem) btSoftRigidCollisionAlgorithm::CreateFunc;
+ m_swappedSoftRigidConvexCreateFunc->m_swapped=true;
+
+#ifdef ENABLE_SOFTBODY_CONCAVE_COLLISIONS
+ mem = btAlignedAlloc(sizeof(btSoftBodyConcaveCollisionAlgorithm::CreateFunc),16);
+ m_softRigidConcaveCreateFunc = new(mem) btSoftBodyConcaveCollisionAlgorithm::CreateFunc;
+
+ mem = btAlignedAlloc(sizeof(btSoftBodyConcaveCollisionAlgorithm::CreateFunc),16);
+ m_swappedSoftRigidConcaveCreateFunc = new(mem) btSoftBodyConcaveCollisionAlgorithm::SwappedCreateFunc;
+ m_swappedSoftRigidConcaveCreateFunc->m_swapped=true;
+#endif
+
+ //replace pool by a new one, with potential larger size
+
+ if (m_ownsCollisionAlgorithmPool && m_collisionAlgorithmPool)
+ {
+ int curElemSize = m_collisionAlgorithmPool->getElementSize();
+ ///calculate maximum element size, big enough to fit any collision algorithm in the memory pool
+
+
+ int maxSize0 = sizeof(btSoftSoftCollisionAlgorithm);
+ int maxSize1 = sizeof(btSoftRigidCollisionAlgorithm);
+ int maxSize2 = sizeof(btSoftBodyConcaveCollisionAlgorithm);
+
+ int collisionAlgorithmMaxElementSize = btMax(maxSize0,maxSize1);
+ collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize,maxSize2);
+
+ if (collisionAlgorithmMaxElementSize > curElemSize)
+ {
+ m_collisionAlgorithmPool->~btPoolAllocator();
+ btAlignedFree(m_collisionAlgorithmPool);
+ void* mem = btAlignedAlloc(sizeof(btPoolAllocator),16);
+ m_collisionAlgorithmPool = new(mem) btPoolAllocator(collisionAlgorithmMaxElementSize,constructionInfo.m_defaultMaxCollisionAlgorithmPoolSize);
+ }
+ }
+
+}
+
+btSoftBodyRigidBodyCollisionConfiguration::~btSoftBodyRigidBodyCollisionConfiguration()
+{
+ m_softSoftCreateFunc->~btCollisionAlgorithmCreateFunc();
+ btAlignedFree( m_softSoftCreateFunc);
+
+ m_softRigidConvexCreateFunc->~btCollisionAlgorithmCreateFunc();
+ btAlignedFree( m_softRigidConvexCreateFunc);
+
+ m_swappedSoftRigidConvexCreateFunc->~btCollisionAlgorithmCreateFunc();
+ btAlignedFree( m_swappedSoftRigidConvexCreateFunc);
+
+#ifdef ENABLE_SOFTBODY_CONCAVE_COLLISIONS
+ m_softRigidConcaveCreateFunc->~btCollisionAlgorithmCreateFunc();
+ btAlignedFree( m_softRigidConcaveCreateFunc);
+
+ m_swappedSoftRigidConcaveCreateFunc->~btCollisionAlgorithmCreateFunc();
+ btAlignedFree( m_swappedSoftRigidConcaveCreateFunc);
+#endif
+}
+
+///creation of soft-soft and soft-rigid, and otherwise fallback to base class implementation
+btCollisionAlgorithmCreateFunc* btSoftBodyRigidBodyCollisionConfiguration::getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1)
+{
+
+ ///try to handle the softbody interactions first
+
+ if ((proxyType0 == SOFTBODY_SHAPE_PROXYTYPE ) && (proxyType1==SOFTBODY_SHAPE_PROXYTYPE))
+ {
+ return m_softSoftCreateFunc;
+ }
+
+ ///softbody versus convex
+ if (proxyType0 == SOFTBODY_SHAPE_PROXYTYPE && btBroadphaseProxy::isConvex(proxyType1))
+ {
+ return m_softRigidConvexCreateFunc;
+ }
+
+ ///convex versus soft body
+ if (btBroadphaseProxy::isConvex(proxyType0) && proxyType1 == SOFTBODY_SHAPE_PROXYTYPE )
+ {
+ return m_swappedSoftRigidConvexCreateFunc;
+ }
+
+#ifdef ENABLE_SOFTBODY_CONCAVE_COLLISIONS
+ ///softbody versus convex
+ if (proxyType0 == SOFTBODY_SHAPE_PROXYTYPE && btBroadphaseProxy::isConcave(proxyType1))
+ {
+ return m_softRigidConcaveCreateFunc;
+ }
+
+ ///convex versus soft body
+ if (btBroadphaseProxy::isConcave(proxyType0) && proxyType1 == SOFTBODY_SHAPE_PROXYTYPE )
+ {
+ return m_swappedSoftRigidConcaveCreateFunc;
+ }
+#endif
+
+ ///fallback to the regular rigid collision shape
+ return btDefaultCollisionConfiguration::getCollisionAlgorithmCreateFunc(proxyType0,proxyType1);
+}
diff --git a/thirdparty/bullet/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h b/thirdparty/bullet/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h
new file mode 100644
index 0000000000..21addcfe2e
--- /dev/null
+++ b/thirdparty/bullet/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h
@@ -0,0 +1,48 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_SOFTBODY_RIGIDBODY_COLLISION_CONFIGURATION
+#define BT_SOFTBODY_RIGIDBODY_COLLISION_CONFIGURATION
+
+#include "BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h"
+
+class btVoronoiSimplexSolver;
+class btGjkEpaPenetrationDepthSolver;
+
+
+///btSoftBodyRigidBodyCollisionConfiguration add softbody interaction on top of btDefaultCollisionConfiguration
+class btSoftBodyRigidBodyCollisionConfiguration : public btDefaultCollisionConfiguration
+{
+
+ //default CreationFunctions, filling the m_doubleDispatch table
+ btCollisionAlgorithmCreateFunc* m_softSoftCreateFunc;
+ btCollisionAlgorithmCreateFunc* m_softRigidConvexCreateFunc;
+ btCollisionAlgorithmCreateFunc* m_swappedSoftRigidConvexCreateFunc;
+ btCollisionAlgorithmCreateFunc* m_softRigidConcaveCreateFunc;
+ btCollisionAlgorithmCreateFunc* m_swappedSoftRigidConcaveCreateFunc;
+
+public:
+
+ btSoftBodyRigidBodyCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo = btDefaultCollisionConstructionInfo());
+
+ virtual ~btSoftBodyRigidBodyCollisionConfiguration();
+
+ ///creation of soft-soft and soft-rigid, and otherwise fallback to base class implementation
+ virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1);
+
+};
+
+#endif //BT_SOFTBODY_RIGIDBODY_COLLISION_CONFIGURATION
+
diff --git a/thirdparty/bullet/src/BulletSoftBody/btSoftBodySolverVertexBuffer.h b/thirdparty/bullet/src/BulletSoftBody/btSoftBodySolverVertexBuffer.h
new file mode 100644
index 0000000000..c4733d6400
--- /dev/null
+++ b/thirdparty/bullet/src/BulletSoftBody/btSoftBodySolverVertexBuffer.h
@@ -0,0 +1,165 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_SOFT_BODY_SOLVER_VERTEX_BUFFER_H
+#define BT_SOFT_BODY_SOLVER_VERTEX_BUFFER_H
+
+
+class btVertexBufferDescriptor
+{
+public:
+ enum BufferTypes
+ {
+ CPU_BUFFER,
+ DX11_BUFFER,
+ OPENGL_BUFFER
+ };
+
+protected:
+
+ bool m_hasVertexPositions;
+ bool m_hasNormals;
+
+ int m_vertexOffset;
+ int m_vertexStride;
+
+ int m_normalOffset;
+ int m_normalStride;
+
+public:
+ btVertexBufferDescriptor()
+ {
+ m_hasVertexPositions = false;
+ m_hasNormals = false;
+ m_vertexOffset = 0;
+ m_vertexStride = 0;
+ m_normalOffset = 0;
+ m_normalStride = 0;
+ }
+
+ virtual ~btVertexBufferDescriptor()
+ {
+
+ }
+
+ virtual bool hasVertexPositions() const
+ {
+ return m_hasVertexPositions;
+ }
+
+ virtual bool hasNormals() const
+ {
+ return m_hasNormals;
+ }
+
+ /**
+ * Return the type of the vertex buffer descriptor.
+ */
+ virtual BufferTypes getBufferType() const = 0;
+
+ /**
+ * Return the vertex offset in floats from the base pointer.
+ */
+ virtual int getVertexOffset() const
+ {
+ return m_vertexOffset;
+ }
+
+ /**
+ * Return the vertex stride in number of floats between vertices.
+ */
+ virtual int getVertexStride() const
+ {
+ return m_vertexStride;
+ }
+
+ /**
+ * Return the vertex offset in floats from the base pointer.
+ */
+ virtual int getNormalOffset() const
+ {
+ return m_normalOffset;
+ }
+
+ /**
+ * Return the vertex stride in number of floats between vertices.
+ */
+ virtual int getNormalStride() const
+ {
+ return m_normalStride;
+ }
+};
+
+
+class btCPUVertexBufferDescriptor : public btVertexBufferDescriptor
+{
+protected:
+ float *m_basePointer;
+
+public:
+ /**
+ * vertexBasePointer is pointer to beginning of the buffer.
+ * vertexOffset is the offset in floats to the first vertex.
+ * vertexStride is the stride in floats between vertices.
+ */
+ btCPUVertexBufferDescriptor( float *basePointer, int vertexOffset, int vertexStride )
+ {
+ m_basePointer = basePointer;
+ m_vertexOffset = vertexOffset;
+ m_vertexStride = vertexStride;
+ m_hasVertexPositions = true;
+ }
+
+ /**
+ * vertexBasePointer is pointer to beginning of the buffer.
+ * vertexOffset is the offset in floats to the first vertex.
+ * vertexStride is the stride in floats between vertices.
+ */
+ btCPUVertexBufferDescriptor( float *basePointer, int vertexOffset, int vertexStride, int normalOffset, int normalStride )
+ {
+ m_basePointer = basePointer;
+
+ m_vertexOffset = vertexOffset;
+ m_vertexStride = vertexStride;
+ m_hasVertexPositions = true;
+
+ m_normalOffset = normalOffset;
+ m_normalStride = normalStride;
+ m_hasNormals = true;
+ }
+
+ virtual ~btCPUVertexBufferDescriptor()
+ {
+
+ }
+
+ /**
+ * Return the type of the vertex buffer descriptor.
+ */
+ virtual BufferTypes getBufferType() const
+ {
+ return CPU_BUFFER;
+ }
+
+ /**
+ * Return the base pointer in memory to the first vertex.
+ */
+ virtual float *getBasePointer() const
+ {
+ return m_basePointer;
+ }
+};
+
+#endif // #ifndef BT_SOFT_BODY_SOLVER_VERTEX_BUFFER_H
diff --git a/thirdparty/bullet/src/BulletSoftBody/btSoftBodySolvers.h b/thirdparty/bullet/src/BulletSoftBody/btSoftBodySolvers.h
new file mode 100644
index 0000000000..6947bc27d2
--- /dev/null
+++ b/thirdparty/bullet/src/BulletSoftBody/btSoftBodySolvers.h
@@ -0,0 +1,154 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_SOFT_BODY_SOLVERS_H
+#define BT_SOFT_BODY_SOLVERS_H
+
+#include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h"
+
+
+class btSoftBodyTriangleData;
+class btSoftBodyLinkData;
+class btSoftBodyVertexData;
+class btVertexBufferDescriptor;
+class btCollisionObject;
+class btSoftBody;
+
+
+class btSoftBodySolver
+{
+public:
+ enum SolverTypes
+ {
+ DEFAULT_SOLVER,
+ CPU_SOLVER,
+ CL_SOLVER,
+ CL_SIMD_SOLVER,
+ DX_SOLVER,
+ DX_SIMD_SOLVER
+ };
+
+
+protected:
+ int m_numberOfPositionIterations;
+ int m_numberOfVelocityIterations;
+ // Simulation timescale
+ float m_timeScale;
+
+public:
+ btSoftBodySolver() :
+ m_numberOfPositionIterations( 10 ),
+ m_timeScale( 1 )
+ {
+ m_numberOfVelocityIterations = 0;
+ m_numberOfPositionIterations = 5;
+ }
+
+ virtual ~btSoftBodySolver()
+ {
+ }
+
+ /**
+ * Return the type of the solver.
+ */
+ virtual SolverTypes getSolverType() const = 0;
+
+
+ /** Ensure that this solver is initialized. */
+ virtual bool checkInitialized() = 0;
+
+ /** Optimize soft bodies in this solver. */
+ virtual void optimize( btAlignedObjectArray< btSoftBody * > &softBodies , bool forceUpdate=false) = 0;
+
+ /** Copy necessary data back to the original soft body source objects. */
+ virtual void copyBackToSoftBodies(bool bMove = true) = 0;
+
+ /** Predict motion of soft bodies into next timestep */
+ virtual void predictMotion( float solverdt ) = 0;
+
+ /** Solve constraints for a set of soft bodies */
+ virtual void solveConstraints( float solverdt ) = 0;
+
+ /** Perform necessary per-step updates of soft bodies such as recomputing normals and bounding boxes */
+ virtual void updateSoftBodies() = 0;
+
+ /** Process a collision between one of the world's soft bodies and another collision object */
+ virtual void processCollision( btSoftBody *, const struct btCollisionObjectWrapper* ) = 0;
+
+ /** Process a collision between two soft bodies */
+ virtual void processCollision( btSoftBody*, btSoftBody* ) = 0;
+
+ /** Set the number of velocity constraint solver iterations this solver uses. */
+ virtual void setNumberOfPositionIterations( int iterations )
+ {
+ m_numberOfPositionIterations = iterations;
+ }
+
+ /** Get the number of velocity constraint solver iterations this solver uses. */
+ virtual int getNumberOfPositionIterations()
+ {
+ return m_numberOfPositionIterations;
+ }
+
+ /** Set the number of velocity constraint solver iterations this solver uses. */
+ virtual void setNumberOfVelocityIterations( int iterations )
+ {
+ m_numberOfVelocityIterations = iterations;
+ }
+
+ /** Get the number of velocity constraint solver iterations this solver uses. */
+ virtual int getNumberOfVelocityIterations()
+ {
+ return m_numberOfVelocityIterations;
+ }
+
+ /** Return the timescale that the simulation is using */
+ float getTimeScale()
+ {
+ return m_timeScale;
+ }
+
+#if 0
+ /**
+ * Add a collision object to be used by the indicated softbody.
+ */
+ virtual void addCollisionObjectForSoftBody( int clothIdentifier, btCollisionObject *collisionObject ) = 0;
+#endif
+};
+
+/**
+ * Class to manage movement of data from a solver to a given target.
+ * This version is abstract. Subclasses will have custom pairings for different combinations.
+ */
+class btSoftBodySolverOutput
+{
+protected:
+
+public:
+ btSoftBodySolverOutput()
+ {
+ }
+
+ virtual ~btSoftBodySolverOutput()
+ {
+ }
+
+
+ /** Output current computed vertex data to the vertex buffers for all cloths in the solver. */
+ virtual void copySoftBodyToVertexBuffer( const btSoftBody * const softBody, btVertexBufferDescriptor *vertexBuffer ) = 0;
+};
+
+
+#endif // #ifndef BT_SOFT_BODY_SOLVERS_H
diff --git a/thirdparty/bullet/src/BulletSoftBody/btSoftMultiBodyDynamicsWorld.cpp b/thirdparty/bullet/src/BulletSoftBody/btSoftMultiBodyDynamicsWorld.cpp
new file mode 100644
index 0000000000..4e76dca9db
--- /dev/null
+++ b/thirdparty/bullet/src/BulletSoftBody/btSoftMultiBodyDynamicsWorld.cpp
@@ -0,0 +1,367 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "btSoftMultiBodyDynamicsWorld.h"
+#include "LinearMath/btQuickprof.h"
+
+//softbody & helpers
+#include "BulletSoftBody/btSoftBody.h"
+#include "BulletSoftBody/btSoftBodyHelpers.h"
+#include "BulletSoftBody/btSoftBodySolvers.h"
+#include "BulletSoftBody/btDefaultSoftBodySolver.h"
+#include "LinearMath/btSerializer.h"
+
+
+btSoftMultiBodyDynamicsWorld::btSoftMultiBodyDynamicsWorld(
+ btDispatcher* dispatcher,
+ btBroadphaseInterface* pairCache,
+ btMultiBodyConstraintSolver* constraintSolver,
+ btCollisionConfiguration* collisionConfiguration,
+ btSoftBodySolver *softBodySolver ) :
+ btMultiBodyDynamicsWorld(dispatcher,pairCache,constraintSolver,collisionConfiguration),
+ m_softBodySolver( softBodySolver ),
+ m_ownsSolver(false)
+{
+ if( !m_softBodySolver )
+ {
+ void* ptr = btAlignedAlloc(sizeof(btDefaultSoftBodySolver),16);
+ m_softBodySolver = new(ptr) btDefaultSoftBodySolver();
+ m_ownsSolver = true;
+ }
+
+ 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.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_sbi.m_sparsesdf.Initialize();
+
+
+}
+
+btSoftMultiBodyDynamicsWorld::~btSoftMultiBodyDynamicsWorld()
+{
+ if (m_ownsSolver)
+ {
+ m_softBodySolver->~btSoftBodySolver();
+ btAlignedFree(m_softBodySolver);
+ }
+}
+
+void btSoftMultiBodyDynamicsWorld::predictUnconstraintMotion(btScalar timeStep)
+{
+ btDiscreteDynamicsWorld::predictUnconstraintMotion( timeStep );
+ {
+ BT_PROFILE("predictUnconstraintMotionSoftBody");
+ m_softBodySolver->predictMotion( float(timeStep) );
+ }
+}
+
+void btSoftMultiBodyDynamicsWorld::internalSingleStepSimulation( btScalar timeStep )
+{
+
+ // Let the solver grab the soft bodies and if necessary optimize for it
+ m_softBodySolver->optimize( getSoftBodyArray() );
+
+ if( !m_softBodySolver->checkInitialized() )
+ {
+ btAssert( "Solver initialization failed\n" );
+ }
+
+ btDiscreteDynamicsWorld::internalSingleStepSimulation( timeStep );
+
+ ///solve soft bodies constraints
+ solveSoftBodiesConstraints( timeStep );
+
+ //self collisions
+ for ( int i=0;i<m_softBodies.size();i++)
+ {
+ btSoftBody* psb=(btSoftBody*)m_softBodies[i];
+ psb->defaultCollisionHandler(psb);
+ }
+
+ ///update soft bodies
+ m_softBodySolver->updateSoftBodies( );
+
+ // End solver-wise simulation step
+ // ///////////////////////////////
+
+}
+
+void btSoftMultiBodyDynamicsWorld::solveSoftBodiesConstraints( btScalar timeStep )
+{
+ BT_PROFILE("solveSoftConstraints");
+
+ if(m_softBodies.size())
+ {
+ btSoftBody::solveClusters(m_softBodies);
+ }
+
+ // Solve constraints solver-wise
+ m_softBodySolver->solveConstraints( timeStep * m_softBodySolver->getTimeScale() );
+
+}
+
+void btSoftMultiBodyDynamicsWorld::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_softBodySolver );
+
+ btCollisionWorld::addCollisionObject(body,
+ collisionFilterGroup,
+ collisionFilterMask);
+
+}
+
+void btSoftMultiBodyDynamicsWorld::removeSoftBody(btSoftBody* body)
+{
+ m_softBodies.remove(body);
+
+ btCollisionWorld::removeCollisionObject(body);
+}
+
+void btSoftMultiBodyDynamicsWorld::removeCollisionObject(btCollisionObject* collisionObject)
+{
+ btSoftBody* body = btSoftBody::upcast(collisionObject);
+ if (body)
+ removeSoftBody(body);
+ else
+ btDiscreteDynamicsWorld::removeCollisionObject(collisionObject);
+}
+
+void btSoftMultiBodyDynamicsWorld::debugDrawWorld()
+{
+ btDiscreteDynamicsWorld::debugDrawWorld();
+
+ if (getDebugDrawer())
+ {
+ int i;
+ for ( i=0;i<this->m_softBodies.size();i++)
+ {
+ btSoftBody* psb=(btSoftBody*)this->m_softBodies[i];
+ if (getDebugDrawer() && (getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe)))
+ {
+ btSoftBodyHelpers::DrawFrame(psb,m_debugDrawer);
+ btSoftBodyHelpers::Draw(psb,m_debugDrawer,m_drawFlags);
+ }
+
+ if (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawAabb))
+ {
+ if(m_drawNodeTree) btSoftBodyHelpers::DrawNodeTree(psb,m_debugDrawer);
+ if(m_drawFaceTree) btSoftBodyHelpers::DrawFaceTree(psb,m_debugDrawer);
+ if(m_drawClusterTree) btSoftBodyHelpers::DrawClusterTree(psb,m_debugDrawer);
+ }
+ }
+ }
+}
+
+
+
+
+struct btSoftSingleRayCallback : public btBroadphaseRayCallback
+{
+ btVector3 m_rayFromWorld;
+ btVector3 m_rayToWorld;
+ btTransform m_rayFromTrans;
+ btTransform m_rayToTrans;
+ btVector3 m_hitNormal;
+
+ const btSoftMultiBodyDynamicsWorld* m_world;
+ btCollisionWorld::RayResultCallback& m_resultCallback;
+
+ btSoftSingleRayCallback(const btVector3& rayFromWorld,const btVector3& rayToWorld,const btSoftMultiBodyDynamicsWorld* world,btCollisionWorld::RayResultCallback& resultCallback)
+ :m_rayFromWorld(rayFromWorld),
+ m_rayToWorld(rayToWorld),
+ m_world(world),
+ m_resultCallback(resultCallback)
+ {
+ m_rayFromTrans.setIdentity();
+ m_rayFromTrans.setOrigin(m_rayFromWorld);
+ m_rayToTrans.setIdentity();
+ m_rayToTrans.setOrigin(m_rayToWorld);
+
+ btVector3 rayDir = (rayToWorld-rayFromWorld);
+
+ rayDir.normalize ();
+ ///what about division by zero? --> just set rayDirection[i] to INF/1e30
+ m_rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[0];
+ m_rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[1];
+ m_rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[2];
+ m_signs[0] = m_rayDirectionInverse[0] < 0.0;
+ m_signs[1] = m_rayDirectionInverse[1] < 0.0;
+ m_signs[2] = m_rayDirectionInverse[2] < 0.0;
+
+ m_lambda_max = rayDir.dot(m_rayToWorld-m_rayFromWorld);
+
+ }
+
+
+
+ virtual bool process(const btBroadphaseProxy* proxy)
+ {
+ ///terminate further ray tests, once the closestHitFraction reached zero
+ if (m_resultCallback.m_closestHitFraction == btScalar(0.f))
+ return false;
+
+ btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject;
+
+ //only perform raycast if filterMask matches
+ if(m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
+ {
+ //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
+ //btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
+#if 0
+#ifdef RECALCULATE_AABB
+ btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
+ collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax);
+#else
+ //getBroadphase()->getAabb(collisionObject->getBroadphaseHandle(),collisionObjectAabbMin,collisionObjectAabbMax);
+ const btVector3& collisionObjectAabbMin = collisionObject->getBroadphaseHandle()->m_aabbMin;
+ const btVector3& collisionObjectAabbMax = collisionObject->getBroadphaseHandle()->m_aabbMax;
+#endif
+#endif
+ //btScalar hitLambda = m_resultCallback.m_closestHitFraction;
+ //culling already done by broadphase
+ //if (btRayAabb(m_rayFromWorld,m_rayToWorld,collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,m_hitNormal))
+ {
+ m_world->rayTestSingle(m_rayFromTrans,m_rayToTrans,
+ collisionObject,
+ collisionObject->getCollisionShape(),
+ collisionObject->getWorldTransform(),
+ m_resultCallback);
+ }
+ }
+ return true;
+ }
+};
+
+void btSoftMultiBodyDynamicsWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const
+{
+ BT_PROFILE("rayTest");
+ /// use the broadphase to accelerate the search for objects, based on their aabb
+ /// and for each object with ray-aabb overlap, perform an exact ray test
+ btSoftSingleRayCallback rayCB(rayFromWorld,rayToWorld,this,resultCallback);
+
+#ifndef USE_BRUTEFORCE_RAYBROADPHASE
+ m_broadphasePairCache->rayTest(rayFromWorld,rayToWorld,rayCB);
+#else
+ for (int i=0;i<this->getNumCollisionObjects();i++)
+ {
+ rayCB.process(m_collisionObjects[i]->getBroadphaseHandle());
+ }
+#endif //USE_BRUTEFORCE_RAYBROADPHASE
+
+}
+
+
+void btSoftMultiBodyDynamicsWorld::rayTestSingle(const btTransform& rayFromTrans,const btTransform& rayToTrans,
+ btCollisionObject* collisionObject,
+ const btCollisionShape* collisionShape,
+ const btTransform& colObjWorldTransform,
+ RayResultCallback& resultCallback)
+{
+ if (collisionShape->isSoftBody()) {
+ btSoftBody* softBody = btSoftBody::upcast(collisionObject);
+ if (softBody) {
+ btSoftBody::sRayCast softResult;
+ if (softBody->rayTest(rayFromTrans.getOrigin(), rayToTrans.getOrigin(), softResult))
+ {
+
+ if (softResult.fraction<= resultCallback.m_closestHitFraction)
+ {
+
+ btCollisionWorld::LocalShapeInfo shapeInfo;
+ shapeInfo.m_shapePart = 0;
+ shapeInfo.m_triangleIndex = softResult.index;
+ // get the normal
+ btVector3 rayDir = rayToTrans.getOrigin() - rayFromTrans.getOrigin();
+ btVector3 normal=-rayDir;
+ normal.normalize();
+
+ if (softResult.feature == btSoftBody::eFeature::Face)
+ {
+ normal = softBody->m_faces[softResult.index].m_normal;
+ if (normal.dot(rayDir) > 0) {
+ // normal always point toward origin of the ray
+ normal = -normal;
+ }
+ }
+
+ btCollisionWorld::LocalRayResult rayResult
+ (collisionObject,
+ &shapeInfo,
+ normal,
+ softResult.fraction);
+ bool normalInWorldSpace = true;
+ resultCallback.addSingleResult(rayResult,normalInWorldSpace);
+ }
+ }
+ }
+ }
+ else {
+ btCollisionWorld::rayTestSingle(rayFromTrans,rayToTrans,collisionObject,collisionShape,colObjWorldTransform,resultCallback);
+ }
+}
+
+
+void btSoftMultiBodyDynamicsWorld::serializeSoftBodies(btSerializer* serializer)
+{
+ int i;
+ //serialize all collision objects
+ for (i=0;i<m_collisionObjects.size();i++)
+ {
+ btCollisionObject* colObj = m_collisionObjects[i];
+ if (colObj->getInternalType() & btCollisionObject::CO_SOFT_BODY)
+ {
+ int len = colObj->calculateSerializeBufferSize();
+ btChunk* chunk = serializer->allocate(len,1);
+ const char* structType = colObj->serialize(chunk->m_oldPtr, serializer);
+ serializer->finalizeChunk(chunk,structType,BT_SOFTBODY_CODE,colObj);
+ }
+ }
+
+}
+
+void btSoftMultiBodyDynamicsWorld::serialize(btSerializer* serializer)
+{
+
+ serializer->startSerialization();
+
+ serializeDynamicsWorldInfo( serializer);
+
+ serializeSoftBodies(serializer);
+
+ serializeRigidBodies(serializer);
+
+ serializeCollisionObjects(serializer);
+
+ serializer->finishSerialization();
+}
+
+
diff --git a/thirdparty/bullet/src/BulletSoftBody/btSoftMultiBodyDynamicsWorld.h b/thirdparty/bullet/src/BulletSoftBody/btSoftMultiBodyDynamicsWorld.h
new file mode 100644
index 0000000000..6d46a21db5
--- /dev/null
+++ b/thirdparty/bullet/src/BulletSoftBody/btSoftMultiBodyDynamicsWorld.h
@@ -0,0 +1,110 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_SOFT_MULTIBODY_DYNAMICS_WORLD_H
+#define BT_SOFT_MULTIBODY_DYNAMICS_WORLD_H
+
+#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h"
+#include "BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h"
+#include "BulletSoftBody/btSoftBody.h"
+
+#ifndef BT_SOFT_RIGID_DYNAMICS_WORLD_H
+typedef btAlignedObjectArray<btSoftBody*> btSoftBodyArray;
+#endif
+
+class btSoftBodySolver;
+
+class btSoftMultiBodyDynamicsWorld : public btMultiBodyDynamicsWorld
+{
+
+ btSoftBodyArray m_softBodies;
+ int m_drawFlags;
+ bool m_drawNodeTree;
+ bool m_drawFaceTree;
+ bool m_drawClusterTree;
+ btSoftBodyWorldInfo m_sbi;
+ ///Solver classes that encapsulate multiple soft bodies for solving
+ btSoftBodySolver *m_softBodySolver;
+ bool m_ownsSolver;
+
+protected:
+
+ virtual void predictUnconstraintMotion(btScalar timeStep);
+
+ virtual void internalSingleStepSimulation( btScalar timeStep);
+
+ void solveSoftBodiesConstraints( btScalar timeStep );
+
+ void serializeSoftBodies(btSerializer* serializer);
+
+public:
+
+ btSoftMultiBodyDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btMultiBodyConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration, btSoftBodySolver *softBodySolver = 0 );
+
+ virtual ~btSoftMultiBodyDynamicsWorld();
+
+ virtual void debugDrawWorld();
+
+ void addSoftBody(btSoftBody* body, int collisionFilterGroup=btBroadphaseProxy::DefaultFilter, int collisionFilterMask=btBroadphaseProxy::AllFilter);
+
+ void removeSoftBody(btSoftBody* body);
+
+ ///removeCollisionObject will first check if it is a rigid body, if so call removeRigidBody otherwise call btDiscreteDynamicsWorld::removeCollisionObject
+ virtual void removeCollisionObject(btCollisionObject* collisionObject);
+
+ int getDrawFlags() const { return(m_drawFlags); }
+ void setDrawFlags(int f) { m_drawFlags=f; }
+
+ btSoftBodyWorldInfo& getWorldInfo()
+ {
+ return m_sbi;
+ }
+ const btSoftBodyWorldInfo& getWorldInfo() const
+ {
+ return m_sbi;
+ }
+
+ virtual btDynamicsWorldType getWorldType() const
+ {
+ return BT_SOFT_MULTIBODY_DYNAMICS_WORLD;
+ }
+
+ btSoftBodyArray& getSoftBodyArray()
+ {
+ return m_softBodies;
+ }
+
+ const btSoftBodyArray& getSoftBodyArray() const
+ {
+ return m_softBodies;
+ }
+
+
+ virtual void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const;
+
+ /// rayTestSingle performs a raycast call and calls the resultCallback. It is used internally by rayTest.
+ /// In a future implementation, we consider moving the ray test as a virtual method in btCollisionShape.
+ /// This allows more customization.
+ static void rayTestSingle(const btTransform& rayFromTrans,const btTransform& rayToTrans,
+ btCollisionObject* collisionObject,
+ const btCollisionShape* collisionShape,
+ const btTransform& colObjWorldTransform,
+ RayResultCallback& resultCallback);
+
+ virtual void serialize(btSerializer* serializer);
+
+};
+
+#endif //BT_SOFT_MULTIBODY_DYNAMICS_WORLD_H
diff --git a/thirdparty/bullet/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp b/thirdparty/bullet/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp
new file mode 100644
index 0000000000..01c148a2ca
--- /dev/null
+++ b/thirdparty/bullet/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp
@@ -0,0 +1,86 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btSoftRigidCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"
+#include "BulletCollision/CollisionShapes/btBoxShape.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "btSoftBody.h"
+#include "BulletSoftBody/btSoftBodySolvers.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
+
+///TODO: include all the shapes that the softbody can collide with
+///alternatively, implement special case collision algorithms (just like for rigid collision shapes)
+
+//#include <stdio.h>
+
+btSoftRigidCollisionAlgorithm::btSoftRigidCollisionAlgorithm(btPersistentManifold* /*mf*/,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* ,const btCollisionObjectWrapper* , bool isSwapped)
+: btCollisionAlgorithm(ci),
+//m_ownManifold(false),
+//m_manifoldPtr(mf),
+m_isSwapped(isSwapped)
+{
+}
+
+
+btSoftRigidCollisionAlgorithm::~btSoftRigidCollisionAlgorithm()
+{
+
+ //m_softBody->m_overlappingRigidBodies.remove(m_rigidCollisionObject);
+
+ /*if (m_ownManifold)
+ {
+ if (m_manifoldPtr)
+ m_dispatcher->releaseManifold(m_manifoldPtr);
+ }
+ */
+
+}
+
+
+#include <stdio.h>
+
+void btSoftRigidCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+ (void)dispatchInfo;
+ (void)resultOut;
+ //printf("btSoftRigidCollisionAlgorithm\n");
+// const btCollisionObjectWrapper* softWrap = m_isSwapped?body1Wrap:body0Wrap;
+// const btCollisionObjectWrapper* rigidWrap = m_isSwapped?body0Wrap:body1Wrap;
+ btSoftBody* softBody = m_isSwapped? (btSoftBody*)body1Wrap->getCollisionObject() : (btSoftBody*)body0Wrap->getCollisionObject();
+ const btCollisionObjectWrapper* rigidCollisionObjectWrap = m_isSwapped? body0Wrap : body1Wrap;
+
+ if (softBody->m_collisionDisabledObjects.findLinearSearch(rigidCollisionObjectWrap->getCollisionObject())==softBody->m_collisionDisabledObjects.size())
+ {
+ softBody->getSoftBodySolver()->processCollision(softBody, rigidCollisionObjectWrap);
+ }
+
+
+}
+
+btScalar btSoftRigidCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+ (void)resultOut;
+ (void)dispatchInfo;
+ (void)col0;
+ (void)col1;
+
+ //not yet
+ return btScalar(1.);
+}
+
+
+
diff --git a/thirdparty/bullet/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.h b/thirdparty/bullet/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.h
new file mode 100644
index 0000000000..93fcc6065b
--- /dev/null
+++ b/thirdparty/bullet/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.h
@@ -0,0 +1,75 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_SOFT_RIGID_COLLISION_ALGORITHM_H
+#define BT_SOFT_RIGID_COLLISION_ALGORITHM_H
+
+#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
+class btPersistentManifold;
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+
+#include "LinearMath/btVector3.h"
+class btSoftBody;
+
+/// btSoftRigidCollisionAlgorithm provides collision detection between btSoftBody and btRigidBody
+class btSoftRigidCollisionAlgorithm : public btCollisionAlgorithm
+{
+ // bool m_ownManifold;
+ // btPersistentManifold* m_manifoldPtr;
+
+ //btSoftBody* m_softBody;
+ //btCollisionObject* m_rigidCollisionObject;
+
+ ///for rigid versus soft (instead of soft versus rigid), we use this swapped boolean
+ bool m_isSwapped;
+
+public:
+
+ btSoftRigidCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* col0,const btCollisionObjectWrapper* col1Wrap, bool isSwapped);
+
+ virtual ~btSoftRigidCollisionAlgorithm();
+
+ virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+ virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+ virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
+ {
+ //we don't add any manifolds
+ }
+
+
+ struct CreateFunc :public btCollisionAlgorithmCreateFunc
+ {
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
+ {
+ void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSoftRigidCollisionAlgorithm));
+ if (!m_swapped)
+ {
+ return new(mem) btSoftRigidCollisionAlgorithm(0,ci,body0Wrap,body1Wrap,false);
+ } else
+ {
+ return new(mem) btSoftRigidCollisionAlgorithm(0,ci,body0Wrap,body1Wrap,true);
+ }
+ }
+ };
+
+};
+
+#endif //BT_SOFT_RIGID_COLLISION_ALGORITHM_H
+
+
diff --git a/thirdparty/bullet/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp b/thirdparty/bullet/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp
new file mode 100644
index 0000000000..204b4f576d
--- /dev/null
+++ b/thirdparty/bullet/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp
@@ -0,0 +1,367 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "btSoftRigidDynamicsWorld.h"
+#include "LinearMath/btQuickprof.h"
+
+//softbody & helpers
+#include "btSoftBody.h"
+#include "btSoftBodyHelpers.h"
+#include "btSoftBodySolvers.h"
+#include "btDefaultSoftBodySolver.h"
+#include "LinearMath/btSerializer.h"
+
+
+btSoftRigidDynamicsWorld::btSoftRigidDynamicsWorld(
+ btDispatcher* dispatcher,
+ btBroadphaseInterface* pairCache,
+ btConstraintSolver* constraintSolver,
+ btCollisionConfiguration* collisionConfiguration,
+ btSoftBodySolver *softBodySolver ) :
+ btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver,collisionConfiguration),
+ m_softBodySolver( softBodySolver ),
+ m_ownsSolver(false)
+{
+ if( !m_softBodySolver )
+ {
+ void* ptr = btAlignedAlloc(sizeof(btDefaultSoftBodySolver),16);
+ m_softBodySolver = new(ptr) btDefaultSoftBodySolver();
+ m_ownsSolver = true;
+ }
+
+ 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.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_sbi.m_sparsesdf.Initialize();
+
+
+}
+
+btSoftRigidDynamicsWorld::~btSoftRigidDynamicsWorld()
+{
+ if (m_ownsSolver)
+ {
+ m_softBodySolver->~btSoftBodySolver();
+ btAlignedFree(m_softBodySolver);
+ }
+}
+
+void btSoftRigidDynamicsWorld::predictUnconstraintMotion(btScalar timeStep)
+{
+ btDiscreteDynamicsWorld::predictUnconstraintMotion( timeStep );
+ {
+ BT_PROFILE("predictUnconstraintMotionSoftBody");
+ m_softBodySolver->predictMotion( float(timeStep) );
+ }
+}
+
+void btSoftRigidDynamicsWorld::internalSingleStepSimulation( btScalar timeStep )
+{
+
+ // Let the solver grab the soft bodies and if necessary optimize for it
+ m_softBodySolver->optimize( getSoftBodyArray() );
+
+ if( !m_softBodySolver->checkInitialized() )
+ {
+ btAssert( "Solver initialization failed\n" );
+ }
+
+ btDiscreteDynamicsWorld::internalSingleStepSimulation( timeStep );
+
+ ///solve soft bodies constraints
+ solveSoftBodiesConstraints( timeStep );
+
+ //self collisions
+ for ( int i=0;i<m_softBodies.size();i++)
+ {
+ btSoftBody* psb=(btSoftBody*)m_softBodies[i];
+ psb->defaultCollisionHandler(psb);
+ }
+
+ ///update soft bodies
+ m_softBodySolver->updateSoftBodies( );
+
+ // End solver-wise simulation step
+ // ///////////////////////////////
+
+}
+
+void btSoftRigidDynamicsWorld::solveSoftBodiesConstraints( btScalar timeStep )
+{
+ BT_PROFILE("solveSoftConstraints");
+
+ if(m_softBodies.size())
+ {
+ btSoftBody::solveClusters(m_softBodies);
+ }
+
+ // Solve constraints solver-wise
+ m_softBodySolver->solveConstraints( timeStep * m_softBodySolver->getTimeScale() );
+
+}
+
+void btSoftRigidDynamicsWorld::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_softBodySolver );
+
+ btCollisionWorld::addCollisionObject(body,
+ collisionFilterGroup,
+ collisionFilterMask);
+
+}
+
+void btSoftRigidDynamicsWorld::removeSoftBody(btSoftBody* body)
+{
+ m_softBodies.remove(body);
+
+ btCollisionWorld::removeCollisionObject(body);
+}
+
+void btSoftRigidDynamicsWorld::removeCollisionObject(btCollisionObject* collisionObject)
+{
+ btSoftBody* body = btSoftBody::upcast(collisionObject);
+ if (body)
+ removeSoftBody(body);
+ else
+ btDiscreteDynamicsWorld::removeCollisionObject(collisionObject);
+}
+
+void btSoftRigidDynamicsWorld::debugDrawWorld()
+{
+ btDiscreteDynamicsWorld::debugDrawWorld();
+
+ if (getDebugDrawer())
+ {
+ int i;
+ for ( i=0;i<this->m_softBodies.size();i++)
+ {
+ btSoftBody* psb=(btSoftBody*)this->m_softBodies[i];
+ if (getDebugDrawer() && (getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe)))
+ {
+ btSoftBodyHelpers::DrawFrame(psb,m_debugDrawer);
+ btSoftBodyHelpers::Draw(psb,m_debugDrawer,m_drawFlags);
+ }
+
+ if (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawAabb))
+ {
+ if(m_drawNodeTree) btSoftBodyHelpers::DrawNodeTree(psb,m_debugDrawer);
+ if(m_drawFaceTree) btSoftBodyHelpers::DrawFaceTree(psb,m_debugDrawer);
+ if(m_drawClusterTree) btSoftBodyHelpers::DrawClusterTree(psb,m_debugDrawer);
+ }
+ }
+ }
+}
+
+
+
+
+struct btSoftSingleRayCallback : public btBroadphaseRayCallback
+{
+ btVector3 m_rayFromWorld;
+ btVector3 m_rayToWorld;
+ btTransform m_rayFromTrans;
+ btTransform m_rayToTrans;
+ btVector3 m_hitNormal;
+
+ const btSoftRigidDynamicsWorld* m_world;
+ btCollisionWorld::RayResultCallback& m_resultCallback;
+
+ btSoftSingleRayCallback(const btVector3& rayFromWorld,const btVector3& rayToWorld,const btSoftRigidDynamicsWorld* world,btCollisionWorld::RayResultCallback& resultCallback)
+ :m_rayFromWorld(rayFromWorld),
+ m_rayToWorld(rayToWorld),
+ m_world(world),
+ m_resultCallback(resultCallback)
+ {
+ m_rayFromTrans.setIdentity();
+ m_rayFromTrans.setOrigin(m_rayFromWorld);
+ m_rayToTrans.setIdentity();
+ m_rayToTrans.setOrigin(m_rayToWorld);
+
+ btVector3 rayDir = (rayToWorld-rayFromWorld);
+
+ rayDir.normalize ();
+ ///what about division by zero? --> just set rayDirection[i] to INF/1e30
+ m_rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[0];
+ m_rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[1];
+ m_rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[2];
+ m_signs[0] = m_rayDirectionInverse[0] < 0.0;
+ m_signs[1] = m_rayDirectionInverse[1] < 0.0;
+ m_signs[2] = m_rayDirectionInverse[2] < 0.0;
+
+ m_lambda_max = rayDir.dot(m_rayToWorld-m_rayFromWorld);
+
+ }
+
+
+
+ virtual bool process(const btBroadphaseProxy* proxy)
+ {
+ ///terminate further ray tests, once the closestHitFraction reached zero
+ if (m_resultCallback.m_closestHitFraction == btScalar(0.f))
+ return false;
+
+ btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject;
+
+ //only perform raycast if filterMask matches
+ if(m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
+ {
+ //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
+ //btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
+#if 0
+#ifdef RECALCULATE_AABB
+ btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
+ collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax);
+#else
+ //getBroadphase()->getAabb(collisionObject->getBroadphaseHandle(),collisionObjectAabbMin,collisionObjectAabbMax);
+ const btVector3& collisionObjectAabbMin = collisionObject->getBroadphaseHandle()->m_aabbMin;
+ const btVector3& collisionObjectAabbMax = collisionObject->getBroadphaseHandle()->m_aabbMax;
+#endif
+#endif
+ //btScalar hitLambda = m_resultCallback.m_closestHitFraction;
+ //culling already done by broadphase
+ //if (btRayAabb(m_rayFromWorld,m_rayToWorld,collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,m_hitNormal))
+ {
+ m_world->rayTestSingle(m_rayFromTrans,m_rayToTrans,
+ collisionObject,
+ collisionObject->getCollisionShape(),
+ collisionObject->getWorldTransform(),
+ m_resultCallback);
+ }
+ }
+ return true;
+ }
+};
+
+void btSoftRigidDynamicsWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const
+{
+ BT_PROFILE("rayTest");
+ /// use the broadphase to accelerate the search for objects, based on their aabb
+ /// and for each object with ray-aabb overlap, perform an exact ray test
+ btSoftSingleRayCallback rayCB(rayFromWorld,rayToWorld,this,resultCallback);
+
+#ifndef USE_BRUTEFORCE_RAYBROADPHASE
+ m_broadphasePairCache->rayTest(rayFromWorld,rayToWorld,rayCB);
+#else
+ for (int i=0;i<this->getNumCollisionObjects();i++)
+ {
+ rayCB.process(m_collisionObjects[i]->getBroadphaseHandle());
+ }
+#endif //USE_BRUTEFORCE_RAYBROADPHASE
+
+}
+
+
+void btSoftRigidDynamicsWorld::rayTestSingle(const btTransform& rayFromTrans,const btTransform& rayToTrans,
+ btCollisionObject* collisionObject,
+ const btCollisionShape* collisionShape,
+ const btTransform& colObjWorldTransform,
+ RayResultCallback& resultCallback)
+{
+ if (collisionShape->isSoftBody()) {
+ btSoftBody* softBody = btSoftBody::upcast(collisionObject);
+ if (softBody) {
+ btSoftBody::sRayCast softResult;
+ if (softBody->rayTest(rayFromTrans.getOrigin(), rayToTrans.getOrigin(), softResult))
+ {
+
+ if (softResult.fraction<= resultCallback.m_closestHitFraction)
+ {
+
+ btCollisionWorld::LocalShapeInfo shapeInfo;
+ shapeInfo.m_shapePart = 0;
+ shapeInfo.m_triangleIndex = softResult.index;
+ // get the normal
+ btVector3 rayDir = rayToTrans.getOrigin() - rayFromTrans.getOrigin();
+ btVector3 normal=-rayDir;
+ normal.normalize();
+
+ if (softResult.feature == btSoftBody::eFeature::Face)
+ {
+ normal = softBody->m_faces[softResult.index].m_normal;
+ if (normal.dot(rayDir) > 0) {
+ // normal always point toward origin of the ray
+ normal = -normal;
+ }
+ }
+
+ btCollisionWorld::LocalRayResult rayResult
+ (collisionObject,
+ &shapeInfo,
+ normal,
+ softResult.fraction);
+ bool normalInWorldSpace = true;
+ resultCallback.addSingleResult(rayResult,normalInWorldSpace);
+ }
+ }
+ }
+ }
+ else {
+ btCollisionWorld::rayTestSingle(rayFromTrans,rayToTrans,collisionObject,collisionShape,colObjWorldTransform,resultCallback);
+ }
+}
+
+
+void btSoftRigidDynamicsWorld::serializeSoftBodies(btSerializer* serializer)
+{
+ int i;
+ //serialize all collision objects
+ for (i=0;i<m_collisionObjects.size();i++)
+ {
+ btCollisionObject* colObj = m_collisionObjects[i];
+ if (colObj->getInternalType() & btCollisionObject::CO_SOFT_BODY)
+ {
+ int len = colObj->calculateSerializeBufferSize();
+ btChunk* chunk = serializer->allocate(len,1);
+ const char* structType = colObj->serialize(chunk->m_oldPtr, serializer);
+ serializer->finalizeChunk(chunk,structType,BT_SOFTBODY_CODE,colObj);
+ }
+ }
+
+}
+
+void btSoftRigidDynamicsWorld::serialize(btSerializer* serializer)
+{
+
+ serializer->startSerialization();
+
+ serializeDynamicsWorldInfo( serializer);
+
+ serializeSoftBodies(serializer);
+
+ serializeRigidBodies(serializer);
+
+ serializeCollisionObjects(serializer);
+
+ serializer->finishSerialization();
+}
+
+
diff --git a/thirdparty/bullet/src/BulletSoftBody/btSoftRigidDynamicsWorld.h b/thirdparty/bullet/src/BulletSoftBody/btSoftRigidDynamicsWorld.h
new file mode 100644
index 0000000000..d921a6488d
--- /dev/null
+++ b/thirdparty/bullet/src/BulletSoftBody/btSoftRigidDynamicsWorld.h
@@ -0,0 +1,107 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_SOFT_RIGID_DYNAMICS_WORLD_H
+#define BT_SOFT_RIGID_DYNAMICS_WORLD_H
+
+#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h"
+#include "btSoftBody.h"
+
+typedef btAlignedObjectArray<btSoftBody*> btSoftBodyArray;
+
+class btSoftBodySolver;
+
+class btSoftRigidDynamicsWorld : public btDiscreteDynamicsWorld
+{
+
+ btSoftBodyArray m_softBodies;
+ int m_drawFlags;
+ bool m_drawNodeTree;
+ bool m_drawFaceTree;
+ bool m_drawClusterTree;
+ btSoftBodyWorldInfo m_sbi;
+ ///Solver classes that encapsulate multiple soft bodies for solving
+ btSoftBodySolver *m_softBodySolver;
+ bool m_ownsSolver;
+
+protected:
+
+ virtual void predictUnconstraintMotion(btScalar timeStep);
+
+ virtual void internalSingleStepSimulation( btScalar timeStep);
+
+ void solveSoftBodiesConstraints( btScalar timeStep );
+
+ void serializeSoftBodies(btSerializer* serializer);
+
+public:
+
+ btSoftRigidDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration, btSoftBodySolver *softBodySolver = 0 );
+
+ virtual ~btSoftRigidDynamicsWorld();
+
+ virtual void debugDrawWorld();
+
+ void addSoftBody(btSoftBody* body, int collisionFilterGroup=btBroadphaseProxy::DefaultFilter, int collisionFilterMask=btBroadphaseProxy::AllFilter);
+
+ void removeSoftBody(btSoftBody* body);
+
+ ///removeCollisionObject will first check if it is a rigid body, if so call removeRigidBody otherwise call btDiscreteDynamicsWorld::removeCollisionObject
+ virtual void removeCollisionObject(btCollisionObject* collisionObject);
+
+ int getDrawFlags() const { return(m_drawFlags); }
+ void setDrawFlags(int f) { m_drawFlags=f; }
+
+ btSoftBodyWorldInfo& getWorldInfo()
+ {
+ return m_sbi;
+ }
+ const btSoftBodyWorldInfo& getWorldInfo() const
+ {
+ return m_sbi;
+ }
+
+ virtual btDynamicsWorldType getWorldType() const
+ {
+ return BT_SOFT_RIGID_DYNAMICS_WORLD;
+ }
+
+ btSoftBodyArray& getSoftBodyArray()
+ {
+ return m_softBodies;
+ }
+
+ const btSoftBodyArray& getSoftBodyArray() const
+ {
+ return m_softBodies;
+ }
+
+
+ virtual void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const;
+
+ /// rayTestSingle performs a raycast call and calls the resultCallback. It is used internally by rayTest.
+ /// In a future implementation, we consider moving the ray test as a virtual method in btCollisionShape.
+ /// This allows more customization.
+ static void rayTestSingle(const btTransform& rayFromTrans,const btTransform& rayToTrans,
+ btCollisionObject* collisionObject,
+ const btCollisionShape* collisionShape,
+ const btTransform& colObjWorldTransform,
+ RayResultCallback& resultCallback);
+
+ virtual void serialize(btSerializer* serializer);
+
+};
+
+#endif //BT_SOFT_RIGID_DYNAMICS_WORLD_H
diff --git a/thirdparty/bullet/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp b/thirdparty/bullet/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp
new file mode 100644
index 0000000000..72043e69e2
--- /dev/null
+++ b/thirdparty/bullet/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp
@@ -0,0 +1,48 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btSoftSoftCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/CollisionShapes/btBoxShape.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletSoftBody/btSoftBodySolvers.h"
+#include "btSoftBody.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
+
+#define USE_PERSISTENT_CONTACTS 1
+
+btSoftSoftCollisionAlgorithm::btSoftSoftCollisionAlgorithm(btPersistentManifold* /*mf*/,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* /*obj0*/,const btCollisionObjectWrapper* /*obj1*/)
+: btCollisionAlgorithm(ci)
+//m_ownManifold(false),
+//m_manifoldPtr(mf)
+{
+}
+
+btSoftSoftCollisionAlgorithm::~btSoftSoftCollisionAlgorithm()
+{
+}
+
+void btSoftSoftCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& /*dispatchInfo*/,btManifoldResult* /*resultOut*/)
+{
+ btSoftBody* soft0 = (btSoftBody*)body0Wrap->getCollisionObject();
+ btSoftBody* soft1 = (btSoftBody*)body1Wrap->getCollisionObject();
+ soft0->getSoftBodySolver()->processCollision(soft0, soft1);
+}
+
+btScalar btSoftSoftCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* /*body0*/,btCollisionObject* /*body1*/,const btDispatcherInfo& /*dispatchInfo*/,btManifoldResult* /*resultOut*/)
+{
+ //not yet
+ return 1.f;
+}
diff --git a/thirdparty/bullet/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h b/thirdparty/bullet/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h
new file mode 100644
index 0000000000..4eab7aea2f
--- /dev/null
+++ b/thirdparty/bullet/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h
@@ -0,0 +1,69 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_SOFT_SOFT_COLLISION_ALGORITHM_H
+#define BT_SOFT_SOFT_COLLISION_ALGORITHM_H
+
+#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
+#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
+
+class btPersistentManifold;
+class btSoftBody;
+
+///collision detection between two btSoftBody shapes
+class btSoftSoftCollisionAlgorithm : public btCollisionAlgorithm
+{
+ bool m_ownManifold;
+ btPersistentManifold* m_manifoldPtr;
+
+// btSoftBody* m_softBody0;
+// btSoftBody* m_softBody1;
+
+
+public:
+ btSoftSoftCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
+ : btCollisionAlgorithm(ci) {}
+
+ virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+ virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+ virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
+ {
+ if (m_manifoldPtr && m_ownManifold)
+ manifoldArray.push_back(m_manifoldPtr);
+ }
+
+ btSoftSoftCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap);
+
+ virtual ~btSoftSoftCollisionAlgorithm();
+
+ struct CreateFunc :public btCollisionAlgorithmCreateFunc
+ {
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
+ {
+ int bbsize = sizeof(btSoftSoftCollisionAlgorithm);
+ void* ptr = ci.m_dispatcher1->allocateCollisionAlgorithm(bbsize);
+ return new(ptr) btSoftSoftCollisionAlgorithm(0,ci,body0Wrap,body1Wrap);
+ }
+ };
+
+};
+
+#endif //BT_SOFT_SOFT_COLLISION_ALGORITHM_H
+
+
diff --git a/thirdparty/bullet/src/BulletSoftBody/btSparseSDF.h b/thirdparty/bullet/src/BulletSoftBody/btSparseSDF.h
new file mode 100644
index 0000000000..ba437c28ef
--- /dev/null
+++ b/thirdparty/bullet/src/BulletSoftBody/btSparseSDF.h
@@ -0,0 +1,319 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+///btSparseSdf implementation by Nathanael Presson
+
+#ifndef BT_SPARSE_SDF_H
+#define BT_SPARSE_SDF_H
+
+#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);
+}
+
+template <const int CELLSIZE>
+struct btSparseSdf
+{
+ //
+ // Inner types
+ //
+ struct IntFrac
+ {
+ int b;
+ int i;
+ btScalar f;
+ };
+ struct Cell
+ {
+ btScalar d[CELLSIZE+1][CELLSIZE+1][CELLSIZE+1];
+ int c[3];
+ int puid;
+ unsigned hash;
+ const btCollisionShape* pclient;
+ Cell* next;
+ };
+ //
+ // Fields
+ //
+
+ btAlignedObjectArray<Cell*> cells;
+ btScalar voxelsz;
+ int puid;
+ int ncells;
+ int m_clampCells;
+ int nprobes;
+ int nqueries;
+
+ //
+ // Methods
+ //
+
+ //
+ void Initialize(int hashsize=2383, int clampCells = 256*1024)
+ {
+ //avoid a crash due to running out of memory, so clamp the maximum number of cells allocated
+ //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);
+ Reset();
+ }
+ //
+ void Reset()
+ {
+ for(int i=0,ni=cells.size();i<ni;++i)
+ {
+ Cell* pc=cells[i];
+ cells[i]=0;
+ while(pc)
+ {
+ Cell* pn=pc->next;
+ delete pc;
+ pc=pn;
+ }
+ }
+ voxelsz =0.25;
+ puid =0;
+ ncells =0;
+ nprobes =1;
+ nqueries =1;
+ }
+ //
+ void GarbageCollect(int lifetime=256)
+ {
+ const int life=puid-lifetime;
+ for(int i=0;i<cells.size();++i)
+ {
+ Cell*& root=cells[i];
+ Cell* pp=0;
+ Cell* pc=root;
+ while(pc)
+ {
+ Cell* pn=pc->next;
+ if(pc->puid<life)
+ {
+ if(pp) pp->next=pn; else root=pn;
+ delete pc;pc=pp;--ncells;
+ }
+ pp=pc;pc=pn;
+ }
+ }
+ //printf("GC[%d]: %d cells, PpQ: %f\r\n",puid,ncells,nprobes/(btScalar)nqueries);
+ nqueries=1;
+ nprobes=1;
+ ++puid; ///@todo: Reset puid's when int range limit is reached */
+ /* else setup a priority list... */
+ }
+ //
+ int RemoveReferences(btCollisionShape* pcs)
+ {
+ int refcount=0;
+ for(int i=0;i<cells.size();++i)
+ {
+ Cell*& root=cells[i];
+ Cell* pp=0;
+ Cell* pc=root;
+ while(pc)
+ {
+ Cell* pn=pc->next;
+ if(pc->pclient==pcs)
+ {
+ if(pp) pp->next=pn; else root=pn;
+ delete pc;pc=pp;++refcount;
+ }
+ pp=pc;pc=pn;
+ }
+ }
+ return(refcount);
+ }
+ //
+ btScalar Evaluate( const btVector3& x,
+ const btCollisionShape* shape,
+ btVector3& normal,
+ btScalar margin)
+ {
+ /* Lookup cell */
+ const btVector3 scx=x/voxelsz;
+ const IntFrac ix=Decompose(scx.x());
+ const IntFrac iy=Decompose(scx.y());
+ const IntFrac iz=Decompose(scx.z());
+ const unsigned h=Hash(ix.b,iy.b,iz.b,shape);
+ Cell*& root=cells[static_cast<int>(h%cells.size())];
+ Cell* c=root;
+ ++nqueries;
+ while(c)
+ {
+ ++nprobes;
+ if( (c->hash==h) &&
+ (c->c[0]==ix.b) &&
+ (c->c[1]==iy.b) &&
+ (c->c[2]==iz.b) &&
+ (c->pclient==shape))
+ { break; }
+ else
+ { c=c->next; }
+ }
+ if(!c)
+ {
+ ++nprobes;
+ ++ncells;
+ //int sz = sizeof(Cell);
+ if (ncells>m_clampCells)
+ {
+ static int numResets=0;
+ numResets++;
+// printf("numResets=%d\n",numResets);
+ Reset();
+ }
+
+ c=new Cell();
+ c->next=root;root=c;
+ c->pclient=shape;
+ c->hash=h;
+ c->c[0]=ix.b;c->c[1]=iy.b;c->c[2]=iz.b;
+ BuildCell(*c);
+ }
+ c->puid=puid;
+ /* Extract infos */
+ const int o[]={ ix.i,iy.i,iz.i};
+ const btScalar d[]={ c->d[o[0]+0][o[1]+0][o[2]+0],
+ c->d[o[0]+1][o[1]+0][o[2]+0],
+ c->d[o[0]+1][o[1]+1][o[2]+0],
+ c->d[o[0]+0][o[1]+1][o[2]+0],
+ c->d[o[0]+0][o[1]+0][o[2]+1],
+ c->d[o[0]+1][o[1]+0][o[2]+1],
+ c->d[o[0]+1][o[1]+1][o[2]+1],
+ c->d[o[0]+0][o[1]+1][o[2]+1]};
+ /* Normal */
+#if 1
+ const btScalar gx[]={ d[1]-d[0],d[2]-d[3],
+ d[5]-d[4],d[6]-d[7]};
+ const btScalar gy[]={ d[3]-d[0],d[2]-d[1],
+ d[7]-d[4],d[6]-d[5]};
+ const btScalar gz[]={ d[4]-d[0],d[5]-d[1],
+ d[7]-d[3],d[6]-d[2]};
+ normal.setX(Lerp( Lerp(gx[0],gx[1],iy.f),
+ Lerp(gx[2],gx[3],iy.f),iz.f));
+ normal.setY(Lerp( Lerp(gy[0],gy[1],ix.f),
+ 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();
+#else
+ normal = btVector3(d[1]-d[0],d[3]-d[0],d[4]-d[0]).normalized();
+#endif
+ /* Distance */
+ const btScalar d0=Lerp(Lerp(d[0],d[1],ix.f),
+ Lerp(d[3],d[2],ix.f),iy.f);
+ const btScalar d1=Lerp(Lerp(d[4],d[5],ix.f),
+ Lerp(d[7],d[6],ix.f),iy.f);
+ return(Lerp(d0,d1,iz.f)-margin);
+ }
+ //
+ void BuildCell(Cell& c)
+ {
+ const btVector3 org=btVector3( (btScalar)c.c[0],
+ (btScalar)c.c[1],
+ (btScalar)c.c[2]) *
+ CELLSIZE*voxelsz;
+ for(int k=0;k<=CELLSIZE;++k)
+ {
+ const btScalar z=voxelsz*k+org.z();
+ for(int j=0;j<=CELLSIZE;++j)
+ {
+ const btScalar y=voxelsz*j+org.y();
+ for(int i=0;i<=CELLSIZE;++i)
+ {
+ const btScalar x=voxelsz*i+org.x();
+ c.d[i][j][k]=DistanceToShape( btVector3(x,y,z),
+ c.pclient);
+ }
+ }
+ }
+ }
+ //
+ static inline btScalar DistanceToShape(const btVector3& x,
+ const btCollisionShape* shape)
+ {
+ btTransform unit;
+ unit.setIdentity();
+ if(shape->isConvex())
+ {
+ btGjkEpaSolver2::sResults res;
+ const btConvexShape* csh=static_cast<const btConvexShape*>(shape);
+ return(btGjkEpaSolver2::SignedDistance(x,0,csh,unit,res));
+ }
+ return(0);
+ }
+ //
+ static inline IntFrac Decompose(btScalar x)
+ {
+ /* That one need a lot of improvements... */
+ /* Remove test, faster floor... */
+ IntFrac r;
+ x/=CELLSIZE;
+ const int o=x<0?(int)(-x+1):0;
+ x+=o;r.b=(int)x;
+ const btScalar k=(x-r.b)*CELLSIZE;
+ r.i=(int)k;r.f=k-r.i;r.b-=o;
+ return(r);
+ }
+ //
+ static inline btScalar Lerp(btScalar a,btScalar b,btScalar t)
+ {
+ return(a+(b-a)*t);
+ }
+
+
+
+ //
+ static inline unsigned int Hash(int x,int y,int z,const btCollisionShape* shape)
+ {
+ struct btS
+ {
+ int x,y,z;
+ void* p;
+ };
+
+ btS myset;
+
+ myset.x=x;myset.y=y;myset.z=z;myset.p=(void*)shape;
+ const void* ptr = &myset;
+
+ unsigned int result = HsiehHash<sizeof(btS)/4> (ptr);
+
+
+ return result;
+ }
+};
+
+
+#endif //BT_SPARSE_SDF_H
diff --git a/thirdparty/bullet/src/BulletSoftBody/premake4.lua b/thirdparty/bullet/src/BulletSoftBody/premake4.lua
new file mode 100644
index 0000000000..ce384de2c8
--- /dev/null
+++ b/thirdparty/bullet/src/BulletSoftBody/premake4.lua
@@ -0,0 +1,11 @@
+ project "BulletSoftBody"
+
+ kind "StaticLib"
+
+ includedirs {
+ "..",
+ }
+ files {
+ "**.cpp",
+ "**.h"
+ } \ No newline at end of file
diff --git a/thirdparty/bullet/src/CMakeLists.txt b/thirdparty/bullet/src/CMakeLists.txt
new file mode 100644
index 0000000000..c30125c539
--- /dev/null
+++ b/thirdparty/bullet/src/CMakeLists.txt
@@ -0,0 +1,19 @@
+
+IF(BUILD_BULLET3)
+ SUBDIRS( Bullet3OpenCL Bullet3Serialize/Bullet2FileLoader Bullet3Dynamics Bullet3Collision Bullet3Geometry )
+ENDIF(BUILD_BULLET3)
+
+
+SUBDIRS( BulletInverseDynamics BulletSoftBody BulletCollision BulletDynamics LinearMath Bullet3Common)
+
+
+IF(INSTALL_LIBS)
+ #INSTALL of other files requires CMake 2.6
+ IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
+ IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+ # Don't actually need to install any common files, the frameworks include everything
+ ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+ INSTALL(FILES btBulletCollisionCommon.h btBulletDynamicsCommon.h DESTINATION ${INCLUDE_INSTALL_DIR})
+ ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+ ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
+ENDIF(INSTALL_LIBS)
diff --git a/thirdparty/bullet/src/LinearMath/CMakeLists.txt b/thirdparty/bullet/src/LinearMath/CMakeLists.txt
new file mode 100644
index 0000000000..ede21d9a70
--- /dev/null
+++ b/thirdparty/bullet/src/LinearMath/CMakeLists.txt
@@ -0,0 +1,75 @@
+
+INCLUDE_DIRECTORIES(
+ ${BULLET_PHYSICS_SOURCE_DIR}/src
+)
+
+SET(LinearMath_SRCS
+ btAlignedAllocator.cpp
+ btConvexHull.cpp
+ btConvexHullComputer.cpp
+ btGeometryUtil.cpp
+ btPolarDecomposition.cpp
+ btQuickprof.cpp
+ btSerializer.cpp
+ btSerializer64.cpp
+ btThreads.cpp
+ btVector3.cpp
+)
+
+SET(LinearMath_HDRS
+ btAabbUtil2.h
+ btAlignedAllocator.h
+ btAlignedObjectArray.h
+ btConvexHull.h
+ btConvexHullComputer.h
+ btDefaultMotionState.h
+ btGeometryUtil.h
+ btGrahamScan2dConvexHull.h
+ btHashMap.h
+ btIDebugDraw.h
+ btList.h
+ btMatrix3x3.h
+ btMinMax.h
+ btMotionState.h
+ btPolarDecomposition.h
+ btPoolAllocator.h
+ btQuadWord.h
+ btQuaternion.h
+ btQuickprof.h
+ btRandom.h
+ btScalar.h
+ btSerializer.h
+ btStackAlloc.h
+ btThreads.h
+ btTransform.h
+ btTransformUtil.h
+ btVector3.h
+)
+
+ADD_LIBRARY(LinearMath ${LinearMath_SRCS} ${LinearMath_HDRS})
+SET_TARGET_PROPERTIES(LinearMath PROPERTIES VERSION ${BULLET_VERSION})
+SET_TARGET_PROPERTIES(LinearMath PROPERTIES SOVERSION ${BULLET_VERSION})
+
+IF (INSTALL_LIBS)
+ IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
+ #FILES_MATCHING requires CMake 2.6
+ IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
+ IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+ INSTALL(TARGETS LinearMath DESTINATION .)
+ ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+ INSTALL(TARGETS LinearMath
+ RUNTIME DESTINATION bin
+ LIBRARY DESTINATION lib${LIB_SUFFIX}
+ ARCHIVE DESTINATION lib${LIB_SUFFIX})
+ INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.h" PATTERN
+".svn" EXCLUDE PATTERN "CMakeFiles" EXCLUDE)
+ ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+ ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
+
+ IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+ SET_TARGET_PROPERTIES(LinearMath PROPERTIES FRAMEWORK true)
+ SET_TARGET_PROPERTIES(LinearMath PROPERTIES PUBLIC_HEADER "${LinearMath_HDRS}")
+ ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+ ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
+ENDIF (INSTALL_LIBS)
diff --git a/thirdparty/bullet/src/LinearMath/btAabbUtil2.h b/thirdparty/bullet/src/LinearMath/btAabbUtil2.h
new file mode 100644
index 0000000000..d2997b4e65
--- /dev/null
+++ b/thirdparty/bullet/src/LinearMath/btAabbUtil2.h
@@ -0,0 +1,232 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+#ifndef BT_AABB_UTIL2
+#define BT_AABB_UTIL2
+
+#include "btTransform.h"
+#include "btVector3.h"
+#include "btMinMax.h"
+
+
+
+SIMD_FORCE_INLINE void AabbExpand (btVector3& aabbMin,
+ btVector3& aabbMax,
+ const btVector3& expansionMin,
+ const btVector3& expansionMax)
+{
+ aabbMin = aabbMin + expansionMin;
+ aabbMax = aabbMax + expansionMax;
+}
+
+/// conservative test for overlap between two aabbs
+SIMD_FORCE_INLINE bool TestPointAgainstAabb2(const btVector3 &aabbMin1, const btVector3 &aabbMax1,
+ const btVector3 &point)
+{
+ bool overlap = true;
+ overlap = (aabbMin1.getX() > point.getX() || aabbMax1.getX() < point.getX()) ? false : overlap;
+ overlap = (aabbMin1.getZ() > point.getZ() || aabbMax1.getZ() < point.getZ()) ? false : overlap;
+ overlap = (aabbMin1.getY() > point.getY() || aabbMax1.getY() < point.getY()) ? false : overlap;
+ return overlap;
+}
+
+
+/// conservative test for overlap between two aabbs
+SIMD_FORCE_INLINE bool TestAabbAgainstAabb2(const btVector3 &aabbMin1, const btVector3 &aabbMax1,
+ const btVector3 &aabbMin2, const btVector3 &aabbMax2)
+{
+ bool overlap = true;
+ overlap = (aabbMin1.getX() > aabbMax2.getX() || aabbMax1.getX() < aabbMin2.getX()) ? false : overlap;
+ overlap = (aabbMin1.getZ() > aabbMax2.getZ() || aabbMax1.getZ() < aabbMin2.getZ()) ? false : overlap;
+ overlap = (aabbMin1.getY() > aabbMax2.getY() || aabbMax1.getY() < aabbMin2.getY()) ? false : overlap;
+ return overlap;
+}
+
+/// conservative test for overlap between triangle and aabb
+SIMD_FORCE_INLINE bool TestTriangleAgainstAabb2(const btVector3 *vertices,
+ const btVector3 &aabbMin, const btVector3 &aabbMax)
+{
+ const btVector3 &p1 = vertices[0];
+ const btVector3 &p2 = vertices[1];
+ const btVector3 &p3 = vertices[2];
+
+ if (btMin(btMin(p1[0], p2[0]), p3[0]) > aabbMax[0]) return false;
+ if (btMax(btMax(p1[0], p2[0]), p3[0]) < aabbMin[0]) return false;
+
+ if (btMin(btMin(p1[2], p2[2]), p3[2]) > aabbMax[2]) return false;
+ if (btMax(btMax(p1[2], p2[2]), p3[2]) < aabbMin[2]) return false;
+
+ if (btMin(btMin(p1[1], p2[1]), p3[1]) > aabbMax[1]) return false;
+ if (btMax(btMax(p1[1], p2[1]), p3[1]) < aabbMin[1]) return false;
+ return true;
+}
+
+
+SIMD_FORCE_INLINE int btOutcode(const btVector3& p,const btVector3& halfExtent)
+{
+ return (p.getX() < -halfExtent.getX() ? 0x01 : 0x0) |
+ (p.getX() > halfExtent.getX() ? 0x08 : 0x0) |
+ (p.getY() < -halfExtent.getY() ? 0x02 : 0x0) |
+ (p.getY() > halfExtent.getY() ? 0x10 : 0x0) |
+ (p.getZ() < -halfExtent.getZ() ? 0x4 : 0x0) |
+ (p.getZ() > halfExtent.getZ() ? 0x20 : 0x0);
+}
+
+
+
+SIMD_FORCE_INLINE bool btRayAabb2(const btVector3& rayFrom,
+ const btVector3& rayInvDirection,
+ const unsigned int raySign[3],
+ const btVector3 bounds[2],
+ btScalar& tmin,
+ btScalar lambda_min,
+ btScalar lambda_max)
+{
+ btScalar tmax, tymin, tymax, tzmin, tzmax;
+ tmin = (bounds[raySign[0]].getX() - rayFrom.getX()) * rayInvDirection.getX();
+ tmax = (bounds[1-raySign[0]].getX() - rayFrom.getX()) * rayInvDirection.getX();
+ tymin = (bounds[raySign[1]].getY() - rayFrom.getY()) * rayInvDirection.getY();
+ tymax = (bounds[1-raySign[1]].getY() - rayFrom.getY()) * rayInvDirection.getY();
+
+ if ( (tmin > tymax) || (tymin > tmax) )
+ return false;
+
+ if (tymin > tmin)
+ tmin = tymin;
+
+ if (tymax < tmax)
+ tmax = tymax;
+
+ tzmin = (bounds[raySign[2]].getZ() - rayFrom.getZ()) * rayInvDirection.getZ();
+ tzmax = (bounds[1-raySign[2]].getZ() - rayFrom.getZ()) * rayInvDirection.getZ();
+
+ if ( (tmin > tzmax) || (tzmin > tmax) )
+ return false;
+ if (tzmin > tmin)
+ tmin = tzmin;
+ if (tzmax < tmax)
+ tmax = tzmax;
+ return ( (tmin < lambda_max) && (tmax > lambda_min) );
+}
+
+SIMD_FORCE_INLINE bool btRayAabb(const btVector3& rayFrom,
+ const btVector3& rayTo,
+ const btVector3& aabbMin,
+ const btVector3& aabbMax,
+ btScalar& param, btVector3& normal)
+{
+ btVector3 aabbHalfExtent = (aabbMax-aabbMin)* btScalar(0.5);
+ btVector3 aabbCenter = (aabbMax+aabbMin)* btScalar(0.5);
+ btVector3 source = rayFrom - aabbCenter;
+ btVector3 target = rayTo - aabbCenter;
+ int sourceOutcode = btOutcode(source,aabbHalfExtent);
+ int targetOutcode = btOutcode(target,aabbHalfExtent);
+ if ((sourceOutcode & targetOutcode) == 0x0)
+ {
+ btScalar lambda_enter = btScalar(0.0);
+ btScalar lambda_exit = param;
+ btVector3 r = target - source;
+ int i;
+ btScalar normSign = 1;
+ btVector3 hitNormal(0,0,0);
+ int bit=1;
+
+ for (int j=0;j<2;j++)
+ {
+ for (i = 0; i != 3; ++i)
+ {
+ if (sourceOutcode & bit)
+ {
+ btScalar lambda = (-source[i] - aabbHalfExtent[i]*normSign) / r[i];
+ if (lambda_enter <= lambda)
+ {
+ lambda_enter = lambda;
+ hitNormal.setValue(0,0,0);
+ hitNormal[i] = normSign;
+ }
+ }
+ else if (targetOutcode & bit)
+ {
+ btScalar lambda = (-source[i] - aabbHalfExtent[i]*normSign) / r[i];
+ btSetMin(lambda_exit, lambda);
+ }
+ bit<<=1;
+ }
+ normSign = btScalar(-1.);
+ }
+ if (lambda_enter <= lambda_exit)
+ {
+ param = lambda_enter;
+ normal = hitNormal;
+ return true;
+ }
+ }
+ return false;
+}
+
+
+
+SIMD_FORCE_INLINE void btTransformAabb(const btVector3& halfExtents, btScalar margin,const btTransform& t,btVector3& aabbMinOut,btVector3& aabbMaxOut)
+{
+ btVector3 halfExtentsWithMargin = halfExtents+btVector3(margin,margin,margin);
+ btMatrix3x3 abs_b = t.getBasis().absolute();
+ btVector3 center = t.getOrigin();
+ btVector3 extent = halfExtentsWithMargin.dot3( abs_b[0], abs_b[1], abs_b[2] );
+ aabbMinOut = center - extent;
+ aabbMaxOut = center + extent;
+}
+
+
+SIMD_FORCE_INLINE void btTransformAabb(const btVector3& localAabbMin,const btVector3& localAabbMax, btScalar margin,const btTransform& trans,btVector3& aabbMinOut,btVector3& aabbMaxOut)
+{
+ btAssert(localAabbMin.getX() <= localAabbMax.getX());
+ btAssert(localAabbMin.getY() <= localAabbMax.getY());
+ btAssert(localAabbMin.getZ() <= localAabbMax.getZ());
+ btVector3 localHalfExtents = btScalar(0.5)*(localAabbMax-localAabbMin);
+ localHalfExtents+=btVector3(margin,margin,margin);
+
+ btVector3 localCenter = btScalar(0.5)*(localAabbMax+localAabbMin);
+ btMatrix3x3 abs_b = trans.getBasis().absolute();
+ btVector3 center = trans(localCenter);
+ btVector3 extent = localHalfExtents.dot3( abs_b[0], abs_b[1], abs_b[2] );
+ aabbMinOut = center-extent;
+ aabbMaxOut = center+extent;
+}
+
+#define USE_BANCHLESS 1
+#ifdef USE_BANCHLESS
+ //This block replaces the block below and uses no branches, and replaces the 8 bit return with a 32 bit return for improved performance (~3x on XBox 360)
+ SIMD_FORCE_INLINE unsigned testQuantizedAabbAgainstQuantizedAabb(const unsigned short int* aabbMin1,const unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2)
+ {
+ return static_cast<unsigned int>(btSelect((unsigned)((aabbMin1[0] <= aabbMax2[0]) & (aabbMax1[0] >= aabbMin2[0])
+ & (aabbMin1[2] <= aabbMax2[2]) & (aabbMax1[2] >= aabbMin2[2])
+ & (aabbMin1[1] <= aabbMax2[1]) & (aabbMax1[1] >= aabbMin2[1])),
+ 1, 0));
+ }
+#else
+ SIMD_FORCE_INLINE bool testQuantizedAabbAgainstQuantizedAabb(const unsigned short int* aabbMin1,const unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2)
+ {
+ bool overlap = true;
+ overlap = (aabbMin1[0] > aabbMax2[0] || aabbMax1[0] < aabbMin2[0]) ? false : overlap;
+ overlap = (aabbMin1[2] > aabbMax2[2] || aabbMax1[2] < aabbMin2[2]) ? false : overlap;
+ overlap = (aabbMin1[1] > aabbMax2[1] || aabbMax1[1] < aabbMin2[1]) ? false : overlap;
+ return overlap;
+ }
+#endif //USE_BANCHLESS
+
+#endif //BT_AABB_UTIL2
+
+
diff --git a/thirdparty/bullet/src/LinearMath/btAlignedAllocator.cpp b/thirdparty/bullet/src/LinearMath/btAlignedAllocator.cpp
new file mode 100644
index 0000000000..e5f6040c43
--- /dev/null
+++ b/thirdparty/bullet/src/LinearMath/btAlignedAllocator.cpp
@@ -0,0 +1,269 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btAlignedAllocator.h"
+
+int gNumAlignedAllocs = 0;
+int gNumAlignedFree = 0;
+int gTotalBytesAlignedAllocs = 0;//detect memory leaks
+
+static void *btAllocDefault(size_t size)
+{
+ return malloc(size);
+}
+
+static void btFreeDefault(void *ptr)
+{
+ free(ptr);
+}
+
+static btAllocFunc *sAllocFunc = btAllocDefault;
+static btFreeFunc *sFreeFunc = btFreeDefault;
+
+
+
+#if defined (BT_HAS_ALIGNED_ALLOCATOR)
+#include <malloc.h>
+static void *btAlignedAllocDefault(size_t size, int alignment)
+{
+ return _aligned_malloc(size, (size_t)alignment);
+}
+
+static void btAlignedFreeDefault(void *ptr)
+{
+ _aligned_free(ptr);
+}
+#elif defined(__CELLOS_LV2__)
+#include <stdlib.h>
+
+static inline void *btAlignedAllocDefault(size_t size, int alignment)
+{
+ return memalign(alignment, size);
+}
+
+static inline void btAlignedFreeDefault(void *ptr)
+{
+ free(ptr);
+}
+#else
+
+
+
+
+
+static inline void *btAlignedAllocDefault(size_t size, int alignment)
+{
+ void *ret;
+ char *real;
+ real = (char *)sAllocFunc(size + sizeof(void *) + (alignment-1));
+ if (real) {
+ ret = btAlignPointer(real + sizeof(void *),alignment);
+ *((void **)(ret)-1) = (void *)(real);
+ } else {
+ ret = (void *)(real);
+ }
+ return (ret);
+}
+
+static inline void btAlignedFreeDefault(void *ptr)
+{
+ void* real;
+
+ if (ptr) {
+ real = *((void **)(ptr)-1);
+ sFreeFunc(real);
+ }
+}
+#endif
+
+
+static btAlignedAllocFunc *sAlignedAllocFunc = btAlignedAllocDefault;
+static btAlignedFreeFunc *sAlignedFreeFunc = btAlignedFreeDefault;
+
+void btAlignedAllocSetCustomAligned(btAlignedAllocFunc *allocFunc, btAlignedFreeFunc *freeFunc)
+{
+ sAlignedAllocFunc = allocFunc ? allocFunc : btAlignedAllocDefault;
+ sAlignedFreeFunc = freeFunc ? freeFunc : btAlignedFreeDefault;
+}
+
+void btAlignedAllocSetCustom(btAllocFunc *allocFunc, btFreeFunc *freeFunc)
+{
+ sAllocFunc = allocFunc ? allocFunc : btAllocDefault;
+ sFreeFunc = freeFunc ? freeFunc : btFreeDefault;
+}
+
+#ifdef BT_DEBUG_MEMORY_ALLOCATIONS
+
+static int allocations_id[10241024];
+static int allocations_bytes[10241024];
+static int mynumallocs = 0;
+#include <stdio.h>
+
+int btDumpMemoryLeaks()
+{
+ int totalLeak = 0;
+
+ for (int i=0;i<mynumallocs;i++)
+ {
+ printf("Error: leaked memory of allocation #%d (%d bytes)\n", allocations_id[i], allocations_bytes[i]);
+ totalLeak+=allocations_bytes[i];
+ }
+ if (totalLeak)
+ {
+ printf("Error: memory leaks: %d allocations were not freed and leaked together %d bytes\n",mynumallocs,totalLeak);
+ }
+ return totalLeak;
+}
+//this generic allocator provides the total allocated number of bytes
+#include <stdio.h>
+
+struct btDebugPtrMagic
+{
+ union
+ {
+ void** vptrptr;
+ void* vptr;
+ int* iptr;
+ char* cptr;
+ };
+};
+
+
+void* btAlignedAllocInternal (size_t size, int alignment,int line,char* filename)
+{
+ if (size==0)
+ {
+ printf("Whaat? size==0");
+ return 0;
+ }
+ static int allocId = 0;
+
+ void *ret;
+ char *real;
+
+// to find some particular memory leak, you could do something like this:
+// if (allocId==172)
+// {
+// printf("catch me!\n");
+// }
+// if (size>1024*1024)
+// {
+// printf("big alloc!%d\n", size);
+// }
+
+ gTotalBytesAlignedAllocs += size;
+ gNumAlignedAllocs++;
+
+
+int sz4prt = 4*sizeof(void *);
+
+ real = (char *)sAllocFunc(size + sz4prt + (alignment-1));
+ if (real) {
+
+ ret = (void*) btAlignPointer(real + sz4prt, alignment);
+ btDebugPtrMagic p;
+ p.vptr = ret;
+ p.cptr-=sizeof(void*);
+ *p.vptrptr = (void*)real;
+ p.cptr-=sizeof(void*);
+ *p.iptr = size;
+ p.cptr-=sizeof(void*);
+ *p.iptr = allocId;
+
+ allocations_id[mynumallocs] = allocId;
+ allocations_bytes[mynumallocs] = size;
+ mynumallocs++;
+
+ } else {
+ ret = (void *)(real);//??
+ }
+
+ printf("allocation %d at address %x, from %s,line %d, size %d (total allocated = %d)\n",allocId,real, filename,line,size,gTotalBytesAlignedAllocs);
+ allocId++;
+
+ int* ptr = (int*)ret;
+ *ptr = 12;
+ return (ret);
+}
+
+void btAlignedFreeInternal (void* ptr,int line,char* filename)
+{
+
+ void* real;
+
+ if (ptr) {
+ gNumAlignedFree++;
+
+ btDebugPtrMagic p;
+ p.vptr = ptr;
+ p.cptr-=sizeof(void*);
+ real = *p.vptrptr;
+ p.cptr-=sizeof(void*);
+ int size = *p.iptr;
+ p.cptr-=sizeof(void*);
+ int allocId = *p.iptr;
+
+ bool found = false;
+
+ for (int i=0;i<mynumallocs;i++)
+ {
+ if ( allocations_id[i] == allocId)
+ {
+ allocations_id[i] = allocations_id[mynumallocs-1];
+ allocations_bytes[i] = allocations_bytes[mynumallocs-1];
+ mynumallocs--;
+ found = true;
+ break;
+ }
+ }
+
+
+ gTotalBytesAlignedAllocs -= size;
+
+ int diff = gNumAlignedAllocs-gNumAlignedFree;
+ printf("free %d at address %x, from %s,line %d, size %d (total remain = %d in %d non-freed allocations)\n",allocId,real, filename,line,size, gTotalBytesAlignedAllocs, diff);
+
+ sFreeFunc(real);
+ } else
+ {
+ //printf("deleting a NULL ptr, no effect\n");
+ }
+}
+
+#else //BT_DEBUG_MEMORY_ALLOCATIONS
+
+void* btAlignedAllocInternal (size_t size, int alignment)
+{
+ gNumAlignedAllocs++;
+ void* ptr;
+ ptr = sAlignedAllocFunc(size, alignment);
+// printf("btAlignedAllocInternal %d, %x\n",size,ptr);
+ return ptr;
+}
+
+void btAlignedFreeInternal (void* ptr)
+{
+ if (!ptr)
+ {
+ return;
+ }
+
+ gNumAlignedFree++;
+// printf("btAlignedFreeInternal %x\n",ptr);
+ sAlignedFreeFunc(ptr);
+}
+
+#endif //BT_DEBUG_MEMORY_ALLOCATIONS
+
diff --git a/thirdparty/bullet/src/LinearMath/btAlignedAllocator.h b/thirdparty/bullet/src/LinearMath/btAlignedAllocator.h
new file mode 100644
index 0000000000..9873b338d9
--- /dev/null
+++ b/thirdparty/bullet/src/LinearMath/btAlignedAllocator.h
@@ -0,0 +1,113 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_ALIGNED_ALLOCATOR
+#define BT_ALIGNED_ALLOCATOR
+
+///we probably replace this with our own aligned memory allocator
+///so we replace _aligned_malloc and _aligned_free with our own
+///that is better portable and more predictable
+
+#include "btScalar.h"
+
+
+///BT_DEBUG_MEMORY_ALLOCATIONS preprocessor can be set in build system
+///for regression tests to detect memory leaks
+///#define BT_DEBUG_MEMORY_ALLOCATIONS 1
+#ifdef BT_DEBUG_MEMORY_ALLOCATIONS
+
+int btDumpMemoryLeaks();
+
+#define btAlignedAlloc(a,b) \
+ btAlignedAllocInternal(a,b,__LINE__,__FILE__)
+
+#define btAlignedFree(ptr) \
+ btAlignedFreeInternal(ptr,__LINE__,__FILE__)
+
+void* btAlignedAllocInternal (size_t size, int alignment,int line,char* filename);
+
+void btAlignedFreeInternal (void* ptr,int line,char* filename);
+
+#else
+ void* btAlignedAllocInternal (size_t size, int alignment);
+ void btAlignedFreeInternal (void* ptr);
+
+ #define btAlignedAlloc(size,alignment) btAlignedAllocInternal(size,alignment)
+ #define btAlignedFree(ptr) btAlignedFreeInternal(ptr)
+
+#endif
+typedef int size_type;
+
+typedef void *(btAlignedAllocFunc)(size_t size, int alignment);
+typedef void (btAlignedFreeFunc)(void *memblock);
+typedef void *(btAllocFunc)(size_t size);
+typedef void (btFreeFunc)(void *memblock);
+
+///The developer can let all Bullet memory allocations go through a custom memory allocator, using btAlignedAllocSetCustom
+void btAlignedAllocSetCustom(btAllocFunc *allocFunc, btFreeFunc *freeFunc);
+///If the developer has already an custom aligned allocator, then btAlignedAllocSetCustomAligned can be used. The default aligned allocator pre-allocates extra memory using the non-aligned allocator, and instruments it.
+void btAlignedAllocSetCustomAligned(btAlignedAllocFunc *allocFunc, btAlignedFreeFunc *freeFunc);
+
+
+///The btAlignedAllocator is a portable class for aligned memory allocations.
+///Default implementations for unaligned and aligned allocations can be overridden by a custom allocator using btAlignedAllocSetCustom and btAlignedAllocSetCustomAligned.
+template < typename T , unsigned Alignment >
+class btAlignedAllocator {
+
+ typedef btAlignedAllocator< T , Alignment > self_type;
+
+public:
+
+ //just going down a list:
+ btAlignedAllocator() {}
+ /*
+ btAlignedAllocator( const self_type & ) {}
+ */
+
+ template < typename Other >
+ btAlignedAllocator( const btAlignedAllocator< Other , Alignment > & ) {}
+
+ typedef const T* const_pointer;
+ typedef const T& const_reference;
+ typedef T* pointer;
+ typedef T& reference;
+ typedef T value_type;
+
+ pointer address ( reference ref ) const { return &ref; }
+ const_pointer address ( const_reference ref ) const { return &ref; }
+ pointer allocate ( size_type n , const_pointer * hint = 0 ) {
+ (void)hint;
+ return reinterpret_cast< pointer >(btAlignedAlloc( sizeof(value_type) * n , Alignment ));
+ }
+ void construct ( pointer ptr , const value_type & value ) { new (ptr) value_type( value ); }
+ void deallocate( pointer ptr ) {
+ btAlignedFree( reinterpret_cast< void * >( ptr ) );
+ }
+ void destroy ( pointer ptr ) { ptr->~value_type(); }
+
+
+ template < typename O > struct rebind {
+ typedef btAlignedAllocator< O , Alignment > other;
+ };
+ template < typename O >
+ self_type & operator=( const btAlignedAllocator< O , Alignment > & ) { return *this; }
+
+ friend bool operator==( const self_type & , const self_type & ) { return true; }
+};
+
+
+
+#endif //BT_ALIGNED_ALLOCATOR
+
diff --git a/thirdparty/bullet/src/LinearMath/btAlignedObjectArray.h b/thirdparty/bullet/src/LinearMath/btAlignedObjectArray.h
new file mode 100644
index 0000000000..f0b646529a
--- /dev/null
+++ b/thirdparty/bullet/src/LinearMath/btAlignedObjectArray.h
@@ -0,0 +1,530 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#ifndef BT_OBJECT_ARRAY__
+#define BT_OBJECT_ARRAY__
+
+#include "btScalar.h" // has definitions like SIMD_FORCE_INLINE
+#include "btAlignedAllocator.h"
+
+///If the platform doesn't support placement new, you can disable BT_USE_PLACEMENT_NEW
+///then the btAlignedObjectArray doesn't support objects with virtual methods, and non-trivial constructors/destructors
+///You can enable BT_USE_MEMCPY, then swapping elements in the array will use memcpy instead of operator=
+///see discussion here: http://continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1231 and
+///http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1240
+
+#define BT_USE_PLACEMENT_NEW 1
+//#define BT_USE_MEMCPY 1 //disable, because it is cumbersome to find out for each platform where memcpy is defined. It can be in <memory.h> or <string.h> or otherwise...
+#define BT_ALLOW_ARRAY_COPY_OPERATOR // enabling this can accidently perform deep copies of data if you are not careful
+
+#ifdef BT_USE_MEMCPY
+#include <memory.h>
+#include <string.h>
+#endif //BT_USE_MEMCPY
+
+#ifdef BT_USE_PLACEMENT_NEW
+#include <new> //for placement new
+#endif //BT_USE_PLACEMENT_NEW
+
+// The register keyword is deprecated in C++11 so don't use it.
+#if __cplusplus > 199711L
+#define BT_REGISTER
+#else
+#define BT_REGISTER register
+#endif
+
+///The btAlignedObjectArray template class uses a subset of the stl::vector interface for its methods
+///It is developed to replace stl::vector to avoid portability issues, including STL alignment issues to add SIMD/SSE data
+template <typename T>
+//template <class T>
+class btAlignedObjectArray
+{
+ btAlignedAllocator<T , 16> m_allocator;
+
+ int m_size;
+ int m_capacity;
+ T* m_data;
+ //PCK: added this line
+ bool m_ownsMemory;
+
+#ifdef BT_ALLOW_ARRAY_COPY_OPERATOR
+public:
+ SIMD_FORCE_INLINE btAlignedObjectArray<T>& operator=(const btAlignedObjectArray<T> &other)
+ {
+ copyFromArray(other);
+ return *this;
+ }
+#else//BT_ALLOW_ARRAY_COPY_OPERATOR
+private:
+ SIMD_FORCE_INLINE btAlignedObjectArray<T>& operator=(const btAlignedObjectArray<T> &other);
+#endif//BT_ALLOW_ARRAY_COPY_OPERATOR
+
+protected:
+ SIMD_FORCE_INLINE int allocSize(int size)
+ {
+ return (size ? size*2 : 1);
+ }
+ SIMD_FORCE_INLINE void copy(int start,int end, T* dest) const
+ {
+ int i;
+ for (i=start;i<end;++i)
+#ifdef BT_USE_PLACEMENT_NEW
+ new (&dest[i]) T(m_data[i]);
+#else
+ dest[i] = m_data[i];
+#endif //BT_USE_PLACEMENT_NEW
+ }
+
+ SIMD_FORCE_INLINE void init()
+ {
+ //PCK: added this line
+ m_ownsMemory = true;
+ m_data = 0;
+ m_size = 0;
+ m_capacity = 0;
+ }
+ SIMD_FORCE_INLINE void destroy(int first,int last)
+ {
+ int i;
+ for (i=first; i<last;i++)
+ {
+ m_data[i].~T();
+ }
+ }
+
+ SIMD_FORCE_INLINE void* allocate(int size)
+ {
+ if (size)
+ return m_allocator.allocate(size);
+ return 0;
+ }
+
+ SIMD_FORCE_INLINE void deallocate()
+ {
+ if(m_data) {
+ //PCK: enclosed the deallocation in this block
+ if (m_ownsMemory)
+ {
+ m_allocator.deallocate(m_data);
+ }
+ m_data = 0;
+ }
+ }
+
+
+
+
+ public:
+
+ btAlignedObjectArray()
+ {
+ init();
+ }
+
+ ~btAlignedObjectArray()
+ {
+ clear();
+ }
+
+ ///Generally it is best to avoid using the copy constructor of an btAlignedObjectArray, and use a (const) reference to the array instead.
+ btAlignedObjectArray(const btAlignedObjectArray& otherArray)
+ {
+ init();
+
+ int otherSize = otherArray.size();
+ resize (otherSize);
+ otherArray.copy(0, otherSize, m_data);
+ }
+
+
+
+ /// return the number of elements in the array
+ SIMD_FORCE_INLINE int size() const
+ {
+ return m_size;
+ }
+
+ SIMD_FORCE_INLINE const T& at(int n) const
+ {
+ btAssert(n>=0);
+ btAssert(n<size());
+ return m_data[n];
+ }
+
+ SIMD_FORCE_INLINE T& at(int n)
+ {
+ btAssert(n>=0);
+ btAssert(n<size());
+ return m_data[n];
+ }
+
+ SIMD_FORCE_INLINE const T& operator[](int n) const
+ {
+ btAssert(n>=0);
+ btAssert(n<size());
+ return m_data[n];
+ }
+
+ SIMD_FORCE_INLINE T& operator[](int n)
+ {
+ btAssert(n>=0);
+ btAssert(n<size());
+ return m_data[n];
+ }
+
+
+ ///clear the array, deallocated memory. Generally it is better to use array.resize(0), to reduce performance overhead of run-time memory (de)allocations.
+ SIMD_FORCE_INLINE void clear()
+ {
+ destroy(0,size());
+
+ deallocate();
+
+ init();
+ }
+
+ SIMD_FORCE_INLINE void pop_back()
+ {
+ btAssert(m_size>0);
+ m_size--;
+ m_data[m_size].~T();
+ }
+
+
+ ///resize changes the number of elements in the array. If the new size is larger, the new elements will be constructed using the optional second argument.
+ ///when the new number of elements is smaller, the destructor will be called, but memory will not be freed, to reduce performance overhead of run-time memory (de)allocations.
+ SIMD_FORCE_INLINE void resizeNoInitialize(int newsize)
+ {
+ if (newsize > size())
+ {
+ reserve(newsize);
+ }
+ m_size = newsize;
+ }
+
+ SIMD_FORCE_INLINE void resize(int newsize, const T& fillData=T())
+ {
+ const BT_REGISTER int curSize = size();
+
+ if (newsize < curSize)
+ {
+ for(int i = newsize; i < curSize; i++)
+ {
+ m_data[i].~T();
+ }
+ } else
+ {
+ if (newsize > curSize)
+ {
+ reserve(newsize);
+ }
+#ifdef BT_USE_PLACEMENT_NEW
+ for (int i=curSize;i<newsize;i++)
+ {
+ new ( &m_data[i]) T(fillData);
+ }
+#endif //BT_USE_PLACEMENT_NEW
+
+ }
+
+ m_size = newsize;
+ }
+ SIMD_FORCE_INLINE T& expandNonInitializing( )
+ {
+ const BT_REGISTER int sz = size();
+ if( sz == capacity() )
+ {
+ reserve( allocSize(size()) );
+ }
+ m_size++;
+
+ return m_data[sz];
+ }
+
+
+ SIMD_FORCE_INLINE T& expand( const T& fillValue=T())
+ {
+ const BT_REGISTER int sz = size();
+ if( sz == capacity() )
+ {
+ reserve( allocSize(size()) );
+ }
+ m_size++;
+#ifdef BT_USE_PLACEMENT_NEW
+ new (&m_data[sz]) T(fillValue); //use the in-place new (not really allocating heap memory)
+#endif
+
+ return m_data[sz];
+ }
+
+
+ SIMD_FORCE_INLINE void push_back(const T& _Val)
+ {
+ const BT_REGISTER int sz = size();
+ if( sz == capacity() )
+ {
+ reserve( allocSize(size()) );
+ }
+
+#ifdef BT_USE_PLACEMENT_NEW
+ new ( &m_data[m_size] ) T(_Val);
+#else
+ m_data[size()] = _Val;
+#endif //BT_USE_PLACEMENT_NEW
+
+ m_size++;
+ }
+
+
+ /// return the pre-allocated (reserved) elements, this is at least as large as the total number of elements,see size() and reserve()
+ SIMD_FORCE_INLINE int capacity() const
+ {
+ return m_capacity;
+ }
+
+ SIMD_FORCE_INLINE void reserve(int _Count)
+ { // determine new minimum length of allocated storage
+ if (capacity() < _Count)
+ { // not enough room, reallocate
+ T* s = (T*)allocate(_Count);
+
+ copy(0, size(), s);
+
+ destroy(0,size());
+
+ deallocate();
+
+ //PCK: added this line
+ m_ownsMemory = true;
+
+ m_data = s;
+
+ m_capacity = _Count;
+
+ }
+ }
+
+
+ class less
+ {
+ public:
+
+ bool operator() ( const T& a, const T& b ) const
+ {
+ return ( a < b );
+ }
+ };
+
+
+ template <typename L>
+ void quickSortInternal(const L& CompareFunc,int lo, int hi)
+ {
+ // lo is the lower index, hi is the upper index
+ // of the region of array a that is to be sorted
+ int i=lo, j=hi;
+ T x=m_data[(lo+hi)/2];
+
+ // partition
+ do
+ {
+ while (CompareFunc(m_data[i],x))
+ i++;
+ while (CompareFunc(x,m_data[j]))
+ j--;
+ if (i<=j)
+ {
+ swap(i,j);
+ i++; j--;
+ }
+ } while (i<=j);
+
+ // recursion
+ if (lo<j)
+ quickSortInternal( CompareFunc, lo, j);
+ if (i<hi)
+ quickSortInternal( CompareFunc, i, hi);
+ }
+
+
+ template <typename L>
+ void quickSort(const L& CompareFunc)
+ {
+ //don't sort 0 or 1 elements
+ if (size()>1)
+ {
+ quickSortInternal(CompareFunc,0,size()-1);
+ }
+ }
+
+
+ ///heap sort from http://www.csse.monash.edu.au/~lloyd/tildeAlgDS/Sort/Heap/
+ template <typename L>
+ void downHeap(T *pArr, int k, int n, const L& CompareFunc)
+ {
+ /* PRE: a[k+1..N] is a heap */
+ /* POST: a[k..N] is a heap */
+
+ T temp = pArr[k - 1];
+ /* k has child(s) */
+ while (k <= n/2)
+ {
+ int child = 2*k;
+
+ if ((child < n) && CompareFunc(pArr[child - 1] , pArr[child]))
+ {
+ child++;
+ }
+ /* pick larger child */
+ if (CompareFunc(temp , pArr[child - 1]))
+ {
+ /* move child up */
+ pArr[k - 1] = pArr[child - 1];
+ k = child;
+ }
+ else
+ {
+ break;
+ }
+ }
+ pArr[k - 1] = temp;
+ } /*downHeap*/
+
+ void swap(int index0,int index1)
+ {
+#ifdef BT_USE_MEMCPY
+ char temp[sizeof(T)];
+ memcpy(temp,&m_data[index0],sizeof(T));
+ memcpy(&m_data[index0],&m_data[index1],sizeof(T));
+ memcpy(&m_data[index1],temp,sizeof(T));
+#else
+ T temp = m_data[index0];
+ m_data[index0] = m_data[index1];
+ m_data[index1] = temp;
+#endif //BT_USE_PLACEMENT_NEW
+
+ }
+
+ template <typename L>
+ void heapSort(const L& CompareFunc)
+ {
+ /* sort a[0..N-1], N.B. 0 to N-1 */
+ int k;
+ int n = m_size;
+ for (k = n/2; k > 0; k--)
+ {
+ downHeap(m_data, k, n, CompareFunc);
+ }
+
+ /* a[1..N] is now a heap */
+ while ( n>=1 )
+ {
+ swap(0,n-1); /* largest of a[0..n-1] */
+
+
+ n = n - 1;
+ /* restore a[1..i-1] heap */
+ downHeap(m_data, 1, n, CompareFunc);
+ }
+ }
+
+ ///non-recursive binary search, assumes sorted array
+ int findBinarySearch(const T& key) const
+ {
+ int first = 0;
+ int last = size()-1;
+
+ //assume sorted array
+ while (first <= last) {
+ int mid = (first + last) / 2; // compute mid point.
+ if (key > m_data[mid])
+ first = mid + 1; // repeat search in top half.
+ else if (key < m_data[mid])
+ last = mid - 1; // repeat search in bottom half.
+ else
+ return mid; // found it. return position /////
+ }
+ return size(); // failed to find key
+ }
+
+
+ int findLinearSearch(const T& key) const
+ {
+ int index=size();
+ int i;
+
+ for (i=0;i<size();i++)
+ {
+ if (m_data[i] == key)
+ {
+ index = i;
+ break;
+ }
+ }
+ return index;
+ }
+
+ // If the key is not in the array, return -1 instead of 0,
+ // since 0 also means the first element in the array.
+ int findLinearSearch2(const T& key) const
+ {
+ int index=-1;
+ int i;
+
+ for (i=0;i<size();i++)
+ {
+ if (m_data[i] == key)
+ {
+ index = i;
+ break;
+ }
+ }
+ return index;
+ }
+
+ void removeAtIndex(int index)
+ {
+ if (index<size())
+ {
+ swap( index,size()-1);
+ pop_back();
+ }
+ }
+ void remove(const T& key)
+ {
+ int findIndex = findLinearSearch(key);
+ removeAtIndex(findIndex);
+ }
+
+ //PCK: whole function
+ void initializeFromBuffer(void *buffer, int size, int capacity)
+ {
+ clear();
+ m_ownsMemory = false;
+ m_data = (T*)buffer;
+ m_size = size;
+ m_capacity = capacity;
+ }
+
+ void copyFromArray(const btAlignedObjectArray& otherArray)
+ {
+ int otherSize = otherArray.size();
+ resize (otherSize);
+ otherArray.copy(0, otherSize, m_data);
+ }
+
+};
+
+#endif //BT_OBJECT_ARRAY__
diff --git a/thirdparty/bullet/src/LinearMath/btConvexHull.cpp b/thirdparty/bullet/src/LinearMath/btConvexHull.cpp
new file mode 100644
index 0000000000..f8b79a1aba
--- /dev/null
+++ b/thirdparty/bullet/src/LinearMath/btConvexHull.cpp
@@ -0,0 +1,1167 @@
+/*
+Stan Melax Convex Hull Computation
+Copyright (c) 2003-2006 Stan Melax http://www.melax.com/
+
+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 <string.h>
+
+#include "btConvexHull.h"
+#include "btAlignedObjectArray.h"
+#include "btMinMax.h"
+#include "btVector3.h"
+
+
+
+
+
+//----------------------------------
+
+class int3
+{
+public:
+ int x,y,z;
+ int3(){};
+ int3(int _x,int _y, int _z){x=_x;y=_y;z=_z;}
+ const int& operator[](int i) const {return (&x)[i];}
+ int& operator[](int i) {return (&x)[i];}
+};
+
+
+//------- btPlane ----------
+
+
+inline btPlane PlaneFlip(const btPlane &plane){return btPlane(-plane.normal,-plane.dist);}
+inline int operator==( const btPlane &a, const btPlane &b ) { return (a.normal==b.normal && a.dist==b.dist); }
+inline int coplanar( const btPlane &a, const btPlane &b ) { return (a==b || a==PlaneFlip(b)); }
+
+
+//--------- Utility Functions ------
+
+btVector3 PlaneLineIntersection(const btPlane &plane, const btVector3 &p0, const btVector3 &p1);
+btVector3 PlaneProject(const btPlane &plane, const btVector3 &point);
+
+btVector3 ThreePlaneIntersection(const btPlane &p0,const btPlane &p1, const btPlane &p2);
+btVector3 ThreePlaneIntersection(const btPlane &p0,const btPlane &p1, const btPlane &p2)
+{
+ btVector3 N1 = p0.normal;
+ btVector3 N2 = p1.normal;
+ btVector3 N3 = p2.normal;
+
+ btVector3 n2n3; n2n3 = N2.cross(N3);
+ btVector3 n3n1; n3n1 = N3.cross(N1);
+ btVector3 n1n2; n1n2 = N1.cross(N2);
+
+ btScalar quotient = (N1.dot(n2n3));
+
+ btAssert(btFabs(quotient) > btScalar(0.000001));
+
+ quotient = btScalar(-1.) / quotient;
+ n2n3 *= p0.dist;
+ n3n1 *= p1.dist;
+ n1n2 *= p2.dist;
+ btVector3 potentialVertex = n2n3;
+ potentialVertex += n3n1;
+ potentialVertex += n1n2;
+ potentialVertex *= quotient;
+
+ btVector3 result(potentialVertex.getX(),potentialVertex.getY(),potentialVertex.getZ());
+ return result;
+
+}
+
+btScalar DistanceBetweenLines(const btVector3 &ustart, const btVector3 &udir, const btVector3 &vstart, const btVector3 &vdir, btVector3 *upoint=NULL, btVector3 *vpoint=NULL);
+btVector3 TriNormal(const btVector3 &v0, const btVector3 &v1, const btVector3 &v2);
+btVector3 NormalOf(const btVector3 *vert, const int n);
+
+
+btVector3 PlaneLineIntersection(const btPlane &plane, const btVector3 &p0, const btVector3 &p1)
+{
+ // returns the point where the line p0-p1 intersects the plane n&d
+ btVector3 dif;
+ dif = p1-p0;
+ btScalar dn= btDot(plane.normal,dif);
+ btScalar t = -(plane.dist+btDot(plane.normal,p0) )/dn;
+ return p0 + (dif*t);
+}
+
+btVector3 PlaneProject(const btPlane &plane, const btVector3 &point)
+{
+ return point - plane.normal * (btDot(point,plane.normal)+plane.dist);
+}
+
+btVector3 TriNormal(const btVector3 &v0, const btVector3 &v1, const btVector3 &v2)
+{
+ // return the normal of the triangle
+ // inscribed by v0, v1, and v2
+ btVector3 cp=btCross(v1-v0,v2-v1);
+ btScalar m=cp.length();
+ if(m==0) return btVector3(1,0,0);
+ return cp*(btScalar(1.0)/m);
+}
+
+
+btScalar DistanceBetweenLines(const btVector3 &ustart, const btVector3 &udir, const btVector3 &vstart, const btVector3 &vdir, btVector3 *upoint, btVector3 *vpoint)
+{
+ btVector3 cp;
+ cp = btCross(udir,vdir).normalized();
+
+ btScalar distu = -btDot(cp,ustart);
+ btScalar distv = -btDot(cp,vstart);
+ btScalar dist = (btScalar)fabs(distu-distv);
+ if(upoint)
+ {
+ btPlane plane;
+ plane.normal = btCross(vdir,cp).normalized();
+ plane.dist = -btDot(plane.normal,vstart);
+ *upoint = PlaneLineIntersection(plane,ustart,ustart+udir);
+ }
+ if(vpoint)
+ {
+ btPlane plane;
+ plane.normal = btCross(udir,cp).normalized();
+ plane.dist = -btDot(plane.normal,ustart);
+ *vpoint = PlaneLineIntersection(plane,vstart,vstart+vdir);
+ }
+ return dist;
+}
+
+
+
+
+
+
+
+#define COPLANAR (0)
+#define UNDER (1)
+#define OVER (2)
+#define SPLIT (OVER|UNDER)
+#define PAPERWIDTH (btScalar(0.001))
+
+btScalar planetestepsilon = PAPERWIDTH;
+
+
+
+typedef ConvexH::HalfEdge HalfEdge;
+
+ConvexH::ConvexH(int vertices_size,int edges_size,int facets_size)
+{
+ vertices.resize(vertices_size);
+ edges.resize(edges_size);
+ facets.resize(facets_size);
+}
+
+
+int PlaneTest(const btPlane &p, const btVector3 &v);
+int PlaneTest(const btPlane &p, const btVector3 &v) {
+ btScalar a = btDot(v,p.normal)+p.dist;
+ int flag = (a>planetestepsilon)?OVER:((a<-planetestepsilon)?UNDER:COPLANAR);
+ return flag;
+}
+
+int SplitTest(ConvexH &convex,const btPlane &plane);
+int SplitTest(ConvexH &convex,const btPlane &plane) {
+ int flag=0;
+ for(int i=0;i<convex.vertices.size();i++) {
+ flag |= PlaneTest(plane,convex.vertices[i]);
+ }
+ return flag;
+}
+
+class VertFlag
+{
+public:
+ unsigned char planetest;
+ unsigned char junk;
+ unsigned char undermap;
+ unsigned char overmap;
+};
+class EdgeFlag
+{
+public:
+ unsigned char planetest;
+ unsigned char fixes;
+ short undermap;
+ short overmap;
+};
+class PlaneFlag
+{
+public:
+ unsigned char undermap;
+ unsigned char overmap;
+};
+class Coplanar{
+public:
+ unsigned short ea;
+ unsigned char v0;
+ unsigned char v1;
+};
+
+
+
+
+
+
+
+
+template<class T>
+int maxdirfiltered(const T *p,int count,const T &dir,btAlignedObjectArray<int> &allow)
+{
+ btAssert(count);
+ int m=-1;
+ for(int i=0;i<count;i++)
+ if(allow[i])
+ {
+ if(m==-1 || btDot(p[i],dir)>btDot(p[m],dir))
+ m=i;
+ }
+ btAssert(m!=-1);
+ return m;
+}
+
+btVector3 orth(const btVector3 &v);
+btVector3 orth(const btVector3 &v)
+{
+ btVector3 a=btCross(v,btVector3(0,0,1));
+ btVector3 b=btCross(v,btVector3(0,1,0));
+ if (a.length() > b.length())
+ {
+ return a.normalized();
+ } else {
+ return b.normalized();
+ }
+}
+
+
+template<class T>
+int maxdirsterid(const T *p,int count,const T &dir,btAlignedObjectArray<int> &allow)
+{
+ int m=-1;
+ while(m==-1)
+ {
+ m = maxdirfiltered(p,count,dir,allow);
+ if(allow[m]==3) return m;
+ T u = orth(dir);
+ T v = btCross(u,dir);
+ int ma=-1;
+ for(btScalar x = btScalar(0.0) ; x<= btScalar(360.0) ; x+= btScalar(45.0))
+ {
+ btScalar s = btSin(SIMD_RADS_PER_DEG*(x));
+ btScalar c = btCos(SIMD_RADS_PER_DEG*(x));
+ int mb = maxdirfiltered(p,count,dir+(u*s+v*c)*btScalar(0.025),allow);
+ if(ma==m && mb==m)
+ {
+ allow[m]=3;
+ return m;
+ }
+ if(ma!=-1 && ma!=mb) // Yuck - this is really ugly
+ {
+ int mc = ma;
+ for(btScalar xx = x-btScalar(40.0) ; xx <= x ; xx+= btScalar(5.0))
+ {
+ btScalar s = btSin(SIMD_RADS_PER_DEG*(xx));
+ btScalar c = btCos(SIMD_RADS_PER_DEG*(xx));
+ int md = maxdirfiltered(p,count,dir+(u*s+v*c)*btScalar(0.025),allow);
+ if(mc==m && md==m)
+ {
+ allow[m]=3;
+ return m;
+ }
+ mc=md;
+ }
+ }
+ ma=mb;
+ }
+ allow[m]=0;
+ m=-1;
+ }
+ btAssert(0);
+ return m;
+}
+
+
+
+
+int operator ==(const int3 &a,const int3 &b);
+int operator ==(const int3 &a,const int3 &b)
+{
+ for(int i=0;i<3;i++)
+ {
+ if(a[i]!=b[i]) return 0;
+ }
+ return 1;
+}
+
+
+int above(btVector3* vertices,const int3& t, const btVector3 &p, btScalar epsilon);
+int above(btVector3* vertices,const int3& t, const btVector3 &p, btScalar epsilon)
+{
+ btVector3 n=TriNormal(vertices[t[0]],vertices[t[1]],vertices[t[2]]);
+ return (btDot(n,p-vertices[t[0]]) > epsilon); // EPSILON???
+}
+int hasedge(const int3 &t, int a,int b);
+int hasedge(const int3 &t, int a,int b)
+{
+ for(int i=0;i<3;i++)
+ {
+ int i1= (i+1)%3;
+ if(t[i]==a && t[i1]==b) return 1;
+ }
+ return 0;
+}
+int hasvert(const int3 &t, int v);
+int hasvert(const int3 &t, int v)
+{
+ return (t[0]==v || t[1]==v || t[2]==v) ;
+}
+int shareedge(const int3 &a,const int3 &b);
+int shareedge(const int3 &a,const int3 &b)
+{
+ int i;
+ for(i=0;i<3;i++)
+ {
+ int i1= (i+1)%3;
+ if(hasedge(a,b[i1],b[i])) return 1;
+ }
+ return 0;
+}
+
+class btHullTriangle;
+
+
+
+class btHullTriangle : public int3
+{
+public:
+ int3 n;
+ int id;
+ int vmax;
+ btScalar rise;
+ btHullTriangle(int a,int b,int c):int3(a,b,c),n(-1,-1,-1)
+ {
+ vmax=-1;
+ rise = btScalar(0.0);
+ }
+ ~btHullTriangle()
+ {
+ }
+ int &neib(int a,int b);
+};
+
+
+int &btHullTriangle::neib(int a,int b)
+{
+ static int er=-1;
+ int i;
+ for(i=0;i<3;i++)
+ {
+ int i1=(i+1)%3;
+ int i2=(i+2)%3;
+ if((*this)[i]==a && (*this)[i1]==b) return n[i2];
+ if((*this)[i]==b && (*this)[i1]==a) return n[i2];
+ }
+ btAssert(0);
+ return er;
+}
+void HullLibrary::b2bfix(btHullTriangle* s,btHullTriangle*t)
+{
+ int i;
+ for(i=0;i<3;i++)
+ {
+ int i1=(i+1)%3;
+ int i2=(i+2)%3;
+ int a = (*s)[i1];
+ int b = (*s)[i2];
+ btAssert(m_tris[s->neib(a,b)]->neib(b,a) == s->id);
+ btAssert(m_tris[t->neib(a,b)]->neib(b,a) == t->id);
+ m_tris[s->neib(a,b)]->neib(b,a) = t->neib(b,a);
+ m_tris[t->neib(b,a)]->neib(a,b) = s->neib(a,b);
+ }
+}
+
+void HullLibrary::removeb2b(btHullTriangle* s,btHullTriangle*t)
+{
+ b2bfix(s,t);
+ deAllocateTriangle(s);
+
+ deAllocateTriangle(t);
+}
+
+void HullLibrary::checkit(btHullTriangle *t)
+{
+ (void)t;
+
+ int i;
+ btAssert(m_tris[t->id]==t);
+ for(i=0;i<3;i++)
+ {
+ int i1=(i+1)%3;
+ int i2=(i+2)%3;
+ int a = (*t)[i1];
+ int b = (*t)[i2];
+
+ // release compile fix
+ (void)i1;
+ (void)i2;
+ (void)a;
+ (void)b;
+
+ btAssert(a!=b);
+ btAssert( m_tris[t->n[i]]->neib(b,a) == t->id);
+ }
+}
+
+btHullTriangle* HullLibrary::allocateTriangle(int a,int b,int c)
+{
+ void* mem = btAlignedAlloc(sizeof(btHullTriangle),16);
+ btHullTriangle* tr = new (mem)btHullTriangle(a,b,c);
+ tr->id = m_tris.size();
+ m_tris.push_back(tr);
+
+ return tr;
+}
+
+void HullLibrary::deAllocateTriangle(btHullTriangle* tri)
+{
+ btAssert(m_tris[tri->id]==tri);
+ m_tris[tri->id]=NULL;
+ tri->~btHullTriangle();
+ btAlignedFree(tri);
+}
+
+
+void HullLibrary::extrude(btHullTriangle *t0,int v)
+{
+ int3 t= *t0;
+ int n = m_tris.size();
+ btHullTriangle* ta = allocateTriangle(v,t[1],t[2]);
+ ta->n = int3(t0->n[0],n+1,n+2);
+ m_tris[t0->n[0]]->neib(t[1],t[2]) = n+0;
+ btHullTriangle* tb = allocateTriangle(v,t[2],t[0]);
+ tb->n = int3(t0->n[1],n+2,n+0);
+ m_tris[t0->n[1]]->neib(t[2],t[0]) = n+1;
+ btHullTriangle* tc = allocateTriangle(v,t[0],t[1]);
+ tc->n = int3(t0->n[2],n+0,n+1);
+ m_tris[t0->n[2]]->neib(t[0],t[1]) = n+2;
+ checkit(ta);
+ checkit(tb);
+ checkit(tc);
+ if(hasvert(*m_tris[ta->n[0]],v)) removeb2b(ta,m_tris[ta->n[0]]);
+ if(hasvert(*m_tris[tb->n[0]],v)) removeb2b(tb,m_tris[tb->n[0]]);
+ if(hasvert(*m_tris[tc->n[0]],v)) removeb2b(tc,m_tris[tc->n[0]]);
+ deAllocateTriangle(t0);
+
+}
+
+btHullTriangle* HullLibrary::extrudable(btScalar epsilon)
+{
+ int i;
+ btHullTriangle *t=NULL;
+ for(i=0;i<m_tris.size();i++)
+ {
+ if(!t || (m_tris[i] && t->rise<m_tris[i]->rise))
+ {
+ t = m_tris[i];
+ }
+ }
+ return (t->rise >epsilon)?t:NULL ;
+}
+
+
+
+
+int4 HullLibrary::FindSimplex(btVector3 *verts,int verts_count,btAlignedObjectArray<int> &allow)
+{
+ btVector3 basis[3];
+ basis[0] = btVector3( btScalar(0.01), btScalar(0.02), btScalar(1.0) );
+ int p0 = maxdirsterid(verts,verts_count, basis[0],allow);
+ int p1 = maxdirsterid(verts,verts_count,-basis[0],allow);
+ basis[0] = verts[p0]-verts[p1];
+ if(p0==p1 || basis[0]==btVector3(0,0,0))
+ return int4(-1,-1,-1,-1);
+ basis[1] = btCross(btVector3( btScalar(1),btScalar(0.02), btScalar(0)),basis[0]);
+ basis[2] = btCross(btVector3(btScalar(-0.02), btScalar(1), btScalar(0)),basis[0]);
+ if (basis[1].length() > basis[2].length())
+ {
+ basis[1].normalize();
+ } else {
+ basis[1] = basis[2];
+ basis[1].normalize ();
+ }
+ int p2 = maxdirsterid(verts,verts_count,basis[1],allow);
+ if(p2 == p0 || p2 == p1)
+ {
+ p2 = maxdirsterid(verts,verts_count,-basis[1],allow);
+ }
+ if(p2 == p0 || p2 == p1)
+ return int4(-1,-1,-1,-1);
+ basis[1] = verts[p2] - verts[p0];
+ basis[2] = btCross(basis[1],basis[0]).normalized();
+ int p3 = maxdirsterid(verts,verts_count,basis[2],allow);
+ if(p3==p0||p3==p1||p3==p2) p3 = maxdirsterid(verts,verts_count,-basis[2],allow);
+ if(p3==p0||p3==p1||p3==p2)
+ return int4(-1,-1,-1,-1);
+ btAssert(!(p0==p1||p0==p2||p0==p3||p1==p2||p1==p3||p2==p3));
+ if(btDot(verts[p3]-verts[p0],btCross(verts[p1]-verts[p0],verts[p2]-verts[p0])) <0) {btSwap(p2,p3);}
+ return int4(p0,p1,p2,p3);
+}
+
+int HullLibrary::calchullgen(btVector3 *verts,int verts_count, int vlimit)
+{
+ if(verts_count <4) return 0;
+ if(vlimit==0) vlimit=1000000000;
+ int j;
+ btVector3 bmin(*verts),bmax(*verts);
+ btAlignedObjectArray<int> isextreme;
+ isextreme.reserve(verts_count);
+ btAlignedObjectArray<int> allow;
+ allow.reserve(verts_count);
+
+ for(j=0;j<verts_count;j++)
+ {
+ allow.push_back(1);
+ isextreme.push_back(0);
+ bmin.setMin (verts[j]);
+ bmax.setMax (verts[j]);
+ }
+ btScalar epsilon = (bmax-bmin).length() * btScalar(0.001);
+ btAssert (epsilon != 0.0);
+
+
+ int4 p = FindSimplex(verts,verts_count,allow);
+ if(p.x==-1) return 0; // simplex failed
+
+
+
+ btVector3 center = (verts[p[0]]+verts[p[1]]+verts[p[2]]+verts[p[3]]) / btScalar(4.0); // a valid interior point
+ btHullTriangle *t0 = allocateTriangle(p[2],p[3],p[1]); t0->n=int3(2,3,1);
+ btHullTriangle *t1 = allocateTriangle(p[3],p[2],p[0]); t1->n=int3(3,2,0);
+ btHullTriangle *t2 = allocateTriangle(p[0],p[1],p[3]); t2->n=int3(0,1,3);
+ btHullTriangle *t3 = allocateTriangle(p[1],p[0],p[2]); t3->n=int3(1,0,2);
+ isextreme[p[0]]=isextreme[p[1]]=isextreme[p[2]]=isextreme[p[3]]=1;
+ checkit(t0);checkit(t1);checkit(t2);checkit(t3);
+
+ for(j=0;j<m_tris.size();j++)
+ {
+ btHullTriangle *t=m_tris[j];
+ btAssert(t);
+ btAssert(t->vmax<0);
+ btVector3 n=TriNormal(verts[(*t)[0]],verts[(*t)[1]],verts[(*t)[2]]);
+ t->vmax = maxdirsterid(verts,verts_count,n,allow);
+ t->rise = btDot(n,verts[t->vmax]-verts[(*t)[0]]);
+ }
+ btHullTriangle *te;
+ vlimit-=4;
+ while(vlimit >0 && ((te=extrudable(epsilon)) != 0))
+ {
+ //int3 ti=*te;
+ int v=te->vmax;
+ btAssert(v != -1);
+ btAssert(!isextreme[v]); // wtf we've already done this vertex
+ isextreme[v]=1;
+ //if(v==p0 || v==p1 || v==p2 || v==p3) continue; // done these already
+ j=m_tris.size();
+ while(j--) {
+ if(!m_tris[j]) continue;
+ int3 t=*m_tris[j];
+ if(above(verts,t,verts[v],btScalar(0.01)*epsilon))
+ {
+ extrude(m_tris[j],v);
+ }
+ }
+ // now check for those degenerate cases where we have a flipped triangle or a really skinny triangle
+ j=m_tris.size();
+ while(j--)
+ {
+ if(!m_tris[j]) continue;
+ if(!hasvert(*m_tris[j],v)) break;
+ int3 nt=*m_tris[j];
+ if(above(verts,nt,center,btScalar(0.01)*epsilon) || btCross(verts[nt[1]]-verts[nt[0]],verts[nt[2]]-verts[nt[1]]).length()< epsilon*epsilon*btScalar(0.1) )
+ {
+ btHullTriangle *nb = m_tris[m_tris[j]->n[0]];
+ btAssert(nb);btAssert(!hasvert(*nb,v));btAssert(nb->id<j);
+ extrude(nb,v);
+ j=m_tris.size();
+ }
+ }
+ j=m_tris.size();
+ while(j--)
+ {
+ btHullTriangle *t=m_tris[j];
+ if(!t) continue;
+ if(t->vmax>=0) break;
+ btVector3 n=TriNormal(verts[(*t)[0]],verts[(*t)[1]],verts[(*t)[2]]);
+ t->vmax = maxdirsterid(verts,verts_count,n,allow);
+ if(isextreme[t->vmax])
+ {
+ t->vmax=-1; // already done that vertex - algorithm needs to be able to terminate.
+ }
+ else
+ {
+ t->rise = btDot(n,verts[t->vmax]-verts[(*t)[0]]);
+ }
+ }
+ vlimit --;
+ }
+ return 1;
+}
+
+int HullLibrary::calchull(btVector3 *verts,int verts_count, TUIntArray& tris_out, int &tris_count,int vlimit)
+{
+ int rc=calchullgen(verts,verts_count, vlimit) ;
+ if(!rc) return 0;
+ btAlignedObjectArray<int> ts;
+ int i;
+
+ for(i=0;i<m_tris.size();i++)
+ {
+ if(m_tris[i])
+ {
+ for(int j=0;j<3;j++)
+ ts.push_back((*m_tris[i])[j]);
+ deAllocateTriangle(m_tris[i]);
+ }
+ }
+ tris_count = ts.size()/3;
+ tris_out.resize(ts.size());
+
+ for (i=0;i<ts.size();i++)
+ {
+ tris_out[i] = static_cast<unsigned int>(ts[i]);
+ }
+ m_tris.resize(0);
+
+ return 1;
+}
+
+
+
+
+
+bool HullLibrary::ComputeHull(unsigned int vcount,const btVector3 *vertices,PHullResult &result,unsigned int vlimit)
+{
+
+ int tris_count;
+ int ret = calchull( (btVector3 *) vertices, (int) vcount, result.m_Indices, tris_count, static_cast<int>(vlimit) );
+ if(!ret) return false;
+ result.mIndexCount = (unsigned int) (tris_count*3);
+ result.mFaceCount = (unsigned int) tris_count;
+ result.mVertices = (btVector3*) vertices;
+ result.mVcount = (unsigned int) vcount;
+ return true;
+
+}
+
+
+void ReleaseHull(PHullResult &result);
+void ReleaseHull(PHullResult &result)
+{
+ if ( result.m_Indices.size() )
+ {
+ result.m_Indices.clear();
+ }
+
+ result.mVcount = 0;
+ result.mIndexCount = 0;
+ result.mVertices = 0;
+}
+
+
+//*********************************************************************
+//*********************************************************************
+//******** HullLib header
+//*********************************************************************
+//*********************************************************************
+
+//*********************************************************************
+//*********************************************************************
+//******** HullLib implementation
+//*********************************************************************
+//*********************************************************************
+
+HullError HullLibrary::CreateConvexHull(const HullDesc &desc, // describes the input request
+ HullResult &result) // contains the resulst
+{
+ HullError ret = QE_FAIL;
+
+
+ PHullResult hr;
+
+ unsigned int vcount = desc.mVcount;
+ if ( vcount < 8 ) vcount = 8;
+
+ btAlignedObjectArray<btVector3> vertexSource;
+ vertexSource.resize(static_cast<int>(vcount));
+
+ btVector3 scale;
+
+ unsigned int ovcount;
+
+ bool ok = CleanupVertices(desc.mVcount,desc.mVertices, desc.mVertexStride, ovcount, &vertexSource[0], desc.mNormalEpsilon, scale ); // normalize point cloud, remove duplicates!
+
+ if ( ok )
+ {
+
+
+// if ( 1 ) // scale vertices back to their original size.
+ {
+ for (unsigned int i=0; i<ovcount; i++)
+ {
+ btVector3& v = vertexSource[static_cast<int>(i)];
+ v[0]*=scale[0];
+ v[1]*=scale[1];
+ v[2]*=scale[2];
+ }
+ }
+
+ ok = ComputeHull(ovcount,&vertexSource[0],hr,desc.mMaxVertices);
+
+ if ( ok )
+ {
+
+ // re-index triangle mesh so it refers to only used vertices, rebuild a new vertex table.
+ btAlignedObjectArray<btVector3> vertexScratch;
+ vertexScratch.resize(static_cast<int>(hr.mVcount));
+
+ BringOutYourDead(hr.mVertices,hr.mVcount, &vertexScratch[0], ovcount, &hr.m_Indices[0], hr.mIndexCount );
+
+ ret = QE_OK;
+
+ if ( desc.HasHullFlag(QF_TRIANGLES) ) // if he wants the results as triangle!
+ {
+ result.mPolygons = false;
+ result.mNumOutputVertices = ovcount;
+ result.m_OutputVertices.resize(static_cast<int>(ovcount));
+ result.mNumFaces = hr.mFaceCount;
+ result.mNumIndices = hr.mIndexCount;
+
+ result.m_Indices.resize(static_cast<int>(hr.mIndexCount));
+
+ memcpy(&result.m_OutputVertices[0], &vertexScratch[0], sizeof(btVector3)*ovcount );
+
+ if ( desc.HasHullFlag(QF_REVERSE_ORDER) )
+ {
+
+ const unsigned int *source = &hr.m_Indices[0];
+ unsigned int *dest = &result.m_Indices[0];
+
+ for (unsigned int i=0; i<hr.mFaceCount; i++)
+ {
+ dest[0] = source[2];
+ dest[1] = source[1];
+ dest[2] = source[0];
+ dest+=3;
+ source+=3;
+ }
+
+ }
+ else
+ {
+ memcpy(&result.m_Indices[0], &hr.m_Indices[0], sizeof(unsigned int)*hr.mIndexCount);
+ }
+ }
+ else
+ {
+ result.mPolygons = true;
+ result.mNumOutputVertices = ovcount;
+ result.m_OutputVertices.resize(static_cast<int>(ovcount));
+ result.mNumFaces = hr.mFaceCount;
+ result.mNumIndices = hr.mIndexCount+hr.mFaceCount;
+ result.m_Indices.resize(static_cast<int>(result.mNumIndices));
+ memcpy(&result.m_OutputVertices[0], &vertexScratch[0], sizeof(btVector3)*ovcount );
+
+// if ( 1 )
+ {
+ const unsigned int *source = &hr.m_Indices[0];
+ unsigned int *dest = &result.m_Indices[0];
+ for (unsigned int i=0; i<hr.mFaceCount; i++)
+ {
+ dest[0] = 3;
+ if ( desc.HasHullFlag(QF_REVERSE_ORDER) )
+ {
+ dest[1] = source[2];
+ dest[2] = source[1];
+ dest[3] = source[0];
+ }
+ else
+ {
+ dest[1] = source[0];
+ dest[2] = source[1];
+ dest[3] = source[2];
+ }
+
+ dest+=4;
+ source+=3;
+ }
+ }
+ }
+ ReleaseHull(hr);
+ }
+ }
+
+ return ret;
+}
+
+
+
+HullError HullLibrary::ReleaseResult(HullResult &result) // release memory allocated for this result, we are done with it.
+{
+ if ( result.m_OutputVertices.size())
+ {
+ result.mNumOutputVertices=0;
+ result.m_OutputVertices.clear();
+ }
+ if ( result.m_Indices.size() )
+ {
+ result.mNumIndices=0;
+ result.m_Indices.clear();
+ }
+ return QE_OK;
+}
+
+
+static void addPoint(unsigned int &vcount,btVector3 *p,btScalar x,btScalar y,btScalar z)
+{
+ // XXX, might be broken
+ btVector3& dest = p[vcount];
+ dest[0] = x;
+ dest[1] = y;
+ dest[2] = z;
+ vcount++;
+}
+
+btScalar GetDist(btScalar px,btScalar py,btScalar pz,const btScalar *p2);
+btScalar GetDist(btScalar px,btScalar py,btScalar pz,const btScalar *p2)
+{
+
+ btScalar dx = px - p2[0];
+ btScalar dy = py - p2[1];
+ btScalar dz = pz - p2[2];
+
+ return dx*dx+dy*dy+dz*dz;
+}
+
+
+
+bool HullLibrary::CleanupVertices(unsigned int svcount,
+ const btVector3 *svertices,
+ unsigned int stride,
+ unsigned int &vcount, // output number of vertices
+ btVector3 *vertices, // location to store the results.
+ btScalar normalepsilon,
+ btVector3& scale)
+{
+ if ( svcount == 0 ) return false;
+
+ m_vertexIndexMapping.resize(0);
+
+
+#define EPSILON btScalar(0.000001) /* close enough to consider two btScalaring point numbers to be 'the same'. */
+
+ vcount = 0;
+
+ btScalar recip[3]={0.f,0.f,0.f};
+
+ if ( scale )
+ {
+ scale[0] = 1;
+ scale[1] = 1;
+ scale[2] = 1;
+ }
+
+ btScalar bmin[3] = { FLT_MAX, FLT_MAX, FLT_MAX };
+ btScalar bmax[3] = { -FLT_MAX, -FLT_MAX, -FLT_MAX };
+
+ const char *vtx = (const char *) svertices;
+
+// if ( 1 )
+ {
+ for (unsigned int i=0; i<svcount; i++)
+ {
+ const btScalar *p = (const btScalar *) vtx;
+
+ vtx+=stride;
+
+ for (int j=0; j<3; j++)
+ {
+ if ( p[j] < bmin[j] ) bmin[j] = p[j];
+ if ( p[j] > bmax[j] ) bmax[j] = p[j];
+ }
+ }
+ }
+
+ btScalar dx = bmax[0] - bmin[0];
+ btScalar dy = bmax[1] - bmin[1];
+ btScalar dz = bmax[2] - bmin[2];
+
+ btVector3 center;
+
+ center[0] = dx*btScalar(0.5) + bmin[0];
+ center[1] = dy*btScalar(0.5) + bmin[1];
+ center[2] = dz*btScalar(0.5) + bmin[2];
+
+ if ( dx < EPSILON || dy < EPSILON || dz < EPSILON || svcount < 3 )
+ {
+
+ btScalar len = FLT_MAX;
+
+ if ( dx > EPSILON && dx < len ) len = dx;
+ if ( dy > EPSILON && dy < len ) len = dy;
+ if ( dz > EPSILON && dz < len ) len = dz;
+
+ if ( len == FLT_MAX )
+ {
+ dx = dy = dz = btScalar(0.01); // one centimeter
+ }
+ else
+ {
+ if ( dx < EPSILON ) dx = len * btScalar(0.05); // 1/5th the shortest non-zero edge.
+ if ( dy < EPSILON ) dy = len * btScalar(0.05);
+ if ( dz < EPSILON ) dz = len * btScalar(0.05);
+ }
+
+ btScalar x1 = center[0] - dx;
+ btScalar x2 = center[0] + dx;
+
+ btScalar y1 = center[1] - dy;
+ btScalar y2 = center[1] + dy;
+
+ btScalar z1 = center[2] - dz;
+ btScalar z2 = center[2] + dz;
+
+ addPoint(vcount,vertices,x1,y1,z1);
+ addPoint(vcount,vertices,x2,y1,z1);
+ addPoint(vcount,vertices,x2,y2,z1);
+ addPoint(vcount,vertices,x1,y2,z1);
+ addPoint(vcount,vertices,x1,y1,z2);
+ addPoint(vcount,vertices,x2,y1,z2);
+ addPoint(vcount,vertices,x2,y2,z2);
+ addPoint(vcount,vertices,x1,y2,z2);
+
+ return true; // return cube
+
+
+ }
+ else
+ {
+ if ( scale )
+ {
+ scale[0] = dx;
+ scale[1] = dy;
+ scale[2] = dz;
+
+ recip[0] = 1 / dx;
+ recip[1] = 1 / dy;
+ recip[2] = 1 / dz;
+
+ center[0]*=recip[0];
+ center[1]*=recip[1];
+ center[2]*=recip[2];
+
+ }
+
+ }
+
+
+
+ vtx = (const char *) svertices;
+
+ for (unsigned int i=0; i<svcount; i++)
+ {
+ const btVector3 *p = (const btVector3 *)vtx;
+ vtx+=stride;
+
+ btScalar px = p->getX();
+ btScalar py = p->getY();
+ btScalar pz = p->getZ();
+
+ if ( scale )
+ {
+ px = px*recip[0]; // normalize
+ py = py*recip[1]; // normalize
+ pz = pz*recip[2]; // normalize
+ }
+
+// if ( 1 )
+ {
+ unsigned int j;
+
+ for (j=0; j<vcount; j++)
+ {
+ /// XXX might be broken
+ btVector3& v = vertices[j];
+
+ btScalar x = v[0];
+ btScalar y = v[1];
+ btScalar z = v[2];
+
+ btScalar dx = btFabs(x - px );
+ btScalar dy = btFabs(y - py );
+ btScalar dz = btFabs(z - pz );
+
+ if ( dx < normalepsilon && dy < normalepsilon && dz < normalepsilon )
+ {
+ // ok, it is close enough to the old one
+ // now let us see if it is further from the center of the point cloud than the one we already recorded.
+ // in which case we keep this one instead.
+
+ btScalar dist1 = GetDist(px,py,pz,center);
+ btScalar dist2 = GetDist(v[0],v[1],v[2],center);
+
+ if ( dist1 > dist2 )
+ {
+ v[0] = px;
+ v[1] = py;
+ v[2] = pz;
+
+ }
+
+ break;
+ }
+ }
+
+ if ( j == vcount )
+ {
+ btVector3& dest = vertices[vcount];
+ dest[0] = px;
+ dest[1] = py;
+ dest[2] = pz;
+ vcount++;
+ }
+ m_vertexIndexMapping.push_back(j);
+ }
+ }
+
+ // ok..now make sure we didn't prune so many vertices it is now invalid.
+// if ( 1 )
+ {
+ btScalar bmin[3] = { FLT_MAX, FLT_MAX, FLT_MAX };
+ btScalar bmax[3] = { -FLT_MAX, -FLT_MAX, -FLT_MAX };
+
+ for (unsigned int i=0; i<vcount; i++)
+ {
+ const btVector3& p = vertices[i];
+ for (int j=0; j<3; j++)
+ {
+ if ( p[j] < bmin[j] ) bmin[j] = p[j];
+ if ( p[j] > bmax[j] ) bmax[j] = p[j];
+ }
+ }
+
+ btScalar dx = bmax[0] - bmin[0];
+ btScalar dy = bmax[1] - bmin[1];
+ btScalar dz = bmax[2] - bmin[2];
+
+ if ( dx < EPSILON || dy < EPSILON || dz < EPSILON || vcount < 3)
+ {
+ btScalar cx = dx*btScalar(0.5) + bmin[0];
+ btScalar cy = dy*btScalar(0.5) + bmin[1];
+ btScalar cz = dz*btScalar(0.5) + bmin[2];
+
+ btScalar len = FLT_MAX;
+
+ if ( dx >= EPSILON && dx < len ) len = dx;
+ if ( dy >= EPSILON && dy < len ) len = dy;
+ if ( dz >= EPSILON && dz < len ) len = dz;
+
+ if ( len == FLT_MAX )
+ {
+ dx = dy = dz = btScalar(0.01); // one centimeter
+ }
+ else
+ {
+ if ( dx < EPSILON ) dx = len * btScalar(0.05); // 1/5th the shortest non-zero edge.
+ if ( dy < EPSILON ) dy = len * btScalar(0.05);
+ if ( dz < EPSILON ) dz = len * btScalar(0.05);
+ }
+
+ btScalar x1 = cx - dx;
+ btScalar x2 = cx + dx;
+
+ btScalar y1 = cy - dy;
+ btScalar y2 = cy + dy;
+
+ btScalar z1 = cz - dz;
+ btScalar z2 = cz + dz;
+
+ vcount = 0; // add box
+
+ addPoint(vcount,vertices,x1,y1,z1);
+ addPoint(vcount,vertices,x2,y1,z1);
+ addPoint(vcount,vertices,x2,y2,z1);
+ addPoint(vcount,vertices,x1,y2,z1);
+ addPoint(vcount,vertices,x1,y1,z2);
+ addPoint(vcount,vertices,x2,y1,z2);
+ addPoint(vcount,vertices,x2,y2,z2);
+ addPoint(vcount,vertices,x1,y2,z2);
+
+ return true;
+ }
+ }
+
+ return true;
+}
+
+void HullLibrary::BringOutYourDead(const btVector3* verts,unsigned int vcount, btVector3* overts,unsigned int &ocount,unsigned int *indices,unsigned indexcount)
+{
+ btAlignedObjectArray<int>tmpIndices;
+ tmpIndices.resize(m_vertexIndexMapping.size());
+ int i;
+
+ for (i=0;i<m_vertexIndexMapping.size();i++)
+ {
+ tmpIndices[i] = m_vertexIndexMapping[i];
+ }
+
+ TUIntArray usedIndices;
+ usedIndices.resize(static_cast<int>(vcount));
+ memset(&usedIndices[0],0,sizeof(unsigned int)*vcount);
+
+ ocount = 0;
+
+ for (i=0; i<int (indexcount); i++)
+ {
+ unsigned int v = indices[i]; // original array index
+
+ btAssert( v >= 0 && v < vcount );
+
+ if ( usedIndices[static_cast<int>(v)] ) // if already remapped
+ {
+ indices[i] = usedIndices[static_cast<int>(v)]-1; // index to new array
+ }
+ else
+ {
+
+ indices[i] = ocount; // new index mapping
+
+ overts[ocount][0] = verts[v][0]; // copy old vert to new vert array
+ overts[ocount][1] = verts[v][1];
+ overts[ocount][2] = verts[v][2];
+
+ for (int k=0;k<m_vertexIndexMapping.size();k++)
+ {
+ if (tmpIndices[k]==int(v))
+ m_vertexIndexMapping[k]=ocount;
+ }
+
+ ocount++; // increment output vert count
+
+ btAssert( ocount >=0 && ocount <= vcount );
+
+ usedIndices[static_cast<int>(v)] = ocount; // assign new index remapping
+
+
+ }
+ }
+
+
+}
diff --git a/thirdparty/bullet/src/LinearMath/btConvexHull.h b/thirdparty/bullet/src/LinearMath/btConvexHull.h
new file mode 100644
index 0000000000..69c52bc6f8
--- /dev/null
+++ b/thirdparty/bullet/src/LinearMath/btConvexHull.h
@@ -0,0 +1,241 @@
+
+/*
+Stan Melax Convex Hull Computation
+Copyright (c) 2008 Stan Melax http://www.melax.com/
+
+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.
+*/
+
+///includes modifications/improvements by John Ratcliff, see BringOutYourDead below.
+
+#ifndef BT_CD_HULL_H
+#define BT_CD_HULL_H
+
+#include "btVector3.h"
+#include "btAlignedObjectArray.h"
+
+typedef btAlignedObjectArray<unsigned int> TUIntArray;
+
+class HullResult
+{
+public:
+ HullResult(void)
+ {
+ mPolygons = true;
+ mNumOutputVertices = 0;
+ mNumFaces = 0;
+ mNumIndices = 0;
+ }
+ bool mPolygons; // true if indices represents polygons, false indices are triangles
+ unsigned int mNumOutputVertices; // number of vertices in the output hull
+ btAlignedObjectArray<btVector3> m_OutputVertices; // array of vertices
+ unsigned int mNumFaces; // the number of faces produced
+ unsigned int mNumIndices; // the total number of indices
+ btAlignedObjectArray<unsigned int> m_Indices; // pointer to indices.
+
+// If triangles, then indices are array indexes into the vertex list.
+// If polygons, indices are in the form (number of points in face) (p1, p2, p3, ..) etc..
+};
+
+enum HullFlag
+{
+ QF_TRIANGLES = (1<<0), // report results as triangles, not polygons.
+ QF_REVERSE_ORDER = (1<<1), // reverse order of the triangle indices.
+ QF_DEFAULT = QF_TRIANGLES
+};
+
+
+class HullDesc
+{
+public:
+ HullDesc(void)
+ {
+ mFlags = QF_DEFAULT;
+ mVcount = 0;
+ mVertices = 0;
+ mVertexStride = sizeof(btVector3);
+ mNormalEpsilon = 0.001f;
+ mMaxVertices = 4096; // maximum number of points to be considered for a convex hull.
+ mMaxFaces = 4096;
+ };
+
+ HullDesc(HullFlag flag,
+ unsigned int vcount,
+ const btVector3 *vertices,
+ unsigned int stride = sizeof(btVector3))
+ {
+ mFlags = flag;
+ mVcount = vcount;
+ mVertices = vertices;
+ mVertexStride = stride;
+ mNormalEpsilon = btScalar(0.001);
+ mMaxVertices = 4096;
+ }
+
+ bool HasHullFlag(HullFlag flag) const
+ {
+ if ( mFlags & flag ) return true;
+ return false;
+ }
+
+ void SetHullFlag(HullFlag flag)
+ {
+ mFlags|=flag;
+ }
+
+ void ClearHullFlag(HullFlag flag)
+ {
+ mFlags&=~flag;
+ }
+
+ unsigned int mFlags; // flags to use when generating the convex hull.
+ unsigned int mVcount; // number of vertices in the input point cloud
+ const btVector3 *mVertices; // the array of vertices.
+ unsigned int mVertexStride; // the stride of each vertex, in bytes.
+ btScalar mNormalEpsilon; // the epsilon for removing duplicates. This is a normalized value, if normalized bit is on.
+ unsigned int mMaxVertices; // maximum number of vertices to be considered for the hull!
+ unsigned int mMaxFaces;
+};
+
+enum HullError
+{
+ QE_OK, // success!
+ QE_FAIL // failed.
+};
+
+class btPlane
+{
+ public:
+ btVector3 normal;
+ btScalar dist; // distance below origin - the D from plane equasion Ax+By+Cz+D=0
+ btPlane(const btVector3 &n,btScalar d):normal(n),dist(d){}
+ btPlane():normal(),dist(0){}
+
+};
+
+
+
+class ConvexH
+{
+ public:
+ class HalfEdge
+ {
+ public:
+ short ea; // the other half of the edge (index into edges list)
+ unsigned char v; // the vertex at the start of this edge (index into vertices list)
+ unsigned char p; // the facet on which this edge lies (index into facets list)
+ HalfEdge(){}
+ HalfEdge(short _ea,unsigned char _v, unsigned char _p):ea(_ea),v(_v),p(_p){}
+ };
+ ConvexH()
+ {
+ }
+ ~ConvexH()
+ {
+ }
+ btAlignedObjectArray<btVector3> vertices;
+ btAlignedObjectArray<HalfEdge> edges;
+ btAlignedObjectArray<btPlane> facets;
+ ConvexH(int vertices_size,int edges_size,int facets_size);
+};
+
+
+class int4
+{
+public:
+ int x,y,z,w;
+ int4(){};
+ int4(int _x,int _y, int _z,int _w){x=_x;y=_y;z=_z;w=_w;}
+ const int& operator[](int i) const {return (&x)[i];}
+ int& operator[](int i) {return (&x)[i];}
+};
+
+class PHullResult
+{
+public:
+
+ PHullResult(void)
+ {
+ mVcount = 0;
+ mIndexCount = 0;
+ mFaceCount = 0;
+ mVertices = 0;
+ }
+
+ unsigned int mVcount;
+ unsigned int mIndexCount;
+ unsigned int mFaceCount;
+ btVector3* mVertices;
+ TUIntArray m_Indices;
+};
+
+
+
+///The HullLibrary class can create a convex hull from a collection of vertices, using the ComputeHull method.
+///The btShapeHull class uses this HullLibrary to create a approximate convex mesh given a general (non-polyhedral) convex shape.
+class HullLibrary
+{
+
+ btAlignedObjectArray<class btHullTriangle*> m_tris;
+
+public:
+
+ btAlignedObjectArray<int> m_vertexIndexMapping;
+
+
+ HullError CreateConvexHull(const HullDesc& desc, // describes the input request
+ HullResult& result); // contains the resulst
+ HullError ReleaseResult(HullResult &result); // release memory allocated for this result, we are done with it.
+
+private:
+
+ bool ComputeHull(unsigned int vcount,const btVector3 *vertices,PHullResult &result,unsigned int vlimit);
+
+ class btHullTriangle* allocateTriangle(int a,int b,int c);
+ void deAllocateTriangle(btHullTriangle*);
+ void b2bfix(btHullTriangle* s,btHullTriangle*t);
+
+ void removeb2b(btHullTriangle* s,btHullTriangle*t);
+
+ void checkit(btHullTriangle *t);
+
+ btHullTriangle* extrudable(btScalar epsilon);
+
+ int calchull(btVector3 *verts,int verts_count, TUIntArray& tris_out, int &tris_count,int vlimit);
+
+ int calchullgen(btVector3 *verts,int verts_count, int vlimit);
+
+ int4 FindSimplex(btVector3 *verts,int verts_count,btAlignedObjectArray<int> &allow);
+
+ class ConvexH* ConvexHCrop(ConvexH& convex,const btPlane& slice);
+
+ void extrude(class btHullTriangle* t0,int v);
+
+ ConvexH* test_cube();
+
+ //BringOutYourDead (John Ratcliff): When you create a convex hull you hand it a large input set of vertices forming a 'point cloud'.
+ //After the hull is generated it give you back a set of polygon faces which index the *original* point cloud.
+ //The thing is, often times, there are many 'dead vertices' in the point cloud that are on longer referenced by the hull.
+ //The routine 'BringOutYourDead' find only the referenced vertices, copies them to an new buffer, and re-indexes the hull so that it is a minimal representation.
+ void BringOutYourDead(const btVector3* verts,unsigned int vcount, btVector3* overts,unsigned int &ocount,unsigned int* indices,unsigned indexcount);
+
+ bool CleanupVertices(unsigned int svcount,
+ const btVector3* svertices,
+ unsigned int stride,
+ unsigned int &vcount, // output number of vertices
+ btVector3* vertices, // location to store the results.
+ btScalar normalepsilon,
+ btVector3& scale);
+};
+
+
+#endif //BT_CD_HULL_H
+
diff --git a/thirdparty/bullet/src/LinearMath/btConvexHullComputer.cpp b/thirdparty/bullet/src/LinearMath/btConvexHullComputer.cpp
new file mode 100644
index 0000000000..2ea22cbe3b
--- /dev/null
+++ b/thirdparty/bullet/src/LinearMath/btConvexHullComputer.cpp
@@ -0,0 +1,2768 @@
+/*
+Copyright (c) 2011 Ole Kniemeyer, MAXON, www.maxon.net
+
+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 <string.h>
+
+#include "btConvexHullComputer.h"
+#include "btAlignedObjectArray.h"
+#include "btMinMax.h"
+#include "btVector3.h"
+
+#ifdef __GNUC__
+ #include <stdint.h>
+#elif defined(_MSC_VER)
+ typedef __int32 int32_t;
+ typedef __int64 int64_t;
+ typedef unsigned __int32 uint32_t;
+ typedef unsigned __int64 uint64_t;
+#else
+ typedef int int32_t;
+ typedef long long int int64_t;
+ typedef unsigned int uint32_t;
+ typedef unsigned long long int uint64_t;
+#endif
+
+
+//The definition of USE_X86_64_ASM is moved into the build system. You can enable it manually by commenting out the following lines
+//#if (defined(__GNUC__) && defined(__x86_64__) && !defined(__ICL)) // || (defined(__ICL) && defined(_M_X64)) bug in Intel compiler, disable inline assembly
+// #define USE_X86_64_ASM
+//#endif
+
+
+//#define DEBUG_CONVEX_HULL
+//#define SHOW_ITERATIONS
+
+#if defined(DEBUG_CONVEX_HULL) || defined(SHOW_ITERATIONS)
+ #include <stdio.h>
+#endif
+
+// Convex hull implementation based on Preparata and Hong
+// Ole Kniemeyer, MAXON Computer GmbH
+class btConvexHullInternal
+{
+ public:
+
+ class Point64
+ {
+ public:
+ int64_t x;
+ int64_t y;
+ int64_t z;
+
+ Point64(int64_t x, int64_t y, int64_t z): x(x), y(y), z(z)
+ {
+ }
+
+ bool isZero()
+ {
+ return (x == 0) && (y == 0) && (z == 0);
+ }
+
+ int64_t dot(const Point64& b) const
+ {
+ return x * b.x + y * b.y + z * b.z;
+ }
+ };
+
+ class Point32
+ {
+ public:
+ int32_t x;
+ int32_t y;
+ int32_t z;
+ int index;
+
+ Point32()
+ {
+ }
+
+ Point32(int32_t x, int32_t y, int32_t z): x(x), y(y), z(z), index(-1)
+ {
+ }
+
+ bool operator==(const Point32& b) const
+ {
+ return (x == b.x) && (y == b.y) && (z == b.z);
+ }
+
+ bool operator!=(const Point32& b) const
+ {
+ return (x != b.x) || (y != b.y) || (z != b.z);
+ }
+
+ bool isZero()
+ {
+ return (x == 0) && (y == 0) && (z == 0);
+ }
+
+ Point64 cross(const Point32& b) const
+ {
+ return Point64(y * b.z - z * b.y, z * b.x - x * b.z, x * b.y - y * b.x);
+ }
+
+ Point64 cross(const Point64& b) const
+ {
+ return Point64(y * b.z - z * b.y, z * b.x - x * b.z, x * b.y - y * b.x);
+ }
+
+ int64_t dot(const Point32& b) const
+ {
+ return x * b.x + y * b.y + z * b.z;
+ }
+
+ int64_t dot(const Point64& b) const
+ {
+ return x * b.x + y * b.y + z * b.z;
+ }
+
+ Point32 operator+(const Point32& b) const
+ {
+ return Point32(x + b.x, y + b.y, z + b.z);
+ }
+
+ Point32 operator-(const Point32& b) const
+ {
+ return Point32(x - b.x, y - b.y, z - b.z);
+ }
+ };
+
+ class Int128
+ {
+ public:
+ uint64_t low;
+ uint64_t high;
+
+ Int128()
+ {
+ }
+
+ Int128(uint64_t low, uint64_t high): low(low), high(high)
+ {
+ }
+
+ Int128(uint64_t low): low(low), high(0)
+ {
+ }
+
+ Int128(int64_t value): low(value), high((value >= 0) ? 0 : (uint64_t) -1LL)
+ {
+ }
+
+ static Int128 mul(int64_t a, int64_t b);
+
+ static Int128 mul(uint64_t a, uint64_t b);
+
+ Int128 operator-() const
+ {
+ return Int128((uint64_t) -(int64_t)low, ~high + (low == 0));
+ }
+
+ Int128 operator+(const Int128& b) const
+ {
+#ifdef USE_X86_64_ASM
+ Int128 result;
+ __asm__ ("addq %[bl], %[rl]\n\t"
+ "adcq %[bh], %[rh]\n\t"
+ : [rl] "=r" (result.low), [rh] "=r" (result.high)
+ : "0"(low), "1"(high), [bl] "g"(b.low), [bh] "g"(b.high)
+ : "cc" );
+ return result;
+#else
+ uint64_t lo = low + b.low;
+ return Int128(lo, high + b.high + (lo < low));
+#endif
+ }
+
+ Int128 operator-(const Int128& b) const
+ {
+#ifdef USE_X86_64_ASM
+ Int128 result;
+ __asm__ ("subq %[bl], %[rl]\n\t"
+ "sbbq %[bh], %[rh]\n\t"
+ : [rl] "=r" (result.low), [rh] "=r" (result.high)
+ : "0"(low), "1"(high), [bl] "g"(b.low), [bh] "g"(b.high)
+ : "cc" );
+ return result;
+#else
+ return *this + -b;
+#endif
+ }
+
+ Int128& operator+=(const Int128& b)
+ {
+#ifdef USE_X86_64_ASM
+ __asm__ ("addq %[bl], %[rl]\n\t"
+ "adcq %[bh], %[rh]\n\t"
+ : [rl] "=r" (low), [rh] "=r" (high)
+ : "0"(low), "1"(high), [bl] "g"(b.low), [bh] "g"(b.high)
+ : "cc" );
+#else
+ uint64_t lo = low + b.low;
+ if (lo < low)
+ {
+ ++high;
+ }
+ low = lo;
+ high += b.high;
+#endif
+ return *this;
+ }
+
+ Int128& operator++()
+ {
+ if (++low == 0)
+ {
+ ++high;
+ }
+ return *this;
+ }
+
+ Int128 operator*(int64_t b) const;
+
+ btScalar toScalar() const
+ {
+ return ((int64_t) high >= 0) ? btScalar(high) * (btScalar(0x100000000LL) * btScalar(0x100000000LL)) + btScalar(low)
+ : -(-*this).toScalar();
+ }
+
+ int getSign() const
+ {
+ return ((int64_t) high < 0) ? -1 : (high || low) ? 1 : 0;
+ }
+
+ bool operator<(const Int128& b) const
+ {
+ return (high < b.high) || ((high == b.high) && (low < b.low));
+ }
+
+ int ucmp(const Int128&b) const
+ {
+ if (high < b.high)
+ {
+ return -1;
+ }
+ if (high > b.high)
+ {
+ return 1;
+ }
+ if (low < b.low)
+ {
+ return -1;
+ }
+ if (low > b.low)
+ {
+ return 1;
+ }
+ return 0;
+ }
+ };
+
+
+ class Rational64
+ {
+ private:
+ uint64_t m_numerator;
+ uint64_t m_denominator;
+ int sign;
+
+ public:
+ Rational64(int64_t numerator, int64_t denominator)
+ {
+ if (numerator > 0)
+ {
+ sign = 1;
+ m_numerator = (uint64_t) numerator;
+ }
+ else if (numerator < 0)
+ {
+ sign = -1;
+ m_numerator = (uint64_t) -numerator;
+ }
+ else
+ {
+ sign = 0;
+ m_numerator = 0;
+ }
+ if (denominator > 0)
+ {
+ m_denominator = (uint64_t) denominator;
+ }
+ else if (denominator < 0)
+ {
+ sign = -sign;
+ m_denominator = (uint64_t) -denominator;
+ }
+ else
+ {
+ m_denominator = 0;
+ }
+ }
+
+ bool isNegativeInfinity() const
+ {
+ return (sign < 0) && (m_denominator == 0);
+ }
+
+ bool isNaN() const
+ {
+ return (sign == 0) && (m_denominator == 0);
+ }
+
+ int compare(const Rational64& b) const;
+
+ btScalar toScalar() const
+ {
+ return sign * ((m_denominator == 0) ? SIMD_INFINITY : (btScalar) m_numerator / m_denominator);
+ }
+ };
+
+
+ class Rational128
+ {
+ private:
+ Int128 numerator;
+ Int128 denominator;
+ int sign;
+ bool isInt64;
+
+ public:
+ Rational128(int64_t value)
+ {
+ if (value > 0)
+ {
+ sign = 1;
+ this->numerator = value;
+ }
+ else if (value < 0)
+ {
+ sign = -1;
+ this->numerator = -value;
+ }
+ else
+ {
+ sign = 0;
+ this->numerator = (uint64_t) 0;
+ }
+ this->denominator = (uint64_t) 1;
+ isInt64 = true;
+ }
+
+ Rational128(const Int128& numerator, const Int128& denominator)
+ {
+ sign = numerator.getSign();
+ if (sign >= 0)
+ {
+ this->numerator = numerator;
+ }
+ else
+ {
+ this->numerator = -numerator;
+ }
+ int dsign = denominator.getSign();
+ if (dsign >= 0)
+ {
+ this->denominator = denominator;
+ }
+ else
+ {
+ sign = -sign;
+ this->denominator = -denominator;
+ }
+ isInt64 = false;
+ }
+
+ int compare(const Rational128& b) const;
+
+ int compare(int64_t b) const;
+
+ btScalar toScalar() const
+ {
+ return sign * ((denominator.getSign() == 0) ? SIMD_INFINITY : numerator.toScalar() / denominator.toScalar());
+ }
+ };
+
+ class PointR128
+ {
+ public:
+ Int128 x;
+ Int128 y;
+ Int128 z;
+ Int128 denominator;
+
+ PointR128()
+ {
+ }
+
+ PointR128(Int128 x, Int128 y, Int128 z, Int128 denominator): x(x), y(y), z(z), denominator(denominator)
+ {
+ }
+
+ btScalar xvalue() const
+ {
+ return x.toScalar() / denominator.toScalar();
+ }
+
+ btScalar yvalue() const
+ {
+ return y.toScalar() / denominator.toScalar();
+ }
+
+ btScalar zvalue() const
+ {
+ return z.toScalar() / denominator.toScalar();
+ }
+ };
+
+
+ class Edge;
+ class Face;
+
+ class Vertex
+ {
+ public:
+ Vertex* next;
+ Vertex* prev;
+ Edge* edges;
+ Face* firstNearbyFace;
+ Face* lastNearbyFace;
+ PointR128 point128;
+ Point32 point;
+ int copy;
+
+ Vertex(): next(NULL), prev(NULL), edges(NULL), firstNearbyFace(NULL), lastNearbyFace(NULL), copy(-1)
+ {
+ }
+
+#ifdef DEBUG_CONVEX_HULL
+ void print()
+ {
+ printf("V%d (%d, %d, %d)", point.index, point.x, point.y, point.z);
+ }
+
+ void printGraph();
+#endif
+
+ Point32 operator-(const Vertex& b) const
+ {
+ return point - b.point;
+ }
+
+ Rational128 dot(const Point64& b) const
+ {
+ return (point.index >= 0) ? Rational128(point.dot(b))
+ : Rational128(point128.x * b.x + point128.y * b.y + point128.z * b.z, point128.denominator);
+ }
+
+ btScalar xvalue() const
+ {
+ return (point.index >= 0) ? btScalar(point.x) : point128.xvalue();
+ }
+
+ btScalar yvalue() const
+ {
+ return (point.index >= 0) ? btScalar(point.y) : point128.yvalue();
+ }
+
+ btScalar zvalue() const
+ {
+ return (point.index >= 0) ? btScalar(point.z) : point128.zvalue();
+ }
+
+ void receiveNearbyFaces(Vertex* src)
+ {
+ if (lastNearbyFace)
+ {
+ lastNearbyFace->nextWithSameNearbyVertex = src->firstNearbyFace;
+ }
+ else
+ {
+ firstNearbyFace = src->firstNearbyFace;
+ }
+ if (src->lastNearbyFace)
+ {
+ lastNearbyFace = src->lastNearbyFace;
+ }
+ for (Face* f = src->firstNearbyFace; f; f = f->nextWithSameNearbyVertex)
+ {
+ btAssert(f->nearbyVertex == src);
+ f->nearbyVertex = this;
+ }
+ src->firstNearbyFace = NULL;
+ src->lastNearbyFace = NULL;
+ }
+ };
+
+
+ class Edge
+ {
+ public:
+ Edge* next;
+ Edge* prev;
+ Edge* reverse;
+ Vertex* target;
+ Face* face;
+ int copy;
+
+ ~Edge()
+ {
+ next = NULL;
+ prev = NULL;
+ reverse = NULL;
+ target = NULL;
+ face = NULL;
+ }
+
+ void link(Edge* n)
+ {
+ btAssert(reverse->target == n->reverse->target);
+ next = n;
+ n->prev = this;
+ }
+
+#ifdef DEBUG_CONVEX_HULL
+ void print()
+ {
+ printf("E%p : %d -> %d, n=%p p=%p (0 %d\t%d\t%d) -> (%d %d %d)", this, reverse->target->point.index, target->point.index, next, prev,
+ reverse->target->point.x, reverse->target->point.y, reverse->target->point.z, target->point.x, target->point.y, target->point.z);
+ }
+#endif
+ };
+
+ class Face
+ {
+ public:
+ Face* next;
+ Vertex* nearbyVertex;
+ Face* nextWithSameNearbyVertex;
+ Point32 origin;
+ Point32 dir0;
+ Point32 dir1;
+
+ Face(): next(NULL), nearbyVertex(NULL), nextWithSameNearbyVertex(NULL)
+ {
+ }
+
+ void init(Vertex* a, Vertex* b, Vertex* c)
+ {
+ nearbyVertex = a;
+ origin = a->point;
+ dir0 = *b - *a;
+ dir1 = *c - *a;
+ if (a->lastNearbyFace)
+ {
+ a->lastNearbyFace->nextWithSameNearbyVertex = this;
+ }
+ else
+ {
+ a->firstNearbyFace = this;
+ }
+ a->lastNearbyFace = this;
+ }
+
+ Point64 getNormal()
+ {
+ return dir0.cross(dir1);
+ }
+ };
+
+ template<typename UWord, typename UHWord> class DMul
+ {
+ private:
+ static uint32_t high(uint64_t value)
+ {
+ return (uint32_t) (value >> 32);
+ }
+
+ static uint32_t low(uint64_t value)
+ {
+ return (uint32_t) value;
+ }
+
+ static uint64_t mul(uint32_t a, uint32_t b)
+ {
+ return (uint64_t) a * (uint64_t) b;
+ }
+
+ static void shlHalf(uint64_t& value)
+ {
+ value <<= 32;
+ }
+
+ static uint64_t high(Int128 value)
+ {
+ return value.high;
+ }
+
+ static uint64_t low(Int128 value)
+ {
+ return value.low;
+ }
+
+ static Int128 mul(uint64_t a, uint64_t b)
+ {
+ return Int128::mul(a, b);
+ }
+
+ static void shlHalf(Int128& value)
+ {
+ value.high = value.low;
+ value.low = 0;
+ }
+
+ public:
+
+ static void mul(UWord a, UWord b, UWord& resLow, UWord& resHigh)
+ {
+ UWord p00 = mul(low(a), low(b));
+ UWord p01 = mul(low(a), high(b));
+ UWord p10 = mul(high(a), low(b));
+ UWord p11 = mul(high(a), high(b));
+ UWord p0110 = UWord(low(p01)) + UWord(low(p10));
+ p11 += high(p01);
+ p11 += high(p10);
+ p11 += high(p0110);
+ shlHalf(p0110);
+ p00 += p0110;
+ if (p00 < p0110)
+ {
+ ++p11;
+ }
+ resLow = p00;
+ resHigh = p11;
+ }
+ };
+
+ private:
+
+ class IntermediateHull
+ {
+ public:
+ Vertex* minXy;
+ Vertex* maxXy;
+ Vertex* minYx;
+ Vertex* maxYx;
+
+ IntermediateHull(): minXy(NULL), maxXy(NULL), minYx(NULL), maxYx(NULL)
+ {
+ }
+
+ void print();
+ };
+
+ enum Orientation {NONE, CLOCKWISE, COUNTER_CLOCKWISE};
+
+ template <typename T> class PoolArray
+ {
+ private:
+ T* array;
+ int size;
+
+ public:
+ PoolArray<T>* next;
+
+ PoolArray(int size): size(size), next(NULL)
+ {
+ array = (T*) btAlignedAlloc(sizeof(T) * size, 16);
+ }
+
+ ~PoolArray()
+ {
+ btAlignedFree(array);
+ }
+
+ T* init()
+ {
+ T* o = array;
+ for (int i = 0; i < size; i++, o++)
+ {
+ o->next = (i+1 < size) ? o + 1 : NULL;
+ }
+ return array;
+ }
+ };
+
+ template <typename T> class Pool
+ {
+ private:
+ PoolArray<T>* arrays;
+ PoolArray<T>* nextArray;
+ T* freeObjects;
+ int arraySize;
+
+ public:
+ Pool(): arrays(NULL), nextArray(NULL), freeObjects(NULL), arraySize(256)
+ {
+ }
+
+ ~Pool()
+ {
+ while (arrays)
+ {
+ PoolArray<T>* p = arrays;
+ arrays = p->next;
+ p->~PoolArray<T>();
+ btAlignedFree(p);
+ }
+ }
+
+ void reset()
+ {
+ nextArray = arrays;
+ freeObjects = NULL;
+ }
+
+ void setArraySize(int arraySize)
+ {
+ this->arraySize = arraySize;
+ }
+
+ T* newObject()
+ {
+ T* o = freeObjects;
+ if (!o)
+ {
+ PoolArray<T>* p = nextArray;
+ if (p)
+ {
+ nextArray = p->next;
+ }
+ else
+ {
+ p = new(btAlignedAlloc(sizeof(PoolArray<T>), 16)) PoolArray<T>(arraySize);
+ p->next = arrays;
+ arrays = p;
+ }
+ o = p->init();
+ }
+ freeObjects = o->next;
+ return new(o) T();
+ };
+
+ void freeObject(T* object)
+ {
+ object->~T();
+ object->next = freeObjects;
+ freeObjects = object;
+ }
+ };
+
+ btVector3 scaling;
+ btVector3 center;
+ Pool<Vertex> vertexPool;
+ Pool<Edge> edgePool;
+ Pool<Face> facePool;
+ btAlignedObjectArray<Vertex*> originalVertices;
+ int mergeStamp;
+ int minAxis;
+ int medAxis;
+ int maxAxis;
+ int usedEdgePairs;
+ int maxUsedEdgePairs;
+
+ static Orientation getOrientation(const Edge* prev, const Edge* next, const Point32& s, const Point32& t);
+ Edge* findMaxAngle(bool ccw, const Vertex* start, const Point32& s, const Point64& rxs, const Point64& sxrxs, Rational64& minCot);
+ void findEdgeForCoplanarFaces(Vertex* c0, Vertex* c1, Edge*& e0, Edge*& e1, Vertex* stop0, Vertex* stop1);
+
+ Edge* newEdgePair(Vertex* from, Vertex* to);
+
+ void removeEdgePair(Edge* edge)
+ {
+ Edge* n = edge->next;
+ Edge* r = edge->reverse;
+
+ btAssert(edge->target && r->target);
+
+ if (n != edge)
+ {
+ n->prev = edge->prev;
+ edge->prev->next = n;
+ r->target->edges = n;
+ }
+ else
+ {
+ r->target->edges = NULL;
+ }
+
+ n = r->next;
+
+ if (n != r)
+ {
+ n->prev = r->prev;
+ r->prev->next = n;
+ edge->target->edges = n;
+ }
+ else
+ {
+ edge->target->edges = NULL;
+ }
+
+ edgePool.freeObject(edge);
+ edgePool.freeObject(r);
+ usedEdgePairs--;
+ }
+
+ void computeInternal(int start, int end, IntermediateHull& result);
+
+ bool mergeProjection(IntermediateHull& h0, IntermediateHull& h1, Vertex*& c0, Vertex*& c1);
+
+ void merge(IntermediateHull& h0, IntermediateHull& h1);
+
+ btVector3 toBtVector(const Point32& v);
+
+ btVector3 getBtNormal(Face* face);
+
+ bool shiftFace(Face* face, btScalar amount, btAlignedObjectArray<Vertex*> stack);
+
+ public:
+ Vertex* vertexList;
+
+ void compute(const void* coords, bool doubleCoords, int stride, int count);
+
+ btVector3 getCoordinates(const Vertex* v);
+
+ btScalar shrink(btScalar amount, btScalar clampAmount);
+};
+
+
+btConvexHullInternal::Int128 btConvexHullInternal::Int128::operator*(int64_t b) const
+{
+ bool negative = (int64_t) high < 0;
+ Int128 a = negative ? -*this : *this;
+ if (b < 0)
+ {
+ negative = !negative;
+ b = -b;
+ }
+ Int128 result = mul(a.low, (uint64_t) b);
+ result.high += a.high * (uint64_t) b;
+ return negative ? -result : result;
+}
+
+btConvexHullInternal::Int128 btConvexHullInternal::Int128::mul(int64_t a, int64_t b)
+{
+ Int128 result;
+
+#ifdef USE_X86_64_ASM
+ __asm__ ("imulq %[b]"
+ : "=a" (result.low), "=d" (result.high)
+ : "0"(a), [b] "r"(b)
+ : "cc" );
+ return result;
+
+#else
+ bool negative = a < 0;
+ if (negative)
+ {
+ a = -a;
+ }
+ if (b < 0)
+ {
+ negative = !negative;
+ b = -b;
+ }
+ DMul<uint64_t, uint32_t>::mul((uint64_t) a, (uint64_t) b, result.low, result.high);
+ return negative ? -result : result;
+#endif
+}
+
+btConvexHullInternal::Int128 btConvexHullInternal::Int128::mul(uint64_t a, uint64_t b)
+{
+ Int128 result;
+
+#ifdef USE_X86_64_ASM
+ __asm__ ("mulq %[b]"
+ : "=a" (result.low), "=d" (result.high)
+ : "0"(a), [b] "r"(b)
+ : "cc" );
+
+#else
+ DMul<uint64_t, uint32_t>::mul(a, b, result.low, result.high);
+#endif
+
+ return result;
+}
+
+int btConvexHullInternal::Rational64::compare(const Rational64& b) const
+{
+ if (sign != b.sign)
+ {
+ return sign - b.sign;
+ }
+ else if (sign == 0)
+ {
+ return 0;
+ }
+
+ // return (numerator * b.denominator > b.numerator * denominator) ? sign : (numerator * b.denominator < b.numerator * denominator) ? -sign : 0;
+
+#ifdef USE_X86_64_ASM
+
+ int result;
+ int64_t tmp;
+ int64_t dummy;
+ __asm__ ("mulq %[bn]\n\t"
+ "movq %%rax, %[tmp]\n\t"
+ "movq %%rdx, %%rbx\n\t"
+ "movq %[tn], %%rax\n\t"
+ "mulq %[bd]\n\t"
+ "subq %[tmp], %%rax\n\t"
+ "sbbq %%rbx, %%rdx\n\t" // rdx:rax contains 128-bit-difference "numerator*b.denominator - b.numerator*denominator"
+ "setnsb %%bh\n\t" // bh=1 if difference is non-negative, bh=0 otherwise
+ "orq %%rdx, %%rax\n\t"
+ "setnzb %%bl\n\t" // bl=1 if difference if non-zero, bl=0 if it is zero
+ "decb %%bh\n\t" // now bx=0x0000 if difference is zero, 0xff01 if it is negative, 0x0001 if it is positive (i.e., same sign as difference)
+ "shll $16, %%ebx\n\t" // ebx has same sign as difference
+ : "=&b"(result), [tmp] "=&r"(tmp), "=a"(dummy)
+ : "a"(denominator), [bn] "g"(b.numerator), [tn] "g"(numerator), [bd] "g"(b.denominator)
+ : "%rdx", "cc" );
+ return result ? result ^ sign // if sign is +1, only bit 0 of result is inverted, which does not change the sign of result (and cannot result in zero)
+ // if sign is -1, all bits of result are inverted, which changes the sign of result (and again cannot result in zero)
+ : 0;
+
+#else
+
+ return sign * Int128::mul(m_numerator, b.m_denominator).ucmp(Int128::mul(m_denominator, b.m_numerator));
+
+#endif
+}
+
+int btConvexHullInternal::Rational128::compare(const Rational128& b) const
+{
+ if (sign != b.sign)
+ {
+ return sign - b.sign;
+ }
+ else if (sign == 0)
+ {
+ return 0;
+ }
+ if (isInt64)
+ {
+ return -b.compare(sign * (int64_t) numerator.low);
+ }
+
+ Int128 nbdLow, nbdHigh, dbnLow, dbnHigh;
+ DMul<Int128, uint64_t>::mul(numerator, b.denominator, nbdLow, nbdHigh);
+ DMul<Int128, uint64_t>::mul(denominator, b.numerator, dbnLow, dbnHigh);
+
+ int cmp = nbdHigh.ucmp(dbnHigh);
+ if (cmp)
+ {
+ return cmp * sign;
+ }
+ return nbdLow.ucmp(dbnLow) * sign;
+}
+
+int btConvexHullInternal::Rational128::compare(int64_t b) const
+{
+ if (isInt64)
+ {
+ int64_t a = sign * (int64_t) numerator.low;
+ return (a > b) ? 1 : (a < b) ? -1 : 0;
+ }
+ if (b > 0)
+ {
+ if (sign <= 0)
+ {
+ return -1;
+ }
+ }
+ else if (b < 0)
+ {
+ if (sign >= 0)
+ {
+ return 1;
+ }
+ b = -b;
+ }
+ else
+ {
+ return sign;
+ }
+
+ return numerator.ucmp(denominator * b) * sign;
+}
+
+
+btConvexHullInternal::Edge* btConvexHullInternal::newEdgePair(Vertex* from, Vertex* to)
+{
+ btAssert(from && to);
+ Edge* e = edgePool.newObject();
+ Edge* r = edgePool.newObject();
+ e->reverse = r;
+ r->reverse = e;
+ e->copy = mergeStamp;
+ r->copy = mergeStamp;
+ e->target = to;
+ r->target = from;
+ e->face = NULL;
+ r->face = NULL;
+ usedEdgePairs++;
+ if (usedEdgePairs > maxUsedEdgePairs)
+ {
+ maxUsedEdgePairs = usedEdgePairs;
+ }
+ return e;
+}
+
+bool btConvexHullInternal::mergeProjection(IntermediateHull& h0, IntermediateHull& h1, Vertex*& c0, Vertex*& c1)
+{
+ Vertex* v0 = h0.maxYx;
+ Vertex* v1 = h1.minYx;
+ if ((v0->point.x == v1->point.x) && (v0->point.y == v1->point.y))
+ {
+ btAssert(v0->point.z < v1->point.z);
+ Vertex* v1p = v1->prev;
+ if (v1p == v1)
+ {
+ c0 = v0;
+ if (v1->edges)
+ {
+ btAssert(v1->edges->next == v1->edges);
+ v1 = v1->edges->target;
+ btAssert(v1->edges->next == v1->edges);
+ }
+ c1 = v1;
+ return false;
+ }
+ Vertex* v1n = v1->next;
+ v1p->next = v1n;
+ v1n->prev = v1p;
+ if (v1 == h1.minXy)
+ {
+ if ((v1n->point.x < v1p->point.x) || ((v1n->point.x == v1p->point.x) && (v1n->point.y < v1p->point.y)))
+ {
+ h1.minXy = v1n;
+ }
+ else
+ {
+ h1.minXy = v1p;
+ }
+ }
+ if (v1 == h1.maxXy)
+ {
+ if ((v1n->point.x > v1p->point.x) || ((v1n->point.x == v1p->point.x) && (v1n->point.y > v1p->point.y)))
+ {
+ h1.maxXy = v1n;
+ }
+ else
+ {
+ h1.maxXy = v1p;
+ }
+ }
+ }
+
+ v0 = h0.maxXy;
+ v1 = h1.maxXy;
+ Vertex* v00 = NULL;
+ Vertex* v10 = NULL;
+ int32_t sign = 1;
+
+ for (int side = 0; side <= 1; side++)
+ {
+ int32_t dx = (v1->point.x - v0->point.x) * sign;
+ if (dx > 0)
+ {
+ while (true)
+ {
+ int32_t dy = v1->point.y - v0->point.y;
+
+ Vertex* w0 = side ? v0->next : v0->prev;
+ if (w0 != v0)
+ {
+ int32_t dx0 = (w0->point.x - v0->point.x) * sign;
+ int32_t dy0 = w0->point.y - v0->point.y;
+ if ((dy0 <= 0) && ((dx0 == 0) || ((dx0 < 0) && (dy0 * dx <= dy * dx0))))
+ {
+ v0 = w0;
+ dx = (v1->point.x - v0->point.x) * sign;
+ continue;
+ }
+ }
+
+ Vertex* w1 = side ? v1->next : v1->prev;
+ if (w1 != v1)
+ {
+ int32_t dx1 = (w1->point.x - v1->point.x) * sign;
+ int32_t dy1 = w1->point.y - v1->point.y;
+ int32_t dxn = (w1->point.x - v0->point.x) * sign;
+ if ((dxn > 0) && (dy1 < 0) && ((dx1 == 0) || ((dx1 < 0) && (dy1 * dx < dy * dx1))))
+ {
+ v1 = w1;
+ dx = dxn;
+ continue;
+ }
+ }
+
+ break;
+ }
+ }
+ else if (dx < 0)
+ {
+ while (true)
+ {
+ int32_t dy = v1->point.y - v0->point.y;
+
+ Vertex* w1 = side ? v1->prev : v1->next;
+ if (w1 != v1)
+ {
+ int32_t dx1 = (w1->point.x - v1->point.x) * sign;
+ int32_t dy1 = w1->point.y - v1->point.y;
+ if ((dy1 >= 0) && ((dx1 == 0) || ((dx1 < 0) && (dy1 * dx <= dy * dx1))))
+ {
+ v1 = w1;
+ dx = (v1->point.x - v0->point.x) * sign;
+ continue;
+ }
+ }
+
+ Vertex* w0 = side ? v0->prev : v0->next;
+ if (w0 != v0)
+ {
+ int32_t dx0 = (w0->point.x - v0->point.x) * sign;
+ int32_t dy0 = w0->point.y - v0->point.y;
+ int32_t dxn = (v1->point.x - w0->point.x) * sign;
+ if ((dxn < 0) && (dy0 > 0) && ((dx0 == 0) || ((dx0 < 0) && (dy0 * dx < dy * dx0))))
+ {
+ v0 = w0;
+ dx = dxn;
+ continue;
+ }
+ }
+
+ break;
+ }
+ }
+ else
+ {
+ int32_t x = v0->point.x;
+ int32_t y0 = v0->point.y;
+ Vertex* w0 = v0;
+ Vertex* t;
+ while (((t = side ? w0->next : w0->prev) != v0) && (t->point.x == x) && (t->point.y <= y0))
+ {
+ w0 = t;
+ y0 = t->point.y;
+ }
+ v0 = w0;
+
+ int32_t y1 = v1->point.y;
+ Vertex* w1 = v1;
+ while (((t = side ? w1->prev : w1->next) != v1) && (t->point.x == x) && (t->point.y >= y1))
+ {
+ w1 = t;
+ y1 = t->point.y;
+ }
+ v1 = w1;
+ }
+
+ if (side == 0)
+ {
+ v00 = v0;
+ v10 = v1;
+
+ v0 = h0.minXy;
+ v1 = h1.minXy;
+ sign = -1;
+ }
+ }
+
+ v0->prev = v1;
+ v1->next = v0;
+
+ v00->next = v10;
+ v10->prev = v00;
+
+ if (h1.minXy->point.x < h0.minXy->point.x)
+ {
+ h0.minXy = h1.minXy;
+ }
+ if (h1.maxXy->point.x >= h0.maxXy->point.x)
+ {
+ h0.maxXy = h1.maxXy;
+ }
+
+ h0.maxYx = h1.maxYx;
+
+ c0 = v00;
+ c1 = v10;
+
+ return true;
+}
+
+void btConvexHullInternal::computeInternal(int start, int end, IntermediateHull& result)
+{
+ int n = end - start;
+ switch (n)
+ {
+ case 0:
+ result.minXy = NULL;
+ result.maxXy = NULL;
+ result.minYx = NULL;
+ result.maxYx = NULL;
+ return;
+ case 2:
+ {
+ Vertex* v = originalVertices[start];
+ Vertex* w = v + 1;
+ if (v->point != w->point)
+ {
+ int32_t dx = v->point.x - w->point.x;
+ int32_t dy = v->point.y - w->point.y;
+
+ if ((dx == 0) && (dy == 0))
+ {
+ if (v->point.z > w->point.z)
+ {
+ Vertex* t = w;
+ w = v;
+ v = t;
+ }
+ btAssert(v->point.z < w->point.z);
+ v->next = v;
+ v->prev = v;
+ result.minXy = v;
+ result.maxXy = v;
+ result.minYx = v;
+ result.maxYx = v;
+ }
+ else
+ {
+ v->next = w;
+ v->prev = w;
+ w->next = v;
+ w->prev = v;
+
+ if ((dx < 0) || ((dx == 0) && (dy < 0)))
+ {
+ result.minXy = v;
+ result.maxXy = w;
+ }
+ else
+ {
+ result.minXy = w;
+ result.maxXy = v;
+ }
+
+ if ((dy < 0) || ((dy == 0) && (dx < 0)))
+ {
+ result.minYx = v;
+ result.maxYx = w;
+ }
+ else
+ {
+ result.minYx = w;
+ result.maxYx = v;
+ }
+ }
+
+ Edge* e = newEdgePair(v, w);
+ e->link(e);
+ v->edges = e;
+
+ e = e->reverse;
+ e->link(e);
+ w->edges = e;
+
+ return;
+ }
+ {
+ Vertex* v = originalVertices[start];
+ v->edges = NULL;
+ v->next = v;
+ v->prev = v;
+
+ result.minXy = v;
+ result.maxXy = v;
+ result.minYx = v;
+ result.maxYx = v;
+ }
+
+ return;
+ }
+
+ case 1:
+ {
+ Vertex* v = originalVertices[start];
+ v->edges = NULL;
+ v->next = v;
+ v->prev = v;
+
+ result.minXy = v;
+ result.maxXy = v;
+ result.minYx = v;
+ result.maxYx = v;
+
+ return;
+ }
+ }
+
+ int split0 = start + n / 2;
+ Point32 p = originalVertices[split0-1]->point;
+ int split1 = split0;
+ while ((split1 < end) && (originalVertices[split1]->point == p))
+ {
+ split1++;
+ }
+ computeInternal(start, split0, result);
+ IntermediateHull hull1;
+ computeInternal(split1, end, hull1);
+#ifdef DEBUG_CONVEX_HULL
+ printf("\n\nMerge\n");
+ result.print();
+ hull1.print();
+#endif
+ merge(result, hull1);
+#ifdef DEBUG_CONVEX_HULL
+ printf("\n Result\n");
+ result.print();
+#endif
+}
+
+#ifdef DEBUG_CONVEX_HULL
+void btConvexHullInternal::IntermediateHull::print()
+{
+ printf(" Hull\n");
+ for (Vertex* v = minXy; v; )
+ {
+ printf(" ");
+ v->print();
+ if (v == maxXy)
+ {
+ printf(" maxXy");
+ }
+ if (v == minYx)
+ {
+ printf(" minYx");
+ }
+ if (v == maxYx)
+ {
+ printf(" maxYx");
+ }
+ if (v->next->prev != v)
+ {
+ printf(" Inconsistency");
+ }
+ printf("\n");
+ v = v->next;
+ if (v == minXy)
+ {
+ break;
+ }
+ }
+ if (minXy)
+ {
+ minXy->copy = (minXy->copy == -1) ? -2 : -1;
+ minXy->printGraph();
+ }
+}
+
+void btConvexHullInternal::Vertex::printGraph()
+{
+ print();
+ printf("\nEdges\n");
+ Edge* e = edges;
+ if (e)
+ {
+ do
+ {
+ e->print();
+ printf("\n");
+ e = e->next;
+ } while (e != edges);
+ do
+ {
+ Vertex* v = e->target;
+ if (v->copy != copy)
+ {
+ v->copy = copy;
+ v->printGraph();
+ }
+ e = e->next;
+ } while (e != edges);
+ }
+}
+#endif
+
+btConvexHullInternal::Orientation btConvexHullInternal::getOrientation(const Edge* prev, const Edge* next, const Point32& s, const Point32& t)
+{
+ btAssert(prev->reverse->target == next->reverse->target);
+ if (prev->next == next)
+ {
+ if (prev->prev == next)
+ {
+ Point64 n = t.cross(s);
+ Point64 m = (*prev->target - *next->reverse->target).cross(*next->target - *next->reverse->target);
+ btAssert(!m.isZero());
+ int64_t dot = n.dot(m);
+ btAssert(dot != 0);
+ return (dot > 0) ? COUNTER_CLOCKWISE : CLOCKWISE;
+ }
+ return COUNTER_CLOCKWISE;
+ }
+ else if (prev->prev == next)
+ {
+ return CLOCKWISE;
+ }
+ else
+ {
+ return NONE;
+ }
+}
+
+btConvexHullInternal::Edge* btConvexHullInternal::findMaxAngle(bool ccw, const Vertex* start, const Point32& s, const Point64& rxs, const Point64& sxrxs, Rational64& minCot)
+{
+ Edge* minEdge = NULL;
+
+#ifdef DEBUG_CONVEX_HULL
+ printf("find max edge for %d\n", start->point.index);
+#endif
+ Edge* e = start->edges;
+ if (e)
+ {
+ do
+ {
+ if (e->copy > mergeStamp)
+ {
+ Point32 t = *e->target - *start;
+ Rational64 cot(t.dot(sxrxs), t.dot(rxs));
+#ifdef DEBUG_CONVEX_HULL
+ printf(" Angle is %f (%d) for ", (float) btAtan(cot.toScalar()), (int) cot.isNaN());
+ e->print();
+#endif
+ if (cot.isNaN())
+ {
+ btAssert(ccw ? (t.dot(s) < 0) : (t.dot(s) > 0));
+ }
+ else
+ {
+ int cmp;
+ if (minEdge == NULL)
+ {
+ minCot = cot;
+ minEdge = e;
+ }
+ else if ((cmp = cot.compare(minCot)) < 0)
+ {
+ minCot = cot;
+ minEdge = e;
+ }
+ else if ((cmp == 0) && (ccw == (getOrientation(minEdge, e, s, t) == COUNTER_CLOCKWISE)))
+ {
+ minEdge = e;
+ }
+ }
+#ifdef DEBUG_CONVEX_HULL
+ printf("\n");
+#endif
+ }
+ e = e->next;
+ } while (e != start->edges);
+ }
+ return minEdge;
+}
+
+void btConvexHullInternal::findEdgeForCoplanarFaces(Vertex* c0, Vertex* c1, Edge*& e0, Edge*& e1, Vertex* stop0, Vertex* stop1)
+{
+ Edge* start0 = e0;
+ Edge* start1 = e1;
+ Point32 et0 = start0 ? start0->target->point : c0->point;
+ Point32 et1 = start1 ? start1->target->point : c1->point;
+ Point32 s = c1->point - c0->point;
+ Point64 normal = ((start0 ? start0 : start1)->target->point - c0->point).cross(s);
+ int64_t dist = c0->point.dot(normal);
+ btAssert(!start1 || (start1->target->point.dot(normal) == dist));
+ Point64 perp = s.cross(normal);
+ btAssert(!perp.isZero());
+
+#ifdef DEBUG_CONVEX_HULL
+ printf(" Advancing %d %d (%p %p, %d %d)\n", c0->point.index, c1->point.index, start0, start1, start0 ? start0->target->point.index : -1, start1 ? start1->target->point.index : -1);
+#endif
+
+ int64_t maxDot0 = et0.dot(perp);
+ if (e0)
+ {
+ while (e0->target != stop0)
+ {
+ Edge* e = e0->reverse->prev;
+ if (e->target->point.dot(normal) < dist)
+ {
+ break;
+ }
+ btAssert(e->target->point.dot(normal) == dist);
+ if (e->copy == mergeStamp)
+ {
+ break;
+ }
+ int64_t dot = e->target->point.dot(perp);
+ if (dot <= maxDot0)
+ {
+ break;
+ }
+ maxDot0 = dot;
+ e0 = e;
+ et0 = e->target->point;
+ }
+ }
+
+ int64_t maxDot1 = et1.dot(perp);
+ if (e1)
+ {
+ while (e1->target != stop1)
+ {
+ Edge* e = e1->reverse->next;
+ if (e->target->point.dot(normal) < dist)
+ {
+ break;
+ }
+ btAssert(e->target->point.dot(normal) == dist);
+ if (e->copy == mergeStamp)
+ {
+ break;
+ }
+ int64_t dot = e->target->point.dot(perp);
+ if (dot <= maxDot1)
+ {
+ break;
+ }
+ maxDot1 = dot;
+ e1 = e;
+ et1 = e->target->point;
+ }
+ }
+
+#ifdef DEBUG_CONVEX_HULL
+ printf(" Starting at %d %d\n", et0.index, et1.index);
+#endif
+
+ int64_t dx = maxDot1 - maxDot0;
+ if (dx > 0)
+ {
+ while (true)
+ {
+ int64_t dy = (et1 - et0).dot(s);
+
+ if (e0 && (e0->target != stop0))
+ {
+ Edge* f0 = e0->next->reverse;
+ if (f0->copy > mergeStamp)
+ {
+ int64_t dx0 = (f0->target->point - et0).dot(perp);
+ int64_t dy0 = (f0->target->point - et0).dot(s);
+ if ((dx0 == 0) ? (dy0 < 0) : ((dx0 < 0) && (Rational64(dy0, dx0).compare(Rational64(dy, dx)) >= 0)))
+ {
+ et0 = f0->target->point;
+ dx = (et1 - et0).dot(perp);
+ e0 = (e0 == start0) ? NULL : f0;
+ continue;
+ }
+ }
+ }
+
+ if (e1 && (e1->target != stop1))
+ {
+ Edge* f1 = e1->reverse->next;
+ if (f1->copy > mergeStamp)
+ {
+ Point32 d1 = f1->target->point - et1;
+ if (d1.dot(normal) == 0)
+ {
+ int64_t dx1 = d1.dot(perp);
+ int64_t dy1 = d1.dot(s);
+ int64_t dxn = (f1->target->point - et0).dot(perp);
+ if ((dxn > 0) && ((dx1 == 0) ? (dy1 < 0) : ((dx1 < 0) && (Rational64(dy1, dx1).compare(Rational64(dy, dx)) > 0))))
+ {
+ e1 = f1;
+ et1 = e1->target->point;
+ dx = dxn;
+ continue;
+ }
+ }
+ else
+ {
+ btAssert((e1 == start1) && (d1.dot(normal) < 0));
+ }
+ }
+ }
+
+ break;
+ }
+ }
+ else if (dx < 0)
+ {
+ while (true)
+ {
+ int64_t dy = (et1 - et0).dot(s);
+
+ if (e1 && (e1->target != stop1))
+ {
+ Edge* f1 = e1->prev->reverse;
+ if (f1->copy > mergeStamp)
+ {
+ int64_t dx1 = (f1->target->point - et1).dot(perp);
+ int64_t dy1 = (f1->target->point - et1).dot(s);
+ if ((dx1 == 0) ? (dy1 > 0) : ((dx1 < 0) && (Rational64(dy1, dx1).compare(Rational64(dy, dx)) <= 0)))
+ {
+ et1 = f1->target->point;
+ dx = (et1 - et0).dot(perp);
+ e1 = (e1 == start1) ? NULL : f1;
+ continue;
+ }
+ }
+ }
+
+ if (e0 && (e0->target != stop0))
+ {
+ Edge* f0 = e0->reverse->prev;
+ if (f0->copy > mergeStamp)
+ {
+ Point32 d0 = f0->target->point - et0;
+ if (d0.dot(normal) == 0)
+ {
+ int64_t dx0 = d0.dot(perp);
+ int64_t dy0 = d0.dot(s);
+ int64_t dxn = (et1 - f0->target->point).dot(perp);
+ if ((dxn < 0) && ((dx0 == 0) ? (dy0 > 0) : ((dx0 < 0) && (Rational64(dy0, dx0).compare(Rational64(dy, dx)) < 0))))
+ {
+ e0 = f0;
+ et0 = e0->target->point;
+ dx = dxn;
+ continue;
+ }
+ }
+ else
+ {
+ btAssert((e0 == start0) && (d0.dot(normal) < 0));
+ }
+ }
+ }
+
+ break;
+ }
+ }
+#ifdef DEBUG_CONVEX_HULL
+ printf(" Advanced edges to %d %d\n", et0.index, et1.index);
+#endif
+}
+
+
+void btConvexHullInternal::merge(IntermediateHull& h0, IntermediateHull& h1)
+{
+ if (!h1.maxXy)
+ {
+ return;
+ }
+ if (!h0.maxXy)
+ {
+ h0 = h1;
+ return;
+ }
+
+ mergeStamp--;
+
+ Vertex* c0 = NULL;
+ Edge* toPrev0 = NULL;
+ Edge* firstNew0 = NULL;
+ Edge* pendingHead0 = NULL;
+ Edge* pendingTail0 = NULL;
+ Vertex* c1 = NULL;
+ Edge* toPrev1 = NULL;
+ Edge* firstNew1 = NULL;
+ Edge* pendingHead1 = NULL;
+ Edge* pendingTail1 = NULL;
+ Point32 prevPoint;
+
+ if (mergeProjection(h0, h1, c0, c1))
+ {
+ Point32 s = *c1 - *c0;
+ Point64 normal = Point32(0, 0, -1).cross(s);
+ Point64 t = s.cross(normal);
+ btAssert(!t.isZero());
+
+ Edge* e = c0->edges;
+ Edge* start0 = NULL;
+ if (e)
+ {
+ do
+ {
+ int64_t dot = (*e->target - *c0).dot(normal);
+ btAssert(dot <= 0);
+ if ((dot == 0) && ((*e->target - *c0).dot(t) > 0))
+ {
+ if (!start0 || (getOrientation(start0, e, s, Point32(0, 0, -1)) == CLOCKWISE))
+ {
+ start0 = e;
+ }
+ }
+ e = e->next;
+ } while (e != c0->edges);
+ }
+
+ e = c1->edges;
+ Edge* start1 = NULL;
+ if (e)
+ {
+ do
+ {
+ int64_t dot = (*e->target - *c1).dot(normal);
+ btAssert(dot <= 0);
+ if ((dot == 0) && ((*e->target - *c1).dot(t) > 0))
+ {
+ if (!start1 || (getOrientation(start1, e, s, Point32(0, 0, -1)) == COUNTER_CLOCKWISE))
+ {
+ start1 = e;
+ }
+ }
+ e = e->next;
+ } while (e != c1->edges);
+ }
+
+ if (start0 || start1)
+ {
+ findEdgeForCoplanarFaces(c0, c1, start0, start1, NULL, NULL);
+ if (start0)
+ {
+ c0 = start0->target;
+ }
+ if (start1)
+ {
+ c1 = start1->target;
+ }
+ }
+
+ prevPoint = c1->point;
+ prevPoint.z++;
+ }
+ else
+ {
+ prevPoint = c1->point;
+ prevPoint.x++;
+ }
+
+ Vertex* first0 = c0;
+ Vertex* first1 = c1;
+ bool firstRun = true;
+
+ while (true)
+ {
+ Point32 s = *c1 - *c0;
+ Point32 r = prevPoint - c0->point;
+ Point64 rxs = r.cross(s);
+ Point64 sxrxs = s.cross(rxs);
+
+#ifdef DEBUG_CONVEX_HULL
+ printf("\n Checking %d %d\n", c0->point.index, c1->point.index);
+#endif
+ Rational64 minCot0(0, 0);
+ Edge* min0 = findMaxAngle(false, c0, s, rxs, sxrxs, minCot0);
+ Rational64 minCot1(0, 0);
+ Edge* min1 = findMaxAngle(true, c1, s, rxs, sxrxs, minCot1);
+ if (!min0 && !min1)
+ {
+ Edge* e = newEdgePair(c0, c1);
+ e->link(e);
+ c0->edges = e;
+
+ e = e->reverse;
+ e->link(e);
+ c1->edges = e;
+ return;
+ }
+ else
+ {
+ int cmp = !min0 ? 1 : !min1 ? -1 : minCot0.compare(minCot1);
+#ifdef DEBUG_CONVEX_HULL
+ printf(" -> Result %d\n", cmp);
+#endif
+ if (firstRun || ((cmp >= 0) ? !minCot1.isNegativeInfinity() : !minCot0.isNegativeInfinity()))
+ {
+ Edge* e = newEdgePair(c0, c1);
+ if (pendingTail0)
+ {
+ pendingTail0->prev = e;
+ }
+ else
+ {
+ pendingHead0 = e;
+ }
+ e->next = pendingTail0;
+ pendingTail0 = e;
+
+ e = e->reverse;
+ if (pendingTail1)
+ {
+ pendingTail1->next = e;
+ }
+ else
+ {
+ pendingHead1 = e;
+ }
+ e->prev = pendingTail1;
+ pendingTail1 = e;
+ }
+
+ Edge* e0 = min0;
+ Edge* e1 = min1;
+
+#ifdef DEBUG_CONVEX_HULL
+ printf(" Found min edges to %d %d\n", e0 ? e0->target->point.index : -1, e1 ? e1->target->point.index : -1);
+#endif
+
+ if (cmp == 0)
+ {
+ findEdgeForCoplanarFaces(c0, c1, e0, e1, NULL, NULL);
+ }
+
+ if ((cmp >= 0) && e1)
+ {
+ if (toPrev1)
+ {
+ for (Edge* e = toPrev1->next, *n = NULL; e != min1; e = n)
+ {
+ n = e->next;
+ removeEdgePair(e);
+ }
+ }
+
+ if (pendingTail1)
+ {
+ if (toPrev1)
+ {
+ toPrev1->link(pendingHead1);
+ }
+ else
+ {
+ min1->prev->link(pendingHead1);
+ firstNew1 = pendingHead1;
+ }
+ pendingTail1->link(min1);
+ pendingHead1 = NULL;
+ pendingTail1 = NULL;
+ }
+ else if (!toPrev1)
+ {
+ firstNew1 = min1;
+ }
+
+ prevPoint = c1->point;
+ c1 = e1->target;
+ toPrev1 = e1->reverse;
+ }
+
+ if ((cmp <= 0) && e0)
+ {
+ if (toPrev0)
+ {
+ for (Edge* e = toPrev0->prev, *n = NULL; e != min0; e = n)
+ {
+ n = e->prev;
+ removeEdgePair(e);
+ }
+ }
+
+ if (pendingTail0)
+ {
+ if (toPrev0)
+ {
+ pendingHead0->link(toPrev0);
+ }
+ else
+ {
+ pendingHead0->link(min0->next);
+ firstNew0 = pendingHead0;
+ }
+ min0->link(pendingTail0);
+ pendingHead0 = NULL;
+ pendingTail0 = NULL;
+ }
+ else if (!toPrev0)
+ {
+ firstNew0 = min0;
+ }
+
+ prevPoint = c0->point;
+ c0 = e0->target;
+ toPrev0 = e0->reverse;
+ }
+ }
+
+ if ((c0 == first0) && (c1 == first1))
+ {
+ if (toPrev0 == NULL)
+ {
+ pendingHead0->link(pendingTail0);
+ c0->edges = pendingTail0;
+ }
+ else
+ {
+ for (Edge* e = toPrev0->prev, *n = NULL; e != firstNew0; e = n)
+ {
+ n = e->prev;
+ removeEdgePair(e);
+ }
+ if (pendingTail0)
+ {
+ pendingHead0->link(toPrev0);
+ firstNew0->link(pendingTail0);
+ }
+ }
+
+ if (toPrev1 == NULL)
+ {
+ pendingTail1->link(pendingHead1);
+ c1->edges = pendingTail1;
+ }
+ else
+ {
+ for (Edge* e = toPrev1->next, *n = NULL; e != firstNew1; e = n)
+ {
+ n = e->next;
+ removeEdgePair(e);
+ }
+ if (pendingTail1)
+ {
+ toPrev1->link(pendingHead1);
+ pendingTail1->link(firstNew1);
+ }
+ }
+
+ return;
+ }
+
+ firstRun = false;
+ }
+}
+
+class pointCmp
+{
+ public:
+
+ bool operator() ( const btConvexHullInternal::Point32& p, const btConvexHullInternal::Point32& q ) const
+ {
+ return (p.y < q.y) || ((p.y == q.y) && ((p.x < q.x) || ((p.x == q.x) && (p.z < q.z))));
+ }
+};
+
+void btConvexHullInternal::compute(const void* coords, bool doubleCoords, int stride, int count)
+{
+ btVector3 min(btScalar(1e30), btScalar(1e30), btScalar(1e30)), max(btScalar(-1e30), btScalar(-1e30), btScalar(-1e30));
+ const char* ptr = (const char*) coords;
+ if (doubleCoords)
+ {
+ for (int i = 0; i < count; i++)
+ {
+ const double* v = (const double*) ptr;
+ btVector3 p((btScalar) v[0], (btScalar) v[1], (btScalar) v[2]);
+ ptr += stride;
+ min.setMin(p);
+ max.setMax(p);
+ }
+ }
+ else
+ {
+ for (int i = 0; i < count; i++)
+ {
+ const float* v = (const float*) ptr;
+ btVector3 p(v[0], v[1], v[2]);
+ ptr += stride;
+ min.setMin(p);
+ max.setMax(p);
+ }
+ }
+
+ btVector3 s = max - min;
+ maxAxis = s.maxAxis();
+ minAxis = s.minAxis();
+ if (minAxis == maxAxis)
+ {
+ minAxis = (maxAxis + 1) % 3;
+ }
+ medAxis = 3 - maxAxis - minAxis;
+
+ s /= btScalar(10216);
+ if (((medAxis + 1) % 3) != maxAxis)
+ {
+ s *= -1;
+ }
+ scaling = s;
+
+ if (s[0] != 0)
+ {
+ s[0] = btScalar(1) / s[0];
+ }
+ if (s[1] != 0)
+ {
+ s[1] = btScalar(1) / s[1];
+ }
+ if (s[2] != 0)
+ {
+ s[2] = btScalar(1) / s[2];
+ }
+
+ center = (min + max) * btScalar(0.5);
+
+ btAlignedObjectArray<Point32> points;
+ points.resize(count);
+ ptr = (const char*) coords;
+ if (doubleCoords)
+ {
+ for (int i = 0; i < count; i++)
+ {
+ const double* v = (const double*) ptr;
+ btVector3 p((btScalar) v[0], (btScalar) v[1], (btScalar) v[2]);
+ ptr += stride;
+ p = (p - center) * s;
+ points[i].x = (int32_t) p[medAxis];
+ points[i].y = (int32_t) p[maxAxis];
+ points[i].z = (int32_t) p[minAxis];
+ points[i].index = i;
+ }
+ }
+ else
+ {
+ for (int i = 0; i < count; i++)
+ {
+ const float* v = (const float*) ptr;
+ btVector3 p(v[0], v[1], v[2]);
+ ptr += stride;
+ p = (p - center) * s;
+ points[i].x = (int32_t) p[medAxis];
+ points[i].y = (int32_t) p[maxAxis];
+ points[i].z = (int32_t) p[minAxis];
+ points[i].index = i;
+ }
+ }
+ points.quickSort(pointCmp());
+
+ vertexPool.reset();
+ vertexPool.setArraySize(count);
+ originalVertices.resize(count);
+ for (int i = 0; i < count; i++)
+ {
+ Vertex* v = vertexPool.newObject();
+ v->edges = NULL;
+ v->point = points[i];
+ v->copy = -1;
+ originalVertices[i] = v;
+ }
+
+ points.clear();
+
+ edgePool.reset();
+ edgePool.setArraySize(6 * count);
+
+ usedEdgePairs = 0;
+ maxUsedEdgePairs = 0;
+
+ mergeStamp = -3;
+
+ IntermediateHull hull;
+ computeInternal(0, count, hull);
+ vertexList = hull.minXy;
+#ifdef DEBUG_CONVEX_HULL
+ printf("max. edges %d (3v = %d)", maxUsedEdgePairs, 3 * count);
+#endif
+}
+
+btVector3 btConvexHullInternal::toBtVector(const Point32& v)
+{
+ btVector3 p;
+ p[medAxis] = btScalar(v.x);
+ p[maxAxis] = btScalar(v.y);
+ p[minAxis] = btScalar(v.z);
+ return p * scaling;
+}
+
+btVector3 btConvexHullInternal::getBtNormal(Face* face)
+{
+ return toBtVector(face->dir0).cross(toBtVector(face->dir1)).normalized();
+}
+
+btVector3 btConvexHullInternal::getCoordinates(const Vertex* v)
+{
+ btVector3 p;
+ p[medAxis] = v->xvalue();
+ p[maxAxis] = v->yvalue();
+ p[minAxis] = v->zvalue();
+ return p * scaling + center;
+}
+
+btScalar btConvexHullInternal::shrink(btScalar amount, btScalar clampAmount)
+{
+ if (!vertexList)
+ {
+ return 0;
+ }
+ int stamp = --mergeStamp;
+ btAlignedObjectArray<Vertex*> stack;
+ vertexList->copy = stamp;
+ stack.push_back(vertexList);
+ btAlignedObjectArray<Face*> faces;
+
+ Point32 ref = vertexList->point;
+ Int128 hullCenterX(0, 0);
+ Int128 hullCenterY(0, 0);
+ Int128 hullCenterZ(0, 0);
+ Int128 volume(0, 0);
+
+ while (stack.size() > 0)
+ {
+ Vertex* v = stack[stack.size() - 1];
+ stack.pop_back();
+ Edge* e = v->edges;
+ if (e)
+ {
+ do
+ {
+ if (e->target->copy != stamp)
+ {
+ e->target->copy = stamp;
+ stack.push_back(e->target);
+ }
+ if (e->copy != stamp)
+ {
+ Face* face = facePool.newObject();
+ face->init(e->target, e->reverse->prev->target, v);
+ faces.push_back(face);
+ Edge* f = e;
+
+ Vertex* a = NULL;
+ Vertex* b = NULL;
+ do
+ {
+ if (a && b)
+ {
+ int64_t vol = (v->point - ref).dot((a->point - ref).cross(b->point - ref));
+ btAssert(vol >= 0);
+ Point32 c = v->point + a->point + b->point + ref;
+ hullCenterX += vol * c.x;
+ hullCenterY += vol * c.y;
+ hullCenterZ += vol * c.z;
+ volume += vol;
+ }
+
+ btAssert(f->copy != stamp);
+ f->copy = stamp;
+ f->face = face;
+
+ a = b;
+ b = f->target;
+
+ f = f->reverse->prev;
+ } while (f != e);
+ }
+ e = e->next;
+ } while (e != v->edges);
+ }
+ }
+
+ if (volume.getSign() <= 0)
+ {
+ return 0;
+ }
+
+ btVector3 hullCenter;
+ hullCenter[medAxis] = hullCenterX.toScalar();
+ hullCenter[maxAxis] = hullCenterY.toScalar();
+ hullCenter[minAxis] = hullCenterZ.toScalar();
+ hullCenter /= 4 * volume.toScalar();
+ hullCenter *= scaling;
+
+ int faceCount = faces.size();
+
+ if (clampAmount > 0)
+ {
+ btScalar minDist = SIMD_INFINITY;
+ for (int i = 0; i < faceCount; i++)
+ {
+ btVector3 normal = getBtNormal(faces[i]);
+ btScalar dist = normal.dot(toBtVector(faces[i]->origin) - hullCenter);
+ if (dist < minDist)
+ {
+ minDist = dist;
+ }
+ }
+
+ if (minDist <= 0)
+ {
+ return 0;
+ }
+
+ amount = btMin(amount, minDist * clampAmount);
+ }
+
+ unsigned int seed = 243703;
+ for (int i = 0; i < faceCount; i++, seed = 1664525 * seed + 1013904223)
+ {
+ btSwap(faces[i], faces[seed % faceCount]);
+ }
+
+ for (int i = 0; i < faceCount; i++)
+ {
+ if (!shiftFace(faces[i], amount, stack))
+ {
+ return -amount;
+ }
+ }
+
+ return amount;
+}
+
+bool btConvexHullInternal::shiftFace(Face* face, btScalar amount, btAlignedObjectArray<Vertex*> stack)
+{
+ btVector3 origShift = getBtNormal(face) * -amount;
+ if (scaling[0] != 0)
+ {
+ origShift[0] /= scaling[0];
+ }
+ if (scaling[1] != 0)
+ {
+ origShift[1] /= scaling[1];
+ }
+ if (scaling[2] != 0)
+ {
+ origShift[2] /= scaling[2];
+ }
+ Point32 shift((int32_t) origShift[medAxis], (int32_t) origShift[maxAxis], (int32_t) origShift[minAxis]);
+ if (shift.isZero())
+ {
+ return true;
+ }
+ Point64 normal = face->getNormal();
+#ifdef DEBUG_CONVEX_HULL
+ printf("\nShrinking face (%d %d %d) (%d %d %d) (%d %d %d) by (%d %d %d)\n",
+ face->origin.x, face->origin.y, face->origin.z, face->dir0.x, face->dir0.y, face->dir0.z, face->dir1.x, face->dir1.y, face->dir1.z, shift.x, shift.y, shift.z);
+#endif
+ int64_t origDot = face->origin.dot(normal);
+ Point32 shiftedOrigin = face->origin + shift;
+ int64_t shiftedDot = shiftedOrigin.dot(normal);
+ btAssert(shiftedDot <= origDot);
+ if (shiftedDot >= origDot)
+ {
+ return false;
+ }
+
+ Edge* intersection = NULL;
+
+ Edge* startEdge = face->nearbyVertex->edges;
+#ifdef DEBUG_CONVEX_HULL
+ printf("Start edge is ");
+ startEdge->print();
+ printf(", normal is (%lld %lld %lld), shifted dot is %lld\n", normal.x, normal.y, normal.z, shiftedDot);
+#endif
+ Rational128 optDot = face->nearbyVertex->dot(normal);
+ int cmp = optDot.compare(shiftedDot);
+#ifdef SHOW_ITERATIONS
+ int n = 0;
+#endif
+ if (cmp >= 0)
+ {
+ Edge* e = startEdge;
+ do
+ {
+#ifdef SHOW_ITERATIONS
+ n++;
+#endif
+ Rational128 dot = e->target->dot(normal);
+ btAssert(dot.compare(origDot) <= 0);
+#ifdef DEBUG_CONVEX_HULL
+ printf("Moving downwards, edge is ");
+ e->print();
+ printf(", dot is %f (%f %lld)\n", (float) dot.toScalar(), (float) optDot.toScalar(), shiftedDot);
+#endif
+ if (dot.compare(optDot) < 0)
+ {
+ int c = dot.compare(shiftedDot);
+ optDot = dot;
+ e = e->reverse;
+ startEdge = e;
+ if (c < 0)
+ {
+ intersection = e;
+ break;
+ }
+ cmp = c;
+ }
+ e = e->prev;
+ } while (e != startEdge);
+
+ if (!intersection)
+ {
+ return false;
+ }
+ }
+ else
+ {
+ Edge* e = startEdge;
+ do
+ {
+#ifdef SHOW_ITERATIONS
+ n++;
+#endif
+ Rational128 dot = e->target->dot(normal);
+ btAssert(dot.compare(origDot) <= 0);
+#ifdef DEBUG_CONVEX_HULL
+ printf("Moving upwards, edge is ");
+ e->print();
+ printf(", dot is %f (%f %lld)\n", (float) dot.toScalar(), (float) optDot.toScalar(), shiftedDot);
+#endif
+ if (dot.compare(optDot) > 0)
+ {
+ cmp = dot.compare(shiftedDot);
+ if (cmp >= 0)
+ {
+ intersection = e;
+ break;
+ }
+ optDot = dot;
+ e = e->reverse;
+ startEdge = e;
+ }
+ e = e->prev;
+ } while (e != startEdge);
+
+ if (!intersection)
+ {
+ return true;
+ }
+ }
+
+#ifdef SHOW_ITERATIONS
+ printf("Needed %d iterations to find initial intersection\n", n);
+#endif
+
+ if (cmp == 0)
+ {
+ Edge* e = intersection->reverse->next;
+#ifdef SHOW_ITERATIONS
+ n = 0;
+#endif
+ while (e->target->dot(normal).compare(shiftedDot) <= 0)
+ {
+#ifdef SHOW_ITERATIONS
+ n++;
+#endif
+ e = e->next;
+ if (e == intersection->reverse)
+ {
+ return true;
+ }
+#ifdef DEBUG_CONVEX_HULL
+ printf("Checking for outwards edge, current edge is ");
+ e->print();
+ printf("\n");
+#endif
+ }
+#ifdef SHOW_ITERATIONS
+ printf("Needed %d iterations to check for complete containment\n", n);
+#endif
+ }
+
+ Edge* firstIntersection = NULL;
+ Edge* faceEdge = NULL;
+ Edge* firstFaceEdge = NULL;
+
+#ifdef SHOW_ITERATIONS
+ int m = 0;
+#endif
+ while (true)
+ {
+#ifdef SHOW_ITERATIONS
+ m++;
+#endif
+#ifdef DEBUG_CONVEX_HULL
+ printf("Intersecting edge is ");
+ intersection->print();
+ printf("\n");
+#endif
+ if (cmp == 0)
+ {
+ Edge* e = intersection->reverse->next;
+ startEdge = e;
+#ifdef SHOW_ITERATIONS
+ n = 0;
+#endif
+ while (true)
+ {
+#ifdef SHOW_ITERATIONS
+ n++;
+#endif
+ if (e->target->dot(normal).compare(shiftedDot) >= 0)
+ {
+ break;
+ }
+ intersection = e->reverse;
+ e = e->next;
+ if (e == startEdge)
+ {
+ return true;
+ }
+ }
+#ifdef SHOW_ITERATIONS
+ printf("Needed %d iterations to advance intersection\n", n);
+#endif
+ }
+
+#ifdef DEBUG_CONVEX_HULL
+ printf("Advanced intersecting edge to ");
+ intersection->print();
+ printf(", cmp = %d\n", cmp);
+#endif
+
+ if (!firstIntersection)
+ {
+ firstIntersection = intersection;
+ }
+ else if (intersection == firstIntersection)
+ {
+ break;
+ }
+
+ int prevCmp = cmp;
+ Edge* prevIntersection = intersection;
+ Edge* prevFaceEdge = faceEdge;
+
+ Edge* e = intersection->reverse;
+#ifdef SHOW_ITERATIONS
+ n = 0;
+#endif
+ while (true)
+ {
+#ifdef SHOW_ITERATIONS
+ n++;
+#endif
+ e = e->reverse->prev;
+ btAssert(e != intersection->reverse);
+ cmp = e->target->dot(normal).compare(shiftedDot);
+#ifdef DEBUG_CONVEX_HULL
+ printf("Testing edge ");
+ e->print();
+ printf(" -> cmp = %d\n", cmp);
+#endif
+ if (cmp >= 0)
+ {
+ intersection = e;
+ break;
+ }
+ }
+#ifdef SHOW_ITERATIONS
+ printf("Needed %d iterations to find other intersection of face\n", n);
+#endif
+
+ if (cmp > 0)
+ {
+ Vertex* removed = intersection->target;
+ e = intersection->reverse;
+ if (e->prev == e)
+ {
+ removed->edges = NULL;
+ }
+ else
+ {
+ removed->edges = e->prev;
+ e->prev->link(e->next);
+ e->link(e);
+ }
+#ifdef DEBUG_CONVEX_HULL
+ printf("1: Removed part contains (%d %d %d)\n", removed->point.x, removed->point.y, removed->point.z);
+#endif
+
+ Point64 n0 = intersection->face->getNormal();
+ Point64 n1 = intersection->reverse->face->getNormal();
+ int64_t m00 = face->dir0.dot(n0);
+ int64_t m01 = face->dir1.dot(n0);
+ int64_t m10 = face->dir0.dot(n1);
+ int64_t m11 = face->dir1.dot(n1);
+ int64_t r0 = (intersection->face->origin - shiftedOrigin).dot(n0);
+ int64_t r1 = (intersection->reverse->face->origin - shiftedOrigin).dot(n1);
+ Int128 det = Int128::mul(m00, m11) - Int128::mul(m01, m10);
+ btAssert(det.getSign() != 0);
+ Vertex* v = vertexPool.newObject();
+ v->point.index = -1;
+ v->copy = -1;
+ v->point128 = PointR128(Int128::mul(face->dir0.x * r0, m11) - Int128::mul(face->dir0.x * r1, m01)
+ + Int128::mul(face->dir1.x * r1, m00) - Int128::mul(face->dir1.x * r0, m10) + det * shiftedOrigin.x,
+ Int128::mul(face->dir0.y * r0, m11) - Int128::mul(face->dir0.y * r1, m01)
+ + Int128::mul(face->dir1.y * r1, m00) - Int128::mul(face->dir1.y * r0, m10) + det * shiftedOrigin.y,
+ Int128::mul(face->dir0.z * r0, m11) - Int128::mul(face->dir0.z * r1, m01)
+ + Int128::mul(face->dir1.z * r1, m00) - Int128::mul(face->dir1.z * r0, m10) + det * shiftedOrigin.z,
+ det);
+ v->point.x = (int32_t) v->point128.xvalue();
+ v->point.y = (int32_t) v->point128.yvalue();
+ v->point.z = (int32_t) v->point128.zvalue();
+ intersection->target = v;
+ v->edges = e;
+
+ stack.push_back(v);
+ stack.push_back(removed);
+ stack.push_back(NULL);
+ }
+
+ if (cmp || prevCmp || (prevIntersection->reverse->next->target != intersection->target))
+ {
+ faceEdge = newEdgePair(prevIntersection->target, intersection->target);
+ if (prevCmp == 0)
+ {
+ faceEdge->link(prevIntersection->reverse->next);
+ }
+ if ((prevCmp == 0) || prevFaceEdge)
+ {
+ prevIntersection->reverse->link(faceEdge);
+ }
+ if (cmp == 0)
+ {
+ intersection->reverse->prev->link(faceEdge->reverse);
+ }
+ faceEdge->reverse->link(intersection->reverse);
+ }
+ else
+ {
+ faceEdge = prevIntersection->reverse->next;
+ }
+
+ if (prevFaceEdge)
+ {
+ if (prevCmp > 0)
+ {
+ faceEdge->link(prevFaceEdge->reverse);
+ }
+ else if (faceEdge != prevFaceEdge->reverse)
+ {
+ stack.push_back(prevFaceEdge->target);
+ while (faceEdge->next != prevFaceEdge->reverse)
+ {
+ Vertex* removed = faceEdge->next->target;
+ removeEdgePair(faceEdge->next);
+ stack.push_back(removed);
+#ifdef DEBUG_CONVEX_HULL
+ printf("2: Removed part contains (%d %d %d)\n", removed->point.x, removed->point.y, removed->point.z);
+#endif
+ }
+ stack.push_back(NULL);
+ }
+ }
+ faceEdge->face = face;
+ faceEdge->reverse->face = intersection->face;
+
+ if (!firstFaceEdge)
+ {
+ firstFaceEdge = faceEdge;
+ }
+ }
+#ifdef SHOW_ITERATIONS
+ printf("Needed %d iterations to process all intersections\n", m);
+#endif
+
+ if (cmp > 0)
+ {
+ firstFaceEdge->reverse->target = faceEdge->target;
+ firstIntersection->reverse->link(firstFaceEdge);
+ firstFaceEdge->link(faceEdge->reverse);
+ }
+ else if (firstFaceEdge != faceEdge->reverse)
+ {
+ stack.push_back(faceEdge->target);
+ while (firstFaceEdge->next != faceEdge->reverse)
+ {
+ Vertex* removed = firstFaceEdge->next->target;
+ removeEdgePair(firstFaceEdge->next);
+ stack.push_back(removed);
+#ifdef DEBUG_CONVEX_HULL
+ printf("3: Removed part contains (%d %d %d)\n", removed->point.x, removed->point.y, removed->point.z);
+#endif
+ }
+ stack.push_back(NULL);
+ }
+
+ btAssert(stack.size() > 0);
+ vertexList = stack[0];
+
+#ifdef DEBUG_CONVEX_HULL
+ printf("Removing part\n");
+#endif
+#ifdef SHOW_ITERATIONS
+ n = 0;
+#endif
+ int pos = 0;
+ while (pos < stack.size())
+ {
+ int end = stack.size();
+ while (pos < end)
+ {
+ Vertex* kept = stack[pos++];
+#ifdef DEBUG_CONVEX_HULL
+ kept->print();
+#endif
+ bool deeper = false;
+ Vertex* removed;
+ while ((removed = stack[pos++]) != NULL)
+ {
+#ifdef SHOW_ITERATIONS
+ n++;
+#endif
+ kept->receiveNearbyFaces(removed);
+ while (removed->edges)
+ {
+ if (!deeper)
+ {
+ deeper = true;
+ stack.push_back(kept);
+ }
+ stack.push_back(removed->edges->target);
+ removeEdgePair(removed->edges);
+ }
+ }
+ if (deeper)
+ {
+ stack.push_back(NULL);
+ }
+ }
+ }
+#ifdef SHOW_ITERATIONS
+ printf("Needed %d iterations to remove part\n", n);
+#endif
+
+ stack.resize(0);
+ face->origin = shiftedOrigin;
+
+ return true;
+}
+
+
+static int getVertexCopy(btConvexHullInternal::Vertex* vertex, btAlignedObjectArray<btConvexHullInternal::Vertex*>& vertices)
+{
+ int index = vertex->copy;
+ if (index < 0)
+ {
+ index = vertices.size();
+ vertex->copy = index;
+ vertices.push_back(vertex);
+#ifdef DEBUG_CONVEX_HULL
+ printf("Vertex %d gets index *%d\n", vertex->point.index, index);
+#endif
+ }
+ return index;
+}
+
+btScalar btConvexHullComputer::compute(const void* coords, bool doubleCoords, int stride, int count, btScalar shrink, btScalar shrinkClamp)
+{
+ if (count <= 0)
+ {
+ vertices.clear();
+ edges.clear();
+ faces.clear();
+ return 0;
+ }
+
+ btConvexHullInternal hull;
+ hull.compute(coords, doubleCoords, stride, count);
+
+ btScalar shift = 0;
+ if ((shrink > 0) && ((shift = hull.shrink(shrink, shrinkClamp)) < 0))
+ {
+ vertices.clear();
+ edges.clear();
+ faces.clear();
+ return shift;
+ }
+
+ vertices.resize(0);
+ edges.resize(0);
+ faces.resize(0);
+
+ btAlignedObjectArray<btConvexHullInternal::Vertex*> oldVertices;
+ getVertexCopy(hull.vertexList, oldVertices);
+ int copied = 0;
+ while (copied < oldVertices.size())
+ {
+ btConvexHullInternal::Vertex* v = oldVertices[copied];
+ vertices.push_back(hull.getCoordinates(v));
+ btConvexHullInternal::Edge* firstEdge = v->edges;
+ if (firstEdge)
+ {
+ int firstCopy = -1;
+ int prevCopy = -1;
+ btConvexHullInternal::Edge* e = firstEdge;
+ do
+ {
+ if (e->copy < 0)
+ {
+ int s = edges.size();
+ edges.push_back(Edge());
+ edges.push_back(Edge());
+ Edge* c = &edges[s];
+ Edge* r = &edges[s + 1];
+ e->copy = s;
+ e->reverse->copy = s + 1;
+ c->reverse = 1;
+ r->reverse = -1;
+ c->targetVertex = getVertexCopy(e->target, oldVertices);
+ r->targetVertex = copied;
+#ifdef DEBUG_CONVEX_HULL
+ printf(" CREATE: Vertex *%d has edge to *%d\n", copied, c->getTargetVertex());
+#endif
+ }
+ if (prevCopy >= 0)
+ {
+ edges[e->copy].next = prevCopy - e->copy;
+ }
+ else
+ {
+ firstCopy = e->copy;
+ }
+ prevCopy = e->copy;
+ e = e->next;
+ } while (e != firstEdge);
+ edges[firstCopy].next = prevCopy - firstCopy;
+ }
+ copied++;
+ }
+
+ for (int i = 0; i < copied; i++)
+ {
+ btConvexHullInternal::Vertex* v = oldVertices[i];
+ btConvexHullInternal::Edge* firstEdge = v->edges;
+ if (firstEdge)
+ {
+ btConvexHullInternal::Edge* e = firstEdge;
+ do
+ {
+ if (e->copy >= 0)
+ {
+#ifdef DEBUG_CONVEX_HULL
+ printf("Vertex *%d has edge to *%d\n", i, edges[e->copy].getTargetVertex());
+#endif
+ faces.push_back(e->copy);
+ btConvexHullInternal::Edge* f = e;
+ do
+ {
+#ifdef DEBUG_CONVEX_HULL
+ printf(" Face *%d\n", edges[f->copy].getTargetVertex());
+#endif
+ f->copy = -1;
+ f = f->reverse->prev;
+ } while (f != e);
+ }
+ e = e->next;
+ } while (e != firstEdge);
+ }
+ }
+
+ return shift;
+}
+
+
+
+
+
diff --git a/thirdparty/bullet/src/LinearMath/btConvexHullComputer.h b/thirdparty/bullet/src/LinearMath/btConvexHullComputer.h
new file mode 100644
index 0000000000..7240ac4fb5
--- /dev/null
+++ b/thirdparty/bullet/src/LinearMath/btConvexHullComputer.h
@@ -0,0 +1,103 @@
+/*
+Copyright (c) 2011 Ole Kniemeyer, MAXON, www.maxon.net
+
+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_CONVEX_HULL_COMPUTER_H
+#define BT_CONVEX_HULL_COMPUTER_H
+
+#include "btVector3.h"
+#include "btAlignedObjectArray.h"
+
+/// Convex hull implementation based on Preparata and Hong
+/// See http://code.google.com/p/bullet/issues/detail?id=275
+/// Ole Kniemeyer, MAXON Computer GmbH
+class btConvexHullComputer
+{
+ private:
+ btScalar compute(const void* coords, bool doubleCoords, int stride, int count, btScalar shrink, btScalar shrinkClamp);
+
+ public:
+
+ class Edge
+ {
+ private:
+ int next;
+ int reverse;
+ int targetVertex;
+
+ friend class btConvexHullComputer;
+
+ public:
+ int getSourceVertex() const
+ {
+ return (this + reverse)->targetVertex;
+ }
+
+ int getTargetVertex() const
+ {
+ return targetVertex;
+ }
+
+ const Edge* getNextEdgeOfVertex() const // clockwise list of all edges of a vertex
+ {
+ return this + next;
+ }
+
+ const Edge* getNextEdgeOfFace() const // counter-clockwise list of all edges of a face
+ {
+ return (this + reverse)->getNextEdgeOfVertex();
+ }
+
+ const Edge* getReverseEdge() const
+ {
+ return this + reverse;
+ }
+ };
+
+
+ // Vertices of the output hull
+ btAlignedObjectArray<btVector3> vertices;
+
+ // Edges of the output hull
+ btAlignedObjectArray<Edge> edges;
+
+ // Faces of the convex hull. Each entry is an index into the "edges" array pointing to an edge of the face. Faces are planar n-gons
+ btAlignedObjectArray<int> faces;
+
+ /*
+ Compute convex hull of "count" vertices stored in "coords". "stride" is the difference in bytes
+ between the addresses of consecutive vertices. If "shrink" is positive, the convex hull is shrunken
+ by that amount (each face is moved by "shrink" length units towards the center along its normal).
+ If "shrinkClamp" is positive, "shrink" is clamped to not exceed "shrinkClamp * innerRadius", where "innerRadius"
+ is the minimum distance of a face to the center of the convex hull.
+
+ The returned value is the amount by which the hull has been shrunken. If it is negative, the amount was so large
+ that the resulting convex hull is empty.
+
+ The output convex hull can be found in the member variables "vertices", "edges", "faces".
+ */
+ btScalar compute(const float* coords, int stride, int count, btScalar shrink, btScalar shrinkClamp)
+ {
+ return compute(coords, false, stride, count, shrink, shrinkClamp);
+ }
+
+ // same as above, but double precision
+ btScalar compute(const double* coords, int stride, int count, btScalar shrink, btScalar shrinkClamp)
+ {
+ return compute(coords, true, stride, count, shrink, shrinkClamp);
+ }
+};
+
+
+#endif //BT_CONVEX_HULL_COMPUTER_H
+
diff --git a/thirdparty/bullet/src/LinearMath/btCpuFeatureUtility.h b/thirdparty/bullet/src/LinearMath/btCpuFeatureUtility.h
new file mode 100644
index 0000000000..d2cab52d48
--- /dev/null
+++ b/thirdparty/bullet/src/LinearMath/btCpuFeatureUtility.h
@@ -0,0 +1,92 @@
+
+#ifndef BT_CPU_UTILITY_H
+#define BT_CPU_UTILITY_H
+
+#include "LinearMath/btScalar.h"
+
+#include <string.h>//memset
+#ifdef USE_SIMD
+#include <emmintrin.h>
+#ifdef BT_ALLOW_SSE4
+#include <intrin.h>
+#endif //BT_ALLOW_SSE4
+#endif //USE_SIMD
+
+#if defined BT_USE_NEON
+#define ARM_NEON_GCC_COMPATIBILITY 1
+#include <arm_neon.h>
+#include <sys/types.h>
+#include <sys/sysctl.h> //for sysctlbyname
+#endif //BT_USE_NEON
+
+///Rudimentary btCpuFeatureUtility for CPU features: only report the features that Bullet actually uses (SSE4/FMA3, NEON_HPFP)
+///We assume SSE2 in case BT_USE_SSE2 is defined in LinearMath/btScalar.h
+class btCpuFeatureUtility
+{
+public:
+ enum btCpuFeature
+ {
+ CPU_FEATURE_FMA3=1,
+ CPU_FEATURE_SSE4_1=2,
+ CPU_FEATURE_NEON_HPFP=4
+ };
+
+ static int getCpuFeatures()
+ {
+
+ static int capabilities = 0;
+ static bool testedCapabilities = false;
+ if (0 != testedCapabilities)
+ {
+ return capabilities;
+ }
+
+#ifdef BT_USE_NEON
+ {
+ uint32_t hasFeature = 0;
+ size_t featureSize = sizeof(hasFeature);
+ int err = sysctlbyname("hw.optional.neon_hpfp", &hasFeature, &featureSize, NULL, 0);
+ if (0 == err && hasFeature)
+ capabilities |= CPU_FEATURE_NEON_HPFP;
+ }
+#endif //BT_USE_NEON
+
+#ifdef BT_ALLOW_SSE4
+ {
+ int cpuInfo[4];
+ memset(cpuInfo, 0, sizeof(cpuInfo));
+ unsigned long long sseExt = 0;
+ __cpuid(cpuInfo, 1);
+
+ bool osUsesXSAVE_XRSTORE = cpuInfo[2] & (1 << 27) || false;
+ bool cpuAVXSuport = cpuInfo[2] & (1 << 28) || false;
+
+ if (osUsesXSAVE_XRSTORE && cpuAVXSuport)
+ {
+ sseExt = _xgetbv(0);
+ }
+ const int OSXSAVEFlag = (1UL << 27);
+ const int AVXFlag = ((1UL << 28) | OSXSAVEFlag);
+ const int FMAFlag = ((1UL << 12) | AVXFlag | OSXSAVEFlag);
+ if ((cpuInfo[2] & FMAFlag) == FMAFlag && (sseExt & 6) == 6)
+ {
+ capabilities |= btCpuFeatureUtility::CPU_FEATURE_FMA3;
+ }
+
+ const int SSE41Flag = (1 << 19);
+ if (cpuInfo[2] & SSE41Flag)
+ {
+ capabilities |= btCpuFeatureUtility::CPU_FEATURE_SSE4_1;
+ }
+ }
+#endif//BT_ALLOW_SSE4
+
+ testedCapabilities = true;
+ return capabilities;
+ }
+
+
+};
+
+
+#endif //BT_CPU_UTILITY_H
diff --git a/thirdparty/bullet/src/LinearMath/btDefaultMotionState.h b/thirdparty/bullet/src/LinearMath/btDefaultMotionState.h
new file mode 100644
index 0000000000..01c5f8d932
--- /dev/null
+++ b/thirdparty/bullet/src/LinearMath/btDefaultMotionState.h
@@ -0,0 +1,42 @@
+#ifndef BT_DEFAULT_MOTION_STATE_H
+#define BT_DEFAULT_MOTION_STATE_H
+
+#include "btMotionState.h"
+
+///The btDefaultMotionState provides a common implementation to synchronize world transforms with offsets.
+ATTRIBUTE_ALIGNED16(struct) btDefaultMotionState : public btMotionState
+{
+ btTransform m_graphicsWorldTrans;
+ btTransform m_centerOfMassOffset;
+ btTransform m_startWorldTrans;
+ void* m_userPointer;
+
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ btDefaultMotionState(const btTransform& startTrans = btTransform::getIdentity(),const btTransform& centerOfMassOffset = btTransform::getIdentity())
+ : m_graphicsWorldTrans(startTrans),
+ m_centerOfMassOffset(centerOfMassOffset),
+ m_startWorldTrans(startTrans),
+ m_userPointer(0)
+
+ {
+ }
+
+ ///synchronizes world transform from user to physics
+ virtual void getWorldTransform(btTransform& centerOfMassWorldTrans ) const
+ {
+ centerOfMassWorldTrans = m_graphicsWorldTrans * m_centerOfMassOffset.inverse() ;
+ }
+
+ ///synchronizes world transform from physics to user
+ ///Bullet only calls the update of worldtransform for active objects
+ virtual void setWorldTransform(const btTransform& centerOfMassWorldTrans)
+ {
+ m_graphicsWorldTrans = centerOfMassWorldTrans * m_centerOfMassOffset;
+ }
+
+
+
+};
+
+#endif //BT_DEFAULT_MOTION_STATE_H
diff --git a/thirdparty/bullet/src/LinearMath/btGeometryUtil.cpp b/thirdparty/bullet/src/LinearMath/btGeometryUtil.cpp
new file mode 100644
index 0000000000..5ac230f712
--- /dev/null
+++ b/thirdparty/bullet/src/LinearMath/btGeometryUtil.cpp
@@ -0,0 +1,185 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+#include "btGeometryUtil.h"
+
+
+/*
+ Make sure this dummy function never changes so that it
+ can be used by probes that are checking whether the
+ library is actually installed.
+*/
+extern "C"
+{
+ void btBulletMathProbe ();
+
+ void btBulletMathProbe () {}
+}
+
+
+bool btGeometryUtil::isPointInsidePlanes(const btAlignedObjectArray<btVector3>& planeEquations, const btVector3& point, btScalar margin)
+{
+ int numbrushes = planeEquations.size();
+ for (int i=0;i<numbrushes;i++)
+ {
+ const btVector3& N1 = planeEquations[i];
+ btScalar dist = btScalar(N1.dot(point))+btScalar(N1[3])-margin;
+ if (dist>btScalar(0.))
+ {
+ return false;
+ }
+ }
+ return true;
+
+}
+
+
+bool btGeometryUtil::areVerticesBehindPlane(const btVector3& planeNormal, const btAlignedObjectArray<btVector3>& vertices, btScalar margin)
+{
+ int numvertices = vertices.size();
+ for (int i=0;i<numvertices;i++)
+ {
+ const btVector3& N1 = vertices[i];
+ btScalar dist = btScalar(planeNormal.dot(N1))+btScalar(planeNormal[3])-margin;
+ if (dist>btScalar(0.))
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool notExist(const btVector3& planeEquation,const btAlignedObjectArray<btVector3>& planeEquations);
+
+bool notExist(const btVector3& planeEquation,const btAlignedObjectArray<btVector3>& planeEquations)
+{
+ int numbrushes = planeEquations.size();
+ for (int i=0;i<numbrushes;i++)
+ {
+ const btVector3& N1 = planeEquations[i];
+ if (planeEquation.dot(N1) > btScalar(0.999))
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+void btGeometryUtil::getPlaneEquationsFromVertices(btAlignedObjectArray<btVector3>& vertices, btAlignedObjectArray<btVector3>& planeEquationsOut )
+{
+ const int numvertices = vertices.size();
+ // brute force:
+ for (int i=0;i<numvertices;i++)
+ {
+ const btVector3& N1 = vertices[i];
+
+
+ for (int j=i+1;j<numvertices;j++)
+ {
+ const btVector3& N2 = vertices[j];
+
+ for (int k=j+1;k<numvertices;k++)
+ {
+
+ const btVector3& N3 = vertices[k];
+
+ btVector3 planeEquation,edge0,edge1;
+ edge0 = N2-N1;
+ edge1 = N3-N1;
+ btScalar normalSign = btScalar(1.);
+ for (int ww=0;ww<2;ww++)
+ {
+ planeEquation = normalSign * edge0.cross(edge1);
+ if (planeEquation.length2() > btScalar(0.0001))
+ {
+ planeEquation.normalize();
+ if (notExist(planeEquation,planeEquationsOut))
+ {
+ planeEquation[3] = -planeEquation.dot(N1);
+
+ //check if inside, and replace supportingVertexOut if needed
+ if (areVerticesBehindPlane(planeEquation,vertices,btScalar(0.01)))
+ {
+ planeEquationsOut.push_back(planeEquation);
+ }
+ }
+ }
+ normalSign = btScalar(-1.);
+ }
+
+ }
+ }
+ }
+
+}
+
+void btGeometryUtil::getVerticesFromPlaneEquations(const btAlignedObjectArray<btVector3>& planeEquations , btAlignedObjectArray<btVector3>& verticesOut )
+{
+ const int numbrushes = planeEquations.size();
+ // brute force:
+ for (int i=0;i<numbrushes;i++)
+ {
+ const btVector3& N1 = planeEquations[i];
+
+
+ for (int j=i+1;j<numbrushes;j++)
+ {
+ const btVector3& N2 = planeEquations[j];
+
+ for (int k=j+1;k<numbrushes;k++)
+ {
+
+ const btVector3& N3 = planeEquations[k];
+
+ btVector3 n2n3; n2n3 = N2.cross(N3);
+ btVector3 n3n1; n3n1 = N3.cross(N1);
+ btVector3 n1n2; n1n2 = N1.cross(N2);
+
+ if ( ( n2n3.length2() > btScalar(0.0001) ) &&
+ ( n3n1.length2() > btScalar(0.0001) ) &&
+ ( n1n2.length2() > btScalar(0.0001) ) )
+ {
+ //point P out of 3 plane equations:
+
+ // d1 ( N2 * N3 ) + d2 ( N3 * N1 ) + d3 ( N1 * N2 )
+ //P = -------------------------------------------------------------------------
+ // N1 . ( N2 * N3 )
+
+
+ btScalar quotient = (N1.dot(n2n3));
+ if (btFabs(quotient) > btScalar(0.000001))
+ {
+ quotient = btScalar(-1.) / quotient;
+ n2n3 *= N1[3];
+ n3n1 *= N2[3];
+ n1n2 *= N3[3];
+ btVector3 potentialVertex = n2n3;
+ potentialVertex += n3n1;
+ potentialVertex += n1n2;
+ potentialVertex *= quotient;
+
+ //check if inside, and replace supportingVertexOut if needed
+ if (isPointInsidePlanes(planeEquations,potentialVertex,btScalar(0.01)))
+ {
+ verticesOut.push_back(potentialVertex);
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
diff --git a/thirdparty/bullet/src/LinearMath/btGeometryUtil.h b/thirdparty/bullet/src/LinearMath/btGeometryUtil.h
new file mode 100644
index 0000000000..a4b13b4560
--- /dev/null
+++ b/thirdparty/bullet/src/LinearMath/btGeometryUtil.h
@@ -0,0 +1,42 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#ifndef BT_GEOMETRY_UTIL_H
+#define BT_GEOMETRY_UTIL_H
+
+#include "btVector3.h"
+#include "btAlignedObjectArray.h"
+
+///The btGeometryUtil helper class provides a few methods to convert between plane equations and vertices.
+class btGeometryUtil
+{
+ public:
+
+
+ static void getPlaneEquationsFromVertices(btAlignedObjectArray<btVector3>& vertices, btAlignedObjectArray<btVector3>& planeEquationsOut );
+
+ static void getVerticesFromPlaneEquations(const btAlignedObjectArray<btVector3>& planeEquations , btAlignedObjectArray<btVector3>& verticesOut );
+
+ static bool isInside(const btAlignedObjectArray<btVector3>& vertices, const btVector3& planeNormal, btScalar margin);
+
+ static bool isPointInsidePlanes(const btAlignedObjectArray<btVector3>& planeEquations, const btVector3& point, btScalar margin);
+
+ static bool areVerticesBehindPlane(const btVector3& planeNormal, const btAlignedObjectArray<btVector3>& vertices, btScalar margin);
+
+};
+
+
+#endif //BT_GEOMETRY_UTIL_H
+
diff --git a/thirdparty/bullet/src/LinearMath/btGrahamScan2dConvexHull.h b/thirdparty/bullet/src/LinearMath/btGrahamScan2dConvexHull.h
new file mode 100644
index 0000000000..13a79aa585
--- /dev/null
+++ b/thirdparty/bullet/src/LinearMath/btGrahamScan2dConvexHull.h
@@ -0,0 +1,130 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2011 Advanced Micro Devices, 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 GRAHAM_SCAN_2D_CONVEX_HULL_H
+#define GRAHAM_SCAN_2D_CONVEX_HULL_H
+
+
+#include "btVector3.h"
+#include "btAlignedObjectArray.h"
+
+struct GrahamVector3 : public btVector3
+{
+ GrahamVector3(const btVector3& org, int orgIndex)
+ :btVector3(org),
+ m_orgIndex(orgIndex)
+ {
+ }
+ btScalar m_angle;
+ int m_orgIndex;
+};
+
+
+struct btAngleCompareFunc {
+ btVector3 m_anchor;
+ btAngleCompareFunc(const btVector3& anchor)
+ : m_anchor(anchor)
+ {
+ }
+ bool operator()(const GrahamVector3& a, const GrahamVector3& b) const {
+ if (a.m_angle != b.m_angle)
+ return a.m_angle < b.m_angle;
+ else
+ {
+ btScalar al = (a-m_anchor).length2();
+ btScalar bl = (b-m_anchor).length2();
+ if (al != bl)
+ return al < bl;
+ else
+ {
+ return a.m_orgIndex < b.m_orgIndex;
+ }
+ }
+ }
+};
+
+inline void GrahamScanConvexHull2D(btAlignedObjectArray<GrahamVector3>& originalPoints, btAlignedObjectArray<GrahamVector3>& hull, const btVector3& normalAxis)
+{
+ btVector3 axis0,axis1;
+ btPlaneSpace1(normalAxis,axis0,axis1);
+
+
+ if (originalPoints.size()<=1)
+ {
+ for (int i=0;i<originalPoints.size();i++)
+ hull.push_back(originalPoints[0]);
+ return;
+ }
+ //step1 : find anchor point with smallest projection on axis0 and move it to first location
+ for (int i=0;i<originalPoints.size();i++)
+ {
+// const btVector3& left = originalPoints[i];
+// const btVector3& right = originalPoints[0];
+ btScalar projL = originalPoints[i].dot(axis0);
+ btScalar projR = originalPoints[0].dot(axis0);
+ if (projL < projR)
+ {
+ originalPoints.swap(0,i);
+ }
+ }
+
+ //also precompute angles
+ originalPoints[0].m_angle = -1e30f;
+ for (int i=1;i<originalPoints.size();i++)
+ {
+ btVector3 ar = originalPoints[i]-originalPoints[0];
+ btScalar ar1 = axis1.dot(ar);
+ btScalar ar0 = axis0.dot(ar);
+ if( ar1*ar1+ar0*ar0 < FLT_EPSILON )
+ {
+ originalPoints[i].m_angle = 0.0f;
+ }
+ else
+ {
+ originalPoints[i].m_angle = btAtan2Fast(ar1, ar0);
+ }
+ }
+
+ //step 2: sort all points, based on 'angle' with this anchor
+ btAngleCompareFunc comp(originalPoints[0]);
+ originalPoints.quickSortInternal(comp,1,originalPoints.size()-1);
+
+ int i;
+ for (i = 0; i<2; i++)
+ hull.push_back(originalPoints[i]);
+
+ //step 3: keep all 'convex' points and discard concave points (using back tracking)
+ for (; i != originalPoints.size(); i++)
+ {
+ bool isConvex = false;
+ while (!isConvex&& hull.size()>1) {
+ btVector3& a = hull[hull.size()-2];
+ btVector3& b = hull[hull.size()-1];
+ isConvex = btCross(a-b,a-originalPoints[i]).dot(normalAxis)> 0;
+ if (!isConvex)
+ hull.pop_back();
+ else
+ hull.push_back(originalPoints[i]);
+ }
+
+ if( hull.size() == 1 )
+ {
+ hull.push_back( originalPoints[i] );
+ }
+ }
+}
+
+#endif //GRAHAM_SCAN_2D_CONVEX_HULL_H
diff --git a/thirdparty/bullet/src/LinearMath/btHashMap.h b/thirdparty/bullet/src/LinearMath/btHashMap.h
new file mode 100644
index 0000000000..5e9cdb6054
--- /dev/null
+++ b/thirdparty/bullet/src/LinearMath/btHashMap.h
@@ -0,0 +1,482 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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_HASH_MAP_H
+#define BT_HASH_MAP_H
+
+#include "btAlignedObjectArray.h"
+
+///very basic hashable string implementation, compatible with btHashMap
+struct btHashString
+{
+ const char* m_string;
+ unsigned int m_hash;
+
+ SIMD_FORCE_INLINE unsigned int getHash()const
+ {
+ return m_hash;
+ }
+
+ btHashString(const char* name)
+ :m_string(name)
+ {
+ /* magic numbers from http://www.isthe.com/chongo/tech/comp/fnv/ */
+ static const unsigned int InitialFNV = 2166136261u;
+ static const unsigned int FNVMultiple = 16777619u;
+
+ /* Fowler / Noll / Vo (FNV) Hash */
+ unsigned int hash = InitialFNV;
+
+ for(int i = 0; m_string[i]; i++)
+ {
+ hash = hash ^ (m_string[i]); /* xor the low 8 bits */
+ hash = hash * FNVMultiple; /* multiply by the magic number */
+ }
+ m_hash = hash;
+ }
+
+ int portableStringCompare(const char* src, const char* dst) const
+ {
+ int ret = 0 ;
+
+ while( ! (ret = *(const unsigned char *)src - *(const unsigned char *)dst) && *dst)
+ ++src, ++dst;
+
+ if ( ret < 0 )
+ ret = -1 ;
+ else if ( ret > 0 )
+ ret = 1 ;
+
+ return( ret );
+ }
+
+ bool equals(const btHashString& other) const
+ {
+ return (m_string == other.m_string) ||
+ (0==portableStringCompare(m_string,other.m_string));
+
+ }
+
+};
+
+const int BT_HASH_NULL=0xffffffff;
+
+
+class btHashInt
+{
+ int m_uid;
+public:
+
+ btHashInt()
+ {
+ }
+
+ btHashInt(int uid) :m_uid(uid)
+ {
+ }
+
+ int getUid1() const
+ {
+ return m_uid;
+ }
+
+ void setUid1(int uid)
+ {
+ m_uid = uid;
+ }
+
+ bool equals(const btHashInt& other) const
+ {
+ return getUid1() == other.getUid1();
+ }
+ //to our success
+ SIMD_FORCE_INLINE unsigned int getHash()const
+ {
+ unsigned int key = m_uid;
+ // Thomas Wang's hash
+ key += ~(key << 15); key ^= (key >> 10); key += (key << 3); key ^= (key >> 6); key += ~(key << 11); key ^= (key >> 16);
+
+ return key;
+ }
+};
+
+
+
+class btHashPtr
+{
+
+ union
+ {
+ const void* m_pointer;
+ unsigned int m_hashValues[2];
+ };
+
+public:
+
+ btHashPtr(const void* ptr)
+ :m_pointer(ptr)
+ {
+ }
+
+ const void* getPointer() const
+ {
+ return m_pointer;
+ }
+
+ bool equals(const btHashPtr& other) const
+ {
+ return getPointer() == other.getPointer();
+ }
+
+ //to our success
+ SIMD_FORCE_INLINE unsigned int getHash()const
+ {
+ const bool VOID_IS_8 = ((sizeof(void*)==8));
+
+ unsigned int key = VOID_IS_8? m_hashValues[0]+m_hashValues[1] : m_hashValues[0];
+ // Thomas Wang's hash
+ key += ~(key << 15); key ^= (key >> 10); key += (key << 3); key ^= (key >> 6); key += ~(key << 11); key ^= (key >> 16);
+ return key;
+ }
+
+
+};
+
+
+template <class Value>
+class btHashKeyPtr
+{
+ int m_uid;
+public:
+
+ btHashKeyPtr(int uid) :m_uid(uid)
+ {
+ }
+
+ int getUid1() const
+ {
+ return m_uid;
+ }
+
+ bool equals(const btHashKeyPtr<Value>& other) const
+ {
+ return getUid1() == other.getUid1();
+ }
+
+ //to our success
+ SIMD_FORCE_INLINE unsigned int getHash()const
+ {
+ unsigned int key = m_uid;
+ // Thomas Wang's hash
+ key += ~(key << 15); key ^= (key >> 10); key += (key << 3); key ^= (key >> 6); key += ~(key << 11); key ^= (key >> 16);
+ return key;
+ }
+
+
+};
+
+
+template <class Value>
+class btHashKey
+{
+ int m_uid;
+public:
+
+ btHashKey(int uid) :m_uid(uid)
+ {
+ }
+
+ int getUid1() const
+ {
+ return m_uid;
+ }
+
+ bool equals(const btHashKey<Value>& other) const
+ {
+ return getUid1() == other.getUid1();
+ }
+ //to our success
+ SIMD_FORCE_INLINE unsigned int getHash()const
+ {
+ unsigned int key = m_uid;
+ // Thomas Wang's hash
+ key += ~(key << 15); key ^= (key >> 10); key += (key << 3); key ^= (key >> 6); key += ~(key << 11); key ^= (key >> 16);
+ return key;
+ }
+};
+
+
+///The btHashMap template class implements a generic and lightweight hashmap.
+///A basic sample of how to use btHashMap is located in Demos\BasicDemo\main.cpp
+template <class Key, class Value>
+class btHashMap
+{
+
+protected:
+ btAlignedObjectArray<int> m_hashTable;
+ btAlignedObjectArray<int> m_next;
+
+ btAlignedObjectArray<Value> m_valueArray;
+ btAlignedObjectArray<Key> m_keyArray;
+
+ void growTables(const Key& /*key*/)
+ {
+ int newCapacity = m_valueArray.capacity();
+
+ if (m_hashTable.size() < newCapacity)
+ {
+ //grow hashtable and next table
+ int curHashtableSize = m_hashTable.size();
+
+ m_hashTable.resize(newCapacity);
+ m_next.resize(newCapacity);
+
+ int i;
+
+ for (i= 0; i < newCapacity; ++i)
+ {
+ m_hashTable[i] = BT_HASH_NULL;
+ }
+ for (i = 0; i < newCapacity; ++i)
+ {
+ m_next[i] = BT_HASH_NULL;
+ }
+
+ for(i=0;i<curHashtableSize;i++)
+ {
+ //const Value& value = m_valueArray[i];
+ //const Key& key = m_keyArray[i];
+
+ int hashValue = m_keyArray[i].getHash() & (m_valueArray.capacity()-1); // New hash value with new mask
+ m_next[i] = m_hashTable[hashValue];
+ m_hashTable[hashValue] = i;
+ }
+
+
+ }
+ }
+
+ public:
+
+ void insert(const Key& key, const Value& value) {
+ int hash = key.getHash() & (m_valueArray.capacity()-1);
+
+ //replace value if the key is already there
+ int index = findIndex(key);
+ if (index != BT_HASH_NULL)
+ {
+ m_valueArray[index]=value;
+ return;
+ }
+
+ int count = m_valueArray.size();
+ int oldCapacity = m_valueArray.capacity();
+ m_valueArray.push_back(value);
+ m_keyArray.push_back(key);
+
+ int newCapacity = m_valueArray.capacity();
+ if (oldCapacity < newCapacity)
+ {
+ growTables(key);
+ //hash with new capacity
+ hash = key.getHash() & (m_valueArray.capacity()-1);
+ }
+ m_next[count] = m_hashTable[hash];
+ m_hashTable[hash] = count;
+ }
+
+ void remove(const Key& key) {
+
+ int hash = key.getHash() & (m_valueArray.capacity()-1);
+
+ int pairIndex = findIndex(key);
+
+ if (pairIndex ==BT_HASH_NULL)
+ {
+ return;
+ }
+
+ // Remove the pair from the hash table.
+ int index = m_hashTable[hash];
+ btAssert(index != BT_HASH_NULL);
+
+ int previous = BT_HASH_NULL;
+ while (index != pairIndex)
+ {
+ previous = index;
+ index = m_next[index];
+ }
+
+ if (previous != BT_HASH_NULL)
+ {
+ btAssert(m_next[previous] == pairIndex);
+ m_next[previous] = m_next[pairIndex];
+ }
+ else
+ {
+ m_hashTable[hash] = m_next[pairIndex];
+ }
+
+ // We now move the last pair into spot of the
+ // pair being removed. We need to fix the hash
+ // table indices to support the move.
+
+ int lastPairIndex = m_valueArray.size() - 1;
+
+ // If the removed pair is the last pair, we are done.
+ if (lastPairIndex == pairIndex)
+ {
+ m_valueArray.pop_back();
+ m_keyArray.pop_back();
+ return;
+ }
+
+ // Remove the last pair from the hash table.
+ int lastHash = m_keyArray[lastPairIndex].getHash() & (m_valueArray.capacity()-1);
+
+ index = m_hashTable[lastHash];
+ btAssert(index != BT_HASH_NULL);
+
+ previous = BT_HASH_NULL;
+ while (index != lastPairIndex)
+ {
+ previous = index;
+ index = m_next[index];
+ }
+
+ if (previous != BT_HASH_NULL)
+ {
+ btAssert(m_next[previous] == lastPairIndex);
+ m_next[previous] = m_next[lastPairIndex];
+ }
+ else
+ {
+ m_hashTable[lastHash] = m_next[lastPairIndex];
+ }
+
+ // Copy the last pair into the remove pair's spot.
+ m_valueArray[pairIndex] = m_valueArray[lastPairIndex];
+ m_keyArray[pairIndex] = m_keyArray[lastPairIndex];
+
+ // Insert the last pair into the hash table
+ m_next[pairIndex] = m_hashTable[lastHash];
+ m_hashTable[lastHash] = pairIndex;
+
+ m_valueArray.pop_back();
+ m_keyArray.pop_back();
+
+ }
+
+
+ int size() const
+ {
+ return m_valueArray.size();
+ }
+
+ const Value* getAtIndex(int index) const
+ {
+ btAssert(index < m_valueArray.size());
+ btAssert(index>=0);
+ if (index>=0 && index < m_valueArray.size())
+ {
+ return &m_valueArray[index];
+ }
+ return 0;
+ }
+
+ Value* getAtIndex(int index)
+ {
+ btAssert(index < m_valueArray.size());
+ btAssert(index>=0);
+ if (index>=0 && index < m_valueArray.size())
+ {
+ return &m_valueArray[index];
+ }
+ return 0;
+ }
+
+ Key getKeyAtIndex(int index)
+ {
+ btAssert(index < m_keyArray.size());
+ btAssert(index>=0);
+ return m_keyArray[index];
+ }
+
+ const Key getKeyAtIndex(int index) const
+ {
+ btAssert(index < m_keyArray.size());
+ btAssert(index>=0);
+ return m_keyArray[index];
+ }
+
+
+ Value* operator[](const Key& key) {
+ return find(key);
+ }
+
+ const Value* operator[](const Key& key) const {
+ return find(key);
+ }
+
+ const Value* find(const Key& key) const
+ {
+ int index = findIndex(key);
+ if (index == BT_HASH_NULL)
+ {
+ return NULL;
+ }
+ return &m_valueArray[index];
+ }
+
+ Value* find(const Key& key)
+ {
+ int index = findIndex(key);
+ if (index == BT_HASH_NULL)
+ {
+ return NULL;
+ }
+ return &m_valueArray[index];
+ }
+
+
+ int findIndex(const Key& key) const
+ {
+ unsigned int hash = key.getHash() & (m_valueArray.capacity()-1);
+
+ if (hash >= (unsigned int)m_hashTable.size())
+ {
+ return BT_HASH_NULL;
+ }
+
+ int index = m_hashTable[hash];
+ while ((index != BT_HASH_NULL) && key.equals(m_keyArray[index]) == false)
+ {
+ index = m_next[index];
+ }
+ return index;
+ }
+
+ void clear()
+ {
+ m_hashTable.clear();
+ m_next.clear();
+ m_valueArray.clear();
+ m_keyArray.clear();
+ }
+
+};
+
+#endif //BT_HASH_MAP_H
diff --git a/thirdparty/bullet/src/LinearMath/btIDebugDraw.h b/thirdparty/bullet/src/LinearMath/btIDebugDraw.h
new file mode 100644
index 0000000000..936aaa896b
--- /dev/null
+++ b/thirdparty/bullet/src/LinearMath/btIDebugDraw.h
@@ -0,0 +1,483 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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_IDEBUG_DRAW__H
+#define BT_IDEBUG_DRAW__H
+
+#include "btVector3.h"
+#include "btTransform.h"
+
+
+
+///The btIDebugDraw interface class allows hooking up a debug renderer to visually debug simulations.
+///Typical use case: create a debug drawer object, and assign it to a btCollisionWorld or btDynamicsWorld using setDebugDrawer and call debugDrawWorld.
+///A class that implements the btIDebugDraw interface has to implement the drawLine method at a minimum.
+///For color arguments the X,Y,Z components refer to Red, Green and Blue each in the range [0..1]
+class btIDebugDraw
+{
+ public:
+
+ ATTRIBUTE_ALIGNED16(struct) DefaultColors
+ {
+ btVector3 m_activeObject;
+ btVector3 m_deactivatedObject;
+ btVector3 m_wantsDeactivationObject;
+ btVector3 m_disabledDeactivationObject;
+ btVector3 m_disabledSimulationObject;
+ btVector3 m_aabb;
+ btVector3 m_contactPoint;
+
+ DefaultColors()
+ : m_activeObject(1,1,1),
+ m_deactivatedObject(0,1,0),
+ m_wantsDeactivationObject(0,1,1),
+ m_disabledDeactivationObject(1,0,0),
+ m_disabledSimulationObject(1,1,0),
+ m_aabb(1,0,0),
+ m_contactPoint(1,1,0)
+ {
+ }
+ };
+
+
+ enum DebugDrawModes
+ {
+ DBG_NoDebug=0,
+ DBG_DrawWireframe = 1,
+ DBG_DrawAabb=2,
+ DBG_DrawFeaturesText=4,
+ DBG_DrawContactPoints=8,
+ DBG_NoDeactivation=16,
+ DBG_NoHelpText = 32,
+ DBG_DrawText=64,
+ DBG_ProfileTimings = 128,
+ DBG_EnableSatComparison = 256,
+ DBG_DisableBulletLCP = 512,
+ DBG_EnableCCD = 1024,
+ DBG_DrawConstraints = (1 << 11),
+ DBG_DrawConstraintLimits = (1 << 12),
+ DBG_FastWireframe = (1<<13),
+ DBG_DrawNormals = (1<<14),
+ DBG_DrawFrames = (1<<15),
+ DBG_MAX_DEBUG_DRAW_MODE
+ };
+
+ virtual ~btIDebugDraw() {};
+
+
+ virtual DefaultColors getDefaultColors() const { DefaultColors colors; return colors; }
+ ///the default implementation for setDefaultColors has no effect. A derived class can implement it and store the colors.
+ virtual void setDefaultColors(const DefaultColors& /*colors*/) {}
+
+ virtual void drawLine(const btVector3& from,const btVector3& to,const btVector3& color)=0;
+
+ virtual void drawLine(const btVector3& from,const btVector3& to, const btVector3& fromColor, const btVector3& toColor)
+ {
+ (void) toColor;
+ drawLine (from, to, fromColor);
+ }
+
+ virtual void drawSphere(btScalar radius, const btTransform& transform, const btVector3& color)
+ {
+
+ btVector3 center = transform.getOrigin();
+ btVector3 up = transform.getBasis().getColumn(1);
+ btVector3 axis = transform.getBasis().getColumn(0);
+ btScalar minTh = -SIMD_HALF_PI;
+ btScalar maxTh = SIMD_HALF_PI;
+ btScalar minPs = -SIMD_HALF_PI;
+ btScalar maxPs = SIMD_HALF_PI;
+ btScalar stepDegrees = 30.f;
+ drawSpherePatch(center, up, axis, radius,minTh, maxTh, minPs, maxPs, color, stepDegrees ,false);
+ drawSpherePatch(center, up, -axis, radius,minTh, maxTh, minPs, maxPs, color, stepDegrees,false );
+ }
+
+ virtual void drawSphere (const btVector3& p, btScalar radius, const btVector3& color)
+ {
+ btTransform tr;
+ tr.setIdentity();
+ tr.setOrigin(p);
+ drawSphere(radius,tr,color);
+ }
+
+ virtual void drawTriangle(const btVector3& v0,const btVector3& v1,const btVector3& v2,const btVector3& /*n0*/,const btVector3& /*n1*/,const btVector3& /*n2*/,const btVector3& color, btScalar alpha)
+ {
+ drawTriangle(v0,v1,v2,color,alpha);
+ }
+ virtual void drawTriangle(const btVector3& v0,const btVector3& v1,const btVector3& v2,const btVector3& color, btScalar /*alpha*/)
+ {
+ drawLine(v0,v1,color);
+ drawLine(v1,v2,color);
+ drawLine(v2,v0,color);
+ }
+
+ virtual void drawContactPoint(const btVector3& PointOnB,const btVector3& normalOnB,btScalar distance,int lifeTime,const btVector3& color)=0;
+
+ virtual void reportErrorWarning(const char* warningString) = 0;
+
+ virtual void draw3dText(const btVector3& location,const char* textString) = 0;
+
+ virtual void setDebugMode(int debugMode) =0;
+
+ virtual int getDebugMode() const = 0;
+
+ virtual void drawAabb(const btVector3& from,const btVector3& to,const btVector3& color)
+ {
+
+ btVector3 halfExtents = (to-from)* 0.5f;
+ btVector3 center = (to+from) *0.5f;
+ int i,j;
+
+ btVector3 edgecoord(1.f,1.f,1.f),pa,pb;
+ for (i=0;i<4;i++)
+ {
+ for (j=0;j<3;j++)
+ {
+ pa = btVector3(edgecoord[0]*halfExtents[0], edgecoord[1]*halfExtents[1],
+ edgecoord[2]*halfExtents[2]);
+ pa+=center;
+
+ int othercoord = j%3;
+ edgecoord[othercoord]*=-1.f;
+ pb = btVector3(edgecoord[0]*halfExtents[0], edgecoord[1]*halfExtents[1],
+ edgecoord[2]*halfExtents[2]);
+ pb+=center;
+
+ drawLine(pa,pb,color);
+ }
+ edgecoord = btVector3(-1.f,-1.f,-1.f);
+ if (i<3)
+ edgecoord[i]*=-1.f;
+ }
+ }
+ virtual void drawTransform(const btTransform& transform, btScalar orthoLen)
+ {
+ btVector3 start = transform.getOrigin();
+ drawLine(start, start+transform.getBasis() * btVector3(orthoLen, 0, 0), btVector3(1.f,0.3,0.3));
+ drawLine(start, start+transform.getBasis() * btVector3(0, orthoLen, 0), btVector3(0.3,1.f, 0.3));
+ drawLine(start, start+transform.getBasis() * btVector3(0, 0, orthoLen), btVector3(0.3, 0.3,1.f));
+ }
+
+ virtual void drawArc(const btVector3& center, const btVector3& normal, const btVector3& axis, btScalar radiusA, btScalar radiusB, btScalar minAngle, btScalar maxAngle,
+ const btVector3& color, bool drawSect, btScalar stepDegrees = btScalar(10.f))
+ {
+ const btVector3& vx = axis;
+ btVector3 vy = normal.cross(axis);
+ btScalar step = stepDegrees * SIMD_RADS_PER_DEG;
+ int nSteps = (int)btFabs((maxAngle - minAngle) / step);
+ if(!nSteps) nSteps = 1;
+ btVector3 prev = center + radiusA * vx * btCos(minAngle) + radiusB * vy * btSin(minAngle);
+ if(drawSect)
+ {
+ drawLine(center, prev, color);
+ }
+ for(int i = 1; i <= nSteps; i++)
+ {
+ btScalar angle = minAngle + (maxAngle - minAngle) * btScalar(i) / btScalar(nSteps);
+ btVector3 next = center + radiusA * vx * btCos(angle) + radiusB * vy * btSin(angle);
+ drawLine(prev, next, color);
+ prev = next;
+ }
+ if(drawSect)
+ {
+ drawLine(center, prev, color);
+ }
+ }
+ virtual void drawSpherePatch(const btVector3& center, const btVector3& up, const btVector3& axis, btScalar radius,
+ btScalar minTh, btScalar maxTh, btScalar minPs, btScalar maxPs, const btVector3& color, btScalar stepDegrees = btScalar(10.f),bool drawCenter = true)
+ {
+ btVector3 vA[74];
+ btVector3 vB[74];
+ btVector3 *pvA = vA, *pvB = vB, *pT;
+ btVector3 npole = center + up * radius;
+ btVector3 spole = center - up * radius;
+ btVector3 arcStart;
+ btScalar step = stepDegrees * SIMD_RADS_PER_DEG;
+ const btVector3& kv = up;
+ const btVector3& iv = axis;
+ btVector3 jv = kv.cross(iv);
+ bool drawN = false;
+ bool drawS = false;
+ if(minTh <= -SIMD_HALF_PI)
+ {
+ minTh = -SIMD_HALF_PI + step;
+ drawN = true;
+ }
+ if(maxTh >= SIMD_HALF_PI)
+ {
+ maxTh = SIMD_HALF_PI - step;
+ drawS = true;
+ }
+ if(minTh > maxTh)
+ {
+ minTh = -SIMD_HALF_PI + step;
+ maxTh = SIMD_HALF_PI - step;
+ drawN = drawS = true;
+ }
+ int n_hor = (int)((maxTh - minTh) / step) + 1;
+ if(n_hor < 2) n_hor = 2;
+ btScalar step_h = (maxTh - minTh) / btScalar(n_hor - 1);
+ bool isClosed = false;
+ if(minPs > maxPs)
+ {
+ minPs = -SIMD_PI + step;
+ maxPs = SIMD_PI;
+ isClosed = true;
+ }
+ else if((maxPs - minPs) >= SIMD_PI * btScalar(2.f))
+ {
+ isClosed = true;
+ }
+ else
+ {
+ isClosed = false;
+ }
+ int n_vert = (int)((maxPs - minPs) / step) + 1;
+ if(n_vert < 2) n_vert = 2;
+ btScalar step_v = (maxPs - minPs) / btScalar(n_vert - 1);
+ for(int i = 0; i < n_hor; i++)
+ {
+ btScalar th = minTh + btScalar(i) * step_h;
+ btScalar sth = radius * btSin(th);
+ btScalar cth = radius * btCos(th);
+ for(int j = 0; j < n_vert; j++)
+ {
+ btScalar psi = minPs + btScalar(j) * step_v;
+ btScalar sps = btSin(psi);
+ btScalar cps = btCos(psi);
+ pvB[j] = center + cth * cps * iv + cth * sps * jv + sth * kv;
+ if(i)
+ {
+ drawLine(pvA[j], pvB[j], color);
+ }
+ else if(drawS)
+ {
+ drawLine(spole, pvB[j], color);
+ }
+ if(j)
+ {
+ drawLine(pvB[j-1], pvB[j], color);
+ }
+ else
+ {
+ arcStart = pvB[j];
+ }
+ if((i == (n_hor - 1)) && drawN)
+ {
+ drawLine(npole, pvB[j], color);
+ }
+
+ if (drawCenter)
+ {
+ if(isClosed)
+ {
+ if(j == (n_vert-1))
+ {
+ drawLine(arcStart, pvB[j], color);
+ }
+ }
+ else
+ {
+ if(((!i) || (i == (n_hor-1))) && ((!j) || (j == (n_vert-1))))
+ {
+ drawLine(center, pvB[j], color);
+ }
+ }
+ }
+ }
+ pT = pvA; pvA = pvB; pvB = pT;
+ }
+ }
+
+
+ virtual void drawBox(const btVector3& bbMin, const btVector3& bbMax, const btVector3& color)
+ {
+ drawLine(btVector3(bbMin[0], bbMin[1], bbMin[2]), btVector3(bbMax[0], bbMin[1], bbMin[2]), color);
+ drawLine(btVector3(bbMax[0], bbMin[1], bbMin[2]), btVector3(bbMax[0], bbMax[1], bbMin[2]), color);
+ drawLine(btVector3(bbMax[0], bbMax[1], bbMin[2]), btVector3(bbMin[0], bbMax[1], bbMin[2]), color);
+ drawLine(btVector3(bbMin[0], bbMax[1], bbMin[2]), btVector3(bbMin[0], bbMin[1], bbMin[2]), color);
+ drawLine(btVector3(bbMin[0], bbMin[1], bbMin[2]), btVector3(bbMin[0], bbMin[1], bbMax[2]), color);
+ drawLine(btVector3(bbMax[0], bbMin[1], bbMin[2]), btVector3(bbMax[0], bbMin[1], bbMax[2]), color);
+ drawLine(btVector3(bbMax[0], bbMax[1], bbMin[2]), btVector3(bbMax[0], bbMax[1], bbMax[2]), color);
+ drawLine(btVector3(bbMin[0], bbMax[1], bbMin[2]), btVector3(bbMin[0], bbMax[1], bbMax[2]), color);
+ drawLine(btVector3(bbMin[0], bbMin[1], bbMax[2]), btVector3(bbMax[0], bbMin[1], bbMax[2]), color);
+ drawLine(btVector3(bbMax[0], bbMin[1], bbMax[2]), btVector3(bbMax[0], bbMax[1], bbMax[2]), color);
+ drawLine(btVector3(bbMax[0], bbMax[1], bbMax[2]), btVector3(bbMin[0], bbMax[1], bbMax[2]), color);
+ drawLine(btVector3(bbMin[0], bbMax[1], bbMax[2]), btVector3(bbMin[0], bbMin[1], bbMax[2]), color);
+ }
+ virtual void drawBox(const btVector3& bbMin, const btVector3& bbMax, const btTransform& trans, const btVector3& color)
+ {
+ drawLine(trans * btVector3(bbMin[0], bbMin[1], bbMin[2]), trans * btVector3(bbMax[0], bbMin[1], bbMin[2]), color);
+ drawLine(trans * btVector3(bbMax[0], bbMin[1], bbMin[2]), trans * btVector3(bbMax[0], bbMax[1], bbMin[2]), color);
+ drawLine(trans * btVector3(bbMax[0], bbMax[1], bbMin[2]), trans * btVector3(bbMin[0], bbMax[1], bbMin[2]), color);
+ drawLine(trans * btVector3(bbMin[0], bbMax[1], bbMin[2]), trans * btVector3(bbMin[0], bbMin[1], bbMin[2]), color);
+ drawLine(trans * btVector3(bbMin[0], bbMin[1], bbMin[2]), trans * btVector3(bbMin[0], bbMin[1], bbMax[2]), color);
+ drawLine(trans * btVector3(bbMax[0], bbMin[1], bbMin[2]), trans * btVector3(bbMax[0], bbMin[1], bbMax[2]), color);
+ drawLine(trans * btVector3(bbMax[0], bbMax[1], bbMin[2]), trans * btVector3(bbMax[0], bbMax[1], bbMax[2]), color);
+ drawLine(trans * btVector3(bbMin[0], bbMax[1], bbMin[2]), trans * btVector3(bbMin[0], bbMax[1], bbMax[2]), color);
+ drawLine(trans * btVector3(bbMin[0], bbMin[1], bbMax[2]), trans * btVector3(bbMax[0], bbMin[1], bbMax[2]), color);
+ drawLine(trans * btVector3(bbMax[0], bbMin[1], bbMax[2]), trans * btVector3(bbMax[0], bbMax[1], bbMax[2]), color);
+ drawLine(trans * btVector3(bbMax[0], bbMax[1], bbMax[2]), trans * btVector3(bbMin[0], bbMax[1], bbMax[2]), color);
+ drawLine(trans * btVector3(bbMin[0], bbMax[1], bbMax[2]), trans * btVector3(bbMin[0], bbMin[1], bbMax[2]), color);
+ }
+
+ virtual void drawCapsule(btScalar radius, btScalar halfHeight, int upAxis, const btTransform& transform, const btVector3& color)
+ {
+ int stepDegrees = 30;
+
+ btVector3 capStart(0.f,0.f,0.f);
+ capStart[upAxis] = -halfHeight;
+
+ btVector3 capEnd(0.f,0.f,0.f);
+ capEnd[upAxis] = halfHeight;
+
+ // Draw the ends
+ {
+
+ btTransform childTransform = transform;
+ childTransform.getOrigin() = transform * capStart;
+ {
+ btVector3 center = childTransform.getOrigin();
+ btVector3 up = childTransform.getBasis().getColumn((upAxis+1)%3);
+ btVector3 axis = -childTransform.getBasis().getColumn(upAxis);
+ btScalar minTh = -SIMD_HALF_PI;
+ btScalar maxTh = SIMD_HALF_PI;
+ btScalar minPs = -SIMD_HALF_PI;
+ btScalar maxPs = SIMD_HALF_PI;
+
+ drawSpherePatch(center, up, axis, radius,minTh, maxTh, minPs, maxPs, color, btScalar(stepDegrees) ,false);
+ }
+
+
+
+ }
+
+ {
+ btTransform childTransform = transform;
+ childTransform.getOrigin() = transform * capEnd;
+ {
+ btVector3 center = childTransform.getOrigin();
+ btVector3 up = childTransform.getBasis().getColumn((upAxis+1)%3);
+ btVector3 axis = childTransform.getBasis().getColumn(upAxis);
+ btScalar minTh = -SIMD_HALF_PI;
+ btScalar maxTh = SIMD_HALF_PI;
+ btScalar minPs = -SIMD_HALF_PI;
+ btScalar maxPs = SIMD_HALF_PI;
+ drawSpherePatch(center, up, axis, radius,minTh, maxTh, minPs, maxPs, color, btScalar(stepDegrees) ,false);
+ }
+ }
+
+ // Draw some additional lines
+ btVector3 start = transform.getOrigin();
+
+ for (int i=0;i<360;i+=stepDegrees)
+ {
+ capEnd[(upAxis+1)%3] = capStart[(upAxis+1)%3] = btSin(btScalar(i)*SIMD_RADS_PER_DEG)*radius;
+ capEnd[(upAxis+2)%3] = capStart[(upAxis+2)%3] = btCos(btScalar(i)*SIMD_RADS_PER_DEG)*radius;
+ drawLine(start+transform.getBasis() * capStart,start+transform.getBasis() * capEnd, color);
+ }
+
+ }
+
+ virtual void drawCylinder(btScalar radius, btScalar halfHeight, int upAxis, const btTransform& transform, const btVector3& color)
+ {
+ btVector3 start = transform.getOrigin();
+ btVector3 offsetHeight(0,0,0);
+ offsetHeight[upAxis] = halfHeight;
+ int stepDegrees=30;
+ btVector3 capStart(0.f,0.f,0.f);
+ capStart[upAxis] = -halfHeight;
+ btVector3 capEnd(0.f,0.f,0.f);
+ capEnd[upAxis] = halfHeight;
+
+ for (int i=0;i<360;i+=stepDegrees)
+ {
+ capEnd[(upAxis+1)%3] = capStart[(upAxis+1)%3] = btSin(btScalar(i)*SIMD_RADS_PER_DEG)*radius;
+ capEnd[(upAxis+2)%3] = capStart[(upAxis+2)%3] = btCos(btScalar(i)*SIMD_RADS_PER_DEG)*radius;
+ drawLine(start+transform.getBasis() * capStart,start+transform.getBasis() * capEnd, color);
+ }
+ // Drawing top and bottom caps of the cylinder
+ btVector3 yaxis(0,0,0);
+ yaxis[upAxis] = btScalar(1.0);
+ btVector3 xaxis(0,0,0);
+ xaxis[(upAxis+1)%3] = btScalar(1.0);
+ drawArc(start-transform.getBasis()*(offsetHeight),transform.getBasis()*yaxis,transform.getBasis()*xaxis,radius,radius,0,SIMD_2_PI,color,false,btScalar(10.0));
+ drawArc(start+transform.getBasis()*(offsetHeight),transform.getBasis()*yaxis,transform.getBasis()*xaxis,radius,radius,0,SIMD_2_PI,color,false,btScalar(10.0));
+ }
+
+ virtual void drawCone(btScalar radius, btScalar height, int upAxis, const btTransform& transform, const btVector3& color)
+ {
+ int stepDegrees = 30;
+ btVector3 start = transform.getOrigin();
+
+ btVector3 offsetHeight(0,0,0);
+ btScalar halfHeight = height * btScalar(0.5);
+ offsetHeight[upAxis] = halfHeight;
+ btVector3 offsetRadius(0,0,0);
+ offsetRadius[(upAxis+1)%3] = radius;
+ btVector3 offset2Radius(0,0,0);
+ offset2Radius[(upAxis+2)%3] = radius;
+
+
+ btVector3 capEnd(0.f,0.f,0.f);
+ capEnd[upAxis] = -halfHeight;
+
+ for (int i=0;i<360;i+=stepDegrees)
+ {
+ capEnd[(upAxis+1)%3] = btSin(btScalar(i)*SIMD_RADS_PER_DEG)*radius;
+ capEnd[(upAxis+2)%3] = btCos(btScalar(i)*SIMD_RADS_PER_DEG)*radius;
+ drawLine(start+transform.getBasis() * (offsetHeight),start+transform.getBasis() * capEnd, color);
+ }
+
+ drawLine(start+transform.getBasis() * (offsetHeight),start+transform.getBasis() * (-offsetHeight+offsetRadius),color);
+ drawLine(start+transform.getBasis() * (offsetHeight),start+transform.getBasis() * (-offsetHeight-offsetRadius),color);
+ drawLine(start+transform.getBasis() * (offsetHeight),start+transform.getBasis() * (-offsetHeight+offset2Radius),color);
+ drawLine(start+transform.getBasis() * (offsetHeight),start+transform.getBasis() * (-offsetHeight-offset2Radius),color);
+
+ // Drawing the base of the cone
+ btVector3 yaxis(0,0,0);
+ yaxis[upAxis] = btScalar(1.0);
+ btVector3 xaxis(0,0,0);
+ xaxis[(upAxis+1)%3] = btScalar(1.0);
+ drawArc(start-transform.getBasis()*(offsetHeight),transform.getBasis()*yaxis,transform.getBasis()*xaxis,radius,radius,0,SIMD_2_PI,color,false,10.0);
+ }
+
+ virtual void drawPlane(const btVector3& planeNormal, btScalar planeConst, const btTransform& transform, const btVector3& color)
+ {
+ btVector3 planeOrigin = planeNormal * planeConst;
+ btVector3 vec0,vec1;
+ btPlaneSpace1(planeNormal,vec0,vec1);
+ btScalar vecLen = 100.f;
+ btVector3 pt0 = planeOrigin + vec0*vecLen;
+ btVector3 pt1 = planeOrigin - vec0*vecLen;
+ btVector3 pt2 = planeOrigin + vec1*vecLen;
+ btVector3 pt3 = planeOrigin - vec1*vecLen;
+ drawLine(transform*pt0,transform*pt1,color);
+ drawLine(transform*pt2,transform*pt3,color);
+ }
+
+ virtual void clearLines()
+ {
+ }
+
+ virtual void flushLines()
+ {
+ }
+};
+
+
+#endif //BT_IDEBUG_DRAW__H
+
diff --git a/thirdparty/bullet/src/LinearMath/btList.h b/thirdparty/bullet/src/LinearMath/btList.h
new file mode 100644
index 0000000000..eec80a7064
--- /dev/null
+++ b/thirdparty/bullet/src/LinearMath/btList.h
@@ -0,0 +1,73 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+#ifndef BT_GEN_LIST_H
+#define BT_GEN_LIST_H
+
+class btGEN_Link {
+public:
+ btGEN_Link() : m_next(0), m_prev(0) {}
+ btGEN_Link(btGEN_Link *next, btGEN_Link *prev) : m_next(next), m_prev(prev) {}
+
+ btGEN_Link *getNext() const { return m_next; }
+ btGEN_Link *getPrev() const { return m_prev; }
+
+ bool isHead() const { return m_prev == 0; }
+ bool isTail() const { return m_next == 0; }
+
+ void insertBefore(btGEN_Link *link) {
+ m_next = link;
+ m_prev = link->m_prev;
+ m_next->m_prev = this;
+ m_prev->m_next = this;
+ }
+
+ void insertAfter(btGEN_Link *link) {
+ m_next = link->m_next;
+ m_prev = link;
+ m_next->m_prev = this;
+ m_prev->m_next = this;
+ }
+
+ void remove() {
+ m_next->m_prev = m_prev;
+ m_prev->m_next = m_next;
+ }
+
+private:
+ btGEN_Link *m_next;
+ btGEN_Link *m_prev;
+};
+
+class btGEN_List {
+public:
+ btGEN_List() : m_head(&m_tail, 0), m_tail(0, &m_head) {}
+
+ btGEN_Link *getHead() const { return m_head.getNext(); }
+ btGEN_Link *getTail() const { return m_tail.getPrev(); }
+
+ void addHead(btGEN_Link *link) { link->insertAfter(&m_head); }
+ void addTail(btGEN_Link *link) { link->insertBefore(&m_tail); }
+
+private:
+ btGEN_Link m_head;
+ btGEN_Link m_tail;
+};
+
+#endif //BT_GEN_LIST_H
+
+
+
diff --git a/thirdparty/bullet/src/LinearMath/btMatrix3x3.h b/thirdparty/bullet/src/LinearMath/btMatrix3x3.h
new file mode 100644
index 0000000000..9f642a1779
--- /dev/null
+++ b/thirdparty/bullet/src/LinearMath/btMatrix3x3.h
@@ -0,0 +1,1348 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#ifndef BT_MATRIX3x3_H
+#define BT_MATRIX3x3_H
+
+#include "btVector3.h"
+#include "btQuaternion.h"
+#include <stdio.h>
+
+#ifdef BT_USE_SSE
+//const __m128 ATTRIBUTE_ALIGNED16(v2220) = {2.0f, 2.0f, 2.0f, 0.0f};
+//const __m128 ATTRIBUTE_ALIGNED16(vMPPP) = {-0.0f, +0.0f, +0.0f, +0.0f};
+#define vMPPP (_mm_set_ps (+0.0f, +0.0f, +0.0f, -0.0f))
+#endif
+
+#if defined(BT_USE_SSE)
+#define v1000 (_mm_set_ps(0.0f,0.0f,0.0f,1.0f))
+#define v0100 (_mm_set_ps(0.0f,0.0f,1.0f,0.0f))
+#define v0010 (_mm_set_ps(0.0f,1.0f,0.0f,0.0f))
+#elif defined(BT_USE_NEON)
+const btSimdFloat4 ATTRIBUTE_ALIGNED16(v1000) = {1.0f, 0.0f, 0.0f, 0.0f};
+const btSimdFloat4 ATTRIBUTE_ALIGNED16(v0100) = {0.0f, 1.0f, 0.0f, 0.0f};
+const btSimdFloat4 ATTRIBUTE_ALIGNED16(v0010) = {0.0f, 0.0f, 1.0f, 0.0f};
+#endif
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define btMatrix3x3Data btMatrix3x3DoubleData
+#else
+#define btMatrix3x3Data btMatrix3x3FloatData
+#endif //BT_USE_DOUBLE_PRECISION
+
+
+/**@brief The btMatrix3x3 class implements a 3x3 rotation matrix, to perform linear algebra in combination with btQuaternion, btTransform and btVector3.
+* Make sure to only include a pure orthogonal matrix without scaling. */
+ATTRIBUTE_ALIGNED16(class) btMatrix3x3 {
+
+ ///Data storage for the matrix, each vector is a row of the matrix
+ btVector3 m_el[3];
+
+public:
+ /** @brief No initializaion constructor */
+ btMatrix3x3 () {}
+
+ // explicit btMatrix3x3(const btScalar *m) { setFromOpenGLSubMatrix(m); }
+
+ /**@brief Constructor from Quaternion */
+ explicit btMatrix3x3(const btQuaternion& q) { setRotation(q); }
+ /*
+ template <typename btScalar>
+ Matrix3x3(const btScalar& yaw, const btScalar& pitch, const btScalar& roll)
+ {
+ setEulerYPR(yaw, pitch, roll);
+ }
+ */
+ /** @brief Constructor with row major formatting */
+ btMatrix3x3(const btScalar& xx, const btScalar& xy, const btScalar& xz,
+ const btScalar& yx, const btScalar& yy, const btScalar& yz,
+ const btScalar& zx, const btScalar& zy, const btScalar& zz)
+ {
+ setValue(xx, xy, xz,
+ yx, yy, yz,
+ zx, zy, zz);
+ }
+
+#if (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE))|| defined (BT_USE_NEON)
+ SIMD_FORCE_INLINE btMatrix3x3 (const btSimdFloat4 v0, const btSimdFloat4 v1, const btSimdFloat4 v2 )
+ {
+ m_el[0].mVec128 = v0;
+ m_el[1].mVec128 = v1;
+ m_el[2].mVec128 = v2;
+ }
+
+ 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;
+ }
+
+ // Copy constructor
+ SIMD_FORCE_INLINE btMatrix3x3(const btMatrix3x3& rhs)
+ {
+ m_el[0].mVec128 = rhs.m_el[0].mVec128;
+ m_el[1].mVec128 = rhs.m_el[1].mVec128;
+ m_el[2].mVec128 = rhs.m_el[2].mVec128;
+ }
+
+ // Assignment Operator
+ SIMD_FORCE_INLINE btMatrix3x3& operator=(const btMatrix3x3& m)
+ {
+ m_el[0].mVec128 = m.m_el[0].mVec128;
+ m_el[1].mVec128 = m.m_el[1].mVec128;
+ m_el[2].mVec128 = m.m_el[2].mVec128;
+
+ return *this;
+ }
+
+#else
+
+ /** @brief Copy constructor */
+ SIMD_FORCE_INLINE btMatrix3x3 (const btMatrix3x3& other)
+ {
+ m_el[0] = other.m_el[0];
+ m_el[1] = other.m_el[1];
+ m_el[2] = other.m_el[2];
+ }
+
+ /** @brief Assignment Operator */
+ SIMD_FORCE_INLINE btMatrix3x3& operator=(const btMatrix3x3& other)
+ {
+ m_el[0] = other.m_el[0];
+ m_el[1] = other.m_el[1];
+ m_el[2] = other.m_el[2];
+ return *this;
+ }
+
+#endif
+
+ /** @brief Get a column of the matrix as a vector
+ * @param i Column number 0 indexed */
+ SIMD_FORCE_INLINE btVector3 getColumn(int i) const
+ {
+ return btVector3(m_el[0][i],m_el[1][i],m_el[2][i]);
+ }
+
+
+ /** @brief Get a row of the matrix as a vector
+ * @param i Row number 0 indexed */
+ SIMD_FORCE_INLINE const btVector3& getRow(int i) const
+ {
+ btFullAssert(0 <= i && i < 3);
+ return m_el[i];
+ }
+
+ /** @brief Get a mutable reference to a row of the matrix as a vector
+ * @param i Row number 0 indexed */
+ SIMD_FORCE_INLINE btVector3& operator[](int i)
+ {
+ btFullAssert(0 <= i && i < 3);
+ return m_el[i];
+ }
+
+ /** @brief Get a const reference to a row of the matrix as a vector
+ * @param i Row number 0 indexed */
+ SIMD_FORCE_INLINE const btVector3& operator[](int i) const
+ {
+ btFullAssert(0 <= i && i < 3);
+ return m_el[i];
+ }
+
+ /** @brief Multiply by the target matrix on the right
+ * @param m Rotation matrix to be applied
+ * Equivilant to this = this * m */
+ btMatrix3x3& operator*=(const btMatrix3x3& m);
+
+ /** @brief Adds by the target matrix on the right
+ * @param m matrix to be applied
+ * Equivilant to this = this + m */
+ btMatrix3x3& operator+=(const btMatrix3x3& m);
+
+ /** @brief Substractss by the target matrix on the right
+ * @param m matrix to be applied
+ * Equivilant to this = this - m */
+ btMatrix3x3& operator-=(const btMatrix3x3& m);
+
+ /** @brief Set from the rotational part of a 4x4 OpenGL matrix
+ * @param m A pointer to the beginning of the array of scalars*/
+ void setFromOpenGLSubMatrix(const btScalar *m)
+ {
+ m_el[0].setValue(m[0],m[4],m[8]);
+ m_el[1].setValue(m[1],m[5],m[9]);
+ m_el[2].setValue(m[2],m[6],m[10]);
+
+ }
+ /** @brief Set the values of the matrix explicitly (row major)
+ * @param xx Top left
+ * @param xy Top Middle
+ * @param xz Top Right
+ * @param yx Middle Left
+ * @param yy Middle Middle
+ * @param yz Middle Right
+ * @param zx Bottom Left
+ * @param zy Bottom Middle
+ * @param zz Bottom Right*/
+ void setValue(const btScalar& xx, const btScalar& xy, const btScalar& xz,
+ const btScalar& yx, const btScalar& yy, const btScalar& yz,
+ const btScalar& zx, const btScalar& zy, const btScalar& zz)
+ {
+ m_el[0].setValue(xx,xy,xz);
+ m_el[1].setValue(yx,yy,yz);
+ m_el[2].setValue(zx,zy,zz);
+ }
+
+ /** @brief Set the matrix from a quaternion
+ * @param q The Quaternion to match */
+ void setRotation(const btQuaternion& q)
+ {
+ btScalar d = q.length2();
+ btFullAssert(d != btScalar(0.0));
+ btScalar s = btScalar(2.0) / d;
+
+ #if defined BT_USE_SIMD_VECTOR3 && defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ __m128 vs, Q = q.get128();
+ __m128i Qi = btCastfTo128i(Q);
+ __m128 Y, Z;
+ __m128 V1, V2, V3;
+ __m128 V11, V21, V31;
+ __m128 NQ = _mm_xor_ps(Q, btvMzeroMask);
+ __m128i NQi = btCastfTo128i(NQ);
+
+ V1 = btCastiTo128f(_mm_shuffle_epi32 (Qi, BT_SHUFFLE(1,0,2,3))); // Y X Z W
+ V2 = _mm_shuffle_ps(NQ, Q, BT_SHUFFLE(0,0,1,3)); // -X -X Y W
+ V3 = btCastiTo128f(_mm_shuffle_epi32 (Qi, BT_SHUFFLE(2,1,0,3))); // Z Y X W
+ V1 = _mm_xor_ps(V1, vMPPP); // change the sign of the first element
+
+ V11 = btCastiTo128f(_mm_shuffle_epi32 (Qi, BT_SHUFFLE(1,1,0,3))); // Y Y X W
+ V21 = _mm_unpackhi_ps(Q, Q); // Z Z W W
+ V31 = _mm_shuffle_ps(Q, NQ, BT_SHUFFLE(0,2,0,3)); // X Z -X -W
+
+ V2 = V2 * V1; //
+ V1 = V1 * V11; //
+ V3 = V3 * V31; //
+
+ V11 = _mm_shuffle_ps(NQ, Q, BT_SHUFFLE(2,3,1,3)); // -Z -W Y W
+ V11 = V11 * V21; //
+ V21 = _mm_xor_ps(V21, vMPPP); // change the sign of the first element
+ V31 = _mm_shuffle_ps(Q, NQ, BT_SHUFFLE(3,3,1,3)); // W W -Y -W
+ V31 = _mm_xor_ps(V31, vMPPP); // change the sign of the first element
+ Y = btCastiTo128f(_mm_shuffle_epi32 (NQi, BT_SHUFFLE(3,2,0,3))); // -W -Z -X -W
+ Z = btCastiTo128f(_mm_shuffle_epi32 (Qi, BT_SHUFFLE(1,0,1,3))); // Y X Y W
+
+ vs = _mm_load_ss(&s);
+ V21 = V21 * Y;
+ V31 = V31 * Z;
+
+ V1 = V1 + V11;
+ V2 = V2 + V21;
+ V3 = V3 + V31;
+
+ vs = bt_splat3_ps(vs, 0);
+ // s ready
+ V1 = V1 * vs;
+ V2 = V2 * vs;
+ V3 = V3 * vs;
+
+ V1 = V1 + v1000;
+ V2 = V2 + v0100;
+ V3 = V3 + v0010;
+
+ m_el[0] = V1;
+ m_el[1] = V2;
+ m_el[2] = V3;
+ #else
+ btScalar xs = q.x() * s, ys = q.y() * s, zs = q.z() * s;
+ btScalar wx = q.w() * xs, wy = q.w() * ys, wz = q.w() * zs;
+ btScalar xx = q.x() * xs, xy = q.x() * ys, xz = q.x() * zs;
+ btScalar yy = q.y() * ys, yz = q.y() * zs, zz = q.z() * zs;
+ setValue(
+ btScalar(1.0) - (yy + zz), xy - wz, xz + wy,
+ xy + wz, btScalar(1.0) - (xx + zz), yz - wx,
+ xz - wy, yz + wx, btScalar(1.0) - (xx + yy));
+ #endif
+ }
+
+
+ /** @brief Set the matrix from euler angles using YPR around YXZ respectively
+ * @param yaw Yaw about Y axis
+ * @param pitch Pitch about X axis
+ * @param roll Roll about Z axis
+ */
+ void setEulerYPR(const btScalar& yaw, const btScalar& pitch, const btScalar& roll)
+ {
+ setEulerZYX(roll, pitch, yaw);
+ }
+
+ /** @brief Set the matrix from euler angles YPR around ZYX axes
+ * @param eulerX Roll about X axis
+ * @param eulerY Pitch around Y axis
+ * @param eulerZ Yaw aboud Z axis
+ *
+ * These angles are used to produce a rotation matrix. The euler
+ * angles are applied in ZYX order. I.e a vector is first rotated
+ * about X then Y and then Z
+ **/
+ void setEulerZYX(btScalar eulerX,btScalar eulerY,btScalar eulerZ) {
+ ///@todo proposed to reverse this since it's labeled zyx but takes arguments xyz and it will match all other parts of the code
+ btScalar ci ( btCos(eulerX));
+ btScalar cj ( btCos(eulerY));
+ btScalar ch ( btCos(eulerZ));
+ btScalar si ( btSin(eulerX));
+ btScalar sj ( btSin(eulerY));
+ btScalar sh ( btSin(eulerZ));
+ btScalar cc = ci * ch;
+ btScalar cs = ci * sh;
+ btScalar sc = si * ch;
+ btScalar ss = si * sh;
+
+ setValue(cj * ch, sj * sc - cs, sj * cc + ss,
+ cj * sh, sj * ss + cc, sj * cs - sc,
+ -sj, cj * si, cj * ci);
+ }
+
+ /**@brief Set the matrix to the identity */
+ void setIdentity()
+ {
+#if (defined(BT_USE_SSE_IN_API)&& defined (BT_USE_SSE)) || defined(BT_USE_NEON)
+ m_el[0] = v1000;
+ m_el[1] = v0100;
+ m_el[2] = v0010;
+#else
+ setValue(btScalar(1.0), btScalar(0.0), btScalar(0.0),
+ btScalar(0.0), btScalar(1.0), btScalar(0.0),
+ btScalar(0.0), btScalar(0.0), btScalar(1.0));
+#endif
+ }
+
+ static const btMatrix3x3& getIdentity()
+ {
+#if (defined(BT_USE_SSE_IN_API)&& defined (BT_USE_SSE)) || defined(BT_USE_NEON)
+ static const btMatrix3x3
+ identityMatrix(v1000, v0100, v0010);
+#else
+ static const btMatrix3x3
+ identityMatrix(
+ btScalar(1.0), btScalar(0.0), btScalar(0.0),
+ btScalar(0.0), btScalar(1.0), btScalar(0.0),
+ btScalar(0.0), btScalar(0.0), btScalar(1.0));
+#endif
+ return identityMatrix;
+ }
+
+ /**@brief Fill the rotational part of an OpenGL matrix and clear the shear/perspective
+ * @param m The array to be filled */
+ void getOpenGLSubMatrix(btScalar *m) const
+ {
+#if defined BT_USE_SIMD_VECTOR3 && defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ __m128 v0 = m_el[0].mVec128;
+ __m128 v1 = m_el[1].mVec128;
+ __m128 v2 = m_el[2].mVec128; // x2 y2 z2 w2
+ __m128 *vm = (__m128 *)m;
+ __m128 vT;
+
+ v2 = _mm_and_ps(v2, btvFFF0fMask); // x2 y2 z2 0
+
+ vT = _mm_unpackhi_ps(v0, v1); // z0 z1 * *
+ v0 = _mm_unpacklo_ps(v0, v1); // x0 x1 y0 y1
+
+ v1 = _mm_shuffle_ps(v0, v2, BT_SHUFFLE(2, 3, 1, 3) ); // y0 y1 y2 0
+ v0 = _mm_shuffle_ps(v0, v2, BT_SHUFFLE(0, 1, 0, 3) ); // x0 x1 x2 0
+ v2 = btCastdTo128f(_mm_move_sd(btCastfTo128d(v2), btCastfTo128d(vT))); // z0 z1 z2 0
+
+ vm[0] = v0;
+ vm[1] = v1;
+ vm[2] = v2;
+#elif defined(BT_USE_NEON)
+ // note: zeros the w channel. We can preserve it at the cost of two more vtrn instructions.
+ static const uint32x2_t zMask = (const uint32x2_t) {static_cast<uint32_t>(-1), 0 };
+ float32x4_t *vm = (float32x4_t *)m;
+ float32x4x2_t top = vtrnq_f32( m_el[0].mVec128, m_el[1].mVec128 ); // {x0 x1 z0 z1}, {y0 y1 w0 w1}
+ float32x2x2_t bl = vtrn_f32( vget_low_f32(m_el[2].mVec128), vdup_n_f32(0.0f) ); // {x2 0 }, {y2 0}
+ float32x4_t v0 = vcombine_f32( vget_low_f32(top.val[0]), bl.val[0] );
+ float32x4_t v1 = vcombine_f32( vget_low_f32(top.val[1]), bl.val[1] );
+ float32x2_t q = (float32x2_t) vand_u32( (uint32x2_t) vget_high_f32( m_el[2].mVec128), zMask );
+ float32x4_t v2 = vcombine_f32( vget_high_f32(top.val[0]), q ); // z0 z1 z2 0
+
+ vm[0] = v0;
+ vm[1] = v1;
+ vm[2] = v2;
+#else
+ m[0] = btScalar(m_el[0].x());
+ m[1] = btScalar(m_el[1].x());
+ m[2] = btScalar(m_el[2].x());
+ m[3] = btScalar(0.0);
+ m[4] = btScalar(m_el[0].y());
+ m[5] = btScalar(m_el[1].y());
+ m[6] = btScalar(m_el[2].y());
+ m[7] = btScalar(0.0);
+ m[8] = btScalar(m_el[0].z());
+ m[9] = btScalar(m_el[1].z());
+ m[10] = btScalar(m_el[2].z());
+ m[11] = btScalar(0.0);
+#endif
+ }
+
+ /**@brief Get the matrix represented as a quaternion
+ * @param q The quaternion which will be set */
+ void getRotation(btQuaternion& q) const
+ {
+#if (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE))|| defined (BT_USE_NEON)
+ btScalar trace = m_el[0].x() + m_el[1].y() + m_el[2].z();
+ btScalar s, x;
+
+ union {
+ btSimdFloat4 vec;
+ btScalar f[4];
+ } temp;
+
+ if (trace > btScalar(0.0))
+ {
+ x = trace + btScalar(1.0);
+
+ temp.f[0]=m_el[2].y() - m_el[1].z();
+ temp.f[1]=m_el[0].z() - m_el[2].x();
+ temp.f[2]=m_el[1].x() - m_el[0].y();
+ temp.f[3]=x;
+ //temp.f[3]= s * btScalar(0.5);
+ }
+ else
+ {
+ int i, j, k;
+ if(m_el[0].x() < m_el[1].y())
+ {
+ if( m_el[1].y() < m_el[2].z() )
+ { i = 2; j = 0; k = 1; }
+ else
+ { i = 1; j = 2; k = 0; }
+ }
+ else
+ {
+ if( m_el[0].x() < m_el[2].z())
+ { i = 2; j = 0; k = 1; }
+ else
+ { i = 0; j = 1; k = 2; }
+ }
+
+ x = m_el[i][i] - m_el[j][j] - m_el[k][k] + btScalar(1.0);
+
+ temp.f[3] = (m_el[k][j] - m_el[j][k]);
+ temp.f[j] = (m_el[j][i] + m_el[i][j]);
+ temp.f[k] = (m_el[k][i] + m_el[i][k]);
+ temp.f[i] = x;
+ //temp.f[i] = s * btScalar(0.5);
+ }
+
+ s = btSqrt(x);
+ q.set128(temp.vec);
+ s = btScalar(0.5) / s;
+
+ q *= s;
+#else
+ btScalar trace = m_el[0].x() + m_el[1].y() + m_el[2].z();
+
+ btScalar temp[4];
+
+ if (trace > btScalar(0.0))
+ {
+ btScalar s = btSqrt(trace + btScalar(1.0));
+ temp[3]=(s * btScalar(0.5));
+ s = btScalar(0.5) / s;
+
+ temp[0]=((m_el[2].y() - m_el[1].z()) * s);
+ temp[1]=((m_el[0].z() - m_el[2].x()) * s);
+ temp[2]=((m_el[1].x() - m_el[0].y()) * s);
+ }
+ else
+ {
+ int i = m_el[0].x() < m_el[1].y() ?
+ (m_el[1].y() < m_el[2].z() ? 2 : 1) :
+ (m_el[0].x() < m_el[2].z() ? 2 : 0);
+ int j = (i + 1) % 3;
+ int k = (i + 2) % 3;
+
+ btScalar s = btSqrt(m_el[i][i] - m_el[j][j] - m_el[k][k] + btScalar(1.0));
+ temp[i] = s * btScalar(0.5);
+ s = btScalar(0.5) / s;
+
+ temp[3] = (m_el[k][j] - m_el[j][k]) * s;
+ temp[j] = (m_el[j][i] + m_el[i][j]) * s;
+ temp[k] = (m_el[k][i] + m_el[i][k]) * s;
+ }
+ q.setValue(temp[0],temp[1],temp[2],temp[3]);
+#endif
+ }
+
+ /**@brief Get the matrix represented as euler angles around YXZ, roundtrip with setEulerYPR
+ * @param yaw Yaw around Y axis
+ * @param pitch Pitch around X axis
+ * @param roll around Z axis */
+ void getEulerYPR(btScalar& yaw, btScalar& pitch, btScalar& roll) const
+ {
+
+ // first use the normal calculus
+ yaw = btScalar(btAtan2(m_el[1].x(), m_el[0].x()));
+ pitch = btScalar(btAsin(-m_el[2].x()));
+ roll = btScalar(btAtan2(m_el[2].y(), m_el[2].z()));
+
+ // on pitch = +/-HalfPI
+ if (btFabs(pitch)==SIMD_HALF_PI)
+ {
+ if (yaw>0)
+ yaw-=SIMD_PI;
+ else
+ yaw+=SIMD_PI;
+
+ if (roll>0)
+ roll-=SIMD_PI;
+ else
+ roll+=SIMD_PI;
+ }
+ };
+
+
+ /**@brief Get the matrix represented as euler angles around ZYX
+ * @param yaw Yaw around X axis
+ * @param pitch Pitch around Y axis
+ * @param roll around X axis
+ * @param solution_number Which solution of two possible solutions ( 1 or 2) are possible values*/
+ void getEulerZYX(btScalar& yaw, btScalar& pitch, btScalar& roll, unsigned int solution_number = 1) const
+ {
+ struct Euler
+ {
+ btScalar yaw;
+ btScalar pitch;
+ btScalar roll;
+ };
+
+ Euler euler_out;
+ Euler euler_out2; //second solution
+ //get the pointer to the raw data
+
+ // Check that pitch is not at a singularity
+ if (btFabs(m_el[2].x()) >= 1)
+ {
+ euler_out.yaw = 0;
+ euler_out2.yaw = 0;
+
+ // From difference of angles formula
+ btScalar delta = btAtan2(m_el[0].x(),m_el[0].z());
+ if (m_el[2].x() > 0) //gimbal locked up
+ {
+ euler_out.pitch = SIMD_PI / btScalar(2.0);
+ euler_out2.pitch = SIMD_PI / btScalar(2.0);
+ euler_out.roll = euler_out.pitch + delta;
+ euler_out2.roll = euler_out.pitch + delta;
+ }
+ else // gimbal locked down
+ {
+ euler_out.pitch = -SIMD_PI / btScalar(2.0);
+ euler_out2.pitch = -SIMD_PI / btScalar(2.0);
+ euler_out.roll = -euler_out.pitch + delta;
+ euler_out2.roll = -euler_out.pitch + delta;
+ }
+ }
+ else
+ {
+ euler_out.pitch = - btAsin(m_el[2].x());
+ euler_out2.pitch = SIMD_PI - euler_out.pitch;
+
+ euler_out.roll = btAtan2(m_el[2].y()/btCos(euler_out.pitch),
+ m_el[2].z()/btCos(euler_out.pitch));
+ euler_out2.roll = btAtan2(m_el[2].y()/btCos(euler_out2.pitch),
+ m_el[2].z()/btCos(euler_out2.pitch));
+
+ euler_out.yaw = btAtan2(m_el[1].x()/btCos(euler_out.pitch),
+ m_el[0].x()/btCos(euler_out.pitch));
+ euler_out2.yaw = btAtan2(m_el[1].x()/btCos(euler_out2.pitch),
+ m_el[0].x()/btCos(euler_out2.pitch));
+ }
+
+ if (solution_number == 1)
+ {
+ yaw = euler_out.yaw;
+ pitch = euler_out.pitch;
+ roll = euler_out.roll;
+ }
+ else
+ {
+ yaw = euler_out2.yaw;
+ pitch = euler_out2.pitch;
+ roll = euler_out2.roll;
+ }
+ }
+
+ /**@brief Create a scaled copy of the matrix
+ * @param s Scaling vector The elements of the vector will scale each column */
+
+ btMatrix3x3 scaled(const btVector3& s) const
+ {
+#if (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE))|| defined (BT_USE_NEON)
+ return btMatrix3x3(m_el[0] * s, m_el[1] * s, m_el[2] * s);
+#else
+ return btMatrix3x3(
+ m_el[0].x() * s.x(), m_el[0].y() * s.y(), m_el[0].z() * s.z(),
+ m_el[1].x() * s.x(), m_el[1].y() * s.y(), m_el[1].z() * s.z(),
+ m_el[2].x() * s.x(), m_el[2].y() * s.y(), m_el[2].z() * s.z());
+#endif
+ }
+
+ /**@brief Return the determinant of the matrix */
+ btScalar determinant() const;
+ /**@brief Return the adjoint of the matrix */
+ btMatrix3x3 adjoint() const;
+ /**@brief Return the matrix with all values non negative */
+ btMatrix3x3 absolute() const;
+ /**@brief Return the transpose of the matrix */
+ btMatrix3x3 transpose() const;
+ /**@brief Return the inverse of the matrix */
+ btMatrix3x3 inverse() const;
+
+ /// Solve A * x = b, where b is a column vector. This is more efficient
+ /// than computing the inverse in one-shot cases.
+ ///Solve33 is from Box2d, thanks to Erin Catto,
+ btVector3 solve33(const btVector3& b) const
+ {
+ btVector3 col1 = getColumn(0);
+ btVector3 col2 = getColumn(1);
+ btVector3 col3 = getColumn(2);
+
+ btScalar det = btDot(col1, btCross(col2, col3));
+ if (btFabs(det)>SIMD_EPSILON)
+ {
+ det = 1.0f / det;
+ }
+ btVector3 x;
+ x[0] = det * btDot(b, btCross(col2, col3));
+ x[1] = det * btDot(col1, btCross(b, col3));
+ x[2] = det * btDot(col1, btCross(col2, b));
+ return x;
+ }
+
+ btMatrix3x3 transposeTimes(const btMatrix3x3& m) const;
+ btMatrix3x3 timesTranspose(const btMatrix3x3& m) const;
+
+ SIMD_FORCE_INLINE btScalar tdotx(const btVector3& v) const
+ {
+ return m_el[0].x() * v.x() + m_el[1].x() * v.y() + m_el[2].x() * v.z();
+ }
+ SIMD_FORCE_INLINE btScalar tdoty(const btVector3& v) const
+ {
+ return m_el[0].y() * v.x() + m_el[1].y() * v.y() + m_el[2].y() * v.z();
+ }
+ SIMD_FORCE_INLINE btScalar tdotz(const btVector3& v) const
+ {
+ return m_el[0].z() * v.x() + m_el[1].z() * v.y() + m_el[2].z() * v.z();
+ }
+
+ ///extractRotation is from "A robust method to extract the rotational part of deformations"
+ ///See http://dl.acm.org/citation.cfm?doid=2994258.2994269
+ SIMD_FORCE_INLINE void extractRotation(btQuaternion &q,btScalar tolerance = 1.0e-9, int maxIter=100)
+ {
+ int iter =0;
+ btScalar w;
+ const btMatrix3x3& A=*this;
+ for(iter = 0; iter < maxIter; iter++)
+ {
+ btMatrix3x3 R(q);
+ btVector3 omega = (R.getColumn(0).cross(A.getColumn(0)) + R.getColumn(1).cross(A.getColumn(1))
+ + R.getColumn(2).cross(A.getColumn(2))
+ ) * (btScalar(1.0) / btFabs(R.getColumn(0).dot(A.getColumn(0)) + R.getColumn
+ (1).dot(A.getColumn(1)) + R.getColumn(2).dot(A.getColumn(2))) +
+ tolerance);
+ w = omega.norm();
+ if(w < tolerance)
+ break;
+ q = btQuaternion(btVector3((btScalar(1.0) / w) * omega),w) *
+ q;
+ q.normalize();
+ }
+ }
+
+
+
+ /**@brief diagonalizes this matrix
+ * @param rot stores the rotation from the coordinate system in which the matrix is diagonal to the original
+ * coordinate system, i.e., old_this = rot * new_this * rot^T.
+ * @param threshold See iteration
+ * @param maxIter The iteration stops when we hit the given tolerance or when maxIter have been executed.
+ */
+ void diagonalize(btMatrix3x3& rot, btScalar tolerance = 1.0e-9, int maxIter=100)
+ {
+ btQuaternion r;
+ r = btQuaternion::getIdentity();
+ extractRotation(r,tolerance,maxIter);
+ rot.setRotation(r);
+ btMatrix3x3 rotInv = btMatrix3x3(r.inverse());
+ btMatrix3x3 old = *this;
+ setValue(old.tdotx( rotInv[0]), old.tdoty( rotInv[0]), old.tdotz( rotInv[0]),
+ old.tdotx( rotInv[1]), old.tdoty( rotInv[1]), old.tdotz( rotInv[1]),
+ old.tdotx( rotInv[2]), old.tdoty( rotInv[2]), old.tdotz( rotInv[2]));
+ }
+
+
+
+
+ /**@brief Calculate the matrix cofactor
+ * @param r1 The first row to use for calculating the cofactor
+ * @param c1 The first column to use for calculating the cofactor
+ * @param r1 The second row to use for calculating the cofactor
+ * @param c1 The second column to use for calculating the cofactor
+ * See http://en.wikipedia.org/wiki/Cofactor_(linear_algebra) for more details
+ */
+ btScalar cofac(int r1, int c1, int r2, int c2) const
+ {
+ return m_el[r1][c1] * m_el[r2][c2] - m_el[r1][c2] * m_el[r2][c1];
+ }
+
+ void serialize(struct btMatrix3x3Data& dataOut) const;
+
+ void serializeFloat(struct btMatrix3x3FloatData& dataOut) const;
+
+ void deSerialize(const struct btMatrix3x3Data& dataIn);
+
+ void deSerializeFloat(const struct btMatrix3x3FloatData& dataIn);
+
+ void deSerializeDouble(const struct btMatrix3x3DoubleData& dataIn);
+
+};
+
+
+SIMD_FORCE_INLINE btMatrix3x3&
+btMatrix3x3::operator*=(const btMatrix3x3& m)
+{
+#if defined BT_USE_SIMD_VECTOR3 && defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ __m128 rv00, rv01, rv02;
+ __m128 rv10, rv11, rv12;
+ __m128 rv20, rv21, rv22;
+ __m128 mv0, mv1, mv2;
+
+ rv02 = m_el[0].mVec128;
+ rv12 = m_el[1].mVec128;
+ rv22 = m_el[2].mVec128;
+
+ mv0 = _mm_and_ps(m[0].mVec128, btvFFF0fMask);
+ mv1 = _mm_and_ps(m[1].mVec128, btvFFF0fMask);
+ mv2 = _mm_and_ps(m[2].mVec128, btvFFF0fMask);
+
+ // rv0
+ rv00 = bt_splat_ps(rv02, 0);
+ rv01 = bt_splat_ps(rv02, 1);
+ rv02 = bt_splat_ps(rv02, 2);
+
+ rv00 = _mm_mul_ps(rv00, mv0);
+ rv01 = _mm_mul_ps(rv01, mv1);
+ rv02 = _mm_mul_ps(rv02, mv2);
+
+ // rv1
+ rv10 = bt_splat_ps(rv12, 0);
+ rv11 = bt_splat_ps(rv12, 1);
+ rv12 = bt_splat_ps(rv12, 2);
+
+ rv10 = _mm_mul_ps(rv10, mv0);
+ rv11 = _mm_mul_ps(rv11, mv1);
+ rv12 = _mm_mul_ps(rv12, mv2);
+
+ // rv2
+ rv20 = bt_splat_ps(rv22, 0);
+ rv21 = bt_splat_ps(rv22, 1);
+ rv22 = bt_splat_ps(rv22, 2);
+
+ rv20 = _mm_mul_ps(rv20, mv0);
+ rv21 = _mm_mul_ps(rv21, mv1);
+ rv22 = _mm_mul_ps(rv22, mv2);
+
+ rv00 = _mm_add_ps(rv00, rv01);
+ rv10 = _mm_add_ps(rv10, rv11);
+ rv20 = _mm_add_ps(rv20, rv21);
+
+ m_el[0].mVec128 = _mm_add_ps(rv00, rv02);
+ m_el[1].mVec128 = _mm_add_ps(rv10, rv12);
+ m_el[2].mVec128 = _mm_add_ps(rv20, rv22);
+
+#elif defined(BT_USE_NEON)
+
+ float32x4_t rv0, rv1, rv2;
+ float32x4_t v0, v1, v2;
+ float32x4_t mv0, mv1, mv2;
+
+ v0 = m_el[0].mVec128;
+ v1 = m_el[1].mVec128;
+ v2 = m_el[2].mVec128;
+
+ mv0 = (float32x4_t) vandq_s32((int32x4_t)m[0].mVec128, btvFFF0Mask);
+ mv1 = (float32x4_t) vandq_s32((int32x4_t)m[1].mVec128, btvFFF0Mask);
+ mv2 = (float32x4_t) vandq_s32((int32x4_t)m[2].mVec128, btvFFF0Mask);
+
+ rv0 = vmulq_lane_f32(mv0, vget_low_f32(v0), 0);
+ rv1 = vmulq_lane_f32(mv0, vget_low_f32(v1), 0);
+ rv2 = vmulq_lane_f32(mv0, vget_low_f32(v2), 0);
+
+ rv0 = vmlaq_lane_f32(rv0, mv1, vget_low_f32(v0), 1);
+ rv1 = vmlaq_lane_f32(rv1, mv1, vget_low_f32(v1), 1);
+ rv2 = vmlaq_lane_f32(rv2, mv1, vget_low_f32(v2), 1);
+
+ rv0 = vmlaq_lane_f32(rv0, mv2, vget_high_f32(v0), 0);
+ rv1 = vmlaq_lane_f32(rv1, mv2, vget_high_f32(v1), 0);
+ rv2 = vmlaq_lane_f32(rv2, mv2, vget_high_f32(v2), 0);
+
+ m_el[0].mVec128 = rv0;
+ m_el[1].mVec128 = rv1;
+ m_el[2].mVec128 = rv2;
+#else
+ setValue(
+ m.tdotx(m_el[0]), m.tdoty(m_el[0]), m.tdotz(m_el[0]),
+ m.tdotx(m_el[1]), m.tdoty(m_el[1]), m.tdotz(m_el[1]),
+ m.tdotx(m_el[2]), m.tdoty(m_el[2]), m.tdotz(m_el[2]));
+#endif
+ return *this;
+}
+
+SIMD_FORCE_INLINE btMatrix3x3&
+btMatrix3x3::operator+=(const btMatrix3x3& m)
+{
+#if (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE))|| defined (BT_USE_NEON)
+ m_el[0].mVec128 = m_el[0].mVec128 + m.m_el[0].mVec128;
+ m_el[1].mVec128 = m_el[1].mVec128 + m.m_el[1].mVec128;
+ m_el[2].mVec128 = m_el[2].mVec128 + m.m_el[2].mVec128;
+#else
+ setValue(
+ m_el[0][0]+m.m_el[0][0],
+ m_el[0][1]+m.m_el[0][1],
+ m_el[0][2]+m.m_el[0][2],
+ m_el[1][0]+m.m_el[1][0],
+ m_el[1][1]+m.m_el[1][1],
+ m_el[1][2]+m.m_el[1][2],
+ m_el[2][0]+m.m_el[2][0],
+ m_el[2][1]+m.m_el[2][1],
+ m_el[2][2]+m.m_el[2][2]);
+#endif
+ return *this;
+}
+
+SIMD_FORCE_INLINE btMatrix3x3
+operator*(const btMatrix3x3& m, const btScalar & k)
+{
+#if (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE))
+ __m128 vk = bt_splat_ps(_mm_load_ss((float *)&k), 0x80);
+ return btMatrix3x3(
+ _mm_mul_ps(m[0].mVec128, vk),
+ _mm_mul_ps(m[1].mVec128, vk),
+ _mm_mul_ps(m[2].mVec128, vk));
+#elif defined(BT_USE_NEON)
+ return btMatrix3x3(
+ vmulq_n_f32(m[0].mVec128, k),
+ vmulq_n_f32(m[1].mVec128, k),
+ vmulq_n_f32(m[2].mVec128, k));
+#else
+ return btMatrix3x3(
+ m[0].x()*k,m[0].y()*k,m[0].z()*k,
+ m[1].x()*k,m[1].y()*k,m[1].z()*k,
+ m[2].x()*k,m[2].y()*k,m[2].z()*k);
+#endif
+}
+
+SIMD_FORCE_INLINE btMatrix3x3
+operator+(const btMatrix3x3& m1, const btMatrix3x3& m2)
+{
+#if (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE))|| defined (BT_USE_NEON)
+ return btMatrix3x3(
+ m1[0].mVec128 + m2[0].mVec128,
+ m1[1].mVec128 + m2[1].mVec128,
+ m1[2].mVec128 + m2[2].mVec128);
+#else
+ return btMatrix3x3(
+ m1[0][0]+m2[0][0],
+ m1[0][1]+m2[0][1],
+ m1[0][2]+m2[0][2],
+
+ m1[1][0]+m2[1][0],
+ m1[1][1]+m2[1][1],
+ m1[1][2]+m2[1][2],
+
+ m1[2][0]+m2[2][0],
+ m1[2][1]+m2[2][1],
+ m1[2][2]+m2[2][2]);
+#endif
+}
+
+SIMD_FORCE_INLINE btMatrix3x3
+operator-(const btMatrix3x3& m1, const btMatrix3x3& m2)
+{
+#if (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE))|| defined (BT_USE_NEON)
+ return btMatrix3x3(
+ m1[0].mVec128 - m2[0].mVec128,
+ m1[1].mVec128 - m2[1].mVec128,
+ m1[2].mVec128 - m2[2].mVec128);
+#else
+ return btMatrix3x3(
+ m1[0][0]-m2[0][0],
+ m1[0][1]-m2[0][1],
+ m1[0][2]-m2[0][2],
+
+ m1[1][0]-m2[1][0],
+ m1[1][1]-m2[1][1],
+ m1[1][2]-m2[1][2],
+
+ m1[2][0]-m2[2][0],
+ m1[2][1]-m2[2][1],
+ m1[2][2]-m2[2][2]);
+#endif
+}
+
+
+SIMD_FORCE_INLINE btMatrix3x3&
+btMatrix3x3::operator-=(const btMatrix3x3& m)
+{
+#if (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE))|| defined (BT_USE_NEON)
+ m_el[0].mVec128 = m_el[0].mVec128 - m.m_el[0].mVec128;
+ m_el[1].mVec128 = m_el[1].mVec128 - m.m_el[1].mVec128;
+ m_el[2].mVec128 = m_el[2].mVec128 - m.m_el[2].mVec128;
+#else
+ setValue(
+ m_el[0][0]-m.m_el[0][0],
+ m_el[0][1]-m.m_el[0][1],
+ m_el[0][2]-m.m_el[0][2],
+ m_el[1][0]-m.m_el[1][0],
+ m_el[1][1]-m.m_el[1][1],
+ m_el[1][2]-m.m_el[1][2],
+ m_el[2][0]-m.m_el[2][0],
+ m_el[2][1]-m.m_el[2][1],
+ m_el[2][2]-m.m_el[2][2]);
+#endif
+ return *this;
+}
+
+
+SIMD_FORCE_INLINE btScalar
+btMatrix3x3::determinant() const
+{
+ return btTriple((*this)[0], (*this)[1], (*this)[2]);
+}
+
+
+SIMD_FORCE_INLINE btMatrix3x3
+btMatrix3x3::absolute() const
+{
+#if defined BT_USE_SIMD_VECTOR3 && (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE))
+ return btMatrix3x3(
+ _mm_and_ps(m_el[0].mVec128, btvAbsfMask),
+ _mm_and_ps(m_el[1].mVec128, btvAbsfMask),
+ _mm_and_ps(m_el[2].mVec128, btvAbsfMask));
+#elif defined(BT_USE_NEON)
+ return btMatrix3x3(
+ (float32x4_t)vandq_s32((int32x4_t)m_el[0].mVec128, btv3AbsMask),
+ (float32x4_t)vandq_s32((int32x4_t)m_el[1].mVec128, btv3AbsMask),
+ (float32x4_t)vandq_s32((int32x4_t)m_el[2].mVec128, btv3AbsMask));
+#else
+ return btMatrix3x3(
+ btFabs(m_el[0].x()), btFabs(m_el[0].y()), btFabs(m_el[0].z()),
+ btFabs(m_el[1].x()), btFabs(m_el[1].y()), btFabs(m_el[1].z()),
+ btFabs(m_el[2].x()), btFabs(m_el[2].y()), btFabs(m_el[2].z()));
+#endif
+}
+
+SIMD_FORCE_INLINE btMatrix3x3
+btMatrix3x3::transpose() const
+{
+#if defined BT_USE_SIMD_VECTOR3 && (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE))
+ __m128 v0 = m_el[0].mVec128;
+ __m128 v1 = m_el[1].mVec128;
+ __m128 v2 = m_el[2].mVec128; // x2 y2 z2 w2
+ __m128 vT;
+
+ v2 = _mm_and_ps(v2, btvFFF0fMask); // x2 y2 z2 0
+
+ vT = _mm_unpackhi_ps(v0, v1); // z0 z1 * *
+ v0 = _mm_unpacklo_ps(v0, v1); // x0 x1 y0 y1
+
+ v1 = _mm_shuffle_ps(v0, v2, BT_SHUFFLE(2, 3, 1, 3) ); // y0 y1 y2 0
+ v0 = _mm_shuffle_ps(v0, v2, BT_SHUFFLE(0, 1, 0, 3) ); // x0 x1 x2 0
+ v2 = btCastdTo128f(_mm_move_sd(btCastfTo128d(v2), btCastfTo128d(vT))); // z0 z1 z2 0
+
+
+ return btMatrix3x3( v0, v1, v2 );
+#elif defined(BT_USE_NEON)
+ // note: zeros the w channel. We can preserve it at the cost of two more vtrn instructions.
+ static const uint32x2_t zMask = (const uint32x2_t) {static_cast<uint32_t>(-1), 0 };
+ float32x4x2_t top = vtrnq_f32( m_el[0].mVec128, m_el[1].mVec128 ); // {x0 x1 z0 z1}, {y0 y1 w0 w1}
+ float32x2x2_t bl = vtrn_f32( vget_low_f32(m_el[2].mVec128), vdup_n_f32(0.0f) ); // {x2 0 }, {y2 0}
+ float32x4_t v0 = vcombine_f32( vget_low_f32(top.val[0]), bl.val[0] );
+ float32x4_t v1 = vcombine_f32( vget_low_f32(top.val[1]), bl.val[1] );
+ float32x2_t q = (float32x2_t) vand_u32( (uint32x2_t) vget_high_f32( m_el[2].mVec128), zMask );
+ float32x4_t v2 = vcombine_f32( vget_high_f32(top.val[0]), q ); // z0 z1 z2 0
+ return btMatrix3x3( v0, v1, v2 );
+#else
+ return btMatrix3x3( m_el[0].x(), m_el[1].x(), m_el[2].x(),
+ m_el[0].y(), m_el[1].y(), m_el[2].y(),
+ m_el[0].z(), m_el[1].z(), m_el[2].z());
+#endif
+}
+
+SIMD_FORCE_INLINE btMatrix3x3
+btMatrix3x3::adjoint() const
+{
+ return btMatrix3x3(cofac(1, 1, 2, 2), cofac(0, 2, 2, 1), cofac(0, 1, 1, 2),
+ cofac(1, 2, 2, 0), cofac(0, 0, 2, 2), cofac(0, 2, 1, 0),
+ cofac(1, 0, 2, 1), cofac(0, 1, 2, 0), cofac(0, 0, 1, 1));
+}
+
+SIMD_FORCE_INLINE btMatrix3x3
+btMatrix3x3::inverse() const
+{
+ btVector3 co(cofac(1, 1, 2, 2), cofac(1, 2, 2, 0), cofac(1, 0, 2, 1));
+ btScalar det = (*this)[0].dot(co);
+ //btFullAssert(det != btScalar(0.0));
+ btAssert(det != btScalar(0.0));
+ btScalar s = btScalar(1.0) / det;
+ return btMatrix3x3(co.x() * s, cofac(0, 2, 2, 1) * s, cofac(0, 1, 1, 2) * s,
+ co.y() * s, cofac(0, 0, 2, 2) * s, cofac(0, 2, 1, 0) * s,
+ co.z() * s, cofac(0, 1, 2, 0) * s, cofac(0, 0, 1, 1) * s);
+}
+
+SIMD_FORCE_INLINE btMatrix3x3
+btMatrix3x3::transposeTimes(const btMatrix3x3& m) const
+{
+#if defined BT_USE_SIMD_VECTOR3 && (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE))
+ // zeros w
+// static const __m128i xyzMask = (const __m128i){ -1ULL, 0xffffffffULL };
+ __m128 row = m_el[0].mVec128;
+ __m128 m0 = _mm_and_ps( m.getRow(0).mVec128, btvFFF0fMask );
+ __m128 m1 = _mm_and_ps( m.getRow(1).mVec128, btvFFF0fMask);
+ __m128 m2 = _mm_and_ps( m.getRow(2).mVec128, btvFFF0fMask );
+ __m128 r0 = _mm_mul_ps(m0, _mm_shuffle_ps(row, row, 0));
+ __m128 r1 = _mm_mul_ps(m0, _mm_shuffle_ps(row, row, 0x55));
+ __m128 r2 = _mm_mul_ps(m0, _mm_shuffle_ps(row, row, 0xaa));
+ row = m_el[1].mVec128;
+ r0 = _mm_add_ps( r0, _mm_mul_ps(m1, _mm_shuffle_ps(row, row, 0)));
+ r1 = _mm_add_ps( r1, _mm_mul_ps(m1, _mm_shuffle_ps(row, row, 0x55)));
+ r2 = _mm_add_ps( r2, _mm_mul_ps(m1, _mm_shuffle_ps(row, row, 0xaa)));
+ row = m_el[2].mVec128;
+ r0 = _mm_add_ps( r0, _mm_mul_ps(m2, _mm_shuffle_ps(row, row, 0)));
+ r1 = _mm_add_ps( r1, _mm_mul_ps(m2, _mm_shuffle_ps(row, row, 0x55)));
+ r2 = _mm_add_ps( r2, _mm_mul_ps(m2, _mm_shuffle_ps(row, row, 0xaa)));
+ return btMatrix3x3( r0, r1, r2 );
+
+#elif defined BT_USE_NEON
+ // zeros w
+ static const uint32x4_t xyzMask = (const uint32x4_t){ static_cast<uint32_t>(-1), static_cast<uint32_t>(-1), static_cast<uint32_t>(-1), 0 };
+ float32x4_t m0 = (float32x4_t) vandq_u32( (uint32x4_t) m.getRow(0).mVec128, xyzMask );
+ float32x4_t m1 = (float32x4_t) vandq_u32( (uint32x4_t) m.getRow(1).mVec128, xyzMask );
+ float32x4_t m2 = (float32x4_t) vandq_u32( (uint32x4_t) m.getRow(2).mVec128, xyzMask );
+ float32x4_t row = m_el[0].mVec128;
+ float32x4_t r0 = vmulq_lane_f32( m0, vget_low_f32(row), 0);
+ float32x4_t r1 = vmulq_lane_f32( m0, vget_low_f32(row), 1);
+ float32x4_t r2 = vmulq_lane_f32( m0, vget_high_f32(row), 0);
+ row = m_el[1].mVec128;
+ r0 = vmlaq_lane_f32( r0, m1, vget_low_f32(row), 0);
+ r1 = vmlaq_lane_f32( r1, m1, vget_low_f32(row), 1);
+ r2 = vmlaq_lane_f32( r2, m1, vget_high_f32(row), 0);
+ row = m_el[2].mVec128;
+ r0 = vmlaq_lane_f32( r0, m2, vget_low_f32(row), 0);
+ r1 = vmlaq_lane_f32( r1, m2, vget_low_f32(row), 1);
+ r2 = vmlaq_lane_f32( r2, m2, vget_high_f32(row), 0);
+ return btMatrix3x3( r0, r1, r2 );
+#else
+ return btMatrix3x3(
+ m_el[0].x() * m[0].x() + m_el[1].x() * m[1].x() + m_el[2].x() * m[2].x(),
+ m_el[0].x() * m[0].y() + m_el[1].x() * m[1].y() + m_el[2].x() * m[2].y(),
+ m_el[0].x() * m[0].z() + m_el[1].x() * m[1].z() + m_el[2].x() * m[2].z(),
+ m_el[0].y() * m[0].x() + m_el[1].y() * m[1].x() + m_el[2].y() * m[2].x(),
+ m_el[0].y() * m[0].y() + m_el[1].y() * m[1].y() + m_el[2].y() * m[2].y(),
+ m_el[0].y() * m[0].z() + m_el[1].y() * m[1].z() + m_el[2].y() * m[2].z(),
+ m_el[0].z() * m[0].x() + m_el[1].z() * m[1].x() + m_el[2].z() * m[2].x(),
+ m_el[0].z() * m[0].y() + m_el[1].z() * m[1].y() + m_el[2].z() * m[2].y(),
+ m_el[0].z() * m[0].z() + m_el[1].z() * m[1].z() + m_el[2].z() * m[2].z());
+#endif
+}
+
+SIMD_FORCE_INLINE btMatrix3x3
+btMatrix3x3::timesTranspose(const btMatrix3x3& m) const
+{
+#if (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE))
+ __m128 a0 = m_el[0].mVec128;
+ __m128 a1 = m_el[1].mVec128;
+ __m128 a2 = m_el[2].mVec128;
+
+ btMatrix3x3 mT = m.transpose(); // we rely on transpose() zeroing w channel so that we don't have to do it here
+ __m128 mx = mT[0].mVec128;
+ __m128 my = mT[1].mVec128;
+ __m128 mz = mT[2].mVec128;
+
+ __m128 r0 = _mm_mul_ps(mx, _mm_shuffle_ps(a0, a0, 0x00));
+ __m128 r1 = _mm_mul_ps(mx, _mm_shuffle_ps(a1, a1, 0x00));
+ __m128 r2 = _mm_mul_ps(mx, _mm_shuffle_ps(a2, a2, 0x00));
+ r0 = _mm_add_ps(r0, _mm_mul_ps(my, _mm_shuffle_ps(a0, a0, 0x55)));
+ r1 = _mm_add_ps(r1, _mm_mul_ps(my, _mm_shuffle_ps(a1, a1, 0x55)));
+ r2 = _mm_add_ps(r2, _mm_mul_ps(my, _mm_shuffle_ps(a2, a2, 0x55)));
+ r0 = _mm_add_ps(r0, _mm_mul_ps(mz, _mm_shuffle_ps(a0, a0, 0xaa)));
+ r1 = _mm_add_ps(r1, _mm_mul_ps(mz, _mm_shuffle_ps(a1, a1, 0xaa)));
+ r2 = _mm_add_ps(r2, _mm_mul_ps(mz, _mm_shuffle_ps(a2, a2, 0xaa)));
+ return btMatrix3x3( r0, r1, r2);
+
+#elif defined BT_USE_NEON
+ float32x4_t a0 = m_el[0].mVec128;
+ float32x4_t a1 = m_el[1].mVec128;
+ float32x4_t a2 = m_el[2].mVec128;
+
+ btMatrix3x3 mT = m.transpose(); // we rely on transpose() zeroing w channel so that we don't have to do it here
+ float32x4_t mx = mT[0].mVec128;
+ float32x4_t my = mT[1].mVec128;
+ float32x4_t mz = mT[2].mVec128;
+
+ float32x4_t r0 = vmulq_lane_f32( mx, vget_low_f32(a0), 0);
+ float32x4_t r1 = vmulq_lane_f32( mx, vget_low_f32(a1), 0);
+ float32x4_t r2 = vmulq_lane_f32( mx, vget_low_f32(a2), 0);
+ r0 = vmlaq_lane_f32( r0, my, vget_low_f32(a0), 1);
+ r1 = vmlaq_lane_f32( r1, my, vget_low_f32(a1), 1);
+ r2 = vmlaq_lane_f32( r2, my, vget_low_f32(a2), 1);
+ r0 = vmlaq_lane_f32( r0, mz, vget_high_f32(a0), 0);
+ r1 = vmlaq_lane_f32( r1, mz, vget_high_f32(a1), 0);
+ r2 = vmlaq_lane_f32( r2, mz, vget_high_f32(a2), 0);
+ return btMatrix3x3( r0, r1, r2 );
+
+#else
+ return btMatrix3x3(
+ m_el[0].dot(m[0]), m_el[0].dot(m[1]), m_el[0].dot(m[2]),
+ m_el[1].dot(m[0]), m_el[1].dot(m[1]), m_el[1].dot(m[2]),
+ m_el[2].dot(m[0]), m_el[2].dot(m[1]), m_el[2].dot(m[2]));
+#endif
+}
+
+SIMD_FORCE_INLINE btVector3
+operator*(const btMatrix3x3& m, const btVector3& v)
+{
+#if (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE))|| defined (BT_USE_NEON)
+ return v.dot3(m[0], m[1], m[2]);
+#else
+ return btVector3(m[0].dot(v), m[1].dot(v), m[2].dot(v));
+#endif
+}
+
+
+SIMD_FORCE_INLINE btVector3
+operator*(const btVector3& v, const btMatrix3x3& m)
+{
+#if defined BT_USE_SIMD_VECTOR3 && (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE))
+
+ const __m128 vv = v.mVec128;
+
+ __m128 c0 = bt_splat_ps( vv, 0);
+ __m128 c1 = bt_splat_ps( vv, 1);
+ __m128 c2 = bt_splat_ps( vv, 2);
+
+ c0 = _mm_mul_ps(c0, _mm_and_ps(m[0].mVec128, btvFFF0fMask) );
+ c1 = _mm_mul_ps(c1, _mm_and_ps(m[1].mVec128, btvFFF0fMask) );
+ c0 = _mm_add_ps(c0, c1);
+ c2 = _mm_mul_ps(c2, _mm_and_ps(m[2].mVec128, btvFFF0fMask) );
+
+ return btVector3(_mm_add_ps(c0, c2));
+#elif defined(BT_USE_NEON)
+ const float32x4_t vv = v.mVec128;
+ const float32x2_t vlo = vget_low_f32(vv);
+ const float32x2_t vhi = vget_high_f32(vv);
+
+ float32x4_t c0, c1, c2;
+
+ c0 = (float32x4_t) vandq_s32((int32x4_t)m[0].mVec128, btvFFF0Mask);
+ c1 = (float32x4_t) vandq_s32((int32x4_t)m[1].mVec128, btvFFF0Mask);
+ c2 = (float32x4_t) vandq_s32((int32x4_t)m[2].mVec128, btvFFF0Mask);
+
+ c0 = vmulq_lane_f32(c0, vlo, 0);
+ c1 = vmulq_lane_f32(c1, vlo, 1);
+ c2 = vmulq_lane_f32(c2, vhi, 0);
+ c0 = vaddq_f32(c0, c1);
+ c0 = vaddq_f32(c0, c2);
+
+ return btVector3(c0);
+#else
+ return btVector3(m.tdotx(v), m.tdoty(v), m.tdotz(v));
+#endif
+}
+
+SIMD_FORCE_INLINE btMatrix3x3
+operator*(const btMatrix3x3& m1, const btMatrix3x3& m2)
+{
+#if defined BT_USE_SIMD_VECTOR3 && (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE))
+
+ __m128 m10 = m1[0].mVec128;
+ __m128 m11 = m1[1].mVec128;
+ __m128 m12 = m1[2].mVec128;
+
+ __m128 m2v = _mm_and_ps(m2[0].mVec128, btvFFF0fMask);
+
+ __m128 c0 = bt_splat_ps( m10, 0);
+ __m128 c1 = bt_splat_ps( m11, 0);
+ __m128 c2 = bt_splat_ps( m12, 0);
+
+ c0 = _mm_mul_ps(c0, m2v);
+ c1 = _mm_mul_ps(c1, m2v);
+ c2 = _mm_mul_ps(c2, m2v);
+
+ m2v = _mm_and_ps(m2[1].mVec128, btvFFF0fMask);
+
+ __m128 c0_1 = bt_splat_ps( m10, 1);
+ __m128 c1_1 = bt_splat_ps( m11, 1);
+ __m128 c2_1 = bt_splat_ps( m12, 1);
+
+ c0_1 = _mm_mul_ps(c0_1, m2v);
+ c1_1 = _mm_mul_ps(c1_1, m2v);
+ c2_1 = _mm_mul_ps(c2_1, m2v);
+
+ m2v = _mm_and_ps(m2[2].mVec128, btvFFF0fMask);
+
+ c0 = _mm_add_ps(c0, c0_1);
+ c1 = _mm_add_ps(c1, c1_1);
+ c2 = _mm_add_ps(c2, c2_1);
+
+ m10 = bt_splat_ps( m10, 2);
+ m11 = bt_splat_ps( m11, 2);
+ m12 = bt_splat_ps( m12, 2);
+
+ m10 = _mm_mul_ps(m10, m2v);
+ m11 = _mm_mul_ps(m11, m2v);
+ m12 = _mm_mul_ps(m12, m2v);
+
+ c0 = _mm_add_ps(c0, m10);
+ c1 = _mm_add_ps(c1, m11);
+ c2 = _mm_add_ps(c2, m12);
+
+ return btMatrix3x3(c0, c1, c2);
+
+#elif defined(BT_USE_NEON)
+
+ float32x4_t rv0, rv1, rv2;
+ float32x4_t v0, v1, v2;
+ float32x4_t mv0, mv1, mv2;
+
+ v0 = m1[0].mVec128;
+ v1 = m1[1].mVec128;
+ v2 = m1[2].mVec128;
+
+ mv0 = (float32x4_t) vandq_s32((int32x4_t)m2[0].mVec128, btvFFF0Mask);
+ mv1 = (float32x4_t) vandq_s32((int32x4_t)m2[1].mVec128, btvFFF0Mask);
+ mv2 = (float32x4_t) vandq_s32((int32x4_t)m2[2].mVec128, btvFFF0Mask);
+
+ rv0 = vmulq_lane_f32(mv0, vget_low_f32(v0), 0);
+ rv1 = vmulq_lane_f32(mv0, vget_low_f32(v1), 0);
+ rv2 = vmulq_lane_f32(mv0, vget_low_f32(v2), 0);
+
+ rv0 = vmlaq_lane_f32(rv0, mv1, vget_low_f32(v0), 1);
+ rv1 = vmlaq_lane_f32(rv1, mv1, vget_low_f32(v1), 1);
+ rv2 = vmlaq_lane_f32(rv2, mv1, vget_low_f32(v2), 1);
+
+ rv0 = vmlaq_lane_f32(rv0, mv2, vget_high_f32(v0), 0);
+ rv1 = vmlaq_lane_f32(rv1, mv2, vget_high_f32(v1), 0);
+ rv2 = vmlaq_lane_f32(rv2, mv2, vget_high_f32(v2), 0);
+
+ return btMatrix3x3(rv0, rv1, rv2);
+
+#else
+ return btMatrix3x3(
+ m2.tdotx( m1[0]), m2.tdoty( m1[0]), m2.tdotz( m1[0]),
+ m2.tdotx( m1[1]), m2.tdoty( m1[1]), m2.tdotz( m1[1]),
+ m2.tdotx( m1[2]), m2.tdoty( m1[2]), m2.tdotz( m1[2]));
+#endif
+}
+
+/*
+SIMD_FORCE_INLINE btMatrix3x3 btMultTransposeLeft(const btMatrix3x3& m1, const btMatrix3x3& m2) {
+return btMatrix3x3(
+m1[0][0] * m2[0][0] + m1[1][0] * m2[1][0] + m1[2][0] * m2[2][0],
+m1[0][0] * m2[0][1] + m1[1][0] * m2[1][1] + m1[2][0] * m2[2][1],
+m1[0][0] * m2[0][2] + m1[1][0] * m2[1][2] + m1[2][0] * m2[2][2],
+m1[0][1] * m2[0][0] + m1[1][1] * m2[1][0] + m1[2][1] * m2[2][0],
+m1[0][1] * m2[0][1] + m1[1][1] * m2[1][1] + m1[2][1] * m2[2][1],
+m1[0][1] * m2[0][2] + m1[1][1] * m2[1][2] + m1[2][1] * m2[2][2],
+m1[0][2] * m2[0][0] + m1[1][2] * m2[1][0] + m1[2][2] * m2[2][0],
+m1[0][2] * m2[0][1] + m1[1][2] * m2[1][1] + m1[2][2] * m2[2][1],
+m1[0][2] * m2[0][2] + m1[1][2] * m2[1][2] + m1[2][2] * m2[2][2]);
+}
+*/
+
+/**@brief Equality operator between two matrices
+* It will test all elements are equal. */
+SIMD_FORCE_INLINE bool operator==(const btMatrix3x3& m1, const btMatrix3x3& m2)
+{
+#if (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE))
+
+ __m128 c0, c1, c2;
+
+ c0 = _mm_cmpeq_ps(m1[0].mVec128, m2[0].mVec128);
+ c1 = _mm_cmpeq_ps(m1[1].mVec128, m2[1].mVec128);
+ c2 = _mm_cmpeq_ps(m1[2].mVec128, m2[2].mVec128);
+
+ c0 = _mm_and_ps(c0, c1);
+ c0 = _mm_and_ps(c0, c2);
+
+ int m = _mm_movemask_ps((__m128)c0);
+ return (0x7 == (m & 0x7));
+
+#else
+ return
+ ( m1[0][0] == m2[0][0] && m1[1][0] == m2[1][0] && m1[2][0] == m2[2][0] &&
+ m1[0][1] == m2[0][1] && m1[1][1] == m2[1][1] && m1[2][1] == m2[2][1] &&
+ m1[0][2] == m2[0][2] && m1[1][2] == m2[1][2] && m1[2][2] == m2[2][2] );
+#endif
+}
+
+///for serialization
+struct btMatrix3x3FloatData
+{
+ btVector3FloatData m_el[3];
+};
+
+///for serialization
+struct btMatrix3x3DoubleData
+{
+ btVector3DoubleData m_el[3];
+};
+
+
+
+
+SIMD_FORCE_INLINE void btMatrix3x3::serialize(struct btMatrix3x3Data& dataOut) const
+{
+ for (int i=0;i<3;i++)
+ m_el[i].serialize(dataOut.m_el[i]);
+}
+
+SIMD_FORCE_INLINE void btMatrix3x3::serializeFloat(struct btMatrix3x3FloatData& dataOut) const
+{
+ for (int i=0;i<3;i++)
+ m_el[i].serializeFloat(dataOut.m_el[i]);
+}
+
+
+SIMD_FORCE_INLINE void btMatrix3x3::deSerialize(const struct btMatrix3x3Data& dataIn)
+{
+ for (int i=0;i<3;i++)
+ m_el[i].deSerialize(dataIn.m_el[i]);
+}
+
+SIMD_FORCE_INLINE void btMatrix3x3::deSerializeFloat(const struct btMatrix3x3FloatData& dataIn)
+{
+ for (int i=0;i<3;i++)
+ m_el[i].deSerializeFloat(dataIn.m_el[i]);
+}
+
+SIMD_FORCE_INLINE void btMatrix3x3::deSerializeDouble(const struct btMatrix3x3DoubleData& dataIn)
+{
+ for (int i=0;i<3;i++)
+ m_el[i].deSerializeDouble(dataIn.m_el[i]);
+}
+
+#endif //BT_MATRIX3x3_H
+
diff --git a/thirdparty/bullet/src/LinearMath/btMatrixX.h b/thirdparty/bullet/src/LinearMath/btMatrixX.h
new file mode 100644
index 0000000000..42caed42ef
--- /dev/null
+++ b/thirdparty/bullet/src/LinearMath/btMatrixX.h
@@ -0,0 +1,554 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2013 Erwin Coumans 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.
+*/
+///original version written by Erwin Coumans, October 2013
+
+#ifndef BT_MATRIX_X_H
+#define BT_MATRIX_X_H
+
+#include "LinearMath/btQuickprof.h"
+#include "LinearMath/btAlignedObjectArray.h"
+#include <stdio.h>
+
+//#define BT_DEBUG_OSTREAM
+#ifdef BT_DEBUG_OSTREAM
+#include <iostream>
+#include <iomanip> // std::setw
+#endif //BT_DEBUG_OSTREAM
+
+class btIntSortPredicate
+{
+ public:
+ bool operator() ( const int& a, const int& b ) const
+ {
+ return a < b;
+ }
+};
+
+
+template <typename T>
+struct btVectorX
+{
+ btAlignedObjectArray<T> m_storage;
+
+ btVectorX()
+ {
+ }
+ btVectorX(int numRows)
+ {
+ m_storage.resize(numRows);
+ }
+
+ void resize(int rows)
+ {
+ m_storage.resize(rows);
+ }
+ int cols() const
+ {
+ return 1;
+ }
+ int rows() const
+ {
+ return m_storage.size();
+ }
+ int size() const
+ {
+ return rows();
+ }
+
+ T nrm2() const
+ {
+ T norm = T(0);
+
+ int nn = rows();
+
+ {
+ if (nn == 1)
+ {
+ norm = btFabs((*this)[0]);
+ }
+ else
+ {
+ T scale = 0.0;
+ T ssq = 1.0;
+
+ /* The following loop is equivalent to this call to the LAPACK
+ auxiliary routine: CALL SLASSQ( N, X, INCX, SCALE, SSQ ) */
+
+ for (int ix=0;ix<nn;ix++)
+ {
+ if ((*this)[ix] != 0.0)
+ {
+ T absxi = btFabs((*this)[ix]);
+ if (scale < absxi)
+ {
+ T temp;
+ temp = scale / absxi;
+ ssq = ssq * (temp * temp) + BT_ONE;
+ scale = absxi;
+ }
+ else
+ {
+ T temp;
+ temp = absxi / scale;
+ ssq += temp * temp;
+ }
+ }
+ }
+ norm = scale * sqrt(ssq);
+ }
+ }
+ return norm;
+
+ }
+ void setZero()
+ {
+ if (m_storage.size())
+ {
+ // for (int i=0;i<m_storage.size();i++)
+ // m_storage[i]=0;
+ //memset(&m_storage[0],0,sizeof(T)*m_storage.size());
+ btSetZero(&m_storage[0],m_storage.size());
+ }
+ }
+ const T& operator[] (int index) const
+ {
+ return m_storage[index];
+ }
+
+ T& operator[] (int index)
+ {
+ return m_storage[index];
+ }
+
+ T* getBufferPointerWritable()
+ {
+ return m_storage.size() ? &m_storage[0] : 0;
+ }
+
+ const T* getBufferPointer() const
+ {
+ return m_storage.size() ? &m_storage[0] : 0;
+ }
+
+};
+/*
+ template <typename T>
+ void setElem(btMatrixX<T>& mat, int row, int col, T val)
+ {
+ mat.setElem(row,col,val);
+ }
+ */
+
+
+template <typename T>
+struct btMatrixX
+{
+ int m_rows;
+ int m_cols;
+ int m_operations;
+ int m_resizeOperations;
+ int m_setElemOperations;
+
+ btAlignedObjectArray<T> m_storage;
+ mutable btAlignedObjectArray< btAlignedObjectArray<int> > m_rowNonZeroElements1;
+
+ T* getBufferPointerWritable()
+ {
+ return m_storage.size() ? &m_storage[0] : 0;
+ }
+
+ const T* getBufferPointer() const
+ {
+ return m_storage.size() ? &m_storage[0] : 0;
+ }
+ btMatrixX()
+ :m_rows(0),
+ m_cols(0),
+ m_operations(0),
+ m_resizeOperations(0),
+ m_setElemOperations(0)
+ {
+ }
+ btMatrixX(int rows,int cols)
+ :m_rows(rows),
+ m_cols(cols),
+ m_operations(0),
+ m_resizeOperations(0),
+ m_setElemOperations(0)
+ {
+ resize(rows,cols);
+ }
+ void resize(int rows, int cols)
+ {
+ m_resizeOperations++;
+ m_rows = rows;
+ m_cols = cols;
+ {
+ BT_PROFILE("m_storage.resize");
+ m_storage.resize(rows*cols);
+ }
+ }
+ int cols() const
+ {
+ return m_cols;
+ }
+ int rows() const
+ {
+ return m_rows;
+ }
+ ///we don't want this read/write operator(), because we cannot keep track of non-zero elements, use setElem instead
+ /*T& operator() (int row,int col)
+ {
+ return m_storage[col*m_rows+row];
+ }
+ */
+
+ void addElem(int row,int col, T val)
+ {
+ if (val)
+ {
+ if (m_storage[col+row*m_cols]==0.f)
+ {
+ setElem(row,col,val);
+ } else
+ {
+ m_storage[row*m_cols+col] += val;
+ }
+ }
+ }
+
+
+ void setElem(int row,int col, T val)
+ {
+ m_setElemOperations++;
+ m_storage[row*m_cols+col] = val;
+ }
+
+ void mulElem(int row,int col, T val)
+ {
+ m_setElemOperations++;
+ //mul doesn't change sparsity info
+
+ m_storage[row*m_cols+col] *= val;
+ }
+
+
+
+
+ void copyLowerToUpperTriangle()
+ {
+ int count=0;
+ for (int row=0;row<rows();row++)
+ {
+ for (int col=0;col<row;col++)
+ {
+ setElem(col,row, (*this)(row,col));
+ count++;
+
+ }
+ }
+ //printf("copyLowerToUpperTriangle copied %d elements out of %dx%d=%d\n", count,rows(),cols(),cols()*rows());
+ }
+
+ const T& operator() (int row,int col) const
+ {
+ return m_storage[col+row*m_cols];
+ }
+
+
+ void setZero()
+ {
+ {
+ BT_PROFILE("storage=0");
+ btSetZero(&m_storage[0],m_storage.size());
+ //memset(&m_storage[0],0,sizeof(T)*m_storage.size());
+ //for (int i=0;i<m_storage.size();i++)
+ // m_storage[i]=0;
+ }
+ }
+
+ void setIdentity()
+ {
+ btAssert(rows() == cols());
+
+ setZero();
+ for (int row=0;row<rows();row++)
+ {
+ setElem(row,row,1);
+ }
+ }
+
+
+
+ void printMatrix(const char* msg)
+ {
+ printf("%s ---------------------\n",msg);
+ for (int i=0;i<rows();i++)
+ {
+ printf("\n");
+ for (int j=0;j<cols();j++)
+ {
+ printf("%2.1f\t",(*this)(i,j));
+ }
+ }
+ printf("\n---------------------\n");
+
+ }
+
+
+ void rowComputeNonZeroElements() const
+ {
+ m_rowNonZeroElements1.resize(rows());
+ for (int i=0;i<rows();i++)
+ {
+ m_rowNonZeroElements1[i].resize(0);
+ for (int j=0;j<cols();j++)
+ {
+ if ((*this)(i,j)!=0.f)
+ {
+ m_rowNonZeroElements1[i].push_back(j);
+ }
+ }
+ }
+ }
+ btMatrixX transpose() const
+ {
+ //transpose is optimized for sparse matrices
+ btMatrixX tr(m_cols,m_rows);
+ tr.setZero();
+ for (int i=0;i<m_cols;i++)
+ for (int j=0;j<m_rows;j++)
+ {
+ T v = (*this)(j,i);
+ if (v)
+ {
+ tr.setElem(i,j,v);
+ }
+ }
+ return tr;
+ }
+
+
+ btMatrixX operator*(const btMatrixX& other)
+ {
+ //btMatrixX*btMatrixX implementation, brute force
+ btAssert(cols() == other.rows());
+
+ btMatrixX res(rows(),other.cols());
+ res.setZero();
+// BT_PROFILE("btMatrixX mul");
+ for (int j=0; j < res.cols(); ++j)
+ {
+ {
+ for (int i=0; i < res.rows(); ++i)
+ {
+ T dotProd=0;
+// T dotProd2=0;
+ //int waste=0,waste2=0;
+
+ {
+// bool useOtherCol = true;
+ {
+ for (int v=0;v<rows();v++)
+ {
+ T w = (*this)(i,v);
+ if (other(v,j)!=0.f)
+ {
+ dotProd+=w*other(v,j);
+ }
+
+ }
+ }
+ }
+ if (dotProd)
+ res.setElem(i,j,dotProd);
+ }
+ }
+ }
+ return res;
+ }
+
+ // this assumes the 4th and 8th rows of B and C are zero.
+ void multiplyAdd2_p8r (const btScalar *B, const btScalar *C, int numRows, int numRowsOther ,int row, int col)
+ {
+ const btScalar *bb = B;
+ for ( int i = 0;i<numRows;i++)
+ {
+ const btScalar *cc = C;
+ for ( int j = 0;j<numRowsOther;j++)
+ {
+ btScalar sum;
+ sum = bb[0]*cc[0];
+ sum += bb[1]*cc[1];
+ sum += bb[2]*cc[2];
+ sum += bb[4]*cc[4];
+ sum += bb[5]*cc[5];
+ sum += bb[6]*cc[6];
+ addElem(row+i,col+j,sum);
+ cc += 8;
+ }
+ bb += 8;
+ }
+ }
+
+ void multiply2_p8r (const btScalar *B, const btScalar *C, int numRows, int numRowsOther, int row, int col)
+ {
+ btAssert (numRows>0 && numRowsOther>0 && B && C);
+ const btScalar *bb = B;
+ for ( int i = 0;i<numRows;i++)
+ {
+ const btScalar *cc = C;
+ for ( int j = 0;j<numRowsOther;j++)
+ {
+ btScalar sum;
+ sum = bb[0]*cc[0];
+ sum += bb[1]*cc[1];
+ sum += bb[2]*cc[2];
+ sum += bb[4]*cc[4];
+ sum += bb[5]*cc[5];
+ sum += bb[6]*cc[6];
+ setElem(row+i,col+j,sum);
+ cc += 8;
+ }
+ bb += 8;
+ }
+ }
+
+ void setSubMatrix(int rowstart,int colstart,int rowend,int colend,const T value)
+ {
+ int numRows = rowend+1-rowstart;
+ int numCols = colend+1-colstart;
+
+ for (int row=0;row<numRows;row++)
+ {
+ for (int col=0;col<numCols;col++)
+ {
+ setElem(rowstart+row,colstart+col,value);
+ }
+ }
+ }
+
+ void setSubMatrix(int rowstart,int colstart,int rowend,int colend,const btMatrixX& block)
+ {
+ btAssert(rowend+1-rowstart == block.rows());
+ btAssert(colend+1-colstart == block.cols());
+ for (int row=0;row<block.rows();row++)
+ {
+ for (int col=0;col<block.cols();col++)
+ {
+ setElem(rowstart+row,colstart+col,block(row,col));
+ }
+ }
+ }
+ void setSubMatrix(int rowstart,int colstart,int rowend,int colend,const btVectorX<T>& block)
+ {
+ btAssert(rowend+1-rowstart == block.rows());
+ btAssert(colend+1-colstart == block.cols());
+ for (int row=0;row<block.rows();row++)
+ {
+ for (int col=0;col<block.cols();col++)
+ {
+ setElem(rowstart+row,colstart+col,block[row]);
+ }
+ }
+ }
+
+
+ btMatrixX negative()
+ {
+ btMatrixX neg(rows(),cols());
+ for (int i=0;i<rows();i++)
+ for (int j=0;j<cols();j++)
+ {
+ T v = (*this)(i,j);
+ neg.setElem(i,j,-v);
+ }
+ return neg;
+ }
+
+};
+
+
+
+typedef btMatrixX<float> btMatrixXf;
+typedef btVectorX<float> btVectorXf;
+
+typedef btMatrixX<double> btMatrixXd;
+typedef btVectorX<double> btVectorXd;
+
+
+#ifdef BT_DEBUG_OSTREAM
+template <typename T>
+std::ostream& operator<< (std::ostream& os, const btMatrixX<T>& mat)
+ {
+
+ os << " [";
+ //printf("%s ---------------------\n",msg);
+ for (int i=0;i<mat.rows();i++)
+ {
+ for (int j=0;j<mat.cols();j++)
+ {
+ os << std::setw(12) << mat(i,j);
+ }
+ if (i!=mat.rows()-1)
+ os << std::endl << " ";
+ }
+ os << " ]";
+ //printf("\n---------------------\n");
+
+ return os;
+ }
+template <typename T>
+std::ostream& operator<< (std::ostream& os, const btVectorX<T>& mat)
+ {
+
+ os << " [";
+ //printf("%s ---------------------\n",msg);
+ for (int i=0;i<mat.rows();i++)
+ {
+ os << std::setw(12) << mat[i];
+ if (i!=mat.rows()-1)
+ os << std::endl << " ";
+ }
+ os << " ]";
+ //printf("\n---------------------\n");
+
+ return os;
+ }
+
+#endif //BT_DEBUG_OSTREAM
+
+
+inline void setElem(btMatrixXd& mat, int row, int col, double val)
+{
+ mat.setElem(row,col,val);
+}
+
+inline void setElem(btMatrixXf& mat, int row, int col, float val)
+{
+ mat.setElem(row,col,val);
+}
+
+#ifdef BT_USE_DOUBLE_PRECISION
+ #define btVectorXu btVectorXd
+ #define btMatrixXu btMatrixXd
+#else
+ #define btVectorXu btVectorXf
+ #define btMatrixXu btMatrixXf
+#endif //BT_USE_DOUBLE_PRECISION
+
+
+
+#endif//BT_MATRIX_H_H
diff --git a/thirdparty/bullet/src/LinearMath/btMinMax.h b/thirdparty/bullet/src/LinearMath/btMinMax.h
new file mode 100644
index 0000000000..5b436e9ba4
--- /dev/null
+++ b/thirdparty/bullet/src/LinearMath/btMinMax.h
@@ -0,0 +1,71 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+#ifndef BT_GEN_MINMAX_H
+#define BT_GEN_MINMAX_H
+
+#include "btScalar.h"
+
+template <class T>
+SIMD_FORCE_INLINE const T& btMin(const T& a, const T& b)
+{
+ return a < b ? a : b ;
+}
+
+template <class T>
+SIMD_FORCE_INLINE const T& btMax(const T& a, const T& b)
+{
+ return a > b ? a : b;
+}
+
+template <class T>
+SIMD_FORCE_INLINE const T& btClamped(const T& a, const T& lb, const T& ub)
+{
+ return a < lb ? lb : (ub < a ? ub : a);
+}
+
+template <class T>
+SIMD_FORCE_INLINE void btSetMin(T& a, const T& b)
+{
+ if (b < a)
+ {
+ a = b;
+ }
+}
+
+template <class T>
+SIMD_FORCE_INLINE void btSetMax(T& a, const T& b)
+{
+ if (a < b)
+ {
+ a = b;
+ }
+}
+
+template <class T>
+SIMD_FORCE_INLINE void btClamp(T& a, const T& lb, const T& ub)
+{
+ if (a < lb)
+ {
+ a = lb;
+ }
+ else if (ub < a)
+ {
+ a = ub;
+ }
+}
+
+#endif //BT_GEN_MINMAX_H
diff --git a/thirdparty/bullet/src/LinearMath/btMotionState.h b/thirdparty/bullet/src/LinearMath/btMotionState.h
new file mode 100644
index 0000000000..9431814090
--- /dev/null
+++ b/thirdparty/bullet/src/LinearMath/btMotionState.h
@@ -0,0 +1,40 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_MOTIONSTATE_H
+#define BT_MOTIONSTATE_H
+
+#include "btTransform.h"
+
+///The btMotionState interface class allows the dynamics world to synchronize and interpolate the updated world transforms with graphics
+///For optimizations, potentially only moving objects get synchronized (using setWorldPosition/setWorldOrientation)
+class btMotionState
+{
+ public:
+
+ virtual ~btMotionState()
+ {
+
+ }
+
+ virtual void getWorldTransform(btTransform& worldTrans ) const =0;
+
+ //Bullet only calls the update of worldtransform for active objects
+ virtual void setWorldTransform(const btTransform& worldTrans)=0;
+
+
+};
+
+#endif //BT_MOTIONSTATE_H
diff --git a/thirdparty/bullet/src/LinearMath/btPolarDecomposition.cpp b/thirdparty/bullet/src/LinearMath/btPolarDecomposition.cpp
new file mode 100644
index 0000000000..b3664faa4e
--- /dev/null
+++ b/thirdparty/bullet/src/LinearMath/btPolarDecomposition.cpp
@@ -0,0 +1,98 @@
+#include "btPolarDecomposition.h"
+#include "btMinMax.h"
+
+namespace
+{
+ btScalar abs_column_sum(const btMatrix3x3& a, int i)
+ {
+ return btFabs(a[0][i]) + btFabs(a[1][i]) + btFabs(a[2][i]);
+ }
+
+ btScalar abs_row_sum(const btMatrix3x3& a, int i)
+ {
+ return btFabs(a[i][0]) + btFabs(a[i][1]) + btFabs(a[i][2]);
+ }
+
+ btScalar p1_norm(const btMatrix3x3& a)
+ {
+ const btScalar sum0 = abs_column_sum(a,0);
+ const btScalar sum1 = abs_column_sum(a,1);
+ const btScalar sum2 = abs_column_sum(a,2);
+ return btMax(btMax(sum0, sum1), sum2);
+ }
+
+ btScalar pinf_norm(const btMatrix3x3& a)
+ {
+ const btScalar sum0 = abs_row_sum(a,0);
+ const btScalar sum1 = abs_row_sum(a,1);
+ const btScalar sum2 = abs_row_sum(a,2);
+ return btMax(btMax(sum0, sum1), sum2);
+ }
+}
+
+
+
+btPolarDecomposition::btPolarDecomposition(btScalar tolerance, unsigned int maxIterations)
+: m_tolerance(tolerance)
+, m_maxIterations(maxIterations)
+{
+}
+
+unsigned int btPolarDecomposition::decompose(const btMatrix3x3& a, btMatrix3x3& u, btMatrix3x3& h) const
+{
+ // Use the 'u' and 'h' matrices for intermediate calculations
+ u = a;
+ h = a.inverse();
+
+ for (unsigned int i = 0; i < m_maxIterations; ++i)
+ {
+ const btScalar h_1 = p1_norm(h);
+ const btScalar h_inf = pinf_norm(h);
+ const btScalar u_1 = p1_norm(u);
+ const btScalar u_inf = pinf_norm(u);
+
+ const btScalar h_norm = h_1 * h_inf;
+ const btScalar u_norm = u_1 * u_inf;
+
+ // The matrix is effectively singular so we cannot invert it
+ if (btFuzzyZero(h_norm) || btFuzzyZero(u_norm))
+ break;
+
+ const btScalar gamma = btPow(h_norm / u_norm, 0.25f);
+ const btScalar inv_gamma = btScalar(1.0) / gamma;
+
+ // Determine the delta to 'u'
+ const btMatrix3x3 delta = (u * (gamma - btScalar(2.0)) + h.transpose() * inv_gamma) * btScalar(0.5);
+
+ // Update the matrices
+ u += delta;
+ h = u.inverse();
+
+ // Check for convergence
+ if (p1_norm(delta) <= m_tolerance * u_1)
+ {
+ h = u.transpose() * a;
+ h = (h + h.transpose()) * 0.5;
+ return i;
+ }
+ }
+
+ // The algorithm has failed to converge to the specified tolerance, but we
+ // want to make sure that the matrices returned are in the right form.
+ h = u.transpose() * a;
+ h = (h + h.transpose()) * 0.5;
+
+ return m_maxIterations;
+}
+
+unsigned int btPolarDecomposition::maxIterations() const
+{
+ return m_maxIterations;
+}
+
+unsigned int polarDecompose(const btMatrix3x3& a, btMatrix3x3& u, btMatrix3x3& h)
+{
+ static btPolarDecomposition polar;
+ return polar.decompose(a, u, h);
+}
+
diff --git a/thirdparty/bullet/src/LinearMath/btPolarDecomposition.h b/thirdparty/bullet/src/LinearMath/btPolarDecomposition.h
new file mode 100644
index 0000000000..1feea0f78e
--- /dev/null
+++ b/thirdparty/bullet/src/LinearMath/btPolarDecomposition.h
@@ -0,0 +1,72 @@
+#ifndef POLARDECOMPOSITION_H
+#define POLARDECOMPOSITION_H
+
+#include "btMatrix3x3.h"
+
+/**
+ * This class is used to compute the polar decomposition of a matrix. In
+ * general, the polar decomposition factorizes a matrix, A, into two parts: a
+ * unitary matrix (U) and a positive, semi-definite Hermitian matrix (H).
+ * However, in this particular implementation the original matrix, A, is
+ * required to be a square 3x3 matrix with real elements. This means that U will
+ * be an orthogonal matrix and H with be a positive-definite, symmetric matrix.
+ */
+class btPolarDecomposition
+{
+ public:
+
+
+ /**
+ * Creates an instance with optional parameters.
+ *
+ * @param tolerance - the tolerance used to determine convergence of the
+ * algorithm
+ * @param maxIterations - the maximum number of iterations used to achieve
+ * convergence
+ */
+ btPolarDecomposition(btScalar tolerance = btScalar(0.0001),
+ unsigned int maxIterations = 16);
+
+ /**
+ * Decomposes a matrix into orthogonal and symmetric, positive-definite
+ * parts. If the number of iterations returned by this function is equal to
+ * the maximum number of iterations, the algorithm has failed to converge.
+ *
+ * @param a - the original matrix
+ * @param u - the resulting orthogonal matrix
+ * @param h - the resulting symmetric matrix
+ *
+ * @return the number of iterations performed by the algorithm.
+ */
+ unsigned int decompose(const btMatrix3x3& a, btMatrix3x3& u, btMatrix3x3& h) const;
+
+ /**
+ * Returns the maximum number of iterations that this algorithm will perform
+ * to achieve convergence.
+ *
+ * @return maximum number of iterations
+ */
+ unsigned int maxIterations() const;
+
+ private:
+ btScalar m_tolerance;
+ unsigned int m_maxIterations;
+};
+
+/**
+ * This functions decomposes the matrix 'a' into two parts: an orthogonal matrix
+ * 'u' and a symmetric, positive-definite matrix 'h'. If the number of
+ * iterations returned by this function is equal to
+ * btPolarDecomposition::DEFAULT_MAX_ITERATIONS, the algorithm has failed to
+ * converge.
+ *
+ * @param a - the original matrix
+ * @param u - the resulting orthogonal matrix
+ * @param h - the resulting symmetric matrix
+ *
+ * @return the number of iterations performed by the algorithm.
+ */
+unsigned int polarDecompose(const btMatrix3x3& a, btMatrix3x3& u, btMatrix3x3& h);
+
+#endif // POLARDECOMPOSITION_H
+
diff --git a/thirdparty/bullet/src/LinearMath/btPoolAllocator.h b/thirdparty/bullet/src/LinearMath/btPoolAllocator.h
new file mode 100644
index 0000000000..efdeda8ffc
--- /dev/null
+++ b/thirdparty/bullet/src/LinearMath/btPoolAllocator.h
@@ -0,0 +1,130 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#ifndef _BT_POOL_ALLOCATOR_H
+#define _BT_POOL_ALLOCATOR_H
+
+#include "btScalar.h"
+#include "btAlignedAllocator.h"
+#include "btThreads.h"
+
+///The btPoolAllocator class allows to efficiently allocate a large pool of objects, instead of dynamically allocating them separately.
+class btPoolAllocator
+{
+ int m_elemSize;
+ int m_maxElements;
+ int m_freeCount;
+ void* m_firstFree;
+ unsigned char* m_pool;
+ btSpinMutex m_mutex; // only used if BT_THREADSAFE
+
+public:
+
+ btPoolAllocator(int elemSize, int maxElements)
+ :m_elemSize(elemSize),
+ m_maxElements(maxElements)
+ {
+ m_pool = (unsigned char*) btAlignedAlloc( static_cast<unsigned int>(m_elemSize*m_maxElements),16);
+
+ unsigned char* p = m_pool;
+ m_firstFree = p;
+ m_freeCount = m_maxElements;
+ int count = m_maxElements;
+ while (--count) {
+ *(void**)p = (p + m_elemSize);
+ p += m_elemSize;
+ }
+ *(void**)p = 0;
+ }
+
+ ~btPoolAllocator()
+ {
+ btAlignedFree( m_pool);
+ }
+
+ int getFreeCount() const
+ {
+ return m_freeCount;
+ }
+
+ int getUsedCount() const
+ {
+ return m_maxElements - m_freeCount;
+ }
+
+ int getMaxCount() const
+ {
+ return m_maxElements;
+ }
+
+ void* allocate(int size)
+ {
+ // release mode fix
+ (void)size;
+ btMutexLock(&m_mutex);
+ btAssert(!size || size<=m_elemSize);
+ //btAssert(m_freeCount>0); // should return null if all full
+ void* result = m_firstFree;
+ if (NULL != m_firstFree)
+ {
+ m_firstFree = *(void**)m_firstFree;
+ --m_freeCount;
+ }
+ btMutexUnlock(&m_mutex);
+ return result;
+ }
+
+ bool validPtr(void* ptr)
+ {
+ if (ptr) {
+ if (((unsigned char*)ptr >= m_pool && (unsigned char*)ptr < m_pool + m_maxElements * m_elemSize))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ void freeMemory(void* ptr)
+ {
+ if (ptr) {
+ btAssert((unsigned char*)ptr >= m_pool && (unsigned char*)ptr < m_pool + m_maxElements * m_elemSize);
+
+ btMutexLock(&m_mutex);
+ *(void**)ptr = m_firstFree;
+ m_firstFree = ptr;
+ ++m_freeCount;
+ btMutexUnlock(&m_mutex);
+ }
+ }
+
+ int getElementSize() const
+ {
+ return m_elemSize;
+ }
+
+ unsigned char* getPoolAddress()
+ {
+ return m_pool;
+ }
+
+ const unsigned char* getPoolAddress() const
+ {
+ return m_pool;
+ }
+
+};
+
+#endif //_BT_POOL_ALLOCATOR_H
diff --git a/thirdparty/bullet/src/LinearMath/btQuadWord.h b/thirdparty/bullet/src/LinearMath/btQuadWord.h
new file mode 100644
index 0000000000..fcfb3be444
--- /dev/null
+++ b/thirdparty/bullet/src/LinearMath/btQuadWord.h
@@ -0,0 +1,244 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#ifndef BT_SIMD_QUADWORD_H
+#define BT_SIMD_QUADWORD_H
+
+#include "btScalar.h"
+#include "btMinMax.h"
+
+
+
+
+
+#if defined (__CELLOS_LV2) && defined (__SPU__)
+#include <altivec.h>
+#endif
+
+/**@brief The btQuadWord class is base class for btVector3 and btQuaternion.
+ * Some issues under PS3 Linux with IBM 2.1 SDK, gcc compiler prevent from using aligned quadword.
+ */
+#ifndef USE_LIBSPE2
+ATTRIBUTE_ALIGNED16(class) btQuadWord
+#else
+class btQuadWord
+#endif
+{
+protected:
+
+#if defined (__SPU__) && defined (__CELLOS_LV2__)
+ union {
+ vec_float4 mVec128;
+ btScalar m_floats[4];
+ };
+public:
+ vec_float4 get128() const
+ {
+ return mVec128;
+ }
+protected:
+#else //__CELLOS_LV2__ __SPU__
+
+#if defined(BT_USE_SSE) || defined(BT_USE_NEON)
+ union {
+ btSimdFloat4 mVec128;
+ btScalar m_floats[4];
+ };
+public:
+ SIMD_FORCE_INLINE btSimdFloat4 get128() const
+ {
+ return mVec128;
+ }
+ SIMD_FORCE_INLINE void set128(btSimdFloat4 v128)
+ {
+ mVec128 = v128;
+ }
+#else
+ btScalar m_floats[4];
+#endif // BT_USE_SSE
+
+#endif //__CELLOS_LV2__ __SPU__
+
+ public:
+
+#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)) || defined(BT_USE_NEON)
+
+ // Set Vector
+ SIMD_FORCE_INLINE btQuadWord(const btSimdFloat4 vec)
+ {
+ mVec128 = vec;
+ }
+
+ // Copy constructor
+ SIMD_FORCE_INLINE btQuadWord(const btQuadWord& rhs)
+ {
+ mVec128 = rhs.mVec128;
+ }
+
+ // Assignment Operator
+ SIMD_FORCE_INLINE btQuadWord&
+ operator=(const btQuadWord& v)
+ {
+ mVec128 = v.mVec128;
+
+ return *this;
+ }
+
+#endif
+
+ /**@brief Return the x value */
+ SIMD_FORCE_INLINE const btScalar& getX() const { return m_floats[0]; }
+ /**@brief Return the y value */
+ SIMD_FORCE_INLINE const btScalar& getY() const { return m_floats[1]; }
+ /**@brief Return the z value */
+ SIMD_FORCE_INLINE const btScalar& getZ() const { return m_floats[2]; }
+ /**@brief Set the x value */
+ SIMD_FORCE_INLINE void setX(btScalar _x) { m_floats[0] = _x;};
+ /**@brief Set the y value */
+ SIMD_FORCE_INLINE void setY(btScalar _y) { m_floats[1] = _y;};
+ /**@brief Set the z value */
+ SIMD_FORCE_INLINE void setZ(btScalar _z) { m_floats[2] = _z;};
+ /**@brief Set the w value */
+ SIMD_FORCE_INLINE void setW(btScalar _w) { m_floats[3] = _w;};
+ /**@brief Return the x value */
+ SIMD_FORCE_INLINE const btScalar& x() const { return m_floats[0]; }
+ /**@brief Return the y value */
+ SIMD_FORCE_INLINE const btScalar& y() const { return m_floats[1]; }
+ /**@brief Return the z value */
+ SIMD_FORCE_INLINE const btScalar& z() const { return m_floats[2]; }
+ /**@brief Return the w value */
+ SIMD_FORCE_INLINE const btScalar& w() const { return m_floats[3]; }
+
+ //SIMD_FORCE_INLINE btScalar& operator[](int i) { return (&m_floats[0])[i]; }
+ //SIMD_FORCE_INLINE const btScalar& operator[](int i) const { return (&m_floats[0])[i]; }
+ ///operator btScalar*() replaces operator[], using implicit conversion. We added operator != and operator == to avoid pointer comparisons.
+ SIMD_FORCE_INLINE operator btScalar *() { return &m_floats[0]; }
+ SIMD_FORCE_INLINE operator const btScalar *() const { return &m_floats[0]; }
+
+ SIMD_FORCE_INLINE bool operator==(const btQuadWord& other) const
+ {
+#ifdef BT_USE_SSE
+ return (0xf == _mm_movemask_ps((__m128)_mm_cmpeq_ps(mVec128, other.mVec128)));
+#else
+ return ((m_floats[3]==other.m_floats[3]) &&
+ (m_floats[2]==other.m_floats[2]) &&
+ (m_floats[1]==other.m_floats[1]) &&
+ (m_floats[0]==other.m_floats[0]));
+#endif
+ }
+
+ SIMD_FORCE_INLINE bool operator!=(const btQuadWord& other) const
+ {
+ return !(*this == other);
+ }
+
+ /**@brief Set x,y,z and zero w
+ * @param x Value of x
+ * @param y Value of y
+ * @param z Value of z
+ */
+ SIMD_FORCE_INLINE void setValue(const btScalar& _x, const btScalar& _y, const btScalar& _z)
+ {
+ m_floats[0]=_x;
+ m_floats[1]=_y;
+ m_floats[2]=_z;
+ m_floats[3] = 0.f;
+ }
+
+/* void getValue(btScalar *m) const
+ {
+ m[0] = m_floats[0];
+ m[1] = m_floats[1];
+ m[2] = m_floats[2];
+ }
+*/
+/**@brief Set the values
+ * @param x Value of x
+ * @param y Value of y
+ * @param z Value of z
+ * @param w Value of w
+ */
+ SIMD_FORCE_INLINE void setValue(const btScalar& _x, const btScalar& _y, const btScalar& _z,const btScalar& _w)
+ {
+ m_floats[0]=_x;
+ m_floats[1]=_y;
+ m_floats[2]=_z;
+ m_floats[3]=_w;
+ }
+ /**@brief No initialization constructor */
+ SIMD_FORCE_INLINE btQuadWord()
+ // :m_floats[0](btScalar(0.)),m_floats[1](btScalar(0.)),m_floats[2](btScalar(0.)),m_floats[3](btScalar(0.))
+ {
+ }
+
+ /**@brief Three argument constructor (zeros w)
+ * @param x Value of x
+ * @param y Value of y
+ * @param z Value of z
+ */
+ SIMD_FORCE_INLINE btQuadWord(const btScalar& _x, const btScalar& _y, const btScalar& _z)
+ {
+ m_floats[0] = _x, m_floats[1] = _y, m_floats[2] = _z, m_floats[3] = 0.0f;
+ }
+
+/**@brief Initializing constructor
+ * @param x Value of x
+ * @param y Value of y
+ * @param z Value of z
+ * @param w Value of w
+ */
+ SIMD_FORCE_INLINE btQuadWord(const btScalar& _x, const btScalar& _y, const btScalar& _z,const btScalar& _w)
+ {
+ m_floats[0] = _x, m_floats[1] = _y, m_floats[2] = _z, m_floats[3] = _w;
+ }
+
+ /**@brief Set each element to the max of the current values and the values of another btQuadWord
+ * @param other The other btQuadWord to compare with
+ */
+ SIMD_FORCE_INLINE void setMax(const btQuadWord& other)
+ {
+ #ifdef BT_USE_SSE
+ mVec128 = _mm_max_ps(mVec128, other.mVec128);
+ #elif defined(BT_USE_NEON)
+ mVec128 = vmaxq_f32(mVec128, other.mVec128);
+ #else
+ btSetMax(m_floats[0], other.m_floats[0]);
+ btSetMax(m_floats[1], other.m_floats[1]);
+ btSetMax(m_floats[2], other.m_floats[2]);
+ btSetMax(m_floats[3], other.m_floats[3]);
+ #endif
+ }
+ /**@brief Set each element to the min of the current values and the values of another btQuadWord
+ * @param other The other btQuadWord to compare with
+ */
+ SIMD_FORCE_INLINE void setMin(const btQuadWord& other)
+ {
+ #ifdef BT_USE_SSE
+ mVec128 = _mm_min_ps(mVec128, other.mVec128);
+ #elif defined(BT_USE_NEON)
+ mVec128 = vminq_f32(mVec128, other.mVec128);
+ #else
+ btSetMin(m_floats[0], other.m_floats[0]);
+ btSetMin(m_floats[1], other.m_floats[1]);
+ btSetMin(m_floats[2], other.m_floats[2]);
+ btSetMin(m_floats[3], other.m_floats[3]);
+ #endif
+ }
+
+
+
+};
+
+#endif //BT_SIMD_QUADWORD_H
diff --git a/thirdparty/bullet/src/LinearMath/btQuaternion.h b/thirdparty/bullet/src/LinearMath/btQuaternion.h
new file mode 100644
index 0000000000..7bd39e6a33
--- /dev/null
+++ b/thirdparty/bullet/src/LinearMath/btQuaternion.h
@@ -0,0 +1,1016 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+#ifndef BT_SIMD__QUATERNION_H_
+#define BT_SIMD__QUATERNION_H_
+
+
+#include "btVector3.h"
+#include "btQuadWord.h"
+
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define btQuaternionData btQuaternionDoubleData
+#define btQuaternionDataName "btQuaternionDoubleData"
+#else
+#define btQuaternionData btQuaternionFloatData
+#define btQuaternionDataName "btQuaternionFloatData"
+#endif //BT_USE_DOUBLE_PRECISION
+
+
+
+#ifdef BT_USE_SSE
+
+//const __m128 ATTRIBUTE_ALIGNED16(vOnes) = {1.0f, 1.0f, 1.0f, 1.0f};
+#define vOnes (_mm_set_ps(1.0f, 1.0f, 1.0f, 1.0f))
+
+#endif
+
+#if defined(BT_USE_SSE)
+
+#define vQInv (_mm_set_ps(+0.0f, -0.0f, -0.0f, -0.0f))
+#define vPPPM (_mm_set_ps(-0.0f, +0.0f, +0.0f, +0.0f))
+
+#elif defined(BT_USE_NEON)
+
+const btSimdFloat4 ATTRIBUTE_ALIGNED16(vQInv) = {-0.0f, -0.0f, -0.0f, +0.0f};
+const btSimdFloat4 ATTRIBUTE_ALIGNED16(vPPPM) = {+0.0f, +0.0f, +0.0f, -0.0f};
+
+#endif
+
+/**@brief The btQuaternion implements quaternion to perform linear algebra rotations in combination with btMatrix3x3, btVector3 and btTransform. */
+class btQuaternion : public btQuadWord {
+public:
+ /**@brief No initialization constructor */
+ btQuaternion() {}
+
+#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE))|| defined(BT_USE_NEON)
+ // Set Vector
+ SIMD_FORCE_INLINE btQuaternion(const btSimdFloat4 vec)
+ {
+ mVec128 = vec;
+ }
+
+ // Copy constructor
+ SIMD_FORCE_INLINE btQuaternion(const btQuaternion& rhs)
+ {
+ mVec128 = rhs.mVec128;
+ }
+
+ // Assignment Operator
+ SIMD_FORCE_INLINE btQuaternion&
+ operator=(const btQuaternion& v)
+ {
+ mVec128 = v.mVec128;
+
+ return *this;
+ }
+
+#endif
+
+ // template <typename btScalar>
+ // explicit Quaternion(const btScalar *v) : Tuple4<btScalar>(v) {}
+ /**@brief Constructor from scalars */
+ btQuaternion(const btScalar& _x, const btScalar& _y, const btScalar& _z, const btScalar& _w)
+ : btQuadWord(_x, _y, _z, _w)
+ {}
+ /**@brief Axis angle Constructor
+ * @param axis The axis which the rotation is around
+ * @param angle The magnitude of the rotation around the angle (Radians) */
+ btQuaternion(const btVector3& _axis, const btScalar& _angle)
+ {
+ setRotation(_axis, _angle);
+ }
+ /**@brief Constructor from Euler angles
+ * @param yaw Angle around Y unless BT_EULER_DEFAULT_ZYX defined then Z
+ * @param pitch Angle around X unless BT_EULER_DEFAULT_ZYX defined then Y
+ * @param roll Angle around Z unless BT_EULER_DEFAULT_ZYX defined then X */
+ btQuaternion(const btScalar& yaw, const btScalar& pitch, const btScalar& roll)
+ {
+#ifndef BT_EULER_DEFAULT_ZYX
+ setEuler(yaw, pitch, roll);
+#else
+ setEulerZYX(yaw, pitch, roll);
+#endif
+ }
+ /**@brief Set the rotation using axis angle notation
+ * @param axis The axis around which to rotate
+ * @param angle The magnitude of the rotation in Radians */
+ void setRotation(const btVector3& axis, const btScalar& _angle)
+ {
+ btScalar d = axis.length();
+ btAssert(d != btScalar(0.0));
+ btScalar s = btSin(_angle * btScalar(0.5)) / d;
+ setValue(axis.x() * s, axis.y() * s, axis.z() * s,
+ btCos(_angle * btScalar(0.5)));
+ }
+ /**@brief Set the quaternion using Euler angles
+ * @param yaw Angle around Y
+ * @param pitch Angle around X
+ * @param roll Angle around Z */
+ void setEuler(const btScalar& yaw, const btScalar& pitch, const btScalar& roll)
+ {
+ btScalar halfYaw = btScalar(yaw) * btScalar(0.5);
+ btScalar halfPitch = btScalar(pitch) * btScalar(0.5);
+ btScalar halfRoll = btScalar(roll) * btScalar(0.5);
+ btScalar cosYaw = btCos(halfYaw);
+ btScalar sinYaw = btSin(halfYaw);
+ btScalar cosPitch = btCos(halfPitch);
+ btScalar sinPitch = btSin(halfPitch);
+ btScalar cosRoll = btCos(halfRoll);
+ btScalar sinRoll = btSin(halfRoll);
+ setValue(cosRoll * sinPitch * cosYaw + sinRoll * cosPitch * sinYaw,
+ cosRoll * cosPitch * sinYaw - sinRoll * sinPitch * cosYaw,
+ sinRoll * cosPitch * cosYaw - cosRoll * sinPitch * sinYaw,
+ cosRoll * cosPitch * cosYaw + sinRoll * sinPitch * sinYaw);
+ }
+ /**@brief Set the quaternion using euler angles
+ * @param yaw Angle around Z
+ * @param pitch Angle around Y
+ * @param roll Angle around X */
+ void setEulerZYX(const btScalar& yawZ, const btScalar& pitchY, const btScalar& rollX)
+ {
+ btScalar halfYaw = btScalar(yawZ) * btScalar(0.5);
+ btScalar halfPitch = btScalar(pitchY) * btScalar(0.5);
+ btScalar halfRoll = btScalar(rollX) * btScalar(0.5);
+ btScalar cosYaw = btCos(halfYaw);
+ btScalar sinYaw = btSin(halfYaw);
+ btScalar cosPitch = btCos(halfPitch);
+ btScalar sinPitch = btSin(halfPitch);
+ btScalar cosRoll = btCos(halfRoll);
+ btScalar sinRoll = btSin(halfRoll);
+ setValue(sinRoll * cosPitch * cosYaw - cosRoll * sinPitch * sinYaw, //x
+ cosRoll * sinPitch * cosYaw + sinRoll * cosPitch * sinYaw, //y
+ cosRoll * cosPitch * sinYaw - sinRoll * sinPitch * cosYaw, //z
+ cosRoll * cosPitch * cosYaw + sinRoll * sinPitch * sinYaw); //formerly yzx
+ }
+
+ /**@brief Get the euler angles from this quaternion
+ * @param yaw Angle around Z
+ * @param pitch Angle around Y
+ * @param roll Angle around X */
+ void getEulerZYX(btScalar& yawZ, btScalar& pitchY, btScalar& rollX) const
+ {
+ btScalar squ;
+ btScalar sqx;
+ btScalar sqy;
+ btScalar sqz;
+ btScalar sarg;
+ sqx = m_floats[0] * m_floats[0];
+ sqy = m_floats[1] * m_floats[1];
+ sqz = m_floats[2] * m_floats[2];
+ squ = m_floats[3] * m_floats[3];
+ rollX = btAtan2(2 * (m_floats[1] * m_floats[2] + m_floats[3] * m_floats[0]), squ - sqx - sqy + sqz);
+ sarg = btScalar(-2.) * (m_floats[0] * m_floats[2] - m_floats[3] * m_floats[1]);
+ pitchY = sarg <= btScalar(-1.0) ? btScalar(-0.5) * SIMD_PI: (sarg >= btScalar(1.0) ? btScalar(0.5) * SIMD_PI : btAsin(sarg));
+ yawZ = btAtan2(2 * (m_floats[0] * m_floats[1] + m_floats[3] * m_floats[2]), squ + sqx - sqy - sqz);
+ }
+
+ /**@brief Add two quaternions
+ * @param q The quaternion to add to this one */
+ SIMD_FORCE_INLINE btQuaternion& operator+=(const btQuaternion& q)
+ {
+#if defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ mVec128 = _mm_add_ps(mVec128, q.mVec128);
+#elif defined(BT_USE_NEON)
+ mVec128 = vaddq_f32(mVec128, q.mVec128);
+#else
+ m_floats[0] += q.x();
+ m_floats[1] += q.y();
+ m_floats[2] += q.z();
+ m_floats[3] += q.m_floats[3];
+#endif
+ return *this;
+ }
+
+ /**@brief Subtract out a quaternion
+ * @param q The quaternion to subtract from this one */
+ btQuaternion& operator-=(const btQuaternion& q)
+ {
+#if defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ mVec128 = _mm_sub_ps(mVec128, q.mVec128);
+#elif defined(BT_USE_NEON)
+ mVec128 = vsubq_f32(mVec128, q.mVec128);
+#else
+ m_floats[0] -= q.x();
+ m_floats[1] -= q.y();
+ m_floats[2] -= q.z();
+ m_floats[3] -= q.m_floats[3];
+#endif
+ return *this;
+ }
+
+ /**@brief Scale this quaternion
+ * @param s The scalar to scale by */
+ btQuaternion& operator*=(const btScalar& s)
+ {
+#if defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ __m128 vs = _mm_load_ss(&s); // (S 0 0 0)
+ vs = bt_pshufd_ps(vs, 0); // (S S S S)
+ mVec128 = _mm_mul_ps(mVec128, vs);
+#elif defined(BT_USE_NEON)
+ mVec128 = vmulq_n_f32(mVec128, s);
+#else
+ m_floats[0] *= s;
+ m_floats[1] *= s;
+ m_floats[2] *= s;
+ m_floats[3] *= s;
+#endif
+ return *this;
+ }
+
+ /**@brief Multiply this quaternion by q on the right
+ * @param q The other quaternion
+ * Equivilant to this = this * q */
+ btQuaternion& operator*=(const btQuaternion& q)
+ {
+#if defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ __m128 vQ2 = q.get128();
+
+ __m128 A1 = bt_pshufd_ps(mVec128, BT_SHUFFLE(0,1,2,0));
+ __m128 B1 = bt_pshufd_ps(vQ2, BT_SHUFFLE(3,3,3,0));
+
+ A1 = A1 * B1;
+
+ __m128 A2 = bt_pshufd_ps(mVec128, BT_SHUFFLE(1,2,0,1));
+ __m128 B2 = bt_pshufd_ps(vQ2, BT_SHUFFLE(2,0,1,1));
+
+ A2 = A2 * B2;
+
+ B1 = bt_pshufd_ps(mVec128, BT_SHUFFLE(2,0,1,2));
+ B2 = bt_pshufd_ps(vQ2, BT_SHUFFLE(1,2,0,2));
+
+ B1 = B1 * B2; // A3 *= B3
+
+ mVec128 = bt_splat_ps(mVec128, 3); // A0
+ mVec128 = mVec128 * vQ2; // A0 * B0
+
+ A1 = A1 + A2; // AB12
+ mVec128 = mVec128 - B1; // AB03 = AB0 - AB3
+ A1 = _mm_xor_ps(A1, vPPPM); // change sign of the last element
+ mVec128 = mVec128+ A1; // AB03 + AB12
+
+#elif defined(BT_USE_NEON)
+
+ float32x4_t vQ1 = mVec128;
+ float32x4_t vQ2 = q.get128();
+ float32x4_t A0, A1, B1, A2, B2, A3, B3;
+ float32x2_t vQ1zx, vQ2wx, vQ1yz, vQ2zx, vQ2yz, vQ2xz;
+
+ {
+ float32x2x2_t tmp;
+ tmp = vtrn_f32( vget_high_f32(vQ1), vget_low_f32(vQ1) ); // {z x}, {w y}
+ vQ1zx = tmp.val[0];
+
+ tmp = vtrn_f32( vget_high_f32(vQ2), vget_low_f32(vQ2) ); // {z x}, {w y}
+ vQ2zx = tmp.val[0];
+ }
+ vQ2wx = vext_f32(vget_high_f32(vQ2), vget_low_f32(vQ2), 1);
+
+ vQ1yz = vext_f32(vget_low_f32(vQ1), vget_high_f32(vQ1), 1);
+
+ vQ2yz = vext_f32(vget_low_f32(vQ2), vget_high_f32(vQ2), 1);
+ vQ2xz = vext_f32(vQ2zx, vQ2zx, 1);
+
+ A1 = vcombine_f32(vget_low_f32(vQ1), vQ1zx); // X Y z x
+ B1 = vcombine_f32(vdup_lane_f32(vget_high_f32(vQ2), 1), vQ2wx); // W W W X
+
+ A2 = vcombine_f32(vQ1yz, vget_low_f32(vQ1));
+ B2 = vcombine_f32(vQ2zx, vdup_lane_f32(vget_low_f32(vQ2), 1));
+
+ A3 = vcombine_f32(vQ1zx, vQ1yz); // Z X Y Z
+ B3 = vcombine_f32(vQ2yz, vQ2xz); // Y Z x z
+
+ A1 = vmulq_f32(A1, B1);
+ A2 = vmulq_f32(A2, B2);
+ A3 = vmulq_f32(A3, B3); // A3 *= B3
+ A0 = vmulq_lane_f32(vQ2, vget_high_f32(vQ1), 1); // A0 * B0
+
+ A1 = vaddq_f32(A1, A2); // AB12 = AB1 + AB2
+ A0 = vsubq_f32(A0, A3); // AB03 = AB0 - AB3
+
+ // change the sign of the last element
+ A1 = (btSimdFloat4)veorq_s32((int32x4_t)A1, (int32x4_t)vPPPM);
+ A0 = vaddq_f32(A0, A1); // AB03 + AB12
+
+ mVec128 = A0;
+#else
+ setValue(
+ m_floats[3] * q.x() + m_floats[0] * q.m_floats[3] + m_floats[1] * q.z() - m_floats[2] * q.y(),
+ m_floats[3] * q.y() + m_floats[1] * q.m_floats[3] + m_floats[2] * q.x() - m_floats[0] * q.z(),
+ m_floats[3] * q.z() + m_floats[2] * q.m_floats[3] + m_floats[0] * q.y() - m_floats[1] * q.x(),
+ m_floats[3] * q.m_floats[3] - m_floats[0] * q.x() - m_floats[1] * q.y() - m_floats[2] * q.z());
+#endif
+ return *this;
+ }
+ /**@brief Return the dot product between this quaternion and another
+ * @param q The other quaternion */
+ btScalar dot(const btQuaternion& q) const
+ {
+#if defined BT_USE_SIMD_VECTOR3 && defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ __m128 vd;
+
+ vd = _mm_mul_ps(mVec128, q.mVec128);
+
+ __m128 t = _mm_movehl_ps(vd, vd);
+ vd = _mm_add_ps(vd, t);
+ t = _mm_shuffle_ps(vd, vd, 0x55);
+ vd = _mm_add_ss(vd, t);
+
+ return _mm_cvtss_f32(vd);
+#elif defined(BT_USE_NEON)
+ float32x4_t vd = vmulq_f32(mVec128, q.mVec128);
+ float32x2_t x = vpadd_f32(vget_low_f32(vd), vget_high_f32(vd));
+ x = vpadd_f32(x, x);
+ return vget_lane_f32(x, 0);
+#else
+ return m_floats[0] * q.x() +
+ m_floats[1] * q.y() +
+ m_floats[2] * q.z() +
+ m_floats[3] * q.m_floats[3];
+#endif
+ }
+
+ /**@brief Return the length squared of the quaternion */
+ btScalar length2() const
+ {
+ return dot(*this);
+ }
+
+ /**@brief Return the length of the quaternion */
+ btScalar length() const
+ {
+ return btSqrt(length2());
+ }
+ btQuaternion& safeNormalize()
+ {
+ btScalar l2 = length2();
+ if (l2>SIMD_EPSILON)
+ {
+ normalize();
+ }
+ return *this;
+ }
+ /**@brief Normalize the quaternion
+ * Such that x^2 + y^2 + z^2 +w^2 = 1 */
+ btQuaternion& normalize()
+ {
+#if defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ __m128 vd;
+
+ vd = _mm_mul_ps(mVec128, mVec128);
+
+ __m128 t = _mm_movehl_ps(vd, vd);
+ vd = _mm_add_ps(vd, t);
+ t = _mm_shuffle_ps(vd, vd, 0x55);
+ vd = _mm_add_ss(vd, t);
+
+ vd = _mm_sqrt_ss(vd);
+ vd = _mm_div_ss(vOnes, vd);
+ vd = bt_pshufd_ps(vd, 0); // splat
+ mVec128 = _mm_mul_ps(mVec128, vd);
+
+ return *this;
+#else
+ return *this /= length();
+#endif
+ }
+
+ /**@brief Return a scaled version of this quaternion
+ * @param s The scale factor */
+ SIMD_FORCE_INLINE btQuaternion
+ operator*(const btScalar& s) const
+ {
+#if defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ __m128 vs = _mm_load_ss(&s); // (S 0 0 0)
+ vs = bt_pshufd_ps(vs, 0x00); // (S S S S)
+
+ return btQuaternion(_mm_mul_ps(mVec128, vs));
+#elif defined(BT_USE_NEON)
+ return btQuaternion(vmulq_n_f32(mVec128, s));
+#else
+ return btQuaternion(x() * s, y() * s, z() * s, m_floats[3] * s);
+#endif
+ }
+
+ /**@brief Return an inversely scaled versionof this quaternion
+ * @param s The inverse scale factor */
+ btQuaternion operator/(const btScalar& s) const
+ {
+ btAssert(s != btScalar(0.0));
+ return *this * (btScalar(1.0) / s);
+ }
+
+ /**@brief Inversely scale this quaternion
+ * @param s The scale factor */
+ btQuaternion& operator/=(const btScalar& s)
+ {
+ btAssert(s != btScalar(0.0));
+ return *this *= btScalar(1.0) / s;
+ }
+
+ /**@brief Return a normalized version of this quaternion */
+ btQuaternion normalized() const
+ {
+ return *this / length();
+ }
+ /**@brief Return the ***half*** angle between this quaternion and the other
+ * @param q The other quaternion */
+ btScalar angle(const btQuaternion& q) const
+ {
+ btScalar s = btSqrt(length2() * q.length2());
+ btAssert(s != btScalar(0.0));
+ return btAcos(dot(q) / s);
+ }
+
+ /**@brief Return the angle between this quaternion and the other along the shortest path
+ * @param q The other quaternion */
+ btScalar angleShortestPath(const btQuaternion& q) const
+ {
+ btScalar s = btSqrt(length2() * q.length2());
+ btAssert(s != btScalar(0.0));
+ if (dot(q) < 0) // Take care of long angle case see http://en.wikipedia.org/wiki/Slerp
+ return btAcos(dot(-q) / s) * btScalar(2.0);
+ else
+ return btAcos(dot(q) / s) * btScalar(2.0);
+ }
+
+ /**@brief Return the angle [0, 2Pi] of rotation represented by this quaternion */
+ btScalar getAngle() const
+ {
+ btScalar s = btScalar(2.) * btAcos(m_floats[3]);
+ return s;
+ }
+
+ /**@brief Return the angle [0, Pi] of rotation represented by this quaternion along the shortest path */
+ btScalar getAngleShortestPath() const
+ {
+ btScalar s;
+ if (m_floats[3] >= 0)
+ s = btScalar(2.) * btAcos(m_floats[3]);
+ else
+ s = btScalar(2.) * btAcos(-m_floats[3]);
+ return s;
+ }
+
+
+ /**@brief Return the axis of the rotation represented by this quaternion */
+ btVector3 getAxis() const
+ {
+ btScalar s_squared = 1.f-m_floats[3]*m_floats[3];
+
+ if (s_squared < btScalar(10.) * SIMD_EPSILON) //Check for divide by zero
+ return btVector3(1.0, 0.0, 0.0); // Arbitrary
+ btScalar s = 1.f/btSqrt(s_squared);
+ return btVector3(m_floats[0] * s, m_floats[1] * s, m_floats[2] * s);
+ }
+
+ /**@brief Return the inverse of this quaternion */
+ btQuaternion inverse() const
+ {
+#if defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ return btQuaternion(_mm_xor_ps(mVec128, vQInv));
+#elif defined(BT_USE_NEON)
+ return btQuaternion((btSimdFloat4)veorq_s32((int32x4_t)mVec128, (int32x4_t)vQInv));
+#else
+ return btQuaternion(-m_floats[0], -m_floats[1], -m_floats[2], m_floats[3]);
+#endif
+ }
+
+ /**@brief Return the sum of this quaternion and the other
+ * @param q2 The other quaternion */
+ SIMD_FORCE_INLINE btQuaternion
+ operator+(const btQuaternion& q2) const
+ {
+#if defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ return btQuaternion(_mm_add_ps(mVec128, q2.mVec128));
+#elif defined(BT_USE_NEON)
+ return btQuaternion(vaddq_f32(mVec128, q2.mVec128));
+#else
+ const btQuaternion& q1 = *this;
+ return btQuaternion(q1.x() + q2.x(), q1.y() + q2.y(), q1.z() + q2.z(), q1.m_floats[3] + q2.m_floats[3]);
+#endif
+ }
+
+ /**@brief Return the difference between this quaternion and the other
+ * @param q2 The other quaternion */
+ SIMD_FORCE_INLINE btQuaternion
+ operator-(const btQuaternion& q2) const
+ {
+#if defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ return btQuaternion(_mm_sub_ps(mVec128, q2.mVec128));
+#elif defined(BT_USE_NEON)
+ return btQuaternion(vsubq_f32(mVec128, q2.mVec128));
+#else
+ const btQuaternion& q1 = *this;
+ return btQuaternion(q1.x() - q2.x(), q1.y() - q2.y(), q1.z() - q2.z(), q1.m_floats[3] - q2.m_floats[3]);
+#endif
+ }
+
+ /**@brief Return the negative of this quaternion
+ * This simply negates each element */
+ SIMD_FORCE_INLINE btQuaternion operator-() const
+ {
+#if defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ return btQuaternion(_mm_xor_ps(mVec128, btvMzeroMask));
+#elif defined(BT_USE_NEON)
+ return btQuaternion((btSimdFloat4)veorq_s32((int32x4_t)mVec128, (int32x4_t)btvMzeroMask) );
+#else
+ const btQuaternion& q2 = *this;
+ return btQuaternion( - q2.x(), - q2.y(), - q2.z(), - q2.m_floats[3]);
+#endif
+ }
+ /**@todo document this and it's use */
+ SIMD_FORCE_INLINE btQuaternion farthest( const btQuaternion& qd) const
+ {
+ btQuaternion diff,sum;
+ diff = *this - qd;
+ sum = *this + qd;
+ if( diff.dot(diff) > sum.dot(sum) )
+ return qd;
+ return (-qd);
+ }
+
+ /**@todo document this and it's use */
+ SIMD_FORCE_INLINE btQuaternion nearest( const btQuaternion& qd) const
+ {
+ btQuaternion diff,sum;
+ diff = *this - qd;
+ sum = *this + qd;
+ if( diff.dot(diff) < sum.dot(sum) )
+ return qd;
+ return (-qd);
+ }
+
+
+ /**@brief Return the quaternion which is the result of Spherical Linear Interpolation between this and the other quaternion
+ * @param q The other quaternion to interpolate with
+ * @param t The ratio between this and q to interpolate. If t = 0 the result is this, if t=1 the result is q.
+ * Slerp interpolates assuming constant velocity. */
+ btQuaternion slerp(const btQuaternion& q, const btScalar& t) const
+ {
+
+ const btScalar magnitude = btSqrt(length2() * q.length2());
+ btAssert(magnitude > btScalar(0));
+
+ const btScalar product = dot(q) / magnitude;
+ const btScalar absproduct = btFabs(product);
+
+ if(absproduct < btScalar(1.0 - SIMD_EPSILON))
+ {
+ // Take care of long angle case see http://en.wikipedia.org/wiki/Slerp
+ const btScalar theta = btAcos(absproduct);
+ const btScalar d = btSin(theta);
+ btAssert(d > btScalar(0));
+
+ const btScalar sign = (product < 0) ? btScalar(-1) : btScalar(1);
+ const btScalar s0 = btSin((btScalar(1.0) - t) * theta) / d;
+ const btScalar s1 = btSin(sign * t * theta) / d;
+
+ return btQuaternion(
+ (m_floats[0] * s0 + q.x() * s1),
+ (m_floats[1] * s0 + q.y() * s1),
+ (m_floats[2] * s0 + q.z() * s1),
+ (m_floats[3] * s0 + q.w() * s1));
+ }
+ else
+ {
+ return *this;
+ }
+ }
+
+ static const btQuaternion& getIdentity()
+ {
+ static const btQuaternion identityQuat(btScalar(0.),btScalar(0.),btScalar(0.),btScalar(1.));
+ return identityQuat;
+ }
+
+ SIMD_FORCE_INLINE const btScalar& getW() const { return m_floats[3]; }
+
+ SIMD_FORCE_INLINE void serialize(struct btQuaternionData& dataOut) const;
+
+ SIMD_FORCE_INLINE void deSerialize(const struct btQuaternionData& dataIn);
+
+ SIMD_FORCE_INLINE void serializeFloat(struct btQuaternionFloatData& dataOut) const;
+
+ SIMD_FORCE_INLINE void deSerializeFloat(const struct btQuaternionFloatData& dataIn);
+
+ SIMD_FORCE_INLINE void serializeDouble(struct btQuaternionDoubleData& dataOut) const;
+
+ SIMD_FORCE_INLINE void deSerializeDouble(const struct btQuaternionDoubleData& dataIn);
+
+};
+
+
+
+
+
+/**@brief Return the product of two quaternions */
+SIMD_FORCE_INLINE btQuaternion
+operator*(const btQuaternion& q1, const btQuaternion& q2)
+{
+#if defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ __m128 vQ1 = q1.get128();
+ __m128 vQ2 = q2.get128();
+ __m128 A0, A1, B1, A2, B2;
+
+ A1 = bt_pshufd_ps(vQ1, BT_SHUFFLE(0,1,2,0)); // X Y z x // vtrn
+ B1 = bt_pshufd_ps(vQ2, BT_SHUFFLE(3,3,3,0)); // W W W X // vdup vext
+
+ A1 = A1 * B1;
+
+ A2 = bt_pshufd_ps(vQ1, BT_SHUFFLE(1,2,0,1)); // Y Z X Y // vext
+ B2 = bt_pshufd_ps(vQ2, BT_SHUFFLE(2,0,1,1)); // z x Y Y // vtrn vdup
+
+ A2 = A2 * B2;
+
+ B1 = bt_pshufd_ps(vQ1, BT_SHUFFLE(2,0,1,2)); // z x Y Z // vtrn vext
+ B2 = bt_pshufd_ps(vQ2, BT_SHUFFLE(1,2,0,2)); // Y Z x z // vext vtrn
+
+ B1 = B1 * B2; // A3 *= B3
+
+ A0 = bt_splat_ps(vQ1, 3); // A0
+ A0 = A0 * vQ2; // A0 * B0
+
+ A1 = A1 + A2; // AB12
+ A0 = A0 - B1; // AB03 = AB0 - AB3
+
+ A1 = _mm_xor_ps(A1, vPPPM); // change sign of the last element
+ A0 = A0 + A1; // AB03 + AB12
+
+ return btQuaternion(A0);
+
+#elif defined(BT_USE_NEON)
+
+ float32x4_t vQ1 = q1.get128();
+ float32x4_t vQ2 = q2.get128();
+ float32x4_t A0, A1, B1, A2, B2, A3, B3;
+ float32x2_t vQ1zx, vQ2wx, vQ1yz, vQ2zx, vQ2yz, vQ2xz;
+
+ {
+ float32x2x2_t tmp;
+ tmp = vtrn_f32( vget_high_f32(vQ1), vget_low_f32(vQ1) ); // {z x}, {w y}
+ vQ1zx = tmp.val[0];
+
+ tmp = vtrn_f32( vget_high_f32(vQ2), vget_low_f32(vQ2) ); // {z x}, {w y}
+ vQ2zx = tmp.val[0];
+ }
+ vQ2wx = vext_f32(vget_high_f32(vQ2), vget_low_f32(vQ2), 1);
+
+ vQ1yz = vext_f32(vget_low_f32(vQ1), vget_high_f32(vQ1), 1);
+
+ vQ2yz = vext_f32(vget_low_f32(vQ2), vget_high_f32(vQ2), 1);
+ vQ2xz = vext_f32(vQ2zx, vQ2zx, 1);
+
+ A1 = vcombine_f32(vget_low_f32(vQ1), vQ1zx); // X Y z x
+ B1 = vcombine_f32(vdup_lane_f32(vget_high_f32(vQ2), 1), vQ2wx); // W W W X
+
+ A2 = vcombine_f32(vQ1yz, vget_low_f32(vQ1));
+ B2 = vcombine_f32(vQ2zx, vdup_lane_f32(vget_low_f32(vQ2), 1));
+
+ A3 = vcombine_f32(vQ1zx, vQ1yz); // Z X Y Z
+ B3 = vcombine_f32(vQ2yz, vQ2xz); // Y Z x z
+
+ A1 = vmulq_f32(A1, B1);
+ A2 = vmulq_f32(A2, B2);
+ A3 = vmulq_f32(A3, B3); // A3 *= B3
+ A0 = vmulq_lane_f32(vQ2, vget_high_f32(vQ1), 1); // A0 * B0
+
+ A1 = vaddq_f32(A1, A2); // AB12 = AB1 + AB2
+ A0 = vsubq_f32(A0, A3); // AB03 = AB0 - AB3
+
+ // change the sign of the last element
+ A1 = (btSimdFloat4)veorq_s32((int32x4_t)A1, (int32x4_t)vPPPM);
+ A0 = vaddq_f32(A0, A1); // AB03 + AB12
+
+ return btQuaternion(A0);
+
+#else
+ return btQuaternion(
+ q1.w() * q2.x() + q1.x() * q2.w() + q1.y() * q2.z() - q1.z() * q2.y(),
+ q1.w() * q2.y() + q1.y() * q2.w() + q1.z() * q2.x() - q1.x() * q2.z(),
+ q1.w() * q2.z() + q1.z() * q2.w() + q1.x() * q2.y() - q1.y() * q2.x(),
+ q1.w() * q2.w() - q1.x() * q2.x() - q1.y() * q2.y() - q1.z() * q2.z());
+#endif
+}
+
+SIMD_FORCE_INLINE btQuaternion
+operator*(const btQuaternion& q, const btVector3& w)
+{
+#if defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ __m128 vQ1 = q.get128();
+ __m128 vQ2 = w.get128();
+ __m128 A1, B1, A2, B2, A3, B3;
+
+ A1 = bt_pshufd_ps(vQ1, BT_SHUFFLE(3,3,3,0));
+ B1 = bt_pshufd_ps(vQ2, BT_SHUFFLE(0,1,2,0));
+
+ A1 = A1 * B1;
+
+ A2 = bt_pshufd_ps(vQ1, BT_SHUFFLE(1,2,0,1));
+ B2 = bt_pshufd_ps(vQ2, BT_SHUFFLE(2,0,1,1));
+
+ A2 = A2 * B2;
+
+ A3 = bt_pshufd_ps(vQ1, BT_SHUFFLE(2,0,1,2));
+ B3 = bt_pshufd_ps(vQ2, BT_SHUFFLE(1,2,0,2));
+
+ A3 = A3 * B3; // A3 *= B3
+
+ A1 = A1 + A2; // AB12
+ A1 = _mm_xor_ps(A1, vPPPM); // change sign of the last element
+ A1 = A1 - A3; // AB123 = AB12 - AB3
+
+ return btQuaternion(A1);
+
+#elif defined(BT_USE_NEON)
+
+ float32x4_t vQ1 = q.get128();
+ float32x4_t vQ2 = w.get128();
+ float32x4_t A1, B1, A2, B2, A3, B3;
+ float32x2_t vQ1wx, vQ2zx, vQ1yz, vQ2yz, vQ1zx, vQ2xz;
+
+ vQ1wx = vext_f32(vget_high_f32(vQ1), vget_low_f32(vQ1), 1);
+ {
+ float32x2x2_t tmp;
+
+ tmp = vtrn_f32( vget_high_f32(vQ2), vget_low_f32(vQ2) ); // {z x}, {w y}
+ vQ2zx = tmp.val[0];
+
+ tmp = vtrn_f32( vget_high_f32(vQ1), vget_low_f32(vQ1) ); // {z x}, {w y}
+ vQ1zx = tmp.val[0];
+ }
+
+ vQ1yz = vext_f32(vget_low_f32(vQ1), vget_high_f32(vQ1), 1);
+
+ vQ2yz = vext_f32(vget_low_f32(vQ2), vget_high_f32(vQ2), 1);
+ vQ2xz = vext_f32(vQ2zx, vQ2zx, 1);
+
+ A1 = vcombine_f32(vdup_lane_f32(vget_high_f32(vQ1), 1), vQ1wx); // W W W X
+ B1 = vcombine_f32(vget_low_f32(vQ2), vQ2zx); // X Y z x
+
+ A2 = vcombine_f32(vQ1yz, vget_low_f32(vQ1));
+ B2 = vcombine_f32(vQ2zx, vdup_lane_f32(vget_low_f32(vQ2), 1));
+
+ A3 = vcombine_f32(vQ1zx, vQ1yz); // Z X Y Z
+ B3 = vcombine_f32(vQ2yz, vQ2xz); // Y Z x z
+
+ A1 = vmulq_f32(A1, B1);
+ A2 = vmulq_f32(A2, B2);
+ A3 = vmulq_f32(A3, B3); // A3 *= B3
+
+ A1 = vaddq_f32(A1, A2); // AB12 = AB1 + AB2
+
+ // change the sign of the last element
+ A1 = (btSimdFloat4)veorq_s32((int32x4_t)A1, (int32x4_t)vPPPM);
+
+ A1 = vsubq_f32(A1, A3); // AB123 = AB12 - AB3
+
+ return btQuaternion(A1);
+
+#else
+ return btQuaternion(
+ q.w() * w.x() + q.y() * w.z() - q.z() * w.y(),
+ q.w() * w.y() + q.z() * w.x() - q.x() * w.z(),
+ q.w() * w.z() + q.x() * w.y() - q.y() * w.x(),
+ -q.x() * w.x() - q.y() * w.y() - q.z() * w.z());
+#endif
+}
+
+SIMD_FORCE_INLINE btQuaternion
+operator*(const btVector3& w, const btQuaternion& q)
+{
+#if defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ __m128 vQ1 = w.get128();
+ __m128 vQ2 = q.get128();
+ __m128 A1, B1, A2, B2, A3, B3;
+
+ A1 = bt_pshufd_ps(vQ1, BT_SHUFFLE(0,1,2,0)); // X Y z x
+ B1 = bt_pshufd_ps(vQ2, BT_SHUFFLE(3,3,3,0)); // W W W X
+
+ A1 = A1 * B1;
+
+ A2 = bt_pshufd_ps(vQ1, BT_SHUFFLE(1,2,0,1));
+ B2 = bt_pshufd_ps(vQ2, BT_SHUFFLE(2,0,1,1));
+
+ A2 = A2 *B2;
+
+ A3 = bt_pshufd_ps(vQ1, BT_SHUFFLE(2,0,1,2));
+ B3 = bt_pshufd_ps(vQ2, BT_SHUFFLE(1,2,0,2));
+
+ A3 = A3 * B3; // A3 *= B3
+
+ A1 = A1 + A2; // AB12
+ A1 = _mm_xor_ps(A1, vPPPM); // change sign of the last element
+ A1 = A1 - A3; // AB123 = AB12 - AB3
+
+ return btQuaternion(A1);
+
+#elif defined(BT_USE_NEON)
+
+ float32x4_t vQ1 = w.get128();
+ float32x4_t vQ2 = q.get128();
+ float32x4_t A1, B1, A2, B2, A3, B3;
+ float32x2_t vQ1zx, vQ2wx, vQ1yz, vQ2zx, vQ2yz, vQ2xz;
+
+ {
+ float32x2x2_t tmp;
+
+ tmp = vtrn_f32( vget_high_f32(vQ1), vget_low_f32(vQ1) ); // {z x}, {w y}
+ vQ1zx = tmp.val[0];
+
+ tmp = vtrn_f32( vget_high_f32(vQ2), vget_low_f32(vQ2) ); // {z x}, {w y}
+ vQ2zx = tmp.val[0];
+ }
+ vQ2wx = vext_f32(vget_high_f32(vQ2), vget_low_f32(vQ2), 1);
+
+ vQ1yz = vext_f32(vget_low_f32(vQ1), vget_high_f32(vQ1), 1);
+
+ vQ2yz = vext_f32(vget_low_f32(vQ2), vget_high_f32(vQ2), 1);
+ vQ2xz = vext_f32(vQ2zx, vQ2zx, 1);
+
+ A1 = vcombine_f32(vget_low_f32(vQ1), vQ1zx); // X Y z x
+ B1 = vcombine_f32(vdup_lane_f32(vget_high_f32(vQ2), 1), vQ2wx); // W W W X
+
+ A2 = vcombine_f32(vQ1yz, vget_low_f32(vQ1));
+ B2 = vcombine_f32(vQ2zx, vdup_lane_f32(vget_low_f32(vQ2), 1));
+
+ A3 = vcombine_f32(vQ1zx, vQ1yz); // Z X Y Z
+ B3 = vcombine_f32(vQ2yz, vQ2xz); // Y Z x z
+
+ A1 = vmulq_f32(A1, B1);
+ A2 = vmulq_f32(A2, B2);
+ A3 = vmulq_f32(A3, B3); // A3 *= B3
+
+ A1 = vaddq_f32(A1, A2); // AB12 = AB1 + AB2
+
+ // change the sign of the last element
+ A1 = (btSimdFloat4)veorq_s32((int32x4_t)A1, (int32x4_t)vPPPM);
+
+ A1 = vsubq_f32(A1, A3); // AB123 = AB12 - AB3
+
+ return btQuaternion(A1);
+
+#else
+ return btQuaternion(
+ +w.x() * q.w() + w.y() * q.z() - w.z() * q.y(),
+ +w.y() * q.w() + w.z() * q.x() - w.x() * q.z(),
+ +w.z() * q.w() + w.x() * q.y() - w.y() * q.x(),
+ -w.x() * q.x() - w.y() * q.y() - w.z() * q.z());
+#endif
+}
+
+/**@brief Calculate the dot product between two quaternions */
+SIMD_FORCE_INLINE btScalar
+dot(const btQuaternion& q1, const btQuaternion& q2)
+{
+ return q1.dot(q2);
+}
+
+
+/**@brief Return the length of a quaternion */
+SIMD_FORCE_INLINE btScalar
+length(const btQuaternion& q)
+{
+ return q.length();
+}
+
+/**@brief Return the angle between two quaternions*/
+SIMD_FORCE_INLINE btScalar
+btAngle(const btQuaternion& q1, const btQuaternion& q2)
+{
+ return q1.angle(q2);
+}
+
+/**@brief Return the inverse of a quaternion*/
+SIMD_FORCE_INLINE btQuaternion
+inverse(const btQuaternion& q)
+{
+ return q.inverse();
+}
+
+/**@brief Return the result of spherical linear interpolation betwen two quaternions
+ * @param q1 The first quaternion
+ * @param q2 The second quaternion
+ * @param t The ration between q1 and q2. t = 0 return q1, t=1 returns q2
+ * Slerp assumes constant velocity between positions. */
+SIMD_FORCE_INLINE btQuaternion
+slerp(const btQuaternion& q1, const btQuaternion& q2, const btScalar& t)
+{
+ return q1.slerp(q2, t);
+}
+
+SIMD_FORCE_INLINE btVector3
+quatRotate(const btQuaternion& rotation, const btVector3& v)
+{
+ btQuaternion q = rotation * v;
+ q *= rotation.inverse();
+#if defined BT_USE_SIMD_VECTOR3 && defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ return btVector3(_mm_and_ps(q.get128(), btvFFF0fMask));
+#elif defined(BT_USE_NEON)
+ return btVector3((float32x4_t)vandq_s32((int32x4_t)q.get128(), btvFFF0Mask));
+#else
+ return btVector3(q.getX(),q.getY(),q.getZ());
+#endif
+}
+
+SIMD_FORCE_INLINE btQuaternion
+shortestArcQuat(const btVector3& v0, const btVector3& v1) // Game Programming Gems 2.10. make sure v0,v1 are normalized
+{
+ btVector3 c = v0.cross(v1);
+ btScalar d = v0.dot(v1);
+
+ if (d < -1.0 + SIMD_EPSILON)
+ {
+ btVector3 n,unused;
+ btPlaneSpace1(v0,n,unused);
+ return btQuaternion(n.x(),n.y(),n.z(),0.0f); // just pick any vector that is orthogonal to v0
+ }
+
+ btScalar s = btSqrt((1.0f + d) * 2.0f);
+ btScalar rs = 1.0f / s;
+
+ return btQuaternion(c.getX()*rs,c.getY()*rs,c.getZ()*rs,s * 0.5f);
+}
+
+SIMD_FORCE_INLINE btQuaternion
+shortestArcQuatNormalize2(btVector3& v0,btVector3& v1)
+{
+ v0.normalize();
+ v1.normalize();
+ return shortestArcQuat(v0,v1);
+}
+
+
+
+
+struct btQuaternionFloatData
+{
+ float m_floats[4];
+};
+
+struct btQuaternionDoubleData
+{
+ double m_floats[4];
+
+};
+
+SIMD_FORCE_INLINE void btQuaternion::serializeFloat(struct btQuaternionFloatData& dataOut) const
+{
+ ///could also do a memcpy, check if it is worth it
+ for (int i=0;i<4;i++)
+ dataOut.m_floats[i] = float(m_floats[i]);
+}
+
+SIMD_FORCE_INLINE void btQuaternion::deSerializeFloat(const struct btQuaternionFloatData& dataIn)
+{
+ for (int i=0;i<4;i++)
+ m_floats[i] = btScalar(dataIn.m_floats[i]);
+}
+
+
+SIMD_FORCE_INLINE void btQuaternion::serializeDouble(struct btQuaternionDoubleData& dataOut) const
+{
+ ///could also do a memcpy, check if it is worth it
+ for (int i=0;i<4;i++)
+ dataOut.m_floats[i] = double(m_floats[i]);
+}
+
+SIMD_FORCE_INLINE void btQuaternion::deSerializeDouble(const struct btQuaternionDoubleData& dataIn)
+{
+ for (int i=0;i<4;i++)
+ m_floats[i] = btScalar(dataIn.m_floats[i]);
+}
+
+
+SIMD_FORCE_INLINE void btQuaternion::serialize(struct btQuaternionData& dataOut) const
+{
+ ///could also do a memcpy, check if it is worth it
+ for (int i=0;i<4;i++)
+ dataOut.m_floats[i] = m_floats[i];
+}
+
+SIMD_FORCE_INLINE void btQuaternion::deSerialize(const struct btQuaternionData& dataIn)
+{
+ for (int i=0;i<4;i++)
+ m_floats[i] = dataIn.m_floats[i];
+}
+
+
+#endif //BT_SIMD__QUATERNION_H_
+
+
+
diff --git a/thirdparty/bullet/src/LinearMath/btQuickprof.cpp b/thirdparty/bullet/src/LinearMath/btQuickprof.cpp
new file mode 100644
index 0000000000..aed3104a6e
--- /dev/null
+++ b/thirdparty/bullet/src/LinearMath/btQuickprof.cpp
@@ -0,0 +1,789 @@
+/*
+
+***************************************************************************************************
+**
+** profile.cpp
+**
+** Real-Time Hierarchical Profiling for Game Programming Gems 3
+**
+** by Greg Hjelstrom & Byon Garrabrant
+**
+***************************************************************************************************/
+
+// Credits: The Clock class was inspired by the Timer classes in
+// Ogre (www.ogre3d.org).
+
+#include "btQuickprof.h"
+#include "btThreads.h"
+
+
+
+
+#ifdef __CELLOS_LV2__
+#include <sys/sys_time.h>
+#include <sys/time_util.h>
+#include <stdio.h>
+#endif
+
+#if defined (SUNOS) || defined (__SUNOS__)
+#include <stdio.h>
+#endif
+#ifdef __APPLE__
+#include <mach/mach_time.h>
+#include <TargetConditionals.h>
+#endif
+
+#if defined(WIN32) || defined(_WIN32)
+
+#define BT_USE_WINDOWS_TIMERS
+#define WIN32_LEAN_AND_MEAN
+#define NOWINRES
+#define NOMCX
+#define NOIME
+
+#ifdef _XBOX
+ #include <Xtl.h>
+#else //_XBOX
+ #include <windows.h>
+
+#if WINVER <0x0602
+#define GetTickCount64 GetTickCount
+#endif
+
+#endif //_XBOX
+
+#include <time.h>
+
+
+#else //_WIN32
+#include <sys/time.h>
+
+#ifdef BT_LINUX_REALTIME
+//required linking against rt (librt)
+#include <time.h>
+#endif //BT_LINUX_REALTIME
+
+#endif //_WIN32
+
+#define mymin(a,b) (a > b ? a : b)
+
+struct btClockData
+{
+
+#ifdef BT_USE_WINDOWS_TIMERS
+ LARGE_INTEGER mClockFrequency;
+ LONGLONG mStartTick;
+ LARGE_INTEGER mStartTime;
+#else
+#ifdef __CELLOS_LV2__
+ uint64_t mStartTime;
+#else
+#ifdef __APPLE__
+ uint64_t mStartTimeNano;
+#endif
+ struct timeval mStartTime;
+#endif
+#endif //__CELLOS_LV2__
+
+};
+
+///The btClock is a portable basic clock that measures accurate time in seconds, use for profiling.
+btClock::btClock()
+{
+ m_data = new btClockData;
+#ifdef BT_USE_WINDOWS_TIMERS
+ QueryPerformanceFrequency(&m_data->mClockFrequency);
+#endif
+ reset();
+}
+
+btClock::~btClock()
+{
+ delete m_data;
+}
+
+btClock::btClock(const btClock& other)
+{
+ m_data = new btClockData;
+ *m_data = *other.m_data;
+}
+
+btClock& btClock::operator=(const btClock& other)
+{
+ *m_data = *other.m_data;
+ return *this;
+}
+
+
+ /// Resets the initial reference time.
+void btClock::reset()
+{
+#ifdef BT_USE_WINDOWS_TIMERS
+ QueryPerformanceCounter(&m_data->mStartTime);
+ m_data->mStartTick = GetTickCount64();
+#else
+#ifdef __CELLOS_LV2__
+
+ typedef uint64_t ClockSize;
+ ClockSize newTime;
+ //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory");
+ SYS_TIMEBASE_GET( newTime );
+ m_data->mStartTime = newTime;
+#else
+#ifdef __APPLE__
+ m_data->mStartTimeNano = mach_absolute_time();
+#endif
+ gettimeofday(&m_data->mStartTime, 0);
+#endif
+#endif
+}
+
+/// Returns the time in ms since the last call to reset or since
+/// the btClock was created.
+unsigned long long int btClock::getTimeMilliseconds()
+{
+#ifdef BT_USE_WINDOWS_TIMERS
+ LARGE_INTEGER currentTime;
+ QueryPerformanceCounter(&currentTime);
+ LONGLONG elapsedTime = currentTime.QuadPart -
+ m_data->mStartTime.QuadPart;
+ // Compute the number of millisecond ticks elapsed.
+ unsigned long msecTicks = (unsigned long)(1000 * elapsedTime /
+ m_data->mClockFrequency.QuadPart);
+
+ return msecTicks;
+#else
+
+#ifdef __CELLOS_LV2__
+ uint64_t freq=sys_time_get_timebase_frequency();
+ double dFreq=((double) freq) / 1000.0;
+ typedef uint64_t ClockSize;
+ ClockSize newTime;
+ SYS_TIMEBASE_GET( newTime );
+ //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory");
+
+ return (unsigned long int)((double(newTime-m_data->mStartTime)) / dFreq);
+#else
+
+ struct timeval currentTime;
+ gettimeofday(&currentTime, 0);
+ return (currentTime.tv_sec - m_data->mStartTime.tv_sec) * 1000 +
+ (currentTime.tv_usec - m_data->mStartTime.tv_usec) / 1000;
+#endif //__CELLOS_LV2__
+#endif
+}
+
+ /// Returns the time in us since the last call to reset or since
+ /// the Clock was created.
+unsigned long long int btClock::getTimeMicroseconds()
+{
+#ifdef BT_USE_WINDOWS_TIMERS
+ //see https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408(v=vs.85).aspx
+ LARGE_INTEGER currentTime, elapsedTime;
+
+ QueryPerformanceCounter(&currentTime);
+ elapsedTime.QuadPart = currentTime.QuadPart -
+ m_data->mStartTime.QuadPart;
+ elapsedTime.QuadPart *= 1000000;
+ elapsedTime.QuadPart /= m_data->mClockFrequency.QuadPart;
+
+ return (unsigned long long) elapsedTime.QuadPart;
+#else
+
+#ifdef __CELLOS_LV2__
+ uint64_t freq=sys_time_get_timebase_frequency();
+ double dFreq=((double) freq)/ 1000000.0;
+ typedef uint64_t ClockSize;
+ ClockSize newTime;
+ //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory");
+ SYS_TIMEBASE_GET( newTime );
+
+ return (unsigned long int)((double(newTime-m_data->mStartTime)) / dFreq);
+#else
+
+ struct timeval currentTime;
+ gettimeofday(&currentTime, 0);
+ return (currentTime.tv_sec - m_data->mStartTime.tv_sec) * 1000000 +
+ (currentTime.tv_usec - m_data->mStartTime.tv_usec);
+#endif//__CELLOS_LV2__
+#endif
+}
+
+unsigned long long int btClock::getTimeNanoseconds()
+{
+#ifdef BT_USE_WINDOWS_TIMERS
+ //see https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408(v=vs.85).aspx
+ LARGE_INTEGER currentTime, elapsedTime;
+
+ QueryPerformanceCounter(&currentTime);
+ elapsedTime.QuadPart = currentTime.QuadPart -
+ m_data->mStartTime.QuadPart;
+ elapsedTime.QuadPart *= 1000000000;
+ elapsedTime.QuadPart /= m_data->mClockFrequency.QuadPart;
+
+ return (unsigned long long) elapsedTime.QuadPart;
+#else
+
+#ifdef __CELLOS_LV2__
+ uint64_t freq=sys_time_get_timebase_frequency();
+ double dFreq=((double) freq)/ 1e9;
+ typedef uint64_t ClockSize;
+ ClockSize newTime;
+ //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory");
+ SYS_TIMEBASE_GET( newTime );
+
+ return (unsigned long int)((double(newTime-m_data->mStartTime)) / dFreq);
+#else
+#ifdef __APPLE__
+ uint64_t ticks = mach_absolute_time() - m_data->mStartTimeNano;
+ static long double conversion = 0.0L;
+ if( 0.0L == conversion )
+ {
+ // attempt to get conversion to nanoseconds
+ mach_timebase_info_data_t info;
+ int err = mach_timebase_info( &info );
+ if( err )
+ {
+ btAssert(0);
+ conversion = 1.;
+ }
+ conversion = info.numer / info.denom;
+ }
+ return (ticks * conversion);
+
+
+#else//__APPLE__
+
+#ifdef BT_LINUX_REALTIME
+ timespec ts;
+ clock_gettime(CLOCK_REALTIME,&ts);
+ return 1000000000*ts.tv_sec + ts.tv_nsec;
+#else
+ struct timeval currentTime;
+ gettimeofday(&currentTime, 0);
+ return (currentTime.tv_sec - m_data->mStartTime.tv_sec) * 1e9 +
+ (currentTime.tv_usec - m_data->mStartTime.tv_usec)*1000;
+#endif //BT_LINUX_REALTIME
+
+#endif//__APPLE__
+#endif//__CELLOS_LV2__
+#endif
+}
+
+
+/// Returns the time in s since the last call to reset or since
+/// the Clock was created.
+btScalar btClock::getTimeSeconds()
+{
+ static const btScalar microseconds_to_seconds = btScalar(0.000001);
+ return btScalar(getTimeMicroseconds()) * microseconds_to_seconds;
+}
+
+#ifndef BT_NO_PROFILE
+
+
+static btClock gProfileClock;
+
+
+inline void Profile_Get_Ticks(unsigned long int * ticks)
+{
+ *ticks = (unsigned long int)gProfileClock.getTimeMicroseconds();
+}
+
+inline float Profile_Get_Tick_Rate(void)
+{
+// return 1000000.f;
+ return 1000.f;
+
+}
+
+
+/***************************************************************************************************
+**
+** CProfileNode
+**
+***************************************************************************************************/
+
+/***********************************************************************************************
+ * INPUT: *
+ * name - pointer to a static string which is the name of this profile node *
+ * parent - parent pointer *
+ * *
+ * WARNINGS: *
+ * The name is assumed to be a static pointer, only the pointer is stored and compared for *
+ * efficiency reasons. *
+ *=============================================================================================*/
+CProfileNode::CProfileNode( const char * name, CProfileNode * parent ) :
+ Name( name ),
+ TotalCalls( 0 ),
+ TotalTime( 0 ),
+ StartTime( 0 ),
+ RecursionCounter( 0 ),
+ Parent( parent ),
+ Child( NULL ),
+ Sibling( NULL ),
+ m_userPtr(0)
+{
+ Reset();
+}
+
+
+void CProfileNode::CleanupMemory()
+{
+ delete ( Child);
+ Child = NULL;
+ delete ( Sibling);
+ Sibling = NULL;
+}
+
+CProfileNode::~CProfileNode( void )
+{
+ CleanupMemory();
+}
+
+
+/***********************************************************************************************
+ * INPUT: *
+ * name - static string pointer to the name of the node we are searching for *
+ * *
+ * WARNINGS: *
+ * All profile names are assumed to be static strings so this function uses pointer compares *
+ * to find the named node. *
+ *=============================================================================================*/
+CProfileNode * CProfileNode::Get_Sub_Node( const char * name )
+{
+ // Try to find this sub node
+ CProfileNode * child = Child;
+ while ( child ) {
+ if ( child->Name == name ) {
+ return child;
+ }
+ child = child->Sibling;
+ }
+
+ // We didn't find it, so add it
+
+ CProfileNode * node = new CProfileNode( name, this );
+ node->Sibling = Child;
+ Child = node;
+ return node;
+}
+
+
+void CProfileNode::Reset( void )
+{
+ TotalCalls = 0;
+ TotalTime = 0.0f;
+
+
+ if ( Child ) {
+ Child->Reset();
+ }
+ if ( Sibling ) {
+ Sibling->Reset();
+ }
+}
+
+
+void CProfileNode::Call( void )
+{
+ TotalCalls++;
+ if (RecursionCounter++ == 0) {
+ Profile_Get_Ticks(&StartTime);
+ }
+}
+
+
+bool CProfileNode::Return( void )
+{
+ if ( --RecursionCounter == 0 && TotalCalls != 0 ) {
+ unsigned long int time;
+ Profile_Get_Ticks(&time);
+
+ time-=StartTime;
+ TotalTime += (float)time / Profile_Get_Tick_Rate();
+ }
+ return ( RecursionCounter == 0 );
+}
+
+
+/***************************************************************************************************
+**
+** CProfileIterator
+**
+***************************************************************************************************/
+CProfileIterator::CProfileIterator( CProfileNode * start )
+{
+ CurrentParent = start;
+ CurrentChild = CurrentParent->Get_Child();
+}
+
+
+void CProfileIterator::First(void)
+{
+ CurrentChild = CurrentParent->Get_Child();
+}
+
+
+void CProfileIterator::Next(void)
+{
+ CurrentChild = CurrentChild->Get_Sibling();
+}
+
+
+bool CProfileIterator::Is_Done(void)
+{
+ return CurrentChild == NULL;
+}
+
+
+void CProfileIterator::Enter_Child( int index )
+{
+ CurrentChild = CurrentParent->Get_Child();
+ while ( (CurrentChild != NULL) && (index != 0) ) {
+ index--;
+ CurrentChild = CurrentChild->Get_Sibling();
+ }
+
+ if ( CurrentChild != NULL ) {
+ CurrentParent = CurrentChild;
+ CurrentChild = CurrentParent->Get_Child();
+ }
+}
+
+
+void CProfileIterator::Enter_Parent( void )
+{
+ if ( CurrentParent->Get_Parent() != NULL ) {
+ CurrentParent = CurrentParent->Get_Parent();
+ }
+ CurrentChild = CurrentParent->Get_Child();
+}
+
+
+/***************************************************************************************************
+**
+** CProfileManager
+**
+***************************************************************************************************/
+
+
+
+
+CProfileNode gRoots[BT_QUICKPROF_MAX_THREAD_COUNT]={
+ CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),
+ CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),
+ CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),
+ CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),
+ CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),
+ CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),
+ CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),
+ CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),
+ CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),
+ CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),
+ CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),
+ CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),
+ CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),
+ CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),
+ CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),
+ CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL)
+};
+
+
+CProfileNode* gCurrentNodes[BT_QUICKPROF_MAX_THREAD_COUNT]=
+{
+ &gRoots[ 0], &gRoots[ 1], &gRoots[ 2], &gRoots[ 3],
+ &gRoots[ 4], &gRoots[ 5], &gRoots[ 6], &gRoots[ 7],
+ &gRoots[ 8], &gRoots[ 9], &gRoots[10], &gRoots[11],
+ &gRoots[12], &gRoots[13], &gRoots[14], &gRoots[15],
+ &gRoots[16], &gRoots[17], &gRoots[18], &gRoots[19],
+ &gRoots[20], &gRoots[21], &gRoots[22], &gRoots[23],
+ &gRoots[24], &gRoots[25], &gRoots[26], &gRoots[27],
+ &gRoots[28], &gRoots[29], &gRoots[30], &gRoots[31],
+ &gRoots[32], &gRoots[33], &gRoots[34], &gRoots[35],
+ &gRoots[36], &gRoots[37], &gRoots[38], &gRoots[39],
+ &gRoots[40], &gRoots[41], &gRoots[42], &gRoots[43],
+ &gRoots[44], &gRoots[45], &gRoots[46], &gRoots[47],
+ &gRoots[48], &gRoots[49], &gRoots[50], &gRoots[51],
+ &gRoots[52], &gRoots[53], &gRoots[54], &gRoots[55],
+ &gRoots[56], &gRoots[57], &gRoots[58], &gRoots[59],
+ &gRoots[60], &gRoots[61], &gRoots[62], &gRoots[63],
+};
+
+
+int CProfileManager::FrameCounter = 0;
+unsigned long int CProfileManager::ResetTime = 0;
+
+CProfileIterator * CProfileManager::Get_Iterator( void )
+{
+
+ int threadIndex = btQuickprofGetCurrentThreadIndex2();
+ if ((threadIndex<0) || threadIndex >= BT_QUICKPROF_MAX_THREAD_COUNT)
+ return 0;
+
+ return new CProfileIterator( &gRoots[threadIndex]);
+}
+
+void CProfileManager::CleanupMemory(void)
+{
+ for (int i=0;i<BT_QUICKPROF_MAX_THREAD_COUNT;i++)
+ {
+ gRoots[i].CleanupMemory();
+ }
+}
+
+
+/***********************************************************************************************
+ * CProfileManager::Start_Profile -- Begin a named profile *
+ * *
+ * Steps one level deeper into the tree, if a child already exists with the specified name *
+ * then it accumulates the profiling; otherwise a new child node is added to the profile tree. *
+ * *
+ * INPUT: *
+ * name - name of this profiling record *
+ * *
+ * WARNINGS: *
+ * The string used is assumed to be a static string; pointer compares are used throughout *
+ * the profiling code for efficiency. *
+ *=============================================================================================*/
+void CProfileManager::Start_Profile( const char * name )
+{
+ int threadIndex = btQuickprofGetCurrentThreadIndex2();
+ if ((threadIndex<0) || threadIndex >= BT_QUICKPROF_MAX_THREAD_COUNT)
+ return;
+
+ if (name != gCurrentNodes[threadIndex]->Get_Name()) {
+ gCurrentNodes[threadIndex] = gCurrentNodes[threadIndex]->Get_Sub_Node( name );
+ }
+
+ gCurrentNodes[threadIndex]->Call();
+}
+
+
+/***********************************************************************************************
+ * CProfileManager::Stop_Profile -- Stop timing and record the results. *
+ *=============================================================================================*/
+void CProfileManager::Stop_Profile( void )
+{
+ int threadIndex = btQuickprofGetCurrentThreadIndex2();
+ if ((threadIndex<0) || threadIndex >= BT_QUICKPROF_MAX_THREAD_COUNT)
+ return;
+
+ // Return will indicate whether we should back up to our parent (we may
+ // be profiling a recursive function)
+ if (gCurrentNodes[threadIndex]->Return()) {
+ gCurrentNodes[threadIndex] = gCurrentNodes[threadIndex]->Get_Parent();
+ }
+}
+
+
+
+
+
+
+/***********************************************************************************************
+ * CProfileManager::Reset -- Reset the contents of the profiling system *
+ * *
+ * This resets everything except for the tree structure. All of the timing data is reset. *
+ *=============================================================================================*/
+void CProfileManager::Reset( void )
+{
+ gProfileClock.reset();
+ int threadIndex = btQuickprofGetCurrentThreadIndex2();
+ if ((threadIndex<0) || threadIndex >= BT_QUICKPROF_MAX_THREAD_COUNT)
+ return;
+ gRoots[threadIndex].Reset();
+ gRoots[threadIndex].Call();
+ FrameCounter = 0;
+ Profile_Get_Ticks(&ResetTime);
+}
+
+
+/***********************************************************************************************
+ * CProfileManager::Increment_Frame_Counter -- Increment the frame counter *
+ *=============================================================================================*/
+void CProfileManager::Increment_Frame_Counter( void )
+{
+ FrameCounter++;
+}
+
+
+/***********************************************************************************************
+ * CProfileManager::Get_Time_Since_Reset -- returns the elapsed time since last reset *
+ *=============================================================================================*/
+float CProfileManager::Get_Time_Since_Reset( void )
+{
+ unsigned long int time;
+ Profile_Get_Ticks(&time);
+ time -= ResetTime;
+ return (float)time / Profile_Get_Tick_Rate();
+}
+
+#include <stdio.h>
+
+void CProfileManager::dumpRecursive(CProfileIterator* profileIterator, int spacing)
+{
+ profileIterator->First();
+ if (profileIterator->Is_Done())
+ return;
+
+ float accumulated_time=0,parent_time = profileIterator->Is_Root() ? CProfileManager::Get_Time_Since_Reset() : profileIterator->Get_Current_Parent_Total_Time();
+ int i;
+ int frames_since_reset = CProfileManager::Get_Frame_Count_Since_Reset();
+ for (i=0;i<spacing;i++) printf(".");
+ printf("----------------------------------\n");
+ for (i=0;i<spacing;i++) printf(".");
+ printf("Profiling: %s (total running time: %.3f ms) ---\n", profileIterator->Get_Current_Parent_Name(), parent_time );
+ float totalTime = 0.f;
+
+
+ int numChildren = 0;
+
+ for (i = 0; !profileIterator->Is_Done(); i++,profileIterator->Next())
+ {
+ numChildren++;
+ float current_total_time = profileIterator->Get_Current_Total_Time();
+ accumulated_time += current_total_time;
+ float fraction = parent_time > SIMD_EPSILON ? (current_total_time / parent_time) * 100 : 0.f;
+ {
+ int i; for (i=0;i<spacing;i++) printf(".");
+ }
+ printf("%d -- %s (%.2f %%) :: %.3f ms / frame (%d calls)\n",i, profileIterator->Get_Current_Name(), fraction,(current_total_time / (double)frames_since_reset),profileIterator->Get_Current_Total_Calls());
+ totalTime += current_total_time;
+ //recurse into children
+ }
+
+ if (parent_time < accumulated_time)
+ {
+ //printf("what's wrong\n");
+ }
+ for (i=0;i<spacing;i++) printf(".");
+ printf("%s (%.3f %%) :: %.3f ms\n", "Unaccounted:",parent_time > SIMD_EPSILON ? ((parent_time - accumulated_time) / parent_time) * 100 : 0.f, parent_time - accumulated_time);
+
+ for (i=0;i<numChildren;i++)
+ {
+ profileIterator->Enter_Child(i);
+ dumpRecursive(profileIterator,spacing+3);
+ profileIterator->Enter_Parent();
+ }
+}
+
+
+
+void CProfileManager::dumpAll()
+{
+ CProfileIterator* profileIterator = 0;
+ profileIterator = CProfileManager::Get_Iterator();
+
+ dumpRecursive(profileIterator,0);
+
+ CProfileManager::Release_Iterator(profileIterator);
+}
+
+
+
+
+unsigned int btQuickprofGetCurrentThreadIndex2()
+{
+#if BT_THREADSAFE
+ return btGetCurrentThreadIndex();
+#else // #if BT_THREADSAFE
+ const unsigned int kNullIndex = ~0U;
+#ifdef _WIN32
+ #if defined(__MINGW32__) || defined(__MINGW64__)
+ static __thread unsigned int sThreadIndex = kNullIndex;
+ #else
+ __declspec( thread ) static unsigned int sThreadIndex = kNullIndex;
+ #endif
+#else
+#ifdef __APPLE__
+ #if TARGET_OS_IPHONE
+ unsigned int sThreadIndex = 0;
+ return -1;
+ #else
+ static __thread unsigned int sThreadIndex = kNullIndex;
+ #endif
+#else//__APPLE__
+#if __linux__
+ static __thread unsigned int sThreadIndex = kNullIndex;
+#else
+ unsigned int sThreadIndex = 0;
+ return -1;
+#endif
+#endif//__APPLE__
+
+#endif
+ static int gThreadCounter=0;
+
+ if ( sThreadIndex == kNullIndex )
+ {
+ sThreadIndex = gThreadCounter++;
+ }
+ return sThreadIndex;
+#endif // #else // #if BT_THREADSAFE
+}
+
+void btEnterProfileZoneDefault(const char* name)
+{
+ CProfileManager::Start_Profile( name );
+}
+void btLeaveProfileZoneDefault()
+{
+ CProfileManager::Stop_Profile();
+}
+
+
+#else
+void btEnterProfileZoneDefault(const char* name)
+{
+}
+void btLeaveProfileZoneDefault()
+{
+}
+#endif //BT_NO_PROFILE
+
+
+
+
+
+static btEnterProfileZoneFunc* bts_enterFunc = btEnterProfileZoneDefault;
+static btLeaveProfileZoneFunc* bts_leaveFunc = btLeaveProfileZoneDefault;
+
+void btEnterProfileZone(const char* name)
+{
+ (bts_enterFunc)(name);
+}
+void btLeaveProfileZone()
+{
+ (bts_leaveFunc)();
+}
+
+btEnterProfileZoneFunc* btGetCurrentEnterProfileZoneFunc()
+{
+ return bts_enterFunc ;
+}
+btLeaveProfileZoneFunc* btGetCurrentLeaveProfileZoneFunc()
+{
+ return bts_leaveFunc;
+}
+
+
+void btSetCustomEnterProfileZoneFunc(btEnterProfileZoneFunc* enterFunc)
+{
+ bts_enterFunc = enterFunc;
+}
+void btSetCustomLeaveProfileZoneFunc(btLeaveProfileZoneFunc* leaveFunc)
+{
+ bts_leaveFunc = leaveFunc;
+}
+
+CProfileSample::CProfileSample( const char * name )
+{
+ btEnterProfileZone(name);
+}
+
+CProfileSample::~CProfileSample( void )
+{
+ btLeaveProfileZone();
+}
+
diff --git a/thirdparty/bullet/src/LinearMath/btQuickprof.h b/thirdparty/bullet/src/LinearMath/btQuickprof.h
new file mode 100644
index 0000000000..7b38d71b90
--- /dev/null
+++ b/thirdparty/bullet/src/LinearMath/btQuickprof.h
@@ -0,0 +1,221 @@
+
+/***************************************************************************************************
+**
+** Real-Time Hierarchical Profiling for Game Programming Gems 3
+**
+** by Greg Hjelstrom & Byon Garrabrant
+**
+***************************************************************************************************/
+
+// Credits: The Clock class was inspired by the Timer classes in
+// Ogre (www.ogre3d.org).
+
+
+
+#ifndef BT_QUICK_PROF_H
+#define BT_QUICK_PROF_H
+
+#include "btScalar.h"
+#define USE_BT_CLOCK 1
+
+#ifdef USE_BT_CLOCK
+
+///The btClock is a portable basic clock that measures accurate time in seconds, use for profiling.
+class btClock
+{
+public:
+ btClock();
+
+ btClock(const btClock& other);
+ btClock& operator=(const btClock& other);
+
+ ~btClock();
+
+ /// Resets the initial reference time.
+ void reset();
+
+ /// Returns the time in ms since the last call to reset or since
+ /// the btClock was created.
+ unsigned long long int getTimeMilliseconds();
+
+ /// Returns the time in us since the last call to reset or since
+ /// the Clock was created.
+ unsigned long long int getTimeMicroseconds();
+
+ unsigned long long int getTimeNanoseconds();
+
+ /// Returns the time in s since the last call to reset or since
+ /// the Clock was created.
+ btScalar getTimeSeconds();
+
+private:
+ struct btClockData* m_data;
+};
+
+#endif //USE_BT_CLOCK
+
+typedef void (btEnterProfileZoneFunc)(const char* msg);
+typedef void (btLeaveProfileZoneFunc)();
+
+btEnterProfileZoneFunc* btGetCurrentEnterProfileZoneFunc();
+btLeaveProfileZoneFunc* btGetCurrentLeaveProfileZoneFunc();
+
+
+
+void btSetCustomEnterProfileZoneFunc(btEnterProfileZoneFunc* enterFunc);
+void btSetCustomLeaveProfileZoneFunc(btLeaveProfileZoneFunc* leaveFunc);
+
+#ifndef BT_NO_PROFILE // FIX redefinition
+//To disable built-in profiling, please comment out next line
+//#define BT_NO_PROFILE 1
+#endif //BT_NO_PROFILE
+
+#ifndef BT_NO_PROFILE
+//btQuickprofGetCurrentThreadIndex will return -1 if thread index cannot be determined,
+//otherwise returns thread index in range [0..maxThreads]
+unsigned int btQuickprofGetCurrentThreadIndex2();
+const unsigned int BT_QUICKPROF_MAX_THREAD_COUNT = 64;
+
+#include <stdio.h>//@todo remove this, backwards compatibility
+
+#include "btAlignedAllocator.h"
+#include <new>
+
+
+
+
+
+
+
+
+
+///A node in the Profile Hierarchy Tree
+class CProfileNode {
+
+public:
+ CProfileNode( const char * name, CProfileNode * parent );
+ ~CProfileNode( void );
+
+ CProfileNode * Get_Sub_Node( const char * name );
+
+ CProfileNode * Get_Parent( void ) { return Parent; }
+ CProfileNode * Get_Sibling( void ) { return Sibling; }
+ CProfileNode * Get_Child( void ) { return Child; }
+
+ void CleanupMemory();
+ void Reset( void );
+ void Call( void );
+ bool Return( void );
+
+ const char * Get_Name( void ) { return Name; }
+ int Get_Total_Calls( void ) { return TotalCalls; }
+ float Get_Total_Time( void ) { return TotalTime; }
+ void* GetUserPointer() const {return m_userPtr;}
+ void SetUserPointer(void* ptr) { m_userPtr = ptr;}
+protected:
+
+ const char * Name;
+ int TotalCalls;
+ float TotalTime;
+ unsigned long int StartTime;
+ int RecursionCounter;
+
+ CProfileNode * Parent;
+ CProfileNode * Child;
+ CProfileNode * Sibling;
+ void* m_userPtr;
+};
+
+///An iterator to navigate through the tree
+class CProfileIterator
+{
+public:
+ // Access all the children of the current parent
+ void First(void);
+ void Next(void);
+ bool Is_Done(void);
+ bool Is_Root(void) { return (CurrentParent->Get_Parent() == 0); }
+
+ void Enter_Child( int index ); // Make the given child the new parent
+ void Enter_Largest_Child( void ); // Make the largest child the new parent
+ void Enter_Parent( void ); // Make the current parent's parent the new parent
+
+ // Access the current child
+ const char * Get_Current_Name( void ) { return CurrentChild->Get_Name(); }
+ int Get_Current_Total_Calls( void ) { return CurrentChild->Get_Total_Calls(); }
+ float Get_Current_Total_Time( void ) { return CurrentChild->Get_Total_Time(); }
+
+ void* Get_Current_UserPointer( void ) { return CurrentChild->GetUserPointer(); }
+ void Set_Current_UserPointer(void* ptr) {CurrentChild->SetUserPointer(ptr);}
+ // Access the current parent
+ const char * Get_Current_Parent_Name( void ) { return CurrentParent->Get_Name(); }
+ int Get_Current_Parent_Total_Calls( void ) { return CurrentParent->Get_Total_Calls(); }
+ float Get_Current_Parent_Total_Time( void ) { return CurrentParent->Get_Total_Time(); }
+
+
+
+protected:
+
+ CProfileNode * CurrentParent;
+ CProfileNode * CurrentChild;
+
+
+ CProfileIterator( CProfileNode * start );
+ friend class CProfileManager;
+};
+
+
+///The Manager for the Profile system
+class CProfileManager {
+public:
+ static void Start_Profile( const char * name );
+ static void Stop_Profile( void );
+
+ static void CleanupMemory(void);
+// {
+// Root.CleanupMemory();
+// }
+
+ static void Reset( void );
+ static void Increment_Frame_Counter( void );
+ static int Get_Frame_Count_Since_Reset( void ) { return FrameCounter; }
+ static float Get_Time_Since_Reset( void );
+
+ static CProfileIterator * Get_Iterator( void );
+// {
+//
+// return new CProfileIterator( &Root );
+// }
+ static void Release_Iterator( CProfileIterator * iterator ) { delete ( iterator); }
+
+ static void dumpRecursive(CProfileIterator* profileIterator, int spacing);
+
+ static void dumpAll();
+
+private:
+
+ static int FrameCounter;
+ static unsigned long int ResetTime;
+};
+
+
+
+
+#endif //#ifndef BT_NO_PROFILE
+
+///ProfileSampleClass is a simple way to profile a function's scope
+///Use the BT_PROFILE macro at the start of scope to time
+class CProfileSample {
+public:
+ CProfileSample( const char * name );
+
+ ~CProfileSample( void );
+};
+
+#define BT_PROFILE( name ) CProfileSample __profile( name )
+
+
+
+#endif //BT_QUICK_PROF_H
+
+
diff --git a/thirdparty/bullet/src/LinearMath/btRandom.h b/thirdparty/bullet/src/LinearMath/btRandom.h
new file mode 100644
index 0000000000..4cbfc6bfe9
--- /dev/null
+++ b/thirdparty/bullet/src/LinearMath/btRandom.h
@@ -0,0 +1,42 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+#ifndef BT_GEN_RANDOM_H
+#define BT_GEN_RANDOM_H
+
+#ifdef MT19937
+
+#include <limits.h>
+#include <mt19937.h>
+
+#define GEN_RAND_MAX UINT_MAX
+
+SIMD_FORCE_INLINE void GEN_srand(unsigned int seed) { init_genrand(seed); }
+SIMD_FORCE_INLINE unsigned int GEN_rand() { return genrand_int32(); }
+
+#else
+
+#include <stdlib.h>
+
+#define GEN_RAND_MAX RAND_MAX
+
+SIMD_FORCE_INLINE void GEN_srand(unsigned int seed) { srand(seed); }
+SIMD_FORCE_INLINE unsigned int GEN_rand() { return rand(); }
+
+#endif
+
+#endif //BT_GEN_RANDOM_H
+
diff --git a/thirdparty/bullet/src/LinearMath/btScalar.h b/thirdparty/bullet/src/LinearMath/btScalar.h
new file mode 100644
index 0000000000..bffb2ce274
--- /dev/null
+++ b/thirdparty/bullet/src/LinearMath/btScalar.h
@@ -0,0 +1,810 @@
+/*
+Copyright (c) 2003-2009 Erwin Coumans http://bullet.googlecode.com
+
+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_SCALAR_H
+#define BT_SCALAR_H
+
+#ifdef BT_MANAGED_CODE
+//Aligned data types not supported in managed code
+#pragma unmanaged
+#endif
+
+#include <math.h>
+#include <stdlib.h> //size_t for MSVC 6.0
+#include <float.h>
+
+/* SVN $Revision$ on $Date$ from http://bullet.googlecode.com*/
+#define BT_BULLET_VERSION 287
+
+inline int btGetVersion()
+{
+ return BT_BULLET_VERSION;
+}
+
+
+// The following macro "BT_NOT_EMPTY_FILE" can be put into a file
+// in order suppress the MS Visual C++ Linker warning 4221
+//
+// warning LNK4221: no public symbols found; archive member will be inaccessible
+//
+// This warning occurs on PC and XBOX when a file compiles out completely
+// has no externally visible symbols which may be dependant on configuration
+// #defines and options.
+//
+// see more https://stackoverflow.com/questions/1822887/what-is-the-best-way-to-eliminate-ms-visual-c-linker-warning-warning-lnk422
+
+#if defined (_MSC_VER)
+ #define BT_NOT_EMPTY_FILE_CAT_II(p, res) res
+ #define BT_NOT_EMPTY_FILE_CAT_I(a, b) BT_NOT_EMPTY_FILE_CAT_II(~, a ## b)
+ #define BT_NOT_EMPTY_FILE_CAT(a, b) BT_NOT_EMPTY_FILE_CAT_I(a, b)
+ #define BT_NOT_EMPTY_FILE namespace { char BT_NOT_EMPTY_FILE_CAT(NoEmptyFileDummy, __COUNTER__); }
+#else
+ #define BT_NOT_EMPTY_FILE
+#endif
+
+
+// clang and most formatting tools don't support indentation of preprocessor guards, so turn it off
+// clang-format off
+#if defined(DEBUG) || defined (_DEBUG)
+ #define BT_DEBUG
+#endif
+
+#ifdef _WIN32
+ #if defined(__MINGW32__) || defined(__CYGWIN__) || (defined (_MSC_VER) && _MSC_VER < 1300)
+ #define SIMD_FORCE_INLINE inline
+ #define ATTRIBUTE_ALIGNED16(a) a
+ #define ATTRIBUTE_ALIGNED64(a) a
+ #define ATTRIBUTE_ALIGNED128(a) a
+ #elif defined(_M_ARM)
+ #define SIMD_FORCE_INLINE __forceinline
+ #define ATTRIBUTE_ALIGNED16(a) __declspec() a
+ #define ATTRIBUTE_ALIGNED64(a) __declspec() a
+ #define ATTRIBUTE_ALIGNED128(a) __declspec () a
+ #else//__MINGW32__
+ //#define BT_HAS_ALIGNED_ALLOCATOR
+ #pragma warning(disable : 4324) // disable padding warning
+// #pragma warning(disable:4530) // Disable the exception disable but used in MSCV Stl warning.
+ #pragma warning(disable:4996) //Turn off warnings about deprecated C routines
+// #pragma warning(disable:4786) // Disable the "debug name too long" warning
+
+ #define SIMD_FORCE_INLINE __forceinline
+ #define ATTRIBUTE_ALIGNED16(a) __declspec(align(16)) a
+ #define ATTRIBUTE_ALIGNED64(a) __declspec(align(64)) a
+ #define ATTRIBUTE_ALIGNED128(a) __declspec (align(128)) a
+ #ifdef _XBOX
+ #define BT_USE_VMX128
+
+ #include <ppcintrinsics.h>
+ #define BT_HAVE_NATIVE_FSEL
+ #define btFsel(a,b,c) __fsel((a),(b),(c))
+ #else
+
+#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))
+ #if _MSC_VER>1400
+ #define BT_USE_SIMD_VECTOR3
+ #endif
+
+ #define BT_USE_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)
+ #define BT_ALLOW_SSE4
+#endif //(_MSC_FULL_VER >= 160040219)
+
+ //BT_USE_SSE_IN_API is disabled under Windows by default, because
+ //it makes it harder to integrate Bullet into your application under Windows
+ //(structured embedding Bullet structs/classes need to be 16-byte aligned)
+ //with relatively little performance gain
+ //If you are not embedded Bullet data in your classes, or make sure that you align those classes on 16-byte boundaries
+ //you can manually enable this line or set it in the build system for a bit of performance gain (a few percent, dependent on usage)
+ //#define BT_USE_SSE_IN_API
+ #endif //BT_USE_SSE
+ #include <emmintrin.h>
+#endif
+
+ #endif//_XBOX
+
+ #endif //__MINGW32__
+
+ #ifdef BT_DEBUG
+ #ifdef _MSC_VER
+ #include <stdio.h>
+ #define btAssert(x) { if(!(x)){printf("Assert "__FILE__ ":%u (%s)\n", __LINE__, #x);__debugbreak(); }}
+ #else//_MSC_VER
+ #include <assert.h>
+ #define btAssert assert
+ #endif//_MSC_VER
+ #else
+ #define btAssert(x)
+ #endif
+ //btFullAssert is optional, slows down a lot
+ #define btFullAssert(x)
+
+ #define btLikely(_c) _c
+ #define btUnlikely(_c) _c
+
+#else//_WIN32
+
+ #if defined (__CELLOS_LV2__)
+ #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)))
+ #ifndef assert
+ #include <assert.h>
+ #endif
+ #ifdef BT_DEBUG
+ #ifdef __SPU__
+ #include <spu_printf.h>
+ #define printf spu_printf
+ #define btAssert(x) {if(!(x)){printf("Assert "__FILE__ ":%u ("#x")\n", __LINE__);spu_hcmpeq(0,0);}}
+ #else
+ #define btAssert assert
+ #endif
+
+ #else//BT_DEBUG
+ #define btAssert(x)
+ #endif//BT_DEBUG
+ //btFullAssert is optional, slows down a lot
+ #define btFullAssert(x)
+
+ #define btLikely(_c) _c
+ #define btUnlikely(_c) _c
+
+ #else//defined (__CELLOS_LV2__)
+
+ #ifdef USE_LIBSPE2
+
+ #define SIMD_FORCE_INLINE __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)))
+ #ifndef assert
+ #include <assert.h>
+ #endif
+ #ifdef BT_DEBUG
+ #define btAssert assert
+ #else
+ #define btAssert(x)
+ #endif
+ //btFullAssert is optional, slows down a lot
+ #define btFullAssert(x)
+
+
+ #define btLikely(_c) __builtin_expect((_c), 1)
+ #define btUnlikely(_c) __builtin_expect((_c), 0)
+
+
+ #else//USE_LIBSPE2
+ //non-windows systems
+
+ #if (defined (__APPLE__) && (!defined (BT_USE_DOUBLE_PRECISION)))
+ #if defined (__i386__) || defined (__x86_64__)
+ #define BT_USE_SIMD_VECTOR3
+ #define BT_USE_SSE
+ //BT_USE_SSE_IN_API is enabled on Mac OSX by default, because memory is automatically aligned on 16-byte boundaries
+ //if apps run into issues, we will disable the next line
+ #define BT_USE_SSE_IN_API
+ #ifdef BT_USE_SSE
+ // include appropriate SSE level
+ #if defined (__SSE4_1__)
+ #include <smmintrin.h>
+ #elif defined (__SSSE3__)
+ #include <tmmintrin.h>
+ #elif defined (__SSE3__)
+ #include <pmmintrin.h>
+ #else
+ #include <emmintrin.h>
+ #endif
+ #endif //BT_USE_SSE
+ #elif defined( __ARM_NEON__ )
+ #ifdef __clang__
+ #define BT_USE_NEON 1
+ #define BT_USE_SIMD_VECTOR3
+
+ #if defined BT_USE_NEON && defined (__clang__)
+ #include <arm_neon.h>
+ #endif//BT_USE_NEON
+ #endif //__clang__
+ #endif//__arm__
+
+ #define SIMD_FORCE_INLINE inline __attribute__ ((always_inline))
+ ///@todo: check out alignment methods for other platforms/compilers
+ #define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16)))
+ #define ATTRIBUTE_ALIGNED64(a) a __attribute__ ((aligned (64)))
+ #define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128)))
+ #ifndef assert
+ #include <assert.h>
+ #endif
+
+ #if defined(DEBUG) || defined (_DEBUG)
+ #if defined (__i386__) || defined (__x86_64__)
+ #include <stdio.h>
+ #define btAssert(x)\
+ {\
+ if(!(x))\
+ {\
+ printf("Assert %s in line %d, file %s\n",#x, __LINE__, __FILE__);\
+ asm volatile ("int3");\
+ }\
+ }
+ #else//defined (__i386__) || defined (__x86_64__)
+ #define btAssert assert
+ #endif//defined (__i386__) || defined (__x86_64__)
+ #else//defined(DEBUG) || defined (_DEBUG)
+ #define btAssert(x)
+ #endif//defined(DEBUG) || defined (_DEBUG)
+
+ //btFullAssert is optional, slows down a lot
+ #define btFullAssert(x)
+ #define btLikely(_c) _c
+ #define btUnlikely(_c) _c
+
+ #else//__APPLE__
+
+ #define SIMD_FORCE_INLINE inline
+ ///@todo: check out alignment methods for other platforms/compilers
+ ///#define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16)))
+ ///#define ATTRIBUTE_ALIGNED64(a) a __attribute__ ((aligned (64)))
+ ///#define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128)))
+ #define ATTRIBUTE_ALIGNED16(a) a
+ #define ATTRIBUTE_ALIGNED64(a) a
+ #define ATTRIBUTE_ALIGNED128(a) a
+ #ifndef assert
+ #include <assert.h>
+ #endif
+
+ #if defined(DEBUG) || defined (_DEBUG)
+ #define btAssert assert
+ #else
+ #define btAssert(x)
+ #endif
+
+ //btFullAssert is optional, slows down a lot
+ #define btFullAssert(x)
+ #define btLikely(_c) _c
+ #define btUnlikely(_c) _c
+ #endif //__APPLE__
+ #endif // LIBSPE2
+ #endif //__CELLOS_LV2__
+#endif//_WIN32
+
+
+///The btScalar type abstracts floating point numbers, to easily switch between double and single floating point precision.
+#if defined(BT_USE_DOUBLE_PRECISION)
+ typedef double btScalar;
+ //this number could be bigger in double precision
+ #define BT_LARGE_FLOAT 1e30
+#else
+ typedef float btScalar;
+ //keep BT_LARGE_FLOAT*BT_LARGE_FLOAT < FLT_MAX
+ #define BT_LARGE_FLOAT 1e18f
+#endif
+
+#ifdef BT_USE_SSE
+ typedef __m128 btSimdFloat4;
+#endif //BT_USE_SSE
+
+#if defined(BT_USE_SSE)
+ //#if defined BT_USE_SSE_IN_API && defined (BT_USE_SSE)
+ #ifdef _WIN32
+
+ #ifndef BT_NAN
+ static int btNanMask = 0x7F800001;
+ #define BT_NAN (*(float *)&btNanMask)
+ #endif
+
+ #ifndef BT_INFINITY
+ static int btInfinityMask = 0x7F800000;
+ #define BT_INFINITY (*(float *)&btInfinityMask)
+ inline int btGetInfinityMask() //suppress stupid compiler warning
+ {
+ return btInfinityMask;
+ }
+ #endif
+
+
+
+ //use this, in case there are clashes (such as xnamath.h)
+ #ifndef BT_NO_SIMD_OPERATOR_OVERLOADS
+ inline __m128 operator+(const __m128 A, const __m128 B)
+ {
+ return _mm_add_ps(A, B);
+ }
+
+ inline __m128 operator-(const __m128 A, const __m128 B)
+ {
+ return _mm_sub_ps(A, B);
+ }
+
+ inline __m128 operator*(const __m128 A, const __m128 B)
+ {
+ return _mm_mul_ps(A, B);
+ }
+ #endif //BT_NO_SIMD_OPERATOR_OVERLOADS
+
+ #define btCastfTo128i(a) (_mm_castps_si128(a))
+ #define btCastfTo128d(a) (_mm_castps_pd(a))
+ #define btCastiTo128f(a) (_mm_castsi128_ps(a))
+ #define btCastdTo128f(a) (_mm_castpd_ps(a))
+ #define btCastdTo128i(a) (_mm_castpd_si128(a))
+ #define btAssign128(r0, r1, r2, r3) _mm_setr_ps(r0, r1, r2, r3)
+
+ #else //_WIN32
+
+ #define btCastfTo128i(a) ((__m128i)(a))
+ #define btCastfTo128d(a) ((__m128d)(a))
+ #define btCastiTo128f(a) ((__m128)(a))
+ #define btCastdTo128f(a) ((__m128)(a))
+ #define btCastdTo128i(a) ((__m128i)(a))
+ #define btAssign128(r0, r1, r2, r3) \
+ (__m128) { r0, r1, r2, r3 }
+ #define BT_INFINITY INFINITY
+ #define BT_NAN NAN
+ #endif //_WIN32
+#else//BT_USE_SSE
+
+ #ifdef BT_USE_NEON
+ #include <arm_neon.h>
+
+ typedef float32x4_t btSimdFloat4;
+ #define BT_INFINITY INFINITY
+ #define BT_NAN NAN
+ #define btAssign128(r0, r1, r2, r3) \
+ (float32x4_t) { r0, r1, r2, r3 }
+ #else //BT_USE_NEON
+
+ #ifndef BT_INFINITY
+ struct btInfMaskConverter
+ {
+ union {
+ float mask;
+ int intmask;
+ };
+ btInfMaskConverter(int _mask = 0x7F800000)
+ : intmask(_mask)
+ {
+ }
+ };
+ static btInfMaskConverter btInfinityMask = 0x7F800000;
+ #define BT_INFINITY (btInfinityMask.mask)
+ inline int btGetInfinityMask() //suppress stupid compiler warning
+ {
+ return btInfinityMask.intmask;
+ }
+ #endif
+ #endif //BT_USE_NEON
+
+#endif //BT_USE_SSE
+
+#ifdef BT_USE_NEON
+ #include <arm_neon.h>
+
+ typedef float32x4_t btSimdFloat4;
+ #define BT_INFINITY INFINITY
+ #define BT_NAN NAN
+ #define btAssign128(r0, r1, r2, r3) \
+ (float32x4_t) { r0, r1, r2, r3 }
+#endif//BT_USE_NEON
+
+#define BT_DECLARE_ALIGNED_ALLOCATOR() \
+ SIMD_FORCE_INLINE void *operator new(size_t sizeInBytes) { return btAlignedAlloc(sizeInBytes, 16); } \
+ SIMD_FORCE_INLINE void operator delete(void *ptr) { btAlignedFree(ptr); } \
+ SIMD_FORCE_INLINE void *operator new(size_t, void *ptr) { return ptr; } \
+ SIMD_FORCE_INLINE void operator delete(void *, void *) {} \
+ SIMD_FORCE_INLINE void *operator new[](size_t sizeInBytes) { return btAlignedAlloc(sizeInBytes, 16); } \
+ SIMD_FORCE_INLINE void operator delete[](void *ptr) { btAlignedFree(ptr); } \
+ SIMD_FORCE_INLINE void *operator new[](size_t, void *ptr) { return ptr; } \
+ SIMD_FORCE_INLINE void operator delete[](void *, void *) {}
+
+#if defined(BT_USE_DOUBLE_PRECISION) || defined(BT_FORCE_DOUBLE_FUNCTIONS)
+
+ SIMD_FORCE_INLINE btScalar btSqrt(btScalar x)
+ {
+ return sqrt(x);
+ }
+ SIMD_FORCE_INLINE btScalar btFabs(btScalar x) { return fabs(x); }
+ SIMD_FORCE_INLINE btScalar btCos(btScalar x) { return cos(x); }
+ SIMD_FORCE_INLINE btScalar btSin(btScalar x) { return sin(x); }
+ SIMD_FORCE_INLINE btScalar btTan(btScalar x) { return tan(x); }
+ SIMD_FORCE_INLINE btScalar btAcos(btScalar x)
+ {
+ if (x < btScalar(-1)) x = btScalar(-1);
+ if (x > btScalar(1)) x = btScalar(1);
+ return acos(x);
+ }
+ SIMD_FORCE_INLINE btScalar btAsin(btScalar x)
+ {
+ if (x < btScalar(-1)) x = btScalar(-1);
+ if (x > btScalar(1)) x = btScalar(1);
+ return asin(x);
+ }
+ SIMD_FORCE_INLINE btScalar btAtan(btScalar x) { return atan(x); }
+ SIMD_FORCE_INLINE btScalar btAtan2(btScalar x, btScalar y) { return atan2(x, y); }
+ SIMD_FORCE_INLINE btScalar btExp(btScalar x) { return exp(x); }
+ SIMD_FORCE_INLINE btScalar btLog(btScalar x) { return log(x); }
+ SIMD_FORCE_INLINE btScalar btPow(btScalar x, btScalar y) { return pow(x, y); }
+ SIMD_FORCE_INLINE btScalar btFmod(btScalar x, btScalar y) { return fmod(x, y); }
+
+#else//BT_USE_DOUBLE_PRECISION
+
+ SIMD_FORCE_INLINE btScalar btSqrt(btScalar y)
+ {
+ #ifdef USE_APPROXIMATION
+ #ifdef __LP64__
+ float xhalf = 0.5f * y;
+ int i = *(int *)&y;
+ i = 0x5f375a86 - (i >> 1);
+ y = *(float *)&i;
+ y = y * (1.5f - xhalf * y * y);
+ y = y * (1.5f - xhalf * y * y);
+ y = y * (1.5f - xhalf * y * y);
+ y = 1 / y;
+ return y;
+ #else
+ double x, z, tempf;
+ unsigned long *tfptr = ((unsigned long *)&tempf) + 1;
+ tempf = y;
+ *tfptr = (0xbfcdd90a - *tfptr) >> 1; /* estimate of 1/sqrt(y) */
+ x = tempf;
+ z = y * btScalar(0.5);
+ x = (btScalar(1.5) * x) - (x * x) * (x * z); /* iteration formula */
+ x = (btScalar(1.5) * x) - (x * x) * (x * z);
+ x = (btScalar(1.5) * x) - (x * x) * (x * z);
+ x = (btScalar(1.5) * x) - (x * x) * (x * z);
+ x = (btScalar(1.5) * x) - (x * x) * (x * z);
+ return x * y;
+ #endif
+ #else
+ return sqrtf(y);
+ #endif
+ }
+ SIMD_FORCE_INLINE btScalar btFabs(btScalar x) { return fabsf(x); }
+ SIMD_FORCE_INLINE btScalar btCos(btScalar x) { return cosf(x); }
+ SIMD_FORCE_INLINE btScalar btSin(btScalar x) { return sinf(x); }
+ SIMD_FORCE_INLINE btScalar btTan(btScalar x) { return tanf(x); }
+ SIMD_FORCE_INLINE btScalar btAcos(btScalar x)
+ {
+ if (x < btScalar(-1))
+ x = btScalar(-1);
+ if (x > btScalar(1))
+ x = btScalar(1);
+ return acosf(x);
+ }
+ SIMD_FORCE_INLINE btScalar btAsin(btScalar x)
+ {
+ if (x < btScalar(-1))
+ x = btScalar(-1);
+ if (x > btScalar(1))
+ x = btScalar(1);
+ return asinf(x);
+ }
+ SIMD_FORCE_INLINE btScalar btAtan(btScalar x) { return atanf(x); }
+ SIMD_FORCE_INLINE btScalar btAtan2(btScalar x, btScalar y) { return atan2f(x, y); }
+ SIMD_FORCE_INLINE btScalar btExp(btScalar x) { return expf(x); }
+ SIMD_FORCE_INLINE btScalar btLog(btScalar x) { return logf(x); }
+ SIMD_FORCE_INLINE btScalar btPow(btScalar x, btScalar y) { return powf(x, y); }
+ SIMD_FORCE_INLINE btScalar btFmod(btScalar x, btScalar y) { return fmodf(x, y); }
+
+#endif//BT_USE_DOUBLE_PRECISION
+
+#define SIMD_PI btScalar(3.1415926535897932384626433832795029)
+#define SIMD_2_PI (btScalar(2.0) * SIMD_PI)
+#define SIMD_HALF_PI (SIMD_PI * btScalar(0.5))
+#define SIMD_RADS_PER_DEG (SIMD_2_PI / btScalar(360.0))
+#define SIMD_DEGS_PER_RAD (btScalar(360.0) / SIMD_2_PI)
+#define SIMDSQRT12 btScalar(0.7071067811865475244008443621048490)
+#define btRecipSqrt(x) ((btScalar)(btScalar(1.0) / btSqrt(btScalar(x)))) /* reciprocal square root */
+#define btRecip(x) (btScalar(1.0) / btScalar(x))
+
+#ifdef BT_USE_DOUBLE_PRECISION
+ #define SIMD_EPSILON DBL_EPSILON
+ #define SIMD_INFINITY DBL_MAX
+ #define BT_ONE 1.0
+ #define BT_ZERO 0.0
+ #define BT_TWO 2.0
+ #define BT_HALF 0.5
+#else
+ #define SIMD_EPSILON FLT_EPSILON
+ #define SIMD_INFINITY FLT_MAX
+ #define BT_ONE 1.0f
+ #define BT_ZERO 0.0f
+ #define BT_TWO 2.0f
+ #define BT_HALF 0.5f
+#endif
+
+// clang-format on
+
+SIMD_FORCE_INLINE btScalar btAtan2Fast(btScalar y, btScalar x)
+{
+ btScalar coeff_1 = SIMD_PI / 4.0f;
+ btScalar coeff_2 = 3.0f * coeff_1;
+ btScalar abs_y = btFabs(y);
+ btScalar angle;
+ if (x >= 0.0f)
+ {
+ btScalar r = (x - abs_y) / (x + abs_y);
+ angle = coeff_1 - coeff_1 * r;
+ }
+ else
+ {
+ btScalar r = (x + abs_y) / (abs_y - x);
+ angle = coeff_2 - coeff_1 * r;
+ }
+ return (y < 0.0f) ? -angle : angle;
+}
+
+SIMD_FORCE_INLINE bool btFuzzyZero(btScalar x) { return btFabs(x) < SIMD_EPSILON; }
+
+SIMD_FORCE_INLINE bool btEqual(btScalar a, btScalar eps)
+{
+ return (((a) <= eps) && !((a) < -eps));
+}
+SIMD_FORCE_INLINE bool btGreaterEqual(btScalar a, btScalar eps)
+{
+ return (!((a) <= eps));
+}
+
+SIMD_FORCE_INLINE int btIsNegative(btScalar x)
+{
+ return x < btScalar(0.0) ? 1 : 0;
+}
+
+SIMD_FORCE_INLINE btScalar btRadians(btScalar x) { return x * SIMD_RADS_PER_DEG; }
+SIMD_FORCE_INLINE btScalar btDegrees(btScalar x) { return x * SIMD_DEGS_PER_RAD; }
+
+#define BT_DECLARE_HANDLE(name) \
+ typedef struct name##__ \
+ { \
+ int unused; \
+ } * name
+
+#ifndef btFsel
+SIMD_FORCE_INLINE btScalar btFsel(btScalar a, btScalar b, btScalar c)
+{
+ return a >= 0 ? b : c;
+}
+#endif
+#define btFsels(a, b, c) (btScalar) btFsel(a, b, c)
+
+SIMD_FORCE_INLINE bool btMachineIsLittleEndian()
+{
+ long int i = 1;
+ const char *p = (const char *)&i;
+ if (p[0] == 1) // Lowest address contains the least significant byte
+ return true;
+ else
+ return false;
+}
+
+///btSelect avoids branches, which makes performance much better for consoles like Playstation 3 and XBox 360
+///Thanks Phil Knight. See also http://www.cellperformance.com/articles/2006/04/more_techniques_for_eliminatin_1.html
+SIMD_FORCE_INLINE unsigned btSelect(unsigned condition, unsigned valueIfConditionNonZero, unsigned valueIfConditionZero)
+{
+ // Set testNz to 0xFFFFFFFF if condition is nonzero, 0x00000000 if condition is zero
+ // Rely on positive value or'ed with its negative having sign bit on
+ // and zero value or'ed with its negative (which is still zero) having sign bit off
+ // Use arithmetic shift right, shifting the sign bit through all 32 bits
+ unsigned testNz = (unsigned)(((int)condition | -(int)condition) >> 31);
+ unsigned testEqz = ~testNz;
+ return ((valueIfConditionNonZero & testNz) | (valueIfConditionZero & testEqz));
+}
+SIMD_FORCE_INLINE int btSelect(unsigned condition, int valueIfConditionNonZero, int valueIfConditionZero)
+{
+ unsigned testNz = (unsigned)(((int)condition | -(int)condition) >> 31);
+ unsigned testEqz = ~testNz;
+ return static_cast<int>((valueIfConditionNonZero & testNz) | (valueIfConditionZero & testEqz));
+}
+SIMD_FORCE_INLINE float btSelect(unsigned condition, float valueIfConditionNonZero, float valueIfConditionZero)
+{
+#ifdef BT_HAVE_NATIVE_FSEL
+ return (float)btFsel((btScalar)condition - btScalar(1.0f), valueIfConditionNonZero, valueIfConditionZero);
+#else
+ return (condition != 0) ? valueIfConditionNonZero : valueIfConditionZero;
+#endif
+}
+
+template <typename T>
+SIMD_FORCE_INLINE void btSwap(T &a, T &b)
+{
+ T tmp = a;
+ a = b;
+ b = tmp;
+}
+
+//PCK: endian swapping functions
+SIMD_FORCE_INLINE unsigned btSwapEndian(unsigned val)
+{
+ return (((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24));
+}
+
+SIMD_FORCE_INLINE unsigned short btSwapEndian(unsigned short val)
+{
+ return static_cast<unsigned short>(((val & 0xff00) >> 8) | ((val & 0x00ff) << 8));
+}
+
+SIMD_FORCE_INLINE unsigned btSwapEndian(int val)
+{
+ return btSwapEndian((unsigned)val);
+}
+
+SIMD_FORCE_INLINE unsigned short btSwapEndian(short val)
+{
+ return btSwapEndian((unsigned short)val);
+}
+
+///btSwapFloat uses using char pointers to swap the endianness
+////btSwapFloat/btSwapDouble will NOT return a float, because the machine might 'correct' invalid floating point values
+///Not all values of sign/exponent/mantissa are valid floating point numbers according to IEEE 754.
+///When a floating point unit is faced with an invalid value, it may actually change the value, or worse, throw an exception.
+///In most systems, running user mode code, you wouldn't get an exception, but instead the hardware/os/runtime will 'fix' the number for you.
+///so instead of returning a float/double, we return integer/long long integer
+SIMD_FORCE_INLINE unsigned int btSwapEndianFloat(float d)
+{
+ unsigned int a = 0;
+ unsigned char *dst = (unsigned char *)&a;
+ unsigned char *src = (unsigned char *)&d;
+
+ dst[0] = src[3];
+ dst[1] = src[2];
+ dst[2] = src[1];
+ dst[3] = src[0];
+ return a;
+}
+
+// unswap using char pointers
+SIMD_FORCE_INLINE float btUnswapEndianFloat(unsigned int a)
+{
+ float d = 0.0f;
+ unsigned char *src = (unsigned char *)&a;
+ unsigned char *dst = (unsigned char *)&d;
+
+ dst[0] = src[3];
+ dst[1] = src[2];
+ dst[2] = src[1];
+ dst[3] = src[0];
+
+ return d;
+}
+
+// swap using char pointers
+SIMD_FORCE_INLINE void btSwapEndianDouble(double d, unsigned char *dst)
+{
+ unsigned char *src = (unsigned char *)&d;
+
+ dst[0] = src[7];
+ dst[1] = src[6];
+ dst[2] = src[5];
+ dst[3] = src[4];
+ dst[4] = src[3];
+ dst[5] = src[2];
+ dst[6] = src[1];
+ dst[7] = src[0];
+}
+
+// unswap using char pointers
+SIMD_FORCE_INLINE double btUnswapEndianDouble(const unsigned char *src)
+{
+ double d = 0.0;
+ unsigned char *dst = (unsigned char *)&d;
+
+ dst[0] = src[7];
+ dst[1] = src[6];
+ dst[2] = src[5];
+ dst[3] = src[4];
+ dst[4] = src[3];
+ dst[5] = src[2];
+ dst[6] = src[1];
+ dst[7] = src[0];
+
+ return d;
+}
+
+template <typename T>
+SIMD_FORCE_INLINE void btSetZero(T *a, int n)
+{
+ T *acurr = a;
+ size_t ncurr = n;
+ while (ncurr > 0)
+ {
+ *(acurr++) = 0;
+ --ncurr;
+ }
+}
+
+SIMD_FORCE_INLINE btScalar btLargeDot(const btScalar *a, const btScalar *b, int n)
+{
+ btScalar p0, q0, m0, p1, q1, m1, sum;
+ sum = 0;
+ n -= 2;
+ while (n >= 0)
+ {
+ p0 = a[0];
+ q0 = b[0];
+ m0 = p0 * q0;
+ p1 = a[1];
+ q1 = b[1];
+ m1 = p1 * q1;
+ sum += m0;
+ sum += m1;
+ a += 2;
+ b += 2;
+ n -= 2;
+ }
+ n += 2;
+ while (n > 0)
+ {
+ sum += (*a) * (*b);
+ a++;
+ b++;
+ n--;
+ }
+ return sum;
+}
+
+// returns normalized value in range [-SIMD_PI, SIMD_PI]
+SIMD_FORCE_INLINE btScalar btNormalizeAngle(btScalar angleInRadians)
+{
+ angleInRadians = btFmod(angleInRadians, SIMD_2_PI);
+ if (angleInRadians < -SIMD_PI)
+ {
+ return angleInRadians + SIMD_2_PI;
+ }
+ else if (angleInRadians > SIMD_PI)
+ {
+ return angleInRadians - SIMD_2_PI;
+ }
+ else
+ {
+ return angleInRadians;
+ }
+}
+
+///rudimentary class to provide type info
+struct btTypedObject
+{
+ btTypedObject(int objectType)
+ : m_objectType(objectType)
+ {
+ }
+ int m_objectType;
+ inline int getObjectType() const
+ {
+ return m_objectType;
+ }
+};
+
+///align a pointer to the provided alignment, upwards
+template <typename T>
+T *btAlignPointer(T *unalignedPtr, size_t alignment)
+{
+ struct btConvertPointerSizeT
+ {
+ union {
+ T *ptr;
+ size_t integer;
+ };
+ };
+ btConvertPointerSizeT converter;
+
+ const size_t bit_mask = ~(alignment - 1);
+ converter.ptr = unalignedPtr;
+ converter.integer += alignment - 1;
+ converter.integer &= bit_mask;
+ return converter.ptr;
+}
+
+#endif //BT_SCALAR_H
diff --git a/thirdparty/bullet/src/LinearMath/btSerializer.cpp b/thirdparty/bullet/src/LinearMath/btSerializer.cpp
new file mode 100644
index 0000000000..fcd2255ad5
--- /dev/null
+++ b/thirdparty/bullet/src/LinearMath/btSerializer.cpp
@@ -0,0 +1,599 @@
+char sBulletDNAstr[]= {
+char(83),char(68),char(78),char(65),char(78),char(65),char(77),char(69),char(-124),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),
+char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(115),char(0),char(42),char(102),char(105),char(114),char(115),char(116),char(0),char(42),char(108),char(97),char(115),
+char(116),char(0),char(109),char(95),char(102),char(108),char(111),char(97),char(116),char(115),char(91),char(52),char(93),char(0),char(109),char(95),char(101),char(108),char(91),char(51),
+char(93),char(0),char(109),char(95),char(98),char(97),char(115),char(105),char(115),char(0),char(109),char(95),char(111),char(114),char(105),char(103),char(105),char(110),char(0),char(109),
+char(95),char(114),char(111),char(111),char(116),char(78),char(111),char(100),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(115),char(117),char(98),
+char(116),char(114),char(101),char(101),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),
+char(65),char(97),char(98),char(98),char(77),char(105),char(110),char(91),char(51),char(93),char(0),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),char(122),
+char(101),char(100),char(65),char(97),char(98),char(98),char(77),char(97),char(120),char(91),char(51),char(93),char(0),char(109),char(95),char(97),char(97),char(98),char(98),char(77),
+char(105),char(110),char(79),char(114),char(103),char(0),char(109),char(95),char(97),char(97),char(98),char(98),char(77),char(97),char(120),char(79),char(114),char(103),char(0),char(109),
+char(95),char(101),char(115),char(99),char(97),char(112),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(115),char(117),char(98),char(80),char(97),
+char(114),char(116),char(0),char(109),char(95),char(116),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),
+char(95),char(112),char(97),char(100),char(91),char(52),char(93),char(0),char(109),char(95),char(101),char(115),char(99),char(97),char(112),char(101),char(73),char(110),char(100),char(101),
+char(120),char(79),char(114),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(98),
+char(118),char(104),char(65),char(97),char(98),char(98),char(77),char(105),char(110),char(0),char(109),char(95),char(98),char(118),char(104),char(65),char(97),char(98),char(98),char(77),
+char(97),char(120),char(0),char(109),char(95),char(98),char(118),char(104),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(97),char(116),char(105),char(111),char(110),
+char(0),char(109),char(95),char(99),char(117),char(114),char(78),char(111),char(100),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(117),char(115),
+char(101),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(97),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(110),char(117),char(109),char(67),
+char(111),char(110),char(116),char(105),char(103),char(117),char(111),char(117),char(115),char(76),char(101),char(97),char(102),char(78),char(111),char(100),char(101),char(115),char(0),char(109),
+char(95),char(110),char(117),char(109),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(67),char(111),char(110),char(116),char(105),char(103),char(117),
+char(111),char(117),char(115),char(78),char(111),char(100),char(101),char(115),char(0),char(42),char(109),char(95),char(99),char(111),char(110),char(116),char(105),char(103),char(117),char(111),
+char(117),char(115),char(78),char(111),char(100),char(101),char(115),char(80),char(116),char(114),char(0),char(42),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),
+char(122),char(101),char(100),char(67),char(111),char(110),char(116),char(105),char(103),char(117),char(111),char(117),char(115),char(78),char(111),char(100),char(101),char(115),char(80),char(116),
+char(114),char(0),char(42),char(109),char(95),char(115),char(117),char(98),char(84),char(114),char(101),char(101),char(73),char(110),char(102),char(111),char(80),char(116),char(114),char(0),
+char(109),char(95),char(116),char(114),char(97),char(118),char(101),char(114),char(115),char(97),char(108),char(77),char(111),char(100),char(101),char(0),char(109),char(95),char(110),char(117),
+char(109),char(83),char(117),char(98),char(116),char(114),char(101),char(101),char(72),char(101),char(97),char(100),char(101),char(114),char(115),char(0),char(42),char(109),char(95),char(110),
+char(97),char(109),char(101),char(0),char(109),char(95),char(115),char(104),char(97),char(112),char(101),char(84),char(121),char(112),char(101),char(0),char(109),char(95),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(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(68),char(97),char(116),char(97),char(0),char(109),char(95),char(108),char(111),char(99),char(97),char(108),char(83),char(99),char(97),
+char(108),char(105),char(110),char(103),char(0),char(109),char(95),char(112),char(108),char(97),char(110),char(101),char(78),char(111),char(114),char(109),char(97),char(108),char(0),char(109),
+char(95),char(112),char(108),char(97),char(110),char(101),char(67),char(111),char(110),char(115),char(116),char(97),char(110),char(116),char(0),char(109),char(95),char(105),char(109),char(112),
+char(108),char(105),char(99),char(105),char(116),char(83),char(104),char(97),char(112),char(101),char(68),char(105),char(109),char(101),char(110),char(115),char(105),char(111),char(110),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(77),char(97),char(114),char(103),char(105),char(110),char(0),char(109),
+char(95),char(112),char(97),char(100),char(100),char(105),char(110),char(103),char(0),char(109),char(95),char(112),char(111),char(115),char(0),char(109),char(95),char(114),char(97),char(100),
+char(105),char(117),char(115),char(0),char(109),char(95),char(99),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(42),char(109),char(95),char(108),char(111),char(99),char(97),char(108),char(80),char(111),
+char(115),char(105),char(116),char(105),char(111),char(110),char(65),char(114),char(114),char(97),char(121),char(80),char(116),char(114),char(0),char(109),char(95),char(108),char(111),char(99),
+char(97),char(108),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(65),char(114),char(114),char(97),char(121),char(83),char(105),char(122),char(101),char(0),
+char(109),char(95),char(118),char(97),char(108),char(117),char(101),char(0),char(109),char(95),char(112),char(97),char(100),char(91),char(50),char(93),char(0),char(109),char(95),char(118),
+char(97),char(108),char(117),char(101),char(115),char(91),char(51),char(93),char(0),char(109),char(95),char(112),char(97),char(100),char(0),char(42),char(109),char(95),char(118),char(101),
+char(114),char(116),char(105),char(99),char(101),char(115),char(51),char(102),char(0),char(42),char(109),char(95),char(118),char(101),char(114),char(116),char(105),char(99),char(101),char(115),
+char(51),char(100),char(0),char(42),char(109),char(95),char(105),char(110),char(100),char(105),char(99),char(101),char(115),char(51),char(50),char(0),char(42),char(109),char(95),char(51),
+char(105),char(110),char(100),char(105),char(99),char(101),char(115),char(49),char(54),char(0),char(42),char(109),char(95),char(51),char(105),char(110),char(100),char(105),char(99),char(101),
+char(115),char(56),char(0),char(42),char(109),char(95),char(105),char(110),char(100),char(105),char(99),char(101),char(115),char(49),char(54),char(0),char(109),char(95),char(110),char(117),
+char(109),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(86),char(101),char(114),char(116),
+char(105),char(99),char(101),char(115),char(0),char(42),char(109),char(95),char(109),char(101),char(115),char(104),char(80),char(97),char(114),char(116),char(115),char(80),char(116),char(114),
+char(0),char(109),char(95),char(115),char(99),char(97),char(108),char(105),char(110),char(103),char(0),char(109),char(95),char(110),char(117),char(109),char(77),char(101),char(115),char(104),
+char(80),char(97),char(114),char(116),char(115),char(0),char(109),char(95),char(109),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(0),char(42),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(70),char(108),char(111),char(97),char(116),char(66),
+char(118),char(104),char(0),char(42),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(68),char(111),char(117),char(98),char(108),
+char(101),char(66),char(118),char(104),char(0),char(42),char(109),char(95),char(116),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(0),char(109),char(95),char(112),char(97),char(100),char(51),char(91),char(52),char(93),char(0),char(109),char(95),char(116),char(114),char(105),char(109),
+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(109),char(95),char(116),char(114),char(97),char(110),char(115),
+char(102),char(111),char(114),char(109),char(0),char(42),char(109),char(95),char(99),char(104),char(105),char(108),char(100),char(83),char(104),char(97),char(112),char(101),char(0),char(109),
+char(95),char(99),char(104),char(105),char(108),char(100),char(83),char(104),char(97),char(112),char(101),char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(99),char(104),
+char(105),char(108),char(100),char(77),char(97),char(114),char(103),char(105),char(110),char(0),char(42),char(109),char(95),char(99),char(104),char(105),char(108),char(100),char(83),char(104),
+char(97),char(112),char(101),char(80),char(116),char(114),char(0),char(109),char(95),char(110),char(117),char(109),char(67),char(104),char(105),char(108),char(100),char(83),char(104),char(97),
+char(112),char(101),char(115),char(0),char(109),char(95),char(117),char(112),char(65),char(120),char(105),char(115),char(0),char(109),char(95),char(117),char(112),char(73),char(110),char(100),
+char(101),char(120),char(0),char(109),char(95),char(102),char(108),char(97),char(103),char(115),char(0),char(109),char(95),char(101),char(100),char(103),char(101),char(86),char(48),char(86),
+char(49),char(65),char(110),char(103),char(108),char(101),char(0),char(109),char(95),char(101),char(100),char(103),char(101),char(86),char(49),char(86),char(50),char(65),char(110),char(103),
+char(108),char(101),char(0),char(109),char(95),char(101),char(100),char(103),char(101),char(86),char(50),char(86),char(48),char(65),char(110),char(103),char(108),char(101),char(0),char(42),
+char(109),char(95),char(104),char(97),char(115),char(104),char(84),char(97),char(98),char(108),char(101),char(80),char(116),char(114),char(0),char(42),char(109),char(95),char(110),char(101),
+char(120),char(116),char(80),char(116),char(114),char(0),char(42),char(109),char(95),char(118),char(97),char(108),char(117),char(101),char(65),char(114),char(114),char(97),char(121),char(80),
+char(116),char(114),char(0),char(42),char(109),char(95),char(107),char(101),char(121),char(65),char(114),char(114),char(97),char(121),char(80),char(116),char(114),char(0),char(109),char(95),
+char(99),char(111),char(110),char(118),char(101),char(120),char(69),char(112),char(115),char(105),char(108),char(111),char(110),char(0),char(109),char(95),char(112),char(108),char(97),char(110),
+char(97),char(114),char(69),char(112),char(115),char(105),char(108),char(111),char(110),char(0),char(109),char(95),char(101),char(113),char(117),char(97),char(108),char(86),char(101),char(114),
+char(116),char(101),char(120),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(101),char(100),char(103),char(101),char(68),
+char(105),char(115),char(116),char(97),char(110),char(99),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(122),
+char(101),char(114),char(111),char(65),char(114),char(101),char(97),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(101),char(120),char(116),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(104),char(97),char(115),char(104),char(84),char(97),char(98),char(108),char(101),char(83),
+char(105),char(122),char(101),char(0),char(109),char(95),char(110),char(117),char(109),char(86),char(97),char(108),char(117),char(101),char(115),char(0),char(109),char(95),char(110),char(117),
+char(109),char(75),char(101),char(121),char(115),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(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(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(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(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(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(67),char(111),char(109),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(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(84),char(114),char(97),
+char(110),char(115),char(102),char(111),char(114),char(109),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(84),char(89),char(80),char(69),char(95),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(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(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(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(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(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(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(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(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(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(64),char(0),char(68),char(0),char(-32),char(1),char(8),char(1),char(-104),char(0),char(88),char(0),char(-72),char(0),
+char(104),char(0),char(-16),char(1),char(-80),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(-76),char(1),char(-16),char(2),char(-120),char(1),char(-64),char(0),
+char(100),char(0),char(0),char(0),char(83),char(84),char(82),char(67),char(84),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(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(96),char(0),char(48),char(0),char(5),char(0),
+char(29),char(0),char(47),char(0),char(13),char(0),char(97),char(0),char(14),char(0),char(98),char(0),char(4),char(0),char(99),char(0),char(0),char(0),char(100),char(0),
+char(49),char(0),char(27),char(0),char(9),char(0),char(101),char(0),char(9),char(0),char(102),char(0),char(27),char(0),char(103),char(0),char(0),char(0),char(35),char(0),
+char(20),char(0),char(104),char(0),char(20),char(0),char(105),char(0),char(14),char(0),char(106),char(0),char(14),char(0),char(107),char(0),char(14),char(0),char(108),char(0),
+char(8),char(0),char(109),char(0),char(8),char(0),char(110),char(0),char(8),char(0),char(111),char(0),char(8),char(0),char(112),char(0),char(8),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(4),char(0),char(119),char(0),char(4),char(0),char(120),char(0),char(4),char(0),char(121),char(0),char(4),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(0),char(0),char(37),char(0),char(50),char(0),char(27),char(0),char(9),char(0),char(101),char(0),
+char(9),char(0),char(102),char(0),char(27),char(0),char(103),char(0),char(0),char(0),char(35),char(0),char(19),char(0),char(104),char(0),char(19),char(0),char(105),char(0),
+char(13),char(0),char(106),char(0),char(13),char(0),char(107),char(0),char(13),char(0),char(108),char(0),char(7),char(0),char(109),char(0),char(7),char(0),char(110),char(0),
+char(7),char(0),char(111),char(0),char(7),char(0),char(112),char(0),char(7),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(4),char(0),char(119),char(0),char(4),char(0),char(120),char(0),
+char(4),char(0),char(121),char(0),char(4),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(0),char(0),char(37),char(0),char(51),char(0),char(22),char(0),char(8),char(0),char(126),char(0),char(8),char(0),char(127),char(0),char(8),char(0),char(111),char(0),
+char(8),char(0),char(-128),char(0),char(8),char(0),char(115),char(0),char(8),char(0),char(-127),char(0),char(8),char(0),char(-126),char(0),char(8),char(0),char(-125),char(0),
+char(8),char(0),char(-124),char(0),char(8),char(0),char(-123),char(0),char(8),char(0),char(-122),char(0),char(8),char(0),char(-121),char(0),char(8),char(0),char(-120),char(0),
+char(8),char(0),char(-119),char(0),char(8),char(0),char(-118),char(0),char(8),char(0),char(-117),char(0),char(4),char(0),char(-116),char(0),char(4),char(0),char(-115),char(0),
+char(4),char(0),char(-114),char(0),char(4),char(0),char(-113),char(0),char(4),char(0),char(-112),char(0),char(0),char(0),char(37),char(0),char(52),char(0),char(22),char(0),
+char(7),char(0),char(126),char(0),char(7),char(0),char(127),char(0),char(7),char(0),char(111),char(0),char(7),char(0),char(-128),char(0),char(7),char(0),char(115),char(0),
+char(7),char(0),char(-127),char(0),char(7),char(0),char(-126),char(0),char(7),char(0),char(-125),char(0),char(7),char(0),char(-124),char(0),char(7),char(0),char(-123),char(0),
+char(7),char(0),char(-122),char(0),char(7),char(0),char(-121),char(0),char(7),char(0),char(-120),char(0),char(7),char(0),char(-119),char(0),char(7),char(0),char(-118),char(0),
+char(7),char(0),char(-117),char(0),char(4),char(0),char(-116),char(0),char(4),char(0),char(-115),char(0),char(4),char(0),char(-114),char(0),char(4),char(0),char(-113),char(0),
+char(4),char(0),char(-112),char(0),char(0),char(0),char(37),char(0),char(53),char(0),char(2),char(0),char(51),char(0),char(-111),char(0),char(14),char(0),char(-110),char(0),
+char(54),char(0),char(2),char(0),char(52),char(0),char(-111),char(0),char(13),char(0),char(-110),char(0),char(55),char(0),char(21),char(0),char(50),char(0),char(-109),char(0),
+char(17),char(0),char(-108),char(0),char(13),char(0),char(-107),char(0),char(13),char(0),char(-106),char(0),char(13),char(0),char(-105),char(0),char(13),char(0),char(-104),char(0),
+char(13),char(0),char(-110),char(0),char(13),char(0),char(-103),char(0),char(13),char(0),char(-102),char(0),char(13),char(0),char(-101),char(0),char(13),char(0),char(-100),char(0),
+char(7),char(0),char(-99),char(0),char(7),char(0),char(-98),char(0),char(7),char(0),char(-97),char(0),char(7),char(0),char(-96),char(0),char(7),char(0),char(-95),char(0),
+char(7),char(0),char(-94),char(0),char(7),char(0),char(-93),char(0),char(7),char(0),char(-92),char(0),char(7),char(0),char(-91),char(0),char(4),char(0),char(-90),char(0),
+char(56),char(0),char(22),char(0),char(49),char(0),char(-109),char(0),char(18),char(0),char(-108),char(0),char(14),char(0),char(-107),char(0),char(14),char(0),char(-106),char(0),
+char(14),char(0),char(-105),char(0),char(14),char(0),char(-104),char(0),char(14),char(0),char(-110),char(0),char(14),char(0),char(-103),char(0),char(14),char(0),char(-102),char(0),
+char(14),char(0),char(-101),char(0),char(14),char(0),char(-100),char(0),char(8),char(0),char(-99),char(0),char(8),char(0),char(-98),char(0),char(8),char(0),char(-97),char(0),
+char(8),char(0),char(-96),char(0),char(8),char(0),char(-95),char(0),char(8),char(0),char(-94),char(0),char(8),char(0),char(-93),char(0),char(8),char(0),char(-92),char(0),
+char(8),char(0),char(-91),char(0),char(4),char(0),char(-90),char(0),char(0),char(0),char(37),char(0),char(57),char(0),char(2),char(0),char(4),char(0),char(-89),char(0),
+char(4),char(0),char(-88),char(0),char(58),char(0),char(13),char(0),char(55),char(0),char(-87),char(0),char(55),char(0),char(-86),char(0),char(0),char(0),char(35),char(0),
+char(4),char(0),char(-85),char(0),char(4),char(0),char(-84),char(0),char(4),char(0),char(-83),char(0),char(4),char(0),char(-82),char(0),char(7),char(0),char(-81),char(0),
+char(7),char(0),char(-80),char(0),char(4),char(0),char(-79),char(0),char(4),char(0),char(-78),char(0),char(7),char(0),char(-77),char(0),char(4),char(0),char(-76),char(0),
+char(59),char(0),char(13),char(0),char(60),char(0),char(-87),char(0),char(60),char(0),char(-86),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(-85),char(0),
+char(4),char(0),char(-84),char(0),char(4),char(0),char(-83),char(0),char(4),char(0),char(-82),char(0),char(7),char(0),char(-81),char(0),char(7),char(0),char(-80),char(0),
+char(4),char(0),char(-79),char(0),char(4),char(0),char(-78),char(0),char(7),char(0),char(-77),char(0),char(4),char(0),char(-76),char(0),char(61),char(0),char(14),char(0),
+char(56),char(0),char(-87),char(0),char(56),char(0),char(-86),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(-85),char(0),char(4),char(0),char(-84),char(0),
+char(4),char(0),char(-83),char(0),char(4),char(0),char(-82),char(0),char(8),char(0),char(-81),char(0),char(8),char(0),char(-80),char(0),char(4),char(0),char(-79),char(0),
+char(4),char(0),char(-78),char(0),char(8),char(0),char(-77),char(0),char(4),char(0),char(-76),char(0),char(0),char(0),char(-75),char(0),char(62),char(0),char(3),char(0),
+char(59),char(0),char(-74),char(0),char(13),char(0),char(-73),char(0),char(13),char(0),char(-72),char(0),char(63),char(0),char(3),char(0),char(61),char(0),char(-74),char(0),
+char(14),char(0),char(-73),char(0),char(14),char(0),char(-72),char(0),char(64),char(0),char(3),char(0),char(59),char(0),char(-74),char(0),char(14),char(0),char(-73),char(0),
+char(14),char(0),char(-72),char(0),char(65),char(0),char(13),char(0),char(59),char(0),char(-74),char(0),char(20),char(0),char(-71),char(0),char(20),char(0),char(-70),char(0),
+char(4),char(0),char(-69),char(0),char(4),char(0),char(-68),char(0),char(4),char(0),char(-67),char(0),char(7),char(0),char(-66),char(0),char(7),char(0),char(-65),char(0),
+char(7),char(0),char(-64),char(0),char(7),char(0),char(-63),char(0),char(7),char(0),char(-62),char(0),char(7),char(0),char(-61),char(0),char(7),char(0),char(-60),char(0),
+char(66),char(0),char(13),char(0),char(59),char(0),char(-74),char(0),char(19),char(0),char(-71),char(0),char(19),char(0),char(-70),char(0),char(4),char(0),char(-69),char(0),
+char(4),char(0),char(-68),char(0),char(4),char(0),char(-67),char(0),char(7),char(0),char(-66),char(0),char(7),char(0),char(-65),char(0),char(7),char(0),char(-64),char(0),
+char(7),char(0),char(-63),char(0),char(7),char(0),char(-62),char(0),char(7),char(0),char(-61),char(0),char(7),char(0),char(-60),char(0),char(67),char(0),char(14),char(0),
+char(61),char(0),char(-74),char(0),char(20),char(0),char(-71),char(0),char(20),char(0),char(-70),char(0),char(4),char(0),char(-69),char(0),char(4),char(0),char(-68),char(0),
+char(4),char(0),char(-67),char(0),char(8),char(0),char(-66),char(0),char(8),char(0),char(-65),char(0),char(8),char(0),char(-64),char(0),char(8),char(0),char(-63),char(0),
+char(8),char(0),char(-62),char(0),char(8),char(0),char(-61),char(0),char(8),char(0),char(-60),char(0),char(0),char(0),char(-59),char(0),char(68),char(0),char(10),char(0),
+char(61),char(0),char(-74),char(0),char(20),char(0),char(-71),char(0),char(20),char(0),char(-70),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(-62),char(0),char(8),char(0),char(-61),char(0),char(8),char(0),char(-60),char(0),char(8),char(0),char(127),char(0),
+char(69),char(0),char(11),char(0),char(59),char(0),char(-74),char(0),char(19),char(0),char(-71),char(0),char(19),char(0),char(-70),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(-62),char(0),char(7),char(0),char(-61),char(0),char(7),char(0),char(-60),char(0),
+char(7),char(0),char(127),char(0),char(0),char(0),char(21),char(0),char(70),char(0),char(9),char(0),char(59),char(0),char(-74),char(0),char(19),char(0),char(-71),char(0),
+char(19),char(0),char(-70),char(0),char(13),char(0),char(-55),char(0),char(13),char(0),char(-54),char(0),char(13),char(0),char(-53),char(0),char(13),char(0),char(-52),char(0),
+char(4),char(0),char(-51),char(0),char(4),char(0),char(-50),char(0),char(71),char(0),char(9),char(0),char(61),char(0),char(-74),char(0),char(20),char(0),char(-71),char(0),
+char(20),char(0),char(-70),char(0),char(14),char(0),char(-55),char(0),char(14),char(0),char(-54),char(0),char(14),char(0),char(-53),char(0),char(14),char(0),char(-52),char(0),
+char(4),char(0),char(-51),char(0),char(4),char(0),char(-50),char(0),char(72),char(0),char(5),char(0),char(70),char(0),char(-49),char(0),char(4),char(0),char(-48),char(0),
+char(7),char(0),char(-47),char(0),char(7),char(0),char(-46),char(0),char(7),char(0),char(-45),char(0),char(73),char(0),char(5),char(0),char(71),char(0),char(-49),char(0),
+char(4),char(0),char(-48),char(0),char(8),char(0),char(-47),char(0),char(8),char(0),char(-46),char(0),char(8),char(0),char(-45),char(0),char(74),char(0),char(41),char(0),
+char(59),char(0),char(-74),char(0),char(19),char(0),char(-71),char(0),char(19),char(0),char(-70),char(0),char(13),char(0),char(-55),char(0),char(13),char(0),char(-54),char(0),
+char(13),char(0),char(-44),char(0),char(13),char(0),char(-43),char(0),char(13),char(0),char(-42),char(0),char(13),char(0),char(-41),char(0),char(13),char(0),char(-40),char(0),
+char(13),char(0),char(-39),char(0),char(13),char(0),char(-38),char(0),char(13),char(0),char(-37),char(0),char(13),char(0),char(-36),char(0),char(13),char(0),char(-35),char(0),
+char(13),char(0),char(-34),char(0),char(0),char(0),char(-33),char(0),char(0),char(0),char(-32),char(0),char(0),char(0),char(-31),char(0),char(0),char(0),char(-30),char(0),
+char(0),char(0),char(-29),char(0),char(0),char(0),char(-59),char(0),char(13),char(0),char(-53),char(0),char(13),char(0),char(-52),char(0),char(13),char(0),char(-28),char(0),
+char(13),char(0),char(-27),char(0),char(13),char(0),char(-26),char(0),char(13),char(0),char(-25),char(0),char(13),char(0),char(-24),char(0),char(13),char(0),char(-23),char(0),
+char(13),char(0),char(-22),char(0),char(13),char(0),char(-21),char(0),char(13),char(0),char(-20),char(0),char(13),char(0),char(-19),char(0),char(13),char(0),char(-18),char(0),
+char(0),char(0),char(-17),char(0),char(0),char(0),char(-16),char(0),char(0),char(0),char(-15),char(0),char(0),char(0),char(-14),char(0),char(0),char(0),char(-13),char(0),
+char(4),char(0),char(-12),char(0),char(75),char(0),char(41),char(0),char(61),char(0),char(-74),char(0),char(20),char(0),char(-71),char(0),char(20),char(0),char(-70),char(0),
+char(14),char(0),char(-55),char(0),char(14),char(0),char(-54),char(0),char(14),char(0),char(-44),char(0),char(14),char(0),char(-43),char(0),char(14),char(0),char(-42),char(0),
+char(14),char(0),char(-41),char(0),char(14),char(0),char(-40),char(0),char(14),char(0),char(-39),char(0),char(14),char(0),char(-38),char(0),char(14),char(0),char(-37),char(0),
+char(14),char(0),char(-36),char(0),char(14),char(0),char(-35),char(0),char(14),char(0),char(-34),char(0),char(0),char(0),char(-33),char(0),char(0),char(0),char(-32),char(0),
+char(0),char(0),char(-31),char(0),char(0),char(0),char(-30),char(0),char(0),char(0),char(-29),char(0),char(0),char(0),char(-59),char(0),char(14),char(0),char(-53),char(0),
+char(14),char(0),char(-52),char(0),char(14),char(0),char(-28),char(0),char(14),char(0),char(-27),char(0),char(14),char(0),char(-26),char(0),char(14),char(0),char(-25),char(0),
+char(14),char(0),char(-24),char(0),char(14),char(0),char(-23),char(0),char(14),char(0),char(-22),char(0),char(14),char(0),char(-21),char(0),char(14),char(0),char(-20),char(0),
+char(14),char(0),char(-19),char(0),char(14),char(0),char(-18),char(0),char(0),char(0),char(-17),char(0),char(0),char(0),char(-16),char(0),char(0),char(0),char(-15),char(0),
+char(0),char(0),char(-14),char(0),char(0),char(0),char(-13),char(0),char(4),char(0),char(-12),char(0),char(76),char(0),char(9),char(0),char(59),char(0),char(-74),char(0),
+char(19),char(0),char(-71),char(0),char(19),char(0),char(-70),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(4),char(0),char(-50),char(0),char(77),char(0),char(9),char(0),char(61),char(0),char(-74),char(0),
+char(20),char(0),char(-71),char(0),char(20),char(0),char(-70),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(4),char(0),char(-50),char(0),char(78),char(0),char(5),char(0),char(58),char(0),char(-74),char(0),
+char(13),char(0),char(-11),char(0),char(13),char(0),char(-10),char(0),char(7),char(0),char(-9),char(0),char(0),char(0),char(37),char(0),char(79),char(0),char(4),char(0),
+char(61),char(0),char(-74),char(0),char(14),char(0),char(-11),char(0),char(14),char(0),char(-10),char(0),char(8),char(0),char(-9),char(0),char(80),char(0),char(4),char(0),
+char(7),char(0),char(-8),char(0),char(7),char(0),char(-7),char(0),char(7),char(0),char(-6),char(0),char(4),char(0),char(79),char(0),char(81),char(0),char(10),char(0),
+char(80),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(7),char(0),char(-99),char(0),char(7),char(0),char(1),char(1),char(4),char(0),char(2),char(1),char(4),char(0),char(53),char(0),
+char(82),char(0),char(4),char(0),char(80),char(0),char(-5),char(0),char(4),char(0),char(3),char(1),char(7),char(0),char(4),char(1),char(4),char(0),char(5),char(1),
+char(83),char(0),char(4),char(0),char(13),char(0),char(0),char(1),char(80),char(0),char(-5),char(0),char(4),char(0),char(6),char(1),char(7),char(0),char(7),char(1),
+char(84),char(0),char(7),char(0),char(13),char(0),char(8),char(1),char(80),char(0),char(-5),char(0),char(4),char(0),char(9),char(1),char(7),char(0),char(10),char(1),
+char(7),char(0),char(11),char(1),char(7),char(0),char(12),char(1),char(4),char(0),char(53),char(0),char(85),char(0),char(6),char(0),char(17),char(0),char(13),char(1),
+char(13),char(0),char(11),char(1),char(13),char(0),char(14),char(1),char(60),char(0),char(15),char(1),char(4),char(0),char(16),char(1),char(7),char(0),char(12),char(1),
+char(86),char(0),char(26),char(0),char(4),char(0),char(17),char(1),char(7),char(0),char(18),char(1),char(7),char(0),char(127),char(0),char(7),char(0),char(19),char(1),
+char(7),char(0),char(20),char(1),char(7),char(0),char(21),char(1),char(7),char(0),char(22),char(1),char(7),char(0),char(23),char(1),char(7),char(0),char(24),char(1),
+char(7),char(0),char(25),char(1),char(7),char(0),char(26),char(1),char(7),char(0),char(27),char(1),char(7),char(0),char(28),char(1),char(7),char(0),char(29),char(1),
+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(7),char(0),char(33),char(1),char(7),char(0),char(34),char(1),
+char(7),char(0),char(35),char(1),char(7),char(0),char(36),char(1),char(4),char(0),char(37),char(1),char(4),char(0),char(38),char(1),char(4),char(0),char(39),char(1),
+char(4),char(0),char(40),char(1),char(4),char(0),char(120),char(0),char(87),char(0),char(12),char(0),char(17),char(0),char(41),char(1),char(17),char(0),char(42),char(1),
+char(17),char(0),char(43),char(1),char(13),char(0),char(44),char(1),char(13),char(0),char(45),char(1),char(7),char(0),char(46),char(1),char(4),char(0),char(47),char(1),
+char(4),char(0),char(48),char(1),char(4),char(0),char(49),char(1),char(4),char(0),char(50),char(1),char(7),char(0),char(10),char(1),char(4),char(0),char(53),char(0),
+char(88),char(0),char(27),char(0),char(19),char(0),char(51),char(1),char(17),char(0),char(52),char(1),char(17),char(0),char(53),char(1),char(13),char(0),char(44),char(1),
+char(13),char(0),char(54),char(1),char(13),char(0),char(55),char(1),char(13),char(0),char(56),char(1),char(13),char(0),char(57),char(1),char(13),char(0),char(58),char(1),
+char(4),char(0),char(59),char(1),char(7),char(0),char(60),char(1),char(4),char(0),char(61),char(1),char(4),char(0),char(62),char(1),char(4),char(0),char(63),char(1),
+char(7),char(0),char(64),char(1),char(7),char(0),char(65),char(1),char(4),char(0),char(66),char(1),char(4),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(4),char(0),char(74),char(1),char(4),char(0),char(75),char(1),char(4),char(0),char(76),char(1),char(89),char(0),char(12),char(0),char(9),char(0),char(77),char(1),
+char(9),char(0),char(78),char(1),char(13),char(0),char(79),char(1),char(7),char(0),char(80),char(1),char(7),char(0),char(-125),char(0),char(7),char(0),char(81),char(1),
+char(4),char(0),char(82),char(1),char(13),char(0),char(83),char(1),char(4),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(53),char(0),char(90),char(0),char(19),char(0),char(50),char(0),char(-109),char(0),char(87),char(0),char(87),char(1),char(80),char(0),char(88),char(1),
+char(81),char(0),char(89),char(1),char(82),char(0),char(90),char(1),char(83),char(0),char(91),char(1),char(84),char(0),char(92),char(1),char(85),char(0),char(93),char(1),
+char(88),char(0),char(94),char(1),char(89),char(0),char(95),char(1),char(4),char(0),char(96),char(1),char(4),char(0),char(62),char(1),char(4),char(0),char(97),char(1),
+char(4),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(4),char(0),char(102),char(1),
+char(86),char(0),char(103),char(1),char(91),char(0),char(24),char(0),char(16),char(0),char(104),char(1),char(14),char(0),char(105),char(1),char(14),char(0),char(106),char(1),
+char(14),char(0),char(107),char(1),char(14),char(0),char(108),char(1),char(14),char(0),char(109),char(1),char(8),char(0),char(110),char(1),char(4),char(0),char(111),char(1),
+char(4),char(0),char(86),char(1),char(4),char(0),char(112),char(1),char(4),char(0),char(113),char(1),char(8),char(0),char(114),char(1),char(8),char(0),char(115),char(1),
+char(8),char(0),char(116),char(1),char(8),char(0),char(117),char(1),char(8),char(0),char(118),char(1),char(8),char(0),char(119),char(1),char(8),char(0),char(120),char(1),
+char(8),char(0),char(121),char(1),char(8),char(0),char(122),char(1),char(0),char(0),char(123),char(1),char(0),char(0),char(124),char(1),char(49),char(0),char(125),char(1),
+char(0),char(0),char(126),char(1),char(92),char(0),char(24),char(0),char(15),char(0),char(104),char(1),char(13),char(0),char(105),char(1),char(13),char(0),char(106),char(1),
+char(13),char(0),char(107),char(1),char(13),char(0),char(108),char(1),char(13),char(0),char(109),char(1),char(4),char(0),char(112),char(1),char(7),char(0),char(110),char(1),
+char(4),char(0),char(111),char(1),char(4),char(0),char(86),char(1),char(7),char(0),char(114),char(1),char(7),char(0),char(115),char(1),char(7),char(0),char(116),char(1),
+char(4),char(0),char(113),char(1),char(7),char(0),char(117),char(1),char(7),char(0),char(118),char(1),char(7),char(0),char(119),char(1),char(7),char(0),char(120),char(1),
+char(7),char(0),char(121),char(1),char(7),char(0),char(122),char(1),char(0),char(0),char(123),char(1),char(0),char(0),char(124),char(1),char(50),char(0),char(125),char(1),
+char(0),char(0),char(126),char(1),char(93),char(0),char(9),char(0),char(20),char(0),char(127),char(1),char(14),char(0),char(-128),char(1),char(8),char(0),char(-127),char(1),
+char(0),char(0),char(-126),char(1),char(91),char(0),char(90),char(1),char(49),char(0),char(-125),char(1),char(0),char(0),char(126),char(1),char(4),char(0),char(97),char(1),
+char(0),char(0),char(37),char(0),char(94),char(0),char(7),char(0),char(0),char(0),char(-126),char(1),char(92),char(0),char(90),char(1),char(50),char(0),char(-125),char(1),
+char(19),char(0),char(127),char(1),char(13),char(0),char(-128),char(1),char(7),char(0),char(-127),char(1),char(4),char(0),char(97),char(1),};
+int sBulletDNAlen= sizeof(sBulletDNAstr);
diff --git a/thirdparty/bullet/src/LinearMath/btSerializer.h b/thirdparty/bullet/src/LinearMath/btSerializer.h
new file mode 100644
index 0000000000..89b4d74683
--- /dev/null
+++ b/thirdparty/bullet/src/LinearMath/btSerializer.h
@@ -0,0 +1,908 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans 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_SERIALIZER_H
+#define BT_SERIALIZER_H
+
+#include "btScalar.h" // has definitions like SIMD_FORCE_INLINE
+#include "btHashMap.h"
+
+#if !defined( __CELLOS_LV2__) && !defined(__MWERKS__)
+#include <memory.h>
+#endif
+#include <string.h>
+
+
+
+
+extern char sBulletDNAstr[];
+extern int sBulletDNAlen;
+extern char sBulletDNAstr64[];
+extern int sBulletDNAlen64;
+
+SIMD_FORCE_INLINE int btStrLen(const char* str)
+{
+ if (!str)
+ return(0);
+ int len = 0;
+
+ while (*str != 0)
+ {
+ str++;
+ len++;
+ }
+
+ return len;
+}
+
+
+class btChunk
+{
+public:
+ int m_chunkCode;
+ int m_length;
+ void *m_oldPtr;
+ int m_dna_nr;
+ int m_number;
+};
+
+enum btSerializationFlags
+{
+ BT_SERIALIZE_NO_BVH = 1,
+ BT_SERIALIZE_NO_TRIANGLEINFOMAP = 2,
+ BT_SERIALIZE_NO_DUPLICATE_ASSERT = 4
+};
+
+class btSerializer
+{
+
+public:
+
+ virtual ~btSerializer() {}
+
+ virtual const unsigned char* getBufferPointer() const = 0;
+
+ virtual int getCurrentBufferSize() const = 0;
+
+ virtual btChunk* allocate(size_t size, int numElements) = 0;
+
+ virtual void finalizeChunk(btChunk* chunk, const char* structType, int chunkCode,void* oldPtr)= 0;
+
+ virtual void* findPointer(void* oldPtr) = 0;
+
+ virtual void* getUniquePointer(void*oldPtr) = 0;
+
+ virtual void startSerialization() = 0;
+
+ virtual void finishSerialization() = 0;
+
+ virtual const char* findNameForPointer(const void* ptr) const = 0;
+
+ virtual void registerNameForPointer(const void* ptr, const char* name) = 0;
+
+ virtual void serializeName(const char* ptr) = 0;
+
+ virtual int getSerializationFlags() const = 0;
+
+ virtual void setSerializationFlags(int flags) = 0;
+
+ virtual int getNumChunks() const = 0;
+
+ virtual const btChunk* getChunk(int chunkIndex) const = 0;
+
+};
+
+
+
+#define BT_HEADER_LENGTH 12
+#if defined(__sgi) || defined (__sparc) || defined (__sparc__) || defined (__PPC__) || defined (__ppc__) || defined (__BIG_ENDIAN__)
+# define BT_MAKE_ID(a,b,c,d) ( (int)(a)<<24 | (int)(b)<<16 | (c)<<8 | (d) )
+#else
+# define BT_MAKE_ID(a,b,c,d) ( (int)(d)<<24 | (int)(c)<<16 | (b)<<8 | (a) )
+#endif
+
+
+#define BT_MULTIBODY_CODE BT_MAKE_ID('M','B','D','Y')
+#define BT_SOFTBODY_CODE BT_MAKE_ID('S','B','D','Y')
+#define BT_COLLISIONOBJECT_CODE BT_MAKE_ID('C','O','B','J')
+#define BT_RIGIDBODY_CODE BT_MAKE_ID('R','B','D','Y')
+#define BT_CONSTRAINT_CODE BT_MAKE_ID('C','O','N','S')
+#define BT_BOXSHAPE_CODE BT_MAKE_ID('B','O','X','S')
+#define BT_QUANTIZED_BVH_CODE BT_MAKE_ID('Q','B','V','H')
+#define BT_TRIANLGE_INFO_MAP BT_MAKE_ID('T','M','A','P')
+#define BT_SHAPE_CODE BT_MAKE_ID('S','H','A','P')
+#define BT_ARRAY_CODE BT_MAKE_ID('A','R','A','Y')
+#define BT_SBMATERIAL_CODE BT_MAKE_ID('S','B','M','T')
+#define BT_SBNODE_CODE BT_MAKE_ID('S','B','N','D')
+#define BT_DYNAMICSWORLD_CODE BT_MAKE_ID('D','W','L','D')
+#define BT_DNA_CODE BT_MAKE_ID('D','N','A','1')
+
+
+struct btPointerUid
+{
+ union
+ {
+ void* m_ptr;
+ int m_uniqueIds[2];
+ };
+};
+
+struct btBulletSerializedArrays
+{
+ btBulletSerializedArrays()
+ {
+ }
+ btAlignedObjectArray<struct btQuantizedBvhDoubleData*> m_bvhsDouble;
+ btAlignedObjectArray<struct btQuantizedBvhFloatData*> m_bvhsFloat;
+ btAlignedObjectArray<struct btCollisionShapeData*> m_colShapeData;
+ btAlignedObjectArray<struct btDynamicsWorldDoubleData*> m_dynamicWorldInfoDataDouble;
+ btAlignedObjectArray<struct btDynamicsWorldFloatData*> m_dynamicWorldInfoDataFloat;
+ btAlignedObjectArray<struct btRigidBodyDoubleData*> m_rigidBodyDataDouble;
+ btAlignedObjectArray<struct btRigidBodyFloatData*> m_rigidBodyDataFloat;
+ btAlignedObjectArray<struct btCollisionObjectDoubleData*> m_collisionObjectDataDouble;
+ btAlignedObjectArray<struct btCollisionObjectFloatData*> m_collisionObjectDataFloat;
+ btAlignedObjectArray<struct btTypedConstraintFloatData*> m_constraintDataFloat;
+ btAlignedObjectArray<struct btTypedConstraintDoubleData*> m_constraintDataDouble;
+ btAlignedObjectArray<struct btTypedConstraintData*> m_constraintData;//for backwards compatibility
+ btAlignedObjectArray<struct btSoftBodyFloatData*> m_softBodyFloatData;
+ btAlignedObjectArray<struct btSoftBodyDoubleData*> m_softBodyDoubleData;
+
+};
+
+
+///The btDefaultSerializer is the main Bullet serialization class.
+///The constructor takes an optional argument for backwards compatibility, it is recommended to leave this empty/zero.
+class btDefaultSerializer : public btSerializer
+{
+
+protected:
+
+ btAlignedObjectArray<char*> mTypes;
+ btAlignedObjectArray<short*> mStructs;
+ btAlignedObjectArray<short> mTlens;
+ btHashMap<btHashInt, int> mStructReverse;
+ btHashMap<btHashString,int> mTypeLookup;
+
+
+
+ btHashMap<btHashPtr,void*> m_chunkP;
+
+ btHashMap<btHashPtr,const char*> m_nameMap;
+
+ btHashMap<btHashPtr,btPointerUid> m_uniquePointers;
+ int m_uniqueIdGenerator;
+
+ int m_totalSize;
+ unsigned char* m_buffer;
+ bool m_ownsBuffer;
+ int m_currentSize;
+ void* m_dna;
+ int m_dnaLength;
+
+ int m_serializationFlags;
+
+
+ btAlignedObjectArray<btChunk*> m_chunkPtrs;
+
+protected:
+
+
+ virtual void* findPointer(void* oldPtr)
+ {
+ void** ptr = m_chunkP.find(oldPtr);
+ if (ptr && *ptr)
+ return *ptr;
+ return 0;
+ }
+
+
+
+
+
+ virtual void writeDNA()
+ {
+ btChunk* dnaChunk = allocate(m_dnaLength,1);
+ memcpy(dnaChunk->m_oldPtr,m_dna,m_dnaLength);
+ finalizeChunk(dnaChunk,"DNA1",BT_DNA_CODE, m_dna);
+ }
+
+ int getReverseType(const char *type) const
+ {
+
+ btHashString key(type);
+ const int* valuePtr = mTypeLookup.find(key);
+ if (valuePtr)
+ return *valuePtr;
+
+ return -1;
+ }
+
+ void initDNA(const char* bdnaOrg,int dnalen)
+ {
+ ///was already initialized
+ if (m_dna)
+ return;
+
+ int littleEndian= 1;
+ littleEndian= ((char*)&littleEndian)[0];
+
+
+ m_dna = btAlignedAlloc(dnalen,16);
+ memcpy(m_dna,bdnaOrg,dnalen);
+ m_dnaLength = dnalen;
+
+ int *intPtr=0;
+ short *shtPtr=0;
+ char *cp = 0;int dataLen =0;
+ intPtr = (int*)m_dna;
+
+ /*
+ SDNA (4 bytes) (magic number)
+ NAME (4 bytes)
+ <nr> (4 bytes) amount of names (int)
+ <string>
+ <string>
+ */
+
+ if (strncmp((const char*)m_dna, "SDNA", 4)==0)
+ {
+ // skip ++ NAME
+ intPtr++; intPtr++;
+ }
+
+ // Parse names
+ if (!littleEndian)
+ *intPtr = btSwapEndian(*intPtr);
+
+ dataLen = *intPtr;
+
+ intPtr++;
+
+ cp = (char*)intPtr;
+ int i;
+ for ( i=0; i<dataLen; i++)
+ {
+
+ while (*cp)cp++;
+ cp++;
+ }
+ cp = btAlignPointer(cp,4);
+
+ /*
+ TYPE (4 bytes)
+ <nr> amount of types (int)
+ <string>
+ <string>
+ */
+
+ intPtr = (int*)cp;
+ btAssert(strncmp(cp, "TYPE", 4)==0); intPtr++;
+
+ if (!littleEndian)
+ *intPtr = btSwapEndian(*intPtr);
+
+ dataLen = *intPtr;
+ intPtr++;
+
+
+ cp = (char*)intPtr;
+ for (i=0; i<dataLen; i++)
+ {
+ mTypes.push_back(cp);
+ while (*cp)cp++;
+ cp++;
+ }
+
+ cp = btAlignPointer(cp,4);
+
+
+ /*
+ TLEN (4 bytes)
+ <len> (short) the lengths of types
+ <len>
+ */
+
+ // Parse type lens
+ intPtr = (int*)cp;
+ btAssert(strncmp(cp, "TLEN", 4)==0); intPtr++;
+
+ dataLen = (int)mTypes.size();
+
+ shtPtr = (short*)intPtr;
+ for (i=0; i<dataLen; i++, shtPtr++)
+ {
+ if (!littleEndian)
+ shtPtr[0] = btSwapEndian(shtPtr[0]);
+ mTlens.push_back(shtPtr[0]);
+ }
+
+ if (dataLen & 1) shtPtr++;
+
+ /*
+ STRC (4 bytes)
+ <nr> amount of structs (int)
+ <typenr>
+ <nr_of_elems>
+ <typenr>
+ <namenr>
+ <typenr>
+ <namenr>
+ */
+
+ intPtr = (int*)shtPtr;
+ cp = (char*)intPtr;
+ btAssert(strncmp(cp, "STRC", 4)==0); intPtr++;
+
+ if (!littleEndian)
+ *intPtr = btSwapEndian(*intPtr);
+ dataLen = *intPtr ;
+ intPtr++;
+
+
+ shtPtr = (short*)intPtr;
+ for (i=0; i<dataLen; i++)
+ {
+ mStructs.push_back (shtPtr);
+
+ if (!littleEndian)
+ {
+ shtPtr[0]= btSwapEndian(shtPtr[0]);
+ shtPtr[1]= btSwapEndian(shtPtr[1]);
+
+ int len = shtPtr[1];
+ shtPtr+= 2;
+
+ for (int a=0; a<len; a++, shtPtr+=2)
+ {
+ shtPtr[0]= btSwapEndian(shtPtr[0]);
+ shtPtr[1]= btSwapEndian(shtPtr[1]);
+ }
+
+ } else
+ {
+ shtPtr+= (2*shtPtr[1])+2;
+ }
+ }
+
+ // build reverse lookups
+ for (i=0; i<(int)mStructs.size(); i++)
+ {
+ short *strc = mStructs.at(i);
+ mStructReverse.insert(strc[0], i);
+ mTypeLookup.insert(btHashString(mTypes[strc[0]]),i);
+ }
+ }
+
+public:
+
+ btHashMap<btHashPtr,void*> m_skipPointers;
+
+
+ btDefaultSerializer(int totalSize=0, unsigned char* buffer=0)
+ :m_uniqueIdGenerator(0),
+ m_totalSize(totalSize),
+ m_currentSize(0),
+ m_dna(0),
+ m_dnaLength(0),
+ m_serializationFlags(0)
+ {
+ if (buffer==0)
+ {
+ m_buffer = m_totalSize?(unsigned char*)btAlignedAlloc(totalSize,16):0;
+ m_ownsBuffer = true;
+ } else
+ {
+ m_buffer = buffer;
+ m_ownsBuffer = false;
+ }
+
+ const bool VOID_IS_8 = ((sizeof(void*)==8));
+
+#ifdef BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+ if (VOID_IS_8)
+ {
+#if _WIN64
+ initDNA((const char*)sBulletDNAstr64,sBulletDNAlen64);
+#else
+ btAssert(0);
+#endif
+ } else
+ {
+#ifndef _WIN64
+ initDNA((const char*)sBulletDNAstr,sBulletDNAlen);
+#else
+ btAssert(0);
+#endif
+ }
+
+#else //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+ if (VOID_IS_8)
+ {
+ initDNA((const char*)sBulletDNAstr64,sBulletDNAlen64);
+ } else
+ {
+ initDNA((const char*)sBulletDNAstr,sBulletDNAlen);
+ }
+#endif //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+
+ }
+
+ virtual ~btDefaultSerializer()
+ {
+ if (m_buffer && m_ownsBuffer)
+ btAlignedFree(m_buffer);
+ if (m_dna)
+ btAlignedFree(m_dna);
+ }
+
+ static int getMemoryDnaSizeInBytes()
+ {
+ const bool VOID_IS_8 = ((sizeof(void*) == 8));
+
+ if (VOID_IS_8)
+ {
+ return sBulletDNAlen64;
+ }
+ return sBulletDNAlen;
+ }
+ static const char* getMemoryDna()
+ {
+ const bool VOID_IS_8 = ((sizeof(void*) == 8));
+ if (VOID_IS_8)
+ {
+ return (const char*)sBulletDNAstr64;
+ }
+ return (const char*)sBulletDNAstr;
+ }
+
+ void insertHeader()
+ {
+ writeHeader(m_buffer);
+ m_currentSize += BT_HEADER_LENGTH;
+ }
+
+ void writeHeader(unsigned char* buffer) const
+ {
+
+
+#ifdef BT_USE_DOUBLE_PRECISION
+ memcpy(buffer, "BULLETd", 7);
+#else
+ memcpy(buffer, "BULLETf", 7);
+#endif //BT_USE_DOUBLE_PRECISION
+
+ int littleEndian= 1;
+ littleEndian= ((char*)&littleEndian)[0];
+
+ if (sizeof(void*)==8)
+ {
+ buffer[7] = '-';
+ } else
+ {
+ buffer[7] = '_';
+ }
+
+ if (littleEndian)
+ {
+ buffer[8]='v';
+ } else
+ {
+ buffer[8]='V';
+ }
+
+
+ buffer[9] = '2';
+ buffer[10] = '8';
+ buffer[11] = '7';
+
+ }
+
+ virtual void startSerialization()
+ {
+ m_uniqueIdGenerator= 1;
+ if (m_totalSize)
+ {
+ unsigned char* buffer = internalAlloc(BT_HEADER_LENGTH);
+ writeHeader(buffer);
+ }
+
+ }
+
+ virtual void finishSerialization()
+ {
+ writeDNA();
+
+ //if we didn't pre-allocate a buffer, we need to create a contiguous buffer now
+ int mysize = 0;
+ if (!m_totalSize)
+ {
+ if (m_buffer)
+ btAlignedFree(m_buffer);
+
+ m_currentSize += BT_HEADER_LENGTH;
+ m_buffer = (unsigned char*)btAlignedAlloc(m_currentSize,16);
+
+ unsigned char* currentPtr = m_buffer;
+ writeHeader(m_buffer);
+ currentPtr += BT_HEADER_LENGTH;
+ mysize+=BT_HEADER_LENGTH;
+ for (int i=0;i< m_chunkPtrs.size();i++)
+ {
+ int curLength = sizeof(btChunk)+m_chunkPtrs[i]->m_length;
+ memcpy(currentPtr,m_chunkPtrs[i], curLength);
+ btAlignedFree(m_chunkPtrs[i]);
+ currentPtr+=curLength;
+ mysize+=curLength;
+ }
+ }
+
+ mTypes.clear();
+ mStructs.clear();
+ mTlens.clear();
+ mStructReverse.clear();
+ mTypeLookup.clear();
+ m_skipPointers.clear();
+ m_chunkP.clear();
+ m_nameMap.clear();
+ m_uniquePointers.clear();
+ m_chunkPtrs.clear();
+ }
+
+ virtual void* getUniquePointer(void*oldPtr)
+ {
+ btAssert(m_uniqueIdGenerator >= 0);
+ if (!oldPtr)
+ return 0;
+
+ btPointerUid* uptr = (btPointerUid*)m_uniquePointers.find(oldPtr);
+ if (uptr)
+ {
+ return uptr->m_ptr;
+ }
+
+ void** ptr2 = m_skipPointers[oldPtr];
+ if (ptr2)
+ {
+ return 0;
+ }
+
+ m_uniqueIdGenerator++;
+
+ btPointerUid uid;
+ uid.m_uniqueIds[0] = m_uniqueIdGenerator;
+ uid.m_uniqueIds[1] = m_uniqueIdGenerator;
+ m_uniquePointers.insert(oldPtr,uid);
+ return uid.m_ptr;
+
+ }
+
+ virtual const unsigned char* getBufferPointer() const
+ {
+ return m_buffer;
+ }
+
+ virtual int getCurrentBufferSize() const
+ {
+ return m_currentSize;
+ }
+
+ virtual void finalizeChunk(btChunk* chunk, const char* structType, int chunkCode,void* oldPtr)
+ {
+ if (!(m_serializationFlags&BT_SERIALIZE_NO_DUPLICATE_ASSERT))
+ {
+ btAssert(!findPointer(oldPtr));
+ }
+
+ chunk->m_dna_nr = getReverseType(structType);
+
+ chunk->m_chunkCode = chunkCode;
+
+ void* uniquePtr = getUniquePointer(oldPtr);
+
+ m_chunkP.insert(oldPtr,uniquePtr);//chunk->m_oldPtr);
+ chunk->m_oldPtr = uniquePtr;//oldPtr;
+
+ }
+
+
+ virtual unsigned char* internalAlloc(size_t size)
+ {
+ unsigned char* ptr = 0;
+
+ if (m_totalSize)
+ {
+ ptr = m_buffer+m_currentSize;
+ m_currentSize += int(size);
+ btAssert(m_currentSize<m_totalSize);
+ } else
+ {
+ ptr = (unsigned char*)btAlignedAlloc(size,16);
+ m_currentSize += int(size);
+ }
+ return ptr;
+ }
+
+
+
+ virtual btChunk* allocate(size_t size, int numElements)
+ {
+
+ unsigned char* ptr = internalAlloc(int(size)*numElements+sizeof(btChunk));
+
+ unsigned char* data = ptr + sizeof(btChunk);
+
+ btChunk* chunk = (btChunk*)ptr;
+ chunk->m_chunkCode = 0;
+ chunk->m_oldPtr = data;
+ chunk->m_length = int(size)*numElements;
+ chunk->m_number = numElements;
+
+ m_chunkPtrs.push_back(chunk);
+
+
+ return chunk;
+ }
+
+ virtual const char* findNameForPointer(const void* ptr) const
+ {
+ const char*const * namePtr = m_nameMap.find(ptr);
+ if (namePtr && *namePtr)
+ return *namePtr;
+ return 0;
+
+ }
+
+ virtual void registerNameForPointer(const void* ptr, const char* name)
+ {
+ m_nameMap.insert(ptr,name);
+ }
+
+ virtual void serializeName(const char* name)
+ {
+ if (name)
+ {
+ //don't serialize name twice
+ if (findPointer((void*)name))
+ return;
+
+ int len = btStrLen(name);
+ if (len)
+ {
+
+ int newLen = len+1;
+ int padding = ((newLen+3)&~3)-newLen;
+ newLen += padding;
+
+ //serialize name string now
+ btChunk* chunk = allocate(sizeof(char),newLen);
+ char* destinationName = (char*)chunk->m_oldPtr;
+ for (int i=0;i<len;i++)
+ {
+ destinationName[i] = name[i];
+ }
+ destinationName[len] = 0;
+ finalizeChunk(chunk,"char",BT_ARRAY_CODE,(void*)name);
+ }
+ }
+ }
+
+ virtual int getSerializationFlags() const
+ {
+ return m_serializationFlags;
+ }
+
+ virtual void setSerializationFlags(int flags)
+ {
+ m_serializationFlags = flags;
+ }
+ int getNumChunks() const
+ {
+ return m_chunkPtrs.size();
+ }
+
+ const btChunk* getChunk(int chunkIndex) const
+ {
+ return m_chunkPtrs[chunkIndex];
+ }
+};
+
+
+///In general it is best to use btDefaultSerializer,
+///in particular when writing the data to disk or sending it over the network.
+///The btInMemorySerializer is experimental and only suitable in a few cases.
+///The btInMemorySerializer takes a shortcut and can be useful to create a deep-copy
+///of objects. There will be a demo on how to use the btInMemorySerializer.
+#ifdef ENABLE_INMEMORY_SERIALIZER
+
+struct btInMemorySerializer : public btDefaultSerializer
+{
+ btHashMap<btHashPtr,btChunk*> m_uid2ChunkPtr;
+ btHashMap<btHashPtr,void*> m_orgPtr2UniqueDataPtr;
+ btHashMap<btHashString,const void*> m_names2Ptr;
+
+
+ btBulletSerializedArrays m_arrays;
+
+ btInMemorySerializer(int totalSize=0, unsigned char* buffer=0)
+ :btDefaultSerializer(totalSize,buffer)
+ {
+
+ }
+
+ virtual void startSerialization()
+ {
+ m_uid2ChunkPtr.clear();
+ //todo: m_arrays.clear();
+ btDefaultSerializer::startSerialization();
+ }
+
+
+
+ btChunk* findChunkFromUniquePointer(void* uniquePointer)
+ {
+ btChunk** chkPtr = m_uid2ChunkPtr[uniquePointer];
+ if (chkPtr)
+ {
+ return *chkPtr;
+ }
+ return 0;
+ }
+
+ virtual void registerNameForPointer(const void* ptr, const char* name)
+ {
+ btDefaultSerializer::registerNameForPointer(ptr,name);
+ m_names2Ptr.insert(name,ptr);
+ }
+
+ virtual void finishSerialization()
+ {
+ }
+
+ virtual void* getUniquePointer(void*oldPtr)
+ {
+ if (oldPtr==0)
+ return 0;
+
+ // void* uniquePtr = getUniquePointer(oldPtr);
+ btChunk* chunk = findChunkFromUniquePointer(oldPtr);
+ if (chunk)
+ {
+ return chunk->m_oldPtr;
+ } else
+ {
+ const char* n = (const char*) oldPtr;
+ const void** ptr = m_names2Ptr[n];
+ if (ptr)
+ {
+ return oldPtr;
+ } else
+ {
+ void** ptr2 = m_skipPointers[oldPtr];
+ if (ptr2)
+ {
+ return 0;
+ } else
+ {
+ //If this assert hit, serialization happened in the wrong order
+ // 'getUniquePointer'
+ btAssert(0);
+ }
+
+ }
+ return 0;
+ }
+ return oldPtr;
+ }
+
+ virtual void finalizeChunk(btChunk* chunk, const char* structType, int chunkCode,void* oldPtr)
+ {
+ if (!(m_serializationFlags&BT_SERIALIZE_NO_DUPLICATE_ASSERT))
+ {
+ btAssert(!findPointer(oldPtr));
+ }
+
+ chunk->m_dna_nr = getReverseType(structType);
+ chunk->m_chunkCode = chunkCode;
+ //void* uniquePtr = getUniquePointer(oldPtr);
+ m_chunkP.insert(oldPtr,oldPtr);//chunk->m_oldPtr);
+ // chunk->m_oldPtr = uniquePtr;//oldPtr;
+
+ void* uid = findPointer(oldPtr);
+ m_uid2ChunkPtr.insert(uid,chunk);
+
+ switch (chunk->m_chunkCode)
+ {
+ case BT_SOFTBODY_CODE:
+ {
+ #ifdef BT_USE_DOUBLE_PRECISION
+ m_arrays.m_softBodyDoubleData.push_back((btSoftBodyDoubleData*) chunk->m_oldPtr);
+ #else
+ m_arrays.m_softBodyFloatData.push_back((btSoftBodyFloatData*) chunk->m_oldPtr);
+ #endif
+ break;
+ }
+ case BT_COLLISIONOBJECT_CODE:
+ {
+ #ifdef BT_USE_DOUBLE_PRECISION
+ m_arrays.m_collisionObjectDataDouble.push_back((btCollisionObjectDoubleData*)chunk->m_oldPtr);
+ #else//BT_USE_DOUBLE_PRECISION
+ m_arrays.m_collisionObjectDataFloat.push_back((btCollisionObjectFloatData*)chunk->m_oldPtr);
+ #endif //BT_USE_DOUBLE_PRECISION
+ break;
+ }
+ case BT_RIGIDBODY_CODE:
+ {
+ #ifdef BT_USE_DOUBLE_PRECISION
+ m_arrays.m_rigidBodyDataDouble.push_back((btRigidBodyDoubleData*)chunk->m_oldPtr);
+ #else
+ m_arrays.m_rigidBodyDataFloat.push_back((btRigidBodyFloatData*)chunk->m_oldPtr);
+ #endif//BT_USE_DOUBLE_PRECISION
+ break;
+ };
+ case BT_CONSTRAINT_CODE:
+ {
+ #ifdef BT_USE_DOUBLE_PRECISION
+ m_arrays.m_constraintDataDouble.push_back((btTypedConstraintDoubleData*)chunk->m_oldPtr);
+ #else
+ m_arrays.m_constraintDataFloat.push_back((btTypedConstraintFloatData*)chunk->m_oldPtr);
+ #endif
+ break;
+ }
+ case BT_QUANTIZED_BVH_CODE:
+ {
+ #ifdef BT_USE_DOUBLE_PRECISION
+ m_arrays.m_bvhsDouble.push_back((btQuantizedBvhDoubleData*) chunk->m_oldPtr);
+ #else
+ m_arrays.m_bvhsFloat.push_back((btQuantizedBvhFloatData*) chunk->m_oldPtr);
+ #endif
+ break;
+ }
+
+ case BT_SHAPE_CODE:
+ {
+ btCollisionShapeData* shapeData = (btCollisionShapeData*) chunk->m_oldPtr;
+ m_arrays.m_colShapeData.push_back(shapeData);
+ break;
+ }
+ case BT_TRIANLGE_INFO_MAP:
+ case BT_ARRAY_CODE:
+ case BT_SBMATERIAL_CODE:
+ case BT_SBNODE_CODE:
+ case BT_DYNAMICSWORLD_CODE:
+ case BT_DNA_CODE:
+ {
+ break;
+ }
+ default:
+ {
+ }
+ };
+ }
+
+ int getNumChunks() const
+ {
+ return m_uid2ChunkPtr.size();
+ }
+
+ const btChunk* getChunk(int chunkIndex) const
+ {
+ return *m_uid2ChunkPtr.getAtIndex(chunkIndex);
+ }
+
+};
+#endif //ENABLE_INMEMORY_SERIALIZER
+
+#endif //BT_SERIALIZER_H
+
diff --git a/thirdparty/bullet/src/LinearMath/btSerializer64.cpp b/thirdparty/bullet/src/LinearMath/btSerializer64.cpp
new file mode 100644
index 0000000000..05f59202d7
--- /dev/null
+++ b/thirdparty/bullet/src/LinearMath/btSerializer64.cpp
@@ -0,0 +1,599 @@
+char sBulletDNAstr64[]= {
+char(83),char(68),char(78),char(65),char(78),char(65),char(77),char(69),char(-124),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),
+char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(115),char(0),char(42),char(102),char(105),char(114),char(115),char(116),char(0),char(42),char(108),char(97),char(115),
+char(116),char(0),char(109),char(95),char(102),char(108),char(111),char(97),char(116),char(115),char(91),char(52),char(93),char(0),char(109),char(95),char(101),char(108),char(91),char(51),
+char(93),char(0),char(109),char(95),char(98),char(97),char(115),char(105),char(115),char(0),char(109),char(95),char(111),char(114),char(105),char(103),char(105),char(110),char(0),char(109),
+char(95),char(114),char(111),char(111),char(116),char(78),char(111),char(100),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(115),char(117),char(98),
+char(116),char(114),char(101),char(101),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),
+char(65),char(97),char(98),char(98),char(77),char(105),char(110),char(91),char(51),char(93),char(0),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),char(122),
+char(101),char(100),char(65),char(97),char(98),char(98),char(77),char(97),char(120),char(91),char(51),char(93),char(0),char(109),char(95),char(97),char(97),char(98),char(98),char(77),
+char(105),char(110),char(79),char(114),char(103),char(0),char(109),char(95),char(97),char(97),char(98),char(98),char(77),char(97),char(120),char(79),char(114),char(103),char(0),char(109),
+char(95),char(101),char(115),char(99),char(97),char(112),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(115),char(117),char(98),char(80),char(97),
+char(114),char(116),char(0),char(109),char(95),char(116),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),
+char(95),char(112),char(97),char(100),char(91),char(52),char(93),char(0),char(109),char(95),char(101),char(115),char(99),char(97),char(112),char(101),char(73),char(110),char(100),char(101),
+char(120),char(79),char(114),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(98),
+char(118),char(104),char(65),char(97),char(98),char(98),char(77),char(105),char(110),char(0),char(109),char(95),char(98),char(118),char(104),char(65),char(97),char(98),char(98),char(77),
+char(97),char(120),char(0),char(109),char(95),char(98),char(118),char(104),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(97),char(116),char(105),char(111),char(110),
+char(0),char(109),char(95),char(99),char(117),char(114),char(78),char(111),char(100),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(117),char(115),
+char(101),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(97),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(110),char(117),char(109),char(67),
+char(111),char(110),char(116),char(105),char(103),char(117),char(111),char(117),char(115),char(76),char(101),char(97),char(102),char(78),char(111),char(100),char(101),char(115),char(0),char(109),
+char(95),char(110),char(117),char(109),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(67),char(111),char(110),char(116),char(105),char(103),char(117),
+char(111),char(117),char(115),char(78),char(111),char(100),char(101),char(115),char(0),char(42),char(109),char(95),char(99),char(111),char(110),char(116),char(105),char(103),char(117),char(111),
+char(117),char(115),char(78),char(111),char(100),char(101),char(115),char(80),char(116),char(114),char(0),char(42),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),
+char(122),char(101),char(100),char(67),char(111),char(110),char(116),char(105),char(103),char(117),char(111),char(117),char(115),char(78),char(111),char(100),char(101),char(115),char(80),char(116),
+char(114),char(0),char(42),char(109),char(95),char(115),char(117),char(98),char(84),char(114),char(101),char(101),char(73),char(110),char(102),char(111),char(80),char(116),char(114),char(0),
+char(109),char(95),char(116),char(114),char(97),char(118),char(101),char(114),char(115),char(97),char(108),char(77),char(111),char(100),char(101),char(0),char(109),char(95),char(110),char(117),
+char(109),char(83),char(117),char(98),char(116),char(114),char(101),char(101),char(72),char(101),char(97),char(100),char(101),char(114),char(115),char(0),char(42),char(109),char(95),char(110),
+char(97),char(109),char(101),char(0),char(109),char(95),char(115),char(104),char(97),char(112),char(101),char(84),char(121),char(112),char(101),char(0),char(109),char(95),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(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(68),char(97),char(116),char(97),char(0),char(109),char(95),char(108),char(111),char(99),char(97),char(108),char(83),char(99),char(97),
+char(108),char(105),char(110),char(103),char(0),char(109),char(95),char(112),char(108),char(97),char(110),char(101),char(78),char(111),char(114),char(109),char(97),char(108),char(0),char(109),
+char(95),char(112),char(108),char(97),char(110),char(101),char(67),char(111),char(110),char(115),char(116),char(97),char(110),char(116),char(0),char(109),char(95),char(105),char(109),char(112),
+char(108),char(105),char(99),char(105),char(116),char(83),char(104),char(97),char(112),char(101),char(68),char(105),char(109),char(101),char(110),char(115),char(105),char(111),char(110),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(77),char(97),char(114),char(103),char(105),char(110),char(0),char(109),
+char(95),char(112),char(97),char(100),char(100),char(105),char(110),char(103),char(0),char(109),char(95),char(112),char(111),char(115),char(0),char(109),char(95),char(114),char(97),char(100),
+char(105),char(117),char(115),char(0),char(109),char(95),char(99),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(42),char(109),char(95),char(108),char(111),char(99),char(97),char(108),char(80),char(111),
+char(115),char(105),char(116),char(105),char(111),char(110),char(65),char(114),char(114),char(97),char(121),char(80),char(116),char(114),char(0),char(109),char(95),char(108),char(111),char(99),
+char(97),char(108),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(65),char(114),char(114),char(97),char(121),char(83),char(105),char(122),char(101),char(0),
+char(109),char(95),char(118),char(97),char(108),char(117),char(101),char(0),char(109),char(95),char(112),char(97),char(100),char(91),char(50),char(93),char(0),char(109),char(95),char(118),
+char(97),char(108),char(117),char(101),char(115),char(91),char(51),char(93),char(0),char(109),char(95),char(112),char(97),char(100),char(0),char(42),char(109),char(95),char(118),char(101),
+char(114),char(116),char(105),char(99),char(101),char(115),char(51),char(102),char(0),char(42),char(109),char(95),char(118),char(101),char(114),char(116),char(105),char(99),char(101),char(115),
+char(51),char(100),char(0),char(42),char(109),char(95),char(105),char(110),char(100),char(105),char(99),char(101),char(115),char(51),char(50),char(0),char(42),char(109),char(95),char(51),
+char(105),char(110),char(100),char(105),char(99),char(101),char(115),char(49),char(54),char(0),char(42),char(109),char(95),char(51),char(105),char(110),char(100),char(105),char(99),char(101),
+char(115),char(56),char(0),char(42),char(109),char(95),char(105),char(110),char(100),char(105),char(99),char(101),char(115),char(49),char(54),char(0),char(109),char(95),char(110),char(117),
+char(109),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(86),char(101),char(114),char(116),
+char(105),char(99),char(101),char(115),char(0),char(42),char(109),char(95),char(109),char(101),char(115),char(104),char(80),char(97),char(114),char(116),char(115),char(80),char(116),char(114),
+char(0),char(109),char(95),char(115),char(99),char(97),char(108),char(105),char(110),char(103),char(0),char(109),char(95),char(110),char(117),char(109),char(77),char(101),char(115),char(104),
+char(80),char(97),char(114),char(116),char(115),char(0),char(109),char(95),char(109),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(0),char(42),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(70),char(108),char(111),char(97),char(116),char(66),
+char(118),char(104),char(0),char(42),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(68),char(111),char(117),char(98),char(108),
+char(101),char(66),char(118),char(104),char(0),char(42),char(109),char(95),char(116),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(0),char(109),char(95),char(112),char(97),char(100),char(51),char(91),char(52),char(93),char(0),char(109),char(95),char(116),char(114),char(105),char(109),
+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(109),char(95),char(116),char(114),char(97),char(110),char(115),
+char(102),char(111),char(114),char(109),char(0),char(42),char(109),char(95),char(99),char(104),char(105),char(108),char(100),char(83),char(104),char(97),char(112),char(101),char(0),char(109),
+char(95),char(99),char(104),char(105),char(108),char(100),char(83),char(104),char(97),char(112),char(101),char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(99),char(104),
+char(105),char(108),char(100),char(77),char(97),char(114),char(103),char(105),char(110),char(0),char(42),char(109),char(95),char(99),char(104),char(105),char(108),char(100),char(83),char(104),
+char(97),char(112),char(101),char(80),char(116),char(114),char(0),char(109),char(95),char(110),char(117),char(109),char(67),char(104),char(105),char(108),char(100),char(83),char(104),char(97),
+char(112),char(101),char(115),char(0),char(109),char(95),char(117),char(112),char(65),char(120),char(105),char(115),char(0),char(109),char(95),char(117),char(112),char(73),char(110),char(100),
+char(101),char(120),char(0),char(109),char(95),char(102),char(108),char(97),char(103),char(115),char(0),char(109),char(95),char(101),char(100),char(103),char(101),char(86),char(48),char(86),
+char(49),char(65),char(110),char(103),char(108),char(101),char(0),char(109),char(95),char(101),char(100),char(103),char(101),char(86),char(49),char(86),char(50),char(65),char(110),char(103),
+char(108),char(101),char(0),char(109),char(95),char(101),char(100),char(103),char(101),char(86),char(50),char(86),char(48),char(65),char(110),char(103),char(108),char(101),char(0),char(42),
+char(109),char(95),char(104),char(97),char(115),char(104),char(84),char(97),char(98),char(108),char(101),char(80),char(116),char(114),char(0),char(42),char(109),char(95),char(110),char(101),
+char(120),char(116),char(80),char(116),char(114),char(0),char(42),char(109),char(95),char(118),char(97),char(108),char(117),char(101),char(65),char(114),char(114),char(97),char(121),char(80),
+char(116),char(114),char(0),char(42),char(109),char(95),char(107),char(101),char(121),char(65),char(114),char(114),char(97),char(121),char(80),char(116),char(114),char(0),char(109),char(95),
+char(99),char(111),char(110),char(118),char(101),char(120),char(69),char(112),char(115),char(105),char(108),char(111),char(110),char(0),char(109),char(95),char(112),char(108),char(97),char(110),
+char(97),char(114),char(69),char(112),char(115),char(105),char(108),char(111),char(110),char(0),char(109),char(95),char(101),char(113),char(117),char(97),char(108),char(86),char(101),char(114),
+char(116),char(101),char(120),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(101),char(100),char(103),char(101),char(68),
+char(105),char(115),char(116),char(97),char(110),char(99),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(122),
+char(101),char(114),char(111),char(65),char(114),char(101),char(97),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(101),char(120),char(116),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(104),char(97),char(115),char(104),char(84),char(97),char(98),char(108),char(101),char(83),
+char(105),char(122),char(101),char(0),char(109),char(95),char(110),char(117),char(109),char(86),char(97),char(108),char(117),char(101),char(115),char(0),char(109),char(95),char(110),char(117),
+char(109),char(75),char(101),char(121),char(115),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(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(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(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(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(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(67),char(111),char(109),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(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(84),char(114),char(97),
+char(110),char(115),char(102),char(111),char(114),char(109),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(84),char(89),char(80),char(69),char(95),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(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(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(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(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(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(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(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(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(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(72),char(0),char(80),char(0),char(-16),char(1),char(24),char(1),char(-104),char(0),char(88),char(0),char(-72),char(0),
+char(104),char(0),char(0),char(2),char(-64),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(-24),char(1),char(0),char(3),char(-104),char(1),char(-48),char(0),
+char(112),char(0),char(0),char(0),char(83),char(84),char(82),char(67),char(84),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(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(96),char(0),char(48),char(0),char(5),char(0),
+char(29),char(0),char(47),char(0),char(13),char(0),char(97),char(0),char(14),char(0),char(98),char(0),char(4),char(0),char(99),char(0),char(0),char(0),char(100),char(0),
+char(49),char(0),char(27),char(0),char(9),char(0),char(101),char(0),char(9),char(0),char(102),char(0),char(27),char(0),char(103),char(0),char(0),char(0),char(35),char(0),
+char(20),char(0),char(104),char(0),char(20),char(0),char(105),char(0),char(14),char(0),char(106),char(0),char(14),char(0),char(107),char(0),char(14),char(0),char(108),char(0),
+char(8),char(0),char(109),char(0),char(8),char(0),char(110),char(0),char(8),char(0),char(111),char(0),char(8),char(0),char(112),char(0),char(8),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(4),char(0),char(119),char(0),char(4),char(0),char(120),char(0),char(4),char(0),char(121),char(0),char(4),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(0),char(0),char(37),char(0),char(50),char(0),char(27),char(0),char(9),char(0),char(101),char(0),
+char(9),char(0),char(102),char(0),char(27),char(0),char(103),char(0),char(0),char(0),char(35),char(0),char(19),char(0),char(104),char(0),char(19),char(0),char(105),char(0),
+char(13),char(0),char(106),char(0),char(13),char(0),char(107),char(0),char(13),char(0),char(108),char(0),char(7),char(0),char(109),char(0),char(7),char(0),char(110),char(0),
+char(7),char(0),char(111),char(0),char(7),char(0),char(112),char(0),char(7),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(4),char(0),char(119),char(0),char(4),char(0),char(120),char(0),
+char(4),char(0),char(121),char(0),char(4),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(0),char(0),char(37),char(0),char(51),char(0),char(22),char(0),char(8),char(0),char(126),char(0),char(8),char(0),char(127),char(0),char(8),char(0),char(111),char(0),
+char(8),char(0),char(-128),char(0),char(8),char(0),char(115),char(0),char(8),char(0),char(-127),char(0),char(8),char(0),char(-126),char(0),char(8),char(0),char(-125),char(0),
+char(8),char(0),char(-124),char(0),char(8),char(0),char(-123),char(0),char(8),char(0),char(-122),char(0),char(8),char(0),char(-121),char(0),char(8),char(0),char(-120),char(0),
+char(8),char(0),char(-119),char(0),char(8),char(0),char(-118),char(0),char(8),char(0),char(-117),char(0),char(4),char(0),char(-116),char(0),char(4),char(0),char(-115),char(0),
+char(4),char(0),char(-114),char(0),char(4),char(0),char(-113),char(0),char(4),char(0),char(-112),char(0),char(0),char(0),char(37),char(0),char(52),char(0),char(22),char(0),
+char(7),char(0),char(126),char(0),char(7),char(0),char(127),char(0),char(7),char(0),char(111),char(0),char(7),char(0),char(-128),char(0),char(7),char(0),char(115),char(0),
+char(7),char(0),char(-127),char(0),char(7),char(0),char(-126),char(0),char(7),char(0),char(-125),char(0),char(7),char(0),char(-124),char(0),char(7),char(0),char(-123),char(0),
+char(7),char(0),char(-122),char(0),char(7),char(0),char(-121),char(0),char(7),char(0),char(-120),char(0),char(7),char(0),char(-119),char(0),char(7),char(0),char(-118),char(0),
+char(7),char(0),char(-117),char(0),char(4),char(0),char(-116),char(0),char(4),char(0),char(-115),char(0),char(4),char(0),char(-114),char(0),char(4),char(0),char(-113),char(0),
+char(4),char(0),char(-112),char(0),char(0),char(0),char(37),char(0),char(53),char(0),char(2),char(0),char(51),char(0),char(-111),char(0),char(14),char(0),char(-110),char(0),
+char(54),char(0),char(2),char(0),char(52),char(0),char(-111),char(0),char(13),char(0),char(-110),char(0),char(55),char(0),char(21),char(0),char(50),char(0),char(-109),char(0),
+char(17),char(0),char(-108),char(0),char(13),char(0),char(-107),char(0),char(13),char(0),char(-106),char(0),char(13),char(0),char(-105),char(0),char(13),char(0),char(-104),char(0),
+char(13),char(0),char(-110),char(0),char(13),char(0),char(-103),char(0),char(13),char(0),char(-102),char(0),char(13),char(0),char(-101),char(0),char(13),char(0),char(-100),char(0),
+char(7),char(0),char(-99),char(0),char(7),char(0),char(-98),char(0),char(7),char(0),char(-97),char(0),char(7),char(0),char(-96),char(0),char(7),char(0),char(-95),char(0),
+char(7),char(0),char(-94),char(0),char(7),char(0),char(-93),char(0),char(7),char(0),char(-92),char(0),char(7),char(0),char(-91),char(0),char(4),char(0),char(-90),char(0),
+char(56),char(0),char(22),char(0),char(49),char(0),char(-109),char(0),char(18),char(0),char(-108),char(0),char(14),char(0),char(-107),char(0),char(14),char(0),char(-106),char(0),
+char(14),char(0),char(-105),char(0),char(14),char(0),char(-104),char(0),char(14),char(0),char(-110),char(0),char(14),char(0),char(-103),char(0),char(14),char(0),char(-102),char(0),
+char(14),char(0),char(-101),char(0),char(14),char(0),char(-100),char(0),char(8),char(0),char(-99),char(0),char(8),char(0),char(-98),char(0),char(8),char(0),char(-97),char(0),
+char(8),char(0),char(-96),char(0),char(8),char(0),char(-95),char(0),char(8),char(0),char(-94),char(0),char(8),char(0),char(-93),char(0),char(8),char(0),char(-92),char(0),
+char(8),char(0),char(-91),char(0),char(4),char(0),char(-90),char(0),char(0),char(0),char(37),char(0),char(57),char(0),char(2),char(0),char(4),char(0),char(-89),char(0),
+char(4),char(0),char(-88),char(0),char(58),char(0),char(13),char(0),char(55),char(0),char(-87),char(0),char(55),char(0),char(-86),char(0),char(0),char(0),char(35),char(0),
+char(4),char(0),char(-85),char(0),char(4),char(0),char(-84),char(0),char(4),char(0),char(-83),char(0),char(4),char(0),char(-82),char(0),char(7),char(0),char(-81),char(0),
+char(7),char(0),char(-80),char(0),char(4),char(0),char(-79),char(0),char(4),char(0),char(-78),char(0),char(7),char(0),char(-77),char(0),char(4),char(0),char(-76),char(0),
+char(59),char(0),char(13),char(0),char(60),char(0),char(-87),char(0),char(60),char(0),char(-86),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(-85),char(0),
+char(4),char(0),char(-84),char(0),char(4),char(0),char(-83),char(0),char(4),char(0),char(-82),char(0),char(7),char(0),char(-81),char(0),char(7),char(0),char(-80),char(0),
+char(4),char(0),char(-79),char(0),char(4),char(0),char(-78),char(0),char(7),char(0),char(-77),char(0),char(4),char(0),char(-76),char(0),char(61),char(0),char(14),char(0),
+char(56),char(0),char(-87),char(0),char(56),char(0),char(-86),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(-85),char(0),char(4),char(0),char(-84),char(0),
+char(4),char(0),char(-83),char(0),char(4),char(0),char(-82),char(0),char(8),char(0),char(-81),char(0),char(8),char(0),char(-80),char(0),char(4),char(0),char(-79),char(0),
+char(4),char(0),char(-78),char(0),char(8),char(0),char(-77),char(0),char(4),char(0),char(-76),char(0),char(0),char(0),char(-75),char(0),char(62),char(0),char(3),char(0),
+char(59),char(0),char(-74),char(0),char(13),char(0),char(-73),char(0),char(13),char(0),char(-72),char(0),char(63),char(0),char(3),char(0),char(61),char(0),char(-74),char(0),
+char(14),char(0),char(-73),char(0),char(14),char(0),char(-72),char(0),char(64),char(0),char(3),char(0),char(59),char(0),char(-74),char(0),char(14),char(0),char(-73),char(0),
+char(14),char(0),char(-72),char(0),char(65),char(0),char(13),char(0),char(59),char(0),char(-74),char(0),char(20),char(0),char(-71),char(0),char(20),char(0),char(-70),char(0),
+char(4),char(0),char(-69),char(0),char(4),char(0),char(-68),char(0),char(4),char(0),char(-67),char(0),char(7),char(0),char(-66),char(0),char(7),char(0),char(-65),char(0),
+char(7),char(0),char(-64),char(0),char(7),char(0),char(-63),char(0),char(7),char(0),char(-62),char(0),char(7),char(0),char(-61),char(0),char(7),char(0),char(-60),char(0),
+char(66),char(0),char(13),char(0),char(59),char(0),char(-74),char(0),char(19),char(0),char(-71),char(0),char(19),char(0),char(-70),char(0),char(4),char(0),char(-69),char(0),
+char(4),char(0),char(-68),char(0),char(4),char(0),char(-67),char(0),char(7),char(0),char(-66),char(0),char(7),char(0),char(-65),char(0),char(7),char(0),char(-64),char(0),
+char(7),char(0),char(-63),char(0),char(7),char(0),char(-62),char(0),char(7),char(0),char(-61),char(0),char(7),char(0),char(-60),char(0),char(67),char(0),char(14),char(0),
+char(61),char(0),char(-74),char(0),char(20),char(0),char(-71),char(0),char(20),char(0),char(-70),char(0),char(4),char(0),char(-69),char(0),char(4),char(0),char(-68),char(0),
+char(4),char(0),char(-67),char(0),char(8),char(0),char(-66),char(0),char(8),char(0),char(-65),char(0),char(8),char(0),char(-64),char(0),char(8),char(0),char(-63),char(0),
+char(8),char(0),char(-62),char(0),char(8),char(0),char(-61),char(0),char(8),char(0),char(-60),char(0),char(0),char(0),char(-59),char(0),char(68),char(0),char(10),char(0),
+char(61),char(0),char(-74),char(0),char(20),char(0),char(-71),char(0),char(20),char(0),char(-70),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(-62),char(0),char(8),char(0),char(-61),char(0),char(8),char(0),char(-60),char(0),char(8),char(0),char(127),char(0),
+char(69),char(0),char(11),char(0),char(59),char(0),char(-74),char(0),char(19),char(0),char(-71),char(0),char(19),char(0),char(-70),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(-62),char(0),char(7),char(0),char(-61),char(0),char(7),char(0),char(-60),char(0),
+char(7),char(0),char(127),char(0),char(0),char(0),char(21),char(0),char(70),char(0),char(9),char(0),char(59),char(0),char(-74),char(0),char(19),char(0),char(-71),char(0),
+char(19),char(0),char(-70),char(0),char(13),char(0),char(-55),char(0),char(13),char(0),char(-54),char(0),char(13),char(0),char(-53),char(0),char(13),char(0),char(-52),char(0),
+char(4),char(0),char(-51),char(0),char(4),char(0),char(-50),char(0),char(71),char(0),char(9),char(0),char(61),char(0),char(-74),char(0),char(20),char(0),char(-71),char(0),
+char(20),char(0),char(-70),char(0),char(14),char(0),char(-55),char(0),char(14),char(0),char(-54),char(0),char(14),char(0),char(-53),char(0),char(14),char(0),char(-52),char(0),
+char(4),char(0),char(-51),char(0),char(4),char(0),char(-50),char(0),char(72),char(0),char(5),char(0),char(70),char(0),char(-49),char(0),char(4),char(0),char(-48),char(0),
+char(7),char(0),char(-47),char(0),char(7),char(0),char(-46),char(0),char(7),char(0),char(-45),char(0),char(73),char(0),char(5),char(0),char(71),char(0),char(-49),char(0),
+char(4),char(0),char(-48),char(0),char(8),char(0),char(-47),char(0),char(8),char(0),char(-46),char(0),char(8),char(0),char(-45),char(0),char(74),char(0),char(41),char(0),
+char(59),char(0),char(-74),char(0),char(19),char(0),char(-71),char(0),char(19),char(0),char(-70),char(0),char(13),char(0),char(-55),char(0),char(13),char(0),char(-54),char(0),
+char(13),char(0),char(-44),char(0),char(13),char(0),char(-43),char(0),char(13),char(0),char(-42),char(0),char(13),char(0),char(-41),char(0),char(13),char(0),char(-40),char(0),
+char(13),char(0),char(-39),char(0),char(13),char(0),char(-38),char(0),char(13),char(0),char(-37),char(0),char(13),char(0),char(-36),char(0),char(13),char(0),char(-35),char(0),
+char(13),char(0),char(-34),char(0),char(0),char(0),char(-33),char(0),char(0),char(0),char(-32),char(0),char(0),char(0),char(-31),char(0),char(0),char(0),char(-30),char(0),
+char(0),char(0),char(-29),char(0),char(0),char(0),char(-59),char(0),char(13),char(0),char(-53),char(0),char(13),char(0),char(-52),char(0),char(13),char(0),char(-28),char(0),
+char(13),char(0),char(-27),char(0),char(13),char(0),char(-26),char(0),char(13),char(0),char(-25),char(0),char(13),char(0),char(-24),char(0),char(13),char(0),char(-23),char(0),
+char(13),char(0),char(-22),char(0),char(13),char(0),char(-21),char(0),char(13),char(0),char(-20),char(0),char(13),char(0),char(-19),char(0),char(13),char(0),char(-18),char(0),
+char(0),char(0),char(-17),char(0),char(0),char(0),char(-16),char(0),char(0),char(0),char(-15),char(0),char(0),char(0),char(-14),char(0),char(0),char(0),char(-13),char(0),
+char(4),char(0),char(-12),char(0),char(75),char(0),char(41),char(0),char(61),char(0),char(-74),char(0),char(20),char(0),char(-71),char(0),char(20),char(0),char(-70),char(0),
+char(14),char(0),char(-55),char(0),char(14),char(0),char(-54),char(0),char(14),char(0),char(-44),char(0),char(14),char(0),char(-43),char(0),char(14),char(0),char(-42),char(0),
+char(14),char(0),char(-41),char(0),char(14),char(0),char(-40),char(0),char(14),char(0),char(-39),char(0),char(14),char(0),char(-38),char(0),char(14),char(0),char(-37),char(0),
+char(14),char(0),char(-36),char(0),char(14),char(0),char(-35),char(0),char(14),char(0),char(-34),char(0),char(0),char(0),char(-33),char(0),char(0),char(0),char(-32),char(0),
+char(0),char(0),char(-31),char(0),char(0),char(0),char(-30),char(0),char(0),char(0),char(-29),char(0),char(0),char(0),char(-59),char(0),char(14),char(0),char(-53),char(0),
+char(14),char(0),char(-52),char(0),char(14),char(0),char(-28),char(0),char(14),char(0),char(-27),char(0),char(14),char(0),char(-26),char(0),char(14),char(0),char(-25),char(0),
+char(14),char(0),char(-24),char(0),char(14),char(0),char(-23),char(0),char(14),char(0),char(-22),char(0),char(14),char(0),char(-21),char(0),char(14),char(0),char(-20),char(0),
+char(14),char(0),char(-19),char(0),char(14),char(0),char(-18),char(0),char(0),char(0),char(-17),char(0),char(0),char(0),char(-16),char(0),char(0),char(0),char(-15),char(0),
+char(0),char(0),char(-14),char(0),char(0),char(0),char(-13),char(0),char(4),char(0),char(-12),char(0),char(76),char(0),char(9),char(0),char(59),char(0),char(-74),char(0),
+char(19),char(0),char(-71),char(0),char(19),char(0),char(-70),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(4),char(0),char(-50),char(0),char(77),char(0),char(9),char(0),char(61),char(0),char(-74),char(0),
+char(20),char(0),char(-71),char(0),char(20),char(0),char(-70),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(4),char(0),char(-50),char(0),char(78),char(0),char(5),char(0),char(58),char(0),char(-74),char(0),
+char(13),char(0),char(-11),char(0),char(13),char(0),char(-10),char(0),char(7),char(0),char(-9),char(0),char(0),char(0),char(37),char(0),char(79),char(0),char(4),char(0),
+char(61),char(0),char(-74),char(0),char(14),char(0),char(-11),char(0),char(14),char(0),char(-10),char(0),char(8),char(0),char(-9),char(0),char(80),char(0),char(4),char(0),
+char(7),char(0),char(-8),char(0),char(7),char(0),char(-7),char(0),char(7),char(0),char(-6),char(0),char(4),char(0),char(79),char(0),char(81),char(0),char(10),char(0),
+char(80),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(7),char(0),char(-99),char(0),char(7),char(0),char(1),char(1),char(4),char(0),char(2),char(1),char(4),char(0),char(53),char(0),
+char(82),char(0),char(4),char(0),char(80),char(0),char(-5),char(0),char(4),char(0),char(3),char(1),char(7),char(0),char(4),char(1),char(4),char(0),char(5),char(1),
+char(83),char(0),char(4),char(0),char(13),char(0),char(0),char(1),char(80),char(0),char(-5),char(0),char(4),char(0),char(6),char(1),char(7),char(0),char(7),char(1),
+char(84),char(0),char(7),char(0),char(13),char(0),char(8),char(1),char(80),char(0),char(-5),char(0),char(4),char(0),char(9),char(1),char(7),char(0),char(10),char(1),
+char(7),char(0),char(11),char(1),char(7),char(0),char(12),char(1),char(4),char(0),char(53),char(0),char(85),char(0),char(6),char(0),char(17),char(0),char(13),char(1),
+char(13),char(0),char(11),char(1),char(13),char(0),char(14),char(1),char(60),char(0),char(15),char(1),char(4),char(0),char(16),char(1),char(7),char(0),char(12),char(1),
+char(86),char(0),char(26),char(0),char(4),char(0),char(17),char(1),char(7),char(0),char(18),char(1),char(7),char(0),char(127),char(0),char(7),char(0),char(19),char(1),
+char(7),char(0),char(20),char(1),char(7),char(0),char(21),char(1),char(7),char(0),char(22),char(1),char(7),char(0),char(23),char(1),char(7),char(0),char(24),char(1),
+char(7),char(0),char(25),char(1),char(7),char(0),char(26),char(1),char(7),char(0),char(27),char(1),char(7),char(0),char(28),char(1),char(7),char(0),char(29),char(1),
+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(7),char(0),char(33),char(1),char(7),char(0),char(34),char(1),
+char(7),char(0),char(35),char(1),char(7),char(0),char(36),char(1),char(4),char(0),char(37),char(1),char(4),char(0),char(38),char(1),char(4),char(0),char(39),char(1),
+char(4),char(0),char(40),char(1),char(4),char(0),char(120),char(0),char(87),char(0),char(12),char(0),char(17),char(0),char(41),char(1),char(17),char(0),char(42),char(1),
+char(17),char(0),char(43),char(1),char(13),char(0),char(44),char(1),char(13),char(0),char(45),char(1),char(7),char(0),char(46),char(1),char(4),char(0),char(47),char(1),
+char(4),char(0),char(48),char(1),char(4),char(0),char(49),char(1),char(4),char(0),char(50),char(1),char(7),char(0),char(10),char(1),char(4),char(0),char(53),char(0),
+char(88),char(0),char(27),char(0),char(19),char(0),char(51),char(1),char(17),char(0),char(52),char(1),char(17),char(0),char(53),char(1),char(13),char(0),char(44),char(1),
+char(13),char(0),char(54),char(1),char(13),char(0),char(55),char(1),char(13),char(0),char(56),char(1),char(13),char(0),char(57),char(1),char(13),char(0),char(58),char(1),
+char(4),char(0),char(59),char(1),char(7),char(0),char(60),char(1),char(4),char(0),char(61),char(1),char(4),char(0),char(62),char(1),char(4),char(0),char(63),char(1),
+char(7),char(0),char(64),char(1),char(7),char(0),char(65),char(1),char(4),char(0),char(66),char(1),char(4),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(4),char(0),char(74),char(1),char(4),char(0),char(75),char(1),char(4),char(0),char(76),char(1),char(89),char(0),char(12),char(0),char(9),char(0),char(77),char(1),
+char(9),char(0),char(78),char(1),char(13),char(0),char(79),char(1),char(7),char(0),char(80),char(1),char(7),char(0),char(-125),char(0),char(7),char(0),char(81),char(1),
+char(4),char(0),char(82),char(1),char(13),char(0),char(83),char(1),char(4),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(53),char(0),char(90),char(0),char(19),char(0),char(50),char(0),char(-109),char(0),char(87),char(0),char(87),char(1),char(80),char(0),char(88),char(1),
+char(81),char(0),char(89),char(1),char(82),char(0),char(90),char(1),char(83),char(0),char(91),char(1),char(84),char(0),char(92),char(1),char(85),char(0),char(93),char(1),
+char(88),char(0),char(94),char(1),char(89),char(0),char(95),char(1),char(4),char(0),char(96),char(1),char(4),char(0),char(62),char(1),char(4),char(0),char(97),char(1),
+char(4),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(4),char(0),char(102),char(1),
+char(86),char(0),char(103),char(1),char(91),char(0),char(24),char(0),char(16),char(0),char(104),char(1),char(14),char(0),char(105),char(1),char(14),char(0),char(106),char(1),
+char(14),char(0),char(107),char(1),char(14),char(0),char(108),char(1),char(14),char(0),char(109),char(1),char(8),char(0),char(110),char(1),char(4),char(0),char(111),char(1),
+char(4),char(0),char(86),char(1),char(4),char(0),char(112),char(1),char(4),char(0),char(113),char(1),char(8),char(0),char(114),char(1),char(8),char(0),char(115),char(1),
+char(8),char(0),char(116),char(1),char(8),char(0),char(117),char(1),char(8),char(0),char(118),char(1),char(8),char(0),char(119),char(1),char(8),char(0),char(120),char(1),
+char(8),char(0),char(121),char(1),char(8),char(0),char(122),char(1),char(0),char(0),char(123),char(1),char(0),char(0),char(124),char(1),char(49),char(0),char(125),char(1),
+char(0),char(0),char(126),char(1),char(92),char(0),char(24),char(0),char(15),char(0),char(104),char(1),char(13),char(0),char(105),char(1),char(13),char(0),char(106),char(1),
+char(13),char(0),char(107),char(1),char(13),char(0),char(108),char(1),char(13),char(0),char(109),char(1),char(4),char(0),char(112),char(1),char(7),char(0),char(110),char(1),
+char(4),char(0),char(111),char(1),char(4),char(0),char(86),char(1),char(7),char(0),char(114),char(1),char(7),char(0),char(115),char(1),char(7),char(0),char(116),char(1),
+char(4),char(0),char(113),char(1),char(7),char(0),char(117),char(1),char(7),char(0),char(118),char(1),char(7),char(0),char(119),char(1),char(7),char(0),char(120),char(1),
+char(7),char(0),char(121),char(1),char(7),char(0),char(122),char(1),char(0),char(0),char(123),char(1),char(0),char(0),char(124),char(1),char(50),char(0),char(125),char(1),
+char(0),char(0),char(126),char(1),char(93),char(0),char(9),char(0),char(20),char(0),char(127),char(1),char(14),char(0),char(-128),char(1),char(8),char(0),char(-127),char(1),
+char(0),char(0),char(-126),char(1),char(91),char(0),char(90),char(1),char(49),char(0),char(-125),char(1),char(0),char(0),char(126),char(1),char(4),char(0),char(97),char(1),
+char(0),char(0),char(37),char(0),char(94),char(0),char(7),char(0),char(0),char(0),char(-126),char(1),char(92),char(0),char(90),char(1),char(50),char(0),char(-125),char(1),
+char(19),char(0),char(127),char(1),char(13),char(0),char(-128),char(1),char(7),char(0),char(-127),char(1),char(4),char(0),char(97),char(1),};
+int sBulletDNAlen64= sizeof(sBulletDNAstr64);
diff --git a/thirdparty/bullet/src/LinearMath/btSpatialAlgebra.h b/thirdparty/bullet/src/LinearMath/btSpatialAlgebra.h
new file mode 100644
index 0000000000..8e59658bca
--- /dev/null
+++ b/thirdparty/bullet/src/LinearMath/btSpatialAlgebra.h
@@ -0,0 +1,331 @@
+/*
+Copyright (c) 2003-2015 Erwin Coumans, Jakub Stepien
+
+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.
+*/
+
+///These spatial algebra classes are used for btMultiBody,
+///see BulletDynamics/Featherstone
+
+#ifndef BT_SPATIAL_ALGEBRA_H
+#define BT_SPATIAL_ALGEBRA_H
+
+
+#include "btMatrix3x3.h"
+
+struct btSpatialForceVector
+{
+ btVector3 m_topVec, m_bottomVec;
+ //
+ btSpatialForceVector() { setZero(); }
+ btSpatialForceVector(const btVector3 &angular, const btVector3 &linear) : m_topVec(linear), m_bottomVec(angular) {}
+ btSpatialForceVector(const btScalar &ax, const btScalar &ay, const btScalar &az, const btScalar &lx, const btScalar &ly, const btScalar &lz)
+ {
+ setValue(ax, ay, az, lx, ly, lz);
+ }
+ //
+ void setVector(const btVector3 &angular, const btVector3 &linear) { m_topVec = linear; m_bottomVec = angular; }
+ void setValue(const btScalar &ax, const btScalar &ay, const btScalar &az, const btScalar &lx, const btScalar &ly, const btScalar &lz)
+ {
+ m_bottomVec.setValue(ax, ay, az); m_topVec.setValue(lx, ly, lz);
+ }
+ //
+ void addVector(const btVector3 &angular, const btVector3 &linear) { m_topVec += linear; m_bottomVec += angular; }
+ void addValue(const btScalar &ax, const btScalar &ay, const btScalar &az, const btScalar &lx, const btScalar &ly, const btScalar &lz)
+ {
+ m_bottomVec[0] += ax; m_bottomVec[1] += ay; m_bottomVec[2] += az;
+ m_topVec[0] += lx; m_topVec[1] += ly; m_topVec[2] += lz;
+ }
+ //
+ const btVector3 & getLinear() const { return m_topVec; }
+ const btVector3 & getAngular() const { return m_bottomVec; }
+ //
+ void setLinear(const btVector3 &linear) { m_topVec = linear; }
+ void setAngular(const btVector3 &angular) { m_bottomVec = angular; }
+ //
+ void addAngular(const btVector3 &angular) { m_bottomVec += angular; }
+ void addLinear(const btVector3 &linear) { m_topVec += linear; }
+ //
+ void setZero() { m_topVec.setZero(); m_bottomVec.setZero(); }
+ //
+ btSpatialForceVector & operator += (const btSpatialForceVector &vec) { m_topVec += vec.m_topVec; m_bottomVec += vec.m_bottomVec; return *this; }
+ btSpatialForceVector & operator -= (const btSpatialForceVector &vec) { m_topVec -= vec.m_topVec; m_bottomVec -= vec.m_bottomVec; return *this; }
+ btSpatialForceVector operator - (const btSpatialForceVector &vec) const { return btSpatialForceVector(m_bottomVec - vec.m_bottomVec, m_topVec - vec.m_topVec); }
+ btSpatialForceVector operator + (const btSpatialForceVector &vec) const { return btSpatialForceVector(m_bottomVec + vec.m_bottomVec, m_topVec + vec.m_topVec); }
+ btSpatialForceVector operator - () const { return btSpatialForceVector(-m_bottomVec, -m_topVec); }
+ btSpatialForceVector operator * (const btScalar &s) const { return btSpatialForceVector(s * m_bottomVec, s * m_topVec); }
+ //btSpatialForceVector & operator = (const btSpatialForceVector &vec) { m_topVec = vec.m_topVec; m_bottomVec = vec.m_bottomVec; return *this; }
+};
+
+struct btSpatialMotionVector
+{
+ btVector3 m_topVec, m_bottomVec;
+ //
+ btSpatialMotionVector() { setZero(); }
+ btSpatialMotionVector(const btVector3 &angular, const btVector3 &linear) : m_topVec(angular), m_bottomVec(linear) {}
+ //
+ void setVector(const btVector3 &angular, const btVector3 &linear) { m_topVec = angular; m_bottomVec = linear; }
+ void setValue(const btScalar &ax, const btScalar &ay, const btScalar &az, const btScalar &lx, const btScalar &ly, const btScalar &lz)
+ {
+ m_topVec.setValue(ax, ay, az); m_bottomVec.setValue(lx, ly, lz);
+ }
+ //
+ void addVector(const btVector3 &angular, const btVector3 &linear) { m_topVec += linear; m_bottomVec += angular; }
+ void addValue(const btScalar &ax, const btScalar &ay, const btScalar &az, const btScalar &lx, const btScalar &ly, const btScalar &lz)
+ {
+ m_topVec[0] += ax; m_topVec[1] += ay; m_topVec[2] += az;
+ m_bottomVec[0] += lx; m_bottomVec[1] += ly; m_bottomVec[2] += lz;
+ }
+ //
+ const btVector3 & getAngular() const { return m_topVec; }
+ const btVector3 & getLinear() const { return m_bottomVec; }
+ //
+ void setAngular(const btVector3 &angular) { m_topVec = angular; }
+ void setLinear(const btVector3 &linear) { m_bottomVec = linear; }
+ //
+ void addAngular(const btVector3 &angular) { m_topVec += angular; }
+ void addLinear(const btVector3 &linear) { m_bottomVec += linear; }
+ //
+ void setZero() { m_topVec.setZero(); m_bottomVec.setZero(); }
+ //
+ btScalar dot(const btSpatialForceVector &b) const
+ {
+ return m_bottomVec.dot(b.m_topVec) + m_topVec.dot(b.m_bottomVec);
+ }
+ //
+ template<typename SpatialVectorType>
+ void cross(const SpatialVectorType &b, SpatialVectorType &out) const
+ {
+ out.m_topVec = m_topVec.cross(b.m_topVec);
+ out.m_bottomVec = m_bottomVec.cross(b.m_topVec) + m_topVec.cross(b.m_bottomVec);
+ }
+ template<typename SpatialVectorType>
+ SpatialVectorType cross(const SpatialVectorType &b) const
+ {
+ SpatialVectorType out;
+ out.m_topVec = m_topVec.cross(b.m_topVec);
+ out.m_bottomVec = m_bottomVec.cross(b.m_topVec) + m_topVec.cross(b.m_bottomVec);
+ return out;
+ }
+ //
+ btSpatialMotionVector & operator += (const btSpatialMotionVector &vec) { m_topVec += vec.m_topVec; m_bottomVec += vec.m_bottomVec; return *this; }
+ btSpatialMotionVector & operator -= (const btSpatialMotionVector &vec) { m_topVec -= vec.m_topVec; m_bottomVec -= vec.m_bottomVec; return *this; }
+ btSpatialMotionVector & operator *= (const btScalar &s) { m_topVec *= s; m_bottomVec *= s; return *this; }
+ btSpatialMotionVector operator - (const btSpatialMotionVector &vec) const { return btSpatialMotionVector(m_topVec - vec.m_topVec, m_bottomVec - vec.m_bottomVec); }
+ btSpatialMotionVector operator + (const btSpatialMotionVector &vec) const { return btSpatialMotionVector(m_topVec + vec.m_topVec, m_bottomVec + vec.m_bottomVec); }
+ btSpatialMotionVector operator - () const { return btSpatialMotionVector(-m_topVec, -m_bottomVec); }
+ btSpatialMotionVector operator * (const btScalar &s) const { return btSpatialMotionVector(s * m_topVec, s * m_bottomVec); }
+};
+
+struct btSymmetricSpatialDyad
+{
+ btMatrix3x3 m_topLeftMat, m_topRightMat, m_bottomLeftMat;
+ //
+ btSymmetricSpatialDyad() { setIdentity(); }
+ btSymmetricSpatialDyad(const btMatrix3x3 &topLeftMat, const btMatrix3x3 &topRightMat, const btMatrix3x3 &bottomLeftMat) { setMatrix(topLeftMat, topRightMat, bottomLeftMat); }
+ //
+ void setMatrix(const btMatrix3x3 &topLeftMat, const btMatrix3x3 &topRightMat, const btMatrix3x3 &bottomLeftMat)
+ {
+ m_topLeftMat = topLeftMat;
+ m_topRightMat = topRightMat;
+ m_bottomLeftMat = bottomLeftMat;
+ }
+ //
+ void addMatrix(const btMatrix3x3 &topLeftMat, const btMatrix3x3 &topRightMat, const btMatrix3x3 &bottomLeftMat)
+ {
+ m_topLeftMat += topLeftMat;
+ m_topRightMat += topRightMat;
+ m_bottomLeftMat += bottomLeftMat;
+ }
+ //
+ void setIdentity() { m_topLeftMat.setIdentity(); m_topRightMat.setIdentity(); m_bottomLeftMat.setIdentity(); }
+ //
+ btSymmetricSpatialDyad & operator -= (const btSymmetricSpatialDyad &mat)
+ {
+ m_topLeftMat -= mat.m_topLeftMat;
+ m_topRightMat -= mat.m_topRightMat;
+ m_bottomLeftMat -= mat.m_bottomLeftMat;
+ return *this;
+ }
+ //
+ btSpatialForceVector operator * (const btSpatialMotionVector &vec)
+ {
+ return btSpatialForceVector(m_bottomLeftMat * vec.m_topVec + m_topLeftMat.transpose() * vec.m_bottomVec, m_topLeftMat * vec.m_topVec + m_topRightMat * vec.m_bottomVec);
+ }
+};
+
+struct btSpatialTransformationMatrix
+{
+ btMatrix3x3 m_rotMat; //btMatrix3x3 m_trnCrossMat;
+ btVector3 m_trnVec;
+ //
+ enum eOutputOperation
+ {
+ None = 0,
+ Add = 1,
+ Subtract = 2
+ };
+ //
+ template<typename SpatialVectorType>
+ void transform( const SpatialVectorType &inVec,
+ SpatialVectorType &outVec,
+ eOutputOperation outOp = None)
+ {
+ if(outOp == None)
+ {
+ outVec.m_topVec = m_rotMat * inVec.m_topVec;
+ outVec.m_bottomVec = -m_trnVec.cross(outVec.m_topVec) + m_rotMat * inVec.m_bottomVec;
+ }
+ else if(outOp == Add)
+ {
+ outVec.m_topVec += m_rotMat * inVec.m_topVec;
+ outVec.m_bottomVec += -m_trnVec.cross(outVec.m_topVec) + m_rotMat * inVec.m_bottomVec;
+ }
+ else if(outOp == Subtract)
+ {
+ outVec.m_topVec -= m_rotMat * inVec.m_topVec;
+ outVec.m_bottomVec -= -m_trnVec.cross(outVec.m_topVec) + m_rotMat * inVec.m_bottomVec;
+ }
+
+ }
+
+ template<typename SpatialVectorType>
+ void transformRotationOnly( const SpatialVectorType &inVec,
+ SpatialVectorType &outVec,
+ eOutputOperation outOp = None)
+ {
+ if(outOp == None)
+ {
+ outVec.m_topVec = m_rotMat * inVec.m_topVec;
+ outVec.m_bottomVec = m_rotMat * inVec.m_bottomVec;
+ }
+ else if(outOp == Add)
+ {
+ outVec.m_topVec += m_rotMat * inVec.m_topVec;
+ outVec.m_bottomVec += m_rotMat * inVec.m_bottomVec;
+ }
+ else if(outOp == Subtract)
+ {
+ outVec.m_topVec -= m_rotMat * inVec.m_topVec;
+ outVec.m_bottomVec -= m_rotMat * inVec.m_bottomVec;
+ }
+
+ }
+
+ template<typename SpatialVectorType>
+ void transformInverse( const SpatialVectorType &inVec,
+ SpatialVectorType &outVec,
+ eOutputOperation outOp = None)
+ {
+ if(outOp == None)
+ {
+ outVec.m_topVec = m_rotMat.transpose() * inVec.m_topVec;
+ outVec.m_bottomVec = m_rotMat.transpose() * (inVec.m_bottomVec + m_trnVec.cross(inVec.m_topVec));
+ }
+ else if(outOp == Add)
+ {
+ outVec.m_topVec += m_rotMat.transpose() * inVec.m_topVec;
+ outVec.m_bottomVec += m_rotMat.transpose() * (inVec.m_bottomVec + m_trnVec.cross(inVec.m_topVec));
+ }
+ else if(outOp == Subtract)
+ {
+ outVec.m_topVec -= m_rotMat.transpose() * inVec.m_topVec;
+ outVec.m_bottomVec -= m_rotMat.transpose() * (inVec.m_bottomVec + m_trnVec.cross(inVec.m_topVec));
+ }
+ }
+
+ template<typename SpatialVectorType>
+ void transformInverseRotationOnly( const SpatialVectorType &inVec,
+ SpatialVectorType &outVec,
+ eOutputOperation outOp = None)
+ {
+ if(outOp == None)
+ {
+ outVec.m_topVec = m_rotMat.transpose() * inVec.m_topVec;
+ outVec.m_bottomVec = m_rotMat.transpose() * inVec.m_bottomVec;
+ }
+ else if(outOp == Add)
+ {
+ outVec.m_topVec += m_rotMat.transpose() * inVec.m_topVec;
+ outVec.m_bottomVec += m_rotMat.transpose() * inVec.m_bottomVec;
+ }
+ else if(outOp == Subtract)
+ {
+ outVec.m_topVec -= m_rotMat.transpose() * inVec.m_topVec;
+ outVec.m_bottomVec -= m_rotMat.transpose() * inVec.m_bottomVec;
+ }
+
+ }
+
+ void transformInverse( const btSymmetricSpatialDyad &inMat,
+ btSymmetricSpatialDyad &outMat,
+ eOutputOperation outOp = None)
+ {
+ const btMatrix3x3 r_cross( 0, -m_trnVec[2], m_trnVec[1],
+ m_trnVec[2], 0, -m_trnVec[0],
+ -m_trnVec[1], m_trnVec[0], 0);
+
+
+ if(outOp == None)
+ {
+ outMat.m_topLeftMat = m_rotMat.transpose() * ( inMat.m_topLeftMat - inMat.m_topRightMat * r_cross ) * m_rotMat;
+ outMat.m_topRightMat = m_rotMat.transpose() * inMat.m_topRightMat * m_rotMat;
+ outMat.m_bottomLeftMat = m_rotMat.transpose() * (r_cross * (inMat.m_topLeftMat - inMat.m_topRightMat * r_cross) + inMat.m_bottomLeftMat - inMat.m_topLeftMat.transpose() * r_cross) * m_rotMat;
+ }
+ else if(outOp == Add)
+ {
+ outMat.m_topLeftMat += m_rotMat.transpose() * ( inMat.m_topLeftMat - inMat.m_topRightMat * r_cross ) * m_rotMat;
+ outMat.m_topRightMat += m_rotMat.transpose() * inMat.m_topRightMat * m_rotMat;
+ outMat.m_bottomLeftMat += m_rotMat.transpose() * (r_cross * (inMat.m_topLeftMat - inMat.m_topRightMat * r_cross) + inMat.m_bottomLeftMat - inMat.m_topLeftMat.transpose() * r_cross) * m_rotMat;
+ }
+ else if(outOp == Subtract)
+ {
+ outMat.m_topLeftMat -= m_rotMat.transpose() * ( inMat.m_topLeftMat - inMat.m_topRightMat * r_cross ) * m_rotMat;
+ outMat.m_topRightMat -= m_rotMat.transpose() * inMat.m_topRightMat * m_rotMat;
+ outMat.m_bottomLeftMat -= m_rotMat.transpose() * (r_cross * (inMat.m_topLeftMat - inMat.m_topRightMat * r_cross) + inMat.m_bottomLeftMat - inMat.m_topLeftMat.transpose() * r_cross) * m_rotMat;
+ }
+ }
+
+ template<typename SpatialVectorType>
+ SpatialVectorType operator * (const SpatialVectorType &vec)
+ {
+ SpatialVectorType out;
+ transform(vec, out);
+ return out;
+ }
+};
+
+template<typename SpatialVectorType>
+void symmetricSpatialOuterProduct(const SpatialVectorType &a, const SpatialVectorType &b, btSymmetricSpatialDyad &out)
+{
+ //output op maybe?
+
+ out.m_topLeftMat = outerProduct(a.m_topVec, b.m_bottomVec);
+ out.m_topRightMat = outerProduct(a.m_topVec, b.m_topVec);
+ out.m_topLeftMat = outerProduct(a.m_bottomVec, b.m_bottomVec);
+ //maybe simple a*spatTranspose(a) would be nicer?
+}
+
+template<typename SpatialVectorType>
+btSymmetricSpatialDyad symmetricSpatialOuterProduct(const SpatialVectorType &a, const SpatialVectorType &b)
+{
+ btSymmetricSpatialDyad out;
+
+ out.m_topLeftMat = outerProduct(a.m_topVec, b.m_bottomVec);
+ out.m_topRightMat = outerProduct(a.m_topVec, b.m_topVec);
+ out.m_bottomLeftMat = outerProduct(a.m_bottomVec, b.m_bottomVec);
+
+ return out;
+ //maybe simple a*spatTranspose(a) would be nicer?
+}
+
+#endif //BT_SPATIAL_ALGEBRA_H
+
diff --git a/thirdparty/bullet/src/LinearMath/btStackAlloc.h b/thirdparty/bullet/src/LinearMath/btStackAlloc.h
new file mode 100644
index 0000000000..397b084877
--- /dev/null
+++ b/thirdparty/bullet/src/LinearMath/btStackAlloc.h
@@ -0,0 +1,116 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+/*
+StackAlloc extracted from GJK-EPA collision solver by Nathanael Presson
+Nov.2006
+*/
+
+#ifndef BT_STACK_ALLOC
+#define BT_STACK_ALLOC
+
+#include "btScalar.h" //for btAssert
+#include "btAlignedAllocator.h"
+
+///The btBlock class is an internal structure for the btStackAlloc memory allocator.
+struct btBlock
+{
+ btBlock* previous;
+ unsigned char* address;
+};
+
+///The StackAlloc class provides some fast stack-based memory allocator (LIFO last-in first-out)
+class btStackAlloc
+{
+public:
+
+ btStackAlloc(unsigned int size) { ctor();create(size); }
+ ~btStackAlloc() { destroy(); }
+
+ inline void create(unsigned int size)
+ {
+ destroy();
+ data = (unsigned char*) btAlignedAlloc(size,16);
+ totalsize = size;
+ }
+ inline void destroy()
+ {
+ btAssert(usedsize==0);
+ //Raise(L"StackAlloc is still in use");
+
+ if(usedsize==0)
+ {
+ if(!ischild && data)
+ btAlignedFree(data);
+
+ data = 0;
+ usedsize = 0;
+ }
+
+ }
+
+ int getAvailableMemory() const
+ {
+ return static_cast<int>(totalsize - usedsize);
+ }
+
+ unsigned char* allocate(unsigned int size)
+ {
+ const unsigned int nus(usedsize+size);
+ if(nus<totalsize)
+ {
+ usedsize=nus;
+ return(data+(usedsize-size));
+ }
+ btAssert(0);
+ //&& (L"Not enough memory"));
+
+ return(0);
+ }
+ SIMD_FORCE_INLINE btBlock* beginBlock()
+ {
+ btBlock* pb = (btBlock*)allocate(sizeof(btBlock));
+ pb->previous = current;
+ pb->address = data+usedsize;
+ current = pb;
+ return(pb);
+ }
+ SIMD_FORCE_INLINE void endBlock(btBlock* block)
+ {
+ btAssert(block==current);
+ //Raise(L"Unmatched blocks");
+ if(block==current)
+ {
+ current = block->previous;
+ usedsize = (unsigned int)((block->address-data)-sizeof(btBlock));
+ }
+ }
+
+private:
+ void ctor()
+ {
+ data = 0;
+ totalsize = 0;
+ usedsize = 0;
+ current = 0;
+ ischild = false;
+ }
+ unsigned char* data;
+ unsigned int totalsize;
+ unsigned int usedsize;
+ btBlock* current;
+ bool ischild;
+};
+
+#endif //BT_STACK_ALLOC
diff --git a/thirdparty/bullet/src/LinearMath/btThreads.cpp b/thirdparty/bullet/src/LinearMath/btThreads.cpp
new file mode 100644
index 0000000000..59a7ea36e9
--- /dev/null
+++ b/thirdparty/bullet/src/LinearMath/btThreads.cpp
@@ -0,0 +1,722 @@
+/*
+Copyright (c) 2003-2014 Erwin Coumans http://bullet.googlecode.com
+
+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 "btThreads.h"
+#include "btQuickprof.h"
+#include <algorithm> // for min and max
+
+
+#if BT_USE_OPENMP && BT_THREADSAFE
+
+#include <omp.h>
+
+#endif // #if BT_USE_OPENMP && BT_THREADSAFE
+
+
+#if BT_USE_PPL && BT_THREADSAFE
+
+// use Microsoft Parallel Patterns Library (installed with Visual Studio 2010 and later)
+#include <ppl.h> // if you get a compile error here, check whether your version of Visual Studio includes PPL
+// Visual Studio 2010 and later should come with it
+#include <concrtrm.h> // for GetProcessorCount()
+
+#endif // #if BT_USE_PPL && BT_THREADSAFE
+
+
+#if BT_USE_TBB && BT_THREADSAFE
+
+// use Intel Threading Building Blocks for thread management
+#define __TBB_NO_IMPLICIT_LINKAGE 1
+#include <tbb/tbb.h>
+#include <tbb/task_scheduler_init.h>
+#include <tbb/parallel_for.h>
+#include <tbb/blocked_range.h>
+
+#endif // #if BT_USE_TBB && BT_THREADSAFE
+
+
+#if BT_THREADSAFE
+//
+// Lightweight spin-mutex based on atomics
+// Using ordinary system-provided mutexes like Windows critical sections was noticeably slower
+// presumably because when it fails to lock at first it would sleep the thread and trigger costly
+// context switching.
+//
+
+#if __cplusplus >= 201103L
+
+// for anything claiming full C++11 compliance, use C++11 atomics
+// on GCC or Clang you need to compile with -std=c++11
+#define USE_CPP11_ATOMICS 1
+
+#elif defined( _MSC_VER )
+
+// on MSVC, use intrinsics instead
+#define USE_MSVC_INTRINSICS 1
+
+#elif defined( __GNUC__ ) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7))
+
+// available since GCC 4.7 and some versions of clang
+// todo: check for clang
+#define USE_GCC_BUILTIN_ATOMICS 1
+
+#elif defined( __GNUC__ ) && (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)
+
+// available since GCC 4.1
+#define USE_GCC_BUILTIN_ATOMICS_OLD 1
+
+#endif
+
+
+#if USE_CPP11_ATOMICS
+
+#include <atomic>
+#include <thread>
+
+#define THREAD_LOCAL_STATIC thread_local static
+
+bool btSpinMutex::tryLock()
+{
+ std::atomic<int>* aDest = reinterpret_cast<std::atomic<int>*>(&mLock);
+ int expected = 0;
+ return std::atomic_compare_exchange_weak_explicit( aDest, &expected, int(1), std::memory_order_acq_rel, std::memory_order_acquire );
+}
+
+void btSpinMutex::lock()
+{
+ // note: this lock does not sleep the thread.
+ while (! tryLock())
+ {
+ // spin
+ }
+}
+
+void btSpinMutex::unlock()
+{
+ std::atomic<int>* aDest = reinterpret_cast<std::atomic<int>*>(&mLock);
+ std::atomic_store_explicit( aDest, int(0), std::memory_order_release );
+}
+
+
+#elif USE_MSVC_INTRINSICS
+
+#define WIN32_LEAN_AND_MEAN
+
+#include <windows.h>
+#include <intrin.h>
+
+#define THREAD_LOCAL_STATIC __declspec( thread ) static
+
+
+bool btSpinMutex::tryLock()
+{
+ volatile long* aDest = reinterpret_cast<long*>(&mLock);
+ return ( 0 == _InterlockedCompareExchange( aDest, 1, 0) );
+}
+
+void btSpinMutex::lock()
+{
+ // note: this lock does not sleep the thread
+ while (! tryLock())
+ {
+ // spin
+ }
+}
+
+void btSpinMutex::unlock()
+{
+ volatile long* aDest = reinterpret_cast<long*>( &mLock );
+ _InterlockedExchange( aDest, 0 );
+}
+
+#elif USE_GCC_BUILTIN_ATOMICS
+
+#define THREAD_LOCAL_STATIC static __thread
+
+
+bool btSpinMutex::tryLock()
+{
+ int expected = 0;
+ bool weak = false;
+ const int memOrderSuccess = __ATOMIC_ACQ_REL;
+ const int memOrderFail = __ATOMIC_ACQUIRE;
+ return __atomic_compare_exchange_n(&mLock, &expected, int(1), weak, memOrderSuccess, memOrderFail);
+}
+
+void btSpinMutex::lock()
+{
+ // note: this lock does not sleep the thread
+ while (! tryLock())
+ {
+ // spin
+ }
+}
+
+void btSpinMutex::unlock()
+{
+ __atomic_store_n(&mLock, int(0), __ATOMIC_RELEASE);
+}
+
+#elif USE_GCC_BUILTIN_ATOMICS_OLD
+
+
+#define THREAD_LOCAL_STATIC static __thread
+
+bool btSpinMutex::tryLock()
+{
+ return __sync_bool_compare_and_swap(&mLock, int(0), int(1));
+}
+
+void btSpinMutex::lock()
+{
+ // note: this lock does not sleep the thread
+ while (! tryLock())
+ {
+ // spin
+ }
+}
+
+void btSpinMutex::unlock()
+{
+ // write 0
+ __sync_fetch_and_and(&mLock, int(0));
+}
+
+#else //#elif USE_MSVC_INTRINSICS
+
+#error "no threading primitives defined -- unknown platform"
+
+#endif //#else //#elif USE_MSVC_INTRINSICS
+
+#else //#if BT_THREADSAFE
+
+// These should not be called ever
+void btSpinMutex::lock()
+{
+ btAssert( !"unimplemented btSpinMutex::lock() called" );
+}
+
+void btSpinMutex::unlock()
+{
+ btAssert( !"unimplemented btSpinMutex::unlock() called" );
+}
+
+bool btSpinMutex::tryLock()
+{
+ btAssert( !"unimplemented btSpinMutex::tryLock() called" );
+ return true;
+}
+
+#define THREAD_LOCAL_STATIC static
+
+#endif // #else //#if BT_THREADSAFE
+
+
+struct ThreadsafeCounter
+{
+ unsigned int mCounter;
+ btSpinMutex mMutex;
+
+ ThreadsafeCounter()
+ {
+ mCounter = 0;
+ --mCounter; // first count should come back 0
+ }
+
+ unsigned int getNext()
+ {
+ // no need to optimize this with atomics, it is only called ONCE per thread!
+ mMutex.lock();
+ mCounter++;
+ if ( mCounter >= BT_MAX_THREAD_COUNT )
+ {
+ btAssert( !"thread counter exceeded" );
+ // wrap back to the first worker index
+ mCounter = 1;
+ }
+ unsigned int val = mCounter;
+ mMutex.unlock();
+ return val;
+ }
+};
+
+
+static btITaskScheduler* gBtTaskScheduler;
+static int gThreadsRunningCounter = 0; // useful for detecting if we are trying to do nested parallel-for calls
+static btSpinMutex gThreadsRunningCounterMutex;
+static ThreadsafeCounter gThreadCounter;
+
+
+//
+// BT_DETECT_BAD_THREAD_INDEX tries to detect when there are multiple threads assigned the same thread index.
+//
+// BT_DETECT_BAD_THREAD_INDEX is a developer option to test if
+// certain assumptions about how the task scheduler manages its threads
+// holds true.
+// The main assumption is:
+// - when the threadpool is resized, the task scheduler either
+// 1. destroys all worker threads and creates all new ones in the correct number, OR
+// 2. never destroys a worker thread
+//
+// We make that assumption because we can't easily enumerate the worker threads of a task scheduler
+// to assign nice sequential thread-indexes. We also do not get notified if a worker thread is destroyed,
+// so we can't tell when a thread-index is no longer being used.
+// We allocate thread-indexes as needed with a sequential global thread counter.
+//
+// Our simple thread-counting scheme falls apart if the task scheduler destroys some threads but
+// continues to re-use other threads and the application repeatedly resizes the thread pool of the
+// task scheduler.
+// In order to prevent the thread-counter from exceeding the global max (BT_MAX_THREAD_COUNT), we
+// wrap the thread counter back to 1. This should only happen if the worker threads have all been
+// destroyed and re-created.
+//
+// BT_DETECT_BAD_THREAD_INDEX only works for Win32 right now,
+// but could be adapted to work with pthreads
+#define BT_DETECT_BAD_THREAD_INDEX 0
+
+#if BT_DETECT_BAD_THREAD_INDEX
+
+typedef DWORD ThreadId_t;
+const static ThreadId_t kInvalidThreadId = 0;
+ThreadId_t gDebugThreadIds[ BT_MAX_THREAD_COUNT ];
+
+static ThreadId_t getDebugThreadId()
+{
+ return GetCurrentThreadId();
+}
+
+#endif // #if BT_DETECT_BAD_THREAD_INDEX
+
+
+// return a unique index per thread, main thread is 0, worker threads are in [1, BT_MAX_THREAD_COUNT)
+unsigned int btGetCurrentThreadIndex()
+{
+ const unsigned int kNullIndex = ~0U;
+ THREAD_LOCAL_STATIC unsigned int sThreadIndex = kNullIndex;
+ if ( sThreadIndex == kNullIndex )
+ {
+ sThreadIndex = gThreadCounter.getNext();
+ btAssert( sThreadIndex < BT_MAX_THREAD_COUNT );
+ }
+#if BT_DETECT_BAD_THREAD_INDEX
+ if ( gBtTaskScheduler && sThreadIndex > 0 )
+ {
+ ThreadId_t tid = getDebugThreadId();
+ // if not set
+ if ( gDebugThreadIds[ sThreadIndex ] == kInvalidThreadId )
+ {
+ // set it
+ gDebugThreadIds[ sThreadIndex ] = tid;
+ }
+ else
+ {
+ if ( gDebugThreadIds[ sThreadIndex ] != tid )
+ {
+ // this could indicate the task scheduler is breaking our assumptions about
+ // how threads are managed when threadpool is resized
+ btAssert( !"there are 2 or more threads with the same thread-index!" );
+ __debugbreak();
+ }
+ }
+ }
+#endif // #if BT_DETECT_BAD_THREAD_INDEX
+ return sThreadIndex;
+}
+
+bool btIsMainThread()
+{
+ return btGetCurrentThreadIndex() == 0;
+}
+
+void btResetThreadIndexCounter()
+{
+ // for when all current worker threads are destroyed
+ btAssert( btIsMainThread() );
+ gThreadCounter.mCounter = 0;
+}
+
+btITaskScheduler::btITaskScheduler( const char* name )
+{
+ m_name = name;
+ m_savedThreadCounter = 0;
+ m_isActive = false;
+}
+
+void btITaskScheduler::activate()
+{
+ // gThreadCounter is used to assign a thread-index to each worker thread in a task scheduler.
+ // The main thread is always thread-index 0, and worker threads are numbered from 1 to 63 (BT_MAX_THREAD_COUNT-1)
+ // The thread-indexes need to be unique amongst the threads that can be running simultaneously.
+ // Since only one task scheduler can be used at a time, it is OK for a pair of threads that belong to different
+ // task schedulers to share the same thread index because they can't be running at the same time.
+ // So each task scheduler needs to keep its own thread counter value
+ if ( !m_isActive )
+ {
+ gThreadCounter.mCounter = m_savedThreadCounter; // restore saved thread counter
+ m_isActive = true;
+ }
+}
+
+void btITaskScheduler::deactivate()
+{
+ if ( m_isActive )
+ {
+ m_savedThreadCounter = gThreadCounter.mCounter; // save thread counter
+ m_isActive = false;
+ }
+}
+
+void btPushThreadsAreRunning()
+{
+ gThreadsRunningCounterMutex.lock();
+ gThreadsRunningCounter++;
+ gThreadsRunningCounterMutex.unlock();
+}
+
+void btPopThreadsAreRunning()
+{
+ gThreadsRunningCounterMutex.lock();
+ gThreadsRunningCounter--;
+ gThreadsRunningCounterMutex.unlock();
+}
+
+bool btThreadsAreRunning()
+{
+ return gThreadsRunningCounter != 0;
+}
+
+
+void btSetTaskScheduler( btITaskScheduler* ts )
+{
+ int threadId = btGetCurrentThreadIndex(); // make sure we call this on main thread at least once before any workers run
+ if ( threadId != 0 )
+ {
+ btAssert( !"btSetTaskScheduler must be called from the main thread!" );
+ return;
+ }
+ if ( gBtTaskScheduler )
+ {
+ // deactivate old task scheduler
+ gBtTaskScheduler->deactivate();
+ }
+ gBtTaskScheduler = ts;
+ if ( ts )
+ {
+ // activate new task scheduler
+ ts->activate();
+ }
+}
+
+
+btITaskScheduler* btGetTaskScheduler()
+{
+ return gBtTaskScheduler;
+}
+
+
+void btParallelFor( int iBegin, int iEnd, int grainSize, const btIParallelForBody& body )
+{
+#if BT_THREADSAFE
+
+#if BT_DETECT_BAD_THREAD_INDEX
+ if ( !btThreadsAreRunning() )
+ {
+ // clear out thread ids
+ for ( int i = 0; i < BT_MAX_THREAD_COUNT; ++i )
+ {
+ gDebugThreadIds[ i ] = kInvalidThreadId;
+ }
+ }
+#endif // #if BT_DETECT_BAD_THREAD_INDEX
+
+ btAssert( gBtTaskScheduler != NULL ); // call btSetTaskScheduler() with a valid task scheduler first!
+ gBtTaskScheduler->parallelFor( iBegin, iEnd, grainSize, body );
+
+#else // #if BT_THREADSAFE
+
+ // non-parallel version of btParallelFor
+ btAssert( !"called btParallelFor in non-threadsafe build. enable BT_THREADSAFE" );
+ body.forLoop( iBegin, iEnd );
+
+#endif// #if BT_THREADSAFE
+}
+
+
+///
+/// btTaskSchedulerSequential -- non-threaded implementation of task scheduler
+/// (really just useful for testing performance of single threaded vs multi)
+///
+class btTaskSchedulerSequential : public btITaskScheduler
+{
+public:
+ btTaskSchedulerSequential() : btITaskScheduler( "Sequential" ) {}
+ virtual int getMaxNumThreads() const BT_OVERRIDE { return 1; }
+ virtual int getNumThreads() const BT_OVERRIDE { return 1; }
+ virtual void setNumThreads( int numThreads ) BT_OVERRIDE {}
+ virtual void parallelFor( int iBegin, int iEnd, int grainSize, const btIParallelForBody& body ) BT_OVERRIDE
+ {
+ BT_PROFILE( "parallelFor_sequential" );
+ body.forLoop( iBegin, iEnd );
+ }
+};
+
+
+#if BT_USE_OPENMP && BT_THREADSAFE
+///
+/// btTaskSchedulerOpenMP -- wrapper around OpenMP task scheduler
+///
+class btTaskSchedulerOpenMP : public btITaskScheduler
+{
+ int m_numThreads;
+public:
+ btTaskSchedulerOpenMP() : btITaskScheduler( "OpenMP" )
+ {
+ m_numThreads = 0;
+ }
+ virtual int getMaxNumThreads() const BT_OVERRIDE
+ {
+ return omp_get_max_threads();
+ }
+ virtual int getNumThreads() const BT_OVERRIDE
+ {
+ return m_numThreads;
+ }
+ virtual void setNumThreads( int numThreads ) BT_OVERRIDE
+ {
+ // With OpenMP, because it is a standard with various implementations, we can't
+ // know for sure if every implementation has the same behavior of destroying all
+ // previous threads when resizing the threadpool
+ m_numThreads = ( std::max )( 1, ( std::min )( int( BT_MAX_THREAD_COUNT ), numThreads ) );
+ omp_set_num_threads( 1 ); // hopefully, all previous threads get destroyed here
+ omp_set_num_threads( m_numThreads );
+ m_savedThreadCounter = 0;
+ if ( m_isActive )
+ {
+ btResetThreadIndexCounter();
+ }
+ }
+ virtual void parallelFor( int iBegin, int iEnd, int grainSize, const btIParallelForBody& body ) BT_OVERRIDE
+ {
+ BT_PROFILE( "parallelFor_OpenMP" );
+ btPushThreadsAreRunning();
+#pragma omp parallel for schedule( static, 1 )
+ for ( int i = iBegin; i < iEnd; i += grainSize )
+ {
+ BT_PROFILE( "OpenMP_job" );
+ body.forLoop( i, ( std::min )( i + grainSize, iEnd ) );
+ }
+ btPopThreadsAreRunning();
+ }
+};
+#endif // #if BT_USE_OPENMP && BT_THREADSAFE
+
+
+#if BT_USE_TBB && BT_THREADSAFE
+///
+/// btTaskSchedulerTBB -- wrapper around Intel Threaded Building Blocks task scheduler
+///
+class btTaskSchedulerTBB : public btITaskScheduler
+{
+ int m_numThreads;
+ tbb::task_scheduler_init* m_tbbSchedulerInit;
+
+public:
+ btTaskSchedulerTBB() : btITaskScheduler( "IntelTBB" )
+ {
+ m_numThreads = 0;
+ m_tbbSchedulerInit = NULL;
+ }
+ ~btTaskSchedulerTBB()
+ {
+ if ( m_tbbSchedulerInit )
+ {
+ delete m_tbbSchedulerInit;
+ m_tbbSchedulerInit = NULL;
+ }
+ }
+
+ virtual int getMaxNumThreads() const BT_OVERRIDE
+ {
+ return tbb::task_scheduler_init::default_num_threads();
+ }
+ virtual int getNumThreads() const BT_OVERRIDE
+ {
+ return m_numThreads;
+ }
+ virtual void setNumThreads( int numThreads ) BT_OVERRIDE
+ {
+ m_numThreads = ( std::max )( 1, ( std::min )( int(BT_MAX_THREAD_COUNT), numThreads ) );
+ if ( m_tbbSchedulerInit )
+ {
+ // destroys all previous threads
+ delete m_tbbSchedulerInit;
+ m_tbbSchedulerInit = NULL;
+ }
+ m_tbbSchedulerInit = new tbb::task_scheduler_init( m_numThreads );
+ m_savedThreadCounter = 0;
+ if ( m_isActive )
+ {
+ btResetThreadIndexCounter();
+ }
+ }
+ struct BodyAdapter
+ {
+ const btIParallelForBody* mBody;
+
+ void operator()( const tbb::blocked_range<int>& range ) const
+ {
+ BT_PROFILE( "TBB_job" );
+ mBody->forLoop( range.begin(), range.end() );
+ }
+ };
+ virtual void parallelFor( int iBegin, int iEnd, int grainSize, const btIParallelForBody& body ) BT_OVERRIDE
+ {
+ BT_PROFILE( "parallelFor_TBB" );
+ // TBB dispatch
+ BodyAdapter tbbBody;
+ tbbBody.mBody = &body;
+ btPushThreadsAreRunning();
+ tbb::parallel_for( tbb::blocked_range<int>( iBegin, iEnd, grainSize ),
+ tbbBody,
+ tbb::simple_partitioner()
+ );
+ btPopThreadsAreRunning();
+ }
+};
+#endif // #if BT_USE_TBB && BT_THREADSAFE
+
+
+#if BT_USE_PPL && BT_THREADSAFE
+///
+/// btTaskSchedulerPPL -- wrapper around Microsoft Parallel Patterns Lib task scheduler
+///
+class btTaskSchedulerPPL : public btITaskScheduler
+{
+ int m_numThreads;
+public:
+ btTaskSchedulerPPL() : btITaskScheduler( "PPL" )
+ {
+ m_numThreads = 0;
+ }
+ virtual int getMaxNumThreads() const BT_OVERRIDE
+ {
+ return concurrency::GetProcessorCount();
+ }
+ virtual int getNumThreads() const BT_OVERRIDE
+ {
+ return m_numThreads;
+ }
+ virtual void setNumThreads( int numThreads ) BT_OVERRIDE
+ {
+ // capping the thread count for PPL due to a thread-index issue
+ const int maxThreadCount = (std::min)(int(BT_MAX_THREAD_COUNT), 31);
+ m_numThreads = ( std::max )( 1, ( std::min )( maxThreadCount, numThreads ) );
+ using namespace concurrency;
+ if ( CurrentScheduler::Id() != -1 )
+ {
+ CurrentScheduler::Detach();
+ }
+ SchedulerPolicy policy;
+ {
+ // PPL seems to destroy threads when threadpool is shrunk, but keeps reusing old threads
+ // force it to destroy old threads
+ policy.SetConcurrencyLimits( 1, 1 );
+ CurrentScheduler::Create( policy );
+ CurrentScheduler::Detach();
+ }
+ policy.SetConcurrencyLimits( m_numThreads, m_numThreads );
+ CurrentScheduler::Create( policy );
+ m_savedThreadCounter = 0;
+ if ( m_isActive )
+ {
+ btResetThreadIndexCounter();
+ }
+ }
+ struct BodyAdapter
+ {
+ const btIParallelForBody* mBody;
+ int mGrainSize;
+ int mIndexEnd;
+
+ void operator()( int i ) const
+ {
+ BT_PROFILE( "PPL_job" );
+ mBody->forLoop( i, ( std::min )( i + mGrainSize, mIndexEnd ) );
+ }
+ };
+ virtual void parallelFor( int iBegin, int iEnd, int grainSize, const btIParallelForBody& body ) BT_OVERRIDE
+ {
+ BT_PROFILE( "parallelFor_PPL" );
+ // PPL dispatch
+ BodyAdapter pplBody;
+ pplBody.mBody = &body;
+ pplBody.mGrainSize = grainSize;
+ pplBody.mIndexEnd = iEnd;
+ btPushThreadsAreRunning();
+ // note: MSVC 2010 doesn't support partitioner args, so avoid them
+ concurrency::parallel_for( iBegin,
+ iEnd,
+ grainSize,
+ pplBody
+ );
+ btPopThreadsAreRunning();
+ }
+};
+#endif // #if BT_USE_PPL && BT_THREADSAFE
+
+
+// create a non-threaded task scheduler (always available)
+btITaskScheduler* btGetSequentialTaskScheduler()
+{
+ static btTaskSchedulerSequential sTaskScheduler;
+ return &sTaskScheduler;
+}
+
+
+// create an OpenMP task scheduler (if available, otherwise returns null)
+btITaskScheduler* btGetOpenMPTaskScheduler()
+{
+#if BT_USE_OPENMP && BT_THREADSAFE
+ static btTaskSchedulerOpenMP sTaskScheduler;
+ return &sTaskScheduler;
+#else
+ return NULL;
+#endif
+}
+
+
+// create an Intel TBB task scheduler (if available, otherwise returns null)
+btITaskScheduler* btGetTBBTaskScheduler()
+{
+#if BT_USE_TBB && BT_THREADSAFE
+ static btTaskSchedulerTBB sTaskScheduler;
+ return &sTaskScheduler;
+#else
+ return NULL;
+#endif
+}
+
+
+// create a PPL task scheduler (if available, otherwise returns null)
+btITaskScheduler* btGetPPLTaskScheduler()
+{
+#if BT_USE_PPL && BT_THREADSAFE
+ static btTaskSchedulerPPL sTaskScheduler;
+ return &sTaskScheduler;
+#else
+ return NULL;
+#endif
+}
+
diff --git a/thirdparty/bullet/src/LinearMath/btThreads.h b/thirdparty/bullet/src/LinearMath/btThreads.h
new file mode 100644
index 0000000000..05fd15ec82
--- /dev/null
+++ b/thirdparty/bullet/src/LinearMath/btThreads.h
@@ -0,0 +1,155 @@
+/*
+Copyright (c) 2003-2014 Erwin Coumans http://bullet.googlecode.com
+
+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_THREADS_H
+#define BT_THREADS_H
+
+#include "btScalar.h" // has definitions like SIMD_FORCE_INLINE
+
+#if defined (_MSC_VER) && _MSC_VER >= 1600
+// give us a compile error if any signatures of overriden methods is changed
+#define BT_OVERRIDE override
+#endif
+
+#ifndef BT_OVERRIDE
+#define BT_OVERRIDE
+#endif
+
+const unsigned int BT_MAX_THREAD_COUNT = 64; // only if BT_THREADSAFE is 1
+
+// for internal use only
+bool btIsMainThread();
+bool btThreadsAreRunning();
+unsigned int btGetCurrentThreadIndex();
+void btResetThreadIndexCounter(); // notify that all worker threads have been destroyed
+
+///
+/// btSpinMutex -- lightweight spin-mutex implemented with atomic ops, never puts
+/// a thread to sleep because it is designed to be used with a task scheduler
+/// which has one thread per core and the threads don't sleep until they
+/// run out of tasks. Not good for general purpose use.
+///
+class btSpinMutex
+{
+ int mLock;
+
+public:
+ btSpinMutex()
+ {
+ mLock = 0;
+ }
+ void lock();
+ void unlock();
+ bool tryLock();
+};
+
+
+//
+// NOTE: btMutex* is for internal Bullet use only
+//
+// If BT_THREADSAFE is undefined or 0, should optimize away to nothing.
+// This is good because for the single-threaded build of Bullet, any calls
+// to these functions will be optimized out.
+//
+// However, for users of the multi-threaded build of Bullet this is kind
+// of bad because if you call any of these functions from external code
+// (where BT_THREADSAFE is undefined) you will get unexpected race conditions.
+//
+SIMD_FORCE_INLINE void btMutexLock( btSpinMutex* mutex )
+{
+#if BT_THREADSAFE
+ mutex->lock();
+#endif // #if BT_THREADSAFE
+}
+
+SIMD_FORCE_INLINE void btMutexUnlock( btSpinMutex* mutex )
+{
+#if BT_THREADSAFE
+ mutex->unlock();
+#endif // #if BT_THREADSAFE
+}
+
+SIMD_FORCE_INLINE bool btMutexTryLock( btSpinMutex* mutex )
+{
+#if BT_THREADSAFE
+ return mutex->tryLock();
+#else
+ return true;
+#endif // #if BT_THREADSAFE
+}
+
+
+//
+// btIParallelForBody -- subclass this to express work that can be done in parallel
+//
+class btIParallelForBody
+{
+public:
+ virtual ~btIParallelForBody() {}
+ virtual void forLoop( int iBegin, int iEnd ) const = 0;
+};
+
+//
+// btITaskScheduler -- subclass this to implement a task scheduler that can dispatch work to
+// worker threads
+//
+class btITaskScheduler
+{
+public:
+ btITaskScheduler( const char* name );
+ virtual ~btITaskScheduler() {}
+ const char* getName() const { return m_name; }
+
+ virtual int getMaxNumThreads() const = 0;
+ virtual int getNumThreads() const = 0;
+ virtual void setNumThreads( int numThreads ) = 0;
+ virtual void parallelFor( int iBegin, int iEnd, int grainSize, const btIParallelForBody& body ) = 0;
+
+ // internal use only
+ virtual void activate();
+ virtual void deactivate();
+
+protected:
+ const char* m_name;
+ unsigned int m_savedThreadCounter;
+ bool m_isActive;
+};
+
+// set the task scheduler to use for all calls to btParallelFor()
+// NOTE: you must set this prior to using any of the multi-threaded "Mt" classes
+void btSetTaskScheduler( btITaskScheduler* ts );
+
+// get the current task scheduler
+btITaskScheduler* btGetTaskScheduler();
+
+// get non-threaded task scheduler (always available)
+btITaskScheduler* btGetSequentialTaskScheduler();
+
+// get OpenMP task scheduler (if available, otherwise returns null)
+btITaskScheduler* btGetOpenMPTaskScheduler();
+
+// get Intel TBB task scheduler (if available, otherwise returns null)
+btITaskScheduler* btGetTBBTaskScheduler();
+
+// get PPL task scheduler (if available, otherwise returns null)
+btITaskScheduler* btGetPPLTaskScheduler();
+
+// btParallelFor -- call this to dispatch work like a for-loop
+// (iterations may be done out of order, so no dependencies are allowed)
+void btParallelFor( int iBegin, int iEnd, int grainSize, const btIParallelForBody& body );
+
+
+#endif
diff --git a/thirdparty/bullet/src/LinearMath/btTransform.h b/thirdparty/bullet/src/LinearMath/btTransform.h
new file mode 100644
index 0000000000..d4f939a5d9
--- /dev/null
+++ b/thirdparty/bullet/src/LinearMath/btTransform.h
@@ -0,0 +1,305 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+#ifndef BT_TRANSFORM_H
+#define BT_TRANSFORM_H
+
+
+#include "btMatrix3x3.h"
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define btTransformData btTransformDoubleData
+#else
+#define btTransformData btTransformFloatData
+#endif
+
+
+
+
+/**@brief The btTransform class supports rigid transforms with only translation and rotation and no scaling/shear.
+ *It can be used in combination with btVector3, btQuaternion and btMatrix3x3 linear algebra classes. */
+ATTRIBUTE_ALIGNED16(class) btTransform {
+
+ ///Storage for the rotation
+ btMatrix3x3 m_basis;
+ ///Storage for the translation
+ btVector3 m_origin;
+
+public:
+
+ /**@brief No initialization constructor */
+ btTransform() {}
+ /**@brief Constructor from btQuaternion (optional btVector3 )
+ * @param q Rotation from quaternion
+ * @param c Translation from Vector (default 0,0,0) */
+ explicit SIMD_FORCE_INLINE btTransform(const btQuaternion& q,
+ const btVector3& c = btVector3(btScalar(0), btScalar(0), btScalar(0)))
+ : m_basis(q),
+ m_origin(c)
+ {}
+
+ /**@brief Constructor from btMatrix3x3 (optional btVector3)
+ * @param b Rotation from Matrix
+ * @param c Translation from Vector default (0,0,0)*/
+ explicit SIMD_FORCE_INLINE btTransform(const btMatrix3x3& b,
+ const btVector3& c = btVector3(btScalar(0), btScalar(0), btScalar(0)))
+ : m_basis(b),
+ m_origin(c)
+ {}
+ /**@brief Copy constructor */
+ SIMD_FORCE_INLINE btTransform (const btTransform& other)
+ : m_basis(other.m_basis),
+ m_origin(other.m_origin)
+ {
+ }
+ /**@brief Assignment Operator */
+ SIMD_FORCE_INLINE btTransform& operator=(const btTransform& other)
+ {
+ m_basis = other.m_basis;
+ m_origin = other.m_origin;
+ return *this;
+ }
+
+
+ /**@brief Set the current transform as the value of the product of two transforms
+ * @param t1 Transform 1
+ * @param t2 Transform 2
+ * This = Transform1 * Transform2 */
+ SIMD_FORCE_INLINE void mult(const btTransform& t1, const btTransform& t2) {
+ m_basis = t1.m_basis * t2.m_basis;
+ m_origin = t1(t2.m_origin);
+ }
+
+/* void multInverseLeft(const btTransform& t1, const btTransform& t2) {
+ btVector3 v = t2.m_origin - t1.m_origin;
+ m_basis = btMultTransposeLeft(t1.m_basis, t2.m_basis);
+ m_origin = v * t1.m_basis;
+ }
+ */
+
+/**@brief Return the transform of the vector */
+ SIMD_FORCE_INLINE btVector3 operator()(const btVector3& x) const
+ {
+ return x.dot3(m_basis[0], m_basis[1], m_basis[2]) + m_origin;
+ }
+
+ /**@brief Return the transform of the vector */
+ SIMD_FORCE_INLINE btVector3 operator*(const btVector3& x) const
+ {
+ return (*this)(x);
+ }
+
+ /**@brief Return the transform of the btQuaternion */
+ SIMD_FORCE_INLINE btQuaternion operator*(const btQuaternion& q) const
+ {
+ return getRotation() * q;
+ }
+
+ /**@brief Return the basis matrix for the rotation */
+ SIMD_FORCE_INLINE btMatrix3x3& getBasis() { return m_basis; }
+ /**@brief Return the basis matrix for the rotation */
+ SIMD_FORCE_INLINE const btMatrix3x3& getBasis() const { return m_basis; }
+
+ /**@brief Return the origin vector translation */
+ SIMD_FORCE_INLINE btVector3& getOrigin() { return m_origin; }
+ /**@brief Return the origin vector translation */
+ SIMD_FORCE_INLINE const btVector3& getOrigin() const { return m_origin; }
+
+ /**@brief Return a quaternion representing the rotation */
+ btQuaternion getRotation() const {
+ btQuaternion q;
+ m_basis.getRotation(q);
+ return q;
+ }
+
+
+ /**@brief Set from an array
+ * @param m A pointer to a 16 element array (12 rotation(row major padded on the right by 1), and 3 translation */
+ void setFromOpenGLMatrix(const btScalar *m)
+ {
+ m_basis.setFromOpenGLSubMatrix(m);
+ m_origin.setValue(m[12],m[13],m[14]);
+ }
+
+ /**@brief Fill an array representation
+ * @param m A pointer to a 16 element array (12 rotation(row major padded on the right by 1), and 3 translation */
+ void getOpenGLMatrix(btScalar *m) const
+ {
+ m_basis.getOpenGLSubMatrix(m);
+ m[12] = m_origin.x();
+ m[13] = m_origin.y();
+ m[14] = m_origin.z();
+ m[15] = btScalar(1.0);
+ }
+
+ /**@brief Set the translational element
+ * @param origin The vector to set the translation to */
+ SIMD_FORCE_INLINE void setOrigin(const btVector3& origin)
+ {
+ m_origin = origin;
+ }
+
+ SIMD_FORCE_INLINE btVector3 invXform(const btVector3& inVec) const;
+
+
+ /**@brief Set the rotational element by btMatrix3x3 */
+ SIMD_FORCE_INLINE void setBasis(const btMatrix3x3& basis)
+ {
+ m_basis = basis;
+ }
+
+ /**@brief Set the rotational element by btQuaternion */
+ SIMD_FORCE_INLINE void setRotation(const btQuaternion& q)
+ {
+ m_basis.setRotation(q);
+ }
+
+
+ /**@brief Set this transformation to the identity */
+ void setIdentity()
+ {
+ m_basis.setIdentity();
+ m_origin.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
+ }
+
+ /**@brief Multiply this Transform by another(this = this * another)
+ * @param t The other transform */
+ btTransform& operator*=(const btTransform& t)
+ {
+ m_origin += m_basis * t.m_origin;
+ m_basis *= t.m_basis;
+ return *this;
+ }
+
+ /**@brief Return the inverse of this transform */
+ btTransform inverse() const
+ {
+ btMatrix3x3 inv = m_basis.transpose();
+ return btTransform(inv, inv * -m_origin);
+ }
+
+ /**@brief Return the inverse of this transform times the other transform
+ * @param t The other transform
+ * return this.inverse() * the other */
+ btTransform inverseTimes(const btTransform& t) const;
+
+ /**@brief Return the product of this transform and the other */
+ btTransform operator*(const btTransform& t) const;
+
+ /**@brief Return an identity transform */
+ static const btTransform& getIdentity()
+ {
+ static const btTransform identityTransform(btMatrix3x3::getIdentity());
+ return identityTransform;
+ }
+
+ void serialize(struct btTransformData& dataOut) const;
+
+ void serializeFloat(struct btTransformFloatData& dataOut) const;
+
+ void deSerialize(const struct btTransformData& dataIn);
+
+ void deSerializeDouble(const struct btTransformDoubleData& dataIn);
+
+ void deSerializeFloat(const struct btTransformFloatData& dataIn);
+
+};
+
+
+SIMD_FORCE_INLINE btVector3
+btTransform::invXform(const btVector3& inVec) const
+{
+ btVector3 v = inVec - m_origin;
+ return (m_basis.transpose() * v);
+}
+
+SIMD_FORCE_INLINE btTransform
+btTransform::inverseTimes(const btTransform& t) const
+{
+ btVector3 v = t.getOrigin() - m_origin;
+ return btTransform(m_basis.transposeTimes(t.m_basis),
+ v * m_basis);
+}
+
+SIMD_FORCE_INLINE btTransform
+btTransform::operator*(const btTransform& t) const
+{
+ return btTransform(m_basis * t.m_basis,
+ (*this)(t.m_origin));
+}
+
+/**@brief Test if two transforms have all elements equal */
+SIMD_FORCE_INLINE bool operator==(const btTransform& t1, const btTransform& t2)
+{
+ return ( t1.getBasis() == t2.getBasis() &&
+ t1.getOrigin() == t2.getOrigin() );
+}
+
+
+///for serialization
+struct btTransformFloatData
+{
+ btMatrix3x3FloatData m_basis;
+ btVector3FloatData m_origin;
+};
+
+struct btTransformDoubleData
+{
+ btMatrix3x3DoubleData m_basis;
+ btVector3DoubleData m_origin;
+};
+
+
+
+SIMD_FORCE_INLINE void btTransform::serialize(btTransformData& dataOut) const
+{
+ m_basis.serialize(dataOut.m_basis);
+ m_origin.serialize(dataOut.m_origin);
+}
+
+SIMD_FORCE_INLINE void btTransform::serializeFloat(btTransformFloatData& dataOut) const
+{
+ m_basis.serializeFloat(dataOut.m_basis);
+ m_origin.serializeFloat(dataOut.m_origin);
+}
+
+
+SIMD_FORCE_INLINE void btTransform::deSerialize(const btTransformData& dataIn)
+{
+ m_basis.deSerialize(dataIn.m_basis);
+ m_origin.deSerialize(dataIn.m_origin);
+}
+
+SIMD_FORCE_INLINE void btTransform::deSerializeFloat(const btTransformFloatData& dataIn)
+{
+ m_basis.deSerializeFloat(dataIn.m_basis);
+ m_origin.deSerializeFloat(dataIn.m_origin);
+}
+
+SIMD_FORCE_INLINE void btTransform::deSerializeDouble(const btTransformDoubleData& dataIn)
+{
+ m_basis.deSerializeDouble(dataIn.m_basis);
+ m_origin.deSerializeDouble(dataIn.m_origin);
+}
+
+
+#endif //BT_TRANSFORM_H
+
+
+
+
+
+
diff --git a/thirdparty/bullet/src/LinearMath/btTransformUtil.h b/thirdparty/bullet/src/LinearMath/btTransformUtil.h
new file mode 100644
index 0000000000..182cc43fab
--- /dev/null
+++ b/thirdparty/bullet/src/LinearMath/btTransformUtil.h
@@ -0,0 +1,241 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#ifndef BT_TRANSFORM_UTIL_H
+#define BT_TRANSFORM_UTIL_H
+
+#include "btTransform.h"
+#define ANGULAR_MOTION_THRESHOLD btScalar(0.5)*SIMD_HALF_PI
+
+
+
+
+SIMD_FORCE_INLINE btVector3 btAabbSupport(const btVector3& halfExtents,const btVector3& supportDir)
+{
+ return btVector3(supportDir.x() < btScalar(0.0) ? -halfExtents.x() : halfExtents.x(),
+ supportDir.y() < btScalar(0.0) ? -halfExtents.y() : halfExtents.y(),
+ supportDir.z() < btScalar(0.0) ? -halfExtents.z() : halfExtents.z());
+}
+
+
+
+
+
+
+/// Utils related to temporal transforms
+class btTransformUtil
+{
+
+public:
+
+ static void integrateTransform(const btTransform& curTrans,const btVector3& linvel,const btVector3& angvel,btScalar timeStep,btTransform& predictedTransform)
+ {
+ predictedTransform.setOrigin(curTrans.getOrigin() + linvel * timeStep);
+// #define QUATERNION_DERIVATIVE
+ #ifdef QUATERNION_DERIVATIVE
+ btQuaternion predictedOrn = curTrans.getRotation();
+ predictedOrn += (angvel * predictedOrn) * (timeStep * btScalar(0.5));
+ predictedOrn.safeNormalize();
+ #else
+ //Exponential map
+ //google for "Practical Parameterization of Rotations Using the Exponential Map", F. Sebastian Grassia
+
+ btVector3 axis;
+ btScalar fAngle2 = angvel.length2();
+ btScalar fAngle = 0;
+ if (fAngle2>SIMD_EPSILON)
+ {
+ fAngle = btSqrt(fAngle2);
+ }
+
+ //limit the angular motion
+ if (fAngle*timeStep > ANGULAR_MOTION_THRESHOLD)
+ {
+ fAngle = ANGULAR_MOTION_THRESHOLD / timeStep;
+ }
+
+ if ( fAngle < btScalar(0.001) )
+ {
+ // use Taylor's expansions of sync function
+ axis = angvel*( btScalar(0.5)*timeStep-(timeStep*timeStep*timeStep)*(btScalar(0.020833333333))*fAngle*fAngle );
+ }
+ else
+ {
+ // sync(fAngle) = sin(c*fAngle)/t
+ axis = angvel*( btSin(btScalar(0.5)*fAngle*timeStep)/fAngle );
+ }
+ btQuaternion dorn (axis.x(),axis.y(),axis.z(),btCos( fAngle*timeStep*btScalar(0.5) ));
+ btQuaternion orn0 = curTrans.getRotation();
+
+ btQuaternion predictedOrn = dorn * orn0;
+ predictedOrn.safeNormalize();
+ #endif
+ if (predictedOrn.length2()>SIMD_EPSILON)
+ {
+ predictedTransform.setRotation(predictedOrn);
+ }
+ else
+ {
+ predictedTransform.setBasis(curTrans.getBasis());
+ }
+ }
+
+ static void calculateVelocityQuaternion(const btVector3& pos0,const btVector3& pos1,const btQuaternion& orn0,const btQuaternion& orn1,btScalar timeStep,btVector3& linVel,btVector3& angVel)
+ {
+ linVel = (pos1 - pos0) / timeStep;
+ btVector3 axis;
+ btScalar angle;
+ if (orn0 != orn1)
+ {
+ calculateDiffAxisAngleQuaternion(orn0,orn1,axis,angle);
+ angVel = axis * angle / timeStep;
+ } else
+ {
+ angVel.setValue(0,0,0);
+ }
+ }
+
+ static void calculateDiffAxisAngleQuaternion(const btQuaternion& orn0,const btQuaternion& orn1a,btVector3& axis,btScalar& angle)
+ {
+ btQuaternion orn1 = orn0.nearest(orn1a);
+ btQuaternion dorn = orn1 * orn0.inverse();
+ angle = dorn.getAngle();
+ axis = btVector3(dorn.x(),dorn.y(),dorn.z());
+ axis[3] = btScalar(0.);
+ //check for axis length
+ btScalar len = axis.length2();
+ if (len < SIMD_EPSILON*SIMD_EPSILON)
+ axis = btVector3(btScalar(1.),btScalar(0.),btScalar(0.));
+ else
+ axis /= btSqrt(len);
+ }
+
+ static void calculateVelocity(const btTransform& transform0,const btTransform& transform1,btScalar timeStep,btVector3& linVel,btVector3& angVel)
+ {
+ linVel = (transform1.getOrigin() - transform0.getOrigin()) / timeStep;
+ btVector3 axis;
+ btScalar angle;
+ calculateDiffAxisAngle(transform0,transform1,axis,angle);
+ angVel = axis * angle / timeStep;
+ }
+
+ static void calculateDiffAxisAngle(const btTransform& transform0,const btTransform& transform1,btVector3& axis,btScalar& angle)
+ {
+ btMatrix3x3 dmat = transform1.getBasis() * transform0.getBasis().inverse();
+ btQuaternion dorn;
+ dmat.getRotation(dorn);
+
+ ///floating point inaccuracy can lead to w component > 1..., which breaks
+ dorn.normalize();
+
+ angle = dorn.getAngle();
+ axis = btVector3(dorn.x(),dorn.y(),dorn.z());
+ axis[3] = btScalar(0.);
+ //check for axis length
+ btScalar len = axis.length2();
+ if (len < SIMD_EPSILON*SIMD_EPSILON)
+ axis = btVector3(btScalar(1.),btScalar(0.),btScalar(0.));
+ else
+ axis /= btSqrt(len);
+ }
+
+};
+
+
+///The btConvexSeparatingDistanceUtil can help speed up convex collision detection
+///by conservatively updating a cached separating distance/vector instead of re-calculating the closest distance
+class btConvexSeparatingDistanceUtil
+{
+ btQuaternion m_ornA;
+ btQuaternion m_ornB;
+ btVector3 m_posA;
+ btVector3 m_posB;
+
+ btVector3 m_separatingNormal;
+
+ btScalar m_boundingRadiusA;
+ btScalar m_boundingRadiusB;
+ btScalar m_separatingDistance;
+
+public:
+
+ btConvexSeparatingDistanceUtil(btScalar boundingRadiusA,btScalar boundingRadiusB)
+ :m_boundingRadiusA(boundingRadiusA),
+ m_boundingRadiusB(boundingRadiusB),
+ m_separatingDistance(0.f)
+ {
+ }
+
+ btScalar getConservativeSeparatingDistance()
+ {
+ return m_separatingDistance;
+ }
+
+ void updateSeparatingDistance(const btTransform& transA,const btTransform& transB)
+ {
+ const btVector3& toPosA = transA.getOrigin();
+ const btVector3& toPosB = transB.getOrigin();
+ btQuaternion toOrnA = transA.getRotation();
+ btQuaternion toOrnB = transB.getRotation();
+
+ if (m_separatingDistance>0.f)
+ {
+
+
+ btVector3 linVelA,angVelA,linVelB,angVelB;
+ btTransformUtil::calculateVelocityQuaternion(m_posA,toPosA,m_ornA,toOrnA,btScalar(1.),linVelA,angVelA);
+ btTransformUtil::calculateVelocityQuaternion(m_posB,toPosB,m_ornB,toOrnB,btScalar(1.),linVelB,angVelB);
+ btScalar maxAngularProjectedVelocity = angVelA.length() * m_boundingRadiusA + angVelB.length() * m_boundingRadiusB;
+ btVector3 relLinVel = (linVelB-linVelA);
+ btScalar relLinVelocLength = relLinVel.dot(m_separatingNormal);
+ if (relLinVelocLength<0.f)
+ {
+ relLinVelocLength = 0.f;
+ }
+
+ btScalar projectedMotion = maxAngularProjectedVelocity +relLinVelocLength;
+ m_separatingDistance -= projectedMotion;
+ }
+
+ m_posA = toPosA;
+ m_posB = toPosB;
+ m_ornA = toOrnA;
+ m_ornB = toOrnB;
+ }
+
+ void initSeparatingDistance(const btVector3& separatingVector,btScalar separatingDistance,const btTransform& transA,const btTransform& transB)
+ {
+ m_separatingDistance = separatingDistance;
+
+ if (m_separatingDistance>0.f)
+ {
+ m_separatingNormal = separatingVector;
+
+ const btVector3& toPosA = transA.getOrigin();
+ const btVector3& toPosB = transB.getOrigin();
+ btQuaternion toOrnA = transA.getRotation();
+ btQuaternion toOrnB = transB.getRotation();
+ m_posA = toPosA;
+ m_posB = toPosB;
+ m_ornA = toOrnA;
+ m_ornB = toOrnB;
+ }
+ }
+
+};
+
+
+#endif //BT_TRANSFORM_UTIL_H
+
diff --git a/thirdparty/bullet/src/LinearMath/btVector3.cpp b/thirdparty/bullet/src/LinearMath/btVector3.cpp
new file mode 100644
index 0000000000..e05bdccd67
--- /dev/null
+++ b/thirdparty/bullet/src/LinearMath/btVector3.cpp
@@ -0,0 +1,1670 @@
+/*
+ Copyright (c) 2011 Apple Inc.
+ http://continuousphysics.com/Bullet/
+
+ This software is provided 'as-is', without any express or implied warranty.
+ In no event will the authors be held liable for any damages arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it freely,
+ subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ This source version has been altered.
+ */
+
+#if defined (_WIN32) || defined (__i386__)
+#define BT_USE_SSE_IN_API
+#endif
+
+
+#include "btVector3.h"
+
+
+
+#if defined BT_USE_SIMD_VECTOR3
+
+#if DEBUG
+#include <string.h>//for memset
+#endif
+
+
+#ifdef __APPLE__
+#include <stdint.h>
+typedef float float4 __attribute__ ((vector_size(16)));
+#else
+#define float4 __m128
+#endif
+//typedef uint32_t uint4 __attribute__ ((vector_size(16)));
+
+
+#if defined BT_USE_SSE || defined _WIN32
+
+#define LOG2_ARRAY_SIZE 6
+#define STACK_ARRAY_COUNT (1UL << LOG2_ARRAY_SIZE)
+
+#include <emmintrin.h>
+
+long _maxdot_large( const float *vv, const float *vec, unsigned long count, float *dotResult );
+long _maxdot_large( const float *vv, const float *vec, unsigned long count, float *dotResult )
+{
+ const float4 *vertices = (const float4*) vv;
+ static const unsigned char indexTable[16] = {(unsigned char)-1, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 };
+ float4 dotMax = btAssign128( -BT_INFINITY, -BT_INFINITY, -BT_INFINITY, -BT_INFINITY );
+ float4 vvec = _mm_loadu_ps( vec );
+ float4 vHi = btCastiTo128f(_mm_shuffle_epi32( btCastfTo128i( vvec), 0xaa )); /// zzzz
+ float4 vLo = _mm_movelh_ps( vvec, vvec ); /// xyxy
+
+ long maxIndex = -1L;
+
+ size_t segment = 0;
+ float4 stack_array[ STACK_ARRAY_COUNT ];
+
+#if DEBUG
+ //memset( stack_array, -1, STACK_ARRAY_COUNT * sizeof(stack_array[0]) );
+#endif
+
+ size_t index;
+ float4 max;
+ // Faster loop without cleanup code for full tiles
+ for ( segment = 0; segment + STACK_ARRAY_COUNT*4 <= count; segment += STACK_ARRAY_COUNT*4 )
+ {
+ max = dotMax;
+
+ for( index = 0; index < STACK_ARRAY_COUNT; index+= 4 )
+ { // do four dot products at a time. Carefully avoid touching the w element.
+ float4 v0 = vertices[0];
+ float4 v1 = vertices[1];
+ float4 v2 = vertices[2];
+ float4 v3 = vertices[3]; vertices += 4;
+
+ float4 lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
+ float4 hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
+ float4 lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
+ float4 hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
+
+ lo0 = lo0*vLo;
+ lo1 = lo1*vLo;
+ float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z*vHi;
+ x = x+y;
+ x = x+z;
+ stack_array[index] = x;
+ max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3]; vertices += 4;
+
+ lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
+
+ lo0 = lo0*vLo;
+ lo1 = lo1*vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z*vHi;
+ x = x+y;
+ x = x+z;
+ stack_array[index+1] = x;
+ max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3]; vertices += 4;
+
+ lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
+
+ lo0 = lo0*vLo;
+ lo1 = lo1*vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z*vHi;
+ x = x+y;
+ x = x+z;
+ stack_array[index+2] = x;
+ max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3]; vertices += 4;
+
+ lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
+
+ lo0 = lo0*vLo;
+ lo1 = lo1*vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z*vHi;
+ x = x+y;
+ x = x+z;
+ stack_array[index+3] = x;
+ max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan
+
+ // It is too costly to keep the index of the max here. We will look for it again later. We save a lot of work this way.
+ }
+
+ // If we found a new max
+ if( 0xf != _mm_movemask_ps( (float4) _mm_cmpeq_ps(max, dotMax)))
+ {
+ // copy the new max across all lanes of our max accumulator
+ max = _mm_max_ps(max, (float4) _mm_shuffle_ps( max, max, 0x4e));
+ max = _mm_max_ps(max, (float4) _mm_shuffle_ps( max, max, 0xb1));
+
+ dotMax = max;
+
+ // find first occurrence of that max
+ size_t test;
+ for( index = 0; 0 == (test=_mm_movemask_ps( _mm_cmpeq_ps( stack_array[index], max))); index++ ) // local_count must be a multiple of 4
+ {}
+ // record where it is.
+ maxIndex = 4*index + segment + indexTable[test];
+ }
+ }
+
+ // account for work we've already done
+ count -= segment;
+
+ // Deal with the last < STACK_ARRAY_COUNT vectors
+ max = dotMax;
+ index = 0;
+
+
+ if( btUnlikely( count > 16) )
+ {
+ for( ; index + 4 <= count / 4; index+=4 )
+ { // do four dot products at a time. Carefully avoid touching the w element.
+ float4 v0 = vertices[0];
+ float4 v1 = vertices[1];
+ float4 v2 = vertices[2];
+ float4 v3 = vertices[3]; vertices += 4;
+
+ float4 lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
+ float4 hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
+ float4 lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
+ float4 hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
+
+ lo0 = lo0*vLo;
+ lo1 = lo1*vLo;
+ float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z*vHi;
+ x = x+y;
+ x = x+z;
+ stack_array[index] = x;
+ max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3]; vertices += 4;
+
+ lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
+
+ lo0 = lo0*vLo;
+ lo1 = lo1*vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z*vHi;
+ x = x+y;
+ x = x+z;
+ stack_array[index+1] = x;
+ max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3]; vertices += 4;
+
+ lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
+
+ lo0 = lo0*vLo;
+ lo1 = lo1*vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z*vHi;
+ x = x+y;
+ x = x+z;
+ stack_array[index+2] = x;
+ max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3]; vertices += 4;
+
+ lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
+
+ lo0 = lo0*vLo;
+ lo1 = lo1*vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z*vHi;
+ x = x+y;
+ x = x+z;
+ stack_array[index+3] = x;
+ max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan
+
+ // It is too costly to keep the index of the max here. We will look for it again later. We save a lot of work this way.
+ }
+ }
+
+ size_t localCount = (count & -4L) - 4*index;
+ if( localCount )
+ {
+#ifdef __APPLE__
+ float4 t0, t1, t2, t3, t4;
+ float4 * sap = &stack_array[index + localCount / 4];
+ vertices += localCount; // counter the offset
+ size_t byteIndex = -(localCount) * sizeof(float);
+ //AT&T Code style assembly
+ asm volatile
+ ( ".align 4 \n\
+ 0: movaps %[max], %[t2] // move max out of the way to avoid propagating NaNs in max \n\
+ movaps (%[vertices], %[byteIndex], 4), %[t0] // vertices[0] \n\
+ movaps 16(%[vertices], %[byteIndex], 4), %[t1] // vertices[1] \n\
+ movaps %[t0], %[max] // vertices[0] \n\
+ movlhps %[t1], %[max] // x0y0x1y1 \n\
+ movaps 32(%[vertices], %[byteIndex], 4), %[t3] // vertices[2] \n\
+ movaps 48(%[vertices], %[byteIndex], 4), %[t4] // vertices[3] \n\
+ mulps %[vLo], %[max] // x0y0x1y1 * vLo \n\
+ movhlps %[t0], %[t1] // z0w0z1w1 \n\
+ movaps %[t3], %[t0] // vertices[2] \n\
+ movlhps %[t4], %[t0] // x2y2x3y3 \n\
+ mulps %[vLo], %[t0] // x2y2x3y3 * vLo \n\
+ movhlps %[t3], %[t4] // z2w2z3w3 \n\
+ shufps $0x88, %[t4], %[t1] // z0z1z2z3 \n\
+ mulps %[vHi], %[t1] // z0z1z2z3 * vHi \n\
+ movaps %[max], %[t3] // x0y0x1y1 * vLo \n\
+ shufps $0x88, %[t0], %[max] // x0x1x2x3 * vLo.x \n\
+ shufps $0xdd, %[t0], %[t3] // y0y1y2y3 * vLo.y \n\
+ addps %[t3], %[max] // x + y \n\
+ addps %[t1], %[max] // x + y + z \n\
+ movaps %[max], (%[sap], %[byteIndex]) // record result for later scrutiny \n\
+ maxps %[t2], %[max] // record max, restore max \n\
+ add $16, %[byteIndex] // advance loop counter\n\
+ jnz 0b \n\
+ "
+ : [max] "+x" (max), [t0] "=&x" (t0), [t1] "=&x" (t1), [t2] "=&x" (t2), [t3] "=&x" (t3), [t4] "=&x" (t4), [byteIndex] "+r" (byteIndex)
+ : [vLo] "x" (vLo), [vHi] "x" (vHi), [vertices] "r" (vertices), [sap] "r" (sap)
+ : "memory", "cc"
+ );
+ index += localCount/4;
+#else
+ {
+ for( unsigned int i=0; i<localCount/4; i++,index++)
+ { // do four dot products at a time. Carefully avoid touching the w element.
+ float4 v0 = vertices[0];
+ float4 v1 = vertices[1];
+ float4 v2 = vertices[2];
+ float4 v3 = vertices[3];
+ vertices += 4;
+
+ float4 lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
+ float4 hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
+ float4 lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
+ float4 hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
+
+ lo0 = lo0*vLo;
+ lo1 = lo1*vLo;
+ float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z*vHi;
+ x = x+y;
+ x = x+z;
+ stack_array[index] = x;
+ max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan
+ }
+ }
+#endif //__APPLE__
+ }
+
+ // process the last few points
+ if( count & 3 )
+ {
+ float4 v0, v1, v2, x, y, z;
+ switch( count & 3 )
+ {
+ case 3:
+ {
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+
+ // Calculate 3 dot products, transpose, duplicate v2
+ float4 lo0 = _mm_movelh_ps( v0, v1); // xyxy.lo
+ float4 hi0 = _mm_movehl_ps( v1, v0); // z?z?.lo
+ lo0 = lo0*vLo;
+ z = _mm_shuffle_ps(hi0, v2, 0xa8 ); // z0z1z2z2
+ z = z*vHi;
+ float4 lo1 = _mm_movelh_ps(v2, v2); // xyxy
+ lo1 = lo1*vLo;
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ }
+ break;
+ case 2:
+ {
+ v0 = vertices[0];
+ v1 = vertices[1];
+ float4 xy = _mm_movelh_ps(v0, v1);
+ z = _mm_movehl_ps(v1, v0);
+ xy = xy*vLo;
+ z = _mm_shuffle_ps( z, z, 0xa8);
+ x = _mm_shuffle_ps( xy, xy, 0xa8);
+ y = _mm_shuffle_ps( xy, xy, 0xfd);
+ z = z*vHi;
+ }
+ break;
+ case 1:
+ {
+ float4 xy = vertices[0];
+ z = _mm_shuffle_ps( xy, xy, 0xaa);
+ xy = xy*vLo;
+ z = z*vHi;
+ x = _mm_shuffle_ps(xy, xy, 0);
+ y = _mm_shuffle_ps(xy, xy, 0x55);
+ }
+ break;
+ }
+ x = x+y;
+ x = x+z;
+ stack_array[index] = x;
+ max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan
+ index++;
+ }
+
+ // if we found a new max.
+ if( 0 == segment || 0xf != _mm_movemask_ps( (float4) _mm_cmpeq_ps(max, dotMax)))
+ { // we found a new max. Search for it
+ // find max across the max vector, place in all elements of max -- big latency hit here
+ max = _mm_max_ps(max, (float4) _mm_shuffle_ps( max, max, 0x4e));
+ max = _mm_max_ps(max, (float4) _mm_shuffle_ps( max, max, 0xb1));
+
+ // It is slightly faster to do this part in scalar code when count < 8. However, the common case for
+ // this where it actually makes a difference is handled in the early out at the top of the function,
+ // so it is less than a 1% difference here. I opted for improved code size, fewer branches and reduced
+ // complexity, and removed it.
+
+ dotMax = max;
+
+ // scan for the first occurence of max in the array
+ size_t test;
+ for( index = 0; 0 == (test=_mm_movemask_ps( _mm_cmpeq_ps( stack_array[index], max))); index++ ) // local_count must be a multiple of 4
+ {}
+ maxIndex = 4*index + segment + indexTable[test];
+ }
+
+ _mm_store_ss( dotResult, dotMax);
+ return maxIndex;
+}
+
+long _mindot_large( const float *vv, const float *vec, unsigned long count, float *dotResult );
+
+long _mindot_large( const float *vv, const float *vec, unsigned long count, float *dotResult )
+{
+ const float4 *vertices = (const float4*) vv;
+ static const unsigned char indexTable[16] = {(unsigned char)-1, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 };
+ float4 dotmin = btAssign128( BT_INFINITY, BT_INFINITY, BT_INFINITY, BT_INFINITY );
+ float4 vvec = _mm_loadu_ps( vec );
+ float4 vHi = btCastiTo128f(_mm_shuffle_epi32( btCastfTo128i( vvec), 0xaa )); /// zzzz
+ float4 vLo = _mm_movelh_ps( vvec, vvec ); /// xyxy
+
+ long minIndex = -1L;
+
+ size_t segment = 0;
+ float4 stack_array[ STACK_ARRAY_COUNT ];
+
+#if DEBUG
+ //memset( stack_array, -1, STACK_ARRAY_COUNT * sizeof(stack_array[0]) );
+#endif
+
+ size_t index;
+ float4 min;
+ // Faster loop without cleanup code for full tiles
+ for ( segment = 0; segment + STACK_ARRAY_COUNT*4 <= count; segment += STACK_ARRAY_COUNT*4 )
+ {
+ min = dotmin;
+
+ for( index = 0; index < STACK_ARRAY_COUNT; index+= 4 )
+ { // do four dot products at a time. Carefully avoid touching the w element.
+ float4 v0 = vertices[0];
+ float4 v1 = vertices[1];
+ float4 v2 = vertices[2];
+ float4 v3 = vertices[3]; vertices += 4;
+
+ float4 lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
+ float4 hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
+ float4 lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
+ float4 hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
+
+ lo0 = lo0*vLo;
+ lo1 = lo1*vLo;
+ float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z*vHi;
+ x = x+y;
+ x = x+z;
+ stack_array[index] = x;
+ min = _mm_min_ps( x, min ); // control the order here so that min is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3]; vertices += 4;
+
+ lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
+
+ lo0 = lo0*vLo;
+ lo1 = lo1*vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z*vHi;
+ x = x+y;
+ x = x+z;
+ stack_array[index+1] = x;
+ min = _mm_min_ps( x, min ); // control the order here so that min is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3]; vertices += 4;
+
+ lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
+
+ lo0 = lo0*vLo;
+ lo1 = lo1*vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z*vHi;
+ x = x+y;
+ x = x+z;
+ stack_array[index+2] = x;
+ min = _mm_min_ps( x, min ); // control the order here so that min is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3]; vertices += 4;
+
+ lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
+
+ lo0 = lo0*vLo;
+ lo1 = lo1*vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z*vHi;
+ x = x+y;
+ x = x+z;
+ stack_array[index+3] = x;
+ min = _mm_min_ps( x, min ); // control the order here so that min is never NaN even if x is nan
+
+ // It is too costly to keep the index of the min here. We will look for it again later. We save a lot of work this way.
+ }
+
+ // If we found a new min
+ if( 0xf != _mm_movemask_ps( (float4) _mm_cmpeq_ps(min, dotmin)))
+ {
+ // copy the new min across all lanes of our min accumulator
+ min = _mm_min_ps(min, (float4) _mm_shuffle_ps( min, min, 0x4e));
+ min = _mm_min_ps(min, (float4) _mm_shuffle_ps( min, min, 0xb1));
+
+ dotmin = min;
+
+ // find first occurrence of that min
+ size_t test;
+ for( index = 0; 0 == (test=_mm_movemask_ps( _mm_cmpeq_ps( stack_array[index], min))); index++ ) // local_count must be a multiple of 4
+ {}
+ // record where it is.
+ minIndex = 4*index + segment + indexTable[test];
+ }
+ }
+
+ // account for work we've already done
+ count -= segment;
+
+ // Deal with the last < STACK_ARRAY_COUNT vectors
+ min = dotmin;
+ index = 0;
+
+
+ if(btUnlikely( count > 16) )
+ {
+ for( ; index + 4 <= count / 4; index+=4 )
+ { // do four dot products at a time. Carefully avoid touching the w element.
+ float4 v0 = vertices[0];
+ float4 v1 = vertices[1];
+ float4 v2 = vertices[2];
+ float4 v3 = vertices[3]; vertices += 4;
+
+ float4 lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
+ float4 hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
+ float4 lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
+ float4 hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
+
+ lo0 = lo0*vLo;
+ lo1 = lo1*vLo;
+ float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z*vHi;
+ x = x+y;
+ x = x+z;
+ stack_array[index] = x;
+ min = _mm_min_ps( x, min ); // control the order here so that min is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3]; vertices += 4;
+
+ lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
+
+ lo0 = lo0*vLo;
+ lo1 = lo1*vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z*vHi;
+ x = x+y;
+ x = x+z;
+ stack_array[index+1] = x;
+ min = _mm_min_ps( x, min ); // control the order here so that min is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3]; vertices += 4;
+
+ lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
+
+ lo0 = lo0*vLo;
+ lo1 = lo1*vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z*vHi;
+ x = x+y;
+ x = x+z;
+ stack_array[index+2] = x;
+ min = _mm_min_ps( x, min ); // control the order here so that min is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3]; vertices += 4;
+
+ lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
+
+ lo0 = lo0*vLo;
+ lo1 = lo1*vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z*vHi;
+ x = x+y;
+ x = x+z;
+ stack_array[index+3] = x;
+ min = _mm_min_ps( x, min ); // control the order here so that min is never NaN even if x is nan
+
+ // It is too costly to keep the index of the min here. We will look for it again later. We save a lot of work this way.
+ }
+ }
+
+ size_t localCount = (count & -4L) - 4*index;
+ if( localCount )
+ {
+
+
+#ifdef __APPLE__
+ vertices += localCount; // counter the offset
+ float4 t0, t1, t2, t3, t4;
+ size_t byteIndex = -(localCount) * sizeof(float);
+ float4 * sap = &stack_array[index + localCount / 4];
+
+ asm volatile
+ ( ".align 4 \n\
+ 0: movaps %[min], %[t2] // move min out of the way to avoid propagating NaNs in min \n\
+ movaps (%[vertices], %[byteIndex], 4), %[t0] // vertices[0] \n\
+ movaps 16(%[vertices], %[byteIndex], 4), %[t1] // vertices[1] \n\
+ movaps %[t0], %[min] // vertices[0] \n\
+ movlhps %[t1], %[min] // x0y0x1y1 \n\
+ movaps 32(%[vertices], %[byteIndex], 4), %[t3] // vertices[2] \n\
+ movaps 48(%[vertices], %[byteIndex], 4), %[t4] // vertices[3] \n\
+ mulps %[vLo], %[min] // x0y0x1y1 * vLo \n\
+ movhlps %[t0], %[t1] // z0w0z1w1 \n\
+ movaps %[t3], %[t0] // vertices[2] \n\
+ movlhps %[t4], %[t0] // x2y2x3y3 \n\
+ movhlps %[t3], %[t4] // z2w2z3w3 \n\
+ mulps %[vLo], %[t0] // x2y2x3y3 * vLo \n\
+ shufps $0x88, %[t4], %[t1] // z0z1z2z3 \n\
+ mulps %[vHi], %[t1] // z0z1z2z3 * vHi \n\
+ movaps %[min], %[t3] // x0y0x1y1 * vLo \n\
+ shufps $0x88, %[t0], %[min] // x0x1x2x3 * vLo.x \n\
+ shufps $0xdd, %[t0], %[t3] // y0y1y2y3 * vLo.y \n\
+ addps %[t3], %[min] // x + y \n\
+ addps %[t1], %[min] // x + y + z \n\
+ movaps %[min], (%[sap], %[byteIndex]) // record result for later scrutiny \n\
+ minps %[t2], %[min] // record min, restore min \n\
+ add $16, %[byteIndex] // advance loop counter\n\
+ jnz 0b \n\
+ "
+ : [min] "+x" (min), [t0] "=&x" (t0), [t1] "=&x" (t1), [t2] "=&x" (t2), [t3] "=&x" (t3), [t4] "=&x" (t4), [byteIndex] "+r" (byteIndex)
+ : [vLo] "x" (vLo), [vHi] "x" (vHi), [vertices] "r" (vertices), [sap] "r" (sap)
+ : "memory", "cc"
+ );
+ index += localCount/4;
+#else
+ {
+ for( unsigned int i=0; i<localCount/4; i++,index++)
+ { // do four dot products at a time. Carefully avoid touching the w element.
+ float4 v0 = vertices[0];
+ float4 v1 = vertices[1];
+ float4 v2 = vertices[2];
+ float4 v3 = vertices[3];
+ vertices += 4;
+
+ float4 lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
+ float4 hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
+ float4 lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
+ float4 hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
+
+ lo0 = lo0*vLo;
+ lo1 = lo1*vLo;
+ float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z*vHi;
+ x = x+y;
+ x = x+z;
+ stack_array[index] = x;
+ min = _mm_min_ps( x, min ); // control the order here so that max is never NaN even if x is nan
+ }
+ }
+
+#endif
+ }
+
+ // process the last few points
+ if( count & 3 )
+ {
+ float4 v0, v1, v2, x, y, z;
+ switch( count & 3 )
+ {
+ case 3:
+ {
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+
+ // Calculate 3 dot products, transpose, duplicate v2
+ float4 lo0 = _mm_movelh_ps( v0, v1); // xyxy.lo
+ float4 hi0 = _mm_movehl_ps( v1, v0); // z?z?.lo
+ lo0 = lo0*vLo;
+ z = _mm_shuffle_ps(hi0, v2, 0xa8 ); // z0z1z2z2
+ z = z*vHi;
+ float4 lo1 = _mm_movelh_ps(v2, v2); // xyxy
+ lo1 = lo1*vLo;
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ }
+ break;
+ case 2:
+ {
+ v0 = vertices[0];
+ v1 = vertices[1];
+ float4 xy = _mm_movelh_ps(v0, v1);
+ z = _mm_movehl_ps(v1, v0);
+ xy = xy*vLo;
+ z = _mm_shuffle_ps( z, z, 0xa8);
+ x = _mm_shuffle_ps( xy, xy, 0xa8);
+ y = _mm_shuffle_ps( xy, xy, 0xfd);
+ z = z*vHi;
+ }
+ break;
+ case 1:
+ {
+ float4 xy = vertices[0];
+ z = _mm_shuffle_ps( xy, xy, 0xaa);
+ xy = xy*vLo;
+ z = z*vHi;
+ x = _mm_shuffle_ps(xy, xy, 0);
+ y = _mm_shuffle_ps(xy, xy, 0x55);
+ }
+ break;
+ }
+ x = x+y;
+ x = x+z;
+ stack_array[index] = x;
+ min = _mm_min_ps( x, min ); // control the order here so that min is never NaN even if x is nan
+ index++;
+ }
+
+ // if we found a new min.
+ if( 0 == segment || 0xf != _mm_movemask_ps( (float4) _mm_cmpeq_ps(min, dotmin)))
+ { // we found a new min. Search for it
+ // find min across the min vector, place in all elements of min -- big latency hit here
+ min = _mm_min_ps(min, (float4) _mm_shuffle_ps( min, min, 0x4e));
+ min = _mm_min_ps(min, (float4) _mm_shuffle_ps( min, min, 0xb1));
+
+ // It is slightly faster to do this part in scalar code when count < 8. However, the common case for
+ // this where it actually makes a difference is handled in the early out at the top of the function,
+ // so it is less than a 1% difference here. I opted for improved code size, fewer branches and reduced
+ // complexity, and removed it.
+
+ dotmin = min;
+
+ // scan for the first occurence of min in the array
+ size_t test;
+ for( index = 0; 0 == (test=_mm_movemask_ps( _mm_cmpeq_ps( stack_array[index], min))); index++ ) // local_count must be a multiple of 4
+ {}
+ minIndex = 4*index + segment + indexTable[test];
+ }
+
+ _mm_store_ss( dotResult, dotmin);
+ return minIndex;
+}
+
+
+#elif defined BT_USE_NEON
+
+#define ARM_NEON_GCC_COMPATIBILITY 1
+#include <arm_neon.h>
+#include <sys/types.h>
+#include <sys/sysctl.h> //for sysctlbyname
+
+static long _maxdot_large_v0( const float *vv, const float *vec, unsigned long count, float *dotResult );
+static long _maxdot_large_v1( const float *vv, const float *vec, unsigned long count, float *dotResult );
+static long _maxdot_large_sel( const float *vv, const float *vec, unsigned long count, float *dotResult );
+static long _mindot_large_v0( const float *vv, const float *vec, unsigned long count, float *dotResult );
+static long _mindot_large_v1( const float *vv, const float *vec, unsigned long count, float *dotResult );
+static long _mindot_large_sel( const float *vv, const float *vec, unsigned long count, float *dotResult );
+
+long (*_maxdot_large)( const float *vv, const float *vec, unsigned long count, float *dotResult ) = _maxdot_large_sel;
+long (*_mindot_large)( const float *vv, const float *vec, unsigned long count, float *dotResult ) = _mindot_large_sel;
+
+
+static inline uint32_t btGetCpuCapabilities( void )
+{
+ static uint32_t capabilities = 0;
+ static bool testedCapabilities = false;
+
+ if( 0 == testedCapabilities)
+ {
+ uint32_t hasFeature = 0;
+ size_t featureSize = sizeof( hasFeature );
+ int err = sysctlbyname( "hw.optional.neon_hpfp", &hasFeature, &featureSize, NULL, 0 );
+
+ if( 0 == err && hasFeature)
+ capabilities |= 0x2000;
+
+ testedCapabilities = true;
+ }
+
+ return capabilities;
+}
+
+
+
+
+static long _maxdot_large_sel( const float *vv, const float *vec, unsigned long count, float *dotResult )
+{
+
+ if( btGetCpuCapabilities() & 0x2000 )
+ _maxdot_large = _maxdot_large_v1;
+ else
+ _maxdot_large = _maxdot_large_v0;
+
+ return _maxdot_large(vv, vec, count, dotResult);
+}
+
+static long _mindot_large_sel( const float *vv, const float *vec, unsigned long count, float *dotResult )
+{
+
+ if( btGetCpuCapabilities() & 0x2000 )
+ _mindot_large = _mindot_large_v1;
+ else
+ _mindot_large = _mindot_large_v0;
+
+ return _mindot_large(vv, vec, count, dotResult);
+}
+
+
+
+#if defined __arm__
+# define vld1q_f32_aligned_postincrement( _ptr ) ({ float32x4_t _r; asm( "vld1.f32 {%0}, [%1, :128]!\n" : "=w" (_r), "+r" (_ptr) ); /*return*/ _r; })
+#else
+//support 64bit arm
+# define vld1q_f32_aligned_postincrement( _ptr) ({ float32x4_t _r = ((float32x4_t*)(_ptr))[0]; (_ptr) = (const float*) ((const char*)(_ptr) + 16L); /*return*/ _r; })
+#endif
+
+
+long _maxdot_large_v0( const float *vv, const float *vec, unsigned long count, float *dotResult )
+{
+ unsigned long i = 0;
+ float32x4_t vvec = vld1q_f32_aligned_postincrement( vec );
+ float32x2_t vLo = vget_low_f32(vvec);
+ float32x2_t vHi = vdup_lane_f32(vget_high_f32(vvec), 0);
+ float32x2_t dotMaxLo = (float32x2_t) { -BT_INFINITY, -BT_INFINITY };
+ float32x2_t dotMaxHi = (float32x2_t) { -BT_INFINITY, -BT_INFINITY };
+ uint32x2_t indexLo = (uint32x2_t) {0, 1};
+ uint32x2_t indexHi = (uint32x2_t) {2, 3};
+ uint32x2_t iLo = (uint32x2_t) {static_cast<uint32_t>(-1), static_cast<uint32_t>(-1)};
+ uint32x2_t iHi = (uint32x2_t) {static_cast<uint32_t>(-1), static_cast<uint32_t>(-1)};
+ const uint32x2_t four = (uint32x2_t) {4,4};
+
+ for( ; i+8 <= count; i+= 8 )
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v3 = vld1q_f32_aligned_postincrement( vv );
+
+ float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo);
+ float32x2_t xy1 = vmul_f32( vget_low_f32(v1), vLo);
+ float32x2_t xy2 = vmul_f32( vget_low_f32(v2), vLo);
+ float32x2_t xy3 = vmul_f32( vget_low_f32(v3), vLo);
+
+ float32x2x2_t z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1));
+ float32x2x2_t z1 = vtrn_f32( vget_high_f32(v2), vget_high_f32(v3));
+ float32x2_t zLo = vmul_f32( z0.val[0], vHi);
+ float32x2_t zHi = vmul_f32( z1.val[0], vHi);
+
+ float32x2_t rLo = vpadd_f32( xy0, xy1);
+ float32x2_t rHi = vpadd_f32( xy2, xy3);
+ rLo = vadd_f32(rLo, zLo);
+ rHi = vadd_f32(rHi, zHi);
+
+ uint32x2_t maskLo = vcgt_f32( rLo, dotMaxLo );
+ uint32x2_t maskHi = vcgt_f32( rHi, dotMaxHi );
+ dotMaxLo = vbsl_f32( maskLo, rLo, dotMaxLo);
+ dotMaxHi = vbsl_f32( maskHi, rHi, dotMaxHi);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ iHi = vbsl_u32(maskHi, indexHi, iHi);
+ indexLo = vadd_u32(indexLo, four);
+ indexHi = vadd_u32(indexHi, four);
+
+ v0 = vld1q_f32_aligned_postincrement( vv );
+ v1 = vld1q_f32_aligned_postincrement( vv );
+ v2 = vld1q_f32_aligned_postincrement( vv );
+ v3 = vld1q_f32_aligned_postincrement( vv );
+
+ xy0 = vmul_f32( vget_low_f32(v0), vLo);
+ xy1 = vmul_f32( vget_low_f32(v1), vLo);
+ xy2 = vmul_f32( vget_low_f32(v2), vLo);
+ xy3 = vmul_f32( vget_low_f32(v3), vLo);
+
+ z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1));
+ z1 = vtrn_f32( vget_high_f32(v2), vget_high_f32(v3));
+ zLo = vmul_f32( z0.val[0], vHi);
+ zHi = vmul_f32( z1.val[0], vHi);
+
+ rLo = vpadd_f32( xy0, xy1);
+ rHi = vpadd_f32( xy2, xy3);
+ rLo = vadd_f32(rLo, zLo);
+ rHi = vadd_f32(rHi, zHi);
+
+ maskLo = vcgt_f32( rLo, dotMaxLo );
+ maskHi = vcgt_f32( rHi, dotMaxHi );
+ dotMaxLo = vbsl_f32( maskLo, rLo, dotMaxLo);
+ dotMaxHi = vbsl_f32( maskHi, rHi, dotMaxHi);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ iHi = vbsl_u32(maskHi, indexHi, iHi);
+ indexLo = vadd_u32(indexLo, four);
+ indexHi = vadd_u32(indexHi, four);
+ }
+
+ for( ; i+4 <= count; i+= 4 )
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v3 = vld1q_f32_aligned_postincrement( vv );
+
+ float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo);
+ float32x2_t xy1 = vmul_f32( vget_low_f32(v1), vLo);
+ float32x2_t xy2 = vmul_f32( vget_low_f32(v2), vLo);
+ float32x2_t xy3 = vmul_f32( vget_low_f32(v3), vLo);
+
+ float32x2x2_t z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1));
+ float32x2x2_t z1 = vtrn_f32( vget_high_f32(v2), vget_high_f32(v3));
+ float32x2_t zLo = vmul_f32( z0.val[0], vHi);
+ float32x2_t zHi = vmul_f32( z1.val[0], vHi);
+
+ float32x2_t rLo = vpadd_f32( xy0, xy1);
+ float32x2_t rHi = vpadd_f32( xy2, xy3);
+ rLo = vadd_f32(rLo, zLo);
+ rHi = vadd_f32(rHi, zHi);
+
+ uint32x2_t maskLo = vcgt_f32( rLo, dotMaxLo );
+ uint32x2_t maskHi = vcgt_f32( rHi, dotMaxHi );
+ dotMaxLo = vbsl_f32( maskLo, rLo, dotMaxLo);
+ dotMaxHi = vbsl_f32( maskHi, rHi, dotMaxHi);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ iHi = vbsl_u32(maskHi, indexHi, iHi);
+ indexLo = vadd_u32(indexLo, four);
+ indexHi = vadd_u32(indexHi, four);
+ }
+
+ switch( count & 3 )
+ {
+ case 3:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
+
+ float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo);
+ float32x2_t xy1 = vmul_f32( vget_low_f32(v1), vLo);
+ float32x2_t xy2 = vmul_f32( vget_low_f32(v2), vLo);
+
+ float32x2x2_t z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1));
+ float32x2_t zLo = vmul_f32( z0.val[0], vHi);
+ float32x2_t zHi = vmul_f32( vdup_lane_f32(vget_high_f32(v2), 0), vHi);
+
+ float32x2_t rLo = vpadd_f32( xy0, xy1);
+ float32x2_t rHi = vpadd_f32( xy2, xy2);
+ rLo = vadd_f32(rLo, zLo);
+ rHi = vadd_f32(rHi, zHi);
+
+ uint32x2_t maskLo = vcgt_f32( rLo, dotMaxLo );
+ uint32x2_t maskHi = vcgt_f32( rHi, dotMaxHi );
+ dotMaxLo = vbsl_f32( maskLo, rLo, dotMaxLo);
+ dotMaxHi = vbsl_f32( maskHi, rHi, dotMaxHi);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ iHi = vbsl_u32(maskHi, indexHi, iHi);
+ }
+ break;
+ case 2:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
+
+ float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo);
+ float32x2_t xy1 = vmul_f32( vget_low_f32(v1), vLo);
+
+ float32x2x2_t z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1));
+ float32x2_t zLo = vmul_f32( z0.val[0], vHi);
+
+ float32x2_t rLo = vpadd_f32( xy0, xy1);
+ rLo = vadd_f32(rLo, zLo);
+
+ uint32x2_t maskLo = vcgt_f32( rLo, dotMaxLo );
+ dotMaxLo = vbsl_f32( maskLo, rLo, dotMaxLo);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ }
+ break;
+ case 1:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+ float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo);
+ float32x2_t z0 = vdup_lane_f32(vget_high_f32(v0), 0);
+ float32x2_t zLo = vmul_f32( z0, vHi);
+ float32x2_t rLo = vpadd_f32( xy0, xy0);
+ rLo = vadd_f32(rLo, zLo);
+ uint32x2_t maskLo = vcgt_f32( rLo, dotMaxLo );
+ dotMaxLo = vbsl_f32( maskLo, rLo, dotMaxLo);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ // select best answer between hi and lo results
+ uint32x2_t mask = vcgt_f32( dotMaxHi, dotMaxLo );
+ dotMaxLo = vbsl_f32(mask, dotMaxHi, dotMaxLo);
+ iLo = vbsl_u32(mask, iHi, iLo);
+
+ // select best answer between even and odd results
+ dotMaxHi = vdup_lane_f32(dotMaxLo, 1);
+ iHi = vdup_lane_u32(iLo, 1);
+ mask = vcgt_f32( dotMaxHi, dotMaxLo );
+ dotMaxLo = vbsl_f32(mask, dotMaxHi, dotMaxLo);
+ iLo = vbsl_u32(mask, iHi, iLo);
+
+ *dotResult = vget_lane_f32( dotMaxLo, 0);
+ return vget_lane_u32(iLo, 0);
+}
+
+
+long _maxdot_large_v1( const float *vv, const float *vec, unsigned long count, float *dotResult )
+{
+ float32x4_t vvec = vld1q_f32_aligned_postincrement( vec );
+ float32x4_t vLo = vcombine_f32(vget_low_f32(vvec), vget_low_f32(vvec));
+ float32x4_t vHi = vdupq_lane_f32(vget_high_f32(vvec), 0);
+ const uint32x4_t four = (uint32x4_t){ 4, 4, 4, 4 };
+ uint32x4_t local_index = (uint32x4_t) {0, 1, 2, 3};
+ uint32x4_t index = (uint32x4_t) { static_cast<uint32_t>(-1), static_cast<uint32_t>(-1), static_cast<uint32_t>(-1), static_cast<uint32_t>(-1) };
+ float32x4_t maxDot = (float32x4_t) { -BT_INFINITY, -BT_INFINITY, -BT_INFINITY, -BT_INFINITY };
+
+ unsigned long i = 0;
+ for( ; i + 8 <= count; i += 8 )
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v3 = vld1q_f32_aligned_postincrement( vv );
+
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1));
+ float32x4_t xy1 = vcombine_f32( vget_low_f32(v2), vget_low_f32(v3));
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1));
+ float32x4_t z1 = vcombine_f32( vget_high_f32(v2), vget_high_f32(v3));
+
+ xy0 = vmulq_f32(xy0, vLo);
+ xy1 = vmulq_f32(xy1, vLo);
+
+ float32x4x2_t zb = vuzpq_f32( z0, z1);
+ float32x4_t z = vmulq_f32( zb.val[0], vHi);
+ float32x4x2_t xy = vuzpq_f32( xy0, xy1);
+ float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ uint32x4_t mask = vcgtq_f32(x, maxDot);
+ maxDot = vbslq_f32( mask, x, maxDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+
+ v0 = vld1q_f32_aligned_postincrement( vv );
+ v1 = vld1q_f32_aligned_postincrement( vv );
+ v2 = vld1q_f32_aligned_postincrement( vv );
+ v3 = vld1q_f32_aligned_postincrement( vv );
+
+ // the next two lines should resolve to a single vswp d, d
+ xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1));
+ xy1 = vcombine_f32( vget_low_f32(v2), vget_low_f32(v3));
+ // the next two lines should resolve to a single vswp d, d
+ z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1));
+ z1 = vcombine_f32( vget_high_f32(v2), vget_high_f32(v3));
+
+ xy0 = vmulq_f32(xy0, vLo);
+ xy1 = vmulq_f32(xy1, vLo);
+
+ zb = vuzpq_f32( z0, z1);
+ z = vmulq_f32( zb.val[0], vHi);
+ xy = vuzpq_f32( xy0, xy1);
+ x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ mask = vcgtq_f32(x, maxDot);
+ maxDot = vbslq_f32( mask, x, maxDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+ }
+
+ for( ; i + 4 <= count; i += 4 )
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v3 = vld1q_f32_aligned_postincrement( vv );
+
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1));
+ float32x4_t xy1 = vcombine_f32( vget_low_f32(v2), vget_low_f32(v3));
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1));
+ float32x4_t z1 = vcombine_f32( vget_high_f32(v2), vget_high_f32(v3));
+
+ xy0 = vmulq_f32(xy0, vLo);
+ xy1 = vmulq_f32(xy1, vLo);
+
+ float32x4x2_t zb = vuzpq_f32( z0, z1);
+ float32x4_t z = vmulq_f32( zb.val[0], vHi);
+ float32x4x2_t xy = vuzpq_f32( xy0, xy1);
+ float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ uint32x4_t mask = vcgtq_f32(x, maxDot);
+ maxDot = vbslq_f32( mask, x, maxDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+ }
+
+ switch (count & 3) {
+ case 3:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
+
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1));
+ float32x4_t xy1 = vcombine_f32( vget_low_f32(v2), vget_low_f32(v2));
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1));
+ float32x4_t z1 = vcombine_f32( vget_high_f32(v2), vget_high_f32(v2));
+
+ xy0 = vmulq_f32(xy0, vLo);
+ xy1 = vmulq_f32(xy1, vLo);
+
+ float32x4x2_t zb = vuzpq_f32( z0, z1);
+ float32x4_t z = vmulq_f32( zb.val[0], vHi);
+ float32x4x2_t xy = vuzpq_f32( xy0, xy1);
+ float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ uint32x4_t mask = vcgtq_f32(x, maxDot);
+ maxDot = vbslq_f32( mask, x, maxDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+ }
+ break;
+
+ case 2:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
+
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1));
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1));
+
+ xy0 = vmulq_f32(xy0, vLo);
+
+ float32x4x2_t zb = vuzpq_f32( z0, z0);
+ float32x4_t z = vmulq_f32( zb.val[0], vHi);
+ float32x4x2_t xy = vuzpq_f32( xy0, xy0);
+ float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ uint32x4_t mask = vcgtq_f32(x, maxDot);
+ maxDot = vbslq_f32( mask, x, maxDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+ }
+ break;
+
+ case 1:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v0));
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t z = vdupq_lane_f32(vget_high_f32(v0), 0);
+
+ xy0 = vmulq_f32(xy0, vLo);
+
+ z = vmulq_f32( z, vHi);
+ float32x4x2_t xy = vuzpq_f32( xy0, xy0);
+ float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ uint32x4_t mask = vcgtq_f32(x, maxDot);
+ maxDot = vbslq_f32( mask, x, maxDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+
+ // select best answer between hi and lo results
+ uint32x2_t mask = vcgt_f32( vget_high_f32(maxDot), vget_low_f32(maxDot));
+ float32x2_t maxDot2 = vbsl_f32(mask, vget_high_f32(maxDot), vget_low_f32(maxDot));
+ uint32x2_t index2 = vbsl_u32(mask, vget_high_u32(index), vget_low_u32(index));
+
+ // select best answer between even and odd results
+ float32x2_t maxDotO = vdup_lane_f32(maxDot2, 1);
+ uint32x2_t indexHi = vdup_lane_u32(index2, 1);
+ mask = vcgt_f32( maxDotO, maxDot2 );
+ maxDot2 = vbsl_f32(mask, maxDotO, maxDot2);
+ index2 = vbsl_u32(mask, indexHi, index2);
+
+ *dotResult = vget_lane_f32( maxDot2, 0);
+ return vget_lane_u32(index2, 0);
+
+}
+
+long _mindot_large_v0( const float *vv, const float *vec, unsigned long count, float *dotResult )
+{
+ unsigned long i = 0;
+ float32x4_t vvec = vld1q_f32_aligned_postincrement( vec );
+ float32x2_t vLo = vget_low_f32(vvec);
+ float32x2_t vHi = vdup_lane_f32(vget_high_f32(vvec), 0);
+ float32x2_t dotMinLo = (float32x2_t) { BT_INFINITY, BT_INFINITY };
+ float32x2_t dotMinHi = (float32x2_t) { BT_INFINITY, BT_INFINITY };
+ uint32x2_t indexLo = (uint32x2_t) {0, 1};
+ uint32x2_t indexHi = (uint32x2_t) {2, 3};
+ uint32x2_t iLo = (uint32x2_t) {static_cast<uint32_t>(-1), static_cast<uint32_t>(-1)};
+ uint32x2_t iHi = (uint32x2_t) {static_cast<uint32_t>(-1), static_cast<uint32_t>(-1)};
+ const uint32x2_t four = (uint32x2_t) {4,4};
+
+ for( ; i+8 <= count; i+= 8 )
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v3 = vld1q_f32_aligned_postincrement( vv );
+
+ float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo);
+ float32x2_t xy1 = vmul_f32( vget_low_f32(v1), vLo);
+ float32x2_t xy2 = vmul_f32( vget_low_f32(v2), vLo);
+ float32x2_t xy3 = vmul_f32( vget_low_f32(v3), vLo);
+
+ float32x2x2_t z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1));
+ float32x2x2_t z1 = vtrn_f32( vget_high_f32(v2), vget_high_f32(v3));
+ float32x2_t zLo = vmul_f32( z0.val[0], vHi);
+ float32x2_t zHi = vmul_f32( z1.val[0], vHi);
+
+ float32x2_t rLo = vpadd_f32( xy0, xy1);
+ float32x2_t rHi = vpadd_f32( xy2, xy3);
+ rLo = vadd_f32(rLo, zLo);
+ rHi = vadd_f32(rHi, zHi);
+
+ uint32x2_t maskLo = vclt_f32( rLo, dotMinLo );
+ uint32x2_t maskHi = vclt_f32( rHi, dotMinHi );
+ dotMinLo = vbsl_f32( maskLo, rLo, dotMinLo);
+ dotMinHi = vbsl_f32( maskHi, rHi, dotMinHi);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ iHi = vbsl_u32(maskHi, indexHi, iHi);
+ indexLo = vadd_u32(indexLo, four);
+ indexHi = vadd_u32(indexHi, four);
+
+ v0 = vld1q_f32_aligned_postincrement( vv );
+ v1 = vld1q_f32_aligned_postincrement( vv );
+ v2 = vld1q_f32_aligned_postincrement( vv );
+ v3 = vld1q_f32_aligned_postincrement( vv );
+
+ xy0 = vmul_f32( vget_low_f32(v0), vLo);
+ xy1 = vmul_f32( vget_low_f32(v1), vLo);
+ xy2 = vmul_f32( vget_low_f32(v2), vLo);
+ xy3 = vmul_f32( vget_low_f32(v3), vLo);
+
+ z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1));
+ z1 = vtrn_f32( vget_high_f32(v2), vget_high_f32(v3));
+ zLo = vmul_f32( z0.val[0], vHi);
+ zHi = vmul_f32( z1.val[0], vHi);
+
+ rLo = vpadd_f32( xy0, xy1);
+ rHi = vpadd_f32( xy2, xy3);
+ rLo = vadd_f32(rLo, zLo);
+ rHi = vadd_f32(rHi, zHi);
+
+ maskLo = vclt_f32( rLo, dotMinLo );
+ maskHi = vclt_f32( rHi, dotMinHi );
+ dotMinLo = vbsl_f32( maskLo, rLo, dotMinLo);
+ dotMinHi = vbsl_f32( maskHi, rHi, dotMinHi);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ iHi = vbsl_u32(maskHi, indexHi, iHi);
+ indexLo = vadd_u32(indexLo, four);
+ indexHi = vadd_u32(indexHi, four);
+ }
+
+ for( ; i+4 <= count; i+= 4 )
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v3 = vld1q_f32_aligned_postincrement( vv );
+
+ float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo);
+ float32x2_t xy1 = vmul_f32( vget_low_f32(v1), vLo);
+ float32x2_t xy2 = vmul_f32( vget_low_f32(v2), vLo);
+ float32x2_t xy3 = vmul_f32( vget_low_f32(v3), vLo);
+
+ float32x2x2_t z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1));
+ float32x2x2_t z1 = vtrn_f32( vget_high_f32(v2), vget_high_f32(v3));
+ float32x2_t zLo = vmul_f32( z0.val[0], vHi);
+ float32x2_t zHi = vmul_f32( z1.val[0], vHi);
+
+ float32x2_t rLo = vpadd_f32( xy0, xy1);
+ float32x2_t rHi = vpadd_f32( xy2, xy3);
+ rLo = vadd_f32(rLo, zLo);
+ rHi = vadd_f32(rHi, zHi);
+
+ uint32x2_t maskLo = vclt_f32( rLo, dotMinLo );
+ uint32x2_t maskHi = vclt_f32( rHi, dotMinHi );
+ dotMinLo = vbsl_f32( maskLo, rLo, dotMinLo);
+ dotMinHi = vbsl_f32( maskHi, rHi, dotMinHi);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ iHi = vbsl_u32(maskHi, indexHi, iHi);
+ indexLo = vadd_u32(indexLo, four);
+ indexHi = vadd_u32(indexHi, four);
+ }
+ switch( count & 3 )
+ {
+ case 3:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
+
+ float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo);
+ float32x2_t xy1 = vmul_f32( vget_low_f32(v1), vLo);
+ float32x2_t xy2 = vmul_f32( vget_low_f32(v2), vLo);
+
+ float32x2x2_t z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1));
+ float32x2_t zLo = vmul_f32( z0.val[0], vHi);
+ float32x2_t zHi = vmul_f32( vdup_lane_f32(vget_high_f32(v2), 0), vHi);
+
+ float32x2_t rLo = vpadd_f32( xy0, xy1);
+ float32x2_t rHi = vpadd_f32( xy2, xy2);
+ rLo = vadd_f32(rLo, zLo);
+ rHi = vadd_f32(rHi, zHi);
+
+ uint32x2_t maskLo = vclt_f32( rLo, dotMinLo );
+ uint32x2_t maskHi = vclt_f32( rHi, dotMinHi );
+ dotMinLo = vbsl_f32( maskLo, rLo, dotMinLo);
+ dotMinHi = vbsl_f32( maskHi, rHi, dotMinHi);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ iHi = vbsl_u32(maskHi, indexHi, iHi);
+ }
+ break;
+ case 2:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
+
+ float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo);
+ float32x2_t xy1 = vmul_f32( vget_low_f32(v1), vLo);
+
+ float32x2x2_t z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1));
+ float32x2_t zLo = vmul_f32( z0.val[0], vHi);
+
+ float32x2_t rLo = vpadd_f32( xy0, xy1);
+ rLo = vadd_f32(rLo, zLo);
+
+ uint32x2_t maskLo = vclt_f32( rLo, dotMinLo );
+ dotMinLo = vbsl_f32( maskLo, rLo, dotMinLo);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ }
+ break;
+ case 1:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+ float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo);
+ float32x2_t z0 = vdup_lane_f32(vget_high_f32(v0), 0);
+ float32x2_t zLo = vmul_f32( z0, vHi);
+ float32x2_t rLo = vpadd_f32( xy0, xy0);
+ rLo = vadd_f32(rLo, zLo);
+ uint32x2_t maskLo = vclt_f32( rLo, dotMinLo );
+ dotMinLo = vbsl_f32( maskLo, rLo, dotMinLo);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ // select best answer between hi and lo results
+ uint32x2_t mask = vclt_f32( dotMinHi, dotMinLo );
+ dotMinLo = vbsl_f32(mask, dotMinHi, dotMinLo);
+ iLo = vbsl_u32(mask, iHi, iLo);
+
+ // select best answer between even and odd results
+ dotMinHi = vdup_lane_f32(dotMinLo, 1);
+ iHi = vdup_lane_u32(iLo, 1);
+ mask = vclt_f32( dotMinHi, dotMinLo );
+ dotMinLo = vbsl_f32(mask, dotMinHi, dotMinLo);
+ iLo = vbsl_u32(mask, iHi, iLo);
+
+ *dotResult = vget_lane_f32( dotMinLo, 0);
+ return vget_lane_u32(iLo, 0);
+}
+
+long _mindot_large_v1( const float *vv, const float *vec, unsigned long count, float *dotResult )
+{
+ float32x4_t vvec = vld1q_f32_aligned_postincrement( vec );
+ float32x4_t vLo = vcombine_f32(vget_low_f32(vvec), vget_low_f32(vvec));
+ float32x4_t vHi = vdupq_lane_f32(vget_high_f32(vvec), 0);
+ const uint32x4_t four = (uint32x4_t){ 4, 4, 4, 4 };
+ uint32x4_t local_index = (uint32x4_t) {0, 1, 2, 3};
+ uint32x4_t index = (uint32x4_t) { static_cast<uint32_t>(-1), static_cast<uint32_t>(-1), static_cast<uint32_t>(-1), static_cast<uint32_t>(-1) };
+ float32x4_t minDot = (float32x4_t) { BT_INFINITY, BT_INFINITY, BT_INFINITY, BT_INFINITY };
+
+ unsigned long i = 0;
+ for( ; i + 8 <= count; i += 8 )
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v3 = vld1q_f32_aligned_postincrement( vv );
+
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1));
+ float32x4_t xy1 = vcombine_f32( vget_low_f32(v2), vget_low_f32(v3));
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1));
+ float32x4_t z1 = vcombine_f32( vget_high_f32(v2), vget_high_f32(v3));
+
+ xy0 = vmulq_f32(xy0, vLo);
+ xy1 = vmulq_f32(xy1, vLo);
+
+ float32x4x2_t zb = vuzpq_f32( z0, z1);
+ float32x4_t z = vmulq_f32( zb.val[0], vHi);
+ float32x4x2_t xy = vuzpq_f32( xy0, xy1);
+ float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ uint32x4_t mask = vcltq_f32(x, minDot);
+ minDot = vbslq_f32( mask, x, minDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+
+ v0 = vld1q_f32_aligned_postincrement( vv );
+ v1 = vld1q_f32_aligned_postincrement( vv );
+ v2 = vld1q_f32_aligned_postincrement( vv );
+ v3 = vld1q_f32_aligned_postincrement( vv );
+
+ // the next two lines should resolve to a single vswp d, d
+ xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1));
+ xy1 = vcombine_f32( vget_low_f32(v2), vget_low_f32(v3));
+ // the next two lines should resolve to a single vswp d, d
+ z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1));
+ z1 = vcombine_f32( vget_high_f32(v2), vget_high_f32(v3));
+
+ xy0 = vmulq_f32(xy0, vLo);
+ xy1 = vmulq_f32(xy1, vLo);
+
+ zb = vuzpq_f32( z0, z1);
+ z = vmulq_f32( zb.val[0], vHi);
+ xy = vuzpq_f32( xy0, xy1);
+ x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ mask = vcltq_f32(x, minDot);
+ minDot = vbslq_f32( mask, x, minDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+ }
+
+ for( ; i + 4 <= count; i += 4 )
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v3 = vld1q_f32_aligned_postincrement( vv );
+
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1));
+ float32x4_t xy1 = vcombine_f32( vget_low_f32(v2), vget_low_f32(v3));
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1));
+ float32x4_t z1 = vcombine_f32( vget_high_f32(v2), vget_high_f32(v3));
+
+ xy0 = vmulq_f32(xy0, vLo);
+ xy1 = vmulq_f32(xy1, vLo);
+
+ float32x4x2_t zb = vuzpq_f32( z0, z1);
+ float32x4_t z = vmulq_f32( zb.val[0], vHi);
+ float32x4x2_t xy = vuzpq_f32( xy0, xy1);
+ float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ uint32x4_t mask = vcltq_f32(x, minDot);
+ minDot = vbslq_f32( mask, x, minDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+ }
+
+ switch (count & 3) {
+ case 3:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
+
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1));
+ float32x4_t xy1 = vcombine_f32( vget_low_f32(v2), vget_low_f32(v2));
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1));
+ float32x4_t z1 = vcombine_f32( vget_high_f32(v2), vget_high_f32(v2));
+
+ xy0 = vmulq_f32(xy0, vLo);
+ xy1 = vmulq_f32(xy1, vLo);
+
+ float32x4x2_t zb = vuzpq_f32( z0, z1);
+ float32x4_t z = vmulq_f32( zb.val[0], vHi);
+ float32x4x2_t xy = vuzpq_f32( xy0, xy1);
+ float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ uint32x4_t mask = vcltq_f32(x, minDot);
+ minDot = vbslq_f32( mask, x, minDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+ }
+ break;
+
+ case 2:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
+
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1));
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1));
+
+ xy0 = vmulq_f32(xy0, vLo);
+
+ float32x4x2_t zb = vuzpq_f32( z0, z0);
+ float32x4_t z = vmulq_f32( zb.val[0], vHi);
+ float32x4x2_t xy = vuzpq_f32( xy0, xy0);
+ float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ uint32x4_t mask = vcltq_f32(x, minDot);
+ minDot = vbslq_f32( mask, x, minDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+ }
+ break;
+
+ case 1:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v0));
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t z = vdupq_lane_f32(vget_high_f32(v0), 0);
+
+ xy0 = vmulq_f32(xy0, vLo);
+
+ z = vmulq_f32( z, vHi);
+ float32x4x2_t xy = vuzpq_f32( xy0, xy0);
+ float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ uint32x4_t mask = vcltq_f32(x, minDot);
+ minDot = vbslq_f32( mask, x, minDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+
+ // select best answer between hi and lo results
+ uint32x2_t mask = vclt_f32( vget_high_f32(minDot), vget_low_f32(minDot));
+ float32x2_t minDot2 = vbsl_f32(mask, vget_high_f32(minDot), vget_low_f32(minDot));
+ uint32x2_t index2 = vbsl_u32(mask, vget_high_u32(index), vget_low_u32(index));
+
+ // select best answer between even and odd results
+ float32x2_t minDotO = vdup_lane_f32(minDot2, 1);
+ uint32x2_t indexHi = vdup_lane_u32(index2, 1);
+ mask = vclt_f32( minDotO, minDot2 );
+ minDot2 = vbsl_f32(mask, minDotO, minDot2);
+ index2 = vbsl_u32(mask, indexHi, index2);
+
+ *dotResult = vget_lane_f32( minDot2, 0);
+ return vget_lane_u32(index2, 0);
+
+}
+
+#else
+ #error Unhandled __APPLE__ arch
+#endif
+
+#endif /* __APPLE__ */
+
+
diff --git a/thirdparty/bullet/src/LinearMath/btVector3.h b/thirdparty/bullet/src/LinearMath/btVector3.h
new file mode 100644
index 0000000000..c69effa96e
--- /dev/null
+++ b/thirdparty/bullet/src/LinearMath/btVector3.h
@@ -0,0 +1,1363 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+#ifndef BT_VECTOR3_H
+#define BT_VECTOR3_H
+
+//#include <stdint.h>
+#include "btScalar.h"
+#include "btMinMax.h"
+#include "btAlignedAllocator.h"
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define btVector3Data btVector3DoubleData
+#define btVector3DataName "btVector3DoubleData"
+#else
+#define btVector3Data btVector3FloatData
+#define btVector3DataName "btVector3FloatData"
+#endif //BT_USE_DOUBLE_PRECISION
+
+#if defined BT_USE_SSE
+
+//typedef uint32_t __m128i __attribute__ ((vector_size(16)));
+
+#ifdef _MSC_VER
+#pragma warning(disable: 4556) // value of intrinsic immediate argument '4294967239' is out of range '0 - 255'
+#endif
+
+
+#define BT_SHUFFLE(x,y,z,w) ((w)<<6 | (z)<<4 | (y)<<2 | (x))
+//#define bt_pshufd_ps( _a, _mask ) (__m128) _mm_shuffle_epi32((__m128i)(_a), (_mask) )
+#define bt_pshufd_ps( _a, _mask ) _mm_shuffle_ps((_a), (_a), (_mask) )
+#define bt_splat3_ps( _a, _i ) bt_pshufd_ps((_a), BT_SHUFFLE(_i,_i,_i, 3) )
+#define bt_splat_ps( _a, _i ) bt_pshufd_ps((_a), BT_SHUFFLE(_i,_i,_i,_i) )
+
+#define btv3AbsiMask (_mm_set_epi32(0x00000000, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF))
+#define btvAbsMask (_mm_set_epi32( 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF))
+#define btvFFF0Mask (_mm_set_epi32(0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF))
+#define btv3AbsfMask btCastiTo128f(btv3AbsiMask)
+#define btvFFF0fMask btCastiTo128f(btvFFF0Mask)
+#define btvxyzMaskf btvFFF0fMask
+#define btvAbsfMask btCastiTo128f(btvAbsMask)
+
+//there is an issue with XCode 3.2 (LCx errors)
+#define btvMzeroMask (_mm_set_ps(-0.0f, -0.0f, -0.0f, -0.0f))
+#define v1110 (_mm_set_ps(0.0f, 1.0f, 1.0f, 1.0f))
+#define vHalf (_mm_set_ps(0.5f, 0.5f, 0.5f, 0.5f))
+#define v1_5 (_mm_set_ps(1.5f, 1.5f, 1.5f, 1.5f))
+
+//const __m128 ATTRIBUTE_ALIGNED16(btvMzeroMask) = {-0.0f, -0.0f, -0.0f, -0.0f};
+//const __m128 ATTRIBUTE_ALIGNED16(v1110) = {1.0f, 1.0f, 1.0f, 0.0f};
+//const __m128 ATTRIBUTE_ALIGNED16(vHalf) = {0.5f, 0.5f, 0.5f, 0.5f};
+//const __m128 ATTRIBUTE_ALIGNED16(v1_5) = {1.5f, 1.5f, 1.5f, 1.5f};
+
+#endif
+
+#ifdef BT_USE_NEON
+
+const float32x4_t ATTRIBUTE_ALIGNED16(btvMzeroMask) = (float32x4_t){-0.0f, -0.0f, -0.0f, -0.0f};
+const int32x4_t ATTRIBUTE_ALIGNED16(btvFFF0Mask) = (int32x4_t){static_cast<int32_t>(0xFFFFFFFF),
+ static_cast<int32_t>(0xFFFFFFFF), static_cast<int32_t>(0xFFFFFFFF), 0x0};
+const int32x4_t ATTRIBUTE_ALIGNED16(btvAbsMask) = (int32x4_t){0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF};
+const int32x4_t ATTRIBUTE_ALIGNED16(btv3AbsMask) = (int32x4_t){0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x0};
+
+#endif
+
+/**@brief btVector3 can be used to represent 3D points and vectors.
+ * It has an un-used w component to suit 16-byte alignment when btVector3 is stored in containers. This extra component can be used by derived classes (Quaternion?) or by user
+ * Ideally, this class should be replaced by a platform optimized SIMD version that keeps the data in registers
+ */
+ATTRIBUTE_ALIGNED16(class) btVector3
+{
+public:
+
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+#if defined (__SPU__) && defined (__CELLOS_LV2__)
+ btScalar m_floats[4];
+public:
+ SIMD_FORCE_INLINE const vec_float4& get128() const
+ {
+ return *((const vec_float4*)&m_floats[0]);
+ }
+public:
+#else //__CELLOS_LV2__ __SPU__
+ #if defined (BT_USE_SSE) || defined(BT_USE_NEON) // _WIN32 || ARM
+ union {
+ btSimdFloat4 mVec128;
+ btScalar m_floats[4];
+ };
+ SIMD_FORCE_INLINE btSimdFloat4 get128() const
+ {
+ return mVec128;
+ }
+ SIMD_FORCE_INLINE void set128(btSimdFloat4 v128)
+ {
+ mVec128 = v128;
+ }
+ #else
+ btScalar m_floats[4];
+ #endif
+#endif //__CELLOS_LV2__ __SPU__
+
+ public:
+
+ /**@brief No initialization constructor */
+ SIMD_FORCE_INLINE btVector3()
+ {
+
+ }
+
+
+
+ /**@brief Constructor from scalars
+ * @param x X value
+ * @param y Y value
+ * @param z Z value
+ */
+ SIMD_FORCE_INLINE btVector3(const btScalar& _x, const btScalar& _y, const btScalar& _z)
+ {
+ m_floats[0] = _x;
+ m_floats[1] = _y;
+ m_floats[2] = _z;
+ m_floats[3] = btScalar(0.f);
+ }
+
+#if (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE) )|| defined (BT_USE_NEON)
+ // Set Vector
+ SIMD_FORCE_INLINE btVector3( btSimdFloat4 v)
+ {
+ mVec128 = v;
+ }
+
+ // Copy constructor
+ SIMD_FORCE_INLINE btVector3(const btVector3& rhs)
+ {
+ mVec128 = rhs.mVec128;
+ }
+
+ // Assignment Operator
+ SIMD_FORCE_INLINE btVector3&
+ operator=(const btVector3& v)
+ {
+ mVec128 = v.mVec128;
+
+ return *this;
+ }
+#endif // #if defined (BT_USE_SSE_IN_API) || defined (BT_USE_NEON)
+
+/**@brief Add a vector to this one
+ * @param The vector to add to this one */
+ SIMD_FORCE_INLINE btVector3& operator+=(const btVector3& v)
+ {
+#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ mVec128 = _mm_add_ps(mVec128, v.mVec128);
+#elif defined(BT_USE_NEON)
+ mVec128 = vaddq_f32(mVec128, v.mVec128);
+#else
+ m_floats[0] += v.m_floats[0];
+ m_floats[1] += v.m_floats[1];
+ m_floats[2] += v.m_floats[2];
+#endif
+ return *this;
+ }
+
+
+ /**@brief Subtract a vector from this one
+ * @param The vector to subtract */
+ SIMD_FORCE_INLINE btVector3& operator-=(const btVector3& v)
+ {
+#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ mVec128 = _mm_sub_ps(mVec128, v.mVec128);
+#elif defined(BT_USE_NEON)
+ mVec128 = vsubq_f32(mVec128, v.mVec128);
+#else
+ m_floats[0] -= v.m_floats[0];
+ m_floats[1] -= v.m_floats[1];
+ m_floats[2] -= v.m_floats[2];
+#endif
+ return *this;
+ }
+
+ /**@brief Scale the vector
+ * @param s Scale factor */
+ SIMD_FORCE_INLINE btVector3& operator*=(const btScalar& s)
+ {
+#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ __m128 vs = _mm_load_ss(&s); // (S 0 0 0)
+ vs = bt_pshufd_ps(vs, 0x80); // (S S S 0.0)
+ mVec128 = _mm_mul_ps(mVec128, vs);
+#elif defined(BT_USE_NEON)
+ mVec128 = vmulq_n_f32(mVec128, s);
+#else
+ m_floats[0] *= s;
+ m_floats[1] *= s;
+ m_floats[2] *= s;
+#endif
+ return *this;
+ }
+
+ /**@brief Inversely scale the vector
+ * @param s Scale factor to divide by */
+ SIMD_FORCE_INLINE btVector3& operator/=(const btScalar& s)
+ {
+ btFullAssert(s != btScalar(0.0));
+
+#if 0 //defined(BT_USE_SSE_IN_API)
+// this code is not faster !
+ __m128 vs = _mm_load_ss(&s);
+ vs = _mm_div_ss(v1110, vs);
+ vs = bt_pshufd_ps(vs, 0x00); // (S S S S)
+
+ mVec128 = _mm_mul_ps(mVec128, vs);
+
+ return *this;
+#else
+ return *this *= btScalar(1.0) / s;
+#endif
+ }
+
+ /**@brief Return the dot product
+ * @param v The other vector in the dot product */
+ SIMD_FORCE_INLINE btScalar dot(const btVector3& v) const
+ {
+#if defined BT_USE_SIMD_VECTOR3 && defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ __m128 vd = _mm_mul_ps(mVec128, v.mVec128);
+ __m128 z = _mm_movehl_ps(vd, vd);
+ __m128 y = _mm_shuffle_ps(vd, vd, 0x55);
+ vd = _mm_add_ss(vd, y);
+ vd = _mm_add_ss(vd, z);
+ return _mm_cvtss_f32(vd);
+#elif defined(BT_USE_NEON)
+ float32x4_t vd = vmulq_f32(mVec128, v.mVec128);
+ float32x2_t x = vpadd_f32(vget_low_f32(vd), vget_low_f32(vd));
+ x = vadd_f32(x, vget_high_f32(vd));
+ return vget_lane_f32(x, 0);
+#else
+ return m_floats[0] * v.m_floats[0] +
+ m_floats[1] * v.m_floats[1] +
+ m_floats[2] * v.m_floats[2];
+#endif
+ }
+
+ /**@brief Return the length of the vector squared */
+ SIMD_FORCE_INLINE btScalar length2() const
+ {
+ return dot(*this);
+ }
+
+ /**@brief Return the length of the vector */
+ SIMD_FORCE_INLINE btScalar length() const
+ {
+ return btSqrt(length2());
+ }
+
+ /**@brief Return the norm (length) of the vector */
+ SIMD_FORCE_INLINE btScalar norm() const
+ {
+ return length();
+ }
+
+ /**@brief Return the norm (length) of the vector */
+ SIMD_FORCE_INLINE btScalar safeNorm() const
+ {
+ btScalar d = length2();
+ //workaround for some clang/gcc issue of sqrtf(tiny number) = -INF
+ if (d>SIMD_EPSILON)
+ return btSqrt(d);
+ return btScalar(0);
+ }
+
+ /**@brief Return the distance squared between the ends of this and another vector
+ * This is symantically treating the vector like a point */
+ SIMD_FORCE_INLINE btScalar distance2(const btVector3& v) const;
+
+ /**@brief Return the distance between the ends of this and another vector
+ * This is symantically treating the vector like a point */
+ SIMD_FORCE_INLINE btScalar distance(const btVector3& v) const;
+
+ SIMD_FORCE_INLINE btVector3& safeNormalize()
+ {
+ btScalar l2 = length2();
+ //triNormal.normalize();
+ if (l2 >= SIMD_EPSILON*SIMD_EPSILON)
+ {
+ (*this) /= btSqrt(l2);
+ }
+ else
+ {
+ setValue(1, 0, 0);
+ }
+ return *this;
+ }
+
+ /**@brief Normalize this vector
+ * x^2 + y^2 + z^2 = 1 */
+ SIMD_FORCE_INLINE btVector3& normalize()
+ {
+
+ btAssert(!fuzzyZero());
+
+#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ // dot product first
+ __m128 vd = _mm_mul_ps(mVec128, mVec128);
+ __m128 z = _mm_movehl_ps(vd, vd);
+ __m128 y = _mm_shuffle_ps(vd, vd, 0x55);
+ vd = _mm_add_ss(vd, y);
+ vd = _mm_add_ss(vd, z);
+
+ #if 0
+ vd = _mm_sqrt_ss(vd);
+ vd = _mm_div_ss(v1110, vd);
+ vd = bt_splat_ps(vd, 0x80);
+ mVec128 = _mm_mul_ps(mVec128, vd);
+ #else
+
+ // NR step 1/sqrt(x) - vd is x, y is output
+ y = _mm_rsqrt_ss(vd); // estimate
+
+ // one step NR
+ z = v1_5;
+ vd = _mm_mul_ss(vd, vHalf); // vd * 0.5
+ //x2 = vd;
+ vd = _mm_mul_ss(vd, y); // vd * 0.5 * y0
+ vd = _mm_mul_ss(vd, y); // vd * 0.5 * y0 * y0
+ z = _mm_sub_ss(z, vd); // 1.5 - vd * 0.5 * y0 * y0
+
+ y = _mm_mul_ss(y, z); // y0 * (1.5 - vd * 0.5 * y0 * y0)
+
+ y = bt_splat_ps(y, 0x80);
+ mVec128 = _mm_mul_ps(mVec128, y);
+
+ #endif
+
+
+ return *this;
+#else
+ return *this /= length();
+#endif
+ }
+
+ /**@brief Return a normalized version of this vector */
+ SIMD_FORCE_INLINE btVector3 normalized() const;
+
+ /**@brief Return a rotated version of this vector
+ * @param wAxis The axis to rotate about
+ * @param angle The angle to rotate by */
+ SIMD_FORCE_INLINE btVector3 rotate( const btVector3& wAxis, const btScalar angle ) const;
+
+ /**@brief Return the angle between this and another vector
+ * @param v The other vector */
+ SIMD_FORCE_INLINE btScalar angle(const btVector3& v) const
+ {
+ btScalar s = btSqrt(length2() * v.length2());
+ btFullAssert(s != btScalar(0.0));
+ return btAcos(dot(v) / s);
+ }
+
+ /**@brief Return a vector with the absolute values of each element */
+ SIMD_FORCE_INLINE btVector3 absolute() const
+ {
+
+#if defined BT_USE_SIMD_VECTOR3 && defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ return btVector3(_mm_and_ps(mVec128, btv3AbsfMask));
+#elif defined(BT_USE_NEON)
+ return btVector3(vabsq_f32(mVec128));
+#else
+ return btVector3(
+ btFabs(m_floats[0]),
+ btFabs(m_floats[1]),
+ btFabs(m_floats[2]));
+#endif
+ }
+
+ /**@brief Return the cross product between this and another vector
+ * @param v The other vector */
+ SIMD_FORCE_INLINE btVector3 cross(const btVector3& v) const
+ {
+#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ __m128 T, V;
+
+ T = bt_pshufd_ps(mVec128, BT_SHUFFLE(1, 2, 0, 3)); // (Y Z X 0)
+ V = bt_pshufd_ps(v.mVec128, BT_SHUFFLE(1, 2, 0, 3)); // (Y Z X 0)
+
+ V = _mm_mul_ps(V, mVec128);
+ T = _mm_mul_ps(T, v.mVec128);
+ V = _mm_sub_ps(V, T);
+
+ V = bt_pshufd_ps(V, BT_SHUFFLE(1, 2, 0, 3));
+ return btVector3(V);
+#elif defined(BT_USE_NEON)
+ float32x4_t T, V;
+ // form (Y, Z, X, _) of mVec128 and v.mVec128
+ float32x2_t Tlow = vget_low_f32(mVec128);
+ float32x2_t Vlow = vget_low_f32(v.mVec128);
+ T = vcombine_f32(vext_f32(Tlow, vget_high_f32(mVec128), 1), Tlow);
+ V = vcombine_f32(vext_f32(Vlow, vget_high_f32(v.mVec128), 1), Vlow);
+
+ V = vmulq_f32(V, mVec128);
+ T = vmulq_f32(T, v.mVec128);
+ V = vsubq_f32(V, T);
+ Vlow = vget_low_f32(V);
+ // form (Y, Z, X, _);
+ V = vcombine_f32(vext_f32(Vlow, vget_high_f32(V), 1), Vlow);
+ V = (float32x4_t)vandq_s32((int32x4_t)V, btvFFF0Mask);
+
+ return btVector3(V);
+#else
+ return btVector3(
+ m_floats[1] * v.m_floats[2] - m_floats[2] * v.m_floats[1],
+ m_floats[2] * v.m_floats[0] - m_floats[0] * v.m_floats[2],
+ m_floats[0] * v.m_floats[1] - m_floats[1] * v.m_floats[0]);
+#endif
+ }
+
+ SIMD_FORCE_INLINE btScalar triple(const btVector3& v1, const btVector3& v2) const
+ {
+#if defined BT_USE_SIMD_VECTOR3 && defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ // cross:
+ __m128 T = _mm_shuffle_ps(v1.mVec128, v1.mVec128, BT_SHUFFLE(1, 2, 0, 3)); // (Y Z X 0)
+ __m128 V = _mm_shuffle_ps(v2.mVec128, v2.mVec128, BT_SHUFFLE(1, 2, 0, 3)); // (Y Z X 0)
+
+ V = _mm_mul_ps(V, v1.mVec128);
+ T = _mm_mul_ps(T, v2.mVec128);
+ V = _mm_sub_ps(V, T);
+
+ V = _mm_shuffle_ps(V, V, BT_SHUFFLE(1, 2, 0, 3));
+
+ // dot:
+ V = _mm_mul_ps(V, mVec128);
+ __m128 z = _mm_movehl_ps(V, V);
+ __m128 y = _mm_shuffle_ps(V, V, 0x55);
+ V = _mm_add_ss(V, y);
+ V = _mm_add_ss(V, z);
+ return _mm_cvtss_f32(V);
+
+#elif defined(BT_USE_NEON)
+ // cross:
+ float32x4_t T, V;
+ // form (Y, Z, X, _) of mVec128 and v.mVec128
+ float32x2_t Tlow = vget_low_f32(v1.mVec128);
+ float32x2_t Vlow = vget_low_f32(v2.mVec128);
+ T = vcombine_f32(vext_f32(Tlow, vget_high_f32(v1.mVec128), 1), Tlow);
+ V = vcombine_f32(vext_f32(Vlow, vget_high_f32(v2.mVec128), 1), Vlow);
+
+ V = vmulq_f32(V, v1.mVec128);
+ T = vmulq_f32(T, v2.mVec128);
+ V = vsubq_f32(V, T);
+ Vlow = vget_low_f32(V);
+ // form (Y, Z, X, _);
+ V = vcombine_f32(vext_f32(Vlow, vget_high_f32(V), 1), Vlow);
+
+ // dot:
+ V = vmulq_f32(mVec128, V);
+ float32x2_t x = vpadd_f32(vget_low_f32(V), vget_low_f32(V));
+ x = vadd_f32(x, vget_high_f32(V));
+ return vget_lane_f32(x, 0);
+#else
+ return
+ m_floats[0] * (v1.m_floats[1] * v2.m_floats[2] - v1.m_floats[2] * v2.m_floats[1]) +
+ m_floats[1] * (v1.m_floats[2] * v2.m_floats[0] - v1.m_floats[0] * v2.m_floats[2]) +
+ m_floats[2] * (v1.m_floats[0] * v2.m_floats[1] - v1.m_floats[1] * v2.m_floats[0]);
+#endif
+ }
+
+ /**@brief Return the axis with the smallest value
+ * Note return values are 0,1,2 for x, y, or z */
+ SIMD_FORCE_INLINE int minAxis() const
+ {
+ return m_floats[0] < m_floats[1] ? (m_floats[0] <m_floats[2] ? 0 : 2) : (m_floats[1] <m_floats[2] ? 1 : 2);
+ }
+
+ /**@brief Return the axis with the largest value
+ * Note return values are 0,1,2 for x, y, or z */
+ SIMD_FORCE_INLINE int maxAxis() const
+ {
+ return m_floats[0] < m_floats[1] ? (m_floats[1] <m_floats[2] ? 2 : 1) : (m_floats[0] <m_floats[2] ? 2 : 0);
+ }
+
+ SIMD_FORCE_INLINE int furthestAxis() const
+ {
+ return absolute().minAxis();
+ }
+
+ SIMD_FORCE_INLINE int closestAxis() const
+ {
+ return absolute().maxAxis();
+ }
+
+
+ SIMD_FORCE_INLINE void setInterpolate3(const btVector3& v0, const btVector3& v1, btScalar rt)
+ {
+#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ __m128 vrt = _mm_load_ss(&rt); // (rt 0 0 0)
+ btScalar s = btScalar(1.0) - rt;
+ __m128 vs = _mm_load_ss(&s); // (S 0 0 0)
+ vs = bt_pshufd_ps(vs, 0x80); // (S S S 0.0)
+ __m128 r0 = _mm_mul_ps(v0.mVec128, vs);
+ vrt = bt_pshufd_ps(vrt, 0x80); // (rt rt rt 0.0)
+ __m128 r1 = _mm_mul_ps(v1.mVec128, vrt);
+ __m128 tmp3 = _mm_add_ps(r0,r1);
+ mVec128 = tmp3;
+#elif defined(BT_USE_NEON)
+ float32x4_t vl = vsubq_f32(v1.mVec128, v0.mVec128);
+ vl = vmulq_n_f32(vl, rt);
+ mVec128 = vaddq_f32(vl, v0.mVec128);
+#else
+ btScalar s = btScalar(1.0) - rt;
+ m_floats[0] = s * v0.m_floats[0] + rt * v1.m_floats[0];
+ m_floats[1] = s * v0.m_floats[1] + rt * v1.m_floats[1];
+ m_floats[2] = s * v0.m_floats[2] + rt * v1.m_floats[2];
+ //don't do the unused w component
+ // m_co[3] = s * v0[3] + rt * v1[3];
+#endif
+ }
+
+ /**@brief Return the linear interpolation between this and another vector
+ * @param v The other vector
+ * @param t The ration of this to v (t = 0 => return this, t=1 => return other) */
+ SIMD_FORCE_INLINE btVector3 lerp(const btVector3& v, const btScalar& t) const
+ {
+#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ __m128 vt = _mm_load_ss(&t); // (t 0 0 0)
+ vt = bt_pshufd_ps(vt, 0x80); // (rt rt rt 0.0)
+ __m128 vl = _mm_sub_ps(v.mVec128, mVec128);
+ vl = _mm_mul_ps(vl, vt);
+ vl = _mm_add_ps(vl, mVec128);
+
+ return btVector3(vl);
+#elif defined(BT_USE_NEON)
+ float32x4_t vl = vsubq_f32(v.mVec128, mVec128);
+ vl = vmulq_n_f32(vl, t);
+ vl = vaddq_f32(vl, mVec128);
+
+ return btVector3(vl);
+#else
+ return
+ btVector3( m_floats[0] + (v.m_floats[0] - m_floats[0]) * t,
+ m_floats[1] + (v.m_floats[1] - m_floats[1]) * t,
+ m_floats[2] + (v.m_floats[2] - m_floats[2]) * t);
+#endif
+ }
+
+ /**@brief Elementwise multiply this vector by the other
+ * @param v The other vector */
+ SIMD_FORCE_INLINE btVector3& operator*=(const btVector3& v)
+ {
+#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ mVec128 = _mm_mul_ps(mVec128, v.mVec128);
+#elif defined(BT_USE_NEON)
+ mVec128 = vmulq_f32(mVec128, v.mVec128);
+#else
+ m_floats[0] *= v.m_floats[0];
+ m_floats[1] *= v.m_floats[1];
+ m_floats[2] *= v.m_floats[2];
+#endif
+ return *this;
+ }
+
+ /**@brief Return the x value */
+ SIMD_FORCE_INLINE const btScalar& getX() const { return m_floats[0]; }
+ /**@brief Return the y value */
+ SIMD_FORCE_INLINE const btScalar& getY() const { return m_floats[1]; }
+ /**@brief Return the z value */
+ SIMD_FORCE_INLINE const btScalar& getZ() const { return m_floats[2]; }
+ /**@brief Set the x value */
+ SIMD_FORCE_INLINE void setX(btScalar _x) { m_floats[0] = _x;};
+ /**@brief Set the y value */
+ SIMD_FORCE_INLINE void setY(btScalar _y) { m_floats[1] = _y;};
+ /**@brief Set the z value */
+ SIMD_FORCE_INLINE void setZ(btScalar _z) { m_floats[2] = _z;};
+ /**@brief Set the w value */
+ SIMD_FORCE_INLINE void setW(btScalar _w) { m_floats[3] = _w;};
+ /**@brief Return the x value */
+ SIMD_FORCE_INLINE const btScalar& x() const { return m_floats[0]; }
+ /**@brief Return the y value */
+ SIMD_FORCE_INLINE const btScalar& y() const { return m_floats[1]; }
+ /**@brief Return the z value */
+ SIMD_FORCE_INLINE const btScalar& z() const { return m_floats[2]; }
+ /**@brief Return the w value */
+ SIMD_FORCE_INLINE const btScalar& w() const { return m_floats[3]; }
+
+ //SIMD_FORCE_INLINE btScalar& operator[](int i) { return (&m_floats[0])[i]; }
+ //SIMD_FORCE_INLINE const btScalar& operator[](int i) const { return (&m_floats[0])[i]; }
+ ///operator btScalar*() replaces operator[], using implicit conversion. We added operator != and operator == to avoid pointer comparisons.
+ SIMD_FORCE_INLINE operator btScalar *() { return &m_floats[0]; }
+ SIMD_FORCE_INLINE operator const btScalar *() const { return &m_floats[0]; }
+
+ SIMD_FORCE_INLINE bool operator==(const btVector3& other) const
+ {
+#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ return (0xf == _mm_movemask_ps((__m128)_mm_cmpeq_ps(mVec128, other.mVec128)));
+#else
+ return ((m_floats[3]==other.m_floats[3]) &&
+ (m_floats[2]==other.m_floats[2]) &&
+ (m_floats[1]==other.m_floats[1]) &&
+ (m_floats[0]==other.m_floats[0]));
+#endif
+ }
+
+ SIMD_FORCE_INLINE bool operator!=(const btVector3& other) const
+ {
+ return !(*this == other);
+ }
+
+ /**@brief Set each element to the max of the current values and the values of another btVector3
+ * @param other The other btVector3 to compare with
+ */
+ SIMD_FORCE_INLINE void setMax(const btVector3& other)
+ {
+#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ mVec128 = _mm_max_ps(mVec128, other.mVec128);
+#elif defined(BT_USE_NEON)
+ mVec128 = vmaxq_f32(mVec128, other.mVec128);
+#else
+ btSetMax(m_floats[0], other.m_floats[0]);
+ btSetMax(m_floats[1], other.m_floats[1]);
+ btSetMax(m_floats[2], other.m_floats[2]);
+ btSetMax(m_floats[3], other.w());
+#endif
+ }
+
+ /**@brief Set each element to the min of the current values and the values of another btVector3
+ * @param other The other btVector3 to compare with
+ */
+ SIMD_FORCE_INLINE void setMin(const btVector3& other)
+ {
+#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ mVec128 = _mm_min_ps(mVec128, other.mVec128);
+#elif defined(BT_USE_NEON)
+ mVec128 = vminq_f32(mVec128, other.mVec128);
+#else
+ btSetMin(m_floats[0], other.m_floats[0]);
+ btSetMin(m_floats[1], other.m_floats[1]);
+ btSetMin(m_floats[2], other.m_floats[2]);
+ btSetMin(m_floats[3], other.w());
+#endif
+ }
+
+ SIMD_FORCE_INLINE void setValue(const btScalar& _x, const btScalar& _y, const btScalar& _z)
+ {
+ m_floats[0]=_x;
+ m_floats[1]=_y;
+ m_floats[2]=_z;
+ m_floats[3] = btScalar(0.f);
+ }
+
+ void getSkewSymmetricMatrix(btVector3* v0,btVector3* v1,btVector3* v2) const
+ {
+#if defined BT_USE_SIMD_VECTOR3 && defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+
+ __m128 V = _mm_and_ps(mVec128, btvFFF0fMask);
+ __m128 V0 = _mm_xor_ps(btvMzeroMask, V);
+ __m128 V2 = _mm_movelh_ps(V0, V);
+
+ __m128 V1 = _mm_shuffle_ps(V, V0, 0xCE);
+
+ V0 = _mm_shuffle_ps(V0, V, 0xDB);
+ V2 = _mm_shuffle_ps(V2, V, 0xF9);
+
+ v0->mVec128 = V0;
+ v1->mVec128 = V1;
+ v2->mVec128 = V2;
+#else
+ v0->setValue(0. ,-z() ,y());
+ v1->setValue(z() ,0. ,-x());
+ v2->setValue(-y() ,x() ,0.);
+#endif
+ }
+
+ void setZero()
+ {
+#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ mVec128 = (__m128)_mm_xor_ps(mVec128, mVec128);
+#elif defined(BT_USE_NEON)
+ int32x4_t vi = vdupq_n_s32(0);
+ mVec128 = vreinterpretq_f32_s32(vi);
+#else
+ setValue(btScalar(0.),btScalar(0.),btScalar(0.));
+#endif
+ }
+
+ SIMD_FORCE_INLINE bool isZero() const
+ {
+ return m_floats[0] == btScalar(0) && m_floats[1] == btScalar(0) && m_floats[2] == btScalar(0);
+ }
+
+
+ SIMD_FORCE_INLINE bool fuzzyZero() const
+ {
+ return length2() < SIMD_EPSILON*SIMD_EPSILON;
+ }
+
+ SIMD_FORCE_INLINE void serialize(struct btVector3Data& dataOut) const;
+
+ SIMD_FORCE_INLINE void deSerialize(const struct btVector3Data& dataIn);
+
+ SIMD_FORCE_INLINE void serializeFloat(struct btVector3FloatData& dataOut) const;
+
+ SIMD_FORCE_INLINE void deSerializeFloat(const struct btVector3FloatData& dataIn);
+
+ SIMD_FORCE_INLINE void serializeDouble(struct btVector3DoubleData& dataOut) const;
+
+ SIMD_FORCE_INLINE void deSerializeDouble(const struct btVector3DoubleData& dataIn);
+
+ /**@brief returns index of maximum dot product between this and vectors in array[]
+ * @param array The other vectors
+ * @param array_count The number of other vectors
+ * @param dotOut The maximum dot product */
+ SIMD_FORCE_INLINE long maxDot( const btVector3 *array, long array_count, btScalar &dotOut ) const;
+
+ /**@brief returns index of minimum dot product between this and vectors in array[]
+ * @param array The other vectors
+ * @param array_count The number of other vectors
+ * @param dotOut The minimum dot product */
+ SIMD_FORCE_INLINE long minDot( const btVector3 *array, long array_count, btScalar &dotOut ) const;
+
+ /* create a vector as btVector3( this->dot( btVector3 v0 ), this->dot( btVector3 v1), this->dot( btVector3 v2 )) */
+ SIMD_FORCE_INLINE btVector3 dot3( const btVector3 &v0, const btVector3 &v1, const btVector3 &v2 ) const
+ {
+#if defined BT_USE_SIMD_VECTOR3 && defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+
+ __m128 a0 = _mm_mul_ps( v0.mVec128, this->mVec128 );
+ __m128 a1 = _mm_mul_ps( v1.mVec128, this->mVec128 );
+ __m128 a2 = _mm_mul_ps( v2.mVec128, this->mVec128 );
+ __m128 b0 = _mm_unpacklo_ps( a0, a1 );
+ __m128 b1 = _mm_unpackhi_ps( a0, a1 );
+ __m128 b2 = _mm_unpacklo_ps( a2, _mm_setzero_ps() );
+ __m128 r = _mm_movelh_ps( b0, b2 );
+ r = _mm_add_ps( r, _mm_movehl_ps( b2, b0 ));
+ a2 = _mm_and_ps( a2, btvxyzMaskf);
+ r = _mm_add_ps( r, btCastdTo128f (_mm_move_sd( btCastfTo128d(a2), btCastfTo128d(b1) )));
+ return btVector3(r);
+
+#elif defined(BT_USE_NEON)
+ static const uint32x4_t xyzMask = (const uint32x4_t){ static_cast<uint32_t>(-1), static_cast<uint32_t>(-1), static_cast<uint32_t>(-1), 0 };
+ float32x4_t a0 = vmulq_f32( v0.mVec128, this->mVec128);
+ float32x4_t a1 = vmulq_f32( v1.mVec128, this->mVec128);
+ float32x4_t a2 = vmulq_f32( v2.mVec128, this->mVec128);
+ float32x2x2_t zLo = vtrn_f32( vget_high_f32(a0), vget_high_f32(a1));
+ a2 = (float32x4_t) vandq_u32((uint32x4_t) a2, xyzMask );
+ float32x2_t b0 = vadd_f32( vpadd_f32( vget_low_f32(a0), vget_low_f32(a1)), zLo.val[0] );
+ float32x2_t b1 = vpadd_f32( vpadd_f32( vget_low_f32(a2), vget_high_f32(a2)), vdup_n_f32(0.0f));
+ return btVector3( vcombine_f32(b0, b1) );
+#else
+ return btVector3( dot(v0), dot(v1), dot(v2));
+#endif
+ }
+};
+
+/**@brief Return the sum of two vectors (Point symantics)*/
+SIMD_FORCE_INLINE btVector3
+operator+(const btVector3& v1, const btVector3& v2)
+{
+#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ return btVector3(_mm_add_ps(v1.mVec128, v2.mVec128));
+#elif defined(BT_USE_NEON)
+ return btVector3(vaddq_f32(v1.mVec128, v2.mVec128));
+#else
+ return btVector3(
+ v1.m_floats[0] + v2.m_floats[0],
+ v1.m_floats[1] + v2.m_floats[1],
+ v1.m_floats[2] + v2.m_floats[2]);
+#endif
+}
+
+/**@brief Return the elementwise product of two vectors */
+SIMD_FORCE_INLINE btVector3
+operator*(const btVector3& v1, const btVector3& v2)
+{
+#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ return btVector3(_mm_mul_ps(v1.mVec128, v2.mVec128));
+#elif defined(BT_USE_NEON)
+ return btVector3(vmulq_f32(v1.mVec128, v2.mVec128));
+#else
+ return btVector3(
+ v1.m_floats[0] * v2.m_floats[0],
+ v1.m_floats[1] * v2.m_floats[1],
+ v1.m_floats[2] * v2.m_floats[2]);
+#endif
+}
+
+/**@brief Return the difference between two vectors */
+SIMD_FORCE_INLINE btVector3
+operator-(const btVector3& v1, const btVector3& v2)
+{
+#if defined BT_USE_SIMD_VECTOR3 && (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE))
+
+ // without _mm_and_ps this code causes slowdown in Concave moving
+ __m128 r = _mm_sub_ps(v1.mVec128, v2.mVec128);
+ return btVector3(_mm_and_ps(r, btvFFF0fMask));
+#elif defined(BT_USE_NEON)
+ float32x4_t r = vsubq_f32(v1.mVec128, v2.mVec128);
+ return btVector3((float32x4_t)vandq_s32((int32x4_t)r, btvFFF0Mask));
+#else
+ return btVector3(
+ v1.m_floats[0] - v2.m_floats[0],
+ v1.m_floats[1] - v2.m_floats[1],
+ v1.m_floats[2] - v2.m_floats[2]);
+#endif
+}
+
+/**@brief Return the negative of the vector */
+SIMD_FORCE_INLINE btVector3
+operator-(const btVector3& v)
+{
+#if defined BT_USE_SIMD_VECTOR3 && (defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE))
+ __m128 r = _mm_xor_ps(v.mVec128, btvMzeroMask);
+ return btVector3(_mm_and_ps(r, btvFFF0fMask));
+#elif defined(BT_USE_NEON)
+ return btVector3((btSimdFloat4)veorq_s32((int32x4_t)v.mVec128, (int32x4_t)btvMzeroMask));
+#else
+ return btVector3(-v.m_floats[0], -v.m_floats[1], -v.m_floats[2]);
+#endif
+}
+
+/**@brief Return the vector scaled by s */
+SIMD_FORCE_INLINE btVector3
+operator*(const btVector3& v, const btScalar& s)
+{
+#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ __m128 vs = _mm_load_ss(&s); // (S 0 0 0)
+ vs = bt_pshufd_ps(vs, 0x80); // (S S S 0.0)
+ return btVector3(_mm_mul_ps(v.mVec128, vs));
+#elif defined(BT_USE_NEON)
+ float32x4_t r = vmulq_n_f32(v.mVec128, s);
+ return btVector3((float32x4_t)vandq_s32((int32x4_t)r, btvFFF0Mask));
+#else
+ return btVector3(v.m_floats[0] * s, v.m_floats[1] * s, v.m_floats[2] * s);
+#endif
+}
+
+/**@brief Return the vector scaled by s */
+SIMD_FORCE_INLINE btVector3
+operator*(const btScalar& s, const btVector3& v)
+{
+ return v * s;
+}
+
+/**@brief Return the vector inversely scaled by s */
+SIMD_FORCE_INLINE btVector3
+operator/(const btVector3& v, const btScalar& s)
+{
+ btFullAssert(s != btScalar(0.0));
+#if 0 //defined(BT_USE_SSE_IN_API)
+// this code is not faster !
+ __m128 vs = _mm_load_ss(&s);
+ vs = _mm_div_ss(v1110, vs);
+ vs = bt_pshufd_ps(vs, 0x00); // (S S S S)
+
+ return btVector3(_mm_mul_ps(v.mVec128, vs));
+#else
+ return v * (btScalar(1.0) / s);
+#endif
+}
+
+/**@brief Return the vector inversely scaled by s */
+SIMD_FORCE_INLINE btVector3
+operator/(const btVector3& v1, const btVector3& v2)
+{
+#if defined BT_USE_SIMD_VECTOR3 && (defined(BT_USE_SSE_IN_API)&& defined (BT_USE_SSE))
+ __m128 vec = _mm_div_ps(v1.mVec128, v2.mVec128);
+ vec = _mm_and_ps(vec, btvFFF0fMask);
+ return btVector3(vec);
+#elif defined(BT_USE_NEON)
+ float32x4_t x, y, v, m;
+
+ x = v1.mVec128;
+ y = v2.mVec128;
+
+ v = vrecpeq_f32(y); // v ~ 1/y
+ m = vrecpsq_f32(y, v); // m = (2-v*y)
+ v = vmulq_f32(v, m); // vv = v*m ~~ 1/y
+ m = vrecpsq_f32(y, v); // mm = (2-vv*y)
+ v = vmulq_f32(v, x); // x*vv
+ v = vmulq_f32(v, m); // (x*vv)*(2-vv*y) = x*(vv(2-vv*y)) ~~~ x/y
+
+ return btVector3(v);
+#else
+ return btVector3(
+ v1.m_floats[0] / v2.m_floats[0],
+ v1.m_floats[1] / v2.m_floats[1],
+ v1.m_floats[2] / v2.m_floats[2]);
+#endif
+}
+
+/**@brief Return the dot product between two vectors */
+SIMD_FORCE_INLINE btScalar
+btDot(const btVector3& v1, const btVector3& v2)
+{
+ return v1.dot(v2);
+}
+
+
+/**@brief Return the distance squared between two vectors */
+SIMD_FORCE_INLINE btScalar
+btDistance2(const btVector3& v1, const btVector3& v2)
+{
+ return v1.distance2(v2);
+}
+
+
+/**@brief Return the distance between two vectors */
+SIMD_FORCE_INLINE btScalar
+btDistance(const btVector3& v1, const btVector3& v2)
+{
+ return v1.distance(v2);
+}
+
+/**@brief Return the angle between two vectors */
+SIMD_FORCE_INLINE btScalar
+btAngle(const btVector3& v1, const btVector3& v2)
+{
+ return v1.angle(v2);
+}
+
+/**@brief Return the cross product of two vectors */
+SIMD_FORCE_INLINE btVector3
+btCross(const btVector3& v1, const btVector3& v2)
+{
+ return v1.cross(v2);
+}
+
+SIMD_FORCE_INLINE btScalar
+btTriple(const btVector3& v1, const btVector3& v2, const btVector3& v3)
+{
+ return v1.triple(v2, v3);
+}
+
+/**@brief Return the linear interpolation between two vectors
+ * @param v1 One vector
+ * @param v2 The other vector
+ * @param t The ration of this to v (t = 0 => return v1, t=1 => return v2) */
+SIMD_FORCE_INLINE btVector3
+lerp(const btVector3& v1, const btVector3& v2, const btScalar& t)
+{
+ return v1.lerp(v2, t);
+}
+
+
+
+SIMD_FORCE_INLINE btScalar btVector3::distance2(const btVector3& v) const
+{
+ return (v - *this).length2();
+}
+
+SIMD_FORCE_INLINE btScalar btVector3::distance(const btVector3& v) const
+{
+ return (v - *this).length();
+}
+
+SIMD_FORCE_INLINE btVector3 btVector3::normalized() const
+{
+ btVector3 nrm = *this;
+
+ return nrm.normalize();
+}
+
+SIMD_FORCE_INLINE btVector3 btVector3::rotate( const btVector3& wAxis, const btScalar _angle ) const
+{
+ // wAxis must be a unit lenght vector
+
+#if defined BT_USE_SIMD_VECTOR3 && defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+
+ __m128 O = _mm_mul_ps(wAxis.mVec128, mVec128);
+ btScalar ssin = btSin( _angle );
+ __m128 C = wAxis.cross( mVec128 ).mVec128;
+ O = _mm_and_ps(O, btvFFF0fMask);
+ btScalar scos = btCos( _angle );
+
+ __m128 vsin = _mm_load_ss(&ssin); // (S 0 0 0)
+ __m128 vcos = _mm_load_ss(&scos); // (S 0 0 0)
+
+ __m128 Y = bt_pshufd_ps(O, 0xC9); // (Y Z X 0)
+ __m128 Z = bt_pshufd_ps(O, 0xD2); // (Z X Y 0)
+ O = _mm_add_ps(O, Y);
+ vsin = bt_pshufd_ps(vsin, 0x80); // (S S S 0)
+ O = _mm_add_ps(O, Z);
+ vcos = bt_pshufd_ps(vcos, 0x80); // (S S S 0)
+
+ vsin = vsin * C;
+ O = O * wAxis.mVec128;
+ __m128 X = mVec128 - O;
+
+ O = O + vsin;
+ vcos = vcos * X;
+ O = O + vcos;
+
+ return btVector3(O);
+#else
+ btVector3 o = wAxis * wAxis.dot( *this );
+ btVector3 _x = *this - o;
+ btVector3 _y;
+
+ _y = wAxis.cross( *this );
+
+ return ( o + _x * btCos( _angle ) + _y * btSin( _angle ) );
+#endif
+}
+
+SIMD_FORCE_INLINE long btVector3::maxDot( const btVector3 *array, long array_count, btScalar &dotOut ) const
+{
+#if (defined BT_USE_SSE && defined BT_USE_SIMD_VECTOR3 && defined BT_USE_SSE_IN_API) || defined (BT_USE_NEON)
+ #if defined _WIN32 || defined (BT_USE_SSE)
+ const long scalar_cutoff = 10;
+ long _maxdot_large( const float *array, const float *vec, unsigned long array_count, float *dotOut );
+ #elif defined BT_USE_NEON
+ const long scalar_cutoff = 4;
+ extern long (*_maxdot_large)( const float *array, const float *vec, unsigned long array_count, float *dotOut );
+ #endif
+ if( array_count < scalar_cutoff )
+#endif
+ {
+ btScalar maxDot1 = -SIMD_INFINITY;
+ int i = 0;
+ int ptIndex = -1;
+ for( i = 0; i < array_count; i++ )
+ {
+ btScalar dot = array[i].dot(*this);
+
+ if( dot > maxDot1 )
+ {
+ maxDot1 = dot;
+ ptIndex = i;
+ }
+ }
+
+ dotOut = maxDot1;
+ return ptIndex;
+ }
+#if (defined BT_USE_SSE && defined BT_USE_SIMD_VECTOR3 && defined BT_USE_SSE_IN_API) || defined (BT_USE_NEON)
+ return _maxdot_large( (float*) array, (float*) &m_floats[0], array_count, &dotOut );
+#endif
+}
+
+SIMD_FORCE_INLINE long btVector3::minDot( const btVector3 *array, long array_count, btScalar &dotOut ) const
+{
+#if (defined BT_USE_SSE && defined BT_USE_SIMD_VECTOR3 && defined BT_USE_SSE_IN_API) || defined (BT_USE_NEON)
+ #if defined BT_USE_SSE
+ const long scalar_cutoff = 10;
+ long _mindot_large( const float *array, const float *vec, unsigned long array_count, float *dotOut );
+ #elif defined BT_USE_NEON
+ const long scalar_cutoff = 4;
+ extern long (*_mindot_large)( const float *array, const float *vec, unsigned long array_count, float *dotOut );
+ #else
+ #error unhandled arch!
+ #endif
+
+ if( array_count < scalar_cutoff )
+#endif
+ {
+ btScalar minDot = SIMD_INFINITY;
+ int i = 0;
+ int ptIndex = -1;
+
+ for( i = 0; i < array_count; i++ )
+ {
+ btScalar dot = array[i].dot(*this);
+
+ if( dot < minDot )
+ {
+ minDot = dot;
+ ptIndex = i;
+ }
+ }
+
+ dotOut = minDot;
+
+ return ptIndex;
+ }
+#if (defined BT_USE_SSE && defined BT_USE_SIMD_VECTOR3 && defined BT_USE_SSE_IN_API) || defined (BT_USE_NEON)
+ return _mindot_large( (float*) array, (float*) &m_floats[0], array_count, &dotOut );
+#endif//BT_USE_SIMD_VECTOR3
+}
+
+
+class btVector4 : public btVector3
+{
+public:
+
+ SIMD_FORCE_INLINE btVector4() {}
+
+
+ SIMD_FORCE_INLINE btVector4(const btScalar& _x, const btScalar& _y, const btScalar& _z,const btScalar& _w)
+ : btVector3(_x,_y,_z)
+ {
+ m_floats[3] = _w;
+ }
+
+#if (defined (BT_USE_SSE_IN_API)&& defined (BT_USE_SSE)) || defined (BT_USE_NEON)
+ SIMD_FORCE_INLINE btVector4(const btSimdFloat4 vec)
+ {
+ mVec128 = vec;
+ }
+
+ SIMD_FORCE_INLINE btVector4(const btVector3& rhs)
+ {
+ mVec128 = rhs.mVec128;
+ }
+
+ SIMD_FORCE_INLINE btVector4&
+ operator=(const btVector4& v)
+ {
+ mVec128 = v.mVec128;
+ return *this;
+ }
+#endif // #if defined (BT_USE_SSE_IN_API) || defined (BT_USE_NEON)
+
+ SIMD_FORCE_INLINE btVector4 absolute4() const
+ {
+#if defined BT_USE_SIMD_VECTOR3 && defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ return btVector4(_mm_and_ps(mVec128, btvAbsfMask));
+#elif defined(BT_USE_NEON)
+ return btVector4(vabsq_f32(mVec128));
+#else
+ return btVector4(
+ btFabs(m_floats[0]),
+ btFabs(m_floats[1]),
+ btFabs(m_floats[2]),
+ btFabs(m_floats[3]));
+#endif
+ }
+
+
+ btScalar getW() const { return m_floats[3];}
+
+
+ SIMD_FORCE_INLINE int maxAxis4() const
+ {
+ int maxIndex = -1;
+ btScalar maxVal = btScalar(-BT_LARGE_FLOAT);
+ if (m_floats[0] > maxVal)
+ {
+ maxIndex = 0;
+ maxVal = m_floats[0];
+ }
+ if (m_floats[1] > maxVal)
+ {
+ maxIndex = 1;
+ maxVal = m_floats[1];
+ }
+ if (m_floats[2] > maxVal)
+ {
+ maxIndex = 2;
+ maxVal =m_floats[2];
+ }
+ if (m_floats[3] > maxVal)
+ {
+ maxIndex = 3;
+ }
+
+ return maxIndex;
+ }
+
+
+ SIMD_FORCE_INLINE int minAxis4() const
+ {
+ int minIndex = -1;
+ btScalar minVal = btScalar(BT_LARGE_FLOAT);
+ if (m_floats[0] < minVal)
+ {
+ minIndex = 0;
+ minVal = m_floats[0];
+ }
+ if (m_floats[1] < minVal)
+ {
+ minIndex = 1;
+ minVal = m_floats[1];
+ }
+ if (m_floats[2] < minVal)
+ {
+ minIndex = 2;
+ minVal =m_floats[2];
+ }
+ if (m_floats[3] < minVal)
+ {
+ minIndex = 3;
+ }
+
+ return minIndex;
+ }
+
+
+ SIMD_FORCE_INLINE int closestAxis4() const
+ {
+ return absolute4().maxAxis4();
+ }
+
+
+
+
+ /**@brief Set x,y,z and zero w
+ * @param x Value of x
+ * @param y Value of y
+ * @param z Value of z
+ */
+
+
+/* void getValue(btScalar *m) const
+ {
+ m[0] = m_floats[0];
+ m[1] = m_floats[1];
+ m[2] =m_floats[2];
+ }
+*/
+/**@brief Set the values
+ * @param x Value of x
+ * @param y Value of y
+ * @param z Value of z
+ * @param w Value of w
+ */
+ SIMD_FORCE_INLINE void setValue(const btScalar& _x, const btScalar& _y, const btScalar& _z,const btScalar& _w)
+ {
+ m_floats[0]=_x;
+ m_floats[1]=_y;
+ m_floats[2]=_z;
+ m_floats[3]=_w;
+ }
+
+
+};
+
+
+///btSwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization
+SIMD_FORCE_INLINE void btSwapScalarEndian(const btScalar& sourceVal, btScalar& destVal)
+{
+ #ifdef BT_USE_DOUBLE_PRECISION
+ unsigned char* dest = (unsigned char*) &destVal;
+ unsigned char* src = (unsigned char*) &sourceVal;
+ dest[0] = src[7];
+ dest[1] = src[6];
+ dest[2] = src[5];
+ dest[3] = src[4];
+ dest[4] = src[3];
+ dest[5] = src[2];
+ dest[6] = src[1];
+ dest[7] = src[0];
+#else
+ unsigned char* dest = (unsigned char*) &destVal;
+ unsigned char* src = (unsigned char*) &sourceVal;
+ dest[0] = src[3];
+ dest[1] = src[2];
+ dest[2] = src[1];
+ dest[3] = src[0];
+#endif //BT_USE_DOUBLE_PRECISION
+}
+///btSwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization
+SIMD_FORCE_INLINE void btSwapVector3Endian(const btVector3& sourceVec, btVector3& destVec)
+{
+ for (int i=0;i<4;i++)
+ {
+ btSwapScalarEndian(sourceVec[i],destVec[i]);
+ }
+
+}
+
+///btUnSwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization
+SIMD_FORCE_INLINE void btUnSwapVector3Endian(btVector3& vector)
+{
+
+ btVector3 swappedVec;
+ for (int i=0;i<4;i++)
+ {
+ btSwapScalarEndian(vector[i],swappedVec[i]);
+ }
+ vector = swappedVec;
+}
+
+template <class T>
+SIMD_FORCE_INLINE void btPlaneSpace1 (const T& n, T& p, T& q)
+{
+ if (btFabs(n[2]) > SIMDSQRT12) {
+ // choose p in y-z plane
+ btScalar a = n[1]*n[1] + n[2]*n[2];
+ btScalar k = btRecipSqrt (a);
+ p[0] = 0;
+ p[1] = -n[2]*k;
+ p[2] = n[1]*k;
+ // set q = n x p
+ q[0] = a*k;
+ q[1] = -n[0]*p[2];
+ q[2] = n[0]*p[1];
+ }
+ else {
+ // choose p in x-y plane
+ btScalar a = n[0]*n[0] + n[1]*n[1];
+ btScalar k = btRecipSqrt (a);
+ p[0] = -n[1]*k;
+ p[1] = n[0]*k;
+ p[2] = 0;
+ // set q = n x p
+ q[0] = -n[2]*p[1];
+ q[1] = n[2]*p[0];
+ q[2] = a*k;
+ }
+}
+
+
+struct btVector3FloatData
+{
+ float m_floats[4];
+};
+
+struct btVector3DoubleData
+{
+ double m_floats[4];
+
+};
+
+SIMD_FORCE_INLINE void btVector3::serializeFloat(struct btVector3FloatData& dataOut) const
+{
+ ///could also do a memcpy, check if it is worth it
+ for (int i=0;i<4;i++)
+ dataOut.m_floats[i] = float(m_floats[i]);
+}
+
+SIMD_FORCE_INLINE void btVector3::deSerializeFloat(const struct btVector3FloatData& dataIn)
+{
+ for (int i=0;i<4;i++)
+ m_floats[i] = btScalar(dataIn.m_floats[i]);
+}
+
+
+SIMD_FORCE_INLINE void btVector3::serializeDouble(struct btVector3DoubleData& dataOut) const
+{
+ ///could also do a memcpy, check if it is worth it
+ for (int i=0;i<4;i++)
+ dataOut.m_floats[i] = double(m_floats[i]);
+}
+
+SIMD_FORCE_INLINE void btVector3::deSerializeDouble(const struct btVector3DoubleData& dataIn)
+{
+ for (int i=0;i<4;i++)
+ m_floats[i] = btScalar(dataIn.m_floats[i]);
+}
+
+
+SIMD_FORCE_INLINE void btVector3::serialize(struct btVector3Data& dataOut) const
+{
+ ///could also do a memcpy, check if it is worth it
+ for (int i=0;i<4;i++)
+ dataOut.m_floats[i] = m_floats[i];
+}
+
+SIMD_FORCE_INLINE void btVector3::deSerialize(const struct btVector3Data& dataIn)
+{
+ for (int i=0;i<4;i++)
+ m_floats[i] = dataIn.m_floats[i];
+}
+
+#endif //BT_VECTOR3_H
diff --git a/thirdparty/bullet/src/LinearMath/premake4.lua b/thirdparty/bullet/src/LinearMath/premake4.lua
new file mode 100644
index 0000000000..524e2c3161
--- /dev/null
+++ b/thirdparty/bullet/src/LinearMath/premake4.lua
@@ -0,0 +1,10 @@
+ project "LinearMath"
+
+ kind "StaticLib"
+ includedirs {
+ "..",
+ }
+ files {
+ "*.cpp",
+ "*.h"
+ }
diff --git a/thirdparty/bullet/src/btBulletCollisionCommon.h b/thirdparty/bullet/src/btBulletCollisionCommon.h
new file mode 100644
index 0000000000..948e02eb4c
--- /dev/null
+++ b/thirdparty/bullet/src/btBulletCollisionCommon.h
@@ -0,0 +1,67 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BULLET_COLLISION_COMMON_H
+#define BULLET_COLLISION_COMMON_H
+
+///Common headerfile includes for Bullet Collision Detection
+
+///Bullet's btCollisionWorld and btCollisionObject definitions
+#include "BulletCollision/CollisionDispatch/btCollisionWorld.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+
+///Collision Shapes
+#include "BulletCollision/CollisionShapes/btBoxShape.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"
+#include "BulletCollision/CollisionShapes/btCapsuleShape.h"
+#include "BulletCollision/CollisionShapes/btCylinderShape.h"
+#include "BulletCollision/CollisionShapes/btConeShape.h"
+#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h"
+#include "BulletCollision/CollisionShapes/btConvexHullShape.h"
+#include "BulletCollision/CollisionShapes/btTriangleMesh.h"
+#include "BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h"
+#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h"
+#include "BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h"
+#include "BulletCollision/CollisionShapes/btTriangleMeshShape.h"
+#include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h"
+#include "BulletCollision/CollisionShapes/btCompoundShape.h"
+#include "BulletCollision/CollisionShapes/btTetrahedronShape.h"
+#include "BulletCollision/CollisionShapes/btEmptyShape.h"
+#include "BulletCollision/CollisionShapes/btMultiSphereShape.h"
+#include "BulletCollision/CollisionShapes/btUniformScalingShape.h"
+
+///Narrowphase Collision Detector
+#include "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h"
+
+//#include "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h"
+
+///Dispatching and generation of collision pairs (broadphase)
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h"
+#include "BulletCollision/BroadphaseCollision/btAxisSweep3.h"
+#include "BulletCollision/BroadphaseCollision/btDbvtBroadphase.h"
+
+///Math library & Utils
+#include "LinearMath/btQuaternion.h"
+#include "LinearMath/btTransform.h"
+#include "LinearMath/btDefaultMotionState.h"
+#include "LinearMath/btQuickprof.h"
+#include "LinearMath/btIDebugDraw.h"
+#include "LinearMath/btSerializer.h"
+
+
+#endif //BULLET_COLLISION_COMMON_H
+
diff --git a/thirdparty/bullet/src/btBulletDynamicsCommon.h b/thirdparty/bullet/src/btBulletDynamicsCommon.h
new file mode 100644
index 0000000000..50282bf210
--- /dev/null
+++ b/thirdparty/bullet/src/btBulletDynamicsCommon.h
@@ -0,0 +1,51 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BULLET_DYNAMICS_COMMON_H
+#define BULLET_DYNAMICS_COMMON_H
+
+///Common headerfile includes for Bullet Dynamics, including Collision Detection
+#include "btBulletCollisionCommon.h"
+
+#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h"
+
+#include "BulletDynamics/Dynamics/btSimpleDynamicsWorld.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+
+#include "BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btHingeConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btConeTwistConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btSliderConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btUniversalConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btHinge2Constraint.h"
+#include "BulletDynamics/ConstraintSolver/btGearConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btFixedConstraint.h"
+
+
+#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h"
+
+
+///Vehicle simulation, with wheel contact simulated by raycasts
+#include "BulletDynamics/Vehicle/btRaycastVehicle.h"
+
+
+
+
+
+
+#endif //BULLET_DYNAMICS_COMMON_H
+
diff --git a/thirdparty/bullet/src/clew/clew.c b/thirdparty/bullet/src/clew/clew.c
new file mode 100644
index 0000000000..a07b0aad75
--- /dev/null
+++ b/thirdparty/bullet/src/clew/clew.c
@@ -0,0 +1,312 @@
+//////////////////////////////////////////////////////////////////////////
+// Copyright (c) 2009 Organic Vectory B.V.
+// Written by George van Venrooij
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file license.txt)
+//////////////////////////////////////////////////////////////////////////
+
+#include "clew.h"
+
+#ifdef _WIN32
+ #define WIN32_LEAN_AND_MEAN
+ #define VC_EXTRALEAN
+ #include <windows.h>
+
+ typedef HMODULE CLEW_DYNLIB_HANDLE;
+
+ #define CLEW_DYNLIB_OPEN LoadLibrary
+ #define CLEW_DYNLIB_CLOSE FreeLibrary
+ #define CLEW_DYNLIB_IMPORT GetProcAddress
+#else
+ #include <dlfcn.h>
+
+ typedef void* CLEW_DYNLIB_HANDLE;
+
+ #define CLEW_DYNLIB_OPEN(path) dlopen(path, RTLD_NOW | RTLD_GLOBAL)
+ #define CLEW_DYNLIB_CLOSE dlclose
+ #define CLEW_DYNLIB_IMPORT dlsym
+#endif
+
+#include <stdlib.h>
+
+//! \brief module handle
+static CLEW_DYNLIB_HANDLE module = NULL;
+
+// Variables holding function entry points
+PFNCLGETPLATFORMIDS __clewGetPlatformIDs = NULL;
+PFNCLGETPLATFORMINFO __clewGetPlatformInfo = NULL;
+PFNCLGETDEVICEIDS __clewGetDeviceIDs = NULL;
+PFNCLGETDEVICEINFO __clewGetDeviceInfo = NULL;
+PFNCLCREATECONTEXT __clewCreateContext = NULL;
+PFNCLCREATECONTEXTFROMTYPE __clewCreateContextFromType = NULL;
+PFNCLRETAINCONTEXT __clewRetainContext = NULL;
+PFNCLRELEASECONTEXT __clewReleaseContext = NULL;
+PFNCLGETCONTEXTINFO __clewGetContextInfo = NULL;
+PFNCLCREATECOMMANDQUEUE __clewCreateCommandQueue = NULL;
+PFNCLRETAINCOMMANDQUEUE __clewRetainCommandQueue = NULL;
+PFNCLRELEASECOMMANDQUEUE __clewReleaseCommandQueue = NULL;
+PFNCLGETCOMMANDQUEUEINFO __clewGetCommandQueueInfo = NULL;
+#ifdef CL_USE_DEPRECATED_OPENCL_1_0_APIS
+PFNCLSETCOMMANDQUEUEPROPERTY __clewSetCommandQueueProperty = NULL;
+#endif
+PFNCLCREATEBUFFER __clewCreateBuffer = NULL;
+PFNCLCREATESUBBUFFER __clewCreateSubBuffer = NULL;
+PFNCLCREATEIMAGE2D __clewCreateImage2D = NULL;
+PFNCLCREATEIMAGE3D __clewCreateImage3D = NULL;
+PFNCLRETAINMEMOBJECT __clewRetainMemObject = NULL;
+PFNCLRELEASEMEMOBJECT __clewReleaseMemObject = NULL;
+PFNCLGETSUPPORTEDIMAGEFORMATS __clewGetSupportedImageFormats = NULL;
+PFNCLGETMEMOBJECTINFO __clewGetMemObjectInfo = NULL;
+PFNCLGETIMAGEINFO __clewGetImageInfo = NULL;
+PFNCLSETMEMOBJECTDESTRUCTORCALLBACK __clewSetMemObjectDestructorCallback = NULL;
+PFNCLCREATESAMPLER __clewCreateSampler = NULL;
+PFNCLRETAINSAMPLER __clewRetainSampler = NULL;
+PFNCLRELEASESAMPLER __clewReleaseSampler = NULL;
+PFNCLGETSAMPLERINFO __clewGetSamplerInfo = NULL;
+PFNCLCREATEPROGRAMWITHSOURCE __clewCreateProgramWithSource = NULL;
+PFNCLCREATEPROGRAMWITHBINARY __clewCreateProgramWithBinary = NULL;
+PFNCLRETAINPROGRAM __clewRetainProgram = NULL;
+PFNCLRELEASEPROGRAM __clewReleaseProgram = NULL;
+PFNCLBUILDPROGRAM __clewBuildProgram = NULL;
+PFNCLUNLOADCOMPILER __clewUnloadCompiler = NULL;
+PFNCLGETPROGRAMINFO __clewGetProgramInfo = NULL;
+PFNCLGETPROGRAMBUILDINFO __clewGetProgramBuildInfo = NULL;
+PFNCLCREATEKERNEL __clewCreateKernel = NULL;
+PFNCLCREATEKERNELSINPROGRAM __clewCreateKernelsInProgram = NULL;
+PFNCLRETAINKERNEL __clewRetainKernel = NULL;
+PFNCLRELEASEKERNEL __clewReleaseKernel = NULL;
+PFNCLSETKERNELARG __clewSetKernelArg = NULL;
+PFNCLGETKERNELINFO __clewGetKernelInfo = NULL;
+PFNCLGETKERNELWORKGROUPINFO __clewGetKernelWorkGroupInfo = NULL;
+PFNCLWAITFOREVENTS __clewWaitForEvents = NULL;
+PFNCLGETEVENTINFO __clewGetEventInfo = NULL;
+PFNCLCREATEUSEREVENT __clewCreateUserEvent = NULL;
+PFNCLRETAINEVENT __clewRetainEvent = NULL;
+PFNCLRELEASEEVENT __clewReleaseEvent = NULL;
+PFNCLSETUSEREVENTSTATUS __clewSetUserEventStatus = NULL;
+PFNCLSETEVENTCALLBACK __clewSetEventCallback = NULL;
+PFNCLGETEVENTPROFILINGINFO __clewGetEventProfilingInfo = NULL;
+PFNCLFLUSH __clewFlush = NULL;
+PFNCLFINISH __clewFinish = NULL;
+PFNCLENQUEUEREADBUFFER __clewEnqueueReadBuffer = NULL;
+PFNCLENQUEUEREADBUFFERRECT __clewEnqueueReadBufferRect = NULL;
+PFNCLENQUEUEWRITEBUFFER __clewEnqueueWriteBuffer = NULL;
+PFNCLENQUEUEWRITEBUFFERRECT __clewEnqueueWriteBufferRect = NULL;
+PFNCLENQUEUECOPYBUFFER __clewEnqueueCopyBuffer = NULL;
+PFNCLENQUEUEREADIMAGE __clewEnqueueReadImage = NULL;
+PFNCLENQUEUEWRITEIMAGE __clewEnqueueWriteImage = NULL;
+PFNCLENQUEUECOPYIMAGE __clewEnqueueCopyImage = NULL;
+PFNCLENQUEUECOPYBUFFERRECT __clewEnqueueCopyBufferRect = NULL;
+PFNCLENQUEUECOPYIMAGETOBUFFER __clewEnqueueCopyImageToBuffer = NULL;
+PFNCLENQUEUECOPYBUFFERTOIMAGE __clewEnqueueCopyBufferToImage = NULL;
+PFNCLENQUEUEMAPBUFFER __clewEnqueueMapBuffer = NULL;
+PFNCLENQUEUEMAPIMAGE __clewEnqueueMapImage = NULL;
+PFNCLENQUEUEUNMAPMEMOBJECT __clewEnqueueUnmapMemObject = NULL;
+PFNCLENQUEUENDRANGEKERNEL __clewEnqueueNDRangeKernel = NULL;
+PFNCLENQUEUETASK __clewEnqueueTask = NULL;
+PFNCLENQUEUENATIVEKERNEL __clewEnqueueNativeKernel = NULL;
+PFNCLENQUEUEMARKER __clewEnqueueMarker = NULL;
+PFNCLENQUEUEWAITFOREVENTS __clewEnqueueWaitForEvents = NULL;
+PFNCLENQUEUEBARRIER __clewEnqueueBarrier = NULL;
+PFNCLGETEXTENSIONFUNCTIONADDRESS __clewGetExtensionFunctionAddress = NULL;
+
+
+void clewExit(void)
+{
+ if (module != NULL)
+ {
+ // Ignore errors
+ CLEW_DYNLIB_CLOSE(module);
+ module = NULL;
+ }
+}
+
+int clewInit(const char* path)
+{
+ int error = 0;
+
+ // Check if already initialized
+ if (module != NULL)
+ {
+ return CLEW_SUCCESS;
+ }
+
+ // Load library
+ module = CLEW_DYNLIB_OPEN(path);
+
+ // Check for errors
+ if (module == NULL)
+ {
+ return CLEW_ERROR_OPEN_FAILED;
+ }
+
+ // Set unloading
+ error = atexit(clewExit);
+
+ if (error)
+ {
+ // Failure queuing atexit, shutdown with error
+ CLEW_DYNLIB_CLOSE(module);
+ module = NULL;
+
+ return CLEW_ERROR_ATEXIT_FAILED;
+ }
+
+ // Determine function entry-points
+ __clewGetPlatformIDs = (PFNCLGETPLATFORMIDS )CLEW_DYNLIB_IMPORT(module, "clGetPlatformIDs");
+ __clewGetPlatformInfo = (PFNCLGETPLATFORMINFO )CLEW_DYNLIB_IMPORT(module, "clGetPlatformInfo");
+ __clewGetDeviceIDs = (PFNCLGETDEVICEIDS )CLEW_DYNLIB_IMPORT(module, "clGetDeviceIDs");
+ __clewGetDeviceInfo = (PFNCLGETDEVICEINFO )CLEW_DYNLIB_IMPORT(module, "clGetDeviceInfo");
+ __clewCreateContext = (PFNCLCREATECONTEXT )CLEW_DYNLIB_IMPORT(module, "clCreateContext");
+ __clewCreateContextFromType = (PFNCLCREATECONTEXTFROMTYPE )CLEW_DYNLIB_IMPORT(module, "clCreateContextFromType");
+ __clewRetainContext = (PFNCLRETAINCONTEXT )CLEW_DYNLIB_IMPORT(module, "clRetainContext");
+ __clewReleaseContext = (PFNCLRELEASECONTEXT )CLEW_DYNLIB_IMPORT(module, "clReleaseContext");
+ __clewGetContextInfo = (PFNCLGETCONTEXTINFO )CLEW_DYNLIB_IMPORT(module, "clGetContextInfo");
+ __clewCreateCommandQueue = (PFNCLCREATECOMMANDQUEUE )CLEW_DYNLIB_IMPORT(module, "clCreateCommandQueue");
+ __clewRetainCommandQueue = (PFNCLRETAINCOMMANDQUEUE )CLEW_DYNLIB_IMPORT(module, "clRetainCommandQueue");
+ __clewReleaseCommandQueue = (PFNCLRELEASECOMMANDQUEUE )CLEW_DYNLIB_IMPORT(module, "clReleaseCommandQueue");
+ __clewGetCommandQueueInfo = (PFNCLGETCOMMANDQUEUEINFO )CLEW_DYNLIB_IMPORT(module, "clGetCommandQueueInfo");
+#ifdef CL_USE_DEPRECATED_OPENCL_1_0_APIS
+ __clewSetCommandQueueProperty = (PFNCLSETCOMMANDQUEUEPROPERTY )CLEW_DYNLIB_IMPORT(module, "clSetCommandQueueProperty");
+#endif
+ __clewCreateBuffer = (PFNCLCREATEBUFFER )CLEW_DYNLIB_IMPORT(module, "clCreateBuffer");
+ __clewCreateSubBuffer = (PFNCLCREATESUBBUFFER )CLEW_DYNLIB_IMPORT(module, "clCreateBuffer");
+ __clewCreateImage2D = (PFNCLCREATEIMAGE2D )CLEW_DYNLIB_IMPORT(module, "clCreateImage2D");
+ __clewCreateImage3D = (PFNCLCREATEIMAGE3D )CLEW_DYNLIB_IMPORT(module, "clCreateImage3D");
+ __clewRetainMemObject = (PFNCLRETAINMEMOBJECT )CLEW_DYNLIB_IMPORT(module, "clRetainMemObject");
+ __clewReleaseMemObject = (PFNCLRELEASEMEMOBJECT )CLEW_DYNLIB_IMPORT(module, "clReleaseMemObject");
+ __clewGetSupportedImageFormats = (PFNCLGETSUPPORTEDIMAGEFORMATS )CLEW_DYNLIB_IMPORT(module, "clGetSupportedImageFormats");
+ __clewGetMemObjectInfo = (PFNCLGETMEMOBJECTINFO )CLEW_DYNLIB_IMPORT(module, "clGetMemObjectInfo");
+ __clewGetImageInfo = (PFNCLGETIMAGEINFO )CLEW_DYNLIB_IMPORT(module, "clGetImageInfo");
+ __clewSetMemObjectDestructorCallback = (PFNCLSETMEMOBJECTDESTRUCTORCALLBACK)CLEW_DYNLIB_IMPORT(module, "clSetMemObjectDestructorCallback");
+ __clewCreateSampler = (PFNCLCREATESAMPLER )CLEW_DYNLIB_IMPORT(module, "clCreateSampler");
+ __clewRetainSampler = (PFNCLRETAINSAMPLER )CLEW_DYNLIB_IMPORT(module, "clRetainSampler");
+ __clewReleaseSampler = (PFNCLRELEASESAMPLER )CLEW_DYNLIB_IMPORT(module, "clReleaseSampler");
+ __clewGetSamplerInfo = (PFNCLGETSAMPLERINFO )CLEW_DYNLIB_IMPORT(module, "clGetSamplerInfo");
+ __clewCreateProgramWithSource = (PFNCLCREATEPROGRAMWITHSOURCE )CLEW_DYNLIB_IMPORT(module, "clCreateProgramWithSource");
+ __clewCreateProgramWithBinary = (PFNCLCREATEPROGRAMWITHBINARY )CLEW_DYNLIB_IMPORT(module, "clCreateProgramWithBinary");
+ __clewRetainProgram = (PFNCLRETAINPROGRAM )CLEW_DYNLIB_IMPORT(module, "clRetainProgram");
+ __clewReleaseProgram = (PFNCLRELEASEPROGRAM )CLEW_DYNLIB_IMPORT(module, "clReleaseProgram");
+ __clewBuildProgram = (PFNCLBUILDPROGRAM )CLEW_DYNLIB_IMPORT(module, "clBuildProgram");
+ __clewUnloadCompiler = (PFNCLUNLOADCOMPILER )CLEW_DYNLIB_IMPORT(module, "clUnloadCompiler");
+ __clewGetProgramInfo = (PFNCLGETPROGRAMINFO )CLEW_DYNLIB_IMPORT(module, "clGetProgramInfo");
+ __clewGetProgramBuildInfo = (PFNCLGETPROGRAMBUILDINFO )CLEW_DYNLIB_IMPORT(module, "clGetProgramBuildInfo");
+ __clewCreateKernel = (PFNCLCREATEKERNEL )CLEW_DYNLIB_IMPORT(module, "clCreateKernel");
+ __clewCreateKernelsInProgram = (PFNCLCREATEKERNELSINPROGRAM )CLEW_DYNLIB_IMPORT(module, "clCreateKernelsInProgram");
+ __clewRetainKernel = (PFNCLRETAINKERNEL )CLEW_DYNLIB_IMPORT(module, "clRetainKernel");
+ __clewReleaseKernel = (PFNCLRELEASEKERNEL )CLEW_DYNLIB_IMPORT(module, "clReleaseKernel");
+ __clewSetKernelArg = (PFNCLSETKERNELARG )CLEW_DYNLIB_IMPORT(module, "clSetKernelArg");
+ __clewGetKernelInfo = (PFNCLGETKERNELINFO )CLEW_DYNLIB_IMPORT(module, "clGetKernelInfo");
+ __clewGetKernelWorkGroupInfo = (PFNCLGETKERNELWORKGROUPINFO )CLEW_DYNLIB_IMPORT(module, "clGetKernelWorkGroupInfo");
+ __clewWaitForEvents = (PFNCLWAITFOREVENTS )CLEW_DYNLIB_IMPORT(module, "clWaitForEvents");
+ __clewGetEventInfo = (PFNCLGETEVENTINFO )CLEW_DYNLIB_IMPORT(module, "clGetEventInfo");
+ __clewCreateUserEvent = (PFNCLCREATEUSEREVENT )CLEW_DYNLIB_IMPORT(module, "clCreateUserEvent");
+ __clewRetainEvent = (PFNCLRETAINEVENT )CLEW_DYNLIB_IMPORT(module, "clRetainEvent");
+ __clewReleaseEvent = (PFNCLRELEASEEVENT )CLEW_DYNLIB_IMPORT(module, "clReleaseEvent");
+ __clewSetUserEventStatus = (PFNCLSETUSEREVENTSTATUS )CLEW_DYNLIB_IMPORT(module, "clSetUserEventStatus");
+ __clewSetEventCallback = (PFNCLSETEVENTCALLBACK )CLEW_DYNLIB_IMPORT(module, "clSetEventCallback");
+ __clewGetEventProfilingInfo = (PFNCLGETEVENTPROFILINGINFO )CLEW_DYNLIB_IMPORT(module, "clGetEventProfilingInfo");
+ __clewFlush = (PFNCLFLUSH )CLEW_DYNLIB_IMPORT(module, "clFlush");
+ __clewFinish = (PFNCLFINISH )CLEW_DYNLIB_IMPORT(module, "clFinish");
+ __clewEnqueueReadBuffer = (PFNCLENQUEUEREADBUFFER )CLEW_DYNLIB_IMPORT(module, "clEnqueueReadBuffer");
+ __clewEnqueueReadBufferRect = (PFNCLENQUEUEREADBUFFERRECT )CLEW_DYNLIB_IMPORT(module, "clEnqueueReadBufferRect");
+ __clewEnqueueWriteBuffer = (PFNCLENQUEUEWRITEBUFFER )CLEW_DYNLIB_IMPORT(module, "clEnqueueWriteBuffer");
+ __clewEnqueueWriteBufferRect = (PFNCLENQUEUEWRITEBUFFERRECT )CLEW_DYNLIB_IMPORT(module, "clEnqueueWriteBufferRect");
+ __clewEnqueueCopyBuffer = (PFNCLENQUEUECOPYBUFFER )CLEW_DYNLIB_IMPORT(module, "clEnqueueCopyBuffer");
+ __clewEnqueueCopyBufferRect = (PFNCLENQUEUECOPYBUFFERRECT )CLEW_DYNLIB_IMPORT(module, "clEnqueueCopyBufferRect");
+ __clewEnqueueReadImage = (PFNCLENQUEUEREADIMAGE )CLEW_DYNLIB_IMPORT(module, "clEnqueueReadImage");
+ __clewEnqueueWriteImage = (PFNCLENQUEUEWRITEIMAGE )CLEW_DYNLIB_IMPORT(module, "clEnqueueWriteImage");
+ __clewEnqueueCopyImage = (PFNCLENQUEUECOPYIMAGE )CLEW_DYNLIB_IMPORT(module, "clEnqueueCopyImage");
+ __clewEnqueueCopyImageToBuffer = (PFNCLENQUEUECOPYIMAGETOBUFFER )CLEW_DYNLIB_IMPORT(module, "clEnqueueCopyImageToBuffer");
+ __clewEnqueueCopyBufferToImage = (PFNCLENQUEUECOPYBUFFERTOIMAGE )CLEW_DYNLIB_IMPORT(module, "clEnqueueCopyBufferToImage");
+ __clewEnqueueMapBuffer = (PFNCLENQUEUEMAPBUFFER )CLEW_DYNLIB_IMPORT(module, "clEnqueueMapBuffer");
+ __clewEnqueueMapImage = (PFNCLENQUEUEMAPIMAGE )CLEW_DYNLIB_IMPORT(module, "clEnqueueMapImage");
+ __clewEnqueueUnmapMemObject = (PFNCLENQUEUEUNMAPMEMOBJECT )CLEW_DYNLIB_IMPORT(module, "clEnqueueUnmapMemObject");
+ __clewEnqueueNDRangeKernel = (PFNCLENQUEUENDRANGEKERNEL )CLEW_DYNLIB_IMPORT(module, "clEnqueueNDRangeKernel");
+ __clewEnqueueTask = (PFNCLENQUEUETASK )CLEW_DYNLIB_IMPORT(module, "clEnqueueTask");
+ __clewEnqueueNativeKernel = (PFNCLENQUEUENATIVEKERNEL )CLEW_DYNLIB_IMPORT(module, "clEnqueueNativeKernel");
+ __clewEnqueueMarker = (PFNCLENQUEUEMARKER )CLEW_DYNLIB_IMPORT(module, "clEnqueueMarker");
+ __clewEnqueueWaitForEvents = (PFNCLENQUEUEWAITFOREVENTS )CLEW_DYNLIB_IMPORT(module, "clEnqueueWaitForEvents");
+ __clewEnqueueBarrier = (PFNCLENQUEUEBARRIER )CLEW_DYNLIB_IMPORT(module, "clEnqueueBarrier");
+ __clewGetExtensionFunctionAddress = (PFNCLGETEXTENSIONFUNCTIONADDRESS )CLEW_DYNLIB_IMPORT(module, "clGetExtensionFunctionAddress");
+
+ return CLEW_SUCCESS;
+}
+
+const char* clewErrorString(cl_int error)
+{
+ static const char* strings[] =
+ {
+ // Error Codes
+ "CL_SUCCESS" // 0
+ , "CL_DEVICE_NOT_FOUND" // -1
+ , "CL_DEVICE_NOT_AVAILABLE" // -2
+ , "CL_COMPILER_NOT_AVAILABLE" // -3
+ , "CL_MEM_OBJECT_ALLOCATION_FAILURE" // -4
+ , "CL_OUT_OF_RESOURCES" // -5
+ , "CL_OUT_OF_HOST_MEMORY" // -6
+ , "CL_PROFILING_INFO_NOT_AVAILABLE" // -7
+ , "CL_MEM_COPY_OVERLAP" // -8
+ , "CL_IMAGE_FORMAT_MISMATCH" // -9
+ , "CL_IMAGE_FORMAT_NOT_SUPPORTED" // -10
+ , "CL_BUILD_PROGRAM_FAILURE" // -11
+ , "CL_MAP_FAILURE" // -12
+
+ , "" // -13
+ , "" // -14
+ , "" // -15
+ , "" // -16
+ , "" // -17
+ , "" // -18
+ , "" // -19
+
+ , "" // -20
+ , "" // -21
+ , "" // -22
+ , "" // -23
+ , "" // -24
+ , "" // -25
+ , "" // -26
+ , "" // -27
+ , "" // -28
+ , "" // -29
+
+ , "CL_INVALID_VALUE" // -30
+ , "CL_INVALID_DEVICE_TYPE" // -31
+ , "CL_INVALID_PLATFORM" // -32
+ , "CL_INVALID_DEVICE" // -33
+ , "CL_INVALID_CONTEXT" // -34
+ , "CL_INVALID_QUEUE_PROPERTIES" // -35
+ , "CL_INVALID_COMMAND_QUEUE" // -36
+ , "CL_INVALID_HOST_PTR" // -37
+ , "CL_INVALID_MEM_OBJECT" // -38
+ , "CL_INVALID_IMAGE_FORMAT_DESCRIPTOR" // -39
+ , "CL_INVALID_IMAGE_SIZE" // -40
+ , "CL_INVALID_SAMPLER" // -41
+ , "CL_INVALID_BINARY" // -42
+ , "CL_INVALID_BUILD_OPTIONS" // -43
+ , "CL_INVALID_PROGRAM" // -44
+ , "CL_INVALID_PROGRAM_EXECUTABLE" // -45
+ , "CL_INVALID_KERNEL_NAME" // -46
+ , "CL_INVALID_KERNEL_DEFINITION" // -47
+ , "CL_INVALID_KERNEL" // -48
+ , "CL_INVALID_ARG_INDEX" // -49
+ , "CL_INVALID_ARG_VALUE" // -50
+ , "CL_INVALID_ARG_SIZE" // -51
+ , "CL_INVALID_KERNEL_ARGS" // -52
+ , "CL_INVALID_WORK_DIMENSION" // -53
+ , "CL_INVALID_WORK_GROUP_SIZE" // -54
+ , "CL_INVALID_WORK_ITEM_SIZE" // -55
+ , "CL_INVALID_GLOBAL_OFFSET" // -56
+ , "CL_INVALID_EVENT_WAIT_LIST" // -57
+ , "CL_INVALID_EVENT" // -58
+ , "CL_INVALID_OPERATION" // -59
+ , "CL_INVALID_GL_OBJECT" // -60
+ , "CL_INVALID_BUFFER_SIZE" // -61
+ , "CL_INVALID_MIP_LEVEL" // -62
+ , "CL_INVALID_GLOBAL_WORK_SIZE" // -63
+ };
+
+ return strings[-error];
+}
diff --git a/thirdparty/bullet/src/clew/clew.h b/thirdparty/bullet/src/clew/clew.h
new file mode 100644
index 0000000000..ee0fef18b4
--- /dev/null
+++ b/thirdparty/bullet/src/clew/clew.h
@@ -0,0 +1,2397 @@
+#ifndef CLEW_HPP_INCLUDED
+#define CLEW_HPP_INCLUDED
+
+//////////////////////////////////////////////////////////////////////////
+// Copyright (c) 2009-2011 Organic Vectory B.V., KindDragon
+// Written by George van Venrooij
+//
+// Distributed under the MIT License.
+//////////////////////////////////////////////////////////////////////////
+
+//! \file clew.h
+//! \brief OpenCL run-time loader header
+//!
+//! This file contains a copy of the contents of CL.H and CL_PLATFORM.H from the
+//! official OpenCL spec. The purpose of this code is to load the OpenCL dynamic
+//! library at run-time and thus allow the executable to function on many
+//! platforms regardless of the vendor of the OpenCL driver actually installed.
+//! Some of the techniques used here were inspired by work done in the GLEW
+//! library (http://glew.sourceforge.net/)
+
+// Run-time dynamic linking functionality based on concepts used in GLEW
+#ifdef __OPENCL_CL_H
+#error cl.h included before clew.h
+#endif
+
+#ifdef __OPENCL_CL_PLATFORM_H
+#error cl_platform.h included before clew.h
+#endif
+
+// Prevent cl.h inclusion
+#define __OPENCL_CL_H
+// Prevent cl_platform.h inclusion
+#define __CL_PLATFORM_H
+
+/*******************************************************************************
+* Copyright (c) 2008-2010 The Khronos Group Inc.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and/or associated documentation files (the
+* "Materials"), to deal in the Materials without restriction, including
+* without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Materials, and to
+* permit persons to whom the Materials are furnished to do so, subject to
+* the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Materials.
+*
+* THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+* MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+******************************************************************************/
+#ifdef __APPLE__
+ /* Contains #defines for AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER below */
+ #include <AvailabilityMacros.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(_WIN32)
+ #define CL_API_ENTRY
+ #define CL_API_CALL __stdcall
+ #define CL_CALLBACK __stdcall
+#else
+ #define CL_API_ENTRY
+ #define CL_API_CALL
+ #define CL_CALLBACK
+#endif
+//disabled the APPLE thing, don't know why it is there, is just causes tons of warnings
+
+#ifdef __APPLE1__
+ #define CL_EXTENSION_WEAK_LINK __attribute__((weak_import))
+ #define CL_API_SUFFIX__VERSION_1_0 AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER
+ #define CL_EXT_SUFFIX__VERSION_1_0 CL_EXTENSION_WEAK_LINK AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER
+ #define CL_API_SUFFIX__VERSION_1_1 CL_EXTENSION_WEAK_LINK
+ #define CL_EXT_SUFFIX__VERSION_1_1 CL_EXTENSION_WEAK_LINK
+ #define CL_EXT_SUFFIX__VERSION_1_0_DEPRECATED CL_EXTENSION_WEAK_LINK AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER
+#else
+ #define CL_EXTENSION_WEAK_LINK
+ #define CL_API_SUFFIX__VERSION_1_0
+ #define CL_EXT_SUFFIX__VERSION_1_0
+ #define CL_API_SUFFIX__VERSION_1_1
+ #define CL_EXT_SUFFIX__VERSION_1_1
+ #define CL_EXT_SUFFIX__VERSION_1_0_DEPRECATED
+#endif
+
+#if (defined (_WIN32) && defined(_MSC_VER))
+
+/* scalar types */
+typedef signed __int8 cl_char;
+typedef unsigned __int8 cl_uchar;
+typedef signed __int16 cl_short;
+typedef unsigned __int16 cl_ushort;
+typedef signed __int32 cl_int;
+typedef unsigned __int32 cl_uint;
+typedef signed __int64 cl_long;
+typedef unsigned __int64 cl_ulong;
+
+typedef unsigned __int16 cl_half;
+typedef float cl_float;
+typedef double cl_double;
+
+/* Macro names and corresponding values defined by OpenCL */
+#define CL_CHAR_BIT 8
+#define CL_SCHAR_MAX 127
+#define CL_SCHAR_MIN (-127-1)
+#define CL_CHAR_MAX CL_SCHAR_MAX
+#define CL_CHAR_MIN CL_SCHAR_MIN
+#define CL_UCHAR_MAX 255
+#define CL_SHRT_MAX 32767
+#define CL_SHRT_MIN (-32767-1)
+#define CL_USHRT_MAX 65535
+#define CL_INT_MAX 2147483647
+#define CL_INT_MIN (-2147483647-1)
+#define CL_UINT_MAX 0xffffffffU
+#define CL_LONG_MAX ((cl_long) 0x7FFFFFFFFFFFFFFFLL)
+#define CL_LONG_MIN ((cl_long) -0x7FFFFFFFFFFFFFFFLL - 1LL)
+#define CL_ULONG_MAX ((cl_ulong) 0xFFFFFFFFFFFFFFFFULL)
+
+#define CL_FLT_DIG 6
+#define CL_FLT_MANT_DIG 24
+#define CL_FLT_MAX_10_EXP +38
+#define CL_FLT_MAX_EXP +128
+#define CL_FLT_MIN_10_EXP -37
+#define CL_FLT_MIN_EXP -125
+#define CL_FLT_RADIX 2
+#define CL_FLT_MAX 340282346638528859811704183484516925440.0f
+#define CL_FLT_MIN 1.175494350822287507969e-38f
+#define CL_FLT_EPSILON 0x1.0p-23f
+
+#define CL_DBL_DIG 15
+#define CL_DBL_MANT_DIG 53
+#define CL_DBL_MAX_10_EXP +308
+#define CL_DBL_MAX_EXP +1024
+#define CL_DBL_MIN_10_EXP -307
+#define CL_DBL_MIN_EXP -1021
+#define CL_DBL_RADIX 2
+#define CL_DBL_MAX 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.0
+#define CL_DBL_MIN 2.225073858507201383090e-308
+#define CL_DBL_EPSILON 2.220446049250313080847e-16
+
+#define CL_M_E 2.718281828459045090796
+#define CL_M_LOG2E 1.442695040888963387005
+#define CL_M_LOG10E 0.434294481903251816668
+#define CL_M_LN2 0.693147180559945286227
+#define CL_M_LN10 2.302585092994045901094
+#define CL_M_PI 3.141592653589793115998
+#define CL_M_PI_2 1.570796326794896557999
+#define CL_M_PI_4 0.785398163397448278999
+#define CL_M_1_PI 0.318309886183790691216
+#define CL_M_2_PI 0.636619772367581382433
+#define CL_M_2_SQRTPI 1.128379167095512558561
+#define CL_M_SQRT2 1.414213562373095145475
+#define CL_M_SQRT1_2 0.707106781186547572737
+
+#define CL_M_E_F 2.71828174591064f
+#define CL_M_LOG2E_F 1.44269502162933f
+#define CL_M_LOG10E_F 0.43429449200630f
+#define CL_M_LN2_F 0.69314718246460f
+#define CL_M_LN10_F 2.30258512496948f
+#define CL_M_PI_F 3.14159274101257f
+#define CL_M_PI_2_F 1.57079637050629f
+#define CL_M_PI_4_F 0.78539818525314f
+#define CL_M_1_PI_F 0.31830987334251f
+#define CL_M_2_PI_F 0.63661974668503f
+#define CL_M_2_SQRTPI_F 1.12837922573090f
+#define CL_M_SQRT2_F 1.41421353816986f
+#define CL_M_SQRT1_2_F 0.70710676908493f
+
+#define CL_NAN (CL_INFINITY - CL_INFINITY)
+#define CL_HUGE_VALF ((cl_float) 1e50)
+#define CL_HUGE_VAL ((cl_double) 1e500)
+#define CL_MAXFLOAT CL_FLT_MAX
+#define CL_INFINITY CL_HUGE_VALF
+
+#else
+
+#include <stdint.h>
+
+/* scalar types */
+typedef int8_t cl_char;
+typedef uint8_t cl_uchar;
+typedef int16_t cl_short __attribute__((aligned(2)));
+typedef uint16_t cl_ushort __attribute__((aligned(2)));
+typedef int32_t cl_int __attribute__((aligned(4)));
+typedef uint32_t cl_uint __attribute__((aligned(4)));
+typedef int64_t cl_long __attribute__((aligned(8)));
+typedef uint64_t cl_ulong __attribute__((aligned(8)));
+
+typedef uint16_t cl_half __attribute__((aligned(2)));
+typedef float cl_float __attribute__((aligned(4)));
+typedef double cl_double __attribute__((aligned(8)));
+
+/* Macro names and corresponding values defined by OpenCL */
+#define CL_CHAR_BIT 8
+#define CL_SCHAR_MAX 127
+#define CL_SCHAR_MIN (-127-1)
+#define CL_CHAR_MAX CL_SCHAR_MAX
+#define CL_CHAR_MIN CL_SCHAR_MIN
+#define CL_UCHAR_MAX 255
+#define CL_SHRT_MAX 32767
+#define CL_SHRT_MIN (-32767-1)
+#define CL_USHRT_MAX 65535
+#define CL_INT_MAX 2147483647
+#define CL_INT_MIN (-2147483647-1)
+#define CL_UINT_MAX 0xffffffffU
+#define CL_LONG_MAX ((cl_long) 0x7FFFFFFFFFFFFFFFLL)
+#define CL_LONG_MIN ((cl_long) -0x7FFFFFFFFFFFFFFFLL - 1LL)
+#define CL_ULONG_MAX ((cl_ulong) 0xFFFFFFFFFFFFFFFFULL)
+
+#define CL_FLT_DIG 6
+#define CL_FLT_MANT_DIG 24
+#define CL_FLT_MAX_10_EXP +38
+#define CL_FLT_MAX_EXP +128
+#define CL_FLT_MIN_10_EXP -37
+#define CL_FLT_MIN_EXP -125
+#define CL_FLT_RADIX 2
+#define CL_FLT_MAX 0x1.fffffep127f
+#define CL_FLT_MIN 0x1.0p-126f
+#define CL_FLT_EPSILON 0x1.0p-23f
+
+#define CL_DBL_DIG 15
+#define CL_DBL_MANT_DIG 53
+#define CL_DBL_MAX_10_EXP +308
+#define CL_DBL_MAX_EXP +1024
+#define CL_DBL_MIN_10_EXP -307
+#define CL_DBL_MIN_EXP -1021
+#define CL_DBL_RADIX 2
+#define CL_DBL_MAX 0x1.fffffffffffffp1023
+#define CL_DBL_MIN 0x1.0p-1022
+#define CL_DBL_EPSILON 0x1.0p-52
+
+#define CL_M_E 2.718281828459045090796
+#define CL_M_LOG2E 1.442695040888963387005
+#define CL_M_LOG10E 0.434294481903251816668
+#define CL_M_LN2 0.693147180559945286227
+#define CL_M_LN10 2.302585092994045901094
+#define CL_M_PI 3.141592653589793115998
+#define CL_M_PI_2 1.570796326794896557999
+#define CL_M_PI_4 0.785398163397448278999
+#define CL_M_1_PI 0.318309886183790691216
+#define CL_M_2_PI 0.636619772367581382433
+#define CL_M_2_SQRTPI 1.128379167095512558561
+#define CL_M_SQRT2 1.414213562373095145475
+#define CL_M_SQRT1_2 0.707106781186547572737
+
+#define CL_M_E_F 2.71828174591064f
+#define CL_M_LOG2E_F 1.44269502162933f
+#define CL_M_LOG10E_F 0.43429449200630f
+#define CL_M_LN2_F 0.69314718246460f
+#define CL_M_LN10_F 2.30258512496948f
+#define CL_M_PI_F 3.14159274101257f
+#define CL_M_PI_2_F 1.57079637050629f
+#define CL_M_PI_4_F 0.78539818525314f
+#define CL_M_1_PI_F 0.31830987334251f
+#define CL_M_2_PI_F 0.63661974668503f
+#define CL_M_2_SQRTPI_F 1.12837922573090f
+#define CL_M_SQRT2_F 1.41421353816986f
+#define CL_M_SQRT1_2_F 0.70710676908493f
+
+#if defined( __GNUC__ )
+ #define CL_HUGE_VALF __builtin_huge_valf()
+ #define CL_HUGE_VAL __builtin_huge_val()
+ #define CL_NAN __builtin_nanf( "" )
+#else
+ #define CL_HUGE_VALF ((cl_float) 1e50)
+ #define CL_HUGE_VAL ((cl_double) 1e500)
+ float nanf( const char * );
+ #define CL_NAN nanf( "" )
+#endif
+#define CL_MAXFLOAT CL_FLT_MAX
+#define CL_INFINITY CL_HUGE_VALF
+
+#endif
+
+#include <stddef.h>
+
+/* Mirror types to GL types. Mirror types allow us to avoid deciding which headers to load based on whether we are using GL or GLES here. */
+typedef unsigned int cl_GLuint;
+typedef int cl_GLint;
+typedef unsigned int cl_GLenum;
+
+/*
+ * Vector types
+ *
+ * Note: OpenCL requires that all types be naturally aligned.
+ * This means that vector types must be naturally aligned.
+ * For example, a vector of four floats must be aligned to
+ * a 16 byte boundary (calculated as 4 * the natural 4-byte
+ * alignment of the float). The alignment qualifiers here
+ * will only function properly if your compiler supports them
+ * and if you don't actively work to defeat them. For example,
+ * in order for a cl_float4 to be 16 byte aligned in a struct,
+ * the start of the struct must itself be 16-byte aligned.
+ *
+ * Maintaining proper alignment is the user's responsibility.
+ */
+
+
+#ifdef _MSC_VER
+#if defined(_M_IX86)
+#if _M_IX86_FP >= 0
+#define __SSE__
+#endif
+#if _M_IX86_FP >= 1
+#define __SSE2__
+#endif
+#elif defined(_M_X64)
+#define __SSE__
+#define __SSE2__
+#endif
+#endif
+
+/* Define basic vector types */
+#if defined( __VEC__ )
+ #include <altivec.h> /* may be omitted depending on compiler. AltiVec spec provides no way to detect whether the header is required. */
+ typedef vector unsigned char __cl_uchar16;
+ typedef vector signed char __cl_char16;
+ typedef vector unsigned short __cl_ushort8;
+ typedef vector signed short __cl_short8;
+ typedef vector unsigned int __cl_uint4;
+ typedef vector signed int __cl_int4;
+ typedef vector float __cl_float4;
+ #define __CL_UCHAR16__ 1
+ #define __CL_CHAR16__ 1
+ #define __CL_USHORT8__ 1
+ #define __CL_SHORT8__ 1
+ #define __CL_UINT4__ 1
+ #define __CL_INT4__ 1
+ #define __CL_FLOAT4__ 1
+#endif
+
+#if defined( __SSE__ )
+ #if defined( __MINGW64__ )
+ #include <intrin.h>
+ #else
+ #include <xmmintrin.h>
+ #endif
+ #if defined( __GNUC__ ) && !defined( __ICC )
+ typedef float __cl_float4 __attribute__((vector_size(16)));
+ #else
+ typedef __m128 __cl_float4;
+ #endif
+ #define __CL_FLOAT4__ 1
+#endif
+
+#if defined( __SSE2__ )
+ #if defined( __MINGW64__ )
+ #include <intrin.h>
+ #else
+ #include <emmintrin.h>
+ #endif
+ #if defined( __GNUC__ ) && !defined( __ICC )
+ typedef cl_uchar __cl_uchar16 __attribute__((vector_size(16)));
+ typedef cl_char __cl_char16 __attribute__((vector_size(16)));
+ typedef cl_ushort __cl_ushort8 __attribute__((vector_size(16)));
+ typedef cl_short __cl_short8 __attribute__((vector_size(16)));
+ typedef cl_uint __cl_uint4 __attribute__((vector_size(16)));
+ typedef cl_int __cl_int4 __attribute__((vector_size(16)));
+ typedef cl_ulong __cl_ulong2 __attribute__((vector_size(16)));
+ typedef cl_long __cl_long2 __attribute__((vector_size(16)));
+ typedef cl_double __cl_double2 __attribute__((vector_size(16)));
+ #else
+ typedef __m128i __cl_uchar16;
+ typedef __m128i __cl_char16;
+ typedef __m128i __cl_ushort8;
+ typedef __m128i __cl_short8;
+ typedef __m128i __cl_uint4;
+ typedef __m128i __cl_int4;
+ typedef __m128i __cl_ulong2;
+ typedef __m128i __cl_long2;
+ typedef __m128d __cl_double2;
+ #endif
+ #define __CL_UCHAR16__ 1
+ #define __CL_CHAR16__ 1
+ #define __CL_USHORT8__ 1
+ #define __CL_SHORT8__ 1
+ #define __CL_INT4__ 1
+ #define __CL_UINT4__ 1
+ #define __CL_ULONG2__ 1
+ #define __CL_LONG2__ 1
+ #define __CL_DOUBLE2__ 1
+#endif
+
+#if defined( __MMX__ )
+ #include <mmintrin.h>
+ #if defined( __GNUC__ ) && !defined( __ICC )
+ typedef cl_uchar __cl_uchar8 __attribute__((vector_size(8)));
+ typedef cl_char __cl_char8 __attribute__((vector_size(8)));
+ typedef cl_ushort __cl_ushort4 __attribute__((vector_size(8)));
+ typedef cl_short __cl_short4 __attribute__((vector_size(8)));
+ typedef cl_uint __cl_uint2 __attribute__((vector_size(8)));
+ typedef cl_int __cl_int2 __attribute__((vector_size(8)));
+ typedef cl_ulong __cl_ulong1 __attribute__((vector_size(8)));
+ typedef cl_long __cl_long1 __attribute__((vector_size(8)));
+ typedef cl_float __cl_float2 __attribute__((vector_size(8)));
+ #else
+ typedef __m64 __cl_uchar8;
+ typedef __m64 __cl_char8;
+ typedef __m64 __cl_ushort4;
+ typedef __m64 __cl_short4;
+ typedef __m64 __cl_uint2;
+ typedef __m64 __cl_int2;
+ typedef __m64 __cl_ulong1;
+ typedef __m64 __cl_long1;
+ typedef __m64 __cl_float2;
+ #endif
+ #define __CL_UCHAR8__ 1
+ #define __CL_CHAR8__ 1
+ #define __CL_USHORT4__ 1
+ #define __CL_SHORT4__ 1
+ #define __CL_INT2__ 1
+ #define __CL_UINT2__ 1
+ #define __CL_ULONG1__ 1
+ #define __CL_LONG1__ 1
+ #define __CL_FLOAT2__ 1
+#endif
+
+#if defined( __AVX__ )
+ #if defined( __MINGW64__ )
+ #include <intrin.h>
+ #else
+ #include <immintrin.h>
+ #endif
+ #if defined( __GNUC__ ) && !defined( __ICC )
+ typedef cl_float __cl_float8 __attribute__((vector_size(32)));
+ typedef cl_double __cl_double4 __attribute__((vector_size(32)));
+ #else
+ typedef __m256 __cl_float8;
+ typedef __m256d __cl_double4;
+ #endif
+ #define __CL_FLOAT8__ 1
+ #define __CL_DOUBLE4__ 1
+#endif
+
+/* Define alignment keys */
+#if defined( __GNUC__ )
+ #define CL_ALIGNED(_x) __attribute__ ((aligned(_x)))
+#elif defined( _WIN32) && (_MSC_VER)
+ /* Alignment keys neutered on windows because MSVC can't swallow function arguments with alignment requirements */
+ /* http://msdn.microsoft.com/en-us/library/373ak2y1%28VS.71%29.aspx */
+ /* #include <crtdefs.h> */
+ /* #define CL_ALIGNED(_x) _CRT_ALIGN(_x) */
+ #define CL_ALIGNED(_x)
+#else
+ #warning Need to implement some method to align data here
+ #define CL_ALIGNED(_x)
+#endif
+
+/* Indicate whether .xyzw, .s0123 and .hi.lo are supported */
+#if (defined( __GNUC__) && ! defined( __STRICT_ANSI__ )) || (defined( _MSC_VER ) && ! defined( __STDC__ ))
+ /* .xyzw and .s0123...{f|F} are supported */
+ #define CL_HAS_NAMED_VECTOR_FIELDS 1
+ /* .hi and .lo are supported */
+ #define CL_HAS_HI_LO_VECTOR_FIELDS 1
+
+ #define CL_NAMED_STRUCT_SUPPORTED
+#endif
+
+#if defined( CL_NAMED_STRUCT_SUPPORTED) && defined( _MSC_VER )
+#define __extension__ __pragma(warning(suppress:4201))
+#endif
+
+/* Define cl_vector types */
+
+/* ---- cl_charn ---- */
+typedef union
+{
+ cl_char CL_ALIGNED(2) s[2];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_char x, y; };
+ __extension__ struct{ cl_char s0, s1; };
+ __extension__ struct{ cl_char lo, hi; };
+#endif
+#if defined( __CL_CHAR2__)
+ __cl_char2 v2;
+#endif
+}cl_char2;
+
+typedef union
+{
+ cl_char CL_ALIGNED(4) s[4];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_char x, y, z, w; };
+ __extension__ struct{ cl_char s0, s1, s2, s3; };
+ __extension__ struct{ cl_char2 lo, hi; };
+#endif
+#if defined( __CL_CHAR2__)
+ __cl_char2 v2[2];
+#endif
+#if defined( __CL_CHAR4__)
+ __cl_char4 v4;
+#endif
+}cl_char4;
+
+/* cl_char3 is identical in size, alignment and behavior to cl_char4. See section 6.1.5. */
+typedef cl_char4 cl_char3;
+
+typedef union
+{
+ cl_char CL_ALIGNED(8) s[8];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_char x, y, z, w; };
+ __extension__ struct{ cl_char s0, s1, s2, s3, s4, s5, s6, s7; };
+ __extension__ struct{ cl_char4 lo, hi; };
+#endif
+#if defined( __CL_CHAR2__)
+ __cl_char2 v2[4];
+#endif
+#if defined( __CL_CHAR4__)
+ __cl_char4 v4[2];
+#endif
+#if defined( __CL_CHAR8__ )
+ __cl_char8 v8;
+#endif
+}cl_char8;
+
+typedef union
+{
+ cl_char CL_ALIGNED(16) s[16];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_char x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf; };
+ __extension__ struct{ cl_char s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF; };
+ __extension__ struct{ cl_char8 lo, hi; };
+#endif
+#if defined( __CL_CHAR2__)
+ __cl_char2 v2[8];
+#endif
+#if defined( __CL_CHAR4__)
+ __cl_char4 v4[4];
+#endif
+#if defined( __CL_CHAR8__ )
+ __cl_char8 v8[2];
+#endif
+#if defined( __CL_CHAR16__ )
+ __cl_char16 v16;
+#endif
+}cl_char16;
+
+
+/* ---- cl_ucharn ---- */
+typedef union
+{
+ cl_uchar CL_ALIGNED(2) s[2];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_uchar x, y; };
+ __extension__ struct{ cl_uchar s0, s1; };
+ __extension__ struct{ cl_uchar lo, hi; };
+#endif
+#if defined( __cl_uchar2__)
+ __cl_uchar2 v2;
+#endif
+}cl_uchar2;
+
+typedef union
+{
+ cl_uchar CL_ALIGNED(4) s[4];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_uchar x, y, z, w; };
+ __extension__ struct{ cl_uchar s0, s1, s2, s3; };
+ __extension__ struct{ cl_uchar2 lo, hi; };
+#endif
+#if defined( __CL_UCHAR2__)
+ __cl_uchar2 v2[2];
+#endif
+#if defined( __CL_UCHAR4__)
+ __cl_uchar4 v4;
+#endif
+}cl_uchar4;
+
+/* cl_uchar3 is identical in size, alignment and behavior to cl_uchar4. See section 6.1.5. */
+typedef cl_uchar4 cl_uchar3;
+
+typedef union
+{
+ cl_uchar CL_ALIGNED(8) s[8];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_uchar x, y, z, w; };
+ __extension__ struct{ cl_uchar s0, s1, s2, s3, s4, s5, s6, s7; };
+ __extension__ struct{ cl_uchar4 lo, hi; };
+#endif
+#if defined( __CL_UCHAR2__)
+ __cl_uchar2 v2[4];
+#endif
+#if defined( __CL_UCHAR4__)
+ __cl_uchar4 v4[2];
+#endif
+#if defined( __CL_UCHAR8__ )
+ __cl_uchar8 v8;
+#endif
+}cl_uchar8;
+
+typedef union
+{
+ cl_uchar CL_ALIGNED(16) s[16];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_uchar x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf; };
+ __extension__ struct{ cl_uchar s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF; };
+ __extension__ struct{ cl_uchar8 lo, hi; };
+#endif
+#if defined( __CL_UCHAR2__)
+ __cl_uchar2 v2[8];
+#endif
+#if defined( __CL_UCHAR4__)
+ __cl_uchar4 v4[4];
+#endif
+#if defined( __CL_UCHAR8__ )
+ __cl_uchar8 v8[2];
+#endif
+#if defined( __CL_UCHAR16__ )
+ __cl_uchar16 v16;
+#endif
+}cl_uchar16;
+
+
+/* ---- cl_shortn ---- */
+typedef union
+{
+ cl_short CL_ALIGNED(4) s[2];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_short x, y; };
+ __extension__ struct{ cl_short s0, s1; };
+ __extension__ struct{ cl_short lo, hi; };
+#endif
+#if defined( __CL_SHORT2__)
+ __cl_short2 v2;
+#endif
+}cl_short2;
+
+typedef union
+{
+ cl_short CL_ALIGNED(8) s[4];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_short x, y, z, w; };
+ __extension__ struct{ cl_short s0, s1, s2, s3; };
+ __extension__ struct{ cl_short2 lo, hi; };
+#endif
+#if defined( __CL_SHORT2__)
+ __cl_short2 v2[2];
+#endif
+#if defined( __CL_SHORT4__)
+ __cl_short4 v4;
+#endif
+}cl_short4;
+
+/* cl_short3 is identical in size, alignment and behavior to cl_short4. See section 6.1.5. */
+typedef cl_short4 cl_short3;
+
+typedef union
+{
+ cl_short CL_ALIGNED(16) s[8];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_short x, y, z, w; };
+ __extension__ struct{ cl_short s0, s1, s2, s3, s4, s5, s6, s7; };
+ __extension__ struct{ cl_short4 lo, hi; };
+#endif
+#if defined( __CL_SHORT2__)
+ __cl_short2 v2[4];
+#endif
+#if defined( __CL_SHORT4__)
+ __cl_short4 v4[2];
+#endif
+#if defined( __CL_SHORT8__ )
+ __cl_short8 v8;
+#endif
+}cl_short8;
+
+typedef union
+{
+ cl_short CL_ALIGNED(32) s[16];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_short x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf; };
+ __extension__ struct{ cl_short s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF; };
+ __extension__ struct{ cl_short8 lo, hi; };
+#endif
+#if defined( __CL_SHORT2__)
+ __cl_short2 v2[8];
+#endif
+#if defined( __CL_SHORT4__)
+ __cl_short4 v4[4];
+#endif
+#if defined( __CL_SHORT8__ )
+ __cl_short8 v8[2];
+#endif
+#if defined( __CL_SHORT16__ )
+ __cl_short16 v16;
+#endif
+}cl_short16;
+
+
+/* ---- cl_ushortn ---- */
+typedef union
+{
+ cl_ushort CL_ALIGNED(4) s[2];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_ushort x, y; };
+ __extension__ struct{ cl_ushort s0, s1; };
+ __extension__ struct{ cl_ushort lo, hi; };
+#endif
+#if defined( __CL_USHORT2__)
+ __cl_ushort2 v2;
+#endif
+}cl_ushort2;
+
+typedef union
+{
+ cl_ushort CL_ALIGNED(8) s[4];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_ushort x, y, z, w; };
+ __extension__ struct{ cl_ushort s0, s1, s2, s3; };
+ __extension__ struct{ cl_ushort2 lo, hi; };
+#endif
+#if defined( __CL_USHORT2__)
+ __cl_ushort2 v2[2];
+#endif
+#if defined( __CL_USHORT4__)
+ __cl_ushort4 v4;
+#endif
+}cl_ushort4;
+
+/* cl_ushort3 is identical in size, alignment and behavior to cl_ushort4. See section 6.1.5. */
+typedef cl_ushort4 cl_ushort3;
+
+typedef union
+{
+ cl_ushort CL_ALIGNED(16) s[8];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_ushort x, y, z, w; };
+ __extension__ struct{ cl_ushort s0, s1, s2, s3, s4, s5, s6, s7; };
+ __extension__ struct{ cl_ushort4 lo, hi; };
+#endif
+#if defined( __CL_USHORT2__)
+ __cl_ushort2 v2[4];
+#endif
+#if defined( __CL_USHORT4__)
+ __cl_ushort4 v4[2];
+#endif
+#if defined( __CL_USHORT8__ )
+ __cl_ushort8 v8;
+#endif
+}cl_ushort8;
+
+typedef union
+{
+ cl_ushort CL_ALIGNED(32) s[16];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_ushort x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf; };
+ __extension__ struct{ cl_ushort s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF; };
+ __extension__ struct{ cl_ushort8 lo, hi; };
+#endif
+#if defined( __CL_USHORT2__)
+ __cl_ushort2 v2[8];
+#endif
+#if defined( __CL_USHORT4__)
+ __cl_ushort4 v4[4];
+#endif
+#if defined( __CL_USHORT8__ )
+ __cl_ushort8 v8[2];
+#endif
+#if defined( __CL_USHORT16__ )
+ __cl_ushort16 v16;
+#endif
+}cl_ushort16;
+
+/* ---- cl_intn ---- */
+typedef union
+{
+ cl_int CL_ALIGNED(8) s[2];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_int x, y; };
+ __extension__ struct{ cl_int s0, s1; };
+ __extension__ struct{ cl_int lo, hi; };
+#endif
+#if defined( __CL_INT2__)
+ __cl_int2 v2;
+#endif
+}cl_int2;
+
+typedef union
+{
+ cl_int CL_ALIGNED(16) s[4];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_int x, y, z, w; };
+ __extension__ struct{ cl_int s0, s1, s2, s3; };
+ __extension__ struct{ cl_int2 lo, hi; };
+#endif
+#if defined( __CL_INT2__)
+ __cl_int2 v2[2];
+#endif
+#if defined( __CL_INT4__)
+ __cl_int4 v4;
+#endif
+}cl_int4;
+
+/* cl_int3 is identical in size, alignment and behavior to cl_int4. See section 6.1.5. */
+typedef cl_int4 cl_int3;
+
+typedef union
+{
+ cl_int CL_ALIGNED(32) s[8];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_int x, y, z, w; };
+ __extension__ struct{ cl_int s0, s1, s2, s3, s4, s5, s6, s7; };
+ __extension__ struct{ cl_int4 lo, hi; };
+#endif
+#if defined( __CL_INT2__)
+ __cl_int2 v2[4];
+#endif
+#if defined( __CL_INT4__)
+ __cl_int4 v4[2];
+#endif
+#if defined( __CL_INT8__ )
+ __cl_int8 v8;
+#endif
+}cl_int8;
+
+typedef union
+{
+ cl_int CL_ALIGNED(64) s[16];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_int x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf; };
+ __extension__ struct{ cl_int s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF; };
+ __extension__ struct{ cl_int8 lo, hi; };
+#endif
+#if defined( __CL_INT2__)
+ __cl_int2 v2[8];
+#endif
+#if defined( __CL_INT4__)
+ __cl_int4 v4[4];
+#endif
+#if defined( __CL_INT8__ )
+ __cl_int8 v8[2];
+#endif
+#if defined( __CL_INT16__ )
+ __cl_int16 v16;
+#endif
+}cl_int16;
+
+
+/* ---- cl_uintn ---- */
+typedef union
+{
+ cl_uint CL_ALIGNED(8) s[2];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_uint x, y; };
+ __extension__ struct{ cl_uint s0, s1; };
+ __extension__ struct{ cl_uint lo, hi; };
+#endif
+#if defined( __CL_UINT2__)
+ __cl_uint2 v2;
+#endif
+}cl_uint2;
+
+typedef union
+{
+ cl_uint CL_ALIGNED(16) s[4];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_uint x, y, z, w; };
+ __extension__ struct{ cl_uint s0, s1, s2, s3; };
+ __extension__ struct{ cl_uint2 lo, hi; };
+#endif
+#if defined( __CL_UINT2__)
+ __cl_uint2 v2[2];
+#endif
+#if defined( __CL_UINT4__)
+ __cl_uint4 v4;
+#endif
+}cl_uint4;
+
+/* cl_uint3 is identical in size, alignment and behavior to cl_uint4. See section 6.1.5. */
+typedef cl_uint4 cl_uint3;
+
+typedef union
+{
+ cl_uint CL_ALIGNED(32) s[8];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_uint x, y, z, w; };
+ __extension__ struct{ cl_uint s0, s1, s2, s3, s4, s5, s6, s7; };
+ __extension__ struct{ cl_uint4 lo, hi; };
+#endif
+#if defined( __CL_UINT2__)
+ __cl_uint2 v2[4];
+#endif
+#if defined( __CL_UINT4__)
+ __cl_uint4 v4[2];
+#endif
+#if defined( __CL_UINT8__ )
+ __cl_uint8 v8;
+#endif
+}cl_uint8;
+
+typedef union
+{
+ cl_uint CL_ALIGNED(64) s[16];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_uint x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf; };
+ __extension__ struct{ cl_uint s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF; };
+ __extension__ struct{ cl_uint8 lo, hi; };
+#endif
+#if defined( __CL_UINT2__)
+ __cl_uint2 v2[8];
+#endif
+#if defined( __CL_UINT4__)
+ __cl_uint4 v4[4];
+#endif
+#if defined( __CL_UINT8__ )
+ __cl_uint8 v8[2];
+#endif
+#if defined( __CL_UINT16__ )
+ __cl_uint16 v16;
+#endif
+}cl_uint16;
+
+/* ---- cl_longn ---- */
+typedef union
+{
+ cl_long CL_ALIGNED(16) s[2];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_long x, y; };
+ __extension__ struct{ cl_long s0, s1; };
+ __extension__ struct{ cl_long lo, hi; };
+#endif
+#if defined( __CL_LONG2__)
+ __cl_long2 v2;
+#endif
+}cl_long2;
+
+typedef union
+{
+ cl_long CL_ALIGNED(32) s[4];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_long x, y, z, w; };
+ __extension__ struct{ cl_long s0, s1, s2, s3; };
+ __extension__ struct{ cl_long2 lo, hi; };
+#endif
+#if defined( __CL_LONG2__)
+ __cl_long2 v2[2];
+#endif
+#if defined( __CL_LONG4__)
+ __cl_long4 v4;
+#endif
+}cl_long4;
+
+/* cl_long3 is identical in size, alignment and behavior to cl_long4. See section 6.1.5. */
+typedef cl_long4 cl_long3;
+
+typedef union
+{
+ cl_long CL_ALIGNED(64) s[8];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_long x, y, z, w; };
+ __extension__ struct{ cl_long s0, s1, s2, s3, s4, s5, s6, s7; };
+ __extension__ struct{ cl_long4 lo, hi; };
+#endif
+#if defined( __CL_LONG2__)
+ __cl_long2 v2[4];
+#endif
+#if defined( __CL_LONG4__)
+ __cl_long4 v4[2];
+#endif
+#if defined( __CL_LONG8__ )
+ __cl_long8 v8;
+#endif
+}cl_long8;
+
+typedef union
+{
+ cl_long CL_ALIGNED(128) s[16];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_long x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf; };
+ __extension__ struct{ cl_long s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF; };
+ __extension__ struct{ cl_long8 lo, hi; };
+#endif
+#if defined( __CL_LONG2__)
+ __cl_long2 v2[8];
+#endif
+#if defined( __CL_LONG4__)
+ __cl_long4 v4[4];
+#endif
+#if defined( __CL_LONG8__ )
+ __cl_long8 v8[2];
+#endif
+#if defined( __CL_LONG16__ )
+ __cl_long16 v16;
+#endif
+}cl_long16;
+
+
+/* ---- cl_ulongn ---- */
+typedef union
+{
+ cl_ulong CL_ALIGNED(16) s[2];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_ulong x, y; };
+ __extension__ struct{ cl_ulong s0, s1; };
+ __extension__ struct{ cl_ulong lo, hi; };
+#endif
+#if defined( __CL_ULONG2__)
+ __cl_ulong2 v2;
+#endif
+}cl_ulong2;
+
+typedef union
+{
+ cl_ulong CL_ALIGNED(32) s[4];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_ulong x, y, z, w; };
+ __extension__ struct{ cl_ulong s0, s1, s2, s3; };
+ __extension__ struct{ cl_ulong2 lo, hi; };
+#endif
+#if defined( __CL_ULONG2__)
+ __cl_ulong2 v2[2];
+#endif
+#if defined( __CL_ULONG4__)
+ __cl_ulong4 v4;
+#endif
+}cl_ulong4;
+
+/* cl_ulong3 is identical in size, alignment and behavior to cl_ulong4. See section 6.1.5. */
+typedef cl_ulong4 cl_ulong3;
+
+typedef union
+{
+ cl_ulong CL_ALIGNED(64) s[8];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_ulong x, y, z, w; };
+ __extension__ struct{ cl_ulong s0, s1, s2, s3, s4, s5, s6, s7; };
+ __extension__ struct{ cl_ulong4 lo, hi; };
+#endif
+#if defined( __CL_ULONG2__)
+ __cl_ulong2 v2[4];
+#endif
+#if defined( __CL_ULONG4__)
+ __cl_ulong4 v4[2];
+#endif
+#if defined( __CL_ULONG8__ )
+ __cl_ulong8 v8;
+#endif
+}cl_ulong8;
+
+typedef union
+{
+ cl_ulong CL_ALIGNED(128) s[16];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_ulong x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf; };
+ __extension__ struct{ cl_ulong s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF; };
+ __extension__ struct{ cl_ulong8 lo, hi; };
+#endif
+#if defined( __CL_ULONG2__)
+ __cl_ulong2 v2[8];
+#endif
+#if defined( __CL_ULONG4__)
+ __cl_ulong4 v4[4];
+#endif
+#if defined( __CL_ULONG8__ )
+ __cl_ulong8 v8[2];
+#endif
+#if defined( __CL_ULONG16__ )
+ __cl_ulong16 v16;
+#endif
+}cl_ulong16;
+
+
+/* --- cl_floatn ---- */
+
+typedef union
+{
+ cl_float CL_ALIGNED(8) s[2];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_float x, y; };
+ __extension__ struct{ cl_float s0, s1; };
+ __extension__ struct{ cl_float lo, hi; };
+#endif
+#if defined( __CL_FLOAT2__)
+ __cl_float2 v2;
+#endif
+}cl_float2;
+
+typedef union
+{
+ cl_float CL_ALIGNED(16) s[4];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_float x, y, z, w; };
+ __extension__ struct{ cl_float s0, s1, s2, s3; };
+ __extension__ struct{ cl_float2 lo, hi; };
+#endif
+#if defined( __CL_FLOAT2__)
+ __cl_float2 v2[2];
+#endif
+#if defined( __CL_FLOAT4__)
+ __cl_float4 v4;
+#endif
+}cl_float4;
+
+/* cl_float3 is identical in size, alignment and behavior to cl_float4. See section 6.1.5. */
+typedef cl_float4 cl_float3;
+
+typedef union
+{
+ cl_float CL_ALIGNED(32) s[8];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_float x, y, z, w; };
+ __extension__ struct{ cl_float s0, s1, s2, s3, s4, s5, s6, s7; };
+ __extension__ struct{ cl_float4 lo, hi; };
+#endif
+#if defined( __CL_FLOAT2__)
+ __cl_float2 v2[4];
+#endif
+#if defined( __CL_FLOAT4__)
+ __cl_float4 v4[2];
+#endif
+#if defined( __CL_FLOAT8__ )
+ __cl_float8 v8;
+#endif
+}cl_float8;
+
+typedef union
+{
+ cl_float CL_ALIGNED(64) s[16];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_float x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf; };
+ __extension__ struct{ cl_float s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF; };
+ __extension__ struct{ cl_float8 lo, hi; };
+#endif
+#if defined( __CL_FLOAT2__)
+ __cl_float2 v2[8];
+#endif
+#if defined( __CL_FLOAT4__)
+ __cl_float4 v4[4];
+#endif
+#if defined( __CL_FLOAT8__ )
+ __cl_float8 v8[2];
+#endif
+#if defined( __CL_FLOAT16__ )
+ __cl_float16 v16;
+#endif
+}cl_float16;
+
+/* --- cl_doublen ---- */
+
+typedef union
+{
+ cl_double CL_ALIGNED(16) s[2];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_double x, y; };
+ __extension__ struct{ cl_double s0, s1; };
+ __extension__ struct{ cl_double lo, hi; };
+#endif
+#if defined( __CL_DOUBLE2__)
+ __cl_double2 v2;
+#endif
+}cl_double2;
+
+typedef union
+{
+ cl_double CL_ALIGNED(32) s[4];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_double x, y, z, w; };
+ __extension__ struct{ cl_double s0, s1, s2, s3; };
+ __extension__ struct{ cl_double2 lo, hi; };
+#endif
+#if defined( __CL_DOUBLE2__)
+ __cl_double2 v2[2];
+#endif
+#if defined( __CL_DOUBLE4__)
+ __cl_double4 v4;
+#endif
+}cl_double4;
+
+/* cl_double3 is identical in size, alignment and behavior to cl_double4. See section 6.1.5. */
+typedef cl_double4 cl_double3;
+
+typedef union
+{
+ cl_double CL_ALIGNED(64) s[8];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_double x, y, z, w; };
+ __extension__ struct{ cl_double s0, s1, s2, s3, s4, s5, s6, s7; };
+ __extension__ struct{ cl_double4 lo, hi; };
+#endif
+#if defined( __CL_DOUBLE2__)
+ __cl_double2 v2[4];
+#endif
+#if defined( __CL_DOUBLE4__)
+ __cl_double4 v4[2];
+#endif
+#if defined( __CL_DOUBLE8__ )
+ __cl_double8 v8;
+#endif
+}cl_double8;
+
+typedef union
+{
+ cl_double CL_ALIGNED(128) s[16];
+#if defined( CL_NAMED_STRUCT_SUPPORTED )
+ __extension__ struct{ cl_double x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf; };
+ __extension__ struct{ cl_double s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF; };
+ __extension__ struct{ cl_double8 lo, hi; };
+#endif
+#if defined( __CL_DOUBLE2__)
+ __cl_double2 v2[8];
+#endif
+#if defined( __CL_DOUBLE4__)
+ __cl_double4 v4[4];
+#endif
+#if defined( __CL_DOUBLE8__ )
+ __cl_double8 v8[2];
+#endif
+#if defined( __CL_DOUBLE16__ )
+ __cl_double16 v16;
+#endif
+}cl_double16;
+
+/* Macro to facilitate debugging
+ * Usage:
+ * Place CL_PROGRAM_STRING_DEBUG_INFO on the line before the first line of your source.
+ * The first line ends with: CL_PROGRAM_STRING_BEGIN \"
+ * Each line thereafter of OpenCL C source must end with: \n\
+ * The last line ends in ";
+ *
+ * Example:
+ *
+ * const char *my_program = CL_PROGRAM_STRING_BEGIN "\
+ * kernel void foo( int a, float * b ) \n\
+ * { \n\
+ * // my comment \n\
+ * *b[ get_global_id(0)] = a; \n\
+ * } \n\
+ * ";
+ *
+ * This should correctly set up the line, (column) and file information for your source
+ * string so you can do source level debugging.
+ */
+#define __CL_STRINGIFY( _x ) # _x
+#define _CL_STRINGIFY( _x ) __CL_STRINGIFY( _x )
+#define CL_PROGRAM_STRING_DEBUG_INFO "#line " _CL_STRINGIFY(__LINE__) " \"" __FILE__ "\" \n\n"
+
+// CL.h contents
+/******************************************************************************/
+
+typedef struct _cl_platform_id * cl_platform_id;
+typedef struct _cl_device_id * cl_device_id;
+typedef struct _cl_context * cl_context;
+typedef struct _cl_command_queue * cl_command_queue;
+typedef struct _cl_mem * cl_mem;
+typedef struct _cl_program * cl_program;
+typedef struct _cl_kernel * cl_kernel;
+typedef struct _cl_event * cl_event;
+typedef struct _cl_sampler * cl_sampler;
+
+typedef cl_uint cl_bool; /* WARNING! Unlike cl_ types in cl_platform.h, cl_bool is not guaranteed to be the same size as the bool in kernels. */
+typedef cl_ulong cl_bitfield;
+typedef cl_bitfield cl_device_type;
+typedef cl_uint cl_platform_info;
+typedef cl_uint cl_device_info;
+typedef cl_bitfield cl_device_fp_config;
+typedef cl_uint cl_device_mem_cache_type;
+typedef cl_uint cl_device_local_mem_type;
+typedef cl_bitfield cl_device_exec_capabilities;
+typedef cl_bitfield cl_command_queue_properties;
+
+typedef intptr_t cl_context_properties;
+typedef cl_uint cl_context_info;
+typedef cl_uint cl_command_queue_info;
+typedef cl_uint cl_channel_order;
+typedef cl_uint cl_channel_type;
+typedef cl_bitfield cl_mem_flags;
+typedef cl_uint cl_mem_object_type;
+typedef cl_uint cl_mem_info;
+typedef cl_uint cl_image_info;
+typedef cl_uint cl_buffer_create_type;
+typedef cl_uint cl_addressing_mode;
+typedef cl_uint cl_filter_mode;
+typedef cl_uint cl_sampler_info;
+typedef cl_bitfield cl_map_flags;
+typedef cl_uint cl_program_info;
+typedef cl_uint cl_program_build_info;
+typedef cl_int cl_build_status;
+typedef cl_uint cl_kernel_info;
+typedef cl_uint cl_kernel_work_group_info;
+typedef cl_uint cl_event_info;
+typedef cl_uint cl_command_type;
+typedef cl_uint cl_profiling_info;
+
+typedef struct _cl_image_format {
+ cl_channel_order image_channel_order;
+ cl_channel_type image_channel_data_type;
+} cl_image_format;
+
+
+typedef struct _cl_buffer_region {
+ size_t origin;
+ size_t size;
+} cl_buffer_region;
+
+/******************************************************************************/
+
+/* Error Codes */
+#define CL_SUCCESS 0
+#define CL_DEVICE_NOT_FOUND -1
+#define CL_DEVICE_NOT_AVAILABLE -2
+#define CL_COMPILER_NOT_AVAILABLE -3
+#define CL_MEM_OBJECT_ALLOCATION_FAILURE -4
+#define CL_OUT_OF_RESOURCES -5
+#define CL_OUT_OF_HOST_MEMORY -6
+#define CL_PROFILING_INFO_NOT_AVAILABLE -7
+#define CL_MEM_COPY_OVERLAP -8
+#define CL_IMAGE_FORMAT_MISMATCH -9
+#define CL_IMAGE_FORMAT_NOT_SUPPORTED -10
+#define CL_BUILD_PROGRAM_FAILURE -11
+#define CL_MAP_FAILURE -12
+#define CL_MISALIGNED_SUB_BUFFER_OFFSET -13
+#define CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST -14
+
+#define CL_INVALID_VALUE -30
+#define CL_INVALID_DEVICE_TYPE -31
+#define CL_INVALID_PLATFORM -32
+#define CL_INVALID_DEVICE -33
+#define CL_INVALID_CONTEXT -34
+#define CL_INVALID_QUEUE_PROPERTIES -35
+#define CL_INVALID_COMMAND_QUEUE -36
+#define CL_INVALID_HOST_PTR -37
+#define CL_INVALID_MEM_OBJECT -38
+#define CL_INVALID_IMAGE_FORMAT_DESCRIPTOR -39
+#define CL_INVALID_IMAGE_SIZE -40
+#define CL_INVALID_SAMPLER -41
+#define CL_INVALID_BINARY -42
+#define CL_INVALID_BUILD_OPTIONS -43
+#define CL_INVALID_PROGRAM -44
+#define CL_INVALID_PROGRAM_EXECUTABLE -45
+#define CL_INVALID_KERNEL_NAME -46
+#define CL_INVALID_KERNEL_DEFINITION -47
+#define CL_INVALID_KERNEL -48
+#define CL_INVALID_ARG_INDEX -49
+#define CL_INVALID_ARG_VALUE -50
+#define CL_INVALID_ARG_SIZE -51
+#define CL_INVALID_KERNEL_ARGS -52
+#define CL_INVALID_WORK_DIMENSION -53
+#define CL_INVALID_WORK_GROUP_SIZE -54
+#define CL_INVALID_WORK_ITEM_SIZE -55
+#define CL_INVALID_GLOBAL_OFFSET -56
+#define CL_INVALID_EVENT_WAIT_LIST -57
+#define CL_INVALID_EVENT -58
+#define CL_INVALID_OPERATION -59
+#define CL_INVALID_GL_OBJECT -60
+#define CL_INVALID_BUFFER_SIZE -61
+#define CL_INVALID_MIP_LEVEL -62
+#define CL_INVALID_GLOBAL_WORK_SIZE -63
+#define CL_INVALID_PROPERTY -64
+
+/* OpenCL Version */
+#define CL_VERSION_1_0 1
+#define CL_VERSION_1_1 1
+
+/* cl_bool */
+#define CL_FALSE 0
+#define CL_TRUE 1
+
+/* cl_platform_info */
+#define CL_PLATFORM_PROFILE 0x0900
+#define CL_PLATFORM_VERSION 0x0901
+#define CL_PLATFORM_NAME 0x0902
+#define CL_PLATFORM_VENDOR 0x0903
+#define CL_PLATFORM_EXTENSIONS 0x0904
+
+/* cl_device_type - bitfield */
+#define CL_DEVICE_TYPE_DEFAULT (1 << 0)
+#define CL_DEVICE_TYPE_CPU (1 << 1)
+#define CL_DEVICE_TYPE_GPU (1 << 2)
+#define CL_DEVICE_TYPE_ACCELERATOR (1 << 3)
+#define CL_DEVICE_TYPE_ALL 0xFFFFFFFF
+
+/* cl_device_info */
+#define CL_DEVICE_TYPE 0x1000
+#define CL_DEVICE_VENDOR_ID 0x1001
+#define CL_DEVICE_MAX_COMPUTE_UNITS 0x1002
+#define CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS 0x1003
+#define CL_DEVICE_MAX_WORK_GROUP_SIZE 0x1004
+#define CL_DEVICE_MAX_WORK_ITEM_SIZES 0x1005
+#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR 0x1006
+#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT 0x1007
+#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT 0x1008
+#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG 0x1009
+#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT 0x100A
+#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE 0x100B
+#define CL_DEVICE_MAX_CLOCK_FREQUENCY 0x100C
+#define CL_DEVICE_ADDRESS_BITS 0x100D
+#define CL_DEVICE_MAX_READ_IMAGE_ARGS 0x100E
+#define CL_DEVICE_MAX_WRITE_IMAGE_ARGS 0x100F
+#define CL_DEVICE_MAX_MEM_ALLOC_SIZE 0x1010
+#define CL_DEVICE_IMAGE2D_MAX_WIDTH 0x1011
+#define CL_DEVICE_IMAGE2D_MAX_HEIGHT 0x1012
+#define CL_DEVICE_IMAGE3D_MAX_WIDTH 0x1013
+#define CL_DEVICE_IMAGE3D_MAX_HEIGHT 0x1014
+#define CL_DEVICE_IMAGE3D_MAX_DEPTH 0x1015
+#define CL_DEVICE_IMAGE_SUPPORT 0x1016
+#define CL_DEVICE_MAX_PARAMETER_SIZE 0x1017
+#define CL_DEVICE_MAX_SAMPLERS 0x1018
+#define CL_DEVICE_MEM_BASE_ADDR_ALIGN 0x1019
+#define CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE 0x101A
+#define CL_DEVICE_SINGLE_FP_CONFIG 0x101B
+#define CL_DEVICE_GLOBAL_MEM_CACHE_TYPE 0x101C
+#define CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE 0x101D
+#define CL_DEVICE_GLOBAL_MEM_CACHE_SIZE 0x101E
+#define CL_DEVICE_GLOBAL_MEM_SIZE 0x101F
+#define CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE 0x1020
+#define CL_DEVICE_MAX_CONSTANT_ARGS 0x1021
+#define CL_DEVICE_LOCAL_MEM_TYPE 0x1022
+#define CL_DEVICE_LOCAL_MEM_SIZE 0x1023
+#define CL_DEVICE_ERROR_CORRECTION_SUPPORT 0x1024
+#define CL_DEVICE_PROFILING_TIMER_RESOLUTION 0x1025
+#define CL_DEVICE_ENDIAN_LITTLE 0x1026
+#define CL_DEVICE_AVAILABLE 0x1027
+#define CL_DEVICE_COMPILER_AVAILABLE 0x1028
+#define CL_DEVICE_EXECUTION_CAPABILITIES 0x1029
+#define CL_DEVICE_QUEUE_PROPERTIES 0x102A
+#define CL_DEVICE_NAME 0x102B
+#define CL_DEVICE_VENDOR 0x102C
+#define CL_DRIVER_VERSION 0x102D
+#define CL_DEVICE_PROFILE 0x102E
+#define CL_DEVICE_VERSION 0x102F
+#define CL_DEVICE_EXTENSIONS 0x1030
+#define CL_DEVICE_PLATFORM 0x1031
+/* 0x1032 reserved for CL_DEVICE_DOUBLE_FP_CONFIG */
+/* 0x1033 reserved for CL_DEVICE_HALF_FP_CONFIG */
+#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF 0x1034
+#define CL_DEVICE_HOST_UNIFIED_MEMORY 0x1035
+#define CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR 0x1036
+#define CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT 0x1037
+#define CL_DEVICE_NATIVE_VECTOR_WIDTH_INT 0x1038
+#define CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG 0x1039
+#define CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT 0x103A
+#define CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE 0x103B
+#define CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF 0x103C
+#define CL_DEVICE_OPENCL_C_VERSION 0x103D
+
+/* cl_device_fp_config - bitfield */
+#define CL_FP_DENORM (1 << 0)
+#define CL_FP_INF_NAN (1 << 1)
+#define CL_FP_ROUND_TO_NEAREST (1 << 2)
+#define CL_FP_ROUND_TO_ZERO (1 << 3)
+#define CL_FP_ROUND_TO_INF (1 << 4)
+#define CL_FP_FMA (1 << 5)
+#define CL_FP_SOFT_FLOAT (1 << 6)
+
+/* cl_device_mem_cache_type */
+#define CL_NONE 0x0
+#define CL_READ_ONLY_CACHE 0x1
+#define CL_READ_WRITE_CACHE 0x2
+
+/* cl_device_local_mem_type */
+#define CL_LOCAL 0x1
+#define CL_GLOBAL 0x2
+
+/* cl_device_exec_capabilities - bitfield */
+#define CL_EXEC_KERNEL (1 << 0)
+#define CL_EXEC_NATIVE_KERNEL (1 << 1)
+
+/* cl_command_queue_properties - bitfield */
+#define CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE (1 << 0)
+#define CL_QUEUE_PROFILING_ENABLE (1 << 1)
+
+/* cl_context_info */
+#define CL_CONTEXT_REFERENCE_COUNT 0x1080
+#define CL_CONTEXT_DEVICES 0x1081
+#define CL_CONTEXT_PROPERTIES 0x1082
+#define CL_CONTEXT_NUM_DEVICES 0x1083
+
+/* cl_context_info + cl_context_properties */
+#define CL_CONTEXT_PLATFORM 0x1084
+
+/* cl_command_queue_info */
+#define CL_QUEUE_CONTEXT 0x1090
+#define CL_QUEUE_DEVICE 0x1091
+#define CL_QUEUE_REFERENCE_COUNT 0x1092
+#define CL_QUEUE_PROPERTIES 0x1093
+
+/* cl_mem_flags - bitfield */
+#define CL_MEM_READ_WRITE (1 << 0)
+#define CL_MEM_WRITE_ONLY (1 << 1)
+#define CL_MEM_READ_ONLY (1 << 2)
+#define CL_MEM_USE_HOST_PTR (1 << 3)
+#define CL_MEM_ALLOC_HOST_PTR (1 << 4)
+#define CL_MEM_COPY_HOST_PTR (1 << 5)
+
+/* cl_channel_order */
+#define CL_R 0x10B0
+#define CL_A 0x10B1
+#define CL_RG 0x10B2
+#define CL_RA 0x10B3
+#define CL_RGB 0x10B4
+#define CL_RGBA 0x10B5
+#define CL_BGRA 0x10B6
+#define CL_ARGB 0x10B7
+#define CL_INTENSITY 0x10B8
+#define CL_LUMINANCE 0x10B9
+#define CL_Rx 0x10BA
+#define CL_RGx 0x10BB
+#define CL_RGBx 0x10BC
+
+/* cl_channel_type */
+#define CL_SNORM_INT8 0x10D0
+#define CL_SNORM_INT16 0x10D1
+#define CL_UNORM_INT8 0x10D2
+#define CL_UNORM_INT16 0x10D3
+#define CL_UNORM_SHORT_565 0x10D4
+#define CL_UNORM_SHORT_555 0x10D5
+#define CL_UNORM_INT_101010 0x10D6
+#define CL_SIGNED_INT8 0x10D7
+#define CL_SIGNED_INT16 0x10D8
+#define CL_SIGNED_INT32 0x10D9
+#define CL_UNSIGNED_INT8 0x10DA
+#define CL_UNSIGNED_INT16 0x10DB
+#define CL_UNSIGNED_INT32 0x10DC
+#define CL_HALF_FLOAT 0x10DD
+#define CL_FLOAT 0x10DE
+
+/* cl_mem_object_type */
+#define CL_MEM_OBJECT_BUFFER 0x10F0
+#define CL_MEM_OBJECT_IMAGE2D 0x10F1
+#define CL_MEM_OBJECT_IMAGE3D 0x10F2
+
+/* cl_mem_info */
+#define CL_MEM_TYPE 0x1100
+#define CL_MEM_FLAGS 0x1101
+#define CL_MEM_SIZE 0x1102
+#define CL_MEM_HOST_PTR 0x1103
+#define CL_MEM_MAP_COUNT 0x1104
+#define CL_MEM_REFERENCE_COUNT 0x1105
+#define CL_MEM_CONTEXT 0x1106
+#define CL_MEM_ASSOCIATED_MEMOBJECT 0x1107
+#define CL_MEM_OFFSET 0x1108
+
+/* cl_image_info */
+#define CL_IMAGE_FORMAT 0x1110
+#define CL_IMAGE_ELEMENT_SIZE 0x1111
+#define CL_IMAGE_ROW_PITCH 0x1112
+#define CL_IMAGE_SLICE_PITCH 0x1113
+#define CL_IMAGE_WIDTH 0x1114
+#define CL_IMAGE_HEIGHT 0x1115
+#define CL_IMAGE_DEPTH 0x1116
+
+/* cl_addressing_mode */
+#define CL_ADDRESS_NONE 0x1130
+#define CL_ADDRESS_CLAMP_TO_EDGE 0x1131
+#define CL_ADDRESS_CLAMP 0x1132
+#define CL_ADDRESS_REPEAT 0x1133
+#define CL_ADDRESS_MIRRORED_REPEAT 0x1134
+
+/* cl_filter_mode */
+#define CL_FILTER_NEAREST 0x1140
+#define CL_FILTER_LINEAR 0x1141
+
+/* cl_sampler_info */
+#define CL_SAMPLER_REFERENCE_COUNT 0x1150
+#define CL_SAMPLER_CONTEXT 0x1151
+#define CL_SAMPLER_NORMALIZED_COORDS 0x1152
+#define CL_SAMPLER_ADDRESSING_MODE 0x1153
+#define CL_SAMPLER_FILTER_MODE 0x1154
+
+/* cl_map_flags - bitfield */
+#define CL_MAP_READ (1 << 0)
+#define CL_MAP_WRITE (1 << 1)
+
+/* cl_program_info */
+#define CL_PROGRAM_REFERENCE_COUNT 0x1160
+#define CL_PROGRAM_CONTEXT 0x1161
+#define CL_PROGRAM_NUM_DEVICES 0x1162
+#define CL_PROGRAM_DEVICES 0x1163
+#define CL_PROGRAM_SOURCE 0x1164
+#define CL_PROGRAM_BINARY_SIZES 0x1165
+#define CL_PROGRAM_BINARIES 0x1166
+
+/* cl_program_build_info */
+#define CL_PROGRAM_BUILD_STATUS 0x1181
+#define CL_PROGRAM_BUILD_OPTIONS 0x1182
+#define CL_PROGRAM_BUILD_LOG 0x1183
+
+/* cl_build_status */
+#define CL_BUILD_SUCCESS 0
+#define CL_BUILD_NONE -1
+#define CL_BUILD_ERROR -2
+#define CL_BUILD_IN_PROGRESS -3
+
+/* cl_kernel_info */
+#define CL_KERNEL_FUNCTION_NAME 0x1190
+#define CL_KERNEL_NUM_ARGS 0x1191
+#define CL_KERNEL_REFERENCE_COUNT 0x1192
+#define CL_KERNEL_CONTEXT 0x1193
+#define CL_KERNEL_PROGRAM 0x1194
+
+/* cl_kernel_work_group_info */
+#define CL_KERNEL_WORK_GROUP_SIZE 0x11B0
+#define CL_KERNEL_COMPILE_WORK_GROUP_SIZE 0x11B1
+#define CL_KERNEL_LOCAL_MEM_SIZE 0x11B2
+#define CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE 0x11B3
+#define CL_KERNEL_PRIVATE_MEM_SIZE 0x11B4
+
+/* cl_event_info */
+#define CL_EVENT_COMMAND_QUEUE 0x11D0
+#define CL_EVENT_COMMAND_TYPE 0x11D1
+#define CL_EVENT_REFERENCE_COUNT 0x11D2
+#define CL_EVENT_COMMAND_EXECUTION_STATUS 0x11D3
+#define CL_EVENT_CONTEXT 0x11D4
+
+/* cl_command_type */
+#define CL_COMMAND_NDRANGE_KERNEL 0x11F0
+#define CL_COMMAND_TASK 0x11F1
+#define CL_COMMAND_NATIVE_KERNEL 0x11F2
+#define CL_COMMAND_READ_BUFFER 0x11F3
+#define CL_COMMAND_WRITE_BUFFER 0x11F4
+#define CL_COMMAND_COPY_BUFFER 0x11F5
+#define CL_COMMAND_READ_IMAGE 0x11F6
+#define CL_COMMAND_WRITE_IMAGE 0x11F7
+#define CL_COMMAND_COPY_IMAGE 0x11F8
+#define CL_COMMAND_COPY_IMAGE_TO_BUFFER 0x11F9
+#define CL_COMMAND_COPY_BUFFER_TO_IMAGE 0x11FA
+#define CL_COMMAND_MAP_BUFFER 0x11FB
+#define CL_COMMAND_MAP_IMAGE 0x11FC
+#define CL_COMMAND_UNMAP_MEM_OBJECT 0x11FD
+#define CL_COMMAND_MARKER 0x11FE
+#define CL_COMMAND_ACQUIRE_GL_OBJECTS 0x11FF
+#define CL_COMMAND_RELEASE_GL_OBJECTS 0x1200
+#define CL_COMMAND_READ_BUFFER_RECT 0x1201
+#define CL_COMMAND_WRITE_BUFFER_RECT 0x1202
+#define CL_COMMAND_COPY_BUFFER_RECT 0x1203
+#define CL_COMMAND_USER 0x1204
+
+/* command execution status */
+#define CL_COMPLETE 0x0
+#define CL_RUNNING 0x1
+#define CL_SUBMITTED 0x2
+#define CL_QUEUED 0x3
+
+/* cl_buffer_create_type */
+#define CL_BUFFER_CREATE_TYPE_REGION 0x1220
+
+/* cl_profiling_info */
+#define CL_PROFILING_COMMAND_QUEUED 0x1280
+#define CL_PROFILING_COMMAND_SUBMIT 0x1281
+#define CL_PROFILING_COMMAND_START 0x1282
+#define CL_PROFILING_COMMAND_END 0x1283
+
+/********************************************************************************************************/
+
+/********************************************************************************************************/
+
+/* Function signature typedef's */
+
+/* Platform API */
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLGETPLATFORMIDS)(cl_uint /* num_entries */,
+ cl_platform_id * /* platforms */,
+ cl_uint * /* num_platforms */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLGETPLATFORMINFO)(cl_platform_id /* platform */,
+ cl_platform_info /* param_name */,
+ size_t /* param_value_size */,
+ void * /* param_value */,
+ size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+/* Device APIs */
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLGETDEVICEIDS)(cl_platform_id /* platform */,
+ cl_device_type /* device_type */,
+ cl_uint /* num_entries */,
+ cl_device_id * /* devices */,
+ cl_uint * /* num_devices */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLGETDEVICEINFO)(cl_device_id /* device */,
+ cl_device_info /* param_name */,
+ size_t /* param_value_size */,
+ void * /* param_value */,
+ size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+// Context APIs
+typedef CL_API_ENTRY cl_context (CL_API_CALL *
+PFNCLCREATECONTEXT)(const cl_context_properties * /* properties */,
+ cl_uint /* num_devices */,
+ const cl_device_id * /* devices */,
+ void (CL_CALLBACK * /* pfn_notify */)(const char *, const void *, size_t, void *),
+ void * /* user_data */,
+ cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_context (CL_API_CALL *
+PFNCLCREATECONTEXTFROMTYPE)(const cl_context_properties * /* properties */,
+ cl_device_type /* device_type */,
+ void (CL_CALLBACK * /* pfn_notify*/ )(const char *, const void *, size_t, void *),
+ void * /* user_data */,
+ cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLRETAINCONTEXT)(cl_context /* context */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLRELEASECONTEXT)(cl_context /* context */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLGETCONTEXTINFO)(cl_context /* context */,
+ cl_context_info /* param_name */,
+ size_t /* param_value_size */,
+ void * /* param_value */,
+ size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+/* Command Queue APIs */
+typedef CL_API_ENTRY cl_command_queue (CL_API_CALL *
+PFNCLCREATECOMMANDQUEUE)(cl_context /* context */,
+ cl_device_id /* device */,
+ cl_command_queue_properties /* properties */,
+ cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLRETAINCOMMANDQUEUE)(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLRELEASECOMMANDQUEUE)(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLGETCOMMANDQUEUEINFO)(cl_command_queue /* command_queue */,
+ cl_command_queue_info /* param_name */,
+ size_t /* param_value_size */,
+ void * /* param_value */,
+ size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLSETCOMMANDQUEUEPROPERTY)(cl_command_queue /* command_queue */,
+ cl_command_queue_properties /* properties */,
+ cl_bool /* enable */,
+ cl_command_queue_properties * /* old_properties */) CL_API_SUFFIX__VERSION_1_0;
+
+/* Memory Object APIs */
+typedef CL_API_ENTRY cl_mem (CL_API_CALL *
+PFNCLCREATEBUFFER)(cl_context /* context */,
+ cl_mem_flags /* flags */,
+ size_t /* size */,
+ void * /* host_ptr */,
+ cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_mem (CL_API_CALL *
+PFNCLCREATESUBBUFFER)(cl_mem /* buffer */,
+ cl_mem_flags /* flags */,
+ cl_buffer_create_type /* buffer_create_type */,
+ const void * /* buffer_create_info */,
+ cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_1;
+
+typedef CL_API_ENTRY cl_mem (CL_API_CALL *
+PFNCLCREATEIMAGE2D)(cl_context /* context */,
+ cl_mem_flags /* flags */,
+ const cl_image_format * /* image_format */,
+ size_t /* image_width */,
+ size_t /* image_height */,
+ size_t /* image_row_pitch */,
+ void * /* host_ptr */,
+ cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_mem (CL_API_CALL *
+PFNCLCREATEIMAGE3D)(cl_context /* context */,
+ cl_mem_flags /* flags */,
+ const cl_image_format * /* image_format */,
+ size_t /* image_width */,
+ size_t /* image_height */,
+ size_t /* image_depth */,
+ size_t /* image_row_pitch */,
+ size_t /* image_slice_pitch */,
+ void * /* host_ptr */,
+ cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLRETAINMEMOBJECT)(cl_mem /* memobj */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLRELEASEMEMOBJECT)(cl_mem /* memobj */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLGETSUPPORTEDIMAGEFORMATS)(cl_context /* context */,
+ cl_mem_flags /* flags */,
+ cl_mem_object_type /* image_type */,
+ cl_uint /* num_entries */,
+ cl_image_format * /* image_formats */,
+ cl_uint * /* num_image_formats */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLGETMEMOBJECTINFO)(cl_mem /* memobj */,
+ cl_mem_info /* param_name */,
+ size_t /* param_value_size */,
+ void * /* param_value */,
+ size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLGETIMAGEINFO)(cl_mem /* image */,
+ cl_image_info /* param_name */,
+ size_t /* param_value_size */,
+ void * /* param_value */,
+ size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLSETMEMOBJECTDESTRUCTORCALLBACK)( cl_mem /* memobj */,
+ void (CL_CALLBACK * /*pfn_notify*/)( cl_mem /* memobj */, void* /*user_data*/),
+ void * /*user_data */ ) CL_API_SUFFIX__VERSION_1_1;
+
+/* Sampler APIs */
+typedef CL_API_ENTRY cl_sampler (CL_API_CALL *
+PFNCLCREATESAMPLER)(cl_context /* context */,
+ cl_bool /* normalized_coords */,
+ cl_addressing_mode /* addressing_mode */,
+ cl_filter_mode /* filter_mode */,
+ cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLRETAINSAMPLER)(cl_sampler /* sampler */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLRELEASESAMPLER)(cl_sampler /* sampler */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLGETSAMPLERINFO)(cl_sampler /* sampler */,
+ cl_sampler_info /* param_name */,
+ size_t /* param_value_size */,
+ void * /* param_value */,
+ size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+/* Program Object APIs */
+typedef CL_API_ENTRY cl_program (CL_API_CALL *
+PFNCLCREATEPROGRAMWITHSOURCE)(cl_context /* context */,
+ cl_uint /* count */,
+ const char ** /* strings */,
+ const size_t * /* lengths */,
+ cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_program (CL_API_CALL *
+PFNCLCREATEPROGRAMWITHBINARY)(cl_context /* context */,
+ cl_uint /* num_devices */,
+ const cl_device_id * /* device_list */,
+ const size_t * /* lengths */,
+ const unsigned char ** /* binaries */,
+ cl_int * /* binary_status */,
+ cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLRETAINPROGRAM)(cl_program /* program */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLRELEASEPROGRAM)(cl_program /* program */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLBUILDPROGRAM)(cl_program /* program */,
+ cl_uint /* num_devices */,
+ const cl_device_id * /* device_list */,
+ const char * /* options */,
+ void (CL_CALLBACK * /* pfn_notify */)(cl_program /* program */, void * /* user_data */),
+ void * /* user_data */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLUNLOADCOMPILER)(void) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLGETPROGRAMINFO)(cl_program /* program */,
+ cl_program_info /* param_name */,
+ size_t /* param_value_size */,
+ void * /* param_value */,
+ size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLGETPROGRAMBUILDINFO)(cl_program /* program */,
+ cl_device_id /* device */,
+ cl_program_build_info /* param_name */,
+ size_t /* param_value_size */,
+ void * /* param_value */,
+ size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+/* Kernel Object APIs */
+typedef CL_API_ENTRY cl_kernel (CL_API_CALL *
+PFNCLCREATEKERNEL)(cl_program /* program */,
+ const char * /* kernel_name */,
+ cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLCREATEKERNELSINPROGRAM)(cl_program /* program */,
+ cl_uint /* num_kernels */,
+ cl_kernel * /* kernels */,
+ cl_uint * /* num_kernels_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLRETAINKERNEL)(cl_kernel /* kernel */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLRELEASEKERNEL)(cl_kernel /* kernel */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLSETKERNELARG)(cl_kernel /* kernel */,
+ cl_uint /* arg_index */,
+ size_t /* arg_size */,
+ const void * /* arg_value */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLGETKERNELINFO)(cl_kernel /* kernel */,
+ cl_kernel_info /* param_name */,
+ size_t /* param_value_size */,
+ void * /* param_value */,
+ size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLGETKERNELWORKGROUPINFO)(cl_kernel /* kernel */,
+ cl_device_id /* device */,
+ cl_kernel_work_group_info /* param_name */,
+ size_t /* param_value_size */,
+ void * /* param_value */,
+ size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+// Event Object APIs
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLWAITFOREVENTS)(cl_uint /* num_events */,
+ const cl_event * /* event_list */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLGETEVENTINFO)(cl_event /* event */,
+ cl_event_info /* param_name */,
+ size_t /* param_value_size */,
+ void * /* param_value */,
+ size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_event (CL_API_CALL *
+PFNCLCREATEUSEREVENT)(cl_context /* context */,
+ cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_1;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLRETAINEVENT)(cl_event /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLRELEASEEVENT)(cl_event /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLSETUSEREVENTSTATUS)(cl_event /* event */,
+ cl_int /* execution_status */) CL_API_SUFFIX__VERSION_1_1;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLSETEVENTCALLBACK)( cl_event /* event */,
+ cl_int /* command_exec_callback_type */,
+ void (CL_CALLBACK * /* pfn_notify */)(cl_event, cl_int, void *),
+ void * /* user_data */) CL_API_SUFFIX__VERSION_1_1;
+
+/* Profiling APIs */
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLGETEVENTPROFILINGINFO)(cl_event /* event */,
+ cl_profiling_info /* param_name */,
+ size_t /* param_value_size */,
+ void * /* param_value */,
+ size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+// Flush and Finish APIs
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLFLUSH)(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLFINISH)(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0;
+
+/* Enqueued Commands APIs */
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLENQUEUEREADBUFFER)(cl_command_queue /* command_queue */,
+ cl_mem /* buffer */,
+ cl_bool /* blocking_read */,
+ size_t /* offset */,
+ size_t /* cb */,
+ void * /* ptr */,
+ cl_uint /* num_events_in_wait_list */,
+ const cl_event * /* event_wait_list */,
+ cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLENQUEUEREADBUFFERRECT)(cl_command_queue /* command_queue */,
+ cl_mem /* buffer */,
+ cl_bool /* blocking_read */,
+ const size_t * /* buffer_origin */,
+ const size_t * /* host_origin */,
+ const size_t * /* region */,
+ size_t /* buffer_row_pitch */,
+ size_t /* buffer_slice_pitch */,
+ size_t /* host_row_pitch */,
+ size_t /* host_slice_pitch */,
+ void * /* ptr */,
+ cl_uint /* num_events_in_wait_list */,
+ const cl_event * /* event_wait_list */,
+ cl_event * /* event */) CL_API_SUFFIX__VERSION_1_1;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLENQUEUEWRITEBUFFER)(cl_command_queue /* command_queue */,
+ cl_mem /* buffer */,
+ cl_bool /* blocking_write */,
+ size_t /* offset */,
+ size_t /* cb */,
+ const void * /* ptr */,
+ cl_uint /* num_events_in_wait_list */,
+ const cl_event * /* event_wait_list */,
+ cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLENQUEUEWRITEBUFFERRECT)(cl_command_queue /* command_queue */,
+ cl_mem /* buffer */,
+ cl_bool /* blocking_write */,
+ const size_t * /* buffer_origin */,
+ const size_t * /* host_origin */,
+ const size_t * /* region */,
+ size_t /* buffer_row_pitch */,
+ size_t /* buffer_slice_pitch */,
+ size_t /* host_row_pitch */,
+ size_t /* host_slice_pitch */,
+ const void * /* ptr */,
+ cl_uint /* num_events_in_wait_list */,
+ const cl_event * /* event_wait_list */,
+ cl_event * /* event */) CL_API_SUFFIX__VERSION_1_1;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLENQUEUECOPYBUFFER)(cl_command_queue /* command_queue */,
+ cl_mem /* src_buffer */,
+ cl_mem /* dst_buffer */,
+ size_t /* src_offset */,
+ size_t /* dst_offset */,
+ size_t /* cb */,
+ cl_uint /* num_events_in_wait_list */,
+ const cl_event * /* event_wait_list */,
+ cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLENQUEUECOPYBUFFERRECT)(cl_command_queue /* command_queue */,
+ cl_mem /* src_buffer */,
+ cl_mem /* dst_buffer */,
+ const size_t * /* src_origin */,
+ const size_t * /* dst_origin */,
+ const size_t * /* region */,
+ size_t /* src_row_pitch */,
+ size_t /* src_slice_pitch */,
+ size_t /* dst_row_pitch */,
+ size_t /* dst_slice_pitch */,
+ cl_uint /* num_events_in_wait_list */,
+ const cl_event * /* event_wait_list */,
+ cl_event * /* event */) CL_API_SUFFIX__VERSION_1_1;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLENQUEUEREADIMAGE)(cl_command_queue /* command_queue */,
+ cl_mem /* image */,
+ cl_bool /* blocking_read */,
+ const size_t * /* origin[3] */,
+ const size_t * /* region[3] */,
+ size_t /* row_pitch */,
+ size_t /* slice_pitch */,
+ void * /* ptr */,
+ cl_uint /* num_events_in_wait_list */,
+ const cl_event * /* event_wait_list */,
+ cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLENQUEUEWRITEIMAGE)(cl_command_queue /* command_queue */,
+ cl_mem /* image */,
+ cl_bool /* blocking_write */,
+ const size_t * /* origin[3] */,
+ const size_t * /* region[3] */,
+ size_t /* input_row_pitch */,
+ size_t /* input_slice_pitch */,
+ const void * /* ptr */,
+ cl_uint /* num_events_in_wait_list */,
+ const cl_event * /* event_wait_list */,
+ cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLENQUEUECOPYIMAGE)(cl_command_queue /* command_queue */,
+ cl_mem /* src_image */,
+ cl_mem /* dst_image */,
+ const size_t * /* src_origin[3] */,
+ const size_t * /* dst_origin[3] */,
+ const size_t * /* region[3] */,
+ cl_uint /* num_events_in_wait_list */,
+ const cl_event * /* event_wait_list */,
+ cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLENQUEUECOPYIMAGETOBUFFER)(cl_command_queue /* command_queue */,
+ cl_mem /* src_image */,
+ cl_mem /* dst_buffer */,
+ const size_t * /* src_origin[3] */,
+ const size_t * /* region[3] */,
+ size_t /* dst_offset */,
+ cl_uint /* num_events_in_wait_list */,
+ const cl_event * /* event_wait_list */,
+ cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLENQUEUECOPYBUFFERTOIMAGE)(cl_command_queue /* command_queue */,
+ cl_mem /* src_buffer */,
+ cl_mem /* dst_image */,
+ size_t /* src_offset */,
+ const size_t * /* dst_origin[3] */,
+ const size_t * /* region[3] */,
+ cl_uint /* num_events_in_wait_list */,
+ const cl_event * /* event_wait_list */,
+ cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY void * (CL_API_CALL *
+PFNCLENQUEUEMAPBUFFER)(cl_command_queue /* command_queue */,
+ cl_mem /* buffer */,
+ cl_bool /* blocking_map */,
+ cl_map_flags /* map_flags */,
+ size_t /* offset */,
+ size_t /* cb */,
+ cl_uint /* num_events_in_wait_list */,
+ const cl_event * /* event_wait_list */,
+ cl_event * /* event */,
+ cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY void * (CL_API_CALL *
+PFNCLENQUEUEMAPIMAGE)(cl_command_queue /* command_queue */,
+ cl_mem /* image */,
+ cl_bool /* blocking_map */,
+ cl_map_flags /* map_flags */,
+ const size_t * /* origin[3] */,
+ const size_t * /* region[3] */,
+ size_t * /* image_row_pitch */,
+ size_t * /* image_slice_pitch */,
+ cl_uint /* num_events_in_wait_list */,
+ const cl_event * /* event_wait_list */,
+ cl_event * /* event */,
+ cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLENQUEUEUNMAPMEMOBJECT)(cl_command_queue /* command_queue */,
+ cl_mem /* memobj */,
+ void * /* mapped_ptr */,
+ cl_uint /* num_events_in_wait_list */,
+ const cl_event * /* event_wait_list */,
+ cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLENQUEUENDRANGEKERNEL)(cl_command_queue /* command_queue */,
+ cl_kernel /* kernel */,
+ cl_uint /* work_dim */,
+ const size_t * /* global_work_offset */,
+ const size_t * /* global_work_size */,
+ const size_t * /* local_work_size */,
+ cl_uint /* num_events_in_wait_list */,
+ const cl_event * /* event_wait_list */,
+ cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLENQUEUETASK)(cl_command_queue /* command_queue */,
+ cl_kernel /* kernel */,
+ cl_uint /* num_events_in_wait_list */,
+ const cl_event * /* event_wait_list */,
+ cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLENQUEUENATIVEKERNEL)(cl_command_queue /* command_queue */,
+ void (*user_func)(void *),
+ void * /* args */,
+ size_t /* cb_args */,
+ cl_uint /* num_mem_objects */,
+ const cl_mem * /* mem_list */,
+ const void ** /* args_mem_loc */,
+ cl_uint /* num_events_in_wait_list */,
+ const cl_event * /* event_wait_list */,
+ cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLENQUEUEMARKER)(cl_command_queue /* command_queue */,
+ cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLENQUEUEWAITFOREVENTS)(cl_command_queue /* command_queue */,
+ cl_uint /* num_events */,
+ const cl_event * /* event_list */) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *
+PFNCLENQUEUEBARRIER)(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0;
+
+// Extension function access
+//
+// Returns the extension function address for the given function name,
+// or NULL if a valid function can not be found. The client must
+// check to make sure the address is not NULL, before using or
+// calling the returned function address.
+//
+typedef CL_API_ENTRY void * (CL_API_CALL * PFNCLGETEXTENSIONFUNCTIONADDRESS)(const char * /* func_name */) CL_API_SUFFIX__VERSION_1_0;
+
+
+#define CLEW_STATIC
+
+#ifdef CLEW_STATIC
+# define CLEWAPI extern
+#else
+# ifdef CLEW_BUILD
+# define CLEWAPI extern __declspec(dllexport)
+# else
+# define CLEWAPI extern __declspec(dllimport)
+# endif
+#endif
+
+#if defined(_WIN32)
+#define CLEW_FUN_EXPORT extern
+#else
+#define CLEW_FUN_EXPORT CLEWAPI
+#endif
+
+#define CLEW_GET_FUN(x) x
+
+
+// Variables holding function entry points
+CLEW_FUN_EXPORT PFNCLGETPLATFORMIDS __clewGetPlatformIDs ;
+CLEW_FUN_EXPORT PFNCLGETPLATFORMINFO __clewGetPlatformInfo ;
+CLEW_FUN_EXPORT PFNCLGETDEVICEIDS __clewGetDeviceIDs ;
+CLEW_FUN_EXPORT PFNCLGETDEVICEINFO __clewGetDeviceInfo ;
+CLEW_FUN_EXPORT PFNCLCREATECONTEXT __clewCreateContext ;
+CLEW_FUN_EXPORT PFNCLCREATECONTEXTFROMTYPE __clewCreateContextFromType ;
+CLEW_FUN_EXPORT PFNCLRETAINCONTEXT __clewRetainContext ;
+CLEW_FUN_EXPORT PFNCLRELEASECONTEXT __clewReleaseContext ;
+CLEW_FUN_EXPORT PFNCLGETCONTEXTINFO __clewGetContextInfo ;
+CLEW_FUN_EXPORT PFNCLCREATECOMMANDQUEUE __clewCreateCommandQueue ;
+CLEW_FUN_EXPORT PFNCLRETAINCOMMANDQUEUE __clewRetainCommandQueue ;
+CLEW_FUN_EXPORT PFNCLRELEASECOMMANDQUEUE __clewReleaseCommandQueue ;
+CLEW_FUN_EXPORT PFNCLGETCOMMANDQUEUEINFO __clewGetCommandQueueInfo ;
+#ifdef CL_USE_DEPRECATED_OPENCL_1_0_APIS
+CLEW_FUN_EXPORT PFNCLSETCOMMANDQUEUEPROPERTY __clewSetCommandQueueProperty ;
+#endif
+CLEW_FUN_EXPORT PFNCLCREATEBUFFER __clewCreateBuffer ;
+CLEW_FUN_EXPORT PFNCLCREATESUBBUFFER __clewCreateSubBuffer ;
+CLEW_FUN_EXPORT PFNCLCREATEIMAGE2D __clewCreateImage2D ;
+CLEW_FUN_EXPORT PFNCLCREATEIMAGE3D __clewCreateImage3D ;
+CLEW_FUN_EXPORT PFNCLRETAINMEMOBJECT __clewRetainMemObject ;
+CLEW_FUN_EXPORT PFNCLRELEASEMEMOBJECT __clewReleaseMemObject ;
+CLEW_FUN_EXPORT PFNCLGETSUPPORTEDIMAGEFORMATS __clewGetSupportedImageFormats ;
+CLEW_FUN_EXPORT PFNCLGETMEMOBJECTINFO __clewGetMemObjectInfo ;
+CLEW_FUN_EXPORT PFNCLGETIMAGEINFO __clewGetImageInfo ;
+CLEW_FUN_EXPORT PFNCLSETMEMOBJECTDESTRUCTORCALLBACK __clewSetMemObjectDestructorCallback;
+CLEW_FUN_EXPORT PFNCLCREATESAMPLER __clewCreateSampler ;
+CLEW_FUN_EXPORT PFNCLRETAINSAMPLER __clewRetainSampler ;
+CLEW_FUN_EXPORT PFNCLRELEASESAMPLER __clewReleaseSampler ;
+CLEW_FUN_EXPORT PFNCLGETSAMPLERINFO __clewGetSamplerInfo ;
+CLEW_FUN_EXPORT PFNCLCREATEPROGRAMWITHSOURCE __clewCreateProgramWithSource ;
+CLEW_FUN_EXPORT PFNCLCREATEPROGRAMWITHBINARY __clewCreateProgramWithBinary ;
+CLEW_FUN_EXPORT PFNCLRETAINPROGRAM __clewRetainProgram ;
+CLEW_FUN_EXPORT PFNCLRELEASEPROGRAM __clewReleaseProgram ;
+CLEW_FUN_EXPORT PFNCLBUILDPROGRAM __clewBuildProgram ;
+CLEW_FUN_EXPORT PFNCLUNLOADCOMPILER __clewUnloadCompiler ;
+CLEW_FUN_EXPORT PFNCLGETPROGRAMINFO __clewGetProgramInfo ;
+CLEW_FUN_EXPORT PFNCLGETPROGRAMBUILDINFO __clewGetProgramBuildInfo ;
+CLEW_FUN_EXPORT PFNCLCREATEKERNEL __clewCreateKernel ;
+CLEW_FUN_EXPORT PFNCLCREATEKERNELSINPROGRAM __clewCreateKernelsInProgram ;
+CLEW_FUN_EXPORT PFNCLRETAINKERNEL __clewRetainKernel ;
+CLEW_FUN_EXPORT PFNCLRELEASEKERNEL __clewReleaseKernel ;
+CLEW_FUN_EXPORT PFNCLSETKERNELARG __clewSetKernelArg ;
+CLEW_FUN_EXPORT PFNCLGETKERNELINFO __clewGetKernelInfo ;
+CLEW_FUN_EXPORT PFNCLGETKERNELWORKGROUPINFO __clewGetKernelWorkGroupInfo ;
+CLEW_FUN_EXPORT PFNCLWAITFOREVENTS __clewWaitForEvents ;
+CLEW_FUN_EXPORT PFNCLGETEVENTINFO __clewGetEventInfo ;
+CLEW_FUN_EXPORT PFNCLCREATEUSEREVENT __clewCreateUserEvent ;
+CLEW_FUN_EXPORT PFNCLRETAINEVENT __clewRetainEvent ;
+CLEW_FUN_EXPORT PFNCLRELEASEEVENT __clewReleaseEvent ;
+CLEW_FUN_EXPORT PFNCLSETUSEREVENTSTATUS __clewSetUserEventStatus ;
+CLEW_FUN_EXPORT PFNCLSETEVENTCALLBACK __clewSetEventCallback ;
+CLEW_FUN_EXPORT PFNCLGETEVENTPROFILINGINFO __clewGetEventProfilingInfo ;
+CLEW_FUN_EXPORT PFNCLFLUSH __clewFlush ;
+CLEW_FUN_EXPORT PFNCLFINISH __clewFinish ;
+CLEW_FUN_EXPORT PFNCLENQUEUEREADBUFFER __clewEnqueueReadBuffer ;
+CLEW_FUN_EXPORT PFNCLENQUEUEREADBUFFERRECT __clewEnqueueReadBufferRect ;
+CLEW_FUN_EXPORT PFNCLENQUEUEWRITEBUFFER __clewEnqueueWriteBuffer ;
+CLEW_FUN_EXPORT PFNCLENQUEUEWRITEBUFFERRECT __clewEnqueueWriteBufferRect ;
+CLEW_FUN_EXPORT PFNCLENQUEUECOPYBUFFER __clewEnqueueCopyBuffer ;
+CLEW_FUN_EXPORT PFNCLENQUEUECOPYBUFFERRECT __clewEnqueueCopyBufferRect ;
+CLEW_FUN_EXPORT PFNCLENQUEUEREADIMAGE __clewEnqueueReadImage ;
+CLEW_FUN_EXPORT PFNCLENQUEUEWRITEIMAGE __clewEnqueueWriteImage ;
+CLEW_FUN_EXPORT PFNCLENQUEUECOPYIMAGE __clewEnqueueCopyImage ;
+CLEW_FUN_EXPORT PFNCLENQUEUECOPYIMAGETOBUFFER __clewEnqueueCopyImageToBuffer ;
+CLEW_FUN_EXPORT PFNCLENQUEUECOPYBUFFERTOIMAGE __clewEnqueueCopyBufferToImage ;
+CLEW_FUN_EXPORT PFNCLENQUEUEMAPBUFFER __clewEnqueueMapBuffer ;
+CLEW_FUN_EXPORT PFNCLENQUEUEMAPIMAGE __clewEnqueueMapImage ;
+CLEW_FUN_EXPORT PFNCLENQUEUEUNMAPMEMOBJECT __clewEnqueueUnmapMemObject ;
+CLEW_FUN_EXPORT PFNCLENQUEUENDRANGEKERNEL __clewEnqueueNDRangeKernel ;
+CLEW_FUN_EXPORT PFNCLENQUEUETASK __clewEnqueueTask ;
+CLEW_FUN_EXPORT PFNCLENQUEUENATIVEKERNEL __clewEnqueueNativeKernel ;
+CLEW_FUN_EXPORT PFNCLENQUEUEMARKER __clewEnqueueMarker ;
+CLEW_FUN_EXPORT PFNCLENQUEUEWAITFOREVENTS __clewEnqueueWaitForEvents ;
+CLEW_FUN_EXPORT PFNCLENQUEUEBARRIER __clewEnqueueBarrier ;
+CLEW_FUN_EXPORT PFNCLGETEXTENSIONFUNCTIONADDRESS __clewGetExtensionFunctionAddress ;
+
+
+#define clGetPlatformIDs CLEW_GET_FUN(__clewGetPlatformIDs )
+#define clGetPlatformInfo CLEW_GET_FUN(__clewGetPlatformInfo )
+#define clGetDeviceIDs CLEW_GET_FUN(__clewGetDeviceIDs )
+#define clGetDeviceInfo CLEW_GET_FUN(__clewGetDeviceInfo )
+#define clCreateContext CLEW_GET_FUN(__clewCreateContext )
+#define clCreateContextFromType CLEW_GET_FUN(__clewCreateContextFromType )
+#define clRetainContext CLEW_GET_FUN(__clewRetainContext )
+#define clReleaseContext CLEW_GET_FUN(__clewReleaseContext )
+#define clGetContextInfo CLEW_GET_FUN(__clewGetContextInfo )
+#define clCreateCommandQueue CLEW_GET_FUN(__clewCreateCommandQueue )
+#define clRetainCommandQueue CLEW_GET_FUN(__clewRetainCommandQueue )
+#define clReleaseCommandQueue CLEW_GET_FUN(__clewReleaseCommandQueue )
+#define clGetCommandQueueInfo CLEW_GET_FUN(__clewGetCommandQueueInfo )
+#ifdef CL_USE_DEPRECATED_OPENCL_1_0_APIS
+#warning CL_USE_DEPRECATED_OPENCL_1_0_APIS is defined. These APIs are unsupported and untested in OpenCL 1.1!
+/*
+ * WARNING:
+ * This API introduces mutable state into the OpenCL implementation. It has been REMOVED
+ * to better facilitate thread safety. The 1.0 API is not thread safe. It is not tested by the
+ * OpenCL 1.1 conformance test, and consequently may not work or may not work dependably.
+ * It is likely to be non-performant. Use of this API is not advised. Use at your own risk.
+ *
+ * Software developers previously relying on this API are instructed to set the command queue
+ * properties when creating the queue, instead.
+ */
+#define clSetCommandQueueProperty CLEW_GET_FUN(__clewSetCommandQueueProperty )
+#endif /* CL_USE_DEPRECATED_OPENCL_1_0_APIS */
+#define clCreateBuffer CLEW_GET_FUN(__clewCreateBuffer )
+#define clCreateSubBuffer CLEW_GET_FUN(__clewCreateSubBuffer )
+#define clCreateImage2D CLEW_GET_FUN(__clewCreateImage2D )
+#define clCreateImage3D CLEW_GET_FUN(__clewCreateImage3D )
+#define clRetainMemObject CLEW_GET_FUN(__clewRetainMemObject )
+#define clReleaseMemObject CLEW_GET_FUN(__clewReleaseMemObject )
+#define clGetSupportedImageFormats CLEW_GET_FUN(__clewGetSupportedImageFormats )
+#define clGetMemObjectInfo CLEW_GET_FUN(__clewGetMemObjectInfo )
+#define clGetImageInfo CLEW_GET_FUN(__clewGetImageInfo )
+#define clSetMemObjectDestructorCallback CLEW_GET_FUN(__clewSetMemObjectDestructorCallback)
+#define clCreateSampler CLEW_GET_FUN(__clewCreateSampler )
+#define clRetainSampler CLEW_GET_FUN(__clewRetainSampler )
+#define clReleaseSampler CLEW_GET_FUN(__clewReleaseSampler )
+#define clGetSamplerInfo CLEW_GET_FUN(__clewGetSamplerInfo )
+#define clCreateProgramWithSource CLEW_GET_FUN(__clewCreateProgramWithSource )
+#define clCreateProgramWithBinary CLEW_GET_FUN(__clewCreateProgramWithBinary )
+#define clRetainProgram CLEW_GET_FUN(__clewRetainProgram )
+#define clReleaseProgram CLEW_GET_FUN(__clewReleaseProgram )
+#define clBuildProgram CLEW_GET_FUN(__clewBuildProgram )
+#define clUnloadCompiler CLEW_GET_FUN(__clewUnloadCompiler )
+#define clGetProgramInfo CLEW_GET_FUN(__clewGetProgramInfo )
+#define clGetProgramBuildInfo CLEW_GET_FUN(__clewGetProgramBuildInfo )
+#define clCreateKernel CLEW_GET_FUN(__clewCreateKernel )
+#define clCreateKernelsInProgram CLEW_GET_FUN(__clewCreateKernelsInProgram )
+#define clRetainKernel CLEW_GET_FUN(__clewRetainKernel )
+#define clReleaseKernel CLEW_GET_FUN(__clewReleaseKernel )
+#define clSetKernelArg CLEW_GET_FUN(__clewSetKernelArg )
+#define clGetKernelInfo CLEW_GET_FUN(__clewGetKernelInfo )
+#define clGetKernelWorkGroupInfo CLEW_GET_FUN(__clewGetKernelWorkGroupInfo )
+#define clWaitForEvents CLEW_GET_FUN(__clewWaitForEvents )
+#define clGetEventInfo CLEW_GET_FUN(__clewGetEventInfo )
+#define clCreateUserEvent CLEW_GET_FUN(__clewCreateUserEvent )
+#define clRetainEvent CLEW_GET_FUN(__clewRetainEvent )
+#define clReleaseEvent CLEW_GET_FUN(__clewReleaseEvent )
+#define clSetUserEventStatus CLEW_GET_FUN(__clewSetUserEventStatus )
+#define clSetEventCallback CLEW_GET_FUN(__clewSetEventCallback )
+#define clGetEventProfilingInfo CLEW_GET_FUN(__clewGetEventProfilingInfo )
+#define clFlush CLEW_GET_FUN(__clewFlush )
+#define clFinish CLEW_GET_FUN(__clewFinish )
+#define clEnqueueReadBuffer CLEW_GET_FUN(__clewEnqueueReadBuffer )
+#define clEnqueueReadBufferRect CLEW_GET_FUN(__clewEnqueueReadBufferRect )
+#define clEnqueueWriteBuffer CLEW_GET_FUN(__clewEnqueueWriteBuffer )
+#define clEnqueueWriteBufferRect CLEW_GET_FUN(__clewEnqueueWriteBufferRect )
+#define clEnqueueCopyBuffer CLEW_GET_FUN(__clewEnqueueCopyBuffer )
+#define clEnqueueCopyBufferRect CLEW_GET_FUN(__clewEnqueueCopyBufferRect )
+#define clEnqueueReadImage CLEW_GET_FUN(__clewEnqueueReadImage )
+#define clEnqueueWriteImage CLEW_GET_FUN(__clewEnqueueWriteImage )
+#define clEnqueueCopyImage CLEW_GET_FUN(__clewEnqueueCopyImage )
+#define clEnqueueCopyImageToBuffer CLEW_GET_FUN(__clewEnqueueCopyImageToBuffer )
+#define clEnqueueCopyBufferToImage CLEW_GET_FUN(__clewEnqueueCopyBufferToImage )
+#define clEnqueueMapBuffer CLEW_GET_FUN(__clewEnqueueMapBuffer )
+#define clEnqueueMapImage CLEW_GET_FUN(__clewEnqueueMapImage )
+#define clEnqueueUnmapMemObject CLEW_GET_FUN(__clewEnqueueUnmapMemObject )
+#define clEnqueueNDRangeKernel CLEW_GET_FUN(__clewEnqueueNDRangeKernel )
+#define clEnqueueTask CLEW_GET_FUN(__clewEnqueueTask )
+#define clEnqueueNativeKernel CLEW_GET_FUN(__clewEnqueueNativeKernel )
+#define clEnqueueMarker CLEW_GET_FUN(__clewEnqueueMarker )
+#define clEnqueueWaitForEvents CLEW_GET_FUN(__clewEnqueueWaitForEvents )
+#define clEnqueueBarrier CLEW_GET_FUN(__clewEnqueueBarrier )
+#define clGetExtensionFunctionAddress CLEW_GET_FUN(__clewGetExtensionFunctionAddress )
+
+
+#define CLEW_SUCCESS 0 //!< Success error code
+#define CLEW_ERROR_OPEN_FAILED -1 //!< Error code for failing to open the dynamic library
+#define CLEW_ERROR_ATEXIT_FAILED -2 //!< Error code for failing to queue the closing of the dynamic library to atexit()
+
+//! \brief Load OpenCL dynamic library and set function entry points
+int clewInit (const char*);
+
+//! \brief Exit clew and unload OpenCL dynamic library
+void clewExit();
+
+//! \brief Convert an OpenCL error code to its string equivalent
+const char* clewErrorString (cl_int error);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // CLEW_HPP_INCLUDED
diff --git a/thirdparty/bullet/version.txt b/thirdparty/bullet/version.txt
new file mode 100644
index 0000000000..9a3b592267
--- /dev/null
+++ b/thirdparty/bullet/version.txt
@@ -0,0 +1 @@
+GitHub Master d05ad4b (23 / October / 2017) [Bullet ~2.87] \ No newline at end of file
diff --git a/thirdparty/enet/enet/enet.h b/thirdparty/enet/enet/enet.h
index 8c9ad5463e..246cbb0a62 100644
--- a/thirdparty/enet/enet/enet.h
+++ b/thirdparty/enet/enet/enet.h
@@ -10,6 +10,7 @@ extern "C"
{
#endif
+#include <stdint.h>
#include <stdlib.h>
#include "enet/godot.h"
diff --git a/thirdparty/etc2comp/AUTHORS b/thirdparty/etc2comp/AUTHORS
index 32daca27fe..e78a7f4d21 100644
--- a/thirdparty/etc2comp/AUTHORS
+++ b/thirdparty/etc2comp/AUTHORS
@@ -1,7 +1,7 @@
-# This is the list of Etc2Comp authors for copyright purposes.
-#
-# This does not necessarily list everyone who has contributed code, since in
-# some cases, their employer may be the copyright holder. To see the full list
-# of contributors, see the revision history in source control.
-Google Inc.
-Blue Shift Inc.
+# This is the list of Etc2Comp authors for copyright purposes.
+#
+# This does not necessarily list everyone who has contributed code, since in
+# some cases, their employer may be the copyright holder. To see the full list
+# of contributors, see the revision history in source control.
+Google Inc.
+Blue Shift Inc.
diff --git a/thirdparty/etc2comp/LICENSE b/thirdparty/etc2comp/LICENSE
index 75b52484ea..d645695673 100644
--- a/thirdparty/etc2comp/LICENSE
+++ b/thirdparty/etc2comp/LICENSE
@@ -1,202 +1,202 @@
-
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/thirdparty/etc2comp/README.md b/thirdparty/etc2comp/README.md
index 1c70ae9f4e..2f4363d042 100644
--- a/thirdparty/etc2comp/README.md
+++ b/thirdparty/etc2comp/README.md
@@ -1,197 +1,197 @@
-# Etc2Comp - Texture to ETC2 compressor
-
-Etc2Comp is a command line tool that converts textures (e.g. bitmaps)
-into the [ETC2](https://en.wikipedia.org/wiki/Ericsson_Texture_Compression)
-format. The tool is built with a focus on encoding performance
-to reduce the amount of time required to compile asset heavy applications as
-well as reduce overall application size.
-
-This repo provides source code that can be compiled into a binary. The
-binary can then be used to convert textures to the ETC2 format.
-
-Important: This is not an official Google product. It is an experimental
-library published as-is. Please see the CONTRIBUTORS.md file for information
-about questions or issues.
-
-## Setup
-This project uses [CMake](https://cmake.org/) to generate platform-specific
-build files:
- - Linux: make files
- - OS X: Xcode workspace files
- - Microsoft Windows: Visual Studio solution files
- - Note: CMake supports other formats, but this doc only provides steps for
- one of each platform for brevity.
-
-Refer to each platform's setup section to setup your environment and build
-an Etc2Comp binary. Then skip to the usage section of this page for examples
-of how to use the library.
-
-### Setup for OS X
- build tested on this config:
- OS X 10.9.5 i7 16GB RAM
- Xcode 5.1.1
- cmake 3.2.3
-
-Start by downloading and installing the following components if they are not
-already installed on your development machine.
- - *Xcode* version 5.1.1, or greater
- - [CMake](https://cmake.org/download/) version 3.2.3, or greater
-
-To build the Etc2Comp binary:
- 1. Open a *Terminal* window and navigate to the project directory.
- 1. Run `mkdir build_xcode`
- 1. Run `cd build_xcode`
- 1. Run `cmake -G Xcode ../`
- 1. Open *Xcode* and import the `build_xcode/EtcTest.xcodeproj` file.
- 1. Open the Product menu and choose Build For -> Running.
- 1. Once the build succeeds the binary located at `build_xcode/EtcTool/Debug/EtcTool`
-can be executed.
-
-Optional
-Xcode EtcTool ‘Run’ preferences
-note: if the build_xcode/EtcTest.xcodeproj is manually deleted then some Xcode preferences
-will need to be set by hand after cmake is run (these prefs are retained across
-cmake updates if the .xcodeproj is not deleted/removed)
-
-1. Set the active scheme to ‘EtcTool’
-1. Edit the scheme
-1. Select option ‘Run EtcTool’, then tab ‘Arguments’.
-Add this launch argument: ‘-argfile ../../EtcTool/args.txt’
-1. Select tab ‘Options’ and set a custom working directory to: ‘$(SRCROOT)/Build_Xcode/EtcTool’
-
-### SetUp for Windows
-
-1. Open a *Terminal* window and navigate to the project directory.
-1. Run `mkdir build_vs`
-1. Run `cd build_vs`
-1. Run CMAKE, noting what build version you need, and pointing to the parent directory as the source root;
- For VS 2013 : `cmake -G "Visual Studio 12 2013 Win64" ../`
- For VS 2015 : `cmake -G "Visual Studio 14 2015 Win64" ../`
- NOTE: To see what supported Visual Studio outputs there are, run `cmake -G`
-1. open the 'EtcTest' solution
-1. make the 'EtcTool' project the start up project
-1. (optional) in the project properties, under 'Debugging ->command arguments'
-add the argfile textfile thats included in the EtcTool directory.
-example: -argfile C:\etc2\EtcTool\Args.txt
-
-### Setup For Linux
-The Linux build was tested on this config:
- Ubuntu desktop 14.04
- gcc/g++ 4.8
- cmake 2.8.12.2
-
-1. Verify linux has cmake and C++-11 capable g++ installed
-1. Open shell
-1. Run `mkdir build_linux`
-1. Run `cd build_linux`
-1. Run `cmake ../`
-1. Run `make`
-1. navigate to the newly created EtcTool directory `cd EtcTool`
-1. run the executable: `./EtcTool -argfile ../../EtcTool/args.txt`
-
-Skip to the <a href="#usage">Usage</a> section for more information about using the
-tool.
-
-## Usage
-
-### Command Line Usage
-EtcTool can be run from the command line with the following usage:
- etctool.exe source_image [options ...] -output encoded_image
-
-The encoder will use an array of RGBA floats read from the source_image to create
-an ETC1 or ETC2 encoded image in encoded_image. The RGBA floats should be in the
-range [0:1].
-
-Options:
-
- -analyze <analysis_folder>
- -argfile <arg_file> additional command line arguments read from a file
- -blockAtHV <H V> encodes a single block that contains the
- pixel specified by the H V coordinates
- -compare <comparison_image> compares source_image to comparison_image
- -effort <amount> number between 0 and 100 to specify the encoding quality
- (100 is the highest quality)
- -errormetric <error_metric> specify the error metric, the options are
- rgba, rgbx, rec709, numeric and normalxyz
- -format <etc_format> ETC1, RGB8, SRGB8, RGBA8, SRGB8, RGB8A1,
- SRGB8A1 or R11
- -help prints this message
- -jobs or -j <thread_count> specifies the number of threads (default=1)
- -normalizexyz normalize RGB to have a length of 1
- -verbose or -v shows status information during the encoding
- process
- -mipmaps or -m <mip_count> sets the maximum number of mipaps to generate (default=1)
- -mipwrap or -w <x|y|xy> sets the mipmap filter wrap mode (default=clamp)
-
-* -analyze will run an analysis of the encoding and place it in folder
-"analysis_folder" (e.g. ../analysis/kodim05). within the analysis_folder, a folder
-will be created with a name of the current date/time (e.g. 20151204_153306). this
-date/time folder is used to compare encodings of the same texture over time.
-within the date/time folder is a text file with several encoding stats and a 2x png
-image showing the encoding mode for each 4x4 block.
-
-* -argfile allows additional command line arguments to be placed in a text file
-
-* -blockAtHV selects the 4x4 pixel subset of the source image at position (H,V).
-This is mainly used for debugging
-
-* -compare compares the source image to the created encoded image. The encoding
-will dictate what error analysis is used in the comparison.
-
-* -effort uses an "amount" between 0 and 100 to determine how much additional effort
-to apply during the encoding.
-
-* -errormetric selects the fitting algorithm used by the encoder. "rgba" calculates
-RMS error using RGB components that are weighted by A. "rgbx" calculates RMS error
-using RGBA components, where A is treated as an additional data channel, instead of
-as alpha. "rec709" is similar to "rgba", except the RGB components are also weighted
-according to Rec709. "numeric" calculates RMS error using unweighted RGBA components.
-"normalize" calculates error based on dot product and vector length for RGB and RMS
-error for A.
-
-* -help prints out the usage message
-
-* -jobs enables multi-threading to speed up image encoding
-
-* -normalizexyz normalizes the source RGB to have a length of 1.
-
-* -verbose shows information on the current encoding process. It will then display the
-PSNR and time time it took to encode the image.
-
-* -mipmaps takes an argument that specifies how many mipmaps to generate from the
-source image. The mipmaps are generated with a lanczos3 filter using edge clamping.
-If the mipmaps option is not specified no mipmaps are created.
-
-* -mipwrap takes an argument that specifies the mipmap filter wrap mode. The options
-are "x", "y" and "xy" which specify wrapping in x only, y only or x and y respectively.
-The default options are clamping in both x and y.
-
-Note: Path names can use slashes or backslashes. The tool will convert the
-slashes to the appropriate polarity for the current platform.
-
-
-## API
-
-The library supports two different APIs - a C-like API that is not heavily
-class-based and a class-based API.
-
-main() in EtcTool.cpp contains an example of both APIs.
-
-The Encode() method now returns an EncodingStatus that contains bit flags for
-reporting various warnings and flags encountered when encoding.
-
-
-## Copyright
-Copyright 2015 Etc2Comp Authors.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
+# Etc2Comp - Texture to ETC2 compressor
+
+Etc2Comp is a command line tool that converts textures (e.g. bitmaps)
+into the [ETC2](https://en.wikipedia.org/wiki/Ericsson_Texture_Compression)
+format. The tool is built with a focus on encoding performance
+to reduce the amount of time required to compile asset heavy applications as
+well as reduce overall application size.
+
+This repo provides source code that can be compiled into a binary. The
+binary can then be used to convert textures to the ETC2 format.
+
+Important: This is not an official Google product. It is an experimental
+library published as-is. Please see the CONTRIBUTORS.md file for information
+about questions or issues.
+
+## Setup
+This project uses [CMake](https://cmake.org/) to generate platform-specific
+build files:
+ - Linux: make files
+ - OS X: Xcode workspace files
+ - Microsoft Windows: Visual Studio solution files
+ - Note: CMake supports other formats, but this doc only provides steps for
+ one of each platform for brevity.
+
+Refer to each platform's setup section to setup your environment and build
+an Etc2Comp binary. Then skip to the usage section of this page for examples
+of how to use the library.
+
+### Setup for OS X
+ build tested on this config:
+ OS X 10.9.5 i7 16GB RAM
+ Xcode 5.1.1
+ cmake 3.2.3
+
+Start by downloading and installing the following components if they are not
+already installed on your development machine.
+ - *Xcode* version 5.1.1, or greater
+ - [CMake](https://cmake.org/download/) version 3.2.3, or greater
+
+To build the Etc2Comp binary:
+ 1. Open a *Terminal* window and navigate to the project directory.
+ 1. Run `mkdir build_xcode`
+ 1. Run `cd build_xcode`
+ 1. Run `cmake -G Xcode ../`
+ 1. Open *Xcode* and import the `build_xcode/EtcTest.xcodeproj` file.
+ 1. Open the Product menu and choose Build For -> Running.
+ 1. Once the build succeeds the binary located at `build_xcode/EtcTool/Debug/EtcTool`
+can be executed.
+
+Optional
+Xcode EtcTool ‘Run’ preferences
+note: if the build_xcode/EtcTest.xcodeproj is manually deleted then some Xcode preferences
+will need to be set by hand after cmake is run (these prefs are retained across
+cmake updates if the .xcodeproj is not deleted/removed)
+
+1. Set the active scheme to ‘EtcTool’
+1. Edit the scheme
+1. Select option ‘Run EtcTool’, then tab ‘Arguments’.
+Add this launch argument: ‘-argfile ../../EtcTool/args.txt’
+1. Select tab ‘Options’ and set a custom working directory to: ‘$(SRCROOT)/Build_Xcode/EtcTool’
+
+### SetUp for Windows
+
+1. Open a *Terminal* window and navigate to the project directory.
+1. Run `mkdir build_vs`
+1. Run `cd build_vs`
+1. Run CMAKE, noting what build version you need, and pointing to the parent directory as the source root;
+ For VS 2013 : `cmake -G "Visual Studio 12 2013 Win64" ../`
+ For VS 2015 : `cmake -G "Visual Studio 14 2015 Win64" ../`
+ NOTE: To see what supported Visual Studio outputs there are, run `cmake -G`
+1. open the 'EtcTest' solution
+1. make the 'EtcTool' project the start up project
+1. (optional) in the project properties, under 'Debugging ->command arguments'
+add the argfile textfile thats included in the EtcTool directory.
+example: -argfile C:\etc2\EtcTool\Args.txt
+
+### Setup For Linux
+The Linux build was tested on this config:
+ Ubuntu desktop 14.04
+ gcc/g++ 4.8
+ cmake 2.8.12.2
+
+1. Verify linux has cmake and C++-11 capable g++ installed
+1. Open shell
+1. Run `mkdir build_linux`
+1. Run `cd build_linux`
+1. Run `cmake ../`
+1. Run `make`
+1. navigate to the newly created EtcTool directory `cd EtcTool`
+1. run the executable: `./EtcTool -argfile ../../EtcTool/args.txt`
+
+Skip to the <a href="#usage">Usage</a> section for more information about using the
+tool.
+
+## Usage
+
+### Command Line Usage
+EtcTool can be run from the command line with the following usage:
+ etctool.exe source_image [options ...] -output encoded_image
+
+The encoder will use an array of RGBA floats read from the source_image to create
+an ETC1 or ETC2 encoded image in encoded_image. The RGBA floats should be in the
+range [0:1].
+
+Options:
+
+ -analyze <analysis_folder>
+ -argfile <arg_file> additional command line arguments read from a file
+ -blockAtHV <H V> encodes a single block that contains the
+ pixel specified by the H V coordinates
+ -compare <comparison_image> compares source_image to comparison_image
+ -effort <amount> number between 0 and 100 to specify the encoding quality
+ (100 is the highest quality)
+ -errormetric <error_metric> specify the error metric, the options are
+ rgba, rgbx, rec709, numeric and normalxyz
+ -format <etc_format> ETC1, RGB8, SRGB8, RGBA8, SRGB8, RGB8A1,
+ SRGB8A1 or R11
+ -help prints this message
+ -jobs or -j <thread_count> specifies the number of threads (default=1)
+ -normalizexyz normalize RGB to have a length of 1
+ -verbose or -v shows status information during the encoding
+ process
+ -mipmaps or -m <mip_count> sets the maximum number of mipaps to generate (default=1)
+ -mipwrap or -w <x|y|xy> sets the mipmap filter wrap mode (default=clamp)
+
+* -analyze will run an analysis of the encoding and place it in folder
+"analysis_folder" (e.g. ../analysis/kodim05). within the analysis_folder, a folder
+will be created with a name of the current date/time (e.g. 20151204_153306). this
+date/time folder is used to compare encodings of the same texture over time.
+within the date/time folder is a text file with several encoding stats and a 2x png
+image showing the encoding mode for each 4x4 block.
+
+* -argfile allows additional command line arguments to be placed in a text file
+
+* -blockAtHV selects the 4x4 pixel subset of the source image at position (H,V).
+This is mainly used for debugging
+
+* -compare compares the source image to the created encoded image. The encoding
+will dictate what error analysis is used in the comparison.
+
+* -effort uses an "amount" between 0 and 100 to determine how much additional effort
+to apply during the encoding.
+
+* -errormetric selects the fitting algorithm used by the encoder. "rgba" calculates
+RMS error using RGB components that are weighted by A. "rgbx" calculates RMS error
+using RGBA components, where A is treated as an additional data channel, instead of
+as alpha. "rec709" is similar to "rgba", except the RGB components are also weighted
+according to Rec709. "numeric" calculates RMS error using unweighted RGBA components.
+"normalize" calculates error based on dot product and vector length for RGB and RMS
+error for A.
+
+* -help prints out the usage message
+
+* -jobs enables multi-threading to speed up image encoding
+
+* -normalizexyz normalizes the source RGB to have a length of 1.
+
+* -verbose shows information on the current encoding process. It will then display the
+PSNR and time time it took to encode the image.
+
+* -mipmaps takes an argument that specifies how many mipmaps to generate from the
+source image. The mipmaps are generated with a lanczos3 filter using edge clamping.
+If the mipmaps option is not specified no mipmaps are created.
+
+* -mipwrap takes an argument that specifies the mipmap filter wrap mode. The options
+are "x", "y" and "xy" which specify wrapping in x only, y only or x and y respectively.
+The default options are clamping in both x and y.
+
+Note: Path names can use slashes or backslashes. The tool will convert the
+slashes to the appropriate polarity for the current platform.
+
+
+## API
+
+The library supports two different APIs - a C-like API that is not heavily
+class-based and a class-based API.
+
+main() in EtcTool.cpp contains an example of both APIs.
+
+The Encode() method now returns an EncodingStatus that contains bit flags for
+reporting various warnings and flags encountered when encoding.
+
+
+## Copyright
+Copyright 2015 Etc2Comp Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/thirdparty/freetype/include/freetype/config/ftoption.h b/thirdparty/freetype/include/freetype/config/ftoption.h
index 1bf6e8f534..2fbe80b9b4 100644
--- a/thirdparty/freetype/include/freetype/config/ftoption.h
+++ b/thirdparty/freetype/include/freetype/config/ftoption.h
@@ -107,20 +107,17 @@ FT_BEGIN_HEADER
/*************************************************************************/
/* */
- /* Uncomment the line below if you want to activate sub-pixel rendering */
- /* (a.k.a. LCD rendering, or ClearType) in this build of the library. */
+ /* Uncomment the line below if you want to activate LCD rendering */
+ /* technology similar to ClearType in this build of the library. This */
+ /* technology triples the resolution in the direction color subpixels. */
+ /* To mitigate color fringes inherent to this technology, you also need */
+ /* to explicitly set up LCD filtering. */
/* */
/* Note that this feature is covered by several Microsoft patents */
/* and should not be activated in any default build of the library. */
- /* */
- /* This macro has no impact on the FreeType API, only on its */
- /* _implementation_. For example, using FT_RENDER_MODE_LCD when calling */
- /* FT_Render_Glyph still generates a bitmap that is 3 times wider than */
- /* the original size in case this macro isn't defined; however, each */
- /* triplet of subpixels has R=G=B. */
- /* */
- /* This is done to allow FreeType clients to run unmodified, forcing */
- /* them to display normal gray-level anti-aliased glyphs. */
+ /* When this macro is not defined, FreeType offers alternative LCD */
+ /* rendering technology that produces excellent output without LCD */
+ /* filtering. */
/* */
/* #define FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
@@ -327,7 +324,7 @@ FT_BEGIN_HEADER
/* */
/* - The TrueType driver will provide its own set of glyph names, */
/* if you build it to support postscript names in the TrueType */
- /* `post' table. */
+ /* `post' table, but will not synthesize a missing Unicode charmap. */
/* */
/* - The Type 1 driver will not be able to synthesize a Unicode */
/* charmap out of the glyphs found in the fonts. */
diff --git a/thirdparty/freetype/include/freetype/freetype.h b/thirdparty/freetype/include/freetype/freetype.h
index 2989fbb5e1..b0c261799a 100644
--- a/thirdparty/freetype/include/freetype/freetype.h
+++ b/thirdparty/freetype/include/freetype/freetype.h
@@ -575,7 +575,8 @@ FT_BEGIN_HEADER
/* <Note> */
/* When a new face is created (either through @FT_New_Face or */
/* @FT_Open_Face), the library looks for a Unicode charmap within */
- /* the list and automatically activates it. */
+ /* the list and automatically activates it. If there is no Unicode */
+ /* charmap, FreeType doesn't set an `active' charmap. */
/* */
/* <Also> */
/* See @FT_CharMapRec for the publicly accessible fields of a given */
@@ -1529,7 +1530,13 @@ FT_BEGIN_HEADER
/* values of the corresponding fields in @FT_FaceRec. Some values */
/* like ascender or descender are rounded for historical reasons; */
/* more precise values (for outline fonts) can be derived by scaling */
- /* the corresponding @FT_FaceRec values manually. */
+ /* the corresponding @FT_FaceRec values manually, with code similar */
+ /* to the following. */
+ /* */
+ /* { */
+ /* scaled_ascender = FT_MulFix( face->root.ascender, */
+ /* size_metrics->y_scale ); */
+ /* } */
/* */
/* Note that due to glyph hinting and the selected rendering mode */
/* these values are usually not exact; consequently, they must be */
@@ -1774,7 +1781,7 @@ FT_BEGIN_HEADER
/* and add it to `origin_x'> */
/* */
/* origin_x += slot->advance.x; */
- /* origin_x += slot->rsb_delta - slot->lsb_relta; */
+ /* origin_x += slot->rsb_delta - slot->lsb_delta; */
/* endfor */
/* } */
/* */
@@ -1794,9 +1801,9 @@ FT_BEGIN_HEADER
/* */
/* <load glyph with `FT_Load_Glyph'> */
/* */
- /* if ( prev_rsb_delta - slot->lsb_delta >= 32 ) */
+ /* if ( prev_rsb_delta - slot->lsb_delta > 32 ) */
/* origin_x -= 64; */
- /* else if ( prev_rsb_delta - slot->lsb_delta < -32 ) */
+ /* else if ( prev_rsb_delta - slot->lsb_delta < -31 ) */
/* origin_x += 64; */
/* */
/* prev_rsb_delta = slot->rsb_delta; */
@@ -3124,11 +3131,13 @@ FT_BEGIN_HEADER
/* glyph outline in pixels and use the @FT_PIXEL_MODE_LCD_V mode. */
/* */
/* <Note> */
- /* The LCD-optimized glyph bitmaps produced by `FT_Render_Glyph' can */
- /* be filtered to reduce color-fringes by using */
- /* @FT_Library_SetLcdFilter (not active in the default builds). It */
- /* is up to the caller to either call `FT_Library_SetLcdFilter' (if */
- /* available) or do the filtering itself. */
+ /* Should you define FT_CONFIG_OPTION_SUBPIXEL_RENDERING in your */
+ /* `ftoption.h', which enables patented ClearType-style rendering, */
+ /* the LCD-optimized glyph bitmaps should be filtered to reduce color */
+ /* fringes inherent to this technology. You can either set up LCD */
+ /* filtering with @FT_Library_SetLcdFilter or @FT_Face_Properties, */
+ /* or do the filtering yourself. The default FreeType LCD rendering */
+ /* technology does not require filtering. */
/* */
/* The selected render mode only affects vector glyphs of a font. */
/* Embedded bitmaps often have a different pixel mode like */
@@ -4327,6 +4336,9 @@ FT_BEGIN_HEADER
/* `a' rounded to the nearest 16.16 fixed integer, halfway cases away */
/* from zero. */
/* */
+ /* <Note> */
+ /* The function uses wrap-around arithmetic. */
+ /* */
FT_EXPORT( FT_Fixed )
FT_RoundFix( FT_Fixed a );
@@ -4345,6 +4357,9 @@ FT_BEGIN_HEADER
/* <Return> */
/* `a' rounded towards plus infinity. */
/* */
+ /* <Note> */
+ /* The function uses wrap-around arithmetic. */
+ /* */
FT_EXPORT( FT_Fixed )
FT_CeilFix( FT_Fixed a );
@@ -4442,7 +4457,7 @@ FT_BEGIN_HEADER
*/
#define FREETYPE_MAJOR 2
#define FREETYPE_MINOR 8
-#define FREETYPE_PATCH 0
+#define FREETYPE_PATCH 1
/*************************************************************************/
diff --git a/thirdparty/freetype/include/freetype/ftautoh.h b/thirdparty/freetype/include/freetype/ftautoh.h
index abd540f0b5..2bb675ae46 100644
--- a/thirdparty/freetype/include/freetype/ftautoh.h
+++ b/thirdparty/freetype/include/freetype/ftautoh.h
@@ -404,12 +404,12 @@ FT_BEGIN_HEADER
* activate the warp hinting code in the auto-hinter, this property
* switches warping on and off.
*
- * Warping only works in `light' auto-hinting mode. The idea of the
- * code is to slightly scale and shift a glyph along the non-hinted
- * dimension (which is usually the horizontal axis) so that as much of
- * its segments are aligned (more or less) to the grid. To find out a
- * glyph's optimal scaling and shifting value, various parameter
- * combinations are tried and scored.
+ * Warping only works in `normal' auto-hinting mode replacing it.
+ * The idea of the code is to slightly scale and shift a glyph along
+ * the non-hinted dimension (which is usually the horizontal axis) so
+ * that as much of its segments are aligned (more or less) to the grid.
+ * To find out a glyph's optimal scaling and shifting value, various
+ * parameter combinations are tried and scored.
*
* By default, warping is off. The example below shows how to switch on
* warping (omitting the error handling).
@@ -437,7 +437,7 @@ FT_BEGIN_HEADER
*
* Since warping is a global property of the auto-hinter it is best to
* change its value before rendering any face. Otherwise, you should
- * reload all faces that get auto-hinted in `light' hinting mode.
+ * reload all faces that get auto-hinted in `normal' hinting mode.
*
*/
diff --git a/thirdparty/freetype/include/freetype/fterrdef.h b/thirdparty/freetype/include/freetype/fterrdef.h
index cabbac8273..6a6dc85b87 100644
--- a/thirdparty/freetype/include/freetype/fterrdef.h
+++ b/thirdparty/freetype/include/freetype/fterrdef.h
@@ -233,6 +233,8 @@
"invalid PostScript (post) table" )
FT_ERRORDEF_( DEF_In_Glyf_Bytecode, 0x9C,
"found FDEF or IDEF opcode in glyf bytecode" )
+ FT_ERRORDEF_( Missing_Bitmap, 0x9D,
+ "missing bitmap in strike" )
/* CFF, CID, and Type 1 errors */
diff --git a/thirdparty/freetype/include/freetype/fterrors.h b/thirdparty/freetype/include/freetype/fterrors.h
index 42769fa7bf..ae382c419f 100644
--- a/thirdparty/freetype/include/freetype/fterrors.h
+++ b/thirdparty/freetype/include/freetype/fterrors.h
@@ -38,15 +38,15 @@
/* The configuration macro FT_CONFIG_OPTION_USE_MODULE_ERRORS can be */
/* defined in `ftoption.h' in order to make the higher byte indicate */
/* the module where the error has happened (this is not compatible */
- /* with standard builds of FreeType&nbsp;2, however). See the file */
+ /* with standard builds of FreeType~2, however). See the file */
/* `ftmoderr.h' for more details. */
/* */
/* *Error* *Message* *Strings* */
/* */
/* Error definitions are set up with special macros that allow client */
/* applications to build a table of error message strings. The */
- /* strings are not included in a normal build of FreeType&nbsp;2 to */
- /* save space (most client applications do not use them). */
+ /* strings are not included in a normal build of FreeType~2 to save */
+ /* space (most client applications do not use them). */
/* */
/* To do so, you have to define the following macros before including */
/* this file. */
diff --git a/thirdparty/freetype/include/freetype/ftglyph.h b/thirdparty/freetype/include/freetype/ftglyph.h
index 79879a7ac7..db1a2c8ba5 100644
--- a/thirdparty/freetype/include/freetype/ftglyph.h
+++ b/thirdparty/freetype/include/freetype/ftglyph.h
@@ -231,6 +231,12 @@ FT_BEGIN_HEADER
/* <Return> */
/* FreeType error code. 0~means success. */
/* */
+ /* <Note> */
+ /* Because `*aglyph->advance.x' and '*aglyph->advance.y' are 16.16 */
+ /* fixed-point numbers, `slot->advance.x' and `slot->advance.y' */
+ /* (which are in 26.6 fixed-point format) must be in the range */
+ /* ]-32768;32768[. */
+ /* */
FT_EXPORT( FT_Error )
FT_Get_Glyph( FT_GlyphSlot slot,
FT_Glyph *aglyph );
@@ -566,6 +572,9 @@ FT_BEGIN_HEADER
/* <Note> */
/* The result is undefined if either `a' or `b' is zero. */
/* */
+ /* Since the function uses wrap-around arithmetic, results become */
+ /* meaningless if the arguments are very large. */
+ /* */
FT_EXPORT( void )
FT_Matrix_Multiply( const FT_Matrix* a,
FT_Matrix* b );
diff --git a/thirdparty/freetype/include/freetype/ftimage.h b/thirdparty/freetype/include/freetype/ftimage.h
index 1a049ef16d..1c789e5a44 100644
--- a/thirdparty/freetype/include/freetype/ftimage.h
+++ b/thirdparty/freetype/include/freetype/ftimage.h
@@ -1064,24 +1064,24 @@ FT_BEGIN_HEADER
/* */
/* <Description> */
/* FreeType used to provide an area of memory called the `render */
- /* pool' available to all registered rasters. This was not thread */
- /* safe however and now FreeType never allocates this pool. NULL */
- /* is always passed in as pool_base. */
+ /* pool' available to all registered rasterizers. This was not */
+ /* thread safe, however, and now FreeType never allocates this pool. */
/* */
- /* This function is called each time the render pool changes, or just */
- /* after a new raster object is created. */
+ /* This function is called after a new raster object is created. */
/* */
/* <Input> */
/* raster :: A handle to the new raster object. */
/* */
- /* pool_base :: The address in memory of the render pool. */
+ /* pool_base :: Previously, the address in memory of the render pool. */
+ /* Set this to NULL. */
/* */
- /* pool_size :: The size in bytes of the render pool. */
+ /* pool_size :: Previously, the size in bytes of the render pool. */
+ /* Set this to 0. */
/* */
/* <Note> */
- /* Rasters should ignore the render pool and rely on dynamic or stack */
- /* allocation if they want to (a handle to the memory allocator is */
- /* passed to the raster constructor). */
+ /* Rasterizers should rely on dynamic or stack allocation if they */
+ /* want to (a handle to the memory allocator is passed to the */
+ /* rasterizer constructor). */
/* */
typedef void
(*FT_Raster_ResetFunc)( FT_Raster raster,
diff --git a/thirdparty/freetype/include/freetype/ftlcdfil.h b/thirdparty/freetype/include/freetype/ftlcdfil.h
index 680bd90c89..bdaf9af906 100644
--- a/thirdparty/freetype/include/freetype/ftlcdfil.h
+++ b/thirdparty/freetype/include/freetype/ftlcdfil.h
@@ -44,9 +44,16 @@ FT_BEGIN_HEADER
* Reduce color fringes of subpixel-rendered bitmaps.
*
* @description:
- * Subpixel rendering exploits the color-striped structure of LCD
- * pixels, increasing the available resolution in the direction of the
- * stripe (usually horizontal RGB) by a factor of~3. Since these
+ * Should you #define FT_CONFIG_OPTION_SUBPIXEL_RENDERING in your
+ * `ftoption.h', which enables patented ClearType-style rendering,
+ * the LCD-optimized glyph bitmaps should be filtered to reduce color
+ * fringes inherent to this technology. The default FreeType LCD
+ * rendering uses different technology, and API described below,
+ * although available, does nothing.
+ *
+ * ClearType-style LCD rendering exploits the color-striped structure of
+ * LCD pixels, increasing the available resolution in the direction of
+ * the stripe (usually horizontal RGB) by a factor of~3. Since these
* subpixels are color pixels, using them unfiltered creates severe
* color fringes. Use the @FT_Library_SetLcdFilter API to specify a
* low-pass filter, which is then applied to subpixel-rendered bitmaps
@@ -54,12 +61,6 @@ FT_BEGIN_HEADER
* the higher resolution to reduce color fringes, making the glyph image
* slightly blurrier. Positional improvements will remain.
*
- * Note that no filter is active by default, and that this function is
- * *not* implemented in default builds of the library. You need to
- * #define FT_CONFIG_OPTION_SUBPIXEL_RENDERING in your `ftoption.h' file
- * in order to activate it and explicitly call @FT_Library_SetLcdFilter
- * to enable it.
- *
* A filter should have two properties:
*
* 1) It should be normalized, meaning the sum of the 5~components
diff --git a/thirdparty/freetype/include/freetype/ftmac.h b/thirdparty/freetype/include/freetype/ftmac.h
index ad97c6e4c3..a1656eec0e 100644
--- a/thirdparty/freetype/include/freetype/ftmac.h
+++ b/thirdparty/freetype/include/freetype/ftmac.h
@@ -35,11 +35,12 @@
FT_BEGIN_HEADER
-/* gcc-3.4.1 and later can warn about functions tagged as deprecated */
+ /* gcc-3.1 and later can warn about functions tagged as deprecated */
#ifndef FT_DEPRECATED_ATTRIBUTE
-#if defined(__GNUC__) && \
- ((__GNUC__ >= 4) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1)))
-#define FT_DEPRECATED_ATTRIBUTE __attribute__((deprecated))
+#if defined( __GNUC__ ) && \
+ ( ( __GNUC__ >= 4 ) || \
+ ( ( __GNUC__ == 3 ) && ( __GNUC_MINOR__ >= 1 ) ) )
+#define FT_DEPRECATED_ATTRIBUTE __attribute__(( deprecated ))
#else
#define FT_DEPRECATED_ATTRIBUTE
#endif
diff --git a/thirdparty/freetype/include/freetype/ftmm.h b/thirdparty/freetype/include/freetype/ftmm.h
index c41b80ea67..80ac98d612 100644
--- a/thirdparty/freetype/include/freetype/ftmm.h
+++ b/thirdparty/freetype/include/freetype/ftmm.h
@@ -178,7 +178,8 @@ FT_BEGIN_HEADER
/* strid :: The entry in `name' table identifying this instance. */
/* */
/* psid :: The entry in `name' table identifying a PostScript name */
- /* for this instance. */
+ /* for this instance. Value 0xFFFF indicates a missing */
+ /* entry. */
/* */
typedef struct FT_Var_Named_Style_
{
@@ -195,7 +196,7 @@ FT_BEGIN_HEADER
/* FT_MM_Var */
/* */
/* <Description> */
- /* A structure to model the axes and space of a Adobe MM, TrueType */
+ /* A structure to model the axes and space of an Adobe MM, TrueType */
/* GX, or OpenType variation font. */
/* */
/* Some fields are specific to one format and not to the others. */
@@ -321,6 +322,11 @@ FT_BEGIN_HEADER
/* <Return> */
/* FreeType error code. 0~means success. */
/* */
+ /* <Note> */
+ /* To reset all axes to the default values, call the function with */
+ /* `num_coords' set to zero and `coords' set to NULL (new feature in */
+ /* FreeType version 2.8.1). */
+ /* */
FT_EXPORT( FT_Error )
FT_Set_MM_Design_Coordinates( FT_Face face,
FT_UInt num_coords,
@@ -351,6 +357,11 @@ FT_BEGIN_HEADER
/* <Return> */
/* FreeType error code. 0~means success. */
/* */
+ /* <Note> */
+ /* To reset all axes to the default values, call the function with */
+ /* `num_coords' set to zero and `coords' set to NULL (new feature in */
+ /* FreeType version 2.8.1). */
+ /* */
FT_EXPORT( FT_Error )
FT_Set_Var_Design_Coordinates( FT_Face face,
FT_UInt num_coords,
@@ -415,6 +426,11 @@ FT_BEGIN_HEADER
/* <Return> */
/* FreeType error code. 0~means success. */
/* */
+ /* <Note> */
+ /* To reset all axes to the default values, call the function with */
+ /* `num_coords' set to zero and `coords' set to NULL (new feature in */
+ /* FreeType version 2.8.1). */
+ /* */
FT_EXPORT( FT_Error )
FT_Set_MM_Blend_Coordinates( FT_Face face,
FT_UInt num_coords,
@@ -479,6 +495,50 @@ FT_BEGIN_HEADER
FT_UInt num_coords,
FT_Fixed* coords );
+
+ /*************************************************************************/
+ /* */
+ /* <Enum> */
+ /* FT_VAR_AXIS_FLAG_XXX */
+ /* */
+ /* <Description> */
+ /* A list of bit flags used in the return value of */
+ /* @FT_Get_Var_Axis_Flags. */
+ /* */
+ /* <Values> */
+ /* FT_VAR_AXIS_FLAG_HIDDEN :: */
+ /* The variation axis should not be exposed to user interfaces. */
+ /* */
+#define FT_VAR_AXIS_FLAG_HIDDEN 1
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Get_Var_Axis_Flags */
+ /* */
+ /* <Description> */
+ /* Get the `flags' field of an OpenType Variation Axis Record. */
+ /* */
+ /* Not meaningful for Adobe MM fonts (`*flags' is always zero). */
+ /* */
+ /* <Input> */
+ /* master :: The variation descriptor. */
+ /* */
+ /* axis_index :: The index of the requested variation axis. */
+ /* */
+ /* <Output> */
+ /* flags :: The `flags' field. See @FT_VAR_AXIS_FLAG_XXX for */
+ /* possible values. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0~means success. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_Get_Var_Axis_Flags( FT_MM_Var* master,
+ FT_UInt axis_index,
+ FT_UInt* flags );
+
/* */
diff --git a/thirdparty/freetype/include/freetype/ftoutln.h b/thirdparty/freetype/include/freetype/ftoutln.h
index 07f73ebb1b..56f56a9603 100644
--- a/thirdparty/freetype/include/freetype/ftoutln.h
+++ b/thirdparty/freetype/include/freetype/ftoutln.h
@@ -385,6 +385,9 @@ FT_BEGIN_HEADER
/* @FT_Outline_Embolden, which uses the same strength in both */
/* directions. */
/* */
+ /* <Since> */
+ /* 2.4.10 */
+ /* */
FT_EXPORT( FT_Error )
FT_Outline_EmboldenXY( FT_Outline* outline,
FT_Pos xstrength,
diff --git a/thirdparty/freetype/include/freetype/internal/ftcalc.h b/thirdparty/freetype/include/freetype/internal/ftcalc.h
index c9ac9d8246..8b35f03d88 100644
--- a/thirdparty/freetype/include/freetype/internal/ftcalc.h
+++ b/thirdparty/freetype/include/freetype/internal/ftcalc.h
@@ -399,16 +399,42 @@ FT_BEGIN_HEADER
#endif /* 0 */
-#define INT_TO_F26DOT6( x ) ( (FT_Long)(x) << 6 )
-#define INT_TO_F2DOT14( x ) ( (FT_Long)(x) << 14 )
-#define INT_TO_FIXED( x ) ( (FT_Long)(x) << 16 )
-#define F2DOT14_TO_FIXED( x ) ( (FT_Long)(x) << 2 )
-#define FLOAT_TO_FIXED( x ) ( (FT_Long)( x * 65536.0 ) )
+#define INT_TO_F26DOT6( x ) ( (FT_Long)(x) * 64 ) /* << 6 */
+#define INT_TO_F2DOT14( x ) ( (FT_Long)(x) * 16384 ) /* << 14 */
+#define INT_TO_FIXED( x ) ( (FT_Long)(x) * 65536 ) /* << 16 */
+#define F2DOT14_TO_FIXED( x ) ( (FT_Long)(x) * 4 ) /* << 2 */
#define FIXED_TO_INT( x ) ( FT_RoundFix( x ) >> 16 )
#define ROUND_F26DOT6( x ) ( x >= 0 ? ( ( (x) + 32 ) & -64 ) \
: ( -( ( 32 - (x) ) & -64 ) ) )
+ /*
+ * The following macros have two purposes.
+ *
+ * . Tag places where overflow is expected and harmless.
+ *
+ * . Avoid run-time sanitizer errors.
+ *
+ * Use with care!
+ */
+#define ADD_LONG( a, b ) \
+ (FT_Long)( (FT_ULong)(a) + (FT_ULong)(b) )
+#define SUB_LONG( a, b ) \
+ (FT_Long)( (FT_ULong)(a) - (FT_ULong)(b) )
+#define MUL_LONG( a, b ) \
+ (FT_Long)( (FT_ULong)(a) * (FT_ULong)(b) )
+#define NEG_LONG( a ) \
+ (FT_Long)( (FT_ULong)0 - (FT_ULong)(a) )
+
+#define ADD_INT32( a, b ) \
+ (FT_Int32)( (FT_UInt32)(a) + (FT_UInt32)(b) )
+#define SUB_INT32( a, b ) \
+ (FT_Int32)( (FT_UInt32)(a) - (FT_UInt32)(b) )
+#define MUL_INT32( a, b ) \
+ (FT_Int32)( (FT_UInt32)(a) * (FT_UInt32)(b) )
+#define NEG_INT32( a ) \
+ (FT_Int32)( (FT_UInt32)0 - (FT_UInt32)(a) )
+
FT_END_HEADER
diff --git a/thirdparty/freetype/include/freetype/internal/ftobjs.h b/thirdparty/freetype/include/freetype/internal/ftobjs.h
index 558409166d..4231be238a 100644
--- a/thirdparty/freetype/include/freetype/internal/ftobjs.h
+++ b/thirdparty/freetype/include/freetype/internal/ftobjs.h
@@ -36,6 +36,7 @@
#include FT_INTERNAL_AUTOHINT_H
#include FT_INTERNAL_SERVICE_H
#include FT_INTERNAL_PIC_H
+#include FT_INTERNAL_CALC_H
#ifdef FT_CONFIG_OPTION_INCREMENTAL
#include FT_INCREMENTAL_H
@@ -85,13 +86,29 @@ FT_BEGIN_HEADER
/* we use FT_TYPEOF to suppress signedness compilation warnings */
#define FT_PAD_FLOOR( x, n ) ( (x) & ~FT_TYPEOF( x )( (n)-1 ) )
-#define FT_PAD_ROUND( x, n ) FT_PAD_FLOOR( (x) + ((n)/2), n )
-#define FT_PAD_CEIL( x, n ) FT_PAD_FLOOR( (x) + ((n)-1), n )
+#define FT_PAD_ROUND( x, n ) FT_PAD_FLOOR( (x) + (n)/2, n )
+#define FT_PAD_CEIL( x, n ) FT_PAD_FLOOR( (x) + (n)-1, n )
#define FT_PIX_FLOOR( x ) ( (x) & ~FT_TYPEOF( x )63 )
#define FT_PIX_ROUND( x ) FT_PIX_FLOOR( (x) + 32 )
#define FT_PIX_CEIL( x ) FT_PIX_FLOOR( (x) + 63 )
+ /* specialized versions (for signed values) */
+ /* that don't produce run-time errors due to integer overflow */
+#define FT_PAD_ROUND_LONG( x, n ) FT_PAD_FLOOR( ADD_LONG( (x), (n) / 2 ), \
+ n )
+#define FT_PAD_CEIL_LONG( x, n ) FT_PAD_FLOOR( ADD_LONG( (x), (n) - 1 ), \
+ n )
+#define FT_PIX_ROUND_LONG( x ) FT_PIX_FLOOR( ADD_LONG( (x), 32 ) )
+#define FT_PIX_CEIL_LONG( x ) FT_PIX_FLOOR( ADD_LONG( (x), 63 ) )
+
+#define FT_PAD_ROUND_INT32( x, n ) FT_PAD_FLOOR( ADD_INT32( (x), (n) / 2 ), \
+ n )
+#define FT_PAD_CEIL_INT32( x, n ) FT_PAD_FLOOR( ADD_INT32( (x), (n) - 1 ), \
+ n )
+#define FT_PIX_ROUND_INT32( x ) FT_PIX_FLOOR( ADD_INT32( (x), 32 ) )
+#define FT_PIX_CEIL_INT32( x ) FT_PIX_FLOOR( ADD_INT32( (x), 63 ) )
+
/*
* character classification functions -- since these are used to parse
@@ -856,11 +873,6 @@ FT_BEGIN_HEADER
/* */
/* auto_hinter :: The auto-hinter module interface. */
/* */
- /* raster_pool :: The raster object's render pool. This can */
- /* ideally be changed dynamically at run-time. */
- /* */
- /* raster_pool_size :: The size of the render pool in bytes. */
- /* */
/* debug_hooks :: An array of four function pointers that allow */
/* debuggers to hook into a font format's */
/* interpreter. Currently, only the TrueType */
@@ -869,9 +881,6 @@ FT_BEGIN_HEADER
/* lcd_filter :: If subpixel rendering is activated, the */
/* selected LCD filter mode. */
/* */
- /* lcd_extra :: If subpixel rendering is activated, the number */
- /* of extra pixels needed for the LCD filter. */
- /* */
/* lcd_weights :: If subpixel rendering is activated, the LCD */
/* filter weights, if any. */
/* */
@@ -903,15 +912,10 @@ FT_BEGIN_HEADER
FT_Renderer cur_renderer; /* current outline renderer */
FT_Module auto_hinter;
- FT_Byte* raster_pool; /* scan-line conversion */
- /* render pool */
- FT_ULong raster_pool_size; /* size of render pool in bytes */
-
FT_DebugHook_Func debug_hooks[4];
#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
FT_LcdFilter lcd_filter;
- FT_Int lcd_extra; /* number of extra pixels */
FT_LcdFiveTapFilter lcd_weights; /* filter weights, if any */
FT_Bitmap_LcdFilterFunc lcd_filter_func; /* filtering callback */
#endif
diff --git a/thirdparty/freetype/include/freetype/tttags.h b/thirdparty/freetype/include/freetype/tttags.h
index 32eb2fdc26..b7d3bac0f1 100644
--- a/thirdparty/freetype/include/freetype/tttags.h
+++ b/thirdparty/freetype/include/freetype/tttags.h
@@ -106,6 +106,12 @@ FT_BEGIN_HEADER
#define TTAG_VVAR FT_MAKE_TAG( 'V', 'V', 'A', 'R' )
#define TTAG_wOFF FT_MAKE_TAG( 'w', 'O', 'F', 'F' )
+/* used by "Keyboard.dfont" on legacy Mac OS X */
+#define TTAG_0xA5kbd FT_MAKE_TAG( 0xA5, 'k', 'b', 'd' )
+
+/* used by "LastResort.dfont" on legacy Mac OS X */
+#define TTAG_0xA5lst FT_MAKE_TAG( 0xA5, 'l', 's', 't' )
+
FT_END_HEADER
diff --git a/thirdparty/freetype/src/autofit/afblue.c b/thirdparty/freetype/src/autofit/afblue.c
index a00c3a0765..fedeacf797 100644
--- a/thirdparty/freetype/src/autofit/afblue.c
+++ b/thirdparty/freetype/src/autofit/afblue.c
@@ -592,9 +592,6 @@
{ AF_BLUE_STRING_KAYAH_LI_DESCENDER, 0 },
{ AF_BLUE_STRING_KAYAH_LI_LARGE_DESCENDER, 0 },
{ AF_BLUE_STRING_MAX, 0 },
- { AF_BLUE_STRING_KANNADA_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
- { AF_BLUE_STRING_KANNADA_BOTTOM, 0 },
- { AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_KHMER_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
AF_BLUE_PROPERTY_LATIN_X_HEIGHT },
{ AF_BLUE_STRING_KHMER_SUBSCRIPT_TOP, AF_BLUE_PROPERTY_LATIN_SUB_TOP },
@@ -606,6 +603,9 @@
AF_BLUE_PROPERTY_LATIN_X_HEIGHT },
{ AF_BLUE_STRING_KHMER_SYMBOLS_WANING_BOTTOM, 0 },
{ AF_BLUE_STRING_MAX, 0 },
+ { AF_BLUE_STRING_KANNADA_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
+ { AF_BLUE_STRING_KANNADA_BOTTOM, 0 },
+ { AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_LAO_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
AF_BLUE_PROPERTY_LATIN_X_HEIGHT },
{ AF_BLUE_STRING_LAO_BOTTOM, 0 },
@@ -701,6 +701,9 @@
{ AF_BLUE_STRING_TELUGU_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_TELUGU_BOTTOM, 0 },
{ AF_BLUE_STRING_MAX, 0 },
+ { AF_BLUE_STRING_TIFINAGH, AF_BLUE_PROPERTY_LATIN_TOP },
+ { AF_BLUE_STRING_TIFINAGH, 0 },
+ { AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_THAI_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
AF_BLUE_PROPERTY_LATIN_X_HEIGHT },
{ AF_BLUE_STRING_THAI_BOTTOM, 0 },
@@ -710,9 +713,6 @@
{ AF_BLUE_STRING_THAI_LARGE_DESCENDER, 0 },
{ AF_BLUE_STRING_THAI_DIGIT_TOP, 0 },
{ AF_BLUE_STRING_MAX, 0 },
- { AF_BLUE_STRING_TIFINAGH, AF_BLUE_PROPERTY_LATIN_TOP },
- { AF_BLUE_STRING_TIFINAGH, 0 },
- { AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_VAI_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_VAI_BOTTOM, 0 },
{ AF_BLUE_STRING_MAX, 0 },
diff --git a/thirdparty/freetype/src/autofit/afblue.dat b/thirdparty/freetype/src/autofit/afblue.dat
index 454923e9ca..f62eb82a1a 100644
--- a/thirdparty/freetype/src/autofit/afblue.dat
+++ b/thirdparty/freetype/src/autofit/afblue.dat
@@ -872,11 +872,6 @@ AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN:
{ AF_BLUE_STRING_KAYAH_LI_LARGE_DESCENDER, 0 }
{ AF_BLUE_STRING_MAX, 0 }
- AF_BLUE_STRINGSET_KNDA
- { AF_BLUE_STRING_KANNADA_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_KANNADA_BOTTOM, 0 }
- { AF_BLUE_STRING_MAX, 0 }
-
AF_BLUE_STRINGSET_KHMR
{ AF_BLUE_STRING_KHMER_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
AF_BLUE_PROPERTY_LATIN_X_HEIGHT }
@@ -892,6 +887,11 @@ AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN:
{ AF_BLUE_STRING_KHMER_SYMBOLS_WANING_BOTTOM, 0 }
{ AF_BLUE_STRING_MAX, 0 }
+ AF_BLUE_STRINGSET_KNDA
+ { AF_BLUE_STRING_KANNADA_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
+ { AF_BLUE_STRING_KANNADA_BOTTOM, 0 }
+ { AF_BLUE_STRING_MAX, 0 }
+
AF_BLUE_STRINGSET_LAO
{ AF_BLUE_STRING_LAO_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
AF_BLUE_PROPERTY_LATIN_X_HEIGHT }
@@ -1027,6 +1027,11 @@ AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN:
{ AF_BLUE_STRING_TELUGU_BOTTOM, 0 }
{ AF_BLUE_STRING_MAX, 0 }
+ AF_BLUE_STRINGSET_TFNG
+ { AF_BLUE_STRING_TIFINAGH, AF_BLUE_PROPERTY_LATIN_TOP }
+ { AF_BLUE_STRING_TIFINAGH, 0 }
+ { AF_BLUE_STRING_MAX, 0 }
+
AF_BLUE_STRINGSET_THAI
{ AF_BLUE_STRING_THAI_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
AF_BLUE_PROPERTY_LATIN_X_HEIGHT }
@@ -1038,11 +1043,6 @@ AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN:
{ AF_BLUE_STRING_THAI_DIGIT_TOP, 0 }
{ AF_BLUE_STRING_MAX, 0 }
- AF_BLUE_STRINGSET_TFNG
- { AF_BLUE_STRING_TIFINAGH, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_TIFINAGH, 0 }
- { AF_BLUE_STRING_MAX, 0 }
-
AF_BLUE_STRINGSET_VAII
{ AF_BLUE_STRING_VAI_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
{ AF_BLUE_STRING_VAI_BOTTOM, 0 }
diff --git a/thirdparty/freetype/src/autofit/afblue.h b/thirdparty/freetype/src/autofit/afblue.h
index e227dbf50b..99ef51cd4a 100644
--- a/thirdparty/freetype/src/autofit/afblue.h
+++ b/thirdparty/freetype/src/autofit/afblue.h
@@ -344,9 +344,9 @@ FT_BEGIN_HEADER
AF_BLUE_STRINGSET_GURU = 116,
AF_BLUE_STRINGSET_HEBR = 122,
AF_BLUE_STRINGSET_KALI = 126,
- AF_BLUE_STRINGSET_KNDA = 132,
- AF_BLUE_STRINGSET_KHMR = 135,
- AF_BLUE_STRINGSET_KHMS = 141,
+ AF_BLUE_STRINGSET_KHMR = 132,
+ AF_BLUE_STRINGSET_KHMS = 138,
+ AF_BLUE_STRINGSET_KNDA = 141,
AF_BLUE_STRINGSET_LAO = 144,
AF_BLUE_STRINGSET_LATN = 150,
AF_BLUE_STRINGSET_LATB = 157,
@@ -367,8 +367,8 @@ FT_BEGIN_HEADER
AF_BLUE_STRINGSET_TAML = 222,
AF_BLUE_STRINGSET_TAVT = 225,
AF_BLUE_STRINGSET_TELU = 228,
- AF_BLUE_STRINGSET_THAI = 231,
- AF_BLUE_STRINGSET_TFNG = 239,
+ AF_BLUE_STRINGSET_TFNG = 231,
+ AF_BLUE_STRINGSET_THAI = 234,
AF_BLUE_STRINGSET_VAII = 242,
af_blue_2_1 = 245,
#ifdef AF_CONFIG_OPTION_CJK
diff --git a/thirdparty/freetype/src/autofit/afcjk.c b/thirdparty/freetype/src/autofit/afcjk.c
index 61e29cdeda..897533d148 100644
--- a/thirdparty/freetype/src/autofit/afcjk.c
+++ b/thirdparty/freetype/src/autofit/afcjk.c
@@ -2272,13 +2272,7 @@
goto Exit;
/* analyze glyph outline */
-#ifdef AF_CONFIG_OPTION_USE_WARPER
- if ( ( metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT &&
- AF_HINTS_DO_WARP( hints ) ) ||
- AF_HINTS_DO_HORIZONTAL( hints ) )
-#else
if ( AF_HINTS_DO_HORIZONTAL( hints ) )
-#endif
{
error = af_cjk_hints_detect_features( hints, AF_DIMENSION_HORZ );
if ( error )
@@ -2304,9 +2298,9 @@
{
#ifdef AF_CONFIG_OPTION_USE_WARPER
- if ( dim == AF_DIMENSION_HORZ &&
- metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT &&
- AF_HINTS_DO_WARP( hints ) )
+ if ( dim == AF_DIMENSION_HORZ &&
+ metrics->root.scaler.render_mode == FT_RENDER_MODE_NORMAL &&
+ AF_HINTS_DO_WARP( hints ) )
{
AF_WarperRec warper;
FT_Fixed scale;
diff --git a/thirdparty/freetype/src/autofit/afhints.c b/thirdparty/freetype/src/autofit/afhints.c
index f1ff0baef8..1b21c06c2c 100644
--- a/thirdparty/freetype/src/autofit/afhints.c
+++ b/thirdparty/freetype/src/autofit/afhints.c
@@ -507,15 +507,15 @@
return FT_THROW( Invalid_Argument );
seg = &axis->segments[idx];
- *offset = ( dim == AF_DIMENSION_HORZ ) ? seg->first->ox
- : seg->first->oy;
+ *offset = ( dim == AF_DIMENSION_HORZ ) ? seg->first->fx
+ : seg->first->fy;
if ( seg->edge )
*is_blue = (FT_Bool)( seg->edge->blue_edge != 0 );
else
*is_blue = FALSE;
if ( *is_blue )
- *blue_offset = seg->edge->blue_edge->cur;
+ *blue_offset = seg->edge->blue_edge->org;
else
*blue_offset = 0;
diff --git a/thirdparty/freetype/src/autofit/aflatin.c b/thirdparty/freetype/src/autofit/aflatin.c
index 11fa523c83..02b3b8bbd3 100644
--- a/thirdparty/freetype/src/autofit/aflatin.c
+++ b/thirdparty/freetype/src/autofit/aflatin.c
@@ -1690,9 +1690,11 @@
if ( prev_max_on_coord > max_on_coord )
max_on_coord = prev_max_on_coord;
- prev_segment->last = point;
- prev_segment->pos = (FT_Short)( ( min_pos +
- max_pos ) >> 1 );
+ prev_segment->last = point;
+ prev_segment->pos = (FT_Short)( ( min_pos +
+ max_pos ) >> 1 );
+ prev_segment->delta = (FT_Short)( ( max_pos -
+ min_pos ) >> 1 );
if ( ( min_flags | max_flags ) & AF_FLAG_CONTROL &&
( max_on_coord - min_on_coord ) < flat_threshold )
@@ -1720,9 +1722,11 @@
if ( max_pos > prev_max_pos )
prev_max_pos = max_pos;
- prev_segment->last = point;
- prev_segment->pos = (FT_Short)( ( prev_min_pos +
- prev_max_pos ) >> 1 );
+ prev_segment->last = point;
+ prev_segment->pos = (FT_Short)( ( prev_min_pos +
+ prev_max_pos ) >> 1 );
+ prev_segment->delta = (FT_Short)( ( prev_max_pos -
+ prev_min_pos ) >> 1 );
}
else
{
@@ -1733,8 +1737,9 @@
if ( prev_max_pos > max_pos )
max_pos = prev_max_pos;
- segment->last = point;
- segment->pos = (FT_Short)( ( min_pos + max_pos ) >> 1 );
+ segment->last = point;
+ segment->pos = (FT_Short)( ( min_pos + max_pos ) >> 1 );
+ segment->delta = (FT_Short)( ( max_pos - min_pos ) >> 1 );
if ( ( min_flags | max_flags ) & AF_FLAG_CONTROL &&
( max_on_coord - min_on_coord ) < flat_threshold )
@@ -3492,13 +3497,7 @@
goto Exit;
/* analyze glyph outline */
-#ifdef AF_CONFIG_OPTION_USE_WARPER
- if ( ( metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT &&
- AF_HINTS_DO_WARP( hints ) ) ||
- AF_HINTS_DO_HORIZONTAL( hints ) )
-#else
if ( AF_HINTS_DO_HORIZONTAL( hints ) )
-#endif
{
axis = &metrics->axis[AF_DIMENSION_HORZ];
error = af_latin_hints_detect_features( hints,
@@ -3528,9 +3527,9 @@
for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
{
#ifdef AF_CONFIG_OPTION_USE_WARPER
- if ( dim == AF_DIMENSION_HORZ &&
- metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT &&
- AF_HINTS_DO_WARP( hints ) )
+ if ( dim == AF_DIMENSION_HORZ &&
+ metrics->root.scaler.render_mode == FT_RENDER_MODE_NORMAL &&
+ AF_HINTS_DO_WARP( hints ) )
{
AF_WarperRec warper;
FT_Fixed scale;
diff --git a/thirdparty/freetype/src/autofit/aflatin2.c b/thirdparty/freetype/src/autofit/aflatin2.c
index 0607278b1e..fb42445116 100644
--- a/thirdparty/freetype/src/autofit/aflatin2.c
+++ b/thirdparty/freetype/src/autofit/aflatin2.c
@@ -2340,13 +2340,7 @@
goto Exit;
/* analyze glyph outline */
-#ifdef AF_CONFIG_OPTION_USE_WARPER
- if ( ( metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT &&
- AF_HINTS_DO_WARP( hints ) ) ||
- AF_HINTS_DO_HORIZONTAL( hints ) )
-#else
if ( AF_HINTS_DO_HORIZONTAL( hints ) )
-#endif
{
error = af_latin2_hints_detect_features( hints, AF_DIMENSION_HORZ );
if ( error )
@@ -2366,9 +2360,9 @@
for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
{
#ifdef AF_CONFIG_OPTION_USE_WARPER
- if ( dim == AF_DIMENSION_HORZ &&
- metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT &&
- AF_HINTS_DO_WARP( hints ) )
+ if ( dim == AF_DIMENSION_HORZ &&
+ metrics->root.scaler.render_mode == FT_RENDER_MODE_NORMAL &&
+ AF_HINTS_DO_WARP( hints ) )
{
AF_WarperRec warper;
FT_Fixed scale;
diff --git a/thirdparty/freetype/src/autofit/afloader.c b/thirdparty/freetype/src/autofit/afloader.c
index 78c4368b61..067ebd17f6 100644
--- a/thirdparty/freetype/src/autofit/afloader.c
+++ b/thirdparty/freetype/src/autofit/afloader.c
@@ -483,8 +483,8 @@
FT_Pos pp2x = loader->pp2.x;
- loader->pp1.x = FT_PIX_ROUND( pp1x );
- loader->pp2.x = FT_PIX_ROUND( pp2x );
+ loader->pp1.x = FT_PIX_ROUND( pp1x + hints->xmin_delta );
+ loader->pp2.x = FT_PIX_ROUND( pp2x + hints->xmax_delta );
slot->lsb_delta = loader->pp1.x - pp1x;
slot->rsb_delta = loader->pp2.x - pp2x;
@@ -498,8 +498,8 @@
FT_Pos pp2x = loader->pp2.x;
- loader->pp1.x = FT_PIX_ROUND( pp1x + hints->xmin_delta );
- loader->pp2.x = FT_PIX_ROUND( pp2x + hints->xmax_delta );
+ loader->pp1.x = FT_PIX_ROUND( pp1x );
+ loader->pp2.x = FT_PIX_ROUND( pp2x );
slot->lsb_delta = loader->pp1.x - pp1x;
slot->rsb_delta = loader->pp2.x - pp2x;
diff --git a/thirdparty/freetype/src/autofit/afscript.h b/thirdparty/freetype/src/autofit/afscript.h
index 7547a9e6f9..cb815dbb40 100644
--- a/thirdparty/freetype/src/autofit/afscript.h
+++ b/thirdparty/freetype/src/autofit/afscript.h
@@ -187,12 +187,6 @@
HINTING_BOTTOM_TO_TOP,
"\xEA\xA4\x8D \xEA\xA4\x80" ) /* ê¤ ê¤€ */
- SCRIPT( knda, KNDA,
- "Kannada",
- HB_SCRIPT_KANNADA,
- HINTING_BOTTOM_TO_TOP,
- "\xE0\xB3\xA6 \xE0\xB2\xAC" ) /* ೦ ಬ */
-
/* only digit zero has a simple shape in the Khmer script */
SCRIPT( khmr, KHMR,
"Khmer",
@@ -206,6 +200,12 @@
HINTING_BOTTOM_TO_TOP,
"\xE1\xA7\xA1 \xE1\xA7\xAA" ) /* ᧡ ᧪ */
+ SCRIPT( knda, KNDA,
+ "Kannada",
+ HB_SCRIPT_KANNADA,
+ HINTING_BOTTOM_TO_TOP,
+ "\xE0\xB3\xA6 \xE0\xB2\xAC" ) /* ೦ ಬ */
+
/* only digit zero has a simple shape in the Lao script */
SCRIPT( lao, LAO,
"Lao",
@@ -330,18 +330,18 @@
HINTING_BOTTOM_TO_TOP,
"\xE0\xB1\xA6 \xE0\xB1\xA7" ) /* ౦ ౧ */
- SCRIPT( thai, THAI,
- "Thai",
- HB_SCRIPT_THAI,
- HINTING_BOTTOM_TO_TOP,
- "\xE0\xB8\xB2 \xE0\xB9\x85 \xE0\xB9\x90" ) /* า ๅ ๠*/
-
SCRIPT( tfng, TFNG,
"Tifinagh",
HB_SCRIPT_TIFINAGH,
HINTING_BOTTOM_TO_TOP,
"\xE2\xB5\x94" ) /* âµ” */
+ SCRIPT( thai, THAI,
+ "Thai",
+ HB_SCRIPT_THAI,
+ HINTING_BOTTOM_TO_TOP,
+ "\xE0\xB8\xB2 \xE0\xB9\x85 \xE0\xB9\x90" ) /* า ๅ ๠*/
+
SCRIPT( vaii, VAII,
"Vai",
HB_SCRIPT_VAI,
diff --git a/thirdparty/freetype/src/autofit/afshaper.c b/thirdparty/freetype/src/autofit/afshaper.c
index da92fad3ed..d259964217 100644
--- a/thirdparty/freetype/src/autofit/afshaper.c
+++ b/thirdparty/freetype/src/autofit/afshaper.c
@@ -18,6 +18,7 @@
#include <ft2build.h>
#include FT_FREETYPE_H
+#include FT_ADVANCES_H
#include "afglobal.h"
#include "aftypes.h"
#include "afshaper.h"
diff --git a/thirdparty/freetype/src/autofit/afstyles.h b/thirdparty/freetype/src/autofit/afstyles.h
index a5e13d8944..281559eea2 100644
--- a/thirdparty/freetype/src/autofit/afstyles.h
+++ b/thirdparty/freetype/src/autofit/afstyles.h
@@ -255,13 +255,6 @@
AF_BLUE_STRINGSET_KALI,
AF_COVERAGE_DEFAULT )
- STYLE( knda_dflt, KNDA_DFLT,
- "Kannada default style",
- AF_WRITING_SYSTEM_LATIN,
- AF_SCRIPT_KNDA,
- AF_BLUE_STRINGSET_KNDA,
- AF_COVERAGE_DEFAULT )
-
STYLE( khmr_dflt, KHMR_DFLT,
"Khmer default style",
AF_WRITING_SYSTEM_LATIN,
@@ -276,6 +269,13 @@
AF_BLUE_STRINGSET_KHMS,
AF_COVERAGE_DEFAULT )
+ STYLE( knda_dflt, KNDA_DFLT,
+ "Kannada default style",
+ AF_WRITING_SYSTEM_LATIN,
+ AF_SCRIPT_KNDA,
+ AF_BLUE_STRINGSET_KNDA,
+ AF_COVERAGE_DEFAULT )
+
STYLE( lao_dflt, LAO_DFLT,
"Lao default style",
AF_WRITING_SYSTEM_LATIN,
@@ -420,13 +420,6 @@
AF_BLUE_STRINGSET_TELU,
AF_COVERAGE_DEFAULT )
- STYLE( thai_dflt, THAI_DFLT,
- "Thai default style",
- AF_WRITING_SYSTEM_LATIN,
- AF_SCRIPT_THAI,
- AF_BLUE_STRINGSET_THAI,
- AF_COVERAGE_DEFAULT )
-
STYLE( tfng_dflt, TFNG_DFLT,
"Tifinagh default style",
AF_WRITING_SYSTEM_LATIN,
@@ -434,6 +427,13 @@
AF_BLUE_STRINGSET_TFNG,
AF_COVERAGE_DEFAULT )
+ STYLE( thai_dflt, THAI_DFLT,
+ "Thai default style",
+ AF_WRITING_SYSTEM_LATIN,
+ AF_SCRIPT_THAI,
+ AF_BLUE_STRINGSET_THAI,
+ AF_COVERAGE_DEFAULT )
+
STYLE( vaii_dflt, VAII_DFLT,
"Vai default style",
AF_WRITING_SYSTEM_LATIN,
diff --git a/thirdparty/freetype/src/base/ftbitmap.c b/thirdparty/freetype/src/base/ftbitmap.c
index 88c88c4c1b..e567a0453e 100644
--- a/thirdparty/freetype/src/base/ftbitmap.c
+++ b/thirdparty/freetype/src/base/ftbitmap.c
@@ -226,7 +226,7 @@
}
/* otherwise allocate new buffer */
- if ( FT_QALLOC_MULT( buffer, new_pitch, bitmap->rows + ypixels ) )
+ if ( FT_QALLOC_MULT( buffer, bitmap->rows + ypixels, new_pitch ) )
return error;
/* new rows get added at the top of the bitmap, */
@@ -534,8 +534,7 @@
(FT_ULong)target->rows > FT_ULONG_MAX / (FT_ULong)target_pitch )
return FT_THROW( Invalid_Argument );
- if ( target->rows * (FT_ULong)target_pitch > old_size &&
- FT_QREALLOC( target->buffer,
+ if ( FT_QREALLOC( target->buffer,
old_size, target->rows * (FT_UInt)target_pitch ) )
return error;
diff --git a/thirdparty/freetype/src/base/ftcalc.c b/thirdparty/freetype/src/base/ftcalc.c
index f0525502f3..00d63c6e6b 100644
--- a/thirdparty/freetype/src/base/ftcalc.c
+++ b/thirdparty/freetype/src/base/ftcalc.c
@@ -68,14 +68,15 @@
#define FT_COMPONENT trace_calc
- /* transfer sign leaving a positive number */
-#define FT_MOVE_SIGN( x, s ) \
- FT_BEGIN_STMNT \
- if ( x < 0 ) \
- { \
- x = -x; \
- s = -s; \
- } \
+ /* transfer sign, leaving a positive number; */
+ /* we need an unsigned value to safely negate INT_MIN (or LONG_MIN) */
+#define FT_MOVE_SIGN( x, x_unsigned, s ) \
+ FT_BEGIN_STMNT \
+ if ( x < 0 ) \
+ { \
+ x_unsigned = 0U - (x_unsigned); \
+ s = -s; \
+ } \
FT_END_STMNT
/* The following three functions are available regardless of whether */
@@ -86,7 +87,7 @@
FT_EXPORT_DEF( FT_Fixed )
FT_RoundFix( FT_Fixed a )
{
- return ( a + 0x8000L - ( a < 0 ) ) & ~0xFFFFL;
+ return ( ADD_LONG( a, 0x8000L - ( a < 0 ) ) ) & ~0xFFFFL;
}
@@ -95,7 +96,7 @@
FT_EXPORT_DEF( FT_Fixed )
FT_CeilFix( FT_Fixed a )
{
- return ( a + 0xFFFFL ) & ~0xFFFFL;
+ return ( ADD_LONG( a, 0xFFFFL ) ) & ~0xFFFFL;
}
@@ -179,20 +180,20 @@
FT_Long d_;
- FT_MOVE_SIGN( a_, s );
- FT_MOVE_SIGN( b_, s );
- FT_MOVE_SIGN( c_, s );
-
a = (FT_UInt64)a_;
b = (FT_UInt64)b_;
c = (FT_UInt64)c_;
+ FT_MOVE_SIGN( a_, a, s );
+ FT_MOVE_SIGN( b_, b, s );
+ FT_MOVE_SIGN( c_, c, s );
+
d = c > 0 ? ( a * b + ( c >> 1 ) ) / c
: 0x7FFFFFFFUL;
d_ = (FT_Long)d;
- return s < 0 ? -d_ : d_;
+ return s < 0 ? NEG_LONG( d_ ) : d_;
}
@@ -208,20 +209,20 @@
FT_Long d_;
- FT_MOVE_SIGN( a_, s );
- FT_MOVE_SIGN( b_, s );
- FT_MOVE_SIGN( c_, s );
-
a = (FT_UInt64)a_;
b = (FT_UInt64)b_;
c = (FT_UInt64)c_;
+ FT_MOVE_SIGN( a_, a, s );
+ FT_MOVE_SIGN( b_, b, s );
+ FT_MOVE_SIGN( c_, c, s );
+
d = c > 0 ? a * b / c
: 0x7FFFFFFFUL;
d_ = (FT_Long)d;
- return s < 0 ? -d_ : d_;
+ return s < 0 ? NEG_LONG( d_ ) : d_;
}
@@ -257,18 +258,18 @@
FT_Long q_;
- FT_MOVE_SIGN( a_, s );
- FT_MOVE_SIGN( b_, s );
-
a = (FT_UInt64)a_;
b = (FT_UInt64)b_;
+ FT_MOVE_SIGN( a_, a, s );
+ FT_MOVE_SIGN( b_, b, s );
+
q = b > 0 ? ( ( a << 16 ) + ( b >> 1 ) ) / b
: 0x7FFFFFFFUL;
q_ = (FT_Long)q;
- return s < 0 ? -q_ : q_;
+ return s < 0 ? NEG_LONG( q_ ) : q_;
}
@@ -422,14 +423,14 @@
/* XXX: this function does not allow 64-bit arguments */
- FT_MOVE_SIGN( a_, s );
- FT_MOVE_SIGN( b_, s );
- FT_MOVE_SIGN( c_, s );
-
a = (FT_UInt32)a_;
b = (FT_UInt32)b_;
c = (FT_UInt32)c_;
+ FT_MOVE_SIGN( a_, a, s );
+ FT_MOVE_SIGN( b_, b, s );
+ FT_MOVE_SIGN( c_, c, s );
+
if ( c == 0 )
a = 0x7FFFFFFFUL;
@@ -455,7 +456,7 @@
a_ = (FT_Long)a;
- return s < 0 ? -a_ : a_;
+ return s < 0 ? NEG_LONG( a_ ) : a_;
}
@@ -470,14 +471,14 @@
/* XXX: this function does not allow 64-bit arguments */
- FT_MOVE_SIGN( a_, s );
- FT_MOVE_SIGN( b_, s );
- FT_MOVE_SIGN( c_, s );
-
a = (FT_UInt32)a_;
b = (FT_UInt32)b_;
c = (FT_UInt32)c_;
+ FT_MOVE_SIGN( a_, a, s );
+ FT_MOVE_SIGN( b_, b, s );
+ FT_MOVE_SIGN( c_, c, s );
+
if ( c == 0 )
a = 0x7FFFFFFFUL;
@@ -498,7 +499,7 @@
a_ = (FT_Long)a;
- return s < 0 ? -a_ : a_;
+ return s < 0 ? NEG_LONG( a_ ) : a_;
}
@@ -575,12 +576,12 @@
/* XXX: this function does not allow 64-bit arguments */
- FT_MOVE_SIGN( a_, s );
- FT_MOVE_SIGN( b_, s );
-
a = (FT_UInt32)a_;
b = (FT_UInt32)b_;
+ FT_MOVE_SIGN( a_, a, s );
+ FT_MOVE_SIGN( b_, b, s );
+
if ( a + ( b >> 8 ) <= 8190UL )
a = ( a * b + 0x8000UL ) >> 16;
else
@@ -594,7 +595,7 @@
a_ = (FT_Long)a;
- return s < 0 ? -a_ : a_;
+ return s < 0 ? NEG_LONG( a_ ) : a_;
#endif /* 0 */
@@ -614,12 +615,12 @@
/* XXX: this function does not allow 64-bit arguments */
- FT_MOVE_SIGN( a_, s );
- FT_MOVE_SIGN( b_, s );
-
a = (FT_UInt32)a_;
b = (FT_UInt32)b_;
+ FT_MOVE_SIGN( a_, a, s );
+ FT_MOVE_SIGN( b_, b, s );
+
if ( b == 0 )
{
/* check for division by 0 */
@@ -647,7 +648,7 @@
q_ = (FT_Long)q;
- return s < 0 ? -q_ : q_;
+ return s < 0 ? NEG_LONG( q_ ) : q_;
}
@@ -666,13 +667,19 @@
if ( !a || !b )
return;
- xx = FT_MulFix( a->xx, b->xx ) + FT_MulFix( a->xy, b->yx );
- xy = FT_MulFix( a->xx, b->xy ) + FT_MulFix( a->xy, b->yy );
- yx = FT_MulFix( a->yx, b->xx ) + FT_MulFix( a->yy, b->yx );
- yy = FT_MulFix( a->yx, b->xy ) + FT_MulFix( a->yy, b->yy );
-
- b->xx = xx; b->xy = xy;
- b->yx = yx; b->yy = yy;
+ xx = ADD_LONG( FT_MulFix( a->xx, b->xx ),
+ FT_MulFix( a->xy, b->yx ) );
+ xy = ADD_LONG( FT_MulFix( a->xx, b->xy ),
+ FT_MulFix( a->xy, b->yy ) );
+ yx = ADD_LONG( FT_MulFix( a->yx, b->xx ),
+ FT_MulFix( a->yy, b->yx ) );
+ yy = ADD_LONG( FT_MulFix( a->yx, b->xy ),
+ FT_MulFix( a->yy, b->yy ) );
+
+ b->xx = xx;
+ b->xy = xy;
+ b->yx = yx;
+ b->yy = yy;
}
@@ -722,13 +729,19 @@
if ( !a || !b )
return;
- xx = FT_MulDiv( a->xx, b->xx, val ) + FT_MulDiv( a->xy, b->yx, val );
- xy = FT_MulDiv( a->xx, b->xy, val ) + FT_MulDiv( a->xy, b->yy, val );
- yx = FT_MulDiv( a->yx, b->xx, val ) + FT_MulDiv( a->yy, b->yx, val );
- yy = FT_MulDiv( a->yx, b->xy, val ) + FT_MulDiv( a->yy, b->yy, val );
-
- b->xx = xx; b->xy = xy;
- b->yx = yx; b->yy = yy;
+ xx = ADD_LONG( FT_MulDiv( a->xx, b->xx, val ),
+ FT_MulDiv( a->xy, b->yx, val ) );
+ xy = ADD_LONG( FT_MulDiv( a->xx, b->xy, val ),
+ FT_MulDiv( a->xy, b->yy, val ) );
+ yx = ADD_LONG( FT_MulDiv( a->yx, b->xx, val ),
+ FT_MulDiv( a->yy, b->yx, val ) );
+ yy = ADD_LONG( FT_MulDiv( a->yx, b->xy, val ),
+ FT_MulDiv( a->yy, b->yy, val ) );
+
+ b->xx = xx;
+ b->xy = xy;
+ b->yx = yx;
+ b->yy = yy;
}
@@ -747,11 +760,10 @@
if ( !vector || !matrix )
return;
- xz = FT_MulDiv( vector->x, matrix->xx, val ) +
- FT_MulDiv( vector->y, matrix->xy, val );
-
- yz = FT_MulDiv( vector->x, matrix->yx, val ) +
- FT_MulDiv( vector->y, matrix->yy, val );
+ xz = ADD_LONG( FT_MulDiv( vector->x, matrix->xx, val ),
+ FT_MulDiv( vector->y, matrix->xy, val ) );
+ yz = ADD_LONG( FT_MulDiv( vector->x, matrix->yx, val ),
+ FT_MulDiv( vector->y, matrix->yy, val ) );
vector->x = xz;
vector->y = yz;
@@ -770,12 +782,12 @@
FT_Int sx = 1, sy = 1, shift;
- FT_MOVE_SIGN( x_, sx );
- FT_MOVE_SIGN( y_, sy );
-
x = (FT_UInt32)x_;
y = (FT_UInt32)y_;
+ FT_MOVE_SIGN( x_, x, sx );
+ FT_MOVE_SIGN( y_, y, sy );
+
/* trivial cases */
if ( x == 0 )
{
@@ -913,11 +925,13 @@
FT_Int result;
- if ( (FT_ULong)FT_ABS( in_x ) + (FT_ULong)FT_ABS( out_y ) <= 131071UL &&
- (FT_ULong)FT_ABS( in_y ) + (FT_ULong)FT_ABS( out_x ) <= 131071UL )
+ /* we silently ignore overflow errors, since such large values */
+ /* lead to even more (harmless) rendering errors later on */
+ if ( ADD_LONG( FT_ABS( in_x ), FT_ABS( out_y ) ) <= 131071L &&
+ ADD_LONG( FT_ABS( in_y ), FT_ABS( out_x ) ) <= 131071L )
{
- FT_Long z1 = in_x * out_y;
- FT_Long z2 = in_y * out_x;
+ FT_Long z1 = MUL_LONG( in_x, out_y );
+ FT_Long z2 = MUL_LONG( in_y, out_x );
if ( z1 > z2 )
diff --git a/thirdparty/freetype/src/base/ftglyph.c b/thirdparty/freetype/src/base/ftglyph.c
index 9bfb330508..3f78a8c36b 100644
--- a/thirdparty/freetype/src/base/ftglyph.c
+++ b/thirdparty/freetype/src/base/ftglyph.c
@@ -408,12 +408,28 @@
goto Exit;
/* copy advance while converting 26.6 to 16.16 format */
+ if ( slot->advance.x >= 0x8000L * 64 ||
+ slot->advance.x <= -0x8000L * 64 )
+ {
+ FT_ERROR(( "FT_Get_Glyph: advance width too large\n" ));
+ error = FT_THROW( Invalid_Argument );
+ goto Exit2;
+ }
+ if ( slot->advance.y >= 0x8000L * 64 ||
+ slot->advance.y <= -0x8000L * 64 )
+ {
+ FT_ERROR(( "FT_Get_Glyph: advance height too large\n" ));
+ error = FT_THROW( Invalid_Argument );
+ goto Exit2;
+ }
+
glyph->advance.x = slot->advance.x * 1024;
glyph->advance.y = slot->advance.y * 1024;
/* now import the image from the glyph slot */
error = clazz->glyph_init( glyph, slot );
+ Exit2:
/* if an error occurred, destroy the glyph */
if ( error )
FT_Done_Glyph( glyph );
diff --git a/thirdparty/freetype/src/base/ftlcdfil.c b/thirdparty/freetype/src/base/ftlcdfil.c
index 611b39f570..60c813fd9e 100644
--- a/thirdparty/freetype/src/base/ftlcdfil.c
+++ b/thirdparty/freetype/src/base/ftlcdfil.c
@@ -29,141 +29,107 @@
/* define USE_LEGACY to implement the legacy filter */
#define USE_LEGACY
+#define FT_SHIFTCLAMP( x ) ( x >>= 8, (FT_Byte)( x > 255 ? 255 : x ) )
+
/* FIR filter used by the default and light filters */
FT_BASE( void )
ft_lcd_filter_fir( FT_Bitmap* bitmap,
FT_Render_Mode mode,
FT_LcdFiveTapFilter weights )
{
- FT_UInt width = (FT_UInt)bitmap->width;
- FT_UInt height = (FT_UInt)bitmap->rows;
+ FT_UInt width = (FT_UInt)bitmap->width;
+ FT_UInt height = (FT_UInt)bitmap->rows;
+ FT_Int pitch = bitmap->pitch;
+ FT_Byte* origin = bitmap->buffer;
+
+ /* take care of bitmap flow */
+ if ( pitch > 0 )
+ origin += pitch * (FT_Int)( height - 1 );
/* horizontal in-place FIR filter */
- if ( mode == FT_RENDER_MODE_LCD && width >= 4 )
+ if ( mode == FT_RENDER_MODE_LCD && width >= 2 )
{
- FT_Byte* line = bitmap->buffer;
-
+ FT_Byte* line = origin;
- /* take care of bitmap flow */
- if ( bitmap->pitch < 0 )
- line -= bitmap->pitch * (FT_Int)( bitmap->rows - 1 );
- /* `fir' and `pix' must be at least 32 bit wide, since the sum of */
- /* the values in `weights' can exceed 0xFF */
+ /* `fir' must be at least 32 bit wide, since the sum of */
+ /* the values in `weights' can exceed 0xFF */
- for ( ; height > 0; height--, line += bitmap->pitch )
+ for ( ; height > 0; height--, line -= pitch )
{
- FT_UInt fir[4]; /* below, `pix' is used as the 5th element */
- FT_UInt val1, xx;
+ FT_UInt fir[5];
+ FT_UInt val, xx;
- val1 = line[0];
- fir[0] = weights[2] * val1;
- fir[1] = weights[3] * val1;
- fir[2] = weights[4] * val1;
- fir[3] = 0;
+ val = line[0];
+ fir[2] = weights[2] * val;
+ fir[3] = weights[3] * val;
+ fir[4] = weights[4] * val;
- val1 = line[1];
- fir[0] += weights[1] * val1;
- fir[1] += weights[2] * val1;
- fir[2] += weights[3] * val1;
- fir[3] += weights[4] * val1;
+ val = line[1];
+ fir[1] = fir[2] + weights[1] * val;
+ fir[2] = fir[3] + weights[2] * val;
+ fir[3] = fir[4] + weights[3] * val;
+ fir[4] = weights[4] * val;
for ( xx = 2; xx < width; xx++ )
{
- FT_UInt val, pix;
-
-
val = line[xx];
- pix = fir[0] + weights[0] * val;
- fir[0] = fir[1] + weights[1] * val;
- fir[1] = fir[2] + weights[2] * val;
- fir[2] = fir[3] + weights[3] * val;
- fir[3] = weights[4] * val;
-
- pix >>= 8;
- pix |= (FT_UInt)-(FT_Int)( pix >> 8 );
- line[xx - 2] = (FT_Byte)pix;
- }
+ fir[0] = fir[1] + weights[0] * val;
+ fir[1] = fir[2] + weights[1] * val;
+ fir[2] = fir[3] + weights[2] * val;
+ fir[3] = fir[4] + weights[3] * val;
+ fir[4] = weights[4] * val;
- {
- FT_UInt pix;
-
-
- pix = fir[0] >> 8;
- pix |= (FT_UInt)-(FT_Int)( pix >> 8 );
- line[xx - 2] = (FT_Byte)pix;
-
- pix = fir[1] >> 8;
- pix |= (FT_UInt)-(FT_Int)( pix >> 8 );
- line[xx - 1] = (FT_Byte)pix;
+ line[xx - 2] = FT_SHIFTCLAMP( fir[0] );
}
+
+ line[xx - 2] = FT_SHIFTCLAMP( fir[1] );
+ line[xx - 1] = FT_SHIFTCLAMP( fir[2] );
}
}
/* vertical in-place FIR filter */
- else if ( mode == FT_RENDER_MODE_LCD_V && height >= 4 )
+ else if ( mode == FT_RENDER_MODE_LCD_V && height >= 2 )
{
- FT_Byte* column = bitmap->buffer;
- FT_Int pitch = bitmap->pitch;
-
+ FT_Byte* column = origin;
- /* take care of bitmap flow */
- if ( bitmap->pitch < 0 )
- column -= bitmap->pitch * (FT_Int)( bitmap->rows - 1 );
for ( ; width > 0; width--, column++ )
{
FT_Byte* col = column;
- FT_UInt fir[4]; /* below, `pix' is used as the 5th element */
- FT_UInt val1, yy;
+ FT_UInt fir[5];
+ FT_UInt val, yy;
- val1 = col[0];
- fir[0] = weights[2] * val1;
- fir[1] = weights[3] * val1;
- fir[2] = weights[4] * val1;
- fir[3] = 0;
- col += pitch;
+ val = col[0];
+ fir[2] = weights[2] * val;
+ fir[3] = weights[3] * val;
+ fir[4] = weights[4] * val;
+ col -= pitch;
- val1 = col[0];
- fir[0] += weights[1] * val1;
- fir[1] += weights[2] * val1;
- fir[2] += weights[3] * val1;
- fir[3] += weights[4] * val1;
- col += pitch;
+ val = col[0];
+ fir[1] = fir[2] + weights[1] * val;
+ fir[2] = fir[3] + weights[2] * val;
+ fir[3] = fir[4] + weights[3] * val;
+ fir[4] = weights[4] * val;
+ col -= pitch;
- for ( yy = 2; yy < height; yy++ )
+ for ( yy = 2; yy < height; yy++, col -= pitch )
{
- FT_UInt val, pix;
-
-
val = col[0];
- pix = fir[0] + weights[0] * val;
- fir[0] = fir[1] + weights[1] * val;
- fir[1] = fir[2] + weights[2] * val;
- fir[2] = fir[3] + weights[3] * val;
- fir[3] = weights[4] * val;
-
- pix >>= 8;
- pix |= (FT_UInt)-(FT_Int)( pix >> 8 );
- col[-2 * pitch] = (FT_Byte)pix;
- col += pitch;
- }
-
- {
- FT_UInt pix;
-
+ fir[0] = fir[1] + weights[0] * val;
+ fir[1] = fir[2] + weights[1] * val;
+ fir[2] = fir[3] + weights[2] * val;
+ fir[3] = fir[4] + weights[3] * val;
+ fir[4] = weights[4] * val;
- pix = fir[0] >> 8;
- pix |= (FT_UInt)-(FT_Int)( pix >> 8 );
- col[-2 * pitch] = (FT_Byte)pix;
-
- pix = fir[1] >> 8;
- pix |= (FT_UInt)-(FT_Int)( pix >> 8 );
- col[-pitch] = (FT_Byte)pix;
+ col[pitch * 2] = FT_SHIFTCLAMP( fir[0] );
}
+
+ col[pitch * 2] = FT_SHIFTCLAMP( fir[1] );
+ col[pitch] = FT_SHIFTCLAMP( fir[2] );
}
}
}
@@ -177,9 +143,10 @@
FT_Render_Mode mode,
FT_Byte* weights )
{
- FT_UInt width = (FT_UInt)bitmap->width;
- FT_UInt height = (FT_UInt)bitmap->rows;
- FT_Int pitch = bitmap->pitch;
+ FT_UInt width = (FT_UInt)bitmap->width;
+ FT_UInt height = (FT_UInt)bitmap->rows;
+ FT_Int pitch = bitmap->pitch;
+ FT_Byte* origin = bitmap->buffer;
static const unsigned int filters[3][3] =
{
@@ -191,33 +158,31 @@
FT_UNUSED( weights );
+ /* take care of bitmap flow */
+ if ( pitch > 0 )
+ origin += pitch * (FT_Int)( height - 1 );
+
/* horizontal in-place intra-pixel filter */
if ( mode == FT_RENDER_MODE_LCD && width >= 3 )
{
- FT_Byte* line = bitmap->buffer;
+ FT_Byte* line = origin;
- /* take care of bitmap flow */
- if ( bitmap->pitch < 0 )
- line -= bitmap->pitch * (FT_Int)( bitmap->rows - 1 );
-
- for ( ; height > 0; height--, line += pitch )
+ for ( ; height > 0; height--, line -= pitch )
{
FT_UInt xx;
for ( xx = 0; xx < width; xx += 3 )
{
- FT_UInt r = 0;
- FT_UInt g = 0;
- FT_UInt b = 0;
+ FT_UInt r, g, b;
FT_UInt p;
p = line[xx];
- r += filters[0][0] * p;
- g += filters[0][1] * p;
- b += filters[0][2] * p;
+ r = filters[0][0] * p;
+ g = filters[0][1] * p;
+ b = filters[0][2] * p;
p = line[xx + 1];
r += filters[1][0] * p;
@@ -237,31 +202,24 @@
}
else if ( mode == FT_RENDER_MODE_LCD_V && height >= 3 )
{
- FT_Byte* column = bitmap->buffer;
-
+ FT_Byte* column = origin;
- /* take care of bitmap flow */
- if ( bitmap->pitch < 0 )
- column -= bitmap->pitch * (FT_Int)( bitmap->rows - 1 );
for ( ; width > 0; width--, column++ )
{
- FT_Byte* col = column;
- FT_Byte* col_end = col + (FT_Int)height * pitch;
+ FT_Byte* col = column - 2 * pitch;
- for ( ; col < col_end; col += 3 * pitch )
+ for ( ; height > 0; height -= 3, col -= 3 * pitch )
{
- FT_UInt r = 0;
- FT_UInt g = 0;
- FT_UInt b = 0;
+ FT_UInt r, g, b;
FT_UInt p;
p = col[0];
- r += filters[0][0] * p;
- g += filters[0][1] * p;
- b += filters[0][2] * p;
+ r = filters[0][0] * p;
+ g = filters[0][1] * p;
+ b = filters[0][2] * p;
p = col[pitch];
r += filters[1][0] * p;
@@ -275,7 +233,7 @@
col[0] = (FT_Byte)( r / 65536 );
col[pitch] = (FT_Byte)( g / 65536 );
- col[2 * pitch] = (FT_Byte)( b / 65536 );
+ col[pitch * 2] = (FT_Byte)( b / 65536 );
}
}
}
@@ -296,7 +254,6 @@
ft_memcpy( library->lcd_weights, weights, FT_LCD_FILTER_FIVE_TAPS );
library->lcd_filter_func = ft_lcd_filter_fir;
- library->lcd_extra = 2;
return FT_Err_Ok;
}
@@ -319,7 +276,6 @@
{
case FT_LCD_FILTER_NONE:
library->lcd_filter_func = NULL;
- library->lcd_extra = 0;
break;
case FT_LCD_FILTER_DEFAULT:
@@ -327,7 +283,6 @@
default_weights,
FT_LCD_FILTER_FIVE_TAPS );
library->lcd_filter_func = ft_lcd_filter_fir;
- library->lcd_extra = 2;
break;
case FT_LCD_FILTER_LIGHT:
@@ -335,7 +290,6 @@
light_weights,
FT_LCD_FILTER_FIVE_TAPS );
library->lcd_filter_func = ft_lcd_filter_fir;
- library->lcd_extra = 2;
break;
#ifdef USE_LEGACY
@@ -343,7 +297,6 @@
case FT_LCD_FILTER_LEGACY:
case FT_LCD_FILTER_LEGACY1:
library->lcd_filter_func = _ft_lcd_filter_legacy;
- library->lcd_extra = 0;
break;
#endif
diff --git a/thirdparty/freetype/src/base/ftmac.c b/thirdparty/freetype/src/base/ftmac.c
index 4b92066da3..4e76585e5f 100644
--- a/thirdparty/freetype/src/base/ftmac.c
+++ b/thirdparty/freetype/src/base/ftmac.c
@@ -1005,7 +1005,7 @@
/* accepts an FSRef instead of a path. */
/* */
/* This function is deprecated because Carbon data types (FSRef) */
- /* are not cross-platform, and thus not suitable for the freetype API. */
+ /* are not cross-platform, and thus not suitable for the FreeType API. */
FT_EXPORT_DEF( FT_Error )
FT_New_Face_From_FSRef( FT_Library library,
const FSRef* ref,
diff --git a/thirdparty/freetype/src/base/ftmm.c b/thirdparty/freetype/src/base/ftmm.c
index 2cb56a39be..43877ece45 100644
--- a/thirdparty/freetype/src/base/ftmm.c
+++ b/thirdparty/freetype/src/base/ftmm.c
@@ -158,7 +158,7 @@
/* check of `face' delayed to `ft_face_get_mm_service' */
- if ( !coords )
+ if ( num_coords && !coords )
return FT_THROW( Invalid_Argument );
error = ft_face_get_mm_service( face, &service );
@@ -194,7 +194,7 @@
/* check of `face' delayed to `ft_face_get_mm_service' */
- if ( !coords )
+ if ( num_coords && !coords )
return FT_THROW( Invalid_Argument );
error = ft_face_get_mm_service( face, &service_mm );
@@ -266,7 +266,7 @@
/* check of `face' delayed to `ft_face_get_mm_service' */
- if ( !coords )
+ if ( num_coords && !coords )
return FT_THROW( Invalid_Argument );
error = ft_face_get_mm_service( face, &service_mm );
@@ -313,7 +313,7 @@
/* check of `face' delayed to `ft_face_get_mm_service' */
- if ( !coords )
+ if ( num_coords && !coords )
return FT_THROW( Invalid_Argument );
error = ft_face_get_mm_service( face, &service_mm );
@@ -402,4 +402,28 @@
}
+ /* documentation is in ftmm.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Get_Var_Axis_Flags( FT_MM_Var* master,
+ FT_UInt axis_index,
+ FT_UInt* flags )
+ {
+ FT_UShort* axis_flags;
+
+
+ if ( !master || !flags )
+ return FT_THROW( Invalid_Argument );
+
+ if ( axis_index >= master->num_axis )
+ return FT_THROW( Invalid_Argument );
+
+ /* the axis flags array immediately follows the data of `master' */
+ axis_flags = (FT_UShort*)&( master[1] );
+ *flags = axis_flags[axis_index];
+
+ return FT_Err_Ok;
+ }
+
+
/* END */
diff --git a/thirdparty/freetype/src/base/ftobjs.c b/thirdparty/freetype/src/base/ftobjs.c
index 539116e85c..6db8136cfc 100644
--- a/thirdparty/freetype/src/base/ftobjs.c
+++ b/thirdparty/freetype/src/base/ftobjs.c
@@ -579,34 +579,42 @@
if ( vertical )
{
metrics->horiBearingX = FT_PIX_FLOOR( metrics->horiBearingX );
- metrics->horiBearingY = FT_PIX_CEIL ( metrics->horiBearingY );
+ metrics->horiBearingY = FT_PIX_CEIL_LONG( metrics->horiBearingY );
- right = FT_PIX_CEIL( metrics->vertBearingX + metrics->width );
- bottom = FT_PIX_CEIL( metrics->vertBearingY + metrics->height );
+ right = FT_PIX_CEIL_LONG( ADD_LONG( metrics->vertBearingX,
+ metrics->width ) );
+ bottom = FT_PIX_CEIL_LONG( ADD_LONG( metrics->vertBearingY,
+ metrics->height ) );
metrics->vertBearingX = FT_PIX_FLOOR( metrics->vertBearingX );
metrics->vertBearingY = FT_PIX_FLOOR( metrics->vertBearingY );
- metrics->width = right - metrics->vertBearingX;
- metrics->height = bottom - metrics->vertBearingY;
+ metrics->width = SUB_LONG( right,
+ metrics->vertBearingX );
+ metrics->height = SUB_LONG( bottom,
+ metrics->vertBearingY );
}
else
{
metrics->vertBearingX = FT_PIX_FLOOR( metrics->vertBearingX );
metrics->vertBearingY = FT_PIX_FLOOR( metrics->vertBearingY );
- right = FT_PIX_CEIL ( metrics->horiBearingX + metrics->width );
- bottom = FT_PIX_FLOOR( metrics->horiBearingY - metrics->height );
+ right = FT_PIX_CEIL_LONG( ADD_LONG( metrics->horiBearingX,
+ metrics->width ) );
+ bottom = FT_PIX_FLOOR( SUB_LONG( metrics->horiBearingY,
+ metrics->height ) );
metrics->horiBearingX = FT_PIX_FLOOR( metrics->horiBearingX );
- metrics->horiBearingY = FT_PIX_CEIL ( metrics->horiBearingY );
+ metrics->horiBearingY = FT_PIX_CEIL_LONG( metrics->horiBearingY );
- metrics->width = right - metrics->horiBearingX;
- metrics->height = metrics->horiBearingY - bottom;
+ metrics->width = SUB_LONG( right,
+ metrics->horiBearingX );
+ metrics->height = SUB_LONG( metrics->horiBearingY,
+ bottom );
}
- metrics->horiAdvance = FT_PIX_ROUND( metrics->horiAdvance );
- metrics->vertAdvance = FT_PIX_ROUND( metrics->vertAdvance );
+ metrics->horiAdvance = FT_PIX_ROUND_LONG( metrics->horiAdvance );
+ metrics->vertAdvance = FT_PIX_ROUND_LONG( metrics->vertAdvance );
}
#endif /* GRID_FIT_METRICS */
@@ -4549,7 +4557,7 @@
if ( !clazz )
return FT_THROW( Invalid_Argument );
- /* check freetype version */
+ /* check FreeType version */
if ( clazz->module_requires > FREETYPE_VER_FIXED )
return FT_THROW( Invalid_Version );
@@ -4973,10 +4981,6 @@
goto Fail;
#endif
- /* we don't use raster_pool anymore. */
- library->raster_pool_size = 0;
- library->raster_pool = NULL;
-
library->version_major = FREETYPE_MAJOR;
library->version_minor = FREETYPE_MINOR;
library->version_patch = FREETYPE_PATCH;
diff --git a/thirdparty/freetype/src/base/ftoutln.c b/thirdparty/freetype/src/base/ftoutln.c
index 464a066dcc..9ceb9cf1ba 100644
--- a/thirdparty/freetype/src/base/ftoutln.c
+++ b/thirdparty/freetype/src/base/ftoutln.c
@@ -1088,7 +1088,8 @@
v_cur.x = points[n].x >> xshift;
v_cur.y = points[n].y >> yshift;
- area += ( v_cur.y - v_prev.y ) * ( v_cur.x + v_prev.x );
+ area = ADD_LONG( area,
+ ( v_cur.y - v_prev.y ) * ( v_cur.x + v_prev.x ) );
v_prev = v_cur;
}
diff --git a/thirdparty/freetype/src/base/ftrfork.c b/thirdparty/freetype/src/base/ftrfork.c
index f7b81375dd..f5ad2874d8 100644
--- a/thirdparty/freetype/src/base/ftrfork.c
+++ b/thirdparty/freetype/src/base/ftrfork.c
@@ -271,7 +271,13 @@
if ( FT_STREAM_SKIP( 4 ) ) /* mbz */
goto Exit;
- if ( ref[j].res_id < 0 || temp < 0 )
+ /*
+ * According to Inside Macintosh: More Macintosh Toolbox,
+ * "Resource IDs" (1-46), there are some reserved IDs.
+ * However, FreeType2 is not a font synthesizer, no need
+ * to check the acceptable resource ID.
+ */
+ if ( temp < 0 )
{
error = FT_THROW( Invalid_Table );
goto Exit;
@@ -281,7 +287,7 @@
FT_TRACE3(( " [%d]:"
" resource_id=0x%04x, offset=0x%08x\n",
- j, ref[j].res_id, ref[j].offset ));
+ j, (FT_UShort)ref[j].res_id, ref[j].offset ));
}
if ( sort_by_res_id )
diff --git a/thirdparty/freetype/src/base/ftsynth.c b/thirdparty/freetype/src/base/ftsynth.c
index 66dae6037a..5cf386f48d 100644
--- a/thirdparty/freetype/src/base/ftsynth.c
+++ b/thirdparty/freetype/src/base/ftsynth.c
@@ -123,7 +123,7 @@
/*
* XXX: overflow check for 16-bit system, for compatibility
- * with FT_GlyphSlot_Embolden() since freetype-2.1.10.
+ * with FT_GlyphSlot_Embolden() since FreeType 2.1.10.
* unfortunately, this function return no informations
* about the cause of error.
*/
diff --git a/thirdparty/freetype/src/base/ftutil.c b/thirdparty/freetype/src/base/ftutil.c
index dccc209f4d..7bd5bee87c 100644
--- a/thirdparty/freetype/src/base/ftutil.c
+++ b/thirdparty/freetype/src/base/ftutil.c
@@ -135,7 +135,7 @@
ft_mem_free( memory, block );
block = NULL;
}
- else if ( new_count > FT_INT_MAX/item_size )
+ else if ( new_count > FT_INT_MAX / item_size )
{
error = FT_THROW( Array_Too_Large );
}
@@ -143,13 +143,15 @@
{
FT_ASSERT( !block );
- block = ft_mem_alloc( memory, new_count*item_size, &error );
+ block = memory->alloc( memory, new_count * item_size );
+ if ( block == NULL )
+ error = FT_THROW( Out_Of_Memory );
}
else
{
FT_Pointer block2;
- FT_Long cur_size = cur_count*item_size;
- FT_Long new_size = new_count*item_size;
+ FT_Long cur_size = cur_count * item_size;
+ FT_Long new_size = new_count * item_size;
block2 = memory->realloc( memory, cur_size, new_size, block );
diff --git a/thirdparty/freetype/src/bdf/bdfdrivr.c b/thirdparty/freetype/src/bdf/bdfdrivr.c
index a2242be014..fb77810007 100644
--- a/thirdparty/freetype/src/bdf/bdfdrivr.c
+++ b/thirdparty/freetype/src/bdf/bdfdrivr.c
@@ -373,7 +373,7 @@ THE SOFTWARE.
/* we have a bdf font: let's construct the face object */
face->bdffont = font;
- /* BDF could not have multiple face in single font file.
+ /* BDF cannot have multiple faces in a single font file.
* XXX: non-zero face_index is already invalid argument, but
* Type1, Type42 driver has a convention to return
* an invalid argument error when the font could be
@@ -437,46 +437,156 @@ THE SOFTWARE.
{
FT_Bitmap_Size* bsize = bdfface->available_sizes;
FT_Short resolution_x = 0, resolution_y = 0;
+ long value;
FT_ZERO( bsize );
+ /* sanity checks */
+ if ( font->font_ascent > 0x7FFF || font->font_ascent < -0x7FFF )
+ {
+ font->font_ascent = font->font_ascent < 0 ? -0x7FFF : 0x7FFF;
+ FT_TRACE0(( "BDF_Face_Init: clamping font ascent to value %d\n",
+ font->font_ascent ));
+ }
+ if ( font->font_descent > 0x7FFF || font->font_descent < -0x7FFF )
+ {
+ font->font_descent = font->font_descent < 0 ? -0x7FFF : 0x7FFF;
+ FT_TRACE0(( "BDF_Face_Init: clamping font descent to value %d\n",
+ font->font_descent ));
+ }
+
bsize->height = (FT_Short)( font->font_ascent + font->font_descent );
prop = bdf_get_font_property( font, "AVERAGE_WIDTH" );
if ( prop )
- bsize->width = (FT_Short)( ( prop->value.l + 5 ) / 10 );
+ {
+#ifdef FT_DEBUG_LEVEL_TRACE
+ if ( prop->value.l < 0 )
+ FT_TRACE0(( "BDF_Face_Init: negative average width\n" ));
+#endif
+ if ( prop->value.l > 0x7FFFL * 10 - 5 ||
+ prop->value.l < -( 0x7FFFL * 10 - 5 ) )
+ {
+ bsize->width = 0x7FFF;
+ FT_TRACE0(( "BDF_Face_Init: clamping average width to value %d\n",
+ bsize->width ));
+ }
+ else
+ bsize->width = FT_ABS( (FT_Short)( ( prop->value.l + 5 ) / 10 ) );
+ }
else
- bsize->width = (FT_Short)( bsize->height * 2/3 );
+ {
+ /* this is a heuristical value */
+ bsize->width = (FT_Short)FT_MulDiv( bsize->height, 2, 3 );
+ }
prop = bdf_get_font_property( font, "POINT_SIZE" );
if ( prop )
+ {
+#ifdef FT_DEBUG_LEVEL_TRACE
+ if ( prop->value.l < 0 )
+ FT_TRACE0(( "BDF_Face_Init: negative point size\n" ));
+#endif
/* convert from 722.7 decipoints to 72 points per inch */
- bsize->size =
- (FT_Pos)( ( prop->value.l * 64 * 7200 + 36135L ) / 72270L );
+ if ( prop->value.l > 0x504C2L || /* 0x7FFF * 72270/7200 */
+ prop->value.l < -0x504C2L )
+ {
+ bsize->size = 0x7FFF;
+ FT_TRACE0(( "BDF_Face_Init: clamping point size to value %d\n",
+ bsize->size ));
+ }
+ else
+ bsize->size = FT_MulDiv( FT_ABS( prop->value.l ),
+ 64 * 7200,
+ 72270L );
+ }
+ else if ( font->point_size )
+ {
+ if ( font->point_size > 0x7FFF )
+ {
+ bsize->size = 0x7FFF;
+ FT_TRACE0(( "BDF_Face_Init: clamping point size to value %d\n",
+ bsize->size ));
+ }
+ else
+ bsize->size = (FT_Pos)font->point_size << 6;
+ }
else
- bsize->size = bsize->width << 6;
+ {
+ /* this is a heuristical value */
+ bsize->size = bsize->width * 64;
+ }
prop = bdf_get_font_property( font, "PIXEL_SIZE" );
if ( prop )
- bsize->y_ppem = (FT_Short)prop->value.l << 6;
+ {
+#ifdef FT_DEBUG_LEVEL_TRACE
+ if ( prop->value.l < 0 )
+ FT_TRACE0(( "BDF_Face_Init: negative pixel size\n" ));
+#endif
+ if ( prop->value.l > 0x7FFF || prop->value.l < -0x7FFF )
+ {
+ bsize->y_ppem = 0x7FFF << 6;
+ FT_TRACE0(( "BDF_Face_Init: clamping pixel size to value %d\n",
+ bsize->y_ppem ));
+ }
+ else
+ bsize->y_ppem = FT_ABS( (FT_Short)prop->value.l ) << 6;
+ }
prop = bdf_get_font_property( font, "RESOLUTION_X" );
if ( prop )
- resolution_x = (FT_Short)prop->value.l;
+ value = prop->value.l;
+ else
+ value = (long)font->resolution_x;
+ if ( value )
+ {
+#ifdef FT_DEBUG_LEVEL_TRACE
+ if ( value < 0 )
+ FT_TRACE0(( "BDF_Face_Init: negative X resolution\n" ));
+#endif
+ if ( value > 0x7FFF || value < -0x7FFF )
+ {
+ resolution_x = 0x7FFF;
+ FT_TRACE0(( "BDF_Face_Init: clamping X resolution to value %d\n",
+ resolution_x ));
+ }
+ else
+ resolution_x = FT_ABS( (FT_Short)value );
+ }
prop = bdf_get_font_property( font, "RESOLUTION_Y" );
if ( prop )
- resolution_y = (FT_Short)prop->value.l;
+ value = prop->value.l;
+ else
+ value = (long)font->resolution_y;
+ if ( value )
+ {
+#ifdef FT_DEBUG_LEVEL_TRACE
+ if ( value < 0 )
+ FT_TRACE0(( "BDF_Face_Init: negative Y resolution\n" ));
+#endif
+ if ( value > 0x7FFF || value < -0x7FFF )
+ {
+ resolution_y = 0x7FFF;
+ FT_TRACE0(( "BDF_Face_Init: clamping Y resolution to value %d\n",
+ resolution_y ));
+ }
+ else
+ resolution_y = FT_ABS( (FT_Short)value );
+ }
if ( bsize->y_ppem == 0 )
{
bsize->y_ppem = bsize->size;
if ( resolution_y )
- bsize->y_ppem = bsize->y_ppem * resolution_y / 72;
+ bsize->y_ppem = FT_MulDiv( bsize->y_ppem, resolution_y, 72 );
}
if ( resolution_x && resolution_y )
- bsize->x_ppem = bsize->y_ppem * resolution_x / resolution_y;
+ bsize->x_ppem = FT_MulDiv( bsize->y_ppem,
+ resolution_x,
+ resolution_y );
else
bsize->x_ppem = bsize->y_ppem;
}
@@ -545,7 +655,11 @@ THE SOFTWARE.
if ( !ft_strcmp( s, "10646" ) ||
( !ft_strcmp( s, "8859" ) &&
!ft_strcmp( face->charset_encoding, "1" ) ) )
- unicode_charmap = 1;
+ unicode_charmap = 1;
+ /* another name for ASCII */
+ else if ( !ft_strcmp( s, "646.1991" ) &&
+ !ft_strcmp( face->charset_encoding, "IRV" ) )
+ unicode_charmap = 1;
}
{
@@ -566,12 +680,6 @@ THE SOFTWARE.
}
error = FT_CMap_New( &bdf_cmap_class, NULL, &charmap, NULL );
-
-#if 0
- /* Select default charmap */
- if ( bdfface->num_charmaps )
- bdfface->charmap = bdfface->charmaps[0];
-#endif
}
goto Exit;
diff --git a/thirdparty/freetype/src/bdf/bdflib.c b/thirdparty/freetype/src/bdf/bdflib.c
index 7fd95a7385..bf10887fd4 100644
--- a/thirdparty/freetype/src/bdf/bdflib.c
+++ b/thirdparty/freetype/src/bdf/bdflib.c
@@ -704,7 +704,15 @@
return 0;
for ( v = 0; sbitset( ddigits, *s ); s++ )
- v = v * 10 + a2i[(int)*s];
+ {
+ if ( v < ( ULONG_MAX - 9 ) / 10 )
+ v = v * 10 + a2i[(int)*s];
+ else
+ {
+ v = ULONG_MAX;
+ break;
+ }
+ }
return v;
}
@@ -729,7 +737,15 @@
}
for ( v = 0; sbitset( ddigits, *s ); s++ )
- v = v * 10 + a2i[(int)*s];
+ {
+ if ( v < ( LONG_MAX - 9 ) / 10 )
+ v = v * 10 + a2i[(int)*s];
+ else
+ {
+ v = LONG_MAX;
+ break;
+ }
+ }
return ( !neg ) ? v : -v;
}
@@ -746,7 +762,15 @@
return 0;
for ( v = 0; sbitset( ddigits, *s ); s++ )
- v = (unsigned short)( v * 10 + a2i[(int)*s] );
+ {
+ if ( v < ( USHRT_MAX - 9 ) / 10 )
+ v = (unsigned short)( v * 10 + a2i[(int)*s] );
+ else
+ {
+ v = USHRT_MAX;
+ break;
+ }
+ }
return v;
}
@@ -771,7 +795,15 @@
}
for ( v = 0; sbitset( ddigits, *s ); s++ )
- v = (short)( v * 10 + a2i[(int)*s] );
+ {
+ if ( v < ( SHRT_MAX - 9 ) / 10 )
+ v = (short)( v * 10 + a2i[(int)*s] );
+ else
+ {
+ v = SHRT_MAX;
+ break;
+ }
+ }
return (short)( ( !neg ) ? v : -v );
}
diff --git a/thirdparty/freetype/src/cache/ftcbasic.c b/thirdparty/freetype/src/cache/ftcbasic.c
index 289bd5c430..e804776ab4 100644
--- a/thirdparty/freetype/src/cache/ftcbasic.c
+++ b/thirdparty/freetype/src/cache/ftcbasic.c
@@ -304,10 +304,18 @@
if ( anode )
*anode = NULL;
- if ( (FT_ULong)( type->flags - FT_INT_MIN ) > FT_UINT_MAX )
+ /*
+ * Internal `FTC_BasicAttr->load_flags' is of type `FT_UInt',
+ * but public `FT_ImageType->flags' is of type `FT_Int32'.
+ *
+ * On 16bit systems, higher bits of type->flags cannot be handled.
+ */
+#if 0xFFFFFFFFUL > FT_UINT_MAX
+ if ( (type->flags & (FT_ULong)FT_UINT_MAX) )
FT_TRACE1(( "FTC_ImageCache_Lookup:"
" higher bits in load_flags 0x%x are dropped\n",
(FT_ULong)type->flags & ~((FT_ULong)FT_UINT_MAX) ));
+#endif
query.attrs.scaler.face_id = type->face_id;
query.attrs.scaler.width = type->width;
@@ -377,11 +385,18 @@
if ( anode )
*anode = NULL;
- /* `FT_Load_Glyph' and `FT_Load_Char' take FT_UInt flags */
+ /*
+ * Internal `FTC_BasicAttr->load_flags' is of type `FT_UInt',
+ * but public `FT_Face->face_flags' is of type `FT_Long'.
+ *
+ * On long > int systems, higher bits of load_flags cannot be handled.
+ */
+#if FT_ULONG_MAX > FT_UINT_MAX
if ( load_flags > FT_UINT_MAX )
FT_TRACE1(( "FTC_ImageCache_LookupScaler:"
" higher bits in load_flags 0x%x are dropped\n",
load_flags & ~((FT_ULong)FT_UINT_MAX) ));
+#endif
query.attrs.scaler = scaler[0];
query.attrs.load_flags = (FT_UInt)load_flags;
@@ -487,10 +502,18 @@
*ansbit = NULL;
- if ( (FT_ULong)( type->flags - FT_INT_MIN ) > FT_UINT_MAX )
+ /*
+ * Internal `FTC_BasicAttr->load_flags' is of type `FT_UInt',
+ * but public `FT_ImageType->flags' is of type `FT_Int32'.
+ *
+ * On 16bit systems, higher bits of type->flags cannot be handled.
+ */
+#if 0xFFFFFFFFUL > FT_UINT_MAX
+ if ( (type->flags & (FT_ULong)FT_UINT_MAX) )
FT_TRACE1(( "FTC_ImageCache_Lookup:"
" higher bits in load_flags 0x%x are dropped\n",
(FT_ULong)type->flags & ~((FT_ULong)FT_UINT_MAX) ));
+#endif
query.attrs.scaler.face_id = type->face_id;
query.attrs.scaler.width = type->width;
@@ -562,11 +585,18 @@
*ansbit = NULL;
- /* `FT_Load_Glyph' and `FT_Load_Char' take FT_UInt flags */
+ /*
+ * Internal `FTC_BasicAttr->load_flags' is of type `FT_UInt',
+ * but public `FT_Face->face_flags' is of type `FT_Long'.
+ *
+ * On long > int systems, higher bits of load_flags cannot be handled.
+ */
+#if FT_ULONG_MAX > FT_UINT_MAX
if ( load_flags > FT_UINT_MAX )
FT_TRACE1(( "FTC_ImageCache_LookupScaler:"
" higher bits in load_flags 0x%x are dropped\n",
load_flags & ~((FT_ULong)FT_UINT_MAX) ));
+#endif
query.attrs.scaler = scaler[0];
query.attrs.load_flags = (FT_UInt)load_flags;
diff --git a/thirdparty/freetype/src/cff/cf2blues.c b/thirdparty/freetype/src/cff/cf2blues.c
index 250f89e0df..c491f2f9e5 100644
--- a/thirdparty/freetype/src/cff/cf2blues.c
+++ b/thirdparty/freetype/src/cff/cf2blues.c
@@ -194,8 +194,8 @@
blues->zone[blues->count].csTopEdge =
cf2_blueToFixed( blueValues[i + 1] );
- zoneHeight = blues->zone[blues->count].csTopEdge -
- blues->zone[blues->count].csBottomEdge;
+ zoneHeight = SUB_INT32( blues->zone[blues->count].csTopEdge,
+ blues->zone[blues->count].csBottomEdge );
if ( zoneHeight < 0 )
{
@@ -243,8 +243,8 @@
blues->zone[blues->count].csTopEdge =
cf2_blueToFixed( otherBlues[i + 1] );
- zoneHeight = blues->zone[blues->count].csTopEdge -
- blues->zone[blues->count].csBottomEdge;
+ zoneHeight = SUB_INT32( blues->zone[blues->count].csTopEdge,
+ blues->zone[blues->count].csBottomEdge );
if ( zoneHeight < 0 )
{
@@ -301,7 +301,7 @@
/* top edge */
flatFamilyEdge = cf2_blueToFixed( familyOtherBlues[j + 1] );
- diff = cf2_fixedAbs( flatEdge - flatFamilyEdge );
+ diff = cf2_fixedAbs( SUB_INT32( flatEdge, flatFamilyEdge ) );
if ( diff < minDiff && diff < csUnitsPerPixel )
{
@@ -319,7 +319,7 @@
/* top edge */
flatFamilyEdge = cf2_blueToFixed( familyBlues[1] );
- diff = cf2_fixedAbs( flatEdge - flatFamilyEdge );
+ diff = cf2_fixedAbs( SUB_INT32( flatEdge, flatFamilyEdge ) );
if ( diff < minDiff && diff < csUnitsPerPixel )
blues->zone[i].csFlatEdge = flatFamilyEdge;
@@ -342,7 +342,7 @@
/* adjust edges of top zone upward by twice darkening amount */
flatFamilyEdge += 2 * font->darkenY; /* bottom edge */
- diff = cf2_fixedAbs( flatEdge - flatFamilyEdge );
+ diff = cf2_fixedAbs( SUB_INT32( flatEdge, flatFamilyEdge ) );
if ( diff < minDiff && diff < csUnitsPerPixel )
{
@@ -408,8 +408,8 @@
/* Note: constant changed from 0.5 to 0.6 to avoid a problem with */
/* 10ppem Arial */
- blues->boost = cf2_floatToFixed( .6 ) -
- FT_MulDiv( cf2_floatToFixed ( .6 ),
+ blues->boost = cf2_doubleToFixed( .6 ) -
+ FT_MulDiv( cf2_doubleToFixed ( .6 ),
blues->scale,
blues->blueScale );
if ( blues->boost > 0x7FFF )
@@ -489,17 +489,18 @@
if ( blues->zone[i].bottomZone &&
cf2_hint_isBottom( bottomHintEdge ) )
{
- if ( ( blues->zone[i].csBottomEdge - csFuzz ) <=
- bottomHintEdge->csCoord &&
+ if ( SUB_INT32( blues->zone[i].csBottomEdge, csFuzz ) <=
+ bottomHintEdge->csCoord &&
bottomHintEdge->csCoord <=
- ( blues->zone[i].csTopEdge + csFuzz ) )
+ ADD_INT32( blues->zone[i].csTopEdge, csFuzz ) )
{
/* bottom edge captured by bottom zone */
if ( blues->suppressOvershoot )
dsNew = blues->zone[i].dsFlatEdge;
- else if ( ( blues->zone[i].csTopEdge - bottomHintEdge->csCoord ) >=
+ else if ( SUB_INT32( blues->zone[i].csTopEdge,
+ bottomHintEdge->csCoord ) >=
blues->blueShift )
{
/* guarantee minimum of 1 pixel overshoot */
@@ -514,7 +515,7 @@
dsNew = cf2_fixedRound( bottomHintEdge->dsCoord );
}
- dsMove = dsNew - bottomHintEdge->dsCoord;
+ dsMove = SUB_INT32( dsNew, bottomHintEdge->dsCoord );
captured = TRUE;
break;
@@ -523,17 +524,18 @@
if ( !blues->zone[i].bottomZone && cf2_hint_isTop( topHintEdge ) )
{
- if ( ( blues->zone[i].csBottomEdge - csFuzz ) <=
- topHintEdge->csCoord &&
+ if ( SUB_INT32( blues->zone[i].csBottomEdge, csFuzz ) <=
+ topHintEdge->csCoord &&
topHintEdge->csCoord <=
- ( blues->zone[i].csTopEdge + csFuzz ) )
+ ADD_INT32( blues->zone[i].csTopEdge, csFuzz ) )
{
/* top edge captured by top zone */
if ( blues->suppressOvershoot )
dsNew = blues->zone[i].dsFlatEdge;
- else if ( ( topHintEdge->csCoord - blues->zone[i].csBottomEdge ) >=
+ else if ( SUB_INT32( topHintEdge->csCoord,
+ blues->zone[i].csBottomEdge ) >=
blues->blueShift )
{
/* guarantee minimum of 1 pixel overshoot */
@@ -548,7 +550,7 @@
dsNew = cf2_fixedRound( topHintEdge->dsCoord );
}
- dsMove = dsNew - topHintEdge->dsCoord;
+ dsMove = SUB_INT32( dsNew, topHintEdge->dsCoord );
captured = TRUE;
break;
@@ -561,13 +563,14 @@
/* move both edges and flag them `locked' */
if ( cf2_hint_isValid( bottomHintEdge ) )
{
- bottomHintEdge->dsCoord += dsMove;
+ bottomHintEdge->dsCoord = ADD_INT32( bottomHintEdge->dsCoord,
+ dsMove );
cf2_hint_lock( bottomHintEdge );
}
if ( cf2_hint_isValid( topHintEdge ) )
{
- topHintEdge->dsCoord += dsMove;
+ topHintEdge->dsCoord = ADD_INT32( topHintEdge->dsCoord, dsMove );
cf2_hint_lock( topHintEdge );
}
}
diff --git a/thirdparty/freetype/src/cff/cf2blues.h b/thirdparty/freetype/src/cff/cf2blues.h
index 96fb60f38d..a6bcd9de57 100644
--- a/thirdparty/freetype/src/cff/cf2blues.h
+++ b/thirdparty/freetype/src/cff/cf2blues.h
@@ -111,7 +111,7 @@ FT_BEGIN_HEADER
* Constant used for hint adjustment and for synthetic em box hint
* placement.
*/
-#define CF2_MIN_COUNTER cf2_floatToFixed( 0.5 )
+#define CF2_MIN_COUNTER cf2_doubleToFixed( 0.5 )
/* shared typedef is in cf2glue.h */
diff --git a/thirdparty/freetype/src/cff/cf2fixed.h b/thirdparty/freetype/src/cff/cf2fixed.h
index 2e4b5032fa..a041184bda 100644
--- a/thirdparty/freetype/src/cff/cf2fixed.h
+++ b/thirdparty/freetype/src/cff/cf2fixed.h
@@ -63,10 +63,10 @@ FT_BEGIN_HEADER
( (FT_Short)( ( (FT_UInt32)(x) + 0x8000U ) >> 16 ) )
#define cf2_fixedRound( x ) \
( (CF2_Fixed)( ( (FT_UInt32)(x) + 0x8000U ) & 0xFFFF0000UL ) )
-#define cf2_floatToFixed( f ) \
+#define cf2_doubleToFixed( f ) \
( (CF2_Fixed)( (f) * 65536.0 + 0.5 ) )
#define cf2_fixedAbs( x ) \
- ( (x) < 0 ? -(x) : (x) )
+ ( (x) < 0 ? NEG_INT32( x ) : (x) )
#define cf2_fixedFloor( x ) \
( (CF2_Fixed)( (FT_UInt32)(x) & 0xFFFF0000UL ) )
#define cf2_fixedFraction( x ) \
diff --git a/thirdparty/freetype/src/cff/cf2font.c b/thirdparty/freetype/src/cff/cf2font.c
index a86e3619b4..4ac71a8d71 100644
--- a/thirdparty/freetype/src/cff/cf2font.c
+++ b/thirdparty/freetype/src/cff/cf2font.c
@@ -117,7 +117,7 @@
return;
/* protect against range problems and divide by zero */
- if ( emRatio < cf2_floatToFixed( .01 ) )
+ if ( emRatio < cf2_doubleToFixed( .01 ) )
return;
if ( stemDarkened )
@@ -447,7 +447,7 @@
/* choose a constant for StdHW that depends on font contrast */
stdHW = cf2_getStdHW( decoder );
- if ( stdHW > 0 && font->stdVW > 2 * stdHW )
+ if ( stdHW > 0 && font->stdVW > MUL_INT32( 2, stdHW ) )
font->stdHW = FT_DivFix( cf2_intToFixed( 75 ), emRatio );
else
{
diff --git a/thirdparty/freetype/src/cff/cf2ft.c b/thirdparty/freetype/src/cff/cf2ft.c
index eb8472f119..c6c00d1623 100644
--- a/thirdparty/freetype/src/cff/cf2ft.c
+++ b/thirdparty/freetype/src/cff/cf2ft.c
@@ -267,8 +267,8 @@
if ( *hinted )
{
- *x_scale = ( decoder->builder.glyph->x_scale + 32 ) / 64;
- *y_scale = ( decoder->builder.glyph->y_scale + 32 ) / 64;
+ *x_scale = ADD_INT32( decoder->builder.glyph->x_scale, 32 ) / 64;
+ *y_scale = ADD_INT32( decoder->builder.glyph->y_scale, 32 ) / 64;
}
else
{
diff --git a/thirdparty/freetype/src/cff/cf2hints.c b/thirdparty/freetype/src/cff/cf2hints.c
index c8f7dfeba6..656eb2cff1 100644
--- a/thirdparty/freetype/src/cff/cf2hints.c
+++ b/thirdparty/freetype/src/cff/cf2hints.c
@@ -74,8 +74,8 @@
/* cross product of pt1 position from origin with pt2 position from */
/* pt1; we reduce the precision so that the result fits into 32 bits */
- return ( x1 >> 16 ) * ( ( y2 - y1 ) >> 16 ) -
- ( y1 >> 16 ) * ( ( x2 - x1 ) >> 16 );
+ return ( x1 >> 16 ) * ( SUB_INT32( y2, y1 ) >> 16 ) -
+ ( y1 >> 16 ) * ( SUB_INT32( x2, x1 ) >> 16 );
}
@@ -105,7 +105,7 @@
stemHintArray,
indexStemHint );
- width = stemHint->max - stemHint->min;
+ width = SUB_INT32( stemHint->max, stemHint->min );
if ( width == cf2_intToFixed( -21 ) )
{
@@ -185,11 +185,11 @@
/* darkening. Bottoms are not changed; tops are incremented by twice */
/* `darkenY'. */
if ( cf2_hint_isTop( hint ) )
- hint->csCoord += 2 * font->darkenY;
+ hint->csCoord = ADD_INT32( hint->csCoord, 2 * font->darkenY );
- hint->csCoord += hintOrigin;
- hint->scale = scale;
- hint->index = indexStemHint; /* index in original stem hint array */
+ hint->csCoord = ADD_INT32( hint->csCoord, hintOrigin );
+ hint->scale = scale;
+ hint->index = indexStemHint; /* index in original stem hint array */
/* if original stem hint has been used, use the same position */
if ( hint->flags != 0 && stemHint->used )
@@ -314,6 +314,7 @@
/* start linear search from last hit */
CF2_UInt i = hintmap->lastIndex;
+
FT_ASSERT( hintmap->lastIndex < CF2_MAX_HINT_EDGES );
/* search up */
@@ -330,9 +331,10 @@
if ( i == 0 && csCoord < hintmap->edge[0].csCoord )
{
/* special case for points below first edge: use uniform scale */
- return FT_MulFix( csCoord - hintmap->edge[0].csCoord,
- hintmap->scale ) +
- hintmap->edge[0].dsCoord;
+ return ADD_INT32( FT_MulFix( SUB_INT32( csCoord,
+ hintmap->edge[0].csCoord ),
+ hintmap->scale ),
+ hintmap->edge[0].dsCoord );
}
else
{
@@ -340,9 +342,10 @@
* Note: entries with duplicate csCoord are allowed.
* Use edge[i], the highest entry where csCoord >= entry[i].csCoord
*/
- return FT_MulFix( csCoord - hintmap->edge[i].csCoord,
- hintmap->edge[i].scale ) +
- hintmap->edge[i].dsCoord;
+ return ADD_INT32( FT_MulFix( SUB_INT32( csCoord,
+ hintmap->edge[i].csCoord ),
+ hintmap->edge[i].scale ),
+ hintmap->edge[i].dsCoord );
}
}
}
@@ -437,14 +440,16 @@
/* is there room to move up? */
/* there is if we are at top of array or the next edge is at or */
/* beyond proposed move up? */
- if ( j >= hintmap->count - 1 ||
+ if ( j >= hintmap->count - 1 ||
hintmap->edge[j + 1].dsCoord >=
- hintmap->edge[j].dsCoord + moveUp + upMinCounter )
+ ADD_INT32( hintmap->edge[j].dsCoord,
+ moveUp + upMinCounter ) )
{
/* there is room to move up; is there also room to move down? */
- if ( i == 0 ||
+ if ( i == 0 ||
hintmap->edge[i - 1].dsCoord <=
- hintmap->edge[i].dsCoord + moveDown - downMinCounter )
+ ADD_INT32( hintmap->edge[i].dsCoord,
+ moveDown - downMinCounter ) )
{
/* move smaller absolute amount */
move = ( -moveDown < moveUp ) ? moveDown : moveUp; /* optimum */
@@ -455,9 +460,10 @@
else
{
/* is there room to move down? */
- if ( i == 0 ||
+ if ( i == 0 ||
hintmap->edge[i - 1].dsCoord <=
- hintmap->edge[i].dsCoord + moveDown - downMinCounter )
+ ADD_INT32( hintmap->edge[i].dsCoord,
+ moveDown - downMinCounter ) )
{
move = moveDown;
/* true if non-optimum move */
@@ -491,9 +497,11 @@
}
/* move the edge(s) */
- hintmap->edge[i].dsCoord += move;
+ hintmap->edge[i].dsCoord = ADD_INT32( hintmap->edge[i].dsCoord,
+ move );
if ( isPair )
- hintmap->edge[j].dsCoord += move;
+ hintmap->edge[j].dsCoord = ADD_INT32( hintmap->edge[j].dsCoord,
+ move );
}
/* assert there are no overlaps in device space */
@@ -507,18 +515,20 @@
{
if ( hintmap->edge[i].csCoord != hintmap->edge[i - 1].csCoord )
hintmap->edge[i - 1].scale =
- FT_DivFix(
- hintmap->edge[i].dsCoord - hintmap->edge[i - 1].dsCoord,
- hintmap->edge[i].csCoord - hintmap->edge[i - 1].csCoord );
+ FT_DivFix( SUB_INT32( hintmap->edge[i].dsCoord,
+ hintmap->edge[i - 1].dsCoord ),
+ SUB_INT32( hintmap->edge[i].csCoord,
+ hintmap->edge[i - 1].csCoord ) );
}
if ( isPair )
{
if ( hintmap->edge[j].csCoord != hintmap->edge[j - 1].csCoord )
hintmap->edge[j - 1].scale =
- FT_DivFix(
- hintmap->edge[j].dsCoord - hintmap->edge[j - 1].dsCoord,
- hintmap->edge[j].csCoord - hintmap->edge[j - 1].csCoord );
+ FT_DivFix( SUB_INT32( hintmap->edge[j].dsCoord,
+ hintmap->edge[j - 1].dsCoord ),
+ SUB_INT32( hintmap->edge[j].csCoord,
+ hintmap->edge[j - 1].csCoord ) );
i += 1; /* skip upper edge on next loop */
}
@@ -539,15 +549,18 @@
/* is there room to move up? */
if ( hintmap->edge[j + 1].dsCoord >=
- hintmap->edge[j].dsCoord + hintMove->moveUp + CF2_MIN_COUNTER )
+ ADD_INT32( hintmap->edge[j].dsCoord,
+ hintMove->moveUp + CF2_MIN_COUNTER ) )
{
/* there is more room now, move edge up */
- hintmap->edge[j].dsCoord += hintMove->moveUp;
+ hintmap->edge[j].dsCoord = ADD_INT32( hintmap->edge[j].dsCoord,
+ hintMove->moveUp );
if ( cf2_hint_isPair( &hintmap->edge[j] ) )
{
FT_ASSERT( j > 0 );
- hintmap->edge[j - 1].dsCoord += hintMove->moveUp;
+ hintmap->edge[j - 1].dsCoord =
+ ADD_INT32( hintmap->edge[j - 1].dsCoord, hintMove->moveUp );
}
}
}
@@ -635,18 +648,19 @@
{
/* Use hint map to position the center of stem, and nominal scale */
/* to position the two edges. This preserves the stem width. */
- CF2_Fixed midpoint = cf2_hintmap_map(
- hintmap->initialHintMap,
- ( secondHintEdge->csCoord +
- firstHintEdge->csCoord ) / 2 );
- CF2_Fixed halfWidth = FT_MulFix(
- ( secondHintEdge->csCoord -
- firstHintEdge->csCoord ) / 2,
- hintmap->scale );
-
-
- firstHintEdge->dsCoord = midpoint - halfWidth;
- secondHintEdge->dsCoord = midpoint + halfWidth;
+ CF2_Fixed midpoint =
+ cf2_hintmap_map(
+ hintmap->initialHintMap,
+ ADD_INT32( secondHintEdge->csCoord,
+ firstHintEdge->csCoord ) / 2 );
+ CF2_Fixed halfWidth =
+ FT_MulFix( SUB_INT32( secondHintEdge->csCoord,
+ firstHintEdge->csCoord ) / 2,
+ hintmap->scale );
+
+
+ firstHintEdge->dsCoord = SUB_INT32( midpoint, halfWidth );
+ secondHintEdge->dsCoord = ADD_INT32( midpoint, halfWidth );
}
else
firstHintEdge->dsCoord = cf2_hintmap_map( hintmap->initialHintMap,
@@ -715,7 +729,7 @@
/* insert first edge */
hintmap->edge[indexInsert] = *firstHintEdge; /* copy struct */
- hintmap->count += 1;
+ hintmap->count += 1;
if ( isPair )
{
@@ -781,7 +795,7 @@
cf2_arrstack_size( hStemHintArray ) +
cf2_arrstack_size( vStemHintArray ) );
if ( !cf2_hintmask_isValid( hintMask ) )
- return; /* too many stem hints */
+ return; /* too many stem hints */
}
/* begin by clearing the map */
@@ -797,7 +811,7 @@
/* Defense-in-depth. Should never return here. */
if ( bitCount > hintMask->bitCount )
- return;
+ return;
/* synthetic embox hints get highest priority */
if ( font->blues.doEmBoxHints )
@@ -1063,7 +1077,7 @@
cf2_fixedAbs( glyphpath->yOffset ) );
/* .1 character space unit */
- glyphpath->snapThreshold = cf2_floatToFixed( 0.1f );
+ glyphpath->snapThreshold = cf2_doubleToFixed( 0.1 );
glyphpath->moveIsPending = TRUE;
glyphpath->pathIsOpen = FALSE;
@@ -1095,16 +1109,20 @@
FT_Vector pt; /* hinted point in upright DS */
- pt.x = FT_MulFix( glyphpath->scaleX, x ) +
- FT_MulFix( glyphpath->scaleC, y );
+ pt.x = ADD_INT32( FT_MulFix( glyphpath->scaleX, x ),
+ FT_MulFix( glyphpath->scaleC, y ) );
pt.y = cf2_hintmap_map( hintmap, y );
- ppt->x = FT_MulFix( glyphpath->font->outerTransform.a, pt.x ) +
- FT_MulFix( glyphpath->font->outerTransform.c, pt.y ) +
- glyphpath->fractionalTranslation.x;
- ppt->y = FT_MulFix( glyphpath->font->outerTransform.b, pt.x ) +
- FT_MulFix( glyphpath->font->outerTransform.d, pt.y ) +
- glyphpath->fractionalTranslation.y;
+ ppt->x = ADD_INT32(
+ FT_MulFix( glyphpath->font->outerTransform.a, pt.x ),
+ ADD_INT32(
+ FT_MulFix( glyphpath->font->outerTransform.c, pt.y ),
+ glyphpath->fractionalTranslation.x ) );
+ ppt->y = ADD_INT32(
+ FT_MulFix( glyphpath->font->outerTransform.b, pt.x ),
+ ADD_INT32(
+ FT_MulFix( glyphpath->font->outerTransform.d, pt.y ),
+ glyphpath->fractionalTranslation.y ) );
}
@@ -1154,12 +1172,12 @@
CF2_Fixed denominator, s;
- u.x = CF2_CS_SCALE( u2->x - u1->x );
- u.y = CF2_CS_SCALE( u2->y - u1->y );
- v.x = CF2_CS_SCALE( v2->x - v1->x );
- v.y = CF2_CS_SCALE( v2->y - v1->y );
- w.x = CF2_CS_SCALE( v1->x - u1->x );
- w.y = CF2_CS_SCALE( v1->y - u1->y );
+ u.x = CF2_CS_SCALE( SUB_INT32( u2->x, u1->x ) );
+ u.y = CF2_CS_SCALE( SUB_INT32( u2->y, u1->y ) );
+ v.x = CF2_CS_SCALE( SUB_INT32( v2->x, v1->x ) );
+ v.y = CF2_CS_SCALE( SUB_INT32( v2->y, v1->y ) );
+ w.x = CF2_CS_SCALE( SUB_INT32( v1->x, u1->x ) );
+ w.y = CF2_CS_SCALE( SUB_INT32( v1->y, u1->y ) );
denominator = cf2_perp( u, v );
@@ -1168,8 +1186,11 @@
s = FT_DivFix( cf2_perp( w, v ), denominator );
- intersection->x = u1->x + FT_MulFix( s, u2->x - u1->x );
- intersection->y = u1->y + FT_MulFix( s, u2->y - u1->y );
+ intersection->x = ADD_INT32( u1->x,
+ FT_MulFix( s, SUB_INT32( u2->x, u1->x ) ) );
+ intersection->y = ADD_INT32( u1->y,
+ FT_MulFix( s, SUB_INT32( u2->y, u1->y ) ) );
+
/*
* Special case snapping for horizontal and vertical lines.
@@ -1180,25 +1201,29 @@
*
*/
- if ( u1->x == u2->x &&
- cf2_fixedAbs( intersection->x - u1->x ) < glyphpath->snapThreshold )
+ if ( u1->x == u2->x &&
+ cf2_fixedAbs( SUB_INT32( intersection->x,
+ u1->x ) ) < glyphpath->snapThreshold )
intersection->x = u1->x;
- if ( u1->y == u2->y &&
- cf2_fixedAbs( intersection->y - u1->y ) < glyphpath->snapThreshold )
+ if ( u1->y == u2->y &&
+ cf2_fixedAbs( SUB_INT32( intersection->y,
+ u1->y ) ) < glyphpath->snapThreshold )
intersection->y = u1->y;
- if ( v1->x == v2->x &&
- cf2_fixedAbs( intersection->x - v1->x ) < glyphpath->snapThreshold )
+ if ( v1->x == v2->x &&
+ cf2_fixedAbs( SUB_INT32( intersection->x,
+ v1->x ) ) < glyphpath->snapThreshold )
intersection->x = v1->x;
- if ( v1->y == v2->y &&
- cf2_fixedAbs( intersection->y - v1->y ) < glyphpath->snapThreshold )
+ if ( v1->y == v2->y &&
+ cf2_fixedAbs( SUB_INT32( intersection->y,
+ v1->y ) ) < glyphpath->snapThreshold )
intersection->y = v1->y;
/* limit the intersection distance from midpoint of u2 and v1 */
- if ( cf2_fixedAbs( intersection->x - ( u2->x + v1->x ) / 2 ) >
- glyphpath->miterLimit ||
- cf2_fixedAbs( intersection->y - ( u2->y + v1->y ) / 2 ) >
- glyphpath->miterLimit )
+ if ( cf2_fixedAbs( intersection->x - ADD_INT32( u2->x, v1->x ) / 2 ) >
+ glyphpath->miterLimit ||
+ cf2_fixedAbs( intersection->y - ADD_INT32( u2->y, v1->y ) / 2 ) >
+ glyphpath->miterLimit )
return FALSE;
return TRUE;
@@ -1446,16 +1471,16 @@
CF2_Fixed* x,
CF2_Fixed* y )
{
- CF2_Fixed dx = x2 - x1;
- CF2_Fixed dy = y2 - y1;
+ CF2_Fixed dx = SUB_INT32( x2, x1 );
+ CF2_Fixed dy = SUB_INT32( y2, y1 );
/* note: negative offsets don't work here; negate deltas to change */
/* quadrants, below */
if ( glyphpath->font->reverseWinding )
{
- dx = -dx;
- dy = -dy;
+ dx = NEG_INT32( dx );
+ dy = NEG_INT32( dy );
}
*x = *y = 0;
@@ -1464,8 +1489,9 @@
return;
/* add momentum for this path element */
- glyphpath->callbacks->windingMomentum +=
- cf2_getWindingMomentum( x1, y1, x2, y2 );
+ glyphpath->callbacks->windingMomentum =
+ ADD_INT32( glyphpath->callbacks->windingMomentum,
+ cf2_getWindingMomentum( x1, y1, x2, y2 ) );
/* note: allow mixed integer and fixed multiplication here */
if ( dx >= 0 )
@@ -1474,13 +1500,13 @@
{
/* first quadrant, +x +y */
- if ( dx > 2 * dy )
+ if ( dx > MUL_INT32( 2, dy ) )
{
/* +x */
*x = 0;
*y = 0;
}
- else if ( dy > 2 * dx )
+ else if ( dy > MUL_INT32( 2, dx ) )
{
/* +y */
*x = glyphpath->xOffset;
@@ -1489,9 +1515,9 @@
else
{
/* +x +y */
- *x = FT_MulFix( cf2_floatToFixed( 0.7 ),
+ *x = FT_MulFix( cf2_doubleToFixed( 0.7 ),
glyphpath->xOffset );
- *y = FT_MulFix( cf2_floatToFixed( 1.0 - 0.7 ),
+ *y = FT_MulFix( cf2_doubleToFixed( 1.0 - 0.7 ),
glyphpath->yOffset );
}
}
@@ -1499,24 +1525,24 @@
{
/* fourth quadrant, +x -y */
- if ( dx > -2 * dy )
+ if ( dx > MUL_INT32( -2, dy ) )
{
/* +x */
*x = 0;
*y = 0;
}
- else if ( -dy > 2 * dx )
+ else if ( NEG_INT32( dy ) > MUL_INT32( 2, dx ) )
{
/* -y */
- *x = -glyphpath->xOffset;
+ *x = NEG_INT32( glyphpath->xOffset );
*y = glyphpath->yOffset;
}
else
{
/* +x -y */
- *x = FT_MulFix( cf2_floatToFixed( -0.7 ),
+ *x = FT_MulFix( cf2_doubleToFixed( -0.7 ),
glyphpath->xOffset );
- *y = FT_MulFix( cf2_floatToFixed( 1.0 - 0.7 ),
+ *y = FT_MulFix( cf2_doubleToFixed( 1.0 - 0.7 ),
glyphpath->yOffset );
}
}
@@ -1527,13 +1553,13 @@
{
/* second quadrant, -x +y */
- if ( -dx > 2 * dy )
+ if ( NEG_INT32( dx ) > MUL_INT32( 2, dy ) )
{
/* -x */
*x = 0;
- *y = 2 * glyphpath->yOffset;
+ *y = MUL_INT32( 2, glyphpath->yOffset );
}
- else if ( dy > -2 * dx )
+ else if ( dy > MUL_INT32( -2, dx ) )
{
/* +y */
*x = glyphpath->xOffset;
@@ -1542,9 +1568,9 @@
else
{
/* -x +y */
- *x = FT_MulFix( cf2_floatToFixed( 0.7 ),
+ *x = FT_MulFix( cf2_doubleToFixed( 0.7 ),
glyphpath->xOffset );
- *y = FT_MulFix( cf2_floatToFixed( 1.0 + 0.7 ),
+ *y = FT_MulFix( cf2_doubleToFixed( 1.0 + 0.7 ),
glyphpath->yOffset );
}
}
@@ -1552,24 +1578,24 @@
{
/* third quadrant, -x -y */
- if ( -dx > -2 * dy )
+ if ( NEG_INT32( dx ) > MUL_INT32( -2, dy ) )
{
/* -x */
*x = 0;
- *y = 2 * glyphpath->yOffset;
+ *y = MUL_INT32( 2, glyphpath->yOffset );
}
- else if ( -dy > -2 * dx )
+ else if ( NEG_INT32( dy ) > MUL_INT32( -2, dx ) )
{
/* -y */
- *x = -glyphpath->xOffset;
+ *x = NEG_INT32( glyphpath->xOffset );
*y = glyphpath->yOffset;
}
else
{
/* -x -y */
- *x = FT_MulFix( cf2_floatToFixed( -0.7 ),
+ *x = FT_MulFix( cf2_doubleToFixed( -0.7 ),
glyphpath->xOffset );
- *y = FT_MulFix( cf2_floatToFixed( 1.0 + 0.7 ),
+ *y = FT_MulFix( cf2_doubleToFixed( 1.0 + 0.7 ),
glyphpath->yOffset );
}
}
@@ -1675,10 +1701,10 @@
&yOffset );
/* construct offset points */
- P0.x = glyphpath->currentCS.x + xOffset;
- P0.y = glyphpath->currentCS.y + yOffset;
- P1.x = x + xOffset;
- P1.y = y + yOffset;
+ P0.x = ADD_INT32( glyphpath->currentCS.x, xOffset );
+ P0.y = ADD_INT32( glyphpath->currentCS.y, yOffset );
+ P1.x = ADD_INT32( x, xOffset );
+ P1.y = ADD_INT32( y, yOffset );
if ( glyphpath->moveIsPending )
{
@@ -1753,19 +1779,20 @@
&yOffset3 );
/* add momentum from the middle segment */
- glyphpath->callbacks->windingMomentum +=
- cf2_getWindingMomentum( x1, y1, x2, y2 );
+ glyphpath->callbacks->windingMomentum =
+ ADD_INT32( glyphpath->callbacks->windingMomentum,
+ cf2_getWindingMomentum( x1, y1, x2, y2 ) );
/* construct offset points */
- P0.x = glyphpath->currentCS.x + xOffset1;
- P0.y = glyphpath->currentCS.y + yOffset1;
- P1.x = x1 + xOffset1;
- P1.y = y1 + yOffset1;
+ P0.x = ADD_INT32( glyphpath->currentCS.x, xOffset1 );
+ P0.y = ADD_INT32( glyphpath->currentCS.y, yOffset1 );
+ P1.x = ADD_INT32( x1, xOffset1 );
+ P1.y = ADD_INT32( y1, yOffset1 );
/* note: preserve angle of final segment by using offset3 at both ends */
- P2.x = x2 + xOffset3;
- P2.y = y2 + yOffset3;
- P3.x = x3 + xOffset3;
- P3.y = y3 + yOffset3;
+ P2.x = ADD_INT32( x2, xOffset3 );
+ P2.y = ADD_INT32( y2, yOffset3 );
+ P3.x = ADD_INT32( x3, xOffset3 );
+ P3.y = ADD_INT32( y3, yOffset3 );
if ( glyphpath->moveIsPending )
{
diff --git a/thirdparty/freetype/src/cff/cf2intrp.c b/thirdparty/freetype/src/cff/cf2intrp.c
index 40bd9059a1..a816280748 100644
--- a/thirdparty/freetype/src/cff/cf2intrp.c
+++ b/thirdparty/freetype/src/cff/cf2intrp.c
@@ -304,10 +304,12 @@
CF2_StemHintRec stemhint;
- stemhint.min =
- position += cf2_stack_getReal( opStack, i );
- stemhint.max =
- position += cf2_stack_getReal( opStack, i + 1 );
+ stemhint.min =
+ position = ADD_INT32( position,
+ cf2_stack_getReal( opStack, i ) );
+ stemhint.max =
+ position = ADD_INT32( position,
+ cf2_stack_getReal( opStack, i + 1 ) );
stemhint.used = FALSE;
stemhint.maxDS =
@@ -348,7 +350,8 @@
{
vals[i + 2] = vals[i];
if ( readFromStack[i] )
- vals[i + 2] += cf2_stack_getReal( opStack, idx++ );
+ vals[i + 2] = ADD_INT32( vals[i + 2], cf2_stack_getReal( opStack,
+ idx++ ) );
}
if ( isHFlex )
@@ -356,31 +359,34 @@
if ( doConditionalLastRead )
{
- FT_Bool lastIsX = (FT_Bool)( cf2_fixedAbs( vals[10] - *curX ) >
- cf2_fixedAbs( vals[11] - *curY ) );
+ FT_Bool lastIsX = (FT_Bool)(
+ cf2_fixedAbs( SUB_INT32( vals[10], *curX ) ) >
+ cf2_fixedAbs( SUB_INT32( vals[11], *curY ) ) );
CF2_Fixed lastVal = cf2_stack_getReal( opStack, idx );
if ( lastIsX )
{
- vals[12] = vals[10] + lastVal;
+ vals[12] = ADD_INT32( vals[10], lastVal );
vals[13] = *curY;
}
else
{
vals[12] = *curX;
- vals[13] = vals[11] + lastVal;
+ vals[13] = ADD_INT32( vals[11], lastVal );
}
}
else
{
if ( readFromStack[10] )
- vals[12] = vals[10] + cf2_stack_getReal( opStack, idx++ );
+ vals[12] = ADD_INT32( vals[10],
+ cf2_stack_getReal( opStack, idx++ ) );
else
vals[12] = *curX;
if ( readFromStack[11] )
- vals[13] = vals[11] + cf2_stack_getReal( opStack, idx );
+ vals[13] = ADD_INT32( vals[11],
+ cf2_stack_getReal( opStack, idx ) );
else
vals[13] = *curY;
}
@@ -426,7 +432,10 @@
for ( j = 1; j < blend->lenBV; j++ )
- sum += FT_MulFix( *weight++, cf2_stack_getReal( opStack, delta++ ) );
+ sum = ADD_INT32( sum,
+ FT_MulFix( *weight++,
+ cf2_stack_getReal( opStack,
+ delta++ ) ) );
/* store blended result */
cf2_stack_setReal( opStack, i + base, sum );
@@ -759,7 +768,8 @@
FT_TRACE4(( " vmoveto\n" ));
if ( cf2_stack_count( opStack ) > 1 && !haveWidth )
- *width = cf2_stack_getReal( opStack, 0 ) + nominalWidthX;
+ *width = ADD_INT32( cf2_stack_getReal( opStack, 0 ),
+ nominalWidthX );
/* width is defined or default after this */
haveWidth = TRUE;
@@ -767,7 +777,7 @@
if ( font->decoder->width_only )
goto exit;
- curY += cf2_stack_popFixed( opStack );
+ curY = ADD_INT32( curY, cf2_stack_popFixed( opStack ) );
cf2_glyphpath_moveTo( &glyphPath, curX, curY );
@@ -783,8 +793,10 @@
for ( idx = 0; idx < count; idx += 2 )
{
- curX += cf2_stack_getReal( opStack, idx + 0 );
- curY += cf2_stack_getReal( opStack, idx + 1 );
+ curX = ADD_INT32( curX, cf2_stack_getReal( opStack,
+ idx + 0 ) );
+ curY = ADD_INT32( curY, cf2_stack_getReal( opStack,
+ idx + 1 ) );
cf2_glyphpath_lineTo( &glyphPath, curX, curY );
}
@@ -810,9 +822,9 @@
if ( isX )
- curX += v;
+ curX = ADD_INT32( curX, v );
else
- curY += v;
+ curY = ADD_INT32( curY, v );
isX = !isX;
@@ -835,13 +847,15 @@
while ( idx + 6 <= count )
{
- CF2_Fixed x1 = cf2_stack_getReal( opStack, idx + 0 ) + curX;
- CF2_Fixed y1 = cf2_stack_getReal( opStack, idx + 1 ) + curY;
- CF2_Fixed x2 = cf2_stack_getReal( opStack, idx + 2 ) + x1;
- CF2_Fixed y2 = cf2_stack_getReal( opStack, idx + 3 ) + y1;
- CF2_Fixed x3 = cf2_stack_getReal( opStack, idx + 4 ) + x2;
- CF2_Fixed y3 = cf2_stack_getReal( opStack, idx + 5 ) + y2;
+ CF2_Fixed x1, y1, x2, y2, x3, y3;
+
+ x1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curX );
+ y1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), curY );
+ x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), x1 );
+ y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), y1 );
+ x3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 4 ), x2 );
+ y3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 5 ), y2 );
cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 );
@@ -852,8 +866,10 @@
if ( op1 == cf2_cmdRCURVELINE )
{
- curX += cf2_stack_getReal( opStack, idx + 0 );
- curY += cf2_stack_getReal( opStack, idx + 1 );
+ curX = ADD_INT32( curX, cf2_stack_getReal( opStack,
+ idx + 0 ) );
+ curY = ADD_INT32( curY, cf2_stack_getReal( opStack,
+ idx + 1 ) );
cf2_glyphpath_lineTo( &glyphPath, curX, curY );
}
@@ -1129,7 +1145,10 @@
arg = cf2_stack_popFixed( opStack );
- cf2_stack_pushFixed( opStack, FT_ABS( arg ) );
+ if ( arg < -CF2_FIXED_MAX )
+ cf2_stack_pushFixed( opStack, CF2_FIXED_MAX );
+ else
+ cf2_stack_pushFixed( opStack, FT_ABS( arg ) );
}
continue; /* do not clear the stack */
@@ -1144,7 +1163,9 @@
summand2 = cf2_stack_popFixed( opStack );
summand1 = cf2_stack_popFixed( opStack );
- cf2_stack_pushFixed( opStack, summand1 + summand2 );
+ cf2_stack_pushFixed( opStack,
+ ADD_INT32( summand1,
+ summand2 ) );
}
continue; /* do not clear the stack */
@@ -1159,7 +1180,8 @@
subtrahend = cf2_stack_popFixed( opStack );
minuend = cf2_stack_popFixed( opStack );
- cf2_stack_pushFixed( opStack, minuend - subtrahend );
+ cf2_stack_pushFixed( opStack,
+ SUB_INT32( minuend, subtrahend ) );
}
continue; /* do not clear the stack */
@@ -1174,7 +1196,8 @@
divisor = cf2_stack_popFixed( opStack );
dividend = cf2_stack_popFixed( opStack );
- cf2_stack_pushFixed( opStack, FT_DivFix( dividend, divisor ) );
+ cf2_stack_pushFixed( opStack,
+ FT_DivFix( dividend, divisor ) );
}
continue; /* do not clear the stack */
@@ -1187,7 +1210,10 @@
arg = cf2_stack_popFixed( opStack );
- cf2_stack_pushFixed( opStack, -arg );
+ if ( arg < -CF2_FIXED_MAX )
+ cf2_stack_pushFixed( opStack, CF2_FIXED_MAX );
+ else
+ cf2_stack_pushFixed( opStack, -arg );
}
continue; /* do not clear the stack */
@@ -1257,7 +1283,8 @@
arg2 = cf2_stack_popFixed( opStack );
arg1 = cf2_stack_popFixed( opStack );
- cf2_stack_pushFixed( opStack, cond1 <= cond2 ? arg1 : arg2 );
+ cf2_stack_pushFixed( opStack,
+ cond1 <= cond2 ? arg1 : arg2 );
}
continue; /* do not clear the stack */
@@ -1291,7 +1318,8 @@
factor2 = cf2_stack_popFixed( opStack );
factor1 = cf2_stack_popFixed( opStack );
- cf2_stack_pushFixed( opStack, FT_MulFix( factor1, factor2 ) );
+ cf2_stack_pushFixed( opStack,
+ FT_MulFix( factor1, factor2 ) );
}
continue; /* do not clear the stack */
@@ -1305,7 +1333,9 @@
arg = cf2_stack_popFixed( opStack );
if ( arg > 0 )
{
- FT_Fixed root = arg;
+ /* use a start value that doesn't make */
+ /* the algorithm's addition overflow */
+ FT_Fixed root = arg < 10 ? arg : arg >> 1;
FT_Fixed new_root;
@@ -1369,7 +1399,8 @@
if ( size > 0 )
{
- /* for `cf2_stack_getReal', index 0 is bottom of stack */
+ /* for `cf2_stack_getReal', */
+ /* index 0 is bottom of stack */
CF2_UInt gr_idx;
@@ -1381,7 +1412,8 @@
gr_idx = size - 1 - (CF2_UInt)idx;
cf2_stack_pushFixed( opStack,
- cf2_stack_getReal( opStack, gr_idx ) );
+ cf2_stack_getReal( opStack,
+ gr_idx ) );
}
}
continue; /* do not clear the stack */
@@ -1416,7 +1448,8 @@
cf2_stack_count( opStack ) == 5 )
{
if ( !haveWidth )
- *width = cf2_stack_getReal( opStack, 0 ) + nominalWidthX;
+ *width = ADD_INT32( cf2_stack_getReal( opStack, 0 ),
+ nominalWidthX );
}
/* width is defined or default after this */
@@ -1564,7 +1597,8 @@
FT_TRACE4(( " rmoveto\n" ));
if ( cf2_stack_count( opStack ) > 2 && !haveWidth )
- *width = cf2_stack_getReal( opStack, 0 ) + nominalWidthX;
+ *width = ADD_INT32( cf2_stack_getReal( opStack, 0 ),
+ nominalWidthX );
/* width is defined or default after this */
haveWidth = TRUE;
@@ -1572,8 +1606,8 @@
if ( font->decoder->width_only )
goto exit;
- curY += cf2_stack_popFixed( opStack );
- curX += cf2_stack_popFixed( opStack );
+ curY = ADD_INT32( curY, cf2_stack_popFixed( opStack ) );
+ curX = ADD_INT32( curX, cf2_stack_popFixed( opStack ) );
cf2_glyphpath_moveTo( &glyphPath, curX, curY );
@@ -1583,7 +1617,8 @@
FT_TRACE4(( " hmoveto\n" ));
if ( cf2_stack_count( opStack ) > 1 && !haveWidth )
- *width = cf2_stack_getReal( opStack, 0 ) + nominalWidthX;
+ *width = ADD_INT32( cf2_stack_getReal( opStack, 0 ),
+ nominalWidthX );
/* width is defined or default after this */
haveWidth = TRUE;
@@ -1591,7 +1626,7 @@
if ( font->decoder->width_only )
goto exit;
- curX += cf2_stack_popFixed( opStack );
+ curX = ADD_INT32( curX, cf2_stack_popFixed( opStack ) );
cf2_glyphpath_moveTo( &glyphPath, curX, curY );
@@ -1607,8 +1642,10 @@
while ( idx + 6 < count )
{
- curX += cf2_stack_getReal( opStack, idx + 0 );
- curY += cf2_stack_getReal( opStack, idx + 1 );
+ curX = ADD_INT32( curX, cf2_stack_getReal( opStack,
+ idx + 0 ) );
+ curY = ADD_INT32( curY, cf2_stack_getReal( opStack,
+ idx + 1 ) );
cf2_glyphpath_lineTo( &glyphPath, curX, curY );
idx += 2;
@@ -1616,13 +1653,15 @@
while ( idx < count )
{
- CF2_Fixed x1 = cf2_stack_getReal( opStack, idx + 0 ) + curX;
- CF2_Fixed y1 = cf2_stack_getReal( opStack, idx + 1 ) + curY;
- CF2_Fixed x2 = cf2_stack_getReal( opStack, idx + 2 ) + x1;
- CF2_Fixed y2 = cf2_stack_getReal( opStack, idx + 3 ) + y1;
- CF2_Fixed x3 = cf2_stack_getReal( opStack, idx + 4 ) + x2;
- CF2_Fixed y3 = cf2_stack_getReal( opStack, idx + 5 ) + y2;
+ CF2_Fixed x1, y1, x2, y2, x3, y3;
+
+ x1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curX );
+ y1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), curY );
+ x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), x1 );
+ y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), y1 );
+ x3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 4 ), x2 );
+ y3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 5 ), y2 );
cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 );
@@ -1656,18 +1695,18 @@
if ( ( count - idx ) & 1 )
{
- x1 = cf2_stack_getReal( opStack, idx ) + curX;
+ x1 = ADD_INT32( cf2_stack_getReal( opStack, idx ), curX );
idx++;
}
else
x1 = curX;
- y1 = cf2_stack_getReal( opStack, idx + 0 ) + curY;
- x2 = cf2_stack_getReal( opStack, idx + 1 ) + x1;
- y2 = cf2_stack_getReal( opStack, idx + 2 ) + y1;
+ y1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curY );
+ x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), x1 );
+ y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), y1 );
x3 = x2;
- y3 = cf2_stack_getReal( opStack, idx + 3 ) + y2;
+ y3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), y2 );
cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 );
@@ -1701,17 +1740,17 @@
if ( ( count - idx ) & 1 )
{
- y1 = cf2_stack_getReal( opStack, idx ) + curY;
+ y1 = ADD_INT32( cf2_stack_getReal( opStack, idx ), curY );
idx++;
}
else
y1 = curY;
- x1 = cf2_stack_getReal( opStack, idx + 0 ) + curX;
- x2 = cf2_stack_getReal( opStack, idx + 1 ) + x1;
- y2 = cf2_stack_getReal( opStack, idx + 2 ) + y1;
- x3 = cf2_stack_getReal( opStack, idx + 3 ) + x2;
+ x1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curX );
+ x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), x1 );
+ y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), y1 );
+ x3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), x2 );
y3 = y2;
cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 );
@@ -1750,15 +1789,15 @@
if ( alternate )
{
- x1 = cf2_stack_getReal( opStack, idx + 0 ) + curX;
+ x1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curX );
y1 = curY;
- x2 = cf2_stack_getReal( opStack, idx + 1 ) + x1;
- y2 = cf2_stack_getReal( opStack, idx + 2 ) + y1;
- y3 = cf2_stack_getReal( opStack, idx + 3 ) + y2;
+ x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), x1 );
+ y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), y1 );
+ y3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), y2 );
if ( count - idx == 5 )
{
- x3 = cf2_stack_getReal( opStack, idx + 4 ) + x2;
+ x3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 4 ), x2 );
idx++;
}
@@ -1770,14 +1809,14 @@
else
{
x1 = curX;
- y1 = cf2_stack_getReal( opStack, idx + 0 ) + curY;
- x2 = cf2_stack_getReal( opStack, idx + 1 ) + x1;
- y2 = cf2_stack_getReal( opStack, idx + 2 ) + y1;
- x3 = cf2_stack_getReal( opStack, idx + 3 ) + x2;
+ y1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curY );
+ x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), x1 );
+ y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), y1 );
+ x3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), x2 );
if ( count - idx == 5 )
{
- y3 = cf2_stack_getReal( opStack, idx + 4 ) + y2;
+ y3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 4 ), y2 );
idx++;
}
diff --git a/thirdparty/freetype/src/cff/cffgload.c b/thirdparty/freetype/src/cff/cffgload.c
index 940804850e..20f3a2c28e 100644
--- a/thirdparty/freetype/src/cff/cffgload.c
+++ b/thirdparty/freetype/src/cff/cffgload.c
@@ -20,6 +20,7 @@
#include FT_INTERNAL_DEBUG_H
#include FT_INTERNAL_STREAM_H
#include FT_INTERNAL_SFNT_H
+#include FT_INTERNAL_CALC_H
#include FT_OUTLINE_H
#include FT_CFF_DRIVER_H
@@ -1450,8 +1451,8 @@
cff_builder_close_contour( builder );
builder->path_begun = 0;
- x += args[-2];
- y += args[-1];
+ x = ADD_LONG( x, args[-2] );
+ y = ADD_LONG( y, args[-1] );
args = stack;
break;
@@ -1460,7 +1461,7 @@
cff_builder_close_contour( builder );
builder->path_begun = 0;
- y += args[-1];
+ y = ADD_LONG( y, args[-1] );
args = stack;
break;
@@ -1469,7 +1470,7 @@
cff_builder_close_contour( builder );
builder->path_begun = 0;
- x += args[-1];
+ x = ADD_LONG( x, args[-1] );
args = stack;
break;
@@ -1486,8 +1487,8 @@
args -= num_args & ~1;
while ( args < decoder->top )
{
- x += args[0];
- y += args[1];
+ x = ADD_LONG( x, args[0] );
+ y = ADD_LONG( y, args[1] );
cff_builder_add_point( builder, x, y, 1 );
args += 2;
}
@@ -1519,9 +1520,9 @@
while ( args < decoder->top )
{
if ( phase )
- x += args[0];
+ x = ADD_LONG( x, args[0] );
else
- y += args[0];
+ y = ADD_LONG( y, args[0] );
if ( cff_builder_add_point1( builder, x, y ) )
goto Fail;
@@ -1552,15 +1553,18 @@
args -= nargs;
while ( args < decoder->top )
{
- x += args[0];
- y += args[1];
+ x = ADD_LONG( x, args[0] );
+ y = ADD_LONG( y, args[1] );
cff_builder_add_point( builder, x, y, 0 );
- x += args[2];
- y += args[3];
+
+ x = ADD_LONG( x, args[2] );
+ y = ADD_LONG( y, args[3] );
cff_builder_add_point( builder, x, y, 0 );
- x += args[4];
- y += args[5];
+
+ x = ADD_LONG( x, args[4] );
+ y = ADD_LONG( y, args[5] );
cff_builder_add_point( builder, x, y, 1 );
+
args += 6;
}
args = stack;
@@ -1589,7 +1593,7 @@
if ( nargs & 1 )
{
- x += args[0];
+ x = ADD_LONG( x, args[0] );
args++;
nargs--;
}
@@ -1599,13 +1603,16 @@
while ( args < decoder->top )
{
- y += args[0];
+ y = ADD_LONG( y, args[0] );
cff_builder_add_point( builder, x, y, 0 );
- x += args[1];
- y += args[2];
+
+ x = ADD_LONG( x, args[1] );
+ y = ADD_LONG( y, args[2] );
cff_builder_add_point( builder, x, y, 0 );
- y += args[3];
+
+ y = ADD_LONG( y, args[3] );
cff_builder_add_point( builder, x, y, 1 );
+
args += 4;
}
args = stack;
@@ -1633,7 +1640,7 @@
args -= nargs;
if ( nargs & 1 )
{
- y += args[0];
+ y = ADD_LONG( y, args[0] );
args++;
nargs--;
}
@@ -1643,13 +1650,16 @@
while ( args < decoder->top )
{
- x += args[0];
+ x = ADD_LONG( x, args[0] );
cff_builder_add_point( builder, x, y, 0 );
- x += args[1];
- y += args[2];
+
+ x = ADD_LONG( x, args[1] );
+ y = ADD_LONG( y, args[2] );
cff_builder_add_point( builder, x, y, 0 );
- x += args[3];
+
+ x = ADD_LONG( x, args[3] );
cff_builder_add_point( builder, x, y, 1 );
+
args += 4;
}
args = stack;
@@ -1688,26 +1698,30 @@
nargs -= 4;
if ( phase )
{
- x += args[0];
+ x = ADD_LONG( x, args[0] );
cff_builder_add_point( builder, x, y, 0 );
- x += args[1];
- y += args[2];
+
+ x = ADD_LONG( x, args[1] );
+ y = ADD_LONG( y, args[2] );
cff_builder_add_point( builder, x, y, 0 );
- y += args[3];
+
+ y = ADD_LONG( y, args[3] );
if ( nargs == 1 )
- x += args[4];
+ x = ADD_LONG( x, args[4] );
cff_builder_add_point( builder, x, y, 1 );
}
else
{
- y += args[0];
+ y = ADD_LONG( y, args[0] );
cff_builder_add_point( builder, x, y, 0 );
- x += args[1];
- y += args[2];
+
+ x = ADD_LONG( x, args[1] );
+ y = ADD_LONG( y, args[2] );
cff_builder_add_point( builder, x, y, 0 );
- x += args[3];
+
+ x = ADD_LONG( x, args[3] );
if ( nargs == 1 )
- y += args[4];
+ y = ADD_LONG( y, args[4] );
cff_builder_add_point( builder, x, y, 1 );
}
args += 4;
@@ -1740,23 +1754,27 @@
/* first, add the line segments */
while ( num_lines > 0 )
{
- x += args[0];
- y += args[1];
+ x = ADD_LONG( x, args[0] );
+ y = ADD_LONG( y, args[1] );
cff_builder_add_point( builder, x, y, 1 );
+
args += 2;
num_lines--;
}
/* then the curve */
- x += args[0];
- y += args[1];
+ x = ADD_LONG( x, args[0] );
+ y = ADD_LONG( y, args[1] );
cff_builder_add_point( builder, x, y, 0 );
- x += args[2];
- y += args[3];
+
+ x = ADD_LONG( x, args[2] );
+ y = ADD_LONG( y, args[3] );
cff_builder_add_point( builder, x, y, 0 );
- x += args[4];
- y += args[5];
+
+ x = ADD_LONG( x, args[4] );
+ y = ADD_LONG( y, args[5] );
cff_builder_add_point( builder, x, y, 1 );
+
args = stack;
}
break;
@@ -1785,23 +1803,27 @@
/* first, add the curves */
while ( num_curves > 0 )
{
- x += args[0];
- y += args[1];
+ x = ADD_LONG( x, args[0] );
+ y = ADD_LONG( y, args[1] );
cff_builder_add_point( builder, x, y, 0 );
- x += args[2];
- y += args[3];
+
+ x = ADD_LONG( x, args[2] );
+ y = ADD_LONG( y, args[3] );
cff_builder_add_point( builder, x, y, 0 );
- x += args[4];
- y += args[5];
+
+ x = ADD_LONG( x, args[4] );
+ y = ADD_LONG( y, args[5] );
cff_builder_add_point( builder, x, y, 1 );
+
args += 6;
num_curves--;
}
/* then the final line */
- x += args[0];
- y += args[1];
+ x = ADD_LONG( x, args[0] );
+ y = ADD_LONG( y, args[1] );
cff_builder_add_point( builder, x, y, 1 );
+
args = stack;
}
break;
@@ -1824,33 +1846,33 @@
start_y = y;
/* first control point */
- x += args[0];
- y += args[1];
+ x = ADD_LONG( x, args[0] );
+ y = ADD_LONG( y, args[1] );
cff_builder_add_point( builder, x, y, 0 );
/* second control point */
- x += args[2];
- y += args[3];
+ x = ADD_LONG( x, args[2] );
+ y = ADD_LONG( y, args[3] );
cff_builder_add_point( builder, x, y, 0 );
/* join point; on curve, with y-value the same as the last */
/* control point's y-value */
- x += args[4];
+ x = ADD_LONG( x, args[4] );
cff_builder_add_point( builder, x, y, 1 );
/* third control point, with y-value the same as the join */
/* point's y-value */
- x += args[5];
+ x = ADD_LONG( x, args[5] );
cff_builder_add_point( builder, x, y, 0 );
/* fourth control point */
- x += args[6];
- y += args[7];
+ x = ADD_LONG( x, args[6] );
+ y = ADD_LONG( y, args[7] );
cff_builder_add_point( builder, x, y, 0 );
/* ending point, with y-value the same as the start */
- x += args[8];
- y = start_y;
+ x = ADD_LONG( x, args[8] );
+ y = start_y;
cff_builder_add_point( builder, x, y, 1 );
args = stack;
@@ -1873,32 +1895,32 @@
start_y = y;
/* first control point */
- x += args[0];
+ x = ADD_LONG( x, args[0] );
cff_builder_add_point( builder, x, y, 0 );
/* second control point */
- x += args[1];
- y += args[2];
+ x = ADD_LONG( x, args[1] );
+ y = ADD_LONG( y, args[2] );
cff_builder_add_point( builder, x, y, 0 );
/* join point; on curve, with y-value the same as the last */
/* control point's y-value */
- x += args[3];
+ x = ADD_LONG( x, args[3] );
cff_builder_add_point( builder, x, y, 1 );
/* third control point, with y-value the same as the join */
/* point's y-value */
- x += args[4];
+ x = ADD_LONG( x, args[4] );
cff_builder_add_point( builder, x, y, 0 );
/* fourth control point */
- x += args[5];
- y = start_y;
+ x = ADD_LONG( x, args[5] );
+ y = start_y;
cff_builder_add_point( builder, x, y, 0 );
/* ending point, with y-value the same as the start point's */
/* y-value -- we don't add this point, though */
- x += args[6];
+ x = ADD_LONG( x, args[6] );
cff_builder_add_point( builder, x, y, 1 );
args = stack;
@@ -1934,8 +1956,8 @@
/* grab up to the last argument */
for ( count = 5; count > 0; count-- )
{
- dx += temp[0];
- dy += temp[1];
+ dx = ADD_LONG( dx, temp[0] );
+ dy = ADD_LONG( dy, temp[1] );
temp += 2;
}
@@ -1949,8 +1971,8 @@
for ( count = 5; count > 0; count-- )
{
- x += args[0];
- y += args[1];
+ x = ADD_LONG( x, args[0] );
+ y = ADD_LONG( y, args[1] );
cff_builder_add_point( builder, x, y,
(FT_Bool)( count == 3 ) );
args += 2;
@@ -1959,13 +1981,13 @@
/* is last operand an x- or y-delta? */
if ( horizontal )
{
- x += args[0];
- y = start_y;
+ x = ADD_LONG( x, args[0] );
+ y = start_y;
}
else
{
- x = start_x;
- y += args[0];
+ x = start_x;
+ y = ADD_LONG( y, args[0] );
}
cff_builder_add_point( builder, x, y, 1 );
@@ -1987,8 +2009,8 @@
for ( count = 6; count > 0; count-- )
{
- x += args[0];
- y += args[1];
+ x = ADD_LONG( x, args[0] );
+ y = ADD_LONG( y, args[1] );
cff_builder_add_point( builder, x, y,
(FT_Bool)( count == 4 || count == 1 ) );
args += 2;
@@ -2066,21 +2088,26 @@
FT_TRACE4(( " abs\n" ));
if ( args[0] < 0 )
- args[0] = -args[0];
+ {
+ if ( args[0] == FT_LONG_MIN )
+ args[0] = FT_LONG_MAX;
+ else
+ args[0] = -args[0];
+ }
args++;
break;
case cff_op_add:
FT_TRACE4(( " add\n" ));
- args[0] += args[1];
+ args[0] = ADD_LONG( args[0], args[1] );
args++;
break;
case cff_op_sub:
FT_TRACE4(( " sub\n" ));
- args[0] -= args[1];
+ args[0] = SUB_LONG( args[0], args[1] );
args++;
break;
@@ -2094,6 +2121,8 @@
case cff_op_neg:
FT_TRACE4(( " neg\n" ));
+ if ( args[0] == FT_LONG_MIN )
+ args[0] = FT_LONG_MAX;
args[0] = -args[0];
args++;
break;
@@ -2350,12 +2379,13 @@
FT_TRACE4(( " hsbw (invalid op)\n" ));
- decoder->glyph_width = decoder->nominal_width + ( args[1] >> 16 );
+ decoder->glyph_width =
+ ADD_LONG( decoder->nominal_width, ( args[1] >> 16 ) );
decoder->builder.left_bearing.x = args[0];
decoder->builder.left_bearing.y = 0;
- x = decoder->builder.pos_x + args[0];
+ x = ADD_LONG( decoder->builder.pos_x, args[0] );
y = decoder->builder.pos_y;
args = stack;
break;
@@ -2367,13 +2397,14 @@
FT_TRACE4(( " sbw (invalid op)\n" ));
- decoder->glyph_width = decoder->nominal_width + ( args[2] >> 16 );
+ decoder->glyph_width =
+ ADD_LONG( decoder->nominal_width, ( args[2] >> 16 ) );
decoder->builder.left_bearing.x = args[0];
decoder->builder.left_bearing.y = args[1];
- x = decoder->builder.pos_x + args[0];
- y = decoder->builder.pos_y + args[1];
+ x = ADD_LONG( decoder->builder.pos_x, args[0] );
+ y = ADD_LONG( decoder->builder.pos_y, args[1] );
args = stack;
break;
@@ -2384,8 +2415,8 @@
FT_TRACE4(( " setcurrentpoint (invalid op)\n" ));
- x = decoder->builder.pos_x + args[0];
- y = decoder->builder.pos_y + args[1];
+ x = ADD_LONG( decoder->builder.pos_x, args[0] );
+ y = ADD_LONG( decoder->builder.pos_y, args[1] );
args = stack;
break;
diff --git a/thirdparty/freetype/src/cff/cffload.c b/thirdparty/freetype/src/cff/cffload.c
index 3beaeb1c8e..12420384af 100644
--- a/thirdparty/freetype/src/cff/cffload.c
+++ b/thirdparty/freetype/src/cff/cffload.c
@@ -1352,9 +1352,12 @@
sum = cff_parse_num( parser, &parser->stack[i + base] ) * 65536;
for ( j = 1; j < blend->lenBV; j++ )
- sum += FT_MulFix( *weight++,
- cff_parse_num( parser,
- &parser->stack[delta++] ) * 65536 );
+ sum = ADD_INT32(
+ sum,
+ FT_MulFix(
+ *weight++,
+ cff_parse_num( parser,
+ &parser->stack[delta++] ) * 65536 ) );
/* point parser stack to new value on blend_stack */
parser->stack[i + base] = subFont->blend_top;
diff --git a/thirdparty/freetype/src/cff/cffparse.c b/thirdparty/freetype/src/cff/cffparse.c
index e1511bdbd1..9d7bf6d22c 100644
--- a/thirdparty/freetype/src/cff/cffparse.c
+++ b/thirdparty/freetype/src/cff/cffparse.c
@@ -20,6 +20,7 @@
#include "cffparse.h"
#include FT_INTERNAL_STREAM_H
#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_CALC_H
#include "cfferrs.h"
#include "cffpic.h"
@@ -156,6 +157,22 @@
1000000000L
};
+ /* maximum values allowed for multiplying */
+ /* with the corresponding `power_tens' element */
+ static const FT_Long power_ten_limits[] =
+ {
+ FT_LONG_MAX / 1L,
+ FT_LONG_MAX / 10L,
+ FT_LONG_MAX / 100L,
+ FT_LONG_MAX / 1000L,
+ FT_LONG_MAX / 10000L,
+ FT_LONG_MAX / 100000L,
+ FT_LONG_MAX / 1000000L,
+ FT_LONG_MAX / 10000000L,
+ FT_LONG_MAX / 100000000L,
+ FT_LONG_MAX / 1000000000L,
+ };
+
/* read a real */
static FT_Fixed
@@ -484,7 +501,15 @@
if ( scaling )
+ {
+ if ( FT_ABS( val ) > power_ten_limits[scaling] )
+ {
+ val = val > 0 ? 0x7FFFFFFFL : -0x7FFFFFFFL;
+ goto Overflow;
+ }
+
val *= power_tens[scaling];
+ }
if ( val > 0x7FFF )
{
@@ -1585,7 +1610,7 @@
val = 0;
while ( num_args > 0 )
{
- val += cff_parse_num( parser, data++ );
+ val = ADD_LONG( val, cff_parse_num( parser, data++ ) );
switch ( field->size )
{
case (8 / FT_CHAR_BIT):
diff --git a/thirdparty/freetype/src/gxvalid/README b/thirdparty/freetype/src/gxvalid/README
index 7201459aaf..200f66cb12 100644
--- a/thirdparty/freetype/src/gxvalid/README
+++ b/thirdparty/freetype/src/gxvalid/README
@@ -9,7 +9,7 @@ gxvalid: TrueType GX validator
additional tables in TrueType font which are used by `QuickDraw GX
Text', Apple Advanced Typography (AAT). In addition, gxvalid can
validates `kern' tables which have been extended for AAT. Like the
- otvalid module, gxvalid uses Freetype 2's validator framework
+ otvalid module, gxvalid uses FreeType 2's validator framework
(ftvalid).
You can link gxvalid with your program; before running your own layout
diff --git a/thirdparty/freetype/src/pcf/README b/thirdparty/freetype/src/pcf/README
index 10eff15fbe..09ea970eda 100644
--- a/thirdparty/freetype/src/pcf/README
+++ b/thirdparty/freetype/src/pcf/README
@@ -41,8 +41,8 @@ value given as argument into the corresponding glyph number.
Known problems
**************
-- dealing explicitly with encodings breaks the uniformity of freetype2
- api.
+- dealing explicitly with encodings breaks the uniformity of FreeType 2
+ API.
- except for encodings properties, client applications have no
visibility of the PCF_Face object. This means that applications
diff --git a/thirdparty/freetype/src/pcf/pcfdrivr.c b/thirdparty/freetype/src/pcf/pcfdrivr.c
index 9f4d36d111..169f75e950 100644
--- a/thirdparty/freetype/src/pcf/pcfdrivr.c
+++ b/thirdparty/freetype/src/pcf/pcfdrivr.c
@@ -387,7 +387,11 @@ THE SOFTWARE.
if ( !ft_strcmp( s, "10646" ) ||
( !ft_strcmp( s, "8859" ) &&
!ft_strcmp( face->charset_encoding, "1" ) ) )
- unicode_charmap = 1;
+ unicode_charmap = 1;
+ /* another name for ASCII */
+ else if ( !ft_strcmp( s, "646.1991" ) &&
+ !ft_strcmp( face->charset_encoding, "IRV" ) )
+ unicode_charmap = 1;
}
}
@@ -409,12 +413,6 @@ THE SOFTWARE.
}
error = FT_CMap_New( &pcf_cmap_class, NULL, &charmap, NULL );
-
-#if 0
- /* Select default charmap */
- if ( pcfface->num_charmaps )
- pcfface->charmap = pcfface->charmaps[0];
-#endif
}
}
diff --git a/thirdparty/freetype/src/pcf/pcfread.c b/thirdparty/freetype/src/pcf/pcfread.c
index 3eacf2baf6..da216b05f4 100644
--- a/thirdparty/freetype/src/pcf/pcfread.c
+++ b/thirdparty/freetype/src/pcf/pcfread.c
@@ -1162,6 +1162,20 @@ THE SOFTWARE.
accel->fontDescent,
accel->maxOverlap ));
+ /* sanity checks */
+ if ( FT_ABS( accel->fontAscent ) > 0x7FFF )
+ {
+ accel->fontAscent = accel->fontAscent < 0 ? -0x7FFF : 0x7FFF;
+ FT_TRACE0(( "pfc_get_accel: clamping font ascent to value %d\n",
+ accel->fontAscent ));
+ }
+ if ( FT_ABS( accel->fontDescent ) > 0x7FFF )
+ {
+ accel->fontDescent = accel->fontDescent < 0 ? -0x7FFF : 0x7FFF;
+ FT_TRACE0(( "pfc_get_accel: clamping font descent to value %d\n",
+ accel->fontDescent ));
+ }
+
FT_TRACE5(( " minbounds:" ));
error = pcf_get_metric( stream,
format & ( ~PCF_FORMAT_MASK ),
@@ -1496,8 +1510,16 @@ THE SOFTWARE.
if ( face->accel.fontAscent + face->accel.fontDescent < 0 )
FT_TRACE0(( "pcf_load_font: negative height\n" ));
#endif
- bsize->height = FT_ABS( (FT_Short)( face->accel.fontAscent +
- face->accel.fontDescent ) );
+ if ( FT_ABS( face->accel.fontAscent +
+ face->accel.fontDescent ) > 0x7FFF )
+ {
+ bsize->height = 0x7FFF;
+ FT_TRACE0(( "pcf_load_font: clamping height to value %d\n",
+ bsize->height ));
+ }
+ else
+ bsize->height = FT_ABS( (FT_Short)( face->accel.fontAscent +
+ face->accel.fontDescent ) );
prop = pcf_find_property( face, "AVERAGE_WIDTH" );
if ( prop )
@@ -1506,10 +1528,20 @@ THE SOFTWARE.
if ( prop->value.l < 0 )
FT_TRACE0(( "pcf_load_font: negative average width\n" ));
#endif
- bsize->width = FT_ABS( (FT_Short)( ( prop->value.l ) + 5 ) / 10 );
+ if ( ( FT_ABS( prop->value.l ) > 0x7FFFL * 10 - 5 ) )
+ {
+ bsize->width = 0x7FFF;
+ FT_TRACE0(( "pcf_load_font: clamping average width to value %d\n",
+ bsize->width ));
+ }
+ else
+ bsize->width = FT_ABS( (FT_Short)( ( prop->value.l + 5 ) / 10 ) );
}
else
+ {
+ /* this is a heuristical value */
bsize->width = (FT_Short)FT_MulDiv( bsize->height, 2, 3 );
+ }
prop = pcf_find_property( face, "POINT_SIZE" );
if ( prop )
@@ -1519,9 +1551,16 @@ THE SOFTWARE.
FT_TRACE0(( "pcf_load_font: negative point size\n" ));
#endif
/* convert from 722.7 decipoints to 72 points per inch */
- bsize->size = FT_MulDiv( FT_ABS( prop->value.l ),
- 64 * 7200,
- 72270L );
+ if ( FT_ABS( prop->value.l ) > 0x504C2L ) /* 0x7FFF * 72270/7200 */
+ {
+ bsize->size = 0x7FFF;
+ FT_TRACE0(( "pcf_load_font: clamping point size to value %d\n",
+ bsize->size ));
+ }
+ else
+ bsize->size = FT_MulDiv( FT_ABS( prop->value.l ),
+ 64 * 7200,
+ 72270L );
}
prop = pcf_find_property( face, "PIXEL_SIZE" );
@@ -1531,7 +1570,14 @@ THE SOFTWARE.
if ( prop->value.l < 0 )
FT_TRACE0(( "pcf_load_font: negative pixel size\n" ));
#endif
- bsize->y_ppem = FT_ABS( (FT_Short)prop->value.l ) << 6;
+ if ( FT_ABS( prop->value.l ) > 0x7FFF )
+ {
+ bsize->y_ppem = 0x7FFF << 6;
+ FT_TRACE0(( "pcf_load_font: clamping pixel size to value %d\n",
+ bsize->y_ppem ));
+ }
+ else
+ bsize->y_ppem = FT_ABS( (FT_Short)prop->value.l ) << 6;
}
prop = pcf_find_property( face, "RESOLUTION_X" );
@@ -1541,7 +1587,14 @@ THE SOFTWARE.
if ( prop->value.l < 0 )
FT_TRACE0(( "pcf_load_font: negative X resolution\n" ));
#endif
- resolution_x = FT_ABS( (FT_Short)prop->value.l );
+ if ( FT_ABS( prop->value.l ) > 0x7FFF )
+ {
+ resolution_x = 0x7FFF;
+ FT_TRACE0(( "pcf_load_font: clamping X resolution to value %d\n",
+ resolution_x ));
+ }
+ else
+ resolution_x = FT_ABS( (FT_Short)prop->value.l );
}
prop = pcf_find_property( face, "RESOLUTION_Y" );
@@ -1551,7 +1604,14 @@ THE SOFTWARE.
if ( prop->value.l < 0 )
FT_TRACE0(( "pcf_load_font: negative Y resolution\n" ));
#endif
- resolution_y = FT_ABS( (FT_Short)prop->value.l );
+ if ( FT_ABS( prop->value.l ) > 0x7FFF )
+ {
+ resolution_y = 0x7FFF;
+ FT_TRACE0(( "pcf_load_font: clamping Y resolution to value %d\n",
+ resolution_y ));
+ }
+ else
+ resolution_y = FT_ABS( (FT_Short)prop->value.l );
}
if ( bsize->y_ppem == 0 )
diff --git a/thirdparty/freetype/src/pfr/pfrobjs.c b/thirdparty/freetype/src/pfr/pfrobjs.c
index 4b1703f51c..514af8050d 100644
--- a/thirdparty/freetype/src/pfr/pfrobjs.c
+++ b/thirdparty/freetype/src/pfr/pfrobjs.c
@@ -264,12 +264,6 @@
charmap.encoding = FT_ENCODING_UNICODE;
error = FT_CMap_New( &pfr_cmap_class_rec, NULL, &charmap, NULL );
-
-#if 0
- /* select default charmap */
- if ( pfrface->num_charmaps )
- pfrface->charmap = pfrface->charmaps[0];
-#endif
}
/* check whether we have loaded any kerning pairs */
diff --git a/thirdparty/freetype/src/psaux/psconv.c b/thirdparty/freetype/src/psaux/psconv.c
index b092482194..d125b0834a 100644
--- a/thirdparty/freetype/src/psaux/psconv.c
+++ b/thirdparty/freetype/src/psaux/psconv.c
@@ -111,6 +111,10 @@
p++;
if ( p == limit )
goto Bad;
+
+ /* only a single sign is allowed */
+ if ( *p == '-' || *p == '+' )
+ return 0;
}
num_limit = 0x7FFFFFFFL / base;
@@ -215,6 +219,10 @@
p++;
if ( p == limit )
goto Bad;
+
+ /* only a single sign is allowed */
+ if ( *p == '-' || *p == '+' )
+ return 0;
}
/* read the integer part */
diff --git a/thirdparty/freetype/src/psaux/t1decode.c b/thirdparty/freetype/src/psaux/t1decode.c
index 7dd45135de..1250b53f5d 100644
--- a/thirdparty/freetype/src/psaux/t1decode.c
+++ b/thirdparty/freetype/src/psaux/t1decode.c
@@ -864,7 +864,9 @@
for ( mm = 1; mm < blend->num_designs; mm++ )
- tmp += FT_MulFix( *delta++, blend->weight_vector[mm] );
+ tmp = ADD_LONG( tmp,
+ FT_MulFix( *delta++,
+ blend->weight_vector[mm] ) );
*values++ = tmp;
}
@@ -904,7 +906,7 @@
if ( arg_cnt != 2 )
goto Unexpected_OtherSubr;
- top[0] += top[1]; /* XXX (over|under)flow */
+ top[0] = ADD_LONG( top[0], top[1] );
known_othersubr_result_cnt = 1;
break;
@@ -915,7 +917,7 @@
if ( arg_cnt != 2 )
goto Unexpected_OtherSubr;
- top[0] -= top[1]; /* XXX (over|under)flow */
+ top[0] = SUB_LONG( top[0], top[1] );
known_othersubr_result_cnt = 1;
break;
@@ -1147,11 +1149,13 @@
builder->parse_state = T1_Parse_Have_Width;
- builder->left_bearing.x += top[0];
- builder->advance.x = top[1];
- builder->advance.y = 0;
+ builder->left_bearing.x = ADD_LONG( builder->left_bearing.x,
+ top[0] );
- orig_x = x = builder->pos_x + top[0];
+ builder->advance.x = top[1];
+ builder->advance.y = 0;
+
+ orig_x = x = ADD_LONG( builder->pos_x, top[0] );
orig_y = y = builder->pos_y;
FT_UNUSED( orig_y );
@@ -1177,13 +1181,16 @@
builder->parse_state = T1_Parse_Have_Width;
- builder->left_bearing.x += top[0];
- builder->left_bearing.y += top[1];
- builder->advance.x = top[2];
- builder->advance.y = top[3];
+ builder->left_bearing.x = ADD_LONG( builder->left_bearing.x,
+ top[0] );
+ builder->left_bearing.y = ADD_LONG( builder->left_bearing.y,
+ top[1] );
+
+ builder->advance.x = top[2];
+ builder->advance.y = top[3];
- x = builder->pos_x + top[0];
- y = builder->pos_y + top[1];
+ x = ADD_LONG( builder->pos_x, top[0] );
+ y = ADD_LONG( builder->pos_y, top[1] );
/* the `metrics_only' indicates that we only want to compute */
/* the glyph's metrics (lsb + advance width), not load the */
@@ -1210,13 +1217,14 @@
if ( FT_SET_ERROR( t1_builder_start_point( builder, x, y ) ) )
goto Fail;
- x += top[0];
+ x = ADD_LONG( x, top[0] );
goto Add_Line;
case op_hmoveto:
FT_TRACE4(( " hmoveto" ));
- x += top[0];
+ x = ADD_LONG( x, top[0] );
+
if ( !decoder->flex_state )
{
if ( builder->parse_state == T1_Parse_Start )
@@ -1232,12 +1240,14 @@
FT_SET_ERROR( t1_builder_check_points( builder, 3 ) ) )
goto Fail;
- x += top[0];
+ x = ADD_LONG( x, top[0] );
t1_builder_add_point( builder, x, y, 0 );
- x += top[1];
- y += top[2];
+
+ x = ADD_LONG( x, top[1] );
+ y = ADD_LONG( y, top[2] );
t1_builder_add_point( builder, x, y, 0 );
- y += top[3];
+
+ y = ADD_LONG( y, top[3] );
t1_builder_add_point( builder, x, y, 1 );
break;
@@ -1247,8 +1257,8 @@
if ( FT_SET_ERROR( t1_builder_start_point( builder, x, y ) ) )
goto Fail;
- x += top[0];
- y += top[1];
+ x = ADD_LONG( x, top[0] );
+ y = ADD_LONG( y, top[1] );
Add_Line:
if ( FT_SET_ERROR( t1_builder_add_point1( builder, x, y ) ) )
@@ -1258,8 +1268,9 @@
case op_rmoveto:
FT_TRACE4(( " rmoveto" ));
- x += top[0];
- y += top[1];
+ x = ADD_LONG( x, top[0] );
+ y = ADD_LONG( y, top[1] );
+
if ( !decoder->flex_state )
{
if ( builder->parse_state == T1_Parse_Start )
@@ -1275,16 +1286,16 @@
FT_SET_ERROR( t1_builder_check_points( builder, 3 ) ) )
goto Fail;
- x += top[0];
- y += top[1];
+ x = ADD_LONG( x, top[0] );
+ y = ADD_LONG( y, top[1] );
t1_builder_add_point( builder, x, y, 0 );
- x += top[2];
- y += top[3];
+ x = ADD_LONG( x, top[2] );
+ y = ADD_LONG( y, top[3] );
t1_builder_add_point( builder, x, y, 0 );
- x += top[4];
- y += top[5];
+ x = ADD_LONG( x, top[4] );
+ y = ADD_LONG( y, top[5] );
t1_builder_add_point( builder, x, y, 1 );
break;
@@ -1295,12 +1306,14 @@
FT_SET_ERROR( t1_builder_check_points( builder, 3 ) ) )
goto Fail;
- y += top[0];
+ y = ADD_LONG( y, top[0] );
t1_builder_add_point( builder, x, y, 0 );
- x += top[1];
- y += top[2];
+
+ x = ADD_LONG( x, top[1] );
+ y = ADD_LONG( y, top[2] );
t1_builder_add_point( builder, x, y, 0 );
- x += top[3];
+
+ x = ADD_LONG( x, top[3] );
t1_builder_add_point( builder, x, y, 1 );
break;
@@ -1310,13 +1323,14 @@
if ( FT_SET_ERROR( t1_builder_start_point( builder, x, y ) ) )
goto Fail;
- y += top[0];
+ y = ADD_LONG( y, top[0] );
goto Add_Line;
case op_vmoveto:
FT_TRACE4(( " vmoveto" ));
- y += top[0];
+ y = ADD_LONG( y, top[0] );
+
if ( !decoder->flex_state )
{
if ( builder->parse_state == T1_Parse_Start )
@@ -1473,7 +1487,7 @@
/* record vertical hint */
if ( hinter )
{
- top[0] += orig_x;
+ top[0] = ADD_LONG( top[0], orig_x );
hinter->stem( hinter->hints, 0, top );
}
break;
@@ -1487,9 +1501,9 @@
FT_Pos dx = orig_x;
- top[0] += dx;
- top[2] += dx;
- top[4] += dx;
+ top[0] = ADD_LONG( top[0], dx );
+ top[2] = ADD_LONG( top[2], dx );
+ top[4] = ADD_LONG( top[4], dx );
hinter->stem3( hinter->hints, 0, top );
}
break;
diff --git a/thirdparty/freetype/src/psnames/psmodule.c b/thirdparty/freetype/src/psnames/psmodule.c
index 3ff8cb911b..44ba9ec6ab 100644
--- a/thirdparty/freetype/src/psnames/psmodule.c
+++ b/thirdparty/freetype/src/psnames/psmodule.c
@@ -23,8 +23,21 @@
#include "psmodule.h"
+ /*
+ * The file `pstables.h' with its arrays and its function
+ * `ft_get_adobe_glyph_index' is useful for other projects also (for
+ * example, `pdfium' is using it). However, if used as a C++ header,
+ * including it in two different source files makes it necessary to use
+ * `extern const' for the declaration of its arrays, otherwise the data
+ * would be duplicated as mandated by the C++ standard.
+ *
+ * For this reason, we use `DEFINE_PS_TABLES' to guard the function
+ * definitions, and `DEFINE_PS_TABLES_DATA' to provide both proper array
+ * declarations and definitions.
+ */
#include "pstables.h"
#define DEFINE_PS_TABLES
+#define DEFINE_PS_TABLES_DATA
#include "pstables.h"
#include "psnamerr.h"
diff --git a/thirdparty/freetype/src/psnames/pstables.h b/thirdparty/freetype/src/psnames/pstables.h
index e0f5e30804..2a2b717d8f 100644
--- a/thirdparty/freetype/src/psnames/pstables.h
+++ b/thirdparty/freetype/src/psnames/pstables.h
@@ -19,7 +19,7 @@
/* This file has been generated automatically -- do not edit! */
-#ifndef DEFINE_PS_TABLES
+#ifndef DEFINE_PS_TABLES_DATA
#ifdef __cplusplus
extern "C"
#else
@@ -27,7 +27,7 @@
#endif
#endif
const char ft_standard_glyph_names[3696]
-#ifdef DEFINE_PS_TABLES
+#ifdef DEFINE_PS_TABLES_DATA
=
{
'.','n','u','l','l', 0,
@@ -451,7 +451,7 @@
'R','o','m','a','n', 0,
'S','e','m','i','b','o','l','d', 0,
}
-#endif /* DEFINE_PS_TABLES */
+#endif /* DEFINE_PS_TABLES_DATA */
;
@@ -459,7 +459,7 @@
/* Values are offsets into the `ft_standard_glyph_names' table */
-#ifndef DEFINE_PS_TABLES
+#ifndef DEFINE_PS_TABLES_DATA
#ifdef __cplusplus
extern "C"
#else
@@ -467,7 +467,7 @@
#endif
#endif
const short ft_mac_names[FT_NUM_MAC_NAMES]
-#ifdef DEFINE_PS_TABLES
+#ifdef DEFINE_PS_TABLES_DATA
=
{
253, 0, 6, 261, 267, 274, 283, 294, 301, 309, 758, 330, 340, 351,
@@ -490,7 +490,7 @@
1270,1313,1323,1171,1290,1332,1211,1235,1276, 169, 175, 182, 189, 200,
209, 218, 225, 232, 239, 246
}
-#endif /* DEFINE_PS_TABLES */
+#endif /* DEFINE_PS_TABLES_DATA */
;
@@ -498,7 +498,7 @@
/* Values are offsets into the `ft_standard_glyph_names' table */
-#ifndef DEFINE_PS_TABLES
+#ifndef DEFINE_PS_TABLES_DATA
#ifdef __cplusplus
extern "C"
#else
@@ -506,7 +506,7 @@
#endif
#endif
const short ft_sid_names[FT_NUM_SID_NAMES]
-#ifdef DEFINE_PS_TABLES
+#ifdef DEFINE_PS_TABLES_DATA
=
{
253, 261, 267, 274, 283, 294, 301, 309, 319, 330, 340, 351, 360, 365,
@@ -538,12 +538,12 @@
3418,3430,3442,3454,3471,3483,3498,3506,3518,3530,3542,3559,3574,3586,
3597,3612,3620,3628,3636,3644,3650,3655,3660,3666,3673,3681,3687
}
-#endif /* DEFINE_PS_TABLES */
+#endif /* DEFINE_PS_TABLES_DATA */
;
/* the following are indices into the SID name table */
-#ifndef DEFINE_PS_TABLES
+#ifndef DEFINE_PS_TABLES_DATA
#ifdef __cplusplus
extern "C"
#else
@@ -551,7 +551,7 @@
#endif
#endif
const unsigned short t1_standard_encoding[256]
-#ifdef DEFINE_PS_TABLES
+#ifdef DEFINE_PS_TABLES_DATA
=
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -571,12 +571,12 @@
0,138, 0,139, 0, 0, 0, 0,140,141,142,143, 0, 0, 0, 0,
0,144, 0, 0, 0,145, 0, 0,146,147,148,149, 0, 0, 0, 0
}
-#endif /* DEFINE_PS_TABLES */
+#endif /* DEFINE_PS_TABLES_DATA */
;
/* the following are indices into the SID name table */
-#ifndef DEFINE_PS_TABLES
+#ifndef DEFINE_PS_TABLES_DATA
#ifdef __cplusplus
extern "C"
#else
@@ -584,7 +584,7 @@
#endif
#endif
const unsigned short t1_expert_encoding[256]
-#ifdef DEFINE_PS_TABLES
+#ifdef DEFINE_PS_TABLES_DATA
=
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -604,7 +604,7 @@
347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,
363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378
}
-#endif /* DEFINE_PS_TABLES */
+#endif /* DEFINE_PS_TABLES_DATA */
;
@@ -619,7 +619,7 @@
#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
-#ifndef DEFINE_PS_TABLES
+#ifndef DEFINE_PS_TABLES_DATA
#ifdef __cplusplus
extern "C"
#else
@@ -627,7 +627,7 @@
#endif
#endif
const unsigned char ft_adobe_glyph_list[55997L]
-#ifdef DEFINE_PS_TABLES
+#ifdef DEFINE_PS_TABLES_DATA
=
{
0, 52, 0,106, 2,167, 3, 63, 4,220, 6,125, 9,143, 10, 23,
@@ -4131,7 +4131,7 @@
182,117, 2,218,167,218,178,232,233,242,225,231,225,238, 97,128,
48, 90,235,225,244,225,235,225,238, 97,128, 48,186
}
-#endif /* DEFINE_PS_TABLES */
+#endif /* DEFINE_PS_TABLES_DATA */
;
diff --git a/thirdparty/freetype/src/raster/ftrend1.c b/thirdparty/freetype/src/raster/ftrend1.c
index 1a83e9e477..185a7f6fc2 100644
--- a/thirdparty/freetype/src/raster/ftrend1.c
+++ b/thirdparty/freetype/src/raster/ftrend1.c
@@ -31,12 +31,7 @@
static FT_Error
ft_raster1_init( FT_Renderer render )
{
- FT_Library library = FT_MODULE_LIBRARY( render );
-
-
- render->clazz->raster_class->raster_reset( render->raster,
- library->raster_pool,
- library->raster_pool_size );
+ render->clazz->raster_class->raster_reset( render->raster, NULL, 0 );
return FT_Err_Ok;
}
@@ -194,7 +189,7 @@
bitmap->rows = height;
bitmap->pitch = (int)pitch;
- if ( FT_ALLOC_MULT( bitmap->buffer, pitch, height ) )
+ if ( FT_ALLOC_MULT( bitmap->buffer, height, pitch ) )
goto Exit;
slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
diff --git a/thirdparty/freetype/src/sfnt/pngshim.c b/thirdparty/freetype/src/sfnt/pngshim.c
index b9b296ea5f..560db4835a 100644
--- a/thirdparty/freetype/src/sfnt/pngshim.c
+++ b/thirdparty/freetype/src/sfnt/pngshim.c
@@ -49,18 +49,82 @@
}
- /* Premultiplies data and converts RGBA bytes => native endian. */
+ /* Premultiplies data and converts RGBA bytes => BGRA. */
static void
premultiply_data( png_structp png,
png_row_infop row_info,
png_bytep data )
{
- unsigned int i;
+ unsigned int i = 0, limit;
+
+ /* The `vector_size' attribute was introduced in gcc 3.1, which */
+ /* predates clang; the `__BYTE_ORDER__' preprocessor symbol was */
+ /* introduced in gcc 4.6 and clang 3.2, respectively. */
+ /* `__builtin_shuffle' for gcc was introduced in gcc 4.7.0. */
+#if ( ( defined( __GNUC__ ) && \
+ ( ( __GNUC__ >= 5 ) || \
+ ( ( __GNUC__ == 4 ) && ( __GNUC_MINOR__ >= 7 ) ) ) ) || \
+ ( defined( __clang__ ) && \
+ ( ( __clang_major__ >= 4 ) || \
+ ( ( __clang_major__ == 3 ) && ( __clang_minor__ >= 2 ) ) ) ) ) && \
+ defined( __OPTIMIZE__ ) && \
+ __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+
+#ifdef __clang__
+ /* the clang documentation doesn't cover the two-argument case of */
+ /* `__builtin_shufflevector'; however, it is is implemented since */
+ /* version 2.8 */
+#define vector_shuffle __builtin_shufflevector
+#else
+#define vector_shuffle __builtin_shuffle
+#endif
- FT_UNUSED( png );
+ typedef unsigned short v82 __attribute__(( vector_size( 16 ) ));
- for ( i = 0; i < row_info->rowbytes; i += 4 )
+ /* process blocks of 16 bytes in one rush, which gives a nice speed-up */
+ limit = row_info->rowbytes - 16 + 1;
+ for ( ; i < limit; i += 16 )
+ {
+ unsigned char* base = &data[i];
+
+ v82 s, s0, s1, a;
+
+ /* clang <= 3.9 can't apply scalar values to vectors */
+ /* (or rather, it needs a different syntax) */
+ v82 n0x80 = { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 };
+ v82 n0xFF = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+ v82 n8 = { 8, 8, 8, 8, 8, 8, 8, 8 };
+
+ v82 ma = { 1, 1, 3, 3, 5, 5, 7, 7 };
+ v82 o1 = { 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF };
+ v82 m0 = { 1, 0, 3, 2, 5, 4, 7, 6 };
+
+
+ memcpy( &s, base, 16 ); /* RGBA RGBA RGBA RGBA */
+ s0 = s & n0xFF; /* R B R B R B R B */
+ s1 = s >> n8; /* G A G A G A G A */
+
+ a = vector_shuffle( s1, ma ); /* A A A A A A A A */
+ s1 |= o1; /* G 1 G 1 G 1 G 1 */
+ s0 = vector_shuffle( s0, m0 ); /* B R B R B R B R */
+
+ s0 *= a;
+ s1 *= a;
+ s0 += n0x80;
+ s1 += n0x80;
+ s0 = ( s0 + ( s0 >> n8 ) ) >> n8;
+ s1 = ( s1 + ( s1 >> n8 ) ) >> n8;
+
+ s = s0 | ( s1 << n8 );
+ memcpy( base, &s, 16 );
+ }
+#endif /* use `vector_size' */
+
+ FT_UNUSED( png );
+
+ limit = row_info->rowbytes;
+ for ( ; i < limit; i += 4 )
{
unsigned char* base = &data[i];
unsigned int alpha = base[3];
diff --git a/thirdparty/freetype/src/sfnt/sfobjs.c b/thirdparty/freetype/src/sfnt/sfobjs.c
index ac2e620e5d..69bf0a5c3d 100644
--- a/thirdparty/freetype/src/sfnt/sfobjs.c
+++ b/thirdparty/freetype/src/sfnt/sfobjs.c
@@ -787,6 +787,8 @@
tag != TTAG_OTTO &&
tag != TTAG_true &&
tag != TTAG_typ1 &&
+ tag != TTAG_0xA5kbd &&
+ tag != TTAG_0xA5lst &&
tag != 0x00020000UL )
{
FT_TRACE2(( " not a font using the SFNT container format\n" ));
@@ -1224,7 +1226,10 @@
goto Exit;
}
- if ( face->header.Units_Per_EM == 0 )
+ /* OpenType 1.8.2 introduced limits to this value; */
+ /* however, they make sense for older SFNT fonts also */
+ if ( face->header.Units_Per_EM < 16 ||
+ face->header.Units_Per_EM > 16384 )
{
error = FT_THROW( Invalid_Table );
@@ -1464,7 +1469,8 @@
/* Polish the charmaps. */
/* */
/* Try to set the charmap encoding according to the platform & */
- /* encoding ID of each charmap. */
+ /* encoding ID of each charmap. Emulate Unicode charmap if one */
+ /* is missing. */
/* */
tt_face_build_cmaps( face ); /* ignore errors */
@@ -1472,7 +1478,10 @@
/* set the encoding fields */
{
- FT_Int m;
+ FT_Int m;
+#ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
+ FT_Bool has_unicode = FALSE;
+#endif
for ( m = 0; m < root->num_charmaps; m++ )
@@ -1483,14 +1492,34 @@
charmap->encoding = sfnt_find_encoding( charmap->platform_id,
charmap->encoding_id );
-#if 0
- if ( !root->charmap &&
- charmap->encoding == FT_ENCODING_UNICODE )
- {
- /* set 'root->charmap' to the first Unicode encoding we find */
- root->charmap = charmap;
- }
-#endif
+#ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
+
+ if ( charmap->encoding == FT_ENCODING_UNICODE ||
+ charmap->encoding == FT_ENCODING_MS_SYMBOL ) /* PUA */
+ has_unicode = TRUE;
+ }
+
+ /* synthesize Unicode charmap if one is missing */
+ if ( !has_unicode )
+ {
+ FT_CharMapRec cmaprec;
+
+
+ cmaprec.face = root;
+ cmaprec.platform_id = TT_PLATFORM_MICROSOFT;
+ cmaprec.encoding_id = TT_MS_ID_UNICODE_CS;
+ cmaprec.encoding = FT_ENCODING_UNICODE;
+
+
+ error = FT_CMap_New( (FT_CMap_Class)&tt_cmap_unicode_class_rec,
+ NULL, &cmaprec, NULL );
+ if ( error &&
+ FT_ERR_NEQ( error, No_Unicode_Glyph_Name ) )
+ goto Exit;
+ error = FT_Err_Ok;
+
+#endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */
+
}
}
diff --git a/thirdparty/freetype/src/sfnt/ttcmap.c b/thirdparty/freetype/src/sfnt/ttcmap.c
index 5afa6ae4b7..b995e5c050 100644
--- a/thirdparty/freetype/src/sfnt/ttcmap.c
+++ b/thirdparty/freetype/src/sfnt/ttcmap.c
@@ -23,8 +23,10 @@
#include FT_INTERNAL_VALIDATE_H
#include FT_INTERNAL_STREAM_H
+#include FT_SERVICE_POSTSCRIPT_CMAPS_H
#include "ttload.h"
#include "ttcmap.h"
+#include "ttpost.h"
#include "sfntpic.h"
@@ -3622,6 +3624,110 @@
#endif /* TT_CONFIG_CMAP_FORMAT_14 */
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** SYNTHETIC UNICODE *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /* This charmap is generated using postscript glyph names. */
+
+#ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
+
+ FT_CALLBACK_DEF( const char * )
+ tt_get_glyph_name( TT_Face face,
+ FT_UInt idx )
+ {
+ FT_String* PSname;
+
+
+ tt_face_get_ps_name( face, idx, &PSname );
+
+ return PSname;
+ }
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ tt_cmap_unicode_init( PS_Unicodes unicodes,
+ FT_Pointer pointer )
+ {
+ TT_Face face = (TT_Face)FT_CMAP_FACE( unicodes );
+ FT_Memory memory = FT_FACE_MEMORY( face );
+ FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames;
+
+ FT_UNUSED( pointer );
+
+
+ return psnames->unicodes_init( memory,
+ unicodes,
+ face->root.num_glyphs,
+ (PS_GetGlyphNameFunc)&tt_get_glyph_name,
+ (PS_FreeGlyphNameFunc)NULL,
+ (FT_Pointer)face );
+ }
+
+
+ FT_CALLBACK_DEF( void )
+ tt_cmap_unicode_done( PS_Unicodes unicodes )
+ {
+ FT_Face face = FT_CMAP_FACE( unicodes );
+ FT_Memory memory = FT_FACE_MEMORY( face );
+
+
+ FT_FREE( unicodes->maps );
+ unicodes->num_maps = 0;
+ }
+
+
+ FT_CALLBACK_DEF( FT_UInt )
+ tt_cmap_unicode_char_index( PS_Unicodes unicodes,
+ FT_UInt32 char_code )
+ {
+ TT_Face face = (TT_Face)FT_CMAP_FACE( unicodes );
+ FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames;
+
+
+ return psnames->unicodes_char_index( unicodes, char_code );
+ }
+
+
+ FT_CALLBACK_DEF( FT_UInt32 )
+ tt_cmap_unicode_char_next( PS_Unicodes unicodes,
+ FT_UInt32 *pchar_code )
+ {
+ TT_Face face = (TT_Face)FT_CMAP_FACE( unicodes );
+ FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames;
+
+
+ return psnames->unicodes_char_next( unicodes, pchar_code );
+ }
+
+
+ FT_DEFINE_TT_CMAP(
+ tt_cmap_unicode_class_rec,
+
+ sizeof ( PS_UnicodesRec ),
+
+ (FT_CMap_InitFunc) tt_cmap_unicode_init, /* init */
+ (FT_CMap_DoneFunc) tt_cmap_unicode_done, /* done */
+ (FT_CMap_CharIndexFunc)tt_cmap_unicode_char_index, /* char_index */
+ (FT_CMap_CharNextFunc) tt_cmap_unicode_char_next, /* char_next */
+
+ (FT_CMap_CharVarIndexFunc) NULL, /* char_var_index */
+ (FT_CMap_CharVarIsDefaultFunc)NULL, /* char_var_default */
+ (FT_CMap_VariantListFunc) NULL, /* variant_list */
+ (FT_CMap_CharVariantListFunc) NULL, /* charvariant_list */
+ (FT_CMap_VariantCharListFunc) NULL, /* variantchar_list */
+
+ ~0U,
+ (TT_CMap_ValidateFunc)NULL, /* validate */
+ (TT_CMap_Info_GetFunc)NULL /* get_cmap_info */
+ )
+
+#endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */
+
#ifndef FT_CONFIG_OPTION_PIC
static const TT_CMap_Class tt_cmap_classes[] =
@@ -3801,8 +3907,10 @@
FT_CMap cmap = (FT_CMap)charmap;
TT_CMap_Class clazz = (TT_CMap_Class)cmap->clazz;
-
- return clazz->get_cmap_info( charmap, cmap_info );
+ if ( clazz->get_cmap_info )
+ return clazz->get_cmap_info( charmap, cmap_info );
+ else
+ return FT_THROW( Invalid_CharMap_Format );
}
diff --git a/thirdparty/freetype/src/sfnt/ttcmap.h b/thirdparty/freetype/src/sfnt/ttcmap.h
index 83f12df241..f7de0437b0 100644
--- a/thirdparty/freetype/src/sfnt/ttcmap.h
+++ b/thirdparty/freetype/src/sfnt/ttcmap.h
@@ -141,6 +141,8 @@ FT_BEGIN_HEADER
#define TT_VALID_GLYPH_COUNT( x ) TT_VALIDATOR( x )->num_glyphs
+ FT_CALLBACK_TABLE const TT_CMap_ClassRec tt_cmap_unicode_class_rec;
+
FT_LOCAL( FT_Error )
tt_face_build_cmaps( TT_Face face );
diff --git a/thirdparty/freetype/src/sfnt/ttkern.c b/thirdparty/freetype/src/sfnt/ttkern.c
index c97e5789ac..53d2436ae5 100644
--- a/thirdparty/freetype/src/sfnt/ttkern.c
+++ b/thirdparty/freetype/src/sfnt/ttkern.c
@@ -85,7 +85,7 @@
for ( nn = 0; nn < num_tables; nn++ )
{
- FT_UInt num_pairs, length, coverage;
+ FT_UInt num_pairs, length, coverage, format;
FT_Byte* p_next;
FT_UInt32 mask = (FT_UInt32)1UL << nn;
@@ -107,6 +107,12 @@
if ( p_next > p_limit ) /* handle broken table */
p_next = p_limit;
+ format = coverage >> 8;
+
+ /* we currently only support format 0 kerning tables */
+ if ( format != 0 )
+ goto NextTable;
+
/* only use horizontal kerning tables */
if ( ( coverage & 3U ) != 0x0001 ||
p + 8 > p_next )
diff --git a/thirdparty/freetype/src/sfnt/ttpost.c b/thirdparty/freetype/src/sfnt/ttpost.c
index 540d5f2546..69929c8d45 100644
--- a/thirdparty/freetype/src/sfnt/ttpost.c
+++ b/thirdparty/freetype/src/sfnt/ttpost.c
@@ -325,7 +325,6 @@
FT_UNUSED( post_limit );
- /* UNDOCUMENTED! This value appears only in the Apple TT specs. */
if ( FT_READ_USHORT( num_glyphs ) )
goto Exit;
@@ -408,7 +407,7 @@
/* now read postscript table */
if ( format == 0x00020000L )
error = load_format_20( face, stream, post_limit );
- else if ( format == 0x00028000L )
+ else if ( format == 0x00025000L )
error = load_format_25( face, stream, post_limit );
else
error = FT_THROW( Invalid_File_Format );
@@ -447,7 +446,7 @@
FT_FREE( table->glyph_names );
table->num_names = 0;
}
- else if ( format == 0x00028000L )
+ else if ( format == 0x00025000L )
{
TT_Post_25 table = &names->names.format_25;
@@ -543,7 +542,7 @@
*PSname = (FT_String*)table->glyph_names[name_index - 258];
}
}
- else if ( format == 0x00028000L )
+ else if ( format == 0x00025000L )
{
TT_Post_25 table = &names->names.format_25;
diff --git a/thirdparty/freetype/src/sfnt/ttsbit.c b/thirdparty/freetype/src/sfnt/ttsbit.c
index 0c76a55779..f41847b0af 100644
--- a/thirdparty/freetype/src/sfnt/ttsbit.c
+++ b/thirdparty/freetype/src/sfnt/ttsbit.c
@@ -448,6 +448,15 @@
metrics->max_advance =
FT_MulDiv( hori->advance_Width_Max, ppem_ * 64, upem );
+ /* set the scale values (in 16.16 units) so advances */
+ /* from the hmtx and vmtx table are scaled correctly */
+ metrics->x_scale = FT_MulDiv( metrics->x_ppem,
+ 64 * 0x10000,
+ face->header.Units_Per_EM );
+ metrics->y_scale = FT_MulDiv( metrics->y_ppem,
+ 64 * 0x10000,
+ face->header.Units_Per_EM );
+
return error;
}
@@ -1439,10 +1448,17 @@
return FT_THROW( Invalid_Table );
NoBitmap:
+ if ( recurse_count )
+ {
+ FT_TRACE4(( "tt_sbit_decoder_load_image:"
+ " missing subglyph sbit with glyph index %d\n",
+ glyph_index ));
+ return FT_THROW( Invalid_Composite );
+ }
+
FT_TRACE4(( "tt_sbit_decoder_load_image:"
" no sbit found for glyph index %d\n", glyph_index ));
-
- return FT_THROW( Invalid_Argument );
+ return FT_THROW( Missing_Bitmap );
}
diff --git a/thirdparty/freetype/src/smooth/ftgrays.c b/thirdparty/freetype/src/smooth/ftgrays.c
index e9a3ce7a7c..df645e66c9 100644
--- a/thirdparty/freetype/src/smooth/ftgrays.c
+++ b/thirdparty/freetype/src/smooth/ftgrays.c
@@ -141,6 +141,16 @@
#define FT_INT_MAX INT_MAX
#define FT_ULONG_MAX ULONG_MAX
+#define ADD_LONG( a, b ) \
+ (long)( (unsigned long)(a) + (unsigned long)(b) )
+#define SUB_LONG( a, b ) \
+ (long)( (unsigned long)(a) - (unsigned long)(b) )
+#define MUL_LONG( a, b ) \
+ (long)( (unsigned long)(a) * (unsigned long)(b) )
+#define NEG_LONG( a ) \
+ (long)( -(unsigned long)(a) )
+
+
#define ft_memset memset
#define ft_setjmp setjmp
@@ -264,6 +274,7 @@ typedef ptrdiff_t FT_PtrDist;
#include "ftgrays.h"
#include FT_INTERNAL_OBJECTS_H
#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_CALC_H
#include FT_OUTLINE_H
#include "ftsmerrs.h"
@@ -1135,7 +1146,7 @@ typedef ptrdiff_t FT_PtrDist;
/* s is L * the perpendicular distance from P1 to the line P0-P3. */
dx1 = arc[1].x - arc[0].x;
dy1 = arc[1].y - arc[0].y;
- s = FT_ABS( dy * dx1 - dx * dy1 );
+ s = FT_ABS( SUB_LONG( MUL_LONG( dy, dx1 ), MUL_LONG( dx, dy1 ) ) );
if ( s > s_limit )
goto Split;
@@ -1143,7 +1154,7 @@ typedef ptrdiff_t FT_PtrDist;
/* s is L * the perpendicular distance from P2 to the line P0-P3. */
dx2 = arc[2].x - arc[0].x;
dy2 = arc[2].y - arc[0].y;
- s = FT_ABS( dy * dx2 - dx * dy2 );
+ s = FT_ABS( SUB_LONG( MUL_LONG( dy, dx2 ), MUL_LONG( dx, dy2 ) ) );
if ( s > s_limit )
goto Split;
diff --git a/thirdparty/freetype/src/smooth/ftsmooth.c b/thirdparty/freetype/src/smooth/ftsmooth.c
index 435854e673..963435de15 100644
--- a/thirdparty/freetype/src/smooth/ftsmooth.c
+++ b/thirdparty/freetype/src/smooth/ftsmooth.c
@@ -31,12 +31,7 @@
static FT_Error
ft_smooth_init( FT_Renderer render )
{
- FT_Library library = FT_MODULE_LIBRARY( render );
-
-
- render->clazz->raster_class->raster_reset( render->raster,
- library->raster_pool,
- library->raster_pool_size );
+ render->clazz->raster_class->raster_reset( render->raster, NULL, 0 );
return 0;
}
@@ -111,9 +106,6 @@
FT_Pos y_shift = 0;
FT_Pos x_left, y_top;
FT_Pos width, height, pitch;
-#ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
- FT_Pos height_org, width_org;
-#endif
FT_Int hmul = ( mode == FT_RENDER_MODE_LCD );
FT_Int vmul = ( mode == FT_RENDER_MODE_LCD_V );
@@ -124,7 +116,6 @@
#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
- FT_Int lcd_extra = 0;
FT_LcdFiveTapFilter lcd_weights = { 0 };
FT_Bool have_custom_weight = FALSE;
FT_Bitmap_LcdFilterFunc lcd_filter_func = NULL;
@@ -152,13 +143,12 @@
{
/*
* A per-font filter is set. It always uses the default 5-tap
- * in-place FIR filter that needs 2 extra pixels.
+ * in-place FIR filter.
*/
ft_memcpy( lcd_weights,
slot->face->internal->lcd_weights,
FT_LCD_FILTER_FIVE_TAPS );
lcd_filter_func = ft_lcd_filter_fir;
- lcd_extra = 2;
}
else
{
@@ -172,7 +162,6 @@
slot->library->lcd_weights,
FT_LCD_FILTER_FIVE_TAPS );
lcd_filter_func = slot->library->lcd_filter_func;
- lcd_extra = slot->library->lcd_extra;
}
#endif /*FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
@@ -201,6 +190,45 @@
/* taking into account the origin shift */
FT_Outline_Get_CBox( outline, &cbox );
+#ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
+
+ /* add minimal padding for LCD rendering */
+ if ( hmul )
+ {
+ cbox.xMax += 21;
+ cbox.xMin -= 21;
+ }
+
+ if ( vmul )
+ {
+ cbox.yMax += 21;
+ cbox.yMin -= 21;
+ }
+
+#else /* FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
+
+ /* add minimal padding for LCD filter depending on specific weights */
+ if ( lcd_filter_func )
+ {
+ if ( hmul )
+ {
+ cbox.xMax += lcd_weights[4] ? 43
+ : lcd_weights[3] ? 22 : 0;
+ cbox.xMin -= lcd_weights[0] ? 43
+ : lcd_weights[1] ? 22 : 0;
+ }
+
+ if ( vmul )
+ {
+ cbox.yMax += lcd_weights[4] ? 43
+ : lcd_weights[3] ? 22 : 0;
+ cbox.yMin -= lcd_weights[0] ? 43
+ : lcd_weights[1] ? 22 : 0;
+ }
+ }
+
+#endif /* FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
+
cbox.xMin = FT_PIX_FLOOR( cbox.xMin + x_shift );
cbox.yMin = FT_PIX_FLOOR( cbox.yMin + y_shift );
cbox.xMax = FT_PIX_CEIL( cbox.xMax + x_shift );
@@ -215,11 +243,6 @@
width = (FT_ULong)( cbox.xMax - cbox.xMin ) >> 6;
height = (FT_ULong)( cbox.yMax - cbox.yMin ) >> 6;
-#ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
- width_org = width;
- height_org = height;
-#endif
-
pitch = width;
if ( hmul )
{
@@ -230,26 +253,6 @@
if ( vmul )
height *= 3;
-#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
- if ( lcd_filter_func )
- {
- if ( hmul )
- {
- x_shift += 64 * ( lcd_extra >> 1 );
- x_left -= lcd_extra >> 1;
- width += 3 * lcd_extra;
- pitch = FT_PAD_CEIL( width, 4 );
- }
-
- if ( vmul )
- {
- y_shift += 64 * ( lcd_extra >> 1 );
- y_top += lcd_extra >> 1;
- height += 3 * lcd_extra;
- }
- }
-#endif
-
/*
* XXX: on 16bit system, we return an error for huge bitmap
* to prevent an overflow.
@@ -353,57 +356,98 @@
#else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
- /* render outline into bitmap */
- error = render->raster_render( render->raster, &params );
- if ( error )
- goto Exit;
-
- /* expand it horizontally */
- if ( hmul )
+ if ( hmul ) /* lcd */
{
- FT_Byte* line = bitmap->buffer;
- FT_UInt hh;
+ FT_Byte* line;
+ FT_Byte* temp;
+ FT_Int i, j;
- for ( hh = height_org; hh > 0; hh--, line += pitch )
- {
- FT_UInt xx;
- FT_Byte* end = line + width;
+ /* Render 3 separate monochrome bitmaps, shifting the outline */
+ /* by 1/3 pixel. */
+ width /= 3;
+ FT_Outline_Translate( outline, 21, 0 );
- for ( xx = width_org; xx > 0; xx-- )
- {
- FT_UInt pixel = line[xx-1];
+ error = render->raster_render( render->raster, &params );
+ if ( error )
+ goto Exit;
+
+ FT_Outline_Translate( outline, -21, 0 );
+ bitmap->buffer += width;
+
+ error = render->raster_render( render->raster, &params );
+ if ( error )
+ goto Exit;
+
+ FT_Outline_Translate( outline, -21, 0 );
+ bitmap->buffer += width;
+ error = render->raster_render( render->raster, &params );
+ if ( error )
+ goto Exit;
- end[-3] = (FT_Byte)pixel;
- end[-2] = (FT_Byte)pixel;
- end[-1] = (FT_Byte)pixel;
- end -= 3;
+ FT_Outline_Translate( outline, 21, 0 );
+ bitmap->buffer -= 2 * width;
+
+ /* XXX: Rearrange the bytes according to FT_PIXEL_MODE_LCD. */
+ /* XXX: It is more efficient to render every third byte above. */
+
+ if ( FT_ALLOC( temp, (FT_ULong)pitch ) )
+ goto Exit;
+
+ for ( i = 0; i < height; i++ )
+ {
+ line = bitmap->buffer + i * pitch;
+ for ( j = 0; j < width; j++ )
+ {
+ temp[3 * j ] = line[j];
+ temp[3 * j + 1] = line[j + width];
+ temp[3 * j + 2] = line[j + width + width];
}
+ FT_MEM_COPY( line, temp, pitch );
}
- }
- /* expand it vertically */
- if ( vmul )
+ FT_FREE( temp );
+ }
+ else if ( vmul ) /* lcd_v */
{
- FT_Byte* read = bitmap->buffer + ( height - height_org ) * pitch;
- FT_Byte* write = bitmap->buffer;
- FT_UInt hh;
+ /* Render 3 separate monochrome bitmaps, shifting the outline */
+ /* by 1/3 pixel. Triple the pitch to render on each third row. */
+ bitmap->pitch *= 3;
+ bitmap->rows /= 3;
+ FT_Outline_Translate( outline, 0, 21 );
+ bitmap->buffer += 2 * pitch;
- for ( hh = height_org; hh > 0; hh-- )
- {
- ft_memcpy( write, read, pitch );
- write += pitch;
+ error = render->raster_render( render->raster, &params );
+ if ( error )
+ goto Exit;
- ft_memcpy( write, read, pitch );
- write += pitch;
+ FT_Outline_Translate( outline, 0, -21 );
+ bitmap->buffer -= pitch;
- ft_memcpy( write, read, pitch );
- write += pitch;
- read += pitch;
- }
+ error = render->raster_render( render->raster, &params );
+ if ( error )
+ goto Exit;
+
+ FT_Outline_Translate( outline, 0, -21 );
+ bitmap->buffer -= pitch;
+
+ error = render->raster_render( render->raster, &params );
+ if ( error )
+ goto Exit;
+
+ FT_Outline_Translate( outline, 0, 21 );
+
+ bitmap->pitch /= 3;
+ bitmap->rows *= 3;
+ }
+ else /* grayscale */
+ {
+ error = render->raster_render( render->raster, &params );
+ if ( error )
+ goto Exit;
}
#endif /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
diff --git a/thirdparty/freetype/src/truetype/ttgload.c b/thirdparty/freetype/src/truetype/ttgload.c
index b7a844a6c7..5e102c6151 100644
--- a/thirdparty/freetype/src/truetype/ttgload.c
+++ b/thirdparty/freetype/src/truetype/ttgload.c
@@ -87,7 +87,7 @@
/*************************************************************************/
/* */
/* Return the vertical metrics in font units for a given glyph. */
- /* See macro `TT_LOADER_SET_PP' below for explanations. */
+ /* See function `tt_loader_set_pp' below for explanations. */
/* */
FT_LOCAL_DEF( void )
TT_Get_VMetrics( TT_Face face,
@@ -825,7 +825,7 @@
/* compatibility mode, where no movement on the x axis means no reason */
/* to change bearings or advance widths. */
if ( !( driver->interpreter_version == TT_INTERPRETER_VERSION_40 &&
- !loader->exec->backward_compatibility ) )
+ loader->exec->backward_compatibility ) )
{
#endif
loader->pp1 = zone->cur[zone->n_points - 4];
@@ -1686,7 +1686,7 @@
/***********************************************************************/
/* otherwise, load a composite! */
- else if ( loader->n_contours == -1 )
+ else if ( loader->n_contours < 0 )
{
FT_Memory memory = face->root.memory;
@@ -1697,6 +1697,9 @@
FT_ListNode node, node2;
+ /* normalize the `n_contours' value */
+ loader->n_contours = -1;
+
/*
* We store the glyph index directly in the `node->data' pointer,
* following the glib solution (cf. macro `GUINT_TO_POINTER') with a
@@ -1991,12 +1994,6 @@
}
}
}
- else
- {
- /* invalid composite count (negative but not -1) */
- error = FT_THROW( Invalid_Outline );
- goto Exit;
- }
/***********************************************************************/
/***********************************************************************/
@@ -2100,8 +2097,8 @@
}
/* set glyph dimensions */
- glyph->metrics.width = bbox.xMax - bbox.xMin;
- glyph->metrics.height = bbox.yMax - bbox.yMin;
+ glyph->metrics.width = SUB_LONG( bbox.xMax, bbox.xMin );
+ glyph->metrics.height = SUB_LONG( bbox.yMax, bbox.yMin );
/* Now take care of vertical metrics. In the case where there is */
/* no vertical information within the font (relatively common), */
@@ -2137,7 +2134,8 @@
/* table in the font. Otherwise, we use the */
/* values defined in the horizontal header. */
- height = (FT_Short)FT_DivFix( bbox.yMax - bbox.yMin,
+ height = (FT_Short)FT_DivFix( SUB_LONG( bbox.yMax,
+ bbox.yMin ),
y_scale );
if ( face->os2.version != 0xFFFFU )
advance = (FT_Pos)( face->os2.sTypoAscender -
@@ -2339,13 +2337,19 @@
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 )
{
- subpixel_hinting_lean = TRUE;
- grayscale_cleartype = !FT_BOOL( load_flags &
- FT_LOAD_TARGET_LCD ||
- load_flags &
- FT_LOAD_TARGET_LCD_V );
- exec->vertical_lcd_lean = FT_BOOL( load_flags &
- FT_LOAD_TARGET_LCD_V );
+ subpixel_hinting_lean =
+ FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
+ FT_RENDER_MODE_MONO );
+ grayscale_cleartype =
+ FT_BOOL( subpixel_hinting_lean &&
+ !( ( load_flags &
+ FT_LOAD_TARGET_LCD ) ||
+ ( load_flags &
+ FT_LOAD_TARGET_LCD_V ) ) );
+ exec->vertical_lcd_lean =
+ FT_BOOL( subpixel_hinting_lean &&
+ ( load_flags &
+ FT_LOAD_TARGET_LCD_V ) );
}
else
{
@@ -2621,7 +2625,64 @@
IS_DEFAULT_INSTANCE )
{
error = load_sbit_image( size, glyph, glyph_index, load_flags );
- if ( !error )
+ if ( FT_ERR_EQ( error, Missing_Bitmap ) )
+ {
+ /* the bitmap strike is incomplete and misses the requested glyph; */
+ /* if we have a bitmap-only font, return an empty glyph */
+ if ( !FT_IS_SCALABLE( glyph->face ) )
+ {
+ TT_Face face = (TT_Face)glyph->face;
+ FT_Short left_bearing = 0, top_bearing = 0;
+ FT_UShort advance_width = 0, advance_height = 0;
+
+
+ /* to return an empty glyph, however, we need metrics data */
+ /* from the `hmtx' (or `vmtx') table; the assumption is that */
+ /* empty glyphs are missing intentionally, representing */
+ /* whitespace - not having at least horizontal metrics is */
+ /* thus considered an error */
+ if ( !face->horz_metrics_size )
+ return error;
+
+ /* we now construct an empty bitmap glyph */
+ TT_Get_HMetrics( face, glyph_index,
+ &left_bearing,
+ &advance_width );
+ TT_Get_VMetrics( face, glyph_index,
+ 0,
+ &top_bearing,
+ &advance_height );
+
+ glyph->outline.n_points = 0;
+ glyph->outline.n_contours = 0;
+
+ glyph->metrics.width = 0;
+ glyph->metrics.height = 0;
+
+ glyph->metrics.horiBearingX = left_bearing;
+ glyph->metrics.horiBearingY = 0;
+ glyph->metrics.horiAdvance = advance_width;
+
+ glyph->metrics.vertBearingX = 0;
+ glyph->metrics.vertBearingY = top_bearing;
+ glyph->metrics.vertAdvance = advance_height;
+
+ glyph->format = FT_GLYPH_FORMAT_BITMAP;
+ glyph->bitmap.pixel_mode = FT_PIXEL_MODE_MONO;
+
+ glyph->bitmap_left = 0;
+ glyph->bitmap_top = 0;
+
+ return FT_Err_Ok;
+ }
+ }
+ else if ( error )
+ {
+ /* return error if font is not scalable */
+ if ( !FT_IS_SCALABLE( glyph->face ) )
+ return error;
+ }
+ else
{
if ( FT_IS_SCALABLE( glyph->face ) )
{
diff --git a/thirdparty/freetype/src/truetype/ttgxvar.c b/thirdparty/freetype/src/truetype/ttgxvar.c
index 0cedb6bdfa..49aa53a687 100644
--- a/thirdparty/freetype/src/truetype/ttgxvar.c
+++ b/thirdparty/freetype/src/truetype/ttgxvar.c
@@ -60,8 +60,11 @@
#define FT_Stream_FTell( stream ) \
(FT_ULong)( (stream)->cursor - (stream)->base )
-#define FT_Stream_SeekSet( stream, off ) \
- ( (stream)->cursor = (stream)->base + (off) )
+#define FT_Stream_SeekSet( stream, off ) \
+ (stream)->cursor = \
+ ( (off) < (FT_ULong)( (stream)->limit - (stream)->base ) ) \
+ ? (stream)->base + (off) \
+ : (stream)->limit
/*************************************************************************/
@@ -392,14 +395,14 @@
/* some macros we need */
- #define FT_FIXED_ONE ( (FT_Fixed)0x10000 )
+#define FT_FIXED_ONE ( (FT_Fixed)0x10000 )
- #define FT_fdot14ToFixed( x ) \
- ( (FT_Fixed)( (FT_ULong)(x) << 2 ) )
- #define FT_intToFixed( i ) \
- ( (FT_Fixed)( (FT_ULong)(i) << 16 ) )
- #define FT_fixedToInt( x ) \
- ( (FT_Short)( ( (FT_UInt32)(x) + 0x8000U ) >> 16 ) )
+#define FT_fdot14ToFixed( x ) \
+ ( (FT_Fixed)( (FT_ULong)(x) << 2 ) )
+#define FT_intToFixed( i ) \
+ ( (FT_Fixed)( (FT_ULong)(i) << 16 ) )
+#define FT_fixedToInt( x ) \
+ ( (FT_Short)( ( (FT_UInt32)(x) + 0x8000U ) >> 16 ) )
static FT_Error
@@ -1953,6 +1956,7 @@
GX_FVar_Head fvar_head;
FT_Bool usePsName;
FT_UInt num_instances;
+ FT_UShort* axis_flags;
static const FT_Frame_Field fvar_fields[] =
{
@@ -2038,14 +2042,16 @@
/* in fvar's table of named instances */
num_instances = face->root.style_flags >> 16;
- /* cannot overflow 32-bit arithmetic because of the size limits */
- /* used in the `fvar' table validity check in `sfnt_init_face' */
+ /* prepare storage area for MM data; this cannot overflow */
+ /* 32-bit arithmetic because of the size limits used in the */
+ /* `fvar' table validity check in `sfnt_init_face' */
face->blend->mmvar_len =
sizeof ( FT_MM_Var ) +
+ fvar_head.axisCount * sizeof ( FT_UShort ) +
fvar_head.axisCount * sizeof ( FT_Var_Axis ) +
num_instances * sizeof ( FT_Var_Named_Style ) +
num_instances * fvar_head.axisCount * sizeof ( FT_Fixed ) +
- 5 * fvar_head.axisCount;
+ fvar_head.axisCount * 5;
if ( FT_ALLOC( mmvar, face->blend->mmvar_len ) )
goto Exit;
@@ -2062,8 +2068,12 @@
/* (or tuples, as called by Apple) */
mmvar->num_namedstyles =
num_instances;
+
+ /* alas, no public field in `FT_Var_Axis' for axis flags */
+ axis_flags =
+ (FT_UShort*)&( mmvar[1] );
mmvar->axis =
- (FT_Var_Axis*)&( mmvar[1] );
+ (FT_Var_Axis*)&( axis_flags[fvar_head.axisCount] );
mmvar->namedstyle =
(FT_Var_Named_Style*)&( mmvar->axis[fvar_head.axisCount] );
@@ -2107,6 +2117,8 @@
a->name[3] = (FT_String)( ( a->tag ) & 0xFF );
a->name[4] = '\0';
+ *axis_flags = axis_rec.flags;
+
if ( a->minimum > a->def ||
a->def > a->maximum )
{
@@ -2118,13 +2130,17 @@
a->maximum = a->def;
}
- FT_TRACE5(( " \"%s\": minimum=%.5f, default=%.5f, maximum=%.5f\n",
+ FT_TRACE5(( " \"%s\":"
+ " minimum=%.5f, default=%.5f, maximum=%.5f,"
+ " flags=0x%04X\n",
a->name,
a->minimum / 65536.0,
a->def / 65536.0,
- a->maximum / 65536.0 ));
+ a->maximum / 65536.0,
+ *axis_flags ));
a++;
+ axis_flags++;
}
FT_TRACE5(( "\n" ));
@@ -2136,8 +2152,16 @@
goto Exit;
if ( fvar_head.instanceCount && !face->blend->avar_loaded )
+ {
+ FT_ULong offset = FT_STREAM_POS();
+
+
ft_var_load_avar( face );
+ if ( FT_STREAM_SEEK( offset ) )
+ goto Exit;
+ }
+
ns = mmvar->namedstyle;
nsc = face->blend->normalized_stylecoords;
for ( i = 0; i < fvar_head.instanceCount; i++, ns++ )
@@ -2154,8 +2178,11 @@
for ( j = 0; j < fvar_head.axisCount; j++, c++ )
*c = FT_GET_LONG();
+ /* valid psid values are 6, [256;32767], and 0xFFFF */
if ( usePsName )
ns->psid = FT_GET_USHORT();
+ else
+ ns->psid = 0xFFFF;
ft_var_to_normalized( face,
fvar_head.axisCount,
@@ -2171,7 +2198,7 @@
SFNT_Service sfnt = (SFNT_Service)face->sfnt;
FT_Int found, dummy1, dummy2;
- FT_UInt strid = 0xFFFFFFFFUL;
+ FT_UInt strid = ~0U;
/* the default instance is missing in array the */
@@ -2230,13 +2257,15 @@
goto Exit;
FT_MEM_COPY( mmvar, face->blend->mmvar, face->blend->mmvar_len );
+ axis_flags =
+ (FT_UShort*)&( mmvar[1] );
mmvar->axis =
- (FT_Var_Axis*)&( mmvar[1] );
+ (FT_Var_Axis*)&( axis_flags[mmvar->num_axis] );
mmvar->namedstyle =
(FT_Var_Named_Style*)&( mmvar->axis[mmvar->num_axis] );
+
next_coords =
(FT_Fixed*)&( mmvar->namedstyle[mmvar->num_namedstyles] );
-
for ( n = 0; n < mmvar->num_namedstyles; n++ )
{
mmvar->namedstyle[n].coords = next_coords;
@@ -2281,7 +2310,10 @@
GX_Blend blend;
FT_MM_Var* mmvar;
FT_UInt i, j;
- FT_Bool is_default_instance = 1;
+
+ FT_Bool is_default_instance = TRUE;
+ FT_Bool all_design_coords = FALSE;
+
FT_Memory memory = face->root.memory;
enum
@@ -2327,7 +2359,7 @@
}
if ( coords[i] != 0 )
- is_default_instance = 0;
+ is_default_instance = FALSE;
}
FT_TRACE5(( "\n" ));
@@ -2340,6 +2372,9 @@
{
if ( FT_NEW_ARRAY( blend->coords, mmvar->num_axis ) )
goto Exit;
+
+ /* the first time we have to compute all design coordinates */
+ all_design_coords = TRUE;
}
if ( !blend->normalizedcoords )
@@ -2388,7 +2423,7 @@
if ( set_design_coords )
ft_var_to_design( face,
- num_coords,
+ all_design_coords ? blend->num_axis : num_coords,
blend->normalizedcoords,
blend->coords );
@@ -2529,6 +2564,14 @@
blend = face->blend;
+ if ( !blend->coords )
+ {
+ /* select default instance coordinates */
+ /* if no instance is selected yet */
+ if ( FT_SET_ERROR( tt_set_mm_blend( face, 0, NULL, 1 ) ) )
+ return error;
+ }
+
nc = num_coords;
if ( num_coords > blend->num_axis )
{
@@ -2626,7 +2669,7 @@
num_coords * sizeof ( FT_Fixed ) );
a = mmvar->axis + num_coords;
- c = coords + num_coords;
+ c = blend->coords + num_coords;
for ( i = num_coords; i < mmvar->num_axis; i++, a++, c++ )
*c = a->def;
@@ -2636,7 +2679,7 @@
if ( !face->blend->avar_loaded )
ft_var_load_avar( face );
- ft_var_to_normalized( face, num_coords, coords, normalized );
+ ft_var_to_normalized( face, num_coords, blend->coords, normalized );
error = tt_set_mm_blend( face, mmvar->num_axis, normalized, 0 );
@@ -2686,6 +2729,14 @@
blend = face->blend;
+ if ( !blend->coords )
+ {
+ /* select default instance coordinates */
+ /* if no instance is selected yet */
+ if ( FT_SET_ERROR( tt_set_mm_blend( face, 0, NULL, 1 ) ) )
+ return error;
+ }
+
nc = num_coords;
if ( num_coords > blend->num_axis )
{
diff --git a/thirdparty/freetype/src/truetype/ttinterp.c b/thirdparty/freetype/src/truetype/ttinterp.c
index af31408cbf..ddcc839bb3 100644
--- a/thirdparty/freetype/src/truetype/ttinterp.c
+++ b/thirdparty/freetype/src/truetype/ttinterp.c
@@ -65,11 +65,15 @@
TT_INTERPRETER_VERSION_40 )
#endif
-#define PROJECT( v1, v2 ) \
- exc->func_project( exc, (v1)->x - (v2)->x, (v1)->y - (v2)->y )
+#define PROJECT( v1, v2 ) \
+ exc->func_project( exc, \
+ SUB_LONG( (v1)->x, (v2)->x ), \
+ SUB_LONG( (v1)->y, (v2)->y ) )
-#define DUALPROJ( v1, v2 ) \
- exc->func_dualproj( exc, (v1)->x - (v2)->x, (v1)->y - (v2)->y )
+#define DUALPROJ( v1, v2 ) \
+ exc->func_dualproj( exc, \
+ SUB_LONG( (v1)->x, (v2)->x ), \
+ SUB_LONG( (v1)->y, (v2)->y ) )
#define FAST_PROJECT( v ) \
exc->func_project( exc, (v)->x, (v)->y )
@@ -1676,7 +1680,10 @@
if ( SUBPIXEL_HINTING_INFINALITY &&
( !exc->ignore_x_mode ||
( exc->sph_tweak_flags & SPH_TWEAK_ALLOW_X_DMOVE ) ) )
- zone->cur[point].x += FT_MulDiv( distance, v, exc->F_dot_P );
+ zone->cur[point].x = ADD_LONG( zone->cur[point].x,
+ FT_MulDiv( distance,
+ v,
+ exc->F_dot_P ) );
else
#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
@@ -1685,12 +1692,18 @@
/* diagonal moves, but only post-IUP. DejaVu tries to adjust */
/* diagonal stems like on `Z' and `z' post-IUP. */
if ( SUBPIXEL_HINTING_MINIMAL && !exc->backward_compatibility )
- zone->cur[point].x += FT_MulDiv( distance, v, exc->F_dot_P );
+ zone->cur[point].x = ADD_LONG( zone->cur[point].x,
+ FT_MulDiv( distance,
+ v,
+ exc->F_dot_P ) );
else
#endif
if ( NO_SUBPIXEL_HINTING )
- zone->cur[point].x += FT_MulDiv( distance, v, exc->F_dot_P );
+ zone->cur[point].x = ADD_LONG( zone->cur[point].x,
+ FT_MulDiv( distance,
+ v,
+ exc->F_dot_P ) );
zone->tags[point] |= FT_CURVE_TAG_TOUCH_X;
}
@@ -1705,7 +1718,10 @@
exc->iupx_called &&
exc->iupy_called ) )
#endif
- zone->cur[point].y += FT_MulDiv( distance, v, exc->F_dot_P );
+ zone->cur[point].y = ADD_LONG( zone->cur[point].y,
+ FT_MulDiv( distance,
+ v,
+ exc->F_dot_P ) );
zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y;
}
@@ -1741,12 +1757,18 @@
v = exc->GS.freeVector.x;
if ( v != 0 )
- zone->org[point].x += FT_MulDiv( distance, v, exc->F_dot_P );
+ zone->org[point].x = ADD_LONG( zone->org[point].x,
+ FT_MulDiv( distance,
+ v,
+ exc->F_dot_P ) );
v = exc->GS.freeVector.y;
if ( v != 0 )
- zone->org[point].y += FT_MulDiv( distance, v, exc->F_dot_P );
+ zone->org[point].y = ADD_LONG( zone->org[point].y,
+ FT_MulDiv( distance,
+ v,
+ exc->F_dot_P ) );
}
@@ -1769,18 +1791,18 @@
{
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
if ( SUBPIXEL_HINTING_INFINALITY && !exc->ignore_x_mode )
- zone->cur[point].x += distance;
+ zone->cur[point].x = ADD_LONG( zone->cur[point].x, distance );
else
#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
if ( SUBPIXEL_HINTING_MINIMAL && !exc->backward_compatibility )
- zone->cur[point].x += distance;
+ zone->cur[point].x = ADD_LONG( zone->cur[point].x, distance );
else
#endif
if ( NO_SUBPIXEL_HINTING )
- zone->cur[point].x += distance;
+ zone->cur[point].x = ADD_LONG( zone->cur[point].x, distance );
zone->tags[point] |= FT_CURVE_TAG_TOUCH_X;
}
@@ -1799,7 +1821,7 @@
exc->backward_compatibility &&
exc->iupx_called && exc->iupy_called ) )
#endif
- zone->cur[point].y += distance;
+ zone->cur[point].y = ADD_LONG( zone->cur[point].y, distance );
zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y;
}
@@ -1823,7 +1845,7 @@
{
FT_UNUSED( exc );
- zone->org[point].x += distance;
+ zone->org[point].x = ADD_LONG( zone->org[point].x, distance );
}
@@ -1835,7 +1857,7 @@
{
FT_UNUSED( exc );
- zone->org[point].y += distance;
+ zone->org[point].y = ADD_LONG( zone->org[point].y, distance );
}
@@ -1873,13 +1895,13 @@
if ( distance >= 0 )
{
- val = distance + compensation;
+ val = ADD_LONG( distance, compensation );
if ( val < 0 )
val = 0;
}
else
{
- val = distance - compensation;
+ val = SUB_LONG( distance, compensation );
if ( val > 0 )
val = 0;
}
@@ -1915,13 +1937,14 @@
if ( distance >= 0 )
{
- val = FT_PIX_ROUND( distance + compensation );
+ val = FT_PIX_ROUND_LONG( ADD_LONG( distance, compensation ) );
if ( val < 0 )
val = 0;
}
else
{
- val = -FT_PIX_ROUND( compensation - distance );
+ val = NEG_LONG( FT_PIX_ROUND_LONG( SUB_LONG( compensation,
+ distance ) ) );
if ( val > 0 )
val = 0;
}
@@ -1958,13 +1981,16 @@
if ( distance >= 0 )
{
- val = FT_PIX_FLOOR( distance + compensation ) + 32;
+ val = ADD_LONG( FT_PIX_FLOOR( ADD_LONG( distance, compensation ) ),
+ 32 );
if ( val < 0 )
val = 32;
}
else
{
- val = -( FT_PIX_FLOOR( compensation - distance ) + 32 );
+ val = NEG_LONG( ADD_LONG( FT_PIX_FLOOR( SUB_LONG( compensation,
+ distance ) ),
+ 32 ) );
if ( val > 0 )
val = -32;
}
@@ -2001,13 +2027,13 @@
if ( distance >= 0 )
{
- val = FT_PIX_FLOOR( distance + compensation );
+ val = FT_PIX_FLOOR( ADD_LONG( distance, compensation ) );
if ( val < 0 )
val = 0;
}
else
{
- val = -FT_PIX_FLOOR( compensation - distance );
+ val = NEG_LONG( FT_PIX_FLOOR( SUB_LONG( compensation, distance ) ) );
if ( val > 0 )
val = 0;
}
@@ -2044,13 +2070,14 @@
if ( distance >= 0 )
{
- val = FT_PIX_CEIL( distance + compensation );
+ val = FT_PIX_CEIL_LONG( ADD_LONG( distance, compensation ) );
if ( val < 0 )
val = 0;
}
else
{
- val = -FT_PIX_CEIL( compensation - distance );
+ val = NEG_LONG( FT_PIX_CEIL_LONG( SUB_LONG( compensation,
+ distance ) ) );
if ( val > 0 )
val = 0;
}
@@ -2087,13 +2114,14 @@
if ( distance >= 0 )
{
- val = FT_PAD_ROUND( distance + compensation, 32 );
+ val = FT_PAD_ROUND_LONG( ADD_LONG( distance, compensation ), 32 );
if ( val < 0 )
val = 0;
}
else
{
- val = -FT_PAD_ROUND( compensation - distance, 32 );
+ val = NEG_LONG( FT_PAD_ROUND_LONG( SUB_LONG( compensation, distance ),
+ 32 ) );
if ( val > 0 )
val = 0;
}
@@ -2134,7 +2162,8 @@
if ( distance >= 0 )
{
- val = ( distance - exc->phase + exc->threshold + compensation ) &
+ val = ADD_LONG( distance,
+ exc->threshold - exc->phase + compensation ) &
-exc->period;
val += exc->phase;
if ( val < 0 )
@@ -2142,8 +2171,9 @@
}
else
{
- val = -( ( exc->threshold - exc->phase - distance + compensation ) &
- -exc->period );
+ val = NEG_LONG( SUB_LONG( exc->threshold - exc->phase + compensation,
+ distance ) &
+ -exc->period );
val -= exc->phase;
if ( val > 0 )
val = -exc->phase;
@@ -2183,7 +2213,8 @@
if ( distance >= 0 )
{
- val = ( ( distance - exc->phase + exc->threshold + compensation ) /
+ val = ( ADD_LONG( distance,
+ exc->threshold - exc->phase + compensation ) /
exc->period ) * exc->period;
val += exc->phase;
if ( val < 0 )
@@ -2191,8 +2222,9 @@
}
else
{
- val = -( ( ( exc->threshold - exc->phase - distance + compensation ) /
- exc->period ) * exc->period );
+ val = NEG_LONG( ( SUB_LONG( exc->threshold - exc->phase + compensation,
+ distance ) /
+ exc->period ) * exc->period );
val -= exc->phase;
if ( val > 0 )
val = -exc->phase;
@@ -2826,7 +2858,7 @@
static void
Ins_ADD( FT_Long* args )
{
- args[0] += args[1];
+ args[0] = ADD_LONG( args[0], args[1] );
}
@@ -2839,7 +2871,7 @@
static void
Ins_SUB( FT_Long* args )
{
- args[0] -= args[1];
+ args[0] = SUB_LONG( args[0], args[1] );
}
@@ -2882,7 +2914,8 @@
static void
Ins_ABS( FT_Long* args )
{
- args[0] = FT_ABS( args[0] );
+ if ( args[0] < 0 )
+ args[0] = NEG_LONG( args[0] );
}
@@ -2895,7 +2928,7 @@
static void
Ins_NEG( FT_Long* args )
{
- args[0] = -args[0];
+ args[0] = NEG_LONG( args[0] );
}
@@ -4211,8 +4244,8 @@
p1 = exc->zp1.cur + aIdx2;
p2 = exc->zp2.cur + aIdx1;
- A = p1->x - p2->x;
- B = p1->y - p2->y;
+ A = SUB_LONG( p1->x, p2->x );
+ B = SUB_LONG( p1->y, p2->y );
/* If p1 == p2, SPvTL and SFvTL behave the same as */
/* SPvTCA[X] and SFvTCA[X], respectively. */
@@ -4227,9 +4260,9 @@
if ( ( opcode & 1 ) != 0 )
{
- C = B; /* counter clockwise rotation */
- B = A;
- A = -C;
+ C = B; /* counter clockwise rotation */
+ B = A;
+ A = NEG_LONG( C );
}
Normalize( A, B, Vec );
@@ -4770,7 +4803,7 @@
K = FAST_PROJECT( &exc->zp2.cur[L] );
- exc->func_move( exc, &exc->zp2, L, args[1] - K );
+ exc->func_move( exc, &exc->zp2, L, SUB_LONG( args[1], K ) );
/* UNDOCUMENTED! The MS rasterizer does that with */
/* twilight points (confirmed by Greg Hitchcock) */
@@ -4894,12 +4927,12 @@
}
{
- FT_Vector* v1 = exc->zp1.org + p2;
- FT_Vector* v2 = exc->zp2.org + p1;
+ FT_Vector* v1 = exc->zp1.org + p2;
+ FT_Vector* v2 = exc->zp2.org + p1;
- A = v1->x - v2->x;
- B = v1->y - v2->y;
+ A = SUB_LONG( v1->x, v2->x );
+ B = SUB_LONG( v1->y, v2->y );
/* If v1 == v2, SDPvTL behaves the same as */
/* SVTCA[X], respectively. */
@@ -4915,9 +4948,9 @@
if ( ( opcode & 1 ) != 0 )
{
- C = B; /* counter clockwise rotation */
- B = A;
- A = -C;
+ C = B; /* counter clockwise rotation */
+ B = A;
+ A = NEG_LONG( C );
}
Normalize( A, B, &exc->GS.dualVector );
@@ -4927,8 +4960,8 @@
FT_Vector* v2 = exc->zp2.cur + p1;
- A = v1->x - v2->x;
- B = v1->y - v2->y;
+ A = SUB_LONG( v1->x, v2->x );
+ B = SUB_LONG( v1->y, v2->y );
if ( A == 0 && B == 0 )
{
@@ -4939,9 +4972,9 @@
if ( ( opcode & 1 ) != 0 )
{
- C = B; /* counter clockwise rotation */
- B = A;
- A = -C;
+ C = B; /* counter clockwise rotation */
+ B = A;
+ A = NEG_LONG( C );
}
Normalize( A, B, &exc->GS.projVector );
@@ -5392,7 +5425,7 @@
if ( !( SUBPIXEL_HINTING_MINIMAL &&
exc->backward_compatibility ) )
#endif
- exc->zp2.cur[point].x += dx;
+ exc->zp2.cur[point].x = ADD_LONG( exc->zp2.cur[point].x, dx );
if ( touch )
exc->zp2.tags[point] |= FT_CURVE_TAG_TOUCH_X;
@@ -5406,7 +5439,7 @@
exc->iupx_called &&
exc->iupy_called ) )
#endif
- exc->zp2.cur[point].y += dy;
+ exc->zp2.cur[point].y = ADD_LONG( exc->zp2.cur[point].y, dy );
if ( touch )
exc->zp2.tags[point] |= FT_CURVE_TAG_TOUCH_Y;
@@ -5781,14 +5814,17 @@
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
/* subpixel hinting - make MSIRP respect CVT cut-in; */
- if ( SUBPIXEL_HINTING_INFINALITY &&
- exc->ignore_x_mode &&
- exc->GS.freeVector.x != 0 &&
- FT_ABS( distance - args[1] ) >= control_value_cutin )
+ if ( SUBPIXEL_HINTING_INFINALITY &&
+ exc->ignore_x_mode &&
+ exc->GS.freeVector.x != 0 &&
+ FT_ABS( SUB_LONG( distance, args[1] ) ) >= control_value_cutin )
distance = args[1];
#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
- exc->func_move( exc, &exc->zp1, point, args[1] - distance );
+ exc->func_move( exc,
+ &exc->zp1,
+ point,
+ SUB_LONG( args[1], distance ) );
exc->GS.rp1 = exc->GS.rp0;
exc->GS.rp2 = point;
@@ -6027,8 +6063,10 @@
FT_Vector vec;
- vec.x = FT_MulFix( vec1->x - vec2->x, exc->metrics.x_scale );
- vec.y = FT_MulFix( vec1->y - vec2->y, exc->metrics.y_scale );
+ vec.x = FT_MulFix( SUB_LONG( vec1->x, vec2->x ),
+ exc->metrics.x_scale );
+ vec.y = FT_MulFix( SUB_LONG( vec1->y, vec2->y ),
+ exc->metrics.y_scale );
org_dist = FAST_DUALPROJ( &vec );
}
@@ -6081,8 +6119,8 @@
}
else
{
- if ( distance > -minimum_distance )
- distance = -minimum_distance;
+ if ( distance > NEG_LONG( minimum_distance ) )
+ distance = NEG_LONG( minimum_distance );
}
}
@@ -6090,7 +6128,7 @@
org_dist = PROJECT( exc->zp1.cur + point, exc->zp0.cur + exc->GS.rp0 );
- exc->func_move( exc, &exc->zp1, point, distance - org_dist );
+ exc->func_move( exc, &exc->zp1, point, SUB_LONG( distance, org_dist ) );
Fail:
exc->GS.rp1 = exc->GS.rp0;
@@ -6265,8 +6303,8 @@
}
else
{
- if ( distance > -minimum_distance )
- distance = -minimum_distance;
+ if ( distance > NEG_LONG( minimum_distance ) )
+ distance = NEG_LONG( minimum_distance );
}
}
@@ -6290,7 +6328,10 @@
}
#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
- exc->func_move( exc, &exc->zp1, point, distance - cur_dist );
+ exc->func_move( exc,
+ &exc->zp1,
+ point,
+ SUB_LONG( distance, cur_dist ) );
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
if ( SUBPIXEL_HINTING_INFINALITY )
@@ -6314,7 +6355,10 @@
}
if ( reverse_move )
- exc->func_move( exc, &exc->zp1, point, -( distance - cur_dist ) );
+ exc->func_move( exc,
+ &exc->zp1,
+ point,
+ SUB_LONG( cur_dist, distance ) );
}
#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
@@ -6380,7 +6424,7 @@
distance = PROJECT( exc->zp1.cur + point,
exc->zp0.cur + exc->GS.rp0 );
- exc->func_move( exc, &exc->zp1, point, -distance );
+ exc->func_move( exc, &exc->zp1, point, NEG_LONG( distance ) );
}
exc->GS.loop--;
@@ -6437,19 +6481,19 @@
/* Cramer's rule */
- dbx = exc->zp0.cur[b1].x - exc->zp0.cur[b0].x;
- dby = exc->zp0.cur[b1].y - exc->zp0.cur[b0].y;
+ dbx = SUB_LONG( exc->zp0.cur[b1].x, exc->zp0.cur[b0].x );
+ dby = SUB_LONG( exc->zp0.cur[b1].y, exc->zp0.cur[b0].y );
- dax = exc->zp1.cur[a1].x - exc->zp1.cur[a0].x;
- day = exc->zp1.cur[a1].y - exc->zp1.cur[a0].y;
+ dax = SUB_LONG( exc->zp1.cur[a1].x, exc->zp1.cur[a0].x );
+ day = SUB_LONG( exc->zp1.cur[a1].y, exc->zp1.cur[a0].y );
- dx = exc->zp0.cur[b0].x - exc->zp1.cur[a0].x;
- dy = exc->zp0.cur[b0].y - exc->zp1.cur[a0].y;
+ dx = SUB_LONG( exc->zp0.cur[b0].x, exc->zp1.cur[a0].x );
+ dy = SUB_LONG( exc->zp0.cur[b0].y, exc->zp1.cur[a0].y );
- discriminant = FT_MulDiv( dax, -dby, 0x40 ) +
- FT_MulDiv( day, dbx, 0x40 );
- dotproduct = FT_MulDiv( dax, dbx, 0x40 ) +
- FT_MulDiv( day, dby, 0x40 );
+ discriminant = ADD_LONG( FT_MulDiv( dax, NEG_LONG( dby ), 0x40 ),
+ FT_MulDiv( day, dbx, 0x40 ) );
+ dotproduct = ADD_LONG( FT_MulDiv( dax, dbx, 0x40 ),
+ FT_MulDiv( day, dby, 0x40 ) );
/* The discriminant above is actually a cross product of vectors */
/* da and db. Together with the dot product, they can be used as */
@@ -6459,30 +6503,29 @@
/* discriminant = |da||db|sin(angle) . */
/* We use these equations to reject grazing intersections by */
/* thresholding abs(tan(angle)) at 1/19, corresponding to 3 degrees. */
- if ( 19 * FT_ABS( discriminant ) > FT_ABS( dotproduct ) )
+ if ( MUL_LONG( 19, FT_ABS( discriminant ) ) > FT_ABS( dotproduct ) )
{
- val = FT_MulDiv( dx, -dby, 0x40 ) + FT_MulDiv( dy, dbx, 0x40 );
+ val = ADD_LONG( FT_MulDiv( dx, NEG_LONG( dby ), 0x40 ),
+ FT_MulDiv( dy, dbx, 0x40 ) );
R.x = FT_MulDiv( val, dax, discriminant );
R.y = FT_MulDiv( val, day, discriminant );
/* XXX: Block in backward_compatibility and/or post-IUP? */
- exc->zp2.cur[point].x = exc->zp1.cur[a0].x + R.x;
- exc->zp2.cur[point].y = exc->zp1.cur[a0].y + R.y;
+ exc->zp2.cur[point].x = ADD_LONG( exc->zp1.cur[a0].x, R.x );
+ exc->zp2.cur[point].y = ADD_LONG( exc->zp1.cur[a0].y, R.y );
}
else
{
/* else, take the middle of the middles of A and B */
/* XXX: Block in backward_compatibility and/or post-IUP? */
- exc->zp2.cur[point].x = ( exc->zp1.cur[a0].x +
- exc->zp1.cur[a1].x +
- exc->zp0.cur[b0].x +
- exc->zp0.cur[b1].x ) / 4;
- exc->zp2.cur[point].y = ( exc->zp1.cur[a0].y +
- exc->zp1.cur[a1].y +
- exc->zp0.cur[b0].y +
- exc->zp0.cur[b1].y ) / 4;
+ exc->zp2.cur[point].x =
+ ADD_LONG( ADD_LONG( exc->zp1.cur[a0].x, exc->zp1.cur[a1].x ),
+ ADD_LONG( exc->zp0.cur[b0].x, exc->zp0.cur[b1].x ) ) / 4;
+ exc->zp2.cur[point].y =
+ ADD_LONG( ADD_LONG( exc->zp1.cur[a0].y, exc->zp1.cur[a1].y ),
+ ADD_LONG( exc->zp0.cur[b0].y, exc->zp0.cur[b1].y ) ) / 4;
}
exc->zp2.tags[point] |= FT_CURVE_TAG_TOUCH_BOTH;
@@ -6517,7 +6560,7 @@
distance = PROJECT( exc->zp0.cur + p2, exc->zp1.cur + p1 ) / 2;
exc->func_move( exc, &exc->zp1, p1, distance );
- exc->func_move( exc, &exc->zp0, p2, -distance );
+ exc->func_move( exc, &exc->zp0, p2, NEG_LONG( distance ) );
}
@@ -6590,9 +6633,11 @@
FT_Vector vec;
- vec.x = FT_MulFix( exc->zp1.orus[exc->GS.rp2].x - orus_base->x,
+ vec.x = FT_MulFix( SUB_LONG( exc->zp1.orus[exc->GS.rp2].x,
+ orus_base->x ),
exc->metrics.x_scale );
- vec.y = FT_MulFix( exc->zp1.orus[exc->GS.rp2].y - orus_base->y,
+ vec.y = FT_MulFix( SUB_LONG( exc->zp1.orus[exc->GS.rp2].y,
+ orus_base->y ),
exc->metrics.y_scale );
old_range = FAST_DUALPROJ( &vec );
@@ -6627,9 +6672,11 @@
FT_Vector vec;
- vec.x = FT_MulFix( exc->zp2.orus[point].x - orus_base->x,
+ vec.x = FT_MulFix( SUB_LONG( exc->zp2.orus[point].x,
+ orus_base->x ),
exc->metrics.x_scale );
- vec.y = FT_MulFix( exc->zp2.orus[point].y - orus_base->y,
+ vec.y = FT_MulFix( SUB_LONG( exc->zp2.orus[point].y,
+ orus_base->y ),
exc->metrics.y_scale );
org_dist = FAST_DUALPROJ( &vec );
@@ -6668,7 +6715,7 @@
exc->func_move( exc,
&exc->zp2,
(FT_UShort)point,
- new_dist - cur_dist );
+ SUB_LONG( new_dist, cur_dist ) );
}
Fail:
@@ -6733,14 +6780,14 @@
FT_F26Dot6 dx;
- dx = worker->curs[p].x - worker->orgs[p].x;
+ dx = SUB_LONG( worker->curs[p].x, worker->orgs[p].x );
if ( dx != 0 )
{
for ( i = p1; i < p; i++ )
- worker->curs[i].x += dx;
+ worker->curs[i].x = ADD_LONG( worker->curs[i].x, dx );
for ( i = p + 1; i <= p2; i++ )
- worker->curs[i].x += dx;
+ worker->curs[i].x = ADD_LONG( worker->curs[i].x, dx );
}
}
@@ -6785,8 +6832,8 @@
org2 = worker->orgs[ref2].x;
cur1 = worker->curs[ref1].x;
cur2 = worker->curs[ref2].x;
- delta1 = cur1 - org1;
- delta2 = cur2 - org2;
+ delta1 = SUB_LONG( cur1, org1 );
+ delta2 = SUB_LONG( cur2, org2 );
if ( cur1 == cur2 || orus1 == orus2 )
{
@@ -6798,10 +6845,10 @@
if ( x <= org1 )
- x += delta1;
+ x = ADD_LONG( x, delta1 );
else if ( x >= org2 )
- x += delta2;
+ x = ADD_LONG( x, delta2 );
else
x = cur1;
@@ -6822,20 +6869,23 @@
if ( x <= org1 )
- x += delta1;
+ x = ADD_LONG( x, delta1 );
else if ( x >= org2 )
- x += delta2;
+ x = ADD_LONG( x, delta2 );
else
{
if ( !scale_valid )
{
scale_valid = 1;
- scale = FT_DivFix( cur2 - cur1, orus2 - orus1 );
+ scale = FT_DivFix( SUB_LONG( cur2, cur1 ),
+ SUB_LONG( orus2, orus1 ) );
}
- x = cur1 + FT_MulFix( worker->orus[i].x - orus1, scale );
+ x = ADD_LONG( cur1,
+ FT_MulFix( SUB_LONG( worker->orus[i].x, orus1 ),
+ scale ) );
}
worker->curs[i].x = x;
}
@@ -7310,7 +7360,11 @@
K |= 1 << 12;
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
- if ( SUBPIXEL_HINTING_MINIMAL )
+ /* Toggle the following flags only outside of monochrome mode. */
+ /* Otherwise, instructions may behave weirdly and rendering results */
+ /* may differ between v35 and v40 mode, e.g., in `Times New Roman */
+ /* Bold Italic'. */
+ if ( SUBPIXEL_HINTING_MINIMAL && exc->subpixel_hinting_lean )
{
/********************************/
/* HINTING FOR SUBPIXEL */
@@ -7345,7 +7399,7 @@
/* */
/* The only smoothing method FreeType supports unless someone sets */
/* FT_LOAD_TARGET_MONO. */
- if ( ( args[0] & 2048 ) != 0 )
+ if ( ( args[0] & 2048 ) != 0 && exc->subpixel_hinting_lean )
K |= 1 << 18;
/********************************/
@@ -7589,11 +7643,21 @@
#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
- /* Toggle backward compatibility according to what font says, except */
- /* when it's a `tricky' font that heavily relies on the interpreter to */
- /* render glyphs correctly, e.g. DFKai-SB. Backward compatibility */
- /* hacks may break it. */
+ /*
+ * Toggle backward compatibility according to what font wants, except
+ * when
+ *
+ * 1) we have a `tricky' font that heavily relies on the interpreter to
+ * render glyphs correctly, for example DFKai-SB, or
+ * 2) FT_RENDER_MODE_MONO (i.e, monochome rendering) is requested.
+ *
+ * In those cases, backward compatibility needs to be turned off to get
+ * correct rendering. The rendering is then completely up to the
+ * font's programming.
+ *
+ */
if ( SUBPIXEL_HINTING_MINIMAL &&
+ exc->subpixel_hinting_lean &&
!FT_IS_TRICKY( &exc->face->root ) )
exc->backward_compatibility = !( exc->GS.instruct_control & 4 );
else
@@ -7639,8 +7703,7 @@
FT_MAX( 50,
exc->cvtSize / 10 );
else
- exc->loopcall_counter_max = FT_MAX( 100,
- 10 * exc->cvtSize );
+ exc->loopcall_counter_max = 300 + 8 * exc->cvtSize;
/* as a protection against an unreasonable number of CVT entries */
/* we assume at most 100 control values per glyph for the counter */
diff --git a/thirdparty/freetype/src/truetype/ttinterp.h b/thirdparty/freetype/src/truetype/ttinterp.h
index 55e472091c..abbecfcee3 100644
--- a/thirdparty/freetype/src/truetype/ttinterp.h
+++ b/thirdparty/freetype/src/truetype/ttinterp.h
@@ -253,23 +253,38 @@ FT_BEGIN_HEADER
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
/*
- * Modern TrueType fonts are usually rendered through Microsoft's
- * collection of rendering techniques called ClearType (e.g., subpixel
- * rendering and subpixel hinting). When ClearType was introduced, most
- * fonts were not ready. Microsoft decided to implement a backward
- * compatibility mode that employed several simple to complicated
- * assumptions and tricks that modified the interpretation of the
- * bytecode contained in these fonts to make them look ClearType-y
- * somehow. Most (web)fonts that were released since then have come to
- * rely on these hacks to render correctly, even some of Microsoft's
- * flagship ClearType fonts (Calibri, Cambria, Segoe UI).
+ * FreeType supports ClearType-like hinting of TrueType fonts through
+ * the version 40 interpreter. This is achieved through several hacks
+ * in the base (v35) interpreter, as detailed below.
*
- * The minimal subpixel hinting code (interpreter version 40) employs a
- * small list of font-agnostic hacks to bludgeon non-native-ClearType
- * fonts (except tricky ones[1]) into submission. It will not try to
- * toggle hacks for specific fonts for performance and complexity
- * reasons. The focus is on modern (web)fonts rather than legacy fonts
- * that were made for black-and-white rendering.
+ * ClearType is an umbrella term for several rendering techniques
+ * employed by Microsoft's various GUI and rendering toolkit
+ * implementations, most importantly: subpixel rendering for using the
+ * RGB subpixels of LCDs to approximately triple the perceived
+ * resolution on the x-axis and subpixel hinting for positioning stems
+ * on subpixel borders. TrueType programming is explicit, i.e., fonts
+ * must be programmed to take advantage of ClearType's possibilities.
+ *
+ * When ClearType was introduced, it seemed unlikely that all fonts
+ * would be reprogrammed, so Microsoft decided to implement a backward
+ * compatibility mode. It employs several simple to complicated
+ * assumptions and tricks, many of them font-dependent, that modify the
+ * interpretation of the bytecode contained in these fonts to retrofit
+ * them into a ClearType-y look. The quality of the results varies.
+ * Most (web)fonts that were released since then have come to rely on
+ * these hacks to render correctly, even some of Microsoft's flagship
+ * fonts (e.g., Calibri, Cambria, Segoe UI).
+ *
+ * FreeType's minimal subpixel hinting code (interpreter version 40)
+ * employs a small list of font-agnostic hacks loosely based on the
+ * public information available on Microsoft's compatibility mode[2].
+ * The focus is on modern (web)fonts rather than legacy fonts that were
+ * made for monochrome rendering. It will not match ClearType rendering
+ * exactly. Unlike the `Infinality' code (interpreter version 38) that
+ * came before, it will not try to toggle hacks for specific fonts for
+ * performance and complexity reasons. It will fall back to version 35
+ * behavior for tricky fonts[1] or when monochrome rendering is
+ * requested.
*
* Major hacks
*
@@ -347,7 +362,8 @@ FT_BEGIN_HEADER
*
*/
- /* Using v40 implies subpixel hinting. Used to detect interpreter */
+ /* Using v40 implies subpixel hinting, unless FT_RENDER_MODE_MONO has been
+ * requested. Used to detect interpreter */
/* version switches. `_lean' to differentiate from the Infinality */
/* `subpixel_hinting', which is managed differently. */
FT_Bool subpixel_hinting_lean;
diff --git a/thirdparty/freetype/src/truetype/ttobjs.c b/thirdparty/freetype/src/truetype/ttobjs.c
index 4db0f289f8..081fa2f1a5 100644
--- a/thirdparty/freetype/src/truetype/ttobjs.c
+++ b/thirdparty/freetype/src/truetype/ttobjs.c
@@ -576,9 +576,11 @@
/* We must also be able to accept Mac/GX fonts, as well as OT ones. */
/* The 0x00020000 tag is completely undocumented; some fonts from */
/* Arphic made for Chinese Windows 3.1 have this. */
- if ( face->format_tag != 0x00010000L && /* MS fonts */
- face->format_tag != 0x00020000L && /* CJK fonts for Win 3.1 */
- face->format_tag != TTAG_true ) /* Mac fonts */
+ if ( face->format_tag != 0x00010000L && /* MS fonts */
+ face->format_tag != 0x00020000L && /* CJK fonts for Win 3.1 */
+ face->format_tag != TTAG_true && /* Mac fonts */
+ face->format_tag != TTAG_0xA5kbd && /* `Keyboard.dfont' (legacy Mac OS X) */
+ face->format_tag != TTAG_0xA5lst ) /* `LastResort.dfont' (legacy Mac OS X) */
{
FT_TRACE2(( " not a TTF font\n" ));
goto Bad_Format;
@@ -1230,7 +1232,9 @@
/* <Input> */
/* size :: A handle to the target size object. */
/* */
- /* only_height :: Only recompute ascender, descender, and height. */
+ /* only_height :: Only recompute ascender, descender, and height; */
+ /* this flag is used for variation fonts where */
+ /* `tt_size_reset' is used as an iterator function. */
/* */
FT_LOCAL_DEF( FT_Error )
tt_size_reset( TT_Size size,
@@ -1277,7 +1281,11 @@
size->ttmetrics.valid = TRUE;
if ( only_height )
+ {
+ /* we must not recompute the scaling values here since */
+ /* `tt_size_reset' was already called (with only_height = 0) */
return FT_Err_Ok;
+ }
if ( face->header.Flags & 8 )
{
diff --git a/thirdparty/freetype/src/truetype/ttpload.c b/thirdparty/freetype/src/truetype/ttpload.c
index 70ac15da4a..bcf6b34f67 100644
--- a/thirdparty/freetype/src/truetype/ttpload.c
+++ b/thirdparty/freetype/src/truetype/ttpload.c
@@ -247,13 +247,13 @@
if ( pos2 > face->glyf_len )
{
/* We try to sanitize the last `loca' entry. */
- if ( gindex == face->num_locations - 1 )
+ if ( gindex == face->num_locations - 2 )
{
FT_TRACE1(( "tt_face_get_location:"
- " too large offset (0x%08lx) found for glyph index %ld,\n"
+ " too large size (%ld bytes) found for glyph index %ld,\n"
" "
- " truncating at the end of `glyf' table (0x%08lx)\n",
- pos2, gindex + 1, face->glyf_len ));
+ " truncating at the end of `glyf' table to %ld bytes\n",
+ pos2 - pos1, gindex, face->glyf_len - pos1 ));
pos2 = face->glyf_len;
}
else
diff --git a/thirdparty/freetype/src/type1/t1load.c b/thirdparty/freetype/src/type1/t1load.c
index f5c661f7de..f569d6bec3 100644
--- a/thirdparty/freetype/src/type1/t1load.c
+++ b/thirdparty/freetype/src/type1/t1load.c
@@ -329,8 +329,8 @@
for ( i = 0; i < mmaster.num_axis; i++ )
{
mmvar->axis[i].name = mmaster.axis[i].name;
- mmvar->axis[i].minimum = INT_TO_FIXED( mmaster.axis[i].minimum);
- mmvar->axis[i].maximum = INT_TO_FIXED( mmaster.axis[i].maximum);
+ mmvar->axis[i].minimum = INT_TO_FIXED( mmaster.axis[i].minimum );
+ mmvar->axis[i].maximum = INT_TO_FIXED( mmaster.axis[i].maximum );
mmvar->axis[i].def = ( mmvar->axis[i].minimum +
mmvar->axis[i].maximum ) / 2;
/* Does not apply. But this value is in range */
diff --git a/thirdparty/freetype/src/type1/t1objs.c b/thirdparty/freetype/src/type1/t1objs.c
index 97c16b0fdf..5ac1292ae0 100644
--- a/thirdparty/freetype/src/type1/t1objs.c
+++ b/thirdparty/freetype/src/type1/t1objs.c
@@ -555,12 +555,6 @@
if ( clazz )
error = FT_CMap_New( clazz, NULL, &charmap, NULL );
-
-#if 0
- /* Select default charmap */
- if (root->num_charmaps)
- root->charmap = root->charmaps[0];
-#endif
}
}
diff --git a/thirdparty/freetype/src/type42/t42objs.c b/thirdparty/freetype/src/type42/t42objs.c
index 87e5206b7f..1c4ebd768a 100644
--- a/thirdparty/freetype/src/type42/t42objs.c
+++ b/thirdparty/freetype/src/type42/t42objs.c
@@ -394,12 +394,6 @@
if ( clazz )
error = FT_CMap_New( clazz, NULL, &charmap, NULL );
-
-#if 0
- /* Select default charmap */
- if ( root->num_charmaps )
- root->charmap = root->charmaps[0];
-#endif
}
}
Exit:
diff --git a/thirdparty/freetype/src/winfonts/winfnt.c b/thirdparty/freetype/src/winfonts/winfnt.c
index 9811fbb05a..4c47962319 100644
--- a/thirdparty/freetype/src/winfonts/winfnt.c
+++ b/thirdparty/freetype/src/winfonts/winfnt.c
@@ -859,10 +859,6 @@
NULL );
if ( error )
goto Fail;
-
- /* Select default charmap */
- if ( root->num_charmaps )
- root->charmap = root->charmaps[0];
}
/* set up remaining flags */
@@ -1095,7 +1091,7 @@
/* note: since glyphs are stored in columns and not in rows we */
/* can't use ft_glyphslot_set_bitmap */
- if ( FT_ALLOC_MULT( bitmap->buffer, pitch, bitmap->rows ) )
+ if ( FT_ALLOC_MULT( bitmap->buffer, bitmap->rows, pitch ) )
goto Exit;
column = (FT_Byte*)bitmap->buffer;
diff --git a/thirdparty/libpng/LICENSE b/thirdparty/libpng/LICENSE
index b7ad4b9eaf..4cda4fa0ad 100644
--- a/thirdparty/libpng/LICENSE
+++ b/thirdparty/libpng/LICENSE
@@ -10,8 +10,8 @@ this sentence.
This code is released under the libpng license.
-libpng versions 1.0.7, July 1, 2000 through 1.6.23, June 9, 2016 are
-Copyright (c) 2000-2002, 2004, 2006-2016 Glenn Randers-Pehrson, are
+libpng versions 1.0.7, July 1, 2000 through 1.6.34, September 29, 2017 are
+Copyright (c) 2000-2002, 2004, 2006-2017 Glenn Randers-Pehrson, are
derived from libpng-1.0.6, and are distributed according to the same
disclaimer and license as libpng-1.0.6 with the following individuals
added to the list of Contributing Authors:
@@ -22,6 +22,9 @@ added to the list of Contributing Authors:
Cosmin Truta
Gilles Vollant
James Yu
+ Mandar Sahastrabuddhe
+ Google Inc.
+ Vadim Barkov
and with the following additions to the disclaimer:
@@ -127,4 +130,4 @@ any encryption software. See the EAR, paragraphs 734.3(b)(3) and
Glenn Randers-Pehrson
glennrp at users.sourceforge.net
-June 9, 2016
+September 29, 2017
diff --git a/thirdparty/libpng/png.c b/thirdparty/libpng/png.c
index 2352df13cb..ff02c56518 100644
--- a/thirdparty/libpng/png.c
+++ b/thirdparty/libpng/png.c
@@ -1,7 +1,7 @@
/* png.c - location for general purpose libpng functions
*
- * Last changed in libpng 1.6.32 [August 24, 2017]
+ * Last changed in libpng 1.6.33 [September 28, 2017]
* Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
@@ -14,7 +14,7 @@
#include "pngpriv.h"
/* Generate a compiler error if there is an old png.h in the search path. */
-typedef png_libpng_version_1_6_32 Your_png_h_is_not_version_1_6_32;
+typedef png_libpng_version_1_6_34 Your_png_h_is_not_version_1_6_34;
#ifdef __GNUC__
/* The version tests may need to be added to, but the problem warning has
@@ -816,14 +816,14 @@ png_get_copyright(png_const_structrp png_ptr)
#else
# ifdef __STDC__
return PNG_STRING_NEWLINE \
- "libpng version 1.6.32 - August 24, 2017" PNG_STRING_NEWLINE \
+ "libpng version 1.6.34 - September 29, 2017" PNG_STRING_NEWLINE \
"Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson" \
PNG_STRING_NEWLINE \
"Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \
"Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \
PNG_STRING_NEWLINE;
# else
- return "libpng version 1.6.32 - August 24, 2017\
+ return "libpng version 1.6.34 - September 29, 2017\
Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson\
Copyright (c) 1996-1997 Andreas Dilger\
Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.";
@@ -1913,12 +1913,12 @@ png_colorspace_set_sRGB(png_const_structrp png_ptr, png_colorspacerp colorspace,
*/
if (intent < 0 || intent >= PNG_sRGB_INTENT_LAST)
return png_icc_profile_error(png_ptr, colorspace, "sRGB",
- (unsigned)intent, "invalid sRGB rendering intent");
+ (png_alloc_size_t)intent, "invalid sRGB rendering intent");
if ((colorspace->flags & PNG_COLORSPACE_HAVE_INTENT) != 0 &&
colorspace->rendering_intent != intent)
return png_icc_profile_error(png_ptr, colorspace, "sRGB",
- (unsigned)intent, "inconsistent rendering intents");
+ (png_alloc_size_t)intent, "inconsistent rendering intents");
if ((colorspace->flags & PNG_COLORSPACE_FROM_sRGB) != 0)
{
@@ -1979,7 +1979,6 @@ icc_check_length(png_const_structrp png_ptr, png_colorspacerp colorspace,
if (profile_length < 132)
return png_icc_profile_error(png_ptr, colorspace, name, profile_length,
"too short");
-
return 1;
}
@@ -2224,22 +2223,23 @@ png_icc_check_tag_table(png_const_structrp png_ptr, png_colorspacerp colorspace,
* being in range. All defined tag types have an 8 byte header - a 4 byte
* type signature then 0.
*/
+
+ /* This is a hard error; potentially it can cause read outside the
+ * profile.
+ */
+ if (tag_start > profile_length || tag_length > profile_length - tag_start)
+ return png_icc_profile_error(png_ptr, colorspace, name, tag_id,
+ "ICC profile tag outside profile");
+
if ((tag_start & 3) != 0)
{
- /* CNHP730S.icc shipped with Microsoft Windows 64 violates this, it is
+ /* CNHP730S.icc shipped with Microsoft Windows 64 violates this; it is
* only a warning here because libpng does not care about the
* alignment.
*/
(void)png_icc_profile_error(png_ptr, NULL, name, tag_id,
"ICC profile tag start not a multiple of 4");
}
-
- /* This is a hard error; potentially it can cause read outside the
- * profile.
- */
- if (tag_start > profile_length || tag_length > profile_length - tag_start)
- return png_icc_profile_error(png_ptr, colorspace, name, tag_id,
- "ICC profile tag outside profile");
}
return 1; /* success, maybe with warnings */
@@ -3761,7 +3761,7 @@ png_log16bit(png_uint_32 x)
* of getting this accuracy in practice.
*
* To deal with this the following exp() function works out the exponent of the
- * frational part of the logarithm by using an accurate 32-bit value from the
+ * fractional part of the logarithm by using an accurate 32-bit value from the
* top four fractional bits then multiplying in the remaining bits.
*/
static const png_uint_32
diff --git a/thirdparty/libpng/png.h b/thirdparty/libpng/png.h
index 51ac8abe74..4c873f5c22 100644
--- a/thirdparty/libpng/png.h
+++ b/thirdparty/libpng/png.h
@@ -1,7 +1,7 @@
/* png.h - header file for PNG reference library
*
- * libpng version 1.6.32, August 24, 2017
+ * libpng version 1.6.34, September 29, 2017
*
* Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
@@ -12,7 +12,7 @@
* Authors and maintainers:
* libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat
* libpng versions 0.89, June 1996, through 0.96, May 1997: Andreas Dilger
- * libpng versions 0.97, January 1998, through 1.6.32, August 24, 2017:
+ * libpng versions 0.97, January 1998, through 1.6.34, September 29, 2017:
* Glenn Randers-Pehrson.
* See also "Contributing Authors", below.
*/
@@ -25,7 +25,7 @@
*
* This code is released under the libpng license.
*
- * libpng versions 1.0.7, July 1, 2000 through 1.6.32, August 24, 2017 are
+ * libpng versions 1.0.7, July 1, 2000 through 1.6.34, September 29, 2017 are
* Copyright (c) 2000-2002, 2004, 2006-2017 Glenn Randers-Pehrson, are
* derived from libpng-1.0.6, and are distributed according to the same
* disclaimer and license as libpng-1.0.6 with the following individuals
@@ -209,11 +209,11 @@
* ...
* 1.0.19 10 10019 10.so.0.19[.0]
* ...
- * 1.2.57 13 10257 12.so.0.57[.0]
+ * 1.2.59 13 10257 12.so.0.59[.0]
* ...
- * 1.5.28 15 10527 15.so.15.28[.0]
+ * 1.5.30 15 10527 15.so.15.30[.0]
* ...
- * 1.6.32 16 10632 16.so.16.32[.0]
+ * 1.6.34 16 10633 16.so.16.34[.0]
*
* Henceforth the source version will match the shared-library major
* and minor numbers; the shared-library major version number will be
@@ -241,13 +241,13 @@
* Y2K compliance in libpng:
* =========================
*
- * August 24, 2017
+ * September 29, 2017
*
* Since the PNG Development group is an ad-hoc body, we can't make
* an official declaration.
*
* This is your unofficial assurance that libpng from version 0.71 and
- * upward through 1.6.32 are Y2K compliant. It is my belief that
+ * upward through 1.6.34 are Y2K compliant. It is my belief that
* earlier versions were also Y2K compliant.
*
* Libpng only has two year fields. One is a 2-byte unsigned integer
@@ -309,8 +309,8 @@
*/
/* Version information for png.h - this should match the version in png.c */
-#define PNG_LIBPNG_VER_STRING "1.6.32"
-#define PNG_HEADER_VERSION_STRING " libpng version 1.6.32 - August 24, 2017\n"
+#define PNG_LIBPNG_VER_STRING "1.6.34"
+#define PNG_HEADER_VERSION_STRING " libpng version 1.6.34 - September 29, 2017\n"
#define PNG_LIBPNG_VER_SONUM 16
#define PNG_LIBPNG_VER_DLLNUM 16
@@ -318,7 +318,7 @@
/* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */
#define PNG_LIBPNG_VER_MAJOR 1
#define PNG_LIBPNG_VER_MINOR 6
-#define PNG_LIBPNG_VER_RELEASE 32
+#define PNG_LIBPNG_VER_RELEASE 34
/* This should match the numeric part of the final component of
* PNG_LIBPNG_VER_STRING, omitting any leading zero:
@@ -349,7 +349,7 @@
* version 1.0.0 was mis-numbered 100 instead of 10000). From
* version 1.0.1 it's xxyyzz, where x=major, y=minor, z=release
*/
-#define PNG_LIBPNG_VER 10632 /* 1.6.32 */
+#define PNG_LIBPNG_VER 10634 /* 1.6.34 */
/* Library configuration: these options cannot be changed after
* the library has been built.
@@ -459,7 +459,7 @@ extern "C" {
/* This triggers a compiler error in png.c, if png.c and png.h
* do not agree upon the version number.
*/
-typedef char* png_libpng_version_1_6_32;
+typedef char* png_libpng_version_1_6_34;
/* Basic control structions. Read libpng-manual.txt or libpng.3 for more info.
*
@@ -2819,6 +2819,8 @@ typedef struct
# define PNG_FORMAT_FLAG_AFIRST 0x20U /* alpha channel comes first */
#endif
+#define PNG_FORMAT_FLAG_ASSOCIATED_ALPHA 0x40U /* alpha channel is associated */
+
/* Commonly used formats have predefined macros.
*
* First the single byte (sRGB) formats:
diff --git a/thirdparty/libpng/pngconf.h b/thirdparty/libpng/pngconf.h
index c0f15547be..d13b13e57a 100644
--- a/thirdparty/libpng/pngconf.h
+++ b/thirdparty/libpng/pngconf.h
@@ -1,7 +1,7 @@
/* pngconf.h - machine configurable file for libpng
*
- * libpng version 1.6.32, August 24, 2017
+ * libpng version 1.6.34, September 29, 2017
*
* Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
diff --git a/thirdparty/libpng/pnglibconf.h b/thirdparty/libpng/pnglibconf.h
index 9e45f73129..53b5e442c4 100644
--- a/thirdparty/libpng/pnglibconf.h
+++ b/thirdparty/libpng/pnglibconf.h
@@ -1,8 +1,8 @@
-/* libpng 1.6.32 STANDARD API DEFINITION */
+/* libpng 1.6.34 STANDARD API DEFINITION */
/* pnglibconf.h - library build configuration */
-/* Libpng version 1.6.32 - August 24, 2017 */
+/* Libpng version 1.6.34 - September 29, 2017 */
/* Copyright (c) 1998-2017 Glenn Randers-Pehrson */
diff --git a/thirdparty/libpng/pngread.c b/thirdparty/libpng/pngread.c
index e34ddd99a0..da32e9ad9c 100644
--- a/thirdparty/libpng/pngread.c
+++ b/thirdparty/libpng/pngread.c
@@ -1,7 +1,7 @@
/* pngread.c - read a PNG file
*
- * Last changed in libpng 1.6.32 [August 24, 2017]
+ * Last changed in libpng 1.6.33 [September 28, 2017]
* Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
@@ -3759,7 +3759,13 @@ png_image_read_direct(png_voidp argument)
mode = PNG_ALPHA_PNG;
output_gamma = PNG_DEFAULT_sRGB;
}
-
+
+ if ((change & PNG_FORMAT_FLAG_ASSOCIATED_ALPHA) != 0)
+ {
+ mode = PNG_ALPHA_OPTIMIZED;
+ change &= ~PNG_FORMAT_FLAG_ASSOCIATED_ALPHA;
+ }
+
/* If 'do_local_background' is set check for the presence of gamma
* correction; this is part of the work-round for the libpng bug
* described above.
@@ -3985,6 +3991,10 @@ png_image_read_direct(png_voidp argument)
else if (do_local_compose != 0) /* internal error */
png_error(png_ptr, "png_image_read: alpha channel lost");
+ if ((format & PNG_FORMAT_FLAG_ASSOCIATED_ALPHA) != 0) {
+ info_format |= PNG_FORMAT_FLAG_ASSOCIATED_ALPHA;
+ }
+
if (info_ptr->bit_depth == 16)
info_format |= PNG_FORMAT_FLAG_LINEAR;
diff --git a/thirdparty/libpng/pngrtran.c b/thirdparty/libpng/pngrtran.c
index 9a30ddf22b..c189650313 100644
--- a/thirdparty/libpng/pngrtran.c
+++ b/thirdparty/libpng/pngrtran.c
@@ -1,7 +1,7 @@
/* pngrtran.c - transforms the data in a row for PNG readers
*
- * Last changed in libpng 1.6.31 [July 27, 2017]
+ * Last changed in libpng 1.6.33 [September 28, 2017]
* Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
@@ -430,7 +430,7 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette,
int i;
png_ptr->quantize_index = (png_bytep)png_malloc(png_ptr,
- (png_uint_32)((png_uint_32)num_palette * (sizeof (png_byte))));
+ (png_alloc_size_t)((png_uint_32)num_palette * (sizeof (png_byte))));
for (i = 0; i < num_palette; i++)
png_ptr->quantize_index[i] = (png_byte)i;
}
@@ -447,7 +447,7 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette,
/* Initialize an array to sort colors */
png_ptr->quantize_sort = (png_bytep)png_malloc(png_ptr,
- (png_uint_32)((png_uint_32)num_palette * (sizeof (png_byte))));
+ (png_alloc_size_t)((png_uint_32)num_palette * (sizeof (png_byte))));
/* Initialize the quantize_sort array */
for (i = 0; i < num_palette; i++)
@@ -581,9 +581,11 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette,
/* Initialize palette index arrays */
png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr,
- (png_uint_32)((png_uint_32)num_palette * (sizeof (png_byte))));
+ (png_alloc_size_t)((png_uint_32)num_palette *
+ (sizeof (png_byte))));
png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr,
- (png_uint_32)((png_uint_32)num_palette * (sizeof (png_byte))));
+ (png_alloc_size_t)((png_uint_32)num_palette *
+ (sizeof (png_byte))));
/* Initialize the sort array */
for (i = 0; i < num_palette; i++)
@@ -592,7 +594,7 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette,
png_ptr->palette_to_index[i] = (png_byte)i;
}
- hash = (png_dsortpp)png_calloc(png_ptr, (png_uint_32)(769 *
+ hash = (png_dsortpp)png_calloc(png_ptr, (png_alloc_size_t)(769 *
(sizeof (png_dsortp))));
num_new_palette = num_palette;
@@ -623,7 +625,7 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette,
{
t = (png_dsortp)png_malloc_warn(png_ptr,
- (png_uint_32)(sizeof (png_dsort)));
+ (png_alloc_size_t)(sizeof (png_dsort)));
if (t == NULL)
break;
@@ -748,9 +750,9 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette,
png_size_t num_entries = ((png_size_t)1 << total_bits);
png_ptr->palette_lookup = (png_bytep)png_calloc(png_ptr,
- (png_uint_32)(num_entries * (sizeof (png_byte))));
+ (png_alloc_size_t)(num_entries * (sizeof (png_byte))));
- distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries *
+ distance = (png_bytep)png_malloc(png_ptr, (png_alloc_size_t)(num_entries *
(sizeof (png_byte))));
memset(distance, 0xff, num_entries * (sizeof (png_byte)));
@@ -3322,7 +3324,7 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
== png_ptr->trans_color.gray)
{
unsigned int tmp = *sp & (0x0f0f >> (4 - shift));
- tmp |=
+ tmp |=
(unsigned int)(png_ptr->background.gray << shift);
*sp = (png_byte)(tmp & 0xff);
}
diff --git a/thirdparty/libpng/pngrutil.c b/thirdparty/libpng/pngrutil.c
index a4fa71457b..8692933bd8 100644
--- a/thirdparty/libpng/pngrutil.c
+++ b/thirdparty/libpng/pngrutil.c
@@ -1,7 +1,7 @@
/* pngrutil.c - utilities to read a PNG file
*
- * Last changed in libpng 1.6.32 [August 24, 2017]
+ * Last changed in libpng 1.6.33 [September 28, 2017]
* Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
@@ -314,6 +314,7 @@ png_read_buffer(png_structrp png_ptr, png_alloc_size_t new_size, int warn)
if (buffer != NULL)
{
+ memset(buffer, 0, new_size); /* just in case */
png_ptr->read_buffer = buffer;
png_ptr->read_buffer_size = new_size;
}
@@ -673,6 +674,8 @@ png_decompress_chunk(png_structrp png_ptr,
if (text != NULL)
{
+ memset(text, 0, buffer_size);
+
ret = png_inflate(png_ptr, png_ptr->chunk_name, 1/*finish*/,
png_ptr->read_buffer + prefix_size, &lzsize,
text + prefix_size, newlength);
@@ -736,9 +739,7 @@ png_decompress_chunk(png_structrp png_ptr,
{
/* inflateReset failed, store the error message */
png_zstream_error(png_ptr, ret);
-
- if (ret == Z_STREAM_END)
- ret = PNG_UNEXPECTED_ZLIB_RETURN;
+ ret = PNG_UNEXPECTED_ZLIB_RETURN;
}
}
@@ -1476,7 +1477,7 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
/* Now read the tag table; a variable size buffer is
* needed at this point, allocate one for the whole
* profile. The header check has already validated
- * that none of these stuff will overflow.
+ * that none of this stuff will overflow.
*/
const png_uint_32 tag_count = png_get_uint_32(
profile_header+128);
@@ -1583,19 +1584,11 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
return;
}
}
-
- else if (size > 0)
- errmsg = "truncated";
-
-#ifndef __COVERITY__
- else
+ if (errmsg == NULL)
errmsg = png_ptr->zstream.msg;
-#endif
}
-
/* else png_icc_check_tag_table output an error */
}
-
else /* profile truncated */
errmsg = png_ptr->zstream.msg;
}
@@ -3144,28 +3137,28 @@ png_check_chunk_length(png_const_structrp png_ptr, const png_uint_32 length)
{
png_alloc_size_t limit = PNG_UINT_31_MAX;
- if (png_ptr->chunk_name != png_IDAT)
- {
# ifdef PNG_SET_USER_LIMITS_SUPPORTED
- if (png_ptr->user_chunk_malloc_max > 0 &&
- png_ptr->user_chunk_malloc_max < limit)
- limit = png_ptr->user_chunk_malloc_max;
+ if (png_ptr->user_chunk_malloc_max > 0 &&
+ png_ptr->user_chunk_malloc_max < limit)
+ limit = png_ptr->user_chunk_malloc_max;
# elif PNG_USER_CHUNK_MALLOC_MAX > 0
- if (PNG_USER_CHUNK_MALLOC_MAX < limit)
- limit = PNG_USER_CHUNK_MALLOC_MAX;
+ if (PNG_USER_CHUNK_MALLOC_MAX < limit)
+ limit = PNG_USER_CHUNK_MALLOC_MAX;
# endif
- }
- else
+ if (png_ptr->chunk_name == png_IDAT)
{
+ png_alloc_size_t idat_limit = PNG_UINT_31_MAX;
size_t row_factor =
(png_ptr->width * png_ptr->channels * (png_ptr->bit_depth > 8? 2: 1)
+ 1 + (png_ptr->interlaced? 6: 0));
if (png_ptr->height > PNG_UINT_32_MAX/row_factor)
- limit=PNG_UINT_31_MAX;
+ idat_limit=PNG_UINT_31_MAX;
else
- limit = png_ptr->height * row_factor;
- limit += 6 + 5*(limit/32566+1); /* zlib+deflate overhead */
- limit=limit < PNG_UINT_31_MAX? limit : PNG_UINT_31_MAX;
+ idat_limit = png_ptr->height * row_factor;
+ row_factor = row_factor > 32566? 32566 : row_factor;
+ idat_limit += 6 + 5*(idat_limit/row_factor+1); /* zlib+deflate overhead */
+ idat_limit=idat_limit < PNG_UINT_31_MAX? idat_limit : PNG_UINT_31_MAX;
+ limit = limit < idat_limit? idat_limit : limit;
}
if (length > limit)
diff --git a/thirdparty/libpng/pngtrans.c b/thirdparty/libpng/pngtrans.c
index 326ac33f0e..6882f0fd7b 100644
--- a/thirdparty/libpng/pngtrans.c
+++ b/thirdparty/libpng/pngtrans.c
@@ -1,7 +1,7 @@
/* pngtrans.c - transforms the data in a row (used by both readers and writers)
*
- * Last changed in libpng 1.6.30 [June 28, 2017]
+ * Last changed in libpng 1.6.33 [September 28, 2017]
* Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
@@ -609,7 +609,7 @@ png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start)
return; /* The filler channel has gone already */
/* Fix the rowbytes value. */
- row_info->rowbytes = (unsigned int)(dp-row);
+ row_info->rowbytes = (png_size_t)(dp-row);
}
#endif
@@ -708,7 +708,7 @@ png_do_check_palette_indexes(png_structrp png_ptr, png_row_infop row_info)
* forms produced on either GCC or MSVC.
*/
int padding = PNG_PADBITS(row_info->pixel_depth, row_info->width);
- png_bytep rp = png_ptr->row_buf + row_info->rowbytes;
+ png_bytep rp = png_ptr->row_buf + row_info->rowbytes - 1;
switch (row_info->bit_depth)
{
diff --git a/thirdparty/libpng/pngwrite.c b/thirdparty/libpng/pngwrite.c
index a7662acb71..a16d77ce00 100644
--- a/thirdparty/libpng/pngwrite.c
+++ b/thirdparty/libpng/pngwrite.c
@@ -1940,7 +1940,7 @@ png_image_write_main(png_voidp argument)
int colormap = (format & PNG_FORMAT_FLAG_COLORMAP);
int linear = !colormap && (format & PNG_FORMAT_FLAG_LINEAR); /* input */
int alpha = !colormap && (format & PNG_FORMAT_FLAG_ALPHA);
- int write_16bit = linear && !colormap && (display->convert_to_8bit == 0);
+ int write_16bit = linear && (display->convert_to_8bit == 0);
# ifdef PNG_BENIGN_ERRORS_SUPPORTED
/* Make sure we error out on any bad situation */
diff --git a/thirdparty/libsimplewebm/OpusVorbisDecoder.cpp b/thirdparty/libsimplewebm/OpusVorbisDecoder.cpp
index 06447aca57..c9e71eb733 100644
--- a/thirdparty/libsimplewebm/OpusVorbisDecoder.cpp
+++ b/thirdparty/libsimplewebm/OpusVorbisDecoder.cpp
@@ -122,6 +122,43 @@ bool OpusVorbisDecoder::getPCMS16(WebMFrame &frame, short *buffer, int &numOutSa
return false;
}
+bool OpusVorbisDecoder::getPCMF(WebMFrame &frame, float *buffer, int &numOutSamples) {
+ if (m_vorbis) {
+ m_vorbis->op.packet = frame.buffer;
+ m_vorbis->op.bytes = frame.bufferSize;
+
+ if (vorbis_synthesis(&m_vorbis->block, &m_vorbis->op))
+ return false;
+ if (vorbis_synthesis_blockin(&m_vorbis->dspState, &m_vorbis->block))
+ return false;
+
+ const int maxSamples = getBufferSamples();
+ int samplesCount, count = 0;
+ float **pcm;
+ while ((samplesCount = vorbis_synthesis_pcmout(&m_vorbis->dspState, &pcm))) {
+ const int toConvert = samplesCount <= maxSamples ? samplesCount : maxSamples;
+ for (int c = 0; c < m_channels; ++c) {
+ float *samples = pcm[c];
+ for (int i = 0, j = c; i < toConvert; ++i, j += m_channels) {
+ buffer[count + j] = samples[i];
+ }
+ }
+ vorbis_synthesis_read(&m_vorbis->dspState, toConvert);
+ count += toConvert;
+ }
+
+ numOutSamples = count;
+ return true;
+ } else if (m_opus) {
+ const int samples = opus_decode_float(m_opus, frame.buffer, frame.bufferSize, buffer, m_numSamples, 0);
+ if (samples >= 0) {
+ numOutSamples = samples;
+ return true;
+ }
+ }
+ return false;
+}
+
bool OpusVorbisDecoder::openVorbis(const WebMDemuxer &demuxer)
{
size_t extradataSize = 0;
diff --git a/thirdparty/libsimplewebm/OpusVorbisDecoder.hpp b/thirdparty/libsimplewebm/OpusVorbisDecoder.hpp
index bcdca731ee..b7619d6a25 100644
--- a/thirdparty/libsimplewebm/OpusVorbisDecoder.hpp
+++ b/thirdparty/libsimplewebm/OpusVorbisDecoder.hpp
@@ -44,7 +44,7 @@ public:
{
return m_numSamples;
}
-
+ bool getPCMF(WebMFrame &frame, float *buffer, int &numOutSamples);
bool getPCMS16(WebMFrame &frame, short *buffer, int &numOutSamples);
private:
diff --git a/thirdparty/libtheora/x86_vc/mmxencfrag.c b/thirdparty/libtheora/x86_vc/mmxencfrag.c
index ac9dacf377..94f1d06513 100644
--- a/thirdparty/libtheora/x86_vc/mmxencfrag.c
+++ b/thirdparty/libtheora/x86_vc/mmxencfrag.c
@@ -1,969 +1,969 @@
-/********************************************************************
- * *
- * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
- * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
- * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
- * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
- * *
- * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 *
- * by the Xiph.Org Foundation http://www.xiph.org/ *
- * *
- ********************************************************************
-
- function:
- last mod: $Id: dsp_mmx.c 14579 2008-03-12 06:42:40Z xiphmont $
-
- ********************************************************************/
-#include <stddef.h>
-#include "x86enc.h"
-
-#if defined(OC_X86_ASM)
-
-unsigned oc_enc_frag_sad_mmxext(const unsigned char *_src,
- const unsigned char *_ref,int _ystride){
- ptrdiff_t ret;
- __asm{
-#define SRC esi
-#define REF edx
-#define YSTRIDE ecx
-#define YSTRIDE3 edi
- mov YSTRIDE,_ystride
- mov SRC,_src
- mov REF,_ref
- /*Load the first 4 rows of each block.*/
- movq mm0,[SRC]
- movq mm1,[REF]
- movq mm2,[SRC][YSTRIDE]
- movq mm3,[REF][YSTRIDE]
- lea YSTRIDE3,[YSTRIDE+YSTRIDE*2]
- movq mm4,[SRC+YSTRIDE*2]
- movq mm5,[REF+YSTRIDE*2]
- movq mm6,[SRC+YSTRIDE3]
- movq mm7,[REF+YSTRIDE3]
- /*Compute their SADs and add them in mm0*/
- psadbw mm0,mm1
- psadbw mm2,mm3
- lea SRC,[SRC+YSTRIDE*4]
- paddw mm0,mm2
- lea REF,[REF+YSTRIDE*4]
- /*Load the next 3 rows as registers become available.*/
- movq mm2,[SRC]
- movq mm3,[REF]
- psadbw mm4,mm5
- psadbw mm6,mm7
- paddw mm0,mm4
- movq mm5,[REF+YSTRIDE]
- movq mm4,[SRC+YSTRIDE]
- paddw mm0,mm6
- movq mm7,[REF+YSTRIDE*2]
- movq mm6,[SRC+YSTRIDE*2]
- /*Start adding their SADs to mm0*/
- psadbw mm2,mm3
- psadbw mm4,mm5
- paddw mm0,mm2
- psadbw mm6,mm7
- /*Load last row as registers become available.*/
- movq mm2,[SRC+YSTRIDE3]
- movq mm3,[REF+YSTRIDE3]
- /*And finish adding up their SADs.*/
- paddw mm0,mm4
- psadbw mm2,mm3
- paddw mm0,mm6
- paddw mm0,mm2
- movd [ret],mm0
-#undef SRC
-#undef REF
-#undef YSTRIDE
-#undef YSTRIDE3
- }
- return (unsigned)ret;
-}
-
-unsigned oc_enc_frag_sad_thresh_mmxext(const unsigned char *_src,
- const unsigned char *_ref,int _ystride,unsigned _thresh){
- /*Early termination is for suckers.*/
- return oc_enc_frag_sad_mmxext(_src,_ref,_ystride);
-}
-
-#define OC_SAD2_LOOP __asm{ \
- /*We want to compute (mm0+mm1>>1) on unsigned bytes without overflow, but \
- pavgb computes (mm0+mm1+1>>1). \
- The latter is exactly 1 too large when the low bit of two corresponding \
- bytes is only set in one of them. \
- Therefore we pxor the operands, pand to mask out the low bits, and psubb to \
- correct the output of pavgb.*/ \
- __asm movq mm6,mm0 \
- __asm lea REF1,[REF1+YSTRIDE*2] \
- __asm pxor mm0,mm1 \
- __asm pavgb mm6,mm1 \
- __asm lea REF2,[REF2+YSTRIDE*2] \
- __asm movq mm1,mm2 \
- __asm pand mm0,mm7 \
- __asm pavgb mm2,mm3 \
- __asm pxor mm1,mm3 \
- __asm movq mm3,[REF2+YSTRIDE] \
- __asm psubb mm6,mm0 \
- __asm movq mm0,[REF1] \
- __asm pand mm1,mm7 \
- __asm psadbw mm4,mm6 \
- __asm movd mm6,RET \
- __asm psubb mm2,mm1 \
- __asm movq mm1,[REF2] \
- __asm lea SRC,[SRC+YSTRIDE*2] \
- __asm psadbw mm5,mm2 \
- __asm movq mm2,[REF1+YSTRIDE] \
- __asm paddw mm5,mm4 \
- __asm movq mm4,[SRC] \
- __asm paddw mm6,mm5 \
- __asm movq mm5,[SRC+YSTRIDE] \
- __asm movd RET,mm6 \
-}
-
-/*Same as above, but does not pre-load the next two rows.*/
-#define OC_SAD2_TAIL __asm{ \
- __asm movq mm6,mm0 \
- __asm pavgb mm0,mm1 \
- __asm pxor mm6,mm1 \
- __asm movq mm1,mm2 \
- __asm pand mm6,mm7 \
- __asm pavgb mm2,mm3 \
- __asm pxor mm1,mm3 \
- __asm psubb mm0,mm6 \
- __asm pand mm1,mm7 \
- __asm psadbw mm4,mm0 \
- __asm psubb mm2,mm1 \
- __asm movd mm6,RET \
- __asm psadbw mm5,mm2 \
- __asm paddw mm5,mm4 \
- __asm paddw mm6,mm5 \
- __asm movd RET,mm6 \
-}
-
-unsigned oc_enc_frag_sad2_thresh_mmxext(const unsigned char *_src,
- const unsigned char *_ref1,const unsigned char *_ref2,int _ystride,
- unsigned _thresh){
- ptrdiff_t ret;
- __asm{
-#define REF1 ecx
-#define REF2 edi
-#define YSTRIDE esi
-#define SRC edx
-#define RET eax
- mov YSTRIDE,_ystride
- mov SRC,_src
- mov REF1,_ref1
- mov REF2,_ref2
- movq mm0,[REF1]
- movq mm1,[REF2]
- movq mm2,[REF1+YSTRIDE]
- movq mm3,[REF2+YSTRIDE]
- xor RET,RET
- movq mm4,[SRC]
- pxor mm7,mm7
- pcmpeqb mm6,mm6
- movq mm5,[SRC+YSTRIDE]
- psubb mm7,mm6
- OC_SAD2_LOOP
- OC_SAD2_LOOP
- OC_SAD2_LOOP
- OC_SAD2_TAIL
- mov [ret],RET
-#undef REF1
-#undef REF2
-#undef YSTRIDE
-#undef SRC
-#undef RET
- }
- return (unsigned)ret;
-}
-
-/*Load an 8x4 array of pixel values from %[src] and %[ref] and compute their
- 16-bit difference in mm0...mm7.*/
-#define OC_LOAD_SUB_8x4(_off) __asm{ \
- __asm movd mm0,[_off+SRC] \
- __asm movd mm4,[_off+REF] \
- __asm movd mm1,[_off+SRC+SRC_YSTRIDE] \
- __asm lea SRC,[SRC+SRC_YSTRIDE*2] \
- __asm movd mm5,[_off+REF+REF_YSTRIDE] \
- __asm lea REF,[REF+REF_YSTRIDE*2] \
- __asm movd mm2,[_off+SRC] \
- __asm movd mm7,[_off+REF] \
- __asm movd mm3,[_off+SRC+SRC_YSTRIDE] \
- __asm movd mm6,[_off+REF+REF_YSTRIDE] \
- __asm punpcklbw mm0,mm4 \
- __asm lea SRC,[SRC+SRC_YSTRIDE*2] \
- __asm punpcklbw mm4,mm4 \
- __asm lea REF,[REF+REF_YSTRIDE*2] \
- __asm psubw mm0,mm4 \
- __asm movd mm4,[_off+SRC] \
- __asm movq [_off*2+BUF],mm0 \
- __asm movd mm0,[_off+REF] \
- __asm punpcklbw mm1,mm5 \
- __asm punpcklbw mm5,mm5 \
- __asm psubw mm1,mm5 \
- __asm movd mm5,[_off+SRC+SRC_YSTRIDE] \
- __asm punpcklbw mm2,mm7 \
- __asm punpcklbw mm7,mm7 \
- __asm psubw mm2,mm7 \
- __asm movd mm7,[_off+REF+REF_YSTRIDE] \
- __asm punpcklbw mm3,mm6 \
- __asm lea SRC,[SRC+SRC_YSTRIDE*2] \
- __asm punpcklbw mm6,mm6 \
- __asm psubw mm3,mm6 \
- __asm movd mm6,[_off+SRC] \
- __asm punpcklbw mm4,mm0 \
- __asm lea REF,[REF+REF_YSTRIDE*2] \
- __asm punpcklbw mm0,mm0 \
- __asm lea SRC,[SRC+SRC_YSTRIDE*2] \
- __asm psubw mm4,mm0 \
- __asm movd mm0,[_off+REF] \
- __asm punpcklbw mm5,mm7 \
- __asm neg SRC_YSTRIDE \
- __asm punpcklbw mm7,mm7 \
- __asm psubw mm5,mm7 \
- __asm movd mm7,[_off+SRC+SRC_YSTRIDE] \
- __asm punpcklbw mm6,mm0 \
- __asm lea REF,[REF+REF_YSTRIDE*2] \
- __asm punpcklbw mm0,mm0 \
- __asm neg REF_YSTRIDE \
- __asm psubw mm6,mm0 \
- __asm movd mm0,[_off+REF+REF_YSTRIDE] \
- __asm lea SRC,[SRC+SRC_YSTRIDE*8] \
- __asm punpcklbw mm7,mm0 \
- __asm neg SRC_YSTRIDE \
- __asm punpcklbw mm0,mm0 \
- __asm lea REF,[REF+REF_YSTRIDE*8] \
- __asm psubw mm7,mm0 \
- __asm neg REF_YSTRIDE \
- __asm movq mm0,[_off*2+BUF] \
-}
-
-/*Load an 8x4 array of pixel values from %[src] into %%mm0...%%mm7.*/
-#define OC_LOAD_8x4(_off) __asm{ \
- __asm movd mm0,[_off+SRC] \
- __asm movd mm1,[_off+SRC+YSTRIDE] \
- __asm movd mm2,[_off+SRC+YSTRIDE*2] \
- __asm pxor mm7,mm7 \
- __asm movd mm3,[_off+SRC+YSTRIDE3] \
- __asm punpcklbw mm0,mm7 \
- __asm movd mm4,[_off+SRC4] \
- __asm punpcklbw mm1,mm7 \
- __asm movd mm5,[_off+SRC4+YSTRIDE] \
- __asm punpcklbw mm2,mm7 \
- __asm movd mm6,[_off+SRC4+YSTRIDE*2] \
- __asm punpcklbw mm3,mm7 \
- __asm movd mm7,[_off+SRC4+YSTRIDE3] \
- __asm punpcklbw mm4,mm4 \
- __asm punpcklbw mm5,mm5 \
- __asm psrlw mm4,8 \
- __asm psrlw mm5,8 \
- __asm punpcklbw mm6,mm6 \
- __asm punpcklbw mm7,mm7 \
- __asm psrlw mm6,8 \
- __asm psrlw mm7,8 \
-}
-
-/*Performs the first two stages of an 8-point 1-D Hadamard transform.
- The transform is performed in place, except that outputs 0-3 are swapped with
- outputs 4-7.
- Outputs 2, 3, 6 and 7 from the second stage are negated (which allows us to
- perform this stage in place with no temporary registers).*/
-#define OC_HADAMARD_AB_8x4 __asm{ \
- /*Stage A: \
- Outputs 0-3 are swapped with 4-7 here.*/ \
- __asm paddw mm5,mm1 \
- __asm paddw mm6,mm2 \
- __asm paddw mm1,mm1 \
- __asm paddw mm2,mm2 \
- __asm psubw mm1,mm5 \
- __asm psubw mm2,mm6 \
- __asm paddw mm7,mm3 \
- __asm paddw mm4,mm0 \
- __asm paddw mm3,mm3 \
- __asm paddw mm0,mm0 \
- __asm psubw mm3,mm7 \
- __asm psubw mm0,mm4 \
- /*Stage B:*/ \
- __asm paddw mm0,mm2 \
- __asm paddw mm1,mm3 \
- __asm paddw mm4,mm6 \
- __asm paddw mm5,mm7 \
- __asm paddw mm2,mm2 \
- __asm paddw mm3,mm3 \
- __asm paddw mm6,mm6 \
- __asm paddw mm7,mm7 \
- __asm psubw mm2,mm0 \
- __asm psubw mm3,mm1 \
- __asm psubw mm6,mm4 \
- __asm psubw mm7,mm5 \
-}
-
-/*Performs the last stage of an 8-point 1-D Hadamard transform in place.
- Ouputs 1, 3, 5, and 7 are negated (which allows us to perform this stage in
- place with no temporary registers).*/
-#define OC_HADAMARD_C_8x4 __asm{ \
- /*Stage C:*/ \
- __asm paddw mm0,mm1 \
- __asm paddw mm2,mm3 \
- __asm paddw mm4,mm5 \
- __asm paddw mm6,mm7 \
- __asm paddw mm1,mm1 \
- __asm paddw mm3,mm3 \
- __asm paddw mm5,mm5 \
- __asm paddw mm7,mm7 \
- __asm psubw mm1,mm0 \
- __asm psubw mm3,mm2 \
- __asm psubw mm5,mm4 \
- __asm psubw mm7,mm6 \
-}
-
-/*Performs an 8-point 1-D Hadamard transform.
- The transform is performed in place, except that outputs 0-3 are swapped with
- outputs 4-7.
- Outputs 1, 2, 5 and 6 are negated (which allows us to perform the transform
- in place with no temporary registers).*/
-#define OC_HADAMARD_8x4 __asm{ \
- OC_HADAMARD_AB_8x4 \
- OC_HADAMARD_C_8x4 \
-}
-
-/*Performs the first part of the final stage of the Hadamard transform and
- summing of absolute values.
- At the end of this part, mm1 will contain the DC coefficient of the
- transform.*/
-#define OC_HADAMARD_C_ABS_ACCUM_A_8x4(_r6,_r7) __asm{ \
- /*We use the fact that \
- (abs(a+b)+abs(a-b))/2=max(abs(a),abs(b)) \
- to merge the final butterfly with the abs and the first stage of \
- accumulation. \
- Thus we can avoid using pabsw, which is not available until SSSE3. \
- Emulating pabsw takes 3 instructions, so the straightforward MMXEXT \
- implementation would be (3+3)*8+7=55 instructions (+4 for spilling \
- registers). \
- Even with pabsw, it would be (3+1)*8+7=39 instructions (with no spills). \
- This implementation is only 26 (+4 for spilling registers).*/ \
- __asm movq [_r7+BUF],mm7 \
- __asm movq [_r6+BUF],mm6 \
- /*mm7={0x7FFF}x4 \
- mm0=max(abs(mm0),abs(mm1))-0x7FFF*/ \
- __asm pcmpeqb mm7,mm7 \
- __asm movq mm6,mm0 \
- __asm psrlw mm7,1 \
- __asm paddw mm6,mm1 \
- __asm pmaxsw mm0,mm1 \
- __asm paddsw mm6,mm7 \
- __asm psubw mm0,mm6 \
- /*mm2=max(abs(mm2),abs(mm3))-0x7FFF \
- mm4=max(abs(mm4),abs(mm5))-0x7FFF*/ \
- __asm movq mm6,mm2 \
- __asm movq mm1,mm4 \
- __asm pmaxsw mm2,mm3 \
- __asm pmaxsw mm4,mm5 \
- __asm paddw mm6,mm3 \
- __asm paddw mm1,mm5 \
- __asm movq mm3,[_r7+BUF] \
-}
-
-/*Performs the second part of the final stage of the Hadamard transform and
- summing of absolute values.*/
-#define OC_HADAMARD_C_ABS_ACCUM_B_8x4(_r6,_r7) __asm{ \
- __asm paddsw mm6,mm7 \
- __asm movq mm5,[_r6+BUF] \
- __asm paddsw mm1,mm7 \
- __asm psubw mm2,mm6 \
- __asm psubw mm4,mm1 \
- /*mm7={1}x4 (needed for the horizontal add that follows) \
- mm0+=mm2+mm4+max(abs(mm3),abs(mm5))-0x7FFF*/ \
- __asm movq mm6,mm3 \
- __asm pmaxsw mm3,mm5 \
- __asm paddw mm0,mm2 \
- __asm paddw mm6,mm5 \
- __asm paddw mm0,mm4 \
- __asm paddsw mm6,mm7 \
- __asm paddw mm0,mm3 \
- __asm psrlw mm7,14 \
- __asm psubw mm0,mm6 \
-}
-
-/*Performs the last stage of an 8-point 1-D Hadamard transform, takes the
- absolute value of each component, and accumulates everything into mm0.
- This is the only portion of SATD which requires MMXEXT (we could use plain
- MMX, but it takes 4 instructions and an extra register to work around the
- lack of a pmaxsw, which is a pretty serious penalty).*/
-#define OC_HADAMARD_C_ABS_ACCUM_8x4(_r6,_r7) __asm{ \
- OC_HADAMARD_C_ABS_ACCUM_A_8x4(_r6,_r7) \
- OC_HADAMARD_C_ABS_ACCUM_B_8x4(_r6,_r7) \
-}
-
-/*Performs an 8-point 1-D Hadamard transform, takes the absolute value of each
- component, and accumulates everything into mm0.
- Note that mm0 will have an extra 4 added to each column, and that after
- removing this value, the remainder will be half the conventional value.*/
-#define OC_HADAMARD_ABS_ACCUM_8x4(_r6,_r7) __asm{ \
- OC_HADAMARD_AB_8x4 \
- OC_HADAMARD_C_ABS_ACCUM_8x4(_r6,_r7) \
-}
-
-/*Performs two 4x4 transposes (mostly) in place.
- On input, {mm0,mm1,mm2,mm3} contains rows {e,f,g,h}, and {mm4,mm5,mm6,mm7}
- contains rows {a,b,c,d}.
- On output, {0x40,0x50,0x60,0x70}+_off+BUF contains {e,f,g,h}^T, and
- {mm4,mm5,mm6,mm7} contains the transposed rows {a,b,c,d}^T.*/
-#define OC_TRANSPOSE_4x4x2(_off) __asm{ \
- /*First 4x4 transpose:*/ \
- __asm movq [0x10+_off+BUF],mm5 \
- /*mm0 = e3 e2 e1 e0 \
- mm1 = f3 f2 f1 f0 \
- mm2 = g3 g2 g1 g0 \
- mm3 = h3 h2 h1 h0*/ \
- __asm movq mm5,mm2 \
- __asm punpcklwd mm2,mm3 \
- __asm punpckhwd mm5,mm3 \
- __asm movq mm3,mm0 \
- __asm punpcklwd mm0,mm1 \
- __asm punpckhwd mm3,mm1 \
- /*mm0 = f1 e1 f0 e0 \
- mm3 = f3 e3 f2 e2 \
- mm2 = h1 g1 h0 g0 \
- mm5 = h3 g3 h2 g2*/ \
- __asm movq mm1,mm0 \
- __asm punpckldq mm0,mm2 \
- __asm punpckhdq mm1,mm2 \
- __asm movq mm2,mm3 \
- __asm punpckhdq mm3,mm5 \
- __asm movq [0x40+_off+BUF],mm0 \
- __asm punpckldq mm2,mm5 \
- /*mm0 = h0 g0 f0 e0 \
- mm1 = h1 g1 f1 e1 \
- mm2 = h2 g2 f2 e2 \
- mm3 = h3 g3 f3 e3*/ \
- __asm movq mm5,[0x10+_off+BUF] \
- /*Second 4x4 transpose:*/ \
- /*mm4 = a3 a2 a1 a0 \
- mm5 = b3 b2 b1 b0 \
- mm6 = c3 c2 c1 c0 \
- mm7 = d3 d2 d1 d0*/ \
- __asm movq mm0,mm6 \
- __asm punpcklwd mm6,mm7 \
- __asm movq [0x50+_off+BUF],mm1 \
- __asm punpckhwd mm0,mm7 \
- __asm movq mm7,mm4 \
- __asm punpcklwd mm4,mm5 \
- __asm movq [0x60+_off+BUF],mm2 \
- __asm punpckhwd mm7,mm5 \
- /*mm4 = b1 a1 b0 a0 \
- mm7 = b3 a3 b2 a2 \
- mm6 = d1 c1 d0 c0 \
- mm0 = d3 c3 d2 c2*/ \
- __asm movq mm5,mm4 \
- __asm punpckldq mm4,mm6 \
- __asm movq [0x70+_off+BUF],mm3 \
- __asm punpckhdq mm5,mm6 \
- __asm movq mm6,mm7 \
- __asm punpckhdq mm7,mm0 \
- __asm punpckldq mm6,mm0 \
- /*mm4 = d0 c0 b0 a0 \
- mm5 = d1 c1 b1 a1 \
- mm6 = d2 c2 b2 a2 \
- mm7 = d3 c3 b3 a3*/ \
-}
-
-static unsigned oc_int_frag_satd_thresh_mmxext(const unsigned char *_src,
- int _src_ystride,const unsigned char *_ref,int _ref_ystride,unsigned _thresh){
- OC_ALIGN8(ogg_int16_t buf[64]);
- ogg_int16_t *bufp;
- unsigned ret1;
- unsigned ret2;
- bufp=buf;
- __asm{
-#define SRC esi
-#define REF eax
-#define SRC_YSTRIDE ecx
-#define REF_YSTRIDE edx
-#define BUF edi
-#define RET eax
-#define RET2 edx
- mov SRC,_src
- mov SRC_YSTRIDE,_src_ystride
- mov REF,_ref
- mov REF_YSTRIDE,_ref_ystride
- mov BUF,bufp
- OC_LOAD_SUB_8x4(0x00)
- OC_HADAMARD_8x4
- OC_TRANSPOSE_4x4x2(0x00)
- /*Finish swapping out this 8x4 block to make room for the next one.
- mm0...mm3 have been swapped out already.*/
- movq [0x00+BUF],mm4
- movq [0x10+BUF],mm5
- movq [0x20+BUF],mm6
- movq [0x30+BUF],mm7
- OC_LOAD_SUB_8x4(0x04)
- OC_HADAMARD_8x4
- OC_TRANSPOSE_4x4x2(0x08)
- /*Here the first 4x4 block of output from the last transpose is the second
- 4x4 block of input for the next transform.
- We have cleverly arranged that it already be in the appropriate place, so
- we only have to do half the loads.*/
- movq mm1,[0x10+BUF]
- movq mm2,[0x20+BUF]
- movq mm3,[0x30+BUF]
- movq mm0,[0x00+BUF]
- OC_HADAMARD_ABS_ACCUM_8x4(0x28,0x38)
- /*Up to this point, everything fit in 16 bits (8 input + 1 for the
- difference + 2*3 for the two 8-point 1-D Hadamards - 1 for the abs - 1
- for the factor of two we dropped + 3 for the vertical accumulation).
- Now we finally have to promote things to dwords.
- We break this part out of OC_HADAMARD_ABS_ACCUM_8x4 to hide the long
- latency of pmaddwd by starting the next series of loads now.*/
- mov RET2,_thresh
- pmaddwd mm0,mm7
- movq mm1,[0x50+BUF]
- movq mm5,[0x58+BUF]
- movq mm4,mm0
- movq mm2,[0x60+BUF]
- punpckhdq mm0,mm0
- movq mm6,[0x68+BUF]
- paddd mm4,mm0
- movq mm3,[0x70+BUF]
- movd RET,mm4
- movq mm7,[0x78+BUF]
- /*The sums produced by OC_HADAMARD_ABS_ACCUM_8x4 each have an extra 4
- added to them, and a factor of two removed; correct the final sum here.*/
- lea RET,[RET+RET-32]
- movq mm0,[0x40+BUF]
- cmp RET,RET2
- movq mm4,[0x48+BUF]
- jae at_end
- OC_HADAMARD_ABS_ACCUM_8x4(0x68,0x78)
- pmaddwd mm0,mm7
- /*There isn't much to stick in here to hide the latency this time, but the
- alternative to pmaddwd is movq->punpcklwd->punpckhwd->paddd, whose
- latency is even worse.*/
- sub RET,32
- movq mm4,mm0
- punpckhdq mm0,mm0
- paddd mm4,mm0
- movd RET2,mm4
- lea RET,[RET+RET2*2]
- align 16
-at_end:
- mov ret1,RET
-#undef SRC
-#undef REF
-#undef SRC_YSTRIDE
-#undef REF_YSTRIDE
-#undef BUF
-#undef RET
-#undef RET2
- }
- return ret1;
-}
-
-unsigned oc_enc_frag_satd_thresh_mmxext(const unsigned char *_src,
- const unsigned char *_ref,int _ystride,unsigned _thresh){
- return oc_int_frag_satd_thresh_mmxext(_src,_ystride,_ref,_ystride,_thresh);
-}
-
-
-/*Our internal implementation of frag_copy2 takes an extra stride parameter so
- we can share code with oc_enc_frag_satd2_thresh_mmxext().*/
-static void oc_int_frag_copy2_mmxext(unsigned char *_dst,int _dst_ystride,
- const unsigned char *_src1,const unsigned char *_src2,int _src_ystride){
- __asm{
- /*Load the first 3 rows.*/
-#define DST_YSTRIDE edi
-#define SRC_YSTRIDE esi
-#define DST eax
-#define SRC1 edx
-#define SRC2 ecx
- mov DST_YSTRIDE,_dst_ystride
- mov SRC_YSTRIDE,_src_ystride
- mov DST,_dst
- mov SRC1,_src1
- mov SRC2,_src2
- movq mm0,[SRC1]
- movq mm1,[SRC2]
- movq mm2,[SRC1+SRC_YSTRIDE]
- lea SRC1,[SRC1+SRC_YSTRIDE*2]
- movq mm3,[SRC2+SRC_YSTRIDE]
- lea SRC2,[SRC2+SRC_YSTRIDE*2]
- pxor mm7,mm7
- movq mm4,[SRC1]
- pcmpeqb mm6,mm6
- movq mm5,[SRC2]
- /*mm7={1}x8.*/
- psubb mm7,mm6
- /*Start averaging mm0 and mm1 into mm6.*/
- movq mm6,mm0
- pxor mm0,mm1
- pavgb mm6,mm1
- /*mm1 is free, start averaging mm3 into mm2 using mm1.*/
- movq mm1,mm2
- pand mm0,mm7
- pavgb mm2,mm3
- pxor mm1,mm3
- /*mm3 is free.*/
- psubb mm6,mm0
- /*mm0 is free, start loading the next row.*/
- movq mm0,[SRC1+SRC_YSTRIDE]
- /*Start averaging mm5 and mm4 using mm3.*/
- movq mm3,mm4
- /*mm6 [row 0] is done; write it out.*/
- movq [DST],mm6
- pand mm1,mm7
- pavgb mm4,mm5
- psubb mm2,mm1
- /*mm1 is free, continue loading the next row.*/
- movq mm1,[SRC2+SRC_YSTRIDE]
- pxor mm3,mm5
- lea SRC1,[SRC1+SRC_YSTRIDE*2]
- /*mm2 [row 1] is done; write it out.*/
- movq [DST+DST_YSTRIDE],mm2
- pand mm3,mm7
- /*Start loading the next row.*/
- movq mm2,[SRC1]
- lea DST,[DST+DST_YSTRIDE*2]
- psubb mm4,mm3
- lea SRC2,[SRC2+SRC_YSTRIDE*2]
- /*mm4 [row 2] is done; write it out.*/
- movq [DST],mm4
- /*Continue loading the next row.*/
- movq mm3,[SRC2]
- /*Start averaging mm0 and mm1 into mm6.*/
- movq mm6,mm0
- pxor mm0,mm1
- /*Start loading the next row.*/
- movq mm4,[SRC1+SRC_YSTRIDE]
- pavgb mm6,mm1
- /*mm1 is free; start averaging mm3 into mm2 using mm1.*/
- movq mm1,mm2
- pand mm0,mm7
- /*Continue loading the next row.*/
- movq mm5,[SRC2+SRC_YSTRIDE]
- pavgb mm2,mm3
- lea SRC1,[SRC1+SRC_YSTRIDE*2]
- pxor mm1,mm3
- /*mm3 is free.*/
- psubb mm6,mm0
- /*mm0 is free, start loading the next row.*/
- movq mm0,[SRC1]
- /*Start averaging mm5 into mm4 using mm3.*/
- movq mm3,mm4
- /*mm6 [row 3] is done; write it out.*/
- movq [DST+DST_YSTRIDE],mm6
- pand mm1,mm7
- lea SRC2,[SRC2+SRC_YSTRIDE*2]
- pavgb mm4,mm5
- lea DST,[DST+DST_YSTRIDE*2]
- psubb mm2,mm1
- /*mm1 is free; continue loading the next row.*/
- movq mm1,[SRC2]
- pxor mm3,mm5
- /*mm2 [row 4] is done; write it out.*/
- movq [DST],mm2
- pand mm3,mm7
- /*Start loading the next row.*/
- movq mm2,[SRC1+SRC_YSTRIDE]
- psubb mm4,mm3
- /*Start averaging mm0 and mm1 into mm6.*/
- movq mm6,mm0
- /*Continue loading the next row.*/
- movq mm3,[SRC2+SRC_YSTRIDE]
- /*mm4 [row 5] is done; write it out.*/
- movq [DST+DST_YSTRIDE],mm4
- pxor mm0,mm1
- pavgb mm6,mm1
- /*mm4 is free; start averaging mm3 into mm2 using mm4.*/
- movq mm4,mm2
- pand mm0,mm7
- pavgb mm2,mm3
- pxor mm4,mm3
- lea DST,[DST+DST_YSTRIDE*2]
- psubb mm6,mm0
- pand mm4,mm7
- /*mm6 [row 6] is done, write it out.*/
- movq [DST],mm6
- psubb mm2,mm4
- /*mm2 [row 7] is done, write it out.*/
- movq [DST+DST_YSTRIDE],mm2
-#undef SRC1
-#undef SRC2
-#undef SRC_YSTRIDE
-#undef DST_YSTRIDE
-#undef DST
- }
-}
-
-unsigned oc_enc_frag_satd2_thresh_mmxext(const unsigned char *_src,
- const unsigned char *_ref1,const unsigned char *_ref2,int _ystride,
- unsigned _thresh){
- OC_ALIGN8(unsigned char ref[64]);
- oc_int_frag_copy2_mmxext(ref,8,_ref1,_ref2,_ystride);
- return oc_int_frag_satd_thresh_mmxext(_src,_ystride,ref,8,_thresh);
-}
-
-unsigned oc_enc_frag_intra_satd_mmxext(const unsigned char *_src,
- int _ystride){
- OC_ALIGN8(ogg_int16_t buf[64]);
- ogg_int16_t *bufp;
- unsigned ret1;
- unsigned ret2;
- bufp=buf;
- __asm{
-#define SRC eax
-#define SRC4 esi
-#define BUF edi
-#define RET eax
-#define RET_WORD ax
-#define RET2 ecx
-#define YSTRIDE edx
-#define YSTRIDE3 ecx
- mov SRC,_src
- mov BUF,bufp
- mov YSTRIDE,_ystride
- /* src4 = src+4*ystride */
- lea SRC4,[SRC+YSTRIDE*4]
- /* ystride3 = 3*ystride */
- lea YSTRIDE3,[YSTRIDE+YSTRIDE*2]
- OC_LOAD_8x4(0x00)
- OC_HADAMARD_8x4
- OC_TRANSPOSE_4x4x2(0x00)
- /*Finish swapping out this 8x4 block to make room for the next one.
- mm0...mm3 have been swapped out already.*/
- movq [0x00+BUF],mm4
- movq [0x10+BUF],mm5
- movq [0x20+BUF],mm6
- movq [0x30+BUF],mm7
- OC_LOAD_8x4(0x04)
- OC_HADAMARD_8x4
- OC_TRANSPOSE_4x4x2(0x08)
- /*Here the first 4x4 block of output from the last transpose is the second
- 4x4 block of input for the next transform.
- We have cleverly arranged that it already be in the appropriate place, so
- we only have to do half the loads.*/
- movq mm1,[0x10+BUF]
- movq mm2,[0x20+BUF]
- movq mm3,[0x30+BUF]
- movq mm0,[0x00+BUF]
- /*We split out the stages here so we can save the DC coefficient in the
- middle.*/
- OC_HADAMARD_AB_8x4
- OC_HADAMARD_C_ABS_ACCUM_A_8x4(0x28,0x38)
- movd RET,mm1
- OC_HADAMARD_C_ABS_ACCUM_B_8x4(0x28,0x38)
- /*Up to this point, everything fit in 16 bits (8 input + 1 for the
- difference + 2*3 for the two 8-point 1-D Hadamards - 1 for the abs - 1
- for the factor of two we dropped + 3 for the vertical accumulation).
- Now we finally have to promote things to dwords.
- We break this part out of OC_HADAMARD_ABS_ACCUM_8x4 to hide the long
- latency of pmaddwd by starting the next series of loads now.*/
- pmaddwd mm0,mm7
- movq mm1,[0x50+BUF]
- movq mm5,[0x58+BUF]
- movq mm2,[0x60+BUF]
- movq mm4,mm0
- movq mm6,[0x68+BUF]
- punpckhdq mm0,mm0
- movq mm3,[0x70+BUF]
- paddd mm4,mm0
- movq mm7,[0x78+BUF]
- movd RET2,mm4
- movq mm0,[0x40+BUF]
- movq mm4,[0x48+BUF]
- OC_HADAMARD_ABS_ACCUM_8x4(0x68,0x78)
- pmaddwd mm0,mm7
- /*We assume that the DC coefficient is always positive (which is true,
- because the input to the INTRA transform was not a difference).*/
- movzx RET,RET_WORD
- add RET2,RET2
- sub RET2,RET
- movq mm4,mm0
- punpckhdq mm0,mm0
- paddd mm4,mm0
- movd RET,mm4
- lea RET,[-64+RET2+RET*2]
- mov [ret1],RET
-#undef SRC
-#undef SRC4
-#undef BUF
-#undef RET
-#undef RET_WORD
-#undef RET2
-#undef YSTRIDE
-#undef YSTRIDE3
- }
- return ret1;
-}
-
-void oc_enc_frag_sub_mmx(ogg_int16_t _residue[64],
- const unsigned char *_src, const unsigned char *_ref,int _ystride){
- int i;
- __asm pxor mm7,mm7
- for(i=4;i-->0;){
- __asm{
-#define SRC edx
-#define YSTRIDE esi
-#define RESIDUE eax
-#define REF ecx
- mov YSTRIDE,_ystride
- mov RESIDUE,_residue
- mov SRC,_src
- mov REF,_ref
- /*mm0=[src]*/
- movq mm0,[SRC]
- /*mm1=[ref]*/
- movq mm1,[REF]
- /*mm4=[src+ystride]*/
- movq mm4,[SRC+YSTRIDE]
- /*mm5=[ref+ystride]*/
- movq mm5,[REF+YSTRIDE]
- /*Compute [src]-[ref].*/
- movq mm2,mm0
- punpcklbw mm0,mm7
- movq mm3,mm1
- punpckhbw mm2,mm7
- punpcklbw mm1,mm7
- punpckhbw mm3,mm7
- psubw mm0,mm1
- psubw mm2,mm3
- /*Compute [src+ystride]-[ref+ystride].*/
- movq mm1,mm4
- punpcklbw mm4,mm7
- movq mm3,mm5
- punpckhbw mm1,mm7
- lea SRC,[SRC+YSTRIDE*2]
- punpcklbw mm5,mm7
- lea REF,[REF+YSTRIDE*2]
- punpckhbw mm3,mm7
- psubw mm4,mm5
- psubw mm1,mm3
- /*Write the answer out.*/
- movq [RESIDUE+0x00],mm0
- movq [RESIDUE+0x08],mm2
- movq [RESIDUE+0x10],mm4
- movq [RESIDUE+0x18],mm1
- lea RESIDUE,[RESIDUE+0x20]
- mov _residue,RESIDUE
- mov _src,SRC
- mov _ref,REF
-#undef SRC
-#undef YSTRIDE
-#undef RESIDUE
-#undef REF
- }
- }
-}
-
-void oc_enc_frag_sub_128_mmx(ogg_int16_t _residue[64],
- const unsigned char *_src,int _ystride){
- __asm{
-#define YSTRIDE edx
-#define YSTRIDE3 edi
-#define RESIDUE ecx
-#define SRC eax
- mov YSTRIDE,_ystride
- mov RESIDUE,_residue
- mov SRC,_src
- /*mm0=[src]*/
- movq mm0,[SRC]
- /*mm1=[src+ystride]*/
- movq mm1,[SRC+YSTRIDE]
- /*mm6={-1}x4*/
- pcmpeqw mm6,mm6
- /*mm2=[src+2*ystride]*/
- movq mm2,[SRC+YSTRIDE*2]
- /*[ystride3]=3*[ystride]*/
- lea YSTRIDE3,[YSTRIDE+YSTRIDE*2]
- /*mm6={1}x4*/
- psllw mm6,15
- /*mm3=[src+3*ystride]*/
- movq mm3,[SRC+YSTRIDE3]
- /*mm6={128}x4*/
- psrlw mm6,8
- /*mm7=0*/
- pxor mm7,mm7
- /*[src]=[src]+4*[ystride]*/
- lea SRC,[SRC+YSTRIDE*4]
- /*Compute [src]-128 and [src+ystride]-128*/
- movq mm4,mm0
- punpcklbw mm0,mm7
- movq mm5,mm1
- punpckhbw mm4,mm7
- psubw mm0,mm6
- punpcklbw mm1,mm7
- psubw mm4,mm6
- punpckhbw mm5,mm7
- psubw mm1,mm6
- psubw mm5,mm6
- /*Write the answer out.*/
- movq [RESIDUE+0x00],mm0
- movq [RESIDUE+0x08],mm4
- movq [RESIDUE+0x10],mm1
- movq [RESIDUE+0x18],mm5
- /*mm0=[src+4*ystride]*/
- movq mm0,[SRC]
- /*mm1=[src+5*ystride]*/
- movq mm1,[SRC+YSTRIDE]
- /*Compute [src+2*ystride]-128 and [src+3*ystride]-128*/
- movq mm4,mm2
- punpcklbw mm2,mm7
- movq mm5,mm3
- punpckhbw mm4,mm7
- psubw mm2,mm6
- punpcklbw mm3,mm7
- psubw mm4,mm6
- punpckhbw mm5,mm7
- psubw mm3,mm6
- psubw mm5,mm6
- /*Write the answer out.*/
- movq [RESIDUE+0x20],mm2
- movq [RESIDUE+0x28],mm4
- movq [RESIDUE+0x30],mm3
- movq [RESIDUE+0x38],mm5
- /*Compute [src+6*ystride]-128 and [src+7*ystride]-128*/
- movq mm2,[SRC+YSTRIDE*2]
- movq mm3,[SRC+YSTRIDE3]
- movq mm4,mm0
- punpcklbw mm0,mm7
- movq mm5,mm1
- punpckhbw mm4,mm7
- psubw mm0,mm6
- punpcklbw mm1,mm7
- psubw mm4,mm6
- punpckhbw mm5,mm7
- psubw mm1,mm6
- psubw mm5,mm6
- /*Write the answer out.*/
- movq [RESIDUE+0x40],mm0
- movq [RESIDUE+0x48],mm4
- movq [RESIDUE+0x50],mm1
- movq [RESIDUE+0x58],mm5
- /*Compute [src+6*ystride]-128 and [src+7*ystride]-128*/
- movq mm4,mm2
- punpcklbw mm2,mm7
- movq mm5,mm3
- punpckhbw mm4,mm7
- psubw mm2,mm6
- punpcklbw mm3,mm7
- psubw mm4,mm6
- punpckhbw mm5,mm7
- psubw mm3,mm6
- psubw mm5,mm6
- /*Write the answer out.*/
- movq [RESIDUE+0x60],mm2
- movq [RESIDUE+0x68],mm4
- movq [RESIDUE+0x70],mm3
- movq [RESIDUE+0x78],mm5
-#undef YSTRIDE
-#undef YSTRIDE3
-#undef RESIDUE
-#undef SRC
- }
-}
-
-void oc_enc_frag_copy2_mmxext(unsigned char *_dst,
- const unsigned char *_src1,const unsigned char *_src2,int _ystride){
- oc_int_frag_copy2_mmxext(_dst,_ystride,_src1,_src2,_ystride);
-}
-
-#endif
+/********************************************************************
+ * *
+ * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
+ * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
+ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
+ * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
+ * *
+ * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 *
+ * by the Xiph.Org Foundation http://www.xiph.org/ *
+ * *
+ ********************************************************************
+
+ function:
+ last mod: $Id: dsp_mmx.c 14579 2008-03-12 06:42:40Z xiphmont $
+
+ ********************************************************************/
+#include <stddef.h>
+#include "x86enc.h"
+
+#if defined(OC_X86_ASM)
+
+unsigned oc_enc_frag_sad_mmxext(const unsigned char *_src,
+ const unsigned char *_ref,int _ystride){
+ ptrdiff_t ret;
+ __asm{
+#define SRC esi
+#define REF edx
+#define YSTRIDE ecx
+#define YSTRIDE3 edi
+ mov YSTRIDE,_ystride
+ mov SRC,_src
+ mov REF,_ref
+ /*Load the first 4 rows of each block.*/
+ movq mm0,[SRC]
+ movq mm1,[REF]
+ movq mm2,[SRC][YSTRIDE]
+ movq mm3,[REF][YSTRIDE]
+ lea YSTRIDE3,[YSTRIDE+YSTRIDE*2]
+ movq mm4,[SRC+YSTRIDE*2]
+ movq mm5,[REF+YSTRIDE*2]
+ movq mm6,[SRC+YSTRIDE3]
+ movq mm7,[REF+YSTRIDE3]
+ /*Compute their SADs and add them in mm0*/
+ psadbw mm0,mm1
+ psadbw mm2,mm3
+ lea SRC,[SRC+YSTRIDE*4]
+ paddw mm0,mm2
+ lea REF,[REF+YSTRIDE*4]
+ /*Load the next 3 rows as registers become available.*/
+ movq mm2,[SRC]
+ movq mm3,[REF]
+ psadbw mm4,mm5
+ psadbw mm6,mm7
+ paddw mm0,mm4
+ movq mm5,[REF+YSTRIDE]
+ movq mm4,[SRC+YSTRIDE]
+ paddw mm0,mm6
+ movq mm7,[REF+YSTRIDE*2]
+ movq mm6,[SRC+YSTRIDE*2]
+ /*Start adding their SADs to mm0*/
+ psadbw mm2,mm3
+ psadbw mm4,mm5
+ paddw mm0,mm2
+ psadbw mm6,mm7
+ /*Load last row as registers become available.*/
+ movq mm2,[SRC+YSTRIDE3]
+ movq mm3,[REF+YSTRIDE3]
+ /*And finish adding up their SADs.*/
+ paddw mm0,mm4
+ psadbw mm2,mm3
+ paddw mm0,mm6
+ paddw mm0,mm2
+ movd [ret],mm0
+#undef SRC
+#undef REF
+#undef YSTRIDE
+#undef YSTRIDE3
+ }
+ return (unsigned)ret;
+}
+
+unsigned oc_enc_frag_sad_thresh_mmxext(const unsigned char *_src,
+ const unsigned char *_ref,int _ystride,unsigned _thresh){
+ /*Early termination is for suckers.*/
+ return oc_enc_frag_sad_mmxext(_src,_ref,_ystride);
+}
+
+#define OC_SAD2_LOOP __asm{ \
+ /*We want to compute (mm0+mm1>>1) on unsigned bytes without overflow, but \
+ pavgb computes (mm0+mm1+1>>1). \
+ The latter is exactly 1 too large when the low bit of two corresponding \
+ bytes is only set in one of them. \
+ Therefore we pxor the operands, pand to mask out the low bits, and psubb to \
+ correct the output of pavgb.*/ \
+ __asm movq mm6,mm0 \
+ __asm lea REF1,[REF1+YSTRIDE*2] \
+ __asm pxor mm0,mm1 \
+ __asm pavgb mm6,mm1 \
+ __asm lea REF2,[REF2+YSTRIDE*2] \
+ __asm movq mm1,mm2 \
+ __asm pand mm0,mm7 \
+ __asm pavgb mm2,mm3 \
+ __asm pxor mm1,mm3 \
+ __asm movq mm3,[REF2+YSTRIDE] \
+ __asm psubb mm6,mm0 \
+ __asm movq mm0,[REF1] \
+ __asm pand mm1,mm7 \
+ __asm psadbw mm4,mm6 \
+ __asm movd mm6,RET \
+ __asm psubb mm2,mm1 \
+ __asm movq mm1,[REF2] \
+ __asm lea SRC,[SRC+YSTRIDE*2] \
+ __asm psadbw mm5,mm2 \
+ __asm movq mm2,[REF1+YSTRIDE] \
+ __asm paddw mm5,mm4 \
+ __asm movq mm4,[SRC] \
+ __asm paddw mm6,mm5 \
+ __asm movq mm5,[SRC+YSTRIDE] \
+ __asm movd RET,mm6 \
+}
+
+/*Same as above, but does not pre-load the next two rows.*/
+#define OC_SAD2_TAIL __asm{ \
+ __asm movq mm6,mm0 \
+ __asm pavgb mm0,mm1 \
+ __asm pxor mm6,mm1 \
+ __asm movq mm1,mm2 \
+ __asm pand mm6,mm7 \
+ __asm pavgb mm2,mm3 \
+ __asm pxor mm1,mm3 \
+ __asm psubb mm0,mm6 \
+ __asm pand mm1,mm7 \
+ __asm psadbw mm4,mm0 \
+ __asm psubb mm2,mm1 \
+ __asm movd mm6,RET \
+ __asm psadbw mm5,mm2 \
+ __asm paddw mm5,mm4 \
+ __asm paddw mm6,mm5 \
+ __asm movd RET,mm6 \
+}
+
+unsigned oc_enc_frag_sad2_thresh_mmxext(const unsigned char *_src,
+ const unsigned char *_ref1,const unsigned char *_ref2,int _ystride,
+ unsigned _thresh){
+ ptrdiff_t ret;
+ __asm{
+#define REF1 ecx
+#define REF2 edi
+#define YSTRIDE esi
+#define SRC edx
+#define RET eax
+ mov YSTRIDE,_ystride
+ mov SRC,_src
+ mov REF1,_ref1
+ mov REF2,_ref2
+ movq mm0,[REF1]
+ movq mm1,[REF2]
+ movq mm2,[REF1+YSTRIDE]
+ movq mm3,[REF2+YSTRIDE]
+ xor RET,RET
+ movq mm4,[SRC]
+ pxor mm7,mm7
+ pcmpeqb mm6,mm6
+ movq mm5,[SRC+YSTRIDE]
+ psubb mm7,mm6
+ OC_SAD2_LOOP
+ OC_SAD2_LOOP
+ OC_SAD2_LOOP
+ OC_SAD2_TAIL
+ mov [ret],RET
+#undef REF1
+#undef REF2
+#undef YSTRIDE
+#undef SRC
+#undef RET
+ }
+ return (unsigned)ret;
+}
+
+/*Load an 8x4 array of pixel values from %[src] and %[ref] and compute their
+ 16-bit difference in mm0...mm7.*/
+#define OC_LOAD_SUB_8x4(_off) __asm{ \
+ __asm movd mm0,[_off+SRC] \
+ __asm movd mm4,[_off+REF] \
+ __asm movd mm1,[_off+SRC+SRC_YSTRIDE] \
+ __asm lea SRC,[SRC+SRC_YSTRIDE*2] \
+ __asm movd mm5,[_off+REF+REF_YSTRIDE] \
+ __asm lea REF,[REF+REF_YSTRIDE*2] \
+ __asm movd mm2,[_off+SRC] \
+ __asm movd mm7,[_off+REF] \
+ __asm movd mm3,[_off+SRC+SRC_YSTRIDE] \
+ __asm movd mm6,[_off+REF+REF_YSTRIDE] \
+ __asm punpcklbw mm0,mm4 \
+ __asm lea SRC,[SRC+SRC_YSTRIDE*2] \
+ __asm punpcklbw mm4,mm4 \
+ __asm lea REF,[REF+REF_YSTRIDE*2] \
+ __asm psubw mm0,mm4 \
+ __asm movd mm4,[_off+SRC] \
+ __asm movq [_off*2+BUF],mm0 \
+ __asm movd mm0,[_off+REF] \
+ __asm punpcklbw mm1,mm5 \
+ __asm punpcklbw mm5,mm5 \
+ __asm psubw mm1,mm5 \
+ __asm movd mm5,[_off+SRC+SRC_YSTRIDE] \
+ __asm punpcklbw mm2,mm7 \
+ __asm punpcklbw mm7,mm7 \
+ __asm psubw mm2,mm7 \
+ __asm movd mm7,[_off+REF+REF_YSTRIDE] \
+ __asm punpcklbw mm3,mm6 \
+ __asm lea SRC,[SRC+SRC_YSTRIDE*2] \
+ __asm punpcklbw mm6,mm6 \
+ __asm psubw mm3,mm6 \
+ __asm movd mm6,[_off+SRC] \
+ __asm punpcklbw mm4,mm0 \
+ __asm lea REF,[REF+REF_YSTRIDE*2] \
+ __asm punpcklbw mm0,mm0 \
+ __asm lea SRC,[SRC+SRC_YSTRIDE*2] \
+ __asm psubw mm4,mm0 \
+ __asm movd mm0,[_off+REF] \
+ __asm punpcklbw mm5,mm7 \
+ __asm neg SRC_YSTRIDE \
+ __asm punpcklbw mm7,mm7 \
+ __asm psubw mm5,mm7 \
+ __asm movd mm7,[_off+SRC+SRC_YSTRIDE] \
+ __asm punpcklbw mm6,mm0 \
+ __asm lea REF,[REF+REF_YSTRIDE*2] \
+ __asm punpcklbw mm0,mm0 \
+ __asm neg REF_YSTRIDE \
+ __asm psubw mm6,mm0 \
+ __asm movd mm0,[_off+REF+REF_YSTRIDE] \
+ __asm lea SRC,[SRC+SRC_YSTRIDE*8] \
+ __asm punpcklbw mm7,mm0 \
+ __asm neg SRC_YSTRIDE \
+ __asm punpcklbw mm0,mm0 \
+ __asm lea REF,[REF+REF_YSTRIDE*8] \
+ __asm psubw mm7,mm0 \
+ __asm neg REF_YSTRIDE \
+ __asm movq mm0,[_off*2+BUF] \
+}
+
+/*Load an 8x4 array of pixel values from %[src] into %%mm0...%%mm7.*/
+#define OC_LOAD_8x4(_off) __asm{ \
+ __asm movd mm0,[_off+SRC] \
+ __asm movd mm1,[_off+SRC+YSTRIDE] \
+ __asm movd mm2,[_off+SRC+YSTRIDE*2] \
+ __asm pxor mm7,mm7 \
+ __asm movd mm3,[_off+SRC+YSTRIDE3] \
+ __asm punpcklbw mm0,mm7 \
+ __asm movd mm4,[_off+SRC4] \
+ __asm punpcklbw mm1,mm7 \
+ __asm movd mm5,[_off+SRC4+YSTRIDE] \
+ __asm punpcklbw mm2,mm7 \
+ __asm movd mm6,[_off+SRC4+YSTRIDE*2] \
+ __asm punpcklbw mm3,mm7 \
+ __asm movd mm7,[_off+SRC4+YSTRIDE3] \
+ __asm punpcklbw mm4,mm4 \
+ __asm punpcklbw mm5,mm5 \
+ __asm psrlw mm4,8 \
+ __asm psrlw mm5,8 \
+ __asm punpcklbw mm6,mm6 \
+ __asm punpcklbw mm7,mm7 \
+ __asm psrlw mm6,8 \
+ __asm psrlw mm7,8 \
+}
+
+/*Performs the first two stages of an 8-point 1-D Hadamard transform.
+ The transform is performed in place, except that outputs 0-3 are swapped with
+ outputs 4-7.
+ Outputs 2, 3, 6 and 7 from the second stage are negated (which allows us to
+ perform this stage in place with no temporary registers).*/
+#define OC_HADAMARD_AB_8x4 __asm{ \
+ /*Stage A: \
+ Outputs 0-3 are swapped with 4-7 here.*/ \
+ __asm paddw mm5,mm1 \
+ __asm paddw mm6,mm2 \
+ __asm paddw mm1,mm1 \
+ __asm paddw mm2,mm2 \
+ __asm psubw mm1,mm5 \
+ __asm psubw mm2,mm6 \
+ __asm paddw mm7,mm3 \
+ __asm paddw mm4,mm0 \
+ __asm paddw mm3,mm3 \
+ __asm paddw mm0,mm0 \
+ __asm psubw mm3,mm7 \
+ __asm psubw mm0,mm4 \
+ /*Stage B:*/ \
+ __asm paddw mm0,mm2 \
+ __asm paddw mm1,mm3 \
+ __asm paddw mm4,mm6 \
+ __asm paddw mm5,mm7 \
+ __asm paddw mm2,mm2 \
+ __asm paddw mm3,mm3 \
+ __asm paddw mm6,mm6 \
+ __asm paddw mm7,mm7 \
+ __asm psubw mm2,mm0 \
+ __asm psubw mm3,mm1 \
+ __asm psubw mm6,mm4 \
+ __asm psubw mm7,mm5 \
+}
+
+/*Performs the last stage of an 8-point 1-D Hadamard transform in place.
+ Ouputs 1, 3, 5, and 7 are negated (which allows us to perform this stage in
+ place with no temporary registers).*/
+#define OC_HADAMARD_C_8x4 __asm{ \
+ /*Stage C:*/ \
+ __asm paddw mm0,mm1 \
+ __asm paddw mm2,mm3 \
+ __asm paddw mm4,mm5 \
+ __asm paddw mm6,mm7 \
+ __asm paddw mm1,mm1 \
+ __asm paddw mm3,mm3 \
+ __asm paddw mm5,mm5 \
+ __asm paddw mm7,mm7 \
+ __asm psubw mm1,mm0 \
+ __asm psubw mm3,mm2 \
+ __asm psubw mm5,mm4 \
+ __asm psubw mm7,mm6 \
+}
+
+/*Performs an 8-point 1-D Hadamard transform.
+ The transform is performed in place, except that outputs 0-3 are swapped with
+ outputs 4-7.
+ Outputs 1, 2, 5 and 6 are negated (which allows us to perform the transform
+ in place with no temporary registers).*/
+#define OC_HADAMARD_8x4 __asm{ \
+ OC_HADAMARD_AB_8x4 \
+ OC_HADAMARD_C_8x4 \
+}
+
+/*Performs the first part of the final stage of the Hadamard transform and
+ summing of absolute values.
+ At the end of this part, mm1 will contain the DC coefficient of the
+ transform.*/
+#define OC_HADAMARD_C_ABS_ACCUM_A_8x4(_r6,_r7) __asm{ \
+ /*We use the fact that \
+ (abs(a+b)+abs(a-b))/2=max(abs(a),abs(b)) \
+ to merge the final butterfly with the abs and the first stage of \
+ accumulation. \
+ Thus we can avoid using pabsw, which is not available until SSSE3. \
+ Emulating pabsw takes 3 instructions, so the straightforward MMXEXT \
+ implementation would be (3+3)*8+7=55 instructions (+4 for spilling \
+ registers). \
+ Even with pabsw, it would be (3+1)*8+7=39 instructions (with no spills). \
+ This implementation is only 26 (+4 for spilling registers).*/ \
+ __asm movq [_r7+BUF],mm7 \
+ __asm movq [_r6+BUF],mm6 \
+ /*mm7={0x7FFF}x4 \
+ mm0=max(abs(mm0),abs(mm1))-0x7FFF*/ \
+ __asm pcmpeqb mm7,mm7 \
+ __asm movq mm6,mm0 \
+ __asm psrlw mm7,1 \
+ __asm paddw mm6,mm1 \
+ __asm pmaxsw mm0,mm1 \
+ __asm paddsw mm6,mm7 \
+ __asm psubw mm0,mm6 \
+ /*mm2=max(abs(mm2),abs(mm3))-0x7FFF \
+ mm4=max(abs(mm4),abs(mm5))-0x7FFF*/ \
+ __asm movq mm6,mm2 \
+ __asm movq mm1,mm4 \
+ __asm pmaxsw mm2,mm3 \
+ __asm pmaxsw mm4,mm5 \
+ __asm paddw mm6,mm3 \
+ __asm paddw mm1,mm5 \
+ __asm movq mm3,[_r7+BUF] \
+}
+
+/*Performs the second part of the final stage of the Hadamard transform and
+ summing of absolute values.*/
+#define OC_HADAMARD_C_ABS_ACCUM_B_8x4(_r6,_r7) __asm{ \
+ __asm paddsw mm6,mm7 \
+ __asm movq mm5,[_r6+BUF] \
+ __asm paddsw mm1,mm7 \
+ __asm psubw mm2,mm6 \
+ __asm psubw mm4,mm1 \
+ /*mm7={1}x4 (needed for the horizontal add that follows) \
+ mm0+=mm2+mm4+max(abs(mm3),abs(mm5))-0x7FFF*/ \
+ __asm movq mm6,mm3 \
+ __asm pmaxsw mm3,mm5 \
+ __asm paddw mm0,mm2 \
+ __asm paddw mm6,mm5 \
+ __asm paddw mm0,mm4 \
+ __asm paddsw mm6,mm7 \
+ __asm paddw mm0,mm3 \
+ __asm psrlw mm7,14 \
+ __asm psubw mm0,mm6 \
+}
+
+/*Performs the last stage of an 8-point 1-D Hadamard transform, takes the
+ absolute value of each component, and accumulates everything into mm0.
+ This is the only portion of SATD which requires MMXEXT (we could use plain
+ MMX, but it takes 4 instructions and an extra register to work around the
+ lack of a pmaxsw, which is a pretty serious penalty).*/
+#define OC_HADAMARD_C_ABS_ACCUM_8x4(_r6,_r7) __asm{ \
+ OC_HADAMARD_C_ABS_ACCUM_A_8x4(_r6,_r7) \
+ OC_HADAMARD_C_ABS_ACCUM_B_8x4(_r6,_r7) \
+}
+
+/*Performs an 8-point 1-D Hadamard transform, takes the absolute value of each
+ component, and accumulates everything into mm0.
+ Note that mm0 will have an extra 4 added to each column, and that after
+ removing this value, the remainder will be half the conventional value.*/
+#define OC_HADAMARD_ABS_ACCUM_8x4(_r6,_r7) __asm{ \
+ OC_HADAMARD_AB_8x4 \
+ OC_HADAMARD_C_ABS_ACCUM_8x4(_r6,_r7) \
+}
+
+/*Performs two 4x4 transposes (mostly) in place.
+ On input, {mm0,mm1,mm2,mm3} contains rows {e,f,g,h}, and {mm4,mm5,mm6,mm7}
+ contains rows {a,b,c,d}.
+ On output, {0x40,0x50,0x60,0x70}+_off+BUF contains {e,f,g,h}^T, and
+ {mm4,mm5,mm6,mm7} contains the transposed rows {a,b,c,d}^T.*/
+#define OC_TRANSPOSE_4x4x2(_off) __asm{ \
+ /*First 4x4 transpose:*/ \
+ __asm movq [0x10+_off+BUF],mm5 \
+ /*mm0 = e3 e2 e1 e0 \
+ mm1 = f3 f2 f1 f0 \
+ mm2 = g3 g2 g1 g0 \
+ mm3 = h3 h2 h1 h0*/ \
+ __asm movq mm5,mm2 \
+ __asm punpcklwd mm2,mm3 \
+ __asm punpckhwd mm5,mm3 \
+ __asm movq mm3,mm0 \
+ __asm punpcklwd mm0,mm1 \
+ __asm punpckhwd mm3,mm1 \
+ /*mm0 = f1 e1 f0 e0 \
+ mm3 = f3 e3 f2 e2 \
+ mm2 = h1 g1 h0 g0 \
+ mm5 = h3 g3 h2 g2*/ \
+ __asm movq mm1,mm0 \
+ __asm punpckldq mm0,mm2 \
+ __asm punpckhdq mm1,mm2 \
+ __asm movq mm2,mm3 \
+ __asm punpckhdq mm3,mm5 \
+ __asm movq [0x40+_off+BUF],mm0 \
+ __asm punpckldq mm2,mm5 \
+ /*mm0 = h0 g0 f0 e0 \
+ mm1 = h1 g1 f1 e1 \
+ mm2 = h2 g2 f2 e2 \
+ mm3 = h3 g3 f3 e3*/ \
+ __asm movq mm5,[0x10+_off+BUF] \
+ /*Second 4x4 transpose:*/ \
+ /*mm4 = a3 a2 a1 a0 \
+ mm5 = b3 b2 b1 b0 \
+ mm6 = c3 c2 c1 c0 \
+ mm7 = d3 d2 d1 d0*/ \
+ __asm movq mm0,mm6 \
+ __asm punpcklwd mm6,mm7 \
+ __asm movq [0x50+_off+BUF],mm1 \
+ __asm punpckhwd mm0,mm7 \
+ __asm movq mm7,mm4 \
+ __asm punpcklwd mm4,mm5 \
+ __asm movq [0x60+_off+BUF],mm2 \
+ __asm punpckhwd mm7,mm5 \
+ /*mm4 = b1 a1 b0 a0 \
+ mm7 = b3 a3 b2 a2 \
+ mm6 = d1 c1 d0 c0 \
+ mm0 = d3 c3 d2 c2*/ \
+ __asm movq mm5,mm4 \
+ __asm punpckldq mm4,mm6 \
+ __asm movq [0x70+_off+BUF],mm3 \
+ __asm punpckhdq mm5,mm6 \
+ __asm movq mm6,mm7 \
+ __asm punpckhdq mm7,mm0 \
+ __asm punpckldq mm6,mm0 \
+ /*mm4 = d0 c0 b0 a0 \
+ mm5 = d1 c1 b1 a1 \
+ mm6 = d2 c2 b2 a2 \
+ mm7 = d3 c3 b3 a3*/ \
+}
+
+static unsigned oc_int_frag_satd_thresh_mmxext(const unsigned char *_src,
+ int _src_ystride,const unsigned char *_ref,int _ref_ystride,unsigned _thresh){
+ OC_ALIGN8(ogg_int16_t buf[64]);
+ ogg_int16_t *bufp;
+ unsigned ret1;
+ unsigned ret2;
+ bufp=buf;
+ __asm{
+#define SRC esi
+#define REF eax
+#define SRC_YSTRIDE ecx
+#define REF_YSTRIDE edx
+#define BUF edi
+#define RET eax
+#define RET2 edx
+ mov SRC,_src
+ mov SRC_YSTRIDE,_src_ystride
+ mov REF,_ref
+ mov REF_YSTRIDE,_ref_ystride
+ mov BUF,bufp
+ OC_LOAD_SUB_8x4(0x00)
+ OC_HADAMARD_8x4
+ OC_TRANSPOSE_4x4x2(0x00)
+ /*Finish swapping out this 8x4 block to make room for the next one.
+ mm0...mm3 have been swapped out already.*/
+ movq [0x00+BUF],mm4
+ movq [0x10+BUF],mm5
+ movq [0x20+BUF],mm6
+ movq [0x30+BUF],mm7
+ OC_LOAD_SUB_8x4(0x04)
+ OC_HADAMARD_8x4
+ OC_TRANSPOSE_4x4x2(0x08)
+ /*Here the first 4x4 block of output from the last transpose is the second
+ 4x4 block of input for the next transform.
+ We have cleverly arranged that it already be in the appropriate place, so
+ we only have to do half the loads.*/
+ movq mm1,[0x10+BUF]
+ movq mm2,[0x20+BUF]
+ movq mm3,[0x30+BUF]
+ movq mm0,[0x00+BUF]
+ OC_HADAMARD_ABS_ACCUM_8x4(0x28,0x38)
+ /*Up to this point, everything fit in 16 bits (8 input + 1 for the
+ difference + 2*3 for the two 8-point 1-D Hadamards - 1 for the abs - 1
+ for the factor of two we dropped + 3 for the vertical accumulation).
+ Now we finally have to promote things to dwords.
+ We break this part out of OC_HADAMARD_ABS_ACCUM_8x4 to hide the long
+ latency of pmaddwd by starting the next series of loads now.*/
+ mov RET2,_thresh
+ pmaddwd mm0,mm7
+ movq mm1,[0x50+BUF]
+ movq mm5,[0x58+BUF]
+ movq mm4,mm0
+ movq mm2,[0x60+BUF]
+ punpckhdq mm0,mm0
+ movq mm6,[0x68+BUF]
+ paddd mm4,mm0
+ movq mm3,[0x70+BUF]
+ movd RET,mm4
+ movq mm7,[0x78+BUF]
+ /*The sums produced by OC_HADAMARD_ABS_ACCUM_8x4 each have an extra 4
+ added to them, and a factor of two removed; correct the final sum here.*/
+ lea RET,[RET+RET-32]
+ movq mm0,[0x40+BUF]
+ cmp RET,RET2
+ movq mm4,[0x48+BUF]
+ jae at_end
+ OC_HADAMARD_ABS_ACCUM_8x4(0x68,0x78)
+ pmaddwd mm0,mm7
+ /*There isn't much to stick in here to hide the latency this time, but the
+ alternative to pmaddwd is movq->punpcklwd->punpckhwd->paddd, whose
+ latency is even worse.*/
+ sub RET,32
+ movq mm4,mm0
+ punpckhdq mm0,mm0
+ paddd mm4,mm0
+ movd RET2,mm4
+ lea RET,[RET+RET2*2]
+ align 16
+at_end:
+ mov ret1,RET
+#undef SRC
+#undef REF
+#undef SRC_YSTRIDE
+#undef REF_YSTRIDE
+#undef BUF
+#undef RET
+#undef RET2
+ }
+ return ret1;
+}
+
+unsigned oc_enc_frag_satd_thresh_mmxext(const unsigned char *_src,
+ const unsigned char *_ref,int _ystride,unsigned _thresh){
+ return oc_int_frag_satd_thresh_mmxext(_src,_ystride,_ref,_ystride,_thresh);
+}
+
+
+/*Our internal implementation of frag_copy2 takes an extra stride parameter so
+ we can share code with oc_enc_frag_satd2_thresh_mmxext().*/
+static void oc_int_frag_copy2_mmxext(unsigned char *_dst,int _dst_ystride,
+ const unsigned char *_src1,const unsigned char *_src2,int _src_ystride){
+ __asm{
+ /*Load the first 3 rows.*/
+#define DST_YSTRIDE edi
+#define SRC_YSTRIDE esi
+#define DST eax
+#define SRC1 edx
+#define SRC2 ecx
+ mov DST_YSTRIDE,_dst_ystride
+ mov SRC_YSTRIDE,_src_ystride
+ mov DST,_dst
+ mov SRC1,_src1
+ mov SRC2,_src2
+ movq mm0,[SRC1]
+ movq mm1,[SRC2]
+ movq mm2,[SRC1+SRC_YSTRIDE]
+ lea SRC1,[SRC1+SRC_YSTRIDE*2]
+ movq mm3,[SRC2+SRC_YSTRIDE]
+ lea SRC2,[SRC2+SRC_YSTRIDE*2]
+ pxor mm7,mm7
+ movq mm4,[SRC1]
+ pcmpeqb mm6,mm6
+ movq mm5,[SRC2]
+ /*mm7={1}x8.*/
+ psubb mm7,mm6
+ /*Start averaging mm0 and mm1 into mm6.*/
+ movq mm6,mm0
+ pxor mm0,mm1
+ pavgb mm6,mm1
+ /*mm1 is free, start averaging mm3 into mm2 using mm1.*/
+ movq mm1,mm2
+ pand mm0,mm7
+ pavgb mm2,mm3
+ pxor mm1,mm3
+ /*mm3 is free.*/
+ psubb mm6,mm0
+ /*mm0 is free, start loading the next row.*/
+ movq mm0,[SRC1+SRC_YSTRIDE]
+ /*Start averaging mm5 and mm4 using mm3.*/
+ movq mm3,mm4
+ /*mm6 [row 0] is done; write it out.*/
+ movq [DST],mm6
+ pand mm1,mm7
+ pavgb mm4,mm5
+ psubb mm2,mm1
+ /*mm1 is free, continue loading the next row.*/
+ movq mm1,[SRC2+SRC_YSTRIDE]
+ pxor mm3,mm5
+ lea SRC1,[SRC1+SRC_YSTRIDE*2]
+ /*mm2 [row 1] is done; write it out.*/
+ movq [DST+DST_YSTRIDE],mm2
+ pand mm3,mm7
+ /*Start loading the next row.*/
+ movq mm2,[SRC1]
+ lea DST,[DST+DST_YSTRIDE*2]
+ psubb mm4,mm3
+ lea SRC2,[SRC2+SRC_YSTRIDE*2]
+ /*mm4 [row 2] is done; write it out.*/
+ movq [DST],mm4
+ /*Continue loading the next row.*/
+ movq mm3,[SRC2]
+ /*Start averaging mm0 and mm1 into mm6.*/
+ movq mm6,mm0
+ pxor mm0,mm1
+ /*Start loading the next row.*/
+ movq mm4,[SRC1+SRC_YSTRIDE]
+ pavgb mm6,mm1
+ /*mm1 is free; start averaging mm3 into mm2 using mm1.*/
+ movq mm1,mm2
+ pand mm0,mm7
+ /*Continue loading the next row.*/
+ movq mm5,[SRC2+SRC_YSTRIDE]
+ pavgb mm2,mm3
+ lea SRC1,[SRC1+SRC_YSTRIDE*2]
+ pxor mm1,mm3
+ /*mm3 is free.*/
+ psubb mm6,mm0
+ /*mm0 is free, start loading the next row.*/
+ movq mm0,[SRC1]
+ /*Start averaging mm5 into mm4 using mm3.*/
+ movq mm3,mm4
+ /*mm6 [row 3] is done; write it out.*/
+ movq [DST+DST_YSTRIDE],mm6
+ pand mm1,mm7
+ lea SRC2,[SRC2+SRC_YSTRIDE*2]
+ pavgb mm4,mm5
+ lea DST,[DST+DST_YSTRIDE*2]
+ psubb mm2,mm1
+ /*mm1 is free; continue loading the next row.*/
+ movq mm1,[SRC2]
+ pxor mm3,mm5
+ /*mm2 [row 4] is done; write it out.*/
+ movq [DST],mm2
+ pand mm3,mm7
+ /*Start loading the next row.*/
+ movq mm2,[SRC1+SRC_YSTRIDE]
+ psubb mm4,mm3
+ /*Start averaging mm0 and mm1 into mm6.*/
+ movq mm6,mm0
+ /*Continue loading the next row.*/
+ movq mm3,[SRC2+SRC_YSTRIDE]
+ /*mm4 [row 5] is done; write it out.*/
+ movq [DST+DST_YSTRIDE],mm4
+ pxor mm0,mm1
+ pavgb mm6,mm1
+ /*mm4 is free; start averaging mm3 into mm2 using mm4.*/
+ movq mm4,mm2
+ pand mm0,mm7
+ pavgb mm2,mm3
+ pxor mm4,mm3
+ lea DST,[DST+DST_YSTRIDE*2]
+ psubb mm6,mm0
+ pand mm4,mm7
+ /*mm6 [row 6] is done, write it out.*/
+ movq [DST],mm6
+ psubb mm2,mm4
+ /*mm2 [row 7] is done, write it out.*/
+ movq [DST+DST_YSTRIDE],mm2
+#undef SRC1
+#undef SRC2
+#undef SRC_YSTRIDE
+#undef DST_YSTRIDE
+#undef DST
+ }
+}
+
+unsigned oc_enc_frag_satd2_thresh_mmxext(const unsigned char *_src,
+ const unsigned char *_ref1,const unsigned char *_ref2,int _ystride,
+ unsigned _thresh){
+ OC_ALIGN8(unsigned char ref[64]);
+ oc_int_frag_copy2_mmxext(ref,8,_ref1,_ref2,_ystride);
+ return oc_int_frag_satd_thresh_mmxext(_src,_ystride,ref,8,_thresh);
+}
+
+unsigned oc_enc_frag_intra_satd_mmxext(const unsigned char *_src,
+ int _ystride){
+ OC_ALIGN8(ogg_int16_t buf[64]);
+ ogg_int16_t *bufp;
+ unsigned ret1;
+ unsigned ret2;
+ bufp=buf;
+ __asm{
+#define SRC eax
+#define SRC4 esi
+#define BUF edi
+#define RET eax
+#define RET_WORD ax
+#define RET2 ecx
+#define YSTRIDE edx
+#define YSTRIDE3 ecx
+ mov SRC,_src
+ mov BUF,bufp
+ mov YSTRIDE,_ystride
+ /* src4 = src+4*ystride */
+ lea SRC4,[SRC+YSTRIDE*4]
+ /* ystride3 = 3*ystride */
+ lea YSTRIDE3,[YSTRIDE+YSTRIDE*2]
+ OC_LOAD_8x4(0x00)
+ OC_HADAMARD_8x4
+ OC_TRANSPOSE_4x4x2(0x00)
+ /*Finish swapping out this 8x4 block to make room for the next one.
+ mm0...mm3 have been swapped out already.*/
+ movq [0x00+BUF],mm4
+ movq [0x10+BUF],mm5
+ movq [0x20+BUF],mm6
+ movq [0x30+BUF],mm7
+ OC_LOAD_8x4(0x04)
+ OC_HADAMARD_8x4
+ OC_TRANSPOSE_4x4x2(0x08)
+ /*Here the first 4x4 block of output from the last transpose is the second
+ 4x4 block of input for the next transform.
+ We have cleverly arranged that it already be in the appropriate place, so
+ we only have to do half the loads.*/
+ movq mm1,[0x10+BUF]
+ movq mm2,[0x20+BUF]
+ movq mm3,[0x30+BUF]
+ movq mm0,[0x00+BUF]
+ /*We split out the stages here so we can save the DC coefficient in the
+ middle.*/
+ OC_HADAMARD_AB_8x4
+ OC_HADAMARD_C_ABS_ACCUM_A_8x4(0x28,0x38)
+ movd RET,mm1
+ OC_HADAMARD_C_ABS_ACCUM_B_8x4(0x28,0x38)
+ /*Up to this point, everything fit in 16 bits (8 input + 1 for the
+ difference + 2*3 for the two 8-point 1-D Hadamards - 1 for the abs - 1
+ for the factor of two we dropped + 3 for the vertical accumulation).
+ Now we finally have to promote things to dwords.
+ We break this part out of OC_HADAMARD_ABS_ACCUM_8x4 to hide the long
+ latency of pmaddwd by starting the next series of loads now.*/
+ pmaddwd mm0,mm7
+ movq mm1,[0x50+BUF]
+ movq mm5,[0x58+BUF]
+ movq mm2,[0x60+BUF]
+ movq mm4,mm0
+ movq mm6,[0x68+BUF]
+ punpckhdq mm0,mm0
+ movq mm3,[0x70+BUF]
+ paddd mm4,mm0
+ movq mm7,[0x78+BUF]
+ movd RET2,mm4
+ movq mm0,[0x40+BUF]
+ movq mm4,[0x48+BUF]
+ OC_HADAMARD_ABS_ACCUM_8x4(0x68,0x78)
+ pmaddwd mm0,mm7
+ /*We assume that the DC coefficient is always positive (which is true,
+ because the input to the INTRA transform was not a difference).*/
+ movzx RET,RET_WORD
+ add RET2,RET2
+ sub RET2,RET
+ movq mm4,mm0
+ punpckhdq mm0,mm0
+ paddd mm4,mm0
+ movd RET,mm4
+ lea RET,[-64+RET2+RET*2]
+ mov [ret1],RET
+#undef SRC
+#undef SRC4
+#undef BUF
+#undef RET
+#undef RET_WORD
+#undef RET2
+#undef YSTRIDE
+#undef YSTRIDE3
+ }
+ return ret1;
+}
+
+void oc_enc_frag_sub_mmx(ogg_int16_t _residue[64],
+ const unsigned char *_src, const unsigned char *_ref,int _ystride){
+ int i;
+ __asm pxor mm7,mm7
+ for(i=4;i-->0;){
+ __asm{
+#define SRC edx
+#define YSTRIDE esi
+#define RESIDUE eax
+#define REF ecx
+ mov YSTRIDE,_ystride
+ mov RESIDUE,_residue
+ mov SRC,_src
+ mov REF,_ref
+ /*mm0=[src]*/
+ movq mm0,[SRC]
+ /*mm1=[ref]*/
+ movq mm1,[REF]
+ /*mm4=[src+ystride]*/
+ movq mm4,[SRC+YSTRIDE]
+ /*mm5=[ref+ystride]*/
+ movq mm5,[REF+YSTRIDE]
+ /*Compute [src]-[ref].*/
+ movq mm2,mm0
+ punpcklbw mm0,mm7
+ movq mm3,mm1
+ punpckhbw mm2,mm7
+ punpcklbw mm1,mm7
+ punpckhbw mm3,mm7
+ psubw mm0,mm1
+ psubw mm2,mm3
+ /*Compute [src+ystride]-[ref+ystride].*/
+ movq mm1,mm4
+ punpcklbw mm4,mm7
+ movq mm3,mm5
+ punpckhbw mm1,mm7
+ lea SRC,[SRC+YSTRIDE*2]
+ punpcklbw mm5,mm7
+ lea REF,[REF+YSTRIDE*2]
+ punpckhbw mm3,mm7
+ psubw mm4,mm5
+ psubw mm1,mm3
+ /*Write the answer out.*/
+ movq [RESIDUE+0x00],mm0
+ movq [RESIDUE+0x08],mm2
+ movq [RESIDUE+0x10],mm4
+ movq [RESIDUE+0x18],mm1
+ lea RESIDUE,[RESIDUE+0x20]
+ mov _residue,RESIDUE
+ mov _src,SRC
+ mov _ref,REF
+#undef SRC
+#undef YSTRIDE
+#undef RESIDUE
+#undef REF
+ }
+ }
+}
+
+void oc_enc_frag_sub_128_mmx(ogg_int16_t _residue[64],
+ const unsigned char *_src,int _ystride){
+ __asm{
+#define YSTRIDE edx
+#define YSTRIDE3 edi
+#define RESIDUE ecx
+#define SRC eax
+ mov YSTRIDE,_ystride
+ mov RESIDUE,_residue
+ mov SRC,_src
+ /*mm0=[src]*/
+ movq mm0,[SRC]
+ /*mm1=[src+ystride]*/
+ movq mm1,[SRC+YSTRIDE]
+ /*mm6={-1}x4*/
+ pcmpeqw mm6,mm6
+ /*mm2=[src+2*ystride]*/
+ movq mm2,[SRC+YSTRIDE*2]
+ /*[ystride3]=3*[ystride]*/
+ lea YSTRIDE3,[YSTRIDE+YSTRIDE*2]
+ /*mm6={1}x4*/
+ psllw mm6,15
+ /*mm3=[src+3*ystride]*/
+ movq mm3,[SRC+YSTRIDE3]
+ /*mm6={128}x4*/
+ psrlw mm6,8
+ /*mm7=0*/
+ pxor mm7,mm7
+ /*[src]=[src]+4*[ystride]*/
+ lea SRC,[SRC+YSTRIDE*4]
+ /*Compute [src]-128 and [src+ystride]-128*/
+ movq mm4,mm0
+ punpcklbw mm0,mm7
+ movq mm5,mm1
+ punpckhbw mm4,mm7
+ psubw mm0,mm6
+ punpcklbw mm1,mm7
+ psubw mm4,mm6
+ punpckhbw mm5,mm7
+ psubw mm1,mm6
+ psubw mm5,mm6
+ /*Write the answer out.*/
+ movq [RESIDUE+0x00],mm0
+ movq [RESIDUE+0x08],mm4
+ movq [RESIDUE+0x10],mm1
+ movq [RESIDUE+0x18],mm5
+ /*mm0=[src+4*ystride]*/
+ movq mm0,[SRC]
+ /*mm1=[src+5*ystride]*/
+ movq mm1,[SRC+YSTRIDE]
+ /*Compute [src+2*ystride]-128 and [src+3*ystride]-128*/
+ movq mm4,mm2
+ punpcklbw mm2,mm7
+ movq mm5,mm3
+ punpckhbw mm4,mm7
+ psubw mm2,mm6
+ punpcklbw mm3,mm7
+ psubw mm4,mm6
+ punpckhbw mm5,mm7
+ psubw mm3,mm6
+ psubw mm5,mm6
+ /*Write the answer out.*/
+ movq [RESIDUE+0x20],mm2
+ movq [RESIDUE+0x28],mm4
+ movq [RESIDUE+0x30],mm3
+ movq [RESIDUE+0x38],mm5
+ /*Compute [src+6*ystride]-128 and [src+7*ystride]-128*/
+ movq mm2,[SRC+YSTRIDE*2]
+ movq mm3,[SRC+YSTRIDE3]
+ movq mm4,mm0
+ punpcklbw mm0,mm7
+ movq mm5,mm1
+ punpckhbw mm4,mm7
+ psubw mm0,mm6
+ punpcklbw mm1,mm7
+ psubw mm4,mm6
+ punpckhbw mm5,mm7
+ psubw mm1,mm6
+ psubw mm5,mm6
+ /*Write the answer out.*/
+ movq [RESIDUE+0x40],mm0
+ movq [RESIDUE+0x48],mm4
+ movq [RESIDUE+0x50],mm1
+ movq [RESIDUE+0x58],mm5
+ /*Compute [src+6*ystride]-128 and [src+7*ystride]-128*/
+ movq mm4,mm2
+ punpcklbw mm2,mm7
+ movq mm5,mm3
+ punpckhbw mm4,mm7
+ psubw mm2,mm6
+ punpcklbw mm3,mm7
+ psubw mm4,mm6
+ punpckhbw mm5,mm7
+ psubw mm3,mm6
+ psubw mm5,mm6
+ /*Write the answer out.*/
+ movq [RESIDUE+0x60],mm2
+ movq [RESIDUE+0x68],mm4
+ movq [RESIDUE+0x70],mm3
+ movq [RESIDUE+0x78],mm5
+#undef YSTRIDE
+#undef YSTRIDE3
+#undef RESIDUE
+#undef SRC
+ }
+}
+
+void oc_enc_frag_copy2_mmxext(unsigned char *_dst,
+ const unsigned char *_src1,const unsigned char *_src2,int _ystride){
+ oc_int_frag_copy2_mmxext(_dst,_ystride,_src1,_src2,_ystride);
+}
+
+#endif
diff --git a/thirdparty/libtheora/x86_vc/mmxfdct.c b/thirdparty/libtheora/x86_vc/mmxfdct.c
index dcf17c9fa7..d908ce2413 100644
--- a/thirdparty/libtheora/x86_vc/mmxfdct.c
+++ b/thirdparty/libtheora/x86_vc/mmxfdct.c
@@ -1,670 +1,670 @@
-/********************************************************************
- * *
- * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
- * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
- * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
- * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
- * *
- * THE Theora SOURCE CODE IS COPYRIGHT (C) 1999-2006 *
- * by the Xiph.Org Foundation http://www.xiph.org/ *
- * *
- ********************************************************************/
- /*MMX fDCT implementation for x86_32*/
-/*$Id: fdct_ses2.c 14579 2008-03-12 06:42:40Z xiphmont $*/
-#include "x86enc.h"
-
-#if defined(OC_X86_ASM)
-
-#define OC_FDCT_STAGE1_8x4 __asm{ \
- /*Stage 1:*/ \
- /*mm0=t7'=t0-t7*/ \
- __asm psubw mm0,mm7 \
- __asm paddw mm7,mm7 \
- /*mm1=t6'=t1-t6*/ \
- __asm psubw mm1, mm6 \
- __asm paddw mm6,mm6 \
- /*mm2=t5'=t2-t5*/ \
- __asm psubw mm2,mm5 \
- __asm paddw mm5,mm5 \
- /*mm3=t4'=t3-t4*/ \
- __asm psubw mm3,mm4 \
- __asm paddw mm4,mm4 \
- /*mm7=t0'=t0+t7*/ \
- __asm paddw mm7,mm0 \
- /*mm6=t1'=t1+t6*/ \
- __asm paddw mm6,mm1 \
- /*mm5=t2'=t2+t5*/ \
- __asm paddw mm5,mm2 \
- /*mm4=t3'=t3+t4*/ \
- __asm paddw mm4,mm3\
-}
-
-#define OC_FDCT8x4(_r0,_r1,_r2,_r3,_r4,_r5,_r6,_r7) __asm{ \
- /*Stage 2:*/ \
- /*mm7=t3''=t0'-t3'*/ \
- __asm psubw mm7,mm4 \
- __asm paddw mm4,mm4 \
- /*mm6=t2''=t1'-t2'*/ \
- __asm psubw mm6,mm5 \
- __asm movq [Y+_r6],mm7 \
- __asm paddw mm5,mm5 \
- /*mm1=t5''=t6'-t5'*/ \
- __asm psubw mm1,mm2 \
- __asm movq [Y+_r2],mm6 \
- /*mm4=t0''=t0'+t3'*/ \
- __asm paddw mm4,mm7 \
- __asm paddw mm2,mm2 \
- /*mm5=t1''=t1'+t2'*/ \
- __asm movq [Y+_r0],mm4 \
- __asm paddw mm5,mm6 \
- /*mm2=t6''=t6'+t5'*/ \
- __asm paddw mm2,mm1 \
- __asm movq [Y+_r4],mm5 \
- /*mm0=t7', mm1=t5'', mm2=t6'', mm3=t4'.*/ \
- /*mm4, mm5, mm6, mm7 are free.*/ \
- /*Stage 3:*/ \
- /*mm6={2}x4, mm7={27146,0xB500>>1}x2*/ \
- __asm mov A,0x5A806A0A \
- __asm pcmpeqb mm6,mm6 \
- __asm movd mm7,A \
- __asm psrlw mm6,15 \
- __asm punpckldq mm7,mm7 \
- __asm paddw mm6,mm6 \
- /*mm0=0, m2={-1}x4 \
- mm5:mm4=t5''*27146+0xB500*/ \
- __asm movq mm4,mm1 \
- __asm movq mm5,mm1 \
- __asm punpcklwd mm4,mm6 \
- __asm movq [Y+_r3],mm2 \
- __asm pmaddwd mm4,mm7 \
- __asm movq [Y+_r7],mm0 \
- __asm punpckhwd mm5,mm6 \
- __asm pxor mm0,mm0 \
- __asm pmaddwd mm5,mm7 \
- __asm pcmpeqb mm2,mm2 \
- /*mm2=t6'', mm1=t5''+(t5''!=0) \
- mm4=(t5''*27146+0xB500>>16)*/ \
- __asm pcmpeqw mm0,mm1 \
- __asm psrad mm4,16 \
- __asm psubw mm0,mm2 \
- __asm movq mm2, [Y+_r3] \
- __asm psrad mm5,16 \
- __asm paddw mm1,mm0 \
- __asm packssdw mm4,mm5 \
- /*mm4=s=(t5''*27146+0xB500>>16)+t5''+(t5''!=0)>>1*/ \
- __asm paddw mm4,mm1 \
- __asm movq mm0, [Y+_r7] \
- __asm psraw mm4,1 \
- __asm movq mm1,mm3 \
- /*mm3=t4''=t4'+s*/ \
- __asm paddw mm3,mm4 \
- /*mm1=t5'''=t4'-s*/ \
- __asm psubw mm1,mm4 \
- /*mm1=0, mm3={-1}x4 \
- mm5:mm4=t6''*27146+0xB500*/ \
- __asm movq mm4,mm2 \
- __asm movq mm5,mm2 \
- __asm punpcklwd mm4,mm6 \
- __asm movq [Y+_r5],mm1 \
- __asm pmaddwd mm4,mm7 \
- __asm movq [Y+_r1],mm3 \
- __asm punpckhwd mm5,mm6 \
- __asm pxor mm1,mm1 \
- __asm pmaddwd mm5,mm7 \
- __asm pcmpeqb mm3,mm3 \
- /*mm2=t6''+(t6''!=0), mm4=(t6''*27146+0xB500>>16)*/ \
- __asm psrad mm4,16 \
- __asm pcmpeqw mm1,mm2 \
- __asm psrad mm5,16 \
- __asm psubw mm1,mm3 \
- __asm packssdw mm4,mm5 \
- __asm paddw mm2,mm1 \
- /*mm1=t1'' \
- mm4=s=(t6''*27146+0xB500>>16)+t6''+(t6''!=0)>>1*/ \
- __asm paddw mm4,mm2 \
- __asm movq mm1,[Y+_r4] \
- __asm psraw mm4,1 \
- __asm movq mm2,mm0 \
- /*mm7={54491-0x7FFF,0x7FFF}x2 \
- mm0=t7''=t7'+s*/ \
- __asm paddw mm0,mm4 \
- /*mm2=t6'''=t7'-s*/ \
- __asm psubw mm2,mm4 \
- /*Stage 4:*/ \
- /*mm0=0, mm2=t0'' \
- mm5:mm4=t1''*27146+0xB500*/ \
- __asm movq mm4,mm1 \
- __asm movq mm5,mm1 \
- __asm punpcklwd mm4,mm6 \
- __asm movq [Y+_r3],mm2 \
- __asm pmaddwd mm4,mm7 \
- __asm movq mm2,[Y+_r0] \
- __asm punpckhwd mm5,mm6 \
- __asm movq [Y+_r7],mm0 \
- __asm pmaddwd mm5,mm7 \
- __asm pxor mm0,mm0 \
- /*mm7={27146,0x4000>>1}x2 \
- mm0=s=(t1''*27146+0xB500>>16)+t1''+(t1''!=0)*/ \
- __asm psrad mm4,16 \
- __asm mov A,0x20006A0A \
- __asm pcmpeqw mm0,mm1 \
- __asm movd mm7,A \
- __asm psrad mm5,16 \
- __asm psubw mm0,mm3 \
- __asm packssdw mm4,mm5 \
- __asm paddw mm0,mm1 \
- __asm punpckldq mm7,mm7 \
- __asm paddw mm0,mm4 \
- /*mm6={0x00000E3D}x2 \
- mm1=-(t0''==0), mm5:mm4=t0''*27146+0x4000*/ \
- __asm movq mm4,mm2 \
- __asm movq mm5,mm2 \
- __asm punpcklwd mm4,mm6 \
- __asm mov A,0x0E3D \
- __asm pmaddwd mm4,mm7 \
- __asm punpckhwd mm5,mm6 \
- __asm movd mm6,A \
- __asm pmaddwd mm5,mm7 \
- __asm pxor mm1,mm1 \
- __asm punpckldq mm6,mm6 \
- __asm pcmpeqw mm1,mm2 \
- /*mm4=r=(t0''*27146+0x4000>>16)+t0''+(t0''!=0)*/ \
- __asm psrad mm4,16 \
- __asm psubw mm1,mm3 \
- __asm psrad mm5,16 \
- __asm paddw mm2,mm1 \
- __asm packssdw mm4,mm5 \
- __asm movq mm1,[Y+_r5] \
- __asm paddw mm4,mm2 \
- /*mm2=t6'', mm0=_y[0]=u=r+s>>1 \
- The naive implementation could cause overflow, so we use \
- u=(r&s)+((r^s)>>1).*/ \
- __asm movq mm2,[Y+_r3] \
- __asm movq mm7,mm0 \
- __asm pxor mm0,mm4 \
- __asm pand mm7,mm4 \
- __asm psraw mm0,1 \
- __asm mov A,0x7FFF54DC \
- __asm paddw mm0,mm7 \
- __asm movd mm7,A \
- /*mm7={54491-0x7FFF,0x7FFF}x2 \
- mm4=_y[4]=v=r-u*/ \
- __asm psubw mm4,mm0 \
- __asm punpckldq mm7,mm7 \
- __asm movq [Y+_r4],mm4 \
- /*mm0=0, mm7={36410}x4 \
- mm1=(t5'''!=0), mm5:mm4=54491*t5'''+0x0E3D*/ \
- __asm movq mm4,mm1 \
- __asm movq mm5,mm1 \
- __asm punpcklwd mm4,mm1 \
- __asm mov A,0x8E3A8E3A \
- __asm pmaddwd mm4,mm7 \
- __asm movq [Y+_r0],mm0 \
- __asm punpckhwd mm5,mm1 \
- __asm pxor mm0,mm0 \
- __asm pmaddwd mm5,mm7 \
- __asm pcmpeqw mm1,mm0 \
- __asm movd mm7,A \
- __asm psubw mm1,mm3 \
- __asm punpckldq mm7,mm7 \
- __asm paddd mm4,mm6 \
- __asm paddd mm5,mm6 \
- /*mm0=0 \
- mm3:mm1=36410*t6'''+((t5'''!=0)<<16)*/ \
- __asm movq mm6,mm2 \
- __asm movq mm3,mm2 \
- __asm pmulhw mm6,mm7 \
- __asm paddw mm1,mm2 \
- __asm pmullw mm3,mm7 \
- __asm pxor mm0,mm0 \
- __asm paddw mm6,mm1 \
- __asm movq mm1,mm3 \
- __asm punpckhwd mm3,mm6 \
- __asm punpcklwd mm1,mm6 \
- /*mm3={-1}x4, mm6={1}x4 \
- mm4=_y[5]=u=(54491*t5'''+36410*t6'''+0x0E3D>>16)+(t5'''!=0)*/ \
- __asm paddd mm5,mm3 \
- __asm paddd mm4,mm1 \
- __asm psrad mm5,16 \
- __asm pxor mm6,mm6 \
- __asm psrad mm4,16 \
- __asm pcmpeqb mm3,mm3 \
- __asm packssdw mm4,mm5 \
- __asm psubw mm6,mm3 \
- /*mm1=t7'', mm7={26568,0x3400}x2 \
- mm2=s=t6'''-(36410*u>>16)*/ \
- __asm movq mm1,mm4 \
- __asm mov A,0x340067C8 \
- __asm pmulhw mm4,mm7 \
- __asm movd mm7,A \
- __asm movq [Y+_r5],mm1 \
- __asm punpckldq mm7,mm7 \
- __asm paddw mm4,mm1 \
- __asm movq mm1,[Y+_r7] \
- __asm psubw mm2,mm4 \
- /*mm6={0x00007B1B}x2 \
- mm0=(s!=0), mm5:mm4=s*26568+0x3400*/ \
- __asm movq mm4,mm2 \
- __asm movq mm5,mm2 \
- __asm punpcklwd mm4,mm6 \
- __asm pcmpeqw mm0,mm2 \
- __asm pmaddwd mm4,mm7 \
- __asm mov A,0x7B1B \
- __asm punpckhwd mm5,mm6 \
- __asm movd mm6,A \
- __asm pmaddwd mm5,mm7 \
- __asm psubw mm0,mm3 \
- __asm punpckldq mm6,mm6 \
- /*mm7={64277-0x7FFF,0x7FFF}x2 \
- mm2=_y[3]=v=(s*26568+0x3400>>17)+s+(s!=0)*/ \
- __asm psrad mm4,17 \
- __asm paddw mm2,mm0 \
- __asm psrad mm5,17 \
- __asm mov A,0x7FFF7B16 \
- __asm packssdw mm4,mm5 \
- __asm movd mm7,A \
- __asm paddw mm2,mm4 \
- __asm punpckldq mm7,mm7 \
- /*mm0=0, mm7={12785}x4 \
- mm1=(t7''!=0), mm2=t4'', mm5:mm4=64277*t7''+0x7B1B*/ \
- __asm movq mm4,mm1 \
- __asm movq mm5,mm1 \
- __asm movq [Y+_r3],mm2 \
- __asm punpcklwd mm4,mm1 \
- __asm movq mm2,[Y+_r1] \
- __asm pmaddwd mm4,mm7 \
- __asm mov A,0x31F131F1 \
- __asm punpckhwd mm5,mm1 \
- __asm pxor mm0,mm0 \
- __asm pmaddwd mm5,mm7 \
- __asm pcmpeqw mm1,mm0 \
- __asm movd mm7,A \
- __asm psubw mm1,mm3 \
- __asm punpckldq mm7,mm7 \
- __asm paddd mm4,mm6 \
- __asm paddd mm5,mm6 \
- /*mm3:mm1=12785*t4'''+((t7''!=0)<<16)*/ \
- __asm movq mm6,mm2 \
- __asm movq mm3,mm2 \
- __asm pmulhw mm6,mm7 \
- __asm pmullw mm3,mm7 \
- __asm paddw mm6,mm1 \
- __asm movq mm1,mm3 \
- __asm punpckhwd mm3,mm6 \
- __asm punpcklwd mm1,mm6 \
- /*mm3={-1}x4, mm6={1}x4 \
- mm4=_y[1]=u=(12785*t4'''+64277*t7''+0x7B1B>>16)+(t7''!=0)*/ \
- __asm paddd mm5,mm3 \
- __asm paddd mm4,mm1 \
- __asm psrad mm5,16 \
- __asm pxor mm6,mm6 \
- __asm psrad mm4,16 \
- __asm pcmpeqb mm3,mm3 \
- __asm packssdw mm4,mm5 \
- __asm psubw mm6,mm3 \
- /*mm1=t3'', mm7={20539,0x3000}x2 \
- mm4=s=(12785*u>>16)-t4''*/ \
- __asm movq [Y+_r1],mm4 \
- __asm pmulhw mm4,mm7 \
- __asm mov A,0x3000503B \
- __asm movq mm1,[Y+_r6] \
- __asm movd mm7,A \
- __asm psubw mm4,mm2 \
- __asm punpckldq mm7,mm7 \
- /*mm6={0x00006CB7}x2 \
- mm0=(s!=0), mm5:mm4=s*20539+0x3000*/ \
- __asm movq mm5,mm4 \
- __asm movq mm2,mm4 \
- __asm punpcklwd mm4,mm6 \
- __asm pcmpeqw mm0,mm2 \
- __asm pmaddwd mm4,mm7 \
- __asm mov A,0x6CB7 \
- __asm punpckhwd mm5,mm6 \
- __asm movd mm6,A \
- __asm pmaddwd mm5,mm7 \
- __asm psubw mm0,mm3 \
- __asm punpckldq mm6,mm6 \
- /*mm7={60547-0x7FFF,0x7FFF}x2 \
- mm2=_y[7]=v=(s*20539+0x3000>>20)+s+(s!=0)*/ \
- __asm psrad mm4,20 \
- __asm paddw mm2,mm0 \
- __asm psrad mm5,20 \
- __asm mov A,0x7FFF6C84 \
- __asm packssdw mm4,mm5 \
- __asm movd mm7,A \
- __asm paddw mm2,mm4 \
- __asm punpckldq mm7,mm7 \
- /*mm0=0, mm7={25080}x4 \
- mm2=t2'', mm5:mm4=60547*t3''+0x6CB7*/ \
- __asm movq mm4,mm1 \
- __asm movq mm5,mm1 \
- __asm movq [Y+_r7],mm2 \
- __asm punpcklwd mm4,mm1 \
- __asm movq mm2,[Y+_r2] \
- __asm pmaddwd mm4,mm7 \
- __asm mov A,0x61F861F8 \
- __asm punpckhwd mm5,mm1 \
- __asm pxor mm0,mm0 \
- __asm pmaddwd mm5,mm7 \
- __asm movd mm7,A \
- __asm pcmpeqw mm1,mm0 \
- __asm psubw mm1,mm3 \
- __asm punpckldq mm7,mm7 \
- __asm paddd mm4,mm6 \
- __asm paddd mm5,mm6 \
- /*mm3:mm1=25080*t2''+((t3''!=0)<<16)*/ \
- __asm movq mm6,mm2 \
- __asm movq mm3,mm2 \
- __asm pmulhw mm6,mm7 \
- __asm pmullw mm3,mm7 \
- __asm paddw mm6,mm1 \
- __asm movq mm1,mm3 \
- __asm punpckhwd mm3,mm6 \
- __asm punpcklwd mm1,mm6 \
- /*mm1={-1}x4 \
- mm4=u=(25080*t2''+60547*t3''+0x6CB7>>16)+(t3''!=0)*/ \
- __asm paddd mm5,mm3 \
- __asm paddd mm4,mm1 \
- __asm psrad mm5,16 \
- __asm mov A,0x28005460 \
- __asm psrad mm4,16 \
- __asm pcmpeqb mm1,mm1 \
- __asm packssdw mm4,mm5 \
- /*mm5={1}x4, mm6=_y[2]=u, mm7={21600,0x2800}x2 \
- mm4=s=(25080*u>>16)-t2''*/ \
- __asm movq mm6,mm4 \
- __asm pmulhw mm4,mm7 \
- __asm pxor mm5,mm5 \
- __asm movd mm7,A \
- __asm psubw mm5,mm1 \
- __asm punpckldq mm7,mm7 \
- __asm psubw mm4,mm2 \
- /*mm2=s+(s!=0) \
- mm4:mm3=s*21600+0x2800*/ \
- __asm movq mm3,mm4 \
- __asm movq mm2,mm4 \
- __asm punpckhwd mm4,mm5 \
- __asm pcmpeqw mm0,mm2 \
- __asm pmaddwd mm4,mm7 \
- __asm psubw mm0,mm1 \
- __asm punpcklwd mm3,mm5 \
- __asm paddw mm2,mm0 \
- __asm pmaddwd mm3,mm7 \
- /*mm0=_y[4], mm1=_y[7], mm4=_y[0], mm5=_y[5] \
- mm3=_y[6]=v=(s*21600+0x2800>>18)+s+(s!=0)*/ \
- __asm movq mm0,[Y+_r4] \
- __asm psrad mm4,18 \
- __asm movq mm5,[Y+_r5] \
- __asm psrad mm3,18 \
- __asm movq mm1,[Y+_r7] \
- __asm packssdw mm3,mm4 \
- __asm movq mm4,[Y+_r0] \
- __asm paddw mm3,mm2 \
-}
-
-/*On input, mm4=_y[0], mm6=_y[2], mm0=_y[4], mm5=_y[5], mm3=_y[6], mm1=_y[7].
- On output, {_y[4],mm1,mm2,mm3} contains the transpose of _y[4...7] and
- {mm4,mm5,mm6,mm7} contains the transpose of _y[0...3].*/
-#define OC_TRANSPOSE8x4(_r0,_r1,_r2,_r3,_r4,_r5,_r6,_r7) __asm{ \
- /*First 4x4 transpose:*/ \
- /*mm0 = e3 e2 e1 e0 \
- mm5 = f3 f2 f1 f0 \
- mm3 = g3 g2 g1 g0 \
- mm1 = h3 h2 h1 h0*/ \
- __asm movq mm2,mm0 \
- __asm punpcklwd mm0,mm5 \
- __asm punpckhwd mm2,mm5 \
- __asm movq mm5,mm3 \
- __asm punpcklwd mm3,mm1 \
- __asm punpckhwd mm5,mm1 \
- /*mm0 = f1 e1 f0 e0 \
- mm2 = f3 e3 f2 e2 \
- mm3 = h1 g1 h0 g0 \
- mm5 = h3 g3 h2 g2*/ \
- __asm movq mm1,mm0 \
- __asm punpckldq mm0,mm3 \
- __asm movq [Y+_r4],mm0 \
- __asm punpckhdq mm1,mm3 \
- __asm movq mm0,[Y+_r1] \
- __asm movq mm3,mm2 \
- __asm punpckldq mm2,mm5 \
- __asm punpckhdq mm3,mm5 \
- __asm movq mm5,[Y+_r3] \
- /*_y[4] = h0 g0 f0 e0 \
- mm1 = h1 g1 f1 e1 \
- mm2 = h2 g2 f2 e2 \
- mm3 = h3 g3 f3 e3*/ \
- /*Second 4x4 transpose:*/ \
- /*mm4 = a3 a2 a1 a0 \
- mm0 = b3 b2 b1 b0 \
- mm6 = c3 c2 c1 c0 \
- mm5 = d3 d2 d1 d0*/ \
- __asm movq mm7,mm4 \
- __asm punpcklwd mm4,mm0 \
- __asm punpckhwd mm7,mm0 \
- __asm movq mm0,mm6 \
- __asm punpcklwd mm6,mm5 \
- __asm punpckhwd mm0,mm5 \
- /*mm4 = b1 a1 b0 a0 \
- mm7 = b3 a3 b2 a2 \
- mm6 = d1 c1 d0 c0 \
- mm0 = d3 c3 d2 c2*/ \
- __asm movq mm5,mm4 \
- __asm punpckldq mm4,mm6 \
- __asm punpckhdq mm5,mm6 \
- __asm movq mm6,mm7 \
- __asm punpckhdq mm7,mm0 \
- __asm punpckldq mm6,mm0 \
- /*mm4 = d0 c0 b0 a0 \
- mm5 = d1 c1 b1 a1 \
- mm6 = d2 c2 b2 a2 \
- mm7 = d3 c3 b3 a3*/ \
-}
-
-/*MMX implementation of the fDCT.*/
-void oc_enc_fdct8x8_mmx(ogg_int16_t _y[64],const ogg_int16_t _x[64]){
- ptrdiff_t a;
- __asm{
-#define Y eax
-#define A ecx
-#define X edx
- /*Add two extra bits of working precision to improve accuracy; any more and
- we could overflow.*/
- /*We also add biases to correct for some systematic error that remains in
- the full fDCT->iDCT round trip.*/
- mov X, _x
- mov Y, _y
- movq mm0,[0x00+X]
- movq mm1,[0x10+X]
- movq mm2,[0x20+X]
- movq mm3,[0x30+X]
- pcmpeqb mm4,mm4
- pxor mm7,mm7
- movq mm5,mm0
- psllw mm0,2
- pcmpeqw mm5,mm7
- movq mm7,[0x70+X]
- psllw mm1,2
- psubw mm5,mm4
- psllw mm2,2
- mov A,1
- pslld mm5,16
- movd mm6,A
- psllq mm5,16
- mov A,0x10001
- psllw mm3,2
- movd mm4,A
- punpckhwd mm5,mm6
- psubw mm1,mm6
- movq mm6,[0x60+X]
- paddw mm0,mm5
- movq mm5,[0x50+X]
- paddw mm0,mm4
- movq mm4,[0x40+X]
- /*We inline stage1 of the transform here so we can get better instruction
- scheduling with the shifts.*/
- /*mm0=t7'=t0-t7*/
- psllw mm7,2
- psubw mm0,mm7
- psllw mm6,2
- paddw mm7,mm7
- /*mm1=t6'=t1-t6*/
- psllw mm5,2
- psubw mm1,mm6
- psllw mm4,2
- paddw mm6,mm6
- /*mm2=t5'=t2-t5*/
- psubw mm2,mm5
- paddw mm5,mm5
- /*mm3=t4'=t3-t4*/
- psubw mm3,mm4
- paddw mm4,mm4
- /*mm7=t0'=t0+t7*/
- paddw mm7,mm0
- /*mm6=t1'=t1+t6*/
- paddw mm6,mm1
- /*mm5=t2'=t2+t5*/
- paddw mm5,mm2
- /*mm4=t3'=t3+t4*/
- paddw mm4,mm3
- OC_FDCT8x4(0x00,0x10,0x20,0x30,0x40,0x50,0x60,0x70)
- OC_TRANSPOSE8x4(0x00,0x10,0x20,0x30,0x40,0x50,0x60,0x70)
- /*Swap out this 8x4 block for the next one.*/
- movq mm0,[0x08+X]
- movq [0x30+Y],mm7
- movq mm7,[0x78+X]
- movq [0x50+Y],mm1
- movq mm1,[0x18+X]
- movq [0x20+Y],mm6
- movq mm6,[0x68+X]
- movq [0x60+Y],mm2
- movq mm2,[0x28+X]
- movq [0x10+Y],mm5
- movq mm5,[0x58+X]
- movq [0x70+Y],mm3
- movq mm3,[0x38+X]
- /*And increase its working precision, too.*/
- psllw mm0,2
- movq [0x00+Y],mm4
- psllw mm7,2
- movq mm4,[0x48+X]
- /*We inline stage1 of the transform here so we can get better instruction
- scheduling with the shifts.*/
- /*mm0=t7'=t0-t7*/
- psubw mm0,mm7
- psllw mm1,2
- paddw mm7,mm7
- psllw mm6,2
- /*mm1=t6'=t1-t6*/
- psubw mm1,mm6
- psllw mm2,2
- paddw mm6,mm6
- psllw mm5,2
- /*mm2=t5'=t2-t5*/
- psubw mm2,mm5
- psllw mm3,2
- paddw mm5,mm5
- psllw mm4,2
- /*mm3=t4'=t3-t4*/
- psubw mm3,mm4
- paddw mm4,mm4
- /*mm7=t0'=t0+t7*/
- paddw mm7,mm0
- /*mm6=t1'=t1+t6*/
- paddw mm6,mm1
- /*mm5=t2'=t2+t5*/
- paddw mm5,mm2
- /*mm4=t3'=t3+t4*/
- paddw mm4,mm3
- OC_FDCT8x4(0x08,0x18,0x28,0x38,0x48,0x58,0x68,0x78)
- OC_TRANSPOSE8x4(0x08,0x18,0x28,0x38,0x48,0x58,0x68,0x78)
- /*Here the first 4x4 block of output from the last transpose is the second
- 4x4 block of input for the next transform.
- We have cleverly arranged that it already be in the appropriate place,
- so we only have to do half the stores and loads.*/
- movq mm0,[0x00+Y]
- movq [0x58+Y],mm1
- movq mm1,[0x10+Y]
- movq [0x68+Y],mm2
- movq mm2,[0x20+Y]
- movq [0x78+Y],mm3
- movq mm3,[0x30+Y]
- OC_FDCT_STAGE1_8x4
- OC_FDCT8x4(0x00,0x10,0x20,0x30,0x08,0x18,0x28,0x38)
- OC_TRANSPOSE8x4(0x00,0x10,0x20,0x30,0x08,0x18,0x28,0x38)
- /*mm0={-2}x4*/
- pcmpeqw mm0,mm0
- paddw mm0,mm0
- /*Round the results.*/
- psubw mm1,mm0
- psubw mm2,mm0
- psraw mm1,2
- psubw mm3,mm0
- movq [0x18+Y],mm1
- psraw mm2,2
- psubw mm4,mm0
- movq mm1,[0x08+Y]
- psraw mm3,2
- psubw mm5,mm0
- psraw mm4,2
- psubw mm6,mm0
- psraw mm5,2
- psubw mm7,mm0
- psraw mm6,2
- psubw mm1,mm0
- psraw mm7,2
- movq mm0,[0x40+Y]
- psraw mm1,2
- movq [0x30+Y],mm7
- movq mm7,[0x78+Y]
- movq [0x08+Y],mm1
- movq mm1,[0x50+Y]
- movq [0x20+Y],mm6
- movq mm6,[0x68+Y]
- movq [0x28+Y],mm2
- movq mm2,[0x60+Y]
- movq [0x10+Y],mm5
- movq mm5,[0x58+Y]
- movq [0x38+Y],mm3
- movq mm3,[0x70+Y]
- movq [0x00+Y],mm4
- movq mm4,[0x48+Y]
- OC_FDCT_STAGE1_8x4
- OC_FDCT8x4(0x40,0x50,0x60,0x70,0x48,0x58,0x68,0x78)
- OC_TRANSPOSE8x4(0x40,0x50,0x60,0x70,0x48,0x58,0x68,0x78)
- /*mm0={-2}x4*/
- pcmpeqw mm0,mm0
- paddw mm0,mm0
- /*Round the results.*/
- psubw mm1,mm0
- psubw mm2,mm0
- psraw mm1,2
- psubw mm3,mm0
- movq [0x58+Y],mm1
- psraw mm2,2
- psubw mm4,mm0
- movq mm1,[0x48+Y]
- psraw mm3,2
- psubw mm5,mm0
- movq [0x68+Y],mm2
- psraw mm4,2
- psubw mm6,mm0
- movq [0x78+Y],mm3
- psraw mm5,2
- psubw mm7,mm0
- movq [0x40+Y],mm4
- psraw mm6,2
- psubw mm1,mm0
- movq [0x50+Y],mm5
- psraw mm7,2
- movq [0x60+Y],mm6
- psraw mm1,2
- movq [0x70+Y],mm7
- movq [0x48+Y],mm1
-#undef Y
-#undef A
-#undef X
- }
-}
-
-#endif
+/********************************************************************
+ * *
+ * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
+ * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
+ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
+ * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
+ * *
+ * THE Theora SOURCE CODE IS COPYRIGHT (C) 1999-2006 *
+ * by the Xiph.Org Foundation http://www.xiph.org/ *
+ * *
+ ********************************************************************/
+ /*MMX fDCT implementation for x86_32*/
+/*$Id: fdct_ses2.c 14579 2008-03-12 06:42:40Z xiphmont $*/
+#include "x86enc.h"
+
+#if defined(OC_X86_ASM)
+
+#define OC_FDCT_STAGE1_8x4 __asm{ \
+ /*Stage 1:*/ \
+ /*mm0=t7'=t0-t7*/ \
+ __asm psubw mm0,mm7 \
+ __asm paddw mm7,mm7 \
+ /*mm1=t6'=t1-t6*/ \
+ __asm psubw mm1, mm6 \
+ __asm paddw mm6,mm6 \
+ /*mm2=t5'=t2-t5*/ \
+ __asm psubw mm2,mm5 \
+ __asm paddw mm5,mm5 \
+ /*mm3=t4'=t3-t4*/ \
+ __asm psubw mm3,mm4 \
+ __asm paddw mm4,mm4 \
+ /*mm7=t0'=t0+t7*/ \
+ __asm paddw mm7,mm0 \
+ /*mm6=t1'=t1+t6*/ \
+ __asm paddw mm6,mm1 \
+ /*mm5=t2'=t2+t5*/ \
+ __asm paddw mm5,mm2 \
+ /*mm4=t3'=t3+t4*/ \
+ __asm paddw mm4,mm3\
+}
+
+#define OC_FDCT8x4(_r0,_r1,_r2,_r3,_r4,_r5,_r6,_r7) __asm{ \
+ /*Stage 2:*/ \
+ /*mm7=t3''=t0'-t3'*/ \
+ __asm psubw mm7,mm4 \
+ __asm paddw mm4,mm4 \
+ /*mm6=t2''=t1'-t2'*/ \
+ __asm psubw mm6,mm5 \
+ __asm movq [Y+_r6],mm7 \
+ __asm paddw mm5,mm5 \
+ /*mm1=t5''=t6'-t5'*/ \
+ __asm psubw mm1,mm2 \
+ __asm movq [Y+_r2],mm6 \
+ /*mm4=t0''=t0'+t3'*/ \
+ __asm paddw mm4,mm7 \
+ __asm paddw mm2,mm2 \
+ /*mm5=t1''=t1'+t2'*/ \
+ __asm movq [Y+_r0],mm4 \
+ __asm paddw mm5,mm6 \
+ /*mm2=t6''=t6'+t5'*/ \
+ __asm paddw mm2,mm1 \
+ __asm movq [Y+_r4],mm5 \
+ /*mm0=t7', mm1=t5'', mm2=t6'', mm3=t4'.*/ \
+ /*mm4, mm5, mm6, mm7 are free.*/ \
+ /*Stage 3:*/ \
+ /*mm6={2}x4, mm7={27146,0xB500>>1}x2*/ \
+ __asm mov A,0x5A806A0A \
+ __asm pcmpeqb mm6,mm6 \
+ __asm movd mm7,A \
+ __asm psrlw mm6,15 \
+ __asm punpckldq mm7,mm7 \
+ __asm paddw mm6,mm6 \
+ /*mm0=0, m2={-1}x4 \
+ mm5:mm4=t5''*27146+0xB500*/ \
+ __asm movq mm4,mm1 \
+ __asm movq mm5,mm1 \
+ __asm punpcklwd mm4,mm6 \
+ __asm movq [Y+_r3],mm2 \
+ __asm pmaddwd mm4,mm7 \
+ __asm movq [Y+_r7],mm0 \
+ __asm punpckhwd mm5,mm6 \
+ __asm pxor mm0,mm0 \
+ __asm pmaddwd mm5,mm7 \
+ __asm pcmpeqb mm2,mm2 \
+ /*mm2=t6'', mm1=t5''+(t5''!=0) \
+ mm4=(t5''*27146+0xB500>>16)*/ \
+ __asm pcmpeqw mm0,mm1 \
+ __asm psrad mm4,16 \
+ __asm psubw mm0,mm2 \
+ __asm movq mm2, [Y+_r3] \
+ __asm psrad mm5,16 \
+ __asm paddw mm1,mm0 \
+ __asm packssdw mm4,mm5 \
+ /*mm4=s=(t5''*27146+0xB500>>16)+t5''+(t5''!=0)>>1*/ \
+ __asm paddw mm4,mm1 \
+ __asm movq mm0, [Y+_r7] \
+ __asm psraw mm4,1 \
+ __asm movq mm1,mm3 \
+ /*mm3=t4''=t4'+s*/ \
+ __asm paddw mm3,mm4 \
+ /*mm1=t5'''=t4'-s*/ \
+ __asm psubw mm1,mm4 \
+ /*mm1=0, mm3={-1}x4 \
+ mm5:mm4=t6''*27146+0xB500*/ \
+ __asm movq mm4,mm2 \
+ __asm movq mm5,mm2 \
+ __asm punpcklwd mm4,mm6 \
+ __asm movq [Y+_r5],mm1 \
+ __asm pmaddwd mm4,mm7 \
+ __asm movq [Y+_r1],mm3 \
+ __asm punpckhwd mm5,mm6 \
+ __asm pxor mm1,mm1 \
+ __asm pmaddwd mm5,mm7 \
+ __asm pcmpeqb mm3,mm3 \
+ /*mm2=t6''+(t6''!=0), mm4=(t6''*27146+0xB500>>16)*/ \
+ __asm psrad mm4,16 \
+ __asm pcmpeqw mm1,mm2 \
+ __asm psrad mm5,16 \
+ __asm psubw mm1,mm3 \
+ __asm packssdw mm4,mm5 \
+ __asm paddw mm2,mm1 \
+ /*mm1=t1'' \
+ mm4=s=(t6''*27146+0xB500>>16)+t6''+(t6''!=0)>>1*/ \
+ __asm paddw mm4,mm2 \
+ __asm movq mm1,[Y+_r4] \
+ __asm psraw mm4,1 \
+ __asm movq mm2,mm0 \
+ /*mm7={54491-0x7FFF,0x7FFF}x2 \
+ mm0=t7''=t7'+s*/ \
+ __asm paddw mm0,mm4 \
+ /*mm2=t6'''=t7'-s*/ \
+ __asm psubw mm2,mm4 \
+ /*Stage 4:*/ \
+ /*mm0=0, mm2=t0'' \
+ mm5:mm4=t1''*27146+0xB500*/ \
+ __asm movq mm4,mm1 \
+ __asm movq mm5,mm1 \
+ __asm punpcklwd mm4,mm6 \
+ __asm movq [Y+_r3],mm2 \
+ __asm pmaddwd mm4,mm7 \
+ __asm movq mm2,[Y+_r0] \
+ __asm punpckhwd mm5,mm6 \
+ __asm movq [Y+_r7],mm0 \
+ __asm pmaddwd mm5,mm7 \
+ __asm pxor mm0,mm0 \
+ /*mm7={27146,0x4000>>1}x2 \
+ mm0=s=(t1''*27146+0xB500>>16)+t1''+(t1''!=0)*/ \
+ __asm psrad mm4,16 \
+ __asm mov A,0x20006A0A \
+ __asm pcmpeqw mm0,mm1 \
+ __asm movd mm7,A \
+ __asm psrad mm5,16 \
+ __asm psubw mm0,mm3 \
+ __asm packssdw mm4,mm5 \
+ __asm paddw mm0,mm1 \
+ __asm punpckldq mm7,mm7 \
+ __asm paddw mm0,mm4 \
+ /*mm6={0x00000E3D}x2 \
+ mm1=-(t0''==0), mm5:mm4=t0''*27146+0x4000*/ \
+ __asm movq mm4,mm2 \
+ __asm movq mm5,mm2 \
+ __asm punpcklwd mm4,mm6 \
+ __asm mov A,0x0E3D \
+ __asm pmaddwd mm4,mm7 \
+ __asm punpckhwd mm5,mm6 \
+ __asm movd mm6,A \
+ __asm pmaddwd mm5,mm7 \
+ __asm pxor mm1,mm1 \
+ __asm punpckldq mm6,mm6 \
+ __asm pcmpeqw mm1,mm2 \
+ /*mm4=r=(t0''*27146+0x4000>>16)+t0''+(t0''!=0)*/ \
+ __asm psrad mm4,16 \
+ __asm psubw mm1,mm3 \
+ __asm psrad mm5,16 \
+ __asm paddw mm2,mm1 \
+ __asm packssdw mm4,mm5 \
+ __asm movq mm1,[Y+_r5] \
+ __asm paddw mm4,mm2 \
+ /*mm2=t6'', mm0=_y[0]=u=r+s>>1 \
+ The naive implementation could cause overflow, so we use \
+ u=(r&s)+((r^s)>>1).*/ \
+ __asm movq mm2,[Y+_r3] \
+ __asm movq mm7,mm0 \
+ __asm pxor mm0,mm4 \
+ __asm pand mm7,mm4 \
+ __asm psraw mm0,1 \
+ __asm mov A,0x7FFF54DC \
+ __asm paddw mm0,mm7 \
+ __asm movd mm7,A \
+ /*mm7={54491-0x7FFF,0x7FFF}x2 \
+ mm4=_y[4]=v=r-u*/ \
+ __asm psubw mm4,mm0 \
+ __asm punpckldq mm7,mm7 \
+ __asm movq [Y+_r4],mm4 \
+ /*mm0=0, mm7={36410}x4 \
+ mm1=(t5'''!=0), mm5:mm4=54491*t5'''+0x0E3D*/ \
+ __asm movq mm4,mm1 \
+ __asm movq mm5,mm1 \
+ __asm punpcklwd mm4,mm1 \
+ __asm mov A,0x8E3A8E3A \
+ __asm pmaddwd mm4,mm7 \
+ __asm movq [Y+_r0],mm0 \
+ __asm punpckhwd mm5,mm1 \
+ __asm pxor mm0,mm0 \
+ __asm pmaddwd mm5,mm7 \
+ __asm pcmpeqw mm1,mm0 \
+ __asm movd mm7,A \
+ __asm psubw mm1,mm3 \
+ __asm punpckldq mm7,mm7 \
+ __asm paddd mm4,mm6 \
+ __asm paddd mm5,mm6 \
+ /*mm0=0 \
+ mm3:mm1=36410*t6'''+((t5'''!=0)<<16)*/ \
+ __asm movq mm6,mm2 \
+ __asm movq mm3,mm2 \
+ __asm pmulhw mm6,mm7 \
+ __asm paddw mm1,mm2 \
+ __asm pmullw mm3,mm7 \
+ __asm pxor mm0,mm0 \
+ __asm paddw mm6,mm1 \
+ __asm movq mm1,mm3 \
+ __asm punpckhwd mm3,mm6 \
+ __asm punpcklwd mm1,mm6 \
+ /*mm3={-1}x4, mm6={1}x4 \
+ mm4=_y[5]=u=(54491*t5'''+36410*t6'''+0x0E3D>>16)+(t5'''!=0)*/ \
+ __asm paddd mm5,mm3 \
+ __asm paddd mm4,mm1 \
+ __asm psrad mm5,16 \
+ __asm pxor mm6,mm6 \
+ __asm psrad mm4,16 \
+ __asm pcmpeqb mm3,mm3 \
+ __asm packssdw mm4,mm5 \
+ __asm psubw mm6,mm3 \
+ /*mm1=t7'', mm7={26568,0x3400}x2 \
+ mm2=s=t6'''-(36410*u>>16)*/ \
+ __asm movq mm1,mm4 \
+ __asm mov A,0x340067C8 \
+ __asm pmulhw mm4,mm7 \
+ __asm movd mm7,A \
+ __asm movq [Y+_r5],mm1 \
+ __asm punpckldq mm7,mm7 \
+ __asm paddw mm4,mm1 \
+ __asm movq mm1,[Y+_r7] \
+ __asm psubw mm2,mm4 \
+ /*mm6={0x00007B1B}x2 \
+ mm0=(s!=0), mm5:mm4=s*26568+0x3400*/ \
+ __asm movq mm4,mm2 \
+ __asm movq mm5,mm2 \
+ __asm punpcklwd mm4,mm6 \
+ __asm pcmpeqw mm0,mm2 \
+ __asm pmaddwd mm4,mm7 \
+ __asm mov A,0x7B1B \
+ __asm punpckhwd mm5,mm6 \
+ __asm movd mm6,A \
+ __asm pmaddwd mm5,mm7 \
+ __asm psubw mm0,mm3 \
+ __asm punpckldq mm6,mm6 \
+ /*mm7={64277-0x7FFF,0x7FFF}x2 \
+ mm2=_y[3]=v=(s*26568+0x3400>>17)+s+(s!=0)*/ \
+ __asm psrad mm4,17 \
+ __asm paddw mm2,mm0 \
+ __asm psrad mm5,17 \
+ __asm mov A,0x7FFF7B16 \
+ __asm packssdw mm4,mm5 \
+ __asm movd mm7,A \
+ __asm paddw mm2,mm4 \
+ __asm punpckldq mm7,mm7 \
+ /*mm0=0, mm7={12785}x4 \
+ mm1=(t7''!=0), mm2=t4'', mm5:mm4=64277*t7''+0x7B1B*/ \
+ __asm movq mm4,mm1 \
+ __asm movq mm5,mm1 \
+ __asm movq [Y+_r3],mm2 \
+ __asm punpcklwd mm4,mm1 \
+ __asm movq mm2,[Y+_r1] \
+ __asm pmaddwd mm4,mm7 \
+ __asm mov A,0x31F131F1 \
+ __asm punpckhwd mm5,mm1 \
+ __asm pxor mm0,mm0 \
+ __asm pmaddwd mm5,mm7 \
+ __asm pcmpeqw mm1,mm0 \
+ __asm movd mm7,A \
+ __asm psubw mm1,mm3 \
+ __asm punpckldq mm7,mm7 \
+ __asm paddd mm4,mm6 \
+ __asm paddd mm5,mm6 \
+ /*mm3:mm1=12785*t4'''+((t7''!=0)<<16)*/ \
+ __asm movq mm6,mm2 \
+ __asm movq mm3,mm2 \
+ __asm pmulhw mm6,mm7 \
+ __asm pmullw mm3,mm7 \
+ __asm paddw mm6,mm1 \
+ __asm movq mm1,mm3 \
+ __asm punpckhwd mm3,mm6 \
+ __asm punpcklwd mm1,mm6 \
+ /*mm3={-1}x4, mm6={1}x4 \
+ mm4=_y[1]=u=(12785*t4'''+64277*t7''+0x7B1B>>16)+(t7''!=0)*/ \
+ __asm paddd mm5,mm3 \
+ __asm paddd mm4,mm1 \
+ __asm psrad mm5,16 \
+ __asm pxor mm6,mm6 \
+ __asm psrad mm4,16 \
+ __asm pcmpeqb mm3,mm3 \
+ __asm packssdw mm4,mm5 \
+ __asm psubw mm6,mm3 \
+ /*mm1=t3'', mm7={20539,0x3000}x2 \
+ mm4=s=(12785*u>>16)-t4''*/ \
+ __asm movq [Y+_r1],mm4 \
+ __asm pmulhw mm4,mm7 \
+ __asm mov A,0x3000503B \
+ __asm movq mm1,[Y+_r6] \
+ __asm movd mm7,A \
+ __asm psubw mm4,mm2 \
+ __asm punpckldq mm7,mm7 \
+ /*mm6={0x00006CB7}x2 \
+ mm0=(s!=0), mm5:mm4=s*20539+0x3000*/ \
+ __asm movq mm5,mm4 \
+ __asm movq mm2,mm4 \
+ __asm punpcklwd mm4,mm6 \
+ __asm pcmpeqw mm0,mm2 \
+ __asm pmaddwd mm4,mm7 \
+ __asm mov A,0x6CB7 \
+ __asm punpckhwd mm5,mm6 \
+ __asm movd mm6,A \
+ __asm pmaddwd mm5,mm7 \
+ __asm psubw mm0,mm3 \
+ __asm punpckldq mm6,mm6 \
+ /*mm7={60547-0x7FFF,0x7FFF}x2 \
+ mm2=_y[7]=v=(s*20539+0x3000>>20)+s+(s!=0)*/ \
+ __asm psrad mm4,20 \
+ __asm paddw mm2,mm0 \
+ __asm psrad mm5,20 \
+ __asm mov A,0x7FFF6C84 \
+ __asm packssdw mm4,mm5 \
+ __asm movd mm7,A \
+ __asm paddw mm2,mm4 \
+ __asm punpckldq mm7,mm7 \
+ /*mm0=0, mm7={25080}x4 \
+ mm2=t2'', mm5:mm4=60547*t3''+0x6CB7*/ \
+ __asm movq mm4,mm1 \
+ __asm movq mm5,mm1 \
+ __asm movq [Y+_r7],mm2 \
+ __asm punpcklwd mm4,mm1 \
+ __asm movq mm2,[Y+_r2] \
+ __asm pmaddwd mm4,mm7 \
+ __asm mov A,0x61F861F8 \
+ __asm punpckhwd mm5,mm1 \
+ __asm pxor mm0,mm0 \
+ __asm pmaddwd mm5,mm7 \
+ __asm movd mm7,A \
+ __asm pcmpeqw mm1,mm0 \
+ __asm psubw mm1,mm3 \
+ __asm punpckldq mm7,mm7 \
+ __asm paddd mm4,mm6 \
+ __asm paddd mm5,mm6 \
+ /*mm3:mm1=25080*t2''+((t3''!=0)<<16)*/ \
+ __asm movq mm6,mm2 \
+ __asm movq mm3,mm2 \
+ __asm pmulhw mm6,mm7 \
+ __asm pmullw mm3,mm7 \
+ __asm paddw mm6,mm1 \
+ __asm movq mm1,mm3 \
+ __asm punpckhwd mm3,mm6 \
+ __asm punpcklwd mm1,mm6 \
+ /*mm1={-1}x4 \
+ mm4=u=(25080*t2''+60547*t3''+0x6CB7>>16)+(t3''!=0)*/ \
+ __asm paddd mm5,mm3 \
+ __asm paddd mm4,mm1 \
+ __asm psrad mm5,16 \
+ __asm mov A,0x28005460 \
+ __asm psrad mm4,16 \
+ __asm pcmpeqb mm1,mm1 \
+ __asm packssdw mm4,mm5 \
+ /*mm5={1}x4, mm6=_y[2]=u, mm7={21600,0x2800}x2 \
+ mm4=s=(25080*u>>16)-t2''*/ \
+ __asm movq mm6,mm4 \
+ __asm pmulhw mm4,mm7 \
+ __asm pxor mm5,mm5 \
+ __asm movd mm7,A \
+ __asm psubw mm5,mm1 \
+ __asm punpckldq mm7,mm7 \
+ __asm psubw mm4,mm2 \
+ /*mm2=s+(s!=0) \
+ mm4:mm3=s*21600+0x2800*/ \
+ __asm movq mm3,mm4 \
+ __asm movq mm2,mm4 \
+ __asm punpckhwd mm4,mm5 \
+ __asm pcmpeqw mm0,mm2 \
+ __asm pmaddwd mm4,mm7 \
+ __asm psubw mm0,mm1 \
+ __asm punpcklwd mm3,mm5 \
+ __asm paddw mm2,mm0 \
+ __asm pmaddwd mm3,mm7 \
+ /*mm0=_y[4], mm1=_y[7], mm4=_y[0], mm5=_y[5] \
+ mm3=_y[6]=v=(s*21600+0x2800>>18)+s+(s!=0)*/ \
+ __asm movq mm0,[Y+_r4] \
+ __asm psrad mm4,18 \
+ __asm movq mm5,[Y+_r5] \
+ __asm psrad mm3,18 \
+ __asm movq mm1,[Y+_r7] \
+ __asm packssdw mm3,mm4 \
+ __asm movq mm4,[Y+_r0] \
+ __asm paddw mm3,mm2 \
+}
+
+/*On input, mm4=_y[0], mm6=_y[2], mm0=_y[4], mm5=_y[5], mm3=_y[6], mm1=_y[7].
+ On output, {_y[4],mm1,mm2,mm3} contains the transpose of _y[4...7] and
+ {mm4,mm5,mm6,mm7} contains the transpose of _y[0...3].*/
+#define OC_TRANSPOSE8x4(_r0,_r1,_r2,_r3,_r4,_r5,_r6,_r7) __asm{ \
+ /*First 4x4 transpose:*/ \
+ /*mm0 = e3 e2 e1 e0 \
+ mm5 = f3 f2 f1 f0 \
+ mm3 = g3 g2 g1 g0 \
+ mm1 = h3 h2 h1 h0*/ \
+ __asm movq mm2,mm0 \
+ __asm punpcklwd mm0,mm5 \
+ __asm punpckhwd mm2,mm5 \
+ __asm movq mm5,mm3 \
+ __asm punpcklwd mm3,mm1 \
+ __asm punpckhwd mm5,mm1 \
+ /*mm0 = f1 e1 f0 e0 \
+ mm2 = f3 e3 f2 e2 \
+ mm3 = h1 g1 h0 g0 \
+ mm5 = h3 g3 h2 g2*/ \
+ __asm movq mm1,mm0 \
+ __asm punpckldq mm0,mm3 \
+ __asm movq [Y+_r4],mm0 \
+ __asm punpckhdq mm1,mm3 \
+ __asm movq mm0,[Y+_r1] \
+ __asm movq mm3,mm2 \
+ __asm punpckldq mm2,mm5 \
+ __asm punpckhdq mm3,mm5 \
+ __asm movq mm5,[Y+_r3] \
+ /*_y[4] = h0 g0 f0 e0 \
+ mm1 = h1 g1 f1 e1 \
+ mm2 = h2 g2 f2 e2 \
+ mm3 = h3 g3 f3 e3*/ \
+ /*Second 4x4 transpose:*/ \
+ /*mm4 = a3 a2 a1 a0 \
+ mm0 = b3 b2 b1 b0 \
+ mm6 = c3 c2 c1 c0 \
+ mm5 = d3 d2 d1 d0*/ \
+ __asm movq mm7,mm4 \
+ __asm punpcklwd mm4,mm0 \
+ __asm punpckhwd mm7,mm0 \
+ __asm movq mm0,mm6 \
+ __asm punpcklwd mm6,mm5 \
+ __asm punpckhwd mm0,mm5 \
+ /*mm4 = b1 a1 b0 a0 \
+ mm7 = b3 a3 b2 a2 \
+ mm6 = d1 c1 d0 c0 \
+ mm0 = d3 c3 d2 c2*/ \
+ __asm movq mm5,mm4 \
+ __asm punpckldq mm4,mm6 \
+ __asm punpckhdq mm5,mm6 \
+ __asm movq mm6,mm7 \
+ __asm punpckhdq mm7,mm0 \
+ __asm punpckldq mm6,mm0 \
+ /*mm4 = d0 c0 b0 a0 \
+ mm5 = d1 c1 b1 a1 \
+ mm6 = d2 c2 b2 a2 \
+ mm7 = d3 c3 b3 a3*/ \
+}
+
+/*MMX implementation of the fDCT.*/
+void oc_enc_fdct8x8_mmx(ogg_int16_t _y[64],const ogg_int16_t _x[64]){
+ ptrdiff_t a;
+ __asm{
+#define Y eax
+#define A ecx
+#define X edx
+ /*Add two extra bits of working precision to improve accuracy; any more and
+ we could overflow.*/
+ /*We also add biases to correct for some systematic error that remains in
+ the full fDCT->iDCT round trip.*/
+ mov X, _x
+ mov Y, _y
+ movq mm0,[0x00+X]
+ movq mm1,[0x10+X]
+ movq mm2,[0x20+X]
+ movq mm3,[0x30+X]
+ pcmpeqb mm4,mm4
+ pxor mm7,mm7
+ movq mm5,mm0
+ psllw mm0,2
+ pcmpeqw mm5,mm7
+ movq mm7,[0x70+X]
+ psllw mm1,2
+ psubw mm5,mm4
+ psllw mm2,2
+ mov A,1
+ pslld mm5,16
+ movd mm6,A
+ psllq mm5,16
+ mov A,0x10001
+ psllw mm3,2
+ movd mm4,A
+ punpckhwd mm5,mm6
+ psubw mm1,mm6
+ movq mm6,[0x60+X]
+ paddw mm0,mm5
+ movq mm5,[0x50+X]
+ paddw mm0,mm4
+ movq mm4,[0x40+X]
+ /*We inline stage1 of the transform here so we can get better instruction
+ scheduling with the shifts.*/
+ /*mm0=t7'=t0-t7*/
+ psllw mm7,2
+ psubw mm0,mm7
+ psllw mm6,2
+ paddw mm7,mm7
+ /*mm1=t6'=t1-t6*/
+ psllw mm5,2
+ psubw mm1,mm6
+ psllw mm4,2
+ paddw mm6,mm6
+ /*mm2=t5'=t2-t5*/
+ psubw mm2,mm5
+ paddw mm5,mm5
+ /*mm3=t4'=t3-t4*/
+ psubw mm3,mm4
+ paddw mm4,mm4
+ /*mm7=t0'=t0+t7*/
+ paddw mm7,mm0
+ /*mm6=t1'=t1+t6*/
+ paddw mm6,mm1
+ /*mm5=t2'=t2+t5*/
+ paddw mm5,mm2
+ /*mm4=t3'=t3+t4*/
+ paddw mm4,mm3
+ OC_FDCT8x4(0x00,0x10,0x20,0x30,0x40,0x50,0x60,0x70)
+ OC_TRANSPOSE8x4(0x00,0x10,0x20,0x30,0x40,0x50,0x60,0x70)
+ /*Swap out this 8x4 block for the next one.*/
+ movq mm0,[0x08+X]
+ movq [0x30+Y],mm7
+ movq mm7,[0x78+X]
+ movq [0x50+Y],mm1
+ movq mm1,[0x18+X]
+ movq [0x20+Y],mm6
+ movq mm6,[0x68+X]
+ movq [0x60+Y],mm2
+ movq mm2,[0x28+X]
+ movq [0x10+Y],mm5
+ movq mm5,[0x58+X]
+ movq [0x70+Y],mm3
+ movq mm3,[0x38+X]
+ /*And increase its working precision, too.*/
+ psllw mm0,2
+ movq [0x00+Y],mm4
+ psllw mm7,2
+ movq mm4,[0x48+X]
+ /*We inline stage1 of the transform here so we can get better instruction
+ scheduling with the shifts.*/
+ /*mm0=t7'=t0-t7*/
+ psubw mm0,mm7
+ psllw mm1,2
+ paddw mm7,mm7
+ psllw mm6,2
+ /*mm1=t6'=t1-t6*/
+ psubw mm1,mm6
+ psllw mm2,2
+ paddw mm6,mm6
+ psllw mm5,2
+ /*mm2=t5'=t2-t5*/
+ psubw mm2,mm5
+ psllw mm3,2
+ paddw mm5,mm5
+ psllw mm4,2
+ /*mm3=t4'=t3-t4*/
+ psubw mm3,mm4
+ paddw mm4,mm4
+ /*mm7=t0'=t0+t7*/
+ paddw mm7,mm0
+ /*mm6=t1'=t1+t6*/
+ paddw mm6,mm1
+ /*mm5=t2'=t2+t5*/
+ paddw mm5,mm2
+ /*mm4=t3'=t3+t4*/
+ paddw mm4,mm3
+ OC_FDCT8x4(0x08,0x18,0x28,0x38,0x48,0x58,0x68,0x78)
+ OC_TRANSPOSE8x4(0x08,0x18,0x28,0x38,0x48,0x58,0x68,0x78)
+ /*Here the first 4x4 block of output from the last transpose is the second
+ 4x4 block of input for the next transform.
+ We have cleverly arranged that it already be in the appropriate place,
+ so we only have to do half the stores and loads.*/
+ movq mm0,[0x00+Y]
+ movq [0x58+Y],mm1
+ movq mm1,[0x10+Y]
+ movq [0x68+Y],mm2
+ movq mm2,[0x20+Y]
+ movq [0x78+Y],mm3
+ movq mm3,[0x30+Y]
+ OC_FDCT_STAGE1_8x4
+ OC_FDCT8x4(0x00,0x10,0x20,0x30,0x08,0x18,0x28,0x38)
+ OC_TRANSPOSE8x4(0x00,0x10,0x20,0x30,0x08,0x18,0x28,0x38)
+ /*mm0={-2}x4*/
+ pcmpeqw mm0,mm0
+ paddw mm0,mm0
+ /*Round the results.*/
+ psubw mm1,mm0
+ psubw mm2,mm0
+ psraw mm1,2
+ psubw mm3,mm0
+ movq [0x18+Y],mm1
+ psraw mm2,2
+ psubw mm4,mm0
+ movq mm1,[0x08+Y]
+ psraw mm3,2
+ psubw mm5,mm0
+ psraw mm4,2
+ psubw mm6,mm0
+ psraw mm5,2
+ psubw mm7,mm0
+ psraw mm6,2
+ psubw mm1,mm0
+ psraw mm7,2
+ movq mm0,[0x40+Y]
+ psraw mm1,2
+ movq [0x30+Y],mm7
+ movq mm7,[0x78+Y]
+ movq [0x08+Y],mm1
+ movq mm1,[0x50+Y]
+ movq [0x20+Y],mm6
+ movq mm6,[0x68+Y]
+ movq [0x28+Y],mm2
+ movq mm2,[0x60+Y]
+ movq [0x10+Y],mm5
+ movq mm5,[0x58+Y]
+ movq [0x38+Y],mm3
+ movq mm3,[0x70+Y]
+ movq [0x00+Y],mm4
+ movq mm4,[0x48+Y]
+ OC_FDCT_STAGE1_8x4
+ OC_FDCT8x4(0x40,0x50,0x60,0x70,0x48,0x58,0x68,0x78)
+ OC_TRANSPOSE8x4(0x40,0x50,0x60,0x70,0x48,0x58,0x68,0x78)
+ /*mm0={-2}x4*/
+ pcmpeqw mm0,mm0
+ paddw mm0,mm0
+ /*Round the results.*/
+ psubw mm1,mm0
+ psubw mm2,mm0
+ psraw mm1,2
+ psubw mm3,mm0
+ movq [0x58+Y],mm1
+ psraw mm2,2
+ psubw mm4,mm0
+ movq mm1,[0x48+Y]
+ psraw mm3,2
+ psubw mm5,mm0
+ movq [0x68+Y],mm2
+ psraw mm4,2
+ psubw mm6,mm0
+ movq [0x78+Y],mm3
+ psraw mm5,2
+ psubw mm7,mm0
+ movq [0x40+Y],mm4
+ psraw mm6,2
+ psubw mm1,mm0
+ movq [0x50+Y],mm5
+ psraw mm7,2
+ movq [0x60+Y],mm6
+ psraw mm1,2
+ movq [0x70+Y],mm7
+ movq [0x48+Y],mm1
+#undef Y
+#undef A
+#undef X
+ }
+}
+
+#endif
diff --git a/thirdparty/nanosvg/LICENSE.txt b/thirdparty/nanosvg/LICENSE.txt
index 6fde401cb2..f896f2eb0f 100644
--- a/thirdparty/nanosvg/LICENSE.txt
+++ b/thirdparty/nanosvg/LICENSE.txt
@@ -1,18 +1,18 @@
-Copyright (c) 2013-14 Mikko Mononen memon@inside.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) 2013-14 Mikko Mononen memon@inside.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.
+
diff --git a/thirdparty/openssl/uwp.cpp b/thirdparty/openssl/uwp.cpp
index dcfd22b77f..e00c9d59db 100644
--- a/thirdparty/openssl/uwp.cpp
+++ b/thirdparty/openssl/uwp.cpp
@@ -103,12 +103,14 @@ extern "C"
{
return 0;
}
+#ifndef STD_ERROR_HANDLE
int __cdecl GetStdHandle(
_In_ DWORD nStdHandle
)
{
return 0;
}
+#endif
BOOL DeregisterEventSource(
_Inout_ HANDLE hEventLog
)
diff --git a/thirdparty/zstd/SCsub b/thirdparty/zstd/SCsub
index e8be1aaf44..899a18e1cf 100644
--- a/thirdparty/zstd/SCsub
+++ b/thirdparty/zstd/SCsub
@@ -14,10 +14,16 @@ thirdparty_zstd_sources = [
"compress/fse_compress.c",
"compress/huf_compress.c",
"compress/zstd_compress.c",
+ "compress/zstd_double_fast.c",
+ "compress/zstd_fast.c",
+ "compress/zstd_lazy.c",
+ "compress/zstd_ldm.c",
"compress/zstdmt_compress.c",
+ "compress/zstd_opt.c",
"decompress/huf_decompress.c",
"decompress/zstd_decompress.c",
]
thirdparty_zstd_sources = [thirdparty_zstd_dir + file for file in thirdparty_zstd_sources]
env.add_source_files(env.core_sources, thirdparty_zstd_sources)
env.Append(CPPPATH=["#thirdparty/zstd", "#thirdparty/zstd/common"])
+env.Append(CCFLAGS="-DZSTD_STATIC_LINKING_ONLY")
diff --git a/thirdparty/zstd/common/bitstream.h b/thirdparty/zstd/common/bitstream.h
index 06121f21c5..2094823fe2 100644
--- a/thirdparty/zstd/common/bitstream.h
+++ b/thirdparty/zstd/common/bitstream.h
@@ -169,33 +169,39 @@ MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, unsigned nbBits);
****************************************************************/
MEM_STATIC unsigned BIT_highbit32 (register U32 val)
{
+ assert(val != 0);
+ {
# if defined(_MSC_VER) /* Visual */
- unsigned long r=0;
- _BitScanReverse ( &r, val );
- return (unsigned) r;
+ unsigned long r=0;
+ _BitScanReverse ( &r, val );
+ return (unsigned) r;
# elif defined(__GNUC__) && (__GNUC__ >= 3) /* Use GCC Intrinsic */
- return 31 - __builtin_clz (val);
+ return 31 - __builtin_clz (val);
# else /* Software version */
- static const unsigned DeBruijnClz[32] = { 0, 9, 1, 10, 13, 21, 2, 29,
- 11, 14, 16, 18, 22, 25, 3, 30,
- 8, 12, 20, 28, 15, 17, 24, 7,
- 19, 27, 23, 6, 26, 5, 4, 31 };
- U32 v = val;
- v |= v >> 1;
- v |= v >> 2;
- v |= v >> 4;
- v |= v >> 8;
- v |= v >> 16;
- return DeBruijnClz[ (U32) (v * 0x07C4ACDDU) >> 27];
+ static const unsigned DeBruijnClz[32] = { 0, 9, 1, 10, 13, 21, 2, 29,
+ 11, 14, 16, 18, 22, 25, 3, 30,
+ 8, 12, 20, 28, 15, 17, 24, 7,
+ 19, 27, 23, 6, 26, 5, 4, 31 };
+ U32 v = val;
+ v |= v >> 1;
+ v |= v >> 2;
+ v |= v >> 4;
+ v |= v >> 8;
+ v |= v >> 16;
+ return DeBruijnClz[ (U32) (v * 0x07C4ACDDU) >> 27];
# endif
+ }
}
/*===== Local Constants =====*/
-static const unsigned BIT_mask[] = { 0, 1, 3, 7, 0xF, 0x1F, 0x3F, 0x7F,
- 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF,
- 0xFFFF, 0x1FFFF, 0x3FFFF, 0x7FFFF, 0xFFFFF, 0x1FFFFF, 0x3FFFFF, 0x7FFFFF,
- 0xFFFFFF, 0x1FFFFFF, 0x3FFFFFF }; /* up to 26 bits */
-
+static const unsigned BIT_mask[] = {
+ 0, 1, 3, 7, 0xF, 0x1F,
+ 0x3F, 0x7F, 0xFF, 0x1FF, 0x3FF, 0x7FF,
+ 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF, 0x1FFFF,
+ 0x3FFFF, 0x7FFFF, 0xFFFFF, 0x1FFFFF, 0x3FFFFF, 0x7FFFFF,
+ 0xFFFFFF, 0x1FFFFFF, 0x3FFFFFF, 0x7FFFFFF, 0xFFFFFFF, 0x1FFFFFFF,
+ 0x3FFFFFFF, 0x7FFFFFFF}; /* up to 31 bits */
+#define BIT_MASK_SIZE (sizeof(BIT_mask) / sizeof(BIT_mask[0]))
/*-**************************************************************
* bitStream encoding
@@ -217,11 +223,14 @@ MEM_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC,
}
/*! BIT_addBits() :
- * can add up to 26 bits into `bitC`.
+ * can add up to 31 bits into `bitC`.
* Note : does not check for register overflow ! */
MEM_STATIC void BIT_addBits(BIT_CStream_t* bitC,
size_t value, unsigned nbBits)
{
+ MEM_STATIC_ASSERT(BIT_MASK_SIZE == 32);
+ assert(nbBits < BIT_MASK_SIZE);
+ assert(nbBits + bitC->bitPos < sizeof(bitC->bitContainer) * 8);
bitC->bitContainer |= (value & BIT_mask[nbBits]) << bitC->bitPos;
bitC->bitPos += nbBits;
}
@@ -232,6 +241,7 @@ MEM_STATIC void BIT_addBitsFast(BIT_CStream_t* bitC,
size_t value, unsigned nbBits)
{
assert((value>>nbBits) == 0);
+ assert(nbBits + bitC->bitPos < sizeof(bitC->bitContainer) * 8);
bitC->bitContainer |= value << bitC->bitPos;
bitC->bitPos += nbBits;
}
@@ -242,7 +252,7 @@ MEM_STATIC void BIT_addBitsFast(BIT_CStream_t* bitC,
MEM_STATIC void BIT_flushBitsFast(BIT_CStream_t* bitC)
{
size_t const nbBytes = bitC->bitPos >> 3;
- assert( bitC->bitPos <= (sizeof(bitC->bitContainer)*8) );
+ assert(bitC->bitPos < sizeof(bitC->bitContainer) * 8);
MEM_writeLEST(bitC->ptr, bitC->bitContainer);
bitC->ptr += nbBytes;
assert(bitC->ptr <= bitC->endPtr);
@@ -258,7 +268,7 @@ MEM_STATIC void BIT_flushBitsFast(BIT_CStream_t* bitC)
MEM_STATIC void BIT_flushBits(BIT_CStream_t* bitC)
{
size_t const nbBytes = bitC->bitPos >> 3;
- assert( bitC->bitPos <= (sizeof(bitC->bitContainer)*8) );
+ assert(bitC->bitPos < sizeof(bitC->bitContainer) * 8);
MEM_writeLEST(bitC->ptr, bitC->bitContainer);
bitC->ptr += nbBytes;
if (bitC->ptr > bitC->endPtr) bitC->ptr = bitC->endPtr;
@@ -350,12 +360,14 @@ MEM_STATIC size_t BIT_getMiddleBits(size_t bitContainer, U32 const start, U32 co
# endif
return _bextr_u32(bitContainer, start, nbBits);
#else
+ assert(nbBits < BIT_MASK_SIZE);
return (bitContainer >> start) & BIT_mask[nbBits];
#endif
}
MEM_STATIC size_t BIT_getLowerBits(size_t bitContainer, U32 const nbBits)
{
+ assert(nbBits < BIT_MASK_SIZE);
return bitContainer & BIT_mask[nbBits];
}
diff --git a/thirdparty/zstd/common/compiler.h b/thirdparty/zstd/common/compiler.h
index d7225c443e..3a7553c380 100644
--- a/thirdparty/zstd/common/compiler.h
+++ b/thirdparty/zstd/common/compiler.h
@@ -5,6 +5,7 @@
* This source code is licensed under both the BSD-style license (found in the
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
* in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
*/
#ifndef ZSTD_COMPILER_H
diff --git a/thirdparty/zstd/common/error_private.c b/thirdparty/zstd/common/error_private.c
index b5b14b509c..11f7cdab1c 100644
--- a/thirdparty/zstd/common/error_private.c
+++ b/thirdparty/zstd/common/error_private.c
@@ -5,6 +5,7 @@
* This source code is licensed under both the BSD-style license (found in the
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
* in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
*/
/* The purpose of this file is to have a single list of error strings embedded in binary */
@@ -29,14 +30,15 @@ const char* ERR_getErrorString(ERR_enum code)
case PREFIX(init_missing): return "Context should be init first";
case PREFIX(memory_allocation): return "Allocation error : not enough memory";
case PREFIX(stage_wrong): return "Operation not authorized at current processing stage";
- case PREFIX(dstSize_tooSmall): return "Destination buffer is too small";
- case PREFIX(srcSize_wrong): return "Src size is incorrect";
case PREFIX(tableLog_tooLarge): return "tableLog requires too much memory : unsupported";
case PREFIX(maxSymbolValue_tooLarge): return "Unsupported max Symbol Value : too large";
case PREFIX(maxSymbolValue_tooSmall): return "Specified maxSymbolValue is too small";
case PREFIX(dictionary_corrupted): return "Dictionary is corrupted";
case PREFIX(dictionary_wrong): return "Dictionary mismatch";
case PREFIX(dictionaryCreation_failed): return "Cannot create Dictionary from provided samples";
+ case PREFIX(dstSize_tooSmall): return "Destination buffer is too small";
+ case PREFIX(srcSize_wrong): return "Src size is incorrect";
+ /* following error codes are not stable and may be removed or changed in a future version */
case PREFIX(frameIndex_tooLarge): return "Frame index is too large";
case PREFIX(seekableIO): return "An I/O error occurred when reading/seeking";
case PREFIX(maxCode):
diff --git a/thirdparty/zstd/common/error_private.h b/thirdparty/zstd/common/error_private.h
index 9dd9a87cfa..0d2fa7e34b 100644
--- a/thirdparty/zstd/common/error_private.h
+++ b/thirdparty/zstd/common/error_private.h
@@ -5,6 +5,7 @@
* This source code is licensed under both the BSD-style license (found in the
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
* in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
*/
/* Note : this module is expected to remain private, do not expose it */
@@ -48,10 +49,9 @@ typedef ZSTD_ErrorCode ERR_enum;
/*-****************************************
* Error codes handling
******************************************/
-#ifdef ERROR
-# undef ERROR /* reported already defined on VS 2015 (Rich Geldreich) */
-#endif
-#define ERROR(name) ((size_t)-PREFIX(name))
+#undef ERROR /* reported already defined on VS 2015 (Rich Geldreich) */
+#define ERROR(name) ZSTD_ERROR(name)
+#define ZSTD_ERROR(name) ((size_t)-PREFIX(name))
ERR_STATIC unsigned ERR_isError(size_t code) { return (code > ERROR(maxCode)); }
diff --git a/thirdparty/zstd/common/fse.h b/thirdparty/zstd/common/fse.h
index 1c44f83750..afd7801963 100644
--- a/thirdparty/zstd/common/fse.h
+++ b/thirdparty/zstd/common/fse.h
@@ -184,7 +184,7 @@ FSE_PUBLIC_API size_t FSE_writeNCount (void* buffer, size_t bufferSize, const sh
/*! Constructor and Destructor of FSE_CTable.
Note that FSE_CTable size depends on 'tableLog' and 'maxSymbolValue' */
typedef unsigned FSE_CTable; /* don't allocate that. It's only meant to be more restrictive than void* */
-FSE_PUBLIC_API FSE_CTable* FSE_createCTable (unsigned tableLog, unsigned maxSymbolValue);
+FSE_PUBLIC_API FSE_CTable* FSE_createCTable (unsigned maxSymbolValue, unsigned tableLog);
FSE_PUBLIC_API void FSE_freeCTable (FSE_CTable* ct);
/*! FSE_buildCTable():
diff --git a/thirdparty/zstd/common/huf.h b/thirdparty/zstd/common/huf.h
index 2b3015a84c..522bf9b6c0 100644
--- a/thirdparty/zstd/common/huf.h
+++ b/thirdparty/zstd/common/huf.h
@@ -242,7 +242,7 @@ size_t HUF_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats,
/** HUF_readCTable() :
* Loading a CTable saved with HUF_writeCTable() */
-size_t HUF_readCTable (HUF_CElt* CTable, unsigned maxSymbolValue, const void* src, size_t srcSize);
+size_t HUF_readCTable (HUF_CElt* CTable, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize);
/*
diff --git a/thirdparty/zstd/common/mem.h b/thirdparty/zstd/common/mem.h
index df85404fb8..23335c3146 100644
--- a/thirdparty/zstd/common/mem.h
+++ b/thirdparty/zstd/common/mem.h
@@ -5,6 +5,7 @@
* This source code is licensed under both the BSD-style license (found in the
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
* in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
*/
#ifndef MEM_H_MODULE
diff --git a/thirdparty/zstd/common/pool.c b/thirdparty/zstd/common/pool.c
index a227044f7f..1b0fe1035d 100644
--- a/thirdparty/zstd/common/pool.c
+++ b/thirdparty/zstd/common/pool.c
@@ -5,6 +5,7 @@
* This source code is licensed under both the BSD-style license (found in the
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
* in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
*/
@@ -25,13 +26,14 @@
/* A job is a function and an opaque argument */
typedef struct POOL_job_s {
- POOL_function function;
- void *opaque;
+ POOL_function function;
+ void *opaque;
} POOL_job;
struct POOL_ctx_s {
+ ZSTD_customMem customMem;
/* Keep track of the threads */
- pthread_t *threads;
+ ZSTD_pthread_t *threads;
size_t numThreads;
/* The queue is a circular buffer */
@@ -46,11 +48,11 @@ struct POOL_ctx_s {
int queueEmpty;
/* The mutex protects the queue */
- pthread_mutex_t queueMutex;
+ ZSTD_pthread_mutex_t queueMutex;
/* Condition variable for pushers to wait on when the queue is full */
- pthread_cond_t queuePushCond;
+ ZSTD_pthread_cond_t queuePushCond;
/* Condition variables for poppers to wait on when the queue is empty */
- pthread_cond_t queuePopCond;
+ ZSTD_pthread_cond_t queuePopCond;
/* Indicates if the queue is shutting down */
int shutdown;
};
@@ -65,14 +67,14 @@ static void* POOL_thread(void* opaque) {
if (!ctx) { return NULL; }
for (;;) {
/* Lock the mutex and wait for a non-empty queue or until shutdown */
- pthread_mutex_lock(&ctx->queueMutex);
+ ZSTD_pthread_mutex_lock(&ctx->queueMutex);
while (ctx->queueEmpty && !ctx->shutdown) {
- pthread_cond_wait(&ctx->queuePopCond, &ctx->queueMutex);
+ ZSTD_pthread_cond_wait(&ctx->queuePopCond, &ctx->queueMutex);
}
/* empty => shutting down: so stop */
if (ctx->queueEmpty) {
- pthread_mutex_unlock(&ctx->queueMutex);
+ ZSTD_pthread_mutex_unlock(&ctx->queueMutex);
return opaque;
}
/* Pop a job off the queue */
@@ -81,28 +83,32 @@ static void* POOL_thread(void* opaque) {
ctx->numThreadsBusy++;
ctx->queueEmpty = ctx->queueHead == ctx->queueTail;
/* Unlock the mutex, signal a pusher, and run the job */
- pthread_mutex_unlock(&ctx->queueMutex);
- pthread_cond_signal(&ctx->queuePushCond);
+ ZSTD_pthread_mutex_unlock(&ctx->queueMutex);
+ ZSTD_pthread_cond_signal(&ctx->queuePushCond);
job.function(job.opaque);
/* If the intended queue size was 0, signal after finishing job */
if (ctx->queueSize == 1) {
- pthread_mutex_lock(&ctx->queueMutex);
+ ZSTD_pthread_mutex_lock(&ctx->queueMutex);
ctx->numThreadsBusy--;
- pthread_mutex_unlock(&ctx->queueMutex);
- pthread_cond_signal(&ctx->queuePushCond);
+ ZSTD_pthread_mutex_unlock(&ctx->queueMutex);
+ ZSTD_pthread_cond_signal(&ctx->queuePushCond);
} }
} /* for (;;) */
/* Unreachable */
}
-POOL_ctx *POOL_create(size_t numThreads, size_t queueSize) {
- POOL_ctx *ctx;
+POOL_ctx* POOL_create(size_t numThreads, size_t queueSize) {
+ return POOL_create_advanced(numThreads, queueSize, ZSTD_defaultCMem);
+}
+
+POOL_ctx* POOL_create_advanced(size_t numThreads, size_t queueSize, ZSTD_customMem customMem) {
+ POOL_ctx* ctx;
/* Check the parameters */
if (!numThreads) { return NULL; }
/* Allocate the context and zero initialize */
- ctx = (POOL_ctx *)calloc(1, sizeof(POOL_ctx));
+ ctx = (POOL_ctx*)ZSTD_calloc(sizeof(POOL_ctx), customMem);
if (!ctx) { return NULL; }
/* Initialize the job queue.
* It needs one extra space since one space is wasted to differentiate empty
@@ -114,19 +120,20 @@ POOL_ctx *POOL_create(size_t numThreads, size_t queueSize) {
ctx->queueTail = 0;
ctx->numThreadsBusy = 0;
ctx->queueEmpty = 1;
- (void)pthread_mutex_init(&ctx->queueMutex, NULL);
- (void)pthread_cond_init(&ctx->queuePushCond, NULL);
- (void)pthread_cond_init(&ctx->queuePopCond, NULL);
+ (void)ZSTD_pthread_mutex_init(&ctx->queueMutex, NULL);
+ (void)ZSTD_pthread_cond_init(&ctx->queuePushCond, NULL);
+ (void)ZSTD_pthread_cond_init(&ctx->queuePopCond, NULL);
ctx->shutdown = 0;
/* Allocate space for the thread handles */
- ctx->threads = (pthread_t*)malloc(numThreads * sizeof(pthread_t));
+ ctx->threads = (ZSTD_pthread_t*)ZSTD_malloc(numThreads * sizeof(ZSTD_pthread_t), customMem);
ctx->numThreads = 0;
+ ctx->customMem = customMem;
/* Check for errors */
if (!ctx->threads || !ctx->queue) { POOL_free(ctx); return NULL; }
/* Initialize the threads */
{ size_t i;
for (i = 0; i < numThreads; ++i) {
- if (pthread_create(&ctx->threads[i], NULL, &POOL_thread, ctx)) {
+ if (ZSTD_pthread_create(&ctx->threads[i], NULL, &POOL_thread, ctx)) {
ctx->numThreads = i;
POOL_free(ctx);
return NULL;
@@ -139,37 +146,37 @@ POOL_ctx *POOL_create(size_t numThreads, size_t queueSize) {
/*! POOL_join() :
Shutdown the queue, wake any sleeping threads, and join all of the threads.
*/
-static void POOL_join(POOL_ctx *ctx) {
+static void POOL_join(POOL_ctx* ctx) {
/* Shut down the queue */
- pthread_mutex_lock(&ctx->queueMutex);
+ ZSTD_pthread_mutex_lock(&ctx->queueMutex);
ctx->shutdown = 1;
- pthread_mutex_unlock(&ctx->queueMutex);
+ ZSTD_pthread_mutex_unlock(&ctx->queueMutex);
/* Wake up sleeping threads */
- pthread_cond_broadcast(&ctx->queuePushCond);
- pthread_cond_broadcast(&ctx->queuePopCond);
+ ZSTD_pthread_cond_broadcast(&ctx->queuePushCond);
+ ZSTD_pthread_cond_broadcast(&ctx->queuePopCond);
/* Join all of the threads */
{ size_t i;
for (i = 0; i < ctx->numThreads; ++i) {
- pthread_join(ctx->threads[i], NULL);
+ ZSTD_pthread_join(ctx->threads[i], NULL);
} }
}
void POOL_free(POOL_ctx *ctx) {
if (!ctx) { return; }
POOL_join(ctx);
- pthread_mutex_destroy(&ctx->queueMutex);
- pthread_cond_destroy(&ctx->queuePushCond);
- pthread_cond_destroy(&ctx->queuePopCond);
- if (ctx->queue) free(ctx->queue);
- if (ctx->threads) free(ctx->threads);
- free(ctx);
+ ZSTD_pthread_mutex_destroy(&ctx->queueMutex);
+ ZSTD_pthread_cond_destroy(&ctx->queuePushCond);
+ ZSTD_pthread_cond_destroy(&ctx->queuePopCond);
+ ZSTD_free(ctx->queue, ctx->customMem);
+ ZSTD_free(ctx->threads, ctx->customMem);
+ ZSTD_free(ctx, ctx->customMem);
}
size_t POOL_sizeof(POOL_ctx *ctx) {
if (ctx==NULL) return 0; /* supports sizeof NULL */
return sizeof(*ctx)
+ ctx->queueSize * sizeof(POOL_job)
- + ctx->numThreads * sizeof(pthread_t);
+ + ctx->numThreads * sizeof(ZSTD_pthread_t);
}
/**
@@ -191,12 +198,12 @@ void POOL_add(void* ctxVoid, POOL_function function, void *opaque) {
POOL_ctx* const ctx = (POOL_ctx*)ctxVoid;
if (!ctx) { return; }
- pthread_mutex_lock(&ctx->queueMutex);
+ ZSTD_pthread_mutex_lock(&ctx->queueMutex);
{ POOL_job const job = {function, opaque};
/* Wait until there is space in the queue for the new job */
while (isQueueFull(ctx) && !ctx->shutdown) {
- pthread_cond_wait(&ctx->queuePushCond, &ctx->queueMutex);
+ ZSTD_pthread_cond_wait(&ctx->queuePushCond, &ctx->queueMutex);
}
/* The queue is still going => there is space */
if (!ctx->shutdown) {
@@ -205,8 +212,8 @@ void POOL_add(void* ctxVoid, POOL_function function, void *opaque) {
ctx->queueTail = (ctx->queueTail + 1) % ctx->queueSize;
}
}
- pthread_mutex_unlock(&ctx->queueMutex);
- pthread_cond_signal(&ctx->queuePopCond);
+ ZSTD_pthread_mutex_unlock(&ctx->queueMutex);
+ ZSTD_pthread_cond_signal(&ctx->queuePopCond);
}
#else /* ZSTD_MULTITHREAD not defined */
@@ -214,26 +221,34 @@ void POOL_add(void* ctxVoid, POOL_function function, void *opaque) {
/* We don't need any data, but if it is empty malloc() might return NULL. */
struct POOL_ctx_s {
- int data;
+ int dummy;
};
+static POOL_ctx g_ctx;
POOL_ctx* POOL_create(size_t numThreads, size_t queueSize) {
- (void)numThreads;
- (void)queueSize;
- return (POOL_ctx*)malloc(sizeof(POOL_ctx));
+ return POOL_create_advanced(numThreads, queueSize, ZSTD_defaultCMem);
+}
+
+POOL_ctx* POOL_create_advanced(size_t numThreads, size_t queueSize, ZSTD_customMem customMem) {
+ (void)numThreads;
+ (void)queueSize;
+ (void)customMem;
+ return &g_ctx;
}
void POOL_free(POOL_ctx* ctx) {
- free(ctx);
+ assert(!ctx || ctx == &g_ctx);
+ (void)ctx;
}
void POOL_add(void* ctx, POOL_function function, void* opaque) {
- (void)ctx;
- function(opaque);
+ (void)ctx;
+ function(opaque);
}
size_t POOL_sizeof(POOL_ctx* ctx) {
if (ctx==NULL) return 0; /* supports sizeof NULL */
+ assert(ctx == &g_ctx);
return sizeof(*ctx);
}
diff --git a/thirdparty/zstd/common/pool.h b/thirdparty/zstd/common/pool.h
index 264c5c9ca7..08c63715aa 100644
--- a/thirdparty/zstd/common/pool.h
+++ b/thirdparty/zstd/common/pool.h
@@ -5,6 +5,7 @@
* This source code is licensed under both the BSD-style license (found in the
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
* in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
*/
#ifndef POOL_H
@@ -16,6 +17,7 @@ extern "C" {
#include <stddef.h> /* size_t */
+#include "zstd_internal.h" /* ZSTD_customMem */
typedef struct POOL_ctx_s POOL_ctx;
@@ -27,6 +29,8 @@ typedef struct POOL_ctx_s POOL_ctx;
*/
POOL_ctx *POOL_create(size_t numThreads, size_t queueSize);
+POOL_ctx *POOL_create_advanced(size_t numThreads, size_t queueSize, ZSTD_customMem customMem);
+
/*! POOL_free() :
Free a thread pool returned by POOL_create().
*/
diff --git a/thirdparty/zstd/common/threading.c b/thirdparty/zstd/common/threading.c
index 141376c561..8be8c8da94 100644
--- a/thirdparty/zstd/common/threading.c
+++ b/thirdparty/zstd/common/threading.c
@@ -2,9 +2,9 @@
* Copyright (c) 2016 Tino Reichardt
* All rights reserved.
*
- * This source code is licensed under the BSD-style license found in the
- * LICENSE file in the root directory of this source tree. An additional grant
- * of patent rights can be found in the PATENTS file in the same directory.
+ * This source code is licensed under both the BSD-style license (found in the
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
+ * in the COPYING file in the root directory of this source tree).
*
* You can contact the author at:
* - zstdmt source repository: https://github.com/mcmilk/zstdmt
@@ -14,12 +14,8 @@
* This file will hold wrapper for systems, which do not support pthreads
*/
-/* When ZSTD_MULTITHREAD is not defined, this file would become an empty translation unit.
-* Include some ISO C header code to prevent this and portably avoid related warnings.
-* (Visual C++: C4206 / GCC: -Wpedantic / Clang: -Wempty-translation-unit)
-*/
-#include <stddef.h>
-
+/* create fake symbol to avoid empty trnaslation unit warning */
+int g_ZSTD_threading_useles_symbol;
#if defined(ZSTD_MULTITHREAD) && defined(_WIN32)
@@ -39,12 +35,12 @@
static unsigned __stdcall worker(void *arg)
{
- pthread_t* const thread = (pthread_t*) arg;
+ ZSTD_pthread_t* const thread = (ZSTD_pthread_t*) arg;
thread->arg = thread->start_routine(thread->arg);
return 0;
}
-int pthread_create(pthread_t* thread, const void* unused,
+int ZSTD_pthread_create(ZSTD_pthread_t* thread, const void* unused,
void* (*start_routine) (void*), void* arg)
{
(void)unused;
@@ -58,16 +54,16 @@ int pthread_create(pthread_t* thread, const void* unused,
return 0;
}
-int _pthread_join(pthread_t * thread, void **value_ptr)
+int ZSTD_pthread_join(ZSTD_pthread_t thread, void **value_ptr)
{
DWORD result;
- if (!thread->handle) return 0;
+ if (!thread.handle) return 0;
- result = WaitForSingleObject(thread->handle, INFINITE);
+ result = WaitForSingleObject(thread.handle, INFINITE);
switch (result) {
case WAIT_OBJECT_0:
- if (value_ptr) *value_ptr = thread->arg;
+ if (value_ptr) *value_ptr = thread.arg;
return 0;
case WAIT_ABANDONED:
return EINVAL;
diff --git a/thirdparty/zstd/common/threading.h b/thirdparty/zstd/common/threading.h
index ab09977a86..197770db27 100644
--- a/thirdparty/zstd/common/threading.h
+++ b/thirdparty/zstd/common/threading.h
@@ -2,9 +2,9 @@
* Copyright (c) 2016 Tino Reichardt
* All rights reserved.
*
- * This source code is licensed under the BSD-style license found in the
- * LICENSE file in the root directory of this source tree. An additional grant
- * of patent rights can be found in the PATENTS file in the same directory.
+ * This source code is licensed under both the BSD-style license (found in the
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
+ * in the COPYING file in the root directory of this source tree).
*
* You can contact the author at:
* - zstdmt source repository: https://github.com/mcmilk/zstdmt
@@ -37,35 +37,38 @@ extern "C" {
# define WIN32_LEAN_AND_MEAN
#endif
+#undef ERROR /* reported already defined on VS 2015 (Rich Geldreich) */
#include <windows.h>
+#undef ERROR
+#define ERROR(name) ZSTD_ERROR(name)
+
/* mutex */
-#define pthread_mutex_t CRITICAL_SECTION
-#define pthread_mutex_init(a,b) (InitializeCriticalSection((a)), 0)
-#define pthread_mutex_destroy(a) DeleteCriticalSection((a))
-#define pthread_mutex_lock(a) EnterCriticalSection((a))
-#define pthread_mutex_unlock(a) LeaveCriticalSection((a))
+#define ZSTD_pthread_mutex_t CRITICAL_SECTION
+#define ZSTD_pthread_mutex_init(a, b) (InitializeCriticalSection((a)), 0)
+#define ZSTD_pthread_mutex_destroy(a) DeleteCriticalSection((a))
+#define ZSTD_pthread_mutex_lock(a) EnterCriticalSection((a))
+#define ZSTD_pthread_mutex_unlock(a) LeaveCriticalSection((a))
/* condition variable */
-#define pthread_cond_t CONDITION_VARIABLE
-#define pthread_cond_init(a, b) (InitializeConditionVariable((a)), 0)
-#define pthread_cond_destroy(a) /* No delete */
-#define pthread_cond_wait(a, b) SleepConditionVariableCS((a), (b), INFINITE)
-#define pthread_cond_signal(a) WakeConditionVariable((a))
-#define pthread_cond_broadcast(a) WakeAllConditionVariable((a))
-
-/* pthread_create() and pthread_join() */
+#define ZSTD_pthread_cond_t CONDITION_VARIABLE
+#define ZSTD_pthread_cond_init(a, b) (InitializeConditionVariable((a)), 0)
+#define ZSTD_pthread_cond_destroy(a) /* No delete */
+#define ZSTD_pthread_cond_wait(a, b) SleepConditionVariableCS((a), (b), INFINITE)
+#define ZSTD_pthread_cond_signal(a) WakeConditionVariable((a))
+#define ZSTD_pthread_cond_broadcast(a) WakeAllConditionVariable((a))
+
+/* ZSTD_pthread_create() and ZSTD_pthread_join() */
typedef struct {
HANDLE handle;
void* (*start_routine)(void*);
void* arg;
-} pthread_t;
+} ZSTD_pthread_t;
-int pthread_create(pthread_t* thread, const void* unused,
+int ZSTD_pthread_create(ZSTD_pthread_t* thread, const void* unused,
void* (*start_routine) (void*), void* arg);
-#define pthread_join(a, b) _pthread_join(&(a), (b))
-int _pthread_join(pthread_t* thread, void** value_ptr);
+int ZSTD_pthread_join(ZSTD_pthread_t thread, void** value_ptr);
/**
* add here more wrappers as required
@@ -76,23 +79,40 @@ int _pthread_join(pthread_t* thread, void** value_ptr);
/* === POSIX Systems === */
# include <pthread.h>
+#define ZSTD_pthread_mutex_t pthread_mutex_t
+#define ZSTD_pthread_mutex_init(a, b) pthread_mutex_init((a), (b))
+#define ZSTD_pthread_mutex_destroy(a) pthread_mutex_destroy((a))
+#define ZSTD_pthread_mutex_lock(a) pthread_mutex_lock((a))
+#define ZSTD_pthread_mutex_unlock(a) pthread_mutex_unlock((a))
+
+#define ZSTD_pthread_cond_t pthread_cond_t
+#define ZSTD_pthread_cond_init(a, b) pthread_cond_init((a), (b))
+#define ZSTD_pthread_cond_destroy(a) pthread_cond_destroy((a))
+#define ZSTD_pthread_cond_wait(a, b) pthread_cond_wait((a), (b))
+#define ZSTD_pthread_cond_signal(a) pthread_cond_signal((a))
+#define ZSTD_pthread_cond_broadcast(a) pthread_cond_broadcast((a))
+
+#define ZSTD_pthread_t pthread_t
+#define ZSTD_pthread_create(a, b, c, d) pthread_create((a), (b), (c), (d))
+#define ZSTD_pthread_join(a, b) pthread_join((a),(b))
+
#else /* ZSTD_MULTITHREAD not defined */
/* No multithreading support */
-#define pthread_mutex_t int /* #define rather than typedef, because sometimes pthread support is implicit, resulting in duplicated symbols */
-#define pthread_mutex_init(a,b) ((void)a, 0)
-#define pthread_mutex_destroy(a)
-#define pthread_mutex_lock(a)
-#define pthread_mutex_unlock(a)
+typedef int ZSTD_pthread_mutex_t;
+#define ZSTD_pthread_mutex_init(a, b) ((void)a, 0)
+#define ZSTD_pthread_mutex_destroy(a)
+#define ZSTD_pthread_mutex_lock(a)
+#define ZSTD_pthread_mutex_unlock(a)
-#define pthread_cond_t int
-#define pthread_cond_init(a,b) ((void)a, 0)
-#define pthread_cond_destroy(a)
-#define pthread_cond_wait(a,b)
-#define pthread_cond_signal(a)
-#define pthread_cond_broadcast(a)
+typedef int ZSTD_pthread_cond_t;
+#define ZSTD_pthread_cond_init(a, b) ((void)a, 0)
+#define ZSTD_pthread_cond_destroy(a)
+#define ZSTD_pthread_cond_wait(a, b)
+#define ZSTD_pthread_cond_signal(a)
+#define ZSTD_pthread_cond_broadcast(a)
-/* do not use pthread_t */
+/* do not use ZSTD_pthread_t */
#endif /* ZSTD_MULTITHREAD */
diff --git a/thirdparty/zstd/common/zstd_common.c b/thirdparty/zstd/common/zstd_common.c
index 08384cabf5..c2041053be 100644
--- a/thirdparty/zstd/common/zstd_common.c
+++ b/thirdparty/zstd/common/zstd_common.c
@@ -5,6 +5,7 @@
* This source code is licensed under both the BSD-style license (found in the
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
* in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
*/
@@ -15,8 +16,7 @@
#include <stdlib.h> /* malloc, calloc, free */
#include <string.h> /* memset */
#include "error_private.h"
-#define ZSTD_STATIC_LINKING_ONLY
-#include "zstd.h"
+#include "zstd_internal.h"
/*-****************************************
diff --git a/thirdparty/zstd/common/zstd_errors.h b/thirdparty/zstd/common/zstd_errors.h
index a69387b714..4bcb7769fe 100644
--- a/thirdparty/zstd/common/zstd_errors.h
+++ b/thirdparty/zstd/common/zstd_errors.h
@@ -5,6 +5,7 @@
* This source code is licensed under both the BSD-style license (found in the
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
* in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
*/
#ifndef ZSTD_ERRORS_H_398273423
@@ -62,9 +63,10 @@ typedef enum {
ZSTD_error_memory_allocation = 64,
ZSTD_error_dstSize_tooSmall = 70,
ZSTD_error_srcSize_wrong = 72,
+ /* following error codes are not stable and may be removed or changed in a future version */
ZSTD_error_frameIndex_tooLarge = 100,
ZSTD_error_seekableIO = 102,
- ZSTD_error_maxCode = 120 /* never EVER use this value directly, it may change in future versions! Use ZSTD_isError() instead */
+ ZSTD_error_maxCode = 120 /* never EVER use this value directly, it can change in future versions! Use ZSTD_isError() instead */
} ZSTD_ErrorCode;
/*! ZSTD_getErrorCode() :
diff --git a/thirdparty/zstd/common/zstd_internal.h b/thirdparty/zstd/common/zstd_internal.h
index 2610528608..e91cd20baa 100644
--- a/thirdparty/zstd/common/zstd_internal.h
+++ b/thirdparty/zstd/common/zstd_internal.h
@@ -5,6 +5,7 @@
* This source code is licensed under both the BSD-style license (found in the
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
* in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
*/
#ifndef ZSTD_CCOMMON_H_MODULE
@@ -29,6 +30,11 @@
#include "xxhash.h" /* XXH_reset, update, digest */
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+
/*-*************************************
* Debug
***************************************/
@@ -96,9 +102,13 @@ static const U32 repStartValue[ZSTD_REP_NUM] = { 1, 4, 8 };
#define BIT0 1
#define ZSTD_WINDOWLOG_ABSOLUTEMIN 10
+#define ZSTD_WINDOWLOG_DEFAULTMAX 27 /* Default maximum allowed window log */
static const size_t ZSTD_fcs_fieldSize[4] = { 0, 2, 4, 8 };
static const size_t ZSTD_did_fieldSize[4] = { 0, 1, 2, 4 };
+#define ZSTD_FRAMEIDSIZE 4
+static const size_t ZSTD_frameIdSize = ZSTD_FRAMEIDSIZE; /* magic number size */
+
#define ZSTD_BLOCKHEADERSIZE 3 /* C standard doesn't allow `static const` variable to be init using another `static const` variable */
static const size_t ZSTD_blockHeaderSize = ZSTD_BLOCKHEADERSIZE;
typedef enum { bt_raw, bt_rle, bt_compressed, bt_reserved } blockType_e;
@@ -117,7 +127,8 @@ typedef enum { set_basic, set_rle, set_compressed, set_repeat } symbolEncodingTy
#define MaxLit ((1<<Litbits) - 1)
#define MaxML 52
#define MaxLL 35
-#define MaxOff 28
+#define DefaultMaxOff 28
+#define MaxOff 31
#define MaxSeq MAX(MaxLL, MaxML) /* Assumption : MaxOff < MaxLL,MaxML */
#define MLFSELog 9
#define LLFSELog 9
@@ -143,8 +154,8 @@ static const S16 ML_defaultNorm[MaxML+1] = { 1, 4, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1,
#define ML_DEFAULTNORMLOG 6 /* for static allocation */
static const U32 ML_defaultNormLog = ML_DEFAULTNORMLOG;
-static const S16 OF_defaultNorm[MaxOff+1] = { 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,-1,-1,-1,-1,-1 };
+static const S16 OF_defaultNorm[DefaultMaxOff+1] = { 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,-1,-1,-1,-1,-1 };
#define OF_DEFAULTNORMLOG 5 /* for static allocation */
static const U32 OF_defaultNormLog = OF_DEFAULTNORMLOG;
@@ -244,6 +255,26 @@ typedef struct {
} optState_t;
typedef struct {
+ U32 offset;
+ U32 checksum;
+} ldmEntry_t;
+
+typedef struct {
+ ldmEntry_t* hashTable;
+ BYTE* bucketOffsets; /* Next position in bucket to insert entry */
+ U64 hashPower; /* Used to compute the rolling hash.
+ * Depends on ldmParams.minMatchLength */
+} ldmState_t;
+
+typedef struct {
+ U32 enableLdm; /* 1 if enable long distance matching */
+ U32 hashLog; /* Log size of hashTable */
+ U32 bucketSizeLog; /* Log bucket size for collision resolution, at most 8 */
+ U32 minMatchLength; /* Minimum match length */
+ U32 hashEveryLog; /* Log number of entries to skip */
+} ldmParams_t;
+
+typedef struct {
U32 hufCTable[HUF_CTABLE_SIZE_U32(255)];
FSE_CTable offcodeCTable[FSE_CTABLE_SIZE_U32(OffFSELog, MaxOff)];
FSE_CTable matchlengthCTable[FSE_CTABLE_SIZE_U32(MLFSELog, MaxML)];
@@ -255,6 +286,28 @@ typedef struct {
FSE_repeat litlength_repeatMode;
} ZSTD_entropyCTables_t;
+struct ZSTD_CCtx_params_s {
+ ZSTD_format_e format;
+ ZSTD_compressionParameters cParams;
+ ZSTD_frameParameters fParams;
+
+ int compressionLevel;
+ U32 forceWindow; /* force back-references to respect limit of
+ * 1<<wLog, even for dictionary */
+
+ /* Multithreading: used to pass parameters to mtctx */
+ U32 nbThreads;
+ unsigned jobSize;
+ unsigned overlapSizeLog;
+
+ /* Long distance matching parameters */
+ ldmParams_t ldmParams;
+
+ /* For use with createCCtxParams() and freeCCtxParams() only */
+ ZSTD_customMem customMem;
+
+}; /* typedef'd to ZSTD_CCtx_params within "zstd.h" */
+
const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx);
void ZSTD_seqToCodes(const seqStore_t* seqStorePtr);
@@ -268,24 +321,27 @@ void ZSTD_free(void* ptr, ZSTD_customMem customMem);
MEM_STATIC U32 ZSTD_highbit32(U32 val)
{
+ assert(val != 0);
+ {
# if defined(_MSC_VER) /* Visual */
- unsigned long r=0;
- _BitScanReverse(&r, val);
- return (unsigned)r;
+ unsigned long r=0;
+ _BitScanReverse(&r, val);
+ return (unsigned)r;
# elif defined(__GNUC__) && (__GNUC__ >= 3) /* GCC Intrinsic */
- return 31 - __builtin_clz(val);
+ return 31 - __builtin_clz(val);
# else /* Software version */
- static const int DeBruijnClz[32] = { 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 };
- U32 v = val;
- int r;
- v |= v >> 1;
- v |= v >> 2;
- v |= v >> 4;
- v |= v >> 8;
- v |= v >> 16;
- r = DeBruijnClz[(U32)(v * 0x07C4ACDDU) >> 27];
- return r;
+ static const int DeBruijnClz[32] = { 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 };
+ U32 v = val;
+ int r;
+ v |= v >> 1;
+ v |= v >> 2;
+ v |= v >> 4;
+ v |= v >> 8;
+ v |= v >> 16;
+ r = DeBruijnClz[(U32)(v * 0x07C4ACDDU) >> 27];
+ return r;
# endif
+ }
}
@@ -306,7 +362,7 @@ void ZSTD_invalidateRepCodes(ZSTD_CCtx* cctx);
size_t ZSTD_initCStream_internal(ZSTD_CStream* zcs,
const void* dict, size_t dictSize,
const ZSTD_CDict* cdict,
- ZSTD_parameters params, unsigned long long pledgedSrcSize);
+ ZSTD_CCtx_params params, unsigned long long pledgedSrcSize);
/*! ZSTD_compressStream_generic() :
* Private use only. To be called from zstdmt_compress.c in single-thread mode. */
@@ -315,10 +371,25 @@ size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
ZSTD_inBuffer* input,
ZSTD_EndDirective const flushMode);
-/*! ZSTD_getParamsFromCDict() :
+/*! ZSTD_getCParamsFromCDict() :
* as the name implies */
-ZSTD_parameters ZSTD_getParamsFromCDict(const ZSTD_CDict* cdict);
-
+ZSTD_compressionParameters ZSTD_getCParamsFromCDict(const ZSTD_CDict* cdict);
+
+/* ZSTD_compressBegin_advanced_internal() :
+ * Private use only. To be called from zstdmt_compress.c. */
+size_t ZSTD_compressBegin_advanced_internal(ZSTD_CCtx* cctx,
+ const void* dict, size_t dictSize,
+ ZSTD_dictMode_e dictMode,
+ ZSTD_CCtx_params params,
+ unsigned long long pledgedSrcSize);
+
+/* ZSTD_compress_advanced_internal() :
+ * Private use only. To be called from zstdmt_compress.c. */
+size_t ZSTD_compress_advanced_internal(ZSTD_CCtx* cctx,
+ void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize,
+ const void* dict,size_t dictSize,
+ ZSTD_CCtx_params params);
typedef struct {
blockType_e blockType;
@@ -331,5 +402,8 @@ typedef struct {
size_t ZSTD_getcBlockSize(const void* src, size_t srcSize,
blockProperties_t* bpPtr);
+#if defined (__cplusplus)
+}
+#endif
#endif /* ZSTD_CCOMMON_H_MODULE */
diff --git a/thirdparty/zstd/compress/fse_compress.c b/thirdparty/zstd/compress/fse_compress.c
index cc9fa73514..549c115d42 100644
--- a/thirdparty/zstd/compress/fse_compress.c
+++ b/thirdparty/zstd/compress/fse_compress.c
@@ -461,6 +461,7 @@ static unsigned FSE_minTableLog(size_t srcSize, unsigned maxSymbolValue)
U32 minBitsSrc = BIT_highbit32((U32)(srcSize - 1)) + 1;
U32 minBitsSymbols = BIT_highbit32(maxSymbolValue) + 2;
U32 minBits = minBitsSrc < minBitsSymbols ? minBitsSrc : minBitsSymbols;
+ assert(srcSize > 1); /* Not supported, RLE should be used instead */
return minBits;
}
@@ -469,6 +470,7 @@ unsigned FSE_optimalTableLog_internal(unsigned maxTableLog, size_t srcSize, unsi
U32 maxBitsSrc = BIT_highbit32((U32)(srcSize - 1)) - minus;
U32 tableLog = maxTableLog;
U32 minBits = FSE_minTableLog(srcSize, maxSymbolValue);
+ assert(srcSize > 1); /* Not supported, RLE should be used instead */
if (tableLog==0) tableLog = FSE_DEFAULT_TABLELOG;
if (maxBitsSrc < tableLog) tableLog = maxBitsSrc; /* Accuracy can be reduced */
if (minBits > tableLog) tableLog = minBits; /* Need a minimum to safely represent all symbol values */
@@ -580,7 +582,7 @@ size_t FSE_normalizeCount (short* normalizedCounter, unsigned tableLog,
if (tableLog > FSE_MAX_TABLELOG) return ERROR(tableLog_tooLarge); /* Unsupported size */
if (tableLog < FSE_minTableLog(total, maxSymbolValue)) return ERROR(GENERIC); /* Too small tableLog, compression potentially impossible */
- { U32 const rtbTable[] = { 0, 473195, 504333, 520860, 550000, 700000, 750000, 830000 };
+ { static U32 const rtbTable[] = { 0, 473195, 504333, 520860, 550000, 700000, 750000, 830000 };
U64 const scale = 62 - tableLog;
U64 const step = ((U64)1<<62) / total; /* <== here, one division ! */
U64 const vStep = 1ULL<<(scale-20);
diff --git a/thirdparty/zstd/compress/huf_compress.c b/thirdparty/zstd/compress/huf_compress.c
index 2a47c18205..5692d56e00 100644
--- a/thirdparty/zstd/compress/huf_compress.c
+++ b/thirdparty/zstd/compress/huf_compress.c
@@ -167,7 +167,7 @@ size_t HUF_writeCTable (void* dst, size_t maxDstSize,
}
-size_t HUF_readCTable (HUF_CElt* CTable, U32 maxSymbolValue, const void* src, size_t srcSize)
+size_t HUF_readCTable (HUF_CElt* CTable, U32* maxSymbolValuePtr, const void* src, size_t srcSize)
{
BYTE huffWeight[HUF_SYMBOLVALUE_MAX + 1]; /* init not required, even though some static analyzer may complain */
U32 rankVal[HUF_TABLELOG_ABSOLUTEMAX + 1]; /* large enough for values from 0 to 16 */
@@ -179,7 +179,7 @@ size_t HUF_readCTable (HUF_CElt* CTable, U32 maxSymbolValue, const void* src, si
/* check result */
if (tableLog > HUF_TABLELOG_MAX) return ERROR(tableLog_tooLarge);
- if (nbSymbols > maxSymbolValue+1) return ERROR(maxSymbolValue_tooSmall);
+ if (nbSymbols > *maxSymbolValuePtr+1) return ERROR(maxSymbolValue_tooSmall);
/* Prepare base value per rank */
{ U32 n, nextRankStart = 0;
@@ -208,9 +208,10 @@ size_t HUF_readCTable (HUF_CElt* CTable, U32 maxSymbolValue, const void* src, si
min >>= 1;
} }
/* assign value within rank, symbol order */
- { U32 n; for (n=0; n<=maxSymbolValue; n++) CTable[n].val = valPerRank[CTable[n].nbBits]++; }
+ { U32 n; for (n=0; n<nbSymbols; n++) CTable[n].val = valPerRank[CTable[n].nbBits]++; }
}
+ *maxSymbolValuePtr = nbSymbols - 1;
return readSize;
}
diff --git a/thirdparty/zstd/compress/zstd_compress.c b/thirdparty/zstd/compress/zstd_compress.c
index 0322c03eb3..2c46c79f1c 100644
--- a/thirdparty/zstd/compress/zstd_compress.c
+++ b/thirdparty/zstd/compress/zstd_compress.c
@@ -5,6 +5,7 @@
* This source code is licensed under both the BSD-style license (found in the
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
* in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
*/
@@ -25,25 +26,19 @@
#include "fse.h"
#define HUF_STATIC_LINKING_ONLY
#include "huf.h"
-#include "zstd_internal.h" /* includes zstd.h */
-#include "zstdmt_compress.h"
-
-
-/*-*************************************
-* Constants
-***************************************/
-static const U32 g_searchStrength = 8; /* control skip over incompressible data */
-#define HASH_READ_SIZE 8
-typedef enum { ZSTDcs_created=0, ZSTDcs_init, ZSTDcs_ongoing, ZSTDcs_ending } ZSTD_compressionStage_e;
+#include "zstd_compress.h"
+#include "zstd_fast.h"
+#include "zstd_double_fast.h"
+#include "zstd_lazy.h"
+#include "zstd_opt.h"
+#include "zstd_ldm.h"
/*-*************************************
* Helper functions
***************************************/
size_t ZSTD_compressBound(size_t srcSize) {
- size_t const lowLimit = 256 KB;
- size_t const margin = (srcSize < lowLimit) ? (lowLimit-srcSize) >> 12 : 0; /* from 64 to 0 */
- return srcSize + (srcSize >> 8) + margin;
+ return ZSTD_COMPRESSBOUND(srcSize);
}
@@ -61,8 +56,6 @@ static void ZSTD_resetSeqStore(seqStore_t* ssPtr)
/*-*************************************
* Context memory management
***************************************/
-typedef enum { zcss_init=0, zcss_load, zcss_flush } ZSTD_cStreamStage;
-
struct ZSTD_CDict_s {
void* dictBuffer;
const void* dictContent;
@@ -70,65 +63,6 @@ struct ZSTD_CDict_s {
ZSTD_CCtx* refContext;
}; /* typedef'd to ZSTD_CDict within "zstd.h" */
-struct ZSTD_CCtx_s {
- const BYTE* nextSrc; /* next block here to continue on current prefix */
- const BYTE* base; /* All regular indexes relative to this position */
- const BYTE* dictBase; /* extDict indexes relative to this position */
- U32 dictLimit; /* below that point, need extDict */
- U32 lowLimit; /* below that point, no more data */
- U32 nextToUpdate; /* index from which to continue dictionary update */
- U32 nextToUpdate3; /* index from which to continue dictionary update */
- U32 hashLog3; /* dispatch table : larger == faster, more memory */
- U32 loadedDictEnd; /* index of end of dictionary */
- U32 forceWindow; /* force back-references to respect limit of 1<<wLog, even for dictionary */
- ZSTD_compressionStage_e stage;
- U32 dictID;
- int compressionLevel;
- ZSTD_parameters requestedParams;
- ZSTD_parameters appliedParams;
- void* workSpace;
- size_t workSpaceSize;
- size_t blockSize;
- U64 pledgedSrcSizePlusOne; /* this way, 0 (default) == unknown */
- U64 consumedSrcSize;
- XXH64_state_t xxhState;
- ZSTD_customMem customMem;
- size_t staticSize;
-
- seqStore_t seqStore; /* sequences storage ptrs */
- optState_t optState;
- U32* hashTable;
- U32* hashTable3;
- U32* chainTable;
- ZSTD_entropyCTables_t* entropy;
-
- /* streaming */
- char* inBuff;
- size_t inBuffSize;
- size_t inToCompress;
- size_t inBuffPos;
- size_t inBuffTarget;
- char* outBuff;
- size_t outBuffSize;
- size_t outBuffContentSize;
- size_t outBuffFlushedSize;
- ZSTD_cStreamStage streamStage;
- U32 frameEnded;
-
- /* Dictionary */
- ZSTD_dictMode_e dictMode; /* select restricting dictionary to "rawContent" or "fullDict" only */
- U32 dictContentByRef;
- ZSTD_CDict* cdictLocal;
- const ZSTD_CDict* cdict;
- const void* prefix;
- size_t prefixSize;
-
- /* Multi-threading */
- U32 nbThreads;
- ZSTDMT_CCtx* mtctx;
-};
-
-
ZSTD_CCtx* ZSTD_createCCtx(void)
{
return ZSTD_createCCtx_advanced(ZSTD_defaultCMem);
@@ -143,7 +77,7 @@ ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem)
cctx = (ZSTD_CCtx*) ZSTD_calloc(sizeof(ZSTD_CCtx), customMem);
if (!cctx) return NULL;
cctx->customMem = customMem;
- cctx->compressionLevel = ZSTD_CLEVEL_DEFAULT;
+ cctx->requestedParams.compressionLevel = ZSTD_CLEVEL_DEFAULT;
ZSTD_STATIC_ASSERT(zcss_init==0);
ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_UNKNOWN==(0ULL - 1));
return cctx;
@@ -151,7 +85,7 @@ ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem)
ZSTD_CCtx* ZSTD_initStaticCCtx(void *workspace, size_t workspaceSize)
{
- ZSTD_CCtx* cctx = (ZSTD_CCtx*) workspace;
+ ZSTD_CCtx* const cctx = (ZSTD_CCtx*) workspace;
if (workspaceSize <= sizeof(ZSTD_CCtx)) return NULL; /* minimum size */
if ((size_t)workspace & 7) return NULL; /* must be 8-aligned */
memset(workspace, 0, workspaceSize); /* may be a bit generous, could memset be smaller ? */
@@ -161,7 +95,7 @@ ZSTD_CCtx* ZSTD_initStaticCCtx(void *workspace, size_t workspaceSize)
/* entropy space (never moves) */
if (cctx->workSpaceSize < sizeof(ZSTD_entropyCTables_t)) return NULL;
- assert(((size_t)cctx->workSpace & 7) == 0); /* ensure correct alignment */
+ assert(((size_t)cctx->workSpace & (sizeof(void*)-1)) == 0); /* ensure correct alignment */
cctx->entropy = (ZSTD_entropyCTables_t*)cctx->workSpace;
return cctx;
@@ -175,23 +109,36 @@ size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx)
cctx->workSpace = NULL;
ZSTD_freeCDict(cctx->cdictLocal);
cctx->cdictLocal = NULL;
+#ifdef ZSTD_MULTITHREAD
ZSTDMT_freeCCtx(cctx->mtctx);
cctx->mtctx = NULL;
+#endif
ZSTD_free(cctx, cctx->customMem);
return 0; /* reserved as a potential error code in the future */
}
+
+static size_t ZSTD_sizeof_mtctx(const ZSTD_CCtx* cctx)
+{
+#ifdef ZSTD_MULTITHREAD
+ return ZSTDMT_sizeof_CCtx(cctx->mtctx);
+#else
+ (void) cctx;
+ return 0;
+#endif
+}
+
+
size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx)
{
if (cctx==NULL) return 0; /* support sizeof on NULL */
- DEBUGLOG(5, "sizeof(*cctx) : %u", (U32)sizeof(*cctx));
- DEBUGLOG(5, "workSpaceSize : %u", (U32)cctx->workSpaceSize);
- DEBUGLOG(5, "streaming buffers : %u", (U32)(cctx->outBuffSize + cctx->inBuffSize));
- DEBUGLOG(5, "inner MTCTX : %u", (U32)ZSTDMT_sizeof_CCtx(cctx->mtctx));
+ DEBUGLOG(3, "sizeof(*cctx) : %u", (U32)sizeof(*cctx));
+ DEBUGLOG(3, "workSpaceSize (including streaming buffers): %u", (U32)cctx->workSpaceSize);
+ DEBUGLOG(3, "inner cdict : %u", (U32)ZSTD_sizeof_CDict(cctx->cdictLocal));
+ DEBUGLOG(3, "inner MTCTX : %u", (U32)ZSTD_sizeof_mtctx(cctx));
return sizeof(*cctx) + cctx->workSpaceSize
+ ZSTD_sizeof_CDict(cctx->cdictLocal)
- + cctx->outBuffSize + cctx->inBuffSize
- + ZSTDMT_sizeof_CCtx(cctx->mtctx);
+ + ZSTD_sizeof_mtctx(cctx);
}
size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs)
@@ -202,29 +149,99 @@ size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs)
/* private API call, for dictBuilder only */
const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx) { return &(ctx->seqStore); }
-static ZSTD_parameters ZSTD_getParamsFromCCtx(const ZSTD_CCtx* cctx) { return cctx->appliedParams; }
+#define ZSTD_CLEVEL_CUSTOM 999
-/* older variant; will be deprecated */
-size_t ZSTD_setCCtxParameter(ZSTD_CCtx* cctx, ZSTD_CCtxParameter param, unsigned value)
+static ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams(
+ ZSTD_CCtx_params params, U64 srcSizeHint, size_t dictSize)
{
- switch(param)
- {
- case ZSTD_p_forceWindow : cctx->forceWindow = value>0; cctx->loadedDictEnd = 0; return 0;
- ZSTD_STATIC_ASSERT(ZSTD_dm_auto==0);
- ZSTD_STATIC_ASSERT(ZSTD_dm_rawContent==1);
- case ZSTD_p_forceRawDict : cctx->dictMode = (ZSTD_dictMode_e)(value>0); return 0;
- default: return ERROR(parameter_unsupported);
- }
+ return (params.compressionLevel == ZSTD_CLEVEL_CUSTOM ?
+ params.cParams :
+ ZSTD_getCParams(params.compressionLevel, srcSizeHint, dictSize));
}
+static void ZSTD_cLevelToCCtxParams_srcSize(ZSTD_CCtx_params* params, U64 srcSize)
+{
+ params->cParams = ZSTD_getCParamsFromCCtxParams(*params, srcSize, 0);
+ params->compressionLevel = ZSTD_CLEVEL_CUSTOM;
+}
-#define ZSTD_CLEVEL_CUSTOM 999
static void ZSTD_cLevelToCParams(ZSTD_CCtx* cctx)
{
- if (cctx->compressionLevel==ZSTD_CLEVEL_CUSTOM) return;
- cctx->requestedParams.cParams = ZSTD_getCParams(cctx->compressionLevel,
- cctx->pledgedSrcSizePlusOne-1, 0);
- cctx->compressionLevel = ZSTD_CLEVEL_CUSTOM;
+ ZSTD_cLevelToCCtxParams_srcSize(
+ &cctx->requestedParams, cctx->pledgedSrcSizePlusOne-1);
+}
+
+static void ZSTD_cLevelToCCtxParams(ZSTD_CCtx_params* params)
+{
+ ZSTD_cLevelToCCtxParams_srcSize(params, 0);
+}
+
+static ZSTD_CCtx_params ZSTD_makeCCtxParamsFromCParams(
+ ZSTD_compressionParameters cParams)
+{
+ ZSTD_CCtx_params cctxParams;
+ memset(&cctxParams, 0, sizeof(cctxParams));
+ cctxParams.cParams = cParams;
+ cctxParams.compressionLevel = ZSTD_CLEVEL_CUSTOM;
+ return cctxParams;
+}
+
+static ZSTD_CCtx_params* ZSTD_createCCtxParams_advanced(
+ ZSTD_customMem customMem)
+{
+ ZSTD_CCtx_params* params;
+ if (!customMem.customAlloc ^ !customMem.customFree) return NULL;
+ params = (ZSTD_CCtx_params*)ZSTD_calloc(
+ sizeof(ZSTD_CCtx_params), customMem);
+ if (!params) { return NULL; }
+ params->customMem = customMem;
+ params->compressionLevel = ZSTD_CLEVEL_DEFAULT;
+ return params;
+}
+
+ZSTD_CCtx_params* ZSTD_createCCtxParams(void)
+{
+ return ZSTD_createCCtxParams_advanced(ZSTD_defaultCMem);
+}
+
+size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params)
+{
+ if (params == NULL) { return 0; }
+ ZSTD_free(params, params->customMem);
+ return 0;
+}
+
+size_t ZSTD_resetCCtxParams(ZSTD_CCtx_params* params)
+{
+ return ZSTD_initCCtxParams(params, ZSTD_CLEVEL_DEFAULT);
+}
+
+size_t ZSTD_initCCtxParams(ZSTD_CCtx_params* cctxParams, int compressionLevel) {
+ if (!cctxParams) { return ERROR(GENERIC); }
+ memset(cctxParams, 0, sizeof(*cctxParams));
+ cctxParams->compressionLevel = compressionLevel;
+ return 0;
+}
+
+size_t ZSTD_initCCtxParams_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params)
+{
+ if (!cctxParams) { return ERROR(GENERIC); }
+ CHECK_F( ZSTD_checkCParams(params.cParams) );
+ memset(cctxParams, 0, sizeof(*cctxParams));
+ cctxParams->cParams = params.cParams;
+ cctxParams->fParams = params.fParams;
+ cctxParams->compressionLevel = ZSTD_CLEVEL_CUSTOM;
+ return 0;
+}
+
+static ZSTD_CCtx_params ZSTD_assignParamsToCCtxParams(
+ ZSTD_CCtx_params cctxParams, ZSTD_parameters params)
+{
+ ZSTD_CCtx_params ret = cctxParams;
+ ret.cParams = params.cParams;
+ ret.fParams = params.fParams;
+ ret.compressionLevel = ZSTD_CLEVEL_CUSTOM;
+ return ret;
}
#define CLAMPCHECK(val,min,max) { \
@@ -238,167 +255,285 @@ size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, unsigned v
switch(param)
{
- case ZSTD_p_compressionLevel :
- if ((int)value > ZSTD_maxCLevel()) value = ZSTD_maxCLevel(); /* cap max compression level */
+ case ZSTD_p_format :
+ return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
+
+ case ZSTD_p_compressionLevel:
if (value == 0) return 0; /* special value : 0 means "don't change anything" */
if (cctx->cdict) return ERROR(stage_wrong);
- cctx->compressionLevel = value;
- return 0;
+ return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
+
+ case ZSTD_p_windowLog:
+ case ZSTD_p_hashLog:
+ case ZSTD_p_chainLog:
+ case ZSTD_p_searchLog:
+ case ZSTD_p_minMatch:
+ case ZSTD_p_targetLength:
+ case ZSTD_p_compressionStrategy:
+ if (value == 0) return 0; /* special value : 0 means "don't change anything" */
+ if (cctx->cdict) return ERROR(stage_wrong);
+ ZSTD_cLevelToCParams(cctx); /* Can optimize if srcSize is known */
+ return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
- case ZSTD_p_windowLog :
- DEBUGLOG(5, "setting ZSTD_p_windowLog = %u (cdict:%u)",
- value, (cctx->cdict!=NULL));
+ case ZSTD_p_contentSizeFlag:
+ case ZSTD_p_checksumFlag:
+ case ZSTD_p_dictIDFlag:
+ return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
+
+ case ZSTD_p_forceMaxWindow : /* Force back-references to remain < windowSize,
+ * even when referencing into Dictionary content
+ * default : 0 when using a CDict, 1 when using a Prefix */
+ cctx->loadedDictEnd = 0;
+ return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
+
+ case ZSTD_p_nbThreads:
+ if (value==0) return 0;
+ DEBUGLOG(5, " setting nbThreads : %u", value);
+ if (value > 1 && cctx->staticSize) {
+ return ERROR(parameter_unsupported); /* MT not compatible with static alloc */
+ }
+ return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
+
+ case ZSTD_p_jobSize:
+ return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
+
+ case ZSTD_p_overlapSizeLog:
+ DEBUGLOG(5, " setting overlap with nbThreads == %u", cctx->requestedParams.nbThreads);
+ return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
+
+ case ZSTD_p_enableLongDistanceMatching:
+ if (cctx->cdict) return ERROR(stage_wrong);
+ if (value != 0) {
+ ZSTD_cLevelToCParams(cctx);
+ }
+ return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
+
+ case ZSTD_p_ldmHashLog:
+ case ZSTD_p_ldmMinMatch:
if (value == 0) return 0; /* special value : 0 means "don't change anything" */
if (cctx->cdict) return ERROR(stage_wrong);
+ return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
+
+ case ZSTD_p_ldmBucketSizeLog:
+ case ZSTD_p_ldmHashEveryLog:
+ if (cctx->cdict) return ERROR(stage_wrong);
+ return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
+
+ default: return ERROR(parameter_unsupported);
+ }
+}
+
+size_t ZSTD_CCtxParam_setParameter(
+ ZSTD_CCtx_params* params, ZSTD_cParameter param, unsigned value)
+{
+ switch(param)
+ {
+ case ZSTD_p_format :
+ if (value > (unsigned)ZSTD_f_zstd1_magicless)
+ return ERROR(parameter_unsupported);
+ params->format = (ZSTD_format_e)value;
+ return 0;
+
+ case ZSTD_p_compressionLevel :
+ if ((int)value > ZSTD_maxCLevel()) value = ZSTD_maxCLevel();
+ if (value == 0) return 0;
+ params->compressionLevel = value;
+ return 0;
+
+ case ZSTD_p_windowLog :
+ if (value == 0) return 0;
CLAMPCHECK(value, ZSTD_WINDOWLOG_MIN, ZSTD_WINDOWLOG_MAX);
- ZSTD_cLevelToCParams(cctx);
- cctx->requestedParams.cParams.windowLog = value;
+ ZSTD_cLevelToCCtxParams(params);
+ params->cParams.windowLog = value;
return 0;
case ZSTD_p_hashLog :
- if (value == 0) return 0; /* special value : 0 means "don't change anything" */
- if (cctx->cdict) return ERROR(stage_wrong);
+ if (value == 0) return 0;
CLAMPCHECK(value, ZSTD_HASHLOG_MIN, ZSTD_HASHLOG_MAX);
- ZSTD_cLevelToCParams(cctx);
- cctx->requestedParams.cParams.hashLog = value;
+ ZSTD_cLevelToCCtxParams(params);
+ params->cParams.hashLog = value;
return 0;
case ZSTD_p_chainLog :
- if (value == 0) return 0; /* special value : 0 means "don't change anything" */
- if (cctx->cdict) return ERROR(stage_wrong);
+ if (value == 0) return 0;
CLAMPCHECK(value, ZSTD_CHAINLOG_MIN, ZSTD_CHAINLOG_MAX);
- ZSTD_cLevelToCParams(cctx);
- cctx->requestedParams.cParams.chainLog = value;
+ ZSTD_cLevelToCCtxParams(params);
+ params->cParams.chainLog = value;
return 0;
case ZSTD_p_searchLog :
- if (value == 0) return 0; /* special value : 0 means "don't change anything" */
- if (cctx->cdict) return ERROR(stage_wrong);
+ if (value == 0) return 0;
CLAMPCHECK(value, ZSTD_SEARCHLOG_MIN, ZSTD_SEARCHLOG_MAX);
- ZSTD_cLevelToCParams(cctx);
- cctx->requestedParams.cParams.searchLog = value;
+ ZSTD_cLevelToCCtxParams(params);
+ params->cParams.searchLog = value;
return 0;
case ZSTD_p_minMatch :
- if (value == 0) return 0; /* special value : 0 means "don't change anything" */
- if (cctx->cdict) return ERROR(stage_wrong);
+ if (value == 0) return 0;
CLAMPCHECK(value, ZSTD_SEARCHLENGTH_MIN, ZSTD_SEARCHLENGTH_MAX);
- ZSTD_cLevelToCParams(cctx);
- cctx->requestedParams.cParams.searchLength = value;
+ ZSTD_cLevelToCCtxParams(params);
+ params->cParams.searchLength = value;
return 0;
case ZSTD_p_targetLength :
- if (value == 0) return 0; /* special value : 0 means "don't change anything" */
- if (cctx->cdict) return ERROR(stage_wrong);
+ if (value == 0) return 0;
CLAMPCHECK(value, ZSTD_TARGETLENGTH_MIN, ZSTD_TARGETLENGTH_MAX);
- ZSTD_cLevelToCParams(cctx);
- cctx->requestedParams.cParams.targetLength = value;
+ ZSTD_cLevelToCCtxParams(params);
+ params->cParams.targetLength = value;
return 0;
case ZSTD_p_compressionStrategy :
- if (value == 0) return 0; /* special value : 0 means "don't change anything" */
- if (cctx->cdict) return ERROR(stage_wrong);
+ if (value == 0) return 0;
CLAMPCHECK(value, (unsigned)ZSTD_fast, (unsigned)ZSTD_btultra);
- ZSTD_cLevelToCParams(cctx);
- cctx->requestedParams.cParams.strategy = (ZSTD_strategy)value;
+ ZSTD_cLevelToCCtxParams(params);
+ params->cParams.strategy = (ZSTD_strategy)value;
return 0;
case ZSTD_p_contentSizeFlag :
- DEBUGLOG(5, "set content size flag = %u", (value>0));
/* Content size written in frame header _when known_ (default:1) */
- cctx->requestedParams.fParams.contentSizeFlag = value>0;
+ DEBUGLOG(5, "set content size flag = %u", (value>0));
+ params->fParams.contentSizeFlag = value > 0;
return 0;
case ZSTD_p_checksumFlag :
/* A 32-bits content checksum will be calculated and written at end of frame (default:0) */
- cctx->requestedParams.fParams.checksumFlag = value>0;
+ params->fParams.checksumFlag = value > 0;
return 0;
case ZSTD_p_dictIDFlag : /* When applicable, dictionary's dictID is provided in frame header (default:1) */
DEBUGLOG(5, "set dictIDFlag = %u", (value>0));
- cctx->requestedParams.fParams.noDictIDFlag = (value==0);
+ params->fParams.noDictIDFlag = (value == 0);
return 0;
- /* Dictionary parameters */
- case ZSTD_p_dictMode :
- if (cctx->cdict) return ERROR(stage_wrong); /* must be set before loading */
- /* restrict dictionary mode, to "rawContent" or "fullDict" only */
- ZSTD_STATIC_ASSERT((U32)ZSTD_dm_fullDict > (U32)ZSTD_dm_rawContent);
- if (value > (unsigned)ZSTD_dm_fullDict)
- return ERROR(parameter_outOfBound);
- cctx->dictMode = (ZSTD_dictMode_e)value;
+ case ZSTD_p_forceMaxWindow :
+ params->forceWindow = value > 0;
return 0;
- case ZSTD_p_refDictContent :
- if (cctx->cdict) return ERROR(stage_wrong); /* must be set before loading */
- /* dictionary content will be referenced, instead of copied */
- cctx->dictContentByRef = value>0;
+ case ZSTD_p_nbThreads :
+ if (value == 0) return 0;
+#ifndef ZSTD_MULTITHREAD
+ if (value > 1) return ERROR(parameter_unsupported);
return 0;
+#else
+ return ZSTDMT_initializeCCtxParameters(params, value);
+#endif
- case ZSTD_p_forceMaxWindow : /* Force back-references to remain < windowSize,
- * even when referencing into Dictionary content
- * default : 0 when using a CDict, 1 when using a Prefix */
- cctx->forceWindow = value>0;
- cctx->loadedDictEnd = 0;
- return 0;
+ case ZSTD_p_jobSize :
+#ifndef ZSTD_MULTITHREAD
+ return ERROR(parameter_unsupported);
+#else
+ if (params->nbThreads <= 1) return ERROR(parameter_unsupported);
+ return ZSTDMT_CCtxParam_setMTCtxParameter(params, ZSTDMT_p_sectionSize, value);
+#endif
- case ZSTD_p_nbThreads:
- if (value==0) return 0;
- DEBUGLOG(5, " setting nbThreads : %u", value);
+ case ZSTD_p_overlapSizeLog :
#ifndef ZSTD_MULTITHREAD
- if (value > 1) return ERROR(parameter_unsupported);
+ return ERROR(parameter_unsupported);
+#else
+ if (params->nbThreads <= 1) return ERROR(parameter_unsupported);
+ return ZSTDMT_CCtxParam_setMTCtxParameter(params, ZSTDMT_p_overlapSectionLog, value);
#endif
- if ((value>1) && (cctx->nbThreads != value)) {
- if (cctx->staticSize) /* MT not compatible with static alloc */
- return ERROR(parameter_unsupported);
- ZSTDMT_freeCCtx(cctx->mtctx);
- cctx->nbThreads = 1;
- cctx->mtctx = ZSTDMT_createCCtx_advanced(value, cctx->customMem);
- if (cctx->mtctx == NULL) return ERROR(memory_allocation);
+
+ case ZSTD_p_enableLongDistanceMatching :
+ if (value != 0) {
+ ZSTD_cLevelToCCtxParams(params);
+ params->cParams.windowLog = ZSTD_LDM_DEFAULT_WINDOW_LOG;
}
- cctx->nbThreads = value;
+ return ZSTD_ldm_initializeParameters(&params->ldmParams, value);
+
+ case ZSTD_p_ldmHashLog :
+ if (value == 0) return 0;
+ CLAMPCHECK(value, ZSTD_HASHLOG_MIN, ZSTD_HASHLOG_MAX);
+ params->ldmParams.hashLog = value;
return 0;
- case ZSTD_p_jobSize:
- if (cctx->nbThreads <= 1) return ERROR(parameter_unsupported);
- assert(cctx->mtctx != NULL);
- return ZSTDMT_setMTCtxParameter(cctx->mtctx, ZSTDMT_p_sectionSize, value);
+ case ZSTD_p_ldmMinMatch :
+ if (value == 0) return 0;
+ CLAMPCHECK(value, ZSTD_LDM_MINMATCH_MIN, ZSTD_LDM_MINMATCH_MAX);
+ params->ldmParams.minMatchLength = value;
+ return 0;
- case ZSTD_p_overlapSizeLog:
- DEBUGLOG(5, " setting overlap with nbThreads == %u", cctx->nbThreads);
- if (cctx->nbThreads <= 1) return ERROR(parameter_unsupported);
- assert(cctx->mtctx != NULL);
- return ZSTDMT_setMTCtxParameter(cctx->mtctx, ZSTDMT_p_overlapSectionLog, value);
+ case ZSTD_p_ldmBucketSizeLog :
+ if (value > ZSTD_LDM_BUCKETSIZELOG_MAX) {
+ return ERROR(parameter_outOfBound);
+ }
+ params->ldmParams.bucketSizeLog = value;
+ return 0;
+
+ case ZSTD_p_ldmHashEveryLog :
+ if (value > ZSTD_WINDOWLOG_MAX - ZSTD_HASHLOG_MIN) {
+ return ERROR(parameter_outOfBound);
+ }
+ params->ldmParams.hashEveryLog = value;
+ return 0;
default: return ERROR(parameter_unsupported);
}
}
+/**
+ * This function should be updated whenever ZSTD_CCtx_params is updated.
+ * Parameters are copied manually before the dictionary is loaded.
+ * The multithreading parameters jobSize and overlapSizeLog are set only if
+ * nbThreads > 1.
+ *
+ * Pledged srcSize is treated as unknown.
+ */
+size_t ZSTD_CCtx_setParametersUsingCCtxParams(
+ ZSTD_CCtx* cctx, const ZSTD_CCtx_params* params)
+{
+ if (cctx->streamStage != zcss_init) return ERROR(stage_wrong);
+ if (cctx->cdict) return ERROR(stage_wrong);
+
+ /* Assume the compression and frame parameters are validated */
+ cctx->requestedParams.cParams = params->cParams;
+ cctx->requestedParams.fParams = params->fParams;
+ cctx->requestedParams.compressionLevel = params->compressionLevel;
+
+ /* Set force window explicitly since it sets cctx->loadedDictEnd */
+ CHECK_F( ZSTD_CCtx_setParameter(
+ cctx, ZSTD_p_forceMaxWindow, params->forceWindow) );
+
+ /* Set multithreading parameters explicitly */
+ CHECK_F( ZSTD_CCtx_setParameter(cctx, ZSTD_p_nbThreads, params->nbThreads) );
+ if (params->nbThreads > 1) {
+ CHECK_F( ZSTD_CCtx_setParameter(cctx, ZSTD_p_jobSize, params->jobSize) );
+ CHECK_F( ZSTD_CCtx_setParameter(
+ cctx, ZSTD_p_overlapSizeLog, params->overlapSizeLog) );
+ }
+
+ /* Copy long distance matching parameters */
+ cctx->requestedParams.ldmParams = params->ldmParams;
+
+ /* customMem is used only for create/free params and can be ignored */
+ return 0;
+}
+
ZSTDLIB_API size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long long pledgedSrcSize)
{
- DEBUGLOG(5, " setting pledgedSrcSize to %u", (U32)pledgedSrcSize);
+ DEBUGLOG(4, " setting pledgedSrcSize to %u", (U32)pledgedSrcSize);
if (cctx->streamStage != zcss_init) return ERROR(stage_wrong);
cctx->pledgedSrcSizePlusOne = pledgedSrcSize+1;
return 0;
}
-ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, size_t dictSize)
+size_t ZSTD_CCtx_loadDictionary_advanced(
+ ZSTD_CCtx* cctx, const void* dict, size_t dictSize,
+ ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictMode_e dictMode)
{
if (cctx->streamStage != zcss_init) return ERROR(stage_wrong);
if (cctx->staticSize) return ERROR(memory_allocation); /* no malloc for static CCtx */
- DEBUGLOG(5, "load dictionary of size %u", (U32)dictSize);
+ DEBUGLOG(4, "load dictionary of size %u", (U32)dictSize);
ZSTD_freeCDict(cctx->cdictLocal); /* in case one already exists */
if (dict==NULL || dictSize==0) { /* no dictionary mode */
cctx->cdictLocal = NULL;
cctx->cdict = NULL;
} else {
ZSTD_compressionParameters const cParams =
- cctx->compressionLevel == ZSTD_CLEVEL_CUSTOM ?
- cctx->requestedParams.cParams :
- ZSTD_getCParams(cctx->compressionLevel, 0, dictSize);
+ ZSTD_getCParamsFromCCtxParams(cctx->requestedParams, 0, dictSize);
cctx->cdictLocal = ZSTD_createCDict_advanced(
dict, dictSize,
- cctx->dictContentByRef, cctx->dictMode,
+ dictLoadMethod, dictMode,
cParams, cctx->customMem);
cctx->cdict = cctx->cdictLocal;
if (cctx->cdictLocal == NULL)
@@ -407,21 +542,41 @@ ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, s
return 0;
}
+ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary_byReference(
+ ZSTD_CCtx* cctx, const void* dict, size_t dictSize)
+{
+ return ZSTD_CCtx_loadDictionary_advanced(
+ cctx, dict, dictSize, ZSTD_dlm_byRef, ZSTD_dm_auto);
+}
+
+ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, size_t dictSize)
+{
+ return ZSTD_CCtx_loadDictionary_advanced(
+ cctx, dict, dictSize, ZSTD_dlm_byCopy, ZSTD_dm_auto);
+}
+
+
size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict)
{
if (cctx->streamStage != zcss_init) return ERROR(stage_wrong);
cctx->cdict = cdict;
- cctx->prefix = NULL; /* exclusive */
- cctx->prefixSize = 0;
+ memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict)); /* exclusive */
return 0;
}
size_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize)
{
+ return ZSTD_CCtx_refPrefix_advanced(cctx, prefix, prefixSize, ZSTD_dm_rawContent);
+}
+
+size_t ZSTD_CCtx_refPrefix_advanced(
+ ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize, ZSTD_dictMode_e dictMode)
+{
if (cctx->streamStage != zcss_init) return ERROR(stage_wrong);
cctx->cdict = NULL; /* prefix discards any prior cdict */
- cctx->prefix = prefix;
- cctx->prefixSize = prefixSize;
+ cctx->prefixDict.dict = prefix;
+ cctx->prefixDict.dictSize = prefixSize;
+ cctx->prefixDict.dictMode = dictMode;
return 0;
}
@@ -484,28 +639,37 @@ static U32 ZSTD_cycleLog(U32 hashLog, ZSTD_strategy strat)
/** ZSTD_adjustCParams_internal() :
optimize `cPar` for a given input (`srcSize` and `dictSize`).
- mostly downsizing to reduce memory consumption and initialization.
- Both `srcSize` and `dictSize` are optional (use 0 if unknown),
- but if both are 0, no optimization can be done.
- Note : cPar is considered validated at this stage. Use ZSTD_checkParams() to ensure that. */
+ mostly downsizing to reduce memory consumption and initialization latency.
+ Both `srcSize` and `dictSize` are optional (use 0 if unknown).
+ Note : cPar is considered validated at this stage. Use ZSTD_checkCParams() to ensure that condition. */
ZSTD_compressionParameters ZSTD_adjustCParams_internal(ZSTD_compressionParameters cPar, unsigned long long srcSize, size_t dictSize)
{
+ static const U64 minSrcSize = 513; /* (1<<9) + 1 */
+ static const U64 maxWindowResize = 1ULL << (ZSTD_WINDOWLOG_MAX-1);
assert(ZSTD_checkCParams(cPar)==0);
- if (srcSize+dictSize == 0) return cPar; /* no size information available : no adjustment */
-
- /* resize params, to use less memory when necessary */
- { U32 const minSrcSize = (srcSize==0) ? 500 : 0;
- U64 const rSize = srcSize + dictSize + minSrcSize;
- if (rSize < ((U64)1<<ZSTD_WINDOWLOG_MAX)) {
- U32 const srcLog = MAX(ZSTD_HASHLOG_MIN, ZSTD_highbit32((U32)(rSize)-1) + 1);
- if (cPar.windowLog > srcLog) cPar.windowLog = srcLog;
- } }
+
+ if (dictSize && (srcSize+1<2) /* srcSize unknown */ )
+ srcSize = minSrcSize; /* presumed small when there is a dictionary */
+ else if (srcSize == 0)
+ srcSize = ZSTD_CONTENTSIZE_UNKNOWN; /* 0 == unknown : presumed large */
+
+ /* resize windowLog if input is small enough, to use less memory */
+ if ( (srcSize < maxWindowResize)
+ && (dictSize < maxWindowResize) ) {
+ U32 const tSize = (U32)(srcSize + dictSize);
+ static U32 const hashSizeMin = 1 << ZSTD_HASHLOG_MIN;
+ U32 const srcLog = (tSize < hashSizeMin) ? ZSTD_HASHLOG_MIN :
+ ZSTD_highbit32(tSize-1) + 1;
+ if (cPar.windowLog > srcLog) cPar.windowLog = srcLog;
+ }
if (cPar.hashLog > cPar.windowLog) cPar.hashLog = cPar.windowLog;
{ U32 const cycleLog = ZSTD_cycleLog(cPar.chainLog, cPar.strategy);
- if (cycleLog > cPar.windowLog) cPar.chainLog -= (cycleLog - cPar.windowLog);
+ if (cycleLog > cPar.windowLog)
+ cPar.chainLog -= (cycleLog - cPar.windowLog);
}
- if (cPar.windowLog < ZSTD_WINDOWLOG_ABSOLUTEMIN) cPar.windowLog = ZSTD_WINDOWLOG_ABSOLUTEMIN; /* required for frame header */
+ if (cPar.windowLog < ZSTD_WINDOWLOG_ABSOLUTEMIN)
+ cPar.windowLog = ZSTD_WINDOWLOG_ABSOLUTEMIN; /* required for frame header */
return cPar;
}
@@ -516,56 +680,81 @@ ZSTD_compressionParameters ZSTD_adjustCParams(ZSTD_compressionParameters cPar, u
return ZSTD_adjustCParams_internal(cPar, srcSize, dictSize);
}
-
-size_t ZSTD_estimateCCtxSize_advanced(ZSTD_compressionParameters cParams)
+size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params)
{
- size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << cParams.windowLog);
- U32 const divider = (cParams.searchLength==3) ? 3 : 4;
- size_t const maxNbSeq = blockSize / divider;
- size_t const tokenSpace = blockSize + 11*maxNbSeq;
+ /* Estimate CCtx size is supported for single-threaded compression only. */
+ if (params->nbThreads > 1) { return ERROR(GENERIC); }
+ { ZSTD_compressionParameters const cParams =
+ ZSTD_getCParamsFromCCtxParams(*params, 0, 0);
+ size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << cParams.windowLog);
+ U32 const divider = (cParams.searchLength==3) ? 3 : 4;
+ size_t const maxNbSeq = blockSize / divider;
+ size_t const tokenSpace = blockSize + 11*maxNbSeq;
+ size_t const chainSize =
+ (cParams.strategy == ZSTD_fast) ? 0 : ((size_t)1 << cParams.chainLog);
+ size_t const hSize = ((size_t)1) << cParams.hashLog;
+ U32 const hashLog3 = (cParams.searchLength>3) ?
+ 0 : MIN(ZSTD_HASHLOG3_MAX, cParams.windowLog);
+ size_t const h3Size = ((size_t)1) << hashLog3;
+ size_t const entropySpace = sizeof(ZSTD_entropyCTables_t);
+ size_t const tableSpace = (chainSize + hSize + h3Size) * sizeof(U32);
+
+ size_t const optBudget =
+ ((MaxML+1) + (MaxLL+1) + (MaxOff+1) + (1<<Litbits))*sizeof(U32)
+ + (ZSTD_OPT_NUM+1)*(sizeof(ZSTD_match_t) + sizeof(ZSTD_optimal_t));
+ size_t const optSpace = ((cParams.strategy == ZSTD_btopt) || (cParams.strategy == ZSTD_btultra)) ? optBudget : 0;
- size_t const chainSize = (cParams.strategy == ZSTD_fast) ? 0 : (1 << cParams.chainLog);
- size_t const hSize = ((size_t)1) << cParams.hashLog;
- U32 const hashLog3 = (cParams.searchLength>3) ? 0 : MIN(ZSTD_HASHLOG3_MAX, cParams.windowLog);
- size_t const h3Size = ((size_t)1) << hashLog3;
- size_t const entropySpace = sizeof(ZSTD_entropyCTables_t);
- size_t const tableSpace = (chainSize + hSize + h3Size) * sizeof(U32);
+ size_t const ldmSpace = params->ldmParams.enableLdm ?
+ ZSTD_ldm_getTableSize(params->ldmParams.hashLog,
+ params->ldmParams.bucketSizeLog) : 0;
- size_t const optBudget = ((MaxML+1) + (MaxLL+1) + (MaxOff+1) + (1<<Litbits))*sizeof(U32)
- + (ZSTD_OPT_NUM+1)*(sizeof(ZSTD_match_t) + sizeof(ZSTD_optimal_t));
- size_t const optSpace = ((cParams.strategy == ZSTD_btopt) || (cParams.strategy == ZSTD_btultra)) ? optBudget : 0;
- size_t const neededSpace = entropySpace + tableSpace + tokenSpace + optSpace;
+ size_t const neededSpace = entropySpace + tableSpace + tokenSpace +
+ optSpace + ldmSpace;
- DEBUGLOG(5, "sizeof(ZSTD_CCtx) : %u", (U32)sizeof(ZSTD_CCtx));
- DEBUGLOG(5, "estimate workSpace : %u", (U32)neededSpace);
- return sizeof(ZSTD_CCtx) + neededSpace;
+ DEBUGLOG(5, "sizeof(ZSTD_CCtx) : %u", (U32)sizeof(ZSTD_CCtx));
+ DEBUGLOG(5, "estimate workSpace : %u", (U32)neededSpace);
+ return sizeof(ZSTD_CCtx) + neededSpace;
+ }
+}
+
+size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams)
+{
+ ZSTD_CCtx_params const params = ZSTD_makeCCtxParamsFromCParams(cParams);
+ return ZSTD_estimateCCtxSize_usingCCtxParams(&params);
}
size_t ZSTD_estimateCCtxSize(int compressionLevel)
{
ZSTD_compressionParameters const cParams = ZSTD_getCParams(compressionLevel, 0, 0);
- return ZSTD_estimateCCtxSize_advanced(cParams);
+ return ZSTD_estimateCCtxSize_usingCParams(cParams);
}
-size_t ZSTD_estimateCStreamSize_advanced(ZSTD_compressionParameters cParams)
+size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params)
{
- size_t const CCtxSize = ZSTD_estimateCCtxSize_advanced(cParams);
- size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << cParams.windowLog);
- size_t const inBuffSize = ((size_t)1 << cParams.windowLog) + blockSize;
- size_t const outBuffSize = ZSTD_compressBound(blockSize) + 1;
- size_t const streamingSize = inBuffSize + outBuffSize;
+ if (params->nbThreads > 1) { return ERROR(GENERIC); }
+ { size_t const CCtxSize = ZSTD_estimateCCtxSize_usingCCtxParams(params);
+ size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << params->cParams.windowLog);
+ size_t const inBuffSize = ((size_t)1 << params->cParams.windowLog) + blockSize;
+ size_t const outBuffSize = ZSTD_compressBound(blockSize) + 1;
+ size_t const streamingSize = inBuffSize + outBuffSize;
- return CCtxSize + streamingSize;
+ return CCtxSize + streamingSize;
+ }
+}
+
+size_t ZSTD_estimateCStreamSize_usingCParams(ZSTD_compressionParameters cParams)
+{
+ ZSTD_CCtx_params const params = ZSTD_makeCCtxParamsFromCParams(cParams);
+ return ZSTD_estimateCStreamSize_usingCCtxParams(&params);
}
size_t ZSTD_estimateCStreamSize(int compressionLevel) {
ZSTD_compressionParameters const cParams = ZSTD_getCParams(compressionLevel, 0, 0);
- return ZSTD_estimateCStreamSize_advanced(cParams);
+ return ZSTD_estimateCStreamSize_usingCParams(cParams);
}
-
-static U32 ZSTD_equivalentParams(ZSTD_compressionParameters cParams1,
- ZSTD_compressionParameters cParams2)
+static U32 ZSTD_equivalentCParams(ZSTD_compressionParameters cParams1,
+ ZSTD_compressionParameters cParams2)
{
U32 bslog1 = MIN(cParams1.windowLog, ZSTD_BLOCKSIZELOG_MAX);
U32 bslog2 = MIN(cParams2.windowLog, ZSTD_BLOCKSIZELOG_MAX);
@@ -576,18 +765,39 @@ static U32 ZSTD_equivalentParams(ZSTD_compressionParameters cParams1,
& ((cParams1.searchLength==3) == (cParams2.searchLength==3)); /* hashlog3 space */
}
+/** The parameters are equivalent if ldm is not enabled in both sets or
+ * all the parameters are equivalent. */
+static U32 ZSTD_equivalentLdmParams(ldmParams_t ldmParams1,
+ ldmParams_t ldmParams2)
+{
+ return (!ldmParams1.enableLdm && !ldmParams2.enableLdm) ||
+ (ldmParams1.enableLdm == ldmParams2.enableLdm &&
+ ldmParams1.hashLog == ldmParams2.hashLog &&
+ ldmParams1.bucketSizeLog == ldmParams2.bucketSizeLog &&
+ ldmParams1.minMatchLength == ldmParams2.minMatchLength &&
+ ldmParams1.hashEveryLog == ldmParams2.hashEveryLog);
+}
+
+/** Equivalence for resetCCtx purposes */
+static U32 ZSTD_equivalentParams(ZSTD_CCtx_params params1,
+ ZSTD_CCtx_params params2)
+{
+ return ZSTD_equivalentCParams(params1.cParams, params2.cParams) &&
+ ZSTD_equivalentLdmParams(params1.ldmParams, params2.ldmParams);
+}
+
/*! ZSTD_continueCCtx() :
* reuse CCtx without reset (note : requires no dictionary) */
-static size_t ZSTD_continueCCtx(ZSTD_CCtx* cctx, ZSTD_parameters params, U64 pledgedSrcSize)
+static size_t ZSTD_continueCCtx(ZSTD_CCtx* cctx, ZSTD_CCtx_params params, U64 pledgedSrcSize)
{
U32 const end = (U32)(cctx->nextSrc - cctx->base);
- DEBUGLOG(5, "continue mode");
+ DEBUGLOG(4, "continue mode");
cctx->appliedParams = params;
cctx->pledgedSrcSizePlusOne = pledgedSrcSize+1;
cctx->consumedSrcSize = 0;
if (pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN)
cctx->appliedParams.fParams.contentSizeFlag = 0;
- DEBUGLOG(5, "pledged content size : %u ; flag : %u",
+ DEBUGLOG(4, "pledged content size : %u ; flag : %u",
(U32)pledgedSrcSize, cctx->appliedParams.fParams.contentSizeFlag);
cctx->lowLimit = end;
cctx->dictLimit = end;
@@ -607,15 +817,19 @@ typedef enum { ZSTDb_not_buffered, ZSTDb_buffered } ZSTD_buffered_policy_e;
/*! ZSTD_resetCCtx_internal() :
note : `params` are assumed fully validated at this stage */
static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
- ZSTD_parameters params, U64 pledgedSrcSize,
+ ZSTD_CCtx_params params, U64 pledgedSrcSize,
ZSTD_compResetPolicy_e const crp,
ZSTD_buffered_policy_e const zbuff)
{
+ DEBUGLOG(4, "ZSTD_resetCCtx_internal");
assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
+ DEBUGLOG(4, "pledgedSrcSize: %u", (U32)pledgedSrcSize);
if (crp == ZSTDcrp_continue) {
- if (ZSTD_equivalentParams(params.cParams, zc->appliedParams.cParams)) {
- DEBUGLOG(5, "ZSTD_equivalentParams()==1");
+ if (ZSTD_equivalentParams(params, zc->appliedParams)) {
+ DEBUGLOG(4, "ZSTD_equivalentParams()==1");
+ assert(!(params.ldmParams.enableLdm &&
+ params.ldmParams.hashEveryLog == ZSTD_LDM_HASHEVERYLOG_NOTSET));
zc->entropy->hufCTable_repeatMode = HUF_repeat_none;
zc->entropy->offcode_repeatMode = FSE_repeat_none;
zc->entropy->matchlength_repeatMode = FSE_repeat_none;
@@ -623,12 +837,21 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
return ZSTD_continueCCtx(zc, params, pledgedSrcSize);
} }
+ if (params.ldmParams.enableLdm) {
+ /* Adjust long distance matching parameters */
+ ZSTD_ldm_adjustParameters(&params.ldmParams, params.cParams.windowLog);
+ assert(params.ldmParams.hashLog >= params.ldmParams.bucketSizeLog);
+ assert(params.ldmParams.hashEveryLog < 32);
+ zc->ldmState.hashPower =
+ ZSTD_ldm_getHashPower(params.ldmParams.minMatchLength);
+ }
+
{ size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << params.cParams.windowLog);
U32 const divider = (params.cParams.searchLength==3) ? 3 : 4;
size_t const maxNbSeq = blockSize / divider;
size_t const tokenSpace = blockSize + 11*maxNbSeq;
size_t const chainSize = (params.cParams.strategy == ZSTD_fast) ?
- 0 : (1 << params.cParams.chainLog);
+ 0 : ((size_t)1 << params.cParams.chainLog);
size_t const hSize = ((size_t)1) << params.cParams.hashLog;
U32 const hashLog3 = (params.cParams.searchLength>3) ?
0 : MIN(ZSTD_HASHLOG3_MAX, params.cParams.windowLog);
@@ -646,10 +869,13 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
|| (params.cParams.strategy == ZSTD_btultra)) ?
optPotentialSpace : 0;
size_t const bufferSpace = buffInSize + buffOutSize;
- size_t const neededSpace = entropySpace + optSpace + tableSpace
- + tokenSpace + bufferSpace;
+ size_t const ldmSpace = params.ldmParams.enableLdm
+ ? ZSTD_ldm_getTableSize(params.ldmParams.hashLog, params.ldmParams.bucketSizeLog)
+ : 0;
+ size_t const neededSpace = entropySpace + optSpace + ldmSpace +
+ tableSpace + tokenSpace + bufferSpace;
- if (zc->workSpaceSize < neededSpace) { /* too small : resize /*/
+ if (zc->workSpaceSize < neededSpace) { /* too small : resize */
DEBUGLOG(5, "Need to update workSpaceSize from %uK to %uK \n",
(unsigned)zc->workSpaceSize>>10,
(unsigned)neededSpace>>10);
@@ -714,6 +940,16 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
ptr = zc->optState.priceTable + ZSTD_OPT_NUM+1;
}
+ /* ldm hash table */
+ /* initialize bucketOffsets table later for pointer alignment */
+ if (params.ldmParams.enableLdm) {
+ size_t const ldmHSize = ((size_t)1) << params.ldmParams.hashLog;
+ memset(ptr, 0, ldmHSize * sizeof(ldmEntry_t));
+ assert(((size_t)ptr & 3) == 0); /* ensure ptr is properly aligned */
+ zc->ldmState.hashTable = (ldmEntry_t*)ptr;
+ ptr = zc->ldmState.hashTable + ldmHSize;
+ }
+
/* table Space */
if (crp!=ZSTDcrp_noMemset) memset(ptr, 0, tableSpace); /* reset tables only */
assert(((size_t)ptr & 3) == 0); /* ensure ptr is properly aligned */
@@ -731,6 +967,16 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
zc->seqStore.litStart = zc->seqStore.ofCode + maxNbSeq;
ptr = zc->seqStore.litStart + blockSize;
+ /* ldm bucketOffsets table */
+ if (params.ldmParams.enableLdm) {
+ size_t const ldmBucketSize =
+ ((size_t)1) << (params.ldmParams.hashLog -
+ params.ldmParams.bucketSizeLog);
+ memset(ptr, 0, ldmBucketSize);
+ zc->ldmState.bucketOffsets = (BYTE*)ptr;
+ ptr = zc->ldmState.bucketOffsets + ldmBucketSize;
+ }
+
/* buffers */
zc->inBuffSize = buffInSize;
zc->inBuff = (char*)ptr;
@@ -753,6 +999,8 @@ void ZSTD_invalidateRepCodes(ZSTD_CCtx* cctx) {
/*! ZSTD_copyCCtx_internal() :
* Duplicate an existing context `srcCCtx` into another one `dstCCtx`.
+ * The "context", in this case, refers to the hash and chain tables, entropy
+ * tables, and dictionary offsets.
* Only works during stage ZSTDcs_init (i.e. after creation, but before first call to ZSTD_compressContinue()).
* pledgedSrcSize=0 means "empty" if fParams.contentSizeFlag=1
* @return : 0, or an error code */
@@ -766,14 +1014,16 @@ static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx,
if (srcCCtx->stage!=ZSTDcs_init) return ERROR(stage_wrong);
memcpy(&dstCCtx->customMem, &srcCCtx->customMem, sizeof(ZSTD_customMem));
- { ZSTD_parameters params = srcCCtx->appliedParams;
+ { ZSTD_CCtx_params params = dstCCtx->requestedParams;
+ /* Copy only compression parameters related to tables. */
+ params.cParams = srcCCtx->appliedParams.cParams;
params.fParams = fParams;
ZSTD_resetCCtx_internal(dstCCtx, params, pledgedSrcSize,
ZSTDcrp_noMemset, zbuff);
}
/* copy tables */
- { size_t const chainSize = (srcCCtx->appliedParams.cParams.strategy == ZSTD_fast) ? 0 : (1 << srcCCtx->appliedParams.cParams.chainLog);
+ { size_t const chainSize = (srcCCtx->appliedParams.cParams.strategy == ZSTD_fast) ? 0 : ((size_t)1 << srcCCtx->appliedParams.cParams.chainLog);
size_t const hSize = (size_t)1 << srcCCtx->appliedParams.cParams.hashLog;
size_t const h3Size = (size_t)1 << srcCCtx->hashLog3;
size_t const tableSpace = (chainSize + hSize + h3Size) * sizeof(U32);
@@ -826,18 +1076,36 @@ static void ZSTD_reduceTable (U32* const table, U32 const size, U32 const reduce
}
}
+/*! ZSTD_ldm_reduceTable() :
+ * reduce table indexes by `reducerValue` */
+static void ZSTD_ldm_reduceTable(ldmEntry_t* const table, U32 const size,
+ U32 const reducerValue)
+{
+ U32 u;
+ for (u = 0; u < size; u++) {
+ if (table[u].offset < reducerValue) table[u].offset = 0;
+ else table[u].offset -= reducerValue;
+ }
+}
+
/*! ZSTD_reduceIndex() :
* rescale all indexes to avoid future overflow (indexes are U32) */
static void ZSTD_reduceIndex (ZSTD_CCtx* zc, const U32 reducerValue)
{
- { U32 const hSize = 1 << zc->appliedParams.cParams.hashLog;
+ { U32 const hSize = (U32)1 << zc->appliedParams.cParams.hashLog;
ZSTD_reduceTable(zc->hashTable, hSize, reducerValue); }
- { U32 const chainSize = (zc->appliedParams.cParams.strategy == ZSTD_fast) ? 0 : (1 << zc->appliedParams.cParams.chainLog);
+ { U32 const chainSize = (zc->appliedParams.cParams.strategy == ZSTD_fast) ? 0 : ((U32)1 << zc->appliedParams.cParams.chainLog);
ZSTD_reduceTable(zc->chainTable, chainSize, reducerValue); }
- { U32 const h3Size = (zc->hashLog3) ? 1 << zc->hashLog3 : 0;
+ { U32 const h3Size = (zc->hashLog3) ? (U32)1 << zc->hashLog3 : 0;
ZSTD_reduceTable(zc->hashTable3, h3Size, reducerValue); }
+
+ { if (zc->appliedParams.ldmParams.enableLdm) {
+ U32 const ldmHSize = (U32)1 << zc->appliedParams.ldmParams.hashLog;
+ ZSTD_ldm_reduceTable(zc->ldmState.hashTable, ldmHSize, reducerValue);
+ }
+ }
}
@@ -976,24 +1244,6 @@ static size_t ZSTD_compressLiterals (ZSTD_entropyCTables_t * entropy,
return lhSize+cLitSize;
}
-static const BYTE LL_Code[64] = { 0, 1, 2, 3, 4, 5, 6, 7,
- 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 16, 17, 17, 18, 18, 19, 19,
- 20, 20, 20, 20, 21, 21, 21, 21,
- 22, 22, 22, 22, 22, 22, 22, 22,
- 23, 23, 23, 23, 23, 23, 23, 23,
- 24, 24, 24, 24, 24, 24, 24, 24,
- 24, 24, 24, 24, 24, 24, 24, 24 };
-
-static const BYTE ML_Code[128] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
- 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 36, 36, 37, 37, 37, 37,
- 38, 38, 38, 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 39, 39, 39,
- 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
- 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
- 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
- 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42 };
-
void ZSTD_seqToCodes(const seqStore_t* seqStorePtr)
{
@@ -1018,20 +1268,30 @@ void ZSTD_seqToCodes(const seqStore_t* seqStorePtr)
mlCodeTable[seqStorePtr->longLengthPos] = MaxML;
}
-MEM_STATIC symbolEncodingType_e ZSTD_selectEncodingType(FSE_repeat* repeatMode,
- size_t const mostFrequent, size_t nbSeq, U32 defaultNormLog)
+typedef enum {
+ ZSTD_defaultDisallowed = 0,
+ ZSTD_defaultAllowed = 1
+} ZSTD_defaultPolicy_e;
+
+MEM_STATIC symbolEncodingType_e ZSTD_selectEncodingType(
+ FSE_repeat* repeatMode, size_t const mostFrequent, size_t nbSeq,
+ U32 defaultNormLog, ZSTD_defaultPolicy_e const isDefaultAllowed)
{
#define MIN_SEQ_FOR_DYNAMIC_FSE 64
#define MAX_SEQ_FOR_STATIC_FSE 1000
-
- if ((mostFrequent == nbSeq) && (nbSeq > 2)) {
+ ZSTD_STATIC_ASSERT(ZSTD_defaultDisallowed == 0 && ZSTD_defaultAllowed != 0);
+ if ((mostFrequent == nbSeq) && (!isDefaultAllowed || nbSeq > 2)) {
+ /* Prefer set_basic over set_rle when there are 2 or less symbols,
+ * since RLE uses 1 byte, but set_basic uses 5-6 bits per symbol.
+ * If basic encoding isn't possible, always choose RLE.
+ */
*repeatMode = FSE_repeat_check;
return set_rle;
}
- if ((*repeatMode == FSE_repeat_valid) && (nbSeq < MAX_SEQ_FOR_STATIC_FSE)) {
+ if (isDefaultAllowed && (*repeatMode == FSE_repeat_valid) && (nbSeq < MAX_SEQ_FOR_STATIC_FSE)) {
return set_repeat;
}
- if ((nbSeq < MIN_SEQ_FOR_DYNAMIC_FSE) || (mostFrequent < (nbSeq >> (defaultNormLog-1)))) {
+ if (isDefaultAllowed && ((nbSeq < MIN_SEQ_FOR_DYNAMIC_FSE) || (mostFrequent < (nbSeq >> (defaultNormLog-1))))) {
*repeatMode = FSE_repeat_valid;
return set_basic;
}
@@ -1067,6 +1327,7 @@ MEM_STATIC size_t ZSTD_buildCTable(void* dst, size_t dstCapacity,
count[codeTable[nbSeq-1]]--;
nbSeq_1--;
}
+ assert(nbSeq_1 > 1);
CHECK_F(FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max));
{ size_t const NCountSize = FSE_writeNCount(op, oend - op, norm, max, tableLog); /* overflow protected */
if (FSE_isError(NCountSize)) return NCountSize;
@@ -1131,7 +1392,7 @@ MEM_STATIC size_t ZSTD_encodeSequences(void* dst, size_t dstCapacity,
BIT_addBits(&blockStream, sequences[n].litLength, llBits);
if (MEM_32bits() && ((llBits+mlBits)>24)) BIT_flushBits(&blockStream);
BIT_addBits(&blockStream, sequences[n].matchLength, mlBits);
- if (MEM_32bits()) BIT_flushBits(&blockStream); /* (7)*/
+ if (MEM_32bits() || (ofBits+mlBits+llBits > 56)) BIT_flushBits(&blockStream);
if (longOffsets) {
int const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN-1);
if (extraBits) {
@@ -1204,7 +1465,7 @@ MEM_STATIC size_t ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
/* CTable for Literal Lengths */
{ U32 max = MaxLL;
size_t const mostFrequent = FSE_countFast_wksp(count, &max, llCodeTable, nbSeq, entropy->workspace);
- LLtype = ZSTD_selectEncodingType(&entropy->litlength_repeatMode, mostFrequent, nbSeq, LL_defaultNormLog);
+ LLtype = ZSTD_selectEncodingType(&entropy->litlength_repeatMode, mostFrequent, nbSeq, LL_defaultNormLog, ZSTD_defaultAllowed);
{ size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_LitLength, LLFSELog, (symbolEncodingType_e)LLtype,
count, max, llCodeTable, nbSeq, LL_defaultNorm, LL_defaultNormLog, MaxLL,
entropy->workspace, sizeof(entropy->workspace));
@@ -1214,9 +1475,11 @@ MEM_STATIC size_t ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
/* CTable for Offsets */
{ U32 max = MaxOff;
size_t const mostFrequent = FSE_countFast_wksp(count, &max, ofCodeTable, nbSeq, entropy->workspace);
- Offtype = ZSTD_selectEncodingType(&entropy->offcode_repeatMode, mostFrequent, nbSeq, OF_defaultNormLog);
+ /* We can only use the basic table if max <= DefaultMaxOff, otherwise the offsets are too large */
+ ZSTD_defaultPolicy_e const defaultPolicy = max <= DefaultMaxOff ? ZSTD_defaultAllowed : ZSTD_defaultDisallowed;
+ Offtype = ZSTD_selectEncodingType(&entropy->offcode_repeatMode, mostFrequent, nbSeq, OF_defaultNormLog, defaultPolicy);
{ size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_OffsetBits, OffFSELog, (symbolEncodingType_e)Offtype,
- count, max, ofCodeTable, nbSeq, OF_defaultNorm, OF_defaultNormLog, MaxOff,
+ count, max, ofCodeTable, nbSeq, OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff,
entropy->workspace, sizeof(entropy->workspace));
if (ZSTD_isError(countSize)) return countSize;
op += countSize;
@@ -1224,7 +1487,7 @@ MEM_STATIC size_t ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
/* CTable for MatchLengths */
{ U32 max = MaxML;
size_t const mostFrequent = FSE_countFast_wksp(count, &max, mlCodeTable, nbSeq, entropy->workspace);
- MLtype = ZSTD_selectEncodingType(&entropy->matchlength_repeatMode, mostFrequent, nbSeq, ML_defaultNormLog);
+ MLtype = ZSTD_selectEncodingType(&entropy->matchlength_repeatMode, mostFrequent, nbSeq, ML_defaultNormLog, ZSTD_defaultAllowed);
{ size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_MatchLength, MLFSELog, (symbolEncodingType_e)MLtype,
count, max, mlCodeTable, nbSeq, ML_defaultNorm, ML_defaultNormLog, MaxML,
entropy->workspace, sizeof(entropy->workspace));
@@ -1279,1528 +1542,11 @@ MEM_STATIC size_t ZSTD_compressSequences(seqStore_t* seqStorePtr,
return cSize;
}
-
-/*! ZSTD_storeSeq() :
- Store a sequence (literal length, literals, offset code and match length code) into seqStore_t.
- `offsetCode` : distance to match, or 0 == repCode.
- `matchCode` : matchLength - MINMATCH
-*/
-MEM_STATIC void ZSTD_storeSeq(seqStore_t* seqStorePtr, size_t litLength, const void* literals, U32 offsetCode, size_t matchCode)
-{
-#if defined(ZSTD_DEBUG) && (ZSTD_DEBUG >= 6)
- static const BYTE* g_start = NULL;
- U32 const pos = (U32)((const BYTE*)literals - g_start);
- if (g_start==NULL) g_start = (const BYTE*)literals;
- if ((pos > 0) && (pos < 1000000000))
- DEBUGLOG(6, "Cpos %6u :%5u literals & match %3u bytes at distance %6u",
- pos, (U32)litLength, (U32)matchCode+MINMATCH, (U32)offsetCode);
-#endif
- /* copy Literals */
- assert(seqStorePtr->lit + litLength <= seqStorePtr->litStart + 128 KB);
- ZSTD_wildcopy(seqStorePtr->lit, literals, litLength);
- seqStorePtr->lit += litLength;
-
- /* literal Length */
- if (litLength>0xFFFF) {
- seqStorePtr->longLengthID = 1;
- seqStorePtr->longLengthPos = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart);
- }
- seqStorePtr->sequences[0].litLength = (U16)litLength;
-
- /* match offset */
- seqStorePtr->sequences[0].offset = offsetCode + 1;
-
- /* match Length */
- if (matchCode>0xFFFF) {
- seqStorePtr->longLengthID = 2;
- seqStorePtr->longLengthPos = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart);
- }
- seqStorePtr->sequences[0].matchLength = (U16)matchCode;
-
- seqStorePtr->sequences++;
-}
-
-
-/*-*************************************
-* Match length counter
-***************************************/
-static unsigned ZSTD_NbCommonBytes (register size_t val)
-{
- if (MEM_isLittleEndian()) {
- if (MEM_64bits()) {
-# if defined(_MSC_VER) && defined(_WIN64)
- unsigned long r = 0;
- _BitScanForward64( &r, (U64)val );
- return (unsigned)(r>>3);
-# elif defined(__GNUC__) && (__GNUC__ >= 3)
- return (__builtin_ctzll((U64)val) >> 3);
-# else
- static const int DeBruijnBytePos[64] = { 0, 0, 0, 0, 0, 1, 1, 2,
- 0, 3, 1, 3, 1, 4, 2, 7,
- 0, 2, 3, 6, 1, 5, 3, 5,
- 1, 3, 4, 4, 2, 5, 6, 7,
- 7, 0, 1, 2, 3, 3, 4, 6,
- 2, 6, 5, 5, 3, 4, 5, 6,
- 7, 1, 2, 4, 6, 4, 4, 5,
- 7, 2, 6, 5, 7, 6, 7, 7 };
- return DeBruijnBytePos[((U64)((val & -(long long)val) * 0x0218A392CDABBD3FULL)) >> 58];
-# endif
- } else { /* 32 bits */
-# if defined(_MSC_VER)
- unsigned long r=0;
- _BitScanForward( &r, (U32)val );
- return (unsigned)(r>>3);
-# elif defined(__GNUC__) && (__GNUC__ >= 3)
- return (__builtin_ctz((U32)val) >> 3);
-# else
- static const int DeBruijnBytePos[32] = { 0, 0, 3, 0, 3, 1, 3, 0,
- 3, 2, 2, 1, 3, 2, 0, 1,
- 3, 3, 1, 2, 2, 2, 2, 0,
- 3, 1, 2, 0, 1, 0, 1, 1 };
- return DeBruijnBytePos[((U32)((val & -(S32)val) * 0x077CB531U)) >> 27];
-# endif
- }
- } else { /* Big Endian CPU */
- if (MEM_64bits()) {
-# if defined(_MSC_VER) && defined(_WIN64)
- unsigned long r = 0;
- _BitScanReverse64( &r, val );
- return (unsigned)(r>>3);
-# elif defined(__GNUC__) && (__GNUC__ >= 3)
- return (__builtin_clzll(val) >> 3);
-# else
- unsigned r;
- const unsigned n32 = sizeof(size_t)*4; /* calculate this way due to compiler complaining in 32-bits mode */
- if (!(val>>n32)) { r=4; } else { r=0; val>>=n32; }
- if (!(val>>16)) { r+=2; val>>=8; } else { val>>=24; }
- r += (!val);
- return r;
-# endif
- } else { /* 32 bits */
-# if defined(_MSC_VER)
- unsigned long r = 0;
- _BitScanReverse( &r, (unsigned long)val );
- return (unsigned)(r>>3);
-# elif defined(__GNUC__) && (__GNUC__ >= 3)
- return (__builtin_clz((U32)val) >> 3);
-# else
- unsigned r;
- if (!(val>>16)) { r=2; val>>=8; } else { r=0; val>>=24; }
- r += (!val);
- return r;
-# endif
- } }
-}
-
-
-static size_t ZSTD_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* const pInLimit)
-{
- const BYTE* const pStart = pIn;
- const BYTE* const pInLoopLimit = pInLimit - (sizeof(size_t)-1);
-
- while (pIn < pInLoopLimit) {
- size_t const diff = MEM_readST(pMatch) ^ MEM_readST(pIn);
- if (!diff) { pIn+=sizeof(size_t); pMatch+=sizeof(size_t); continue; }
- pIn += ZSTD_NbCommonBytes(diff);
- return (size_t)(pIn - pStart);
- }
- if (MEM_64bits()) if ((pIn<(pInLimit-3)) && (MEM_read32(pMatch) == MEM_read32(pIn))) { pIn+=4; pMatch+=4; }
- if ((pIn<(pInLimit-1)) && (MEM_read16(pMatch) == MEM_read16(pIn))) { pIn+=2; pMatch+=2; }
- if ((pIn<pInLimit) && (*pMatch == *pIn)) pIn++;
- return (size_t)(pIn - pStart);
-}
-
-/** ZSTD_count_2segments() :
-* can count match length with `ip` & `match` in 2 different segments.
-* convention : on reaching mEnd, match count continue starting from iStart
-*/
-static size_t ZSTD_count_2segments(const BYTE* ip, const BYTE* match, const BYTE* iEnd, const BYTE* mEnd, const BYTE* iStart)
-{
- const BYTE* const vEnd = MIN( ip + (mEnd - match), iEnd);
- size_t const matchLength = ZSTD_count(ip, match, vEnd);
- if (match + matchLength != mEnd) return matchLength;
- return matchLength + ZSTD_count(ip+matchLength, iStart, iEnd);
-}
-
-
-/*-*************************************
-* Hashes
-***************************************/
-static const U32 prime3bytes = 506832829U;
-static U32 ZSTD_hash3(U32 u, U32 h) { return ((u << (32-24)) * prime3bytes) >> (32-h) ; }
-MEM_STATIC size_t ZSTD_hash3Ptr(const void* ptr, U32 h) { return ZSTD_hash3(MEM_readLE32(ptr), h); } /* only in zstd_opt.h */
-
-static const U32 prime4bytes = 2654435761U;
-static U32 ZSTD_hash4(U32 u, U32 h) { return (u * prime4bytes) >> (32-h) ; }
-static size_t ZSTD_hash4Ptr(const void* ptr, U32 h) { return ZSTD_hash4(MEM_read32(ptr), h); }
-
-static const U64 prime5bytes = 889523592379ULL;
-static size_t ZSTD_hash5(U64 u, U32 h) { return (size_t)(((u << (64-40)) * prime5bytes) >> (64-h)) ; }
-static size_t ZSTD_hash5Ptr(const void* p, U32 h) { return ZSTD_hash5(MEM_readLE64(p), h); }
-
-static const U64 prime6bytes = 227718039650203ULL;
-static size_t ZSTD_hash6(U64 u, U32 h) { return (size_t)(((u << (64-48)) * prime6bytes) >> (64-h)) ; }
-static size_t ZSTD_hash6Ptr(const void* p, U32 h) { return ZSTD_hash6(MEM_readLE64(p), h); }
-
-static const U64 prime7bytes = 58295818150454627ULL;
-static size_t ZSTD_hash7(U64 u, U32 h) { return (size_t)(((u << (64-56)) * prime7bytes) >> (64-h)) ; }
-static size_t ZSTD_hash7Ptr(const void* p, U32 h) { return ZSTD_hash7(MEM_readLE64(p), h); }
-
-static const U64 prime8bytes = 0xCF1BBCDCB7A56463ULL;
-static size_t ZSTD_hash8(U64 u, U32 h) { return (size_t)(((u) * prime8bytes) >> (64-h)) ; }
-static size_t ZSTD_hash8Ptr(const void* p, U32 h) { return ZSTD_hash8(MEM_readLE64(p), h); }
-
-static size_t ZSTD_hashPtr(const void* p, U32 hBits, U32 mls)
-{
- switch(mls)
- {
- default:
- case 4: return ZSTD_hash4Ptr(p, hBits);
- case 5: return ZSTD_hash5Ptr(p, hBits);
- case 6: return ZSTD_hash6Ptr(p, hBits);
- case 7: return ZSTD_hash7Ptr(p, hBits);
- case 8: return ZSTD_hash8Ptr(p, hBits);
- }
-}
-
-
-/*-*************************************
-* Fast Scan
-***************************************/
-static void ZSTD_fillHashTable (ZSTD_CCtx* zc, const void* end, const U32 mls)
-{
- U32* const hashTable = zc->hashTable;
- U32 const hBits = zc->appliedParams.cParams.hashLog;
- const BYTE* const base = zc->base;
- const BYTE* ip = base + zc->nextToUpdate;
- const BYTE* const iend = ((const BYTE*)end) - HASH_READ_SIZE;
- const size_t fastHashFillStep = 3;
-
- while(ip <= iend) {
- hashTable[ZSTD_hashPtr(ip, hBits, mls)] = (U32)(ip - base);
- ip += fastHashFillStep;
- }
-}
-
-
-FORCE_INLINE_TEMPLATE
-void ZSTD_compressBlock_fast_generic(ZSTD_CCtx* cctx,
- const void* src, size_t srcSize,
- const U32 mls)
-{
- U32* const hashTable = cctx->hashTable;
- U32 const hBits = cctx->appliedParams.cParams.hashLog;
- seqStore_t* seqStorePtr = &(cctx->seqStore);
- const BYTE* const base = cctx->base;
- const BYTE* const istart = (const BYTE*)src;
- const BYTE* ip = istart;
- const BYTE* anchor = istart;
- const U32 lowestIndex = cctx->dictLimit;
- const BYTE* const lowest = base + lowestIndex;
- const BYTE* const iend = istart + srcSize;
- const BYTE* const ilimit = iend - HASH_READ_SIZE;
- U32 offset_1=seqStorePtr->rep[0], offset_2=seqStorePtr->rep[1];
- U32 offsetSaved = 0;
-
- /* init */
- ip += (ip==lowest);
- { U32 const maxRep = (U32)(ip-lowest);
- if (offset_2 > maxRep) offsetSaved = offset_2, offset_2 = 0;
- if (offset_1 > maxRep) offsetSaved = offset_1, offset_1 = 0;
- }
-
- /* Main Search Loop */
- while (ip < ilimit) { /* < instead of <=, because repcode check at (ip+1) */
- size_t mLength;
- size_t const h = ZSTD_hashPtr(ip, hBits, mls);
- U32 const current = (U32)(ip-base);
- U32 const matchIndex = hashTable[h];
- const BYTE* match = base + matchIndex;
- hashTable[h] = current; /* update hash table */
-
- if ((offset_1 > 0) & (MEM_read32(ip+1-offset_1) == MEM_read32(ip+1))) {
- mLength = ZSTD_count(ip+1+4, ip+1+4-offset_1, iend) + 4;
- ip++;
- ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, 0, mLength-MINMATCH);
- } else {
- U32 offset;
- if ( (matchIndex <= lowestIndex) || (MEM_read32(match) != MEM_read32(ip)) ) {
- ip += ((ip-anchor) >> g_searchStrength) + 1;
- continue;
- }
- mLength = ZSTD_count(ip+4, match+4, iend) + 4;
- offset = (U32)(ip-match);
- while (((ip>anchor) & (match>lowest)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */
- offset_2 = offset_1;
- offset_1 = offset;
-
- ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
- }
-
- /* match found */
- ip += mLength;
- anchor = ip;
-
- if (ip <= ilimit) {
- /* Fill Table */
- hashTable[ZSTD_hashPtr(base+current+2, hBits, mls)] = current+2; /* here because current+2 could be > iend-8 */
- hashTable[ZSTD_hashPtr(ip-2, hBits, mls)] = (U32)(ip-2-base);
- /* check immediate repcode */
- while ( (ip <= ilimit)
- && ( (offset_2>0)
- & (MEM_read32(ip) == MEM_read32(ip - offset_2)) )) {
- /* store sequence */
- size_t const rLength = ZSTD_count(ip+4, ip+4-offset_2, iend) + 4;
- { U32 const tmpOff = offset_2; offset_2 = offset_1; offset_1 = tmpOff; } /* swap offset_2 <=> offset_1 */
- hashTable[ZSTD_hashPtr(ip, hBits, mls)] = (U32)(ip-base);
- ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, rLength-MINMATCH);
- ip += rLength;
- anchor = ip;
- continue; /* faster when present ... (?) */
- } } }
-
- /* save reps for next block */
- seqStorePtr->repToConfirm[0] = offset_1 ? offset_1 : offsetSaved;
- seqStorePtr->repToConfirm[1] = offset_2 ? offset_2 : offsetSaved;
-
- /* Last Literals */
- { size_t const lastLLSize = iend - anchor;
- memcpy(seqStorePtr->lit, anchor, lastLLSize);
- seqStorePtr->lit += lastLLSize;
- }
-}
-
-
-static void ZSTD_compressBlock_fast(ZSTD_CCtx* ctx,
- const void* src, size_t srcSize)
-{
- const U32 mls = ctx->appliedParams.cParams.searchLength;
- switch(mls)
- {
- default: /* includes case 3 */
- case 4 :
- ZSTD_compressBlock_fast_generic(ctx, src, srcSize, 4); return;
- case 5 :
- ZSTD_compressBlock_fast_generic(ctx, src, srcSize, 5); return;
- case 6 :
- ZSTD_compressBlock_fast_generic(ctx, src, srcSize, 6); return;
- case 7 :
- ZSTD_compressBlock_fast_generic(ctx, src, srcSize, 7); return;
- }
-}
-
-
-static void ZSTD_compressBlock_fast_extDict_generic(ZSTD_CCtx* ctx,
- const void* src, size_t srcSize,
- const U32 mls)
-{
- U32* hashTable = ctx->hashTable;
- const U32 hBits = ctx->appliedParams.cParams.hashLog;
- seqStore_t* seqStorePtr = &(ctx->seqStore);
- const BYTE* const base = ctx->base;
- const BYTE* const dictBase = ctx->dictBase;
- const BYTE* const istart = (const BYTE*)src;
- const BYTE* ip = istart;
- const BYTE* anchor = istart;
- const U32 lowestIndex = ctx->lowLimit;
- const BYTE* const dictStart = dictBase + lowestIndex;
- const U32 dictLimit = ctx->dictLimit;
- const BYTE* const lowPrefixPtr = base + dictLimit;
- const BYTE* const dictEnd = dictBase + dictLimit;
- const BYTE* const iend = istart + srcSize;
- const BYTE* const ilimit = iend - 8;
- U32 offset_1=seqStorePtr->rep[0], offset_2=seqStorePtr->rep[1];
-
- /* Search Loop */
- while (ip < ilimit) { /* < instead of <=, because (ip+1) */
- const size_t h = ZSTD_hashPtr(ip, hBits, mls);
- const U32 matchIndex = hashTable[h];
- const BYTE* matchBase = matchIndex < dictLimit ? dictBase : base;
- const BYTE* match = matchBase + matchIndex;
- const U32 current = (U32)(ip-base);
- const U32 repIndex = current + 1 - offset_1; /* offset_1 expected <= current +1 */
- const BYTE* repBase = repIndex < dictLimit ? dictBase : base;
- const BYTE* repMatch = repBase + repIndex;
- size_t mLength;
- hashTable[h] = current; /* update hash table */
-
- if ( (((U32)((dictLimit-1) - repIndex) >= 3) /* intentional underflow */ & (repIndex > lowestIndex))
- && (MEM_read32(repMatch) == MEM_read32(ip+1)) ) {
- const BYTE* repMatchEnd = repIndex < dictLimit ? dictEnd : iend;
- mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, lowPrefixPtr) + 4;
- ip++;
- ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, 0, mLength-MINMATCH);
- } else {
- if ( (matchIndex < lowestIndex) ||
- (MEM_read32(match) != MEM_read32(ip)) ) {
- ip += ((ip-anchor) >> g_searchStrength) + 1;
- continue;
- }
- { const BYTE* matchEnd = matchIndex < dictLimit ? dictEnd : iend;
- const BYTE* lowMatchPtr = matchIndex < dictLimit ? dictStart : lowPrefixPtr;
- U32 offset;
- mLength = ZSTD_count_2segments(ip+4, match+4, iend, matchEnd, lowPrefixPtr) + 4;
- while (((ip>anchor) & (match>lowMatchPtr)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */
- offset = current - matchIndex;
- offset_2 = offset_1;
- offset_1 = offset;
- ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
- } }
-
- /* found a match : store it */
- ip += mLength;
- anchor = ip;
-
- if (ip <= ilimit) {
- /* Fill Table */
- hashTable[ZSTD_hashPtr(base+current+2, hBits, mls)] = current+2;
- hashTable[ZSTD_hashPtr(ip-2, hBits, mls)] = (U32)(ip-2-base);
- /* check immediate repcode */
- while (ip <= ilimit) {
- U32 const current2 = (U32)(ip-base);
- U32 const repIndex2 = current2 - offset_2;
- const BYTE* repMatch2 = repIndex2 < dictLimit ? dictBase + repIndex2 : base + repIndex2;
- if ( (((U32)((dictLimit-1) - repIndex2) >= 3) & (repIndex2 > lowestIndex)) /* intentional overflow */
- && (MEM_read32(repMatch2) == MEM_read32(ip)) ) {
- const BYTE* const repEnd2 = repIndex2 < dictLimit ? dictEnd : iend;
- size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, lowPrefixPtr) + 4;
- U32 tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; /* swap offset_2 <=> offset_1 */
- ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, repLength2-MINMATCH);
- hashTable[ZSTD_hashPtr(ip, hBits, mls)] = current2;
- ip += repLength2;
- anchor = ip;
- continue;
- }
- break;
- } } }
-
- /* save reps for next block */
- seqStorePtr->repToConfirm[0] = offset_1; seqStorePtr->repToConfirm[1] = offset_2;
-
- /* Last Literals */
- { size_t const lastLLSize = iend - anchor;
- memcpy(seqStorePtr->lit, anchor, lastLLSize);
- seqStorePtr->lit += lastLLSize;
- }
-}
-
-
-static void ZSTD_compressBlock_fast_extDict(ZSTD_CCtx* ctx,
- const void* src, size_t srcSize)
-{
- U32 const mls = ctx->appliedParams.cParams.searchLength;
- switch(mls)
- {
- default: /* includes case 3 */
- case 4 :
- ZSTD_compressBlock_fast_extDict_generic(ctx, src, srcSize, 4); return;
- case 5 :
- ZSTD_compressBlock_fast_extDict_generic(ctx, src, srcSize, 5); return;
- case 6 :
- ZSTD_compressBlock_fast_extDict_generic(ctx, src, srcSize, 6); return;
- case 7 :
- ZSTD_compressBlock_fast_extDict_generic(ctx, src, srcSize, 7); return;
- }
-}
-
-
-/*-*************************************
-* Double Fast
-***************************************/
-static void ZSTD_fillDoubleHashTable (ZSTD_CCtx* cctx, const void* end, const U32 mls)
-{
- U32* const hashLarge = cctx->hashTable;
- U32 const hBitsL = cctx->appliedParams.cParams.hashLog;
- U32* const hashSmall = cctx->chainTable;
- U32 const hBitsS = cctx->appliedParams.cParams.chainLog;
- const BYTE* const base = cctx->base;
- const BYTE* ip = base + cctx->nextToUpdate;
- const BYTE* const iend = ((const BYTE*)end) - HASH_READ_SIZE;
- const size_t fastHashFillStep = 3;
-
- while(ip <= iend) {
- hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = (U32)(ip - base);
- hashLarge[ZSTD_hashPtr(ip, hBitsL, 8)] = (U32)(ip - base);
- ip += fastHashFillStep;
- }
-}
-
-
-FORCE_INLINE_TEMPLATE
-void ZSTD_compressBlock_doubleFast_generic(ZSTD_CCtx* cctx,
- const void* src, size_t srcSize,
- const U32 mls)
-{
- U32* const hashLong = cctx->hashTable;
- const U32 hBitsL = cctx->appliedParams.cParams.hashLog;
- U32* const hashSmall = cctx->chainTable;
- const U32 hBitsS = cctx->appliedParams.cParams.chainLog;
- seqStore_t* seqStorePtr = &(cctx->seqStore);
- const BYTE* const base = cctx->base;
- const BYTE* const istart = (const BYTE*)src;
- const BYTE* ip = istart;
- const BYTE* anchor = istart;
- const U32 lowestIndex = cctx->dictLimit;
- const BYTE* const lowest = base + lowestIndex;
- const BYTE* const iend = istart + srcSize;
- const BYTE* const ilimit = iend - HASH_READ_SIZE;
- U32 offset_1=seqStorePtr->rep[0], offset_2=seqStorePtr->rep[1];
- U32 offsetSaved = 0;
-
- /* init */
- ip += (ip==lowest);
- { U32 const maxRep = (U32)(ip-lowest);
- if (offset_2 > maxRep) offsetSaved = offset_2, offset_2 = 0;
- if (offset_1 > maxRep) offsetSaved = offset_1, offset_1 = 0;
- }
-
- /* Main Search Loop */
- while (ip < ilimit) { /* < instead of <=, because repcode check at (ip+1) */
- size_t mLength;
- size_t const h2 = ZSTD_hashPtr(ip, hBitsL, 8);
- size_t const h = ZSTD_hashPtr(ip, hBitsS, mls);
- U32 const current = (U32)(ip-base);
- U32 const matchIndexL = hashLong[h2];
- U32 const matchIndexS = hashSmall[h];
- const BYTE* matchLong = base + matchIndexL;
- const BYTE* match = base + matchIndexS;
- hashLong[h2] = hashSmall[h] = current; /* update hash tables */
-
- assert(offset_1 <= current); /* supposed guaranteed by construction */
- if ((offset_1 > 0) & (MEM_read32(ip+1-offset_1) == MEM_read32(ip+1))) {
- /* favor repcode */
- mLength = ZSTD_count(ip+1+4, ip+1+4-offset_1, iend) + 4;
- ip++;
- ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, 0, mLength-MINMATCH);
- } else {
- U32 offset;
- if ( (matchIndexL > lowestIndex) && (MEM_read64(matchLong) == MEM_read64(ip)) ) {
- mLength = ZSTD_count(ip+8, matchLong+8, iend) + 8;
- offset = (U32)(ip-matchLong);
- while (((ip>anchor) & (matchLong>lowest)) && (ip[-1] == matchLong[-1])) { ip--; matchLong--; mLength++; } /* catch up */
- } else if ( (matchIndexS > lowestIndex) && (MEM_read32(match) == MEM_read32(ip)) ) {
- size_t const hl3 = ZSTD_hashPtr(ip+1, hBitsL, 8);
- U32 const matchIndexL3 = hashLong[hl3];
- const BYTE* matchL3 = base + matchIndexL3;
- hashLong[hl3] = current + 1;
- if ( (matchIndexL3 > lowestIndex) && (MEM_read64(matchL3) == MEM_read64(ip+1)) ) {
- mLength = ZSTD_count(ip+9, matchL3+8, iend) + 8;
- ip++;
- offset = (U32)(ip-matchL3);
- while (((ip>anchor) & (matchL3>lowest)) && (ip[-1] == matchL3[-1])) { ip--; matchL3--; mLength++; } /* catch up */
- } else {
- mLength = ZSTD_count(ip+4, match+4, iend) + 4;
- offset = (U32)(ip-match);
- while (((ip>anchor) & (match>lowest)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */
- }
- } else {
- ip += ((ip-anchor) >> g_searchStrength) + 1;
- continue;
- }
-
- offset_2 = offset_1;
- offset_1 = offset;
-
- ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
- }
-
- /* match found */
- ip += mLength;
- anchor = ip;
-
- if (ip <= ilimit) {
- /* Fill Table */
- hashLong[ZSTD_hashPtr(base+current+2, hBitsL, 8)] =
- hashSmall[ZSTD_hashPtr(base+current+2, hBitsS, mls)] = current+2; /* here because current+2 could be > iend-8 */
- hashLong[ZSTD_hashPtr(ip-2, hBitsL, 8)] =
- hashSmall[ZSTD_hashPtr(ip-2, hBitsS, mls)] = (U32)(ip-2-base);
-
- /* check immediate repcode */
- while ( (ip <= ilimit)
- && ( (offset_2>0)
- & (MEM_read32(ip) == MEM_read32(ip - offset_2)) )) {
- /* store sequence */
- size_t const rLength = ZSTD_count(ip+4, ip+4-offset_2, iend) + 4;
- { U32 const tmpOff = offset_2; offset_2 = offset_1; offset_1 = tmpOff; } /* swap offset_2 <=> offset_1 */
- hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = (U32)(ip-base);
- hashLong[ZSTD_hashPtr(ip, hBitsL, 8)] = (U32)(ip-base);
- ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, rLength-MINMATCH);
- ip += rLength;
- anchor = ip;
- continue; /* faster when present ... (?) */
- } } }
-
- /* save reps for next block */
- seqStorePtr->repToConfirm[0] = offset_1 ? offset_1 : offsetSaved;
- seqStorePtr->repToConfirm[1] = offset_2 ? offset_2 : offsetSaved;
-
- /* Last Literals */
- { size_t const lastLLSize = iend - anchor;
- memcpy(seqStorePtr->lit, anchor, lastLLSize);
- seqStorePtr->lit += lastLLSize;
- }
-}
-
-
-static void ZSTD_compressBlock_doubleFast(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
-{
- const U32 mls = ctx->appliedParams.cParams.searchLength;
- switch(mls)
- {
- default: /* includes case 3 */
- case 4 :
- ZSTD_compressBlock_doubleFast_generic(ctx, src, srcSize, 4); return;
- case 5 :
- ZSTD_compressBlock_doubleFast_generic(ctx, src, srcSize, 5); return;
- case 6 :
- ZSTD_compressBlock_doubleFast_generic(ctx, src, srcSize, 6); return;
- case 7 :
- ZSTD_compressBlock_doubleFast_generic(ctx, src, srcSize, 7); return;
- }
-}
-
-
-static void ZSTD_compressBlock_doubleFast_extDict_generic(ZSTD_CCtx* ctx,
- const void* src, size_t srcSize,
- const U32 mls)
-{
- U32* const hashLong = ctx->hashTable;
- U32 const hBitsL = ctx->appliedParams.cParams.hashLog;
- U32* const hashSmall = ctx->chainTable;
- U32 const hBitsS = ctx->appliedParams.cParams.chainLog;
- seqStore_t* seqStorePtr = &(ctx->seqStore);
- const BYTE* const base = ctx->base;
- const BYTE* const dictBase = ctx->dictBase;
- const BYTE* const istart = (const BYTE*)src;
- const BYTE* ip = istart;
- const BYTE* anchor = istart;
- const U32 lowestIndex = ctx->lowLimit;
- const BYTE* const dictStart = dictBase + lowestIndex;
- const U32 dictLimit = ctx->dictLimit;
- const BYTE* const lowPrefixPtr = base + dictLimit;
- const BYTE* const dictEnd = dictBase + dictLimit;
- const BYTE* const iend = istart + srcSize;
- const BYTE* const ilimit = iend - 8;
- U32 offset_1=seqStorePtr->rep[0], offset_2=seqStorePtr->rep[1];
-
- /* Search Loop */
- while (ip < ilimit) { /* < instead of <=, because (ip+1) */
- const size_t hSmall = ZSTD_hashPtr(ip, hBitsS, mls);
- const U32 matchIndex = hashSmall[hSmall];
- const BYTE* matchBase = matchIndex < dictLimit ? dictBase : base;
- const BYTE* match = matchBase + matchIndex;
-
- const size_t hLong = ZSTD_hashPtr(ip, hBitsL, 8);
- const U32 matchLongIndex = hashLong[hLong];
- const BYTE* matchLongBase = matchLongIndex < dictLimit ? dictBase : base;
- const BYTE* matchLong = matchLongBase + matchLongIndex;
-
- const U32 current = (U32)(ip-base);
- const U32 repIndex = current + 1 - offset_1; /* offset_1 expected <= current +1 */
- const BYTE* repBase = repIndex < dictLimit ? dictBase : base;
- const BYTE* repMatch = repBase + repIndex;
- size_t mLength;
- hashSmall[hSmall] = hashLong[hLong] = current; /* update hash table */
-
- if ( (((U32)((dictLimit-1) - repIndex) >= 3) /* intentional underflow */ & (repIndex > lowestIndex))
- && (MEM_read32(repMatch) == MEM_read32(ip+1)) ) {
- const BYTE* repMatchEnd = repIndex < dictLimit ? dictEnd : iend;
- mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, lowPrefixPtr) + 4;
- ip++;
- ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, 0, mLength-MINMATCH);
- } else {
- if ((matchLongIndex > lowestIndex) && (MEM_read64(matchLong) == MEM_read64(ip))) {
- const BYTE* matchEnd = matchLongIndex < dictLimit ? dictEnd : iend;
- const BYTE* lowMatchPtr = matchLongIndex < dictLimit ? dictStart : lowPrefixPtr;
- U32 offset;
- mLength = ZSTD_count_2segments(ip+8, matchLong+8, iend, matchEnd, lowPrefixPtr) + 8;
- offset = current - matchLongIndex;
- while (((ip>anchor) & (matchLong>lowMatchPtr)) && (ip[-1] == matchLong[-1])) { ip--; matchLong--; mLength++; } /* catch up */
- offset_2 = offset_1;
- offset_1 = offset;
- ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
-
- } else if ((matchIndex > lowestIndex) && (MEM_read32(match) == MEM_read32(ip))) {
- size_t const h3 = ZSTD_hashPtr(ip+1, hBitsL, 8);
- U32 const matchIndex3 = hashLong[h3];
- const BYTE* const match3Base = matchIndex3 < dictLimit ? dictBase : base;
- const BYTE* match3 = match3Base + matchIndex3;
- U32 offset;
- hashLong[h3] = current + 1;
- if ( (matchIndex3 > lowestIndex) && (MEM_read64(match3) == MEM_read64(ip+1)) ) {
- const BYTE* matchEnd = matchIndex3 < dictLimit ? dictEnd : iend;
- const BYTE* lowMatchPtr = matchIndex3 < dictLimit ? dictStart : lowPrefixPtr;
- mLength = ZSTD_count_2segments(ip+9, match3+8, iend, matchEnd, lowPrefixPtr) + 8;
- ip++;
- offset = current+1 - matchIndex3;
- while (((ip>anchor) & (match3>lowMatchPtr)) && (ip[-1] == match3[-1])) { ip--; match3--; mLength++; } /* catch up */
- } else {
- const BYTE* matchEnd = matchIndex < dictLimit ? dictEnd : iend;
- const BYTE* lowMatchPtr = matchIndex < dictLimit ? dictStart : lowPrefixPtr;
- mLength = ZSTD_count_2segments(ip+4, match+4, iend, matchEnd, lowPrefixPtr) + 4;
- offset = current - matchIndex;
- while (((ip>anchor) & (match>lowMatchPtr)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */
- }
- offset_2 = offset_1;
- offset_1 = offset;
- ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
-
- } else {
- ip += ((ip-anchor) >> g_searchStrength) + 1;
- continue;
- } }
-
- /* found a match : store it */
- ip += mLength;
- anchor = ip;
-
- if (ip <= ilimit) {
- /* Fill Table */
- hashSmall[ZSTD_hashPtr(base+current+2, hBitsS, mls)] = current+2;
- hashLong[ZSTD_hashPtr(base+current+2, hBitsL, 8)] = current+2;
- hashSmall[ZSTD_hashPtr(ip-2, hBitsS, mls)] = (U32)(ip-2-base);
- hashLong[ZSTD_hashPtr(ip-2, hBitsL, 8)] = (U32)(ip-2-base);
- /* check immediate repcode */
- while (ip <= ilimit) {
- U32 const current2 = (U32)(ip-base);
- U32 const repIndex2 = current2 - offset_2;
- const BYTE* repMatch2 = repIndex2 < dictLimit ? dictBase + repIndex2 : base + repIndex2;
- if ( (((U32)((dictLimit-1) - repIndex2) >= 3) & (repIndex2 > lowestIndex)) /* intentional overflow */
- && (MEM_read32(repMatch2) == MEM_read32(ip)) ) {
- const BYTE* const repEnd2 = repIndex2 < dictLimit ? dictEnd : iend;
- size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, lowPrefixPtr) + 4;
- U32 tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; /* swap offset_2 <=> offset_1 */
- ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, repLength2-MINMATCH);
- hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = current2;
- hashLong[ZSTD_hashPtr(ip, hBitsL, 8)] = current2;
- ip += repLength2;
- anchor = ip;
- continue;
- }
- break;
- } } }
-
- /* save reps for next block */
- seqStorePtr->repToConfirm[0] = offset_1; seqStorePtr->repToConfirm[1] = offset_2;
-
- /* Last Literals */
- { size_t const lastLLSize = iend - anchor;
- memcpy(seqStorePtr->lit, anchor, lastLLSize);
- seqStorePtr->lit += lastLLSize;
- }
-}
-
-
-static void ZSTD_compressBlock_doubleFast_extDict(ZSTD_CCtx* ctx,
- const void* src, size_t srcSize)
-{
- U32 const mls = ctx->appliedParams.cParams.searchLength;
- switch(mls)
- {
- default: /* includes case 3 */
- case 4 :
- ZSTD_compressBlock_doubleFast_extDict_generic(ctx, src, srcSize, 4); return;
- case 5 :
- ZSTD_compressBlock_doubleFast_extDict_generic(ctx, src, srcSize, 5); return;
- case 6 :
- ZSTD_compressBlock_doubleFast_extDict_generic(ctx, src, srcSize, 6); return;
- case 7 :
- ZSTD_compressBlock_doubleFast_extDict_generic(ctx, src, srcSize, 7); return;
- }
-}
-
-
-/*-*************************************
-* Binary Tree search
-***************************************/
-/** ZSTD_insertBt1() : add one or multiple positions to tree.
-* ip : assumed <= iend-8 .
-* @return : nb of positions added */
-static U32 ZSTD_insertBt1(ZSTD_CCtx* zc, const BYTE* const ip, const U32 mls, const BYTE* const iend, U32 nbCompares,
- U32 extDict)
-{
- U32* const hashTable = zc->hashTable;
- U32 const hashLog = zc->appliedParams.cParams.hashLog;
- size_t const h = ZSTD_hashPtr(ip, hashLog, mls);
- U32* const bt = zc->chainTable;
- U32 const btLog = zc->appliedParams.cParams.chainLog - 1;
- U32 const btMask = (1 << btLog) - 1;
- U32 matchIndex = hashTable[h];
- size_t commonLengthSmaller=0, commonLengthLarger=0;
- const BYTE* const base = zc->base;
- const BYTE* const dictBase = zc->dictBase;
- const U32 dictLimit = zc->dictLimit;
- const BYTE* const dictEnd = dictBase + dictLimit;
- const BYTE* const prefixStart = base + dictLimit;
- const BYTE* match;
- const U32 current = (U32)(ip-base);
- const U32 btLow = btMask >= current ? 0 : current - btMask;
- U32* smallerPtr = bt + 2*(current&btMask);
- U32* largerPtr = smallerPtr + 1;
- U32 dummy32; /* to be nullified at the end */
- U32 const windowLow = zc->lowLimit;
- U32 matchEndIdx = current+8;
- size_t bestLength = 8;
-#ifdef ZSTD_C_PREDICT
- U32 predictedSmall = *(bt + 2*((current-1)&btMask) + 0);
- U32 predictedLarge = *(bt + 2*((current-1)&btMask) + 1);
- predictedSmall += (predictedSmall>0);
- predictedLarge += (predictedLarge>0);
-#endif /* ZSTD_C_PREDICT */
-
- hashTable[h] = current; /* Update Hash Table */
-
- while (nbCompares-- && (matchIndex > windowLow)) {
- U32* const nextPtr = bt + 2*(matchIndex & btMask);
- size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
-
-#ifdef ZSTD_C_PREDICT /* note : can create issues when hlog small <= 11 */
- const U32* predictPtr = bt + 2*((matchIndex-1) & btMask); /* written this way, as bt is a roll buffer */
- if (matchIndex == predictedSmall) {
- /* no need to check length, result known */
- *smallerPtr = matchIndex;
- if (matchIndex <= btLow) { smallerPtr=&dummy32; break; } /* beyond tree size, stop the search */
- smallerPtr = nextPtr+1; /* new "smaller" => larger of match */
- matchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */
- predictedSmall = predictPtr[1] + (predictPtr[1]>0);
- continue;
- }
- if (matchIndex == predictedLarge) {
- *largerPtr = matchIndex;
- if (matchIndex <= btLow) { largerPtr=&dummy32; break; } /* beyond tree size, stop the search */
- largerPtr = nextPtr;
- matchIndex = nextPtr[0];
- predictedLarge = predictPtr[0] + (predictPtr[0]>0);
- continue;
- }
-#endif
- if ((!extDict) || (matchIndex+matchLength >= dictLimit)) {
- match = base + matchIndex;
- if (match[matchLength] == ip[matchLength])
- matchLength += ZSTD_count(ip+matchLength+1, match+matchLength+1, iend) +1;
- } else {
- match = dictBase + matchIndex;
- matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iend, dictEnd, prefixStart);
- if (matchIndex+matchLength >= dictLimit)
- match = base + matchIndex; /* to prepare for next usage of match[matchLength] */
- }
-
- if (matchLength > bestLength) {
- bestLength = matchLength;
- if (matchLength > matchEndIdx - matchIndex)
- matchEndIdx = matchIndex + (U32)matchLength;
- }
-
- if (ip+matchLength == iend) /* equal : no way to know if inf or sup */
- break; /* drop , to guarantee consistency ; miss a bit of compression, but other solutions can corrupt the tree */
-
- if (match[matchLength] < ip[matchLength]) { /* necessarily within correct buffer */
- /* match is smaller than current */
- *smallerPtr = matchIndex; /* update smaller idx */
- commonLengthSmaller = matchLength; /* all smaller will now have at least this guaranteed common length */
- if (matchIndex <= btLow) { smallerPtr=&dummy32; break; } /* beyond tree size, stop the search */
- smallerPtr = nextPtr+1; /* new "smaller" => larger of match */
- matchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */
- } else {
- /* match is larger than current */
- *largerPtr = matchIndex;
- commonLengthLarger = matchLength;
- if (matchIndex <= btLow) { largerPtr=&dummy32; break; } /* beyond tree size, stop the search */
- largerPtr = nextPtr;
- matchIndex = nextPtr[0];
- } }
-
- *smallerPtr = *largerPtr = 0;
- if (bestLength > 384) return MIN(192, (U32)(bestLength - 384)); /* speed optimization */
- if (matchEndIdx > current + 8) return matchEndIdx - current - 8;
- return 1;
-}
-
-
-static size_t ZSTD_insertBtAndFindBestMatch (
- ZSTD_CCtx* zc,
- const BYTE* const ip, const BYTE* const iend,
- size_t* offsetPtr,
- U32 nbCompares, const U32 mls,
- U32 extDict)
-{
- U32* const hashTable = zc->hashTable;
- U32 const hashLog = zc->appliedParams.cParams.hashLog;
- size_t const h = ZSTD_hashPtr(ip, hashLog, mls);
- U32* const bt = zc->chainTable;
- U32 const btLog = zc->appliedParams.cParams.chainLog - 1;
- U32 const btMask = (1 << btLog) - 1;
- U32 matchIndex = hashTable[h];
- size_t commonLengthSmaller=0, commonLengthLarger=0;
- const BYTE* const base = zc->base;
- const BYTE* const dictBase = zc->dictBase;
- const U32 dictLimit = zc->dictLimit;
- const BYTE* const dictEnd = dictBase + dictLimit;
- const BYTE* const prefixStart = base + dictLimit;
- const U32 current = (U32)(ip-base);
- const U32 btLow = btMask >= current ? 0 : current - btMask;
- const U32 windowLow = zc->lowLimit;
- U32* smallerPtr = bt + 2*(current&btMask);
- U32* largerPtr = bt + 2*(current&btMask) + 1;
- U32 matchEndIdx = current+8;
- U32 dummy32; /* to be nullified at the end */
- size_t bestLength = 0;
-
- hashTable[h] = current; /* Update Hash Table */
-
- while (nbCompares-- && (matchIndex > windowLow)) {
- U32* const nextPtr = bt + 2*(matchIndex & btMask);
- size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
- const BYTE* match;
-
- if ((!extDict) || (matchIndex+matchLength >= dictLimit)) {
- match = base + matchIndex;
- if (match[matchLength] == ip[matchLength])
- matchLength += ZSTD_count(ip+matchLength+1, match+matchLength+1, iend) +1;
- } else {
- match = dictBase + matchIndex;
- matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iend, dictEnd, prefixStart);
- if (matchIndex+matchLength >= dictLimit)
- match = base + matchIndex; /* to prepare for next usage of match[matchLength] */
- }
-
- if (matchLength > bestLength) {
- if (matchLength > matchEndIdx - matchIndex)
- matchEndIdx = matchIndex + (U32)matchLength;
- if ( (4*(int)(matchLength-bestLength)) > (int)(ZSTD_highbit32(current-matchIndex+1) - ZSTD_highbit32((U32)offsetPtr[0]+1)) )
- bestLength = matchLength, *offsetPtr = ZSTD_REP_MOVE + current - matchIndex;
- if (ip+matchLength == iend) /* equal : no way to know if inf or sup */
- break; /* drop, to guarantee consistency (miss a little bit of compression) */
- }
-
- if (match[matchLength] < ip[matchLength]) {
- /* match is smaller than current */
- *smallerPtr = matchIndex; /* update smaller idx */
- commonLengthSmaller = matchLength; /* all smaller will now have at least this guaranteed common length */
- if (matchIndex <= btLow) { smallerPtr=&dummy32; break; } /* beyond tree size, stop the search */
- smallerPtr = nextPtr+1; /* new "smaller" => larger of match */
- matchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */
- } else {
- /* match is larger than current */
- *largerPtr = matchIndex;
- commonLengthLarger = matchLength;
- if (matchIndex <= btLow) { largerPtr=&dummy32; break; } /* beyond tree size, stop the search */
- largerPtr = nextPtr;
- matchIndex = nextPtr[0];
- } }
-
- *smallerPtr = *largerPtr = 0;
-
- zc->nextToUpdate = (matchEndIdx > current + 8) ? matchEndIdx - 8 : current+1;
- return bestLength;
-}
-
-
-static void ZSTD_updateTree(ZSTD_CCtx* zc, const BYTE* const ip, const BYTE* const iend, const U32 nbCompares, const U32 mls)
-{
- const BYTE* const base = zc->base;
- const U32 target = (U32)(ip - base);
- U32 idx = zc->nextToUpdate;
-
- while(idx < target)
- idx += ZSTD_insertBt1(zc, base+idx, mls, iend, nbCompares, 0);
-}
-
-/** ZSTD_BtFindBestMatch() : Tree updater, providing best match */
-static size_t ZSTD_BtFindBestMatch (
- ZSTD_CCtx* zc,
- const BYTE* const ip, const BYTE* const iLimit,
- size_t* offsetPtr,
- const U32 maxNbAttempts, const U32 mls)
-{
- if (ip < zc->base + zc->nextToUpdate) return 0; /* skipped area */
- ZSTD_updateTree(zc, ip, iLimit, maxNbAttempts, mls);
- return ZSTD_insertBtAndFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, mls, 0);
-}
-
-
-static size_t ZSTD_BtFindBestMatch_selectMLS (
- ZSTD_CCtx* zc, /* Index table will be updated */
- const BYTE* ip, const BYTE* const iLimit,
- size_t* offsetPtr,
- const U32 maxNbAttempts, const U32 matchLengthSearch)
-{
- switch(matchLengthSearch)
- {
- default : /* includes case 3 */
- case 4 : return ZSTD_BtFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, 4);
- case 5 : return ZSTD_BtFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, 5);
- case 7 :
- case 6 : return ZSTD_BtFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, 6);
- }
-}
-
-
-static void ZSTD_updateTree_extDict(ZSTD_CCtx* zc, const BYTE* const ip, const BYTE* const iend, const U32 nbCompares, const U32 mls)
-{
- const BYTE* const base = zc->base;
- const U32 target = (U32)(ip - base);
- U32 idx = zc->nextToUpdate;
-
- while (idx < target) idx += ZSTD_insertBt1(zc, base+idx, mls, iend, nbCompares, 1);
-}
-
-
-/** Tree updater, providing best match */
-static size_t ZSTD_BtFindBestMatch_extDict (
- ZSTD_CCtx* zc,
- const BYTE* const ip, const BYTE* const iLimit,
- size_t* offsetPtr,
- const U32 maxNbAttempts, const U32 mls)
-{
- if (ip < zc->base + zc->nextToUpdate) return 0; /* skipped area */
- ZSTD_updateTree_extDict(zc, ip, iLimit, maxNbAttempts, mls);
- return ZSTD_insertBtAndFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, mls, 1);
-}
-
-
-static size_t ZSTD_BtFindBestMatch_selectMLS_extDict (
- ZSTD_CCtx* zc, /* Index table will be updated */
- const BYTE* ip, const BYTE* const iLimit,
- size_t* offsetPtr,
- const U32 maxNbAttempts, const U32 matchLengthSearch)
-{
- switch(matchLengthSearch)
- {
- default : /* includes case 3 */
- case 4 : return ZSTD_BtFindBestMatch_extDict(zc, ip, iLimit, offsetPtr, maxNbAttempts, 4);
- case 5 : return ZSTD_BtFindBestMatch_extDict(zc, ip, iLimit, offsetPtr, maxNbAttempts, 5);
- case 7 :
- case 6 : return ZSTD_BtFindBestMatch_extDict(zc, ip, iLimit, offsetPtr, maxNbAttempts, 6);
- }
-}
-
-
-
-/* *********************************
-* Hash Chain
-***********************************/
-#define NEXT_IN_CHAIN(d, mask) chainTable[(d) & mask]
-
-/* Update chains up to ip (excluded)
- Assumption : always within prefix (i.e. not within extDict) */
-FORCE_INLINE_TEMPLATE
-U32 ZSTD_insertAndFindFirstIndex (ZSTD_CCtx* zc, const BYTE* ip, U32 mls)
-{
- U32* const hashTable = zc->hashTable;
- const U32 hashLog = zc->appliedParams.cParams.hashLog;
- U32* const chainTable = zc->chainTable;
- const U32 chainMask = (1 << zc->appliedParams.cParams.chainLog) - 1;
- const BYTE* const base = zc->base;
- const U32 target = (U32)(ip - base);
- U32 idx = zc->nextToUpdate;
-
- while(idx < target) { /* catch up */
- size_t const h = ZSTD_hashPtr(base+idx, hashLog, mls);
- NEXT_IN_CHAIN(idx, chainMask) = hashTable[h];
- hashTable[h] = idx;
- idx++;
- }
-
- zc->nextToUpdate = target;
- return hashTable[ZSTD_hashPtr(ip, hashLog, mls)];
-}
-
-
-/* inlining is important to hardwire a hot branch (template emulation) */
-FORCE_INLINE_TEMPLATE
-size_t ZSTD_HcFindBestMatch_generic (
- ZSTD_CCtx* zc, /* Index table will be updated */
- const BYTE* const ip, const BYTE* const iLimit,
- size_t* offsetPtr,
- const U32 maxNbAttempts, const U32 mls, const U32 extDict)
-{
- U32* const chainTable = zc->chainTable;
- const U32 chainSize = (1 << zc->appliedParams.cParams.chainLog);
- const U32 chainMask = chainSize-1;
- const BYTE* const base = zc->base;
- const BYTE* const dictBase = zc->dictBase;
- const U32 dictLimit = zc->dictLimit;
- const BYTE* const prefixStart = base + dictLimit;
- const BYTE* const dictEnd = dictBase + dictLimit;
- const U32 lowLimit = zc->lowLimit;
- const U32 current = (U32)(ip-base);
- const U32 minChain = current > chainSize ? current - chainSize : 0;
- int nbAttempts=maxNbAttempts;
- size_t ml=4-1;
-
- /* HC4 match finder */
- U32 matchIndex = ZSTD_insertAndFindFirstIndex (zc, ip, mls);
-
- for ( ; (matchIndex>lowLimit) & (nbAttempts>0) ; nbAttempts--) {
- const BYTE* match;
- size_t currentMl=0;
- if ((!extDict) || matchIndex >= dictLimit) {
- match = base + matchIndex;
- if (match[ml] == ip[ml]) /* potentially better */
- currentMl = ZSTD_count(ip, match, iLimit);
- } else {
- match = dictBase + matchIndex;
- if (MEM_read32(match) == MEM_read32(ip)) /* assumption : matchIndex <= dictLimit-4 (by table construction) */
- currentMl = ZSTD_count_2segments(ip+4, match+4, iLimit, dictEnd, prefixStart) + 4;
- }
-
- /* save best solution */
- if (currentMl > ml) {
- ml = currentMl;
- *offsetPtr = current - matchIndex + ZSTD_REP_MOVE;
- if (ip+currentMl == iLimit) break; /* best possible, avoids read overflow on next attempt */
- }
-
- if (matchIndex <= minChain) break;
- matchIndex = NEXT_IN_CHAIN(matchIndex, chainMask);
- }
-
- return ml;
-}
-
-
-FORCE_INLINE_TEMPLATE size_t ZSTD_HcFindBestMatch_selectMLS (
- ZSTD_CCtx* zc,
- const BYTE* ip, const BYTE* const iLimit,
- size_t* offsetPtr,
- const U32 maxNbAttempts, const U32 matchLengthSearch)
-{
- switch(matchLengthSearch)
- {
- default : /* includes case 3 */
- case 4 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 4, 0);
- case 5 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 5, 0);
- case 7 :
- case 6 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 6, 0);
- }
-}
-
-
-FORCE_INLINE_TEMPLATE size_t ZSTD_HcFindBestMatch_extDict_selectMLS (
- ZSTD_CCtx* zc,
- const BYTE* ip, const BYTE* const iLimit,
- size_t* offsetPtr,
- const U32 maxNbAttempts, const U32 matchLengthSearch)
-{
- switch(matchLengthSearch)
- {
- default : /* includes case 3 */
- case 4 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 4, 1);
- case 5 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 5, 1);
- case 7 :
- case 6 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 6, 1);
- }
-}
-
-
-/* *******************************
-* Common parser - lazy strategy
-*********************************/
-FORCE_INLINE_TEMPLATE
-void ZSTD_compressBlock_lazy_generic(ZSTD_CCtx* ctx,
- const void* src, size_t srcSize,
- const U32 searchMethod, const U32 depth)
-{
- seqStore_t* seqStorePtr = &(ctx->seqStore);
- const BYTE* const istart = (const BYTE*)src;
- const BYTE* ip = istart;
- const BYTE* anchor = istart;
- const BYTE* const iend = istart + srcSize;
- const BYTE* const ilimit = iend - 8;
- const BYTE* const base = ctx->base + ctx->dictLimit;
-
- U32 const maxSearches = 1 << ctx->appliedParams.cParams.searchLog;
- U32 const mls = ctx->appliedParams.cParams.searchLength;
-
- typedef size_t (*searchMax_f)(ZSTD_CCtx* zc, const BYTE* ip, const BYTE* iLimit,
- size_t* offsetPtr,
- U32 maxNbAttempts, U32 matchLengthSearch);
- searchMax_f const searchMax = searchMethod ? ZSTD_BtFindBestMatch_selectMLS : ZSTD_HcFindBestMatch_selectMLS;
- U32 offset_1 = seqStorePtr->rep[0], offset_2 = seqStorePtr->rep[1], savedOffset=0;
-
- /* init */
- ip += (ip==base);
- ctx->nextToUpdate3 = ctx->nextToUpdate;
- { U32 const maxRep = (U32)(ip-base);
- if (offset_2 > maxRep) savedOffset = offset_2, offset_2 = 0;
- if (offset_1 > maxRep) savedOffset = offset_1, offset_1 = 0;
- }
-
- /* Match Loop */
- while (ip < ilimit) {
- size_t matchLength=0;
- size_t offset=0;
- const BYTE* start=ip+1;
-
- /* check repCode */
- if ((offset_1>0) & (MEM_read32(ip+1) == MEM_read32(ip+1 - offset_1))) {
- /* repcode : we take it */
- matchLength = ZSTD_count(ip+1+4, ip+1+4-offset_1, iend) + 4;
- if (depth==0) goto _storeSequence;
- }
-
- /* first search (depth 0) */
- { size_t offsetFound = 99999999;
- size_t const ml2 = searchMax(ctx, ip, iend, &offsetFound, maxSearches, mls);
- if (ml2 > matchLength)
- matchLength = ml2, start = ip, offset=offsetFound;
- }
-
- if (matchLength < 4) {
- ip += ((ip-anchor) >> g_searchStrength) + 1; /* jump faster over incompressible sections */
- continue;
- }
-
- /* let's try to find a better solution */
- if (depth>=1)
- while (ip<ilimit) {
- ip ++;
- if ((offset) && ((offset_1>0) & (MEM_read32(ip) == MEM_read32(ip - offset_1)))) {
- size_t const mlRep = ZSTD_count(ip+4, ip+4-offset_1, iend) + 4;
- int const gain2 = (int)(mlRep * 3);
- int const gain1 = (int)(matchLength*3 - ZSTD_highbit32((U32)offset+1) + 1);
- if ((mlRep >= 4) && (gain2 > gain1))
- matchLength = mlRep, offset = 0, start = ip;
- }
- { size_t offset2=99999999;
- size_t const ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls);
- int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)offset2+1)); /* raw approx */
- int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 4);
- if ((ml2 >= 4) && (gain2 > gain1)) {
- matchLength = ml2, offset = offset2, start = ip;
- continue; /* search a better one */
- } }
-
- /* let's find an even better one */
- if ((depth==2) && (ip<ilimit)) {
- ip ++;
- if ((offset) && ((offset_1>0) & (MEM_read32(ip) == MEM_read32(ip - offset_1)))) {
- size_t const ml2 = ZSTD_count(ip+4, ip+4-offset_1, iend) + 4;
- int const gain2 = (int)(ml2 * 4);
- int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 1);
- if ((ml2 >= 4) && (gain2 > gain1))
- matchLength = ml2, offset = 0, start = ip;
- }
- { size_t offset2=99999999;
- size_t const ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls);
- int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)offset2+1)); /* raw approx */
- int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 7);
- if ((ml2 >= 4) && (gain2 > gain1)) {
- matchLength = ml2, offset = offset2, start = ip;
- continue;
- } } }
- break; /* nothing found : store previous solution */
- }
-
- /* NOTE:
- * start[-offset+ZSTD_REP_MOVE-1] is undefined behavior.
- * (-offset+ZSTD_REP_MOVE-1) is unsigned, and is added to start, which
- * overflows the pointer, which is undefined behavior.
- */
- /* catch up */
- if (offset) {
- while ( (start > anchor)
- && (start > base+offset-ZSTD_REP_MOVE)
- && (start[-1] == (start-offset+ZSTD_REP_MOVE)[-1]) ) /* only search for offset within prefix */
- { start--; matchLength++; }
- offset_2 = offset_1; offset_1 = (U32)(offset - ZSTD_REP_MOVE);
- }
- /* store sequence */
-_storeSequence:
- { size_t const litLength = start - anchor;
- ZSTD_storeSeq(seqStorePtr, litLength, anchor, (U32)offset, matchLength-MINMATCH);
- anchor = ip = start + matchLength;
- }
-
- /* check immediate repcode */
- while ( (ip <= ilimit)
- && ((offset_2>0)
- & (MEM_read32(ip) == MEM_read32(ip - offset_2)) )) {
- /* store sequence */
- matchLength = ZSTD_count(ip+4, ip+4-offset_2, iend) + 4;
- offset = offset_2; offset_2 = offset_1; offset_1 = (U32)offset; /* swap repcodes */
- ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, matchLength-MINMATCH);
- ip += matchLength;
- anchor = ip;
- continue; /* faster when present ... (?) */
- } }
-
- /* Save reps for next block */
- seqStorePtr->repToConfirm[0] = offset_1 ? offset_1 : savedOffset;
- seqStorePtr->repToConfirm[1] = offset_2 ? offset_2 : savedOffset;
-
- /* Last Literals */
- { size_t const lastLLSize = iend - anchor;
- memcpy(seqStorePtr->lit, anchor, lastLLSize);
- seqStorePtr->lit += lastLLSize;
- }
-}
-
-
-static void ZSTD_compressBlock_btlazy2(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
-{
- ZSTD_compressBlock_lazy_generic(ctx, src, srcSize, 1, 2);
-}
-
-static void ZSTD_compressBlock_lazy2(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
-{
- ZSTD_compressBlock_lazy_generic(ctx, src, srcSize, 0, 2);
-}
-
-static void ZSTD_compressBlock_lazy(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
-{
- ZSTD_compressBlock_lazy_generic(ctx, src, srcSize, 0, 1);
-}
-
-static void ZSTD_compressBlock_greedy(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
-{
- ZSTD_compressBlock_lazy_generic(ctx, src, srcSize, 0, 0);
-}
-
-
-FORCE_INLINE_TEMPLATE
-void ZSTD_compressBlock_lazy_extDict_generic(ZSTD_CCtx* ctx,
- const void* src, size_t srcSize,
- const U32 searchMethod, const U32 depth)
-{
- seqStore_t* seqStorePtr = &(ctx->seqStore);
- const BYTE* const istart = (const BYTE*)src;
- const BYTE* ip = istart;
- const BYTE* anchor = istart;
- const BYTE* const iend = istart + srcSize;
- const BYTE* const ilimit = iend - 8;
- const BYTE* const base = ctx->base;
- const U32 dictLimit = ctx->dictLimit;
- const U32 lowestIndex = ctx->lowLimit;
- const BYTE* const prefixStart = base + dictLimit;
- const BYTE* const dictBase = ctx->dictBase;
- const BYTE* const dictEnd = dictBase + dictLimit;
- const BYTE* const dictStart = dictBase + ctx->lowLimit;
-
- const U32 maxSearches = 1 << ctx->appliedParams.cParams.searchLog;
- const U32 mls = ctx->appliedParams.cParams.searchLength;
-
- typedef size_t (*searchMax_f)(ZSTD_CCtx* zc, const BYTE* ip, const BYTE* iLimit,
- size_t* offsetPtr,
- U32 maxNbAttempts, U32 matchLengthSearch);
- searchMax_f searchMax = searchMethod ? ZSTD_BtFindBestMatch_selectMLS_extDict : ZSTD_HcFindBestMatch_extDict_selectMLS;
-
- U32 offset_1 = seqStorePtr->rep[0], offset_2 = seqStorePtr->rep[1];
-
- /* init */
- ctx->nextToUpdate3 = ctx->nextToUpdate;
- ip += (ip == prefixStart);
-
- /* Match Loop */
- while (ip < ilimit) {
- size_t matchLength=0;
- size_t offset=0;
- const BYTE* start=ip+1;
- U32 current = (U32)(ip-base);
-
- /* check repCode */
- { const U32 repIndex = (U32)(current+1 - offset_1);
- const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
- const BYTE* const repMatch = repBase + repIndex;
- if (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex > lowestIndex)) /* intentional overflow */
- if (MEM_read32(ip+1) == MEM_read32(repMatch)) {
- /* repcode detected we should take it */
- const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
- matchLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repEnd, prefixStart) + 4;
- if (depth==0) goto _storeSequence;
- } }
-
- /* first search (depth 0) */
- { size_t offsetFound = 99999999;
- size_t const ml2 = searchMax(ctx, ip, iend, &offsetFound, maxSearches, mls);
- if (ml2 > matchLength)
- matchLength = ml2, start = ip, offset=offsetFound;
- }
-
- if (matchLength < 4) {
- ip += ((ip-anchor) >> g_searchStrength) + 1; /* jump faster over incompressible sections */
- continue;
- }
-
- /* let's try to find a better solution */
- if (depth>=1)
- while (ip<ilimit) {
- ip ++;
- current++;
- /* check repCode */
- if (offset) {
- const U32 repIndex = (U32)(current - offset_1);
- const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
- const BYTE* const repMatch = repBase + repIndex;
- if (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex > lowestIndex)) /* intentional overflow */
- if (MEM_read32(ip) == MEM_read32(repMatch)) {
- /* repcode detected */
- const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
- size_t const repLength = ZSTD_count_2segments(ip+4, repMatch+4, iend, repEnd, prefixStart) + 4;
- int const gain2 = (int)(repLength * 3);
- int const gain1 = (int)(matchLength*3 - ZSTD_highbit32((U32)offset+1) + 1);
- if ((repLength >= 4) && (gain2 > gain1))
- matchLength = repLength, offset = 0, start = ip;
- } }
-
- /* search match, depth 1 */
- { size_t offset2=99999999;
- size_t const ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls);
- int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)offset2+1)); /* raw approx */
- int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 4);
- if ((ml2 >= 4) && (gain2 > gain1)) {
- matchLength = ml2, offset = offset2, start = ip;
- continue; /* search a better one */
- } }
-
- /* let's find an even better one */
- if ((depth==2) && (ip<ilimit)) {
- ip ++;
- current++;
- /* check repCode */
- if (offset) {
- const U32 repIndex = (U32)(current - offset_1);
- const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
- const BYTE* const repMatch = repBase + repIndex;
- if (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex > lowestIndex)) /* intentional overflow */
- if (MEM_read32(ip) == MEM_read32(repMatch)) {
- /* repcode detected */
- const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
- size_t const repLength = ZSTD_count_2segments(ip+4, repMatch+4, iend, repEnd, prefixStart) + 4;
- int const gain2 = (int)(repLength * 4);
- int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 1);
- if ((repLength >= 4) && (gain2 > gain1))
- matchLength = repLength, offset = 0, start = ip;
- } }
-
- /* search match, depth 2 */
- { size_t offset2=99999999;
- size_t const ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls);
- int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)offset2+1)); /* raw approx */
- int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 7);
- if ((ml2 >= 4) && (gain2 > gain1)) {
- matchLength = ml2, offset = offset2, start = ip;
- continue;
- } } }
- break; /* nothing found : store previous solution */
- }
-
- /* catch up */
- if (offset) {
- U32 const matchIndex = (U32)((start-base) - (offset - ZSTD_REP_MOVE));
- const BYTE* match = (matchIndex < dictLimit) ? dictBase + matchIndex : base + matchIndex;
- const BYTE* const mStart = (matchIndex < dictLimit) ? dictStart : prefixStart;
- while ((start>anchor) && (match>mStart) && (start[-1] == match[-1])) { start--; match--; matchLength++; } /* catch up */
- offset_2 = offset_1; offset_1 = (U32)(offset - ZSTD_REP_MOVE);
- }
-
- /* store sequence */
-_storeSequence:
- { size_t const litLength = start - anchor;
- ZSTD_storeSeq(seqStorePtr, litLength, anchor, (U32)offset, matchLength-MINMATCH);
- anchor = ip = start + matchLength;
- }
-
- /* check immediate repcode */
- while (ip <= ilimit) {
- const U32 repIndex = (U32)((ip-base) - offset_2);
- const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
- const BYTE* const repMatch = repBase + repIndex;
- if (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex > lowestIndex)) /* intentional overflow */
- if (MEM_read32(ip) == MEM_read32(repMatch)) {
- /* repcode detected we should take it */
- const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
- matchLength = ZSTD_count_2segments(ip+4, repMatch+4, iend, repEnd, prefixStart) + 4;
- offset = offset_2; offset_2 = offset_1; offset_1 = (U32)offset; /* swap offset history */
- ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, matchLength-MINMATCH);
- ip += matchLength;
- anchor = ip;
- continue; /* faster when present ... (?) */
- }
- break;
- } }
-
- /* Save reps for next block */
- seqStorePtr->repToConfirm[0] = offset_1; seqStorePtr->repToConfirm[1] = offset_2;
-
- /* Last Literals */
- { size_t const lastLLSize = iend - anchor;
- memcpy(seqStorePtr->lit, anchor, lastLLSize);
- seqStorePtr->lit += lastLLSize;
- }
-}
-
-
-void ZSTD_compressBlock_greedy_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
-{
- ZSTD_compressBlock_lazy_extDict_generic(ctx, src, srcSize, 0, 0);
-}
-
-static void ZSTD_compressBlock_lazy_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
-{
- ZSTD_compressBlock_lazy_extDict_generic(ctx, src, srcSize, 0, 1);
-}
-
-static void ZSTD_compressBlock_lazy2_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
-{
- ZSTD_compressBlock_lazy_extDict_generic(ctx, src, srcSize, 0, 2);
-}
-
-static void ZSTD_compressBlock_btlazy2_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
-{
- ZSTD_compressBlock_lazy_extDict_generic(ctx, src, srcSize, 1, 2);
-}
-
-
-/* The optimal parser */
-#include "zstd_opt.h"
-
-static void ZSTD_compressBlock_btopt(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
-{
-#ifdef ZSTD_OPT_H_91842398743
- ZSTD_compressBlock_opt_generic(ctx, src, srcSize, 0);
-#else
- (void)ctx; (void)src; (void)srcSize;
- return;
-#endif
-}
-
-static void ZSTD_compressBlock_btultra(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
-{
-#ifdef ZSTD_OPT_H_91842398743
- ZSTD_compressBlock_opt_generic(ctx, src, srcSize, 1);
-#else
- (void)ctx; (void)src; (void)srcSize;
- return;
-#endif
-}
-
-static void ZSTD_compressBlock_btopt_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
-{
-#ifdef ZSTD_OPT_H_91842398743
- ZSTD_compressBlock_opt_extDict_generic(ctx, src, srcSize, 0);
-#else
- (void)ctx; (void)src; (void)srcSize;
- return;
-#endif
-}
-
-static void ZSTD_compressBlock_btultra_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
-{
-#ifdef ZSTD_OPT_H_91842398743
- ZSTD_compressBlock_opt_extDict_generic(ctx, src, srcSize, 1);
-#else
- (void)ctx; (void)src; (void)srcSize;
- return;
-#endif
-}
-
-
/* ZSTD_selectBlockCompressor() :
+ * Not static, but internal use only (used by long distance matcher)
* assumption : strat is a valid strategy */
-typedef void (*ZSTD_blockCompressor) (ZSTD_CCtx* ctx, const void* src, size_t srcSize);
-static ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, int extDict)
+typedef size_t (*ZSTD_blockCompressor) (ZSTD_CCtx* ctx, const void* src, size_t srcSize);
+ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, int extDict)
{
static const ZSTD_blockCompressor blockCompressor[2][(unsigned)ZSTD_btultra+1] = {
{ ZSTD_compressBlock_fast /* default for 0 */,
@@ -2819,18 +1565,37 @@ static ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, int
return blockCompressor[extDict!=0][(U32)strat];
}
+static void ZSTD_storeLastLiterals(seqStore_t* seqStorePtr,
+ const BYTE* anchor, size_t lastLLSize)
+{
+ memcpy(seqStorePtr->lit, anchor, lastLLSize);
+ seqStorePtr->lit += lastLLSize;
+}
static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
{
- ZSTD_blockCompressor const blockCompressor = ZSTD_selectBlockCompressor(zc->appliedParams.cParams.strategy, zc->lowLimit < zc->dictLimit);
const BYTE* const base = zc->base;
const BYTE* const istart = (const BYTE*)src;
const U32 current = (U32)(istart-base);
+ size_t lastLLSize;
+ const BYTE* anchor;
+ U32 const extDict = zc->lowLimit < zc->dictLimit;
+ const ZSTD_blockCompressor blockCompressor =
+ zc->appliedParams.ldmParams.enableLdm
+ ? (extDict ? ZSTD_compressBlock_ldm_extDict : ZSTD_compressBlock_ldm)
+ : ZSTD_selectBlockCompressor(zc->appliedParams.cParams.strategy, extDict);
+
if (srcSize < MIN_CBLOCK_SIZE+ZSTD_blockHeaderSize+1) return 0; /* don't even attempt compression below a certain srcSize */
ZSTD_resetSeqStore(&(zc->seqStore));
if (current > zc->nextToUpdate + 384)
zc->nextToUpdate = current - MIN(192, (U32)(current - zc->nextToUpdate - 384)); /* limited update after finding a very long match */
- blockCompressor(zc, src, srcSize);
+
+ lastLLSize = blockCompressor(zc, src, srcSize);
+
+ /* Last literals */
+ anchor = (const BYTE*)src + srcSize - lastLLSize;
+ ZSTD_storeLastLiterals(&zc->seqStore, anchor, lastLLSize);
+
return ZSTD_compressSequences(&zc->seqStore, zc->entropy, &zc->appliedParams.cParams, dst, dstCapacity, srcSize);
}
@@ -2852,7 +1617,7 @@ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx,
const BYTE* ip = (const BYTE*)src;
BYTE* const ostart = (BYTE*)dst;
BYTE* op = ostart;
- U32 const maxDist = 1 << cctx->appliedParams.cParams.windowLog;
+ U32 const maxDist = (U32)1 << cctx->appliedParams.cParams.windowLog;
if (cctx->appliedParams.fParams.checksumFlag && srcSize)
XXH64_update(&cctx->xxhState, src, srcSize);
@@ -2865,13 +1630,33 @@ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx,
return ERROR(dstSize_tooSmall); /* not enough space to store compressed block */
if (remaining < blockSize) blockSize = remaining;
- /* preemptive overflow correction */
+ /* preemptive overflow correction:
+ * 1. correction is large enough:
+ * lowLimit > (3<<29) ==> current > 3<<29 + 1<<windowLog - blockSize
+ * 1<<windowLog <= newCurrent < 1<<chainLog + 1<<windowLog
+ *
+ * current - newCurrent
+ * > (3<<29 + 1<<windowLog - blockSize) - (1<<windowLog + 1<<chainLog)
+ * > (3<<29 - blockSize) - (1<<chainLog)
+ * > (3<<29 - blockSize) - (1<<30) (NOTE: chainLog <= 30)
+ * > 1<<29 - 1<<17
+ *
+ * 2. (ip+blockSize - cctx->base) doesn't overflow:
+ * In 32 bit mode we limit windowLog to 30 so we don't get
+ * differences larger than 1<<31-1.
+ * 3. cctx->lowLimit < 1<<32:
+ * windowLog <= 31 ==> 3<<29 + 1<<windowLog < 7<<29 < 1<<32.
+ */
if (cctx->lowLimit > (3U<<29)) {
- U32 const cycleMask = (1 << ZSTD_cycleLog(cctx->appliedParams.cParams.hashLog, cctx->appliedParams.cParams.strategy)) - 1;
+ U32 const cycleMask = ((U32)1 << ZSTD_cycleLog(cctx->appliedParams.cParams.chainLog, cctx->appliedParams.cParams.strategy)) - 1;
U32 const current = (U32)(ip - cctx->base);
- U32 const newCurrent = (current & cycleMask) + (1 << cctx->appliedParams.cParams.windowLog);
+ U32 const newCurrent = (current & cycleMask) + ((U32)1 << cctx->appliedParams.cParams.windowLog);
U32 const correction = current - newCurrent;
- ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX_64 <= 30);
+ ZSTD_STATIC_ASSERT(ZSTD_CHAINLOG_MAX <= 30);
+ ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX_32 <= 30);
+ ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX <= 31);
+ assert(current > newCurrent);
+ assert(correction > 1<<28); /* Loose bound, should be about 1<<29 */
ZSTD_reduceIndex(cctx, correction);
cctx->base += correction;
cctx->dictBase += correction;
@@ -2879,6 +1664,7 @@ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx,
cctx->dictLimit -= correction;
if (cctx->nextToUpdate < correction) cctx->nextToUpdate = 0;
else cctx->nextToUpdate -= correction;
+ DEBUGLOG(4, "Correction of 0x%x bytes to lowLimit=0x%x\n", correction, cctx->lowLimit);
}
if ((U32)(ip+blockSize - cctx->base) > cctx->loadedDictEnd + maxDist) {
@@ -2915,25 +1701,29 @@ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx,
static size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity,
- ZSTD_parameters params, U64 pledgedSrcSize, U32 dictID)
+ ZSTD_CCtx_params params, U64 pledgedSrcSize, U32 dictID)
{ BYTE* const op = (BYTE*)dst;
U32 const dictIDSizeCodeLength = (dictID>0) + (dictID>=256) + (dictID>=65536); /* 0-3 */
U32 const dictIDSizeCode = params.fParams.noDictIDFlag ? 0 : dictIDSizeCodeLength; /* 0-3 */
U32 const checksumFlag = params.fParams.checksumFlag>0;
- U32 const windowSize = 1U << params.cParams.windowLog;
+ U32 const windowSize = (U32)1 << params.cParams.windowLog;
U32 const singleSegment = params.fParams.contentSizeFlag && (windowSize >= pledgedSrcSize);
BYTE const windowLogByte = (BYTE)((params.cParams.windowLog - ZSTD_WINDOWLOG_ABSOLUTEMIN) << 3);
U32 const fcsCode = params.fParams.contentSizeFlag ?
(pledgedSrcSize>=256) + (pledgedSrcSize>=65536+256) + (pledgedSrcSize>=0xFFFFFFFFU) : 0; /* 0-3 */
BYTE const frameHeaderDecriptionByte = (BYTE)(dictIDSizeCode + (checksumFlag<<2) + (singleSegment<<5) + (fcsCode<<6) );
- size_t pos;
+ size_t pos=0;
if (dstCapacity < ZSTD_frameHeaderSize_max) return ERROR(dstSize_tooSmall);
- DEBUGLOG(5, "ZSTD_writeFrameHeader : dictIDFlag : %u ; dictID : %u ; dictIDSizeCode : %u",
+ DEBUGLOG(4, "ZSTD_writeFrameHeader : dictIDFlag : %u ; dictID : %u ; dictIDSizeCode : %u",
!params.fParams.noDictIDFlag, dictID, dictIDSizeCode);
- MEM_writeLE32(dst, ZSTD_MAGICNUMBER);
- op[4] = frameHeaderDecriptionByte; pos=5;
+ if (params.format == ZSTD_f_zstd1) {
+ DEBUGLOG(4, "writing zstd magic number");
+ MEM_writeLE32(dst, ZSTD_MAGICNUMBER);
+ pos = 4;
+ }
+ op[pos++] = frameHeaderDecriptionByte;
if (!singleSegment) op[pos++] = windowLogByte;
switch(dictIDSizeCode)
{
@@ -2969,7 +1759,7 @@ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* cctx,
if (frame && (cctx->stage==ZSTDcs_init)) {
fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, cctx->appliedParams,
- cctx->pledgedSrcSizePlusOne-1, cctx->dictID);
+ cctx->pledgedSrcSizePlusOne-1, cctx->dictID);
if (ZSTD_isError(fhSize)) return fhSize;
dstCapacity -= fhSize;
dst = (char*)dst + fhSize;
@@ -3018,11 +1808,9 @@ size_t ZSTD_compressContinue (ZSTD_CCtx* cctx,
size_t ZSTD_getBlockSize(const ZSTD_CCtx* cctx)
{
- U32 const cLevel = cctx->compressionLevel;
- ZSTD_compressionParameters cParams = (cLevel == ZSTD_CLEVEL_CUSTOM) ?
- cctx->appliedParams.cParams :
- ZSTD_getCParams(cLevel, 0, 0);
- return MIN (ZSTD_BLOCKSIZE_MAX, 1 << cParams.windowLog);
+ ZSTD_compressionParameters const cParams =
+ ZSTD_getCParamsFromCCtxParams(cctx->appliedParams, 0, 0);
+ return MIN (ZSTD_BLOCKSIZE_MAX, (U32)1 << cParams.windowLog);
}
size_t ZSTD_compressBlock(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
@@ -3046,7 +1834,7 @@ static size_t ZSTD_loadDictionaryContent(ZSTD_CCtx* zc, const void* src, size_t
zc->dictBase = zc->base;
zc->base += ip - zc->nextSrc;
zc->nextToUpdate = zc->dictLimit;
- zc->loadedDictEnd = zc->forceWindow ? 0 : (U32)(iend - zc->base);
+ zc->loadedDictEnd = zc->appliedParams.forceWindow ? 0 : (U32)(iend - zc->base);
zc->nextSrc = iend;
if (srcSize <= HASH_READ_SIZE) return 0;
@@ -3056,7 +1844,6 @@ static size_t ZSTD_loadDictionaryContent(ZSTD_CCtx* zc, const void* src, size_t
case ZSTD_fast:
ZSTD_fillHashTable (zc, iend, zc->appliedParams.cParams.searchLength);
break;
-
case ZSTD_dfast:
ZSTD_fillDoubleHashTable (zc, iend, zc->appliedParams.cParams.searchLength);
break;
@@ -3072,7 +1859,7 @@ static size_t ZSTD_loadDictionaryContent(ZSTD_CCtx* zc, const void* src, size_t
case ZSTD_btopt:
case ZSTD_btultra:
if (srcSize >= HASH_READ_SIZE)
- ZSTD_updateTree(zc, iend-HASH_READ_SIZE, iend, 1 << zc->appliedParams.cParams.searchLog, zc->appliedParams.cParams.searchLength);
+ ZSTD_updateTree(zc, iend-HASH_READ_SIZE, iend, (U32)1 << zc->appliedParams.cParams.searchLog, zc->appliedParams.cParams.searchLength);
break;
default:
@@ -3120,8 +1907,10 @@ static size_t ZSTD_loadZstdDictionary(ZSTD_CCtx* cctx, const void* dict, size_t
cctx->dictID = cctx->appliedParams.fParams.noDictIDFlag ? 0 : MEM_readLE32(dictPtr);
dictPtr += 4;
- { size_t const hufHeaderSize = HUF_readCTable((HUF_CElt*)cctx->entropy->hufCTable, 255, dictPtr, dictEnd-dictPtr);
+ { unsigned maxSymbolValue = 255;
+ size_t const hufHeaderSize = HUF_readCTable((HUF_CElt*)cctx->entropy->hufCTable, &maxSymbolValue, dictPtr, dictEnd-dictPtr);
if (HUF_isError(hufHeaderSize)) return ERROR(dictionary_corrupted);
+ if (maxSymbolValue < 255) return ERROR(dictionary_corrupted);
dictPtr += hufHeaderSize;
}
@@ -3221,12 +2010,10 @@ static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx,
const void* dict, size_t dictSize,
ZSTD_dictMode_e dictMode,
const ZSTD_CDict* cdict,
- ZSTD_parameters params, U64 pledgedSrcSize,
+ ZSTD_CCtx_params params, U64 pledgedSrcSize,
ZSTD_buffered_policy_e zbuff)
{
DEBUGLOG(4, "ZSTD_compressBegin_internal");
- DEBUGLOG(4, "dict ? %s", dict ? "dict" : (cdict ? "cdict" : "none"));
- DEBUGLOG(4, "dictMode : %u", (U32)dictMode);
/* params are supposed to be fully validated at this point */
assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
assert(!((dict) && (cdict))); /* either dict or cdict, not both */
@@ -3242,6 +2029,19 @@ static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx,
return ZSTD_compress_insertDictionary(cctx, dict, dictSize, dictMode);
}
+size_t ZSTD_compressBegin_advanced_internal(
+ ZSTD_CCtx* cctx,
+ const void* dict, size_t dictSize,
+ ZSTD_dictMode_e dictMode,
+ ZSTD_CCtx_params params,
+ unsigned long long pledgedSrcSize)
+{
+ /* compression parameters verification and optimization */
+ CHECK_F( ZSTD_checkCParams(params.cParams) );
+ return ZSTD_compressBegin_internal(cctx, dict, dictSize, dictMode, NULL,
+ params, pledgedSrcSize,
+ ZSTDb_not_buffered);
+}
/*! ZSTD_compressBegin_advanced() :
* @return : 0, or an error code */
@@ -3249,21 +2049,22 @@ size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* cctx,
const void* dict, size_t dictSize,
ZSTD_parameters params, unsigned long long pledgedSrcSize)
{
- /* compression parameters verification and optimization */
- CHECK_F(ZSTD_checkCParams(params.cParams));
- return ZSTD_compressBegin_internal(cctx, dict, dictSize, ZSTD_dm_auto, NULL,
- params, pledgedSrcSize, ZSTDb_not_buffered);
+ ZSTD_CCtx_params const cctxParams =
+ ZSTD_assignParamsToCCtxParams(cctx->requestedParams, params);
+ return ZSTD_compressBegin_advanced_internal(cctx, dict, dictSize, ZSTD_dm_auto,
+ cctxParams,
+ pledgedSrcSize);
}
-
size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel)
{
ZSTD_parameters const params = ZSTD_getParams(compressionLevel, 0, dictSize);
+ ZSTD_CCtx_params const cctxParams =
+ ZSTD_assignParamsToCCtxParams(cctx->requestedParams, params);
return ZSTD_compressBegin_internal(cctx, dict, dictSize, ZSTD_dm_auto, NULL,
- params, 0, ZSTDb_not_buffered);
+ cctxParams, 0, ZSTDb_not_buffered);
}
-
size_t ZSTD_compressBegin(ZSTD_CCtx* cctx, int compressionLevel)
{
return ZSTD_compressBegin_usingDict(cctx, NULL, 0, compressionLevel);
@@ -3324,9 +2125,9 @@ size_t ZSTD_compressEnd (ZSTD_CCtx* cctx,
endResult = ZSTD_writeEpilogue(cctx, (char*)dst + cSize, dstCapacity-cSize);
if (ZSTD_isError(endResult)) return endResult;
if (cctx->appliedParams.fParams.contentSizeFlag) { /* control src size */
- DEBUGLOG(5, "end of frame : controlling src size");
+ DEBUGLOG(4, "end of frame : controlling src size");
if (cctx->pledgedSrcSizePlusOne != cctx->consumedSrcSize+1) {
- DEBUGLOG(5, "error : pledgedSrcSize = %u, while realSrcSize = %u",
+ DEBUGLOG(4, "error : pledgedSrcSize = %u, while realSrcSize = %u",
(U32)cctx->pledgedSrcSizePlusOne-1, (U32)cctx->consumedSrcSize);
return ERROR(srcSize_wrong);
} }
@@ -3340,9 +2141,13 @@ static size_t ZSTD_compress_internal (ZSTD_CCtx* cctx,
const void* dict,size_t dictSize,
ZSTD_parameters params)
{
- CHECK_F( ZSTD_compressBegin_internal(cctx, dict, dictSize, ZSTD_dm_auto, NULL,
- params, srcSize, ZSTDb_not_buffered) );
- return ZSTD_compressEnd(cctx, dst, dstCapacity, src, srcSize);
+ ZSTD_CCtx_params const cctxParams =
+ ZSTD_assignParamsToCCtxParams(cctx->requestedParams, params);
+ return ZSTD_compress_advanced_internal(cctx,
+ dst, dstCapacity,
+ src, srcSize,
+ dict, dictSize,
+ cctxParams);
}
size_t ZSTD_compress_advanced (ZSTD_CCtx* ctx,
@@ -3355,6 +2160,19 @@ size_t ZSTD_compress_advanced (ZSTD_CCtx* ctx,
return ZSTD_compress_internal(ctx, dst, dstCapacity, src, srcSize, dict, dictSize, params);
}
+/* Internal */
+size_t ZSTD_compress_advanced_internal(
+ ZSTD_CCtx* cctx,
+ void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize,
+ const void* dict,size_t dictSize,
+ ZSTD_CCtx_params params)
+{
+ CHECK_F( ZSTD_compressBegin_internal(cctx, dict, dictSize, ZSTD_dm_auto, NULL,
+ params, srcSize, ZSTDb_not_buffered) );
+ return ZSTD_compressEnd(cctx, dst, dstCapacity, src, srcSize);
+}
+
size_t ZSTD_compress_usingDict(ZSTD_CCtx* ctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize,
const void* dict, size_t dictSize, int compressionLevel)
{
@@ -3384,18 +2202,21 @@ size_t ZSTD_compress(void* dst, size_t dstCapacity, const void* src, size_t srcS
/*! ZSTD_estimateCDictSize_advanced() :
* Estimate amount of memory that will be needed to create a dictionary with following arguments */
-size_t ZSTD_estimateCDictSize_advanced(size_t dictSize, ZSTD_compressionParameters cParams, unsigned byReference)
+size_t ZSTD_estimateCDictSize_advanced(
+ size_t dictSize, ZSTD_compressionParameters cParams,
+ ZSTD_dictLoadMethod_e dictLoadMethod)
{
DEBUGLOG(5, "sizeof(ZSTD_CDict) : %u", (U32)sizeof(ZSTD_CDict));
- DEBUGLOG(5, "CCtx estimate : %u", (U32)ZSTD_estimateCCtxSize_advanced(cParams));
- return sizeof(ZSTD_CDict) + ZSTD_estimateCCtxSize_advanced(cParams)
- + (byReference ? 0 : dictSize);
+ DEBUGLOG(5, "CCtx estimate : %u",
+ (U32)ZSTD_estimateCCtxSize_usingCParams(cParams));
+ return sizeof(ZSTD_CDict) + ZSTD_estimateCCtxSize_usingCParams(cParams)
+ + (dictLoadMethod == ZSTD_dlm_byRef ? 0 : dictSize);
}
size_t ZSTD_estimateCDictSize(size_t dictSize, int compressionLevel)
{
ZSTD_compressionParameters const cParams = ZSTD_getCParams(compressionLevel, 0, dictSize);
- return ZSTD_estimateCDictSize_advanced(dictSize, cParams, 0);
+ return ZSTD_estimateCDictSize_advanced(dictSize, cParams, ZSTD_dlm_byCopy);
}
size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict)
@@ -3406,22 +2227,15 @@ size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict)
return ZSTD_sizeof_CCtx(cdict->refContext) + (cdict->dictBuffer ? cdict->dictContentSize : 0) + sizeof(*cdict);
}
-static ZSTD_parameters ZSTD_makeParams(ZSTD_compressionParameters cParams, ZSTD_frameParameters fParams)
-{
- ZSTD_parameters params;
- params.cParams = cParams;
- params.fParams = fParams;
- return params;
-}
-
static size_t ZSTD_initCDict_internal(
ZSTD_CDict* cdict,
const void* dictBuffer, size_t dictSize,
- unsigned byReference, ZSTD_dictMode_e dictMode,
+ ZSTD_dictLoadMethod_e dictLoadMethod,
+ ZSTD_dictMode_e dictMode,
ZSTD_compressionParameters cParams)
{
DEBUGLOG(5, "ZSTD_initCDict_internal, mode %u", (U32)dictMode);
- if ((byReference) || (!dictBuffer) || (!dictSize)) {
+ if ((dictLoadMethod == ZSTD_dlm_byRef) || (!dictBuffer) || (!dictSize)) {
cdict->dictBuffer = NULL;
cdict->dictContent = dictBuffer;
} else {
@@ -3433,13 +2247,12 @@ static size_t ZSTD_initCDict_internal(
}
cdict->dictContentSize = dictSize;
- { ZSTD_frameParameters const fParams = { 0 /* contentSizeFlag */,
- 0 /* checksumFlag */, 0 /* noDictIDFlag */ }; /* dummy */
- ZSTD_parameters const params = ZSTD_makeParams(cParams, fParams);
+ { ZSTD_CCtx_params cctxParams = cdict->refContext->requestedParams;
+ cctxParams.cParams = cParams;
CHECK_F( ZSTD_compressBegin_internal(cdict->refContext,
cdict->dictContent, dictSize, dictMode,
NULL,
- params, ZSTD_CONTENTSIZE_UNKNOWN,
+ cctxParams, ZSTD_CONTENTSIZE_UNKNOWN,
ZSTDb_not_buffered) );
}
@@ -3447,7 +2260,8 @@ static size_t ZSTD_initCDict_internal(
}
ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize,
- unsigned byReference, ZSTD_dictMode_e dictMode,
+ ZSTD_dictLoadMethod_e dictLoadMethod,
+ ZSTD_dictMode_e dictMode,
ZSTD_compressionParameters cParams, ZSTD_customMem customMem)
{
DEBUGLOG(5, "ZSTD_createCDict_advanced, mode %u", (U32)dictMode);
@@ -3462,10 +2276,9 @@ ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize,
return NULL;
}
cdict->refContext = cctx;
-
if (ZSTD_isError( ZSTD_initCDict_internal(cdict,
dictBuffer, dictSize,
- byReference, dictMode,
+ dictLoadMethod, dictMode,
cParams) )) {
ZSTD_freeCDict(cdict);
return NULL;
@@ -3479,7 +2292,7 @@ ZSTD_CDict* ZSTD_createCDict(const void* dict, size_t dictSize, int compressionL
{
ZSTD_compressionParameters cParams = ZSTD_getCParams(compressionLevel, 0, dictSize);
return ZSTD_createCDict_advanced(dict, dictSize,
- 0 /* byReference */, ZSTD_dm_auto,
+ ZSTD_dlm_byCopy, ZSTD_dm_auto,
cParams, ZSTD_defaultCMem);
}
@@ -3487,7 +2300,7 @@ ZSTD_CDict* ZSTD_createCDict_byReference(const void* dict, size_t dictSize, int
{
ZSTD_compressionParameters cParams = ZSTD_getCParams(compressionLevel, 0, dictSize);
return ZSTD_createCDict_advanced(dict, dictSize,
- 1 /* byReference */, ZSTD_dm_auto,
+ ZSTD_dlm_byRef, ZSTD_dm_auto,
cParams, ZSTD_defaultCMem);
}
@@ -3517,11 +2330,12 @@ size_t ZSTD_freeCDict(ZSTD_CDict* cdict)
*/
ZSTD_CDict* ZSTD_initStaticCDict(void* workspace, size_t workspaceSize,
const void* dict, size_t dictSize,
- unsigned byReference, ZSTD_dictMode_e dictMode,
+ ZSTD_dictLoadMethod_e dictLoadMethod,
+ ZSTD_dictMode_e dictMode,
ZSTD_compressionParameters cParams)
{
- size_t const cctxSize = ZSTD_estimateCCtxSize_advanced(cParams);
- size_t const neededSize = sizeof(ZSTD_CDict) + (byReference ? 0 : dictSize)
+ size_t const cctxSize = ZSTD_estimateCCtxSize_usingCParams(cParams);
+ size_t const neededSize = sizeof(ZSTD_CDict) + (dictLoadMethod == ZSTD_dlm_byRef ? 0 : dictSize)
+ cctxSize;
ZSTD_CDict* const cdict = (ZSTD_CDict*) workspace;
void* ptr;
@@ -3531,7 +2345,7 @@ ZSTD_CDict* ZSTD_initStaticCDict(void* workspace, size_t workspaceSize,
(U32)workspaceSize, (U32)neededSize, (U32)(workspaceSize < neededSize));
if (workspaceSize < neededSize) return NULL;
- if (!byReference) {
+ if (dictLoadMethod == ZSTD_dlm_byCopy) {
memcpy(cdict+1, dict, dictSize);
dict = cdict+1;
ptr = (char*)workspace + sizeof(ZSTD_CDict) + dictSize;
@@ -3542,15 +2356,15 @@ ZSTD_CDict* ZSTD_initStaticCDict(void* workspace, size_t workspaceSize,
if (ZSTD_isError( ZSTD_initCDict_internal(cdict,
dict, dictSize,
- 1 /* byReference */, dictMode,
+ ZSTD_dlm_byRef, dictMode,
cParams) ))
return NULL;
return cdict;
}
-ZSTD_parameters ZSTD_getParamsFromCDict(const ZSTD_CDict* cdict) {
- return ZSTD_getParamsFromCCtx(cdict->refContext);
+ZSTD_compressionParameters ZSTD_getCParamsFromCDict(const ZSTD_CDict* cdict) {
+ return cdict->refContext->appliedParams.cParams;
}
/* ZSTD_compressBegin_usingCDict_advanced() :
@@ -3560,7 +2374,8 @@ size_t ZSTD_compressBegin_usingCDict_advanced(
ZSTD_frameParameters const fParams, unsigned long long const pledgedSrcSize)
{
if (cdict==NULL) return ERROR(dictionary_wrong);
- { ZSTD_parameters params = cdict->refContext->appliedParams;
+ { ZSTD_CCtx_params params = cctx->requestedParams;
+ params.cParams = ZSTD_getCParamsFromCDict(cdict);
params.fParams = fParams;
DEBUGLOG(5, "ZSTD_compressBegin_usingCDict_advanced");
return ZSTD_compressBegin_internal(cctx,
@@ -3644,7 +2459,7 @@ size_t ZSTD_CStreamOutSize(void)
static size_t ZSTD_resetCStream_internal(ZSTD_CStream* zcs,
const void* dict, size_t dictSize, ZSTD_dictMode_e dictMode,
const ZSTD_CDict* cdict,
- ZSTD_parameters params, unsigned long long pledgedSrcSize)
+ const ZSTD_CCtx_params params, unsigned long long pledgedSrcSize)
{
DEBUGLOG(4, "ZSTD_resetCStream_internal");
/* params are supposed to be fully validated at this point */
@@ -3668,13 +2483,11 @@ static size_t ZSTD_resetCStream_internal(ZSTD_CStream* zcs,
size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize)
{
- ZSTD_parameters params = zcs->requestedParams;
+ ZSTD_CCtx_params params = zcs->requestedParams;
params.fParams.contentSizeFlag = (pledgedSrcSize > 0);
- DEBUGLOG(5, "ZSTD_resetCStream");
- if (zcs->compressionLevel != ZSTD_CLEVEL_CUSTOM) {
- params.cParams = ZSTD_getCParams(zcs->compressionLevel, pledgedSrcSize, 0 /* dictSize */);
- }
- return ZSTD_resetCStream_internal(zcs, NULL, 0, zcs->dictMode, zcs->cdict, params, pledgedSrcSize);
+ params.cParams = ZSTD_getCParamsFromCCtxParams(params, pledgedSrcSize, 0);
+ DEBUGLOG(4, "ZSTD_resetCStream");
+ return ZSTD_resetCStream_internal(zcs, NULL, 0, ZSTD_dm_auto, zcs->cdict, params, pledgedSrcSize);
}
/*! ZSTD_initCStream_internal() :
@@ -3683,9 +2496,9 @@ size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize)
* Assumption 2 : either dict, or cdict, is defined, not both */
size_t ZSTD_initCStream_internal(ZSTD_CStream* zcs,
const void* dict, size_t dictSize, const ZSTD_CDict* cdict,
- ZSTD_parameters params, unsigned long long pledgedSrcSize)
+ ZSTD_CCtx_params params, unsigned long long pledgedSrcSize)
{
- DEBUGLOG(5, "ZSTD_initCStream_internal");
+ DEBUGLOG(4, "ZSTD_initCStream_internal");
assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
assert(!((dict) && (cdict))); /* either dict or cdict, not both */
@@ -3697,23 +2510,23 @@ size_t ZSTD_initCStream_internal(ZSTD_CStream* zcs,
}
ZSTD_freeCDict(zcs->cdictLocal);
zcs->cdictLocal = ZSTD_createCDict_advanced(dict, dictSize,
- zcs->dictContentByRef, zcs->dictMode,
+ ZSTD_dlm_byCopy, ZSTD_dm_auto,
params.cParams, zcs->customMem);
zcs->cdict = zcs->cdictLocal;
if (zcs->cdictLocal == NULL) return ERROR(memory_allocation);
} else {
if (cdict) {
- ZSTD_parameters const cdictParams = ZSTD_getParamsFromCDict(cdict);
- params.cParams = cdictParams.cParams; /* cParams are enforced from cdict */
+ params.cParams = ZSTD_getCParamsFromCDict(cdict); /* cParams are enforced from cdict */
}
ZSTD_freeCDict(zcs->cdictLocal);
zcs->cdictLocal = NULL;
zcs->cdict = cdict;
}
+ params.compressionLevel = ZSTD_CLEVEL_CUSTOM;
zcs->requestedParams = params;
- zcs->compressionLevel = ZSTD_CLEVEL_CUSTOM;
- return ZSTD_resetCStream_internal(zcs, NULL, 0, zcs->dictMode, zcs->cdict, params, pledgedSrcSize);
+
+ return ZSTD_resetCStream_internal(zcs, NULL, 0, ZSTD_dm_auto, zcs->cdict, params, pledgedSrcSize);
}
/* ZSTD_initCStream_usingCDict_advanced() :
@@ -3724,7 +2537,8 @@ size_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs,
unsigned long long pledgedSrcSize)
{ /* cannot handle NULL cdict (does not know what to do) */
if (!cdict) return ERROR(dictionary_wrong);
- { ZSTD_parameters params = ZSTD_getParamsFromCDict(cdict);
+ { ZSTD_CCtx_params params = zcs->requestedParams;
+ params.cParams = ZSTD_getCParamsFromCDict(cdict);
params.fParams = fParams;
return ZSTD_initCStream_internal(zcs,
NULL, 0, cdict,
@@ -3743,30 +2557,32 @@ size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs,
const void* dict, size_t dictSize,
ZSTD_parameters params, unsigned long long pledgedSrcSize)
{
+ ZSTD_CCtx_params const cctxParams =
+ ZSTD_assignParamsToCCtxParams(zcs->requestedParams, params);
CHECK_F( ZSTD_checkCParams(params.cParams) );
- zcs->requestedParams = params;
- zcs->compressionLevel = ZSTD_CLEVEL_CUSTOM;
- return ZSTD_initCStream_internal(zcs, dict, dictSize, NULL, params, pledgedSrcSize);
+ return ZSTD_initCStream_internal(zcs, dict, dictSize, NULL, cctxParams, pledgedSrcSize);
}
size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel)
{
ZSTD_parameters const params = ZSTD_getParams(compressionLevel, 0, dictSize);
- zcs->compressionLevel = compressionLevel;
- return ZSTD_initCStream_internal(zcs, dict, dictSize, NULL, params, 0);
+ ZSTD_CCtx_params const cctxParams =
+ ZSTD_assignParamsToCCtxParams(zcs->requestedParams, params);
+ return ZSTD_initCStream_internal(zcs, dict, dictSize, NULL, cctxParams, 0);
}
size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pledgedSrcSize)
{
- ZSTD_parameters params = ZSTD_getParams(compressionLevel, pledgedSrcSize, 0);
- params.fParams.contentSizeFlag = (pledgedSrcSize>0);
- return ZSTD_initCStream_internal(zcs, NULL, 0, NULL, params, pledgedSrcSize);
+ ZSTD_CCtx_params cctxParams;
+ ZSTD_parameters const params = ZSTD_getParams(compressionLevel, pledgedSrcSize, 0);
+ cctxParams = ZSTD_assignParamsToCCtxParams(zcs->requestedParams, params);
+ cctxParams.fParams.contentSizeFlag = (pledgedSrcSize>0);
+ return ZSTD_initCStream_internal(zcs, NULL, 0, NULL, cctxParams, pledgedSrcSize);
}
size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel)
{
- ZSTD_parameters const params = ZSTD_getParams(compressionLevel, 0, 0);
- return ZSTD_initCStream_internal(zcs, NULL, 0, NULL, params, 0);
+ return ZSTD_initCStream_srcSize(zcs, compressionLevel, 0);
}
/*====== Compression ======*/
@@ -3781,6 +2597,7 @@ MEM_STATIC size_t ZSTD_limitCopy(void* dst, size_t dstCapacity,
/** ZSTD_compressStream_generic():
* internal function for all *compressStream*() variants and *compress_generic()
+ * non-static, because can be called from zstdmt.c
* @return : hint size for next input */
size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
ZSTD_outBuffer* output,
@@ -3934,21 +2751,13 @@ size_t ZSTD_compressStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output, ZSTD_inBuf
return ZSTD_compressStream_generic(zcs, output, input, ZSTD_e_continue);
}
-/*! ZSTDMT_initCStream_internal() :
- * Private use only. Init streaming operation.
- * expects params to be valid.
- * must receive dict, or cdict, or none, but not both.
- * @return : 0, or an error code */
-size_t ZSTDMT_initCStream_internal(ZSTDMT_CCtx* zcs,
- const void* dict, size_t dictSize, const ZSTD_CDict* cdict,
- ZSTD_parameters params, unsigned long long pledgedSrcSize);
-
size_t ZSTD_compress_generic (ZSTD_CCtx* cctx,
ZSTD_outBuffer* output,
ZSTD_inBuffer* input,
ZSTD_EndDirective endOp)
{
+ DEBUGLOG(5, "ZSTD_compress_generic");
/* check conditions */
if (output->pos > output->size) return ERROR(GENERIC);
if (input->pos > input->size) return ERROR(GENERIC);
@@ -3956,31 +2765,42 @@ size_t ZSTD_compress_generic (ZSTD_CCtx* cctx,
/* transparent initialization stage */
if (cctx->streamStage == zcss_init) {
- const void* const prefix = cctx->prefix;
- size_t const prefixSize = cctx->prefixSize;
- ZSTD_parameters params = cctx->requestedParams;
- if (cctx->compressionLevel != ZSTD_CLEVEL_CUSTOM)
- params.cParams = ZSTD_getCParams(cctx->compressionLevel,
- cctx->pledgedSrcSizePlusOne-1, 0 /*dictSize*/);
- cctx->prefix = NULL; cctx->prefixSize = 0; /* single usage */
- assert(prefix==NULL || cctx->cdict==NULL); /* only one can be set */
+ ZSTD_prefixDict const prefixDict = cctx->prefixDict;
+ ZSTD_CCtx_params params = cctx->requestedParams;
+ params.cParams = ZSTD_getCParamsFromCCtxParams(
+ cctx->requestedParams, cctx->pledgedSrcSizePlusOne-1, 0 /*dictSize*/);
+ memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict)); /* single usage */
+ assert(prefixDict.dict==NULL || cctx->cdict==NULL); /* only one can be set */
+ DEBUGLOG(4, "ZSTD_compress_generic : transparent init stage");
#ifdef ZSTD_MULTITHREAD
- if (cctx->nbThreads > 1) {
- DEBUGLOG(4, "call ZSTDMT_initCStream_internal as nbThreads=%u", cctx->nbThreads);
- CHECK_F( ZSTDMT_initCStream_internal(cctx->mtctx, prefix, prefixSize, cctx->cdict, params, cctx->pledgedSrcSizePlusOne-1) );
+ if (params.nbThreads > 1) {
+ if (cctx->mtctx == NULL || cctx->appliedParams.nbThreads != params.nbThreads) {
+ ZSTDMT_freeCCtx(cctx->mtctx);
+ cctx->mtctx = ZSTDMT_createCCtx_advanced(params.nbThreads, cctx->customMem);
+ if (cctx->mtctx == NULL) return ERROR(memory_allocation);
+ }
+ DEBUGLOG(4, "call ZSTDMT_initCStream_internal as nbThreads=%u", params.nbThreads);
+ CHECK_F( ZSTDMT_initCStream_internal(
+ cctx->mtctx,
+ prefixDict.dict, prefixDict.dictSize, ZSTD_dm_rawContent,
+ cctx->cdict, params, cctx->pledgedSrcSizePlusOne-1) );
cctx->streamStage = zcss_load;
+ cctx->appliedParams.nbThreads = params.nbThreads;
} else
#endif
{
- CHECK_F( ZSTD_resetCStream_internal(cctx, prefix, prefixSize, cctx->dictMode, cctx->cdict, params, cctx->pledgedSrcSizePlusOne-1) );
+ CHECK_F( ZSTD_resetCStream_internal(
+ cctx, prefixDict.dict, prefixDict.dictSize,
+ prefixDict.dictMode, cctx->cdict, params,
+ cctx->pledgedSrcSizePlusOne-1) );
} }
/* compression stage */
#ifdef ZSTD_MULTITHREAD
- if (cctx->nbThreads > 1) {
+ if (cctx->appliedParams.nbThreads > 1) {
size_t const flushMin = ZSTDMT_compressStream_generic(cctx->mtctx, output, input, endOp);
- DEBUGLOG(5, "ZSTDMT_compressStream_generic : %u", (U32)flushMin);
+ DEBUGLOG(5, "ZSTDMT_compressStream_generic result : %u", (U32)flushMin);
if ( ZSTD_isError(flushMin)
|| (endOp == ZSTD_e_end && flushMin == 0) ) { /* compression completed */
ZSTD_startNewCompression(cctx);
@@ -3988,7 +2808,6 @@ size_t ZSTD_compress_generic (ZSTD_CCtx* cctx,
return flushMin;
}
#endif
-
CHECK_F( ZSTD_compressStream_generic(cctx, output, input, endOp) );
DEBUGLOG(5, "completed ZSTD_compress_generic");
return cctx->outBuffContentSize - cctx->outBuffFlushedSize; /* remaining to flush */
@@ -4189,6 +3008,7 @@ ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long l
if (compressionLevel > ZSTD_MAX_CLEVEL) compressionLevel = ZSTD_MAX_CLEVEL;
{ ZSTD_compressionParameters const cp = ZSTD_defaultCParameters[tableID][compressionLevel];
return ZSTD_adjustCParams_internal(cp, srcSizeHint, dictSize); }
+
}
/*! ZSTD_getParams() :
diff --git a/thirdparty/zstd/compress/zstd_compress.h b/thirdparty/zstd/compress/zstd_compress.h
new file mode 100644
index 0000000000..94606edc93
--- /dev/null
+++ b/thirdparty/zstd/compress/zstd_compress.h
@@ -0,0 +1,307 @@
+/*
+ * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under both the BSD-style license (found in the
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
+ * in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
+ */
+
+
+#ifndef ZSTD_COMPRESS_H
+#define ZSTD_COMPRESS_H
+
+/*-*************************************
+* Dependencies
+***************************************/
+#include "zstd_internal.h"
+#ifdef ZSTD_MULTITHREAD
+# include "zstdmt_compress.h"
+#endif
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+/*-*************************************
+* Constants
+***************************************/
+static const U32 g_searchStrength = 8;
+#define HASH_READ_SIZE 8
+
+
+/*-*************************************
+* Context memory management
+***************************************/
+typedef enum { ZSTDcs_created=0, ZSTDcs_init, ZSTDcs_ongoing, ZSTDcs_ending } ZSTD_compressionStage_e;
+typedef enum { zcss_init=0, zcss_load, zcss_flush } ZSTD_cStreamStage;
+
+typedef struct ZSTD_prefixDict_s {
+ const void* dict;
+ size_t dictSize;
+ ZSTD_dictMode_e dictMode;
+} ZSTD_prefixDict;
+
+struct ZSTD_CCtx_s {
+ const BYTE* nextSrc; /* next block here to continue on current prefix */
+ const BYTE* base; /* All regular indexes relative to this position */
+ const BYTE* dictBase; /* extDict indexes relative to this position */
+ U32 dictLimit; /* below that point, need extDict */
+ U32 lowLimit; /* below that point, no more data */
+ U32 nextToUpdate; /* index from which to continue dictionary update */
+ U32 nextToUpdate3; /* index from which to continue dictionary update */
+ U32 hashLog3; /* dispatch table : larger == faster, more memory */
+ U32 loadedDictEnd; /* index of end of dictionary */
+ ZSTD_compressionStage_e stage;
+ U32 dictID;
+ ZSTD_CCtx_params requestedParams;
+ ZSTD_CCtx_params appliedParams;
+ void* workSpace;
+ size_t workSpaceSize;
+ size_t blockSize;
+ U64 pledgedSrcSizePlusOne; /* this way, 0 (default) == unknown */
+ U64 consumedSrcSize;
+ XXH64_state_t xxhState;
+ ZSTD_customMem customMem;
+ size_t staticSize;
+
+ seqStore_t seqStore; /* sequences storage ptrs */
+ optState_t optState;
+ ldmState_t ldmState; /* long distance matching state */
+ U32* hashTable;
+ U32* hashTable3;
+ U32* chainTable;
+ ZSTD_entropyCTables_t* entropy;
+
+ /* streaming */
+ char* inBuff;
+ size_t inBuffSize;
+ size_t inToCompress;
+ size_t inBuffPos;
+ size_t inBuffTarget;
+ char* outBuff;
+ size_t outBuffSize;
+ size_t outBuffContentSize;
+ size_t outBuffFlushedSize;
+ ZSTD_cStreamStage streamStage;
+ U32 frameEnded;
+
+ /* Dictionary */
+ ZSTD_CDict* cdictLocal;
+ const ZSTD_CDict* cdict;
+ ZSTD_prefixDict prefixDict; /* single-usage dictionary */
+
+ /* Multi-threading */
+#ifdef ZSTD_MULTITHREAD
+ ZSTDMT_CCtx* mtctx;
+#endif
+};
+
+
+static const BYTE LL_Code[64] = { 0, 1, 2, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 16, 17, 17, 18, 18, 19, 19,
+ 20, 20, 20, 20, 21, 21, 21, 21,
+ 22, 22, 22, 22, 22, 22, 22, 22,
+ 23, 23, 23, 23, 23, 23, 23, 23,
+ 24, 24, 24, 24, 24, 24, 24, 24,
+ 24, 24, 24, 24, 24, 24, 24, 24 };
+
+static const BYTE ML_Code[128] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 36, 36, 37, 37, 37, 37,
+ 38, 38, 38, 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 39, 39, 39,
+ 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
+ 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42 };
+
+/*! ZSTD_storeSeq() :
+ Store a sequence (literal length, literals, offset code and match length code) into seqStore_t.
+ `offsetCode` : distance to match, or 0 == repCode.
+ `matchCode` : matchLength - MINMATCH
+*/
+MEM_STATIC void ZSTD_storeSeq(seqStore_t* seqStorePtr, size_t litLength, const void* literals, U32 offsetCode, size_t matchCode)
+{
+#if defined(ZSTD_DEBUG) && (ZSTD_DEBUG >= 6)
+ static const BYTE* g_start = NULL;
+ U32 const pos = (U32)((const BYTE*)literals - g_start);
+ if (g_start==NULL) g_start = (const BYTE*)literals;
+ if ((pos > 0) && (pos < 1000000000))
+ DEBUGLOG(6, "Cpos %6u :%5u literals & match %3u bytes at distance %6u",
+ pos, (U32)litLength, (U32)matchCode+MINMATCH, (U32)offsetCode);
+#endif
+ /* copy Literals */
+ assert(seqStorePtr->lit + litLength <= seqStorePtr->litStart + 128 KB);
+ ZSTD_wildcopy(seqStorePtr->lit, literals, litLength);
+ seqStorePtr->lit += litLength;
+
+ /* literal Length */
+ if (litLength>0xFFFF) {
+ seqStorePtr->longLengthID = 1;
+ seqStorePtr->longLengthPos = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart);
+ }
+ seqStorePtr->sequences[0].litLength = (U16)litLength;
+
+ /* match offset */
+ seqStorePtr->sequences[0].offset = offsetCode + 1;
+
+ /* match Length */
+ if (matchCode>0xFFFF) {
+ seqStorePtr->longLengthID = 2;
+ seqStorePtr->longLengthPos = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart);
+ }
+ seqStorePtr->sequences[0].matchLength = (U16)matchCode;
+
+ seqStorePtr->sequences++;
+}
+
+
+/*-*************************************
+* Match length counter
+***************************************/
+static unsigned ZSTD_NbCommonBytes (register size_t val)
+{
+ if (MEM_isLittleEndian()) {
+ if (MEM_64bits()) {
+# if defined(_MSC_VER) && defined(_WIN64)
+ unsigned long r = 0;
+ _BitScanForward64( &r, (U64)val );
+ return (unsigned)(r>>3);
+# elif defined(__GNUC__) && (__GNUC__ >= 4)
+ return (__builtin_ctzll((U64)val) >> 3);
+# else
+ static const int DeBruijnBytePos[64] = { 0, 0, 0, 0, 0, 1, 1, 2,
+ 0, 3, 1, 3, 1, 4, 2, 7,
+ 0, 2, 3, 6, 1, 5, 3, 5,
+ 1, 3, 4, 4, 2, 5, 6, 7,
+ 7, 0, 1, 2, 3, 3, 4, 6,
+ 2, 6, 5, 5, 3, 4, 5, 6,
+ 7, 1, 2, 4, 6, 4, 4, 5,
+ 7, 2, 6, 5, 7, 6, 7, 7 };
+ return DeBruijnBytePos[((U64)((val & -(long long)val) * 0x0218A392CDABBD3FULL)) >> 58];
+# endif
+ } else { /* 32 bits */
+# if defined(_MSC_VER)
+ unsigned long r=0;
+ _BitScanForward( &r, (U32)val );
+ return (unsigned)(r>>3);
+# elif defined(__GNUC__) && (__GNUC__ >= 3)
+ return (__builtin_ctz((U32)val) >> 3);
+# else
+ static const int DeBruijnBytePos[32] = { 0, 0, 3, 0, 3, 1, 3, 0,
+ 3, 2, 2, 1, 3, 2, 0, 1,
+ 3, 3, 1, 2, 2, 2, 2, 0,
+ 3, 1, 2, 0, 1, 0, 1, 1 };
+ return DeBruijnBytePos[((U32)((val & -(S32)val) * 0x077CB531U)) >> 27];
+# endif
+ }
+ } else { /* Big Endian CPU */
+ if (MEM_64bits()) {
+# if defined(_MSC_VER) && defined(_WIN64)
+ unsigned long r = 0;
+ _BitScanReverse64( &r, val );
+ return (unsigned)(r>>3);
+# elif defined(__GNUC__) && (__GNUC__ >= 4)
+ return (__builtin_clzll(val) >> 3);
+# else
+ unsigned r;
+ const unsigned n32 = sizeof(size_t)*4; /* calculate this way due to compiler complaining in 32-bits mode */
+ if (!(val>>n32)) { r=4; } else { r=0; val>>=n32; }
+ if (!(val>>16)) { r+=2; val>>=8; } else { val>>=24; }
+ r += (!val);
+ return r;
+# endif
+ } else { /* 32 bits */
+# if defined(_MSC_VER)
+ unsigned long r = 0;
+ _BitScanReverse( &r, (unsigned long)val );
+ return (unsigned)(r>>3);
+# elif defined(__GNUC__) && (__GNUC__ >= 3)
+ return (__builtin_clz((U32)val) >> 3);
+# else
+ unsigned r;
+ if (!(val>>16)) { r=2; val>>=8; } else { r=0; val>>=24; }
+ r += (!val);
+ return r;
+# endif
+ } }
+}
+
+
+MEM_STATIC size_t ZSTD_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* const pInLimit)
+{
+ const BYTE* const pStart = pIn;
+ const BYTE* const pInLoopLimit = pInLimit - (sizeof(size_t)-1);
+
+ while (pIn < pInLoopLimit) {
+ size_t const diff = MEM_readST(pMatch) ^ MEM_readST(pIn);
+ if (!diff) { pIn+=sizeof(size_t); pMatch+=sizeof(size_t); continue; }
+ pIn += ZSTD_NbCommonBytes(diff);
+ return (size_t)(pIn - pStart);
+ }
+ if (MEM_64bits()) if ((pIn<(pInLimit-3)) && (MEM_read32(pMatch) == MEM_read32(pIn))) { pIn+=4; pMatch+=4; }
+ if ((pIn<(pInLimit-1)) && (MEM_read16(pMatch) == MEM_read16(pIn))) { pIn+=2; pMatch+=2; }
+ if ((pIn<pInLimit) && (*pMatch == *pIn)) pIn++;
+ return (size_t)(pIn - pStart);
+}
+
+/** ZSTD_count_2segments() :
+* can count match length with `ip` & `match` in 2 different segments.
+* convention : on reaching mEnd, match count continue starting from iStart
+*/
+MEM_STATIC size_t ZSTD_count_2segments(const BYTE* ip, const BYTE* match, const BYTE* iEnd, const BYTE* mEnd, const BYTE* iStart)
+{
+ const BYTE* const vEnd = MIN( ip + (mEnd - match), iEnd);
+ size_t const matchLength = ZSTD_count(ip, match, vEnd);
+ if (match + matchLength != mEnd) return matchLength;
+ return matchLength + ZSTD_count(ip+matchLength, iStart, iEnd);
+}
+
+
+/*-*************************************
+* Hashes
+***************************************/
+static const U32 prime3bytes = 506832829U;
+static U32 ZSTD_hash3(U32 u, U32 h) { return ((u << (32-24)) * prime3bytes) >> (32-h) ; }
+MEM_STATIC size_t ZSTD_hash3Ptr(const void* ptr, U32 h) { return ZSTD_hash3(MEM_readLE32(ptr), h); } /* only in zstd_opt.h */
+
+static const U32 prime4bytes = 2654435761U;
+static U32 ZSTD_hash4(U32 u, U32 h) { return (u * prime4bytes) >> (32-h) ; }
+static size_t ZSTD_hash4Ptr(const void* ptr, U32 h) { return ZSTD_hash4(MEM_read32(ptr), h); }
+
+static const U64 prime5bytes = 889523592379ULL;
+static size_t ZSTD_hash5(U64 u, U32 h) { return (size_t)(((u << (64-40)) * prime5bytes) >> (64-h)) ; }
+static size_t ZSTD_hash5Ptr(const void* p, U32 h) { return ZSTD_hash5(MEM_readLE64(p), h); }
+
+static const U64 prime6bytes = 227718039650203ULL;
+static size_t ZSTD_hash6(U64 u, U32 h) { return (size_t)(((u << (64-48)) * prime6bytes) >> (64-h)) ; }
+static size_t ZSTD_hash6Ptr(const void* p, U32 h) { return ZSTD_hash6(MEM_readLE64(p), h); }
+
+static const U64 prime7bytes = 58295818150454627ULL;
+static size_t ZSTD_hash7(U64 u, U32 h) { return (size_t)(((u << (64-56)) * prime7bytes) >> (64-h)) ; }
+static size_t ZSTD_hash7Ptr(const void* p, U32 h) { return ZSTD_hash7(MEM_readLE64(p), h); }
+
+static const U64 prime8bytes = 0xCF1BBCDCB7A56463ULL;
+static size_t ZSTD_hash8(U64 u, U32 h) { return (size_t)(((u) * prime8bytes) >> (64-h)) ; }
+static size_t ZSTD_hash8Ptr(const void* p, U32 h) { return ZSTD_hash8(MEM_readLE64(p), h); }
+
+MEM_STATIC size_t ZSTD_hashPtr(const void* p, U32 hBits, U32 mls)
+{
+ switch(mls)
+ {
+ default:
+ case 4: return ZSTD_hash4Ptr(p, hBits);
+ case 5: return ZSTD_hash5Ptr(p, hBits);
+ case 6: return ZSTD_hash6Ptr(p, hBits);
+ case 7: return ZSTD_hash7Ptr(p, hBits);
+ case 8: return ZSTD_hash8Ptr(p, hBits);
+ }
+}
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* ZSTD_COMPRESS_H */
diff --git a/thirdparty/zstd/compress/zstd_double_fast.c b/thirdparty/zstd/compress/zstd_double_fast.c
new file mode 100644
index 0000000000..876a36042c
--- /dev/null
+++ b/thirdparty/zstd/compress/zstd_double_fast.c
@@ -0,0 +1,308 @@
+/*
+ * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under both the BSD-style license (found in the
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
+ * in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
+ */
+
+#include "zstd_double_fast.h"
+
+
+void ZSTD_fillDoubleHashTable(ZSTD_CCtx* cctx, const void* end, const U32 mls)
+{
+ U32* const hashLarge = cctx->hashTable;
+ U32 const hBitsL = cctx->appliedParams.cParams.hashLog;
+ U32* const hashSmall = cctx->chainTable;
+ U32 const hBitsS = cctx->appliedParams.cParams.chainLog;
+ const BYTE* const base = cctx->base;
+ const BYTE* ip = base + cctx->nextToUpdate;
+ const BYTE* const iend = ((const BYTE*)end) - HASH_READ_SIZE;
+ const size_t fastHashFillStep = 3;
+
+ while(ip <= iend) {
+ hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = (U32)(ip - base);
+ hashLarge[ZSTD_hashPtr(ip, hBitsL, 8)] = (U32)(ip - base);
+ ip += fastHashFillStep;
+ }
+}
+
+
+FORCE_INLINE_TEMPLATE
+size_t ZSTD_compressBlock_doubleFast_generic(ZSTD_CCtx* cctx,
+ const void* src, size_t srcSize,
+ const U32 mls)
+{
+ U32* const hashLong = cctx->hashTable;
+ const U32 hBitsL = cctx->appliedParams.cParams.hashLog;
+ U32* const hashSmall = cctx->chainTable;
+ const U32 hBitsS = cctx->appliedParams.cParams.chainLog;
+ seqStore_t* seqStorePtr = &(cctx->seqStore);
+ const BYTE* const base = cctx->base;
+ const BYTE* const istart = (const BYTE*)src;
+ const BYTE* ip = istart;
+ const BYTE* anchor = istart;
+ const U32 lowestIndex = cctx->dictLimit;
+ const BYTE* const lowest = base + lowestIndex;
+ const BYTE* const iend = istart + srcSize;
+ const BYTE* const ilimit = iend - HASH_READ_SIZE;
+ U32 offset_1=seqStorePtr->rep[0], offset_2=seqStorePtr->rep[1];
+ U32 offsetSaved = 0;
+
+ /* init */
+ ip += (ip==lowest);
+ { U32 const maxRep = (U32)(ip-lowest);
+ if (offset_2 > maxRep) offsetSaved = offset_2, offset_2 = 0;
+ if (offset_1 > maxRep) offsetSaved = offset_1, offset_1 = 0;
+ }
+
+ /* Main Search Loop */
+ while (ip < ilimit) { /* < instead of <=, because repcode check at (ip+1) */
+ size_t mLength;
+ size_t const h2 = ZSTD_hashPtr(ip, hBitsL, 8);
+ size_t const h = ZSTD_hashPtr(ip, hBitsS, mls);
+ U32 const current = (U32)(ip-base);
+ U32 const matchIndexL = hashLong[h2];
+ U32 const matchIndexS = hashSmall[h];
+ const BYTE* matchLong = base + matchIndexL;
+ const BYTE* match = base + matchIndexS;
+ hashLong[h2] = hashSmall[h] = current; /* update hash tables */
+
+ assert(offset_1 <= current); /* supposed guaranteed by construction */
+ if ((offset_1 > 0) & (MEM_read32(ip+1-offset_1) == MEM_read32(ip+1))) {
+ /* favor repcode */
+ mLength = ZSTD_count(ip+1+4, ip+1+4-offset_1, iend) + 4;
+ ip++;
+ ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, 0, mLength-MINMATCH);
+ } else {
+ U32 offset;
+ if ( (matchIndexL > lowestIndex) && (MEM_read64(matchLong) == MEM_read64(ip)) ) {
+ mLength = ZSTD_count(ip+8, matchLong+8, iend) + 8;
+ offset = (U32)(ip-matchLong);
+ while (((ip>anchor) & (matchLong>lowest)) && (ip[-1] == matchLong[-1])) { ip--; matchLong--; mLength++; } /* catch up */
+ } else if ( (matchIndexS > lowestIndex) && (MEM_read32(match) == MEM_read32(ip)) ) {
+ size_t const hl3 = ZSTD_hashPtr(ip+1, hBitsL, 8);
+ U32 const matchIndexL3 = hashLong[hl3];
+ const BYTE* matchL3 = base + matchIndexL3;
+ hashLong[hl3] = current + 1;
+ if ( (matchIndexL3 > lowestIndex) && (MEM_read64(matchL3) == MEM_read64(ip+1)) ) {
+ mLength = ZSTD_count(ip+9, matchL3+8, iend) + 8;
+ ip++;
+ offset = (U32)(ip-matchL3);
+ while (((ip>anchor) & (matchL3>lowest)) && (ip[-1] == matchL3[-1])) { ip--; matchL3--; mLength++; } /* catch up */
+ } else {
+ mLength = ZSTD_count(ip+4, match+4, iend) + 4;
+ offset = (U32)(ip-match);
+ while (((ip>anchor) & (match>lowest)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */
+ }
+ } else {
+ ip += ((ip-anchor) >> g_searchStrength) + 1;
+ continue;
+ }
+
+ offset_2 = offset_1;
+ offset_1 = offset;
+
+ ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
+ }
+
+ /* match found */
+ ip += mLength;
+ anchor = ip;
+
+ if (ip <= ilimit) {
+ /* Fill Table */
+ hashLong[ZSTD_hashPtr(base+current+2, hBitsL, 8)] =
+ hashSmall[ZSTD_hashPtr(base+current+2, hBitsS, mls)] = current+2; /* here because current+2 could be > iend-8 */
+ hashLong[ZSTD_hashPtr(ip-2, hBitsL, 8)] =
+ hashSmall[ZSTD_hashPtr(ip-2, hBitsS, mls)] = (U32)(ip-2-base);
+
+ /* check immediate repcode */
+ while ( (ip <= ilimit)
+ && ( (offset_2>0)
+ & (MEM_read32(ip) == MEM_read32(ip - offset_2)) )) {
+ /* store sequence */
+ size_t const rLength = ZSTD_count(ip+4, ip+4-offset_2, iend) + 4;
+ { U32 const tmpOff = offset_2; offset_2 = offset_1; offset_1 = tmpOff; } /* swap offset_2 <=> offset_1 */
+ hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = (U32)(ip-base);
+ hashLong[ZSTD_hashPtr(ip, hBitsL, 8)] = (U32)(ip-base);
+ ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, rLength-MINMATCH);
+ ip += rLength;
+ anchor = ip;
+ continue; /* faster when present ... (?) */
+ } } }
+
+ /* save reps for next block */
+ seqStorePtr->repToConfirm[0] = offset_1 ? offset_1 : offsetSaved;
+ seqStorePtr->repToConfirm[1] = offset_2 ? offset_2 : offsetSaved;
+
+ /* Return the last literals size */
+ return iend - anchor;
+}
+
+
+size_t ZSTD_compressBlock_doubleFast(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
+{
+ const U32 mls = ctx->appliedParams.cParams.searchLength;
+ switch(mls)
+ {
+ default: /* includes case 3 */
+ case 4 :
+ return ZSTD_compressBlock_doubleFast_generic(ctx, src, srcSize, 4);
+ case 5 :
+ return ZSTD_compressBlock_doubleFast_generic(ctx, src, srcSize, 5);
+ case 6 :
+ return ZSTD_compressBlock_doubleFast_generic(ctx, src, srcSize, 6);
+ case 7 :
+ return ZSTD_compressBlock_doubleFast_generic(ctx, src, srcSize, 7);
+ }
+}
+
+
+static size_t ZSTD_compressBlock_doubleFast_extDict_generic(ZSTD_CCtx* ctx,
+ const void* src, size_t srcSize,
+ const U32 mls)
+{
+ U32* const hashLong = ctx->hashTable;
+ U32 const hBitsL = ctx->appliedParams.cParams.hashLog;
+ U32* const hashSmall = ctx->chainTable;
+ U32 const hBitsS = ctx->appliedParams.cParams.chainLog;
+ seqStore_t* seqStorePtr = &(ctx->seqStore);
+ const BYTE* const base = ctx->base;
+ const BYTE* const dictBase = ctx->dictBase;
+ const BYTE* const istart = (const BYTE*)src;
+ const BYTE* ip = istart;
+ const BYTE* anchor = istart;
+ const U32 lowestIndex = ctx->lowLimit;
+ const BYTE* const dictStart = dictBase + lowestIndex;
+ const U32 dictLimit = ctx->dictLimit;
+ const BYTE* const lowPrefixPtr = base + dictLimit;
+ const BYTE* const dictEnd = dictBase + dictLimit;
+ const BYTE* const iend = istart + srcSize;
+ const BYTE* const ilimit = iend - 8;
+ U32 offset_1=seqStorePtr->rep[0], offset_2=seqStorePtr->rep[1];
+
+ /* Search Loop */
+ while (ip < ilimit) { /* < instead of <=, because (ip+1) */
+ const size_t hSmall = ZSTD_hashPtr(ip, hBitsS, mls);
+ const U32 matchIndex = hashSmall[hSmall];
+ const BYTE* matchBase = matchIndex < dictLimit ? dictBase : base;
+ const BYTE* match = matchBase + matchIndex;
+
+ const size_t hLong = ZSTD_hashPtr(ip, hBitsL, 8);
+ const U32 matchLongIndex = hashLong[hLong];
+ const BYTE* matchLongBase = matchLongIndex < dictLimit ? dictBase : base;
+ const BYTE* matchLong = matchLongBase + matchLongIndex;
+
+ const U32 current = (U32)(ip-base);
+ const U32 repIndex = current + 1 - offset_1; /* offset_1 expected <= current +1 */
+ const BYTE* repBase = repIndex < dictLimit ? dictBase : base;
+ const BYTE* repMatch = repBase + repIndex;
+ size_t mLength;
+ hashSmall[hSmall] = hashLong[hLong] = current; /* update hash table */
+
+ if ( (((U32)((dictLimit-1) - repIndex) >= 3) /* intentional underflow */ & (repIndex > lowestIndex))
+ && (MEM_read32(repMatch) == MEM_read32(ip+1)) ) {
+ const BYTE* repMatchEnd = repIndex < dictLimit ? dictEnd : iend;
+ mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, lowPrefixPtr) + 4;
+ ip++;
+ ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, 0, mLength-MINMATCH);
+ } else {
+ if ((matchLongIndex > lowestIndex) && (MEM_read64(matchLong) == MEM_read64(ip))) {
+ const BYTE* matchEnd = matchLongIndex < dictLimit ? dictEnd : iend;
+ const BYTE* lowMatchPtr = matchLongIndex < dictLimit ? dictStart : lowPrefixPtr;
+ U32 offset;
+ mLength = ZSTD_count_2segments(ip+8, matchLong+8, iend, matchEnd, lowPrefixPtr) + 8;
+ offset = current - matchLongIndex;
+ while (((ip>anchor) & (matchLong>lowMatchPtr)) && (ip[-1] == matchLong[-1])) { ip--; matchLong--; mLength++; } /* catch up */
+ offset_2 = offset_1;
+ offset_1 = offset;
+ ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
+
+ } else if ((matchIndex > lowestIndex) && (MEM_read32(match) == MEM_read32(ip))) {
+ size_t const h3 = ZSTD_hashPtr(ip+1, hBitsL, 8);
+ U32 const matchIndex3 = hashLong[h3];
+ const BYTE* const match3Base = matchIndex3 < dictLimit ? dictBase : base;
+ const BYTE* match3 = match3Base + matchIndex3;
+ U32 offset;
+ hashLong[h3] = current + 1;
+ if ( (matchIndex3 > lowestIndex) && (MEM_read64(match3) == MEM_read64(ip+1)) ) {
+ const BYTE* matchEnd = matchIndex3 < dictLimit ? dictEnd : iend;
+ const BYTE* lowMatchPtr = matchIndex3 < dictLimit ? dictStart : lowPrefixPtr;
+ mLength = ZSTD_count_2segments(ip+9, match3+8, iend, matchEnd, lowPrefixPtr) + 8;
+ ip++;
+ offset = current+1 - matchIndex3;
+ while (((ip>anchor) & (match3>lowMatchPtr)) && (ip[-1] == match3[-1])) { ip--; match3--; mLength++; } /* catch up */
+ } else {
+ const BYTE* matchEnd = matchIndex < dictLimit ? dictEnd : iend;
+ const BYTE* lowMatchPtr = matchIndex < dictLimit ? dictStart : lowPrefixPtr;
+ mLength = ZSTD_count_2segments(ip+4, match+4, iend, matchEnd, lowPrefixPtr) + 4;
+ offset = current - matchIndex;
+ while (((ip>anchor) & (match>lowMatchPtr)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */
+ }
+ offset_2 = offset_1;
+ offset_1 = offset;
+ ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
+
+ } else {
+ ip += ((ip-anchor) >> g_searchStrength) + 1;
+ continue;
+ } }
+
+ /* found a match : store it */
+ ip += mLength;
+ anchor = ip;
+
+ if (ip <= ilimit) {
+ /* Fill Table */
+ hashSmall[ZSTD_hashPtr(base+current+2, hBitsS, mls)] = current+2;
+ hashLong[ZSTD_hashPtr(base+current+2, hBitsL, 8)] = current+2;
+ hashSmall[ZSTD_hashPtr(ip-2, hBitsS, mls)] = (U32)(ip-2-base);
+ hashLong[ZSTD_hashPtr(ip-2, hBitsL, 8)] = (U32)(ip-2-base);
+ /* check immediate repcode */
+ while (ip <= ilimit) {
+ U32 const current2 = (U32)(ip-base);
+ U32 const repIndex2 = current2 - offset_2;
+ const BYTE* repMatch2 = repIndex2 < dictLimit ? dictBase + repIndex2 : base + repIndex2;
+ if ( (((U32)((dictLimit-1) - repIndex2) >= 3) & (repIndex2 > lowestIndex)) /* intentional overflow */
+ && (MEM_read32(repMatch2) == MEM_read32(ip)) ) {
+ const BYTE* const repEnd2 = repIndex2 < dictLimit ? dictEnd : iend;
+ size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, lowPrefixPtr) + 4;
+ U32 tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; /* swap offset_2 <=> offset_1 */
+ ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, repLength2-MINMATCH);
+ hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = current2;
+ hashLong[ZSTD_hashPtr(ip, hBitsL, 8)] = current2;
+ ip += repLength2;
+ anchor = ip;
+ continue;
+ }
+ break;
+ } } }
+
+ /* save reps for next block */
+ seqStorePtr->repToConfirm[0] = offset_1; seqStorePtr->repToConfirm[1] = offset_2;
+
+ /* Return the last literals size */
+ return iend - anchor;
+}
+
+
+size_t ZSTD_compressBlock_doubleFast_extDict(ZSTD_CCtx* ctx,
+ const void* src, size_t srcSize)
+{
+ U32 const mls = ctx->appliedParams.cParams.searchLength;
+ switch(mls)
+ {
+ default: /* includes case 3 */
+ case 4 :
+ return ZSTD_compressBlock_doubleFast_extDict_generic(ctx, src, srcSize, 4);
+ case 5 :
+ return ZSTD_compressBlock_doubleFast_extDict_generic(ctx, src, srcSize, 5);
+ case 6 :
+ return ZSTD_compressBlock_doubleFast_extDict_generic(ctx, src, srcSize, 6);
+ case 7 :
+ return ZSTD_compressBlock_doubleFast_extDict_generic(ctx, src, srcSize, 7);
+ }
+}
diff --git a/thirdparty/zstd/compress/zstd_double_fast.h b/thirdparty/zstd/compress/zstd_double_fast.h
new file mode 100644
index 0000000000..3dba6c7108
--- /dev/null
+++ b/thirdparty/zstd/compress/zstd_double_fast.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under both the BSD-style license (found in the
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
+ * in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
+ */
+
+#ifndef ZSTD_DOUBLE_FAST_H
+#define ZSTD_DOUBLE_FAST_H
+
+#include "zstd_compress.h"
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+void ZSTD_fillDoubleHashTable(ZSTD_CCtx* cctx, const void* end, const U32 mls);
+size_t ZSTD_compressBlock_doubleFast(ZSTD_CCtx* ctx, const void* src, size_t srcSize);
+size_t ZSTD_compressBlock_doubleFast_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* ZSTD_DOUBLE_FAST_H */
diff --git a/thirdparty/zstd/compress/zstd_fast.c b/thirdparty/zstd/compress/zstd_fast.c
new file mode 100644
index 0000000000..2e057017b9
--- /dev/null
+++ b/thirdparty/zstd/compress/zstd_fast.c
@@ -0,0 +1,242 @@
+/*
+ * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under both the BSD-style license (found in the
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
+ * in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
+ */
+
+#include "zstd_fast.h"
+
+
+void ZSTD_fillHashTable (ZSTD_CCtx* zc, const void* end, const U32 mls)
+{
+ U32* const hashTable = zc->hashTable;
+ U32 const hBits = zc->appliedParams.cParams.hashLog;
+ const BYTE* const base = zc->base;
+ const BYTE* ip = base + zc->nextToUpdate;
+ const BYTE* const iend = ((const BYTE*)end) - HASH_READ_SIZE;
+ const size_t fastHashFillStep = 3;
+
+ while(ip <= iend) {
+ hashTable[ZSTD_hashPtr(ip, hBits, mls)] = (U32)(ip - base);
+ ip += fastHashFillStep;
+ }
+}
+
+
+FORCE_INLINE_TEMPLATE
+size_t ZSTD_compressBlock_fast_generic(ZSTD_CCtx* cctx,
+ const void* src, size_t srcSize,
+ const U32 mls)
+{
+ U32* const hashTable = cctx->hashTable;
+ U32 const hBits = cctx->appliedParams.cParams.hashLog;
+ seqStore_t* seqStorePtr = &(cctx->seqStore);
+ const BYTE* const base = cctx->base;
+ const BYTE* const istart = (const BYTE*)src;
+ const BYTE* ip = istart;
+ const BYTE* anchor = istart;
+ const U32 lowestIndex = cctx->dictLimit;
+ const BYTE* const lowest = base + lowestIndex;
+ const BYTE* const iend = istart + srcSize;
+ const BYTE* const ilimit = iend - HASH_READ_SIZE;
+ U32 offset_1=seqStorePtr->rep[0], offset_2=seqStorePtr->rep[1];
+ U32 offsetSaved = 0;
+
+ /* init */
+ ip += (ip==lowest);
+ { U32 const maxRep = (U32)(ip-lowest);
+ if (offset_2 > maxRep) offsetSaved = offset_2, offset_2 = 0;
+ if (offset_1 > maxRep) offsetSaved = offset_1, offset_1 = 0;
+ }
+
+ /* Main Search Loop */
+ while (ip < ilimit) { /* < instead of <=, because repcode check at (ip+1) */
+ size_t mLength;
+ size_t const h = ZSTD_hashPtr(ip, hBits, mls);
+ U32 const current = (U32)(ip-base);
+ U32 const matchIndex = hashTable[h];
+ const BYTE* match = base + matchIndex;
+ hashTable[h] = current; /* update hash table */
+
+ if ((offset_1 > 0) & (MEM_read32(ip+1-offset_1) == MEM_read32(ip+1))) {
+ mLength = ZSTD_count(ip+1+4, ip+1+4-offset_1, iend) + 4;
+ ip++;
+ ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, 0, mLength-MINMATCH);
+ } else {
+ U32 offset;
+ if ( (matchIndex <= lowestIndex) || (MEM_read32(match) != MEM_read32(ip)) ) {
+ ip += ((ip-anchor) >> g_searchStrength) + 1;
+ continue;
+ }
+ mLength = ZSTD_count(ip+4, match+4, iend) + 4;
+ offset = (U32)(ip-match);
+ while (((ip>anchor) & (match>lowest)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */
+ offset_2 = offset_1;
+ offset_1 = offset;
+
+ ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
+ }
+
+ /* match found */
+ ip += mLength;
+ anchor = ip;
+
+ if (ip <= ilimit) {
+ /* Fill Table */
+ hashTable[ZSTD_hashPtr(base+current+2, hBits, mls)] = current+2; /* here because current+2 could be > iend-8 */
+ hashTable[ZSTD_hashPtr(ip-2, hBits, mls)] = (U32)(ip-2-base);
+ /* check immediate repcode */
+ while ( (ip <= ilimit)
+ && ( (offset_2>0)
+ & (MEM_read32(ip) == MEM_read32(ip - offset_2)) )) {
+ /* store sequence */
+ size_t const rLength = ZSTD_count(ip+4, ip+4-offset_2, iend) + 4;
+ { U32 const tmpOff = offset_2; offset_2 = offset_1; offset_1 = tmpOff; } /* swap offset_2 <=> offset_1 */
+ hashTable[ZSTD_hashPtr(ip, hBits, mls)] = (U32)(ip-base);
+ ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, rLength-MINMATCH);
+ ip += rLength;
+ anchor = ip;
+ continue; /* faster when present ... (?) */
+ } } }
+
+ /* save reps for next block */
+ seqStorePtr->repToConfirm[0] = offset_1 ? offset_1 : offsetSaved;
+ seqStorePtr->repToConfirm[1] = offset_2 ? offset_2 : offsetSaved;
+
+ /* Return the last literals size */
+ return iend - anchor;
+}
+
+
+size_t ZSTD_compressBlock_fast(ZSTD_CCtx* ctx,
+ const void* src, size_t srcSize)
+{
+ const U32 mls = ctx->appliedParams.cParams.searchLength;
+ switch(mls)
+ {
+ default: /* includes case 3 */
+ case 4 :
+ return ZSTD_compressBlock_fast_generic(ctx, src, srcSize, 4);
+ case 5 :
+ return ZSTD_compressBlock_fast_generic(ctx, src, srcSize, 5);
+ case 6 :
+ return ZSTD_compressBlock_fast_generic(ctx, src, srcSize, 6);
+ case 7 :
+ return ZSTD_compressBlock_fast_generic(ctx, src, srcSize, 7);
+ }
+}
+
+
+static size_t ZSTD_compressBlock_fast_extDict_generic(ZSTD_CCtx* ctx,
+ const void* src, size_t srcSize,
+ const U32 mls)
+{
+ U32* hashTable = ctx->hashTable;
+ const U32 hBits = ctx->appliedParams.cParams.hashLog;
+ seqStore_t* seqStorePtr = &(ctx->seqStore);
+ const BYTE* const base = ctx->base;
+ const BYTE* const dictBase = ctx->dictBase;
+ const BYTE* const istart = (const BYTE*)src;
+ const BYTE* ip = istart;
+ const BYTE* anchor = istart;
+ const U32 lowestIndex = ctx->lowLimit;
+ const BYTE* const dictStart = dictBase + lowestIndex;
+ const U32 dictLimit = ctx->dictLimit;
+ const BYTE* const lowPrefixPtr = base + dictLimit;
+ const BYTE* const dictEnd = dictBase + dictLimit;
+ const BYTE* const iend = istart + srcSize;
+ const BYTE* const ilimit = iend - 8;
+ U32 offset_1=seqStorePtr->rep[0], offset_2=seqStorePtr->rep[1];
+
+ /* Search Loop */
+ while (ip < ilimit) { /* < instead of <=, because (ip+1) */
+ const size_t h = ZSTD_hashPtr(ip, hBits, mls);
+ const U32 matchIndex = hashTable[h];
+ const BYTE* matchBase = matchIndex < dictLimit ? dictBase : base;
+ const BYTE* match = matchBase + matchIndex;
+ const U32 current = (U32)(ip-base);
+ const U32 repIndex = current + 1 - offset_1; /* offset_1 expected <= current +1 */
+ const BYTE* repBase = repIndex < dictLimit ? dictBase : base;
+ const BYTE* repMatch = repBase + repIndex;
+ size_t mLength;
+ hashTable[h] = current; /* update hash table */
+
+ if ( (((U32)((dictLimit-1) - repIndex) >= 3) /* intentional underflow */ & (repIndex > lowestIndex))
+ && (MEM_read32(repMatch) == MEM_read32(ip+1)) ) {
+ const BYTE* repMatchEnd = repIndex < dictLimit ? dictEnd : iend;
+ mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, lowPrefixPtr) + 4;
+ ip++;
+ ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, 0, mLength-MINMATCH);
+ } else {
+ if ( (matchIndex < lowestIndex) ||
+ (MEM_read32(match) != MEM_read32(ip)) ) {
+ ip += ((ip-anchor) >> g_searchStrength) + 1;
+ continue;
+ }
+ { const BYTE* matchEnd = matchIndex < dictLimit ? dictEnd : iend;
+ const BYTE* lowMatchPtr = matchIndex < dictLimit ? dictStart : lowPrefixPtr;
+ U32 offset;
+ mLength = ZSTD_count_2segments(ip+4, match+4, iend, matchEnd, lowPrefixPtr) + 4;
+ while (((ip>anchor) & (match>lowMatchPtr)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */
+ offset = current - matchIndex;
+ offset_2 = offset_1;
+ offset_1 = offset;
+ ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
+ } }
+
+ /* found a match : store it */
+ ip += mLength;
+ anchor = ip;
+
+ if (ip <= ilimit) {
+ /* Fill Table */
+ hashTable[ZSTD_hashPtr(base+current+2, hBits, mls)] = current+2;
+ hashTable[ZSTD_hashPtr(ip-2, hBits, mls)] = (U32)(ip-2-base);
+ /* check immediate repcode */
+ while (ip <= ilimit) {
+ U32 const current2 = (U32)(ip-base);
+ U32 const repIndex2 = current2 - offset_2;
+ const BYTE* repMatch2 = repIndex2 < dictLimit ? dictBase + repIndex2 : base + repIndex2;
+ if ( (((U32)((dictLimit-1) - repIndex2) >= 3) & (repIndex2 > lowestIndex)) /* intentional overflow */
+ && (MEM_read32(repMatch2) == MEM_read32(ip)) ) {
+ const BYTE* const repEnd2 = repIndex2 < dictLimit ? dictEnd : iend;
+ size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, lowPrefixPtr) + 4;
+ U32 tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; /* swap offset_2 <=> offset_1 */
+ ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, repLength2-MINMATCH);
+ hashTable[ZSTD_hashPtr(ip, hBits, mls)] = current2;
+ ip += repLength2;
+ anchor = ip;
+ continue;
+ }
+ break;
+ } } }
+
+ /* save reps for next block */
+ seqStorePtr->repToConfirm[0] = offset_1; seqStorePtr->repToConfirm[1] = offset_2;
+
+ /* Return the last literals size */
+ return iend - anchor;
+}
+
+
+size_t ZSTD_compressBlock_fast_extDict(ZSTD_CCtx* ctx,
+ const void* src, size_t srcSize)
+{
+ U32 const mls = ctx->appliedParams.cParams.searchLength;
+ switch(mls)
+ {
+ default: /* includes case 3 */
+ case 4 :
+ return ZSTD_compressBlock_fast_extDict_generic(ctx, src, srcSize, 4);
+ case 5 :
+ return ZSTD_compressBlock_fast_extDict_generic(ctx, src, srcSize, 5);
+ case 6 :
+ return ZSTD_compressBlock_fast_extDict_generic(ctx, src, srcSize, 6);
+ case 7 :
+ return ZSTD_compressBlock_fast_extDict_generic(ctx, src, srcSize, 7);
+ }
+}
diff --git a/thirdparty/zstd/compress/zstd_fast.h b/thirdparty/zstd/compress/zstd_fast.h
new file mode 100644
index 0000000000..4205141a9a
--- /dev/null
+++ b/thirdparty/zstd/compress/zstd_fast.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under both the BSD-style license (found in the
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
+ * in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
+ */
+
+#ifndef ZSTD_FAST_H
+#define ZSTD_FAST_H
+
+#include "zstd_compress.h"
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+void ZSTD_fillHashTable(ZSTD_CCtx* zc, const void* end, const U32 mls);
+size_t ZSTD_compressBlock_fast(ZSTD_CCtx* ctx,
+ const void* src, size_t srcSize);
+size_t ZSTD_compressBlock_fast_extDict(ZSTD_CCtx* ctx,
+ const void* src, size_t srcSize);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* ZSTD_FAST_H */
diff --git a/thirdparty/zstd/compress/zstd_lazy.c b/thirdparty/zstd/compress/zstd_lazy.c
new file mode 100644
index 0000000000..2a7f6a0fe2
--- /dev/null
+++ b/thirdparty/zstd/compress/zstd_lazy.c
@@ -0,0 +1,749 @@
+/*
+ * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under both the BSD-style license (found in the
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
+ * in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
+ */
+
+#include "zstd_lazy.h"
+
+
+/*-*************************************
+* Binary Tree search
+***************************************/
+/** ZSTD_insertBt1() : add one or multiple positions to tree.
+* ip : assumed <= iend-8 .
+* @return : nb of positions added */
+static U32 ZSTD_insertBt1(ZSTD_CCtx* zc, const BYTE* const ip, const U32 mls, const BYTE* const iend, U32 nbCompares,
+ U32 extDict)
+{
+ U32* const hashTable = zc->hashTable;
+ U32 const hashLog = zc->appliedParams.cParams.hashLog;
+ size_t const h = ZSTD_hashPtr(ip, hashLog, mls);
+ U32* const bt = zc->chainTable;
+ U32 const btLog = zc->appliedParams.cParams.chainLog - 1;
+ U32 const btMask = (1 << btLog) - 1;
+ U32 matchIndex = hashTable[h];
+ size_t commonLengthSmaller=0, commonLengthLarger=0;
+ const BYTE* const base = zc->base;
+ const BYTE* const dictBase = zc->dictBase;
+ const U32 dictLimit = zc->dictLimit;
+ const BYTE* const dictEnd = dictBase + dictLimit;
+ const BYTE* const prefixStart = base + dictLimit;
+ const BYTE* match;
+ const U32 current = (U32)(ip-base);
+ const U32 btLow = btMask >= current ? 0 : current - btMask;
+ U32* smallerPtr = bt + 2*(current&btMask);
+ U32* largerPtr = smallerPtr + 1;
+ U32 dummy32; /* to be nullified at the end */
+ U32 const windowLow = zc->lowLimit;
+ U32 matchEndIdx = current+8;
+ size_t bestLength = 8;
+#ifdef ZSTD_C_PREDICT
+ U32 predictedSmall = *(bt + 2*((current-1)&btMask) + 0);
+ U32 predictedLarge = *(bt + 2*((current-1)&btMask) + 1);
+ predictedSmall += (predictedSmall>0);
+ predictedLarge += (predictedLarge>0);
+#endif /* ZSTD_C_PREDICT */
+
+ assert(ip <= iend-8); /* required for h calculation */
+ hashTable[h] = current; /* Update Hash Table */
+
+ while (nbCompares-- && (matchIndex > windowLow)) {
+ U32* const nextPtr = bt + 2*(matchIndex & btMask);
+ size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
+
+#ifdef ZSTD_C_PREDICT /* note : can create issues when hlog small <= 11 */
+ const U32* predictPtr = bt + 2*((matchIndex-1) & btMask); /* written this way, as bt is a roll buffer */
+ if (matchIndex == predictedSmall) {
+ /* no need to check length, result known */
+ *smallerPtr = matchIndex;
+ if (matchIndex <= btLow) { smallerPtr=&dummy32; break; } /* beyond tree size, stop the search */
+ smallerPtr = nextPtr+1; /* new "smaller" => larger of match */
+ matchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */
+ predictedSmall = predictPtr[1] + (predictPtr[1]>0);
+ continue;
+ }
+ if (matchIndex == predictedLarge) {
+ *largerPtr = matchIndex;
+ if (matchIndex <= btLow) { largerPtr=&dummy32; break; } /* beyond tree size, stop the search */
+ largerPtr = nextPtr;
+ matchIndex = nextPtr[0];
+ predictedLarge = predictPtr[0] + (predictPtr[0]>0);
+ continue;
+ }
+#endif
+ if ((!extDict) || (matchIndex+matchLength >= dictLimit)) {
+ match = base + matchIndex;
+ if (match[matchLength] == ip[matchLength])
+ matchLength += ZSTD_count(ip+matchLength+1, match+matchLength+1, iend) +1;
+ } else {
+ match = dictBase + matchIndex;
+ matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iend, dictEnd, prefixStart);
+ if (matchIndex+matchLength >= dictLimit)
+ match = base + matchIndex; /* to prepare for next usage of match[matchLength] */
+ }
+
+ if (matchLength > bestLength) {
+ bestLength = matchLength;
+ if (matchLength > matchEndIdx - matchIndex)
+ matchEndIdx = matchIndex + (U32)matchLength;
+ }
+
+ if (ip+matchLength == iend) /* equal : no way to know if inf or sup */
+ break; /* drop , to guarantee consistency ; miss a bit of compression, but other solutions can corrupt tree */
+
+ if (match[matchLength] < ip[matchLength]) { /* necessarily within buffer */
+ /* match+1 is smaller than current */
+ *smallerPtr = matchIndex; /* update smaller idx */
+ commonLengthSmaller = matchLength; /* all smaller will now have at least this guaranteed common length */
+ if (matchIndex <= btLow) { smallerPtr=&dummy32; break; } /* beyond tree size, stop searching */
+ smallerPtr = nextPtr+1; /* new "smaller" => larger of match */
+ matchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */
+ } else {
+ /* match is larger than current */
+ *largerPtr = matchIndex;
+ commonLengthLarger = matchLength;
+ if (matchIndex <= btLow) { largerPtr=&dummy32; break; } /* beyond tree size, stop searching */
+ largerPtr = nextPtr;
+ matchIndex = nextPtr[0];
+ } }
+
+ *smallerPtr = *largerPtr = 0;
+ if (bestLength > 384) return MIN(192, (U32)(bestLength - 384)); /* speed optimization */
+ if (matchEndIdx > current + 8) return matchEndIdx - (current + 8);
+ return 1;
+}
+
+
+static size_t ZSTD_insertBtAndFindBestMatch (
+ ZSTD_CCtx* zc,
+ const BYTE* const ip, const BYTE* const iend,
+ size_t* offsetPtr,
+ U32 nbCompares, const U32 mls,
+ U32 extDict)
+{
+ U32* const hashTable = zc->hashTable;
+ U32 const hashLog = zc->appliedParams.cParams.hashLog;
+ size_t const h = ZSTD_hashPtr(ip, hashLog, mls);
+ U32* const bt = zc->chainTable;
+ U32 const btLog = zc->appliedParams.cParams.chainLog - 1;
+ U32 const btMask = (1 << btLog) - 1;
+ U32 matchIndex = hashTable[h];
+ size_t commonLengthSmaller=0, commonLengthLarger=0;
+ const BYTE* const base = zc->base;
+ const BYTE* const dictBase = zc->dictBase;
+ const U32 dictLimit = zc->dictLimit;
+ const BYTE* const dictEnd = dictBase + dictLimit;
+ const BYTE* const prefixStart = base + dictLimit;
+ const U32 current = (U32)(ip-base);
+ const U32 btLow = btMask >= current ? 0 : current - btMask;
+ const U32 windowLow = zc->lowLimit;
+ U32* smallerPtr = bt + 2*(current&btMask);
+ U32* largerPtr = bt + 2*(current&btMask) + 1;
+ U32 matchEndIdx = current+8;
+ U32 dummy32; /* to be nullified at the end */
+ size_t bestLength = 0;
+
+ assert(ip <= iend-8); /* required for h calculation */
+ hashTable[h] = current; /* Update Hash Table */
+
+ while (nbCompares-- && (matchIndex > windowLow)) {
+ U32* const nextPtr = bt + 2*(matchIndex & btMask);
+ size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
+ const BYTE* match;
+
+ if ((!extDict) || (matchIndex+matchLength >= dictLimit)) {
+ match = base + matchIndex;
+ if (match[matchLength] == ip[matchLength])
+ matchLength += ZSTD_count(ip+matchLength+1, match+matchLength+1, iend) +1;
+ } else {
+ match = dictBase + matchIndex;
+ matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iend, dictEnd, prefixStart);
+ if (matchIndex+matchLength >= dictLimit)
+ match = base + matchIndex; /* to prepare for next usage of match[matchLength] */
+ }
+
+ if (matchLength > bestLength) {
+ if (matchLength > matchEndIdx - matchIndex)
+ matchEndIdx = matchIndex + (U32)matchLength;
+ if ( (4*(int)(matchLength-bestLength)) > (int)(ZSTD_highbit32(current-matchIndex+1) - ZSTD_highbit32((U32)offsetPtr[0]+1)) )
+ bestLength = matchLength, *offsetPtr = ZSTD_REP_MOVE + current - matchIndex;
+ if (ip+matchLength == iend) /* equal : no way to know if inf or sup */
+ break; /* drop, to guarantee consistency (miss a little bit of compression) */
+ }
+
+ if (match[matchLength] < ip[matchLength]) {
+ /* match is smaller than current */
+ *smallerPtr = matchIndex; /* update smaller idx */
+ commonLengthSmaller = matchLength; /* all smaller will now have at least this guaranteed common length */
+ if (matchIndex <= btLow) { smallerPtr=&dummy32; break; } /* beyond tree size, stop the search */
+ smallerPtr = nextPtr+1; /* new "smaller" => larger of match */
+ matchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */
+ } else {
+ /* match is larger than current */
+ *largerPtr = matchIndex;
+ commonLengthLarger = matchLength;
+ if (matchIndex <= btLow) { largerPtr=&dummy32; break; } /* beyond tree size, stop the search */
+ largerPtr = nextPtr;
+ matchIndex = nextPtr[0];
+ } }
+
+ *smallerPtr = *largerPtr = 0;
+
+ zc->nextToUpdate = (matchEndIdx > current + 8) ? matchEndIdx - 8 : current+1;
+ return bestLength;
+}
+
+
+void ZSTD_updateTree(ZSTD_CCtx* zc, const BYTE* const ip, const BYTE* const iend, const U32 nbCompares, const U32 mls)
+{
+ const BYTE* const base = zc->base;
+ const U32 target = (U32)(ip - base);
+ U32 idx = zc->nextToUpdate;
+
+ while(idx < target)
+ idx += ZSTD_insertBt1(zc, base+idx, mls, iend, nbCompares, 0);
+}
+
+/** ZSTD_BtFindBestMatch() : Tree updater, providing best match */
+static size_t ZSTD_BtFindBestMatch (
+ ZSTD_CCtx* zc,
+ const BYTE* const ip, const BYTE* const iLimit,
+ size_t* offsetPtr,
+ const U32 maxNbAttempts, const U32 mls)
+{
+ if (ip < zc->base + zc->nextToUpdate) return 0; /* skipped area */
+ ZSTD_updateTree(zc, ip, iLimit, maxNbAttempts, mls);
+ return ZSTD_insertBtAndFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, mls, 0);
+}
+
+
+static size_t ZSTD_BtFindBestMatch_selectMLS (
+ ZSTD_CCtx* zc, /* Index table will be updated */
+ const BYTE* ip, const BYTE* const iLimit,
+ size_t* offsetPtr,
+ const U32 maxNbAttempts, const U32 matchLengthSearch)
+{
+ switch(matchLengthSearch)
+ {
+ default : /* includes case 3 */
+ case 4 : return ZSTD_BtFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, 4);
+ case 5 : return ZSTD_BtFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, 5);
+ case 7 :
+ case 6 : return ZSTD_BtFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, 6);
+ }
+}
+
+
+void ZSTD_updateTree_extDict(ZSTD_CCtx* zc, const BYTE* const ip, const BYTE* const iend, const U32 nbCompares, const U32 mls)
+{
+ const BYTE* const base = zc->base;
+ const U32 target = (U32)(ip - base);
+ U32 idx = zc->nextToUpdate;
+
+ while (idx < target) idx += ZSTD_insertBt1(zc, base+idx, mls, iend, nbCompares, 1);
+}
+
+
+/** Tree updater, providing best match */
+static size_t ZSTD_BtFindBestMatch_extDict (
+ ZSTD_CCtx* zc,
+ const BYTE* const ip, const BYTE* const iLimit,
+ size_t* offsetPtr,
+ const U32 maxNbAttempts, const U32 mls)
+{
+ if (ip < zc->base + zc->nextToUpdate) return 0; /* skipped area */
+ ZSTD_updateTree_extDict(zc, ip, iLimit, maxNbAttempts, mls);
+ return ZSTD_insertBtAndFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, mls, 1);
+}
+
+
+static size_t ZSTD_BtFindBestMatch_selectMLS_extDict (
+ ZSTD_CCtx* zc, /* Index table will be updated */
+ const BYTE* ip, const BYTE* const iLimit,
+ size_t* offsetPtr,
+ const U32 maxNbAttempts, const U32 matchLengthSearch)
+{
+ switch(matchLengthSearch)
+ {
+ default : /* includes case 3 */
+ case 4 : return ZSTD_BtFindBestMatch_extDict(zc, ip, iLimit, offsetPtr, maxNbAttempts, 4);
+ case 5 : return ZSTD_BtFindBestMatch_extDict(zc, ip, iLimit, offsetPtr, maxNbAttempts, 5);
+ case 7 :
+ case 6 : return ZSTD_BtFindBestMatch_extDict(zc, ip, iLimit, offsetPtr, maxNbAttempts, 6);
+ }
+}
+
+
+
+/* *********************************
+* Hash Chain
+***********************************/
+#define NEXT_IN_CHAIN(d, mask) chainTable[(d) & mask]
+
+/* Update chains up to ip (excluded)
+ Assumption : always within prefix (i.e. not within extDict) */
+U32 ZSTD_insertAndFindFirstIndex (ZSTD_CCtx* zc, const BYTE* ip, U32 mls)
+{
+ U32* const hashTable = zc->hashTable;
+ const U32 hashLog = zc->appliedParams.cParams.hashLog;
+ U32* const chainTable = zc->chainTable;
+ const U32 chainMask = (1 << zc->appliedParams.cParams.chainLog) - 1;
+ const BYTE* const base = zc->base;
+ const U32 target = (U32)(ip - base);
+ U32 idx = zc->nextToUpdate;
+
+ while(idx < target) { /* catch up */
+ size_t const h = ZSTD_hashPtr(base+idx, hashLog, mls);
+ NEXT_IN_CHAIN(idx, chainMask) = hashTable[h];
+ hashTable[h] = idx;
+ idx++;
+ }
+
+ zc->nextToUpdate = target;
+ return hashTable[ZSTD_hashPtr(ip, hashLog, mls)];
+}
+
+
+/* inlining is important to hardwire a hot branch (template emulation) */
+FORCE_INLINE_TEMPLATE
+size_t ZSTD_HcFindBestMatch_generic (
+ ZSTD_CCtx* zc, /* Index table will be updated */
+ const BYTE* const ip, const BYTE* const iLimit,
+ size_t* offsetPtr,
+ const U32 maxNbAttempts, const U32 mls, const U32 extDict)
+{
+ U32* const chainTable = zc->chainTable;
+ const U32 chainSize = (1 << zc->appliedParams.cParams.chainLog);
+ const U32 chainMask = chainSize-1;
+ const BYTE* const base = zc->base;
+ const BYTE* const dictBase = zc->dictBase;
+ const U32 dictLimit = zc->dictLimit;
+ const BYTE* const prefixStart = base + dictLimit;
+ const BYTE* const dictEnd = dictBase + dictLimit;
+ const U32 lowLimit = zc->lowLimit;
+ const U32 current = (U32)(ip-base);
+ const U32 minChain = current > chainSize ? current - chainSize : 0;
+ int nbAttempts=maxNbAttempts;
+ size_t ml=4-1;
+
+ /* HC4 match finder */
+ U32 matchIndex = ZSTD_insertAndFindFirstIndex (zc, ip, mls);
+
+ for ( ; (matchIndex>lowLimit) & (nbAttempts>0) ; nbAttempts--) {
+ const BYTE* match;
+ size_t currentMl=0;
+ if ((!extDict) || matchIndex >= dictLimit) {
+ match = base + matchIndex;
+ if (match[ml] == ip[ml]) /* potentially better */
+ currentMl = ZSTD_count(ip, match, iLimit);
+ } else {
+ match = dictBase + matchIndex;
+ if (MEM_read32(match) == MEM_read32(ip)) /* assumption : matchIndex <= dictLimit-4 (by table construction) */
+ currentMl = ZSTD_count_2segments(ip+4, match+4, iLimit, dictEnd, prefixStart) + 4;
+ }
+
+ /* save best solution */
+ if (currentMl > ml) {
+ ml = currentMl;
+ *offsetPtr = current - matchIndex + ZSTD_REP_MOVE;
+ if (ip+currentMl == iLimit) break; /* best possible, avoids read overflow on next attempt */
+ }
+
+ if (matchIndex <= minChain) break;
+ matchIndex = NEXT_IN_CHAIN(matchIndex, chainMask);
+ }
+
+ return ml;
+}
+
+
+FORCE_INLINE_TEMPLATE size_t ZSTD_HcFindBestMatch_selectMLS (
+ ZSTD_CCtx* zc,
+ const BYTE* ip, const BYTE* const iLimit,
+ size_t* offsetPtr,
+ const U32 maxNbAttempts, const U32 matchLengthSearch)
+{
+ switch(matchLengthSearch)
+ {
+ default : /* includes case 3 */
+ case 4 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 4, 0);
+ case 5 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 5, 0);
+ case 7 :
+ case 6 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 6, 0);
+ }
+}
+
+
+FORCE_INLINE_TEMPLATE size_t ZSTD_HcFindBestMatch_extDict_selectMLS (
+ ZSTD_CCtx* zc,
+ const BYTE* ip, const BYTE* const iLimit,
+ size_t* offsetPtr,
+ const U32 maxNbAttempts, const U32 matchLengthSearch)
+{
+ switch(matchLengthSearch)
+ {
+ default : /* includes case 3 */
+ case 4 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 4, 1);
+ case 5 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 5, 1);
+ case 7 :
+ case 6 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 6, 1);
+ }
+}
+
+
+/* *******************************
+* Common parser - lazy strategy
+*********************************/
+FORCE_INLINE_TEMPLATE
+size_t ZSTD_compressBlock_lazy_generic(ZSTD_CCtx* ctx,
+ const void* src, size_t srcSize,
+ const U32 searchMethod, const U32 depth)
+{
+ seqStore_t* seqStorePtr = &(ctx->seqStore);
+ const BYTE* const istart = (const BYTE*)src;
+ const BYTE* ip = istart;
+ const BYTE* anchor = istart;
+ const BYTE* const iend = istart + srcSize;
+ const BYTE* const ilimit = iend - 8;
+ const BYTE* const base = ctx->base + ctx->dictLimit;
+
+ U32 const maxSearches = 1 << ctx->appliedParams.cParams.searchLog;
+ U32 const mls = ctx->appliedParams.cParams.searchLength;
+
+ typedef size_t (*searchMax_f)(ZSTD_CCtx* zc, const BYTE* ip, const BYTE* iLimit,
+ size_t* offsetPtr,
+ U32 maxNbAttempts, U32 matchLengthSearch);
+ searchMax_f const searchMax = searchMethod ? ZSTD_BtFindBestMatch_selectMLS : ZSTD_HcFindBestMatch_selectMLS;
+ U32 offset_1 = seqStorePtr->rep[0], offset_2 = seqStorePtr->rep[1], savedOffset=0;
+
+ /* init */
+ ip += (ip==base);
+ ctx->nextToUpdate3 = ctx->nextToUpdate;
+ { U32 const maxRep = (U32)(ip-base);
+ if (offset_2 > maxRep) savedOffset = offset_2, offset_2 = 0;
+ if (offset_1 > maxRep) savedOffset = offset_1, offset_1 = 0;
+ }
+
+ /* Match Loop */
+ while (ip < ilimit) {
+ size_t matchLength=0;
+ size_t offset=0;
+ const BYTE* start=ip+1;
+
+ /* check repCode */
+ if ((offset_1>0) & (MEM_read32(ip+1) == MEM_read32(ip+1 - offset_1))) {
+ /* repcode : we take it */
+ matchLength = ZSTD_count(ip+1+4, ip+1+4-offset_1, iend) + 4;
+ if (depth==0) goto _storeSequence;
+ }
+
+ /* first search (depth 0) */
+ { size_t offsetFound = 99999999;
+ size_t const ml2 = searchMax(ctx, ip, iend, &offsetFound, maxSearches, mls);
+ if (ml2 > matchLength)
+ matchLength = ml2, start = ip, offset=offsetFound;
+ }
+
+ if (matchLength < 4) {
+ ip += ((ip-anchor) >> g_searchStrength) + 1; /* jump faster over incompressible sections */
+ continue;
+ }
+
+ /* let's try to find a better solution */
+ if (depth>=1)
+ while (ip<ilimit) {
+ ip ++;
+ if ((offset) && ((offset_1>0) & (MEM_read32(ip) == MEM_read32(ip - offset_1)))) {
+ size_t const mlRep = ZSTD_count(ip+4, ip+4-offset_1, iend) + 4;
+ int const gain2 = (int)(mlRep * 3);
+ int const gain1 = (int)(matchLength*3 - ZSTD_highbit32((U32)offset+1) + 1);
+ if ((mlRep >= 4) && (gain2 > gain1))
+ matchLength = mlRep, offset = 0, start = ip;
+ }
+ { size_t offset2=99999999;
+ size_t const ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls);
+ int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)offset2+1)); /* raw approx */
+ int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 4);
+ if ((ml2 >= 4) && (gain2 > gain1)) {
+ matchLength = ml2, offset = offset2, start = ip;
+ continue; /* search a better one */
+ } }
+
+ /* let's find an even better one */
+ if ((depth==2) && (ip<ilimit)) {
+ ip ++;
+ if ((offset) && ((offset_1>0) & (MEM_read32(ip) == MEM_read32(ip - offset_1)))) {
+ size_t const ml2 = ZSTD_count(ip+4, ip+4-offset_1, iend) + 4;
+ int const gain2 = (int)(ml2 * 4);
+ int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 1);
+ if ((ml2 >= 4) && (gain2 > gain1))
+ matchLength = ml2, offset = 0, start = ip;
+ }
+ { size_t offset2=99999999;
+ size_t const ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls);
+ int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)offset2+1)); /* raw approx */
+ int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 7);
+ if ((ml2 >= 4) && (gain2 > gain1)) {
+ matchLength = ml2, offset = offset2, start = ip;
+ continue;
+ } } }
+ break; /* nothing found : store previous solution */
+ }
+
+ /* NOTE:
+ * start[-offset+ZSTD_REP_MOVE-1] is undefined behavior.
+ * (-offset+ZSTD_REP_MOVE-1) is unsigned, and is added to start, which
+ * overflows the pointer, which is undefined behavior.
+ */
+ /* catch up */
+ if (offset) {
+ while ( (start > anchor)
+ && (start > base+offset-ZSTD_REP_MOVE)
+ && (start[-1] == (start-offset+ZSTD_REP_MOVE)[-1]) ) /* only search for offset within prefix */
+ { start--; matchLength++; }
+ offset_2 = offset_1; offset_1 = (U32)(offset - ZSTD_REP_MOVE);
+ }
+ /* store sequence */
+_storeSequence:
+ { size_t const litLength = start - anchor;
+ ZSTD_storeSeq(seqStorePtr, litLength, anchor, (U32)offset, matchLength-MINMATCH);
+ anchor = ip = start + matchLength;
+ }
+
+ /* check immediate repcode */
+ while ( (ip <= ilimit)
+ && ((offset_2>0)
+ & (MEM_read32(ip) == MEM_read32(ip - offset_2)) )) {
+ /* store sequence */
+ matchLength = ZSTD_count(ip+4, ip+4-offset_2, iend) + 4;
+ offset = offset_2; offset_2 = offset_1; offset_1 = (U32)offset; /* swap repcodes */
+ ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, matchLength-MINMATCH);
+ ip += matchLength;
+ anchor = ip;
+ continue; /* faster when present ... (?) */
+ } }
+
+ /* Save reps for next block */
+ seqStorePtr->repToConfirm[0] = offset_1 ? offset_1 : savedOffset;
+ seqStorePtr->repToConfirm[1] = offset_2 ? offset_2 : savedOffset;
+
+ /* Return the last literals size */
+ return iend - anchor;
+}
+
+
+size_t ZSTD_compressBlock_btlazy2(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
+{
+ return ZSTD_compressBlock_lazy_generic(ctx, src, srcSize, 1, 2);
+}
+
+size_t ZSTD_compressBlock_lazy2(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
+{
+ return ZSTD_compressBlock_lazy_generic(ctx, src, srcSize, 0, 2);
+}
+
+size_t ZSTD_compressBlock_lazy(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
+{
+ return ZSTD_compressBlock_lazy_generic(ctx, src, srcSize, 0, 1);
+}
+
+size_t ZSTD_compressBlock_greedy(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
+{
+ return ZSTD_compressBlock_lazy_generic(ctx, src, srcSize, 0, 0);
+}
+
+
+FORCE_INLINE_TEMPLATE
+size_t ZSTD_compressBlock_lazy_extDict_generic(ZSTD_CCtx* ctx,
+ const void* src, size_t srcSize,
+ const U32 searchMethod, const U32 depth)
+{
+ seqStore_t* seqStorePtr = &(ctx->seqStore);
+ const BYTE* const istart = (const BYTE*)src;
+ const BYTE* ip = istart;
+ const BYTE* anchor = istart;
+ const BYTE* const iend = istart + srcSize;
+ const BYTE* const ilimit = iend - 8;
+ const BYTE* const base = ctx->base;
+ const U32 dictLimit = ctx->dictLimit;
+ const U32 lowestIndex = ctx->lowLimit;
+ const BYTE* const prefixStart = base + dictLimit;
+ const BYTE* const dictBase = ctx->dictBase;
+ const BYTE* const dictEnd = dictBase + dictLimit;
+ const BYTE* const dictStart = dictBase + ctx->lowLimit;
+
+ const U32 maxSearches = 1 << ctx->appliedParams.cParams.searchLog;
+ const U32 mls = ctx->appliedParams.cParams.searchLength;
+
+ typedef size_t (*searchMax_f)(ZSTD_CCtx* zc, const BYTE* ip, const BYTE* iLimit,
+ size_t* offsetPtr,
+ U32 maxNbAttempts, U32 matchLengthSearch);
+ searchMax_f searchMax = searchMethod ? ZSTD_BtFindBestMatch_selectMLS_extDict : ZSTD_HcFindBestMatch_extDict_selectMLS;
+
+ U32 offset_1 = seqStorePtr->rep[0], offset_2 = seqStorePtr->rep[1];
+
+ /* init */
+ ctx->nextToUpdate3 = ctx->nextToUpdate;
+ ip += (ip == prefixStart);
+
+ /* Match Loop */
+ while (ip < ilimit) {
+ size_t matchLength=0;
+ size_t offset=0;
+ const BYTE* start=ip+1;
+ U32 current = (U32)(ip-base);
+
+ /* check repCode */
+ { const U32 repIndex = (U32)(current+1 - offset_1);
+ const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
+ const BYTE* const repMatch = repBase + repIndex;
+ if (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex > lowestIndex)) /* intentional overflow */
+ if (MEM_read32(ip+1) == MEM_read32(repMatch)) {
+ /* repcode detected we should take it */
+ const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
+ matchLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repEnd, prefixStart) + 4;
+ if (depth==0) goto _storeSequence;
+ } }
+
+ /* first search (depth 0) */
+ { size_t offsetFound = 99999999;
+ size_t const ml2 = searchMax(ctx, ip, iend, &offsetFound, maxSearches, mls);
+ if (ml2 > matchLength)
+ matchLength = ml2, start = ip, offset=offsetFound;
+ }
+
+ if (matchLength < 4) {
+ ip += ((ip-anchor) >> g_searchStrength) + 1; /* jump faster over incompressible sections */
+ continue;
+ }
+
+ /* let's try to find a better solution */
+ if (depth>=1)
+ while (ip<ilimit) {
+ ip ++;
+ current++;
+ /* check repCode */
+ if (offset) {
+ const U32 repIndex = (U32)(current - offset_1);
+ const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
+ const BYTE* const repMatch = repBase + repIndex;
+ if (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex > lowestIndex)) /* intentional overflow */
+ if (MEM_read32(ip) == MEM_read32(repMatch)) {
+ /* repcode detected */
+ const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
+ size_t const repLength = ZSTD_count_2segments(ip+4, repMatch+4, iend, repEnd, prefixStart) + 4;
+ int const gain2 = (int)(repLength * 3);
+ int const gain1 = (int)(matchLength*3 - ZSTD_highbit32((U32)offset+1) + 1);
+ if ((repLength >= 4) && (gain2 > gain1))
+ matchLength = repLength, offset = 0, start = ip;
+ } }
+
+ /* search match, depth 1 */
+ { size_t offset2=99999999;
+ size_t const ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls);
+ int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)offset2+1)); /* raw approx */
+ int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 4);
+ if ((ml2 >= 4) && (gain2 > gain1)) {
+ matchLength = ml2, offset = offset2, start = ip;
+ continue; /* search a better one */
+ } }
+
+ /* let's find an even better one */
+ if ((depth==2) && (ip<ilimit)) {
+ ip ++;
+ current++;
+ /* check repCode */
+ if (offset) {
+ const U32 repIndex = (U32)(current - offset_1);
+ const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
+ const BYTE* const repMatch = repBase + repIndex;
+ if (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex > lowestIndex)) /* intentional overflow */
+ if (MEM_read32(ip) == MEM_read32(repMatch)) {
+ /* repcode detected */
+ const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
+ size_t const repLength = ZSTD_count_2segments(ip+4, repMatch+4, iend, repEnd, prefixStart) + 4;
+ int const gain2 = (int)(repLength * 4);
+ int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 1);
+ if ((repLength >= 4) && (gain2 > gain1))
+ matchLength = repLength, offset = 0, start = ip;
+ } }
+
+ /* search match, depth 2 */
+ { size_t offset2=99999999;
+ size_t const ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls);
+ int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)offset2+1)); /* raw approx */
+ int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 7);
+ if ((ml2 >= 4) && (gain2 > gain1)) {
+ matchLength = ml2, offset = offset2, start = ip;
+ continue;
+ } } }
+ break; /* nothing found : store previous solution */
+ }
+
+ /* catch up */
+ if (offset) {
+ U32 const matchIndex = (U32)((start-base) - (offset - ZSTD_REP_MOVE));
+ const BYTE* match = (matchIndex < dictLimit) ? dictBase + matchIndex : base + matchIndex;
+ const BYTE* const mStart = (matchIndex < dictLimit) ? dictStart : prefixStart;
+ while ((start>anchor) && (match>mStart) && (start[-1] == match[-1])) { start--; match--; matchLength++; } /* catch up */
+ offset_2 = offset_1; offset_1 = (U32)(offset - ZSTD_REP_MOVE);
+ }
+
+ /* store sequence */
+_storeSequence:
+ { size_t const litLength = start - anchor;
+ ZSTD_storeSeq(seqStorePtr, litLength, anchor, (U32)offset, matchLength-MINMATCH);
+ anchor = ip = start + matchLength;
+ }
+
+ /* check immediate repcode */
+ while (ip <= ilimit) {
+ const U32 repIndex = (U32)((ip-base) - offset_2);
+ const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
+ const BYTE* const repMatch = repBase + repIndex;
+ if (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex > lowestIndex)) /* intentional overflow */
+ if (MEM_read32(ip) == MEM_read32(repMatch)) {
+ /* repcode detected we should take it */
+ const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
+ matchLength = ZSTD_count_2segments(ip+4, repMatch+4, iend, repEnd, prefixStart) + 4;
+ offset = offset_2; offset_2 = offset_1; offset_1 = (U32)offset; /* swap offset history */
+ ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, matchLength-MINMATCH);
+ ip += matchLength;
+ anchor = ip;
+ continue; /* faster when present ... (?) */
+ }
+ break;
+ } }
+
+ /* Save reps for next block */
+ seqStorePtr->repToConfirm[0] = offset_1; seqStorePtr->repToConfirm[1] = offset_2;
+
+ /* Return the last literals size */
+ return iend - anchor;
+}
+
+
+size_t ZSTD_compressBlock_greedy_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
+{
+ return ZSTD_compressBlock_lazy_extDict_generic(ctx, src, srcSize, 0, 0);
+}
+
+size_t ZSTD_compressBlock_lazy_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
+{
+ return ZSTD_compressBlock_lazy_extDict_generic(ctx, src, srcSize, 0, 1);
+}
+
+size_t ZSTD_compressBlock_lazy2_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
+{
+ return ZSTD_compressBlock_lazy_extDict_generic(ctx, src, srcSize, 0, 2);
+}
+
+size_t ZSTD_compressBlock_btlazy2_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
+{
+ return ZSTD_compressBlock_lazy_extDict_generic(ctx, src, srcSize, 1, 2);
+}
diff --git a/thirdparty/zstd/compress/zstd_lazy.h b/thirdparty/zstd/compress/zstd_lazy.h
new file mode 100644
index 0000000000..a9c4daed25
--- /dev/null
+++ b/thirdparty/zstd/compress/zstd_lazy.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under both the BSD-style license (found in the
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
+ * in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
+ */
+
+#ifndef ZSTD_LAZY_H
+#define ZSTD_LAZY_H
+
+#include "zstd_compress.h"
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+U32 ZSTD_insertAndFindFirstIndex (ZSTD_CCtx* zc, const BYTE* ip, U32 mls);
+void ZSTD_updateTree(ZSTD_CCtx* zc, const BYTE* const ip, const BYTE* const iend, const U32 nbCompares, const U32 mls);
+void ZSTD_updateTree_extDict(ZSTD_CCtx* zc, const BYTE* const ip, const BYTE* const iend, const U32 nbCompares, const U32 mls);
+
+size_t ZSTD_compressBlock_btlazy2(ZSTD_CCtx* ctx, const void* src, size_t srcSize);
+size_t ZSTD_compressBlock_lazy2(ZSTD_CCtx* ctx, const void* src, size_t srcSize);
+size_t ZSTD_compressBlock_lazy(ZSTD_CCtx* ctx, const void* src, size_t srcSize);
+size_t ZSTD_compressBlock_greedy(ZSTD_CCtx* ctx, const void* src, size_t srcSize);
+
+size_t ZSTD_compressBlock_greedy_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize);
+size_t ZSTD_compressBlock_lazy_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize);
+size_t ZSTD_compressBlock_lazy2_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize);
+size_t ZSTD_compressBlock_btlazy2_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* ZSTD_LAZY_H */
diff --git a/thirdparty/zstd/compress/zstd_ldm.c b/thirdparty/zstd/compress/zstd_ldm.c
new file mode 100644
index 0000000000..be50872cf7
--- /dev/null
+++ b/thirdparty/zstd/compress/zstd_ldm.c
@@ -0,0 +1,707 @@
+/*
+ * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under both the BSD-style license (found in the
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
+ * in the COPYING file in the root directory of this source tree).
+ */
+
+#include "zstd_ldm.h"
+
+#include "zstd_fast.h" /* ZSTD_fillHashTable() */
+#include "zstd_double_fast.h" /* ZSTD_fillDoubleHashTable() */
+
+#define LDM_BUCKET_SIZE_LOG 3
+#define LDM_MIN_MATCH_LENGTH 64
+#define LDM_HASH_RLOG 7
+#define LDM_HASH_CHAR_OFFSET 10
+
+size_t ZSTD_ldm_initializeParameters(ldmParams_t* params, U32 enableLdm)
+{
+ ZSTD_STATIC_ASSERT(LDM_BUCKET_SIZE_LOG <= ZSTD_LDM_BUCKETSIZELOG_MAX);
+ params->enableLdm = enableLdm>0;
+ params->hashLog = 0;
+ params->bucketSizeLog = LDM_BUCKET_SIZE_LOG;
+ params->minMatchLength = LDM_MIN_MATCH_LENGTH;
+ params->hashEveryLog = ZSTD_LDM_HASHEVERYLOG_NOTSET;
+ return 0;
+}
+
+void ZSTD_ldm_adjustParameters(ldmParams_t* params, U32 windowLog)
+{
+ if (params->hashLog == 0) {
+ params->hashLog = MAX(ZSTD_HASHLOG_MIN, windowLog - LDM_HASH_RLOG);
+ assert(params->hashLog <= ZSTD_HASHLOG_MAX);
+ }
+ if (params->hashEveryLog == ZSTD_LDM_HASHEVERYLOG_NOTSET) {
+ params->hashEveryLog =
+ windowLog < params->hashLog ? 0 : windowLog - params->hashLog;
+ }
+ params->bucketSizeLog = MIN(params->bucketSizeLog, params->hashLog);
+}
+
+size_t ZSTD_ldm_getTableSize(U32 hashLog, U32 bucketSizeLog) {
+ size_t const ldmHSize = ((size_t)1) << hashLog;
+ size_t const ldmBucketSizeLog = MIN(bucketSizeLog, hashLog);
+ size_t const ldmBucketSize =
+ ((size_t)1) << (hashLog - ldmBucketSizeLog);
+ return ldmBucketSize + (ldmHSize * (sizeof(ldmEntry_t)));
+}
+
+/** ZSTD_ldm_getSmallHash() :
+ * numBits should be <= 32
+ * If numBits==0, returns 0.
+ * @return : the most significant numBits of value. */
+static U32 ZSTD_ldm_getSmallHash(U64 value, U32 numBits)
+{
+ assert(numBits <= 32);
+ return numBits == 0 ? 0 : (U32)(value >> (64 - numBits));
+}
+
+/** ZSTD_ldm_getChecksum() :
+ * numBitsToDiscard should be <= 32
+ * @return : the next most significant 32 bits after numBitsToDiscard */
+static U32 ZSTD_ldm_getChecksum(U64 hash, U32 numBitsToDiscard)
+{
+ assert(numBitsToDiscard <= 32);
+ return (hash >> (64 - 32 - numBitsToDiscard)) & 0xFFFFFFFF;
+}
+
+/** ZSTD_ldm_getTag() ;
+ * Given the hash, returns the most significant numTagBits bits
+ * after (32 + hbits) bits.
+ *
+ * If there are not enough bits remaining, return the last
+ * numTagBits bits. */
+static U32 ZSTD_ldm_getTag(U64 hash, U32 hbits, U32 numTagBits)
+{
+ assert(numTagBits < 32 && hbits <= 32);
+ if (32 - hbits < numTagBits) {
+ return hash & (((U32)1 << numTagBits) - 1);
+ } else {
+ return (hash >> (32 - hbits - numTagBits)) & (((U32)1 << numTagBits) - 1);
+ }
+}
+
+/** ZSTD_ldm_getBucket() :
+ * Returns a pointer to the start of the bucket associated with hash. */
+static ldmEntry_t* ZSTD_ldm_getBucket(
+ ldmState_t* ldmState, size_t hash, ldmParams_t const ldmParams)
+{
+ return ldmState->hashTable + (hash << ldmParams.bucketSizeLog);
+}
+
+/** ZSTD_ldm_insertEntry() :
+ * Insert the entry with corresponding hash into the hash table */
+static void ZSTD_ldm_insertEntry(ldmState_t* ldmState,
+ size_t const hash, const ldmEntry_t entry,
+ ldmParams_t const ldmParams)
+{
+ BYTE* const bucketOffsets = ldmState->bucketOffsets;
+ *(ZSTD_ldm_getBucket(ldmState, hash, ldmParams) + bucketOffsets[hash]) = entry;
+ bucketOffsets[hash]++;
+ bucketOffsets[hash] &= ((U32)1 << ldmParams.bucketSizeLog) - 1;
+}
+
+/** ZSTD_ldm_makeEntryAndInsertByTag() :
+ *
+ * Gets the small hash, checksum, and tag from the rollingHash.
+ *
+ * If the tag matches (1 << ldmParams.hashEveryLog)-1, then
+ * creates an ldmEntry from the offset, and inserts it into the hash table.
+ *
+ * hBits is the length of the small hash, which is the most significant hBits
+ * of rollingHash. The checksum is the next 32 most significant bits, followed
+ * by ldmParams.hashEveryLog bits that make up the tag. */
+static void ZSTD_ldm_makeEntryAndInsertByTag(ldmState_t* ldmState,
+ U64 const rollingHash,
+ U32 const hBits,
+ U32 const offset,
+ ldmParams_t const ldmParams)
+{
+ U32 const tag = ZSTD_ldm_getTag(rollingHash, hBits, ldmParams.hashEveryLog);
+ U32 const tagMask = ((U32)1 << ldmParams.hashEveryLog) - 1;
+ if (tag == tagMask) {
+ U32 const hash = ZSTD_ldm_getSmallHash(rollingHash, hBits);
+ U32 const checksum = ZSTD_ldm_getChecksum(rollingHash, hBits);
+ ldmEntry_t entry;
+ entry.offset = offset;
+ entry.checksum = checksum;
+ ZSTD_ldm_insertEntry(ldmState, hash, entry, ldmParams);
+ }
+}
+
+/** ZSTD_ldm_getRollingHash() :
+ * Get a 64-bit hash using the first len bytes from buf.
+ *
+ * Giving bytes s = s_1, s_2, ... s_k, the hash is defined to be
+ * H(s) = s_1*(a^(k-1)) + s_2*(a^(k-2)) + ... + s_k*(a^0)
+ *
+ * where the constant a is defined to be prime8bytes.
+ *
+ * The implementation adds an offset to each byte, so
+ * H(s) = (s_1 + HASH_CHAR_OFFSET)*(a^(k-1)) + ... */
+static U64 ZSTD_ldm_getRollingHash(const BYTE* buf, U32 len)
+{
+ U64 ret = 0;
+ U32 i;
+ for (i = 0; i < len; i++) {
+ ret *= prime8bytes;
+ ret += buf[i] + LDM_HASH_CHAR_OFFSET;
+ }
+ return ret;
+}
+
+/** ZSTD_ldm_ipow() :
+ * Return base^exp. */
+static U64 ZSTD_ldm_ipow(U64 base, U64 exp)
+{
+ U64 ret = 1;
+ while (exp) {
+ if (exp & 1) { ret *= base; }
+ exp >>= 1;
+ base *= base;
+ }
+ return ret;
+}
+
+U64 ZSTD_ldm_getHashPower(U32 minMatchLength) {
+ assert(minMatchLength >= ZSTD_LDM_MINMATCH_MIN);
+ return ZSTD_ldm_ipow(prime8bytes, minMatchLength - 1);
+}
+
+/** ZSTD_ldm_updateHash() :
+ * Updates hash by removing toRemove and adding toAdd. */
+static U64 ZSTD_ldm_updateHash(U64 hash, BYTE toRemove, BYTE toAdd, U64 hashPower)
+{
+ hash -= ((toRemove + LDM_HASH_CHAR_OFFSET) * hashPower);
+ hash *= prime8bytes;
+ hash += toAdd + LDM_HASH_CHAR_OFFSET;
+ return hash;
+}
+
+/** ZSTD_ldm_countBackwardsMatch() :
+ * Returns the number of bytes that match backwards before pIn and pMatch.
+ *
+ * We count only bytes where pMatch >= pBase and pIn >= pAnchor. */
+static size_t ZSTD_ldm_countBackwardsMatch(
+ const BYTE* pIn, const BYTE* pAnchor,
+ const BYTE* pMatch, const BYTE* pBase)
+{
+ size_t matchLength = 0;
+ while (pIn > pAnchor && pMatch > pBase && pIn[-1] == pMatch[-1]) {
+ pIn--;
+ pMatch--;
+ matchLength++;
+ }
+ return matchLength;
+}
+
+/** ZSTD_ldm_fillFastTables() :
+ *
+ * Fills the relevant tables for the ZSTD_fast and ZSTD_dfast strategies.
+ * This is similar to ZSTD_loadDictionaryContent.
+ *
+ * The tables for the other strategies are filled within their
+ * block compressors. */
+static size_t ZSTD_ldm_fillFastTables(ZSTD_CCtx* zc, const void* end)
+{
+ const BYTE* const iend = (const BYTE*)end;
+ const U32 mls = zc->appliedParams.cParams.searchLength;
+
+ switch(zc->appliedParams.cParams.strategy)
+ {
+ case ZSTD_fast:
+ ZSTD_fillHashTable(zc, iend, mls);
+ zc->nextToUpdate = (U32)(iend - zc->base);
+ break;
+
+ case ZSTD_dfast:
+ ZSTD_fillDoubleHashTable(zc, iend, mls);
+ zc->nextToUpdate = (U32)(iend - zc->base);
+ break;
+
+ case ZSTD_greedy:
+ case ZSTD_lazy:
+ case ZSTD_lazy2:
+ case ZSTD_btlazy2:
+ case ZSTD_btopt:
+ case ZSTD_btultra:
+ break;
+ default:
+ assert(0); /* not possible : not a valid strategy id */
+ }
+
+ return 0;
+}
+
+/** ZSTD_ldm_fillLdmHashTable() :
+ *
+ * Fills hashTable from (lastHashed + 1) to iend (non-inclusive).
+ * lastHash is the rolling hash that corresponds to lastHashed.
+ *
+ * Returns the rolling hash corresponding to position iend-1. */
+static U64 ZSTD_ldm_fillLdmHashTable(ldmState_t* state,
+ U64 lastHash, const BYTE* lastHashed,
+ const BYTE* iend, const BYTE* base,
+ U32 hBits, ldmParams_t const ldmParams)
+{
+ U64 rollingHash = lastHash;
+ const BYTE* cur = lastHashed + 1;
+
+ while (cur < iend) {
+ rollingHash = ZSTD_ldm_updateHash(rollingHash, cur[-1],
+ cur[ldmParams.minMatchLength-1],
+ state->hashPower);
+ ZSTD_ldm_makeEntryAndInsertByTag(state,
+ rollingHash, hBits,
+ (U32)(cur - base), ldmParams);
+ ++cur;
+ }
+ return rollingHash;
+}
+
+
+/** ZSTD_ldm_limitTableUpdate() :
+ *
+ * Sets cctx->nextToUpdate to a position corresponding closer to anchor
+ * if it is far way
+ * (after a long match, only update tables a limited amount). */
+static void ZSTD_ldm_limitTableUpdate(ZSTD_CCtx* cctx, const BYTE* anchor)
+{
+ U32 const current = (U32)(anchor - cctx->base);
+ if (current > cctx->nextToUpdate + 1024) {
+ cctx->nextToUpdate =
+ current - MIN(512, current - cctx->nextToUpdate - 1024);
+ }
+}
+
+typedef size_t (*ZSTD_blockCompressor) (ZSTD_CCtx* ctx, const void* src, size_t srcSize);
+/* defined in zstd_compress.c */
+ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, int extDict);
+
+FORCE_INLINE_TEMPLATE
+size_t ZSTD_compressBlock_ldm_generic(ZSTD_CCtx* cctx,
+ const void* src, size_t srcSize)
+{
+ ldmState_t* const ldmState = &(cctx->ldmState);
+ const ldmParams_t ldmParams = cctx->appliedParams.ldmParams;
+ const U64 hashPower = ldmState->hashPower;
+ const U32 hBits = ldmParams.hashLog - ldmParams.bucketSizeLog;
+ const U32 ldmBucketSize = ((U32)1 << ldmParams.bucketSizeLog);
+ const U32 ldmTagMask = ((U32)1 << ldmParams.hashEveryLog) - 1;
+ seqStore_t* const seqStorePtr = &(cctx->seqStore);
+ const BYTE* const base = cctx->base;
+ const BYTE* const istart = (const BYTE*)src;
+ const BYTE* ip = istart;
+ const BYTE* anchor = istart;
+ const U32 lowestIndex = cctx->dictLimit;
+ const BYTE* const lowest = base + lowestIndex;
+ const BYTE* const iend = istart + srcSize;
+ const BYTE* const ilimit = iend - MAX(ldmParams.minMatchLength, HASH_READ_SIZE);
+
+ const ZSTD_blockCompressor blockCompressor =
+ ZSTD_selectBlockCompressor(cctx->appliedParams.cParams.strategy, 0);
+ U32* const repToConfirm = seqStorePtr->repToConfirm;
+ U32 savedRep[ZSTD_REP_NUM];
+ U64 rollingHash = 0;
+ const BYTE* lastHashed = NULL;
+ size_t i, lastLiterals;
+
+ /* Save seqStorePtr->rep and copy repToConfirm */
+ for (i = 0; i < ZSTD_REP_NUM; i++)
+ savedRep[i] = repToConfirm[i] = seqStorePtr->rep[i];
+
+ /* Main Search Loop */
+ while (ip < ilimit) { /* < instead of <=, because repcode check at (ip+1) */
+ size_t mLength;
+ U32 const current = (U32)(ip - base);
+ size_t forwardMatchLength = 0, backwardMatchLength = 0;
+ ldmEntry_t* bestEntry = NULL;
+ if (ip != istart) {
+ rollingHash = ZSTD_ldm_updateHash(rollingHash, lastHashed[0],
+ lastHashed[ldmParams.minMatchLength],
+ hashPower);
+ } else {
+ rollingHash = ZSTD_ldm_getRollingHash(ip, ldmParams.minMatchLength);
+ }
+ lastHashed = ip;
+
+ /* Do not insert and do not look for a match */
+ if (ZSTD_ldm_getTag(rollingHash, hBits, ldmParams.hashEveryLog) !=
+ ldmTagMask) {
+ ip++;
+ continue;
+ }
+
+ /* Get the best entry and compute the match lengths */
+ {
+ ldmEntry_t* const bucket =
+ ZSTD_ldm_getBucket(ldmState,
+ ZSTD_ldm_getSmallHash(rollingHash, hBits),
+ ldmParams);
+ ldmEntry_t* cur;
+ size_t bestMatchLength = 0;
+ U32 const checksum = ZSTD_ldm_getChecksum(rollingHash, hBits);
+
+ for (cur = bucket; cur < bucket + ldmBucketSize; ++cur) {
+ const BYTE* const pMatch = cur->offset + base;
+ size_t curForwardMatchLength, curBackwardMatchLength,
+ curTotalMatchLength;
+ if (cur->checksum != checksum || cur->offset <= lowestIndex) {
+ continue;
+ }
+
+ curForwardMatchLength = ZSTD_count(ip, pMatch, iend);
+ if (curForwardMatchLength < ldmParams.minMatchLength) {
+ continue;
+ }
+ curBackwardMatchLength = ZSTD_ldm_countBackwardsMatch(
+ ip, anchor, pMatch, lowest);
+ curTotalMatchLength = curForwardMatchLength +
+ curBackwardMatchLength;
+
+ if (curTotalMatchLength > bestMatchLength) {
+ bestMatchLength = curTotalMatchLength;
+ forwardMatchLength = curForwardMatchLength;
+ backwardMatchLength = curBackwardMatchLength;
+ bestEntry = cur;
+ }
+ }
+ }
+
+ /* No match found -- continue searching */
+ if (bestEntry == NULL) {
+ ZSTD_ldm_makeEntryAndInsertByTag(ldmState, rollingHash,
+ hBits, current,
+ ldmParams);
+ ip++;
+ continue;
+ }
+
+ /* Match found */
+ mLength = forwardMatchLength + backwardMatchLength;
+ ip -= backwardMatchLength;
+
+ /* Call the block compressor on the remaining literals */
+ {
+ U32 const matchIndex = bestEntry->offset;
+ const BYTE* const match = base + matchIndex - backwardMatchLength;
+ U32 const offset = (U32)(ip - match);
+
+ /* Overwrite rep codes */
+ for (i = 0; i < ZSTD_REP_NUM; i++)
+ seqStorePtr->rep[i] = repToConfirm[i];
+
+ /* Fill tables for block compressor */
+ ZSTD_ldm_limitTableUpdate(cctx, anchor);
+ ZSTD_ldm_fillFastTables(cctx, anchor);
+
+ /* Call block compressor and get remaining literals */
+ lastLiterals = blockCompressor(cctx, anchor, ip - anchor);
+ cctx->nextToUpdate = (U32)(ip - base);
+
+ /* Update repToConfirm with the new offset */
+ for (i = ZSTD_REP_NUM - 1; i > 0; i--)
+ repToConfirm[i] = repToConfirm[i-1];
+ repToConfirm[0] = offset;
+
+ /* Store the sequence with the leftover literals */
+ ZSTD_storeSeq(seqStorePtr, lastLiterals, ip - lastLiterals,
+ offset + ZSTD_REP_MOVE, mLength - MINMATCH);
+ }
+
+ /* Insert the current entry into the hash table */
+ ZSTD_ldm_makeEntryAndInsertByTag(ldmState, rollingHash, hBits,
+ (U32)(lastHashed - base),
+ ldmParams);
+
+ assert(ip + backwardMatchLength == lastHashed);
+
+ /* Fill the hash table from lastHashed+1 to ip+mLength*/
+ /* Heuristic: don't need to fill the entire table at end of block */
+ if (ip + mLength < ilimit) {
+ rollingHash = ZSTD_ldm_fillLdmHashTable(
+ ldmState, rollingHash, lastHashed,
+ ip + mLength, base, hBits, ldmParams);
+ lastHashed = ip + mLength - 1;
+ }
+ ip += mLength;
+ anchor = ip;
+ /* Check immediate repcode */
+ while ( (ip < ilimit)
+ && ( (repToConfirm[1] > 0) && (repToConfirm[1] <= (U32)(ip-lowest))
+ && (MEM_read32(ip) == MEM_read32(ip - repToConfirm[1])) )) {
+
+ size_t const rLength = ZSTD_count(ip+4, ip+4-repToConfirm[1],
+ iend) + 4;
+ /* Swap repToConfirm[1] <=> repToConfirm[0] */
+ {
+ U32 const tmpOff = repToConfirm[1];
+ repToConfirm[1] = repToConfirm[0];
+ repToConfirm[0] = tmpOff;
+ }
+
+ ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, rLength-MINMATCH);
+
+ /* Fill the hash table from lastHashed+1 to ip+rLength*/
+ if (ip + rLength < ilimit) {
+ rollingHash = ZSTD_ldm_fillLdmHashTable(
+ ldmState, rollingHash, lastHashed,
+ ip + rLength, base, hBits, ldmParams);
+ lastHashed = ip + rLength - 1;
+ }
+ ip += rLength;
+ anchor = ip;
+ }
+ }
+
+ /* Overwrite rep */
+ for (i = 0; i < ZSTD_REP_NUM; i++)
+ seqStorePtr->rep[i] = repToConfirm[i];
+
+ ZSTD_ldm_limitTableUpdate(cctx, anchor);
+ ZSTD_ldm_fillFastTables(cctx, anchor);
+
+ lastLiterals = blockCompressor(cctx, anchor, iend - anchor);
+ cctx->nextToUpdate = (U32)(iend - base);
+
+ /* Restore seqStorePtr->rep */
+ for (i = 0; i < ZSTD_REP_NUM; i++)
+ seqStorePtr->rep[i] = savedRep[i];
+
+ /* Return the last literals size */
+ return lastLiterals;
+}
+
+size_t ZSTD_compressBlock_ldm(ZSTD_CCtx* ctx,
+ const void* src, size_t srcSize)
+{
+ return ZSTD_compressBlock_ldm_generic(ctx, src, srcSize);
+}
+
+static size_t ZSTD_compressBlock_ldm_extDict_generic(
+ ZSTD_CCtx* ctx,
+ const void* src, size_t srcSize)
+{
+ ldmState_t* const ldmState = &(ctx->ldmState);
+ const ldmParams_t ldmParams = ctx->appliedParams.ldmParams;
+ const U64 hashPower = ldmState->hashPower;
+ const U32 hBits = ldmParams.hashLog - ldmParams.bucketSizeLog;
+ const U32 ldmBucketSize = ((U32)1 << ldmParams.bucketSizeLog);
+ const U32 ldmTagMask = ((U32)1 << ldmParams.hashEveryLog) - 1;
+ seqStore_t* const seqStorePtr = &(ctx->seqStore);
+ const BYTE* const base = ctx->base;
+ const BYTE* const dictBase = ctx->dictBase;
+ const BYTE* const istart = (const BYTE*)src;
+ const BYTE* ip = istart;
+ const BYTE* anchor = istart;
+ const U32 lowestIndex = ctx->lowLimit;
+ const BYTE* const dictStart = dictBase + lowestIndex;
+ const U32 dictLimit = ctx->dictLimit;
+ const BYTE* const lowPrefixPtr = base + dictLimit;
+ const BYTE* const dictEnd = dictBase + dictLimit;
+ const BYTE* const iend = istart + srcSize;
+ const BYTE* const ilimit = iend - MAX(ldmParams.minMatchLength, HASH_READ_SIZE);
+
+ const ZSTD_blockCompressor blockCompressor =
+ ZSTD_selectBlockCompressor(ctx->appliedParams.cParams.strategy, 1);
+ U32* const repToConfirm = seqStorePtr->repToConfirm;
+ U32 savedRep[ZSTD_REP_NUM];
+ U64 rollingHash = 0;
+ const BYTE* lastHashed = NULL;
+ size_t i, lastLiterals;
+
+ /* Save seqStorePtr->rep and copy repToConfirm */
+ for (i = 0; i < ZSTD_REP_NUM; i++) {
+ savedRep[i] = repToConfirm[i] = seqStorePtr->rep[i];
+ }
+
+ /* Search Loop */
+ while (ip < ilimit) { /* < instead of <=, because (ip+1) */
+ size_t mLength;
+ const U32 current = (U32)(ip-base);
+ size_t forwardMatchLength = 0, backwardMatchLength = 0;
+ ldmEntry_t* bestEntry = NULL;
+ if (ip != istart) {
+ rollingHash = ZSTD_ldm_updateHash(rollingHash, lastHashed[0],
+ lastHashed[ldmParams.minMatchLength],
+ hashPower);
+ } else {
+ rollingHash = ZSTD_ldm_getRollingHash(ip, ldmParams.minMatchLength);
+ }
+ lastHashed = ip;
+
+ if (ZSTD_ldm_getTag(rollingHash, hBits, ldmParams.hashEveryLog) !=
+ ldmTagMask) {
+ /* Don't insert and don't look for a match */
+ ip++;
+ continue;
+ }
+
+ /* Get the best entry and compute the match lengths */
+ {
+ ldmEntry_t* const bucket =
+ ZSTD_ldm_getBucket(ldmState,
+ ZSTD_ldm_getSmallHash(rollingHash, hBits),
+ ldmParams);
+ ldmEntry_t* cur;
+ size_t bestMatchLength = 0;
+ U32 const checksum = ZSTD_ldm_getChecksum(rollingHash, hBits);
+
+ for (cur = bucket; cur < bucket + ldmBucketSize; ++cur) {
+ const BYTE* const curMatchBase =
+ cur->offset < dictLimit ? dictBase : base;
+ const BYTE* const pMatch = curMatchBase + cur->offset;
+ const BYTE* const matchEnd =
+ cur->offset < dictLimit ? dictEnd : iend;
+ const BYTE* const lowMatchPtr =
+ cur->offset < dictLimit ? dictStart : lowPrefixPtr;
+ size_t curForwardMatchLength, curBackwardMatchLength,
+ curTotalMatchLength;
+
+ if (cur->checksum != checksum || cur->offset <= lowestIndex) {
+ continue;
+ }
+
+ curForwardMatchLength = ZSTD_count_2segments(
+ ip, pMatch, iend,
+ matchEnd, lowPrefixPtr);
+ if (curForwardMatchLength < ldmParams.minMatchLength) {
+ continue;
+ }
+ curBackwardMatchLength = ZSTD_ldm_countBackwardsMatch(
+ ip, anchor, pMatch, lowMatchPtr);
+ curTotalMatchLength = curForwardMatchLength +
+ curBackwardMatchLength;
+
+ if (curTotalMatchLength > bestMatchLength) {
+ bestMatchLength = curTotalMatchLength;
+ forwardMatchLength = curForwardMatchLength;
+ backwardMatchLength = curBackwardMatchLength;
+ bestEntry = cur;
+ }
+ }
+ }
+
+ /* No match found -- continue searching */
+ if (bestEntry == NULL) {
+ ZSTD_ldm_makeEntryAndInsertByTag(ldmState, rollingHash, hBits,
+ (U32)(lastHashed - base),
+ ldmParams);
+ ip++;
+ continue;
+ }
+
+ /* Match found */
+ mLength = forwardMatchLength + backwardMatchLength;
+ ip -= backwardMatchLength;
+
+ /* Call the block compressor on the remaining literals */
+ {
+ /* ip = current - backwardMatchLength
+ * The match is at (bestEntry->offset - backwardMatchLength) */
+ U32 const matchIndex = bestEntry->offset;
+ U32 const offset = current - matchIndex;
+
+ /* Overwrite rep codes */
+ for (i = 0; i < ZSTD_REP_NUM; i++)
+ seqStorePtr->rep[i] = repToConfirm[i];
+
+ /* Fill the hash table for the block compressor */
+ ZSTD_ldm_limitTableUpdate(ctx, anchor);
+ ZSTD_ldm_fillFastTables(ctx, anchor);
+
+ /* Call block compressor and get remaining literals */
+ lastLiterals = blockCompressor(ctx, anchor, ip - anchor);
+ ctx->nextToUpdate = (U32)(ip - base);
+
+ /* Update repToConfirm with the new offset */
+ for (i = ZSTD_REP_NUM - 1; i > 0; i--)
+ repToConfirm[i] = repToConfirm[i-1];
+ repToConfirm[0] = offset;
+
+ /* Store the sequence with the leftover literals */
+ ZSTD_storeSeq(seqStorePtr, lastLiterals, ip - lastLiterals,
+ offset + ZSTD_REP_MOVE, mLength - MINMATCH);
+ }
+
+ /* Insert the current entry into the hash table */
+ ZSTD_ldm_makeEntryAndInsertByTag(ldmState, rollingHash, hBits,
+ (U32)(lastHashed - base),
+ ldmParams);
+
+ /* Fill the hash table from lastHashed+1 to ip+mLength */
+ assert(ip + backwardMatchLength == lastHashed);
+ if (ip + mLength < ilimit) {
+ rollingHash = ZSTD_ldm_fillLdmHashTable(
+ ldmState, rollingHash, lastHashed,
+ ip + mLength, base, hBits,
+ ldmParams);
+ lastHashed = ip + mLength - 1;
+ }
+ ip += mLength;
+ anchor = ip;
+
+ /* check immediate repcode */
+ while (ip < ilimit) {
+ U32 const current2 = (U32)(ip-base);
+ U32 const repIndex2 = current2 - repToConfirm[1];
+ const BYTE* repMatch2 = repIndex2 < dictLimit ?
+ dictBase + repIndex2 : base + repIndex2;
+ if ( (((U32)((dictLimit-1) - repIndex2) >= 3) &
+ (repIndex2 > lowestIndex)) /* intentional overflow */
+ && (MEM_read32(repMatch2) == MEM_read32(ip)) ) {
+ const BYTE* const repEnd2 = repIndex2 < dictLimit ?
+ dictEnd : iend;
+ size_t const repLength2 =
+ ZSTD_count_2segments(ip+4, repMatch2+4, iend,
+ repEnd2, lowPrefixPtr) + 4;
+
+ U32 tmpOffset = repToConfirm[1];
+ repToConfirm[1] = repToConfirm[0];
+ repToConfirm[0] = tmpOffset;
+
+ ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, repLength2-MINMATCH);
+
+ /* Fill the hash table from lastHashed+1 to ip+repLength2*/
+ if (ip + repLength2 < ilimit) {
+ rollingHash = ZSTD_ldm_fillLdmHashTable(
+ ldmState, rollingHash, lastHashed,
+ ip + repLength2, base, hBits,
+ ldmParams);
+ lastHashed = ip + repLength2 - 1;
+ }
+ ip += repLength2;
+ anchor = ip;
+ continue;
+ }
+ break;
+ }
+ }
+
+ /* Overwrite rep */
+ for (i = 0; i < ZSTD_REP_NUM; i++)
+ seqStorePtr->rep[i] = repToConfirm[i];
+
+ ZSTD_ldm_limitTableUpdate(ctx, anchor);
+ ZSTD_ldm_fillFastTables(ctx, anchor);
+
+ /* Call the block compressor one last time on the last literals */
+ lastLiterals = blockCompressor(ctx, anchor, iend - anchor);
+ ctx->nextToUpdate = (U32)(iend - base);
+
+ /* Restore seqStorePtr->rep */
+ for (i = 0; i < ZSTD_REP_NUM; i++)
+ seqStorePtr->rep[i] = savedRep[i];
+
+ /* Return the last literals size */
+ return lastLiterals;
+}
+
+size_t ZSTD_compressBlock_ldm_extDict(ZSTD_CCtx* ctx,
+ const void* src, size_t srcSize)
+{
+ return ZSTD_compressBlock_ldm_extDict_generic(ctx, src, srcSize);
+}
diff --git a/thirdparty/zstd/compress/zstd_ldm.h b/thirdparty/zstd/compress/zstd_ldm.h
new file mode 100644
index 0000000000..d6d3d42c33
--- /dev/null
+++ b/thirdparty/zstd/compress/zstd_ldm.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under both the BSD-style license (found in the
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
+ * in the COPYING file in the root directory of this source tree).
+ */
+
+#ifndef ZSTD_LDM_H
+#define ZSTD_LDM_H
+
+#include "zstd_compress.h"
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+/*-*************************************
+* Long distance matching
+***************************************/
+
+#define ZSTD_LDM_DEFAULT_WINDOW_LOG ZSTD_WINDOWLOG_DEFAULTMAX
+#define ZSTD_LDM_HASHEVERYLOG_NOTSET 9999
+
+/** ZSTD_compressBlock_ldm_generic() :
+ *
+ * This is a block compressor intended for long distance matching.
+ *
+ * The function searches for matches of length at least
+ * ldmParams.minMatchLength using a hash table in cctx->ldmState.
+ * Matches can be at a distance of up to cParams.windowLog.
+ *
+ * Upon finding a match, the unmatched literals are compressed using a
+ * ZSTD_blockCompressor (depending on the strategy in the compression
+ * parameters), which stores the matched sequences. The "long distance"
+ * match is then stored with the remaining literals from the
+ * ZSTD_blockCompressor. */
+size_t ZSTD_compressBlock_ldm(ZSTD_CCtx* cctx, const void* src, size_t srcSize);
+size_t ZSTD_compressBlock_ldm_extDict(ZSTD_CCtx* ctx,
+ const void* src, size_t srcSize);
+
+/** ZSTD_ldm_initializeParameters() :
+ * Initialize the long distance matching parameters to their default values. */
+size_t ZSTD_ldm_initializeParameters(ldmParams_t* params, U32 enableLdm);
+
+/** ZSTD_ldm_getTableSize() :
+ * Estimate the space needed for long distance matching tables. */
+size_t ZSTD_ldm_getTableSize(U32 hashLog, U32 bucketSizeLog);
+
+/** ZSTD_ldm_getTableSize() :
+ * Return prime8bytes^(minMatchLength-1) */
+U64 ZSTD_ldm_getHashPower(U32 minMatchLength);
+
+/** ZSTD_ldm_adjustParameters() :
+ * If the params->hashEveryLog is not set, set it to its default value based on
+ * windowLog and params->hashLog.
+ *
+ * Ensures that params->bucketSizeLog is <= params->hashLog (setting it to
+ * params->hashLog if it is not). */
+void ZSTD_ldm_adjustParameters(ldmParams_t* params, U32 windowLog);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* ZSTD_FAST_H */
diff --git a/thirdparty/zstd/compress/zstd_opt.c b/thirdparty/zstd/compress/zstd_opt.c
new file mode 100644
index 0000000000..c47ce23ad5
--- /dev/null
+++ b/thirdparty/zstd/compress/zstd_opt.c
@@ -0,0 +1,957 @@
+/*
+ * Copyright (c) 2016-present, Przemyslaw Skibinski, Yann Collet, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under both the BSD-style license (found in the
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
+ * in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
+ */
+
+#include "zstd_opt.h"
+#include "zstd_lazy.h"
+
+
+#define ZSTD_LITFREQ_ADD 2
+#define ZSTD_FREQ_DIV 4
+#define ZSTD_MAX_PRICE (1<<30)
+
+/*-*************************************
+* Price functions for optimal parser
+***************************************/
+static void ZSTD_setLog2Prices(optState_t* optPtr)
+{
+ optPtr->log2matchLengthSum = ZSTD_highbit32(optPtr->matchLengthSum+1);
+ optPtr->log2litLengthSum = ZSTD_highbit32(optPtr->litLengthSum+1);
+ optPtr->log2litSum = ZSTD_highbit32(optPtr->litSum+1);
+ optPtr->log2offCodeSum = ZSTD_highbit32(optPtr->offCodeSum+1);
+ optPtr->factor = 1 + ((optPtr->litSum>>5) / optPtr->litLengthSum) + ((optPtr->litSum<<1) / (optPtr->litSum + optPtr->matchSum));
+}
+
+
+static void ZSTD_rescaleFreqs(optState_t* optPtr, const BYTE* src, size_t srcSize)
+{
+ unsigned u;
+
+ optPtr->cachedLiterals = NULL;
+ optPtr->cachedPrice = optPtr->cachedLitLength = 0;
+ optPtr->staticPrices = 0;
+
+ if (optPtr->litLengthSum == 0) {
+ if (srcSize <= 1024) optPtr->staticPrices = 1;
+
+ assert(optPtr->litFreq!=NULL);
+ for (u=0; u<=MaxLit; u++)
+ optPtr->litFreq[u] = 0;
+ for (u=0; u<srcSize; u++)
+ optPtr->litFreq[src[u]]++;
+
+ optPtr->litSum = 0;
+ optPtr->litLengthSum = MaxLL+1;
+ optPtr->matchLengthSum = MaxML+1;
+ optPtr->offCodeSum = (MaxOff+1);
+ optPtr->matchSum = (ZSTD_LITFREQ_ADD<<Litbits);
+
+ for (u=0; u<=MaxLit; u++) {
+ optPtr->litFreq[u] = 1 + (optPtr->litFreq[u]>>ZSTD_FREQ_DIV);
+ optPtr->litSum += optPtr->litFreq[u];
+ }
+ for (u=0; u<=MaxLL; u++)
+ optPtr->litLengthFreq[u] = 1;
+ for (u=0; u<=MaxML; u++)
+ optPtr->matchLengthFreq[u] = 1;
+ for (u=0; u<=MaxOff; u++)
+ optPtr->offCodeFreq[u] = 1;
+ } else {
+ optPtr->matchLengthSum = 0;
+ optPtr->litLengthSum = 0;
+ optPtr->offCodeSum = 0;
+ optPtr->matchSum = 0;
+ optPtr->litSum = 0;
+
+ for (u=0; u<=MaxLit; u++) {
+ optPtr->litFreq[u] = 1 + (optPtr->litFreq[u]>>(ZSTD_FREQ_DIV+1));
+ optPtr->litSum += optPtr->litFreq[u];
+ }
+ for (u=0; u<=MaxLL; u++) {
+ optPtr->litLengthFreq[u] = 1 + (optPtr->litLengthFreq[u]>>(ZSTD_FREQ_DIV+1));
+ optPtr->litLengthSum += optPtr->litLengthFreq[u];
+ }
+ for (u=0; u<=MaxML; u++) {
+ optPtr->matchLengthFreq[u] = 1 + (optPtr->matchLengthFreq[u]>>ZSTD_FREQ_DIV);
+ optPtr->matchLengthSum += optPtr->matchLengthFreq[u];
+ optPtr->matchSum += optPtr->matchLengthFreq[u] * (u + 3);
+ }
+ optPtr->matchSum *= ZSTD_LITFREQ_ADD;
+ for (u=0; u<=MaxOff; u++) {
+ optPtr->offCodeFreq[u] = 1 + (optPtr->offCodeFreq[u]>>ZSTD_FREQ_DIV);
+ optPtr->offCodeSum += optPtr->offCodeFreq[u];
+ }
+ }
+
+ ZSTD_setLog2Prices(optPtr);
+}
+
+
+static U32 ZSTD_getLiteralPrice(optState_t* optPtr, U32 litLength, const BYTE* literals)
+{
+ U32 price, u;
+
+ if (optPtr->staticPrices)
+ return ZSTD_highbit32((U32)litLength+1) + (litLength*6);
+
+ if (litLength == 0)
+ return optPtr->log2litLengthSum - ZSTD_highbit32(optPtr->litLengthFreq[0]+1);
+
+ /* literals */
+ if (optPtr->cachedLiterals == literals) {
+ U32 const additional = litLength - optPtr->cachedLitLength;
+ const BYTE* literals2 = optPtr->cachedLiterals + optPtr->cachedLitLength;
+ price = optPtr->cachedPrice + additional * optPtr->log2litSum;
+ for (u=0; u < additional; u++)
+ price -= ZSTD_highbit32(optPtr->litFreq[literals2[u]]+1);
+ optPtr->cachedPrice = price;
+ optPtr->cachedLitLength = litLength;
+ } else {
+ price = litLength * optPtr->log2litSum;
+ for (u=0; u < litLength; u++)
+ price -= ZSTD_highbit32(optPtr->litFreq[literals[u]]+1);
+
+ if (litLength >= 12) {
+ optPtr->cachedLiterals = literals;
+ optPtr->cachedPrice = price;
+ optPtr->cachedLitLength = litLength;
+ }
+ }
+
+ /* literal Length */
+ { const BYTE LL_deltaCode = 19;
+ const BYTE llCode = (litLength>63) ? (BYTE)ZSTD_highbit32(litLength) + LL_deltaCode : LL_Code[litLength];
+ price += LL_bits[llCode] + optPtr->log2litLengthSum - ZSTD_highbit32(optPtr->litLengthFreq[llCode]+1);
+ }
+
+ return price;
+}
+
+
+FORCE_INLINE_TEMPLATE U32 ZSTD_getPrice(optState_t* optPtr, U32 litLength, const BYTE* literals, U32 offset, U32 matchLength, const int ultra)
+{
+ /* offset */
+ U32 price;
+ BYTE const offCode = (BYTE)ZSTD_highbit32(offset+1);
+
+ if (optPtr->staticPrices)
+ return ZSTD_getLiteralPrice(optPtr, litLength, literals) + ZSTD_highbit32((U32)matchLength+1) + 16 + offCode;
+
+ price = offCode + optPtr->log2offCodeSum - ZSTD_highbit32(optPtr->offCodeFreq[offCode]+1);
+ if (!ultra && offCode >= 20) price += (offCode-19)*2;
+
+ /* match Length */
+ { const BYTE ML_deltaCode = 36;
+ const BYTE mlCode = (matchLength>127) ? (BYTE)ZSTD_highbit32(matchLength) + ML_deltaCode : ML_Code[matchLength];
+ price += ML_bits[mlCode] + optPtr->log2matchLengthSum - ZSTD_highbit32(optPtr->matchLengthFreq[mlCode]+1);
+ }
+
+ return price + ZSTD_getLiteralPrice(optPtr, litLength, literals) + optPtr->factor;
+}
+
+
+static void ZSTD_updatePrice(optState_t* optPtr, U32 litLength, const BYTE* literals, U32 offset, U32 matchLength)
+{
+ U32 u;
+
+ /* literals */
+ optPtr->litSum += litLength*ZSTD_LITFREQ_ADD;
+ for (u=0; u < litLength; u++)
+ optPtr->litFreq[literals[u]] += ZSTD_LITFREQ_ADD;
+
+ /* literal Length */
+ { const BYTE LL_deltaCode = 19;
+ const BYTE llCode = (litLength>63) ? (BYTE)ZSTD_highbit32(litLength) + LL_deltaCode : LL_Code[litLength];
+ optPtr->litLengthFreq[llCode]++;
+ optPtr->litLengthSum++;
+ }
+
+ /* match offset */
+ { BYTE const offCode = (BYTE)ZSTD_highbit32(offset+1);
+ optPtr->offCodeSum++;
+ optPtr->offCodeFreq[offCode]++;
+ }
+
+ /* match Length */
+ { const BYTE ML_deltaCode = 36;
+ const BYTE mlCode = (matchLength>127) ? (BYTE)ZSTD_highbit32(matchLength) + ML_deltaCode : ML_Code[matchLength];
+ optPtr->matchLengthFreq[mlCode]++;
+ optPtr->matchLengthSum++;
+ }
+
+ ZSTD_setLog2Prices(optPtr);
+}
+
+
+#define SET_PRICE(pos, mlen_, offset_, litlen_, price_) \
+ { \
+ while (last_pos < pos) { opt[last_pos+1].price = ZSTD_MAX_PRICE; last_pos++; } \
+ opt[pos].mlen = mlen_; \
+ opt[pos].off = offset_; \
+ opt[pos].litlen = litlen_; \
+ opt[pos].price = price_; \
+ }
+
+
+/* function safe only for comparisons */
+static U32 ZSTD_readMINMATCH(const void* memPtr, U32 length)
+{
+ switch (length)
+ {
+ default :
+ case 4 : return MEM_read32(memPtr);
+ case 3 : if (MEM_isLittleEndian())
+ return MEM_read32(memPtr)<<8;
+ else
+ return MEM_read32(memPtr)>>8;
+ }
+}
+
+
+/* Update hashTable3 up to ip (excluded)
+ Assumption : always within prefix (i.e. not within extDict) */
+static
+U32 ZSTD_insertAndFindFirstIndexHash3 (ZSTD_CCtx* zc, const BYTE* ip)
+{
+ U32* const hashTable3 = zc->hashTable3;
+ U32 const hashLog3 = zc->hashLog3;
+ const BYTE* const base = zc->base;
+ U32 idx = zc->nextToUpdate3;
+ const U32 target = zc->nextToUpdate3 = (U32)(ip - base);
+ const size_t hash3 = ZSTD_hash3Ptr(ip, hashLog3);
+
+ while(idx < target) {
+ hashTable3[ZSTD_hash3Ptr(base+idx, hashLog3)] = idx;
+ idx++;
+ }
+
+ return hashTable3[hash3];
+}
+
+
+/*-*************************************
+* Binary Tree search
+***************************************/
+static U32 ZSTD_insertBtAndGetAllMatches (
+ ZSTD_CCtx* zc,
+ const BYTE* const ip, const BYTE* const iLimit,
+ U32 nbCompares, const U32 mls,
+ U32 extDict, ZSTD_match_t* matches, const U32 minMatchLen)
+{
+ const BYTE* const base = zc->base;
+ const U32 current = (U32)(ip-base);
+ const U32 hashLog = zc->appliedParams.cParams.hashLog;
+ const size_t h = ZSTD_hashPtr(ip, hashLog, mls);
+ U32* const hashTable = zc->hashTable;
+ U32 matchIndex = hashTable[h];
+ U32* const bt = zc->chainTable;
+ const U32 btLog = zc->appliedParams.cParams.chainLog - 1;
+ const U32 btMask= (1U << btLog) - 1;
+ size_t commonLengthSmaller=0, commonLengthLarger=0;
+ const BYTE* const dictBase = zc->dictBase;
+ const U32 dictLimit = zc->dictLimit;
+ const BYTE* const dictEnd = dictBase + dictLimit;
+ const BYTE* const prefixStart = base + dictLimit;
+ const U32 btLow = btMask >= current ? 0 : current - btMask;
+ const U32 windowLow = zc->lowLimit;
+ U32* smallerPtr = bt + 2*(current&btMask);
+ U32* largerPtr = bt + 2*(current&btMask) + 1;
+ U32 matchEndIdx = current+8;
+ U32 dummy32; /* to be nullified at the end */
+ U32 mnum = 0;
+
+ const U32 minMatch = (mls == 3) ? 3 : 4;
+ size_t bestLength = minMatchLen-1;
+
+ if (minMatch == 3) { /* HC3 match finder */
+ U32 const matchIndex3 = ZSTD_insertAndFindFirstIndexHash3 (zc, ip);
+ if (matchIndex3>windowLow && (current - matchIndex3 < (1<<18))) {
+ const BYTE* match;
+ size_t currentMl=0;
+ if ((!extDict) || matchIndex3 >= dictLimit) {
+ match = base + matchIndex3;
+ if (match[bestLength] == ip[bestLength]) currentMl = ZSTD_count(ip, match, iLimit);
+ } else {
+ match = dictBase + matchIndex3;
+ if (ZSTD_readMINMATCH(match, MINMATCH) == ZSTD_readMINMATCH(ip, MINMATCH)) /* assumption : matchIndex3 <= dictLimit-4 (by table construction) */
+ currentMl = ZSTD_count_2segments(ip+MINMATCH, match+MINMATCH, iLimit, dictEnd, prefixStart) + MINMATCH;
+ }
+
+ /* save best solution */
+ if (currentMl > bestLength) {
+ bestLength = currentMl;
+ matches[mnum].off = ZSTD_REP_MOVE_OPT + current - matchIndex3;
+ matches[mnum].len = (U32)currentMl;
+ mnum++;
+ if (currentMl > ZSTD_OPT_NUM) goto update;
+ if (ip+currentMl == iLimit) goto update; /* best possible, and avoid read overflow*/
+ }
+ }
+ }
+
+ hashTable[h] = current; /* Update Hash Table */
+
+ while (nbCompares-- && (matchIndex > windowLow)) {
+ U32* nextPtr = bt + 2*(matchIndex & btMask);
+ size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
+ const BYTE* match;
+
+ if ((!extDict) || (matchIndex+matchLength >= dictLimit)) {
+ match = base + matchIndex;
+ if (match[matchLength] == ip[matchLength]) {
+ matchLength += ZSTD_count(ip+matchLength+1, match+matchLength+1, iLimit) +1;
+ }
+ } else {
+ match = dictBase + matchIndex;
+ matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iLimit, dictEnd, prefixStart);
+ if (matchIndex+matchLength >= dictLimit)
+ match = base + matchIndex; /* to prepare for next usage of match[matchLength] */
+ }
+
+ if (matchLength > bestLength) {
+ if (matchLength > matchEndIdx - matchIndex) matchEndIdx = matchIndex + (U32)matchLength;
+ bestLength = matchLength;
+ matches[mnum].off = ZSTD_REP_MOVE_OPT + current - matchIndex;
+ matches[mnum].len = (U32)matchLength;
+ mnum++;
+ if (matchLength > ZSTD_OPT_NUM) break;
+ if (ip+matchLength == iLimit) /* equal : no way to know if inf or sup */
+ break; /* drop, to guarantee consistency (miss a little bit of compression) */
+ }
+
+ if (match[matchLength] < ip[matchLength]) {
+ /* match is smaller than current */
+ *smallerPtr = matchIndex; /* update smaller idx */
+ commonLengthSmaller = matchLength; /* all smaller will now have at least this guaranteed common length */
+ if (matchIndex <= btLow) { smallerPtr=&dummy32; break; } /* beyond tree size, stop the search */
+ smallerPtr = nextPtr+1; /* new "smaller" => larger of match */
+ matchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */
+ } else {
+ /* match is larger than current */
+ *largerPtr = matchIndex;
+ commonLengthLarger = matchLength;
+ if (matchIndex <= btLow) { largerPtr=&dummy32; break; } /* beyond tree size, stop the search */
+ largerPtr = nextPtr;
+ matchIndex = nextPtr[0];
+ } }
+
+ *smallerPtr = *largerPtr = 0;
+
+update:
+ zc->nextToUpdate = (matchEndIdx > current + 8) ? matchEndIdx - 8 : current+1;
+ return mnum;
+}
+
+
+/** Tree updater, providing best match */
+static U32 ZSTD_BtGetAllMatches (
+ ZSTD_CCtx* zc,
+ const BYTE* const ip, const BYTE* const iLimit,
+ const U32 maxNbAttempts, const U32 mls, ZSTD_match_t* matches, const U32 minMatchLen)
+{
+ if (ip < zc->base + zc->nextToUpdate) return 0; /* skipped area */
+ ZSTD_updateTree(zc, ip, iLimit, maxNbAttempts, mls);
+ return ZSTD_insertBtAndGetAllMatches(zc, ip, iLimit, maxNbAttempts, mls, 0, matches, minMatchLen);
+}
+
+
+static U32 ZSTD_BtGetAllMatches_selectMLS (
+ ZSTD_CCtx* zc, /* Index table will be updated */
+ const BYTE* ip, const BYTE* const iHighLimit,
+ const U32 maxNbAttempts, const U32 matchLengthSearch, ZSTD_match_t* matches, const U32 minMatchLen)
+{
+ switch(matchLengthSearch)
+ {
+ case 3 : return ZSTD_BtGetAllMatches(zc, ip, iHighLimit, maxNbAttempts, 3, matches, minMatchLen);
+ default :
+ case 4 : return ZSTD_BtGetAllMatches(zc, ip, iHighLimit, maxNbAttempts, 4, matches, minMatchLen);
+ case 5 : return ZSTD_BtGetAllMatches(zc, ip, iHighLimit, maxNbAttempts, 5, matches, minMatchLen);
+ case 7 :
+ case 6 : return ZSTD_BtGetAllMatches(zc, ip, iHighLimit, maxNbAttempts, 6, matches, minMatchLen);
+ }
+}
+
+/** Tree updater, providing best match */
+static U32 ZSTD_BtGetAllMatches_extDict (
+ ZSTD_CCtx* zc,
+ const BYTE* const ip, const BYTE* const iLimit,
+ const U32 maxNbAttempts, const U32 mls, ZSTD_match_t* matches, const U32 minMatchLen)
+{
+ if (ip < zc->base + zc->nextToUpdate) return 0; /* skipped area */
+ ZSTD_updateTree_extDict(zc, ip, iLimit, maxNbAttempts, mls);
+ return ZSTD_insertBtAndGetAllMatches(zc, ip, iLimit, maxNbAttempts, mls, 1, matches, minMatchLen);
+}
+
+
+static U32 ZSTD_BtGetAllMatches_selectMLS_extDict (
+ ZSTD_CCtx* zc, /* Index table will be updated */
+ const BYTE* ip, const BYTE* const iHighLimit,
+ const U32 maxNbAttempts, const U32 matchLengthSearch, ZSTD_match_t* matches, const U32 minMatchLen)
+{
+ switch(matchLengthSearch)
+ {
+ case 3 : return ZSTD_BtGetAllMatches_extDict(zc, ip, iHighLimit, maxNbAttempts, 3, matches, minMatchLen);
+ default :
+ case 4 : return ZSTD_BtGetAllMatches_extDict(zc, ip, iHighLimit, maxNbAttempts, 4, matches, minMatchLen);
+ case 5 : return ZSTD_BtGetAllMatches_extDict(zc, ip, iHighLimit, maxNbAttempts, 5, matches, minMatchLen);
+ case 7 :
+ case 6 : return ZSTD_BtGetAllMatches_extDict(zc, ip, iHighLimit, maxNbAttempts, 6, matches, minMatchLen);
+ }
+}
+
+
+/*-*******************************
+* Optimal parser
+*********************************/
+FORCE_INLINE_TEMPLATE
+size_t ZSTD_compressBlock_opt_generic(ZSTD_CCtx* ctx,
+ const void* src, size_t srcSize, const int ultra)
+{
+ seqStore_t* seqStorePtr = &(ctx->seqStore);
+ optState_t* optStatePtr = &(ctx->optState);
+ const BYTE* const istart = (const BYTE*)src;
+ const BYTE* ip = istart;
+ const BYTE* anchor = istart;
+ const BYTE* const iend = istart + srcSize;
+ const BYTE* const ilimit = iend - 8;
+ const BYTE* const base = ctx->base;
+ const BYTE* const prefixStart = base + ctx->dictLimit;
+
+ const U32 maxSearches = 1U << ctx->appliedParams.cParams.searchLog;
+ const U32 sufficient_len = ctx->appliedParams.cParams.targetLength;
+ const U32 mls = ctx->appliedParams.cParams.searchLength;
+ const U32 minMatch = (ctx->appliedParams.cParams.searchLength == 3) ? 3 : 4;
+
+ ZSTD_optimal_t* opt = optStatePtr->priceTable;
+ ZSTD_match_t* matches = optStatePtr->matchTable;
+ const BYTE* inr;
+ U32 offset, rep[ZSTD_REP_NUM];
+
+ /* init */
+ ctx->nextToUpdate3 = ctx->nextToUpdate;
+ ZSTD_rescaleFreqs(optStatePtr, (const BYTE*)src, srcSize);
+ ip += (ip==prefixStart);
+ { U32 i; for (i=0; i<ZSTD_REP_NUM; i++) rep[i]=seqStorePtr->rep[i]; }
+
+ /* Match Loop */
+ while (ip < ilimit) {
+ U32 cur, match_num, last_pos, litlen, price;
+ U32 u, mlen, best_mlen, best_off, litLength;
+ memset(opt, 0, sizeof(ZSTD_optimal_t));
+ last_pos = 0;
+ litlen = (U32)(ip - anchor);
+
+ /* check repCode */
+ { U32 i, last_i = ZSTD_REP_CHECK + (ip==anchor);
+ for (i=(ip == anchor); i<last_i; i++) {
+ const S32 repCur = (i==ZSTD_REP_MOVE_OPT) ? (rep[0] - 1) : rep[i];
+ if ( (repCur > 0) && (repCur < (S32)(ip-prefixStart))
+ && (ZSTD_readMINMATCH(ip, minMatch) == ZSTD_readMINMATCH(ip - repCur, minMatch))) {
+ mlen = (U32)ZSTD_count(ip+minMatch, ip+minMatch-repCur, iend) + minMatch;
+ if (mlen > sufficient_len || mlen >= ZSTD_OPT_NUM) {
+ best_mlen = mlen; best_off = i; cur = 0; last_pos = 1;
+ goto _storeSequence;
+ }
+ best_off = i - (ip == anchor);
+ do {
+ price = ZSTD_getPrice(optStatePtr, litlen, anchor, best_off, mlen - MINMATCH, ultra);
+ if (mlen > last_pos || price < opt[mlen].price)
+ SET_PRICE(mlen, mlen, i, litlen, price); /* note : macro modifies last_pos */
+ mlen--;
+ } while (mlen >= minMatch);
+ } } }
+
+ match_num = ZSTD_BtGetAllMatches_selectMLS(ctx, ip, iend, maxSearches, mls, matches, minMatch);
+
+ if (!last_pos && !match_num) { ip++; continue; }
+
+ if (match_num && (matches[match_num-1].len > sufficient_len || matches[match_num-1].len >= ZSTD_OPT_NUM)) {
+ best_mlen = matches[match_num-1].len;
+ best_off = matches[match_num-1].off;
+ cur = 0;
+ last_pos = 1;
+ goto _storeSequence;
+ }
+
+ /* set prices using matches at position = 0 */
+ best_mlen = (last_pos) ? last_pos : minMatch;
+ for (u = 0; u < match_num; u++) {
+ mlen = (u>0) ? matches[u-1].len+1 : best_mlen;
+ best_mlen = matches[u].len;
+ while (mlen <= best_mlen) {
+ price = ZSTD_getPrice(optStatePtr, litlen, anchor, matches[u].off-1, mlen - MINMATCH, ultra);
+ if (mlen > last_pos || price < opt[mlen].price)
+ SET_PRICE(mlen, mlen, matches[u].off, litlen, price); /* note : macro modifies last_pos */
+ mlen++;
+ } }
+
+ if (last_pos < minMatch) { ip++; continue; }
+
+ /* initialize opt[0] */
+ { U32 i ; for (i=0; i<ZSTD_REP_NUM; i++) opt[0].rep[i] = rep[i]; }
+ opt[0].mlen = 1;
+ opt[0].litlen = litlen;
+
+ /* check further positions */
+ for (cur = 1; cur <= last_pos; cur++) {
+ inr = ip + cur;
+
+ if (opt[cur-1].mlen == 1) {
+ litlen = opt[cur-1].litlen + 1;
+ if (cur > litlen) {
+ price = opt[cur - litlen].price + ZSTD_getLiteralPrice(optStatePtr, litlen, inr-litlen);
+ } else
+ price = ZSTD_getLiteralPrice(optStatePtr, litlen, anchor);
+ } else {
+ litlen = 1;
+ price = opt[cur - 1].price + ZSTD_getLiteralPrice(optStatePtr, litlen, inr-1);
+ }
+
+ if (cur > last_pos || price <= opt[cur].price)
+ SET_PRICE(cur, 1, 0, litlen, price);
+
+ if (cur == last_pos) break;
+
+ if (inr > ilimit) /* last match must start at a minimum distance of 8 from oend */
+ continue;
+
+ mlen = opt[cur].mlen;
+ if (opt[cur].off > ZSTD_REP_MOVE_OPT) {
+ opt[cur].rep[2] = opt[cur-mlen].rep[1];
+ opt[cur].rep[1] = opt[cur-mlen].rep[0];
+ opt[cur].rep[0] = opt[cur].off - ZSTD_REP_MOVE_OPT;
+ } else {
+ opt[cur].rep[2] = (opt[cur].off > 1) ? opt[cur-mlen].rep[1] : opt[cur-mlen].rep[2];
+ opt[cur].rep[1] = (opt[cur].off > 0) ? opt[cur-mlen].rep[0] : opt[cur-mlen].rep[1];
+ /* If opt[cur].off == ZSTD_REP_MOVE_OPT, then mlen != 1.
+ * offset ZSTD_REP_MOVE_OPT is used for the special case
+ * litLength == 0, where offset 0 means something special.
+ * mlen == 1 means the previous byte was stored as a literal,
+ * so they are mutually exclusive.
+ */
+ assert(!(opt[cur].off == ZSTD_REP_MOVE_OPT && mlen == 1));
+ opt[cur].rep[0] = (opt[cur].off == ZSTD_REP_MOVE_OPT) ? (opt[cur-mlen].rep[0] - 1) : (opt[cur-mlen].rep[opt[cur].off]);
+ }
+
+ best_mlen = minMatch;
+ { U32 i, last_i = ZSTD_REP_CHECK + (mlen != 1);
+ for (i=(opt[cur].mlen != 1); i<last_i; i++) { /* check rep */
+ const S32 repCur = (i==ZSTD_REP_MOVE_OPT) ? (opt[cur].rep[0] - 1) : opt[cur].rep[i];
+ if ( (repCur > 0) && (repCur < (S32)(inr-prefixStart))
+ && (ZSTD_readMINMATCH(inr, minMatch) == ZSTD_readMINMATCH(inr - repCur, minMatch))) {
+ mlen = (U32)ZSTD_count(inr+minMatch, inr+minMatch - repCur, iend) + minMatch;
+
+ if (mlen > sufficient_len || cur + mlen >= ZSTD_OPT_NUM) {
+ best_mlen = mlen; best_off = i; last_pos = cur + 1;
+ goto _storeSequence;
+ }
+
+ best_off = i - (opt[cur].mlen != 1);
+ if (mlen > best_mlen) best_mlen = mlen;
+
+ do {
+ if (opt[cur].mlen == 1) {
+ litlen = opt[cur].litlen;
+ if (cur > litlen) {
+ price = opt[cur - litlen].price + ZSTD_getPrice(optStatePtr, litlen, inr-litlen, best_off, mlen - MINMATCH, ultra);
+ } else
+ price = ZSTD_getPrice(optStatePtr, litlen, anchor, best_off, mlen - MINMATCH, ultra);
+ } else {
+ litlen = 0;
+ price = opt[cur].price + ZSTD_getPrice(optStatePtr, 0, NULL, best_off, mlen - MINMATCH, ultra);
+ }
+
+ if (cur + mlen > last_pos || price <= opt[cur + mlen].price)
+ SET_PRICE(cur + mlen, mlen, i, litlen, price);
+ mlen--;
+ } while (mlen >= minMatch);
+ } } }
+
+ match_num = ZSTD_BtGetAllMatches_selectMLS(ctx, inr, iend, maxSearches, mls, matches, best_mlen);
+
+ if (match_num > 0 && (matches[match_num-1].len > sufficient_len || cur + matches[match_num-1].len >= ZSTD_OPT_NUM)) {
+ best_mlen = matches[match_num-1].len;
+ best_off = matches[match_num-1].off;
+ last_pos = cur + 1;
+ goto _storeSequence;
+ }
+
+ /* set prices using matches at position = cur */
+ for (u = 0; u < match_num; u++) {
+ mlen = (u>0) ? matches[u-1].len+1 : best_mlen;
+ best_mlen = matches[u].len;
+
+ while (mlen <= best_mlen) {
+ if (opt[cur].mlen == 1) {
+ litlen = opt[cur].litlen;
+ if (cur > litlen)
+ price = opt[cur - litlen].price + ZSTD_getPrice(optStatePtr, litlen, ip+cur-litlen, matches[u].off-1, mlen - MINMATCH, ultra);
+ else
+ price = ZSTD_getPrice(optStatePtr, litlen, anchor, matches[u].off-1, mlen - MINMATCH, ultra);
+ } else {
+ litlen = 0;
+ price = opt[cur].price + ZSTD_getPrice(optStatePtr, 0, NULL, matches[u].off-1, mlen - MINMATCH, ultra);
+ }
+
+ if (cur + mlen > last_pos || (price < opt[cur + mlen].price))
+ SET_PRICE(cur + mlen, mlen, matches[u].off, litlen, price);
+
+ mlen++;
+ } } }
+
+ best_mlen = opt[last_pos].mlen;
+ best_off = opt[last_pos].off;
+ cur = last_pos - best_mlen;
+
+ /* store sequence */
+_storeSequence: /* cur, last_pos, best_mlen, best_off have to be set */
+ opt[0].mlen = 1;
+
+ while (1) {
+ mlen = opt[cur].mlen;
+ offset = opt[cur].off;
+ opt[cur].mlen = best_mlen;
+ opt[cur].off = best_off;
+ best_mlen = mlen;
+ best_off = offset;
+ if (mlen > cur) break;
+ cur -= mlen;
+ }
+
+ for (u = 0; u <= last_pos;) {
+ u += opt[u].mlen;
+ }
+
+ for (cur=0; cur < last_pos; ) {
+ mlen = opt[cur].mlen;
+ if (mlen == 1) { ip++; cur++; continue; }
+ offset = opt[cur].off;
+ cur += mlen;
+ litLength = (U32)(ip - anchor);
+
+ if (offset > ZSTD_REP_MOVE_OPT) {
+ rep[2] = rep[1];
+ rep[1] = rep[0];
+ rep[0] = offset - ZSTD_REP_MOVE_OPT;
+ offset--;
+ } else {
+ if (offset != 0) {
+ best_off = (offset==ZSTD_REP_MOVE_OPT) ? (rep[0] - 1) : (rep[offset]);
+ if (offset != 1) rep[2] = rep[1];
+ rep[1] = rep[0];
+ rep[0] = best_off;
+ }
+ if (litLength==0) offset--;
+ }
+
+ ZSTD_updatePrice(optStatePtr, litLength, anchor, offset, mlen-MINMATCH);
+ ZSTD_storeSeq(seqStorePtr, litLength, anchor, offset, mlen-MINMATCH);
+ anchor = ip = ip + mlen;
+ } } /* for (cur=0; cur < last_pos; ) */
+
+ /* Save reps for next block */
+ { int i; for (i=0; i<ZSTD_REP_NUM; i++) seqStorePtr->repToConfirm[i] = rep[i]; }
+
+ /* Return the last literals size */
+ return iend - anchor;
+}
+
+
+size_t ZSTD_compressBlock_btopt(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
+{
+ return ZSTD_compressBlock_opt_generic(ctx, src, srcSize, 0);
+}
+
+size_t ZSTD_compressBlock_btultra(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
+{
+ return ZSTD_compressBlock_opt_generic(ctx, src, srcSize, 1);
+}
+
+
+FORCE_INLINE_TEMPLATE
+size_t ZSTD_compressBlock_opt_extDict_generic(ZSTD_CCtx* ctx,
+ const void* src, size_t srcSize, const int ultra)
+{
+ seqStore_t* seqStorePtr = &(ctx->seqStore);
+ optState_t* optStatePtr = &(ctx->optState);
+ const BYTE* const istart = (const BYTE*)src;
+ const BYTE* ip = istart;
+ const BYTE* anchor = istart;
+ const BYTE* const iend = istart + srcSize;
+ const BYTE* const ilimit = iend - 8;
+ const BYTE* const base = ctx->base;
+ const U32 lowestIndex = ctx->lowLimit;
+ const U32 dictLimit = ctx->dictLimit;
+ const BYTE* const prefixStart = base + dictLimit;
+ const BYTE* const dictBase = ctx->dictBase;
+ const BYTE* const dictEnd = dictBase + dictLimit;
+
+ const U32 maxSearches = 1U << ctx->appliedParams.cParams.searchLog;
+ const U32 sufficient_len = ctx->appliedParams.cParams.targetLength;
+ const U32 mls = ctx->appliedParams.cParams.searchLength;
+ const U32 minMatch = (ctx->appliedParams.cParams.searchLength == 3) ? 3 : 4;
+
+ ZSTD_optimal_t* opt = optStatePtr->priceTable;
+ ZSTD_match_t* matches = optStatePtr->matchTable;
+ const BYTE* inr;
+
+ /* init */
+ U32 offset, rep[ZSTD_REP_NUM];
+ { U32 i; for (i=0; i<ZSTD_REP_NUM; i++) rep[i]=seqStorePtr->rep[i]; }
+
+ ctx->nextToUpdate3 = ctx->nextToUpdate;
+ ZSTD_rescaleFreqs(optStatePtr, (const BYTE*)src, srcSize);
+ ip += (ip==prefixStart);
+
+ /* Match Loop */
+ while (ip < ilimit) {
+ U32 cur, match_num, last_pos, litlen, price;
+ U32 u, mlen, best_mlen, best_off, litLength;
+ U32 current = (U32)(ip-base);
+ memset(opt, 0, sizeof(ZSTD_optimal_t));
+ last_pos = 0;
+ opt[0].litlen = (U32)(ip - anchor);
+
+ /* check repCode */
+ { U32 i, last_i = ZSTD_REP_CHECK + (ip==anchor);
+ for (i = (ip==anchor); i<last_i; i++) {
+ const S32 repCur = (i==ZSTD_REP_MOVE_OPT) ? (rep[0] - 1) : rep[i];
+ const U32 repIndex = (U32)(current - repCur);
+ const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
+ const BYTE* const repMatch = repBase + repIndex;
+ if ( (repCur > 0 && repCur <= (S32)current)
+ && (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex>lowestIndex)) /* intentional overflow */
+ && (ZSTD_readMINMATCH(ip, minMatch) == ZSTD_readMINMATCH(repMatch, minMatch)) ) {
+ /* repcode detected we should take it */
+ const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
+ mlen = (U32)ZSTD_count_2segments(ip+minMatch, repMatch+minMatch, iend, repEnd, prefixStart) + minMatch;
+
+ if (mlen > sufficient_len || mlen >= ZSTD_OPT_NUM) {
+ best_mlen = mlen; best_off = i; cur = 0; last_pos = 1;
+ goto _storeSequence;
+ }
+
+ best_off = i - (ip==anchor);
+ litlen = opt[0].litlen;
+ do {
+ price = ZSTD_getPrice(optStatePtr, litlen, anchor, best_off, mlen - MINMATCH, ultra);
+ if (mlen > last_pos || price < opt[mlen].price)
+ SET_PRICE(mlen, mlen, i, litlen, price); /* note : macro modifies last_pos */
+ mlen--;
+ } while (mlen >= minMatch);
+ } } }
+
+ match_num = ZSTD_BtGetAllMatches_selectMLS_extDict(ctx, ip, iend, maxSearches, mls, matches, minMatch); /* first search (depth 0) */
+
+ if (!last_pos && !match_num) { ip++; continue; }
+
+ { U32 i; for (i=0; i<ZSTD_REP_NUM; i++) opt[0].rep[i] = rep[i]; }
+ opt[0].mlen = 1;
+
+ if (match_num && (matches[match_num-1].len > sufficient_len || matches[match_num-1].len >= ZSTD_OPT_NUM)) {
+ best_mlen = matches[match_num-1].len;
+ best_off = matches[match_num-1].off;
+ cur = 0;
+ last_pos = 1;
+ goto _storeSequence;
+ }
+
+ best_mlen = (last_pos) ? last_pos : minMatch;
+
+ /* set prices using matches at position = 0 */
+ for (u = 0; u < match_num; u++) {
+ mlen = (u>0) ? matches[u-1].len+1 : best_mlen;
+ best_mlen = matches[u].len;
+ litlen = opt[0].litlen;
+ while (mlen <= best_mlen) {
+ price = ZSTD_getPrice(optStatePtr, litlen, anchor, matches[u].off-1, mlen - MINMATCH, ultra);
+ if (mlen > last_pos || price < opt[mlen].price)
+ SET_PRICE(mlen, mlen, matches[u].off, litlen, price);
+ mlen++;
+ } }
+
+ if (last_pos < minMatch) {
+ ip++; continue;
+ }
+
+ /* check further positions */
+ for (cur = 1; cur <= last_pos; cur++) {
+ inr = ip + cur;
+
+ if (opt[cur-1].mlen == 1) {
+ litlen = opt[cur-1].litlen + 1;
+ if (cur > litlen) {
+ price = opt[cur - litlen].price + ZSTD_getLiteralPrice(optStatePtr, litlen, inr-litlen);
+ } else
+ price = ZSTD_getLiteralPrice(optStatePtr, litlen, anchor);
+ } else {
+ litlen = 1;
+ price = opt[cur - 1].price + ZSTD_getLiteralPrice(optStatePtr, litlen, inr-1);
+ }
+
+ if (cur > last_pos || price <= opt[cur].price)
+ SET_PRICE(cur, 1, 0, litlen, price);
+
+ if (cur == last_pos) break;
+
+ if (inr > ilimit) /* last match must start at a minimum distance of 8 from oend */
+ continue;
+
+ mlen = opt[cur].mlen;
+ if (opt[cur].off > ZSTD_REP_MOVE_OPT) {
+ opt[cur].rep[2] = opt[cur-mlen].rep[1];
+ opt[cur].rep[1] = opt[cur-mlen].rep[0];
+ opt[cur].rep[0] = opt[cur].off - ZSTD_REP_MOVE_OPT;
+ } else {
+ opt[cur].rep[2] = (opt[cur].off > 1) ? opt[cur-mlen].rep[1] : opt[cur-mlen].rep[2];
+ opt[cur].rep[1] = (opt[cur].off > 0) ? opt[cur-mlen].rep[0] : opt[cur-mlen].rep[1];
+ assert(!(opt[cur].off == ZSTD_REP_MOVE_OPT && mlen == 1));
+ opt[cur].rep[0] = (opt[cur].off == ZSTD_REP_MOVE_OPT) ? (opt[cur-mlen].rep[0] - 1) : (opt[cur-mlen].rep[opt[cur].off]);
+ }
+
+ best_mlen = minMatch;
+ { U32 i, last_i = ZSTD_REP_CHECK + (mlen != 1);
+ for (i = (mlen != 1); i<last_i; i++) {
+ const S32 repCur = (i==ZSTD_REP_MOVE_OPT) ? (opt[cur].rep[0] - 1) : opt[cur].rep[i];
+ const U32 repIndex = (U32)(current+cur - repCur);
+ const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
+ const BYTE* const repMatch = repBase + repIndex;
+ if ( (repCur > 0 && repCur <= (S32)(current+cur))
+ && (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex>lowestIndex)) /* intentional overflow */
+ && (ZSTD_readMINMATCH(inr, minMatch) == ZSTD_readMINMATCH(repMatch, minMatch)) ) {
+ /* repcode detected */
+ const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
+ mlen = (U32)ZSTD_count_2segments(inr+minMatch, repMatch+minMatch, iend, repEnd, prefixStart) + minMatch;
+
+ if (mlen > sufficient_len || cur + mlen >= ZSTD_OPT_NUM) {
+ best_mlen = mlen; best_off = i; last_pos = cur + 1;
+ goto _storeSequence;
+ }
+
+ best_off = i - (opt[cur].mlen != 1);
+ if (mlen > best_mlen) best_mlen = mlen;
+
+ do {
+ if (opt[cur].mlen == 1) {
+ litlen = opt[cur].litlen;
+ if (cur > litlen) {
+ price = opt[cur - litlen].price + ZSTD_getPrice(optStatePtr, litlen, inr-litlen, best_off, mlen - MINMATCH, ultra);
+ } else
+ price = ZSTD_getPrice(optStatePtr, litlen, anchor, best_off, mlen - MINMATCH, ultra);
+ } else {
+ litlen = 0;
+ price = opt[cur].price + ZSTD_getPrice(optStatePtr, 0, NULL, best_off, mlen - MINMATCH, ultra);
+ }
+
+ if (cur + mlen > last_pos || price <= opt[cur + mlen].price)
+ SET_PRICE(cur + mlen, mlen, i, litlen, price);
+ mlen--;
+ } while (mlen >= minMatch);
+ } } }
+
+ match_num = ZSTD_BtGetAllMatches_selectMLS_extDict(ctx, inr, iend, maxSearches, mls, matches, minMatch);
+
+ if (match_num > 0 && (matches[match_num-1].len > sufficient_len || cur + matches[match_num-1].len >= ZSTD_OPT_NUM)) {
+ best_mlen = matches[match_num-1].len;
+ best_off = matches[match_num-1].off;
+ last_pos = cur + 1;
+ goto _storeSequence;
+ }
+
+ /* set prices using matches at position = cur */
+ for (u = 0; u < match_num; u++) {
+ mlen = (u>0) ? matches[u-1].len+1 : best_mlen;
+ best_mlen = matches[u].len;
+
+ while (mlen <= best_mlen) {
+ if (opt[cur].mlen == 1) {
+ litlen = opt[cur].litlen;
+ if (cur > litlen)
+ price = opt[cur - litlen].price + ZSTD_getPrice(optStatePtr, litlen, ip+cur-litlen, matches[u].off-1, mlen - MINMATCH, ultra);
+ else
+ price = ZSTD_getPrice(optStatePtr, litlen, anchor, matches[u].off-1, mlen - MINMATCH, ultra);
+ } else {
+ litlen = 0;
+ price = opt[cur].price + ZSTD_getPrice(optStatePtr, 0, NULL, matches[u].off-1, mlen - MINMATCH, ultra);
+ }
+
+ if (cur + mlen > last_pos || (price < opt[cur + mlen].price))
+ SET_PRICE(cur + mlen, mlen, matches[u].off, litlen, price);
+
+ mlen++;
+ } } } /* for (cur = 1; cur <= last_pos; cur++) */
+
+ best_mlen = opt[last_pos].mlen;
+ best_off = opt[last_pos].off;
+ cur = last_pos - best_mlen;
+
+ /* store sequence */
+_storeSequence: /* cur, last_pos, best_mlen, best_off have to be set */
+ opt[0].mlen = 1;
+
+ while (1) {
+ mlen = opt[cur].mlen;
+ offset = opt[cur].off;
+ opt[cur].mlen = best_mlen;
+ opt[cur].off = best_off;
+ best_mlen = mlen;
+ best_off = offset;
+ if (mlen > cur) break;
+ cur -= mlen;
+ }
+
+ for (u = 0; u <= last_pos; ) {
+ u += opt[u].mlen;
+ }
+
+ for (cur=0; cur < last_pos; ) {
+ mlen = opt[cur].mlen;
+ if (mlen == 1) { ip++; cur++; continue; }
+ offset = opt[cur].off;
+ cur += mlen;
+ litLength = (U32)(ip - anchor);
+
+ if (offset > ZSTD_REP_MOVE_OPT) {
+ rep[2] = rep[1];
+ rep[1] = rep[0];
+ rep[0] = offset - ZSTD_REP_MOVE_OPT;
+ offset--;
+ } else {
+ if (offset != 0) {
+ best_off = (offset==ZSTD_REP_MOVE_OPT) ? (rep[0] - 1) : (rep[offset]);
+ if (offset != 1) rep[2] = rep[1];
+ rep[1] = rep[0];
+ rep[0] = best_off;
+ }
+
+ if (litLength==0) offset--;
+ }
+
+ ZSTD_updatePrice(optStatePtr, litLength, anchor, offset, mlen-MINMATCH);
+ ZSTD_storeSeq(seqStorePtr, litLength, anchor, offset, mlen-MINMATCH);
+ anchor = ip = ip + mlen;
+ } } /* for (cur=0; cur < last_pos; ) */
+
+ /* Save reps for next block */
+ { int i; for (i=0; i<ZSTD_REP_NUM; i++) seqStorePtr->repToConfirm[i] = rep[i]; }
+
+ /* Return the last literals size */
+ return iend - anchor;
+}
+
+
+size_t ZSTD_compressBlock_btopt_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
+{
+ return ZSTD_compressBlock_opt_extDict_generic(ctx, src, srcSize, 0);
+}
+
+size_t ZSTD_compressBlock_btultra_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
+{
+ return ZSTD_compressBlock_opt_extDict_generic(ctx, src, srcSize, 1);
+}
diff --git a/thirdparty/zstd/compress/zstd_opt.h b/thirdparty/zstd/compress/zstd_opt.h
index ae24732c7d..816a1fabbf 100644
--- a/thirdparty/zstd/compress/zstd_opt.h
+++ b/thirdparty/zstd/compress/zstd_opt.h
@@ -5,934 +5,26 @@
* This source code is licensed under both the BSD-style license (found in the
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
* in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
*/
+#ifndef ZSTD_OPT_H
+#define ZSTD_OPT_H
-/* Note : this file is intended to be included within zstd_compress.c */
+#include "zstd_compress.h"
+#if defined (__cplusplus)
+extern "C" {
+#endif
-#ifndef ZSTD_OPT_H_91842398743
-#define ZSTD_OPT_H_91842398743
+size_t ZSTD_compressBlock_btopt(ZSTD_CCtx* ctx, const void* src, size_t srcSize);
+size_t ZSTD_compressBlock_btultra(ZSTD_CCtx* ctx, const void* src, size_t srcSize);
+size_t ZSTD_compressBlock_btopt_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize);
+size_t ZSTD_compressBlock_btultra_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize);
-#define ZSTD_LITFREQ_ADD 2
-#define ZSTD_FREQ_DIV 4
-#define ZSTD_MAX_PRICE (1<<30)
-
-/*-*************************************
-* Price functions for optimal parser
-***************************************/
-static void ZSTD_setLog2Prices(optState_t* optPtr)
-{
- optPtr->log2matchLengthSum = ZSTD_highbit32(optPtr->matchLengthSum+1);
- optPtr->log2litLengthSum = ZSTD_highbit32(optPtr->litLengthSum+1);
- optPtr->log2litSum = ZSTD_highbit32(optPtr->litSum+1);
- optPtr->log2offCodeSum = ZSTD_highbit32(optPtr->offCodeSum+1);
- optPtr->factor = 1 + ((optPtr->litSum>>5) / optPtr->litLengthSum) + ((optPtr->litSum<<1) / (optPtr->litSum + optPtr->matchSum));
-}
-
-
-static void ZSTD_rescaleFreqs(optState_t* optPtr, const BYTE* src, size_t srcSize)
-{
- unsigned u;
-
- optPtr->cachedLiterals = NULL;
- optPtr->cachedPrice = optPtr->cachedLitLength = 0;
- optPtr->staticPrices = 0;
-
- if (optPtr->litLengthSum == 0) {
- if (srcSize <= 1024) optPtr->staticPrices = 1;
-
- assert(optPtr->litFreq!=NULL);
- for (u=0; u<=MaxLit; u++)
- optPtr->litFreq[u] = 0;
- for (u=0; u<srcSize; u++)
- optPtr->litFreq[src[u]]++;
-
- optPtr->litSum = 0;
- optPtr->litLengthSum = MaxLL+1;
- optPtr->matchLengthSum = MaxML+1;
- optPtr->offCodeSum = (MaxOff+1);
- optPtr->matchSum = (ZSTD_LITFREQ_ADD<<Litbits);
-
- for (u=0; u<=MaxLit; u++) {
- optPtr->litFreq[u] = 1 + (optPtr->litFreq[u]>>ZSTD_FREQ_DIV);
- optPtr->litSum += optPtr->litFreq[u];
- }
- for (u=0; u<=MaxLL; u++)
- optPtr->litLengthFreq[u] = 1;
- for (u=0; u<=MaxML; u++)
- optPtr->matchLengthFreq[u] = 1;
- for (u=0; u<=MaxOff; u++)
- optPtr->offCodeFreq[u] = 1;
- } else {
- optPtr->matchLengthSum = 0;
- optPtr->litLengthSum = 0;
- optPtr->offCodeSum = 0;
- optPtr->matchSum = 0;
- optPtr->litSum = 0;
-
- for (u=0; u<=MaxLit; u++) {
- optPtr->litFreq[u] = 1 + (optPtr->litFreq[u]>>(ZSTD_FREQ_DIV+1));
- optPtr->litSum += optPtr->litFreq[u];
- }
- for (u=0; u<=MaxLL; u++) {
- optPtr->litLengthFreq[u] = 1 + (optPtr->litLengthFreq[u]>>(ZSTD_FREQ_DIV+1));
- optPtr->litLengthSum += optPtr->litLengthFreq[u];
- }
- for (u=0; u<=MaxML; u++) {
- optPtr->matchLengthFreq[u] = 1 + (optPtr->matchLengthFreq[u]>>ZSTD_FREQ_DIV);
- optPtr->matchLengthSum += optPtr->matchLengthFreq[u];
- optPtr->matchSum += optPtr->matchLengthFreq[u] * (u + 3);
- }
- optPtr->matchSum *= ZSTD_LITFREQ_ADD;
- for (u=0; u<=MaxOff; u++) {
- optPtr->offCodeFreq[u] = 1 + (optPtr->offCodeFreq[u]>>ZSTD_FREQ_DIV);
- optPtr->offCodeSum += optPtr->offCodeFreq[u];
- }
- }
-
- ZSTD_setLog2Prices(optPtr);
-}
-
-
-static U32 ZSTD_getLiteralPrice(optState_t* optPtr, U32 litLength, const BYTE* literals)
-{
- U32 price, u;
-
- if (optPtr->staticPrices)
- return ZSTD_highbit32((U32)litLength+1) + (litLength*6);
-
- if (litLength == 0)
- return optPtr->log2litLengthSum - ZSTD_highbit32(optPtr->litLengthFreq[0]+1);
-
- /* literals */
- if (optPtr->cachedLiterals == literals) {
- U32 const additional = litLength - optPtr->cachedLitLength;
- const BYTE* literals2 = optPtr->cachedLiterals + optPtr->cachedLitLength;
- price = optPtr->cachedPrice + additional * optPtr->log2litSum;
- for (u=0; u < additional; u++)
- price -= ZSTD_highbit32(optPtr->litFreq[literals2[u]]+1);
- optPtr->cachedPrice = price;
- optPtr->cachedLitLength = litLength;
- } else {
- price = litLength * optPtr->log2litSum;
- for (u=0; u < litLength; u++)
- price -= ZSTD_highbit32(optPtr->litFreq[literals[u]]+1);
-
- if (litLength >= 12) {
- optPtr->cachedLiterals = literals;
- optPtr->cachedPrice = price;
- optPtr->cachedLitLength = litLength;
- }
- }
-
- /* literal Length */
- { const BYTE LL_deltaCode = 19;
- const BYTE llCode = (litLength>63) ? (BYTE)ZSTD_highbit32(litLength) + LL_deltaCode : LL_Code[litLength];
- price += LL_bits[llCode] + optPtr->log2litLengthSum - ZSTD_highbit32(optPtr->litLengthFreq[llCode]+1);
- }
-
- return price;
-}
-
-
-FORCE_INLINE_TEMPLATE U32 ZSTD_getPrice(optState_t* optPtr, U32 litLength, const BYTE* literals, U32 offset, U32 matchLength, const int ultra)
-{
- /* offset */
- U32 price;
- BYTE const offCode = (BYTE)ZSTD_highbit32(offset+1);
-
- if (optPtr->staticPrices)
- return ZSTD_getLiteralPrice(optPtr, litLength, literals) + ZSTD_highbit32((U32)matchLength+1) + 16 + offCode;
-
- price = offCode + optPtr->log2offCodeSum - ZSTD_highbit32(optPtr->offCodeFreq[offCode]+1);
- if (!ultra && offCode >= 20) price += (offCode-19)*2;
-
- /* match Length */
- { const BYTE ML_deltaCode = 36;
- const BYTE mlCode = (matchLength>127) ? (BYTE)ZSTD_highbit32(matchLength) + ML_deltaCode : ML_Code[matchLength];
- price += ML_bits[mlCode] + optPtr->log2matchLengthSum - ZSTD_highbit32(optPtr->matchLengthFreq[mlCode]+1);
- }
-
- return price + ZSTD_getLiteralPrice(optPtr, litLength, literals) + optPtr->factor;
-}
-
-
-static void ZSTD_updatePrice(optState_t* optPtr, U32 litLength, const BYTE* literals, U32 offset, U32 matchLength)
-{
- U32 u;
-
- /* literals */
- optPtr->litSum += litLength*ZSTD_LITFREQ_ADD;
- for (u=0; u < litLength; u++)
- optPtr->litFreq[literals[u]] += ZSTD_LITFREQ_ADD;
-
- /* literal Length */
- { const BYTE LL_deltaCode = 19;
- const BYTE llCode = (litLength>63) ? (BYTE)ZSTD_highbit32(litLength) + LL_deltaCode : LL_Code[litLength];
- optPtr->litLengthFreq[llCode]++;
- optPtr->litLengthSum++;
- }
-
- /* match offset */
- { BYTE const offCode = (BYTE)ZSTD_highbit32(offset+1);
- optPtr->offCodeSum++;
- optPtr->offCodeFreq[offCode]++;
- }
-
- /* match Length */
- { const BYTE ML_deltaCode = 36;
- const BYTE mlCode = (matchLength>127) ? (BYTE)ZSTD_highbit32(matchLength) + ML_deltaCode : ML_Code[matchLength];
- optPtr->matchLengthFreq[mlCode]++;
- optPtr->matchLengthSum++;
- }
-
- ZSTD_setLog2Prices(optPtr);
-}
-
-
-#define SET_PRICE(pos, mlen_, offset_, litlen_, price_) \
- { \
- while (last_pos < pos) { opt[last_pos+1].price = ZSTD_MAX_PRICE; last_pos++; } \
- opt[pos].mlen = mlen_; \
- opt[pos].off = offset_; \
- opt[pos].litlen = litlen_; \
- opt[pos].price = price_; \
- }
-
-
-/* function safe only for comparisons */
-static U32 ZSTD_readMINMATCH(const void* memPtr, U32 length)
-{
- switch (length)
- {
- default :
- case 4 : return MEM_read32(memPtr);
- case 3 : if (MEM_isLittleEndian())
- return MEM_read32(memPtr)<<8;
- else
- return MEM_read32(memPtr)>>8;
- }
-}
-
-
-/* Update hashTable3 up to ip (excluded)
- Assumption : always within prefix (i.e. not within extDict) */
-static
-U32 ZSTD_insertAndFindFirstIndexHash3 (ZSTD_CCtx* zc, const BYTE* ip)
-{
- U32* const hashTable3 = zc->hashTable3;
- U32 const hashLog3 = zc->hashLog3;
- const BYTE* const base = zc->base;
- U32 idx = zc->nextToUpdate3;
- const U32 target = zc->nextToUpdate3 = (U32)(ip - base);
- const size_t hash3 = ZSTD_hash3Ptr(ip, hashLog3);
-
- while(idx < target) {
- hashTable3[ZSTD_hash3Ptr(base+idx, hashLog3)] = idx;
- idx++;
- }
-
- return hashTable3[hash3];
-}
-
-
-/*-*************************************
-* Binary Tree search
-***************************************/
-static U32 ZSTD_insertBtAndGetAllMatches (
- ZSTD_CCtx* zc,
- const BYTE* const ip, const BYTE* const iLimit,
- U32 nbCompares, const U32 mls,
- U32 extDict, ZSTD_match_t* matches, const U32 minMatchLen)
-{
- const BYTE* const base = zc->base;
- const U32 current = (U32)(ip-base);
- const U32 hashLog = zc->appliedParams.cParams.hashLog;
- const size_t h = ZSTD_hashPtr(ip, hashLog, mls);
- U32* const hashTable = zc->hashTable;
- U32 matchIndex = hashTable[h];
- U32* const bt = zc->chainTable;
- const U32 btLog = zc->appliedParams.cParams.chainLog - 1;
- const U32 btMask= (1U << btLog) - 1;
- size_t commonLengthSmaller=0, commonLengthLarger=0;
- const BYTE* const dictBase = zc->dictBase;
- const U32 dictLimit = zc->dictLimit;
- const BYTE* const dictEnd = dictBase + dictLimit;
- const BYTE* const prefixStart = base + dictLimit;
- const U32 btLow = btMask >= current ? 0 : current - btMask;
- const U32 windowLow = zc->lowLimit;
- U32* smallerPtr = bt + 2*(current&btMask);
- U32* largerPtr = bt + 2*(current&btMask) + 1;
- U32 matchEndIdx = current+8;
- U32 dummy32; /* to be nullified at the end */
- U32 mnum = 0;
-
- const U32 minMatch = (mls == 3) ? 3 : 4;
- size_t bestLength = minMatchLen-1;
-
- if (minMatch == 3) { /* HC3 match finder */
- U32 const matchIndex3 = ZSTD_insertAndFindFirstIndexHash3 (zc, ip);
- if (matchIndex3>windowLow && (current - matchIndex3 < (1<<18))) {
- const BYTE* match;
- size_t currentMl=0;
- if ((!extDict) || matchIndex3 >= dictLimit) {
- match = base + matchIndex3;
- if (match[bestLength] == ip[bestLength]) currentMl = ZSTD_count(ip, match, iLimit);
- } else {
- match = dictBase + matchIndex3;
- if (ZSTD_readMINMATCH(match, MINMATCH) == ZSTD_readMINMATCH(ip, MINMATCH)) /* assumption : matchIndex3 <= dictLimit-4 (by table construction) */
- currentMl = ZSTD_count_2segments(ip+MINMATCH, match+MINMATCH, iLimit, dictEnd, prefixStart) + MINMATCH;
- }
-
- /* save best solution */
- if (currentMl > bestLength) {
- bestLength = currentMl;
- matches[mnum].off = ZSTD_REP_MOVE_OPT + current - matchIndex3;
- matches[mnum].len = (U32)currentMl;
- mnum++;
- if (currentMl > ZSTD_OPT_NUM) goto update;
- if (ip+currentMl == iLimit) goto update; /* best possible, and avoid read overflow*/
- }
- }
- }
-
- hashTable[h] = current; /* Update Hash Table */
-
- while (nbCompares-- && (matchIndex > windowLow)) {
- U32* nextPtr = bt + 2*(matchIndex & btMask);
- size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
- const BYTE* match;
-
- if ((!extDict) || (matchIndex+matchLength >= dictLimit)) {
- match = base + matchIndex;
- if (match[matchLength] == ip[matchLength]) {
- matchLength += ZSTD_count(ip+matchLength+1, match+matchLength+1, iLimit) +1;
- }
- } else {
- match = dictBase + matchIndex;
- matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iLimit, dictEnd, prefixStart);
- if (matchIndex+matchLength >= dictLimit)
- match = base + matchIndex; /* to prepare for next usage of match[matchLength] */
- }
-
- if (matchLength > bestLength) {
- if (matchLength > matchEndIdx - matchIndex) matchEndIdx = matchIndex + (U32)matchLength;
- bestLength = matchLength;
- matches[mnum].off = ZSTD_REP_MOVE_OPT + current - matchIndex;
- matches[mnum].len = (U32)matchLength;
- mnum++;
- if (matchLength > ZSTD_OPT_NUM) break;
- if (ip+matchLength == iLimit) /* equal : no way to know if inf or sup */
- break; /* drop, to guarantee consistency (miss a little bit of compression) */
- }
-
- if (match[matchLength] < ip[matchLength]) {
- /* match is smaller than current */
- *smallerPtr = matchIndex; /* update smaller idx */
- commonLengthSmaller = matchLength; /* all smaller will now have at least this guaranteed common length */
- if (matchIndex <= btLow) { smallerPtr=&dummy32; break; } /* beyond tree size, stop the search */
- smallerPtr = nextPtr+1; /* new "smaller" => larger of match */
- matchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */
- } else {
- /* match is larger than current */
- *largerPtr = matchIndex;
- commonLengthLarger = matchLength;
- if (matchIndex <= btLow) { largerPtr=&dummy32; break; } /* beyond tree size, stop the search */
- largerPtr = nextPtr;
- matchIndex = nextPtr[0];
- } }
-
- *smallerPtr = *largerPtr = 0;
-
-update:
- zc->nextToUpdate = (matchEndIdx > current + 8) ? matchEndIdx - 8 : current+1;
- return mnum;
-}
-
-
-/** Tree updater, providing best match */
-static U32 ZSTD_BtGetAllMatches (
- ZSTD_CCtx* zc,
- const BYTE* const ip, const BYTE* const iLimit,
- const U32 maxNbAttempts, const U32 mls, ZSTD_match_t* matches, const U32 minMatchLen)
-{
- if (ip < zc->base + zc->nextToUpdate) return 0; /* skipped area */
- ZSTD_updateTree(zc, ip, iLimit, maxNbAttempts, mls);
- return ZSTD_insertBtAndGetAllMatches(zc, ip, iLimit, maxNbAttempts, mls, 0, matches, minMatchLen);
-}
-
-
-static U32 ZSTD_BtGetAllMatches_selectMLS (
- ZSTD_CCtx* zc, /* Index table will be updated */
- const BYTE* ip, const BYTE* const iHighLimit,
- const U32 maxNbAttempts, const U32 matchLengthSearch, ZSTD_match_t* matches, const U32 minMatchLen)
-{
- switch(matchLengthSearch)
- {
- case 3 : return ZSTD_BtGetAllMatches(zc, ip, iHighLimit, maxNbAttempts, 3, matches, minMatchLen);
- default :
- case 4 : return ZSTD_BtGetAllMatches(zc, ip, iHighLimit, maxNbAttempts, 4, matches, minMatchLen);
- case 5 : return ZSTD_BtGetAllMatches(zc, ip, iHighLimit, maxNbAttempts, 5, matches, minMatchLen);
- case 7 :
- case 6 : return ZSTD_BtGetAllMatches(zc, ip, iHighLimit, maxNbAttempts, 6, matches, minMatchLen);
- }
-}
-
-/** Tree updater, providing best match */
-static U32 ZSTD_BtGetAllMatches_extDict (
- ZSTD_CCtx* zc,
- const BYTE* const ip, const BYTE* const iLimit,
- const U32 maxNbAttempts, const U32 mls, ZSTD_match_t* matches, const U32 minMatchLen)
-{
- if (ip < zc->base + zc->nextToUpdate) return 0; /* skipped area */
- ZSTD_updateTree_extDict(zc, ip, iLimit, maxNbAttempts, mls);
- return ZSTD_insertBtAndGetAllMatches(zc, ip, iLimit, maxNbAttempts, mls, 1, matches, minMatchLen);
-}
-
-
-static U32 ZSTD_BtGetAllMatches_selectMLS_extDict (
- ZSTD_CCtx* zc, /* Index table will be updated */
- const BYTE* ip, const BYTE* const iHighLimit,
- const U32 maxNbAttempts, const U32 matchLengthSearch, ZSTD_match_t* matches, const U32 minMatchLen)
-{
- switch(matchLengthSearch)
- {
- case 3 : return ZSTD_BtGetAllMatches_extDict(zc, ip, iHighLimit, maxNbAttempts, 3, matches, minMatchLen);
- default :
- case 4 : return ZSTD_BtGetAllMatches_extDict(zc, ip, iHighLimit, maxNbAttempts, 4, matches, minMatchLen);
- case 5 : return ZSTD_BtGetAllMatches_extDict(zc, ip, iHighLimit, maxNbAttempts, 5, matches, minMatchLen);
- case 7 :
- case 6 : return ZSTD_BtGetAllMatches_extDict(zc, ip, iHighLimit, maxNbAttempts, 6, matches, minMatchLen);
- }
-}
-
-
-/*-*******************************
-* Optimal parser
-*********************************/
-FORCE_INLINE_TEMPLATE
-void ZSTD_compressBlock_opt_generic(ZSTD_CCtx* ctx,
- const void* src, size_t srcSize, const int ultra)
-{
- seqStore_t* seqStorePtr = &(ctx->seqStore);
- optState_t* optStatePtr = &(ctx->optState);
- const BYTE* const istart = (const BYTE*)src;
- const BYTE* ip = istart;
- const BYTE* anchor = istart;
- const BYTE* const iend = istart + srcSize;
- const BYTE* const ilimit = iend - 8;
- const BYTE* const base = ctx->base;
- const BYTE* const prefixStart = base + ctx->dictLimit;
-
- const U32 maxSearches = 1U << ctx->appliedParams.cParams.searchLog;
- const U32 sufficient_len = ctx->appliedParams.cParams.targetLength;
- const U32 mls = ctx->appliedParams.cParams.searchLength;
- const U32 minMatch = (ctx->appliedParams.cParams.searchLength == 3) ? 3 : 4;
-
- ZSTD_optimal_t* opt = optStatePtr->priceTable;
- ZSTD_match_t* matches = optStatePtr->matchTable;
- const BYTE* inr;
- U32 offset, rep[ZSTD_REP_NUM];
-
- /* init */
- ctx->nextToUpdate3 = ctx->nextToUpdate;
- ZSTD_rescaleFreqs(optStatePtr, (const BYTE*)src, srcSize);
- ip += (ip==prefixStart);
- { U32 i; for (i=0; i<ZSTD_REP_NUM; i++) rep[i]=seqStorePtr->rep[i]; }
-
- /* Match Loop */
- while (ip < ilimit) {
- U32 cur, match_num, last_pos, litlen, price;
- U32 u, mlen, best_mlen, best_off, litLength;
- memset(opt, 0, sizeof(ZSTD_optimal_t));
- last_pos = 0;
- litlen = (U32)(ip - anchor);
-
- /* check repCode */
- { U32 i, last_i = ZSTD_REP_CHECK + (ip==anchor);
- for (i=(ip == anchor); i<last_i; i++) {
- const S32 repCur = (i==ZSTD_REP_MOVE_OPT) ? (rep[0] - 1) : rep[i];
- if ( (repCur > 0) && (repCur < (S32)(ip-prefixStart))
- && (ZSTD_readMINMATCH(ip, minMatch) == ZSTD_readMINMATCH(ip - repCur, minMatch))) {
- mlen = (U32)ZSTD_count(ip+minMatch, ip+minMatch-repCur, iend) + minMatch;
- if (mlen > sufficient_len || mlen >= ZSTD_OPT_NUM) {
- best_mlen = mlen; best_off = i; cur = 0; last_pos = 1;
- goto _storeSequence;
- }
- best_off = i - (ip == anchor);
- do {
- price = ZSTD_getPrice(optStatePtr, litlen, anchor, best_off, mlen - MINMATCH, ultra);
- if (mlen > last_pos || price < opt[mlen].price)
- SET_PRICE(mlen, mlen, i, litlen, price); /* note : macro modifies last_pos */
- mlen--;
- } while (mlen >= minMatch);
- } } }
-
- match_num = ZSTD_BtGetAllMatches_selectMLS(ctx, ip, iend, maxSearches, mls, matches, minMatch);
-
- if (!last_pos && !match_num) { ip++; continue; }
-
- if (match_num && (matches[match_num-1].len > sufficient_len || matches[match_num-1].len >= ZSTD_OPT_NUM)) {
- best_mlen = matches[match_num-1].len;
- best_off = matches[match_num-1].off;
- cur = 0;
- last_pos = 1;
- goto _storeSequence;
- }
-
- /* set prices using matches at position = 0 */
- best_mlen = (last_pos) ? last_pos : minMatch;
- for (u = 0; u < match_num; u++) {
- mlen = (u>0) ? matches[u-1].len+1 : best_mlen;
- best_mlen = matches[u].len;
- while (mlen <= best_mlen) {
- price = ZSTD_getPrice(optStatePtr, litlen, anchor, matches[u].off-1, mlen - MINMATCH, ultra);
- if (mlen > last_pos || price < opt[mlen].price)
- SET_PRICE(mlen, mlen, matches[u].off, litlen, price); /* note : macro modifies last_pos */
- mlen++;
- } }
-
- if (last_pos < minMatch) { ip++; continue; }
-
- /* initialize opt[0] */
- { U32 i ; for (i=0; i<ZSTD_REP_NUM; i++) opt[0].rep[i] = rep[i]; }
- opt[0].mlen = 1;
- opt[0].litlen = litlen;
-
- /* check further positions */
- for (cur = 1; cur <= last_pos; cur++) {
- inr = ip + cur;
-
- if (opt[cur-1].mlen == 1) {
- litlen = opt[cur-1].litlen + 1;
- if (cur > litlen) {
- price = opt[cur - litlen].price + ZSTD_getLiteralPrice(optStatePtr, litlen, inr-litlen);
- } else
- price = ZSTD_getLiteralPrice(optStatePtr, litlen, anchor);
- } else {
- litlen = 1;
- price = opt[cur - 1].price + ZSTD_getLiteralPrice(optStatePtr, litlen, inr-1);
- }
-
- if (cur > last_pos || price <= opt[cur].price)
- SET_PRICE(cur, 1, 0, litlen, price);
-
- if (cur == last_pos) break;
-
- if (inr > ilimit) /* last match must start at a minimum distance of 8 from oend */
- continue;
-
- mlen = opt[cur].mlen;
- if (opt[cur].off > ZSTD_REP_MOVE_OPT) {
- opt[cur].rep[2] = opt[cur-mlen].rep[1];
- opt[cur].rep[1] = opt[cur-mlen].rep[0];
- opt[cur].rep[0] = opt[cur].off - ZSTD_REP_MOVE_OPT;
- } else {
- opt[cur].rep[2] = (opt[cur].off > 1) ? opt[cur-mlen].rep[1] : opt[cur-mlen].rep[2];
- opt[cur].rep[1] = (opt[cur].off > 0) ? opt[cur-mlen].rep[0] : opt[cur-mlen].rep[1];
- opt[cur].rep[0] = ((opt[cur].off==ZSTD_REP_MOVE_OPT) && (mlen != 1)) ? (opt[cur-mlen].rep[0] - 1) : (opt[cur-mlen].rep[opt[cur].off]);
- }
-
- best_mlen = minMatch;
- { U32 i, last_i = ZSTD_REP_CHECK + (mlen != 1);
- for (i=(opt[cur].mlen != 1); i<last_i; i++) { /* check rep */
- const S32 repCur = (i==ZSTD_REP_MOVE_OPT) ? (opt[cur].rep[0] - 1) : opt[cur].rep[i];
- if ( (repCur > 0) && (repCur < (S32)(inr-prefixStart))
- && (ZSTD_readMINMATCH(inr, minMatch) == ZSTD_readMINMATCH(inr - repCur, minMatch))) {
- mlen = (U32)ZSTD_count(inr+minMatch, inr+minMatch - repCur, iend) + minMatch;
-
- if (mlen > sufficient_len || cur + mlen >= ZSTD_OPT_NUM) {
- best_mlen = mlen; best_off = i; last_pos = cur + 1;
- goto _storeSequence;
- }
-
- best_off = i - (opt[cur].mlen != 1);
- if (mlen > best_mlen) best_mlen = mlen;
-
- do {
- if (opt[cur].mlen == 1) {
- litlen = opt[cur].litlen;
- if (cur > litlen) {
- price = opt[cur - litlen].price + ZSTD_getPrice(optStatePtr, litlen, inr-litlen, best_off, mlen - MINMATCH, ultra);
- } else
- price = ZSTD_getPrice(optStatePtr, litlen, anchor, best_off, mlen - MINMATCH, ultra);
- } else {
- litlen = 0;
- price = opt[cur].price + ZSTD_getPrice(optStatePtr, 0, NULL, best_off, mlen - MINMATCH, ultra);
- }
-
- if (cur + mlen > last_pos || price <= opt[cur + mlen].price)
- SET_PRICE(cur + mlen, mlen, i, litlen, price);
- mlen--;
- } while (mlen >= minMatch);
- } } }
-
- match_num = ZSTD_BtGetAllMatches_selectMLS(ctx, inr, iend, maxSearches, mls, matches, best_mlen);
-
- if (match_num > 0 && (matches[match_num-1].len > sufficient_len || cur + matches[match_num-1].len >= ZSTD_OPT_NUM)) {
- best_mlen = matches[match_num-1].len;
- best_off = matches[match_num-1].off;
- last_pos = cur + 1;
- goto _storeSequence;
- }
-
- /* set prices using matches at position = cur */
- for (u = 0; u < match_num; u++) {
- mlen = (u>0) ? matches[u-1].len+1 : best_mlen;
- best_mlen = matches[u].len;
-
- while (mlen <= best_mlen) {
- if (opt[cur].mlen == 1) {
- litlen = opt[cur].litlen;
- if (cur > litlen)
- price = opt[cur - litlen].price + ZSTD_getPrice(optStatePtr, litlen, ip+cur-litlen, matches[u].off-1, mlen - MINMATCH, ultra);
- else
- price = ZSTD_getPrice(optStatePtr, litlen, anchor, matches[u].off-1, mlen - MINMATCH, ultra);
- } else {
- litlen = 0;
- price = opt[cur].price + ZSTD_getPrice(optStatePtr, 0, NULL, matches[u].off-1, mlen - MINMATCH, ultra);
- }
-
- if (cur + mlen > last_pos || (price < opt[cur + mlen].price))
- SET_PRICE(cur + mlen, mlen, matches[u].off, litlen, price);
-
- mlen++;
- } } }
-
- best_mlen = opt[last_pos].mlen;
- best_off = opt[last_pos].off;
- cur = last_pos - best_mlen;
-
- /* store sequence */
-_storeSequence: /* cur, last_pos, best_mlen, best_off have to be set */
- opt[0].mlen = 1;
-
- while (1) {
- mlen = opt[cur].mlen;
- offset = opt[cur].off;
- opt[cur].mlen = best_mlen;
- opt[cur].off = best_off;
- best_mlen = mlen;
- best_off = offset;
- if (mlen > cur) break;
- cur -= mlen;
- }
-
- for (u = 0; u <= last_pos;) {
- u += opt[u].mlen;
- }
-
- for (cur=0; cur < last_pos; ) {
- mlen = opt[cur].mlen;
- if (mlen == 1) { ip++; cur++; continue; }
- offset = opt[cur].off;
- cur += mlen;
- litLength = (U32)(ip - anchor);
-
- if (offset > ZSTD_REP_MOVE_OPT) {
- rep[2] = rep[1];
- rep[1] = rep[0];
- rep[0] = offset - ZSTD_REP_MOVE_OPT;
- offset--;
- } else {
- if (offset != 0) {
- best_off = (offset==ZSTD_REP_MOVE_OPT) ? (rep[0] - 1) : (rep[offset]);
- if (offset != 1) rep[2] = rep[1];
- rep[1] = rep[0];
- rep[0] = best_off;
- }
- if (litLength==0) offset--;
- }
-
- ZSTD_updatePrice(optStatePtr, litLength, anchor, offset, mlen-MINMATCH);
- ZSTD_storeSeq(seqStorePtr, litLength, anchor, offset, mlen-MINMATCH);
- anchor = ip = ip + mlen;
- } } /* for (cur=0; cur < last_pos; ) */
-
- /* Save reps for next block */
- { int i; for (i=0; i<ZSTD_REP_NUM; i++) seqStorePtr->repToConfirm[i] = rep[i]; }
-
- /* Last Literals */
- { size_t const lastLLSize = iend - anchor;
- memcpy(seqStorePtr->lit, anchor, lastLLSize);
- seqStorePtr->lit += lastLLSize;
- }
-}
-
-
-FORCE_INLINE_TEMPLATE
-void ZSTD_compressBlock_opt_extDict_generic(ZSTD_CCtx* ctx,
- const void* src, size_t srcSize, const int ultra)
-{
- seqStore_t* seqStorePtr = &(ctx->seqStore);
- optState_t* optStatePtr = &(ctx->optState);
- const BYTE* const istart = (const BYTE*)src;
- const BYTE* ip = istart;
- const BYTE* anchor = istart;
- const BYTE* const iend = istart + srcSize;
- const BYTE* const ilimit = iend - 8;
- const BYTE* const base = ctx->base;
- const U32 lowestIndex = ctx->lowLimit;
- const U32 dictLimit = ctx->dictLimit;
- const BYTE* const prefixStart = base + dictLimit;
- const BYTE* const dictBase = ctx->dictBase;
- const BYTE* const dictEnd = dictBase + dictLimit;
-
- const U32 maxSearches = 1U << ctx->appliedParams.cParams.searchLog;
- const U32 sufficient_len = ctx->appliedParams.cParams.targetLength;
- const U32 mls = ctx->appliedParams.cParams.searchLength;
- const U32 minMatch = (ctx->appliedParams.cParams.searchLength == 3) ? 3 : 4;
-
- ZSTD_optimal_t* opt = optStatePtr->priceTable;
- ZSTD_match_t* matches = optStatePtr->matchTable;
- const BYTE* inr;
-
- /* init */
- U32 offset, rep[ZSTD_REP_NUM];
- { U32 i; for (i=0; i<ZSTD_REP_NUM; i++) rep[i]=seqStorePtr->rep[i]; }
-
- ctx->nextToUpdate3 = ctx->nextToUpdate;
- ZSTD_rescaleFreqs(optStatePtr, (const BYTE*)src, srcSize);
- ip += (ip==prefixStart);
-
- /* Match Loop */
- while (ip < ilimit) {
- U32 cur, match_num, last_pos, litlen, price;
- U32 u, mlen, best_mlen, best_off, litLength;
- U32 current = (U32)(ip-base);
- memset(opt, 0, sizeof(ZSTD_optimal_t));
- last_pos = 0;
- opt[0].litlen = (U32)(ip - anchor);
-
- /* check repCode */
- { U32 i, last_i = ZSTD_REP_CHECK + (ip==anchor);
- for (i = (ip==anchor); i<last_i; i++) {
- const S32 repCur = (i==ZSTD_REP_MOVE_OPT) ? (rep[0] - 1) : rep[i];
- const U32 repIndex = (U32)(current - repCur);
- const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
- const BYTE* const repMatch = repBase + repIndex;
- if ( (repCur > 0 && repCur <= (S32)current)
- && (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex>lowestIndex)) /* intentional overflow */
- && (ZSTD_readMINMATCH(ip, minMatch) == ZSTD_readMINMATCH(repMatch, minMatch)) ) {
- /* repcode detected we should take it */
- const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
- mlen = (U32)ZSTD_count_2segments(ip+minMatch, repMatch+minMatch, iend, repEnd, prefixStart) + minMatch;
-
- if (mlen > sufficient_len || mlen >= ZSTD_OPT_NUM) {
- best_mlen = mlen; best_off = i; cur = 0; last_pos = 1;
- goto _storeSequence;
- }
-
- best_off = i - (ip==anchor);
- litlen = opt[0].litlen;
- do {
- price = ZSTD_getPrice(optStatePtr, litlen, anchor, best_off, mlen - MINMATCH, ultra);
- if (mlen > last_pos || price < opt[mlen].price)
- SET_PRICE(mlen, mlen, i, litlen, price); /* note : macro modifies last_pos */
- mlen--;
- } while (mlen >= minMatch);
- } } }
-
- match_num = ZSTD_BtGetAllMatches_selectMLS_extDict(ctx, ip, iend, maxSearches, mls, matches, minMatch); /* first search (depth 0) */
-
- if (!last_pos && !match_num) { ip++; continue; }
-
- { U32 i; for (i=0; i<ZSTD_REP_NUM; i++) opt[0].rep[i] = rep[i]; }
- opt[0].mlen = 1;
-
- if (match_num && (matches[match_num-1].len > sufficient_len || matches[match_num-1].len >= ZSTD_OPT_NUM)) {
- best_mlen = matches[match_num-1].len;
- best_off = matches[match_num-1].off;
- cur = 0;
- last_pos = 1;
- goto _storeSequence;
- }
-
- best_mlen = (last_pos) ? last_pos : minMatch;
-
- /* set prices using matches at position = 0 */
- for (u = 0; u < match_num; u++) {
- mlen = (u>0) ? matches[u-1].len+1 : best_mlen;
- best_mlen = matches[u].len;
- litlen = opt[0].litlen;
- while (mlen <= best_mlen) {
- price = ZSTD_getPrice(optStatePtr, litlen, anchor, matches[u].off-1, mlen - MINMATCH, ultra);
- if (mlen > last_pos || price < opt[mlen].price)
- SET_PRICE(mlen, mlen, matches[u].off, litlen, price);
- mlen++;
- } }
-
- if (last_pos < minMatch) {
- ip++; continue;
- }
-
- /* check further positions */
- for (cur = 1; cur <= last_pos; cur++) {
- inr = ip + cur;
-
- if (opt[cur-1].mlen == 1) {
- litlen = opt[cur-1].litlen + 1;
- if (cur > litlen) {
- price = opt[cur - litlen].price + ZSTD_getLiteralPrice(optStatePtr, litlen, inr-litlen);
- } else
- price = ZSTD_getLiteralPrice(optStatePtr, litlen, anchor);
- } else {
- litlen = 1;
- price = opt[cur - 1].price + ZSTD_getLiteralPrice(optStatePtr, litlen, inr-1);
- }
-
- if (cur > last_pos || price <= opt[cur].price)
- SET_PRICE(cur, 1, 0, litlen, price);
-
- if (cur == last_pos) break;
-
- if (inr > ilimit) /* last match must start at a minimum distance of 8 from oend */
- continue;
-
- mlen = opt[cur].mlen;
- if (opt[cur].off > ZSTD_REP_MOVE_OPT) {
- opt[cur].rep[2] = opt[cur-mlen].rep[1];
- opt[cur].rep[1] = opt[cur-mlen].rep[0];
- opt[cur].rep[0] = opt[cur].off - ZSTD_REP_MOVE_OPT;
- } else {
- opt[cur].rep[2] = (opt[cur].off > 1) ? opt[cur-mlen].rep[1] : opt[cur-mlen].rep[2];
- opt[cur].rep[1] = (opt[cur].off > 0) ? opt[cur-mlen].rep[0] : opt[cur-mlen].rep[1];
- opt[cur].rep[0] = ((opt[cur].off==ZSTD_REP_MOVE_OPT) && (mlen != 1)) ? (opt[cur-mlen].rep[0] - 1) : (opt[cur-mlen].rep[opt[cur].off]);
- }
-
- best_mlen = minMatch;
- { U32 i, last_i = ZSTD_REP_CHECK + (mlen != 1);
- for (i = (mlen != 1); i<last_i; i++) {
- const S32 repCur = (i==ZSTD_REP_MOVE_OPT) ? (opt[cur].rep[0] - 1) : opt[cur].rep[i];
- const U32 repIndex = (U32)(current+cur - repCur);
- const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
- const BYTE* const repMatch = repBase + repIndex;
- if ( (repCur > 0 && repCur <= (S32)(current+cur))
- && (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex>lowestIndex)) /* intentional overflow */
- && (ZSTD_readMINMATCH(inr, minMatch) == ZSTD_readMINMATCH(repMatch, minMatch)) ) {
- /* repcode detected */
- const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
- mlen = (U32)ZSTD_count_2segments(inr+minMatch, repMatch+minMatch, iend, repEnd, prefixStart) + minMatch;
-
- if (mlen > sufficient_len || cur + mlen >= ZSTD_OPT_NUM) {
- best_mlen = mlen; best_off = i; last_pos = cur + 1;
- goto _storeSequence;
- }
-
- best_off = i - (opt[cur].mlen != 1);
- if (mlen > best_mlen) best_mlen = mlen;
-
- do {
- if (opt[cur].mlen == 1) {
- litlen = opt[cur].litlen;
- if (cur > litlen) {
- price = opt[cur - litlen].price + ZSTD_getPrice(optStatePtr, litlen, inr-litlen, best_off, mlen - MINMATCH, ultra);
- } else
- price = ZSTD_getPrice(optStatePtr, litlen, anchor, best_off, mlen - MINMATCH, ultra);
- } else {
- litlen = 0;
- price = opt[cur].price + ZSTD_getPrice(optStatePtr, 0, NULL, best_off, mlen - MINMATCH, ultra);
- }
-
- if (cur + mlen > last_pos || price <= opt[cur + mlen].price)
- SET_PRICE(cur + mlen, mlen, i, litlen, price);
- mlen--;
- } while (mlen >= minMatch);
- } } }
-
- match_num = ZSTD_BtGetAllMatches_selectMLS_extDict(ctx, inr, iend, maxSearches, mls, matches, minMatch);
-
- if (match_num > 0 && (matches[match_num-1].len > sufficient_len || cur + matches[match_num-1].len >= ZSTD_OPT_NUM)) {
- best_mlen = matches[match_num-1].len;
- best_off = matches[match_num-1].off;
- last_pos = cur + 1;
- goto _storeSequence;
- }
-
- /* set prices using matches at position = cur */
- for (u = 0; u < match_num; u++) {
- mlen = (u>0) ? matches[u-1].len+1 : best_mlen;
- best_mlen = matches[u].len;
-
- while (mlen <= best_mlen) {
- if (opt[cur].mlen == 1) {
- litlen = opt[cur].litlen;
- if (cur > litlen)
- price = opt[cur - litlen].price + ZSTD_getPrice(optStatePtr, litlen, ip+cur-litlen, matches[u].off-1, mlen - MINMATCH, ultra);
- else
- price = ZSTD_getPrice(optStatePtr, litlen, anchor, matches[u].off-1, mlen - MINMATCH, ultra);
- } else {
- litlen = 0;
- price = opt[cur].price + ZSTD_getPrice(optStatePtr, 0, NULL, matches[u].off-1, mlen - MINMATCH, ultra);
- }
-
- if (cur + mlen > last_pos || (price < opt[cur + mlen].price))
- SET_PRICE(cur + mlen, mlen, matches[u].off, litlen, price);
-
- mlen++;
- } } } /* for (cur = 1; cur <= last_pos; cur++) */
-
- best_mlen = opt[last_pos].mlen;
- best_off = opt[last_pos].off;
- cur = last_pos - best_mlen;
-
- /* store sequence */
-_storeSequence: /* cur, last_pos, best_mlen, best_off have to be set */
- opt[0].mlen = 1;
-
- while (1) {
- mlen = opt[cur].mlen;
- offset = opt[cur].off;
- opt[cur].mlen = best_mlen;
- opt[cur].off = best_off;
- best_mlen = mlen;
- best_off = offset;
- if (mlen > cur) break;
- cur -= mlen;
- }
-
- for (u = 0; u <= last_pos; ) {
- u += opt[u].mlen;
- }
-
- for (cur=0; cur < last_pos; ) {
- mlen = opt[cur].mlen;
- if (mlen == 1) { ip++; cur++; continue; }
- offset = opt[cur].off;
- cur += mlen;
- litLength = (U32)(ip - anchor);
-
- if (offset > ZSTD_REP_MOVE_OPT) {
- rep[2] = rep[1];
- rep[1] = rep[0];
- rep[0] = offset - ZSTD_REP_MOVE_OPT;
- offset--;
- } else {
- if (offset != 0) {
- best_off = (offset==ZSTD_REP_MOVE_OPT) ? (rep[0] - 1) : (rep[offset]);
- if (offset != 1) rep[2] = rep[1];
- rep[1] = rep[0];
- rep[0] = best_off;
- }
-
- if (litLength==0) offset--;
- }
-
- ZSTD_updatePrice(optStatePtr, litLength, anchor, offset, mlen-MINMATCH);
- ZSTD_storeSeq(seqStorePtr, litLength, anchor, offset, mlen-MINMATCH);
- anchor = ip = ip + mlen;
- } } /* for (cur=0; cur < last_pos; ) */
-
- /* Save reps for next block */
- { int i; for (i=0; i<ZSTD_REP_NUM; i++) seqStorePtr->repToConfirm[i] = rep[i]; }
-
- /* Last Literals */
- { size_t lastLLSize = iend - anchor;
- memcpy(seqStorePtr->lit, anchor, lastLLSize);
- seqStorePtr->lit += lastLLSize;
- }
+#if defined (__cplusplus)
}
+#endif
-#endif /* ZSTD_OPT_H_91842398743 */
+#endif /* ZSTD_OPT_H */
diff --git a/thirdparty/zstd/compress/zstdmt_compress.c b/thirdparty/zstd/compress/zstdmt_compress.c
index 8564bc4392..7831cd3bd8 100644
--- a/thirdparty/zstd/compress/zstdmt_compress.c
+++ b/thirdparty/zstd/compress/zstdmt_compress.c
@@ -5,11 +5,12 @@
* This source code is licensed under both the BSD-style license (found in the
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
* in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
*/
/* ====== Tuning parameters ====== */
-#define ZSTDMT_NBTHREADS_MAX 256
+#define ZSTDMT_NBTHREADS_MAX 200
#define ZSTDMT_OVERLAPLOG_DEFAULT 6
@@ -52,22 +53,24 @@ static unsigned long long GetCurrentClockTimeMicroseconds(void)
}
#define MUTEX_WAIT_TIME_DLEVEL 6
-#define PTHREAD_MUTEX_LOCK(mutex) { \
- if (ZSTD_DEBUG>=MUTEX_WAIT_TIME_DLEVEL) { \
+#define ZSTD_PTHREAD_MUTEX_LOCK(mutex) { \
+ if (ZSTD_DEBUG >= MUTEX_WAIT_TIME_DLEVEL) { \
unsigned long long const beforeTime = GetCurrentClockTimeMicroseconds(); \
- pthread_mutex_lock(mutex); \
+ ZSTD_pthread_mutex_lock(mutex); \
{ unsigned long long const afterTime = GetCurrentClockTimeMicroseconds(); \
unsigned long long const elapsedTime = (afterTime-beforeTime); \
if (elapsedTime > 1000) { /* or whatever threshold you like; I'm using 1 millisecond here */ \
DEBUGLOG(MUTEX_WAIT_TIME_DLEVEL, "Thread took %llu microseconds to acquire mutex %s \n", \
elapsedTime, #mutex); \
} } \
- } else pthread_mutex_lock(mutex); \
+ } else { \
+ ZSTD_pthread_mutex_lock(mutex); \
+ } \
}
#else
-# define PTHREAD_MUTEX_LOCK(m) pthread_mutex_lock(m)
+# define ZSTD_PTHREAD_MUTEX_LOCK(m) ZSTD_pthread_mutex_lock(m)
# define DEBUG_PRINTHEX(l,p,n) {}
#endif
@@ -84,7 +87,7 @@ typedef struct buffer_s {
static const buffer_t g_nullBuffer = { NULL, 0 };
typedef struct ZSTDMT_bufferPool_s {
- pthread_mutex_t poolMutex;
+ ZSTD_pthread_mutex_t poolMutex;
size_t bufferSize;
unsigned totalBuffers;
unsigned nbBuffers;
@@ -98,7 +101,7 @@ static ZSTDMT_bufferPool* ZSTDMT_createBufferPool(unsigned nbThreads, ZSTD_custo
ZSTDMT_bufferPool* const bufPool = (ZSTDMT_bufferPool*)ZSTD_calloc(
sizeof(ZSTDMT_bufferPool) + (maxNbBuffers-1) * sizeof(buffer_t), cMem);
if (bufPool==NULL) return NULL;
- if (pthread_mutex_init(&bufPool->poolMutex, NULL)) {
+ if (ZSTD_pthread_mutex_init(&bufPool->poolMutex, NULL)) {
ZSTD_free(bufPool, cMem);
return NULL;
}
@@ -112,10 +115,13 @@ static ZSTDMT_bufferPool* ZSTDMT_createBufferPool(unsigned nbThreads, ZSTD_custo
static void ZSTDMT_freeBufferPool(ZSTDMT_bufferPool* bufPool)
{
unsigned u;
+ DEBUGLOG(3, "ZSTDMT_freeBufferPool (address:%08X)", (U32)(size_t)bufPool);
if (!bufPool) return; /* compatibility with free on NULL */
- for (u=0; u<bufPool->totalBuffers; u++)
+ for (u=0; u<bufPool->totalBuffers; u++) {
+ DEBUGLOG(4, "free buffer %2u (address:%08X)", u, (U32)(size_t)bufPool->bTable[u].start);
ZSTD_free(bufPool->bTable[u].start, bufPool->cMem);
- pthread_mutex_destroy(&bufPool->poolMutex);
+ }
+ ZSTD_pthread_mutex_destroy(&bufPool->poolMutex);
ZSTD_free(bufPool, bufPool->cMem);
}
@@ -126,10 +132,10 @@ static size_t ZSTDMT_sizeof_bufferPool(ZSTDMT_bufferPool* bufPool)
+ (bufPool->totalBuffers - 1) * sizeof(buffer_t);
unsigned u;
size_t totalBufferSize = 0;
- pthread_mutex_lock(&bufPool->poolMutex);
+ ZSTD_pthread_mutex_lock(&bufPool->poolMutex);
for (u=0; u<bufPool->totalBuffers; u++)
totalBufferSize += bufPool->bTable[u].size;
- pthread_mutex_unlock(&bufPool->poolMutex);
+ ZSTD_pthread_mutex_unlock(&bufPool->poolMutex);
return poolSize + totalBufferSize;
}
@@ -145,20 +151,21 @@ static buffer_t ZSTDMT_getBuffer(ZSTDMT_bufferPool* bufPool)
{
size_t const bSize = bufPool->bufferSize;
DEBUGLOG(5, "ZSTDMT_getBuffer");
- pthread_mutex_lock(&bufPool->poolMutex);
+ ZSTD_pthread_mutex_lock(&bufPool->poolMutex);
if (bufPool->nbBuffers) { /* try to use an existing buffer */
buffer_t const buf = bufPool->bTable[--(bufPool->nbBuffers)];
size_t const availBufferSize = buf.size;
+ bufPool->bTable[bufPool->nbBuffers] = g_nullBuffer;
if ((availBufferSize >= bSize) & (availBufferSize <= 10*bSize)) {
/* large enough, but not too much */
- pthread_mutex_unlock(&bufPool->poolMutex);
+ ZSTD_pthread_mutex_unlock(&bufPool->poolMutex);
return buf;
}
/* size conditions not respected : scratch this buffer, create new one */
DEBUGLOG(5, "existing buffer does not meet size conditions => freeing");
ZSTD_free(buf.start, bufPool->cMem);
}
- pthread_mutex_unlock(&bufPool->poolMutex);
+ ZSTD_pthread_mutex_unlock(&bufPool->poolMutex);
/* create new buffer */
DEBUGLOG(5, "create a new buffer");
{ buffer_t buffer;
@@ -174,24 +181,38 @@ static void ZSTDMT_releaseBuffer(ZSTDMT_bufferPool* bufPool, buffer_t buf)
{
if (buf.start == NULL) return; /* compatible with release on NULL */
DEBUGLOG(5, "ZSTDMT_releaseBuffer");
- pthread_mutex_lock(&bufPool->poolMutex);
+ ZSTD_pthread_mutex_lock(&bufPool->poolMutex);
if (bufPool->nbBuffers < bufPool->totalBuffers) {
bufPool->bTable[bufPool->nbBuffers++] = buf; /* stored for later use */
- pthread_mutex_unlock(&bufPool->poolMutex);
+ ZSTD_pthread_mutex_unlock(&bufPool->poolMutex);
return;
}
- pthread_mutex_unlock(&bufPool->poolMutex);
+ ZSTD_pthread_mutex_unlock(&bufPool->poolMutex);
/* Reached bufferPool capacity (should not happen) */
DEBUGLOG(5, "buffer pool capacity reached => freeing ");
ZSTD_free(buf.start, bufPool->cMem);
}
+/* Sets parameters relevant to the compression job, initializing others to
+ * default values. Notably, nbThreads should probably be zero. */
+static ZSTD_CCtx_params ZSTDMT_makeJobCCtxParams(ZSTD_CCtx_params const params)
+{
+ ZSTD_CCtx_params jobParams;
+ memset(&jobParams, 0, sizeof(jobParams));
+
+ jobParams.cParams = params.cParams;
+ jobParams.fParams = params.fParams;
+ jobParams.compressionLevel = params.compressionLevel;
+
+ jobParams.ldmParams = params.ldmParams;
+ return jobParams;
+}
/* ===== CCtx Pool ===== */
/* a single CCtx Pool can be invoked from multiple threads in parallel */
typedef struct {
- pthread_mutex_t poolMutex;
+ ZSTD_pthread_mutex_t poolMutex;
unsigned totalCCtx;
unsigned availCCtx;
ZSTD_customMem cMem;
@@ -204,7 +225,7 @@ static void ZSTDMT_freeCCtxPool(ZSTDMT_CCtxPool* pool)
unsigned u;
for (u=0; u<pool->totalCCtx; u++)
ZSTD_freeCCtx(pool->cctx[u]); /* note : compatible with free on NULL */
- pthread_mutex_destroy(&pool->poolMutex);
+ ZSTD_pthread_mutex_destroy(&pool->poolMutex);
ZSTD_free(pool, pool->cMem);
}
@@ -216,7 +237,7 @@ static ZSTDMT_CCtxPool* ZSTDMT_createCCtxPool(unsigned nbThreads,
ZSTDMT_CCtxPool* const cctxPool = (ZSTDMT_CCtxPool*) ZSTD_calloc(
sizeof(ZSTDMT_CCtxPool) + (nbThreads-1)*sizeof(ZSTD_CCtx*), cMem);
if (!cctxPool) return NULL;
- if (pthread_mutex_init(&cctxPool->poolMutex, NULL)) {
+ if (ZSTD_pthread_mutex_init(&cctxPool->poolMutex, NULL)) {
ZSTD_free(cctxPool, cMem);
return NULL;
}
@@ -232,7 +253,7 @@ static ZSTDMT_CCtxPool* ZSTDMT_createCCtxPool(unsigned nbThreads,
/* only works during initialization phase, not during compression */
static size_t ZSTDMT_sizeof_CCtxPool(ZSTDMT_CCtxPool* cctxPool)
{
- pthread_mutex_lock(&cctxPool->poolMutex);
+ ZSTD_pthread_mutex_lock(&cctxPool->poolMutex);
{ unsigned const nbThreads = cctxPool->totalCCtx;
size_t const poolSize = sizeof(*cctxPool)
+ (nbThreads-1)*sizeof(ZSTD_CCtx*);
@@ -241,7 +262,7 @@ static size_t ZSTDMT_sizeof_CCtxPool(ZSTDMT_CCtxPool* cctxPool)
for (u=0; u<nbThreads; u++) {
totalCCtxSize += ZSTD_sizeof_CCtx(cctxPool->cctx[u]);
}
- pthread_mutex_unlock(&cctxPool->poolMutex);
+ ZSTD_pthread_mutex_unlock(&cctxPool->poolMutex);
return poolSize + totalCCtxSize;
}
}
@@ -249,14 +270,14 @@ static size_t ZSTDMT_sizeof_CCtxPool(ZSTDMT_CCtxPool* cctxPool)
static ZSTD_CCtx* ZSTDMT_getCCtx(ZSTDMT_CCtxPool* cctxPool)
{
DEBUGLOG(5, "ZSTDMT_getCCtx");
- pthread_mutex_lock(&cctxPool->poolMutex);
+ ZSTD_pthread_mutex_lock(&cctxPool->poolMutex);
if (cctxPool->availCCtx) {
cctxPool->availCCtx--;
{ ZSTD_CCtx* const cctx = cctxPool->cctx[cctxPool->availCCtx];
- pthread_mutex_unlock(&cctxPool->poolMutex);
+ ZSTD_pthread_mutex_unlock(&cctxPool->poolMutex);
return cctx;
} }
- pthread_mutex_unlock(&cctxPool->poolMutex);
+ ZSTD_pthread_mutex_unlock(&cctxPool->poolMutex);
DEBUGLOG(5, "create one more CCtx");
return ZSTD_createCCtx_advanced(cctxPool->cMem); /* note : can be NULL, when creation fails ! */
}
@@ -264,7 +285,7 @@ static ZSTD_CCtx* ZSTDMT_getCCtx(ZSTDMT_CCtxPool* cctxPool)
static void ZSTDMT_releaseCCtx(ZSTDMT_CCtxPool* pool, ZSTD_CCtx* cctx)
{
if (cctx==NULL) return; /* compatibility with release on NULL */
- pthread_mutex_lock(&pool->poolMutex);
+ ZSTD_pthread_mutex_lock(&pool->poolMutex);
if (pool->availCCtx < pool->totalCCtx)
pool->cctx[pool->availCCtx++] = cctx;
else {
@@ -272,7 +293,7 @@ static void ZSTDMT_releaseCCtx(ZSTDMT_CCtxPool* pool, ZSTD_CCtx* cctx)
DEBUGLOG(5, "CCtx pool overflow : free cctx");
ZSTD_freeCCtx(cctx);
}
- pthread_mutex_unlock(&pool->poolMutex);
+ ZSTD_pthread_mutex_unlock(&pool->poolMutex);
}
@@ -290,9 +311,9 @@ typedef struct {
unsigned lastChunk;
unsigned jobCompleted;
unsigned jobScanned;
- pthread_mutex_t* jobCompleted_mutex;
- pthread_cond_t* jobCompleted_cond;
- ZSTD_parameters params;
+ ZSTD_pthread_mutex_t* jobCompleted_mutex;
+ ZSTD_pthread_cond_t* jobCompleted_cond;
+ ZSTD_CCtx_params params;
const ZSTD_CDict* cdict;
ZSTDMT_CCtxPool* cctxPool;
ZSTDMT_bufferPool* bufPool;
@@ -329,10 +350,15 @@ void ZSTDMT_compressChunk(void* jobDescription)
if (ZSTD_isError(initError)) { job->cSize = initError; goto _endJob; }
} else { /* srcStart points at reloaded section */
if (!job->firstChunk) job->params.fParams.contentSizeFlag = 0; /* ensure no srcSize control */
- { size_t const dictModeError = ZSTD_setCCtxParameter(cctx, ZSTD_p_forceRawDict, 1); /* Force loading dictionary in "content-only" mode (no header analysis) */
- size_t const initError = ZSTD_compressBegin_advanced(cctx, job->srcStart, job->dictSize, job->params, job->fullFrameSize);
- if (ZSTD_isError(initError) || ZSTD_isError(dictModeError)) { job->cSize = initError; goto _endJob; }
- ZSTD_setCCtxParameter(cctx, ZSTD_p_forceWindow, 1);
+ { ZSTD_CCtx_params jobParams = job->params;
+ size_t const forceWindowError =
+ ZSTD_CCtxParam_setParameter(&jobParams, ZSTD_p_forceMaxWindow, !job->firstChunk);
+ /* Force loading dictionary in "content-only" mode (no header analysis) */
+ size_t const initError = ZSTD_compressBegin_advanced_internal(cctx, job->srcStart, job->dictSize, ZSTD_dm_rawContent, jobParams, job->fullFrameSize);
+ if (ZSTD_isError(initError) || ZSTD_isError(forceWindowError)) {
+ job->cSize = initError;
+ goto _endJob;
+ }
} }
if (!job->firstChunk) { /* flush and overwrite frame header when it's not first segment */
size_t const hSize = ZSTD_compressContinue(cctx, dstBuff.start, dstBuff.size, src, 0);
@@ -353,11 +379,11 @@ _endJob:
ZSTDMT_releaseCCtx(job->cctxPool, cctx);
ZSTDMT_releaseBuffer(job->bufPool, job->src);
job->src = g_nullBuffer; job->srcStart = NULL;
- PTHREAD_MUTEX_LOCK(job->jobCompleted_mutex);
+ ZSTD_PTHREAD_MUTEX_LOCK(job->jobCompleted_mutex);
job->jobCompleted = 1;
job->jobScanned = 0;
- pthread_cond_signal(job->jobCompleted_cond);
- pthread_mutex_unlock(job->jobCompleted_mutex);
+ ZSTD_pthread_cond_signal(job->jobCompleted_cond);
+ ZSTD_pthread_mutex_unlock(job->jobCompleted_mutex);
}
@@ -375,24 +401,21 @@ struct ZSTDMT_CCtx_s {
ZSTDMT_jobDescription* jobs;
ZSTDMT_bufferPool* bufPool;
ZSTDMT_CCtxPool* cctxPool;
- pthread_mutex_t jobCompleted_mutex;
- pthread_cond_t jobCompleted_cond;
+ ZSTD_pthread_mutex_t jobCompleted_mutex;
+ ZSTD_pthread_cond_t jobCompleted_cond;
size_t targetSectionSize;
size_t inBuffSize;
size_t dictSize;
size_t targetDictSize;
inBuff_t inBuff;
- ZSTD_parameters params;
+ ZSTD_CCtx_params params;
XXH64_state_t xxhState;
- unsigned nbThreads;
unsigned jobIDMask;
unsigned doneJobID;
unsigned nextJobID;
unsigned frameEnded;
unsigned allJobsCompleted;
- unsigned overlapLog;
unsigned long long frameContentSize;
- size_t sectionSize;
ZSTD_customMem cMem;
ZSTD_CDict* cdictLocal;
const ZSTD_CDict* cdict;
@@ -407,6 +430,15 @@ static ZSTDMT_jobDescription* ZSTDMT_allocJobsTable(U32* nbJobsPtr, ZSTD_customM
nbJobs * sizeof(ZSTDMT_jobDescription), cMem);
}
+/* Internal only */
+size_t ZSTDMT_initializeCCtxParameters(ZSTD_CCtx_params* params, unsigned nbThreads)
+{
+ params->nbThreads = nbThreads;
+ params->overlapSizeLog = ZSTDMT_OVERLAPLOG_DEFAULT;
+ params->jobSize = 0;
+ return 0;
+}
+
ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbThreads, ZSTD_customMem cMem)
{
ZSTDMT_CCtx* mtctx;
@@ -421,12 +453,10 @@ ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbThreads, ZSTD_customMem cMem)
mtctx = (ZSTDMT_CCtx*) ZSTD_calloc(sizeof(ZSTDMT_CCtx), cMem);
if (!mtctx) return NULL;
+ ZSTDMT_initializeCCtxParameters(&mtctx->params, nbThreads);
mtctx->cMem = cMem;
- mtctx->nbThreads = nbThreads;
mtctx->allJobsCompleted = 1;
- mtctx->sectionSize = 0;
- mtctx->overlapLog = ZSTDMT_OVERLAPLOG_DEFAULT;
- mtctx->factory = POOL_create(nbThreads, 0);
+ mtctx->factory = POOL_create_advanced(nbThreads, 0, cMem);
mtctx->jobs = ZSTDMT_allocJobsTable(&nbJobs, cMem);
mtctx->jobIDMask = nbJobs - 1;
mtctx->bufPool = ZSTDMT_createBufferPool(nbThreads, cMem);
@@ -435,11 +465,11 @@ ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbThreads, ZSTD_customMem cMem)
ZSTDMT_freeCCtx(mtctx);
return NULL;
}
- if (pthread_mutex_init(&mtctx->jobCompleted_mutex, NULL)) {
+ if (ZSTD_pthread_mutex_init(&mtctx->jobCompleted_mutex, NULL)) {
ZSTDMT_freeCCtx(mtctx);
return NULL;
}
- if (pthread_cond_init(&mtctx->jobCompleted_cond, NULL)) {
+ if (ZSTD_pthread_cond_init(&mtctx->jobCompleted_cond, NULL)) {
ZSTDMT_freeCCtx(mtctx);
return NULL;
}
@@ -459,28 +489,46 @@ static void ZSTDMT_releaseAllJobResources(ZSTDMT_CCtx* mtctx)
unsigned jobID;
DEBUGLOG(3, "ZSTDMT_releaseAllJobResources");
for (jobID=0; jobID <= mtctx->jobIDMask; jobID++) {
+ DEBUGLOG(4, "job%02u: release dst address %08X", jobID, (U32)(size_t)mtctx->jobs[jobID].dstBuff.start);
ZSTDMT_releaseBuffer(mtctx->bufPool, mtctx->jobs[jobID].dstBuff);
mtctx->jobs[jobID].dstBuff = g_nullBuffer;
+ DEBUGLOG(4, "job%02u: release src address %08X", jobID, (U32)(size_t)mtctx->jobs[jobID].src.start);
ZSTDMT_releaseBuffer(mtctx->bufPool, mtctx->jobs[jobID].src);
mtctx->jobs[jobID].src = g_nullBuffer;
}
memset(mtctx->jobs, 0, (mtctx->jobIDMask+1)*sizeof(ZSTDMT_jobDescription));
+ DEBUGLOG(4, "input: release address %08X", (U32)(size_t)mtctx->inBuff.buffer.start);
ZSTDMT_releaseBuffer(mtctx->bufPool, mtctx->inBuff.buffer);
mtctx->inBuff.buffer = g_nullBuffer;
mtctx->allJobsCompleted = 1;
}
+static void ZSTDMT_waitForAllJobsCompleted(ZSTDMT_CCtx* zcs)
+{
+ DEBUGLOG(4, "ZSTDMT_waitForAllJobsCompleted");
+ while (zcs->doneJobID < zcs->nextJobID) {
+ unsigned const jobID = zcs->doneJobID & zcs->jobIDMask;
+ ZSTD_PTHREAD_MUTEX_LOCK(&zcs->jobCompleted_mutex);
+ while (zcs->jobs[jobID].jobCompleted==0) {
+ DEBUGLOG(5, "waiting for jobCompleted signal from chunk %u", zcs->doneJobID); /* we want to block when waiting for data to flush */
+ ZSTD_pthread_cond_wait(&zcs->jobCompleted_cond, &zcs->jobCompleted_mutex);
+ }
+ ZSTD_pthread_mutex_unlock(&zcs->jobCompleted_mutex);
+ zcs->doneJobID++;
+ }
+}
+
size_t ZSTDMT_freeCCtx(ZSTDMT_CCtx* mtctx)
{
if (mtctx==NULL) return 0; /* compatible with free on NULL */
- POOL_free(mtctx->factory);
- if (!mtctx->allJobsCompleted) ZSTDMT_releaseAllJobResources(mtctx); /* stop workers first */
- ZSTDMT_freeBufferPool(mtctx->bufPool); /* release job resources into pools first */
+ POOL_free(mtctx->factory); /* stop and free worker threads */
+ ZSTDMT_releaseAllJobResources(mtctx); /* release job resources into pools first */
ZSTD_free(mtctx->jobs, mtctx->cMem);
+ ZSTDMT_freeBufferPool(mtctx->bufPool);
ZSTDMT_freeCCtxPool(mtctx->cctxPool);
ZSTD_freeCDict(mtctx->cdictLocal);
- pthread_mutex_destroy(&mtctx->jobCompleted_mutex);
- pthread_cond_destroy(&mtctx->jobCompleted_cond);
+ ZSTD_pthread_mutex_destroy(&mtctx->jobCompleted_mutex);
+ ZSTD_pthread_cond_destroy(&mtctx->jobCompleted_cond);
ZSTD_free(mtctx, mtctx->cMem);
return 0;
}
@@ -496,22 +544,35 @@ size_t ZSTDMT_sizeof_CCtx(ZSTDMT_CCtx* mtctx)
+ ZSTD_sizeof_CDict(mtctx->cdictLocal);
}
-size_t ZSTDMT_setMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSDTMT_parameter parameter, unsigned value)
-{
+/* Internal only */
+size_t ZSTDMT_CCtxParam_setMTCtxParameter(
+ ZSTD_CCtx_params* params, ZSTDMT_parameter parameter, unsigned value) {
switch(parameter)
{
case ZSTDMT_p_sectionSize :
- mtctx->sectionSize = value;
+ params->jobSize = value;
return 0;
case ZSTDMT_p_overlapSectionLog :
- DEBUGLOG(5, "ZSTDMT_p_overlapSectionLog : %u", value);
- mtctx->overlapLog = (value >= 9) ? 9 : value;
+ DEBUGLOG(4, "ZSTDMT_p_overlapSectionLog : %u", value);
+ params->overlapSizeLog = (value >= 9) ? 9 : value;
return 0;
default :
return ERROR(parameter_unsupported);
}
}
+size_t ZSTDMT_setMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter parameter, unsigned value)
+{
+ switch(parameter)
+ {
+ case ZSTDMT_p_sectionSize :
+ return ZSTDMT_CCtxParam_setMTCtxParameter(&mtctx->params, parameter, value);
+ case ZSTDMT_p_overlapSectionLog :
+ return ZSTDMT_CCtxParam_setMTCtxParameter(&mtctx->params, parameter, value);
+ default :
+ return ERROR(parameter_unsupported);
+ }
+}
/* ------------------------------------------ */
/* ===== Multi-threaded compression ===== */
@@ -528,17 +589,17 @@ static unsigned computeNbChunks(size_t srcSize, unsigned windowLog, unsigned nbT
return (multiplier>1) ? nbChunksLarge : nbChunksSmall;
}
-
-size_t ZSTDMT_compress_advanced(ZSTDMT_CCtx* mtctx,
- void* dst, size_t dstCapacity,
- const void* src, size_t srcSize,
- const ZSTD_CDict* cdict,
- ZSTD_parameters const params,
- unsigned overlapLog)
+static size_t ZSTDMT_compress_advanced_internal(
+ ZSTDMT_CCtx* mtctx,
+ void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize,
+ const ZSTD_CDict* cdict,
+ ZSTD_CCtx_params const params)
{
- unsigned const overlapRLog = (overlapLog>9) ? 0 : 9-overlapLog;
+ ZSTD_CCtx_params const jobParams = ZSTDMT_makeJobCCtxParams(params);
+ unsigned const overlapRLog = (params.overlapSizeLog>9) ? 0 : 9-params.overlapSizeLog;
size_t const overlapSize = (overlapRLog>=9) ? 0 : (size_t)1 << (params.cParams.windowLog - overlapRLog);
- unsigned nbChunks = computeNbChunks(srcSize, params.cParams.windowLog, mtctx->nbThreads);
+ unsigned nbChunks = computeNbChunks(srcSize, params.cParams.windowLog, params.nbThreads);
size_t const proposedChunkSize = (srcSize + (nbChunks-1)) / nbChunks;
size_t const avgChunkSize = ((proposedChunkSize & 0x1FFFF) < 0x7FFF) ? proposedChunkSize + 0xFFFF : proposedChunkSize; /* avoid too small last block */
const char* const srcStart = (const char*)src;
@@ -546,12 +607,14 @@ size_t ZSTDMT_compress_advanced(ZSTDMT_CCtx* mtctx,
unsigned const compressWithinDst = (dstCapacity >= ZSTD_compressBound(srcSize)) ? nbChunks : (unsigned)(dstCapacity / ZSTD_compressBound(avgChunkSize)); /* presumes avgChunkSize >= 256 KB, which should be the case */
size_t frameStartPos = 0, dstBufferPos = 0;
XXH64_state_t xxh64;
+ assert(jobParams.nbThreads == 0);
+ assert(mtctx->cctxPool->totalCCtx == params.nbThreads);
DEBUGLOG(4, "nbChunks : %2u (chunkSize : %u bytes) ", nbChunks, (U32)avgChunkSize);
if (nbChunks==1) { /* fallback to single-thread mode */
ZSTD_CCtx* const cctx = mtctx->cctxPool->cctx[0];
- if (cdict) return ZSTD_compress_usingCDict_advanced(cctx, dst, dstCapacity, src, srcSize, cdict, params.fParams);
- return ZSTD_compress_advanced(cctx, dst, dstCapacity, src, srcSize, NULL, 0, params);
+ if (cdict) return ZSTD_compress_usingCDict_advanced(cctx, dst, dstCapacity, src, srcSize, cdict, jobParams.fParams);
+ return ZSTD_compress_advanced_internal(cctx, dst, dstCapacity, src, srcSize, NULL, 0, jobParams);
}
assert(avgChunkSize >= 256 KB); /* condition for ZSTD_compressBound(A) + ZSTD_compressBound(B) <= ZSTD_compressBound(A+B), which is required for compressWithinDst */
ZSTDMT_setBufferSize(mtctx->bufPool, ZSTD_compressBound(avgChunkSize) );
@@ -580,7 +643,7 @@ size_t ZSTDMT_compress_advanced(ZSTDMT_CCtx* mtctx,
mtctx->jobs[u].srcSize = chunkSize;
mtctx->jobs[u].cdict = mtctx->nextJobID==0 ? cdict : NULL;
mtctx->jobs[u].fullFrameSize = srcSize;
- mtctx->jobs[u].params = params;
+ mtctx->jobs[u].params = jobParams;
/* do not calculate checksum within sections, but write it in header for first section */
if (u!=0) mtctx->jobs[u].params.fParams.checksumFlag = 0;
mtctx->jobs[u].dstBuff = dstBuffer;
@@ -610,12 +673,12 @@ size_t ZSTDMT_compress_advanced(ZSTDMT_CCtx* mtctx,
unsigned chunkID;
for (chunkID=0; chunkID<nbChunks; chunkID++) {
DEBUGLOG(5, "waiting for chunk %u ", chunkID);
- PTHREAD_MUTEX_LOCK(&mtctx->jobCompleted_mutex);
+ ZSTD_PTHREAD_MUTEX_LOCK(&mtctx->jobCompleted_mutex);
while (mtctx->jobs[chunkID].jobCompleted==0) {
DEBUGLOG(5, "waiting for jobCompleted signal from chunk %u", chunkID);
- pthread_cond_wait(&mtctx->jobCompleted_cond, &mtctx->jobCompleted_mutex);
+ ZSTD_pthread_cond_wait(&mtctx->jobCompleted_cond, &mtctx->jobCompleted_mutex);
}
- pthread_mutex_unlock(&mtctx->jobCompleted_mutex);
+ ZSTD_pthread_mutex_unlock(&mtctx->jobCompleted_mutex);
DEBUGLOG(5, "ready to write chunk %u ", chunkID);
mtctx->jobs[chunkID].srcStart = NULL;
@@ -628,9 +691,8 @@ size_t ZSTDMT_compress_advanced(ZSTDMT_CCtx* mtctx,
if (chunkID >= compressWithinDst) { /* chunk compressed into its own buffer, which must be released */
DEBUGLOG(5, "releasing buffer %u>=%u", chunkID, compressWithinDst);
ZSTDMT_releaseBuffer(mtctx->bufPool, mtctx->jobs[chunkID].dstBuff);
- }
- mtctx->jobs[chunkID].dstBuff = g_nullBuffer;
- }
+ } }
+ mtctx->jobs[chunkID].dstBuff = g_nullBuffer;
dstPos += cSize ;
}
} /* for (chunkID=0; chunkID<nbChunks; chunkID++) */
@@ -651,6 +713,23 @@ size_t ZSTDMT_compress_advanced(ZSTDMT_CCtx* mtctx,
}
}
+size_t ZSTDMT_compress_advanced(ZSTDMT_CCtx* mtctx,
+ void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize,
+ const ZSTD_CDict* cdict,
+ ZSTD_parameters const params,
+ unsigned overlapLog)
+{
+ ZSTD_CCtx_params cctxParams = mtctx->params;
+ cctxParams.cParams = params.cParams;
+ cctxParams.fParams = params.fParams;
+ cctxParams.overlapSizeLog = overlapLog;
+ return ZSTDMT_compress_advanced_internal(mtctx,
+ dst, dstCapacity,
+ src, srcSize,
+ cdict, cctxParams);
+}
+
size_t ZSTDMT_compressCCtx(ZSTDMT_CCtx* mtctx,
void* dst, size_t dstCapacity,
@@ -668,38 +747,25 @@ size_t ZSTDMT_compressCCtx(ZSTDMT_CCtx* mtctx,
/* ======= Streaming API ======= */
/* ====================================== */
-static void ZSTDMT_waitForAllJobsCompleted(ZSTDMT_CCtx* zcs)
-{
- DEBUGLOG(4, "ZSTDMT_waitForAllJobsCompleted");
- while (zcs->doneJobID < zcs->nextJobID) {
- unsigned const jobID = zcs->doneJobID & zcs->jobIDMask;
- PTHREAD_MUTEX_LOCK(&zcs->jobCompleted_mutex);
- while (zcs->jobs[jobID].jobCompleted==0) {
- DEBUGLOG(5, "waiting for jobCompleted signal from chunk %u", zcs->doneJobID); /* we want to block when waiting for data to flush */
- pthread_cond_wait(&zcs->jobCompleted_cond, &zcs->jobCompleted_mutex);
- }
- pthread_mutex_unlock(&zcs->jobCompleted_mutex);
- zcs->doneJobID++;
- }
-}
-
-
-/** ZSTDMT_initCStream_internal() :
- * internal usage only */
-size_t ZSTDMT_initCStream_internal(ZSTDMT_CCtx* zcs,
- const void* dict, size_t dictSize, const ZSTD_CDict* cdict,
- ZSTD_parameters params, unsigned long long pledgedSrcSize)
+size_t ZSTDMT_initCStream_internal(
+ ZSTDMT_CCtx* zcs,
+ const void* dict, size_t dictSize, ZSTD_dictMode_e dictMode,
+ const ZSTD_CDict* cdict, ZSTD_CCtx_params params,
+ unsigned long long pledgedSrcSize)
{
DEBUGLOG(4, "ZSTDMT_initCStream_internal");
/* params are supposed to be fully validated at this point */
assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
assert(!((dict) && (cdict))); /* either dict or cdict, not both */
+ assert(zcs->cctxPool->totalCCtx == params.nbThreads);
- if (zcs->nbThreads==1) {
+ if (params.nbThreads==1) {
+ ZSTD_CCtx_params const singleThreadParams = ZSTDMT_makeJobCCtxParams(params);
DEBUGLOG(4, "single thread mode");
+ assert(singleThreadParams.nbThreads == 0);
return ZSTD_initCStream_internal(zcs->cctxPool->cctx[0],
- dict, dictSize, cdict,
- params, pledgedSrcSize);
+ dict, dictSize, cdict,
+ singleThreadParams, pledgedSrcSize);
}
if (zcs->allJobsCompleted == 0) { /* previous compression not correctly finished */
@@ -714,7 +780,7 @@ size_t ZSTDMT_initCStream_internal(ZSTDMT_CCtx* zcs,
DEBUGLOG(4,"cdictLocal: %08X", (U32)(size_t)zcs->cdictLocal);
ZSTD_freeCDict(zcs->cdictLocal);
zcs->cdictLocal = ZSTD_createCDict_advanced(dict, dictSize,
- 0 /* byRef */, ZSTD_dm_auto, /* note : a loadPrefix becomes an internal CDict */
+ ZSTD_dlm_byCopy, dictMode, /* note : a loadPrefix becomes an internal CDict */
params.cParams, zcs->cMem);
zcs->cdict = zcs->cdictLocal;
if (zcs->cdictLocal == NULL) return ERROR(memory_allocation);
@@ -725,10 +791,10 @@ size_t ZSTDMT_initCStream_internal(ZSTDMT_CCtx* zcs,
zcs->cdict = cdict;
}
- zcs->targetDictSize = (zcs->overlapLog==0) ? 0 : (size_t)1 << (zcs->params.cParams.windowLog - (9 - zcs->overlapLog));
- DEBUGLOG(4, "overlapLog : %u ", zcs->overlapLog);
+ zcs->targetDictSize = (params.overlapSizeLog==0) ? 0 : (size_t)1 << (params.cParams.windowLog - (9 - params.overlapSizeLog));
+ DEBUGLOG(4, "overlapLog : %u ", params.overlapSizeLog);
DEBUGLOG(4, "overlap Size : %u KB", (U32)(zcs->targetDictSize>>10));
- zcs->targetSectionSize = zcs->sectionSize ? zcs->sectionSize : (size_t)1 << (zcs->params.cParams.windowLog + 2);
+ zcs->targetSectionSize = params.jobSize ? params.jobSize : (size_t)1 << (params.cParams.windowLog + 2);
zcs->targetSectionSize = MAX(ZSTDMT_SECTION_SIZE_MIN, zcs->targetSectionSize);
zcs->targetSectionSize = MAX(zcs->targetDictSize, zcs->targetSectionSize);
DEBUGLOG(4, "Section Size : %u KB", (U32)(zcs->targetSectionSize>>10));
@@ -749,8 +815,12 @@ size_t ZSTDMT_initCStream_advanced(ZSTDMT_CCtx* mtctx,
ZSTD_parameters params,
unsigned long long pledgedSrcSize)
{
+ ZSTD_CCtx_params cctxParams = mtctx->params;
DEBUGLOG(5, "ZSTDMT_initCStream_advanced");
- return ZSTDMT_initCStream_internal(mtctx, dict, dictSize, NULL, params, pledgedSrcSize);
+ cctxParams.cParams = params.cParams;
+ cctxParams.fParams = params.fParams;
+ return ZSTDMT_initCStream_internal(mtctx, dict, dictSize, ZSTD_dm_auto, NULL,
+ cctxParams, pledgedSrcSize);
}
size_t ZSTDMT_initCStream_usingCDict(ZSTDMT_CCtx* mtctx,
@@ -758,11 +828,12 @@ size_t ZSTDMT_initCStream_usingCDict(ZSTDMT_CCtx* mtctx,
ZSTD_frameParameters fParams,
unsigned long long pledgedSrcSize)
{
- ZSTD_parameters params = ZSTD_getParamsFromCDict(cdict);
+ ZSTD_CCtx_params cctxParams = mtctx->params;
+ cctxParams.cParams = ZSTD_getCParamsFromCDict(cdict);
+ cctxParams.fParams = fParams;
if (cdict==NULL) return ERROR(dictionary_wrong); /* method incompatible with NULL cdict */
- params.fParams = fParams;
- return ZSTDMT_initCStream_internal(mtctx, NULL, 0 /*dictSize*/, cdict,
- params, pledgedSrcSize);
+ return ZSTDMT_initCStream_internal(mtctx, NULL, 0 /*dictSize*/, ZSTD_dm_auto, cdict,
+ cctxParams, pledgedSrcSize);
}
@@ -770,14 +841,18 @@ size_t ZSTDMT_initCStream_usingCDict(ZSTDMT_CCtx* mtctx,
* pledgedSrcSize is optional and can be zero == unknown */
size_t ZSTDMT_resetCStream(ZSTDMT_CCtx* zcs, unsigned long long pledgedSrcSize)
{
- if (zcs->nbThreads==1)
+ if (zcs->params.nbThreads==1)
return ZSTD_resetCStream(zcs->cctxPool->cctx[0], pledgedSrcSize);
- return ZSTDMT_initCStream_internal(zcs, NULL, 0, 0, zcs->params, pledgedSrcSize);
+ return ZSTDMT_initCStream_internal(zcs, NULL, 0, ZSTD_dm_auto, 0, zcs->params,
+ pledgedSrcSize);
}
size_t ZSTDMT_initCStream(ZSTDMT_CCtx* zcs, int compressionLevel) {
ZSTD_parameters const params = ZSTD_getParams(compressionLevel, 0, 0);
- return ZSTDMT_initCStream_internal(zcs, NULL, 0, NULL, params, 0);
+ ZSTD_CCtx_params cctxParams = zcs->params;
+ cctxParams.cParams = params.cParams;
+ cctxParams.fParams = params.fParams;
+ return ZSTDMT_initCStream_internal(zcs, NULL, 0, ZSTD_dm_auto, NULL, cctxParams, 0);
}
@@ -856,13 +931,13 @@ static size_t ZSTDMT_flushNextJob(ZSTDMT_CCtx* zcs, ZSTD_outBuffer* output, unsi
{
unsigned const wJobID = zcs->doneJobID & zcs->jobIDMask;
if (zcs->doneJobID == zcs->nextJobID) return 0; /* all flushed ! */
- PTHREAD_MUTEX_LOCK(&zcs->jobCompleted_mutex);
+ ZSTD_PTHREAD_MUTEX_LOCK(&zcs->jobCompleted_mutex);
while (zcs->jobs[wJobID].jobCompleted==0) {
DEBUGLOG(5, "waiting for jobCompleted signal from job %u", zcs->doneJobID);
- if (!blockToFlush) { pthread_mutex_unlock(&zcs->jobCompleted_mutex); return 0; } /* nothing ready to be flushed => skip */
- pthread_cond_wait(&zcs->jobCompleted_cond, &zcs->jobCompleted_mutex); /* block when nothing available to flush */
+ if (!blockToFlush) { ZSTD_pthread_mutex_unlock(&zcs->jobCompleted_mutex); return 0; } /* nothing ready to be flushed => skip */
+ ZSTD_pthread_cond_wait(&zcs->jobCompleted_cond, &zcs->jobCompleted_mutex); /* block when nothing available to flush */
}
- pthread_mutex_unlock(&zcs->jobCompleted_mutex);
+ ZSTD_pthread_mutex_unlock(&zcs->jobCompleted_mutex);
/* compression job completed : output can be flushed */
{ ZSTDMT_jobDescription job = zcs->jobs[wJobID];
if (!job.jobScanned) {
@@ -906,7 +981,7 @@ static size_t ZSTDMT_flushNextJob(ZSTDMT_CCtx* zcs, ZSTD_outBuffer* output, unsi
/** ZSTDMT_compressStream_generic() :
- * internal use only
+ * internal use only - exposed to be invoked from zstd_compress.c
* assumption : output and input are valid (pos <= size)
* @return : minimum amount of data remaining to flush, 0 if none */
size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
@@ -915,25 +990,26 @@ size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
ZSTD_EndDirective endOp)
{
size_t const newJobThreshold = mtctx->dictSize + mtctx->targetSectionSize;
+ unsigned forwardInputProgress = 0;
assert(output->pos <= output->size);
assert(input->pos <= input->size);
if ((mtctx->frameEnded) && (endOp==ZSTD_e_continue)) {
- /* current frame being ended. Only flush/end are allowed. Or start new frame with init */
+ /* current frame being ended. Only flush/end are allowed */
return ERROR(stage_wrong);
}
- if (mtctx->nbThreads==1) { /* delegate to single-thread (synchronous) */
+ if (mtctx->params.nbThreads==1) { /* delegate to single-thread (synchronous) */
return ZSTD_compressStream_generic(mtctx->cctxPool->cctx[0], output, input, endOp);
}
- /* single-pass shortcut (note : this is synchronous-mode) */
- if ( (mtctx->nextJobID==0) /* just started */
- && (mtctx->inBuff.filled==0) /* nothing buffered */
- && (endOp==ZSTD_e_end) /* end order */
+ /* single-pass shortcut (note : synchronous-mode) */
+ if ( (mtctx->nextJobID == 0) /* just started */
+ && (mtctx->inBuff.filled == 0) /* nothing buffered */
+ && (endOp == ZSTD_e_end) /* end order */
&& (output->size - output->pos >= ZSTD_compressBound(input->size - input->pos)) ) { /* enough room */
- size_t const cSize = ZSTDMT_compress_advanced(mtctx,
+ size_t const cSize = ZSTDMT_compress_advanced_internal(mtctx,
(char*)output->dst + output->pos, output->size - output->pos,
(const char*)input->src + input->pos, input->size - input->pos,
- mtctx->cdict, mtctx->params, mtctx->overlapLog);
+ mtctx->cdict, mtctx->params);
if (ZSTD_isError(cSize)) return cSize;
input->pos = input->size;
output->pos += cSize;
@@ -946,15 +1022,16 @@ size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
/* fill input buffer */
if (input->size > input->pos) { /* support NULL input */
if (mtctx->inBuff.buffer.start == NULL) {
- mtctx->inBuff.buffer = ZSTDMT_getBuffer(mtctx->bufPool);
- if (mtctx->inBuff.buffer.start == NULL) return ERROR(memory_allocation);
+ mtctx->inBuff.buffer = ZSTDMT_getBuffer(mtctx->bufPool); /* note : may fail, in which case, no forward input progress */
mtctx->inBuff.filled = 0;
}
- { size_t const toLoad = MIN(input->size - input->pos, mtctx->inBuffSize - mtctx->inBuff.filled);
+ if (mtctx->inBuff.buffer.start) {
+ size_t const toLoad = MIN(input->size - input->pos, mtctx->inBuffSize - mtctx->inBuff.filled);
DEBUGLOG(5, "inBuff:%08X; inBuffSize=%u; ToCopy=%u", (U32)(size_t)mtctx->inBuff.buffer.start, (U32)mtctx->inBuffSize, (U32)toLoad);
memcpy((char*)mtctx->inBuff.buffer.start + mtctx->inBuff.filled, (const char*)input->src + input->pos, toLoad);
input->pos += toLoad;
mtctx->inBuff.filled += toLoad;
+ forwardInputProgress = toLoad>0;
} }
if ( (mtctx->inBuff.filled >= newJobThreshold) /* filled enough : let's compress */
@@ -963,7 +1040,7 @@ size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
}
/* check for potential compressed data ready to be flushed */
- CHECK_F( ZSTDMT_flushNextJob(mtctx, output, (mtctx->inBuff.filled == mtctx->inBuffSize) /* blockToFlush */) ); /* block if it wasn't possible to create new job due to saturation */
+ CHECK_F( ZSTDMT_flushNextJob(mtctx, output, !forwardInputProgress /* blockToFlush */) ); /* block if there was no forward input progress */
if (input->pos < input->size) /* input not consumed : do not flush yet */
endOp = ZSTD_e_continue;
@@ -1008,7 +1085,7 @@ static size_t ZSTDMT_flushStream_internal(ZSTDMT_CCtx* zcs, ZSTD_outBuffer* outp
size_t ZSTDMT_flushStream(ZSTDMT_CCtx* zcs, ZSTD_outBuffer* output)
{
DEBUGLOG(5, "ZSTDMT_flushStream");
- if (zcs->nbThreads==1)
+ if (zcs->params.nbThreads==1)
return ZSTD_flushStream(zcs->cctxPool->cctx[0], output);
return ZSTDMT_flushStream_internal(zcs, output, 0 /* endFrame */);
}
@@ -1016,7 +1093,7 @@ size_t ZSTDMT_flushStream(ZSTDMT_CCtx* zcs, ZSTD_outBuffer* output)
size_t ZSTDMT_endStream(ZSTDMT_CCtx* zcs, ZSTD_outBuffer* output)
{
DEBUGLOG(4, "ZSTDMT_endStream");
- if (zcs->nbThreads==1)
+ if (zcs->params.nbThreads==1)
return ZSTD_endStream(zcs->cctxPool->cctx[0], output);
return ZSTDMT_flushStream_internal(zcs, output, 1 /* endFrame */);
}
diff --git a/thirdparty/zstd/compress/zstdmt_compress.h b/thirdparty/zstd/compress/zstdmt_compress.h
index 0f0fc2b03f..8c59c684f1 100644
--- a/thirdparty/zstd/compress/zstdmt_compress.h
+++ b/thirdparty/zstd/compress/zstdmt_compress.h
@@ -5,6 +5,7 @@
* This source code is licensed under both the BSD-style license (found in the
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
* in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
*/
#ifndef ZSTDMT_COMPRESS_H
@@ -80,19 +81,19 @@ ZSTDLIB_API size_t ZSTDMT_initCStream_usingCDict(ZSTDMT_CCtx* mtctx,
ZSTD_frameParameters fparams,
unsigned long long pledgedSrcSize); /* note : zero means empty */
-/* ZSDTMT_parameter :
+/* ZSTDMT_parameter :
* List of parameters that can be set using ZSTDMT_setMTCtxParameter() */
typedef enum {
ZSTDMT_p_sectionSize, /* size of input "section". Each section is compressed in parallel. 0 means default, which is dynamically determined within compression functions */
ZSTDMT_p_overlapSectionLog /* Log of overlapped section; 0 == no overlap, 6(default) == use 1/8th of window, >=9 == use full window */
-} ZSDTMT_parameter;
+} ZSTDMT_parameter;
/* ZSTDMT_setMTCtxParameter() :
* allow setting individual parameters, one at a time, among a list of enums defined in ZSTDMT_parameter.
* The function must be called typically after ZSTD_createCCtx().
* Parameters not explicitly reset by ZSTDMT_init*() remain the same in consecutive compression sessions.
* @return : 0, or an error code (which can be tested using ZSTD_isError()) */
-ZSTDLIB_API size_t ZSTDMT_setMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSDTMT_parameter parameter, unsigned value);
+ZSTDLIB_API size_t ZSTDMT_setMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter parameter, unsigned value);
/*! ZSTDMT_compressStream_generic() :
@@ -107,6 +108,22 @@ ZSTDLIB_API size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
ZSTD_EndDirective endOp);
+/* === Private definitions; never ever use directly === */
+
+size_t ZSTDMT_CCtxParam_setMTCtxParameter(ZSTD_CCtx_params* params, ZSTDMT_parameter parameter, unsigned value);
+
+size_t ZSTDMT_initializeCCtxParameters(ZSTD_CCtx_params* params, unsigned nbThreads);
+
+/*! ZSTDMT_initCStream_internal() :
+ * Private use only. Init streaming operation.
+ * expects params to be valid.
+ * must receive dict, or cdict, or none, but not both.
+ * @return : 0, or an error code */
+size_t ZSTDMT_initCStream_internal(ZSTDMT_CCtx* zcs,
+ const void* dict, size_t dictSize, ZSTD_dictMode_e dictMode,
+ const ZSTD_CDict* cdict,
+ ZSTD_CCtx_params params, unsigned long long pledgedSrcSize);
+
#if defined (__cplusplus)
}
diff --git a/thirdparty/zstd/decompress/zstd_decompress.c b/thirdparty/zstd/decompress/zstd_decompress.c
index d2bc545e52..96fc609089 100644
--- a/thirdparty/zstd/decompress/zstd_decompress.c
+++ b/thirdparty/zstd/decompress/zstd_decompress.c
@@ -5,6 +5,7 @@
* This source code is licensed under both the BSD-style license (found in the
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
* in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
*/
@@ -34,7 +35,7 @@
* Frames requiring more memory will be rejected.
*/
#ifndef ZSTD_MAXWINDOWSIZE_DEFAULT
-# define ZSTD_MAXWINDOWSIZE_DEFAULT ((1 << ZSTD_WINDOWLOG_MAX) + 1) /* defined within zstd.h */
+# define ZSTD_MAXWINDOWSIZE_DEFAULT (((U32)1 << ZSTD_WINDOWLOG_DEFAULTMAX) + 1)
#endif
@@ -101,13 +102,15 @@ struct ZSTD_DCtx_s
const void* dictEnd; /* end of previous segment */
size_t expected;
ZSTD_frameHeader fParams;
- blockType_e bType; /* used in ZSTD_decompressContinue(), to transfer blockType between header decoding and block decoding stages */
+ U64 decodedSize;
+ blockType_e bType; /* used in ZSTD_decompressContinue(), store blockType between block header decoding and block decompression stages */
ZSTD_dStage stage;
U32 litEntropy;
U32 fseEntropy;
XXH64_state_t xxhState;
size_t headerSize;
U32 dictID;
+ ZSTD_format_e format;
const BYTE* litPtr;
ZSTD_customMem customMem;
size_t litSize;
@@ -126,7 +129,6 @@ struct ZSTD_DCtx_s
size_t outBuffSize;
size_t outStart;
size_t outEnd;
- size_t blockSize;
size_t lhSize;
void* legacyContext;
U32 previousLegacyVersion;
@@ -148,39 +150,44 @@ size_t ZSTD_sizeof_DCtx (const ZSTD_DCtx* dctx)
size_t ZSTD_estimateDCtxSize(void) { return sizeof(ZSTD_DCtx); }
-size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
+
+static size_t ZSTD_startingInputLength(ZSTD_format_e format)
{
- dctx->expected = ZSTD_frameHeaderSize_prefix;
- dctx->stage = ZSTDds_getFrameHeaderSize;
- dctx->previousDstEnd = NULL;
- dctx->base = NULL;
- dctx->vBase = NULL;
- dctx->dictEnd = NULL;
- dctx->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */
- dctx->litEntropy = dctx->fseEntropy = 0;
- dctx->dictID = 0;
- MEM_STATIC_ASSERT(sizeof(dctx->entropy.rep) == sizeof(repStartValue));
- memcpy(dctx->entropy.rep, repStartValue, sizeof(repStartValue)); /* initial repcodes */
- dctx->LLTptr = dctx->entropy.LLTable;
- dctx->MLTptr = dctx->entropy.MLTable;
- dctx->OFTptr = dctx->entropy.OFTable;
- dctx->HUFptr = dctx->entropy.hufTable;
- return 0;
+ size_t const startingInputLength = (format==ZSTD_f_zstd1_magicless) ?
+ ZSTD_frameHeaderSize_prefix - ZSTD_frameIdSize :
+ ZSTD_frameHeaderSize_prefix;
+ ZSTD_STATIC_ASSERT(ZSTD_FRAMEHEADERSIZE_PREFIX >= ZSTD_FRAMEIDSIZE);
+ /* only supports formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless */
+ assert( (format == ZSTD_f_zstd1) || (format == ZSTD_f_zstd1_magicless) );
+ return startingInputLength;
}
static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx)
{
- ZSTD_decompressBegin(dctx); /* cannot fail */
- dctx->staticSize = 0;
+ dctx->format = ZSTD_f_zstd1; /* ZSTD_decompressBegin() invokes ZSTD_startingInputLength() with argument dctx->format */
+ dctx->staticSize = 0;
dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
- dctx->ddict = NULL;
- dctx->ddictLocal = NULL;
- dctx->inBuff = NULL;
- dctx->inBuffSize = 0;
- dctx->outBuffSize= 0;
+ dctx->ddict = NULL;
+ dctx->ddictLocal = NULL;
+ dctx->inBuff = NULL;
+ dctx->inBuffSize = 0;
+ dctx->outBuffSize = 0;
dctx->streamStage = zdss_init;
}
+ZSTD_DCtx* ZSTD_initStaticDCtx(void *workspace, size_t workspaceSize)
+{
+ ZSTD_DCtx* const dctx = (ZSTD_DCtx*) workspace;
+
+ if ((size_t)workspace & 7) return NULL; /* 8-aligned */
+ if (workspaceSize < sizeof(ZSTD_DCtx)) return NULL; /* minimum size */
+
+ ZSTD_initDCtx_internal(dctx);
+ dctx->staticSize = workspaceSize;
+ dctx->inBuff = (char*)(dctx+1);
+ return dctx;
+}
+
ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem)
{
if (!customMem.customAlloc ^ !customMem.customFree) return NULL;
@@ -195,19 +202,6 @@ ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem)
}
}
-ZSTD_DCtx* ZSTD_initStaticDCtx(void *workspace, size_t workspaceSize)
-{
- ZSTD_DCtx* dctx = (ZSTD_DCtx*) workspace;
-
- if ((size_t)workspace & 7) return NULL; /* 8-aligned */
- if (workspaceSize < sizeof(ZSTD_DCtx)) return NULL; /* minimum size */
-
- ZSTD_initDCtx_internal(dctx);
- dctx->staticSize = workspaceSize;
- dctx->inBuff = (char*)(dctx+1);
- return dctx;
-}
-
ZSTD_DCtx* ZSTD_createDCtx(void)
{
return ZSTD_createDCtx_advanced(ZSTD_defaultCMem);
@@ -250,7 +244,7 @@ void ZSTD_copyDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx)
* Note 3 : Skippable Frame Identifiers are considered valid. */
unsigned ZSTD_isFrame(const void* buffer, size_t size)
{
- if (size < 4) return 0;
+ if (size < ZSTD_frameIdSize) return 0;
{ U32 const magic = MEM_readLE32(buffer);
if (magic == ZSTD_MAGICNUMBER) return 1;
if ((magic & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) return 1;
@@ -261,55 +255,70 @@ unsigned ZSTD_isFrame(const void* buffer, size_t size)
return 0;
}
-
-/** ZSTD_frameHeaderSize() :
-* srcSize must be >= ZSTD_frameHeaderSize_prefix.
-* @return : size of the Frame Header */
-size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize)
+/** ZSTD_frameHeaderSize_internal() :
+ * srcSize must be large enough to reach header size fields.
+ * note : only works for formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless
+ * @return : size of the Frame Header
+ * or an error code, which can be tested with ZSTD_isError() */
+static size_t ZSTD_frameHeaderSize_internal(const void* src, size_t srcSize, ZSTD_format_e format)
{
- if (srcSize < ZSTD_frameHeaderSize_prefix) return ERROR(srcSize_wrong);
- { BYTE const fhd = ((const BYTE*)src)[4];
+ size_t const minInputSize = ZSTD_startingInputLength(format);
+ if (srcSize < minInputSize) return ERROR(srcSize_wrong);
+
+ { BYTE const fhd = ((const BYTE*)src)[minInputSize-1];
U32 const dictID= fhd & 3;
U32 const singleSegment = (fhd >> 5) & 1;
U32 const fcsId = fhd >> 6;
- return ZSTD_frameHeaderSize_prefix + !singleSegment + ZSTD_did_fieldSize[dictID] + ZSTD_fcs_fieldSize[fcsId]
- + (singleSegment && !fcsId);
+ return minInputSize + !singleSegment
+ + ZSTD_did_fieldSize[dictID] + ZSTD_fcs_fieldSize[fcsId]
+ + (singleSegment && !fcsId);
}
}
+/** ZSTD_frameHeaderSize() :
+ * srcSize must be >= ZSTD_frameHeaderSize_prefix.
+ * @return : size of the Frame Header */
+size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize)
+{
+ return ZSTD_frameHeaderSize_internal(src, srcSize, ZSTD_f_zstd1);
+}
-/** ZSTD_getFrameHeader() :
-* decode Frame Header, or require larger `srcSize`.
-* @return : 0, `zfhPtr` is correctly filled,
-* >0, `srcSize` is too small, result is expected `srcSize`,
-* or an error code, which can be tested using ZSTD_isError() */
-size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize)
+
+/** ZSTD_getFrameHeader_internal() :
+ * decode Frame Header, or require larger `srcSize`.
+ * note : only works for formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless
+ * @return : 0, `zfhPtr` is correctly filled,
+ * >0, `srcSize` is too small, value is wanted `srcSize` amount,
+ * or an error code, which can be tested using ZSTD_isError() */
+static size_t ZSTD_getFrameHeader_internal(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize, ZSTD_format_e format)
{
const BYTE* ip = (const BYTE*)src;
- if (srcSize < ZSTD_frameHeaderSize_prefix) return ZSTD_frameHeaderSize_prefix;
+ size_t const minInputSize = ZSTD_startingInputLength(format);
- if (MEM_readLE32(src) != ZSTD_MAGICNUMBER) {
+ if (srcSize < minInputSize) return minInputSize;
+
+ if ( (format != ZSTD_f_zstd1_magicless)
+ && (MEM_readLE32(src) != ZSTD_MAGICNUMBER) ) {
if ((MEM_readLE32(src) & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) {
/* skippable frame */
if (srcSize < ZSTD_skippableHeaderSize)
return ZSTD_skippableHeaderSize; /* magic number + frame length */
memset(zfhPtr, 0, sizeof(*zfhPtr));
- zfhPtr->frameContentSize = MEM_readLE32((const char *)src + 4);
+ zfhPtr->frameContentSize = MEM_readLE32((const char *)src + ZSTD_frameIdSize);
zfhPtr->frameType = ZSTD_skippableFrame;
- zfhPtr->windowSize = 0;
return 0;
}
return ERROR(prefix_unknown);
}
/* ensure there is enough `srcSize` to fully read/decode frame header */
- { size_t const fhsize = ZSTD_frameHeaderSize(src, srcSize);
+ { size_t const fhsize = ZSTD_frameHeaderSize_internal(src, srcSize, format);
if (srcSize < fhsize) return fhsize;
zfhPtr->headerSize = (U32)fhsize;
}
- { BYTE const fhdByte = ip[4];
- size_t pos = 5;
+ { BYTE const fhdByte = ip[minInputSize-1];
+ size_t pos = minInputSize;
U32 const dictIDSizeCode = fhdByte&3;
U32 const checksumFlag = (fhdByte>>2)&1;
U32 const singleSegment = (fhdByte>>5)&1;
@@ -349,12 +358,25 @@ size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, const void* src, size_t src
zfhPtr->frameType = ZSTD_frame;
zfhPtr->frameContentSize = frameContentSize;
zfhPtr->windowSize = windowSize;
+ zfhPtr->blockSizeMax = (unsigned) MIN(windowSize, ZSTD_BLOCKSIZE_MAX);
zfhPtr->dictID = dictID;
zfhPtr->checksumFlag = checksumFlag;
}
return 0;
}
+/** ZSTD_getFrameHeader() :
+ * decode Frame Header, or require larger `srcSize`.
+ * note : this function does not consume input, it only reads it.
+ * @return : 0, `zfhPtr` is correctly filled,
+ * >0, `srcSize` is too small, value is wanted `srcSize` amount,
+ * or an error code, which can be tested using ZSTD_isError() */
+size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize)
+{
+ return ZSTD_getFrameHeader_internal(zfhPtr, src, srcSize, ZSTD_f_zstd1);
+}
+
+
/** ZSTD_getFrameContentSize() :
* compatible with legacy mode
* @return : decompressed size of the single frame pointed to be `src` if known, otherwise
@@ -388,14 +410,14 @@ unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize)
unsigned long long totalDstSize = 0;
while (srcSize >= ZSTD_frameHeaderSize_prefix) {
- const U32 magicNumber = MEM_readLE32(src);
+ U32 const magicNumber = MEM_readLE32(src);
if ((magicNumber & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) {
size_t skippableSize;
if (srcSize < ZSTD_skippableHeaderSize)
return ERROR(srcSize_wrong);
- skippableSize = MEM_readLE32((const BYTE *)src + 4) +
- ZSTD_skippableHeaderSize;
+ skippableSize = MEM_readLE32((const BYTE *)src + ZSTD_frameIdSize)
+ + ZSTD_skippableHeaderSize;
if (srcSize < skippableSize) {
return ZSTD_CONTENTSIZE_ERROR;
}
@@ -420,11 +442,9 @@ unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize)
src = (const BYTE *)src + frameSrcSize;
srcSize -= frameSrcSize;
}
- }
+ } /* while (srcSize >= ZSTD_frameHeaderSize_prefix) */
- if (srcSize) {
- return ZSTD_CONTENTSIZE_ERROR;
- }
+ if (srcSize) return ZSTD_CONTENTSIZE_ERROR;
return totalDstSize;
}
@@ -440,7 +460,8 @@ unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize)
unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize)
{
unsigned long long const ret = ZSTD_getFrameContentSize(src, srcSize);
- return ret >= ZSTD_CONTENTSIZE_ERROR ? 0 : ret;
+ ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_ERROR < ZSTD_CONTENTSIZE_UNKNOWN);
+ return (ret >= ZSTD_CONTENTSIZE_ERROR) ? 0 : ret;
}
@@ -449,9 +470,9 @@ unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize)
* @return : 0 if success, or an error code, which can be tested using ZSTD_isError() */
static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* dctx, const void* src, size_t headerSize)
{
- size_t const result = ZSTD_getFrameHeader(&(dctx->fParams), src, headerSize);
- if (ZSTD_isError(result)) return result; /* invalid header */
- if (result>0) return ERROR(srcSize_wrong); /* headerSize too small */
+ size_t const result = ZSTD_getFrameHeader_internal(&(dctx->fParams), src, headerSize, dctx->format);
+ if (ZSTD_isError(result)) return result; /* invalid header */
+ if (result>0) return ERROR(srcSize_wrong); /* headerSize too small */
if (dctx->fParams.dictID && (dctx->dictID != dctx->fParams.dictID))
return ERROR(dictionary_wrong);
if (dctx->fParams.checksumFlag) XXH64_reset(&dctx->xxhState, 0);
@@ -497,7 +518,8 @@ static size_t ZSTD_setRleBlock(void* dst, size_t dstCapacity,
}
/*! ZSTD_decodeLiteralsBlock() :
- @return : nb of bytes read from src (< srcSize ) */
+ * @return : nb of bytes read from src (< srcSize )
+ * note : symbol not declared but exposed for fullbench */
size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
const void* src, size_t srcSize) /* note : srcSize < BLOCKSIZE */
{
@@ -698,9 +720,9 @@ static const FSE_decode_t4 OF_defaultDTable[(1<<OF_DEFAULTNORMLOG)+1] = {
}; /* OF_defaultDTable */
/*! ZSTD_buildSeqTable() :
- @return : nb bytes read from src,
- or an error code if it fails, testable with ZSTD_isError()
-*/
+ * @return : nb bytes read from src,
+ * or an error code if it fails, testable with ZSTD_isError()
+ */
static size_t ZSTD_buildSeqTable(FSE_DTable* DTableSpace, const FSE_DTable** DTablePtr,
symbolEncodingType_e type, U32 max, U32 maxLog,
const void* src, size_t srcSize,
@@ -858,13 +880,25 @@ size_t ZSTD_execSequenceLast7(BYTE* op,
}
-static seq_t ZSTD_decodeSequence(seqState_t* seqState)
+typedef enum { ZSTD_lo_isRegularOffset, ZSTD_lo_isLongOffset=1 } ZSTD_longOffset_e;
+
+/* We need to add at most (ZSTD_WINDOWLOG_MAX_32 - 1) bits to read the maximum
+ * offset bits. But we can only read at most (STREAM_ACCUMULATOR_MIN_32 - 1)
+ * bits before reloading. This value is the maximum number of bytes we read
+ * after reloading when we are decoding long offets.
+ */
+#define LONG_OFFSETS_MAX_EXTRA_BITS_32 \
+ (ZSTD_WINDOWLOG_MAX_32 > STREAM_ACCUMULATOR_MIN_32 \
+ ? ZSTD_WINDOWLOG_MAX_32 - STREAM_ACCUMULATOR_MIN_32 \
+ : 0)
+
+static seq_t ZSTD_decodeSequence(seqState_t* seqState, const ZSTD_longOffset_e longOffsets)
{
seq_t seq;
U32 const llCode = FSE_peekSymbol(&seqState->stateLL);
U32 const mlCode = FSE_peekSymbol(&seqState->stateML);
- U32 const ofCode = FSE_peekSymbol(&seqState->stateOffb); /* <= maxOff, by table construction */
+ U32 const ofCode = FSE_peekSymbol(&seqState->stateOffb); /* <= MaxOff, by table construction */
U32 const llBits = LL_bits[llCode];
U32 const mlBits = ML_bits[mlCode];
@@ -891,15 +925,25 @@ static seq_t ZSTD_decodeSequence(seqState_t* seqState)
0, 1, 1, 5, 0xD, 0x1D, 0x3D, 0x7D,
0xFD, 0x1FD, 0x3FD, 0x7FD, 0xFFD, 0x1FFD, 0x3FFD, 0x7FFD,
0xFFFD, 0x1FFFD, 0x3FFFD, 0x7FFFD, 0xFFFFD, 0x1FFFFD, 0x3FFFFD, 0x7FFFFD,
- 0xFFFFFD, 0x1FFFFFD, 0x3FFFFFD, 0x7FFFFFD, 0xFFFFFFD };
+ 0xFFFFFD, 0x1FFFFFD, 0x3FFFFFD, 0x7FFFFFD, 0xFFFFFFD, 0x1FFFFFFD, 0x3FFFFFFD, 0x7FFFFFFD };
/* sequence */
{ size_t offset;
if (!ofCode)
offset = 0;
else {
- offset = OF_base[ofCode] + BIT_readBitsFast(&seqState->DStream, ofBits); /* <= (ZSTD_WINDOWLOG_MAX-1) bits */
- if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream);
+ ZSTD_STATIC_ASSERT(ZSTD_lo_isLongOffset == 1);
+ ZSTD_STATIC_ASSERT(LONG_OFFSETS_MAX_EXTRA_BITS_32 == 5);
+ assert(ofBits <= MaxOff);
+ if (MEM_32bits() && longOffsets) {
+ U32 const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN_32-1);
+ offset = OF_base[ofCode] + (BIT_readBitsFast(&seqState->DStream, ofBits - extraBits) << extraBits);
+ if (MEM_32bits() || extraBits) BIT_reloadDStream(&seqState->DStream);
+ if (extraBits) offset += BIT_readBitsFast(&seqState->DStream, extraBits);
+ } else {
+ offset = OF_base[ofCode] + BIT_readBitsFast(&seqState->DStream, ofBits); /* <= (ZSTD_WINDOWLOG_MAX-1) bits */
+ if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream);
+ }
}
if (ofCode <= 1) {
@@ -923,13 +967,17 @@ static seq_t ZSTD_decodeSequence(seqState_t* seqState)
seq.matchLength = ML_base[mlCode]
+ ((mlCode>31) ? BIT_readBitsFast(&seqState->DStream, mlBits) : 0); /* <= 16 bits */
- if (MEM_32bits() && (mlBits+llBits>24)) BIT_reloadDStream(&seqState->DStream);
+ if (MEM_32bits() && (mlBits+llBits >= STREAM_ACCUMULATOR_MIN_32-LONG_OFFSETS_MAX_EXTRA_BITS_32))
+ BIT_reloadDStream(&seqState->DStream);
+ if (MEM_64bits() && (totalBits >= STREAM_ACCUMULATOR_MIN_64-(LLFSELog+MLFSELog+OffFSELog)))
+ BIT_reloadDStream(&seqState->DStream);
+ /* Verify that there is enough bits to read the rest of the data in 64-bit mode. */
+ ZSTD_STATIC_ASSERT(16+LLFSELog+MLFSELog+OffFSELog < STREAM_ACCUMULATOR_MIN_64);
seq.litLength = LL_base[llCode]
+ ((llCode>15) ? BIT_readBitsFast(&seqState->DStream, llBits) : 0); /* <= 16 bits */
- if ( MEM_32bits()
- || (totalBits > 64 - 7 - (LLFSELog+MLFSELog+OffFSELog)) )
- BIT_reloadDStream(&seqState->DStream);
+ if (MEM_32bits())
+ BIT_reloadDStream(&seqState->DStream);
DEBUGLOG(6, "seq: litL=%u, matchL=%u, offset=%u",
(U32)seq.litLength, (U32)seq.matchLength, (U32)seq.offset);
@@ -1028,7 +1076,8 @@ size_t ZSTD_execSequence(BYTE* op,
static size_t ZSTD_decompressSequences(
ZSTD_DCtx* dctx,
void* dst, size_t maxDstSize,
- const void* seqStart, size_t seqSize)
+ const void* seqStart, size_t seqSize,
+ const ZSTD_longOffset_e isLongOffset)
{
const BYTE* ip = (const BYTE*)seqStart;
const BYTE* const iend = ip + seqSize;
@@ -1063,7 +1112,7 @@ static size_t ZSTD_decompressSequences(
for ( ; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && nbSeq ; ) {
nbSeq--;
- { seq_t const sequence = ZSTD_decodeSequence(&seqState);
+ { seq_t const sequence = ZSTD_decodeSequence(&seqState, isLongOffset);
size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequence, &litPtr, litEnd, base, vBase, dictEnd);
DEBUGLOG(6, "regenerated sequence size : %u", (U32)oneSeqSize);
if (ZSTD_isError(oneSeqSize)) return oneSeqSize;
@@ -1088,13 +1137,14 @@ static size_t ZSTD_decompressSequences(
}
-FORCE_INLINE_TEMPLATE seq_t ZSTD_decodeSequenceLong_generic(seqState_t* seqState, int const longOffsets)
+HINT_INLINE
+seq_t ZSTD_decodeSequenceLong(seqState_t* seqState, ZSTD_longOffset_e const longOffsets)
{
seq_t seq;
U32 const llCode = FSE_peekSymbol(&seqState->stateLL);
U32 const mlCode = FSE_peekSymbol(&seqState->stateML);
- U32 const ofCode = FSE_peekSymbol(&seqState->stateOffb); /* <= maxOff, by table construction */
+ U32 const ofCode = FSE_peekSymbol(&seqState->stateOffb); /* <= MaxOff, by table construction */
U32 const llBits = LL_bits[llCode];
U32 const mlBits = ML_bits[mlCode];
@@ -1121,15 +1171,18 @@ FORCE_INLINE_TEMPLATE seq_t ZSTD_decodeSequenceLong_generic(seqState_t* seqState
0, 1, 1, 5, 0xD, 0x1D, 0x3D, 0x7D,
0xFD, 0x1FD, 0x3FD, 0x7FD, 0xFFD, 0x1FFD, 0x3FFD, 0x7FFD,
0xFFFD, 0x1FFFD, 0x3FFFD, 0x7FFFD, 0xFFFFD, 0x1FFFFD, 0x3FFFFD, 0x7FFFFD,
- 0xFFFFFD, 0x1FFFFFD, 0x3FFFFFD, 0x7FFFFFD, 0xFFFFFFD };
+ 0xFFFFFD, 0x1FFFFFD, 0x3FFFFFD, 0x7FFFFFD, 0xFFFFFFD, 0x1FFFFFFD, 0x3FFFFFFD, 0x7FFFFFFD };
/* sequence */
{ size_t offset;
if (!ofCode)
offset = 0;
else {
- if (longOffsets) {
- int const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN);
+ ZSTD_STATIC_ASSERT(ZSTD_lo_isLongOffset == 1);
+ ZSTD_STATIC_ASSERT(LONG_OFFSETS_MAX_EXTRA_BITS_32 == 5);
+ assert(ofBits <= MaxOff);
+ if (MEM_32bits() && longOffsets) {
+ U32 const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN_32-1);
offset = OF_base[ofCode] + (BIT_readBitsFast(&seqState->DStream, ofBits - extraBits) << extraBits);
if (MEM_32bits() || extraBits) BIT_reloadDStream(&seqState->DStream);
if (extraBits) offset += BIT_readBitsFast(&seqState->DStream, extraBits);
@@ -1159,11 +1212,16 @@ FORCE_INLINE_TEMPLATE seq_t ZSTD_decodeSequenceLong_generic(seqState_t* seqState
}
seq.matchLength = ML_base[mlCode] + ((mlCode>31) ? BIT_readBitsFast(&seqState->DStream, mlBits) : 0); /* <= 16 bits */
- if (MEM_32bits() && (mlBits+llBits>24)) BIT_reloadDStream(&seqState->DStream);
+ if (MEM_32bits() && (mlBits+llBits >= STREAM_ACCUMULATOR_MIN_32-LONG_OFFSETS_MAX_EXTRA_BITS_32))
+ BIT_reloadDStream(&seqState->DStream);
+ if (MEM_64bits() && (totalBits >= STREAM_ACCUMULATOR_MIN_64-(LLFSELog+MLFSELog+OffFSELog)))
+ BIT_reloadDStream(&seqState->DStream);
+ /* Verify that there is enough bits to read the rest of the data in 64-bit mode. */
+ ZSTD_STATIC_ASSERT(16+LLFSELog+MLFSELog+OffFSELog < STREAM_ACCUMULATOR_MIN_64);
seq.litLength = LL_base[llCode] + ((llCode>15) ? BIT_readBitsFast(&seqState->DStream, llBits) : 0); /* <= 16 bits */
- if (MEM_32bits() ||
- (totalBits > 64 - 7 - (LLFSELog+MLFSELog+OffFSELog)) ) BIT_reloadDStream(&seqState->DStream);
+ if (MEM_32bits())
+ BIT_reloadDStream(&seqState->DStream);
{ size_t const pos = seqState->pos + seq.litLength;
seq.match = seqState->base + pos - seq.offset; /* single memory segment */
@@ -1180,19 +1238,12 @@ FORCE_INLINE_TEMPLATE seq_t ZSTD_decodeSequenceLong_generic(seqState_t* seqState
return seq;
}
-static seq_t ZSTD_decodeSequenceLong(seqState_t* seqState, unsigned const windowSize) {
- if (ZSTD_highbit32(windowSize) > STREAM_ACCUMULATOR_MIN) {
- return ZSTD_decodeSequenceLong_generic(seqState, 1);
- } else {
- return ZSTD_decodeSequenceLong_generic(seqState, 0);
- }
-}
HINT_INLINE
size_t ZSTD_execSequenceLong(BYTE* op,
- BYTE* const oend, seq_t sequence,
- const BYTE** litPtr, const BYTE* const litLimit,
- const BYTE* const base, const BYTE* const vBase, const BYTE* const dictEnd)
+ BYTE* const oend, seq_t sequence,
+ const BYTE** litPtr, const BYTE* const litLimit,
+ const BYTE* const base, const BYTE* const vBase, const BYTE* const dictEnd)
{
BYTE* const oLitEnd = op + sequence.litLength;
size_t const sequenceLength = sequence.litLength + sequence.matchLength;
@@ -1202,11 +1253,9 @@ size_t ZSTD_execSequenceLong(BYTE* op,
const BYTE* match = sequence.match;
/* check */
-#if 1
if (oMatchEnd>oend) return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of WILDCOPY_OVERLENGTH from oend */
if (iLitEnd > litLimit) return ERROR(corruption_detected); /* over-read beyond lit buffer */
if (oLitEnd>oend_w) return ZSTD_execSequenceLast7(op, oend, sequence, litPtr, litLimit, base, vBase, dictEnd);
-#endif
/* copy Literals */
ZSTD_copy8(op, *litPtr);
@@ -1216,7 +1265,6 @@ size_t ZSTD_execSequenceLong(BYTE* op,
*litPtr = iLitEnd; /* update for next sequence */
/* copy Match */
-#if 1
if (sequence.offset > (size_t)(oLitEnd - base)) {
/* offset beyond prefix */
if (sequence.offset > (size_t)(oLitEnd - vBase)) return ERROR(corruption_detected);
@@ -1236,8 +1284,8 @@ size_t ZSTD_execSequenceLong(BYTE* op,
return sequenceLength;
}
} }
- /* Requirement: op <= oend_w && sequence.matchLength >= MINMATCH */
-#endif
+ assert(op <= oend_w);
+ assert(sequence.matchLength >= MINMATCH);
/* match within prefix */
if (sequence.offset < 8) {
@@ -1273,7 +1321,8 @@ size_t ZSTD_execSequenceLong(BYTE* op,
static size_t ZSTD_decompressSequencesLong(
ZSTD_DCtx* dctx,
void* dst, size_t maxDstSize,
- const void* seqStart, size_t seqSize)
+ const void* seqStart, size_t seqSize,
+ const ZSTD_longOffset_e isLongOffset)
{
const BYTE* ip = (const BYTE*)seqStart;
const BYTE* const iend = ip + seqSize;
@@ -1285,7 +1334,6 @@ static size_t ZSTD_decompressSequencesLong(
const BYTE* const base = (const BYTE*) (dctx->base);
const BYTE* const vBase = (const BYTE*) (dctx->vBase);
const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd);
- unsigned const windowSize32 = (unsigned)dctx->fParams.windowSize;
int nbSeq;
/* Build Decoding Tables */
@@ -1315,13 +1363,13 @@ static size_t ZSTD_decompressSequencesLong(
/* prepare in advance */
for (seqNb=0; (BIT_reloadDStream(&seqState.DStream) <= BIT_DStream_completed) && seqNb<seqAdvance; seqNb++) {
- sequences[seqNb] = ZSTD_decodeSequenceLong(&seqState, windowSize32);
+ sequences[seqNb] = ZSTD_decodeSequenceLong(&seqState, isLongOffset);
}
if (seqNb<seqAdvance) return ERROR(corruption_detected);
/* decode and decompress */
for ( ; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && seqNb<nbSeq ; seqNb++) {
- seq_t const sequence = ZSTD_decodeSequenceLong(&seqState, windowSize32);
+ seq_t const sequence = ZSTD_decodeSequenceLong(&seqState, isLongOffset);
size_t const oneSeqSize = ZSTD_execSequenceLong(op, oend, sequences[(seqNb-ADVANCED_SEQS) & STOSEQ_MASK], &litPtr, litEnd, base, vBase, dictEnd);
if (ZSTD_isError(oneSeqSize)) return oneSeqSize;
PREFETCH(sequence.match);
@@ -1355,10 +1403,20 @@ static size_t ZSTD_decompressSequencesLong(
static size_t ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx,
void* dst, size_t dstCapacity,
- const void* src, size_t srcSize)
+ const void* src, size_t srcSize, const int frame)
{ /* blockType == blockCompressed */
const BYTE* ip = (const BYTE*)src;
- DEBUGLOG(5, "ZSTD_decompressBlock_internal");
+ /* isLongOffset must be true if there are long offsets.
+ * Offsets are long if they are larger than 2^STREAM_ACCUMULATOR_MIN.
+ * We don't expect that to be the case in 64-bit mode.
+ * If we are in block mode we don't know the window size, so we have to be
+ * conservative.
+ */
+ ZSTD_longOffset_e const isLongOffset = (ZSTD_longOffset_e)(MEM_32bits() && (!frame || dctx->fParams.windowSize > (1ULL << STREAM_ACCUMULATOR_MIN)));
+ /* windowSize could be any value at this point, since it is only validated
+ * in the streaming API.
+ */
+ DEBUGLOG(5, "ZSTD_decompressBlock_internal (size : %u)", (U32)srcSize);
if (srcSize >= ZSTD_BLOCKSIZE_MAX) return ERROR(srcSize_wrong);
@@ -1369,13 +1427,9 @@ static size_t ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx,
ip += litCSize;
srcSize -= litCSize;
}
- if (sizeof(size_t) > 4) /* do not enable prefetching on 32-bits x86, as it's performance detrimental */
- /* likely because of register pressure */
- /* if that's the correct cause, then 32-bits ARM should be affected differently */
- /* it would be good to test this on ARM real hardware, to see if prefetch version improves speed */
- if (dctx->fParams.windowSize > (1<<23))
- return ZSTD_decompressSequencesLong(dctx, dst, dstCapacity, ip, srcSize);
- return ZSTD_decompressSequences(dctx, dst, dstCapacity, ip, srcSize);
+ if (frame && dctx->fParams.windowSize > (1<<23))
+ return ZSTD_decompressSequencesLong(dctx, dst, dstCapacity, ip, srcSize, isLongOffset);
+ return ZSTD_decompressSequences(dctx, dst, dstCapacity, ip, srcSize, isLongOffset);
}
@@ -1395,7 +1449,7 @@ size_t ZSTD_decompressBlock(ZSTD_DCtx* dctx,
{
size_t dSize;
ZSTD_checkContinuity(dctx, dst);
- dSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize);
+ dSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, /* frame */ 0);
dctx->previousDstEnd = (char*)dst + dSize;
return dSize;
}
@@ -1411,7 +1465,7 @@ ZSTDLIB_API size_t ZSTD_insertBlock(ZSTD_DCtx* dctx, const void* blockStart, siz
}
-size_t ZSTD_generateNxBytes(void* dst, size_t dstCapacity, BYTE byte, size_t length)
+static size_t ZSTD_generateNxBytes(void* dst, size_t dstCapacity, BYTE byte, size_t length)
{
if (length > dstCapacity) return ERROR(dstSize_tooSmall);
memset(dst, byte, length);
@@ -1431,7 +1485,7 @@ size_t ZSTD_findFrameCompressedSize(const void *src, size_t srcSize)
#endif
if ( (srcSize >= ZSTD_skippableHeaderSize)
&& (MEM_readLE32(src) & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START ) {
- return ZSTD_skippableHeaderSize + MEM_readLE32((const BYTE*)src + 4);
+ return ZSTD_skippableHeaderSize + MEM_readLE32((const BYTE*)src + ZSTD_frameIdSize);
} else {
const BYTE* ip = (const BYTE*)src;
const BYTE* const ipstart = ip;
@@ -1511,7 +1565,7 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
switch(blockProperties.blockType)
{
case bt_compressed:
- decodedSize = ZSTD_decompressBlock_internal(dctx, op, oend-op, ip, cBlockSize);
+ decodedSize = ZSTD_decompressBlock_internal(dctx, op, oend-op, ip, cBlockSize, /* frame */ 1);
break;
case bt_raw :
decodedSize = ZSTD_copyRawBlock(op, oend-op, ip, cBlockSize);
@@ -1533,6 +1587,10 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
if (blockProperties.lastBlock) break;
}
+ if (dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN) {
+ if ((U64)(op-ostart) != dctx->fParams.frameContentSize) {
+ return ERROR(corruption_detected);
+ } }
if (dctx->fParams.checksumFlag) { /* Frame content checksum verification */
U32 const checkCalc = (U32)XXH64_digest(&dctx->xxhState);
U32 checkRead;
@@ -1590,13 +1648,15 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
#endif
magicNumber = MEM_readLE32(src);
+ DEBUGLOG(4, "reading magic number %08X (expecting %08X)",
+ (U32)magicNumber, (U32)ZSTD_MAGICNUMBER);
if (magicNumber != ZSTD_MAGICNUMBER) {
if ((magicNumber & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) {
size_t skippableSize;
if (srcSize < ZSTD_skippableHeaderSize)
return ERROR(srcSize_wrong);
- skippableSize = MEM_readLE32((const BYTE *)src + 4) +
- ZSTD_skippableHeaderSize;
+ skippableSize = MEM_readLE32((const BYTE*)src + ZSTD_frameIdSize)
+ + ZSTD_skippableHeaderSize;
if (srcSize < skippableSize) return ERROR(srcSize_wrong);
src = (const BYTE *)src + skippableSize;
@@ -1699,33 +1759,31 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
{
DEBUGLOG(5, "ZSTD_decompressContinue");
/* Sanity check */
- if (srcSize != dctx->expected) return ERROR(srcSize_wrong); /* unauthorized */
+ if (srcSize != dctx->expected) return ERROR(srcSize_wrong); /* not allowed */
if (dstCapacity) ZSTD_checkContinuity(dctx, dst);
switch (dctx->stage)
{
case ZSTDds_getFrameHeaderSize :
- if (srcSize != ZSTD_frameHeaderSize_prefix) return ERROR(srcSize_wrong); /* unauthorized */
assert(src != NULL);
- if ((MEM_readLE32(src) & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */
- memcpy(dctx->headerBuffer, src, ZSTD_frameHeaderSize_prefix);
- dctx->expected = ZSTD_skippableHeaderSize - ZSTD_frameHeaderSize_prefix; /* magic number + skippable frame length */
- dctx->stage = ZSTDds_decodeSkippableHeader;
- return 0;
- }
- dctx->headerSize = ZSTD_frameHeaderSize(src, ZSTD_frameHeaderSize_prefix);
+ if (dctx->format == ZSTD_f_zstd1) { /* allows header */
+ assert(srcSize >= ZSTD_frameIdSize); /* to read skippable magic number */
+ if ((MEM_readLE32(src) & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */
+ memcpy(dctx->headerBuffer, src, srcSize);
+ dctx->expected = ZSTD_skippableHeaderSize - srcSize; /* remaining to load to get full skippable frame header */
+ dctx->stage = ZSTDds_decodeSkippableHeader;
+ return 0;
+ } }
+ dctx->headerSize = ZSTD_frameHeaderSize_internal(src, srcSize, dctx->format);
if (ZSTD_isError(dctx->headerSize)) return dctx->headerSize;
- memcpy(dctx->headerBuffer, src, ZSTD_frameHeaderSize_prefix);
- if (dctx->headerSize > ZSTD_frameHeaderSize_prefix) {
- dctx->expected = dctx->headerSize - ZSTD_frameHeaderSize_prefix;
- dctx->stage = ZSTDds_decodeFrameHeader;
- return 0;
- }
- dctx->expected = 0; /* not necessary to copy more */
- /* fall-through */
+ memcpy(dctx->headerBuffer, src, srcSize);
+ dctx->expected = dctx->headerSize - srcSize;
+ dctx->stage = ZSTDds_decodeFrameHeader;
+ return 0;
+
case ZSTDds_decodeFrameHeader:
assert(src != NULL);
- memcpy(dctx->headerBuffer + ZSTD_frameHeaderSize_prefix, src, dctx->expected);
+ memcpy(dctx->headerBuffer + (dctx->headerSize - srcSize), src, srcSize);
CHECK_F(ZSTD_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize));
dctx->expected = ZSTD_blockHeaderSize;
dctx->stage = ZSTDds_decodeBlockHeader;
@@ -1757,6 +1815,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
}
return 0;
}
+
case ZSTDds_decompressLastBlock:
case ZSTDds_decompressBlock:
DEBUGLOG(5, "case ZSTDds_decompressBlock");
@@ -1765,7 +1824,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
{
case bt_compressed:
DEBUGLOG(5, "case bt_compressed");
- rSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize);
+ rSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, /* frame */ 1);
break;
case bt_raw :
rSize = ZSTD_copyRawBlock(dst, dstCapacity, src, srcSize);
@@ -1778,9 +1837,16 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
return ERROR(corruption_detected);
}
if (ZSTD_isError(rSize)) return rSize;
+ DEBUGLOG(5, "decoded size from block : %u", (U32)rSize);
+ dctx->decodedSize += rSize;
if (dctx->fParams.checksumFlag) XXH64_update(&dctx->xxhState, dst, rSize);
if (dctx->stage == ZSTDds_decompressLastBlock) { /* end of frame */
+ DEBUGLOG(4, "decoded size from frame : %u", (U32)dctx->decodedSize);
+ if (dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN) {
+ if (dctx->decodedSize != dctx->fParams.frameContentSize) {
+ return ERROR(corruption_detected);
+ } }
if (dctx->fParams.checksumFlag) { /* another round for frame checksum */
dctx->expected = 4;
dctx->stage = ZSTDds_checkChecksum;
@@ -1795,26 +1861,31 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
}
return rSize;
}
+
case ZSTDds_checkChecksum:
+ assert(srcSize == 4); /* guaranteed by dctx->expected */
{ U32 const h32 = (U32)XXH64_digest(&dctx->xxhState);
- U32 const check32 = MEM_readLE32(src); /* srcSize == 4, guaranteed by dctx->expected */
+ U32 const check32 = MEM_readLE32(src);
+ DEBUGLOG(4, "checksum : calculated %08X :: %08X read", h32, check32);
if (check32 != h32) return ERROR(checksum_wrong);
dctx->expected = 0;
dctx->stage = ZSTDds_getFrameHeaderSize;
return 0;
}
+
case ZSTDds_decodeSkippableHeader:
- { assert(src != NULL);
- memcpy(dctx->headerBuffer + ZSTD_frameHeaderSize_prefix, src, dctx->expected);
- dctx->expected = MEM_readLE32(dctx->headerBuffer + 4);
- dctx->stage = ZSTDds_skipFrame;
- return 0;
- }
+ assert(src != NULL);
+ assert(srcSize <= ZSTD_skippableHeaderSize);
+ memcpy(dctx->headerBuffer + (ZSTD_skippableHeaderSize - srcSize), src, srcSize); /* complete skippable header */
+ dctx->expected = MEM_readLE32(dctx->headerBuffer + ZSTD_frameIdSize); /* note : dctx->expected can grow seriously large, beyond local buffer size */
+ dctx->stage = ZSTDds_skipFrame;
+ return 0;
+
case ZSTDds_skipFrame:
- { dctx->expected = 0;
- dctx->stage = ZSTDds_getFrameHeaderSize;
- return 0;
- }
+ dctx->expected = 0;
+ dctx->stage = ZSTDds_getFrameHeaderSize;
+ return 0;
+
default:
return ERROR(GENERIC); /* impossible */
}
@@ -1895,7 +1966,7 @@ static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict
if (magic != ZSTD_MAGIC_DICTIONARY) {
return ZSTD_refDictContent(dctx, dict, dictSize); /* pure content mode */
} }
- dctx->dictID = MEM_readLE32((const char*)dict + 4);
+ dctx->dictID = MEM_readLE32((const char*)dict + ZSTD_frameIdSize);
/* load entropy tables */
{ size_t const eSize = ZSTD_loadEntropy(&dctx->entropy, dict, dictSize);
@@ -1909,6 +1980,29 @@ static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict
return ZSTD_refDictContent(dctx, dict, dictSize);
}
+/* Note : this function cannot fail */
+size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
+{
+ assert(dctx != NULL);
+ dctx->expected = ZSTD_startingInputLength(dctx->format); /* dctx->format must be properly set */
+ dctx->stage = ZSTDds_getFrameHeaderSize;
+ dctx->decodedSize = 0;
+ dctx->previousDstEnd = NULL;
+ dctx->base = NULL;
+ dctx->vBase = NULL;
+ dctx->dictEnd = NULL;
+ dctx->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */
+ dctx->litEntropy = dctx->fseEntropy = 0;
+ dctx->dictID = 0;
+ ZSTD_STATIC_ASSERT(sizeof(dctx->entropy.rep) == sizeof(repStartValue));
+ memcpy(dctx->entropy.rep, repStartValue, sizeof(repStartValue)); /* initial repcodes */
+ dctx->LLTptr = dctx->entropy.LLTable;
+ dctx->MLTptr = dctx->entropy.MLTable;
+ dctx->OFTptr = dctx->entropy.OFTable;
+ dctx->HUFptr = dctx->entropy.hufTable;
+ return 0;
+}
+
size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
{
CHECK_F( ZSTD_decompressBegin(dctx) );
@@ -1975,7 +2069,7 @@ static size_t ZSTD_loadEntropy_inDDict(ZSTD_DDict* ddict)
{ U32 const magic = MEM_readLE32(ddict->dictContent);
if (magic != ZSTD_MAGIC_DICTIONARY) return 0; /* pure content mode */
}
- ddict->dictID = MEM_readLE32((const char*)ddict->dictContent + 4);
+ ddict->dictID = MEM_readLE32((const char*)ddict->dictContent + ZSTD_frameIdSize);
/* load entropy tables */
CHECK_E( ZSTD_loadEntropy(&ddict->entropy, ddict->dictContent, ddict->dictSize), dictionary_corrupted );
@@ -1984,9 +2078,9 @@ static size_t ZSTD_loadEntropy_inDDict(ZSTD_DDict* ddict)
}
-static size_t ZSTD_initDDict_internal(ZSTD_DDict* ddict, const void* dict, size_t dictSize, unsigned byReference)
+static size_t ZSTD_initDDict_internal(ZSTD_DDict* ddict, const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod)
{
- if ((byReference) || (!dict) || (!dictSize)) {
+ if ((dictLoadMethod == ZSTD_dlm_byRef) || (!dict) || (!dictSize)) {
ddict->dictBuffer = NULL;
ddict->dictContent = dict;
} else {
@@ -2005,7 +2099,7 @@ static size_t ZSTD_initDDict_internal(ZSTD_DDict* ddict, const void* dict, size_
return 0;
}
-ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictSize, unsigned byReference, ZSTD_customMem customMem)
+ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_customMem customMem)
{
if (!customMem.customAlloc ^ !customMem.customFree) return NULL;
@@ -2013,7 +2107,7 @@ ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictSize, unsigne
if (!ddict) return NULL;
ddict->cMem = customMem;
- if (ZSTD_isError( ZSTD_initDDict_internal(ddict, dict, dictSize, byReference) )) {
+ if (ZSTD_isError( ZSTD_initDDict_internal(ddict, dict, dictSize, dictLoadMethod) )) {
ZSTD_freeDDict(ddict);
return NULL;
}
@@ -2029,7 +2123,7 @@ ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictSize, unsigne
ZSTD_DDict* ZSTD_createDDict(const void* dict, size_t dictSize)
{
ZSTD_customMem const allocator = { NULL, NULL, NULL };
- return ZSTD_createDDict_advanced(dict, dictSize, 0, allocator);
+ return ZSTD_createDDict_advanced(dict, dictSize, ZSTD_dlm_byCopy, allocator);
}
/*! ZSTD_createDDict_byReference() :
@@ -2039,25 +2133,26 @@ ZSTD_DDict* ZSTD_createDDict(const void* dict, size_t dictSize)
ZSTD_DDict* ZSTD_createDDict_byReference(const void* dictBuffer, size_t dictSize)
{
ZSTD_customMem const allocator = { NULL, NULL, NULL };
- return ZSTD_createDDict_advanced(dictBuffer, dictSize, 1, allocator);
+ return ZSTD_createDDict_advanced(dictBuffer, dictSize, ZSTD_dlm_byRef, allocator);
}
ZSTD_DDict* ZSTD_initStaticDDict(void* workspace, size_t workspaceSize,
const void* dict, size_t dictSize,
- unsigned byReference)
+ ZSTD_dictLoadMethod_e dictLoadMethod)
{
- size_t const neededSpace = sizeof(ZSTD_DDict) + (byReference ? 0 : dictSize);
+ size_t const neededSpace =
+ sizeof(ZSTD_DDict) + (dictLoadMethod == ZSTD_dlm_byRef ? 0 : dictSize);
ZSTD_DDict* const ddict = (ZSTD_DDict*)workspace;
assert(workspace != NULL);
assert(dict != NULL);
if ((size_t)workspace & 7) return NULL; /* 8-aligned */
if (workspaceSize < neededSpace) return NULL;
- if (!byReference) {
+ if (dictLoadMethod == ZSTD_dlm_byCopy) {
memcpy(ddict+1, dict, dictSize); /* local copy */
dict = ddict+1;
}
- if (ZSTD_isError( ZSTD_initDDict_internal(ddict, dict, dictSize, 1 /* byRef */) ))
+ if (ZSTD_isError( ZSTD_initDDict_internal(ddict, dict, dictSize, ZSTD_dlm_byRef) ))
return NULL;
return ddict;
}
@@ -2075,10 +2170,10 @@ size_t ZSTD_freeDDict(ZSTD_DDict* ddict)
/*! ZSTD_estimateDDictSize() :
* Estimate amount of memory that will be needed to create a dictionary for decompression.
- * Note : dictionary created "byReference" are smaller */
-size_t ZSTD_estimateDDictSize(size_t dictSize, unsigned byReference)
+ * Note : dictionary created by reference using ZSTD_dlm_byRef are smaller */
+size_t ZSTD_estimateDDictSize(size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod)
{
- return sizeof(ZSTD_DDict) + (byReference ? 0 : dictSize);
+ return sizeof(ZSTD_DDict) + (dictLoadMethod == ZSTD_dlm_byRef ? 0 : dictSize);
}
size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict)
@@ -2095,7 +2190,7 @@ unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize)
{
if (dictSize < 8) return 0;
if (MEM_readLE32(dict) != ZSTD_MAGIC_DICTIONARY) return 0;
- return MEM_readLE32((const char*)dict + 4);
+ return MEM_readLE32((const char*)dict + ZSTD_frameIdSize);
}
/*! ZSTD_getDictID_fromDDict() :
@@ -2123,7 +2218,7 @@ unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict* ddict)
* ZSTD_getFrameHeader(), which will provide a more precise error code. */
unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize)
{
- ZSTD_frameHeader zfp = { 0, 0, ZSTD_frame, 0, 0, 0 };
+ ZSTD_frameHeader zfp = { 0, 0, 0, ZSTD_frame, 0, 0, 0 };
size_t const hError = ZSTD_getFrameHeader(&zfp, src, srcSize);
if (ZSTD_isError(hError)) return 0;
return zfp.dictID;
@@ -2190,13 +2285,15 @@ size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t di
return ZSTD_frameHeaderSize_prefix;
}
+/* note : this variant can't fail */
size_t ZSTD_initDStream(ZSTD_DStream* zds)
{
return ZSTD_initDStream_usingDict(zds, NULL, 0);
}
/* ZSTD_initDStream_usingDDict() :
- * ddict will just be referenced, and must outlive decompression session */
+ * ddict will just be referenced, and must outlive decompression session
+ * this function cannot fail */
size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* zds, const ZSTD_DDict* ddict)
{
size_t const initResult = ZSTD_initDStream(zds);
@@ -2216,31 +2313,66 @@ size_t ZSTD_resetDStream(ZSTD_DStream* zds)
size_t ZSTD_setDStreamParameter(ZSTD_DStream* zds,
ZSTD_DStreamParameter_e paramType, unsigned paramValue)
{
+ ZSTD_STATIC_ASSERT((unsigned)zdss_loadHeader >= (unsigned)zdss_init);
+ if ((unsigned)zds->streamStage > (unsigned)zdss_loadHeader)
+ return ERROR(stage_wrong);
switch(paramType)
{
default : return ERROR(parameter_unsupported);
- case DStream_p_maxWindowSize : zds->maxWindowSize = paramValue ? paramValue : (U32)(-1); break;
+ case DStream_p_maxWindowSize :
+ DEBUGLOG(4, "setting maxWindowSize = %u KB", paramValue >> 10);
+ zds->maxWindowSize = paramValue ? paramValue : (U32)(-1);
+ break;
}
return 0;
}
+size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize)
+{
+ ZSTD_STATIC_ASSERT((unsigned)zdss_loadHeader >= (unsigned)zdss_init);
+ if ((unsigned)dctx->streamStage > (unsigned)zdss_loadHeader)
+ return ERROR(stage_wrong);
+ dctx->maxWindowSize = maxWindowSize;
+ return 0;
+}
+
+size_t ZSTD_DCtx_setFormat(ZSTD_DCtx* dctx, ZSTD_format_e format)
+{
+ DEBUGLOG(4, "ZSTD_DCtx_setFormat : %u", (unsigned)format);
+ ZSTD_STATIC_ASSERT((unsigned)zdss_loadHeader >= (unsigned)zdss_init);
+ if ((unsigned)dctx->streamStage > (unsigned)zdss_loadHeader)
+ return ERROR(stage_wrong);
+ dctx->format = format;
+ return 0;
+}
+
size_t ZSTD_sizeof_DStream(const ZSTD_DStream* zds)
{
return ZSTD_sizeof_DCtx(zds);
}
+size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long long frameContentSize)
+{
+ size_t const blockSize = (size_t) MIN(windowSize, ZSTD_BLOCKSIZE_MAX);
+ unsigned long long const neededRBSize = windowSize + blockSize + (WILDCOPY_OVERLENGTH * 2);
+ unsigned long long const neededSize = MIN(frameContentSize, neededRBSize);
+ size_t const minRBSize = (size_t) neededSize;
+ if ((unsigned long long)minRBSize != neededSize) return ERROR(frameParameter_windowTooLarge);
+ return minRBSize;
+}
+
size_t ZSTD_estimateDStreamSize(size_t windowSize)
{
size_t const blockSize = MIN(windowSize, ZSTD_BLOCKSIZE_MAX);
size_t const inBuffSize = blockSize; /* no block can be larger */
- size_t const outBuffSize = windowSize + blockSize + (WILDCOPY_OVERLENGTH * 2);
+ size_t const outBuffSize = ZSTD_decodingBufferSize_min(windowSize, ZSTD_CONTENTSIZE_UNKNOWN);
return ZSTD_estimateDCtxSize() + inBuffSize + outBuffSize;
}
-ZSTDLIB_API size_t ZSTD_estimateDStreamSize_fromFrame(const void* src, size_t srcSize)
+size_t ZSTD_estimateDStreamSize_fromFrame(const void* src, size_t srcSize)
{
- U32 const windowSizeMax = 1U << ZSTD_WINDOWLOG_MAX;
+ U32 const windowSizeMax = 1U << ZSTD_WINDOWLOG_MAX; /* note : should be user-selectable */
ZSTD_frameHeader zfh;
size_t const err = ZSTD_getFrameHeader(&zfh, src, srcSize);
if (ZSTD_isError(err)) return err;
@@ -2272,7 +2404,18 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
U32 someMoreWork = 1;
DEBUGLOG(5, "ZSTD_decompressStream");
+ if (input->pos > input->size) { /* forbidden */
+ DEBUGLOG(5, "in: pos: %u vs size: %u",
+ (U32)input->pos, (U32)input->size);
+ return ERROR(srcSize_wrong);
+ }
+ if (output->pos > output->size) { /* forbidden */
+ DEBUGLOG(5, "out: pos: %u vs size: %u",
+ (U32)output->pos, (U32)output->size);
+ return ERROR(dstSize_tooSmall);
+ }
DEBUGLOG(5, "input size : %u", (U32)(input->size - input->pos));
+
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
if (zds->legacyVersion) {
/* legacy support is incompatible with static dctx */
@@ -2289,7 +2432,9 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
/* fall-through */
case zdss_loadHeader :
- { size_t const hSize = ZSTD_getFrameHeader(&zds->fParams, zds->headerBuffer, zds->lhSize);
+ DEBUGLOG(5, "stage zdss_loadHeader (srcSize : %u)", (U32)(iend - ip));
+ { size_t const hSize = ZSTD_getFrameHeader_internal(&zds->fParams, zds->headerBuffer, zds->lhSize, zds->format);
+ DEBUGLOG(5, "header size : %u", (U32)hSize);
if (ZSTD_isError(hSize)) {
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
U32 const legacyVersion = ZSTD_isLegacy(istart, iend-istart);
@@ -2342,7 +2487,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
CHECK_F(ZSTD_decompressBegin_usingDDict(zds, zds->ddict));
if ((MEM_readLE32(zds->headerBuffer) & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */
- zds->expected = MEM_readLE32(zds->headerBuffer + 4);
+ zds->expected = MEM_readLE32(zds->headerBuffer + ZSTD_frameIdSize);
zds->stage = ZSTDds_skipFrame;
} else {
CHECK_F(ZSTD_decodeFrameHeader(zds, zds->headerBuffer, zds->lhSize));
@@ -2351,20 +2496,20 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
}
/* control buffer memory usage */
- DEBUGLOG(4, "Control max buffer memory usage");
+ DEBUGLOG(4, "Control max buffer memory usage (max %u KB)",
+ (U32)(zds->maxWindowSize >> 10));
zds->fParams.windowSize = MAX(zds->fParams.windowSize, 1U << ZSTD_WINDOWLOG_ABSOLUTEMIN);
if (zds->fParams.windowSize > zds->maxWindowSize) return ERROR(frameParameter_windowTooLarge);
/* Adapt buffer sizes to frame header instructions */
- { size_t const blockSize = (size_t)(MIN(zds->fParams.windowSize, ZSTD_BLOCKSIZE_MAX));
- size_t const neededOutSize = (size_t)(zds->fParams.windowSize + blockSize + WILDCOPY_OVERLENGTH * 2);
- zds->blockSize = blockSize;
- if ((zds->inBuffSize < blockSize) || (zds->outBuffSize < neededOutSize)) {
- size_t const bufferSize = blockSize + neededOutSize;
+ { size_t const neededInBuffSize = MAX(zds->fParams.blockSizeMax, 4 /* frame checksum */);
+ size_t const neededOutBuffSize = ZSTD_decodingBufferSize_min(zds->fParams.windowSize, zds->fParams.frameContentSize);
+ if ((zds->inBuffSize < neededInBuffSize) || (zds->outBuffSize < neededOutBuffSize)) {
+ size_t const bufferSize = neededInBuffSize + neededOutBuffSize;
DEBUGLOG(4, "inBuff : from %u to %u",
- (U32)zds->inBuffSize, (U32)blockSize);
+ (U32)zds->inBuffSize, (U32)neededInBuffSize);
DEBUGLOG(4, "outBuff : from %u to %u",
- (U32)zds->outBuffSize, (U32)neededOutSize);
+ (U32)zds->outBuffSize, (U32)neededOutBuffSize);
if (zds->staticSize) { /* static DCtx */
DEBUGLOG(4, "staticSize : %u", (U32)zds->staticSize);
assert(zds->staticSize >= sizeof(ZSTD_DCtx)); /* controlled at init */
@@ -2377,9 +2522,9 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
zds->inBuff = (char*)ZSTD_malloc(bufferSize, zds->customMem);
if (zds->inBuff == NULL) return ERROR(memory_allocation);
}
- zds->inBuffSize = blockSize;
+ zds->inBuffSize = neededInBuffSize;
zds->outBuff = zds->inBuff + zds->inBuffSize;
- zds->outBuffSize = neededOutSize;
+ zds->outBuffSize = neededOutBuffSize;
} }
zds->streamStage = zdss_read;
/* fall-through */
@@ -2437,8 +2582,13 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
zds->outStart += flushedSize;
if (flushedSize == toFlushSize) { /* flush completed */
zds->streamStage = zdss_read;
- if (zds->outStart + zds->blockSize > zds->outBuffSize)
+ if ( (zds->outBuffSize < zds->fParams.frameContentSize)
+ && (zds->outStart + zds->fParams.blockSizeMax > zds->outBuffSize) ) {
+ DEBUGLOG(5, "restart filling outBuff from beginning (left:%i, needed:%u)",
+ (int)(zds->outBuffSize - zds->outStart),
+ (U32)zds->fParams.blockSizeMax);
zds->outStart = zds->outEnd = 0;
+ }
break;
} }
/* cannot complete flush */
@@ -2476,3 +2626,30 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
return nextSrcSizeHint;
}
}
+
+
+size_t ZSTD_decompress_generic(ZSTD_DCtx* dctx, ZSTD_outBuffer* output, ZSTD_inBuffer* input)
+{
+ return ZSTD_decompressStream(dctx, output, input);
+}
+
+size_t ZSTD_decompress_generic_simpleArgs (
+ ZSTD_DCtx* dctx,
+ void* dst, size_t dstCapacity, size_t* dstPos,
+ const void* src, size_t srcSize, size_t* srcPos)
+{
+ ZSTD_outBuffer output = { dst, dstCapacity, *dstPos };
+ ZSTD_inBuffer input = { src, srcSize, *srcPos };
+ /* ZSTD_compress_generic() will check validity of dstPos and srcPos */
+ size_t const cErr = ZSTD_decompress_generic(dctx, &output, &input);
+ *dstPos = output.pos;
+ *srcPos = input.pos;
+ return cErr;
+}
+
+void ZSTD_DCtx_reset(ZSTD_DCtx* dctx)
+{
+ (void)ZSTD_initDStream(dctx);
+ dctx->format = ZSTD_f_zstd1;
+ dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
+}
diff --git a/thirdparty/zstd/zstd.h b/thirdparty/zstd/zstd.h
index 13b4563fd6..2194a3b23d 100644
--- a/thirdparty/zstd/zstd.h
+++ b/thirdparty/zstd/zstd.h
@@ -5,6 +5,7 @@
* This source code is licensed under both the BSD-style license (found in the
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
* in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
*/
#if defined (__cplusplus)
extern "C" {
@@ -58,7 +59,7 @@ extern "C" {
/*------ Version ------*/
#define ZSTD_VERSION_MAJOR 1
#define ZSTD_VERSION_MINOR 3
-#define ZSTD_VERSION_RELEASE 1
+#define ZSTD_VERSION_RELEASE 2
#define ZSTD_VERSION_NUMBER (ZSTD_VERSION_MAJOR *100*100 + ZSTD_VERSION_MINOR *100 + ZSTD_VERSION_RELEASE)
ZSTDLIB_API unsigned ZSTD_versionNumber(void); /**< useful to check dll version */
@@ -130,10 +131,11 @@ ZSTDLIB_API unsigned long long ZSTD_getDecompressedSize(const void* src, size_t
/*====== Helper functions ======*/
-ZSTDLIB_API int ZSTD_maxCLevel(void); /*!< maximum compression level available */
+#define ZSTD_COMPRESSBOUND(srcSize) ((srcSize) + ((srcSize)>>8) + (((srcSize) < 128 KB) ? ((128 KB - (srcSize)) >> 11) /* margin, from 64 to 0 */ : 0)) /* this formula ensures that bound(A) + bound(B) <= bound(A+B) as long as A and B >= 128 KB */
ZSTDLIB_API size_t ZSTD_compressBound(size_t srcSize); /*!< maximum compressed size in worst case scenario */
ZSTDLIB_API unsigned ZSTD_isError(size_t code); /*!< tells if a `size_t` function result is an error code */
ZSTDLIB_API const char* ZSTD_getErrorName(size_t code); /*!< provides readable string from an error code */
+ZSTDLIB_API int ZSTD_maxCLevel(void); /*!< maximum compression level available */
/***************************************
@@ -375,27 +377,31 @@ ZSTDLIB_API size_t ZSTD_DStreamOutSize(void); /*!< recommended size for output
#define ZSTD_MAGIC_SKIPPABLE_START 0x184D2A50U
#define ZSTD_MAGIC_DICTIONARY 0xEC30A437 /* v0.7+ */
-#define ZSTD_WINDOWLOG_MAX_32 27
-#define ZSTD_WINDOWLOG_MAX_64 27
+#define ZSTD_WINDOWLOG_MAX_32 30
+#define ZSTD_WINDOWLOG_MAX_64 31
#define ZSTD_WINDOWLOG_MAX ((unsigned)(sizeof(size_t) == 4 ? ZSTD_WINDOWLOG_MAX_32 : ZSTD_WINDOWLOG_MAX_64))
-#define ZSTD_WINDOWLOG_MIN 10
-#define ZSTD_HASHLOG_MAX ZSTD_WINDOWLOG_MAX
-#define ZSTD_HASHLOG_MIN 6
-#define ZSTD_CHAINLOG_MAX (ZSTD_WINDOWLOG_MAX+1)
-#define ZSTD_CHAINLOG_MIN ZSTD_HASHLOG_MIN
-#define ZSTD_HASHLOG3_MAX 17
-#define ZSTD_SEARCHLOG_MAX (ZSTD_WINDOWLOG_MAX-1)
-#define ZSTD_SEARCHLOG_MIN 1
-#define ZSTD_SEARCHLENGTH_MAX 7 /* only for ZSTD_fast, other strategies are limited to 6 */
-#define ZSTD_SEARCHLENGTH_MIN 3 /* only for ZSTD_btopt, other strategies are limited to 4 */
-#define ZSTD_TARGETLENGTH_MIN 4
-#define ZSTD_TARGETLENGTH_MAX 999
-
-#define ZSTD_FRAMEHEADERSIZE_MAX 18 /* for static allocation */
-#define ZSTD_FRAMEHEADERSIZE_MIN 6
-static const size_t ZSTD_frameHeaderSize_prefix = 5; /* minimum input size to know frame header size */
-static const size_t ZSTD_frameHeaderSize_max = ZSTD_FRAMEHEADERSIZE_MAX;
+#define ZSTD_WINDOWLOG_MIN 10
+#define ZSTD_HASHLOG_MAX MIN(ZSTD_WINDOWLOG_MAX, 30)
+#define ZSTD_HASHLOG_MIN 6
+#define ZSTD_CHAINLOG_MAX MIN(ZSTD_WINDOWLOG_MAX+1, 30)
+#define ZSTD_CHAINLOG_MIN ZSTD_HASHLOG_MIN
+#define ZSTD_HASHLOG3_MAX 17
+#define ZSTD_SEARCHLOG_MAX (ZSTD_WINDOWLOG_MAX-1)
+#define ZSTD_SEARCHLOG_MIN 1
+#define ZSTD_SEARCHLENGTH_MAX 7 /* only for ZSTD_fast, other strategies are limited to 6 */
+#define ZSTD_SEARCHLENGTH_MIN 3 /* only for ZSTD_btopt, other strategies are limited to 4 */
+#define ZSTD_TARGETLENGTH_MIN 4 /* only useful for btopt */
+#define ZSTD_TARGETLENGTH_MAX 999 /* only useful for btopt */
+#define ZSTD_LDM_MINMATCH_MIN 4
+#define ZSTD_LDM_MINMATCH_MAX 4096
+#define ZSTD_LDM_BUCKETSIZELOG_MAX 8
+
+#define ZSTD_FRAMEHEADERSIZE_PREFIX 5 /* minimum input size to know frame header size */
+#define ZSTD_FRAMEHEADERSIZE_MIN 6
+#define ZSTD_FRAMEHEADERSIZE_MAX 18 /* for static allocation */
+static const size_t ZSTD_frameHeaderSize_prefix = ZSTD_FRAMEHEADERSIZE_PREFIX;
static const size_t ZSTD_frameHeaderSize_min = ZSTD_FRAMEHEADERSIZE_MIN;
+static const size_t ZSTD_frameHeaderSize_max = ZSTD_FRAMEHEADERSIZE_MAX;
static const size_t ZSTD_skippableHeaderSize = 8; /* magic number + skippable frame length */
@@ -424,6 +430,8 @@ typedef struct {
ZSTD_frameParameters fParams;
} ZSTD_parameters;
+typedef struct ZSTD_CCtx_params_s ZSTD_CCtx_params;
+
/*= Custom memory allocation functions */
typedef void* (*ZSTD_allocFunction) (void* opaque, size_t size);
typedef void (*ZSTD_freeFunction) (void* opaque, void* address);
@@ -480,7 +488,7 @@ ZSTDLIB_API size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize);
/*! ZSTD_sizeof_*() :
* These functions give the current memory usage of selected object.
- * Object memory usage can evolve if it's re-used multiple times. */
+ * Object memory usage can evolve when re-used multiple times. */
ZSTDLIB_API size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx);
ZSTDLIB_API size_t ZSTD_sizeof_DCtx(const ZSTD_DCtx* dctx);
ZSTDLIB_API size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs);
@@ -493,18 +501,21 @@ ZSTDLIB_API size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
* of a future {D,C}Ctx, before its creation.
* ZSTD_estimateCCtxSize() will provide a budget large enough for any compression level up to selected one.
* It will also consider src size to be arbitrarily "large", which is worst case.
- * If srcSize is known to always be small, ZSTD_estimateCCtxSize_advanced() can provide a tighter estimation.
- * ZSTD_estimateCCtxSize_advanced() can be used in tandem with ZSTD_getCParams() to create cParams from compressionLevel.
+ * If srcSize is known to always be small, ZSTD_estimateCCtxSize_usingCParams() can provide a tighter estimation.
+ * ZSTD_estimateCCtxSize_usingCParams() can be used in tandem with ZSTD_getCParams() to create cParams from compressionLevel.
+ * ZSTD_estimateCCtxSize_usingCCtxParams() can be used in tandem with ZSTD_CCtxParam_setParameter(). Only single-threaded compression is supported. This function will return an error code if ZSTD_p_nbThreads is > 1.
* Note : CCtx estimation is only correct for single-threaded compression */
ZSTDLIB_API size_t ZSTD_estimateCCtxSize(int compressionLevel);
-ZSTDLIB_API size_t ZSTD_estimateCCtxSize_advanced(ZSTD_compressionParameters cParams);
+ZSTDLIB_API size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams);
+ZSTDLIB_API size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params);
ZSTDLIB_API size_t ZSTD_estimateDCtxSize(void);
-/*! ZSTD_estimate?StreamSize() :
+/*! ZSTD_estimateCStreamSize() :
* ZSTD_estimateCStreamSize() will provide a budget large enough for any compression level up to selected one.
* It will also consider src size to be arbitrarily "large", which is worst case.
- * If srcSize is known to always be small, ZSTD_estimateCStreamSize_advanced() can provide a tighter estimation.
- * ZSTD_estimateCStreamSize_advanced() can be used in tandem with ZSTD_getCParams() to create cParams from compressionLevel.
+ * If srcSize is known to always be small, ZSTD_estimateCStreamSize_usingCParams() can provide a tighter estimation.
+ * ZSTD_estimateCStreamSize_usingCParams() can be used in tandem with ZSTD_getCParams() to create cParams from compressionLevel.
+ * ZSTD_estimateCStreamSize_usingCCtxParams() can be used in tandem with ZSTD_CCtxParam_setParameter(). Only single-threaded compression is supported. This function will return an error code if ZSTD_p_nbThreads is set to a value > 1.
* Note : CStream estimation is only correct for single-threaded compression.
* ZSTD_DStream memory budget depends on window Size.
* This information can be passed manually, using ZSTD_estimateDStreamSize,
@@ -513,17 +524,24 @@ ZSTDLIB_API size_t ZSTD_estimateDCtxSize(void);
* an internal ?Dict will be created, which additional size is not estimated here.
* In this case, get total size by adding ZSTD_estimate?DictSize */
ZSTDLIB_API size_t ZSTD_estimateCStreamSize(int compressionLevel);
-ZSTDLIB_API size_t ZSTD_estimateCStreamSize_advanced(ZSTD_compressionParameters cParams);
+ZSTDLIB_API size_t ZSTD_estimateCStreamSize_usingCParams(ZSTD_compressionParameters cParams);
+ZSTDLIB_API size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params);
ZSTDLIB_API size_t ZSTD_estimateDStreamSize(size_t windowSize);
ZSTDLIB_API size_t ZSTD_estimateDStreamSize_fromFrame(const void* src, size_t srcSize);
+typedef enum {
+ ZSTD_dlm_byCopy = 0, /**< Copy dictionary content internally */
+ ZSTD_dlm_byRef, /**< Reference dictionary content -- the dictionary buffer must outlive its users. */
+} ZSTD_dictLoadMethod_e;
+
/*! ZSTD_estimate?DictSize() :
* ZSTD_estimateCDictSize() will bet that src size is relatively "small", and content is copied, like ZSTD_createCDict().
- * ZSTD_estimateCStreamSize_advanced() makes it possible to control precisely compression parameters, like ZSTD_createCDict_advanced().
- * Note : dictionary created "byReference" are smaller */
+ * ZSTD_estimateCStreamSize_advanced_usingCParams() makes it possible to control precisely compression parameters, like ZSTD_createCDict_advanced().
+ * Note : dictionary created by reference using ZSTD_dlm_byRef are smaller
+ */
ZSTDLIB_API size_t ZSTD_estimateCDictSize(size_t dictSize, int compressionLevel);
-ZSTDLIB_API size_t ZSTD_estimateCDictSize_advanced(size_t dictSize, ZSTD_compressionParameters cParams, unsigned byReference);
-ZSTDLIB_API size_t ZSTD_estimateDDictSize(size_t dictSize, unsigned byReference);
+ZSTDLIB_API size_t ZSTD_estimateCDictSize_advanced(size_t dictSize, ZSTD_compressionParameters cParams, ZSTD_dictLoadMethod_e dictLoadMethod);
+ZSTDLIB_API size_t ZSTD_estimateDDictSize(size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod);
/***************************************
@@ -551,24 +569,12 @@ ZSTDLIB_API ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem);
ZSTDLIB_API ZSTD_CCtx* ZSTD_initStaticCCtx(void* workspace, size_t workspaceSize);
-/* !!! To be deprecated !!! */
-typedef enum {
- ZSTD_p_forceWindow, /* Force back-references to remain < windowSize, even when referencing Dictionary content (default:0) */
- ZSTD_p_forceRawDict /* Force loading dictionary in "content-only" mode (no header analysis) */
-} ZSTD_CCtxParameter;
-/*! ZSTD_setCCtxParameter() :
- * Set advanced parameters, selected through enum ZSTD_CCtxParameter
- * @result : 0, or an error code (which can be tested with ZSTD_isError()) */
-ZSTDLIB_API size_t ZSTD_setCCtxParameter(ZSTD_CCtx* cctx, ZSTD_CCtxParameter param, unsigned value);
-
-
/*! ZSTD_createCDict_byReference() :
* Create a digested dictionary for compression
* Dictionary content is simply referenced, and therefore stays in dictBuffer.
* It is important that dictBuffer outlives CDict, it must remain read accessible throughout the lifetime of CDict */
ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_byReference(const void* dictBuffer, size_t dictSize, int compressionLevel);
-
typedef enum { ZSTD_dm_auto=0, /* dictionary is "full" if it starts with ZSTD_MAGIC_DICTIONARY, otherwise it is "rawContent" */
ZSTD_dm_rawContent, /* ensures dictionary is always loaded as rawContent, even if it starts with ZSTD_MAGIC_DICTIONARY */
ZSTD_dm_fullDict /* refuses to load a dictionary if it does not respect Zstandard's specification */
@@ -576,7 +582,8 @@ typedef enum { ZSTD_dm_auto=0, /* dictionary is "full" if it starts with
/*! ZSTD_createCDict_advanced() :
* Create a ZSTD_CDict using external alloc and free, and customized compression parameters */
ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_advanced(const void* dict, size_t dictSize,
- unsigned byReference, ZSTD_dictMode_e dictMode,
+ ZSTD_dictLoadMethod_e dictLoadMethod,
+ ZSTD_dictMode_e dictMode,
ZSTD_compressionParameters cParams,
ZSTD_customMem customMem);
@@ -596,7 +603,7 @@ ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_advanced(const void* dict, size_t dictS
ZSTDLIB_API ZSTD_CDict* ZSTD_initStaticCDict(
void* workspace, size_t workspaceSize,
const void* dict, size_t dictSize,
- unsigned byReference, ZSTD_dictMode_e dictMode,
+ ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictMode_e dictMode,
ZSTD_compressionParameters cParams);
/*! ZSTD_getCParams() :
@@ -674,7 +681,8 @@ ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict_byReference(const void* dictBuffer, siz
/*! ZSTD_createDDict_advanced() :
* Create a ZSTD_DDict using external alloc and free, optionally by reference */
ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictSize,
- unsigned byReference, ZSTD_customMem customMem);
+ ZSTD_dictLoadMethod_e dictLoadMethod,
+ ZSTD_customMem customMem);
/*! ZSTD_initStaticDDict() :
* Generate a digested dictionary in provided memory area.
@@ -689,7 +697,7 @@ ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictS
*/
ZSTDLIB_API ZSTD_DDict* ZSTD_initStaticDDict(void* workspace, size_t workspaceSize,
const void* dict, size_t dictSize,
- unsigned byReference);
+ ZSTD_dictLoadMethod_e dictLoadMethod);
/*! ZSTD_getDictID_fromDict() :
* Provides the dictID stored within dictionary.
@@ -724,9 +732,9 @@ ZSTDLIB_API unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize);
ZSTDLIB_API ZSTD_CStream* ZSTD_createCStream_advanced(ZSTD_customMem customMem);
ZSTDLIB_API ZSTD_CStream* ZSTD_initStaticCStream(void* workspace, size_t workspaceSize); /**< same as ZSTD_initStaticCCtx() */
ZSTDLIB_API size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pledgedSrcSize); /**< pledgedSrcSize must be correct, a size of 0 means unknown. for a frame size of 0 use initCStream_advanced */
-ZSTDLIB_API size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel); /**< creates of an internal CDict (incompatible with static CCtx), except if dict == NULL or dictSize < 8, in which case no dict is used. */
+ZSTDLIB_API size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel); /**< creates of an internal CDict (incompatible with static CCtx), except if dict == NULL or dictSize < 8, in which case no dict is used. Note: dict is loaded with ZSTD_dm_auto (treated as a full zstd dictionary if it begins with ZSTD_MAGIC_DICTIONARY, else as raw content) and ZSTD_dlm_byCopy.*/
ZSTDLIB_API size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs, const void* dict, size_t dictSize,
- ZSTD_parameters params, unsigned long long pledgedSrcSize); /**< pledgedSrcSize is optional and can be 0 (meaning unknown). note: if the contentSizeFlag is set, pledgedSrcSize == 0 means the source size is actually 0 */
+ ZSTD_parameters params, unsigned long long pledgedSrcSize); /**< pledgedSrcSize is optional and can be 0 (meaning unknown). note: if the contentSizeFlag is set, pledgedSrcSize == 0 means the source size is actually 0. dict is loaded with ZSTD_dm_auto and ZSTD_dlm_byCopy. */
ZSTDLIB_API size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict); /**< note : cdict will just be referenced, and must outlive compression session */
ZSTDLIB_API size_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs, const ZSTD_CDict* cdict, ZSTD_frameParameters fParams, unsigned long long pledgedSrcSize); /**< same as ZSTD_initCStream_usingCDict(), with control over frame parameters */
@@ -741,12 +749,12 @@ ZSTDLIB_API size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledg
/*===== Advanced Streaming decompression functions =====*/
-typedef enum { DStream_p_maxWindowSize } ZSTD_DStreamParameter_e;
ZSTDLIB_API ZSTD_DStream* ZSTD_createDStream_advanced(ZSTD_customMem customMem);
ZSTDLIB_API ZSTD_DStream* ZSTD_initStaticDStream(void* workspace, size_t workspaceSize); /**< same as ZSTD_initStaticDCtx() */
-ZSTDLIB_API size_t ZSTD_setDStreamParameter(ZSTD_DStream* zds, ZSTD_DStreamParameter_e paramType, unsigned paramValue);
-ZSTDLIB_API size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize); /**< note: a dict will not be used if dict == NULL or dictSize < 8 */
-ZSTDLIB_API size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* zds, const ZSTD_DDict* ddict); /**< note : ddict will just be referenced, and must outlive decompression session */
+typedef enum { DStream_p_maxWindowSize } ZSTD_DStreamParameter_e;
+ZSTDLIB_API size_t ZSTD_setDStreamParameter(ZSTD_DStream* zds, ZSTD_DStreamParameter_e paramType, unsigned paramValue); /* obsolete : this API will be removed in a future version */
+ZSTDLIB_API size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize); /**< note: no dictionary will be used if dict == NULL or dictSize < 8 */
+ZSTDLIB_API size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* zds, const ZSTD_DDict* ddict); /**< note : ddict is referenced, it must outlive decompression session */
ZSTDLIB_API size_t ZSTD_resetDStream(ZSTD_DStream* zds); /**< re-use decompression parameters from previous init; saves dictionary loading */
@@ -754,8 +762,8 @@ ZSTDLIB_API size_t ZSTD_resetDStream(ZSTD_DStream* zds); /**< re-use decompress
* Buffer-less and synchronous inner streaming functions
*
* This is an advanced API, giving full control over buffer management, for users which need direct control over memory.
-* But it's also a complex one, with many restrictions (documented below).
-* Prefer using normal streaming API for an easier experience
+* But it's also a complex one, with several restrictions, documented below.
+* Prefer normal streaming API for an easier experience.
********************************************************************* */
/**
@@ -772,8 +780,8 @@ ZSTDLIB_API size_t ZSTD_resetDStream(ZSTD_DStream* zds); /**< re-use decompress
Then, consume your input using ZSTD_compressContinue().
There are some important considerations to keep in mind when using this advanced function :
- - ZSTD_compressContinue() has no internal buffer. It uses externally provided buffer only.
- - Interface is synchronous : input is consumed entirely and produce 1+ (or more) compressed blocks.
+ - ZSTD_compressContinue() has no internal buffer. It uses externally provided buffers only.
+ - Interface is synchronous : input is consumed entirely and produces 1+ compressed blocks.
- Caller must ensure there is enough space in `dst` to store compressed data under worst case scenario.
Worst case evaluation is provided by ZSTD_compressBound().
ZSTD_compressContinue() doesn't guarantee recover after a failed compression.
@@ -784,9 +792,9 @@ ZSTDLIB_API size_t ZSTD_resetDStream(ZSTD_DStream* zds); /**< re-use decompress
Finish a frame with ZSTD_compressEnd(), which will write the last block(s) and optional checksum.
It's possible to use srcSize==0, in which case, it will write a final empty block to end the frame.
- Without last block mark, frames will be considered unfinished (corrupted) by decoders.
+ Without last block mark, frames are considered unfinished (hence corrupted) by compliant decoders.
- `ZSTD_CCtx` object can be re-used (ZSTD_compressBegin()) to compress some new frame.
+ `ZSTD_CCtx` object can be re-used (ZSTD_compressBegin()) to compress again.
*/
/*===== Buffer-less streaming compression functions =====*/
@@ -809,40 +817,53 @@ ZSTDLIB_API size_t ZSTD_compressEnd(ZSTD_CCtx* cctx, void* dst, size_t dstCapaci
A ZSTD_DCtx object can be re-used multiple times.
First typical operation is to retrieve frame parameters, using ZSTD_getFrameHeader().
- It fills a ZSTD_frameHeader structure with important information to correctly decode the frame,
- such as minimum rolling buffer size to allocate to decompress data (`windowSize`),
- and the dictionary ID in use.
- (Note : content size is optional, it may not be present. 0 means : content size unknown).
- Note that these values could be wrong, either because of data malformation, or because an attacker is spoofing deliberate false information.
- As a consequence, check that values remain within valid application range, especially `windowSize`, before allocation.
- Each application can set its own limit, depending on local restrictions.
- For extended interoperability, it is recommended to support windowSize of at least 8 MB.
Frame header is extracted from the beginning of compressed frame, so providing only the frame's beginning is enough.
Data fragment must be large enough to ensure successful decoding.
- `ZSTD_frameHeaderSize_max` bytes is guaranteed to always be large enough.
+ `ZSTD_frameHeaderSize_max` bytes is guaranteed to always be large enough.
@result : 0 : successful decoding, the `ZSTD_frameHeader` structure is correctly filled.
>0 : `srcSize` is too small, please provide at least @result bytes on next attempt.
errorCode, which can be tested using ZSTD_isError().
- Start decompression, with ZSTD_decompressBegin().
+ It fills a ZSTD_frameHeader structure with important information to correctly decode the frame,
+ such as the dictionary ID, content size, or maximum back-reference distance (`windowSize`).
+ Note that these values could be wrong, either because of data corruption, or because a 3rd party deliberately spoofs false information.
+ As a consequence, check that values remain within valid application range.
+ For example, do not allocate memory blindly, check that `windowSize` is within expectation.
+ Each application can set its own limits, depending on local restrictions.
+ For extended interoperability, it is recommended to support `windowSize` of at least 8 MB.
+
+ ZSTD_decompressContinue() needs previous data blocks during decompression, up to `windowSize` bytes.
+ ZSTD_decompressContinue() is very sensitive to contiguity,
+ if 2 blocks don't follow each other, make sure that either the compressor breaks contiguity at the same place,
+ or that previous contiguous segment is large enough to properly handle maximum back-reference distance.
+ There are multiple ways to guarantee this condition.
+
+ The most memory efficient way is to use a round buffer of sufficient size.
+ Sufficient size is determined by invoking ZSTD_decodingBufferSize_min(),
+ which can @return an error code if required value is too large for current system (in 32-bits mode).
+ In a round buffer methodology, ZSTD_decompressContinue() decompresses each block next to previous one,
+ up to the moment there is not enough room left in the buffer to guarantee decoding another full block,
+ which maximum size is provided in `ZSTD_frameHeader` structure, field `blockSizeMax`.
+ At which point, decoding can resume from the beginning of the buffer.
+ Note that already decoded data stored in the buffer should be flushed before being overwritten.
+
+ There are alternatives possible, for example using two or more buffers of size `windowSize` each, though they consume more memory.
+
+ Finally, if you control the compression process, you can also ignore all buffer size rules,
+ as long as the encoder and decoder progress in "lock-step",
+ aka use exactly the same buffer sizes, break contiguity at the same place, etc.
+
+ Once buffers are setup, start decompression, with ZSTD_decompressBegin().
If decompression requires a dictionary, use ZSTD_decompressBegin_usingDict() or ZSTD_decompressBegin_usingDDict().
- Alternatively, you can copy a prepared context, using ZSTD_copyDCtx().
Then use ZSTD_nextSrcSizeToDecompress() and ZSTD_decompressContinue() alternatively.
ZSTD_nextSrcSizeToDecompress() tells how many bytes to provide as 'srcSize' to ZSTD_decompressContinue().
ZSTD_decompressContinue() requires this _exact_ amount of bytes, or it will fail.
- @result of ZSTD_decompressContinue() is the number of bytes regenerated within 'dst' (necessarily <= dstCapacity).
- It can be zero, which is not an error; it just means ZSTD_decompressContinue() has decoded some metadata item.
+ @result of ZSTD_decompressContinue() is the number of bytes regenerated within 'dst' (necessarily <= dstCapacity).
+ It can be zero : it just means ZSTD_decompressContinue() has decoded some metadata item.
It can also be an error code, which can be tested with ZSTD_isError().
- ZSTD_decompressContinue() needs previous data blocks during decompression, up to `windowSize`.
- They should preferably be located contiguously, prior to current block.
- Alternatively, a round buffer of sufficient size is also possible. Sufficient size is determined by frame parameters.
- ZSTD_decompressContinue() is very sensitive to contiguity,
- if 2 blocks don't follow each other, make sure that either the compressor breaks contiguity at the same place,
- or that previous contiguous segment is large enough to properly handle maximum back-reference.
-
A frame is fully decoded when ZSTD_nextSrcSizeToDecompress() returns zero.
Context can then be reset to start a new decompression.
@@ -852,75 +873,101 @@ ZSTDLIB_API size_t ZSTD_compressEnd(ZSTD_CCtx* cctx, void* dst, size_t dstCapaci
== Special case : skippable frames ==
Skippable frames allow integration of user-defined data into a flow of concatenated frames.
- Skippable frames will be ignored (skipped) by a decompressor. The format of skippable frames is as follows :
+ Skippable frames will be ignored (skipped) by decompressor.
+ The format of skippable frames is as follows :
a) Skippable frame ID - 4 Bytes, Little endian format, any value from 0x184D2A50 to 0x184D2A5F
b) Frame Size - 4 Bytes, Little endian format, unsigned 32-bits
c) Frame Content - any content (User Data) of length equal to Frame Size
- For skippable frames ZSTD_decompressContinue() always returns 0.
- For skippable frames ZSTD_getFrameHeader() returns fparamsPtr->windowLog==0 what means that a frame is skippable.
- Note : If fparamsPtr->frameContentSize==0, it is ambiguous: the frame might actually be a Zstd encoded frame with no content.
- For purposes of decompression, it is valid in both cases to skip the frame using
- ZSTD_findFrameCompressedSize to find its size in bytes.
- It also returns Frame Size as fparamsPtr->frameContentSize.
+ For skippable frames ZSTD_getFrameHeader() returns zfhPtr->frameType==ZSTD_skippableFrame.
+ For skippable frames ZSTD_decompressContinue() always returns 0 : it only skips the content.
*/
/*===== Buffer-less streaming decompression functions =====*/
typedef enum { ZSTD_frame, ZSTD_skippableFrame } ZSTD_frameType_e;
typedef struct {
- unsigned long long frameContentSize; /* ZSTD_CONTENTSIZE_UNKNOWN means this field is not available. 0 means "empty" */
+ unsigned long long frameContentSize; /* if == ZSTD_CONTENTSIZE_UNKNOWN, it means this field is not available. 0 means "empty" */
unsigned long long windowSize; /* can be very large, up to <= frameContentSize */
+ unsigned blockSizeMax;
ZSTD_frameType_e frameType; /* if == ZSTD_skippableFrame, frameContentSize is the size of skippable content */
unsigned headerSize;
unsigned dictID;
unsigned checksumFlag;
} ZSTD_frameHeader;
ZSTDLIB_API size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize); /**< doesn't consume input */
+ZSTDLIB_API size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long long frameContentSize); /**< when frame content size is not known, pass in frameContentSize == ZSTD_CONTENTSIZE_UNKNOWN */
+
ZSTDLIB_API size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx);
ZSTDLIB_API size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t dictSize);
ZSTDLIB_API size_t ZSTD_decompressBegin_usingDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict);
-ZSTDLIB_API void ZSTD_copyDCtx(ZSTD_DCtx* dctx, const ZSTD_DCtx* preparedDCtx);
ZSTDLIB_API size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx);
ZSTDLIB_API size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
+
+/* misc */
+ZSTDLIB_API void ZSTD_copyDCtx(ZSTD_DCtx* dctx, const ZSTD_DCtx* preparedDCtx);
typedef enum { ZSTDnit_frameHeader, ZSTDnit_blockHeader, ZSTDnit_block, ZSTDnit_lastBlock, ZSTDnit_checksum, ZSTDnit_skippableFrame } ZSTD_nextInputType_e;
ZSTDLIB_API ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx);
-/*=== New advanced API (experimental, and compression only) ===*/
+/* ============================================ */
+/** New advanced API (experimental) */
+/* ============================================ */
/* notes on API design :
- * In this proposal, parameters are pushed one by one into an existing CCtx,
+ * In this proposal, parameters are pushed one by one into an existing context,
* and then applied on all subsequent compression jobs.
* When no parameter is ever provided, CCtx is created with compression level ZSTD_CLEVEL_DEFAULT.
*
* This API is intended to replace all others experimental API.
* It can basically do all other use cases, and even new ones.
- * It stands a good chance to become "stable",
- * after a reasonable testing period.
+ * In constrast with _advanced() variants, it stands a reasonable chance to become "stable",
+ * after a good testing period.
*/
/* note on naming convention :
* Initially, the API favored names like ZSTD_setCCtxParameter() .
* In this proposal, convention is changed towards ZSTD_CCtx_setParameter() .
* The main driver is that it identifies more clearly the target object type.
- * It feels clearer in light of potential variants :
+ * It feels clearer when considering multiple targets :
* ZSTD_CDict_setParameter() (rather than ZSTD_setCDictParameter())
- * ZSTD_DCtx_setParameter() (rather than ZSTD_setDCtxParameter() )
- * Left variant feels easier to distinguish.
+ * ZSTD_CCtxParams_setParameter() (rather than ZSTD_setCCtxParamsParameter() )
+ * etc...
*/
/* note on enum design :
- * All enum will be manually set to explicit values before reaching "stable API" status */
+ * All enum will be pinned to explicit values before reaching "stable API" status */
typedef enum {
+ /* Question : should we have a format ZSTD_f_auto ?
+ * For the time being, it would mean exactly the same as ZSTD_f_zstd1.
+ * But, in the future, should several formats be supported,
+ * on the compression side, it would mean "default format".
+ * On the decompression side, it would mean "multi format",
+ * and ZSTD_f_zstd1 could be reserved to mean "accept *only* zstd frames".
+ * Since meaning is a little different, another option could be to define different enums for compression and decompression.
+ * This question could be kept for later, when there are actually multiple formats to support,
+ * but there is also the question of pinning enum values, and pinning value `0` is especially important */
+ ZSTD_f_zstd1 = 0, /* zstd frame format, specified in zstd_compression_format.md (default) */
+ ZSTD_f_zstd1_magicless, /* Variant of zstd frame format, without initial 4-bytes magic number.
+ * Useful to save 4 bytes per generated frame.
+ * Decoder cannot recognise automatically this format, requiring instructions. */
+} ZSTD_format_e;
+
+typedef enum {
+ /* compression format */
+ ZSTD_p_format = 10, /* See ZSTD_format_e enum definition.
+ * Cast selected format as unsigned for ZSTD_CCtx_setParameter() compatibility. */
+
/* compression parameters */
ZSTD_p_compressionLevel=100, /* Update all compression parameters according to pre-defined cLevel table
* Default level is ZSTD_CLEVEL_DEFAULT==3.
* Special: value 0 means "do not change cLevel". */
ZSTD_p_windowLog, /* Maximum allowed back-reference distance, expressed as power of 2.
* Must be clamped between ZSTD_WINDOWLOG_MIN and ZSTD_WINDOWLOG_MAX.
- * Special: value 0 means "do not change windowLog". */
+ * Special: value 0 means "do not change windowLog".
+ * Note: Using a window size greater than ZSTD_MAXWINDOWSIZE_DEFAULT (default: 2^27)
+ * requires setting the maximum window size at least as large during decompression. */
ZSTD_p_hashLog, /* Size of the probe table, as a power of 2.
* Resulting table size is (1 << (hashLog+2)).
* Must be clamped between ZSTD_HASHLOG_MIN and ZSTD_HASHLOG_MAX.
@@ -959,12 +1006,6 @@ typedef enum {
ZSTD_p_checksumFlag, /* A 32-bits checksum of content is written at end of frame (default:0) */
ZSTD_p_dictIDFlag, /* When applicable, dictID of dictionary is provided in frame header (default:1) */
- /* dictionary parameters (must be set before ZSTD_CCtx_loadDictionary) */
- ZSTD_p_dictMode=300, /* Select how dictionary content must be interpreted. Value must be from type ZSTD_dictMode_e.
- * default : 0==auto : dictionary will be "full" if it respects specification, otherwise it will be "rawContent" */
- ZSTD_p_refDictContent, /* Dictionary content will be referenced, instead of copied (default:0==byCopy).
- * It requires that dictionary buffer outlives its users */
-
/* multi-threading parameters */
ZSTD_p_nbThreads=400, /* Select how many threads a compression job can spawn (default:1)
* More threads improve speed, but also increase memory usage.
@@ -980,6 +1021,35 @@ typedef enum {
/* advanced parameters - may not remain available after API update */
ZSTD_p_forceMaxWindow=1100, /* Force back-reference distances to remain < windowSize,
* even when referencing into Dictionary content (default:0) */
+ ZSTD_p_enableLongDistanceMatching=1200, /* Enable long distance matching.
+ * This parameter is designed to improve the compression
+ * ratio for large inputs with long distance matches.
+ * This increases the memory usage as well as window size.
+ * Note: setting this parameter sets all the LDM parameters
+ * as well as ZSTD_p_windowLog. It should be set after
+ * ZSTD_p_compressionLevel and before ZSTD_p_windowLog and
+ * other LDM parameters. Setting the compression level
+ * after this parameter overrides the window log, though LDM
+ * will remain enabled until explicitly disabled. */
+ ZSTD_p_ldmHashLog, /* Size of the table for long distance matching, as a power of 2.
+ * Larger values increase memory usage and compression ratio, but decrease
+ * compression speed.
+ * Must be clamped between ZSTD_HASHLOG_MIN and ZSTD_HASHLOG_MAX
+ * (default: windowlog - 7). */
+ ZSTD_p_ldmMinMatch, /* Minimum size of searched matches for long distance matcher.
+ * Larger/too small values usually decrease compression ratio.
+ * Must be clamped between ZSTD_LDM_MINMATCH_MIN
+ * and ZSTD_LDM_MINMATCH_MAX (default: 64). */
+ ZSTD_p_ldmBucketSizeLog, /* Log size of each bucket in the LDM hash table for collision resolution.
+ * Larger values usually improve collision resolution but may decrease
+ * compression speed.
+ * The maximum value is ZSTD_LDM_BUCKETSIZELOG_MAX (default: 3). */
+ ZSTD_p_ldmHashEveryLog, /* Frequency of inserting/looking up entries in the LDM hash table.
+ * The default is MAX(0, (windowLog - ldmHashLog)) to
+ * optimize hash table usage.
+ * Larger values improve compression speed. Deviating far from the
+ * default value will likely result in a decrease in compression ratio.
+ * Must be clamped between 0 and ZSTD_WINDOWLOG_MAX - ZSTD_HASHLOG_MIN. */
} ZSTD_cParameter;
@@ -1007,14 +1077,22 @@ ZSTDLIB_API size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long lo
* @result : 0, or an error code (which can be tested with ZSTD_isError()).
* Special : Adding a NULL (or 0-size) dictionary invalidates any previous dictionary,
* meaning "return to no-dictionary mode".
- * Note 1 : `dict` content will be copied internally,
- * except if ZSTD_p_refDictContent is set before loading.
+ * Note 1 : `dict` content will be copied internally. Use
+ * ZSTD_CCtx_loadDictionary_byReference() to reference dictionary
+ * content instead. The dictionary buffer must then outlive its
+ * users.
* Note 2 : Loading a dictionary involves building tables, which are dependent on compression parameters.
* For this reason, compression parameters cannot be changed anymore after loading a dictionary.
* It's also a CPU-heavy operation, with non-negligible impact on latency.
* Note 3 : Dictionary will be used for all future compression jobs.
- * To return to "no-dictionary" situation, load a NULL dictionary */
+ * To return to "no-dictionary" situation, load a NULL dictionary
+ * Note 5 : Use ZSTD_CCtx_loadDictionary_advanced() to select how dictionary
+ * content will be interpreted.
+ */
ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, size_t dictSize);
+ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary_byReference(ZSTD_CCtx* cctx, const void* dict, size_t dictSize);
+ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary_advanced(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictMode_e dictMode);
+
/*! ZSTD_CCtx_refCDict() :
* Reference a prepared dictionary, to be used for all next compression jobs.
@@ -1040,23 +1118,26 @@ ZSTDLIB_API size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict);
* Note 1 : Prefix buffer is referenced. It must outlive compression job.
* Note 2 : Referencing a prefix involves building tables, which are dependent on compression parameters.
* It's a CPU-heavy operation, with non-negligible impact on latency.
- * Note 3 : it's possible to alter ZSTD_p_dictMode using ZSTD_CCtx_setParameter() */
+ * Note 3 : By default, the prefix is treated as raw content
+ * (ZSTD_dm_rawContent). Use ZSTD_CCtx_refPrefix_advanced() to alter
+ * dictMode. */
ZSTDLIB_API size_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize);
+ZSTDLIB_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize, ZSTD_dictMode_e dictMode);
typedef enum {
ZSTD_e_continue=0, /* collect more data, encoder transparently decides when to output result, for optimal conditions */
ZSTD_e_flush, /* flush any data provided so far - frame will continue, future data can still reference previous data for better compression */
- ZSTD_e_end /* flush any remaining data and ends current frame. Any future compression starts a new frame. */
+ ZSTD_e_end /* flush any remaining data and close current frame. Any additional data starts a new frame. */
} ZSTD_EndDirective;
/*! ZSTD_compress_generic() :
* Behave about the same as ZSTD_compressStream. To note :
* - Compression parameters are pushed into CCtx before starting compression, using ZSTD_CCtx_setParameter()
* - Compression parameters cannot be changed once compression is started.
- * - *dstPos must be <= dstCapacity, *srcPos must be <= srcSize
- * - *dspPos and *srcPos will be updated. They are guaranteed to remain below their respective limit.
+ * - outpot->pos must be <= dstCapacity, input->pos must be <= srcSize
+ * - outpot->pos and input->pos will be updated. They are guaranteed to remain below their respective limit.
* - @return provides the minimum amount of data still to flush from internal buffers
* or an error code, which can be tested using ZSTD_isError().
* if @return != 0, flush is not fully completed, there is some data left within internal buffers.
@@ -1075,6 +1156,7 @@ ZSTDLIB_API size_t ZSTD_compress_generic (ZSTD_CCtx* cctx,
* Useful after an error, or to interrupt an ongoing compression job and start a new one.
* Any internal data not yet flushed is cancelled.
* Dictionary (if any) is dropped.
+ * All parameters are back to default values.
* It's possible to modify compression parameters after a reset.
*/
ZSTDLIB_API void ZSTD_CCtx_reset(ZSTD_CCtx* cctx); /* Not ready yet ! */
@@ -1083,21 +1165,187 @@ ZSTDLIB_API void ZSTD_CCtx_reset(ZSTD_CCtx* cctx); /* Not ready yet ! */
/*! ZSTD_compress_generic_simpleArgs() :
* Same as ZSTD_compress_generic(),
* but using only integral types as arguments.
- * Argument list is larger and less expressive than ZSTD_{in,out}Buffer,
+ * Argument list is larger than ZSTD_{in,out}Buffer,
* but can be helpful for binders from dynamic languages
* which have troubles handling structures containing memory pointers.
*/
-size_t ZSTD_compress_generic_simpleArgs (
+ZSTDLIB_API size_t ZSTD_compress_generic_simpleArgs (
ZSTD_CCtx* cctx,
void* dst, size_t dstCapacity, size_t* dstPos,
const void* src, size_t srcSize, size_t* srcPos,
ZSTD_EndDirective endOp);
+/*! ZSTD_CCtx_params :
+ * Quick howto :
+ * - ZSTD_createCCtxParams() : Create a ZSTD_CCtx_params structure
+ * - ZSTD_CCtxParam_setParameter() : Push parameters one by one into
+ * an existing ZSTD_CCtx_params structure.
+ * This is similar to
+ * ZSTD_CCtx_setParameter().
+ * - ZSTD_CCtx_setParametersUsingCCtxParams() : Apply parameters to
+ * an existing CCtx.
+ * These parameters will be applied to
+ * all subsequent compression jobs.
+ * - ZSTD_compress_generic() : Do compression using the CCtx.
+ * - ZSTD_freeCCtxParams() : Free the memory.
+ *
+ * This can be used with ZSTD_estimateCCtxSize_advanced_usingCCtxParams()
+ * for static allocation for single-threaded compression.
+ */
+ZSTDLIB_API ZSTD_CCtx_params* ZSTD_createCCtxParams(void);
-/**
- Block functions
+/*! ZSTD_resetCCtxParams() :
+ * Reset params to default, with the default compression level.
+ */
+ZSTDLIB_API size_t ZSTD_resetCCtxParams(ZSTD_CCtx_params* params);
+
+/*! ZSTD_initCCtxParams() :
+ * Initializes the compression parameters of cctxParams according to
+ * compression level. All other parameters are reset to their default values.
+ */
+ZSTDLIB_API size_t ZSTD_initCCtxParams(ZSTD_CCtx_params* cctxParams, int compressionLevel);
+
+/*! ZSTD_initCCtxParams_advanced() :
+ * Initializes the compression and frame parameters of cctxParams according to
+ * params. All other parameters are reset to their default values.
+ */
+ZSTDLIB_API size_t ZSTD_initCCtxParams_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params);
+
+ZSTDLIB_API size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params);
+
+/*! ZSTD_CCtxParam_setParameter() :
+ * Similar to ZSTD_CCtx_setParameter.
+ * Set one compression parameter, selected by enum ZSTD_cParameter.
+ * Parameters must be applied to a ZSTD_CCtx using ZSTD_CCtx_setParametersUsingCCtxParams().
+ * Note : when `value` is an enum, cast it to unsigned for proper type checking.
+ * @result : 0, or an error code (which can be tested with ZSTD_isError()).
+ */
+ZSTDLIB_API size_t ZSTD_CCtxParam_setParameter(ZSTD_CCtx_params* params, ZSTD_cParameter param, unsigned value);
+
+/*! ZSTD_CCtx_setParametersUsingCCtxParams() :
+ * Apply a set of ZSTD_CCtx_params to the compression context.
+ * This must be done before the dictionary is loaded.
+ * The pledgedSrcSize is treated as unknown.
+ * Multithreading parameters are applied only if nbThreads > 1.
+ */
+ZSTDLIB_API size_t ZSTD_CCtx_setParametersUsingCCtxParams(
+ ZSTD_CCtx* cctx, const ZSTD_CCtx_params* params);
+
+
+/*=== Advanced parameters for decompression API ===*/
+
+/* The following parameters must be set after creating a ZSTD_DCtx* (or ZSTD_DStream*) object,
+ * but before starting decompression of a frame.
+ */
+
+/*! ZSTD_DCtx_loadDictionary() :
+ * Create an internal DDict from dict buffer,
+ * to be used to decompress next frames.
+ * @result : 0, or an error code (which can be tested with ZSTD_isError()).
+ * Special : Adding a NULL (or 0-size) dictionary invalidates any previous dictionary,
+ * meaning "return to no-dictionary mode".
+ * Note 1 : `dict` content will be copied internally.
+ * Use ZSTD_DCtx_loadDictionary_byReference()
+ * to reference dictionary content instead.
+ * In which case, the dictionary buffer must outlive its users.
+ * Note 2 : Loading a dictionary involves building tables,
+ * which has a non-negligible impact on CPU usage and latency.
+ * Note 3 : Use ZSTD_DCtx_loadDictionary_advanced() to select
+ * how dictionary content will be interpreted and loaded.
+ */
+ZSTDLIB_API size_t ZSTD_DCtx_loadDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize); /* not implemented */
+ZSTDLIB_API size_t ZSTD_DCtx_loadDictionary_byReference(ZSTD_DCtx* dctx, const void* dict, size_t dictSize); /* not implemented */
+ZSTDLIB_API size_t ZSTD_DCtx_loadDictionary_advanced(ZSTD_DCtx* dctx, const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictMode_e dictMode); /* not implemented */
+
+
+/*! ZSTD_DCtx_refDDict() :
+ * Reference a prepared dictionary, to be used to decompress next frames.
+ * The dictionary remains active for decompression of future frames using same DCtx.
+ * @result : 0, or an error code (which can be tested with ZSTD_isError()).
+ * Note 1 : Currently, only one dictionary can be managed.
+ * Referencing a new dictionary effectively "discards" any previous one.
+ * Special : adding a NULL DDict means "return to no-dictionary mode".
+ * Note 2 : DDict is just referenced, its lifetime must outlive its usage from DCtx.
+ */
+ZSTDLIB_API size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict); /* not implemented */
+
+
+/*! ZSTD_DCtx_refPrefix() :
+ * Reference a prefix (single-usage dictionary) for next compression job.
+ * Prefix is **only used once**. It must be explicitly referenced before each frame.
+ * If there is a need to use same prefix multiple times, consider embedding it into a ZSTD_DDict instead.
+ * @result : 0, or an error code (which can be tested with ZSTD_isError()).
+ * Note 1 : Adding any prefix (including NULL) invalidates any previously set prefix or dictionary
+ * Note 2 : Prefix buffer is referenced. It must outlive compression job.
+ * Note 3 : By default, the prefix is treated as raw content (ZSTD_dm_rawContent).
+ * Use ZSTD_CCtx_refPrefix_advanced() to alter dictMode.
+ * Note 4 : Referencing a raw content prefix has almost no cpu nor memory cost.
+ */
+ZSTDLIB_API size_t ZSTD_DCtx_refPrefix(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize); /* not implemented */
+ZSTDLIB_API size_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize, ZSTD_dictMode_e dictMode); /* not implemented */
+
+
+/*! ZSTD_DCtx_setMaxWindowSize() :
+ * Refuses allocating internal buffers for frames requiring a window size larger than provided limit.
+ * This is useful to prevent a decoder context from reserving too much memory for itself (potential attack scenario).
+ * This parameter is only useful in streaming mode, since no internal buffer is allocated in direct mode.
+ * By default, a decompression context accepts all window sizes <= (1 << ZSTD_WINDOWLOG_MAX)
+ * @return : 0, or an error code (which can be tested using ZSTD_isError()).
+ */
+ZSTDLIB_API size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize);
+
+
+/*! ZSTD_DCtx_setFormat() :
+ * Instruct the decoder context about what kind of data to decode next.
+ * This instruction is mandatory to decode data without a fully-formed header,
+ * such ZSTD_f_zstd1_magicless for example.
+ * @return : 0, or an error code (which can be tested using ZSTD_isError()).
+ */
+ZSTDLIB_API size_t ZSTD_DCtx_setFormat(ZSTD_DCtx* dctx, ZSTD_format_e format);
+
+
+/*! ZSTD_decompress_generic() :
+ * Behave the same as ZSTD_decompressStream.
+ * Decompression parameters cannot be changed once decompression is started.
+ * @return : an error code, which can be tested using ZSTD_isError()
+ * if >0, a hint, nb of expected input bytes for next invocation.
+ * `0` means : a frame has just been fully decoded and flushed.
+ */
+ZSTDLIB_API size_t ZSTD_decompress_generic(ZSTD_DCtx* dctx,
+ ZSTD_outBuffer* output,
+ ZSTD_inBuffer* input);
+
+
+/*! ZSTD_decompress_generic_simpleArgs() :
+ * Same as ZSTD_decompress_generic(),
+ * but using only integral types as arguments.
+ * Argument list is larger than ZSTD_{in,out}Buffer,
+ * but can be helpful for binders from dynamic languages
+ * which have troubles handling structures containing memory pointers.
+ */
+ZSTDLIB_API size_t ZSTD_decompress_generic_simpleArgs (
+ ZSTD_DCtx* dctx,
+ void* dst, size_t dstCapacity, size_t* dstPos,
+ const void* src, size_t srcSize, size_t* srcPos);
+
+
+/*! ZSTD_DCtx_reset() :
+ * Return a DCtx to clean state.
+ * If a decompression was ongoing, any internal data not yet flushed is cancelled.
+ * All parameters are back to default values, including sticky ones.
+ * Dictionary (if any) is dropped.
+ * Parameters can be modified again after a reset.
+ */
+ZSTDLIB_API void ZSTD_DCtx_reset(ZSTD_DCtx* dctx);
+
+
+
+/* ============================ */
+/** Block level API */
+/* ============================ */
+/*!
Block functions produce and decode raw zstd blocks, without frame metadata.
Frame metadata cost is typically ~18 bytes, which can be non-negligible for very small blocks (< 100 bytes).
User will have to take in charge required information to regenerate data, such as compressed and content sizes.
@@ -1109,7 +1357,7 @@ size_t ZSTD_compress_generic_simpleArgs (
+ compression : any ZSTD_compressBegin*() variant, including with dictionary
+ decompression : any ZSTD_decompressBegin*() variant, including with dictionary
+ copyCCtx() and copyDCtx() can be used too
- - Block size is limited, it must be <= ZSTD_getBlockSize() <= ZSTD_BLOCKSIZE_MAX
+ - Block size is limited, it must be <= ZSTD_getBlockSize() <= ZSTD_BLOCKSIZE_MAX == 128 KB
+ If input is larger than a block size, it's necessary to split input data into multiple blocks
+ For inputs larger than a single block size, consider using the regular ZSTD_compress() instead.
Frame metadata is not that costly, and quickly becomes negligible as source size grows larger.
@@ -1128,7 +1376,7 @@ size_t ZSTD_compress_generic_simpleArgs (
ZSTDLIB_API size_t ZSTD_getBlockSize (const ZSTD_CCtx* cctx);
ZSTDLIB_API size_t ZSTD_compressBlock (ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
ZSTDLIB_API size_t ZSTD_decompressBlock(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
-ZSTDLIB_API size_t ZSTD_insertBlock(ZSTD_DCtx* dctx, const void* blockStart, size_t blockSize); /**< insert block into `dctx` history. Useful for uncompressed blocks */
+ZSTDLIB_API size_t ZSTD_insertBlock(ZSTD_DCtx* dctx, const void* blockStart, size_t blockSize); /**< insert uncompressed block into `dctx` history. Useful for multi-blocks decompression */
#endif /* ZSTD_H_ZSTD_STATIC_LINKING_ONLY */
diff --git a/version.py b/version.py
index f0da206837..cce155c9af 100644
--- a/version.py
+++ b/version.py
@@ -2,4 +2,5 @@ short_name = "godot"
name = "Godot Engine"
major = 3
minor = 0
-status = "alpha"
+status = "beta"
+module_config = ""